From 808d2288725586de17c4f6c39b578fd32a256fe3 Mon Sep 17 00:00:00 2001 From: Sebastian Sumpf Date: Fri, 11 Jan 2013 17:00:47 +0100 Subject: [PATCH] FOC/L4RE: Upstream revision 40 --- kernel/fiasco/BENCHMARKING | 13 + kernel/fiasco/COPYING | 339 + kernel/fiasco/MAINTAINER | 1 + kernel/fiasco/Makefile | 213 + kernel/fiasco/README | 71 + kernel/fiasco/src/.gdbinit | 22 + kernel/fiasco/src/BUG-HUNTING | 31 + kernel/fiasco/src/Circular.max.amd64 | 18 + kernel/fiasco/src/Circular.max.arm | 6 + kernel/fiasco/src/Circular.max.ia32 | 18 + kernel/fiasco/src/Circular.max.ppc32 | 1694 ++ kernel/fiasco/src/Circular.max.ux | 6 + kernel/fiasco/src/DEPS.blacklist | 13 + kernel/fiasco/src/Kconfig | 804 + kernel/fiasco/src/Makeconf | 205 + kernel/fiasco/src/Makeconf.amd64 | 27 + kernel/fiasco/src/Makeconf.arm | 17 + kernel/fiasco/src/Makeconf.ia32 | 40 + kernel/fiasco/src/Makeconf.ppc32 | 5 + kernel/fiasco/src/Makeconf.sparc | 2 + kernel/fiasco/src/Makeconf.ux | 34 + kernel/fiasco/src/Makefile | 246 + kernel/fiasco/src/Makefile.sub1 | 118 + kernel/fiasco/src/Makefile.sub2 | 261 + kernel/fiasco/src/Makerules.ABI | 8 + kernel/fiasco/src/Makerules.BOOT | 13 + kernel/fiasco/src/Makerules.CHECKSUM | 40 + kernel/fiasco/src/Makerules.CRT0 | 5 + kernel/fiasco/src/Makerules.CXXLIB | 7 + kernel/fiasco/src/Makerules.DRIVERS | 17 + kernel/fiasco/src/Makerules.GBLCFG | 19 + kernel/fiasco/src/Makerules.JABI | 7 + kernel/fiasco/src/Makerules.JDB | 10 + kernel/fiasco/src/Makerules.LIBDISASM | 7 + kernel/fiasco/src/Makerules.LIBGZIP | 7 + kernel/fiasco/src/Makerules.LIBK | 12 + kernel/fiasco/src/Makerules.LIBKERN | 7 + kernel/fiasco/src/Makerules.LIBPERFCTR | 7 + kernel/fiasco/src/Makerules.LIBREGEX | 7 + kernel/fiasco/src/Makerules.LIBUART | 19 + kernel/fiasco/src/Makerules.LINES | 15 + kernel/fiasco/src/Makerules.MINILIBC | 7 + kernel/fiasco/src/Makerules.SYMBOLS | 3 + kernel/fiasco/src/Makerules.TCBOFFSET | 20 + kernel/fiasco/src/Makerules.TYPES | 8 + kernel/fiasco/src/Makerules.UNITTEST | 116 + kernel/fiasco/src/Makerules.VERSION | 31 + kernel/fiasco/src/Makerules.global | 169 + kernel/fiasco/src/Modules.amd64 | 447 + kernel/fiasco/src/Modules.arm | 334 + kernel/fiasco/src/Modules.generic | 29 + kernel/fiasco/src/Modules.ia32 | 448 + kernel/fiasco/src/Modules.ppc32 | 259 + kernel/fiasco/src/Modules.sparc | 257 + kernel/fiasco/src/Modules.ux | 362 + kernel/fiasco/src/README | 168 + kernel/fiasco/src/README.style | 785 + kernel/fiasco/src/TODO | 74 + .../fiasco/src/abi/amd64/kip-amd64-debug.cpp | 7 + kernel/fiasco/src/abi/amd64/kip-amd64.cpp | 71 + kernel/fiasco/src/abi/arm/kip-arm.cpp | 82 + kernel/fiasco/src/abi/ia32/kip-ia32-debug.cpp | 20 + kernel/fiasco/src/abi/ia32/kip-ia32.cpp | 82 + kernel/fiasco/src/abi/kip-debug.cpp | 94 + kernel/fiasco/src/abi/kip.cpp | 169 + kernel/fiasco/src/abi/l4_buf_desc.cpp | 109 + kernel/fiasco/src/abi/l4_error.cpp | 62 + kernel/fiasco/src/abi/l4_fpage.cpp | 274 + kernel/fiasco/src/abi/l4_msg_item.cpp | 218 + kernel/fiasco/src/abi/l4_types-debug.cpp | 43 + kernel/fiasco/src/abi/l4_types-objs.cpp | 124 + kernel/fiasco/src/abi/l4_types.cpp | 934 ++ kernel/fiasco/src/abi/ppc32/kip-ppc32.cpp | 76 + kernel/fiasco/src/abi/sparc/kip-sparc.cpp | 76 + kernel/fiasco/src/abi/virt-ia32-amd64.cpp | 147 + .../src/boot/amd64/Makerules.BOOT.amd64 | 37 + kernel/fiasco/src/boot/amd64/boot.S | 21 + kernel/fiasco/src/boot/amd64/boot_cpu.cc | 634 + kernel/fiasco/src/boot/amd64/boot_idt.S | 99 + kernel/fiasco/src/boot/amd64/boot_paging.h | 39 + kernel/fiasco/src/boot/amd64/bootstrap.ld | 19 + kernel/fiasco/src/boot/arm/Makerules.BOOT.arm | 23 + kernel/fiasco/src/boot/boot_cpu.h | 10 + kernel/fiasco/src/boot/boot_direct_cons.h | 6 + kernel/fiasco/src/boot/boot_libc_glue.cc | 17 + kernel/fiasco/src/boot/bootstrap.cc | 107 + kernel/fiasco/src/boot/direct_cons_putchar.cc | 44 + .../fiasco/src/boot/ia32/Makerules.BOOT.ia32 | 43 + kernel/fiasco/src/boot/ia32/boot.S | 19 + kernel/fiasco/src/boot/ia32/boot_cpu.cc | 561 + kernel/fiasco/src/boot/ia32/boot_idt.S | 74 + kernel/fiasco/src/boot/ia32/boot_paging.h | 30 + kernel/fiasco/src/boot/ia32/bootstrap.ld | 18 + kernel/fiasco/src/doxygen.conf | 939 ++ kernel/fiasco/src/drivers/amd64/io-amd64.cpp | 53 + .../fiasco/src/drivers/amd64/keycodes-arch.h | 15 + kernel/fiasco/src/drivers/amd64/mem-amd64.cpp | 91 + .../src/drivers/amd64/processor-amd64.cpp | 139 + .../fiasco/src/drivers/amd64/reset-amd64.cpp | 41 + .../fiasco/src/drivers/arm/cache_func_gen.cpp | 57 + kernel/fiasco/src/drivers/arm/h3xxx.cpp | 140 + kernel/fiasco/src/drivers/arm/io-arm.cpp | 43 + kernel/fiasco/src/drivers/arm/keycodes-arch.h | 15 + kernel/fiasco/src/drivers/arm/mem-arm.cpp | 71 + kernel/fiasco/src/drivers/arm/mmu-arm.cpp | 634 + .../fiasco/src/drivers/arm/processor-arm.cpp | 238 + kernel/fiasco/src/drivers/arm/sa1100.cpp | 53 + kernel/fiasco/src/drivers/arm/uart-sa1100.cpp | 316 + kernel/fiasco/src/drivers/console.cpp | 206 + kernel/fiasco/src/drivers/delayloop.cpp | 59 + kernel/fiasco/src/drivers/filter_console.cpp | 269 + kernel/fiasco/src/drivers/glue_libc.cc | 52 + kernel/fiasco/src/drivers/ia32/io-ia32.cpp | 53 + .../fiasco/src/drivers/ia32/keycodes-arch.h | 15 + kernel/fiasco/src/drivers/ia32/mem-ia32.cpp | 84 + .../src/drivers/ia32/processor-ia32.cpp | 92 + kernel/fiasco/src/drivers/ia32/reset-ia32.cpp | 41 + kernel/fiasco/src/drivers/io.cpp | 185 + kernel/fiasco/src/drivers/keyb-pc.cpp | 252 + kernel/fiasco/src/drivers/keyb.cpp | 36 + kernel/fiasco/src/drivers/keycodes.h | 24 + kernel/fiasco/src/drivers/libc_backend.h | 47 + kernel/fiasco/src/drivers/mem.cpp | 37 + kernel/fiasco/src/drivers/mmu.cpp | 186 + kernel/fiasco/src/drivers/mux_console.cpp | 277 + kernel/fiasco/src/drivers/pci.cpp | 89 + kernel/fiasco/src/drivers/ppc32/include/mmu.h | 46 + kernel/fiasco/src/drivers/ppc32/io-ppc32.cpp | 101 + .../src/drivers/ppc32/kernel_uart-ppc32.cpp | 11 + .../fiasco/src/drivers/ppc32/keycodes-arch.h | 15 + kernel/fiasco/src/drivers/ppc32/mem-ppc32.cpp | 25 + kernel/fiasco/src/drivers/ppc32/ppc_types.cpp | 21 + .../src/drivers/ppc32/processor-ppc32.cpp | 118 + .../fiasco/src/drivers/ppc32/reset-ppc32.cpp | 38 + .../fiasco/src/drivers/ppc32/uart-mpc52xx.cpp | 32 + kernel/fiasco/src/drivers/ppc32/uart-of.cpp | 10 + kernel/fiasco/src/drivers/processor.cpp | 47 + kernel/fiasco/src/drivers/sparc/io-sparc.cpp | 84 + .../src/drivers/sparc/kernel_uart-sparc.cpp | 11 + .../fiasco/src/drivers/sparc/keycodes-arch.h | 15 + kernel/fiasco/src/drivers/sparc/mem-sparc.cpp | 25 + .../src/drivers/sparc/processor-sparc.cpp | 141 + .../fiasco/src/drivers/sparc/reset-sparc.cpp | 38 + .../fiasco/src/drivers/sparc/sparc_types.cpp | 2 + .../fiasco/src/drivers/sparc/uart-leon3.cpp | 14 + kernel/fiasco/src/drivers/uart-16550.cpp | 335 + kernel/fiasco/src/drivers/uart.cpp | 180 + kernel/fiasco/src/drivers/ux/keycodes-arch.h | 15 + kernel/fiasco/src/drivers/ux/processor-ux.cpp | 104 + kernel/fiasco/src/drivers/ux/ux_con.c | 536 + kernel/fiasco/src/drivers/ux/ux_net.c | 103 + kernel/fiasco/src/drivers/vga_console.cpp | 488 + kernel/fiasco/src/jabi/jdb_ktrace.cpp | 52 + kernel/fiasco/src/jdb/arm/jdb-arm.cpp | 319 + .../src/jdb/arm/jdb_dump_entry_frame-arm.cpp | 65 + .../src/jdb/arm/jdb_entry_frame-arm.cpp | 121 + kernel/fiasco/src/jdb/arm/jdb_extensions.cpp | 168 + .../fiasco/src/jdb/arm/jdb_kern_info-arm.cpp | 37 + .../src/jdb/arm/jdb_kern_info-bench-arm.cpp | 24 + .../src/jdb/arm/jdb_kern_info-cpu-arm.cpp | 190 + kernel/fiasco/src/jdb/arm/jdb_mem_dump.cpp | 59 + kernel/fiasco/src/jdb/arm/jdb_perf.cpp | 62 + kernel/fiasco/src/jdb/arm/jdb_ptab-arm.cpp | 208 + kernel/fiasco/src/jdb/arm/jdb_reg_dump.cpp | 43 + kernel/fiasco/src/jdb/arm/jdb_tcb-arm.cpp | 77 + .../fiasco/src/jdb/arm/jdb_trace_set-arm.cpp | 65 + kernel/fiasco/src/jdb/arm/jdb_vm.cpp | 67 + kernel/fiasco/src/jdb/ia32/32/jdb_bp-ia32.cpp | 13 + .../ia32/32/jdb_kern_info-bench-ia32-32.cpp | 485 + .../src/jdb/ia32/32/jdb_kern_info-bench.txt | 111 + .../src/jdb/ia32/32/jdb_tcb-ia32-ux.cpp | 217 + .../fiasco/src/jdb/ia32/64/jdb_bp-amd64.cpp | 13 + .../ia32/64/jdb_kern_info-bench-ia32-64.cpp | 232 + .../fiasco/src/jdb/ia32/64/jdb_ptab-amd64.cpp | 105 + .../fiasco/src/jdb/ia32/64/jdb_tcb-amd64.cpp | 329 + kernel/fiasco/src/jdb/ia32/jdb-ia32-amd64.cpp | 1021 ++ kernel/fiasco/src/jdb/ia32/jdb-ia32-ux.cpp | 126 + .../src/jdb/ia32/jdb-int3-ia32-amd64.cpp | 70 + .../fiasco/src/jdb/ia32/jdb-int3-ia32-ux.cpp | 239 + .../fiasco/src/jdb/ia32/jdb_bp-ia32-amd64.cpp | 175 + kernel/fiasco/src/jdb/ia32/jdb_bp-ia32-ux.cpp | 838 + kernel/fiasco/src/jdb/ia32/jdb_bt-ia32-ux.cpp | 440 + .../src/jdb/ia32/jdb_entry_frame-ia32.cpp | 194 + kernel/fiasco/src/jdb/ia32/jdb_io_ports.cpp | 235 + kernel/fiasco/src/jdb/ia32/jdb_iomap.cpp | 156 + .../fiasco/src/jdb/ia32/jdb_kern_info-dr.cpp | 38 + .../src/jdb/ia32/jdb_kern_info-ia32-amd64.cpp | 399 + .../src/jdb/ia32/jdb_kern_info-ia32-ux.cpp | 142 + .../src/jdb/ia32/jdb_kern_info-mtrr.cpp | 83 + .../fiasco/src/jdb/ia32/jdb_kern_info-pci.cpp | 66 + .../src/jdb/ia32/jdb_misc-ia32-amd64.cpp | 402 + .../fiasco/src/jdb/ia32/jdb_screen-ia32.cpp | 32 + .../src/jdb/ia32/jdb_trace_set-ia32-ux.cpp | 153 + kernel/fiasco/src/jdb/jdb-ansi.cpp | 120 + kernel/fiasco/src/jdb/jdb-thread.cpp | 78 + kernel/fiasco/src/jdb/jdb.cpp | 1413 ++ kernel/fiasco/src/jdb/jdb_attach_irq.cpp | 205 + kernel/fiasco/src/jdb/jdb_bp.cpp | 8 + kernel/fiasco/src/jdb/jdb_bts.cpp | 331 + kernel/fiasco/src/jdb/jdb_console_buffer.cpp | 431 + kernel/fiasco/src/jdb/jdb_core.cpp | 962 ++ kernel/fiasco/src/jdb/jdb_counters.cpp | 90 + kernel/fiasco/src/jdb/jdb_dbinfo.cpp | 297 + kernel/fiasco/src/jdb/jdb_disasm.cpp | 358 + kernel/fiasco/src/jdb/jdb_dump.cpp | 425 + kernel/fiasco/src/jdb/jdb_exit_module.cpp | 107 + kernel/fiasco/src/jdb/jdb_factory.cpp | 53 + kernel/fiasco/src/jdb/jdb_gzip.cpp | 110 + kernel/fiasco/src/jdb/jdb_halt_thread.cpp | 66 + kernel/fiasco/src/jdb/jdb_handler_queue.cpp | 46 + kernel/fiasco/src/jdb/jdb_idle_stats.cpp | 55 + kernel/fiasco/src/jdb/jdb_input.cpp | 238 + kernel/fiasco/src/jdb/jdb_io_apic.cpp | 129 + kernel/fiasco/src/jdb/jdb_ipc_gate.cpp | 63 + kernel/fiasco/src/jdb/jdb_ipi.cpp | 58 + kernel/fiasco/src/jdb/jdb_jaf_module.cpp | 84 + kernel/fiasco/src/jdb/jdb_kern_info-apic.cpp | 39 + kernel/fiasco/src/jdb/jdb_kern_info-bench.cpp | 164 + kernel/fiasco/src/jdb/jdb_kern_info.cpp | 136 + .../fiasco/src/jdb/jdb_kern_info_config.cpp | 31 + kernel/fiasco/src/jdb/jdb_kern_info_kip.cpp | 27 + .../src/jdb/jdb_kern_info_kmem_alloc.cpp | 33 + .../fiasco/src/jdb/jdb_kern_info_region.cpp | 26 + kernel/fiasco/src/jdb/jdb_kobject.cpp | 614 + kernel/fiasco/src/jdb/jdb_kobject_names.cpp | 212 + kernel/fiasco/src/jdb/jdb_lines.cpp | 323 + kernel/fiasco/src/jdb/jdb_list.cpp | 417 + kernel/fiasco/src/jdb/jdb_log.cpp | 373 + kernel/fiasco/src/jdb/jdb_mapdb.cpp | 544 + kernel/fiasco/src/jdb/jdb_module.cpp | 427 + kernel/fiasco/src/jdb/jdb_mp_request_sl.cpp | 147 + kernel/fiasco/src/jdb/jdb_obj_space.cpp | 262 + kernel/fiasco/src/jdb/jdb_pic.cpp | 89 + kernel/fiasco/src/jdb/jdb_prompt_ext.cpp | 51 + kernel/fiasco/src/jdb/jdb_prompt_module.cpp | 258 + .../fiasco/src/jdb/jdb_ptab-ia32-ux-arm.cpp | 127 + kernel/fiasco/src/jdb/jdb_ptab.cpp | 274 + kernel/fiasco/src/jdb/jdb_rcupdate.cpp | 94 + kernel/fiasco/src/jdb/jdb_regex.cpp | 102 + kernel/fiasco/src/jdb/jdb_scheduler.cpp | 56 + kernel/fiasco/src/jdb/jdb_screen.cpp | 78 + kernel/fiasco/src/jdb/jdb_sender_list.cpp | 126 + kernel/fiasco/src/jdb/jdb_space.cpp | 138 + kernel/fiasco/src/jdb/jdb_symbol.cpp | 484 + kernel/fiasco/src/jdb/jdb_table.cpp | 384 + kernel/fiasco/src/jdb/jdb_tbuf.cpp | 621 + kernel/fiasco/src/jdb/jdb_tbuf_init.cpp | 91 + kernel/fiasco/src/jdb/jdb_tbuf_output.cpp | 273 + kernel/fiasco/src/jdb/jdb_tbuf_show.cpp | 1049 ++ kernel/fiasco/src/jdb/jdb_tcb.cpp | 990 ++ kernel/fiasco/src/jdb/jdb_tetris.cpp | 331 + kernel/fiasco/src/jdb/jdb_thread.cpp | 120 + kernel/fiasco/src/jdb/jdb_thread_list.cpp | 872 + kernel/fiasco/src/jdb/jdb_timeout.cpp | 447 + kernel/fiasco/src/jdb/jdb_trace.cpp | 294 + kernel/fiasco/src/jdb/jdb_trace_set.cpp | 374 + kernel/fiasco/src/jdb/jdb_trap_state.cpp | 88 + kernel/fiasco/src/jdb/jdb_utcb.cpp | 133 + kernel/fiasco/src/jdb/jdb_util.cpp | 48 + kernel/fiasco/src/jdb/ppc32/jdb-ppc32.cpp | 245 + .../src/jdb/ppc32/jdb_entry_frame-ppc32.cpp | 120 + kernel/fiasco/src/jdb/ppc32/jdb_tcb-ppc32.cpp | 111 + kernel/fiasco/src/jdb/sparc/jdb-sparc.cpp | 243 + .../src/jdb/sparc/jdb_entry_frame-sparc.cpp | 120 + kernel/fiasco/src/jdb/sparc/jdb_tcb-sparc.cpp | 111 + kernel/fiasco/src/jdb/ux/jdb-int3.cpp | 14 + kernel/fiasco/src/jdb/ux/jdb-ux.cpp | 456 + kernel/fiasco/src/jdb/ux/jdb_bp-ux.cpp | 185 + kernel/fiasco/src/jdb/ux/jdb_kern_info-ux.cpp | 140 + kernel/fiasco/src/kern/acpi.cpp | 358 + .../src/kern/amd64/Makerules.SYMBOLS.amd64 | 11 + kernel/fiasco/src/kern/app_cpu_thread.cpp | 78 + kernel/fiasco/src/kern/arm/Makerules.KERNEL | 27 + kernel/fiasco/src/kern/arm/__main.cpp | 23 + kernel/fiasco/src/kern/arm/boot_info-arch.cpp | 47 + kernel/fiasco/src/kern/arm/boot_uart_init.cpp | 10 + kernel/fiasco/src/kern/arm/bootstrap.cpp | 183 + kernel/fiasco/src/kern/arm/bsp/imx/Kconfig | 34 + kernel/fiasco/src/kern/arm/bsp/imx/Modules | 27 + .../kern/arm/bsp/imx/bootstrap-arm-imx.cpp | 34 + .../src/kern/arm/bsp/imx/config-arm-imx.cpp | 11 + .../kern/arm/bsp/imx/kernel_uart-arm-imx.cpp | 12 + .../kern/arm/bsp/imx/mem_layout-arm-imx.cpp | 92 + .../src/kern/arm/bsp/imx/pic-arm-imx.cpp | 138 + .../src/kern/arm/bsp/imx/pic-arm-imx51.cpp | 31 + .../src/kern/arm/bsp/imx/reset-arm-imx.cpp | 46 + .../src/kern/arm/bsp/imx/timer-arm-imx21.cpp | 85 + .../kern/arm/bsp/imx/timer-arm-imx_epit.cpp | 112 + .../fiasco/src/kern/arm/bsp/imx/uart-imx.cpp | 44 + .../src/kern/arm/bsp/integrator/Kconfig | 4 + .../src/kern/arm/bsp/integrator/Modules | 18 + .../integrator/bootstrap-arm-integrator.cpp | 21 + .../bsp/integrator/config-arm-integrator.cpp | 3 + .../integrator/kernel_uart-arm-integrator.cpp | 12 + .../integrator/mem_layout-arm-integrator.cpp | 23 + .../arm/bsp/integrator/pic-arm-integrator.cpp | 101 + .../bsp/integrator/reset-arm-integrator.cpp | 17 + .../bsp/integrator/timer-arm-integrator.cpp | 87 + .../bsp/integrator/uart-arm-integrator.cpp | 14 + .../fiasco/src/kern/arm/bsp/kirkwood/Kconfig | 4 + .../fiasco/src/kern/arm/bsp/kirkwood/Modules | 15 + .../bsp/kirkwood/bootstrap-arm-kirkwood.cpp | 14 + .../arm/bsp/kirkwood/config-arm-kirkwood.cpp | 3 + .../bsp/kirkwood/kernel_uart-arm-kirkwood.cpp | 14 + .../bsp/kirkwood/mem_layout-arm-kirkwood.cpp | 23 + .../arm/bsp/kirkwood/pic-arm-kirkwood.cpp | 129 + .../arm/bsp/kirkwood/reset-arm-kirkwood.cpp | 30 + .../arm/bsp/kirkwood/timer-arm-kirkwood.cpp | 84 + .../bsp/kirkwood/uart-16550-arm-kirkwood.cpp | 20 + kernel/fiasco/src/kern/arm/bsp/omap3/Kconfig | 37 + kernel/fiasco/src/kern/arm/bsp/omap3/Modules | 26 + .../kern/arm/bsp/omap3/boot_mp-arm-omap4.cpp | 60 + .../kern/arm/bsp/omap3/bootstrap-arm-omap.cpp | 21 + .../kern/arm/bsp/omap3/config-arm-omap.cpp | 11 + .../arm/bsp/omap3/kernel_uart-arm-omap.cpp | 12 + .../arm/bsp/omap3/mem_layout-arm-omap.cpp | 115 + .../kern/arm/bsp/omap3/pic-arm-gic-omap4.cpp | 40 + .../src/kern/arm/bsp/omap3/pic-arm-omap3.cpp | 155 + .../src/kern/arm/bsp/omap3/reset-arm-omap.cpp | 54 + .../arm/bsp/omap3/timer-arm-mptimer-omap4.cpp | 8 + .../kern/arm/bsp/omap3/timer-arm-omap3.cpp | 285 + .../src/kern/arm/bsp/omap3/uart-arm-omap.cpp | 24 + .../arm/bsp/pxa-sa/config-arm-pxa_sa1100.cpp | 5 + .../arm/bsp/pxa-sa/pic-arm-pxa_sa1100.cpp | 126 + .../arm/bsp/pxa-sa/timer-arm-pxa_sa1100.cpp | 110 + kernel/fiasco/src/kern/arm/bsp/pxa/Kconfig | 4 + kernel/fiasco/src/kern/arm/bsp/pxa/Modules | 17 + .../kern/arm/bsp/pxa/bootstrap-arm-pxa.cpp | 23 + .../kern/arm/bsp/pxa/kernel_uart-arm-pxa.cpp | 13 + .../kern/arm/bsp/pxa/mem_layout-arm-pxa.cpp | 21 + .../src/kern/arm/bsp/pxa/reset-arm-pxa.cpp | 18 + .../kern/arm/bsp/pxa/uart-16550-arm-pxa.cpp | 22 + .../fiasco/src/kern/arm/bsp/realview/Kconfig | 71 + .../fiasco/src/kern/arm/bsp/realview/Modules | 36 + .../bsp/realview/board_check-arm-realview.cpp | 96 + .../arm/bsp/realview/boot_mp-arm-realview.cpp | 30 + .../bsp/realview/bootstrap-arm-realview.cpp | 51 + .../arm/bsp/realview/clock-arm-realview.cpp | 34 + .../arm/bsp/realview/config-arm-realview.cpp | 3 + .../bsp/realview/kernel_uart-arm-realview.cpp | 12 + .../bsp/realview/mem_layout-arm-realview.cpp | 185 + .../bsp/realview/outer_cache-arm-realview.cpp | 31 + .../arm/bsp/realview/pic-arm-realview.cpp | 129 + .../bsp/realview/platform-arm-realview.cpp | 39 + .../arm/bsp/realview/reset-arm-realview.cpp | 51 + .../realview/timer-arm-mptimer-realview.cpp | 28 + .../arm/bsp/realview/timer-arm-realview.cpp | 129 + .../arm/bsp/realview/uart-arm-realview.cpp | 24 + kernel/fiasco/src/kern/arm/bsp/s3c/Kconfig | 4 + kernel/fiasco/src/kern/arm/bsp/s3c/Modules | 17 + .../arm/bsp/s3c/bootstrap-arm-s3c2410.cpp | 24 + .../kern/arm/bsp/s3c/config-arm-s3c2410.cpp | 3 + .../arm/bsp/s3c/kernel_uart-arm-s3c2410.cpp | 12 + .../arm/bsp/s3c/mem_layout-arm-s3c2410.cpp | 22 + .../src/kern/arm/bsp/s3c/pic-arm-s3c2410.cpp | 254 + .../kern/arm/bsp/s3c/reset-arm-s3c2410.cpp | 28 + .../kern/arm/bsp/s3c/timer-arm-s3c2410.cpp | 83 + .../src/kern/arm/bsp/s3c/uart-s3c2410.cpp | 14 + kernel/fiasco/src/kern/arm/bsp/sa1100/Kconfig | 4 + kernel/fiasco/src/kern/arm/bsp/sa1100/Modules | 16 + .../arm/bsp/sa1100/bootstrap-arm-sa1100.cpp | 23 + .../arm/bsp/sa1100/kernel_uart-arm-sa1100.cpp | 14 + .../arm/bsp/sa1100/mem_layout-arm-sa1100.cpp | 23 + .../kern/arm/bsp/sa1100/reset-arm-sa1100.cpp | 15 + kernel/fiasco/src/kern/arm/bsp/tegra2/Kconfig | 4 + kernel/fiasco/src/kern/arm/bsp/tegra2/Modules | 19 + .../arm/bsp/tegra2/boot_mp-arm-tegra2.cpp | 48 + .../arm/bsp/tegra2/bootstrap-arm-tegra2.cpp | 16 + .../kern/arm/bsp/tegra2/config-arm-tegra2.cpp | 3 + .../arm/bsp/tegra2/kernel_uart-arm-tegra2.cpp | 14 + .../arm/bsp/tegra2/mem_layout-arm-tegra2.cpp | 30 + .../arm/bsp/tegra2/outer_cache-arm-tegra2.cpp | 18 + .../kern/arm/bsp/tegra2/pic-arm-tegra2.cpp | 41 + .../kern/arm/bsp/tegra2/reset-arm-tegra2.cpp | 24 + .../kern/arm/bsp/tegra2/timer-arm-tegra2.cpp | 8 + .../arm/bsp/tegra2/uart-16550-arm-tegra2.cpp | 20 + kernel/fiasco/src/kern/arm/config-arm.cpp | 87 + kernel/fiasco/src/kern/arm/context-arm.cpp | 168 + .../fiasco/src/kern/arm/continuation-arm.cpp | 75 + kernel/fiasco/src/kern/arm/cpu-arm.cpp | 679 + kernel/fiasco/src/kern/arm/crt0.S | 27 + .../fiasco/src/kern/arm/entry_frame-arm.cpp | 108 + kernel/fiasco/src/kern/arm/fpu-arm.cpp | 306 + kernel/fiasco/src/kern/arm/gic.cpp | 335 + kernel/fiasco/src/kern/arm/ipi-arm.cpp | 63 + kernel/fiasco/src/kern/arm/ivt.S | 1192 ++ kernel/fiasco/src/kern/arm/kdb_ke-arm.cpp | 8 + kernel/fiasco/src/kern/arm/kern_lib_page.cpp | 144 + .../fiasco/src/kern/arm/kernel_task-arm.cpp | 11 + .../fiasco/src/kern/arm/kernel_thread-arm.cpp | 103 + kernel/fiasco/src/kern/arm/kip_init.cpp | 74 + kernel/fiasco/src/kern/arm/kmem.cpp | 30 + kernel/fiasco/src/kern/arm/kmem_alloc-arm.cpp | 87 + kernel/fiasco/src/kern/arm/kmem_space.cpp | 48 + kernel/fiasco/src/kern/arm/logdefs.h | 238 + kernel/fiasco/src/kern/arm/main.cpp | 152 + kernel/fiasco/src/kern/arm/mapping-arm.cpp | 25 + kernel/fiasco/src/kern/arm/mem_layout-arm.cpp | 135 + .../src/kern/arm/mem_layout-noncont.cpp | 69 + kernel/fiasco/src/kern/arm/mem_op.cpp | 257 + kernel/fiasco/src/kern/arm/mem_space-arm.cpp | 572 + kernel/fiasco/src/kern/arm/mem_unit.cpp | 125 + .../src/kern/arm/outer_cache-l2cxx0.cpp | 227 + kernel/fiasco/src/kern/arm/outer_cache.cpp | 121 + kernel/fiasco/src/kern/arm/pagetable-arch.cpp | 732 + .../fiasco/src/kern/arm/pagetable-arch_defs.h | 97 + kernel/fiasco/src/kern/arm/pagetable.cpp | 37 + kernel/fiasco/src/kern/arm/paging-arm.cpp | 186 + kernel/fiasco/src/kern/arm/perf_cnt-arm.cpp | 496 + kernel/fiasco/src/kern/arm/pic-gic.cpp | 18 + kernel/fiasco/src/kern/arm/space-arm.cpp | 6 + kernel/fiasco/src/kern/arm/spin_lock-arm.cpp | 66 + kernel/fiasco/src/kern/arm/startup-arm.cpp | 64 + .../fiasco/src/kern/arm/sys_call_page-arm.cpp | 56 + kernel/fiasco/src/kern/arm/task-arm.cpp | 8 + kernel/fiasco/src/kern/arm/tb_entry-arm.cpp | 158 + kernel/fiasco/src/kern/arm/thread-arm.cpp | 732 + kernel/fiasco/src/kern/arm/thread-entry.cpp | 15 + kernel/fiasco/src/kern/arm/thread-jdb.cpp | 131 + .../fiasco/src/kern/arm/timer-arm-mptimer.cpp | 108 + kernel/fiasco/src/kern/arm/timer-arm.cpp | 44 + kernel/fiasco/src/kern/arm/timer_tick-arm.cpp | 11 + kernel/fiasco/src/kern/arm/tramp-mp.S | 178 + kernel/fiasco/src/kern/arm/trap_state.cpp | 95 + kernel/fiasco/src/kern/arm/utcb_init-arm.cpp | 20 + .../fiasco/src/kern/arm/utcb_support-arm.cpp | 33 + kernel/fiasco/src/kern/arm/vm.cpp | 440 + .../fiasco/src/kern/arm/vmem_alloc-arch.cpp | 52 + kernel/fiasco/src/kern/auto_quota.h | 65 + kernel/fiasco/src/kern/banner.cpp | 25 + kernel/fiasco/src/kern/boot_alloc.cpp | 115 + kernel/fiasco/src/kern/boot_info.cpp | 12 + kernel/fiasco/src/kern/buddy_alloc.cpp | 266 + kernel/fiasco/src/kern/bug.h | 17 + kernel/fiasco/src/kern/cascade_irq.cpp | 25 + kernel/fiasco/src/kern/checksum.cpp | 44 + kernel/fiasco/src/kern/clock-generic.cpp | 28 + kernel/fiasco/src/kern/clock.cpp | 44 + kernel/fiasco/src/kern/config.cpp | 243 + kernel/fiasco/src/kern/config_gdt.h | 40 + kernel/fiasco/src/kern/config_tcbsize.h | 12 + kernel/fiasco/src/kern/context-vcpu.cpp | 170 + kernel/fiasco/src/kern/context.cpp | 2106 +++ kernel/fiasco/src/kern/context_base.cpp | 89 + kernel/fiasco/src/kern/cpu.cpp | 144 + kernel/fiasco/src/kern/cpu_lock-generic.cpp | 32 + kernel/fiasco/src/kern/cpu_lock.cpp | 94 + kernel/fiasco/src/kern/cpu_mask.cpp | 24 + kernel/fiasco/src/kern/dbg_page_info.cpp | 129 + kernel/fiasco/src/kern/dump_tcboffsets.cc | 59 + .../src/kern/entry_frame-abs-timeout-hack.cpp | 1 + kernel/fiasco/src/kern/entry_frame.cpp | 53 + kernel/fiasco/src/kern/factory.cpp | 347 + kernel/fiasco/src/kern/feature.h | 14 + kernel/fiasco/src/kern/fpu.cpp | 105 + kernel/fiasco/src/kern/fpu_alloc.cpp | 61 + kernel/fiasco/src/kern/fpu_state.cpp | 59 + kernel/fiasco/src/kern/genchecksum.cc | 168 + kernel/fiasco/src/kern/genlines.c | 323 + kernel/fiasco/src/kern/globals.cpp | 78 + kernel/fiasco/src/kern/helping_lock.cpp | 124 + kernel/fiasco/src/kern/hpet.cpp | 230 + .../src/kern/ia32/32/config-ia32-32.cpp | 18 + .../src/kern/ia32/32/context-ia32-32.cpp | 76 + .../kern/ia32/32/continuation-ia32-32-ux.cpp | 75 + .../src/kern/ia32/32/continuation-ia32-32.cpp | 76 + kernel/fiasco/src/kern/ia32/32/cpu-32.cpp | 208 + kernel/fiasco/src/kern/ia32/32/crt0.S | 14 + kernel/fiasco/src/kern/ia32/32/entry-native.S | 312 + kernel/fiasco/src/kern/ia32/32/entry-ux.S | 11 + kernel/fiasco/src/kern/ia32/32/entry.S | 676 + .../src/kern/ia32/32/entry_frame-ia32-ux.cpp | 187 + .../fiasco/src/kern/ia32/32/kmem-ia32-32.cpp | 13 + kernel/fiasco/src/kern/ia32/32/linking.h | 8 + kernel/fiasco/src/kern/ia32/32/low_level.h | 119 + .../fiasco/src/kern/ia32/32/main-ia32-32.cpp | 78 + .../src/kern/ia32/32/mapping-ia32-32.cpp | 27 + .../src/kern/ia32/32/mem_layout-ia32-32.cpp | 134 + .../fiasco/src/kern/ia32/32/mem_unit-ia32.cpp | 35 + .../src/kern/ia32/32/paging-ia32-32.cpp | 71 + .../kern/ia32/32/sys_call_page-abs-ia32.cpp | 70 + .../src/kern/ia32/32/sys_call_page-asm.S | 40 + .../src/kern/ia32/32/tb_entry-ia32-32.cpp | 183 + kernel/fiasco/src/kern/ia32/32/thread-dbf.cpp | 100 + .../src/kern/ia32/32/thread-ia32-32.cpp | 372 + kernel/fiasco/src/kern/ia32/32/trap_state.cpp | 249 + kernel/fiasco/src/kern/ia32/32/tss.cpp | 44 + kernel/fiasco/src/kern/ia32/32/vm_svm_asm.S | 64 + kernel/fiasco/src/kern/ia32/32/vm_vmx_asm.S | 75 + .../src/kern/ia32/64/config-ia32-64.cpp | 30 + .../src/kern/ia32/64/context-ia32-64.cpp | 71 + .../src/kern/ia32/64/continuation-ia32-64.cpp | 81 + kernel/fiasco/src/kern/ia32/64/cpu-64.cpp | 176 + kernel/fiasco/src/kern/ia32/64/crt0.S | 13 + kernel/fiasco/src/kern/ia32/64/entry-native.S | 221 + kernel/fiasco/src/kern/ia32/64/entry.S | 512 + .../src/kern/ia32/64/entry_frame-amd64.cpp | 153 + .../fiasco/src/kern/ia32/64/kmem-ia32-64.cpp | 7 + kernel/fiasco/src/kern/ia32/64/linking.h | 8 + kernel/fiasco/src/kern/ia32/64/low_level.h | 185 + .../fiasco/src/kern/ia32/64/main-ia32-64.cpp | 77 + .../src/kern/ia32/64/mapping-ia32-64.cpp | 28 + .../src/kern/ia32/64/mem_layout-ia32-64.cpp | 135 + .../src/kern/ia32/64/mem_unit-amd64.cpp | 35 + .../src/kern/ia32/64/paging-ia32-64.cpp | 86 + kernel/fiasco/src/kern/ia32/64/shortcut.S | 512 + .../src/kern/ia32/64/tb_entry-ia32-64.cpp | 183 + kernel/fiasco/src/kern/ia32/64/thread-dbf.cpp | 78 + .../src/kern/ia32/64/thread-ia32-64.cpp | 263 + .../src/kern/ia32/64/trap_state-amd64.cpp | 237 + kernel/fiasco/src/kern/ia32/64/tss-amd64.cpp | 35 + kernel/fiasco/src/kern/ia32/64/vm_svm_asm.S | 79 + kernel/fiasco/src/kern/ia32/64/vm_vmx_asm.S | 93 + kernel/fiasco/src/kern/ia32/Makerules.KERNEL | 15 + .../src/kern/ia32/Makerules.SYMBOLS.ia32 | 12 + kernel/fiasco/src/kern/ia32/__main.cpp | 29 + kernel/fiasco/src/kern/ia32/apic-debug.cpp | 134 + kernel/fiasco/src/kern/ia32/apic-ia32-mp.cpp | 160 + kernel/fiasco/src/kern/ia32/apic-ia32.cpp | 838 + kernel/fiasco/src/kern/ia32/asm.h | 78 + .../src/kern/ia32/boot_console-ia32-amd64.cpp | 52 + .../fiasco/src/kern/ia32/boot_info-ia32.cpp | 85 + kernel/fiasco/src/kern/ia32/clock-ia32.cpp | 28 + kernel/fiasco/src/kern/ia32/config-ia32.cpp | 165 + kernel/fiasco/src/kern/ia32/context-ia32.cpp | 67 + kernel/fiasco/src/kern/ia32/cpu-ia32.cpp | 1707 ++ kernel/fiasco/src/kern/ia32/dirq-ia32-ux.cpp | 51 + kernel/fiasco/src/kern/ia32/entry-mp.S | 27 + kernel/fiasco/src/kern/ia32/fpu-ia32-ux.cpp | 182 + kernel/fiasco/src/kern/ia32/fpu-ia32.cpp | 148 + kernel/fiasco/src/kern/ia32/gdt.cpp | 119 + kernel/fiasco/src/kern/ia32/idt.cpp | 237 + kernel/fiasco/src/kern/ia32/idt_init.h | 78 + kernel/fiasco/src/kern/ia32/io_apic.cpp | 475 + kernel/fiasco/src/kern/ia32/ipi-ia32.cpp | 103 + kernel/fiasco/src/kern/ia32/irq_chip_ia32.cpp | 290 + kernel/fiasco/src/kern/ia32/irq_chip_pic.cpp | 153 + kernel/fiasco/src/kern/ia32/irq_msi.cpp | 137 + kernel/fiasco/src/kern/ia32/kdb_ke-ia32.cpp | 15 + .../src/kern/ia32/kernel_thread-ia32.cpp | 122 + kernel/fiasco/src/kern/ia32/kip_init-ia32.cpp | 154 + kernel/fiasco/src/kern/ia32/kmem-ia32.cpp | 575 + .../fiasco/src/kern/ia32/kmem_alloc-ia32.cpp | 171 + kernel/fiasco/src/kern/ia32/loadcnt.cpp | 20 + kernel/fiasco/src/kern/ia32/logdefs.h | 240 + kernel/fiasco/src/kern/ia32/main-ia32.cpp | 146 + kernel/fiasco/src/kern/ia32/map_util-io.cpp | 121 + .../fiasco/src/kern/ia32/mem_layout-ia32.cpp | 74 + .../fiasco/src/kern/ia32/mem_space-ia32.cpp | 475 + kernel/fiasco/src/kern/ia32/no_kdb_ke.cpp | 11 + kernel/fiasco/src/kern/ia32/paging-ia32.cpp | 148 + kernel/fiasco/src/kern/ia32/perf_cnt-ia32.cpp | 1230 ++ kernel/fiasco/src/kern/ia32/rtc-ia32.cpp | 124 + kernel/fiasco/src/kern/ia32/shortcut.h | 125 + kernel/fiasco/src/kern/ia32/space-ia32.cpp | 66 + .../fiasco/src/kern/ia32/spin_lock-ia32.cpp | 43 + kernel/fiasco/src/kern/ia32/startup-ia32.cpp | 119 + kernel/fiasco/src/kern/ia32/svm.cpp | 244 + .../fiasco/src/kern/ia32/task-ia32-amd64.cpp | 76 + kernel/fiasco/src/kern/ia32/thread-ia32.cpp | 821 + kernel/fiasco/src/kern/ia32/thread-io.cpp | 198 + kernel/fiasco/src/kern/ia32/timer-apic.cpp | 83 + .../src/kern/ia32/timer-ia32-amd64-ux.cpp | 39 + kernel/fiasco/src/kern/ia32/timer-pit.cpp | 35 + kernel/fiasco/src/kern/ia32/timer-rtc.cpp | 54 + kernel/fiasco/src/kern/ia32/timer_irq.cpp | 54 + .../fiasco/src/kern/ia32/timer_tick-apic.cpp | 73 + .../fiasco/src/kern/ia32/timer_tick-ia32.cpp | 70 + kernel/fiasco/src/kern/ia32/tramp-mp.S | 165 + .../fiasco/src/kern/ia32/utcb_init-ia32.cpp | 35 + kernel/fiasco/src/kern/ia32/vm.cpp | 49 + .../fiasco/src/kern/ia32/vm_factory-ia32.cpp | 39 + kernel/fiasco/src/kern/ia32/vm_svm.cpp | 718 + kernel/fiasco/src/kern/ia32/vm_vmx.cpp | 520 + .../fiasco/src/kern/ia32/vmem_alloc-ia32.cpp | 69 + kernel/fiasco/src/kern/ia32/vmx.cpp | 578 + kernel/fiasco/src/kern/ia32/watchdog-ia32.cpp | 141 + kernel/fiasco/src/kern/ia32/x86desc.cpp | 423 + kernel/fiasco/src/kern/icu_helper.cpp | 203 + kernel/fiasco/src/kern/initcalls.h | 17 + kernel/fiasco/src/kern/io_space.cpp | 472 + kernel/fiasco/src/kern/ipc_gate.cpp | 383 + kernel/fiasco/src/kern/ipc_sender.cpp | 177 + kernel/fiasco/src/kern/ipc_timeout.cpp | 64 + kernel/fiasco/src/kern/ipi.cpp | 91 + kernel/fiasco/src/kern/irq.cpp | 717 + kernel/fiasco/src/kern/irq_chip.cpp | 336 + kernel/fiasco/src/kern/irq_chip_generic.cpp | 88 + kernel/fiasco/src/kern/irq_controller.cpp | 82 + kernel/fiasco/src/kern/irq_mgr.cpp | 131 + kernel/fiasco/src/kern/irq_mgr_multi_chip.cpp | 85 + kernel/fiasco/src/kern/kdb_ke.cpp | 17 + kernel/fiasco/src/kern/kern_cnt.cpp | 109 + kernel/fiasco/src/kern/kernel_console.cpp | 64 + kernel/fiasco/src/kern/kernel_panic.cc | 42 + kernel/fiasco/src/kern/kernel_task.cpp | 39 + kernel/fiasco/src/kern/kernel_thread-std.cpp | 161 + kernel/fiasco/src/kern/kernel_thread.cpp | 186 + kernel/fiasco/src/kern/kernel_uart-16550.cpp | 12 + kernel/fiasco/src/kern/kernel_uart.cpp | 145 + kernel/fiasco/src/kern/kmem_alloc.cpp | 325 + kernel/fiasco/src/kern/kmem_slab.cpp | 122 + kernel/fiasco/src/kern/kobject.cpp | 249 + kernel/fiasco/src/kern/kobject_dbg.cpp | 175 + kernel/fiasco/src/kern/kobject_helper.cpp | 67 + kernel/fiasco/src/kern/kobject_iface.cpp | 63 + kernel/fiasco/src/kern/kobject_mapdb.cpp | 184 + kernel/fiasco/src/kern/koptions-def.h | 75 + kernel/fiasco/src/kern/koptions.cpp | 30 + kernel/fiasco/src/kern/l4_buf_iter.cpp | 112 + kernel/fiasco/src/kern/libc_backend_lock.cc | 15 + kernel/fiasco/src/kern/lock.cpp | 11 + kernel/fiasco/src/kern/map_util-mem.cpp | 186 + kernel/fiasco/src/kern/map_util-objs.cpp | 152 + kernel/fiasco/src/kern/map_util.cpp | 812 + kernel/fiasco/src/kern/mapdb.cpp | 1120 ++ kernel/fiasco/src/kern/mappable.cpp | 21 + kernel/fiasco/src/kern/mapping.cpp | 178 + kernel/fiasco/src/kern/mapping_tree.cpp | 1007 ++ kernel/fiasco/src/kern/mem_layout.cpp | 46 + kernel/fiasco/src/kern/mem_space-user.cpp | 67 + kernel/fiasco/src/kern/mem_space.cpp | 219 + kernel/fiasco/src/kern/member_offs.h | 7 + kernel/fiasco/src/kern/mp_lock.cpp | 182 + kernel/fiasco/src/kern/obj_helping_lock.cpp | 76 + kernel/fiasco/src/kern/obj_ref_ptr.cpp | 44 + kernel/fiasco/src/kern/obj_space-phys.cpp | 243 + kernel/fiasco/src/kern/obj_space-virt.cpp | 315 + kernel/fiasco/src/kern/obj_space.cpp | 321 + kernel/fiasco/src/kern/paging.cpp | 137 + kernel/fiasco/src/kern/per_cpu_data.cpp | 319 + kernel/fiasco/src/kern/per_cpu_data_alloc.cpp | 62 + kernel/fiasco/src/kern/perf_cnt.cpp | 95 + kernel/fiasco/src/kern/pic-i8259.cpp | 355 + kernel/fiasco/src/kern/pic.cpp | 75 + kernel/fiasco/src/kern/pit-i8254.cpp | 102 + kernel/fiasco/src/kern/ppc32/Makerules.KERNEL | 34 + .../fiasco/src/kern/ppc32/boot_info-ppc32.cpp | 73 + .../fiasco/src/kern/ppc32/boot_uart_init.cpp | 14 + kernel/fiasco/src/kern/ppc32/bootstrap.cpp | 34 + .../fiasco/src/kern/ppc32/bsp/mpc52xx/Kconfig | 3 + .../fiasco/src/kern/ppc32/bsp/mpc52xx/Modules | 9 + .../ppc32/bsp/mpc52xx/boot_info-mpc52xx.cpp | 25 + .../bsp/mpc52xx/config-ppc32-mpc52xx.cpp | 11 + .../kern/ppc32/bsp/mpc52xx/pic-mpc52xx.cpp | 385 + kernel/fiasco/src/kern/ppc32/bsp/qemu/Kconfig | 3 + kernel/fiasco/src/kern/ppc32/bsp/qemu/Modules | 8 + .../ppc32/bsp/qemu/boot_info-ppc32-qemu.cpp | 9 + .../kern/ppc32/bsp/qemu/config-ppc32-qemu.cpp | 11 + .../kern/ppc32/bsp/qemu/pic-ppc32-qemu.cpp | 49 + kernel/fiasco/src/kern/ppc32/config-ppc32.cpp | 53 + .../fiasco/src/kern/ppc32/context-ppc32.cpp | 94 + .../src/kern/ppc32/continuation-ppc32.cpp | 82 + kernel/fiasco/src/kern/ppc32/cpu-ppc32.cpp | 213 + kernel/fiasco/src/kern/ppc32/crt0.S | 18 + kernel/fiasco/src/kern/ppc32/decrementer.cpp | 69 + kernel/fiasco/src/kern/ppc32/dirq-ppc32.cpp | 31 + .../src/kern/ppc32/entry_frame-ppc32.cpp | 149 + kernel/fiasco/src/kern/ppc32/exception.S | 361 + kernel/fiasco/src/kern/ppc32/kdb_ke-ppc32.cpp | 4 + .../src/kern/ppc32/kernel_task-ppc32.cpp | 10 + .../src/kern/ppc32/kernel_thread-ppc32.cpp | 22 + kernel/fiasco/src/kern/ppc32/kip_init.cpp | 73 + kernel/fiasco/src/kern/ppc32/kmem.cpp | 88 + .../src/kern/ppc32/kmem_alloc-ppc32.cpp | 51 + kernel/fiasco/src/kern/ppc32/main.cpp | 99 + .../fiasco/src/kern/ppc32/mapping-ppc32.cpp | 24 + .../src/kern/ppc32/mem_layout-ppc32.cpp | 147 + .../fiasco/src/kern/ppc32/mem_space-cache.cpp | 71 + .../fiasco/src/kern/ppc32/mem_space-htab.cpp | 439 + .../fiasco/src/kern/ppc32/mem_space-ppc32.cpp | 465 + .../fiasco/src/kern/ppc32/mem_unit-ppc32.cpp | 52 + kernel/fiasco/src/kern/ppc32/msr.cpp | 85 + kernel/fiasco/src/kern/ppc32/paging-ppc32.cpp | 386 + kernel/fiasco/src/kern/ppc32/phys_mem.S | 7 + kernel/fiasco/src/kern/ppc32/space-ppc32.cpp | 6 + .../fiasco/src/kern/ppc32/startup-ppc32.cpp | 58 + .../src/kern/ppc32/sys_call_page-ppc32.cpp | 47 + kernel/fiasco/src/kern/ppc32/task-ppc32.cpp | 8 + .../fiasco/src/kern/ppc32/tb_entry-ppc32.cpp | 151 + kernel/fiasco/src/kern/ppc32/thread-jdb.cpp | 117 + kernel/fiasco/src/kern/ppc32/thread-ppc32.cpp | 377 + .../src/kern/ppc32/timer-decr-ppc32.cpp | 86 + .../src/kern/ppc32/timer_tick-ppc32.cpp | 7 + kernel/fiasco/src/kern/ppc32/trap_state.cpp | 89 + .../fiasco/src/kern/ppc32/utcb_init-ppc32.cpp | 20 + .../src/kern/ppc32/utcb_support-ppc32.cpp | 18 + kernel/fiasco/src/kern/ppc32/util.cpp | 18 + .../src/kern/ppc32/vmem_alloc-ppc32.cpp | 29 + kernel/fiasco/src/kern/ppc32/warn-ppc32.cpp | 5 + kernel/fiasco/src/kern/prio_list.cpp | 200 + kernel/fiasco/src/kern/ptab_base.cpp | 597 + kernel/fiasco/src/kern/push_console.cpp | 74 + kernel/fiasco/src/kern/queue.cpp | 136 + kernel/fiasco/src/kern/queue_item.cpp | 44 + kernel/fiasco/src/kern/ram_quota.cpp | 83 + kernel/fiasco/src/kern/rcupdate.cpp | 545 + kernel/fiasco/src/kern/ready_queue_fp.cpp | 101 + kernel/fiasco/src/kern/ready_queue_wfq.cpp | 180 + kernel/fiasco/src/kern/receiver.cpp | 332 + kernel/fiasco/src/kern/ref_obj.cpp | 49 + kernel/fiasco/src/kern/ref_ptr.cpp | 70 + kernel/fiasco/src/kern/regdefs.h | 160 + kernel/fiasco/src/kern/reset-dummy.cpp | 10 + .../src/kern/sched_context-fixed_prio.cpp | 225 + .../fiasco/src/kern/sched_context-fp_wfq.cpp | 309 + kernel/fiasco/src/kern/sched_context-wfq.cpp | 254 + kernel/fiasco/src/kern/sched_context.cpp | 70 + kernel/fiasco/src/kern/scheduler.cpp | 266 + kernel/fiasco/src/kern/sender.cpp | 166 + kernel/fiasco/src/kern/setchecksum.c | 96 + kernel/fiasco/src/kern/sigma0_task-io.cpp | 15 + kernel/fiasco/src/kern/sigma0_task.cpp | 40 + kernel/fiasco/src/kern/space-io.cpp | 9 + kernel/fiasco/src/kern/space.cpp | 153 + kernel/fiasco/src/kern/sparc/Makerules.KERNEL | 27 + .../fiasco/src/kern/sparc/boot_info-sparc.cpp | 28 + .../fiasco/src/kern/sparc/boot_uart_init.cpp | 17 + kernel/fiasco/src/kern/sparc/bootstrap.cpp | 34 + .../fiasco/src/kern/sparc/bsp/leon3/Kconfig | 3 + .../fiasco/src/kern/sparc/bsp/leon3/Modules | 11 + .../sparc/bsp/leon3/boot_info-sparc-leon3.cpp | 21 + .../sparc/bsp/leon3/config-sparc-leon3.cpp | 11 + .../kern/sparc/bsp/leon3/pic-sparc-leon3.cpp | 322 + kernel/fiasco/src/kern/sparc/config-sparc.cpp | 51 + .../fiasco/src/kern/sparc/context-sparc.cpp | 48 + .../src/kern/sparc/continuation-sparc.cpp | 82 + kernel/fiasco/src/kern/sparc/cpu-sparc.cpp | 167 + kernel/fiasco/src/kern/sparc/crt0.S | 172 + kernel/fiasco/src/kern/sparc/decrementer.cpp | 67 + kernel/fiasco/src/kern/sparc/dirq-sparc.cpp | 31 + .../src/kern/sparc/entry_frame-sparc.cpp | 150 + kernel/fiasco/src/kern/sparc/exceptions.S | 8 + kernel/fiasco/src/kern/sparc/kdb_ke-sparc.cpp | 4 + .../src/kern/sparc/kernel_task-sparc.cpp | 10 + .../src/kern/sparc/kernel_thread-sparc.cpp | 22 + kernel/fiasco/src/kern/sparc/kip_init.cpp | 73 + kernel/fiasco/src/kern/sparc/kmem.cpp | 88 + .../src/kern/sparc/kmem_alloc-sparc.cpp | 31 + kernel/fiasco/src/kern/sparc/main.cpp | 92 + .../fiasco/src/kern/sparc/mapping-sparc.cpp | 24 + .../src/kern/sparc/mem_layout-sparc.cpp | 166 + .../fiasco/src/kern/sparc/mem_space-sparc.cpp | 344 + .../fiasco/src/kern/sparc/mem_unit-sparc.cpp | 94 + kernel/fiasco/src/kern/sparc/paging-sparc.cpp | 326 + kernel/fiasco/src/kern/sparc/psr.cpp | 52 + kernel/fiasco/src/kern/sparc/space-sparc.cpp | 6 + .../fiasco/src/kern/sparc/startup-sparc.cpp | 58 + .../src/kern/sparc/sys_call_page-sparc.cpp | 16 + kernel/fiasco/src/kern/sparc/task-sparc.cpp | 8 + .../fiasco/src/kern/sparc/tb_entry-sparc.cpp | 151 + kernel/fiasco/src/kern/sparc/thread-jdb.cpp | 79 + kernel/fiasco/src/kern/sparc/thread-sparc.cpp | 299 + .../src/kern/sparc/timer-decr-sparc.cpp | 86 + .../src/kern/sparc/timer_tick-sparc.cpp | 7 + kernel/fiasco/src/kern/sparc/trap_state.cpp | 88 + kernel/fiasco/src/kern/sparc/uart-asi.cpp | 15 + .../fiasco/src/kern/sparc/utcb_init-sparc.cpp | 20 + .../src/kern/sparc/utcb_support-sparc.cpp | 17 + kernel/fiasco/src/kern/sparc/util.cpp | 18 + .../src/kern/sparc/vmem_alloc-sparc.cpp | 29 + kernel/fiasco/src/kern/sparc/warn-sparc.cpp | 5 + kernel/fiasco/src/kern/spin_lock.cpp | 149 + kernel/fiasco/src/kern/startup.cpp | 20 + kernel/fiasco/src/kern/static_assert.h | 9 + kernel/fiasco/src/kern/static_init.h | 120 + kernel/fiasco/src/kern/switch_lock.cpp | 392 + kernel/fiasco/src/kern/sys_call_page.cpp | 19 + kernel/fiasco/src/kern/syscalls-log.cpp | 126 + kernel/fiasco/src/kern/syscalls.cpp | 69 + kernel/fiasco/src/kern/task.cpp | 615 + kernel/fiasco/src/kern/tb_entry.cpp | 887 ++ kernel/fiasco/src/kern/tb_entry_output.cpp | 526 + kernel/fiasco/src/kern/tcboffset.cc | 60 + kernel/fiasco/src/kern/tcboffset_in.h | 89 + kernel/fiasco/src/kern/terminate.cpp | 53 + kernel/fiasco/src/kern/thread-debug.cpp | 43 + kernel/fiasco/src/kern/thread-ipc.cpp | 1237 ++ kernel/fiasco/src/kern/thread-log.cpp | 39 + kernel/fiasco/src/kern/thread-pagefault.cpp | 127 + kernel/fiasco/src/kern/thread-vcpu.cpp | 54 + kernel/fiasco/src/kern/thread.cpp | 1210 ++ kernel/fiasco/src/kern/thread_lock.cpp | 284 + kernel/fiasco/src/kern/thread_object.cpp | 688 + kernel/fiasco/src/kern/thread_state.cpp | 51 + kernel/fiasco/src/kern/timeout.cpp | 374 + kernel/fiasco/src/kern/timer-hpet.cpp | 76 + kernel/fiasco/src/kern/timer.cpp | 46 + .../src/kern/timer_tick-single-vector.cpp | 51 + kernel/fiasco/src/kern/timer_tick.cpp | 127 + kernel/fiasco/src/kern/timeslice_timeout.cpp | 55 + kernel/fiasco/src/kern/uart-mmio.cpp | 14 + kernel/fiasco/src/kern/uart_console.cpp | 41 + kernel/fiasco/src/kern/utcb_init.cpp | 20 + kernel/fiasco/src/kern/utcb_support.cpp | 10 + kernel/fiasco/src/kern/ux/Makerules.KERNEL | 75 + .../fiasco/src/kern/ux/Makerules.SYMBOLS.ux | 11 + kernel/fiasco/src/kern/ux/boot_info-ux.cpp | 749 + kernel/fiasco/src/kern/ux/config-ux.cpp | 55 + kernel/fiasco/src/kern/ux/context-ux.cpp | 59 + kernel/fiasco/src/kern/ux/cpu-ux.cpp | 220 + kernel/fiasco/src/kern/ux/emulation.cpp | 286 + kernel/fiasco/src/kern/ux/fb.cpp | 150 + kernel/fiasco/src/kern/ux/format.h | 20 + kernel/fiasco/src/kern/ux/fpu-ux.cpp | 68 + kernel/fiasco/src/kern/ux/glibc_getchar.cpp | 45 + kernel/fiasco/src/kern/ux/glue_libc_ux.cc | 24 + kernel/fiasco/src/kern/ux/hostproc.cpp | 136 + kernel/fiasco/src/kern/ux/ipi-ux.cpp | 75 + kernel/fiasco/src/kern/ux/irq-ux.cpp | 0 kernel/fiasco/src/kern/ux/irq0.c | 38 + .../fiasco/src/kern/ux/kernel_thread-ux.cpp | 106 + kernel/fiasco/src/kern/ux/kip_init-ux.cpp | 96 + kernel/fiasco/src/kern/ux/kmem-ux.cpp | 133 + .../fiasco/src/kern/ux/libc_backend_nolock.cc | 10 + kernel/fiasco/src/kern/ux/libc_support.cpp | 47 + kernel/fiasco/src/kern/ux/loader.cpp | 236 + kernel/fiasco/src/kern/ux/low_level.h | 86 + kernel/fiasco/src/kern/ux/main-ux.cpp | 70 + kernel/fiasco/src/kern/ux/mem_layout-ux.cpp | 179 + kernel/fiasco/src/kern/ux/mem_space-ux.cpp | 264 + kernel/fiasco/src/kern/ux/mem_unit-ux.cpp | 13 + kernel/fiasco/src/kern/ux/multiboot.h | 259 + kernel/fiasco/src/kern/ux/net.cpp | 75 + kernel/fiasco/src/kern/ux/panic.cpp | 30 + kernel/fiasco/src/kern/ux/pic-ux.cpp | 351 + kernel/fiasco/src/kern/ux/sighandler.S | 34 + kernel/fiasco/src/kern/ux/simpleio.cpp | 30 + kernel/fiasco/src/kern/ux/space-ux.cpp | 6 + kernel/fiasco/src/kern/ux/startup.cpp | 72 + .../src/kern/ux/sys_call_page-abs-ux.cpp | 47 + kernel/fiasco/src/kern/ux/task-ux.cpp | 120 + kernel/fiasco/src/kern/ux/terminate-ux.cpp | 12 + kernel/fiasco/src/kern/ux/thread-ux.cpp | 279 + kernel/fiasco/src/kern/ux/timer-ux.cpp | 64 + kernel/fiasco/src/kern/ux/trampoline.cpp | 70 + kernel/fiasco/src/kern/ux/undef_page.h | 5 + kernel/fiasco/src/kern/ux/usermode.cpp | 763 + kernel/fiasco/src/kern/ux/utcb_init-ux.cpp | 35 + kernel/fiasco/src/kern/ux/vhw.cpp | 110 + kernel/fiasco/src/kern/ux/vmem_alloc-ux.cpp | 24 + kernel/fiasco/src/kern/vcpu.cpp | 39 + kernel/fiasco/src/kern/vkey.cpp | 236 + kernel/fiasco/src/kern/vlog.cpp | 244 + kernel/fiasco/src/kern/vm_factory.cpp | 10 + kernel/fiasco/src/kern/vmem_alloc.cpp | 42 + kernel/fiasco/src/kern/warn.cpp | 21 + kernel/fiasco/src/kern/watchdog.cpp | 53 + kernel/fiasco/src/kernel.amd64.ld | 229 + kernel/fiasco/src/kernel.arm.ld | 251 + kernel/fiasco/src/kernel.ia32.ld | 219 + kernel/fiasco/src/kernel.ppc32.ld | 199 + kernel/fiasco/src/kernel.sparc.ld | 197 + kernel/fiasco/src/kernel.ux.ld | 227 + kernel/fiasco/src/lib/cxxlib/paranoia.cpp | 39 + kernel/fiasco/src/lib/cxxlib/s_cruft.cpp | 20 + kernel/fiasco/src/lib/disasm/COPYING | 340 + kernel/fiasco/src/lib/disasm/bfd/bfd.h | 5405 +++++++ kernel/fiasco/src/lib/disasm/bfd/elf-bfd.h | 2133 +++ kernel/fiasco/src/lib/disasm/bfd/libbfd.c | 28 + kernel/fiasco/src/lib/disasm/bfd/libbfd.h | 7 + kernel/fiasco/src/lib/disasm/disasm.cc | 242 + kernel/fiasco/src/lib/disasm/disasm.h | 16 + kernel/fiasco/src/lib/disasm/elf/arm.h | 287 + kernel/fiasco/src/lib/disasm/elf/common.h | 785 + kernel/fiasco/src/lib/disasm/elf/external.h | 275 + kernel/fiasco/src/lib/disasm/elf/i386.h | 78 + kernel/fiasco/src/lib/disasm/elf/internal.h | 299 + .../fiasco/src/lib/disasm/elf/reloc-macros.h | 101 + kernel/fiasco/src/lib/disasm/elf/x86-64.h | 87 + .../fiasco/src/lib/disasm/include/ansidecl.h | 393 + .../fiasco/src/lib/disasm/include/bfdlink.h | 775 + .../fiasco/src/lib/disasm/include/dis-asm.h | 353 + .../src/lib/disasm/include/floatformat.h | 140 + .../src/lib/disasm/include/opcode/arm.h | 197 + .../src/lib/disasm/include/opcode/ppc.h | 326 + .../src/lib/disasm/include/opcode/sparc.h | 258 + .../src/lib/disasm/include/safe-ctype.h | 119 + kernel/fiasco/src/lib/disasm/include/symcat.h | 49 + .../src/lib/disasm/libiberty/safe-ctype.c | 257 + .../fiasco/src/lib/disasm/opcodes/arm-dis.c | 4243 +++++ .../fiasco/src/lib/disasm/opcodes/dis-buf.c | 104 + .../fiasco/src/lib/disasm/opcodes/dis-init.c | 45 + .../fiasco/src/lib/disasm/opcodes/i386-dis.c | 4565 ++++++ kernel/fiasco/src/lib/disasm/opcodes/opintl.h | 2 + .../fiasco/src/lib/disasm/opcodes/ppc-dis.c | 376 + .../fiasco/src/lib/disasm/opcodes/ppc-opc.c | 4740 ++++++ .../fiasco/src/lib/disasm/opcodes/sparc-dis.c | 1033 ++ .../fiasco/src/lib/disasm/opcodes/sparc-opc.c | 2248 +++ kernel/fiasco/src/lib/disasm/opcodes/sysdep.h | 5 + kernel/fiasco/src/lib/gzip/COPYING | 340 + kernel/fiasco/src/lib/gzip/adler32.c | 48 + kernel/fiasco/src/lib/gzip/crc32.c | 162 + kernel/fiasco/src/lib/gzip/deflate.c | 1350 ++ kernel/fiasco/src/lib/gzip/deflate.h | 318 + kernel/fiasco/src/lib/gzip/gzip.c | 285 + kernel/fiasco/src/lib/gzip/gzip.h | 20 + kernel/fiasco/src/lib/gzip/my_conf.h | 8 + kernel/fiasco/src/lib/gzip/trees.c | 1214 ++ kernel/fiasco/src/lib/gzip/trees.h | 128 + kernel/fiasco/src/lib/gzip/zconf.h | 281 + kernel/fiasco/src/lib/gzip/zlib.h | 893 ++ kernel/fiasco/src/lib/gzip/zutil.c | 228 + kernel/fiasco/src/lib/gzip/zutil.h | 221 + .../src/lib/libk/amd64/atomic-amd64.cpp | 121 + kernel/fiasco/src/lib/libk/amd64/div32.h | 18 + kernel/fiasco/src/lib/libk/amd64/mod32.h | 21 + .../fiasco/src/lib/libk/arm/atomic-arm-up.cpp | 83 + kernel/fiasco/src/lib/libk/arm/div32.h | 14 + kernel/fiasco/src/lib/libk/assert_opt.h | 13 + kernel/fiasco/src/lib/libk/atomic.cpp | 369 + kernel/fiasco/src/lib/libk/auto_ptr.cpp | 110 + kernel/fiasco/src/lib/libk/bitmap.cpp | 166 + kernel/fiasco/src/lib/libk/bits/list_basics.h | 158 + kernel/fiasco/src/lib/libk/cdefs.h | 13 + kernel/fiasco/src/lib/libk/construction.cc | 48 + kernel/fiasco/src/lib/libk/construction.h | 19 + kernel/fiasco/src/lib/libk/dlist | 270 + kernel/fiasco/src/lib/libk/fiasco_defs.h | 12 + kernel/fiasco/src/lib/libk/gcc_lib.c | 54 + kernel/fiasco/src/lib/libk/hlist | 137 + .../src/lib/libk/ia32/atomic-ia32-smp.cpp | 77 + kernel/fiasco/src/lib/libk/ia32/div32.h | 23 + kernel/fiasco/src/lib/libk/ia32/mod32.h | 21 + kernel/fiasco/src/lib/libk/ia32/unistd.cpp | 97 + kernel/fiasco/src/lib/libk/lock_guard.cpp | 184 + kernel/fiasco/src/lib/libk/mem_region.cpp | 166 + kernel/fiasco/src/lib/libk/minmax.h | 14 + kernel/fiasco/src/lib/libk/new | 9 + .../src/lib/libk/ppc32/atomic-ppc32.cpp | 57 + kernel/fiasco/src/lib/libk/ppc32/div32.h | 14 + kernel/fiasco/src/lib/libk/slab_cache.cpp | 440 + .../src/lib/libk/slab_cache_anon-old.cpp | 612 + kernel/fiasco/src/lib/libk/slist | 181 + .../src/lib/libk/sparc/atomic-sparc.cpp | 60 + kernel/fiasco/src/lib/libk/sparc/div32.h | 14 + kernel/fiasco/src/lib/libk/std_macros.cpp | 42 + kernel/fiasco/src/lib/libk/template_math.h | 17 + kernel/fiasco/src/lib/libk/type_traits | 138 + kernel/fiasco/src/lib/libk/unique_ptr.h | 92 + kernel/fiasco/src/lib/libk/ux/div32.h | 23 + kernel/fiasco/src/lib/libk/ux/mod32.h | 21 + .../fiasco/src/lib/minilibc/__assert_fail.c | 12 + kernel/fiasco/src/lib/minilibc/__lltostr.c | 34 + kernel/fiasco/src/lib/minilibc/__ltostr.c | 35 + kernel/fiasco/src/lib/minilibc/__v_printf.c | 281 + kernel/fiasco/src/lib/minilibc/aeabi.c | 20 + .../src/lib/minilibc/amd64/include/limits.h | 62 + .../src/lib/minilibc/amd64/include/setjmp.h | 42 + .../fiasco/src/lib/minilibc/amd64/lltostr.c | 34 + kernel/fiasco/src/lib/minilibc/amd64/setjmp.S | 63 + .../src/lib/minilibc/arm/include/limits.h | 62 + .../src/lib/minilibc/arm/include/setjmp.h | 30 + kernel/fiasco/src/lib/minilibc/arm/setjmp.S | 22 + kernel/fiasco/src/lib/minilibc/atexit.c | 54 + kernel/fiasco/src/lib/minilibc/fprintf.c | 15 + kernel/fiasco/src/lib/minilibc/getchar.c | 12 + kernel/fiasco/src/lib/minilibc/gets.c | 13 + .../src/lib/minilibc/ia32/include/limits.h | 62 + .../src/lib/minilibc/ia32/include/memcpy.h | 24 + .../src/lib/minilibc/ia32/include/setjmp.h | 35 + kernel/fiasco/src/lib/minilibc/ia32/lltostr.c | 34 + kernel/fiasco/src/lib/minilibc/ia32/setjmp.S | 43 + .../fiasco/src/lib/minilibc/include/alloca.h | 13 + .../fiasco/src/lib/minilibc/include/assert.h | 42 + .../fiasco/src/lib/minilibc/include/cassert | 8 + kernel/fiasco/src/lib/minilibc/include/cctype | 27 + .../fiasco/src/lib/minilibc/include/cdefs.h | 13 + .../fiasco/src/lib/minilibc/include/climits | 10 + .../fiasco/src/lib/minilibc/include/csetjmp | 21 + .../fiasco/src/lib/minilibc/include/cstdarg | 21 + .../fiasco/src/lib/minilibc/include/cstddef | 20 + kernel/fiasco/src/lib/minilibc/include/cstdio | 22 + .../fiasco/src/lib/minilibc/include/cstdlib | 48 + .../fiasco/src/lib/minilibc/include/cstring | 73 + .../fiasco/src/lib/minilibc/include/ctype.h | 32 + .../fiasco/src/lib/minilibc/include/errno.h | 8 + .../fiasco/src/lib/minilibc/include/malloc.h | 12 + .../fiasco/src/lib/minilibc/include/memcpy.h | 14 + .../src/lib/minilibc/include/mini_defs.h | 12 + .../fiasco/src/lib/minilibc/include/panic.h | 15 + .../src/lib/minilibc/include/simpleio.h | 14 + .../fiasco/src/lib/minilibc/include/stdio.h | 33 + .../fiasco/src/lib/minilibc/include/stdlib.h | 52 + .../fiasco/src/lib/minilibc/include/string.h | 56 + kernel/fiasco/src/lib/minilibc/isalnum.c | 9 + kernel/fiasco/src/lib/minilibc/isalpha.c | 8 + kernel/fiasco/src/lib/minilibc/isascii.c | 6 + kernel/fiasco/src/lib/minilibc/isblank.c | 6 + kernel/fiasco/src/lib/minilibc/iscntrl.c | 8 + kernel/fiasco/src/lib/minilibc/isdigit.c | 8 + kernel/fiasco/src/lib/minilibc/isgraph.c | 6 + kernel/fiasco/src/lib/minilibc/islower.c | 8 + kernel/fiasco/src/lib/minilibc/isprint.c | 7 + kernel/fiasco/src/lib/minilibc/ispunct.c | 9 + kernel/fiasco/src/lib/minilibc/isspace.c | 9 + kernel/fiasco/src/lib/minilibc/isupper.c | 9 + kernel/fiasco/src/lib/minilibc/isxdigit.c | 8 + kernel/fiasco/src/lib/minilibc/longjmp.c | 1 + kernel/fiasco/src/lib/minilibc/memccpy.c | 20 + kernel/fiasco/src/lib/minilibc/memchr.c | 12 + kernel/fiasco/src/lib/minilibc/memcmp.c | 16 + kernel/fiasco/src/lib/minilibc/memcpy.c | 12 + kernel/fiasco/src/lib/minilibc/memmove.c | 24 + kernel/fiasco/src/lib/minilibc/memset.c | 9 + kernel/fiasco/src/lib/minilibc/panic.c | 29 + .../src/lib/minilibc/ppc32/include/limits.h | 62 + .../src/lib/minilibc/ppc32/include/setjmp.h | 30 + kernel/fiasco/src/lib/minilibc/ppc32/setjmp.S | 34 + kernel/fiasco/src/lib/minilibc/printf.c | 14 + kernel/fiasco/src/lib/minilibc/putchar.c | 11 + kernel/fiasco/src/lib/minilibc/puts.c | 31 + kernel/fiasco/src/lib/minilibc/raise.c | 16 + kernel/fiasco/src/lib/minilibc/snprintf.c | 13 + .../src/lib/minilibc/sparc/include/limits.h | 62 + .../src/lib/minilibc/sparc/include/setjmp.h | 30 + kernel/fiasco/src/lib/minilibc/sparc/setjmp.S | 18 + kernel/fiasco/src/lib/minilibc/sprintf.c | 13 + kernel/fiasco/src/lib/minilibc/strchr.c | 14 + kernel/fiasco/src/lib/minilibc/strcmp.c | 19 + kernel/fiasco/src/lib/minilibc/strcpy.c | 10 + kernel/fiasco/src/lib/minilibc/strcspn.c | 19 + kernel/fiasco/src/lib/minilibc/strlen.c | 10 + kernel/fiasco/src/lib/minilibc/strncmp.c | 15 + kernel/fiasco/src/lib/minilibc/strncpy.c | 11 + kernel/fiasco/src/lib/minilibc/strspn.c | 19 + kernel/fiasco/src/lib/minilibc/strstr.c | 15 + kernel/fiasco/src/lib/minilibc/strtol.c | 29 + kernel/fiasco/src/lib/minilibc/strtoul.c | 40 + kernel/fiasco/src/lib/minilibc/tolower.c | 8 + kernel/fiasco/src/lib/minilibc/vprintf.c | 15 + .../fiasco/src/lib/minilibc/vprintf_backend.h | 21 + kernel/fiasco/src/lib/minilibc/vsnprintf.c | 31 + kernel/fiasco/src/lib/minilibc/vsprintf.c | 9 + kernel/fiasco/src/lib/perfctr/COPYING | 504 + kernel/fiasco/src/lib/perfctr/event_set.h | 92 + kernel/fiasco/src/lib/perfctr/event_set_amd.c | 600 + kernel/fiasco/src/lib/perfctr/event_set_arm.c | 69 + .../src/lib/perfctr/event_set_centaur.c | 108 + kernel/fiasco/src/lib/perfctr/event_set_p4.c | 514 + kernel/fiasco/src/lib/perfctr/event_set_p5.c | 283 + kernel/fiasco/src/lib/perfctr/event_set_p6.c | 486 + kernel/fiasco/src/lib/perfctr/event_set_ppc.c | 523 + kernel/fiasco/src/lib/perfctr/event_set_x86.c | 53 + kernel/fiasco/src/lib/perfctr/libperfctr.h | 75 + kernel/fiasco/src/lib/perfctr/perfctr.c | 88 + kernel/fiasco/src/lib/regex/COPYING | 340 + kernel/fiasco/src/lib/regex/README | 1 + kernel/fiasco/src/lib/regex/alloc.c | 315 + kernel/fiasco/src/lib/regex/regex.h | 83 + kernel/fiasco/src/lib/regex/rx.c | 530 + kernel/fiasco/src/lib/uart/Makefile | 12 + kernel/fiasco/src/lib/uart/io_regblock.h | 96 + kernel/fiasco/src/lib/uart/io_regblock_asi.h | 53 + kernel/fiasco/src/lib/uart/io_regblock_port.h | 50 + kernel/fiasco/src/lib/uart/of1275.h | 109 + kernel/fiasco/src/lib/uart/uart_base.h | 40 + kernel/fiasco/src/lib/uart/uart_dcc-v6.cc | 56 + kernel/fiasco/src/lib/uart/uart_dcc-v6.h | 21 + kernel/fiasco/src/lib/uart/uart_imx.cc | 159 + kernel/fiasco/src/lib/uart/uart_imx.h | 46 + kernel/fiasco/src/lib/uart/uart_leon3.cc | 93 + kernel/fiasco/src/lib/uart/uart_leon3.h | 21 + kernel/fiasco/src/lib/uart/uart_mpc52xx.cc | 147 + kernel/fiasco/src/lib/uart/uart_mpc52xx.h | 68 + kernel/fiasco/src/lib/uart/uart_of.cc | 58 + kernel/fiasco/src/lib/uart/uart_of.h | 30 + kernel/fiasco/src/lib/uart/uart_omap35x.cc | 100 + kernel/fiasco/src/lib/uart/uart_omap35x.h | 22 + kernel/fiasco/src/lib/uart/uart_pl011.cc | 132 + kernel/fiasco/src/lib/uart/uart_pl011.h | 22 + kernel/fiasco/src/lib/uart/uart_s3c2410.cc | 239 + kernel/fiasco/src/lib/uart/uart_s3c2410.h | 78 + kernel/fiasco/src/templates/.gdbinit.ux | 20 + kernel/fiasco/src/templates/Makefile | 40 + .../src/templates/Makefile.builddir.templ | 9 + .../src/templates/globalconfig.out.amd64-1 | 72 + .../src/templates/globalconfig.out.amd64-2 | 72 + .../templates/globalconfig.out.amd64-3-noinl | 72 + .../src/templates/globalconfig.out.amd64-mp | 70 + .../templates/globalconfig.out.arm-a9-mp-1 | 89 + .../templates/globalconfig.out.arm-a9-mp-2 | 89 + .../globalconfig.out.arm-a9-mp-vexpress | 83 + .../src/templates/globalconfig.out.arm-imx21 | 70 + .../src/templates/globalconfig.out.arm-imx35 | 72 + .../src/templates/globalconfig.out.arm-imx51 | 72 + .../src/templates/globalconfig.out.arm-int-1 | 68 + .../src/templates/globalconfig.out.arm-int-2 | 71 + .../templates/globalconfig.out.arm-kirkwood | 66 + .../templates/globalconfig.out.arm-omap3evm | 72 + .../globalconfig.out.arm-omap4-panda | 80 + .../src/templates/globalconfig.out.arm-pxa | 66 + .../src/templates/globalconfig.out.arm-rv-1 | 79 + .../src/templates/globalconfig.out.arm-rv-2 | 82 + .../src/templates/globalconfig.out.arm-rv-3 | 85 + .../templates/globalconfig.out.arm-rv-4-noinl | 79 + .../src/templates/globalconfig.out.arm-s3c | 66 + .../src/templates/globalconfig.out.arm-sa | 66 + .../src/templates/globalconfig.out.arm-t2 | 78 + .../src/templates/globalconfig.out.arm-v6 | 82 + .../templates/globalconfig.out.arm-v6-mp-eb | 89 + .../templates/globalconfig.out.arm-v6-mp-pb | 83 + .../src/templates/globalconfig.out.arm-v7 | 81 + .../src/templates/globalconfig.out.ia32-1 | 81 + .../src/templates/globalconfig.out.ia32-2 | 85 + .../templates/globalconfig.out.ia32-3-noinl | 81 + .../src/templates/globalconfig.out.ia32-big | 86 + .../src/templates/globalconfig.out.ia32-mp | 83 + .../templates/globalconfig.out.ia32-ndebug | 79 + .../src/templates/globalconfig.out.ux-1 | 70 + .../src/templates/globalconfig.out.ux-2 | 73 + .../src/templates/globalconfig.out.ux-3-noinl | 70 + kernel/fiasco/src/test/Makefile | 5 + kernel/fiasco/src/test/Makerules.BOOTTASK | 23 + .../src/test/Makerules.SYSTEM_UNDER_TEST | 26 + kernel/fiasco/src/test/Makerules.TESTTASK | 11 + kernel/fiasco/src/test/Makerules.WRAPPERS | 15 + .../src/test/boottask/bootstrap-boottask.cc | 71 + kernel/fiasco/src/test/boottask/boottask-r.ld | 15 + kernel/fiasco/src/test/map_util/Makefile | 7 + .../fiasco/src/test/map_util/Modules.map_util | 24 + kernel/fiasco/src/test/map_util/map_util.t.cc | 170 + .../src/test/map_util/map_util.t.out.verify | 17 + kernel/fiasco/src/test/mapdb/Makefile | 7 + kernel/fiasco/src/test/mapdb/Modules.mapdb | 20 + kernel/fiasco/src/test/mapdb/mapdb.t.cc | 252 + .../fiasco/src/test/mapdb/mapdb.t.out.verify | 119 + kernel/fiasco/src/test/pingpong/Makefile | 7 + kernel/fiasco/src/test/pingpong/Modules | 85 + .../src/test/pingpong/kernel_thread-test.cpp | 255 + kernel/fiasco/src/test/pingpong/pingpong.c | 14 + kernel/fiasco/src/test/space/Makefile | 7 + kernel/fiasco/src/test/space/Modules.space | 23 + kernel/fiasco/src/test/space/space.t.cc | 136 + .../fiasco/src/test/space/space.t.out.verify | 0 kernel/fiasco/src/test/sysenterexit/Makefile | 7 + kernel/fiasco/src/test/sysenterexit/Modules | 138 + .../src/test/sysenterexit/sysenterexit.c | 24 + kernel/fiasco/src/test/testtask/crt0-user.S | 35 + kernel/fiasco/src/test/trace/Makefile | 10 + kernel/fiasco/src/test/trace/README | 3 + kernel/fiasco/src/test/trace/trace.c | 218 + kernel/fiasco/src/test/unit/map_util_t.cpp | 431 + .../src/test/unit/map_util_t.out.verify.v2 | 1818 +++ kernel/fiasco/src/test/unit/mapdb_t.cpp | 373 + .../fiasco/src/test/unit/mapdb_t.out.verify | 124 + kernel/fiasco/src/test/wrappers/Makefile | 7 + .../fiasco/src/test/wrappers/Modules.wrappers | 39 + .../src/test/wrappers/fake_boot_info.cpp | 14 + .../src/test/wrappers/fake_checksum.cpp | 5 + .../fiasco/src/test/wrappers/fake_globals.cpp | 37 + .../src/test/wrappers/fake_helping_lock.cpp | 32 + .../fiasco/src/test/wrappers/fake_kdb_ke.cpp | 9 + kernel/fiasco/src/test/wrappers/fake_kmem.cpp | 262 + .../src/test/wrappers/fake_kmem_alloc.cpp | 110 + .../fiasco/src/test/wrappers/simple_lock.cpp | 40 + kernel/fiasco/src/test/wrappers/symbols.c | 12 + .../src/test/wrappers/unix_aligned_alloc.cpp | 43 + kernel/fiasco/src/test/wrappers/unix_slab.cpp | 53 + kernel/fiasco/src/types/amd64/types-arch.h | 37 + kernel/fiasco/src/types/arm/asm.h | 9 + kernel/fiasco/src/types/arm/types-arch.h | 37 + kernel/fiasco/src/types/ia32/types-arch.h | 37 + kernel/fiasco/src/types/ppc32/types-arch.h | 37 + kernel/fiasco/src/types/sparc/types-arch.h | 37 + kernel/fiasco/src/types/types.h | 337 + kernel/fiasco/src/types/ux/types-arch.h | 37 + kernel/fiasco/tool/backtrace | 136 + kernel/fiasco/tool/checkinitcalls | 153 + kernel/fiasco/tool/circular | 48 + kernel/fiasco/tool/gen_kconfig | 67 + kernel/fiasco/tool/gendotdeps | 630 + kernel/fiasco/tool/genoffset.py | 230 + kernel/fiasco/tool/kconfig/COPYING | 356 + kernel/fiasco/tool/kconfig/Makefile | 1400 ++ kernel/fiasco/tool/kconfig/README | 3 + .../tool/kconfig/scripts/Kbuild.include | 278 + kernel/fiasco/tool/kconfig/scripts/Makefile | 40 + .../tool/kconfig/scripts/Makefile.build | 467 + .../tool/kconfig/scripts/Makefile.clean | 104 + .../tool/kconfig/scripts/Makefile.headersinst | 117 + .../fiasco/tool/kconfig/scripts/Makefile.host | 170 + .../fiasco/tool/kconfig/scripts/Makefile.lib | 361 + .../tool/kconfig/scripts/Makefile.modinst | 35 + .../tool/kconfig/scripts/Makefile.modpost | 153 + .../tool/kconfig/scripts/basic/Makefile | 15 + .../tool/kconfig/scripts/basic/docproc.c | 583 + .../tool/kconfig/scripts/basic/fixdep.c | 433 + .../fiasco/tool/kconfig/scripts/basic/hash.c | 64 + .../tool/kconfig/scripts/kconfig/.gitignore | 23 + .../tool/kconfig/scripts/kconfig/Makefile | 308 + .../tool/kconfig/scripts/kconfig/POTFILES.in | 12 + .../tool/kconfig/scripts/kconfig/check.sh | 14 + .../tool/kconfig/scripts/kconfig/conf.c | 694 + .../tool/kconfig/scripts/kconfig/confdata.c | 1107 ++ .../tool/kconfig/scripts/kconfig/expr.c | 1168 ++ .../tool/kconfig/scripts/kconfig/expr.h | 225 + .../tool/kconfig/scripts/kconfig/gconf.c | 1542 ++ .../tool/kconfig/scripts/kconfig/gconf.glade | 661 + .../tool/kconfig/scripts/kconfig/images.c | 326 + .../tool/kconfig/scripts/kconfig/kxgettext.c | 235 + .../fiasco/tool/kconfig/scripts/kconfig/lkc.h | 190 + .../tool/kconfig/scripts/kconfig/lkc_proto.h | 54 + .../scripts/kconfig/lxdialog/.gitignore | 4 + .../scripts/kconfig/lxdialog/BIG.FAT.WARNING | 4 + .../kconfig/lxdialog/check-lxdialog.sh | 84 + .../scripts/kconfig/lxdialog/checklist.c | 332 + .../kconfig/scripts/kconfig/lxdialog/dialog.h | 230 + .../scripts/kconfig/lxdialog/inputbox.c | 238 + .../scripts/kconfig/lxdialog/menubox.c | 434 + .../scripts/kconfig/lxdialog/textbox.c | 390 + .../kconfig/scripts/kconfig/lxdialog/util.c | 657 + .../kconfig/scripts/kconfig/lxdialog/yesno.c | 114 + .../tool/kconfig/scripts/kconfig/mconf.c | 882 ++ .../tool/kconfig/scripts/kconfig/menu.c | 607 + .../tool/kconfig/scripts/kconfig/nconf.c | 1546 ++ .../tool/kconfig/scripts/kconfig/nconf.gui.c | 652 + .../tool/kconfig/scripts/kconfig/nconf.h | 96 + .../tool/kconfig/scripts/kconfig/qconf.cc | 1789 +++ .../tool/kconfig/scripts/kconfig/qconf.h | 337 + .../tool/kconfig/scripts/kconfig/symbol.c | 1310 ++ .../tool/kconfig/scripts/kconfig/util.c | 140 + .../tool/kconfig/scripts/kconfig/zconf.gperf | 47 + .../scripts/kconfig/zconf.hash.c_shipped | 286 + .../tool/kconfig/scripts/kconfig/zconf.l | 364 + .../scripts/kconfig/zconf.lex.c_shipped | 2420 +++ .../scripts/kconfig/zconf.tab.c_shipped | 2504 +++ .../tool/kconfig/scripts/kconfig/zconf.y | 740 + kernel/fiasco/tool/kobjdeps | 192 + kernel/fiasco/tool/mksnap | 69 + kernel/fiasco/tool/move-if-change | 19 + kernel/fiasco/tool/parsedeps | 45 + kernel/fiasco/tool/preprocess/COPYING | 339 + kernel/fiasco/tool/preprocess/MAINTAINER | 2 + kernel/fiasco/tool/preprocess/Makefile | 7 + kernel/fiasco/tool/preprocess/README | 38 + kernel/fiasco/tool/preprocess/TODO | 44 + kernel/fiasco/tool/preprocess/doc/Doxyfile | 192 + kernel/fiasco/tool/preprocess/doc/Makefile | 34 + kernel/fiasco/tool/preprocess/doc/manpage.dox | 661 + kernel/fiasco/tool/preprocess/src/Makefile | 25 + kernel/fiasco/tool/preprocess/src/preprocess | 1799 +++ kernel/fiasco/tool/preprocess/test/Makefile | 134 + .../fiasco/tool/preprocess/test/c-preproc.cpp | 19 + kernel/fiasco/tool/preprocess/test/combine.pl | 57 + .../preprocess/test/comment_in_string.cpp | 23 + .../tool/preprocess/test/default_args.cpp | 32 + .../tool/preprocess/test/dropsection-ext.cpp | 22 + .../tool/preprocess/test/dropsection.cpp | 60 + .../fiasco/tool/preprocess/test/explicit.cpp | 11 + .../fiasco/tool/preprocess/test/extern_c.cpp | 8 + kernel/fiasco/tool/preprocess/test/inline.cpp | 74 + .../fiasco/tool/preprocess/test/interface.cpp | 15 + kernel/fiasco/tool/preprocess/test/line.cpp | 20 + .../fiasco/tool/preprocess/test/mapping.cpp | 784 + .../tool/preprocess/test/multifile1.cpp | 24 + .../tool/preprocess/test/multifile2.cpp | 23 + .../fiasco/tool/preprocess/test/noinline.cpp | 8 + .../fiasco/tool/preprocess/test/operator.cpp | 88 + kernel/fiasco/tool/preprocess/test/parser.cpp | 90 + kernel/fiasco/tool/preprocess/test/static.cpp | 25 + .../fiasco/tool/preprocess/test/template.cpp | 236 + .../fiasco/tool/preprocess/test/variable.cpp | 6 + .../tool/preprocess/test/verify/c-preproc.cc | 24 + .../tool/preprocess/test/verify/c-preproc.h | 15 + .../tool/preprocess/test/verify/c-preproc_i.h | 6 + .../test/verify/comment_in_string.cc | 30 + .../test/verify/comment_in_string.h | 17 + .../test/verify/comment_in_string_i.h | 6 + .../preprocess/test/verify/default_args.cc | 13 + .../preprocess/test/verify/default_args.h | 52 + .../preprocess/test/verify/default_args_i.h | 6 + .../preprocess/test/verify/drop_multi1-ext.cc | 5 + .../preprocess/test/verify/drop_multi1.cc | 39 + .../tool/preprocess/test/verify/drop_multi1.h | 43 + .../preprocess/test/verify/drop_multi1_i.h | 6 + .../preprocess/test/verify/drop_multi2-ext.cc | 13 + .../preprocess/test/verify/drop_multi2.cc | 39 + .../tool/preprocess/test/verify/drop_multi2.h | 64 + .../preprocess/test/verify/drop_multi2_i.h | 6 + .../preprocess/test/verify/drop_single1.cc | 30 + .../preprocess/test/verify/drop_single1.h | 43 + .../preprocess/test/verify/drop_single1_i.h | 6 + .../preprocess/test/verify/drop_single2.cc | 31 + .../preprocess/test/verify/drop_single2.h | 39 + .../preprocess/test/verify/drop_single2_i.h | 6 + .../preprocess/test/verify/drop_single3.cc | 39 + .../preprocess/test/verify/drop_single3.h | 43 + .../preprocess/test/verify/drop_single3_i.h | 6 + .../tool/preprocess/test/verify/explicit.cc | 11 + .../tool/preprocess/test/verify/explicit.h | 20 + .../tool/preprocess/test/verify/explicit_i.h | 6 + .../tool/preprocess/test/verify/extern_c.cc | 11 + .../tool/preprocess/test/verify/extern_c.h | 6 + .../tool/preprocess/test/verify/extern_c_i.h | 6 + .../tool/preprocess/test/verify/inline.cc | 33 + .../tool/preprocess/test/verify/inline.h | 125 + .../tool/preprocess/test/verify/inline_i.h | 6 + .../preprocess/test/verify/inline_noinline.cc | 73 + .../preprocess/test/verify/inline_noinline.h | 73 + .../test/verify/inline_noinline_i.h | 18 + .../tool/preprocess/test/verify/interface.cc | 14 + .../tool/preprocess/test/verify/interface_i.h | 6 + .../preprocess/test/verify/interfacepublic.h | 22 + .../tool/preprocess/test/verify/line.cc | 19 + .../fiasco/tool/preprocess/test/verify/line.h | 28 + .../tool/preprocess/test/verify/line_i.h | 6 + .../tool/preprocess/test/verify/line_nh.cc | 19 + .../tool/preprocess/test/verify/line_nh.h | 21 + .../tool/preprocess/test/verify/line_nh_i.h | 6 + .../tool/preprocess/test/verify/line_not.cc | 15 + .../tool/preprocess/test/verify/line_not.h | 21 + .../tool/preprocess/test/verify/line_not_i.h | 6 + .../tool/preprocess/test/verify/mapping.cc | 730 + .../tool/preprocess/test/verify/mapping.h | 155 + .../tool/preprocess/test/verify/mapping_i.h | 95 + .../preprocess/test/verify/mapping_inline.cc | 647 + .../preprocess/test/verify/mapping_inline.h | 231 + .../preprocess/test/verify/mapping_inline_i.h | 112 + .../preprocess/test/verify/multifile-part1.cc | 12 + .../preprocess/test/verify/multifile-part2.cc | 12 + .../tool/preprocess/test/verify/multifile.cc | 12 + .../tool/preprocess/test/verify/multifile.h | 66 + .../tool/preprocess/test/verify/multifile_i.h | 9 + .../tool/preprocess/test/verify/noinline.cc | 5 + .../tool/preprocess/test/verify/noinline.h | 6 + .../tool/preprocess/test/verify/noinline_i.h | 12 + .../tool/preprocess/test/verify/operator.cc | 170 + .../tool/preprocess/test/verify/operator.h | 52 + .../tool/preprocess/test/verify/operator_i.h | 144 + .../tool/preprocess/test/verify/parser.cc | 55 + .../tool/preprocess/test/verify/parser.h | 87 + .../tool/preprocess/test/verify/parser_i.h | 14 + .../preprocess/test/verify/parser_noinline.cc | 75 + .../preprocess/test/verify/parser_noinline.h | 54 + .../test/verify/parser_noinline_i.h | 17 + .../tool/preprocess/test/verify/random.cc | 373 + .../tool/preprocess/test/verify/random.h | 227 + .../tool/preprocess/test/verify/random_i.h | 16 + .../preprocess/test/verify/random_inline.cc | 110 + .../preprocess/test/verify/random_inline.h | 388 + .../preprocess/test/verify/random_inline_i.h | 133 + .../tool/preprocess/test/verify/static.cc | 35 + .../tool/preprocess/test/verify/static.h | 6 + .../tool/preprocess/test/verify/static_i.h | 6 + .../tool/preprocess/test/verify/template.cc | 24 + .../tool/preprocess/test/verify/template.h | 301 + .../tool/preprocess/test/verify/template_i.h | 65 + .../preprocess/test/verify/template_inline.cc | 14 + .../preprocess/test/verify/template_inline.h | 316 + .../test/verify/template_inline_i.h | 65 + .../tool/preprocess/test/verify/variable.cc | 11 + .../tool/preprocess/test/verify/variable.h | 6 + .../tool/preprocess/test/verify/variable_i.h | 6 + kernel/fiasco/tool/showdeps | 148 + kernel/fiasco/tool/split_config | 68 + l4/BENCHMARKING | 13 + l4/COPYING-GPL-2 | 349 + l4/COPYING-LGPL-2.1 | 510 + l4/LICENSING | 10 + l4/Makefile | 688 + l4/conf/Makeconf.boot.example | 91 + l4/conf/examples/arm-rv-lcd.cfg | 69 + l4/conf/examples/arm-rv-lcd.io | 14 + l4/conf/examples/arm-rv-lcd.list | 16 + l4/conf/examples/arm-rv.io | 14 + l4/conf/examples/hello.cfg | 5 + l4/conf/examples/l4lx-gfx.cfg | 60 + l4/conf/examples/l4lx-x86.io | 27 + l4/conf/examples/l4lx.cfg | 15 + l4/conf/examples/x86-fb.cfg | 68 + l4/conf/examples/x86-fb.io | 19 + l4/conf/examples/x86-fb.list | 16 + l4/conf/modules.list | 103 + l4/conf/platforms/README | 1 + l4/doc/Makefile | 9 + l4/doc/source/Makefile | 10 + l4/doc/source/getting_started.dox | 98 + l4/doc/source/header.tex | 45 + l4/doc/source/images/Makefile | 23 + l4/doc/source/images/header-bg.png | Bin 0 -> 715 bytes l4/doc/source/images/io-overview.pdf | Bin 0 -> 41742 bytes l4/doc/source/images/io-overview.png | Bin 0 -> 48195 bytes l4/doc/source/images/l4-caps-basic.pdf | Bin 0 -> 20453 bytes l4/doc/source/images/l4-caps-basic.png | Bin 0 -> 26844 bytes l4/doc/source/images/l4re-basic.pdf | Bin 0 -> 29667 bytes l4/doc/source/images/l4re-basic.png | Bin 0 -> 27273 bytes l4/doc/source/l4re-footer.html | 6 + l4/doc/source/l4re-header.html | 12 + l4/doc/source/l4re.cfg | 1643 ++ l4/doc/source/l4re.dox | 82 + l4/doc/source/overview.dox | 526 + l4/doc/source/pthreads.dox | 58 + l4/doc/source/server_overview.dox | 94 + l4/mk/Kconfig | 454 + l4/mk/Makeconf | 662 + l4/mk/WhatIsThis | 2 + l4/mk/aliases.d/10-stdlibs | 3 + l4/mk/aliases.d/15-libio | 1 + l4/mk/binary.inc | 773 + l4/mk/config.inc | 175 + l4/mk/defconfig/config.amd64 | 39 + l4/mk/defconfig/config.arm-rv | 58 + l4/mk/defconfig/config.ppc32 | 35 + l4/mk/defconfig/config.sparc | 47 + l4/mk/defconfig/config.x86 | 54 + l4/mk/doc.mk | 327 + l4/mk/export_defs.inc | 150 + l4/mk/idl.mk | 202 + l4/mk/include.mk | 94 + l4/mk/install.inc | 66 + l4/mk/lib.mk | 166 + l4/mk/makehelpers.inc | 15 + l4/mk/modes.inc | 140 + l4/mk/pkgdeps | 706 + l4/mk/platforms/beagleboard.conf | 4 + l4/mk/platforms/imx21.conf | 4 + l4/mk/platforms/imx35.conf | 4 + l4/mk/platforms/imx51.conf | 4 + l4/mk/platforms/integrator.conf | 4 + l4/mk/platforms/kirkwood.conf | 4 + l4/mk/platforms/leon3.conf | 3 + l4/mk/platforms/mpc5200.conf | 4 + l4/mk/platforms/omap3_am33xx.conf | 4 + l4/mk/platforms/omap3evm.conf | 4 + l4/mk/platforms/pandaboard.conf | 4 + l4/mk/platforms/pc.conf | 3 + l4/mk/platforms/rv.conf | 4 + l4/mk/platforms/rv_pbx.conf | 4 + l4/mk/platforms/rv_vexpress.conf | 4 + l4/mk/platforms/tegra2.conf | 3 + l4/mk/prog.mk | 204 + l4/mk/ptest | 444 + l4/mk/redo_defconfigs | 22 + l4/mk/rel2abs.sh | 72 + l4/mk/rules.inc | 94 + l4/mk/runux.mk | 194 + l4/mk/subdir.mk | 75 + l4/mk/tmpl/Control | 3 + l4/mk/tmpl/Makefile | 9 + l4/mk/tmpl/examples/Makefile | 10 + l4/mk/tmpl/include/Makefile | 9 + l4/mk/tmpl/inst | 8 + l4/mk/tmpl/lib/Makefile | 9 + l4/mk/tmpl/lib/src/Makefile | 11 + l4/mk/tmpl/ptest/Makefile | 6 + l4/mk/tmpl/ptest/run/Makefile | 10 + l4/mk/tmpl/server/Makefile | 9 + l4/mk/tmpl/server/src/Makefile | 13 + l4/mk/tmpl/server/src/main.c | 5 + l4/pkg/Makefile | 270 + l4/pkg/README | 66 + l4/pkg/bootstrap/Control | 2 + l4/pkg/bootstrap/LEGAL | 43 + l4/pkg/bootstrap/Makefile | 4 + l4/pkg/bootstrap/README | 40 + l4/pkg/bootstrap/server/Makefile | 4 + .../server/src/ARCH-amd64/boot32/boot.S | 63 + .../server/src/ARCH-amd64/boot32/boot_cpu.c | 639 + .../server/src/ARCH-amd64/boot32/boot_cpu.h | 20 + .../server/src/ARCH-amd64/boot32/boot_idt.S | 99 + .../src/ARCH-amd64/boot32/boot_kernel.c | 71 + .../src/ARCH-amd64/boot32/boot_paging.h | 43 + .../src/ARCH-amd64/boot32/bootstrap32.ld | 26 + .../server/src/ARCH-amd64/boot32/load_elf.c | 72 + .../server/src/ARCH-amd64/boot32/load_elf.h | 19 + .../src/ARCH-amd64/boot32/minilibc_support.c | 351 + l4/pkg/bootstrap/server/src/ARCH-amd64/crt0.S | 53 + .../server/src/ARCH-amd64/libc32/Makefile | 17 + .../src/ARCH-amd64/libc32/__assert_fail.c | 17 + .../server/src/ARCH-amd64/libc32/__lltostr.c | 36 + .../server/src/ARCH-amd64/libc32/__ltostr.c | 35 + .../server/src/ARCH-amd64/libc32/__v_printf.c | 232 + .../src/ARCH-amd64/libc32/include/assert.h | 35 + .../src/ARCH-amd64/libc32/include/cdefs.h | 13 + .../src/ARCH-amd64/libc32/include/ctype.h | 32 + .../ARCH-amd64/libc32/include/libc_backend.h | 47 + .../src/ARCH-amd64/libc32/include/memcpy.h | 14 + .../src/ARCH-amd64/libc32/include/panic.h | 12 + .../ARCH-amd64/libc32/include/stdarg-cruft.h | 299 + .../src/ARCH-amd64/libc32/include/stdarg.h | 26 + .../src/ARCH-amd64/libc32/include/stddef.h | 7 + .../src/ARCH-amd64/libc32/include/stdio.h | 37 + .../src/ARCH-amd64/libc32/include/stdlib.h | 52 + .../src/ARCH-amd64/libc32/include/string.h | 56 + .../src/ARCH-amd64/libc32/include/strings.h | 2 + .../server/src/ARCH-amd64/libc32/isspace.c | 9 + .../server/src/ARCH-amd64/libc32/memcpy.c | 13 + .../server/src/ARCH-amd64/libc32/memmove.c | 24 + .../server/src/ARCH-amd64/libc32/memset.c | 10 + .../server/src/ARCH-amd64/libc32/printf.c | 14 + .../server/src/ARCH-amd64/libc32/puts.c | 21 + .../server/src/ARCH-amd64/libc32/strtol.c | 29 + .../server/src/ARCH-amd64/libc32/strtoul.c | 40 + .../server/src/ARCH-amd64/libc32/vprintf.c | 14 + .../src/ARCH-amd64/libc32/vprintf_backend.h | 21 + .../bootstrap/server/src/ARCH-amd64/macros.h | 21 + .../server/src/ARCH-arm/bootstrap.ld.in | 145 + l4/pkg/bootstrap/server/src/ARCH-arm/crt0.S | 200 + l4/pkg/bootstrap/server/src/ARCH-arm/macros.h | 9 + .../bootstrap/server/src/ARCH-arm/reboot.cc | 17 + .../server/src/ARCH-ppc32/bootstrap.ld.in | 108 + l4/pkg/bootstrap/server/src/ARCH-ppc32/crt0.S | 27 + .../server/src/ARCH-ppc32/init_kip_v2-arch.cc | 23 + .../bootstrap/server/src/ARCH-ppc32/macros.h | 9 + .../bootstrap/server/src/ARCH-ppc32/reboot.cc | 17 + .../server/src/ARCH-sparc/bootstrap.ld.in | 81 + l4/pkg/bootstrap/server/src/ARCH-sparc/crt0.S | 168 + .../server/src/ARCH-sparc/leon_ahb.h | 69 + .../bootstrap/server/src/ARCH-sparc/macros.h | 17 + .../bootstrap/server/src/ARCH-sparc/reboot.cc | 17 + .../bootstrap/server/src/ARCH-x86/bootsect.S | 108 + .../server/src/ARCH-x86/bootstrap.ld.in | 79 + l4/pkg/bootstrap/server/src/ARCH-x86/crt0.S | 200 + l4/pkg/bootstrap/server/src/ARCH-x86/macros.h | 17 + .../bootstrap/server/src/ARCH-x86/reboot.cc | 34 + l4/pkg/bootstrap/server/src/ARCH-x86/setup.S | 3039 ++++ l4/pkg/bootstrap/server/src/ARCH-x86/xen.c | 21 + l4/pkg/bootstrap/server/src/Make.rules | 437 + l4/pkg/bootstrap/server/src/Makefile | 6 + l4/pkg/bootstrap/server/src/README | 70 + l4/pkg/bootstrap/server/src/base_critical.c | 34 + l4/pkg/bootstrap/server/src/base_critical.h | 22 + l4/pkg/bootstrap/server/src/build.pl | 229 + l4/pkg/bootstrap/server/src/exec.c | 66 + l4/pkg/bootstrap/server/src/exec.h | 50 + l4/pkg/bootstrap/server/src/gunzip.c | 1262 ++ l4/pkg/bootstrap/server/src/gunzip.h | 36 + l4/pkg/bootstrap/server/src/init_kip-arch.h | 19 + l4/pkg/bootstrap/server/src/init_kip.h | 27 + l4/pkg/bootstrap/server/src/init_kip_v2.cc | 93 + l4/pkg/bootstrap/server/src/init_kip_v4.cc | 134 + l4/pkg/bootstrap/server/src/koptions-def.h | 75 + l4/pkg/bootstrap/server/src/koptions.cc | 136 + l4/pkg/bootstrap/server/src/koptions.h | 6 + l4/pkg/bootstrap/server/src/ldscript.inc | 24 + l4/pkg/bootstrap/server/src/libc_support+.cc | 294 + l4/pkg/bootstrap/server/src/loader_mbi.cc | 38 + l4/pkg/bootstrap/server/src/loader_mbi.h | 17 + l4/pkg/bootstrap/server/src/module.c | 34 + l4/pkg/bootstrap/server/src/module.h | 24 + l4/pkg/bootstrap/server/src/panic.h | 15 + l4/pkg/bootstrap/server/src/patch.cc | 218 + l4/pkg/bootstrap/server/src/patch.h | 23 + l4/pkg/bootstrap/server/src/platform/imx.cc | 48 + .../server/src/platform/integrator.cc | 36 + .../bootstrap/server/src/platform/kirkwood.cc | 45 + l4/pkg/bootstrap/server/src/platform/leon3.cc | 143 + .../bootstrap/server/src/platform/mpc5200.cc | 42 + l4/pkg/bootstrap/server/src/platform/om.cc | 39 + l4/pkg/bootstrap/server/src/platform/omap.cc | 46 + l4/pkg/bootstrap/server/src/platform/pxa.cc | 36 + l4/pkg/bootstrap/server/src/platform/rv.cc | 36 + .../bootstrap/server/src/platform/sa1000.cc | 37 + .../bootstrap/server/src/platform/tegra2.cc | 88 + .../bootstrap/server/src/platform/x86_pc.cc | 676 + l4/pkg/bootstrap/server/src/region.cc | 269 + l4/pkg/bootstrap/server/src/region.h | 194 + l4/pkg/bootstrap/server/src/startup.cc | 1489 ++ l4/pkg/bootstrap/server/src/startup.h | 39 + l4/pkg/bootstrap/server/src/support.h | 80 + l4/pkg/bootstrap/server/src/types.h | 28 + l4/pkg/bootstrap/server/src/uncompress.c | 119 + l4/pkg/bootstrap/server/src/uncompress.h | 21 + l4/pkg/bootstrap/server/src/unpack | 175 + l4/pkg/cxx/Control | 5 + l4/pkg/cxx/LEGAL | 8 + l4/pkg/cxx/Makefile | 8 + l4/pkg/cxx/doc/cxx.dox | 6 + l4/pkg/cxx/doc/files.cfg | 2 + l4/pkg/cxx/lib/Makefile | 12 + l4/pkg/cxx/lib/Makefile.inc | 45 + l4/pkg/cxx/lib/base/Makefile | 5 + l4/pkg/cxx/lib/base/include/Makefile | 5 + l4/pkg/cxx/lib/base/include/exceptions | 307 + l4/pkg/cxx/lib/base/include/std_exc_io | 54 + l4/pkg/cxx/lib/base/include/string | 252 + l4/pkg/cxx/lib/base/src/Makefile | 13 + l4/pkg/cxx/lib/base/src/cxa_pure_delete.cc | 25 + l4/pkg/cxx/lib/base/src/cxa_pure_virtual.cc | 34 + l4/pkg/cxx/lib/base/src/dso_handle.cc | 20 + l4/pkg/cxx/lib/be/Makefile | 5 + l4/pkg/cxx/lib/be/kdebug/Makefile | 12 + l4/pkg/cxx/lib/be/kdebug/iostream.cc | 64 + l4/pkg/cxx/lib/io/Makefile | 8 + l4/pkg/cxx/lib/io/include/Makefile | 6 + l4/pkg/cxx/lib/io/include/basic_ostream | 275 + l4/pkg/cxx/lib/io/include/iostream | 49 + l4/pkg/cxx/lib/io/include/iostream.h | 4 + l4/pkg/cxx/lib/io/include/l4iostream | 49 + l4/pkg/cxx/lib/io/include/l4iostream.h | 4 + l4/pkg/cxx/lib/io/src/Makefile | 12 + l4/pkg/cxx/lib/io/src/iob_write.cc | 101 + l4/pkg/cxx/lib/ipc/Makefile | 6 + l4/pkg/cxx/lib/ipc/include/Makefile | 5 + l4/pkg/cxx/lib/ipc/include/ipc_helper | 64 + l4/pkg/cxx/lib/ipc/include/ipc_server | 348 + l4/pkg/cxx/lib/ipc/include/ipc_stream | 1493 ++ l4/pkg/cxx/lib/start/Makefile | 5 + l4/pkg/cxx/lib/start/include/Makefile | 4 + l4/pkg/cxx/lib/start/src/Makefile | 12 + l4/pkg/cxx/lib/start/src/cxx_atexit.cc | 68 + l4/pkg/cxx/lib/start/src/cxx_atexit.h | 26 + l4/pkg/cxx/lib/supc++-support/Makefile | 5 + l4/pkg/cxx/lib/supc++-support/src/Makefile | 11 + l4/pkg/cxx/lib/supc++-support/src/abort.cc | 31 + l4/pkg/cxx/lib/supc++-support/src/memset.c | 31 + l4/pkg/cxx/lib/tl/Makefile | 5 + l4/pkg/cxx/lib/tl/include/Makefile | 26 + l4/pkg/cxx/lib/tl/include/arith | 42 + l4/pkg/cxx/lib/tl/include/auto_ptr | 113 + l4/pkg/cxx/lib/tl/include/avl_map | 151 + l4/pkg/cxx/lib/tl/include/avl_set | 360 + l4/pkg/cxx/lib/tl/include/avl_tree | 414 + l4/pkg/cxx/lib/tl/include/basic_vector.h | 44 + l4/pkg/cxx/lib/tl/include/bitmap | 223 + l4/pkg/cxx/lib/tl/include/bits/bst.h | 289 + l4/pkg/cxx/lib/tl/include/bits/bst_base.h | 135 + l4/pkg/cxx/lib/tl/include/bits/bst_iter.h | 188 + l4/pkg/cxx/lib/tl/include/bits/list_basics.h | 147 + l4/pkg/cxx/lib/tl/include/bits/type_traits.h | 229 + l4/pkg/cxx/lib/tl/include/dlist | 270 + l4/pkg/cxx/lib/tl/include/hlist | 137 + l4/pkg/cxx/lib/tl/include/list | 424 + l4/pkg/cxx/lib/tl/include/list_alloc | 326 + l4/pkg/cxx/lib/tl/include/minmax | 48 + l4/pkg/cxx/lib/tl/include/observer | 34 + l4/pkg/cxx/lib/tl/include/pair | 104 + l4/pkg/cxx/lib/tl/include/ref_ptr | 201 + l4/pkg/cxx/lib/tl/include/slab_alloc | 432 + l4/pkg/cxx/lib/tl/include/slist | 162 + l4/pkg/cxx/lib/tl/include/static_container | 35 + l4/pkg/cxx/lib/tl/include/std_alloc | 78 + l4/pkg/cxx/lib/tl/include/std_ops | 36 + l4/pkg/cxx/lib/tl/include/type_traits | 129 + l4/pkg/cxx/lib/tl/test/Makefile | 26 + l4/pkg/cxx/lib/tl/test/avl_tree_test.cc | 143 + .../cxx/lib/tl/test/avl_tree_test.reference | 388 + l4/pkg/cxx/lib/util/Makefile | 8 + l4/pkg/cxx/lib/util/include/Makefile | 4 + l4/pkg/cxx/lib/util/include/alloc.h | 55 + l4/pkg/cxx/lib/util/include/atomic.h | 53 + l4/pkg/cxx/lib/util/include/l4types.h | 27 + l4/pkg/cxx/lib/util/include/string.h | 59 + l4/pkg/cxx/lib/util/src/Makefile | 12 + l4/pkg/cxx/lib/util/src/alloc_list.cc | 93 + l4/pkg/cxx/lib/util/src/ipc_error_str.cc | 31 + l4/pkg/drivers-frst/Control | 3 + l4/pkg/drivers-frst/Makefile | 8 + l4/pkg/drivers-frst/hpet/Makefile | 8 + l4/pkg/drivers-frst/hpet/include/Makefile | 7 + l4/pkg/drivers-frst/hpet/include/hpet | 155 + l4/pkg/drivers-frst/hpet/src/Makefile | 10 + l4/pkg/drivers-frst/hpet/src/hpet.cc | 58 + l4/pkg/drivers-frst/include/Makefile | 6 + l4/pkg/drivers-frst/include/io_regblock.h | 204 + .../drivers-frst/include/io_regblock_port.h | 60 + l4/pkg/drivers-frst/nand/Makefile | 8 + l4/pkg/drivers-frst/nand/include/Makefile | 4 + l4/pkg/drivers-frst/nand/include/lib_nand.h | 36 + l4/pkg/drivers-frst/nand/include/transfer.h | 67 + l4/pkg/drivers-frst/nand/src/Makefile | 12 + l4/pkg/drivers-frst/nand/src/common.h | 15 + l4/pkg/drivers-frst/nand/src/gpmc.cc | 124 + l4/pkg/drivers-frst/nand/src/gpmc.h | 60 + l4/pkg/drivers-frst/nand/src/lib_nand.cc | 75 + l4/pkg/drivers-frst/nand/src/mpc5121.cc | 326 + l4/pkg/drivers-frst/nand/src/mpc5121.h | 76 + l4/pkg/drivers-frst/nand/src/nand.cc | 316 + l4/pkg/drivers-frst/nand/src/nand.h | 205 + l4/pkg/drivers-frst/nand/src/nand_ids.cc | 115 + l4/pkg/drivers-frst/nand/src/types.h | 15 + l4/pkg/drivers-frst/of/Makefile | 8 + l4/pkg/drivers-frst/of/include/Makefile | 6 + l4/pkg/drivers-frst/of/include/of.h | 117 + l4/pkg/drivers-frst/of/include/of_dev.h | 24 + l4/pkg/drivers-frst/of/include/of_if.h | 40 + l4/pkg/drivers-frst/of/src/Makefile | 13 + l4/pkg/drivers-frst/of/src/of.cc | 152 + l4/pkg/drivers-frst/uart/Makefile | 5 + l4/pkg/drivers-frst/uart/include/Makefile | 6 + l4/pkg/drivers-frst/uart/include/uart_base.h | 48 + .../drivers-frst/uart/include/uart_dcc-v6.h | 27 + l4/pkg/drivers-frst/uart/include/uart_dummy.h | 29 + l4/pkg/drivers-frst/uart/include/uart_imx.h | 54 + l4/pkg/drivers-frst/uart/include/uart_leon3.h | 30 + l4/pkg/drivers-frst/uart/include/uart_of.h | 38 + .../drivers-frst/uart/include/uart_omap35x.h | 30 + l4/pkg/drivers-frst/uart/include/uart_pl011.h | 30 + l4/pkg/drivers-frst/uart/include/uart_pxa.h | 58 + .../drivers-frst/uart/include/uart_s3c2410.h | 86 + .../drivers-frst/uart/include/uart_sa1000.h | 30 + l4/pkg/drivers-frst/uart/src/Makefile | 19 + l4/pkg/drivers-frst/uart/src/uart_dcc-v6.cc | 62 + l4/pkg/drivers-frst/uart/src/uart_dummy.cc | 33 + l4/pkg/drivers-frst/uart/src/uart_imx.cc | 167 + l4/pkg/drivers-frst/uart/src/uart_leon3.cc | 102 + l4/pkg/drivers-frst/uart/src/uart_of.cc | 66 + l4/pkg/drivers-frst/uart/src/uart_omap35x.cc | 108 + l4/pkg/drivers-frst/uart/src/uart_pl011.cc | 140 + l4/pkg/drivers-frst/uart/src/uart_pxa.cc | 157 + l4/pkg/drivers-frst/uart/src/uart_s3c2410.cc | 247 + l4/pkg/drivers-frst/uart/src/uart_sa1000.cc | 189 + l4/pkg/l4sys/Control | 3 + l4/pkg/l4sys/LEGAL | 11 + l4/pkg/l4sys/Makefile | 6 + l4/pkg/l4sys/README | 10 + l4/pkg/l4sys/doc/files.cfg | 3 + l4/pkg/l4sys/doc/l4sys-l4f-groups.dox | 77 + .../L4API-l4f/__kernel_object_impl.h | 53 + .../ARCH-amd64/L4API-l4f/ipc-l42-gcc3.h | 255 + .../l4sys/include/ARCH-amd64/L4API-l4f/ipc.h | 52 + .../include/ARCH-amd64/L4API-l4f/ktrace.h | 255 + .../include/ARCH-amd64/L4API-l4f/segment.h | 50 + .../include/ARCH-amd64/L4API-l4f/types.h | 35 + l4/pkg/l4sys/include/ARCH-amd64/__vcpu-arch.h | 73 + l4/pkg/l4sys/include/ARCH-amd64/cache.h | 67 + l4/pkg/l4sys/include/ARCH-amd64/consts.h | 45 + l4/pkg/l4sys/include/ARCH-amd64/ipc-invoke.h | 77 + l4/pkg/l4sys/include/ARCH-amd64/kdebug.h | 426 + l4/pkg/l4sys/include/ARCH-amd64/l4int.h | 39 + l4/pkg/l4sys/include/ARCH-amd64/linkage.h | 49 + l4/pkg/l4sys/include/ARCH-amd64/segment.h | 126 + l4/pkg/l4sys/include/ARCH-amd64/utcb.h | 125 + l4/pkg/l4sys/include/ARCH-amd64/vm | 25 + l4/pkg/l4sys/include/ARCH-amd64/vm.h | 28 + .../ARCH-arm/L4API-l4f/__kernel_object_impl.h | 57 + l4/pkg/l4sys/include/ARCH-arm/L4API-l4f/ipc.h | 280 + .../include/ARCH-arm/L4API-l4f/syscall_defs.h | 32 + l4/pkg/l4sys/include/ARCH-arm/__vcpu-arch.h | 51 + l4/pkg/l4sys/include/ARCH-arm/atomic.h | 35 + l4/pkg/l4sys/include/ARCH-arm/cache.h | 145 + l4/pkg/l4sys/include/ARCH-arm/consts.h | 48 + l4/pkg/l4sys/include/ARCH-arm/kdebug.h | 288 + l4/pkg/l4sys/include/ARCH-arm/ktrace.h | 227 + l4/pkg/l4sys/include/ARCH-arm/l4int.h | 38 + l4/pkg/l4sys/include/ARCH-arm/linkage.h | 63 + l4/pkg/l4sys/include/ARCH-arm/mem_op.h | 155 + l4/pkg/l4sys/include/ARCH-arm/rt_sched.h | 27 + l4/pkg/l4sys/include/ARCH-arm/types.h | 80 + l4/pkg/l4sys/include/ARCH-arm/utcb.h | 114 + l4/pkg/l4sys/include/ARCH-arm/vm | 56 + l4/pkg/l4sys/include/ARCH-arm/vm.h | 139 + .../L4API-l4f/__kernel_object_impl.h | 55 + .../l4sys/include/ARCH-ppc32/L4API-l4f/ipc.h | 264 + l4/pkg/l4sys/include/ARCH-ppc32/__vcpu-arch.h | 51 + l4/pkg/l4sys/include/ARCH-ppc32/atomic.h | 27 + l4/pkg/l4sys/include/ARCH-ppc32/cache.h | 67 + l4/pkg/l4sys/include/ARCH-ppc32/consts.h | 45 + l4/pkg/l4sys/include/ARCH-ppc32/kdebug.h | 241 + l4/pkg/l4sys/include/ARCH-ppc32/l4int.h | 37 + l4/pkg/l4sys/include/ARCH-ppc32/linkage.h | 53 + l4/pkg/l4sys/include/ARCH-ppc32/types.h | 35 + l4/pkg/l4sys/include/ARCH-ppc32/utcb.h | 121 + .../L4API-l4f/__kernel_object_impl.h | 41 + .../l4sys/include/ARCH-sparc/L4API-l4f/ipc.h | 141 + .../ARCH-sparc/L4API-l4f/syscall_defs.h | 32 + l4/pkg/l4sys/include/ARCH-sparc/__vcpu-arch.h | 51 + l4/pkg/l4sys/include/ARCH-sparc/atomic.h | 24 + l4/pkg/l4sys/include/ARCH-sparc/cache.h | 67 + l4/pkg/l4sys/include/ARCH-sparc/consts.h | 45 + l4/pkg/l4sys/include/ARCH-sparc/kdebug.h | 215 + l4/pkg/l4sys/include/ARCH-sparc/l4int.h | 38 + l4/pkg/l4sys/include/ARCH-sparc/linkage.h | 49 + l4/pkg/l4sys/include/ARCH-sparc/types.h | 36 + l4/pkg/l4sys/include/ARCH-sparc/utcb.h | 112 + .../ARCH-x86/L4API-l4f/__kernel_object_impl.h | 50 + .../ARCH-x86/L4API-l4f/ipc-l42-gcc3-nopic.h | 268 + l4/pkg/l4sys/include/ARCH-x86/L4API-l4f/ipc.h | 40 + .../include/ARCH-x86/L4API-l4f/segment.h | 44 + .../l4sys/include/ARCH-x86/L4API-l4f/types.h | 34 + l4/pkg/l4sys/include/ARCH-x86/__vcpu-arch.h | 63 + l4/pkg/l4sys/include/ARCH-x86/cache.h | 67 + l4/pkg/l4sys/include/ARCH-x86/consts.h | 45 + l4/pkg/l4sys/include/ARCH-x86/ipc-invoke.h | 88 + l4/pkg/l4sys/include/ARCH-x86/kdebug.h | 426 + l4/pkg/l4sys/include/ARCH-x86/ktrace.h | 257 + l4/pkg/l4sys/include/ARCH-x86/ktrace_events.h | 200 + l4/pkg/l4sys/include/ARCH-x86/l4int.h | 38 + l4/pkg/l4sys/include/ARCH-x86/linkage.h | 49 + l4/pkg/l4sys/include/ARCH-x86/rt_sched-impl.h | 186 + .../l4sys/include/ARCH-x86/rt_sched-proto.h | 316 + l4/pkg/l4sys/include/ARCH-x86/rt_sched.h | 32 + l4/pkg/l4sys/include/ARCH-x86/segment.h | 115 + .../l4sys/include/ARCH-x86/syscall-invoke.h | 65 + l4/pkg/l4sys/include/ARCH-x86/utcb.h | 134 + l4/pkg/l4sys/include/ARCH-x86/vm | 25 + l4/pkg/l4sys/include/ARCH-x86/vm.h | 29 + l4/pkg/l4sys/include/L4API-l4f/ipc-impl.h | 31 + l4/pkg/l4sys/include/Makefile | 11 + l4/pkg/l4sys/include/__kip-32bit.h | 105 + l4/pkg/l4sys/include/__kip-64bit.h | 101 + l4/pkg/l4sys/include/__l4_fpage.h | 533 + l4/pkg/l4sys/include/__timeout.h | 277 + l4/pkg/l4sys/include/__typeinfo.h | 195 + l4/pkg/l4sys/include/__vm | 46 + l4/pkg/l4sys/include/__vm-svm.h | 161 + l4/pkg/l4sys/include/__vm-vmx.h | 84 + l4/pkg/l4sys/include/__vm.h | 27 + l4/pkg/l4sys/include/cache.h | 103 + l4/pkg/l4sys/include/capability | 567 + l4/pkg/l4sys/include/compiler.h | 312 + l4/pkg/l4sys/include/consts.h | 390 + l4/pkg/l4sys/include/debugger | 111 + l4/pkg/l4sys/include/debugger.h | 336 + l4/pkg/l4sys/include/err.h | 70 + l4/pkg/l4sys/include/factory | 270 + l4/pkg/l4sys/include/factory.h | 455 + l4/pkg/l4sys/include/icu | 26 + l4/pkg/l4sys/include/icu.h | 447 + l4/pkg/l4sys/include/ipc.h | 493 + l4/pkg/l4sys/include/ipc_gate | 63 + l4/pkg/l4sys/include/ipc_gate.h | 127 + l4/pkg/l4sys/include/irq | 226 + l4/pkg/l4sys/include/irq.h | 318 + l4/pkg/l4sys/include/kernel_object.h | 88 + l4/pkg/l4sys/include/kip | 189 + l4/pkg/l4sys/include/kip.h | 112 + l4/pkg/l4sys/include/l4int.h | 67 + l4/pkg/l4sys/include/memdesc.h | 233 + l4/pkg/l4sys/include/meta | 117 + l4/pkg/l4sys/include/scheduler | 79 + l4/pkg/l4sys/include/scheduler.h | 307 + l4/pkg/l4sys/include/smart_capability | 178 + l4/pkg/l4sys/include/task | 110 + l4/pkg/l4sys/include/task.h | 355 + l4/pkg/l4sys/include/thread | 275 + l4/pkg/l4sys/include/thread.h | 985 ++ l4/pkg/l4sys/include/typeinfo_svr | 64 + l4/pkg/l4sys/include/types.h | 415 + l4/pkg/l4sys/include/utcb.h | 367 + l4/pkg/l4sys/include/vcon | 88 + l4/pkg/l4sys/include/vcon.h | 327 + l4/pkg/l4sys/include/vcpu.h | 81 + l4/pkg/l4sys/include/vhw.h | 115 + l4/pkg/l4sys/lib/Makefile | 4 + .../lib/src/ARCH-amd64/syscalls_direct.S | 27 + l4/pkg/l4sys/lib/src/ARCH-arm/atomic_ops_s.S | 51 + l4/pkg/l4sys/lib/src/ARCH-ppc32/atomic_ops.c | 73 + l4/pkg/l4sys/lib/src/ARCH-sparc/atomic_ops.S | 7 + .../l4sys/lib/src/ARCH-x86/syscalls_direct.S | 31 + l4/pkg/l4sys/lib/src/ARCH-x86/utcb-l4x.c | 34 + l4/pkg/l4sys/lib/src/Makefile | 45 + l4/pkg/l4sys/lib/src/errtostr.c | 70 + l4/pkg/l4sys/lib/src/kobject.cc | 3 + l4/pkg/l4sys/lib/src/utcb.c | 32 + l4/pkg/l4util/Control | 3 + l4/pkg/l4util/LEGAL | 78 + l4/pkg/l4util/Makefile | 4 + l4/pkg/l4util/README | 19 + l4/pkg/l4util/doc/Makefile | 6 + l4/pkg/l4util/doc/files.cfg | 3 + l4/pkg/l4util/doc/footer.html | 10 + l4/pkg/l4util/doc/header.html | 12 + l4/pkg/l4util/doc/l4util.cfg | 911 ++ l4/pkg/l4util/doc/l4util.dox | 20 + .../include/ARCH-amd64/L4API-l4f/l4_macros.h | 34 + .../include/ARCH-amd64/L4API-l4f/port_io.h | 12 + .../include/ARCH-amd64/L4API-l4f/setjmp.h | 77 + l4/pkg/l4util/include/ARCH-amd64/apic.h | 415 + .../l4util/include/ARCH-amd64/atomic_arch.h | 451 + .../l4util/include/ARCH-amd64/bitops_arch.h | 353 + l4/pkg/l4util/include/ARCH-amd64/cpu.h | 125 + l4/pkg/l4util/include/ARCH-amd64/idt.h | 86 + l4/pkg/l4util/include/ARCH-amd64/irq.h | 81 + l4/pkg/l4util/include/ARCH-amd64/l4_macros.h | 23 + l4/pkg/l4util/include/ARCH-amd64/mbi_argv.h | 33 + l4/pkg/l4util/include/ARCH-amd64/perform.h | 450 + l4/pkg/l4util/include/ARCH-amd64/port_io.h | 12 + l4/pkg/l4util/include/ARCH-amd64/rdtsc.h | 339 + l4/pkg/l4util/include/ARCH-amd64/spin.h | 41 + l4/pkg/l4util/include/ARCH-amd64/stack_impl.h | 32 + l4/pkg/l4util/include/ARCH-amd64/util.h | 89 + .../include/ARCH-arm/L4API-l4f/l4_macros.h | 34 + l4/pkg/l4util/include/ARCH-arm/atomic_arch.h | 95 + l4/pkg/l4util/include/ARCH-arm/bitops_arch.h | 24 + l4/pkg/l4util/include/ARCH-arm/cpu.h | 21 + l4/pkg/l4util/include/ARCH-arm/irq.h | 84 + l4/pkg/l4util/include/ARCH-arm/l4_macros.h | 23 + l4/pkg/l4util/include/ARCH-arm/mbi_argv.h | 13 + l4/pkg/l4util/include/ARCH-arm/stack_impl.h | 31 + .../include/ARCH-ppc32/L4API-l4f/l4_macros.h | 30 + .../l4util/include/ARCH-ppc32/atomic_arch.h | 8 + .../l4util/include/ARCH-ppc32/bitops_arch.h | 8 + l4/pkg/l4util/include/ARCH-ppc32/irq.h | 8 + l4/pkg/l4util/include/ARCH-ppc32/l4_macros.h | 20 + l4/pkg/l4util/include/ARCH-ppc32/rdtsc.h | 163 + l4/pkg/l4util/include/ARCH-ppc32/stack_impl.h | 31 + .../include/ARCH-sparc/L4API-l4f/l4_macros.h | 30 + .../l4util/include/ARCH-sparc/atomic_arch.h | 103 + .../l4util/include/ARCH-sparc/bitops_arch.h | 4 + l4/pkg/l4util/include/ARCH-sparc/irq.h | 47 + l4/pkg/l4util/include/ARCH-sparc/l4_macros.h | 20 + l4/pkg/l4util/include/ARCH-sparc/stack_impl.h | 31 + .../include/ARCH-x86/L4API-l4f/l4_macros.h | 34 + .../include/ARCH-x86/L4API-l4f/port_io.h | 79 + .../include/ARCH-x86/L4API-l4f/setjmp.h | 70 + l4/pkg/l4util/include/ARCH-x86/apic.h | 415 + l4/pkg/l4util/include/ARCH-x86/atomic_arch.h | 363 + l4/pkg/l4util/include/ARCH-x86/bitops_arch.h | 294 + l4/pkg/l4util/include/ARCH-x86/cpu.h | 125 + l4/pkg/l4util/include/ARCH-x86/idt.h | 87 + l4/pkg/l4util/include/ARCH-x86/irq.h | 81 + l4/pkg/l4util/include/ARCH-x86/l4_macros.h | 24 + l4/pkg/l4util/include/ARCH-x86/mbi_argv.h | 33 + l4/pkg/l4util/include/ARCH-x86/perform.h | 452 + l4/pkg/l4util/include/ARCH-x86/port_io.h | 274 + l4/pkg/l4util/include/ARCH-x86/rdtsc.h | 365 + l4/pkg/l4util/include/ARCH-x86/spin.h | 41 + l4/pkg/l4util/include/ARCH-x86/stack_impl.h | 31 + l4/pkg/l4util/include/ARCH-x86/util.h | 90 + l4/pkg/l4util/include/Makefile | 6 + l4/pkg/l4util/include/alloc.h | 38 + l4/pkg/l4util/include/assert.h | 107 + l4/pkg/l4util/include/atomic.h | 559 + l4/pkg/l4util/include/backtrace.h | 28 + l4/pkg/l4util/include/base64.h | 58 + l4/pkg/l4util/include/bitops.h | 445 + l4/pkg/l4util/include/elf.h | 873 + l4/pkg/l4util/include/getopt.h | 107 + l4/pkg/l4util/include/keymap.h | 24 + l4/pkg/l4util/include/kip.h | 78 + l4/pkg/l4util/include/kprintf.h | 29 + l4/pkg/l4util/include/list_alloc.h | 59 + l4/pkg/l4util/include/llulc.h | 47 + l4/pkg/l4util/include/lock.h | 69 + l4/pkg/l4util/include/lock_wq.h | 134 + l4/pkg/l4util/include/macros.h | 130 + l4/pkg/l4util/include/mb_info.h | 301 + l4/pkg/l4util/include/parse_cmd.h | 149 + l4/pkg/l4util/include/prio.h | 59 + l4/pkg/l4util/include/queue.h | 37 + l4/pkg/l4util/include/rand.h | 51 + l4/pkg/l4util/include/reboot.h | 33 + l4/pkg/l4util/include/sll.h | 286 + l4/pkg/l4util/include/slmap.h | 99 + l4/pkg/l4util/include/splitlog2.h | 82 + l4/pkg/l4util/include/stack.h | 54 + l4/pkg/l4util/include/thread.h | 55 + l4/pkg/l4util/include/util.h | 92 + l4/pkg/l4util/lib/Makefile | 4 + l4/pkg/l4util/lib/src/ARCH-amd64/apic.c | 226 + l4/pkg/l4util/lib/src/ARCH-amd64/backtrace.c | 89 + l4/pkg/l4util/lib/src/ARCH-amd64/perform.c | 38 + .../l4util/lib/src/ARCH-amd64/pmc_events.in | 87 + l4/pkg/l4util/lib/src/ARCH-amd64/setjmp.c | 81 + l4/pkg/l4util/lib/src/ARCH-amd64/spin.c | 67 + l4/pkg/l4util/lib/src/ARCH-arm/backtrace.c | 13 + l4/pkg/l4util/lib/src/ARCH-ppc32/backtrace.c | 16 + l4/pkg/l4util/lib/src/ARCH-ppc32/rdtsc.c | 25 + l4/pkg/l4util/lib/src/ARCH-sparc/backtrace.c | 16 + l4/pkg/l4util/lib/src/ARCH-x86/apic.c | 226 + l4/pkg/l4util/lib/src/ARCH-x86/backtrace.c | 118 + l4/pkg/l4util/lib/src/ARCH-x86/perform.c | 40 + l4/pkg/l4util/lib/src/ARCH-x86/pmc_events.in | 87 + l4/pkg/l4util/lib/src/ARCH-x86/rdtsc.c | 145 + l4/pkg/l4util/lib/src/ARCH-x86/setjmp.c | 74 + l4/pkg/l4util/lib/src/ARCH-x86/spin.c | 67 + l4/pkg/l4util/lib/src/Makefile | 31 + l4/pkg/l4util/lib/src/__main.c | 25 + l4/pkg/l4util/lib/src/alloc.c | 94 + l4/pkg/l4util/lib/src/base64.c | 360 + l4/pkg/l4util/lib/src/getopt2.c | 94 + l4/pkg/l4util/lib/src/keymap.c | 31 + l4/pkg/l4util/lib/src/keymap_de.h | 145 + l4/pkg/l4util/lib/src/keymap_en.h | 145 + l4/pkg/l4util/lib/src/kip.c | 58 + l4/pkg/l4util/lib/src/kprintf.c | 41 + l4/pkg/l4util/lib/src/list_alloc.c | 256 + l4/pkg/l4util/lib/src/llulc.cc | 293 + l4/pkg/l4util/lib/src/memdesc.c | 30 + l4/pkg/l4util/lib/src/micros2l4to.c | 54 + l4/pkg/l4util/lib/src/parse_cmdline.c | 344 + l4/pkg/l4util/lib/src/queue.c | 152 + l4/pkg/l4util/lib/src/rand.c | 34 + l4/pkg/l4util/lib/src/reboot.c | 21 + l4/pkg/l4util/lib/src/sleep.c | 59 + l4/pkg/l4util/lib/src/slmap.c | 144 + l4/pkg/l4util/lib/src/thread.c | 50 + l4/pkg/ldscripts/ARCH-amd64/main_dyn.ld | 289 + l4/pkg/ldscripts/ARCH-amd64/main_rel.ld | 212 + l4/pkg/ldscripts/ARCH-amd64/main_stat.ld | 265 + l4/pkg/ldscripts/ARCH-arm/bits/arm_asm.h | 0 l4/pkg/ldscripts/ARCH-arm/main_dyn.ld | 222 + l4/pkg/ldscripts/ARCH-arm/main_rel.ld | 209 + l4/pkg/ldscripts/ARCH-arm/main_stat.ld | 274 + l4/pkg/ldscripts/ARCH-ppc32/main_dyn.ld | 249 + l4/pkg/ldscripts/ARCH-ppc32/main_rel.ld | 225 + l4/pkg/ldscripts/ARCH-ppc32/main_stat.ld | 256 + l4/pkg/ldscripts/ARCH-sparc/bits/wordsize.h | 20 + l4/pkg/ldscripts/ARCH-sparc/main_dyn.ld | 253 + l4/pkg/ldscripts/ARCH-sparc/main_rel.ld | 226 + l4/pkg/ldscripts/ARCH-sparc/main_stat.ld | 273 + l4/pkg/ldscripts/ARCH-x86/main_dyn.ld | 272 + l4/pkg/ldscripts/ARCH-x86/main_rel.ld | 197 + l4/pkg/ldscripts/ARCH-x86/main_stat.ld | 263 + l4/pkg/ldscripts/Control | 3 + l4/pkg/ldscripts/Makefile | 54 + l4/pkg/ldscripts/features.h | 4 + l4/pkg/ldscripts/generic.h | 13 + l4/pkg/ldscripts/kip_addr.c | 14 + l4/pkg/libgcc-pure/Control | 3 + l4/pkg/libgcc-pure/Makefile | 4 + l4/pkg/libgcc-pure/lib/Makefile | 8 + l4/pkg/libgcc/Control | 3 + l4/pkg/libgcc/Makefile | 4 + l4/pkg/libgcc/lib/ARCH-arm/l4-atomic-64bit.c | 170 + l4/pkg/libgcc/lib/ARCH-arm/l4-atomic.c | 313 + l4/pkg/libgcc/lib/Makefile | 15 + l4/pkg/libgcc/lib/Makefile.libgcc | 35 + l4/pkg/libsigma0/Control | 3 + l4/pkg/libsigma0/LEGAL | 8 + l4/pkg/libsigma0/Makefile | 4 + l4/pkg/libsigma0/doc/Makefile | 6 + l4/pkg/libsigma0/doc/files.cfg | 1 + l4/pkg/libsigma0/doc/libsigma0.cfg | 843 + l4/pkg/libsigma0/include/Makefile | 6 + l4/pkg/libsigma0/include/sigma0.h | 226 + l4/pkg/libsigma0/lib/Makefile | 4 + l4/pkg/libsigma0/lib/src/Makefile | 7 + l4/pkg/libsigma0/lib/src/anypage.c | 57 + l4/pkg/libsigma0/lib/src/client.c | 42 + l4/pkg/libsigma0/lib/src/debug.c | 20 + l4/pkg/libsigma0/lib/src/iomem.c | 82 + l4/pkg/libsigma0/lib/src/kip.c | 48 + l4/pkg/libsigma0/lib/src/mem.c | 76 + l4/pkg/libsigma0/lib/src/tbuf.c | 50 + l4/pkg/libvcpu/Control | 3 + l4/pkg/libvcpu/Makefile | 4 + l4/pkg/libvcpu/doc/files.cfg | 1 + l4/pkg/libvcpu/include/ARCH-amd64/vcpu_arch.h | 32 + l4/pkg/libvcpu/include/ARCH-arm/vcpu_arch.h | 32 + l4/pkg/libvcpu/include/ARCH-ppc32/vcpu_arch.h | 36 + l4/pkg/libvcpu/include/ARCH-sparc/vcpu_arch.h | 32 + l4/pkg/libvcpu/include/ARCH-x86/vcpu_arch.h | 32 + l4/pkg/libvcpu/include/Makefile | 7 + l4/pkg/libvcpu/include/vcpu | 271 + l4/pkg/libvcpu/include/vcpu.h | 301 + l4/pkg/libvcpu/lib/Makefile | 4 + l4/pkg/libvcpu/lib/src/ARCH-amd64/arch.cc | 32 + l4/pkg/libvcpu/lib/src/ARCH-arm/arch.cc | 36 + l4/pkg/libvcpu/lib/src/ARCH-ppc32/arch.cc | 28 + l4/pkg/libvcpu/lib/src/ARCH-sparc/arch.cc | 36 + l4/pkg/libvcpu/lib/src/ARCH-x86/arch.cc | 34 + l4/pkg/libvcpu/lib/src/Makefile | 8 + l4/pkg/libvcpu/lib/src/vcpu.cc | 72 + l4/pkg/sigma0/Control | 2 + l4/pkg/sigma0/Makefile | 4 + l4/pkg/sigma0/server/Makefile | 4 + l4/pkg/sigma0/server/src/ARCH-amd64/crt0.S | 34 + l4/pkg/sigma0/server/src/ARCH-arm/crt0.S | 27 + l4/pkg/sigma0/server/src/ARCH-ppc32/crt0.S | 23 + l4/pkg/sigma0/server/src/ARCH-sparc/crt0.S | 26 + l4/pkg/sigma0/server/src/ARCH-x86/crt0.S | 34 + l4/pkg/sigma0/server/src/Makefile | 32 + l4/pkg/sigma0/server/src/globals.h | 40 + l4/pkg/sigma0/server/src/init.cc | 79 + l4/pkg/sigma0/server/src/init.h | 21 + l4/pkg/sigma0/server/src/init_mem.cc | 99 + l4/pkg/sigma0/server/src/init_mem.h | 17 + l4/pkg/sigma0/server/src/io_backend.cc | 76 + l4/pkg/sigma0/server/src/ioports.h | 21 + l4/pkg/sigma0/server/src/ioports_none.cc | 29 + l4/pkg/sigma0/server/src/ioports_x86.cc | 46 + l4/pkg/sigma0/server/src/mem_man.cc | 265 + l4/pkg/sigma0/server/src/mem_man.h | 48 + l4/pkg/sigma0/server/src/mem_man_test.cc | 44 + l4/pkg/sigma0/server/src/mem_man_test.h | 14 + l4/pkg/sigma0/server/src/memmap.cc | 333 + l4/pkg/sigma0/server/src/memmap.h | 37 + l4/pkg/sigma0/server/src/memmap_internal.h | 63 + l4/pkg/sigma0/server/src/page_alloc.cc | 17 + l4/pkg/sigma0/server/src/page_alloc.h | 55 + l4/pkg/sigma0/server/src/region.h | 63 + l4/pkg/sigma0/server/src/support.c | 25 + l4/pkg/uclibc-headers/Control | 3 + l4/pkg/uclibc-headers/Makefile | 55 + l4/pkg/uclibc-minimal/Control | 4 + l4/pkg/uclibc-minimal/Makefile | 6 + l4/pkg/uclibc-minimal/libc/Make.rules | 33 + l4/pkg/uclibc-minimal/libc/Makefile | 9 + l4/pkg/uclibc/Control | 3 + l4/pkg/uclibc/LEGAL | 3 + l4/pkg/uclibc/Makefile | 7 + l4/pkg/uclibc/README.L4 | 8 + l4/pkg/uclibc/doc/Makefile | 6 + l4/pkg/uclibc/doc/general.dox | 55 + l4/pkg/uclibc/doc/uclibc.cfg | 1220 ++ l4/pkg/uclibc/lib/Makefile | 6 + l4/pkg/uclibc/lib/contrib/uclibc/.gitignore | 36 + l4/pkg/uclibc/lib/contrib/uclibc/COPYING.LIB | 504 + .../contrib/uclibc/COPYING.LIB.boilerplate | 1 + l4/pkg/uclibc/lib/contrib/uclibc/Changelog | 804 + .../uclibc/lib/contrib/uclibc/DEDICATION.mjn3 | 22 + l4/pkg/uclibc/lib/contrib/uclibc/INSTALL | 80 + l4/pkg/uclibc/lib/contrib/uclibc/MAINTAINERS | 152 + l4/pkg/uclibc/lib/contrib/uclibc/Makefile | 19 + .../uclibc/lib/contrib/uclibc/Makefile.help | 63 + l4/pkg/uclibc/lib/contrib/uclibc/Makefile.in | 489 + l4/pkg/uclibc/lib/contrib/uclibc/Makerules | 487 + l4/pkg/uclibc/lib/contrib/uclibc/README | 73 + l4/pkg/uclibc/lib/contrib/uclibc/Rules.mak | 740 + l4/pkg/uclibc/lib/contrib/uclibc/TODO | 188 + .../docs/Glibc_vs_uClibc_Differences.txt | 215 + l4/pkg/uclibc/lib/contrib/uclibc/docs/PORTING | 138 + .../lib/contrib/uclibc/docs/defines.txt | 85 + .../lib/contrib/uclibc/docs/man/ldconfig.8 | 73 + .../uclibc/lib/contrib/uclibc/docs/man/ldd.1 | 17 + .../uclibc/docs/probe_math_exception.c | 64 + .../contrib/uclibc/docs/pthreads_hacking.txt | 748 + .../lib/contrib/uclibc/docs/sigaction.txt | 249 + .../lib/contrib/uclibc/docs/threads.txt | 56 + .../contrib/uclibc/docs/uClibc_vs_SuSv3.txt | 105 + .../contrib/uclibc/docs/wchar_and_locale.txt | 113 + .../contrib/uclibc/extra/Configs/Config.alpha | 16 + .../contrib/uclibc/extra/Configs/Config.arm | 133 + .../contrib/uclibc/extra/Configs/Config.avr32 | 28 + .../contrib/uclibc/extra/Configs/Config.bfin | 14 + .../contrib/uclibc/extra/Configs/Config.cris | 34 + .../contrib/uclibc/extra/Configs/Config.e1 | 15 + .../contrib/uclibc/extra/Configs/Config.frv | 15 + .../contrib/uclibc/extra/Configs/Config.h8300 | 28 + .../contrib/uclibc/extra/Configs/Config.hppa | 17 + .../contrib/uclibc/extra/Configs/Config.i386 | 102 + .../contrib/uclibc/extra/Configs/Config.i960 | 15 + .../contrib/uclibc/extra/Configs/Config.ia64 | 15 + .../contrib/uclibc/extra/Configs/Config.in | 2365 +++ .../uclibc/extra/Configs/Config.in.arch | 216 + .../contrib/uclibc/extra/Configs/Config.m68k | 13 + .../uclibc/extra/Configs/Config.microblaze | 14 + .../contrib/uclibc/extra/Configs/Config.mips | 73 + .../contrib/uclibc/extra/Configs/Config.nios | 16 + .../contrib/uclibc/extra/Configs/Config.nios2 | 16 + .../uclibc/extra/Configs/Config.powerpc | 35 + .../contrib/uclibc/extra/Configs/Config.sh | 52 + .../contrib/uclibc/extra/Configs/Config.sh64 | 32 + .../contrib/uclibc/extra/Configs/Config.sparc | 34 + .../contrib/uclibc/extra/Configs/Config.v850 | 15 + .../contrib/uclibc/extra/Configs/Config.vax | 14 + .../uclibc/extra/Configs/Config.x86_64 | 14 + .../uclibc/extra/Configs/Config.xtensa | 8 + .../uclibc/extra/Configs/defconfigs/alpha | 1 + .../uclibc/extra/Configs/defconfigs/arm | 1 + .../uclibc/extra/Configs/defconfigs/avr32 | 1 + .../uclibc/extra/Configs/defconfigs/bfin | 1 + .../uclibc/extra/Configs/defconfigs/cris | 1 + .../uclibc/extra/Configs/defconfigs/e1 | 1 + .../uclibc/extra/Configs/defconfigs/frv | 1 + .../uclibc/extra/Configs/defconfigs/h8300 | 1 + .../uclibc/extra/Configs/defconfigs/hppa | 1 + .../uclibc/extra/Configs/defconfigs/i386 | 1 + .../uclibc/extra/Configs/defconfigs/i960 | 1 + .../uclibc/extra/Configs/defconfigs/ia64 | 1 + .../uclibc/extra/Configs/defconfigs/m68k | 1 + .../extra/Configs/defconfigs/microblaze | 1 + .../uclibc/extra/Configs/defconfigs/mips | 1 + .../uclibc/extra/Configs/defconfigs/nios | 1 + .../uclibc/extra/Configs/defconfigs/nios2 | 1 + .../uclibc/extra/Configs/defconfigs/powerpc | 1 + .../uclibc/extra/Configs/defconfigs/sh | 1 + .../uclibc/extra/Configs/defconfigs/sh64 | 1 + .../uclibc/extra/Configs/defconfigs/sparc | 1 + .../uclibc/extra/Configs/defconfigs/v850 | 1 + .../uclibc/extra/Configs/defconfigs/vax | 1 + .../uclibc/extra/Configs/defconfigs/x86_64 | 1 + .../uclibc/lib/contrib/uclibc/extra/Makefile | 13 + .../lib/contrib/uclibc/extra/Makefile.in | 9 + .../contrib/uclibc/extra/config/.gitignore | 19 + .../lib/contrib/uclibc/extra/config/Makefile | 86 + .../uclibc/extra/config/Makefile.kconfig | 289 + .../contrib/uclibc/extra/config/POTFILES.in | 12 + .../contrib/uclibc/extra/config/README.uClibc | 19 + .../lib/contrib/uclibc/extra/config/check.sh | 14 + .../lib/contrib/uclibc/extra/config/conf.c | 617 + .../contrib/uclibc/extra/config/confdata.c | 912 ++ .../lib/contrib/uclibc/extra/config/expr.c | 1106 ++ .../lib/contrib/uclibc/extra/config/expr.h | 228 + .../lib/contrib/uclibc/extra/config/gconf.c | 1632 ++ .../contrib/uclibc/extra/config/gconf.glade | 648 + .../lib/contrib/uclibc/extra/config/images.c | 326 + .../uclibc/extra/config/kconfig-language.txt | 379 + .../extra/config/kconfig-to-uclibc.patch.gz | Bin 0 -> 5816 bytes .../uclibc/extra/config/kconfig_load.c | 35 + .../contrib/uclibc/extra/config/kxgettext.c | 229 + .../uclibc/extra/config/lex.zconf.c_shipped | 2416 +++ .../lib/contrib/uclibc/extra/config/lkc.h | 168 + .../contrib/uclibc/extra/config/lkc_proto.h | 45 + .../uclibc/extra/config/lxdialog/.gitignore | 4 + .../extra/config/lxdialog/BIG.FAT.WARNING | 4 + .../extra/config/lxdialog/check-lxdialog.sh | 86 + .../uclibc/extra/config/lxdialog/checklist.c | 325 + .../uclibc/extra/config/lxdialog/dialog.h | 230 + .../uclibc/extra/config/lxdialog/inputbox.c | 238 + .../uclibc/extra/config/lxdialog/menubox.c | 434 + .../uclibc/extra/config/lxdialog/textbox.c | 391 + .../uclibc/extra/config/lxdialog/util.c | 655 + .../uclibc/extra/config/lxdialog/yesno.c | 114 + .../lib/contrib/uclibc/extra/config/mconf.c | 930 ++ .../lib/contrib/uclibc/extra/config/menu.c | 453 + .../lib/contrib/uclibc/extra/config/qconf.cc | 1759 +++ .../lib/contrib/uclibc/extra/config/qconf.h | 334 + .../lib/contrib/uclibc/extra/config/symbol.c | 973 ++ .../lib/contrib/uclibc/extra/config/util.c | 133 + .../contrib/uclibc/extra/config/zconf.gperf | 44 + .../uclibc/extra/config/zconf.hash.c_shipped | 237 + .../lib/contrib/uclibc/extra/config/zconf.l | 359 + .../uclibc/extra/config/zconf.tab.c_shipped | 2490 +++ .../lib/contrib/uclibc/extra/config/zconf.y | 706 + .../contrib/uclibc/extra/libstrip/libstrip | 72 + .../contrib/uclibc/extra/locale/.gitignore | 26 + .../lib/contrib/uclibc/extra/locale/LOCALES | 346 + .../lib/contrib/uclibc/extra/locale/Makefile | 13 + .../contrib/uclibc/extra/locale/Makefile.in | 242 + .../lib/contrib/uclibc/extra/locale/README | 71 + .../extra/locale/charmaps/ARMSCII-8.pairs | 254 + .../uclibc/extra/locale/charmaps/ASCII.pairs | 128 + .../uclibc/extra/locale/charmaps/CP1251.pairs | 255 + .../uclibc/extra/locale/charmaps/CP1255.pairs | 233 + .../extra/locale/charmaps/GEORGIAN-PS.pairs | 256 + .../extra/locale/charmaps/ISO-8859-1.pairs | 256 + .../extra/locale/charmaps/ISO-8859-10.pairs | 256 + .../extra/locale/charmaps/ISO-8859-13.pairs | 256 + .../extra/locale/charmaps/ISO-8859-14.pairs | 256 + .../extra/locale/charmaps/ISO-8859-15.pairs | 256 + .../extra/locale/charmaps/ISO-8859-16.pairs | 256 + .../extra/locale/charmaps/ISO-8859-2.pairs | 256 + .../extra/locale/charmaps/ISO-8859-3.pairs | 249 + .../extra/locale/charmaps/ISO-8859-4.pairs | 256 + .../extra/locale/charmaps/ISO-8859-5.pairs | 256 + .../extra/locale/charmaps/ISO-8859-6.pairs | 211 + .../extra/locale/charmaps/ISO-8859-7.pairs | 250 + .../extra/locale/charmaps/ISO-8859-8.pairs | 220 + .../extra/locale/charmaps/ISO-8859-9.pairs | 256 + .../uclibc/extra/locale/charmaps/KOI8-R.pairs | 256 + .../uclibc/extra/locale/charmaps/KOI8-T.pairs | 237 + .../uclibc/extra/locale/charmaps/KOI8-U.pairs | 256 + .../extra/locale/charmaps/TIS-620.pairs | 215 + .../uclibc/extra/locale/collation/af_ZA | 1 + .../uclibc/extra/locale/collation/am_ET | 26 + .../uclibc/extra/locale/collation/ar_AE | 4 + .../uclibc/extra/locale/collation/ar_BH | 4 + .../uclibc/extra/locale/collation/ar_DZ | 4 + .../uclibc/extra/locale/collation/ar_EG | 4 + .../uclibc/extra/locale/collation/ar_IN | 3 + .../uclibc/extra/locale/collation/ar_IQ | 4 + .../uclibc/extra/locale/collation/ar_JO | 4 + .../uclibc/extra/locale/collation/ar_KW | 4 + .../uclibc/extra/locale/collation/ar_LB | 4 + .../uclibc/extra/locale/collation/ar_LY | 4 + .../uclibc/extra/locale/collation/ar_MA | 4 + .../uclibc/extra/locale/collation/ar_OM | 4 + .../uclibc/extra/locale/collation/ar_QA | 4 + .../uclibc/extra/locale/collation/ar_SA | 220 + .../uclibc/extra/locale/collation/ar_SD | 4 + .../uclibc/extra/locale/collation/ar_SY | 4 + .../uclibc/extra/locale/collation/ar_TN | 4 + .../uclibc/extra/locale/collation/ar_YE | 4 + .../uclibc/extra/locale/collation/az_AZ | 137 + .../uclibc/extra/locale/collation/be_BY | 15 + .../uclibc/extra/locale/collation/bg_BG | 106 + .../uclibc/extra/locale/collation/bn_BD | 2 + .../uclibc/extra/locale/collation/bn_IN | 4 + .../uclibc/extra/locale/collation/br_FR | 40 + .../uclibc/extra/locale/collation/bs_BA | 91 + .../uclibc/extra/locale/collation/ca_ES | 2061 +++ .../uclibc/extra/locale/collation/comm | 1872 +++ .../uclibc/extra/locale/collation/cs_CZ | 2162 +++ .../uclibc/extra/locale/collation/cy_GB | 136 + .../uclibc/extra/locale/collation/da_DK | 2075 +++ .../uclibc/extra/locale/collation/de_AT | 2 + .../uclibc/extra/locale/collation/de_BE | 1 + .../uclibc/extra/locale/collation/de_CH | 1 + .../uclibc/extra/locale/collation/de_DE | 4 + .../uclibc/extra/locale/collation/de_LU | 1 + .../uclibc/extra/locale/collation/el_GR | 1 + .../uclibc/extra/locale/collation/en_AU | 1 + .../uclibc/extra/locale/collation/en_BW | 1 + .../uclibc/extra/locale/collation/en_CA | 2061 +++ .../uclibc/extra/locale/collation/en_DK | 1 + .../uclibc/extra/locale/collation/en_GB | 2 + .../uclibc/extra/locale/collation/en_HK | 1 + .../uclibc/extra/locale/collation/en_IE | 1 + .../uclibc/extra/locale/collation/en_IN | 4 + .../uclibc/extra/locale/collation/en_NZ | 1 + .../uclibc/extra/locale/collation/en_PH | 4 + .../uclibc/extra/locale/collation/en_SG | 4 + .../uclibc/extra/locale/collation/en_US | 4 + .../uclibc/extra/locale/collation/en_ZA | 1 + .../uclibc/extra/locale/collation/en_ZW | 1 + .../uclibc/extra/locale/collation/eo_EO | 49 + .../uclibc/extra/locale/collation/es_AR | 1 + .../uclibc/extra/locale/collation/es_BO | 1 + .../uclibc/extra/locale/collation/es_CL | 1 + .../uclibc/extra/locale/collation/es_CO | 1 + .../uclibc/extra/locale/collation/es_CR | 1 + .../uclibc/extra/locale/collation/es_DO | 1 + .../uclibc/extra/locale/collation/es_EC | 1 + .../uclibc/extra/locale/collation/es_ES | 2061 +++ .../uclibc/extra/locale/collation/es_GT | 1 + .../uclibc/extra/locale/collation/es_HN | 1 + .../uclibc/extra/locale/collation/es_MX | 1 + .../uclibc/extra/locale/collation/es_NI | 1 + .../uclibc/extra/locale/collation/es_PA | 1 + .../uclibc/extra/locale/collation/es_PE | 1 + .../uclibc/extra/locale/collation/es_PR | 1 + .../uclibc/extra/locale/collation/es_PY | 1 + .../uclibc/extra/locale/collation/es_SV | 1 + .../uclibc/extra/locale/collation/es_US | 2077 +++ .../uclibc/extra/locale/collation/es_UY | 1 + .../uclibc/extra/locale/collation/es_VE | 1 + .../uclibc/extra/locale/collation/et_EE | 2061 +++ .../uclibc/extra/locale/collation/eu_ES | 1 + .../uclibc/extra/locale/collation/fa_IR | 185 + .../uclibc/extra/locale/collation/fi_FI | 2062 +++ .../uclibc/extra/locale/collation/fo_FO | 1 + .../uclibc/extra/locale/collation/fr_BE | 1 + .../uclibc/extra/locale/collation/fr_CA | 1 + .../uclibc/extra/locale/collation/fr_CH | 1 + .../uclibc/extra/locale/collation/fr_FR | 2 + .../uclibc/extra/locale/collation/fr_LU | 1 + .../uclibc/extra/locale/collation/ga_IE | 1 + .../uclibc/extra/locale/collation/gd_GB | 1 + .../uclibc/extra/locale/collation/gl_ES | 1 + .../uclibc/extra/locale/collation/gv_GB | 1 + .../uclibc/extra/locale/collation/he_IL | 1 + .../uclibc/extra/locale/collation/hi_IN | 4 + .../uclibc/extra/locale/collation/hr_HR | 2085 +++ .../uclibc/extra/locale/collation/hu_HU | 357 + .../uclibc/extra/locale/collation/hy_AM | 91 + .../uclibc/extra/locale/collation/id_ID | 1 + .../uclibc/extra/locale/collation/is_IS | 2104 +++ .../uclibc/extra/locale/collation/iso14651_t1 | 1495 ++ .../uclibc/extra/locale/collation/it_CH | 1 + .../uclibc/extra/locale/collation/it_IT | 1 + .../uclibc/extra/locale/collation/iw_IL | 1 + .../uclibc/extra/locale/collation/ja_JP | 13188 ++++++++++++++++ .../uclibc/extra/locale/collation/ka_GE | 1 + .../uclibc/extra/locale/collation/kl_GL | 1 + .../uclibc/extra/locale/collation/ko_KR | 6010 +++++++ .../uclibc/extra/locale/collation/kw_GB | 1 + .../uclibc/extra/locale/collation/lt_LT | 2061 +++ .../uclibc/extra/locale/collation/lv_LV | 2061 +++ .../uclibc/extra/locale/collation/mi_NZ | 44 + .../uclibc/extra/locale/collation/mk_MK | 1 + .../uclibc/extra/locale/collation/mr_IN | 4 + .../uclibc/extra/locale/collation/ms_MY | 4 + .../uclibc/extra/locale/collation/mt_MT | 80 + .../uclibc/extra/locale/collation/nl_BE | 1 + .../uclibc/extra/locale/collation/nl_NL | 1 + .../uclibc/extra/locale/collation/nn_NO | 4 + .../uclibc/extra/locale/collation/no_NO | 2070 +++ .../uclibc/extra/locale/collation/oc_FR | 1 + .../uclibc/extra/locale/collation/pl_PL | 2061 +++ .../uclibc/extra/locale/collation/pt_BR | 1 + .../uclibc/extra/locale/collation/pt_PT | 1 + .../uclibc/extra/locale/collation/ro_RO | 54 + .../uclibc/extra/locale/collation/ru_RU | 15 + .../uclibc/extra/locale/collation/ru_UA | 15 + .../uclibc/extra/locale/collation/se_NO | 149 + .../uclibc/extra/locale/collation/sk_SK | 1 + .../uclibc/extra/locale/collation/sl_SI | 2061 +++ .../uclibc/extra/locale/collation/sq_AL | 4 + .../uclibc/extra/locale/collation/sr_YU | 90 + .../uclibc/extra/locale/collation/sv_FI | 1 + .../uclibc/extra/locale/collation/sv_SE | 51 + .../uclibc/extra/locale/collation/ta_IN | 4 + .../uclibc/extra/locale/collation/te_IN | 4 + .../uclibc/extra/locale/collation/tg_TJ | 63 + .../uclibc/extra/locale/collation/th_TH | 746 + .../uclibc/extra/locale/collation/ti_ER | 1 + .../uclibc/extra/locale/collation/ti_ET | 1 + .../uclibc/extra/locale/collation/tl_PH | 30 + .../uclibc/extra/locale/collation/tr_TR | 2061 +++ .../uclibc/extra/locale/collation/tt_RU | 162 + .../uclibc/extra/locale/collation/uk_UA | 15 + .../uclibc/extra/locale/collation/ur_PK | 1 + .../uclibc/extra/locale/collation/uz_UZ | 28 + .../uclibc/extra/locale/collation/vi_VN | 4 + .../uclibc/extra/locale/collation/wa_BE | 1 + .../uclibc/extra/locale/collation/yi_US | 43 + .../uclibc/extra/locale/collation/zh_CN | 1 + .../uclibc/extra/locale/collation/zh_HK | 4 + .../uclibc/extra/locale/collation/zh_SG | 4 + .../uclibc/extra/locale/collation/zh_TW | 1 + .../contrib/uclibc/extra/locale/gen_collate.c | 3997 +++++ .../lib/contrib/uclibc/extra/locale/gen_ldc.c | 298 + .../contrib/uclibc/extra/locale/gen_locale.c | 1337 ++ .../contrib/uclibc/extra/locale/gen_mmap.c | 237 + .../contrib/uclibc/extra/locale/gen_wc8bit.c | 732 + .../contrib/uclibc/extra/locale/gen_wctype.c | 814 + .../contrib/uclibc/extra/locale/lmmtolso.c | 72 + .../contrib/uclibc/extra/locale/locale_mmap.h | 91 + .../extra/locale/programs/categories.def | 357 + .../uclibc/extra/locale/programs/locale.c | 486 + .../uclibc/extra/locale/tst_nl_langinfo.c | 296 + .../contrib/uclibc/extra/scripts/.gitignore | 1 + .../lib/contrib/uclibc/extra/scripts/MAKEALL | 143 + .../uclibc/extra/scripts/Makefile.arch.lvl3 | 13 + .../uclibc/extra/scripts/Makefile.arch.lvl4 | 13 + .../uclibc/extra/scripts/Makefile.libs.lvl0 | 13 + .../uclibc/extra/scripts/Makefile.libs.lvl1 | 13 + .../uclibc/extra/scripts/Makefile.libs.lvl2 | 13 + .../uclibc/extra/scripts/Makefile.objs.lvl2 | 13 + .../uclibc/extra/scripts/Makefile.objs.lvl3 | 13 + .../uclibc/extra/scripts/Makefile.objs.lvl4 | 13 + .../uclibc/extra/scripts/Makefile.utils.lvl1 | 13 + .../uclibc/extra/scripts/conf-header.sh | 27 + .../uclibc/extra/scripts/create_makefiles.sh | 71 + .../lib/contrib/uclibc/extra/scripts/defs.awk | 27 + .../contrib/uclibc/extra/scripts/format.lds | 3 + .../uclibc/extra/scripts/gen-as-const.awk | 33 + .../extra/scripts/gen_bits_syscall_h.sh | 46 + .../lib/contrib/uclibc/extra/scripts/getent | 43 + .../uclibc/extra/scripts/install_headers.sh | 76 + .../uclibc/extra/scripts/randconfig.sh | 44 + .../uclibc/extra/scripts/relative_path.sh | 47 + .../contrib/uclibc/extra/scripts/relinfo.pl | 78 + .../contrib/uclibc/extra/scripts/unifdef.c | 1074 ++ .../contrib/uclibc/extra/scripts/unifdef.test | 67 + .../lib/contrib/uclibc/include/.gitignore | 43 + .../lib/contrib/uclibc/include/_lfs_64.h | 29 + .../uclibc/lib/contrib/uclibc/include/a.out.h | 1 + .../lib/contrib/uclibc/include/alloca.h | 74 + l4/pkg/uclibc/lib/contrib/uclibc/include/ar.h | 48 + .../lib/contrib/uclibc/include/arpa/ftp.h | 105 + .../lib/contrib/uclibc/include/arpa/inet.h | 121 + .../lib/contrib/uclibc/include/arpa/nameser.h | 560 + .../uclibc/include/arpa/nameser_compat.h | 183 + .../lib/contrib/uclibc/include/arpa/telnet.h | 316 + .../lib/contrib/uclibc/include/arpa/tftp.h | 76 + .../lib/contrib/uclibc/include/assert.h | 79 + .../lib/contrib/uclibc/include/atomic.h | 537 + .../lib/contrib/uclibc/include/byteswap.h | 40 + .../lib/contrib/uclibc/include/complex.h | 107 + .../uclibc/lib/contrib/uclibc/include/cpio.h | 74 + .../uclibc/lib/contrib/uclibc/include/crypt.h | 42 + .../uclibc/lib/contrib/uclibc/include/ctype.h | 421 + .../lib/contrib/uclibc/include/dirent.h | 371 + .../uclibc/lib/contrib/uclibc/include/dlfcn.h | 201 + .../uclibc/lib/contrib/uclibc/include/elf.h | 3070 ++++ .../lib/contrib/uclibc/include/endian.h | 96 + .../uclibc/lib/contrib/uclibc/include/err.h | 62 + .../uclibc/lib/contrib/uclibc/include/errno.h | 89 + .../uclibc/lib/contrib/uclibc/include/error.h | 52 + .../lib/contrib/uclibc/include/execinfo.h | 44 + .../uclibc/lib/contrib/uclibc/include/fcntl.h | 241 + .../lib/contrib/uclibc/include/features.h | 452 + .../uclibc/lib/contrib/uclibc/include/fenv.h | 136 + .../lib/contrib/uclibc/include/fnmatch.h | 73 + .../uclibc/lib/contrib/uclibc/include/ftw.h | 180 + .../lib/contrib/uclibc/include/getopt.h | 4 + .../uclibc/lib/contrib/uclibc/include/glob.h | 213 + .../lib/contrib/uclibc/include/gnu-versions.h | 53 + .../uclibc/lib/contrib/uclibc/include/grp.h | 215 + .../uclibc/lib/contrib/uclibc/include/iconv.h | 60 + .../lib/contrib/uclibc/include/ieee754.h | 199 + .../lib/contrib/uclibc/include/ifaddrs.h | 74 + .../uclibc/include/internal/parse_config.h | 57 + .../lib/contrib/uclibc/include/inttypes.h | 448 + .../lib/contrib/uclibc/include/langinfo.h | 637 + .../lib/contrib/uclibc/include/lastlog.h | 4 + .../contrib/uclibc/include/libc-internal.h | 80 + .../lib/contrib/uclibc/include/libc-symbols.h | 790 + .../lib/contrib/uclibc/include/libgen.h | 40 + .../lib/contrib/uclibc/include/libintl.h | 133 + .../lib/contrib/uclibc/include/limits.h | 154 + .../uclibc/lib/contrib/uclibc/include/link.h | 240 + .../lib/contrib/uclibc/include/locale.h | 231 + .../lib/contrib/uclibc/include/malloc.h | 201 + .../uclibc/lib/contrib/uclibc/include/math.h | 506 + .../lib/contrib/uclibc/include/memory.h | 34 + .../lib/contrib/uclibc/include/mntent.h | 101 + .../lib/contrib/uclibc/include/mqueue.h | 94 + .../lib/contrib/uclibc/include/net/ethernet.h | 84 + .../lib/contrib/uclibc/include/net/if.h | 208 + .../lib/contrib/uclibc/include/net/if_arp.h | 182 + .../contrib/uclibc/include/net/if_packet.h | 37 + .../lib/contrib/uclibc/include/net/if_ppp.h | 169 + .../contrib/uclibc/include/net/if_shaper.h | 59 + .../lib/contrib/uclibc/include/net/if_slip.h | 25 + .../lib/contrib/uclibc/include/net/ppp-comp.h | 1 + .../lib/contrib/uclibc/include/net/ppp_defs.h | 10 + .../lib/contrib/uclibc/include/net/route.h | 145 + .../lib/contrib/uclibc/include/netax25/ax25.h | 171 + .../uclibc/lib/contrib/uclibc/include/netdb.h | 705 + .../lib/contrib/uclibc/include/neteconet/ec.h | 52 + .../contrib/uclibc/include/netinet/ether.h | 64 + .../contrib/uclibc/include/netinet/icmp6.h | 346 + .../contrib/uclibc/include/netinet/if_ether.h | 105 + .../contrib/uclibc/include/netinet/if_fddi.h | 37 + .../contrib/uclibc/include/netinet/if_tr.h | 111 + .../lib/contrib/uclibc/include/netinet/igmp.h | 126 + .../lib/contrib/uclibc/include/netinet/in.h | 578 + .../contrib/uclibc/include/netinet/in_systm.h | 41 + .../lib/contrib/uclibc/include/netinet/ip.h | 249 + .../lib/contrib/uclibc/include/netinet/ip6.h | 189 + .../contrib/uclibc/include/netinet/ip_icmp.h | 283 + .../lib/contrib/uclibc/include/netinet/tcp.h | 246 + .../lib/contrib/uclibc/include/netinet/udp.h | 79 + .../lib/contrib/uclibc/include/netipx/ipx.h | 113 + .../contrib/uclibc/include/netpacket/packet.h | 64 + .../lib/contrib/uclibc/include/nl_types.h | 61 + .../lib/contrib/uclibc/include/obstack.h | 509 + .../uclibc/lib/contrib/uclibc/include/paths.h | 79 + .../uclibc/lib/contrib/uclibc/include/poll.h | 1 + .../lib/contrib/uclibc/include/printf.h | 237 + .../contrib/uclibc/include/protocols/routed.h | 101 + .../contrib/uclibc/include/protocols/rwhod.h | 67 + .../contrib/uclibc/include/protocols/talkd.h | 113 + .../contrib/uclibc/include/protocols/timed.h | 99 + .../uclibc/lib/contrib/uclibc/include/pty.h | 44 + .../uclibc/lib/contrib/uclibc/include/pwd.h | 190 + .../uclibc/lib/contrib/uclibc/include/regex.h | 567 + .../lib/contrib/uclibc/include/regexp.h | 232 + .../lib/contrib/uclibc/include/resolv.h | 443 + .../lib/contrib/uclibc/include/rpc/auth.h | 232 + .../lib/contrib/uclibc/include/rpc/auth_des.h | 117 + .../contrib/uclibc/include/rpc/auth_unix.h | 91 + .../lib/contrib/uclibc/include/rpc/clnt.h | 433 + .../contrib/uclibc/include/rpc/des_crypt.h | 97 + .../lib/contrib/uclibc/include/rpc/key_prot.h | 346 + .../lib/contrib/uclibc/include/rpc/netdb.h | 79 + .../contrib/uclibc/include/rpc/pmap_clnt.h | 101 + .../contrib/uclibc/include/rpc/pmap_prot.h | 110 + .../lib/contrib/uclibc/include/rpc/pmap_rmt.h | 71 + .../lib/contrib/uclibc/include/rpc/rpc.h | 119 + .../lib/contrib/uclibc/include/rpc/rpc_des.h | 72 + .../lib/contrib/uclibc/include/rpc/rpc_msg.h | 206 + .../lib/contrib/uclibc/include/rpc/svc.h | 330 + .../lib/contrib/uclibc/include/rpc/svc_auth.h | 55 + .../lib/contrib/uclibc/include/rpc/types.h | 108 + .../lib/contrib/uclibc/include/rpc/xdr.h | 407 + .../uclibc/lib/contrib/uclibc/include/sched.h | 92 + .../lib/contrib/uclibc/include/scsi/scsi.h | 226 + .../contrib/uclibc/include/scsi/scsi_ioctl.h | 34 + .../lib/contrib/uclibc/include/scsi/sg.h | 275 + .../lib/contrib/uclibc/include/search.h | 182 + .../lib/contrib/uclibc/include/setjmp.h | 104 + .../uclibc/lib/contrib/uclibc/include/sgtty.h | 41 + .../lib/contrib/uclibc/include/shadow.h | 153 + .../lib/contrib/uclibc/include/signal.h | 440 + .../lib/contrib/uclibc/include/stdint.h | 332 + .../uclibc/lib/contrib/uclibc/include/stdio.h | 938 ++ .../lib/contrib/uclibc/include/stdio_ext.h | 88 + .../lib/contrib/uclibc/include/stdlib.h | 906 ++ .../lib/contrib/uclibc/include/string.h | 492 + .../lib/contrib/uclibc/include/strings.h | 101 + .../lib/contrib/uclibc/include/sys/bitypes.h | 3 + .../lib/contrib/uclibc/include/sys/cdefs.h | 350 + .../lib/contrib/uclibc/include/sys/dir.h | 28 + .../lib/contrib/uclibc/include/sys/errno.h | 1 + .../lib/contrib/uclibc/include/sys/fcntl.h | 1 + .../lib/contrib/uclibc/include/sys/file.h | 56 + .../lib/contrib/uclibc/include/sys/fsuid.h | 36 + .../lib/contrib/uclibc/include/sys/ioctl.h | 47 + .../lib/contrib/uclibc/include/sys/ipc.h | 58 + .../lib/contrib/uclibc/include/sys/kd.h | 35 + .../lib/contrib/uclibc/include/sys/kdaemon.h | 33 + .../lib/contrib/uclibc/include/sys/klog.h | 34 + .../lib/contrib/uclibc/include/sys/mman.h | 180 + .../lib/contrib/uclibc/include/sys/mount.h | 123 + .../lib/contrib/uclibc/include/sys/msg.h | 85 + .../lib/contrib/uclibc/include/sys/mtio.h | 277 + .../lib/contrib/uclibc/include/sys/param.h | 82 + .../contrib/uclibc/include/sys/personality.h | 73 + .../lib/contrib/uclibc/include/sys/poll.h | 76 + .../lib/contrib/uclibc/include/sys/queue.h | 618 + .../lib/contrib/uclibc/include/sys/quota.h | 158 + .../lib/contrib/uclibc/include/sys/reboot.h | 49 + .../lib/contrib/uclibc/include/sys/resource.h | 107 + .../lib/contrib/uclibc/include/sys/select.h | 131 + .../lib/contrib/uclibc/include/sys/sem.h | 69 + .../lib/contrib/uclibc/include/sys/sendfile.h | 52 + .../lib/contrib/uclibc/include/sys/shm.h | 65 + .../lib/contrib/uclibc/include/sys/signal.h | 1 + .../lib/contrib/uclibc/include/sys/signalfd.h | 86 + .../lib/contrib/uclibc/include/sys/socket.h | 254 + .../contrib/uclibc/include/sys/socketvar.h | 3 + .../contrib/uclibc/include/sys/soundcard.h | 1 + .../lib/contrib/uclibc/include/sys/stat.h | 396 + .../lib/contrib/uclibc/include/sys/statfs.h | 70 + .../lib/contrib/uclibc/include/sys/statvfs.h | 93 + .../lib/contrib/uclibc/include/sys/swap.h | 43 + .../lib/contrib/uclibc/include/sys/syscall.h | 38 + .../lib/contrib/uclibc/include/sys/sysctl.h | 72 + .../lib/contrib/uclibc/include/sys/sysinfo.h | 68 + .../lib/contrib/uclibc/include/sys/syslog.h | 216 + .../contrib/uclibc/include/sys/sysmacros.h | 69 + .../lib/contrib/uclibc/include/sys/termios.h | 4 + .../lib/contrib/uclibc/include/sys/time.h | 199 + .../lib/contrib/uclibc/include/sys/timeb.h | 46 + .../lib/contrib/uclibc/include/sys/times.h | 54 + .../lib/contrib/uclibc/include/sys/timex.h | 132 + .../contrib/uclibc/include/sys/ttydefaults.h | 100 + .../lib/contrib/uclibc/include/sys/types.h | 275 + .../lib/contrib/uclibc/include/sys/uio.h | 54 + .../lib/contrib/uclibc/include/sys/un.h | 47 + .../lib/contrib/uclibc/include/sys/unistd.h | 1 + .../lib/contrib/uclibc/include/sys/ustat.h | 38 + .../lib/contrib/uclibc/include/sys/utsname.h | 88 + .../lib/contrib/uclibc/include/sys/vfs.h | 4 + .../lib/contrib/uclibc/include/sys/vt.h | 1 + .../lib/contrib/uclibc/include/sys/wait.h | 188 + .../lib/contrib/uclibc/include/sys/xattr.h | 104 + .../lib/contrib/uclibc/include/syscall.h | 1 + .../lib/contrib/uclibc/include/sysexits.h | 114 + .../lib/contrib/uclibc/include/syslog.h | 1 + .../uclibc/lib/contrib/uclibc/include/tar.h | 108 + .../lib/contrib/uclibc/include/termio.h | 6 + .../lib/contrib/uclibc/include/termios.h | 114 + .../lib/contrib/uclibc/include/tgmath.h | 432 + .../uclibc/lib/contrib/uclibc/include/time.h | 451 + .../uclibc/lib/contrib/uclibc/include/tls.h | 20 + .../lib/contrib/uclibc/include/ttyent.h | 68 + .../lib/contrib/uclibc/include/ucontext.h | 32 + .../lib/contrib/uclibc/include/ulimit.h | 48 + .../lib/contrib/uclibc/include/unistd.h | 1186 ++ .../uclibc/lib/contrib/uclibc/include/ustat.h | 1 + .../uclibc/lib/contrib/uclibc/include/utime.h | 53 + .../uclibc/lib/contrib/uclibc/include/utmp.h | 106 + .../uclibc/lib/contrib/uclibc/include/utmpx.h | 127 + .../lib/contrib/uclibc/include/values.h | 73 + .../uclibc/lib/contrib/uclibc/include/wait.h | 1 + .../lib/contrib/uclibc/include/wchar-stub.h | 14 + .../uclibc/lib/contrib/uclibc/include/wchar.h | 795 + .../lib/contrib/uclibc/include/wctype.h | 345 + .../lib/contrib/uclibc/include/wordexp.h | 72 + .../lib/contrib/uclibc/include/xlocale.h | 62 + .../uclibc/lib/contrib/uclibc/ldso/COPYRIGHT | 49 + .../uclibc/lib/contrib/uclibc/ldso/Makefile | 13 + .../lib/contrib/uclibc/ldso/Makefile.in | 9 + l4/pkg/uclibc/lib/contrib/uclibc/ldso/README | 841 + .../lib/contrib/uclibc/ldso/include/dl-defs.h | 254 + .../lib/contrib/uclibc/ldso/include/dl-elf.h | 222 + .../lib/contrib/uclibc/ldso/include/dl-hash.h | 173 + .../contrib/uclibc/ldso/include/dl-string.h | 365 + .../contrib/uclibc/ldso/include/dl-syscall.h | 163 + .../lib/contrib/uclibc/ldso/include/dlfcn.h | 28 + .../lib/contrib/uclibc/ldso/include/ldso.h | 159 + .../contrib/uclibc/ldso/include/ldsodefs.h | 147 + .../contrib/uclibc/ldso/include/unsecvars.h | 32 + .../lib/contrib/uclibc/ldso/ldso/Makefile | 13 + .../lib/contrib/uclibc/ldso/ldso/Makefile.in | 75 + .../uclibc/ldso/ldso/arm/aeabi_read_tp.S | 63 + .../contrib/uclibc/ldso/ldso/arm/dl-debug.h | 46 + .../contrib/uclibc/ldso/ldso/arm/dl-startup.h | 194 + .../uclibc/ldso/ldso/arm/dl-syscalls.h | 42 + .../contrib/uclibc/ldso/ldso/arm/dl-sysdep.h | 155 + .../contrib/uclibc/ldso/ldso/arm/elfinterp.c | 354 + .../contrib/uclibc/ldso/ldso/arm/resolve.S | 173 + .../uclibc/ldso/ldso/arm/thumb_atomics.S | 79 + .../contrib/uclibc/ldso/ldso/avr32/dl-debug.h | 45 + .../uclibc/ldso/ldso/avr32/dl-startup.h | 103 + .../uclibc/ldso/ldso/avr32/dl-syscalls.h | 6 + .../uclibc/ldso/ldso/avr32/dl-sysdep.h | 103 + .../uclibc/ldso/ldso/avr32/elfinterp.c | 194 + .../contrib/uclibc/ldso/ldso/avr32/resolve.S | 28 + .../contrib/uclibc/ldso/ldso/bfin/dl-debug.h | 54 + .../uclibc/ldso/ldso/bfin/dl-inlines.h | 593 + .../uclibc/ldso/ldso/bfin/dl-startup.h | 142 + .../uclibc/ldso/ldso/bfin/dl-syscalls.h | 208 + .../contrib/uclibc/ldso/ldso/bfin/dl-sysdep.h | 234 + .../contrib/uclibc/ldso/ldso/bfin/elfinterp.c | 349 + .../contrib/uclibc/ldso/ldso/bfin/resolve.S | 77 + .../contrib/uclibc/ldso/ldso/c6x/dl-debug.h | 49 + .../contrib/uclibc/ldso/ldso/c6x/dl-inlines.h | 91 + .../contrib/uclibc/ldso/ldso/c6x/dl-startup.h | 122 + .../uclibc/ldso/ldso/c6x/dl-syscalls.h | 25 + .../contrib/uclibc/ldso/ldso/c6x/dl-sysdep.h | 209 + .../contrib/uclibc/ldso/ldso/c6x/elfinterp.c | 296 + .../contrib/uclibc/ldso/ldso/c6x/resolve.S | 68 + .../contrib/uclibc/ldso/ldso/cris/dl-debug.h | 42 + .../uclibc/ldso/ldso/cris/dl-startup.h | 81 + .../uclibc/ldso/ldso/cris/dl-syscalls.h | 6 + .../contrib/uclibc/ldso/ldso/cris/dl-sysdep.h | 109 + .../contrib/uclibc/ldso/ldso/cris/elfinterp.c | 289 + .../contrib/uclibc/ldso/ldso/cris/resolve.S | 89 + .../lib/contrib/uclibc/ldso/ldso/dl-array.c | 84 + .../lib/contrib/uclibc/ldso/ldso/dl-debug.c | 106 + .../lib/contrib/uclibc/ldso/ldso/dl-elf.c | 1074 ++ .../lib/contrib/uclibc/ldso/ldso/dl-hash.c | 380 + .../lib/contrib/uclibc/ldso/ldso/dl-startup.c | 392 + .../lib/contrib/uclibc/ldso/ldso/dl-symbols.c | 21 + .../lib/contrib/uclibc/ldso/ldso/dl-tls.c | 1043 ++ .../contrib/uclibc/ldso/ldso/frv/dl-debug.h | 29 + .../contrib/uclibc/ldso/ldso/frv/dl-inlines.h | 456 + .../contrib/uclibc/ldso/ldso/frv/dl-startup.h | 133 + .../uclibc/ldso/ldso/frv/dl-syscalls.h | 175 + .../contrib/uclibc/ldso/ldso/frv/dl-sysdep.h | 188 + .../contrib/uclibc/ldso/ldso/frv/elfinterp.c | 347 + .../contrib/uclibc/ldso/ldso/frv/resolve.S | 57 + .../contrib/uclibc/ldso/ldso/i386/dl-debug.h | 36 + .../uclibc/ldso/ldso/i386/dl-startup.h | 65 + .../uclibc/ldso/ldso/i386/dl-syscalls.h | 6 + .../contrib/uclibc/ldso/ldso/i386/dl-sysdep.h | 78 + .../contrib/uclibc/ldso/ldso/i386/elfinterp.c | 324 + .../contrib/uclibc/ldso/ldso/i386/resolve.S | 51 + .../lib/contrib/uclibc/ldso/ldso/ldso.c | 1146 ++ .../contrib/uclibc/ldso/ldso/m68k/dl-debug.h | 42 + .../uclibc/ldso/ldso/m68k/dl-startup.h | 97 + .../uclibc/ldso/ldso/m68k/dl-syscalls.h | 6 + .../contrib/uclibc/ldso/ldso/m68k/dl-sysdep.h | 82 + .../contrib/uclibc/ldso/ldso/m68k/elfinterp.c | 319 + .../contrib/uclibc/ldso/ldso/m68k/resolve.S | 28 + .../lib/contrib/uclibc/ldso/ldso/mips/README | 52 + .../contrib/uclibc/ldso/ldso/mips/dl-debug.h | 45 + .../uclibc/ldso/ldso/mips/dl-startup.h | 190 + .../uclibc/ldso/ldso/mips/dl-syscalls.h | 6 + .../contrib/uclibc/ldso/ldso/mips/dl-sysdep.h | 242 + .../contrib/uclibc/ldso/ldso/mips/elfinterp.c | 390 + .../contrib/uclibc/ldso/ldso/mips/resolve.S | 165 + .../uclibc/ldso/ldso/powerpc/dl-debug.h | 44 + .../uclibc/ldso/ldso/powerpc/dl-startup.h | 89 + .../uclibc/ldso/ldso/powerpc/dl-syscalls.h | 6 + .../uclibc/ldso/ldso/powerpc/dl-sysdep.h | 184 + .../uclibc/ldso/ldso/powerpc/elfinterp.c | 448 + .../uclibc/ldso/ldso/powerpc/resolve.S | 57 + .../contrib/uclibc/ldso/ldso/sh/dl-debug.h | 43 + .../contrib/uclibc/ldso/ldso/sh/dl-startup.h | 68 + .../contrib/uclibc/ldso/ldso/sh/dl-syscalls.h | 14 + .../contrib/uclibc/ldso/ldso/sh/dl-sysdep.h | 171 + .../contrib/uclibc/ldso/ldso/sh/elfinterp.c | 303 + .../lib/contrib/uclibc/ldso/ldso/sh/resolve.S | 98 + .../contrib/uclibc/ldso/ldso/sh64/dl-debug.h | 79 + .../uclibc/ldso/ldso/sh64/dl-startup.h | 117 + .../uclibc/ldso/ldso/sh64/dl-syscalls.h | 25 + .../contrib/uclibc/ldso/ldso/sh64/dl-sysdep.h | 168 + .../contrib/uclibc/ldso/ldso/sh64/elfinterp.c | 341 + .../contrib/uclibc/ldso/ldso/sh64/resolve.S | 95 + .../contrib/uclibc/ldso/ldso/sparc/dl-debug.h | 40 + .../uclibc/ldso/ldso/sparc/dl-startup.h | 78 + .../uclibc/ldso/ldso/sparc/dl-syscalls.h | 6 + .../uclibc/ldso/ldso/sparc/dl-sysdep.h | 164 + .../uclibc/ldso/ldso/sparc/elfinterp.c | 371 + .../contrib/uclibc/ldso/ldso/sparc/resolve.S | 22 + .../uclibc/ldso/ldso/x86_64/dl-debug.h | 39 + .../uclibc/ldso/ldso/x86_64/dl-startup.h | 69 + .../uclibc/ldso/ldso/x86_64/dl-syscalls.h | 6 + .../uclibc/ldso/ldso/x86_64/dl-sysdep.h | 112 + .../uclibc/ldso/ldso/x86_64/elfinterp.c | 339 + .../contrib/uclibc/ldso/ldso/x86_64/resolve.S | 62 + .../uclibc/ldso/ldso/xtensa/dl-debug.h | 61 + .../uclibc/ldso/ldso/xtensa/dl-startup.h | 106 + .../uclibc/ldso/ldso/xtensa/dl-syscalls.h | 7 + .../uclibc/ldso/ldso/xtensa/dl-sysdep.h | 130 + .../uclibc/ldso/ldso/xtensa/elfinterp.c | 278 + .../contrib/uclibc/ldso/ldso/xtensa/resolve.S | 57 + .../lib/contrib/uclibc/ldso/libdl/Makefile | 13 + .../lib/contrib/uclibc/ldso/libdl/Makefile.in | 60 + .../lib/contrib/uclibc/ldso/libdl/libdl.c | 1130 ++ .../lib/contrib/uclibc/ldso/man/Makefile | 22 + .../lib/contrib/uclibc/ldso/man/dlopen.3 | 218 + .../lib/contrib/uclibc/ldso/man/ld.so.8 | 113 + .../lib/contrib/uclibc/ldso/man/ld.so.texi | 411 + .../lib/contrib/uclibc/ldso/man/ldconfig.8 | 189 + .../uclibc/lib/contrib/uclibc/ldso/man/ldd.1 | 59 + .../uclibc/lib/contrib/uclibc/libc/Makefile | 13 + .../lib/contrib/uclibc/libc/Makefile.in | 103 + .../lib/contrib/uclibc/libc/inet/.indent.pro | 33 + .../lib/contrib/uclibc/libc/inet/Makefile | 13 + .../lib/contrib/uclibc/libc/inet/Makefile.in | 63 + .../lib/contrib/uclibc/libc/inet/_res_state.c | 8 + .../lib/contrib/uclibc/libc/inet/accept.c | 8 + .../lib/contrib/uclibc/libc/inet/addr.c | 210 + .../lib/contrib/uclibc/libc/inet/bind.c | 8 + .../uclibc/libc/inet/closenameservers.c | 8 + .../lib/contrib/uclibc/libc/inet/connect.c | 8 + .../lib/contrib/uclibc/libc/inet/decodea.c | 8 + .../lib/contrib/uclibc/libc/inet/decoded.c | 8 + .../lib/contrib/uclibc/libc/inet/decodeh.c | 8 + .../lib/contrib/uclibc/libc/inet/decodep.c | 8 + .../lib/contrib/uclibc/libc/inet/decodeq.c | 8 + .../lib/contrib/uclibc/libc/inet/dnslookup.c | 8 + .../lib/contrib/uclibc/libc/inet/encodea.c | 8 + .../lib/contrib/uclibc/libc/inet/encoded.c | 8 + .../lib/contrib/uclibc/libc/inet/encodeh.c | 8 + .../lib/contrib/uclibc/libc/inet/encodep.c | 8 + .../lib/contrib/uclibc/libc/inet/encodeq.c | 8 + .../lib/contrib/uclibc/libc/inet/ether_addr.c | 100 + .../lib/contrib/uclibc/libc/inet/ethers.c | 122 + .../lib/contrib/uclibc/libc/inet/formquery.c | 8 + .../contrib/uclibc/libc/inet/gai_strerror.c | 61 + .../uclibc/libc/inet/get_hosts_byaddr_r.c | 8 + .../uclibc/libc/inet/get_hosts_byname_r.c | 8 + .../contrib/uclibc/libc/inet/getaddrinfo.c | 878 + .../contrib/uclibc/libc/inet/gethostbyaddr.c | 8 + .../uclibc/libc/inet/gethostbyaddr_r.c | 8 + .../contrib/uclibc/libc/inet/gethostbyname.c | 8 + .../contrib/uclibc/libc/inet/gethostbyname2.c | 8 + .../uclibc/libc/inet/gethostbyname2_r.c | 8 + .../uclibc/libc/inet/gethostbyname_r.c | 8 + .../lib/contrib/uclibc/libc/inet/gethostent.c | 8 + .../contrib/uclibc/libc/inet/gethostent_r.c | 8 + .../contrib/uclibc/libc/inet/getnameinfo.c | 8 + .../lib/contrib/uclibc/libc/inet/getnet.c | 208 + .../contrib/uclibc/libc/inet/getpeername.c | 8 + .../lib/contrib/uclibc/libc/inet/getproto.c | 182 + .../lib/contrib/uclibc/libc/inet/getservice.c | 190 + .../contrib/uclibc/libc/inet/getsockname.c | 8 + .../lib/contrib/uclibc/libc/inet/getsockopt.c | 8 + .../lib/contrib/uclibc/libc/inet/herror.c | 65 + .../lib/contrib/uclibc/libc/inet/hostid.c | 80 + .../lib/contrib/uclibc/libc/inet/if_index.c | 337 + .../lib/contrib/uclibc/libc/inet/ifaddrs.c | 848 + .../lib/contrib/uclibc/libc/inet/in6_addr.c | 32 + .../lib/contrib/uclibc/libc/inet/inet_addr.c | 8 + .../lib/contrib/uclibc/libc/inet/inet_aton.c | 8 + .../lib/contrib/uclibc/libc/inet/inet_lnaof.c | 8 + .../contrib/uclibc/libc/inet/inet_makeaddr.c | 8 + .../lib/contrib/uclibc/libc/inet/inet_net.c | 99 + .../lib/contrib/uclibc/libc/inet/inet_netof.c | 8 + .../lib/contrib/uclibc/libc/inet/inet_ntoa.c | 8 + .../lib/contrib/uclibc/libc/inet/lengthd.c | 8 + .../lib/contrib/uclibc/libc/inet/lengthq.c | 8 + .../lib/contrib/uclibc/libc/inet/listen.c | 8 + .../contrib/uclibc/libc/inet/netlinkaccess.h | 69 + .../lib/contrib/uclibc/libc/inet/ns_name.c | 8 + .../lib/contrib/uclibc/libc/inet/ntohl.c | 66 + .../lib/contrib/uclibc/libc/inet/ntop.c | 396 + .../uclibc/libc/inet/opennameservers.c | 8 + .../lib/contrib/uclibc/libc/inet/opensock.c | 43 + .../uclibc/libc/inet/read_etc_hosts_r.c | 8 + .../lib/contrib/uclibc/libc/inet/recv.c | 8 + .../lib/contrib/uclibc/libc/inet/recvfrom.c | 8 + .../lib/contrib/uclibc/libc/inet/recvmsg.c | 8 + .../lib/contrib/uclibc/libc/inet/res_comp.c | 8 + .../lib/contrib/uclibc/libc/inet/res_init.c | 8 + .../lib/contrib/uclibc/libc/inet/res_query.c | 8 + .../lib/contrib/uclibc/libc/inet/resolv.c | 3332 ++++ .../contrib/uclibc/libc/inet/rpc/.indent.pro | 33 + .../lib/contrib/uclibc/libc/inet/rpc/Makefile | 13 + .../contrib/uclibc/libc/inet/rpc/Makefile.in | 47 + .../contrib/uclibc/libc/inet/rpc/auth_none.c | 137 + .../contrib/uclibc/libc/inet/rpc/auth_unix.c | 336 + .../uclibc/libc/inet/rpc/authunix_prot.c | 67 + .../uclibc/libc/inet/rpc/bindresvport.c | 90 + .../uclibc/libc/inet/rpc/clnt_generic.c | 179 + .../uclibc/libc/inet/rpc/clnt_perror.c | 435 + .../contrib/uclibc/libc/inet/rpc/clnt_raw.c | 248 + .../uclibc/libc/inet/rpc/clnt_simple.c | 164 + .../contrib/uclibc/libc/inet/rpc/clnt_tcp.c | 531 + .../contrib/uclibc/libc/inet/rpc/clnt_udp.c | 608 + .../contrib/uclibc/libc/inet/rpc/clnt_unix.c | 600 + .../contrib/uclibc/libc/inet/rpc/create_xid.c | 58 + .../contrib/uclibc/libc/inet/rpc/errqueue.h | 46 + .../uclibc/libc/inet/rpc/get_myaddress.c | 109 + .../contrib/uclibc/libc/inet/rpc/getrpcent.c | 347 + .../contrib/uclibc/libc/inet/rpc/getrpcport.c | 78 + .../contrib/uclibc/libc/inet/rpc/pm_getmaps.c | 84 + .../contrib/uclibc/libc/inet/rpc/pm_getport.c | 94 + .../contrib/uclibc/libc/inet/rpc/pmap_clnt.c | 176 + .../contrib/uclibc/libc/inet/rpc/pmap_prot.c | 56 + .../contrib/uclibc/libc/inet/rpc/pmap_prot2.c | 117 + .../contrib/uclibc/libc/inet/rpc/pmap_rmt.c | 412 + .../lib/contrib/uclibc/libc/inet/rpc/rcmd.c | 689 + .../lib/contrib/uclibc/libc/inet/rpc/rexec.c | 192 + .../contrib/uclibc/libc/inet/rpc/rpc_cmsg.c | 208 + .../uclibc/libc/inet/rpc/rpc_commondata.c | 47 + .../uclibc/libc/inet/rpc/rpc_dtablesize.c | 56 + .../uclibc/libc/inet/rpc/rpc_private.h | 55 + .../contrib/uclibc/libc/inet/rpc/rpc_prot.c | 285 + .../contrib/uclibc/libc/inet/rpc/rpc_thread.c | 166 + .../lib/contrib/uclibc/libc/inet/rpc/rtime.c | 153 + .../contrib/uclibc/libc/inet/rpc/ruserpass.c | 325 + .../lib/contrib/uclibc/libc/inet/rpc/sa_len.c | 63 + .../lib/contrib/uclibc/libc/inet/rpc/svc.c | 505 + .../contrib/uclibc/libc/inet/rpc/svc_auth.c | 124 + .../contrib/uclibc/libc/inet/rpc/svc_authux.c | 159 + .../contrib/uclibc/libc/inet/rpc/svc_raw.c | 166 + .../contrib/uclibc/libc/inet/rpc/svc_run.c | 90 + .../contrib/uclibc/libc/inet/rpc/svc_simple.c | 197 + .../contrib/uclibc/libc/inet/rpc/svc_tcp.c | 428 + .../contrib/uclibc/libc/inet/rpc/svc_udp.c | 596 + .../contrib/uclibc/libc/inet/rpc/svc_unix.c | 536 + .../lib/contrib/uclibc/libc/inet/rpc/xdr.c | 745 + .../contrib/uclibc/libc/inet/rpc/xdr_array.c | 171 + .../contrib/uclibc/libc/inet/rpc/xdr_float.c | 306 + .../uclibc/libc/inet/rpc/xdr_intXX_t.c | 203 + .../contrib/uclibc/libc/inet/rpc/xdr_mem.c | 237 + .../contrib/uclibc/libc/inet/rpc/xdr_rec.c | 646 + .../uclibc/libc/inet/rpc/xdr_reference.c | 147 + .../contrib/uclibc/libc/inet/rpc/xdr_stdio.c | 195 + .../lib/contrib/uclibc/libc/inet/send.c | 8 + .../lib/contrib/uclibc/libc/inet/sendmsg.c | 8 + .../lib/contrib/uclibc/libc/inet/sendto.c | 8 + .../lib/contrib/uclibc/libc/inet/setsockopt.c | 8 + .../lib/contrib/uclibc/libc/inet/shutdown.c | 8 + .../lib/contrib/uclibc/libc/inet/socket.c | 8 + .../contrib/uclibc/libc/inet/socketcalls.c | 562 + .../lib/contrib/uclibc/libc/inet/socketpair.c | 8 + .../lib/contrib/uclibc/libc/misc/Makefile | 13 + .../lib/contrib/uclibc/libc/misc/Makefile.in | 35 + .../uclibc/libc/misc/assert/.indent.pro | 33 + .../contrib/uclibc/libc/misc/assert/Makefile | 13 + .../uclibc/libc/misc/assert/Makefile.in | 23 + .../uclibc/libc/misc/assert/__assert.c | 66 + .../uclibc/libc/misc/ctype/.indent.pro | 33 + .../contrib/uclibc/libc/misc/ctype/Makefile | 13 + .../uclibc/libc/misc/ctype/Makefile.in | 42 + .../uclibc/libc/misc/ctype/__C_ctype_b.c | 8 + .../libc/misc/ctype/__C_ctype_tolower.c | 8 + .../libc/misc/ctype/__C_ctype_toupper.c | 8 + .../uclibc/libc/misc/ctype/__ctype_assert.c | 8 + .../uclibc/libc/misc/ctype/__ctype_b_loc.c | 8 + .../libc/misc/ctype/__ctype_tolower_loc.c | 8 + .../libc/misc/ctype/__ctype_toupper_loc.c | 8 + .../contrib/uclibc/libc/misc/ctype/ctype.c | 1088 ++ .../contrib/uclibc/libc/misc/ctype/isalnum.c | 8 + .../uclibc/libc/misc/ctype/isalnum_l.c | 9 + .../contrib/uclibc/libc/misc/ctype/isalpha.c | 8 + .../uclibc/libc/misc/ctype/isalpha_l.c | 9 + .../contrib/uclibc/libc/misc/ctype/isascii.c | 8 + .../uclibc/libc/misc/ctype/isascii_l.c | 9 + .../contrib/uclibc/libc/misc/ctype/isblank.c | 8 + .../uclibc/libc/misc/ctype/isblank_l.c | 9 + .../contrib/uclibc/libc/misc/ctype/iscntrl.c | 8 + .../uclibc/libc/misc/ctype/iscntrl_l.c | 9 + .../contrib/uclibc/libc/misc/ctype/isctype.c | 8 + .../contrib/uclibc/libc/misc/ctype/isdigit.c | 8 + .../uclibc/libc/misc/ctype/isdigit_l.c | 9 + .../contrib/uclibc/libc/misc/ctype/isgraph.c | 8 + .../uclibc/libc/misc/ctype/isgraph_l.c | 9 + .../contrib/uclibc/libc/misc/ctype/islower.c | 8 + .../uclibc/libc/misc/ctype/islower_l.c | 9 + .../contrib/uclibc/libc/misc/ctype/isprint.c | 8 + .../uclibc/libc/misc/ctype/isprint_l.c | 9 + .../contrib/uclibc/libc/misc/ctype/ispunct.c | 8 + .../uclibc/libc/misc/ctype/ispunct_l.c | 9 + .../contrib/uclibc/libc/misc/ctype/isspace.c | 8 + .../uclibc/libc/misc/ctype/isspace_l.c | 9 + .../contrib/uclibc/libc/misc/ctype/isupper.c | 8 + .../uclibc/libc/misc/ctype/isupper_l.c | 9 + .../contrib/uclibc/libc/misc/ctype/isxdigit.c | 8 + .../uclibc/libc/misc/ctype/isxdigit_l.c | 9 + .../contrib/uclibc/libc/misc/ctype/toascii.c | 8 + .../uclibc/libc/misc/ctype/toascii_l.c | 9 + .../contrib/uclibc/libc/misc/ctype/tolower.c | 8 + .../uclibc/libc/misc/ctype/tolower_l.c | 9 + .../contrib/uclibc/libc/misc/ctype/toupper.c | 8 + .../uclibc/libc/misc/ctype/toupper_l.c | 9 + .../contrib/uclibc/libc/misc/dirent/Makefile | 13 + .../uclibc/libc/misc/dirent/Makefile.in | 28 + .../uclibc/libc/misc/dirent/alphasort.c | 15 + .../uclibc/libc/misc/dirent/alphasort64.c | 16 + .../uclibc/libc/misc/dirent/closedir.c | 37 + .../contrib/uclibc/libc/misc/dirent/dirfd.c | 21 + .../uclibc/libc/misc/dirent/dirstream.h | 74 + .../contrib/uclibc/libc/misc/dirent/opendir.c | 117 + .../contrib/uclibc/libc/misc/dirent/readdir.c | 56 + .../uclibc/libc/misc/dirent/readdir64.c | 56 + .../uclibc/libc/misc/dirent/readdir64_r.c | 66 + .../uclibc/libc/misc/dirent/readdir_r.c | 64 + .../uclibc/libc/misc/dirent/rewinddir.c | 24 + .../contrib/uclibc/libc/misc/dirent/scandir.c | 94 + .../uclibc/libc/misc/dirent/scandir64.c | 111 + .../contrib/uclibc/libc/misc/dirent/seekdir.c | 23 + .../contrib/uclibc/libc/misc/dirent/telldir.c | 22 + .../uclibc/libc/misc/dirent/versionsort.c | 14 + .../uclibc/libc/misc/dirent/versionsort64.c | 16 + .../lib/contrib/uclibc/libc/misc/elf/Makefile | 12 + .../contrib/uclibc/libc/misc/elf/Makefile.in | 22 + .../contrib/uclibc/libc/misc/elf/dl-core.c | 20 + .../uclibc/libc/misc/elf/dl-iterate-phdr.c | 83 + .../contrib/uclibc/libc/misc/elf/dl-support.c | 71 + .../contrib/uclibc/libc/misc/error/Makefile | 13 + .../uclibc/libc/misc/error/Makefile.in | 29 + .../lib/contrib/uclibc/libc/misc/error/err.c | 120 + .../contrib/uclibc/libc/misc/error/error.c | 106 + .../contrib/uclibc/libc/misc/file/Makefile | 13 + .../contrib/uclibc/libc/misc/file/Makefile.in | 26 + .../lib/contrib/uclibc/libc/misc/file/lockf.c | 75 + .../contrib/uclibc/libc/misc/file/lockf64.c | 93 + .../uclibc/libc/misc/fnmatch/.indent.pro | 33 + .../contrib/uclibc/libc/misc/fnmatch/Makefile | 13 + .../uclibc/libc/misc/fnmatch/Makefile.in | 27 + .../uclibc/libc/misc/fnmatch/fnmatch.c | 440 + .../uclibc/libc/misc/fnmatch/fnmatch_loop.c | 1205 ++ .../uclibc/libc/misc/fnmatch/fnmatch_old.c | 220 + .../lib/contrib/uclibc/libc/misc/ftw/Makefile | 13 + .../contrib/uclibc/libc/misc/ftw/Makefile.in | 26 + .../lib/contrib/uclibc/libc/misc/ftw/ftw.c | 807 + .../lib/contrib/uclibc/libc/misc/ftw/ftw64.c | 32 + .../contrib/uclibc/libc/misc/glob/.indent.pro | 33 + .../contrib/uclibc/libc/misc/glob/Makefile | 13 + .../contrib/uclibc/libc/misc/glob/Makefile.in | 33 + .../uclibc/libc/misc/glob/glob-susv3.c | 299 + .../lib/contrib/uclibc/libc/misc/glob/glob.c | 1067 ++ .../uclibc/libc/misc/glob/glob64-susv3.c | 20 + .../contrib/uclibc/libc/misc/glob/glob64.c | 15 + .../lib/contrib/uclibc/libc/misc/gnu/Makefile | 13 + .../contrib/uclibc/libc/misc/gnu/Makefile.in | 23 + .../contrib/uclibc/libc/misc/gnu/obstack.c | 456 + .../uclibc/libc/misc/internals/Makefile | 13 + .../uclibc/libc/misc/internals/Makefile.in | 43 + .../libc/misc/internals/__errno_location.c | 20 + .../libc/misc/internals/__h_errno_location.c | 13 + .../libc/misc/internals/__uClibc_main.c | 533 + .../uclibc/libc/misc/internals/errno.c | 21 + .../libc/misc/internals/internal_errno.h | 21 + .../uclibc/libc/misc/internals/parse_config.c | 277 + .../misc/internals/shared_flat_add_library.c | 46 + .../misc/internals/shared_flat_initfini.c | 53 + .../libc/misc/internals/shared_flat_lib.h | 35 + .../uclibc/libc/misc/internals/tempname.c | 249 + .../uclibc/libc/misc/internals/tempname.h | 21 + .../contrib/uclibc/libc/misc/locale/Makefile | 13 + .../uclibc/libc/misc/locale/Makefile.in | 30 + .../uclibc/libc/misc/locale/__curlocale.c | 9 + .../libc/misc/locale/__locale_mbrtowc_l.c | 8 + .../uclibc/libc/misc/locale/_locale_init.c | 8 + .../uclibc/libc/misc/locale/duplocale.c | 9 + .../uclibc/libc/misc/locale/freelocale.c | 9 + .../contrib/uclibc/libc/misc/locale/locale.c | 1474 ++ .../uclibc/libc/misc/locale/localeconv.c | 8 + .../uclibc/libc/misc/locale/newlocale.c | 8 + .../uclibc/libc/misc/locale/nl_langinfo.c | 8 + .../uclibc/libc/misc/locale/nl_langinfo_l.c | 9 + .../uclibc/libc/misc/locale/setlocale.c | 8 + .../uclibc/libc/misc/locale/uselocale.c | 9 + .../uclibc/libc/misc/mntent/.indent.pro | 33 + .../contrib/uclibc/libc/misc/mntent/Makefile | 13 + .../uclibc/libc/misc/mntent/Makefile.in | 23 + .../contrib/uclibc/libc/misc/mntent/mntent.c | 112 + .../contrib/uclibc/libc/misc/pthread/Makefile | 13 + .../uclibc/libc/misc/pthread/Makefile.in | 18 + .../contrib/uclibc/libc/misc/pthread/tsd.c | 10 + .../uclibc/libc/misc/regex/.indent.pro | 33 + .../contrib/uclibc/libc/misc/regex/Makefile | 13 + .../uclibc/libc/misc/regex/Makefile.in | 27 + .../contrib/uclibc/libc/misc/regex/regcomp.c | 3783 +++++ .../contrib/uclibc/libc/misc/regex/regex.c | 58 + .../uclibc/libc/misc/regex/regex_internal.c | 1642 ++ .../uclibc/libc/misc/regex/regex_internal.h | 708 + .../uclibc/libc/misc/regex/regex_old.c | 8269 ++++++++++ .../contrib/uclibc/libc/misc/regex/regexec.c | 4247 +++++ .../contrib/uclibc/libc/misc/search/Makefile | 13 + .../uclibc/libc/misc/search/Makefile.in | 35 + .../uclibc/libc/misc/search/_hsearch_r.c | 226 + .../uclibc/libc/misc/search/_lsearch.c | 49 + .../uclibc/libc/misc/search/_tsearch.c | 220 + .../uclibc/libc/misc/search/hcreate_r.c | 8 + .../uclibc/libc/misc/search/hdestroy_r.c | 8 + .../contrib/uclibc/libc/misc/search/hsearch.c | 52 + .../uclibc/libc/misc/search/hsearch_r.c | 8 + .../contrib/uclibc/libc/misc/search/insque.c | 8 + .../uclibc/libc/misc/search/insremque.c | 54 + .../contrib/uclibc/libc/misc/search/lfind.c | 8 + .../contrib/uclibc/libc/misc/search/lsearch.c | 8 + .../contrib/uclibc/libc/misc/search/remque.c | 8 + .../contrib/uclibc/libc/misc/search/tdelete.c | 8 + .../uclibc/libc/misc/search/tdestroy.c | 8 + .../contrib/uclibc/libc/misc/search/tfind.c | 8 + .../contrib/uclibc/libc/misc/search/tsearch.c | 8 + .../contrib/uclibc/libc/misc/search/twalk.c | 8 + .../contrib/uclibc/libc/misc/statfs/Makefile | 13 + .../uclibc/libc/misc/statfs/Makefile.in | 31 + .../uclibc/libc/misc/statfs/fstatfs64.c | 51 + .../uclibc/libc/misc/statfs/fstatvfs.c | 60 + .../uclibc/libc/misc/statfs/fstatvfs64.c | 68 + .../libc/misc/statfs/internal_statvfs.c | 111 + .../uclibc/libc/misc/statfs/statfs64.c | 49 + .../contrib/uclibc/libc/misc/statfs/statvfs.c | 48 + .../uclibc/libc/misc/statfs/statvfs64.c | 68 + .../contrib/uclibc/libc/misc/syslog/Makefile | 13 + .../uclibc/libc/misc/syslog/Makefile.in | 25 + .../contrib/uclibc/libc/misc/syslog/syslog.c | 343 + .../uclibc/libc/misc/sysvipc/.indent.pro | 33 + .../contrib/uclibc/libc/misc/sysvipc/Makefile | 13 + .../uclibc/libc/misc/sysvipc/Makefile.in | 32 + .../uclibc/libc/misc/sysvipc/__syscall_ipc.c | 17 + .../contrib/uclibc/libc/misc/sysvipc/ftok.c | 36 + .../contrib/uclibc/libc/misc/sysvipc/ipc.h | 35 + .../contrib/uclibc/libc/misc/sysvipc/msgctl.c | 8 + .../contrib/uclibc/libc/misc/sysvipc/msgget.c | 8 + .../contrib/uclibc/libc/misc/sysvipc/msgq.c | 112 + .../contrib/uclibc/libc/misc/sysvipc/msgrcv.c | 8 + .../contrib/uclibc/libc/misc/sysvipc/msgsnd.c | 8 + .../contrib/uclibc/libc/misc/sysvipc/sem.c | 105 + .../contrib/uclibc/libc/misc/sysvipc/semctl.c | 8 + .../contrib/uclibc/libc/misc/sysvipc/semget.c | 8 + .../contrib/uclibc/libc/misc/sysvipc/semop.c | 8 + .../uclibc/libc/misc/sysvipc/semtimedop.c | 8 + .../contrib/uclibc/libc/misc/sysvipc/shm.c | 95 + .../contrib/uclibc/libc/misc/sysvipc/shmat.c | 8 + .../contrib/uclibc/libc/misc/sysvipc/shmctl.c | 8 + .../contrib/uclibc/libc/misc/sysvipc/shmdt.c | 8 + .../contrib/uclibc/libc/misc/sysvipc/shmget.c | 8 + .../contrib/uclibc/libc/misc/time/.indent.pro | 33 + .../contrib/uclibc/libc/misc/time/Makefile | 13 + .../contrib/uclibc/libc/misc/time/Makefile.in | 43 + .../contrib/uclibc/libc/misc/time/__time_tm.c | 8 + .../libc/misc/time/_time_localtime_tzi.c | 8 + .../uclibc/libc/misc/time/_time_mktime.c | 8 + .../uclibc/libc/misc/time/_time_mktime_tzi.c | 8 + .../uclibc/libc/misc/time/_time_t2tm.c | 8 + .../contrib/uclibc/libc/misc/time/adjtime.c | 58 + .../contrib/uclibc/libc/misc/time/asctime.c | 8 + .../contrib/uclibc/libc/misc/time/asctime_r.c | 8 + .../lib/contrib/uclibc/libc/misc/time/clock.c | 8 + .../lib/contrib/uclibc/libc/misc/time/ctime.c | 8 + .../contrib/uclibc/libc/misc/time/ctime_r.c | 8 + .../contrib/uclibc/libc/misc/time/difftime.c | 8 + .../contrib/uclibc/libc/misc/time/dysize.c | 8 + .../lib/contrib/uclibc/libc/misc/time/ftime.c | 38 + .../contrib/uclibc/libc/misc/time/gmtime.c | 8 + .../contrib/uclibc/libc/misc/time/gmtime_r.c | 8 + .../contrib/uclibc/libc/misc/time/localtime.c | 8 + .../uclibc/libc/misc/time/localtime_r.c | 8 + .../contrib/uclibc/libc/misc/time/mktime.c | 8 + .../contrib/uclibc/libc/misc/time/strftime.c | 8 + .../uclibc/libc/misc/time/strftime_l.c | 9 + .../contrib/uclibc/libc/misc/time/strptime.c | 8 + .../uclibc/libc/misc/time/strptime_l.c | 9 + .../lib/contrib/uclibc/libc/misc/time/time.c | 2485 +++ .../contrib/uclibc/libc/misc/time/timegm.c | 8 + .../lib/contrib/uclibc/libc/misc/time/tzset.c | 8 + .../contrib/uclibc/libc/misc/time/wcsftime.c | 8 + .../uclibc/libc/misc/time/wcsftime_l.c | 9 + .../contrib/uclibc/libc/misc/ttyent/Makefile | 13 + .../uclibc/libc/misc/ttyent/Makefile.in | 23 + .../uclibc/libc/misc/ttyent/getttyent.c | 208 + .../contrib/uclibc/libc/misc/utmp/Makefile | 13 + .../contrib/uclibc/libc/misc/utmp/Makefile.in | 27 + .../lib/contrib/uclibc/libc/misc/utmp/utent.c | 207 + .../contrib/uclibc/libc/misc/utmp/utxent.c | 107 + .../lib/contrib/uclibc/libc/misc/utmp/wtent.c | 49 + .../contrib/uclibc/libc/misc/wchar/Makefile | 13 + .../uclibc/libc/misc/wchar/Makefile.in | 41 + .../libc/misc/wchar/_wchar_utf8sntowcs.c | 8 + .../libc/misc/wchar/_wchar_wcsntoutf8s.c | 8 + .../contrib/uclibc/libc/misc/wchar/btowc.c | 8 + .../contrib/uclibc/libc/misc/wchar/iconv.c | 8 + .../contrib/uclibc/libc/misc/wchar/mbrlen.c | 8 + .../contrib/uclibc/libc/misc/wchar/mbrtowc.c | 8 + .../contrib/uclibc/libc/misc/wchar/mbsinit.c | 8 + .../uclibc/libc/misc/wchar/mbsnrtowcs.c | 8 + .../uclibc/libc/misc/wchar/mbsrtowcs.c | 8 + .../contrib/uclibc/libc/misc/wchar/wchar.c | 1565 ++ .../contrib/uclibc/libc/misc/wchar/wcrtomb.c | 8 + .../uclibc/libc/misc/wchar/wcsnrtombs.c | 8 + .../uclibc/libc/misc/wchar/wcsrtombs.c | 8 + .../contrib/uclibc/libc/misc/wchar/wcswidth.c | 8 + .../contrib/uclibc/libc/misc/wchar/wctob.c | 8 + .../contrib/uclibc/libc/misc/wchar/wcwidth.c | 8 + .../contrib/uclibc/libc/misc/wctype/Makefile | 13 + .../uclibc/libc/misc/wctype/Makefile.in | 36 + .../contrib/uclibc/libc/misc/wctype/_wctype.c | 851 + .../uclibc/libc/misc/wctype/iswalnum.c | 8 + .../uclibc/libc/misc/wctype/iswalnum_l.c | 9 + .../uclibc/libc/misc/wctype/iswalpha.c | 8 + .../uclibc/libc/misc/wctype/iswalpha_l.c | 9 + .../uclibc/libc/misc/wctype/iswblank.c | 8 + .../uclibc/libc/misc/wctype/iswblank_l.c | 9 + .../uclibc/libc/misc/wctype/iswcntrl.c | 8 + .../uclibc/libc/misc/wctype/iswcntrl_l.c | 9 + .../uclibc/libc/misc/wctype/iswctype.c | 8 + .../uclibc/libc/misc/wctype/iswctype_l.c | 9 + .../uclibc/libc/misc/wctype/iswdigit.c | 8 + .../uclibc/libc/misc/wctype/iswdigit_l.c | 9 + .../uclibc/libc/misc/wctype/iswgraph.c | 8 + .../uclibc/libc/misc/wctype/iswgraph_l.c | 9 + .../uclibc/libc/misc/wctype/iswlower.c | 8 + .../uclibc/libc/misc/wctype/iswlower_l.c | 9 + .../uclibc/libc/misc/wctype/iswprint.c | 8 + .../uclibc/libc/misc/wctype/iswprint_l.c | 9 + .../uclibc/libc/misc/wctype/iswpunct.c | 8 + .../uclibc/libc/misc/wctype/iswpunct_l.c | 9 + .../uclibc/libc/misc/wctype/iswspace.c | 8 + .../uclibc/libc/misc/wctype/iswspace_l.c | 9 + .../uclibc/libc/misc/wctype/iswupper.c | 8 + .../uclibc/libc/misc/wctype/iswupper_l.c | 9 + .../uclibc/libc/misc/wctype/iswxdigit.c | 8 + .../uclibc/libc/misc/wctype/iswxdigit_l.c | 9 + .../uclibc/libc/misc/wctype/towctrans.c | 8 + .../uclibc/libc/misc/wctype/towctrans_l.c | 9 + .../uclibc/libc/misc/wctype/towlower.c | 8 + .../uclibc/libc/misc/wctype/towlower_l.c | 9 + .../uclibc/libc/misc/wctype/towupper.c | 8 + .../uclibc/libc/misc/wctype/towupper_l.c | 9 + .../contrib/uclibc/libc/misc/wctype/wctrans.c | 8 + .../uclibc/libc/misc/wctype/wctrans_l.c | 9 + .../contrib/uclibc/libc/misc/wctype/wctype.c | 8 + .../uclibc/libc/misc/wctype/wctype_l.c | 9 + .../contrib/uclibc/libc/misc/wordexp/Makefile | 13 + .../uclibc/libc/misc/wordexp/Makefile.in | 23 + .../uclibc/libc/misc/wordexp/wordexp.c | 2239 +++ .../contrib/uclibc/libc/pwd_grp/.indent.pro | 33 + .../lib/contrib/uclibc/libc/pwd_grp/Makefile | 13 + .../contrib/uclibc/libc/pwd_grp/Makefile.in | 33 + .../libc/pwd_grp/__getgrouplist_internal.c | 8 + .../uclibc/libc/pwd_grp/__parsegrent.c | 8 + .../uclibc/libc/pwd_grp/__parsepwent.c | 8 + .../uclibc/libc/pwd_grp/__parsespent.c | 8 + .../contrib/uclibc/libc/pwd_grp/__pgsreader.c | 8 + .../contrib/uclibc/libc/pwd_grp/fgetgrent.c | 8 + .../contrib/uclibc/libc/pwd_grp/fgetgrent_r.c | 8 + .../contrib/uclibc/libc/pwd_grp/fgetpwent.c | 8 + .../contrib/uclibc/libc/pwd_grp/fgetpwent_r.c | 8 + .../contrib/uclibc/libc/pwd_grp/fgetspent.c | 8 + .../contrib/uclibc/libc/pwd_grp/fgetspent_r.c | 8 + .../contrib/uclibc/libc/pwd_grp/getgrent.c | 8 + .../contrib/uclibc/libc/pwd_grp/getgrent_r.c | 12 + .../contrib/uclibc/libc/pwd_grp/getgrgid.c | 8 + .../contrib/uclibc/libc/pwd_grp/getgrgid_r.c | 8 + .../contrib/uclibc/libc/pwd_grp/getgrnam.c | 8 + .../contrib/uclibc/libc/pwd_grp/getgrnam_r.c | 8 + .../uclibc/libc/pwd_grp/getgrouplist.c | 8 + .../lib/contrib/uclibc/libc/pwd_grp/getpw.c | 12 + .../contrib/uclibc/libc/pwd_grp/getpwent.c | 8 + .../contrib/uclibc/libc/pwd_grp/getpwent_r.c | 8 + .../contrib/uclibc/libc/pwd_grp/getpwnam.c | 8 + .../contrib/uclibc/libc/pwd_grp/getpwnam_r.c | 8 + .../contrib/uclibc/libc/pwd_grp/getpwuid.c | 8 + .../contrib/uclibc/libc/pwd_grp/getpwuid_r.c | 8 + .../contrib/uclibc/libc/pwd_grp/getspent.c | 8 + .../contrib/uclibc/libc/pwd_grp/getspent_r.c | 8 + .../contrib/uclibc/libc/pwd_grp/getspnam.c | 8 + .../contrib/uclibc/libc/pwd_grp/getspnam_r.c | 8 + .../contrib/uclibc/libc/pwd_grp/initgroups.c | 8 + .../lib/contrib/uclibc/libc/pwd_grp/lckpwdf.c | 152 + .../contrib/uclibc/libc/pwd_grp/putgrent.c | 12 + .../contrib/uclibc/libc/pwd_grp/putpwent.c | 8 + .../contrib/uclibc/libc/pwd_grp/putspent.c | 8 + .../lib/contrib/uclibc/libc/pwd_grp/pwd_grp.c | 1185 ++ .../uclibc/libc/pwd_grp/pwd_grp_internal.c | 103 + .../contrib/uclibc/libc/pwd_grp/sgetspent.c | 8 + .../contrib/uclibc/libc/pwd_grp/sgetspent_r.c | 8 + .../lib/contrib/uclibc/libc/signal/Makefile | 13 + .../contrib/uclibc/libc/signal/Makefile.in | 38 + .../contrib/uclibc/libc/signal/allocrtsig.c | 66 + .../lib/contrib/uclibc/libc/signal/killpg.c | 36 + .../lib/contrib/uclibc/libc/signal/raise.c | 14 + .../contrib/uclibc/libc/signal/sigaction.c | 87 + .../contrib/uclibc/libc/signal/sigaddset.c | 33 + .../contrib/uclibc/libc/signal/sigandset.c | 34 + .../lib/contrib/uclibc/libc/signal/sigblock.c | 34 + .../contrib/uclibc/libc/signal/sigdelset.c | 32 + .../lib/contrib/uclibc/libc/signal/sigempty.c | 39 + .../contrib/uclibc/libc/signal/sigfillset.c | 49 + .../contrib/uclibc/libc/signal/siggetmask.c | 31 + .../lib/contrib/uclibc/libc/signal/sighold.c | 39 + .../contrib/uclibc/libc/signal/sigignore.c | 36 + .../lib/contrib/uclibc/libc/signal/sigintr.c | 56 + .../contrib/uclibc/libc/signal/sigisempty.c | 34 + .../lib/contrib/uclibc/libc/signal/sigismem.c | 31 + .../lib/contrib/uclibc/libc/signal/sigjmp.c | 36 + .../lib/contrib/uclibc/libc/signal/signal.c | 54 + .../lib/contrib/uclibc/libc/signal/sigorset.c | 34 + .../lib/contrib/uclibc/libc/signal/sigpause.c | 77 + .../lib/contrib/uclibc/libc/signal/sigrelse.c | 39 + .../uclibc/libc/signal/sigset-cvt-mask.h | 38 + .../lib/contrib/uclibc/libc/signal/sigset.c | 67 + .../contrib/uclibc/libc/signal/sigsetmask.c | 35 + .../contrib/uclibc/libc/signal/sigsetops.c | 20 + .../contrib/uclibc/libc/signal/sigsetops.h | 33 + .../lib/contrib/uclibc/libc/signal/sigwait.c | 167 + .../contrib/uclibc/libc/signal/sysv_signal.c | 57 + .../lib/contrib/uclibc/libc/stdio/.indent.pro | 33 + .../lib/contrib/uclibc/libc/stdio/Makefile | 13 + .../lib/contrib/uclibc/libc/stdio/Makefile.in | 109 + .../lib/contrib/uclibc/libc/stdio/_READ.c | 67 + .../lib/contrib/uclibc/libc/stdio/_WRITE.c | 101 + .../contrib/uclibc/libc/stdio/__fbufsize.c | 20 + .../lib/contrib/uclibc/libc/stdio/__flbf.c | 20 + .../contrib/uclibc/libc/stdio/__fpending.c | 35 + .../lib/contrib/uclibc/libc/stdio/__fpurge.c | 34 + .../contrib/uclibc/libc/stdio/__freadable.c | 20 + .../contrib/uclibc/libc/stdio/__freading.c | 20 + .../contrib/uclibc/libc/stdio/__fsetlocking.c | 47 + .../contrib/uclibc/libc/stdio/__fwritable.c | 20 + .../contrib/uclibc/libc/stdio/__fwriting.c | 20 + .../uclibc/libc/stdio/__psfs_do_numeric.c | 9 + .../uclibc/libc/stdio/__psfs_parse_spec.c | 9 + .../contrib/uclibc/libc/stdio/__scan_cookie.c | 9 + .../contrib/uclibc/libc/stdio/_adjust_pos.c | 68 + .../lib/contrib/uclibc/libc/stdio/_cs_funcs.c | 67 + .../lib/contrib/uclibc/libc/stdio/_flushlbf.c | 19 + .../lib/contrib/uclibc/libc/stdio/_fopen.c | 226 + .../contrib/uclibc/libc/stdio/_fpmaxtostr.c | 765 + .../lib/contrib/uclibc/libc/stdio/_fwrite.c | 79 + .../contrib/uclibc/libc/stdio/_load_inttype.c | 67 + .../contrib/uclibc/libc/stdio/_ppfs_init.c | 9 + .../uclibc/libc/stdio/_ppfs_parsespec.c | 9 + .../uclibc/libc/stdio/_ppfs_prepargs.c | 9 + .../contrib/uclibc/libc/stdio/_ppfs_setargs.c | 9 + .../lib/contrib/uclibc/libc/stdio/_rfill.c | 45 + .../lib/contrib/uclibc/libc/stdio/_scanf.c | 2221 +++ .../lib/contrib/uclibc/libc/stdio/_stdio.c | 465 + .../lib/contrib/uclibc/libc/stdio/_stdio.h | 456 + .../uclibc/libc/stdio/_store_inttype.c | 58 + .../lib/contrib/uclibc/libc/stdio/_trans2r.c | 79 + .../lib/contrib/uclibc/libc/stdio/_trans2w.c | 94 + .../contrib/uclibc/libc/stdio/_uintmaxtostr.c | 152 + .../lib/contrib/uclibc/libc/stdio/_vfprintf.c | 1969 +++ .../uclibc/libc/stdio/_vfprintf_internal.c | 9 + .../uclibc/libc/stdio/_vfwprintf_internal.c | 9 + .../lib/contrib/uclibc/libc/stdio/_wcommit.c | 31 + .../lib/contrib/uclibc/libc/stdio/_wfwrite.c | 73 + .../lib/contrib/uclibc/libc/stdio/asprintf.c | 34 + .../lib/contrib/uclibc/libc/stdio/clearerr.c | 40 + .../uclibc/libc/stdio/clearerr_unlocked.c | 9 + .../lib/contrib/uclibc/libc/stdio/ctermid.c | 27 + .../lib/contrib/uclibc/libc/stdio/dprintf.c | 26 + .../lib/contrib/uclibc/libc/stdio/fclose.c | 103 + .../lib/contrib/uclibc/libc/stdio/fcloseall.c | 70 + .../lib/contrib/uclibc/libc/stdio/fdopen.c | 20 + .../lib/contrib/uclibc/libc/stdio/feof.c | 43 + .../contrib/uclibc/libc/stdio/feof_unlocked.c | 9 + .../lib/contrib/uclibc/libc/stdio/ferror.c | 43 + .../uclibc/libc/stdio/ferror_unlocked.c | 9 + .../lib/contrib/uclibc/libc/stdio/fflush.c | 211 + .../uclibc/libc/stdio/fflush_unlocked.c | 9 + .../lib/contrib/uclibc/libc/stdio/fgetc.c | 107 + .../uclibc/libc/stdio/fgetc_unlocked.c | 9 + .../lib/contrib/uclibc/libc/stdio/fgetpos.c | 40 + .../lib/contrib/uclibc/libc/stdio/fgetpos64.c | 14 + .../lib/contrib/uclibc/libc/stdio/fgets.c | 87 + .../uclibc/libc/stdio/fgets_unlocked.c | 14 + .../lib/contrib/uclibc/libc/stdio/fgetwc.c | 138 + .../uclibc/libc/stdio/fgetwc_unlocked.c | 9 + .../lib/contrib/uclibc/libc/stdio/fgetws.c | 60 + .../uclibc/libc/stdio/fgetws_unlocked.c | 9 + .../lib/contrib/uclibc/libc/stdio/fileno.c | 48 + .../uclibc/libc/stdio/fileno_unlocked.c | 9 + .../lib/contrib/uclibc/libc/stdio/flockfile.c | 16 + .../lib/contrib/uclibc/libc/stdio/fmemopen.c | 181 + .../lib/contrib/uclibc/libc/stdio/fopen.c | 21 + .../lib/contrib/uclibc/libc/stdio/fopen64.c | 14 + .../contrib/uclibc/libc/stdio/fopencookie.c | 66 + .../lib/contrib/uclibc/libc/stdio/fprintf.c | 23 + .../lib/contrib/uclibc/libc/stdio/fputc.c | 106 + .../uclibc/libc/stdio/fputc_unlocked.c | 9 + .../lib/contrib/uclibc/libc/stdio/fputs.c | 50 + .../uclibc/libc/stdio/fputs_unlocked.c | 14 + .../lib/contrib/uclibc/libc/stdio/fputwc.c | 43 + .../uclibc/libc/stdio/fputwc_unlocked.c | 9 + .../lib/contrib/uclibc/libc/stdio/fputws.c | 45 + .../uclibc/libc/stdio/fputws_unlocked.c | 9 + .../lib/contrib/uclibc/libc/stdio/fread.c | 112 + .../uclibc/libc/stdio/fread_unlocked.c | 9 + .../lib/contrib/uclibc/libc/stdio/freopen.c | 75 + .../lib/contrib/uclibc/libc/stdio/freopen64.c | 13 + .../lib/contrib/uclibc/libc/stdio/fscanf.c | 9 + .../lib/contrib/uclibc/libc/stdio/fseeko.c | 81 + .../lib/contrib/uclibc/libc/stdio/fseeko64.c | 13 + .../lib/contrib/uclibc/libc/stdio/fsetpos.c | 39 + .../lib/contrib/uclibc/libc/stdio/fsetpos64.c | 14 + .../lib/contrib/uclibc/libc/stdio/ftello.c | 57 + .../lib/contrib/uclibc/libc/stdio/ftello64.c | 13 + .../contrib/uclibc/libc/stdio/ftrylockfile.c | 19 + .../contrib/uclibc/libc/stdio/funlockfile.c | 15 + .../lib/contrib/uclibc/libc/stdio/fwide.c | 32 + .../lib/contrib/uclibc/libc/stdio/fwprintf.c | 24 + .../lib/contrib/uclibc/libc/stdio/fwrite.c | 62 + .../uclibc/libc/stdio/fwrite_unlocked.c | 9 + .../lib/contrib/uclibc/libc/stdio/fwscanf.c | 9 + .../lib/contrib/uclibc/libc/stdio/getchar.c | 45 + .../uclibc/libc/stdio/getchar_unlocked.c | 9 + .../lib/contrib/uclibc/libc/stdio/getdelim.c | 82 + .../lib/contrib/uclibc/libc/stdio/getline.c | 21 + .../lib/contrib/uclibc/libc/stdio/gets.c | 39 + .../lib/contrib/uclibc/libc/stdio/getw.c | 19 + .../lib/contrib/uclibc/libc/stdio/getwchar.c | 30 + .../uclibc/libc/stdio/getwchar_unlocked.c | 9 + .../contrib/uclibc/libc/stdio/old_vfprintf.c | 710 + .../uclibc/libc/stdio/open_memstream.c | 166 + .../uclibc/libc/stdio/parse_printf_format.c | 9 + .../lib/contrib/uclibc/libc/stdio/perror.c | 38 + .../lib/contrib/uclibc/libc/stdio/popen.c | 186 + .../lib/contrib/uclibc/libc/stdio/printf.c | 23 + .../lib/contrib/uclibc/libc/stdio/putchar.c | 43 + .../uclibc/libc/stdio/putchar_unlocked.c | 9 + .../lib/contrib/uclibc/libc/stdio/puts.c | 34 + .../lib/contrib/uclibc/libc/stdio/putw.c | 29 + .../lib/contrib/uclibc/libc/stdio/putwchar.c | 31 + .../uclibc/libc/stdio/putwchar_unlocked.c | 9 + .../libc/stdio/register_printf_function.c | 9 + .../lib/contrib/uclibc/libc/stdio/remove.c | 31 + .../lib/contrib/uclibc/libc/stdio/rewind.c | 22 + .../lib/contrib/uclibc/libc/stdio/scanf.c | 9 + .../lib/contrib/uclibc/libc/stdio/setbuf.c | 16 + .../lib/contrib/uclibc/libc/stdio/setbuffer.c | 25 + .../contrib/uclibc/libc/stdio/setlinebuf.c | 24 + .../lib/contrib/uclibc/libc/stdio/setvbuf.c | 107 + .../lib/contrib/uclibc/libc/stdio/snprintf.c | 29 + .../lib/contrib/uclibc/libc/stdio/sprintf.c | 29 + .../lib/contrib/uclibc/libc/stdio/sscanf.c | 9 + .../lib/contrib/uclibc/libc/stdio/swprintf.c | 30 + .../lib/contrib/uclibc/libc/stdio/swscanf.c | 9 + .../lib/contrib/uclibc/libc/stdio/tempnam.c | 44 + .../lib/contrib/uclibc/libc/stdio/tmpfile.c | 54 + .../lib/contrib/uclibc/libc/stdio/tmpnam.c | 54 + .../lib/contrib/uclibc/libc/stdio/tmpnam_r.c | 35 + .../lib/contrib/uclibc/libc/stdio/ungetc.c | 78 + .../lib/contrib/uclibc/libc/stdio/ungetwc.c | 49 + .../lib/contrib/uclibc/libc/stdio/vasprintf.c | 82 + .../lib/contrib/uclibc/libc/stdio/vdprintf.c | 74 + .../lib/contrib/uclibc/libc/stdio/vfprintf.c | 9 + .../lib/contrib/uclibc/libc/stdio/vfscanf.c | 9 + .../lib/contrib/uclibc/libc/stdio/vfwprintf.c | 9 + .../lib/contrib/uclibc/libc/stdio/vfwscanf.c | 9 + .../lib/contrib/uclibc/libc/stdio/vprintf.c | 15 + .../lib/contrib/uclibc/libc/stdio/vscanf.c | 9 + .../lib/contrib/uclibc/libc/stdio/vsnprintf.c | 216 + .../lib/contrib/uclibc/libc/stdio/vsprintf.c | 22 + .../lib/contrib/uclibc/libc/stdio/vsscanf.c | 9 + .../lib/contrib/uclibc/libc/stdio/vswprintf.c | 70 + .../lib/contrib/uclibc/libc/stdio/vswscanf.c | 9 + .../lib/contrib/uclibc/libc/stdio/vwprintf.c | 16 + .../lib/contrib/uclibc/libc/stdio/vwscanf.c | 9 + .../lib/contrib/uclibc/libc/stdio/wprintf.c | 24 + .../lib/contrib/uclibc/libc/stdio/wscanf.c | 9 + .../contrib/uclibc/libc/stdlib/.indent.pro | 33 + .../lib/contrib/uclibc/libc/stdlib/Makefile | 13 + .../contrib/uclibc/libc/stdlib/Makefile.in | 80 + .../contrib/uclibc/libc/stdlib/__cxa_atexit.c | 8 + .../uclibc/libc/stdlib/__cxa_finalize.c | 8 + .../uclibc/libc/stdlib/__exit_handler.c | 8 + .../uclibc/libc/stdlib/__fp_range_check.c | 8 + .../contrib/uclibc/libc/stdlib/__strtofpmax.c | 8 + .../uclibc/libc/stdlib/__strtofpmax_l.c | 9 + .../contrib/uclibc/libc/stdlib/__uc_malloc.c | 45 + .../contrib/uclibc/libc/stdlib/__wcstofpmax.c | 8 + .../uclibc/libc/stdlib/__wcstofpmax_l.c | 9 + .../lib/contrib/uclibc/libc/stdlib/_atexit.c | 337 + .../uclibc/libc/stdlib/_stdlib_mb_cur_max.c | 7 + .../uclibc/libc/stdlib/_stdlib_strto_l.c | 7 + .../uclibc/libc/stdlib/_stdlib_strto_l_l.c | 8 + .../uclibc/libc/stdlib/_stdlib_strto_ll.c | 7 + .../uclibc/libc/stdlib/_stdlib_strto_ll_l.c | 8 + .../uclibc/libc/stdlib/_stdlib_wcsto_l.c | 7 + .../uclibc/libc/stdlib/_stdlib_wcsto_l_l.c | 8 + .../uclibc/libc/stdlib/_stdlib_wcsto_ll.c | 7 + .../uclibc/libc/stdlib/_stdlib_wcsto_ll_l.c | 8 + .../lib/contrib/uclibc/libc/stdlib/_strtod.c | 604 + .../lib/contrib/uclibc/libc/stdlib/a64l.c | 64 + .../lib/contrib/uclibc/libc/stdlib/abort.c | 114 + .../lib/contrib/uclibc/libc/stdlib/abs.c | 7 + .../contrib/uclibc/libc/stdlib/arc4random.c | 204 + .../lib/contrib/uclibc/libc/stdlib/atexit.c | 8 + .../lib/contrib/uclibc/libc/stdlib/atof.c | 7 + .../lib/contrib/uclibc/libc/stdlib/atoi.c | 7 + .../lib/contrib/uclibc/libc/stdlib/atol.c | 7 + .../lib/contrib/uclibc/libc/stdlib/atoll.c | 7 + .../contrib/uclibc/libc/stdlib/bsd_getpt.c | 76 + .../lib/contrib/uclibc/libc/stdlib/bsearch.c | 7 + .../contrib/uclibc/libc/stdlib/canonicalize.c | 38 + .../lib/contrib/uclibc/libc/stdlib/div.c | 17 + .../contrib/uclibc/libc/stdlib/drand48-iter.c | 59 + .../lib/contrib/uclibc/libc/stdlib/drand48.c | 33 + .../contrib/uclibc/libc/stdlib/drand48_r.c | 28 + .../lib/contrib/uclibc/libc/stdlib/erand48.c | 33 + .../contrib/uclibc/libc/stdlib/erand48_r.c | 48 + .../lib/contrib/uclibc/libc/stdlib/exit.c | 8 + .../lib/contrib/uclibc/libc/stdlib/gcvt.c | 12 + .../lib/contrib/uclibc/libc/stdlib/getenv.c | 30 + .../lib/contrib/uclibc/libc/stdlib/getpt.c | 132 + .../lib/contrib/uclibc/libc/stdlib/grantpt.c | 76 + .../lib/contrib/uclibc/libc/stdlib/jrand48.c | 33 + .../contrib/uclibc/libc/stdlib/jrand48_r.c | 36 + .../lib/contrib/uclibc/libc/stdlib/l64a.c | 56 + .../lib/contrib/uclibc/libc/stdlib/labs.c | 7 + .../lib/contrib/uclibc/libc/stdlib/ldiv.c | 61 + .../lib/contrib/uclibc/libc/stdlib/llabs.c | 7 + .../lib/contrib/uclibc/libc/stdlib/lldiv.c | 61 + .../lib/contrib/uclibc/libc/stdlib/lrand48.c | 33 + .../contrib/uclibc/libc/stdlib/lrand48_r.c | 31 + .../uclibc/libc/stdlib/malloc-simple/Makefile | 13 + .../libc/stdlib/malloc-simple/Makefile.in | 24 + .../uclibc/libc/stdlib/malloc-simple/alloc.c | 185 + .../uclibc/libc/stdlib/malloc-simple/calloc.c | 8 + .../uclibc/libc/stdlib/malloc-simple/free.c | 8 + .../uclibc/libc/stdlib/malloc-simple/malloc.c | 8 + .../libc/stdlib/malloc-simple/memalign.c | 8 + .../libc/stdlib/malloc-simple/realloc.c | 8 + .../libc/stdlib/malloc-standard/Makefile | 13 + .../libc/stdlib/malloc-standard/Makefile.in | 25 + .../libc/stdlib/malloc-standard/calloc.c | 93 + .../uclibc/libc/stdlib/malloc-standard/free.c | 410 + .../libc/stdlib/malloc-standard/mallinfo.c | 124 + .../libc/stdlib/malloc-standard/malloc.c | 1167 ++ .../libc/stdlib/malloc-standard/malloc.h | 959 ++ .../libc/stdlib/malloc-standard/mallopt.c | 64 + .../libc/stdlib/malloc-standard/memalign.c | 130 + .../libc/stdlib/malloc-standard/realloc.c | 240 + .../uclibc/libc/stdlib/malloc/Makefile | 13 + .../uclibc/libc/stdlib/malloc/Makefile.in | 39 + .../uclibc/libc/stdlib/malloc/calloc.c | 42 + .../contrib/uclibc/libc/stdlib/malloc/free.c | 272 + .../contrib/uclibc/libc/stdlib/malloc/heap.h | 229 + .../uclibc/libc/stdlib/malloc/heap_alloc.c | 51 + .../uclibc/libc/stdlib/malloc/heap_alloc_at.c | 47 + .../uclibc/libc/stdlib/malloc/heap_debug.c | 144 + .../uclibc/libc/stdlib/malloc/heap_free.c | 89 + .../uclibc/libc/stdlib/malloc/malloc.c | 233 + .../uclibc/libc/stdlib/malloc/malloc.h | 229 + .../uclibc/libc/stdlib/malloc/malloc_debug.c | 87 + .../uclibc/libc/stdlib/malloc/memalign.c | 95 + .../uclibc/libc/stdlib/malloc/realloc.c | 100 + .../lib/contrib/uclibc/libc/stdlib/mblen.c | 7 + .../lib/contrib/uclibc/libc/stdlib/mbstowcs.c | 7 + .../lib/contrib/uclibc/libc/stdlib/mbtowc.c | 7 + .../lib/contrib/uclibc/libc/stdlib/mkdtemp.c | 38 + .../lib/contrib/uclibc/libc/stdlib/mkstemp.c | 31 + .../contrib/uclibc/libc/stdlib/mkstemp64.c | 31 + .../lib/contrib/uclibc/libc/stdlib/mktemp.c | 35 + .../lib/contrib/uclibc/libc/stdlib/mrand48.c | 33 + .../contrib/uclibc/libc/stdlib/mrand48_r.c | 30 + .../lib/contrib/uclibc/libc/stdlib/nrand48.c | 33 + .../contrib/uclibc/libc/stdlib/nrand48_r.c | 39 + .../contrib/uclibc/libc/stdlib/old_atexit.c | 8 + .../lib/contrib/uclibc/libc/stdlib/on_exit.c | 8 + .../uclibc/libc/stdlib/posix_memalign.c | 42 + .../lib/contrib/uclibc/libc/stdlib/ptsname.c | 192 + .../contrib/uclibc/libc/stdlib/pty-private.h | 42 + .../lib/contrib/uclibc/libc/stdlib/qsort.c | 7 + .../lib/contrib/uclibc/libc/stdlib/rand.c | 14 + .../lib/contrib/uclibc/libc/stdlib/rand_r.c | 48 + .../lib/contrib/uclibc/libc/stdlib/random.c | 243 + .../lib/contrib/uclibc/libc/stdlib/random_r.c | 359 + .../lib/contrib/uclibc/libc/stdlib/realpath.c | 162 + .../lib/contrib/uclibc/libc/stdlib/seed48.c | 31 + .../lib/contrib/uclibc/libc/stdlib/seed48_r.c | 40 + .../lib/contrib/uclibc/libc/stdlib/setenv.c | 183 + .../lib/contrib/uclibc/libc/stdlib/srand48.c | 29 + .../contrib/uclibc/libc/stdlib/srand48_r.c | 39 + .../lib/contrib/uclibc/libc/stdlib/stdlib.c | 1152 ++ .../lib/contrib/uclibc/libc/stdlib/strtod.c | 8 + .../lib/contrib/uclibc/libc/stdlib/strtod_l.c | 9 + .../lib/contrib/uclibc/libc/stdlib/strtof.c | 8 + .../lib/contrib/uclibc/libc/stdlib/strtof_l.c | 9 + .../lib/contrib/uclibc/libc/stdlib/strtol.c | 7 + .../lib/contrib/uclibc/libc/stdlib/strtol_l.c | 8 + .../lib/contrib/uclibc/libc/stdlib/strtold.c | 8 + .../contrib/uclibc/libc/stdlib/strtold_l.c | 9 + .../lib/contrib/uclibc/libc/stdlib/strtoll.c | 7 + .../contrib/uclibc/libc/stdlib/strtoll_l.c | 8 + .../lib/contrib/uclibc/libc/stdlib/strtoul.c | 7 + .../contrib/uclibc/libc/stdlib/strtoul_l.c | 8 + .../lib/contrib/uclibc/libc/stdlib/strtoull.c | 7 + .../contrib/uclibc/libc/stdlib/strtoull_l.c | 8 + .../lib/contrib/uclibc/libc/stdlib/system.c | 270 + .../contrib/uclibc/libc/stdlib/unix_grantpt.c | 201 + .../lib/contrib/uclibc/libc/stdlib/unlockpt.c | 49 + .../lib/contrib/uclibc/libc/stdlib/valloc.c | 36 + .../lib/contrib/uclibc/libc/stdlib/wcstod.c | 8 + .../lib/contrib/uclibc/libc/stdlib/wcstod_l.c | 9 + .../lib/contrib/uclibc/libc/stdlib/wcstof.c | 8 + .../lib/contrib/uclibc/libc/stdlib/wcstof_l.c | 9 + .../lib/contrib/uclibc/libc/stdlib/wcstol.c | 7 + .../lib/contrib/uclibc/libc/stdlib/wcstol_l.c | 8 + .../lib/contrib/uclibc/libc/stdlib/wcstold.c | 8 + .../contrib/uclibc/libc/stdlib/wcstold_l.c | 9 + .../lib/contrib/uclibc/libc/stdlib/wcstoll.c | 7 + .../contrib/uclibc/libc/stdlib/wcstoll_l.c | 8 + .../lib/contrib/uclibc/libc/stdlib/wcstombs.c | 7 + .../lib/contrib/uclibc/libc/stdlib/wcstoul.c | 7 + .../contrib/uclibc/libc/stdlib/wcstoul_l.c | 8 + .../lib/contrib/uclibc/libc/stdlib/wcstoull.c | 7 + .../contrib/uclibc/libc/stdlib/wcstoull_l.c | 8 + .../lib/contrib/uclibc/libc/stdlib/wctomb.c | 7 + .../contrib/uclibc/libc/string/.indent.pro | 33 + .../lib/contrib/uclibc/libc/string/Makefile | 13 + .../contrib/uclibc/libc/string/Makefile.in | 144 + .../uclibc/libc/string/__glibc_strerror_r.c | 18 + .../uclibc/libc/string/__xpg_basename.c | 36 + .../uclibc/libc/string/__xpg_strerror_r.c | 276 + .../lib/contrib/uclibc/libc/string/_collate.c | 673 + .../lib/contrib/uclibc/libc/string/_string.h | 32 + .../uclibc/libc/string/_string_syserrmsgs.c | 147 + .../uclibc/libc/string/_string_syssigmsgs.c | 51 + .../contrib/uclibc/libc/string/_syserrmsg.h | 37 + .../contrib/uclibc/libc/string/arm/Makefile | 13 + .../contrib/uclibc/libc/string/arm/_memcpy.S | 747 + .../contrib/uclibc/libc/string/arm/bcopy.S | 72 + .../contrib/uclibc/libc/string/arm/bzero.S | 68 + .../contrib/uclibc/libc/string/arm/memcmp.S | 96 + .../contrib/uclibc/libc/string/arm/memcpy.S | 61 + .../contrib/uclibc/libc/string/arm/memmove.S | 61 + .../contrib/uclibc/libc/string/arm/memset.S | 144 + .../contrib/uclibc/libc/string/arm/strcmp.S | 78 + .../contrib/uclibc/libc/string/arm/strlen.S | 111 + .../contrib/uclibc/libc/string/avr32/Makefile | 26 + .../contrib/uclibc/libc/string/avr32/bcopy.S | 26 + .../contrib/uclibc/libc/string/avr32/bzero.S | 24 + .../contrib/uclibc/libc/string/avr32/memcmp.S | 61 + .../contrib/uclibc/libc/string/avr32/memcpy.S | 111 + .../uclibc/libc/string/avr32/memmove.S | 116 + .../contrib/uclibc/libc/string/avr32/memset.S | 65 + .../contrib/uclibc/libc/string/avr32/strcmp.S | 91 + .../contrib/uclibc/libc/string/avr32/strlen.S | 62 + .../lib/contrib/uclibc/libc/string/basename.c | 28 + .../lib/contrib/uclibc/libc/string/bcopy.c | 36 + .../contrib/uclibc/libc/string/bfin/Makefile | 13 + .../contrib/uclibc/libc/string/bfin/memchr.S | 55 + .../contrib/uclibc/libc/string/bfin/memcmp.S | 104 + .../contrib/uclibc/libc/string/bfin/memcpy.S | 77 + .../contrib/uclibc/libc/string/bfin/memmove.S | 100 + .../contrib/uclibc/libc/string/bfin/memset.S | 90 + .../contrib/uclibc/libc/string/bfin/strcmp.S | 122 + .../lib/contrib/uclibc/libc/string/bzero.c | 24 + .../contrib/uclibc/libc/string/cris/memcopy.h | 62 + .../contrib/uclibc/libc/string/cris/memcpy.c | 242 + .../contrib/uclibc/libc/string/cris/memmove.c | 100 + .../contrib/uclibc/libc/string/cris/memset.c | 262 + .../contrib/uclibc/libc/string/cris/strcpy.c | 50 + .../contrib/uclibc/libc/string/cris/strncpy.c | 59 + .../lib/contrib/uclibc/libc/string/dirname.c | 44 + .../lib/contrib/uclibc/libc/string/ffs.c | 54 + .../contrib/uclibc/libc/string/frv/Makefile | 13 + .../contrib/uclibc/libc/string/frv/memcpy.S | 127 + .../contrib/uclibc/libc/string/frv/memset.S | 157 + .../uclibc/libc/string/generic/Makefile | 13 + .../uclibc/libc/string/generic/_memcpy_fwd.c | 185 + .../uclibc/libc/string/generic/memchr.c | 175 + .../uclibc/libc/string/generic/memcmp.c | 315 + .../uclibc/libc/string/generic/memcopy.h | 150 + .../uclibc/libc/string/generic/memcpy.c | 61 + .../uclibc/libc/string/generic/memmem.c | 52 + .../uclibc/libc/string/generic/memmove.c | 289 + .../uclibc/libc/string/generic/mempcpy.c | 19 + .../uclibc/libc/string/generic/memrchr.c | 176 + .../uclibc/libc/string/generic/memset.c | 85 + .../uclibc/libc/string/generic/pagecopy.h | 75 + .../uclibc/libc/string/generic/rawmemchr.c | 162 + .../uclibc/libc/string/generic/strcat.c | 47 + .../uclibc/libc/string/generic/strchr.c | 185 + .../uclibc/libc/string/generic/strchrnul.c | 167 + .../uclibc/libc/string/generic/strcmp.c | 48 + .../uclibc/libc/string/generic/strcpy.c | 36 + .../uclibc/libc/string/generic/strcspn.c | 36 + .../uclibc/libc/string/generic/strlen.c | 150 + .../uclibc/libc/string/generic/strncat.c | 76 + .../uclibc/libc/string/generic/strncmp.c | 67 + .../uclibc/libc/string/generic/strncpy.c | 81 + .../uclibc/libc/string/generic/strnlen.c | 162 + .../uclibc/libc/string/generic/strrchr.c | 46 + .../uclibc/libc/string/generic/strsep.c | 68 + .../uclibc/libc/string/generic/strspn.c | 42 + .../uclibc/libc/string/generic/strstr.c | 113 + .../uclibc/libc/string/generic/strtok_r.c | 67 + .../contrib/uclibc/libc/string/i386/Makefile | 13 + .../contrib/uclibc/libc/string/i386/memchr.c | 75 + .../contrib/uclibc/libc/string/i386/memcpy.c | 54 + .../contrib/uclibc/libc/string/i386/memmove.c | 71 + .../contrib/uclibc/libc/string/i386/memset.c | 95 + .../uclibc/libc/string/i386/rawmemchr.c | 24 + .../contrib/uclibc/libc/string/i386/strcat.c | 50 + .../contrib/uclibc/libc/string/i386/strchr.c | 58 + .../uclibc/libc/string/i386/strchrnul.c | 47 + .../contrib/uclibc/libc/string/i386/strcmp.c | 59 + .../contrib/uclibc/libc/string/i386/strcpy.c | 48 + .../contrib/uclibc/libc/string/i386/string.h | 338 + .../contrib/uclibc/libc/string/i386/strlen.c | 48 + .../contrib/uclibc/libc/string/i386/strncat.c | 86 + .../contrib/uclibc/libc/string/i386/strncmp.c | 59 + .../contrib/uclibc/libc/string/i386/strncpy.c | 75 + .../contrib/uclibc/libc/string/i386/strnlen.c | 75 + .../contrib/uclibc/libc/string/i386/strrchr.c | 58 + .../contrib/uclibc/libc/string/ia64/Makefile | 13 + .../contrib/uclibc/libc/string/ia64/bcopy.S | 14 + .../contrib/uclibc/libc/string/ia64/bzero.S | 320 + .../contrib/uclibc/libc/string/ia64/memccpy.S | 213 + .../contrib/uclibc/libc/string/ia64/memchr.S | 131 + .../contrib/uclibc/libc/string/ia64/memcmp.S | 166 + .../contrib/uclibc/libc/string/ia64/memcpy.S | 436 + .../contrib/uclibc/libc/string/ia64/memmove.S | 251 + .../contrib/uclibc/libc/string/ia64/memset.S | 400 + .../uclibc/libc/string/ia64/softpipe.h | 29 + .../contrib/uclibc/libc/string/ia64/strchr.S | 113 + .../contrib/uclibc/libc/string/ia64/strcmp.S | 59 + .../contrib/uclibc/libc/string/ia64/strcpy.S | 145 + .../contrib/uclibc/libc/string/ia64/strlen.S | 98 + .../contrib/uclibc/libc/string/ia64/strncmp.S | 62 + .../contrib/uclibc/libc/string/ia64/strncpy.S | 232 + .../contrib/uclibc/libc/string/ia64/sysdep.h | 168 + .../lib/contrib/uclibc/libc/string/memccpy.c | 21 + .../lib/contrib/uclibc/libc/string/memchr.c | 32 + .../lib/contrib/uclibc/libc/string/memcmp.c | 43 + .../lib/contrib/uclibc/libc/string/memcpy.c | 29 + .../lib/contrib/uclibc/libc/string/memmem.c | 41 + .../lib/contrib/uclibc/libc/string/memmove.c | 38 + .../lib/contrib/uclibc/libc/string/mempcpy.c | 33 + .../lib/contrib/uclibc/libc/string/memrchr.c | 28 + .../lib/contrib/uclibc/libc/string/memset.c | 31 + .../uclibc/libc/string/microblaze/Makefile | 13 + .../uclibc/libc/string/microblaze/memcpy.S | 326 + .../uclibc/libc/string/microblaze/memmove.S | 348 + .../contrib/uclibc/libc/string/mips/Makefile | 13 + .../contrib/uclibc/libc/string/mips/memcpy.S | 257 + .../contrib/uclibc/libc/string/mips/memset.S | 159 + .../contrib/uclibc/libc/string/mips/sysdep.h | 45 + .../uclibc/libc/string/powerpc/Makefile | 13 + .../uclibc/libc/string/powerpc/memcpy.c | 82 + .../uclibc/libc/string/powerpc/memmove.c | 76 + .../uclibc/libc/string/powerpc/memset.c | 82 + .../lib/contrib/uclibc/libc/string/psignal.c | 30 + .../contrib/uclibc/libc/string/rawmemchr.c | 20 + .../contrib/uclibc/libc/string/sh/memchr.S | 30 + .../uclibc/libc/string/sh/sh4/memcpy.S | 1006 ++ .../uclibc/libc/string/sh/sh4/memmove.c | 121 + .../uclibc/libc/string/sh/sh4/memset.S | 152 + .../uclibc/libc/string/sh/sh4/strcpy.S | 28 + .../uclibc/libc/string/sh/sh4/strncpy.S | 43 + .../contrib/uclibc/libc/string/sh/strlen.S | 75 + .../contrib/uclibc/libc/string/sh64/Makefile | 13 + .../contrib/uclibc/libc/string/sh64/memcpy.S | 205 + .../contrib/uclibc/libc/string/sh64/memset.S | 97 + .../contrib/uclibc/libc/string/sh64/strcpy.S | 102 + .../contrib/uclibc/libc/string/sh64/strlen.S | 63 + .../contrib/uclibc/libc/string/sparc/Makefile | 13 + .../uclibc/libc/string/sparc/_glibc_inc.h | 27 + .../contrib/uclibc/libc/string/sparc/bcopy.c | 1 + .../contrib/uclibc/libc/string/sparc/bzero.c | 1 + .../contrib/uclibc/libc/string/sparc/memchr.S | 13 + .../contrib/uclibc/libc/string/sparc/memcpy.S | 19 + .../uclibc/libc/string/sparc/memmove.c | 1 + .../contrib/uclibc/libc/string/sparc/memset.S | 13 + .../uclibc/libc/string/sparc/sparc32/memchr.S | 142 + .../uclibc/libc/string/sparc/sparc32/memcpy.S | 973 ++ .../uclibc/libc/string/sparc/sparc32/memset.S | 157 + .../string/sparc/sparc32/sparcv9b/memchr.S | 4 + .../string/sparc/sparc32/sparcv9b/memcpy.S | 4 + .../string/sparc/sparc32/sparcv9b/memset.S | 4 + .../string/sparc/sparc32/sparcv9b/stpcpy.S | 4 + .../string/sparc/sparc32/sparcv9b/strcat.S | 4 + .../string/sparc/sparc32/sparcv9b/strchr.S | 4 + .../string/sparc/sparc32/sparcv9b/strcmp.S | 4 + .../string/sparc/sparc32/sparcv9b/strcpy.S | 4 + .../string/sparc/sparc32/sparcv9b/strlen.S | 4 + .../uclibc/libc/string/sparc/sparc32/stpcpy.S | 161 + .../uclibc/libc/string/sparc/sparc32/strcat.S | 348 + .../uclibc/libc/string/sparc/sparc32/strchr.S | 287 + .../uclibc/libc/string/sparc/sparc32/strcmp.S | 256 + .../uclibc/libc/string/sparc/sparc32/strcpy.S | 273 + .../uclibc/libc/string/sparc/sparc32/strlen.S | 102 + .../uclibc/libc/string/sparc/sparc64/memchr.S | 259 + .../uclibc/libc/string/sparc/sparc64/memcpy.S | 923 ++ .../uclibc/libc/string/sparc/sparc64/memset.S | 317 + .../string/sparc/sparc64/sparcv9b/memcpy.S | 612 + .../uclibc/libc/string/sparc/sparc64/stpcpy.S | 271 + .../uclibc/libc/string/sparc/sparc64/strcat.S | 339 + .../uclibc/libc/string/sparc/sparc64/strchr.S | 486 + .../uclibc/libc/string/sparc/sparc64/strcmp.S | 279 + .../uclibc/libc/string/sparc/sparc64/strcpy.S | 245 + .../uclibc/libc/string/sparc/sparc64/strlen.S | 173 + .../contrib/uclibc/libc/string/sparc/stpcpy.S | 13 + .../contrib/uclibc/libc/string/sparc/strcat.S | 13 + .../contrib/uclibc/libc/string/sparc/strchr.S | 13 + .../contrib/uclibc/libc/string/sparc/strcmp.S | 18 + .../contrib/uclibc/libc/string/sparc/strcpy.S | 13 + .../contrib/uclibc/libc/string/sparc/strlen.S | 13 + .../uclibc/libc/string/sparc/strrchr.c | 1 + .../lib/contrib/uclibc/libc/string/stpcpy.c | 26 + .../lib/contrib/uclibc/libc/string/stpncpy.c | 33 + .../contrib/uclibc/libc/string/strcasecmp.c | 64 + .../contrib/uclibc/libc/string/strcasecmp_l.c | 8 + .../contrib/uclibc/libc/string/strcasestr.c | 50 + .../lib/contrib/uclibc/libc/string/strcat.c | 26 + .../lib/contrib/uclibc/libc/string/strchr.c | 30 + .../contrib/uclibc/libc/string/strchrnul.c | 25 + .../lib/contrib/uclibc/libc/string/strcmp.c | 43 + .../lib/contrib/uclibc/libc/string/strcpy.c | 29 + .../lib/contrib/uclibc/libc/string/strcspn.c | 32 + .../lib/contrib/uclibc/libc/string/strdup.c | 33 + .../lib/contrib/uclibc/libc/string/strerror.c | 21 + .../lib/contrib/uclibc/libc/string/strlcat.c | 47 + .../lib/contrib/uclibc/libc/string/strlcpy.c | 63 + .../lib/contrib/uclibc/libc/string/strlen.c | 24 + .../contrib/uclibc/libc/string/strncasecmp.c | 67 + .../uclibc/libc/string/strncasecmp_l.c | 8 + .../lib/contrib/uclibc/libc/string/strncat.c | 34 + .../lib/contrib/uclibc/libc/string/strncmp.c | 41 + .../lib/contrib/uclibc/libc/string/strncpy.c | 31 + .../lib/contrib/uclibc/libc/string/strndup.c | 25 + .../lib/contrib/uclibc/libc/string/strnlen.c | 31 + .../lib/contrib/uclibc/libc/string/strpbrk.c | 28 + .../lib/contrib/uclibc/libc/string/strrchr.c | 34 + .../lib/contrib/uclibc/libc/string/strsep.c | 34 + .../contrib/uclibc/libc/string/strsignal.c | 143 + .../lib/contrib/uclibc/libc/string/strspn.c | 29 + .../lib/contrib/uclibc/libc/string/strstr.c | 43 + .../lib/contrib/uclibc/libc/string/strtok.c | 24 + .../lib/contrib/uclibc/libc/string/strtok_r.c | 55 + .../contrib/uclibc/libc/string/strverscmp.c | 118 + .../lib/contrib/uclibc/libc/string/strxfrm.c | 9 + .../contrib/uclibc/libc/string/strxfrm_l.c | 10 + .../contrib/uclibc/libc/string/sys_errlist.c | 171 + .../contrib/uclibc/libc/string/sys_siglist.c | 57 + .../lib/contrib/uclibc/libc/string/wcpcpy.c | 8 + .../lib/contrib/uclibc/libc/string/wcpncpy.c | 8 + .../contrib/uclibc/libc/string/wcscasecmp.c | 8 + .../contrib/uclibc/libc/string/wcscasecmp_l.c | 9 + .../lib/contrib/uclibc/libc/string/wcscat.c | 8 + .../lib/contrib/uclibc/libc/string/wcschr.c | 8 + .../contrib/uclibc/libc/string/wcschrnul.c | 8 + .../lib/contrib/uclibc/libc/string/wcscmp.c | 8 + .../lib/contrib/uclibc/libc/string/wcscpy.c | 8 + .../lib/contrib/uclibc/libc/string/wcscspn.c | 8 + .../lib/contrib/uclibc/libc/string/wcsdup.c | 8 + .../lib/contrib/uclibc/libc/string/wcslcpy.c | 8 + .../lib/contrib/uclibc/libc/string/wcslen.c | 8 + .../contrib/uclibc/libc/string/wcsncasecmp.c | 8 + .../uclibc/libc/string/wcsncasecmp_l.c | 9 + .../lib/contrib/uclibc/libc/string/wcsncat.c | 8 + .../lib/contrib/uclibc/libc/string/wcsncmp.c | 8 + .../lib/contrib/uclibc/libc/string/wcsncpy.c | 8 + .../lib/contrib/uclibc/libc/string/wcsnlen.c | 8 + .../lib/contrib/uclibc/libc/string/wcspbrk.c | 8 + .../lib/contrib/uclibc/libc/string/wcsrchr.c | 8 + .../lib/contrib/uclibc/libc/string/wcsspn.c | 8 + .../lib/contrib/uclibc/libc/string/wcsstr.c | 8 + .../lib/contrib/uclibc/libc/string/wcstok.c | 8 + .../lib/contrib/uclibc/libc/string/wcsxfrm.c | 9 + .../contrib/uclibc/libc/string/wcsxfrm_l.c | 10 + .../lib/contrib/uclibc/libc/string/wmemchr.c | 8 + .../lib/contrib/uclibc/libc/string/wmemcmp.c | 8 + .../lib/contrib/uclibc/libc/string/wmemcpy.c | 8 + .../lib/contrib/uclibc/libc/string/wmemmove.c | 8 + .../lib/contrib/uclibc/libc/string/wmempcpy.c | 8 + .../lib/contrib/uclibc/libc/string/wmemset.c | 8 + .../uclibc/libc/string/x86_64/Makefile | 13 + .../uclibc/libc/string/x86_64/_glibc_inc.h | 21 + .../contrib/uclibc/libc/string/x86_64/bzero.S | 6 + .../uclibc/libc/string/x86_64/memcpy.S | 100 + .../uclibc/libc/string/x86_64/mempcpy.S | 4 + .../uclibc/libc/string/x86_64/memset.S | 149 + .../uclibc/libc/string/x86_64/stpcpy.S | 4 + .../uclibc/libc/string/x86_64/strcat.S | 268 + .../uclibc/libc/string/x86_64/strchr.S | 295 + .../uclibc/libc/string/x86_64/strcmp.S | 47 + .../uclibc/libc/string/x86_64/strcpy.S | 162 + .../uclibc/libc/string/x86_64/strcspn.S | 137 + .../uclibc/libc/string/x86_64/strlen.S | 144 + .../uclibc/libc/string/x86_64/strpbrk.S | 3 + .../uclibc/libc/string/x86_64/strspn.S | 124 + .../uclibc/libc/string/xtensa/Makefile | 13 + .../uclibc/libc/string/xtensa/memcpy.S | 297 + .../uclibc/libc/string/xtensa/memset.S | 165 + .../uclibc/libc/string/xtensa/strcmp.S | 314 + .../uclibc/libc/string/xtensa/strcpy.S | 150 + .../uclibc/libc/string/xtensa/strlen.S | 104 + .../uclibc/libc/string/xtensa/strncpy.S | 241 + .../lib/contrib/uclibc/libc/sysdeps/Makefile | 13 + .../contrib/uclibc/libc/sysdeps/Makefile.in | 8 + .../lib/contrib/uclibc/libc/sysdeps/README | 6 + .../uclibc/libc/sysdeps/linux/Makefile | 13 + .../libc/sysdeps/linux/Makefile.commonarch | 41 + .../uclibc/libc/sysdeps/linux/Makefile.in | 13 + .../contrib/uclibc/libc/sysdeps/linux/README | 7 + .../uclibc/libc/sysdeps/linux/alpha/Makefile | 13 + .../libc/sysdeps/linux/alpha/Makefile.arch | 13 + .../libc/sysdeps/linux/alpha/__longjmp.S | 57 + .../sysdeps/linux/alpha/__syscall_error.c | 16 + .../linux/alpha/__syscall_rt_sigaction.S | 81 + .../libc/sysdeps/linux/alpha/bits/atomic.h | 369 + .../libc/sysdeps/linux/alpha/bits/dirent.h | 55 + .../libc/sysdeps/linux/alpha/bits/elfclass.h | 14 + .../libc/sysdeps/linux/alpha/bits/endian.h | 7 + .../libc/sysdeps/linux/alpha/bits/fcntl.h | 230 + .../libc/sysdeps/linux/alpha/bits/fenv.h | 123 + .../libc/sysdeps/linux/alpha/bits/ioctls.h | 37 + .../libc/sysdeps/linux/alpha/bits/ipc.h | 55 + .../linux/alpha/bits/kernel_sigaction.h | 20 + .../sysdeps/linux/alpha/bits/kernel_stat.h | 49 + .../sysdeps/linux/alpha/bits/kernel_types.h | 41 + .../libc/sysdeps/linux/alpha/bits/mathdef.h | 66 + .../sysdeps/linux/alpha/bits/mathinline.h | 183 + .../libc/sysdeps/linux/alpha/bits/mman.h | 120 + .../libc/sysdeps/linux/alpha/bits/msq.h | 74 + .../libc/sysdeps/linux/alpha/bits/netdb.h | 35 + .../libc/sysdeps/linux/alpha/bits/resource.h | 225 + .../libc/sysdeps/linux/alpha/bits/sem.h | 85 + .../libc/sysdeps/linux/alpha/bits/setjmp.h | 87 + .../libc/sysdeps/linux/alpha/bits/shm.h | 101 + .../libc/sysdeps/linux/alpha/bits/sigaction.h | 65 + .../sysdeps/linux/alpha/bits/sigcontextinfo.h | 25 + .../libc/sysdeps/linux/alpha/bits/siginfo.h | 303 + .../libc/sysdeps/linux/alpha/bits/signum.h | 63 + .../libc/sysdeps/linux/alpha/bits/sigstack.h | 55 + .../libc/sysdeps/linux/alpha/bits/stackinfo.h | 28 + .../libc/sysdeps/linux/alpha/bits/stat.h | 156 + .../libc/sysdeps/linux/alpha/bits/statfs.h | 67 + .../libc/sysdeps/linux/alpha/bits/statvfs.h | 96 + .../libc/sysdeps/linux/alpha/bits/syscalls.h | 257 + .../libc/sysdeps/linux/alpha/bits/termios.h | 226 + .../libc/sysdeps/linux/alpha/bits/typesizes.h | 66 + .../linux/alpha/bits/uClibc_arch_features.h | 47 + .../sysdeps/linux/alpha/bits/uClibc_clk_tck.h | 8 + .../sysdeps/linux/alpha/bits/uClibc_page.h | 28 + .../libc/sysdeps/linux/alpha/bits/wordsize.h | 30 + .../uclibc/libc/sysdeps/linux/alpha/brk.S | 82 + .../libc/sysdeps/linux/alpha/bsd-_setjmp.S | 1 + .../libc/sysdeps/linux/alpha/bsd-setjmp.S | 1 + .../uclibc/libc/sysdeps/linux/alpha/clone.S | 95 + .../uclibc/libc/sysdeps/linux/alpha/crt1.S | 97 + .../uclibc/libc/sysdeps/linux/alpha/crti.S | 43 + .../uclibc/libc/sysdeps/linux/alpha/crtn.S | 13 + .../uclibc/libc/sysdeps/linux/alpha/divl.S | 6 + .../uclibc/libc/sysdeps/linux/alpha/divq.S | 6 + .../uclibc/libc/sysdeps/linux/alpha/divrem.h | 198 + .../libc/sysdeps/linux/alpha/fpu_control.h | 108 + .../uclibc/libc/sysdeps/linux/alpha/pipe.S | 48 + .../uclibc/libc/sysdeps/linux/alpha/reml.S | 6 + .../uclibc/libc/sysdeps/linux/alpha/remq.S | 6 + .../uclibc/libc/sysdeps/linux/alpha/setjmp.S | 91 + .../libc/sysdeps/linux/alpha/sigprocmask.c | 62 + .../libc/sysdeps/linux/alpha/sys/acct.h | 66 + .../uclibc/libc/sysdeps/linux/alpha/sys/io.h | 96 + .../libc/sysdeps/linux/alpha/sys/procfs.h | 128 + .../libc/sysdeps/linux/alpha/sys/regdef.h | 47 + .../libc/sysdeps/linux/alpha/sys/ucontext.h | 61 + .../libc/sysdeps/linux/alpha/sys/user.h | 50 + .../uclibc/libc/sysdeps/linux/alpha/syscall.S | 71 + .../uclibc/libc/sysdeps/linux/arm/Makefile | 13 + .../libc/sysdeps/linux/arm/Makefile.arch | 46 + .../uclibc/libc/sysdeps/linux/arm/__longjmp.S | 114 + .../libc/sysdeps/linux/arm/__syscall_error.c | 18 + .../libc/sysdeps/linux/arm/aeabi_assert.c | 28 + .../libc/sysdeps/linux/arm/aeabi_atexit.c | 31 + .../libc/sysdeps/linux/arm/aeabi_errno_addr.c | 25 + .../libc/sysdeps/linux/arm/aeabi_lcsts.c | 99 + .../libc/sysdeps/linux/arm/aeabi_localeconv.c | 26 + .../libc/sysdeps/linux/arm/aeabi_math.c | 42 + .../libc/sysdeps/linux/arm/aeabi_mb_cur_max.c | 31 + .../libc/sysdeps/linux/arm/aeabi_memclr.c | 32 + .../libc/sysdeps/linux/arm/aeabi_memcpy.c | 33 + .../libc/sysdeps/linux/arm/aeabi_memmove.c | 33 + .../libc/sysdeps/linux/arm/aeabi_memset.c | 32 + .../sysdeps/linux/arm/aeabi_sighandlers.S | 52 + .../sysdeps/linux/arm/aeabi_unwind_cpp_pr1.c | 40 + .../libc/sysdeps/linux/arm/bits/arm_asm.h | 28 + .../libc/sysdeps/linux/arm/bits/armsigctx.h | 73 + .../libc/sysdeps/linux/arm/bits/endian.h | 19 + .../libc/sysdeps/linux/arm/bits/fcntl.h | 238 + .../uclibc/libc/sysdeps/linux/arm/bits/fenv.h | 99 + .../libc/sysdeps/linux/arm/bits/huge_val.h | 72 + .../libc/sysdeps/linux/arm/bits/kernel_stat.h | 68 + .../sysdeps/linux/arm/bits/kernel_types.h | 44 + .../libc/sysdeps/linux/arm/bits/mathdef.h | 46 + .../libc/sysdeps/linux/arm/bits/setjmp.h | 52 + .../uclibc/libc/sysdeps/linux/arm/bits/shm.h | 103 + .../sysdeps/linux/arm/bits/sigcontextinfo.h | 51 + .../libc/sysdeps/linux/arm/bits/stackinfo.h | 28 + .../libc/sysdeps/linux/arm/bits/syscalls.h | 139 + .../linux/arm/bits/uClibc_arch_features.h | 51 + .../libc/sysdeps/linux/arm/bits/wordsize.h | 19 + .../uclibc/libc/sysdeps/linux/arm/brk.c | 41 + .../libc/sysdeps/linux/arm/bsd-_setjmp.S | 61 + .../libc/sysdeps/linux/arm/bsd-setjmp.S | 61 + .../uclibc/libc/sysdeps/linux/arm/clone.S | 138 + .../uclibc/libc/sysdeps/linux/arm/crt1.S | 253 + .../uclibc/libc/sysdeps/linux/arm/crti.S | 87 + .../uclibc/libc/sysdeps/linux/arm/crtn.S | 33 + .../libc/sysdeps/linux/arm/find_exidx.c | 80 + .../libc/sysdeps/linux/arm/fpu_control.h | 203 + .../uclibc/libc/sysdeps/linux/arm/ioperm.c | 246 + .../uclibc/libc/sysdeps/linux/arm/iopl.c | 36 + .../sysdeps/linux/arm/libc-aeabi_read_tp.S | 1 + .../sysdeps/linux/arm/libc-thumb_atomics.S | 1 + .../uclibc/libc/sysdeps/linux/arm/mmap.c | 74 + .../uclibc/libc/sysdeps/linux/arm/mmap64.S | 142 + .../libc/sysdeps/linux/arm/posix_fadvise.c | 49 + .../libc/sysdeps/linux/arm/posix_fadvise64.c | 59 + .../uclibc/libc/sysdeps/linux/arm/setjmp.S | 101 + .../uclibc/libc/sysdeps/linux/arm/sigaction.c | 101 + .../libc/sysdeps/linux/arm/sigrestorer.S | 89 + .../uclibc/libc/sysdeps/linux/arm/sys/elf.h | 26 + .../uclibc/libc/sysdeps/linux/arm/sys/io.h | 49 + .../libc/sysdeps/linux/arm/sys/procfs.h | 123 + .../libc/sysdeps/linux/arm/sys/ucontext.h | 97 + .../uclibc/libc/sysdeps/linux/arm/sys/user.h | 72 + .../libc/sysdeps/linux/arm/syscall-eabi.S | 73 + .../uclibc/libc/sysdeps/linux/arm/syscall.c | 53 + .../uclibc/libc/sysdeps/linux/arm/sysdep.h | 367 + .../uclibc/libc/sysdeps/linux/arm/vfork.S | 108 + .../uclibc/libc/sysdeps/linux/avr32/Makefile | 25 + .../libc/sysdeps/linux/avr32/Makefile.arch | 11 + .../libc/sysdeps/linux/avr32/__longjmp.S | 21 + .../libc/sysdeps/linux/avr32/bits/atomic.h | 120 + .../libc/sysdeps/linux/avr32/bits/endian.h | 7 + .../libc/sysdeps/linux/avr32/bits/fcntl.h | 215 + .../sysdeps/linux/avr32/bits/kernel_stat.h | 57 + .../sysdeps/linux/avr32/bits/kernel_types.h | 55 + .../libc/sysdeps/linux/avr32/bits/setjmp.h | 30 + .../libc/sysdeps/linux/avr32/bits/stackinfo.h | 28 + .../libc/sysdeps/linux/avr32/bits/syscalls.h | 54 + .../linux/avr32/bits/uClibc_arch_features.h | 48 + .../libc/sysdeps/linux/avr32/bits/wordsize.h | 1 + .../uclibc/libc/sysdeps/linux/avr32/brk.c | 30 + .../libc/sysdeps/linux/avr32/bsd-_setjmp.S | 16 + .../libc/sysdeps/linux/avr32/bsd-setjmp.S | 16 + .../uclibc/libc/sysdeps/linux/avr32/clone.c | 42 + .../uclibc/libc/sysdeps/linux/avr32/crt1.S | 97 + .../uclibc/libc/sysdeps/linux/avr32/crti.S | 26 + .../uclibc/libc/sysdeps/linux/avr32/crtn.S | 12 + .../uclibc/libc/sysdeps/linux/avr32/mmap.c | 32 + .../uclibc/libc/sysdeps/linux/avr32/prctl.c | 36 + .../uclibc/libc/sysdeps/linux/avr32/setjmp.S | 29 + .../libc/sysdeps/linux/avr32/sigaction.c | 43 + .../libc/sysdeps/linux/avr32/sigrestorer.S | 15 + .../uclibc/libc/sysdeps/linux/avr32/sys/elf.h | 26 + .../libc/sysdeps/linux/avr32/sys/procfs.h | 123 + .../libc/sysdeps/linux/avr32/sys/ucontext.h | 90 + .../libc/sysdeps/linux/avr32/sys/user.h | 46 + .../uclibc/libc/sysdeps/linux/avr32/syscall.S | 71 + .../uclibc/libc/sysdeps/linux/avr32/vfork.S | 58 + .../uclibc/libc/sysdeps/linux/bfin/Makefile | 13 + .../libc/sysdeps/linux/bfin/Makefile.arch | 13 + .../libc/sysdeps/linux/bfin/__longjmp.S | 107 + .../libc/sysdeps/linux/bfin/bfin_fixed_code.h | 155 + .../libc/sysdeps/linux/bfin/bfin_l1layout.h | 17 + .../libc/sysdeps/linux/bfin/bfin_sram.h | 31 + .../libc/sysdeps/linux/bfin/bits/byteswap.h | 34 + .../libc/sysdeps/linux/bfin/bits/elf-fdpic.h | 115 + .../libc/sysdeps/linux/bfin/bits/endian.h | 7 + .../libc/sysdeps/linux/bfin/bits/fcntl.h | 238 + .../libc/sysdeps/linux/bfin/bits/huge_val.h | 56 + .../sysdeps/linux/bfin/bits/kernel_stat.h | 53 + .../sysdeps/linux/bfin/bits/kernel_types.h | 44 + .../libc/sysdeps/linux/bfin/bits/setjmp.h | 57 + .../sysdeps/linux/bfin/bits/sigcontextinfo.h | 26 + .../libc/sysdeps/linux/bfin/bits/stackinfo.h | 28 + .../libc/sysdeps/linux/bfin/bits/syscalls.h | 46 + .../libc/sysdeps/linux/bfin/bits/typesizes.h | 66 + .../linux/bfin/bits/uClibc_arch_features.h | 48 + .../libc/sysdeps/linux/bfin/bits/wordsize.h | 19 + .../libc/sysdeps/linux/bfin/bsd-_setjmp.S | 99 + .../libc/sysdeps/linux/bfin/bsdsetjmp.c | 103 + .../uclibc/libc/sysdeps/linux/bfin/clone.c | 45 + .../uclibc/libc/sysdeps/linux/bfin/crt1.S | 168 + .../uclibc/libc/sysdeps/linux/bfin/crti.S | 64 + .../uclibc/libc/sysdeps/linux/bfin/crtn.S | 55 + .../uclibc/libc/sysdeps/linux/bfin/crtreloc.c | 145 + .../libc/sysdeps/linux/bfin/dma-memcpy.c | 6 + .../uclibc/libc/sysdeps/linux/bfin/setjmp.S | 98 + .../libc/sysdeps/linux/bfin/sram-alloc.c | 6 + .../libc/sysdeps/linux/bfin/sram-free.c | 6 + .../uclibc/libc/sysdeps/linux/bfin/sys/elf.h | 26 + .../uclibc/libc/sysdeps/linux/bfin/sys/io.h | 49 + .../libc/sysdeps/linux/bfin/sys/procfs.h | 125 + .../libc/sysdeps/linux/bfin/sys/ucontext.h | 152 + .../uclibc/libc/sysdeps/linux/bfin/sys/user.h | 57 + .../uclibc/libc/sysdeps/linux/bfin/sysdep.h | 21 + .../libc/sysdeps/linux/common/.indent.pro | 33 + .../uclibc/libc/sysdeps/linux/common/Makefile | 13 + .../libc/sysdeps/linux/common/Makefile.in | 138 + .../sysdeps/linux/common/__rt_sigtimedwait.c | 101 + .../sysdeps/linux/common/__rt_sigwaitinfo.c | 98 + .../libc/sysdeps/linux/common/__socketcall.c | 15 + .../sysdeps/linux/common/__syscall_fcntl.c | 90 + .../sysdeps/linux/common/__syscall_fcntl64.c | 30 + .../linux/common/__syscall_rt_sigaction.c | 22 + .../linux/common/__syscall_sigaction.c | 19 + .../uclibc/libc/sysdeps/linux/common/_exit.c | 34 + .../uclibc/libc/sysdeps/linux/common/access.c | 12 + .../uclibc/libc/sysdeps/linux/common/acct.c | 14 + .../libc/sysdeps/linux/common/adjtimex.c | 18 + .../uclibc/libc/sysdeps/linux/common/alarm.c | 39 + .../libc/sysdeps/linux/common/arch_prctl.c | 15 + .../libc/sysdeps/linux/common/bdflush.c | 21 + .../libc/sysdeps/linux/common/bits/atomic.h | 43 + .../linux/common/bits/byteswap-common.h | 108 + .../libc/sysdeps/linux/common/bits/byteswap.h | 1 + .../sysdeps/linux/common/bits/cmathcalls.h | 181 + .../libc/sysdeps/linux/common/bits/confname.h | 681 + .../libc/sysdeps/linux/common/bits/dirent.h | 53 + .../libc/sysdeps/linux/common/bits/dlfcn.h | 67 + .../libc/sysdeps/linux/common/bits/elfclass.h | 14 + .../libc/sysdeps/linux/common/bits/endian.h | 18 + .../sysdeps/linux/common/bits/environments.h | 88 + .../libc/sysdeps/linux/common/bits/errno.h | 62 + .../libc/sysdeps/linux/common/bits/fcntl.h | 3 + .../libc/sysdeps/linux/common/bits/fenv.h | 56 + .../sysdeps/linux/common/bits/fenvinline.h | 8 + .../libc/sysdeps/linux/common/bits/getopt.h | 183 + .../libc/sysdeps/linux/common/bits/huge_val.h | 55 + .../sysdeps/linux/common/bits/huge_valf.h | 53 + .../sysdeps/linux/common/bits/huge_vall.h | 29 + .../libc/sysdeps/linux/common/bits/in.h | 172 + .../libc/sysdeps/linux/common/bits/inf.h | 30 + .../libc/sysdeps/linux/common/bits/initspin.h | 28 + .../sysdeps/linux/common/bits/ioctl-types.h | 78 + .../libc/sysdeps/linux/common/bits/ioctls.h | 109 + .../libc/sysdeps/linux/common/bits/ipc.h | 56 + .../linux/common/bits/kernel-features.h | 472 + .../linux/common/bits/kernel_sigaction.h | 36 + .../sysdeps/linux/common/bits/kernel_stat.h | 2 + .../sysdeps/linux/common/bits/kernel_types.h | 20 + .../sysdeps/linux/common/bits/local_lim.h | 95 + .../libc/sysdeps/linux/common/bits/locale.h | 44 + .../sysdeps/linux/common/bits/mathcalls.h | 380 + .../libc/sysdeps/linux/common/bits/mathdef.h | 43 + .../sysdeps/linux/common/bits/mathinline.h | 12 + .../sysdeps/linux/common/bits/mman-common.h | 109 + .../libc/sysdeps/linux/common/bits/mman.h | 1 + .../libc/sysdeps/linux/common/bits/mqueue.h | 32 + .../libc/sysdeps/linux/common/bits/msq.h | 77 + .../libc/sysdeps/linux/common/bits/nan.h | 53 + .../libc/sysdeps/linux/common/bits/netdb.h | 33 + .../libc/sysdeps/linux/common/bits/poll.h | 50 + .../sysdeps/linux/common/bits/posix1_lim.h | 169 + .../sysdeps/linux/common/bits/posix2_lim.h | 91 + .../sysdeps/linux/common/bits/posix_opt.h | 190 + .../libc/sysdeps/linux/common/bits/resource.h | 225 + .../libc/sysdeps/linux/common/bits/sched.h | 132 + .../libc/sysdeps/linux/common/bits/select.h | 35 + .../libc/sysdeps/linux/common/bits/sem.h | 87 + .../libc/sysdeps/linux/common/bits/setjmp.h | 2 + .../libc/sysdeps/linux/common/bits/shm.h | 103 + .../sysdeps/linux/common/bits/sigaction.h | 69 + .../sysdeps/linux/common/bits/sigcontext.h | 32 + .../linux/common/bits/sigcontextinfo.h | 27 + .../libc/sysdeps/linux/common/bits/siginfo.h | 313 + .../libc/sysdeps/linux/common/bits/signum.h | 58 + .../libc/sysdeps/linux/common/bits/sigset.h | 223 + .../libc/sysdeps/linux/common/bits/sigstack.h | 55 + .../sysdeps/linux/common/bits/sigthread.h | 38 + .../libc/sysdeps/linux/common/bits/sockaddr.h | 40 + .../libc/sysdeps/linux/common/bits/socket.h | 344 + .../libc/sysdeps/linux/common/bits/stab.def | 234 + .../sysdeps/linux/common/bits/stackinfo.h | 34 + .../libc/sysdeps/linux/common/bits/stat.h | 170 + .../libc/sysdeps/linux/common/bits/statfs.h | 67 + .../libc/sysdeps/linux/common/bits/statvfs.h | 107 + .../libc/sysdeps/linux/common/bits/stdio.h | 23 + .../sysdeps/linux/common/bits/stdio_lim.h | 41 + .../linux/common/bits/syscalls-common.h | 112 + .../libc/sysdeps/linux/common/bits/syscalls.h | 9 + .../libc/sysdeps/linux/common/bits/termios.h | 219 + .../libc/sysdeps/linux/common/bits/time.h | 79 + .../libc/sysdeps/linux/common/bits/types.h | 213 + .../sysdeps/linux/common/bits/typesizes.h | 66 + .../sysdeps/linux/common/bits/uClibc_alloc.h | 26 + .../linux/common/bits/uClibc_arch_features.h | 50 + .../linux/common/bits/uClibc_charclass.h | 40 + .../linux/common/bits/uClibc_clk_tck.h | 8 + .../sysdeps/linux/common/bits/uClibc_ctype.h | 199 + .../sysdeps/linux/common/bits/uClibc_errno.h | 43 + .../sysdeps/linux/common/bits/uClibc_fpmax.h | 122 + .../linux/common/bits/uClibc_local_lim.h | 33 + .../sysdeps/linux/common/bits/uClibc_locale.h | 374 + .../sysdeps/linux/common/bits/uClibc_mutex.h | 157 + .../sysdeps/linux/common/bits/uClibc_page.h | 29 + .../linux/common/bits/uClibc_pthread.h | 51 + .../sysdeps/linux/common/bits/uClibc_stdio.h | 527 + .../linux/common/bits/uClibc_touplow.h | 55 + .../linux/common/bits/uClibc_uintmaxtostr.h | 116 + .../sysdeps/linux/common/bits/uClibc_uwchar.h | 57 + .../linux/common/bits/uClibc_va_copy.h | 40 + .../libc/sysdeps/linux/common/bits/uio.h | 51 + .../libc/sysdeps/linux/common/bits/ustat.h | 31 + .../libc/sysdeps/linux/common/bits/utmp.h | 125 + .../libc/sysdeps/linux/common/bits/utmpx.h | 103 + .../libc/sysdeps/linux/common/bits/utsname.h | 29 + .../sysdeps/linux/common/bits/waitflags.h | 38 + .../sysdeps/linux/common/bits/waitstatus.h | 106 + .../libc/sysdeps/linux/common/bits/wchar.h | 26 + .../libc/sysdeps/linux/common/bits/wordsize.h | 6 + .../sysdeps/linux/common/bits/xopen_lim.h | 150 + .../uclibc/libc/sysdeps/linux/common/brk.c | 32 + .../uclibc/libc/sysdeps/linux/common/capget.c | 20 + .../uclibc/libc/sysdeps/linux/common/capset.c | 20 + .../uclibc/libc/sysdeps/linux/common/chdir.c | 22 + .../uclibc/libc/sysdeps/linux/common/chmod.c | 21 + .../uclibc/libc/sysdeps/linux/common/chown.c | 40 + .../uclibc/libc/sysdeps/linux/common/chroot.c | 23 + .../libc/sysdeps/linux/common/clock_getres.c | 43 + .../libc/sysdeps/linux/common/clock_gettime.c | 41 + .../libc/sysdeps/linux/common/clock_settime.c | 41 + .../uclibc/libc/sysdeps/linux/common/close.c | 20 + .../libc/sysdeps/linux/common/cmsg_nxthdr.c | 44 + .../uclibc/libc/sysdeps/linux/common/creat.c | 15 + .../libc/sysdeps/linux/common/creat64.c | 30 + .../libc/sysdeps/linux/common/create_module.c | 59 + .../libc/sysdeps/linux/common/delete_module.c | 19 + .../libc/sysdeps/linux/common/dl-osinfo.h | 65 + .../uclibc/libc/sysdeps/linux/common/dup.c | 11 + .../uclibc/libc/sysdeps/linux/common/dup2.c | 15 + .../uclibc/libc/sysdeps/linux/common/epoll.c | 50 + .../uclibc/libc/sysdeps/linux/common/execve.c | 17 + .../libc/sysdeps/linux/common/faccessat.c | 16 + .../uclibc/libc/sysdeps/linux/common/fchdir.c | 15 + .../uclibc/libc/sysdeps/linux/common/fchmod.c | 20 + .../libc/sysdeps/linux/common/fchmodat.c | 16 + .../uclibc/libc/sysdeps/linux/common/fchown.c | 38 + .../libc/sysdeps/linux/common/fchownat.c | 16 + .../libc/sysdeps/linux/common/fdatasync.c | 50 + .../uclibc/libc/sysdeps/linux/common/flock.c | 19 + .../uclibc/libc/sysdeps/linux/common/fork.c | 35 + .../libc/sysdeps/linux/common/fpu_control.h | 41 + .../uclibc/libc/sysdeps/linux/common/fstat.c | 34 + .../libc/sysdeps/linux/common/fstat64.c | 34 + .../libc/sysdeps/linux/common/fstatat.c | 32 + .../libc/sysdeps/linux/common/fstatat64.c | 36 + .../libc/sysdeps/linux/common/fstatfs.c | 31 + .../uclibc/libc/sysdeps/linux/common/fsync.c | 37 + .../libc/sysdeps/linux/common/ftruncate.c | 15 + .../libc/sysdeps/linux/common/ftruncate64.c | 71 + .../libc/sysdeps/linux/common/futimens.c | 29 + .../libc/sysdeps/linux/common/futimesat.c | 16 + .../sysdeps/linux/common/get_kernel_syms.c | 22 + .../uclibc/libc/sysdeps/linux/common/getcwd.c | 198 + .../libc/sysdeps/linux/common/getdents.c | 174 + .../libc/sysdeps/linux/common/getdents64.c | 105 + .../libc/sysdeps/linux/common/getdirname.c | 58 + .../libc/sysdeps/linux/common/getdomainname.c | 49 + .../libc/sysdeps/linux/common/getdtablesize.c | 30 + .../libc/sysdeps/linux/common/getegid.c | 33 + .../libc/sysdeps/linux/common/geteuid.c | 34 + .../uclibc/libc/sysdeps/linux/common/getgid.c | 23 + .../libc/sysdeps/linux/common/getgroups.c | 60 + .../libc/sysdeps/linux/common/gethostname.c | 33 + .../libc/sysdeps/linux/common/getitimer.c | 12 + .../libc/sysdeps/linux/common/getpagesize.c | 47 + .../libc/sysdeps/linux/common/getpgid.c | 25 + .../libc/sysdeps/linux/common/getpgrp.c | 28 + .../uclibc/libc/sysdeps/linux/common/getpid.c | 20 + .../libc/sysdeps/linux/common/getppid.c | 19 + .../libc/sysdeps/linux/common/getpriority.c | 30 + .../libc/sysdeps/linux/common/getresgid.c | 38 + .../libc/sysdeps/linux/common/getresuid.c | 38 + .../libc/sysdeps/linux/common/getrlimit.c | 67 + .../libc/sysdeps/linux/common/getrlimit64.c | 50 + .../libc/sysdeps/linux/common/getrusage.c | 13 + .../uclibc/libc/sysdeps/linux/common/getsid.c | 23 + .../libc/sysdeps/linux/common/gettimeofday.c | 18 + .../uclibc/libc/sysdeps/linux/common/getuid.c | 23 + .../libc/sysdeps/linux/common/hp-timing.h | 83 + .../libc/sysdeps/linux/common/init_module.c | 25 + .../libc/sysdeps/linux/common/inotify.c | 28 + .../uclibc/libc/sysdeps/linux/common/ioctl.c | 46 + .../uclibc/libc/sysdeps/linux/common/ioperm.c | 22 + .../uclibc/libc/sysdeps/linux/common/iopl.c | 15 + .../uclibc/libc/sysdeps/linux/common/kill.c | 21 + .../libc/sysdeps/linux/common/klogctl.c | 18 + .../uclibc/libc/sysdeps/linux/common/lchown.c | 38 + .../libc/sysdeps/linux/common/libgcc_s.h | 2 + .../uclibc/libc/sysdeps/linux/common/link.c | 12 + .../uclibc/libc/sysdeps/linux/common/linkat.c | 16 + .../uclibc/libc/sysdeps/linux/common/llseek.c | 37 + .../libc/sysdeps/linux/common/longjmp.c | 49 + .../uclibc/libc/sysdeps/linux/common/lseek.c | 27 + .../uclibc/libc/sysdeps/linux/common/lstat.c | 35 + .../libc/sysdeps/linux/common/lstat64.c | 35 + .../libc/sysdeps/linux/common/lutimes.c | 38 + .../libc/sysdeps/linux/common/madvise.c | 14 + .../libc/sysdeps/linux/common/mincore.c | 15 + .../uclibc/libc/sysdeps/linux/common/mkdir.c | 22 + .../libc/sysdeps/linux/common/mkdirat.c | 16 + .../uclibc/libc/sysdeps/linux/common/mkfifo.c | 30 + .../libc/sysdeps/linux/common/mkfifoat.c | 19 + .../uclibc/libc/sysdeps/linux/common/mknod.c | 22 + .../libc/sysdeps/linux/common/mknodat.c | 25 + .../uclibc/libc/sysdeps/linux/common/mlock.c | 14 + .../libc/sysdeps/linux/common/mlockall.c | 14 + .../uclibc/libc/sysdeps/linux/common/mmap.c | 71 + .../uclibc/libc/sysdeps/linux/common/mmap64.c | 72 + .../libc/sysdeps/linux/common/modify_ldt.c | 15 + .../uclibc/libc/sysdeps/linux/common/mount.c | 14 + .../libc/sysdeps/linux/common/mprotect.c | 15 + .../uclibc/libc/sysdeps/linux/common/mremap.c | 28 + .../uclibc/libc/sysdeps/linux/common/msync.c | 45 + .../libc/sysdeps/linux/common/munlock.c | 14 + .../libc/sysdeps/linux/common/munlockall.c | 16 + .../uclibc/libc/sysdeps/linux/common/munmap.c | 16 + .../libc/sysdeps/linux/common/nanosleep.c | 41 + .../uclibc/libc/sysdeps/linux/common/nice.c | 75 + .../libc/sysdeps/linux/common/noophooks.c | 29 + .../libc/sysdeps/linux/common/not-cancel.h | 60 + .../libc/sysdeps/linux/common/ntp_gettime.c | 33 + .../uclibc/libc/sysdeps/linux/common/open.c | 39 + .../uclibc/libc/sysdeps/linux/common/open64.c | 57 + .../uclibc/libc/sysdeps/linux/common/openat.c | 25 + .../libc/sysdeps/linux/common/openat64.c | 32 + .../uclibc/libc/sysdeps/linux/common/pause.c | 41 + .../libc/sysdeps/linux/common/personality.c | 12 + .../uclibc/libc/sysdeps/linux/common/pipe.c | 15 + .../libc/sysdeps/linux/common/pivot_root.c | 21 + .../uclibc/libc/sysdeps/linux/common/poll.c | 230 + .../libc/sysdeps/linux/common/posix_fadvise.c | 36 + .../sysdeps/linux/common/posix_fadvise64.c | 71 + .../uclibc/libc/sysdeps/linux/common/ppoll.c | 55 + .../uclibc/libc/sysdeps/linux/common/prctl.c | 17 + .../libc/sysdeps/linux/common/pread_write.c | 187 + .../libc/sysdeps/linux/common/pselect.c | 94 + .../uclibc/libc/sysdeps/linux/common/ptrace.c | 43 + .../libc/sysdeps/linux/common/query_module.c | 23 + .../libc/sysdeps/linux/common/quotactl.c | 16 + .../uclibc/libc/sysdeps/linux/common/read.c | 19 + .../libc/sysdeps/linux/common/readahead.c | 58 + .../libc/sysdeps/linux/common/readlink.c | 14 + .../libc/sysdeps/linux/common/readlinkat.c | 16 + .../uclibc/libc/sysdeps/linux/common/readv.c | 50 + .../uclibc/libc/sysdeps/linux/common/reboot.c | 17 + .../sysdeps/linux/common/remap_file_pages.c | 16 + .../uclibc/libc/sysdeps/linux/common/rename.c | 24 + .../libc/sysdeps/linux/common/renameat.c | 16 + .../uclibc/libc/sysdeps/linux/common/rmdir.c | 15 + .../uclibc/libc/sysdeps/linux/common/sbrk.c | 34 + .../linux/common/sched_get_priority_max.c | 12 + .../linux/common/sched_get_priority_min.c | 12 + .../sysdeps/linux/common/sched_getaffinity.c | 54 + .../sysdeps/linux/common/sched_getparam.c | 21 + .../sysdeps/linux/common/sched_getscheduler.c | 20 + .../linux/common/sched_rr_get_interval.c | 21 + .../sysdeps/linux/common/sched_setaffinity.c | 85 + .../sysdeps/linux/common/sched_setparam.c | 21 + .../sysdeps/linux/common/sched_setscheduler.c | 21 + .../libc/sysdeps/linux/common/sched_yield.c | 12 + .../uclibc/libc/sysdeps/linux/common/select.c | 94 + .../libc/sysdeps/linux/common/sendfile.c | 23 + .../libc/sysdeps/linux/common/sendfile64.c | 24 + .../libc/sysdeps/linux/common/setdomainname.c | 14 + .../libc/sysdeps/linux/common/setegid.c | 33 + .../libc/sysdeps/linux/common/seteuid.c | 39 + .../libc/sysdeps/linux/common/setfsgid.c | 35 + .../libc/sysdeps/linux/common/setfsuid.c | 35 + .../uclibc/libc/sysdeps/linux/common/setgid.c | 35 + .../libc/sysdeps/linux/common/setgroups.c | 64 + .../libc/sysdeps/linux/common/sethostname.c | 14 + .../libc/sysdeps/linux/common/setitimer.c | 16 + .../libc/sysdeps/linux/common/setpgid.c | 25 + .../libc/sysdeps/linux/common/setpgrp.c | 14 + .../libc/sysdeps/linux/common/setpriority.c | 15 + .../libc/sysdeps/linux/common/setregid.c | 40 + .../libc/sysdeps/linux/common/setresgid.c | 41 + .../libc/sysdeps/linux/common/setresuid.c | 41 + .../libc/sysdeps/linux/common/setreuid.c | 40 + .../libc/sysdeps/linux/common/setrlimit.c | 69 + .../libc/sysdeps/linux/common/setrlimit64.c | 48 + .../uclibc/libc/sysdeps/linux/common/setsid.c | 15 + .../libc/sysdeps/linux/common/settimeofday.c | 19 + .../uclibc/libc/sysdeps/linux/common/setuid.c | 35 + .../libc/sysdeps/linux/common/sigaltstack.c | 17 + .../libc/sysdeps/linux/common/signalfd.c | 41 + .../libc/sysdeps/linux/common/sigpending.c | 27 + .../libc/sysdeps/linux/common/sigprocmask.c | 89 + .../libc/sysdeps/linux/common/sigqueue.c | 52 + .../libc/sysdeps/linux/common/sigsuspend.c | 59 + .../uclibc/libc/sysdeps/linux/common/splice.c | 23 + .../libc/sysdeps/linux/common/ssp-local.c | 35 + .../uclibc/libc/sysdeps/linux/common/ssp.c | 117 + .../uclibc/libc/sysdeps/linux/common/stat.c | 36 + .../uclibc/libc/sysdeps/linux/common/stat64.c | 34 + .../uclibc/libc/sysdeps/linux/common/statfs.c | 22 + .../uclibc/libc/sysdeps/linux/common/stime.c | 32 + .../libc/sysdeps/linux/common/swapoff.c | 17 + .../uclibc/libc/sysdeps/linux/common/swapon.c | 17 + .../libc/sysdeps/linux/common/symlink.c | 14 + .../libc/sysdeps/linux/common/symlinkat.c | 16 + .../uclibc/libc/sysdeps/linux/common/sync.c | 19 + .../sysdeps/linux/common/sync_file_range.c | 33 + .../libc/sysdeps/linux/common/sys/acct.h | 77 + .../libc/sysdeps/linux/common/sys/epoll.h | 112 + .../libc/sysdeps/linux/common/sys/inotify.h | 105 + .../libc/sysdeps/linux/common/sys/prctl.h | 32 + .../libc/sysdeps/linux/common/sys/ptrace.h | 168 + .../libc/sysdeps/linux/common/sys/timerfd.h | 60 + .../libc/sysdeps/linux/common/sys/user.h | 1 + .../libc/sysdeps/linux/common/syscall.c | 12 + .../libc/sysdeps/linux/common/syscalls.h | 24 + .../uclibc/libc/sysdeps/linux/common/sysctl.c | 38 + .../uclibc/libc/sysdeps/linux/common/sysdep.h | 170 + .../uclibc/libc/sysdeps/linux/common/sysfs.c | 17 + .../libc/sysdeps/linux/common/sysinfo.c | 12 + .../uclibc/libc/sysdeps/linux/common/tee.c | 16 + .../uclibc/libc/sysdeps/linux/common/time.c | 34 + .../libc/sysdeps/linux/common/timerfd.c | 32 + .../uclibc/libc/sysdeps/linux/common/times.c | 15 + .../libc/sysdeps/linux/common/truncate.c | 15 + .../libc/sysdeps/linux/common/truncate64.c | 68 + .../uclibc/libc/sysdeps/linux/common/ulimit.c | 56 + .../uclibc/libc/sysdeps/linux/common/umask.c | 19 + .../uclibc/libc/sysdeps/linux/common/umount.c | 41 + .../libc/sysdeps/linux/common/umount2.c | 23 + .../uclibc/libc/sysdeps/linux/common/uname.c | 15 + .../uclibc/libc/sysdeps/linux/common/unlink.c | 15 + .../libc/sysdeps/linux/common/unlinkat.c | 16 + .../uclibc/libc/sysdeps/linux/common/uselib.c | 18 + .../uclibc/libc/sysdeps/linux/common/ustat.c | 26 + .../uclibc/libc/sysdeps/linux/common/utime.c | 35 + .../libc/sysdeps/linux/common/utimensat.c | 18 + .../uclibc/libc/sysdeps/linux/common/utimes.c | 35 + .../uclibc/libc/sysdeps/linux/common/vfork.c | 33 + .../libc/sysdeps/linux/common/vhangup.c | 14 + .../libc/sysdeps/linux/common/vmsplice.c | 23 + .../uclibc/libc/sysdeps/linux/common/wait.c | 44 + .../uclibc/libc/sysdeps/linux/common/wait3.c | 24 + .../uclibc/libc/sysdeps/linux/common/wait4.c | 25 + .../uclibc/libc/sysdeps/linux/common/waitid.c | 81 + .../libc/sysdeps/linux/common/waitpid.c | 37 + .../uclibc/libc/sysdeps/linux/common/write.c | 25 + .../uclibc/libc/sysdeps/linux/common/writev.c | 50 + .../uclibc/libc/sysdeps/linux/common/xattr.c | 164 + .../libc/sysdeps/linux/common/xstatconv.c | 90 + .../libc/sysdeps/linux/common/xstatconv.h | 33 + .../uclibc/libc/sysdeps/linux/cris/Makefile | 13 + .../libc/sysdeps/linux/cris/Makefile.arch | 13 + .../libc/sysdeps/linux/cris/__init_brk.c | 32 + .../libc/sysdeps/linux/cris/__longjmp.S | 62 + .../libc/sysdeps/linux/cris/bits/byteswap.h | 20 + .../libc/sysdeps/linux/cris/bits/endian.h | 7 + .../libc/sysdeps/linux/cris/bits/fcntl.h | 239 + .../sysdeps/linux/cris/bits/kernel_stat.h | 62 + .../sysdeps/linux/cris/bits/kernel_types.h | 46 + .../libc/sysdeps/linux/cris/bits/setjmp.h | 66 + .../libc/sysdeps/linux/cris/bits/stackinfo.h | 28 + .../libc/sysdeps/linux/cris/bits/syscalls.h | 95 + .../libc/sysdeps/linux/cris/bits/termios.h | 215 + .../linux/cris/bits/uClibc_arch_features.h | 48 + .../sysdeps/linux/cris/bits/uClibc_page.h | 34 + .../libc/sysdeps/linux/cris/bits/wordsize.h | 19 + .../uclibc/libc/sysdeps/linux/cris/brk.c | 37 + .../uclibc/libc/sysdeps/linux/cris/clone.S | 96 + .../uclibc/libc/sysdeps/linux/cris/crt1.S | 56 + .../uclibc/libc/sysdeps/linux/cris/crti.S | 37 + .../uclibc/libc/sysdeps/linux/cris/crtn.S | 21 + .../uclibc/libc/sysdeps/linux/cris/fork.c | 18 + .../uclibc/libc/sysdeps/linux/cris/libc.map | 3 + .../uclibc/libc/sysdeps/linux/cris/sbrk.c | 41 + .../uclibc/libc/sysdeps/linux/cris/setjmp.S | 84 + .../libc/sysdeps/linux/cris/sys/procfs.h | 115 + .../libc/sysdeps/linux/cris/sys/ucontext.h | 95 + .../uclibc/libc/sysdeps/linux/cris/syscall.S | 61 + .../uclibc/libc/sysdeps/linux/cris/sysdep.S | 80 + .../uclibc/libc/sysdeps/linux/cris/sysdep.h | 149 + .../uclibc/libc/sysdeps/linux/e1/Makefile | 56 + .../libc/sysdeps/linux/e1/bits/endian.h | 7 + .../uclibc/libc/sysdeps/linux/e1/bits/fcntl.h | 233 + .../uclibc/libc/sysdeps/linux/e1/bits/fenv.h | 88 + .../libc/sysdeps/linux/e1/bits/fenvinline.h | 298 + .../libc/sysdeps/linux/e1/bits/kernel_stat.h | 54 + .../libc/sysdeps/linux/e1/bits/kernel_types.h | 46 + .../uclibc/libc/sysdeps/linux/e1/bits/proto.h | 5 + .../libc/sysdeps/linux/e1/bits/setjmp.h | 22 + .../libc/sysdeps/linux/e1/bits/syscalls.h | 17 + .../linux/e1/bits/uClibc_arch_features.h | 48 + .../libc/sysdeps/linux/e1/bits/unistd.h | 464 + .../libc/sysdeps/linux/e1/bits/wordsize.h | 22 + .../uclibc/libc/sysdeps/linux/e1/crt0.S | 17 + .../uclibc/libc/sysdeps/linux/e1/crt1.c | 48 + .../uclibc/libc/sysdeps/linux/e1/longjmp.c | 76 + .../uclibc/libc/sysdeps/linux/e1/setjmp.c | 55 + .../uclibc/libc/sysdeps/linux/e1/sys/procfs.h | 31 + .../uclibc/libc/sysdeps/linux/e1/sys/reg.h | 25 + .../libc/sysdeps/linux/e1/sys/ucontext.h | 109 + .../uclibc/libc/sysdeps/linux/e1/syscalls.c | 11 + .../uclibc/libc/sysdeps/linux/e1/vfork.c | 14 + .../uclibc/libc/sysdeps/linux/frv/Makefile | 58 + .../libc/sysdeps/linux/frv/__init_brk.c | 26 + .../uclibc/libc/sysdeps/linux/frv/__longjmp.S | 83 + .../libc/sysdeps/linux/frv/bits/elf-fdpic.h | 115 + .../libc/sysdeps/linux/frv/bits/endian.h | 7 + .../libc/sysdeps/linux/frv/bits/fcntl.h | 217 + .../libc/sysdeps/linux/frv/bits/kernel_stat.h | 78 + .../sysdeps/linux/frv/bits/kernel_types.h | 43 + .../libc/sysdeps/linux/frv/bits/setjmp.h | 58 + .../libc/sysdeps/linux/frv/bits/stackinfo.h | 28 + .../uclibc/libc/sysdeps/linux/frv/bits/stat.h | 159 + .../libc/sysdeps/linux/frv/bits/syscalls.h | 139 + .../linux/frv/bits/uClibc_arch_features.h | 48 + .../libc/sysdeps/linux/frv/bits/uClibc_page.h | 32 + .../libc/sysdeps/linux/frv/bits/wordsize.h | 19 + .../uclibc/libc/sysdeps/linux/frv/brk.c | 27 + .../uclibc/libc/sysdeps/linux/frv/clone.S | 83 + .../uclibc/libc/sysdeps/linux/frv/crt0.S | 125 + .../uclibc/libc/sysdeps/linux/frv/crti.S | 50 + .../uclibc/libc/sysdeps/linux/frv/crtn.S | 42 + .../uclibc/libc/sysdeps/linux/frv/crtreloc.c | 120 + .../libc/sysdeps/linux/frv/dl-iterate-phdr.c | 42 + .../uclibc/libc/sysdeps/linux/frv/fstat.c | 17 + .../uclibc/libc/sysdeps/linux/frv/fstat64.c | 19 + .../uclibc/libc/sysdeps/linux/frv/lstat.c | 17 + .../uclibc/libc/sysdeps/linux/frv/lstat64.c | 19 + .../uclibc/libc/sysdeps/linux/frv/mmap.c | 50 + .../uclibc/libc/sysdeps/linux/frv/sbrk.c | 25 + .../uclibc/libc/sysdeps/linux/frv/setjmp.S | 90 + .../uclibc/libc/sysdeps/linux/frv/stat.c | 17 + .../uclibc/libc/sysdeps/linux/frv/stat64.c | 19 + .../libc/sysdeps/linux/frv/sys/procfs.h | 125 + .../libc/sysdeps/linux/frv/sys/ptrace.h | 139 + .../libc/sysdeps/linux/frv/sys/ucontext.h | 451 + .../uclibc/libc/sysdeps/linux/frv/syscall.c | 41 + .../uclibc/libc/sysdeps/linux/frv/sysdep.c | 27 + .../uclibc/libc/sysdeps/linux/frv/vfork.S | 47 + .../uclibc/libc/sysdeps/linux/frv/xstatconv.c | 1 + .../uclibc/libc/sysdeps/linux/h8300/Makefile | 65 + .../libc/sysdeps/linux/h8300/__longjmp.S | 22 + .../libc/sysdeps/linux/h8300/bits/byteswap.h | 40 + .../libc/sysdeps/linux/h8300/bits/endian.h | 7 + .../libc/sysdeps/linux/h8300/bits/fcntl.h | 233 + .../sysdeps/linux/h8300/bits/kernel_stat.h | 54 + .../sysdeps/linux/h8300/bits/kernel_types.h | 44 + .../libc/sysdeps/linux/h8300/bits/setjmp.h | 32 + .../sysdeps/linux/h8300/bits/sigcontextinfo.h | 26 + .../libc/sysdeps/linux/h8300/bits/stackinfo.h | 28 + .../libc/sysdeps/linux/h8300/bits/syscalls.h | 151 + .../linux/h8300/bits/uClibc_arch_features.h | 48 + .../libc/sysdeps/linux/h8300/bits/wordsize.h | 1 + .../uclibc/libc/sysdeps/linux/h8300/brk.c | 37 + .../libc/sysdeps/linux/h8300/bsd-_setjmp.S | 27 + .../libc/sysdeps/linux/h8300/bsd-setjmp.S | 30 + .../uclibc/libc/sysdeps/linux/h8300/clone.S | 68 + .../uclibc/libc/sysdeps/linux/h8300/crt0.S | 70 + .../uclibc/libc/sysdeps/linux/h8300/crti.S | 30 + .../uclibc/libc/sysdeps/linux/h8300/crtn.S | 28 + .../uclibc/libc/sysdeps/linux/h8300/float.h | 96 + .../uclibc/libc/sysdeps/linux/h8300/ptrace.c | 36 + .../uclibc/libc/sysdeps/linux/h8300/setjmp.S | 23 + .../libc/sysdeps/linux/h8300/sys/procfs.h | 126 + .../libc/sysdeps/linux/h8300/sys/ucontext.h | 75 + .../uclibc/libc/sysdeps/linux/h8300/vfork.S | 41 + .../uclibc/libc/sysdeps/linux/hppa/Makefile | 13 + .../libc/sysdeps/linux/hppa/Makefile.arch | 11 + .../libc/sysdeps/linux/hppa/__longjmp.S | 74 + .../libc/sysdeps/linux/hppa/__syscall_error.c | 18 + .../uclibc/libc/sysdeps/linux/hppa/add_n.s | 58 + .../libc/sysdeps/linux/hppa/bits/endian.h | 7 + .../libc/sysdeps/linux/hppa/bits/fcntl.h | 229 + .../libc/sysdeps/linux/hppa/bits/fenv.h | 78 + .../uclibc/libc/sysdeps/linux/hppa/bits/ipc.h | 63 + .../linux/hppa/bits/kernel_sigaction.h | 23 + .../sysdeps/linux/hppa/bits/kernel_stat.h | 64 + .../sysdeps/linux/hppa/bits/kernel_types.h | 61 + .../libc/sysdeps/linux/hppa/bits/mman.h | 94 + .../libc/sysdeps/linux/hppa/bits/setjmp.h | 45 + .../libc/sysdeps/linux/hppa/bits/sigaction.h | 66 + .../libc/sysdeps/linux/hppa/bits/signum.h | 62 + .../libc/sysdeps/linux/hppa/bits/stackinfo.h | 28 + .../libc/sysdeps/linux/hppa/bits/syscalls.h | 98 + .../linux/hppa/bits/uClibc_arch_features.h | 47 + .../libc/sysdeps/linux/hppa/bits/wordsize.h | 7 + .../uclibc/libc/sysdeps/linux/hppa/brk.c | 42 + .../libc/sysdeps/linux/hppa/bsd-_setjmp.S | 36 + .../libc/sysdeps/linux/hppa/bsd-setjmp.S | 36 + .../uclibc/libc/sysdeps/linux/hppa/clone.S | 135 + .../uclibc/libc/sysdeps/linux/hppa/crt1.S | 126 + .../uclibc/libc/sysdeps/linux/hppa/crti.S | 24 + .../uclibc/libc/sysdeps/linux/hppa/crtn.S | 34 + .../uclibc/libc/sysdeps/linux/hppa/lshift.s | 66 + .../uclibc/libc/sysdeps/linux/hppa/mmap.c | 19 + .../uclibc/libc/sysdeps/linux/hppa/rshift.s | 63 + .../uclibc/libc/sysdeps/linux/hppa/setjmp.S | 63 + .../uclibc/libc/sysdeps/linux/hppa/sub_n.s | 59 + .../libc/sysdeps/linux/hppa/sys/procfs.h | 113 + .../libc/sysdeps/linux/hppa/sys/ucontext.h | 67 + .../uclibc/libc/sysdeps/linux/hppa/syscall.c | 65 + .../libc/sysdeps/linux/hppa/udiv_qrnnd.s | 286 + .../uclibc/libc/sysdeps/linux/i386/Makefile | 13 + .../libc/sysdeps/linux/i386/Makefile.arch | 21 + .../libc/sysdeps/linux/i386/__longjmp.S | 42 + .../libc/sysdeps/linux/i386/__syscall_error.c | 35 + .../libc/sysdeps/linux/i386/bits/atomic.h | 369 + .../libc/sysdeps/linux/i386/bits/byteswap.h | 56 + .../libc/sysdeps/linux/i386/bits/endian.h | 7 + .../libc/sysdeps/linux/i386/bits/fcntl.h | 239 + .../libc/sysdeps/linux/i386/bits/fenv.h | 90 + .../sysdeps/linux/i386/bits/kernel_stat.h | 53 + .../sysdeps/linux/i386/bits/kernel_types.h | 53 + .../libc/sysdeps/linux/i386/bits/mathdef.h | 50 + .../libc/sysdeps/linux/i386/bits/mathinline.h | 766 + .../libc/sysdeps/linux/i386/bits/select.h | 72 + .../libc/sysdeps/linux/i386/bits/setjmp.h | 46 + .../sysdeps/linux/i386/bits/sigcontextinfo.h | 51 + .../libc/sysdeps/linux/i386/bits/stackinfo.h | 28 + .../libc/sysdeps/linux/i386/bits/syscalls.h | 189 + .../linux/i386/bits/uClibc_arch_features.h | 52 + .../libc/sysdeps/linux/i386/bits/wchar.h | 26 + .../libc/sysdeps/linux/i386/bits/wordsize.h | 25 + .../uclibc/libc/sysdeps/linux/i386/brk.c | 51 + .../libc/sysdeps/linux/i386/bsd-_setjmp.S | 46 + .../libc/sysdeps/linux/i386/bsd-setjmp.S | 60 + .../uclibc/libc/sysdeps/linux/i386/clone.S | 131 + .../uclibc/libc/sysdeps/linux/i386/crt1.S | 140 + .../uclibc/libc/sysdeps/linux/i386/crti.S | 31 + .../uclibc/libc/sysdeps/linux/i386/crtn.S | 27 + .../libc/sysdeps/linux/i386/fpu_control.h | 104 + .../uclibc/libc/sysdeps/linux/i386/mmap.S | 51 + .../uclibc/libc/sysdeps/linux/i386/mmap64.S | 93 + .../libc/sysdeps/linux/i386/posix_fadvise64.S | 108 + .../uclibc/libc/sysdeps/linux/i386/setjmp.S | 58 + .../libc/sysdeps/linux/i386/sigaction.c | 138 + .../libc/sysdeps/linux/i386/sync_file_range.S | 67 + .../libc/sysdeps/linux/i386/sys/debugreg.h | 91 + .../uclibc/libc/sysdeps/linux/i386/sys/elf.h | 26 + .../uclibc/libc/sysdeps/linux/i386/sys/io.h | 184 + .../uclibc/libc/sysdeps/linux/i386/sys/perm.h | 37 + .../libc/sysdeps/linux/i386/sys/procfs.h | 131 + .../uclibc/libc/sysdeps/linux/i386/sys/reg.h | 43 + .../libc/sysdeps/linux/i386/sys/ucontext.h | 129 + .../uclibc/libc/sysdeps/linux/i386/sys/user.h | 101 + .../uclibc/libc/sysdeps/linux/i386/sys/vm86.h | 34 + .../uclibc/libc/sysdeps/linux/i386/syscall.S | 50 + .../uclibc/libc/sysdeps/linux/i386/sysdep.h | 462 + .../uclibc/libc/sysdeps/linux/i386/vfork.S | 41 + .../uclibc/libc/sysdeps/linux/i960/AUTHORS | 4 + .../uclibc/libc/sysdeps/linux/i960/Makefile | 55 + .../uclibc/libc/sysdeps/linux/i960/README | 71 + .../libc/sysdeps/linux/i960/bits/endian.h | 15 + .../libc/sysdeps/linux/i960/bits/fcntl.h | 233 + .../libc/sysdeps/linux/i960/bits/setjmp.h | 38 + .../libc/sysdeps/linux/i960/bits/syscalls.h | 15 + .../linux/i960/bits/uClibc_arch_features.h | 48 + .../libc/sysdeps/linux/i960/bits/wordsize.h | 19 + .../uclibc/libc/sysdeps/linux/i960/clone.S | 62 + .../uclibc/libc/sysdeps/linux/i960/crt0.S | 58 + .../uclibc/libc/sysdeps/linux/i960/mmap.S | 52 + .../uclibc/libc/sysdeps/linux/i960/setjmp.S | 124 + .../specs.uclinux.gcc-2.95.i960-intel-coff | 64 + .../libc/sysdeps/linux/i960/sys/procfs.h | 126 + .../libc/sysdeps/linux/i960/sys/ucontext.h | 76 + .../uclibc/libc/sysdeps/linux/i960/vfork.S | 33 + .../uclibc/libc/sysdeps/linux/ia64/Makefile | 15 + .../libc/sysdeps/linux/ia64/Makefile.arch | 12 + .../libc/sysdeps/linux/ia64/__longjmp.S | 162 + .../libc/sysdeps/linux/ia64/__syscall_error.c | 19 + .../libc/sysdeps/linux/ia64/bits/atomic.h | 119 + .../libc/sysdeps/linux/ia64/bits/byteswap.h | 52 + .../libc/sysdeps/linux/ia64/bits/endian.h | 7 + .../libc/sysdeps/linux/ia64/bits/fcntl.h | 232 + .../libc/sysdeps/linux/ia64/bits/fenv.h | 87 + .../uclibc/libc/sysdeps/linux/ia64/bits/ipc.h | 54 + .../sysdeps/linux/ia64/bits/kernel_stat.h | 37 + .../sysdeps/linux/ia64/bits/kernel_types.h | 56 + .../libc/sysdeps/linux/ia64/bits/mathdef.h | 41 + .../libc/sysdeps/linux/ia64/bits/mathinline.h | 54 + .../libc/sysdeps/linux/ia64/bits/mman.h | 4 + .../uclibc/libc/sysdeps/linux/ia64/bits/msq.h | 69 + .../uclibc/libc/sysdeps/linux/ia64/bits/sem.h | 87 + .../libc/sysdeps/linux/ia64/bits/setjmp.h | 40 + .../uclibc/libc/sysdeps/linux/ia64/bits/shm.h | 94 + .../libc/sysdeps/linux/ia64/bits/sigaction.h | 64 + .../libc/sysdeps/linux/ia64/bits/sigcontext.h | 79 + .../libc/sysdeps/linux/ia64/bits/siginfo.h | 339 + .../libc/sysdeps/linux/ia64/bits/sigstack.h | 63 + .../libc/sysdeps/linux/ia64/bits/stackinfo.h | 29 + .../libc/sysdeps/linux/ia64/bits/stat.h | 145 + .../libc/sysdeps/linux/ia64/bits/syscalls.h | 161 + .../linux/ia64/bits/uClibc_arch_features.h | 47 + .../libc/sysdeps/linux/ia64/bits/wordsize.h | 19 + .../uclibc/libc/sysdeps/linux/ia64/brk.S | 52 + .../libc/sysdeps/linux/ia64/bsd-_setjmp.S | 1 + .../libc/sysdeps/linux/ia64/bsd-setjmp.S | 1 + .../uclibc/libc/sysdeps/linux/ia64/clone2.S | 107 + .../uclibc/libc/sysdeps/linux/ia64/crt1.S | 129 + .../uclibc/libc/sysdeps/linux/ia64/crti.S | 36 + .../uclibc/libc/sysdeps/linux/ia64/crtn.S | 33 + .../uclibc/libc/sysdeps/linux/ia64/fork.S | 42 + .../uclibc/libc/sysdeps/linux/ia64/pipe.S | 37 + .../uclibc/libc/sysdeps/linux/ia64/setjmp.S | 189 + .../uclibc/libc/sysdeps/linux/ia64/sys/io.h | 69 + .../libc/sysdeps/linux/ia64/sys/procfs.h | 130 + .../libc/sysdeps/linux/ia64/sys/ptrace.h | 135 + .../libc/sysdeps/linux/ia64/sys/ucontext.h | 66 + .../uclibc/libc/sysdeps/linux/ia64/sys/user.h | 54 + .../uclibc/libc/sysdeps/linux/ia64/syscall.S | 30 + .../uclibc/libc/sysdeps/linux/ia64/sysdep.h | 168 + .../uclibc/libc/sysdeps/linux/ia64/vfork.S | 44 + .../uclibc/libc/sysdeps/linux/m68k/Makefile | 13 + .../libc/sysdeps/linux/m68k/Makefile.arch | 10 + .../libc/sysdeps/linux/m68k/README.m68k | 54 + .../libc/sysdeps/linux/m68k/__longjmp.S | 26 + .../libc/sysdeps/linux/m68k/__syscall_error.c | 19 + .../libc/sysdeps/linux/m68k/bits/byteswap.h | 37 + .../libc/sysdeps/linux/m68k/bits/endian.h | 7 + .../libc/sysdeps/linux/m68k/bits/fcntl.h | 238 + .../libc/sysdeps/linux/m68k/bits/fenv.h | 79 + .../sysdeps/linux/m68k/bits/kernel_stat.h | 56 + .../sysdeps/linux/m68k/bits/kernel_types.h | 44 + .../libc/sysdeps/linux/m68k/bits/mathdef.h | 42 + .../libc/sysdeps/linux/m68k/bits/mathinline.h | 445 + .../libc/sysdeps/linux/m68k/bits/poll.h | 43 + .../libc/sysdeps/linux/m68k/bits/setjmp.h | 68 + .../sysdeps/linux/m68k/bits/sigcontextinfo.h | 26 + .../libc/sysdeps/linux/m68k/bits/stackinfo.h | 28 + .../libc/sysdeps/linux/m68k/bits/stat.h | 169 + .../libc/sysdeps/linux/m68k/bits/syscalls.h | 111 + .../linux/m68k/bits/uClibc_arch_features.h | 51 + .../sysdeps/linux/m68k/bits/uClibc_page.h | 41 + .../libc/sysdeps/linux/m68k/bits/wordsize.h | 19 + .../uclibc/libc/sysdeps/linux/m68k/brk.c | 37 + .../libc/sysdeps/linux/m68k/bsd-_setjmp.S | 24 + .../libc/sysdeps/linux/m68k/bsd-setjmp.S | 23 + .../uclibc/libc/sysdeps/linux/m68k/clone.S | 69 + .../uclibc/libc/sysdeps/linux/m68k/crt1.S | 152 + .../uclibc/libc/sysdeps/linux/m68k/crti.S | 17 + .../uclibc/libc/sysdeps/linux/m68k/crtn.S | 11 + .../uclibc/libc/sysdeps/linux/m68k/float.h | 96 + .../libc/sysdeps/linux/m68k/fpu_control.h | 103 + .../uclibc/libc/sysdeps/linux/m68k/m68k_pic.S | 64 + .../uclibc/libc/sysdeps/linux/m68k/setjmp.S | 23 + .../libc/sysdeps/linux/m68k/sys/procfs.h | 126 + .../uclibc/libc/sysdeps/linux/m68k/sys/reg.h | 89 + .../libc/sysdeps/linux/m68k/sys/ucontext.h | 109 + .../uclibc/libc/sysdeps/linux/m68k/sys/user.h | 90 + .../uclibc/libc/sysdeps/linux/m68k/vfork.S | 45 + .../libc/sysdeps/linux/microblaze/Makefile | 25 + .../sysdeps/linux/microblaze/Makefile.arch | 14 + .../libc/sysdeps/linux/microblaze/__longjmp.S | 49 + .../sysdeps/linux/microblaze/bits/endian.h | 20 + .../sysdeps/linux/microblaze/bits/fcntl.h | 240 + .../linux/microblaze/bits/kernel_stat.h | 52 + .../linux/microblaze/bits/kernel_types.h | 60 + .../libc/sysdeps/linux/microblaze/bits/poll.h | 43 + .../sysdeps/linux/microblaze/bits/select.h | 58 + .../sysdeps/linux/microblaze/bits/setjmp.h | 47 + .../sysdeps/linux/microblaze/bits/stackinfo.h | 28 + .../sysdeps/linux/microblaze/bits/syscalls.h | 57 + .../microblaze/bits/uClibc_arch_features.h | 48 + .../linux/microblaze/bits/uClibc_page.h | 41 + .../sysdeps/linux/microblaze/bits/wordsize.h | 19 + .../libc/sysdeps/linux/microblaze/clone.c | 47 + .../libc/sysdeps/linux/microblaze/crt0.S | 56 + .../libc/sysdeps/linux/microblaze/crt1.S | 61 + .../libc/sysdeps/linux/microblaze/crti.S | 41 + .../libc/sysdeps/linux/microblaze/crtn.S | 43 + .../libc/sysdeps/linux/microblaze/fixdfsi.c | 85 + .../libc/sysdeps/linux/microblaze/floatlib.h | 140 + .../libc/sysdeps/linux/microblaze/mmap.c | 16 + .../libc/sysdeps/linux/microblaze/setjmp.S | 56 + .../sysdeps/linux/microblaze/sys/procfs.h | 145 + .../sysdeps/linux/microblaze/sys/ptrace.h | 98 + .../sysdeps/linux/microblaze/sys/ucontext.h | 41 + .../libc/sysdeps/linux/microblaze/vfork.S | 46 + .../uclibc/libc/sysdeps/linux/mips/Makefile | 13 + .../libc/sysdeps/linux/mips/Makefile.arch | 27 + .../libc/sysdeps/linux/mips/__longjmp.c | 128 + .../libc/sysdeps/linux/mips/__syscall_error.c | 18 + .../libc/sysdeps/linux/mips/_test_and_set.c | 30 + .../libc/sysdeps/linux/mips/bits/atomic.h | 303 + .../libc/sysdeps/linux/mips/bits/dirent.h | 61 + .../libc/sysdeps/linux/mips/bits/dlfcn.h | 66 + .../libc/sysdeps/linux/mips/bits/endian.h | 16 + .../libc/sysdeps/linux/mips/bits/fcntl.h | 262 + .../libc/sysdeps/linux/mips/bits/fenv.h | 77 + .../sysdeps/linux/mips/bits/ioctl-types.h | 76 + .../uclibc/libc/sysdeps/linux/mips/bits/ipc.h | 55 + .../linux/mips/bits/kernel_sigaction.h | 35 + .../sysdeps/linux/mips/bits/kernel_stat.h | 98 + .../sysdeps/linux/mips/bits/kernel_types.h | 79 + .../libc/sysdeps/linux/mips/bits/mathdef.h | 48 + .../libc/sysdeps/linux/mips/bits/mman.h | 108 + .../uclibc/libc/sysdeps/linux/mips/bits/msq.h | 93 + .../libc/sysdeps/linux/mips/bits/poll.h | 50 + .../libc/sysdeps/linux/mips/bits/resource.h | 233 + .../uclibc/libc/sysdeps/linux/mips/bits/sem.h | 85 + .../libc/sysdeps/linux/mips/bits/setjmp.h | 72 + .../uclibc/libc/sysdeps/linux/mips/bits/shm.h | 94 + .../libc/sysdeps/linux/mips/bits/sigaction.h | 74 + .../libc/sysdeps/linux/mips/bits/sigcontext.h | 84 + .../sysdeps/linux/mips/bits/sigcontextinfo.h | 43 + .../libc/sysdeps/linux/mips/bits/siginfo.h | 311 + .../libc/sysdeps/linux/mips/bits/signum.h | 60 + .../libc/sysdeps/linux/mips/bits/sigstack.h | 55 + .../libc/sysdeps/linux/mips/bits/socket.h | 349 + .../libc/sysdeps/linux/mips/bits/stackinfo.h | 28 + .../libc/sysdeps/linux/mips/bits/stat.h | 254 + .../libc/sysdeps/linux/mips/bits/statfs.h | 72 + .../libc/sysdeps/linux/mips/bits/syscalls.h | 326 + .../libc/sysdeps/linux/mips/bits/termios.h | 218 + .../linux/mips/bits/uClibc_arch_features.h | 47 + .../sysdeps/linux/mips/bits/uClibc_page.h | 35 + .../libc/sysdeps/linux/mips/bits/wordsize.h | 19 + .../uclibc/libc/sysdeps/linux/mips/brk.c | 51 + .../libc/sysdeps/linux/mips/bsd-_setjmp.S | 56 + .../libc/sysdeps/linux/mips/bsd-setjmp.S | 56 + .../libc/sysdeps/linux/mips/cacheflush.c | 30 + .../uclibc/libc/sysdeps/linux/mips/clone.S | 173 + .../uclibc/libc/sysdeps/linux/mips/crt1.S | 131 + .../uclibc/libc/sysdeps/linux/mips/crti.S | 158 + .../uclibc/libc/sysdeps/linux/mips/crtn.S | 130 + .../libc/sysdeps/linux/mips/fpu_control.h | 100 + .../uclibc/libc/sysdeps/linux/mips/mmap.c | 26 + .../uclibc/libc/sysdeps/linux/mips/pipe.S | 45 + .../libc/sysdeps/linux/mips/posix_fadvise.c | 39 + .../libc/sysdeps/linux/mips/posix_fadvise64.c | 43 + .../libc/sysdeps/linux/mips/pread_write.c | 115 + .../libc/sysdeps/linux/mips/readahead.c | 41 + .../uclibc/libc/sysdeps/linux/mips/setjmp.S | 61 + .../libc/sysdeps/linux/mips/setjmp_aux.c | 108 + .../uclibc/libc/sysdeps/linux/mips/sgidefs.h | 73 + .../libc/sysdeps/linux/mips/sigaction.c | 133 + .../uclibc/libc/sysdeps/linux/mips/sys/asm.h | 491 + .../libc/sysdeps/linux/mips/sys/cachectl.h | 42 + .../libc/sysdeps/linux/mips/sys/fpregdef.h | 61 + .../libc/sysdeps/linux/mips/sys/procfs.h | 112 + .../libc/sysdeps/linux/mips/sys/regdef.h | 82 + .../libc/sysdeps/linux/mips/sys/sysmips.h | 44 + .../uclibc/libc/sysdeps/linux/mips/sys/tas.h | 67 + .../libc/sysdeps/linux/mips/sys/ucontext.h | 117 + .../uclibc/libc/sysdeps/linux/mips/sys/user.h | 217 + .../uclibc/libc/sysdeps/linux/mips/syscall.S | 80 + .../libc/sysdeps/linux/mips/syscall_error.S | 84 + .../uclibc/libc/sysdeps/linux/mips/sysdep.h | 393 + .../uclibc/libc/sysdeps/linux/mips/sysmips.c | 7 + .../uclibc/libc/sysdeps/linux/mips/vfork.S | 100 + .../uclibc/libc/sysdeps/linux/nios/Makefile | 13 + .../libc/sysdeps/linux/nios/Makefile.arch | 12 + .../libc/sysdeps/linux/nios/NM_Macros.S | 473 + .../uclibc/libc/sysdeps/linux/nios/NR_Math1.S | 63 + .../libc/sysdeps/linux/nios/__longjmp.S | 103 + .../libc/sysdeps/linux/nios/bits/endian.h | 8 + .../libc/sysdeps/linux/nios/bits/fcntl.h | 236 + .../sysdeps/linux/nios/bits/kernel_types.h | 43 + .../libc/sysdeps/linux/nios/bits/mathdef.h | 44 + .../libc/sysdeps/linux/nios/bits/setjmp.h | 76 + .../sysdeps/linux/nios/bits/sigcontextinfo.h | 27 + .../libc/sysdeps/linux/nios/bits/stackinfo.h | 28 + .../libc/sysdeps/linux/nios/bits/stat.h | 168 + .../libc/sysdeps/linux/nios/bits/syscalls.h | 13 + .../linux/nios/bits/uClibc_arch_features.h | 48 + .../libc/sysdeps/linux/nios/bits/wordsize.h | 19 + .../uclibc/libc/sysdeps/linux/nios/brk.c | 44 + .../libc/sysdeps/linux/nios/bsd-_setjmp.S | 1 + .../libc/sysdeps/linux/nios/bsd-setjmp.S | 1 + .../uclibc/libc/sysdeps/linux/nios/clone.S | 88 + .../uclibc/libc/sysdeps/linux/nios/crt1.S | 59 + .../uclibc/libc/sysdeps/linux/nios/crtbegin.c | 37 + .../uclibc/libc/sysdeps/linux/nios/crtend.c | 44 + .../libc/sysdeps/linux/nios/fpu_control.h | 99 + .../uclibc/libc/sysdeps/linux/nios/setjmp.S | 102 + .../libc/sysdeps/linux/nios/sys/procfs.h | 123 + .../libc/sysdeps/linux/nios/sys/ucontext.h | 104 + .../uclibc/libc/sysdeps/linux/nios/vfork.S | 54 + .../uclibc/libc/sysdeps/linux/nios2/Makefile | 13 + .../libc/sysdeps/linux/nios2/Makefile.arch | 12 + .../libc/sysdeps/linux/nios2/__longjmp.S | 50 + .../libc/sysdeps/linux/nios2/bits/endian.h | 7 + .../libc/sysdeps/linux/nios2/bits/fcntl.h | 238 + .../sysdeps/linux/nios2/bits/kernel_stat.h | 54 + .../sysdeps/linux/nios2/bits/kernel_types.h | 44 + .../libc/sysdeps/linux/nios2/bits/mathdef.h | 44 + .../libc/sysdeps/linux/nios2/bits/setjmp.h | 72 + .../sysdeps/linux/nios2/bits/sigcontextinfo.h | 26 + .../libc/sysdeps/linux/nios2/bits/stackinfo.h | 28 + .../libc/sysdeps/linux/nios2/bits/stat.h | 168 + .../libc/sysdeps/linux/nios2/bits/syscalls.h | 106 + .../linux/nios2/bits/uClibc_arch_features.h | 48 + .../sysdeps/linux/nios2/bits/uClibc_page.h | 29 + .../libc/sysdeps/linux/nios2/bits/wordsize.h | 19 + .../uclibc/libc/sysdeps/linux/nios2/brk.c | 45 + .../libc/sysdeps/linux/nios2/bsd-_setjmp.S | 45 + .../libc/sysdeps/linux/nios2/bsd-setjmp.S | 52 + .../uclibc/libc/sysdeps/linux/nios2/clone.S | 70 + .../uclibc/libc/sysdeps/linux/nios2/clone.c | 50 + .../uclibc/libc/sysdeps/linux/nios2/crt1.S | 73 + .../uclibc/libc/sysdeps/linux/nios2/crti.S | 22 + .../uclibc/libc/sysdeps/linux/nios2/crtn.S | 14 + .../libc/sysdeps/linux/nios2/fpu_control.h | 99 + .../uclibc/libc/sysdeps/linux/nios2/setjmp.S | 51 + .../libc/sysdeps/linux/nios2/sys/procfs.h | 123 + .../libc/sysdeps/linux/nios2/sys/ucontext.h | 104 + .../libc/sysdeps/linux/nios2/sys/user.h | 93 + .../uclibc/libc/sysdeps/linux/nios2/syscall.c | 47 + .../uclibc/libc/sysdeps/linux/nios2/vfork.S | 56 + .../libc/sysdeps/linux/powerpc/Makefile | 13 + .../libc/sysdeps/linux/powerpc/Makefile.arch | 23 + .../libc/sysdeps/linux/powerpc/README.bits | 14 + .../libc/sysdeps/linux/powerpc/__longjmp.S | 94 + .../sysdeps/linux/powerpc/__syscall_error.c | 18 + .../sysdeps/linux/powerpc/__uClibc_syscall.S | 12 + .../libc/sysdeps/linux/powerpc/bits/atomic.h | 630 + .../libc/sysdeps/linux/powerpc/bits/endian.h | 37 + .../libc/sysdeps/linux/powerpc/bits/fcntl.h | 239 + .../libc/sysdeps/linux/powerpc/bits/fenv.h | 168 + .../sysdeps/linux/powerpc/bits/fenvinline.h | 64 + .../sysdeps/linux/powerpc/bits/ioctl-types.h | 5 + .../libc/sysdeps/linux/powerpc/bits/ipc.h | 62 + .../sysdeps/linux/powerpc/bits/kernel_stat.h | 54 + .../sysdeps/linux/powerpc/bits/kernel_types.h | 72 + .../libc/sysdeps/linux/powerpc/bits/mathdef.h | 54 + .../sysdeps/linux/powerpc/bits/mathinline.h | 185 + .../libc/sysdeps/linux/powerpc/bits/mman.h | 106 + .../libc/sysdeps/linux/powerpc/bits/msq.h | 83 + .../libc/sysdeps/linux/powerpc/bits/sem.h | 92 + .../libc/sysdeps/linux/powerpc/bits/setjmp.h | 80 + .../libc/sysdeps/linux/powerpc/bits/shm.h | 113 + .../linux/powerpc/bits/sigcontextinfo.h | 27 + .../sysdeps/linux/powerpc/bits/stackinfo.h | 28 + .../libc/sysdeps/linux/powerpc/bits/stat.h | 272 + .../sysdeps/linux/powerpc/bits/syscalls.h | 255 + .../libc/sysdeps/linux/powerpc/bits/termios.h | 319 + .../linux/powerpc/bits/uClibc_arch_features.h | 47 + .../sysdeps/linux/powerpc/bits/wordsize.h | 19 + .../uclibc/libc/sysdeps/linux/powerpc/brk.S | 80 + .../libc/sysdeps/linux/powerpc/bsd-_setjmp.S | 35 + .../libc/sysdeps/linux/powerpc/bsd-setjmp.S | 38 + .../uclibc/libc/sysdeps/linux/powerpc/clone.S | 145 + .../uclibc/libc/sysdeps/linux/powerpc/crt1.S | 107 + .../uclibc/libc/sysdeps/linux/powerpc/crti.S | 24 + .../uclibc/libc/sysdeps/linux/powerpc/crtn.S | 21 + .../uclibc/libc/sysdeps/linux/powerpc/fenv.h | 136 + .../libc/sysdeps/linux/powerpc/fpu_control.h | 94 + .../uclibc/libc/sysdeps/linux/powerpc/ioctl.c | 71 + .../sysdeps/linux/powerpc/posix_fadvise.c | 36 + .../sysdeps/linux/powerpc/posix_fadvise64.c | 69 + .../sysdeps/linux/powerpc/powerpc32/sysdep.h | 151 + .../sysdeps/linux/powerpc/powerpc64/sysdep.h | 264 + .../libc/sysdeps/linux/powerpc/ppc_asm.h | 137 + .../libc/sysdeps/linux/powerpc/pread_write.c | 183 + .../libc/sysdeps/linux/powerpc/setjmp.S | 92 + .../libc/sysdeps/linux/powerpc/sys/procfs.h | 140 + .../libc/sysdeps/linux/powerpc/sys/ptrace.h | 99 + .../libc/sysdeps/linux/powerpc/sys/ucontext.h | 177 + .../libc/sysdeps/linux/powerpc/sys/user.h | 40 + .../libc/sysdeps/linux/powerpc/syscall.S | 38 + .../libc/sysdeps/linux/powerpc/sysdep.h | 196 + .../uclibc/libc/sysdeps/linux/powerpc/vfork.S | 30 + .../uclibc/libc/sysdeps/linux/sh/Makefile | 13 + .../libc/sysdeps/linux/sh/Makefile.arch | 12 + .../libc/sysdeps/linux/sh/___fpscr_values.S | 34 + .../uclibc/libc/sysdeps/linux/sh/__init_brk.c | 26 + .../uclibc/libc/sysdeps/linux/sh/__longjmp.S | 65 + .../libc/sysdeps/linux/sh/bits/atomic.h | 293 + .../libc/sysdeps/linux/sh/bits/endian.h | 13 + .../uclibc/libc/sysdeps/linux/sh/bits/fcntl.h | 239 + .../uclibc/libc/sysdeps/linux/sh/bits/fenv.h | 72 + .../libc/sysdeps/linux/sh/bits/huge_val.h | 56 + .../libc/sysdeps/linux/sh/bits/kernel_stat.h | 81 + .../libc/sysdeps/linux/sh/bits/kernel_types.h | 45 + .../libc/sysdeps/linux/sh/bits/mathdef.h | 49 + .../libc/sysdeps/linux/sh/bits/setjmp.h | 56 + .../uclibc/libc/sysdeps/linux/sh/bits/shm.h | 109 + .../sysdeps/linux/sh/bits/sigcontextinfo.h | 27 + .../libc/sysdeps/linux/sh/bits/stackinfo.h | 28 + .../libc/sysdeps/linux/sh/bits/syscalls.h | 134 + .../linux/sh/bits/uClibc_arch_features.h | 51 + .../libc/sysdeps/linux/sh/bits/wordsize.h | 19 + .../uclibc/libc/sysdeps/linux/sh/brk.c | 27 + .../uclibc/libc/sysdeps/linux/sh/cacheflush.c | 15 + .../uclibc/libc/sysdeps/linux/sh/clone.S | 134 + .../uclibc/libc/sysdeps/linux/sh/crt1.S | 142 + .../uclibc/libc/sysdeps/linux/sh/crti.S | 32 + .../uclibc/libc/sysdeps/linux/sh/crtn.S | 34 + .../libc/sysdeps/linux/sh/fpu_control.h | 64 + .../uclibc/libc/sysdeps/linux/sh/longjmp.c | 56 + .../uclibc/libc/sysdeps/linux/sh/mmap.c | 34 + .../uclibc/libc/sysdeps/linux/sh/pipe.c | 39 + .../libc/sysdeps/linux/sh/pread_write.c | 125 + .../uclibc/libc/sysdeps/linux/sh/sbrk.c | 25 + .../uclibc/libc/sysdeps/linux/sh/setjmp.S | 102 + .../uclibc/libc/sysdeps/linux/sh/sys/io.h | 49 + .../uclibc/libc/sysdeps/linux/sh/sys/procfs.h | 126 + .../libc/sysdeps/linux/sh/sys/ucontext.h | 121 + .../uclibc/libc/sysdeps/linux/sh/sys/user.h | 89 + .../libc/sysdeps/linux/sh/syscall_error.S | 37 + .../uclibc/libc/sysdeps/linux/sh/sysdep.h | 297 + .../uclibc/libc/sysdeps/linux/sh/vfork.S | 114 + .../uclibc/libc/sysdeps/linux/sh64/Makefile | 15 + .../libc/sysdeps/linux/sh64/Makefile.arch | 10 + .../libc/sysdeps/linux/sh64/__init_brk.c | 26 + .../libc/sysdeps/linux/sh64/__longjmp.S | 141 + .../libc/sysdeps/linux/sh64/bits/endian.h | 20 + .../libc/sysdeps/linux/sh64/bits/fcntl.h | 217 + .../sysdeps/linux/sh64/bits/kernel_stat.h | 59 + .../sysdeps/linux/sh64/bits/kernel_types.h | 56 + .../libc/sysdeps/linux/sh64/bits/setjmp.h | 50 + .../uclibc/libc/sysdeps/linux/sh64/bits/shm.h | 103 + .../libc/sysdeps/linux/sh64/bits/stackinfo.h | 28 + .../libc/sysdeps/linux/sh64/bits/syscalls.h | 126 + .../linux/sh64/bits/uClibc_arch_features.h | 47 + .../libc/sysdeps/linux/sh64/bits/wordsize.h | 12 + .../uclibc/libc/sysdeps/linux/sh64/brk.c | 27 + .../uclibc/libc/sysdeps/linux/sh64/crt1.S | 83 + .../uclibc/libc/sysdeps/linux/sh64/crti.S | 42 + .../uclibc/libc/sysdeps/linux/sh64/crtn.S | 31 + .../uclibc/libc/sysdeps/linux/sh64/sbrk.c | 25 + .../uclibc/libc/sysdeps/linux/sh64/setjmp.S | 140 + .../libc/sysdeps/linux/sh64/sys/procfs.h | 126 + .../libc/sysdeps/linux/sh64/sys/ucontext.h | 205 + .../uclibc/libc/sysdeps/linux/sh64/syscall.c | 24 + .../uclibc/libc/sysdeps/linux/sparc/Makefile | 13 + .../libc/sysdeps/linux/sparc/Makefile.arch | 24 + .../libc/sysdeps/linux/sparc/__longjmp.S | 89 + .../sysdeps/linux/sparc/__syscall_error.c | 18 + .../libc/sysdeps/linux/sparc/_math_inc.h | 32 + .../libc/sysdeps/linux/sparc/bits/atomic.h | 329 + .../libc/sysdeps/linux/sparc/bits/endian.h | 12 + .../libc/sysdeps/linux/sparc/bits/fcntl.h | 258 + .../libc/sysdeps/linux/sparc/bits/fenv.h | 85 + .../libc/sysdeps/linux/sparc/bits/ioctls.h | 37 + .../libc/sysdeps/linux/sparc/bits/ipc.h | 62 + .../sysdeps/linux/sparc/bits/kernel_stat.h | 55 + .../sysdeps/linux/sparc/bits/kernel_types.h | 77 + .../libc/sysdeps/linux/sparc/bits/mathdef.h | 55 + .../sysdeps/linux/sparc/bits/mathinline.h | 292 + .../libc/sysdeps/linux/sparc/bits/mman.h | 108 + .../libc/sysdeps/linux/sparc/bits/msq.h | 84 + .../libc/sysdeps/linux/sparc/bits/poll.h | 50 + .../libc/sysdeps/linux/sparc/bits/resource.h | 241 + .../libc/sysdeps/linux/sparc/bits/sem.h | 92 + .../libc/sysdeps/linux/sparc/bits/setjmp.h | 84 + .../libc/sysdeps/linux/sparc/bits/shm.h | 111 + .../libc/sysdeps/linux/sparc/bits/sigaction.h | 64 + .../sysdeps/linux/sparc/bits/sigcontext.h | 78 + .../sysdeps/linux/sparc/bits/sigcontextinfo.h | 29 + .../libc/sysdeps/linux/sparc/bits/siginfo.h | 318 + .../libc/sysdeps/linux/sparc/bits/signum.h | 64 + .../libc/sysdeps/linux/sparc/bits/sigstack.h | 55 + .../libc/sysdeps/linux/sparc/bits/socket.h | 356 + .../libc/sysdeps/linux/sparc/bits/stackinfo.h | 28 + .../libc/sysdeps/linux/sparc/bits/stat.h | 169 + .../libc/sysdeps/linux/sparc/bits/statvfs.h | 106 + .../libc/sysdeps/linux/sparc/bits/syscalls.h | 118 + .../libc/sysdeps/linux/sparc/bits/termios.h | 233 + .../libc/sysdeps/linux/sparc/bits/typesizes.h | 66 + .../linux/sparc/bits/uClibc_arch_features.h | 47 + .../libc/sysdeps/linux/sparc/bits/wordsize.h | 20 + .../uclibc/libc/sysdeps/linux/sparc/brk.c | 49 + .../libc/sysdeps/linux/sparc/bsd-_setjmp.S | 1 + .../libc/sysdeps/linux/sparc/bsd-setjmp.S | 1 + .../uclibc/libc/sysdeps/linux/sparc/clone.S | 107 + .../uclibc/libc/sysdeps/linux/sparc/crt1.S | 134 + .../uclibc/libc/sysdeps/linux/sparc/crti.S | 23 + .../uclibc/libc/sysdeps/linux/sparc/crtn.S | 17 + .../uclibc/libc/sysdeps/linux/sparc/fork.S | 49 + .../libc/sysdeps/linux/sparc/fpu_control.h | 75 + .../uclibc/libc/sysdeps/linux/sparc/pipe.S | 62 + .../uclibc/libc/sysdeps/linux/sparc/qp_ops.c | 47 + .../uclibc/libc/sysdeps/linux/sparc/rem.S | 9 + .../uclibc/libc/sysdeps/linux/sparc/sdiv.S | 9 + .../uclibc/libc/sysdeps/linux/sparc/setjmp.S | 70 + .../libc/sysdeps/linux/sparc/sigaction.c | 92 + .../libc/sysdeps/linux/sparc/soft-fp/double.h | 264 + .../sysdeps/linux/sparc/soft-fp/extended.h | 431 + .../sysdeps/linux/sparc/soft-fp/longlong.h | 1461 ++ .../sysdeps/linux/sparc/soft-fp/mp_clz_tab.c | 37 + .../libc/sysdeps/linux/sparc/soft-fp/op-1.h | 302 + .../libc/sysdeps/linux/sparc/soft-fp/op-2.h | 617 + .../libc/sysdeps/linux/sparc/soft-fp/op-4.h | 688 + .../libc/sysdeps/linux/sparc/soft-fp/op-8.h | 111 + .../sysdeps/linux/sparc/soft-fp/op-common.h | 1359 ++ .../libc/sysdeps/linux/sparc/soft-fp/q_add.c | 39 + .../libc/sysdeps/linux/sparc/soft-fp/q_cmp.c | 41 + .../libc/sysdeps/linux/sparc/soft-fp/q_cmpe.c | 42 + .../libc/sysdeps/linux/sparc/soft-fp/q_div.c | 39 + .../libc/sysdeps/linux/sparc/soft-fp/q_dtoq.c | 44 + .../libc/sysdeps/linux/sparc/soft-fp/q_feq.c | 40 + .../libc/sysdeps/linux/sparc/soft-fp/q_fge.c | 40 + .../libc/sysdeps/linux/sparc/soft-fp/q_fgt.c | 40 + .../libc/sysdeps/linux/sparc/soft-fp/q_fle.c | 40 + .../libc/sysdeps/linux/sparc/soft-fp/q_flt.c | 40 + .../libc/sysdeps/linux/sparc/soft-fp/q_fne.c | 40 + .../libc/sysdeps/linux/sparc/soft-fp/q_itoq.c | 38 + .../sysdeps/linux/sparc/soft-fp/q_lltoq.c | 38 + .../libc/sysdeps/linux/sparc/soft-fp/q_mul.c | 39 + .../libc/sysdeps/linux/sparc/soft-fp/q_neg.c | 47 + .../libc/sysdeps/linux/sparc/soft-fp/q_qtod.c | 45 + .../libc/sysdeps/linux/sparc/soft-fp/q_qtoi.c | 38 + .../sysdeps/linux/sparc/soft-fp/q_qtoll.c | 38 + .../libc/sysdeps/linux/sparc/soft-fp/q_qtos.c | 45 + .../libc/sysdeps/linux/sparc/soft-fp/q_qtou.c | 38 + .../sysdeps/linux/sparc/soft-fp/q_qtoull.c | 38 + .../libc/sysdeps/linux/sparc/soft-fp/q_sqrt.c | 39 + .../libc/sysdeps/linux/sparc/soft-fp/q_stoq.c | 43 + .../libc/sysdeps/linux/sparc/soft-fp/q_sub.c | 39 + .../sysdeps/linux/sparc/soft-fp/q_ulltoq.c | 38 + .../libc/sysdeps/linux/sparc/soft-fp/q_util.c | 57 + .../libc/sysdeps/linux/sparc/soft-fp/q_utoq.c | 38 + .../libc/sysdeps/linux/sparc/soft-fp/quad.h | 271 + .../sysdeps/linux/sparc/soft-fp/sfp-machine.h | 213 + .../libc/sysdeps/linux/sparc/soft-fp/single.h | 151 + .../sysdeps/linux/sparc/soft-fp/soft-fp.h | 205 + .../libc/sysdeps/linux/sparc/sparcv7/rem.S | 360 + .../libc/sysdeps/linux/sparc/sparcv7/sdiv.S | 360 + .../libc/sysdeps/linux/sparc/sparcv7/udiv.S | 343 + .../libc/sysdeps/linux/sparc/sparcv7/umul.S | 153 + .../libc/sysdeps/linux/sparc/sparcv7/urem.S | 343 + .../libc/sysdeps/linux/sparc/sparcv8/rem.S | 19 + .../libc/sysdeps/linux/sparc/sparcv8/sdiv.S | 18 + .../libc/sysdeps/linux/sparc/sparcv8/udiv.S | 13 + .../libc/sysdeps/linux/sparc/sparcv8/umul.S | 11 + .../libc/sysdeps/linux/sparc/sparcv8/urem.S | 16 + .../libc/sysdeps/linux/sparc/sparcv9/clone.S | 102 + .../libc/sysdeps/linux/sparc/sparcv9/rem.S | 20 + .../libc/sysdeps/linux/sparc/sparcv9/sdiv.S | 18 + .../libc/sysdeps/linux/sparc/sparcv9/udiv.S | 15 + .../libc/sysdeps/linux/sparc/sparcv9/umul.S | 15 + .../libc/sysdeps/linux/sparc/sparcv9/urem.S | 17 + .../libc/sysdeps/linux/sparc/sys/procfs.h | 211 + .../libc/sysdeps/linux/sparc/sys/ptrace.h | 183 + .../libc/sysdeps/linux/sparc/sys/ucontext.h | 270 + .../libc/sysdeps/linux/sparc/sys/user.h | 85 + .../uclibc/libc/sysdeps/linux/sparc/syscall.S | 50 + .../uclibc/libc/sysdeps/linux/sparc/sysdep.h | 69 + .../uclibc/libc/sysdeps/linux/sparc/udiv.S | 9 + .../uclibc/libc/sysdeps/linux/sparc/umul.S | 9 + .../uclibc/libc/sysdeps/linux/sparc/urem.S | 9 + .../uclibc/libc/sysdeps/linux/sparc/vfork.S | 55 + .../uclibc/libc/sysdeps/linux/v850/Makefile | 64 + .../libc/sysdeps/linux/v850/__longjmp.S | 41 + .../libc/sysdeps/linux/v850/bits/byteswap.h | 31 + .../libc/sysdeps/linux/v850/bits/endian.h | 18 + .../libc/sysdeps/linux/v850/bits/fcntl.h | 233 + .../sysdeps/linux/v850/bits/kernel_stat.h | 58 + .../sysdeps/linux/v850/bits/kernel_types.h | 53 + .../libc/sysdeps/linux/v850/bits/poll.h | 43 + .../libc/sysdeps/linux/v850/bits/select.h | 64 + .../libc/sysdeps/linux/v850/bits/setjmp.h | 42 + .../sysdeps/linux/v850/bits/sigcontextinfo.h | 17 + .../libc/sysdeps/linux/v850/bits/stackinfo.h | 23 + .../libc/sysdeps/linux/v850/bits/syscalls.h | 15 + .../linux/v850/bits/uClibc_arch_features.h | 48 + .../libc/sysdeps/linux/v850/bits/wordsize.h | 19 + .../uclibc/libc/sysdeps/linux/v850/clinkage.h | 14 + .../uclibc/libc/sysdeps/linux/v850/clone.c | 50 + .../uclibc/libc/sysdeps/linux/v850/crt0.S | 57 + .../uclibc/libc/sysdeps/linux/v850/crti.S | 27 + .../uclibc/libc/sysdeps/linux/v850/crtn.S | 22 + .../uclibc/libc/sysdeps/linux/v850/mmap.c | 16 + .../uclibc/libc/sysdeps/linux/v850/setjmp.S | 48 + .../libc/sysdeps/linux/v850/sys/procfs.h | 136 + .../libc/sysdeps/linux/v850/sys/ptrace.h | 98 + .../libc/sysdeps/linux/v850/sys/ucontext.h | 41 + .../uclibc/libc/sysdeps/linux/v850/syscall.c | 43 + .../uclibc/libc/sysdeps/linux/v850/vfork.S | 42 + .../uclibc/libc/sysdeps/linux/vax/Makefile | 15 + .../libc/sysdeps/linux/vax/Makefile.arch | 10 + .../uclibc/libc/sysdeps/linux/vax/__longjmp.S | 47 + .../uclibc/libc/sysdeps/linux/vax/_setjmp.S | 53 + .../libc/sysdeps/linux/vax/bits/endian.h | 9 + .../libc/sysdeps/linux/vax/bits/fcntl.h | 214 + .../uclibc/libc/sysdeps/linux/vax/bits/ipc.h | 50 + .../libc/sysdeps/linux/vax/bits/kernel_stat.h | 54 + .../sysdeps/linux/vax/bits/kernel_types.h | 45 + .../sysdeps/linux/vax/bits/machine-gmon.h | 41 + .../uclibc/libc/sysdeps/linux/vax/bits/sem.h | 87 + .../libc/sysdeps/linux/vax/bits/setjmp.h | 37 + .../uclibc/libc/sysdeps/linux/vax/bits/shm.h | 88 + .../libc/sysdeps/linux/vax/bits/sigcontext.h | 29 + .../libc/sysdeps/linux/vax/bits/stackinfo.h | 7 + .../libc/sysdeps/linux/vax/bits/statfs.h | 61 + .../libc/sysdeps/linux/vax/bits/syscalls.h | 258 + .../linux/vax/bits/uClibc_arch_features.h | 47 + .../libc/sysdeps/linux/vax/bits/wordsize.h | 19 + .../uclibc/libc/sysdeps/linux/vax/brk.c | 53 + .../uclibc/libc/sysdeps/linux/vax/clone.S | 85 + .../uclibc/libc/sysdeps/linux/vax/crt1.S | 73 + .../uclibc/libc/sysdeps/linux/vax/crti.S | 21 + .../uclibc/libc/sysdeps/linux/vax/crtn.S | 19 + .../uclibc/libc/sysdeps/linux/vax/mmap.c | 10 + .../uclibc/libc/sysdeps/linux/vax/setjmp.S | 39 + .../libc/sysdeps/linux/vax/sys/procfs.h | 123 + .../libc/sysdeps/linux/vax/sys/ucontext.h | 80 + .../uclibc/libc/sysdeps/linux/x86_64/Makefile | 13 + .../libc/sysdeps/linux/x86_64/Makefile.arch | 19 + .../libc/sysdeps/linux/x86_64/__longjmp.S | 46 + .../sysdeps/linux/x86_64/__syscall_error.c | 21 + .../libc/sysdeps/linux/x86_64/bits/atomic.h | 324 + .../libc/sysdeps/linux/x86_64/bits/byteswap.h | 68 + .../libc/sysdeps/linux/x86_64/bits/endian.h | 7 + .../sysdeps/linux/x86_64/bits/environments.h | 87 + .../libc/sysdeps/linux/x86_64/bits/fcntl.h | 253 + .../libc/sysdeps/linux/x86_64/bits/fenv.h | 97 + .../sysdeps/linux/x86_64/bits/kernel_stat.h | 34 + .../sysdeps/linux/x86_64/bits/kernel_types.h | 53 + .../libc/sysdeps/linux/x86_64/bits/mathdef.h | 52 + .../sysdeps/linux/x86_64/bits/mathinline.h | 53 + .../libc/sysdeps/linux/x86_64/bits/mman.h | 4 + .../libc/sysdeps/linux/x86_64/bits/msq.h | 83 + .../libc/sysdeps/linux/x86_64/bits/sem.h | 87 + .../libc/sysdeps/linux/x86_64/bits/setjmp.h | 78 + .../libc/sysdeps/linux/x86_64/bits/shm.h | 110 + .../sysdeps/linux/x86_64/bits/sigcontext.h | 159 + .../linux/x86_64/bits/sigcontextinfo.h | 26 + .../sysdeps/linux/x86_64/bits/stackinfo.h | 28 + .../libc/sysdeps/linux/x86_64/bits/stat.h | 208 + .../libc/sysdeps/linux/x86_64/bits/syscalls.h | 133 + .../linux/x86_64/bits/uClibc_arch_features.h | 47 + .../libc/sysdeps/linux/x86_64/bits/wordsize.h | 9 + .../uclibc/libc/sysdeps/linux/x86_64/brk.c | 46 + .../libc/sysdeps/linux/x86_64/bsd-_setjmp.S | 29 + .../libc/sysdeps/linux/x86_64/bsd-setjmp.S | 29 + .../uclibc/libc/sysdeps/linux/x86_64/clone.S | 116 + .../uclibc/libc/sysdeps/linux/x86_64/crt1.S | 140 + .../uclibc/libc/sysdeps/linux/x86_64/crti.S | 16 + .../uclibc/libc/sysdeps/linux/x86_64/crtn.S | 16 + .../libc/sysdeps/linux/x86_64/fpu_control.h | 103 + .../uclibc/libc/sysdeps/linux/x86_64/mmap.c | 19 + .../uclibc/libc/sysdeps/linux/x86_64/setjmp.S | 45 + .../libc/sysdeps/linux/x86_64/sigaction.c | 130 + .../libc/sysdeps/linux/x86_64/sys/debugreg.h | 88 + .../libc/sysdeps/linux/x86_64/sys/epoll.h | 110 + .../uclibc/libc/sysdeps/linux/x86_64/sys/io.h | 182 + .../libc/sysdeps/linux/x86_64/sys/perm.h | 37 + .../libc/sysdeps/linux/x86_64/sys/procfs.h | 143 + .../libc/sysdeps/linux/x86_64/sys/reg.h | 79 + .../libc/sysdeps/linux/x86_64/sys/ucontext.h | 248 + .../libc/sysdeps/linux/x86_64/sys/user.h | 176 + .../libc/sysdeps/linux/x86_64/syscall.S | 42 + .../uclibc/libc/sysdeps/linux/x86_64/sysdep.h | 333 + .../uclibc/libc/sysdeps/linux/x86_64/vfork.S | 66 + .../uclibc/libc/sysdeps/linux/xtensa/Makefile | 13 + .../libc/sysdeps/linux/xtensa/Makefile.arch | 15 + .../libc/sysdeps/linux/xtensa/__longjmp.S | 126 + .../sysdeps/linux/xtensa/__syscall_error.c | 18 + .../libc/sysdeps/linux/xtensa/bits/endian.h | 10 + .../libc/sysdeps/linux/xtensa/bits/fcntl.h | 239 + .../libc/sysdeps/linux/xtensa/bits/ipc.h | 54 + .../sysdeps/linux/xtensa/bits/kernel_stat.h | 49 + .../sysdeps/linux/xtensa/bits/kernel_types.h | 48 + .../libc/sysdeps/linux/xtensa/bits/mathdef.h | 43 + .../libc/sysdeps/linux/xtensa/bits/mman.h | 106 + .../libc/sysdeps/linux/xtensa/bits/msq.h | 88 + .../libc/sysdeps/linux/xtensa/bits/setjmp.h | 46 + .../libc/sysdeps/linux/xtensa/bits/shm.h | 115 + .../linux/xtensa/bits/sigcontextinfo.h | 33 + .../sysdeps/linux/xtensa/bits/stackinfo.h | 28 + .../libc/sysdeps/linux/xtensa/bits/stat.h | 158 + .../libc/sysdeps/linux/xtensa/bits/syscalls.h | 85 + .../linux/xtensa/bits/uClibc_arch_features.h | 47 + .../sysdeps/linux/xtensa/bits/uClibc_page.h | 31 + .../libc/sysdeps/linux/xtensa/bits/wordsize.h | 19 + .../sysdeps/linux/xtensa/bits/xtensa-config.h | 53 + .../uclibc/libc/sysdeps/linux/xtensa/brk.c | 42 + .../libc/sysdeps/linux/xtensa/bsd-_setjmp.S | 1 + .../libc/sysdeps/linux/xtensa/bsd-setjmp.S | 1 + .../uclibc/libc/sysdeps/linux/xtensa/clone.S | 103 + .../uclibc/libc/sysdeps/linux/xtensa/crt1.S | 119 + .../uclibc/libc/sysdeps/linux/xtensa/crti.S | 16 + .../uclibc/libc/sysdeps/linux/xtensa/crtn.S | 8 + .../uclibc/libc/sysdeps/linux/xtensa/fork.c | 25 + .../uclibc/libc/sysdeps/linux/xtensa/mmap.S | 57 + .../libc/sysdeps/linux/xtensa/posix_fadvise.c | 29 + .../sysdeps/linux/xtensa/posix_fadvise64.c | 39 + .../libc/sysdeps/linux/xtensa/pread_write.c | 189 + .../uclibc/libc/sysdeps/linux/xtensa/setjmp.S | 131 + .../libc/sysdeps/linux/xtensa/sigaction.c | 39 + .../libc/sysdeps/linux/xtensa/sigrestorer.S | 19 + .../libc/sysdeps/linux/xtensa/sys/procfs.h | 121 + .../libc/sysdeps/linux/xtensa/sys/ptrace.h | 156 + .../libc/sysdeps/linux/xtensa/sys/ucontext.h | 49 + .../libc/sysdeps/linux/xtensa/syscall.S | 42 + .../uclibc/libc/sysdeps/linux/xtensa/sysdep.h | 160 + .../uclibc/libc/sysdeps/linux/xtensa/vfork.S | 170 + .../libc/sysdeps/linux/xtensa/windowspill.S | 96 + .../contrib/uclibc/libc/termios/.indent.pro | 33 + .../lib/contrib/uclibc/libc/termios/Makefile | 13 + .../contrib/uclibc/libc/termios/Makefile.in | 21 + .../contrib/uclibc/libc/termios/cfmakeraw.c | 33 + .../contrib/uclibc/libc/termios/cfsetspeed.c | 177 + .../lib/contrib/uclibc/libc/termios/isatty.c | 30 + .../uclibc/libc/termios/kernel_termios.h | 139 + .../lib/contrib/uclibc/libc/termios/speed.c | 95 + .../lib/contrib/uclibc/libc/termios/tcdrain.c | 49 + .../lib/contrib/uclibc/libc/termios/tcflow.c | 29 + .../lib/contrib/uclibc/libc/termios/tcflush.c | 30 + .../contrib/uclibc/libc/termios/tcgetattr.c | 77 + .../contrib/uclibc/libc/termios/tcgetpgrp.c | 34 + .../contrib/uclibc/libc/termios/tcgetsid.c | 63 + .../contrib/uclibc/libc/termios/tcsendbrk.c | 47 + .../contrib/uclibc/libc/termios/tcsetattr.c | 118 + .../contrib/uclibc/libc/termios/tcsetpgrp.c | 29 + .../lib/contrib/uclibc/libc/termios/ttyname.c | 127 + .../contrib/uclibc/libc/unistd/.indent.pro | 33 + .../lib/contrib/uclibc/libc/unistd/Makefile | 13 + .../contrib/uclibc/libc/unistd/Makefile.in | 52 + .../contrib/uclibc/libc/unistd/__exec_alloc.c | 8 + .../lib/contrib/uclibc/libc/unistd/confstr.c | 81 + .../lib/contrib/uclibc/libc/unistd/daemon.c | 144 + .../lib/contrib/uclibc/libc/unistd/exec.c | 331 + .../lib/contrib/uclibc/libc/unistd/execl.c | 8 + .../lib/contrib/uclibc/libc/unistd/execle.c | 8 + .../lib/contrib/uclibc/libc/unistd/execlp.c | 8 + .../lib/contrib/uclibc/libc/unistd/execv.c | 8 + .../lib/contrib/uclibc/libc/unistd/execvp.c | 8 + .../contrib/uclibc/libc/unistd/fpathconf.c | 253 + .../lib/contrib/uclibc/libc/unistd/getlogin.c | 45 + .../contrib/uclibc/libc/unistd/getopt-susv3.c | 123 + .../lib/contrib/uclibc/libc/unistd/getopt.c | 1198 ++ .../contrib/uclibc/libc/unistd/getopt_int.h | 134 + .../uclibc/libc/unistd/getopt_long-simple.c | 57 + .../lib/contrib/uclibc/libc/unistd/getpass.c | 107 + .../uclibc/libc/unistd/getsubopt-susv3.c | 30 + .../contrib/uclibc/libc/unistd/getsubopt.c | 72 + .../lib/contrib/uclibc/libc/unistd/pathconf.c | 199 + .../lib/contrib/uclibc/libc/unistd/sleep.c | 193 + .../lib/contrib/uclibc/libc/unistd/swab.c | 23 + .../lib/contrib/uclibc/libc/unistd/sysconf.c | 1014 ++ .../lib/contrib/uclibc/libc/unistd/ualarm.c | 25 + .../contrib/uclibc/libc/unistd/usershell.c | 74 + .../lib/contrib/uclibc/libc/unistd/usleep.c | 33 + .../lib/contrib/uclibc/libcrypt/Makefile | 13 + .../lib/contrib/uclibc/libcrypt/Makefile.in | 65 + .../lib/contrib/uclibc/libcrypt/crypt.c | 21 + .../lib/contrib/uclibc/libcrypt/crypt_stub.c | 30 + .../uclibc/lib/contrib/uclibc/libcrypt/des.c | 739 + .../lib/contrib/uclibc/libcrypt/libcrypt.h | 20 + .../uclibc/lib/contrib/uclibc/libcrypt/md5.c | 637 + .../lib/contrib/uclibc/libintl/Makefile | 13 + .../lib/contrib/uclibc/libintl/Makefile.in | 76 + .../uclibc/lib/contrib/uclibc/libintl/intl.c | 154 + .../uclibc/lib/contrib/uclibc/libm/Makefile | 13 + .../lib/contrib/uclibc/libm/Makefile.in | 316 + l4/pkg/uclibc/lib/contrib/uclibc/libm/README | 15 + l4/pkg/uclibc/lib/contrib/uclibc/libm/carg.c | 29 + .../uclibc/lib/contrib/uclibc/libm/e_acos.c | 115 + .../uclibc/lib/contrib/uclibc/libm/e_acosh.c | 73 + .../uclibc/lib/contrib/uclibc/libm/e_asin.c | 124 + .../uclibc/lib/contrib/uclibc/libm/e_atan2.c | 134 + .../uclibc/lib/contrib/uclibc/libm/e_atanh.c | 79 + .../uclibc/lib/contrib/uclibc/libm/e_cosh.c | 97 + l4/pkg/uclibc/lib/contrib/uclibc/libm/e_exp.c | 182 + .../uclibc/lib/contrib/uclibc/libm/e_fmod.c | 144 + .../uclibc/lib/contrib/uclibc/libm/e_hypot.c | 136 + l4/pkg/uclibc/lib/contrib/uclibc/libm/e_j0.c | 415 + l4/pkg/uclibc/lib/contrib/uclibc/libm/e_j1.c | 409 + l4/pkg/uclibc/lib/contrib/uclibc/libm/e_jn.c | 298 + .../lib/contrib/uclibc/libm/e_lgamma_r.c | 394 + l4/pkg/uclibc/lib/contrib/uclibc/libm/e_log.c | 147 + .../uclibc/lib/contrib/uclibc/libm/e_log10.c | 101 + .../uclibc/lib/contrib/uclibc/libm/e_log2.c | 118 + l4/pkg/uclibc/lib/contrib/uclibc/libm/e_pow.c | 338 + .../lib/contrib/uclibc/libm/e_rem_pio2.c | 161 + .../lib/contrib/uclibc/libm/e_remainder.c | 85 + .../uclibc/lib/contrib/uclibc/libm/e_scalb.c | 59 + .../uclibc/lib/contrib/uclibc/libm/e_sinh.c | 90 + .../uclibc/lib/contrib/uclibc/libm/e_sqrt.c | 457 + .../lib/contrib/uclibc/libm/float_wrappers.c | 404 + .../contrib/uclibc/libm/i386/Makefile.arch | 24 + .../lib/contrib/uclibc/libm/i386/fclrexcpt.c | 61 + .../contrib/uclibc/libm/i386/fedisblxcpt.c | 55 + .../contrib/uclibc/libm/i386/feenablxcpt.c | 55 + .../lib/contrib/uclibc/libm/i386/fegetenv.c | 34 + .../contrib/uclibc/libm/i386/fegetexcept.c | 32 + .../lib/contrib/uclibc/libm/i386/fegetround.c | 31 + .../contrib/uclibc/libm/i386/feholdexcpt.c | 59 + .../lib/contrib/uclibc/libm/i386/fesetenv.c | 80 + .../lib/contrib/uclibc/libm/i386/fesetround.c | 52 + .../contrib/uclibc/libm/i386/feupdateenv.c | 56 + .../contrib/uclibc/libm/i386/fgetexcptflg.c | 35 + .../contrib/uclibc/libm/i386/fraiseexcpt.c | 118 + .../contrib/uclibc/libm/i386/fsetexcptflg.c | 62 + .../contrib/uclibc/libm/i386/ftestexcept.c | 40 + l4/pkg/uclibc/lib/contrib/uclibc/libm/k_cos.c | 82 + .../lib/contrib/uclibc/libm/k_rem_pio2.c | 298 + l4/pkg/uclibc/lib/contrib/uclibc/libm/k_sin.c | 65 + .../lib/contrib/uclibc/libm/k_standard.c | 770 + l4/pkg/uclibc/lib/contrib/uclibc/libm/k_tan.c | 118 + .../contrib/uclibc/libm/ldouble_wrappers.c | 400 + .../lib/contrib/uclibc/libm/math_private.h | 259 + l4/pkg/uclibc/lib/contrib/uclibc/libm/nan.c | 60 + .../uclibc/libm/powerpc/classic/Makefile.arch | 18 + .../uclibc/libm/powerpc/e500/Makefile.arch | 10 + .../uclibc/libm/powerpc/e500/README.txt | 8 + .../libm/powerpc/e500/fpu/Makefile.arch | 19 + .../uclibc/libm/powerpc/e500/fpu/fclrexcpt.c | 39 + .../uclibc/libm/powerpc/e500/fpu/fe_nomask.c | 32 + .../libm/powerpc/e500/fpu/fedisblxcpt.c | 60 + .../libm/powerpc/e500/fpu/feenablxcpt.c | 60 + .../uclibc/libm/powerpc/e500/fpu/fegetenv.c | 38 + .../libm/powerpc/e500/fpu/fegetexcept.c | 31 + .../uclibc/libm/powerpc/e500/fpu/fegetround.c | 31 + .../libm/powerpc/e500/fpu/feholdexcpt.c | 45 + .../uclibc/libm/powerpc/e500/fpu/fenv_const.c | 27 + .../uclibc/libm/powerpc/e500/fpu/fenv_libc.h | 77 + .../uclibc/libm/powerpc/e500/fpu/fesetenv.c | 38 + .../uclibc/libm/powerpc/e500/fpu/fesetround.c | 37 + .../libm/powerpc/e500/fpu/feupdateenv.c | 49 + .../libm/powerpc/e500/fpu/fgetexcptflg.c | 39 + .../libm/powerpc/e500/fpu/fraiseexcpt.c | 29 + .../libm/powerpc/e500/fpu/fsetexcptflg.c | 46 + .../libm/powerpc/e500/fpu/ftestexcept.c | 32 + .../uclibc/libm/powerpc/e500/spe-raise.c | 67 + .../uclibc/lib/contrib/uclibc/libm/s_asinh.c | 52 + .../uclibc/lib/contrib/uclibc/libm/s_atan.c | 114 + .../uclibc/lib/contrib/uclibc/libm/s_cbrt.c | 76 + .../uclibc/lib/contrib/uclibc/libm/s_ceil.c | 70 + .../lib/contrib/uclibc/libm/s_copysign.c | 29 + l4/pkg/uclibc/lib/contrib/uclibc/libm/s_cos.c | 73 + l4/pkg/uclibc/lib/contrib/uclibc/libm/s_erf.c | 296 + .../uclibc/lib/contrib/uclibc/libm/s_expm1.c | 216 + .../uclibc/lib/contrib/uclibc/libm/s_fabs.c | 29 + .../uclibc/lib/contrib/uclibc/libm/s_fdim.c | 18 + .../uclibc/lib/contrib/uclibc/libm/s_finite.c | 32 + .../lib/contrib/uclibc/libm/s_finitef.c | 33 + .../uclibc/lib/contrib/uclibc/libm/s_floor.c | 71 + l4/pkg/uclibc/lib/contrib/uclibc/libm/s_fma.c | 28 + .../uclibc/lib/contrib/uclibc/libm/s_fmax.c | 19 + .../uclibc/lib/contrib/uclibc/libm/s_fmin.c | 19 + .../lib/contrib/uclibc/libm/s_fpclassify.c | 42 + .../lib/contrib/uclibc/libm/s_fpclassifyf.c | 40 + .../uclibc/lib/contrib/uclibc/libm/s_frexp.c | 46 + .../uclibc/lib/contrib/uclibc/libm/s_ilogb.c | 57 + .../uclibc/lib/contrib/uclibc/libm/s_isinf.c | 23 + .../uclibc/lib/contrib/uclibc/libm/s_isinff.c | 23 + .../uclibc/lib/contrib/uclibc/libm/s_isnan.c | 29 + .../uclibc/lib/contrib/uclibc/libm/s_isnanf.c | 32 + .../uclibc/lib/contrib/uclibc/libm/s_ldexp.c | 39 + .../lib/contrib/uclibc/libm/s_lib_version.c | 34 + .../uclibc/lib/contrib/uclibc/libm/s_llrint.c | 90 + .../lib/contrib/uclibc/libm/s_llround.c | 74 + .../uclibc/lib/contrib/uclibc/libm/s_log1p.c | 157 + .../uclibc/lib/contrib/uclibc/libm/s_logb.c | 33 + .../uclibc/lib/contrib/uclibc/libm/s_lrint.c | 95 + .../uclibc/lib/contrib/uclibc/libm/s_lround.c | 74 + .../lib/contrib/uclibc/libm/s_matherr.c | 24 + .../uclibc/lib/contrib/uclibc/libm/s_modf.c | 67 + .../lib/contrib/uclibc/libm/s_nextafter.c | 70 + .../lib/contrib/uclibc/libm/s_nextafterf.c | 96 + .../uclibc/lib/contrib/uclibc/libm/s_remquo.c | 31 + .../uclibc/lib/contrib/uclibc/libm/s_rint.c | 92 + .../uclibc/lib/contrib/uclibc/libm/s_round.c | 90 + .../uclibc/lib/contrib/uclibc/libm/s_scalbn.c | 77 + .../lib/contrib/uclibc/libm/s_signbit.c | 35 + .../lib/contrib/uclibc/libm/s_signbitf.c | 35 + .../lib/contrib/uclibc/libm/s_signgam.c | 3 + .../lib/contrib/uclibc/libm/s_significand.c | 24 + l4/pkg/uclibc/lib/contrib/uclibc/libm/s_sin.c | 73 + l4/pkg/uclibc/lib/contrib/uclibc/libm/s_tan.c | 67 + .../uclibc/lib/contrib/uclibc/libm/s_tanh.c | 73 + .../uclibc/lib/contrib/uclibc/libm/s_trunc.c | 55 + .../contrib/uclibc/libm/sh/sh4/Makefile.arch | 24 + .../contrib/uclibc/libm/sh/sh4/feholdexcpt.c | 29 + .../lib/contrib/uclibc/libm/sh/sh4/fesetenv.c | 26 + .../lib/contrib/uclibc/libm/sh/sh4/s_lrintf.S | 52 + .../contrib/uclibc/libm/sh/sh4/s_lroundf.S | 39 + .../uclibc/lib/contrib/uclibc/libm/w_cabs.c | 15 + .../uclibc/lib/contrib/uclibc/libm/w_exp2.c | 19 + .../uclibc/lib/contrib/uclibc/libnsl/Makefile | 13 + .../lib/contrib/uclibc/libnsl/Makefile.in | 52 + l4/pkg/uclibc/lib/contrib/uclibc/libnsl/nsl.c | 17 + .../lib/contrib/uclibc/libpthread/Makefile | 13 + .../lib/contrib/uclibc/libpthread/Makefile.in | 11 + .../libpthread/linuxthreads.old/Makefile | 13 + .../libpthread/linuxthreads.old/Makefile.in | 126 + .../uclibc/libpthread/linuxthreads.old/attr.c | 240 + .../libpthread/linuxthreads.old/cancel.c | 221 + .../libpthread/linuxthreads.old/condvar.c | 314 + .../libpthread/linuxthreads.old/debug.h | 40 + .../libpthread/linuxthreads.old/errno.c | 37 + .../libpthread/linuxthreads.old/events.c | 37 + .../libpthread/linuxthreads.old/forward.c | 170 + .../libpthread/linuxthreads.old/internals.h | 525 + .../uclibc/libpthread/linuxthreads.old/join.c | 231 + .../linuxthreads.old/libc_pthread_init.c | 58 + .../linuxthreads.old/linuxthreads.texi | 1627 ++ .../libpthread/linuxthreads.old/locale.c | 57 + .../libpthread/linuxthreads.old/lockfile.c | 43 + .../libpthread/linuxthreads.old/manager.c | 927 ++ .../libpthread/linuxthreads.old/mutex.c | 362 + .../linuxthreads.old/oldsemaphore.c | 241 + .../libpthread/linuxthreads.old/pt-machine.c | 22 + .../libpthread/linuxthreads.old/ptfork.c | 174 + .../libpthread/linuxthreads.old/pthread.c | 1162 ++ .../libpthread/linuxthreads.old/ptlongjmp.c | 71 + .../libpthread/linuxthreads.old/queue.h | 60 + .../libpthread/linuxthreads.old/restart.h | 50 + .../libpthread/linuxthreads.old/rwlock.c | 486 + .../libpthread/linuxthreads.old/semaphore.c | 313 + .../libpthread/linuxthreads.old/semaphore.h | 94 + .../libpthread/linuxthreads.old/signals.c | 250 + .../libpthread/linuxthreads.old/specific.c | 198 + .../libpthread/linuxthreads.old/spinlock.c | 723 + .../libpthread/linuxthreads.old/spinlock.h | 218 + .../sysdeps/alpha/pt-machine.h | 127 + .../linuxthreads.old/sysdeps/arm/pt-machine.h | 69 + .../sysdeps/avr32/pt-machine.h | 73 + .../sysdeps/bfin/pt-machine.h | 76 + .../sysdeps/cris/pt-machine.h | 70 + .../linuxthreads.old/sysdeps/frv/pt-machine.h | 70 + .../sysdeps/h8300/pt-machine.h | 58 + .../sysdeps/i386/pt-machine.h | 147 + .../linuxthreads.old/sysdeps/i386/tls.h | 185 + .../linuxthreads.old/sysdeps/i386/useldt.h | 307 + .../sysdeps/ia64/pt-machine.h | 135 + .../linuxthreads.old/sysdeps/ia64/tls.h | 139 + .../sysdeps/m68k/pt-machine.h | 75 + .../sysdeps/microblaze/pt-machine.h | 106 + .../sysdeps/microblaze/sigcontextinfo.h | 17 + .../sysdeps/mips/pt-machine.h | 106 + .../sysdeps/nios/pt-machine.h | 68 + .../sysdeps/nios2/pt-machine.h | 58 + .../sysdeps/powerpc/pt-machine.h | 102 + .../sysdeps/pthread/bits/libc-lock.h | 416 + .../sysdeps/pthread/bits/libc-tsd.h | 73 + .../sysdeps/pthread/bits/pthreadtypes.h | 142 + .../sysdeps/pthread/not-cancel.h | 105 + .../sysdeps/pthread/pthread-functions.h | 98 + .../sysdeps/pthread/pthread.h | 702 + .../linuxthreads.old/sysdeps/pthread/tls.h | 81 + .../linuxthreads.old/sysdeps/sh/pt-machine.h | 82 + .../linuxthreads.old/sysdeps/sh/tls.h | 117 + .../sysdeps/sh64/Makefile.arch | 30 + .../sysdeps/sh64/pt-machine.c | 47 + .../sysdeps/sh64/pt-machine.h | 39 + .../sysdeps/sparc/pt-machine.h | 8 + .../sysdeps/sparc/sparc32/pt-machine.h | 83 + .../sysdeps/sparc/sparc64/pt-machine.h | 105 + .../sysdeps/v850/pt-machine.h | 52 + .../sysdeps/x86_64/pt-machine.h | 85 + .../linuxthreads.old/sysdeps/x86_64/tls.h | 134 + .../sysdeps/xtensa/pt-machine.h | 48 + .../libpthread/linuxthreads.old/wrapsyscall.c | 229 + .../libpthread/linuxthreads.old_db/Banner | 1 + .../libpthread/linuxthreads.old_db/Makefile | 13 + .../linuxthreads.old_db/Makefile.in | 78 + .../libpthread/linuxthreads.old_db/Versions | 24 + .../linuxthreads.old_db/proc_service.h | 70 + .../libpthread/linuxthreads.old_db/td_init.c | 33 + .../libpthread/linuxthreads.old_db/td_log.c | 32 + .../linuxthreads.old_db/td_symbol_list.c | 61 + .../linuxthreads.old_db/td_ta_clear_event.c | 53 + .../linuxthreads.old_db/td_ta_delete.c | 58 + .../linuxthreads.old_db/td_ta_enable_stats.c | 35 + .../linuxthreads.old_db/td_ta_event_addr.c | 73 + .../linuxthreads.old_db/td_ta_event_getmsg.c | 128 + .../linuxthreads.old_db/td_ta_get_nthreads.c | 42 + .../linuxthreads.old_db/td_ta_get_ph.c | 36 + .../linuxthreads.old_db/td_ta_get_stats.c | 35 + .../linuxthreads.old_db/td_ta_map_id2thr.c | 78 + .../linuxthreads.old_db/td_ta_map_lwp2thr.c | 90 + .../linuxthreads.old_db/td_ta_new.c | 149 + .../linuxthreads.old_db/td_ta_reset_stats.c | 35 + .../linuxthreads.old_db/td_ta_set_event.c | 53 + .../td_ta_setconcurrency.c | 35 + .../linuxthreads.old_db/td_ta_thr_iter.c | 173 + .../linuxthreads.old_db/td_ta_tsd_iter.c | 55 + .../linuxthreads.old_db/td_thr_clear_event.c | 62 + .../linuxthreads.old_db/td_thr_dbresume.c | 30 + .../linuxthreads.old_db/td_thr_dbsuspend.c | 30 + .../linuxthreads.old_db/td_thr_event_enable.c | 57 + .../linuxthreads.old_db/td_thr_event_getmsg.c | 65 + .../linuxthreads.old_db/td_thr_get_info.c | 83 + .../linuxthreads.old_db/td_thr_getfpregs.c | 58 + .../linuxthreads.old_db/td_thr_getgregs.c | 58 + .../linuxthreads.old_db/td_thr_getxregs.c | 30 + .../linuxthreads.old_db/td_thr_getxregsize.c | 30 + .../linuxthreads.old_db/td_thr_set_event.c | 62 + .../linuxthreads.old_db/td_thr_setfpregs.c | 47 + .../linuxthreads.old_db/td_thr_setgregs.c | 47 + .../linuxthreads.old_db/td_thr_setprio.c | 30 + .../td_thr_setsigpending.c | 31 + .../linuxthreads.old_db/td_thr_setxregs.c | 30 + .../linuxthreads.old_db/td_thr_sigsetmask.c | 30 + .../linuxthreads.old_db/td_thr_tls_get_addr.c | 69 + .../linuxthreads.old_db/td_thr_tsd.c | 81 + .../linuxthreads.old_db/td_thr_validate.c | 69 + .../linuxthreads.old_db/thread_db.h | 459 + .../linuxthreads.old_db/thread_dbP.h | 110 + .../uclibc/libpthread/linuxthreads/.cvsignore | 3 + .../uclibc/libpthread/linuxthreads/Makefile | 13 + .../libpthread/linuxthreads/Makefile.in | 142 + .../libpthread/linuxthreads/alloca_cutoff.c | 36 + .../uclibc/libpthread/linuxthreads/attr.c | 469 + .../uclibc/libpthread/linuxthreads/barrier.c | 128 + .../uclibc/libpthread/linuxthreads/cancel.c | 238 + .../uclibc/libpthread/linuxthreads/condvar.c | 304 + .../uclibc/libpthread/linuxthreads/descr.h | 268 + .../uclibc/libpthread/linuxthreads/errno.c | 48 + .../uclibc/libpthread/linuxthreads/events.c | 37 + .../uclibc/libpthread/linuxthreads/forward.c | 145 + .../libpthread/linuxthreads/internals.h | 551 + .../uclibc/libpthread/linuxthreads/join.c | 220 + .../linuxthreads/libc-cancellation.c | 61 + .../linuxthreads/libc_pthread_init.c | 52 + .../uclibc/libpthread/linuxthreads/lockfile.c | 52 + .../uclibc/libpthread/linuxthreads/manager.c | 1122 ++ .../uclibc/libpthread/linuxthreads/mutex.c | 357 + .../libpthread/linuxthreads/pt-machine.c | 25 + .../libpthread/linuxthreads/ptcleanup.c | 74 + .../libpthread/linuxthreads/ptclock_gettime.c | 69 + .../libpthread/linuxthreads/ptclock_settime.c | 55 + .../uclibc/libpthread/linuxthreads/ptfork.c | 94 + .../libpthread/linuxthreads/pthandles.c | 5 + .../uclibc/libpthread/linuxthreads/pthread.c | 1390 ++ .../libpthread/linuxthreads/pthread_atfork.c | 63 + .../libpthread/linuxthreads/pthread_setegid.c | 28 + .../libpthread/linuxthreads/pthread_seteuid.c | 28 + .../libpthread/linuxthreads/pthread_setgid.c | 28 + .../linuxthreads/pthread_setregid.c | 28 + .../linuxthreads/pthread_setresgid.c | 28 + .../linuxthreads/pthread_setresuid.c | 28 + .../linuxthreads/pthread_setreuid.c | 28 + .../libpthread/linuxthreads/pthread_setuid.c | 28 + .../uclibc/libpthread/linuxthreads/queue.h | 61 + .../uclibc/libpthread/linuxthreads/restart.h | 49 + .../uclibc/libpthread/linuxthreads/rwlock.c | 658 + .../libpthread/linuxthreads/semaphore.c | 298 + .../libpthread/linuxthreads/semaphore.h | 94 + .../libpthread/linuxthreads/sighandler.c | 71 + .../uclibc/libpthread/linuxthreads/signals.c | 215 + .../uclibc/libpthread/linuxthreads/specific.c | 243 + .../uclibc/libpthread/linuxthreads/spinlock.c | 732 + .../uclibc/libpthread/linuxthreads/spinlock.h | 220 + .../sysdeps/alpha/elf/pt-initfini.c | 90 + .../linuxthreads/sysdeps/alpha/pspinlock.c | 110 + .../linuxthreads/sysdeps/alpha/pt-machine.h | 127 + .../linuxthreads/sysdeps/alpha/tls.h | 134 + .../linuxthreads/sysdeps/arm/pspinlock.c | 82 + .../linuxthreads/sysdeps/arm/pt-machine.h | 54 + .../linuxthreads/sysdeps/arm/sysdep-cancel.h | 8 + .../linuxthreads/sysdeps/arm/sysdep.h | 137 + .../libpthread/linuxthreads/sysdeps/arm/tls.h | 172 + .../linuxthreads/sysdeps/avr32/pt-machine.h | 73 + .../linuxthreads/sysdeps/cris/pspinlock.c | 72 + .../linuxthreads/sysdeps/cris/pt-machine.h | 57 + .../linuxthreads/sysdeps/hppa/pspinlock.c | 81 + .../linuxthreads/sysdeps/hppa/pt-machine.h | 60 + .../sysdeps/i386/i686/pt-machine.h | 79 + .../linuxthreads/sysdeps/i386/pspinlock.c | 103 + .../linuxthreads/sysdeps/i386/pt-machine.h | 118 + .../linuxthreads/sysdeps/i386/tcb-offsets.sym | 7 + .../linuxthreads/sysdeps/i386/tls.h | 227 + .../linuxthreads/sysdeps/i386/useldt.h | 314 + .../linuxthreads/sysdeps/ia64/pspinlock.c | 79 + .../linuxthreads/sysdeps/ia64/pt-machine.h | 131 + .../linuxthreads/sysdeps/ia64/tcb-offsets.sym | 9 + .../linuxthreads/sysdeps/ia64/tls.h | 145 + .../linuxthreads/sysdeps/m68k/pspinlock.c | 82 + .../linuxthreads/sysdeps/m68k/pt-machine.h | 68 + .../linuxthreads/sysdeps/mips/pspinlock.c | 96 + .../linuxthreads/sysdeps/mips/pt-machine.h | 89 + .../linuxthreads/sysdeps/mips/tls.h | 170 + .../sysdeps/powerpc/powerpc32/pspinlock.c | 70 + .../sysdeps/powerpc/powerpc32/pt-machine.h | 120 + .../sysdeps/powerpc/powerpc64/pspinlock.c | 70 + .../sysdeps/powerpc/powerpc64/pt-machine.h | 185 + .../linuxthreads/sysdeps/powerpc/pspinlock.c | 8 + .../linuxthreads/sysdeps/powerpc/pt-machine.h | 8 + .../sysdeps/powerpc/tcb-offsets.sym | 19 + .../linuxthreads/sysdeps/powerpc/tls.h | 165 + .../linuxthreads/sysdeps/pthread/.cvsignore | 2 + .../sysdeps/pthread/bits/initspin.h | 28 + .../sysdeps/pthread/bits/libc-lock.h | 409 + .../sysdeps/pthread/bits/libc-tsd.h | 59 + .../sysdeps/pthread/bits/pthreadtypes.h | 152 + .../sysdeps/pthread/bits/typesizes.h | 66 + .../linuxthreads/sysdeps/pthread/errno-loc.c | 45 + .../linuxthreads/sysdeps/pthread/flockfile.c | 33 + .../sysdeps/pthread/ftrylockfile.c | 33 + .../sysdeps/pthread/funlockfile.c | 33 + .../sysdeps/pthread/getcpuclockid.c | 117 + .../linuxthreads/sysdeps/pthread/herrno-loc.c | 43 + .../linuxthreads/sysdeps/pthread/list.h | 114 + .../sysdeps/pthread/malloc-machine.h | 67 + .../linuxthreads/sysdeps/pthread/not-cancel.h | 105 + .../sysdeps/pthread/posix-timer.h | 204 + .../sysdeps/pthread/pt-initfini.c | 124 + .../sysdeps/pthread/pthread-functions.h | 98 + .../linuxthreads/sysdeps/pthread/pthread.h | 680 + .../linuxthreads/sysdeps/pthread/ptlongjmp.c | 39 + .../linuxthreads/sysdeps/pthread/res-state.c | 47 + .../linuxthreads/sysdeps/pthread/semaphore.h | 1 + .../linuxthreads/sysdeps/pthread/sigaction.c | 57 + .../sysdeps/pthread/tcb-offsets.h | 1 + .../sysdeps/pthread/timer_create.c | 170 + .../sysdeps/pthread/timer_delete.c | 70 + .../sysdeps/pthread/timer_getoverr.c | 45 + .../sysdeps/pthread/timer_gettime.c | 77 + .../sysdeps/pthread/timer_routines.c | 573 + .../sysdeps/pthread/timer_settime.c | 137 + .../linuxthreads/sysdeps/pthread/tst-timer.c | 114 + .../sysdeps/pthread/uClibc-glue.h | 47 + .../linuxthreads/sysdeps/s390/pspinlock.c | 91 + .../sysdeps/s390/s390-32/pt-machine.h | 120 + .../sysdeps/s390/s390-64/pt-machine.h | 125 + .../linuxthreads/sysdeps/s390/tcb-offsets.sym | 4 + .../linuxthreads/sysdeps/s390/tls.h | 145 + .../linuxthreads/sysdeps/sh/pspinlock.c | 80 + .../linuxthreads/sysdeps/sh/pt-machine.h | 82 + .../linuxthreads/sysdeps/sh/tcb-offsets.sym | 10 + .../libpthread/linuxthreads/sysdeps/sh/tls.h | 159 + .../linuxthreads/sysdeps/sparc/pspinlock.c | 14 + .../linuxthreads/sysdeps/sparc/pt-machine.h | 8 + .../sysdeps/sparc/sparc32/pspinlock.c | 88 + .../sysdeps/sparc/sparc32/pt-machine.h | 83 + .../sysdeps/sparc/sparc32/sparcv9/pspinlock.c | 94 + .../sysdeps/sparc/sparc64/pspinlock.c | 93 + .../sysdeps/sparc/sparc64/pt-machine.h | 105 + .../sysdeps/sparc/tcb-offsets.sym | 4 + .../linuxthreads/sysdeps/sparc/tls.h | 115 + .../sysdeps/unix/sysv/linux/.cvsignore | 2 + .../sysdeps/unix/sysv/linux/allocalim.h | 26 + .../sysdeps/unix/sysv/linux/allocrtsig.c | 87 + .../unix/sysv/linux/alpha/aio_cancel.c | 33 + .../unix/sysv/linux/alpha/bits/local_lim.h | 92 + .../unix/sysv/linux/alpha/bits/typesizes.h | 66 + .../unix/sysv/linux/alpha/pt-sigsuspend.S | 28 + .../unix/sysv/linux/alpha/sysdep-cancel.h | 146 + .../sysdeps/unix/sysv/linux/alpha/vfork.S | 70 + .../unix/sysv/linux/arm/sysdep-cancel.h | 130 + .../sysdeps/unix/sysv/linux/arm/vfork.S | 78 + .../sysdeps/unix/sysv/linux/execve.c | 40 + .../sysdeps/unix/sysv/linux/fork.c | 30 + .../sysdeps/unix/sysv/linux/fork.h | 58 + .../sysdeps/unix/sysv/linux/hppa/aio_cancel.c | 33 + .../unix/sysv/linux/hppa/bits/initspin.h | 27 + .../unix/sysv/linux/hppa/malloc-machine.h | 73 + .../unix/sysv/linux/hppa/pt-initfini.c | 109 + .../unix/sysv/linux/hppa/sysdep-cancel.h | 189 + .../unix/sysv/linux/i386/sysdep-cancel.h | 187 + .../sysdeps/unix/sysv/linux/i386/vfork.S | 95 + .../unix/sysv/linux/ia64/bits/local_lim.h | 92 + .../sysdeps/unix/sysv/linux/ia64/fork.h | 25 + .../unix/sysv/linux/ia64/pt-initfini.c | 142 + .../unix/sysv/linux/ia64/pt-sigsuspend.c | 33 + .../unix/sysv/linux/ia64/sysdep-cancel.h | 144 + .../sysdeps/unix/sysv/linux/ia64/vfork.S | 54 + .../sysdeps/unix/sysv/linux/jmp-unwind.c | 34 + .../unix/sysv/linux/m68k/sysdep-cancel.h | 129 + .../sysdeps/unix/sysv/linux/m68k/vfork.S | 84 + .../sysv/linux/mips/mips64/sysdep-cancel.h | 144 + .../unix/sysv/linux/mips/sysdep-cancel.h | 144 + .../sysdeps/unix/sysv/linux/mips/vfork.S | 104 + .../sysdeps/unix/sysv/linux/mq_notify.c | 285 + .../linux/powerpc/powerpc32/sysdep-cancel.h | 159 + .../unix/sysv/linux/powerpc/powerpc32/vfork.S | 86 + .../linux/powerpc/powerpc64/sysdep-cancel.h | 127 + .../unix/sysv/linux/powerpc/powerpc64/vfork.S | 91 + .../unix/sysv/linux/powerpc/ptlongjmp.c | 70 + .../sysdeps/unix/sysv/linux/pt-sigsuspend.c | 33 + .../sysdeps/unix/sysv/linux/raise.c | 43 + .../sysdeps/unix/sysv/linux/register-atfork.c | 87 + .../unix/sysv/linux/s390/bits/typesizes.h | 72 + .../sysv/linux/s390/s390-32/pt-initfini.c | 154 + .../sysv/linux/s390/s390-32/sysdep-cancel.h | 137 + .../unix/sysv/linux/s390/s390-32/vfork.S | 69 + .../sysv/linux/s390/s390-64/pt-initfini.c | 137 + .../sysv/linux/s390/s390-64/pt-sigsuspend.c | 1 + .../sysv/linux/s390/s390-64/sysdep-cancel.h | 116 + .../unix/sysv/linux/s390/s390-64/vfork.S | 54 + .../sysdeps/unix/sysv/linux/sh/pt-initfini.c | 143 + .../sysdeps/unix/sysv/linux/sh/smp.h | 24 + .../unix/sysv/linux/sh/sysdep-cancel.h | 227 + .../sysdeps/unix/sysv/linux/sh/vfork.S | 78 + .../sysdeps/unix/sysv/linux/sigwait.c | 83 + .../sysdeps/unix/sysv/linux/smp.h | 48 + .../unix/sysv/linux/sparc/aio_cancel.c | 33 + .../unix/sysv/linux/sparc/bits/local_lim.h | 92 + .../unix/sysv/linux/sparc/bits/typesizes.h | 66 + .../sysdeps/unix/sysv/linux/sparc/fork.h | 21 + .../sysv/linux/sparc/sparc32/sysdep-cancel.h | 101 + .../unix/sysv/linux/sparc/sparc32/vfork.S | 65 + .../sysv/linux/sparc/sparc64/pt-sigsuspend.c | 1 + .../sysv/linux/sparc/sparc64/sysdep-cancel.h | 100 + .../unix/sysv/linux/sparc/sparc64/vfork.S | 64 + .../unix/sysv/linux/sparc/sysdep-cancel.h | 10 + .../unix/sysv/linux/unregister-atfork.c | 49 + .../unix/sysv/linux/x86_64/pt-sigsuspend.c | 1 + .../unix/sysv/linux/x86_64/sysdep-cancel.h | 132 + .../sysdeps/unix/sysv/linux/x86_64/vfork.S | 62 + .../linuxthreads/sysdeps/x86_64/pspinlock.c | 97 + .../linuxthreads/sysdeps/x86_64/pt-machine.h | 224 + .../sysdeps/x86_64/tcb-offsets.sym | 4 + .../linuxthreads/sysdeps/x86_64/tls.h | 134 + .../libpthread/linuxthreads_db/.cvsignore | 5 + .../uclibc/libpthread/linuxthreads_db/Banner | 1 + .../libpthread/linuxthreads_db/ChangeLog | 467 + .../libpthread/linuxthreads_db/Makefile | 13 + .../libpthread/linuxthreads_db/Makefile.in | 78 + .../libpthread/linuxthreads_db/Makefile.old | 57 + .../libpthread/linuxthreads_db/Versions | 24 + .../libpthread/linuxthreads_db/proc_service.h | 70 + .../libpthread/linuxthreads_db/shlib-versions | 2 + .../libpthread/linuxthreads_db/td_init.c | 34 + .../libpthread/linuxthreads_db/td_log.c | 32 + .../linuxthreads_db/td_symbol_list.c | 61 + .../linuxthreads_db/td_ta_clear_event.c | 53 + .../libpthread/linuxthreads_db/td_ta_delete.c | 58 + .../linuxthreads_db/td_ta_enable_stats.c | 35 + .../linuxthreads_db/td_ta_event_addr.c | 73 + .../linuxthreads_db/td_ta_event_getmsg.c | 129 + .../linuxthreads_db/td_ta_get_nthreads.c | 42 + .../libpthread/linuxthreads_db/td_ta_get_ph.c | 36 + .../linuxthreads_db/td_ta_get_stats.c | 35 + .../linuxthreads_db/td_ta_map_id2thr.c | 79 + .../linuxthreads_db/td_ta_map_lwp2thr.c | 91 + .../libpthread/linuxthreads_db/td_ta_new.c | 149 + .../linuxthreads_db/td_ta_reset_stats.c | 35 + .../linuxthreads_db/td_ta_set_event.c | 53 + .../linuxthreads_db/td_ta_setconcurrency.c | 35 + .../linuxthreads_db/td_ta_thr_iter.c | 176 + .../linuxthreads_db/td_ta_tsd_iter.c | 56 + .../linuxthreads_db/td_thr_clear_event.c | 62 + .../linuxthreads_db/td_thr_dbresume.c | 30 + .../linuxthreads_db/td_thr_dbsuspend.c | 30 + .../linuxthreads_db/td_thr_event_enable.c | 57 + .../linuxthreads_db/td_thr_event_getmsg.c | 65 + .../linuxthreads_db/td_thr_get_info.c | 83 + .../linuxthreads_db/td_thr_getfpregs.c | 58 + .../linuxthreads_db/td_thr_getgregs.c | 58 + .../linuxthreads_db/td_thr_getxregs.c | 30 + .../linuxthreads_db/td_thr_getxregsize.c | 30 + .../linuxthreads_db/td_thr_set_event.c | 62 + .../linuxthreads_db/td_thr_setfpregs.c | 47 + .../linuxthreads_db/td_thr_setgregs.c | 47 + .../linuxthreads_db/td_thr_setprio.c | 30 + .../linuxthreads_db/td_thr_setsigpending.c | 31 + .../linuxthreads_db/td_thr_setxregs.c | 30 + .../linuxthreads_db/td_thr_sigsetmask.c | 30 + .../linuxthreads_db/td_thr_tls_get_addr.c | 45 + .../linuxthreads_db/td_thr_tlsbase.c | 71 + .../libpthread/linuxthreads_db/td_thr_tsd.c | 82 + .../linuxthreads_db/td_thr_validate.c | 70 + .../libpthread/linuxthreads_db/thread_db.h | 459 + .../libpthread/linuxthreads_db/thread_dbP.h | 108 + .../contrib/uclibc/libpthread/nptl/.gitignore | 26 + .../contrib/uclibc/libpthread/nptl/ChangeLog | 11100 +++++++++++++ .../uclibc/libpthread/nptl/DESIGN-barrier.txt | 44 + .../uclibc/libpthread/nptl/DESIGN-condvar.txt | 134 + .../uclibc/libpthread/nptl/DESIGN-rwlock.txt | 113 + .../uclibc/libpthread/nptl/DESIGN-sem.txt | 46 + .../contrib/uclibc/libpthread/nptl/Makefile | 13 + .../uclibc/libpthread/nptl/Makefile.in | 224 + .../uclibc/libpthread/nptl/README.NPTL | 307 + .../lib/contrib/uclibc/libpthread/nptl/TODO | 31 + .../uclibc/libpthread/nptl/TODO-kernel | 20 + .../uclibc/libpthread/nptl/TODO-testing | 20 + .../uclibc/libpthread/nptl/alloca_cutoff.c | 36 + .../uclibc/libpthread/nptl/allocatestack.c | 1217 ++ .../contrib/uclibc/libpthread/nptl/banner.h | 1 + .../uclibc/libpthread/nptl/cancellation.c | 100 + .../contrib/uclibc/libpthread/nptl/cleanup.c | 49 + .../uclibc/libpthread/nptl/cleanup_compat.c | 55 + .../uclibc/libpthread/nptl/cleanup_defer.c | 92 + .../libpthread/nptl/cleanup_defer_compat.c | 100 + .../uclibc/libpthread/nptl/cleanup_routine.c | 28 + .../contrib/uclibc/libpthread/nptl/descr.h | 377 + .../uclibc/libpthread/nptl/errno_location.c | 1 + .../contrib/uclibc/libpthread/nptl/events.c | 34 + .../contrib/uclibc/libpthread/nptl/forward.c | 165 + .../contrib/uclibc/libpthread/nptl/herrno.c | 35 + .../lib/contrib/uclibc/libpthread/nptl/init.c | 446 + .../libpthread/nptl/libc-cancellation.c | 25 + .../uclibc/libpthread/nptl/linux_fsinfo.h | 153 + .../uclibc/libpthread/nptl/pt-cleanup.c | 64 + .../uclibc/libpthread/nptl/pt-system.c | 36 + .../uclibc/libpthread/nptl/pthread-errnos.sym | 13 + .../contrib/uclibc/libpthread/nptl/pthreadP.h | 589 + .../uclibc/libpthread/nptl/pthread_atfork.c | 56 + .../libpthread/nptl/pthread_attr_destroy.c | 41 + .../nptl/pthread_attr_getdetachstate.c | 40 + .../nptl/pthread_attr_getguardsize.c | 35 + .../nptl/pthread_attr_getinheritsched.c | 41 + .../nptl/pthread_attr_getschedparam.c | 41 + .../nptl/pthread_attr_getschedpolicy.c | 40 + .../libpthread/nptl/pthread_attr_getscope.c | 41 + .../libpthread/nptl/pthread_attr_getstack.c | 41 + .../nptl/pthread_attr_getstackaddr.c | 45 + .../nptl/pthread_attr_getstacksize.c | 40 + .../libpthread/nptl/pthread_attr_init.c | 51 + .../nptl/pthread_attr_setdetachstate.c | 47 + .../nptl/pthread_attr_setguardsize.c | 38 + .../nptl/pthread_attr_setinheritsched.c | 48 + .../nptl/pthread_attr_setschedparam.c | 49 + .../nptl/pthread_attr_setschedpolicy.c | 48 + .../libpthread/nptl/pthread_attr_setscope.c | 52 + .../libpthread/nptl/pthread_attr_setstack.c | 56 + .../nptl/pthread_attr_setstackaddr.c | 47 + .../nptl/pthread_attr_setstacksize.c | 49 + .../nptl/pthread_barrierattr_destroy.c | 29 + .../nptl/pthread_barrierattr_getpshared.c | 31 + .../nptl/pthread_barrierattr_init.c | 29 + .../nptl/pthread_barrierattr_setpshared.c | 40 + .../uclibc/libpthread/nptl/pthread_cancel.c | 108 + .../libpthread/nptl/pthread_clock_gettime.c | 69 + .../libpthread/nptl/pthread_clock_settime.c | 56 + .../libpthread/nptl/pthread_cond_destroy.c | 84 + .../libpthread/nptl/pthread_cond_init.c | 47 + .../nptl/pthread_condattr_destroy.c | 30 + .../nptl/pthread_condattr_getclock.c | 31 + .../nptl/pthread_condattr_getpshared.c | 31 + .../libpthread/nptl/pthread_condattr_init.c | 32 + .../nptl/pthread_condattr_setclock.c | 73 + .../nptl/pthread_condattr_setpshared.c | 37 + .../uclibc/libpthread/nptl/pthread_create.c | 586 + .../uclibc/libpthread/nptl/pthread_detach.c | 56 + .../uclibc/libpthread/nptl/pthread_equal.c | 29 + .../uclibc/libpthread/nptl/pthread_exit.c | 32 + .../libpthread/nptl/pthread_getattr_np.c | 179 + .../libpthread/nptl/pthread_getconcurrency.c | 27 + .../libpthread/nptl/pthread_getschedparam.c | 76 + .../libpthread/nptl/pthread_getspecific.c | 69 + .../uclibc/libpthread/nptl/pthread_join.c | 114 + .../libpthread/nptl/pthread_key_create.c | 56 + .../libpthread/nptl/pthread_key_delete.c | 42 + .../nptl/pthread_kill_other_threads.c | 32 + .../nptl/pthread_mutex_consistent.c | 37 + .../libpthread/nptl/pthread_mutex_destroy.c | 39 + .../nptl/pthread_mutex_getprioceiling.c | 38 + .../libpthread/nptl/pthread_mutex_init.c | 142 + .../libpthread/nptl/pthread_mutex_lock.c | 500 + .../nptl/pthread_mutex_setprioceiling.c | 119 + .../libpthread/nptl/pthread_mutex_timedlock.c | 488 + .../libpthread/nptl/pthread_mutex_trylock.c | 382 + .../libpthread/nptl/pthread_mutex_unlock.c | 294 + .../nptl/pthread_mutexattr_destroy.c | 28 + .../nptl/pthread_mutexattr_getprioceiling.c | 48 + .../nptl/pthread_mutexattr_getprotocol.c | 37 + .../nptl/pthread_mutexattr_getpshared.c | 36 + .../nptl/pthread_mutexattr_getrobust.c | 37 + .../nptl/pthread_mutexattr_gettype.c | 36 + .../libpthread/nptl/pthread_mutexattr_init.c | 38 + .../nptl/pthread_mutexattr_setprioceiling.c | 47 + .../nptl/pthread_mutexattr_setprotocol.c | 41 + .../nptl/pthread_mutexattr_setpshared.c | 43 + .../nptl/pthread_mutexattr_setrobust.c | 44 + .../nptl/pthread_mutexattr_settype.c | 41 + .../libpthread/nptl/pthread_rwlock_destroy.c | 29 + .../libpthread/nptl/pthread_rwlock_init.c | 73 + .../nptl/pthread_rwlock_tryrdlock.c | 50 + .../nptl/pthread_rwlock_trywrlock.c | 43 + .../nptl/pthread_rwlockattr_destroy.c | 29 + .../nptl/pthread_rwlockattr_getkind_np.c | 31 + .../nptl/pthread_rwlockattr_getpshared.c | 31 + .../libpthread/nptl/pthread_rwlockattr_init.c | 34 + .../nptl/pthread_rwlockattr_setkind_np.c | 41 + .../nptl/pthread_rwlockattr_setpshared.c | 40 + .../uclibc/libpthread/nptl/pthread_self.c | 30 + .../libpthread/nptl/pthread_setcancelstate.c | 74 + .../libpthread/nptl/pthread_setcanceltype.c | 77 + .../libpthread/nptl/pthread_setconcurrency.c | 40 + .../uclibc/libpthread/nptl/pthread_setegid.c | 3 + .../uclibc/libpthread/nptl/pthread_seteuid.c | 3 + .../uclibc/libpthread/nptl/pthread_setgid.c | 3 + .../uclibc/libpthread/nptl/pthread_setregid.c | 3 + .../libpthread/nptl/pthread_setresgid.c | 3 + .../libpthread/nptl/pthread_setresuid.c | 3 + .../uclibc/libpthread/nptl/pthread_setreuid.c | 3 + .../libpthread/nptl/pthread_setschedparam.c | 75 + .../libpthread/nptl/pthread_setschedprio.c | 66 + .../libpthread/nptl/pthread_setspecific.c | 97 + .../uclibc/libpthread/nptl/pthread_setuid.c | 3 + .../libpthread/nptl/pthread_testcancel.c | 28 + .../libpthread/nptl/pthread_timedjoin.c | 107 + .../uclibc/libpthread/nptl/pthread_tryjoin.c | 75 + .../lib/contrib/uclibc/libpthread/nptl/res.c | 27 + .../uclibc/libpthread/nptl/sem_close.c | 81 + .../uclibc/libpthread/nptl/sem_destroy.c | 33 + .../uclibc/libpthread/nptl/sem_getvalue.c | 37 + .../contrib/uclibc/libpthread/nptl/sem_init.c | 56 + .../contrib/uclibc/libpthread/nptl/sem_open.c | 397 + .../uclibc/libpthread/nptl/sem_unlink.c | 67 + .../uclibc/libpthread/nptl/semaphore.h | 79 + .../uclibc/libpthread/nptl/semaphoreP.h | 69 + .../uclibc/libpthread/nptl/sysdeps/Makefile | 13 + .../nptl/sysdeps/Makefile.commonarch | 69 + .../libpthread/nptl/sysdeps/Makefile.in | 29 + .../libpthread/nptl/sysdeps/alpha/Makefile | 21 + .../libpthread/nptl/sysdeps/alpha/dl-tls.h | 29 + .../nptl/sysdeps/alpha/elf/pt-initfini.c | 89 + .../nptl/sysdeps/alpha/jmpbuf-unwind.h | 31 + .../libpthread/nptl/sysdeps/alpha/libc-tls.c | 37 + .../nptl/sysdeps/alpha/pthread_spin_lock.S | 45 + .../nptl/sysdeps/alpha/pthread_spin_trylock.S | 46 + .../nptl/sysdeps/alpha/pthreaddef.h | 38 + .../nptl/sysdeps/alpha/tcb-offsets.sym | 14 + .../libpthread/nptl/sysdeps/alpha/tls.h | 127 + .../libpthread/nptl/sysdeps/arm/Makefile.arch | 17 + .../nptl/sysdeps/arm/aeabi_read_tp.S | 1 + .../nptl/sysdeps/arm/aeabi_unwind_cpp_pr1.c | 1 + .../libpthread/nptl/sysdeps/arm/dl-tls.h | 29 + .../nptl/sysdeps/arm/jmpbuf-unwind.h | 36 + .../nptl/sysdeps/arm/pthread_spin_lock.S | 31 + .../nptl/sysdeps/arm/pthread_spin_trylock.S | 34 + .../libpthread/nptl/sysdeps/arm/pthreaddef.h | 39 + .../nptl/sysdeps/arm/tcb-offsets.sym | 11 + .../nptl/sysdeps/arm/thumb_atomics.S | 1 + .../uclibc/libpthread/nptl/sysdeps/arm/tls.h | 159 + .../libpthread/nptl/sysdeps/generic/Makefile | 13 + .../nptl/sysdeps/generic/Makefile.in | 25 + .../libpthread/nptl/sysdeps/generic/dl-tls.c | 899 ++ .../libpthread/nptl/sysdeps/generic/dl-tls.h | 2 + .../nptl/sysdeps/generic/libc-tls.c | 265 + .../nptl/sysdeps/generic/lowlevellock.h | 84 + .../libpthread/nptl/sysdeps/generic/unwind.h | 220 + .../libpthread/nptl/sysdeps/i386/Makefile | 27 + .../nptl/sysdeps/i386/Makefile.arch | 10 + .../libpthread/nptl/sysdeps/i386/dl-tls.h | 62 + .../sysdeps/i386/i486/pthread_spin_trylock.S | 47 + .../sysdeps/i386/i586/pthread_spin_trylock.S | 20 + .../nptl/sysdeps/i386/i686/Makefile | 32 + .../sysdeps/i386/i686/pthread_spin_trylock.S | 21 + .../libpthread/nptl/sysdeps/i386/i686/tls.h | 36 + .../nptl/sysdeps/i386/jmpbuf-unwind.h | 32 + .../nptl/sysdeps/i386/pthread_spin_init.c | 20 + .../nptl/sysdeps/i386/pthread_spin_lock.c | 49 + .../nptl/sysdeps/i386/pthread_spin_unlock.S | 32 + .../libpthread/nptl/sysdeps/i386/pthreaddef.h | 48 + .../nptl/sysdeps/i386/tcb-offsets.sym | 17 + .../uclibc/libpthread/nptl/sysdeps/i386/tls.h | 480 + .../libpthread/nptl/sysdeps/mips/Makefile | 13 + .../nptl/sysdeps/mips/Makefile.arch | 17 + .../libpthread/nptl/sysdeps/mips/dl-tls.h | 46 + .../nptl/sysdeps/mips/jmpbuf-unwind.h | 30 + .../libpthread/nptl/sysdeps/mips/libc-tls.c | 37 + .../nptl/sysdeps/mips/nptl-sysdep.S | 2 + .../nptl/sysdeps/mips/pthread_spin_lock.S | 38 + .../nptl/sysdeps/mips/pthread_spin_trylock.S | 43 + .../libpthread/nptl/sysdeps/mips/pthreaddef.h | 39 + .../libpthread/nptl/sysdeps/mips/regdef.h | 26 + .../nptl/sysdeps/mips/tcb-offsets.sym | 11 + .../uclibc/libpthread/nptl/sysdeps/mips/tls.h | 181 + .../nptl/sysdeps/powerpc/Makefile.arch | 7 + .../libpthread/nptl/sysdeps/powerpc/dl-tls.h | 49 + .../nptl/sysdeps/powerpc/jmpbuf-unwind.h | 31 + .../nptl/sysdeps/powerpc/pthread_spin_lock.c | 44 + .../sysdeps/powerpc/pthread_spin_trylock.c | 42 + .../nptl/sysdeps/powerpc/pthreaddef.h | 41 + .../nptl/sysdeps/powerpc/tcb-offsets.sym | 20 + .../libpthread/nptl/sysdeps/powerpc/tls.h | 216 + .../libpthread/nptl/sysdeps/pthread/Makefile | 13 + .../nptl/sysdeps/pthread/Makefile.in | 109 + .../nptl/sysdeps/pthread/allocalim.h | 30 + .../nptl/sysdeps/pthread/bits/libc-lock.h | 584 + .../nptl/sysdeps/pthread/bits/libc-tsd.h | 69 + .../nptl/sysdeps/pthread/bits/sigthread.h | 44 + .../nptl/sysdeps/pthread/bits/stdio-lock.h | 111 + .../nptl/sysdeps/pthread/createthread.c | 257 + .../libpthread/nptl/sysdeps/pthread/defs.awk | 24 + .../nptl/sysdeps/pthread/librt-cancellation.c | 25 + .../libpthread/nptl/sysdeps/pthread/list.h | 103 + .../nptl/sysdeps/pthread/malloc-machine.h | 73 + .../nptl/sysdeps/pthread/posix-timer.h | 197 + .../nptl/sysdeps/pthread/pt-initfini.c | 125 + .../nptl/sysdeps/pthread/pt-longjmp.c | 29 + .../nptl/sysdeps/pthread/pthread-functions.h | 117 + .../libpthread/nptl/sysdeps/pthread/pthread.h | 1138 ++ .../sysdeps/pthread/pthread_barrier_destroy.c | 44 + .../sysdeps/pthread/pthread_barrier_init.c | 71 + .../sysdeps/pthread/pthread_barrier_wait.c | 79 + .../sysdeps/pthread/pthread_cond_broadcast.c | 90 + .../sysdeps/pthread/pthread_cond_signal.c | 63 + .../sysdeps/pthread/pthread_cond_timedwait.c | 216 + .../nptl/sysdeps/pthread/pthread_cond_wait.c | 193 + .../nptl/sysdeps/pthread/pthread_once.c | 54 + .../sysdeps/pthread/pthread_rwlock_rdlock.c | 97 + .../pthread/pthread_rwlock_timedrdlock.c | 137 + .../pthread/pthread_rwlock_timedwrlock.c | 127 + .../sysdeps/pthread/pthread_rwlock_unlock.c | 60 + .../sysdeps/pthread/pthread_rwlock_wrlock.c | 89 + .../nptl/sysdeps/pthread/pthread_sigmask.c | 58 + .../sysdeps/pthread/pthread_spin_destroy.c | 29 + .../nptl/sysdeps/pthread/pthread_spin_init.c | 28 + .../sysdeps/pthread/pthread_spin_unlock.c | 30 + .../nptl/sysdeps/pthread/rt-unwind-resume.c | 1 + .../libpthread/nptl/sysdeps/pthread/setxid.h | 63 + .../nptl/sysdeps/pthread/sigaction.c | 49 + .../nptl/sysdeps/pthread/sigfillset.c | 21 + .../nptl/sysdeps/pthread/sigprocmask.c | 22 + .../nptl/sysdeps/pthread/timer_create.c | 170 + .../nptl/sysdeps/pthread/timer_delete.c | 70 + .../nptl/sysdeps/pthread/timer_getoverr.c | 45 + .../nptl/sysdeps/pthread/timer_gettime.c | 77 + .../nptl/sysdeps/pthread/timer_routines.c | 578 + .../nptl/sysdeps/pthread/timer_settime.c | 137 + .../libpthread/nptl/sysdeps/pthread/tpp.c | 172 + .../nptl/sysdeps/pthread/uClibc-glue.h | 47 + .../sysdeps/pthread/unwind-forcedunwind.c | 151 + .../nptl/sysdeps/pthread/unwind-resume.c | 76 + .../libpthread/nptl/sysdeps/sh/Makefile | 3 + .../libpthread/nptl/sysdeps/sh/Makefile.arch | 13 + .../libpthread/nptl/sysdeps/sh/dl-tls.h | 29 + .../nptl/sysdeps/sh/jmpbuf-unwind.h | 33 + .../libpthread/nptl/sysdeps/sh/libc-tls.c | 31 + .../nptl/sysdeps/sh/pthread_spin_init.c | 20 + .../nptl/sysdeps/sh/pthread_spin_lock.c | 34 + .../nptl/sysdeps/sh/pthread_spin_trylock.S | 32 + .../nptl/sysdeps/sh/pthread_spin_unlock.S | 30 + .../libpthread/nptl/sysdeps/sh/pthreaddef.h | 49 + .../nptl/sysdeps/sh/tcb-offsets.sym | 15 + .../uclibc/libpthread/nptl/sysdeps/sh/tls.h | 182 + .../libpthread/nptl/sysdeps/sparc/Makefile | 3 + .../nptl/sysdeps/sparc/Makefile.arch | 11 + .../libpthread/nptl/sysdeps/sparc/dl-tls.h | 29 + .../nptl/sysdeps/sparc/jmpbuf-unwind.h | 5 + .../nptl/sysdeps/sparc/pthreaddef.h | 5 + .../sysdeps/sparc/sparc32/jmpbuf-unwind.h | 32 + .../sysdeps/sparc/sparc32/pthread_spin_lock.c | 40 + .../sparc/sparc32/pthread_spin_trylock.c | 29 + .../nptl/sysdeps/sparc/sparc32/pthreaddef.h | 40 + .../sparc/sparc32/sparcv9/pthread_spin_lock.c | 39 + .../sparc32/sparcv9/pthread_spin_trylock.c | 1 + .../sparc32/sparcv9/pthread_spin_unlock.c | 1 + .../sysdeps/sparc/sparc64/jmpbuf-unwind.h | 31 + .../sysdeps/sparc/sparc64/pthread_spin_lock.c | 39 + .../sparc/sparc64/pthread_spin_trylock.c | 34 + .../sparc/sparc64/pthread_spin_unlock.c | 30 + .../nptl/sysdeps/sparc/sparc64/pthreaddef.h | 40 + .../nptl/sysdeps/sparc/tcb-offsets.sym | 7 + .../libpthread/nptl/sysdeps/sparc/tls.h | 181 + .../libpthread/nptl/sysdeps/unix/Makefile | 13 + .../libpthread/nptl/sysdeps/unix/Makefile.in | 8 + .../nptl/sysdeps/unix/sysv/Makefile | 13 + .../nptl/sysdeps/unix/sysv/Makefile.in | 8 + .../nptl/sysdeps/unix/sysv/linux/Makefile | 13 + .../unix/sysv/linux/Makefile.commonarch | 211 + .../sysdeps/unix/sysv/linux/__syscall_error.c | 18 + .../nptl/sysdeps/unix/sysv/linux/accept.S | 12 + .../sysdeps/unix/sysv/linux/alpha/Makefile | 2 + .../unix/sysv/linux/alpha/bits/local_lim.h | 100 + .../unix/sysv/linux/alpha/bits/pthreadtypes.h | 168 + .../unix/sysv/linux/alpha/bits/semaphore.h | 34 + .../sysdeps/unix/sysv/linux/alpha/clone.S | 2 + .../unix/sysv/linux/alpha/createthread.c | 23 + .../nptl/sysdeps/unix/sysv/linux/alpha/fork.c | 30 + .../unix/sysv/linux/alpha/lowlevellock.h | 284 + .../sysdeps/unix/sysv/linux/alpha/pt-vfork.S | 43 + .../unix/sysv/linux/alpha/pthread_once.c | 97 + .../sysdeps/unix/sysv/linux/alpha/sem_post.c | 5 + .../unix/sysv/linux/alpha/sysdep-cancel.h | 177 + .../unix/sysv/linux/alpha/timer_create.c | 1 + .../unix/sysv/linux/alpha/timer_delete.c | 1 + .../unix/sysv/linux/alpha/timer_getoverr.c | 1 + .../unix/sysv/linux/alpha/timer_gettime.c | 1 + .../unix/sysv/linux/alpha/timer_settime.c | 1 + .../sysdeps/unix/sysv/linux/alpha/vfork.S | 46 + .../nptl/sysdeps/unix/sysv/linux/arm/Makefile | 13 + .../sysdeps/unix/sysv/linux/arm/Makefile.arch | 32 + .../sysdeps/unix/sysv/linux/arm/bits/atomic.h | 122 + .../unix/sysv/linux/arm/bits/pthreadtypes.h | 181 + .../unix/sysv/linux/arm/bits/semaphore.h | 35 + .../nptl/sysdeps/unix/sysv/linux/arm/clone.S | 3 + .../unix/sysv/linux/arm/createthread.c | 23 + .../nptl/sysdeps/unix/sysv/linux/arm/fork.c | 31 + .../unix/sysv/linux/arm/libc-lowlevellock.c | 21 + .../unix/sysv/linux/arm/lowlevellock.c | 134 + .../unix/sysv/linux/arm/lowlevellock.h | 282 + .../linux/arm/nptl-aeabi_unwind_cpp_pr1.c | 1 + .../unix/sysv/linux/arm/pt-__syscall_error.c | 1 + .../linux/arm/pt-__syscall_rt_sigaction.c | 1 + .../unix/sysv/linux/arm/pt-gettimeofday.c | 5 + .../sysdeps/unix/sysv/linux/arm/pt-vfork.S | 38 + .../unix/sysv/linux/arm/pthread_once.c | 100 + .../unix/sysv/linux/arm/sysdep-cancel.h | 254 + .../unix/sysv/linux/arm/unwind-forcedunwind.c | 177 + .../unix/sysv/linux/arm/unwind-resume.c | 116 + .../nptl/sysdeps/unix/sysv/linux/arm/unwind.h | 279 + .../nptl/sysdeps/unix/sysv/linux/arm/vfork.S | 39 + .../sysdeps/unix/sysv/linux/bits/local_lim.h | 100 + .../sysdeps/unix/sysv/linux/bits/posix_opt.h | 204 + .../nptl/sysdeps/unix/sysv/linux/close.S | 21 + .../nptl/sysdeps/unix/sysv/linux/connect.S | 12 + .../nptl/sysdeps/unix/sysv/linux/creat.S | 7 + .../sysdeps/unix/sysv/linux/createthread.c | 24 + .../sysdeps/unix/sysv/linux/exit-thread.S | 23 + .../nptl/sysdeps/unix/sysv/linux/fork.c | 229 + .../nptl/sysdeps/unix/sysv/linux/fork.h | 60 + .../nptl/sysdeps/unix/sysv/linux/getpid.c | 65 + .../sysdeps/unix/sysv/linux/i386/Makefile | 13 + .../unix/sysv/linux/i386/Makefile.arch | 29 + .../unix/sysv/linux/i386/bits/pthreadtypes.h | 173 + .../unix/sysv/linux/i386/bits/semaphore.h | 36 + .../nptl/sysdeps/unix/sysv/linux/i386/clone.S | 2 + .../unix/sysv/linux/i386/createthread.c | 49 + .../nptl/sysdeps/unix/sysv/linux/i386/fork.c | 31 + .../sysv/linux/i386/i486/libc-lowlevellock.S | 20 + .../unix/sysv/linux/i386/i486/lowlevellock.S | 459 + .../sysv/linux/i386/i486/lowlevelrobustlock.S | 234 + .../linux/i386/i486/pthread_barrier_wait.S | 187 + .../linux/i386/i486/pthread_cond_broadcast.S | 239 + .../linux/i386/i486/pthread_cond_signal.S | 216 + .../linux/i386/i486/pthread_cond_timedwait.S | 698 + .../sysv/linux/i386/i486/pthread_cond_wait.S | 595 + .../linux/i386/i486/pthread_rwlock_rdlock.S | 195 + .../i386/i486/pthread_rwlock_timedrdlock.S | 245 + .../i386/i486/pthread_rwlock_timedwrlock.S | 238 + .../linux/i386/i486/pthread_rwlock_unlock.S | 157 + .../linux/i386/i486/pthread_rwlock_wrlock.S | 186 + .../unix/sysv/linux/i386/i486/sem_post.S | 142 + .../unix/sysv/linux/i386/i486/sem_timedwait.S | 329 + .../unix/sysv/linux/i386/i486/sem_trywait.S | 79 + .../unix/sysv/linux/i386/i486/sem_wait.S | 269 + .../sysv/linux/i386/i586/libc-lowlevellock.S | 1 + .../unix/sysv/linux/i386/i586/lowlevellock.S | 20 + .../sysv/linux/i386/i586/lowlevelrobustlock.S | 20 + .../linux/i386/i586/pthread_barrier_wait.S | 20 + .../linux/i386/i586/pthread_cond_broadcast.S | 20 + .../linux/i386/i586/pthread_cond_signal.S | 20 + .../linux/i386/i586/pthread_cond_timedwait.S | 20 + .../sysv/linux/i386/i586/pthread_cond_wait.S | 20 + .../linux/i386/i586/pthread_rwlock_rdlock.S | 20 + .../i386/i586/pthread_rwlock_timedrdlock.S | 20 + .../i386/i586/pthread_rwlock_timedwrlock.S | 20 + .../linux/i386/i586/pthread_rwlock_unlock.S | 20 + .../linux/i386/i586/pthread_rwlock_wrlock.S | 20 + .../unix/sysv/linux/i386/i586/sem_post.S | 20 + .../unix/sysv/linux/i386/i586/sem_timedwait.S | 20 + .../unix/sysv/linux/i386/i586/sem_trywait.S | 20 + .../unix/sysv/linux/i386/i586/sem_wait.S | 20 + .../sysv/linux/i386/i686/libc-lowlevellock.S | 1 + .../unix/sysv/linux/i386/i686/lowlevellock.S | 20 + .../sysv/linux/i386/i686/lowlevelrobustlock.S | 20 + .../linux/i386/i686/pthread_barrier_wait.S | 20 + .../linux/i386/i686/pthread_cond_broadcast.S | 20 + .../linux/i386/i686/pthread_cond_signal.S | 20 + .../linux/i386/i686/pthread_cond_timedwait.S | 21 + .../sysv/linux/i386/i686/pthread_cond_wait.S | 20 + .../linux/i386/i686/pthread_rwlock_rdlock.S | 20 + .../i386/i686/pthread_rwlock_timedrdlock.S | 20 + .../i386/i686/pthread_rwlock_timedwrlock.S | 20 + .../linux/i386/i686/pthread_rwlock_unlock.S | 21 + .../linux/i386/i686/pthread_rwlock_wrlock.S | 20 + .../unix/sysv/linux/i386/i686/sem_post.S | 20 + .../unix/sysv/linux/i386/i686/sem_timedwait.S | 20 + .../unix/sysv/linux/i386/i686/sem_trywait.S | 20 + .../unix/sysv/linux/i386/i686/sem_wait.S | 20 + .../unix/sysv/linux/i386/lowlevellock.h | 585 + .../unix/sysv/linux/i386/pt-__syscall_error.c | 1 + .../sysdeps/unix/sysv/linux/i386/pt-vfork.S | 68 + .../unix/sysv/linux/i386/pthread_once.S | 197 + .../unix/sysv/linux/i386/pthread_spin_init.c | 1 + .../sysv/linux/i386/pthread_spin_unlock.S | 1 + .../nptl/sysdeps/unix/sysv/linux/i386/smp.h | 56 + .../unix/sysv/linux/i386/sysdep-cancel.h | 155 + .../nptl/sysdeps/unix/sysv/linux/i386/vfork.S | 38 + .../sysdeps/unix/sysv/linux/internaltypes.h | 162 + .../nptl/sysdeps/unix/sysv/linux/jmp-unwind.c | 39 + .../unix/sysv/linux/kernel-posix-timers.h | 1 + .../unix/sysv/linux/libc-lowlevellock.c | 21 + .../unix/sysv/linux/libc_multiple_threads.c | 26 + .../unix/sysv/linux/libc_pthread_init.c | 74 + .../unix/sysv/linux/lowlevelbarrier.sym | 12 + .../sysdeps/unix/sysv/linux/lowlevelcond.sym | 16 + .../sysdeps/unix/sysv/linux/lowlevellock.c | 127 + .../unix/sysv/linux/lowlevelrobustlock.c | 114 + .../unix/sysv/linux/lowlevelrobustlock.sym | 6 + .../unix/sysv/linux/lowlevelrwlock.sym | 16 + .../nptl/sysdeps/unix/sysv/linux/lseek.S | 7 + .../sysdeps/unix/sysv/linux/mips/Makefile | 13 + .../unix/sysv/linux/mips/Makefile.arch | 25 + .../unix/sysv/linux/mips/bits/pthreadtypes.h | 230 + .../unix/sysv/linux/mips/bits/semaphore.h | 37 + .../nptl/sysdeps/unix/sysv/linux/mips/clone.S | 2 + .../unix/sysv/linux/mips/createthread.c | 24 + .../nptl/sysdeps/unix/sysv/linux/mips/fork.c | 1 + .../unix/sysv/linux/mips/lowlevellock.h | 295 + .../linux/mips/pt-__syscall_rt_sigaction.c | 1 + .../sysdeps/unix/sysv/linux/mips/pt-clone.S | 2 + .../sysdeps/unix/sysv/linux/mips/pt-vfork.S | 38 + .../unix/sysv/linux/mips/pthread_once.c | 95 + .../unix/sysv/linux/mips/sysdep-cancel.h | 188 + .../nptl/sysdeps/unix/sysv/linux/mips/vfork.S | 43 + .../nptl/sysdeps/unix/sysv/linux/mq_notify.c | 286 + .../nptl/sysdeps/unix/sysv/linux/msync.S | 7 + .../nptl/sysdeps/unix/sysv/linux/nanosleep.S | 9 + .../nptl/sysdeps/unix/sysv/linux/not-cancel.h | 105 + .../nptl/sysdeps/unix/sysv/linux/open.S | 21 + .../nptl/sysdeps/unix/sysv/linux/pause.S | 7 + .../sysdeps/unix/sysv/linux/powerpc/Makefile | 13 + .../unix/sysv/linux/powerpc/Makefile.arch | 30 + .../sysv/linux/powerpc/bits/pthreadtypes.h | 221 + .../unix/sysv/linux/powerpc/bits/semaphore.h | 41 + .../sysdeps/unix/sysv/linux/powerpc/clone.S | 5 + .../unix/sysv/linux/powerpc/createthread.c | 25 + .../sysdeps/unix/sysv/linux/powerpc/fork.c | 1 + .../unix/sysv/linux/powerpc/lowlevellock.h | 315 + .../unix/sysv/linux/powerpc/powerpc32/clone.S | 9 + .../sysv/linux/powerpc/powerpc32/pt-vfork.S | 49 + .../linux/powerpc/powerpc32/sysdep-cancel.h | 119 + .../unix/sysv/linux/powerpc/powerpc32/vfork.S | 58 + .../unix/sysv/linux/powerpc/powerpc64/clone.S | 9 + .../sysv/linux/powerpc/powerpc64/pt-vfork.S | 49 + .../linux/powerpc/powerpc64/sysdep-cancel.h | 125 + .../linux/powerpc/powerpc64/timer_create.c | 1 + .../linux/powerpc/powerpc64/timer_delete.c | 1 + .../linux/powerpc/powerpc64/timer_getoverr.c | 1 + .../linux/powerpc/powerpc64/timer_gettime.c | 1 + .../linux/powerpc/powerpc64/timer_settime.c | 1 + .../unix/sysv/linux/powerpc/powerpc64/vfork.S | 57 + .../sysv/linux/powerpc/pt-__syscall_error.c | 1 + .../unix/sysv/linux/powerpc/pt-longjmp.c | 37 + .../unix/sysv/linux/powerpc/pt-vfork.S | 5 + .../unix/sysv/linux/powerpc/pthread_once.c | 101 + .../sysv/linux/powerpc/pthread_spin_unlock.c | 29 + .../unix/sysv/linux/powerpc/sem_post.c | 47 + .../unix/sysv/linux/powerpc/sysdep-cancel.h | 5 + .../sysdeps/unix/sysv/linux/powerpc/vfork.S | 5 + .../nptl/sysdeps/unix/sysv/linux/pt-accept.S | 12 + .../nptl/sysdeps/unix/sysv/linux/pt-close.S | 9 + .../nptl/sysdeps/unix/sysv/linux/pt-connect.S | 12 + .../nptl/sysdeps/unix/sysv/linux/pt-fcntl.c | 1 + .../nptl/sysdeps/unix/sysv/linux/pt-fork.c | 29 + .../nptl/sysdeps/unix/sysv/linux/pt-fsync.c | 2 + .../nptl/sysdeps/unix/sysv/linux/pt-llseek.c | 3 + .../nptl/sysdeps/unix/sysv/linux/pt-lseek.S | 7 + .../nptl/sysdeps/unix/sysv/linux/pt-msgrcv.c | 2 + .../nptl/sysdeps/unix/sysv/linux/pt-msgsnd.c | 2 + .../nptl/sysdeps/unix/sysv/linux/pt-msync.S | 7 + .../sysdeps/unix/sysv/linux/pt-nanosleep.S | 9 + .../nptl/sysdeps/unix/sysv/linux/pt-open.S | 9 + .../nptl/sysdeps/unix/sysv/linux/pt-open64.c | 1 + .../nptl/sysdeps/unix/sysv/linux/pt-pause.S | 7 + .../sysdeps/unix/sysv/linux/pt-pread_pwrite.c | 1 + .../nptl/sysdeps/unix/sysv/linux/pt-raise.c | 52 + .../nptl/sysdeps/unix/sysv/linux/pt-read.S | 9 + .../nptl/sysdeps/unix/sysv/linux/pt-recv.S | 12 + .../sysdeps/unix/sysv/linux/pt-recvfrom.S | 12 + .../nptl/sysdeps/unix/sysv/linux/pt-recvmsg.S | 12 + .../nptl/sysdeps/unix/sysv/linux/pt-send.S | 12 + .../nptl/sysdeps/unix/sysv/linux/pt-sendmsg.S | 12 + .../nptl/sysdeps/unix/sysv/linux/pt-sendto.S | 12 + .../nptl/sysdeps/unix/sysv/linux/pt-sigwait.c | 2 + .../nptl/sysdeps/unix/sysv/linux/pt-sleep.c | 2 + .../nptl/sysdeps/unix/sysv/linux/pt-tcdrain.c | 1 + .../nptl/sysdeps/unix/sysv/linux/pt-wait.c | 2 + .../nptl/sysdeps/unix/sysv/linux/pt-waitpid.c | 1 + .../nptl/sysdeps/unix/sysv/linux/pt-write.S | 9 + .../unix/sysv/linux/pthread-pi-defines.sym | 8 + .../sysv/linux/pthread_attr_getaffinity.c | 55 + .../sysv/linux/pthread_attr_setaffinity.c | 81 + .../unix/sysv/linux/pthread_getaffinity.c | 46 + .../unix/sysv/linux/pthread_getcpuclockid.c | 57 + .../sysdeps/unix/sysv/linux/pthread_kill.c | 78 + .../unix/sysv/linux/pthread_mutex_cond_lock.c | 14 + .../unix/sysv/linux/pthread_setaffinity.c | 92 + .../unix/sysv/linux/pthread_sigqueue.c | 83 + .../sysdeps/unix/sysv/linux/pthread_yield.c | 30 + .../nptl/sysdeps/unix/sysv/linux/raise.c | 74 + .../nptl/sysdeps/unix/sysv/linux/read.S | 19 + .../nptl/sysdeps/unix/sysv/linux/recv.S | 12 + .../nptl/sysdeps/unix/sysv/linux/recvfrom.S | 12 + .../nptl/sysdeps/unix/sysv/linux/recvmsg.S | 12 + .../sysdeps/unix/sysv/linux/register-atfork.c | 149 + .../nptl/sysdeps/unix/sysv/linux/sem_post.c | 58 + .../sysdeps/unix/sysv/linux/sem_timedwait.c | 111 + .../sysdeps/unix/sysv/linux/sem_trywait.c | 44 + .../nptl/sysdeps/unix/sysv/linux/sem_wait.c | 84 + .../nptl/sysdeps/unix/sysv/linux/send.S | 12 + .../nptl/sysdeps/unix/sysv/linux/sendmsg.S | 12 + .../nptl/sysdeps/unix/sysv/linux/sendto.S | 12 + .../nptl/sysdeps/unix/sysv/linux/sh/Makefile | 13 + .../sysdeps/unix/sysv/linux/sh/Makefile.arch | 46 + .../unix/sysv/linux/sh/bits/pthreadtypes.h | 183 + .../unix/sysv/linux/sh/bits/semaphore.h | 36 + .../nptl/sysdeps/unix/sysv/linux/sh/clone.S | 2 + .../sysdeps/unix/sysv/linux/sh/createthread.c | 24 + .../nptl/sysdeps/unix/sysv/linux/sh/fork.c | 30 + .../unix/sysv/linux/sh/libc-lowlevellock.S | 19 + .../unix/sysv/linux/sh/lowlevel-atomic.h | 81 + .../sysdeps/unix/sysv/linux/sh/lowlevellock.S | 540 + .../sysdeps/unix/sysv/linux/sh/lowlevellock.h | 420 + .../unix/sysv/linux/sh/lowlevelrobustlock.S | 265 + .../sysdeps/unix/sysv/linux/sh/pt-initfini.c | 126 + .../sysdeps/unix/sysv/linux/sh/pt-vfork.S | 65 + .../unix/sysv/linux/sh/pthread_barrier_wait.S | 216 + .../sysv/linux/sh/pthread_cond_broadcast.S | 263 + .../unix/sysv/linux/sh/pthread_cond_signal.S | 190 + .../sysv/linux/sh/pthread_cond_timedwait.S | 861 + .../unix/sysv/linux/sh/pthread_cond_wait.S | 754 + .../sysdeps/unix/sysv/linux/sh/pthread_once.S | 263 + .../sysv/linux/sh/pthread_rwlock_rdlock.S | 255 + .../linux/sh/pthread_rwlock_timedrdlock.S | 314 + .../linux/sh/pthread_rwlock_timedwrlock.S | 298 + .../sysv/linux/sh/pthread_rwlock_unlock.S | 199 + .../sysv/linux/sh/pthread_rwlock_wrlock.S | 235 + .../sysdeps/unix/sysv/linux/sh/sem_post.S | 110 + .../unix/sysv/linux/sh/sem_timedwait.S | 358 + .../sysdeps/unix/sysv/linux/sh/sem_trywait.S | 90 + .../sysdeps/unix/sysv/linux/sh/sem_wait.S | 303 + .../unix/sysv/linux/sh/sh4/lowlevellock.h | 4 + .../nptl/sysdeps/unix/sysv/linux/sh/smp.h | 24 + .../unix/sysv/linux/sh/sysdep-cancel.h | 169 + .../nptl/sysdeps/unix/sysv/linux/sh/vfork.S | 71 + .../sysdeps/unix/sysv/linux/sigtimedwait.c | 88 + .../nptl/sysdeps/unix/sysv/linux/sigwait.c | 2 + .../sysdeps/unix/sysv/linux/sigwaitinfo.c | 88 + .../nptl/sysdeps/unix/sysv/linux/sleep.c | 2 + .../nptl/sysdeps/unix/sysv/linux/smp.h | 28 + .../sysdeps/unix/sysv/linux/sparc/Makefile | 13 + .../unix/sysv/linux/sparc/Makefile.arch | 27 + .../unix/sysv/linux/sparc/bits/local_lim.h | 100 + .../unix/sysv/linux/sparc/bits/pthreadtypes.h | 221 + .../unix/sysv/linux/sparc/bits/semaphore.h | 41 + .../sysdeps/unix/sysv/linux/sparc/clone.S | 5 + .../nptl/sysdeps/unix/sysv/linux/sparc/fork.c | 29 + .../unix/sysv/linux/sparc/internaltypes.h | 34 + .../unix/sysv/linux/sparc/libc-lowlevellock.c | 21 + .../unix/sysv/linux/sparc/lowlevellock.c | 133 + .../unix/sysv/linux/sparc/lowlevellock.h | 297 + .../sysdeps/unix/sysv/linux/sparc/pt-vfork.S | 5 + .../linux/sparc/pthread_barrier_destroy.c | 45 + .../sysv/linux/sparc/pthread_barrier_init.c | 55 + .../sysv/linux/sparc/pthread_barrier_wait.c | 1 + .../unix/sysv/linux/sparc/pthread_once.c | 95 + .../sysdeps/unix/sysv/linux/sparc/sem_init.c | 57 + .../unix/sysv/linux/sparc/sparc32/clone.S | 2 + .../unix/sysv/linux/sparc/sparc32/pt-vfork.S | 45 + .../sparc/sparc32/pthread_barrier_wait.c | 94 + .../unix/sysv/linux/sparc/sparc32/sem_post.c | 55 + .../sysv/linux/sparc/sparc32/sem_timedwait.c | 148 + .../sysv/linux/sparc/sparc32/sem_trywait.c | 54 + .../unix/sysv/linux/sparc/sparc32/sem_wait.c | 127 + .../sysv/linux/sparc/sparc32/sysdep-cancel.h | 112 + .../unix/sysv/linux/sparc/sparc32/vfork.S | 49 + .../unix/sysv/linux/sparc/sparc64/clone.S | 2 + .../unix/sysv/linux/sparc/sparc64/pt-vfork.S | 45 + .../sysv/linux/sparc/sparc64/sysdep-cancel.h | 110 + .../sysv/linux/sparc/sparc64/timer_create.c | 1 + .../sysv/linux/sparc/sparc64/timer_delete.c | 1 + .../sysv/linux/sparc/sparc64/timer_getoverr.c | 1 + .../sysv/linux/sparc/sparc64/timer_gettime.c | 1 + .../sysv/linux/sparc/sparc64/timer_settime.c | 1 + .../unix/sysv/linux/sparc/sparc64/vfork.S | 49 + .../unix/sysv/linux/sparc/sysdep-cancel.h | 5 + .../sysdeps/unix/sysv/linux/sparc/vfork.S | 5 + .../sysdeps/unix/sysv/linux/structsem.sym | 12 + .../sysdeps/unix/sysv/linux/timer_create.c | 243 + .../sysdeps/unix/sysv/linux/timer_delete.c | 115 + .../sysdeps/unix/sysv/linux/timer_getoverr.c | 81 + .../sysdeps/unix/sysv/linux/timer_gettime.c | 83 + .../sysdeps/unix/sysv/linux/timer_routines.c | 204 + .../sysdeps/unix/sysv/linux/timer_settime.c | 88 + .../unix/sysv/linux/unregister-atfork.c | 123 + .../sysdeps/unix/sysv/linux/unwindbuf.sym | 7 + .../nptl/sysdeps/unix/sysv/linux/waitpid.S | 23 + .../nptl/sysdeps/unix/sysv/linux/write.S | 19 + .../sysdeps/unix/sysv/linux/x86_64/Makefile | 13 + .../unix/sysv/linux/x86_64/Makefile.arch | 38 + .../sysv/linux/x86_64/bits/pthreadtypes.h | 225 + .../unix/sysv/linux/x86_64/bits/semaphore.h | 41 + .../unix/sysv/linux/x86_64/cancellation.S | 116 + .../sysdeps/unix/sysv/linux/x86_64/clone.S | 3 + .../unix/sysv/linux/x86_64/compat-timer.h | 46 + .../sysdeps/unix/sysv/linux/x86_64/fork.c | 31 + .../sysv/linux/x86_64/libc-cancellation.S | 22 + .../sysv/linux/x86_64/libc-lowlevellock.S | 20 + .../sysv/linux/x86_64/librt-cancellation.S | 22 + .../unix/sysv/linux/x86_64/lowlevellock.S | 457 + .../unix/sysv/linux/x86_64/lowlevellock.h | 598 + .../sysv/linux/x86_64/lowlevelrobustlock.S | 306 + .../sysv/linux/x86_64/pt-__syscall_error.c | 1 + .../sysdeps/unix/sysv/linux/x86_64/pt-vfork.S | 33 + .../sysv/linux/x86_64/pthread_barrier_wait.S | 161 + .../linux/x86_64/pthread_cond_broadcast.S | 178 + .../sysv/linux/x86_64/pthread_cond_signal.S | 161 + .../linux/x86_64/pthread_cond_timedwait.S | 804 + .../sysv/linux/x86_64/pthread_cond_wait.S | 487 + .../unix/sysv/linux/x86_64/pthread_once.S | 190 + .../sysv/linux/x86_64/pthread_rwlock_rdlock.S | 180 + .../linux/x86_64/pthread_rwlock_timedrdlock.S | 276 + .../linux/x86_64/pthread_rwlock_timedwrlock.S | 268 + .../sysv/linux/x86_64/pthread_rwlock_unlock.S | 131 + .../sysv/linux/x86_64/pthread_rwlock_wrlock.S | 168 + .../sysv/linux/x86_64/pthread_setaffinity.c | 14 + .../sysv/linux/x86_64/pthread_spin_init.c | 1 + .../sysv/linux/x86_64/pthread_spin_unlock.S | 1 + .../sysdeps/unix/sysv/linux/x86_64/sem_post.S | 89 + .../unix/sysv/linux/x86_64/sem_timedwait.S | 379 + .../unix/sysv/linux/x86_64/sem_trywait.S | 52 + .../sysdeps/unix/sysv/linux/x86_64/sem_wait.S | 174 + .../unix/sysv/linux/x86_64/sysdep-cancel.h | 111 + .../sysdeps/unix/sysv/linux/x86_64/vfork.S | 43 + .../nptl/sysdeps/x86_64/Makefile.arch | 10 + .../libpthread/nptl/sysdeps/x86_64/dl-tls.h | 29 + .../nptl/sysdeps/x86_64/jmpbuf-unwind.h | 31 + .../nptl/sysdeps/x86_64/pthread_spin_init.c | 1 + .../nptl/sysdeps/x86_64/pthread_spin_lock.c | 1 + .../sysdeps/x86_64/pthread_spin_trylock.S | 40 + .../nptl/sysdeps/x86_64/pthread_spin_unlock.S | 31 + .../nptl/sysdeps/x86_64/pthreaddef.h | 43 + .../nptl/sysdeps/x86_64/tcb-offsets.sym | 28 + .../libpthread/nptl/sysdeps/x86_64/tls.h | 438 + .../contrib/uclibc/libpthread/nptl/unwind.c | 177 + .../lib/contrib/uclibc/libpthread/nptl/vars.c | 43 + .../contrib/uclibc/libpthread/nptl/version.c | 45 + .../contrib/uclibc/libpthread/nptl/version.h | 1 + .../uclibc/libpthread/nptl_db/ChangeLog | 207 + .../uclibc/libpthread/nptl_db/Makefile | 13 + .../uclibc/libpthread/nptl_db/Makefile.in | 69 + .../uclibc/libpthread/nptl_db/db_info.c | 103 + .../uclibc/libpthread/nptl_db/fetch-value.c | 284 + .../uclibc/libpthread/nptl_db/proc_service.h | 87 + .../uclibc/libpthread/nptl_db/structs.def | 88 + .../uclibc/libpthread/nptl_db/td_init.c | 32 + .../uclibc/libpthread/nptl_db/td_log.c | 32 + .../libpthread/nptl_db/td_symbol_list.c | 87 + .../libpthread/nptl_db/td_ta_clear_event.c | 77 + .../uclibc/libpthread/nptl_db/td_ta_delete.c | 42 + .../libpthread/nptl_db/td_ta_enable_stats.c | 35 + .../libpthread/nptl_db/td_ta_event_addr.c | 61 + .../libpthread/nptl_db/td_ta_event_getmsg.c | 105 + .../libpthread/nptl_db/td_ta_get_nthreads.c | 42 + .../uclibc/libpthread/nptl_db/td_ta_get_ph.c | 36 + .../libpthread/nptl_db/td_ta_get_stats.c | 35 + .../libpthread/nptl_db/td_ta_map_id2thr.c | 38 + .../libpthread/nptl_db/td_ta_map_lwp2thr.c | 178 + .../uclibc/libpthread/nptl_db/td_ta_new.c | 65 + .../libpthread/nptl_db/td_ta_reset_stats.c | 35 + .../libpthread/nptl_db/td_ta_set_event.c | 77 + .../libpthread/nptl_db/td_ta_setconcurrency.c | 35 + .../libpthread/nptl_db/td_ta_thr_iter.c | 148 + .../libpthread/nptl_db/td_ta_tsd_iter.c | 81 + .../libpthread/nptl_db/td_thr_clear_event.c | 75 + .../libpthread/nptl_db/td_thr_dbresume.c | 30 + .../libpthread/nptl_db/td_thr_dbsuspend.c | 30 + .../libpthread/nptl_db/td_thr_event_enable.c | 32 + .../libpthread/nptl_db/td_thr_event_getmsg.c | 119 + .../libpthread/nptl_db/td_thr_get_info.c | 110 + .../libpthread/nptl_db/td_thr_getfpregs.c | 53 + .../libpthread/nptl_db/td_thr_getgregs.c | 53 + .../libpthread/nptl_db/td_thr_getxregs.c | 30 + .../libpthread/nptl_db/td_thr_getxregsize.c | 30 + .../libpthread/nptl_db/td_thr_set_event.c | 75 + .../libpthread/nptl_db/td_thr_setfpregs.c | 50 + .../libpthread/nptl_db/td_thr_setgregs.c | 50 + .../libpthread/nptl_db/td_thr_setprio.c | 30 + .../libpthread/nptl_db/td_thr_setsigpending.c | 31 + .../libpthread/nptl_db/td_thr_setxregs.c | 30 + .../libpthread/nptl_db/td_thr_sigsetmask.c | 30 + .../libpthread/nptl_db/td_thr_tls_get_addr.c | 43 + .../libpthread/nptl_db/td_thr_tlsbase.c | 55 + .../uclibc/libpthread/nptl_db/td_thr_tsd.c | 96 + .../libpthread/nptl_db/td_thr_validate.c | 91 + .../uclibc/libpthread/nptl_db/thread_db.h | 459 + .../uclibc/libpthread/nptl_db/thread_dbP.h | 258 + .../lib/contrib/uclibc/libresolv/Makefile | 13 + .../lib/contrib/uclibc/libresolv/Makefile.in | 52 + .../lib/contrib/uclibc/libresolv/resolv.c | 18 + .../uclibc/lib/contrib/uclibc/librt/Makefile | 13 + .../lib/contrib/uclibc/librt/Makefile.in | 70 + .../uclibc/librt/clock_getcpuclockid.c | 104 + .../lib/contrib/uclibc/librt/clock_gettime.c | 301 + .../contrib/uclibc/librt/clock_nanosleep.c | 96 + .../uclibc/librt/kernel-posix-cpu-timers.h | 18 + .../uclibc/librt/kernel-posix-timers.h | 58 + .../lib/contrib/uclibc/librt/mq_close.c | 22 + .../lib/contrib/uclibc/librt/mq_getsetattr.c | 36 + .../lib/contrib/uclibc/librt/mq_notify.c | 28 + .../uclibc/lib/contrib/uclibc/librt/mq_open.c | 52 + .../lib/contrib/uclibc/librt/mq_receive.c | 46 + .../uclibc/lib/contrib/uclibc/librt/mq_send.c | 45 + .../contrib/uclibc/librt/mq_timedreceive.S | 10 + .../lib/contrib/uclibc/librt/mq_timedsend.S | 10 + .../lib/contrib/uclibc/librt/mq_unlink.c | 39 + l4/pkg/uclibc/lib/contrib/uclibc/librt/shm.c | 102 + .../lib/contrib/uclibc/librt/timer_create.c | 71 + .../lib/contrib/uclibc/librt/timer_delete.c | 33 + .../lib/contrib/uclibc/librt/timer_getoverr.c | 26 + .../lib/contrib/uclibc/librt/timer_gettime.c | 27 + .../lib/contrib/uclibc/librt/timer_settime.c | 28 + .../lib/contrib/uclibc/libubacktrace/Makefile | 14 + .../contrib/uclibc/libubacktrace/Makefile.in | 84 + .../contrib/uclibc/libubacktrace/backtrace.c | 19 + .../uclibc/libubacktrace/backtracesyms.c | 105 + .../uclibc/libubacktrace/backtracesymsfd.c | 116 + .../libubacktrace/sysdeps/sh/Makefile.arch | 12 + .../libubacktrace/sysdeps/sh/backtrace.c | 84 + .../lib/contrib/uclibc/libutil/Makefile | 13 + .../lib/contrib/uclibc/libutil/Makefile.in | 68 + .../lib/contrib/uclibc/libutil/forkpty.c | 55 + .../uclibc/lib/contrib/uclibc/libutil/login.c | 60 + .../lib/contrib/uclibc/libutil/login_tty.c | 71 + .../lib/contrib/uclibc/libutil/logout.c | 79 + .../lib/contrib/uclibc/libutil/logwtmp.c | 55 + .../lib/contrib/uclibc/libutil/openpty.c | 157 + .../uclibc/lib/contrib/uclibc/test/.gitignore | 304 + .../lib/contrib/uclibc/test/API/Makefile | 7 + .../lib/contrib/uclibc/test/API/Makefile.in | 26 + .../contrib/uclibc/test/API/aio.SUSv4.syms | 8 + .../uclibc/test/API/arpa_inet.SUSv4.syms | 8 + .../uclibc/test/API/complex.SUSv4.syms | 66 + .../uclibc/test/API/ctype-CX.SUSv4.syms | 14 + .../uclibc/test/API/ctype-OBXSI.SUSv4.syms | 2 + .../contrib/uclibc/test/API/ctype.SUSv4.syms | 14 + .../uclibc/test/API/dirent-XSI.SUSv4.syms | 2 + .../contrib/uclibc/test/API/dirent.SUSv4.syms | 9 + .../contrib/uclibc/test/API/dlfcn.SUSv4.syms | 4 + .../uclibc/test/API/fcntl-ADV.SUSv4.syms | 2 + .../contrib/uclibc/test/API/fcntl.SUSv4.syms | 4 + .../contrib/uclibc/test/API/fenv.SUSv4.syms | 11 + .../contrib/uclibc/test/API/ftw-OB.SUSv4.syms | 1 + .../contrib/uclibc/test/API/ftw.SUSv4.syms | 1 + .../contrib/uclibc/test/API/glob.SUSv4.syms | 2 + .../uclibc/test/API/grp-XSI.SUSv4.syms | 1 + .../contrib/uclibc/test/API/grp.SUSv4.syms | 6 + .../lib/contrib/uclibc/test/API/html2input.sh | 119 + .../contrib/uclibc/test/API/iconv.SUSv4.syms | 3 + .../uclibc/test/API/inttypes.SUSv4.syms | 6 + .../contrib/uclibc/test/API/libgen.SUSv4.syms | 2 + .../uclibc/test/API/locale-CX.SUSv4.syms | 4 + .../contrib/uclibc/test/API/locale.SUSv4.syms | 2 + .../uclibc/test/API/math-XSI.SUSv4.syms | 6 + .../contrib/uclibc/test/API/math.SUSv4.syms | 171 + .../uclibc/test/API/monetary.SUSv4.syms | 2 + .../contrib/uclibc/test/API/mqueue.SUSv4.syms | 10 + .../contrib/uclibc/test/API/ndbm.SUSv4.syms | 9 + .../contrib/uclibc/test/API/net_if.SUSv4.syms | 4 + .../contrib/uclibc/test/API/netdb.SUSv4.syms | 22 + .../uclibc/test/API/nl_types.SUSv4.syms | 3 + .../uclibc/test/API/pthread-MC1.SUSv4.syms | 2 + .../uclibc/test/API/pthread-OBXSI.SUSv4.syms | 2 + .../test/API/pthread-RPP|TPP.SUSv4.syms | 4 + .../uclibc/test/API/pthread-TCT.SUSv4.syms | 1 + .../uclibc/test/API/pthread-TPS.SUSv4.syms | 9 + .../uclibc/test/API/pthread-TSATSS.SUSv4.syms | 2 + .../uclibc/test/API/pthread-TSH.SUSv4.syms | 8 + .../uclibc/test/API/pthread-TSS.SUSv4.syms | 2 + .../uclibc/test/API/pthread.SUSv4.syms | 70 + .../uclibc/test/API/pwd-XSI.SUSv4.syms | 3 + .../contrib/uclibc/test/API/pwd.SUSv4.syms | 4 + .../contrib/uclibc/test/API/regex.SUSv4.syms | 4 + .../uclibc/test/API/sched-PS.SUSv4.syms | 4 + .../uclibc/test/API/sched-PS|TPS.SUSv4.syms | 3 + .../contrib/uclibc/test/API/sched.SUSv4.syms | 1 + .../contrib/uclibc/test/API/search.SUSv4.syms | 11 + .../uclibc/test/API/semaphore.SUSv4.syms | 10 + .../lib/contrib/uclibc/test/API/separate.awk | 48 + .../uclibc/test/API/setjmp-CX.SUSv4.syms | 1 + .../uclibc/test/API/setjmp-OBXSI.SUSv4.syms | 1 + .../contrib/uclibc/test/API/setjmp.SUSv4.syms | 1 + .../uclibc/test/API/signal-CX.SUSv4.syms | 18 + .../uclibc/test/API/signal-OBXSI.SUSv4.syms | 6 + .../uclibc/test/API/signal-XSI.SUSv4.syms | 2 + .../contrib/uclibc/test/API/signal.SUSv4.syms | 2 + .../uclibc/test/API/spawn-PS.SUSv4.syms | 4 + .../contrib/uclibc/test/API/spawn.SUSv4.syms | 17 + .../uclibc/test/API/stdio-CX.SUSv4.syms | 20 + .../uclibc/test/API/stdio-OB.SUSv4.syms | 2 + .../uclibc/test/API/stdio-OBXSI.SUSv4.syms | 1 + .../contrib/uclibc/test/API/stdio.SUSv4.syms | 44 + .../uclibc/test/API/stdlib-ADV.SUSv4.syms | 1 + .../uclibc/test/API/stdlib-CX.SUSv4.syms | 4 + .../uclibc/test/API/stdlib-OBCX.SUSv4.syms | 1 + .../uclibc/test/API/stdlib-XSI.SUSv4.syms | 22 + .../contrib/uclibc/test/API/stdlib.SUSv4.syms | 37 + .../uclibc/test/API/string-CX.SUSv4.syms | 11 + .../uclibc/test/API/string-XSI.SUSv4.syms | 1 + .../contrib/uclibc/test/API/string.SUSv4.syms | 22 + .../uclibc/test/API/strings-XSI.SUSv4.syms | 1 + .../uclibc/test/API/strings.SUSv4.syms | 4 + .../uclibc/test/API/stropts.SUSv4.syms | 8 + .../uclibc/test/API/sys_mman-ADV.SUSv4.syms | 1 + .../uclibc/test/API/sys_mman-ML.SUSv4.syms | 2 + .../uclibc/test/API/sys_mman-MLR.SUSv4.syms | 2 + .../uclibc/test/API/sys_mman-SHM.SUSv4.syms | 2 + .../uclibc/test/API/sys_mman-TYM.SUSv4.syms | 3 + .../test/API/sys_mman-XSI|SIO.SUSv4.syms | 1 + .../uclibc/test/API/sys_mman.SUSv4.syms | 3 + .../uclibc/test/API/sys_msg.SUSv4.syms | 4 + .../uclibc/test/API/sys_resource.SUSv4.syms | 5 + .../uclibc/test/API/sys_select.SUSv4.syms | 6 + .../uclibc/test/API/sys_sem.SUSv4.syms | 3 + .../uclibc/test/API/sys_shm.SUSv4.syms | 4 + .../uclibc/test/API/sys_socket.SUSv4.syms | 18 + .../uclibc/test/API/sys_stat-XSI.SUSv4.syms | 2 + .../uclibc/test/API/sys_stat.SUSv4.syms | 14 + .../uclibc/test/API/sys_statvfs.SUSv4.syms | 2 + .../uclibc/test/API/sys_time-OB.SUSv4.syms | 3 + .../uclibc/test/API/sys_time.SUSv4.syms | 2 + .../uclibc/test/API/sys_uio.SUSv4.syms | 2 + .../uclibc/test/API/sys_wait.SUSv4.syms | 3 + .../contrib/uclibc/test/API/syslog.SUSv4.syms | 4 + .../uclibc/test/API/termios.SUSv4.syms | 11 + .../uclibc/test/API/time-CPT.SUSv4.syms | 1 + .../uclibc/test/API/time-CX.SUSv4.syms | 15 + .../uclibc/test/API/time-OB.SUSv4.syms | 2 + .../uclibc/test/API/time-OBCX.SUSv4.syms | 2 + .../uclibc/test/API/time-XSI.SUSv4.syms | 4 + .../contrib/uclibc/test/API/time.SUSv4.syms | 7 + .../uclibc/test/API/trace-TEF.SUSv4.syms | 8 + .../uclibc/test/API/trace-TRI.SUSv4.syms | 2 + .../uclibc/test/API/trace-TRL.SUSv4.syms | 9 + .../contrib/uclibc/test/API/trace.SUSv4.syms | 31 + .../lib/contrib/uclibc/test/API/tst-API.sh | 16 + .../uclibc/test/API/unistd-CX.SUSv4.syms | 1 + .../uclibc/test/API/unistd-FSC.SUSv4.syms | 1 + .../uclibc/test/API/unistd-OBXSI.SUSv4.syms | 1 + .../uclibc/test/API/unistd-SIO.SUSv4.syms | 1 + .../uclibc/test/API/unistd-XSI.SUSv4.syms | 9 + .../contrib/uclibc/test/API/unistd.SUSv4.syms | 74 + .../contrib/uclibc/test/API/utmpx.SUSv4.syms | 6 + .../uclibc/test/API/wchar-CX.SUSv4.syms | 13 + .../uclibc/test/API/wchar-OBXSI.SUSv4.syms | 15 + .../uclibc/test/API/wchar-XSI.SUSv4.syms | 2 + .../contrib/uclibc/test/API/wchar.SUSv4.syms | 59 + .../uclibc/test/API/wctype-CX.SUSv4.syms | 18 + .../contrib/uclibc/test/API/wctype.SUSv4.syms | 18 + .../uclibc/test/API/wordexp.SUSv4.syms | 2 + .../uclibc/lib/contrib/uclibc/test/Makefile | 76 + l4/pkg/uclibc/lib/contrib/uclibc/test/README | 85 + .../uclibc/lib/contrib/uclibc/test/Rules.mak | 140 + .../uclibc/lib/contrib/uclibc/test/Test.mak | 129 + .../lib/contrib/uclibc/test/args/Makefile | 7 + .../lib/contrib/uclibc/test/args/Makefile.in | 9 + .../lib/contrib/uclibc/test/args/arg_test.c | 40 + .../uclibc/test/args/arg_test.out.good | 13 + .../uclibc/test/args/arg_test_glibc.out.good | 13 + .../lib/contrib/uclibc/test/assert/Makefile | 7 + .../contrib/uclibc/test/assert/Makefile.in | 5 + .../lib/contrib/uclibc/test/assert/assert.c | 47 + .../lib/contrib/uclibc/test/build/Makefile | 7 + .../uclibc/test/build/check_config_options.sh | 21 + .../lib/contrib/uclibc/test/crypt/Makefile | 7 + .../lib/contrib/uclibc/test/crypt/Makefile.in | 6 + .../lib/contrib/uclibc/test/crypt/crypt.c | 113 + .../lib/contrib/uclibc/test/crypt/crypt.input | 171 + .../contrib/uclibc/test/crypt/crypt.out.good | 172 + .../lib/contrib/uclibc/test/crypt/md5c-test.c | 19 + .../lib/contrib/uclibc/test/ctype/Makefile | 7 + .../lib/contrib/uclibc/test/ctype/Makefile.in | 4 + .../lib/contrib/uclibc/test/ctype/ctype.c | 250 + .../lib/contrib/uclibc/test/dlopen/Makefile | 12 + .../contrib/uclibc/test/dlopen/Makefile.in | 39 + .../lib/contrib/uclibc/test/dlopen/dladdr.c | 25 + .../lib/contrib/uclibc/test/dlopen/dlafk.c | 36 + .../lib/contrib/uclibc/test/dlopen/dlstatic.c | 43 + .../lib/contrib/uclibc/test/dlopen/dltest.c | 41 + .../lib/contrib/uclibc/test/dlopen/dltest2.c | 1 + .../lib/contrib/uclibc/test/dlopen/dlundef.c | 29 + .../contrib/uclibc/test/dlopen/libafk-temp.c | 1 + .../lib/contrib/uclibc/test/dlopen/libafk.c | 1 + .../contrib/uclibc/test/dlopen/libstatic.c | 15 + .../lib/contrib/uclibc/test/dlopen/libtest.c | 11 + .../lib/contrib/uclibc/test/dlopen/libtest1.c | 40 + .../lib/contrib/uclibc/test/dlopen/libtest2.c | 38 + .../lib/contrib/uclibc/test/dlopen/libtest3.c | 1 + .../lib/contrib/uclibc/test/dlopen/libundef.c | 1 + .../lib/contrib/uclibc/test/dlopen/test1.c | 33 + .../lib/contrib/uclibc/test/dlopen/test2.c | 39 + .../lib/contrib/uclibc/test/dlopen/test3.c | 13 + .../lib/contrib/uclibc/test/inet/Makefile | 7 + .../lib/contrib/uclibc/test/inet/Makefile.in | 7 + .../lib/contrib/uclibc/test/inet/bug-if1.c | 54 + .../uclibc/test/inet/gethost_r-align.c | 50 + .../lib/contrib/uclibc/test/inet/gethostid.c | 6 + .../lib/contrib/uclibc/test/inet/getnetent.c | 17 + .../contrib/uclibc/test/inet/if_nameindex.c | 61 + .../lib/contrib/uclibc/test/inet/tst-aton.c | 80 + .../uclibc/test/inet/tst-ethers-line.c | 54 + .../lib/contrib/uclibc/test/inet/tst-ethers.c | 33 + .../contrib/uclibc/test/inet/tst-network.c | 105 + .../lib/contrib/uclibc/test/inet/tst-ntoa.c | 36 + .../lib/contrib/uclibc/test/librt/Makefile | 7 + .../lib/contrib/uclibc/test/librt/Makefile.in | 4 + .../lib/contrib/uclibc/test/librt/shmtest.c | 104 + .../contrib/uclibc/test/locale-mbwc/Makefile | 7 + .../uclibc/test/locale-mbwc/Makefile.in | 27 + .../uclibc/test/locale-mbwc/dat_isw-funcs.h | 37 + .../uclibc/test/locale-mbwc/dat_iswalnum.c | 196 + .../uclibc/test/locale-mbwc/dat_iswalpha.c | 169 + .../uclibc/test/locale-mbwc/dat_iswcntrl.c | 125 + .../uclibc/test/locale-mbwc/dat_iswctype.c | 667 + .../uclibc/test/locale-mbwc/dat_iswdigit.c | 125 + .../uclibc/test/locale-mbwc/dat_iswgraph.c | 167 + .../uclibc/test/locale-mbwc/dat_iswlower.c | 96 + .../uclibc/test/locale-mbwc/dat_iswprint.c | 170 + .../uclibc/test/locale-mbwc/dat_iswpunct.c | 155 + .../uclibc/test/locale-mbwc/dat_iswspace.c | 129 + .../uclibc/test/locale-mbwc/dat_iswupper.c | 94 + .../uclibc/test/locale-mbwc/dat_iswxdigit.c | 125 + .../uclibc/test/locale-mbwc/dat_mblen.c | 137 + .../uclibc/test/locale-mbwc/dat_mbrlen.c | 222 + .../uclibc/test/locale-mbwc/dat_mbrtowc.c | 140 + .../uclibc/test/locale-mbwc/dat_mbsrtowcs.c | 180 + .../uclibc/test/locale-mbwc/dat_mbstowcs.c | 190 + .../uclibc/test/locale-mbwc/dat_mbtowc.c | 444 + .../uclibc/test/locale-mbwc/dat_strcoll.c | 209 + .../uclibc/test/locale-mbwc/dat_strfmon.c | 268 + .../uclibc/test/locale-mbwc/dat_strxfrm.c | 147 + .../uclibc/test/locale-mbwc/dat_swscanf.c | 185 + .../uclibc/test/locale-mbwc/dat_tow-funcs.h | 24 + .../uclibc/test/locale-mbwc/dat_towctrans.c | 97 + .../uclibc/test/locale-mbwc/dat_towlower.c | 47 + .../uclibc/test/locale-mbwc/dat_towupper.c | 47 + .../uclibc/test/locale-mbwc/dat_wcrtomb.c | 122 + .../uclibc/test/locale-mbwc/dat_wcscat.c | 116 + .../uclibc/test/locale-mbwc/dat_wcschr.c | 94 + .../uclibc/test/locale-mbwc/dat_wcscmp.c | 137 + .../uclibc/test/locale-mbwc/dat_wcscoll.c | 210 + .../uclibc/test/locale-mbwc/dat_wcscpy.c | 44 + .../uclibc/test/locale-mbwc/dat_wcscspn.c | 164 + .../uclibc/test/locale-mbwc/dat_wcslen.c | 62 + .../uclibc/test/locale-mbwc/dat_wcsncat.c | 158 + .../uclibc/test/locale-mbwc/dat_wcsncmp.c | 144 + .../uclibc/test/locale-mbwc/dat_wcsncpy.c | 119 + .../uclibc/test/locale-mbwc/dat_wcspbrk.c | 176 + .../uclibc/test/locale-mbwc/dat_wcsrtombs.c | 272 + .../uclibc/test/locale-mbwc/dat_wcsspn.c | 179 + .../uclibc/test/locale-mbwc/dat_wcsstr.c | 175 + .../uclibc/test/locale-mbwc/dat_wcstod.c | 78 + .../uclibc/test/locale-mbwc/dat_wcstok.c | 138 + .../uclibc/test/locale-mbwc/dat_wcstombs.c | 271 + .../uclibc/test/locale-mbwc/dat_wcswidth.c | 263 + .../uclibc/test/locale-mbwc/dat_wcsxfrm.c | 102 + .../uclibc/test/locale-mbwc/dat_wctob.c | 61 + .../uclibc/test/locale-mbwc/dat_wctomb.c | 168 + .../uclibc/test/locale-mbwc/dat_wctrans.c | 99 + .../uclibc/test/locale-mbwc/dat_wctype.c | 189 + .../uclibc/test/locale-mbwc/dat_wcwidth.c | 149 + .../uclibc/test/locale-mbwc/tgn_funcdef.h | 160 + .../uclibc/test/locale-mbwc/tgn_locdef.h | 32 + .../uclibc/test/locale-mbwc/tsp_common.c | 64 + .../uclibc/test/locale-mbwc/tst2_mbrtowc.c | 21 + .../uclibc/test/locale-mbwc/tst_funcs.h | 296 + .../uclibc/test/locale-mbwc/tst_iswalnum.c | 10 + .../uclibc/test/locale-mbwc/tst_iswalpha.c | 10 + .../uclibc/test/locale-mbwc/tst_iswcntrl.c | 10 + .../uclibc/test/locale-mbwc/tst_iswctype.c | 53 + .../uclibc/test/locale-mbwc/tst_iswdigit.c | 11 + .../uclibc/test/locale-mbwc/tst_iswgraph.c | 10 + .../uclibc/test/locale-mbwc/tst_iswlower.c | 10 + .../uclibc/test/locale-mbwc/tst_iswprint.c | 10 + .../uclibc/test/locale-mbwc/tst_iswpunct.c | 10 + .../uclibc/test/locale-mbwc/tst_iswspace.c | 10 + .../uclibc/test/locale-mbwc/tst_iswupper.c | 10 + .../uclibc/test/locale-mbwc/tst_iswxdigit.c | 10 + .../uclibc/test/locale-mbwc/tst_mblen.c | 85 + .../uclibc/test/locale-mbwc/tst_mbrlen.c | 82 + .../uclibc/test/locale-mbwc/tst_mbrtowc.c | 103 + .../uclibc/test/locale-mbwc/tst_mbsrtowcs.c | 109 + .../uclibc/test/locale-mbwc/tst_mbstowcs.c | 98 + .../uclibc/test/locale-mbwc/tst_mbtowc.c | 130 + .../uclibc/test/locale-mbwc/tst_strcoll.c | 87 + .../uclibc/test/locale-mbwc/tst_strfmon.c | 74 + .../uclibc/test/locale-mbwc/tst_strxfrm.c | 136 + .../uclibc/test/locale-mbwc/tst_swscanf.c | 137 + .../uclibc/test/locale-mbwc/tst_towctrans.c | 82 + .../uclibc/test/locale-mbwc/tst_towlower.c | 11 + .../uclibc/test/locale-mbwc/tst_towupper.c | 10 + .../uclibc/test/locale-mbwc/tst_types.h | 729 + .../uclibc/test/locale-mbwc/tst_wcrtomb.c | 79 + .../uclibc/test/locale-mbwc/tst_wcscat.c | 78 + .../uclibc/test/locale-mbwc/tst_wcschr.c | 70 + .../uclibc/test/locale-mbwc/tst_wcscmp.c | 40 + .../uclibc/test/locale-mbwc/tst_wcscoll.c | 76 + .../uclibc/test/locale-mbwc/tst_wcscpy.c | 85 + .../uclibc/test/locale-mbwc/tst_wcscspn.c | 38 + .../uclibc/test/locale-mbwc/tst_wcslen.c | 31 + .../uclibc/test/locale-mbwc/tst_wcsncat.c | 75 + .../uclibc/test/locale-mbwc/tst_wcsncmp.c | 40 + .../uclibc/test/locale-mbwc/tst_wcsncpy.c | 93 + .../uclibc/test/locale-mbwc/tst_wcspbrk.c | 80 + .../uclibc/test/locale-mbwc/tst_wcsrtombs.c | 127 + .../uclibc/test/locale-mbwc/tst_wcsspn.c | 38 + .../uclibc/test/locale-mbwc/tst_wcsstr.c | 86 + .../uclibc/test/locale-mbwc/tst_wcstod.c | 69 + .../uclibc/test/locale-mbwc/tst_wcstok.c | 96 + .../uclibc/test/locale-mbwc/tst_wcstombs.c | 115 + .../uclibc/test/locale-mbwc/tst_wcswidth.c | 39 + .../uclibc/test/locale-mbwc/tst_wcsxfrm.c | 122 + .../uclibc/test/locale-mbwc/tst_wctob.c | 37 + .../uclibc/test/locale-mbwc/tst_wctomb.c | 99 + .../uclibc/test/locale-mbwc/tst_wctrans.c | 52 + .../uclibc/test/locale-mbwc/tst_wctype.c | 48 + .../uclibc/test/locale-mbwc/tst_wcwidth.c | 38 + .../lib/contrib/uclibc/test/locale/Makefile | 7 + .../contrib/uclibc/test/locale/Makefile.in | 29 + .../uclibc/test/locale/bug-iconv-trans.c | 68 + .../uclibc/test/locale/bug-usesetlocale.c | 38 + .../contrib/uclibc/test/locale/collate-test.c | 133 + .../contrib/uclibc/test/locale/dump-ctype.c | 164 + .../uclibc/test/locale/gen-unicode-ctype.c | 785 + .../uclibc/test/locale/show-ucs-data.c | 62 + .../contrib/uclibc/test/locale/tst-C-locale.c | 498 + .../test/locale/tst-ctype-de_DE.ISO-8859-1.in | 56 + .../contrib/uclibc/test/locale/tst-ctype.c | 447 + .../contrib/uclibc/test/locale/tst-digits.c | 249 + .../lib/contrib/uclibc/test/locale/tst-fmon.c | 68 + .../contrib/uclibc/test/locale/tst-langinfo.c | 284 + .../uclibc/test/locale/tst-langinfo.input | 303 + .../contrib/uclibc/test/locale/tst-leaks.c | 18 + .../contrib/uclibc/test/locale/tst-mbswcs1.c | 63 + .../contrib/uclibc/test/locale/tst-mbswcs2.c | 65 + .../contrib/uclibc/test/locale/tst-mbswcs3.c | 76 + .../contrib/uclibc/test/locale/tst-mbswcs4.c | 63 + .../contrib/uclibc/test/locale/tst-mbswcs5.c | 75 + .../contrib/uclibc/test/locale/tst-mbswcs6.c | 74 + .../contrib/uclibc/test/locale/tst-numeric.c | 74 + .../contrib/uclibc/test/locale/tst-rpmatch.c | 37 + .../uclibc/test/locale/tst-setlocale.c | 25 + .../contrib/uclibc/test/locale/tst-sscanf.c | 56 + .../contrib/uclibc/test/locale/tst-strfmon1.c | 42 + .../contrib/uclibc/test/locale/tst-trans.c | 71 + .../contrib/uclibc/test/locale/tst-wctype.c | 144 + .../contrib/uclibc/test/locale/tst-xlocale1.c | 75 + .../contrib/uclibc/test/locale/tst-xlocale2.c | 64 + .../uclibc/test/locale/tst_nl_langinfo.c | 296 + .../contrib/uclibc/test/locale/xfrm-test.c | 144 + .../lib/contrib/uclibc/test/malloc/Makefile | 7 + .../contrib/uclibc/test/malloc/Makefile.in | 4 + .../test/malloc/malloc-standard-alignment.c | 42 + .../lib/contrib/uclibc/test/malloc/malloc.c | 81 + .../contrib/uclibc/test/malloc/mallocbug.c | 67 + .../uclibc/test/malloc/realloc-can-shrink.c | 17 + .../lib/contrib/uclibc/test/malloc/realloc0.c | 13 + .../contrib/uclibc/test/malloc/testmalloc.c | 101 + .../contrib/uclibc/test/malloc/time_malloc.c | 62 + .../contrib/uclibc/test/malloc/tst-calloc.c | 128 + .../contrib/uclibc/test/malloc/tst-malloc.c | 73 + .../uclibc/test/malloc/tst-mallocfork.c | 51 + .../contrib/uclibc/test/malloc/tst-mcheck.c | 96 + .../contrib/uclibc/test/malloc/tst-obstack.c | 64 + .../contrib/uclibc/test/malloc/tst-valloc.c | 23 + .../lib/contrib/uclibc/test/math/Makefile | 7 + .../lib/contrib/uclibc/test/math/Makefile.in | 31 + .../lib/contrib/uclibc/test/math/basic-test.c | 125 + .../lib/contrib/uclibc/test/math/c99_test.c | 116 + .../contrib/uclibc/test/math/compile_test.c | 141 + .../lib/contrib/uclibc/test/math/fenv.h | 3 + .../lib/contrib/uclibc/test/math/gamma.c | 73 + .../contrib/uclibc/test/math/gen-libm-test.pl | 738 + .../lib/contrib/uclibc/test/math/ilogb.c | 52 + .../uclibc/test/math/libm-test-ulps-generic | 5 + .../uclibc/test/math/libm-test-ulps-i386 | 1261 ++ .../uclibc/test/math/libm-test-ulps-ia64 | 1146 ++ .../uclibc/test/math/libm-test-ulps-powerpc | 1336 ++ .../uclibc/test/math/libm-test-ulps-s390 | 1332 ++ .../uclibc/test/math/libm-test-ulps-sh4 | 1094 ++ .../uclibc/test/math/libm-test-ulps-sparc32 | 1322 ++ .../uclibc/test/math/libm-test-ulps-sparc64 | 1322 ++ .../uclibc/test/math/libm-test-ulps-x86_64 | 1308 ++ .../contrib/uclibc/test/math/libm-test.inc | 5109 ++++++ .../lib/contrib/uclibc/test/math/rint.c | 33 + .../lib/contrib/uclibc/test/math/signgam.c | 28 + .../contrib/uclibc/test/math/test-double.c | 34 + .../lib/contrib/uclibc/test/math/test-float.c | 34 + .../lib/contrib/uclibc/test/math/test-fpucw.c | 43 + .../contrib/uclibc/test/math/test-idouble.c | 35 + .../contrib/uclibc/test/math/test-ifloat.c | 35 + .../contrib/uclibc/test/math/test-ildoubl.c | 35 + .../contrib/uclibc/test/math/test-ldouble.c | 34 + .../uclibc/test/math/tst-definitions.c | 47 + .../lib/contrib/uclibc/test/misc/Makefile | 7 + .../lib/contrib/uclibc/test/misc/Makefile.in | 14 + .../lib/contrib/uclibc/test/misc/bug-glob1.c | 94 + .../lib/contrib/uclibc/test/misc/bug-glob2.c | 302 + .../contrib/uclibc/test/misc/bug-readdir1.c | 37 + .../lib/contrib/uclibc/test/misc/dirent.c | 39 + .../lib/contrib/uclibc/test/misc/dirent64.c | 1 + .../lib/contrib/uclibc/test/misc/fdopen.c | 52 + .../contrib/uclibc/test/misc/opendir-tst1.c | 95 + .../lib/contrib/uclibc/test/misc/outb.c | 9 + .../lib/contrib/uclibc/test/misc/popen.c | 47 + .../lib/contrib/uclibc/test/misc/seek.c | 82 + .../uclibc/lib/contrib/uclibc/test/misc/sem.c | 45 + .../lib/contrib/uclibc/test/misc/stdarg.c | 23 + .../contrib/uclibc/test/misc/tst-fnmatch.c | 444 + .../uclibc/test/misc/tst-fnmatch.input | 755 + .../contrib/uclibc/test/misc/tst-gnuglob.c | 447 + .../contrib/uclibc/test/misc/tst-scandir.c | 23 + .../contrib/uclibc/test/misc/tst-seekdir.c | 79 + .../lib/contrib/uclibc/test/misc/tst-utmp.c | 404 + .../lib/contrib/uclibc/test/mmap/Makefile | 7 + .../lib/contrib/uclibc/test/mmap/mmap.c | 73 + .../lib/contrib/uclibc/test/mmap/mmap2.c | 41 + .../lib/contrib/uclibc/test/mmap/mmap64.c | 29 + .../lib/contrib/uclibc/test/nptl/Makefile | 8 + .../lib/contrib/uclibc/test/nptl/Makefile.in | 229 + .../lib/contrib/uclibc/test/nptl/eintr.c | 89 + .../lib/contrib/uclibc/test/nptl/tst-align.c | 71 + .../lib/contrib/uclibc/test/nptl/tst-align2.c | 87 + .../lib/contrib/uclibc/test/nptl/tst-align3.c | 57 + .../contrib/uclibc/test/nptl/tst-atfork1.c | 121 + .../lib/contrib/uclibc/test/nptl/tst-attr1.c | 306 + .../lib/contrib/uclibc/test/nptl/tst-attr2.c | 317 + .../lib/contrib/uclibc/test/nptl/tst-attr3.c | 420 + .../contrib/uclibc/test/nptl/tst-barrier1.c | 71 + .../contrib/uclibc/test/nptl/tst-barrier2.c | 185 + .../contrib/uclibc/test/nptl/tst-barrier3.c | 154 + .../contrib/uclibc/test/nptl/tst-barrier4.c | 122 + .../lib/contrib/uclibc/test/nptl/tst-basic1.c | 82 + .../lib/contrib/uclibc/test/nptl/tst-basic2.c | 121 + .../lib/contrib/uclibc/test/nptl/tst-basic3.c | 87 + .../lib/contrib/uclibc/test/nptl/tst-basic4.c | 101 + .../lib/contrib/uclibc/test/nptl/tst-basic5.c | 74 + .../lib/contrib/uclibc/test/nptl/tst-basic6.c | 132 + .../lib/contrib/uclibc/test/nptl/tst-basic7.c | 75 + .../contrib/uclibc/test/nptl/tst-cancel1.c | 163 + .../contrib/uclibc/test/nptl/tst-cancel10.c | 126 + .../contrib/uclibc/test/nptl/tst-cancel11.c | 123 + .../contrib/uclibc/test/nptl/tst-cancel12.c | 127 + .../contrib/uclibc/test/nptl/tst-cancel13.c | 129 + .../contrib/uclibc/test/nptl/tst-cancel14.c | 137 + .../contrib/uclibc/test/nptl/tst-cancel15.c | 142 + .../contrib/uclibc/test/nptl/tst-cancel16.c | 231 + .../contrib/uclibc/test/nptl/tst-cancel18.c | 174 + .../contrib/uclibc/test/nptl/tst-cancel19.c | 287 + .../contrib/uclibc/test/nptl/tst-cancel2.c | 100 + .../contrib/uclibc/test/nptl/tst-cancel20.c | 264 + .../contrib/uclibc/test/nptl/tst-cancel21.c | 294 + .../contrib/uclibc/test/nptl/tst-cancel22.c | 122 + .../contrib/uclibc/test/nptl/tst-cancel23.c | 1 + .../contrib/uclibc/test/nptl/tst-cancel25.c | 171 + .../contrib/uclibc/test/nptl/tst-cancel3.c | 98 + .../contrib/uclibc/test/nptl/tst-cancel4.c | 2374 +++ .../contrib/uclibc/test/nptl/tst-cancel5.c | 1 + .../contrib/uclibc/test/nptl/tst-cancel6.c | 79 + .../contrib/uclibc/test/nptl/tst-cancel7.c | 213 + .../contrib/uclibc/test/nptl/tst-cancel8.c | 143 + .../contrib/uclibc/test/nptl/tst-cancel9.c | 126 + .../contrib/uclibc/test/nptl/tst-cancelx10.c | 1 + .../contrib/uclibc/test/nptl/tst-cancelx11.c | 1 + .../contrib/uclibc/test/nptl/tst-cancelx12.c | 1 + .../contrib/uclibc/test/nptl/tst-cancelx13.c | 1 + .../contrib/uclibc/test/nptl/tst-cancelx14.c | 1 + .../contrib/uclibc/test/nptl/tst-cancelx15.c | 1 + .../contrib/uclibc/test/nptl/tst-cancelx16.c | 1 + .../contrib/uclibc/test/nptl/tst-cancelx18.c | 1 + .../contrib/uclibc/test/nptl/tst-cancelx2.c | 1 + .../contrib/uclibc/test/nptl/tst-cancelx20.c | 1 + .../contrib/uclibc/test/nptl/tst-cancelx21.c | 1 + .../contrib/uclibc/test/nptl/tst-cancelx3.c | 1 + .../contrib/uclibc/test/nptl/tst-cancelx4.c | 1 + .../contrib/uclibc/test/nptl/tst-cancelx6.c | 1 + .../contrib/uclibc/test/nptl/tst-cancelx7.c | 1 + .../contrib/uclibc/test/nptl/tst-cancelx8.c | 1 + .../contrib/uclibc/test/nptl/tst-cancelx9.c | 1 + .../contrib/uclibc/test/nptl/tst-cleanup0.c | 76 + .../contrib/uclibc/test/nptl/tst-cleanup1.c | 100 + .../contrib/uclibc/test/nptl/tst-cleanup2.c | 63 + .../contrib/uclibc/test/nptl/tst-cleanup3.c | 98 + .../contrib/uclibc/test/nptl/tst-cleanup4.c | 198 + .../uclibc/test/nptl/tst-cleanup4aux.c | 121 + .../contrib/uclibc/test/nptl/tst-cleanupx0.c | 1 + .../contrib/uclibc/test/nptl/tst-cleanupx1.c | 1 + .../contrib/uclibc/test/nptl/tst-cleanupx2.c | 1 + .../contrib/uclibc/test/nptl/tst-cleanupx3.c | 1 + .../contrib/uclibc/test/nptl/tst-cleanupx4.c | 1 + .../lib/contrib/uclibc/test/nptl/tst-clock.c | 124 + .../lib/contrib/uclibc/test/nptl/tst-clock1.c | 51 + .../lib/contrib/uclibc/test/nptl/tst-clock2.c | 202 + .../uclibc/test/nptl/tst-clock_nanosleep.c | 58 + .../lib/contrib/uclibc/test/nptl/tst-cond1.c | 94 + .../lib/contrib/uclibc/test/nptl/tst-cond10.c | 173 + .../lib/contrib/uclibc/test/nptl/tst-cond11.c | 191 + .../lib/contrib/uclibc/test/nptl/tst-cond12.c | 196 + .../lib/contrib/uclibc/test/nptl/tst-cond13.c | 2 + .../lib/contrib/uclibc/test/nptl/tst-cond14.c | 118 + .../lib/contrib/uclibc/test/nptl/tst-cond15.c | 160 + .../lib/contrib/uclibc/test/nptl/tst-cond16.c | 105 + .../lib/contrib/uclibc/test/nptl/tst-cond17.c | 2 + .../lib/contrib/uclibc/test/nptl/tst-cond18.c | 117 + .../lib/contrib/uclibc/test/nptl/tst-cond19.c | 76 + .../lib/contrib/uclibc/test/nptl/tst-cond2.c | 163 + .../lib/contrib/uclibc/test/nptl/tst-cond20.c | 170 + .../lib/contrib/uclibc/test/nptl/tst-cond21.c | 3 + .../lib/contrib/uclibc/test/nptl/tst-cond22.c | 160 + .../lib/contrib/uclibc/test/nptl/tst-cond23.c | 184 + .../lib/contrib/uclibc/test/nptl/tst-cond3.c | 113 + .../lib/contrib/uclibc/test/nptl/tst-cond4.c | 264 + .../lib/contrib/uclibc/test/nptl/tst-cond5.c | 106 + .../lib/contrib/uclibc/test/nptl/tst-cond6.c | 234 + .../lib/contrib/uclibc/test/nptl/tst-cond7.c | 168 + .../lib/contrib/uclibc/test/nptl/tst-cond8.c | 277 + .../lib/contrib/uclibc/test/nptl/tst-cond9.c | 150 + .../contrib/uclibc/test/nptl/tst-cpuclock1.c | 307 + .../contrib/uclibc/test/nptl/tst-cpuclock2.c | 332 + .../contrib/uclibc/test/nptl/tst-cputimer1.c | 68 + .../contrib/uclibc/test/nptl/tst-cputimer2.c | 83 + .../contrib/uclibc/test/nptl/tst-cputimer3.c | 130 + .../contrib/uclibc/test/nptl/tst-detach1.c | 56 + .../lib/contrib/uclibc/test/nptl/tst-dlsym1.c | 66 + .../lib/contrib/uclibc/test/nptl/tst-eintr1.c | 105 + .../lib/contrib/uclibc/test/nptl/tst-eintr2.c | 118 + .../lib/contrib/uclibc/test/nptl/tst-eintr3.c | 72 + .../lib/contrib/uclibc/test/nptl/tst-eintr4.c | 56 + .../lib/contrib/uclibc/test/nptl/tst-eintr5.c | 81 + .../lib/contrib/uclibc/test/nptl/tst-exec2.c | 154 + .../lib/contrib/uclibc/test/nptl/tst-exec3.c | 152 + .../lib/contrib/uclibc/test/nptl/tst-exec4.c | 116 + .../lib/contrib/uclibc/test/nptl/tst-exit1.c | 79 + .../lib/contrib/uclibc/test/nptl/tst-exit2.c | 40 + .../lib/contrib/uclibc/test/nptl/tst-exit3.c | 81 + .../lib/contrib/uclibc/test/nptl/tst-fini1.c | 35 + .../contrib/uclibc/test/nptl/tst-fini1mod.c | 72 + .../lib/contrib/uclibc/test/nptl/tst-flock1.c | 93 + .../lib/contrib/uclibc/test/nptl/tst-flock2.c | 260 + .../lib/contrib/uclibc/test/nptl/tst-fork1.c | 120 + .../lib/contrib/uclibc/test/nptl/tst-fork2.c | 90 + .../lib/contrib/uclibc/test/nptl/tst-fork3.c | 107 + .../lib/contrib/uclibc/test/nptl/tst-fork4.c | 65 + .../contrib/uclibc/test/nptl/tst-getpid1.c | 122 + .../contrib/uclibc/test/nptl/tst-getpid2.c | 2 + .../contrib/uclibc/test/nptl/tst-getpid3.c | 114 + .../uclibc/test/nptl/tst-initializers1-c89.c | 1 + .../uclibc/test/nptl/tst-initializers1-c99.c | 1 + .../test/nptl/tst-initializers1-gnu89.c | 1 + .../test/nptl/tst-initializers1-gnu99.c | 1 + .../uclibc/test/nptl/tst-initializers1.c | 48 + .../lib/contrib/uclibc/test/nptl/tst-join1.c | 83 + .../lib/contrib/uclibc/test/nptl/tst-join2.c | 104 + .../lib/contrib/uclibc/test/nptl/tst-join3.c | 123 + .../lib/contrib/uclibc/test/nptl/tst-join4.c | 125 + .../lib/contrib/uclibc/test/nptl/tst-join5.c | 143 + .../lib/contrib/uclibc/test/nptl/tst-join6.c | 2 + .../lib/contrib/uclibc/test/nptl/tst-key1.c | 89 + .../lib/contrib/uclibc/test/nptl/tst-key2.c | 115 + .../lib/contrib/uclibc/test/nptl/tst-key3.c | 156 + .../lib/contrib/uclibc/test/nptl/tst-key4.c | 137 + .../lib/contrib/uclibc/test/nptl/tst-kill1.c | 100 + .../lib/contrib/uclibc/test/nptl/tst-kill2.c | 139 + .../lib/contrib/uclibc/test/nptl/tst-kill3.c | 159 + .../lib/contrib/uclibc/test/nptl/tst-kill4.c | 74 + .../lib/contrib/uclibc/test/nptl/tst-kill5.c | 49 + .../lib/contrib/uclibc/test/nptl/tst-kill6.c | 162 + .../lib/contrib/uclibc/test/nptl/tst-mqueue.h | 84 + .../contrib/uclibc/test/nptl/tst-mqueue1.c | 417 + .../contrib/uclibc/test/nptl/tst-mqueue2.c | 477 + .../contrib/uclibc/test/nptl/tst-mqueue3.c | 244 + .../contrib/uclibc/test/nptl/tst-mqueue4.c | 288 + .../contrib/uclibc/test/nptl/tst-mqueue5.c | 1014 ++ .../contrib/uclibc/test/nptl/tst-mqueue6.c | 305 + .../contrib/uclibc/test/nptl/tst-mqueue7.c | 109 + .../contrib/uclibc/test/nptl/tst-mqueue8.c | 266 + .../contrib/uclibc/test/nptl/tst-mqueue9.c | 92 + .../lib/contrib/uclibc/test/nptl/tst-mutex1.c | 57 + .../lib/contrib/uclibc/test/nptl/tst-mutex2.c | 223 + .../lib/contrib/uclibc/test/nptl/tst-mutex3.c | 225 + .../lib/contrib/uclibc/test/nptl/tst-mutex4.c | 191 + .../lib/contrib/uclibc/test/nptl/tst-mutex5.c | 186 + .../contrib/uclibc/test/nptl/tst-mutex5a.c | 2 + .../lib/contrib/uclibc/test/nptl/tst-mutex6.c | 55 + .../lib/contrib/uclibc/test/nptl/tst-mutex7.c | 121 + .../contrib/uclibc/test/nptl/tst-mutex7a.c | 2 + .../lib/contrib/uclibc/test/nptl/tst-mutex8.c | 367 + .../lib/contrib/uclibc/test/nptl/tst-mutex9.c | 191 + .../uclibc/test/nptl/tst-oddstacklimit.c | 1 + .../lib/contrib/uclibc/test/nptl/tst-once1.c | 51 + .../lib/contrib/uclibc/test/nptl/tst-once2.c | 104 + .../lib/contrib/uclibc/test/nptl/tst-once3.c | 162 + .../lib/contrib/uclibc/test/nptl/tst-once4.c | 202 + .../lib/contrib/uclibc/test/nptl/tst-oncex3.c | 1 + .../lib/contrib/uclibc/test/nptl/tst-oncex4.c | 1 + .../lib/contrib/uclibc/test/nptl/tst-popen1.c | 60 + .../lib/contrib/uclibc/test/nptl/tst-raise1.c | 62 + .../contrib/uclibc/test/nptl/tst-rwlock1.c | 117 + .../contrib/uclibc/test/nptl/tst-rwlock10.c | 21 + .../contrib/uclibc/test/nptl/tst-rwlock11.c | 21 + .../contrib/uclibc/test/nptl/tst-rwlock12.c | 208 + .../contrib/uclibc/test/nptl/tst-rwlock13.c | 71 + .../contrib/uclibc/test/nptl/tst-rwlock14.c | 169 + .../contrib/uclibc/test/nptl/tst-rwlock2.c | 143 + .../contrib/uclibc/test/nptl/tst-rwlock2a.c | 2 + .../contrib/uclibc/test/nptl/tst-rwlock3.c | 93 + .../contrib/uclibc/test/nptl/tst-rwlock4.c | 190 + .../contrib/uclibc/test/nptl/tst-rwlock5.c | 87 + .../contrib/uclibc/test/nptl/tst-rwlock6.c | 226 + .../contrib/uclibc/test/nptl/tst-rwlock7.c | 179 + .../contrib/uclibc/test/nptl/tst-rwlock8.c | 164 + .../contrib/uclibc/test/nptl/tst-rwlock9.c | 203 + .../lib/contrib/uclibc/test/nptl/tst-sched1.c | 98 + .../lib/contrib/uclibc/test/nptl/tst-sem1.c | 89 + .../lib/contrib/uclibc/test/nptl/tst-sem10.c | 88 + .../lib/contrib/uclibc/test/nptl/tst-sem11.c | 76 + .../lib/contrib/uclibc/test/nptl/tst-sem12.c | 14 + .../lib/contrib/uclibc/test/nptl/tst-sem2.c | 54 + .../lib/contrib/uclibc/test/nptl/tst-sem3.c | 142 + .../lib/contrib/uclibc/test/nptl/tst-sem4.c | 147 + .../lib/contrib/uclibc/test/nptl/tst-sem5.c | 80 + .../lib/contrib/uclibc/test/nptl/tst-sem6.c | 81 + .../lib/contrib/uclibc/test/nptl/tst-sem7.c | 109 + .../lib/contrib/uclibc/test/nptl/tst-sem8.c | 74 + .../lib/contrib/uclibc/test/nptl/tst-sem9.c | 81 + .../contrib/uclibc/test/nptl/tst-signal1.c | 189 + .../contrib/uclibc/test/nptl/tst-signal2.c | 198 + .../contrib/uclibc/test/nptl/tst-signal3.c | 261 + .../contrib/uclibc/test/nptl/tst-signal4.c | 60 + .../contrib/uclibc/test/nptl/tst-signal5.c | 111 + .../contrib/uclibc/test/nptl/tst-signal6.c | 192 + .../contrib/uclibc/test/nptl/tst-signal7.c | 59 + .../lib/contrib/uclibc/test/nptl/tst-spin1.c | 57 + .../lib/contrib/uclibc/test/nptl/tst-spin2.c | 159 + .../lib/contrib/uclibc/test/nptl/tst-spin3.c | 55 + .../uclibc/test/nptl/tst-stack-align.h | 35 + .../lib/contrib/uclibc/test/nptl/tst-stack1.c | 146 + .../lib/contrib/uclibc/test/nptl/tst-stack2.c | 80 + .../lib/contrib/uclibc/test/nptl/tst-stdio1.c | 57 + .../lib/contrib/uclibc/test/nptl/tst-stdio2.c | 82 + .../contrib/uclibc/test/nptl/tst-sysconf.c | 48 + .../lib/contrib/uclibc/test/nptl/tst-timer2.c | 65 + .../lib/contrib/uclibc/test/nptl/tst-timer3.c | 86 + .../lib/contrib/uclibc/test/nptl/tst-timer4.c | 648 + .../lib/contrib/uclibc/test/nptl/tst-timer5.c | 38 + .../lib/contrib/uclibc/test/nptl/tst-tls1.c | 122 + .../lib/contrib/uclibc/test/nptl/tst-tls2.c | 216 + .../lib/contrib/uclibc/test/nptl/tst-tls3.c | 225 + .../contrib/uclibc/test/nptl/tst-tls3mod.c | 106 + .../lib/contrib/uclibc/test/nptl/tst-tls4.c | 191 + .../contrib/uclibc/test/nptl/tst-tls4moda.c | 56 + .../contrib/uclibc/test/nptl/tst-tls4modb.c | 65 + .../lib/contrib/uclibc/test/nptl/tst-tls5.c | 119 + .../lib/contrib/uclibc/test/nptl/tst-tls5.h | 28 + .../contrib/uclibc/test/nptl/tst-tls5mod.c | 6 + .../contrib/uclibc/test/nptl/tst-tls5moda.c | 6 + .../contrib/uclibc/test/nptl/tst-tls5modb.c | 6 + .../contrib/uclibc/test/nptl/tst-tls5modc.c | 6 + .../contrib/uclibc/test/nptl/tst-tls5modd.c | 6 + .../contrib/uclibc/test/nptl/tst-tls5mode.c | 8 + .../contrib/uclibc/test/nptl/tst-tls5modf.c | 9 + .../lib/contrib/uclibc/test/nptl/tst-tsd1.c | 118 + .../lib/contrib/uclibc/test/nptl/tst-tsd2.c | 97 + .../lib/contrib/uclibc/test/nptl/tst-tsd3.c | 129 + .../lib/contrib/uclibc/test/nptl/tst-tsd4.c | 103 + .../lib/contrib/uclibc/test/nptl/tst-tsd5.c | 81 + .../lib/contrib/uclibc/test/nptl/tst-tsd6.c | 89 + .../contrib/uclibc/test/nptl/tst-typesizes.c | 96 + .../lib/contrib/uclibc/test/nptl/tst-umask1.c | 137 + .../lib/contrib/uclibc/test/nptl/tst-unload.c | 47 + .../lib/contrib/uclibc/test/nptl/tst-vfork1.c | 150 + .../contrib/uclibc/test/nptl/tst-vfork1x.c | 150 + .../lib/contrib/uclibc/test/nptl/tst-vfork2.c | 199 + .../contrib/uclibc/test/nptl/tst-vfork2x.c | 199 + .../lib/contrib/uclibc/test/plt/check-plt.sh | 38 + .../lib/contrib/uclibc/test/pthread/Makefile | 7 + .../contrib/uclibc/test/pthread/Makefile.in | 8 + .../uclibc/test/pthread/cancellation-points.c | 284 + .../lib/contrib/uclibc/test/pthread/ex1.c | 35 + .../lib/contrib/uclibc/test/pthread/ex2.c | 113 + .../lib/contrib/uclibc/test/pthread/ex3.c | 152 + .../lib/contrib/uclibc/test/pthread/ex4.c | 107 + .../lib/contrib/uclibc/test/pthread/ex5.c | 102 + .../lib/contrib/uclibc/test/pthread/ex6.c | 44 + .../lib/contrib/uclibc/test/pthread/ex7.c | 106 + .../test/pthread/tst-too-many-cleanups.c | 104 + .../contrib/uclibc/test/pwd_grp/.indent.pro | 33 + .../lib/contrib/uclibc/test/pwd_grp/Makefile | 7 + .../contrib/uclibc/test/pwd_grp/Makefile.in | 8 + .../contrib/uclibc/test/pwd_grp/getgroups.c | 99 + .../lib/contrib/uclibc/test/pwd_grp/grcat.c | 32 + .../lib/contrib/uclibc/test/pwd_grp/pwcat.c | 26 + .../contrib/uclibc/test/pwd_grp/test_grp.c | 87 + .../contrib/uclibc/test/pwd_grp/test_pwd.c | 74 + .../lib/contrib/uclibc/test/regex/LICENSE | 72 + .../lib/contrib/uclibc/test/regex/Makefile | 7 + .../lib/contrib/uclibc/test/regex/basic.dat | 216 + .../contrib/uclibc/test/regex/categorize.dat | 62 + .../contrib/uclibc/test/regex/forcedassoc.dat | 30 + .../uclibc/test/regex/interpretation.dat | 93 + .../contrib/uclibc/test/regex/leftassoc.dat | 16 + .../contrib/uclibc/test/regex/nullsubexpr.dat | 73 + .../contrib/uclibc/test/regex/repetition.dat | 79 + .../contrib/uclibc/test/regex/rightassoc.dat | 16 + .../lib/contrib/uclibc/test/regex/testregex.c | 2145 +++ .../contrib/uclibc/test/regex/tst-regex2.c | 250 + .../contrib/uclibc/test/regex/tst-regex2.dat | 2176 +++ .../contrib/uclibc/test/regex/tst-regexloc.c | 54 + .../lib/contrib/uclibc/test/rpc/Makefile | 7 + .../lib/contrib/uclibc/test/rpc/Makefile.in | 11 + .../lib/contrib/uclibc/test/rpc/getrpcent.c | 18 + .../lib/contrib/uclibc/test/rpc/getrpcent_r.c | 25 + .../lib/contrib/uclibc/test/setjmp/Makefile | 7 + .../uclibc/test/setjmp/bug269-setjmp.c | 107 + .../lib/contrib/uclibc/test/setjmp/jmpbug.c | 51 + .../contrib/uclibc/test/setjmp/sigjmpbug.c | 51 + .../contrib/uclibc/test/setjmp/tst-setjmp.c | 119 + .../uclibc/test/setjmp/tst-vfork-longjmp.c | 108 + .../contrib/uclibc/test/signal/.indent.pro | 33 + .../lib/contrib/uclibc/test/signal/Makefile | 7 + .../contrib/uclibc/test/signal/Makefile.in | 6 + .../lib/contrib/uclibc/test/signal/sigchld.c | 68 + .../lib/contrib/uclibc/test/signal/signal.c | 95 + .../contrib/uclibc/test/signal/tst-raise.c | 63 + .../contrib/uclibc/test/signal/tst-signal.c | 44 + .../contrib/uclibc/test/signal/tst-sigset.c | 45 + .../uclibc/test/signal/tst-sigsimple.c | 57 + .../lib/contrib/uclibc/test/silly/Makefile | 7 + .../lib/contrib/uclibc/test/silly/Makefile.in | 5 + .../lib/contrib/uclibc/test/silly/hello.c | 8 + .../lib/contrib/uclibc/test/silly/tiny.c | 6 + .../lib/contrib/uclibc/test/stat/Makefile | 7 + .../lib/contrib/uclibc/test/stat/Makefile.in | 13 + .../contrib/uclibc/test/stat/memcmp-stat.c | 107 + .../lib/contrib/uclibc/test/stat/stat.c | 71 + .../lib/contrib/uclibc/test/stat/stat64.c | 1 + .../lib/contrib/uclibc/test/stdio/64bit.c | 12 + .../lib/contrib/uclibc/test/stdio/Makefile | 7 + .../lib/contrib/uclibc/test/stdio/Makefile.in | 4 + .../contrib/uclibc/test/stdio/fclose-loop.c | 21 + .../lib/contrib/uclibc/test/stdlib/Makefile | 7 + .../contrib/uclibc/test/stdlib/Makefile.in | 7 + .../lib/contrib/uclibc/test/stdlib/ptytest.c | 20 + .../lib/contrib/uclibc/test/stdlib/qsort.c | 53 + .../contrib/uclibc/test/stdlib/test-canon.c | 251 + .../contrib/uclibc/test/stdlib/test-canon2.c | 75 + .../contrib/uclibc/test/stdlib/testatexit.c | 81 + .../contrib/uclibc/test/stdlib/teston_exit.c | 82 + .../contrib/uclibc/test/stdlib/teststrtol.c | 109 + .../contrib/uclibc/test/stdlib/teststrtoq.c | 89 + .../lib/contrib/uclibc/test/string/Makefile | 7 + .../contrib/uclibc/test/string/Makefile.in | 4 + .../contrib/uclibc/test/string/bug-strcoll1.c | 24 + .../contrib/uclibc/test/string/bug-strncat1.c | 31 + .../contrib/uclibc/test/string/bug-strpbrk1.c | 19 + .../contrib/uclibc/test/string/bug-strspn1.c | 19 + .../contrib/uclibc/test/string/stratcliff.c | 349 + .../lib/contrib/uclibc/test/string/test-ffs.c | 66 + .../lib/contrib/uclibc/test/string/testcopy.c | 108 + .../lib/contrib/uclibc/test/string/tester.c | 1647 ++ .../contrib/uclibc/test/string/tst-bswap.c | 74 + .../contrib/uclibc/test/string/tst-inlcall.c | 83 + .../contrib/uclibc/test/string/tst-strlen.c | 45 + .../contrib/uclibc/test/string/tst-strtok.c | 23 + .../contrib/uclibc/test/string/tst-strxfrm.c | 80 + .../lib/contrib/uclibc/test/termios/Makefile | 7 + .../lib/contrib/uclibc/test/termios/termios.c | 25 + .../lib/contrib/uclibc/test/test-skeleton.c | 411 + .../lib/contrib/uclibc/test/testsuite.h | 100 + .../lib/contrib/uclibc/test/time/Makefile | 7 + .../lib/contrib/uclibc/test/time/Makefile.in | 12 + .../contrib/uclibc/test/time/bug-asctime.c | 40 + .../contrib/uclibc/test/time/bug-asctime_r.c | 37 + .../lib/contrib/uclibc/test/time/clocktest.c | 36 + .../lib/contrib/uclibc/test/time/test_time.c | 116 + .../lib/contrib/uclibc/test/time/time.c | 76 + .../lib/contrib/uclibc/test/time/tst-ctime.c | 44 + .../contrib/uclibc/test/time/tst-ftime_l.c | 136 + .../contrib/uclibc/test/time/tst-futimens1.c | 105 + .../lib/contrib/uclibc/test/time/tst-mktime.c | 70 + .../contrib/uclibc/test/time/tst-mktime2.c | 141 + .../contrib/uclibc/test/time/tst-mktime3.c | 50 + .../contrib/uclibc/test/time/tst-posixtz.c | 88 + .../contrib/uclibc/test/time/tst-strftime.c | 111 + .../contrib/uclibc/test/time/tst-strptime.c | 193 + .../contrib/uclibc/test/time/tst-strptime2.c | 59 + .../contrib/uclibc/test/time/tst-timezone.c | 170 + .../contrib/uclibc/test/time/tst_wcsftime.c | 39 + .../lib/contrib/uclibc/test/tls/Makefile | 8 + .../lib/contrib/uclibc/test/tls/Makefile.in | 148 + .../uclibc/lib/contrib/uclibc/test/tls/README | 8 + .../contrib/uclibc/test/tls/tls-macros-arm.h | 51 + .../contrib/uclibc/test/tls/tls-macros-mips.h | 88 + .../uclibc/test/tls/tls-macros-thumb.h | 57 + .../lib/contrib/uclibc/test/tls/tls-macros.h | 861 + .../contrib/uclibc/test/tls/tst-tls-at-ctor.c | 21 + .../contrib/uclibc/test/tls/tst-tls1-static.c | 1 + .../lib/contrib/uclibc/test/tls/tst-tls1.c | 92 + .../lib/contrib/uclibc/test/tls/tst-tls10.c | 40 + .../lib/contrib/uclibc/test/tls/tst-tls10.h | 38 + .../lib/contrib/uclibc/test/tls/tst-tls11.c | 27 + .../lib/contrib/uclibc/test/tls/tst-tls12.c | 18 + .../lib/contrib/uclibc/test/tls/tst-tls13.c | 30 + .../lib/contrib/uclibc/test/tls/tst-tls14.c | 66 + .../lib/contrib/uclibc/test/tls/tst-tls15.c | 33 + .../lib/contrib/uclibc/test/tls/tst-tls16.c | 53 + .../lib/contrib/uclibc/test/tls/tst-tls17.c | 29 + .../lib/contrib/uclibc/test/tls/tst-tls18.c | 38 + .../contrib/uclibc/test/tls/tst-tls2-static.c | 1 + .../lib/contrib/uclibc/test/tls/tst-tls2.c | 91 + .../lib/contrib/uclibc/test/tls/tst-tls3.c | 76 + .../lib/contrib/uclibc/test/tls/tst-tls4.c | 56 + .../lib/contrib/uclibc/test/tls/tst-tls5.c | 72 + .../lib/contrib/uclibc/test/tls/tst-tls6.c | 108 + .../lib/contrib/uclibc/test/tls/tst-tls7.c | 79 + .../lib/contrib/uclibc/test/tls/tst-tls8.c | 230 + .../contrib/uclibc/test/tls/tst-tls9-static.c | 1 + .../lib/contrib/uclibc/test/tls/tst-tls9.c | 42 + .../uclibc/test/tls/tst-tlsmod-at-ctor.c | 25 + .../lib/contrib/uclibc/test/tls/tst-tlsmod1.c | 68 + .../contrib/uclibc/test/tls/tst-tlsmod10.c | 1 + .../contrib/uclibc/test/tls/tst-tlsmod11.c | 6 + .../contrib/uclibc/test/tls/tst-tlsmod12.c | 14 + .../contrib/uclibc/test/tls/tst-tlsmod13.c | 14 + .../contrib/uclibc/test/tls/tst-tlsmod13a.c | 16 + .../contrib/uclibc/test/tls/tst-tlsmod14a.c | 41 + .../contrib/uclibc/test/tls/tst-tlsmod14b.c | 2 + .../contrib/uclibc/test/tls/tst-tlsmod15a.c | 6 + .../contrib/uclibc/test/tls/tst-tlsmod15b.c | 17 + .../contrib/uclibc/test/tls/tst-tlsmod16a.c | 7 + .../contrib/uclibc/test/tls/tst-tlsmod16b.c | 13 + .../contrib/uclibc/test/tls/tst-tlsmod17a.c | 23 + .../contrib/uclibc/test/tls/tst-tlsmod17b.c | 15 + .../contrib/uclibc/test/tls/tst-tlsmod18a.c | 21 + .../lib/contrib/uclibc/test/tls/tst-tlsmod2.c | 38 + .../lib/contrib/uclibc/test/tls/tst-tlsmod3.c | 41 + .../lib/contrib/uclibc/test/tls/tst-tlsmod4.c | 38 + .../lib/contrib/uclibc/test/tls/tst-tlsmod5.c | 7 + .../lib/contrib/uclibc/test/tls/tst-tlsmod6.c | 7 + .../lib/contrib/uclibc/test/tls/tst-tlsmod7.c | 103 + .../lib/contrib/uclibc/test/tls/tst-tlsmod8.c | 72 + .../lib/contrib/uclibc/test/tls/tst-tlsmod9.c | 101 + .../lib/contrib/uclibc/test/unistd/Makefile | 7 + .../contrib/uclibc/test/unistd/Makefile.in | 23 + .../lib/contrib/uclibc/test/unistd/clone.c | 101 + .../contrib/uclibc/test/unistd/clone_cruft.h | 24 + .../lib/contrib/uclibc/test/unistd/errno.c | 29 + .../contrib/uclibc/test/unistd/exec-null.c | 13 + .../lib/contrib/uclibc/test/unistd/fork.c | 91 + .../lib/contrib/uclibc/test/unistd/getcwd.c | 39 + .../lib/contrib/uclibc/test/unistd/getopt.c | 69 + .../contrib/uclibc/test/unistd/getopt_long.c | 93 + .../contrib/uclibc/test/unistd/tst-getconf.sh | 240 + .../uclibc/test/unistd/tst-preadwrite.c | 105 + .../uclibc/test/unistd/tst-preadwrite64.c | 24 + .../contrib/uclibc/test/unistd/tstgetopt.c | 76 + .../lib/contrib/uclibc/test/unistd/vfork.c | 53 + .../lib/contrib/uclibc/utils/.gitignore | 12 + .../uclibc/lib/contrib/uclibc/utils/Makefile | 13 + .../lib/contrib/uclibc/utils/Makefile.in | 138 + .../uclibc/lib/contrib/uclibc/utils/bswap.h | 45 + .../contrib/uclibc/utils/chroot_realpath.c | 152 + .../uclibc/lib/contrib/uclibc/utils/getconf.c | 1337 ++ .../uclibc/lib/contrib/uclibc/utils/iconv.c | 264 + .../lib/contrib/uclibc/utils/ldconfig.c | 984 ++ l4/pkg/uclibc/lib/contrib/uclibc/utils/ldd.c | 808 + .../lib/contrib/uclibc/utils/mmap-windows.c | 100 + .../uclibc/lib/contrib/uclibc/utils/porting.h | 83 + .../lib/contrib/uclibc/utils/readsoname2.c | 141 + l4/pkg/uclibc/lib/libpthread/Makefile | 8 + l4/pkg/uclibc/lib/libpthread/include/Makefile | 7 + .../lib/libpthread/include/bits/initspin.h | 28 + .../lib/libpthread/include/bits/libc-lock.h | 419 + .../libpthread/include/bits/pthreadtypes.h | 148 + .../lib/libpthread/include/pthread-l4.h | 12 + .../uclibc/lib/libpthread/include/pthread.h | 689 + .../uclibc/lib/libpthread/include/semaphore.h | 94 + l4/pkg/uclibc/lib/libpthread/include/smp.h | 54 + l4/pkg/uclibc/lib/libpthread/src/Makefile | 61 + l4/pkg/uclibc/lib/libpthread/src/attr.c | 505 + l4/pkg/uclibc/lib/libpthread/src/barrier.c | 128 + l4/pkg/uclibc/lib/libpthread/src/cancel.c | 304 + l4/pkg/uclibc/lib/libpthread/src/condvar.c | 317 + l4/pkg/uclibc/lib/libpthread/src/descr.h | 236 + l4/pkg/uclibc/lib/libpthread/src/errno-loc.c | 53 + l4/pkg/uclibc/lib/libpthread/src/errno.c | 48 + l4/pkg/uclibc/lib/libpthread/src/forward.c | 145 + l4/pkg/uclibc/lib/libpthread/src/internals.h | 601 + l4/pkg/uclibc/lib/libpthread/src/join.c | 208 + l4/pkg/uclibc/lib/libpthread/src/l4.cc | 154 + l4/pkg/uclibc/lib/libpthread/src/l4.h | 15 + .../lib/libpthread/src/libc_pthread_init.c | 52 + l4/pkg/uclibc/lib/libpthread/src/manager.cc | 1071 ++ l4/pkg/uclibc/lib/libpthread/src/mutex.c | 393 + .../uclibc/lib/libpthread/src/pt-initfini.c | 124 + l4/pkg/uclibc/lib/libpthread/src/ptcleanup.c | 78 + .../lib/libpthread/src/pthread-functions.h | 104 + l4/pkg/uclibc/lib/libpthread/src/pthread.c | 1502 ++ l4/pkg/uclibc/lib/libpthread/src/queue.h | 61 + l4/pkg/uclibc/lib/libpthread/src/restart.h | 48 + l4/pkg/uclibc/lib/libpthread/src/rwlock.c | 658 + l4/pkg/uclibc/lib/libpthread/src/semaphore.c | 304 + .../uclibc/lib/libpthread/src/so_init-amd64.S | 4 + .../uclibc/lib/libpthread/src/so_init-arm.S | 4 + .../uclibc/lib/libpthread/src/so_init-ppc32.S | 4 + .../uclibc/lib/libpthread/src/so_init-sparc.S | 4 + .../uclibc/lib/libpthread/src/so_init-x86.S | 4 + l4/pkg/uclibc/lib/libpthread/src/specific.c | 258 + l4/pkg/uclibc/lib/libpthread/src/spinlock.c | 732 + l4/pkg/uclibc/lib/libpthread/src/spinlock.h | 223 + .../lib/libpthread/src/sysdeps/alpha/dl-tls.h | 29 + .../lib/libpthread/src/sysdeps/alpha/tls.h | 127 + .../lib/libpthread/src/sysdeps/arm/dl-tls.h | 29 + .../libpthread/src/sysdeps/arm/pt-machine.h | 62 + .../lib/libpthread/src/sysdeps/arm/tls.h | 178 + .../libpthread/src/sysdeps/generic/dl-tls.c | 899 ++ .../libpthread/src/sysdeps/generic/dl-tls.h | 2 + .../src/sysdeps/generic/libc-tls.cc | 289 + .../lib/libpthread/src/sysdeps/i386/dl-tls.h | 62 + .../src/sysdeps/i386/i686/pt-machine.h | 79 + .../libpthread/src/sysdeps/i386/i686/tls.h | 36 + .../libpthread/src/sysdeps/i386/pt-machine.h | 119 + .../src/sysdeps/i386/sysdep-cancel.h | 187 + .../lib/libpthread/src/sysdeps/i386/tls.h | 507 + .../lib/libpthread/src/sysdeps/mips/dl-tls.h | 46 + .../lib/libpthread/src/sysdeps/mips/tls.h | 181 + .../libpthread/src/sysdeps/powerpc/dl-tls.h | 49 + .../sysdeps/powerpc/powerpc32/pt-machine.h | 123 + .../sysdeps/powerpc/powerpc64/pt-machine.h | 187 + .../src/sysdeps/powerpc/pt-machine.h | 8 + .../lib/libpthread/src/sysdeps/powerpc/tls.h | 216 + .../lib/libpthread/src/sysdeps/sh/dl-tls.h | 29 + .../lib/libpthread/src/sysdeps/sh/tls.h | 182 + .../lib/libpthread/src/sysdeps/sparc/dl-tls.h | 29 + .../libpthread/src/sysdeps/sparc/pt-machine.h | 8 + .../src/sysdeps/sparc/sparc32/pt-machine.h | 85 + .../src/sysdeps/sparc/sparc64/pt-machine.h | 105 + .../lib/libpthread/src/sysdeps/sparc/tls.h | 182 + .../libpthread/src/sysdeps/x86_64/dl-tls.h | 29 + .../src/sysdeps/x86_64/pt-machine.h | 228 + .../src/sysdeps/x86_64/sysdep-cancel.h | 131 + .../lib/libpthread/src/sysdeps/x86_64/tls.h | 463 + .../uclibc/lib/libpthread/src/tramp-amd64.S | 9 + l4/pkg/uclibc/lib/libpthread/src/tramp-arm.S | 9 + .../uclibc/lib/libpthread/src/tramp-ppc32.S | 6 + .../uclibc/lib/libpthread/src/tramp-sparc.S | 6 + l4/pkg/uclibc/lib/libpthread/src/tramp-x86.S | 4 + .../uclibc/lib/libpthread/src/uClibc-glue.h | 46 + l4/pkg/uclibc/lib/minimal_l4re/Makefile | 12 + .../ARCH-all/include/bits/kernel-features.h | 1 + .../uclibc/ARCH-all/include/bits/sigthread.h | 0 .../lib/uclibc/ARCH-all/include/linux/errno.h | 1 + .../uclibc/ARCH-all/include/linux/if_ether.h | 10 + .../lib/uclibc/ARCH-all/include/not-cancel.h | 13 + .../lib/uclibc/ARCH-all/include/sys/syscall.h | 0 .../ARCH-all/libc/misc/dirent/dirstream.h | 78 + .../lib/uclibc/ARCH-all/libc/signal/raise.c | 18 + .../lib/uclibc/ARCH-all/libc/signal/sigjmp.c | 39 + .../lib/uclibc/ARCH-all/libc/stdlib/_atexit.c | 343 + .../lib/uclibc/ARCH-all/libc/stdlib/abort.c | 10 + .../libc/stdlib/malloc-standard/malloc.h | 972 ++ .../libc/sysdeps/linux/common/getdents.c | 174 + .../libc/sysdeps/linux/common/getsid.c | 19 + .../libc/sysdeps/linux/common/longjmp.c | 52 + .../lib/uclibc/ARCH-all/libc/unistd/sleep.c | 12 + .../lib/uclibc/ARCH-amd64/include/asm/errno.h | 147 + .../uclibc/ARCH-amd64/include/asm/ioctls.h | 141 + .../ARCH-amd64/include/asm/sigcontext.h | 45 + .../uclibc/ARCH-amd64/include/asm/socket.h | 48 + .../ARCH-amd64/include/bits/uClibc_config.h | 291 + .../uclibc/ARCH-amd64/include/linux/limits.h | 7 + .../uclibc/ARCH-amd64/include/linux/param.h | 6 + .../lib/uclibc/ARCH-arm/aeabi_read_tp-v6p.S | 67 + .../uclibc/ARCH-arm/aeabi_read_tp_generic.c | 15 + .../lib/uclibc/ARCH-arm/include/asm/errno.h | 147 + .../lib/uclibc/ARCH-arm/include/asm/ioctls.h | 149 + .../uclibc/ARCH-arm/include/asm/sigcontext.h | 32 + .../lib/uclibc/ARCH-arm/include/asm/socket.h | 48 + .../ARCH-arm/include/bits/uClibc_config.h | 290 + .../uclibc/ARCH-arm/include/linux/limits.h | 7 + .../lib/uclibc/ARCH-arm/include/linux/param.h | 6 + .../lib/uclibc/ARCH-ppc32/include/asm/errno.h | 147 + .../lib/uclibc/ARCH-ppc32/include/asm/ioctl.h | 73 + .../uclibc/ARCH-ppc32/include/asm/ioctls.h | 110 + .../ARCH-ppc32/include/asm/sigcontext.h | 40 + .../uclibc/ARCH-ppc32/include/asm/socket.h | 62 + .../uclibc/ARCH-ppc32/include/asm/sockios.h | 20 + .../ARCH-ppc32/include/bits/uClibc_config.h | 290 + .../uclibc/ARCH-ppc32/include/linux/limits.h | 22 + .../uclibc/ARCH-ppc32/include/linux/param.h | 22 + .../lib/uclibc/ARCH-sparc/include/asm/errno.h | 147 + .../uclibc/ARCH-sparc/include/asm/ioctls.h | 149 + .../ARCH-sparc/include/asm/sigcontext.h | 78 + .../uclibc/ARCH-sparc/include/asm/socket.h | 4 + .../ARCH-sparc/include/bits/uClibc_config.h | 290 + .../ARCH-sparc/include/linux/bits/ioctls.h | 35 + .../ARCH-sparc/include/linux/bits/socket.h | 356 + .../uclibc/ARCH-sparc/include/linux/limits.h | 22 + .../uclibc/ARCH-sparc/include/linux/param.h | 22 + .../uclibc/ARCH-sparc/include/linux/sockios.h | 0 .../lib/uclibc/ARCH-x86/include/asm/errno.h | 147 + .../lib/uclibc/ARCH-x86/include/asm/ioctls.h | 141 + .../uclibc/ARCH-x86/include/asm/sigcontext.h | 66 + .../lib/uclibc/ARCH-x86/include/asm/socket.h | 48 + .../ARCH-x86/include/bits/uClibc_config.h | 291 + .../uclibc/ARCH-x86/include/linux/limits.h | 7 + .../lib/uclibc/ARCH-x86/include/linux/param.h | 6 + l4/pkg/uclibc/lib/uclibc/Make.rules | 84 + l4/pkg/uclibc/lib/uclibc/Makefile | 6 + l4/pkg/uclibc/lib/uclibc/_exit.cc | 14 + l4/pkg/uclibc/lib/uclibc/contrib_files.mk | 740 + l4/pkg/uclibc/lib/uclibc/make_diff.sh | 6 + l4/pkg/uclibc/lib/uclibc/make_rules.mk | 115 + l4/pkg/uclibc/lib/uclibc/make_vars.mk | 36 + l4/pkg/uclibc/lib/uclibc/src_rules.mk | 21 + l4/pkg/uclibc/lib/uclibc/target_headers.lst | 216 + l4/tool/Makefile | 13 + l4/tool/bin/entry-selector | 67 + l4/tool/bin/genexportpack | 103 + l4/tool/bin/gengrub1iso | 57 + l4/tool/bin/gengrub2iso | 54 + l4/tool/bin/isocreator | 76 + l4/tool/bin/mkspafs | 169 + l4/tool/bin/qemu-x86-launch | 68 + l4/tool/bin/ux-launch | 77 + l4/tool/elf-patcher/Makefile | 27 + l4/tool/elf-patcher/elf-patcher.cc | 166 + l4/tool/elf-patcher/elf-patcher.h | 60 + l4/tool/gendep/COPYING | 50 + l4/tool/gendep/Doxyfile | 1630 ++ l4/tool/gendep/MAINTAINER | 1 + l4/tool/gendep/Makefile | 104 + l4/tool/gendep/WhatIsThis | 1 + l4/tool/gendep/deptrack.c | 483 + l4/tool/gendep/gendep.h | 3 + l4/tool/gendep/manpage.dox | 110 + l4/tool/gendep/simple-cat.c | 11 + l4/tool/gendep/syscall.c | 194 + l4/tool/kconfig/COPYING | 356 + l4/tool/kconfig/Makefile | 1400 ++ l4/tool/kconfig/README | 3 + l4/tool/kconfig/scripts/Kbuild.include | 278 + l4/tool/kconfig/scripts/Makefile | 40 + l4/tool/kconfig/scripts/Makefile.build | 467 + l4/tool/kconfig/scripts/Makefile.clean | 104 + l4/tool/kconfig/scripts/Makefile.headersinst | 117 + l4/tool/kconfig/scripts/Makefile.host | 170 + l4/tool/kconfig/scripts/Makefile.lib | 361 + l4/tool/kconfig/scripts/Makefile.modinst | 35 + l4/tool/kconfig/scripts/Makefile.modpost | 153 + l4/tool/kconfig/scripts/basic/.gitignore | 1 + l4/tool/kconfig/scripts/basic/Makefile | 15 + l4/tool/kconfig/scripts/basic/docproc.c | 583 + l4/tool/kconfig/scripts/basic/fixdep.c | 433 + l4/tool/kconfig/scripts/basic/hash.c | 64 + l4/tool/kconfig/scripts/kconfig/.gitignore | 23 + l4/tool/kconfig/scripts/kconfig/Makefile | 308 + l4/tool/kconfig/scripts/kconfig/POTFILES.in | 12 + l4/tool/kconfig/scripts/kconfig/check.sh | 14 + l4/tool/kconfig/scripts/kconfig/conf.c | 694 + l4/tool/kconfig/scripts/kconfig/confdata.c | 1107 ++ l4/tool/kconfig/scripts/kconfig/expr.c | 1168 ++ l4/tool/kconfig/scripts/kconfig/expr.h | 225 + l4/tool/kconfig/scripts/kconfig/gconf.c | 1542 ++ l4/tool/kconfig/scripts/kconfig/gconf.glade | 661 + l4/tool/kconfig/scripts/kconfig/images.c | 326 + l4/tool/kconfig/scripts/kconfig/kxgettext.c | 235 + l4/tool/kconfig/scripts/kconfig/lkc.h | 190 + l4/tool/kconfig/scripts/kconfig/lkc_proto.h | 54 + .../scripts/kconfig/lxdialog/.gitignore | 4 + .../scripts/kconfig/lxdialog/BIG.FAT.WARNING | 4 + .../kconfig/lxdialog/check-lxdialog.sh | 84 + .../scripts/kconfig/lxdialog/checklist.c | 332 + .../kconfig/scripts/kconfig/lxdialog/dialog.h | 230 + .../scripts/kconfig/lxdialog/inputbox.c | 238 + .../scripts/kconfig/lxdialog/menubox.c | 434 + .../scripts/kconfig/lxdialog/textbox.c | 390 + .../kconfig/scripts/kconfig/lxdialog/util.c | 657 + .../kconfig/scripts/kconfig/lxdialog/yesno.c | 114 + l4/tool/kconfig/scripts/kconfig/mconf.c | 882 ++ l4/tool/kconfig/scripts/kconfig/menu.c | 607 + l4/tool/kconfig/scripts/kconfig/nconf.c | 1546 ++ l4/tool/kconfig/scripts/kconfig/nconf.gui.c | 652 + l4/tool/kconfig/scripts/kconfig/nconf.h | 96 + l4/tool/kconfig/scripts/kconfig/qconf.cc | 1789 +++ l4/tool/kconfig/scripts/kconfig/qconf.h | 337 + l4/tool/kconfig/scripts/kconfig/symbol.c | 1310 ++ l4/tool/kconfig/scripts/kconfig/util.c | 140 + l4/tool/kconfig/scripts/kconfig/zconf.gperf | 47 + .../scripts/kconfig/zconf.hash.c_shipped | 286 + l4/tool/kconfig/scripts/kconfig/zconf.l | 364 + .../scripts/kconfig/zconf.lex.c_shipped | 2420 +++ .../scripts/kconfig/zconf.tab.c_shipped | 2504 +++ l4/tool/kconfig/scripts/kconfig/zconf.y | 740 + l4/tool/lib/L4/Grub.pm | 117 + l4/tool/lib/L4/ModList.pm | 421 + l4/tool/vim/syntax/ioconfig.vim | 21 + l4/tool/vim/syntax/l4mods.vim | 26 + l4/tool/vim/syntax/objdump.vim | 27 + l4/tool/vim/syntax/simics.vim | 89 + repomgr | 584 + tools/preprocess/COPYING | 339 + tools/preprocess/MAINTAINER | 2 + tools/preprocess/Makefile | 7 + tools/preprocess/README | 38 + tools/preprocess/TODO | 44 + tools/preprocess/doc/Doxyfile | 192 + tools/preprocess/doc/Makefile | 34 + tools/preprocess/doc/manpage.dox | 661 + tools/preprocess/src/Makefile | 25 + tools/preprocess/src/preprocess | 1799 +++ tools/preprocess/test/Makefile | 134 + tools/preprocess/test/c-preproc.cpp | 19 + tools/preprocess/test/combine.pl | 57 + tools/preprocess/test/comment_in_string.cpp | 23 + tools/preprocess/test/default_args.cpp | 32 + tools/preprocess/test/dropsection-ext.cpp | 22 + tools/preprocess/test/dropsection.cpp | 60 + tools/preprocess/test/explicit.cpp | 11 + tools/preprocess/test/extern_c.cpp | 8 + tools/preprocess/test/inline.cpp | 74 + tools/preprocess/test/interface.cpp | 15 + tools/preprocess/test/line.cpp | 20 + tools/preprocess/test/mapping.cpp | 784 + tools/preprocess/test/multifile1.cpp | 24 + tools/preprocess/test/multifile2.cpp | 23 + tools/preprocess/test/noinline.cpp | 8 + tools/preprocess/test/operator.cpp | 88 + tools/preprocess/test/parser.cpp | 90 + tools/preprocess/test/static.cpp | 25 + tools/preprocess/test/template.cpp | 236 + tools/preprocess/test/variable.cpp | 6 + tools/preprocess/test/verify/c-preproc.cc | 24 + tools/preprocess/test/verify/c-preproc.h | 15 + tools/preprocess/test/verify/c-preproc_i.h | 6 + .../test/verify/comment_in_string.cc | 30 + .../test/verify/comment_in_string.h | 17 + .../test/verify/comment_in_string_i.h | 6 + tools/preprocess/test/verify/default_args.cc | 13 + tools/preprocess/test/verify/default_args.h | 52 + tools/preprocess/test/verify/default_args_i.h | 6 + .../preprocess/test/verify/drop_multi1-ext.cc | 5 + tools/preprocess/test/verify/drop_multi1.cc | 39 + tools/preprocess/test/verify/drop_multi1.h | 43 + tools/preprocess/test/verify/drop_multi1_i.h | 6 + .../preprocess/test/verify/drop_multi2-ext.cc | 13 + tools/preprocess/test/verify/drop_multi2.cc | 39 + tools/preprocess/test/verify/drop_multi2.h | 64 + tools/preprocess/test/verify/drop_multi2_i.h | 6 + tools/preprocess/test/verify/drop_single1.cc | 30 + tools/preprocess/test/verify/drop_single1.h | 43 + tools/preprocess/test/verify/drop_single1_i.h | 6 + tools/preprocess/test/verify/drop_single2.cc | 31 + tools/preprocess/test/verify/drop_single2.h | 39 + tools/preprocess/test/verify/drop_single2_i.h | 6 + tools/preprocess/test/verify/drop_single3.cc | 39 + tools/preprocess/test/verify/drop_single3.h | 43 + tools/preprocess/test/verify/drop_single3_i.h | 6 + tools/preprocess/test/verify/explicit.cc | 11 + tools/preprocess/test/verify/explicit.h | 20 + tools/preprocess/test/verify/explicit_i.h | 6 + tools/preprocess/test/verify/extern_c.cc | 11 + tools/preprocess/test/verify/extern_c.h | 6 + tools/preprocess/test/verify/extern_c_i.h | 6 + tools/preprocess/test/verify/inline.cc | 33 + tools/preprocess/test/verify/inline.h | 125 + tools/preprocess/test/verify/inline_i.h | 6 + .../preprocess/test/verify/inline_noinline.cc | 73 + .../preprocess/test/verify/inline_noinline.h | 73 + .../test/verify/inline_noinline_i.h | 18 + tools/preprocess/test/verify/interface.cc | 14 + tools/preprocess/test/verify/interface_i.h | 6 + .../preprocess/test/verify/interfacepublic.h | 22 + tools/preprocess/test/verify/line.cc | 19 + tools/preprocess/test/verify/line.h | 28 + tools/preprocess/test/verify/line_i.h | 6 + tools/preprocess/test/verify/line_nh.cc | 19 + tools/preprocess/test/verify/line_nh.h | 21 + tools/preprocess/test/verify/line_nh_i.h | 6 + tools/preprocess/test/verify/line_not.cc | 15 + tools/preprocess/test/verify/line_not.h | 21 + tools/preprocess/test/verify/line_not_i.h | 6 + tools/preprocess/test/verify/mapping.cc | 730 + tools/preprocess/test/verify/mapping.h | 155 + tools/preprocess/test/verify/mapping_i.h | 95 + .../preprocess/test/verify/mapping_inline.cc | 647 + tools/preprocess/test/verify/mapping_inline.h | 231 + .../preprocess/test/verify/mapping_inline_i.h | 112 + .../preprocess/test/verify/multifile-part1.cc | 12 + .../preprocess/test/verify/multifile-part2.cc | 12 + tools/preprocess/test/verify/multifile.cc | 12 + tools/preprocess/test/verify/multifile.h | 66 + tools/preprocess/test/verify/multifile_i.h | 9 + tools/preprocess/test/verify/noinline.cc | 5 + tools/preprocess/test/verify/noinline.h | 6 + tools/preprocess/test/verify/noinline_i.h | 12 + tools/preprocess/test/verify/operator.cc | 170 + tools/preprocess/test/verify/operator.h | 52 + tools/preprocess/test/verify/operator_i.h | 144 + tools/preprocess/test/verify/parser.cc | 55 + tools/preprocess/test/verify/parser.h | 87 + tools/preprocess/test/verify/parser_i.h | 14 + .../preprocess/test/verify/parser_noinline.cc | 75 + .../preprocess/test/verify/parser_noinline.h | 54 + .../test/verify/parser_noinline_i.h | 17 + tools/preprocess/test/verify/random.cc | 373 + tools/preprocess/test/verify/random.h | 227 + tools/preprocess/test/verify/random_i.h | 16 + tools/preprocess/test/verify/random_inline.cc | 110 + tools/preprocess/test/verify/random_inline.h | 388 + .../preprocess/test/verify/random_inline_i.h | 133 + tools/preprocess/test/verify/static.cc | 35 + tools/preprocess/test/verify/static.h | 6 + tools/preprocess/test/verify/static_i.h | 6 + tools/preprocess/test/verify/template.cc | 24 + tools/preprocess/test/verify/template.h | 301 + tools/preprocess/test/verify/template_i.h | 65 + .../preprocess/test/verify/template_inline.cc | 14 + .../preprocess/test/verify/template_inline.h | 316 + .../test/verify/template_inline_i.h | 65 + tools/preprocess/test/verify/variable.cc | 11 + tools/preprocess/test/verify/variable.h | 6 + tools/preprocess/test/verify/variable_i.h | 6 + 7744 files changed, 987172 insertions(+) create mode 100644 kernel/fiasco/BENCHMARKING create mode 100644 kernel/fiasco/COPYING create mode 100644 kernel/fiasco/MAINTAINER create mode 100644 kernel/fiasco/Makefile create mode 100644 kernel/fiasco/README create mode 100644 kernel/fiasco/src/.gdbinit create mode 100644 kernel/fiasco/src/BUG-HUNTING create mode 100644 kernel/fiasco/src/Circular.max.amd64 create mode 100644 kernel/fiasco/src/Circular.max.arm create mode 100644 kernel/fiasco/src/Circular.max.ia32 create mode 100644 kernel/fiasco/src/Circular.max.ppc32 create mode 100644 kernel/fiasco/src/Circular.max.ux create mode 100644 kernel/fiasco/src/DEPS.blacklist create mode 100644 kernel/fiasco/src/Kconfig create mode 100644 kernel/fiasco/src/Makeconf create mode 100644 kernel/fiasco/src/Makeconf.amd64 create mode 100644 kernel/fiasco/src/Makeconf.arm create mode 100644 kernel/fiasco/src/Makeconf.ia32 create mode 100644 kernel/fiasco/src/Makeconf.ppc32 create mode 100644 kernel/fiasco/src/Makeconf.sparc create mode 100644 kernel/fiasco/src/Makeconf.ux create mode 100644 kernel/fiasco/src/Makefile create mode 100644 kernel/fiasco/src/Makefile.sub1 create mode 100644 kernel/fiasco/src/Makefile.sub2 create mode 100644 kernel/fiasco/src/Makerules.ABI create mode 100644 kernel/fiasco/src/Makerules.BOOT create mode 100644 kernel/fiasco/src/Makerules.CHECKSUM create mode 100644 kernel/fiasco/src/Makerules.CRT0 create mode 100644 kernel/fiasco/src/Makerules.CXXLIB create mode 100644 kernel/fiasco/src/Makerules.DRIVERS create mode 100644 kernel/fiasco/src/Makerules.GBLCFG create mode 100644 kernel/fiasco/src/Makerules.JABI create mode 100644 kernel/fiasco/src/Makerules.JDB create mode 100644 kernel/fiasco/src/Makerules.LIBDISASM create mode 100644 kernel/fiasco/src/Makerules.LIBGZIP create mode 100644 kernel/fiasco/src/Makerules.LIBK create mode 100644 kernel/fiasco/src/Makerules.LIBKERN create mode 100644 kernel/fiasco/src/Makerules.LIBPERFCTR create mode 100644 kernel/fiasco/src/Makerules.LIBREGEX create mode 100644 kernel/fiasco/src/Makerules.LIBUART create mode 100644 kernel/fiasco/src/Makerules.LINES create mode 100644 kernel/fiasco/src/Makerules.MINILIBC create mode 100644 kernel/fiasco/src/Makerules.SYMBOLS create mode 100644 kernel/fiasco/src/Makerules.TCBOFFSET create mode 100644 kernel/fiasco/src/Makerules.TYPES create mode 100644 kernel/fiasco/src/Makerules.UNITTEST create mode 100644 kernel/fiasco/src/Makerules.VERSION create mode 100644 kernel/fiasco/src/Makerules.global create mode 100644 kernel/fiasco/src/Modules.amd64 create mode 100644 kernel/fiasco/src/Modules.arm create mode 100644 kernel/fiasco/src/Modules.generic create mode 100644 kernel/fiasco/src/Modules.ia32 create mode 100644 kernel/fiasco/src/Modules.ppc32 create mode 100644 kernel/fiasco/src/Modules.sparc create mode 100644 kernel/fiasco/src/Modules.ux create mode 100644 kernel/fiasco/src/README create mode 100644 kernel/fiasco/src/README.style create mode 100644 kernel/fiasco/src/TODO create mode 100644 kernel/fiasco/src/abi/amd64/kip-amd64-debug.cpp create mode 100644 kernel/fiasco/src/abi/amd64/kip-amd64.cpp create mode 100644 kernel/fiasco/src/abi/arm/kip-arm.cpp create mode 100644 kernel/fiasco/src/abi/ia32/kip-ia32-debug.cpp create mode 100644 kernel/fiasco/src/abi/ia32/kip-ia32.cpp create mode 100644 kernel/fiasco/src/abi/kip-debug.cpp create mode 100644 kernel/fiasco/src/abi/kip.cpp create mode 100644 kernel/fiasco/src/abi/l4_buf_desc.cpp create mode 100644 kernel/fiasco/src/abi/l4_error.cpp create mode 100644 kernel/fiasco/src/abi/l4_fpage.cpp create mode 100644 kernel/fiasco/src/abi/l4_msg_item.cpp create mode 100644 kernel/fiasco/src/abi/l4_types-debug.cpp create mode 100644 kernel/fiasco/src/abi/l4_types-objs.cpp create mode 100644 kernel/fiasco/src/abi/l4_types.cpp create mode 100644 kernel/fiasco/src/abi/ppc32/kip-ppc32.cpp create mode 100644 kernel/fiasco/src/abi/sparc/kip-sparc.cpp create mode 100644 kernel/fiasco/src/abi/virt-ia32-amd64.cpp create mode 100644 kernel/fiasco/src/boot/amd64/Makerules.BOOT.amd64 create mode 100644 kernel/fiasco/src/boot/amd64/boot.S create mode 100644 kernel/fiasco/src/boot/amd64/boot_cpu.cc create mode 100644 kernel/fiasco/src/boot/amd64/boot_idt.S create mode 100644 kernel/fiasco/src/boot/amd64/boot_paging.h create mode 100644 kernel/fiasco/src/boot/amd64/bootstrap.ld create mode 100644 kernel/fiasco/src/boot/arm/Makerules.BOOT.arm create mode 100644 kernel/fiasco/src/boot/boot_cpu.h create mode 100644 kernel/fiasco/src/boot/boot_direct_cons.h create mode 100644 kernel/fiasco/src/boot/boot_libc_glue.cc create mode 100644 kernel/fiasco/src/boot/bootstrap.cc create mode 100644 kernel/fiasco/src/boot/direct_cons_putchar.cc create mode 100644 kernel/fiasco/src/boot/ia32/Makerules.BOOT.ia32 create mode 100644 kernel/fiasco/src/boot/ia32/boot.S create mode 100644 kernel/fiasco/src/boot/ia32/boot_cpu.cc create mode 100644 kernel/fiasco/src/boot/ia32/boot_idt.S create mode 100644 kernel/fiasco/src/boot/ia32/boot_paging.h create mode 100644 kernel/fiasco/src/boot/ia32/bootstrap.ld create mode 100644 kernel/fiasco/src/doxygen.conf create mode 100644 kernel/fiasco/src/drivers/amd64/io-amd64.cpp create mode 100644 kernel/fiasco/src/drivers/amd64/keycodes-arch.h create mode 100644 kernel/fiasco/src/drivers/amd64/mem-amd64.cpp create mode 100644 kernel/fiasco/src/drivers/amd64/processor-amd64.cpp create mode 100644 kernel/fiasco/src/drivers/amd64/reset-amd64.cpp create mode 100644 kernel/fiasco/src/drivers/arm/cache_func_gen.cpp create mode 100644 kernel/fiasco/src/drivers/arm/h3xxx.cpp create mode 100644 kernel/fiasco/src/drivers/arm/io-arm.cpp create mode 100644 kernel/fiasco/src/drivers/arm/keycodes-arch.h create mode 100644 kernel/fiasco/src/drivers/arm/mem-arm.cpp create mode 100644 kernel/fiasco/src/drivers/arm/mmu-arm.cpp create mode 100644 kernel/fiasco/src/drivers/arm/processor-arm.cpp create mode 100644 kernel/fiasco/src/drivers/arm/sa1100.cpp create mode 100644 kernel/fiasco/src/drivers/arm/uart-sa1100.cpp create mode 100644 kernel/fiasco/src/drivers/console.cpp create mode 100644 kernel/fiasco/src/drivers/delayloop.cpp create mode 100644 kernel/fiasco/src/drivers/filter_console.cpp create mode 100644 kernel/fiasco/src/drivers/glue_libc.cc create mode 100644 kernel/fiasco/src/drivers/ia32/io-ia32.cpp create mode 100644 kernel/fiasco/src/drivers/ia32/keycodes-arch.h create mode 100644 kernel/fiasco/src/drivers/ia32/mem-ia32.cpp create mode 100644 kernel/fiasco/src/drivers/ia32/processor-ia32.cpp create mode 100644 kernel/fiasco/src/drivers/ia32/reset-ia32.cpp create mode 100644 kernel/fiasco/src/drivers/io.cpp create mode 100644 kernel/fiasco/src/drivers/keyb-pc.cpp create mode 100644 kernel/fiasco/src/drivers/keyb.cpp create mode 100644 kernel/fiasco/src/drivers/keycodes.h create mode 100644 kernel/fiasco/src/drivers/libc_backend.h create mode 100644 kernel/fiasco/src/drivers/mem.cpp create mode 100644 kernel/fiasco/src/drivers/mmu.cpp create mode 100644 kernel/fiasco/src/drivers/mux_console.cpp create mode 100644 kernel/fiasco/src/drivers/pci.cpp create mode 100644 kernel/fiasco/src/drivers/ppc32/include/mmu.h create mode 100644 kernel/fiasco/src/drivers/ppc32/io-ppc32.cpp create mode 100644 kernel/fiasco/src/drivers/ppc32/kernel_uart-ppc32.cpp create mode 100644 kernel/fiasco/src/drivers/ppc32/keycodes-arch.h create mode 100644 kernel/fiasco/src/drivers/ppc32/mem-ppc32.cpp create mode 100644 kernel/fiasco/src/drivers/ppc32/ppc_types.cpp create mode 100644 kernel/fiasco/src/drivers/ppc32/processor-ppc32.cpp create mode 100644 kernel/fiasco/src/drivers/ppc32/reset-ppc32.cpp create mode 100644 kernel/fiasco/src/drivers/ppc32/uart-mpc52xx.cpp create mode 100644 kernel/fiasco/src/drivers/ppc32/uart-of.cpp create mode 100644 kernel/fiasco/src/drivers/processor.cpp create mode 100644 kernel/fiasco/src/drivers/sparc/io-sparc.cpp create mode 100644 kernel/fiasco/src/drivers/sparc/kernel_uart-sparc.cpp create mode 100644 kernel/fiasco/src/drivers/sparc/keycodes-arch.h create mode 100644 kernel/fiasco/src/drivers/sparc/mem-sparc.cpp create mode 100644 kernel/fiasco/src/drivers/sparc/processor-sparc.cpp create mode 100644 kernel/fiasco/src/drivers/sparc/reset-sparc.cpp create mode 100644 kernel/fiasco/src/drivers/sparc/sparc_types.cpp create mode 100644 kernel/fiasco/src/drivers/sparc/uart-leon3.cpp create mode 100644 kernel/fiasco/src/drivers/uart-16550.cpp create mode 100644 kernel/fiasco/src/drivers/uart.cpp create mode 100644 kernel/fiasco/src/drivers/ux/keycodes-arch.h create mode 100644 kernel/fiasco/src/drivers/ux/processor-ux.cpp create mode 100644 kernel/fiasco/src/drivers/ux/ux_con.c create mode 100644 kernel/fiasco/src/drivers/ux/ux_net.c create mode 100644 kernel/fiasco/src/drivers/vga_console.cpp create mode 100644 kernel/fiasco/src/jabi/jdb_ktrace.cpp create mode 100644 kernel/fiasco/src/jdb/arm/jdb-arm.cpp create mode 100644 kernel/fiasco/src/jdb/arm/jdb_dump_entry_frame-arm.cpp create mode 100644 kernel/fiasco/src/jdb/arm/jdb_entry_frame-arm.cpp create mode 100644 kernel/fiasco/src/jdb/arm/jdb_extensions.cpp create mode 100644 kernel/fiasco/src/jdb/arm/jdb_kern_info-arm.cpp create mode 100644 kernel/fiasco/src/jdb/arm/jdb_kern_info-bench-arm.cpp create mode 100644 kernel/fiasco/src/jdb/arm/jdb_kern_info-cpu-arm.cpp create mode 100644 kernel/fiasco/src/jdb/arm/jdb_mem_dump.cpp create mode 100644 kernel/fiasco/src/jdb/arm/jdb_perf.cpp create mode 100644 kernel/fiasco/src/jdb/arm/jdb_ptab-arm.cpp create mode 100644 kernel/fiasco/src/jdb/arm/jdb_reg_dump.cpp create mode 100644 kernel/fiasco/src/jdb/arm/jdb_tcb-arm.cpp create mode 100644 kernel/fiasco/src/jdb/arm/jdb_trace_set-arm.cpp create mode 100644 kernel/fiasco/src/jdb/arm/jdb_vm.cpp create mode 100644 kernel/fiasco/src/jdb/ia32/32/jdb_bp-ia32.cpp create mode 100644 kernel/fiasco/src/jdb/ia32/32/jdb_kern_info-bench-ia32-32.cpp create mode 100644 kernel/fiasco/src/jdb/ia32/32/jdb_kern_info-bench.txt create mode 100644 kernel/fiasco/src/jdb/ia32/32/jdb_tcb-ia32-ux.cpp create mode 100644 kernel/fiasco/src/jdb/ia32/64/jdb_bp-amd64.cpp create mode 100644 kernel/fiasco/src/jdb/ia32/64/jdb_kern_info-bench-ia32-64.cpp create mode 100644 kernel/fiasco/src/jdb/ia32/64/jdb_ptab-amd64.cpp create mode 100644 kernel/fiasco/src/jdb/ia32/64/jdb_tcb-amd64.cpp create mode 100644 kernel/fiasco/src/jdb/ia32/jdb-ia32-amd64.cpp create mode 100644 kernel/fiasco/src/jdb/ia32/jdb-ia32-ux.cpp create mode 100644 kernel/fiasco/src/jdb/ia32/jdb-int3-ia32-amd64.cpp create mode 100644 kernel/fiasco/src/jdb/ia32/jdb-int3-ia32-ux.cpp create mode 100644 kernel/fiasco/src/jdb/ia32/jdb_bp-ia32-amd64.cpp create mode 100644 kernel/fiasco/src/jdb/ia32/jdb_bp-ia32-ux.cpp create mode 100644 kernel/fiasco/src/jdb/ia32/jdb_bt-ia32-ux.cpp create mode 100644 kernel/fiasco/src/jdb/ia32/jdb_entry_frame-ia32.cpp create mode 100644 kernel/fiasco/src/jdb/ia32/jdb_io_ports.cpp create mode 100644 kernel/fiasco/src/jdb/ia32/jdb_iomap.cpp create mode 100644 kernel/fiasco/src/jdb/ia32/jdb_kern_info-dr.cpp create mode 100644 kernel/fiasco/src/jdb/ia32/jdb_kern_info-ia32-amd64.cpp create mode 100644 kernel/fiasco/src/jdb/ia32/jdb_kern_info-ia32-ux.cpp create mode 100644 kernel/fiasco/src/jdb/ia32/jdb_kern_info-mtrr.cpp create mode 100644 kernel/fiasco/src/jdb/ia32/jdb_kern_info-pci.cpp create mode 100644 kernel/fiasco/src/jdb/ia32/jdb_misc-ia32-amd64.cpp create mode 100644 kernel/fiasco/src/jdb/ia32/jdb_screen-ia32.cpp create mode 100644 kernel/fiasco/src/jdb/ia32/jdb_trace_set-ia32-ux.cpp create mode 100644 kernel/fiasco/src/jdb/jdb-ansi.cpp create mode 100644 kernel/fiasco/src/jdb/jdb-thread.cpp create mode 100644 kernel/fiasco/src/jdb/jdb.cpp create mode 100644 kernel/fiasco/src/jdb/jdb_attach_irq.cpp create mode 100644 kernel/fiasco/src/jdb/jdb_bp.cpp create mode 100644 kernel/fiasco/src/jdb/jdb_bts.cpp create mode 100644 kernel/fiasco/src/jdb/jdb_console_buffer.cpp create mode 100644 kernel/fiasco/src/jdb/jdb_core.cpp create mode 100644 kernel/fiasco/src/jdb/jdb_counters.cpp create mode 100644 kernel/fiasco/src/jdb/jdb_dbinfo.cpp create mode 100644 kernel/fiasco/src/jdb/jdb_disasm.cpp create mode 100644 kernel/fiasco/src/jdb/jdb_dump.cpp create mode 100644 kernel/fiasco/src/jdb/jdb_exit_module.cpp create mode 100644 kernel/fiasco/src/jdb/jdb_factory.cpp create mode 100644 kernel/fiasco/src/jdb/jdb_gzip.cpp create mode 100644 kernel/fiasco/src/jdb/jdb_halt_thread.cpp create mode 100644 kernel/fiasco/src/jdb/jdb_handler_queue.cpp create mode 100644 kernel/fiasco/src/jdb/jdb_idle_stats.cpp create mode 100644 kernel/fiasco/src/jdb/jdb_input.cpp create mode 100644 kernel/fiasco/src/jdb/jdb_io_apic.cpp create mode 100644 kernel/fiasco/src/jdb/jdb_ipc_gate.cpp create mode 100644 kernel/fiasco/src/jdb/jdb_ipi.cpp create mode 100644 kernel/fiasco/src/jdb/jdb_jaf_module.cpp create mode 100644 kernel/fiasco/src/jdb/jdb_kern_info-apic.cpp create mode 100644 kernel/fiasco/src/jdb/jdb_kern_info-bench.cpp create mode 100644 kernel/fiasco/src/jdb/jdb_kern_info.cpp create mode 100644 kernel/fiasco/src/jdb/jdb_kern_info_config.cpp create mode 100644 kernel/fiasco/src/jdb/jdb_kern_info_kip.cpp create mode 100644 kernel/fiasco/src/jdb/jdb_kern_info_kmem_alloc.cpp create mode 100644 kernel/fiasco/src/jdb/jdb_kern_info_region.cpp create mode 100644 kernel/fiasco/src/jdb/jdb_kobject.cpp create mode 100644 kernel/fiasco/src/jdb/jdb_kobject_names.cpp create mode 100644 kernel/fiasco/src/jdb/jdb_lines.cpp create mode 100644 kernel/fiasco/src/jdb/jdb_list.cpp create mode 100644 kernel/fiasco/src/jdb/jdb_log.cpp create mode 100644 kernel/fiasco/src/jdb/jdb_mapdb.cpp create mode 100644 kernel/fiasco/src/jdb/jdb_module.cpp create mode 100644 kernel/fiasco/src/jdb/jdb_mp_request_sl.cpp create mode 100644 kernel/fiasco/src/jdb/jdb_obj_space.cpp create mode 100644 kernel/fiasco/src/jdb/jdb_pic.cpp create mode 100644 kernel/fiasco/src/jdb/jdb_prompt_ext.cpp create mode 100644 kernel/fiasco/src/jdb/jdb_prompt_module.cpp create mode 100644 kernel/fiasco/src/jdb/jdb_ptab-ia32-ux-arm.cpp create mode 100644 kernel/fiasco/src/jdb/jdb_ptab.cpp create mode 100644 kernel/fiasco/src/jdb/jdb_rcupdate.cpp create mode 100644 kernel/fiasco/src/jdb/jdb_regex.cpp create mode 100644 kernel/fiasco/src/jdb/jdb_scheduler.cpp create mode 100644 kernel/fiasco/src/jdb/jdb_screen.cpp create mode 100644 kernel/fiasco/src/jdb/jdb_sender_list.cpp create mode 100644 kernel/fiasco/src/jdb/jdb_space.cpp create mode 100644 kernel/fiasco/src/jdb/jdb_symbol.cpp create mode 100644 kernel/fiasco/src/jdb/jdb_table.cpp create mode 100644 kernel/fiasco/src/jdb/jdb_tbuf.cpp create mode 100644 kernel/fiasco/src/jdb/jdb_tbuf_init.cpp create mode 100644 kernel/fiasco/src/jdb/jdb_tbuf_output.cpp create mode 100644 kernel/fiasco/src/jdb/jdb_tbuf_show.cpp create mode 100644 kernel/fiasco/src/jdb/jdb_tcb.cpp create mode 100644 kernel/fiasco/src/jdb/jdb_tetris.cpp create mode 100644 kernel/fiasco/src/jdb/jdb_thread.cpp create mode 100644 kernel/fiasco/src/jdb/jdb_thread_list.cpp create mode 100644 kernel/fiasco/src/jdb/jdb_timeout.cpp create mode 100644 kernel/fiasco/src/jdb/jdb_trace.cpp create mode 100644 kernel/fiasco/src/jdb/jdb_trace_set.cpp create mode 100644 kernel/fiasco/src/jdb/jdb_trap_state.cpp create mode 100644 kernel/fiasco/src/jdb/jdb_utcb.cpp create mode 100644 kernel/fiasco/src/jdb/jdb_util.cpp create mode 100644 kernel/fiasco/src/jdb/ppc32/jdb-ppc32.cpp create mode 100644 kernel/fiasco/src/jdb/ppc32/jdb_entry_frame-ppc32.cpp create mode 100644 kernel/fiasco/src/jdb/ppc32/jdb_tcb-ppc32.cpp create mode 100644 kernel/fiasco/src/jdb/sparc/jdb-sparc.cpp create mode 100644 kernel/fiasco/src/jdb/sparc/jdb_entry_frame-sparc.cpp create mode 100644 kernel/fiasco/src/jdb/sparc/jdb_tcb-sparc.cpp create mode 100644 kernel/fiasco/src/jdb/ux/jdb-int3.cpp create mode 100644 kernel/fiasco/src/jdb/ux/jdb-ux.cpp create mode 100644 kernel/fiasco/src/jdb/ux/jdb_bp-ux.cpp create mode 100644 kernel/fiasco/src/jdb/ux/jdb_kern_info-ux.cpp create mode 100644 kernel/fiasco/src/kern/acpi.cpp create mode 100644 kernel/fiasco/src/kern/amd64/Makerules.SYMBOLS.amd64 create mode 100644 kernel/fiasco/src/kern/app_cpu_thread.cpp create mode 100644 kernel/fiasco/src/kern/arm/Makerules.KERNEL create mode 100644 kernel/fiasco/src/kern/arm/__main.cpp create mode 100644 kernel/fiasco/src/kern/arm/boot_info-arch.cpp create mode 100644 kernel/fiasco/src/kern/arm/boot_uart_init.cpp create mode 100644 kernel/fiasco/src/kern/arm/bootstrap.cpp create mode 100644 kernel/fiasco/src/kern/arm/bsp/imx/Kconfig create mode 100644 kernel/fiasco/src/kern/arm/bsp/imx/Modules create mode 100644 kernel/fiasco/src/kern/arm/bsp/imx/bootstrap-arm-imx.cpp create mode 100644 kernel/fiasco/src/kern/arm/bsp/imx/config-arm-imx.cpp create mode 100644 kernel/fiasco/src/kern/arm/bsp/imx/kernel_uart-arm-imx.cpp create mode 100644 kernel/fiasco/src/kern/arm/bsp/imx/mem_layout-arm-imx.cpp create mode 100644 kernel/fiasco/src/kern/arm/bsp/imx/pic-arm-imx.cpp create mode 100644 kernel/fiasco/src/kern/arm/bsp/imx/pic-arm-imx51.cpp create mode 100644 kernel/fiasco/src/kern/arm/bsp/imx/reset-arm-imx.cpp create mode 100644 kernel/fiasco/src/kern/arm/bsp/imx/timer-arm-imx21.cpp create mode 100644 kernel/fiasco/src/kern/arm/bsp/imx/timer-arm-imx_epit.cpp create mode 100644 kernel/fiasco/src/kern/arm/bsp/imx/uart-imx.cpp create mode 100644 kernel/fiasco/src/kern/arm/bsp/integrator/Kconfig create mode 100644 kernel/fiasco/src/kern/arm/bsp/integrator/Modules create mode 100644 kernel/fiasco/src/kern/arm/bsp/integrator/bootstrap-arm-integrator.cpp create mode 100644 kernel/fiasco/src/kern/arm/bsp/integrator/config-arm-integrator.cpp create mode 100644 kernel/fiasco/src/kern/arm/bsp/integrator/kernel_uart-arm-integrator.cpp create mode 100644 kernel/fiasco/src/kern/arm/bsp/integrator/mem_layout-arm-integrator.cpp create mode 100644 kernel/fiasco/src/kern/arm/bsp/integrator/pic-arm-integrator.cpp create mode 100644 kernel/fiasco/src/kern/arm/bsp/integrator/reset-arm-integrator.cpp create mode 100644 kernel/fiasco/src/kern/arm/bsp/integrator/timer-arm-integrator.cpp create mode 100644 kernel/fiasco/src/kern/arm/bsp/integrator/uart-arm-integrator.cpp create mode 100644 kernel/fiasco/src/kern/arm/bsp/kirkwood/Kconfig create mode 100644 kernel/fiasco/src/kern/arm/bsp/kirkwood/Modules create mode 100644 kernel/fiasco/src/kern/arm/bsp/kirkwood/bootstrap-arm-kirkwood.cpp create mode 100644 kernel/fiasco/src/kern/arm/bsp/kirkwood/config-arm-kirkwood.cpp create mode 100644 kernel/fiasco/src/kern/arm/bsp/kirkwood/kernel_uart-arm-kirkwood.cpp create mode 100644 kernel/fiasco/src/kern/arm/bsp/kirkwood/mem_layout-arm-kirkwood.cpp create mode 100644 kernel/fiasco/src/kern/arm/bsp/kirkwood/pic-arm-kirkwood.cpp create mode 100644 kernel/fiasco/src/kern/arm/bsp/kirkwood/reset-arm-kirkwood.cpp create mode 100644 kernel/fiasco/src/kern/arm/bsp/kirkwood/timer-arm-kirkwood.cpp create mode 100644 kernel/fiasco/src/kern/arm/bsp/kirkwood/uart-16550-arm-kirkwood.cpp create mode 100644 kernel/fiasco/src/kern/arm/bsp/omap3/Kconfig create mode 100644 kernel/fiasco/src/kern/arm/bsp/omap3/Modules create mode 100644 kernel/fiasco/src/kern/arm/bsp/omap3/boot_mp-arm-omap4.cpp create mode 100644 kernel/fiasco/src/kern/arm/bsp/omap3/bootstrap-arm-omap.cpp create mode 100644 kernel/fiasco/src/kern/arm/bsp/omap3/config-arm-omap.cpp create mode 100644 kernel/fiasco/src/kern/arm/bsp/omap3/kernel_uart-arm-omap.cpp create mode 100644 kernel/fiasco/src/kern/arm/bsp/omap3/mem_layout-arm-omap.cpp create mode 100644 kernel/fiasco/src/kern/arm/bsp/omap3/pic-arm-gic-omap4.cpp create mode 100644 kernel/fiasco/src/kern/arm/bsp/omap3/pic-arm-omap3.cpp create mode 100644 kernel/fiasco/src/kern/arm/bsp/omap3/reset-arm-omap.cpp create mode 100644 kernel/fiasco/src/kern/arm/bsp/omap3/timer-arm-mptimer-omap4.cpp create mode 100644 kernel/fiasco/src/kern/arm/bsp/omap3/timer-arm-omap3.cpp create mode 100644 kernel/fiasco/src/kern/arm/bsp/omap3/uart-arm-omap.cpp create mode 100644 kernel/fiasco/src/kern/arm/bsp/pxa-sa/config-arm-pxa_sa1100.cpp create mode 100644 kernel/fiasco/src/kern/arm/bsp/pxa-sa/pic-arm-pxa_sa1100.cpp create mode 100644 kernel/fiasco/src/kern/arm/bsp/pxa-sa/timer-arm-pxa_sa1100.cpp create mode 100644 kernel/fiasco/src/kern/arm/bsp/pxa/Kconfig create mode 100644 kernel/fiasco/src/kern/arm/bsp/pxa/Modules create mode 100644 kernel/fiasco/src/kern/arm/bsp/pxa/bootstrap-arm-pxa.cpp create mode 100644 kernel/fiasco/src/kern/arm/bsp/pxa/kernel_uart-arm-pxa.cpp create mode 100644 kernel/fiasco/src/kern/arm/bsp/pxa/mem_layout-arm-pxa.cpp create mode 100644 kernel/fiasco/src/kern/arm/bsp/pxa/reset-arm-pxa.cpp create mode 100644 kernel/fiasco/src/kern/arm/bsp/pxa/uart-16550-arm-pxa.cpp create mode 100644 kernel/fiasco/src/kern/arm/bsp/realview/Kconfig create mode 100644 kernel/fiasco/src/kern/arm/bsp/realview/Modules create mode 100644 kernel/fiasco/src/kern/arm/bsp/realview/board_check-arm-realview.cpp create mode 100644 kernel/fiasco/src/kern/arm/bsp/realview/boot_mp-arm-realview.cpp create mode 100644 kernel/fiasco/src/kern/arm/bsp/realview/bootstrap-arm-realview.cpp create mode 100644 kernel/fiasco/src/kern/arm/bsp/realview/clock-arm-realview.cpp create mode 100644 kernel/fiasco/src/kern/arm/bsp/realview/config-arm-realview.cpp create mode 100644 kernel/fiasco/src/kern/arm/bsp/realview/kernel_uart-arm-realview.cpp create mode 100644 kernel/fiasco/src/kern/arm/bsp/realview/mem_layout-arm-realview.cpp create mode 100644 kernel/fiasco/src/kern/arm/bsp/realview/outer_cache-arm-realview.cpp create mode 100644 kernel/fiasco/src/kern/arm/bsp/realview/pic-arm-realview.cpp create mode 100644 kernel/fiasco/src/kern/arm/bsp/realview/platform-arm-realview.cpp create mode 100644 kernel/fiasco/src/kern/arm/bsp/realview/reset-arm-realview.cpp create mode 100644 kernel/fiasco/src/kern/arm/bsp/realview/timer-arm-mptimer-realview.cpp create mode 100644 kernel/fiasco/src/kern/arm/bsp/realview/timer-arm-realview.cpp create mode 100644 kernel/fiasco/src/kern/arm/bsp/realview/uart-arm-realview.cpp create mode 100644 kernel/fiasco/src/kern/arm/bsp/s3c/Kconfig create mode 100644 kernel/fiasco/src/kern/arm/bsp/s3c/Modules create mode 100644 kernel/fiasco/src/kern/arm/bsp/s3c/bootstrap-arm-s3c2410.cpp create mode 100644 kernel/fiasco/src/kern/arm/bsp/s3c/config-arm-s3c2410.cpp create mode 100644 kernel/fiasco/src/kern/arm/bsp/s3c/kernel_uart-arm-s3c2410.cpp create mode 100644 kernel/fiasco/src/kern/arm/bsp/s3c/mem_layout-arm-s3c2410.cpp create mode 100644 kernel/fiasco/src/kern/arm/bsp/s3c/pic-arm-s3c2410.cpp create mode 100644 kernel/fiasco/src/kern/arm/bsp/s3c/reset-arm-s3c2410.cpp create mode 100644 kernel/fiasco/src/kern/arm/bsp/s3c/timer-arm-s3c2410.cpp create mode 100644 kernel/fiasco/src/kern/arm/bsp/s3c/uart-s3c2410.cpp create mode 100644 kernel/fiasco/src/kern/arm/bsp/sa1100/Kconfig create mode 100644 kernel/fiasco/src/kern/arm/bsp/sa1100/Modules create mode 100644 kernel/fiasco/src/kern/arm/bsp/sa1100/bootstrap-arm-sa1100.cpp create mode 100644 kernel/fiasco/src/kern/arm/bsp/sa1100/kernel_uart-arm-sa1100.cpp create mode 100644 kernel/fiasco/src/kern/arm/bsp/sa1100/mem_layout-arm-sa1100.cpp create mode 100644 kernel/fiasco/src/kern/arm/bsp/sa1100/reset-arm-sa1100.cpp create mode 100644 kernel/fiasco/src/kern/arm/bsp/tegra2/Kconfig create mode 100644 kernel/fiasco/src/kern/arm/bsp/tegra2/Modules create mode 100644 kernel/fiasco/src/kern/arm/bsp/tegra2/boot_mp-arm-tegra2.cpp create mode 100644 kernel/fiasco/src/kern/arm/bsp/tegra2/bootstrap-arm-tegra2.cpp create mode 100644 kernel/fiasco/src/kern/arm/bsp/tegra2/config-arm-tegra2.cpp create mode 100644 kernel/fiasco/src/kern/arm/bsp/tegra2/kernel_uart-arm-tegra2.cpp create mode 100644 kernel/fiasco/src/kern/arm/bsp/tegra2/mem_layout-arm-tegra2.cpp create mode 100644 kernel/fiasco/src/kern/arm/bsp/tegra2/outer_cache-arm-tegra2.cpp create mode 100644 kernel/fiasco/src/kern/arm/bsp/tegra2/pic-arm-tegra2.cpp create mode 100644 kernel/fiasco/src/kern/arm/bsp/tegra2/reset-arm-tegra2.cpp create mode 100644 kernel/fiasco/src/kern/arm/bsp/tegra2/timer-arm-tegra2.cpp create mode 100644 kernel/fiasco/src/kern/arm/bsp/tegra2/uart-16550-arm-tegra2.cpp create mode 100644 kernel/fiasco/src/kern/arm/config-arm.cpp create mode 100644 kernel/fiasco/src/kern/arm/context-arm.cpp create mode 100644 kernel/fiasco/src/kern/arm/continuation-arm.cpp create mode 100644 kernel/fiasco/src/kern/arm/cpu-arm.cpp create mode 100644 kernel/fiasco/src/kern/arm/crt0.S create mode 100644 kernel/fiasco/src/kern/arm/entry_frame-arm.cpp create mode 100644 kernel/fiasco/src/kern/arm/fpu-arm.cpp create mode 100644 kernel/fiasco/src/kern/arm/gic.cpp create mode 100644 kernel/fiasco/src/kern/arm/ipi-arm.cpp create mode 100644 kernel/fiasco/src/kern/arm/ivt.S create mode 100644 kernel/fiasco/src/kern/arm/kdb_ke-arm.cpp create mode 100644 kernel/fiasco/src/kern/arm/kern_lib_page.cpp create mode 100644 kernel/fiasco/src/kern/arm/kernel_task-arm.cpp create mode 100644 kernel/fiasco/src/kern/arm/kernel_thread-arm.cpp create mode 100644 kernel/fiasco/src/kern/arm/kip_init.cpp create mode 100644 kernel/fiasco/src/kern/arm/kmem.cpp create mode 100644 kernel/fiasco/src/kern/arm/kmem_alloc-arm.cpp create mode 100644 kernel/fiasco/src/kern/arm/kmem_space.cpp create mode 100644 kernel/fiasco/src/kern/arm/logdefs.h create mode 100644 kernel/fiasco/src/kern/arm/main.cpp create mode 100644 kernel/fiasco/src/kern/arm/mapping-arm.cpp create mode 100644 kernel/fiasco/src/kern/arm/mem_layout-arm.cpp create mode 100644 kernel/fiasco/src/kern/arm/mem_layout-noncont.cpp create mode 100644 kernel/fiasco/src/kern/arm/mem_op.cpp create mode 100644 kernel/fiasco/src/kern/arm/mem_space-arm.cpp create mode 100644 kernel/fiasco/src/kern/arm/mem_unit.cpp create mode 100644 kernel/fiasco/src/kern/arm/outer_cache-l2cxx0.cpp create mode 100644 kernel/fiasco/src/kern/arm/outer_cache.cpp create mode 100644 kernel/fiasco/src/kern/arm/pagetable-arch.cpp create mode 100644 kernel/fiasco/src/kern/arm/pagetable-arch_defs.h create mode 100644 kernel/fiasco/src/kern/arm/pagetable.cpp create mode 100644 kernel/fiasco/src/kern/arm/paging-arm.cpp create mode 100644 kernel/fiasco/src/kern/arm/perf_cnt-arm.cpp create mode 100644 kernel/fiasco/src/kern/arm/pic-gic.cpp create mode 100644 kernel/fiasco/src/kern/arm/space-arm.cpp create mode 100644 kernel/fiasco/src/kern/arm/spin_lock-arm.cpp create mode 100644 kernel/fiasco/src/kern/arm/startup-arm.cpp create mode 100644 kernel/fiasco/src/kern/arm/sys_call_page-arm.cpp create mode 100644 kernel/fiasco/src/kern/arm/task-arm.cpp create mode 100644 kernel/fiasco/src/kern/arm/tb_entry-arm.cpp create mode 100644 kernel/fiasco/src/kern/arm/thread-arm.cpp create mode 100644 kernel/fiasco/src/kern/arm/thread-entry.cpp create mode 100644 kernel/fiasco/src/kern/arm/thread-jdb.cpp create mode 100644 kernel/fiasco/src/kern/arm/timer-arm-mptimer.cpp create mode 100644 kernel/fiasco/src/kern/arm/timer-arm.cpp create mode 100644 kernel/fiasco/src/kern/arm/timer_tick-arm.cpp create mode 100644 kernel/fiasco/src/kern/arm/tramp-mp.S create mode 100644 kernel/fiasco/src/kern/arm/trap_state.cpp create mode 100644 kernel/fiasco/src/kern/arm/utcb_init-arm.cpp create mode 100644 kernel/fiasco/src/kern/arm/utcb_support-arm.cpp create mode 100644 kernel/fiasco/src/kern/arm/vm.cpp create mode 100644 kernel/fiasco/src/kern/arm/vmem_alloc-arch.cpp create mode 100644 kernel/fiasco/src/kern/auto_quota.h create mode 100644 kernel/fiasco/src/kern/banner.cpp create mode 100644 kernel/fiasco/src/kern/boot_alloc.cpp create mode 100644 kernel/fiasco/src/kern/boot_info.cpp create mode 100644 kernel/fiasco/src/kern/buddy_alloc.cpp create mode 100644 kernel/fiasco/src/kern/bug.h create mode 100644 kernel/fiasco/src/kern/cascade_irq.cpp create mode 100644 kernel/fiasco/src/kern/checksum.cpp create mode 100644 kernel/fiasco/src/kern/clock-generic.cpp create mode 100644 kernel/fiasco/src/kern/clock.cpp create mode 100644 kernel/fiasco/src/kern/config.cpp create mode 100644 kernel/fiasco/src/kern/config_gdt.h create mode 100644 kernel/fiasco/src/kern/config_tcbsize.h create mode 100644 kernel/fiasco/src/kern/context-vcpu.cpp create mode 100644 kernel/fiasco/src/kern/context.cpp create mode 100644 kernel/fiasco/src/kern/context_base.cpp create mode 100644 kernel/fiasco/src/kern/cpu.cpp create mode 100644 kernel/fiasco/src/kern/cpu_lock-generic.cpp create mode 100644 kernel/fiasco/src/kern/cpu_lock.cpp create mode 100644 kernel/fiasco/src/kern/cpu_mask.cpp create mode 100644 kernel/fiasco/src/kern/dbg_page_info.cpp create mode 100644 kernel/fiasco/src/kern/dump_tcboffsets.cc create mode 100644 kernel/fiasco/src/kern/entry_frame-abs-timeout-hack.cpp create mode 100644 kernel/fiasco/src/kern/entry_frame.cpp create mode 100644 kernel/fiasco/src/kern/factory.cpp create mode 100644 kernel/fiasco/src/kern/feature.h create mode 100644 kernel/fiasco/src/kern/fpu.cpp create mode 100644 kernel/fiasco/src/kern/fpu_alloc.cpp create mode 100644 kernel/fiasco/src/kern/fpu_state.cpp create mode 100644 kernel/fiasco/src/kern/genchecksum.cc create mode 100644 kernel/fiasco/src/kern/genlines.c create mode 100644 kernel/fiasco/src/kern/globals.cpp create mode 100644 kernel/fiasco/src/kern/helping_lock.cpp create mode 100644 kernel/fiasco/src/kern/hpet.cpp create mode 100644 kernel/fiasco/src/kern/ia32/32/config-ia32-32.cpp create mode 100644 kernel/fiasco/src/kern/ia32/32/context-ia32-32.cpp create mode 100644 kernel/fiasco/src/kern/ia32/32/continuation-ia32-32-ux.cpp create mode 100644 kernel/fiasco/src/kern/ia32/32/continuation-ia32-32.cpp create mode 100644 kernel/fiasco/src/kern/ia32/32/cpu-32.cpp create mode 100644 kernel/fiasco/src/kern/ia32/32/crt0.S create mode 100644 kernel/fiasco/src/kern/ia32/32/entry-native.S create mode 100644 kernel/fiasco/src/kern/ia32/32/entry-ux.S create mode 100644 kernel/fiasco/src/kern/ia32/32/entry.S create mode 100644 kernel/fiasco/src/kern/ia32/32/entry_frame-ia32-ux.cpp create mode 100644 kernel/fiasco/src/kern/ia32/32/kmem-ia32-32.cpp create mode 100644 kernel/fiasco/src/kern/ia32/32/linking.h create mode 100644 kernel/fiasco/src/kern/ia32/32/low_level.h create mode 100644 kernel/fiasco/src/kern/ia32/32/main-ia32-32.cpp create mode 100644 kernel/fiasco/src/kern/ia32/32/mapping-ia32-32.cpp create mode 100644 kernel/fiasco/src/kern/ia32/32/mem_layout-ia32-32.cpp create mode 100644 kernel/fiasco/src/kern/ia32/32/mem_unit-ia32.cpp create mode 100644 kernel/fiasco/src/kern/ia32/32/paging-ia32-32.cpp create mode 100644 kernel/fiasco/src/kern/ia32/32/sys_call_page-abs-ia32.cpp create mode 100644 kernel/fiasco/src/kern/ia32/32/sys_call_page-asm.S create mode 100644 kernel/fiasco/src/kern/ia32/32/tb_entry-ia32-32.cpp create mode 100644 kernel/fiasco/src/kern/ia32/32/thread-dbf.cpp create mode 100644 kernel/fiasco/src/kern/ia32/32/thread-ia32-32.cpp create mode 100644 kernel/fiasco/src/kern/ia32/32/trap_state.cpp create mode 100644 kernel/fiasco/src/kern/ia32/32/tss.cpp create mode 100644 kernel/fiasco/src/kern/ia32/32/vm_svm_asm.S create mode 100644 kernel/fiasco/src/kern/ia32/32/vm_vmx_asm.S create mode 100644 kernel/fiasco/src/kern/ia32/64/config-ia32-64.cpp create mode 100644 kernel/fiasco/src/kern/ia32/64/context-ia32-64.cpp create mode 100644 kernel/fiasco/src/kern/ia32/64/continuation-ia32-64.cpp create mode 100644 kernel/fiasco/src/kern/ia32/64/cpu-64.cpp create mode 100644 kernel/fiasco/src/kern/ia32/64/crt0.S create mode 100644 kernel/fiasco/src/kern/ia32/64/entry-native.S create mode 100644 kernel/fiasco/src/kern/ia32/64/entry.S create mode 100644 kernel/fiasco/src/kern/ia32/64/entry_frame-amd64.cpp create mode 100644 kernel/fiasco/src/kern/ia32/64/kmem-ia32-64.cpp create mode 100644 kernel/fiasco/src/kern/ia32/64/linking.h create mode 100644 kernel/fiasco/src/kern/ia32/64/low_level.h create mode 100644 kernel/fiasco/src/kern/ia32/64/main-ia32-64.cpp create mode 100644 kernel/fiasco/src/kern/ia32/64/mapping-ia32-64.cpp create mode 100644 kernel/fiasco/src/kern/ia32/64/mem_layout-ia32-64.cpp create mode 100644 kernel/fiasco/src/kern/ia32/64/mem_unit-amd64.cpp create mode 100644 kernel/fiasco/src/kern/ia32/64/paging-ia32-64.cpp create mode 100644 kernel/fiasco/src/kern/ia32/64/shortcut.S create mode 100644 kernel/fiasco/src/kern/ia32/64/tb_entry-ia32-64.cpp create mode 100644 kernel/fiasco/src/kern/ia32/64/thread-dbf.cpp create mode 100644 kernel/fiasco/src/kern/ia32/64/thread-ia32-64.cpp create mode 100644 kernel/fiasco/src/kern/ia32/64/trap_state-amd64.cpp create mode 100644 kernel/fiasco/src/kern/ia32/64/tss-amd64.cpp create mode 100644 kernel/fiasco/src/kern/ia32/64/vm_svm_asm.S create mode 100644 kernel/fiasco/src/kern/ia32/64/vm_vmx_asm.S create mode 100644 kernel/fiasco/src/kern/ia32/Makerules.KERNEL create mode 100644 kernel/fiasco/src/kern/ia32/Makerules.SYMBOLS.ia32 create mode 100644 kernel/fiasco/src/kern/ia32/__main.cpp create mode 100644 kernel/fiasco/src/kern/ia32/apic-debug.cpp create mode 100644 kernel/fiasco/src/kern/ia32/apic-ia32-mp.cpp create mode 100644 kernel/fiasco/src/kern/ia32/apic-ia32.cpp create mode 100644 kernel/fiasco/src/kern/ia32/asm.h create mode 100644 kernel/fiasco/src/kern/ia32/boot_console-ia32-amd64.cpp create mode 100644 kernel/fiasco/src/kern/ia32/boot_info-ia32.cpp create mode 100644 kernel/fiasco/src/kern/ia32/clock-ia32.cpp create mode 100644 kernel/fiasco/src/kern/ia32/config-ia32.cpp create mode 100644 kernel/fiasco/src/kern/ia32/context-ia32.cpp create mode 100644 kernel/fiasco/src/kern/ia32/cpu-ia32.cpp create mode 100644 kernel/fiasco/src/kern/ia32/dirq-ia32-ux.cpp create mode 100644 kernel/fiasco/src/kern/ia32/entry-mp.S create mode 100644 kernel/fiasco/src/kern/ia32/fpu-ia32-ux.cpp create mode 100644 kernel/fiasco/src/kern/ia32/fpu-ia32.cpp create mode 100644 kernel/fiasco/src/kern/ia32/gdt.cpp create mode 100644 kernel/fiasco/src/kern/ia32/idt.cpp create mode 100644 kernel/fiasco/src/kern/ia32/idt_init.h create mode 100644 kernel/fiasco/src/kern/ia32/io_apic.cpp create mode 100644 kernel/fiasco/src/kern/ia32/ipi-ia32.cpp create mode 100644 kernel/fiasco/src/kern/ia32/irq_chip_ia32.cpp create mode 100644 kernel/fiasco/src/kern/ia32/irq_chip_pic.cpp create mode 100644 kernel/fiasco/src/kern/ia32/irq_msi.cpp create mode 100644 kernel/fiasco/src/kern/ia32/kdb_ke-ia32.cpp create mode 100644 kernel/fiasco/src/kern/ia32/kernel_thread-ia32.cpp create mode 100644 kernel/fiasco/src/kern/ia32/kip_init-ia32.cpp create mode 100644 kernel/fiasco/src/kern/ia32/kmem-ia32.cpp create mode 100644 kernel/fiasco/src/kern/ia32/kmem_alloc-ia32.cpp create mode 100644 kernel/fiasco/src/kern/ia32/loadcnt.cpp create mode 100644 kernel/fiasco/src/kern/ia32/logdefs.h create mode 100644 kernel/fiasco/src/kern/ia32/main-ia32.cpp create mode 100644 kernel/fiasco/src/kern/ia32/map_util-io.cpp create mode 100644 kernel/fiasco/src/kern/ia32/mem_layout-ia32.cpp create mode 100644 kernel/fiasco/src/kern/ia32/mem_space-ia32.cpp create mode 100644 kernel/fiasco/src/kern/ia32/no_kdb_ke.cpp create mode 100644 kernel/fiasco/src/kern/ia32/paging-ia32.cpp create mode 100644 kernel/fiasco/src/kern/ia32/perf_cnt-ia32.cpp create mode 100644 kernel/fiasco/src/kern/ia32/rtc-ia32.cpp create mode 100644 kernel/fiasco/src/kern/ia32/shortcut.h create mode 100644 kernel/fiasco/src/kern/ia32/space-ia32.cpp create mode 100644 kernel/fiasco/src/kern/ia32/spin_lock-ia32.cpp create mode 100644 kernel/fiasco/src/kern/ia32/startup-ia32.cpp create mode 100644 kernel/fiasco/src/kern/ia32/svm.cpp create mode 100644 kernel/fiasco/src/kern/ia32/task-ia32-amd64.cpp create mode 100644 kernel/fiasco/src/kern/ia32/thread-ia32.cpp create mode 100644 kernel/fiasco/src/kern/ia32/thread-io.cpp create mode 100644 kernel/fiasco/src/kern/ia32/timer-apic.cpp create mode 100644 kernel/fiasco/src/kern/ia32/timer-ia32-amd64-ux.cpp create mode 100644 kernel/fiasco/src/kern/ia32/timer-pit.cpp create mode 100644 kernel/fiasco/src/kern/ia32/timer-rtc.cpp create mode 100644 kernel/fiasco/src/kern/ia32/timer_irq.cpp create mode 100644 kernel/fiasco/src/kern/ia32/timer_tick-apic.cpp create mode 100644 kernel/fiasco/src/kern/ia32/timer_tick-ia32.cpp create mode 100644 kernel/fiasco/src/kern/ia32/tramp-mp.S create mode 100644 kernel/fiasco/src/kern/ia32/utcb_init-ia32.cpp create mode 100644 kernel/fiasco/src/kern/ia32/vm.cpp create mode 100644 kernel/fiasco/src/kern/ia32/vm_factory-ia32.cpp create mode 100644 kernel/fiasco/src/kern/ia32/vm_svm.cpp create mode 100644 kernel/fiasco/src/kern/ia32/vm_vmx.cpp create mode 100644 kernel/fiasco/src/kern/ia32/vmem_alloc-ia32.cpp create mode 100644 kernel/fiasco/src/kern/ia32/vmx.cpp create mode 100644 kernel/fiasco/src/kern/ia32/watchdog-ia32.cpp create mode 100644 kernel/fiasco/src/kern/ia32/x86desc.cpp create mode 100644 kernel/fiasco/src/kern/icu_helper.cpp create mode 100644 kernel/fiasco/src/kern/initcalls.h create mode 100644 kernel/fiasco/src/kern/io_space.cpp create mode 100644 kernel/fiasco/src/kern/ipc_gate.cpp create mode 100644 kernel/fiasco/src/kern/ipc_sender.cpp create mode 100644 kernel/fiasco/src/kern/ipc_timeout.cpp create mode 100644 kernel/fiasco/src/kern/ipi.cpp create mode 100644 kernel/fiasco/src/kern/irq.cpp create mode 100644 kernel/fiasco/src/kern/irq_chip.cpp create mode 100644 kernel/fiasco/src/kern/irq_chip_generic.cpp create mode 100644 kernel/fiasco/src/kern/irq_controller.cpp create mode 100644 kernel/fiasco/src/kern/irq_mgr.cpp create mode 100644 kernel/fiasco/src/kern/irq_mgr_multi_chip.cpp create mode 100644 kernel/fiasco/src/kern/kdb_ke.cpp create mode 100644 kernel/fiasco/src/kern/kern_cnt.cpp create mode 100644 kernel/fiasco/src/kern/kernel_console.cpp create mode 100644 kernel/fiasco/src/kern/kernel_panic.cc create mode 100644 kernel/fiasco/src/kern/kernel_task.cpp create mode 100644 kernel/fiasco/src/kern/kernel_thread-std.cpp create mode 100644 kernel/fiasco/src/kern/kernel_thread.cpp create mode 100644 kernel/fiasco/src/kern/kernel_uart-16550.cpp create mode 100644 kernel/fiasco/src/kern/kernel_uart.cpp create mode 100644 kernel/fiasco/src/kern/kmem_alloc.cpp create mode 100644 kernel/fiasco/src/kern/kmem_slab.cpp create mode 100644 kernel/fiasco/src/kern/kobject.cpp create mode 100644 kernel/fiasco/src/kern/kobject_dbg.cpp create mode 100644 kernel/fiasco/src/kern/kobject_helper.cpp create mode 100644 kernel/fiasco/src/kern/kobject_iface.cpp create mode 100644 kernel/fiasco/src/kern/kobject_mapdb.cpp create mode 100644 kernel/fiasco/src/kern/koptions-def.h create mode 100644 kernel/fiasco/src/kern/koptions.cpp create mode 100644 kernel/fiasco/src/kern/l4_buf_iter.cpp create mode 100644 kernel/fiasco/src/kern/libc_backend_lock.cc create mode 100644 kernel/fiasco/src/kern/lock.cpp create mode 100644 kernel/fiasco/src/kern/map_util-mem.cpp create mode 100644 kernel/fiasco/src/kern/map_util-objs.cpp create mode 100644 kernel/fiasco/src/kern/map_util.cpp create mode 100644 kernel/fiasco/src/kern/mapdb.cpp create mode 100644 kernel/fiasco/src/kern/mappable.cpp create mode 100644 kernel/fiasco/src/kern/mapping.cpp create mode 100644 kernel/fiasco/src/kern/mapping_tree.cpp create mode 100644 kernel/fiasco/src/kern/mem_layout.cpp create mode 100644 kernel/fiasco/src/kern/mem_space-user.cpp create mode 100644 kernel/fiasco/src/kern/mem_space.cpp create mode 100644 kernel/fiasco/src/kern/member_offs.h create mode 100644 kernel/fiasco/src/kern/mp_lock.cpp create mode 100644 kernel/fiasco/src/kern/obj_helping_lock.cpp create mode 100644 kernel/fiasco/src/kern/obj_ref_ptr.cpp create mode 100644 kernel/fiasco/src/kern/obj_space-phys.cpp create mode 100644 kernel/fiasco/src/kern/obj_space-virt.cpp create mode 100644 kernel/fiasco/src/kern/obj_space.cpp create mode 100644 kernel/fiasco/src/kern/paging.cpp create mode 100644 kernel/fiasco/src/kern/per_cpu_data.cpp create mode 100644 kernel/fiasco/src/kern/per_cpu_data_alloc.cpp create mode 100644 kernel/fiasco/src/kern/perf_cnt.cpp create mode 100644 kernel/fiasco/src/kern/pic-i8259.cpp create mode 100644 kernel/fiasco/src/kern/pic.cpp create mode 100644 kernel/fiasco/src/kern/pit-i8254.cpp create mode 100644 kernel/fiasco/src/kern/ppc32/Makerules.KERNEL create mode 100644 kernel/fiasco/src/kern/ppc32/boot_info-ppc32.cpp create mode 100644 kernel/fiasco/src/kern/ppc32/boot_uart_init.cpp create mode 100644 kernel/fiasco/src/kern/ppc32/bootstrap.cpp create mode 100644 kernel/fiasco/src/kern/ppc32/bsp/mpc52xx/Kconfig create mode 100644 kernel/fiasco/src/kern/ppc32/bsp/mpc52xx/Modules create mode 100644 kernel/fiasco/src/kern/ppc32/bsp/mpc52xx/boot_info-mpc52xx.cpp create mode 100644 kernel/fiasco/src/kern/ppc32/bsp/mpc52xx/config-ppc32-mpc52xx.cpp create mode 100644 kernel/fiasco/src/kern/ppc32/bsp/mpc52xx/pic-mpc52xx.cpp create mode 100644 kernel/fiasco/src/kern/ppc32/bsp/qemu/Kconfig create mode 100644 kernel/fiasco/src/kern/ppc32/bsp/qemu/Modules create mode 100644 kernel/fiasco/src/kern/ppc32/bsp/qemu/boot_info-ppc32-qemu.cpp create mode 100644 kernel/fiasco/src/kern/ppc32/bsp/qemu/config-ppc32-qemu.cpp create mode 100644 kernel/fiasco/src/kern/ppc32/bsp/qemu/pic-ppc32-qemu.cpp create mode 100644 kernel/fiasco/src/kern/ppc32/config-ppc32.cpp create mode 100644 kernel/fiasco/src/kern/ppc32/context-ppc32.cpp create mode 100644 kernel/fiasco/src/kern/ppc32/continuation-ppc32.cpp create mode 100644 kernel/fiasco/src/kern/ppc32/cpu-ppc32.cpp create mode 100644 kernel/fiasco/src/kern/ppc32/crt0.S create mode 100644 kernel/fiasco/src/kern/ppc32/decrementer.cpp create mode 100644 kernel/fiasco/src/kern/ppc32/dirq-ppc32.cpp create mode 100644 kernel/fiasco/src/kern/ppc32/entry_frame-ppc32.cpp create mode 100644 kernel/fiasco/src/kern/ppc32/exception.S create mode 100644 kernel/fiasco/src/kern/ppc32/kdb_ke-ppc32.cpp create mode 100644 kernel/fiasco/src/kern/ppc32/kernel_task-ppc32.cpp create mode 100644 kernel/fiasco/src/kern/ppc32/kernel_thread-ppc32.cpp create mode 100644 kernel/fiasco/src/kern/ppc32/kip_init.cpp create mode 100644 kernel/fiasco/src/kern/ppc32/kmem.cpp create mode 100644 kernel/fiasco/src/kern/ppc32/kmem_alloc-ppc32.cpp create mode 100644 kernel/fiasco/src/kern/ppc32/main.cpp create mode 100644 kernel/fiasco/src/kern/ppc32/mapping-ppc32.cpp create mode 100644 kernel/fiasco/src/kern/ppc32/mem_layout-ppc32.cpp create mode 100644 kernel/fiasco/src/kern/ppc32/mem_space-cache.cpp create mode 100644 kernel/fiasco/src/kern/ppc32/mem_space-htab.cpp create mode 100644 kernel/fiasco/src/kern/ppc32/mem_space-ppc32.cpp create mode 100644 kernel/fiasco/src/kern/ppc32/mem_unit-ppc32.cpp create mode 100644 kernel/fiasco/src/kern/ppc32/msr.cpp create mode 100644 kernel/fiasco/src/kern/ppc32/paging-ppc32.cpp create mode 100644 kernel/fiasco/src/kern/ppc32/phys_mem.S create mode 100644 kernel/fiasco/src/kern/ppc32/space-ppc32.cpp create mode 100644 kernel/fiasco/src/kern/ppc32/startup-ppc32.cpp create mode 100644 kernel/fiasco/src/kern/ppc32/sys_call_page-ppc32.cpp create mode 100644 kernel/fiasco/src/kern/ppc32/task-ppc32.cpp create mode 100644 kernel/fiasco/src/kern/ppc32/tb_entry-ppc32.cpp create mode 100644 kernel/fiasco/src/kern/ppc32/thread-jdb.cpp create mode 100644 kernel/fiasco/src/kern/ppc32/thread-ppc32.cpp create mode 100644 kernel/fiasco/src/kern/ppc32/timer-decr-ppc32.cpp create mode 100644 kernel/fiasco/src/kern/ppc32/timer_tick-ppc32.cpp create mode 100644 kernel/fiasco/src/kern/ppc32/trap_state.cpp create mode 100644 kernel/fiasco/src/kern/ppc32/utcb_init-ppc32.cpp create mode 100644 kernel/fiasco/src/kern/ppc32/utcb_support-ppc32.cpp create mode 100644 kernel/fiasco/src/kern/ppc32/util.cpp create mode 100644 kernel/fiasco/src/kern/ppc32/vmem_alloc-ppc32.cpp create mode 100644 kernel/fiasco/src/kern/ppc32/warn-ppc32.cpp create mode 100644 kernel/fiasco/src/kern/prio_list.cpp create mode 100644 kernel/fiasco/src/kern/ptab_base.cpp create mode 100644 kernel/fiasco/src/kern/push_console.cpp create mode 100644 kernel/fiasco/src/kern/queue.cpp create mode 100644 kernel/fiasco/src/kern/queue_item.cpp create mode 100644 kernel/fiasco/src/kern/ram_quota.cpp create mode 100644 kernel/fiasco/src/kern/rcupdate.cpp create mode 100644 kernel/fiasco/src/kern/ready_queue_fp.cpp create mode 100644 kernel/fiasco/src/kern/ready_queue_wfq.cpp create mode 100644 kernel/fiasco/src/kern/receiver.cpp create mode 100644 kernel/fiasco/src/kern/ref_obj.cpp create mode 100644 kernel/fiasco/src/kern/ref_ptr.cpp create mode 100644 kernel/fiasco/src/kern/regdefs.h create mode 100644 kernel/fiasco/src/kern/reset-dummy.cpp create mode 100644 kernel/fiasco/src/kern/sched_context-fixed_prio.cpp create mode 100644 kernel/fiasco/src/kern/sched_context-fp_wfq.cpp create mode 100644 kernel/fiasco/src/kern/sched_context-wfq.cpp create mode 100644 kernel/fiasco/src/kern/sched_context.cpp create mode 100644 kernel/fiasco/src/kern/scheduler.cpp create mode 100644 kernel/fiasco/src/kern/sender.cpp create mode 100644 kernel/fiasco/src/kern/setchecksum.c create mode 100644 kernel/fiasco/src/kern/sigma0_task-io.cpp create mode 100644 kernel/fiasco/src/kern/sigma0_task.cpp create mode 100644 kernel/fiasco/src/kern/space-io.cpp create mode 100644 kernel/fiasco/src/kern/space.cpp create mode 100644 kernel/fiasco/src/kern/sparc/Makerules.KERNEL create mode 100644 kernel/fiasco/src/kern/sparc/boot_info-sparc.cpp create mode 100644 kernel/fiasco/src/kern/sparc/boot_uart_init.cpp create mode 100644 kernel/fiasco/src/kern/sparc/bootstrap.cpp create mode 100644 kernel/fiasco/src/kern/sparc/bsp/leon3/Kconfig create mode 100644 kernel/fiasco/src/kern/sparc/bsp/leon3/Modules create mode 100644 kernel/fiasco/src/kern/sparc/bsp/leon3/boot_info-sparc-leon3.cpp create mode 100644 kernel/fiasco/src/kern/sparc/bsp/leon3/config-sparc-leon3.cpp create mode 100644 kernel/fiasco/src/kern/sparc/bsp/leon3/pic-sparc-leon3.cpp create mode 100644 kernel/fiasco/src/kern/sparc/config-sparc.cpp create mode 100644 kernel/fiasco/src/kern/sparc/context-sparc.cpp create mode 100644 kernel/fiasco/src/kern/sparc/continuation-sparc.cpp create mode 100644 kernel/fiasco/src/kern/sparc/cpu-sparc.cpp create mode 100644 kernel/fiasco/src/kern/sparc/crt0.S create mode 100644 kernel/fiasco/src/kern/sparc/decrementer.cpp create mode 100644 kernel/fiasco/src/kern/sparc/dirq-sparc.cpp create mode 100644 kernel/fiasco/src/kern/sparc/entry_frame-sparc.cpp create mode 100644 kernel/fiasco/src/kern/sparc/exceptions.S create mode 100644 kernel/fiasco/src/kern/sparc/kdb_ke-sparc.cpp create mode 100644 kernel/fiasco/src/kern/sparc/kernel_task-sparc.cpp create mode 100644 kernel/fiasco/src/kern/sparc/kernel_thread-sparc.cpp create mode 100644 kernel/fiasco/src/kern/sparc/kip_init.cpp create mode 100644 kernel/fiasco/src/kern/sparc/kmem.cpp create mode 100644 kernel/fiasco/src/kern/sparc/kmem_alloc-sparc.cpp create mode 100644 kernel/fiasco/src/kern/sparc/main.cpp create mode 100644 kernel/fiasco/src/kern/sparc/mapping-sparc.cpp create mode 100644 kernel/fiasco/src/kern/sparc/mem_layout-sparc.cpp create mode 100644 kernel/fiasco/src/kern/sparc/mem_space-sparc.cpp create mode 100644 kernel/fiasco/src/kern/sparc/mem_unit-sparc.cpp create mode 100644 kernel/fiasco/src/kern/sparc/paging-sparc.cpp create mode 100644 kernel/fiasco/src/kern/sparc/psr.cpp create mode 100644 kernel/fiasco/src/kern/sparc/space-sparc.cpp create mode 100644 kernel/fiasco/src/kern/sparc/startup-sparc.cpp create mode 100644 kernel/fiasco/src/kern/sparc/sys_call_page-sparc.cpp create mode 100644 kernel/fiasco/src/kern/sparc/task-sparc.cpp create mode 100644 kernel/fiasco/src/kern/sparc/tb_entry-sparc.cpp create mode 100644 kernel/fiasco/src/kern/sparc/thread-jdb.cpp create mode 100644 kernel/fiasco/src/kern/sparc/thread-sparc.cpp create mode 100644 kernel/fiasco/src/kern/sparc/timer-decr-sparc.cpp create mode 100644 kernel/fiasco/src/kern/sparc/timer_tick-sparc.cpp create mode 100644 kernel/fiasco/src/kern/sparc/trap_state.cpp create mode 100644 kernel/fiasco/src/kern/sparc/uart-asi.cpp create mode 100644 kernel/fiasco/src/kern/sparc/utcb_init-sparc.cpp create mode 100644 kernel/fiasco/src/kern/sparc/utcb_support-sparc.cpp create mode 100644 kernel/fiasco/src/kern/sparc/util.cpp create mode 100644 kernel/fiasco/src/kern/sparc/vmem_alloc-sparc.cpp create mode 100644 kernel/fiasco/src/kern/sparc/warn-sparc.cpp create mode 100644 kernel/fiasco/src/kern/spin_lock.cpp create mode 100644 kernel/fiasco/src/kern/startup.cpp create mode 100644 kernel/fiasco/src/kern/static_assert.h create mode 100644 kernel/fiasco/src/kern/static_init.h create mode 100644 kernel/fiasco/src/kern/switch_lock.cpp create mode 100644 kernel/fiasco/src/kern/sys_call_page.cpp create mode 100644 kernel/fiasco/src/kern/syscalls-log.cpp create mode 100644 kernel/fiasco/src/kern/syscalls.cpp create mode 100644 kernel/fiasco/src/kern/task.cpp create mode 100644 kernel/fiasco/src/kern/tb_entry.cpp create mode 100644 kernel/fiasco/src/kern/tb_entry_output.cpp create mode 100644 kernel/fiasco/src/kern/tcboffset.cc create mode 100644 kernel/fiasco/src/kern/tcboffset_in.h create mode 100644 kernel/fiasco/src/kern/terminate.cpp create mode 100644 kernel/fiasco/src/kern/thread-debug.cpp create mode 100644 kernel/fiasco/src/kern/thread-ipc.cpp create mode 100644 kernel/fiasco/src/kern/thread-log.cpp create mode 100644 kernel/fiasco/src/kern/thread-pagefault.cpp create mode 100644 kernel/fiasco/src/kern/thread-vcpu.cpp create mode 100644 kernel/fiasco/src/kern/thread.cpp create mode 100644 kernel/fiasco/src/kern/thread_lock.cpp create mode 100644 kernel/fiasco/src/kern/thread_object.cpp create mode 100644 kernel/fiasco/src/kern/thread_state.cpp create mode 100644 kernel/fiasco/src/kern/timeout.cpp create mode 100644 kernel/fiasco/src/kern/timer-hpet.cpp create mode 100644 kernel/fiasco/src/kern/timer.cpp create mode 100644 kernel/fiasco/src/kern/timer_tick-single-vector.cpp create mode 100644 kernel/fiasco/src/kern/timer_tick.cpp create mode 100644 kernel/fiasco/src/kern/timeslice_timeout.cpp create mode 100644 kernel/fiasco/src/kern/uart-mmio.cpp create mode 100644 kernel/fiasco/src/kern/uart_console.cpp create mode 100644 kernel/fiasco/src/kern/utcb_init.cpp create mode 100644 kernel/fiasco/src/kern/utcb_support.cpp create mode 100644 kernel/fiasco/src/kern/ux/Makerules.KERNEL create mode 100644 kernel/fiasco/src/kern/ux/Makerules.SYMBOLS.ux create mode 100644 kernel/fiasco/src/kern/ux/boot_info-ux.cpp create mode 100644 kernel/fiasco/src/kern/ux/config-ux.cpp create mode 100644 kernel/fiasco/src/kern/ux/context-ux.cpp create mode 100644 kernel/fiasco/src/kern/ux/cpu-ux.cpp create mode 100644 kernel/fiasco/src/kern/ux/emulation.cpp create mode 100644 kernel/fiasco/src/kern/ux/fb.cpp create mode 100644 kernel/fiasco/src/kern/ux/format.h create mode 100644 kernel/fiasco/src/kern/ux/fpu-ux.cpp create mode 100644 kernel/fiasco/src/kern/ux/glibc_getchar.cpp create mode 100644 kernel/fiasco/src/kern/ux/glue_libc_ux.cc create mode 100644 kernel/fiasco/src/kern/ux/hostproc.cpp create mode 100644 kernel/fiasco/src/kern/ux/ipi-ux.cpp create mode 100644 kernel/fiasco/src/kern/ux/irq-ux.cpp create mode 100644 kernel/fiasco/src/kern/ux/irq0.c create mode 100644 kernel/fiasco/src/kern/ux/kernel_thread-ux.cpp create mode 100644 kernel/fiasco/src/kern/ux/kip_init-ux.cpp create mode 100644 kernel/fiasco/src/kern/ux/kmem-ux.cpp create mode 100644 kernel/fiasco/src/kern/ux/libc_backend_nolock.cc create mode 100644 kernel/fiasco/src/kern/ux/libc_support.cpp create mode 100644 kernel/fiasco/src/kern/ux/loader.cpp create mode 100644 kernel/fiasco/src/kern/ux/low_level.h create mode 100644 kernel/fiasco/src/kern/ux/main-ux.cpp create mode 100644 kernel/fiasco/src/kern/ux/mem_layout-ux.cpp create mode 100644 kernel/fiasco/src/kern/ux/mem_space-ux.cpp create mode 100644 kernel/fiasco/src/kern/ux/mem_unit-ux.cpp create mode 100644 kernel/fiasco/src/kern/ux/multiboot.h create mode 100644 kernel/fiasco/src/kern/ux/net.cpp create mode 100644 kernel/fiasco/src/kern/ux/panic.cpp create mode 100644 kernel/fiasco/src/kern/ux/pic-ux.cpp create mode 100644 kernel/fiasco/src/kern/ux/sighandler.S create mode 100644 kernel/fiasco/src/kern/ux/simpleio.cpp create mode 100644 kernel/fiasco/src/kern/ux/space-ux.cpp create mode 100644 kernel/fiasco/src/kern/ux/startup.cpp create mode 100644 kernel/fiasco/src/kern/ux/sys_call_page-abs-ux.cpp create mode 100644 kernel/fiasco/src/kern/ux/task-ux.cpp create mode 100644 kernel/fiasco/src/kern/ux/terminate-ux.cpp create mode 100644 kernel/fiasco/src/kern/ux/thread-ux.cpp create mode 100644 kernel/fiasco/src/kern/ux/timer-ux.cpp create mode 100644 kernel/fiasco/src/kern/ux/trampoline.cpp create mode 100644 kernel/fiasco/src/kern/ux/undef_page.h create mode 100644 kernel/fiasco/src/kern/ux/usermode.cpp create mode 100644 kernel/fiasco/src/kern/ux/utcb_init-ux.cpp create mode 100644 kernel/fiasco/src/kern/ux/vhw.cpp create mode 100644 kernel/fiasco/src/kern/ux/vmem_alloc-ux.cpp create mode 100644 kernel/fiasco/src/kern/vcpu.cpp create mode 100644 kernel/fiasco/src/kern/vkey.cpp create mode 100644 kernel/fiasco/src/kern/vlog.cpp create mode 100644 kernel/fiasco/src/kern/vm_factory.cpp create mode 100644 kernel/fiasco/src/kern/vmem_alloc.cpp create mode 100644 kernel/fiasco/src/kern/warn.cpp create mode 100644 kernel/fiasco/src/kern/watchdog.cpp create mode 100644 kernel/fiasco/src/kernel.amd64.ld create mode 100644 kernel/fiasco/src/kernel.arm.ld create mode 100644 kernel/fiasco/src/kernel.ia32.ld create mode 100644 kernel/fiasco/src/kernel.ppc32.ld create mode 100644 kernel/fiasco/src/kernel.sparc.ld create mode 100644 kernel/fiasco/src/kernel.ux.ld create mode 100644 kernel/fiasco/src/lib/cxxlib/paranoia.cpp create mode 100644 kernel/fiasco/src/lib/cxxlib/s_cruft.cpp create mode 100644 kernel/fiasco/src/lib/disasm/COPYING create mode 100644 kernel/fiasco/src/lib/disasm/bfd/bfd.h create mode 100644 kernel/fiasco/src/lib/disasm/bfd/elf-bfd.h create mode 100644 kernel/fiasco/src/lib/disasm/bfd/libbfd.c create mode 100644 kernel/fiasco/src/lib/disasm/bfd/libbfd.h create mode 100644 kernel/fiasco/src/lib/disasm/disasm.cc create mode 100644 kernel/fiasco/src/lib/disasm/disasm.h create mode 100644 kernel/fiasco/src/lib/disasm/elf/arm.h create mode 100644 kernel/fiasco/src/lib/disasm/elf/common.h create mode 100644 kernel/fiasco/src/lib/disasm/elf/external.h create mode 100644 kernel/fiasco/src/lib/disasm/elf/i386.h create mode 100644 kernel/fiasco/src/lib/disasm/elf/internal.h create mode 100644 kernel/fiasco/src/lib/disasm/elf/reloc-macros.h create mode 100644 kernel/fiasco/src/lib/disasm/elf/x86-64.h create mode 100644 kernel/fiasco/src/lib/disasm/include/ansidecl.h create mode 100644 kernel/fiasco/src/lib/disasm/include/bfdlink.h create mode 100644 kernel/fiasco/src/lib/disasm/include/dis-asm.h create mode 100644 kernel/fiasco/src/lib/disasm/include/floatformat.h create mode 100644 kernel/fiasco/src/lib/disasm/include/opcode/arm.h create mode 100644 kernel/fiasco/src/lib/disasm/include/opcode/ppc.h create mode 100644 kernel/fiasco/src/lib/disasm/include/opcode/sparc.h create mode 100644 kernel/fiasco/src/lib/disasm/include/safe-ctype.h create mode 100644 kernel/fiasco/src/lib/disasm/include/symcat.h create mode 100644 kernel/fiasco/src/lib/disasm/libiberty/safe-ctype.c create mode 100644 kernel/fiasco/src/lib/disasm/opcodes/arm-dis.c create mode 100644 kernel/fiasco/src/lib/disasm/opcodes/dis-buf.c create mode 100644 kernel/fiasco/src/lib/disasm/opcodes/dis-init.c create mode 100644 kernel/fiasco/src/lib/disasm/opcodes/i386-dis.c create mode 100644 kernel/fiasco/src/lib/disasm/opcodes/opintl.h create mode 100644 kernel/fiasco/src/lib/disasm/opcodes/ppc-dis.c create mode 100644 kernel/fiasco/src/lib/disasm/opcodes/ppc-opc.c create mode 100644 kernel/fiasco/src/lib/disasm/opcodes/sparc-dis.c create mode 100644 kernel/fiasco/src/lib/disasm/opcodes/sparc-opc.c create mode 100644 kernel/fiasco/src/lib/disasm/opcodes/sysdep.h create mode 100644 kernel/fiasco/src/lib/gzip/COPYING create mode 100644 kernel/fiasco/src/lib/gzip/adler32.c create mode 100644 kernel/fiasco/src/lib/gzip/crc32.c create mode 100644 kernel/fiasco/src/lib/gzip/deflate.c create mode 100644 kernel/fiasco/src/lib/gzip/deflate.h create mode 100644 kernel/fiasco/src/lib/gzip/gzip.c create mode 100644 kernel/fiasco/src/lib/gzip/gzip.h create mode 100644 kernel/fiasco/src/lib/gzip/my_conf.h create mode 100644 kernel/fiasco/src/lib/gzip/trees.c create mode 100644 kernel/fiasco/src/lib/gzip/trees.h create mode 100644 kernel/fiasco/src/lib/gzip/zconf.h create mode 100644 kernel/fiasco/src/lib/gzip/zlib.h create mode 100644 kernel/fiasco/src/lib/gzip/zutil.c create mode 100644 kernel/fiasco/src/lib/gzip/zutil.h create mode 100644 kernel/fiasco/src/lib/libk/amd64/atomic-amd64.cpp create mode 100644 kernel/fiasco/src/lib/libk/amd64/div32.h create mode 100644 kernel/fiasco/src/lib/libk/amd64/mod32.h create mode 100644 kernel/fiasco/src/lib/libk/arm/atomic-arm-up.cpp create mode 100644 kernel/fiasco/src/lib/libk/arm/div32.h create mode 100644 kernel/fiasco/src/lib/libk/assert_opt.h create mode 100644 kernel/fiasco/src/lib/libk/atomic.cpp create mode 100644 kernel/fiasco/src/lib/libk/auto_ptr.cpp create mode 100644 kernel/fiasco/src/lib/libk/bitmap.cpp create mode 100644 kernel/fiasco/src/lib/libk/bits/list_basics.h create mode 100644 kernel/fiasco/src/lib/libk/cdefs.h create mode 100644 kernel/fiasco/src/lib/libk/construction.cc create mode 100644 kernel/fiasco/src/lib/libk/construction.h create mode 100644 kernel/fiasco/src/lib/libk/dlist create mode 100644 kernel/fiasco/src/lib/libk/fiasco_defs.h create mode 100644 kernel/fiasco/src/lib/libk/gcc_lib.c create mode 100644 kernel/fiasco/src/lib/libk/hlist create mode 100644 kernel/fiasco/src/lib/libk/ia32/atomic-ia32-smp.cpp create mode 100644 kernel/fiasco/src/lib/libk/ia32/div32.h create mode 100644 kernel/fiasco/src/lib/libk/ia32/mod32.h create mode 100644 kernel/fiasco/src/lib/libk/ia32/unistd.cpp create mode 100644 kernel/fiasco/src/lib/libk/lock_guard.cpp create mode 100644 kernel/fiasco/src/lib/libk/mem_region.cpp create mode 100644 kernel/fiasco/src/lib/libk/minmax.h create mode 100644 kernel/fiasco/src/lib/libk/new create mode 100644 kernel/fiasco/src/lib/libk/ppc32/atomic-ppc32.cpp create mode 100644 kernel/fiasco/src/lib/libk/ppc32/div32.h create mode 100644 kernel/fiasco/src/lib/libk/slab_cache.cpp create mode 100644 kernel/fiasco/src/lib/libk/slab_cache_anon-old.cpp create mode 100644 kernel/fiasco/src/lib/libk/slist create mode 100644 kernel/fiasco/src/lib/libk/sparc/atomic-sparc.cpp create mode 100644 kernel/fiasco/src/lib/libk/sparc/div32.h create mode 100644 kernel/fiasco/src/lib/libk/std_macros.cpp create mode 100644 kernel/fiasco/src/lib/libk/template_math.h create mode 100644 kernel/fiasco/src/lib/libk/type_traits create mode 100644 kernel/fiasco/src/lib/libk/unique_ptr.h create mode 100644 kernel/fiasco/src/lib/libk/ux/div32.h create mode 100644 kernel/fiasco/src/lib/libk/ux/mod32.h create mode 100644 kernel/fiasco/src/lib/minilibc/__assert_fail.c create mode 100644 kernel/fiasco/src/lib/minilibc/__lltostr.c create mode 100644 kernel/fiasco/src/lib/minilibc/__ltostr.c create mode 100644 kernel/fiasco/src/lib/minilibc/__v_printf.c create mode 100644 kernel/fiasco/src/lib/minilibc/aeabi.c create mode 100644 kernel/fiasco/src/lib/minilibc/amd64/include/limits.h create mode 100644 kernel/fiasco/src/lib/minilibc/amd64/include/setjmp.h create mode 100644 kernel/fiasco/src/lib/minilibc/amd64/lltostr.c create mode 100644 kernel/fiasco/src/lib/minilibc/amd64/setjmp.S create mode 100644 kernel/fiasco/src/lib/minilibc/arm/include/limits.h create mode 100644 kernel/fiasco/src/lib/minilibc/arm/include/setjmp.h create mode 100644 kernel/fiasco/src/lib/minilibc/arm/setjmp.S create mode 100644 kernel/fiasco/src/lib/minilibc/atexit.c create mode 100644 kernel/fiasco/src/lib/minilibc/fprintf.c create mode 100644 kernel/fiasco/src/lib/minilibc/getchar.c create mode 100644 kernel/fiasco/src/lib/minilibc/gets.c create mode 100644 kernel/fiasco/src/lib/minilibc/ia32/include/limits.h create mode 100644 kernel/fiasco/src/lib/minilibc/ia32/include/memcpy.h create mode 100644 kernel/fiasco/src/lib/minilibc/ia32/include/setjmp.h create mode 100644 kernel/fiasco/src/lib/minilibc/ia32/lltostr.c create mode 100644 kernel/fiasco/src/lib/minilibc/ia32/setjmp.S create mode 100644 kernel/fiasco/src/lib/minilibc/include/alloca.h create mode 100644 kernel/fiasco/src/lib/minilibc/include/assert.h create mode 100644 kernel/fiasco/src/lib/minilibc/include/cassert create mode 100644 kernel/fiasco/src/lib/minilibc/include/cctype create mode 100644 kernel/fiasco/src/lib/minilibc/include/cdefs.h create mode 100644 kernel/fiasco/src/lib/minilibc/include/climits create mode 100644 kernel/fiasco/src/lib/minilibc/include/csetjmp create mode 100644 kernel/fiasco/src/lib/minilibc/include/cstdarg create mode 100644 kernel/fiasco/src/lib/minilibc/include/cstddef create mode 100644 kernel/fiasco/src/lib/minilibc/include/cstdio create mode 100644 kernel/fiasco/src/lib/minilibc/include/cstdlib create mode 100644 kernel/fiasco/src/lib/minilibc/include/cstring create mode 100644 kernel/fiasco/src/lib/minilibc/include/ctype.h create mode 100644 kernel/fiasco/src/lib/minilibc/include/errno.h create mode 100644 kernel/fiasco/src/lib/minilibc/include/malloc.h create mode 100644 kernel/fiasco/src/lib/minilibc/include/memcpy.h create mode 100644 kernel/fiasco/src/lib/minilibc/include/mini_defs.h create mode 100644 kernel/fiasco/src/lib/minilibc/include/panic.h create mode 100644 kernel/fiasco/src/lib/minilibc/include/simpleio.h create mode 100644 kernel/fiasco/src/lib/minilibc/include/stdio.h create mode 100644 kernel/fiasco/src/lib/minilibc/include/stdlib.h create mode 100644 kernel/fiasco/src/lib/minilibc/include/string.h create mode 100644 kernel/fiasco/src/lib/minilibc/isalnum.c create mode 100644 kernel/fiasco/src/lib/minilibc/isalpha.c create mode 100644 kernel/fiasco/src/lib/minilibc/isascii.c create mode 100644 kernel/fiasco/src/lib/minilibc/isblank.c create mode 100644 kernel/fiasco/src/lib/minilibc/iscntrl.c create mode 100644 kernel/fiasco/src/lib/minilibc/isdigit.c create mode 100644 kernel/fiasco/src/lib/minilibc/isgraph.c create mode 100644 kernel/fiasco/src/lib/minilibc/islower.c create mode 100644 kernel/fiasco/src/lib/minilibc/isprint.c create mode 100644 kernel/fiasco/src/lib/minilibc/ispunct.c create mode 100644 kernel/fiasco/src/lib/minilibc/isspace.c create mode 100644 kernel/fiasco/src/lib/minilibc/isupper.c create mode 100644 kernel/fiasco/src/lib/minilibc/isxdigit.c create mode 100644 kernel/fiasco/src/lib/minilibc/longjmp.c create mode 100644 kernel/fiasco/src/lib/minilibc/memccpy.c create mode 100644 kernel/fiasco/src/lib/minilibc/memchr.c create mode 100644 kernel/fiasco/src/lib/minilibc/memcmp.c create mode 100644 kernel/fiasco/src/lib/minilibc/memcpy.c create mode 100644 kernel/fiasco/src/lib/minilibc/memmove.c create mode 100644 kernel/fiasco/src/lib/minilibc/memset.c create mode 100644 kernel/fiasco/src/lib/minilibc/panic.c create mode 100644 kernel/fiasco/src/lib/minilibc/ppc32/include/limits.h create mode 100644 kernel/fiasco/src/lib/minilibc/ppc32/include/setjmp.h create mode 100644 kernel/fiasco/src/lib/minilibc/ppc32/setjmp.S create mode 100644 kernel/fiasco/src/lib/minilibc/printf.c create mode 100644 kernel/fiasco/src/lib/minilibc/putchar.c create mode 100644 kernel/fiasco/src/lib/minilibc/puts.c create mode 100644 kernel/fiasco/src/lib/minilibc/raise.c create mode 100644 kernel/fiasco/src/lib/minilibc/snprintf.c create mode 100644 kernel/fiasco/src/lib/minilibc/sparc/include/limits.h create mode 100644 kernel/fiasco/src/lib/minilibc/sparc/include/setjmp.h create mode 100644 kernel/fiasco/src/lib/minilibc/sparc/setjmp.S create mode 100644 kernel/fiasco/src/lib/minilibc/sprintf.c create mode 100644 kernel/fiasco/src/lib/minilibc/strchr.c create mode 100644 kernel/fiasco/src/lib/minilibc/strcmp.c create mode 100644 kernel/fiasco/src/lib/minilibc/strcpy.c create mode 100644 kernel/fiasco/src/lib/minilibc/strcspn.c create mode 100644 kernel/fiasco/src/lib/minilibc/strlen.c create mode 100644 kernel/fiasco/src/lib/minilibc/strncmp.c create mode 100644 kernel/fiasco/src/lib/minilibc/strncpy.c create mode 100644 kernel/fiasco/src/lib/minilibc/strspn.c create mode 100644 kernel/fiasco/src/lib/minilibc/strstr.c create mode 100644 kernel/fiasco/src/lib/minilibc/strtol.c create mode 100644 kernel/fiasco/src/lib/minilibc/strtoul.c create mode 100644 kernel/fiasco/src/lib/minilibc/tolower.c create mode 100644 kernel/fiasco/src/lib/minilibc/vprintf.c create mode 100644 kernel/fiasco/src/lib/minilibc/vprintf_backend.h create mode 100644 kernel/fiasco/src/lib/minilibc/vsnprintf.c create mode 100644 kernel/fiasco/src/lib/minilibc/vsprintf.c create mode 100644 kernel/fiasco/src/lib/perfctr/COPYING create mode 100644 kernel/fiasco/src/lib/perfctr/event_set.h create mode 100644 kernel/fiasco/src/lib/perfctr/event_set_amd.c create mode 100644 kernel/fiasco/src/lib/perfctr/event_set_arm.c create mode 100644 kernel/fiasco/src/lib/perfctr/event_set_centaur.c create mode 100644 kernel/fiasco/src/lib/perfctr/event_set_p4.c create mode 100644 kernel/fiasco/src/lib/perfctr/event_set_p5.c create mode 100644 kernel/fiasco/src/lib/perfctr/event_set_p6.c create mode 100644 kernel/fiasco/src/lib/perfctr/event_set_ppc.c create mode 100644 kernel/fiasco/src/lib/perfctr/event_set_x86.c create mode 100644 kernel/fiasco/src/lib/perfctr/libperfctr.h create mode 100644 kernel/fiasco/src/lib/perfctr/perfctr.c create mode 100644 kernel/fiasco/src/lib/regex/COPYING create mode 100644 kernel/fiasco/src/lib/regex/README create mode 100644 kernel/fiasco/src/lib/regex/alloc.c create mode 100644 kernel/fiasco/src/lib/regex/regex.h create mode 100644 kernel/fiasco/src/lib/regex/rx.c create mode 100644 kernel/fiasco/src/lib/uart/Makefile create mode 100644 kernel/fiasco/src/lib/uart/io_regblock.h create mode 100644 kernel/fiasco/src/lib/uart/io_regblock_asi.h create mode 100644 kernel/fiasco/src/lib/uart/io_regblock_port.h create mode 100644 kernel/fiasco/src/lib/uart/of1275.h create mode 100644 kernel/fiasco/src/lib/uart/uart_base.h create mode 100644 kernel/fiasco/src/lib/uart/uart_dcc-v6.cc create mode 100644 kernel/fiasco/src/lib/uart/uart_dcc-v6.h create mode 100644 kernel/fiasco/src/lib/uart/uart_imx.cc create mode 100644 kernel/fiasco/src/lib/uart/uart_imx.h create mode 100644 kernel/fiasco/src/lib/uart/uart_leon3.cc create mode 100644 kernel/fiasco/src/lib/uart/uart_leon3.h create mode 100644 kernel/fiasco/src/lib/uart/uart_mpc52xx.cc create mode 100644 kernel/fiasco/src/lib/uart/uart_mpc52xx.h create mode 100644 kernel/fiasco/src/lib/uart/uart_of.cc create mode 100644 kernel/fiasco/src/lib/uart/uart_of.h create mode 100644 kernel/fiasco/src/lib/uart/uart_omap35x.cc create mode 100644 kernel/fiasco/src/lib/uart/uart_omap35x.h create mode 100644 kernel/fiasco/src/lib/uart/uart_pl011.cc create mode 100644 kernel/fiasco/src/lib/uart/uart_pl011.h create mode 100644 kernel/fiasco/src/lib/uart/uart_s3c2410.cc create mode 100644 kernel/fiasco/src/lib/uart/uart_s3c2410.h create mode 100644 kernel/fiasco/src/templates/.gdbinit.ux create mode 100644 kernel/fiasco/src/templates/Makefile create mode 100644 kernel/fiasco/src/templates/Makefile.builddir.templ create mode 100644 kernel/fiasco/src/templates/globalconfig.out.amd64-1 create mode 100644 kernel/fiasco/src/templates/globalconfig.out.amd64-2 create mode 100644 kernel/fiasco/src/templates/globalconfig.out.amd64-3-noinl create mode 100644 kernel/fiasco/src/templates/globalconfig.out.amd64-mp create mode 100644 kernel/fiasco/src/templates/globalconfig.out.arm-a9-mp-1 create mode 100644 kernel/fiasco/src/templates/globalconfig.out.arm-a9-mp-2 create mode 100644 kernel/fiasco/src/templates/globalconfig.out.arm-a9-mp-vexpress create mode 100644 kernel/fiasco/src/templates/globalconfig.out.arm-imx21 create mode 100644 kernel/fiasco/src/templates/globalconfig.out.arm-imx35 create mode 100644 kernel/fiasco/src/templates/globalconfig.out.arm-imx51 create mode 100644 kernel/fiasco/src/templates/globalconfig.out.arm-int-1 create mode 100644 kernel/fiasco/src/templates/globalconfig.out.arm-int-2 create mode 100644 kernel/fiasco/src/templates/globalconfig.out.arm-kirkwood create mode 100644 kernel/fiasco/src/templates/globalconfig.out.arm-omap3evm create mode 100644 kernel/fiasco/src/templates/globalconfig.out.arm-omap4-panda create mode 100644 kernel/fiasco/src/templates/globalconfig.out.arm-pxa create mode 100644 kernel/fiasco/src/templates/globalconfig.out.arm-rv-1 create mode 100644 kernel/fiasco/src/templates/globalconfig.out.arm-rv-2 create mode 100644 kernel/fiasco/src/templates/globalconfig.out.arm-rv-3 create mode 100644 kernel/fiasco/src/templates/globalconfig.out.arm-rv-4-noinl create mode 100644 kernel/fiasco/src/templates/globalconfig.out.arm-s3c create mode 100644 kernel/fiasco/src/templates/globalconfig.out.arm-sa create mode 100644 kernel/fiasco/src/templates/globalconfig.out.arm-t2 create mode 100644 kernel/fiasco/src/templates/globalconfig.out.arm-v6 create mode 100644 kernel/fiasco/src/templates/globalconfig.out.arm-v6-mp-eb create mode 100644 kernel/fiasco/src/templates/globalconfig.out.arm-v6-mp-pb create mode 100644 kernel/fiasco/src/templates/globalconfig.out.arm-v7 create mode 100644 kernel/fiasco/src/templates/globalconfig.out.ia32-1 create mode 100644 kernel/fiasco/src/templates/globalconfig.out.ia32-2 create mode 100644 kernel/fiasco/src/templates/globalconfig.out.ia32-3-noinl create mode 100644 kernel/fiasco/src/templates/globalconfig.out.ia32-big create mode 100644 kernel/fiasco/src/templates/globalconfig.out.ia32-mp create mode 100644 kernel/fiasco/src/templates/globalconfig.out.ia32-ndebug create mode 100644 kernel/fiasco/src/templates/globalconfig.out.ux-1 create mode 100644 kernel/fiasco/src/templates/globalconfig.out.ux-2 create mode 100644 kernel/fiasco/src/templates/globalconfig.out.ux-3-noinl create mode 100644 kernel/fiasco/src/test/Makefile create mode 100644 kernel/fiasco/src/test/Makerules.BOOTTASK create mode 100644 kernel/fiasco/src/test/Makerules.SYSTEM_UNDER_TEST create mode 100644 kernel/fiasco/src/test/Makerules.TESTTASK create mode 100644 kernel/fiasco/src/test/Makerules.WRAPPERS create mode 100644 kernel/fiasco/src/test/boottask/bootstrap-boottask.cc create mode 100644 kernel/fiasco/src/test/boottask/boottask-r.ld create mode 100644 kernel/fiasco/src/test/map_util/Makefile create mode 100644 kernel/fiasco/src/test/map_util/Modules.map_util create mode 100644 kernel/fiasco/src/test/map_util/map_util.t.cc create mode 100644 kernel/fiasco/src/test/map_util/map_util.t.out.verify create mode 100644 kernel/fiasco/src/test/mapdb/Makefile create mode 100644 kernel/fiasco/src/test/mapdb/Modules.mapdb create mode 100644 kernel/fiasco/src/test/mapdb/mapdb.t.cc create mode 100644 kernel/fiasco/src/test/mapdb/mapdb.t.out.verify create mode 100644 kernel/fiasco/src/test/pingpong/Makefile create mode 100644 kernel/fiasco/src/test/pingpong/Modules create mode 100644 kernel/fiasco/src/test/pingpong/kernel_thread-test.cpp create mode 100644 kernel/fiasco/src/test/pingpong/pingpong.c create mode 100644 kernel/fiasco/src/test/space/Makefile create mode 100644 kernel/fiasco/src/test/space/Modules.space create mode 100644 kernel/fiasco/src/test/space/space.t.cc create mode 100644 kernel/fiasco/src/test/space/space.t.out.verify create mode 100644 kernel/fiasco/src/test/sysenterexit/Makefile create mode 100644 kernel/fiasco/src/test/sysenterexit/Modules create mode 100644 kernel/fiasco/src/test/sysenterexit/sysenterexit.c create mode 100644 kernel/fiasco/src/test/testtask/crt0-user.S create mode 100644 kernel/fiasco/src/test/trace/Makefile create mode 100644 kernel/fiasco/src/test/trace/README create mode 100644 kernel/fiasco/src/test/trace/trace.c create mode 100644 kernel/fiasco/src/test/unit/map_util_t.cpp create mode 100644 kernel/fiasco/src/test/unit/map_util_t.out.verify.v2 create mode 100644 kernel/fiasco/src/test/unit/mapdb_t.cpp create mode 100644 kernel/fiasco/src/test/unit/mapdb_t.out.verify create mode 100644 kernel/fiasco/src/test/wrappers/Makefile create mode 100644 kernel/fiasco/src/test/wrappers/Modules.wrappers create mode 100644 kernel/fiasco/src/test/wrappers/fake_boot_info.cpp create mode 100644 kernel/fiasco/src/test/wrappers/fake_checksum.cpp create mode 100644 kernel/fiasco/src/test/wrappers/fake_globals.cpp create mode 100644 kernel/fiasco/src/test/wrappers/fake_helping_lock.cpp create mode 100644 kernel/fiasco/src/test/wrappers/fake_kdb_ke.cpp create mode 100644 kernel/fiasco/src/test/wrappers/fake_kmem.cpp create mode 100644 kernel/fiasco/src/test/wrappers/fake_kmem_alloc.cpp create mode 100644 kernel/fiasco/src/test/wrappers/simple_lock.cpp create mode 100644 kernel/fiasco/src/test/wrappers/symbols.c create mode 100644 kernel/fiasco/src/test/wrappers/unix_aligned_alloc.cpp create mode 100644 kernel/fiasco/src/test/wrappers/unix_slab.cpp create mode 100644 kernel/fiasco/src/types/amd64/types-arch.h create mode 100644 kernel/fiasco/src/types/arm/asm.h create mode 100644 kernel/fiasco/src/types/arm/types-arch.h create mode 100644 kernel/fiasco/src/types/ia32/types-arch.h create mode 100644 kernel/fiasco/src/types/ppc32/types-arch.h create mode 100644 kernel/fiasco/src/types/sparc/types-arch.h create mode 100644 kernel/fiasco/src/types/types.h create mode 100644 kernel/fiasco/src/types/ux/types-arch.h create mode 100755 kernel/fiasco/tool/backtrace create mode 100755 kernel/fiasco/tool/checkinitcalls create mode 100755 kernel/fiasco/tool/circular create mode 100755 kernel/fiasco/tool/gen_kconfig create mode 100755 kernel/fiasco/tool/gendotdeps create mode 100755 kernel/fiasco/tool/genoffset.py create mode 100644 kernel/fiasco/tool/kconfig/COPYING create mode 100644 kernel/fiasco/tool/kconfig/Makefile create mode 100644 kernel/fiasco/tool/kconfig/README create mode 100644 kernel/fiasco/tool/kconfig/scripts/Kbuild.include create mode 100644 kernel/fiasco/tool/kconfig/scripts/Makefile create mode 100644 kernel/fiasco/tool/kconfig/scripts/Makefile.build create mode 100644 kernel/fiasco/tool/kconfig/scripts/Makefile.clean create mode 100644 kernel/fiasco/tool/kconfig/scripts/Makefile.headersinst create mode 100644 kernel/fiasco/tool/kconfig/scripts/Makefile.host create mode 100644 kernel/fiasco/tool/kconfig/scripts/Makefile.lib create mode 100644 kernel/fiasco/tool/kconfig/scripts/Makefile.modinst create mode 100644 kernel/fiasco/tool/kconfig/scripts/Makefile.modpost create mode 100644 kernel/fiasco/tool/kconfig/scripts/basic/Makefile create mode 100644 kernel/fiasco/tool/kconfig/scripts/basic/docproc.c create mode 100644 kernel/fiasco/tool/kconfig/scripts/basic/fixdep.c create mode 100644 kernel/fiasco/tool/kconfig/scripts/basic/hash.c create mode 100644 kernel/fiasco/tool/kconfig/scripts/kconfig/.gitignore create mode 100644 kernel/fiasco/tool/kconfig/scripts/kconfig/Makefile create mode 100644 kernel/fiasco/tool/kconfig/scripts/kconfig/POTFILES.in create mode 100755 kernel/fiasco/tool/kconfig/scripts/kconfig/check.sh create mode 100644 kernel/fiasco/tool/kconfig/scripts/kconfig/conf.c create mode 100644 kernel/fiasco/tool/kconfig/scripts/kconfig/confdata.c create mode 100644 kernel/fiasco/tool/kconfig/scripts/kconfig/expr.c create mode 100644 kernel/fiasco/tool/kconfig/scripts/kconfig/expr.h create mode 100644 kernel/fiasco/tool/kconfig/scripts/kconfig/gconf.c create mode 100644 kernel/fiasco/tool/kconfig/scripts/kconfig/gconf.glade create mode 100644 kernel/fiasco/tool/kconfig/scripts/kconfig/images.c create mode 100644 kernel/fiasco/tool/kconfig/scripts/kconfig/kxgettext.c create mode 100644 kernel/fiasco/tool/kconfig/scripts/kconfig/lkc.h create mode 100644 kernel/fiasco/tool/kconfig/scripts/kconfig/lkc_proto.h create mode 100644 kernel/fiasco/tool/kconfig/scripts/kconfig/lxdialog/.gitignore create mode 100644 kernel/fiasco/tool/kconfig/scripts/kconfig/lxdialog/BIG.FAT.WARNING create mode 100644 kernel/fiasco/tool/kconfig/scripts/kconfig/lxdialog/check-lxdialog.sh create mode 100644 kernel/fiasco/tool/kconfig/scripts/kconfig/lxdialog/checklist.c create mode 100644 kernel/fiasco/tool/kconfig/scripts/kconfig/lxdialog/dialog.h create mode 100644 kernel/fiasco/tool/kconfig/scripts/kconfig/lxdialog/inputbox.c create mode 100644 kernel/fiasco/tool/kconfig/scripts/kconfig/lxdialog/menubox.c create mode 100644 kernel/fiasco/tool/kconfig/scripts/kconfig/lxdialog/textbox.c create mode 100644 kernel/fiasco/tool/kconfig/scripts/kconfig/lxdialog/util.c create mode 100644 kernel/fiasco/tool/kconfig/scripts/kconfig/lxdialog/yesno.c create mode 100644 kernel/fiasco/tool/kconfig/scripts/kconfig/mconf.c create mode 100644 kernel/fiasco/tool/kconfig/scripts/kconfig/menu.c create mode 100644 kernel/fiasco/tool/kconfig/scripts/kconfig/nconf.c create mode 100644 kernel/fiasco/tool/kconfig/scripts/kconfig/nconf.gui.c create mode 100644 kernel/fiasco/tool/kconfig/scripts/kconfig/nconf.h create mode 100644 kernel/fiasco/tool/kconfig/scripts/kconfig/qconf.cc create mode 100644 kernel/fiasco/tool/kconfig/scripts/kconfig/qconf.h create mode 100644 kernel/fiasco/tool/kconfig/scripts/kconfig/symbol.c create mode 100644 kernel/fiasco/tool/kconfig/scripts/kconfig/util.c create mode 100644 kernel/fiasco/tool/kconfig/scripts/kconfig/zconf.gperf create mode 100644 kernel/fiasco/tool/kconfig/scripts/kconfig/zconf.hash.c_shipped create mode 100644 kernel/fiasco/tool/kconfig/scripts/kconfig/zconf.l create mode 100644 kernel/fiasco/tool/kconfig/scripts/kconfig/zconf.lex.c_shipped create mode 100644 kernel/fiasco/tool/kconfig/scripts/kconfig/zconf.tab.c_shipped create mode 100644 kernel/fiasco/tool/kconfig/scripts/kconfig/zconf.y create mode 100755 kernel/fiasco/tool/kobjdeps create mode 100755 kernel/fiasco/tool/mksnap create mode 100755 kernel/fiasco/tool/move-if-change create mode 100755 kernel/fiasco/tool/parsedeps create mode 100644 kernel/fiasco/tool/preprocess/COPYING create mode 100644 kernel/fiasco/tool/preprocess/MAINTAINER create mode 100644 kernel/fiasco/tool/preprocess/Makefile create mode 100644 kernel/fiasco/tool/preprocess/README create mode 100644 kernel/fiasco/tool/preprocess/TODO create mode 100644 kernel/fiasco/tool/preprocess/doc/Doxyfile create mode 100644 kernel/fiasco/tool/preprocess/doc/Makefile create mode 100644 kernel/fiasco/tool/preprocess/doc/manpage.dox create mode 100644 kernel/fiasco/tool/preprocess/src/Makefile create mode 100755 kernel/fiasco/tool/preprocess/src/preprocess create mode 100644 kernel/fiasco/tool/preprocess/test/Makefile create mode 100644 kernel/fiasco/tool/preprocess/test/c-preproc.cpp create mode 100644 kernel/fiasco/tool/preprocess/test/combine.pl create mode 100644 kernel/fiasco/tool/preprocess/test/comment_in_string.cpp create mode 100644 kernel/fiasco/tool/preprocess/test/default_args.cpp create mode 100644 kernel/fiasco/tool/preprocess/test/dropsection-ext.cpp create mode 100644 kernel/fiasco/tool/preprocess/test/dropsection.cpp create mode 100644 kernel/fiasco/tool/preprocess/test/explicit.cpp create mode 100644 kernel/fiasco/tool/preprocess/test/extern_c.cpp create mode 100644 kernel/fiasco/tool/preprocess/test/inline.cpp create mode 100644 kernel/fiasco/tool/preprocess/test/interface.cpp create mode 100644 kernel/fiasco/tool/preprocess/test/line.cpp create mode 100644 kernel/fiasco/tool/preprocess/test/mapping.cpp create mode 100644 kernel/fiasco/tool/preprocess/test/multifile1.cpp create mode 100644 kernel/fiasco/tool/preprocess/test/multifile2.cpp create mode 100644 kernel/fiasco/tool/preprocess/test/noinline.cpp create mode 100644 kernel/fiasco/tool/preprocess/test/operator.cpp create mode 100644 kernel/fiasco/tool/preprocess/test/parser.cpp create mode 100644 kernel/fiasco/tool/preprocess/test/static.cpp create mode 100644 kernel/fiasco/tool/preprocess/test/template.cpp create mode 100644 kernel/fiasco/tool/preprocess/test/variable.cpp create mode 100644 kernel/fiasco/tool/preprocess/test/verify/c-preproc.cc create mode 100644 kernel/fiasco/tool/preprocess/test/verify/c-preproc.h create mode 100644 kernel/fiasco/tool/preprocess/test/verify/c-preproc_i.h create mode 100644 kernel/fiasco/tool/preprocess/test/verify/comment_in_string.cc create mode 100644 kernel/fiasco/tool/preprocess/test/verify/comment_in_string.h create mode 100644 kernel/fiasco/tool/preprocess/test/verify/comment_in_string_i.h create mode 100644 kernel/fiasco/tool/preprocess/test/verify/default_args.cc create mode 100644 kernel/fiasco/tool/preprocess/test/verify/default_args.h create mode 100644 kernel/fiasco/tool/preprocess/test/verify/default_args_i.h create mode 100644 kernel/fiasco/tool/preprocess/test/verify/drop_multi1-ext.cc create mode 100644 kernel/fiasco/tool/preprocess/test/verify/drop_multi1.cc create mode 100644 kernel/fiasco/tool/preprocess/test/verify/drop_multi1.h create mode 100644 kernel/fiasco/tool/preprocess/test/verify/drop_multi1_i.h create mode 100644 kernel/fiasco/tool/preprocess/test/verify/drop_multi2-ext.cc create mode 100644 kernel/fiasco/tool/preprocess/test/verify/drop_multi2.cc create mode 100644 kernel/fiasco/tool/preprocess/test/verify/drop_multi2.h create mode 100644 kernel/fiasco/tool/preprocess/test/verify/drop_multi2_i.h create mode 100644 kernel/fiasco/tool/preprocess/test/verify/drop_single1.cc create mode 100644 kernel/fiasco/tool/preprocess/test/verify/drop_single1.h create mode 100644 kernel/fiasco/tool/preprocess/test/verify/drop_single1_i.h create mode 100644 kernel/fiasco/tool/preprocess/test/verify/drop_single2.cc create mode 100644 kernel/fiasco/tool/preprocess/test/verify/drop_single2.h create mode 100644 kernel/fiasco/tool/preprocess/test/verify/drop_single2_i.h create mode 100644 kernel/fiasco/tool/preprocess/test/verify/drop_single3.cc create mode 100644 kernel/fiasco/tool/preprocess/test/verify/drop_single3.h create mode 100644 kernel/fiasco/tool/preprocess/test/verify/drop_single3_i.h create mode 100644 kernel/fiasco/tool/preprocess/test/verify/explicit.cc create mode 100644 kernel/fiasco/tool/preprocess/test/verify/explicit.h create mode 100644 kernel/fiasco/tool/preprocess/test/verify/explicit_i.h create mode 100644 kernel/fiasco/tool/preprocess/test/verify/extern_c.cc create mode 100644 kernel/fiasco/tool/preprocess/test/verify/extern_c.h create mode 100644 kernel/fiasco/tool/preprocess/test/verify/extern_c_i.h create mode 100644 kernel/fiasco/tool/preprocess/test/verify/inline.cc create mode 100644 kernel/fiasco/tool/preprocess/test/verify/inline.h create mode 100644 kernel/fiasco/tool/preprocess/test/verify/inline_i.h create mode 100644 kernel/fiasco/tool/preprocess/test/verify/inline_noinline.cc create mode 100644 kernel/fiasco/tool/preprocess/test/verify/inline_noinline.h create mode 100644 kernel/fiasco/tool/preprocess/test/verify/inline_noinline_i.h create mode 100644 kernel/fiasco/tool/preprocess/test/verify/interface.cc create mode 100644 kernel/fiasco/tool/preprocess/test/verify/interface_i.h create mode 100644 kernel/fiasco/tool/preprocess/test/verify/interfacepublic.h create mode 100644 kernel/fiasco/tool/preprocess/test/verify/line.cc create mode 100644 kernel/fiasco/tool/preprocess/test/verify/line.h create mode 100644 kernel/fiasco/tool/preprocess/test/verify/line_i.h create mode 100644 kernel/fiasco/tool/preprocess/test/verify/line_nh.cc create mode 100644 kernel/fiasco/tool/preprocess/test/verify/line_nh.h create mode 100644 kernel/fiasco/tool/preprocess/test/verify/line_nh_i.h create mode 100644 kernel/fiasco/tool/preprocess/test/verify/line_not.cc create mode 100644 kernel/fiasco/tool/preprocess/test/verify/line_not.h create mode 100644 kernel/fiasco/tool/preprocess/test/verify/line_not_i.h create mode 100644 kernel/fiasco/tool/preprocess/test/verify/mapping.cc create mode 100644 kernel/fiasco/tool/preprocess/test/verify/mapping.h create mode 100644 kernel/fiasco/tool/preprocess/test/verify/mapping_i.h create mode 100644 kernel/fiasco/tool/preprocess/test/verify/mapping_inline.cc create mode 100644 kernel/fiasco/tool/preprocess/test/verify/mapping_inline.h create mode 100644 kernel/fiasco/tool/preprocess/test/verify/mapping_inline_i.h create mode 100644 kernel/fiasco/tool/preprocess/test/verify/multifile-part1.cc create mode 100644 kernel/fiasco/tool/preprocess/test/verify/multifile-part2.cc create mode 100644 kernel/fiasco/tool/preprocess/test/verify/multifile.cc create mode 100644 kernel/fiasco/tool/preprocess/test/verify/multifile.h create mode 100644 kernel/fiasco/tool/preprocess/test/verify/multifile_i.h create mode 100644 kernel/fiasco/tool/preprocess/test/verify/noinline.cc create mode 100644 kernel/fiasco/tool/preprocess/test/verify/noinline.h create mode 100644 kernel/fiasco/tool/preprocess/test/verify/noinline_i.h create mode 100644 kernel/fiasco/tool/preprocess/test/verify/operator.cc create mode 100644 kernel/fiasco/tool/preprocess/test/verify/operator.h create mode 100644 kernel/fiasco/tool/preprocess/test/verify/operator_i.h create mode 100644 kernel/fiasco/tool/preprocess/test/verify/parser.cc create mode 100644 kernel/fiasco/tool/preprocess/test/verify/parser.h create mode 100644 kernel/fiasco/tool/preprocess/test/verify/parser_i.h create mode 100644 kernel/fiasco/tool/preprocess/test/verify/parser_noinline.cc create mode 100644 kernel/fiasco/tool/preprocess/test/verify/parser_noinline.h create mode 100644 kernel/fiasco/tool/preprocess/test/verify/parser_noinline_i.h create mode 100644 kernel/fiasco/tool/preprocess/test/verify/random.cc create mode 100644 kernel/fiasco/tool/preprocess/test/verify/random.h create mode 100644 kernel/fiasco/tool/preprocess/test/verify/random_i.h create mode 100644 kernel/fiasco/tool/preprocess/test/verify/random_inline.cc create mode 100644 kernel/fiasco/tool/preprocess/test/verify/random_inline.h create mode 100644 kernel/fiasco/tool/preprocess/test/verify/random_inline_i.h create mode 100644 kernel/fiasco/tool/preprocess/test/verify/static.cc create mode 100644 kernel/fiasco/tool/preprocess/test/verify/static.h create mode 100644 kernel/fiasco/tool/preprocess/test/verify/static_i.h create mode 100644 kernel/fiasco/tool/preprocess/test/verify/template.cc create mode 100644 kernel/fiasco/tool/preprocess/test/verify/template.h create mode 100644 kernel/fiasco/tool/preprocess/test/verify/template_i.h create mode 100644 kernel/fiasco/tool/preprocess/test/verify/template_inline.cc create mode 100644 kernel/fiasco/tool/preprocess/test/verify/template_inline.h create mode 100644 kernel/fiasco/tool/preprocess/test/verify/template_inline_i.h create mode 100644 kernel/fiasco/tool/preprocess/test/verify/variable.cc create mode 100644 kernel/fiasco/tool/preprocess/test/verify/variable.h create mode 100644 kernel/fiasco/tool/preprocess/test/verify/variable_i.h create mode 100755 kernel/fiasco/tool/showdeps create mode 100755 kernel/fiasco/tool/split_config create mode 100644 l4/BENCHMARKING create mode 100644 l4/COPYING-GPL-2 create mode 100644 l4/COPYING-LGPL-2.1 create mode 100644 l4/LICENSING create mode 100644 l4/Makefile create mode 100644 l4/conf/Makeconf.boot.example create mode 100644 l4/conf/examples/arm-rv-lcd.cfg create mode 100644 l4/conf/examples/arm-rv-lcd.io create mode 100644 l4/conf/examples/arm-rv-lcd.list create mode 100644 l4/conf/examples/arm-rv.io create mode 100644 l4/conf/examples/hello.cfg create mode 100644 l4/conf/examples/l4lx-gfx.cfg create mode 100644 l4/conf/examples/l4lx-x86.io create mode 100644 l4/conf/examples/l4lx.cfg create mode 100644 l4/conf/examples/x86-fb.cfg create mode 100644 l4/conf/examples/x86-fb.io create mode 100644 l4/conf/examples/x86-fb.list create mode 100644 l4/conf/modules.list create mode 100644 l4/conf/platforms/README create mode 100644 l4/doc/Makefile create mode 100644 l4/doc/source/Makefile create mode 100644 l4/doc/source/getting_started.dox create mode 100644 l4/doc/source/header.tex create mode 100644 l4/doc/source/images/Makefile create mode 100644 l4/doc/source/images/header-bg.png create mode 100644 l4/doc/source/images/io-overview.pdf create mode 100644 l4/doc/source/images/io-overview.png create mode 100644 l4/doc/source/images/l4-caps-basic.pdf create mode 100644 l4/doc/source/images/l4-caps-basic.png create mode 100644 l4/doc/source/images/l4re-basic.pdf create mode 100644 l4/doc/source/images/l4re-basic.png create mode 100644 l4/doc/source/l4re-footer.html create mode 100644 l4/doc/source/l4re-header.html create mode 100644 l4/doc/source/l4re.cfg create mode 100644 l4/doc/source/l4re.dox create mode 100644 l4/doc/source/overview.dox create mode 100644 l4/doc/source/pthreads.dox create mode 100644 l4/doc/source/server_overview.dox create mode 100644 l4/mk/Kconfig create mode 100644 l4/mk/Makeconf create mode 100644 l4/mk/WhatIsThis create mode 100644 l4/mk/aliases.d/10-stdlibs create mode 100644 l4/mk/aliases.d/15-libio create mode 100644 l4/mk/binary.inc create mode 100644 l4/mk/config.inc create mode 100644 l4/mk/defconfig/config.amd64 create mode 100644 l4/mk/defconfig/config.arm-rv create mode 100644 l4/mk/defconfig/config.ppc32 create mode 100644 l4/mk/defconfig/config.sparc create mode 100644 l4/mk/defconfig/config.x86 create mode 100644 l4/mk/doc.mk create mode 100644 l4/mk/export_defs.inc create mode 100644 l4/mk/idl.mk create mode 100644 l4/mk/include.mk create mode 100644 l4/mk/install.inc create mode 100644 l4/mk/lib.mk create mode 100644 l4/mk/makehelpers.inc create mode 100644 l4/mk/modes.inc create mode 100755 l4/mk/pkgdeps create mode 100644 l4/mk/platforms/beagleboard.conf create mode 100644 l4/mk/platforms/imx21.conf create mode 100644 l4/mk/platforms/imx35.conf create mode 100644 l4/mk/platforms/imx51.conf create mode 100644 l4/mk/platforms/integrator.conf create mode 100644 l4/mk/platforms/kirkwood.conf create mode 100644 l4/mk/platforms/leon3.conf create mode 100644 l4/mk/platforms/mpc5200.conf create mode 100644 l4/mk/platforms/omap3_am33xx.conf create mode 100644 l4/mk/platforms/omap3evm.conf create mode 100644 l4/mk/platforms/pandaboard.conf create mode 100644 l4/mk/platforms/pc.conf create mode 100644 l4/mk/platforms/rv.conf create mode 100644 l4/mk/platforms/rv_pbx.conf create mode 100644 l4/mk/platforms/rv_vexpress.conf create mode 100644 l4/mk/platforms/tegra2.conf create mode 100644 l4/mk/prog.mk create mode 100755 l4/mk/ptest create mode 100755 l4/mk/redo_defconfigs create mode 100755 l4/mk/rel2abs.sh create mode 100644 l4/mk/rules.inc create mode 100644 l4/mk/runux.mk create mode 100644 l4/mk/subdir.mk create mode 100644 l4/mk/tmpl/Control create mode 100644 l4/mk/tmpl/Makefile create mode 100644 l4/mk/tmpl/examples/Makefile create mode 100644 l4/mk/tmpl/include/Makefile create mode 100755 l4/mk/tmpl/inst create mode 100644 l4/mk/tmpl/lib/Makefile create mode 100644 l4/mk/tmpl/lib/src/Makefile create mode 100644 l4/mk/tmpl/ptest/Makefile create mode 100644 l4/mk/tmpl/ptest/run/Makefile create mode 100644 l4/mk/tmpl/server/Makefile create mode 100644 l4/mk/tmpl/server/src/Makefile create mode 100644 l4/mk/tmpl/server/src/main.c create mode 100644 l4/pkg/Makefile create mode 100644 l4/pkg/README create mode 100644 l4/pkg/bootstrap/Control create mode 100644 l4/pkg/bootstrap/LEGAL create mode 100644 l4/pkg/bootstrap/Makefile create mode 100644 l4/pkg/bootstrap/README create mode 100644 l4/pkg/bootstrap/server/Makefile create mode 100644 l4/pkg/bootstrap/server/src/ARCH-amd64/boot32/boot.S create mode 100644 l4/pkg/bootstrap/server/src/ARCH-amd64/boot32/boot_cpu.c create mode 100644 l4/pkg/bootstrap/server/src/ARCH-amd64/boot32/boot_cpu.h create mode 100644 l4/pkg/bootstrap/server/src/ARCH-amd64/boot32/boot_idt.S create mode 100644 l4/pkg/bootstrap/server/src/ARCH-amd64/boot32/boot_kernel.c create mode 100644 l4/pkg/bootstrap/server/src/ARCH-amd64/boot32/boot_paging.h create mode 100644 l4/pkg/bootstrap/server/src/ARCH-amd64/boot32/bootstrap32.ld create mode 100644 l4/pkg/bootstrap/server/src/ARCH-amd64/boot32/load_elf.c create mode 100644 l4/pkg/bootstrap/server/src/ARCH-amd64/boot32/load_elf.h create mode 100644 l4/pkg/bootstrap/server/src/ARCH-amd64/boot32/minilibc_support.c create mode 100644 l4/pkg/bootstrap/server/src/ARCH-amd64/crt0.S create mode 100644 l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/Makefile create mode 100644 l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/__assert_fail.c create mode 100644 l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/__lltostr.c create mode 100644 l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/__ltostr.c create mode 100644 l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/__v_printf.c create mode 100644 l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/include/assert.h create mode 100644 l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/include/cdefs.h create mode 100644 l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/include/ctype.h create mode 100644 l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/include/libc_backend.h create mode 100644 l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/include/memcpy.h create mode 100644 l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/include/panic.h create mode 100644 l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/include/stdarg-cruft.h create mode 100644 l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/include/stdarg.h create mode 100644 l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/include/stddef.h create mode 100644 l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/include/stdio.h create mode 100644 l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/include/stdlib.h create mode 100644 l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/include/string.h create mode 100644 l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/include/strings.h create mode 100644 l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/isspace.c create mode 100644 l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/memcpy.c create mode 100644 l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/memmove.c create mode 100644 l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/memset.c create mode 100644 l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/printf.c create mode 100644 l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/puts.c create mode 100644 l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/strtol.c create mode 100644 l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/strtoul.c create mode 100644 l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/vprintf.c create mode 100644 l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/vprintf_backend.h create mode 100644 l4/pkg/bootstrap/server/src/ARCH-amd64/macros.h create mode 100644 l4/pkg/bootstrap/server/src/ARCH-arm/bootstrap.ld.in create mode 100644 l4/pkg/bootstrap/server/src/ARCH-arm/crt0.S create mode 100644 l4/pkg/bootstrap/server/src/ARCH-arm/macros.h create mode 100644 l4/pkg/bootstrap/server/src/ARCH-arm/reboot.cc create mode 100644 l4/pkg/bootstrap/server/src/ARCH-ppc32/bootstrap.ld.in create mode 100644 l4/pkg/bootstrap/server/src/ARCH-ppc32/crt0.S create mode 100644 l4/pkg/bootstrap/server/src/ARCH-ppc32/init_kip_v2-arch.cc create mode 100644 l4/pkg/bootstrap/server/src/ARCH-ppc32/macros.h create mode 100644 l4/pkg/bootstrap/server/src/ARCH-ppc32/reboot.cc create mode 100644 l4/pkg/bootstrap/server/src/ARCH-sparc/bootstrap.ld.in create mode 100644 l4/pkg/bootstrap/server/src/ARCH-sparc/crt0.S create mode 100644 l4/pkg/bootstrap/server/src/ARCH-sparc/leon_ahb.h create mode 100644 l4/pkg/bootstrap/server/src/ARCH-sparc/macros.h create mode 100644 l4/pkg/bootstrap/server/src/ARCH-sparc/reboot.cc create mode 100644 l4/pkg/bootstrap/server/src/ARCH-x86/bootsect.S create mode 100644 l4/pkg/bootstrap/server/src/ARCH-x86/bootstrap.ld.in create mode 100644 l4/pkg/bootstrap/server/src/ARCH-x86/crt0.S create mode 100644 l4/pkg/bootstrap/server/src/ARCH-x86/macros.h create mode 100644 l4/pkg/bootstrap/server/src/ARCH-x86/reboot.cc create mode 100644 l4/pkg/bootstrap/server/src/ARCH-x86/setup.S create mode 100644 l4/pkg/bootstrap/server/src/ARCH-x86/xen.c create mode 100644 l4/pkg/bootstrap/server/src/Make.rules create mode 100644 l4/pkg/bootstrap/server/src/Makefile create mode 100644 l4/pkg/bootstrap/server/src/README create mode 100644 l4/pkg/bootstrap/server/src/base_critical.c create mode 100644 l4/pkg/bootstrap/server/src/base_critical.h create mode 100755 l4/pkg/bootstrap/server/src/build.pl create mode 100644 l4/pkg/bootstrap/server/src/exec.c create mode 100644 l4/pkg/bootstrap/server/src/exec.h create mode 100644 l4/pkg/bootstrap/server/src/gunzip.c create mode 100644 l4/pkg/bootstrap/server/src/gunzip.h create mode 100644 l4/pkg/bootstrap/server/src/init_kip-arch.h create mode 100644 l4/pkg/bootstrap/server/src/init_kip.h create mode 100644 l4/pkg/bootstrap/server/src/init_kip_v2.cc create mode 100644 l4/pkg/bootstrap/server/src/init_kip_v4.cc create mode 100644 l4/pkg/bootstrap/server/src/koptions-def.h create mode 100644 l4/pkg/bootstrap/server/src/koptions.cc create mode 100644 l4/pkg/bootstrap/server/src/koptions.h create mode 100644 l4/pkg/bootstrap/server/src/ldscript.inc create mode 100644 l4/pkg/bootstrap/server/src/libc_support+.cc create mode 100644 l4/pkg/bootstrap/server/src/loader_mbi.cc create mode 100644 l4/pkg/bootstrap/server/src/loader_mbi.h create mode 100644 l4/pkg/bootstrap/server/src/module.c create mode 100644 l4/pkg/bootstrap/server/src/module.h create mode 100644 l4/pkg/bootstrap/server/src/panic.h create mode 100644 l4/pkg/bootstrap/server/src/patch.cc create mode 100644 l4/pkg/bootstrap/server/src/patch.h create mode 100644 l4/pkg/bootstrap/server/src/platform/imx.cc create mode 100644 l4/pkg/bootstrap/server/src/platform/integrator.cc create mode 100644 l4/pkg/bootstrap/server/src/platform/kirkwood.cc create mode 100644 l4/pkg/bootstrap/server/src/platform/leon3.cc create mode 100644 l4/pkg/bootstrap/server/src/platform/mpc5200.cc create mode 100644 l4/pkg/bootstrap/server/src/platform/om.cc create mode 100644 l4/pkg/bootstrap/server/src/platform/omap.cc create mode 100644 l4/pkg/bootstrap/server/src/platform/pxa.cc create mode 100644 l4/pkg/bootstrap/server/src/platform/rv.cc create mode 100644 l4/pkg/bootstrap/server/src/platform/sa1000.cc create mode 100644 l4/pkg/bootstrap/server/src/platform/tegra2.cc create mode 100644 l4/pkg/bootstrap/server/src/platform/x86_pc.cc create mode 100644 l4/pkg/bootstrap/server/src/region.cc create mode 100644 l4/pkg/bootstrap/server/src/region.h create mode 100644 l4/pkg/bootstrap/server/src/startup.cc create mode 100644 l4/pkg/bootstrap/server/src/startup.h create mode 100644 l4/pkg/bootstrap/server/src/support.h create mode 100644 l4/pkg/bootstrap/server/src/types.h create mode 100644 l4/pkg/bootstrap/server/src/uncompress.c create mode 100644 l4/pkg/bootstrap/server/src/uncompress.h create mode 100755 l4/pkg/bootstrap/server/src/unpack create mode 100644 l4/pkg/cxx/Control create mode 100644 l4/pkg/cxx/LEGAL create mode 100644 l4/pkg/cxx/Makefile create mode 100644 l4/pkg/cxx/doc/cxx.dox create mode 100644 l4/pkg/cxx/doc/files.cfg create mode 100644 l4/pkg/cxx/lib/Makefile create mode 100644 l4/pkg/cxx/lib/Makefile.inc create mode 100644 l4/pkg/cxx/lib/base/Makefile create mode 100644 l4/pkg/cxx/lib/base/include/Makefile create mode 100644 l4/pkg/cxx/lib/base/include/exceptions create mode 100644 l4/pkg/cxx/lib/base/include/std_exc_io create mode 100644 l4/pkg/cxx/lib/base/include/string create mode 100644 l4/pkg/cxx/lib/base/src/Makefile create mode 100644 l4/pkg/cxx/lib/base/src/cxa_pure_delete.cc create mode 100644 l4/pkg/cxx/lib/base/src/cxa_pure_virtual.cc create mode 100644 l4/pkg/cxx/lib/base/src/dso_handle.cc create mode 100644 l4/pkg/cxx/lib/be/Makefile create mode 100644 l4/pkg/cxx/lib/be/kdebug/Makefile create mode 100644 l4/pkg/cxx/lib/be/kdebug/iostream.cc create mode 100644 l4/pkg/cxx/lib/io/Makefile create mode 100644 l4/pkg/cxx/lib/io/include/Makefile create mode 100644 l4/pkg/cxx/lib/io/include/basic_ostream create mode 100644 l4/pkg/cxx/lib/io/include/iostream create mode 100644 l4/pkg/cxx/lib/io/include/iostream.h create mode 100644 l4/pkg/cxx/lib/io/include/l4iostream create mode 100644 l4/pkg/cxx/lib/io/include/l4iostream.h create mode 100644 l4/pkg/cxx/lib/io/src/Makefile create mode 100644 l4/pkg/cxx/lib/io/src/iob_write.cc create mode 100644 l4/pkg/cxx/lib/ipc/Makefile create mode 100644 l4/pkg/cxx/lib/ipc/include/Makefile create mode 100644 l4/pkg/cxx/lib/ipc/include/ipc_helper create mode 100644 l4/pkg/cxx/lib/ipc/include/ipc_server create mode 100644 l4/pkg/cxx/lib/ipc/include/ipc_stream create mode 100644 l4/pkg/cxx/lib/start/Makefile create mode 100644 l4/pkg/cxx/lib/start/include/Makefile create mode 100644 l4/pkg/cxx/lib/start/src/Makefile create mode 100644 l4/pkg/cxx/lib/start/src/cxx_atexit.cc create mode 100644 l4/pkg/cxx/lib/start/src/cxx_atexit.h create mode 100644 l4/pkg/cxx/lib/supc++-support/Makefile create mode 100644 l4/pkg/cxx/lib/supc++-support/src/Makefile create mode 100644 l4/pkg/cxx/lib/supc++-support/src/abort.cc create mode 100644 l4/pkg/cxx/lib/supc++-support/src/memset.c create mode 100644 l4/pkg/cxx/lib/tl/Makefile create mode 100644 l4/pkg/cxx/lib/tl/include/Makefile create mode 100644 l4/pkg/cxx/lib/tl/include/arith create mode 100644 l4/pkg/cxx/lib/tl/include/auto_ptr create mode 100644 l4/pkg/cxx/lib/tl/include/avl_map create mode 100644 l4/pkg/cxx/lib/tl/include/avl_set create mode 100644 l4/pkg/cxx/lib/tl/include/avl_tree create mode 100644 l4/pkg/cxx/lib/tl/include/basic_vector.h create mode 100644 l4/pkg/cxx/lib/tl/include/bitmap create mode 100644 l4/pkg/cxx/lib/tl/include/bits/bst.h create mode 100644 l4/pkg/cxx/lib/tl/include/bits/bst_base.h create mode 100644 l4/pkg/cxx/lib/tl/include/bits/bst_iter.h create mode 100644 l4/pkg/cxx/lib/tl/include/bits/list_basics.h create mode 100644 l4/pkg/cxx/lib/tl/include/bits/type_traits.h create mode 100644 l4/pkg/cxx/lib/tl/include/dlist create mode 100644 l4/pkg/cxx/lib/tl/include/hlist create mode 100644 l4/pkg/cxx/lib/tl/include/list create mode 100644 l4/pkg/cxx/lib/tl/include/list_alloc create mode 100644 l4/pkg/cxx/lib/tl/include/minmax create mode 100644 l4/pkg/cxx/lib/tl/include/observer create mode 100644 l4/pkg/cxx/lib/tl/include/pair create mode 100644 l4/pkg/cxx/lib/tl/include/ref_ptr create mode 100644 l4/pkg/cxx/lib/tl/include/slab_alloc create mode 100644 l4/pkg/cxx/lib/tl/include/slist create mode 100644 l4/pkg/cxx/lib/tl/include/static_container create mode 100644 l4/pkg/cxx/lib/tl/include/std_alloc create mode 100644 l4/pkg/cxx/lib/tl/include/std_ops create mode 100644 l4/pkg/cxx/lib/tl/include/type_traits create mode 100644 l4/pkg/cxx/lib/tl/test/Makefile create mode 100644 l4/pkg/cxx/lib/tl/test/avl_tree_test.cc create mode 100644 l4/pkg/cxx/lib/tl/test/avl_tree_test.reference create mode 100644 l4/pkg/cxx/lib/util/Makefile create mode 100644 l4/pkg/cxx/lib/util/include/Makefile create mode 100644 l4/pkg/cxx/lib/util/include/alloc.h create mode 100644 l4/pkg/cxx/lib/util/include/atomic.h create mode 100644 l4/pkg/cxx/lib/util/include/l4types.h create mode 100644 l4/pkg/cxx/lib/util/include/string.h create mode 100644 l4/pkg/cxx/lib/util/src/Makefile create mode 100644 l4/pkg/cxx/lib/util/src/alloc_list.cc create mode 100644 l4/pkg/cxx/lib/util/src/ipc_error_str.cc create mode 100644 l4/pkg/drivers-frst/Control create mode 100644 l4/pkg/drivers-frst/Makefile create mode 100644 l4/pkg/drivers-frst/hpet/Makefile create mode 100644 l4/pkg/drivers-frst/hpet/include/Makefile create mode 100644 l4/pkg/drivers-frst/hpet/include/hpet create mode 100644 l4/pkg/drivers-frst/hpet/src/Makefile create mode 100644 l4/pkg/drivers-frst/hpet/src/hpet.cc create mode 100644 l4/pkg/drivers-frst/include/Makefile create mode 100644 l4/pkg/drivers-frst/include/io_regblock.h create mode 100644 l4/pkg/drivers-frst/include/io_regblock_port.h create mode 100644 l4/pkg/drivers-frst/nand/Makefile create mode 100644 l4/pkg/drivers-frst/nand/include/Makefile create mode 100644 l4/pkg/drivers-frst/nand/include/lib_nand.h create mode 100644 l4/pkg/drivers-frst/nand/include/transfer.h create mode 100644 l4/pkg/drivers-frst/nand/src/Makefile create mode 100644 l4/pkg/drivers-frst/nand/src/common.h create mode 100644 l4/pkg/drivers-frst/nand/src/gpmc.cc create mode 100644 l4/pkg/drivers-frst/nand/src/gpmc.h create mode 100644 l4/pkg/drivers-frst/nand/src/lib_nand.cc create mode 100644 l4/pkg/drivers-frst/nand/src/mpc5121.cc create mode 100644 l4/pkg/drivers-frst/nand/src/mpc5121.h create mode 100644 l4/pkg/drivers-frst/nand/src/nand.cc create mode 100644 l4/pkg/drivers-frst/nand/src/nand.h create mode 100644 l4/pkg/drivers-frst/nand/src/nand_ids.cc create mode 100644 l4/pkg/drivers-frst/nand/src/types.h create mode 100644 l4/pkg/drivers-frst/of/Makefile create mode 100644 l4/pkg/drivers-frst/of/include/Makefile create mode 100644 l4/pkg/drivers-frst/of/include/of.h create mode 100644 l4/pkg/drivers-frst/of/include/of_dev.h create mode 100644 l4/pkg/drivers-frst/of/include/of_if.h create mode 100644 l4/pkg/drivers-frst/of/src/Makefile create mode 100644 l4/pkg/drivers-frst/of/src/of.cc create mode 100644 l4/pkg/drivers-frst/uart/Makefile create mode 100644 l4/pkg/drivers-frst/uart/include/Makefile create mode 100644 l4/pkg/drivers-frst/uart/include/uart_base.h create mode 100644 l4/pkg/drivers-frst/uart/include/uart_dcc-v6.h create mode 100644 l4/pkg/drivers-frst/uart/include/uart_dummy.h create mode 100644 l4/pkg/drivers-frst/uart/include/uart_imx.h create mode 100644 l4/pkg/drivers-frst/uart/include/uart_leon3.h create mode 100644 l4/pkg/drivers-frst/uart/include/uart_of.h create mode 100644 l4/pkg/drivers-frst/uart/include/uart_omap35x.h create mode 100644 l4/pkg/drivers-frst/uart/include/uart_pl011.h create mode 100644 l4/pkg/drivers-frst/uart/include/uart_pxa.h create mode 100644 l4/pkg/drivers-frst/uart/include/uart_s3c2410.h create mode 100644 l4/pkg/drivers-frst/uart/include/uart_sa1000.h create mode 100644 l4/pkg/drivers-frst/uart/src/Makefile create mode 100644 l4/pkg/drivers-frst/uart/src/uart_dcc-v6.cc create mode 100644 l4/pkg/drivers-frst/uart/src/uart_dummy.cc create mode 100644 l4/pkg/drivers-frst/uart/src/uart_imx.cc create mode 100644 l4/pkg/drivers-frst/uart/src/uart_leon3.cc create mode 100644 l4/pkg/drivers-frst/uart/src/uart_of.cc create mode 100644 l4/pkg/drivers-frst/uart/src/uart_omap35x.cc create mode 100644 l4/pkg/drivers-frst/uart/src/uart_pl011.cc create mode 100644 l4/pkg/drivers-frst/uart/src/uart_pxa.cc create mode 100644 l4/pkg/drivers-frst/uart/src/uart_s3c2410.cc create mode 100644 l4/pkg/drivers-frst/uart/src/uart_sa1000.cc create mode 100644 l4/pkg/l4sys/Control create mode 100644 l4/pkg/l4sys/LEGAL create mode 100644 l4/pkg/l4sys/Makefile create mode 100644 l4/pkg/l4sys/README create mode 100644 l4/pkg/l4sys/doc/files.cfg create mode 100644 l4/pkg/l4sys/doc/l4sys-l4f-groups.dox create mode 100644 l4/pkg/l4sys/include/ARCH-amd64/L4API-l4f/__kernel_object_impl.h create mode 100644 l4/pkg/l4sys/include/ARCH-amd64/L4API-l4f/ipc-l42-gcc3.h create mode 100644 l4/pkg/l4sys/include/ARCH-amd64/L4API-l4f/ipc.h create mode 100644 l4/pkg/l4sys/include/ARCH-amd64/L4API-l4f/ktrace.h create mode 100644 l4/pkg/l4sys/include/ARCH-amd64/L4API-l4f/segment.h create mode 100644 l4/pkg/l4sys/include/ARCH-amd64/L4API-l4f/types.h create mode 100644 l4/pkg/l4sys/include/ARCH-amd64/__vcpu-arch.h create mode 100644 l4/pkg/l4sys/include/ARCH-amd64/cache.h create mode 100644 l4/pkg/l4sys/include/ARCH-amd64/consts.h create mode 100644 l4/pkg/l4sys/include/ARCH-amd64/ipc-invoke.h create mode 100644 l4/pkg/l4sys/include/ARCH-amd64/kdebug.h create mode 100644 l4/pkg/l4sys/include/ARCH-amd64/l4int.h create mode 100644 l4/pkg/l4sys/include/ARCH-amd64/linkage.h create mode 100644 l4/pkg/l4sys/include/ARCH-amd64/segment.h create mode 100644 l4/pkg/l4sys/include/ARCH-amd64/utcb.h create mode 100644 l4/pkg/l4sys/include/ARCH-amd64/vm create mode 100644 l4/pkg/l4sys/include/ARCH-amd64/vm.h create mode 100644 l4/pkg/l4sys/include/ARCH-arm/L4API-l4f/__kernel_object_impl.h create mode 100644 l4/pkg/l4sys/include/ARCH-arm/L4API-l4f/ipc.h create mode 100644 l4/pkg/l4sys/include/ARCH-arm/L4API-l4f/syscall_defs.h create mode 100644 l4/pkg/l4sys/include/ARCH-arm/__vcpu-arch.h create mode 100644 l4/pkg/l4sys/include/ARCH-arm/atomic.h create mode 100644 l4/pkg/l4sys/include/ARCH-arm/cache.h create mode 100644 l4/pkg/l4sys/include/ARCH-arm/consts.h create mode 100644 l4/pkg/l4sys/include/ARCH-arm/kdebug.h create mode 100644 l4/pkg/l4sys/include/ARCH-arm/ktrace.h create mode 100644 l4/pkg/l4sys/include/ARCH-arm/l4int.h create mode 100644 l4/pkg/l4sys/include/ARCH-arm/linkage.h create mode 100644 l4/pkg/l4sys/include/ARCH-arm/mem_op.h create mode 100644 l4/pkg/l4sys/include/ARCH-arm/rt_sched.h create mode 100644 l4/pkg/l4sys/include/ARCH-arm/types.h create mode 100644 l4/pkg/l4sys/include/ARCH-arm/utcb.h create mode 100644 l4/pkg/l4sys/include/ARCH-arm/vm create mode 100644 l4/pkg/l4sys/include/ARCH-arm/vm.h create mode 100644 l4/pkg/l4sys/include/ARCH-ppc32/L4API-l4f/__kernel_object_impl.h create mode 100644 l4/pkg/l4sys/include/ARCH-ppc32/L4API-l4f/ipc.h create mode 100644 l4/pkg/l4sys/include/ARCH-ppc32/__vcpu-arch.h create mode 100644 l4/pkg/l4sys/include/ARCH-ppc32/atomic.h create mode 100644 l4/pkg/l4sys/include/ARCH-ppc32/cache.h create mode 100644 l4/pkg/l4sys/include/ARCH-ppc32/consts.h create mode 100644 l4/pkg/l4sys/include/ARCH-ppc32/kdebug.h create mode 100644 l4/pkg/l4sys/include/ARCH-ppc32/l4int.h create mode 100644 l4/pkg/l4sys/include/ARCH-ppc32/linkage.h create mode 100644 l4/pkg/l4sys/include/ARCH-ppc32/types.h create mode 100644 l4/pkg/l4sys/include/ARCH-ppc32/utcb.h create mode 100644 l4/pkg/l4sys/include/ARCH-sparc/L4API-l4f/__kernel_object_impl.h create mode 100644 l4/pkg/l4sys/include/ARCH-sparc/L4API-l4f/ipc.h create mode 100644 l4/pkg/l4sys/include/ARCH-sparc/L4API-l4f/syscall_defs.h create mode 100644 l4/pkg/l4sys/include/ARCH-sparc/__vcpu-arch.h create mode 100644 l4/pkg/l4sys/include/ARCH-sparc/atomic.h create mode 100644 l4/pkg/l4sys/include/ARCH-sparc/cache.h create mode 100644 l4/pkg/l4sys/include/ARCH-sparc/consts.h create mode 100644 l4/pkg/l4sys/include/ARCH-sparc/kdebug.h create mode 100644 l4/pkg/l4sys/include/ARCH-sparc/l4int.h create mode 100644 l4/pkg/l4sys/include/ARCH-sparc/linkage.h create mode 100644 l4/pkg/l4sys/include/ARCH-sparc/types.h create mode 100644 l4/pkg/l4sys/include/ARCH-sparc/utcb.h create mode 100644 l4/pkg/l4sys/include/ARCH-x86/L4API-l4f/__kernel_object_impl.h create mode 100644 l4/pkg/l4sys/include/ARCH-x86/L4API-l4f/ipc-l42-gcc3-nopic.h create mode 100644 l4/pkg/l4sys/include/ARCH-x86/L4API-l4f/ipc.h create mode 100644 l4/pkg/l4sys/include/ARCH-x86/L4API-l4f/segment.h create mode 100644 l4/pkg/l4sys/include/ARCH-x86/L4API-l4f/types.h create mode 100644 l4/pkg/l4sys/include/ARCH-x86/__vcpu-arch.h create mode 100644 l4/pkg/l4sys/include/ARCH-x86/cache.h create mode 100644 l4/pkg/l4sys/include/ARCH-x86/consts.h create mode 100644 l4/pkg/l4sys/include/ARCH-x86/ipc-invoke.h create mode 100644 l4/pkg/l4sys/include/ARCH-x86/kdebug.h create mode 100644 l4/pkg/l4sys/include/ARCH-x86/ktrace.h create mode 100644 l4/pkg/l4sys/include/ARCH-x86/ktrace_events.h create mode 100644 l4/pkg/l4sys/include/ARCH-x86/l4int.h create mode 100644 l4/pkg/l4sys/include/ARCH-x86/linkage.h create mode 100644 l4/pkg/l4sys/include/ARCH-x86/rt_sched-impl.h create mode 100644 l4/pkg/l4sys/include/ARCH-x86/rt_sched-proto.h create mode 100644 l4/pkg/l4sys/include/ARCH-x86/rt_sched.h create mode 100644 l4/pkg/l4sys/include/ARCH-x86/segment.h create mode 100644 l4/pkg/l4sys/include/ARCH-x86/syscall-invoke.h create mode 100644 l4/pkg/l4sys/include/ARCH-x86/utcb.h create mode 100644 l4/pkg/l4sys/include/ARCH-x86/vm create mode 100644 l4/pkg/l4sys/include/ARCH-x86/vm.h create mode 100644 l4/pkg/l4sys/include/L4API-l4f/ipc-impl.h create mode 100644 l4/pkg/l4sys/include/Makefile create mode 100644 l4/pkg/l4sys/include/__kip-32bit.h create mode 100644 l4/pkg/l4sys/include/__kip-64bit.h create mode 100644 l4/pkg/l4sys/include/__l4_fpage.h create mode 100644 l4/pkg/l4sys/include/__timeout.h create mode 100644 l4/pkg/l4sys/include/__typeinfo.h create mode 100644 l4/pkg/l4sys/include/__vm create mode 100644 l4/pkg/l4sys/include/__vm-svm.h create mode 100644 l4/pkg/l4sys/include/__vm-vmx.h create mode 100644 l4/pkg/l4sys/include/__vm.h create mode 100644 l4/pkg/l4sys/include/cache.h create mode 100644 l4/pkg/l4sys/include/capability create mode 100644 l4/pkg/l4sys/include/compiler.h create mode 100644 l4/pkg/l4sys/include/consts.h create mode 100644 l4/pkg/l4sys/include/debugger create mode 100644 l4/pkg/l4sys/include/debugger.h create mode 100644 l4/pkg/l4sys/include/err.h create mode 100644 l4/pkg/l4sys/include/factory create mode 100644 l4/pkg/l4sys/include/factory.h create mode 100644 l4/pkg/l4sys/include/icu create mode 100644 l4/pkg/l4sys/include/icu.h create mode 100644 l4/pkg/l4sys/include/ipc.h create mode 100644 l4/pkg/l4sys/include/ipc_gate create mode 100644 l4/pkg/l4sys/include/ipc_gate.h create mode 100644 l4/pkg/l4sys/include/irq create mode 100644 l4/pkg/l4sys/include/irq.h create mode 100644 l4/pkg/l4sys/include/kernel_object.h create mode 100644 l4/pkg/l4sys/include/kip create mode 100644 l4/pkg/l4sys/include/kip.h create mode 100644 l4/pkg/l4sys/include/l4int.h create mode 100644 l4/pkg/l4sys/include/memdesc.h create mode 100644 l4/pkg/l4sys/include/meta create mode 100644 l4/pkg/l4sys/include/scheduler create mode 100644 l4/pkg/l4sys/include/scheduler.h create mode 100644 l4/pkg/l4sys/include/smart_capability create mode 100644 l4/pkg/l4sys/include/task create mode 100644 l4/pkg/l4sys/include/task.h create mode 100644 l4/pkg/l4sys/include/thread create mode 100644 l4/pkg/l4sys/include/thread.h create mode 100644 l4/pkg/l4sys/include/typeinfo_svr create mode 100644 l4/pkg/l4sys/include/types.h create mode 100644 l4/pkg/l4sys/include/utcb.h create mode 100644 l4/pkg/l4sys/include/vcon create mode 100644 l4/pkg/l4sys/include/vcon.h create mode 100644 l4/pkg/l4sys/include/vcpu.h create mode 100644 l4/pkg/l4sys/include/vhw.h create mode 100644 l4/pkg/l4sys/lib/Makefile create mode 100644 l4/pkg/l4sys/lib/src/ARCH-amd64/syscalls_direct.S create mode 100644 l4/pkg/l4sys/lib/src/ARCH-arm/atomic_ops_s.S create mode 100644 l4/pkg/l4sys/lib/src/ARCH-ppc32/atomic_ops.c create mode 100644 l4/pkg/l4sys/lib/src/ARCH-sparc/atomic_ops.S create mode 100644 l4/pkg/l4sys/lib/src/ARCH-x86/syscalls_direct.S create mode 100644 l4/pkg/l4sys/lib/src/ARCH-x86/utcb-l4x.c create mode 100644 l4/pkg/l4sys/lib/src/Makefile create mode 100644 l4/pkg/l4sys/lib/src/errtostr.c create mode 100644 l4/pkg/l4sys/lib/src/kobject.cc create mode 100644 l4/pkg/l4sys/lib/src/utcb.c create mode 100644 l4/pkg/l4util/Control create mode 100644 l4/pkg/l4util/LEGAL create mode 100644 l4/pkg/l4util/Makefile create mode 100644 l4/pkg/l4util/README create mode 100644 l4/pkg/l4util/doc/Makefile create mode 100644 l4/pkg/l4util/doc/files.cfg create mode 100644 l4/pkg/l4util/doc/footer.html create mode 100644 l4/pkg/l4util/doc/header.html create mode 100644 l4/pkg/l4util/doc/l4util.cfg create mode 100644 l4/pkg/l4util/doc/l4util.dox create mode 100644 l4/pkg/l4util/include/ARCH-amd64/L4API-l4f/l4_macros.h create mode 100644 l4/pkg/l4util/include/ARCH-amd64/L4API-l4f/port_io.h create mode 100644 l4/pkg/l4util/include/ARCH-amd64/L4API-l4f/setjmp.h create mode 100644 l4/pkg/l4util/include/ARCH-amd64/apic.h create mode 100644 l4/pkg/l4util/include/ARCH-amd64/atomic_arch.h create mode 100644 l4/pkg/l4util/include/ARCH-amd64/bitops_arch.h create mode 100644 l4/pkg/l4util/include/ARCH-amd64/cpu.h create mode 100644 l4/pkg/l4util/include/ARCH-amd64/idt.h create mode 100644 l4/pkg/l4util/include/ARCH-amd64/irq.h create mode 100644 l4/pkg/l4util/include/ARCH-amd64/l4_macros.h create mode 100644 l4/pkg/l4util/include/ARCH-amd64/mbi_argv.h create mode 100644 l4/pkg/l4util/include/ARCH-amd64/perform.h create mode 100644 l4/pkg/l4util/include/ARCH-amd64/port_io.h create mode 100644 l4/pkg/l4util/include/ARCH-amd64/rdtsc.h create mode 100644 l4/pkg/l4util/include/ARCH-amd64/spin.h create mode 100644 l4/pkg/l4util/include/ARCH-amd64/stack_impl.h create mode 100644 l4/pkg/l4util/include/ARCH-amd64/util.h create mode 100644 l4/pkg/l4util/include/ARCH-arm/L4API-l4f/l4_macros.h create mode 100644 l4/pkg/l4util/include/ARCH-arm/atomic_arch.h create mode 100644 l4/pkg/l4util/include/ARCH-arm/bitops_arch.h create mode 100644 l4/pkg/l4util/include/ARCH-arm/cpu.h create mode 100644 l4/pkg/l4util/include/ARCH-arm/irq.h create mode 100644 l4/pkg/l4util/include/ARCH-arm/l4_macros.h create mode 100644 l4/pkg/l4util/include/ARCH-arm/mbi_argv.h create mode 100644 l4/pkg/l4util/include/ARCH-arm/stack_impl.h create mode 100644 l4/pkg/l4util/include/ARCH-ppc32/L4API-l4f/l4_macros.h create mode 100644 l4/pkg/l4util/include/ARCH-ppc32/atomic_arch.h create mode 100644 l4/pkg/l4util/include/ARCH-ppc32/bitops_arch.h create mode 100644 l4/pkg/l4util/include/ARCH-ppc32/irq.h create mode 100644 l4/pkg/l4util/include/ARCH-ppc32/l4_macros.h create mode 100644 l4/pkg/l4util/include/ARCH-ppc32/rdtsc.h create mode 100644 l4/pkg/l4util/include/ARCH-ppc32/stack_impl.h create mode 100644 l4/pkg/l4util/include/ARCH-sparc/L4API-l4f/l4_macros.h create mode 100644 l4/pkg/l4util/include/ARCH-sparc/atomic_arch.h create mode 100644 l4/pkg/l4util/include/ARCH-sparc/bitops_arch.h create mode 100644 l4/pkg/l4util/include/ARCH-sparc/irq.h create mode 100644 l4/pkg/l4util/include/ARCH-sparc/l4_macros.h create mode 100644 l4/pkg/l4util/include/ARCH-sparc/stack_impl.h create mode 100644 l4/pkg/l4util/include/ARCH-x86/L4API-l4f/l4_macros.h create mode 100644 l4/pkg/l4util/include/ARCH-x86/L4API-l4f/port_io.h create mode 100644 l4/pkg/l4util/include/ARCH-x86/L4API-l4f/setjmp.h create mode 100644 l4/pkg/l4util/include/ARCH-x86/apic.h create mode 100644 l4/pkg/l4util/include/ARCH-x86/atomic_arch.h create mode 100644 l4/pkg/l4util/include/ARCH-x86/bitops_arch.h create mode 100644 l4/pkg/l4util/include/ARCH-x86/cpu.h create mode 100644 l4/pkg/l4util/include/ARCH-x86/idt.h create mode 100644 l4/pkg/l4util/include/ARCH-x86/irq.h create mode 100644 l4/pkg/l4util/include/ARCH-x86/l4_macros.h create mode 100644 l4/pkg/l4util/include/ARCH-x86/mbi_argv.h create mode 100644 l4/pkg/l4util/include/ARCH-x86/perform.h create mode 100644 l4/pkg/l4util/include/ARCH-x86/port_io.h create mode 100644 l4/pkg/l4util/include/ARCH-x86/rdtsc.h create mode 100644 l4/pkg/l4util/include/ARCH-x86/spin.h create mode 100644 l4/pkg/l4util/include/ARCH-x86/stack_impl.h create mode 100644 l4/pkg/l4util/include/ARCH-x86/util.h create mode 100644 l4/pkg/l4util/include/Makefile create mode 100644 l4/pkg/l4util/include/alloc.h create mode 100644 l4/pkg/l4util/include/assert.h create mode 100644 l4/pkg/l4util/include/atomic.h create mode 100644 l4/pkg/l4util/include/backtrace.h create mode 100644 l4/pkg/l4util/include/base64.h create mode 100644 l4/pkg/l4util/include/bitops.h create mode 100644 l4/pkg/l4util/include/elf.h create mode 100644 l4/pkg/l4util/include/getopt.h create mode 100644 l4/pkg/l4util/include/keymap.h create mode 100644 l4/pkg/l4util/include/kip.h create mode 100644 l4/pkg/l4util/include/kprintf.h create mode 100644 l4/pkg/l4util/include/list_alloc.h create mode 100644 l4/pkg/l4util/include/llulc.h create mode 100644 l4/pkg/l4util/include/lock.h create mode 100644 l4/pkg/l4util/include/lock_wq.h create mode 100644 l4/pkg/l4util/include/macros.h create mode 100644 l4/pkg/l4util/include/mb_info.h create mode 100644 l4/pkg/l4util/include/parse_cmd.h create mode 100644 l4/pkg/l4util/include/prio.h create mode 100644 l4/pkg/l4util/include/queue.h create mode 100644 l4/pkg/l4util/include/rand.h create mode 100644 l4/pkg/l4util/include/reboot.h create mode 100644 l4/pkg/l4util/include/sll.h create mode 100644 l4/pkg/l4util/include/slmap.h create mode 100644 l4/pkg/l4util/include/splitlog2.h create mode 100644 l4/pkg/l4util/include/stack.h create mode 100644 l4/pkg/l4util/include/thread.h create mode 100644 l4/pkg/l4util/include/util.h create mode 100644 l4/pkg/l4util/lib/Makefile create mode 100644 l4/pkg/l4util/lib/src/ARCH-amd64/apic.c create mode 100644 l4/pkg/l4util/lib/src/ARCH-amd64/backtrace.c create mode 100644 l4/pkg/l4util/lib/src/ARCH-amd64/perform.c create mode 100644 l4/pkg/l4util/lib/src/ARCH-amd64/pmc_events.in create mode 100644 l4/pkg/l4util/lib/src/ARCH-amd64/setjmp.c create mode 100644 l4/pkg/l4util/lib/src/ARCH-amd64/spin.c create mode 100644 l4/pkg/l4util/lib/src/ARCH-arm/backtrace.c create mode 100644 l4/pkg/l4util/lib/src/ARCH-ppc32/backtrace.c create mode 100644 l4/pkg/l4util/lib/src/ARCH-ppc32/rdtsc.c create mode 100644 l4/pkg/l4util/lib/src/ARCH-sparc/backtrace.c create mode 100644 l4/pkg/l4util/lib/src/ARCH-x86/apic.c create mode 100644 l4/pkg/l4util/lib/src/ARCH-x86/backtrace.c create mode 100644 l4/pkg/l4util/lib/src/ARCH-x86/perform.c create mode 100644 l4/pkg/l4util/lib/src/ARCH-x86/pmc_events.in create mode 100644 l4/pkg/l4util/lib/src/ARCH-x86/rdtsc.c create mode 100644 l4/pkg/l4util/lib/src/ARCH-x86/setjmp.c create mode 100644 l4/pkg/l4util/lib/src/ARCH-x86/spin.c create mode 100644 l4/pkg/l4util/lib/src/Makefile create mode 100644 l4/pkg/l4util/lib/src/__main.c create mode 100644 l4/pkg/l4util/lib/src/alloc.c create mode 100644 l4/pkg/l4util/lib/src/base64.c create mode 100644 l4/pkg/l4util/lib/src/getopt2.c create mode 100644 l4/pkg/l4util/lib/src/keymap.c create mode 100644 l4/pkg/l4util/lib/src/keymap_de.h create mode 100644 l4/pkg/l4util/lib/src/keymap_en.h create mode 100644 l4/pkg/l4util/lib/src/kip.c create mode 100644 l4/pkg/l4util/lib/src/kprintf.c create mode 100644 l4/pkg/l4util/lib/src/list_alloc.c create mode 100644 l4/pkg/l4util/lib/src/llulc.cc create mode 100644 l4/pkg/l4util/lib/src/memdesc.c create mode 100644 l4/pkg/l4util/lib/src/micros2l4to.c create mode 100644 l4/pkg/l4util/lib/src/parse_cmdline.c create mode 100644 l4/pkg/l4util/lib/src/queue.c create mode 100644 l4/pkg/l4util/lib/src/rand.c create mode 100644 l4/pkg/l4util/lib/src/reboot.c create mode 100644 l4/pkg/l4util/lib/src/sleep.c create mode 100644 l4/pkg/l4util/lib/src/slmap.c create mode 100644 l4/pkg/l4util/lib/src/thread.c create mode 100644 l4/pkg/ldscripts/ARCH-amd64/main_dyn.ld create mode 100644 l4/pkg/ldscripts/ARCH-amd64/main_rel.ld create mode 100644 l4/pkg/ldscripts/ARCH-amd64/main_stat.ld create mode 100644 l4/pkg/ldscripts/ARCH-arm/bits/arm_asm.h create mode 100644 l4/pkg/ldscripts/ARCH-arm/main_dyn.ld create mode 100644 l4/pkg/ldscripts/ARCH-arm/main_rel.ld create mode 100644 l4/pkg/ldscripts/ARCH-arm/main_stat.ld create mode 100644 l4/pkg/ldscripts/ARCH-ppc32/main_dyn.ld create mode 100644 l4/pkg/ldscripts/ARCH-ppc32/main_rel.ld create mode 100644 l4/pkg/ldscripts/ARCH-ppc32/main_stat.ld create mode 100644 l4/pkg/ldscripts/ARCH-sparc/bits/wordsize.h create mode 100644 l4/pkg/ldscripts/ARCH-sparc/main_dyn.ld create mode 100644 l4/pkg/ldscripts/ARCH-sparc/main_rel.ld create mode 100644 l4/pkg/ldscripts/ARCH-sparc/main_stat.ld create mode 100644 l4/pkg/ldscripts/ARCH-x86/main_dyn.ld create mode 100644 l4/pkg/ldscripts/ARCH-x86/main_rel.ld create mode 100644 l4/pkg/ldscripts/ARCH-x86/main_stat.ld create mode 100644 l4/pkg/ldscripts/Control create mode 100644 l4/pkg/ldscripts/Makefile create mode 100644 l4/pkg/ldscripts/features.h create mode 100644 l4/pkg/ldscripts/generic.h create mode 100644 l4/pkg/ldscripts/kip_addr.c create mode 100644 l4/pkg/libgcc-pure/Control create mode 100644 l4/pkg/libgcc-pure/Makefile create mode 100644 l4/pkg/libgcc-pure/lib/Makefile create mode 100644 l4/pkg/libgcc/Control create mode 100644 l4/pkg/libgcc/Makefile create mode 100644 l4/pkg/libgcc/lib/ARCH-arm/l4-atomic-64bit.c create mode 100644 l4/pkg/libgcc/lib/ARCH-arm/l4-atomic.c create mode 100644 l4/pkg/libgcc/lib/Makefile create mode 100644 l4/pkg/libgcc/lib/Makefile.libgcc create mode 100644 l4/pkg/libsigma0/Control create mode 100644 l4/pkg/libsigma0/LEGAL create mode 100644 l4/pkg/libsigma0/Makefile create mode 100644 l4/pkg/libsigma0/doc/Makefile create mode 100644 l4/pkg/libsigma0/doc/files.cfg create mode 100644 l4/pkg/libsigma0/doc/libsigma0.cfg create mode 100644 l4/pkg/libsigma0/include/Makefile create mode 100644 l4/pkg/libsigma0/include/sigma0.h create mode 100644 l4/pkg/libsigma0/lib/Makefile create mode 100644 l4/pkg/libsigma0/lib/src/Makefile create mode 100644 l4/pkg/libsigma0/lib/src/anypage.c create mode 100644 l4/pkg/libsigma0/lib/src/client.c create mode 100644 l4/pkg/libsigma0/lib/src/debug.c create mode 100644 l4/pkg/libsigma0/lib/src/iomem.c create mode 100644 l4/pkg/libsigma0/lib/src/kip.c create mode 100644 l4/pkg/libsigma0/lib/src/mem.c create mode 100644 l4/pkg/libsigma0/lib/src/tbuf.c create mode 100644 l4/pkg/libvcpu/Control create mode 100644 l4/pkg/libvcpu/Makefile create mode 100644 l4/pkg/libvcpu/doc/files.cfg create mode 100644 l4/pkg/libvcpu/include/ARCH-amd64/vcpu_arch.h create mode 100644 l4/pkg/libvcpu/include/ARCH-arm/vcpu_arch.h create mode 100644 l4/pkg/libvcpu/include/ARCH-ppc32/vcpu_arch.h create mode 100644 l4/pkg/libvcpu/include/ARCH-sparc/vcpu_arch.h create mode 100644 l4/pkg/libvcpu/include/ARCH-x86/vcpu_arch.h create mode 100644 l4/pkg/libvcpu/include/Makefile create mode 100644 l4/pkg/libvcpu/include/vcpu create mode 100644 l4/pkg/libvcpu/include/vcpu.h create mode 100644 l4/pkg/libvcpu/lib/Makefile create mode 100644 l4/pkg/libvcpu/lib/src/ARCH-amd64/arch.cc create mode 100644 l4/pkg/libvcpu/lib/src/ARCH-arm/arch.cc create mode 100644 l4/pkg/libvcpu/lib/src/ARCH-ppc32/arch.cc create mode 100644 l4/pkg/libvcpu/lib/src/ARCH-sparc/arch.cc create mode 100644 l4/pkg/libvcpu/lib/src/ARCH-x86/arch.cc create mode 100644 l4/pkg/libvcpu/lib/src/Makefile create mode 100644 l4/pkg/libvcpu/lib/src/vcpu.cc create mode 100644 l4/pkg/sigma0/Control create mode 100644 l4/pkg/sigma0/Makefile create mode 100644 l4/pkg/sigma0/server/Makefile create mode 100644 l4/pkg/sigma0/server/src/ARCH-amd64/crt0.S create mode 100644 l4/pkg/sigma0/server/src/ARCH-arm/crt0.S create mode 100644 l4/pkg/sigma0/server/src/ARCH-ppc32/crt0.S create mode 100644 l4/pkg/sigma0/server/src/ARCH-sparc/crt0.S create mode 100644 l4/pkg/sigma0/server/src/ARCH-x86/crt0.S create mode 100644 l4/pkg/sigma0/server/src/Makefile create mode 100644 l4/pkg/sigma0/server/src/globals.h create mode 100644 l4/pkg/sigma0/server/src/init.cc create mode 100644 l4/pkg/sigma0/server/src/init.h create mode 100644 l4/pkg/sigma0/server/src/init_mem.cc create mode 100644 l4/pkg/sigma0/server/src/init_mem.h create mode 100644 l4/pkg/sigma0/server/src/io_backend.cc create mode 100644 l4/pkg/sigma0/server/src/ioports.h create mode 100644 l4/pkg/sigma0/server/src/ioports_none.cc create mode 100644 l4/pkg/sigma0/server/src/ioports_x86.cc create mode 100644 l4/pkg/sigma0/server/src/mem_man.cc create mode 100644 l4/pkg/sigma0/server/src/mem_man.h create mode 100644 l4/pkg/sigma0/server/src/mem_man_test.cc create mode 100644 l4/pkg/sigma0/server/src/mem_man_test.h create mode 100644 l4/pkg/sigma0/server/src/memmap.cc create mode 100644 l4/pkg/sigma0/server/src/memmap.h create mode 100644 l4/pkg/sigma0/server/src/memmap_internal.h create mode 100644 l4/pkg/sigma0/server/src/page_alloc.cc create mode 100644 l4/pkg/sigma0/server/src/page_alloc.h create mode 100644 l4/pkg/sigma0/server/src/region.h create mode 100644 l4/pkg/sigma0/server/src/support.c create mode 100644 l4/pkg/uclibc-headers/Control create mode 100644 l4/pkg/uclibc-headers/Makefile create mode 100644 l4/pkg/uclibc-minimal/Control create mode 100644 l4/pkg/uclibc-minimal/Makefile create mode 100644 l4/pkg/uclibc-minimal/libc/Make.rules create mode 100644 l4/pkg/uclibc-minimal/libc/Makefile create mode 100644 l4/pkg/uclibc/Control create mode 100644 l4/pkg/uclibc/LEGAL create mode 100644 l4/pkg/uclibc/Makefile create mode 100644 l4/pkg/uclibc/README.L4 create mode 100644 l4/pkg/uclibc/doc/Makefile create mode 100644 l4/pkg/uclibc/doc/general.dox create mode 100644 l4/pkg/uclibc/doc/uclibc.cfg create mode 100644 l4/pkg/uclibc/lib/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/.gitignore create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/COPYING.LIB create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/COPYING.LIB.boilerplate create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/Changelog create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/DEDICATION.mjn3 create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/INSTALL create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/MAINTAINERS create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/Makefile.help create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/Makerules create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/README create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/Rules.mak create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/TODO create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/docs/Glibc_vs_uClibc_Differences.txt create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/docs/PORTING create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/docs/defines.txt create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/docs/man/ldconfig.8 create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/docs/man/ldd.1 create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/docs/probe_math_exception.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/docs/pthreads_hacking.txt create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/docs/sigaction.txt create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/docs/threads.txt create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/docs/uClibc_vs_SuSv3.txt create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/docs/wchar_and_locale.txt create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.alpha create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.arm create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.avr32 create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.bfin create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.cris create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.e1 create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.frv create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.h8300 create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.hppa create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.i386 create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.i960 create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.ia64 create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.in.arch create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.m68k create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.microblaze create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.mips create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.nios create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.nios2 create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.powerpc create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.sh create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.sh64 create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.sparc create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.v850 create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.vax create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.x86_64 create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.xtensa create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/alpha create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/arm create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/avr32 create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/bfin create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/cris create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/e1 create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/frv create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/h8300 create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/hppa create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/i386 create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/i960 create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/ia64 create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/m68k create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/microblaze create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/mips create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/nios create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/nios2 create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/powerpc create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/sh create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/sh64 create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/sparc create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/v850 create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/vax create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/x86_64 create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/config/.gitignore create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/config/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/config/Makefile.kconfig create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/config/POTFILES.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/config/README.uClibc create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/config/check.sh create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/config/conf.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/config/confdata.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/config/expr.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/config/expr.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/config/gconf.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/config/gconf.glade create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/config/images.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/config/kconfig-language.txt create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/config/kconfig-to-uclibc.patch.gz create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/config/kconfig_load.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/config/kxgettext.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/config/lex.zconf.c_shipped create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/config/lkc.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/config/lkc_proto.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/config/lxdialog/.gitignore create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/config/lxdialog/BIG.FAT.WARNING create mode 100755 l4/pkg/uclibc/lib/contrib/uclibc/extra/config/lxdialog/check-lxdialog.sh create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/config/lxdialog/checklist.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/config/lxdialog/dialog.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/config/lxdialog/inputbox.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/config/lxdialog/menubox.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/config/lxdialog/textbox.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/config/lxdialog/util.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/config/lxdialog/yesno.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/config/mconf.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/config/menu.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/config/qconf.cc create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/config/qconf.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/config/symbol.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/config/util.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/config/zconf.gperf create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/config/zconf.hash.c_shipped create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/config/zconf.l create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/config/zconf.tab.c_shipped create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/config/zconf.y create mode 100755 l4/pkg/uclibc/lib/contrib/uclibc/extra/libstrip/libstrip create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/.gitignore create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/LOCALES create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/README create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/ARMSCII-8.pairs create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/ASCII.pairs create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/CP1251.pairs create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/CP1255.pairs create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/GEORGIAN-PS.pairs create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/ISO-8859-1.pairs create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/ISO-8859-10.pairs create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/ISO-8859-13.pairs create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/ISO-8859-14.pairs create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/ISO-8859-15.pairs create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/ISO-8859-16.pairs create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/ISO-8859-2.pairs create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/ISO-8859-3.pairs create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/ISO-8859-4.pairs create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/ISO-8859-5.pairs create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/ISO-8859-6.pairs create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/ISO-8859-7.pairs create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/ISO-8859-8.pairs create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/ISO-8859-9.pairs create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/KOI8-R.pairs create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/KOI8-T.pairs create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/KOI8-U.pairs create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/TIS-620.pairs create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/af_ZA create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/am_ET create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ar_AE create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ar_BH create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ar_DZ create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ar_EG create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ar_IN create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ar_IQ create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ar_JO create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ar_KW create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ar_LB create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ar_LY create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ar_MA create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ar_OM create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ar_QA create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ar_SA create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ar_SD create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ar_SY create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ar_TN create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ar_YE create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/az_AZ create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/be_BY create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/bg_BG create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/bn_BD create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/bn_IN create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/br_FR create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/bs_BA create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ca_ES create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/comm create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/cs_CZ create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/cy_GB create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/da_DK create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/de_AT create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/de_BE create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/de_CH create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/de_DE create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/de_LU create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/el_GR create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/en_AU create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/en_BW create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/en_CA create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/en_DK create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/en_GB create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/en_HK create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/en_IE create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/en_IN create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/en_NZ create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/en_PH create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/en_SG create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/en_US create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/en_ZA create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/en_ZW create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/eo_EO create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/es_AR create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/es_BO create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/es_CL create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/es_CO create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/es_CR create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/es_DO create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/es_EC create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/es_ES create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/es_GT create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/es_HN create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/es_MX create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/es_NI create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/es_PA create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/es_PE create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/es_PR create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/es_PY create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/es_SV create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/es_US create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/es_UY create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/es_VE create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/et_EE create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/eu_ES create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/fa_IR create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/fi_FI create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/fo_FO create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/fr_BE create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/fr_CA create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/fr_CH create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/fr_FR create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/fr_LU create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ga_IE create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/gd_GB create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/gl_ES create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/gv_GB create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/he_IL create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/hi_IN create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/hr_HR create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/hu_HU create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/hy_AM create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/id_ID create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/is_IS create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/iso14651_t1 create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/it_CH create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/it_IT create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/iw_IL create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ja_JP create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ka_GE create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/kl_GL create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ko_KR create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/kw_GB create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/lt_LT create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/lv_LV create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/mi_NZ create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/mk_MK create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/mr_IN create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ms_MY create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/mt_MT create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/nl_BE create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/nl_NL create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/nn_NO create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/no_NO create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/oc_FR create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/pl_PL create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/pt_BR create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/pt_PT create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ro_RO create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ru_RU create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ru_UA create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/se_NO create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/sk_SK create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/sl_SI create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/sq_AL create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/sr_YU create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/sv_FI create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/sv_SE create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ta_IN create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/te_IN create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/tg_TJ create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/th_TH create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ti_ER create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ti_ET create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/tl_PH create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/tr_TR create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/tt_RU create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/uk_UA create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ur_PK create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/uz_UZ create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/vi_VN create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/wa_BE create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/yi_US create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/zh_CN create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/zh_HK create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/zh_SG create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/zh_TW create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/gen_collate.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/gen_ldc.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/gen_locale.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/gen_mmap.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/gen_wc8bit.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/gen_wctype.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/lmmtolso.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/locale_mmap.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/programs/categories.def create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/programs/locale.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/tst_nl_langinfo.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/.gitignore create mode 100755 l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/MAKEALL create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/Makefile.arch.lvl3 create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/Makefile.arch.lvl4 create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/Makefile.libs.lvl0 create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/Makefile.libs.lvl1 create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/Makefile.libs.lvl2 create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/Makefile.objs.lvl2 create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/Makefile.objs.lvl3 create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/Makefile.objs.lvl4 create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/Makefile.utils.lvl1 create mode 100755 l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/conf-header.sh create mode 100755 l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/create_makefiles.sh create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/defs.awk create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/format.lds create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/gen-as-const.awk create mode 100755 l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/gen_bits_syscall_h.sh create mode 100755 l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/getent create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/install_headers.sh create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/randconfig.sh create mode 100755 l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/relative_path.sh create mode 100755 l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/relinfo.pl create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/unifdef.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/unifdef.test create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/.gitignore create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/_lfs_64.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/a.out.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/alloca.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/ar.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/arpa/ftp.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/arpa/inet.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/arpa/nameser.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/arpa/nameser_compat.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/arpa/telnet.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/arpa/tftp.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/assert.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/atomic.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/byteswap.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/complex.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/cpio.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/crypt.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/ctype.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/dirent.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/dlfcn.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/elf.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/endian.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/err.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/errno.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/error.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/execinfo.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/fcntl.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/features.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/fenv.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/fnmatch.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/ftw.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/getopt.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/glob.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/gnu-versions.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/grp.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/iconv.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/ieee754.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/ifaddrs.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/internal/parse_config.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/inttypes.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/langinfo.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/lastlog.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/libc-internal.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/libc-symbols.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/libgen.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/libintl.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/limits.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/link.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/locale.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/malloc.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/math.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/memory.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/mntent.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/mqueue.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/net/ethernet.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/net/if.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/net/if_arp.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/net/if_packet.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/net/if_ppp.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/net/if_shaper.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/net/if_slip.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/net/ppp-comp.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/net/ppp_defs.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/net/route.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/netax25/ax25.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/netdb.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/neteconet/ec.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/netinet/ether.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/netinet/icmp6.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/netinet/if_ether.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/netinet/if_fddi.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/netinet/if_tr.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/netinet/igmp.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/netinet/in.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/netinet/in_systm.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/netinet/ip.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/netinet/ip6.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/netinet/ip_icmp.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/netinet/tcp.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/netinet/udp.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/netipx/ipx.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/netpacket/packet.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/nl_types.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/obstack.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/paths.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/poll.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/printf.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/protocols/routed.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/protocols/rwhod.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/protocols/talkd.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/protocols/timed.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/pty.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/pwd.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/regex.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/regexp.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/resolv.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/rpc/auth.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/rpc/auth_des.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/rpc/auth_unix.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/rpc/clnt.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/rpc/des_crypt.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/rpc/key_prot.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/rpc/netdb.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/rpc/pmap_clnt.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/rpc/pmap_prot.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/rpc/pmap_rmt.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/rpc/rpc.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/rpc/rpc_des.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/rpc/rpc_msg.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/rpc/svc.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/rpc/svc_auth.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/rpc/types.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/rpc/xdr.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/sched.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/scsi/scsi.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/scsi/scsi_ioctl.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/scsi/sg.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/search.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/setjmp.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/sgtty.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/shadow.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/signal.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/stdint.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/stdio.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/stdio_ext.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/stdlib.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/string.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/strings.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/sys/bitypes.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/sys/cdefs.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/sys/dir.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/sys/errno.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/sys/fcntl.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/sys/file.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/sys/fsuid.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/sys/ioctl.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/sys/ipc.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/sys/kd.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/sys/kdaemon.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/sys/klog.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/sys/mman.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/sys/mount.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/sys/msg.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/sys/mtio.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/sys/param.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/sys/personality.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/sys/poll.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/sys/queue.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/sys/quota.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/sys/reboot.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/sys/resource.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/sys/select.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/sys/sem.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/sys/sendfile.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/sys/shm.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/sys/signal.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/sys/signalfd.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/sys/socket.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/sys/socketvar.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/sys/soundcard.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/sys/stat.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/sys/statfs.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/sys/statvfs.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/sys/swap.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/sys/syscall.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/sys/sysctl.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/sys/sysinfo.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/sys/syslog.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/sys/sysmacros.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/sys/termios.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/sys/time.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/sys/timeb.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/sys/times.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/sys/timex.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/sys/ttydefaults.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/sys/types.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/sys/uio.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/sys/un.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/sys/unistd.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/sys/ustat.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/sys/utsname.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/sys/vfs.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/sys/vt.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/sys/wait.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/sys/xattr.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/syscall.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/sysexits.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/syslog.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/tar.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/termio.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/termios.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/tgmath.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/time.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/tls.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/ttyent.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/ucontext.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/ulimit.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/unistd.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/ustat.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/utime.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/utmp.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/utmpx.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/values.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/wait.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/wchar-stub.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/wchar.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/wctype.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/wordexp.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/include/xlocale.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/COPYRIGHT create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/README create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/include/dl-defs.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/include/dl-elf.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/include/dl-hash.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/include/dl-string.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/include/dl-syscall.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/include/dlfcn.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/include/ldso.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/include/ldsodefs.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/include/unsecvars.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/arm/aeabi_read_tp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/arm/dl-debug.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/arm/dl-startup.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/arm/dl-syscalls.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/arm/dl-sysdep.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/arm/elfinterp.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/arm/resolve.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/arm/thumb_atomics.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/avr32/dl-debug.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/avr32/dl-startup.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/avr32/dl-syscalls.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/avr32/dl-sysdep.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/avr32/elfinterp.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/avr32/resolve.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/bfin/dl-debug.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/bfin/dl-inlines.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/bfin/dl-startup.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/bfin/dl-syscalls.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/bfin/dl-sysdep.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/bfin/elfinterp.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/bfin/resolve.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/c6x/dl-debug.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/c6x/dl-inlines.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/c6x/dl-startup.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/c6x/dl-syscalls.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/c6x/dl-sysdep.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/c6x/elfinterp.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/c6x/resolve.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/cris/dl-debug.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/cris/dl-startup.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/cris/dl-syscalls.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/cris/dl-sysdep.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/cris/elfinterp.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/cris/resolve.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/dl-array.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/dl-debug.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/dl-elf.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/dl-hash.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/dl-startup.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/dl-symbols.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/dl-tls.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/frv/dl-debug.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/frv/dl-inlines.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/frv/dl-startup.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/frv/dl-syscalls.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/frv/dl-sysdep.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/frv/elfinterp.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/frv/resolve.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/i386/dl-debug.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/i386/dl-startup.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/i386/dl-syscalls.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/i386/dl-sysdep.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/i386/elfinterp.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/i386/resolve.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/ldso.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/m68k/dl-debug.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/m68k/dl-startup.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/m68k/dl-syscalls.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/m68k/dl-sysdep.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/m68k/elfinterp.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/m68k/resolve.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/mips/README create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/mips/dl-debug.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/mips/dl-startup.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/mips/dl-syscalls.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/mips/dl-sysdep.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/mips/elfinterp.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/mips/resolve.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/powerpc/dl-debug.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/powerpc/dl-startup.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/powerpc/dl-syscalls.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/powerpc/dl-sysdep.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/powerpc/elfinterp.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/powerpc/resolve.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/sh/dl-debug.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/sh/dl-startup.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/sh/dl-syscalls.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/sh/dl-sysdep.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/sh/elfinterp.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/sh/resolve.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/sh64/dl-debug.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/sh64/dl-startup.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/sh64/dl-syscalls.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/sh64/dl-sysdep.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/sh64/elfinterp.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/sh64/resolve.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/sparc/dl-debug.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/sparc/dl-startup.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/sparc/dl-syscalls.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/sparc/dl-sysdep.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/sparc/elfinterp.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/sparc/resolve.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/x86_64/dl-debug.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/x86_64/dl-startup.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/x86_64/dl-syscalls.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/x86_64/dl-sysdep.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/x86_64/elfinterp.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/x86_64/resolve.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/xtensa/dl-debug.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/xtensa/dl-startup.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/xtensa/dl-syscalls.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/xtensa/dl-sysdep.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/xtensa/elfinterp.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/xtensa/resolve.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/libdl/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/libdl/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/libdl/libdl.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/man/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/man/dlopen.3 create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/man/ld.so.8 create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/man/ld.so.texi create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/man/ldconfig.8 create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/ldso/man/ldd.1 create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/.indent.pro create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/_res_state.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/accept.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/addr.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/bind.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/closenameservers.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/connect.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/decodea.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/decoded.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/decodeh.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/decodep.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/decodeq.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/dnslookup.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/encodea.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/encoded.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/encodeh.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/encodep.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/encodeq.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/ether_addr.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/ethers.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/formquery.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/gai_strerror.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/get_hosts_byaddr_r.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/get_hosts_byname_r.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/getaddrinfo.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/gethostbyaddr.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/gethostbyaddr_r.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/gethostbyname.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/gethostbyname2.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/gethostbyname2_r.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/gethostbyname_r.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/gethostent.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/gethostent_r.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/getnameinfo.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/getnet.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/getpeername.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/getproto.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/getservice.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/getsockname.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/getsockopt.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/herror.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/hostid.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/if_index.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/ifaddrs.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/in6_addr.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/inet_addr.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/inet_aton.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/inet_lnaof.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/inet_makeaddr.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/inet_net.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/inet_netof.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/inet_ntoa.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/lengthd.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/lengthq.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/listen.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/netlinkaccess.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/ns_name.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/ntohl.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/ntop.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/opennameservers.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/opensock.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/read_etc_hosts_r.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/recv.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/recvfrom.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/recvmsg.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/res_comp.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/res_init.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/res_query.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/resolv.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/.indent.pro create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/auth_none.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/auth_unix.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/authunix_prot.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/bindresvport.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/clnt_generic.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/clnt_perror.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/clnt_raw.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/clnt_simple.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/clnt_tcp.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/clnt_udp.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/clnt_unix.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/create_xid.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/errqueue.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/get_myaddress.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/getrpcent.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/getrpcport.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/pm_getmaps.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/pm_getport.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/pmap_clnt.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/pmap_prot.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/pmap_prot2.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/pmap_rmt.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/rcmd.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/rexec.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/rpc_cmsg.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/rpc_commondata.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/rpc_dtablesize.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/rpc_private.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/rpc_prot.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/rpc_thread.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/rtime.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/ruserpass.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/sa_len.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/svc.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/svc_auth.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/svc_authux.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/svc_raw.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/svc_run.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/svc_simple.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/svc_tcp.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/svc_udp.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/svc_unix.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/xdr.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/xdr_array.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/xdr_float.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/xdr_intXX_t.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/xdr_mem.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/xdr_rec.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/xdr_reference.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/xdr_stdio.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/send.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/sendmsg.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/sendto.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/setsockopt.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/shutdown.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/socket.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/socketcalls.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/socketpair.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/assert/.indent.pro create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/assert/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/assert/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/assert/__assert.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/.indent.pro create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/__C_ctype_b.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/__C_ctype_tolower.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/__C_ctype_toupper.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/__ctype_assert.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/__ctype_b_loc.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/__ctype_tolower_loc.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/__ctype_toupper_loc.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/ctype.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/isalnum.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/isalnum_l.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/isalpha.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/isalpha_l.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/isascii.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/isascii_l.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/isblank.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/isblank_l.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/iscntrl.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/iscntrl_l.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/isctype.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/isdigit.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/isdigit_l.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/isgraph.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/isgraph_l.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/islower.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/islower_l.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/isprint.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/isprint_l.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/ispunct.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/ispunct_l.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/isspace.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/isspace_l.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/isupper.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/isupper_l.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/isxdigit.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/isxdigit_l.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/toascii.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/toascii_l.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/tolower.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/tolower_l.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/toupper.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/toupper_l.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/dirent/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/dirent/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/dirent/alphasort.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/dirent/alphasort64.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/dirent/closedir.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/dirent/dirfd.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/dirent/dirstream.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/dirent/opendir.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/dirent/readdir.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/dirent/readdir64.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/dirent/readdir64_r.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/dirent/readdir_r.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/dirent/rewinddir.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/dirent/scandir.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/dirent/scandir64.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/dirent/seekdir.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/dirent/telldir.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/dirent/versionsort.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/dirent/versionsort64.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/elf/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/elf/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/elf/dl-core.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/elf/dl-iterate-phdr.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/elf/dl-support.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/error/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/error/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/error/err.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/error/error.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/file/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/file/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/file/lockf.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/file/lockf64.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/fnmatch/.indent.pro create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/fnmatch/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/fnmatch/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/fnmatch/fnmatch.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/fnmatch/fnmatch_loop.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/fnmatch/fnmatch_old.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ftw/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ftw/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ftw/ftw.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ftw/ftw64.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/glob/.indent.pro create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/glob/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/glob/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/glob/glob-susv3.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/glob/glob.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/glob/glob64-susv3.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/glob/glob64.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/gnu/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/gnu/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/gnu/obstack.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/internals/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/internals/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/internals/__errno_location.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/internals/__h_errno_location.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/internals/__uClibc_main.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/internals/errno.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/internals/internal_errno.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/internals/parse_config.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/internals/shared_flat_add_library.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/internals/shared_flat_initfini.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/internals/shared_flat_lib.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/internals/tempname.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/internals/tempname.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/locale/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/locale/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/locale/__curlocale.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/locale/__locale_mbrtowc_l.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/locale/_locale_init.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/locale/duplocale.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/locale/freelocale.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/locale/locale.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/locale/localeconv.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/locale/newlocale.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/locale/nl_langinfo.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/locale/nl_langinfo_l.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/locale/setlocale.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/locale/uselocale.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/mntent/.indent.pro create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/mntent/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/mntent/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/mntent/mntent.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/pthread/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/pthread/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/pthread/tsd.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/regex/.indent.pro create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/regex/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/regex/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/regex/regcomp.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/regex/regex.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/regex/regex_internal.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/regex/regex_internal.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/regex/regex_old.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/regex/regexec.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/search/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/search/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/search/_hsearch_r.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/search/_lsearch.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/search/_tsearch.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/search/hcreate_r.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/search/hdestroy_r.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/search/hsearch.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/search/hsearch_r.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/search/insque.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/search/insremque.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/search/lfind.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/search/lsearch.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/search/remque.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/search/tdelete.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/search/tdestroy.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/search/tfind.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/search/tsearch.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/search/twalk.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/statfs/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/statfs/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/statfs/fstatfs64.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/statfs/fstatvfs.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/statfs/fstatvfs64.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/statfs/internal_statvfs.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/statfs/statfs64.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/statfs/statvfs.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/statfs/statvfs64.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/syslog/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/syslog/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/syslog/syslog.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/sysvipc/.indent.pro create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/sysvipc/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/sysvipc/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/sysvipc/__syscall_ipc.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/sysvipc/ftok.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/sysvipc/ipc.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/sysvipc/msgctl.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/sysvipc/msgget.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/sysvipc/msgq.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/sysvipc/msgrcv.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/sysvipc/msgsnd.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/sysvipc/sem.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/sysvipc/semctl.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/sysvipc/semget.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/sysvipc/semop.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/sysvipc/semtimedop.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/sysvipc/shm.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/sysvipc/shmat.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/sysvipc/shmctl.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/sysvipc/shmdt.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/sysvipc/shmget.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/.indent.pro create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/__time_tm.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/_time_localtime_tzi.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/_time_mktime.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/_time_mktime_tzi.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/_time_t2tm.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/adjtime.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/asctime.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/asctime_r.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/clock.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/ctime.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/ctime_r.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/difftime.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/dysize.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/ftime.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/gmtime.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/gmtime_r.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/localtime.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/localtime_r.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/mktime.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/strftime.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/strftime_l.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/strptime.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/strptime_l.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/time.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/timegm.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/tzset.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/wcsftime.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/wcsftime_l.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ttyent/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ttyent/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ttyent/getttyent.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/utmp/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/utmp/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/utmp/utent.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/utmp/utxent.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/utmp/wtent.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wchar/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wchar/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wchar/_wchar_utf8sntowcs.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wchar/_wchar_wcsntoutf8s.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wchar/btowc.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wchar/iconv.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wchar/mbrlen.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wchar/mbrtowc.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wchar/mbsinit.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wchar/mbsnrtowcs.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wchar/mbsrtowcs.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wchar/wchar.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wchar/wcrtomb.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wchar/wcsnrtombs.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wchar/wcsrtombs.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wchar/wcswidth.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wchar/wctob.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wchar/wcwidth.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/_wctype.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswalnum.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswalnum_l.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswalpha.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswalpha_l.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswblank.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswblank_l.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswcntrl.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswcntrl_l.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswctype.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswctype_l.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswdigit.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswdigit_l.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswgraph.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswgraph_l.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswlower.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswlower_l.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswprint.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswprint_l.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswpunct.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswpunct_l.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswspace.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswspace_l.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswupper.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswupper_l.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswxdigit.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswxdigit_l.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/towctrans.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/towctrans_l.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/towlower.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/towlower_l.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/towupper.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/towupper_l.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/wctrans.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/wctrans_l.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/wctype.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/wctype_l.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wordexp/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wordexp/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wordexp/wordexp.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/.indent.pro create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/__getgrouplist_internal.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/__parsegrent.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/__parsepwent.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/__parsespent.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/__pgsreader.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/fgetgrent.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/fgetgrent_r.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/fgetpwent.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/fgetpwent_r.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/fgetspent.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/fgetspent_r.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/getgrent.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/getgrent_r.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/getgrgid.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/getgrgid_r.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/getgrnam.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/getgrnam_r.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/getgrouplist.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/getpw.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/getpwent.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/getpwent_r.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/getpwnam.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/getpwnam_r.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/getpwuid.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/getpwuid_r.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/getspent.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/getspent_r.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/getspnam.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/getspnam_r.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/initgroups.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/lckpwdf.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/putgrent.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/putpwent.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/putspent.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/pwd_grp.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/pwd_grp_internal.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/sgetspent.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/sgetspent_r.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/allocrtsig.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/killpg.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/raise.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sigaction.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sigaddset.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sigandset.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sigblock.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sigdelset.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sigempty.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sigfillset.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/siggetmask.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sighold.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sigignore.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sigintr.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sigisempty.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sigismem.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sigjmp.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/signal.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sigorset.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sigpause.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sigrelse.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sigset-cvt-mask.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sigset.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sigsetmask.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sigsetops.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sigsetops.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sigwait.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sysv_signal.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/.indent.pro create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_READ.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_WRITE.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/__fbufsize.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/__flbf.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/__fpending.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/__fpurge.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/__freadable.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/__freading.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/__fsetlocking.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/__fwritable.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/__fwriting.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/__psfs_do_numeric.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/__psfs_parse_spec.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/__scan_cookie.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_adjust_pos.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_cs_funcs.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_flushlbf.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_fopen.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_fpmaxtostr.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_fwrite.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_load_inttype.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_ppfs_init.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_ppfs_parsespec.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_ppfs_prepargs.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_ppfs_setargs.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_rfill.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_scanf.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_stdio.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_stdio.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_store_inttype.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_trans2r.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_trans2w.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_uintmaxtostr.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_vfprintf.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_vfprintf_internal.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_vfwprintf_internal.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_wcommit.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_wfwrite.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/asprintf.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/clearerr.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/clearerr_unlocked.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/ctermid.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/dprintf.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fclose.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fcloseall.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fdopen.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/feof.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/feof_unlocked.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/ferror.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/ferror_unlocked.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fflush.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fflush_unlocked.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fgetc.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fgetc_unlocked.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fgetpos.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fgetpos64.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fgets.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fgets_unlocked.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fgetwc.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fgetwc_unlocked.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fgetws.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fgetws_unlocked.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fileno.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fileno_unlocked.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/flockfile.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fmemopen.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fopen.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fopen64.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fopencookie.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fprintf.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fputc.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fputc_unlocked.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fputs.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fputs_unlocked.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fputwc.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fputwc_unlocked.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fputws.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fputws_unlocked.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fread.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fread_unlocked.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/freopen.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/freopen64.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fscanf.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fseeko.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fseeko64.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fsetpos.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fsetpos64.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/ftello.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/ftello64.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/ftrylockfile.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/funlockfile.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fwide.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fwprintf.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fwrite.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fwrite_unlocked.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fwscanf.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/getchar.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/getchar_unlocked.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/getdelim.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/getline.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/gets.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/getw.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/getwchar.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/getwchar_unlocked.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/old_vfprintf.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/open_memstream.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/parse_printf_format.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/perror.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/popen.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/printf.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/putchar.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/putchar_unlocked.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/puts.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/putw.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/putwchar.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/putwchar_unlocked.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/register_printf_function.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/remove.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/rewind.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/scanf.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/setbuf.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/setbuffer.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/setlinebuf.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/setvbuf.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/snprintf.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/sprintf.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/sscanf.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/swprintf.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/swscanf.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/tempnam.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/tmpfile.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/tmpnam.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/tmpnam_r.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/ungetc.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/ungetwc.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/vasprintf.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/vdprintf.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/vfprintf.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/vfscanf.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/vfwprintf.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/vfwscanf.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/vprintf.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/vscanf.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/vsnprintf.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/vsprintf.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/vsscanf.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/vswprintf.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/vswscanf.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/vwprintf.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/vwscanf.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/wprintf.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/wscanf.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/.indent.pro create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/__cxa_atexit.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/__cxa_finalize.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/__exit_handler.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/__fp_range_check.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/__strtofpmax.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/__strtofpmax_l.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/__uc_malloc.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/__wcstofpmax.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/__wcstofpmax_l.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/_atexit.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/_stdlib_mb_cur_max.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/_stdlib_strto_l.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/_stdlib_strto_l_l.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/_stdlib_strto_ll.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/_stdlib_strto_ll_l.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/_stdlib_wcsto_l.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/_stdlib_wcsto_l_l.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/_stdlib_wcsto_ll.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/_stdlib_wcsto_ll_l.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/_strtod.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/a64l.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/abort.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/abs.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/arc4random.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/atexit.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/atof.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/atoi.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/atol.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/atoll.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/bsd_getpt.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/bsearch.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/canonicalize.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/div.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/drand48-iter.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/drand48.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/drand48_r.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/erand48.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/erand48_r.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/exit.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/gcvt.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/getenv.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/getpt.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/grantpt.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/jrand48.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/jrand48_r.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/l64a.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/labs.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/ldiv.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/llabs.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/lldiv.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/lrand48.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/lrand48_r.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc-simple/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc-simple/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc-simple/alloc.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc-simple/calloc.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc-simple/free.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc-simple/malloc.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc-simple/memalign.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc-simple/realloc.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc-standard/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc-standard/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc-standard/calloc.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc-standard/free.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc-standard/mallinfo.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc-standard/malloc.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc-standard/malloc.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc-standard/mallopt.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc-standard/memalign.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc-standard/realloc.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc/calloc.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc/free.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc/heap.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc/heap_alloc.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc/heap_alloc_at.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc/heap_debug.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc/heap_free.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc/malloc.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc/malloc.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc/malloc_debug.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc/memalign.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc/realloc.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/mblen.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/mbstowcs.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/mbtowc.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/mkdtemp.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/mkstemp.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/mkstemp64.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/mktemp.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/mrand48.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/mrand48_r.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/nrand48.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/nrand48_r.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/old_atexit.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/on_exit.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/posix_memalign.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/ptsname.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/pty-private.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/qsort.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/rand.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/rand_r.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/random.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/random_r.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/realpath.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/seed48.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/seed48_r.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/setenv.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/srand48.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/srand48_r.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/stdlib.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/strtod.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/strtod_l.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/strtof.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/strtof_l.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/strtol.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/strtol_l.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/strtold.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/strtold_l.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/strtoll.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/strtoll_l.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/strtoul.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/strtoul_l.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/strtoull.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/strtoull_l.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/system.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/unix_grantpt.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/unlockpt.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/valloc.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/wcstod.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/wcstod_l.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/wcstof.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/wcstof_l.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/wcstol.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/wcstol_l.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/wcstold.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/wcstold_l.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/wcstoll.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/wcstoll_l.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/wcstombs.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/wcstoul.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/wcstoul_l.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/wcstoull.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/wcstoull_l.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/wctomb.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/.indent.pro create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/__glibc_strerror_r.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/__xpg_basename.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/__xpg_strerror_r.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/_collate.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/_string.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/_string_syserrmsgs.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/_string_syssigmsgs.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/_syserrmsg.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/arm/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/arm/_memcpy.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/arm/bcopy.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/arm/bzero.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/arm/memcmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/arm/memcpy.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/arm/memmove.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/arm/memset.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/arm/strcmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/arm/strlen.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/avr32/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/avr32/bcopy.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/avr32/bzero.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/avr32/memcmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/avr32/memcpy.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/avr32/memmove.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/avr32/memset.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/avr32/strcmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/avr32/strlen.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/basename.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/bcopy.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/bfin/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/bfin/memchr.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/bfin/memcmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/bfin/memcpy.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/bfin/memmove.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/bfin/memset.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/bfin/strcmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/bzero.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/cris/memcopy.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/cris/memcpy.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/cris/memmove.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/cris/memset.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/cris/strcpy.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/cris/strncpy.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/dirname.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/ffs.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/frv/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/frv/memcpy.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/frv/memset.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/_memcpy_fwd.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/memchr.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/memcmp.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/memcopy.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/memcpy.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/memmem.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/memmove.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/mempcpy.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/memrchr.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/memset.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/pagecopy.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/rawmemchr.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/strcat.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/strchr.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/strchrnul.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/strcmp.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/strcpy.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/strcspn.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/strlen.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/strncat.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/strncmp.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/strncpy.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/strnlen.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/strrchr.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/strsep.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/strspn.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/strstr.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/strtok_r.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/i386/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/i386/memchr.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/i386/memcpy.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/i386/memmove.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/i386/memset.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/i386/rawmemchr.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/i386/strcat.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/i386/strchr.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/i386/strchrnul.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/i386/strcmp.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/i386/strcpy.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/i386/string.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/i386/strlen.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/i386/strncat.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/i386/strncmp.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/i386/strncpy.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/i386/strnlen.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/i386/strrchr.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/ia64/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/ia64/bcopy.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/ia64/bzero.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/ia64/memccpy.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/ia64/memchr.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/ia64/memcmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/ia64/memcpy.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/ia64/memmove.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/ia64/memset.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/ia64/softpipe.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/ia64/strchr.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/ia64/strcmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/ia64/strcpy.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/ia64/strlen.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/ia64/strncmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/ia64/strncpy.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/ia64/sysdep.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/memccpy.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/memchr.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/memcmp.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/memcpy.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/memmem.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/memmove.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/mempcpy.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/memrchr.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/memset.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/microblaze/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/microblaze/memcpy.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/microblaze/memmove.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/mips/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/mips/memcpy.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/mips/memset.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/mips/sysdep.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/powerpc/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/powerpc/memcpy.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/powerpc/memmove.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/powerpc/memset.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/psignal.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/rawmemchr.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sh/memchr.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sh/sh4/memcpy.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sh/sh4/memmove.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sh/sh4/memset.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sh/sh4/strcpy.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sh/sh4/strncpy.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sh/strlen.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sh64/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sh64/memcpy.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sh64/memset.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sh64/strcpy.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sh64/strlen.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/_glibc_inc.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/bcopy.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/bzero.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/memchr.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/memcpy.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/memmove.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/memset.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc32/memchr.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc32/memcpy.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc32/memset.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc32/sparcv9b/memchr.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc32/sparcv9b/memcpy.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc32/sparcv9b/memset.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc32/sparcv9b/stpcpy.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc32/sparcv9b/strcat.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc32/sparcv9b/strchr.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc32/sparcv9b/strcmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc32/sparcv9b/strcpy.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc32/sparcv9b/strlen.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc32/stpcpy.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc32/strcat.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc32/strchr.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc32/strcmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc32/strcpy.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc32/strlen.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc64/memchr.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc64/memcpy.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc64/memset.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc64/sparcv9b/memcpy.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc64/stpcpy.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc64/strcat.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc64/strchr.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc64/strcmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc64/strcpy.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc64/strlen.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/stpcpy.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/strcat.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/strchr.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/strcmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/strcpy.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/strlen.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/strrchr.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/stpcpy.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/stpncpy.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strcasecmp.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strcasecmp_l.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strcasestr.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strcat.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strchr.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strchrnul.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strcmp.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strcpy.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strcspn.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strdup.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strerror.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strlcat.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strlcpy.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strlen.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strncasecmp.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strncasecmp_l.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strncat.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strncmp.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strncpy.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strndup.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strnlen.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strpbrk.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strrchr.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strsep.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strsignal.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strspn.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strstr.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strtok.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strtok_r.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strverscmp.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strxfrm.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strxfrm_l.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sys_errlist.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sys_siglist.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcpcpy.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcpncpy.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcscasecmp.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcscasecmp_l.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcscat.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcschr.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcschrnul.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcscmp.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcscpy.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcscspn.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcsdup.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcslcpy.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcslen.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcsncasecmp.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcsncasecmp_l.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcsncat.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcsncmp.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcsncpy.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcsnlen.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcspbrk.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcsrchr.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcsspn.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcsstr.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcstok.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcsxfrm.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcsxfrm_l.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wmemchr.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wmemcmp.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wmemcpy.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wmemmove.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wmempcpy.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wmemset.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/x86_64/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/x86_64/_glibc_inc.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/x86_64/bzero.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/x86_64/memcpy.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/x86_64/mempcpy.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/x86_64/memset.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/x86_64/stpcpy.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/x86_64/strcat.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/x86_64/strchr.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/x86_64/strcmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/x86_64/strcpy.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/x86_64/strcspn.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/x86_64/strlen.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/x86_64/strpbrk.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/x86_64/strspn.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/xtensa/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/xtensa/memcpy.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/xtensa/memset.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/xtensa/strcmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/xtensa/strcpy.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/xtensa/strlen.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/string/xtensa/strncpy.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/README create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/Makefile.commonarch create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/README create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/Makefile.arch create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/__longjmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/__syscall_error.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/__syscall_rt_sigaction.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/atomic.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/dirent.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/elfclass.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/endian.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/fcntl.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/fenv.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/ioctls.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/ipc.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/kernel_sigaction.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/kernel_stat.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/kernel_types.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/mathdef.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/mathinline.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/mman.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/msq.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/netdb.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/resource.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/sem.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/setjmp.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/shm.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/sigaction.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/sigcontextinfo.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/siginfo.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/signum.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/sigstack.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/stackinfo.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/stat.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/statfs.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/statvfs.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/syscalls.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/termios.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/typesizes.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/uClibc_arch_features.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/uClibc_clk_tck.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/uClibc_page.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/wordsize.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/brk.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bsd-_setjmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bsd-setjmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/clone.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/crt1.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/crti.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/crtn.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/divl.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/divq.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/divrem.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/fpu_control.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/pipe.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/reml.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/remq.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/setjmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/sigprocmask.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/sys/acct.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/sys/io.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/sys/procfs.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/sys/regdef.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/sys/ucontext.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/sys/user.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/syscall.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/Makefile.arch create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/__longjmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/__syscall_error.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/aeabi_assert.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/aeabi_atexit.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/aeabi_errno_addr.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/aeabi_lcsts.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/aeabi_localeconv.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/aeabi_math.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/aeabi_mb_cur_max.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/aeabi_memclr.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/aeabi_memcpy.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/aeabi_memmove.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/aeabi_memset.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/aeabi_sighandlers.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/aeabi_unwind_cpp_pr1.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/bits/arm_asm.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/bits/armsigctx.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/bits/endian.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/bits/fcntl.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/bits/fenv.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/bits/huge_val.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/bits/kernel_stat.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/bits/kernel_types.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/bits/mathdef.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/bits/setjmp.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/bits/shm.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/bits/sigcontextinfo.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/bits/stackinfo.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/bits/syscalls.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/bits/uClibc_arch_features.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/bits/wordsize.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/brk.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/bsd-_setjmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/bsd-setjmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/clone.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/crt1.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/crti.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/crtn.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/find_exidx.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/fpu_control.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/ioperm.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/iopl.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/libc-aeabi_read_tp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/libc-thumb_atomics.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/mmap.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/mmap64.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/posix_fadvise.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/posix_fadvise64.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/setjmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/sigaction.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/sigrestorer.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/sys/elf.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/sys/io.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/sys/procfs.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/sys/ucontext.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/sys/user.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/syscall-eabi.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/syscall.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/sysdep.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/vfork.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/Makefile.arch create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/__longjmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/bits/atomic.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/bits/endian.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/bits/fcntl.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/bits/kernel_stat.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/bits/kernel_types.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/bits/setjmp.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/bits/stackinfo.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/bits/syscalls.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/bits/uClibc_arch_features.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/bits/wordsize.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/brk.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/bsd-_setjmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/bsd-setjmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/clone.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/crt1.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/crti.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/crtn.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/mmap.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/prctl.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/setjmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/sigaction.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/sigrestorer.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/sys/elf.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/sys/procfs.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/sys/ucontext.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/sys/user.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/syscall.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/vfork.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/Makefile.arch create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/__longjmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/bfin_fixed_code.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/bfin_l1layout.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/bfin_sram.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/bits/byteswap.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/bits/elf-fdpic.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/bits/endian.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/bits/fcntl.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/bits/huge_val.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/bits/kernel_stat.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/bits/kernel_types.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/bits/setjmp.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/bits/sigcontextinfo.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/bits/stackinfo.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/bits/syscalls.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/bits/typesizes.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/bits/uClibc_arch_features.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/bits/wordsize.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/bsd-_setjmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/bsdsetjmp.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/clone.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/crt1.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/crti.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/crtn.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/crtreloc.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/dma-memcpy.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/setjmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/sram-alloc.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/sram-free.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/sys/elf.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/sys/io.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/sys/procfs.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/sys/ucontext.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/sys/user.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/sysdep.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/.indent.pro create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/__rt_sigtimedwait.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/__rt_sigwaitinfo.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/__socketcall.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/__syscall_fcntl.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/__syscall_fcntl64.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/__syscall_rt_sigaction.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/__syscall_sigaction.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/_exit.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/access.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/acct.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/adjtimex.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/alarm.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/arch_prctl.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bdflush.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/atomic.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/byteswap-common.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/byteswap.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/cmathcalls.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/confname.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/dirent.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/dlfcn.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/elfclass.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/endian.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/environments.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/errno.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/fcntl.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/fenv.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/fenvinline.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/getopt.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/huge_val.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/huge_valf.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/huge_vall.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/in.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/inf.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/initspin.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/ioctl-types.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/ioctls.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/ipc.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/kernel-features.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/kernel_sigaction.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/kernel_stat.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/kernel_types.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/local_lim.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/locale.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/mathcalls.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/mathdef.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/mathinline.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/mman-common.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/mman.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/mqueue.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/msq.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/nan.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/netdb.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/poll.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/posix1_lim.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/posix2_lim.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/posix_opt.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/resource.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/sched.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/select.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/sem.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/setjmp.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/shm.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/sigaction.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/sigcontext.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/sigcontextinfo.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/siginfo.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/signum.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/sigset.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/sigstack.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/sigthread.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/sockaddr.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/socket.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/stab.def create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/stackinfo.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/stat.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/statfs.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/statvfs.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/stdio.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/stdio_lim.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/syscalls-common.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/syscalls.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/termios.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/time.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/types.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/typesizes.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/uClibc_alloc.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/uClibc_arch_features.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/uClibc_charclass.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/uClibc_clk_tck.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/uClibc_ctype.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/uClibc_errno.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/uClibc_fpmax.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/uClibc_local_lim.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/uClibc_locale.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/uClibc_mutex.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/uClibc_page.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/uClibc_pthread.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/uClibc_stdio.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/uClibc_touplow.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/uClibc_uintmaxtostr.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/uClibc_uwchar.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/uClibc_va_copy.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/uio.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/ustat.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/utmp.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/utmpx.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/utsname.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/waitflags.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/waitstatus.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/wchar.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/wordsize.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/xopen_lim.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/brk.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/capget.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/capset.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/chdir.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/chmod.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/chown.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/chroot.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/clock_getres.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/clock_gettime.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/clock_settime.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/close.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/cmsg_nxthdr.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/creat.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/creat64.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/create_module.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/delete_module.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/dl-osinfo.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/dup.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/dup2.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/epoll.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/execve.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/faccessat.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/fchdir.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/fchmod.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/fchmodat.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/fchown.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/fchownat.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/fdatasync.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/flock.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/fork.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/fpu_control.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/fstat.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/fstat64.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/fstatat.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/fstatat64.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/fstatfs.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/fsync.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/ftruncate.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/ftruncate64.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/futimens.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/futimesat.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/get_kernel_syms.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getcwd.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getdents.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getdents64.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getdirname.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getdomainname.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getdtablesize.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getegid.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/geteuid.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getgid.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getgroups.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/gethostname.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getitimer.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getpagesize.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getpgid.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getpgrp.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getpid.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getppid.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getpriority.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getresgid.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getresuid.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getrlimit.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getrlimit64.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getrusage.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getsid.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/gettimeofday.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getuid.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/hp-timing.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/init_module.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/inotify.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/ioctl.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/ioperm.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/iopl.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/kill.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/klogctl.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/lchown.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/libgcc_s.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/link.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/linkat.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/llseek.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/longjmp.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/lseek.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/lstat.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/lstat64.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/lutimes.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/madvise.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/mincore.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/mkdir.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/mkdirat.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/mkfifo.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/mkfifoat.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/mknod.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/mknodat.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/mlock.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/mlockall.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/mmap.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/mmap64.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/modify_ldt.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/mount.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/mprotect.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/mremap.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/msync.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/munlock.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/munlockall.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/munmap.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/nanosleep.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/nice.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/noophooks.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/not-cancel.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/ntp_gettime.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/open.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/open64.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/openat.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/openat64.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/pause.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/personality.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/pipe.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/pivot_root.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/poll.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/posix_fadvise.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/posix_fadvise64.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/ppoll.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/prctl.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/pread_write.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/pselect.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/ptrace.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/query_module.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/quotactl.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/read.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/readahead.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/readlink.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/readlinkat.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/readv.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/reboot.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/remap_file_pages.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/rename.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/renameat.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/rmdir.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sbrk.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sched_get_priority_max.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sched_get_priority_min.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sched_getaffinity.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sched_getparam.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sched_getscheduler.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sched_rr_get_interval.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sched_setaffinity.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sched_setparam.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sched_setscheduler.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sched_yield.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/select.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sendfile.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sendfile64.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/setdomainname.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/setegid.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/seteuid.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/setfsgid.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/setfsuid.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/setgid.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/setgroups.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sethostname.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/setitimer.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/setpgid.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/setpgrp.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/setpriority.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/setregid.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/setresgid.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/setresuid.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/setreuid.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/setrlimit.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/setrlimit64.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/setsid.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/settimeofday.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/setuid.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sigaltstack.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/signalfd.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sigpending.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sigprocmask.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sigqueue.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sigsuspend.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/splice.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/ssp-local.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/ssp.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/stat.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/stat64.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/statfs.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/stime.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/swapoff.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/swapon.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/symlink.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/symlinkat.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sync.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sync_file_range.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sys/acct.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sys/epoll.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sys/inotify.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sys/prctl.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sys/ptrace.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sys/timerfd.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sys/user.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/syscall.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/syscalls.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sysctl.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sysdep.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sysfs.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sysinfo.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/tee.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/time.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/timerfd.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/times.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/truncate.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/truncate64.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/ulimit.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/umask.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/umount.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/umount2.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/uname.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/unlink.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/unlinkat.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/uselib.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/ustat.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/utime.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/utimensat.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/utimes.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/vfork.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/vhangup.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/vmsplice.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/wait.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/wait3.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/wait4.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/waitid.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/waitpid.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/write.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/writev.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/xattr.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/xstatconv.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/xstatconv.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/Makefile.arch create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/__init_brk.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/__longjmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/bits/byteswap.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/bits/endian.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/bits/fcntl.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/bits/kernel_stat.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/bits/kernel_types.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/bits/setjmp.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/bits/stackinfo.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/bits/syscalls.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/bits/termios.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/bits/uClibc_arch_features.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/bits/uClibc_page.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/bits/wordsize.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/brk.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/clone.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/crt1.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/crti.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/crtn.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/fork.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/libc.map create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/sbrk.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/setjmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/sys/procfs.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/sys/ucontext.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/syscall.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/sysdep.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/sysdep.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/e1/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/e1/bits/endian.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/e1/bits/fcntl.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/e1/bits/fenv.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/e1/bits/fenvinline.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/e1/bits/kernel_stat.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/e1/bits/kernel_types.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/e1/bits/proto.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/e1/bits/setjmp.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/e1/bits/syscalls.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/e1/bits/uClibc_arch_features.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/e1/bits/unistd.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/e1/bits/wordsize.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/e1/crt0.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/e1/crt1.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/e1/longjmp.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/e1/setjmp.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/e1/sys/procfs.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/e1/sys/reg.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/e1/sys/ucontext.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/e1/syscalls.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/e1/vfork.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/__init_brk.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/__longjmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/bits/elf-fdpic.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/bits/endian.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/bits/fcntl.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/bits/kernel_stat.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/bits/kernel_types.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/bits/setjmp.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/bits/stackinfo.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/bits/stat.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/bits/syscalls.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/bits/uClibc_arch_features.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/bits/uClibc_page.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/bits/wordsize.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/brk.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/clone.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/crt0.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/crti.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/crtn.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/crtreloc.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/dl-iterate-phdr.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/fstat.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/fstat64.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/lstat.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/lstat64.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/mmap.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/sbrk.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/setjmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/stat.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/stat64.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/sys/procfs.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/sys/ptrace.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/sys/ucontext.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/syscall.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/sysdep.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/vfork.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/xstatconv.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/__longjmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/bits/byteswap.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/bits/endian.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/bits/fcntl.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/bits/kernel_stat.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/bits/kernel_types.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/bits/setjmp.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/bits/sigcontextinfo.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/bits/stackinfo.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/bits/syscalls.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/bits/uClibc_arch_features.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/bits/wordsize.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/brk.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/bsd-_setjmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/bsd-setjmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/clone.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/crt0.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/crti.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/crtn.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/float.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/ptrace.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/setjmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/sys/procfs.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/sys/ucontext.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/vfork.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/Makefile.arch create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/__longjmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/__syscall_error.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/add_n.s create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/bits/endian.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/bits/fcntl.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/bits/fenv.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/bits/ipc.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/bits/kernel_sigaction.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/bits/kernel_stat.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/bits/kernel_types.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/bits/mman.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/bits/setjmp.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/bits/sigaction.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/bits/signum.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/bits/stackinfo.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/bits/syscalls.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/bits/uClibc_arch_features.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/bits/wordsize.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/brk.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/bsd-_setjmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/bsd-setjmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/clone.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/crt1.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/crti.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/crtn.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/lshift.s create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/mmap.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/rshift.s create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/setjmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/sub_n.s create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/sys/procfs.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/sys/ucontext.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/syscall.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/udiv_qrnnd.s create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/Makefile.arch create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/__longjmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/__syscall_error.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/bits/atomic.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/bits/byteswap.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/bits/endian.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/bits/fcntl.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/bits/fenv.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/bits/kernel_stat.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/bits/kernel_types.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/bits/mathdef.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/bits/mathinline.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/bits/select.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/bits/setjmp.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/bits/sigcontextinfo.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/bits/stackinfo.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/bits/syscalls.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/bits/uClibc_arch_features.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/bits/wchar.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/bits/wordsize.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/brk.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/bsd-_setjmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/bsd-setjmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/clone.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/crt1.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/crti.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/crtn.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/fpu_control.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/mmap.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/mmap64.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/posix_fadvise64.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/setjmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/sigaction.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/sync_file_range.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/sys/debugreg.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/sys/elf.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/sys/io.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/sys/perm.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/sys/procfs.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/sys/reg.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/sys/ucontext.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/sys/user.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/sys/vm86.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/syscall.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/sysdep.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/vfork.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i960/AUTHORS create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i960/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i960/README create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i960/bits/endian.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i960/bits/fcntl.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i960/bits/setjmp.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i960/bits/syscalls.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i960/bits/uClibc_arch_features.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i960/bits/wordsize.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i960/clone.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i960/crt0.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i960/mmap.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i960/setjmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i960/specs.uclinux.gcc-2.95.i960-intel-coff create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i960/sys/procfs.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i960/sys/ucontext.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i960/vfork.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/Makefile.arch create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/__longjmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/__syscall_error.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/atomic.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/byteswap.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/endian.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/fcntl.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/fenv.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/ipc.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/kernel_stat.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/kernel_types.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/mathdef.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/mathinline.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/mman.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/msq.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/sem.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/setjmp.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/shm.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/sigaction.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/sigcontext.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/siginfo.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/sigstack.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/stackinfo.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/stat.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/syscalls.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/uClibc_arch_features.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/wordsize.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/brk.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bsd-_setjmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bsd-setjmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/clone2.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/crt1.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/crti.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/crtn.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/fork.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/pipe.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/setjmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/sys/io.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/sys/procfs.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/sys/ptrace.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/sys/ucontext.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/sys/user.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/syscall.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/sysdep.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/vfork.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/Makefile.arch create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/README.m68k create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/__longjmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/__syscall_error.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/bits/byteswap.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/bits/endian.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/bits/fcntl.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/bits/fenv.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/bits/kernel_stat.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/bits/kernel_types.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/bits/mathdef.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/bits/mathinline.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/bits/poll.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/bits/setjmp.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/bits/sigcontextinfo.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/bits/stackinfo.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/bits/stat.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/bits/syscalls.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/bits/uClibc_arch_features.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/bits/uClibc_page.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/bits/wordsize.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/brk.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/bsd-_setjmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/bsd-setjmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/clone.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/crt1.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/crti.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/crtn.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/float.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/fpu_control.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/m68k_pic.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/setjmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/sys/procfs.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/sys/reg.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/sys/ucontext.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/sys/user.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/vfork.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/Makefile.arch create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/__longjmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/bits/endian.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/bits/fcntl.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/bits/kernel_stat.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/bits/kernel_types.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/bits/poll.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/bits/select.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/bits/setjmp.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/bits/stackinfo.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/bits/syscalls.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/bits/uClibc_arch_features.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/bits/uClibc_page.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/bits/wordsize.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/clone.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/crt0.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/crt1.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/crti.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/crtn.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/fixdfsi.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/floatlib.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/mmap.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/setjmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/sys/procfs.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/sys/ptrace.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/sys/ucontext.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/vfork.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/Makefile.arch create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/__longjmp.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/__syscall_error.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/_test_and_set.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/atomic.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/dirent.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/dlfcn.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/endian.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/fcntl.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/fenv.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/ioctl-types.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/ipc.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/kernel_sigaction.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/kernel_stat.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/kernel_types.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/mathdef.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/mman.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/msq.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/poll.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/resource.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/sem.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/setjmp.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/shm.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/sigaction.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/sigcontext.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/sigcontextinfo.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/siginfo.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/signum.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/sigstack.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/socket.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/stackinfo.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/stat.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/statfs.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/syscalls.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/termios.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/uClibc_arch_features.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/uClibc_page.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/wordsize.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/brk.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bsd-_setjmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bsd-setjmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/cacheflush.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/clone.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/crt1.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/crti.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/crtn.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/fpu_control.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/mmap.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/pipe.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/posix_fadvise.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/posix_fadvise64.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/pread_write.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/readahead.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/setjmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/setjmp_aux.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/sgidefs.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/sigaction.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/sys/asm.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/sys/cachectl.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/sys/fpregdef.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/sys/procfs.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/sys/regdef.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/sys/sysmips.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/sys/tas.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/sys/ucontext.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/sys/user.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/syscall.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/syscall_error.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/sysdep.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/sysmips.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/vfork.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/Makefile.arch create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/NM_Macros.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/NR_Math1.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/__longjmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/bits/endian.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/bits/fcntl.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/bits/kernel_types.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/bits/mathdef.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/bits/setjmp.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/bits/sigcontextinfo.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/bits/stackinfo.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/bits/stat.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/bits/syscalls.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/bits/uClibc_arch_features.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/bits/wordsize.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/brk.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/bsd-_setjmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/bsd-setjmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/clone.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/crt1.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/crtbegin.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/crtend.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/fpu_control.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/setjmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/sys/procfs.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/sys/ucontext.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/vfork.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/Makefile.arch create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/__longjmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/bits/endian.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/bits/fcntl.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/bits/kernel_stat.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/bits/kernel_types.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/bits/mathdef.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/bits/setjmp.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/bits/sigcontextinfo.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/bits/stackinfo.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/bits/stat.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/bits/syscalls.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/bits/uClibc_arch_features.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/bits/uClibc_page.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/bits/wordsize.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/brk.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/bsd-_setjmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/bsd-setjmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/clone.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/clone.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/crt1.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/crti.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/crtn.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/fpu_control.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/setjmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/sys/procfs.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/sys/ucontext.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/sys/user.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/syscall.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/vfork.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/Makefile.arch create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/README.bits create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/__longjmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/__syscall_error.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/__uClibc_syscall.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/atomic.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/endian.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/fcntl.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/fenv.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/fenvinline.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/ioctl-types.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/ipc.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/kernel_stat.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/kernel_types.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/mathdef.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/mathinline.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/mman.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/msq.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/sem.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/setjmp.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/shm.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/sigcontextinfo.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/stackinfo.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/stat.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/syscalls.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/termios.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/uClibc_arch_features.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/wordsize.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/brk.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bsd-_setjmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bsd-setjmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/clone.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/crt1.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/crti.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/crtn.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/fenv.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/fpu_control.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/ioctl.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/posix_fadvise.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/posix_fadvise64.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/powerpc32/sysdep.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/powerpc64/sysdep.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/ppc_asm.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/pread_write.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/setjmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/sys/procfs.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/sys/ptrace.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/sys/ucontext.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/sys/user.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/syscall.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/sysdep.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/vfork.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/Makefile.arch create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/___fpscr_values.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/__init_brk.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/__longjmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/bits/atomic.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/bits/endian.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/bits/fcntl.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/bits/fenv.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/bits/huge_val.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/bits/kernel_stat.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/bits/kernel_types.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/bits/mathdef.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/bits/setjmp.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/bits/shm.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/bits/sigcontextinfo.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/bits/stackinfo.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/bits/syscalls.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/bits/uClibc_arch_features.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/bits/wordsize.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/brk.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/cacheflush.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/clone.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/crt1.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/crti.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/crtn.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/fpu_control.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/longjmp.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/mmap.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/pipe.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/pread_write.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/sbrk.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/setjmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/sys/io.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/sys/procfs.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/sys/ucontext.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/sys/user.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/syscall_error.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/sysdep.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/vfork.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/Makefile.arch create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/__init_brk.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/__longjmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/bits/endian.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/bits/fcntl.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/bits/kernel_stat.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/bits/kernel_types.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/bits/setjmp.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/bits/shm.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/bits/stackinfo.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/bits/syscalls.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/bits/uClibc_arch_features.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/bits/wordsize.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/brk.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/crt1.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/crti.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/crtn.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/sbrk.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/setjmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/sys/procfs.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/sys/ucontext.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/syscall.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/Makefile.arch create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/__longjmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/__syscall_error.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/_math_inc.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/atomic.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/endian.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/fcntl.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/fenv.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/ioctls.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/ipc.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/kernel_stat.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/kernel_types.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/mathdef.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/mathinline.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/mman.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/msq.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/poll.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/resource.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/sem.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/setjmp.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/shm.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/sigaction.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/sigcontext.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/sigcontextinfo.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/siginfo.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/signum.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/sigstack.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/socket.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/stackinfo.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/stat.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/statvfs.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/syscalls.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/termios.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/typesizes.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/uClibc_arch_features.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/wordsize.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/brk.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bsd-_setjmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bsd-setjmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/clone.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/crt1.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/crti.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/crtn.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/fork.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/fpu_control.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/pipe.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/qp_ops.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/rem.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sdiv.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/setjmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sigaction.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/double.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/extended.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/longlong.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/mp_clz_tab.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/op-1.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/op-2.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/op-4.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/op-8.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/op-common.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_add.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_cmp.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_cmpe.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_div.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_dtoq.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_feq.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_fge.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_fgt.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_fle.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_flt.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_fne.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_itoq.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_lltoq.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_mul.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_neg.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_qtod.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_qtoi.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_qtoll.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_qtos.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_qtou.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_qtoull.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_sqrt.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_stoq.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_sub.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_ulltoq.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_util.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_utoq.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/quad.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/sfp-machine.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/single.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/soft-fp.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sparcv7/rem.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sparcv7/sdiv.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sparcv7/udiv.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sparcv7/umul.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sparcv7/urem.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sparcv8/rem.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sparcv8/sdiv.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sparcv8/udiv.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sparcv8/umul.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sparcv8/urem.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sparcv9/clone.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sparcv9/rem.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sparcv9/sdiv.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sparcv9/udiv.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sparcv9/umul.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sparcv9/urem.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sys/procfs.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sys/ptrace.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sys/ucontext.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sys/user.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/syscall.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sysdep.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/udiv.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/umul.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/urem.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/vfork.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/__longjmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/bits/byteswap.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/bits/endian.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/bits/fcntl.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/bits/kernel_stat.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/bits/kernel_types.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/bits/poll.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/bits/select.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/bits/setjmp.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/bits/sigcontextinfo.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/bits/stackinfo.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/bits/syscalls.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/bits/uClibc_arch_features.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/bits/wordsize.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/clinkage.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/clone.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/crt0.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/crti.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/crtn.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/mmap.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/setjmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/sys/procfs.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/sys/ptrace.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/sys/ucontext.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/syscall.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/vfork.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/Makefile.arch create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/__longjmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/_setjmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/bits/endian.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/bits/fcntl.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/bits/ipc.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/bits/kernel_stat.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/bits/kernel_types.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/bits/machine-gmon.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/bits/sem.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/bits/setjmp.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/bits/shm.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/bits/sigcontext.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/bits/stackinfo.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/bits/statfs.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/bits/syscalls.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/bits/uClibc_arch_features.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/bits/wordsize.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/brk.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/clone.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/crt1.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/crti.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/crtn.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/mmap.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/setjmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/sys/procfs.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/sys/ucontext.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/Makefile.arch create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/__longjmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/__syscall_error.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bits/atomic.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bits/byteswap.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bits/endian.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bits/environments.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bits/fcntl.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bits/fenv.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bits/kernel_stat.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bits/kernel_types.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bits/mathdef.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bits/mathinline.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bits/mman.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bits/msq.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bits/sem.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bits/setjmp.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bits/shm.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bits/sigcontext.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bits/sigcontextinfo.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bits/stackinfo.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bits/stat.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bits/syscalls.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bits/uClibc_arch_features.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bits/wordsize.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/brk.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bsd-_setjmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bsd-setjmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/clone.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/crt1.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/crti.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/crtn.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/fpu_control.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/mmap.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/setjmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/sigaction.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/sys/debugreg.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/sys/epoll.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/sys/io.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/sys/perm.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/sys/procfs.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/sys/reg.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/sys/ucontext.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/sys/user.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/syscall.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/sysdep.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/vfork.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/Makefile.arch create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/__longjmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/__syscall_error.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/bits/endian.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/bits/fcntl.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/bits/ipc.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/bits/kernel_stat.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/bits/kernel_types.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/bits/mathdef.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/bits/mman.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/bits/msq.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/bits/setjmp.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/bits/shm.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/bits/sigcontextinfo.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/bits/stackinfo.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/bits/stat.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/bits/syscalls.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/bits/uClibc_arch_features.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/bits/uClibc_page.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/bits/wordsize.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/bits/xtensa-config.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/brk.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/bsd-_setjmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/bsd-setjmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/clone.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/crt1.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/crti.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/crtn.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/fork.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/mmap.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/posix_fadvise.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/posix_fadvise64.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/pread_write.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/setjmp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/sigaction.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/sigrestorer.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/sys/procfs.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/sys/ptrace.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/sys/ucontext.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/syscall.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/sysdep.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/vfork.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/windowspill.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/termios/.indent.pro create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/termios/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/termios/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/termios/cfmakeraw.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/termios/cfsetspeed.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/termios/isatty.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/termios/kernel_termios.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/termios/speed.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/termios/tcdrain.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/termios/tcflow.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/termios/tcflush.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/termios/tcgetattr.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/termios/tcgetpgrp.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/termios/tcgetsid.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/termios/tcsendbrk.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/termios/tcsetattr.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/termios/tcsetpgrp.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/termios/ttyname.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/.indent.pro create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/__exec_alloc.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/confstr.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/daemon.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/exec.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/execl.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/execle.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/execlp.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/execv.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/execvp.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/fpathconf.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/getlogin.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/getopt-susv3.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/getopt.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/getopt_int.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/getopt_long-simple.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/getpass.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/getsubopt-susv3.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/getsubopt.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/pathconf.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/sleep.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/swab.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/sysconf.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/ualarm.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/usershell.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/usleep.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libcrypt/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libcrypt/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libcrypt/crypt.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libcrypt/crypt_stub.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libcrypt/des.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libcrypt/libcrypt.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libcrypt/md5.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libintl/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libintl/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libintl/intl.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/README create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/carg.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/e_acos.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/e_acosh.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/e_asin.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/e_atan2.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/e_atanh.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/e_cosh.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/e_exp.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/e_fmod.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/e_hypot.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/e_j0.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/e_j1.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/e_jn.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/e_lgamma_r.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/e_log.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/e_log10.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/e_log2.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/e_pow.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/e_rem_pio2.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/e_remainder.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/e_scalb.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/e_sinh.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/e_sqrt.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/float_wrappers.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/i386/Makefile.arch create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/i386/fclrexcpt.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/i386/fedisblxcpt.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/i386/feenablxcpt.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/i386/fegetenv.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/i386/fegetexcept.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/i386/fegetround.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/i386/feholdexcpt.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/i386/fesetenv.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/i386/fesetround.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/i386/feupdateenv.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/i386/fgetexcptflg.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/i386/fraiseexcpt.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/i386/fsetexcptflg.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/i386/ftestexcept.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/k_cos.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/k_rem_pio2.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/k_sin.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/k_standard.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/k_tan.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/ldouble_wrappers.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/math_private.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/nan.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/powerpc/classic/Makefile.arch create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/powerpc/e500/Makefile.arch create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/powerpc/e500/README.txt create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/powerpc/e500/fpu/Makefile.arch create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/powerpc/e500/fpu/fclrexcpt.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/powerpc/e500/fpu/fe_nomask.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/powerpc/e500/fpu/fedisblxcpt.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/powerpc/e500/fpu/feenablxcpt.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/powerpc/e500/fpu/fegetenv.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/powerpc/e500/fpu/fegetexcept.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/powerpc/e500/fpu/fegetround.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/powerpc/e500/fpu/feholdexcpt.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/powerpc/e500/fpu/fenv_const.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/powerpc/e500/fpu/fenv_libc.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/powerpc/e500/fpu/fesetenv.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/powerpc/e500/fpu/fesetround.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/powerpc/e500/fpu/feupdateenv.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/powerpc/e500/fpu/fgetexcptflg.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/powerpc/e500/fpu/fraiseexcpt.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/powerpc/e500/fpu/fsetexcptflg.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/powerpc/e500/fpu/ftestexcept.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/powerpc/e500/spe-raise.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/s_asinh.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/s_atan.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/s_cbrt.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/s_ceil.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/s_copysign.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/s_cos.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/s_erf.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/s_expm1.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/s_fabs.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/s_fdim.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/s_finite.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/s_finitef.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/s_floor.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/s_fma.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/s_fmax.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/s_fmin.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/s_fpclassify.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/s_fpclassifyf.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/s_frexp.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/s_ilogb.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/s_isinf.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/s_isinff.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/s_isnan.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/s_isnanf.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/s_ldexp.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/s_lib_version.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/s_llrint.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/s_llround.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/s_log1p.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/s_logb.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/s_lrint.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/s_lround.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/s_matherr.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/s_modf.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/s_nextafter.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/s_nextafterf.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/s_remquo.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/s_rint.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/s_round.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/s_scalbn.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/s_signbit.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/s_signbitf.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/s_signgam.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/s_significand.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/s_sin.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/s_tan.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/s_tanh.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/s_trunc.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/sh/sh4/Makefile.arch create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/sh/sh4/feholdexcpt.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/sh/sh4/fesetenv.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/sh/sh4/s_lrintf.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/sh/sh4/s_lroundf.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/w_cabs.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libm/w_exp2.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libnsl/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libnsl/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libnsl/nsl.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/attr.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/cancel.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/condvar.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/debug.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/errno.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/events.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/forward.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/internals.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/join.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/libc_pthread_init.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/linuxthreads.texi create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/locale.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/lockfile.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/manager.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/mutex.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/oldsemaphore.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/pt-machine.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/ptfork.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/pthread.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/ptlongjmp.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/queue.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/restart.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/rwlock.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/semaphore.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/semaphore.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/signals.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/specific.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/spinlock.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/spinlock.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/alpha/pt-machine.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/arm/pt-machine.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/avr32/pt-machine.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/bfin/pt-machine.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/cris/pt-machine.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/frv/pt-machine.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/h8300/pt-machine.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/i386/pt-machine.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/i386/tls.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/i386/useldt.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/ia64/pt-machine.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/ia64/tls.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/m68k/pt-machine.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/microblaze/pt-machine.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/microblaze/sigcontextinfo.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/mips/pt-machine.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/nios/pt-machine.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/nios2/pt-machine.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/powerpc/pt-machine.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/pthread/bits/libc-lock.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/pthread/bits/libc-tsd.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/pthread/bits/pthreadtypes.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/pthread/not-cancel.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/pthread/pthread-functions.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/pthread/pthread.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/pthread/tls.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/sh/pt-machine.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/sh/tls.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/sh64/Makefile.arch create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/sh64/pt-machine.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/sh64/pt-machine.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/sparc/pt-machine.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/sparc/sparc32/pt-machine.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/sparc/sparc64/pt-machine.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/v850/pt-machine.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/x86_64/pt-machine.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/x86_64/tls.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/xtensa/pt-machine.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/wrapsyscall.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/Banner create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/Versions create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/proc_service.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_init.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_log.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_symbol_list.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_ta_clear_event.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_ta_delete.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_ta_enable_stats.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_ta_event_addr.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_ta_event_getmsg.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_ta_get_nthreads.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_ta_get_ph.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_ta_get_stats.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_ta_map_id2thr.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_ta_map_lwp2thr.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_ta_new.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_ta_reset_stats.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_ta_set_event.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_ta_setconcurrency.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_ta_thr_iter.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_ta_tsd_iter.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_thr_clear_event.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_thr_dbresume.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_thr_dbsuspend.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_thr_event_enable.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_thr_event_getmsg.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_thr_get_info.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_thr_getfpregs.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_thr_getgregs.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_thr_getxregs.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_thr_getxregsize.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_thr_set_event.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_thr_setfpregs.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_thr_setgregs.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_thr_setprio.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_thr_setsigpending.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_thr_setxregs.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_thr_sigsetmask.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_thr_tls_get_addr.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_thr_tsd.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_thr_validate.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/thread_db.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/thread_dbP.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/.cvsignore create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/alloca_cutoff.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/attr.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/barrier.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/cancel.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/condvar.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/descr.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/errno.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/events.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/forward.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/internals.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/join.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/libc-cancellation.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/libc_pthread_init.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/lockfile.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/manager.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/mutex.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/pt-machine.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/ptcleanup.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/ptclock_gettime.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/ptclock_settime.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/ptfork.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/pthandles.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/pthread.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/pthread_atfork.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/pthread_setegid.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/pthread_seteuid.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/pthread_setgid.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/pthread_setregid.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/pthread_setresgid.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/pthread_setresuid.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/pthread_setreuid.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/pthread_setuid.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/queue.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/restart.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/rwlock.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/semaphore.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/semaphore.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sighandler.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/signals.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/specific.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/spinlock.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/spinlock.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/alpha/elf/pt-initfini.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/alpha/pspinlock.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/alpha/pt-machine.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/alpha/tls.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/arm/pspinlock.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/arm/pt-machine.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/arm/sysdep-cancel.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/arm/sysdep.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/arm/tls.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/avr32/pt-machine.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/cris/pspinlock.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/cris/pt-machine.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/hppa/pspinlock.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/hppa/pt-machine.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/i386/i686/pt-machine.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/i386/pspinlock.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/i386/pt-machine.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/i386/tcb-offsets.sym create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/i386/tls.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/i386/useldt.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/ia64/pspinlock.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/ia64/pt-machine.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/ia64/tcb-offsets.sym create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/ia64/tls.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/m68k/pspinlock.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/m68k/pt-machine.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/mips/pspinlock.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/mips/pt-machine.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/mips/tls.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/powerpc/powerpc32/pspinlock.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/powerpc/powerpc32/pt-machine.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/powerpc/powerpc64/pspinlock.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/powerpc/powerpc64/pt-machine.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/powerpc/pspinlock.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/powerpc/pt-machine.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/powerpc/tcb-offsets.sym create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/powerpc/tls.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/.cvsignore create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/bits/initspin.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/bits/libc-lock.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/bits/libc-tsd.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/bits/pthreadtypes.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/bits/typesizes.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/errno-loc.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/flockfile.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/ftrylockfile.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/funlockfile.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/getcpuclockid.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/herrno-loc.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/list.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/malloc-machine.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/not-cancel.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/posix-timer.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/pt-initfini.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/pthread-functions.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/pthread.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/ptlongjmp.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/res-state.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/semaphore.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/sigaction.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/tcb-offsets.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/timer_create.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/timer_delete.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/timer_getoverr.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/timer_gettime.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/timer_routines.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/timer_settime.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/tst-timer.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/uClibc-glue.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/s390/pspinlock.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/s390/s390-32/pt-machine.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/s390/s390-64/pt-machine.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/s390/tcb-offsets.sym create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/s390/tls.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/sh/pspinlock.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/sh/pt-machine.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/sh/tcb-offsets.sym create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/sh/tls.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/sparc/pspinlock.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/sparc/pt-machine.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/sparc/sparc32/pspinlock.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/sparc/sparc32/pt-machine.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/sparc/sparc32/sparcv9/pspinlock.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/sparc/sparc64/pspinlock.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/sparc/sparc64/pt-machine.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/sparc/tcb-offsets.sym create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/sparc/tls.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/.cvsignore create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/allocalim.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/allocrtsig.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/alpha/aio_cancel.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/alpha/bits/local_lim.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/alpha/bits/typesizes.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/alpha/pt-sigsuspend.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/alpha/sysdep-cancel.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/alpha/vfork.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/arm/sysdep-cancel.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/arm/vfork.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/execve.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/fork.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/fork.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/hppa/aio_cancel.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/hppa/bits/initspin.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/hppa/malloc-machine.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/hppa/pt-initfini.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/hppa/sysdep-cancel.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/i386/sysdep-cancel.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/i386/vfork.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/ia64/bits/local_lim.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/ia64/fork.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/ia64/pt-initfini.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/ia64/pt-sigsuspend.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/ia64/sysdep-cancel.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/ia64/vfork.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/jmp-unwind.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/m68k/sysdep-cancel.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/m68k/vfork.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/mips/mips64/sysdep-cancel.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/mips/sysdep-cancel.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/mips/vfork.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/mq_notify.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/powerpc/powerpc32/vfork.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/powerpc/powerpc64/vfork.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/powerpc/ptlongjmp.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/pt-sigsuspend.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/raise.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/register-atfork.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/s390/bits/typesizes.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-32/pt-initfini.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-32/sysdep-cancel.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-32/vfork.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-64/pt-initfini.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-64/pt-sigsuspend.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-64/vfork.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sh/pt-initfini.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sh/smp.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sh/sysdep-cancel.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sh/vfork.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sigwait.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/smp.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sparc/aio_cancel.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sparc/bits/local_lim.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sparc/bits/typesizes.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sparc/fork.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc32/sysdep-cancel.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc32/vfork.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc64/pt-sigsuspend.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc64/sysdep-cancel.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc64/vfork.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sparc/sysdep-cancel.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/unregister-atfork.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/x86_64/pt-sigsuspend.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/x86_64/vfork.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/x86_64/pspinlock.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/x86_64/pt-machine.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/x86_64/tcb-offsets.sym create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/x86_64/tls.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/.cvsignore create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/Banner create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/ChangeLog create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/Makefile.old create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/Versions create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/proc_service.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/shlib-versions create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_init.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_log.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_symbol_list.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_ta_clear_event.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_ta_delete.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_ta_enable_stats.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_ta_event_addr.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_ta_event_getmsg.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_ta_get_nthreads.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_ta_get_ph.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_ta_get_stats.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_ta_map_id2thr.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_ta_map_lwp2thr.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_ta_new.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_ta_reset_stats.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_ta_set_event.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_ta_setconcurrency.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_ta_thr_iter.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_ta_tsd_iter.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_thr_clear_event.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_thr_dbresume.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_thr_dbsuspend.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_thr_event_enable.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_thr_event_getmsg.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_thr_get_info.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_thr_getfpregs.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_thr_getgregs.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_thr_getxregs.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_thr_getxregsize.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_thr_set_event.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_thr_setfpregs.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_thr_setgregs.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_thr_setprio.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_thr_setsigpending.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_thr_setxregs.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_thr_sigsetmask.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_thr_tls_get_addr.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_thr_tlsbase.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_thr_tsd.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_thr_validate.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/thread_db.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/thread_dbP.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/.gitignore create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/ChangeLog create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/DESIGN-barrier.txt create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/DESIGN-condvar.txt create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/DESIGN-rwlock.txt create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/DESIGN-sem.txt create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/README.NPTL create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/TODO create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/TODO-kernel create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/TODO-testing create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/alloca_cutoff.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/allocatestack.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/banner.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/cancellation.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/cleanup.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/cleanup_compat.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/cleanup_defer.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/cleanup_defer_compat.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/cleanup_routine.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/descr.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/errno_location.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/events.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/forward.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/herrno.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/init.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/libc-cancellation.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/linux_fsinfo.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pt-cleanup.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pt-system.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread-errnos.sym create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthreadP.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_atfork.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_attr_destroy.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_attr_getdetachstate.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_attr_getguardsize.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_attr_getinheritsched.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_attr_getschedparam.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_attr_getschedpolicy.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_attr_getscope.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_attr_getstack.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_attr_getstackaddr.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_attr_getstacksize.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_attr_init.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_attr_setdetachstate.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_attr_setguardsize.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_attr_setinheritsched.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_attr_setschedparam.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_attr_setschedpolicy.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_attr_setscope.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_attr_setstack.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_attr_setstackaddr.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_attr_setstacksize.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_barrierattr_destroy.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_barrierattr_getpshared.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_barrierattr_init.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_barrierattr_setpshared.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_cancel.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_clock_gettime.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_clock_settime.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_cond_destroy.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_cond_init.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_condattr_destroy.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_condattr_getclock.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_condattr_getpshared.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_condattr_init.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_condattr_setclock.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_condattr_setpshared.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_create.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_detach.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_equal.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_exit.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_getattr_np.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_getconcurrency.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_getschedparam.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_getspecific.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_join.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_key_create.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_key_delete.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_kill_other_threads.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_mutex_consistent.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_mutex_destroy.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_mutex_getprioceiling.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_mutex_init.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_mutex_lock.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_mutex_setprioceiling.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_mutex_timedlock.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_mutex_trylock.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_mutex_unlock.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_mutexattr_destroy.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_mutexattr_getprioceiling.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_mutexattr_getprotocol.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_mutexattr_getpshared.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_mutexattr_getrobust.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_mutexattr_gettype.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_mutexattr_init.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_mutexattr_setprioceiling.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_mutexattr_setprotocol.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_mutexattr_setpshared.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_mutexattr_setrobust.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_mutexattr_settype.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_rwlock_destroy.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_rwlock_init.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_rwlock_tryrdlock.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_rwlock_trywrlock.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_rwlockattr_destroy.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_rwlockattr_getkind_np.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_rwlockattr_getpshared.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_rwlockattr_init.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_rwlockattr_setkind_np.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_rwlockattr_setpshared.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_self.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_setcancelstate.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_setcanceltype.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_setconcurrency.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_setegid.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_seteuid.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_setgid.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_setregid.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_setresgid.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_setresuid.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_setreuid.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_setschedparam.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_setschedprio.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_setspecific.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_setuid.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_testcancel.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_timedjoin.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_tryjoin.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/res.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sem_close.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sem_destroy.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sem_getvalue.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sem_init.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sem_open.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sem_unlink.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/semaphore.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/semaphoreP.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/Makefile.commonarch create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/alpha/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/alpha/dl-tls.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/alpha/elf/pt-initfini.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/alpha/jmpbuf-unwind.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/alpha/libc-tls.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/alpha/pthread_spin_lock.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/alpha/pthread_spin_trylock.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/alpha/pthreaddef.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/alpha/tcb-offsets.sym create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/alpha/tls.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/arm/Makefile.arch create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/arm/aeabi_read_tp.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/arm/aeabi_unwind_cpp_pr1.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/arm/dl-tls.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/arm/jmpbuf-unwind.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/arm/pthread_spin_lock.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/arm/pthread_spin_trylock.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/arm/pthreaddef.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/arm/tcb-offsets.sym create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/arm/thumb_atomics.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/arm/tls.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/generic/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/generic/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/generic/dl-tls.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/generic/dl-tls.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/generic/libc-tls.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/generic/lowlevellock.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/generic/unwind.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/i386/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/i386/Makefile.arch create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/i386/dl-tls.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/i386/i486/pthread_spin_trylock.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/i386/i586/pthread_spin_trylock.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/i386/i686/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/i386/i686/pthread_spin_trylock.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/i386/i686/tls.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/i386/jmpbuf-unwind.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/i386/pthread_spin_init.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/i386/pthread_spin_lock.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/i386/pthread_spin_unlock.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/i386/pthreaddef.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/i386/tcb-offsets.sym create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/i386/tls.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/mips/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/mips/Makefile.arch create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/mips/dl-tls.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/mips/jmpbuf-unwind.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/mips/libc-tls.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/mips/nptl-sysdep.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/mips/pthread_spin_lock.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/mips/pthread_spin_trylock.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/mips/pthreaddef.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/mips/regdef.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/mips/tcb-offsets.sym create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/mips/tls.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/powerpc/Makefile.arch create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/powerpc/dl-tls.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/powerpc/jmpbuf-unwind.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/powerpc/pthread_spin_lock.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/powerpc/pthread_spin_trylock.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/powerpc/pthreaddef.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/powerpc/tcb-offsets.sym create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/powerpc/tls.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/allocalim.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/bits/libc-lock.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/bits/libc-tsd.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/bits/sigthread.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/bits/stdio-lock.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/createthread.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/defs.awk create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/librt-cancellation.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/list.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/malloc-machine.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/posix-timer.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/pt-initfini.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/pt-longjmp.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/pthread-functions.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/pthread.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/pthread_barrier_destroy.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/pthread_barrier_init.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/pthread_barrier_wait.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/pthread_cond_broadcast.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/pthread_cond_signal.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/pthread_cond_timedwait.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/pthread_cond_wait.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/pthread_once.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/pthread_rwlock_rdlock.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/pthread_rwlock_timedrdlock.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/pthread_rwlock_timedwrlock.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/pthread_rwlock_unlock.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/pthread_rwlock_wrlock.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/pthread_sigmask.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/pthread_spin_destroy.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/pthread_spin_init.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/pthread_spin_unlock.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/rt-unwind-resume.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/setxid.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/sigaction.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/sigfillset.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/sigprocmask.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/timer_create.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/timer_delete.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/timer_getoverr.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/timer_gettime.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/timer_routines.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/timer_settime.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/tpp.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/uClibc-glue.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/unwind-forcedunwind.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/unwind-resume.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sh/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sh/Makefile.arch create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sh/dl-tls.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sh/jmpbuf-unwind.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sh/libc-tls.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sh/pthread_spin_init.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sh/pthread_spin_lock.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sh/pthread_spin_trylock.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sh/pthread_spin_unlock.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sh/pthreaddef.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sh/tcb-offsets.sym create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sh/tls.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sparc/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sparc/Makefile.arch create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sparc/dl-tls.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sparc/jmpbuf-unwind.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sparc/pthreaddef.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sparc/sparc32/jmpbuf-unwind.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sparc/sparc32/pthread_spin_lock.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sparc/sparc32/pthread_spin_trylock.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sparc/sparc32/pthreaddef.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sparc/sparc32/sparcv9/pthread_spin_lock.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sparc/sparc32/sparcv9/pthread_spin_trylock.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sparc/sparc32/sparcv9/pthread_spin_unlock.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sparc/sparc64/jmpbuf-unwind.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sparc/sparc64/pthread_spin_lock.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sparc/sparc64/pthread_spin_trylock.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sparc/sparc64/pthread_spin_unlock.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sparc/sparc64/pthreaddef.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sparc/tcb-offsets.sym create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sparc/tls.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/Makefile.commonarch create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/__syscall_error.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/accept.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/bits/local_lim.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/bits/semaphore.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/clone.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/createthread.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/fork.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/lowlevellock.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/pt-vfork.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/pthread_once.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/sem_post.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/sysdep-cancel.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/timer_create.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/timer_delete.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/timer_getoverr.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/timer_gettime.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/timer_settime.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/vfork.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/arm/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/arm/Makefile.arch create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/arm/bits/atomic.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/arm/bits/pthreadtypes.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/arm/bits/semaphore.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/arm/clone.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/arm/createthread.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/arm/fork.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/arm/libc-lowlevellock.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/arm/lowlevellock.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/arm/lowlevellock.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/arm/nptl-aeabi_unwind_cpp_pr1.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/arm/pt-__syscall_error.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/arm/pt-__syscall_rt_sigaction.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/arm/pt-gettimeofday.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/arm/pt-vfork.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/arm/pthread_once.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/arm/sysdep-cancel.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/arm/unwind-forcedunwind.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/arm/unwind-resume.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/arm/unwind.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/arm/vfork.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/bits/local_lim.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/bits/posix_opt.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/close.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/connect.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/creat.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/createthread.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/exit-thread.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/fork.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/fork.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/getpid.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/Makefile.arch create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/bits/semaphore.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/clone.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/createthread.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/fork.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/libc-lowlevellock.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevelrobustlock.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_barrier_wait.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_signal.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_rdlock.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedrdlock.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedwrlock.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_unlock.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_wrlock.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_post.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_trywait.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_wait.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/libc-lowlevellock.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/lowlevellock.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/lowlevelrobustlock.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_barrier_wait.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_cond_broadcast.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_cond_signal.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_cond_timedwait.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_cond_wait.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_rwlock_rdlock.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_rwlock_timedrdlock.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_rwlock_timedwrlock.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_rwlock_unlock.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_rwlock_wrlock.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/sem_post.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/sem_timedwait.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/sem_trywait.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/sem_wait.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/libc-lowlevellock.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/lowlevellock.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/lowlevelrobustlock.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_barrier_wait.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_cond_broadcast.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_cond_signal.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_cond_timedwait.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_cond_wait.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_rwlock_rdlock.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_rwlock_timedrdlock.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_rwlock_timedwrlock.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_rwlock_unlock.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_rwlock_wrlock.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/sem_post.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/sem_timedwait.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/sem_trywait.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/sem_wait.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/pt-__syscall_error.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/pt-vfork.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/pthread_once.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/pthread_spin_init.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/pthread_spin_unlock.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/smp.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/sysdep-cancel.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/vfork.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/internaltypes.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/jmp-unwind.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/kernel-posix-timers.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/libc-lowlevellock.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/libc_multiple_threads.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/libc_pthread_init.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevelbarrier.sym create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevelcond.sym create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevellock.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevelrobustlock.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevelrobustlock.sym create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevelrwlock.sym create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/lseek.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/mips/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/mips/Makefile.arch create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/mips/bits/pthreadtypes.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/mips/bits/semaphore.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/mips/clone.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/mips/createthread.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/mips/fork.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/mips/lowlevellock.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/mips/pt-__syscall_rt_sigaction.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/mips/pt-clone.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/mips/pt-vfork.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/mips/pthread_once.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/mips/sysdep-cancel.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/mips/vfork.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/mq_notify.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/msync.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/nanosleep.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/not-cancel.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/open.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pause.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/Makefile.arch create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/bits/semaphore.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/clone.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/createthread.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/fork.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/lowlevellock.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc32/clone.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc32/pt-vfork.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc32/vfork.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/clone.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/pt-vfork.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/timer_create.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/timer_delete.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/timer_getoverr.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/timer_gettime.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/timer_settime.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/vfork.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/pt-__syscall_error.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/pt-longjmp.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/pt-vfork.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/pthread_once.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/pthread_spin_unlock.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/sem_post.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/sysdep-cancel.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/vfork.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-accept.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-close.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-connect.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-fcntl.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-fork.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-fsync.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-llseek.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-lseek.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-msgrcv.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-msgsnd.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-msync.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-nanosleep.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-open.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-open64.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-pause.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-pread_pwrite.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-raise.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-read.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-recv.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-recvfrom.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-recvmsg.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-send.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-sendmsg.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-sendto.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-sigwait.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-sleep.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-tcdrain.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-wait.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-waitpid.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-write.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pthread-pi-defines.sym create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_attr_getaffinity.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_attr_setaffinity.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_getaffinity.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_getcpuclockid.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_kill.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_mutex_cond_lock.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_setaffinity.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_sigqueue.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_yield.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/raise.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/read.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/recv.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/recvfrom.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/recvmsg.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/register-atfork.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sem_post.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sem_timedwait.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sem_trywait.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sem_wait.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/send.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sendmsg.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sendto.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/Makefile.arch create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/bits/semaphore.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/clone.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/createthread.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/fork.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/libc-lowlevellock.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/lowlevel-atomic.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/lowlevellock.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/lowlevellock.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/lowlevelrobustlock.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pt-initfini.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pt-vfork.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_barrier_wait.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_broadcast.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_signal.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_timedwait.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_wait.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_once.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_rdlock.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedrdlock.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedwrlock.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_unlock.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_wrlock.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sem_post.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sem_timedwait.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sem_trywait.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sem_wait.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sh4/lowlevellock.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/smp.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sysdep-cancel.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/vfork.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sigtimedwait.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sigwait.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sigwaitinfo.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sleep.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/smp.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/Makefile.arch create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/bits/local_lim.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/bits/pthreadtypes.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/bits/semaphore.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/clone.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/fork.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/internaltypes.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/libc-lowlevellock.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/lowlevellock.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/lowlevellock.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/pt-vfork.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/pthread_barrier_destroy.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/pthread_barrier_init.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/pthread_barrier_wait.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/pthread_once.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sem_init.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/clone.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/pt-vfork.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/pthread_barrier_wait.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_post.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_timedwait.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_trywait.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_wait.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sysdep-cancel.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/vfork.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/clone.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/pt-vfork.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/sysdep-cancel.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/timer_create.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/timer_delete.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/timer_getoverr.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/timer_gettime.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/timer_settime.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/vfork.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sysdep-cancel.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/vfork.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/structsem.sym create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/timer_create.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/timer_delete.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/timer_getoverr.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/timer_gettime.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/timer_routines.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/timer_settime.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/unregister-atfork.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/unwindbuf.sym create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/waitpid.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/write.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/Makefile.arch create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/bits/semaphore.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/cancellation.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/clone.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/compat-timer.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/fork.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/libc-cancellation.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/libc-lowlevellock.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/librt-cancellation.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevelrobustlock.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pt-__syscall_error.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pt-vfork.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_barrier_wait.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_once.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_rdlock.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedrdlock.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedwrlock.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_unlock.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_wrlock.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_setaffinity.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_spin_init.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_spin_unlock.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/sem_post.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/sem_trywait.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/sem_wait.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/vfork.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/x86_64/Makefile.arch create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/x86_64/dl-tls.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/x86_64/jmpbuf-unwind.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/x86_64/pthread_spin_init.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/x86_64/pthread_spin_lock.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/x86_64/pthread_spin_trylock.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/x86_64/pthread_spin_unlock.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/x86_64/pthreaddef.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/x86_64/tcb-offsets.sym create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/x86_64/tls.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/unwind.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/vars.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/version.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/version.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/ChangeLog create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/db_info.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/fetch-value.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/proc_service.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/structs.def create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_init.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_log.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_symbol_list.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_ta_clear_event.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_ta_delete.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_ta_enable_stats.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_ta_event_addr.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_ta_event_getmsg.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_ta_get_nthreads.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_ta_get_ph.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_ta_get_stats.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_ta_map_id2thr.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_ta_map_lwp2thr.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_ta_new.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_ta_reset_stats.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_ta_set_event.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_ta_setconcurrency.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_ta_thr_iter.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_ta_tsd_iter.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_thr_clear_event.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_thr_dbresume.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_thr_dbsuspend.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_thr_event_enable.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_thr_event_getmsg.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_thr_get_info.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_thr_getfpregs.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_thr_getgregs.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_thr_getxregs.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_thr_getxregsize.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_thr_set_event.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_thr_setfpregs.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_thr_setgregs.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_thr_setprio.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_thr_setsigpending.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_thr_setxregs.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_thr_sigsetmask.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_thr_tls_get_addr.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_thr_tlsbase.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_thr_tsd.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_thr_validate.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/thread_db.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/thread_dbP.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libresolv/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libresolv/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libresolv/resolv.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/librt/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/librt/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/librt/clock_getcpuclockid.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/librt/clock_gettime.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/librt/clock_nanosleep.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/librt/kernel-posix-cpu-timers.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/librt/kernel-posix-timers.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/librt/mq_close.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/librt/mq_getsetattr.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/librt/mq_notify.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/librt/mq_open.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/librt/mq_receive.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/librt/mq_send.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/librt/mq_timedreceive.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/librt/mq_timedsend.S create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/librt/mq_unlink.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/librt/shm.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/librt/timer_create.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/librt/timer_delete.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/librt/timer_getoverr.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/librt/timer_gettime.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/librt/timer_settime.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libubacktrace/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libubacktrace/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libubacktrace/backtrace.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libubacktrace/backtracesyms.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libubacktrace/backtracesymsfd.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libubacktrace/sysdeps/sh/Makefile.arch create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libubacktrace/sysdeps/sh/backtrace.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libutil/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libutil/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libutil/forkpty.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libutil/login.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libutil/login_tty.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libutil/logout.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libutil/logwtmp.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/libutil/openpty.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/.gitignore create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/aio.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/arpa_inet.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/complex.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/ctype-CX.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/ctype-OBXSI.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/ctype.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/dirent-XSI.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/dirent.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/dlfcn.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/fcntl-ADV.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/fcntl.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/fenv.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/ftw-OB.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/ftw.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/glob.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/grp-XSI.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/grp.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/html2input.sh create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/iconv.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/inttypes.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/libgen.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/locale-CX.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/locale.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/math-XSI.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/math.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/monetary.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/mqueue.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/ndbm.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/net_if.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/netdb.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/nl_types.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/pthread-MC1.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/pthread-OBXSI.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/pthread-RPP|TPP.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/pthread-TCT.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/pthread-TPS.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/pthread-TSATSS.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/pthread-TSH.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/pthread-TSS.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/pthread.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/pwd-XSI.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/pwd.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/regex.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/sched-PS.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/sched-PS|TPS.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/sched.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/search.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/semaphore.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/separate.awk create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/setjmp-CX.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/setjmp-OBXSI.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/setjmp.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/signal-CX.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/signal-OBXSI.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/signal-XSI.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/signal.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/spawn-PS.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/spawn.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/stdio-CX.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/stdio-OB.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/stdio-OBXSI.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/stdio.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/stdlib-ADV.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/stdlib-CX.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/stdlib-OBCX.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/stdlib-XSI.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/stdlib.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/string-CX.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/string-XSI.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/string.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/strings-XSI.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/strings.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/stropts.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/sys_mman-ADV.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/sys_mman-ML.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/sys_mman-MLR.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/sys_mman-SHM.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/sys_mman-TYM.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/sys_mman-XSI|SIO.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/sys_mman.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/sys_msg.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/sys_resource.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/sys_select.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/sys_sem.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/sys_shm.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/sys_socket.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/sys_stat-XSI.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/sys_stat.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/sys_statvfs.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/sys_time-OB.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/sys_time.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/sys_uio.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/sys_wait.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/syslog.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/termios.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/time-CPT.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/time-CX.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/time-OB.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/time-OBCX.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/time-XSI.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/time.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/trace-TEF.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/trace-TRI.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/trace-TRL.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/trace.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/tst-API.sh create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/unistd-CX.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/unistd-FSC.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/unistd-OBXSI.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/unistd-SIO.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/unistd-XSI.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/unistd.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/utmpx.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/wchar-CX.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/wchar-OBXSI.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/wchar-XSI.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/wchar.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/wctype-CX.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/wctype.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/API/wordexp.SUSv4.syms create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/README create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/Rules.mak create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/Test.mak create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/args/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/args/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/args/arg_test.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/args/arg_test.out.good create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/args/arg_test_glibc.out.good create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/assert/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/assert/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/assert/assert.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/build/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/build/check_config_options.sh create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/crypt/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/crypt/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/crypt/crypt.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/crypt/crypt.input create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/crypt/crypt.out.good create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/crypt/md5c-test.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/ctype/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/ctype/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/ctype/ctype.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/dlopen/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/dlopen/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/dlopen/dladdr.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/dlopen/dlafk.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/dlopen/dlstatic.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/dlopen/dltest.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/dlopen/dltest2.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/dlopen/dlundef.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/dlopen/libafk-temp.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/dlopen/libafk.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/dlopen/libstatic.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/dlopen/libtest.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/dlopen/libtest1.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/dlopen/libtest2.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/dlopen/libtest3.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/dlopen/libundef.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/dlopen/test1.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/dlopen/test2.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/dlopen/test3.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/inet/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/inet/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/inet/bug-if1.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/inet/gethost_r-align.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/inet/gethostid.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/inet/getnetent.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/inet/if_nameindex.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/inet/tst-aton.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/inet/tst-ethers-line.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/inet/tst-ethers.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/inet/tst-network.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/inet/tst-ntoa.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/librt/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/librt/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/librt/shmtest.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_isw-funcs.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_iswalnum.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_iswalpha.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_iswcntrl.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_iswctype.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_iswdigit.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_iswgraph.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_iswlower.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_iswprint.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_iswpunct.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_iswspace.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_iswupper.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_iswxdigit.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_mblen.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_mbrlen.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_mbrtowc.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_mbsrtowcs.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_mbstowcs.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_mbtowc.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_strcoll.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_strfmon.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_strxfrm.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_swscanf.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_tow-funcs.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_towctrans.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_towlower.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_towupper.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wcrtomb.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wcscat.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wcschr.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wcscmp.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wcscoll.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wcscpy.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wcscspn.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wcslen.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wcsncat.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wcsncmp.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wcsncpy.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wcspbrk.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wcsrtombs.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wcsspn.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wcsstr.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wcstod.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wcstok.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wcstombs.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wcswidth.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wcsxfrm.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wctob.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wctomb.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wctrans.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wctype.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wcwidth.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tgn_funcdef.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tgn_locdef.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tsp_common.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst2_mbrtowc.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_funcs.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_iswalnum.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_iswalpha.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_iswcntrl.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_iswctype.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_iswdigit.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_iswgraph.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_iswlower.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_iswprint.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_iswpunct.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_iswspace.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_iswupper.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_iswxdigit.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_mblen.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_mbrlen.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_mbrtowc.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_mbsrtowcs.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_mbstowcs.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_mbtowc.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_strcoll.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_strfmon.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_strxfrm.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_swscanf.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_towctrans.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_towlower.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_towupper.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_types.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wcrtomb.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wcscat.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wcschr.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wcscmp.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wcscoll.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wcscpy.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wcscspn.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wcslen.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wcsncat.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wcsncmp.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wcsncpy.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wcspbrk.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wcsrtombs.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wcsspn.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wcsstr.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wcstod.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wcstok.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wcstombs.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wcswidth.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wcsxfrm.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wctob.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wctomb.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wctrans.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wctype.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wcwidth.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale/bug-iconv-trans.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale/bug-usesetlocale.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale/collate-test.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale/dump-ctype.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale/gen-unicode-ctype.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale/show-ucs-data.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-C-locale.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-ctype-de_DE.ISO-8859-1.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-ctype.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-digits.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-fmon.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-langinfo.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-langinfo.input create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-leaks.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-mbswcs1.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-mbswcs2.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-mbswcs3.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-mbswcs4.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-mbswcs5.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-mbswcs6.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-numeric.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-rpmatch.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-setlocale.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-sscanf.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-strfmon1.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-trans.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-wctype.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-xlocale1.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-xlocale2.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst_nl_langinfo.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/locale/xfrm-test.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/malloc/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/malloc/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/malloc/malloc-standard-alignment.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/malloc/malloc.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/malloc/mallocbug.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/malloc/realloc-can-shrink.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/malloc/realloc0.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/malloc/testmalloc.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/malloc/time_malloc.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/malloc/tst-calloc.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/malloc/tst-malloc.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/malloc/tst-mallocfork.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/malloc/tst-mcheck.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/malloc/tst-obstack.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/malloc/tst-valloc.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/math/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/math/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/math/basic-test.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/math/c99_test.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/math/compile_test.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/math/fenv.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/math/gamma.c create mode 100755 l4/pkg/uclibc/lib/contrib/uclibc/test/math/gen-libm-test.pl create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/math/ilogb.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/math/libm-test-ulps-generic create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/math/libm-test-ulps-i386 create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/math/libm-test-ulps-ia64 create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/math/libm-test-ulps-powerpc create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/math/libm-test-ulps-s390 create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/math/libm-test-ulps-sh4 create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/math/libm-test-ulps-sparc32 create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/math/libm-test-ulps-sparc64 create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/math/libm-test-ulps-x86_64 create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/math/libm-test.inc create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/math/rint.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/math/signgam.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/math/test-double.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/math/test-float.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/math/test-fpucw.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/math/test-idouble.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/math/test-ifloat.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/math/test-ildoubl.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/math/test-ldouble.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/math/tst-definitions.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/misc/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/misc/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/misc/bug-glob1.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/misc/bug-glob2.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/misc/bug-readdir1.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/misc/dirent.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/misc/dirent64.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/misc/fdopen.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/misc/opendir-tst1.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/misc/outb.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/misc/popen.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/misc/seek.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/misc/sem.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/misc/stdarg.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/misc/tst-fnmatch.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/misc/tst-fnmatch.input create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/misc/tst-gnuglob.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/misc/tst-scandir.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/misc/tst-seekdir.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/misc/tst-utmp.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/mmap/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/mmap/mmap.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/mmap/mmap2.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/mmap/mmap64.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/eintr.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-align.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-align2.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-align3.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-atfork1.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-attr1.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-attr2.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-attr3.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-barrier1.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-barrier2.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-barrier3.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-barrier4.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-basic1.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-basic2.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-basic3.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-basic4.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-basic5.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-basic6.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-basic7.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel1.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel10.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel11.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel12.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel13.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel14.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel15.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel16.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel18.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel19.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel2.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel20.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel21.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel22.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel23.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel25.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel3.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel4.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel5.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel6.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel7.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel8.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel9.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancelx10.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancelx11.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancelx12.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancelx13.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancelx14.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancelx15.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancelx16.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancelx18.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancelx2.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancelx20.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancelx21.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancelx3.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancelx4.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancelx6.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancelx7.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancelx8.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancelx9.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cleanup0.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cleanup1.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cleanup2.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cleanup3.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cleanup4.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cleanup4aux.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cleanupx0.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cleanupx1.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cleanupx2.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cleanupx3.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cleanupx4.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-clock.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-clock1.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-clock2.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-clock_nanosleep.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond1.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond10.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond11.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond12.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond13.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond14.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond15.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond16.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond17.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond18.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond19.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond2.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond20.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond21.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond22.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond23.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond3.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond4.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond5.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond6.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond7.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond8.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond9.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cpuclock1.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cpuclock2.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cputimer1.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cputimer2.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cputimer3.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-detach1.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-dlsym1.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-eintr1.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-eintr2.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-eintr3.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-eintr4.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-eintr5.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-exec2.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-exec3.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-exec4.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-exit1.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-exit2.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-exit3.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-fini1.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-fini1mod.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-flock1.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-flock2.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-fork1.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-fork2.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-fork3.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-fork4.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-getpid1.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-getpid2.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-getpid3.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-initializers1-c89.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-initializers1-c99.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-initializers1-gnu89.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-initializers1-gnu99.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-initializers1.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-join1.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-join2.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-join3.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-join4.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-join5.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-join6.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-key1.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-key2.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-key3.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-key4.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-kill1.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-kill2.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-kill3.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-kill4.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-kill5.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-kill6.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-mqueue.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-mqueue1.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-mqueue2.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-mqueue3.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-mqueue4.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-mqueue5.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-mqueue6.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-mqueue7.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-mqueue8.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-mqueue9.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-mutex1.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-mutex2.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-mutex3.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-mutex4.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-mutex5.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-mutex5a.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-mutex6.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-mutex7.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-mutex7a.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-mutex8.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-mutex9.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-oddstacklimit.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-once1.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-once2.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-once3.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-once4.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-oncex3.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-oncex4.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-popen1.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-raise1.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-rwlock1.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-rwlock10.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-rwlock11.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-rwlock12.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-rwlock13.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-rwlock14.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-rwlock2.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-rwlock2a.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-rwlock3.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-rwlock4.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-rwlock5.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-rwlock6.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-rwlock7.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-rwlock8.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-rwlock9.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-sched1.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-sem1.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-sem10.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-sem11.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-sem12.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-sem2.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-sem3.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-sem4.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-sem5.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-sem6.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-sem7.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-sem8.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-sem9.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-signal1.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-signal2.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-signal3.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-signal4.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-signal5.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-signal6.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-signal7.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-spin1.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-spin2.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-spin3.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-stack-align.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-stack1.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-stack2.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-stdio1.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-stdio2.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-sysconf.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-timer2.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-timer3.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-timer4.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-timer5.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-tls1.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-tls2.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-tls3.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-tls3mod.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-tls4.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-tls4moda.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-tls4modb.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-tls5.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-tls5.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-tls5mod.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-tls5moda.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-tls5modb.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-tls5modc.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-tls5modd.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-tls5mode.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-tls5modf.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-tsd1.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-tsd2.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-tsd3.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-tsd4.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-tsd5.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-tsd6.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-typesizes.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-umask1.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-unload.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-vfork1.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-vfork1x.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-vfork2.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-vfork2x.c create mode 100755 l4/pkg/uclibc/lib/contrib/uclibc/test/plt/check-plt.sh create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/pthread/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/pthread/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/pthread/cancellation-points.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/pthread/ex1.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/pthread/ex2.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/pthread/ex3.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/pthread/ex4.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/pthread/ex5.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/pthread/ex6.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/pthread/ex7.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/pthread/tst-too-many-cleanups.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/pwd_grp/.indent.pro create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/pwd_grp/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/pwd_grp/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/pwd_grp/getgroups.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/pwd_grp/grcat.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/pwd_grp/pwcat.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/pwd_grp/test_grp.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/pwd_grp/test_pwd.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/regex/LICENSE create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/regex/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/regex/basic.dat create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/regex/categorize.dat create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/regex/forcedassoc.dat create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/regex/interpretation.dat create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/regex/leftassoc.dat create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/regex/nullsubexpr.dat create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/regex/repetition.dat create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/regex/rightassoc.dat create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/regex/testregex.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/regex/tst-regex2.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/regex/tst-regex2.dat create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/regex/tst-regexloc.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/rpc/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/rpc/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/rpc/getrpcent.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/rpc/getrpcent_r.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/setjmp/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/setjmp/bug269-setjmp.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/setjmp/jmpbug.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/setjmp/sigjmpbug.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/setjmp/tst-setjmp.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/setjmp/tst-vfork-longjmp.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/signal/.indent.pro create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/signal/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/signal/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/signal/sigchld.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/signal/signal.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/signal/tst-raise.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/signal/tst-signal.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/signal/tst-sigset.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/signal/tst-sigsimple.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/silly/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/silly/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/silly/hello.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/silly/tiny.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/stat/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/stat/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/stat/memcmp-stat.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/stat/stat.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/stat/stat64.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/stdio/64bit.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/stdio/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/stdio/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/stdio/fclose-loop.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/stdlib/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/stdlib/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/stdlib/ptytest.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/stdlib/qsort.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/stdlib/test-canon.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/stdlib/test-canon2.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/stdlib/testatexit.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/stdlib/teston_exit.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/stdlib/teststrtol.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/stdlib/teststrtoq.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/string/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/string/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/string/bug-strcoll1.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/string/bug-strncat1.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/string/bug-strpbrk1.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/string/bug-strspn1.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/string/stratcliff.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/string/test-ffs.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/string/testcopy.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/string/tester.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/string/tst-bswap.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/string/tst-inlcall.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/string/tst-strlen.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/string/tst-strtok.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/string/tst-strxfrm.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/termios/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/termios/termios.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/test-skeleton.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/testsuite.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/time/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/time/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/time/bug-asctime.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/time/bug-asctime_r.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/time/clocktest.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/time/test_time.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/time/time.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/time/tst-ctime.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/time/tst-ftime_l.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/time/tst-futimens1.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/time/tst-mktime.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/time/tst-mktime2.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/time/tst-mktime3.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/time/tst-posixtz.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/time/tst-strftime.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/time/tst-strptime.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/time/tst-strptime2.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/time/tst-timezone.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/time/tst_wcsftime.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/tls/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/tls/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/tls/README create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tls-macros-arm.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tls-macros-mips.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tls-macros-thumb.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tls-macros.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls-at-ctor.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls1-static.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls1.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls10.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls10.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls11.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls12.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls13.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls14.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls15.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls16.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls17.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls18.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls2-static.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls2.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls3.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls4.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls5.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls6.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls7.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls8.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls9-static.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls9.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod-at-ctor.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod1.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod10.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod11.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod12.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod13.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod13a.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod14a.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod14b.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod15a.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod15b.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod16a.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod16b.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod17a.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod17b.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod18a.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod2.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod3.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod4.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod5.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod6.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod7.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod8.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod9.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/unistd/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/unistd/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/unistd/clone.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/unistd/clone_cruft.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/unistd/errno.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/unistd/exec-null.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/unistd/fork.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/unistd/getcwd.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/unistd/getopt.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/unistd/getopt_long.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/unistd/tst-getconf.sh create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/unistd/tst-preadwrite.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/unistd/tst-preadwrite64.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/unistd/tstgetopt.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/test/unistd/vfork.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/utils/.gitignore create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/utils/Makefile create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/utils/Makefile.in create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/utils/bswap.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/utils/chroot_realpath.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/utils/getconf.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/utils/iconv.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/utils/ldconfig.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/utils/ldd.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/utils/mmap-windows.c create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/utils/porting.h create mode 100644 l4/pkg/uclibc/lib/contrib/uclibc/utils/readsoname2.c create mode 100644 l4/pkg/uclibc/lib/libpthread/Makefile create mode 100644 l4/pkg/uclibc/lib/libpthread/include/Makefile create mode 100644 l4/pkg/uclibc/lib/libpthread/include/bits/initspin.h create mode 100644 l4/pkg/uclibc/lib/libpthread/include/bits/libc-lock.h create mode 100644 l4/pkg/uclibc/lib/libpthread/include/bits/pthreadtypes.h create mode 100644 l4/pkg/uclibc/lib/libpthread/include/pthread-l4.h create mode 100644 l4/pkg/uclibc/lib/libpthread/include/pthread.h create mode 100644 l4/pkg/uclibc/lib/libpthread/include/semaphore.h create mode 100644 l4/pkg/uclibc/lib/libpthread/include/smp.h create mode 100644 l4/pkg/uclibc/lib/libpthread/src/Makefile create mode 100644 l4/pkg/uclibc/lib/libpthread/src/attr.c create mode 100644 l4/pkg/uclibc/lib/libpthread/src/barrier.c create mode 100644 l4/pkg/uclibc/lib/libpthread/src/cancel.c create mode 100644 l4/pkg/uclibc/lib/libpthread/src/condvar.c create mode 100644 l4/pkg/uclibc/lib/libpthread/src/descr.h create mode 100644 l4/pkg/uclibc/lib/libpthread/src/errno-loc.c create mode 100644 l4/pkg/uclibc/lib/libpthread/src/errno.c create mode 100644 l4/pkg/uclibc/lib/libpthread/src/forward.c create mode 100644 l4/pkg/uclibc/lib/libpthread/src/internals.h create mode 100644 l4/pkg/uclibc/lib/libpthread/src/join.c create mode 100644 l4/pkg/uclibc/lib/libpthread/src/l4.cc create mode 100644 l4/pkg/uclibc/lib/libpthread/src/l4.h create mode 100644 l4/pkg/uclibc/lib/libpthread/src/libc_pthread_init.c create mode 100644 l4/pkg/uclibc/lib/libpthread/src/manager.cc create mode 100644 l4/pkg/uclibc/lib/libpthread/src/mutex.c create mode 100644 l4/pkg/uclibc/lib/libpthread/src/pt-initfini.c create mode 100644 l4/pkg/uclibc/lib/libpthread/src/ptcleanup.c create mode 100644 l4/pkg/uclibc/lib/libpthread/src/pthread-functions.h create mode 100644 l4/pkg/uclibc/lib/libpthread/src/pthread.c create mode 100644 l4/pkg/uclibc/lib/libpthread/src/queue.h create mode 100644 l4/pkg/uclibc/lib/libpthread/src/restart.h create mode 100644 l4/pkg/uclibc/lib/libpthread/src/rwlock.c create mode 100644 l4/pkg/uclibc/lib/libpthread/src/semaphore.c create mode 100644 l4/pkg/uclibc/lib/libpthread/src/so_init-amd64.S create mode 100644 l4/pkg/uclibc/lib/libpthread/src/so_init-arm.S create mode 100644 l4/pkg/uclibc/lib/libpthread/src/so_init-ppc32.S create mode 100644 l4/pkg/uclibc/lib/libpthread/src/so_init-sparc.S create mode 100644 l4/pkg/uclibc/lib/libpthread/src/so_init-x86.S create mode 100644 l4/pkg/uclibc/lib/libpthread/src/specific.c create mode 100644 l4/pkg/uclibc/lib/libpthread/src/spinlock.c create mode 100644 l4/pkg/uclibc/lib/libpthread/src/spinlock.h create mode 100644 l4/pkg/uclibc/lib/libpthread/src/sysdeps/alpha/dl-tls.h create mode 100644 l4/pkg/uclibc/lib/libpthread/src/sysdeps/alpha/tls.h create mode 100644 l4/pkg/uclibc/lib/libpthread/src/sysdeps/arm/dl-tls.h create mode 100644 l4/pkg/uclibc/lib/libpthread/src/sysdeps/arm/pt-machine.h create mode 100644 l4/pkg/uclibc/lib/libpthread/src/sysdeps/arm/tls.h create mode 100644 l4/pkg/uclibc/lib/libpthread/src/sysdeps/generic/dl-tls.c create mode 100644 l4/pkg/uclibc/lib/libpthread/src/sysdeps/generic/dl-tls.h create mode 100644 l4/pkg/uclibc/lib/libpthread/src/sysdeps/generic/libc-tls.cc create mode 100644 l4/pkg/uclibc/lib/libpthread/src/sysdeps/i386/dl-tls.h create mode 100644 l4/pkg/uclibc/lib/libpthread/src/sysdeps/i386/i686/pt-machine.h create mode 100644 l4/pkg/uclibc/lib/libpthread/src/sysdeps/i386/i686/tls.h create mode 100644 l4/pkg/uclibc/lib/libpthread/src/sysdeps/i386/pt-machine.h create mode 100644 l4/pkg/uclibc/lib/libpthread/src/sysdeps/i386/sysdep-cancel.h create mode 100644 l4/pkg/uclibc/lib/libpthread/src/sysdeps/i386/tls.h create mode 100644 l4/pkg/uclibc/lib/libpthread/src/sysdeps/mips/dl-tls.h create mode 100644 l4/pkg/uclibc/lib/libpthread/src/sysdeps/mips/tls.h create mode 100644 l4/pkg/uclibc/lib/libpthread/src/sysdeps/powerpc/dl-tls.h create mode 100644 l4/pkg/uclibc/lib/libpthread/src/sysdeps/powerpc/powerpc32/pt-machine.h create mode 100644 l4/pkg/uclibc/lib/libpthread/src/sysdeps/powerpc/powerpc64/pt-machine.h create mode 100644 l4/pkg/uclibc/lib/libpthread/src/sysdeps/powerpc/pt-machine.h create mode 100644 l4/pkg/uclibc/lib/libpthread/src/sysdeps/powerpc/tls.h create mode 100644 l4/pkg/uclibc/lib/libpthread/src/sysdeps/sh/dl-tls.h create mode 100644 l4/pkg/uclibc/lib/libpthread/src/sysdeps/sh/tls.h create mode 100644 l4/pkg/uclibc/lib/libpthread/src/sysdeps/sparc/dl-tls.h create mode 100644 l4/pkg/uclibc/lib/libpthread/src/sysdeps/sparc/pt-machine.h create mode 100644 l4/pkg/uclibc/lib/libpthread/src/sysdeps/sparc/sparc32/pt-machine.h create mode 100644 l4/pkg/uclibc/lib/libpthread/src/sysdeps/sparc/sparc64/pt-machine.h create mode 100644 l4/pkg/uclibc/lib/libpthread/src/sysdeps/sparc/tls.h create mode 100644 l4/pkg/uclibc/lib/libpthread/src/sysdeps/x86_64/dl-tls.h create mode 100644 l4/pkg/uclibc/lib/libpthread/src/sysdeps/x86_64/pt-machine.h create mode 100644 l4/pkg/uclibc/lib/libpthread/src/sysdeps/x86_64/sysdep-cancel.h create mode 100644 l4/pkg/uclibc/lib/libpthread/src/sysdeps/x86_64/tls.h create mode 100644 l4/pkg/uclibc/lib/libpthread/src/tramp-amd64.S create mode 100644 l4/pkg/uclibc/lib/libpthread/src/tramp-arm.S create mode 100644 l4/pkg/uclibc/lib/libpthread/src/tramp-ppc32.S create mode 100644 l4/pkg/uclibc/lib/libpthread/src/tramp-sparc.S create mode 100644 l4/pkg/uclibc/lib/libpthread/src/tramp-x86.S create mode 100644 l4/pkg/uclibc/lib/libpthread/src/uClibc-glue.h create mode 100644 l4/pkg/uclibc/lib/minimal_l4re/Makefile create mode 100644 l4/pkg/uclibc/lib/uclibc/ARCH-all/include/bits/kernel-features.h create mode 100644 l4/pkg/uclibc/lib/uclibc/ARCH-all/include/bits/sigthread.h create mode 100644 l4/pkg/uclibc/lib/uclibc/ARCH-all/include/linux/errno.h create mode 100644 l4/pkg/uclibc/lib/uclibc/ARCH-all/include/linux/if_ether.h create mode 100644 l4/pkg/uclibc/lib/uclibc/ARCH-all/include/not-cancel.h create mode 100644 l4/pkg/uclibc/lib/uclibc/ARCH-all/include/sys/syscall.h create mode 100644 l4/pkg/uclibc/lib/uclibc/ARCH-all/libc/misc/dirent/dirstream.h create mode 100644 l4/pkg/uclibc/lib/uclibc/ARCH-all/libc/signal/raise.c create mode 100644 l4/pkg/uclibc/lib/uclibc/ARCH-all/libc/signal/sigjmp.c create mode 100644 l4/pkg/uclibc/lib/uclibc/ARCH-all/libc/stdlib/_atexit.c create mode 100644 l4/pkg/uclibc/lib/uclibc/ARCH-all/libc/stdlib/abort.c create mode 100644 l4/pkg/uclibc/lib/uclibc/ARCH-all/libc/stdlib/malloc-standard/malloc.h create mode 100644 l4/pkg/uclibc/lib/uclibc/ARCH-all/libc/sysdeps/linux/common/getdents.c create mode 100644 l4/pkg/uclibc/lib/uclibc/ARCH-all/libc/sysdeps/linux/common/getsid.c create mode 100644 l4/pkg/uclibc/lib/uclibc/ARCH-all/libc/sysdeps/linux/common/longjmp.c create mode 100644 l4/pkg/uclibc/lib/uclibc/ARCH-all/libc/unistd/sleep.c create mode 100644 l4/pkg/uclibc/lib/uclibc/ARCH-amd64/include/asm/errno.h create mode 100644 l4/pkg/uclibc/lib/uclibc/ARCH-amd64/include/asm/ioctls.h create mode 100644 l4/pkg/uclibc/lib/uclibc/ARCH-amd64/include/asm/sigcontext.h create mode 100644 l4/pkg/uclibc/lib/uclibc/ARCH-amd64/include/asm/socket.h create mode 100644 l4/pkg/uclibc/lib/uclibc/ARCH-amd64/include/bits/uClibc_config.h create mode 100644 l4/pkg/uclibc/lib/uclibc/ARCH-amd64/include/linux/limits.h create mode 100644 l4/pkg/uclibc/lib/uclibc/ARCH-amd64/include/linux/param.h create mode 100644 l4/pkg/uclibc/lib/uclibc/ARCH-arm/aeabi_read_tp-v6p.S create mode 100644 l4/pkg/uclibc/lib/uclibc/ARCH-arm/aeabi_read_tp_generic.c create mode 100644 l4/pkg/uclibc/lib/uclibc/ARCH-arm/include/asm/errno.h create mode 100644 l4/pkg/uclibc/lib/uclibc/ARCH-arm/include/asm/ioctls.h create mode 100644 l4/pkg/uclibc/lib/uclibc/ARCH-arm/include/asm/sigcontext.h create mode 100644 l4/pkg/uclibc/lib/uclibc/ARCH-arm/include/asm/socket.h create mode 100644 l4/pkg/uclibc/lib/uclibc/ARCH-arm/include/bits/uClibc_config.h create mode 100644 l4/pkg/uclibc/lib/uclibc/ARCH-arm/include/linux/limits.h create mode 100644 l4/pkg/uclibc/lib/uclibc/ARCH-arm/include/linux/param.h create mode 100644 l4/pkg/uclibc/lib/uclibc/ARCH-ppc32/include/asm/errno.h create mode 100644 l4/pkg/uclibc/lib/uclibc/ARCH-ppc32/include/asm/ioctl.h create mode 100644 l4/pkg/uclibc/lib/uclibc/ARCH-ppc32/include/asm/ioctls.h create mode 100644 l4/pkg/uclibc/lib/uclibc/ARCH-ppc32/include/asm/sigcontext.h create mode 100644 l4/pkg/uclibc/lib/uclibc/ARCH-ppc32/include/asm/socket.h create mode 100644 l4/pkg/uclibc/lib/uclibc/ARCH-ppc32/include/asm/sockios.h create mode 100644 l4/pkg/uclibc/lib/uclibc/ARCH-ppc32/include/bits/uClibc_config.h create mode 100644 l4/pkg/uclibc/lib/uclibc/ARCH-ppc32/include/linux/limits.h create mode 100644 l4/pkg/uclibc/lib/uclibc/ARCH-ppc32/include/linux/param.h create mode 100644 l4/pkg/uclibc/lib/uclibc/ARCH-sparc/include/asm/errno.h create mode 100644 l4/pkg/uclibc/lib/uclibc/ARCH-sparc/include/asm/ioctls.h create mode 100644 l4/pkg/uclibc/lib/uclibc/ARCH-sparc/include/asm/sigcontext.h create mode 100644 l4/pkg/uclibc/lib/uclibc/ARCH-sparc/include/asm/socket.h create mode 100644 l4/pkg/uclibc/lib/uclibc/ARCH-sparc/include/bits/uClibc_config.h create mode 100644 l4/pkg/uclibc/lib/uclibc/ARCH-sparc/include/linux/bits/ioctls.h create mode 100644 l4/pkg/uclibc/lib/uclibc/ARCH-sparc/include/linux/bits/socket.h create mode 100644 l4/pkg/uclibc/lib/uclibc/ARCH-sparc/include/linux/limits.h create mode 100644 l4/pkg/uclibc/lib/uclibc/ARCH-sparc/include/linux/param.h create mode 100644 l4/pkg/uclibc/lib/uclibc/ARCH-sparc/include/linux/sockios.h create mode 100644 l4/pkg/uclibc/lib/uclibc/ARCH-x86/include/asm/errno.h create mode 100644 l4/pkg/uclibc/lib/uclibc/ARCH-x86/include/asm/ioctls.h create mode 100644 l4/pkg/uclibc/lib/uclibc/ARCH-x86/include/asm/sigcontext.h create mode 100644 l4/pkg/uclibc/lib/uclibc/ARCH-x86/include/asm/socket.h create mode 100644 l4/pkg/uclibc/lib/uclibc/ARCH-x86/include/bits/uClibc_config.h create mode 100644 l4/pkg/uclibc/lib/uclibc/ARCH-x86/include/linux/limits.h create mode 100644 l4/pkg/uclibc/lib/uclibc/ARCH-x86/include/linux/param.h create mode 100644 l4/pkg/uclibc/lib/uclibc/Make.rules create mode 100644 l4/pkg/uclibc/lib/uclibc/Makefile create mode 100644 l4/pkg/uclibc/lib/uclibc/_exit.cc create mode 100644 l4/pkg/uclibc/lib/uclibc/contrib_files.mk create mode 100755 l4/pkg/uclibc/lib/uclibc/make_diff.sh create mode 100644 l4/pkg/uclibc/lib/uclibc/make_rules.mk create mode 100644 l4/pkg/uclibc/lib/uclibc/make_vars.mk create mode 100644 l4/pkg/uclibc/lib/uclibc/src_rules.mk create mode 100644 l4/pkg/uclibc/lib/uclibc/target_headers.lst create mode 100644 l4/tool/Makefile create mode 100755 l4/tool/bin/entry-selector create mode 100755 l4/tool/bin/genexportpack create mode 100755 l4/tool/bin/gengrub1iso create mode 100755 l4/tool/bin/gengrub2iso create mode 100755 l4/tool/bin/isocreator create mode 100755 l4/tool/bin/mkspafs create mode 100755 l4/tool/bin/qemu-x86-launch create mode 100755 l4/tool/bin/ux-launch create mode 100644 l4/tool/elf-patcher/Makefile create mode 100644 l4/tool/elf-patcher/elf-patcher.cc create mode 100644 l4/tool/elf-patcher/elf-patcher.h create mode 100644 l4/tool/gendep/COPYING create mode 100644 l4/tool/gendep/Doxyfile create mode 100644 l4/tool/gendep/MAINTAINER create mode 100644 l4/tool/gendep/Makefile create mode 100644 l4/tool/gendep/WhatIsThis create mode 100644 l4/tool/gendep/deptrack.c create mode 100644 l4/tool/gendep/gendep.h create mode 100644 l4/tool/gendep/manpage.dox create mode 100644 l4/tool/gendep/simple-cat.c create mode 100644 l4/tool/gendep/syscall.c create mode 100644 l4/tool/kconfig/COPYING create mode 100644 l4/tool/kconfig/Makefile create mode 100644 l4/tool/kconfig/README create mode 100644 l4/tool/kconfig/scripts/Kbuild.include create mode 100644 l4/tool/kconfig/scripts/Makefile create mode 100644 l4/tool/kconfig/scripts/Makefile.build create mode 100644 l4/tool/kconfig/scripts/Makefile.clean create mode 100644 l4/tool/kconfig/scripts/Makefile.headersinst create mode 100644 l4/tool/kconfig/scripts/Makefile.host create mode 100644 l4/tool/kconfig/scripts/Makefile.lib create mode 100644 l4/tool/kconfig/scripts/Makefile.modinst create mode 100644 l4/tool/kconfig/scripts/Makefile.modpost create mode 100644 l4/tool/kconfig/scripts/basic/.gitignore create mode 100644 l4/tool/kconfig/scripts/basic/Makefile create mode 100644 l4/tool/kconfig/scripts/basic/docproc.c create mode 100644 l4/tool/kconfig/scripts/basic/fixdep.c create mode 100644 l4/tool/kconfig/scripts/basic/hash.c create mode 100644 l4/tool/kconfig/scripts/kconfig/.gitignore create mode 100644 l4/tool/kconfig/scripts/kconfig/Makefile create mode 100644 l4/tool/kconfig/scripts/kconfig/POTFILES.in create mode 100755 l4/tool/kconfig/scripts/kconfig/check.sh create mode 100644 l4/tool/kconfig/scripts/kconfig/conf.c create mode 100644 l4/tool/kconfig/scripts/kconfig/confdata.c create mode 100644 l4/tool/kconfig/scripts/kconfig/expr.c create mode 100644 l4/tool/kconfig/scripts/kconfig/expr.h create mode 100644 l4/tool/kconfig/scripts/kconfig/gconf.c create mode 100644 l4/tool/kconfig/scripts/kconfig/gconf.glade create mode 100644 l4/tool/kconfig/scripts/kconfig/images.c create mode 100644 l4/tool/kconfig/scripts/kconfig/kxgettext.c create mode 100644 l4/tool/kconfig/scripts/kconfig/lkc.h create mode 100644 l4/tool/kconfig/scripts/kconfig/lkc_proto.h create mode 100644 l4/tool/kconfig/scripts/kconfig/lxdialog/.gitignore create mode 100644 l4/tool/kconfig/scripts/kconfig/lxdialog/BIG.FAT.WARNING create mode 100644 l4/tool/kconfig/scripts/kconfig/lxdialog/check-lxdialog.sh create mode 100644 l4/tool/kconfig/scripts/kconfig/lxdialog/checklist.c create mode 100644 l4/tool/kconfig/scripts/kconfig/lxdialog/dialog.h create mode 100644 l4/tool/kconfig/scripts/kconfig/lxdialog/inputbox.c create mode 100644 l4/tool/kconfig/scripts/kconfig/lxdialog/menubox.c create mode 100644 l4/tool/kconfig/scripts/kconfig/lxdialog/textbox.c create mode 100644 l4/tool/kconfig/scripts/kconfig/lxdialog/util.c create mode 100644 l4/tool/kconfig/scripts/kconfig/lxdialog/yesno.c create mode 100644 l4/tool/kconfig/scripts/kconfig/mconf.c create mode 100644 l4/tool/kconfig/scripts/kconfig/menu.c create mode 100644 l4/tool/kconfig/scripts/kconfig/nconf.c create mode 100644 l4/tool/kconfig/scripts/kconfig/nconf.gui.c create mode 100644 l4/tool/kconfig/scripts/kconfig/nconf.h create mode 100644 l4/tool/kconfig/scripts/kconfig/qconf.cc create mode 100644 l4/tool/kconfig/scripts/kconfig/qconf.h create mode 100644 l4/tool/kconfig/scripts/kconfig/symbol.c create mode 100644 l4/tool/kconfig/scripts/kconfig/util.c create mode 100644 l4/tool/kconfig/scripts/kconfig/zconf.gperf create mode 100644 l4/tool/kconfig/scripts/kconfig/zconf.hash.c_shipped create mode 100644 l4/tool/kconfig/scripts/kconfig/zconf.l create mode 100644 l4/tool/kconfig/scripts/kconfig/zconf.lex.c_shipped create mode 100644 l4/tool/kconfig/scripts/kconfig/zconf.tab.c_shipped create mode 100644 l4/tool/kconfig/scripts/kconfig/zconf.y create mode 100644 l4/tool/lib/L4/Grub.pm create mode 100644 l4/tool/lib/L4/ModList.pm create mode 100644 l4/tool/vim/syntax/ioconfig.vim create mode 100644 l4/tool/vim/syntax/l4mods.vim create mode 100644 l4/tool/vim/syntax/objdump.vim create mode 100644 l4/tool/vim/syntax/simics.vim create mode 100755 repomgr create mode 100644 tools/preprocess/COPYING create mode 100644 tools/preprocess/MAINTAINER create mode 100644 tools/preprocess/Makefile create mode 100644 tools/preprocess/README create mode 100644 tools/preprocess/TODO create mode 100644 tools/preprocess/doc/Doxyfile create mode 100644 tools/preprocess/doc/Makefile create mode 100644 tools/preprocess/doc/manpage.dox create mode 100644 tools/preprocess/src/Makefile create mode 100755 tools/preprocess/src/preprocess create mode 100644 tools/preprocess/test/Makefile create mode 100644 tools/preprocess/test/c-preproc.cpp create mode 100644 tools/preprocess/test/combine.pl create mode 100644 tools/preprocess/test/comment_in_string.cpp create mode 100644 tools/preprocess/test/default_args.cpp create mode 100644 tools/preprocess/test/dropsection-ext.cpp create mode 100644 tools/preprocess/test/dropsection.cpp create mode 100644 tools/preprocess/test/explicit.cpp create mode 100644 tools/preprocess/test/extern_c.cpp create mode 100644 tools/preprocess/test/inline.cpp create mode 100644 tools/preprocess/test/interface.cpp create mode 100644 tools/preprocess/test/line.cpp create mode 100644 tools/preprocess/test/mapping.cpp create mode 100644 tools/preprocess/test/multifile1.cpp create mode 100644 tools/preprocess/test/multifile2.cpp create mode 100644 tools/preprocess/test/noinline.cpp create mode 100644 tools/preprocess/test/operator.cpp create mode 100644 tools/preprocess/test/parser.cpp create mode 100644 tools/preprocess/test/static.cpp create mode 100644 tools/preprocess/test/template.cpp create mode 100644 tools/preprocess/test/variable.cpp create mode 100644 tools/preprocess/test/verify/c-preproc.cc create mode 100644 tools/preprocess/test/verify/c-preproc.h create mode 100644 tools/preprocess/test/verify/c-preproc_i.h create mode 100644 tools/preprocess/test/verify/comment_in_string.cc create mode 100644 tools/preprocess/test/verify/comment_in_string.h create mode 100644 tools/preprocess/test/verify/comment_in_string_i.h create mode 100644 tools/preprocess/test/verify/default_args.cc create mode 100644 tools/preprocess/test/verify/default_args.h create mode 100644 tools/preprocess/test/verify/default_args_i.h create mode 100644 tools/preprocess/test/verify/drop_multi1-ext.cc create mode 100644 tools/preprocess/test/verify/drop_multi1.cc create mode 100644 tools/preprocess/test/verify/drop_multi1.h create mode 100644 tools/preprocess/test/verify/drop_multi1_i.h create mode 100644 tools/preprocess/test/verify/drop_multi2-ext.cc create mode 100644 tools/preprocess/test/verify/drop_multi2.cc create mode 100644 tools/preprocess/test/verify/drop_multi2.h create mode 100644 tools/preprocess/test/verify/drop_multi2_i.h create mode 100644 tools/preprocess/test/verify/drop_single1.cc create mode 100644 tools/preprocess/test/verify/drop_single1.h create mode 100644 tools/preprocess/test/verify/drop_single1_i.h create mode 100644 tools/preprocess/test/verify/drop_single2.cc create mode 100644 tools/preprocess/test/verify/drop_single2.h create mode 100644 tools/preprocess/test/verify/drop_single2_i.h create mode 100644 tools/preprocess/test/verify/drop_single3.cc create mode 100644 tools/preprocess/test/verify/drop_single3.h create mode 100644 tools/preprocess/test/verify/drop_single3_i.h create mode 100644 tools/preprocess/test/verify/explicit.cc create mode 100644 tools/preprocess/test/verify/explicit.h create mode 100644 tools/preprocess/test/verify/explicit_i.h create mode 100644 tools/preprocess/test/verify/extern_c.cc create mode 100644 tools/preprocess/test/verify/extern_c.h create mode 100644 tools/preprocess/test/verify/extern_c_i.h create mode 100644 tools/preprocess/test/verify/inline.cc create mode 100644 tools/preprocess/test/verify/inline.h create mode 100644 tools/preprocess/test/verify/inline_i.h create mode 100644 tools/preprocess/test/verify/inline_noinline.cc create mode 100644 tools/preprocess/test/verify/inline_noinline.h create mode 100644 tools/preprocess/test/verify/inline_noinline_i.h create mode 100644 tools/preprocess/test/verify/interface.cc create mode 100644 tools/preprocess/test/verify/interface_i.h create mode 100644 tools/preprocess/test/verify/interfacepublic.h create mode 100644 tools/preprocess/test/verify/line.cc create mode 100644 tools/preprocess/test/verify/line.h create mode 100644 tools/preprocess/test/verify/line_i.h create mode 100644 tools/preprocess/test/verify/line_nh.cc create mode 100644 tools/preprocess/test/verify/line_nh.h create mode 100644 tools/preprocess/test/verify/line_nh_i.h create mode 100644 tools/preprocess/test/verify/line_not.cc create mode 100644 tools/preprocess/test/verify/line_not.h create mode 100644 tools/preprocess/test/verify/line_not_i.h create mode 100644 tools/preprocess/test/verify/mapping.cc create mode 100644 tools/preprocess/test/verify/mapping.h create mode 100644 tools/preprocess/test/verify/mapping_i.h create mode 100644 tools/preprocess/test/verify/mapping_inline.cc create mode 100644 tools/preprocess/test/verify/mapping_inline.h create mode 100644 tools/preprocess/test/verify/mapping_inline_i.h create mode 100644 tools/preprocess/test/verify/multifile-part1.cc create mode 100644 tools/preprocess/test/verify/multifile-part2.cc create mode 100644 tools/preprocess/test/verify/multifile.cc create mode 100644 tools/preprocess/test/verify/multifile.h create mode 100644 tools/preprocess/test/verify/multifile_i.h create mode 100644 tools/preprocess/test/verify/noinline.cc create mode 100644 tools/preprocess/test/verify/noinline.h create mode 100644 tools/preprocess/test/verify/noinline_i.h create mode 100644 tools/preprocess/test/verify/operator.cc create mode 100644 tools/preprocess/test/verify/operator.h create mode 100644 tools/preprocess/test/verify/operator_i.h create mode 100644 tools/preprocess/test/verify/parser.cc create mode 100644 tools/preprocess/test/verify/parser.h create mode 100644 tools/preprocess/test/verify/parser_i.h create mode 100644 tools/preprocess/test/verify/parser_noinline.cc create mode 100644 tools/preprocess/test/verify/parser_noinline.h create mode 100644 tools/preprocess/test/verify/parser_noinline_i.h create mode 100644 tools/preprocess/test/verify/random.cc create mode 100644 tools/preprocess/test/verify/random.h create mode 100644 tools/preprocess/test/verify/random_i.h create mode 100644 tools/preprocess/test/verify/random_inline.cc create mode 100644 tools/preprocess/test/verify/random_inline.h create mode 100644 tools/preprocess/test/verify/random_inline_i.h create mode 100644 tools/preprocess/test/verify/static.cc create mode 100644 tools/preprocess/test/verify/static.h create mode 100644 tools/preprocess/test/verify/static_i.h create mode 100644 tools/preprocess/test/verify/template.cc create mode 100644 tools/preprocess/test/verify/template.h create mode 100644 tools/preprocess/test/verify/template_i.h create mode 100644 tools/preprocess/test/verify/template_inline.cc create mode 100644 tools/preprocess/test/verify/template_inline.h create mode 100644 tools/preprocess/test/verify/template_inline_i.h create mode 100644 tools/preprocess/test/verify/variable.cc create mode 100644 tools/preprocess/test/verify/variable.h create mode 100644 tools/preprocess/test/verify/variable_i.h diff --git a/kernel/fiasco/BENCHMARKING b/kernel/fiasco/BENCHMARKING new file mode 100644 index 00000000..e41f8895 --- /dev/null +++ b/kernel/fiasco/BENCHMARKING @@ -0,0 +1,13 @@ + +IMPORTANT NOTE ON BENCHMARKING Fiasco.OC/L4RE SOFTWARE +====================================================== + +Owing to the flexibility of configurations possible with this software we +urge you to send any benchmarking results for review prior to publication to + + benchmarking@os.inf.tu-dresden.de + +to get feedback and an 'OK' from our side that the presented figures are +reasonable. + +Thanks. diff --git a/kernel/fiasco/COPYING b/kernel/fiasco/COPYING new file mode 100644 index 00000000..e77696ae --- /dev/null +++ b/kernel/fiasco/COPYING @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 675 Mass Ave, Cambridge, MA 02139, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/kernel/fiasco/MAINTAINER b/kernel/fiasco/MAINTAINER new file mode 100644 index 00000000..3ec7cf30 --- /dev/null +++ b/kernel/fiasco/MAINTAINER @@ -0,0 +1 @@ +mailaddr aw11@os.inf.tu-dresden.de, adam@os.inf.tu-dresden.de diff --git a/kernel/fiasco/Makefile b/kernel/fiasco/Makefile new file mode 100644 index 00000000..474b8c36 --- /dev/null +++ b/kernel/fiasco/Makefile @@ -0,0 +1,213 @@ +# +# +# GLOBAL Makefile for FIASCO + +# enviroment +DFLBUILDDIR := build +ALLBUILDDIR := build-all +RANDBUILDDIR := build-rand +TEMPLDIR := src/templates +MAKEFILETEMPL := $(TEMPLDIR)/Makefile.builddir.templ +MANSUBDIRS := man +INSTALLSUBDIRS := $(MANSUBDIRS) +CLEANSUBDIRS := $(MANSUBDIRS) $(wildcard $(DFLBUILDDIR)) +CONFIG_FILE := $(TEMPLDIR)/globalconfig.out +TEST_TEMPLATES := $(patsubst $(CONFIG_FILE).%,%,$(wildcard $(CONFIG_FILE).*)) +TEST_TEMPLATES := $(if $(TEMPLATE_FILTER),$(filter $(TEMPLATE_FILTER),$(TEST_TEMPLATES)),$(TEST_TEMPLATES)) +DFL_TEMPLATE := ia32-1 +PL ?= 1 + +getdir = $(shell \ + bd="$(1)"; \ + if [ "$${bd\#/}" = "$$bd" -a \ + "$${bd\#*..}" = "$$bd" ]; then \ + relp=".."; \ + while [ "$${bd\#*/}" != "$$bd" ]; do \ + relp="$$relp/.."; \ + bd="$${bd\#*/}"; \ + done; \ + echo "$$relp"; \ + else \ + pwd; \ + fi \ + ) + +buildmakefile = mkdir -p "$(1)"; \ + perl -p -i -e '$$s = "$(CURDIR)/src"; s/\@SRCDIR\@/$$s/' \ + < $(MAKEFILETEMPL) > $(1)/Makefile + +ifneq ($(strip $(B)),) +BUILDDIR := $(B) +endif +ifneq ($(strip $(BUILDDIR)),) +builddir: + @echo "Creating build directory \"$(BUILDDIR)\"..." + @if [ -e "$(BUILDDIR)" ]; then \ + echo "Already exists, aborting."; \ + exit 1; \ + fi + @$(call buildmakefile,$(BUILDDIR)) + @echo "done." +endif + +ifneq ($(strip $(T)),) +this: + set -e; \ + test -f $(TEMPLDIR)/globalconfig.out.$(T); \ + bdir=T-$(DFLBUILDDIR)-$(T); \ + rm -rf $$bdir; \ + $(call buildmakefile,T-$(DFLBUILDDIR)-$(T)); \ + cp $(TEMPLDIR)/globalconfig.out.$(T) $$bdir/globalconfig.out; \ + $(MAKE) -C $$bdir +endif + +$(DFLBUILDDIR): fiasco.builddir.create + $(MAKE) -C $@ -j$(PL) + +all: fiasco man + +clean cleanall: + set -e; for i in $(CLEANSUBDIRS); do $(MAKE) -C $$i $@; done + +purge: cleanall + $(RM) -r $(DFLBUILDDIR) + +man: + set -e; for i in $(MANSUBDIRS); do $(MAKE) -C $$i; done + +fiasco.builddir.create: + [ -e $(DFLBUILDDIR)/Makefile ] || \ + ($(call buildmakefile,$(DFLBUILDDIR))) + [ -f $(DFLBUILDDIR)/globalconfig.out ] || { \ + cp $(TEMPLDIR)/globalconfig.out.$(DFL_TEMPLATE) \ + $(DFLBUILDDIR)/globalconfig.out; \ + } + +config $(filter config %config,$(MAKECMDGOALS)): fiasco.builddir.create + $(MAKE) -C $(DFLBUILDDIR) $@ + +fiasco: fiasco.builddir.create + $(MAKE) -C $(DFLBUILDDIR) -j$(PL) + +checkall l4check: + error=0; \ + $(RM) -r $(ALLBUILDDIR); \ + for X in $(TEST_TEMPLATES); do \ + echo -e "\n= Building configuration: $$X\n\n"; \ + $(call buildmakefile,$(ALLBUILDDIR)/$$X); \ + cp $(TEMPLDIR)/globalconfig.out.$$X \ + $(ALLBUILDDIR)/$$X/globalconfig.out; \ + if $(MAKE) -C $(ALLBUILDDIR)/$$X -j$(PL); then \ + [ -z "$(KEEP_BUILD_DIRS)" ] && \ + $(RM) -r $(ALLBUILDDIR)/$$X; \ + else \ + error=$$?; \ + failed="$$failed $$X"; \ + fi \ + done; \ + rmdir $(ALLBUILDDIR) >/dev/null 2>&1; \ + [ "$$failed" ] && echo -e "\nFailed configurations:$$failed"; \ + exit $$error; + +checkallp: + $(RM) -r $(ALLBUILDDIR) + $(MAKE) dobuildparallel SHELL=bash + +.PHONY: dobuildparallel checkallp + +dobuildparallel: $(addprefix $(ALLBUILDDIR)/,$(TEST_TEMPLATES)) + error=0; \ + echo "======================================================"; \ + for d in $(TEST_TEMPLATES); do \ + if [ -e $(ALLBUILDDIR)/$$d/build.failed ]; then \ + error=1; failed="$$failed $$d"; \ + fi; \ + done; \ + for f in $$failed; do echo "====== Failed Build Log: $$f ======"; \ + tail -60 $(ALLBUILDDIR)/$$f/build.log; \ + done; \ + rmdir $(ALLBUILDDIR) >/dev/null 2>&1; \ + [ "$$failed" ] && echo -e "\nFailed configurations:$$failed"; \ + exit $$error; + +$(addprefix $(ALLBUILDDIR)/,$(TEST_TEMPLATES)): + $(call buildmakefile,$@) + cp $(TEMPLDIR)/globalconfig.out.$(patsubst $(ALLBUILDDIR)/%,%,$@) \ + $@/globalconfig.out + $(MAKE) -C $@ 2>&1 | tee $@/build.log; \ + if [ $${PIPESTATUS[0]} = 0 ]; \ + then [ -z "$(KEEP_BUILD_DIRS)" ] && $(RM) -r $@; \ + else echo $${PIPESTATUS[0]} > $@/build.failed; fi + +list: + @echo "Templates:" + @echo $(TEST_TEMPLATES) + +randcheck: + $(RM) -r $(RANDBUILDDIR); \ + $(call buildmakefile,$(RANDBUILDDIR)/b); \ + while true; do \ + $(RM) $(RANDBUILDDIR)/b/globalconfig.out; \ + $(MAKE) -C $(RANDBUILDDIR)/b randconfig; \ + fn=$$(cat $(RANDBUILDDIR)/b/globalconfig.out \ + | grep -e "^CONFIG_" | sort | sha1sum \ + | cut -f1 -d\ ); \ + if [ -e "ok-$$fn" -o -e "failed-$$fn" ]; then \ + echo "Configuration $$fn already checked." \ + continue; \ + fi; \ + if $(MAKE) -C $(RANDBUILDDIR)/b -j$(PL); then \ + cp $(RANDBUILDDIR)/b/globalconfig.out \ + $(RANDBUILDDIR)/ok-$$fn; \ + else \ + [ -n "$$STOP_ON_ERROR" ] && exit 1; \ + cp -a $(RANDBUILDDIR)/b \ + $(RANDBUILDDIR)/failed-$$fn; \ + fi; \ + done + +randcheckstop: + $(MAKE) STOP_ON_ERROR=1 randcheck + +randcheckagain: + for f in $(RANDBUILDDIR)/failed-*; do \ + if $(MAKE) -C $$f -j$(PL); then \ + $(RM) -rf $$f; \ + else \ + [ -n "$$STOP_ON_ERROR" ] && exit 1; \ + fi \ + done + +randcheckagainstop: + $(MAKE) STOP_ON_ERROR=1 randcheckagain + +help: + @echo + @echo "fiasco Builds the default configuration ($(DFL_TEMPLATE))" + @echo "T=template Build a certain configuration" + @echo "checkall Build all template configurations in one go" + @echo "list List templates" + @echo + @echo "config menuconfig xconfig oldconfig" + @echo " Configure kernel in \"$(DFLBUILDDIR)\"" + @echo "$(DFLBUILDDIR) Build kernel in \"$(DFLBUILDDIR)\"" + @echo "clean cleanall clean or cleanall in \"$(CLEANSUBDIRS)\"" + @echo "purge cleanall, remove \"$(DFLBUILDDIR)\" and build helper" + @echo + @echo "Creating a custom kernel:" + @echo + @echo " Create a build directory with:" + @echo " make BUILDDIR=builddir" + @echo " Then build the kernel:" + @echo " cd builddir" + @echo " make config" + @echo " make" + @echo + @echo "Call \"make help\" in the build directory for more information on build targets." + @echo + @echo "Default target: $(DFLBUILDDIR)" + @echo + +.PHONY: man install clean cleanall fiasco.builddir.create fiasco \ + l4check checkall config oldconfig menuconfig nconfig xconfig \ + randcheck randcheckstop help diff --git a/kernel/fiasco/README b/kernel/fiasco/README new file mode 100644 index 00000000..72812733 --- /dev/null +++ b/kernel/fiasco/README @@ -0,0 +1,71 @@ + +Welcome to Fiasco.OC! +---------------------- + +Fiasco is a microkernel and an be used to construct flexible systems. We at +TU Dresden use it as a base for our TUD:OS system which supports running +real-time and time-sharing applications as well as virtualization +concurrently on one system. However, Fiasco is not only suitable for big and +complex systems, but also for small, embedded applications. + +This distribution contains the Fiasco.OC microkernel and tools to build +it. User level applications are not included in this package. + +Licensing +--------- + +Fiasco is freely redistributable under the GPL (see l4/kernel/fiasco/COPYING). +For different licensing schemes please contact us at: + fiasco-core@os.inf.tu-dresden.de +This is a closed list, proper mails will be let through by the moderator. + +For more details, see our webpage at: http://os.inf.tu-dresden.de/fiasco/ + +Supported architectures and ABIs +-------------------------------- + + * IA32 (32-bit Intel, AMD and compatible CPUs, i486 and above) + * AMD64 (64-bit Intel, AMD and compatible CPUs) + * ARM (various ARM CPUs and platforms) + * UX (Linux usermode emulation of Fiasco/L4) + +A list of changes since the last release can be found in the CHANGES file. + +Building the Fiasco kernel +-------------------------- + +To compile Fiasco you need a recent version of gcc and a recent version of +GNU binutils, GNU make and Perl version 5.6 or later. + +Change to the directory fiasco/l4/kernel/fiasco/ and +create a build directory with "make BUILDDIR=build" and change to the +'build' directory. Optionally modify the default configuration using +"make menuconfig". Then compile the kernel by typing "make". + +The kernel image can then be found in fiasco/l4/kernel/fiasco/build/ as +'fiasco'. + +For further information refer to: http://os.inf.tu-dresden.de/fiasco/build.html + +Mailing List +------------ + +For problem reports and suggestions regarding the Fiasco microkernel, +please subscribe and send mail to the l4-hackers mailing list: + http://os.inf.tu-dresden.de/mailman/listinfo/l4-hackers/ + +Remote SVN +---------- + +The latest development versions are available from our SVN server. +The truly bleeding edge will want to check out daily snapshots from there. +However, be aware that these may not always run correctly. +You can also get user land programs for L4 from this SVN. + +For information how to use SVN see: +http://os.inf.tu-dresden.de/L4Re/download.html + + +Enjoy! + +The Fiasco Team diff --git a/kernel/fiasco/src/.gdbinit b/kernel/fiasco/src/.gdbinit new file mode 100644 index 00000000..447f881b --- /dev/null +++ b/kernel/fiasco/src/.gdbinit @@ -0,0 +1,22 @@ +define tcb + p *(class thread_t*)((unsigned)&_tcbs_1 + (($arg0 << 17) + ($arg1 << 10) << 1)) +end +define dtcb + graph display *(class thread_t*)((unsigned)&_tcbs_1 + (($arg0 << 17) + ($arg1 << 10) << 1)) +end + +define tcbat + p *(class thread_t*)($arg0) +end + +file fiasco.image +set remotebaud 115200 + +## for debugging on COM2 +target remote /dev/ttyS1 + +## for debugging on COM2 +#target remote /dev/ttyS0 + +set output-radix 16 +set history save on diff --git a/kernel/fiasco/src/BUG-HUNTING b/kernel/fiasco/src/BUG-HUNTING new file mode 100644 index 00000000..f4f3f816 --- /dev/null +++ b/kernel/fiasco/src/BUG-HUNTING @@ -0,0 +1,31 @@ +This is a list of (funny) things, you have to check before you dig +into deep debugging sessions. + + * Check for assumptions about structure layout (and v-table + pointers) + + * Check for assumptions about bitfield layout (just the same + as above, but as reminder) + + * Is there code with side effects (i++=i++ or so)? + + * Some unclobbered registers or memory in inline assembly? + - Keep in mind there was a problem on x86 with the clobber + list, you have to mark clobbered registers as output to + a dummy variable. + + - Clobbering ebp has no effects. Really! We've tried it! + Also there is no output constraint, so if you use ebp, + you must explicitly save/restore it. + + * Missing 'volatile' on shared and manipulated data? + + * You made assumptions about the width of native data types? + + +Put some printfs into the code, and hope they will not cover +the bug. Or just use JDB and find the bug. + +Remember: FIND THE BUG. + + diff --git a/kernel/fiasco/src/Circular.max.amd64 b/kernel/fiasco/src/Circular.max.amd64 new file mode 100644 index 00000000..8dfa2942 --- /dev/null +++ b/kernel/fiasco/src/Circular.max.amd64 @@ -0,0 +1,18 @@ +Do "make DEPS" for full fine-grained dependency information. + +--- + + checksum +boot_info + checksum + +--- + + boot_info +checksum + boot_info + +--- + +TOTAL CIRCULAR DEPS: +2 diff --git a/kernel/fiasco/src/Circular.max.arm b/kernel/fiasco/src/Circular.max.arm new file mode 100644 index 00000000..6b184900 --- /dev/null +++ b/kernel/fiasco/src/Circular.max.arm @@ -0,0 +1,6 @@ +Do "make DEPS" for full fine-grained dependency information. + +--- + +TOTAL CIRCULAR DEPS: +0 diff --git a/kernel/fiasco/src/Circular.max.ia32 b/kernel/fiasco/src/Circular.max.ia32 new file mode 100644 index 00000000..8dfa2942 --- /dev/null +++ b/kernel/fiasco/src/Circular.max.ia32 @@ -0,0 +1,18 @@ +Do "make DEPS" for full fine-grained dependency information. + +--- + + checksum +boot_info + checksum + +--- + + boot_info +checksum + boot_info + +--- + +TOTAL CIRCULAR DEPS: +2 diff --git a/kernel/fiasco/src/Circular.max.ppc32 b/kernel/fiasco/src/Circular.max.ppc32 new file mode 100644 index 00000000..b81ff5ec --- /dev/null +++ b/kernel/fiasco/src/Circular.max.ppc32 @@ -0,0 +1,1694 @@ +Do "make DEPS" for full fine-grained dependency information. + +--- + + kmem_alloc +buddy_alloc + config + pic + +--- + + context + deadline_timeout + helping_lock + ipc_timeout + irq + kernel_uart + kobject + map_util + mapdb + mappable + mapping_tree + pic + preemption + receiver + simple_mapdb + switch_lock + task + thread_lock + thread + vkey +clock + kip + +--- + + kip + buddy_alloc + context + deadline_timeout + entry_frame + fpu_alloc + globals + helping_lock + ipc_timeout + irq + irq_alloc + kernel_console + kernel_uart + kip_init + kmem + kmem_alloc + kmem_slab + kmem_slab_simple + kobject + map_util + mapdb + mappable + mapped_alloc + mapping + mapping_tree + mem_layout + mem_space + obj_space + paging + pic + preemption + rcupdate + receiver + simple_mapdb + space + switch_lock + task + thread_lock + timeout + timer + thread + vkey + vmem_alloc + jdb_trace + jdb_tbuf + tb_entry +config + pic + +--- + + deadline_timeout + helping_lock + ipc_timeout + irq + kernel_uart + kobject + map_util + mapdb + mappable + mapping_tree + pic + preemption + receiver + simple_mapdb + switch_lock + task + thread_lock + thread + vkey +context + clock + config + entry_frame + globals + jdb_tbuf + kip + kip_init + kmem + mapped_alloc + mem_layout + mem_space + obj_space + paging + pic + rcupdate + space + tb_entry + timeout + timer + trap_state + +--- + + irq + kernel_uart + pic + thread + vkey +deadline_timeout + clock + config + context + entry_frame + globals + jdb_tbuf + kip + kip_init + kmem + mapped_alloc + mem_layout + mem_space + obj_space + paging + pic + preemption + rcupdate + receiver + space + switch_lock + tb_entry + thread_lock + timeout + timer + trap_state + +--- + + context + deadline_timeout + helping_lock + ipc_timeout + irq + kernel_uart + kobject + map_util + mapdb + mappable + mapping_tree + mem_space + obj_space + pic + preemption + rcupdate + receiver + simple_mapdb + space + switch_lock + task + thread_lock + trap_state + thread + vkey + jdb_trace + jdb_tbuf + tb_entry +entry_frame + config + pic + +--- + + thread +fpu_alloc + config + kmem_slab + kmem_slab_simple + pic + +--- + + context + deadline_timeout + helping_lock + ipc_timeout + irq + kernel_uart + kobject + map_util + mapdb + mappable + mapping_tree + mem_space + obj_space + pic + preemption + rcupdate + receiver + simple_mapdb + space + switch_lock + task + thread_lock + timeout + timer + thread + vkey + jdb_trace + jdb_tbuf + tb_entry +globals + config + mem_layout + pic + +--- + + irq + kernel_uart + kobject + map_util + mapdb + mappable + mapping_tree + pic + simple_mapdb + task + thread + vkey +helping_lock + clock + config + context + entry_frame + globals + jdb_tbuf + kip + kip_init + kmem + mapped_alloc + mem_layout + mem_space + obj_space + paging + pic + rcupdate + space + switch_lock + tb_entry + timeout + timer + trap_state + +--- + + thread +ipc_timeout + clock + config + context + entry_frame + globals + jdb_tbuf + kip + kip_init + kmem + mapped_alloc + mem_layout + mem_space + obj_space + paging + pic + rcupdate + receiver + space + switch_lock + tb_entry + thread_lock + timeout + timer + trap_state + +--- + + kernel_uart + pic + vkey +irq + clock + config + context + deadline_timeout + entry_frame + globals + helping_lock + irq_alloc + jdb_tbuf + jdb_trace + kip + kip_init + kmem + kmem_slab + kmem_slab_simple + kobject + map_util + mapdb + mappable + mapped_alloc + mapping + mapping_tree + mem_layout + mem_space + obj_space + paging + pic + preemption + rcupdate + receiver + simple_mapdb + space + switch_lock + tb_entry + thread + thread_lock + timeout + timer + trap_state + vmem_alloc + +--- + + irq + kernel_uart + pic + thread + vkey +irq_alloc + config + pic + +--- + + context + deadline_timeout + helping_lock + ipc_timeout + irq + kernel_uart + kobject + map_util + mapdb + mappable + mapping_tree + mem_space + obj_space + pic + preemption + rcupdate + receiver + simple_mapdb + space + switch_lock + task + thread_lock + thread + vkey + jdb_trace +jdb_tbuf + config + entry_frame + globals + kip + mem_layout + pic + tb_entry + trap_state + +--- + + irq + kernel_uart + pic + thread + vkey +jdb_trace + config + entry_frame + globals + jdb_tbuf + kip + mem_layout + pic + tb_entry + trap_state + +--- + + vkey +kernel_console + config + pic + +--- + + vkey +kernel_uart + clock + config + context + deadline_timeout + entry_frame + globals + helping_lock + irq + irq_alloc + jdb_tbuf + jdb_trace + kip + kip_init + kmem + kmem_slab + kmem_slab_simple + kobject + map_util + mapdb + mappable + mapped_alloc + mapping + mapping_tree + mem_layout + mem_space + obj_space + paging + pic + preemption + rcupdate + receiver + simple_mapdb + space + switch_lock + tb_entry + thread + thread_lock + timeout + timer + trap_state + uart + vmem_alloc + +--- + + context + clock + deadline_timeout + helping_lock + ipc_timeout + irq + kernel_uart + kip_init + kmem_alloc + kobject + map_util + mapdb + mappable + mapping_tree + mem_layout + mem_space + obj_space + pic + preemption + rcupdate + receiver + simple_mapdb + space + switch_lock + task + thread_lock + timeout + timer + thread + vkey + jdb_trace + jdb_tbuf + tb_entry +kip + config + pic + +--- + + context + deadline_timeout + helping_lock + ipc_timeout + irq + kernel_uart + kmem_alloc + kobject + map_util + mapdb + mappable + mapping_tree + mem_layout + mem_space + obj_space + pic + preemption + receiver + simple_mapdb + space + switch_lock + task + thread_lock + thread + vkey +kip_init + config + kip + mem_layout + pic + +--- + + context + deadline_timeout + helping_lock + ipc_timeout + irq + kernel_uart + kobject + map_util + mapdb + mappable + mapping_tree + mem_space + obj_space + pic + preemption + receiver + simple_mapdb + space + switch_lock + task + thread_lock + thread + vkey +kmem + config + mapped_alloc + mem_layout + paging + pic + +--- + + thread +kmem_alloc + buddy_alloc + config + kip + kip_init + mapped_alloc + mem_layout + pic + +--- + + fpu_alloc + irq + kernel_uart + kobject + map_util + mapdb + mappable + mapping_tree + pic + simple_mapdb + task + thread + vkey +kmem_slab + config + kmem_slab_simple + mapped_alloc + mem_layout + pic + +--- + + fpu_alloc + irq + kernel_uart + kmem_slab + kobject + map_util + mapdb + mappable + mapping_tree + pic + simple_mapdb + task + thread + vkey +kmem_slab_simple + config + mapped_alloc + mem_layout + pic + +--- + + irq + kernel_uart + map_util + pic + simple_mapdb + task + thread + vkey +kobject + clock + config + context + entry_frame + globals + helping_lock + jdb_tbuf + kip + kip_init + kmem + kmem_slab + kmem_slab_simple + mappable + mapped_alloc + mapping + mapping_tree + mem_layout + mem_space + obj_space + paging + pic + rcupdate + space + switch_lock + tb_entry + timeout + timer + trap_state + +--- + + irq + kernel_uart + pic + task + thread + vkey +map_util + clock + config + context + entry_frame + globals + helping_lock + jdb_tbuf + kip + kip_init + kmem + kmem_slab + kmem_slab_simple + kobject + mapdb + mappable + mapped_alloc + mapping + mapping_tree + mem_layout + mem_space + obj_space + paging + pic + rcupdate + simple_mapdb + space + switch_lock + tb_entry + timeout + timer + trap_state + +--- + + irq + kernel_uart + map_util + pic + task + thread + vkey +mapdb + clock + config + context + entry_frame + globals + helping_lock + jdb_tbuf + kip + kip_init + kmem + kmem_slab + kmem_slab_simple + mapped_alloc + mapping + mapping_tree + mem_layout + mem_space + obj_space + paging + pic + rcupdate + space + switch_lock + tb_entry + timeout + timer + trap_state + +--- + + irq + kernel_uart + kobject + map_util + pic + simple_mapdb + task + thread + vkey +mappable + clock + config + context + entry_frame + globals + helping_lock + jdb_tbuf + kip + kip_init + kmem + kmem_slab + kmem_slab_simple + mapped_alloc + mapping + mapping_tree + mem_layout + mem_space + obj_space + paging + pic + rcupdate + space + switch_lock + tb_entry + timeout + timer + trap_state + +--- + + context + deadline_timeout + helping_lock + ipc_timeout + irq + kernel_uart + kmem + kmem_alloc + kmem_slab + kmem_slab_simple + kobject + map_util + mapdb + mappable + mapping_tree + mem_space + obj_space + paging + pic + preemption + receiver + simple_mapdb + space + switch_lock + task + thread_lock + thread + vkey + vmem_alloc +mapped_alloc + config + mem_layout + pic + +--- + + irq + kernel_uart + kobject + map_util + mapdb + mappable + mapping_tree + pic + simple_mapdb + task + thread + vkey +mapping + config + pic + +--- + + irq + kernel_uart + kobject + map_util + mapdb + mappable + pic + simple_mapdb + task + thread + vkey +mapping_tree + clock + config + context + entry_frame + globals + helping_lock + jdb_tbuf + kip + kip_init + kmem + kmem_slab + kmem_slab_simple + mapped_alloc + mapping + mem_layout + mem_space + obj_space + paging + pic + rcupdate + space + switch_lock + tb_entry + timeout + timer + trap_state + +--- + + context + deadline_timeout + globals + helping_lock + ipc_timeout + irq + kernel_uart + kip_init + kmem + kmem_alloc + kmem_slab + kmem_slab_simple + kobject + map_util + mapdb + mappable + mapped_alloc + mapping_tree + mem_space + obj_space + paging + pic + preemption + rcupdate + receiver + simple_mapdb + space + switch_lock + task + thread_lock + timeout + timer + thread + vkey + vmem_alloc + jdb_trace + jdb_tbuf + tb_entry +mem_layout + config + kip + kip_init + pic + +--- + + context + deadline_timeout + helping_lock + ipc_timeout + irq + kernel_uart + kobject + map_util + mapdb + mappable + mapping_tree + obj_space + pic + preemption + receiver + simple_mapdb + space + switch_lock + task + thread_lock + thread + vkey +mem_space + config + entry_frame + globals + jdb_tbuf + kip + kip_init + kmem + mapped_alloc + mem_layout + paging + pic + tb_entry + trap_state + +--- + + context + deadline_timeout + helping_lock + ipc_timeout + irq + kernel_uart + kobject + map_util + mapdb + mappable + mapping_tree + pic + preemption + receiver + simple_mapdb + space + switch_lock + task + thread_lock + thread + vkey +obj_space + config + entry_frame + globals + jdb_tbuf + kip + kip_init + kmem + mapped_alloc + mem_layout + mem_space + paging + pic + tb_entry + trap_state + +--- + + context + deadline_timeout + helping_lock + ipc_timeout + irq + kernel_uart + kmem + kobject + map_util + mapdb + mappable + mapping_tree + mem_space + obj_space + pic + preemption + receiver + simple_mapdb + space + switch_lock + task + thread_lock + thread + vkey + vmem_alloc +paging + config + mapped_alloc + mem_layout + pic + +--- + + kip + buddy_alloc + config + context + deadline_timeout + entry_frame + fpu_alloc + globals + helping_lock + ipc_timeout + irq + irq_alloc + kernel_console + kernel_uart + kip_init + kmem + kmem_alloc + kmem_slab + kmem_slab_simple + kobject + map_util + mapdb + mappable + mapped_alloc + mapping + mapping_tree + mem_layout + mem_space + obj_space + paging + preemption + rcupdate + receiver + simple_mapdb + space + switch_lock + task + thread_lock + timeout + timer + thread + vkey + vmem_alloc + jdb_trace + jdb_tbuf + tb_entry + uart +pic + clock + config + context + deadline_timeout + entry_frame + globals + helping_lock + irq + irq_alloc + jdb_tbuf + jdb_trace + kip + kip_init + kmem + kmem_slab + kmem_slab_simple + kobject + map_util + mapdb + mappable + mapped_alloc + mapping + mapping_tree + mem_layout + mem_space + obj_space + paging + preemption + rcupdate + receiver + simple_mapdb + space + switch_lock + tb_entry + thread + thread_lock + timeout + timer + trap_state + vkey + vmem_alloc + +--- + + deadline_timeout + irq + kernel_uart + pic + thread + vkey +preemption + clock + config + context + entry_frame + globals + jdb_tbuf + kip + kip_init + kmem + mapped_alloc + mem_layout + mem_space + obj_space + paging + pic + rcupdate + receiver + space + switch_lock + tb_entry + thread_lock + timeout + timer + trap_state + +--- + + context + deadline_timeout + helping_lock + ipc_timeout + irq + kernel_uart + kobject + map_util + mapdb + mappable + mapping_tree + pic + preemption + receiver + simple_mapdb + switch_lock + task + thread_lock + thread + vkey +rcupdate + config + entry_frame + globals + jdb_tbuf + kip + mem_layout + pic + tb_entry + timeout + timer + trap_state + +--- + + deadline_timeout + ipc_timeout + irq + kernel_uart + pic + preemption + thread + vkey +receiver + clock + config + context + entry_frame + globals + jdb_tbuf + kip + kip_init + kmem + mapped_alloc + mem_layout + mem_space + obj_space + paging + pic + rcupdate + space + switch_lock + tb_entry + thread_lock + timeout + timer + trap_state + +--- + + irq + kernel_uart + map_util + pic + task + thread + vkey +simple_mapdb + clock + config + context + entry_frame + globals + helping_lock + jdb_tbuf + kip + kip_init + kmem + kmem_slab + kmem_slab_simple + kobject + mappable + mapped_alloc + mapping + mapping_tree + mem_layout + mem_space + obj_space + paging + pic + rcupdate + space + switch_lock + tb_entry + timeout + timer + trap_state + +--- + + context + deadline_timeout + helping_lock + ipc_timeout + irq + kernel_uart + kobject + map_util + mapdb + mappable + mapping_tree + pic + preemption + receiver + simple_mapdb + switch_lock + task + thread_lock + thread + vkey +space + config + entry_frame + globals + jdb_tbuf + kip + kip_init + kmem + mapped_alloc + mem_layout + mem_space + obj_space + paging + pic + tb_entry + trap_state + +--- + + deadline_timeout + helping_lock + ipc_timeout + irq + kernel_uart + kobject + map_util + mapdb + mappable + mapping_tree + pic + preemption + receiver + simple_mapdb + task + thread_lock + thread + vkey +switch_lock + clock + config + context + entry_frame + globals + jdb_tbuf + kip + kip_init + kmem + mapped_alloc + mem_layout + mem_space + obj_space + paging + pic + rcupdate + space + tb_entry + timeout + timer + trap_state + +--- + + thread +task + clock + config + context + entry_frame + globals + helping_lock + jdb_tbuf + kip + kip_init + kmem + kmem_slab + kmem_slab_simple + kobject + map_util + mapdb + mappable + mapped_alloc + mapping + mapping_tree + mem_layout + mem_space + obj_space + paging + pic + rcupdate + simple_mapdb + space + switch_lock + tb_entry + timeout + timer + trap_state + vmem_alloc + +--- + + context + deadline_timeout + helping_lock + ipc_timeout + irq + kernel_uart + kobject + map_util + mapdb + mappable + mapping_tree + mem_space + obj_space + pic + preemption + rcupdate + receiver + simple_mapdb + space + switch_lock + task + thread_lock + thread + vkey + jdb_trace + jdb_tbuf +tb_entry + config + entry_frame + globals + kip + mem_layout + pic + trap_state + +--- + + irq + kernel_uart + pic + vkey +thread + clock + config + context + deadline_timeout + entry_frame + fpu_alloc + globals + helping_lock + ipc_timeout + irq_alloc + jdb_tbuf + jdb_trace + kip + kip_init + kmem + kmem_alloc + kmem_slab + kmem_slab_simple + kobject + map_util + mapdb + mappable + mapped_alloc + mapping + mapping_tree + mem_layout + mem_space + obj_space + paging + pic + preemption + rcupdate + receiver + simple_mapdb + space + switch_lock + task + tb_entry + thread_lock + timeout + timer + trap_state + vmem_alloc + +--- + + deadline_timeout + ipc_timeout + irq + kernel_uart + pic + preemption + receiver + thread + vkey +thread_lock + clock + config + context + entry_frame + globals + jdb_tbuf + kip + kip_init + kmem + mapped_alloc + mem_layout + mem_space + obj_space + paging + pic + rcupdate + space + switch_lock + tb_entry + timeout + timer + trap_state + +--- + + context + deadline_timeout + helping_lock + ipc_timeout + irq + kernel_uart + kobject + map_util + mapdb + mappable + mapping_tree + pic + preemption + rcupdate + receiver + simple_mapdb + switch_lock + task + thread_lock + thread + vkey +timeout + config + globals + kip + mem_layout + pic + timer + +--- + + context + deadline_timeout + helping_lock + ipc_timeout + irq + kernel_uart + kobject + map_util + mapdb + mappable + mapping_tree + pic + preemption + rcupdate + receiver + simple_mapdb + switch_lock + task + thread_lock + timeout + thread + vkey +timer + config + globals + kip + mem_layout + pic + +--- + + context + deadline_timeout + helping_lock + ipc_timeout + irq + kernel_uart + kobject + map_util + mapdb + mappable + mapping_tree + mem_space + obj_space + pic + preemption + rcupdate + receiver + simple_mapdb + space + switch_lock + task + thread_lock + thread + vkey + jdb_trace + jdb_tbuf + tb_entry +trap_state + entry_frame + +--- + + kernel_uart + vkey +uart + pic + +--- + + pic +vkey + clock + config + context + deadline_timeout + entry_frame + globals + helping_lock + irq + irq_alloc + jdb_tbuf + jdb_trace + kernel_console + kernel_uart + kip + kip_init + kmem + kmem_slab + kmem_slab_simple + kobject + map_util + mapdb + mappable + mapped_alloc + mapping + mapping_tree + mem_layout + mem_space + obj_space + paging + pic + preemption + rcupdate + receiver + simple_mapdb + space + switch_lock + tb_entry + thread + thread_lock + timeout + timer + trap_state + uart + vmem_alloc + +--- + + irq + kernel_uart + pic + task + thread + vkey +vmem_alloc + config + mapped_alloc + mem_layout + paging + pic + +--- + +TOTAL CIRCULAR DEPS: +744 diff --git a/kernel/fiasco/src/Circular.max.ux b/kernel/fiasco/src/Circular.max.ux new file mode 100644 index 00000000..6b184900 --- /dev/null +++ b/kernel/fiasco/src/Circular.max.ux @@ -0,0 +1,6 @@ +Do "make DEPS" for full fine-grained dependency information. + +--- + +TOTAL CIRCULAR DEPS: +0 diff --git a/kernel/fiasco/src/DEPS.blacklist b/kernel/fiasco/src/DEPS.blacklist new file mode 100644 index 00000000..5a617062 --- /dev/null +++ b/kernel/fiasco/src/DEPS.blacklist @@ -0,0 +1,13 @@ +# lines starting with '*' are black lists for dependents and dependees +# lines starting with '->' are black lists for dependees +# lines starting with ':' are black lists for dependents + +# KERNEL +*config.* l4_types types globalconfig + +# LIBC +*.?stdlib .?assert .?stdio .?stdarg .?string __main _exit initfini +*.?ctype .?setjmp .?alloca .?limits .?stddef .?cdefs .?signal +*sys_wait sys_types sys_ptrace sys_user .?errno asm_unistd sys_stat +*sys_mman fcntl sys_poll sys_ucontext simpleio keycodes + diff --git a/kernel/fiasco/src/Kconfig b/kernel/fiasco/src/Kconfig new file mode 100644 index 00000000..bed59ed9 --- /dev/null +++ b/kernel/fiasco/src/Kconfig @@ -0,0 +1,804 @@ + + +mainmenu "Fiasco configuration" + +config KERNELVERSION + string + option env="KERNELVERSION" + +config INCLUDE_PPC32 + bool + option env="INCLUDE_PPC32" + help + Use "INCLUDE_PPC32=y make config" to include ppc32 options. + +config INCLUDE_SPARC + bool + option env="INCLUDE_SPARC" + help + Use "INCLUDE_SPARC=y make config" to include sparc options. + +menu "Target configuration" + +choice + prompt "Architecture" + default IA32 + +config IA32 + bool "Intel IA-32 processor family" + +config AMD64 + bool "AMD64 processor family" + select CONTEXT_4K + +config ARM + bool "ARM processor family" + +config PPC32 + bool "PowerPC 32 processor family (Caution: INCOMPLETE!)" + depends on EXPERIMENTAL && INCLUDE_PPC32 + help + PPC32 testing version, mainly for MPC5200 (603e). Currently, + there is no support whatsoever. + select CONTEXT_4K + select BIG_ENDIAN + +config SPARC + bool "SPARC v8 processor family (Caution: EXPERIMENTAL)" + depends on EXPERIMENTAL && INCLUDE_SPARC + help + SPARC v8 is supposed to run on the LEON3 platform. + It is unsupported at the moment. + select CONTEXT_4K + + +endchoice + +config BIG_ENDIAN + bool + +choice + prompt "Platform" + default PF_INTEGRATOR if ARM + default PF_PC if IA32 + default PF_PC if AMD64 + default PF_MP52CXX if PPC32 + default PF_LEON3 if SPARC + +config PF_PC + bool "PC platform" + depends on IA32 || AMD64 + +config PF_UX + bool "Linux Usermode Platform" + depends on IA32 + select JDB + +# PF_CHOICE + +endchoice + +# PF_INCLUDE + +config ABI_VF + def_bool y + +config PF_ARM_MP_CAPABLE + bool + default y if ARM_MPCORE || ARM_CORTEX_A9 + +config CAN_ARM_CPU_SA1100 + bool + +config CAN_ARM_CPU_XSCALE + bool + +config CAN_ARM_CPU_920T + bool + +config CAN_ARM_CPU_926 + bool + +config CAN_ARM_CPU_1136 + bool + +config CAN_ARM_CPU_1176 + bool + +config CAN_ARM_CPU_MPCORE + bool + +config CAN_ARM_CPU_CORTEX_A8 + bool + +config CAN_ARM_CPU_CORTEX_A9 + bool + +config CAN_ARM_CACHE_L2CXX0 + bool + +choice + prompt "CPU" + default IA32_686 if IA32 + default ARM_926 if ARM + default AMD64_K8 if AMD64 + default PPC32_603e if PPC32 + default LEON3 if SPARC + +config ARM_PXA + bool "Intel XScale" + depends on PF_XSCALE + +config ARM_SA + bool "Intel StrongARM" + depends on PF_SA1100 + +config ARM_920T + bool "ARM 920T Processor" + depends on PF_S3C2410 + +config ARM_926 + bool "ARM 926 Processor" + depends on CAN_ARM_CPU_926 + +config ARM_1136 + bool "ARM 1136 CPU" + depends on CAN_ARM_CPU_1136 + +config ARM_1176 + bool "ARM 1176 CPU" + depends on CAN_ARM_CPU_1176 + +config ARM_MPCORE + bool "ARM MPCore CPU" + depends on CAN_ARM_CPU_MPCORE + +config ARM_CORTEX_A8 + bool "ARM Cortex-A8 CPU" + depends on CAN_ARM_CPU_CORTEX_A8 + +config ARM_CORTEX_A9 + bool "ARM Cortex-A9 CPU" + depends on CAN_ARM_CPU_CORTEX_A9 + +config IA32_486 + bool "Intel 80486" + depends on IA32 + help + Choose this if you have an Intel 80486 or equivalent CPU (i486). + +config IA32_586 + bool "Intel Pentium / AMD K5" + depends on IA32 + help + Choose this if you have an Intel Pentium or compatible i586 CPU. + +config IA32_686 + bool "Intel Pentium Pro" + depends on IA32 + help + Choose this if you have an Intel Pentium Pro or compatible i686 CPU. + +config IA32_P2 + bool "Intel Pentium II / Celeron II" + depends on IA32 + help + Choose this if you have an Intel Pentium II or Pentium II based Celeron. + +config IA32_P3 + bool "Intel Pentium III / Celeron III" + depends on IA32 + help + Choose this if you have an Intel Pentium III or Pentium III based Celeron. + +config IA32_P4 + bool "Intel Pentium 4 / Celeron 4" + depends on IA32 + help + Choose this if you have an Intel Pentium 4 or Pentium 4 based Celeron. + +config IA32_PM + bool "Intel Pentium M" + depends on IA32 + help + Choose this if you have an Intel Pentium M. + +config IA32_CORE2 + bool "Intel Core 2" + depends on IA32 + help + Choose this if you have an Intel Core 2. + +config IA32_ATOM + bool "Intel Atom" + depends on IA32 + help + Choose this if you have an Intel Atom. + +config IA32_K6 + bool "AMD K6 / K6-II / K6-III" + depends on IA32 + help + Choose this if you have an AMD K6 CPU. + +config IA32_K7 + bool "AMD Athlon / Duron" + depends on IA32 + help + Choose this if you have an AMD Athlon or Duron CPU. + +config IA32_K8 + bool "AMD Opteron / Athlon64" + depends on IA32 + help + Choose this if you have an AMD Opteron or Athlon64 CPU. + +config IA32_K10 + bool "AMD Barcelona (K10)" + depends on IA32 + help + Choose this if you have an AMD Barcelona based CPU. + + +config AMD64_K8 + bool "AMD Opteron / Athlon64" + depends on AMD64 + help + Choose this if you have an AMD Opteron or Athlon64 CPU. + +config AMD64_CORE2 + bool "Intel Core 2" + depends on AMD64 + help + Choose this if you have an Intel Core 2. + +config AMD64_ATOM + bool "Intel Atom" + depends on AMD64 + help + Choose this if you have an Intel Atom. + +config AMD64_K10 + bool "AMD Barcelona (K10)" + depends on AMD64 + help + Choose this if you have an AMD Barcelona based CPU. + + +config PPC32_603e + bool "PowerPC 603e" + depends on PPC32 + help + Choose this if you have an PowerPC 603e CPU. + +config LEON3 + bool "Gaisler SPARC LEON3" + depends on SPARC + help + Choose this if you have a LEON3 CPU. +endchoice + + + +config CPU_VIRT + bool "Enable CPU virtualization (SVM and VT)" + depends on PF_PC + help + Support virtualization extensions that comes with x86 CPUs, + including nested paging. This feature allows you to run a virtual + machine monitor (VMM) on top of Fiasco. + +config ARM_ALIGNMENT_CHECK + bool "Enable alignment check" + depends on ARM + help + Enable if you want to have alignment check enabled. + +config ARM_TZ + bool "Enable ARM TrustZone support" + depends on (ARM_1176 || ARM_CORTEX_A8 || ARM_CORTEX_A9) && EXPERIMENTAL + help + Support ARM TrustZone security extension. + +config ARM_CA9_ENABLE_SWP + bool "Enable the deprecated 'swp' instruction" + depends on ARM_CORTEX_A9 + help + Enabling this option enables the deprecated 'swp' instruction. + Avoid to enable it. + +config ARM_CACHE_L2CXX0 + bool "Enable L2 Cache" + default y + depends on CAN_ARM_CACHE_L2CXX0 + help + Enable L2 cache functionality. + +choice + prompt "Timer tick source" + depends on PF_PC || PF_UX + default SCHED_APIC + +config SCHED_PIT + bool "Use PIT for scheduling" + depends on (PF_PC || PF_UX) && !MP + help + Normally, Fiasco uses the RTC at IRQ8 for scheduling. This can be + disadvantageous in certain circumstances, e.g. VMWare doesn't seem + to emulate the RTC good enough so that not enough timer interrupts + are produced. The PIT mode (using IRQ0) seems to work better in + this case. It is generally safe to use this option, so if you are + unsure, say 'Y'. + + Consider that the interrupt priorities change: Using RTC, IRQ8 has + the highest priority. Using PIT, IRQ0 has the highest priority. + The only case where PIT scheduling does not work is with + profiling. If profiling is enabled the PIT is used for generating + the profiling interrupts. + +config SCHED_RTC + bool "Use RTC for scheduling" + depends on PF_PC && !MP + help + 'Yes' is the standard for this option. If this option is set + Fiasco uses the RTC on IRQ 8 for scheduling. This can be + disadvantageous in certain circumstances, e.g. VMWare doesn't seem + to emulate the RTC good enough so that not enough timer interrupts + are produced. The PIT (8254) mode (say 'no' here), seems to work + better in this case. It is generally safe to use the PIT, so if + you are unsure, say 'no'. + Consider that the interrupt priorities change: Using RTC, IRQ8 has + the highest priority. Using PIT, IRQ0 has the highest priority. + The only case where PIT scheduling does not work is with + profiling. If profiling is enabled the PIT is used for generating + the profiling interrupts and the RTC must be used for scheduling. + In the case where profiling shall be used within VMWare the + SLOW_RTC option must be set, so that the timer resolution of + Fiasco is reduced to 100Hz. + +config SCHED_APIC + bool "Use APIC timer for scheduling" + depends on PF_PC + help + Use the Local APIC for scheduling. + +config SCHED_HPET + bool "Use HPET timer for scheduling (EXPERIMENTAL)" + depends on PF_PC && !MP && EXPERIMENTAL + help + Use the HPET timer for scheduling. + +endchoice + +config WORKAROUND_AMD_FPU_LEAK + bool "Enables workaroud for AMD FPU security leak" + depends on PF_PC + help + If you use Fiasco for high assurance, high security and use AMD + CPUs you should enable this option. In any other case it is no + harm to disable it. + +config REGPARM3 + bool "Compile with regparm=3" + default y + depends on IA32 && PF_PC + help + Compile Fiasco with -mregparm=3. This uses a different ABI and + passes the first three arguments of a function call in registers. + +config FPU + bool "Enable FPU co-processor" + depends on ARM + help + Enable this if your platform has hardware floating point support. + +config ARM_1176_CACHE_ALIAS_FIX + bool "Use cache restriction to supress aliasing issue on ARM1176" + depends on ARM_1176 + help + The ARM1176 processor might have a memory aliasing problem when + using cache sizes of more than 16kB cache. Enabling this option + enables the workaround of reducing the cache size to 16kB. + +endmenu # target + +menu "Kernel options" + +config MP + bool "Enable multi processor support" + depends on (PF_PC || PF_ARM_MP_CAPABLE || (PF_UX && EXPERIMENTAL)) + help + Enable support for machines with multiple processors. + +config MP_MAX_CPUS + int "Maximal supported number of CPUs" + depends on MP + range 1 128 + default 4 + help + The maximum number of CPUs the kernel supports. + +#config ASSEMBLER_IPC_SHORTCUT +# bool "Assembler IPC shortcut" +# default y +# depends on (PF_PC || PF_UX) && !MP +# help +# Use the assembler IPC shortcut to get even better short IPC +# performance in the common case. + +config CONTEXT_4K + bool #"TCB size of 4k" + default y + help + Use this option to use 4K kernel stacks. Only disable this option + when you know what you're doing. + +config IO_PROT + bool "Enable I/O port protection" + default y + depends on PF_PC + help + Enabling this option adds I/O port protection to the kernel. That + means that every thread starts running at IOPL 0 which means that + only the kernel has full access to all I/O ports. This includes + the right to set and clear the interrupt flags (that is using cli + and sti). Access rights to I/O ports can be mapped like memory. If + a task has access to the whole I/O port space, its IOPL is raised + to 3 allowing the task to use cli and sti. + +config SLOW_RTC + bool "Use RTC with 100 ticks per second" + depends on SCHED_RTC + help + This option should be enabled if you use VMWare and no PIT + scheduling. The timer resolution is lowered to 100 ticks per + second. + +config ONE_SHOT + bool "Use scheduling timer in one-shot mode" + depends on SCHED_APIC && SYNC_TSC + help + More costly than periodic but more fine-granular scheduling + possible. EXPERIMENTAL! + +config SYNC_TSC + bool "Use time-stamp counter for KIP and scheduling accounting" + depends on PF_PC && IA32 + help + Synchronize the internal kernel clock with the CPU time stamp + counter. + +config FINE_GRAINED_CPUTIME + bool "Fine-grained CPU time" + help + Measure CPU time consumed by a thread from switching to the thread + until switching to another thread. Induces an overhead during each + thread switch, so only activate it for debugging. + +config UX_CON + bool "Graphical console (requires SDL library!)" + depends on PF_UX + help + Fiasco-UX can supply a graphical console for the L4 program it is + running. Enabling this option will build the additional program + but needs the SDL library including development header files + installed. + +config UX_NET + bool "Network support" + depends on PF_UX + help + Enabling this option makes Fiasco-UX provide network support for + L4 programs. + +choice + prompt "Scheduler" + default FIXED_PRIO + +config SCHED_FIXED_PRIO + bool "Fixed priority scheduler" + help + Choose this for the standard fixed priority scheduler with + 256 priority levels. + +config SCHED_WFQ + bool "Weighted fair queueing scheduler" + depends on EXPERIMENTAL + help + Choose this scheduler for a weighted fair queueing scheduler + running with dynamic priorities. + +config SCHED_FP_WFQ + bool "Combined fixed priority RT and WFQ scheduler" + depends on EXPERIMENTAL + help + Combination of Fixed priority and weighted fair queueing + scheduler. + +endchoice + +config DISABLE_VIRT_OBJ_SPACE + bool "No virtually mapped array for cap tables" + depends on (PF_PC || ARM) && EXPERIMENTAL + default n + +endmenu # kernel options + +menu "Debugging" + +config INLINE + bool "Generate inline code" + default y + help + Inlining specifies that it is desirable for the compiler to + integrate functions declared 'inline' into the calling routine. + This usually leads to faster code, so unless you want to debug the + kernel you should say 'Y' here. + +config NDEBUG + bool "Do not compile assertions" + help + Don't insert assertions into the code. Should be enabled for + kernels which are used for measurements. + +config NO_FRAME_PTR + bool "Compile without frame pointer" + default y + help + Enabling this option optimizes for speed but makes debugging more + difficult. + +config STACK_DEPTH + bool "Measure stack depth of threads" + help + When this option is enabled, each thread control block is marked + with magic numbers while creation. The function ``show thread + lists'' scans the TCB for these magic numbers and shows the + currently used depth of each thread. + +config LIST_ALLOC_SANITY + bool "Sanity checks in low level allocator" + help + When this option is enabled the low level memory allocator does + extra sanity checks on its data structures before and after every + operation. This can halp detect flaws like double frees or memory + corruption by other means. + + These tests are very expensive so only enable them if a problem + with memory allocation is expected. + +config BEFORE_IRET_SANITY + bool "Sanity checks at syscall entry/exit" + depends on PF_PC + help + Perform the following additional sanity checks before returning to + usermode: + - Does the thread hold any locks? + - Is the thread locked by any other thread? + - Does the thread have the right state: + * Thread_ready must be set. + * Thread_cancel and Thread_fpu_owner might be set. + * Any other state bit must not be set. + Don't use Fiasco compiled with this option for performance analysis! + +config GSTABS + bool "Compile with gstabs+ debugging information" + depends on n + help + Enabling this option includes the debugging information using the + older gstabs+ format into the kernel image. This is necessary to + access line number information of the kernel from JDB. + +config IRQ_SPINNER + bool "Display IRQ activity on VGA screen" + depends on PF_PC + help + Display IRQ activity on VGA screen. + +config WATCHDOG + bool "Enable Watchdog support" + default y + depends on PF_PC + help + Enable support for watchdog using the builtin Local APIC and a + performance counter. The watchdog can be enabled using the + -watchdog command line option. + +config SERIAL + bool "Support for debugging over serial line" + depends on PF_PC || ARM || PPC32 || SPARC + default y + help + This option enables support for input/output over serial interface. + +menuconfig JDB + bool "JDB kernel debugger" + default y + help + The powerful Fiasco kernel debugger. + +if JDB + +config JDB_LOGGING + bool "JDB extended logging" + help + There are two classes of logging events: Basic events don't + consume any time if they are disabled (ipc, ipc result, + pagefaults, unmap). Extended logging events add an additional + overhead of most probably less than 10 cycles if they are + disabled. These events can be activated/deactivated by the 'O' + command in jdb. + + Should be disabled for kernels which are used for measurements. + +config JDB_DISASM + bool "JDB disassembler" + default n if ARM + default y + help + Add support for disassembly. Increases memory foot-print, only + enable when needed. + +config JDB_GZIP + bool "GZIP compressed dumps" + default n if ARM + default y + help + Add supprt for gzip compressed dumps of the trace buffer. + Increases memory foot-print, only enabled when needed. + +config JDB_ACCOUNTING + bool "JDB accounting" + depends on IA32 + help + Enable accounting information about IPCs, context switches, page + faults, and other events. The counters are accessible from + userland through the tbuf status page. + + Should be disabled for kernels which are used for measurements. + +config JDB_MISC + bool "Miscellaneous JDB modules" + depends on PF_UX || PF_PC + +endif # JDB + + +config VMEM_ALLOC_TEST + bool "Run test for Vmem_alloc allocator" + depends on ARM + +config DEBUG_KERNEL_PAGE_FAULTS + bool "Debugging of kernel page-faults" + depends on ARM + help + This option enables logging of kernel page-faults (aka page faults + from kernel mode). The page faults are logged to the normal + console in the format *KP[pfa, error_code, ip]. + +config POWERSAVE_GETCHAR + bool "Save power in getchar()" + default y + depends on PF_PC + help + This option uses a processor HALT in getchar() to save power and + prevent some P4 processors from being overheated. This option + requires a working timer IRQ to wakeup getchar periodically. + +choice + prompt "Warn levels" + default WARN_WARNING + +config WARN_NONE + bool "Do not show show any kernel warning" + +config WARN_WARNING + bool "Show messages of warning level" + +config WARN_ANY + bool "Show all kernel warnings" + +endchoice # warn levels + +endmenu # debugging + +menu "Compiling" + +config CC + string "C compiler" + default "gcc" + help + Use this option to override the default C compiler (gcc). + +config CXX + string "C++ compiler" + default "g++" + help + Use this option to override the default C++ compiler (g++). + +config HOST_CC + string "C host compiler" + default "gcc" + help + Use this option to override the default C host compiler (gcc). + +config HOST_CXX + string "C++ host compiler" + default "g++" + help + Use this option to override the default C++ host compiler (g++). + +config MAINTAINER_MODE + bool "Do additional checks at build time" + help + This enables the circular dependency and initcall checks. + Say 'Yes' here if you do kernel hacking. + +config LABEL + string "Configuration label" + help + Text string with a name for this configuration. To be displayed in + the kernel boot-up. + +endmenu + +config EXPERIMENTAL + bool "Prompt for experimental features" + help + Experimental features are available when enabling this option. + Enabling these features might be less than fully secure and may + disrupt the stability of your kernel. + + Use with caution! + +config PERF_CNT + def_bool y if JDB && (IA32 || AMD64 || ARM) + +config BIT32 + def_bool y if ARM || IA32 || PPC32 || SPARC + +config BIT64 + def_bool y if AMD64 + +config ARM_V6 + def_bool y if ARM_1136 || ARM_1176 || ARM_MPCORE + +config ARM_V7 + def_bool y if ARM_CORTEX_A8 || ARM_CORTEX_A9 + +config ARM_V6PLUS + def_bool y if ARM_V6 || ARM_V7 + +config WARN_LEVEL + int + default 2 if WARN_ANY + default 1 if WARN_WARNING + default 0 if WARN_NONE + +config XARCH + string + default "arm" if ARM + default "ux" if PF_UX + default "amd64" if AMD64 && PF_PC + default "ia32" if IA32 && PF_PC + default "ppc32" if PPC32 + default "sparc" if SPARC + +config IA32_TARGET + string + default "Intel 80486" if IA32_486 + default "Intel Pentium" if IA32_586 + default "Intel Pentium Pro" if IA32_686 + default "Intel Pentium II" if IA32_P2 + default "Intel Pentium III" if IA32_P3 + default "Intel Pentium 4" if IA32_P4 + default "Pentium M" if IA32_PM + default "AMD K6" if IA32_K6 + default "AMD Athlon" if IA32_K7 + default "Intel Core2" if IA32_CORE2 || AMD64_CORE2 + default "Intel Atom" if IA32_ATOM || AMD64_ATOM + default "AMD Opteron" if IA32_K8 || AMD64_K8 || AMD64_K10 || IA32_K10 + +config ABI + string + default "vf" diff --git a/kernel/fiasco/src/Makeconf b/kernel/fiasco/src/Makeconf new file mode 100644 index 00000000..64c327b1 --- /dev/null +++ b/kernel/fiasco/src/Makeconf @@ -0,0 +1,205 @@ +# -*- Makefile -*- +# Fiasco make configuration file +# +# created 1996/04/20 by hohmuth +# + +CHECKCC = $(shell if $(CC) $(1) -S -o /dev/null -xc /dev/null \ + > /dev/null 2>&1; then echo "$(1)"; else echo "$(2)"; fi ;) + +CHECKCXX = $(shell if $(CXX) $(1) -S -o /dev/null -xc++ /dev/null \ + > /dev/null 2>&1; then echo "$(1)"; else echo "$(2)"; fi ;) + +eval_impl = $(if $($(1)_IMPL),$($(1)_IMPL),$(1)) + +include $(objbase)/globalconfig.out +# use patsubst here to prevent confusion of syntax highlighting editors :-) +CONFIG_XARCH := $(patsubst "%",%,$(CONFIG_XARCH)) +CONFIG_ABI := $(patsubst "%",%,$(CONFIG_ABI)) + +SYSTEM := $(shell uname) +CC := $(patsubst "%",%,$(CONFIG_CC)) +CXX := $(patsubst "%",%,$(CONFIG_CXX)) +HOST_CC := $(patsubst "%",%,$(CONFIG_HOST_CC)) +HOST_CXX := $(patsubst "%",%,$(CONFIG_HOST_CXX)) +RM := rm -f +RM_R := rm -rf +ECHO := echo +ECHO_E := bash --norc -c 'echo -e "$$0" "$$@"' +CP := cp +GREP := GREP_OPTIONS= grep +AWKP ?= gawk --posix +CFLAGS := +CXXFLAGS := -std=c++0x +OPT_CFLAGS := -O2 +OPT_CXXFLAGS := -O2 +NOOPT_CFLAGS := -Os +NOOPT_CXXFLAGS := -Os +ARFLAGS := crs +srcdir ?= . +L4DIR ?= $(srcdir)/../../../l4 +tooldir := $(srcdir)/../tool +MOVE_IF_CHANGE := $(srcdir)/../tool/move-if-change +SHOWDEPS := $(srcdir)/../tool/showdeps +PREPROCESSDEPS := $(srcdir)/../tool/parsedeps +CIRCULAR := $(srcdir)/../tool/circular + +ifeq ($(SYSTEM),FreeBSD) + MD5SUM := /sbin/md5 +else + MD5SUM := md5sum +endif + +# The name of this file can be overridden from the command line or in +# objdir/Makeconf.local. +MODULES_FILE = $(srcdir)/Modules.$(CONFIG_XARCH) + +PREPROCESS = $(srcdir)/../tool/preprocess/src/preprocess + +ifeq ($(CONFIG_INLINE),y) + PREPROCESS_FLAGS = -i -t +else + PREPROCESS_FLAGS = -t +endif + +AS = $(SYSTEM_TARGET)as +LD = $(SYSTEM_TARGET)ld +AR = $(SYSTEM_TARGET)ar +NM = $(SYSTEM_TARGET)nm +RANLIB = $(SYSTEM_TARGET)ranlib +SIZE = $(SYSTEM_TARGET)size +STRIP = $(SYSTEM_TARGET)strip +OBJCOPY = $(SYSTEM_TARGET)objcopy +OBJDUMP = $(SYSTEM_TARGET)objdump + +# Include architecture-specific rules. These may overwrite anything above +include $(srcdir)/Makeconf.$(CONFIG_XARCH) + +# Include user-specific rules. These may overwrite anything above +-include $(srcdir)/Makeconf.local +-include $(objbase)/Makeconf.local + +ifneq ($(CCXX_VERSION),) + CCXX_SUFFIX := -$(CCXX_VERSION) +endif + +CPP := $(SYSTEM_TARGET)cpp$(CCXX_SUFFIX) + +CC := $(CCXX_WRAP) $(SYSTEM_TARGET)$(CC)$(CCXX_SUFFIX) +CXX := $(CCXX_WRAP) $(SYSTEM_TARGET)$(CXX)$(CCXX_SUFFIX) + +CC_TYPE := $(if $(findstring clang,$(shell $(CXX) --version)),clang,gcc) +CCVER_MAJOR := $(shell $(CXX) -dumpversion | cut -d . -f 1) +CCVER_MINOR := $(shell $(CXX) -dumpversion | cut -d . -f 2) +LIBGCC := $(shell $(CXX) -print-libgcc-file-name) + + +L4ALL_INCDIR ?= $(addprefix -I, $(PRIVATE_INCDIR)) +L4STD_INCDIR ?= -nostdinc +L4STD_INCDIR_LAST ?= -I$(wildcard $(dir $(LIBGCC))/include \ + $(dir $(LIBGCC))/../include) +KERNEL_LDFLAGS += -gc-sections +SHARED_FLAGS-gcc += -fno-defer-pop -freg-struct-return +SHARED_FLAGS += -g -Wall -W +SHARED_FLAGS += -Wno-parentheses +SHARED_FLAGS += $(call CHECKCC,-Wformat=2,) +SHARED_FLAGS += $(call CHECKCC,-fno-stack-protector,) +SHARED_FLAGS += $(call CHECKCC,-fdiagnostics-show-option) + +OPT_CXXFLAGS-gcc += $(call CHECKCXX,-fweb,) +OPT_CFLAGS-gcc += $(call CHECKCC,-fweb,) +OPT_SHARED_FLAGS-gcc += $(call CHECKCC,-frename-registers,) +OPT_SHARED_FLAGS-gcc += $(call CHECKCC,-fgcse-after-reload,) +CXXFLAGS-gcc += -fno-implement-inlines + +-include $(objbase)/.Host-config + +# Configuration dependent compile flags +SHARED_FLAGS-$(CONFIG_NDEBUG) += -DNDEBUG +SHARED_FLAGS-$(CONFIG_NO_FRAME_PTR) += -fomit-frame-pointer +SHARED_FLAGS-$(CONFIG_GSTABS) += -gstabs+ +SHARED_FLAGS-$(CONFIG_UNREACHABLE_CODE) += $(call CHECKCC,-Wunreachable-code,) + +# Eagerly compute SHARED_FLAGS to avoid calling CHECKCC over and over again. +SHARED_FLAGS := $(SHARED_FLAGS) $(SHARED_FLAGS-y) +SHARED_FLAGS += $(SHARED_FLAGS-$(CC_TYPE)) +OPT_SHARED_FLAGS += $(OPT_SHARED_FLAGS-$(CC_TYPE)) +NOOPT_SHARED_FLAGS += $(NOOPT_SHARED_FLAGS-$(CC_TYPE)) + +# Standard compile flags +ASFLAGS += $(SHARED_FLAGS) -DASSEMBLER +ASFLAGS-clang += -no-integrated-as +CFLAGS += $(SHARED_FLAGS) +CXXFLAGS += $(SHARED_FLAGS) -fno-rtti -fno-exceptions +OPT_CFLAGS += $(OPT_SHARED_FLAGS) +OPT_CXXFLAGS += $(OPT_SHARED_FLAGS) +NOOPT_CFLAGS += $(NOOPT_SHARED_FLAGS) +NOOPT_CXXFLAGS += $(NOOPT_SHARED_FLAGS) +CPPFLAGS += $(L4STD_INCDIR) $(L4ALL_INCDIR) $(L4STD_INCDIR_LAST) +CXXFLAGS += $(call CHECKCXX,-fno-threadsafe-statics,) +CXXFLAGS += $(call CHECKCXX,-Wno-non-virtual-dtor,) + +ASFLAGS += $(ASFLAGS-$(CC_TYPE)) +CXXFLAGS += $(CXXFLAGS-$(CC_TYPE)) +OPT_CFLAGS += $(OPT_CFLAGS-$(CC_TYPE)) +OPT_CXXFLAGS += $(OPT_CXXFLAGS-$(CC_TYPE)) +NOOPT_CFLAGS += $(NOOPT_CFLAGS-$(CC_TYPE)) +NOOPT_CXXFLAGS += $(NOOPT_CXXFLAGS-$(CC_TYPE)) + + +# Output formatting, set V=1 to see command line, V=0 to prevent printing them +VERBOSE ?= @ +ifeq ($(V),1) + VERBOSE := + PREP_MESSAGE ?= @$(ECHO) " ... Preprocessing $(filter %.cpp,$^)" +endif +AR_MESSAGE ?= @$(ECHO) " ==> Archiving into $@" +COMP_MESSAGE ?= @$(ECHO) " ... Making $@" +LINK_MESSAGE ?= @$(ECHO) " ==> Linking $@" +DEP_MESSAGE ?= @$(ECHO) " ... Building dependencies for $<" +PREP_MESSAGE ?= @$(ECHO) " ... Preprocessing $*" +CHKSUM_MESSAGE ?= @$(ECHO) " ... Generating checksum for " +PATCH_MESSAGE ?= @$(ECHO) " ... Writing checksum into " +STRIP_MESSAGE ?= @$(ECHO) " ... Stripping $@" +GENVER_MESSAGE ?= @$(ECHO) " ... Generating version information" +CLEAN_MESSAGE ?= @$(ECHO) "Removing created files" +CLEANALL_MESSAGE?= @$(ECHO) "Removing all created files" +INST_MESSAGE ?= @$(ECHO) "Installing $(^F)" +OK_MESSAGE ?= + +COMP_MESSAGE_NOOPT ?= $(COMP_MESSAGE) + +ifneq ($(VERBOSE),) +MOVE_IF_CHANGE += -q +endif + +SRC_ALL = $(SRC_S) $(SRC_CPP) $(SRC_C) $(SRC_CC) +ifeq ($(filter clean cleanall mrproper,$(MAKECMDGOALS)),) +DEPS = $(foreach file,$(SRC_ALL), $(dir $(file)).$(notdir $(file)).d) +else +DEPS = /dev/null +endif + +# To enable all warning ... +ENABLE_ALL_WARNINGS ?= n + +ifeq ($(CC_TYPE),gcc) + ifeq ($(ENABLE_ALL_WARNINGS),y) + tmp := $(call CHECKCC,-Wframe-larger-than=512) + CFLAGS += $(tmp) + CXXFLAGS += $(tmp) + tmp := + else + F_UNINITIALIZED := $(firstword $(call CHECKCC,-Wmaybe-uninitialized) \ + $(call CHECKCC,-Wuninitialized)) + F_SET_NOT_USED := $(call CHECKCC,-Wunused-but-set-variable) + + F_UNINITIALIZED := $(patsubst -W%,-Wno-%,$(F_UNINITIALIZED)) + F_SET_NOT_USED := $(patsubst -W%,-Wno-%,$(F_SET_NOT_USED)) + + CFLAGS += $(F_UNINITIALIZED) $(F_SET_NOT_USED) + CXXFLAGS += $(F_UNINITIALIZED) $(F_SET_NOT_USED) + endif +endif + + diff --git a/kernel/fiasco/src/Makeconf.amd64 b/kernel/fiasco/src/Makeconf.amd64 new file mode 100644 index 00000000..1853672e --- /dev/null +++ b/kernel/fiasco/src/Makeconf.amd64 @@ -0,0 +1,27 @@ +# -*- makefile -*- + +#OPT_SHARED_FLAGS += $(call CHECKCC,-finline-limit=10000,) +#OPT_CXXFLAGS += $(call CHECKCXX,--param large-function-insns=10000) +#OPT_CFLAGS += $(call CHECKCC,--param large-function-insns=10000) + +# The -Os option of gcc-4.0 sets max-inline-insns-single to 5 which prevents +# inlining of almost every function +NOOPT_SHARED_FLAGS-gcc += $(call CHECKCC,--param max-inline-insns-single=50) +SHARED_FLAGS-gcc += -mpreferred-stack-boundary=4 +SHARED_FLAGS += -m64 -mcmodel=kernel -mno-red-zone -funit-at-a-time + +OPT_CFLAGS += -mno-red-zone -funit-at-a-time +OPT_CXXFLAGS += -mno-red-zone -funit-at-a-time + +SHARED_FLAGS-$(CONFIG_AMD64_CORE2) += $(call CHECKCC,-march=core2,) +SHARED_FLAGS-$(CONFIG_AMD64_ATOM) += $(call CHECKCC,-march=atom,) +SHARED_FLAGS-$(CONFIG_AMD64_K8) += $(call CHECKCC,-march=k8,) +SHARED_FLAGS += $(call CHECKCC,-mno-mmx,) +SHARED_FLAGS += $(call CHECKCC,-mno-sse,) +SHARED_FLAGS += $(call CHECKCC,-mno-sse2,) +SHARED_FLAGS += $(call CHECKCC,-mno-sse3,) +SHARED_FLAGS += $(call CHECKCC,-mno-3dnow,) + +ASFLAGS += -m64 -mcmodel=kernel +OFORMAT := elf64-x86-64 +LD_EMULATION_CHOICE := elf_x86_64 elf_x86_64_fbsd diff --git a/kernel/fiasco/src/Makeconf.arm b/kernel/fiasco/src/Makeconf.arm new file mode 100644 index 00000000..43bfbfe5 --- /dev/null +++ b/kernel/fiasco/src/Makeconf.arm @@ -0,0 +1,17 @@ +# -*- makefile -*- +#OPT_SHARED_FLAGS += $(call CHECKCC,-finline-limit=10000,) +SYSTEM_TARGET ?= arm-linux- +SHARED_FLAGS-$(CONFIG_ARM_PXA) += -mcpu=xscale +SHARED_FLAGS-$(CONFIG_ARM_SA) += -mcpu=strongarm1100 +SHARED_FLAGS-$(CONFIG_ARM_920T) += -mcpu=arm920t +SHARED_FLAGS-$(CONFIG_ARM_926) += -mcpu=arm926ej-s +SHARED_FLAGS-$(CONFIG_ARM_1136) += -mcpu=arm1136jf-s +SHARED_FLAGS-$(CONFIG_ARM_1176) += -mcpu=arm1176jzf-s +SHARED_FLAGS-$(CONFIG_ARM_MPCORE) += -mcpu=mpcore +SHARED_FLAGS-$(CONFIG_ARM_CORTEX_A8) += $(call CHECKCC,-mcpu=cortex-a8) +SHARED_FLAGS-$(CONFIG_ARM_CORTEX_A9) += $(call CHECKCC,-mcpu=cortex-a9) +SHARED_FLAGS += -msoft-float +SHARED_FLAGS += $(call CHECKCC,-mno-thumb-interwork) +SHARED_FLAGS += -marm -mabi=apcs-gnu +LDFLAGS += --no-warn-mismatch +LD_EMULATION_CHOICE := armelf armelf_linux_eabi armelf_fbsd diff --git a/kernel/fiasco/src/Makeconf.ia32 b/kernel/fiasco/src/Makeconf.ia32 new file mode 100644 index 00000000..7635ee32 --- /dev/null +++ b/kernel/fiasco/src/Makeconf.ia32 @@ -0,0 +1,40 @@ +# -*- makefile -*- + +#OPT_SHARED_FLAGS += $(call CHECKCC,-finline-limit=10000,) +#OPT_CXXFLAGS += $(call CHECKCXX,--param large-function-insns=10000) +#OPT_CFLAGS += $(call CHECKCC,--param large-function-insns=10000) + +# The -Os option of gcc-4.0 sets max-inline-insns-single to 5 which prevents +# inlining of almost every function +NOOPT_SHARED_FLAGS-gcc += $(call CHECKCC,--param max-inline-insns-single=50) +SHARED_FLAGS-gcc += -mpreferred-stack-boundary=2 +SHARED_FLAGS += -m32 + +SHARED_FLAGS-$(CONFIG_REGPARM3) += -mregparm=3 +SHARED_FLAGS-$(CONFIG_IA32_486) += -march=i486 +SHARED_FLAGS-$(CONFIG_IA32_586) += -march=i586 +SHARED_FLAGS-$(CONFIG_IA32_686) += -march=i686 +SHARED_FLAGS-$(CONFIG_IA32_P2) += -march=i686 $(call CHECKCC,-mtune=pentium2,\ + $(call CHECKCC,-mcpu=pentium2)) +SHARED_FLAGS-$(CONFIG_IA32_P3) += -march=i686 $(call CHECKCC,-mtune=pentium3,\ + $(call CHECKCC,-mcpu=pentium3)) +SHARED_FLAGS-$(CONFIG_IA32_P4) += -march=i686 $(call CHECKCC,-mtune=pentium4,\ + $(call CHECKCC,-mcpu=pentium4)) +SHARED_FLAGS-$(CONFIG_IA32_PM) += -march=i686 $(call CHECKCC,-mtune=pentium-m,\ + $(call CHECKCC,-mcpu=pentiumm)) +SHARED_FLAGS-$(CONFIG_IA32_CORE2) += $(call CHECKCC,-march=core2,-march=i686) +SHARED_FLAGS-$(CONFIG_IA32_ATOM) += $(call CHECKCC,-march=atom,-march=i686) +SHARED_FLAGS-$(CONFIG_IA32_K6) += $(call CHECKCC,-march=k6,-march=i586) +SHARED_FLAGS-$(CONFIG_IA32_K7) += $(call CHECKCC,-march=athlon,-march=i686) +SHARED_FLAGS-$(CONFIG_IA32_K8) += $(call CHECKCC,-march=k8,-march=i686) +SHARED_FLAGS-$(CONFIG_IA32_K10) += $(call CHECKCC,-march=barcelona,-march=i686) + +SHARED_FLAGS += $(call CHECKCC,-mno-mmx,) +SHARED_FLAGS += $(call CHECKCC,-mno-sse,) +SHARED_FLAGS += $(call CHECKCC,-mno-sse2,) +SHARED_FLAGS += $(call CHECKCC,-mno-sse3,) +SHARED_FLAGS += $(call CHECKCC,-mno-3dnow,) + +ASFLAGS += -m32 +OFORMAT := elf32-i386 +LD_EMULATION_CHOICE := elf_i386 elf_i386_fbsd diff --git a/kernel/fiasco/src/Makeconf.ppc32 b/kernel/fiasco/src/Makeconf.ppc32 new file mode 100644 index 00000000..1bcb6b91 --- /dev/null +++ b/kernel/fiasco/src/Makeconf.ppc32 @@ -0,0 +1,5 @@ +SYSTEM_TARGET ?= powerpc-linux- +LD_EMULATION_CHOICE := elf32ppc +SHARED_FLAGS += -m32 + +ASFLAGS += -m32 diff --git a/kernel/fiasco/src/Makeconf.sparc b/kernel/fiasco/src/Makeconf.sparc new file mode 100644 index 00000000..69de2bcf --- /dev/null +++ b/kernel/fiasco/src/Makeconf.sparc @@ -0,0 +1,2 @@ +SYSTEM_TARGET ?= sparc-elf- +LD_EMULATION_CHOICE := sparcleon diff --git a/kernel/fiasco/src/Makeconf.ux b/kernel/fiasco/src/Makeconf.ux new file mode 100644 index 00000000..58afa2e0 --- /dev/null +++ b/kernel/fiasco/src/Makeconf.ux @@ -0,0 +1,34 @@ +# -*- makefile -*- + +OPT_SHARED_FLAGS += $(call CHECKCC,-finline-limit=10000,) +OPT_CXXFLAGS += $(call CHECKCXX,--param large-function-insns=10000) +OPT_CFLAGS += $(call CHECKCC,--param large-function-insns=10000) + +# The -Os option of gcc-4.0 sets max-inline-insns-single to 5 which prevents +# inlining of almost every function +NOOPT_SHARED_FLAGS += $(call CHECKCC,--param max-inline-insns-single=50) +SHARED_FLAGS += -mpreferred-stack-boundary=2 -m32 + +L4STD_INCDIR := -include $(srcdir)/kern/ux/format.h +L4STD_INCDIR_LAST := +CPPFLAGS += -D_GNU_SOURCE + +SHARED_FLAGS-$(CONFIG_IA32_486) += -march=i486 +SHARED_FLAGS-$(CONFIG_IA32_586) += -march=i586 +SHARED_FLAGS-$(CONFIG_IA32_686) += -march=i686 +SHARED_FLAGS-$(CONFIG_IA32_P2) += $(call CHECKCC,-march=pentium2,-march=i686) +SHARED_FLAGS-$(CONFIG_IA32_P3) += $(call CHECKCC,-march=pentium3,-march=i686) +SHARED_FLAGS-$(CONFIG_IA32_P4) += $(call CHECKCC,-march=pentium4,-march=i686) +SHARED_FLAGS-$(CONFIG_IA32_K6) += $(call CHECKCC,-march=k6,-march=i586) +SHARED_FLAGS-$(CONFIG_IA32_K7) += $(call CHECKCC,-march=athlon,-march=i686) +SHARED_FLAGS-$(CONFIG_IA32_K8) += $(call CHECKCC,-march=k8,-march=i686) + +SHARED_FLAGS += $(call CHECKCC,-mno-mmx,) +SHARED_FLAGS += $(call CHECKCC,-mno-sse,) +SHARED_FLAGS += $(call CHECKCC,-mno-sse2,) +SHARED_FLAGS += $(call CHECKCC,-mno-sse3,) +SHARED_FLAGS += $(call CHECKCC,-mno-3dnow,) + +ASFLAGS += -m32 +OFORMAT := elf32-i386 +LD_EMULATION_CHOICE := elf_i386 elf_i386_fbsd diff --git a/kernel/fiasco/src/Makefile b/kernel/fiasco/src/Makefile new file mode 100644 index 00000000..b0497ddd --- /dev/null +++ b/kernel/fiasco/src/Makefile @@ -0,0 +1,246 @@ +srcdir ?= NOT_SET +tooldir := $(srcdir)/../tool + +CONFIG_BANNER_STRING ?= "Fiasco - prepare for world domination" + +.PHONY: all do-all test-all config textconfig menuconfig xconfig \ + oldconfig regenconfig mrproper doc help update nconfig + +all: + +help: + @echo "Possible targets are:" + @echo " menuconfig - configure Fiasco (ncurses mode)" + @echo " config - like menuconfig" + @echo " textconfig - line-oriented config" + @echo " xconfig - configure Fiasco (graphical mode)" + @echo " all - Fiasco binary" + @echo " clean - clear all auto-generated files in auto" + @echo " cleanall - like clean + dependencies" + @echo " mrproper - like cleanall + config files" + @echo " update - update Fiasco and preprocess using svn" + @echo " DEPS - dependencies between kernel object files" + @echo " DEPS.ps - graphical (ps) representation of DEPS" + @echo " DEPS.svg - graphical (svg) representation of DEPS" + @echo " DEPS.tred.ps - transitive reduction of DEPS.ps" + @echo " DEPS.tred.svg - transitive reduction of DEPS.svg" + @echo " doc - doxygen HTML documentation into docs/" + @echo " TAGS tags - create tags files" + + +ifneq ($(srcdir),NOT_SET) +Makefile: $(srcdir)/templates/Makefile.builddir.templ + perl -p -i -e '$$s = "$(srcdir)"; s/\@SRCDIR\@/$$s/' \ + < $< >$@ +endif + +ifneq ($(MAKECMDGOALS),help) + +ifeq ($(srcdir),NOT_SET) +all $(filter config %config,$(MAKECMDGOALS)): + @echo "======================================================================" + @echo " Building Fiasco in the src directory is not possible!" + @echo "" + @echo " Go to the Fiasco root directory and create your build directory with" + @echo " cd .. && make BUILDDIR=build-dir" + @echo "======================================================================" + @exit 1 + +else # srcdir != NOT_SET + +all: globalconfig.h + +ifeq ($(filter config %config,$(MAKECMDGOALS)),) + +-include globalconfig.out + +# use patsubst here to prevent confusion of syntax highlighting editors :-) +CONFIG_XARCH := $(patsubst "%",%,$(CONFIG_XARCH)) +CONFIG_ABI := $(patsubst "%",%,$(CONFIG_ABI)) + +ifeq ("$(CONFIG_XARCH)","") + +all: menuconfig + @echo "=========================================================" + @echo "Now run make again to build!" + @echo "=========================================================" + @exit 1 + +else # ! no XARCH +ifeq ("$(CONFIG_ABI)","") +all: + @echo "=========================================================" + @echo "ERROR: No ABI version set (run 'make menuconfig')!" + @echo "=========================================================" + @exit 1 +else # ! no ABI + +# +# At this point, globalconfig.out is up-to-date. Update Modules and +# .Modules.deps, then restart using Makefile.sub1, Makefile.sub2. +# + +# Read Make configuration +include $(srcdir)/Makeconf + +include $(MODULES_FILE) +MODULES_FILES += $(srcdir)/Modules.generic + +ifdef SUBSYSTEMS + _modules_read_ = true +endif + +ifdef _modules_read_ +GENERATED_MODULES = $(foreach subsys, $(SUBSYSTEMS), \ + $(INTERFACES_$(subsys))) +ALL = $(foreach subsys, $(SUBSYSTEMS), $($(subsys)) $($(subsys)_EXTRA)) + +$(foreach m, $(GENERATED_MODULES), auto/stamp-$(m).ready): $(MODULES_FILES) + +.PRECIOUS: .Modules.deps +.Modules.deps: $(MODULES_FILES) globalconfig.h + @mkdir -p auto + @echo "Creating $@" + @($(foreach mod, $(GENERATED_MODULES), \ + echo 'auto/stamp-$(mod).ready: \ + $(addsuffix .cpp,$(call eval_impl,$(mod)))'; \ + echo '$(patsubst %,auto/%.cc,$(call eval_impl,$(mod)))' \ + 'auto/$(mod).h auto/$(mod)_i.h: \ + auto/stamp-$(mod).ready ; \ + @[ -e $$@ ] || { $$(RM) $$<; $$(MAKE) $$<; }'; \ + )) > $@.new + @($(foreach subsys, $(SUBSYSTEMS), \ + echo 'IFDEPS += $(addprefix ., $(addsuffix .cc.d, \ + $(foreach in,$(INTERFACES_$(subsys)), \ + $(call eval_impl,$(in)))))' ; \ + echo 'CXXSRC_$(subsys) += $(addsuffix .cc, \ + $(foreach in,$(INTERFACES_$(subsys)), \ + $(call eval_impl,$(in))))'; \ + echo 'OBJ_$(subsys) += $$(CXXSRC_$(subsys):.cc=.o) \ + $$(CSRC_$(subsys):.c=.o) \ + $$(ASSRC_$(subsys):.S=.o)' ; ) ) >> $@.new + @echo "GENERATED_MODULES = $(GENERATED_MODULES)" >> $@.new + @echo "ALL = $(ALL)" >> $@.new + @echo "_modules_deps_read_ = true" >> $@.new + @mv $@.new $@ + +endif # _modules_read_ + +# +# Makefile.sub1: Create source files. +# + +.PHONY: create-sources +create-sources: $(MODULES_FILES) globalconfig.h .Modules.deps + $(MAKE) srcdir=$(srcdir) objbase=$(objbase) -f $(srcdir)/Makefile.sub1 +auto/stamp-%.ready: $(MODULES_FILES) globalconfig.h .Modules.deps + $(MAKE) srcdir=$(srcdir) objbase=$(objbase) -f $(srcdir)/Makefile.sub1 $@ + +DEPS_FILES=DEPS DEPS.a4 DEPS.tred + +# +# Makefile.sub2: Create everything else. +# +all doc $(addsuffix .ps,$(DEPS_FILES)) $(addsuffix .svg,$(DEPS_FILES)) TAGS tags: \ + $(MODULES_FILES) .Modules.deps create-sources globalconfig.h + $(MAKE) srcdir=$(srcdir) objbase=$(objbase) -f $(srcdir)/Makefile.sub2 $@ + +%.o %_t: $(MODULES_FILES) .Modules.deps create-sources globalconfig.h + $(MAKE) srcdir=$(srcdir) objbase=$(objbase) -f $(srcdir)/Makefile.sub2 $@ + +# Divert any target we do not explicitly mention in this Makefile to +# Makefile.sub2. (Unfortunately 1, this does not work for file +# targets that already exist in this directory. Unfortunately 2, +# .DEFAULT does not accept prerequisites, so we must "make +# create-sources" manually.) +.DEFAULT: + $(MAKE) create-sources + $(MAKE) srcdir=$(srcdir) objbase=$(objbase) -f $(srcdir)/Makefile.sub2 $@ + +# Well, we need to provide some empty rules for some targets to +# prevent the above catch-all from running amok. +Makerules.local $(srcdir)/Makeconf.local $(objbase)/Makeconf.local \ + $(objbase)/.Host-config: ; + +%: %.o # delete implicit rule + +endif # ! no ABI +endif # ! no XARCH +endif # ! config xconfig menuconfig oldconfig + +auto: + test -e auto || mkdir auto + +BSP_DIR := $(srcdir)/kern/arm/bsp $(srcdir)/kern/ppc32/bsp $(srcdir)/kern/sparc/bsp +KCONFIG_FILE := Kconfig +KCONFIG_SRC_FILE := $(srcdir)/Kconfig +KCONFIG_BSP_FILES := $(shell find $(BSP_DIR) -name Kconfig -follow -print) + +kconfig_call = $(MAKE) -C $(tooldir)/kconfig O=$(objbase) \ + Kconfig=$(KCONFIG_FILE) \ + KCONFIG_AUTOHEADER=globalconfig.h \ + KCONFIG_TRISTATE=config/tristate.conf \ + KCONFIG_CONFIG=globalconfig.out \ + KCONFIG_AUTOCONFIG=config/auto.conf \ + KERNELVERSION=SVN MENUCONFIG_COLOR=blackbg \ + INCLUDE_PPC32=$(INCLUDE_PPC32) \ + INCLUDE_SPARC=$(INCLUDE_SPARC) \ + fiasco_srcdir=$(srcdir)/.. + +$(KCONFIG_FILE): $(KCONFIG_SRC_FILE) $(KCONFIG_BSP_FILES) $(srcdir)/Makefile + @$(tooldir)/gen_kconfig $(KCONFIG_SRC_FILE) $(KCONFIG_FILE) $(KCONFIG_BSP_FILES) + +globalconfig.out: $(KCONFIG_FILE) + +$(kconfig_call) oldconfig + +globalconfig.h: globalconfig.out + +$(kconfig_call) silentoldconfig + +config: $(KCONFIG_FILE) + +$(kconfig_call) menuconfig silentoldconfig + +textconfig: $(KCONFIG_FILE) + +$(kconfig_call) config silentoldconfig + +menuconfig oldconfig xconfig gconfig nconfig randconfig allyesconfig allnoconfig: $(KCONFIG_FILE) + +$(kconfig_call) $@ silentoldconfig + +ifneq ($(filter clean cleanall mrproper,$(MAKECMDGOALS)),) + +# Try to suck in clean targets from subsystems' Makefile fragments +ifdef _modules_read_ +MAKERULES_SUBSYS = $(foreach subsys, $(SUBSYSTEMS), $(firstword $(wildcard $(addsuffix /Makerules.$(subsys),$(addprefix $(srcdir)/,$(VPATH)) $(srcdir))))) +-include $(MAKERULES_SUBSYS) +endif + +.DEFAULT: + +.PHONY: clean cleanall mrproper \ + $(foreach subsys, $(SUBSYSTEMS), clean-$(subsys)) \ + $(foreach subsys, $(SUBSYSTEMS), cleanall-$(subsys)) + +clean: $(foreach subsys, $(SUBSYSTEMS), clean-$(subsys)) + $(RM) $(ALL) + $(RM) *.o fiasco + $(RM) auto/*.cc auto/*.h auto/*.S auto/stamp-*.ready + $(RM) .Clean-auto .Compiler-config + +cleanall: clean $(foreach subsys, $(SUBSYSTEMS), cleanall-$(subsys)) + $(foreach subdir, $(SUBDIRS), $(RM) $(subdir)/{.,}*.d) + $(RM) {.,}*.d {.,}*.d.new *~ globalconfig.{h,h.old} Circular + $(RM) .Modules.deps + +mrproper: cleanall + $(RM_R) globalconfig.out Modules.* DEPS* + $(RM_R) auto docs config scripts + +endif # clean, cleanall, mrproper + +update: + cd $(srcdir)/.. && svn update + cd $(dir $(PREPROCESS))/.. && svn update + +endif # srcdir != NOT_SET + +endif # MAKECMDGOALS != help + diff --git a/kernel/fiasco/src/Makefile.sub1 b/kernel/fiasco/src/Makefile.sub1 new file mode 100644 index 00000000..97d0928a --- /dev/null +++ b/kernel/fiasco/src/Makefile.sub1 @@ -0,0 +1,118 @@ +# -*- makefile -*- + +# Targets in this Makefile: +# - all: Create C++ sources from Preprocess input +# +# This Makefile is invoked in a sub-Make from the top-level Makefile +# (via Makerules.global) when globalconfig.out, Modules and +# .Modules.deps are up-to-date. + +all: do-all + +BUILD_SOURCES=true + +include $(srcdir)/Makeconf # also reads srcdir/Makeconf.local + # and objdir/Makeconf.local +include $(MODULES_FILE) +include .Modules.deps + +include $(srcdir)/Makerules.global # also reads objdir/Makerules.local + +# Read subsystem Makefile fragments. We do not explicity use any +# targets of these fragments in this Makefile, but this include allows +# subsystem Makefile fragments to implicitly create more Makefile +# fragments. +include $(MAKERULES_SUBSYS) + +ALL_STAMPS = $(foreach m, $(GENERATED_MODULES), auto/stamp-$(m).ready) + +.PHONY: do-all +do-all: $(ALL_STAMPS) + +# +# Auto-created source files +# + +.Clean-auto: $(MODULES_FILES) .Modules.deps globalconfig.out + rm -f \ + $(filter-out \ + $(addprefix auto/, \ + $(addsuffix .cc, \ + $(foreach mod, $(GENERATED_MODULES), $(call eval_impl,$(mod)))) \ + $(foreach mod, $(GENERATED_MODULES), \ + $(mod).h $(mod)_i.h stamp-$(mod).ready)), \ + $(wildcard auto/*)) + touch $@ + +define find_ld_emulation + emulations=$$(LANG= $(LD) --help | \ + grep -i "supported emulations:" | \ + sed -e 's/.*supported emulations: //') ; \ + unset found_it; \ + for e in $$emulations; do \ + for c in $(2); do \ + if [ "$$e" = "$$c" ]; then \ + echo LD_EMULATION = $$e >> $(1); \ + found_it=1; \ + break; \ + fi; \ + done; \ + done; \ + if [ "$$found_it" != "1" ]; then \ + echo "No known ld emulation found"; exit 1; \ + fi +endef + +# Force that rule to ensure that compiler changes caused by make command line +# or system-wide compiler updates are noticed. +# Do not use .PHONY, because preprocess would then be triggered everytime. +.Compiler-config: force-the-rule + @echo -n "Checking compiler config... " + @echo "CC = $(CC)" > $@.new + @echo "CXX = $(CXX)" >> $@.new + @echo "CPPFLAGS = $(CPPFLAGS)" >> $@.new + @echo "CFLAGS = $(CFLAGS)" >> $@.new + @echo "CXXFLAGS = $(CXXFLAGS)" >> $@.new + @echo "OPT_CFLAGS = $(OPT_CFLAGS)" >> $@.new + @echo "OPT_CXXFLAGS = $(OPT_CXXFLAGS)" >> $@.new + @echo "ASFLAGS = $(ASFLAGS)" >> $@.new + @echo "CONFIG_XARCH = $(CONFIG_XARCH)" >> $@.new +# If the compiler configuration has changed, remove all dependency +# files -- they have just become useless. + @$(MOVE_IF_CHANGE) $@.new $@ \ + && { $(RM) .*.d */.*.d; echo "CHANGED. Recompiling."; } \ + || echo "unchanged." + +.Host-config: force-the-rule + @$(call find_ld_emulation,$@.new,$(LD_EMULATION_CHOICE)) + @$(MOVE_IF_CHANGE) $@.new $@ || true + +force-the-rule: ; + +$(ALL_STAMPS): $(MODULES_FILES) .Modules.deps globalconfig.out \ + .Clean-auto .Compiler-config .Host-config + +# Basename of implementation files = Basename of first .cpp file +impl_name = $(basename $(firstword $(subst -, ,\ + $(firstword $(filter %.cpp, $(notdir $(1))))))) + +$(ALL_STAMPS): auto/stamp-%.ready: + $(PREP_MESSAGE) + @test -e auto || mkdir auto + $(VERBOSE)$(PREPROCESS) \ + $(PREPROCESS_FLAGS) \ + $(if $(filter $(call impl_name,$^),$(ALWAYS_INLINE)),-i,) \ + -p auto/new_ \ + -e "$(PREPROCESS_PARTS)" -s \ + -h $* -c $(call impl_name,$^) $(filter %.cpp, $^) + @for i in $*.h $(call impl_name,$^)_i.h \ + $(patsubst %.cpp, %.cc, $(filter %.cpp, $(notdir $^))); \ + do \ + $(MOVE_IF_CHANGE) auto/new_$$i auto/$$i || true; \ + done + $(OK_MESSAGE) + $(VERBOSE)touch $@ + +.PRECIOUS: auto/stamp-%.ready +.PRECIOUS: %.cc %.h %_i.h + diff --git a/kernel/fiasco/src/Makefile.sub2 b/kernel/fiasco/src/Makefile.sub2 new file mode 100644 index 00000000..becf5772 --- /dev/null +++ b/kernel/fiasco/src/Makefile.sub2 @@ -0,0 +1,261 @@ +# -*- makefile -*- + +# Targets in this Makefile: +# - all: Run all subsystems' "all" targets +# - doc: Create doxygen documentation in directory "docs" +# - DEPS, DEPS.ps, DEPS.a4.ps, DEPS.tred.ps: +# Create dependency graphs +# - TAGS, tags: +# Create editor tags +# This Makefile is invoked in a sub-Make from the top-level Makefile +# when globalconfig.out, Modules and .Modules.deps are up-to-date and +# all `preprocess'd C++ source files have been created. + +all: do-all + $(VERBOSE)echo " --> Build-Nr: $$(cat .build_nr)" + +BUILD_OBJECTS=true + +include $(srcdir)/Makeconf # also reads srcdir/Makeconf.local + # and objdir/Makeconf.local +include $(MODULES_FILE) +include .Modules.deps + +# Compute sets of sources. From these variables, Makeconf computes +# $(DEPS) and $(SRC_ALL). Set them before including Makerules.global. +SRC_S = $(foreach subsys, $(SUBSYSTEMS), $(ASSRC_$(subsys))) +SRC_C = $(foreach subsys, $(SUBSYSTEMS), $(CSRC_$(subsys))) +SRC_CC = $(foreach subsys, $(SUBSYSTEMS), $(CXXSRC_$(subsys))) + +include $(srcdir)/Makerules.global # also reads objdir/Makerules.local + +include $(MAKERULES_SUBSYS) +-include $(DEPS) + +# Recompile everything if the compiler configuration has changed. +OBJS = $(foreach subsys, $(SUBSYSTEMS), $(OBJ_$(subsys))) +$(OBJS): .Compiler-config + +# +# Subsystem-specific rules and targets +# + +ifeq ("$(CONFIG_MAINTAINER_MODE)","y") + +do-all: Checkinitcalls Circular-ok ToDoItems compilertest $(ALL) +ifeq ($(CONFIG_XARCH),ux) +# disabled until unittests fixed +#do-all: unittest +endif # UX + +else # ! maintainer mode + +do-all: compilertest $(ALL) + +endif # ! maintainer mode + +ifeq ($(CC_TYPE),gcc) +ifneq ($(findstring $(CCVER_MAJOR),4 5 6 7),) + ifeq ($(CCVER_MAJOR),4) + ifeq ($(findstring $(CCVER_MINOR), 0 1 2 3),) + CC_OK := 1 + endif + else + CC_OK := 1 + endif +endif + CC_OK := 1 +endif + +compilertest: +ifeq ($(CC_TYPE),gcc) +ifeq ($(CC_OK),) + @$(ECHO_E) "\033[31m\n" \ + " ERROR: gcc version "$(CCVER_MAJOR).$(CCVER_MINOR)" is not supported for "\ + "Fiasco -- \n"\ + " please update gcc to at least version 4.4.\033[m\n"; exit -1 +endif +endif +ifeq ($(CC_TYPE),gcc) +ifeq ($(CC_OK),) + @$(ECHO_E) "\033[31m\n" \ + " ERROR: clang version "$(CCVER_MAJOR).$(CCVER_MINOR)" is not supported for "\ + "Fiasco -- \n"\ + " please update clang to at least version ?.?.\033[m\n"; exit -1 +endif +endif + +Checkinitcalls: $(KERNEL) $(OBJ_KERNEL) +ifneq ($(shell $(CXX) -dumpversion | cut -d . -f1-2),3.4) + @echo "Checking initcalls" + $(VERBOSE)$(srcdir)/../tool/checkinitcalls \ + -k fiasco.image \ + -Werror $(filter-out fiasco.image, $^) \ + $(if $(SYSTEM_TARGET),-t $(SYSTEM_TARGET)) && \ + echo "Initcalls OK" +else + @echo "Initcall check disabled due to gcc-3.4" +endif + +ToDoItems: + @files=$$(cd $(srcdir) && \ + find . -type f -name '*.cpp' -o -name '*.cc' -o \ + -name '*.h' -o -name '*.S' -o -name '*.h'); \ + fixme=$$(cd $(srcdir) && cat $$files | grep -wc FIXME); \ + XXX=$$(cd $(srcdir) && cat $$files | grep -wc XXX); \ + if [ "$$fixme" -ne "0" -o "$$XXX" -ne "0" ]; then \ + echo "Found $$fixme times 'FIXME' and $$XXX times 'XXX'"; \ + fi + +doc: docs/stamp-doc.ready + +docs/stamp-doc.ready: $(foreach m, $(GENERATED_MODULES), auto/stamp-$(m).ready) + @mkdir -p docs + @touch $@ + @doxygen $(srcdir)/doxygen.conf + +### + +# Make function "makedeps": Creates (on stdout) a list of Make-like +# dependencies in a format suitable for $(SHOWDEPS). Expects a list +# of source (BASE-suffix.{cpp,cc,c}, BASE[_i].h) files as input and extracts +# include directives from them. Dependecies contain only basenames of +# files (up to the first "-"). Suffixes and extensions are stripped. +makedeps= implname () { echo $$1 | sed 's|.*/||; s|_i\.h|.h|; s|[.-].*||;'; };\ + for i in $(1); \ + do \ + echo $$(implname $$i): $$(perl -n -e \ + '/^\s*\#include\s+["<](.*).h[">]/ && print "$$1 "; next;' \ + $$i); \ + done + +DEPS: $(SRC_ALL) $(foreach idir, $(PRIVATE_INCDIR), $(wildcard $(idir)/*.h)) + $(call makedeps, $^) | $(SHOWDEPS) > $@.new + mv $@.new $@ + +# Graphical version of DEPS dependency graph. + +# XXX DEPS.{dot,ps} only contain dependency graphs for the KERNEL and +# LIBK subsystem. Also, we remove a number of top-level and low-level +# modules from the resulting graph to reduce the overwhelming number +# of edges; however, `gendotdeps' ensures that modules participating +# in circular dependencies are never removed. + +GENDOT_FLAGS ?= -t1u1 + +KERNEL_MODULES_CPP = $(foreach mod, $(INTERFACES_KERNEL) $(INTERFACES_LIBK), \ + $(addsuffix .cpp,$(call eval_impl,$(mod)))) \ + $(foreach idir, $(srcdir)/kern $(srcdir)/kern/shared \ + $(srcdir)/kern/$(CONFIG_XARCH), \ + $(wildcard $(idir)/*.h)) + +ifeq ($(CONFIG_XARCH),ux) +EXTRA_INCLUDES = -I/usr/include/c++/$(shell $(CXX) -dumpversion) -I/usr/include +endif + +DEPS.dot: $(KERNEL_MODULES_CPP) + @echo -n > source_files.mkdeps + @for f in $^ ; do \ + echo $$f >> source_files.mkdeps ; \ + done + $(srcdir)/../tool/gendotdeps \ + -E "$(PREPROCESS_PARTS)" $(addprefix -I,$(PRIVATE_INCDIR)) \ + $(EXTRA_INCLUDES) $(addprefix --vpath=,$(VPATH)) $(GENDOT_FLAGS) \ + -v -b $(srcdir)/DEPS.blacklist source_files.mkdeps -o $@ || $(RM) $@ + @$(RM) source_files.mkdeps + +%.ps: %.dot + dot -Tps -Gmclimit=200.0 -Gnslimit=500.0 \ + -Gsize=11,10 -Grotate=90 -o $@ $< + +%.a4.ps: %.dot + dot -Tps -Gmclimit=200.0 -Gnslimit=500.0 \ + -Gsize="11,8" -Granksep=0.7 -Grotate=90 -o $@ $< + +%.tred.ps: %.dot + tred $< | dot -Tps -Gmclimit=200.0 -Gnslimit=500.0 \ + -Gsize="11,8" -Granksep=0.7 -Grotate=90 -o $@ + +%.svg: %.dot + dot -Tsvg -Gmclimit=200.0 -Gnslimit=500.0 \ + -Gsize=11,10 -Grotate=90 -o $@ $< + +%.a4.svg: %.dot + dot -Tsvg -Gmclimit=200.0 -Gnslimit=500.0 \ + -Gsize="11,8" -Granksep=0.7 -Grotate=90 -o $@ $< + +%.tred.svg: %.dot + tred $< | dot -Tsvg -Gmclimit=200.0 -Gnslimit=500.0 \ + -Gsize="11,8" -Granksep=0.7 -Grotate=90 -o $@ + + +### + +# Circular should really be dependent on $(DEPS). However, we cannot +# enforce that all $(DEPS) are made before this target, because the +# Makefile contains "-include $(DEPS)" (which can result in Circular +# being created/updated before all $(DEPS) are). Therefore, depend on +# the fiasco.image and on main (not with Fiasco-UX). Once this is made, +# we know all $(DEPS) have been updated. +Circular: $(KERNEL) $(BOOT) $(RUN_TESTS) $(CHECKSUM) + @echo "Creating $@" + @( \ + echo 'Do "make DEPS" for full fine-grained dependency information.';\ + for i in $(DEPS); \ + do \ + $(PREPROCESSDEPS) $$i; \ + done | $(SHOWDEPS) | $(CIRCULAR) \ + ) > $@.new + @mv $@.new $@ + +# Create a Circular.max file for the first time. Usually this target +# is not needed -- there should be a Circular.max file in the CVS. +$(srcdir)/Circular.max.$(CONFIG_XARCH): +# Circular is not in the dependencies because we do not want a new +# copy of Circular.max every time Circular changes. We nevertheless +# need it to so the copy -- so create it explicitly + $(MAKE) -f $(srcdir)/Makefile.sub2 Circular + cp Circular $@ + +# Check that the number of circular dependency has not increased in +# this build. +.PHONY: Circular-ok +Circular-ok: $(srcdir)/Circular.max.$(CONFIG_XARCH) Circular +# Circular.max.* must be the first dependency: We are going to +# reference it as $<. + @ max=$$(tail -1 $<); \ + current=$$(tail -1 Circular); \ + if [ $$current -gt $$max ]; \ + then \ + echo "Number of circular dependencies increased!"; \ + diff -up $< Circular; \ + exit 1; \ + fi; \ + echo "Circular-dependency check OK ($$current <= $$max)" + +### + +.PHONY: TAGS tags + +# Find directories for source and header files. There may be +# duplicates, so weed out the list using a tiny Perl script. +define source-files + ( find $(shell perl -e ' \ + %seen = (); \ + foreach $$i (@ARGV) { \ + next if ! -e $$i || $$i eq "."; \ + next if defined $$seen{$$i}; \ + $$seen{$$i} = 1; \ + print "$$i "; \ + }' $(filter-out auto, $(VPATH) $(PRIVATE_INCDIR))) \ + -maxdepth 1 -type f -name '*.cpp' -o -name '*.h' \ + -o -name '*.cc' -o -name '*.c' ) +endef + +TAGS: + $(source-files) | etags --members --language=c++ - + +tags: + $(source-files) | ctags --members --language=c++ -d -w -T - + + diff --git a/kernel/fiasco/src/Makerules.ABI b/kernel/fiasco/src/Makerules.ABI new file mode 100644 index 00000000..7d00e4bd --- /dev/null +++ b/kernel/fiasco/src/Makerules.ABI @@ -0,0 +1,8 @@ +# -*- makefile -*- + +$(ABI): $(OBJ_ABI) + $(AR_MESSAGE) + $(VERBOSE)$(RM) $@ + $(VERBOSE)$(AR) $(ARFLAGS) $@ $^ + + diff --git a/kernel/fiasco/src/Makerules.BOOT b/kernel/fiasco/src/Makerules.BOOT new file mode 100644 index 00000000..c6cd39c3 --- /dev/null +++ b/kernel/fiasco/src/Makerules.BOOT @@ -0,0 +1,13 @@ +# -*- makefile -*- +# Boot Makefile + +# Add future prerequisites somewhere among the list of libraries. +# You really should not have to add anything in the $(LD) line. + +include $(srcdir)/boot/$(CONFIG_XARCH)/Makerules.BOOT.$(CONFIG_XARCH) + +clean-BOOT: + rm -f kernel kernel.o + +cleanall-BOOT: + rm -f fiasco diff --git a/kernel/fiasco/src/Makerules.CHECKSUM b/kernel/fiasco/src/Makerules.CHECKSUM new file mode 100644 index 00000000..2b3ede83 --- /dev/null +++ b/kernel/fiasco/src/Makerules.CHECKSUM @@ -0,0 +1,40 @@ +# -*- makefile -*- + + +checksum.ro: genchecksum $(KERNEL) $(BOOT) + $(CHKSUM_MESSAGE)"$(BOOT) text section" + $(VERBOSE)$(OBJDUMP) \ + --start-address=0x`$(NM) $(KERNEL) | $(GREP) -w _start | cut -f1 -d' '` \ + --stop-address=0x`$(NM) $(KERNEL) | $(GREP) -w _etext | cut -f1 -d' '` \ + -s $(BOOT) | cut -f3,4,5,6 -d' ' | ./genchecksum > $@ + +checksum.rw: genchecksum $(KERNEL) $(BOOT) + $(CHKSUM_MESSAGE)"$(BOOT) data section" + $(VERBOSE)$(OBJDUMP) \ + --start-address=0x`$(NM) $(KERNEL) | $(GREP) -w _kernel_data_start | cut -f1 -d' '` \ + --stop-address=0x`$(NM) $(KERNEL) | $(GREP) -w _edata | cut -f1 -d' '` \ + -s $(BOOT) | cut -f3,4,5,6 -d' ' | ./genchecksum > $@ + +$(CHECKSUM): checksum.ro checksum.rw setchecksum $(BOOT) + $(PATCH_MESSAGE)"$(BOOT)" + $(VERBOSE)./setchecksum $(BOOT) \ + "0x$(shell cat checksum.ro)" \ + "0x$(shell cat checksum.rw)" && echo done >$@ + $(call INSTALLFILE_RULE,fiasco,fiasco) + +setchecksum: setchecksum.c + $(COMP_MESSAGE) + $(VERBOSE)$(HOST_CC) -O2 -Wall $(HOST_CPPFLAGS) $(HOST_CFLAGS) -o $@ $^ + +genchecksum: $(OBJ_CHECKSUM) + $(LINK_MESSAGE) + $(VERBOSE)$(HOST_CXX) -fno-rtti -fno-exceptions $(HOST_CPPFLAGS) $(HOST_CXXFLAGS) -o $@ $^ + +$(OBJ_CHECKSUM): %.o: %.cc + $(COMP_MESSAGE) + $(VERBOSE)$(HOST_CXX) -fno-rtti -fno-exceptions -c -MD -MP -MF .$*.cc.d.new -O2 $(HOST_CPPFLAGS) $(HOST_CXXFLAGS) $< -o $@ + @mv .$*.cc.d.new .$*.cc.d + +clean-CHECKSUM: + rm -f genchecksum setchecksum checksum.ro checksum.rw + diff --git a/kernel/fiasco/src/Makerules.CRT0 b/kernel/fiasco/src/Makerules.CRT0 new file mode 100644 index 00000000..052650d5 --- /dev/null +++ b/kernel/fiasco/src/Makerules.CRT0 @@ -0,0 +1,5 @@ +# -*- makefile -*- + +# No special rules -- crt0.o can be build using implicit rules. + +clean-CRT0: diff --git a/kernel/fiasco/src/Makerules.CXXLIB b/kernel/fiasco/src/Makerules.CXXLIB new file mode 100644 index 00000000..6be6fe2b --- /dev/null +++ b/kernel/fiasco/src/Makerules.CXXLIB @@ -0,0 +1,7 @@ +# -*- makefile -*- + +$(CXXLIB): $(OBJ_CXXLIB) + $(AR_MESSAGE) + $(VERBOSE)$(RM) $@ + $(VERBOSE)$(AR) $(ARFLAGS) $@ $^ + diff --git a/kernel/fiasco/src/Makerules.DRIVERS b/kernel/fiasco/src/Makerules.DRIVERS new file mode 100644 index 00000000..7c229b29 --- /dev/null +++ b/kernel/fiasco/src/Makerules.DRIVERS @@ -0,0 +1,17 @@ +# -*- makefile -*- + +#$(DRIVERS): $(OBJ_DRIVERS) +# $(AR_MESSAGE) +# $(VERBOSE)$(RM) $@ +# $(VERBOSE)$(AR) $(ARFLAGS) $@ $? + +libdrivers.a: $(filter-out glue%.o, $(OBJ_DRIVERS)) + $(AR_MESSAGE) + $(VERBOSE)$(RM) $@ + $(VERBOSE)$(AR) $(ARFLAGS) $@ $^ + +libgluedriverslibc.a: $(filter glue%.o, $(OBJ_DRIVERS)) + $(AR_MESSAGE) + $(VERBOSE)$(RM) $@ + $(VERBOSE)$(AR) $(ARFLAGS) $@ $^ + diff --git a/kernel/fiasco/src/Makerules.GBLCFG b/kernel/fiasco/src/Makerules.GBLCFG new file mode 100644 index 00000000..d779dab3 --- /dev/null +++ b/kernel/fiasco/src/Makerules.GBLCFG @@ -0,0 +1,19 @@ +# -*- makefile -*- + +# 'date -r' doesn't work on BSDs, so we use stat there +filedate = $(shell if date --version 2>&1 | grep -q "Free Software F"; then \ + date -R -r $(1); \ + else \ + stat -f '%Sm' $(1); \ + fi) + +$(GBLCFG): globalconfig.out + $(VERBOSE)$(GREP) "CONFIG_.*=[^n].*$$" globalconfig.out | cut -f2- -d'_' > $@.txt + $(VERBOSE)echo "$(call filedate,globalconfig.out)" >> $@.txt + $(VERBOSE)$(LD) -m $(LD_EMULATION) -r --oformat $(OFORMAT) \ + -b binary -o $@ $@.txt + $(VERBOSE)$(RM) $@.txt + +clean-GBLCFG: + rm -f $(GBLCFG) + diff --git a/kernel/fiasco/src/Makerules.JABI b/kernel/fiasco/src/Makerules.JABI new file mode 100644 index 00000000..1fdffd97 --- /dev/null +++ b/kernel/fiasco/src/Makerules.JABI @@ -0,0 +1,7 @@ +# -*- makefile -*- + +$(JABI): $(OBJ_JABI) + $(AR_MESSAGE) + $(VERBOSE)$(RM) $@ + $(VERBOSE)$(AR) $(ARFLAGS) $@ $^ + diff --git a/kernel/fiasco/src/Makerules.JDB b/kernel/fiasco/src/Makerules.JDB new file mode 100644 index 00000000..99007993 --- /dev/null +++ b/kernel/fiasco/src/Makerules.JDB @@ -0,0 +1,10 @@ + + +$(JDB): $(OBJ_JDB) .$(JDB).deps + $(AR_MESSAGE) + $(VERBOSE)$(LD) -T/dev/null -m $(LD_EMULATION) -r -o $@ $(OBJ_JDB) + +.$(JDB).deps: FORCE + $(VERBOSE)echo $(OBJ_JDB) > $@.new + $(VERBOSE)$(MOVE_IF_CHANGE) $@.new $@ || true + diff --git a/kernel/fiasco/src/Makerules.LIBDISASM b/kernel/fiasco/src/Makerules.LIBDISASM new file mode 100644 index 00000000..71fb74e9 --- /dev/null +++ b/kernel/fiasco/src/Makerules.LIBDISASM @@ -0,0 +1,7 @@ +# -*- makefile -*- + +$(LIBDISASM): $(OBJ_LIBDISASM) + $(AR_MESSAGE) + $(VERBOSE)$(RM) $@ + $(VERBOSE)$(AR) $(ARFLAGS) $@ $^ + diff --git a/kernel/fiasco/src/Makerules.LIBGZIP b/kernel/fiasco/src/Makerules.LIBGZIP new file mode 100644 index 00000000..e317f3fc --- /dev/null +++ b/kernel/fiasco/src/Makerules.LIBGZIP @@ -0,0 +1,7 @@ +# -*- makefile -*- + +$(LIBGZIP): $(OBJ_LIBGZIP) + $(AR_MESSAGE) + $(VERBOSE)$(RM) $@ + $(VERBOSE)$(AR) $(ARFLAGS) $@ $^ + diff --git a/kernel/fiasco/src/Makerules.LIBK b/kernel/fiasco/src/Makerules.LIBK new file mode 100644 index 00000000..a30252e1 --- /dev/null +++ b/kernel/fiasco/src/Makerules.LIBK @@ -0,0 +1,12 @@ +# -*- makefile -*- + +# Kernel library: stuff which is linked in optionally. This includes +# everything in the lib subdirectory, but may also include optional +# kernel subsystems which may be optimized away + +$(LIBK): $(OBJ_LIBK) + $(AR_MESSAGE) + $(VERBOSE)$(RM) $@ + $(VERBOSE)$(AR) $(ARFLAGS) $@ $^ + +clean-LIBK: diff --git a/kernel/fiasco/src/Makerules.LIBKERN b/kernel/fiasco/src/Makerules.LIBKERN new file mode 100644 index 00000000..ef3d9927 --- /dev/null +++ b/kernel/fiasco/src/Makerules.LIBKERN @@ -0,0 +1,7 @@ +# -*- makefile -*- + +$(LIBKERN): $(OBJ_LIBKERN) + $(AR_MESSAGE) + $(VERBOSE)$(RM) $@ + $(VERBOSE)$(AR) $(ARFLAGS) $@ $^ + diff --git a/kernel/fiasco/src/Makerules.LIBPERFCTR b/kernel/fiasco/src/Makerules.LIBPERFCTR new file mode 100644 index 00000000..67ceb608 --- /dev/null +++ b/kernel/fiasco/src/Makerules.LIBPERFCTR @@ -0,0 +1,7 @@ +# -*- makefile -*- + +$(LIBPERFCTR): $(OBJ_LIBPERFCTR) + $(AR_MESSAGE) + $(VERBOSE)$(RM) $@ + $(VERBOSE)$(AR) $(ARFLAGS) $@ $^ + diff --git a/kernel/fiasco/src/Makerules.LIBREGEX b/kernel/fiasco/src/Makerules.LIBREGEX new file mode 100644 index 00000000..93d1db97 --- /dev/null +++ b/kernel/fiasco/src/Makerules.LIBREGEX @@ -0,0 +1,7 @@ +# -*- makefile -*- + +$(LIBREGEX): $(OBJ_LIBREGEX) + $(AR_MESSAGE) + $(VERBOSE)$(RM) $@ + $(VERBOSE)$(AR) $(ARFLAGS) $@ $^ + diff --git a/kernel/fiasco/src/Makerules.LIBUART b/kernel/fiasco/src/Makerules.LIBUART new file mode 100644 index 00000000..c4623242 --- /dev/null +++ b/kernel/fiasco/src/Makerules.LIBUART @@ -0,0 +1,19 @@ +# vim:set ft=make: + +rel2abs = $(foreach f, $(1),$(shell cd $(f); pwd)) + +LIBUART_srcdir := $(strip $(call rel2abs, $(srcdir))) +LIBUART_VPATH_abs := $(call rel2abs, $(VPATH_LIBUART)) + +$(LIBUART): FORCE + $(VERBOSE)if [ -e $(dir $@) ]; then true; else mkdir -p $(dir $@); fi + $(MAKE_MESSAGE) + $(VERBOSE)$(MAKE) -C uart \ + -f $(LIBUART_srcdir)/lib/uart/Makefile \ + srcdir=$(LIBUART_srcdir) \ + objbase=$(objbase) \ + VERBOSE="$(VERBOSE)" \ + OBJECTS="$(OBJECTS_LIBUART)" \ + TARGET="$(LIBUART)" \ + VPATH_LIBUART="$(LIBUART_VPATH_abs)" \ + PRIVATE_INCDIR="$(LIBUART_srcdir)/lib/uart $(PRIVATE_INCDIR)" diff --git a/kernel/fiasco/src/Makerules.LINES b/kernel/fiasco/src/Makerules.LINES new file mode 100644 index 00000000..2afd735b --- /dev/null +++ b/kernel/fiasco/src/Makerules.LINES @@ -0,0 +1,15 @@ +# -*- makefile -*- + +$(LINES): $(PROG_LINES) $(KERNEL) + $(COMP_MESSAGE) + $(VERBOSE)./$< $(KERNEL) > $@.new || true + $(VERBOSE)mv $@.new $@ + $(VERBOSE)chmod 644 $@ + $(call INSTALLFILE_RULE,$@,fiasco_lines) + +$(PROG_LINES): genlines.c + $(LINK_MESSAGE) + $(VERBOSE)$(HOST_CC) -O2 -Wall $(HOST_CPPFLAGS) $(HOST_CXXFLAGS) -o $@ $^ + +clean-LINES: + rm -f $(LINES) $(PROG_LINES) diff --git a/kernel/fiasco/src/Makerules.MINILIBC b/kernel/fiasco/src/Makerules.MINILIBC new file mode 100644 index 00000000..236b29c7 --- /dev/null +++ b/kernel/fiasco/src/Makerules.MINILIBC @@ -0,0 +1,7 @@ +# -*- makefile -*- + +$(MINILIBC): $(OBJ_MINILIBC) + $(AR_MESSAGE) + $(VERBOSE)$(RM) $@ + $(VERBOSE)$(AR) $(ARFLAGS) $@ $^ + diff --git a/kernel/fiasco/src/Makerules.SYMBOLS b/kernel/fiasco/src/Makerules.SYMBOLS new file mode 100644 index 00000000..5717b5e1 --- /dev/null +++ b/kernel/fiasco/src/Makerules.SYMBOLS @@ -0,0 +1,3 @@ +# -*- makefile -*- + +include $(srcdir)/kern/$(CONFIG_XARCH)/Makerules.SYMBOLS.$(CONFIG_XARCH) diff --git a/kernel/fiasco/src/Makerules.TCBOFFSET b/kernel/fiasco/src/Makerules.TCBOFFSET new file mode 100644 index 00000000..b7af9289 --- /dev/null +++ b/kernel/fiasco/src/Makerules.TCBOFFSET @@ -0,0 +1,20 @@ +# -*- makefile -*- + +$(TCBOFFSET): dump_tcboffsets tcboffset.bin + ./$< tcboffset.bin > $@.new + mv $@.new $@ + +dump_tcboffsets: dump_tcboffsets.cc tcboffset_in.h globalconfig.h .Compiler-config + $(COMP_MESSAGE) + $(VERBOSE)$(HOST_CXX) -MD -MP -MF .$@.cc.d.new -Wall -W -I . $(HOST_CPPFLAGS) $(HOST_CXXFLAGS) -o $@ $< + @mv .$@.cc.d.new .$@.cc.d + +tcboffset.o: tcboffset_in.h + +tcboffset.bin: tcboffset.o + $(LINK_MESSAGE) + $(VERBOSE)$(OBJCOPY) -j .e_length -j .offsets --adjust-section-vma .offsets=32 -Obinary $< $@ + + +clean-TCBOFFSET: + rm -f tcboffset.o tcboffset.bin $(TCBOFFSET) dump_tcboffsets diff --git a/kernel/fiasco/src/Makerules.TYPES b/kernel/fiasco/src/Makerules.TYPES new file mode 100644 index 00000000..c209d219 --- /dev/null +++ b/kernel/fiasco/src/Makerules.TYPES @@ -0,0 +1,8 @@ +# -*- makefile -*- + +$(TYPES): $(OBJ_TYPES) + $(AR_MESSAGE) + $(VERBOSE)$(RM) $@ + $(VERBOSE)$(AR) $(ARFLAGS) $@ $^ + + diff --git a/kernel/fiasco/src/Makerules.UNITTEST b/kernel/fiasco/src/Makerules.UNITTEST new file mode 100644 index 00000000..d6ce5b0a --- /dev/null +++ b/kernel/fiasco/src/Makerules.UNITTEST @@ -0,0 +1,116 @@ +# -*- makefile -*- + +# Unit tests for the KERN subsystem + +UNITTEST = unittest + +ALL_TESTS = $(INTERFACES_UNITTEST) +RUN_TESTS = $(addsuffix .ok, $(ALL_TESTS)) + +.PHONY: unittest +unittest: $(RUN_TESTS) + +# +# Dependency calculation. WARNING: Black Art [tm]. +# Algorithm: For each module M: +# - Include everything mentioned in the INTERFACES_KERNEL before M +# - Optimization: Sibling weed-out: Remove all modules mentioned +# directly before M that M does not #include +# - Find object files comprising these modules +# - Finally, add objects comprising module M_t, and all libraries +# subsystem KERNEL depends on +# + +# Trim trailing "_t" +module_of_test = $(patsubst %_t,%,$(1)) + +# return sublist of $(2) which contains all elements before $(1) +earlier_modules = $(shell echo $(2) | sed 's, $(strip $(1)) *.*$$,,') + +# return list of modules included by module $(1); candidates are in $(2) +inc_sedstr = 's/^ *\# *include *"\(.*\)\.h"/\1/p' +includes = $(filter $(2), \ + $(shell sed -n $(inc_sedstr) auto/$(strip $(1)).h auto/$(strip $(1))_i.h)) + +# remove elements trailing list $(1) that do not appear in list $(2) +comma = , +define trimlist + $(shell perl -e '@l = split " ", "$(strip $(1))"; + %inc = ( $(addsuffix =>" "$(comma),$(2)) ); + sub trim { return () if ! scalar @_; + my $$last = $$_[-1]; + return @_ if defined $$inc{$$last}; + pop @_; + return trim(@_); } + print join(" ", trim(@l));') +endef + +# return list of objects belonging to a list of module +objects = $(addsuffix .o, $(foreach mod, $(1), \ + $(if $($(mod)_IMPL), $($(mod)_IMPL), $(mod)))) + +ifdef BUILD_SOURCES + +do-all: .Unittest.deps + +.Unittest.deps: $(MODULES_FILE) + @echo "Generating $@" + $(VERBOSE)( $(foreach test, $(ALL_TESTS), \ + test_base=$(call module_of_test, $(test)); \ + echo '$(test): $(call objects, $(test)) \ + $$(call objects, '"$$test_base"' $$(call trimlist, \ + $(call earlier_modules, \ + $(call module_of_test, $(test)), \ + $(INTERFACES_KERNEL)), \ + $$(call includes, '"$$test_base"', \ + $$(INTERFACES_KERNEL))))';) \ + ) > $@.new + mv $@.new $@ +endif + +ifdef BUILD_OBJECTS +include .Unittest.deps +endif + +# List of subsystems on which KERNEL depends +$(ALL_TESTS): $(ABI) $(JABI) $(DRIVERS) $(LIBK) $(LIBAMM) $(CXXLIB) +$(ALL_TESTS): kernel.ux.lds + +# XXX Hacks +$(ALL_TESTS): sighandler.o + +# +# Compilation Rules +# + +$(ALL_TESTS): %: %.o + @echo "Linking test $@" + $(VERBOSE)$(CXX) -m32 -Wl,-Tkernel.ux.lds,--gc-sections \ + -static $(CXXFLAGS) $(LDFLAGS) $(PROF_FLAGS) $(OPT_CXXFLAGS) \ + $(filter-out kernel.ux.lds,$^) -o $@ $(TEST_LIB) + +%.ok: % +ifeq ($(SYSTEM_TARGET)$(CONFIG_XARCH),ux) # Test execution for non-cross UX builds + @echo -n "Running test $* ... " + @./$< --test --quiet > $*.out +ifeq ($(RECREATE_OUTPUT),1) + @cp $*.out $(srcdir)/test/unit/$*.out.verify.$(CONFIG_ABI) +endif # RECREATE_OUTPUT + @set -e; \ + testbase=$(srcdir)/test/unit/$*.out.verify; \ + if [ -f $$testbase ]; then \ + if [ -f $$testbase.$(CONFIG_ABI) ]; then \ + echo "Error: $$testbase.$(CONFIG_ABI) and $$testbase both exist."; \ + exit 1; \ + fi; \ + else \ + testbase=$$testbase.$(CONFIG_ABI); \ + fi; \ + diff -u $(DIFF_FLAGS) $$testbase $*.out +else # ! ux +# Add commands for executing tests built for other architectures. +endif # ! ux + @touch $@ + +clean-UNITTEST: + rm -f *_t *_t.ok *_t.out .Unittest.deps diff --git a/kernel/fiasco/src/Makerules.VERSION b/kernel/fiasco/src/Makerules.VERSION new file mode 100644 index 00000000..3922d3f5 --- /dev/null +++ b/kernel/fiasco/src/Makerules.VERSION @@ -0,0 +1,31 @@ +# -*- makefile -*- +# vim:set ft=make: + +# recent version.h required for any kip*.o files +$(filter kip%.o,$(OBJ_ABI)): $(VERSION) + +$(VERSION): FORCE + $(GENVER_MESSAGE) + $(VERBOSE)if [ -d $(srcdir)/.svn ]; then \ + v=`svnversion -nc $(srcdir)`; v=$${v%[A-Z]}; \ + echo "#define CODE_VERSION \"r$${v#*:}\"" > $@; \ + elif [ -d $(srcdir)/.git ]; then \ + v=`git rev-parse --verify --short HEAD 2>/dev/null` \ + echo "#define CODE_VERSION \"$$v\"" > $@; \ + elif [ -d $(srcdir)/.hg ]; then \ + v=`hg id 2>/dev/null` \ + echo "#define CODE_VERSION \"$${v% *}\"" > $@; \ + else \ + echo "#define CODE_VERSION \"UNKNOWN\"" > $@; \ + fi + $(VERBOSE)echo "#define BUILD_DATE \"$$(date)\"" >> $@ + $(VERBOSE)if [ -e .build_nr ]; then \ + nr=$$(($$(cat .build_nr) + 1)); \ + else \ + nr=1; \ + fi; \ + echo $$nr > .build_nr; \ + echo "#define BUILD_NR \"$$nr\"" >> $@ + +clean-VERSION: + rm -f $(VERSION) diff --git a/kernel/fiasco/src/Makerules.global b/kernel/fiasco/src/Makerules.global new file mode 100644 index 00000000..85a21d4a --- /dev/null +++ b/kernel/fiasco/src/Makerules.global @@ -0,0 +1,169 @@ +# -*- makefile -*- + +# +# Makerules for the sources of Fiasco +# + +# +# Source-code locations +# + + +# If building in a separate srcdir, prepend it to module-provided include paths +ifneq ($(srcdir),.) +VPATH := $(addprefix $(srcdir)/, $(VPATH)) +PRIVATE_INCDIR := $(addprefix $(srcdir)/, $(PRIVATE_INCDIR)) +endif + +# Finally add the current directory and the preprocessor directory +VPATH += . auto +PRIVATE_INCDIR += . auto + +# +# Function for all Makreuls. files +# + +MAKERULES_SUBSYS = $(foreach subsys, $(SUBSYSTEMS), $(firstword $(wildcard $(addsuffix /Makerules.$(subsys),$(VPATH) $(srcdir))))) + +# +# special: build certain sources without profiling flags +# +NOPROFILE_C = $(filter $(addsuffix .c, $(NOPROFILE)), $(SRC_C)) +NOPROFILE_CC = $(filter $(addsuffix .cc, $(NOPROFILE)), $(SRC_CC)) +NOOPT_C = $(filter $(addsuffix .c, $(NOOPT)), $(SRC_C)) +NOOPT_CC = $(filter $(addsuffix .cc, $(NOOPT)), $(SRC_CC)) +NONDEBUG_C = $(filter $(addsuffix .c, $(NONDEBUG)), $(SRC_C)) +NONDEBUG_CC = $(filter $(addsuffix .cc, $(NONDEBUG)), $(SRC_CC)) +INSTRUMENT_C = $(filter $(addsuffix .c, $(INSTRUMENT)), $(SRC_C)) +INSTRUMENT_CC = $(filter $(addsuffix .cc, $(INSTRUMENT)), $(SRC_CC)) + +$(NOPROFILE_CC:.cc=.o) : %.o: %.cc + $(COMP_MESSAGE) + $(VERBOSE)$(CXX) -c -MD -MP -MF .$*.cc.d.new -o $@ \ + $(CPPFLAGS) $(CXXFLAGS) $(OPT_CXXFLAGS) $< + @mv .$*.cc.d.new .$*.cc.d + +$(NOPROFILE_C:.c=.o) : %.o: %.c + $(COMP_MESSAGE) + $(VERBOSE)$(CC) -c -MD -MP -MF .$*.c.d.new -o $@ \ + $(CPPFLAGS) $(CFLAGS) $(OPT_CFLAGS) $< + @mv .$*.c.d.new .$*.c.d + +$(NOOPT_CC:.cc=.o) : %.o: %.cc + $(COMP_MESSAGE_NOOPT) + $(VERBOSE)$(CXX) -c -MD -MP -MF .$*.cc.d.new -o $@ \ + $(CPPFLAGS) $(CXXFLAGS) $(NOOPT_CXXFLAGS) $< + @mv .$*.cc.d.new .$*.cc.d + +$(NOOPT_CC:.cc=.S) : %.S: %.cc + $(COMP_MESSAGE_NOOPT) + $(VERBOSE)$(CXX) -S -o $@ \ + $(CPPFLAGS) $(CXXFLAGS) $(NOOPT_CXXFLAGS) $< + +$(NOOPT_C:.c=.o) : %.o: %.c + $(COMP_MESSAGE_NOOPT) + $(VERBOSE)$(CC) -c -MD -MP -MF .$*.c.d.new -o $@ \ + $(CPPFLAGS) $(CFLAGS) $(NOOPT_CFLAGS) $< + @mv .$*.c.d.new .$*.c.d + +$(NOOPT_C:.c=.S) : %.S: %.c + $(COMP_MESSAGE_NOOPT) + $(VERBOSE)$(CC) -S -o $@ \ + $(CPPFLAGS) $(CFLAGS) $(NOOPT_CFLAGS) $< + +$(INSTRUMENT_CC:.cc=.o) : %.o: %.cc + $(COMP_MESSAGE) + $(VERBOSE)$(CXX) -c -MD -MP -MF .$*.cc.d.new -o $@ \ + $(CPPFLAGS) $(CXXFLAGS) $(PROF_FLAGS) $(OPT_CXXFLAGS) $(INST_FLAGS) $< + @mv .$*.cc.d.new .$*.cc.d + +$(INSTRUMENT_C:.c=.o) : %.o: %.c + $(COMP_MESSAGE) + $(VERBOSE)$(CC) -c -MD -MP -MF .$*.c.d.new -o $@ \ + $(CPPFLAGS) $(CFLAGS) $(PROF_FLAGS) $(OPT_CFLAGS) $(INST_FLAGS) $< + @mv .$*.c.d.new .$*.c.d + +$(NONDEBUG_CC:.cc=.o) : %.o: %.cc + $(COMP_MESSAGE) + $(VERBOSE)$(CXX) -c -MD -MP -MF .$*.cc.d.new -o $@ $(filter-out -DNDEBUG, \ + $(CPPFLAGS) $(CXXFLAGS) $(PROF_FLAGS) $(OPT_CXXFLAGS)) $< + @mv .$*.cc.d.new .$*.cc.d + +$(NONDEBUG_CC:.cc=.S) : %.S: %.cc + $(COMP_MESSAGE) + $(VERBOSE)$(CXX) -S -o $@ $(filter-out -DNDEBUG, \ + $(CPPFLAGS) $(CXXFLAGS) $(PROF_FLAGS) $(OPT_CXXFLAGS)) $< + +$(NONDEBUG_C:.c=.o) : %.o: %.c + $(COMP_MESSAGE) + $(VERBOSE)$(CC) -c -MD -MP -MF .$*.c.d.new -o $@ $(filter-out -DNDEBUG, \ + $(CPPFLAGS) $(CFLAGS) $(PROF_FLAGS) $(OPT_CFLAGS)) $< + @mv .$*.c.d.new .$*.c.d + +$(NONDEBUG_C:.c=.S) : %.S: %.c + $(COMP_MESSAGE) + $(VERBOSE)$(CC) -S -o $@ $(filter-out -DNDEBUG, \ + $(CPPFLAGS) $(CFLAGS) $(PROF_FLAGS) $(OPT_CFLAGS)) $< + +### + +# +# Implicit rules +# + +.PHONY: FORCE + +%.o: %.cc + $(COMP_MESSAGE) + $(VERBOSE)$(CXX) -c -MD -MP -MF .$*.cc.d.new -o $@ \ + $(CPPFLAGS) $(CXXFLAGS) $(PROF_FLAGS) $(OPT_CXXFLAGS) $< + @mv .$*.cc.d.new .$*.cc.d + +%.S: %.cc + $(COMP_MESSAGE) + $(VERBOSE)$(CC) -S -o $@ -fverbose-asm \ + $(CPPFLAGS) $(CXXFLAGS) $(PROF_FLAGS) $(OPT_CXXFLAGS) $< + +%.o: %.c + $(COMP_MESSAGE) + $(VERBOSE)$(CC) -c -MD -MP -MF .$*.c.d.new -o $@ \ + $(CPPFLAGS) $(CFLAGS) $(PROF_FLAGS) $(OPT_CFLAGS) $< + @mv .$*.c.d.new .$*.c.d + +%.S: %.c + $(COMP_MESSAGE) + $(VERBOSE)$(CC) -S -o $@ -fverbose-asm \ + $(CPPFLAGS) $(CFLAGS) $(PROF_FLAGS) $(OPT_CFLAGS) $< + +%.o: %.S + $(COMP_MESSAGE) + $(VERBOSE)$(CC) -c -MD -MP -MF .$*.S.d.new -o $@ \ + $(CPPFLAGS) $(ASFLAGS) $< + @mv .$*.S.d.new .$*.S.d + +%.i: %.c + $(COMP_MESSAGE) + $(VERBOSE)$(CC) -E -dD -o $@ \ + $(CPPFLAGS) $(CFLAGS) $(PROF_FLAGS) $(OPT_CFLAGS) $< + +%.i: %.cc + $(COMP_MESSAGE) + $(VERBOSE)$(CXX) -E -dD -o $@ \ + $(CPPFLAGS) $(CXXFLAGS) $(PROF_FLAGS) $(OPT_CXXFLAGS) $< + +%.i: %.S + $(COMP_MESSAGE) + $(VERBOSE)$(CC) -E -dD -o $@ $(CPPFLAGS) $(ASFLAGS) $< + +%.lds: %.ld + $(COMP_MESSAGE) + $(VERBOSE)$(CPP) -undef -P -DASSEMBLER -o $@ $(CPPFLAGS) $< + +(%): % + $(AR_MESSAGE) + $(VERBOSE)$(AR) $(ARFLAGS) $@ $< + +vpath %.ld $(srcdir) + +# Suck in user-specific optional Makerules files +-include Makerules.local diff --git a/kernel/fiasco/src/Modules.amd64 b/kernel/fiasco/src/Modules.amd64 new file mode 100644 index 00000000..4c676d57 --- /dev/null +++ b/kernel/fiasco/src/Modules.amd64 @@ -0,0 +1,447 @@ +# -*- makefile -*- + +include $(srcdir)/Modules.generic + +SUBSYSTEMS = JABI ABI DRIVERS KERNEL CRT0 BOOT LIBK \ + CHECKSUM CXXLIB MINILIBC LIBKERN TCBOFFSET SYMBOLS VERSION GBLCFG + +ifeq ("$(CONFIG_GSTABS)","y") + SUBSYSTEMS += LINES +endif + +PREPROCESS_PARTS += arch $(CONFIG_ABI) 64bit iofp \ + $(CONFIG_XARCH) apic abs-timeout-hack \ + i8259 pc i8254 fpu \ + auto_map_kip + +OBJ_SPACE-y = phys +OBJ_SPACE- = virt +OBJ_SPACE = $(OBJ_SPACE-$(CONFIG_DISABLE_VIRT_OBJ_SPACE)) + +PREPROCESS_PARTS += obj_space_$(OBJ_SPACE) + +PREPROCESS_PARTS-$(CONFIG_MP) += mp +PREPROCESS_PARTS-$(CONFIG_LIST_ALLOC_SANITY) += list_alloc_debug +PREPROCESS_PARTS-$(CONFIG_JDB) += debug log +PREPROCESS_PARTS-$(CONFIG_SCHED_PIT) += pit_timer +PREPROCESS_PARTS-$(CONFIG_SCHED_RTC) += rtc_timer +PREPROCESS_PARTS-$(CONFIG_SCHED_APIC) += apic_timer +PREPROCESS_PARTS-$(CONFIG_SCHED_HPET) += hpet_timer +PREPROCESS_PARTS-$(CONFIG_SERIAL) += serial 16550 +PREPROCESS_PARTS-$(CONFIG_WATCHDOG) += watchdog +PREPROCESS_PARTS-$(CONFIG_PERF_CNT) += perf_cnt +PREPROCESS_PARTS-$(CONFIG_IO_PROT) += io +PREPROCESS_PARTS-$(CONFIG_CPU_VIRT) += svm vmx +PREPROCESS_PARTS-$(CONFIG_SCHED_FIXED_PRIO) += sched_fixed_prio +PREPROCESS_PARTS-$(CONFIG_SCHED_WFQ) += sched_wfq +PREPROCESS_PARTS-$(CONFIG_SCHED_FP_WFQ) += sched_fp_wfq + +PREPROCESS_PARTS += $(PREPROCESS_PARTS-y) + +# +# TYPES subsystem +# +PRIVATE_INCDIR += types/$(CONFIG_XARCH) types + +# +# ABI Subsystem +# +ABI := libabi.a +VPATH += abi/$(CONFIG_XARCH) abi +INTERFACES_ABI := l4_fpage l4_msg_item l4_buf_desc kip l4_types \ + l4_error virt + +kip_IMPL := kip kip-debug kip-amd64 kip-amd64-debug +l4_types_IMPL := l4_types l4_types-debug +virt_IMPL := virt-ia32-amd64 + +# +# JABI Subsystem +# +JABI := libjabi.a +VPATH += jabi/$(CONFIG_XARCH) jabi +INTERFACES_JABI := jdb_ktrace + +# +# DRIVERS subsystem +# +DRIVERS := libdrivers.a libgluedriverslibc.a +VPATH += drivers/$(CONFIG_XARCH) drivers +PRIVATE_INCDIR += drivers/$(CONFIG_XARCH) drivers +INTERFACES_DRIVERS := mux_console console keyb io pci vga_console reset \ + processor delayloop mem +ifeq ("$(CONFIG_SERIAL)","y") +INTERFACES_DRIVERS += filter_console uart +endif +reset_IMPL := reset-amd64 +uart_IMPL := uart uart-16550 +CXXSRC_DRIVERS := glue_libc.cc +NOOPT += $(patsubst %.o, %, $(OBJ_DRIVERS)) + +keyb_IMPL := keyb keyb-pc +io_IMPL := io io-amd64 +mem_IMPL := mem mem-amd64 +processor_IMPL := processor processor-amd64 + +# +# KERNEL subsystem +# +KERNEL := fiasco.image +VPATH += kern/$(CONFIG_XARCH) kern/ia32/64 kern/ia32 kern +PRIVATE_INCDIR += kern/$(CONFIG_XARCH) kern/ia32/64 kern/ia32 kern + +INTERFACES_KERNEL += __main acpi io_apic irq_chip_ia32 irq_chip_pic \ + irq_msi io_space apic pit checksum \ + boot_console x86desc gdt idt tss timer_irq \ + dirq + +INTERFACES_KERNEL-$(CONFIG_CPU_VIRT) += svm vmx vm vm_svm vm_vmx + + +apic_IMPL := apic-ia32 apic-ia32-mp +boot_console_IMPL := boot_console-ia32-amd64 +boot_info_IMPL := boot_info boot_info-ia32 +clock_IMPL := clock clock-ia32 +config_IMPL := config config-ia32-64 config-ia32 +context_IMPL := context context-ia32 context-ia32-64 context-vcpu +continuation_IMPL := continuation-ia32-64 +cpu_IMPL := cpu cpu-ia32 cpu-64 +dirq_IMPL := dirq-ia32-ux +entry_frame_IMPL := entry_frame entry_frame-amd64 \ + entry_frame-abs-timeout-hack +fpu_IMPL := fpu fpu-ia32-ux fpu-ia32 +ipi_IMPL := ipi ipi-ia32 +kdb_ke_IMPL := kdb_ke kdb_ke-ia32 +kernel_thread_IMPL := kernel_thread kernel_thread-std kernel_thread-ia32 +kernel_uart_IMPL := kernel_uart kernel_uart-16550 +kip_init_IMPL := kip_init-ia32 +kmem_IMPL := kmem-ia32 kmem-ia32-64 +kmem_alloc_IMPL := kmem_alloc kmem_alloc-ia32 +main_IMPL := main-ia32-64 main-ia32 +mapping_IMPL := mapping-ia32-64 mapping +map_util_IMPL := map_util map_util-mem map_util-io map_util-objs +mem_layout_IMPL := mem_layout mem_layout-ia32 mem_layout-ia32-64 +mem_space_IMPL := mem_space mem_space-user mem_space-ia32 +mem_unit_IMPL := mem_unit-amd64 +obj_space_IMPL := obj_space obj_space-$(OBJ_SPACE) +paging_IMPL := paging-ia32-64 paging-ia32 paging +perf_cnt_IMPL := perf_cnt perf_cnt-ia32 +pic_IMPL := pic pic-i8259 +pit_IMPL := pit-i8254 +pmem_alloc_IMPL := pmem_alloc pmem_alloc-ia32-ux +rtc_IMPL := rtc-ia32 +sched_context_IMPL := sched_context-wfq sched_context-fixed_prio \ + sched_context-fp_wfq sched_context +space_IMPL := space space-ia32 +spin_lock_IMPL := spin_lock spin_lock-ia32 +startup_IMPL := startup startup-ia32 +task_IMPL := task task-ia32-amd64 +tb_entry_IMPL := tb_entry tb_entry-ia32-64 +timer_IMPL := timer timer-ia32-amd64-ux +thread_IMPL := thread thread-ia32 thread-ia32-64 \ + thread-ipc thread-pagefault thread-log \ + thread-debug thread-dbf thread-vcpu +trap_state_IMPL := trap_state-amd64 +tss_IMPL := tss-amd64 +utcb_init_IMPL := utcb_init utcb_init-ia32 +vmem_alloc_IMPL := vmem_alloc vmem_alloc-ia32 +vm_factory_IMPL := vm_factory vm_factory-ia32 +watchdog_IMPL := watchdog watchdog-ia32 + +INTERFACES_KERNEL-$(CONFIG_SERIAL) += uart_console + +cpu_lock_IMPL := cpu_lock cpu_lock-generic + +ifeq ("$(CONFIG_SCHED_PIT)","y") + timer_IMPL += timer-pit + timer_tick_IMPL += timer_tick-single-vector timer_tick-ia32 +endif +ifeq ("$(CONFIG_SCHED_RTC)","y") + timer_IMPL += timer-rtc + timer_tick_IMPL += timer_tick-single-vector timer_tick-ia32 + INTERFACES_KERNEL += rtc +endif +ifeq ("$(CONFIG_SCHED_APIC)","y") + timer_IMPL += timer-apic + timer_tick_IMPL += timer_tick-apic +endif +ifeq ("$(CONFIG_SCHED_HPET)","y") + timer_IMPL += timer-hpet + INTERFACES_KERNEL += hpet +endif + + +ifeq ("$(CONFIG_IO_PROT)","y") + space_IMPL += space-io + sigma0_task_IMPL = sigma0_task sigma0_task-io + thread_IMPL += thread-io +endif + +ifeq ("$(CONFIG_JDB)","y") +JDB := jdb_compound.o +SUBSYSTEMS += JDB +VPATH += jdb/ia32/64 jdb/ia32 jdb +INTERFACES_KERNEL += jdb_tbuf jdb_trace tb_entry jdb_tbuf_init +INTERFACES_JDB += jdb jdb_util jdb_prompt_ext jdb_symbol jdb_lines \ + jdb_dbinfo jdb_bp \ + jdb_module jdb_core jdb_io_ports \ + jdb_kern_info jdb_prompt_module jdb_tbuf_output \ + jdb_input jdb_dump jdb_ptab jdb_misc jdb_mapdb \ + jdb_tcb jdb_attach_irq \ + jdb_trace_set jdb_counters jdb_table kern_cnt \ + tb_entry_output jdb_exit_module \ + jdb_tbuf_show jdb_console_buffer \ + jdb_list jdb_screen push_console jdb_timeout \ + jdb_handler_queue jdb_halt_thread \ + jdb_kern_info_kmem_alloc \ + jdb_kern_info_kip jdb_kern_info_config \ + loadcnt jdb_utcb jdb_thread_list \ + jdb_entry_frame jdb_kobject jdb_space jdb_io_apic \ + jdb_trap_state jdb_ipi jdb_kobject_names \ + jdb_rcupdate jdb_bt jdb_ipc_gate jdb_obj_space \ + jdb_log jdb_factory jdb_iomap \ + jdb_thread jdb_scheduler jdb_sender_list \ + jdb_regex jdb_disasm + +apic_IMPL += apic-debug +jdb_IMPL := jdb jdb-ia32-amd64 jdb-ansi jdb-ia32-ux jdb-thread \ + jdb-int3-ia32-amd64 jdb-int3-ia32-ux +jdb_bp_IMPL := jdb_bp-ia32-ux jdb_bp-ia32-amd64 jdb_bp-amd64 +jdb_bt_IMPL := jdb_bt-ia32-ux +jdb_entry_frame_IMPL := jdb_entry_frame-ia32 +jdb_kern_info_IMPL := jdb_kern_info jdb_kern_info-ia32-amd64 \ + jdb_kern_info-ia32-ux jdb_kern_info-apic \ + jdb_kern_info-pci jdb_kern_info-bench \ + jdb_kern_info-bench-ia32-64 \ + jdb_kern_info-dr jdb_kern_info-mtrr +jdb_misc_IMPL := jdb_misc-ia32-amd64 +jdb_ptab_IMPL := jdb_ptab jdb_ptab-amd64 +jdb_screen_IMPL := jdb_screen jdb_screen-ia32 +jdb_tcb_IMPL := jdb_tcb jdb_tcb-amd64 +jdb_trace_set_IMPL := jdb_trace_set jdb_trace_set-ia32-ux + +INTERFACES_JDB-$(CONFIG_JDB_MISC) += jdb_tetris + +INTERFACES_JDB += $(INTERFACES_JDB-y) +endif + + +CXXSRC_KERNEL := kernel_panic.cc libc_backend_lock.cc +ASSRC_KERNEL := entry.S entry-native.S shortcut.S + +ASSRC_KERNEL-$(CONFIG_KIP_SYSCALLS_ABS) += sys_call_page-asm.S +ASSRC_KERNEL-$(CONFIG_MP) += tramp-mp.S entry-mp.S +ASSRC_KERNEL-$(CONFIG_CPU_VIRT) += vm_svm_asm.S vm_vmx_asm.S +ASSRC_KERNEL += $(ASSRC_KERNEL-y) + +NOOPT += $(filter jdb%,\ + $(foreach in,$(INTERFACES_KERNEL), \ + $(if $($(in)_IMPL),$($(in)_IMPL),$(in)))) +NOOPT += tb_entry_output $(tb_entry_IMPL) $(perf_cnt_IMPL) \ + kern_cnt loadcnt $(apic_IMPL) $(watchdog_IMPL) kdb \ + $(kernel_uart_IMPL) push_console thread-dbf \ + trap_state + +### When testing with test threads, uncomment the following: +# +# VPATH += kern-test +# PRIVATE_INCDIR += kern-test +# +# INTERFACES_KERNEL += generic_test_thread test_thread node cpu \ +# back_trace cpu_guard types +# +# node_IMPL := node node-up +# cpu_IMPL := cpu cpu-perf cpu-perfp4 +# config_IMPL := config config-test +# +# kernel_thread_IMPL := $(filter-out kernel_thread-std,$(kernel_thread_IMPL)) \ +# kernel_thread-test +# +# Replace this definition with your own test thread. +# test_thread_IMPL := test_thread-test26 +# +### End of test-thread section + +# +# CRT0 subsystem +# +CRT0 := crt0.o +ASSRC_CRT0 := crt0.S + +# +# BOOT subsystem +# +BOOT := main +VPATH += boot/$(CONFIG_XARCH) boot +PRIVATE_INCDIR += boot boot/amd64 +CXXSRC_BOOT := boot_libc_glue.cc bootstrap.cc boot_cpu.cc \ + direct_cons_putchar.cc +ASSRC_BOOT := boot.S boot_idt.S +NOOPT += $(patsubst %.o, %, $(OBJ_BOOT)) + +# +# TCBOFFSET subsystem +# +TCBOFFSET := tcboffset.h +CXXSRC_TCBOFFSET := tcboffset.cc dump_tcboffsets.cc + +# +# SYMBOLS subsystem +# +SYMBOLS := Symbols + +# +# LINES subsystem +# +LINES := Lines +PROG_LINES := genlines + +# +# CHECKSUM subsystem +# +CHECKSUM := checksum +CXXSRC_CHECKSUM := genchecksum.cc + +# +# VERSION subsystem +# +VERSION := version.h + +# +# GBLCFG subsystem +# +GBLCFG := gblcfg.o +OBJ_KERNEL += gblcfg.o + +# +# CXXLIB Subsystem +# + +CXXLIB := libcxx.a +VPATH += lib/cxxlib +INTERFACES_CXXLIB := paranoia s_cruft + +# +# LIBK subsystem +# +LIBK := libk.a +VPATH += lib/libk/$(CONFIG_XARCH) lib/libk +PRIVATE_INCDIR += lib/libk/$(CONFIG_XARCH) lib/libk +INTERFACES_LIBK := atomic lock_guard auto_ptr std_macros +CXXSRC_LIBK += construction.cc +atomic_IMPL := atomic atomic-amd64 + +# +# LIBKERN Subsystem +# +LIBKERN := libkern.a +VPATH += lib/kern +PRIVATE_INCDIR += lib/kern/include +CSRC_LIBKERN := +NOOPT += $(patsubst %.o, %, $(OBJ_LIBKERN)) + + +# +# LIBGZIP subsystem (only for Jdb) +# +ifneq ($(CONFIG_JDB_GZIP),) + LIBGZIP := libgzip.a + VPATH += lib/gzip + PRIVATE_INCDIR += lib/gzip + CSRC_LIBGZIP := adler32.c crc32.c gzip.c trees.c deflate.c zutil.c + NOOPT += $(patsubst %.o, %, $(OBJ_LIBGZIP)) +endif + +# +# LIBDISASM subsystem (only for Jdb) +# +ifeq ("$(CONFIG_JDB_DISASM)","y") + # $(srcdir)/lib/disasm may be removed + ifeq ($(wildcard $(srcdir)/lib/disasm),) + $(error $(srcdir)/lib/disasm is missing, disable CONFIG_JDB_DISASM) + endif + + SUBSYSTEMS += LIBDISASM + KERNEL_EXTRA_LIBS += $(LIBDISASM) + PREPROCESS_PARTS += jdb_disasm + + LIBDISASM := libdisasm.a + VPATH += lib/disasm lib/disasm/elf lib/disasm/include \ + lib/disasm/include/opcode lib/disasm/opcodes \ + lib/disasm/libiberty lib/disasm/bfd + PRIVATE_INCDIR += lib/disasm lib/disasm/elf lib/disasm/include \ + lib/disasm/include/opcode lib/disasm/opcodes \ + lib/disasm/libiberty lib/disasm/bfd + PRIVATE_INCDIR += lib/disasm + CXXSRC_LIBDISASM := disasm.cc + CSRC_LIBDISASM := dis-init.c i386-dis.c dis-buf.c + NOOPT += $(patsubst %.o, %, $(OBJ_LIBDISASM)) +endif + +# +# LIBPERFCTR subsystem (only for Jdb) +# +LIBPERFCTR := libperfctr.a +VPATH += lib/perfctr +PRIVATE_INCDIR += lib/perfctr +CSRC_LIBPERFCTR := event_set_p5.c event_set_p6.c event_set_amd.c \ + event_set_p4.c event_set_x86.c perfctr.c \ + event_set_centaur.c +NOOPT += $(patsubst %.o, %, $(OBJ_LIBPERFCTR)) + +# +# LIBREGEX subsystem (only for Jdb) +# +LIBREGEX := libregex.a +VPATH += lib/regex +PRIVATE_INCDIR += lib/regex +CSRC_LIBREGEX := alloc.c rx.c +NOOPT += $(patsubst %.o, %, $(OBJ_LIBREGEX)) + +# +# MINILIBC Subsystem +# +MINILIBC := libc.a +VPATH += lib/minilibc/$(CONFIG_XARCH) lib/minilibc +PRIVATE_INCDIR += lib/minilibc/$(CONFIG_XARCH)/include lib/minilibc/include +CSRC_MINILIBC := atexit.c memccpy.c memcmp.c memmove.c memset.c memcpy.c \ + memchr.c strchr.c strcmp.c strcpy.c strlen.c strncmp.c \ + strncpy.c strstr.c __assert_fail.c printf.c __v_printf.c \ + vprintf.c strtol.c strtoul.c lltostr.c __ltostr.c \ + putchar.c puts.c getchar.c gets.c sprintf.c \ + snprintf.c vsnprintf.c vsprintf.c longjmp.c isalnum.c \ + isalpha.c isascii.c isblank.c iscntrl.c isdigit.c \ + isgraph.c islower.c isprint.c ispunct.c isspace.c \ + isupper.c isxdigit.c tolower.c strcspn.c strspn.c panic.c +ASSRC_MINILIBC := setjmp.S + +# do not profile all of MINILIBC, because it is used in the BOOT subsystem +NOOPT += $(patsubst %.o, %, $(OBJ_MINILIBC)) + +ifeq ("$(CONFIG_JDB)","y") + +ifneq ($(CONFIG_JDB_GZIP),) + ifneq ($(wildcard $(srcdir)/lib/gzip),) + SUBSYSTEMS += LIBGZIP + KERNEL_EXTRA_LIBS += $(LIBGZIP) + INTERFACES_KERNEL += jdb_gzip + endif +endif + +ifneq ($(wildcard $(srcdir)/lib/perfctr),) + SUBSYSTEMS += LIBPERFCTR + KERNEL_EXTRA_LIBS += $(LIBPERFCTR) + KERNEL_UNRES_SYMS += -u perfctr_set_cputype +endif + +ifneq ($(wildcard $(srcdir)/lib/regex),) + SUBSYSTEMS += LIBREGEX + KERNEL_EXTRA_LIBS += $(LIBREGEX) + PREPROCESS_PARTS += jdb_regex +endif + +endif + +MODULES_FILES = $(MODULES_FILE) $(MODULES_FILE_BSP) + +INTERFACES_KERNEL += $(INTERFACES_KERNEL-y) diff --git a/kernel/fiasco/src/Modules.arm b/kernel/fiasco/src/Modules.arm new file mode 100644 index 00000000..d6516d7c --- /dev/null +++ b/kernel/fiasco/src/Modules.arm @@ -0,0 +1,334 @@ +# -*- makefile -*- + +############################################################################### + +include $(srcdir)/Modules.generic + +SUBSYSTEMS := ABI KERNEL LIBK DRIVERS MINILIBC \ + CXXLIB VERSION JABI TCBOFFSET CRT0 + + +PREPROCESS_PARTS += arch $(CONFIG_ABI) 32bit $(CONFIG_XARCH) \ + h3800 noncont_mem abs_syscalls + +PREPROCESS_PARTS-$(CONFIG_SERIAL) += serial +PREPROCESS_PARTS-$(CONFIG_MP) += mp +PREPROCESS_PARTS-$(CONFIG_FPU) += fpu +PREPROCESS_PARTS-$(CONFIG_LIST_ALLOC_SANITY) += list_alloc_debug +PREPROCESS_PARTS-$(CONFIG_JDB) += debug jdb log +PREPROCESS_PARTS-$(CONFIG_PERF_CNT) += perf_cnt +PREPROCESS_PARTS-$(CONFIG_ARM_CACHE_L2CXX0) += outer_cache outer_cache_l2cxx0 + +PREPROCESS_PARTS-$(CONFIG_ARM_920T) += armv5 arm920t vcache +PREPROCESS_PARTS-$(CONFIG_ARM_926) += armv5 926 vcache +PREPROCESS_PARTS-$(CONFIG_ARM_V6PLUS) += armv6plus +PREPROCESS_PARTS-$(CONFIG_ARM_V6) += armv6 +PREPROCESS_PARTS-$(CONFIG_ARM_V7) += armv7 +PREPROCESS_PARTS-$(CONFIG_ARM_1136) += arm1136 +PREPROCESS_PARTS-$(CONFIG_ARM_1176) += arm1176 +PREPROCESS_PARTS-$(CONFIG_ARM_MPCORE) += mpcore +PREPROCESS_PARTS-$(CONFIG_ARM_CORTEX_A8) += armca8 +PREPROCESS_PARTS-$(CONFIG_ARM_CORTEX_A9) += armca9 +PREPROCESS_PARTS-$(CONFIG_ARM_TZ) += tz +PREPROCESS_PARTS-$(CONFIG_ARM_1176_CACHE_ALIAS_FIX) += arm1176_cache_alias_fix +PREPROCESS_PARTS-$(CONFIG_SCHED_FIXED_PRIO) += sched_fixed_prio +PREPROCESS_PARTS-$(CONFIG_SCHED_WFQ) += sched_wfq +PREPROCESS_PARTS-$(CONFIG_SCHED_FP_WFQ) += sched_fp_wfq + + +OBJ_SPACE-y = phys +OBJ_SPACE- = virt +OBJ_SPACE = $(OBJ_SPACE-$(CONFIG_DISABLE_VIRT_OBJ_SPACE)) + + +ifeq ("$(CONFIG_ARM_1176)@$(CONFIG_ARM_1176_CACHE_ALIAS_FIX)","y@") +OBJ_SPACE_TYPE = phys +else +OBJ_SPACE_TYPE = $(if $(CONFIG_ARM_V6PLUS),$(OBJ_SPACE),phys) +endif + +PREPROCESS_PARTS += obj_space_$(OBJ_SPACE_TYPE) + +# +# TYPES subsystem +# + +PRIVATE_INCDIR += types/$(CONFIG_XARCH) types + +VPATH_LIBUART := $(srcdir)/lib/uart +PRIVATE_INCDIR += lib/uart + +# +# DRIVERS Subsystem +# +DRIVERS := libdrivers.a libgluedriverslibc.a +VPATH += drivers/$(CONFIG_XARCH) drivers +PRIVATE_INCDIR += drivers/$(CONFIG_XARCH) drivers +INTERFACES_DRIVERS := sa1100 mux_console console uart filter_console \ + h3xxx io mem mmu reset processor delayloop +io_IMPL := io io-arm +mmu_IMPL := mmu mmu-arm +mem_IMPL := mem mem-arm +uart_IMPL := uart uart-mmio +reset_IMPL := +processor_IMPL := processor processor-arm +CXXSRC_DRIVERS := glue_libc.cc +NOOPT += $(patsubst %.o, %, $(OBJ_DRIVERS)) +ALWAYS_INLINE += mem + +# +# MINILIBC Subsystem +# +MINILIBC := libc.a +VPATH += lib/minilibc/$(CONFIG_XARCH) lib/minilibc +PRIVATE_INCDIR += lib/minilibc/$(CONFIG_XARCH)/include lib/minilibc/include +CSRC_MINILIBC := atexit.c memccpy.c memcmp.c memmove.c memset.c memcpy.c \ + memchr.c panic.c strchr.c strcmp.c strcpy.c strlen.c \ + strncmp.c strncpy.c strstr.c __assert_fail.c printf.c \ + __v_printf.c vprintf.c strtol.c strtoul.c __lltostr.c \ + __ltostr.c putchar.c puts.c getchar.c gets.c \ + sprintf.c snprintf.c vsnprintf.c vsprintf.c \ + longjmp.c isalnum.c isalpha.c isascii.c isblank.c \ + iscntrl.c isdigit.c isgraph.c islower.c isprint.c \ + ispunct.c isspace.c isupper.c isxdigit.c strspn.c \ + strcspn.c tolower.c raise.c aeabi.c +ASSRC_MINILIBC := setjmp.S +NOOPT += $(patsubst %.o, %, $(OBJ_MINILIBC)) + + +# +# LIBGZIP subsystem (only for Jdb) +# +ifneq ($(CONFIG_JDB_GZIP),) + LIBGZIP := libgzip.a + VPATH += lib/gzip + PRIVATE_INCDIR += lib/gzip + CSRC_LIBGZIP := adler32.c crc32.c gzip.c trees.c deflate.c zutil.c + NOOPT += $(patsubst %.o, %, $(OBJ_LIBGZIP)) +endif + + +# +# JABI Subsystem +# +JABI := libjabi.a +VPATH += jabi/$(CONFIG_XARCH) jabi +INTERFACES_JABI := jdb_ktrace + +# +# ABI Subsystem +# + +ABI := libabi.a +VPATH += abi/$(CONFIG_XARCH) abi + +INTERFACES_ABI := kip l4_types l4_fpage l4_msg_item \ + l4_buf_desc l4_error + +l4_types_IMPL := l4_types l4_types-debug + + +# x0!=32Bit UIDs +kip_IMPL := kip kip-debug kip-arm + + +# +# KERNEL subsystem +# +KERNEL := fiasco +KERNEL_EXTRA := Symbols +VPATH += kern/$(CONFIG_XARCH) kern +VPATH += jdb/arm jdb +PRIVATE_INCDIR += kern/$(CONFIG_XARCH) kern + +INTERFACES_KERNEL += __main mem_op pagetable kmem_space boot_uart_init \ + irq_chip_generic bootstrap kern_lib_page \ + jdb_extensions outer_cache utcb_support cascade_irq \ + irq_mgr_multi_chip + +INTERFACES_KERNEL-$(CONFIG_SERIAL) += uart_console +INTERFACES_KERNEL-$(CONFIG_ARM_TZ) += vm + +INTERFACES_KERNEL += $(INTERFACES_KERNEL-y) + + +boot_info_IMPL := boot_info boot_info-arch +bootstrap_IMPL := bootstrap +clock_IMPL := clock +config_IMPL := config config-arm +context_IMPL := context context-arm context-vcpu +continuation_IMPL := continuation-arm +cpu_IMPL := cpu cpu-arm +cpu_lock_IMPL := cpu_lock cpu_lock-generic +entry_frame_IMPL := entry_frame entry_frame-arm \ + entry_frame-abs-timeout-hack +fpu_IMPL := fpu fpu-arm +ipi_IMPL := ipi ipi-arm +kdb_ke_IMPL := kdb_ke kdb_ke-arm +kernel_task_IMPL := kernel_task kernel_task-arm +kernel_thread_IMPL := kernel_thread kernel_thread-std kernel_thread-arm +kernel_uart_IMPL := kernel_uart +map_util_IMPL := map_util map_util-mem map_util-objs +mapping_IMPL := mapping-arm mapping +mem_layout_IMPL := mem_layout mem_layout-arm mem_layout-noncont +mem_space_IMPL := mem_space mem_space-arm mem_space-user +kmem_alloc_IMPL := kmem_alloc kmem_alloc-arm +obj_space_IMPL := obj_space obj_space-$(OBJ_SPACE_TYPE) +outer_cache_IMPL := outer_cache outer_cache-l2cxx0 +pagetable_IMPL := pagetable pagetable-arch +paging_IMPL := paging-arm paging +perf_cnt_IMPL := perf_cnt perf_cnt-arm +pic_IMPL := pic +sched_context_IMPL := sched_context-wfq sched_context-fixed_prio \ + sched_context-fp_wfq sched_context +space_IMPL := space space-arm +spin_lock_IMPL := spin_lock spin_lock-arm +startup_IMPL := startup startup-arm +sys_call_page_IMPL := sys_call_page sys_call_page-arm +task_IMPL := task task-arm +thread_IMPL := thread thread-arm \ + thread-jdb thread-ipc \ + thread-pagefault thread-log \ + thread-vcpu +timer_IMPL := timer timer-arm +timer_tick_IMPL := timer_tick timer_tick-arm +utcb_init_IMPL := utcb_init utcb_init-arm +utcb_support_IMPL := utcb_support utcb_support-arm +vmem_alloc_IMPL := vmem_alloc vmem_alloc-arch +tb_entry_IMPL := tb_entry tb_entry-arm + + +ifeq ("$(CONFIG_JDB)","y") +JDB := jdb_compound.o +SUBSYSTEMS += JDB +INTERFACES_JDB := jdb_handler_queue jdb_module jdb_pic \ + jdb jdb_core jdb_prompt_ext jdb_list \ + jdb_prompt_module jdb_exit_module jdb_kern_info \ + jdb_tcb jdb_screen jdb_thread_list jdb_input \ + jdb_symbol jdb_lines push_console \ + jdb_timeout jdb_dump jdb_ptab \ + jdb_attach_irq jdb_table \ + jdb_kern_info_kmem_alloc \ + jdb_kern_info_kip jdb_mapdb kern_cnt \ + jdb_trace_set jdb_entry_frame \ + jdb_kobject jdb_kobject_names \ + jdb_util jdb_space jdb_utcb \ + jdb_trap_state jdb_ipi jdb_rcupdate \ + jdb_ipc_gate jdb_obj_space jdb_log jdb_factory \ + jdb_thread jdb_scheduler jdb_sender_list\ + jdb_perf jdb_vm jdb_regex jdb_disasm jdb_bp \ + jdb_tbuf_output jdb_tbuf_show tb_entry_output \ + jdb_idle_stats + + +INTERFACES_KERNEL += jdb_tbuf jdb_tbuf_init tb_entry jdb_trace +jdb_IMPL := jdb jdb-arm jdb-ansi jdb-thread +jdb_kern_info_IMPL := jdb_kern_info jdb_kern_info-arm \ + jdb_kern_info-bench jdb_kern_info-bench-arm \ + jdb_kern_info-cpu-arm +jdb_dump_entry_frame_IMPL:= jdb_dump_entry_frame-arm +jdb_tcb_IMPL := jdb_tcb jdb_tcb-arm +jdb_ptab_IMPL := jdb_ptab jdb_ptab-ia32-ux-arm jdb_ptab-arm +jdb_entry_frame_IMPL := jdb_entry_frame-arm +jdb_trace_set_IMPL := jdb_trace_set jdb_trace_set-arm +jdb_bp := jdb_bp +thread_IMPL += thread-debug + +ifneq ($(CONFIG_JDB_GZIP),) + ifneq ($(wildcard $(srcdir)/lib/gzip),) + SUBSYSTEMS += LIBGZIP + KERNEL_EXTRA_LIBS += $(LIBGZIP) + INTERFACES_KERNEL += jdb_gzip + endif +endif + +INTERFACES_JDB += $(INTERFACES_JDB-y) +endif + +CXXSRC_KERNEL := kernel_panic.cc libc_backend_lock.cc +ASSRC_KERNEL := ivt.S $(if $(CONFIG_MP),tramp-mp.S) +CPPFLAGS += $(if $(CONFIG_MP),-DMPCORE_PHYS_BASE=$(MPCORE_PHYS_BASE)) + +NOOPT += $(filter jdb%,\ + $(foreach in,$(INTERFACES_KERNEL), \ + $(if $($(in)_IMPL),$($(in)_IMPL),$(in)))) +NOOPT += tb_entry tb_entry_output + + +# +# CRT0 subsystem +# +CRT0 := crt0.o +ASSRC_CRT0 := crt0.S + + +# +# CXXLIB Subsystem +# +CXXLIB := libcxx.a +VPATH += lib/cxxlib +INTERFACES_CXXLIB := paranoia s_cruft + +# +# LIBK subsystem +# +LIBK := libk.a +VPATH += lib/libk/$(CONFIG_XARCH) lib/libk +PRIVATE_INCDIR += lib/libk/$(CONFIG_XARCH) lib/libk + +#INTERFACES_LIBK:= atomic lock_guard profile uuencode gmon unistd panic auto_ptr +INTERFACES_LIBK := std_macros atomic lock_guard auto_ptr +CXXSRC_LIBK += construction.cc +atomic_IMPL := atomic atomic-arm-up + +ifeq ("$(CONFIG_JDB_DISASM)","y") + # $(srcdir)/lib/disasm may be removed + ifeq ($(wildcard $(srcdir)/lib/disasm),) + $(error $(srcdir)/lib/disasm is missing, disable CONFIG_JDB_DISASM) + endif + SUBSYSTEMS += LIBDISASM + KERNEL_EXTRA_LIBS += $(LIBDISASM) + PREPROCESS_PARTS += jdb_disasm + + LIBDISASM := libdisasm.a + VPATH += lib/disasm lib/disasm/elf lib/disasm/include \ + lib/disasm/include/opcode lib/disasm/opcodes \ + lib/disasm/libiberty lib/disasm/bfd + PRIVATE_INCDIR += lib/disasm lib/disasm/elf lib/disasm/include \ + lib/disasm/include/opcode lib/disasm/opcodes \ + lib/disasm/libiberty lib/disasm/bfd + PRIVATE_INCDIR += lib/disasm + CXXSRC_LIBDISASM := disasm.cc + CSRC_LIBDISASM := arm-dis.c dis-init.c dis-buf.c safe-ctype.c + NOOPT += $(patsubst %.o, %, $(OBJ_LIBDISASM)) +endif + +# +# VERSION subsystem +# +VERSION := version.h + +TCBOFFSET := tcboffset.h +CXXSRC_TCBOFFSET := tcboffset.cc dump_tcboffsets.cc + +BSP_NAME := $(patsubst "%",%,$(CONFIG_BSP_NAME)) +MODULES_FILE_BSP := $(srcdir)/kern/arm/bsp/$(BSP_NAME)/Modules +ifeq ($(wildcard $(MODULES_FILE_BSP)),) + $(error No BSP name defined or no BSP Modules file available) +endif + +include $(MODULES_FILE_BSP) +VPATH += kern/arm/bsp/$(BSP_NAME) +PREPROCESS_PARTS += $(PREPROCESS_PARTS-y) + +ifeq ("$(filter LIBUART, $(SUBSYSTEMS))","LIBUART") + LIBUART := uart/libuart.a +endif + +ifneq ($(CONFIG_MP),) +ifeq ($(MPCORE_PHYS_BASE),) +$(error $(MODULES_FILE_BSP) needs to set MPCORE_PHYS_BASE variable) +endif +endif + +MODULES_FILES = $(MODULES_FILE) $(MODULES_FILE_BSP) diff --git a/kernel/fiasco/src/Modules.generic b/kernel/fiasco/src/Modules.generic new file mode 100644 index 00000000..df7bf949 --- /dev/null +++ b/kernel/fiasco/src/Modules.generic @@ -0,0 +1,29 @@ +INTERFACES_KERNEL := cpu_mask rcupdate kobject_mapdb context_base \ + mem_region per_cpu_data startup boot_info \ + queue queue_item l4_buf_iter bitmap \ + mapping spin_lock mapping_tree mappable \ + dbg_page_info mapdb pic kobject_dbg koptions \ + kobject_iface kobject ready_queue_wfq \ + ready_queue_fp obj_space ptab_base ram_quota \ + ref_ptr ref_obj mem_space space \ + vlog kmem kmem_alloc slab_cache mem_layout \ + kmem_slab switch_lock kip_init \ + thread_lock helping_lock cpu_lock timer timeout \ + ipc_timeout timeslice_timeout per_cpu_data_alloc \ + vcpu kobject_helper icu_helper thread_state \ + context mp_lock sender receiver mem_unit factory \ + lock ipc_sender thread thread_object syscalls \ + kernel_thread map_util irq banner warn \ + app_cpu_thread globals watchdog kernel_uart \ + main config vmem_alloc paging fpu \ + fpu_state fpu_alloc cpu entry_frame \ + kernel_console ipc_gate task sigma0_task \ + kernel_task \ + irq_controller irq_chip irq_mgr terminate \ + continuation timer_tick \ + sched_context utcb_init perf_cnt trap_state \ + buddy_alloc vkey kdb_ke prio_list ipi scheduler \ + clock vm_factory sys_call_page boot_alloc + +syscalls_IMPL := syscalls syscalls-log +timer_tick_IMPL := timer_tick diff --git a/kernel/fiasco/src/Modules.ia32 b/kernel/fiasco/src/Modules.ia32 new file mode 100644 index 00000000..746771da --- /dev/null +++ b/kernel/fiasco/src/Modules.ia32 @@ -0,0 +1,448 @@ +# -*- makefile -*- + +include $(srcdir)/Modules.generic + +SUBSYSTEMS = JABI ABI DRIVERS KERNEL CRT0 BOOT LIBK \ + CHECKSUM CXXLIB MINILIBC LIBKERN TCBOFFSET VERSION GBLCFG + +ifeq ("$(CONFIG_GSTABS)","y") + SUBSYSTEMS += LINES +endif + +PREPROCESS_PARTS += arch $(CONFIG_ABI) 32bit iofp \ + $(CONFIG_XARCH) apic abs-timeout-hack \ + i8259 pc i8254 fpu \ + abs_syscalls auto_map_kip + +OBJ_SPACE-y = phys +OBJ_SPACE- = virt +OBJ_SPACE = $(OBJ_SPACE-$(CONFIG_DISABLE_VIRT_OBJ_SPACE)) + +PREPROCESS_PARTS += obj_space_$(OBJ_SPACE) + +PREPROCESS_PARTS-$(CONFIG_MP) += mp +PREPROCESS_PARTS-$(CONFIG_LIST_ALLOC_SANITY) += list_alloc_debug +PREPROCESS_PARTS-$(CONFIG_JDB) += debug log +PREPROCESS_PARTS-$(CONFIG_SCHED_PIT) += pit_timer +PREPROCESS_PARTS-$(CONFIG_SCHED_RTC) += rtc_timer +PREPROCESS_PARTS-$(CONFIG_SCHED_APIC) += apic_timer +PREPROCESS_PARTS-$(CONFIG_SCHED_HPET) += hpet_timer +PREPROCESS_PARTS-$(CONFIG_SERIAL) += serial 16550 +PREPROCESS_PARTS-$(CONFIG_WATCHDOG) += watchdog +PREPROCESS_PARTS-$(CONFIG_PERF_CNT) += perf_cnt +PREPROCESS_PARTS-$(CONFIG_IO_PROT) += io +PREPROCESS_PARTS-$(CONFIG_CPU_VIRT) += svm vmx +PREPROCESS_PARTS-$(CONFIG_SCHED_FIXED_PRIO) += sched_fixed_prio +PREPROCESS_PARTS-$(CONFIG_SCHED_WFQ) += sched_wfq +PREPROCESS_PARTS-$(CONFIG_SCHED_FP_WFQ) += sched_fp_wfq + +PREPROCESS_PARTS += $(PREPROCESS_PARTS-y) + +# +# TYPES subsystem +# +PRIVATE_INCDIR += types/$(CONFIG_XARCH) types + +# +# ABI Subsystem +# +ABI := libabi.a +VPATH += abi/$(CONFIG_XARCH) abi +INTERFACES_ABI := l4_fpage l4_msg_item l4_buf_desc kip l4_types \ + l4_error virt + +kip_IMPL := kip kip-debug kip-ia32 kip-ia32-debug +l4_types_IMPL := l4_types l4_types-debug +virt_IMPL := virt-ia32-amd64 + +# +# JABI Subsystem +# +JABI := libjabi.a +VPATH += jabi/$(CONFIG_XARCH) jabi +INTERFACES_JABI := jdb_ktrace + +# +# DRIVERS subsystem +# +DRIVERS := libdrivers.a libgluedriverslibc.a +VPATH += drivers/$(CONFIG_XARCH) drivers +PRIVATE_INCDIR += drivers/$(CONFIG_XARCH) drivers +INTERFACES_DRIVERS := mux_console console keyb io pci vga_console reset \ + processor delayloop mem +ifeq ("$(CONFIG_SERIAL)","y") +INTERFACES_DRIVERS += filter_console uart +endif +reset_IMPL := reset-ia32 +uart_IMPL := uart uart-16550 +CXXSRC_DRIVERS := glue_libc.cc +NOOPT += $(patsubst %.o, %, $(OBJ_DRIVERS)) + +keyb_IMPL := keyb keyb-pc +io_IMPL := io io-ia32 +mem_IMPL := mem mem-ia32 +processor_IMPL := processor processor-ia32 + +# +# KERNEL subsystem +# +KERNEL := fiasco.image +VPATH += kern/$(CONFIG_XARCH) kern/ia32/32 kern/ia32 kern +PRIVATE_INCDIR += kern/$(CONFIG_XARCH) kern/ia32/32 kern/ia32 kern + +INTERFACES_KERNEL += __main acpi irq_chip_ia32 irq_chip_pic io_apic \ + irq_msi boot_console \ + io_space apic pit checksum x86desc gdt idt tss \ + timer_irq dirq + +INTERFACES_KERNEL-$(CONFIG_CPU_VIRT) += svm vmx vm vm_svm vm_vmx + +apic_IMPL := apic-ia32 apic-ia32-mp +boot_console_IMPL := boot_console-ia32-amd64 +boot_info_IMPL := boot_info boot_info-ia32 +clock_IMPL := clock clock-ia32 +config_IMPL := config config-ia32-32 config-ia32 +context_IMPL := context context-ia32 context-ia32-32 context-vcpu +continuation_IMPL := continuation-ia32-32 +cpu_IMPL := cpu cpu-ia32 cpu-32 +dirq_IMPL := dirq-ia32-ux +entry_frame_IMPL := entry_frame entry_frame-ia32-ux \ + entry_frame-abs-timeout-hack +fpu_IMPL := fpu fpu-ia32-ux fpu-ia32 +ipi_IMPL := ipi ipi-ia32 +kdb_ke_IMPL := kdb_ke kdb_ke-ia32 +kernel_thread_IMPL := kernel_thread kernel_thread-std kernel_thread-ia32 +kernel_uart_IMPL := kernel_uart kernel_uart-16550 +kip_init_IMPL := kip_init-ia32 +kmem_IMPL := kmem-ia32 kmem-ia32-32 +kmem_alloc_IMPL := kmem_alloc kmem_alloc-ia32 +main_IMPL := main-ia32-32 main-ia32 +mapping_IMPL := mapping-ia32-32 mapping +map_util_IMPL := map_util map_util-mem map_util-io map_util-objs +mem_layout_IMPL := mem_layout mem_layout-ia32 mem_layout-ia32-32 +mem_space_IMPL := mem_space mem_space-user mem_space-ia32 +mem_unit_IMPL := mem_unit-ia32 +obj_space_IMPL := obj_space obj_space-$(OBJ_SPACE) +paging_IMPL := paging-ia32-32 paging-ia32 paging +perf_cnt_IMPL := perf_cnt perf_cnt-ia32 +pic_IMPL := pic pic-i8259 +pit_IMPL := pit-i8254 +pmem_alloc_IMPL := pmem_alloc pmem_alloc-ia32-ux +rtc_IMPL := rtc-ia32 +sched_context_IMPL := sched_context-wfq sched_context-fixed_prio \ + sched_context-fp_wfq sched_context +space_IMPL := space space-ia32 +spin_lock_IMPL := spin_lock spin_lock-ia32 +startup_IMPL := startup startup-ia32 +sys_call_page_IMPL := sys_call_page sys_call_page-abs-ia32 +task_IMPL := task task-ia32-amd64 +tb_entry_IMPL := tb_entry tb_entry-ia32-32 +timer_IMPL := timer timer-ia32-amd64-ux +thread_IMPL := thread thread-ia32 thread-ia32-32 \ + thread-ipc thread-pagefault thread-log \ + thread-debug thread-dbf thread-vcpu +utcb_init_IMPL := utcb_init utcb_init-ia32 +vmem_alloc_IMPL := vmem_alloc vmem_alloc-ia32 +vm_factory_IMPL := vm_factory vm_factory-ia32 +watchdog_IMPL := watchdog watchdog-ia32 + +INTERFACES_KERNEL-$(CONFIG_SERIAL) += uart_console + +cpu_lock_IMPL := cpu_lock cpu_lock-generic + +ifeq ("$(CONFIG_SCHED_PIT)","y") + timer_IMPL += timer-pit + timer_tick_IMPL += timer_tick-single-vector timer_tick-ia32 +endif +ifeq ("$(CONFIG_SCHED_RTC)","y") + timer_IMPL += timer-rtc + timer_tick_IMPL += timer_tick-single-vector timer_tick-ia32 + INTERFACES_KERNEL += rtc +endif +ifeq ("$(CONFIG_SCHED_APIC)","y") + timer_IMPL += timer-apic + timer_tick_IMPL += timer_tick-apic +endif +ifeq ("$(CONFIG_SCHED_HPET)","y") + timer_IMPL += timer-hpet + timer_tick_IMPL += timer_tick-single-vector timer_tick-ia32 + INTERFACES_KERNEL += hpet +endif + + +ifeq ("$(CONFIG_IO_PROT)","y") + space_IMPL += space-io + sigma0_task_IMPL = sigma0_task sigma0_task-io + thread_IMPL += thread-io +endif + +ifeq ("$(CONFIG_JDB)","y") +JDB := jdb_compound.o +SUBSYSTEMS += JDB +VPATH += jdb/ia32/32 jdb/ia32 jdb +INTERFACES_KERNEL += jdb_tbuf jdb_tbuf_init jdb_trace tb_entry +INTERFACES_JDB += jdb jdb_util jdb_prompt_ext jdb_symbol jdb_lines \ + jdb_dbinfo jdb_bp \ + jdb_module jdb_core jdb_io_ports \ + jdb_kern_info jdb_prompt_module jdb_tbuf_output \ + jdb_input jdb_dump jdb_ptab jdb_misc jdb_mapdb \ + jdb_tcb jdb_attach_irq \ + jdb_trace_set jdb_counters jdb_table kern_cnt \ + tb_entry_output jdb_exit_module \ + jdb_tbuf_show jdb_console_buffer \ + jdb_list jdb_screen push_console jdb_timeout \ + jdb_handler_queue jdb_halt_thread \ + jdb_kern_info_kmem_alloc \ + jdb_kern_info_kip jdb_kern_info_config \ + loadcnt jdb_utcb jdb_thread_list \ + jdb_entry_frame jdb_kobject jdb_space jdb_io_apic \ + jdb_trap_state jdb_ipi jdb_kobject_names \ + jdb_rcupdate jdb_bt jdb_ipc_gate jdb_obj_space \ + jdb_log jdb_factory jdb_iomap \ + jdb_thread jdb_scheduler jdb_sender_list \ + jdb_regex jdb_disasm + +apic_IMPL += apic-debug +jdb_IMPL := jdb jdb-ia32-amd64 jdb-ansi jdb-ia32-ux jdb-thread \ + jdb-int3-ia32-amd64 jdb-int3-ia32-ux +jdb_bp_IMPL := jdb_bp-ia32-ux jdb_bp-ia32-amd64 jdb_bp-ia32 +jdb_bt_IMPL := jdb_bt-ia32-ux +jdb_entry_frame_IMPL := jdb_entry_frame-ia32 +jdb_kern_info_IMPL := jdb_kern_info jdb_kern_info-ia32-amd64 \ + jdb_kern_info-ia32-ux jdb_kern_info-apic \ + jdb_kern_info-pci jdb_kern_info-bench \ + jdb_kern_info-bench-ia32-32 \ + jdb_kern_info-dr jdb_kern_info-mtrr +jdb_misc_IMPL := jdb_misc-ia32-amd64 +jdb_ptab_IMPL := jdb_ptab jdb_ptab-ia32-ux-arm +jdb_screen_IMPL := jdb_screen jdb_screen-ia32 +jdb_tcb_IMPL := jdb_tcb jdb_tcb-ia32-ux +jdb_trace_set_IMPL := jdb_trace_set jdb_trace_set-ia32-ux + +INTERFACES_JDB-$(CONFIG_JDB_MISC) += jdb_tetris + +INTERFACES_JDB += $(INTERFACES_JDB-y) +endif + + +CXXSRC_KERNEL := kernel_panic.cc libc_backend_lock.cc +ASSRC_KERNEL := entry.S entry-native.S sys_call_page-asm.S + +ASSRC_KERNEL-$(CONFIG_MP) += tramp-mp.S entry-mp.S +ASSRC_KERNEL-$(CONFIG_CPU_VIRT) += vm_svm_asm.S vm_vmx_asm.S +ASSRC_KERNEL += $(ASSRC_KERNEL-y) + +NOOPT += $(filter jdb%,\ + $(foreach in,$(INTERFACES_KERNEL), \ + $(if $($(in)_IMPL),$($(in)_IMPL),$(in)))) +NOOPT += tb_entry_output $(tb_entry_IMPL) $(perf_cnt_IMPL) \ + kern_cnt loadcnt $(apic_IMPL) $(watchdog_IMPL) kdb \ + $(kernel_uart_IMPL) push_console virq thread-dbf \ + trap_state +NOOPT += $(foreach in,$(INTERFACES_JDB), \ + $(if $($(in)_IMPL),$($(in)_IMPL),$(in))) + + +### When testing with test threads, uncomment the following: +# +# VPATH += kern-test +# PRIVATE_INCDIR += kern-test +# +# INTERFACES_KERNEL += generic_test_thread test_thread node cpu \ +# back_trace cpu_guard types +# +# node_IMPL := node node-up +# cpu_IMPL := cpu cpu-perf cpu-perfp4 +# config_IMPL := config config-test +# +# kernel_thread_IMPL := $(filter-out kernel_thread-std,$(kernel_thread_IMPL)) \ +# kernel_thread-test +# +# Replace this definition with your own test thread. +# test_thread_IMPL := test_thread-test26 +# +### End of test-thread section + +# +# CRT0 subsystem +# +CRT0 := crt0.o +ASSRC_CRT0 := crt0.S + +# +# BOOT subsystem +# +BOOT := main +VPATH += boot/$(CONFIG_XARCH) boot +PRIVATE_INCDIR += boot boot/ia32 +CXXSRC_BOOT := boot_libc_glue.cc bootstrap.cc boot_cpu.cc \ + direct_cons_putchar.cc +ASSRC_BOOT := boot.S boot_idt.S +NOOPT += $(patsubst %.o, %, $(OBJ_BOOT)) + +# +# TCBOFFSET subsystem +# +TCBOFFSET := tcboffset.h +CXXSRC_TCBOFFSET := tcboffset.cc dump_tcboffsets.cc + +# +# SYMBOLS subsystem +# +SYMBOLS := Symbols + +# +# LINES subsystem +# +LINES := Lines +PROG_LINES := genlines + +# +# CHECKSUM subsystem +# +CHECKSUM := checksum +CXXSRC_CHECKSUM := genchecksum.cc + +# +# VERSION subsystem +# +VERSION := version.h + +# +# GBLCFG subsystem +# +GBLCFG := gblcfg.o +OBJ_KERNEL += gblcfg.o + +# +# CXXLIB Subsystem +# + +CXXLIB := libcxx.a +VPATH += lib/cxxlib +INTERFACES_CXXLIB := paranoia s_cruft + +# +# LIBK subsystem +# +LIBK := libk.a +VPATH += lib/libk/$(CONFIG_XARCH) lib/libk +PRIVATE_INCDIR += lib/libk/$(CONFIG_XARCH) lib/libk +INTERFACES_LIBK := atomic lock_guard auto_ptr std_macros +CSRC_LIBK += gcc_lib.c +CXXSRC_LIBK += construction.cc + +# +# LIBKERN Subsystem +# +LIBKERN := libkern.a +VPATH += lib/kern +PRIVATE_INCDIR += lib/kern/include +CSRC_LIBKERN := +NOOPT += $(patsubst %.o, %, $(OBJ_LIBKERN)) + + +# +# LIBGZIP subsystem (only for Jdb) +# +ifneq ($(CONFIG_JDB_GZIP),) + LIBGZIP := libgzip.a + VPATH += lib/gzip + PRIVATE_INCDIR += lib/gzip + CSRC_LIBGZIP := adler32.c crc32.c gzip.c trees.c deflate.c zutil.c + NOOPT += $(patsubst %.o, %, $(OBJ_LIBGZIP)) +endif + +# +# LIBDISASM subsystem (only for Jdb) +# +ifeq ("$(CONFIG_JDB_DISASM)","y") + # $(srcdir)/lib/disasm may be removed + ifeq ($(wildcard $(srcdir)/lib/disasm),) + $(error $(srcdir)/lib/disasm is missing, disable CONFIG_JDB_DISASM) + endif + + SUBSYSTEMS += LIBDISASM + KERNEL_EXTRA_LIBS += $(LIBDISASM) + PREPROCESS_PARTS += jdb_disasm + + LIBDISASM := libdisasm.a + VPATH += lib/disasm lib/disasm/elf lib/disasm/include \ + lib/disasm/include/opcode lib/disasm/opcodes \ + lib/disasm/libiberty lib/disasm/bfd + PRIVATE_INCDIR += lib/disasm lib/disasm/elf lib/disasm/include \ + lib/disasm/include/opcode lib/disasm/opcodes \ + lib/disasm/libiberty lib/disasm/bfd + PRIVATE_INCDIR += lib/disasm + CXXSRC_LIBDISASM := disasm.cc + CSRC_LIBDISASM := dis-init.c i386-dis.c dis-buf.c + NOOPT += $(patsubst %.o, %, $(OBJ_LIBDISASM)) +endif + +# +# LIBPERFCTR subsystem (only for Jdb) +# +LIBPERFCTR := libperfctr.a +VPATH += lib/perfctr +PRIVATE_INCDIR += lib/perfctr +CSRC_LIBPERFCTR := event_set_p5.c event_set_p6.c event_set_amd.c \ + event_set_p4.c event_set_x86.c perfctr.c \ + event_set_centaur.c +NOOPT += $(patsubst %.o, %, $(OBJ_LIBPERFCTR)) + +# +# LIBREGEX subsystem (only for Jdb) +# +LIBREGEX := libregex.a +VPATH += lib/regex +PRIVATE_INCDIR += lib/regex +CSRC_LIBREGEX := alloc.c rx.c +NOOPT += $(patsubst %.o, %, $(OBJ_LIBREGEX)) + +# +# MINILIBC Subsystem +# +MINILIBC := libc.a +VPATH += lib/minilibc/$(CONFIG_XARCH) lib/minilibc +PRIVATE_INCDIR += lib/minilibc/$(CONFIG_XARCH)/include lib/minilibc/include +CSRC_MINILIBC := atexit.c memccpy.c memcmp.c memmove.c memset.c memcpy.c \ + memchr.c strchr.c strcmp.c strcpy.c strlen.c strncmp.c \ + strncpy.c strstr.c __assert_fail.c printf.c __v_printf.c \ + vprintf.c strtol.c strtoul.c lltostr.c __ltostr.c \ + putchar.c puts.c getchar.c gets.c sprintf.c \ + snprintf.c vsnprintf.c vsprintf.c longjmp.c isalnum.c \ + isalpha.c isascii.c isblank.c iscntrl.c isdigit.c \ + isgraph.c islower.c isprint.c ispunct.c isspace.c \ + isupper.c isxdigit.c tolower.c strcspn.c strspn.c panic.c +ASSRC_MINILIBC := setjmp.S + +# do not profile all of MINILIBC, because it is used in the BOOT subsystem +NOOPT += $(patsubst %.o, %, $(OBJ_MINILIBC)) + +ifeq ("$(CONFIG_JDB)","y") + +ifneq ($(CONFIG_JDB_GZIP),) + ifneq ($(wildcard $(srcdir)/lib/gzip),) + SUBSYSTEMS += LIBGZIP + KERNEL_EXTRA_LIBS += $(LIBGZIP) + INTERFACES_KERNEL += jdb_gzip + endif +endif + +ifneq ($(wildcard $(srcdir)/lib/perfctr),) + SUBSYSTEMS += LIBPERFCTR + KERNEL_EXTRA_LIBS += $(LIBPERFCTR) + KERNEL_UNRES_SYMS += -u perfctr_set_cputype +endif + +ifneq ($(wildcard $(srcdir)/lib/regex),) + SUBSYSTEMS += LIBREGEX + KERNEL_EXTRA_LIBS += $(LIBREGEX) + PREPROCESS_PARTS += jdb_regex +endif + +endif + +MODULES_FILES = $(MODULES_FILE) $(MODULES_FILE_BSP) + +INTERFACES_KERNEL += $(INTERFACES_KERNEL-y) diff --git a/kernel/fiasco/src/Modules.ppc32 b/kernel/fiasco/src/Modules.ppc32 new file mode 100644 index 00000000..8802d384 --- /dev/null +++ b/kernel/fiasco/src/Modules.ppc32 @@ -0,0 +1,259 @@ +# -*- makefile -*- + +############################################################################### + +include $(srcdir)/Modules.generic + +SUBSYSTEMS := ABI KERNEL LIBUART LIBK DRIVERS MINILIBC CXXLIB CRT0 \ + VERSION JABI TCBOFFSET + + +PREPROCESS_PARTS += $(CONFIG_XARCH) $(CONFIG_ABI) 32bit \ + abs_syscalls big_endian jdb_thread_names \ + obj_space_phys + +PREPROCESS_PARTS-$(CONFIG_SERIAL) += serial +PREPROCESS_PARTS-$(CONFIG_JDB) += debug jdb log +PREPROCESS_PARTS-$(CONFIG_SCHED_FIXED_PRIO) += sched_fixed_prio +PREPROCESS_PARTS-$(CONFIG_SCHED_WFQ) += sched_wfq +PREPROCESS_PARTS-$(CONFIG_SCHED_FP_WFQ) += sched_fp_wfq +PREPROCESS_PARTS += $(PREPROCESS_PARTS-y) + +# +# TYPES subsystem +# +PRIVATE_INCDIR += types/$(CONFIG_XARCH) types + +# +# LIBUART subsystem +# +ifeq ("$(filter LIBUART, $(SUBSYSTEMS))","LIBUART") +LIBUART := uart/libuart.a +PREPROCESS_PARTS += libuart +endif + +OBJECTS_LIBUART += uart_of.o uart_mpc52xx.o +VPATH_LIBUART := $(srcdir)/lib/uart +PRIVATE_INCDIR += lib/uart drivers/$(CONFIG_XARCH)/include + +# +# DRIVERS Subsystem +# +DRIVERS := libdrivers.a libgluedriverslibc.a +VPATH += drivers/$(CONFIG_XARCH) drivers +PRIVATE_INCDIR += drivers/$(CONFIG_XARCH) drivers +INTERFACES_DRIVERS := mux_console console mem reset uart filter_console \ + processor delayloop io +io_IMPL := io io-ppc32 +mem_IMPL := mem mem-ppc32 +uart_IMPL := uart uart-mmio +reset_IMPL := reset-ppc32 +processor_IMPL := processor processor-ppc32 +CXXSRC_DRIVERS := glue_libc.cc +NOOPT += $(patsubst %.o, %, $(OBJ_DRIVERS)) + +# +# MINILIBC Subsystem +# +MINILIBC := libc.a +VPATH += lib/minilibc/$(CONFIG_XARCH) lib/minilibc +PRIVATE_INCDIR += lib/minilibc/$(CONFIG_XARCH)/include lib/minilibc/include +CSRC_MINILIBC := atexit.c memccpy.c memcmp.c memmove.c memset.c memcpy.c \ + memchr.c panic.c strchr.c strcmp.c strcpy.c strlen.c \ + strncmp.c strncpy.c strstr.c __assert_fail.c printf.c \ + __v_printf.c vprintf.c strtol.c strtoul.c __lltostr.c \ + __ltostr.c putchar.c puts.c getchar.c gets.c \ + sprintf.c snprintf.c vsnprintf.c vsprintf.c \ + longjmp.c isalnum.c isalpha.c isascii.c isblank.c \ + iscntrl.c isdigit.c isgraph.c islower.c isprint.c \ + ispunct.c isspace.c isupper.c isxdigit.c strspn.c \ + strcspn.c tolower.c +ASSRC_MINILIBC := setjmp.S +NOOPT += $(patsubst %.o, %, $(OBJ_MINILIBC)) + + +# +# JABI Subsystem +# +JABI := libjabi.a +VPATH += jabi/$(CONFIG_XARCH) jabi +INTERFACES_JABI := jdb_ktrace + + +# +# ABI Subsystem +# +ABI := libabi.a +VPATH += abi/$(CONFIG_XARCH) abi +INTERFACES_ABI := kip l4_types l4_fpage l4_msg_item l4_buf_desc l4_error + +kip_IMPL := kip kip-debug kip-ppc32 +l4_types_IMPL := l4_types l4_types-debug + +# +# KERNEL subsystem +# +KERNEL := fiasco +KERNEL_EXTRA := Symbols +VPATH += kern/$(CONFIG_XARCH) kern +VPATH += jdb/$(CONFIG_XARCH) jdb +PRIVATE_INCDIR += kern/$(CONFIG_XARCH) kern kern/ia32 + +INTERFACES_KERNEL += boot_uart_init bootstrap decrementer msr ppc_types \ + util utcb_support irq_chip_generic dirq + +INTERFACES_KERNEL-$(CONFIG_SERIAL) += uart_console + +INTERFACES_KERNEL += $(INTERFACES_KERNEL-y) + + +boot_info_IMPL := boot_info boot_info-ppc32 +clock_IMPL := clock +config_IMPL := config config-ppc32 +context_IMPL := context context-ppc32 context-vcpu +continuation_IMPL := continuation-ppc32 +cpu_IMPL := cpu cpu-ppc32 +cpu_lock_IMPL := cpu_lock cpu_lock-generic +dirq_IMPL := dirq-ppc32 +entry_frame_IMPL := entry_frame entry_frame-ppc32 +kdb_ke_IMPL := kdb_ke kdb_ke-ppc32 +kernel_task_IMPL := kernel_task kernel_task-ppc32 +kernel_thread_IMPL := kernel_thread kernel_thread-std kernel_thread-ppc32 +kernel_uart_IMPL := kernel_uart kernel_uart-ppc32 +kmem_alloc_IMPL := kmem_alloc kmem_alloc-ppc32 +map_util_IMPL := map_util map_util-mem map_util-objs +mapping_IMPL := mapping-ppc32 mapping +mem_layout_IMPL := mem_layout mem_layout-ppc32 +mem_unit_IMPL := mem_unit-ppc32 +mem_space_IMPL := mem_space mem_space-user mem_space-ppc32 \ + mem_space-htab mem_space-cache +obj_space_IMPL := obj_space obj_space-phys +paging_IMPL := paging-ppc32 paging +pic_IMPL := pic +sched_context_IMPL := sched_context-wfq sched_context-fixed_prio \ + sched_context-fp_wfq sched_context +space_IMPL := space space-ppc32 +startup_IMPL := startup startup-ppc32 +sys_call_page_IMPL := sys_call_page sys_call_page-ppc32 +task_IMPL := task task-ppc32 +timer_IMPL := timer timer-decr-ppc32 +timer_tick_IMPL := timer_tick timer_tick-ppc32 +thread_IMPL := thread thread-log thread-pagefault \ + thread-ppc32 thread-ipc thread-jdb \ + thread-vcpu +utcb_init_IMPL := utcb_init utcb_init-ppc32 +utcb_support_IMPL := utcb_support utcb_support-ppc32 +vmem_alloc_IMPL := vmem_alloc vmem_alloc-ppc32 +tb_entry_IMPL := tb_entry tb_entry-ppc32 +warn_IMPL := warn warn-ppc32 + + +ifeq ("$(CONFIG_JDB)","y") +JDB := jdb_compound.o +SUBSYSTEMS += JDB +INTERFACES_JDB := jdb jdb_attach_irq jdb_core jdb_scheduler jdb_entry_frame \ + jdb_exit_module jdb_factory jdb_handler_queue \ + jdb_input jdb_ipc_gate jdb_kobject jdb_kobject_names\ + jdb_lines jdb_list jdb_module jdb_prompt_module \ + jdb_obj_space jdb_prompt_ext jdb_screen jdb_space \ + jdb_symbol jdb_table jdb_tcb jdb_thread \ + jdb_thread_list jdb_util kern_cnt \ + push_console jdb_regex jdb_disasm jdb_bp \ + jdb_tbuf_output \ + jdb_tbuf_show tb_entry_output + +INTERFACES_KERNEL += jdb_tbuf jdb_tbuf_init tb_entry jdb_trace + +jdb_IMPL := jdb jdb-ansi jdb-ppc32 jdb-thread +jdb_tcb_IMPL := jdb_tcb jdb_tcb-ppc32 +jdb_entry_frame_IMPL := jdb_entry_frame-ppc32 +jdb_bp := jdb_bp +thread_IMPL += thread-debug + +INTERFACES_JDB += $(INTERFACES_JDB-y) +endif + +CXXSRC_KERNEL := kernel_panic.cc libc_backend_lock.cc +ASSRC_KERNEL := exception.S phys_mem.S + +NOOPT += $(filter jdb%,\ + $(foreach in,$(INTERFACES_KERNEL), \ + $(if $($(in)_IMPL),$($(in)_IMPL),$(in)))) +NOOPT += tb_entry #tb_entry_output + +# +# CRT0 subsystem +# +CRT0 := crt0.o +ASSRC_CRT0 := crt0.S + + +# +# CXXLIB Subsystem +# +CXXLIB := libcxx.a +VPATH += lib/cxxlib +INTERFACES_CXXLIB := paranoia s_cruft + +# +# LIBK subsystem +# +LIBK := libk.a +VPATH += lib/libk/$(CONFIG_XARCH) lib/libk +PRIVATE_INCDIR += lib/libk/$(CONFIG_XARCH) lib/libk + +INTERFACES_LIBK := auto_ptr atomic lock_guard std_macros +CXXSRC_LIBK += construction.cc +atomic_IMPL := atomic atomic-ppc32 + +# +# LIBDISASM subsystem (only for Jdb) +# +ifeq ("$(CONFIG_JDB_DISASM)","y") + # $(srcdir)/lib/disasm may be removed + ifeq ($(wildcard $(srcdir)/lib/disasm),) + $(error $(srcdir)/lib/disasm is missing, disable CONFIG_JDB_DISASM) + endif + SUBSYSTEMS += LIBDISASM + KERNEL_EXTRA_LIBS += $(LIBDISASM) + PREPROCESS_PARTS += jdb_disasm + + LIBDISASM := libdisasm.a + VPATH += lib/disasm lib/disasm/elf lib/disasm/include \ + lib/disasm/include/opcode lib/disasm/opcodes \ + lib/disasm/libiberty lib/disasm/bfd + PRIVATE_INCDIR += lib/disasm lib/disasm/elf lib/disasm/include \ + lib/disasm/include/opcode lib/disasm/opcodes \ + lib/disasm/libiberty lib/disasm/bfd + PRIVATE_INCDIR += lib/disasm + CXXSRC_LIBDISASM := disasm.cc + CSRC_LIBDISASM := ppc-dis.c ppc-opc.c dis-init.c dis-buf.c \ + safe-ctype.c libbfd.c + NOOPT += $(patsubst %.o, %, $(OBJ_LIBDISASM)) +endif + +# +# VERSION subsystem +# +VERSION := version.h + +TCBOFFSET := tcboffset.h +CXXSRC_TCBOFFSET := tcboffset.cc dump_tcboffsets.cc + +# +# BSP subsystem +# +BSP_NAME := $(patsubst "%",%,$(CONFIG_BSP_NAME)) +MODULES_FILE_BSP := $(srcdir)/kern/ppc32/bsp/$(BSP_NAME)/Modules +ifeq ($(wildcard $(MODULES_FILE_BSP)),) + $(error No BSP name defined or no BSP Modules file available) +endif + +include $(MODULES_FILE_BSP) +VPATH += kern/ppc32/bsp/$(BSP_NAME) kern/ppc32/bsp + +ifeq ("$(filter LIBUART, $(SUBSYSTEMS))","LIBUART") + LIBUART := uart/libuart.a +endif + +MODULES_FILES = $(MODULES_FILE) $(MODULES_FILE_BSP) diff --git a/kernel/fiasco/src/Modules.sparc b/kernel/fiasco/src/Modules.sparc new file mode 100644 index 00000000..ea488ed6 --- /dev/null +++ b/kernel/fiasco/src/Modules.sparc @@ -0,0 +1,257 @@ +# -*- makefile -*- + +############################################################################### + +include $(srcdir)/Modules.generic + +SUBSYSTEMS := ABI KERNEL LIBUART LIBK DRIVERS MINILIBC CXXLIB CRT0 \ + VERSION JABI TCBOFFSET + + +PREPROCESS_PARTS += $(CONFIG_XARCH) $(CONFIG_ABI) 32bit \ + abs_syscalls big_endian jdb_thread_names \ + obj_space_phys + +PREPROCESS_PARTS-$(CONFIG_SERIAL) += serial +PREPROCESS_PARTS-$(CONFIG_JDB) += debug jdb log +PREPROCESS_PARTS-$(CONFIG_SCHED_FIXED_PRIO) += sched_fixed_prio +PREPROCESS_PARTS-$(CONFIG_SCHED_WFQ) += sched_wfq +PREPROCESS_PARTS-$(CONFIG_SCHED_FP_WFQ) += sched_fp_wfq +PREPROCESS_PARTS += $(PREPROCESS_PARTS-y) + +# +# TYPES subsystem +# +PRIVATE_INCDIR += types/$(CONFIG_XARCH) types + +# +# LIBUART subsystem +# +ifeq ("$(filter LIBUART, $(SUBSYSTEMS))","LIBUART") +LIBUART := uart/libuart.a +PREPROCESS_PARTS += libuart +endif + +OBJECTS_LIBUART += uart_leon3.o +VPATH_LIBUART := $(srcdir)/lib/uart +PRIVATE_INCDIR += lib/uart drivers/$(CONFIG_XARCH)/include + +# +# DRIVERS Subsystem +# +DRIVERS := libdrivers.a libgluedriverslibc.a +VPATH += drivers/$(CONFIG_XARCH) drivers +PRIVATE_INCDIR += drivers/$(CONFIG_XARCH) drivers +INTERFACES_DRIVERS := mux_console console mem reset uart filter_console \ + processor delayloop io +io_IMPL := io io-sparc +mem_IMPL := mem mem-sparc +reset_IMPL := reset-sparc +processor_IMPL := processor processor-sparc +uart_IMPL := uart uart-asi +CXXSRC_DRIVERS := glue_libc.cc +NOOPT += $(patsubst %.o, %, $(OBJ_DRIVERS)) + +# +# MINILIBC Subsystem +# +MINILIBC := libc.a +VPATH += lib/minilibc/$(CONFIG_XARCH) lib/minilibc +PRIVATE_INCDIR += lib/minilibc/$(CONFIG_XARCH)/include lib/minilibc/include +CSRC_MINILIBC := atexit.c memccpy.c memcmp.c memmove.c memset.c memcpy.c \ + memchr.c panic.c strchr.c strcmp.c strcpy.c strlen.c \ + strncmp.c strncpy.c strstr.c __assert_fail.c printf.c \ + __v_printf.c vprintf.c strtol.c strtoul.c __lltostr.c \ + __ltostr.c putchar.c puts.c getchar.c gets.c \ + sprintf.c snprintf.c vsnprintf.c vsprintf.c \ + longjmp.c isalnum.c isalpha.c isascii.c isblank.c \ + iscntrl.c isdigit.c isgraph.c islower.c isprint.c \ + ispunct.c isspace.c isupper.c isxdigit.c strspn.c \ + strcspn.c tolower.c +ASSRC_MINILIBC := setjmp.S +NOOPT += $(patsubst %.o, %, $(OBJ_MINILIBC)) + + +# +# JABI Subsystem +# +JABI := libjabi.a +VPATH += jabi/$(CONFIG_XARCH) jabi +INTERFACES_JABI := jdb_ktrace + + +# +# ABI Subsystem +# +ABI := libabi.a +VPATH += abi/$(CONFIG_XARCH) abi +INTERFACES_ABI := kip l4_types l4_fpage l4_msg_item l4_buf_desc l4_error + +kip_IMPL := kip kip-debug kip-sparc +l4_types_IMPL := l4_types l4_types-debug + +# +# KERNEL subsystem +# +KERNEL := fiasco +KERNEL_EXTRA := Symbols +VPATH += kern/$(CONFIG_XARCH) kern +VPATH += jdb/$(CONFIG_XARCH) jdb +PRIVATE_INCDIR += kern/$(CONFIG_XARCH) kern kern/ia32 + +INTERFACES_KERNEL += boot_uart_init bootstrap decrementer psr sparc_types \ + util utcb_support irq_chip_generic + +INTERFACES_KERNEL-$(CONFIG_SERIAL) += uart_console + +INTERFACES_KERNEL += $(INTERFACES_KERNEL-y) + + +boot_info_IMPL := boot_info boot_info-sparc +clock_IMPL := clock +config_IMPL := config config-sparc +context_IMPL := context context-sparc context-vcpu +continuation_IMPL := continuation-sparc +cpu_IMPL := cpu cpu-sparc +cpu_lock_IMPL := cpu_lock cpu_lock-generic +dirq_IMPL := dirq-sparc +entry_frame_IMPL := entry_frame entry_frame-sparc +kdb_ke_IMPL := kdb_ke kdb_ke-sparc +kernel_task_IMPL := kernel_task kernel_task-sparc +kernel_thread_IMPL := kernel_thread kernel_thread-std kernel_thread-sparc +kernel_uart_IMPL := kernel_uart kernel_uart-sparc +kmem_alloc_IMPL := kmem_alloc kmem_alloc-sparc +map_util_IMPL := map_util map_util-mem map_util-objs +mapping_IMPL := mapping-sparc mapping +mem_layout_IMPL := mem_layout mem_layout-sparc +mem_unit_IMPL := mem_unit-sparc +mem_space_IMPL := mem_space mem_space-user mem_space-sparc +obj_space_IMPL := obj_space obj_space-phys +paging_IMPL := paging-sparc paging +pic_IMPL := pic +sched_context_IMPL := sched_context-wfq sched_context-fixed_prio \ + sched_context-fp_wfq sched_context +space_IMPL := space space-sparc +startup_IMPL := startup startup-sparc +sys_call_page_IMPL := sys_call_page sys_call_page-sparc +task_IMPL := task task-sparc +timer_IMPL := timer timer-decr-sparc +thread_IMPL := thread thread-log thread-pagefault \ + thread-sparc thread-ipc thread-jdb \ + thread-vcpu +utcb_init_IMPL := utcb_init utcb_init-sparc +utcb_support_IMPL := utcb_support utcb_support-sparc +vmem_alloc_IMPL := vmem_alloc vmem_alloc-sparc +tb_entry_IMPL := tb_entry tb_entry-sparc +warn_IMPL := warn warn-sparc + + +ifeq ("$(CONFIG_JDB)","y") +JDB := jdb_compound.o +SUBSYSTEMS += JDB +INTERFACES_JDB := jdb jdb_attach_irq jdb_core jdb_scheduler jdb_entry_frame \ + jdb_exit_module jdb_factory jdb_handler_queue \ + jdb_input jdb_ipc_gate jdb_kobject jdb_kobject_names\ + jdb_lines jdb_list jdb_module jdb_prompt_module \ + jdb_obj_space jdb_prompt_ext jdb_screen jdb_space \ + jdb_symbol jdb_table jdb_tcb jdb_thread \ + jdb_thread_list jdb_util kern_cnt \ + push_console jdb_regex jdb_disasm jdb_bp \ + jdb_tbuf_output \ + jdb_tbuf_show tb_entry_output + +INTERFACES_KERNEL += jdb_tbuf jdb_tbuf_init tb_entry jdb_trace + +jdb_IMPL := jdb jdb-ansi jdb-sparc jdb-thread +jdb_tcb_IMPL := jdb_tcb jdb_tcb-sparc +jdb_entry_frame_IMPL := jdb_entry_frame-sparc +jdb_bp := jdb_bp +thread_IMPL += thread-debug + +INTERFACES_JDB += $(INTERFACES_JDB-y) +endif + +CXXSRC_KERNEL := kernel_panic.cc libc_backend_lock.cc +ASSRC_KERNEL := exceptions.S + +NOOPT += $(filter jdb%,\ + $(foreach in,$(INTERFACES_KERNEL), \ + $(if $($(in)_IMPL),$($(in)_IMPL),$(in)))) +NOOPT += tb_entry #tb_entry_output + +# +# CRT0 subsystem +# +CRT0 := crt0.o +ASSRC_CRT0 := crt0.S + + +# +# CXXLIB Subsystem +# +CXXLIB := libcxx.a +VPATH += lib/cxxlib +INTERFACES_CXXLIB := paranoia s_cruft + +# +# LIBK subsystem +# +LIBK := libk.a +VPATH += lib/libk/$(CONFIG_XARCH) lib/libk +PRIVATE_INCDIR += lib/libk/$(CONFIG_XARCH) lib/libk + +INTERFACES_LIBK := auto_ptr atomic lock_guard std_macros +CXXSRC_LIBK += construction.cc +atomic_IMPL := atomic atomic-sparc + +# +# LIBDISASM subsystem (only for Jdb) +# +ifeq ("$(CONFIG_JDB_DISASM)","y") + # $(srcdir)/lib/disasm may be removed + ifeq ($(wildcard $(srcdir)/lib/disasm),) + $(error $(srcdir)/lib/disasm is missing, disable CONFIG_JDB_DISASM) + endif + SUBSYSTEMS += LIBDISASM + KERNEL_EXTRA_LIBS += $(LIBDISASM) + PREPROCESS_PARTS += jdb_disasm + + LIBDISASM := libdisasm.a + VPATH += lib/disasm lib/disasm/elf lib/disasm/include \ + lib/disasm/include/opcode lib/disasm/opcodes \ + lib/disasm/libiberty lib/disasm/bfd + PRIVATE_INCDIR += lib/disasm lib/disasm/elf lib/disasm/include \ + lib/disasm/include/opcode lib/disasm/opcodes \ + lib/disasm/libiberty lib/disasm/bfd + PRIVATE_INCDIR += lib/disasm + CXXSRC_LIBDISASM := disasm.cc + CSRC_LIBDISASM := sparc-dis.c sparc-opc.c dis-init.c dis-buf.c \ + safe-ctype.c libbfd.c + NOOPT += $(patsubst %.o, %, $(OBJ_LIBDISASM)) +endif + +# +# VERSION subsystem +# +VERSION := version.h + +TCBOFFSET := tcboffset.h +CXXSRC_TCBOFFSET := tcboffset.cc dump_tcboffsets.cc + +# +# BSP subsystem +# +BSP_NAME := $(patsubst "%",%,$(CONFIG_BSP_NAME)) +MODULES_FILE_BSP := $(srcdir)/kern/sparc/bsp/$(BSP_NAME)/Modules +ifeq ($(wildcard $(MODULES_FILE_BSP)),) + $(error No BSP name defined or no BSP Modules file available) +endif + +include $(MODULES_FILE_BSP) +VPATH += kern/sparc/bsp/$(BSP_NAME) kern/sparc/bsp + +ifeq ("$(filter LIBUART, $(SUBSYSTEMS))","LIBUART") + LIBUART := uart/libuart.a +endif + +MODULES_FILES = $(MODULES_FILE) $(MODULES_FILE_BSP) diff --git a/kernel/fiasco/src/Modules.ux b/kernel/fiasco/src/Modules.ux new file mode 100644 index 00000000..01004734 --- /dev/null +++ b/kernel/fiasco/src/Modules.ux @@ -0,0 +1,362 @@ +# -*- makefile -*- + +SUBSYSTEMS = JABI ABI DRIVERS KERNEL LIBK CXXLIB JDB \ + TCBOFFSET SYMBOLS VERSION GBLCFG MINILIBC + +ifeq ("$(CONFIG_GSTABS)","y") + SUBSYSTEMS += LINES +endif + +PREPROCESS_PARTS += arch $(CONFIG_ABI) 32bit $(CONFIG_XARCH) \ + fpu jdb_thread_names iofp \ + obj_space_phys abs_syscalls auto_map_kip \ + kernel_can_exit + +PREPROCESS_PARTS-$(CONFIG_MP) += mp +PREPROCESS_PARTS-$(CONFIG_LIST_ALLOC_SANITY) += list_alloc_debug +PREPROCESS_PARTS-$(CONFIG_JDB) += debug log +PREPROCESS_PARTS-$(CONFIG_PERF_CNT) += perf_cnt +PREPROCESS_PARTS-$(CONFIG_CONTEXT_4K) += context_4k +PREPROCESS_PARTS-$(CONFIG_SCHED_FIXED_PRIO) += sched_fixed_prio +PREPROCESS_PARTS-$(CONFIG_SCHED_WFQ) += sched_wfq +PREPROCESS_PARTS-$(CONFIG_SCHED_FP_WFQ) += sched_fp_wfq + +PREPROCESS_PARTS += $(PREPROCESS_PARTS-y) + +# +# TYPES subsystem +# +PRIVATE_INCDIR += types/$(CONFIG_XARCH) types + +# +# ABI Subsystem +# +ABI := libabi.a +VPATH += abi/ia32 abi +INTERFACES_ABI := l4_fpage l4_msg_item l4_buf_desc kip l4_types \ + l4_error + +kip_IMPL := kip kip-ia32 kip-debug kip-ia32-debug +l4_types_IMPL := l4_types l4_types-debug + +# +# JABI Subsystem +# +JABI := libjabi.a +VPATH += jabi/$(CONFIG_XARCH) jabi +INTERFACES_JABI := jdb_ktrace + +# +# DRIVERS subsystem +# +DRIVERS := libdrivers.a +VPATH += drivers/ux drivers/ia32 drivers +PRIVATE_INCDIR += drivers/ux drivers/ia32 drivers +INTERFACES_DRIVERS := mux_console console filter_console processor \ + delayloop mem + +processor_IMPL := processor processor-ux +mem_IMPL := mem mem-ia32 + +# +# KERNEL subsystem +# +KERNEL := fiasco.image +KERNEL_EXTRA := irq0 +VPATH += kern/$(CONFIG_XARCH) kern/ia32/32 kern/ia32 kern +VPATH += jdb/ia32 jdb/ia32/32 jdb/ux jdb +PRIVATE_INCDIR += kern/$(CONFIG_XARCH) kern/ia32/32 kern/ia32 kern + +KERNEL_EXTRA-$(CONFIG_UX_CON) += ux_con +KERNEL_EXTRA-$(CONFIG_UX_NET) += ux_net +KERNEL_EXTRA += $(KERNEL_EXTRA-y) + +# KERNEL modules. + +# Important: The following list must be roughly sorted according to +# link dependencies. The Unit test for a module M links against all +# modules that precede M in this list, minus sibling modules (those +# modules that _directly_ precede M and that M does not include). + +INTERFACES_KERNEL := mem_region simpleio kernel_console panic warn \ + bitmap buddy_alloc koptions context_base \ + mem_layout per_cpu_data globals loader vhw \ + kip_init ipi queue_item queue cpu_mask rcupdate \ + boot_info config jdb_symbol jdb_util \ + tb_entry perf_cnt jdb_tbuf x86desc \ + emulation pic usermode cpu trampoline cpu_lock \ + spin_lock boot_alloc \ + entry_frame continuation \ + kmem mem_unit \ + ram_quota kmem_alloc ptab_base per_cpu_data_alloc \ + ref_ptr ref_obj \ + slab_cache kmem_slab dbg_page_info \ + vmem_alloc paging fpu_state fpu \ + ready_queue_wfq ready_queue_fp \ + sched_context switch_lock timer timeout \ + obj_space kobject_dbg kobject kobject_iface \ + l4_buf_iter lock \ + mem_space space vcpu context \ + helping_lock \ + mp_lock ipc_gate irq_controller \ + mapping mapping_tree mappable \ + mapdb kobject_mapdb map_util \ + hostproc task sigma0_task kernel_task prio_list \ + thread_lock timeslice_timeout \ + ipc_timeout thread_state \ + sender receiver ipc_sender thread thread_object \ + kobject_helper timer_tick \ + syscalls \ + kernel_thread dirq irq_chip irq_mgr \ + irq_chip_ia32 irq_chip_pic \ + banner fpu_alloc irq icu_helper main \ + startup libc_support \ + jdb_dbinfo jdb fb net utcb_init \ + jdb_core jdb_module jdb_table \ + jdb_thread_list jdb_input jdb_dump jdb_thread \ + jdb_lines jdb_tcb jdb_prompt_module jdb_bt \ + jdb_mapdb jdb_ptab jdb_kern_info jdb_counters \ + glibc_getchar jdb_trace jdb_trace_set \ + tb_entry_output jdb_tbuf_init kern_cnt \ + jdb_tbuf_output jdb_tbuf_show \ + jdb_misc checksum watchdog terminate \ + jdb_screen push_console jdb_bp \ + jdb_attach_irq sys_call_page \ + jdb_timeout gdt factory \ + idt tss trap_state jdb_prompt_ext \ + jdb_handler_queue jdb_exit_module \ + jdb_halt_thread jdb_tetris \ + jdb_kern_info_kip \ + jdb_kern_info_kmem_alloc jdb_kern_info_config \ + jdb_space jdb_trap_state \ + vkey jdb_utcb vlog \ + jdb_entry_frame kdb_ke jdb_ipi app_cpu_thread \ + jdb_rcupdate jdb_kobject jdb_kobject_names \ + jdb_list jdb_ipc_gate jdb_obj_space \ + jdb_log jdb_factory scheduler \ + jdb_scheduler clock jdb_sender_list \ + jdb_disasm jdb_regex + + +boot_info_IMPL := boot_info boot_info-ia32 boot_info-ux +clock_IMPL := clock clock-ia32 +config_IMPL := config config-ia32-32 config-ux +context_IMPL := context context-ia32 context-ia32-32 context-ux \ + context-vcpu +continuation_IMPL := continuation-ia32-32-ux +cpu_IMPL := cpu cpu-ia32 cpu-ux cpu-32 +cpu_lock_IMPL := cpu_lock cpu_lock-generic +dirq_IMPL := dirq-ia32-ux +dirq_pic_pin_IMPL := dirq_pic_pin dirq_pic_pin-ia32-ux +entry_frame_IMPL := entry_frame entry_frame-ia32-ux \ + entry_frame-abs-timeout-hack +fpu_IMPL := fpu fpu-ia32-ux fpu-ux +irq_IMPL := irq irq-ux +ipi_IMPL := ipi ipi-ux +jdb_IMPL := jdb jdb-ux jdb-ansi jdb-ia32-ux jdb-thread \ + jdb-int3 jdb-int3-ia32-ux +jdb_tcb_IMPL := jdb_tcb jdb_tcb-ia32-ux +jdb_bp_IMPL := jdb_bp-ia32-ux jdb_bp-ux +jdb_bt_IMPL := jdb_bt-ia32-ux +jdb_entry_frame_IMPL := jdb_entry_frame-ia32 +jdb_kern_info_IMPL := jdb_kern_info jdb_kern_info-ux \ + jdb_kern_info-ia32-ux jdb_kern_info-ia32-amd64 +jdb_misc_IMPL := jdb_misc-ia32-amd64 +jdb_ptab_IMPL := jdb_ptab jdb_ptab-ia32-ux-arm +jdb_screen_IMPL := jdb_screen jdb_screen-ia32 +jdb_trace_set_IMPL := jdb_trace_set jdb_trace_set-ia32-ux +kdb_ke_IMPL := kdb_ke kdb_ke-ia32 +kernel_thread_IMPL := kernel_thread kernel_thread-std kernel_thread-ux +kip_init_IMPL := kip_init-ia32 kip_init-ux +kmem_IMPL := kmem-ia32 kmem-ux +kmem_alloc_IMPL := kmem_alloc kmem_alloc-ia32 +main_IMPL := main-ia32-32 main-ux +mapping_IMPL := mapping-ia32-32 mapping +map_util_IMPL := map_util map_util-mem map_util-objs +mem_layout_IMPL := mem_layout mem_layout-ia32 mem_layout-ux +mem_space_IMPL := mem_space mem_space-user mem_space-ia32 \ + mem_space-ux +mem_unit_IMPL := mem_unit-ux +obj_space_IMPL := obj_space obj_space-phys +paging_IMPL := paging-ia32-32 paging-ia32 paging +perf_cnt_IMPL := perf_cnt perf_cnt-ia32 +pic_IMPL := pic pic-ux +pmem_alloc_IMPL := pmem_alloc pmem_alloc-ia32-ux +sched_context_IMPL := sched_context-wfq sched_context-fixed_prio \ + sched_context-fp_wfq sched_context +space_IMPL := space space-ux +syscalls_IMPL := syscalls syscalls-log +sys_call_page_IMPL := sys_call_page sys_call_page-abs-ux +task_IMPL := task task-ux +tb_entry_IMPL := tb_entry tb_entry-ia32-32 +terminate_IMPL := terminate-ux +thread_IMPL := thread thread-ia32 thread-ia32-32 thread-ux \ + thread-ipc thread-pagefault thread-log \ + thread-debug thread-io thread-vcpu +timer_IMPL := timer timer-ia32-amd64-ux timer-ux +timer_tick_IMPL := timer_tick timer_tick-single-vector timer_tick-ia32 +utcb_init_IMPL := utcb_init utcb_init-ux +vmem_alloc_IMPL := vmem_alloc vmem_alloc-ia32 vmem_alloc-ux +spin_lock_IMPL := spin_lock spin_lock-ia32 + +CXXSRC_KERNEL := libc_backend_nolock.cc glue_libc_ux.cc +ASSRC_KERNEL := entry-ux.S entry.S sighandler.S \ + sys_call_page-asm.S + +ifeq ($(CONFIG_MP),y) +ASSRC_KERNEL += tramp-mp.S entry-mp.S +endif + + +NOOPT += $(filter jdb%,\ + $(foreach in,$(INTERFACES_KERNEL), \ + $(if $($(in)_IMPL),$($(in)_IMPL),$(in)))) +NOOPT += tb_entry tb_entry_output + +# +# TCBOFFSET subsystem +# +TCBOFFSET := tcboffset.h +CXXSRC_TCBOFFSET := tcboffset.cc dump_tcboffsets.cc + +# +# SYMBOLS subsystem +# +SYMBOLS := Symbols + +# +# LINES subsystem +# +LINES := Lines +PROG_LINES := genlines + +# +# VERSION subsystem +# +VERSION := version.h + +# +# GBLCFG subsystem +# +GBLCFG := gblcfg.o +OBJ_KERNEL += gblcfg.o + +# +# CXXLIB Subsystem +# +CXXLIB := libcxx.a +VPATH += lib/cxxlib +INTERFACES_CXXLIB := s_cruft paranoia + +# +# LIBK subsystem +# +LIBK := libk.a +VPATH += lib/libk/$(CONFIG_XARCH) lib/libk +PRIVATE_INCDIR += lib/libk/$(CONFIG_XARCH) lib/libk +INTERFACES_LIBK := atomic lock_guard auto_ptr std_macros +CXXSRC_LIBK += construction.cc + + +ifneq ($(CONFIG_JDB_GZIP),) + ifneq ($(wildcard $(srcdir)/lib/gzip),) + SUBSYSTEMS += LIBGZIP + KERNEL_EXTRA_LIBS += $(LIBGZIP) + INTERFACES_KERNEL += jdb_gzip + LIBGZIP := libgzip.a + + VPATH += lib/gzip + PRIVATE_INCDIR += lib/gzip + CSRC_LIBGZIP := adler32.c crc32.c gzip.c trees.c deflate.c zutil.c + NOOPT += $(patsubst %.o, %, $(OBJ_LIBGZIP)) + endif +endif + +# +# LIBDISASM subsystem (only for Jdb) +# +ifeq ("$(CONFIG_JDB_DISASM)","y") + # $(srcdir)/lib/disasm may be removed + ifeq ($(wildcard $(srcdir)/lib/disasm),) + $(error $(srcdir)/lib/disasm is missing, disable CONFIG_JDB_DISASM) + endif + + SUBSYSTEMS += LIBDISASM + KERNEL_EXTRA_LIBS += $(LIBDISASM) + PREPROCESS_PARTS += jdb_disasm + + LIBDISASM := libdisasm.a + VPATH += lib/disasm lib/disasm/elf lib/disasm/include \ + lib/disasm/include/opcode lib/disasm/opcodes \ + lib/disasm/libiberty lib/disasm/bfd + PRIVATE_INCDIR += lib/disasm lib/disasm/elf lib/disasm/include \ + lib/disasm/include/opcode lib/disasm/opcodes \ + lib/disasm/libiberty lib/disasm/bfd + PRIVATE_INCDIR += lib/disasm + CXXSRC_LIBDISASM := disasm.cc + CSRC_LIBDISASM := dis-init.c i386-dis.c dis-buf.c + NOOPT += $(patsubst %.o, %, $(OBJ_LIBDISASM)) +endif + + +# +# LIBPERFCTR subsystem (only for Jdb) +# +LIBPERFCTR := libperfctr.a +VPATH += lib/perfctr +PRIVATE_INCDIR += lib/perfctr +CSRC_LIBPERFCTR := event_set_p5.c event_set_p6.c event_set_amd.c \ + event_set_p4.c event_set_x86.c perfctr.c \ + event_set_centaur.c +NOOPT += $(patsubst %.o, %, $(OBJ_LIBPERFCTR)) + +# +# LIBREGEX subsystem (only for Jdb) +# +LIBREGEX := libregex.a +VPATH += lib/regex +PRIVATE_INCDIR += lib/regex +CSRC_LIBREGEX := alloc.c rx.c +NOOPT += $(patsubst %.o, %, $(OBJ_LIBREGEX)) + +ifneq ($(wildcard $(srcdir)/lib/perfctr),) + SUBSYSTEMS += LIBPERFCTR + KERNEL_EXTRA_LIBS += $(LIBPERFCTR) + KERNEL_UNRES_SYMS += -u perfctr_set_cputype +endif + +ifneq ($(wildcard $(srcdir)/lib/regex),) + SUBSYSTEMS += LIBREGEX + KERNEL_EXTRA_LIBS += $(LIBREGEX) + PREPROCESS_PARTS += jdb_regex +endif + +# +# UNITTEST subsystem +# +# disabled until unittests fixed +SUBSYSTEMS += UNITTEST +VPATH += test/unit + +INTERFACES_UNITTEST += mapdb_t map_util_t + +# Compile all unit tests without -DNDEBUG. +NONDEBUG += $(patsubst %.o, %, $(OBJ_UNITTEST)) + +MODULES_FILES = $(MODULES_FILE) $(MODULES_FILE_BSP) + +# +# MINILIBC Subsystem +# +MINILIBC := libc.a +VPATH += lib/minilibc/ia32 lib/minilibc +CSRC_MINILIBC := printf.c __v_printf.c \ + vprintf.c lltostr.c __ltostr.c \ + putchar.c puts.c gets.c sprintf.c \ + snprintf.c vsnprintf.c vsprintf.c fprintf.c \ + memccpy.c memchr.c memcmp.c memcpy.c memmove.c memset.c \ + strcpy.c strlen.c strstr.c \ +strcmp.c strcspn.c strncmp.c strspn.c + +# do not profile all of MINILIBC, because it is used in the BOOT subsystem +NOOPT += $(patsubst %.o, %, $(OBJ_MINILIBC)) diff --git a/kernel/fiasco/src/README b/kernel/fiasco/src/README new file mode 100644 index 00000000..a7efcd4d --- /dev/null +++ b/kernel/fiasco/src/README @@ -0,0 +1,168 @@ + Fiasco's build system + + Michael Hohmuth + +Motivation +########## + +My main goal when I designed Fiasco's build system was to allow for +multiple configurations of the kernel, based on different +implementations of the same interface, to coexist in multiple object +directories. + + +Configuration +############# + +Fiasco's build system consists of a number of configuration files, and +it also makes use of the L4 source tree's global Make configuration +file, l4/Makeconf. All configuration files are written in Makefile +language. + +:l4/Makeconf: + Global Make rules and search paths + +:l4/kernel/fiasco/src/Makefile: + ``Fiasco's build system'' rules + +:l4/kernel/fiasco/src/Modules.in: + Standard configuration for Fiasco + +: /Modules: + Current configuration for Fiasco + +:l4/kernel/fiasco/src/Makerules.*: + Make rules for each subsystem defined in Modules + +:l4/kernel/fiasco/src/Makerules.local': + (Optional) User-specific configuration files + +:l4/Makeconf.local': + (Optional) User-specific configuration files + +(By default, the object directory is the main source directory, +l4/kernel/fiasco/src/. See the next section on how to use other +object directories with custom configurations.) + +Users configure the build system by creating a Modules file. If no +Modules file exists, the standard configuration Modules.in is copied +to Modules. The build system warns the user if (after a "cvs update") +Modules.in is newer than Modules. + +The Modules file defines a number of subsystems that should be built. +For each subsystem, there must be a Makerules. file that +defines rules for building the subsystem's targets. + +In the remainder of this section, I describe by example the language +used in Modules file and the contents of the Makerules.* files. + +!SUBSYSTEMS = FOO BAR +! # Defines two subsystems, FOO and BAR. This means that there +! # exist two files, Makerules.FOO and Makerules.BAR, that +! # contain rules on how to build the targets of these +! # subsystems. These targets are defined later. +! +!### Definitions for subsystem FOO follow +! +!FOO = foo +! # Defines the main target of subsystem FOO: a file named +! # "foo". +! +!FOO_EXTRA = foo.man +! # (Optional) Defines more targets that should be built for +! # subsystem FOO. +! +!INTERFACES_FOO = foo1 foo2 foo3 +! # (Optional) C++ modules for subsystem FOO (written in +! # `preprocess' format; see +! # ) +! # Each module normally consists of one implementation file +! # such as foo1.cpp -- unless IMPL definitions such as the +! # following ones are given: +! +!foo2_IMPL = foo2 foo2-more +! # (Optional) C++ module foo2 is implemented in two files +! # foo2.cpp and foo2-more.cpp (instead of just foo2.cpp). The +! # public header file generated from these implementation files +! # will be called foo2.h. +! +!foo3_IMPL = foo3-debug +! # (Optional) C++ module foo3 is implemented in foo3-debug.cpp, +! # not foo3.cpp. The public header file generated from this +! # implementation file will be called foo3.h. +! +!CXXSRC_FOO = frob1.cc frob2.cc +! # (Optional) Additional C++ sources for subsystem FOO (not in +! # `preprocess' format) +! +!CSRC_FOO = frob3.c frob4.c +! # (Optional) Additional C sources for subsystem FOO +! +!ASSRC_FOO = frob5.S +! # (Optional) Additional assembly-language sources for +! # subsystem FOO +! +!OBJ_FOO = frob6.o +! # (Optional) Additional objects for subsystem FOO. These +! # objects can be precompiled or generated using custom rules +! # in Makerules.FOO. +! +!NOPROFILE += frob2 +! # (Optional) Basenames of objects that should not be compiled +! # with profiling options in profiling builds. +! +!NOOPT += frob3 +! # (Optional) Basenames of objects that should not be compiled +! # with optimization options. +! +!PRIVATE_INCDIR += incdir +! # (Optional) Add incdir to the include path for all source +! # files. (This feature is implemented by l4/Makeconf.) +! +!VPATH += foodir +! # (Optional) Add foodir to Make's source-file search +! # path. (This feature is implemented internally by Make.) +! +!### Definitions for subsystem BAR follow +!### (similar to FOO's definitions) + + +The Makerules.FOO file usually contains just rules for linking the +subsystem's targets. Additionally, it must contain a rule +"clean-FOO:" that cleans the object directory from files created by +this configuration file. + +It can access the following Make variables: + +:'FOO', 'FOO_EXTRA': + names of targets + +:'OBJ_FOO': + expanded to contain _all_ objects that will be created for subsystem FOO + +:'BAR': + targets of other subsystems + + +Building in separate object directories +####################################### + +It is possible to configure multiple directories, each with its own +Modules file, as separate object directories. (This usage is +supported only if the main source directory [the one containing +Modules.in] is not also used as an object directory.) + +To use a directory as an object directory, create in it a Makefile +like this: + +!srcdir = .. +! +!all: +! +!%: +! $(MAKE) -I $(srcdir) -f $(srcdir)/Makefile \ +! srcdir=$(srcdir) $@ + +Change the "srcdir" definition to point to the main source directory. +You can then create custom Modules files (and custom source files and +Makerules.* files) in each object directory. diff --git a/kernel/fiasco/src/README.style b/kernel/fiasco/src/README.style new file mode 100644 index 00000000..dbc82249 --- /dev/null +++ b/kernel/fiasco/src/README.style @@ -0,0 +1,785 @@ + Fiasco style guide + + Michael Hohmuth + +; To generate a printable version of this document, please type +; cd ../doc/style; make + +Introduction +############ + +Motivation and intended audience +================================ + +This document is meant as a quick reference to a number of guidelines +meant for existing and especially new Fiasco kernel developers. + + +How to follow these rules: Metarules +==================================== + +This document does not differentiate between strict rules and ``soft'' +guidelines. Also, when browsing the source code, you will notice a +large number of deviations from these rules (because most rules are +younger than the current kernel code). In this sense, all rules are +``soft.'' + +However, as the master guideline, when writing new code, please ensure +that the number of rule violations does not grow. (In the future, we +might even enforce this property automatically when someone is +checking in code.) + + +Programming language, dialect, and subset +######################################### + +Fiasco has been written in C++. However, it uses C++ in a special +dialect supported by the Preprocess tool [Hohmuth: Preprocess]. In +effect, programmers do not need to write C++ header files, and do not +need to declare (member) functions -- Preprocess automates these +tasks. + +We use some features of Preprocess for configuration +management---please refer to Section [Configuration-specific source code]. + +Preprocess lacks support for the following C++ features, which +therefore cannot be used in Fiasco source code (but can be used in +third-party source code used, i.e., can be included, by Fiasco): + +* Name spaces --- use static class interfaces or global or static free + functions instead (Section [Singletons]) +* Nested classes --- use forward-declared ``private classes'' instead +* '#ifdef' and + '#if' on file top level, except for + '#if 0' --- use + Preprocess' configuration features instead (Section + [Configuration-specific source code]) + +Some features of C++ are explicitly disallowed because Fiasco contains +no run-time support for them: + +* Exceptions +* Run-time type identification and dynamic_cast + +These features are always disabled on the compiler command line. + +On the other hand, templates are allowed. However, please keep in +mind that Fiasco's source code needs to be interpreted not only by the +latest version of GCC, but also by at least the two preceding stable +versions of GCC, _and_ ---more significantly---by the VFiasco project's +semantics compiler, which is a custom compiler _we_ (in a broader +sense of we) have to maintain. Therefore, using advanced tricks such +as expression templates or partial specialization is strongly +discouraged. + + +Source-code organization and directory structure +################################################ + +Subsystems +========== + +Fiasco consists of a number of subsystems; among them: + +:KERNEL: The kernel proper. This is the part that implements the L4 + specification. + +:ABI: ABI-specific definitions, mostly type definitions and accessor + functions. + +:JDB: The built-in kernel debugger. + +:BOOT: The bootstrapper. This part sets up virtual memory, copies the + kernel to its standard virtual-address-space location (0xf0001000), + and runs the kernel. + +Subsystems are defined in the Modules file, which is the main +configuration file for Fiasco's build system. Please refer to +the build-system documentation [README] for more information on this +build system. + +Directory structure +=================== + +Subsystems usually reside in their own directory under src (the +exception being those subsystems which do not contain any source code, +but which exist only for maintenance purposes). + +Inside each (source-code) subsystem directory such as kern, the +directory layout is as follows: + +:kern/: Source files shared for all Fiasco-supported + architectures + +:kern/shared/: Source files shared by more than one, but not + all architectures. + +:kern/ia32, kern/ia64, kern/ux, and so on: Source files that are + specific for only one architecture. + +Currently, hardware architectures is the only configuration dimension +that motivates moving a source file into a subdirectory. In other +words, source files pertaining to a particular configuration option +(other than hardware architecture), but not another, are located in +one of the mentioned directories. + +Source-file naming +================== + +Usually, source files belong to exactly one module, consisting of one +main C++ class plus, optionally, public utility functions, small +interface classes for exchanging data with the main class, and private +auxiliary classes and functions. A module can be comprised of +multiple source files. These source files all start with the name of +the module's main class, in all lower case (e.g., for class +Thread_state, file names start with the string "thread_state"). When +multiple source files implement one module, each file name (except for +the main file's) add a submodule-specific suffix, separated with a +dash (-). For example: + +* kern/thread.cpp +* kern/thread-ipc.cpp + +Fiasco's build system mandates that all source files (of all +subsystems) have different names, even if they reside in different +directories. To make file names different, our naming convention is +to add architecture-configuration strings to the file names, separated +by dashes (-). For example: + +* kern/thread.cpp +* kern/shared/thread-ia32-ux.cpp +* kern/ia64/thread-ia64.cpp + +Occasionally, it is useful to separate configuration-specific code +into a source file of its own (see Section +[Configuration-specific source code]). In this case, the file name +contains the configuration string as a suffix, separated by dashes +(-). For example: + +* kern/thread-v4.cpp +* kern/thread-v2x0.cpp +* kern/ia32/thread-ia32-smas.cpp + + +Header files and the C++ preprocessor +===================================== + +As Preprocess assumes the task of writing header files, programmers +should not add new header files. The exception to this rule is that +header files are required when defining constants that are needed by +both assembly code and C++ code. + +When using header files, these files must be protected from multiple +inclusions using include-file guards, as in the following example for +the file config_gdt.h: + +! #ifndef CONFIG_GDT_H +! #define CONFIG_GDT_H +! // File contents +! #endif + + +Configuration management +######################## + +The configuration tool +====================== + +The interactive configuration tool is started using "make menuconfig". +The tool creates two files, intended for inclusion in C++ code and in +makefiles: + +:globalconfig.h: This file defines a preprocessor symbol for each + _enabled_ configuration option. + +:globalconfig.out: This file defines a Make variable for set _each_ + configuration option. Variables for enables options are set to "y", + those for disabled options are set to "n". + +Adding new configuration options +-------------------------------- + +Help texts for configuration options in the rules file (rules.cml) are +sorted by order in which the options appear in the menu defined at the +bottom of the file. New configuration options must add such a help text +describing what the config option does. After a new config option +has been added, define under which conditions the config option should +be suppressed, if any. It is generally a good idea to suppress config +options for architectures and configurations where the option is +meaningless. Options which can be suppressed for certain configurations +usually require consistency rules to ensure they are not left in an +undefined state from a previous selection. + +An example suppression rule is: +! when UX suppress SERIAL +The corresponding consistency rule is: +! require UX implies (SERIAL == n) + +This ensures that 'SERIAL' is set to "n" when someone had previously chosen +'IA32' and 'SERIAL' set to "y" and then changes the architecture to 'UX'. + +Do not forget to update the configuration templates in the directory +src/templates after modifying configuration options. + +Class Config +============ + +This class defines boot-time and constant configuration variables for +Fiasco. + +The constant variables can be derived from options the configuration +tool has written to globalconfig.h. As a special exception, '#ifdef' +is allowed here. + +Boot-time configuration variables can be derived from the kernel's +command line (class Cmdline). + +Configuration-specific source code +================================== + +Single or multiple source files +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Source code that is specific to one or a single combination of +configuration options can reside in a separate file or in the same +file as code for other configuration options. The decision of which +works better is in the developer's discretion. Developers should try +to combine logically cohesive code fragments in one source file, even +if the fragments are mutually exclusive. + +Conditional compilation +~~~~~~~~~~~~~~~~~~~~~~~ + +Using preprocessor constants and '#ifdef' for conditional compilation +is only allowed for source code passed to the assembler (assembly +files and header files meant to be included in assembly code). In C++ +source code, this style is discouraged, and Preprocess does not even +support it (for top-level conditional compilation). + +Configuration-specific C++ code blocks are labeled using Preprocess' +configuration-tag feature with 'IMPLEMENTATION' and 'INTERFACE' +directives. + +This feature is available only on file top level. Conditional +compilation inside function or class blocks is not allowed. Instead, +programmers have the following options: + +:For class definitions: + Use Preprocess' 'EXTENSION' feature to extend class data with + configuration-specific contents. + +:For function definitions: + # Create a Boolean constant in class Config that depends on the + configuration option ('#ifdef' is allowed there; see Section + [Class Config]), and use the normal C++ 'if' statement to + conditionalize the code. We rely on the C++ compiler's optimizer + to remove dead code. + # Factor out configuration-specific functions with a common + interface. + + +Compile-time polymorphism +========================= + +Many configurable aspects of Fiasco are implemented as a set of +(member) functions that implement a given interface in a specific way. +However, unlike typical C++ programs, Fiasco usually does not define +these interfaces as abstract base classes and then derives +configuration-specific subclass implementations from them. We have +deemed the overhead of virtual-function calls as too high in many +cases. + +Instead, in Fiasco these interfaces are not declared as virtual +functions, but as nonvirtual functions. These functions are then +defined in configuration-specific 'IMPLEMENTATION' sections, which can +be combined in one file or spread across multiple files (see Section +[Configuration-specific source code]). Preprocess assists in this +kind of compile-time polymorphism by allowing configuration-specific +inline functions and private member functions. + +These interfaces do not need to be split out into separate classes. +It is often useful to have a part of a class interface that is +implemented in a configuration-specific way. + +Usually, Preprocess assumes the task of copying (member-) function +declarations into a module's public header file, and this is our +preferred usage. However, for interfaces that are implemented in a +configuration-specific source-code block, we make an exception: The +``public'' interface (i.e., the interface used by generic client code, +which not necessarily needs consist of only public member functions) +can be declared and documented in the 'INTERFACE' section of the +corresponding module. To prevent Preprocess from adding another +declaration, the definition needs to add the 'IMPLEMENT' directive. +The prerequisite is that the interface is implemented in an +'IMPLEMENTATION' section that depends on _more_ configuration options +than the 'INTERFACE' section containing the declaration. For example: + +! INTERFACE: +! +! class Pic +! { +! public: +! /** +! * Static initalization of the interrupt controller. +! */ +! static void init(); +! // ... +! }; +! +! IMPLEMENTATION[i8259]: +! +! IMPLEMENT +! void +! Pic::init() +! { +! pic_init(0x20,0x28); +! } + +Maintainer-mode configuration +============================= + +Fiasco's build process can be instrumented with a number of checks +that ensure some of the rules defined in this document. Fiasco +developers should enable this option in the interactive configuration +tool; the option is called 'MAINTAINER_MODE' (``Do additional checks +at build time''). + +The checks enabled by this option include: +* Checking for mutual or circular dependencies between modules (see + Section [Dependency management]) +* Checking for use of deallocated initialization data after + initialization time. + + +Dependency management +##################### + +Fiasco has been designed to be configurable and robust. A +precondition for achieving these properties is that modules and +subsystems can be removed from the kernel and tested in isolation, +which in turn depends on the absence of mutual or circular +dependencies between modules and subsystems. + +Therefore, as a rule, these dependencies must be avoided. Please +consult [Lakos: Large-scale C++ Software Design] for standard methods to +resolve circular dependencies. + +The current dependency graph can be generated in text or graphics form +using "make DEPS" and "make DEPS.ps". + + +Source-code style and indentation +################################# + +Naming conventions +================== + +In general, Fiasco developers despise the ugly +MixedCapsNamingConvention made popular by Java. If you really must +use such names, please go hack some Java project, not Fiasco. In +Fiasco, words in multi-word identifier names are generally separated +with underscores, with the sequencing words starting with a lowercase +letter or a digit (the only exception being preprocessor symbols). +Examples: + +! Funky_type +! thread_id +! Thread_ready +! _current_sched +! _thread_0 + +In particular, the conventions are as follows: + +* Type names (class names, typedef names, enum names) all start with a + capital letter. Examples: 'Thread', 'Jdb', 'Boot_info' + +* Function names (both member functions and free functions) start with + a lowercase letter. Examples: 'fpage_map()', 'ipc_send_regs()' + +* Nonstatic member variables start with an underscore (_). Examples: + '_mode', '_ready_time' + +* Other variables (including static member variables, global and local + variables, function-argument names) start with a lower-case letter. + Examples: 'preempter', 'cpu_lock' + +* Enumeration constants start with a capital letter. Examples: + 'Thread_ready', 'Page_writable' + + The Fiasco architecture board has declared that having the same + naming convention for types and constants is not confusing. + +* Preprocessor-symbol identifiers are all-uppercase and start with a + letter. As with all other identifiers, multiple words are separated + using underscores. Examples: 'THREAD_BLOCK_SIZE', 'CONFIG_IA32_486' + + Please note that preprocessor constants are deprecated and allowed + only in assembly files and header files meant to be included in + assembly code (see Section [Constant definitions]). + +(For file-naming conventions refer to Section [Source-file naming].) + +Comments +======== + +All comments must be in English. American / Aussie / Kiwi English are +OK, too, but Pidgin English or Denglisch are not. + +Doxygen comments +~~~~~~~~~~~~~~~~ + +Please document at least all interfaces of all classes that are meant +for client-code use. These interfaces usually include all public and +protected member functions and all nonstatic free functions, but +possibly more if there is a private interface implemented by +configuration-specific code. + +The interface documentation belongs to the function definition, except +if configuration-specific functions (with the 'IMPLEMENT' directive) +are declared in an 'INTERFACE' section. In the that case, the +documentation belongs to the declaration. + +Please use Doxygen's Javadoc-like style (the style using '@' instead +of backslashes) to document your interfaces. Fiasco's documentation +is generated using Doxygen's auto-brief feature, so '@brief' +directives are unnecessary [Heesch: Doxygen Manual]. + +Comment style +~~~~~~~~~~~~~ + +The style of multi-line comments is not prescribed, but please be +consistent within one source file. All of the following forms are +OK: + +! /** The foo function. +! * This function frobnifies its arguments. +! */ +! +! /** +! * The foo function. +! * This function frobnifies its arguments. +! */ +! +! /** The foo function. +! This function frobnifies its arguments. +! */ + +Marking incomplete code +~~~~~~~~~~~~~~~~~~~~~~~ + +Please use the token 'XXX' inside a comment to mark broken or +incomplete code. + +Module-level rules +================== + +Singletons +~~~~~~~~~~ + +Singleton objects (classes that will be instantiated only once) should +be implemented as static class interfaces instead of a normal +instantiable class in order to save kernel-stack space (the this +pointer does not need to be passed to these classes). However, +developers should use normal classes when it is foreseeable that the +class needs to be instantiated multiple times in the future, for +instance to support SMP machines. + +Constant definitions +~~~~~~~~~~~~~~~~~~~~ + +Constants should generally only be defined in enumerations. +Preprocessor constants are discouraged except for source code passed +to the assembler (assembly files and header files meant to be included +in assembly code). + +In C++ code, preprocessor constants must not be used for conditional +compilation using '#ifdef' and friends (see Section +[Conditional compilation]). + +Bit-field types +~~~~~~~~~~~~~~~ + +When implementing a binary interface that has been specified in terms +of bits of machine words (such as the L4 ABI or a device interface), +it is a bad idea to implement the interface using bit-field types, +unless the interface is architecture-specific. The reason is that the +assignment of bit-field members to bit offsets is both +compiler-dependent and architecture-dependent. If bit fiddling is +required, please define a class that wraps an integral type (such as +'unsigned') and manipulate the bits using bit-and and bit-or +operators. + +Bit-field structures are OK when the exact order of bits in the type's +memory representation does not matter. + +Block-level rules +================= + +Assertions +~~~~~~~~~~ + +Use assertions generously. + +Fiasco supports two kinds of runtime assertions: 'assert' and 'check'. +Both cause a kernel panic when their argument evaluates to false. + +The first, 'assert', works just like 'assert' in standard C. It can +be removed from the build by defining the preprocessor symbol 'NDEBUG' +and therefore must not include code that has side effects. + +When side effects are desired, use 'check' instead of assert. The +contents of this macro are not optimized away with 'NDEBUG' -- only +the error-checking code is. + +Common idioms +~~~~~~~~~~~~~ + +* Endless loops are programmed like this: + + ! for (;;) + ! // do stuff + +* Sometimes a private inline function is desired, for example if it + needs to be wrapped by a stub that is callable from assembly code. + In this case, use 'inline NOEXPORT' to avoid having to specify a + lengthy 'NEEDS[]' directive for the inline function: + + ! extern "C" + ! void + ! asm_callable_stub (Thread* t) + ! { + ! t->do_stuff(); + ! } + ! + ! PRIVATE inline NOEXPORT + ! Thread::do_stuff () + ! { + ! // ... + ! } + +* Macros are discouraged. Use inline functions instead. + +* If you really, absolutely have to define a macro, please make sure + it can be used as single-statement blocks after 'if', 'else', and + the like, by wrapping it like this: + + ! #define foo(x) do { /* your stuff */ } while (0) + +Rules for spacing, bracing, and indentation +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If not specified more precisely in this standard, the GNU Coding +Conventions for spacing and bracing apply ([GNU Coding Standards], +Section 5.1). + +* The tabulator size is 8. A tabulator can always be replaced with + spaces that lead to the next tab stop. + +* The maximum line length is 80. If a code line becomes longer than + 80 characters, it must be broken into shorter lines. If line length + becomes excessive, developers should factor out utility functions. + +* The indentation increment is 2 spaces. + +* In function definitions, put both the return type and the function + signature on a line by themselves. Example: + + ! PUBLIC inline + ! void + ! Preemption::set_preempter (Receiver *preempter) + ! { + ! // ... + ! } + +* Put whitespace before each opening parenthesis, except if it is + preceded by another opening parenthesis. Put whitespace after each + closing parenthesis, except if it is followed by another closing + parenthesis or a comma or semicolon. As a special exception, you do + not need to put a space between a function name and the + function-call operator. + + ! a = f (b(), sin ((x + y) * z)); + +* Do not wrap the argument to the 'return' statement into parentheses. + +* Opening and closing braces ('\{', '\}', including the form '\};') + always reside on a line of their own. The braces are indented for + nested code blocks, but not for type and function definitions. The + braced content is always indented with respect to the braces. + + Goto labels are back-indented 1 space, class-access specifiers + (public, protected, private) are back-indented 2 spaces. + + ! class Thread + ! { + ! public: + ! enum Thread_state + ! { + ! Thread_invalid, Thread_running + ! }; + ! + ! int _prio; + ! }; + + ! PUBLIC + ! void + ! Thread::stuff () + ! { + ! if (receiver()->ipc_try_lock (this) == 0) + ! { + ! do_stuff(); + ! } + ! } + + As an exception, if a function definition fits into a single line, + the whole function can be defined in one line. This style can aid + readability when defining many small functions in a row. + +* Curly braces around single-statement code blocks for 'if', 'while', + 'do', and 'for' are optional, except if the control expression(s) of + these statement spans more than one line, the statement following it + must be braced. + +* Spacing inside expressions is not prescribed. Please do something + sensible to save us from adding more rules to this document. + +; Fiasco style rules +; +; Y Directory organization +; +; Y Naming: Classes, methods, constants +; +; Y No exceptions, no RTTI +; +; Y Singleton objects as static class interfaces, to save stack space +; +; Y no preprocessor variables -- use enums +; +; Y IMPLEMENT nur für definitionen in spezielleren Subsections +; +; Y config class vs configuration management +; +; Y header files: unusally not. otherwise, multi-inc protection +; +; Y assert, check +; +; Y Max. 80 Zeichen pro Zeile +; +; Y Doxygen-Style +; +; Y Doxygen: Bei deklarierten Memberfunktionen (mit IMPLEMENT +; implementiert) kommt die Doku vor die Deklaration +; +; Y Member-Vars: _member_name +; Klassen: Class_name +; Konstanten: Constant_name +; +; Y XXX-Kommentare +; +; Y wann eigenes Quellfile, wann mehrere IMPLEMENTATION-Sections in +; einem File? +; +; Y Funktionname an Zeilenbeginn, Name/Parameter auf einer Zeile +; +; Y Rückgabetyp auf Extra-Zeile +; +; Y Einrücke-Standards +; . Enums +; +; Y Endlosschleife: for (;;) +; +; Y Makros: use do {} while (0); (else-kompatibel) +; +; Y Use inline NOEXPORT für lokale Inlines (ohne NEEDS) +; +; - kleine Interfaces erwünscht -- minimiere PUBLIC +; +; Y Makros vermeiden +; +; Y Konstanten als enums +; +; Y cyclic dependencies, +; +; - initcalls +; +; - boolean return values -- bool vs Mword, maybe a new type Bool? +; +; - "Thread*" t vs "Thread *t" +; +; - Style of CVS commit messages +; +; - Code duplication avoidance +; +; - C++ default parameters -- discouraged? +; +; - Passing structures as const structure& +; +; - Makeconf.local: the place to set CC, CXX +; +; - Sort IMPLEMENTATION[xyz] sections alphabetically: ARM vor IA32 vor +; UX, V2 vor V4 vor X0 bzw. V2,X0 vor V4. +; +; - declaration/IMPLEMENT are not for documentation purposes, which +; would not work anyway; use the files in auto/ or Doxygen. +; +; ---------------------------------------------------------------------- +; +; René: +; +; Was mir am Anfang nicht klar war: +; +; Y Namenskonvention, member mit _foo, Klassen mit Grossbuchstaben +; beginnen & co, Namen allg. +; +; Y Comments englisch only +; +; Y Klammersetzung!! Auch wo man Klammern weglassen soll! +; +; - IMPLEMENT vs PUBLIC, PRIVATE, PROTECTED +; +; Erwaehnenswert waere noch fuer Neuanfaenger +; +; Y keine ifdefs +; +; - vieleicht Waechter-Style: +; also nicht +; +; if foo +; if bar +; if foobar +; +; sondern eher +; if !foo +; return +; if !bar +; return +; usw. +; +; Y Vieleicht sollten wir die maximale Einruecktiefe begrenzen. Ich bin fuer +; 3-4. Ich weis das vieles im Code noch nicht so ist, aber man kann ja mal +; anfangen. +; +; - Generic vs Arch.-spezifische Sachen, zB im generic kein regs()->ecx & +; co. +; +; +; +; Assemblermacros: +; Bis vor kurzen habe ich noch die #define Version genommen. +; Macht sich aber richtig ******* beim schreiben. +; Habe jetzt mein Zeug auf .macro umgestellt, sieht erheblich freundlicher +; aus. +; +; Ein paar hinweise allg zu Assembler, wann man lieber +; Funktionen/gemeinsamen Code sollte und wann Makros. + +;Local Variables: +;mode:flyspell +;ispell-local-dictionary: "american" +;comment-start: ";" +;comment-start-skip: "; *" +;End: + +; LocalWords: accessor Hohmuth tex pdflatex README Preprocess GCC polymorphism +; LocalWords: nonvirtual instantiable NDEBUG Doxygen's Doxygen XXX Javadoc cpp +; LocalWords: NOEXPORT Metarules ifdef diff --git a/kernel/fiasco/src/TODO b/kernel/fiasco/src/TODO new file mode 100644 index 00000000..b84a0ba1 --- /dev/null +++ b/kernel/fiasco/src/TODO @@ -0,0 +1,74 @@ + + - make kobject_start_addr and co depend on debug feature + - remote TLB handling + - testing, testing, testing + + + + + +######################################################################### +Older stuff, needs reviewing: + + +Functionality +############# + +- Kill (deadline) timeouts if a thread is terminated. +- Fix Receiver::sender_enqueue (see ktest: "unfair scheduling"). +- Long IPC: Reserve first 4MB page after User_max as ``not available'' to + allow user to use the last 4MB page for long IPC (keyword IPC window) +- Lazy IPC windowing for long IPC (similar to lazy FPU). The kernel should + store the IPC owner per address space (e.g. the last thread that called + setup_ipc_window()). When switching to a thread which performs long IPC + only flush the IPC window if it doesn't own the IPC window. + * Udo: It is also possible to setup the IPC window for the other thread + (saves pagefaults) but don't do this in switch_to() +- Compare version numbers in IPC (and not only there). +- Add receiver lists (similar to sender lists). A thread A stays in closed + wait to thread B. The IPC is not aborted if thread B is killed. + * Udo: Receiver lists are probably also needed for time donation. +- Enhance the mapping database to support I/O flexpages for x86. +- Enhance the mapping database to support Memory-Mapped flexpages. +- Add scatter/gather as defined in the X.0 specification. +- Replace fixed addresses of TCBs with e.g. a slab allocator and a hash table + for mapping Threadid->TCB (even for V2?) +- IPC via chiefs. Does that still make sense? +- The current profiling implementation produces the old BSD-GPROF4 format + which don't includes a magic number and the sample frequency. Either use + the 4.4BSD format (which isn't recognized by the binutils by default) or + use the GNU format (take the libc6 sources). +- Vkey IRQ support for Fiasco-UX. +- UTCBs for all architectures. + + +Code cosmetics +############## + +- Use the minilibc as GlibC replacement for Fiasco-UX. This would reduce the + stack footprint of printf() & colleagues and would allow to use these + functions from kernel thread contexts without switching the stack. +- Remove all 32 bit values of -1 (0xffffffff). Replace them by a constant + defined as static_cast(-1). +- Remove multiple definitions of offsetof macro. +- Unify long IPC pathes of all architectures. +- More unification between the kernel debugger of IA32 and UX. +- Fiasco-UX platform/subarchitecture separation. +- Class Kmem should be related to Space. Kmem should be a ``real'' object. +- ``Signal'' should be renamed to ``transactional message''. +- Rename object variables ``my_foo'' to ``_foo''. +- Simplify the IPC path by reducing the number of possible states. +- Unify the Thread stuff in ARM and IA32 V4. + + +Performance +########### + +- The most important members of the TCB should have an offset less than 0x80 + to achive smaller code (can save up to 3 bytes per instruction). +- TCB cache line optimization. +- Selective assertions, differ between ``normal'' assertions and ``expensive + assertions''. + * Frank: Assertions are quite cheap because they are marked as EXPECT_FALSE + (at least with gcc-3). + diff --git a/kernel/fiasco/src/abi/amd64/kip-amd64-debug.cpp b/kernel/fiasco/src/abi/amd64/kip-amd64-debug.cpp new file mode 100644 index 00000000..d3d5c487 --- /dev/null +++ b/kernel/fiasco/src/abi/amd64/kip-amd64-debug.cpp @@ -0,0 +1,7 @@ +IMPLEMENTATION [amd64-debug]: + +IMPLEMENT inline +void +Kip::debug_print_syscalls() const +{} + diff --git a/kernel/fiasco/src/abi/amd64/kip-amd64.cpp b/kernel/fiasco/src/abi/amd64/kip-amd64.cpp new file mode 100644 index 00000000..9400e83a --- /dev/null +++ b/kernel/fiasco/src/abi/amd64/kip-amd64.cpp @@ -0,0 +1,71 @@ +/* + * AMD64 Kernel-Info Page + */ + +INTERFACE [amd64]: + +#include "types.h" + +EXTENSION class Kip +{ +public: + + /* 0x00 */ + Mword magic; + Mword version; + Unsigned8 offset_version_strings; + Unsigned8 fill2[7]; + Unsigned8 kip_sys_calls; + Unsigned8 fill3[7]; + + /* the following stuff is undocumented; we assume that the kernel + info page is located at offset 0x1000 into the L4 kernel boot + image so that these declarations are consistent with section 2.9 + of the L4 Reference Manual */ + + /* 0x20 */ + Mword sched_granularity; + Mword _res1[3]; + + /* 0x40 */ + Mword sigma0_sp, sigma0_ip; + Mword _res2[2]; + + /* 0x60 */ + Mword sigma1_sp, sigma1_ip; + Mword _res3[2]; + + /* 0x80 */ + Mword root_sp, root_ip; + Mword _res4[2]; + + /* 0xA0 */ + Mword _res_a0; + Mword _mem_info; + Mword _res_b0[2]; + + /* 0xC0 */ + Mword _res5[16]; + + /* 0x140 */ + volatile Cpu_time clock; + Unsigned64 _res6; + + /* 0x150 */ + Mword frequency_cpu; + Mword frequency_bus; + + /* 0x160 */ + Mword _res7[12]; + + /* 0x1C0 */ + Mword user_ptr; + Mword vhw_offset; + + /* 0x1D0 */ + Mword _res8[2]; + + /* 0x1E0 */ + Unsigned32 __reserved[20]; +}; + diff --git a/kernel/fiasco/src/abi/arm/kip-arm.cpp b/kernel/fiasco/src/abi/arm/kip-arm.cpp new file mode 100644 index 00000000..05dfdae2 --- /dev/null +++ b/kernel/fiasco/src/abi/arm/kip-arm.cpp @@ -0,0 +1,82 @@ +/* + * ARM Kernel-Info Page + */ + +INTERFACE [arm]: + +#include "types.h" + +EXTENSION class Kip +{ +public: + struct Platform_info + { + Unsigned32 cpuid; + Unsigned32 mp; + }; + + /* 0x00 */ + Mword magic; + Mword version; + Unsigned8 offset_version_strings; + Unsigned8 fill0[3]; + Unsigned8 kip_sys_calls; + Unsigned8 fill1[3]; + + /* the following stuff is undocumented; we assume that the kernel + info page is located at offset 0x1000 into the L4 kernel boot + image so that these declarations are consistent with section 2.9 + of the L4 Reference Manual */ + + /* 0x10 */ + Mword sched_granularity; + Mword _res1[3]; + + /* 0x20 */ + Mword sigma0_sp, sigma0_ip; + Mword _res2[2]; + + /* 0x30 */ + Mword sigma1_sp, sigma1_ip; + Mword _res3[2]; + + /* 0x40 */ + Mword root_sp, root_ip; + Mword _res4[2]; + + /* 0x50 */ + Mword _res_50; + Mword _mem_info; + Mword _res_58[2]; + + /* 0x60 */ + Mword _res5[16]; + + /* 0xA0 */ + volatile Cpu_time clock; + Unsigned64 _res6; + + /* 0xB0 */ + Mword frequency_cpu; + Mword frequency_bus; + + /* 0xB8 */ + Mword _res7[10]; + + /* 0xE0 */ + Mword user_ptr; + Mword vhw_offset; + Unsigned32 _res8[2]; + + /* 0xF0 */ + Platform_info platform_info; + Unsigned32 __reserved[18]; +}; + +//--------------------------------------------------------------------------- +IMPLEMENTATION [arm && debug]: + +IMPLEMENT inline +void +Kip::debug_print_syscalls() const +{} diff --git a/kernel/fiasco/src/abi/ia32/kip-ia32-debug.cpp b/kernel/fiasco/src/abi/ia32/kip-ia32-debug.cpp new file mode 100644 index 00000000..2b2406f6 --- /dev/null +++ b/kernel/fiasco/src/abi/ia32/kip-ia32-debug.cpp @@ -0,0 +1,20 @@ +IMPLEMENTATION [{ia32,ux}-debug]: + +#include +#include "types.h" + +IMPLEMENT +void +Kip::debug_print_syscalls() const +{ + unsigned kips = kip_sys_calls; + static char const* const KIPS[] = {"No KIP syscalls supported", + "KIP syscalls via KIP relative stubs", + "KIP syscalls via absolute stubs", + "KIP syscalls ERROR: bad value"}; + + if (kips > 3) + kips = 3; + + printf("%s\n", KIPS[kips]); +} diff --git a/kernel/fiasco/src/abi/ia32/kip-ia32.cpp b/kernel/fiasco/src/abi/ia32/kip-ia32.cpp new file mode 100644 index 00000000..f60bfa85 --- /dev/null +++ b/kernel/fiasco/src/abi/ia32/kip-ia32.cpp @@ -0,0 +1,82 @@ +/* + * IA-32 Kernel-Info Page + */ + +INTERFACE [ux]: + +#include "vhw.h" + +INTERFACE [ia32 || ux]: + +#include "types.h" + +EXTENSION class Kip +{ +public: + + /* 0x00 */ + Mword magic; + Mword version; + Unsigned8 offset_version_strings; + Unsigned8 fill0[3]; + Unsigned8 kip_sys_calls; + Unsigned8 fill1[3]; + + /* the following stuff is undocumented; we assume that the kernel + info page is located at offset 0x1000 into the L4 kernel boot + image so that these declarations are consistent with section 2.9 + of the L4 Reference Manual */ + + /* 0x10 */ + Mword sched_granularity; + Mword _res1[3]; + + /* 0x20 */ + Mword sigma0_sp, sigma0_ip; + Mword _res2[2]; + + /* 0x30 */ + Mword sigma1_sp, sigma1_ip; + Mword _res3[2]; + + /* 0x40 */ + Mword root_sp, root_ip; + Mword _res4[2]; + + /* 0x50 */ + Mword _res_50; + Mword _mem_info; + Mword _res_58[2]; + + /* 0x60 */ + Mword _res5[16]; + + /* 0xA0 */ + volatile Cpu_time clock; + Unsigned64 _res6; + + /* 0xB0 */ + Mword frequency_cpu; + Mword frequency_bus; + + /* 0xB8 */ + Mword _res7[10]; + + /* 0xE0 */ + Mword user_ptr; + Mword vhw_offset; + Unsigned32 _res8[2]; + + /* 0xF0 */ + Unsigned32 __reserved[20]; +}; + +//--------------------------------------------------------------------------- +IMPLEMENTATION [ux]: + +PUBLIC +Vhw_descriptor * +Kip::vhw() const +{ + return reinterpret_cast(((unsigned long)this) + vhw_offset); +} diff --git a/kernel/fiasco/src/abi/kip-debug.cpp b/kernel/fiasco/src/abi/kip-debug.cpp new file mode 100644 index 00000000..8ac81589 --- /dev/null +++ b/kernel/fiasco/src/abi/kip-debug.cpp @@ -0,0 +1,94 @@ +INTERFACE [debug]: + +EXTENSION class Kip +{ +private: + void debug_print_syscalls() const; +}; + +IMPLEMENTATION [debug]: + + +#include +#include +#include "simpleio.h" + +static char const *const memory_desc_types[] = { + "Undefined", + "Conventional", + "Reserved", + "Dedicated", + "Shared", + "(undef)", + "(undef)", + "(undef)", + "(undef)", + "(undef)", + "(undef)", + "(undef)", + "(undef)", + "(undef)", + "Bootloader", + "Arch" }; + +PUBLIC +void +Mem_desc::dump() const +{ + printf("%s [%016lx-%016lx] %s", is_virtual()?"virt":"phys", + start(), end() + 1, memory_desc_types[type()]); +} + +PRIVATE +void +Kip::debug_print_memory() const +{ + printf("Memory (max %d descriptors):\n",num_mem_descs()); + Mem_desc const *m = mem_descs(); + Mem_desc const *const e = m + num_mem_descs(); + for (;mtype() != Mem_desc::Undefined) + { + printf(" %2d:", (int)(m - mem_descs() + 1)); + m->dump(); + puts(""); + } + } +} + +PRIVATE +void +Kip::debug_print_features() const +{ + printf("Kernel features:"); + char const *f = version_string(); + for (f += strlen(f) + 1; *f; f += strlen(f) + 1) + { + putchar(' '); + putstr(f); + } + putchar('\n'); +} + + +IMPLEMENT +void Kip::print() const +{ + printf("KIP @ %p\n", this); + printf("magic: %.4s version: 0x%lx\n",(char*)&magic, version); + printf("clock: " L4_X64_FMT " (%lld)\n", clock, clock); + printf("freq_cpu: %ldkHz\n", frequency_cpu); + printf("freq_bus: %ldkHz\n", frequency_bus); + + printf("sigma0_ip: " L4_PTR_FMT " sigma0_sp: " L4_PTR_FMT "\n", sigma0_ip, sigma0_sp); + printf("sigma1_ip: " L4_PTR_FMT " sigma1_sp: " L4_PTR_FMT "\n", sigma1_ip, sigma1_sp); + printf("root_ip: " L4_PTR_FMT " root_sp: " L4_PTR_FMT "\n", root_ip, root_sp); + debug_print_memory(); + debug_print_syscalls(); + + printf("user_ptr: %p vhw_offset: " L4_MWORD_FMT "\n", + (void*)user_ptr, vhw_offset); + + debug_print_features(); +} diff --git a/kernel/fiasco/src/abi/kip.cpp b/kernel/fiasco/src/abi/kip.cpp new file mode 100644 index 00000000..346574bc --- /dev/null +++ b/kernel/fiasco/src/abi/kip.cpp @@ -0,0 +1,169 @@ +INTERFACE: + +class Mem_desc +{ +public: + enum Mem_type + { + Undefined = 0x0, + Conventional = 0x1, + Reserved = 0x2, + Dedicated = 0x3, + Shared = 0x4, + Kernel_tmp = 0x7, + + Bootloader = 0xe, + Arch = 0xf, + }; + +private: + Mword _l, _h; +}; + +//---------------------------------------------------------------------------- +INTERFACE [ia32]: + +/* Empty class for VHW descriptor in KIP for native ia32 */ +class Vhw_descriptor {}; + +//---------------------------------------------------------------------------- +INTERFACE: + +#include "mem_region.h" +#include "types.h" + +class Kip +{ +public: + void print() const; + + char const *version_string() const; + + // returns the 1st address beyond all available physical memory + Address main_memory_high() const; + +private: + static Kip *global_kip asm ("GLOBAL_KIP"); +}; + +#define L4_KERNEL_INFO_MAGIC (0x4BE6344CL) /* "L4µK" */ + +//============================================================================ +IMPLEMENTATION: + +#include "assert.h" +#include "config.h" +#include "panic.h" +#include "static_assert.h" +#include "version.h" + +PUBLIC inline +Mem_desc::Mem_desc(Address start, Address end, Mem_type t, bool v = false, + unsigned st = 0) +: _l((start & ~0x3ffUL) | (t & 0x0f) | ((st << 4) & 0x0f0) + | (v?0x0200:0x0)), + _h(end) +{} + +PUBLIC inline +Address Mem_desc::start() const +{ return _l & ~0x3ffUL; } + +PUBLIC inline +Address Mem_desc::end() const +{ return _h | 0x3ffUL; } + +PUBLIC inline +void +Mem_desc::type(Mem_type t) +{ _l = (_l & ~0x0f) | (t & 0x0f); } + +PUBLIC inline +Mem_desc::Mem_type Mem_desc::type() const +{ return (Mem_type)(_l & 0x0f); } + +PUBLIC inline +unsigned Mem_desc::ext_type() const +{ return _l & 0x0f0; } + +PUBLIC inline +unsigned Mem_desc::is_virtual() const +{ return _l & 0x200; } + +PUBLIC inline +bool Mem_desc::contains(unsigned long addr) +{ + return start() <= addr && end() >= addr; +} + +PUBLIC inline +bool Mem_desc::valid() const +{ return type() && start() < end(); } + +PUBLIC inline +Mem_desc *Kip::mem_descs() +{ return (Mem_desc*)(((Address)this) + (_mem_info >> (MWORD_BITS/2))); } + +PUBLIC inline +Mem_desc const *Kip::mem_descs() const +{ return (Mem_desc const *)(((Address)this) + (_mem_info >> (MWORD_BITS/2))); } + +PUBLIC inline +unsigned Kip::num_mem_descs() const +{ return _mem_info & ((1UL << (MWORD_BITS/2))-1); } + +PUBLIC inline +void Kip::num_mem_descs (unsigned n) +{ + _mem_info = (_mem_info & ~((1UL << (MWORD_BITS/2))-1) + | (n & ((1UL << (MWORD_BITS/2))-1))); +} + +PUBLIC +Mem_desc *Kip::add_mem_region(Mem_desc const &md) +{ + Mem_desc *m = mem_descs(); + Mem_desc *end = m + num_mem_descs(); + for (;mtype() == Mem_desc::Undefined) + { + *m = md; + return m; + } + } + + // Add mem region failed -- must be a Fiasco startup problem. Bail out. + panic("Too few memory descriptors in KIP"); + + return 0; +} + +Kip *Kip::global_kip; + +PUBLIC static +void Kip::init_global_kip(Kip *kip) +{ + global_kip = kip; + + // check that the KIP has actually been set up + assert(kip->sigma0_ip && kip->root_ip && kip->user_ptr); +} + +PUBLIC static inline Kip *Kip::k() { return global_kip; } + +IMPLEMENT +char const *Kip::version_string() const +{ + static_assert((sizeof(Kip) & 0xf) == 0, "Invalid KIP structure size"); + + return reinterpret_cast (this) + (offset_version_strings << 4); +} + +asm(".section .initkip.version, \"a\", %progbits \n" \ + ".string \"" CONFIG_KERNEL_VERSION_STRING "\" \n" \ + ".previous \n"); + +asm(".section .initkip.features.fini, \"a\", %progbits \n" \ + ".string \"\" \n" \ + ".previous \n"); diff --git a/kernel/fiasco/src/abi/l4_buf_desc.cpp b/kernel/fiasco/src/abi/l4_buf_desc.cpp new file mode 100644 index 00000000..be8dc6e8 --- /dev/null +++ b/kernel/fiasco/src/abi/l4_buf_desc.cpp @@ -0,0 +1,109 @@ +INTERFACE: + +#include "types.h" + +/** + * Description of the mapping buffer registers contained in the UTCB + * (used e.g. during IPC). + * The utcb can contain buffers that describe memory regions, bits in the + * I/O bitmap or capabilities. The buffer description is used to find the + * first buffer for each type. + * Additionally, the buffer description contains a flag to specify the + * willingness to receive FPU state in an IPC operation. + * + * Note that a single buffer might occupy more than one word in the buffer- + * registers array in the UTCB. The L4_buf_iter class can be used to iterate + * over buffers. + */ +class L4_buf_desc +{ +public: + enum Flags + { + /** + * \brief Flag the willingness to receive FPU state during IPC. + * + * If this flag is set, the receiving thread in an IPC is willing + * to receive the status of the floating point unit (FPU) from its partner + * as part of an IPC. Conceptually, this flag adds the FPU of the + * receiver as an additional message receiver buffer. + * The sender must set the corresponding flag L4_msg_tag::Transfer_fpu. + */ + Inherit_fpu = (1UL << 24) + }; + + /** + * Create an uninitialized buffer descriptor. + * \note The value of the buffer descriptor is unpredictable. + */ + L4_buf_desc() {} + + /** + * Create a buffer descriptor with given values. + * \param mem the BR index for the first memory buffer item. + * \param io the BR index for the first I/O-port buffer item. + * \param obj the BR index for the first object/capability buffer item. + * \param flags the flags, such as, Inherit_fpu. + * + * The buffer registers must contain blocks of buffers of identical + * type (memory, caps, I/O-ports) starting at the given index. The first + * non-matching item terminates the items of the particular type. + * \see Utcb and L4_msg_tag + */ + L4_buf_desc(unsigned mem, unsigned io, unsigned obj, + unsigned flags = 0) + : _raw(mem | (io << 5) | (obj << 10) | flags) + {} + + /** + * Index of the first memory receive buffer. + * \return the index of the first receive buffer for memory mappings. + * + * The memory receive items use two BRs each. + * \see L4_fpage, L4_msg_item + */ + unsigned mem() const { return _raw & ((1UL << 5)-1); } + + /** + * Index of the first I/O-port buffer item. + * \return the index of the first BR containing a I/O-port buffer. + * + * The I/O-port buffer items use two BRs each. + * \see L4_fpage, L4_msg_item. + */ + unsigned io() const { return (_raw >> 5) & ((1UL << 5)-1); } + + /** + * Index of the first object receive buffer. + * \return the BR index for the first object/capability receive buffer. + * + * An object receive buffer may use one or two BRs depending on the + * value in the L4_msg_item in the first BR. + * \see L4_msg_item, L4_fpage. + */ + unsigned obj() const { return (_raw >> 10) & ((1UL << 5)-1); } + + /** + * The flags of the BDR. + * \return flags encoded in the BDR, see #Inherit_fpu, L4_buf_desc::Flags. + * \note The return value may have reserved bits set. + */ + Mword flags() const { return _raw; } + + /** + * Get the raw binary representation of the buffer descriptor. + * \return binary representation of the buffer descriptor. + */ + Mword raw() const { return _raw; } + +private: + /** + * A single machine word that describes the buffers that follow: + * - Bits 0..4: The index of the first memory buffer. + * - Bits 5..9: The index of the first io buffer. + * - Bits 10..14: The index of the first capability buffer. + * - Bits 15..23: Unused + * - Bits 24..31: Flags as defined above (only #Inherit_fpu is in use). + */ + Mword _raw; +}; diff --git a/kernel/fiasco/src/abi/l4_error.cpp b/kernel/fiasco/src/abi/l4_error.cpp new file mode 100644 index 00000000..714a881c --- /dev/null +++ b/kernel/fiasco/src/abi/l4_error.cpp @@ -0,0 +1,62 @@ +INTERFACE: + +#include "types.h" + +class L4_error +{ +public: + enum Error_code + { + None = 0, + Timeout = 2, + R_timeout = 3, + Not_existent = 4, + Canceled = 6, + R_canceled = 7, + Overflow = 8, + Snd_xfertimeout = 10, + Rcv_xfertimeout = 12, + Aborted = 14, + R_aborted = 15, + Map_failed = 16, + }; + + enum Phase + { + Snd = 0, + Rcv = 1 + }; + + L4_error(Error_code ec = None, Phase p = Snd) : _raw(ec | p) {} + L4_error(L4_error const &e, Phase p = Snd) : _raw(e._raw | p) {} + + bool ok() const { return _raw == 0; } + + Error_code error() const { return Error_code(_raw & 0x1e); } + Mword raw() const { return _raw; } + bool snd_phase() const { return !(_raw & Rcv); } + + static L4_error from_raw(Mword raw) { return L4_error(true, raw); } + +private: + L4_error(bool, Mword raw) : _raw(raw) {} + Mword _raw; +}; + + +//---------------------------------------------------------------------------- +IMPLEMENTATION [debug]: + +static char const *__errors[] = +{ "OK", "timeout", "not existent", "canceled", "overflow", + "xfer snd", "xfer rcv", "aborted", "map failed" }; + + + +PUBLIC +char const * +L4_error::str_error() +{ + return __errors[(_raw >> 1) & 0xf]; +} + diff --git a/kernel/fiasco/src/abi/l4_fpage.cpp b/kernel/fiasco/src/abi/l4_fpage.cpp new file mode 100644 index 00000000..9fdb2777 --- /dev/null +++ b/kernel/fiasco/src/abi/l4_fpage.cpp @@ -0,0 +1,274 @@ +INTERFACE: + +#include "types.h" + +/** + * A L4 flex page. + * + * A flex page represents a naturally aligned area of mappable space, + * such as memory, I/O-ports, and capabilities (kernel objects). + * There is also a representation for describing a flex page that represents + * the whole of all these address spaces. The size of a flex page is given + * as a power of two. + * + * + * The internal representation is a single machine word with the following + * layout: + * \verbatim + * +- bitsize-12 +- 11-6 -+ 5-4 -+-- 3-0 -+ + * | page number | order | type | rights | + * +-------------+--------+------+--------+ + * \endverbatim + * + * - The rights bits (0-3) denote the access rights to an object, see + * L4_fpage::Rights. + * - The \a type of a flex page is denotes the address space that is + * referenced by that flex page (see L4_fpage::Type). + * - The order is the exponent for the size calculation (size = 2^order). + * - The page number denotes the page address within the address space + * denoted by \a type. For example when \a type is #Memory, the \a page + * \a number must contain the most significant bits of a virtual address + * that must be aligned to \a order bits. In the case that \a type + * equals either #Io or #Obj, the \a page \a number contains all bits of + * the I/O-port number or the capability index, respectively (note, the + * values must also be aligned according to the value of \a order). + * + */ +class L4_fpage +{ +public: + /** + * Data type to represent the binary representation of a flex page. + */ + typedef Mword Raw; + + /** + * Address space type of a flex page. + */ + enum Type + { + Special = 0, ///< Special flex pages, either invalid or all spaces. + Memory, ///< Memory flex page + Io, ///< I/O-port flex page + Obj ///< Object flex page (capabilities) + }; + + enum { Addr_shift = 12 }; + +private: + /** + * Create a flex page with the given parameters. + */ + L4_fpage(Type type, Mword address, unsigned char order, + unsigned char rights) + : _raw(address | Raw(rights) | (Raw(order) << 6) | (Raw(type) << 4)) + {} + +public: + enum + { + Whole_space = 63 ///< Value to use as \a order for a whole address space. + }; + + /** + * Create an I/O flex page. + * + * IO flex pages do not support access rights other than RW or nothing. + * \param port base I/O-port number (0..65535), must be aligned to + * 2^\a order. The value is shifted by #Addr_shift bits to the + * left. + * \param order the order of the I/O flex page, size is 2^\a order ports. + */ + static L4_fpage io(Mword port, unsigned char order) + { return L4_fpage(Io, port << Addr_shift, order, 0); } + + /** + * Create an object flex page. + * + * \param idx capability index, note capability indexes are multiples of + * 0x1000. (hence \a idx is not shifted) + * \param order The size of the flex page is 2^\a order. The value in \a idx + * must be aligned to 2^(\a order + #Addr_shift. + */ + static L4_fpage obj(Mword idx, unsigned char order, unsigned char rights = 0) + { return L4_fpage(Obj, idx & (~0UL << Addr_shift), order, rights); } + + /** + * Create a memory flex page. + * + * \param addr The virtual address. Only the most significant bits are + * considered, bits from 0 to \a order-1 are dropped. + * \param order The size of the flex page is 2^\a order in bytes. + */ + static L4_fpage mem(Mword addr, unsigned char order, unsigned char rights = 0) + { return L4_fpage(Memory, addr & (~0UL << Addr_shift), order, rights); } + + /** + * Create a nil (invalid) flex page. + */ + static L4_fpage nil() + { return L4_fpage(0); } + + /** + * Create a special receive flex page representing + * all available address spaces at once. This is used + * for page-fault and exception IPC. + */ + static L4_fpage all_spaces(unsigned char rights = 0) + { return L4_fpage(Special, 0, Whole_space, rights); } + + /** + * Create a flex page from the raw value. + */ + explicit L4_fpage(Raw raw) : _raw(raw) {} + + /** + * Get the type, see #L4_fpage::Type. + * \return the type of the flex page. + */ + Type type() const { return Type((_raw >> 4) & 3); } + + /** + * Get the order of a flex page. + * \return the order of the flex page (size is 2^\a order). + */ + unsigned char order() const { return (_raw >> 6) & 0x3f; } + + /** + * The robust type for carrying virtual memory addresses. + */ + typedef Virt_addr Mem_addr; + + /** + * Get the virtual address of a memory flex page. + * + * \pre type() must return #Memory to return a valid value. + * \return The virtual memory base address of the flex page. + */ + Virt_addr mem_address() const + { return Virt_addr(_raw & (~0UL << Addr_shift)); } + + /** + * Get the capability address of an object flex page. + * + * \pre type() must return #Obj to return a valid value. + * \return The capability value (index) of this flex page. + * This value is not shifted, so it is a multiple of 0x1000. + * See obj_index() for reference. + */ + Mword obj_address() const { return _raw & (~0UL << Addr_shift); } + + /** + * Get the I/O-port number of an I/O flex page. + * \pre type() must return #Io to return a valid value. + * \return The I/O-port index of this flex page. + */ + Mword io_address() const { return _raw >> Addr_shift; } + + /** + * Get the capability index of an object flex page. + * + * \pre type() must return #Obj to return a valid value. + * \return The index into the capability table provided by this flex page. + * This value is shifted #Addr_shift to be a real index + * (opposed to obj_address()). + */ + Mword obj_index() const { return _raw >> Addr_shift; } + + /** + * Test for memory flex page (if type() is #Memory). + * \return true if type() is #Memory. + */ + bool is_mempage() const { return type() == Memory; } + + /** + * Test for I/O flex page (if type() is #Io). + * \return true if type() is #Io. + */ + bool is_iopage() const { return type() == Io; } + + /** + * Test for object flex page (if type() is #Obj). + * \return true if type() is #Obj. + */ + bool is_objpage() const { return type() == Obj; } + + + /** + * Is the flex page the whole address space? + * @return not zero, if the flex page covers the + * whole address space. + */ + Mword is_all_spaces() const { return (_raw & 0xff8) == (Whole_space << 6); } + + /** + * Is the flex page valid? + * \return not zero if the flex page + * contains a value other than 0. + */ + Mword is_valid() const { return _raw; } + + /** + * Get the binary representation of the flex page. + * \return this flex page in binary representation. + */ + Raw raw() const { return _raw; } + +private: + Raw _raw; + +public: + + /** + * Rights bits for flex pages. + * + * The particular semantics of the rights bits in a flex page differ depending on the + * type of the flex page. For memory there are #R, #W, and #X rights. For + * I/O-ports there must be #R and #W, to get access. For object (capabilities) + * there are #CD, #CR, #CS, and #CW rights on the object and additional + * rights in the map control value of the map operation (see L4_fpage::Obj_map_ctl). + */ + enum Rights + { + R = 4, ///< Memory flex page is readable + W = 2, ///< Memory flex page is writable + X = 1, ///< Memory flex page is executable (often equal to #R) + + RX = R | X, ///< Memory flex page is readable and executable + RWX = R | W | X, ///< Memory flex page is readable, writeable, and executable + RW = R | W, ///< Memory flex page is readable and writable + WX = W | X, ///< Memory flex page is writable and executable + + + CD = 0x8, ///< Object flex page: delete rights + CR = 0x4, ///< Object flex page: read rights (w/o this the mapping is not present) + CS = 0x2, ///< Object flex page: strong semantics (object specific, i.e. not having + /// this right on an IPC gate demotes all capabilities transferred via this + /// IPC gate to also suffer this right. + CW = 0x1, ///< Object flex page: write rights (purely object specific) + + CRW = CR | CW, ///< Object flex page: combine #CR and #CW + CRS = CR | CS, ///< Object flex page: combine #CR and #CS + CRWS = CRW | CS, ///< Object flex page: combine #CR, #CW, and #CS + CWS = CW | CS, ///< Object flex page: combine #CS and #CW + CWSD = CW | CS | CD, ///< Object flex page: combine #CS, #CW, and #CD + CRWSD = CRWS | CD, ///< Object flex page: combine #CR, #CW, #CS, and #CD + + FULL = 0xf, ///< All rights shall be transferred, independent of the type + }; + + /** + * Get the rights associated with this flexpage. + * \return The rights associated with this flex page. The semantics of this + * value also depends on the type (type()) of the flex page. + */ + Rights rights() const { return Rights(_raw & FULL); } + + /** + * Remove the given rights from this flex page. + * \param r the rights to remove. The semantics depend on the + * type (type()) of the flex page. + */ + void mask_rights(Rights r) { _raw &= (Mword(r) | ~0x0fUL); } +}; + diff --git a/kernel/fiasco/src/abi/l4_msg_item.cpp b/kernel/fiasco/src/abi/l4_msg_item.cpp new file mode 100644 index 00000000..14982e5b --- /dev/null +++ b/kernel/fiasco/src/abi/l4_msg_item.cpp @@ -0,0 +1,218 @@ +INTERFACE: + +#include "types.h" +#include "l4_fpage.h" + +/** + * The first word of a message item, either a send item or a receive buffer. + * + * L4_msg_item is the first word of a typed message item in system calls (incl. + * IPC) The L4_msg_item is usually followed by a second word. The + * interpretation of the second word depends on the contents of the + * L4_msg_item. + * + * A generic message item has the following binary layout. + * \verbatim + * +----------------------------+ 3 + 2 .. 1 + 0 + + * | | t | | c | + * +----------------------------+---+--------+---+ \endverbatim + * + * Bit 3 (\a t) is the type bit, if t is set the item is a map + * item. \note Fiasco.OC currently has no support for other types + * than map items. + * + * Bit 0 (\a c) is the compound bit and is available + * for scatter-gather behavior. For map items the \a c bit is useful + * for send items only, and described afterwards. + * + * A map item has a more specific layout: + * \verbatim + * +-- x .. 12 --+- 11 .. 8 -+- 7 .. 4 -+ 3 + 2 +- 1 -+ 0 + + * | hot_spot | SBZ | attr | 1 | i | g/s | c | + * +-------------+-----------+----------+---+---+-----+---+ \endverbatim + * + * Bit 0 (\a c), the compound bit: if this bit is set on a send map item + * the next message item of the same type shall be mapped using the same + * receive buffer as this send item. The caller should properly use the + * \a hot_spot to avoid overlapping mappings. + * + * Bit 1 (\a g/s): On a send map item a set \a g bit flags a grant operation. + * This means, the sender delegates access to the receiver and atomically + * removes the own rights (basically a move operation). On a receive buffer + * a set \a s bit flags a small object buffer. This means, the whole buffer + * item is just a single buffer register in size and provides a receive buffer + * for a single object mapping, the address of the buffer is stored in the + * \a hot_spot. + * + * Bit 2 (\a i): This bit is defined for small receive buffers only, a set \a i + * bit denotes that he receiver wants to avoid a full mapping. Instead, if all + * preconditions are met, the receiver will get either the label of an Ipc_gate + * or a capability selector in its message registers. A label of an Ipc_gate + * is sent if and only if the receiving thread is in the same task as the + * thread that is attached to the Ipc_gate. A capability selector is received + * if the sending and the receiving thread are in the same task. + * + * Bits 7..4 (\a attr): This bits contain extra attributes that influence the + * mapping itself. For memory mapping these bits contain cachebility information. + * For object mappings these bits contain extra rights on the object. + * + * Bits x..12 (\a hot_spot): These bits are the so called hot spot and are used + * to disambiguate the cases where either the send flex page or the receive flex + * page is larger that the other. + */ +class L4_msg_item +{ +private: + enum + { + Addr_shift = 12, ///< number of bits an index must be shifted, or + /// an address must be aligned to, in the control word + }; + +public: + /** + * Additional rights for objects (capabilities) apply to the control word of L4_msg_item. + */ + enum Obj_attribs + { + C_weak_ref = 0x10, ///< Map a weak reference (not counted in the kernel) + C_ref = 0x00, ///< Map a normal reference (counted, if not derived + /// from a weak reference) + + C_obj_right_1 = 0x20, ///< Some kernel internal, object-type specific right + C_obj_right_2 = 0x40, ///< Some kernel internal, object-type specific right + C_obj_right_3 = 0x80, ///< Some kernel internal, object-type specific right + + C_obj_specific_rights = C_obj_right_1 | C_obj_right_2 | C_obj_right_3, + C_ctl_rights = C_obj_specific_rights | C_weak_ref, + }; + + /** + * Additional flags for memory send items. + * + * These flags are to control the caching attributes of memory mappings. + */ + enum Memory_attribs + { + Caching_opt = 0x10, ///< This flag denotes the presence of a cachability option + Cached = 0x30, ///< Map the memory cachable + Buffered = 0x50, ///< Map the memory bufferable (write combining in Intel speech) + Uncached = 0x10, ///< Map the memory fully uncachable + }; + + enum Type + { + Map = 8, + }; + + /** + * Create a message item from its binary represenation. + * \param raw is the binary representation of the message item. + */ + explicit L4_msg_item(Mword raw) : _raw(raw) {} + + /** + * Use the same receive buffer for the next send item. + * \pre The item must be a send item. + * \return true if the next send item shall be handled with the + * same receive buffer as this one. + */ + Mword compound() const { return _raw & 1; } + + /** + * Get the type of the message item. + * \return the type of the message item, currently Fiasco.OC + * supports map items only, see #L4_msg_item::Map). + */ + Type type() const { return Type(_raw & 8); } + + /** + * Is the item a a void item? + * \return true if the item is \a void, false if it is valid. + */ + bool is_void() const { return _raw == 0; } + + /** + * Is the buffer item a small object buffer? + * \pre The item must be a receive buffer. + * \pre type() == #L4_msg_item::Map + * \return true if the buffer is a single-word single-object + * receive buffer, false else. + */ + Mword is_small_obj() const { return _raw & 2; } + + /** + * Receiver tries to receive an object ID or a + * capability selector? + * \pre The item must be a receive buffer. + * \pre type() == #L4_msg_item::Map + * \pre is_small_obj() == true + * \return true if the receiver is willing to receive an object ID + * or a capability selector, if possible. + */ + Mword is_rcv_id() const { return _raw & 4; } + + /** + * Is the map item actually a grant item? + * \pre type() == #L4_msg_item::Map + * \pre The item is a send item. + * \return true if the sender does a grant operation. + */ + Mword is_grant() const { return _raw & 2; } + + /** + * Get the binary representation of the item. + * \return the binary representation of this item. + */ + Mword raw() const { return _raw; } + + /** + * Get the extra attributes for the send item. + * \pre The item is a send item. + * \pre type() == #L4_msg_item::Map. + * \return the extra attributes for this send item. + * + * The semantics of the extra attributes depends on + * the type of the second word, the L4_fpage, of the + * complete send item. + * \see L4_msg_item::Memory_attribs, L4_msg_item::Obj_attribs + */ + Mword attr() const { return _raw & 0xf0; } + + /** + * Get the value of the most significant bits of a map item. + * \pre type() == #L4_msg_item::Map + * \return the most significant bits (shifted by #L4_msg_item::Addr_shift). + */ + Mword index() const { return _raw >> Addr_shift; } + + /** + * Get the most significant bits of a map item (masked). + * \pre type() == #L4_msg_item::Map + * \return the most significant bits (masked the lower + * #L4_msg_item::Addr_shift bits). + */ + Mword address() const { return _raw & (~0UL << Addr_shift); } + + /** + * Get the L4_fpage that represents the small buffer item. + * \pre type() == #L4_msg_item::Map + * \pre is_small_obj() == true + * \return the flex page (L4_fpage) representing the single + * object slot with index index(). + */ + + L4_fpage get_small_buf() { return L4_fpage::obj(_raw, 0, attr() >> 4); } + + /** + * Create a map item. + * \param base the hot spot address of the map item. + */ + static L4_msg_item map(Mword base) { return L4_msg_item(base | Map); } + +private: + /** + * The binary representation. + */ + Mword _raw; +}; diff --git a/kernel/fiasco/src/abi/l4_types-debug.cpp b/kernel/fiasco/src/abi/l4_types-debug.cpp new file mode 100644 index 00000000..1908b1da --- /dev/null +++ b/kernel/fiasco/src/abi/l4_types-debug.cpp @@ -0,0 +1,43 @@ +IMPLEMENTATION [debug]: + +#include +#include "simpleio.h" + +PUBLIC void L4_timeout::print() const +{ + printf("m=%ld e=%ld", man(), exp()); +} + +PUBLIC void L4_timeout_pair::print() const +{ + printf("snd: "); + snd.print(); + printf(" rcv: "); + rcv.print(); +} + +PUBLIC +void +Utcb::print() const +{ + puts("Values:"); + for (unsigned i = 0; i < Max_words; ++i) + printf("%2d:%16lx%c", i, values[i], !((i+1) % 4) ? '\n' : ' '); + if (Max_words % 4) + puts(""); + printf("Reserved: %16lx\n", utcb_addr); + + printf("Buffers: desc=%16lx\n", buf_desc.raw()); + for (unsigned i = 0; i < sizeof(buffers) / sizeof(buffers[0]); ++i) + printf("%2d:%16lx%c", i, buffers[i], !((i+1) % 4) ? '\n' : ' '); + if ((sizeof(buffers) / sizeof(buffers[0])) % 4) + puts(""); + + printf("Xfer timeout: "); + xfer.print(); + puts(""); + + printf("Error: %16lx\n", error.raw()); + printf("User values: %16lx %16lx %16lx\n", user[0], user[1], user[2]); +} + diff --git a/kernel/fiasco/src/abi/l4_types-objs.cpp b/kernel/fiasco/src/abi/l4_types-objs.cpp new file mode 100644 index 00000000..85b08c71 --- /dev/null +++ b/kernel/fiasco/src/abi/l4_types-objs.cpp @@ -0,0 +1,124 @@ +INTERFACE: + +EXTENSION class L4_fpage +{ +public: + /** + * task cap specific constants. + */ + enum { + Whole_obj_space = 25, ///< The order used to cover the whole x-cap space + Obj_max = 1L << Whole_obj_space, ///< Number of available task caps. + }; + + /** + * Create the given task flex page. + * @param port the port address. + * @param order the size of the flex page is 2^order. + * @param grant if not zero the grant bit is to be set. + */ + static L4_fpage obj(Mword index, Mword order, Mword grant); + + /** + * Get the x-cap flexpage base address. + * @return The x-cap flexpage base address. + */ + Mword obj() const; + + /** + * Set the x-cap flexpage base address. + * @param addr the x-cap flexpage base address. + */ + void obj( Mword index ); + + /** + * Is the flex page a task-cap flex page? + * @returns not zero if this flex page is a task-cap flex page. + */ + Mword is_objpage() const; + + /** + * Does the flex page cover the whole task-cap space. + * @pre The is_cappage() method must return true or the + * behavior is undefined. + * @return not zero if the flex page covers the whole task-cap + * space. + */ + Mword is_whole_obj_space() const; + +private: + enum { + Obj_mask = 0x007ff000, + Obj_shift = 12, + }; +}; + +INTERFACE [32bit]: + +EXTENSION class L4_fpage +{ +private: + enum + { + Obj_id = 0xf0000300, + }; +}; + +INTERFACE [64bit]: + +EXTENSION class L4_fpage +{ +private: + enum + { + Obj_id = 0xfffffffff0000300UL, + }; +}; + +//--------------------------------------------------------------------------- +IMPLEMENTATION [!caps]: + +IMPLEMENT inline +Mword L4_fpage::obj() const +{ + return 0; +} + +IMPLEMENT inline +Mword L4_fpage::is_objpage() const +{ + return 0; +} + +//--------------------------------------------------------------------------- +IMPLEMENTATION [caps]: + +IMPLEMENT inline +Mword L4_fpage::is_objpage() const +{ return (_raw & Special_fp_mask) == Obj_id; } + +IMPLEMENT inline +void L4_fpage::obj( Mword w ) +{ + _raw = (_raw & ~Obj_mask) | ((w << Obj_shift) & Obj_mask); +} + +IMPLEMENT inline +Mword L4_fpage::obj() const +{ + return (_raw & Obj_mask) >> Obj_shift; +} + +IMPLEMENT inline +L4_fpage L4_fpage::obj(Mword index, Mword order, Mword grant) +{ + return L4_fpage( (grant ? 1 : 0) + | ((index << Obj_shift) & Obj_mask) + | ((order << Size_shift) & Size_mask) + | Obj_id); +} + +IMPLEMENT inline +Mword L4_fpage::is_whole_obj_space() const +{ return (_raw >> 2) == Whole_obj_space; } + diff --git a/kernel/fiasco/src/abi/l4_types.cpp b/kernel/fiasco/src/abi/l4_types.cpp new file mode 100644 index 00000000..8e75cc07 --- /dev/null +++ b/kernel/fiasco/src/abi/l4_types.cpp @@ -0,0 +1,934 @@ +/* + * arch. independent L4 Types + */ + +INTERFACE: + +#include "types.h" +#include "l4_fpage.h" +#include "l4_buf_desc.h" +#include "l4_error.h" + +typedef Address Local_id; + +class Utcb; + +/** + * A reference to a kernel object (capability selector), + * as passed from user level. + * + * A capability selector contains an index into the capability table/object + * space of a task. The index is usually stored in the most significant bits + * of the binary representation. The twelve least significant bits are used to + * to denote the type of operation that shall be invoked and also so flags for + * special capabilities, such as the invalid cap, the reply capability, or the + * self capability. + * + * Generally all operations on kernel objects are modelled as message passing + * primitives that consist of two phases, the send phase and the receive phase. + * However, both phases are optional and come in slightly different flavors. + * \see L4_obj_ref::Operation. + * The terms send and receive are from the invokers point of view. This means, + * a client doing RPC needs a send for sending the requested operation an + * parameters and a receive to receive the return code of the RPC. + */ +class L4_obj_ref +{ +public: + /** + * Operation codes, stored in the four least significant bits of a capability + * selector. + */ + enum Operation + { + /// A no-op on the capability (undefined from user level). + None = 0, + + /** + * \deprecated Use #Ipc_call_ipc. + * Deprecated call code, do not use this operation code. + */ + Ipc_call = 0, + + /** + * Set this bit to include a send phase. + * + * In the case of a send phase, the message is send to the object + * denoted by either the capability selector (cap()), the reply capability + * (if #Ipc_reply is also set), or to the thread itself (if the cap is the + * special self capability). + */ + Ipc_send = 1, + + /** + * Set this bit to include a receive phase. + * + * During the receive phase the caller waits for a message from either a + * specific sender (closed wait) or from any possible sender + * (#Ipc_open_wait) that has a capability to send messages to the invoker. + */ + Ipc_recv = 2, + + /** + * Set this bit to denote an open-wait receive phase. + * + * An open wait means that the invoker shall wait for a message from any + * sender that has a capability to send messages to the invoker. In this + * case the index (cap()) in the capability selector are ignored for the + * receive phase. + */ + Ipc_open_wait = 4, + + /** + * Set this bit to make the send phase a reply. + * + * A reply operation uses the implicit reply capability that is stored + * in per thread storage and can be used only once. The reply capability + * also vanishes in the case of an abort due to the caller or a newly + * received call operation by the same thread. + * \see #Ipc_send. + */ + Ipc_reply = 8, + + /** + * Denotes a wait operation. (#Ipc_recv | #Ipc_open_wait). + * + * The wait operation is usually used by servers to implement remote + * objects. + */ + Ipc_wait = Ipc_open_wait | Ipc_recv, + + /** + * Denotes a combination of a send and a wait operation (#Ipc_send | + * #Ipc_recv | #Ipc_open_wait). + * + * \note this is not used for usual RPC, see #Ipc_reply_and_wait for that. + */ + Ipc_send_and_wait = Ipc_open_wait | Ipc_send | Ipc_recv, + + /** + * Denotes a reply and wait operation (#Ipc_send | #Ipc_reply | #Ipc_recv | + * #Ipc_open_wait). + * + * This operation is usually used to send replies to RPC requests. + */ + Ipc_reply_and_wait = Ipc_open_wait | Ipc_send | Ipc_recv | Ipc_reply, + + /** + * Denotes a call operation (#Ipc_send | #Ipc_recv). + * + * A call is usually used by a client to invoke an operation on a remote + * object and wait for a result. The call operation establishes the + * implicit reply capability for the partner thread (see #Ipc_reply) + * and enables the implementation of an object to respond to an invocation + * without knowledge of the invoker thread. + */ + Ipc_call_ipc = Ipc_send | Ipc_recv, + }; + + /** + * Special capability selectors (e.g., Invalid cap). + */ + enum Special + { + /** + * Invalid capability selector. + */ + Invalid = 1UL << 11UL, + + /** + * Bit that flags a capability selector as special. + */ + Special_bit = 1UL << 11UL, + + /** + * Value for the self capability selector. This means, the invoking thread + * references itself. + */ + Self = (~0UL) << 11UL, + + /** + * Mask for getting all bits of special capabilities. + */ + Special_mask = (~0UL) << 11UL, + }; + + enum + { + Cap_shift = 12UL + }; + + /** + * Create a special capability selector from \a s. + * \param s which special cap selector shall be created + * (see L4_obj_ref::Special). + * + * Special capability selectors are the invalid capability and the self + * Capability. All special capability selectors must have the #Special_bit + * set. + */ + L4_obj_ref(Special s = Invalid) : _raw(s) {} + + /** + * Create a capability selector from it's binary representation. + * \param raw the raw binary representation of a capability selector. As + * passed from user land. + */ + static L4_obj_ref from_raw(Mword raw) { return L4_obj_ref(true, raw); } + + /** + * Is the capability selector a valid capability (no special capability). + * \return true if the capability selector is a valid index into the + * capability table, or false if the selector is a special + * capability. + */ + bool valid() const { return !(_raw & Special_bit); } + + /** + * Is the capability selector a special capability (i.e., not an index + * into the capability table). + * \return true if the capability selector denotes a special capability + * (see L4_obj_ref::Special), or false if this capability is a + * valid index into a capability table. + * + */ + bool special() const { return _raw & Special_bit; } + + /** + * Is this capability selector the special \a self capability. + * \return true if this capability is the special self capability for the + * invoking thread. + */ + bool self() const { return special(); } + + /** + * Get the value of a special capability. + * \pre special() == true + * \return the value of a special capability selector, see + * L4_obj_ref::Special. + */ + Special special_cap() const { return Special(_raw & Special_mask); } + //bool self() const { return (_raw & Invalid_mask) == Self; } + + /** + * Does the operation contain a receive phase? + * \return true if the operation encoded in the capability selector + * comprises a receive phase, see #L4_obj_ref::Ipc_recv. + */ + unsigned have_recv() const { return _raw & Ipc_recv; } + + /** + * Get the index into the capability table. + * \pre valid() == true + * \return The index into the capability table stored in the capability + * selector (i.e., the most significant bits of the selector). + */ + unsigned long cap() const { return _raw >> 12; } + + /** + * Get the operation stored in this selector (see L4_obj_ref::Operation). + * \return The operation encoded in the lower 4 bits of the capability + * selector, see L4_obj_ref::Operation. + */ + Operation op() const { return Operation(_raw & 0xf); } + + /** + * Get the raw binary representation of this capability selector. + * \return the binary representation of this cap selector. + */ + Mword raw() const { return _raw; } + + /** + * Create a valid capability selector for the shifted cap-table index + * and the operation. + * \param cap the shifted (<< #Cap_shift) capability-table index. + * \param op the operation to be encoded in bits 0..3. + */ + explicit L4_obj_ref(Mword cap, Operation op = None) : _raw(cap | op) {} + + /** + * Create a capability selector (index 0) with the given operation. + * \param op the operation to be encoded into the capability selector, + * see L4_obj_ref::Operation. + */ + L4_obj_ref(Operation op) : _raw(op) {} + + /** + * Compare two capability selectors for equality. + * \param o the right hand side for te comparison. + * \note Capability selectors are compared by their binary representation. + */ + bool operator == (L4_obj_ref const &o) const { return _raw == o._raw; } + +private: + L4_obj_ref(bool, Mword raw) : _raw(raw) {} + Mword _raw; +}; + + +/** + * Flags for unmap operations. + */ +class L4_map_mask +{ +public: + + /** + * Create a from binary representation. + * \param raw the binary representation, as passed from user level. + */ + explicit L4_map_mask(Mword raw = 0) : _raw(raw) {} + + /** + * Get the flags for a full unmap. + * \return A L4_map_mask for doing a full unmap operation. + */ + static L4_map_mask full() { return L4_map_mask(0xc0000002); } + + /** + * Get the raw binary representation for the map mask. + * \return the binary value of the flags. + */ + Mword raw() const { return _raw; } + + /** + * Unmap from the calling Task too. + * \return true if the caller wishes to unmap from its own address space too. + */ + Mword self_unmap() const { return _raw & 0x80000000; } + + /** + * Shall the unmap delete the object if allowed? + * \return true if the unmap operation shall also delete the kernel + * object if permitted to the caller. + */ + Mword do_delete() const { return _raw & 0x40000000; } + +private: + Mword _raw; +}; + + +/** + * Description of a message to the kernel or other thread. + * + * A message tag determines the number of untyped message words (words()), the + * number of typed message items (items(), L4_msg_item), some flags, and a + * protocol ID. The number of typed and untyped items in the UTCB's message + * registers, as well as the flags, control the kernels message passing + * mechanism. The protocol ID is not interpreted by the message passing + * itself, however is interpreted by the receiving object itself. In thread to + * thread IPC the all contents besides the flags are copied from the sender to + * the receiver. The flags on the receiver side contain some information about + * the operation itself. + * + * The untyped message words are copied to the receiving object/thread + * uninterpreted. The typed items directly following the untyped words in + * the message registers are interpreted by the message passing and contain, + * for example, map items for memory or kernel objects (see L4_msg_item, + * L4_fpage). + */ +class L4_msg_tag +{ +public: + /** + * Flags in the message tag. + * + * The input flags control the send phase of an IPC operation. Flags might + * have a different semantics in the returned message tag, the result of an + * IPC operation, see L4_msg_tag::Output_flags. However, the #Transfer_fpu + * and #Schedule flags are passed to the receiver. + */ + enum Flags + { + /** + * The sender is transferring the state of the floating-point unit (FPU) + * as part of the message. + * \note The receiver needs to agree with that by setting + * L4_buf_desc::Inherit_fpu in its buffer descriptor register (BDR). + * \note This flag is passed through to the receiver. + */ + Transfer_fpu = 0x1000, + + /** + * The sender does not want to donate its remaining time-slice to the + * receiver (partner) thread. + * \note This flag is passed on to the receiver. + */ + Schedule = 0x2000, + + /** + * The sender wants to propagate an incoming call operation to a different + * thread. + * \note Not implemented in Fiasco.OC. + * + * Propagation means that the reply capability shall be passed on to the + * receiver of this message to enable a direct reply. + */ + Propagate = 0x4000, // snd only flag + }; + + /** + * Result flags for IPC operations. + * + * These flags are dedicated return values for an IPC operation. + */ + enum Output_flags + { + /** + * The IPC operation did not succeed, the detailed error code + * is in the error register in the UTCB. + */ + Error = 0x8000, + + /** + * The IPC operation did cross CPU boundaries. + */ + X_cpu = 0x4000, + + /** + * Combination of flags that are not pass through. + */ + Rcv_flags = Error | X_cpu, + }; + + /** + * Protocol IDs that are defined by the kernel ABI. + * + * These protocol IDs are used for either kernel implemented + * objects, or used for kernel-synthesized requests to user + * objects. + */ + enum Protocol + { + Label_none = 0, ///< No protocol, the default + /** + * Value to allow the current system call for an alien thread. + * + * This value is used in the reply to an alien pre-syscall exception IPC. + */ + Label_allow_syscall = 1, + + Label_irq = -1L, ///< IRQ object protocol. + Label_page_fault = -2L, ///< Page fault messages use this protocol. + Label_preemption = -3L, ///< Preemption IPC protocol. \note unused. + Label_sys_exception = -4L, ///< Sys exception protocol. \note unused. + Label_exception = -5L, ///< Exception IPC protocol. + Label_sigma0 = -6L, ///< Protocol for sigma0 objects. + Label_io_page_fault = -8L, ///< Protocol for I/O-port page faults. + Label_kobject = -10L, ///< Control protocol iD for IPC gates (server + /// side). + Label_task = -11L, ///< Protocol ID for task and VM objects. + Label_thread = -12L, ///< Protocol ID for thread objects. + Label_log = -13L, ///< Protocol ID for log / vcon objects. + Label_scheduler = -14L, ///< Protocol ID for scheduler objects. + Label_factory = -15L, ///< Protocol ID for factory objects. + Label_vm = -16L, ///< Protocol ID for VM objects (used for create + /// operations on a factory). + Label_semaphore = -20L, ///< Protocol ID for semaphore objects. + }; +private: + Mword _tag; +}; + +/** + * L4 timeouts data type. + */ +class L4_timeout +{ +public: + /// Typical timeout constants. + enum { + Never = 0, ///< Never timeout. + Zero = 0x400, ///< Zero timeout. + }; + + /** + * Create the specified timeout. + * @param man mantissa of the send timeout. + * @param exp exponent of the send timeout + * (exp=0: infinite timeout, + * exp>0: t=2^(exp)*man, + * man=0 & exp!=0: t=0). + */ + L4_timeout(Mword man, Mword exp); + L4_timeout(Mword man, Mword exp, bool clock); + + /** + * Create a timeout from it's binary representation. + * @param t the binary timeout value. + */ + L4_timeout(unsigned short t = 0); + + /** + * Get the binary representation of the timeout. + * @return The timeout as binary representation. + */ + unsigned short raw() const; + + /** + * Get the receive exponent. + * @return The exponent of the receive timeout. + * @see rcv_man() + */ + Mword exp() const; + + /** + * Set the exponent of the receive timeout. + * @param er the exponent for the receive timeout (see L4_timeout()). + * @see rcv_man() + */ + void exp(Mword er); + + /** + * Get the receive timout's mantissa. + * @return The mantissa of the receive timeout (see L4_timeout()). + * @see rcv_exp() + */ + Mword man() const; + + /** + * Set the mantissa of the receive timeout. + * @param mr the mantissa of the recieve timeout (see L4_timeout()). + * @see rcv_exp() + */ + void man(Mword mr); + + /** + * Get the relative receive timeout in microseconds. + * @param clock Current value of kernel clock + * @return The receive timeout in micro seconds. + */ + Unsigned64 microsecs_rel(Unsigned64 clock) const; + + /** + * Get the absolute receive timeout in microseconds. + * @param clock Current value of kernel clock + * @return The receive timeout in micro seconds. + */ + Unsigned64 microsecs_abs(Utcb *u) const; + +private: + enum + { + Clock_mask = 0x0400, + Abs_mask = 0x8000, + + Exp_mask = 0x7c00, + Exp_shift = 10, + + Man_mask = 0x3ff, + Man_shift = 0, + }; + + unsigned short _t; +} __attribute__((packed)); + +struct L4_timeout_pair +{ + L4_timeout rcv; + L4_timeout snd; + + L4_timeout_pair(L4_timeout const &rcv, L4_timeout const &snd) + : rcv(rcv), snd(snd) {} + + L4_timeout_pair(unsigned long v) : rcv(v), snd(v >> 16) {} + + Mword raw() const { return (Mword)rcv.raw() | (Mword)snd.raw() << 16; } +}; + +/** + * This class contains constants for the message size for exception IPC. + * + * This information is architecture dependent, see #Msg_size. + */ +class L4_exception_ipc +{}; + +class L4_semaphore +{ +public: + Smword counter; + Mword flags; +}; + +/** + * Constants for error codes returned by kernel objects. + */ +class L4_err +{ +public: + enum Err + { + EPerm = 1, ///< Permission denied. + ENoent = 2, ///< Some object was not found. + ENomem = 12, ///< Out of memory. + EBusy = 16, ///< The object is busy, try again. + EExists = 17, ///< Some object does already exist. + ENodev = 19, ///< Objects of the specified type cannot be created. + EInval = 22, ///< Invalid parameters passed. + ENosys = 38, ///< No such operation. + EBadproto = 39, ///< Protocol not supported by object. + + EAddrnotavail = 99, ///< The given address is not available. + }; +}; + + +//---------------------------------------------------------------------------- +INTERFACE [ia32 || ux]: + +EXTENSION class L4_exception_ipc +{ +public: + enum { Msg_size = 16 }; +}; + + +//---------------------------------------------------------------------------- +INTERFACE [arm]: + +EXTENSION class L4_exception_ipc +{ +public: + enum { Msg_size = 20 }; +}; + + +//---------------------------------------------------------------------------- +INTERFACE [amd64]: + +EXTENSION class L4_exception_ipc +{ +public: + enum { Msg_size = 23 }; +}; + +INTERFACE [ppc32]: +EXTENSION class L4_exception_ipc +{ +public: + enum { Msg_size = 39 }; +}; + +INTERFACE [sparc]: +EXTENSION class L4_exception_ipc +{ +public: + enum { Msg_size = 12 }; // XXX whatever? +}; + +//---------------------------------------------------------------------------- +INTERFACE: + +/** + * User-level Thread Control Block (UTCB). + * + * The UTCB is a virtual extension of the registers of a thread. A UTCB + * comprises three sets of registers: the message registers (MRs), the buffer + * registers (BRs and BDR), and the control registers (TCRs). + * + * The message registers (MRs) contain the contents of the messages that are + * sent to objects or received from objects. The message contents consist of + * untyped data and typed message items (see L4_msg_tag). The untyped must be + * stored in the first \a n message registers (\a n = L4_msg_tag::words()) and + * are transferred / copied uninterpreted to the receiving object (MRs of + * receiver thread or kernel object). The typed items follow starting at MR[\a + * n+1]. Each typed item is stored in two MRs and is interpreted by the kernel + * (see L4_msg_item, L4_fpage). The number of items is denoted by + * L4_msg_tag::items(). On the receiver side the typed items are translated + * into a format that is useful for the receiver and stored at into the same + * MRs in the receivers UTCB. + * + * The buffer registers (BRs and BDR) contain information that describe receive + * buffers for incoming typed items. The contents of these registers are not + * altered by the kernel. The buffer descriptor register (BDR, Utcb::buf_desc) + * contains information about the items in the buffer registers (BRs) and + * flags to enable FPU state transfer. The BRs contain a set of receive + * message items (L4_msg_item) that describe receive buffers, such as, virtual + * memory regions for incoming memory mappings or buffers for capabilities. + * The BRs are also used to store absolute 64bit timeout values for operations, + * The value of the timeout pair encodes the number of the BR if an absolute + * timeout is used. + * + * The thread control registers (TCRs) comprise an error code for errors during + * message passing and a set of user-level registers. The user-level registers + * are not used by the kernel and provide and anchor for thread-local storage. + */ +class Utcb +{ + /* must be 2^n bytes */ +public: + + /** + * Type for time values in the UTCB (size is fix 64bit). + * + * On 32bit architectures this type uses two MRs on 64bit one Mr is used. + * This type is used for conversion of time values stored in MRs or BRs. + */ + union Time_val + { + enum { Words = sizeof(Cpu_time)/sizeof(Mword) /**< Number of MRs used. */ }; + Mword b[Words]; ///< The array of MRs to use. + Cpu_time t; ///< The time value itself. + }; + + enum + { + Max_words = 63, ///< Number of MRs. + Max_buffers = 58 ///< Number of BRs. + }; + + /// The message registers (MRs). + Mword values[Max_words]; + Mword utcb_addr; + + /// The buffer descriptor register (BDR). + L4_buf_desc buf_desc; + /// The buffer registers (BRs). + Mword buffers[Max_buffers]; + + /// The error code for IPC (TCR). + L4_error error; + /// \deprecated transfer timeout is not used currently (TCR). + L4_timeout_pair xfer; + /// The user-level registers for TLS (TCR). + Mword user[3]; +}; + +//---------------------------------------------------------------------------- +IMPLEMENTATION: + +#include + +/** + * Receiver is ready to receive FPU contents? + * \return true if the receiver is ready to receive the state of the FPU as + * part of a message. + * \see L4_buf_desc::Inherit_fpu, L4_buf_desc. + */ +PUBLIC inline +bool Utcb::inherit_fpu() const +{ return buf_desc.flags() & L4_buf_desc::Inherit_fpu; } + + +/** + * Create a message tag from its parts. + * \param words the number of untyped message words to transfer. + * \param items the number of typed message items, following the untyped words + * in the message registers. See L4_msg_item. + * \param flags the flags, see L4_msg_tag::Flags and L4_msg_tag::Output_flags. + * \param proto the protocol ID to use. + */ +PUBLIC inline +L4_msg_tag::L4_msg_tag(unsigned words, unsigned items, unsigned long flags, + unsigned long proto) + : _tag((words & 0x3f) | ((items & 0x3f) << 6) | flags | (proto << 16)) +{} + +/** + * Create an uninitialized message tag. + * \note the value of the tag is unpredictable. + */ +PUBLIC inline +L4_msg_tag::L4_msg_tag() +{} + +/** + * Create a message tag from another message tag, replacing + * the L4_msg_tag::Output_flags. + * \param o the message tag to copy. + * \param flags the output flags to set in the new tag. + * \pre (flags & ~Rcv_flags) == 0 + */ +PUBLIC inline +L4_msg_tag::L4_msg_tag(L4_msg_tag const &o, Mword flags) + : _tag((o.raw() & ~Mword(Rcv_flags)) | flags) +{} + +/** + * Create msg tag from the binary representation. + * \param raw the raw binary representation, as passed from user level. + */ +PUBLIC explicit inline +L4_msg_tag::L4_msg_tag(Mword raw) + : _tag(raw) +{} + +/** + * Get the protocol ID. + * \return the protocol ID. + */ +PUBLIC inline +long +L4_msg_tag::proto() const +{ return long(_tag) >> 16; } + +/** + * Get the binary representation. + * \return the binary value of the tag. + */ +PUBLIC inline +unsigned long +L4_msg_tag::raw() const +{ return _tag; } + +/** + * Get the number of untyped words to deliver. + * \return number message registers that shall be transferred + * uninterpreted to the receiving object. + */ +PUBLIC inline +unsigned L4_msg_tag::words() const +{ return _tag & 63; } + +/** + * Get the number of typed message items in the message. + * \return the number of typed items, directly following the + * untyped words in the message registers. + * \see L4_msg_item. + */ +PUBLIC inline +unsigned L4_msg_tag::items() const +{ return (_tag >> 6) & 0x3f; } + +/** + * Get the flags of the tag. + * \return the flags of the message tag, note reserved bits might be + * set in the result. + */ +PUBLIC inline +Mword L4_msg_tag::flags() const +{ return _tag; } + +/** + * Transfer the FPU? + * \return true if the sender wishes to transfer FPU contents. + * \see #Transfer_fpu. + */ +PUBLIC inline +bool L4_msg_tag::transfer_fpu() const +{ return _tag & Transfer_fpu; } + +/** + * Do time-slice donation? + * \return true if the sender is willing to donate its remaining time- + * slice to the receiver. + * \see #Schedule. + */ +PUBLIC inline +bool L4_msg_tag::do_switch() const +{ return !(_tag & Schedule); } + +/** + * Set the error flag to \a e. + * \param e the value of the error flag to be set. + */ +PUBLIC inline +void L4_msg_tag::set_error(bool e = true) +{ if (e) _tag |= Error; else _tag &= ~Mword(Error); } + +/** + * Is there an error flagged? + * \return true if the error flag of the message tag is set. + */ +PUBLIC inline +bool L4_msg_tag::has_error() const +{ return _tag & Error; } +// +// L4_timeout implementation +// + +IMPLEMENT inline L4_timeout::L4_timeout(unsigned short t) + : _t(t) +{} + +IMPLEMENT inline unsigned short L4_timeout::raw() const +{ return _t; } + +PUBLIC inline +Mword L4_timeout::abs_exp() const +{ return (_t >> 11) & 0xf; } + +PUBLIC inline +bool L4_timeout::abs_clock() const +{ return _t & Clock_mask; } + +IMPLEMENT inline +Unsigned64 +L4_timeout::microsecs_rel(Unsigned64 clock) const +{ + if (man() == 0) + return 0; + else + return clock + ((Unsigned64)man() << exp()); +} + +IMPLEMENT inline NEEDS[] +Unsigned64 +L4_timeout::microsecs_abs(Utcb *u) const +{ + int idx = min(_t & 0x3f, Utcb::Max_buffers); + Utcb::Time_val const *top + = reinterpret_cast(&u->buffers[idx]); + return top->t; +} + +PUBLIC inline +bool +L4_timeout::is_absolute() const +{ return _t & Abs_mask; } + +PUBLIC inline +Unsigned64 +L4_timeout::microsecs(Unsigned64 clock, Utcb *u) const +{ + if (is_absolute()) + return microsecs_abs(u); + else + return microsecs_rel(clock); +} + +PUBLIC inline +bool L4_timeout::is_never() const +{ return !_t; } + +PUBLIC inline +bool L4_timeout::is_zero() const +{ return _t == Zero; } + +PUBLIC inline +unsigned short L4_timeout::is_finite() const +{ return _t; } + + +// +// L4_timeout implementation +// + +IMPLEMENT inline +L4_timeout::L4_timeout(Mword man, Mword exp) +: _t (((man & Man_mask) | ((exp << Exp_shift) & Exp_mask))) +{} + +IMPLEMENT inline +L4_timeout::L4_timeout(Mword man, Mword exp, bool clock) +: _t (((man & Man_mask) | ((exp << (Exp_shift+1)) & Exp_mask) + | (clock ? Clock_mask : 0) | Abs_mask)) +{} + +IMPLEMENT inline Mword L4_timeout::exp() const +{ return (_t & Exp_mask) >> Exp_shift; } + +IMPLEMENT inline void L4_timeout::exp(Mword w) +{ _t = (_t & ~Exp_mask) | ((w << Exp_shift) & Exp_mask); } + +IMPLEMENT inline Mword L4_timeout::man() const +{ return (_t & Man_mask) >> Man_shift; } + +IMPLEMENT inline void L4_timeout::man (Mword w) +{ _t = (_t & ~Man_mask) | ((w << Man_shift) & Man_mask); } + + + + diff --git a/kernel/fiasco/src/abi/ppc32/kip-ppc32.cpp b/kernel/fiasco/src/abi/ppc32/kip-ppc32.cpp new file mode 100644 index 00000000..c740a92d --- /dev/null +++ b/kernel/fiasco/src/abi/ppc32/kip-ppc32.cpp @@ -0,0 +1,76 @@ +/* + * PPC32 Kernel-Info Page + */ + +INTERFACE [ppc32]: + +#include "types.h" + +EXTENSION class Kip +{ +public: + + /* 0x00 */ + Mword magic; + Mword version; + Unsigned8 offset_version_strings; + Unsigned8 fill0[3]; + Unsigned8 kip_sys_calls; + Unsigned8 fill1[3]; + + /* the following stuff is undocumented; we assume that the kernel + info page is located at offset 0x1000 into the L4 kernel boot + image so that these declarations are consistent with section 2.9 + of the L4 Reference Manual */ + + /* 0x10 */ + Mword sched_granularity; + Mword _res1[3]; + + /* 0x20 */ + Mword sigma0_sp, sigma0_ip; + Mword _res2[2]; + + /* 0x30 */ + Mword sigma1_sp, sigma1_ip; + Mword _res3[2]; + + /* 0x40 */ + Mword root_sp, root_ip; + Mword _res4[2]; + + /* 0x50 */ + Mword _res_50; + Mword _mem_info; + Mword _res_58[2]; + + /* 0x60 */ + Mword _res5[16]; + + /* 0xA0 */ + volatile Cpu_time clock; + Unsigned64 _res6; + + /* 0xB0 */ + Mword frequency_cpu; + Mword frequency_bus; + + /* 0xB8 */ + Mword _res7[10]; + + /* 0xE0 */ + Mword user_ptr; + Mword vhw_offset; + Unsigned32 _res8[2]; + + /* 0xF0 */ + Unsigned32 __reserved[20]; +}; + +//--------------------------------------------------------------------------- +IMPLEMENTATION [ppc32 && debug]: + +IMPLEMENT inline +void +Kip::debug_print_syscalls() const +{} diff --git a/kernel/fiasco/src/abi/sparc/kip-sparc.cpp b/kernel/fiasco/src/abi/sparc/kip-sparc.cpp new file mode 100644 index 00000000..352e0a98 --- /dev/null +++ b/kernel/fiasco/src/abi/sparc/kip-sparc.cpp @@ -0,0 +1,76 @@ +/* + * SPARC Kernel-Info Page + */ + +INTERFACE [sparc]: + +#include "types.h" + +EXTENSION class Kip +{ +public: + + /* 0x00 */ + Mword magic; + Mword version; + Unsigned8 offset_version_strings; + Unsigned8 fill0[3]; + Unsigned8 kip_sys_calls; + Unsigned8 fill1[3]; + + /* the following stuff is undocumented; we assume that the kernel + info page is located at offset 0x1000 into the L4 kernel boot + image so that these declarations are consistent with section 2.9 + of the L4 Reference Manual */ + + /* 0x10 */ + Mword sched_granularity; + Mword _res1[3]; + + /* 0x20 */ + Mword sigma0_sp, sigma0_ip; + Mword _res2[2]; + + /* 0x30 */ + Mword sigma1_sp, sigma1_ip; + Mword _res3[2]; + + /* 0x40 */ + Mword root_sp, root_ip; + Mword _res4[2]; + + /* 0x50 */ + Mword _res_50; + Mword _mem_info; + Mword _res_58[2]; + + /* 0x60 */ + Mword _res5[16]; + + /* 0xA0 */ + volatile Cpu_time clock; + Unsigned64 _res6; + + /* 0xB0 */ + Mword frequency_cpu; + Mword frequency_bus; + + /* 0xB8 */ + Mword _res7[10]; + + /* 0xE0 */ + Mword user_ptr; + Mword vhw_offset; + Unsigned32 _res8[2]; + + /* 0xF0 */ + Unsigned32 __reserved[20]; +}; + +//--------------------------------------------------------------------------- +IMPLEMENTATION [sparc && debug]: + +IMPLEMENT inline +void +Kip::debug_print_syscalls() const +{} diff --git a/kernel/fiasco/src/abi/virt-ia32-amd64.cpp b/kernel/fiasco/src/abi/virt-ia32-amd64.cpp new file mode 100644 index 00000000..f9c37558 --- /dev/null +++ b/kernel/fiasco/src/abi/virt-ia32-amd64.cpp @@ -0,0 +1,147 @@ +INTERFACE [svm]: + +#include "l4_types.h" + +// TODO: Make this sharable with user-land (see uarts) +struct Vmcb_control_area +{ + Unsigned16 intercept_rd_crX; + Unsigned16 intercept_wr_crX; + + Unsigned16 intercept_rd_drX; + Unsigned16 intercept_wr_drX; + + Unsigned32 intercept_exceptions; + + Unsigned32 intercept_instruction0; + Unsigned32 intercept_instruction1; + + Unsigned8 _reserved0[44]; + + Unsigned64 iopm_base_pa; + Unsigned64 msrpm_base_pa; + Unsigned64 tsc_offset; + Unsigned64 guest_asid_tlb_ctl; + Unsigned64 interrupt_ctl; + Unsigned64 interrupt_shadow; + Unsigned64 exitcode; + Unsigned64 exitinfo1; + Unsigned64 exitinfo2; + Unsigned64 exitintinfo; + Unsigned64 np_enable; + + Unsigned8 _reserved1[16]; + + Unsigned64 eventinj; + Unsigned64 n_cr3; + Unsigned64 lbr_virtualization_enable; + + Unsigned8 _reserved2[832]; +} __attribute__((packed)); + +struct Vmcb_state_save_area +{ + Unsigned16 es_sel; + Unsigned16 es_attrib; + Unsigned32 es_limit; + Unsigned64 es_base; + + Unsigned16 cs_sel; + Unsigned16 cs_attrib; + Unsigned32 cs_limit; + Unsigned64 cs_base; + + Unsigned16 ss_sel; + Unsigned16 ss_attrib; + Unsigned32 ss_limit; + Unsigned64 ss_base; + + Unsigned16 ds_sel; + Unsigned16 ds_attrib; + Unsigned32 ds_limit; + Unsigned64 ds_base; + + Unsigned16 fs_sel; + Unsigned16 fs_attrib; + Unsigned32 fs_limit; + Unsigned64 fs_base; + + Unsigned16 gs_sel; + Unsigned16 gs_attrib; + Unsigned32 gs_limit; + Unsigned64 gs_base; + + Unsigned16 gdtr_sel; + Unsigned16 gdtr_attrib; + Unsigned32 gdtr_limit; + Unsigned64 gdtr_base; + + Unsigned16 ldtr_sel; + Unsigned16 ldtr_attrib; + Unsigned32 ldtr_limit; + Unsigned64 ldtr_base; + + Unsigned16 idtr_sel; + Unsigned16 idtr_attrib; + Unsigned32 idtr_limit; + Unsigned64 idtr_base; + + Unsigned16 tr_sel; + Unsigned16 tr_attrib; + Unsigned32 tr_limit; + Unsigned64 tr_base; + + Unsigned8 _reserved0[43]; + + Unsigned8 cpl; + + Unsigned32 _reserved1; + + Unsigned64 efer; + + Unsigned8 _reserved2[112]; + + Unsigned64 cr4; + Unsigned64 cr3; + Unsigned64 cr0; + Unsigned64 dr7; + Unsigned64 dr6; + Unsigned64 rflags; + Unsigned64 rip; + + Unsigned8 _reserved3[88]; + + Unsigned64 rsp; + + Unsigned8 _reserved4[24]; + + Unsigned64 rax; + Unsigned64 star; + Unsigned64 lstar; + Unsigned64 cstar; + Unsigned64 sfmask; + Unsigned64 kernelgsbase; + Unsigned64 sysenter_cs; + Unsigned64 sysenter_esp; + Unsigned64 sysenter_eip; + Unsigned64 cr2; + + Unsigned8 _reserved5[32]; + + Unsigned64 g_pat; + Unsigned64 dbgctl; + Unsigned64 br_from; + Unsigned64 br_to; + Unsigned64 lastexcpfrom; + Unsigned64 last_excpto; + + Unsigned8 _reserved6[2408]; +} __attribute__((packed)); + +struct Vmcb +{ + unsigned np_enabled() const { return control_area.np_enable & 1; } + + Vmcb_control_area control_area; + Vmcb_state_save_area state_save_area; +} __attribute__((packed)); diff --git a/kernel/fiasco/src/boot/amd64/Makerules.BOOT.amd64 b/kernel/fiasco/src/boot/amd64/Makerules.BOOT.amd64 new file mode 100644 index 00000000..cdafb985 --- /dev/null +++ b/kernel/fiasco/src/boot/amd64/Makerules.BOOT.amd64 @@ -0,0 +1,37 @@ +# -*- makefile -*- +# Boot Makefile + +# Add future prerequisites somewhere among the list of libraries. +# You really should not have to add anything in the $(LD) line. + +boot_img.o: boot_img.x2 boot_img.ren_syms + $(LINK_MESSAGE) + $(VERBOSE)$(OBJCOPY) --redefine-syms=boot_img.ren_syms $< $@ + +boot_img.ren_syms: boot_img.x2 + $(LINK_MESSAGE) + $(VERBOSE)$(NM) -u $^ | perl -n -e 'if (/^\s*U\s+bootstrap_(.*)$$/) { print "bootstrap_$$1 $$1\n"; }' > $@ + +boot_img.x1: $(OBJ_BOOT) $(DRIVERS) $(MINILIBC) + $(LINK_MESSAGE) + $(VERBOSE)$(LD) -m $(LD_EMULATION) -r -s -o $@ \ + -T $(srcdir)/boot/amd64/bootstrap.ld $^ $(LIBGCC) + +boot_img.x2: boot_img.x1 + $(LINK_MESSAGE) + $(VERBOSE)$(OBJCOPY) --prefix-alloc-sections=.bootstrap --prefix-symbols=bootstrap_ -G bootstrap__boot_start $^ $@ + + + +kernel.amd64.lds: linking.h + +$(KERNEL): kernel.amd64.lds boot_img.o $(CRT0) $(OBJ_KERNEL) $(JDB) $(LIBK) $(KERNEL_EXTRA_LIBS) $(ABI) $(JABI) libdrivers.a $(CXXLIB) $(LIBKERN) $(MINILIBC) libgluedriverslibc.a + $(LINK_MESSAGE) + $(VERBOSE)$(LD) -m elf_x86_64 -N -T $< -gc-sections \ + -o $@ $(filter-out $<,$+) $(LIBGCC) $(KERNEL_UNRES_SYMS) + +$(BOOT): $(KERNEL) + $(LINK_MESSAGE) + $(VERBOSE)$(STRIP) -o $@ $< + $(VERBOSE)chmod 755 $@ + $(VERBOSE)ln -sf $@ fiasco diff --git a/kernel/fiasco/src/boot/amd64/boot.S b/kernel/fiasco/src/boot/amd64/boot.S new file mode 100644 index 00000000..17d4f9e0 --- /dev/null +++ b/kernel/fiasco/src/boot/amd64/boot.S @@ -0,0 +1,21 @@ +/* -*- c -*- */ + + .globl _boot_start + .p2align 4 +_boot_start: + lea _stack,%rsp + push $0 /* no return address */ + jmp bootstrap + + .align 4 + + .p2align(2), 0x90 + .long 0x1BADB002 /* magic */ + .long 0x00000000 /* feature flags */ + .long 0 - 0x1BADB002 + + .bss + .align 8 + .space 4096 +_stack: + diff --git a/kernel/fiasco/src/boot/amd64/boot_cpu.cc b/kernel/fiasco/src/boot/amd64/boot_cpu.cc new file mode 100644 index 00000000..1d4a6c05 --- /dev/null +++ b/kernel/fiasco/src/boot/amd64/boot_cpu.cc @@ -0,0 +1,634 @@ +#include +#include +#include + +#include "types.h" +#include "boot_cpu.h" +#include "boot_paging.h" +#include "mem_layout.h" +#include "processor.h" +#include "regdefs.h" + +enum +{ + PML4ESHIFT = 38, + PML4EMASK = 0x1ff, + PDPESHIFT = 30, + PDPEMASK = 0x1ff, + PDESHIFT = 21, + PDEMASK = 0x1ff, + PTESHIFT = 12, + PTEMASK = 0x1ff, + + INTEL_PTE_VALID = 0x0000000000000001LL, + INTEL_PTE_WRITE = 0x0000000000000002LL, + INTEL_PTE_USER = 0x0000000000000004LL, + INTEL_PTE_WTHRU = 0x00000008, + INTEL_PTE_NCACHE = 0x00000010, + INTEL_PTE_REF = 0x00000020, + INTEL_PTE_MOD = 0x00000040, + INTEL_PTE_GLOBAL = 0x00000100, + INTEL_PTE_AVAIL = 0x00000e00, + INTEL_PTE_PFN = 0x000ffffffffff000LL, + + INTEL_PDE_VALID = 0x0000000000000001LL, + INTEL_PDE_WRITE = 0x0000000000000002LL, + INTEL_PDE_USER = 0x0000000000000004LL, + INTEL_PDE_WTHRU = 0x00000008, + INTEL_PDE_NCACHE = 0x00000010, + INTEL_PDE_REF = 0x00000020, + INTEL_PDE_MOD = 0x00000040, + INTEL_PDE_SUPERPAGE = 0x0000000000000080LL, + INTEL_PDE_GLOBAL = 0x00000100, + INTEL_PDE_AVAIL = 0x00000e00, + INTEL_PDE_PFN = 0x000ffffffffff000LL, + + INTEL_PDPE_VALID = 0x0000000000000001LL, + INTEL_PDPE_WRITE = 0x0000000000000002LL, + INTEL_PDPE_USER = 0x0000000000000004LL, + INTEL_PDPE_PFN = 0x000ffffffffff000LL, + + INTEL_PML4E_VALID = 0x0000000000000001LL, + INTEL_PML4E_WRITE = 0x0000000000000002LL, + INTEL_PML4E_USER = 0x0000000000000004LL, + INTEL_PML4E_PFN = 0x000ffffffffff000LL, + + CPUF_4MB_PAGES = 0x00000008, + + BASE_TSS = 0x08, + KERNEL_DS = 0x18, + KERNEL_CS_64 = 0x20, // XXX + + DBF_TSS = 0x28, // XXX check this value + + ACC_TSS = 0x09, + ACC_TSS_BUSY = 0x02, + ACC_CODE_R = 0x1a, + ACC_DATA_W = 0x12, + ACC_PL_K = 0x00, + ACC_P = 0x80, + SZ_32 = 0x4, + SZ_16 = 0x0, + SZ_G = 0x8, + SZ_CODE_64 = 0x2, // XXX 64 Bit Code Segment + + GDTSZ = (0x30/8), // XXX check this value + IDTSZ = 256, +}; + + +struct pseudo_descriptor +{ + Unsigned16 pad; + Unsigned16 limit; + Unsigned64 linear_base; +} __attribute__((packed)); + +struct x86_desc +{ + Unsigned16 limit_low; + Unsigned16 base_low; + Unsigned8 base_med; + Unsigned8 access; + Unsigned8 limit_high:4; + Unsigned8 granularity:4; + Unsigned8 base_high; +} __attribute__((packed)); + +struct idt_desc +{ + Unsigned16 offset_low0; + Unsigned16 selector; + Unsigned8 zero_and_ist; + Unsigned8 access; + Unsigned16 offset_low1; + Unsigned32 offset_high; + Unsigned32 ignored; +} __attribute__((packed)); + +struct x86_tss +{ + Unsigned32 ign0; + Unsigned64 rsp0; + Unsigned64 rsp1; + Unsigned64 rsp2; + Unsigned32 ign1; + Unsigned32 ign2; + Unsigned64 ist1; + Unsigned64 ist2; + Unsigned64 ist3; + Unsigned64 ist4; + Unsigned64 ist5; + Unsigned64 ist6; + Unsigned64 ist7; + Unsigned32 ign3; + Unsigned32 ign4; + Unsigned16 ign5; + Unsigned16 io_bit_map_offset; +} __attribute__((packed)); + +struct idt_init_entry +{ + Unsigned64 entrypoint; + Unsigned16 vector; + Unsigned16 type; +} __attribute__((packed)); + +struct trap_state +{ + Unsigned64 rax, rbx, rcx, rdx; + Unsigned64 rdi, rsi, rbp, cr2; + Unsigned64 r8, r9, r10, r11; + Unsigned64 r12, r13, r14, r15; + Unsigned64 trapno, err; + Unsigned64 rip, cs, rflags, rsp, ss; +}; + +static Unsigned64 cpu_feature_flags; +static Address base_pml4_pa; +static struct x86_tss base_tss; +static struct x86_desc base_gdt[GDTSZ]; +static struct idt_desc base_idt[IDTSZ]; + +static char dbf_stack[2048]; + +extern "C" void _exit(int code) __attribute__((noreturn)); + +static inline Unsigned64* find_pml4e(Address pml4_pa, Address la) +{ return (&((Unsigned64*)pml4_pa)[(la >> PML4ESHIFT) & PML4EMASK]); } + +static inline Unsigned64* find_pdpe(Address pdp_pa, Address la) +{ return (&((Unsigned64*)pdp_pa)[(la >> PDPESHIFT) & PDPEMASK]); } + +static inline Unsigned64* find_pde(Address pdir_pa, Address la) +{ return (&((Unsigned64*)pdir_pa)[(la >> PDESHIFT) & PDEMASK]); } + +static inline Unsigned64* find_pte(Address ptab_pa, Address la) +{ return (&((Unsigned64*)ptab_pa)[(la >> PTESHIFT) & PTEMASK]); } + +extern inline Unsigned32 get_eflags() +{ Mword efl; asm volatile("pushf \n\t pop %0" : "=r" (efl)); return efl; } + +extern inline void set_eflags(Mword efl) +{ asm volatile("push %0 ; popf" : : "r" (efl) : "memory"); } + +extern inline void set_ds(Unsigned16 ds) +{ asm volatile("mov %w0,%%ds" : : "r" (ds)); } + +extern inline void set_es(Unsigned16 es) +{ asm volatile("mov %w0,%%es" : : "r" (es)); } + +extern inline void set_fs(Unsigned16 fs) +{ asm volatile("mov %w0,%%fs" : : "r" (fs)); } + +extern inline void set_gs(Unsigned16 gs) +{ asm volatile("mov %w0,%%gs" : : "r" (gs)); } + +extern inline void set_ss(Unsigned16 ss) +{ asm volatile("mov %w0,%%ss" : : "r" (ss)); } + +extern inline Unsigned16 get_ss() +{ Unsigned16 ss; asm volatile("mov %%ss,%w0" : "=r" (ss)); return ss; } + +#define set_idt(pseudo_desc) \ + asm volatile("lidt %0" : : "m"((pseudo_desc)->limit), "m"(*pseudo_desc)) + +#define set_gdt(pseudo_desc) \ + asm volatile("lgdt %0" : : "m"((pseudo_desc)->limit), "m"(*pseudo_desc)) + +#define set_tr(seg) \ + asm volatile("ltr %0" : : "rm" ((Unsigned16)(seg))) + +#define get_esp() \ + ({ register Unsigned64 _temp__; \ + asm("mov %%rsp, %0" : "=r" (_temp__)); _temp__; }) + +#define get_cr0() \ + ({ register Unsigned64 _temp__; \ + asm volatile("mov %%cr0, %0" : "=r" (_temp__)); _temp__; }) + +#define set_cr3(value) \ + ({ register Unsigned64 _temp__ = (value); \ + asm volatile("mov %0, %%cr3" : : "r" (_temp__)); }) + +#define get_cr4() \ + ({ register Unsigned64 _temp__; \ + asm volatile("mov %%cr4, %0" : "=r" (_temp__)); _temp__; }) + +#define set_cr4(value) \ + ({ register Unsigned64 _temp__ = (value); \ + asm volatile("mov %0, %%cr4" : : "r" (_temp__)); }) + + +extern inline void enable_longmode() +{ Proc::efer(Proc::efer() | Proc::Efer_lme_flag); } + +static inline void +fill_descriptor(struct x86_desc *desc, Unsigned32 base, Unsigned32 limit, + Unsigned8 access, Unsigned8 sizebits) +{ + if (limit > 0xfffff) + { + limit >>= 12; + sizebits |= SZ_G; + } + desc->limit_low = limit & 0xffff; + desc->base_low = base & 0xffff; + desc->base_med = (base >> 16) & 0xff; + desc->access = access | ACC_P; + desc->limit_high = limit >> 16; + desc->granularity = sizebits; + desc->base_high = base >> 24; +} + +static inline void +fill_idt_desc(struct idt_desc *desc, Unsigned64 offset, + Unsigned16 selector, Unsigned8 access, Unsigned8 ist_entry) +{ + desc->offset_low0 = offset & 0x000000000000ffffLL; + desc->selector = selector; + desc->zero_and_ist = ist_entry; + desc->access = access | ACC_P; + desc->offset_low1 = (offset & 0x00000000ffff0000LL) >> 16; + desc->offset_high = (offset & 0xffffffff00000000LL) >> 32; + desc->ignored = 0; +} + +inline void ALWAYS_INLINE +paging_enable(Address pml4) +{ + /* Enable Physical Address Extension (PAE). */ + set_cr4(get_cr4() | CR4_PAE); + + /* Load the page map level 4. */ + set_cr3(pml4); + + /* Enable long mode. */ + enable_longmode(); + + /* Turn on paging and switch to long mode. */ + asm volatile("mov %0,%%cr0 ; jmp 1f ; 1:" : : "r" (get_cr0() | CR0_PG)); +} + +static void +panic(const char *str) +{ + printf("\n%s\n", str); + _exit(-1); +} + +static void +cpuid() +{ + int orig_eflags = get_eflags(); + + /* Check for a dumb old 386 by trying to toggle the AC flag. */ + set_eflags(orig_eflags ^ EFLAGS_AC); + if ((get_eflags() ^ orig_eflags) & EFLAGS_AC) + { + /* It's a 486 or better. Now try toggling the ID flag. */ + set_eflags(orig_eflags ^ EFLAGS_ID); + if ((get_eflags() ^ orig_eflags) & EFLAGS_ID) + { + int highest_val, dummy; + asm volatile("cpuid" + : "=a" (highest_val) + : "a" (0) : "ebx", "ecx", "edx"); + + if (highest_val >= 1) + { + asm volatile("cpuid" + : "=a" (dummy), + "=d" (cpu_feature_flags) + : "a" (1) + : "ebx", "ecx"); + } + } + } + + set_eflags(orig_eflags); +} + +extern "C" struct idt_init_entry boot_idt_inittab[]; +static void +base_idt_init(void) +{ + struct idt_desc *dst = base_idt; + const struct idt_init_entry *src = boot_idt_inittab; + + while (src->entrypoint) + { + fill_idt_desc(&dst[src->vector], src->entrypoint, KERNEL_CS_64, + src->type,(src->vector==8)?1:0); + src++; + } +} + +static void +base_gdt_init(void) +{ + printf("base_tss @%p\n", &base_tss); + /* Initialize the base TSS descriptor. */ + fill_descriptor(&base_gdt[BASE_TSS / 8], + (Address)&base_tss, sizeof(base_tss) - 1, + ACC_PL_K | ACC_TSS, 0); + + memset(&base_gdt[(BASE_TSS / 8) + 1], 0, 8); + + /* Initialize the 64-bit kernel code and data segment descriptors + to point to the base of the kernel linear space region. */ + fill_descriptor(&base_gdt[KERNEL_CS_64 / 8], 0, 0xffffffff, + ACC_PL_K | ACC_CODE_R, SZ_CODE_64); + + fill_descriptor(&base_gdt[KERNEL_DS / 8], 0, 0xffffffff, + ACC_PL_K | ACC_DATA_W, SZ_32); + +} + +static void +base_tss_init(void) +{ + base_tss.rsp0 = get_esp(); /* only temporary */ + base_tss.ist1 = (Unsigned64)(dbf_stack + sizeof(dbf_stack)); + base_tss.io_bit_map_offset = sizeof(base_tss); +} + +static void +base_gdt_load(void) +{ + struct pseudo_descriptor pdesc; + + /* Create a pseudo-descriptor describing the GDT. */ + pdesc.limit = sizeof(base_gdt) - 1; + pdesc.linear_base = (Address)&base_gdt; + + /* Load it into the CPU. */ + set_gdt(&pdesc); + + // XXX must be fixed + /* Reload all the segment registers from the new GDT. */ + asm volatile ( + "movabsq $1f, %%rax \n" + "pushq %%rbx \n" + "pushq %%rax \n" + "lretq \n" + "1: \n" + : + : "b" (KERNEL_CS_64) + : "rax", "memory"); + set_ds(KERNEL_DS); + set_es(KERNEL_DS); + set_ss(KERNEL_DS); + set_fs(0); + set_gs(0); +} + +static void +base_idt_load(void) +{ + struct pseudo_descriptor pdesc; + + /* Create a pseudo-descriptor describing the GDT. */ + pdesc.limit = sizeof(base_idt) - 1; + pdesc.linear_base = (Address)&base_idt; + set_idt(&pdesc); +} + +static void +base_tss_load(void) +{ + /* Make sure the TSS isn't marked busy. */ + base_gdt[BASE_TSS / 8].access &= ~ACC_TSS_BUSY; + asm volatile ("" : : : "memory"); + set_tr(BASE_TSS); +} + +void +base_cpu_setup(void) +{ + cpuid(); + base_idt_init(); + base_gdt_init(); + base_tss_init(); + // force tables to memory before loading segment registers + asm volatile ("" : : : "memory"); + base_gdt_load(); + base_idt_load(); + base_tss_load(); +} + +static void +ptab_alloc(Address *out_ptab_pa) +{ + static char pool[69<<12] __attribute__((aligned(4096))); + static Address pdirs; + static int initialized; + + if (! initialized) + { + initialized = 1; + memset(pool, 0, sizeof(pool)); + pdirs = ((Address)pool + PAGE_SIZE - 1) & ~PAGE_MASK; + } + + if (pdirs > (Address)pool + sizeof(pool)) + panic("Cannot allocate page table -- increase ptab_alloc::pool"); + + *out_ptab_pa = pdirs; + pdirs += PAGE_SIZE; +} + +static void +pdir_map_range(Address pml4_pa, Address la, Address pa, + Unsigned32 size, Unsigned32 mapping_bits) +{ + assert(la+size-1 > la); // avoid 4GB wrap around + + while (size > 0) + { + Unsigned64 *pml4e = find_pml4e(pml4_pa, la); + + /* Create new pml4e with corresponding pdp (page directory pointer) + * if no valid entry exists. */ + if (!(*pml4e & INTEL_PML4E_VALID)) + { + Address pdp_pa; + + /* Allocate new page for pdp. */ + ptab_alloc(&pdp_pa); + + /* Set the pml4 to point to it. */ + *pml4e = (pdp_pa & INTEL_PML4E_PFN) + | INTEL_PML4E_VALID | INTEL_PML4E_USER | INTEL_PML4E_WRITE; + } + + do + { + Unsigned64 *pdpe = find_pdpe(*pml4e & INTEL_PML4E_PFN, la); + + /* Create new pdpe with corresponding pd (page directory) + * if no valid entry exists. */ + if (!(*pdpe & INTEL_PDPE_VALID)) + { + Address pd_pa; + + /* Allocate new page for pd. */ + ptab_alloc(&pd_pa); + + /* Set the pdpe to point to it. */ + *pdpe = (pd_pa & INTEL_PDPE_PFN) + | INTEL_PDPE_VALID | INTEL_PDPE_USER | INTEL_PDPE_WRITE; + } + + do + { + Unsigned64 *pde = find_pde(*pdpe & INTEL_PDPE_PFN, la); + + /* Use a 2MB page if we can. */ + if (superpage_aligned(la) && superpage_aligned(pa) + && (size >= SUPERPAGE_SIZE)) + //&& (cpu_feature_flags & CPUF_4MB_PAGES)) XXX + { + /* a failed assertion here may indicate a memory wrap + around problem */ + assert(!(*pde & INTEL_PDE_VALID)); + /* XXX what if an empty page table exists + from previous finer-granularity mappings? */ + *pde = pa | mapping_bits | INTEL_PDE_SUPERPAGE; + la += SUPERPAGE_SIZE; + pa += SUPERPAGE_SIZE; + size -= SUPERPAGE_SIZE; + } + else + { + /* Find the page table, creating one if necessary. */ + if (!(*pde & INTEL_PDE_VALID)) + { + Address ptab_pa; + + /* Allocate a new page table. */ + ptab_alloc(&ptab_pa); + + /* Set the pde to point to it. */ + *pde = (ptab_pa & INTEL_PTE_PFN) + | INTEL_PDE_VALID | INTEL_PDE_USER | INTEL_PDE_WRITE; + } + assert(!(*pde & INTEL_PDE_SUPERPAGE)); + + + /* Use normal 4KB page mappings. */ + do + { + Unsigned64 *pte = find_pte(*pde & INTEL_PDE_PFN, la); + assert(!(*pte & INTEL_PTE_VALID)); + + /* Insert the mapping. */ + *pte = pa | mapping_bits; + + /* Advance to the next page. */ + //pte++; + la += PAGE_SIZE; + pa += PAGE_SIZE; + size -= PAGE_SIZE; + } + while ((size > 0) && !superpage_aligned(la)); + } + } + while ((size > 0) && !pd_aligned(la)); + } + while ((size > 0) && !pdp_aligned(la)); + } +} + +void +base_paging_init(void) +{ + ptab_alloc(&base_pml4_pa); + + // Establish one-to-one mappings for the first 4MB of physical memory + pdir_map_range(base_pml4_pa, /*virt*/0, /*phys*/0, /*size*/4 << 20, + INTEL_PDE_VALID | INTEL_PDE_WRITE | INTEL_PDE_USER); + + // map in the first 4MB of physical memory to 0xfffffffff0000000 + pdir_map_range(base_pml4_pa, Mem_layout::Kernel_image, + Mem_layout::Kernel_image_phys, + Mem_layout::Kernel_image_end - Mem_layout::Kernel_image, + INTEL_PDE_VALID | INTEL_PDE_WRITE | INTEL_PDE_USER); + + // Adapter memory needs a seperate mapping + if (!Mem_layout::Adap_in_kernel_image) + // map in the adapter memory (superpage) of physical memory to ... + pdir_map_range(base_pml4_pa, /*virt*/Mem_layout::Adap_image, + /*phys*/Mem_layout::Adap_image_phys, + /*size*/Config::SUPERPAGE_SIZE, + INTEL_PDE_VALID | INTEL_PDE_WRITE | INTEL_PDE_USER); + + // XXX Turn on paging and activate 64Bit mode + paging_enable(base_pml4_pa); +} + +void +base_map_physical_memory_for_kernel() +{ + unsigned long sz = Mem_layout::pmem_size; + printf("map pmem %14lx-%14lx to %14lx-%14lx\n", + Mem_layout::pmem_to_phys(Mem_layout::Physmem), + Mem_layout::pmem_to_phys(Mem_layout::Physmem) + sz, + Mem_layout::Physmem, + Mem_layout::Physmem + sz); + // map in the last 60MB of physical memory to 0xfc400000 + pdir_map_range(base_pml4_pa, + /*virt*/Mem_layout::Physmem, + /*phys*/Mem_layout::pmem_to_phys(Mem_layout::Physmem), + /*size*/sz, + INTEL_PDE_VALID | INTEL_PDE_WRITE | INTEL_PDE_USER); +} + + +extern "C" void +trap_dump_panic(const struct trap_state *st) +{ + int from_user = (st->cs & 3); + int i; + + printf("RAX %016llx RBX %016llx\n", st->rax, st->rbx); + printf("RCX %016llx RDX %016llx\n", st->rcx, st->rdx); + printf("RSI %016llx RDI %016llx\n", st->rsi, st->rdi); + printf("RBP %016llx RSP %016llx\n", + st->rbp, from_user ? st->rsp : (Address)&st->rsp); + printf("R8 %016llx R9 %016llx\n", st->r8, st->r9); + printf("R10 %016llx R11 %016llx\n", st->r10, st->r11); + printf("R12 %016llx R13 %016llx\n", st->r12, st->r13); + printf("R14 %016llx R15 %016llx\n", st->r14, st->r15); + printf("RIP %016llx RFLAGS %016llx\n", st->rip, st->rflags); + printf("CS %04llx SS %04llx\n", + st->cs & 0xffff, from_user ? st->ss & 0xffff : get_ss()); + printf("trapno %lld, error %08llx, from %s mode\n", + st->trapno, st->err, from_user ? "user" : "kernel"); + if (st->trapno == 0x0d) + { + if (st->err & 1) + printf("(external event"); + else + printf("(internal event"); + if (st->err & 2) + { + printf(" regarding IDT gate descriptor no. 0x%02llx)\n", + st->err >> 3); + } + else + { + printf(" regarding %s entry no. 0x%02llx)\n", + st->err & 4 ? "LDT" : "GDT", st->err >> 3); + } + } + else if (st->trapno == 0x0e) + printf("page fault linear address %016llx\n", st->cr2); + + if (!from_user) + { + for (i = 0; i < 32; i++) + printf("%016llx%c", (&st->rsp)[i], ((i & 7) == 7) ? '\n' : ' '); + } + panic("Unexpected trap while booting Fiasco!"); +} diff --git a/kernel/fiasco/src/boot/amd64/boot_idt.S b/kernel/fiasco/src/boot/amd64/boot_idt.S new file mode 100644 index 00000000..2ce0abe0 --- /dev/null +++ b/kernel/fiasco/src/boot/amd64/boot_idt.S @@ -0,0 +1,99 @@ + +#define GATE_INITTAB_BEGIN(name) \ + .text 1 ;\ + .globl name ;\ +name: ;\ + .text + +#define GATE_ENTRY(n,entry,type) \ + .text 1 ;\ + .quad entry ;\ + .word n ;\ + .word type ;\ + .text + +#define GATE_INITTAB_END \ + .text 1 ;\ + .quad 0 ;\ + .text + +#define EXCEPTION(n,name) \ + GATE_ENTRY(n,name,0x0e) ;\ +name: ;\ + push $(0) ;\ + push $(n) ;\ + jmp alltraps + +#define EXCEP_USR(n,name) \ + GATE_ENTRY(n,name,0x6e) ;\ +name: ;\ + push $(0) ;\ + push $(n) ;\ + jmp alltraps + +#define EXCEP_ERR(n,name) \ + GATE_ENTRY(n,name,0x0e) ;\ +name: ;\ + push $(n) ;\ + jmp alltraps + + +GATE_INITTAB_BEGIN(boot_idt_inittab) + +EXCEPTION(0x00,t_zero_div) +EXCEPTION(0x01,t_debug) +EXCEPTION(0x02,t_nmi) +EXCEP_USR(0x03,t_int3) +EXCEP_USR(0x04,t_into) +EXCEP_USR(0x05,t_bounds) +EXCEPTION(0x06,t_invop) +EXCEPTION(0x07,t_nofpu) +EXCEPTION(0x08,t_double_fault) +EXCEPTION(0x09,a_fpu_over) +EXCEP_ERR(0x0a,a_inv_tss) +EXCEP_ERR(0x0b,t_segnp) +EXCEP_ERR(0x0c,t_stack_fault) +EXCEP_ERR(0x0d,t_gen_prot) +EXCEP_ERR(0x0e,t_page_fault) +EXCEPTION(0x0f,t_trap_0f) +EXCEPTION(0x10,t_fpu_err) +EXCEPTION(0x11,t_trap_11) +EXCEPTION(0x12,t_trap_12) +EXCEPTION(0x13,t_trap_13) +EXCEPTION(0x14,t_trap_14) +EXCEPTION(0x15,t_trap_15) +EXCEPTION(0x16,t_trap_16) +EXCEPTION(0x17,t_trap_17) +EXCEPTION(0x18,t_trap_18) +EXCEPTION(0x19,t_trap_19) +EXCEPTION(0x1a,t_trap_1a) +EXCEPTION(0x1b,t_trap_1b) +EXCEPTION(0x1c,t_trap_1c) +EXCEPTION(0x1d,t_trap_1d) +EXCEPTION(0x1e,t_trap_1e) +EXCEPTION(0x1f,t_trap_1f) + +GATE_INITTAB_END + +alltraps: + push %r15 + push %r14 + push %r13 + push %r12 + push %r11 + push %r10 + push %r9 + push %r8 + mov %cr2,%r8 + push %r8 + push %rbp + push %rsi + push %rdi + push %rdx + push %rcx + push %rbx + push %rax + + + call trap_dump_panic + diff --git a/kernel/fiasco/src/boot/amd64/boot_paging.h b/kernel/fiasco/src/boot/amd64/boot_paging.h new file mode 100644 index 00000000..0e423067 --- /dev/null +++ b/kernel/fiasco/src/boot/amd64/boot_paging.h @@ -0,0 +1,39 @@ +#ifndef BOOT_PAGING_H +#define BOOT_PAGING_H + +#include "types.h" + +enum +{ + PAGE_SIZE = (1 << 12), + PAGE_MASK = (PAGE_SIZE - 1), + SUPERPAGE_SIZE = (1 << 21), + SUPERPAGE_MASK = (SUPERPAGE_SIZE - 1), + PD_SIZE = (1 << 30), + PD_MASK = (PD_SIZE - 1), + PDP_SIZE = (1LL << 39), + PDP_MASK = (PDP_SIZE - 1), +}; + +static inline int +superpage_aligned(Address x) +{ return (x & SUPERPAGE_MASK) == 0; } + +static inline int +pd_aligned(Address x) +{ return (x & PD_MASK) == 0; } + +static inline int +pdp_aligned(Address x) +{ return (x & PDP_MASK) == 0; } + +static inline Address trunc_page(Address x) +{ return x & ~PAGE_MASK; } + +static inline Address round_page(Address x) +{ return (x + PAGE_MASK) & ~PAGE_MASK; } + +static inline Address round_superpage(Address x) +{ return (x + SUPERPAGE_MASK) & ~SUPERPAGE_MASK; } + +#endif diff --git a/kernel/fiasco/src/boot/amd64/bootstrap.ld b/kernel/fiasco/src/boot/amd64/bootstrap.ld new file mode 100644 index 00000000..4f5b99f8 --- /dev/null +++ b/kernel/fiasco/src/boot/amd64/bootstrap.ld @@ -0,0 +1,19 @@ +FORCE_COMMON_ALLOCATION +SECTIONS +{ + .text : + { + *(.init) + *(.text .text.* .gnu.linkonce.t.*) + *(.fini) + *(.rodata .rodata.* .gnu.linkonce.r.*) + *(.data .data.* .gnu.linkonce.d.*) + *(.anno) + } = 0x90909090 + + .bss : + { + *(.bss .gnu.linkonce.b.* COMMON) + } + +} diff --git a/kernel/fiasco/src/boot/arm/Makerules.BOOT.arm b/kernel/fiasco/src/boot/arm/Makerules.BOOT.arm new file mode 100644 index 00000000..98ac6653 --- /dev/null +++ b/kernel/fiasco/src/boot/arm/Makerules.BOOT.arm @@ -0,0 +1,23 @@ +# -*- makefile -*- +# Boot Makefile + +# Add future prerequisites somewhere among the list of libraries. +# You really should not have to add anything in the $(LD) line. + +$(BOOT): $(BOOT).elf + $(OBJCOPY) -O binary $< $@ + chmod 755 $@ + ln -sf $@ fiasco + $(call INSTALLFILE_RULE,fiasco,fiasco) + +$(BOOT).elf: $(KERNEL) + cp $(KERNEL) $(BOOT).elf + $(STRIP) $(BOOT).elf + +%.img.o: %.elf + $(OBJCOPY) -S $< $* + $(OBJCOPY) -B arm -I binary -O elf32-littlearm $* $@ + +kernel.o: $(KERNEL) + $(OBJCOPY) -S $(KERNEL) $(@:.o=) + $(OBJCOPY) -B arm -I binary -O elf32-littlearm $(@:.o=) $@ diff --git a/kernel/fiasco/src/boot/boot_cpu.h b/kernel/fiasco/src/boot/boot_cpu.h new file mode 100644 index 00000000..3ae3673c --- /dev/null +++ b/kernel/fiasco/src/boot/boot_cpu.h @@ -0,0 +1,10 @@ +#ifndef BOOT_CPU_H +#define BOOT_CPU_H + +#include "types.h" + +void base_paging_init (void); +void base_map_physical_memory_for_kernel (); +void base_cpu_setup (void); + +#endif diff --git a/kernel/fiasco/src/boot/boot_direct_cons.h b/kernel/fiasco/src/boot/boot_direct_cons.h new file mode 100644 index 00000000..c7d594c1 --- /dev/null +++ b/kernel/fiasco/src/boot/boot_direct_cons.h @@ -0,0 +1,6 @@ +#ifndef BOOT_DIRECT_CONS_H +#define BOOT_DIRECT_CONS_H + +void direct_cons_putchar(unsigned char c); + +#endif diff --git a/kernel/fiasco/src/boot/boot_libc_glue.cc b/kernel/fiasco/src/boot/boot_libc_glue.cc new file mode 100644 index 00000000..1b42db44 --- /dev/null +++ b/kernel/fiasco/src/boot/boot_libc_glue.cc @@ -0,0 +1,17 @@ +#include + +#include "boot_direct_cons.h" + +unsigned long __libc_backend_printf_lock() +{ return 0; } + +void __libc_backend_printf_unlock(unsigned long) +{} + +int __libc_backend_outs(const char *s, size_t len) +{ + size_t i = 0; + for (; i < len; ++i) + direct_cons_putchar(s[i]); + return 1; +} diff --git a/kernel/fiasco/src/boot/bootstrap.cc b/kernel/fiasco/src/boot/bootstrap.cc new file mode 100644 index 00000000..5e7224ae --- /dev/null +++ b/kernel/fiasco/src/boot/bootstrap.cc @@ -0,0 +1,107 @@ +/* this code is run directly from boot.S. our task is to setup the + paging just enough so that L4 can run in its native address space + at 0xf0001000, and then start up L4. */ + +#include +#include +#include +#include + +#include "boot_cpu.h" +#include "boot_paging.h" +#include "boot_console.h" +#include "kernel_console.h" +#include "checksum.h" +#include "config.h" +#include "globalconfig.h" +#include "kip.h" +#include "kmem_alloc.h" +#include "mem_layout.h" +#include "mem_region.h" +#include "panic.h" +#include "processor.h" +#include "reset.h" + +struct check_sum +{ + char delimiter[16]; + Unsigned32 checksum_ro; + Unsigned32 checksum_rw; +} check_sum = {"FIASCOCHECKSUM=", 0, 0}; + +extern "C" char _start[]; +extern "C" char _end[]; + +extern "C" void exit(int rc) __attribute__((noreturn)); + +void +exit(int) +{ + for (;;) + Proc::pause(); +} + +// test if [start1..end1-1] overlaps [start2..end2-1] +static +void +check_overlap (const char *str, + Address start1, Address end1, Address start2, Address end2) +{ + if ((start1 >= start2 && start1 < end2) || (end1 > start2 && end1 <= end2)) + panic("Kernel [0x%014lx,0x%014lx) overlaps %s [0x%014lx,0x%014lx).", + start1, end1, str, start2, end2); +} + +typedef void (*Start)(void *, unsigned, unsigned) FIASCO_FASTCALL; + +extern "C" FIASCO_FASTCALL +void +bootstrap (void *, unsigned int flag) +{ + extern Kip my_kernel_info_page; + Start start; + + // setup stuff for base_paging_init() + base_cpu_setup(); + // now do base_paging_init(): sets up paging with one-to-one mapping + base_paging_init(); + + asm volatile ("" ::: "memory"); + + Kip::init_global_kip(&my_kernel_info_page); + Kconsole::init(); + Boot_console::init(); + printf("Boot: KIP @ %p\n", Kip::k()); + + printf("Boot: Kmem_alloc::base_init();\n"); + if (!Kmem_alloc::base_init()) + { + panic("FATAL: Could not reserve kernel memory, halted\n"); + } + printf("Boot: kernel memory reserved\n"); + + // make sure that we did not forgot to discard an unused header section + // (compare "objdump -p fiasco.image") + if ((Address)_start < Mem_layout::Kernel_image) + panic("Fiasco kernel occupies memory below %014lx", + (unsigned long)Mem_layout::Kernel_image); + + if ((Address)&_end - Mem_layout::Kernel_image > 4<<20) + panic("Fiasco boot system occupies more than 4MB"); + + base_map_physical_memory_for_kernel(); + + start = (Start)_start; + + Address phys_start = (Address)_start - Mem_layout::Kernel_image + Mem_layout::Kernel_image_phys; + Address phys_end = (Address)_end - Mem_layout::Kernel_image + Mem_layout::Kernel_image_phys; + check_overlap ("VGA/IO", phys_start, phys_end, 0xa0000, 0x100000); + + if (Checksum::get_checksum_ro() != check_sum.checksum_ro) + panic("Read-only (text) checksum does not match."); + + if (Checksum::get_checksum_rw() != check_sum.checksum_rw) + panic("Read-write (data) checksum does not match."); + + start (0, flag, check_sum.checksum_ro); +} diff --git a/kernel/fiasco/src/boot/direct_cons_putchar.cc b/kernel/fiasco/src/boot/direct_cons_putchar.cc new file mode 100644 index 00000000..4036ae5b --- /dev/null +++ b/kernel/fiasco/src/boot/direct_cons_putchar.cc @@ -0,0 +1,44 @@ + +#include +#include "boot_direct_cons.h" +#include "boot_paging.h" + +void +direct_cons_putchar(unsigned char c) +{ + static int ofs = -1; + unsigned char *vidbase = ((unsigned char*)0xb8000); + + if (ofs < 0) + { + ofs = 0; + direct_cons_putchar('\n'); + } + + switch (c) + { + case '\n': + memcpy(vidbase, vidbase+80*2, 80*2*24); + memset(vidbase+80*2*24,0, 80*2); + /* fall through... */ + case '\r': + ofs = 0; + break; + + case '\t': + ofs = (ofs + 8) & ~7; + break; + + default: + if (ofs >= 80) + direct_cons_putchar('\n'); + + { + volatile unsigned char *p = vidbase + 80*2*24 + ofs*2; + p[0] = c; + p[1] = 0x0f; + ofs++; + } + break; + } +} diff --git a/kernel/fiasco/src/boot/ia32/Makerules.BOOT.ia32 b/kernel/fiasco/src/boot/ia32/Makerules.BOOT.ia32 new file mode 100644 index 00000000..1eb498ae --- /dev/null +++ b/kernel/fiasco/src/boot/ia32/Makerules.BOOT.ia32 @@ -0,0 +1,43 @@ +# -*- makefile -*- +# Boot Makefile + +# Add future prerequisites somewhere among the list of libraries. +# You really should not have to add anything in the $(LD) line. +# +# Don't link against libgcc because of -mregparm=3. The library +# would only be necessary for 64-bit arithmetics. These functions +# can be replaced by using div32/mod32 from lib/libk (and should +# for efficency reasons). + +boot_img.o: boot_img.x2 boot_img.ren_syms + $(LINK_MESSAGE) + $(VERBOSE)$(OBJCOPY) --redefine-syms=boot_img.ren_syms $< $@ + +boot_img.ren_syms: boot_img.x2 + $(LINK_MESSAGE) + $(VERBOSE)$(NM) -u $^ | perl -n -e 'if (/^\s*U\s+bootstrap_(.*)$$/) { print "bootstrap_$$1 $$1\n"; }' > $@ + +boot_img.x1: $(OBJ_BOOT) $(DRIVERS) $(MINILIBC) + $(LINK_MESSAGE) + $(VERBOSE)$(LD) -m $(LD_EMULATION) -r -s -o $@ \ + -T $(srcdir)/boot/ia32/bootstrap.ld $^ $(LIBGCC) + +boot_img.x2: boot_img.x1 + $(LINK_MESSAGE) + $(VERBOSE)$(OBJCOPY) --prefix-alloc-sections=.bootstrap --prefix-symbols=bootstrap_ -G bootstrap__boot_start $^ $@ + + + +kernel.ia32.lds: linking.h + +$(KERNEL): kernel.ia32.lds boot_img.o $(CRT0) $(OBJ_KERNEL) $(JDB) $(LIBK) $(KERNEL_EXTRA_LIBS) $(ABI) $(JABI) libdrivers.a $(CXXLIB) $(LIBKERN) $(MINILIBC) libgluedriverslibc.a + $(LINK_MESSAGE) + $(VERBOSE)$(LD) -m $(LD_EMULATION) -N -o $@ \ + -T $< -gc-sections $(filter-out $<,$+) \ + $(KERNEL_UNRES_SYMS) + +$(BOOT): $(KERNEL) + $(LINK_MESSAGE) + $(VERBOSE)$(STRIP) -o $@ $< + $(VERBOSE)chmod 755 $@ + $(VERBOSE)ln -sf $@ fiasco diff --git a/kernel/fiasco/src/boot/ia32/boot.S b/kernel/fiasco/src/boot/ia32/boot.S new file mode 100644 index 00000000..a3feb407 --- /dev/null +++ b/kernel/fiasco/src/boot/ia32/boot.S @@ -0,0 +1,19 @@ +/* -*- c -*- */ + + .globl _boot_start +_boot_start: + leal _stack,%esp + movl %eax,%edx /* mbinfo_flag */ + movl %ebx,%eax /* mbinfo */ + pushl $0 /* no return address */ + jmp bootstrap + + .align 4, 0x90 + .long 0x1BADB002 /* magic */ + .long 0x00000000 /* feature flags */ + .long 0 - 0x1BADB002 + + .bss + .space 1024 +_stack: + diff --git a/kernel/fiasco/src/boot/ia32/boot_cpu.cc b/kernel/fiasco/src/boot/ia32/boot_cpu.cc new file mode 100644 index 00000000..661b4741 --- /dev/null +++ b/kernel/fiasco/src/boot/ia32/boot_cpu.cc @@ -0,0 +1,561 @@ +#include +#include +#include + +#include "types.h" +#include "boot_cpu.h" +#include "boot_paging.h" +#include "mem_layout.h" +#include "panic.h" +#include "regdefs.h" + +enum +{ + PDESHIFT = 22, + PDEMASK = 0x3ff, + PTESHIFT = 12, + PTEMASK = 0x3ff, + + INTEL_PTE_VALID = 0x00000001, + INTEL_PTE_WRITE = 0x00000002, + INTEL_PTE_USER = 0x00000004, + INTEL_PTE_WTHRU = 0x00000008, + INTEL_PTE_NCACHE = 0x00000010, + INTEL_PTE_REF = 0x00000020, + INTEL_PTE_MOD = 0x00000040, + INTEL_PTE_GLOBAL = 0x00000100, + INTEL_PTE_AVAIL = 0x00000e00, + INTEL_PTE_PFN = 0xfffff000, + + INTEL_PDE_VALID = 0x00000001, + INTEL_PDE_WRITE = 0x00000002, + INTEL_PDE_USER = 0x00000004, + INTEL_PDE_WTHRU = 0x00000008, + INTEL_PDE_NCACHE = 0x00000010, + INTEL_PDE_REF = 0x00000020, + INTEL_PDE_MOD = 0x00000040, + INTEL_PDE_SUPERPAGE = 0x00000080, + INTEL_PDE_GLOBAL = 0x00000100, + INTEL_PDE_AVAIL = 0x00000e00, + INTEL_PDE_PFN = 0xfffff000, + CPUF_4MB_PAGES = 0x00000008, + + BASE_TSS = 0x08, + KERNEL_CS = 0x10, + KERNEL_DS = 0x18, + DBF_TSS = 0x20, + + ACC_TSS = 0x09, + ACC_TSS_BUSY = 0x02, + ACC_CODE_R = 0x1a, + ACC_DATA_W = 0x12, + ACC_PL_K = 0x00, + ACC_P = 0x80, + SZ_32 = 0x4, + SZ_16 = 0x0, + SZ_G = 0x8, + + GDTSZ = (0x28/8), + IDTSZ = 0x14, +}; + +struct pseudo_descriptor +{ + Unsigned16 pad; + Unsigned16 limit; + Unsigned32 linear_base; +}; + +struct x86_desc +{ + Unsigned16 limit_low; /* limit 0..15 */ + Unsigned16 base_low; /* base 0..15 */ + Unsigned8 base_med; /* base 16..23 */ + Unsigned8 access; /* access byte */ + Unsigned8 limit_high:4; /* limit 16..19 */ + Unsigned8 granularity:4; /* granularity */ + Unsigned8 base_high; /* base 24..31 */ +} __attribute__((packed)); + +struct x86_gate +{ + Unsigned16 offset_low; /* offset 0..15 */ + Unsigned16 selector; + Unsigned8 word_count; + Unsigned8 access; + Unsigned16 offset_high; /* offset 16..31 */ +} __attribute__((packed)); + +struct x86_tss +{ + Unsigned32 back_link; + Unsigned32 esp0, ss0; + Unsigned32 esp1, ss1; + Unsigned32 esp2, ss2; + Unsigned32 cr3; + Unsigned32 eip, eflags; + Unsigned32 eax, ecx, edx, ebx, esp, ebp, esi, edi; + Unsigned32 es, cs, ss, ds, fs, gs; + Unsigned32 ldt; + Unsigned16 trace_trap; + Unsigned16 io_bit_map_offset; +}; + +struct gate_init_entry +{ + Unsigned32 entrypoint; + Unsigned16 vector; + Unsigned16 type; +}; + +struct trap_state +{ + Unsigned32 gs, fs, es, ds; + Unsigned32 edi, esi, ebp, cr2, ebx, edx, ecx, eax; + Unsigned32 trapno, err; + Unsigned32 eip, cs, eflags, esp, ss; +}; + +static Unsigned32 cpu_feature_flags; +static Address base_pdir_pa; +static struct x86_tss base_tss; +static struct x86_desc base_gdt[GDTSZ]; +static struct x86_gate base_idt[IDTSZ]; + +static void handle_dbf(void); +static char dbf_stack[2048]; +static struct x86_tss dbf_tss = + { + 0/*back_link*/, + 0/*esp0*/, 0/*ss0*/, 0/*esp1*/, 0/*ss1*/, 0/*esp2*/, 0/*ss2*/, + 0/*cr3*/, + (Unsigned32)handle_dbf/*eip*/, 0x00000082/*eflags*/, + 0/*eax*/, 0/*ecx*/, 0/*edx*/, 0/*ebx*/, + (Unsigned32)dbf_stack + sizeof(dbf_stack)/*esp*/, + 0/*ebp*/, 0/*esi*/, 0/*edi*/, + KERNEL_DS/*es*/, KERNEL_CS/*cs*/, KERNEL_DS/*ss*/, + KERNEL_DS/*ds*/, KERNEL_DS/*fs*/, KERNEL_DS/*gs*/, + 0/*ldt*/, 0/*trace_trap*/, 0x8000/*io_bit_map_offset*/ + }; + +extern "C" void _exit(int code) __attribute__((noreturn)); + +static inline Address* pdir_find_pde(Address pdir_pa, Address la) +{ return (&((Address*)pdir_pa)[(la >> PDESHIFT) & PDEMASK]); } + +static inline Address* ptab_find_pte(Address ptab_pa, Address la) +{ return (&((Address*)ptab_pa)[(la >> PTESHIFT) & PTEMASK]); } + +extern inline Unsigned32 get_eflags() +{ Unsigned32 efl; asm volatile("pushf ; popl %0" : "=r" (efl)); return efl; } + +extern inline void set_eflags(Unsigned32 efl) +{ asm volatile("pushl %0 ; popf" : : "r" (efl) : "memory"); } + +extern inline void set_ds(Unsigned16 ds) +{ asm volatile("movw %w0,%%ds" : : "r" (ds)); } + +extern inline void set_es(Unsigned16 es) +{ asm volatile("movw %w0,%%es" : : "r" (es)); } + +extern inline void set_fs(Unsigned16 fs) +{ asm volatile("movw %w0,%%fs" : : "r" (fs)); } + +extern inline void set_gs(Unsigned16 gs) +{ asm volatile("movw %w0,%%gs" : : "r" (gs)); } + +extern inline void set_ss(Unsigned16 ss) +{ asm volatile("movw %w0,%%ss" : : "r" (ss)); } + +extern inline Unsigned16 get_ss() +{ Unsigned16 ss; asm volatile("movw %%ss,%w0" : "=r" (ss)); return ss; } + +#define set_idt(pseudo_desc) \ + asm volatile("lidt %0" : : "m"((pseudo_desc)->limit), "m"(*pseudo_desc)) + +#define set_gdt(pseudo_desc) \ + asm volatile("lgdt %0" : : "m"((pseudo_desc)->limit), "m"(*pseudo_desc)) + +#define set_tr(seg) \ + asm volatile("ltr %0" : : "rm"((Unsigned16)(seg))) + +#define get_esp() \ + ({ register Unsigned32 _temp__; \ + asm("movl %%esp, %0" : "=r" (_temp__)); _temp__; }) + +#define get_cr0() \ + ({ register Unsigned32 _temp__; \ + asm volatile("mov %%cr0, %0" : "=r" (_temp__)); _temp__; }) + +#define get_cr2() \ + ({ register Unsigned32 _temp__; \ + asm volatile("mov %%cr2, %0" : "=r" (_temp__)); _temp__; }) + +#define set_cr3(value) \ + ({ register Unsigned32 _temp__ = (value); \ + asm volatile("mov %0, %%cr3" : : "r" (_temp__)); }) + +#define get_cr4() \ + ({ register Unsigned32 _temp__; \ + asm volatile("mov %%cr4, %0" : "=r" (_temp__)); _temp__; }) + +#define set_cr4(value) \ + ({ register Unsigned32 _temp__ = (value); \ + asm volatile("mov %0, %%cr4" : : "r" (_temp__)); }) + +static inline void +fill_descriptor(struct x86_desc *desc, Unsigned32 base, Unsigned32 limit, + Unsigned8 access, Unsigned8 sizebits) +{ + if (limit > 0xfffff) + { + limit >>= 12; + sizebits |= SZ_G; + } + desc->limit_low = limit & 0xffff; + desc->base_low = base & 0xffff; + desc->base_med = (base >> 16) & 0xff; + desc->access = access | ACC_P; + desc->limit_high = limit >> 16; + desc->granularity = sizebits; + desc->base_high = base >> 24; +} + +static inline void +fill_gate(unsigned vector, Unsigned32 offset, + Unsigned16 selector, Unsigned8 access) +{ + base_idt[vector].offset_low = offset & 0xffff; + base_idt[vector].selector = selector; + base_idt[vector].word_count = 0; + base_idt[vector].access = access | ACC_P; + base_idt[vector].offset_high = (offset >> 16) & 0xffff; +} + +inline void ALWAYS_INLINE +paging_enable(Address pdir) +{ + /* Load the page directory. */ + set_cr3(pdir); + + /* Turn on paging. */ + asm volatile("movl %0,%%cr0 ; jmp 1f ; 1:" : : "r" ((get_cr0() & ~0xf0000000) | CR0_PG)); +} + +static void +cpuid() +{ + int orig_eflags = get_eflags(); + + /* Check for a dumb old 386 by trying to toggle the AC flag. */ + set_eflags(orig_eflags ^ EFLAGS_AC); + if ((get_eflags() ^ orig_eflags) & EFLAGS_AC) + { + /* It's a 486 or better. Now try toggling the ID flag. */ + set_eflags(orig_eflags ^ EFLAGS_ID); + if ((get_eflags() ^ orig_eflags) & EFLAGS_ID) + { + int highest_val, dummy; + asm volatile("cpuid" + : "=a" (highest_val) + : "a" (0) : "ebx", "ecx", "edx"); + + if (highest_val >= 1) + { + asm volatile("cpuid" + : "=a" (dummy), + "=d" (cpu_feature_flags) + : "a" (1) + : "ebx", "ecx"); + } + } + } + + set_eflags(orig_eflags); +} + +extern "C" struct gate_init_entry boot_idt_inittab[]; +static void +base_idt_init(void) +{ + const struct gate_init_entry *src = boot_idt_inittab; + + while (src->entrypoint) + { + if ((src->type & 0x1f) == 0x05) + // task gate + fill_gate(src->vector, 0, src->entrypoint, src->type); + else + // interrupt gate + fill_gate(src->vector, src->entrypoint, KERNEL_CS, src->type); + src++; + } +} + +static void +base_gdt_init(void) +{ + /* Initialize the base TSS descriptor. */ + fill_descriptor(&base_gdt[BASE_TSS / 8], + (Address)&base_tss, sizeof(base_tss) - 1, + ACC_PL_K | ACC_TSS, 0); + /* Initialize the TSS descriptor for the double fault handler */ + fill_descriptor(&base_gdt[DBF_TSS / 8], + (Address)&dbf_tss, sizeof(dbf_tss) - 1, + ACC_PL_K | ACC_TSS, 0); + /* Initialize the 32-bit kernel code and data segment descriptors + to point to the base of the kernel linear space region. */ + fill_descriptor(&base_gdt[KERNEL_CS / 8], 0, 0xffffffff, + ACC_PL_K | ACC_CODE_R, SZ_32); + fill_descriptor(&base_gdt[KERNEL_DS / 8], 0, 0xffffffff, + ACC_PL_K | ACC_DATA_W, SZ_32); +} + +static void +base_tss_init(void) +{ + base_tss.ss0 = KERNEL_DS; + base_tss.esp0 = get_esp(); /* only temporary */ + base_tss.io_bit_map_offset = sizeof(base_tss); +} + +static void +base_gdt_load(void) +{ + struct pseudo_descriptor pdesc; + + /* Create a pseudo-descriptor describing the GDT. */ + pdesc.limit = sizeof(base_gdt) - 1; + pdesc.linear_base = (Address)&base_gdt; + + /* Load it into the CPU. */ + set_gdt(&pdesc); + + /* Reload all the segment registers from the new GDT. */ + asm volatile("ljmp %0,$1f ; 1:" : : "i" (KERNEL_CS)); + set_ds(KERNEL_DS); + set_es(KERNEL_DS); + set_ss(KERNEL_DS); + set_fs(0); + set_gs(0); +} + +static void +base_idt_load(void) +{ + struct pseudo_descriptor pdesc; + + /* Create a pseudo-descriptor describing the GDT. */ + pdesc.limit = sizeof(base_idt) - 1; + pdesc.linear_base = (Address)&base_idt; + set_idt(&pdesc); +} + +static void +base_tss_load(void) +{ + /* Make sure the TSS isn't marked busy. */ + base_gdt[BASE_TSS / 8].access &= ~ACC_TSS_BUSY; + set_tr(BASE_TSS); +} + +void +base_cpu_setup(void) +{ + cpuid(); + base_idt_init(); + base_gdt_init(); + base_tss_init(); + // force tables to memory before loading segment registers + asm volatile ("" : : : "memory"); + base_gdt_load(); + base_idt_load(); + base_tss_load(); +} + +static void +ptab_alloc(Address *out_ptab_pa) +{ + static char pool[140<<12] __attribute__((aligned(4096))); + static Address pdirs; + static int initialized; + + if (! initialized) + { + initialized = 1; + memset(pool, 0, sizeof(pool)); + pdirs = round_page((Address)pool); + } + + if (pdirs >= (Address)pool + sizeof(pool)) + panic("Cannot allocate page table -- increase ptab_alloc::pool"); + + *out_ptab_pa = pdirs; + pdirs += PAGE_SIZE; +} + +static void +pdir_map_range(Address pdir_pa, Address la, Address pa, + Unsigned32 size, Unsigned32 mapping_bits) +{ + while (size > 0) + { + Address *pde = pdir_find_pde(pdir_pa, la); + + /* Use a 4MB page if we can. */ + if (superpage_aligned(la) && superpage_aligned(pa) + && (size >= SUPERPAGE_SIZE) + && (cpu_feature_flags & CPUF_4MB_PAGES)) + { + /* a failed assertion here may indicate a memory wrap + around problem */ + assert(!(*pde & INTEL_PDE_VALID)); + /* XXX what if an empty page table exists + from previous finer-granularity mappings? */ + *pde = pa | mapping_bits | INTEL_PDE_SUPERPAGE; + la += SUPERPAGE_SIZE; + pa += SUPERPAGE_SIZE; + size -= SUPERPAGE_SIZE; + } + else + { + Address *pte; + + /* Find the page table, creating one if necessary. */ + if (!(*pde & INTEL_PDE_VALID)) + { + Address ptab_pa; + + /* Allocate a new page table. */ + ptab_alloc(&ptab_pa); + + /* Set the pde to point to it. */ + *pde = (ptab_pa & INTEL_PTE_PFN) + | INTEL_PDE_VALID | INTEL_PDE_USER | INTEL_PDE_WRITE; + } + assert(!(*pde & INTEL_PDE_SUPERPAGE)); + pte = ptab_find_pte(*pde & INTEL_PDE_PFN, la); + + /* Use normal 4KB page mappings. */ + do + { + assert(!(*pte & INTEL_PTE_VALID)); + + /* Insert the mapping. */ + *pte = pa | mapping_bits; + + /* Advance to the next page. */ + pte++; + la += PAGE_SIZE; + pa += PAGE_SIZE; + size -= PAGE_SIZE; + } + while ((size > 0) && !superpage_aligned(la)); + } + } +} + +void +base_paging_init(void) +{ + // We assume that we only have to map the first 4MB page. This has + // to be checked before base_paging_init was called. + ptab_alloc(&base_pdir_pa); + + // Establish one-to-one mapping for the first 4MB of physical memory + pdir_map_range(base_pdir_pa, /*virt*/0, /*phys*/0, /*size*/4 << 20, + INTEL_PDE_VALID | INTEL_PDE_WRITE | INTEL_PDE_USER); + + // Enable superpage support if we have it + if (cpu_feature_flags & CPUF_4MB_PAGES) + set_cr4(get_cr4() | CR4_PSE); + + dbf_tss.cr3 = base_pdir_pa; + + // Turn on paging + paging_enable(base_pdir_pa); + + // map in the Kernel image (superpage) of physical memory to 0xf0000000 + pdir_map_range(base_pdir_pa, /*virt*/Mem_layout::Kernel_image, + Mem_layout::Kernel_image_phys, + /*size*/Mem_layout::Kernel_image_end - + Mem_layout::Kernel_image, + INTEL_PDE_VALID | INTEL_PDE_WRITE | INTEL_PDE_USER); + + // Adapter memory is already contrained in the kernel-image mapping + if (Mem_layout::Adap_in_kernel_image) + return; + + // map in the adapter memory (superpage) of physical memory to ... + pdir_map_range(base_pdir_pa, /*virt*/Mem_layout::Adap_image, + /*phys*/Mem_layout::Adap_image_phys, + /*size*/Config::SUPERPAGE_SIZE, + INTEL_PDE_VALID | INTEL_PDE_WRITE | INTEL_PDE_USER); +} + +void +base_map_physical_memory_for_kernel() +{ + unsigned long sz = Mem_layout::pmem_size; + // map in the last 60MB of physical memory to 0xfc400000 + pdir_map_range(base_pdir_pa, + /*virt*/Mem_layout::Physmem, + /*phys*/Mem_layout::pmem_to_phys(Mem_layout::Physmem), + /*size*/sz, + INTEL_PDE_VALID | INTEL_PDE_WRITE | INTEL_PDE_USER); +} + +static char const * const base_regs = + "\n" + "EAX %08x EBX %08x ECX %08x EDX %08x\n" + "ESI %08x EDI %08x EBP %08x ESP %08x\n" + "EIP %08x EFLAGS %08x\n" + "CS %04x SS %04x DS %04x ES %04x FS %04x GS %04x\n"; + +extern "C" FIASCO_FASTCALL +void +trap_dump_panic(const struct trap_state *st) +{ + int from_user = (st->cs & 3); + int i; + + printf(base_regs, + st->eax, st->ebx, st->ecx, st->edx, + st->esi, st->edi, st->ebp, from_user ? st->esp : (Unsigned32)&st->esp, + st->eip, st->eflags, + st->cs & 0xffff, from_user ? st->ss & 0xffff : get_ss(), + st->ds & 0xffff, st->es & 0xffff, st->fs & 0xffff, st->gs & 0xffff); + printf("trapno %d, error %08x, from %s mode\n", + st->trapno, st->err, from_user ? "user" : "kernel"); + if (st->trapno == 0x0d) + { + printf("(%sternal event regarding ", st->err & 1 ? "ex" : "in"); + if (st->err & 2) + printf("IDT gate descriptor"); + else + printf("%cDT entry", st->err & 4 ? 'L' : 'G'); + printf(" no. 0x%02x)\n", st->err >> 3); + } + else if (st->trapno == 0x0e) + printf("page fault linear address %08x\n", get_cr2()); + + if (!from_user) + { + for (i = 0; i < 32; i++) + printf("%08x%c", (&st->esp)[i], ((i & 7) == 7) ? '\n' : ' '); + } + panic("Unexpected trap while booting Fiasco!"); +} + +static void +handle_dbf() +{ + printf(base_regs, + base_tss.eax, base_tss.ebx, base_tss.ecx, base_tss.edx, + base_tss.esi, base_tss.edi, base_tss.ebp, base_tss.esp, + base_tss.eip, base_tss.eflags, + base_tss.cs & 0xffff, base_tss.ss & 0xffff, base_tss.ds & 0xffff, + base_tss.es & 0xffff, base_tss.fs & 0xffff, base_tss.gs & 0xffff); + + panic("Unexpected DOUBLE FAULT while booting Fiasco!"); +} diff --git a/kernel/fiasco/src/boot/ia32/boot_idt.S b/kernel/fiasco/src/boot/ia32/boot_idt.S new file mode 100644 index 00000000..1dfc4989 --- /dev/null +++ b/kernel/fiasco/src/boot/ia32/boot_idt.S @@ -0,0 +1,74 @@ +#include "globalconfig.h" + +#define GATE_INITTAB_BEGIN(name) \ + .text 1 ;\ + .globl name ;\ +name: ;\ + .text + +#define GATE_ENTRY(n,entry,type) \ + .text 1 ;\ + .long entry ;\ + .word n ;\ + .word type ;\ + .text + +#define GATE_INITTAB_END \ + .text 1 ;\ + .long 0 ;\ + .text + +#define EXCEPTION(n,name) \ + GATE_ENTRY(n,1f,0x0e) ;\ +1: pushl $(0) ;\ + pushl $(n) ;\ + jmp 2f + +#define EXCEP_USR(n,name) \ + GATE_ENTRY(n,1f,0x6e) ;\ +1: pushl $(0) ;\ + pushl $(n) ;\ + jmp 2f + +#define EXCEP_ERR(n,name) \ + GATE_ENTRY(n,1f,0x0e) ;\ +1: pushl $(n) ;\ + jmp 2f + + +GATE_INITTAB_BEGIN(boot_idt_inittab) + +EXCEPTION(0x00,t_zero_div) +EXCEPTION(0x01,t_debug) +EXCEPTION(0x02,t_nmi) +EXCEP_USR(0x03,t_int3) +EXCEP_USR(0x04,t_into) +EXCEP_USR(0x05,t_bounds) +EXCEPTION(0x06,t_invop) +EXCEPTION(0x07,t_nofpu) +GATE_ENTRY(0x08,0x20,0x05) +EXCEPTION(0x09,a_fpu_over) +EXCEP_ERR(0x0a,a_inv_tss) +EXCEP_ERR(0x0b,t_segnp) +EXCEP_ERR(0x0c,t_stack_fault) +EXCEP_ERR(0x0d,t_gen_prot) +EXCEP_ERR(0x0e,t_page_fault) +EXCEPTION(0x0f,t_trap_0f) +EXCEPTION(0x10,t_fpu_err) +EXCEPTION(0x11,t_trap_11) +EXCEPTION(0x12,t_trap_12) +EXCEPTION(0x13,t_trap_13) + +GATE_INITTAB_END + +2: pusha + pushl %ds + pushl %es + pushl %fs + pushl %gs + movl %ss,%eax + movl %eax,%ds + movl %eax,%es + movl %esp,%eax + call trap_dump_panic + diff --git a/kernel/fiasco/src/boot/ia32/boot_paging.h b/kernel/fiasco/src/boot/ia32/boot_paging.h new file mode 100644 index 00000000..9e899161 --- /dev/null +++ b/kernel/fiasco/src/boot/ia32/boot_paging.h @@ -0,0 +1,30 @@ +#ifndef BOOT_PAGING_H +#define BOOT_PAGING_H + +#include "types.h" + +enum +{ + PAGE_SIZE = (1 << 12), + PAGE_MASK = (PAGE_SIZE - 1), + SUPERPAGE_SIZE = (1 << 22), + SUPERPAGE_MASK = (SUPERPAGE_SIZE - 1), +}; + +static inline int +superpage_aligned(Address x) +{ return (x & SUPERPAGE_MASK) == 0; } + +static inline Address trunc_superpage(Address x) +{ return x & ~SUPERPAGE_MASK; } + +static inline Address trunc_page(Address x) +{ return x & ~PAGE_MASK; } + +static inline Address round_page(Address x) +{ return (x + PAGE_MASK) & ~PAGE_MASK; } + +static inline Address round_superpage(Address x) +{ return (x + SUPERPAGE_MASK) & ~SUPERPAGE_MASK; } + +#endif diff --git a/kernel/fiasco/src/boot/ia32/bootstrap.ld b/kernel/fiasco/src/boot/ia32/bootstrap.ld new file mode 100644 index 00000000..c200854b --- /dev/null +++ b/kernel/fiasco/src/boot/ia32/bootstrap.ld @@ -0,0 +1,18 @@ +SECTIONS +{ + .text : + { + *(.init) + *(.text .text.* .gnu.linkonce.t.*) + *(.fini) + *(.rodata .rodata.* .gnu.linkonce.r.*) + *(.data .data.* .gnu.linkonce.d.*) + *(.anno) + } = 0x90909090 + + .bss : + { + *(.bss .gnu.linkonce.b.* COMMON) + } + +} diff --git a/kernel/fiasco/src/doxygen.conf b/kernel/fiasco/src/doxygen.conf new file mode 100644 index 00000000..94adf241 --- /dev/null +++ b/kernel/fiasco/src/doxygen.conf @@ -0,0 +1,939 @@ +# Doxyfile 1.2.15 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project +# +# All text after a hash (#) is considered a comment and will be ignored +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" ") + +#--------------------------------------------------------------------------- +# General configuration options +#--------------------------------------------------------------------------- + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded +# by quotes) that should identify the project. + +PROJECT_NAME = Fiasco Microkernel + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = docs + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Brazilian, Chinese, Croatian, Czech, Danish, Dutch, Finnish, French, +# German, Greek, Hungarian, Italian, Japanese, Korean, Norwegian, Polish, +# Portuguese, Romanian, Russian, Slovak, Slovene, Spanish and Swedish. + +OUTPUT_LANGUAGE = English + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = YES + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = YES + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = YES + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these class will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all inherited +# members of a class in the documentation of that class as if those members were +# ordinary class members. Constructors, destructors and assignment operators of +# the base classes will not be shown. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = NO + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. It is allowed to use relative paths in the argument list. + +STRIP_FROM_PATH = + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = YES + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower case letters. If set to YES upper case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# users are adviced to set this option to NO. + +CASE_SENSE_NAMES = YES + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful is your file systems +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = NO + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = YES + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = YES + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like the Qt-style comments (thus requiring an +# explict @brief command for a brief description. + +#JAVADOC_AUTOBRIEF = NO +JAVADOC_AUTOBRIEF = YES + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# reimplements. + +INHERIT_DOCS = YES + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 8 + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = YES + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or define consist of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and defines in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 30 + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources +# only. Doxygen will then generate output that is more tailored for C. +# For instance some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources +# only. Doxygen will then generate output that is more tailored for Java. +# For instance namespaces will be presented as packages, qualified scopes +# will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = YES + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = YES + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = auto/ + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx *.hpp +# *.h++ *.idl *.odl + +FILE_PATTERNS = *.h *.cc + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = NO + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used select whether or not files or directories +# that are symbolic links (a Unix filesystem feature) are excluded from the input. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. + +EXCLUDE_PATTERNS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. + +INPUT_FILTER = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse. + +FILTER_SOURCE_FILES = NO + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. + +SOURCE_BROWSER = NO + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# If the REFERENCED_BY_RELATION tag is set to YES (the default) +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = YES + +# If the REFERENCES_RELATION tag is set to YES (the default) +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = YES + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = NO + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet + +HTML_STYLESHEET = + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. + +HTML_ALIGN_MEMBERS = YES + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the Html help documentation and to the tree view. + +TOC_EXPAND = NO + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. + +DISABLE_INDEX = NO + +# This tag can be used to set the number of enum values (range [1..20]) +# that doxygen will group on one line in the generated HTML documentation. + +ENUM_VALUES_PER_LINE = 4 + +# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be +# generated containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript and frames is required (for instance Mozilla, Netscape 4.0+, +# or Internet explorer 4.0+). Note that for large projects the tree generation +# can take a very long time. In such cases it is better to disable this feature. +# Windows users are probably better off using the HTML help feature. + +GENERATE_TREEVIEW = NO + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = NO + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be invoked. If left blank `latex' will be used as the default command name. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, a4wide, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = a4wide + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = NO + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = NO + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimised for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assigments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_XML = NO + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = NO + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_PREDEFINED tags. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# in the INCLUDE_PATH (see below) will be search if a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. + +PREDEFINED = + +# If the MACRO_EXPANSION and EXPAND_PREDEF_ONLY tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all function-like macros that are alone +# on a line and do not end with a semicolon. Such function macros are typically +# used for boiler-plate code, and will confuse the parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::addtions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES tag can be used to specify one or more tagfiles. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in Html, RTF and LaTeX) for classes with base or +# super classes. Setting the tag to NO turns the diagrams off. Note that this +# option is superceded by the HAVE_DOT option below. This is only a fallback. It is +# recommended to install and use dot, since it yield more powerful graphs. + +CLASS_DIAGRAMS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = NO + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# the CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = YES + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = YES + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = YES + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are png, jpg, or gif +# If left blank png will be used. + +DOT_IMAGE_FORMAT = png + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found on the path. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = + +# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width +# (in pixels) of the graphs generated by dot. If a graph becomes larger than +# this value, doxygen will try to truncate the graph, so that it fits within +# the specified constraint. Beware that most browsers cannot cope with very +# large images. + +MAX_DOT_GRAPH_WIDTH = 1024 + +# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height +# (in pixels) of the graphs generated by dot. If a graph becomes larger than +# this value, doxygen will try to truncate the graph, so that it fits within +# the specified constraint. Beware that most browsers cannot cope with very +# large images. + +MAX_DOT_GRAPH_HEIGHT = 1024 + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermedate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES + +#--------------------------------------------------------------------------- +# Configuration::addtions related to the search engine +#--------------------------------------------------------------------------- + +# The SEARCHENGINE tag specifies whether or not a search engine should be +# used. If set to NO the values of all tags below this one will be ignored. + +SEARCHENGINE = NO + +# The CGI_NAME tag should be the name of the CGI script that +# starts the search engine (doxysearch) with the correct parameters. +# A script with this name will be generated by doxygen. + +CGI_NAME = search.cgi + +# The CGI_URL tag should be the absolute URL to the directory where the +# cgi binaries are located. See the documentation of your http daemon for +# details. + +CGI_URL = + +# The DOC_URL tag should be the absolute URL to the directory where the +# documentation is located. If left blank the absolute path to the +# documentation, with file:// prepended to it, will be used. + +DOC_URL = + +# The DOC_ABSPATH tag should be the absolute path to the directory where the +# documentation is located. If left blank the directory on the local machine +# will be used. + +DOC_ABSPATH = + +# The BIN_ABSPATH tag must point to the directory where the doxysearch binary +# is installed. + +BIN_ABSPATH = /usr/local/bin/ + +# The EXT_DOC_PATHS tag can be used to specify one or more paths to +# documentation generated for other projects. This allows doxysearch to search +# the documentation for these projects as well. + +EXT_DOC_PATHS = diff --git a/kernel/fiasco/src/drivers/amd64/io-amd64.cpp b/kernel/fiasco/src/drivers/amd64/io-amd64.cpp new file mode 100644 index 00000000..7dba0942 --- /dev/null +++ b/kernel/fiasco/src/drivers/amd64/io-amd64.cpp @@ -0,0 +1,53 @@ +IMPLEMENTATION[amd64]: + + +/* This is a more reliable delay than a few short jmps. */ +IMPLEMENT inline +void Io::iodelay() +{ + asm("inb $0x80,%%al; inb $0x80,%%al" : : : "eax"); +} + +IMPLEMENT inline +Unsigned8 Io::in8 ( unsigned long port ) +{ + Unsigned8 tmp; + asm volatile ("inb %w1, %b0": "=a"(tmp) : "Nd"(port) ); + return tmp; +} + +IMPLEMENT inline +Unsigned16 Io::in16( unsigned long port ) +{ + Unsigned16 tmp; + asm volatile ("inw %w1, %w0": "=a"(tmp) : "Nd"(port) ); + return tmp; +} + +IMPLEMENT inline +Unsigned32 Io::in32( unsigned long port ) +{ + Unsigned32 tmp; + asm volatile ("in %w1, %0": "=a"(tmp) : "Nd"(port) ); + return tmp; +} + +IMPLEMENT inline +void Io::out8 ( Unsigned8 val, unsigned long port ) +{ + asm volatile ("outb %b0, %w1": : "a"(val), "Nd"(port) ); +} + +IMPLEMENT inline +void Io::out16( Unsigned16 val, unsigned long port ) +{ + asm volatile ("outw %w0, %w1": : "a"(val), "Nd"(port) ); +} + +IMPLEMENT inline +void Io::out32( Unsigned32 val, unsigned long port ) +{ + asm volatile ("out %0, %w1": : "a"(val), "Nd"(port) ); +} + + diff --git a/kernel/fiasco/src/drivers/amd64/keycodes-arch.h b/kernel/fiasco/src/drivers/amd64/keycodes-arch.h new file mode 100644 index 00000000..dc8f6158 --- /dev/null +++ b/kernel/fiasco/src/drivers/amd64/keycodes-arch.h @@ -0,0 +1,15 @@ +/* -*- c++ -*- */ + +#ifndef KEYCODES_ARCH_H__ +#define KEYCODES_ARCH_H__ + +enum +{ + KEY_BACKSPACE = 0x08, + KEY_TAB = 0x09, + KEY_ESC = 0x1b, + KEY_RETURN = 0x0d, +}; + +#endif // KEYCODES_ARCH_H__ + diff --git a/kernel/fiasco/src/drivers/amd64/mem-amd64.cpp b/kernel/fiasco/src/drivers/amd64/mem-amd64.cpp new file mode 100644 index 00000000..aace4ecf --- /dev/null +++ b/kernel/fiasco/src/drivers/amd64/mem-amd64.cpp @@ -0,0 +1,91 @@ +IMPLEMENTATION [amd64]: + +IMPLEMENT static inline +void +Mem::memset_mwords (void *dst, unsigned long value, unsigned long n) +{ + unsigned long dummy1, dummy2; + + asm volatile ("cld \n\t" + "rep stosq \n\t" + : "=c" (dummy1), "=D" (dummy2) + : "a"(value), "c" (n), "D" (dst) + : "memory"); +} + + +IMPLEMENT static inline +void +Mem::memcpy_bytes (void *dst, void const *src, unsigned long n) +{ + unsigned long dummy1, dummy2, dummy3; + + asm volatile ("cld \n\t" + "repz movsq (%%rsi), (%%rdi) \n\t" + "mov %%rdx, %%rcx \n\t" + "repz movsb (%%rsi), (%%rdi) \n\t" + : "=c" (dummy1), "=S" (dummy2), "=D" (dummy3) + : "c" (n >> 3), "d" (n & 7), "S" (src), "D" (dst) + : "memory"); +} + +IMPLEMENT static inline +void +Mem::memcpy_mwords (void *dst, void const *src, unsigned long n) +{ + unsigned long dummy1, dummy2, dummy3; + + asm volatile ("cld \n\t" + "rep movsq (%%rsi), (%%rdi) \n\t" + : "=c" (dummy1), "=S" (dummy2), "=D" (dummy3) + : "c" (n), "S" (src), "D" (dst) + : "memory"); +} + +PUBLIC static inline +void +Mem::memcpy_bytes_fs (void *dst, void const *src, unsigned long n) +{ + unsigned long dummy1, dummy2, dummy3; + + asm volatile ("cld \n\t" + "rep movsq (%%rsi), (%%rdi) \n\t" + "mov %%rdx, %%rcx \n\t" + "repz movsb (%%rsi), (%%rdi) \n\t" + : "=c" (dummy1), "=S" (dummy2), "=D" (dummy3) + : "c" (n >> 3), "d" (n & 7), "S" (src), "D" (dst) + : "memory"); +} + +PUBLIC static inline +void +Mem::memcpy_mwords_fs (void *dst, void const *src, unsigned long n) +{ + unsigned long dummy1, dummy2, dummy3; + + asm volatile ("cld \n\t" + "rep movsq (%%rsi), (%%rdi) \n\t" + : "=c" (dummy1), "=S" (dummy2), "=D" (dummy3) + : "c" (n), "S" (src), "D" (dst) + : "memory"); +} + + + +// ------------------------------------------------------------------------ +IMPLEMENTATION [amd64 && mp]: + +IMPLEMENT inline static void Mem::mb() +{ __asm__ __volatile__ ("mfence" : : : "memory"); } + +IMPLEMENT inline static void Mem::rmb() +{ __asm__ __volatile__ ("lfence" : : : "memory"); } + +IMPLEMENT inline static void Mem::wmb() +{ /* Just barrier should be enough */ + __asm__ __volatile__ ("sfence" : : : "memory"); +} + +IMPLEMENT inline static void Mem::mp_mb() { mb(); } +IMPLEMENT inline static void Mem::mp_rmb() { rmb(); } +IMPLEMENT inline static void Mem::mp_wmb() { wmb(); } diff --git a/kernel/fiasco/src/drivers/amd64/processor-amd64.cpp b/kernel/fiasco/src/drivers/amd64/processor-amd64.cpp new file mode 100644 index 00000000..07d87b4a --- /dev/null +++ b/kernel/fiasco/src/drivers/amd64/processor-amd64.cpp @@ -0,0 +1,139 @@ +INTERFACE[amd64]: + +EXTENSION class Proc +{ +public: + enum Efer_bits + { + Efer_sce_flag = 0x00000001, // Syscall Enable Flag + Efer_lme_flag = 0x00000100, // Long Mode Enable Flag + Efer_nxe_flag = 0x00000800, // Not-executable + Efer_svme_flag = 0x00001000, // Enable SVM + }; +}; + +IMPLEMENTATION[amd64]: + +#include "types.h" +#include "std_macros.h" + +IMPLEMENT static inline +Mword Proc::stack_pointer() +{ + Mword sp; + asm volatile ("mov %%rsp, %0 \n" : "=r"(sp) ); + return sp; +} + +IMPLEMENT static inline +void Proc::stack_pointer(Mword sp) +{ + asm volatile ("mov %0, %%rsp \n" : : "r"(sp) ); +} + +IMPLEMENT static inline +Mword ALWAYS_INLINE Proc::program_counter() +{ + Mword pc; + asm volatile ("call 1f ; 1: pop %0" : "=r"(pc)); + return pc; +} + +IMPLEMENT static inline +void Proc::pause() +{ + asm volatile (" .byte 0xf3, 0x90 #pause \n" ); +} + +/* + * The following simple ASM statements need the clobbering to work around + * a bug in (at least) gcc-3.2.x up to x == 1. The bug was fixed on + * Jan 9th 2003 (see gcc-bugs #9242 and #8832), so a released gcc-3.2.2 + * won't have it. It's safe to take the clobber statements out after + * some time (e.g. when gcc-3.3 is used as a standard compiler). + */ + +IMPLEMENT static inline +void Proc::halt() +{ + asm volatile ("hlt" : : : "memory"); +} + +IMPLEMENT static inline +void Proc::cli() +{ + asm volatile ("cli" : : : "memory"); +} + +IMPLEMENT static inline +void Proc::sti() +{ + asm volatile ("sti" : : : "memory"); +} + +IMPLEMENT static inline +Proc::Status Proc::cli_save() +{ + Status ret; + asm volatile ("pushfq \n\t" + "popq %0 \n\t" + "cli \n\t" + : "=g"(ret) : /* no input */ : "memory"); + return ret; +} + +IMPLEMENT static inline +void Proc::sti_restore(Status st) +{ + if (st & 0x0200) + asm volatile ("sti" : : : "memory"); +} + +IMPLEMENT static inline +Proc::Status Proc::interrupts() +{ + Status ret; + asm volatile ("pushfq \n" + "popq %0 \n" + : "=g"(ret) : /* no input */ : "memory"); + return ret & 0x0200; +} + +IMPLEMENT static inline +void Proc::irq_chance() +{ + asm volatile ("nop; nop;" : : : "memory"); +} + + +PUBLIC static inline +Unsigned64 +Proc::rdmsr(Unsigned32 msr) +{ + Unsigned32 h,l; + + asm volatile ("rdmsr" : "=a" (l), "=d" (h) : "c" (msr)); + return (((Mword)h) << 32) | l; +} + +PUBLIC static inline +void +Proc::wrmsr(Unsigned32 msr, Unsigned64 value) +{ + asm volatile ("wrmsr" : : + "a" ((Unsigned32)value), + "d" ((Unsigned32)(value >> 32)), + "c" (msr)); +} + +PUBLIC static inline +Mword +Proc::efer() +{ return rdmsr(0xc0000080); } + +PUBLIC static inline +void +Proc::efer(Mword value) +{ wrmsr(0xc0000080, value); } + + diff --git a/kernel/fiasco/src/drivers/amd64/reset-amd64.cpp b/kernel/fiasco/src/drivers/amd64/reset-amd64.cpp new file mode 100644 index 00000000..d59af2c5 --- /dev/null +++ b/kernel/fiasco/src/drivers/amd64/reset-amd64.cpp @@ -0,0 +1,41 @@ +IMPLEMENTATION[amd64]: + +#include "io.h" +#include "processor.h" + +// reset PC +void __attribute__ ((noreturn)) +platform_reset() +{ + // i8042: store the next byte at port 0x60 as command byte + while (Io::in8 (0x64) & 0x2) + ; + Io::out8_p (0x60, 0x64); + + // i8042 command byte (PS/2-compatible mode): + // b0=0 ... no IRQ 1 is generated when data available in input buffer + // b1=0 ... no IRQ 1 is generated when mouse data available in input buffer + // b2=1 ... set SYS flag in status register -- tells POST to perform + // "warm boot" tests/initiailization + // b3=0 ... reserved + // b4=0 ... keyboard interface enabled + // b5=0 ... auxillary PS/2 device (mouse) interface enabled + // b6=0 ... translation disabled -- data appears at input buffer exactly + // as read from keyboard + // b7=0 ... reserved + while (Io::in8 (0x64) & 0x2) + ; + Io::out8_p (0x4, 0x60); + + // i8042: pulse output port with 1110b + // b0=0 ... reset computer + // b1=1 ... set gate A20 + // b2=1 ... pull mouse data low + // b3=1 ... pull mouse clock low + while (Io::in8 (0x64) & 0x2) + ; + Io::out8_p (0xfe,0x64); + + for (;;) + Proc::pause(); +} diff --git a/kernel/fiasco/src/drivers/arm/cache_func_gen.cpp b/kernel/fiasco/src/drivers/arm/cache_func_gen.cpp new file mode 100644 index 00000000..81a9dd7e --- /dev/null +++ b/kernel/fiasco/src/drivers/arm/cache_func_gen.cpp @@ -0,0 +1,57 @@ +// Source for generating some asm for cut'n'paste, why program asm ourselves +// when the compiler can do it? +// arm-linux-g++ -fverbose-asm -fPIC -W -Wall -Os -S cache_func_gen.cpp + +#include + +enum { + DEBUG = 0, +}; + +void num_way_l1_cache_op() +{ + asm volatile("@ Start:"); + register unsigned long ccsidr; + asm volatile("mcr p15, 2, %0, c0, c0, 0" : : "r" (0)); // L1, data or unified + asm volatile("mrc p15, 1, %0, c0, c0, 0" : "=r" (ccsidr)); + + if (DEBUG) + printf("ccsidr = %08lx\n", ccsidr); + + // sets + register unsigned numsets = ((ccsidr >> 13) & ((1 << 15) - 1)); + // associativity - 1 + register unsigned numways = ((ccsidr >> 3) & ((1 << 10) - 1)); + // linesize + register unsigned linesizel2 = (ccsidr >> 0) & ((1 << 3) - 1); + + if (DEBUG) + printf("linesizel2: %d numways: %d numsets: %d\n", + linesizel2, numways + 1, numsets + 1); + + register int shiftways = __builtin_clz(numways); + register int shiftset = linesizel2 + 4; + + if (DEBUG) + printf("shiftways: %d shiftset: %d\n", shiftways, shiftset); + + unsigned int cnt = 0; + for (register int w = numways; w >= 0; --w) + for (register int s = numsets; s >= 0; --s) + { + register unsigned long v = (w << shiftways) | (s << shiftset); + if (!DEBUG) + // invalidate num/way + asm volatile("mcr p15, 0, %0, c7, c6, 2" : : "r" (v)); + if (DEBUG) + printf("w=%d s=%d: %08lx\n", w, s, v); + if (DEBUG) + cnt++; + } + + asm volatile("isb"); + asm volatile("dsb"); + asm volatile("@ End:"); + if (DEBUG) + printf("cnt: %d\n", cnt); +} diff --git a/kernel/fiasco/src/drivers/arm/h3xxx.cpp b/kernel/fiasco/src/drivers/arm/h3xxx.cpp new file mode 100644 index 00000000..6f70ddcc --- /dev/null +++ b/kernel/fiasco/src/drivers/arm/h3xxx.cpp @@ -0,0 +1,140 @@ +INTERFACE[ arm-{h3600,h3800} ]: + +#include + +template< unsigned long Egpio_base > +class H3xxx_generic +{ +public: + enum { + H3800_asic1_gpio_offset = 0x1e00, + + /// R/W 0:don't mask, 1:mask interrupt + H3800_asic1_gpio_mask = 0x60, + /// R/W 0:input, 1:output + H3800_asic1_gpio_direction = 0x64, + /// R/W 0:output low, 1:output high + H3800_asic1_gpio_out = 0x68, + /// R/W 0:level, 1:edge + H3800_asic1_gpio_trigger_type = 0x6c, + /// R/W 0:falling, 1:rising + H3800_asic1_gpio_edge_trigger = 0x70, + /// R/W 0:low, 1:high level detect + H3800_asic1_gpio_level_trigger = 0x74, + /// R/W 0:none, 1:detect + H3800_asic1_gpio_level_status = 0x78, + /// R/W 0:none, 1:detect + H3800_asic1_gpio_edge_status = 0x7c, + /// R See masks below (default 0) + H3800_asic1_gpio_state = 0x80, + /// R/W See masks below (default 0x04) + H3800_asic1_gpio_reset = 0x84, + /// R/W 0:don't mask, 1:mask trigger in sleep mode + H3800_asic1_gpio_sleep_mask = 0x88, + /// R/W direction 0:input, 1:ouput in sleep mode + H3800_asic1_gpio_sleep_dir = 0x8c, + /// R/W level 0:low, 1:high in sleep mode + H3800_asic1_gpio_sleep_out = 0x90, + /// R Pin status + H3800_asic1_gpio_status = 0x94, + /// R/W direction 0:input, 1:output in batt_fault + H3800_asic1_gpio_batt_fault_dir = 0x98, + /// R/W level 0:low, 1:high in batt_fault + H3800_asic1_gpio_batt_fault_out = 0x9c, + + /// Apply power to the IR Module + H3800_asic1_ir_on = 1 << 0, + /// Secure Digital power on + H3800_asic1_sd_pwr_on = 1 << 1, + /// Turn on power to the RS232 chip ? + H3800_asic1_rs232_on = 1 << 2, + /// Goes to speaker / earphone + H3800_asic1_pulse_gen = 1 << 3, + /// + H3800_asic1_ch_timer = 1 << 4, + /// Enables LCD_5V + H3800_asic1_lcd_5v_on = 1 << 5, + /// Enables LCD_3V + H3800_asic1_lcd_on = 1 << 6, + /// Connects to PDWN on LCD controller + H3800_asic1_lcd_pci = 1 << 7, + /// Drives VGH on the LCD (+9??) + H3800_asic1_vgh_on = 1 << 8, + /// Drivers VGL on the LCD (-6??) + H3800_asic1_vgl_on = 1 << 9, + /// Frontlight power on + H3800_asic1_fl_pwr_on = 1 << 10, + /// Bluetooth power on + H3800_asic1_bt_pwr_on = 1 << 11, + /// + H3800_asic1_spk_on = 1 << 12, + /// + H3800_asic1_ear_on = 1 << 13, + /// + H3800_asic1_aud_pwr_on = 1 << 14, + }; + +private: + template< typename Reg_type > + static inline void h3800_asic1_gpio( Reg_type val, unsigned long offset ) + { + *((volatile Reg_type*)(Egpio_base + H3800_asic1_gpio_offset + offset)) = + val; + } + + template< typename Reg_type > + static inline Reg_type h3800_asic1_gpio( unsigned long offset ) + { + return *((volatile Reg_type*)(Egpio_base + H3800_asic1_gpio_offset + + offset)); + } + + // define all the asic accessor functions. +# define ____H3800_asic1_ac( t, x, o ) \ + *((volatile t*)(Egpio_base + H3800_asic1_## x ##_offset + (o))) +# define ____H3800_asic1( t, x, m ) \ + static inline void h3800_asic1_## x ##_## m ( t v ) \ + { ____H3800_asic1_ac(t, x, H3800_asic1_## x ##_## m) = v; } \ + static inline t h3800_asic1_## x ##_## m () \ + { return ____H3800_asic1_ac( t, x, H3800_asic1_## x ##_## m); } + +public: + ____H3800_asic1( Unsigned16, gpio, mask ) + ____H3800_asic1( Unsigned16, gpio, direction ) + ____H3800_asic1( Unsigned16, gpio, out ) + ____H3800_asic1( Unsigned16, gpio, trigger_type ) + ____H3800_asic1( Unsigned16, gpio, edge_trigger ) + ____H3800_asic1( Unsigned16, gpio, level_trigger ) + ____H3800_asic1( Unsigned16, gpio, level_status ) + ____H3800_asic1( Unsigned16, gpio, edge_status ) + ____H3800_asic1( Unsigned8, gpio, state ) + ____H3800_asic1( Unsigned8, gpio, reset ) + ____H3800_asic1( Unsigned16, gpio, sleep_mask ) + ____H3800_asic1( Unsigned16, gpio, sleep_dir ) + ____H3800_asic1( Unsigned16, gpio, sleep_out ) + ____H3800_asic1( Unsigned16, gpio, status ) + ____H3800_asic1( Unsigned16, gpio, batt_fault_dir ) + ____H3800_asic1( Unsigned16, gpio, batt_fault_out ) + +# undef ____H3800_asic1 +# undef ____H3800_asic1_ac + +}; + +IMPLEMENTATION[ arm-{h3600,h3800} ]: + +PUBLIC static +template< unsigned long Egpio_base > +void H3xxx_generic::h3800_init() +{ + h3800_asic1_gpio_direction( 0x7fff ); // all outputs + h3800_asic1_gpio_mask( 0x7fff ); // all outputs + h3800_asic1_gpio_sleep_mask( 0x7fff ); + h3800_asic1_gpio_sleep_dir( 0x7fff ); + h3800_asic1_gpio_sleep_out( H3800_asic1_ear_on ); + h3800_asic1_gpio_batt_fault_dir( 0x7fff ); + h3800_asic1_gpio_batt_fault_out( H3800_asic1_ear_on ); + + h3800_asic1_gpio_out( H3800_asic1_ear_on | H3800_asic1_rs232_on ); +} + diff --git a/kernel/fiasco/src/drivers/arm/io-arm.cpp b/kernel/fiasco/src/drivers/arm/io-arm.cpp new file mode 100644 index 00000000..d81081bf --- /dev/null +++ b/kernel/fiasco/src/drivers/arm/io-arm.cpp @@ -0,0 +1,43 @@ +IMPLEMENTATION [arm]: + +IMPLEMENT inline +void Io::iodelay() +{} + +IMPLEMENT inline +Unsigned8 Io::in8(unsigned long port) +{ + return *(volatile Unsigned8 *)port; +} + +IMPLEMENT inline +Unsigned16 Io::in16( unsigned long port ) +{ + return *(volatile Unsigned16 *)port; +} + +IMPLEMENT inline +Unsigned32 Io::in32(unsigned long port) +{ + return *(volatile Unsigned32 *)port; +} + +IMPLEMENT inline +void Io::out8 (Unsigned8 val, unsigned long port) +{ + *(volatile Unsigned8 *)port = val; +} + +IMPLEMENT inline +void Io::out16( Unsigned16 val, unsigned long port) +{ + *(volatile Unsigned16 *)port = val; +} + +IMPLEMENT inline +void Io::out32(Unsigned32 val, unsigned long port) +{ + *(volatile Unsigned32 *)port = val; +} + + diff --git a/kernel/fiasco/src/drivers/arm/keycodes-arch.h b/kernel/fiasco/src/drivers/arm/keycodes-arch.h new file mode 100644 index 00000000..dc8f6158 --- /dev/null +++ b/kernel/fiasco/src/drivers/arm/keycodes-arch.h @@ -0,0 +1,15 @@ +/* -*- c++ -*- */ + +#ifndef KEYCODES_ARCH_H__ +#define KEYCODES_ARCH_H__ + +enum +{ + KEY_BACKSPACE = 0x08, + KEY_TAB = 0x09, + KEY_ESC = 0x1b, + KEY_RETURN = 0x0d, +}; + +#endif // KEYCODES_ARCH_H__ + diff --git a/kernel/fiasco/src/drivers/arm/mem-arm.cpp b/kernel/fiasco/src/drivers/arm/mem-arm.cpp new file mode 100644 index 00000000..7128fffe --- /dev/null +++ b/kernel/fiasco/src/drivers/arm/mem-arm.cpp @@ -0,0 +1,71 @@ +//----------------------------------------------------------------------------- +IMPLEMENTATION [arm]: + +IMPLEMENT static inline +void +Mem::memset_mwords (void *dst, const unsigned long value, unsigned long nr_of_mwords) +{ + unsigned long *d = (unsigned long *)dst; + for (; nr_of_mwords--; d++) + *d = value; +} + +IMPLEMENT static inline +void +Mem::memcpy_mwords (void *dst, void const *src, unsigned long nr_of_mwords) +{ + __builtin_memcpy(dst, src, nr_of_mwords * sizeof(unsigned long)); +} + +IMPLEMENT static inline +void +Mem::memcpy_bytes(void *dst, void const *src, unsigned long nr_of_bytes) +{ + __builtin_memcpy(dst, src, nr_of_bytes); +} + +//----------------------------------------------------------------------------- +IMPLEMENTATION [armv5]: + +PUBLIC static inline void Mem::dmb() { barrier(); } + +PUBLIC static inline void Mem::isb() { barrier(); } + +PUBLIC static inline void Mem::dsb() +{ __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 4" : : "r" (0) : "memory"); } + +//----------------------------------------------------------------------------- +IMPLEMENTATION [armv6]: + +PUBLIC static inline void Mem::dmb() +{ __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 5" : : "r" (0) : "memory"); } + +PUBLIC static inline void Mem::isb() +{ __asm__ __volatile__ ("mcr p15, 0, %0, c7, c5, 4" : : "r" (0) : "memory"); } + +PUBLIC static inline void Mem::dsb() +{ __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 4" : : "r" (0) : "memory"); } + +//----------------------------------------------------------------------------- +IMPLEMENTATION [armv7]: + +PUBLIC static inline void Mem::dmb() +{ __asm__ __volatile__ ("dmb" : : : "memory"); } + +PUBLIC static inline void Mem::isb() +{ __asm__ __volatile__ ("isb" : : : "memory"); } + +PUBLIC static inline void Mem::dsb() +{ __asm__ __volatile__ ("dsb" : : : "memory"); } + +//----------------------------------------------------------------------------- +IMPLEMENTATION [arm && mp]: + +IMPLEMENT inline static void Mem::mb() { dmb(); } +IMPLEMENT inline static void Mem::rmb() { dmb(); } +IMPLEMENT inline static void Mem::wmb() { dmb(); } + +IMPLEMENT inline static void Mem::mp_mb() { dmb(); } +IMPLEMENT inline static void Mem::mp_rmb() { dmb(); } +IMPLEMENT inline static void Mem::mp_wmb() { dmb(); } + diff --git a/kernel/fiasco/src/drivers/arm/mmu-arm.cpp b/kernel/fiasco/src/drivers/arm/mmu-arm.cpp new file mode 100644 index 00000000..cf445f3e --- /dev/null +++ b/kernel/fiasco/src/drivers/arm/mmu-arm.cpp @@ -0,0 +1,634 @@ +INTERFACE: + +#include "mem.h" +#include "std_macros.h" + +EXTENSION class Mmu +{ +public: + static void btc_flush(); + static void btc_inv(); + + enum + { + Cache_line_size = 32, + Cache_line_mask = Cache_line_size - 1, + Icache_line_size = 32, + Icache_line_mask = Icache_line_size - 1, + }; +}; + +//--------------------------------------------------------------------------- +IMPLEMENTATION [arm && armv5]: + +IMPLEMENT static inline +template < unsigned long Flush_area, bool Ram > +void Mmu::btc_flush() +{} + +IMPLEMENT static inline +template < unsigned long Flush_area, bool Ram > +void Mmu::btc_inv() +{} + +//--------------------------------------------------------------------------- +IMPLEMENTATION [arm && (armv6 || armv7)]: + +IMPLEMENT static inline +template < unsigned long Flush_area, bool Ram > +void Mmu::btc_flush() +{ asm volatile ("mcr p15, 0, %0, c7, c5, 6" : : "r" (0) : "memory"); } + +IMPLEMENT static inline +template < unsigned long Flush_area, bool Ram > +void Mmu::btc_inv() +{ asm volatile ("mcr p15, 0, %0, c7, c5, 0" : : "r" (0) : "memory"); } + +// --------------------------------------------------------------------------- +IMPLEMENTATION [arm && arm920t]: + +IMPLEMENT inline +template< unsigned long Flush_area, bool Ram > +void Mmu::flush_cache(void const * /*start*/, + void const * /*end*/) +{ + flush_cache(); +} + +IMPLEMENT +template< unsigned long Flush_area , bool Ram > +FIASCO_NOINLINE void Mmu::clean_dcache(void const *start, void const *end) +{ + (void)start; (void)end; + clean_dcache(); +} + +IMPLEMENT +template< unsigned long Flush_area , bool Ram > +void Mmu::clean_dcache(void const *va) +{ + (void)va; + clean_dcache(); +} + +IMPLEMENT +template< unsigned long Flush_area, bool Ram > +FIASCO_NOINLINE void Mmu::flush_dcache(void const *start, void const *end) +{ + (void)start; (void)end; + flush_dcache(); +} + + +IMPLEMENT +template< unsigned long Flush_area, bool Ram > +FIASCO_NOINLINE void Mmu::inv_dcache(void const *start, void const *end) +{ + // clean && invalidate dcache ||| XXX: all +#if 1 + for (unsigned long index = 0; index < (1 << (32 - 26)); ++index) + for (unsigned long seg = 0; seg < 256; seg += 32) + asm volatile("mcr p15,0,%0,c7,c14,2" : : "r" ((index << 26) | seg)); +#else + // invalidate dcache --- all + asm volatile("mcr p15,0,%0,c7,c6,0" : : "r" (0) : "memory"); +#endif +} + + +// --------------------------------------------------------------------------- +IMPLEMENTATION [arm && (pxa || sa1100 || 926)]: + +IMPLEMENT inline +template< unsigned long Flush_area, bool Ram > +void Mmu::flush_cache(void const * /*start*/, + void const * /*end*/) +{ + flush_cache(); +} + +IMPLEMENT +template< unsigned long Flush_area , bool Ram > +FIASCO_NOINLINE void Mmu::clean_dcache(void const *start, void const *end) +{ + if (((Address)end) - ((Address)start) >= 8192) + clean_dcache(); + else + { + asm volatile ( + " bic %0, %0, %2 - 1 \n" + "1: mcr p15, 0, %0, c7, c10, 1 \n" + " add %0, %0, %2 \n" + " cmp %0, %1 \n" + " blo 1b \n" + " mcr p15, 0, %0, c7, c10, 4 \n" // drain WB + : : "r" (start), "r" (end), "i" (Cache_line_size) + ); + } +} + +IMPLEMENT +template< unsigned long Flush_area , bool Ram > +void Mmu::clean_dcache(void const *va) +{ + __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 1 \n" + : : "r"(va) : "memory"); +} + +IMPLEMENT +template< unsigned long Flush_area, bool Ram > +FIASCO_NOINLINE void Mmu::flush_dcache(void const *start, void const *end) +{ + if (((Address)end) - ((Address)start) >= 8192) + flush_dcache(); + else + { + asm volatile ( + " bic %0, %0, %2 - 1 \n" + "1: mcr p15, 0, %0, c7, c14, 1 \n" + " add %0, %0, %2 \n" + " cmp %0, %1 \n" + " blo 1b \n" + " mcr p15, 0, %0, c7, c10, 4 \n" // drain WB + : : "r" (start), "r" (end), "i" (Cache_line_size) + ); + } +} + + +IMPLEMENT +template< unsigned long Flush_area, bool Ram > +FIASCO_NOINLINE void Mmu::inv_dcache(void const *start, void const *end) +{ + asm volatile ( + " bic %0, %0, %2 - 1 \n" + "1: mcr p15, 0, %0, c7, c6, 1 \n" + " add %0, %0, %2 \n" + " cmp %0, %1 \n" + " blo 1b \n" + : : "r" (start), "r" (end), "i" (Cache_line_size) + ); +} + +//----------------------------------------------------------------------------- +IMPLEMENTATION [arm && (mpcore || arm1136 || arm1176 || armca8 || armca9)]: + +IMPLEMENT inline +template< unsigned long Flush_area, bool Ram > +void Mmu::flush_cache(void const *start, + void const *end) +{ + __asm__ __volatile__ ( + "1: mcr p15, 0, %[i], c7, c14, 1 \n" + " mcr p15, 0, %[i], c7, c5, 1 \n" + " add %[i], %[i], %[clsz] \n" + " cmp %[i], %[end] \n" + " blo 1b \n" + : [i] "=&r" (start) + : "0" ((unsigned long)start & ~(Cache_line_size - 1)), + [end] "r" (end), + [clsz] "i" (Cache_line_size) + : "r0", "memory"); + btc_inv(); + Mem::dsb(); +} + +IMPLEMENT inline +template< unsigned long Flush_area , bool Ram > +void Mmu::clean_dcache(void const *va) +{ + Mem::dsb(); + __asm__ __volatile__ ( + "mcr p15, 0, %1, c7, c10, 1 \n" // Clean Data Cache Line (using MVA) Register + : + : "r" (0), + "r"((unsigned long)va & ~(Cache_line_size - 1)) + : "memory"); +} + +IMPLEMENT inline +template< unsigned long Flush_area , bool Ram > +void Mmu::clean_dcache(void const *start, void const *end) +{ + Mem::dsb(); + __asm__ __volatile__ ( + // arm1176 only: " mcrr p15, 0, %2, %1, c12 \n" + "1: mcr p15, 0, %[i], c7, c10, 1 \n" // Clean Data Cache Line (using MVA) Register + " add %[i], %[i], %[clsz] \n" + " cmp %[i], %[end] \n" + " blo 1b \n" + : [i] "=&r" (start) + : "0" ((unsigned long)start & ~(Cache_line_size - 1)), + [end] "r" (end), + [clsz] "i" (Cache_line_size) + : "memory"); + btc_inv(); + Mem::dsb(); +} + +IMPLEMENT +template< unsigned long Flush_area, bool Ram > +void Mmu::flush_dcache(void const *start, void const *end) +{ + Mem::dsb(); + __asm__ __volatile__ ( + "1: mcr p15, 0, %[i], c7, c14, 1 \n" // Clean and Invalidate Data Cache Line (using MVA) Register + " add %[i], %[i], %[clsz] \n" + " cmp %[i], %[end] \n" + " blo 1b \n" + : [i] "=&r" (start) + : "0" ((unsigned long)start & ~(Cache_line_size - 1)), + [end] "r" (end), + [clsz] "i" (Cache_line_size) + : "memory"); + btc_inv(); + Mem::dsb(); +} + +IMPLEMENT +template< unsigned long Flush_area, bool Ram > +void Mmu::inv_dcache(void const *start, void const *end) +{ + Mem::dsb(); + __asm__ __volatile__ ( + "1: mcr p15, 0, %[i], c7, c6, 1 \n" // Invalidate Data Cache Line (using MVA) Register + " add %[i], %[i], %[clsz] \n" + " cmp %[i], %[end] \n" + " blo 1b \n" + : [i] "=&r" (start) + : "0" ((unsigned long)start & ~(Cache_line_size - 1)), + [end] "r" (end), + [clsz] "i" (Cache_line_size) + : "memory"); + btc_inv(); + Mem::dsb(); +} + +//----------------------------------------------------------------------------- +IMPLEMENTATION [arm && (mpcore || arm1136 || arm1176)]: + +IMPLEMENT +template< unsigned long Flush_area, bool Ram > +void Mmu::flush_cache() +{ + Mem::dsb(); + __asm__ __volatile__ ( + " mcr p15, 0, r0, c7, c14, 0 \n" // Clean and Invalidate Entire Data Cache Register + " mcr p15, 0, r0, c7, c5, 0 \n" // Invalidate Entire Instruction Cache Register + : : : "memory"); + btc_inv(); +} + +IMPLEMENT +template< unsigned long Flush_area, bool Ram > +void Mmu::clean_dcache() +{ + Mem::dsb(); + __asm__ __volatile__ ( + " mcr p15, 0, r0, c7, c10, 0 \n" // Clean Entire Data Cache Register + : : : "memory"); + btc_inv(); +} + +IMPLEMENT +template< unsigned long Flush_area, bool Ram > +void Mmu::flush_dcache() +{ + Mem::dsb(); + __asm__ __volatile__ ( + " mcr p15, 0, r0, c7, c14, 0 \n" // Clean and Invalidate Entire Data Cache Register + : : : "memory"); + btc_inv(); +} + + +//----------------------------------------------------------------------------- +INTERFACE [arm && (armca8 || armca9)]: + +EXTENSION class Mmu +{ +private: + struct set_way_dcache_flush_op + { + void operator()(Mword v) const + { // clean+inv data cache by set/way + __asm__ __volatile__ + ( "mcr p15, 0, %0, c7, c14, 2" : : "r"(v) : "memory"); + } + }; + + struct set_way_dcache_clean_op + { + void operator()(Mword v) const + { // clean data cache by set/way + __asm__ __volatile__ + ( "mcr p15, 0, %0, c7, c10, 2" : : "r"(v) : "memory"); + } + }; +}; + +//----------------------------------------------------------------------------- +INTERFACE [arm && armca8]: + +EXTENSION class Mmu +{ + enum + { + SET_SIZE_16KB = 1 << 12, + SET_SIZE_32KB = 1 << 13, + SET_SIZE = SET_SIZE_32KB, + SET_INCR = 1 << 6, + WAY_INCR = 1 << 30, + WAY_SIZE = 4, + }; +}; + +//----------------------------------------------------------------------------- +INTERFACE [arm && armca9]: + +EXTENSION class Mmu +{ + enum + { + SET_SIZE_16KB = 1 << 12, + SET_SIZE_32KB = 1 << 13, + SET_SIZE_64KB = 1 << 14, + SET_SIZE = SET_SIZE_32KB, + SET_INCR = 1 << 5, + WAY_INCR = 1 << 30, + WAY_SIZE = 4, + }; + +}; + +//----------------------------------------- +IMPLEMENTATION [arm && (armca8 || armca9)]: + +PRIVATE +template< unsigned long Flush_area, bool Ram > +template< typename T > +static inline +void Mmu::set_way_full_op(T const &f) +{ + unsigned wv, w; + for (w = 0, wv = 0; w < WAY_SIZE; ++w, wv += WAY_INCR) + for (unsigned s = 0; s < SET_SIZE; s += SET_INCR) + f(wv | s); + btc_inv(); + __asm__ __volatile__ ("dsb; isb"); +} + +IMPLEMENT +template< unsigned long Flush_area, bool Ram > +void Mmu::flush_dcache() +{ + __asm__ __volatile__("dsb"); + set_way_full_op(set_way_dcache_flush_op()); +} + + +IMPLEMENT +template< unsigned long Flush_area, bool Ram > +void Mmu::flush_cache() +{ + __asm__ __volatile__ ( + " dsb \n" + // Invalidate Entire Instruction Cache Register + BTC + " mcr p15, 0, r0, c7, c5, 0 \n" + : : : "memory"); + + set_way_full_op(set_way_dcache_flush_op()); +} + +IMPLEMENT +template< unsigned long Flush_area, bool Ram > +void Mmu::clean_dcache() +{ + __asm__ __volatile__ ( + " dsb \n" // Drain Synchronization Barrier Register + : : : "memory"); + + set_way_full_op(set_way_dcache_clean_op()); +} + +//----------------------------------------------------------------------------- +IMPLEMENTATION [arm && sa1100]: + +IMPLEMENT +template< unsigned long Flush_area, bool Ram > +FIASCO_NOINLINE void Mmu::flush_cache() +{ + register Mword dummy; + asm volatile ( + " add %0, %1, #8192 \n" // 8k flush area + " 1: ldr r0, [%1], %2 \n" // 32 bytes cache line size + " teq %1, %0 \n" + " bne 1b \n" + " mov r0, #0 \n" + " mcr p15, 0, r0, c7, c7, 0 \n" + " mcr p15, 0, r0, c7, c10, 4 \n" // drain WB + : "=r" (dummy) + : "r" (Flush_area), "i" (Cache_line_size) + : "r0" + ); +} + +IMPLEMENT +template< unsigned long Flush_area, bool Ram > +FIASCO_NOINLINE void Mmu::clean_dcache() +{ + register Mword dummy; + asm volatile ( + " add %0, %1, #8192 \n" // 8k flush area + " 1: ldr r0, [%1], %2 \n" // 32 bytes cache line size + " teq %1, %0 \n" + " bne 1b \n" + " mcr p15, 0, r0, c7, c10, 4 \n" // drain WB + : "=r" (dummy) + : "r" (Flush_area), "i" (Cache_line_size) + : "r0" + ); +} + +IMPLEMENT +template< unsigned long Flush_area, bool Ram > +FIASCO_NOINLINE void Mmu::flush_dcache() +{ + register Mword dummy; + asm volatile ( + " add %0, %1, #8192 \n" // 8k flush area + " 1: ldr r0, [%1], %2 \n" // 32 bytes cache line size + " teq %1, %0 \n" + " bne 1b \n" + " mov r0, #0 \n" + " mcr p15, 0, r0, c7, c6, 0 \n" // inv D cache + " mcr p15, 0, r0, c7, c10, 4 \n" // drain WB + : "=r" (dummy) + : "r" (Flush_area), "i" (Cache_line_size) + : "r0" + ); + +} + + +//----------------------------------------------------------------------------- +IMPLEMENTATION [arm && pxa]: + +IMPLEMENT +template< unsigned long Flush_area, bool Ram > +FIASCO_NOINLINE void Mmu::flush_cache() +{ + register Mword dummy1, dummy2; + asm volatile + ( + // write back data cache + " 1: mcr p15,0,%0,c7,c2,5 \n\t" + " add %0, %0, #32 \n\t" + " subs %1, %1, #1 \n\t" + " bne 1b \n\t" + // drain write buffer + " mcr p15, 0, %0, c7, c7, 0 \n" + " mcr p15, 0, r0, c7, c10, 4 \n\t" + : + "=r" (dummy1), + "=r" (dummy2) + : + "0" (Flush_area), + "1" (Ram?2048:1024) + ); +} + +IMPLEMENT +template< unsigned long Flush_area, bool Ram > +FIASCO_NOINLINE void Mmu::clean_dcache() +{ + register Mword dummy1, dummy2; + asm volatile + ( + // write back data cache + " 1: mcr p15,0,%0,c7,c2,5 \n\t" + " add %0, %0, #32 \n\t" + " subs %1, %1, #1 \n\t" + " bne 1b \n\t" + // drain write buffer + " mcr p15, 0, r0, c7, c10, 4 \n\t" + : + "=r" (dummy1), + "=r" (dummy2) + : + "0" (Flush_area), + "1" (Ram?2048:1024) + ); +} + +IMPLEMENT +template< unsigned long Flush_area, bool Ram > +FIASCO_NOINLINE void Mmu::flush_dcache() +{ + register Mword dummy1, dummy2; + asm volatile + ( + // write back data cache + " 1: mcr p15,0,%0,c7,c2,5 \n\t" + " add %0, %0, #32 \n\t" + " subs %1, %1, #1 \n\t" + " bne 1b \n\t" + " mcr p15, 0, %0, c7, c6, 0 \n" // inv D cache + // drain write buffer + " mcr p15, 0, r0, c7, c10, 4 \n\t" + : + "=r" (dummy1), + "=r" (dummy2) + : + "0" (Flush_area), + "1" (Ram?2048:1024) + ); +} + +//----------------------------------------------------------------------------- +IMPLEMENTATION [arm && arm920t]: + +IMPLEMENT +template< unsigned long Flush_area, bool Ram > +FIASCO_NOINLINE void Mmu::flush_cache() +{ + Mem::dsb(); + + // clean and invalidate dcache + for (unsigned long index = 0; index < (1 << (32 - 26)); ++index) + for (unsigned long seg = 0; seg < 256; seg += 32) + asm volatile("mcr p15,0,%0,c7,c14,2" : : "r" ((index << 26) | seg)); + + // invalidate icache + asm volatile("mcr p15,0,%0,c7,c5,0" : : "r" (0) : "memory"); +} + + +IMPLEMENT +template< unsigned long Flush_area, bool Ram > +FIASCO_NOINLINE void Mmu::clean_dcache() +{ + flush_cache(); +} + +IMPLEMENT +template< unsigned long Flush_area, bool Ram > +FIASCO_NOINLINE void Mmu::flush_dcache() +{ + flush_cache(); +} + +//----------------------------------------------------------------------------- +IMPLEMENTATION [arm && 926]: + +IMPLEMENT +template< unsigned long Flush_area, bool Ram > +FIASCO_NOINLINE void Mmu::flush_cache() +{ + asm volatile + ( + // write back data cache + "1: mrc p15, 0, r15, c7, c14, 3 \n\t" + " bne 1b \n\t" + // drain write buffer + " mcr p15, 0, %0, c7, c7, 0 \n\t" + " mcr p15, 0, %0, c7, c10, 4 \n\t" + : : + "r" (0) + ); +} + +IMPLEMENT +template< unsigned long Flush_area, bool Ram > +FIASCO_NOINLINE void Mmu::clean_dcache() +{ + asm volatile + ( + // write back data cache + "1: mrc p15, 0, r15, c7, c14, 3 \n\t" + " bne 1b \n\t" + // drain write buffer + " mcr p15, 0, %0, c7, c10, 4 \n\t" + : : + "r" (0) + ); +} + +IMPLEMENT +template< unsigned long Flush_area, bool Ram > +FIASCO_NOINLINE void Mmu::flush_dcache() +{ + asm volatile + ( + // write back data cache + "1: mrc p15, 0, r15, c7, c14, 3 \n\t" + " bne 1b \n\t" + " mcr p15, 0, %0, c7, c6, 0 \n" // inv D cache + // drain write buffer + " mcr p15, 0, %0, c7, c10, 4 \n\t" + : : + "r" (0) + ); +} + + diff --git a/kernel/fiasco/src/drivers/arm/processor-arm.cpp b/kernel/fiasco/src/drivers/arm/processor-arm.cpp new file mode 100644 index 00000000..e315ce8e --- /dev/null +++ b/kernel/fiasco/src/drivers/arm/processor-arm.cpp @@ -0,0 +1,238 @@ +INTERFACE[arm]: + +EXTENSION class Proc +{ +public: + enum + { + Status_mode_user = 0x10, + Status_mode_supervisor = 0x13, + Status_mode_mask = 0x1f, + + Status_FIQ_disabled = 0x40, + Status_IRQ_disabled = 0x80, + Status_interrupts_disabled = Status_FIQ_disabled | Status_IRQ_disabled, + Status_interrupts_mask = 0xc0, + Status_thumb = 0x20, + }; + + static unsigned cpu_id(); +}; + +INTERFACE[arm && !tz]: + +EXTENSION class Proc +{ +public: + enum + { + Cli_mask = Status_IRQ_disabled, + Sti_mask = Status_IRQ_disabled, + }; +}; + +INTERFACE[arm && tz]: + +EXTENSION class Proc +{ +public: + enum + { + Cli_mask = Status_IRQ_disabled | Status_FIQ_disabled, + Sti_mask = Status_IRQ_disabled | Status_FIQ_disabled, + }; +}; + +IMPLEMENTATION[arm]: + +#include "types.h" +#include "std_macros.h" + +IMPLEMENT static inline +Mword Proc::stack_pointer() +{ + Mword sp; + asm volatile ( "mov %0, sp \n" : "=r"(sp) ); + return sp; +} + +IMPLEMENT static inline +void Proc::stack_pointer(Mword sp) +{ + asm volatile ( "mov sp, %0 \n" : : "r"(sp) ); +} + +IMPLEMENT static inline +Mword Proc::program_counter() +{ + register Mword pc asm ("pc"); + return pc; +} + +IMPLEMENT static inline +void Proc::cli() +{ + asm volatile ( " mrs r6, cpsr \n" + " orr r6,r6,%0 \n" + " msr cpsr_c, r6 \n" + : : "i" (Cli_mask) : "r6", "memory" + ); +} + +IMPLEMENT static inline +void Proc::sti() +{ + asm volatile ( " mrs r6, cpsr \n" + " bic r6,r6,%0 \n" + " msr cpsr_c, r6 \n" + : : "i" (Sti_mask) : "r6", "memory" + ); +} + +IMPLEMENT static inline +Proc::Status Proc::cli_save() +{ + Status ret; + asm volatile ( " mrs r6, cpsr \n" + " mov %0, r6 \n" + " orr r6,r6,%1 \n" + " msr cpsr_c, r6 \n" + : "=r"(ret) : "i" (Cli_mask) : "r6" + ); + return ret; +} + +IMPLEMENT static inline +Proc::Status Proc::interrupts() +{ + Status ret; + asm volatile (" mrs %0, cpsr \n" + : "=r"(ret) + ); + return !(ret & Sti_mask); +} + +IMPLEMENT static inline +void Proc::sti_restore(Status st) +{ + asm volatile ( " tst %0, %1 \n" + " bne 1f \n" + " mrs r6, cpsr \n" + " bic r6,r6,%1 \n" + " msr cpsr_c, r6 \n" + "1: \n" + : : "r"(st), "i" (Sti_mask) : "r6" + ); +} + +IMPLEMENT static inline +void Proc::irq_chance() +{ + asm volatile ("nop; nop;" : : : "memory"); +} + + +//---------------------------------------------------------------- +IMPLEMENTATION[arm && !mp]: + +IMPLEMENT static inline +unsigned Proc::cpu_id() +{ return 0; } + +//---------------------------------------------------------------- +IMPLEMENTATION[arm && mp]: + +IMPLEMENT static inline +unsigned Proc::cpu_id() +{ + unsigned int cpunum; + __asm__("mrc p15, 0, %0, c0, c0, 5": "=r" (cpunum)); + return cpunum & 0xf; +} + +//---------------------------------------------------------------- +IMPLEMENTATION[arm && (pxa || sa1100 || s3c2410)]: + +IMPLEMENT static inline +void Proc::halt() +{} + +IMPLEMENT static inline +void Proc::pause() +{} + +//---------------------------------------------------------------- +IMPLEMENTATION[arm && 926]: + +IMPLEMENT static inline +void Proc::pause() +{ +} + +IMPLEMENT static inline +void Proc::halt() +{ + Status f = cli_save(); + asm volatile("mov r0, #0 \n\t" + "mrc p15, 0, r1, c1, c0, 0 @ Read control register \n\t" + "mcr p15, 0, r0, c7, c10, 4 @ Drain write buffer \n\t" + "bic r2, r1, #1 << 12 \n\t" + "mcr p15, 0, r2, c1, c0, 0 @ Disable I cache \n\t" + "mcr p15, 0, r0, c7, c0, 4 @ Wait for interrupt \n\t" + "mcr 15, 0, r1, c1, c0, 0 @ Restore ICache enable \n\t" + :::"memory", + "r0", "r1", "r2", "r3", "r4", "r5", + "r6", "r7", "r8", "r9", "r10", "r11", + "r12", "r13", "r14", "r15" + ); + sti_restore(f); +} + +//---------------------------------------------------------------- +IMPLEMENTATION[arm && arm1136]: + +IMPLEMENT static inline +void Proc::pause() +{} + +IMPLEMENT static inline +void Proc::halt() +{ + Status f = cli_save(); + asm volatile("mcr p15, 0, r0, c7, c10, 4 @ DWB/DSB \n\t" + "mcr p15, 0, r0, c7, c0, 4 @ WFI \n\t"); + sti_restore(f); +} + + +//---------------------------------------------------------------- +IMPLEMENTATION[arm && (arm1176 || mpcore)]: + +IMPLEMENT static inline +void Proc::pause() +{} + +IMPLEMENT static inline +void Proc::halt() +{ + Status f = cli_save(); + asm volatile("mcr p15, 0, r0, c7, c10, 4 @ DWB/DSB \n\t" + "wfi \n\t"); + sti_restore(f); +} + +//---------------------------------------------------------------- +IMPLEMENTATION[arm && (armca8 || armca9)]: + +IMPLEMENT static inline +void Proc::pause() +{} + +IMPLEMENT static inline +void Proc::halt() +{ + Status f = cli_save(); + asm volatile("dsb \n\t" + "wfi \n\t"); + sti_restore(f); +} diff --git a/kernel/fiasco/src/drivers/arm/sa1100.cpp b/kernel/fiasco/src/drivers/arm/sa1100.cpp new file mode 100644 index 00000000..da67fd75 --- /dev/null +++ b/kernel/fiasco/src/drivers/arm/sa1100.cpp @@ -0,0 +1,53 @@ +INTERFACE [sa1100]: + +#include "types.h" + +template< unsigned long Hw_regs_base > +class Sa1100_generic +{ +public: + enum { + RSRR = Hw_regs_base + 0x030000, + + /* interrupt controller */ + ICIP = Hw_regs_base + 0x050000, + ICMR = Hw_regs_base + 0x050004, + ICLR = Hw_regs_base + 0x050008, + ICCR = Hw_regs_base + 0x05000c, + ICFP = Hw_regs_base + 0x050010, + ICPR = Hw_regs_base + 0x050020, + + /* OS Timer */ + OSMR0 = Hw_regs_base + 0x000000, + OSMR1 = Hw_regs_base + 0x000004, + OSMR2 = Hw_regs_base + 0x000008, + OSMR3 = Hw_regs_base + 0x00000c, + OSCR = Hw_regs_base + 0x000010, + OSSR = Hw_regs_base + 0x000014, + OWER = Hw_regs_base + 0x000018, + OIER = Hw_regs_base + 0x00001c, + + RSRR_SWR = 1, + }; + + static inline void hw_reg( Mword value, Mword reg ); + static inline Mword hw_reg( Mword reg ); +}; + +//--------------------------------------------------------------------------- +IMPLEMENTATION [sa1100]: + +IMPLEMENT inline +template< unsigned long Hw_regs_base > +void Sa1100_generic::hw_reg( Mword value, Mword reg ) +{ + *(Mword volatile*)reg = value; +} + +IMPLEMENT inline +template< unsigned long Hw_regs_base > +Mword Sa1100_generic::hw_reg( Mword reg ) +{ + return *(Mword volatile*)reg; +} + diff --git a/kernel/fiasco/src/drivers/arm/uart-sa1100.cpp b/kernel/fiasco/src/drivers/arm/uart-sa1100.cpp new file mode 100644 index 00000000..47572d63 --- /dev/null +++ b/kernel/fiasco/src/drivers/arm/uart-sa1100.cpp @@ -0,0 +1,316 @@ +INTERFACE [sa1100]: + +#include "types.h" + +EXTENSION class Uart +{ +public: + + bool startup(Address address, unsigned irq); + + enum { + PAR_NONE = 0x00, + PAR_EVEN = 0x03, + PAR_ODD = 0x01, + DAT_5 = (unsigned)-1, + DAT_6 = (unsigned)-1, + DAT_7 = 0x00, + DAT_8 = 0x08, + STOP_1 = 0x00, + STOP_2 = 0x04, + + MODE_8N1 = PAR_NONE | DAT_8 | STOP_1, + MODE_7E1 = PAR_EVEN | DAT_7 | STOP_1, + + // these two values are to leave either mode + // or baud rate unchanged on a call to change_mode + MODE_NC = 0x1000000, + BAUD_NC = 0x1000000, + + }; + +private: + Address address; + unsigned _irq; + enum { + UTCR0_PE = 0x01, + UTCR0_OES = 0x02, + UTCR0_SBS = 0x04, + UTCR0_DSS = 0x08, + UTCR0_SCE = 0x10, + UTCR0_RCE = 0x20, + UTCR0_TCE = 0x40, + + UTCR3_RXE = 0x01, + UTCR3_TXE = 0x02, + UTCR3_BRK = 0x04, + UTCR3_RIE = 0x08, + UTCR3_TIE = 0x10, + UTCR3_LBM = 0x20, + + + UTSR0_TFS = 0x01, + UTSR0_RFS = 0x02, + UTSR0_RID = 0x04, + UTSR0_RBB = 0x08, + UTSR0_REB = 0x10, + UTSR0_EIF = 0x20, + + UTSR1_TBY = 0x01, + UTSR1_RNE = 0x02, + UTSR1_TNF = 0x04, + UTSR1_PRE = 0x08, + UTSR1_FRE = 0x10, + UTSR1_ROR = 0x20, + + UARTCLK = 3686400, + }; + +}; + +//--------------------------------------------------------------------------- +IMPLEMENTATION [sa1100]: + +#include +#include "processor.h" + +PRIVATE INLINE static Address Uart::_utcr0( Address a ) +{ return a; } + +PRIVATE INLINE static Address Uart::_utcr1( Address a ) +{ return (a+0x04); } + +PRIVATE INLINE static Address Uart::_utcr2( Address a ) +{ return (a+0x08); } + +PRIVATE INLINE static Address Uart::_utcr3( Address a ) +{ return (a+0x0c); } + +PRIVATE INLINE static Address Uart::_utcr4( Address a ) +{ return (a+0x10); } + +PRIVATE INLINE static Address Uart::_utdr( Address a ) +{ return (a+0x14); } + +PRIVATE INLINE static Address Uart::_utsr0( Address a ) +{ return (a+0x1c); } + +PRIVATE INLINE static Address Uart::_utsr1( Address a ) +{ return (a+0x20); } + + +PRIVATE INLINE NEEDS[Uart::_utcr0] +unsigned Uart::utcr0() const +{ return *((volatile unsigned*)(_utcr0(address))); } + +PRIVATE INLINE NEEDS[Uart::_utcr1] +unsigned Uart::utcr1() const +{ return *((volatile unsigned*)(_utcr1(address))); } + +PRIVATE INLINE NEEDS[Uart::_utcr2] +unsigned Uart::utcr2() const +{ return *((volatile unsigned*)(_utcr2(address))); } + +PRIVATE INLINE NEEDS[Uart::_utcr3] +unsigned Uart::utcr3() const +{ return *((volatile unsigned*)(_utcr3(address))); } + +PRIVATE INLINE NEEDS[Uart::_utcr4] +unsigned Uart::utcr4() const +{ return *((volatile unsigned*)(_utcr4(address))); } + +PRIVATE INLINE NEEDS[Uart::_utdr] +unsigned Uart::utdr() const +{ return *((volatile unsigned*)(_utdr(address))); } + +PRIVATE INLINE NEEDS[Uart::_utsr0] +unsigned Uart::utsr0() const +{ return *((volatile unsigned*)(_utsr0(address))); } + +PRIVATE INLINE NEEDS[Uart::_utsr1] +unsigned Uart::utsr1() const +{ return *((volatile unsigned*)(_utsr1(address))); } + + +PRIVATE INLINE NEEDS[Uart::_utcr0] +void Uart::utcr0(unsigned v) +{ *((volatile unsigned*)(_utcr0(address)))= v; } + +PRIVATE INLINE NEEDS[Uart::_utcr1] +void Uart::utcr1(unsigned v) +{ *((volatile unsigned*)(_utcr1(address)))= v; } + +PRIVATE INLINE NEEDS[Uart::_utcr2] +void Uart::utcr2(unsigned v) +{ *((volatile unsigned*)(_utcr2(address)))= v; } + +PRIVATE INLINE NEEDS[Uart::_utcr3] +void Uart::utcr3(unsigned v) +{ *((volatile unsigned*)(_utcr3(address)))= v; } + +PRIVATE INLINE NEEDS[Uart::_utcr4] +void Uart::utcr4(unsigned v) +{ *((volatile unsigned*)(_utcr4(address)))= v; } + +PRIVATE INLINE NEEDS[Uart::_utdr] +void Uart::utdr(unsigned v) +{ *((volatile unsigned*)(_utdr(address)))= v; } + +PRIVATE INLINE NEEDS[Uart::_utsr0] +void Uart::utsr0(unsigned v) +{ *((volatile unsigned*)(_utsr0(address)))= v; } + +PRIVATE INLINE NEEDS[Uart::_utsr1] +void Uart::utsr1(unsigned v) +{ *((volatile unsigned*)(_utsr1(address)))= v; } + + +IMPLEMENT Uart::Uart() +{ + address = (unsigned)-1; + _irq = (unsigned)-1; +} + +IMPLEMENT Uart::~Uart() +{ + utcr3(0); +} + + +IMPLEMENT bool Uart::startup( Address _address, unsigned irq ) +{ + address =_address; + _irq = irq; + utsr0((unsigned)-1); //clear pending status bits + utcr3(UTCR3_RXE | UTCR3_TXE); //enable transmitter and receiver + return true; +} + +IMPLEMENT void Uart::shutdown() +{ + utcr3(0); +} + + +IMPLEMENT bool Uart::change_mode(TransferMode m, BaudRate baud) +{ + unsigned old_utcr3, quot; + Proc::Status st; + if(baud == (BaudRate)-1) + return false; + if(baud != BAUD_NC && (baud>115200 || baud<96)) + return false; + if(m == (TransferMode)-1) + return false; + + st = Proc::cli_save(); + old_utcr3 = utcr3(); + utcr3(old_utcr3 & ~(UTCR3_RIE|UTCR3_TIE)); + Proc::sti_restore(st); + + while(utsr1() & UTSR1_TBY); + + /* disable all */ + utcr3(0); + + /* set parity, data size, and stop bits */ + if(m!=MODE_NC) + utcr0(m & 0x0ff); + + /* set baud rate */ + if(baud!=BAUD_NC) + { + quot = (UARTCLK / (16*baud)) -1; + utcr1((quot & 0xf00) >> 8); + utcr2(quot & 0x0ff); + } + + utsr0((unsigned)-1); + + utcr3(old_utcr3); + return true; +} + +PUBLIC bool Uart::tx_empty() +{ + return !(utsr1() & UTSR1_TBY); +} + + +IMPLEMENT +int Uart::write( const char *s, size_t count ) +{ + unsigned old_utcr3; + Proc::Status st; + st = Proc::cli_save(); + old_utcr3 = utcr3(); + utcr3( (old_utcr3 & ~(UTCR3_RIE|UTCR3_TIE)) | UTCR3_TXE ); + + /* transmission */ + for(unsigned i =0; i +#include "l4_types.h" + +/** + * The abstract interface for a text I/O console. + * + * This abstract interface can be implemented for virtually every + * text input or output device. + */ +class Console +{ +public: + enum Console_state + { + DISABLED = 0, + INENABLED = 1, ///< output channel of console enabled + OUTENABLED = 2, ///< input channel of console enabled + DISABLED_INIT = 4, ///< the console remains disabled during boot + }; + + enum Console_attr + { + // universal attributes + INVALID = 0, + OUT = 0x1, ///< output to console is possible + IN = 0x2, ///< input from console is possible + // attributes to identify a specific console + DIRECT = 0x4, ///< output to screen or input from keyboard + UART = 0x8, ///< output to/input from serial serial line + UX = 0x10, ///< filtered input console for UX + PUSH = 0x20, ///< input console + GZIP = 0x40, ///< gzip+uuencode output and sent to uart console + BUFFER = 0x80, ///< ring buffer + DEBUG = 0x100, ///< kdb interface + FAILED = 0x200, ///< initialization failed + }; + + /** + * modify console state + */ + virtual void state(Mword new_state); + + /** + * Write a string of len chacters to the output. + * @param str the string to write (no zero termination is needed) + * @param len the number of chacters to write. + * + * This method must be implemented in every implementation, but + * can simply do nothing for input only consoles. + */ + virtual int write(char const *str, size_t len); + + /** + * read a charcater from the input. + * @param blocking if true getchar blocks til a charcater is available. + * + * This method must be implemented in every implementation, but + * can simply return -1 for output only consoles. + */ + virtual int getchar(bool blocking = true); + + /** + * Is input available? + * + * This method can be implemented. + * It must return -1 if no information is available, + * 1 if at least one character is avialable, and 0 if + * no charachter is available. + */ + virtual int char_avail() const; + + /** + * Console attributes. + */ + virtual Mword get_attributes() const; + + virtual ~Console(); + +public: + /** + * Disables the stdout, stdin, and stderr console. + */ + static void disable_all(); + + /// stdout for libc glue. + static Console *stdout; + /// stderr for libc glue. + static Console *stderr; + /// stdin for libc glue. + static Console *stdin; + +protected: + Mword _state; +}; + + + +IMPLEMENTATION: + +#include +#include + +Console *Console::stdout; +Console *Console::stderr; +Console *Console::stdin; + +IMPLEMENT Console::~Console() +{} + +/** + * get current console state + */ +PUBLIC inline +Mword +Console::state() const +{ + return _state; +} + +IMPLEMENT +void Console::state(Mword new_state) +{ + _state = new_state; +} + +PUBLIC inline +bool +Console::failed() const +{ + return _state & FAILED; +} + +PUBLIC inline +void +Console::fail() +{ + _state |= FAILED; +} + +IMPLEMENT +void Console::disable_all() +{ + stdout = 0; + stderr = 0; + stdin = 0; +} + +IMPLEMENT +int Console::write(char const *, size_t len) +{ + return len; +} + +IMPLEMENT +int Console::getchar(bool /* blocking */) +{ + return -1; /* no input */ +} + +IMPLEMENT +int Console::char_avail() const +{ + return -1; /* unknown */ +} + +IMPLEMENT +Mword Console::get_attributes() const +{ + return 0; +} + +IMPLEMENTATION[debug]: + +PUBLIC +const char* +Console::str_mode() const +{ + static char const * const mode_str[] = + { " ", "Output", "Input ", "InOut " }; + return mode_str[get_attributes() & (OUT|IN)]; +} + +PUBLIC +const char* +Console::str_state() const +{ + static char const * const state_str[] = + { "Disabled ", "Output disabled", + "Input disabled ", "Enabled " }; + return state_str[state() & (INENABLED|OUTENABLED)]; +} + +PUBLIC +const char* +Console::str_attr(Mword bit) const +{ + static char const * const attr_str[] = + { "Direct", "Uart", "UX", "Push", "Gzip", "Buffer", "Kdb", "FAILED!" }; + + return (bit < 2 || bit >= (sizeof(attr_str)/sizeof(attr_str[0]))+2) + ? "???" + : attr_str[bit-2]; +} + diff --git a/kernel/fiasco/src/drivers/delayloop.cpp b/kernel/fiasco/src/drivers/delayloop.cpp new file mode 100644 index 00000000..8a801e22 --- /dev/null +++ b/kernel/fiasco/src/drivers/delayloop.cpp @@ -0,0 +1,59 @@ +INTERFACE: + +#include "std_macros.h" +#include "initcalls.h" + +class Delay +{ +private: + static unsigned count; + +public: + static void init() FIASCO_INIT; +}; + +IMPLEMENTATION: + +#include "kip.h" +#include "processor.h" +#include "timer.h" + +unsigned Delay::count; + +IMPLEMENT void +Delay::init() +{ + Cpu_time t1; + count = 0; + + Kip *k = Kip::k(); + Cpu_time t = Kip::k()->clock; + Timer::update_timer(t + 1000); // 1ms + while (t == (t1 = k->clock)) + Proc::pause(); + Timer::update_timer(k->clock + 1000); // 1ms + while (t1 == k->clock) + { + ++count; + Proc::pause(); + } +} + +/** + * Hint: ms is actually the timer granularity, which + * currently happens to be milliseconds + */ +PUBLIC static void +Delay::delay(unsigned ms) +{ + Kip *k = Kip::k(); + while (ms--) + { + unsigned c = count; + while (c--) + { + (void)k->clock; + Proc::pause(); + } + } +} diff --git a/kernel/fiasco/src/drivers/filter_console.cpp b/kernel/fiasco/src/drivers/filter_console.cpp new file mode 100644 index 00000000..fede1832 --- /dev/null +++ b/kernel/fiasco/src/drivers/filter_console.cpp @@ -0,0 +1,269 @@ +INTERFACE: + +#include "console.h" +#include "types.h" + +class Filter_console : public Console +{ +public: + ~Filter_console() {} + +private: + Console *const _o; + int csi_timeout; + enum State + { + NORMAL, + UNKNOWN_ESC, + GOT_CSI, ///< control sequence introducer + }; + + State state; + unsigned pos; + char ibuf[32]; + unsigned arg; + int args[4]; +}; + + +IMPLEMENTATION: + +#include +#include +#include +#include "keycodes.h" +#include "delayloop.h" + + +PUBLIC +int Filter_console::char_avail() const +{ + switch (state) + { + case NORMAL: + case UNKNOWN_ESC: + if (pos) + return 1; + else + return _o->char_avail(); + + default: + return -1; + } +} + +PUBLIC inline explicit +Filter_console::Filter_console(Console *o, int to = 10) + : _o(o), csi_timeout(to), state(NORMAL), pos(0), arg(0) +{ + if (o->failed()) + fail(); +} + + +PUBLIC +int +Filter_console::write(char const *str, size_t len) +{ + char const *start = str; + char const *stop = str; + + static char seq[18]; + char const *const home = "\033[H"; + char const *const cel = "\033[K"; + + for (;stop < str + len; ++stop) + { + switch (*stop) + { + case 1: + if (stop-start) + _o->write(start, stop-start); + start = stop + 1; + _o->write(home,3); + break; + case 5: + if (stop-start) + _o->write(start, stop-start); + start = stop + 1; + _o->write(cel,3); + break; + case 6: + if (stop-start) + _o->write(start, stop-start); + if (stop + 2 < str+len) + { + snprintf(seq, sizeof(seq), "\033[%d;%dH", stop[1]+1,stop[2]+1); + _o->write(seq,strlen(seq)); + } + stop += 2; + start = stop + 1; + break; + } + } + + if (stop-start) + _o->write(start, stop-start); + + return len; +} + +PRIVATE inline +int +Filter_console::getchar_timeout(unsigned timeout) +{ + int c; + while ((c= _o->getchar(false)) == -1 && timeout--) + Delay::delay(1); + return c; +} + + +PUBLIC +int +Filter_console::getchar(bool b = true) +{ + unsigned loop_count = 100; + int ch; + + get_char: + if (state == UNKNOWN_ESC && pos) + { + ch = ibuf[0]; + memmove(ibuf, ibuf + 1, --pos); + } + else + ch = _o->getchar(b); + + if (!pos) + state = NORMAL; + + if (ch==-1) + { + if (state == NORMAL) + return -1; + else if (!b && loop_count--) + goto get_char; + else + return -1; + } + + switch (state) + { + case UNKNOWN_ESC: + return ch; + + case NORMAL: + if (ch==27) + { + ibuf[pos++] = 27; + int nc = getchar_timeout(csi_timeout); + if (nc == -1) + { + pos = 0; + return 27; + } + else + { + if (pos < sizeof(ibuf)) + ibuf[pos++] = nc; + if (nc=='[' || nc == 'O') + { + arg = 0; + memset(args, 0, sizeof(args)); + state = GOT_CSI; + break; + } + else + { + state = UNKNOWN_ESC; + goto get_char; + } + } + } + return ch; + + case GOT_CSI: + if (isdigit(ch)) + { + if (pos < sizeof(ibuf)) + ibuf[pos++] = ch; + + if (arg < (sizeof(args)/sizeof(int))) + args[arg] = args[arg]*10 + (ch-'0'); + } + else if (ch==';') + { + if (pos < sizeof(ibuf)) + ibuf[pos++] = ch; + + arg++; + } + else + { + state = NORMAL; + if (pos < sizeof(ibuf)) + ibuf[pos++] = ch; + + switch(ch) + { + case 'A': pos = 0; return KEY_CURSOR_UP; + case 'B': pos = 0; return KEY_CURSOR_DOWN; + case 'C': pos = 0; return KEY_CURSOR_RIGHT; + case 'D': pos = 0; return KEY_CURSOR_LEFT; + case 'H': pos = 0; return KEY_CURSOR_HOME; + case 'F': pos = 0; return KEY_CURSOR_END; + case '~': + pos = 0; + switch (args[0]) + { + case 7: + case 1: return KEY_CURSOR_HOME; + case 2: return KEY_INSERT; + case 3: return KEY_DELETE; + case 8: + case 4: return KEY_CURSOR_END; + case 5: return KEY_PAGE_UP; + case 6: return KEY_PAGE_DOWN; + case 11: return KEY_F1; + + default: + arg = 0; + if (b) + goto get_char; + else if (loop_count) + { + --loop_count; + goto get_char; + } + else + return -1; + } + case 'P': return KEY_F1; + default: + state = UNKNOWN_ESC; + break; + } + } + break; + } + + if (b) + goto get_char; + else if (loop_count) + { + loop_count --; + goto get_char; + } + + return -1; +} + + +PUBLIC +Mword +Filter_console::get_attributes() const +{ + return _o->get_attributes(); +} + diff --git a/kernel/fiasco/src/drivers/glue_libc.cc b/kernel/fiasco/src/drivers/glue_libc.cc new file mode 100644 index 00000000..e1081080 --- /dev/null +++ b/kernel/fiasco/src/drivers/glue_libc.cc @@ -0,0 +1,52 @@ +#include "libc_backend.h" +#include "console.h" + +int __libc_backend_outs(const char *s, size_t len) +{ + if (!Console::stdout) + return len; + + char const *e = s + len; + char const *p = s; + while (s < e) + { + for (; p < e && *p != '\n'; ++p) + ; + + while (s < p) + { + int written = Console::stdout->write(s, p - s); + if (written < 0) + return written; + s += written; + } + + if (p < e && *p == '\n') + { + Console::stdout->write("\r", 1); + ++p; + } + } + + return len; +} + +int __libc_backend_ins(char *s, size_t len) +{ + if (Console::stdin) + { + size_t act = 0; + for (; act < len; act++) + { + s[act] = Console::stdin->getchar(); + if (s[act] == '\r') + { + act++; + break; + } + } + return act; + } + + return 0; +} diff --git a/kernel/fiasco/src/drivers/ia32/io-ia32.cpp b/kernel/fiasco/src/drivers/ia32/io-ia32.cpp new file mode 100644 index 00000000..f61a9b03 --- /dev/null +++ b/kernel/fiasco/src/drivers/ia32/io-ia32.cpp @@ -0,0 +1,53 @@ +IMPLEMENTATION[ia32]: + + +/* This is a more reliable delay than a few short jmps. */ +IMPLEMENT inline +void Io::iodelay() +{ + asm("inb $0x80,%%al; inb $0x80,%%al" : : : "eax"); +} + +IMPLEMENT inline +Unsigned8 Io::in8 ( unsigned long port ) +{ + Unsigned8 tmp; + asm volatile ("inb %w1, %b0": "=a"(tmp) : "Nd"(port) ); + return tmp; +} + +IMPLEMENT inline +Unsigned16 Io::in16( unsigned long port ) +{ + Unsigned16 tmp; + asm volatile ("inw %w1, %w0": "=a"(tmp) : "Nd"(port) ); + return tmp; +} + +IMPLEMENT inline +Unsigned32 Io::in32( unsigned long port ) +{ + Unsigned32 tmp; + asm volatile ("in %w1, %0": "=a"(tmp) : "Nd"(port) ); + return tmp; +} + +IMPLEMENT inline +void Io::out8 ( Unsigned8 val, unsigned long port ) +{ + asm volatile ("outb %b0, %w1": : "a"(val), "Nd"(port) ); +} + +IMPLEMENT inline +void Io::out16( Unsigned16 val, unsigned long port ) +{ + asm volatile ("outw %w0, %w1": : "a"(val), "Nd"(port) ); +} + +IMPLEMENT inline +void Io::out32( Unsigned32 val, unsigned long port ) +{ + asm volatile ("out %0, %w1": : "a"(val), "Nd"(port) ); +} + + diff --git a/kernel/fiasco/src/drivers/ia32/keycodes-arch.h b/kernel/fiasco/src/drivers/ia32/keycodes-arch.h new file mode 100644 index 00000000..dc8f6158 --- /dev/null +++ b/kernel/fiasco/src/drivers/ia32/keycodes-arch.h @@ -0,0 +1,15 @@ +/* -*- c++ -*- */ + +#ifndef KEYCODES_ARCH_H__ +#define KEYCODES_ARCH_H__ + +enum +{ + KEY_BACKSPACE = 0x08, + KEY_TAB = 0x09, + KEY_ESC = 0x1b, + KEY_RETURN = 0x0d, +}; + +#endif // KEYCODES_ARCH_H__ + diff --git a/kernel/fiasco/src/drivers/ia32/mem-ia32.cpp b/kernel/fiasco/src/drivers/ia32/mem-ia32.cpp new file mode 100644 index 00000000..d2fcb8fb --- /dev/null +++ b/kernel/fiasco/src/drivers/ia32/mem-ia32.cpp @@ -0,0 +1,84 @@ +IMPLEMENTATION [ia32 || ux]: + +IMPLEMENT static inline +void +Mem::memset_mwords (void *dst, unsigned long value, unsigned long n) +{ + unsigned dummy1, dummy2; + asm volatile ("cld \n\t" + "repz stosl \n\t" + : "=c"(dummy1), "=D"(dummy2) + : "a"(value), "c"(n), "D"(dst) + : "memory"); +} + + +IMPLEMENT static inline +void +Mem::memcpy_bytes (void *dst, void const *src, unsigned long n) +{ + unsigned dummy1, dummy2, dummy3; + + asm volatile ("cld \n\t" + "repz movsl %%ds:(%%esi), %%es:(%%edi) \n\t" + "mov %%edx, %%ecx \n\t" + "repz movsb %%ds:(%%esi), %%es:(%%edi) \n\t" + : "=c" (dummy1), "=S" (dummy2), "=D" (dummy3) + : "c" (n >> 2), "d" (n & 3), "S" (src), "D" (dst) + : "memory"); +} + + +IMPLEMENT static inline +void +Mem::memcpy_mwords (void *dst, void const *src, unsigned long n) +{ + unsigned dummy1, dummy2, dummy3; + + asm volatile ("cld \n\t" + "rep movsl %%ds:(%%esi), %%es:(%%edi) \n\t" + : "=c" (dummy1), "=S" (dummy2), "=D" (dummy3) + : "c" (n), "S" (src), "D" (dst) + : "memory"); +} + +PUBLIC static inline +void +Mem::memcpy_bytes_fs (void *dst, void const *src, unsigned long n) +{ + unsigned dummy1, dummy2, dummy3; + + asm volatile ("cld \n\t" + "rep movsl %%fs:(%%esi), %%es:(%%edi) \n\t" + "mov %%edx, %%ecx \n\t" + "repz movsb %%fs:(%%esi), %%es:(%%edi) \n\t" + : "=c" (dummy1), "=S" (dummy2), "=D" (dummy3) + : "c" (n >> 2), "d" (n & 3), "S" (src), "D" (dst) + : "memory"); +} + +PUBLIC static inline +void +Mem::memcpy_mwords_fs (void *dst, void const *src, unsigned long n) +{ + unsigned dummy1, dummy2, dummy3; + + asm volatile ("cld \n\t" + "rep movsl %%fs:(%%esi), %%es:(%%edi) \n\t" + : "=c" (dummy1), "=S" (dummy2), "=D" (dummy3) + : "c" (n), "S" (src), "D" (dst) + : "memory"); +} + +// ------------------------------------------------------------------------ +IMPLEMENTATION [(ia32 || ux) && mp]: + +IMPLEMENT inline static void Mem::mb() +{ __asm__ __volatile__ ("lock; addl $0,0(%%esp)" : : : "memory"); /* mfence */ } + +IMPLEMENT inline static void Mem::rmb() { mb(); /* lfence */ } +IMPLEMENT inline static void Mem::wmb() { barrier(); /* sfence */} + +IMPLEMENT inline static void Mem::mp_mb() { mb(); } +IMPLEMENT inline static void Mem::mp_rmb() { rmb(); } +IMPLEMENT inline static void Mem::mp_wmb() { wmb(); } diff --git a/kernel/fiasco/src/drivers/ia32/processor-ia32.cpp b/kernel/fiasco/src/drivers/ia32/processor-ia32.cpp new file mode 100644 index 00000000..bd9f012b --- /dev/null +++ b/kernel/fiasco/src/drivers/ia32/processor-ia32.cpp @@ -0,0 +1,92 @@ +IMPLEMENTATION [ia32]: + +#include "types.h" +#include "std_macros.h" + +IMPLEMENT static inline +Mword Proc::stack_pointer() +{ + Mword sp; + asm volatile ("movl %%esp, %0" : "=r" (sp)); + return sp; +} + +IMPLEMENT static inline +void Proc::stack_pointer(Mword sp) +{ + asm volatile ("movl %0, %%esp \n" : : "r"(sp)); +} + +IMPLEMENT static inline +Mword Proc::program_counter() +{ + Mword pc; + asm volatile ("call 1f ; 1: pop %0" : "=r"(pc)); + return pc; +} + +IMPLEMENT static inline +void Proc::pause() +{ + asm volatile (" .byte 0xf3, 0x90 #pause \n" ); +} + +/* + * The following simple ASM statements need the clobbering to work around + * a bug in (at least) gcc-3.2.x up to x == 1. The bug was fixed on + * Jan 9th 2003 (see gcc-bugs #9242 and #8832), so a released gcc-3.2.2 + * won't have it. It's safe to take the clobber statements out after + * some time (e.g. when gcc-3.3 is used as a standard compiler). + */ + +IMPLEMENT static inline +void Proc::halt() +{ + asm volatile (" hlt" : : : "memory"); +} + +IMPLEMENT static inline +void Proc::cli() +{ + asm volatile ("cli" : : : "memory"); +} + +IMPLEMENT static inline +void Proc::sti() +{ + asm volatile ("sti" : : : "memory"); +} + +IMPLEMENT static inline +Proc::Status Proc::cli_save() +{ + Status ret; + asm volatile ("pushfl \n\t" + "popl %0 \n\t" + "cli \n\t" + : "=g"(ret) : /* no input */ : "memory"); + return ret; +} + +IMPLEMENT static inline +void Proc::sti_restore(Status st) +{ + if (st & 0x0200) + asm volatile ("sti" : : : "memory"); +} + +IMPLEMENT static inline +Proc::Status Proc::interrupts() +{ + Status ret; + asm volatile ("pushfl \n" + "popl %0 \n" + : "=g"(ret) : /* no input */ : "memory"); + return ret & 0x0200; +} + +IMPLEMENT static inline +void Proc::irq_chance() +{ + asm volatile ("nop; nop;" : : : "memory"); +} diff --git a/kernel/fiasco/src/drivers/ia32/reset-ia32.cpp b/kernel/fiasco/src/drivers/ia32/reset-ia32.cpp new file mode 100644 index 00000000..21a8e0a5 --- /dev/null +++ b/kernel/fiasco/src/drivers/ia32/reset-ia32.cpp @@ -0,0 +1,41 @@ +IMPLEMENTATION[ia32]: + +#include "io.h" +#include "processor.h" + +// reset PC +void __attribute__ ((noreturn)) +platform_reset() +{ + // i8042: store the next byte at port 0x60 as command byte + while (Io::in8 (0x64) & 0x2) + ; + Io::out8_p (0x60, 0x64); + + // i8042 command byte (PS/2-compatible mode): + // b0=0 ... no IRQ 1 is generated when data available in input buffer + // b1=0 ... no IRQ 1 is generated when mouse data available in input buffer + // b2=1 ... set SYS flag in status register -- tells POST to perform + // "warm boot" tests/initiailization + // b3=0 ... reserved + // b4=0 ... keyboard interface enabled + // b5=0 ... auxillary PS/2 device (mouse) interface enabled + // b6=0 ... translation disabled -- data appears at input buffer exactly + // as read from keyboard + // b7=0 ... reserved + while (Io::in8 (0x64) & 0x2) + ; + Io::out8_p (0x4, 0x60); + + // i8042: pulse output port with 1110b + // b0=0 ... reset computer + // b1=1 ... set gate A20 + // b2=1 ... pull mouse data low + // b3=1 ... pull mouse clock low + while (Io::in8 (0x64) & 0x2) + ; + Io::out8_p (0xfe,0x64); + + for (;;) + Proc::pause(); +} diff --git a/kernel/fiasco/src/drivers/io.cpp b/kernel/fiasco/src/drivers/io.cpp new file mode 100644 index 00000000..e1a0685a --- /dev/null +++ b/kernel/fiasco/src/drivers/io.cpp @@ -0,0 +1,185 @@ +INTERFACE: + +#include "types.h" + +/** + * PC I/O port API. + */ +class Io +{ +public: + + /// Delay for slow I/O operations. + static void iodelay(); + + /** + * Read the value of type T at address. + */ + template< typename T > + static T read(Address address); + + /** + * Write the value of type T at address. + */ + template< typename T > + static void write(T value, Address address); + + /** + * Write (read(address) & maskbits) of type T at address. + */ + template< typename T > + static void mask(T mask, Address address); + + /** + * Write (read(address) & ~clearbits) of type T at address. + */ + template< typename T > + static void clear(T clearbits, Address address); + + /** + * Write (read(address) | setbits) of type T at address. + */ + template< typename T > + static void set(T setbits, Address address); + + /** + * Read byte port. + */ + static Unsigned8 in8 ( unsigned long port ); + + /** + * Read 16-bit port. + */ + static Unsigned16 in16( unsigned long port ); + + /** + * Read 32-bit port. + */ + static Unsigned32 in32( unsigned long port ); + + /** + * Write byte port. + */ + static void out8 ( Unsigned8 val, unsigned long port ); + + /** + * Write 16-bit port. + */ + static void out16( Unsigned16 val, unsigned long port ); + + /** + * Write 32-bit port. + */ + static void out32( Unsigned32 val, unsigned long port ); + + /// @name Delayed versions. + //@{ + + /** + * Read 8-bit port. + */ + static Unsigned8 in8_p ( unsigned long port ); + + /** + * Read 16-bit port. + */ + static Unsigned16 in16_p( unsigned long port ); + + /** + * Read 32-bit port. + */ + static Unsigned32 in32_p( unsigned long port ); + + /** + * Write 8-bit port. + */ + static void out8_p ( Unsigned8 val, unsigned long port ); + + /** + * Write 16-bit port. + */ + static void out16_p( Unsigned16 val, unsigned long port ); + + /** + * Write 32-bit port. + */ + static void out32_p( Unsigned32 val, unsigned long port ); + //@} + +}; + + +// ---------------------------------------------------------------------- +IMPLEMENTATION [!ppc32]: + +IMPLEMENT inline +template< typename T > +T Io::read(Address address) +{ return *(volatile T *)address; } + +IMPLEMENT inline +template< typename T> +void Io::write(T value, Address address) +{ *(volatile T *)address = value; } + +IMPLEMENTATION: + +IMPLEMENT inline +template< typename T> +void Io::mask(T mask, Address address) +{ write(read(address) & mask, address); } + +IMPLEMENT inline +template< typename T> +void Io::clear(T clearbits, Address address) +{ write(read(address) & ~clearbits, address); } + +IMPLEMENT inline +template< typename T> +void Io::set(T setbits, Address address) +{ write(read(address) | setbits, address); } + + + + + +IMPLEMENT inline +Unsigned8 Io::in8_p(unsigned long port) +{ + Unsigned8 tmp = in8(port); + iodelay(); + return tmp; +} + +IMPLEMENT inline +Unsigned16 Io::in16_p(unsigned long port) +{ + Unsigned16 tmp = in16(port); + iodelay(); + return tmp; +} + +IMPLEMENT inline +Unsigned32 Io::in32_p(unsigned long port) +{ + Unsigned32 tmp = in32(port); + iodelay(); + return tmp; +} + +IMPLEMENT inline +void Io::out8_p(Unsigned8 val, unsigned long port) +{ + out8(val,port); iodelay(); +} + +IMPLEMENT inline +void Io::out16_p(Unsigned16 val, unsigned long port) +{ + out16(val,port); iodelay(); +} +IMPLEMENT inline +void Io::out32_p(Unsigned32 val, unsigned long port) +{ + out32(val,port); iodelay(); +} diff --git a/kernel/fiasco/src/drivers/keyb-pc.cpp b/kernel/fiasco/src/drivers/keyb-pc.cpp new file mode 100644 index 00000000..312a31ed --- /dev/null +++ b/kernel/fiasco/src/drivers/keyb-pc.cpp @@ -0,0 +1,252 @@ +INTERFACE: + +/** + * Implementation for PC keyboards. + */ +EXTENSION class Keyb +{ +private: + + enum { + /* + * Keyboard I/O ports. + */ + K_RDWR = 0x60, /* keyboard data & cmds (read/write) */ + K_STATUS = 0x64, /* keybd status (read-only) */ + K_CMD = 0x64, /* keybd ctlr command (write-only) */ + + /* + * Bit definitions for K_STATUS port. + */ + K_OBUF_FUL = 0x01, /* output (from keybd) buffer full */ + K_IBUF_FUL = 0x02, /* input (to keybd) buffer full */ + K_SYSFLAG = 0x04, /* "System Flag" */ + K_CMD_DATA = 0x08, /* 1 = input buf has cmd, 0 = data */ + K_KBD_INHIBIT = 0x10, /* 0 if keyboard inhibited */ + K_AUX_OBUF_FUL = 0x20, /* 1 = obuf holds aux device data */ + K_TIMEOUT = 0x40, /* timout error flag */ + K_PARITY_ERROR = 0x80, /* parity error flag */ + + /* + * Keyboard controller commands (sent to K_CMD port). + */ + KC_CMD_READ = 0x20, /* read controller command byte */ + KC_CMD_WRITE = 0x60, /* write controller command byte */ + KC_CMD_DIS_AUX = 0xa7, /* disable auxiliary device */ + KC_CMD_ENB_AUX = 0xa8, /* enable auxiliary device */ + KC_CMD_TEST_AUX = 0xa9, /* test auxiliary device interface */ + KC_CMD_SELFTEST = 0xaa, /* keyboard controller self-test */ + KC_CMD_TEST = 0xab, /* test keyboard interface */ + KC_CMD_DUMP = 0xac, /* diagnostic dump */ + KC_CMD_DISABLE = 0xad, /* disable keyboard */ + KC_CMD_ENABLE = 0xae, /* enable keyboard */ + KC_CMD_RDKBD = 0xc4, /* read keyboard ID */ + KC_CMD_WIN = 0xd0, /* read output port */ + KC_CMD_WOUT = 0xd1, /* write output port */ + KC_CMD_ECHO = 0xee, /* used for diagnostic testing */ + KC_CMD_PULSE = 0xff, /* pulse bits 3-0 based on low nybble */ + + /* + * Keyboard commands (send to K_RDWR). + */ + K_CMD_LEDS = 0xed, /* set status LEDs (caps lock, etc.) */ + + /* + * Bit definitions for controller command byte (sent following + * K_CMD_WRITE command). + */ + K_CB_ENBLIRQ = 0x01, /* enable data-ready intrpt */ + K_CB_SETSYSF = 0x04, /* Set System Flag */ + K_CB_INHBOVR = 0x08, /* Inhibit Override */ + K_CB_DISBLE = 0x10, /* disable keyboard */ + + /* + * Bit definitions for "Indicator Status Byte" (sent after a + * K_CMD_LEDS command). If the bit is on, the LED is on. Undefined + * bit positions must be 0. + */ + K_LED_SCRLLK = 0x1, /* scroll lock */ + K_LED_NUMLK = 0x2, /* num lock */ + K_LED_CAPSLK = 0x4, /* caps lock */ + + /* + * Bit definitions for "Miscellaneous port B" (K_PORTB). + */ + /* read/write */ + K_ENABLETMR2 = 0x01, /* enable output from timer 2 */ + K_SPKRDATA = 0x02, /* direct input to speaker */ + K_ENABLEPRTB = 0x04, /* "enable" port B */ + K_EIOPRTB = 0x08, /* enable NMI on parity error */ + /* read-only */ + K_REFRESHB = 0x10, /* refresh flag from INLTCONT PAL */ + K_OUT2B = 0x20, /* timer 2 output */ + K_ICKB = 0x40, /* I/O channel check (parity error) */ + + /* + * Bit definitions for the keyboard controller's output port. + */ + KO_SYSRESET = 0x01, /* processor reset */ + KO_GATE20 = 0x02, /* A20 address line enable */ + KO_AUX_DATA_OUT = 0x04, /* output data to auxiliary device */ + KO_AUX_CLOCK = 0x08, /* auxiliary device clock */ + KO_OBUF_FUL = 0x10, /* keyboard output buffer full */ + KO_AUX_OBUF_FUL = 0x20, /* aux device output buffer full */ + KO_CLOCK = 0x40, /* keyboard clock */ + KO_DATA_OUT = 0x80, /* output data to keyboard */ + }; +}; + +IMPLEMENTATION[pc]: + +#include "processor.h" +#include "io.h" + +enum { + SHIFT = 0xff, +}; + +static const unsigned char keymap[][2] = { + {0 }, /* 0 */ + {27, 27 }, /* 1 - ESC */ + {'1', '!'}, /* 2 */ + {'2', '@'}, + {'3', '#'}, + {'4', '$'}, + {'5', '%'}, + {'6', '^'}, + {'7', '&'}, + {'8', '*'}, + {'9', '('}, + {'0', ')'}, + {'-', '_'}, + {'=', '+'}, + {8, 8 }, /* 14 - Backspace */ + {'\t','\t'}, /* 15 */ + {'q', 'Q'}, + {'w', 'W'}, + {'e', 'E'}, + {'r', 'R'}, + {'t', 'T'}, + {'y', 'Y'}, + {'u', 'U'}, + {'i', 'I'}, + {'o', 'O'}, + {'p', 'P'}, + {'[', '{'}, +// {']','}'}, /* 27 */ + {'+', '*'}, /* 27 */ + {'\r','\r'}, /* 28 - Enter */ + {0, 0 }, /* 29 - Ctrl */ + {'a', 'A'}, /* 30 */ + {'s', 'S'}, + {'d', 'D'}, + {'f', 'F'}, + {'g', 'G'}, + {'h', 'H'}, + {'j', 'J'}, + {'k', 'K'}, + {'l', 'L'}, + {';', ':'}, + {'\'','"'}, /* 40 */ + {'`', '~'}, /* 41 */ + {SHIFT, SHIFT}, /* 42 - Left Shift */ + {'\\','|'}, /* 43 */ + {'z', 'Z'}, /* 44 */ + {'x', 'X'}, + {'c', 'C'}, + {'v', 'V'}, + {'b', 'B'}, + {'n', 'N'}, + {'m', 'M'}, + {',', '<'}, + {'.', '>'}, +// {'/', '?'}, /* 53 */ + {'-', '_'}, /* 53 */ + {SHIFT, SHIFT}, /* 54 - Right Shift */ + {0, 0}, /* 55 - Print Screen */ + {0, 0}, /* 56 - Alt */ + {' ',' '}, /* 57 - Space bar */ + {0, 0}, /* 58 - Caps Lock */ + {0, 0}, /* 59 - F1 */ + {0, 0}, /* 60 - F2 */ + {0, 0}, /* 61 - F3 */ + {0, 0}, /* 62 - F4 */ + {0, 0}, /* 63 - F5 */ + {0, 0}, /* 64 - F6 */ + {0, 0}, /* 65 - F7 */ + {0, 0}, /* 66 - F8 */ + {0, 0}, /* 67 - F9 */ + {0, 0}, /* 68 - F10 */ + {0, 0}, /* 69 - Num Lock */ + {0, 0}, /* 70 - Scroll Lock */ + {0xb7,0xb7}, /* 71 - Numeric keypad 7 */ + {0xb8,0xb8}, /* 72 - Numeric keypad 8 */ + {0xb9,0xb9}, /* 73 - Numeric keypad 9 */ + {'-', '-'}, /* 74 - Numeric keypad '-' */ + {0xb4,0xb4}, /* 75 - Numeric keypad 4 */ + {0xb5,0xb5}, /* 76 - Numeric keypad 5 */ + {0xb6,0xb6}, /* 77 - Numeric keypad 6 */ + {'+', '+'}, /* 78 - Numeric keypad '+' */ + {0xb1,0xb1}, /* 79 - Numeric keypad 1 */ + {0xb2,0xb2}, /* 80 - Numeric keypad 2 */ + {0xb3,0xb3}, /* 81 - Numeric keypad 3 */ + {0xb0,0xb0}, /* 82 - Numeric keypad 0 */ + {0xae,0xae}, /* 83 - Numeric keypad '.' */ +}; + + +IMPLEMENT +int Keyb::getchar(bool wait) +{ + static unsigned shift_state; + unsigned status, scan_code, ch; + Proc::Status old_s = Proc::cli_save(); + + for (;;) + { + /* Wait until a scan code is ready and read it. */ + status = Io::in8(0x64); + if ((status & K_OBUF_FUL) == 0) + { + if (wait) + continue; + Proc::sti_restore(old_s); + return -1; + } + scan_code = Io::in8(0x60); + + /* Drop mouse events */ + if ((status & K_AUX_OBUF_FUL) != 0) + { + if (wait) + continue; + Proc::sti_restore(old_s); + return -1; + } + + if ((scan_code & 0x7f) >= sizeof(keymap)/sizeof(keymap[0])) + continue; + + /* Handle key releases - only release of SHIFT is important. */ + if (scan_code & 0x80) + { + scan_code &= 0x7f; + if (keymap[scan_code][0] == SHIFT) + shift_state = 0; + continue; + } + + /* Translate the character through the keymap. */ + ch = keymap[scan_code][shift_state]; + if (ch == (unsigned)SHIFT) + { + shift_state = 1; + continue; + } + if (ch == 0) + continue; + + Proc::sti_restore(old_s); + return ch; + } +} diff --git a/kernel/fiasco/src/drivers/keyb.cpp b/kernel/fiasco/src/drivers/keyb.cpp new file mode 100644 index 00000000..c0efa7dc --- /dev/null +++ b/kernel/fiasco/src/drivers/keyb.cpp @@ -0,0 +1,36 @@ +INTERFACE: + +#include "console.h" + +/** + * Platform independent keyboard stub. + * + * Provides an empty implentation for write(...). + */ +class Keyb : public Console +{ +public: + // must be implemented in platform part. + int getchar(bool blocking = true); + + // implemented empty + int write(char const *str, size_t len); +}; + + +IMPLEMENTATION: + +IMPLEMENT +int +Keyb::write( char const *, size_t len) +{ + return len; +} + +PUBLIC +Mword +Keyb::get_attributes() const +{ + return DIRECT | IN; +} + diff --git a/kernel/fiasco/src/drivers/keycodes.h b/kernel/fiasco/src/drivers/keycodes.h new file mode 100644 index 00000000..44dba42a --- /dev/null +++ b/kernel/fiasco/src/drivers/keycodes.h @@ -0,0 +1,24 @@ +/* -*- c++ -*- */ + +#ifndef KEYCODES_H__ +#define KEYCODES_H__ + +#include "keycodes-arch.h" + +enum +{ + KEY_CURSOR_UP = 0xb8, + KEY_CURSOR_DOWN = 0xb2, + KEY_CURSOR_LEFT = 0xb4, + KEY_CURSOR_RIGHT = 0xb6, + KEY_CURSOR_HOME = 0xb7, + KEY_CURSOR_END = 0xb1, + KEY_PAGE_UP = 0xb9, + KEY_PAGE_DOWN = 0xb3, + KEY_INSERT = 0xb0, + KEY_DELETE = 0xae, + KEY_F1 = 0xc0, +}; + +#endif // KEYCODES_H__ + diff --git a/kernel/fiasco/src/drivers/libc_backend.h b/kernel/fiasco/src/drivers/libc_backend.h new file mode 100644 index 00000000..abb446f3 --- /dev/null +++ b/kernel/fiasco/src/drivers/libc_backend.h @@ -0,0 +1,47 @@ +/* This file defines the back-end interface */ +/* of the kernel C-library. */ + +#ifndef __LIBC_BACKEND_H__ +#define __LIBC_BACKEND_H__ + +#include +#include + +__BEGIN_DECLS + +/** + * The text output back-end. + * + * This function must be provided to the C-library for + * text output. It must simply send len characters of s + * to an output device. + * + * @param s Buffer to send. + * @param len The number of bytes. + * @return 1 on success, 0 else. + */ +int __libc_backend_outs(const char *s, size_t len); + +/** + * The text input back-end. + * + * This function must be provided to the C-library for + * text input. It has to block until len characters are + * read or a newline is reached. The return value gives + * the number of characters virtually read. + * + * @param s A pointer to the buffer for the read text. + * @param len The size of the buffer. + * @return the number of characters virtually read. + */ +int __libc_backend_ins(char *s, size_t len); + +typedef unsigned long __libc_backend_printf_lock_t; + +__libc_backend_printf_lock_t __libc_backend_printf_lock(void); + +void __libc_backend_printf_unlock(__libc_backend_printf_lock_t); + +__END_DECLS + +#endif //__LIBC_BACKEND_H__ diff --git a/kernel/fiasco/src/drivers/mem.cpp b/kernel/fiasco/src/drivers/mem.cpp new file mode 100644 index 00000000..d978cb7c --- /dev/null +++ b/kernel/fiasco/src/drivers/mem.cpp @@ -0,0 +1,37 @@ +INTERFACE: + +class Mem +{ +public: + /** + * Memory barriers. + */ + static void barrier() { __asm__ __volatile__ ("" : : : "memory"); } + + static void mb(); + static void rmb(); + static void wmb(); + + static void mp_mb(); + static void mp_rmb(); + static void mp_wmb(); + + + /** + * Memory operations. + */ + static void memcpy_mwords(void *dst, void const *src, unsigned long nr_of_mwords); + static void memcpy_bytes (void *dst, void const *src, unsigned long nr_of_bytes); + static void memset_mwords(void *dst, const unsigned long val, unsigned long nr_of_mwords); +}; + +//--------------------------------------------------------------------------- +IMPLEMENTATION[!mp]: + +IMPLEMENT inline static void Mem::mb() { barrier(); } +IMPLEMENT inline static void Mem::rmb() { barrier(); } +IMPLEMENT inline static void Mem::wmb() { barrier(); } + +IMPLEMENT inline static void Mem::mp_mb() { barrier(); } +IMPLEMENT inline static void Mem::mp_rmb() { barrier(); } +IMPLEMENT inline static void Mem::mp_wmb() { barrier(); } diff --git a/kernel/fiasco/src/drivers/mmu.cpp b/kernel/fiasco/src/drivers/mmu.cpp new file mode 100644 index 00000000..7cc8310e --- /dev/null +++ b/kernel/fiasco/src/drivers/mmu.cpp @@ -0,0 +1,186 @@ +INTERFACE: + +#include "types.h" + +template< unsigned long Flush_area = 0, bool Ram = false > +class Mmu +{ +public: + /* start address is include, end address is exclusive + * (end = start + size) */ + static void clean_vdcache(); + static void clean_vdcache(void const *start, void const *end); + static void flush_vcache(); + static void flush_vcache(void const *start, void const *end); + static void flush_vdcache(); + static void flush_vdcache(void const *start, void const *end); + static void inv_vdcache(void const *start, void const *end); + + /** + * Clean the entire dcache. + */ + static void clean_dcache(); + + + /** + * Clean given D cache region. + */ + static void clean_dcache(void const *va); + + /** + * Clean given D cache region. + */ + static void clean_dcache(void const *start, void const *end); + /** + * Clean and invalidate the entire cache. + * D and I cache is cleaned and invalidated and the write buffer is + * drained. + */ + static void flush_cache(); + + + /** + * Clean and invalidate the given cache region. + * D and I cache are affected. + */ + static void flush_cache(void const *start, void const *end); + + /** + * Clean and invalidate the entire D cache. + */ + static void flush_dcache(); + + /** + * Clean and invalidate the given D cache region. + */ + static void flush_dcache(void const *start, void const *end); + + /** + * Invalidate the given D cache region. + */ + static void inv_dcache(void const *start, void const *end); + + /** + * Switch page table and do the necessary things. + */ + static void switch_pdbr(Address base); + + // static void write_back_data_cache(bool ram = false); + // static void write_back_data_cache(void *a); +}; + +//--------------------------------------------------------------------------- +IMPLEMENTATION [!arm || arm_nocache]: + +IMPLEMENT inline +template< unsigned long Flush_area, bool Ram > +void Mmu::flush_cache() +{} + +IMPLEMENT inline +template< unsigned long Flush_area, bool Ram > +void Mmu::flush_cache(void const *, void const *) +{} + +IMPLEMENT inline +template< unsigned long Flush_area, bool Ram > +void Mmu::clean_dcache() +{} + +IMPLEMENT inline +template< unsigned long Flush_area, bool Ram > +void Mmu::clean_dcache(void const *, void const *) +{} + +IMPLEMENT inline +template< unsigned long Flush_area, bool Ram > +void Mmu::flush_dcache() +{} + +IMPLEMENT inline +template< unsigned long Flush_area, bool Ram > +void Mmu::flush_dcache(void const *, void const *) +{} + +IMPLEMENT inline +template< unsigned long Flush_area, bool Ram > +void Mmu::inv_dcache(void const *, void const *) +{} + +//--------------------------------------------------------------------------- +IMPLEMENTATION[!vcache]: + +IMPLEMENT inline +template< unsigned long Flush_area, bool Ram > +void Mmu::flush_vcache(void const *, void const *) +{} + +IMPLEMENT +template< unsigned long Flush_area , bool Ram > +void Mmu::clean_vdcache(void const *, void const *) +{} + +IMPLEMENT +template< unsigned long Flush_area, bool Ram > +void Mmu::flush_vdcache(void const *, void const *) +{} + +IMPLEMENT +template< unsigned long Flush_area, bool Ram > +void Mmu::inv_vdcache(void const *, void const *) +{} + +IMPLEMENT +template< unsigned long Flush_area, bool Ram > +void Mmu::flush_vcache() +{} + +IMPLEMENT +template< unsigned long Flush_area, bool Ram > +void Mmu::clean_vdcache() +{} + +IMPLEMENT +template< unsigned long Flush_area, bool Ram > +void Mmu::flush_vdcache() +{} + + +//--------------------------------------------------------------------------- +IMPLEMENTATION[vcache]: + +IMPLEMENT inline +template< unsigned long Flush_area, bool Ram > +void Mmu::flush_vcache(void const *start, + void const *end) +{ flush_cache(start, end); } + +IMPLEMENT +template< unsigned long Flush_area , bool Ram > +void Mmu::clean_vdcache(void const *start, void const *end) +{ clean_dcache(start, end); } + +IMPLEMENT +template< unsigned long Flush_area, bool Ram > +void Mmu::flush_vdcache(void const *start, void const *end) +{ flush_dcache(start, end); } + +IMPLEMENT +template< unsigned long Flush_area, bool Ram > +void Mmu::inv_vdcache(void const *start, void const *end) +{ inv_dcache(start, end); } + +IMPLEMENT +template< unsigned long Flush_area, bool Ram > +void Mmu::flush_vcache() +{ flush_cache(); } + +IMPLEMENT +template< unsigned long Flush_area, bool Ram > +void Mmu::clean_vdcache() +{ clean_dcache(); } + +IMPLEMENT +template< unsigned long Flush_area, bool Ram > +void Mmu::flush_vdcache() +{ flush_dcache(); } diff --git a/kernel/fiasco/src/drivers/mux_console.cpp b/kernel/fiasco/src/drivers/mux_console.cpp new file mode 100644 index 00000000..cc6cbf07 --- /dev/null +++ b/kernel/fiasco/src/drivers/mux_console.cpp @@ -0,0 +1,277 @@ +INTERFACE: + +#include "types.h" +#include "console.h" + +/** + * Console multiplexer. + * + * This implementation of the Console interface can be used to + * multiplex among some input, output, and in-out consoles. + */ +class Mux_console : public Console +{ +public: + + enum + { + SIZE = 8 ///< The maximum number of consoles to be multiplexed. + }; + + int write(char const *str, size_t len); + int getchar(bool blocking = true); + int char_avail() const; + +private: + int _next_getchar; + int _items; + Console *_cons[SIZE]; +}; + + +IMPLEMENTATION: + +#include +#include "processor.h" + +PUBLIC +Mux_console::Mux_console() + : _next_getchar(-1), _items(0) +{} + +IMPLEMENT +int +Mux_console::write(char const *str, size_t len) +{ + for (int i = 0; i < _items; ++i) + if (_cons[i] && (_cons[i]->state() & OUTENABLED)) + _cons[i]->write(str, len); + + return len; +} + +IMPLEMENT +int +Mux_console::getchar(bool blocking) +{ + if (_next_getchar != -1) + { + int c = _next_getchar; + _next_getchar = -1; + return c; + } + + int ret = -1; + do + { + for (int i = 0; i < _items; ++i) + if (_cons[i] && (_cons[i]->state() & INENABLED)) + { + ret = _cons[i]->getchar(false); + if (ret != -1) + return ret; + } + + if (blocking) + Proc::pause(); + } + while (blocking && ret == -1); + + return ret; +} + +/** + * deliver attributes of all subconsoles. + */ +PUBLIC +Mword +Mux_console::get_attributes() const +{ + Mword attr = 0; + + for (int i = 0; i < _items; i++) + if (_cons[i]) + attr |= _cons[i]->get_attributes(); + + return attr; +} + +PUBLIC +void +Mux_console::getchar_chance() +{ + for (int i = 0; i < _items; ++i) + if ( _cons[i] && (_cons[i]->state() & INENABLED) + && _cons[i]->char_avail() == 1) + { + int c = _cons[i]->getchar(false); + if (c != -1 && _next_getchar == -1) + _next_getchar = c; + } +} + +IMPLEMENT +int +Mux_console::char_avail() const +{ + int ret = -1; + for (int i = 0; i < _items; ++i) + if (_cons[i] && (_cons[i]->state() & INENABLED)) + { + int tmp = _cons[i]->char_avail(); + if (tmp == 1) + return 1; + else if (tmp == 0) + ret = tmp; + } + return ret; +} + +/** + * Register a console to be multiplexed. + * @param cons the Console to add. + * @param pos the position of the console, normally not needed. + */ +PUBLIC virtual +bool +Mux_console::register_console(Console *c, int pos = 0) +{ + if (c->failed()) + return false; + + if (_items >= SIZE) + return false; + + if (pos >= SIZE || pos < 0) + return false; + + if (pos > _items) + pos = _items; + + if (pos < _items) + for (int i = _items - 1; i >= pos; --i) + _cons[i + 1] = _cons[i]; + + _items++; + _cons[pos] = c; + if (_cons[pos]->state() & DISABLED_INIT) + _cons[pos]->state(DISABLED); + else + _cons[pos]->state(INENABLED | OUTENABLED); + + return true; +} + +/** + * Unregister a console from the multiplexer. + * @param cons the console to remove. + */ +PUBLIC +bool +Mux_console::unregister_console(Console *c) +{ + int pos; + for (pos = 0; pos < _items && _cons[pos] != c; pos++) + ; + if (pos == _items) + return false; + + --_items; + for (int i = pos; i < _items; ++i) + _cons[i] = _cons[i + 1]; + + return true; +} + +/** + * Change the state of a group of consoles specified by + * attributes. + * @param any_true match if console has any of these attributes + * @param all_false match if console doesn't have any of these attributes + */ +PUBLIC +void +Mux_console::change_state(Mword any_true, Mword all_false, + Mword mask, Mword bits) +{ + for (int i=0; i<_items; i++) + { + if (_cons[i]) + { + Mword attr = _cons[i]->get_attributes(); + if ( // any bit of the any_true attributes must be set + (!any_true || (attr & any_true) != 0) + // all bits of the all_false attributes must be cleared + && (!all_false || (attr & all_false) == 0)) + { + _cons[i]->state((_cons[i]->state() & mask) | bits); + } + } + } +} + +/** + * Find a console with a specific attribute. + * @param any_true match to console which has set any bit of this bitmask + */ +PUBLIC +Console* +Mux_console::find_console(Mword any_true) +{ + for (int i = 0; i < _items; i++) + if (_cons[i] && _cons[i]->get_attributes() & any_true) + return _cons[i]; + + return 0; +} + +/** + * Start exclusive mode for a specific console. Only the one + * console which matches to any_true is enabled for input and + * output. All other consoles are disabled. + * @param any_true match to console which has set any bit of this bitmask + */ +PUBLIC +void +Mux_console::start_exclusive(Mword any_true) +{ + // enable exclusive console + change_state(any_true, 0, ~0UL, (OUTENABLED|INENABLED)); + // disable all other consoles + change_state(0, any_true, ~(OUTENABLED|INENABLED), 0); +} + +/** + * End exclusive mode for a specific console. + * @param any_true match to console which has set any bit of this bitmask + */ +PUBLIC +void +Mux_console::end_exclusive(Mword any_true) +{ + // disable exclusive console + change_state(any_true, 0, ~(OUTENABLED|INENABLED), 0); + // enable all other consoles + change_state(0, any_true, ~0UL, (OUTENABLED|INENABLED)); +} + + +IMPLEMENTATION[debug]: + +PUBLIC +void +Mux_console::list_consoles() +{ + for (int i = 0; i < _items; i++) + if (_cons[i]) + { + Mword attr = _cons[i]->get_attributes(); + + printf(" " L4_PTR_FMT " %s (%s) ", + attr, _cons[i]->str_mode(), _cons[i]->str_state()); + for (unsigned bit = 2; bit < sizeof(attr) * 4; bit++) + if (attr & (1 << bit)) + printf("%s ", Console::str_attr(bit)); + putchar('\n'); + } +} diff --git a/kernel/fiasco/src/drivers/pci.cpp b/kernel/fiasco/src/drivers/pci.cpp new file mode 100644 index 00000000..07185e22 --- /dev/null +++ b/kernel/fiasco/src/drivers/pci.cpp @@ -0,0 +1,89 @@ +INTERFACE: + +#include "types.h" + +class Pci +{ + enum + { + Cfg_addr = 0xcf8, + Cfg_data = 0xcfc, + }; +}; + + +IMPLEMENTATION: + +#include "io.h" + +PUBLIC static inline NEEDS["io.h"] +Unsigned8 +Pci::read_cfg8 (Mword bus, Mword dev, Mword subdev, Mword reg) +{ + Io::out32 (((bus & 0xffff) << 16) | + ((dev & 0x1f) << 11) | + ((subdev & 0x07) << 8) | + ((reg & 0xff) ) | + 1<<31, Cfg_addr); + return Io::in8 (Cfg_data + (reg & 3)); +} + +PUBLIC static inline NEEDS["io.h"] +Unsigned16 +Pci::read_cfg16 (Mword bus, Mword dev, Mword subdev, Mword reg) +{ + Io::out32 (((bus & 0xffff) << 16) | + ((dev & 0x1f) << 11) | + ((subdev & 0x07) << 8) | + ((reg & 0xfe) ) | + 1<<31, Cfg_addr); + return Io::in16 (Cfg_data + (reg & 2)); +} + +PUBLIC static inline NEEDS["io.h"] +Unsigned32 +Pci::read_cfg32 (Mword bus, Mword dev, Mword subdev, Mword reg) +{ + Io::out32 (((bus & 0xffff) << 16) | + ((dev & 0x1f) << 11) | + ((subdev & 0x07) << 8) | + ((reg & 0xfc) ) | + 1<<31, Cfg_addr); + return Io::in32 (Cfg_data); +} + +PUBLIC static inline NEEDS["io.h"] +void +Pci::write_cfg8 (Mword bus, Mword dev, Mword subdev, Mword reg, Unsigned8 v) +{ + Io::out32 (((bus & 0xffff) << 16) | + ((dev & 0x1f) << 11) | + ((subdev & 0x07) << 8) | + ((reg & 0xff) ) | + 1<<31, Cfg_addr); + Io::out8 (v, Cfg_data + (reg & 3)); +} + +PUBLIC static inline NEEDS["io.h"] +void +Pci::write_cfg16 (Mword bus, Mword dev, Mword subdev, Mword reg, Unsigned16 v) +{ + Io::out32 (((bus & 0xffff) << 16) | + ((dev & 0x1f) << 11) | + ((subdev & 0x07) << 8) | + ((reg & 0xfe) ) | + 1<<31, Cfg_addr); + Io::out16 (v, Cfg_data + (reg & 2)); +} + +PUBLIC static inline NEEDS["io.h"] +void +Pci::write_cfg32 (Mword bus, Mword dev, Mword subdev, Mword reg, Unsigned32 v) +{ + Io::out32 (((bus & 0xffff) << 16) | + ((dev & 0x1f) << 11) | + ((subdev & 0x07) << 8) | + ((reg & 0xfc) ) | + 1<<31, Cfg_addr); + Io::out32 (v, Cfg_data); +} diff --git a/kernel/fiasco/src/drivers/ppc32/include/mmu.h b/kernel/fiasco/src/drivers/ppc32/include/mmu.h new file mode 100644 index 00000000..3cf741a3 --- /dev/null +++ b/kernel/fiasco/src/drivers/ppc32/include/mmu.h @@ -0,0 +1,46 @@ +#ifndef __DRIVERS_PPC32_INCLUDE_MMU_H_ +#define __DRIVERS_PPC32_INCLUDE_MMU_H_ + +/** + * This guard enables and disables the data-cache of G2 cores using the HID0 + * register + */ +class Mmu_guard +{ +public: + Mmu_guard() : _interrupt(0), _hid0(0) + { + asm volatile ( " mfmsr %[intr] \n" //disable interrupts + " andc %[ee], %[intr], %[ee] \n" + " mtmsr %[ee] \n" + " mfspr %[hid0], 1008 \n" //read HID0 + " or %[dcache], %[hid0], %[dcache] \n" + " sync \n" + " mtspr 1008, %[dcache] \n" //disable data cache + // " isync \n" + : [intr] "=r" (_interrupt), + [hid0] "=r" (_hid0) + : [ee] "r"(1 << 15), + [dcache] "r"(1 << 12) + : "memory" + ); + } + + ~Mmu_guard() + { + asm volatile(" sync \n" + " mtspr 1008, %1 \n" + " mtmsr %0 \n" +// " isync \n" + : + : "r"(_interrupt), + "r"(_hid0)); + + } + +private: + unsigned int _interrupt; + unsigned int _hid0; +}; + +#endif //__DRIVERS_PPC32_INCLUDE_MMU_H_ diff --git a/kernel/fiasco/src/drivers/ppc32/io-ppc32.cpp b/kernel/fiasco/src/drivers/ppc32/io-ppc32.cpp new file mode 100644 index 00000000..8901cab7 --- /dev/null +++ b/kernel/fiasco/src/drivers/ppc32/io-ppc32.cpp @@ -0,0 +1,101 @@ +INTERFACE [ppc32]: + +EXTENSION class Io +{ +public: + /** + * Read but do not disable data cache + */ + template< typename T > + static T read_dirty(Address address); + + /** + * Write but do not disable data cache + */ + template< typename T> + static void write_dirty(T value, Address address); +}; + + +IMPLEMENTATION [ppc32]: + +#include "mem_unit.h" +#include "mmu.h" + +IMPLEMENT inline NEEDS["mem_unit.h"] +template< typename T > +T Io::read_dirty(Address address) +{ + volatile T ret; + Mem_unit::sync(); + ret = *(volatile T *)address; + Mem_unit::isync(); + return ret; +} + +IMPLEMENT inline NEEDS["mmu.h"] +template< typename T > +T Io::read(Address address) +{ + Mmu_guard dcache; + return read_dirty(address); +} + +IMPLEMENT inline NEEDS["mem_unit.h"] +template< typename T> +void Io::write_dirty(T value, Address address) +{ + Mem_unit::sync(); + *(volatile T *)address = value; +} + +IMPLEMENT inline NEEDS["mmu.h"] +template< typename T> +void Io::write(T value, Address address) +{ + Mmu_guard dcache; + write_dirty(value, address); +} + +//------------------------------------------------------------------------------ +/** + * No port support + */ +IMPLEMENT inline +void Io::iodelay() +{} + +IMPLEMENT inline +Unsigned8 Io::in8 ( unsigned long /* port */ ) +{ + return 0; +} + +IMPLEMENT inline +Unsigned16 Io::in16( unsigned long /* port */ ) +{ + return 0; +} + +IMPLEMENT inline +Unsigned32 Io::in32( unsigned long /* port */ ) +{ + return 0; +} + +IMPLEMENT inline +void Io::out8 ( Unsigned8 /* val */, unsigned long /* port */ ) +{ +} + +IMPLEMENT inline +void Io::out16( Unsigned16 /* val */, unsigned long /* port */ ) +{ +} + +IMPLEMENT inline +void Io::out32( Unsigned32 /* val */, unsigned long /* port */ ) +{ +} + + diff --git a/kernel/fiasco/src/drivers/ppc32/kernel_uart-ppc32.cpp b/kernel/fiasco/src/drivers/ppc32/kernel_uart-ppc32.cpp new file mode 100644 index 00000000..f5b7750e --- /dev/null +++ b/kernel/fiasco/src/drivers/ppc32/kernel_uart-ppc32.cpp @@ -0,0 +1,11 @@ +INTERFACE: + +EXTENSION class Kernel_uart { enum { Bsp_init_mode = Init_before_mmu }; }; + +IMPLEMENTATION [ppc32 && serial]: + +IMPLEMENT +bool Kernel_uart::startup(unsigned, int /*irq*/) +{ + return Uart::startup(); +} diff --git a/kernel/fiasco/src/drivers/ppc32/keycodes-arch.h b/kernel/fiasco/src/drivers/ppc32/keycodes-arch.h new file mode 100644 index 00000000..dc8f6158 --- /dev/null +++ b/kernel/fiasco/src/drivers/ppc32/keycodes-arch.h @@ -0,0 +1,15 @@ +/* -*- c++ -*- */ + +#ifndef KEYCODES_ARCH_H__ +#define KEYCODES_ARCH_H__ + +enum +{ + KEY_BACKSPACE = 0x08, + KEY_TAB = 0x09, + KEY_ESC = 0x1b, + KEY_RETURN = 0x0d, +}; + +#endif // KEYCODES_ARCH_H__ + diff --git a/kernel/fiasco/src/drivers/ppc32/mem-ppc32.cpp b/kernel/fiasco/src/drivers/ppc32/mem-ppc32.cpp new file mode 100644 index 00000000..181def98 --- /dev/null +++ b/kernel/fiasco/src/drivers/ppc32/mem-ppc32.cpp @@ -0,0 +1,25 @@ +//----------------------------------------------------------------------------- +IMPLEMENTATION [ppc32]: + +IMPLEMENT static inline +void +Mem::memset_mwords (void *dst, const unsigned long value, unsigned long nr_of_mwords) +{ + unsigned long *d = (unsigned long *)dst; + for (; nr_of_mwords--; d++) + *d = value; +} + +IMPLEMENT static inline +void +Mem::memcpy_mwords (void *dst, void const *src, unsigned long nr_of_mwords) +{ + __builtin_memcpy(dst, src, nr_of_mwords * sizeof(unsigned long)); +} + +IMPLEMENT static inline +void +Mem::memcpy_bytes(void *dst, void const *src, unsigned long nr_of_bytes) +{ + __builtin_memcpy(dst, src, nr_of_bytes); +} diff --git a/kernel/fiasco/src/drivers/ppc32/ppc_types.cpp b/kernel/fiasco/src/drivers/ppc32/ppc_types.cpp new file mode 100644 index 00000000..556e75de --- /dev/null +++ b/kernel/fiasco/src/drivers/ppc32/ppc_types.cpp @@ -0,0 +1,21 @@ +INTERFACE [ppc32]: + +/** + * Device specification + */ +class Of_device +{ +public: + char type[32]; //device type name + char name[32]; //device name + Address reg; //memory-mapped-register base + + union { + struct { + unsigned long cpu_freq; + unsigned long bus_freq; + unsigned long time_freq; + } freq; + unsigned interrupt[3]; //pin, int nr, sense + }; +}; diff --git a/kernel/fiasco/src/drivers/ppc32/processor-ppc32.cpp b/kernel/fiasco/src/drivers/ppc32/processor-ppc32.cpp new file mode 100644 index 00000000..1b04dbf8 --- /dev/null +++ b/kernel/fiasco/src/drivers/ppc32/processor-ppc32.cpp @@ -0,0 +1,118 @@ +#include "types.h" +#include "msr.h" + +IMPLEMENTATION [ppc32]: + +EXTENSION class Proc +{ +public: + //disable power savings mode + static Mword wake(Mword); + static unsigned cpu_id(); +}; + +/// Unblock external inetrrupts +IMPLEMENT static inline +void Proc::sti() +{ + Msr::set_msr_bit(Msr::Msr_ee); +} + +/// Block external interrupts +IMPLEMENT static inline +void Proc::cli() +{ + Msr::clear_msr_bit(Msr::Msr_ee); +} + +/// Are external interrupts enabled ? +IMPLEMENT static inline +Proc::Status Proc::interrupts() +{ + return (Status)Msr::read_msr() & Msr::Msr_ee; +} + +/// Block external interrupts and save the old state +IMPLEMENT static inline +Proc::Status Proc::cli_save() +{ + Status ret = Msr::read_msr(); + Proc::cli(); + return ret; +} + +/// Conditionally unblock external interrupts +IMPLEMENT static inline +void Proc::sti_restore(Status status) +{ + asm volatile ( " mtmsr %[status] \n" + : + : [status] "r" (status) + ); +} + +IMPLEMENT static inline +void Proc::pause() +{ +} + +IMPLEMENT static inline +void Proc::halt() +{ + //enable interrupt and power saving mode in msr and wait for timer + //exception + Msr::set_msr_bit(Msr::Msr_ee | Msr::Msr_pow); + while(Msr::read_msr() & Msr::Msr_pow) + ; +} + +IMPLEMENT static inline +Mword Proc::wake(Mword srr1) +{ + return srr1 & ~(Msr::Msr_ee | Msr::Msr_pow); +} + +IMPLEMENT static inline +void Proc::irq_chance() +{ + asm volatile ("nop; nop;" : : : "memory"); +} + +IMPLEMENT static inline +void Proc::stack_pointer(Mword sp) +{ + asm volatile ( " mr %%r1, %0 \n" + : : "r" (sp) + ); +} + +IMPLEMENT static inline +Mword Proc::stack_pointer() +{ + Mword sp; + asm volatile ( " mr %0, %%r1 \n" + : "=r" (sp) + ); + return sp; +} + +IMPLEMENT static inline +Mword Proc::program_counter() +{ + Mword pc; + asm volatile ( " mflr %%r5 \n" + " bl 1f \n" + " 1: \n" + " mflr %0 \n" + " mtlr %%r5 \n" + : "=r" (pc) : : "r5"); + return pc; +} + +IMPLEMENTATION [ppc32 && !mpcore]: + +IMPLEMENT static inline +unsigned Proc::cpu_id() +{ return 0; } + + diff --git a/kernel/fiasco/src/drivers/ppc32/reset-ppc32.cpp b/kernel/fiasco/src/drivers/ppc32/reset-ppc32.cpp new file mode 100644 index 00000000..443963e1 --- /dev/null +++ b/kernel/fiasco/src/drivers/ppc32/reset-ppc32.cpp @@ -0,0 +1,38 @@ +IMPLEMENTATION [ppc32 && mpc52xx]: + +#include "io.h" +#include "boot_info.h" + +enum Reg_offsets +{ + Gp0_mode = 0x600, + Gp0_count = 0x604 +}; + +/** + * Porgram Gerneral purpose timer as watchdog, thus causing a system reset + */ +void __attribute__ ((noreturn)) +platform_reset(void) +{ + + Address mbar = Boot_info::mbar(); + Io::write(0, mbar + Gp0_mode); + Io::write(0xff, mbar + Gp0_count); //timeout + + //0x9004 (0x8000 enable watchdog | 0x1000 CE bit - start counter | + //0x4 CE bit controls timer counter + Io::write(0x9004, mbar + Gp0_mode); + + //in case we return + for(;;) ; +} + +IMPLEMENTATION [ppc32 && !mpc52xx]: + +void __attribute__ ((noreturn)) +platform_reset(void) +{ + for(;;); +} + diff --git a/kernel/fiasco/src/drivers/ppc32/uart-mpc52xx.cpp b/kernel/fiasco/src/drivers/ppc32/uart-mpc52xx.cpp new file mode 100644 index 00000000..c0f25bd7 --- /dev/null +++ b/kernel/fiasco/src/drivers/ppc32/uart-mpc52xx.cpp @@ -0,0 +1,32 @@ +IMPLEMENTATION[uart_mpc52xx && libuart && debug]: + +#include "uart_mpc52xx.h" +#include "pic.h" +#include + +IMPLEMENT Address Uart::base() const { return Boot_info::uart_base(); } + +IMPLEMENT int Uart::irq() const +{ return Pic::get_irq_num((char*)"serial", (char*)"serial"); } + +IMPLEMENT L4::Uart *Uart::uart() +{ + static L4::Uart_mpc52xx uart; + return &uart; +} + +IMPLEMENTATION[uart_mpc52xx && libuart && !debug]: + +#include "uart_mpc52xx.h" +#include + +IMPLEMENT Address Uart::base() const { return Boot_info::uart_base(); } + +IMPLEMENT int Uart::irq() const +{ return -1; } + +IMPLEMENT L4::Uart *Uart::uart() +{ + static L4::Uart_mpc52xx uart; + return &uart; +} diff --git a/kernel/fiasco/src/drivers/ppc32/uart-of.cpp b/kernel/fiasco/src/drivers/ppc32/uart-of.cpp new file mode 100644 index 00000000..faff5226 --- /dev/null +++ b/kernel/fiasco/src/drivers/ppc32/uart-of.cpp @@ -0,0 +1,10 @@ +IMPLEMENTATION[uart_of && libuart]: +#include "ppc32/uart_of.h" +#include "boot_info.h" + +IMPLEMENT L4::Uart *Uart::uart() +{ + static L4::Uart_of uart((unsigned long)Boot_info::get_prom()); + return &uart; +} + diff --git a/kernel/fiasco/src/drivers/processor.cpp b/kernel/fiasco/src/drivers/processor.cpp new file mode 100644 index 00000000..91618fa1 --- /dev/null +++ b/kernel/fiasco/src/drivers/processor.cpp @@ -0,0 +1,47 @@ +INTERFACE: + +#include "types.h" + +/// Central processor specific methods. +class Proc +{ +public: + + typedef Mword Status; + + /// Block external interrupts + static void cli(); + + /// Unblock external inetrrupts + static void sti(); + + /// Are external interrupts enabled ? + static Status interrupts(); + + /// Block external interrupts and save the old state + static Status cli_save(); + + /// Conditionally unblock external interrupts + static void sti_restore( Status ); + + static void pause(); + + static void halt(); + + static void irq_chance(); + + static void stack_pointer(Mword sp); + + static Mword stack_pointer(); + + static Mword program_counter(); + + static inline + void preemption_point() + { + sti(); + irq_chance(); + cli(); + } + +}; diff --git a/kernel/fiasco/src/drivers/sparc/io-sparc.cpp b/kernel/fiasco/src/drivers/sparc/io-sparc.cpp new file mode 100644 index 00000000..4eb9700d --- /dev/null +++ b/kernel/fiasco/src/drivers/sparc/io-sparc.cpp @@ -0,0 +1,84 @@ +INTERFACE [sparc]: + +EXTENSION class Io +{ +public: + /** + * Read but do not disable data cache + */ + template< typename T > + static T read_dirty(Address address); + + /** + * Write but do not disable data cache + */ + template< typename T> + static void write_dirty(T value, Address address); +}; + + +IMPLEMENTATION [sparc]: + +#include "mem_unit.h" + +IMPLEMENT inline NEEDS["mem_unit.h"] +template< typename T > +T Io::read_dirty(Address address) +{ + volatile T ret; + Mem_unit::sync(); + ret = *(volatile T *)address; + Mem_unit::isync(); + return ret; +} + +IMPLEMENT inline NEEDS["mem_unit.h"] +template< typename T> +void Io::write_dirty(T value, Address address) +{ + Mem_unit::sync(); + *(volatile T *)address = value; +} + +//------------------------------------------------------------------------------ +/** + * No port support + */ +IMPLEMENT inline +void Io::iodelay() +{} + +IMPLEMENT inline +Unsigned8 Io::in8 ( unsigned long /* port */ ) +{ + return 0; +} + +IMPLEMENT inline +Unsigned16 Io::in16( unsigned long /* port */ ) +{ + return 0; +} + +IMPLEMENT inline +Unsigned32 Io::in32( unsigned long /* port */ ) +{ + return 0; +} + +IMPLEMENT inline +void Io::out8 ( Unsigned8 /* val */, unsigned long /* port */ ) +{ +} + +IMPLEMENT inline +void Io::out16( Unsigned16 /* val */, unsigned long /* port */ ) +{ +} + +IMPLEMENT inline +void Io::out32( Unsigned32 /* val */, unsigned long /* port */ ) +{ +} + + diff --git a/kernel/fiasco/src/drivers/sparc/kernel_uart-sparc.cpp b/kernel/fiasco/src/drivers/sparc/kernel_uart-sparc.cpp new file mode 100644 index 00000000..7d46c887 --- /dev/null +++ b/kernel/fiasco/src/drivers/sparc/kernel_uart-sparc.cpp @@ -0,0 +1,11 @@ +INTERFACE: + +EXTENSION class Kernel_uart { enum { Bsp_init_mode = Init_before_mmu }; }; + +IMPLEMENTATION [sparc && serial]: + +IMPLEMENT +bool Kernel_uart::startup(unsigned, int) +{ + return Uart::startup(); +} diff --git a/kernel/fiasco/src/drivers/sparc/keycodes-arch.h b/kernel/fiasco/src/drivers/sparc/keycodes-arch.h new file mode 100644 index 00000000..dc8f6158 --- /dev/null +++ b/kernel/fiasco/src/drivers/sparc/keycodes-arch.h @@ -0,0 +1,15 @@ +/* -*- c++ -*- */ + +#ifndef KEYCODES_ARCH_H__ +#define KEYCODES_ARCH_H__ + +enum +{ + KEY_BACKSPACE = 0x08, + KEY_TAB = 0x09, + KEY_ESC = 0x1b, + KEY_RETURN = 0x0d, +}; + +#endif // KEYCODES_ARCH_H__ + diff --git a/kernel/fiasco/src/drivers/sparc/mem-sparc.cpp b/kernel/fiasco/src/drivers/sparc/mem-sparc.cpp new file mode 100644 index 00000000..cf2e3a18 --- /dev/null +++ b/kernel/fiasco/src/drivers/sparc/mem-sparc.cpp @@ -0,0 +1,25 @@ +//----------------------------------------------------------------------------- +IMPLEMENTATION [sparc]: + +IMPLEMENT static inline +void +Mem::memset_mwords (void *dst, const unsigned long value, unsigned long nr_of_mwords) +{ + unsigned long *d = (unsigned long *)dst; + for (; nr_of_mwords--; d++) + *d = value; +} + +IMPLEMENT static inline +void +Mem::memcpy_mwords (void *dst, void const *src, unsigned long nr_of_mwords) +{ + __builtin_memcpy(dst, src, nr_of_mwords * sizeof(unsigned long)); +} + +IMPLEMENT static inline +void +Mem::memcpy_bytes(void *dst, void const *src, unsigned long nr_of_bytes) +{ + __builtin_memcpy(dst, src, nr_of_bytes); +} diff --git a/kernel/fiasco/src/drivers/sparc/processor-sparc.cpp b/kernel/fiasco/src/drivers/sparc/processor-sparc.cpp new file mode 100644 index 00000000..001d0c8f --- /dev/null +++ b/kernel/fiasco/src/drivers/sparc/processor-sparc.cpp @@ -0,0 +1,141 @@ +#include "types.h" +#include "psr.h" +#include "processor.h" + +IMPLEMENTATION [sparc]: + +EXTENSION class Proc +{ +public: + //disable power savings mode + static Mword wake(Mword); + static unsigned cpu_id(); +}; + +/// Unblock external interrupts +IMPLEMENT static inline +void Proc::sti() +{ + unsigned p = Psr::read(); + p &= ~(0xF << Psr::Interrupt_lvl); + Psr::write(p); +} + +/// Block external interrupts +IMPLEMENT static inline +void Proc::cli() +{ + unsigned p = Psr::read(); + p |= (0xF << Psr::Interrupt_lvl); + Psr::write(p); +} + +/// Are external interrupts enabled ? +IMPLEMENT static inline +Proc::Status Proc::interrupts() +{ + return Psr::read() & (0xF << Psr::Interrupt_lvl); +} + +/// Block external interrupts and save the old state +IMPLEMENT static inline +Proc::Status Proc::cli_save() +{ + Status ret = Psr::read(); + Proc::cli(); + return ret; +} + +/// Conditionally unblock external interrupts +IMPLEMENT static inline +void Proc::sti_restore(Status status) +{ + (void)status; + Psr::write(status); +} + +IMPLEMENT static inline +void Proc::pause() +{ + // XXX +} + +IMPLEMENT static inline +void Proc::halt() +{ + // XXX + asm volatile ("ta 0\n"); +} + +IMPLEMENT static inline +Mword Proc::wake(Mword srr1) +{ + (void)srr1; + return 0; // XXX +} + +IMPLEMENT static inline +void Proc::irq_chance() +{ + // XXX? + asm volatile ("nop; nop;" : : : "memory"); +} + +IMPLEMENT static inline +void Proc::stack_pointer(Mword sp) +{ + (void)sp; + asm volatile ("mov %0, %%sp\n" : : "r"(sp)); +} + +IMPLEMENT static inline +Mword Proc::stack_pointer() +{ + Mword sp = 0; + asm volatile ("mov %%sp, %0\n" : "=r" (sp)); + return sp; +} + +IMPLEMENT static inline +Mword Proc::program_counter() +{ + Mword pc = 0; + asm volatile ("call 1\n\t" + "nop\n\t" // delay instruction + "1: mov %%o7, %0\n\t" + : "=r" (pc) : : "o7"); + return pc; +} + +PUBLIC static inline +template +Mword Proc::read_alternative(Mword reg) +{ + Mword ret; + asm volatile("lda [%1] %2, %0" + : "=r" (ret) + : "r" (reg), + "i" (ASI)); + return ret; + +} + +PUBLIC static inline +template +void Proc::write_alternative(Mword reg, Mword value) +{ + asm volatile ("sta %0, [%1] %2\n\t" + : + : "r"(value), + "r"(reg), + "i"(ASI)); +} + + +IMPLEMENTATION [sparc && !mpcore]: + +IMPLEMENT static inline +unsigned Proc::cpu_id() +{ return 0; } + + diff --git a/kernel/fiasco/src/drivers/sparc/reset-sparc.cpp b/kernel/fiasco/src/drivers/sparc/reset-sparc.cpp new file mode 100644 index 00000000..b18fa05f --- /dev/null +++ b/kernel/fiasco/src/drivers/sparc/reset-sparc.cpp @@ -0,0 +1,38 @@ +IMPLEMENTATION [sparc && leon3]: + +#include "io.h" +#include "boot_info.h" + +enum Reg_offsets +{ + Gp0_mode = 0x600, + Gp0_count = 0x604 +}; + +/** + * Porgram Gerneral purpose timer as watchdog, thus causing a system reset + */ +void __attribute__ ((noreturn)) +platform_reset(void) +{ + + Address mbar = Boot_info::mbar(); + Io::write(0, mbar + Gp0_mode); + Io::write(0xff, mbar + Gp0_count); //timeout + + //0x9004 (0x8000 enable watchdog | 0x1000 CE bit - start counter | + //0x4 CE bit controls timer counter + Io::write(0x9004, mbar + Gp0_mode); + + //in case we return + for(;;) ; +} + +IMPLEMENTATION [sparc && !leon3]: + +void __attribute__ ((noreturn)) +platform_reset(void) +{ + for(;;); +} + diff --git a/kernel/fiasco/src/drivers/sparc/sparc_types.cpp b/kernel/fiasco/src/drivers/sparc/sparc_types.cpp new file mode 100644 index 00000000..fb2719b9 --- /dev/null +++ b/kernel/fiasco/src/drivers/sparc/sparc_types.cpp @@ -0,0 +1,2 @@ +INTERFACE [sparc]: + diff --git a/kernel/fiasco/src/drivers/sparc/uart-leon3.cpp b/kernel/fiasco/src/drivers/sparc/uart-leon3.cpp new file mode 100644 index 00000000..815f0f09 --- /dev/null +++ b/kernel/fiasco/src/drivers/sparc/uart-leon3.cpp @@ -0,0 +1,14 @@ +IMPLEMENTATION[uart_leon3 && libuart]: + +#include "uart_leon3.h" +#include "mem_layout.h" + +IMPLEMENT Address Uart::base() const { return Mem_layout::Uart_base; } + +IMPLEMENT int Uart::irq() const { return 0; } + +IMPLEMENT L4::Uart *Uart::uart() +{ + static L4::Uart_leon3 uart; + return &uart; +} diff --git a/kernel/fiasco/src/drivers/uart-16550.cpp b/kernel/fiasco/src/drivers/uart-16550.cpp new file mode 100644 index 00000000..86e85bca --- /dev/null +++ b/kernel/fiasco/src/drivers/uart-16550.cpp @@ -0,0 +1,335 @@ +INTERFACE [16550-{ia32,amd64}]: + +EXTENSION class Uart +{ +public: + enum { + Base_rate = 115200, + Base_ier_bits = 0, + + Access_shift = 0, + }; +}; + + +INTERFACE[16550]: + +#include "types.h" + +/** + * 16550 implementation of the UART interface. + */ +EXTENSION class Uart +{ +public: + + /** + * Start this serial port for I/O. + * @param port the I/O port base address. + * @param irq the IRQ assigned to this port, -1 if none. + */ + bool startup(Address port, int irq); + + enum { + PAR_NONE = 0x00, + PAR_EVEN = 0x18, + PAR_ODD = 0x08, + DAT_5 = 0x00, + DAT_6 = 0x01, + DAT_7 = 0x02, + DAT_8 = 0x03, + STOP_1 = 0x00, + STOP_2 = 0x04, + + MODE_8N1 = PAR_NONE | DAT_8 | STOP_1, + MODE_7E1 = PAR_EVEN | DAT_7 | STOP_1, + + // these two values are to leave either mode + // or baud rate unchanged on a call to change_mode + MODE_NC = 0x1000000, + BAUD_NC = 0x1000000, + }; + +private: + + enum Registers { + TRB = 0, // Transmit/Receive Buffer (read/write) + BRD_LOW = 0, // Baud Rate Divisor LSB if bit 7 of LCR is set (read/write) + IER = 1, // Interrupt Enable Register (read/write) + BRD_HIGH = 1, // Baud Rate Divisor MSB if bit 7 of LCR is set (read/write) + IIR = 2, // Interrupt Identification Register (read only) + FCR = 2, // 16550 FIFO Control Register (write only) + LCR = 3, // Line Control Register (read/write) + MCR = 4, // Modem Control Register (read/write) + LSR = 5, // Line Status Register (read only) + MSR = 6, // Modem Status Register (read only) + SPR = 7, // Scratch Pad Register (read/write) + }; + + Address port; + int _irq; +}; + + +IMPLEMENTATION[16550]: + +#include "io.h" +#include "processor.h" + + +IMPLEMENT +Uart::Uart() : port(~0U), _irq(-1) +{} + +IMPLEMENT +Uart::~Uart() +{} + + +PRIVATE inline NEEDS["io.h"] +void Uart::outb( Unsigned8 b, Registers reg ) +{ + Io::out8(b, port + (reg << Access_shift)); +} + +PRIVATE inline NEEDS["io.h"] +Unsigned8 Uart::inb( Registers reg ) const +{ + return Io::in8(port + (reg << Access_shift)); +} + + +PRIVATE inline NEEDS[Uart::outb] +void Uart::mcr(Unsigned8 b) +{ + outb(b, MCR); +} + +PRIVATE inline NEEDS[Uart::inb] +Unsigned8 Uart::mcr() const +{ + return inb(MCR); +} + +PRIVATE inline NEEDS[Uart::outb] +void Uart::fcr(Unsigned8 b) +{ + outb(b, FCR); +} + +PRIVATE inline NEEDS[Uart::outb] +void Uart::lcr(Unsigned8 b) +{ + outb(b, LCR); +} + +PRIVATE inline NEEDS[Uart::inb] +Unsigned8 Uart::lcr() const +{ + return inb(LCR); +} + +PRIVATE inline NEEDS[Uart::outb] +void Uart::ier(Unsigned8 b) +{ + outb(b, IER); +} + +PRIVATE inline NEEDS[Uart::inb] +Unsigned8 Uart::ier() const +{ + return inb(IER); +} + +PRIVATE inline NEEDS[Uart::inb] +Unsigned8 Uart::iir() const +{ + return inb(IIR); +} + +PRIVATE inline NEEDS[Uart::inb] +Unsigned8 Uart::msr() const +{ + return inb(MSR); +} + +PRIVATE inline NEEDS[Uart::inb] +Unsigned8 Uart::lsr() const +{ + return inb(LSR); +} + +PRIVATE inline NEEDS[Uart::outb] +void Uart::trb(Unsigned8 b) +{ + outb(b, TRB); +} + +PRIVATE inline NEEDS[Uart::inb] +Unsigned8 Uart::trb() const +{ + return inb(TRB); +} + +PRIVATE +bool Uart::valid() +{ + Unsigned8 scratch, scratch2, scratch3; + + scratch = ier(); + ier(0x00); + + Io::iodelay(); + + scratch2 = ier(); + ier(0x0f); + Io::iodelay(); + + scratch3 = ier(); + ier(scratch); + + return (scratch2 == 0x00 && scratch3 == 0x0f); +} + +IMPLEMENT +bool Uart::startup(Address _port, int __irq) +{ + port = _port; + _irq = __irq; + + Proc::Status o = Proc::cli_save(); + + if (!valid()) + { + Proc::sti_restore(o); + fail(); + return false; + } + + ier(Base_ier_bits);/* disable all rs-232 interrupts */ + mcr(0x0b); /* out2, rts, and dtr enabled */ + fcr(1); /* enable fifo */ + fcr(0x07); /* clear rcv xmit fifo */ + fcr(1); /* enable fifo */ + lcr(0); /* clear line control register */ + + /* clearall interrupts */ + /*read*/ msr(); /* IRQID 0*/ + /*read*/ iir(); /* IRQID 1*/ + /*read*/ trb(); /* IRQID 2*/ + /*read*/ lsr(); /* IRQID 3*/ + + while(lsr() & 1/*DATA READY*/) /*read*/ trb(); + Proc::sti_restore(o); + return true; +} + + +IMPLEMENT +void Uart::shutdown() +{ + Proc::Status o = Proc::cli_save(); + mcr(0x06); + fcr(0); + lcr(0); + ier(0); + Proc::sti_restore(o); +} + +IMPLEMENT +bool Uart::change_mode(TransferMode m, BaudRate r) +{ + Proc::Status o = Proc::cli_save(); + Unsigned8 old_lcr = lcr(); + if(r != BAUD_NC) { + lcr(old_lcr | 0x80/*DLAB*/); + Unsigned16 divisor = Base_rate/r; + trb( divisor & 0x0ff ); /* BRD_LOW */ + ier( (divisor >> 8) & 0x0ff ); /* BRD_HIGH */ + lcr(old_lcr); + } + if( m != MODE_NC ) { + lcr( m & 0x07f ); + } + + Proc::sti_restore(o); + return true; +} + +IMPLEMENT +Uart::TransferMode Uart::get_mode() +{ + return lcr() & 0x7f; +} + +IMPLEMENT +int Uart::write(char const *s, size_t count) +{ + /* disable uart irqs */ + Unsigned8 old_ier; + old_ier = ier(); + ier(old_ier & ~0x0f); + + /* transmission */ + for (unsigned i = 0; i < count; i++) + { + while (!(lsr() & 0x20 /* THRE */)) + ; + trb(s[i]); + } + + /* wait till everything is transmitted */ + while (!(lsr() & 0x40 /* TSRE */)) + ; + + ier(old_ier); + return count; +} + +IMPLEMENT +int Uart::getchar(bool blocking) +{ + if (!blocking && !(lsr() & 1 /* DATA READY */)) + return -1; + + Unsigned8 old_ier, ch; + old_ier = ier(); + ier(old_ier & ~0x0f); + while (!(lsr() & 1 /* DATA READY */)) + ; + ch = trb(); + ier(old_ier); + return ch; +} + +IMPLEMENT +int Uart::char_avail() const +{ + if (lsr() & 1 /* DATA READY */) + return 1; + + return 0; +} + + +IMPLEMENT inline +int Uart::irq() const +{ + return _irq; +} + +IMPLEMENT inline NEEDS[Uart::ier] +void Uart::disable_rcv_irq() +{ + ier(ier() & ~1); +} + + +// ------------------------------------------------------------------------ +IMPLEMENTATION [16550-{ia32,amd64}]: + +IMPLEMENT inline NEEDS[Uart::ier] +void Uart::enable_rcv_irq() +{ + ier(ier() | 1); +} diff --git a/kernel/fiasco/src/drivers/uart.cpp b/kernel/fiasco/src/drivers/uart.cpp new file mode 100644 index 00000000..aa064f30 --- /dev/null +++ b/kernel/fiasco/src/drivers/uart.cpp @@ -0,0 +1,180 @@ +INTERFACE: + +#include "console.h" + +/** + * Platform independent UART stub. + */ +class Uart : public Console +{ +public: + /** + * Type UART transfer mode (Bits, Stopbits etc.). + */ + typedef unsigned TransferMode; + + /** + * Type for baud rate. + */ + typedef unsigned BaudRate; + + /* These constants must be defined in the + arch part of the uart. To define them there + has the advantage of most efficent definition + for the hardware. + + static unsigned const PAR_NONE = xxx; + static unsigned const PAR_EVEN = xxx; + static unsigned const PAR_ODD = xxx; + static unsigned const DAT_5 = xxx; + static unsigned const DAT_6 = xxx; + static unsigned const DAT_7 = xxx; + static unsigned const DAT_8 = xxx; + static unsigned const STOP_1 = xxx; + static unsigned const STOP_2 = xxx; + + static unsigned const MODE_8N1 = PAR_NONE | DAT_8 | STOP_1; + static unsigned const MODE_7E1 = PAR_EVEN | DAT_7 | STOP_1; + + // these two values are to leave either mode + // or baud rate unchanged on a call to change_mode + static unsigned const MODE_NC = xxx; + static unsigned const BAUD_NC = xxx; + + */ + + +public: + /* Interface definition - implemented in the arch part */ + /// ctor + Uart(); + + /// dtor + ~Uart(); + + /** + * (abstract) Shutdown the serial port. + */ + void shutdown(); + + /** + * (abstract) Get the IRQ assigned to the port. + */ + int irq() const; + + Address base() const; + + /** + * (abstract) Enable rcv IRQ in UART. + */ + void enable_rcv_irq(); + + /** + * (abstract) Disable rcv IRQ in UART. + */ + void disable_rcv_irq(); + + /** + * (abstract) Change transfer mode or speed. + * @param m the new mode for the transfer, or MODE_NC for no mode change. + * @param r the new baud rate, or BAUD_NC, for no speed change. + */ + bool change_mode(TransferMode m, BaudRate r); + + /** + * (abstract) Get the current transfer mode. + */ + TransferMode get_mode(); + + /** + * (abstract) Write str. + */ + int write( char const *str, size_t len ); + + /** + * (abstract) Read a character. + */ + int getchar( bool blocking = true ); + + /** + * (abstract) Is there anything to read? + */ + int char_avail() const; + + Mword get_attributes() const; +}; + +IMPLEMENTATION: + +IMPLEMENT +Mword +Uart::get_attributes() const +{ + return UART | IN | OUT; +} + +//--------------------------------------------------------------------------- +INTERFACE [libuart]: + +#include "uart_base.h" + +EXTENSION class Uart +{ +public: + enum + { + MODE_8N1 = 1, + }; +protected: + static L4::Uart *uart(); +}; + + +//--------------------------------------------------------------------------- +IMPLEMENTATION [libuart]: + + +IMPLEMENT inline Uart::~Uart() +{ } + +IMPLEMENT inline void Uart::shutdown() +{ + uart()->shutdown(); +} + +IMPLEMENT inline bool Uart::change_mode(TransferMode m, BaudRate baud) +{ + return uart()->change_mode(m, baud); +} + +IMPLEMENT inline +int Uart::write(const char *s, __SIZE_TYPE__ count) +{ + return uart()->write(s, count); +} + +IMPLEMENT inline +int Uart::getchar(bool blocking) +{ + return uart()->get_char(blocking); +} + + +IMPLEMENT inline +int Uart::char_avail() const +{ + return uart()->char_avail(); +} + +IMPLEMENT +void Uart::enable_rcv_irq() +{ + uart()->enable_rx_irq(true); +} + +IMPLEMENT +void Uart::disable_rcv_irq() +{ + uart()->enable_rx_irq(false); +} + diff --git a/kernel/fiasco/src/drivers/ux/keycodes-arch.h b/kernel/fiasco/src/drivers/ux/keycodes-arch.h new file mode 100644 index 00000000..4e8fe8c8 --- /dev/null +++ b/kernel/fiasco/src/drivers/ux/keycodes-arch.h @@ -0,0 +1,15 @@ +/* -*- c++ -*- */ + +#ifndef KEYCODES_ARCH_H__ +#define KEYCODES_ARCH_H__ + +enum +{ + KEY_BACKSPACE = 0x7F, + KEY_TAB = 0x09, + KEY_ESC = 0x1b, + KEY_RETURN = 0x0a, +}; + +#endif // KEYCODES_ARCH_H__ + diff --git a/kernel/fiasco/src/drivers/ux/processor-ux.cpp b/kernel/fiasco/src/drivers/ux/processor-ux.cpp new file mode 100644 index 00000000..152cc4ed --- /dev/null +++ b/kernel/fiasco/src/drivers/ux/processor-ux.cpp @@ -0,0 +1,104 @@ +INTERFACE [ux]: + +#include "types.h" + +EXTENSION class Proc +{ + static Status volatile virtual_processor_state; +}; + +IMPLEMENTATION [ux]: + +#include + +#include "types.h" +#include "std_macros.h" + + +IMPLEMENT static inline +void Proc::stack_pointer(Mword sp) +{ + asm volatile ( "movl %0, %%esp \n" : : "r"(sp) ); +} + +IMPLEMENT static inline +Mword Proc::stack_pointer() +{ + Mword res; + asm volatile ( "movl %%esp, %0 \n" : "=r" (res) ); + return res; +} + +IMPLEMENT static inline +Mword Proc::program_counter () +{ + Mword pc; + asm volatile ("call 1f ; 1: pop %0" : "=rm"(pc)); + return pc; +} + +PUBLIC static inline +Proc::Status Proc::processor_state() +{ + return virtual_processor_state; +} + +PUBLIC static inline +void Proc::ux_set_virtual_processor_state(Status s) +{ + virtual_processor_state = s; +} + +IMPLEMENT static inline +void Proc::pause() +{ + asm volatile (" .byte 0xf3, 0x90 #pause \n" ); +} + +IMPLEMENT static inline +void Proc::halt() +{ + static struct timespec idle; + idle.tv_sec = 10; + idle.tv_nsec = 0; + nanosleep (&idle, NULL); +} + +IMPLEMENT static inline +void Proc::cli() +{ + asm volatile ("cli" : : : "memory"); +} + +IMPLEMENT static inline +void Proc::sti() +{ + asm volatile ("sti" : : : "memory"); +} + +IMPLEMENT static inline +Proc::Status Proc::cli_save() +{ + Status ret = virtual_processor_state; + cli(); + return ret; +} + +IMPLEMENT static inline +void Proc::sti_restore(Status st) +{ + if (st & 0x200) + Proc::sti(); +} + +IMPLEMENT static inline +Proc::Status Proc::interrupts() +{ + return virtual_processor_state & 0x0200; +} + +IMPLEMENT static inline NEEDS[] +void Proc::irq_chance() +{ + asm volatile ("nop; nop;" : : : "memory"); +} diff --git a/kernel/fiasco/src/drivers/ux/ux_con.c b/kernel/fiasco/src/drivers/ux/ux_con.c new file mode 100644 index 00000000..72691178 --- /dev/null +++ b/kernel/fiasco/src/drivers/ux/ux_con.c @@ -0,0 +1,536 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "SDL.h" + + +#define PROGNAME "ux_con" + +#define DFL_MOUSE_VISIBLE 1 +#define DFL_REFRESH_INTERVAL 100 + +#define WM_WINDOW_TITLE "Fiasco-UX graphical console" +#define WM_ICON_TITLE "F-UX con" + +#define LOGGING 0 +#define LOGGING_FILE "/tmp/ux_con_key.log" + +/* this is from libinput.h -- size == 16 byte */ +struct l4input +{ + long long time; /* used as a marker here */ + unsigned short type; + unsigned short code; + unsigned int value; + unsigned long stream_id; +}; + +enum { + SUPERPAGESIZE = 1 << 22, +}; + +/* needs to be the same as in libinput-ux! */ +enum { + INPUTMEM_SIZE = 1 << 12, + NR_INPUT_OBJS = INPUTMEM_SIZE / sizeof(struct l4input), +}; + +enum { + EV_SYN = 0, + EV_KEY = 0x01, + EV_REL = 0x02, + + SYN_REPORT = 0, + + BTN_LEFT = 0x110, + BTN_RIGHT = 0x111, + BTN_MIDDLE = 0x112, + + REL_X = 0, + REL_Y = 1, +}; + +int physmem_fd; +unsigned long physmem_fb_start; +int width, height, depth; +size_t physmem_size; +size_t fb_size; +int depth_bytes; +int refresh_rate; +int mouse_visible; +struct l4input *input_mem; +int input_queue_pos; +int signal_mode, sig_redraw_pending; + +struct key_mapping { + unsigned long sdlkey; + unsigned long l4ev; +}; + +/* + * This table translates from a german SDL map to a normal keyboard. + * Other keymaps on the host keyboard should give weird behavior + * (patches welcome). + */ +static struct key_mapping key_map[] = { + { SDLK_ESCAPE, 1 }, + { SDLK_1, 2 }, + { SDLK_2, 3 }, + { SDLK_3, 4 }, + { SDLK_4, 5 }, + { SDLK_5, 6 }, + { SDLK_6, 7 }, + { SDLK_7, 8 }, + { SDLK_8, 9 }, + { SDLK_9, 10 }, + { SDLK_0, 11 }, + { SDLK_MINUS, 53 }, + { SDLK_EQUALS, 13 }, + { SDLK_WORLD_20, 13 }, + { SDLK_BACKSPACE, 14 }, + { SDLK_TAB, 15 }, + { SDLK_q, 16 }, + { SDLK_w, 17 }, + { SDLK_e, 18 }, + { SDLK_r, 19 }, + { SDLK_t, 20 }, + { SDLK_z, 21 }, + { SDLK_u, 22 }, + { SDLK_i, 23 }, + { SDLK_o, 24 }, + { SDLK_p, 25 }, + { SDLK_LEFTBRACKET, 26 }, + { SDLK_RIGHTBRACKET, 27 }, + { SDLK_RETURN, 28 }, + { SDLK_LCTRL, 29 }, + { SDLK_a, 30 }, + { SDLK_s, 31 }, + { SDLK_d, 32 }, + { SDLK_f, 33 }, + { SDLK_g, 34 }, + { SDLK_h, 35 }, + { SDLK_j, 36 }, + { SDLK_k, 37 }, + { SDLK_l, 38 }, + { SDLK_SEMICOLON, 39 }, + { SDLK_QUOTE, 13 }, + { SDLK_BACKQUOTE, 41 }, + { SDLK_LSHIFT, 42 }, + { SDLK_BACKSLASH, 43 }, + { SDLK_y, 44 }, + { SDLK_x, 45 }, + { SDLK_c, 46 }, + { SDLK_v, 47 }, + { SDLK_b, 48 }, + { SDLK_n, 49 }, + { SDLK_m, 50 }, + { SDLK_COMMA, 51 }, + { SDLK_PERIOD, 52 }, + { SDLK_SLASH, 53 }, + { SDLK_RSHIFT, 54 }, + { SDLK_KP_MULTIPLY, 55 }, + { SDLK_LALT, 56 }, + { SDLK_LMETA, 56 }, + { SDLK_SPACE, 57 }, + { SDLK_CAPSLOCK, 58 }, + { SDLK_F1, 59 }, + { SDLK_F2, 60 }, + { SDLK_F3, 61 }, + { SDLK_F4, 62 }, + { SDLK_F5, 63 }, + { SDLK_F6, 64 }, + { SDLK_F7, 65 }, + { SDLK_F8, 66 }, + { SDLK_F9, 67 }, + { SDLK_F10, 68 }, + { SDLK_NUMLOCK, 69 }, + { SDLK_SCROLLOCK, 70 }, + { SDLK_KP7, 71 }, /* Keypad 7 */ + { SDLK_KP8, 72 }, /* Keypad 8 */ + { SDLK_KP9, 73 }, /* Keypad 9 */ + { SDLK_KP_MINUS, 74 }, /* Keypad minus */ + { SDLK_KP4, 75 }, /* Keypad 4 */ + { SDLK_KP5, 76 }, /* Keypad 5 */ + { SDLK_KP6, 77 }, /* Keypad 6 */ + { SDLK_KP_PLUS, 78 }, /* Keypad plus */ + { SDLK_KP1, 79 }, /* Keypad 1 */ + { SDLK_KP2, 80 }, /* Keypad 2 */ + { SDLK_KP3, 81 }, /* Keypad 3 */ + { SDLK_KP0, 82 }, /* Keypad 0 */ + { SDLK_KP_PERIOD, 83 }, /* Keypad dot */ + + { SDLK_F11, 87 }, + { SDLK_F12, 88 }, + { SDLK_F13, 85 }, + { SDLK_F14, 89 }, + { SDLK_F15, 90 }, + + { SDLK_KP_ENTER, 96 }, /* Keypad enter */ + { SDLK_RCTRL, 97 }, + { SDLK_KP_DIVIDE, 98 }, /* Keypad slash */ + { SDLK_PRINT, 99 }, + { SDLK_RALT, 100 }, + { SDLK_RMETA, 100 }, + { SDLK_MODE, 100 }, /* Alt Gr */ + + { SDLK_HOME, 102 }, + { SDLK_UP, 103 }, + { SDLK_PAGEUP, 104 }, + { SDLK_LEFT, 105 }, + { SDLK_RIGHT, 106 }, + { SDLK_END, 107 }, + { SDLK_DOWN, 108 }, + { SDLK_PAGEDOWN, 109 }, + { SDLK_INSERT, 110 }, + { SDLK_DELETE, 111 }, + + { SDLK_KP_EQUALS, 117 }, /* Keypad equals */ + + { SDLK_PAUSE, 119 }, + + { SDLK_LSUPER, 125 }, /* Left "Penguin" key */ + { SDLK_RSUPER, 126 }, /* Right "Penguin" key */ + { SDLK_MENU, 127 }, + + { 223, 12 }, /* sz */ + { 252, 26 }, /* ue */ + { 43, 27 }, /* + -> ] */ + { 246, 39 }, /* oe -> ; */ + { 228, 40 }, /* ae -> " */ + { 94, 41 }, /* ^ ° -> ` */ + { 35, 43 }, /* # ' -> backslash */ + { 60, 86 }, /* < > | */ + + { 0, 0}, +}; + +#if LOGGING +FILE *log_fd; +#define DO_LOG(x...) do { fprintf(log_fd, x); fflush(log_fd); } while (0) +#else +#define DO_LOG(x...) do { } while (0) +#endif + +static void start_logging(void) +{ +#if LOGGING + log_fd = fopen(LOGGING_FILE, "a"); +#endif +} + +static void end_logging(void) +{ +#if LOGGING + fclose(log_fd); +#endif +} + +static unsigned long map_keycode(SDLKey sk) +{ + unsigned int i; + + for (i = 0; key_map[i].sdlkey; i++) + if (key_map[i].sdlkey == sk) { + DO_LOG("%s: keytrans: #%d (%s) -> %ld\n", + PROGNAME, sk, SDL_GetKeyName(sk), key_map[i].l4ev); + return key_map[i].l4ev; + } + + DO_LOG("%s: Unknown key pressed/released: #%d (%s)\n", + PROGNAME, sk, SDL_GetKeyName(sk)); + return 0; +} + +void usage(char *prog) +{ + printf("%s options\n\n" + " -f fd File descriptor to mmap\n" + " -s 0x... Start of FB in physmem\n" + " -x val Width of screen in pixels\n" + " -y val Height of screen in pixels\n" + " -d val Color depth in bits\n" + " -r val Refresh rate in ms\n" + " -m Flip mouse visibility\n" + " -F Switch to fullscreen mode\n" + ,prog); +} + +static void set_window_title(int count) +{ + char title[100]; + + snprintf(title, sizeof(title), "%s - %s | %d", + WM_WINDOW_TITLE, + signal_mode ? "Signalled mode" : "Polling mode", count); + + SDL_WM_SetCaption(title, WM_ICON_TITLE); +} + +Uint32 timer_call_back(Uint32 interval, void *param) +{ + static SDL_Event se = { .type = SDL_USEREVENT }; + + (void)param; + + SDL_PushEvent(&se); + + return interval; +} + +static inline int enqueue_event(struct l4input e) +{ + struct l4input *p = input_mem + input_queue_pos; + + if (p->time) { + printf("Ringbuffer overflow, don't type/move too fast!\n"); + DO_LOG("Ringbuffer overflow, don't type/move too fast!\n"); + return 1; + } + + e.time = SDL_GetTicks() * 1000ULL + 1; + *p = e; + + input_queue_pos++; + if (input_queue_pos == NR_INPUT_OBJS) + input_queue_pos = 0; + return 0; +} + +static inline void generate_irq(void) +{ + struct l4input e; + e.type = EV_SYN; + e.code = SYN_REPORT; + e.value = e.stream_id = 0; + enqueue_event(e); + + + if (write(0, "I", 1) != 1) { + DO_LOG("%s: Communication problems with Fiasco-UX, dying...!\n", + PROGNAME); + exit(0); + } +} + +static void propagate_event(struct l4input e) +{ + if (!enqueue_event(e)) + generate_irq(); +} + +void signal_handler(int sig) +{ + (void)sig; + signal_mode = sig_redraw_pending = 1; +} + +static void loop(SDL_Surface *screen, void *fbmem) +{ + SDL_Event e; + SDL_TimerID timer_id; + int count = 0; + int poll_mode_shown = 1; + + /* Install signal handler for SIGUSR1 */ + signal(SIGUSR1, signal_handler); + + if ((timer_id = SDL_AddTimer(refresh_rate, timer_call_back, NULL)) == NULL) { + fprintf(stderr, "%s: Adding of timer failed!", PROGNAME); + exit(1); + } + + while (SDL_WaitEvent(&e)) { + struct l4input l4e = { .time = 0, .code = 0, + .type = 0, .value = 0, .stream_id = 0 }; + + if (signal_mode && poll_mode_shown) { + set_window_title(count); + poll_mode_shown = 0; + } + + if (count % 100 == 0) + set_window_title(count); + + switch (e.type) { + case SDL_KEYUP: + case SDL_KEYDOWN: + l4e.value = e.type == SDL_KEYDOWN; + l4e.type = EV_KEY; + l4e.code = map_keycode(e.key.keysym.sym); + + //fprintf(stderr, "%s: sdlkey = %d l4e.code = %d\n", __func__, e.key.keysym.sym, l4e.code); + + propagate_event(l4e); + + break; + + case SDL_MOUSEBUTTONDOWN: + case SDL_MOUSEBUTTONUP: + l4e.value = e.type == SDL_MOUSEBUTTONDOWN; + l4e.type = EV_KEY; + + switch (e.button.button) { + case SDL_BUTTON_LEFT: + l4e.code = BTN_LEFT; + break; + case SDL_BUTTON_RIGHT: + l4e.code = BTN_RIGHT; + break; + case SDL_BUTTON_MIDDLE: + l4e.code = BTN_MIDDLE; + break; + default: + l4e.code = 0; + } + + propagate_event(l4e); + + break; + + case SDL_MOUSEMOTION: + { + int ret = 1; + + l4e.type = EV_REL; + if (e.motion.xrel) { + l4e.code = REL_X; + l4e.value = e.motion.xrel; + ret = enqueue_event(l4e); + } + if (e.motion.yrel) { + l4e.code = REL_Y; + l4e.value = e.motion.yrel; + ret |= enqueue_event(l4e); + } + if (!ret) + generate_irq(); + } + + break; + + case SDL_ACTIVEEVENT: /* Window (non-)active */ + break; + + case SDL_QUIT: + exit(0); + + case SDL_USEREVENT: + if (!signal_mode || sig_redraw_pending) { + /* Redraw screen */ + if (SDL_LockSurface(screen) < 0) + break; + memcpy(screen->pixels, fbmem, fb_size); + SDL_UnlockSurface(screen); + SDL_Flip(screen); + count++; + sig_redraw_pending = 0; + } + break; + + default: + fprintf(stderr, "%s: Unknown event: %d\n", PROGNAME, e.type); + DO_LOG("Unknown event: %d\n", e.type); + break; + } + + } + +} + +int main(int argc, char **argv) +{ + int c; + void *fbmem; + SDL_Surface *screen; + unsigned int sdl_video_flags = 0; /* SDL_DOUBLEBUF; */ + + refresh_rate = DFL_REFRESH_INTERVAL; + mouse_visible = DFL_MOUSE_VISIBLE; + + while ((c = getopt(argc, argv, "f:x:y:s:d:r:mF")) != -1) { + switch (c) { + case 'f': + physmem_fd = atoi(optarg); + break; + case 's': + physmem_fb_start = atol(optarg); + break; + case 'x': + width = atoi(optarg); + break; + case 'y': + height = atoi(optarg); + break; + case 'd': + depth = atoi(optarg); + break; + case 'r': + refresh_rate = atoi(optarg); + break; + case 'm': + mouse_visible = !mouse_visible; + break; + case 'F': + sdl_video_flags |= SDL_FULLSCREEN; + break; + default: + usage(*argv); + break; + } + } + + start_logging(); + atexit(end_logging); + + if (!physmem_fd || !physmem_fb_start || !width || !height || !depth || + !refresh_rate) { + fprintf(stderr, "%s: Invalid arguments!\n", PROGNAME); + usage(*argv); + exit(1); + } + + printf("Frame buffer resolution of UX-con: %dx%d@%d, refresh: %dms\n", + width, height, depth, refresh_rate); + + depth_bytes = ((depth + 7) >> 3); + fb_size = width * height * depth_bytes; + + physmem_size = ((fb_size & ~(SUPERPAGESIZE - 1))) + SUPERPAGESIZE; + + if ((fbmem = mmap(NULL, physmem_size + INPUTMEM_SIZE, + PROT_READ | PROT_WRITE, MAP_SHARED, + physmem_fd, physmem_fb_start)) == MAP_FAILED) { + fprintf(stderr, "%s: mmap failed: %s\n", PROGNAME, strerror(errno)); + exit(1); + } + + input_mem = (struct l4input *)((char *)fbmem + physmem_size); + + if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) < 0) { + fprintf(stderr, "%s: Can't init SDL: %s\n", + PROGNAME, SDL_GetError()); + exit(1); + } + atexit(SDL_Quit); + + screen = SDL_SetVideoMode(width, height, depth, sdl_video_flags); + if (screen == NULL) { + fprintf(stderr, "%s: Couldn't init video mode: %s\n", + PROGNAME, SDL_GetError()); + exit(1); + } + + set_window_title(0); + + SDL_ShowCursor(mouse_visible); + + loop(screen, fbmem); + + return 0; +} diff --git a/kernel/fiasco/src/drivers/ux/ux_net.c b/kernel/fiasco/src/drivers/ux/ux_net.c new file mode 100644 index 00000000..c40a8a75 --- /dev/null +++ b/kernel/fiasco/src/drivers/ux/ux_net.c @@ -0,0 +1,103 @@ +/* + * Net helper for Fiasco-UX + * + * Adam Lackorzynski + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PROGNAME "ux_tun" + +static inline void generate_irq() +{ + if (write(0, "I", 1) == -1) { + printf("%s: Communication problems with Fiasco-UX, dying...!\n", + PROGNAME); + exit(0); + } +} + +static int pollfds = 1; + +static void sig_handler(int sig) +{ + (void)sig; + pollfds = 1; +} + +void loop(int fd) +{ + struct pollfd p; + int ret; + + p.fd = fd; + p.events = POLLIN; + + signal(SIGUSR1, sig_handler); + + while (1) { + if ((ret = poll(&p, pollfds, 4000)) >= 0) { + pollfds = 0; + // also ping for ret==0 so that this program can exit if fiasco goes + // away, the other side must cope with that + generate_irq(); + } + } +} + +void usage(char *prog) +{ + printf("%s options\n\n" + " -t fd TUN file descriptor\n" + ,prog); +} + +int main(int argc, char **argv) +{ + int c; + int tun_fd = 0; + struct ifreq ifr; + + while ((c = getopt(argc, argv, "t:")) != -1) { + switch (c) { + case 't': + tun_fd = atol(optarg); + break; + default: + usage(*argv); + break; + } + } + + if (!tun_fd) { + fprintf(stderr, "%s: Invalid arguments!\n", PROGNAME); + usage(*argv); + exit(1); + } + + memset(&ifr, 0, sizeof(ifr)); + ifr.ifr_flags = IFF_TAP | IFF_NO_PI; + strncpy(ifr.ifr_name, "tun%d", IFNAMSIZ); + if (ioctl(tun_fd, TUNSETIFF, (unsigned long)&ifr) != 0) { + perror("ioctl on tun device"); + exit(1); + } + + fcntl(tun_fd, F_SETFL, O_NONBLOCK); + + loop(tun_fd); + + return 0; +} diff --git a/kernel/fiasco/src/drivers/vga_console.cpp b/kernel/fiasco/src/drivers/vga_console.cpp new file mode 100644 index 00000000..9f04a340 --- /dev/null +++ b/kernel/fiasco/src/drivers/vga_console.cpp @@ -0,0 +1,488 @@ +INTERFACE: + +#include "types.h" +#include "console.h" + +/** + * Console implementation for VGA. + * + * This console is a output only console for VGA. + * It implements an ANSI ESC capable output device. + */ +class Vga_console : public Console +{ +public: + + /** + * Clear the screen, + */ + void clear(); + + /** + * Scroll the screen n lines up. + * @param n number of lines to scroll. + */ + void scroll( unsigned n ); + + /** + * Get the base address for the VGA memory. + * @return The base address of the VGA memory. + */ + Address video_base() const; + + /** + * Set the base address of the VGA memory. + * @param base the base address of the VGA memory. + */ + void video_base( Address base ); + + /** + * Create a new instance of a VGA console. + * @param base the base address of the VGA memory. + * @param width the width of the screen. + * @param height the height of the screen. + * @param light_white if set to true the color + * grey is replaced with white. + * @param use_color says whether ANSI ESC colors should be + * passed (=true) to the video memory or not (=false). + */ + Vga_console( Address base, unsigned width = 80, unsigned height = 25, + bool light_white = false, bool use_color = false ); + + /** + * dtor. + */ + ~Vga_console(); + + /** + * Output method. + */ + int write( char const *str, size_t len ); + + /** + * Empty implementation. + */ + int getchar( bool blocking = true ); + + inline bool is_working(); + + /** + * Output a character. + */ + inline void printchar(unsigned x, unsigned y, unsigned char c, unsigned char a); + +private: + + /// Type of a on screen character. + struct VChar { + char c; + char a; + } __attribute__((packed)); + + VChar *_video_base; + Address _crtc; + unsigned _width, _height; + unsigned _x, _y; + unsigned _attribute; + enum { + MAX_ANSI_ESC_ARGS = 5, + }; + + int ansi_esc_args[MAX_ANSI_ESC_ARGS]; + unsigned num_ansi_esc_args; + + void (Vga_console::*wr)(char const *, size_t, unsigned & ); + + bool const _light_white; + bool const _use_color; + bool _is_working; + + /** + * Set blinking screen cursor + */ + void blink_cursor( unsigned x, unsigned y ); +}; + + + +IMPLEMENTATION: + +#include +#include + +#include "io.h" +#include "mem_layout.h" + + +IMPLEMENT +Vga_console::Vga_console( Address vbase, unsigned width, unsigned height, + bool light_white, bool use_color ) + : _video_base((VChar*)vbase), _width(width), _height(height), + _x(0), _y(height-1), _attribute(light_white ? 0x0f : 0x07), + wr(&Vga_console::normal_write), _light_white(light_white), + _use_color(use_color), _is_working(false) +{ + unsigned volatile *vm = (unsigned volatile *)_video_base; + unsigned x = *vm; + *vm = 12; + if(*vm!=12) + { + _is_working = false; + *vm = x; + return; + } + + *vm = 47634; + if(*vm != 47634) + { + _is_working = false; + *vm = x; + return; + } + + _is_working = true; + *vm = x; + + if (vbase == Mem_layout::Adap_vram_mda_beg) + _crtc = 0x3b4; + else + _crtc = 0x3d4; + + scroll(1); +} + +PRIVATE inline +void Vga_console::set(unsigned i, char c, char a) +{ + _video_base[i].c = c; + _video_base[i].a = a; +} + +IMPLEMENT +void Vga_console::scroll( unsigned lines ) +{ + if(lines && lines <= _height) { + for( unsigned i = lines*_width; i< _width * _height; ++i ) + _video_base[i-lines*_width] = _video_base[i]; +#if 0 + memmove( _video_base, _video_base + _width*lines, + _width*(_height - lines)*2 ); +#endif + + for (unsigned i = (_height - lines) * _width; i < _width * _height; ++i) + set(i, 0x20, _attribute); + } +} + +IMPLEMENT inline NEEDS[Vga_console::set] +void +Vga_console::printchar(unsigned x, unsigned y, + unsigned char c, unsigned char a) +{ + set(x + y * _width, c, a); +} + +IMPLEMENT +void Vga_console::blink_cursor( unsigned x, unsigned y) +{ + unsigned pos = 80*y + x; + + Io::out16( (pos & 0xff00) | 0x0e, _crtc); + Io::out16( (pos << 8) | 0x0f, _crtc); +} + +IMPLEMENT +void Vga_console::clear() +{ + for (unsigned i = 0; i<_width*_height; ++i) + set(i, 0x20, _attribute); +} + + + +PRIVATE inline +int Vga_console::seq_6( char const *str, size_t len, unsigned &pos ) +{ + if( pos+2 >= len ) return 0; + _y = str[pos+1]; + _x = str[pos+2]; + if( _y >= _height ) _y = _height -1; + if( _x >= _width ) _x = _width -1; + pos += 2; + return 1; +} + +PRIVATE inline +int Vga_console::seq_1( char const *, size_t, unsigned & ) +{ + _x = 0; _y = 0; return 1; +} + +PRIVATE inline NEEDS[Vga_console::set] +int Vga_console::seq_5( char const *, size_t , unsigned & ) +{ + for( unsigned i = 0; i<_width-_x; ++i) + set(_x+(_y*_width)+i, 0x20, _attribute); + + return 1; +} + + +PRIVATE inline +void Vga_console::ansi_attrib( int a ) +{ + char const colors[] = { 0, 4, 2, 6, 1, 5, 3, 7 }; + + if(!_use_color && a>=30 && a <=47) + return; + + switch(a) { + case 0: + if(_light_white) + _attribute = 0x0f; + else + _attribute = 0x07; + break; + case 1: + _attribute |= 0x0808; + break; + case 22: + _attribute &= ~0x0808; + break; + case 5: + _attribute |= 0x8080; + default: + if (30 <= a && a <= 37) + _attribute = (_attribute & 0x0f0) | colors[a-30] | ((_attribute >> 8) & 0x08); + else if (40 <= a && a <= 47) + _attribute = (_attribute & 0x0f) | (colors[a-40] << 4) | ((_attribute >> 8) & 0x80); + break; + }; + +} + + + +PRIVATE +void Vga_console::esc_write( char const *str, size_t len, unsigned &i ) +{ + if(i>=len) return; + + if(str[i] == '[') { + ansi_esc_args[0] = 0; + ansi_esc_args[1] = 0; + num_ansi_esc_args = 0; + wr = &Vga_console::ansi_esc_write; + } else + wr = &Vga_console::normal_write; + + ++i; +} + +PRIVATE +void Vga_console::ansi_esc_write( char const *str, size_t len, unsigned &i ) +{ + + /* ansi seq */ + for(;i=len) return; + + switch(str[i]) { + + case 'f': /* Move cursor + blink cursor to location v,h */ + _x = ansi_esc_args[1]; if(_y) --_y; + _y = ansi_esc_args[0]; if(_x) --_x; + if(_x>=_width ) _x=_width -1; + if(_y>=_height) _y=_height -1; + blink_cursor(_x, _y); + break; + + case 'H': /* Move cursor to screen location v,h */ + _x = ansi_esc_args[1]; if(_x) --_x; + _y = ansi_esc_args[0]; if(_y) --_y; + if(_x>=_width ) _x=_width -1; + if(_y>=_height) _y=_height -1; + break; + + case 'm': /*color*/ + { + int p = 0; + do { + ansi_attrib(ansi_esc_args[p++]); + } while(num_ansi_esc_args--); + } + break; + + case 'X': /* clear n characters */ + for (unsigned i = _x + (_y*_width); i< _x + (_y*_width) + ansi_esc_args[0]; + ++i) + set(i, 0x20, _attribute); + + break; + + case 'K': /* Clear line from cursor right */ + switch(ansi_esc_args[0]) { + default: + case 0: + for (unsigned i = _x + (_y*_width); i< (_y*_width) + _width;++i) + set(i, 0x20, _attribute); + + break; + case 1: + for (unsigned i = (_y*_width); i<(_y*_width)+_x;++i) + set(i, 0x20, _attribute); + + break; + case 2: + for (unsigned i = (_y*_width); i<(_y*_width)+_width;++i) + set(i, 0x20, _attribute); + + break; + } + break; + + case 'J': /* Clear screen from cursor */ + switch(ansi_esc_args[0]) { + default: + case 0: + for (unsigned i = (_y*_width); i<(_y*_width)+_width*(_height-_y);++i) + set(i, 0x20, _attribute); + + break; + case 1: + for (unsigned i = 0; i<_width*_y;++i) + set(i, 0x20, _attribute); + + break; + case 2: + for (unsigned i = 0; i<_width*_height;++i) + set(i, 0x20, _attribute); + + break; + } + break; + } + + wr = &Vga_console::normal_write; + ++i; +} + +PRIVATE +void Vga_console::normal_write( char const *str, size_t len, unsigned &i ) +{ + for(; i=_height) { + scroll(_y-_height+1); + _y = _height -1; + } + break; + case '\r': + _x = 0; break; + case '\t': + _x = (_x & ~7) + 8; + break; + + case 27: /*ESC*/ + wr = &Vga_console::esc_write; + ++i; + return; + break; + + case 6: + /* cursor */ + seq_6( str, len, i ); + break; + + case 1: + /* home */ + seq_1( str, len, i ); + break; + + case 5: + /* clear to end of line */ + seq_5( str, len, i ); + break; + + case 8: + /* back space */ + if(_x) --_x; + break; + + default: + if((unsigned)str[i] >= 32) { + if(_x>=_width) { + ++_y; _x = 0; + } + + if(_y>=_height) { + scroll(_y-_height+1); + _y = _height -1; + } + if(_x<_width) + set(_y * _width + _x, + str[i] == '\265' ? '\346' : str[i], _attribute); + + ++_x; + } + break; + } + } +} + + +IMPLEMENT +int Vga_console::write( char const *str, size_t len ) +{ + unsigned pos = 0; + while(pos*wr)(str,len,pos); + + return pos; +} + +IMPLEMENT +int Vga_console::getchar( bool ) +{ + blink_cursor(_x,_y); + return -1; +} + + +IMPLEMENT +Vga_console::~Vga_console() +{} + + +IMPLEMENT inline +bool Vga_console::is_working() +{ + return _is_working; +} + +PUBLIC +Mword Vga_console::get_attributes() const +{ + return DIRECT | OUT; +} + diff --git a/kernel/fiasco/src/jabi/jdb_ktrace.cpp b/kernel/fiasco/src/jabi/jdb_ktrace.cpp new file mode 100644 index 00000000..8ec38a10 --- /dev/null +++ b/kernel/fiasco/src/jabi/jdb_ktrace.cpp @@ -0,0 +1,52 @@ +INTERFACE: + +#include "types.h" + +enum { + Log_event_context_switch = 0, + Log_event_ipc_shortcut = 1, + Log_event_irq_raised = 2, + Log_event_timer_irq = 3, + Log_event_thread_ex_regs = 4, + Log_event_trap = 5, + Log_event_pf_res = 6, + Log_event_sched = 7, + Log_event_preemption = 8, + Log_event_max = 16, +}; + +enum { + Kern_cnt_context_switch = 0, + Kern_cnt_addr_space_switch = 1, + Kern_cnt_shortcut_failed = 2, + Kern_cnt_shortcut_success = 3, + Kern_cnt_irq = 4, + Kern_cnt_ipc_long = 5, + Kern_cnt_page_fault = 6, + Kern_cnt_io_fault = 7, + Kern_cnt_task_create = 8, + Kern_cnt_schedule = 9, + Kern_cnt_iobmap_tlb_flush = 10, + Kern_cnt_exc_ipc = 11, + Kern_cnt_max +}; + +struct Tracebuffer_status_window +{ + Address tracebuffer; + Address size; + Unsigned64 version; +}; + +struct Tracebuffer_status +{ + Tracebuffer_status_window window[2]; + Address current; + Unsigned32 logevents[Log_event_max]; + + Unsigned32 scaler_tsc_to_ns; + Unsigned32 scaler_tsc_to_us; + Unsigned32 scaler_ns_to_tsc; + + Unsigned32 kerncnts[Kern_cnt_max]; +}; diff --git a/kernel/fiasco/src/jdb/arm/jdb-arm.cpp b/kernel/fiasco/src/jdb/arm/jdb-arm.cpp new file mode 100644 index 00000000..a0ac4c13 --- /dev/null +++ b/kernel/fiasco/src/jdb/arm/jdb-arm.cpp @@ -0,0 +1,319 @@ +IMPLEMENTATION [arm]: + +#include "globals.h" +#include "kernel_task.h" +#include "kmem_alloc.h" +#include "kmem_space.h" +#include "space.h" +#include "mem_layout.h" +#include "mem_unit.h" +#include "static_init.h" +#include "watchdog.h" + +STATIC_INITIALIZE_P(Jdb, JDB_INIT_PRIO); + +DEFINE_PER_CPU static Per_cpu jdb_irq_state; + +// disable interrupts before entering the kernel debugger +IMPLEMENT +void +Jdb::save_disable_irqs(unsigned cpu) +{ + jdb_irq_state.cpu(cpu) = Proc::cli_save(); + if (cpu == 0) + Watchdog::disable(); +} + +// restore interrupts after leaving the kernel debugger +IMPLEMENT +void +Jdb::restore_irqs(unsigned cpu) +{ + if (cpu == 0) + Watchdog::enable(); + Proc::sti_restore(jdb_irq_state.cpu(cpu)); +} + +IMPLEMENT inline +void +Jdb::enter_trap_handler(unsigned /*cpu*/) +{} + +IMPLEMENT inline +void +Jdb::leave_trap_handler(unsigned /*cpu*/) +{} + +PROTECTED static inline +void +Jdb::monitor_address(unsigned, void *) +{} + +IMPLEMENT inline +bool +Jdb::handle_conditional_breakpoint(unsigned /*cpu*/) +{ return false; } + +IMPLEMENT +void +Jdb::handle_nested_trap(Jdb_entry_frame *e) +{ + printf("Trap in JDB: IP:%08lx PSR=%08lx ERR=%08lx\n", + e->ip(), e->psr, e->error_code); +} + +IMPLEMENT +bool +Jdb::handle_debug_traps(unsigned cpu) +{ + Jdb_entry_frame *ef = entry_frame.cpu(cpu); + + if (ef->error_code == 0x00e00000) + snprintf(error_buffer.cpu(cpu), sizeof(error_buffer.cpu(0)), "%s", + (char const *)ef->r[0]); + else if (ef->debug_ipi()) + snprintf(error_buffer.cpu(cpu), sizeof(error_buffer.cpu(0)), + "IPI ENTRY"); + + return true; +} + +IMPLEMENT inline +bool +Jdb::handle_user_request(unsigned cpu) +{ + Jdb_entry_frame *ef = Jdb::entry_frame.cpu(cpu); + const char *str = (char const *)ef->r[0]; + Space * task = get_task(cpu); + char tmp; + + if (ef->debug_ipi()) + return cpu != 0; + + if (ef->error_code == 0x00e00001) + return execute_command_ni(task, str); + + if (!peek(str, task, tmp) || tmp != '*') + return false; + if (!peek(str+1, task, tmp) || tmp != '#') + return false; + + return execute_command_ni(task, str+2); +} + +IMPLEMENT inline +bool +Jdb::test_checksums() +{ return true; } + +static +bool +Jdb::handle_special_cmds(int) +{ return 1; } + +PUBLIC static +FIASCO_INIT FIASCO_NOINLINE void +Jdb::init() +{ + static Jdb_handler enter(at_jdb_enter); + static Jdb_handler leave(at_jdb_leave); + + Jdb::jdb_enter.add(&enter); + Jdb::jdb_leave.add(&leave); + + Thread::nested_trap_handler = (Trap_state::Handler)enter_jdb; + + Kconsole::console()->register_console(push_cons()); +} + + +PRIVATE static +void * +Jdb::access_mem_task(Address virt, Space * task) +{ + // align + virt &= ~0x03; + + Address phys; + + if (!task) + { + if (Mem_layout::in_kernel(virt)) + { + Pte p = Kmem_space::kdir()->walk((void *)virt, 0, false, Ptab::Null_alloc(), 0); + if (!p.valid()) + return 0; + + phys = p.phys((void*)virt); + } + else + phys = virt; + } + else + { + phys = Address(task->virt_to_phys(virt)); + + + if (phys == (Address)-1) + phys = task->virt_to_phys_s0((void *)virt); + + if (phys == (Address)-1) + return 0; + } + + unsigned long addr = Mem_layout::phys_to_pmem(phys); + if (addr == (Address)-1) + { + Mem_unit::flush_vdcache(); + Pte pte = static_cast(Kernel_task::kernel_task()) + ->_dir->walk((void*)Mem_layout::Jdb_tmp_map_area, 0, false, Ptab::Null_alloc(), 0); + + if (pte.phys() != (phys & ~(Config::SUPERPAGE_SIZE - 1))) + pte.set(phys & ~(Config::SUPERPAGE_SIZE - 1), Config::SUPERPAGE_SIZE, + Mem_page_attr(Page::KERN_RW | Page::CACHEABLE), true); + + Mem_unit::dtlb_flush(); + + addr = Mem_layout::Jdb_tmp_map_area + (phys & (Config::SUPERPAGE_SIZE - 1)); + } + + return (Mword*)addr; +} + +PUBLIC static +Space * +Jdb::translate_task(Address addr, Space * task) +{ + return (Kmem::is_kmem_page_fault(addr, 0)) ? 0 : task; +} + +PUBLIC static +int +Jdb::peek_task(Address virt, Space * task, void *value, int width) +{ + void const *mem = access_mem_task(virt, task); + if (!mem) + return -1; + + switch (width) + { + case 1: + { + Mword dealign = (virt & 0x3) * 8; + *(Mword*)value = (*(Mword*)mem & (0xff << dealign)) >> dealign; + } + break; + case 2: + { + Mword dealign = ((virt & 0x2) >> 1) * 16; + *(Mword*)value = (*(Mword*)mem & (0xffff << dealign)) >> dealign; + } + break; + case 4: + memcpy(value, mem, width); + } + + return 0; +} + +PUBLIC static +int +Jdb::is_adapter_memory(Address, Space *) +{ + return 0; +} + +PUBLIC static +int +Jdb::poke_task(Address virt, Space * task, void const *val, int width) +{ + void *mem = access_mem_task(virt, task); + if (!mem) + return -1; + + memcpy(mem, val, width); + return 0; +} + + +PRIVATE static +void +Jdb::at_jdb_enter() +{ + Mem_unit::clean_vdcache(); +} + +PRIVATE static +void +Jdb::at_jdb_leave() +{ + Mem_unit::flush_vcache(); +} + +PUBLIC static inline +void +Jdb::enter_getchar() +{} + +PUBLIC static inline +void +Jdb::leave_getchar() +{} + +PUBLIC static +void +Jdb::write_tsc_s(Signed64 tsc, char *buf, int maxlen, bool sign) +{ + if (sign) + { + *buf++ = (tsc < 0) ? '-' : (tsc == 0) ? ' ' : '+'; + maxlen--; + } + snprintf(buf, maxlen, "%lld c", tsc); +} + +PUBLIC static +void +Jdb::write_tsc(Signed64 tsc, char *buf, int maxlen, bool sign) +{ + write_tsc_s(tsc, buf, maxlen, sign); +} + +//---------------------------------------------------------------------------- +IMPLEMENTATION [arm && !mp]: + +PROTECTED static inline +template< typename T > +void +Jdb::set_monitored_address(T *dest, T val) +{ *dest = val; } + +//---------------------------------------------------------------------------- +IMPLEMENTATION [arm && mp]: + +#include + +static +void +Jdb::send_nmi(unsigned cpu) +{ + printf("NMI to %d, what's that?\n", cpu); +} + +PROTECTED static inline +template< typename T > +void +Jdb::set_monitored_address(T *dest, T val) +{ + *dest = val; + Mem::dsb(); + asm volatile("sev"); +} + +PROTECTED static inline +template< typename T > +T Jdb::monitor_address(unsigned, T volatile *addr) +{ + asm volatile("wfe"); + return *addr; +} diff --git a/kernel/fiasco/src/jdb/arm/jdb_dump_entry_frame-arm.cpp b/kernel/fiasco/src/jdb/arm/jdb_dump_entry_frame-arm.cpp new file mode 100644 index 00000000..cbc71db4 --- /dev/null +++ b/kernel/fiasco/src/jdb/arm/jdb_dump_entry_frame-arm.cpp @@ -0,0 +1,65 @@ +IMPLEMENTATION[arm]: + +#include + +#include "jdb.h" +#include "jdb_module.h" +#include "static_init.h" +#include "types.h" + + +//=================== +// Std JDB modules +//=================== + +/** + * 'IRQ' module. + * + * This module handles the 'e' command that + * dumps the entry frame. + */ +class Jdb_dump_ef + : public Jdb_module +{ +}; + +static Jdb_dump_ef jdb_dump_ef INIT_PRIORITY(JDB_MODULE_INIT_PRIO); + +PUBLIC Jdb_module::Action_code +Jdb_dump_ef::action( int cmd, void *&, char const *&, int & ) +{ + if (cmd!=0) + return NOTHING; + + printf("klr: %08x ksp: %08x cpsr: %08x spsr: %08x\n", + Jdb::entry_frame->pc, + Jdb::entry_frame->ksp, + Jdb::entry_frame->cpsr, + Jdb::entry_frame->spsr); + + for(int i = 0; i<=14; i++) + { + printf("r[%2d]: %08x %c", i, Jdb::entry_frame->r[i], (i%4 == 3)?'\n':' '); + } + + putchar('\n'); + + return NOTHING; +} + +PUBLIC +int const Jdb_dump_ef::num_cmds() const +{ + return 1; +} + +PUBLIC +Jdb_module::Cmd const *const Jdb_dump_ef::cmds() const +{ + static Cmd cs[] = + { { 0, "e", "entryframe", "\n", + "e\tdump the JDB entry frame", 0 } + }; + + return cs; +} diff --git a/kernel/fiasco/src/jdb/arm/jdb_entry_frame-arm.cpp b/kernel/fiasco/src/jdb/arm/jdb_entry_frame-arm.cpp new file mode 100644 index 00000000..a41ee588 --- /dev/null +++ b/kernel/fiasco/src/jdb/arm/jdb_entry_frame-arm.cpp @@ -0,0 +1,121 @@ +INTERFACE [arm]: + +#include "cpu.h" +#include "trap_state.h" +#include "tb_entry.h" + +class Jdb_entry_frame : public Trap_state +{ +public: + Address_type from_user() const; + Address ip() const; + bool debug_ipi() const; +}; + +class Jdb_output_frame : public Jdb_entry_frame +{}; + +class Jdb_status_page_frame : public Jdb_entry_frame +{}; + +class Jdb_log_frame : public Jdb_entry_frame +{}; + +class Jdb_log_3val_frame : public Jdb_log_frame +{}; + +class Jdb_debug_frame : public Jdb_entry_frame +{}; + +class Jdb_symbols_frame : public Jdb_debug_frame +{}; + +class Jdb_lines_frame : public Jdb_debug_frame +{}; + +class Jdb_get_cputime_frame : public Jdb_entry_frame +{}; + +class Jdb_thread_name_frame : public Jdb_entry_frame +{}; + +//--------------------------------------------------------------------------- +IMPLEMENTATION[arm]: + +#include +#include "processor.h" + +#if 0 +PUBLIC +void +Jdb_entry_frame::dump() const +{ + printf( + "R[ 0- 3]: %08lx %08lx %08lx %08lx\n" + "R[ 4- 7]: %08lx %08lx %08lx %08lx\n" + "R[ 8-11]: %08lx %08lx %08lx %08lx\n" + "R[12-15]: %08lx %08lx %08lx %08lx\n" + "kernel sp = %08lx cpsr = %08lx spsr = %08lx\n", + r[0], r[1], r[2], r[3], r[4], r[5], r[6], r[7], r[8], + r[9], r[10], r[11], r[12], r[13], r[14], pc, ksp, cpsr, spsr); +} +#endif + +IMPLEMENT inline +bool +Jdb_entry_frame::debug_ipi() const +{ return error_code == 0x00e00002; } + +IMPLEMENT inline NEEDS["processor.h"] +Address_type +Jdb_entry_frame::from_user() const +{ + return (psr & Proc::Status_mode_mask) == Proc::Status_mode_user + ? ADDR_USER : ADDR_KERNEL; +} + +PUBLIC inline +Address Jdb_entry_frame::ksp() const +{ return Address(this); } + +IMPLEMENT inline +Address Jdb_entry_frame::ip() const +{ return pc; } + +PUBLIC inline +Mword +Jdb_entry_frame::param() const +{ return r[0]; } + + +PUBLIC inline +Unsigned8* +Jdb_log_frame::str() const +{ return (Unsigned8*)r[1]; } + +PUBLIC inline NEEDS["tb_entry.h"] +void +Jdb_log_frame::set_tb_entry(Tb_entry* tb_entry) +{ r[0] = (Mword)tb_entry; } + +//--------------------------------------------------------------------------- +PUBLIC inline +Mword +Jdb_log_3val_frame::val1() const +{ return r[2]; } + +PUBLIC inline +Mword +Jdb_log_3val_frame::val2() const +{ return r[3]; } + +PUBLIC inline +Mword +Jdb_log_3val_frame::val3() const +{ return r[4]; } + +//--------------------------------------------------------------------------- +PUBLIC inline +void +Jdb_status_page_frame::set(Address status_page) +{ r[0] = (Mword)status_page; } diff --git a/kernel/fiasco/src/jdb/arm/jdb_extensions.cpp b/kernel/fiasco/src/jdb/arm/jdb_extensions.cpp new file mode 100644 index 00000000..eba7c0ea --- /dev/null +++ b/kernel/fiasco/src/jdb/arm/jdb_extensions.cpp @@ -0,0 +1,168 @@ +IMPLEMENTATION [arm-debug]: + +#include +#include +#include "jdb_tbuf.h" +#include "jdb_entry_frame.h" +#include "kdb_ke.h" +#include "cpu_lock.h" +#include "vkey.h" +#include "static_init.h" +#include "thread.h" +#include "outer_cache.h" +#include "processor.h" + +static void outchar(Thread *, Entry_frame *r) +{ putchar(r->r[0] & 0xff); } + +static void outstring(Thread *, Entry_frame *r) +{ putstr((char*)r->r[0]); } + +static void outnstring(Thread *, Entry_frame *r) +{ putnstr((char*)r->r[0], r->r[1]); } + +static void outdec(Thread *, Entry_frame *r) +{ printf("%ld", r->r[0]); } + +static void outhex(Thread *, Entry_frame *r) +{ printf("%08lx", r->r[0]); } + +static void outhex20(Thread *, Entry_frame *r) +{ printf("%05lx", r->r[0] & 0xfffff); } + +static void outhex16(Thread *, Entry_frame *r) +{ printf("%04lx", r->r[0] & 0xffff); } + +static void outhex12(Thread *, Entry_frame *r) +{ printf("%03lx", r->r[0] & 0xfff); } + +static void outhex8(Thread *, Entry_frame *r) +{ printf("%02lx", r->r[0] & 0xff); } + +static void inchar(Thread *, Entry_frame *r) +{ + r->r[0] = Vkey::get(); + Vkey::clear(); +} + +static void tbuf(Thread *t, Entry_frame *r) +{ + Mem_space *s = t->mem_space(); + Address ip = r->ip(); + Address_type user; + Unsigned8 *str; + int len; + char c; + + Jdb_entry_frame *entry_frame = reinterpret_cast((char *)r - 8); + /* Why the -8? The Jdb_entry_frame has two more members in the beginning + * (see Trap_state_regs) so we're compensating for this with the -8. + * Alex: Proper fix? + */ + user = entry_frame->from_user(); + + switch (entry_frame->param()) + { + case 0: // fiasco_tbuf_get_status() + { + Jdb_status_page_frame *regs = + reinterpret_cast(entry_frame); + regs->set(Mem_layout::Tbuf_ustatus_page); + } + break; + case 1: // fiasco_tbuf_log() + { + Jdb_log_frame *regs = reinterpret_cast(entry_frame); + Tb_entry_ke *tb = + static_cast(Jdb_tbuf::new_entry()); + str = regs->str(); + tb->set(t, ip-4); + for (len=0; (c = s->peek(str++, user)); len++) + tb->set_buf(len, c); + tb->term_buf(len); + regs->set_tb_entry(tb); + Jdb_tbuf::commit_entry(); + } + break; + case 2: // fiasco_tbuf_clear() + Jdb_tbuf::clear_tbuf(); + break; + case 3: // fiasco_tbuf_dump() + return; // => Jdb + case 4: // fiasco_tbuf_log_3val() + { + // interrupts are disabled in handle_slow_trap() + Jdb_log_3val_frame *regs = + reinterpret_cast(entry_frame); + Tb_entry_ke_reg *tb = + static_cast(Jdb_tbuf::new_entry()); + str = regs->str(); + tb->set(t, ip-4, regs->val1(), regs->val2(), regs->val3()); + for (len=0; (c = s->peek(str++, user)); len++) + tb->set_buf(len, c); + tb->term_buf(len); + regs->set_tb_entry(tb); + Jdb_tbuf::commit_entry(); + } + break; + case 5: // fiasco_tbuf_get_status_phys() + { + Jdb_status_page_frame *regs = + reinterpret_cast(entry_frame); + regs->set(s->virt_to_phys(Mem_layout::Tbuf_ustatus_page)); + } + break; + case 6: // fiasco_timer_disable + printf("JDB: no more timer disable\n"); + //Timer::disable(); + break; + case 7: // fiasco_timer_enable + printf("JDB: no more timer enable\n"); + //Timer::enable(); + break; + case 8: // fiasco_tbuf_log_binary() + // interrupts are disabled in handle_slow_trap() + Jdb_log_frame *regs = reinterpret_cast(entry_frame); + Tb_entry_ke_bin *tb = + static_cast(Jdb_tbuf::new_entry()); + str = regs->str(); + tb->set(t, ip-4); + for (len=0; len < Tb_entry_ke_bin::SIZE; len++) + tb->set_buf(len, s->peek(str++, user)); + regs->set_tb_entry(tb); + Jdb_tbuf::commit_entry(); + break; + } +} + +static void do_cli(Thread *, Entry_frame *r) +{ r->psr |= Proc::Status_IRQ_disabled; } + +static void do_sti(Thread *, Entry_frame *r) +{ r->psr &= ~Proc::Status_IRQ_disabled; } + +static void getcpu(Thread *, Entry_frame *r) +{ + r->r[0] = current_cpu(); +} + +static void init_dbg_extensions() +{ + Thread::dbg_extension[0x01] = &outchar; + Thread::dbg_extension[0x02] = &outstring; + Thread::dbg_extension[0x03] = &outnstring; + Thread::dbg_extension[0x04] = &outdec; + Thread::dbg_extension[0x05] = &outhex; + Thread::dbg_extension[0x06] = &outhex20; + Thread::dbg_extension[0x07] = &outhex16; + Thread::dbg_extension[0x08] = &outhex12; + Thread::dbg_extension[0x09] = &outhex8; + Thread::dbg_extension[0x0d] = &inchar; + Thread::dbg_extension[0x1d] = &tbuf; + Thread::dbg_extension[0x32] = &do_cli; + Thread::dbg_extension[0x33] = &do_sti; + Thread::dbg_extension[0x34] = &getcpu; +} + +STATIC_INITIALIZER(init_dbg_extensions); + diff --git a/kernel/fiasco/src/jdb/arm/jdb_kern_info-arm.cpp b/kernel/fiasco/src/jdb/arm/jdb_kern_info-arm.cpp new file mode 100644 index 00000000..1c61a175 --- /dev/null +++ b/kernel/fiasco/src/jdb/arm/jdb_kern_info-arm.cpp @@ -0,0 +1,37 @@ +IMPLEMENTATION [arm]: + +#include +#include + +#include "config.h" +#include "globals.h" +#include "space.h" + +class Jdb_kern_info_misc : public Jdb_kern_info_module +{ +}; + +static Jdb_kern_info_misc k_i INIT_PRIORITY(JDB_MODULE_INIT_PRIO+1); + +PUBLIC +Jdb_kern_info_misc::Jdb_kern_info_misc() + : Jdb_kern_info_module('i', "Miscellaneous info") +{ + Jdb_kern_info::register_subcmd(this); +} + +PUBLIC +void +Jdb_kern_info_misc::show() +{ + // FIXME: assume UP here (current_meme_space(0)) + printf("clck: %08x.%08x\n" + "pdir: %08x\n", + (unsigned) (Kip::k()->clock >> 32), + (unsigned) (Kip::k()->clock), + (unsigned) Mem_space::current_mem_space(0)->dir()); + + +} + + diff --git a/kernel/fiasco/src/jdb/arm/jdb_kern_info-bench-arm.cpp b/kernel/fiasco/src/jdb/arm/jdb_kern_info-bench-arm.cpp new file mode 100644 index 00000000..18453b95 --- /dev/null +++ b/kernel/fiasco/src/jdb/arm/jdb_kern_info-bench-arm.cpp @@ -0,0 +1,24 @@ +IMPLEMENTATION[arm]: + +IMPLEMENT +void +Jdb_kern_info_bench::show_arch() +{} + +IMPLEMENTATION[arm && realview]: + +#include "platform.h" + +IMPLEMENT inline NEEDS["platform.h"] +Unsigned64 +Jdb_kern_info_bench::get_time_now() +{ return Platform::read(Platform::Sys::Cnt_24mhz); } + +IMPLEMENTATION[arm && !realview]: + +#include "kip.h" + +IMPLEMENT inline NEEDS["kip.h"] +Unsigned64 +Jdb_kern_info_bench::get_time_now() +{ return Kip::k()->clock; } diff --git a/kernel/fiasco/src/jdb/arm/jdb_kern_info-cpu-arm.cpp b/kernel/fiasco/src/jdb/arm/jdb_kern_info-cpu-arm.cpp new file mode 100644 index 00000000..74c8a998 --- /dev/null +++ b/kernel/fiasco/src/jdb/arm/jdb_kern_info-cpu-arm.cpp @@ -0,0 +1,190 @@ +IMPLEMENTATION [arm]: + +#include +#include + +#include "config.h" +#include "globals.h" +#include "space.h" + +class Jdb_kern_info_cpu : public Jdb_kern_info_module +{ +private: + static Mword jdb_mrc_insn(unsigned r_val) asm ("jdb_mrc_insn"); +}; + +static Jdb_kern_info_cpu k_c INIT_PRIORITY(JDB_MODULE_INIT_PRIO+1); + +PUBLIC +Jdb_kern_info_cpu::Jdb_kern_info_cpu() + : Jdb_kern_info_module('c', "CPU features") +{ + Jdb_kern_info::register_subcmd(this); +} + +asm ( + ".section \".text.jdb\" \t\n" + ".global jdb_mrc_insn \t\n" + "jdb_mrc_insn: mrc p0, 0, r0, c0, c0, 0 \t\n" + " mov pc, lr \t\n" + ".previous \t\n"); + +PRIVATE +Mword +Jdb_kern_info_cpu::mrc(Mword insn) +{ + char *m = reinterpret_cast(jdb_mrc_insn); + *reinterpret_cast(m) = insn; + Mem_unit::flush_cache(m, m); + return jdb_mrc_insn(0); +} + +PRIVATE +Mword +Jdb_kern_info_cpu::mrc(unsigned cp_num, unsigned opcode_1, + unsigned CRn, unsigned CRm, unsigned opcode_2) +{ + Mword insn = 0xee100010 + | (cp_num & 0xf) << 8 + | (opcode_1 & 0x7) << 21 + | (CRn & 0xf) << 16 + | (CRm & 0xf) + | (opcode_2 & 0x7) << 5; + + return mrc(insn); +} + + +template< + unsigned cp_num, + unsigned opcode_1, + unsigned CRn, + unsigned CRm, + unsigned opcode_2 +> +struct Arm_cp_op +{ + enum + { + Mrc = 0xee100010 + | (cp_num & 0xf) << 8 + | (opcode_1 & 0x7) << 21 + | (CRn & 0xf) << 16 + | (CRm & 0xf) + | (opcode_2 & 0x7) << 5, + + }; +}; + + +struct Cp_struct { + Mword mrc_opcode; + const char *descr; + void (*show)(Mword val); +}; + +static +void +show_cache_type(Mword val) +{ + Mword dcache_size = 512 << ((val >> 18) & 0xf); + Mword icache_size = 512 << ((val >> 6) & 0xf); + printf(" D-size: %ld dP: %ld I-size: %ld iP: %ld\n", + dcache_size, ((val >> 23) & 1), + icache_size, ((val >> 11) & 1)); +} + +static Cp_struct cp_vals[] = { + { Arm_cp_op<15, 0, 0, 0, 0>::Mrc, "Main ID", 0 }, + { Arm_cp_op<15, 0, 0, 0, 1>::Mrc, "Cache type", show_cache_type }, +}; + +PUBLIC +void +Jdb_kern_info_cpu::show() +{ + + for (unsigned i = 0; i < sizeof(cp_vals) / sizeof(cp_vals[0]); ++i) + { + Mword val = mrc(cp_vals[i].mrc_opcode); + printf("%47.s: %08lx\n", cp_vals[i].descr, val); + if (cp_vals[i].show) + cp_vals[i].show(val); + } + + + printf("Main ID: %08lx\n", mrc(15, 0, 0, 0, 0)); + printf("Cache type: %08lx\n", mrc(15, 0, 0, 0, 1)); + printf("TCM Status: %08lx\n", mrc(15, 0, 0, 0, 2)); + printf("TLB Type: %08lx\n", mrc(15, 0, 0, 0, 3)); + printf("Processor Feature Register 0: %08lx\n", mrc(15, 0, 0, 1, 0)); + printf("Processor Feature Register 1: %08lx\n", mrc(15, 0, 0, 1, 1)); + printf("Debug Feature Register 0: %08lx\n", mrc(15, 0, 0, 1, 2)); + printf("Auxiliary Feature Register 0: %08lx\n", mrc(15, 0, 0, 1, 3)); + printf("Memory Model Feature Register 0: %08lx\n", mrc(15, 0, 0, 1, 4)); + printf("Memory Model Feature Register 1: %08lx\n", mrc(15, 0, 0, 1, 5)); + printf("Memory Model Feature Register 2: %08lx\n", mrc(15, 0, 0, 1, 6)); + printf("Memory Model Feature Register 3: %08lx\n", mrc(15, 0, 0, 1, 7)); + printf("Instruction Set Attribute Reg 0: %08lx\n", mrc(15, 0, 0, 2, 0)); + printf("Instruction Set Attribute Reg 1: %08lx\n", mrc(15, 0, 0, 2, 1)); + printf("Instruction Set Attribute Reg 2: %08lx\n", mrc(15, 0, 0, 2, 2)); + printf("Instruction Set Attribute Reg 3: %08lx\n", mrc(15, 0, 0, 2, 3)); + printf("Instruction Set Attribute Reg 4: %08lx\n", mrc(15, 0, 0, 2, 4)); + printf("Instruction Set Attribute Reg 5: %08lx\n", mrc(15, 0, 0, 2, 5)); + printf("Control Register: %08lx\n", mrc(15, 0, 1, 0, 0)); + printf("Auxiliary Control Register: %08lx\n", mrc(15, 0, 1, 0, 1)); + printf("Coprocessor Access Control Reg: %08lx\n", mrc(15, 0, 1, 0, 2)); + printf("Secure Configuration Register: %08lx\n", mrc(15, 0, 1, 1, 0)); + printf("Secure Debug Enable Register: %08lx\n", mrc(15, 0, 1, 1, 1)); + printf("Non-Secure Access Control Reg: %08lx\n", mrc(15, 0, 1, 1, 2)); + printf("Translation Table Base Reg 0: %08lx\n", mrc(15, 0, 2, 0, 0)); + printf("Translation Table Base Reg 1: %08lx\n", mrc(15, 0, 2, 0, 1)); + printf("Translation Table Base Control Reg: %08lx\n", mrc(15, 0, 2, 0, 2)); + printf("Domain Access Control Register: %08lx\n", mrc(15, 0, 3, 0, 0)); + printf("Data Fault Status Register: %08lx\n", mrc(15, 0, 5, 0, 0)); + printf("Instruction Fault Status Register: %08lx\n", mrc(15, 0, 5, 0, 1)); + printf("Fault Address Register: %08lx\n", mrc(15, 0, 6, 0, 0)); + printf("Instruction Fault Address Register: %08lx\n", mrc(15, 0, 6, 0, 2)); + printf("Data Cache Lockdown Register: %08lx\n", mrc(15, 0, 9, 0, 0)); + printf("Instruction Cache Lockdown Register: %08lx\n", mrc(15, 0, 9, 0, 1)); + printf("Data TCM Region Register: %08lx\n", mrc(15, 0, 9, 1, 0)); + printf("Instruction TCM Region Register: %08lx\n", mrc(15, 0, 9, 1, 1)); + printf("Data TCM Non-secure Control Access Reg: %08lx\n", mrc(15, 0, 9, 1, 2)); + printf("Instruction TCM Non-secure Control Access Reg: %08lx\n", mrc(15, 0, 9, 1, 3)); + printf("TCM Selection Register: %08lx\n", mrc(15, 0, 9, 2, 0)); + printf("Cache Behavior Override Register: %08lx\n", mrc(15, 0, 9, 8, 0)); + printf("TLB Lockdown Register: %08lx\n", mrc(15, 0, 10, 0, 0)); + printf("Primary Region Remap Register: %08lx\n", mrc(15, 0, 10, 2, 0)); + printf("Normal Region Remap Register: %08lx\n", mrc(15, 0, 10, 2, 1)); + printf("DMA Ident and Status Register present: %08lx\n", mrc(15, 0, 11, 0, 0)); + printf("DMA Ident and Status Register queued: %08lx\n", mrc(15, 0, 11, 0, 1)); + printf("DMA Ident and Status Register running: %08lx\n", mrc(15, 0, 11, 0, 2)); + printf("DMA Ident and Status Register interrupting: %08lx\n", mrc(15, 0, 11, 0, 3)); + printf("DMA User Accessibility Register: %08lx\n", mrc(15, 0, 11, 1, 0)); + printf("DMA Channel Number Register: %08lx\n", mrc(15, 0, 11, 2, 0)); + printf("DMA Control Register: %08lx\n", mrc(15, 0, 11, 4, 0)); + printf("DMA Internal Start Address Register: %08lx\n", mrc(15, 0, 11, 5, 0)); + printf("DMA External Start Address Register: %08lx\n", mrc(15, 0, 11, 6, 0)); + printf("DMA Internal End Address Register: %08lx\n", mrc(15, 0, 11, 7, 0)); + printf("DMA Channel Status Register: %08lx\n", mrc(15, 0, 11, 8, 0)); + printf("DMA Context ID Register: %08lx\n", mrc(15, 0, 11, 15, 0)); + printf("Secure or Non-Secure Vector Base Address Reg: %08lx\n", mrc(15, 0, 12, 0, 0)); + printf("Monitor Vector Base Address Register: %08lx\n", mrc(15, 0, 12, 0, 1)); + printf("Interrupt Status Register: %08lx\n", mrc(15, 0, 12, 1, 0)); + printf("FCSE PID Register: %08lx\n", mrc(15, 0, 13, 0, 0)); + printf("Context ID Register: %08lx\n", mrc(15, 0, 13, 0, 1)); + printf("User Read/Write Thread and Proc. ID Register: %08lx\n", mrc(15, 0, 13, 0, 2)); + printf("User Read Only Thread and Proc. ID Register: %08lx\n", mrc(15, 0, 13, 0, 3)); + printf("Privileged Only Thread and Proc. ID Register: %08lx\n", mrc(15, 0, 13, 0, 4)); + printf("Peripheral Port Memory Remap Register: %08lx\n", mrc(15, 0, 15, 2, 4)); + printf("Sec User and Non-sec Access Validation Cntr R: %08lx\n", mrc(15, 0, 15, 9, 0)); + printf("Performance Montior Control Register: %08lx\n", mrc(15, 0, 15, 12, 0)); + printf("Cycle Counter Register: %08lx\n", mrc(15, 0, 15, 12, 1)); + printf("Counter Register 0: %08lx\n", mrc(15, 0, 15, 12, 2)); + printf("Counter Register 1: %08lx\n", mrc(15, 0, 15, 12, 3)); + printf("System Validation Cache Size Mask Register: %08lx\n", mrc(15, 0, 15, 14, 0)); + printf("TLB Lockdown Index Register: %08lx\n", mrc(15, 5, 15, 4, 2)); + printf("TLB Lockdown VA Register: %08lx\n", mrc(15, 5, 15, 5, 2)); + printf("TLB Lockdown PA Register: %08lx\n", mrc(15, 5, 15, 6, 2)); + printf("TLB Lockdown Attributes Register: %08lx\n", mrc(15, 5, 15, 7, 2)); +} diff --git a/kernel/fiasco/src/jdb/arm/jdb_mem_dump.cpp b/kernel/fiasco/src/jdb/arm/jdb_mem_dump.cpp new file mode 100644 index 00000000..dd7c56b9 --- /dev/null +++ b/kernel/fiasco/src/jdb/arm/jdb_mem_dump.cpp @@ -0,0 +1,59 @@ +IMPLEMENTATION: + +#include + +#include "irq_alloc.h" +#include "jdb_module.h" +#include "static_init.h" +#include "types.h" + + +//=================== +// Std JDB modules +//=================== + +/** + * 'Mem-Dump' module. + * + * This module handles the 'd' command that + * dumps the memory at the specified address. + */ +class Jdb_mem_dump + : public Jdb_module +{ +public: +private: + char subcmd; + void *address; +}; + +static Jdb_mem_dump jdb_mem_dump INIT_PRIORITY(JDB_MODULE_INIT_PRIO); + +PUBLIC +Jdb_module::Action_code Jdb_mem_dump::action( int cmd, void *&, char const *&, int & ) +{ + if(cmd!=0) + return NOTHING; + + unsigned v = *((unsigned*)((Mword)address & ~0x03)); + printf(" => 0x%08x\n", v); + return NOTHING; +} + +PUBLIC +int const Jdb_mem_dump::num_cmds() const +{ + return 1; +} + +PUBLIC +Jdb_module::Cmd const *const Jdb_mem_dump::cmds() const +{ + static Cmd cs[] = + { { 0, "d", "dump", " address: %x", + "d\tdump memory at specific address", (void*)&address } + }; + + return cs; +} + diff --git a/kernel/fiasco/src/jdb/arm/jdb_perf.cpp b/kernel/fiasco/src/jdb/arm/jdb_perf.cpp new file mode 100644 index 00000000..d98decae --- /dev/null +++ b/kernel/fiasco/src/jdb/arm/jdb_perf.cpp @@ -0,0 +1,62 @@ +INTERFACE [arm]: + +#include "jdb_module.h" + +class Jdb_perf : public Jdb_module +{ +public: + Jdb_perf() FIASCO_INIT; +}; + +// ---------------------------------------------------------------- +IMPLEMENTATION [arm]: + +#include "perf_cnt.h" +#include "static_init.h" + +#include + +PUBLIC +Jdb_module::Action_code +Jdb_perf::action(int cmd, void *&, char const *&, int &) +{ + if (cmd) + return NOTHING; + + printf("\n"); + Mword val = Perf_cnt::read_cycle_cnt();; + printf("Cycle counter: %08lx / %10lu\n", val, val); + for (unsigned i = 0; i < 8; ++i) + { + val = Perf_cnt::read_counter(i); + printf("Event counter %d, type=%03d: %08lx / %10lu\n", + i, Perf_cnt::mon_event_type(i), val, val); + } + + return NOTHING; +} + +PUBLIC +int +Jdb_perf::num_cmds() const +{ return 1; } + + +PUBLIC +Jdb_module::Cmd const * +Jdb_perf::cmds() const +{ + static Cmd cs[] = + { + { 0, "M", "monperf", "", "M\tPerformance monitor events", 0 }, + }; + return cs; +} + +IMPLEMENT +Jdb_perf::Jdb_perf() + : Jdb_module("INFO") +{ +} + +static Jdb_perf jdb_perf INIT_PRIORITY(JDB_MODULE_INIT_PRIO); diff --git a/kernel/fiasco/src/jdb/arm/jdb_ptab-arm.cpp b/kernel/fiasco/src/jdb/arm/jdb_ptab-arm.cpp new file mode 100644 index 00000000..cf96fd15 --- /dev/null +++ b/kernel/fiasco/src/jdb/arm/jdb_ptab-arm.cpp @@ -0,0 +1,208 @@ +IMPLEMENTATION [arm]: + +#include "paging.h" +#include "simpleio.h" + +unsigned Jdb_ptab::max_pt_level = 1; + +// ----------------------------------------------------------------------- +IMPLEMENTATION [arm && armv5]: + +IMPLEMENT inline +unsigned +Jdb_ptab::entry_valid(Mword entry, unsigned) +{ return entry & 0x03; } + +IMPLEMENT inline +unsigned +Jdb_ptab::entry_is_pt_ptr(Mword entry, unsigned level, + unsigned *entries, unsigned *next_level) +{ + if (level > 0 || (entry & 0x03) == 0x02) + return 0; + + if ((entry & 0x03) == 0x01) + *entries = 256; // coarse (1KB) + else + *entries = 1024; // fine (4KB) + + *next_level = 1; + return 1; +} + +PRIVATE inline +bool +Jdb_ptab::is_cached(Mword entry, unsigned level) +{ + if (level == 0 && (entry & 3) != 2) + return true; /* No caching options on PDEs */ + return (entry & Page::Cache_mask) == Page::CACHEABLE; +} + +PRIVATE inline +bool +Jdb_ptab::is_executable(Mword entry) +{ + (void)entry; + return 1; +} + +PRIVATE inline +char +Jdb_ptab::ap_char(unsigned ap) +{ + return ap & 0x2 ? (ap & 0x1) ? 'w' : 'r' + : (ap & 0x1) ? 'W' : 'R'; +} + + +// ----------------------------------------------------------------------- +IMPLEMENTATION [arm && (armv6 || armv7)]: + +IMPLEMENT inline NEEDS ["paging.h"] +unsigned +Jdb_ptab::entry_valid(Mword entry, unsigned) +{ return (entry & 3) == 1 || (entry & 3) == 2; } + +IMPLEMENT inline +unsigned +Jdb_ptab::entry_is_pt_ptr(Mword entry, unsigned level, + unsigned *entries, unsigned *next_level) +{ + if (level > 0 || (entry & 0x03) == 0x02) + return 0; + + *entries = 256; // coarse (1KB) + *next_level = 1; + return 1; +} + +PRIVATE inline +bool +Jdb_ptab::is_cached(Mword entry, unsigned level) +{ + if (level == 0) + { + if ((entry & 3) == 2) + return (entry & 0x700c) == 0x5004; + return true; + } + + return (entry & Page::Cache_mask) == Page::CACHEABLE; +} + +PRIVATE inline +bool +Jdb_ptab::is_executable(Mword entry) +{ + return (entry & 3) == 2 || (entry & 3) == 1; +} + +PRIVATE inline +char +Jdb_ptab::ap_char(unsigned ap) +{ + switch (ap & 0x23) + { + case 0: return '-'; + case 1: return 'W'; + case 2: return 'r'; + case 3: return 'w'; + case 0x21: return 'R'; + case 0x22: case 0x23: return 'r'; + default: return '?'; + }; +} + +// ----------------------------------------------------------------------- +IMPLEMENTATION [arm]: + +IMPLEMENT inline NEEDS ["paging.h"] +Address +Jdb_ptab::entry_phys(Mword entry, unsigned level) +{ + unsigned t = entry & 0x03; + if (level == 0) + { + switch(t) + { + default: + case 0: + return 0; + case 1: + return entry & 0xfffffc00; + case 2: + return entry & 0xfff00000; + case 3: + return entry & 0xfffff000; + } + } + else + { + switch (t) + { + default: + case 0: + return 0; + case 1: + return entry & 0xffff0000; + case 2: + return entry & 0xfffff000; + case 3: + return entry & 0xfffffc00; + } + } +} + +IMPLEMENT +void +Jdb_ptab::print_entry(Mword entry, unsigned level) +{ + if (dump_raw) + printf("%08lx", entry); + else + { + if (!entry_valid(entry,level)) + { + putstr(" - "); + return; + } + Address phys = entry_phys(entry, level); + + unsigned t = entry & 0x03; + unsigned ap = entry >> 4; + char ps; + if (level == 0) + switch (t) + { + case 1: ps = 'C'; break; + case 2: ps = 'S'; ap = entry >> 10; break; + case 3: ps = 'F'; break; + default: ps = 'U'; break; + } + else + switch (t) + { + case 1: ps = 'l'; break; + case 2: ps = 's'; break; + case 3: ps = 't'; break; + default: ps = 'u'; break; + } + + printf("%05lx%s%c", phys >> Config::PAGE_SHIFT, + is_cached(entry, level) + ? "-" : JDB_ANSI_COLOR(lightblue) "n" JDB_ANSI_END, + ps); + if (level == 0 && t != 2) + putchar('-'); + else + printf("%s%c" JDB_ANSI_END, + is_executable(entry) ? "" : JDB_ANSI_COLOR(red), + ap_char(ap)); + } +} + +PUBLIC +unsigned long +Jdb_ptab::rows() const +{ return entries/8; } diff --git a/kernel/fiasco/src/jdb/arm/jdb_reg_dump.cpp b/kernel/fiasco/src/jdb/arm/jdb_reg_dump.cpp new file mode 100644 index 00000000..d12bc42a --- /dev/null +++ b/kernel/fiasco/src/jdb/arm/jdb_reg_dump.cpp @@ -0,0 +1,43 @@ +IMPLEMENTATION: + +#include +#include "jdb.h" + +/** + * 'Reg-Dump' module. + * + * This module handles the 'r' command that + * dumps the register contents at kernel entry. + */ +class J_reg_dump : public Jdb_module +{ +public: + J_reg_dump() FIASCO_INIT; + Jdb::Action action(); +}; + + +IMPLEMENT +J_reg_dump::J_reg_dump() + : Jdb_module( Jdb::top(), "regs", "dumps all register contents" , 'r' ) +{} + +IMPLEMENT +Jdb::Action J_reg_dump::action() +{ + Jdb_regs *r = Jdb::registers(); + printf("\nRegister dump\n" + "0: %08x %08x %08x %08x %08x %08x %08x %08x\n" + "8: %08x %08x %08x %08x %08x %08x %08x %08x\n", + r->r0,r->r1,r->r2,r->r3,r->r4,r->r5,r->r6, + r->r7,r->r8,r->r9,r->r10,r->r11,r->r12,r->r13, + r->r14,r->r15); + + return Jdb::NOTHING; +} + + + +J_reg_dump register_dumper; + + diff --git a/kernel/fiasco/src/jdb/arm/jdb_tcb-arm.cpp b/kernel/fiasco/src/jdb/arm/jdb_tcb-arm.cpp new file mode 100644 index 00000000..3f941e7a --- /dev/null +++ b/kernel/fiasco/src/jdb/arm/jdb_tcb-arm.cpp @@ -0,0 +1,77 @@ +IMPLEMENTATION [arm]: + +#include "config.h" + +EXTENSION class Jdb_tcb +{ + enum + { + Disasm_x = 41, + Disasm_y = 11, + Stack_y = 17, + }; + +}; + +IMPLEMENT +void Jdb_tcb::print_entry_frame_regs(Thread *) +{ + Jdb_entry_frame *ef = Jdb::get_entry_frame(Jdb::current_cpu); + int from_user = ef->from_user(); + + printf("Registers (before debug entry from %s mode):\n" + "[0] %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n" + "[8] %08lx %08lx %08lx %08lx %08lx %08lx %08lx %s%08lx\033[m\n" + "upsr = %08lx\n", + from_user ? "user" : "kernel", + ef->r[0], ef->r[1],ef->r[2], ef->r[3], + ef->r[4], ef->r[5],ef->r[6], ef->r[7], + ef->r[8], ef->r[9],ef->r[10], ef->r[11], + ef->r[12], ef->usp, ef->ulr, Jdb::esc_iret, ef->pc, + ef->psr); +} + +IMPLEMENT +void +Jdb_tcb::info_thread_state(Thread *t) +{ + Jdb_tcb_ptr current((Address)t->get_kernel_sp()); + + printf("PC=%s%08lx\033[m USP=%08lx\n", + Jdb::esc_emph, current.top_value(-2), current.top_value(-5)); + printf("[0] %08lx %08lx %08lx %08lx [4] %08lx %08lx %08lx %08lx\n", + current.top_value(-18), current.top_value(-17), + current.top_value(-16), current.top_value(-15), + current.top_value(-14), current.top_value(-13), + current.top_value(-12), current.top_value(-11)); + printf("[8] %08lx %08lx %08lx %08lx [c] %08lx %08lx %08lx %08lx\n", + current.top_value(-10), current.top_value(-9), + current.top_value(-8), current.top_value(-7), + current.top_value(-6), current.top_value(-4), + current.top_value(-3), current.top_value(-1)); +} + +IMPLEMENT +void +Jdb_tcb::print_return_frame_regs(Jdb_tcb_ptr const &, Address) +{} + +IMPLEMENT +bool +Jdb_stack_view::edit_registers() +{ return false; } + +IMPLEMENT inline +bool +Jdb_tcb_ptr::is_user_value() const +{ + return _offs >= Context::Size - 5 * sizeof(Mword); +} + +IMPLEMENT inline +const char * +Jdb_tcb_ptr::user_value_desc() const +{ + const char *desc[] = { "PSR", "PC", "KLR", "ULR", "SP" }; + return desc[(Context::Size - _offs) / sizeof(Mword) - 1]; +} diff --git a/kernel/fiasco/src/jdb/arm/jdb_trace_set-arm.cpp b/kernel/fiasco/src/jdb/arm/jdb_trace_set-arm.cpp new file mode 100644 index 00000000..af3aa3dd --- /dev/null +++ b/kernel/fiasco/src/jdb/arm/jdb_trace_set-arm.cpp @@ -0,0 +1,65 @@ +IMPLEMENTATION: + +extern "C" void sys_ipc_wrapper (void); +extern "C" void sys_ipc_log_wrapper (void); +extern "C" void sys_ipc_trace_wrapper (void); + + +typedef void (*Sys_call)(void); +extern "C" Sys_call sys_call_table[]; + + +IMPLEMENT void +Jdb_set_trace::next_preiod_tracing(bool /*enable*/) +{ +} + +IMPLEMENT void +Jdb_set_trace::page_fault_tracing(bool /*enable*/) +{ +} + +IMPLEMENT void +Jdb_set_trace::ipc_tracing(Mode mode) +{ + switch (mode) + { + case Off: + Jdb_ipc_trace::_trace = 0; + Jdb_ipc_trace::_log = 0; + Jdb_ipc_trace::_cshortcut = 0; + Jdb_ipc_trace::_slow_ipc = 0; + sys_call_table[2] = sys_ipc_wrapper; + break; + case Log: + Jdb_ipc_trace::_trace = 0; + Jdb_ipc_trace::_log = 1; + Jdb_ipc_trace::_log_to_buf = 0; + Jdb_ipc_trace::_cshortcut = 0; + Jdb_ipc_trace::_slow_ipc = 0; + sys_call_table[2] = sys_ipc_log_wrapper; + break; + case Log_to_buf: + Jdb_ipc_trace::_trace = 0; + Jdb_ipc_trace::_log = 1; + Jdb_ipc_trace::_log_to_buf = 1; + Jdb_ipc_trace::_cshortcut = 0; + Jdb_ipc_trace::_slow_ipc = 0; + sys_call_table[2] = sys_ipc_log_wrapper; + break; + case Trace: + Jdb_ipc_trace::_trace = 1; + Jdb_ipc_trace::_cshortcut = 0; + Jdb_ipc_trace::_log = 0; + Jdb_ipc_trace::_slow_ipc = 0; + sys_call_table[2] = sys_ipc_trace_wrapper; + break; + case Use_c_short_cut: + break; + case Use_slow_path: + Jdb_ipc_trace::_slow_ipc = 1; + sys_call_table[2] = sys_ipc_wrapper; + break; + } +} + diff --git a/kernel/fiasco/src/jdb/arm/jdb_vm.cpp b/kernel/fiasco/src/jdb/arm/jdb_vm.cpp new file mode 100644 index 00000000..1ccf454d --- /dev/null +++ b/kernel/fiasco/src/jdb/arm/jdb_vm.cpp @@ -0,0 +1,67 @@ +IMPLEMENTATION [tz]: + +#include +#include +#include + +#include "jdb.h" +#include "jdb_core.h" +#include "jdb_module.h" +#include "jdb_screen.h" +#include "jdb_kobject.h" +#include "kernel_console.h" +#include "keycodes.h" +#include "simpleio.h" +#include "static_init.h" +#include "vm.h" + +class Jdb_vm : public Jdb_kobject_handler +{ +public: + Jdb_vm() FIASCO_INIT; +}; + +IMPLEMENT +Jdb_vm::Jdb_vm() + : Jdb_kobject_handler(Vm::static_kobj_type) +{ + Jdb_kobject::module()->register_handler(this); +} + +PUBLIC +bool +Jdb_vm::show_kobject(Kobject_common *o, int lvl) +{ + Kobject::dcast(o)->dump_machine_state(); + if (lvl) + { + Jdb::getchar(); + return true; + } + + return false; +} + +PUBLIC +char const * +Jdb_vm::kobject_type() const +{ + return JDB_ANSI_COLOR(yellow) "Vm" JDB_ANSI_COLOR(default); +} + +PUBLIC +int +Jdb_vm::show_kobject_short(char *buf, int max, Kobject_common *o) +{ + return Kobject::dcast(o)->show_short(buf, max); +} + +static Jdb_vm jdb_vm INIT_PRIORITY(JDB_MODULE_INIT_PRIO); + +static +bool +filter_vm(Kobject_common const *o) +{ + return Kobject::dcast(o); +} +static Jdb_kobject_list::Mode INIT_PRIORITY(JDB_MODULE_INIT_PRIO) tnt("[Vms]", filter_vm); diff --git a/kernel/fiasco/src/jdb/ia32/32/jdb_bp-ia32.cpp b/kernel/fiasco/src/jdb/ia32/32/jdb_bp-ia32.cpp new file mode 100644 index 00000000..69a7b5fe --- /dev/null +++ b/kernel/fiasco/src/jdb/ia32/32/jdb_bp-ia32.cpp @@ -0,0 +1,13 @@ +INTERFACE: + +EXTENSION class Jdb_bp +{ + enum + { + Val_enter = 0x0000ff00, + Val_leave = 0x00000000, + Val_test_sstep = 0x00004000, + Val_test = 0x0000000f, + Val_test_other = 0x0000e00f, + }; +}; diff --git a/kernel/fiasco/src/jdb/ia32/32/jdb_kern_info-bench-ia32-32.cpp b/kernel/fiasco/src/jdb/ia32/32/jdb_kern_info-bench-ia32-32.cpp new file mode 100644 index 00000000..217eadf8 --- /dev/null +++ b/kernel/fiasco/src/jdb/ia32/32/jdb_kern_info-bench-ia32-32.cpp @@ -0,0 +1,485 @@ +IMPLEMENTATION: + +#include +#include "cpu.h" +#include "div32.h" +#include "gdt.h" +#include "simpleio.h" +#include "static_init.h" +#include "timer_tick.h" + +static void +Jdb_kern_info_bench::show_time(Unsigned64 time, Unsigned32 rounds, + const char *descr) +{ + Unsigned64 cycs = div32(time, rounds); + printf(" %-24s %6lld.%lld cycles\n", + descr, cycs, div32(time-cycs*rounds, rounds/10)); +} + +IMPLEMENT inline +Unsigned64 +Jdb_kern_info_bench::get_time_now() +{ return Cpu::rdtsc(); } + +#define inst_wbinvd \ + asm volatile ("wbinvd") + +#define inst_invlpg \ + asm volatile ("invlpg %0" \ + : : "m" (*(char*)Mem_layout::Kmem_tmp_page_1)) + +#define inst_read_cr3 \ + asm volatile ("mov %%cr3,%0" \ + : "=r"(dummy)) + +#define inst_reload_cr3 \ + asm volatile ("mov %%cr3,%0; mov %0,%%cr3" \ + : "=r"(dummy)) + +#define inst_clts \ + asm volatile ("clts") + +#define inst_cli_sti \ + asm volatile ("cli; sti") + +#define inst_set_cr0_ts \ + asm volatile ("mov %%cr0,%0; or %1,%0; mov %0,%%cr0" \ + : "=r" (dummy) : "i" (CR0_TS)) + +#define inst_push_pop \ + asm volatile ("push %eax; pop %eax") + +#define inst_pushf_pop \ + asm volatile ("pushf; pop %%eax" : : : "eax") + +#define inst_in8_pic \ + asm volatile ("inb $0x21, %%al" : "=a" (dummy)) + +#define inst_in8_80 \ + asm volatile ("inb $0x80, %%al" : "=a" (dummy)) + +#define inst_out8_pic \ + asm volatile ("outb %%al, $0x21" : : "a" (0xff)) + +#define inst_apic_timer_read \ + (volatile Unsigned32)Apic::timer_reg_read() + +#define BENCH(name, instruction, rounds) \ + do \ + { \ + time = Cpu::rdtsc(); \ + for (i=rounds; i; i--) \ + instruction; \ + time = Cpu::rdtsc() - time; \ + show_time (time, rounds, name); \ + } while (0) + + +#include "apic.h" +#include "cpu.h" + +IMPLEMENT +void +Jdb_kern_info_bench::show_arch() +{ + Unsigned64 time; + Mword dummy; + Mword cr0, pic; + Unsigned32 time_reload_cr3, time_invlpg; + register int i; + Gdt *gdt = Cpu::boot_cpu()->get_gdt(); + Unsigned32 flags = Proc::cli_save(); + + if (!Cpu::boot_cpu()->tsc()) + return; + + // we need a cached, non-global mapping for measuring the time to load + // TLB entries + Address phys = Kmem::virt_to_phys((void*)Mem_layout::Tbuf_status_page); + Kmem::map_phys_page(phys, Mem_layout::Jdb_bench_page, true, false); + + { + time = Cpu::rdtsc(); + asm volatile ("mov $10000000,%%ecx; .align 4;\n\t" + "1:dec %%ecx; jnz 1b" : : : "ecx"); + time = Cpu::rdtsc() - time; + show_time(time, 10000000, "1:dec ECX, jnz 1b"); + } + BENCH("wbinvd", inst_wbinvd, 5000); + BENCH("invlpg", inst_invlpg, 200000); + time_invlpg = time; + BENCH("read CR3", inst_read_cr3, 200000); + BENCH("reload CR3", inst_reload_cr3, 200000); + time_reload_cr3 = time; + cr0 = Cpu::get_cr0(); + BENCH("clts", inst_clts, 200000); + BENCH("cli + sti", inst_cli_sti, 200000); + Proc::cli(); + BENCH("set CR0.ts", inst_set_cr0_ts, 200000); + Cpu::set_cr0(cr0); + pic = Io::in8(0x21); + BENCH("in8(PIC)", inst_in8_pic, 200000); + BENCH("in8(iodelay)", inst_in8_80, 200000); + BENCH("out8(PIC)", inst_out8_pic, 200000); + Io::out8(pic, 0x21); + { + // read ES segment descriptor + time = Cpu::rdtsc(); + asm volatile ("mov $200000,%%ebx\n\t" + ".align 8; 1: mov %%es, %%eax; dec %%ebx; jnz 1b" + : : : "eax", "ebx"); + time = Cpu::rdtsc() - time; + show_time(time, 200000, "get ES"); + } + { + // set ES segment descriptor and access memory through the ES segment + time = Cpu::rdtsc(); + asm volatile ("mov $200000,%%ebx \n\t" + ".align 8 \n\t" + "1: \n\t" + "mov %%eax, %%es \n\t" + "dec %%ebx \n\t" + "mov %%es:(%c1),%%edi \n\t" + "jnz 1b \n\t" + : + : "a"(Gdt::gdt_data_kernel | Gdt::Selector_kernel), + "i"(Mem_layout::Kernel_image) + : "ebx", "edi"); + time = Cpu::rdtsc() - time; + show_time(time, 200000, "set ES + load ES:mem"); + } + { + // write a GDT entry, set ES segment descriptor to this gdt entry + // and access memory through the ES segment + Unsigned32 *gdt_e = (Unsigned32*)&(*gdt)[Gdt::gdt_data_kernel/8]; + time = Cpu::rdtsc(); + asm volatile ("mov $200000,%%ebx \n\t" + ".align 16 \n\t" + "1: \n\t" + "mov %%eax, (%%esi) \n\t" + "mov %%ecx, 4(%%esi) \n\t" + "mov %%edx, %%es \n\t" + "dec %%ebx \n\t" + "mov %%es:(%c4),%%edi \n\t" + "jnz 1b \n\t" + : + : "a"(gdt_e[0]), "c"(gdt_e[1]), + "d"(Gdt::gdt_data_kernel | Gdt::Selector_kernel), + "S"(gdt->entries() + Gdt::gdt_data_kernel/8), + "i"(Mem_layout::Kernel_image) + : "ebx", "edi"); + time = Cpu::rdtsc() - time; + show_time(time, 200000, "modify ES + load ES:mem"); + } + { + // Write "1: int 0x1f ; jmp 1b" to the last 4 bytes of the Tbuf status + // page (which is accessible by user mode), set IDT entry #0x1f, set + // TSS.esp0 and do "iret ; int 0x1f". Take care that the user code + // segment is loaded with limit = 0xffffffff if small spaces are active + Idt::set_writable(true); + Gdt_entry orig = (*gdt)[Gdt::gdt_code_user/8]; + Unsigned32 *gdt_e = (Unsigned32*)&(*gdt)[Gdt::gdt_code_user/8]; + gdt_e[0] = 0x0000FFFF; + gdt_e[1] = 0x00CFFB00; + asm volatile ("pushf \n\t" + "push %c3 \n\t" // save IDT entry low + "push %c3+4 \n\t" // save IDT entry high + "push %%ds \n\t" + "push %%es \n\t" + "push %%fs \n\t" + "push %%gs \n\t" + "mov %%esp, %%edi \n\t" // save esp + "andl $0xffffffc0, %%esp \n\t" // cache line align esp + "movl $(%c4*256+0xfceb00cd), %c2 \n\t" + "mov $1f, %%eax \n\t" // '1: int 0x1f; jmp 1b' + "and $0x0000ffff, %%eax \n\t" + "or $0x00080000, %%eax \n\t" + "mov %%eax, %c3 \n\t" // change IDT entry low + "mov $1f, %%eax \n\t" + "and $0xffff0000, %%eax \n\t" + "or $0x0000ee00, %%eax \n\t" + "mov %%eax, %c3+4 \n\t" // change IDT entry high + "mov (%%ecx), %%ebx \n\t" // save kernel esp + "push $%c5 \n\t" // user ss + "push $0 \n\t" // user esp + "push $0x3082 \n\t" // user eflags (IOPL3) + "push $%c6 \n\t" // user cs + "push $%c2 \n\t" // user eip + "mov %%esp, (%%ecx) \n\t" // change kernel esp + "mov $%c5, %%eax \n\t" + "mov %%eax, %%ds \n\t" // ensure dpl3 at ds + "mov %%eax, %%es \n\t" // ensure dpl3 at es + "mov %%eax, %%fs \n\t" // ensure dpl3 at fs + "mov %%eax, %%gs \n\t" // enusre dpl3 at gs + + "rdtsc \n\t" + "mov %%eax, %%esi \n\t" + "movl $200001, %%eax \n\t" + + ".align 4 \n\t" + "1: \n\t" + "dec %%eax \n\t" + "jz 2f \n\t" + "iret \n\t" + + "2: \n\t" + "rdtsc \n\t" + "mov %%edi, %%esp \n\t" // restore esp + "sub %%esi, %%eax \n\t" + "pop %%gs \n\t" + "pop %%fs \n\t" + "pop %%es \n\t" + "pop %%ds \n\t" + "sub %%edx, %%edx \n\t" + "mov %%ebx, (%%ecx) \n\t" // restore kernel esp + "pop %c3+4 \n\t" // restore IDT entry high + "pop %c3 \n\t" // restore IDT entry low + "popf \n\t" + + : "=A"(time),"=c"(dummy) + : "i"(Mem_layout::Tbuf_status_page + Config::PAGE_SIZE-4), + "i"(Mem_layout::Idt + (0x1f<<3)), + "i"(0x1f), + "i"(Gdt::gdt_data_user | Gdt::Selector_user), + "i"(Gdt::gdt_code_user | Gdt::Selector_user), + "c"((Address)Cpu::boot_cpu()->kernel_sp()) + : "ebx", "esi", "edi", "memory"); + Idt::set_writable(false); + (*gdt)[Gdt::gdt_code_user/8] = orig; + show_time(time, 200000, "int + iret"); + } + if (Cpu::have_sysenter()) + { + // Set Sysenter MSR, write "sysenter" to the last two bytes of the + // Tbuf status page (which is accessible from usermode) and do "sysexit ; + // sysenter". Gdt doesn't care us since sysexit loads a flat segment. + // The sysenter esp also doesn't care us since we don't access esp + // inside the measurement loop. + asm volatile ("pushf \n\t" + "mov $0x176, %%ecx \n\t" + "rdmsr \n\t" + "mov %%eax, %%ebx \n\t" // save sysenter eip + "mov $1f, %%eax \n\t" + "wrmsr \n\t" // change sysenter eip + "mov %%esp, %%edi \n\t" // save esp + "movw $0x340f, %c1 \n\t" + "rdtsc \n\t" + "mov %%eax, %%esi \n\t" + "movl $200001, %%eax \n\t" + "mov $%c1, %%edx \n\t" + + ".align 8 \n\t" + "1: \n\t" + "dec %%eax \n\t" + "jz 2f \n\t" + "sysexit \n\t" + + "2: \n\t" + "rdtsc \n\t" + "sub %%eax, %%esi \n\t" + "mov $0x176, %%ecx \n\t" + "mov %%ebx, %%eax \n\t" + "sub %%edx, %%edx \n\t" + "wrmsr \n\t" + + "mov %%esi, %%eax \n\t" + "neg %%eax \n\t" + "mov %%edi, %%esp \n\t" // restore esp + "popf \n\t" + : "=A"(time) + : "i"(Mem_layout::Tbuf_status_page + Config::PAGE_SIZE-2) + : "ebx", "ecx", "esi", "edi", "memory"); + show_time(time, 200000, "sysenter + sysexit"); + } + if (Cpu::have_sysenter()) + { + // Set Sysenter MSR, write "sysenter" to the last two bytes of the + // Tbuf status page (which is accessible from usermode) and do "iret ; + // sysenter". + asm volatile ("pushf \n\t" + "push %%ebp \n\t" + "push %%ds \n\t" + "push %%es \n\t" + "push %%fs \n\t" + "push %%gs \n\t" + "mov $0x176, %%ecx \n\t" + "rdmsr \n\t" + "mov %%eax, %%ebx \n\t" // save sysenter eip + "mov $1f, %%eax \n\t" + "wrmsr \n\t" // change sysenter eip + "mov %%esp, %%edi \n\t" // save esp + "andl $0xffffffc0, %%esp \n\t" // cache line align esp + "movw $0x340f, %c1 \n\t" // 'sysenter' + "push $%c3 \n\t" // user ss + "push $0 \n\t" // user esp + "push $0x3082 \n\t" // user flags + "push $%c2 \n\t" // user cs + "push $%c1 \n\t" // user eip + "mov $0x175, %%ecx \n\t" + "rdmsr \n\t" + "mov %%eax, %%ebp \n\t" // save sysenter esp + "mov %%esp, %%eax \n\t" + "wrmsr \n\t" // change sysenter esp + "mov $%c3, %%eax \n\t" + "mov %%eax, %%ds \n\t" // ensure dpl3 at ds + "mov %%eax, %%es \n\t" // ensure dpl3 at es + "mov %%eax, %%fs \n\t" // ensure dpl3 at fs + "mov %%eax, %%gs \n\t" // ensure dpl3 at gs + + "rdtsc \n\t" + "mov %%eax, %%esi \n\t" + "movl $200001, %%eax \n\t" + + ".align 8 \n\t" + "1: \n\t" + "dec %%eax \n\t" + "jz 2f \n\t" + "iret \n\t" + + "2: \n\t" + "rdtsc \n\t" + "sub %%eax, %%esi \n\t" + "sub %%edx, %%edx \n\t" + "mov $0x176, %%ecx \n\t" + "mov %%ebx, %%eax \n\t" + "wrmsr \n\t" // restore sysenter eip + "mov $0x175, %%ecx \n\t" + "mov %%ebp, %%eax \n\t" + "wrmsr \n\t" // restore sysenter esp + + "mov %%edi, %%esp \n\t" // restore esp + "pop %%gs \n\t" + "pop %%fs \n\t" + "pop %%es \n\t" + "pop %%ds \n\t" + "mov %%esi, %%eax \n\t" + "neg %%eax \n\t" + "pop %%ebp \n\t" + "popf \n\t" + : "=A"(time) + : "i"(Mem_layout::Tbuf_status_page + Config::PAGE_SIZE-2), + "i"(Gdt::gdt_code_user | Gdt::Selector_user), + "i"(Gdt::gdt_data_user | Gdt::Selector_user) + : "ebx", "ecx", "esi", "edi", "memory"); + show_time(time, 200000, "sysenter + iret"); + } + if (Cpu::have_syscall()) + { + // Enable syscall/sysret, set Syscall MSR, write "syscall" to the last + // two bytes of the Tbuf status page (which is accessible from usermode) + // and do "sysret ; syscall". Gdt doesn't care us since sysret loads a + // flat segment. Sysret enables the interrupts again so make sure that + // we don't receive a timer interrupt. + Timer_tick::disable(0); + Proc::sti(); + Proc::irq_chance(); + asm volatile ("pushf \n\t" + "push %%ebp \n\t" + "mov $0xC0000080, %%ecx \n\t" + "sub %%edx, %%edx \n\t" + "movl $1, %%eax \n\t" // enable syscall + "wrmsr \n\t" + "mov $0xC0000081, %%ecx \n\t" + "rdmsr \n\t" + "mov %%eax, %%ebx \n\t" // save IA32_STAR + "mov %%edx, %%ebp \n\t" + "mov $1f, %%eax \n\t" // syscall eip + "mov $0x00180008, %%edx \n\t" // syscall cs+ss + "wrmsr \n\t" + "mov %%esp, %%edi \n\t" + "movw $0x050f, %c1 \n\t" + "rdtsc \n\t" + "mov %%eax, %%esi \n\t" + "movl $200001, %%eax \n\t" + "mov $(%c1+2), %%ecx \n\t" + + ".align 8 \n\t" + "1: \n\t" + "dec %%eax \n\t" + "jz 2f \n\t" + "sub $2, %%ecx \n\t" + "sysret \n\t" + + "2: \n\t" + "rdtsc \n\t" + "sub %%eax, %%esi \n\t" + "mov $0xC0000081, %%ecx \n\t" + "mov %%ebx, %%eax \n\t" + "mov %%ebp, %%edx \n\t" + "wrmsr \n\t" // restore IA32_STAR + + "mov %%esi, %%eax \n\t" + "neg %%eax \n\t" + "mov %%edi, %%esp \n\t" + "pop %%ebp \n\t" + "sub %%edx, %%edx \n\t" + "popf \n\t" + : "=A"(time) + : "i"(Mem_layout::Tbuf_status_page + Config::PAGE_SIZE-2) + : "ebx", "ecx", "esi", "edi", "memory"); + Proc::cli(); + Timer_tick::enable(0); + show_time(time, 200000, "syscall + sysret"); + } + BENCH("push EAX + pop EAX", inst_push_pop, 200000); + BENCH("push flags + pop EAX", inst_pushf_pop, 200000); + { + time = Cpu::rdtsc(); + asm volatile ("mov $200000,%%ebx\n\t" + ".align 4; 1: rdtsc; dec %%ebx; jnz 1b" + : : : "eax", "ebx", "edx"); + time = Cpu::rdtsc() - time; + show_time(time, 200000, "rdtsc"); + } + if (Cpu::boot_cpu()->local_features() & Cpu::Lf_rdpmc) + { + time = Cpu::rdtsc(); + asm volatile ("mov $200000,%%ebx; movl $0x00000000,%%ecx\n\t" + ".align 4; 1: rdpmc; dec %%ebx; jnz 1b" + : : : "eax", "ebx", "ecx", "edx"); + time = Cpu::rdtsc() - time; + show_time(time, 200000, "rdpmc(0)"); + } + if (Cpu::boot_cpu()->local_features() & Cpu::Lf_rdpmc32) + { + time = Cpu::rdtsc(); + asm volatile ("mov $200000,%%ebx; movl $0x80000000,%%ecx\n\t" + ".align 4; 1: rdpmc; dec %%ebx; jnz 1b" + : : : "eax", "ebx", "ecx", "edx"); + time = Cpu::rdtsc() - time; + show_time(time, 200000, "rdpmc32(0)"); + } + if (Config::apic) + { + BENCH("APIC timer read", (void)inst_apic_timer_read, 200000); + } + { + time = Cpu::rdtsc(); + for (i=200000; i; i--) + asm volatile ("invlpg %c2 \n\t" + "mov %c2, %1 \n\t" + : "=r" (dummy), "=r" (dummy) + : "i"(Mem_layout::Jdb_bench_page)); + time = Cpu::rdtsc() - time - time_invlpg; + show_time (time, 200000, "load data TLB (4k)"); + } + { + // asm ("1: mov %%cr3,%%edx; mov %%edx, %%cr3; dec %%eax; jnz 1b; ret") + *(Unsigned32*)(Mem_layout::Jdb_bench_page + 0xff0) = 0x0fda200f; + *(Unsigned32*)(Mem_layout::Jdb_bench_page + 0xff4) = 0x7548da22; + *(Unsigned32*)(Mem_layout::Jdb_bench_page + 0xff8) = 0xc3f7; + + Mem::barrier(); + time = Cpu::rdtsc(); + asm volatile ("call *%%ecx" + : "=a"(dummy) + : "c"(Mem_layout::Jdb_bench_page + 0xff0), "a"(200000) + : "edx"); + + time = Cpu::rdtsc() - time - time_reload_cr3; + show_time (time, 200000, "load code TLB (4k)"); + } + + Proc::sti_restore(flags); +} diff --git a/kernel/fiasco/src/jdb/ia32/32/jdb_kern_info-bench.txt b/kernel/fiasco/src/jdb/ia32/32/jdb_kern_info-bench.txt new file mode 100644 index 00000000..d24f14a5 --- /dev/null +++ b/kernel/fiasco/src/jdb/ia32/32/jdb_kern_info-bench.txt @@ -0,0 +1,111 @@ +Some results of 'kb' on different CPUs +************************************** + +o 6:4:2:0 (Athlon [Thunderbird]), 807MHz, 256KB L2 cache: + 1:dec ECX, jnz 1b 2.0 cycles + wbinvd 46040.9 cycles + invlpg 92.0 cycles + read CR3 3.0 cycles + reload CR3 102.0 cycles + clts 12.0 cycles + cli + sti 9.0 cycles + set CR0.ts 62.0 cycles + in8(PIC) 1085.4 cycles + in8(iodelay) 1085.4 cycles + out8(PIC) 1127.0 cycles + get ES 2.0 cycles + set ES + load ES:mem 9.0 cycles + modify ES + load ES:mem 18.0 cycles + int + iret 202.0 cycles + sysenter + sysexit 67.0 cycles + sysenter + iret 107.0 cycles + syscall + sysret 64.0 cycles + push EAX + pop EAX 5.6 cycles + push flags + pop EAX 4.0 cycles + rdtsc 11.0 cycles + rdpmc(0) 11.0 cycles + APIC timer read 29.0 cycles + load data TLB (4k) 73.0 cycles + load code TLB (4k) 54.0 cycles + +o F:2:9:A (Celeron [Northwood]), 1995MHz, 128KB L2 cache + 1:dec ECX, jnz 1b 1.5 cycles + wbinvd 117953.0 cycles + invlpg 520.0 cycles + read CR3 8.0 cycles + reload CR3 295.6 cycles + clts 276.0 cycles + cli + sti 88.0 cycles + set CR0.ts 292.0 cycles + in8(PIC) 1765.8 cycles + in8(iodelay) 1882.2 cycles + out8(PIC) 1685.9 cycles + get ES 8.0 cycles + set ES + load ES:mem 16.0 cycles + modify ES + load ES:mem 52.0 cycles + int + iret 932.0 cycles + sysenter + sysexit 146.0 cycles + sysenter + iret 509.6 cycles + push EAX + pop EAX 8.2 cycles + push flags + pop EAX 8.0 cycles + rdtsc 80.0 cycles + rdpmc(0) 153.3 cycles + rdpmc32(0) 63.2 cycles + APIC timer read 134.9 cycles + load data TLB (4k) 48.0 cycles + load code TLB (4k) 32.3 cycles + +o F:4:1:0 (Celeron 4E [Prescott/Nocona]), 2933MHz, 256KB L2 cache: + 1:dec ECX, jnz 1b 1.5 cycles + wbinvd 237504.0 cycles + invlpg 512.0 cycles + read CR3 23.4 cycles + reload CR3 424.0 cycles + clts 356.0 cycles + cli + sti 122.1 cycles + set CR0.ts 460.0 cycles + in8(PIC) 3084.8 cycles + in8(iodelay) 1838.5 cycles + out8(PIC) 3077.6 cycles + get ES 9.0 cycles + set ES + load ES:mem 27.5 cycles + modify ES + load ES:mem 67.5 cycles + int + iret 796.0 cycles + sysenter + sysexit 212.0 cycles + sysenter + iret 518.0 cycles + push EAX + pop EAX 7.0 cycles + push flags + pop EAX 9.0 cycles + rdtsc 100.0 cycles + rdpmc(0) 238.0 cycles + rdpmc32(0) 91.0 cycles + APIC timer read 181.4 cycles + load data TLB (4k) 36.0 cycles + load code TLB (4k) 55.9 cycles + +o F:3:3:0 (Pentium 4E [Prescott/Nocona]), 2793.189 MHz (native), 1024 KB L2 + 1:dec ECX, jnz 1b 1.5 cycles + wbinvd 466357.2 cycles + invlpg 512.0 cycles + read CR3 27.3 cycles + reload CR3 368.0 cycles + clts 344.0 cycles + cli + sti 116.2 cycles + set CR0.ts 432.0 cycles + in8(PIC) 2128.0 cycles + in8(iodelay) 2271.0 cycles + out8(PIC) 2016.0 cycles + get ES 10.0 cycles + set ES + load ES:mem 22.5 cycles + modify ES + load ES:mem 67.5 cycles + int + iret 1064.0 cycles + sysenter + sysexit 206.0 cycles + sysenter + iret 628.0 cycles + push EAX + pop EAX 5.0 cycles + push flags + pop EAX 10.0 cycles + rdtsc 124.0 cycles + rdpmc(0) 232.0 cycles + rdpmc32(0) 92.0 cycles + APIC timer read 185.5 cycles + load data TLB (4k) 36.0 cycles + load code TLB (4k) 47.9 cycles + diff --git a/kernel/fiasco/src/jdb/ia32/32/jdb_tcb-ia32-ux.cpp b/kernel/fiasco/src/jdb/ia32/32/jdb_tcb-ia32-ux.cpp new file mode 100644 index 00000000..55e24612 --- /dev/null +++ b/kernel/fiasco/src/jdb/ia32/32/jdb_tcb-ia32-ux.cpp @@ -0,0 +1,217 @@ +IMPLEMENTATION [ia32,ux]: + +#include "config.h" +#include "jdb.h" +#include "jdb_disasm.h" + +EXTENSION class Jdb_tcb +{ + enum + { + Disasm_x = 41, + Disasm_y = 11, + Stack_y = 17, + }; + +}; + + +IMPLEMENT +void +Jdb_tcb::print_entry_frame_regs(Thread *t) +{ + Jdb_entry_frame *ef = Jdb::get_entry_frame(Jdb::current_cpu); + int from_user = ef->from_user(); + Address disass_addr = ef->ip(); + + // registers, disassemble + printf("EAX=%08lx ESI=%08lx DS=%04lx\n" + "EBX=%08lx EDI=%08lx ES=%04lx ", + ef->_ax, ef->_si, ef->_ds & 0xffff, ef->_bx, ef->_di, ef->_es & 0xffff); + + if (Jdb_disasm::avail()) + { + putstr(Jdb::esc_emph); + Jdb_disasm::show_disasm_line(-40, disass_addr, 0, from_user ? t->space() : 0); + putstr("\033[m"); + } + + printf("ECX=%08lx EBP=%08lx GS=%04lx ", + ef->_cx, ef->_bp, ef->_gs & 0xffff); + + if (Jdb_disasm::avail()) + Jdb_disasm::show_disasm_line(-40, disass_addr, 0, from_user ? t->space() : 0); + + printf("EDX=%08lx ESP=%08lx SS=%04lx\n" + "trap %ld (%s), error %08lx, from %s mode\n" + "CS=%04lx EIP=%s%08lx\033[m EFlags=%08lx\n", + ef->_dx, ef->sp(), ef->ss() & 0xffff, + ef->_trapno, Cpu::exception_string(ef->_trapno), ef->_err, + from_user ? "user" : "kernel", + ef->cs() & 0xffff, Jdb::esc_emph, ef->ip(), ef->flags()); + + if (ef->_trapno == 14) + printf("page fault linear address " L4_PTR_FMT "\n", ef->_cr2); +} + +IMPLEMENT +void +Jdb_tcb::print_return_frame_regs(Jdb_tcb_ptr const ¤t, Mword ksp) +{ + printf("CS=%04lx EIP=%s%08lx\033[m EFlags=%08lx kernel ESP=%08lx", + current.top_value(-4) & 0xffff, Jdb::esc_emph, + current.top_value(-5), current.top_value(-3), ksp); +} + +IMPLEMENT +void +Jdb_tcb::info_thread_state(Thread *t) +{ + Jdb::Guessed_thread_state state = Jdb::guess_thread_state(t); + Jdb_tcb_ptr p((Address)t->get_kernel_sp()); + int sub = 0; + + switch (state) + { + case Jdb::s_ipc: + case Jdb::s_syscall: + printf("EAX=%08lx ESI=%08lx\n" + "EBX=%08lx EDI=%08lx\n" + "ECX=%08lx EBP=%08lx\n" + "EDX=%08lx ESP=%08lx SS=%04lx\n" + "in %s (user level registers)", + p.top_value( -6), p.top_value(-10), + p.top_value( -8), p.top_value( -9), + p.top_value(-12), p.top_value( -7), + p.top_value(-11), p.top_value( -2), p.top_value(-1) & 0xffff, + state == Jdb::s_ipc ? "ipc" : "syscall"); + break; + case Jdb::s_user_invoke: + printf("EAX=00000000 ESI=00000000\n" + "EBX=00000000 EDI=00000000\n" + "ECX=00000000 EBP=00000000\n" + "EDX=00000000 ESP=%08lx SS=%04lx\n" + "invoking user the first time (user level registers)", + p.top_value(-2), p.top_value(-1) & 0xffff); + break; + case Jdb::s_fputrap: + printf("EAX=%08lx\n" + "\n" + "ECX=%08lx\n" + "EDX=%08lx ESP=%08lx SS=%04lx\n" + "in exception #0x07 (user level registers)", + p.top_value(-7), p.top_value(-8), + p.top_value(-9), p.top_value(-2), p.top_value(-1) & 0xffff); + break; + case Jdb::s_pagefault: + printf("EAX=%08lx\n" + "\n" + "ECX=%08lx EBP=%08lx\n" + "EDX=%08lx ESP=%08lx SS=%04lx\n" + "in page fault, error %08lx (user level registers)\n" + "\n" + "page fault linear address %08lx", + p.top_value( -7), p.top_value( -8), p.top_value(-6), + p.top_value( -9), p.top_value( -2), p.top_value(-1) & 0xffff, + p.top_value(-11), p.top_value(-10)); + break; + case Jdb::s_interrupt: + printf("EAX=%08lx\n" + "\n" + "ECX=%08lx\n" + "EDX=%08lx ESP=%08lx SS=%04lx\n" + "in interrupt #0x%02lx (user level registers)", + p.top_value(-6), p.top_value(-8), + p.top_value(-7), p.top_value(-2), p.top_value(-1) & 0xffff, + p.top_value(-9)); + break; + case Jdb::s_timer_interrupt: + if (Config::Have_frame_ptr) + sub = -1; + printf("EAX=%08lx\n" + "\n" + "ECX=%08lx\n" + "EDX=%08lx ESP=%08lx SS=%04lx\n" + "in timer interrupt (user level registers)", + p.top_value(-6-sub), p.top_value(-8-sub), + p.top_value(-7-sub), p.top_value(-2), p.top_value(-1) & 0xffff); + break; + case Jdb::s_slowtrap: + printf("EAX=%08lx ESI=%08lx DS=%04lx\n" + "EBX=%08lx EDI=%08lx ES=%04lx\n" + "ECX=%08lx EBP=%08lx GS=%04lx\n" + "EDX=%08lx ESP=%08lx SS=%04lx\n" + "in exception %ld, error %08lx (user level registers)", + p.top_value( -8), p.top_value(-14), p.top_value(-18) & 0xffff, + p.top_value(-11), p.top_value(-15), p.top_value(-19) & 0xffff, + p.top_value( -9), p.top_value(-13), p.top_value(-17) & 0xffff, + p.top_value(-10), p.top_value( -2), p.top_value( -1) & 0xffff, + p.top_value( -7), p.top_value( -6)); + break; + case Jdb::s_unknown: + break; + } +} + +IMPLEMENT +bool +Jdb_stack_view::edit_registers() +{ + Mword value; + char reg = (char)(-1); + Mword *reg_ptr=0; + unsigned x=0, y=0; + + + Jdb::printf_statline("tcb", 0, "edit register " + "e{ax|bx|cx|dx|si|di|sp|bp|ip|fl}: "); + Jdb::cursor(Jdb_screen::height(), 53); + Jdb::get_register(®); + + switch (reg) + { + case 1: x= 4; y= 9; reg_ptr = &ef->_ax; break; + case 2: x= 4; y=10; reg_ptr = &ef->_bx; break; + case 3: x= 4; y=11; reg_ptr = &ef->_cx; break; + case 4: x= 4; y=12; reg_ptr = &ef->_dx; break; + case 5: x=18; y=11; reg_ptr = &ef->_bp; break; + case 6: x=18; y= 9; reg_ptr = &ef->_si; break; + case 7: x=18; y=10; reg_ptr = &ef->_di; break; + case 8: x=13; y=14; reg_ptr = &ef->_ip; break; + case 9: // we have no esp if we come from kernel + if (!ef->from_user()) + return false; + x=18; y=12; reg_ptr = &ef->_sp; break; + case 10: x=35; y=12; reg_ptr = &ef->_flags; + break; + default: return false; + } + + Jdb::cursor(y+1, x+1); + putstr(" "); + Jdb::printf_statline("tcb", 0, "edit %s = %08lx", + Jdb_screen::Reg_names[reg-1], *reg_ptr); + Jdb::cursor(y+1, x+1); + if (Jdb_input::get_mword(&value, 8, 16)) + { + *reg_ptr = value; + Jdb::cursor(y+1, x+1); + printf("%08lx", *reg_ptr); + } + return true; +} + +IMPLEMENT inline +bool +Jdb_tcb_ptr::is_user_value() const +{ + return _offs >= Context::Size - 5 * sizeof(Mword); +} + +IMPLEMENT inline +const char * +Jdb_tcb_ptr::user_value_desc() const +{ + const char *desc[] = { "SS", "SP", "EFL", "CS", "IP" }; + return desc[(Context::Size - _offs) / sizeof(Mword) - 1]; +} diff --git a/kernel/fiasco/src/jdb/ia32/64/jdb_bp-amd64.cpp b/kernel/fiasco/src/jdb/ia32/64/jdb_bp-amd64.cpp new file mode 100644 index 00000000..75d58725 --- /dev/null +++ b/kernel/fiasco/src/jdb/ia32/64/jdb_bp-amd64.cpp @@ -0,0 +1,13 @@ +INTERFACE: + +EXTENSION class Jdb_bp +{ + enum + { + Val_enter = 0x000000000000ff00, + Val_leave = 0x0000000000000000, + Val_test_sstep = 0x0000000000004000, + Val_test = 0x000000000000000f, + Val_test_other = 0x000000000000e00f, + }; +}; diff --git a/kernel/fiasco/src/jdb/ia32/64/jdb_kern_info-bench-ia32-64.cpp b/kernel/fiasco/src/jdb/ia32/64/jdb_kern_info-bench-ia32-64.cpp new file mode 100644 index 00000000..1af3dec8 --- /dev/null +++ b/kernel/fiasco/src/jdb/ia32/64/jdb_kern_info-bench-ia32-64.cpp @@ -0,0 +1,232 @@ +IMPLEMENTATION: + +#include +#include "cpu.h" +#include "div32.h" +#include "gdt.h" +#include "simpleio.h" +#include "static_init.h" +#include "timer.h" + +static void +Jdb_kern_info_bench::show_time(Unsigned64 time, Unsigned32 rounds, + const char *descr) +{ + Unsigned64 cycs = div32(time, rounds); + printf(" %-24s %6lld.%lld cycles\n", + descr, cycs, div32(time-cycs*rounds, rounds/10)); +} + +IMPLEMENT inline +Unsigned64 +Jdb_kern_info_bench::get_time_now() +{ return Cpu::rdtsc(); } + +#define inst_wbinvd \ + asm volatile ("wbinvd") + +#define inst_invlpg \ + asm volatile ("invlpg %0" \ + : : "m" (*(char*)Mem_layout::Kmem_tmp_page_1)) + +#define inst_read_cr3 \ + asm volatile ("mov %%cr3,%0" \ + : "=r"(dummy)) + +#define inst_reload_cr3 \ + asm volatile ("mov %%cr3,%0; mov %0,%%cr3" \ + : "=r"(dummy)) + +#define inst_clts \ + asm volatile ("clts") + +#define inst_cli_sti \ + asm volatile ("cli; sti") + +#define inst_set_cr0_ts \ + asm volatile ("mov %%cr0,%0; or %1,%0; mov %0,%%cr0" \ + : "=r" (dummy) : "i" (CR0_TS)) + +#define inst_push_pop \ + asm volatile ("push %rax; pop %rax") + +#define inst_pushf_pop \ + asm volatile ("pushf; pop %%rax" : : : "rax") + +#define inst_in8_pic \ + asm volatile ("inb $0x21, %%al" : "=a" (dummy)) + +#define inst_in8_80 \ + asm volatile ("inb $0x80, %%al" : "=a" (dummy)) + +#define inst_out8_pic \ + asm volatile ("outb %%al, $0x21" : : "a" (0xff)) + +#define inst_apic_timer_read \ + (volatile Unsigned32)Apic::timer_reg_read() + +#define BENCH(name, instruction, rounds) \ + do \ + { \ + time = Cpu::rdtsc(); \ + for (i=rounds; i; i--) \ + instruction; \ + time = Cpu::rdtsc() - time; \ + show_time (time, rounds, name); \ + } while (0) + +IMPLEMENT +void +Jdb_kern_info_bench::show_arch() +{ + Unsigned64 time; + Mword dummy; + Mword cr0, pic; + Unsigned32 time_reload_cr3, time_invlpg; + register int i; + Gdt *gdt = Cpu::boot_cpu()->get_gdt(); + Unsigned32 flags = Proc::cli_save(); + + if (!Cpu::boot_cpu()->tsc()) + return; + + // we need a cached, non-global mapping for measuring the time to load + // TLB entries + Address phys = Kmem::virt_to_phys((void*)Mem_layout::Tbuf_status_page); + Kmem::map_phys_page(phys, Mem_layout::Jdb_bench_page, true, false); + + { + time = Cpu::rdtsc(); + asm volatile ("mov $10000000,%%rcx; .align 4;\n\t" + "1:dec %%rcx; jnz 1b" : : : "rcx"); + + time = Cpu::rdtsc() - time; + show_time(time, 10000000, "1:dec RCX, jnz 1b"); + } + BENCH("wbinvd", inst_wbinvd, 5000); + BENCH("invlpg", inst_invlpg, 200000); + time_invlpg = time; + BENCH("read CR3", inst_read_cr3, 200000); + BENCH("reload CR3", inst_reload_cr3, 200000); + time_reload_cr3 = time; + cr0 = Cpu::get_cr0(); + BENCH("clts", inst_clts, 200000); + BENCH("cli + sti", inst_cli_sti, 200000); + Proc::cli(); + BENCH("set CR0.ts", inst_set_cr0_ts, 200000); + Cpu::set_cr0(cr0); + pic = Io::in8(0x21); + BENCH("in8(PIC)", inst_in8_pic, 200000); + BENCH("in8(iodelay)", inst_in8_80, 200000); + BENCH("out8(PIC)", inst_out8_pic, 200000); + Io::out8(pic, 0x21); + { + // read ES segment descriptor + time = Cpu::rdtsc(); + asm volatile ("mov $200000,%%rbx\n\t" + ".align 8; 1: mov %%es, %%eax; dec %%rbx; jnz 1b" + : : : "rax", "rbx"); + time = Cpu::rdtsc() - time; + show_time(time, 200000, "get ES"); + } + { + // set ES segment descriptor and access memory through the ES segment + time = Cpu::rdtsc(); + asm volatile ("mov $200000,%%rbx \n\t" + ".align 8 \n\t" + "1: \n\t" + "mov %%rax, %%es \n\t" + "dec %%rbx \n\t" + "mov %%es:(%c1),%%rdi \n\t" + "jnz 1b \n\t" + : + : "a"(Gdt::gdt_data_kernel | Gdt::Selector_kernel), + "i"(Mem_layout::Kernel_image) + : "rbx", "rdi"); + time = Cpu::rdtsc() - time; + show_time(time, 200000, "set ES + load ES:mem"); + } + { + // write a GDT entry, set ES segment descriptor to this gdt entry + // and access memory through the ES segment + Unsigned32 *gdt_e = (Unsigned32*)&(*gdt)[Gdt::gdt_data_kernel/8]; + time = Cpu::rdtsc(); + asm volatile ("mov $200000,%%rbx \n\t" + ".align 16 \n\t" + "1: \n\t" + "mov %%rax, (%%rsi) \n\t" + "mov %%rcx, 4(%%rsi) \n\t" + "mov %%rdx, %%es \n\t" + "dec %%rbx \n\t" + "mov %%es:(%c4),%%rdi \n\t" + "jnz 1b \n\t" + : + : "a"(gdt_e[0]), "c"(gdt_e[1]), + "d"(Gdt::gdt_data_kernel | Gdt::Selector_kernel), + "S"(gdt->entries() + Gdt::gdt_data_kernel/8), + "i"(Mem_layout::Kernel_image) + : "rbx", "rdi"); + time = Cpu::rdtsc() - time; + show_time(time, 200000, "modify ES + load ES:mem"); + } + BENCH("push RAX + pop RAX", inst_push_pop, 200000); + BENCH("push flags + pop RAX", inst_pushf_pop, 200000); + { + time = Cpu::rdtsc(); + asm volatile ("mov $200000,%%rbx\n\t" + ".align 4; 1: rdtsc; dec %%rbx; jnz 1b" + : : : "rax", "rbx", "rdx"); + time = Cpu::rdtsc() - time; + show_time(time, 200000, "rdtsc"); + } + if (Cpu::boot_cpu()->local_features() & Cpu::Lf_rdpmc) + { + time = Cpu::rdtsc(); + asm volatile ("mov $200000,%%rbx; mov $0x00000000,%%rcx\n\t" + ".align 4; 1: rdpmc; dec %%rbx; jnz 1b" + : : : "rax", "rbx", "rcx", "rdx"); + time = Cpu::rdtsc() - time; + show_time(time, 200000, "rdpmc(0)"); + } + if (Cpu::boot_cpu()->local_features() & Cpu::Lf_rdpmc32) + { + time = Cpu::rdtsc(); + asm volatile ("mov $200000,%%rbx; mov $0x80000000,%%rcx\n\t" + ".align 4; 1: rdpmc; dec %%rbx; jnz 1b" + : : : "rax", "rbx", "rcx", "rdx"); + time = Cpu::rdtsc() - time; + show_time(time, 200000, "rdpmc32(0)"); + } + if (Config::apic) + { + BENCH("APIC timer read", (void)inst_apic_timer_read, 200000); + } + { + time = Cpu::rdtsc(); + for (i=200000; i; i--) + asm volatile ("invlpg %c2 \n\t" + "mov %c2, %1 \n\t" + : "=r" (dummy), "=r" (dummy) + : "i"(Mem_layout::Jdb_bench_page)); + time = Cpu::rdtsc() - time - time_invlpg; + show_time (time, 200000, "load data TLB (4k)"); + } + { + // asm ("1: mov %%cr3,%%rdx; mov %%rdx, %%cr3; dec %%rax; jnz 1b; ret") + *(Unsigned32*)(Mem_layout::Jdb_bench_page + 0xff0) = 0x0fda200f; + *(Unsigned32*)(Mem_layout::Jdb_bench_page + 0xff4) = 0xff48da22; + *(Unsigned32*)(Mem_layout::Jdb_bench_page + 0xff8) = 0xc3f575c8; + + Mem::barrier(); + time = Cpu::rdtsc(); + asm volatile ("call *%%rcx" + : "=a"(dummy) + : "c"(Mem_layout::Jdb_bench_page + 0xff0), "a"(200000) + : "rdx"); + + time = Cpu::rdtsc() - time - time_reload_cr3; + show_time (time, 200000, "load code TLB (4k)"); + } + + Proc::sti_restore(flags); +} diff --git a/kernel/fiasco/src/jdb/ia32/64/jdb_ptab-amd64.cpp b/kernel/fiasco/src/jdb/ia32/64/jdb_ptab-amd64.cpp new file mode 100644 index 00000000..a3aaa2e2 --- /dev/null +++ b/kernel/fiasco/src/jdb/ia32/64/jdb_ptab-amd64.cpp @@ -0,0 +1,105 @@ +IMPLEMENTATION [amd64]: + +#include "paging.h" + +unsigned Jdb_ptab::max_pt_level = Pdir::Depth; + +IMPLEMENT inline NEEDS ["paging.h"] +unsigned +Jdb_ptab::entry_is_pt_ptr(Mword entry, unsigned level, + unsigned *entries, unsigned *next_level) +{ + if (level > Pdir::Super_level || entry & Pt_entry::Pse_bit) + return 0; + *entries = Ptab::Level::length(level); + *next_level = level+1; + return 1; +} + +IMPLEMENT inline NEEDS ["paging.h"] +Address +Jdb_ptab::entry_phys(Mword entry, unsigned level) +{ + return Ptab::Level::addr(level, entry); +} + +IMPLEMENT inline NEEDS ["paging.h"] +unsigned +Jdb_ptab::entry_valid(Mword entry, unsigned) +{ return entry & Pt_entry::Valid; } + +IMPLEMENT +void +Jdb_ptab::print_entry(Mword entry, unsigned level) +{ + if (dump_raw) + { + printf(L4_PTR_FMT, entry); + return; + } + + if (!entry_valid(entry,level)) + { + putstr(" - "); + return; + } + + Address phys = entry_phys(entry, level); + + if (level == Pdir::Super_level && entry & Pt_entry::Pse_bit) + printf((phys >> 20) > 0xFF + ? " %03lx/2" : " %02lx/2", phys >> 20); + else + printf((phys >> Config::PAGE_SHIFT) > 0xFFFF + ? "%13lx" : " %04lx", phys >> Config::PAGE_SHIFT); + + putchar(((cur_pt_level>=max_pt_level || (entry & Pt_entry::Pse_bit)) && + (entry & Pt_entry::Cpu_global)) ? '+' : '-'); + printf("%s%c%s", entry & Pt_entry::Noncacheable ? JDB_ANSI_COLOR(lightblue) : "", + entry & Pt_entry::Noncacheable + ? 'n' : (entry & Pt_entry::Write_through) ? 't' : '-', + entry & Pt_entry::Noncacheable ? JDB_ANSI_END : ""); + putchar(entry & Pt_entry::User + ? (entry & Pt_entry::Writable) ? 'w' : 'r' + : (entry & Pt_entry::Writable) ? 'W' : 'R'); +} + +PUBLIC +unsigned long +Jdb_ptab::rows() const +{ return entries/4; } + +PRIVATE +Address +Jdb_ptab::disp_virt(unsigned long row, unsigned col) +{ + Pdir::Va e(Mword(col-1) + (Mword(row) * Mword(cols()-1))); + e <<= Ptab::Level::shift(cur_pt_level); + return Virt_addr(e).value() + virt_base; +} + +PUBLIC +void +Jdb_ptab::print_statline(unsigned long row, unsigned long col) +{ + if (cur_pt_level == 0) + { + Jdb::printf_statline("pml4", "=mode =goto pdp", + "<" L4_PTR_FMT "> task %p", disp_virt(row,col), _task); + } + else if (cur_pt_level == 1) + { + Jdb::printf_statline("pdp", "=mode =goto pdir", + "<" L4_PTR_FMT "> task %p", disp_virt(row,col), _task); + } + else if (cur_pt_level == 2) + { + Jdb::printf_statline("pdir", "=mode =goto ptab/superpage", + "<" L4_PTR_FMT "> task %p", disp_virt(row,col), _task); + } + else // PT_MODE + { + Jdb::printf_statline("ptab", "=mode =goto page", + "<" L4_PTR_FMT "> task %p", disp_virt(row,col), _task); + } +} diff --git a/kernel/fiasco/src/jdb/ia32/64/jdb_tcb-amd64.cpp b/kernel/fiasco/src/jdb/ia32/64/jdb_tcb-amd64.cpp new file mode 100644 index 00000000..a20cd19b --- /dev/null +++ b/kernel/fiasco/src/jdb/ia32/64/jdb_tcb-amd64.cpp @@ -0,0 +1,329 @@ +IMPLEMENTATION [amd64]: + +#include "jdb_disasm.h" + +EXTENSION class Jdb_tcb +{ + enum + { + Disasm_x = 45, + Disasm_y = 11, + Stack_y = 21, + }; +}; + +PRIVATE static +void +Jdb_tcb::print_regs_invalid_tid() +{ + //const Mword mask + // = (Context::Size * Mem_layout::max_threads()) - 1; + //const Mword tsksz = Context::Size * L4_uid::threads_per_task(); + + // LThread_num task = ((Address)Jdb::get_thread(Jdb::current_cpu) & mask) / tsksz; + putchar('\n'); + //print_entry_frame_regs (task); +} + +IMPLEMENT +void +Jdb_tcb::print_entry_frame_regs(Thread *t) +{ + Jdb_entry_frame *ef = Jdb::get_entry_frame(Jdb::current_cpu); + int from_user = ef->from_user(); + Address disass_addr = ef->ip(); + + // registers, disassemble + printf("RAX=%016lx RSI=%016lx\n" + "RBX=%016lx RDI=%016lx ", + ef->_ax, ef->_si, ef->_bx, ef->_di); + // XXX mix register status with disasemble code + + if (Jdb_disasm::avail()) + { + putstr(Jdb::esc_emph); + Jdb_disasm::show_disasm_line(-40, disass_addr, 0, from_user ? t->space() : 0); + putstr("\033[m"); + } + + printf("RCX=%016lx RBP=%016lx ", + ef->_cx, ef->_bp); + + if (Jdb_disasm::avail()) + Jdb_disasm::show_disasm_line(-40, disass_addr, 0, from_user ? t->space() : 0); + + printf("RDX=%016lx RSP=%016lx\n" + " R8=%016lx R9=%016lx\n" + "R10=%016lx R11=%016lx\n" + "R12=%016lx R13=%016lx\n" + "R14=%016lx R15=%016lx FS=%04lx\n" + "trapno %ld, error %08lx, from %s mode\n" + "RIP=%s%016lx\033[m RFlags=%016lx\n", + ef->_dx, ef->sp(), + ef->_r8, ef->_r9, + ef->_r10, ef->_r11, + ef->_r12, ef->_r13, + ef->_r14, ef->_r15, t->_fs_base, + ef->_trapno, ef->_err, from_user ? "user" : "kernel", + Jdb::esc_emph, ef->ip(), ef->flags()); + + if (ef->_trapno == 14) + printf("page fault linear address " L4_PTR_FMT "\n", ef->_cr2); +} + +IMPLEMENT +void +Jdb_tcb::print_return_frame_regs(Jdb_tcb_ptr const ¤t, Mword ksp) +{ + printf("RIP=%s%016lx\033[m RFlags=%016lx kernel RSP=%016lx", + Jdb::esc_emph, current.top_value(-5), current.top_value(-3), ksp); +} + +IMPLEMENT +void +Jdb_tcb::info_thread_state(Thread *t) +{ + Jdb::Guessed_thread_state state = Jdb::guess_thread_state(t); + Jdb_tcb_ptr p((Address)t->get_kernel_sp()); + int sub = 0; + + switch (state) + { + case Jdb::s_ipc: + case Jdb::s_syscall: + printf("RAX=%016lx RSI=%016lx\n" + "RBX=%016lx RDI=%016lx\n" + "RCX=%016lx RBP=%016lx\n" + "RDX=%016lx RSP=%016lx\n" + "R8= %016lx R9= %016lx\n" + "R10=%016lx R11=%016lx\n" + "R12=%016lx R13=%016lx SS=%04lx\n" + "R14=%016lx R15=%016lx CS=%04lx\n" + "in %s (user level registers)", + p.top_value( -6), p.top_value(-10), + p.top_value( -8), p.top_value( -9), + p.top_value(-12), p.top_value( -7), + p.top_value(-11), p.top_value( -2), + p.top_value(-19), p.top_value(-18), + p.top_value(-17), p.top_value(-16), + p.top_value(-15), p.top_value(-14), p.top_value(-1) & 0xffff, + p.top_value(-13), p.top_value(-12), p.top_value(-4) & 0xffff, + state == Jdb::s_ipc ? "ipc" : "syscall"); + break; + case Jdb::s_user_invoke: + printf("RAX=0000000000000000 RSI=0000000000000000\n" + "RBX=0000000000000000 RDI=0000000000000000\n" + "RCX=0000000000000000 RBP=0000000000000000\n" + "RDX=0000000000000000 RSP=%16lx SS=%04lx\n" + " R8=0000000000000000 R9=0000000000000000\n" + "R10=0000000000000000 R11=0000000000000000\n" + "R12=0000000000000000 R13=0000000000000000\n" + "R14=0000000000000000 R15=0000000000000000\n" + "invoking user the first time (user level registers)", + p.top_value(-2), p.top_value(-1) & 0xffff); + break; + case Jdb::s_fputrap: + printf("RAX=%016lx RSI=----------------\n" + "RBX=---------------- RDI=----------------\n" + "RCX=%016lx RBP=----------------\n" + "RDX=%016lx RSP=%016lx SS=%04lx\n" + " R8=---------------- R9=----------------\n" + "R10=---------------- R11=----------------\n" + "R12=---------------- R13=----------------\n" + "R14=---------------- R15=----------------\n" + "in exception #0x07 (user level registers)", + p.top_value(-7), p.top_value(-8), + p.top_value(-9), p.top_value(-2), p.top_value(-1) & 0xffff); + break; + case Jdb::s_pagefault: + printf("RAX=%016lx RSI=----------------\n" + "RBX=---------------- RDI=----------------\n" + "RCX=%016lx RBP=%016lx\n" + "RDX=%016lx RSP=%016lx SS=%04lx\n" + " R8=---------------- R9=----------------\n" + "R10=---------------- R11=----------------\n" + "R12=---------------- R13=----------------\n" + "R14=---------------- R15=----------------\n" + "in page fault, error %08lx (user level registers)\n" + "\n" + "page fault linear address %16lx", + p.top_value( -7), p.top_value( -8), p.top_value(-6), + p.top_value( -9), p.top_value( -2), p.top_value(-1) & 0xffff, + p.top_value(-10), p.top_value(-11)); + break; + case Jdb::s_interrupt: + printf("RAX=%016lx\n RSI=----------------\n" + "RBX=---------------- RDI=----------------\n" + "RCX=%016lx\n RBP=----------------\n" + "RDX=%016lx RSP=%016lx SS=%04lx\n" + " R8=---------------- R9=----------------\n" + "R10=---------------- R11=----------------\n" + "R12=---------------- R13=----------------\n" + "R14=---------------- R15=----------------\n" + "in interrupt #0x%02lx (user level registers)", + p.top_value(-6), p.top_value(-8), + p.top_value(-7), p.top_value(-2), p.top_value(-1) & 0xffff, + p.top_value(-9)); + break; + case Jdb::s_timer_interrupt: + if (Config::Have_frame_ptr) + sub = -1; + printf("RAX=%016lx RSI=----------------\n" + "RBX=---------------- RDI=----------------\n" + "RCX=%016lx RBP=----------------\n" + "RDX=%016lx RSP=%016lx SS=%04lx\n" + " R8=---------------- R9=----------------\n" + "R10=---------------- R11=----------------\n" + "R12=---------------- R13=----------------\n" + "R14=---------------- R15=----------------\n" + "in timer interrupt (user level registers)", + p.top_value(-6-sub), p.top_value(-8-sub), + p.top_value(-7-sub), p.top_value(-2), p.top_value(-1) & 0xffff); + break; + case Jdb::s_slowtrap: + printf("RAX=%016lx RSI=%016lx\n" + "RBX=%016lx RDI=%016lx\n" + "RCX=%016lx RBP=%016lx\n" + "RDX=%016lx RSP=%016lx SS=%04lx\n" + " R8=%016lx R9=%016lx\n" + "R10=%016lx R11=%016lx\n" + "R12=%016lx R13=%016lx\n" + "R14=%016lx R15=%016lx CS=%04lx\n" + "in exception %ld, error %08lx (user level registers)", + p.top_value( -8), p.top_value(-14), + p.top_value(-11), p.top_value(-15), + p.top_value( -9), p.top_value(-13), + p.top_value(-10), p.top_value( -2), + p.top_value(-20), p.top_value(-19), + p.top_value(-18), p.top_value(-17), + p.top_value(-16), p.top_value(-15), p.top_value(-1) & 0xffff, + p.top_value(-14), p.top_value(-13), p.top_value(-4) & 0xffff, + p.top_value( -7), p.top_value( -6)); + break; + case Jdb::s_unknown: + break; + } +} + +#if 0 +PUBLIC +bool +Jdb_tcb_ptr::in_backtrace(Address bt_start, Address tcb) +{ + if (bt_start) + { + if (!Config::Have_frame_ptr) + return Mem_layout::in_kernel_code(value()); + + Jdb_tcb_ptr ebp(bt_start); + + for (;;) + { + Jdb_tcb_ptr eip(ebp.addr()+4); + + if (!Mem_layout::in_kernel_code(eip.value())) + return false; + if (ebp.addr()+4 == addr()) + return true; + if (ebp.addr() == 0 || !Jdb_tcb_ptr(ebp.value()).valid()) + return false; + + ebp = ebp.value(); + } + } + return false; +} + + +static +Address +Jdb_tcb::search_bt_start(Address tcb, Mword *ksp, bool is_current_thread) +{ + if (!Config::Have_frame_ptr) + return 1; + + if (is_current_thread) + return (Address)__builtin_frame_address(6); + + Address tcb_next = tcb + Context::size; + + for (int i=0; (Address)(ksp+i+1)= tcb + 0x180 && + ksp[i] < tcb_next-20 && + ksp[i] > (Address)(ksp+i)) + return (Address)(ksp+i); + } + + return 0; +} +#endif + +IMPLEMENT +bool +Jdb_stack_view::edit_registers() +{ + Mword value; + char reg = char(-1); + Mword *reg_ptr = 0; + unsigned x=0, y=0; + + + Jdb::printf_statline("tcb", 0, "edit register " + "r{ax|bx|cx|dx|si|di|sp|bp|ip|fl}: "); + Jdb::cursor(Jdb_screen::height(), 53); + + switch (reg) + { + case 1: x= 4; y= 9; reg_ptr = &ef->_ax; break; + case 2: x= 4; y=10; reg_ptr = &ef->_bx; break; + case 3: x= 4; y=11; reg_ptr = &ef->_cx; break; + case 4: x= 4; y=12; reg_ptr = &ef->_dx; break; + case 5: x=24; y=11; reg_ptr = &ef->_bp; break; + case 6: x=24; y= 9; reg_ptr = &ef->_si; break; + case 7: x=24; y=10; reg_ptr = &ef->_di; break; + case 8: x=13; y=14; reg_ptr = &ef->_ip; break; + case 20: x= 4; y=14; reg_ptr = &ef->_ip; break; + case 21: x=24; y=14; reg_ptr = &ef->_ip; break; + case 22: x= 4; y=15; reg_ptr = &ef->_ip; break; + case 23: x=24; y=15; reg_ptr = &ef->_ip; break; + case 24: x= 4; y=16; reg_ptr = &ef->_ip; break; + + case 9: // we have no esp if we come from kernel + if (!ef->from_user()) + return false; + x=24; y=12; reg_ptr = &ef->_sp; break; + case 10: x=35; y=12; reg_ptr = &ef->_flags; break; + default: return false; + } + + Jdb::cursor(y+1, x+1); + putstr(" "); + Jdb::printf_statline("tcb", 0, "edit %s = %16lx", + Jdb_screen::Reg_names[reg-1], + *reg_ptr); + Jdb::cursor(y+1, x+1); + if (Jdb_input::get_mword(&value, 16, 16)) + { + *reg_ptr = value; + Jdb::cursor(y+1, x+1); + printf("%016lx", *reg_ptr); + } + return true; +} + +IMPLEMENT inline +bool +Jdb_tcb_ptr::is_user_value() const +{ + return _offs >= Context::Size - 5 * sizeof(Mword); +} + +IMPLEMENT inline +const char * +Jdb_tcb_ptr::user_value_desc() const +{ + const char *desc[] = { "SS", "SP", "RFL", "CS", "IP" }; + return desc[(Context::Size - _offs) / sizeof(Mword) - 1]; +} diff --git a/kernel/fiasco/src/jdb/ia32/jdb-ia32-amd64.cpp b/kernel/fiasco/src/jdb/ia32/jdb-ia32-amd64.cpp new file mode 100644 index 00000000..2fe08524 --- /dev/null +++ b/kernel/fiasco/src/jdb/ia32/jdb-ia32-amd64.cpp @@ -0,0 +1,1021 @@ +// Inside Jdb the method Jdb::get_thread() should be used instead of +// Thread::current_thread(). The latter function cannot not handle the +// case when we came from the kernel stack context! + +INTERFACE: + +#include "l4_types.h" +#include "pic.h" + +class Trap_state; +class Thread; +class Console_buffer; +class Jdb_entry_frame; +class Push_console; + +EXTENSION class Jdb +{ +public: + enum + { + Msr_test_default = 0, + Msr_test_fail_warn = 1, + Msr_test_fail_ignore = 2, + }; + + static void init(); + + static Per_cpu apic_tpr; + static Pic::Status pic_status; + static volatile char msr_test; + static volatile char msr_fail; + + typedef enum + { + s_unknown, s_ipc, s_syscall, s_pagefault, s_fputrap, + s_interrupt, s_timer_interrupt, s_slowtrap, s_user_invoke, + } Guessed_thread_state; + + + static int (*bp_test_log_only)(); + static int (*bp_test_sstep)(); + static int (*bp_test_break)(char *errbuf, size_t bufsize); + static int (*bp_test_other)(char *errbuf, size_t bufsize); + +private: + + static char _connected; + static Per_cpu permanent_single_step; + static Per_cpu code_ret, code_call, code_bra, code_int; + + typedef enum + { + SS_NONE=0, SS_BRANCH, SS_RETURN + } Step_state; + + static Per_cpu ss_state; + static Per_cpu ss_level; + + static const Unsigned8 *debug_ctrl_str; + static int debug_ctrl_len; + + static Per_cpu jdb_irqs_disabled; +}; + +IMPLEMENTATION [{amd64,ia32}-!serial]: + +static inline +void Jdb::init_serial_console() +{} + +IMPLEMENTATION [{amd64,ia32}-serial]: + +#include +#include "kernel_uart.h" + +static +void Jdb::init_serial_console() +{ + if (Config::serial_esc == Config::SERIAL_ESC_IRQ && + !Kernel_uart::uart()->failed()) + { + int irq; + + if ((irq = Kernel_uart::uart()->irq()) == -1) + { + Config::serial_esc = Config::SERIAL_ESC_NOIRQ; + puts("SERIAL ESC: Using serial hack in slow timer handler."); + } + else + { + Kernel_uart::enable_rcv_irq(); + printf("SERIAL ESC: allocated IRQ %d for serial uart\n", irq); + } + } +} + +IMPLEMENTATION[ia32,amd64]: + +#include +#include +#include +#include +#include +#include +#include "simpleio.h" + +#include "apic.h" +#include "boot_info.h" +#include "checksum.h" +#include "config.h" +#include "cpu.h" +#include "initcalls.h" +#include "idt.h" +#include "io_apic.h" +#include "jdb_core.h" +#include "jdb_screen.h" +#include "kernel_console.h" +#include "keycodes.h" +#include "kernel_uart.h" +#include "kernel_task.h" +#include "kmem.h" +#include "koptions.h" +#include "logdefs.h" +#include "mem_layout.h" +#include "pic.h" +#include "push_console.h" +#include "processor.h" +#include "regdefs.h" +#include "static_init.h" +#include "terminate.h" +#include "thread.h" +#include "thread_state.h" +#include "timer.h" +#include "timer_tick.h" +#include "trap_state.h" +#include "vkey.h" +#include "watchdog.h" + +char Jdb::_connected; // Jdb::init() was done +// explicit single_step command +DEFINE_PER_CPU Per_cpu Jdb::permanent_single_step; +volatile char Jdb::msr_test; // = 1: trying to access an msr +volatile char Jdb::msr_fail; // = 1: MSR access failed +DEFINE_PER_CPU Per_cpu Jdb::code_ret; // current instruction is ret/iret +DEFINE_PER_CPU Per_cpu Jdb::code_call;// current instruction is call +DEFINE_PER_CPU Per_cpu Jdb::code_bra; // current instruction is jmp/jxx +DEFINE_PER_CPU Per_cpu Jdb::code_int; // current instruction is int x + +// special single step state +DEFINE_PER_CPU Per_cpu Jdb::ss_state; +DEFINE_PER_CPU Per_cpu Jdb::ss_level; // current call level + +const Unsigned8*Jdb::debug_ctrl_str; // string+length for remote control of +int Jdb::debug_ctrl_len; // Jdb via enter_kdebugger("*#"); + +Pic::Status Jdb::pic_status; +DEFINE_PER_CPU Per_cpu Jdb::apic_tpr; +DEFINE_PER_CPU Per_cpu Jdb::jdb_irqs_disabled; + +int (*Jdb::bp_test_log_only)(); +int (*Jdb::bp_test_sstep)(); +int (*Jdb::bp_test_break)(char *errbuf, size_t bufsize); +int (*Jdb::bp_test_other)(char *errbuf, size_t bufsize); + +// available from the jdb_dump module +int jdb_dump_addr_task (Address addr, Space *task, int level) + __attribute__((weak)); + + +STATIC_INITIALIZE_P(Jdb,JDB_INIT_PRIO); + + +IMPLEMENT FIASCO_INIT FIASCO_NOINLINE +void Jdb::init() +{ + if (Koptions::o()->opt(Koptions::F_nojdb)) + return; + + if (Koptions::o()->opt(Koptions::F_jdb_never_stop)) + never_break = 1; + + init_serial_console(); + + Trap_state::base_handler = (Trap_state::Handler)enter_jdb; + + // if esc_hack, serial_esc or watchdog enabled, set slow timer handler + Idt::set_vectors_run(); + + // disable lbr feature per default since it eats cycles on AMD Athlon boxes + Cpu::boot_cpu()->lbr_enable(false); + + Kconsole::console()->register_console(push_cons()); + + Thread::set_int3_handler(handle_int3_threadctx); + + _connected = true; + Thread::may_enter_jdb = true; +} + +PUBLIC static inline bool +Jdb::connected() +{ + return _connected; +} + +PROTECTED static inline +template< typename T > +void +Jdb::set_monitored_address(T *dest, T val) +{ + *dest = val; +} + +PROTECTED static inline +template< typename T > +T +Jdb::monitor_address(unsigned current_cpu, T *addr) +{ + if (!*addr && Cpu::cpus.cpu(current_cpu).has_monitor_mwait()) + { + asm volatile ("monitor \n" : : "a"(addr), "c"(0), "d"(0) ); + Mword irq_sup = Cpu::cpus.cpu(current_cpu).has_monitor_mwait_irq() ? 1 : 0; + asm volatile ("mwait \n" : : "a"(0x00), "c"(irq_sup) ); + } + + return *addr; +} + + +#if 0 +PUBLIC static +template T +Jdb::peek(T const *addr) +{ + return *addr; +} + +PUBLIC static +template T +Jdb::peek(T const *addr, Address_type) +{ + // on IA32 we can touch directly into the user-space + return *(T*)addr; +} +#endif + +static inline +void +Jdb::backspace() +{ + putstr("\b \b"); +} + + +DEFINE_PER_CPU static Per_cpu jdb_saved_flags; + +// disable interrupts before entering the kernel debugger +IMPLEMENT +void +Jdb::save_disable_irqs(unsigned cpu) +{ + if (!jdb_irqs_disabled.cpu(cpu)++) + { + // save interrupt flags + jdb_saved_flags.cpu(cpu) = Proc::cli_save(); + + if (cpu == 0) + { + Watchdog::disable(); + pic_status = Pic::disable_all_save(); + if (Config::getchar_does_hlt_works_ok) + Timer_tick::disable(0); + } + if (Io_apic::active() && Apic::is_present()) + { + apic_tpr.cpu(cpu) = Apic::tpr(); + Apic::tpr(APIC_IRQ_BASE - 0x10); + } + + if (cpu == 0 && Config::getchar_does_hlt_works_ok) + { + // set timer interrupt does nothing than wakeup from hlt + Timer_tick::set_vectors_stop(); + Timer_tick::enable(0); + } + + } + + if (cpu == 0 && Config::getchar_does_hlt_works_ok) + // explicit enable interrupts because the timer interrupt is + // needed to wakeup from "hlt" state in getchar(). All other + // interrupts are disabled at the pic. + Proc::sti(); +} + +// restore interrupts after leaving the kernel debugger +IMPLEMENT +void +Jdb::restore_irqs(unsigned cpu) +{ + if (!--jdb_irqs_disabled.cpu(cpu)) + { + Proc::cli(); + + if (Io_apic::active() && Apic::is_present()) + Apic::tpr(apic_tpr.cpu(cpu)); + + if (cpu == 0) + { + Pic::restore_all(Jdb::pic_status); + Watchdog::enable(); + } + + // reset timer interrupt vector + if (cpu == 0 && Config::getchar_does_hlt_works_ok) + Idt::set_vectors_run(); + + // reset interrupt flags + Proc::sti_restore(jdb_saved_flags.cpu(cpu)); + } +} + + +struct On_dbg_stack +{ + Mword sp; + On_dbg_stack(Mword sp) : sp(sp) {} + bool operator () (unsigned cpu) const + { + Thread::Dbg_stack const &st = Thread::dbg_stack.cpu(cpu); + return sp <= Mword(st.stack_top) + && sp >= Mword(st.stack_top) - Thread::Dbg_stack::Stack_size; + } +}; + +// Do thread lookup using Trap_state. In contrast to Thread::current_thread() +// this function can also handle cases where we entered from kernel stack +// context. We _never_ return 0! +IMPLEMENT +Thread* +Jdb::get_thread(unsigned cpu) +{ + Jdb_entry_frame *entry_frame = Jdb::entry_frame.cpu(cpu); + Address sp = (Address) entry_frame; + + // special case since we come from the double fault handler stack + if (entry_frame->_trapno == 8 && !(entry_frame->cs() & 3)) + sp = entry_frame->sp(); // we can trust esp since it comes from main_tss + + if (foreach_cpu(On_dbg_stack(sp), false)) + return 0; + + if (!Helping_lock::threading_system_active) + return 0; + + return static_cast(context_of((const void*)sp)); +} + +PUBLIC static +Space * +Jdb::translate_task(Address addr, Space *task) +{ + return (Kmem::is_kmem_page_fault(addr, 0)) ? 0 : task; +} + +PUBLIC static +void +Jdb::peek_phys(Address phys, void *value, int width) +{ + assert(!(phys & (width-1))); + + Address virt = Kmem::map_phys_page_tmp(phys, 0); + + memcpy(value, (void*)virt, width); +} + +PUBLIC static +void +Jdb::poke_phys(Address phys, void const *value, int width) +{ + assert(!(phys & (width-1))); + + Address virt = Kmem::map_phys_page_tmp(phys, 0); + + memcpy((void*)virt, value, width); +} + + +PUBLIC static +int +Jdb::peek_task(Address addr, Space *task, void *value, int width) +{ + Address phys; + + if (!task && Kmem::is_kmem_page_fault(addr, 0)) + { + // address of kernel directory + Address pdbr; + asm volatile ("mov %%cr3, %0" : "=r" (pdbr)); + Pdir *kdir = (Pdir*)Mem_layout::phys_to_pmem(pdbr); + Pdir::Iter i = kdir->walk(Virt_addr(addr)); + if (i.e->valid()) + { + memcpy(value, (void*)addr, width); + return 0; + } + } + // specific address space, use temporary mapping + if (!task) + phys = addr; + else + { + // user address, use temporary mapping + phys = Address(task->virt_to_phys (addr)); + + if (phys == ~0UL) + phys = task->virt_to_phys_s0((void*)addr); + + if (phys == ~0UL) + return -1; + } + + peek_phys(phys, value, width); + return 0; +} + +PUBLIC static +int +Jdb::poke_task(Address addr, Space *task, void const *value, int width) +{ + Address phys; + + if (task && Kmem::is_kmem_page_fault(addr, 0)) + { + Address pdbr; + asm volatile ("mov %%cr3, %0" : "=r" (pdbr)); + Pdir *kdir = (Pdir*)Mem_layout::phys_to_pmem(pdbr); + Pdir::Iter i = kdir->walk(Virt_addr(addr)); + if (i.e->valid()) + { + memcpy((void*)addr, value, width); + return 0; + } + } + + if (!task) + phys = addr; + else + { + // user address, use temporary mapping + phys = Address(task->virt_to_phys(addr)); + + if (phys == ~0UL) + phys = task->virt_to_phys_s0((void*)addr); + + if (phys == ~0UL) + return -1; + } + + poke_phys(phys, value, width); + return 0; +} + +// The content of apdapter memory is not shown by default because reading +// memory-mapped I/O registers may confuse the hardware. We assume that all +// memory above the end of the RAM is adapter memory. +PUBLIC static +int +Jdb::is_adapter_memory(Address virt, Space *task) +{ + Address phys; + + if (!task) + // phys requested + phys = virt; + else if ( !Kmem::is_io_bitmap_page_fault(virt) + && Kmem::is_kmem_page_fault(virt, 0)) + // kernel address + phys = Kmem::virt_to_phys((const void*)virt); + else + // user address + phys = task->virt_to_phys_s0((void*)virt); + + if (phys == ~0UL) + return false; + + Mem_desc *m = Kip::k()->mem_descs(); + Mem_desc *e = m + Kip::k()->num_mem_descs(); + for (; m != e; ++m) + if (m->type() == Mem_desc::Conventional && !m->is_virtual() + && m->start() <= phys && m->end() >= phys) + return false; + + return true; +} + +#define WEAK __attribute__((weak)) +extern "C" char in_slowtrap, in_page_fault, in_handle_fputrap; +extern "C" char in_interrupt, in_timer_interrupt, in_timer_interrupt_slow; +extern "C" char i30_ret_switch WEAK, se_ret_switch WEAK, in_slow_ipc1 WEAK; +extern "C" char in_slow_ipc2 WEAK, in_slow_ipc4; +extern "C" char in_slow_ipc5, in_sc_ipc1 WEAK; +extern "C" char in_sc_ipc2 WEAK, in_syscall WEAK; +#undef WEAK + +// Try to guess the thread state of t by walking down the kernel stack and +// locking at the first return address we find. +PUBLIC static +Jdb::Guessed_thread_state +Jdb::guess_thread_state(Thread *t) +{ + Guessed_thread_state state = s_unknown; + Mword *ktop = (Mword*)((Mword)context_of(t->get_kernel_sp()) + + Context::Size); + + for (int i=-1; i>-26; i--) + { + if (ktop[i] != 0) + { + if (ktop[i] == (Mword)&in_page_fault) + state = s_pagefault; + if ((ktop[i] == (Mword)&i30_ret_switch) ||// shortcut.S, int 0x30 + (ktop[i] == (Mword)&in_slow_ipc1) || // shortcut.S, int 0x30 + (ktop[i] == (Mword)&se_ret_switch) || // shortcut.S, sysenter + (ktop[i] == (Mword)&in_slow_ipc2) || // shortcut.S, sysenter + (ktop[i] == (Mword)&in_slow_ipc4) || // entry.S, int 0x30 log + (ktop[i] == (Mword)&in_slow_ipc5) || // entry.S, sysenter log +#if defined (CONFIG_JDB_LOGGING) || !defined(CONFIG_ASSEMBLER_IPC_SHORTCUT) + (ktop[i] == (Mword)&in_sc_ipc1) || // entry.S, int 0x30 + (ktop[i] == (Mword)&in_sc_ipc2) || // entry.S, sysenter +#endif + 0) + state = s_ipc; + else if (ktop[i] == (Mword)&in_syscall) + state = s_syscall; + else if (ktop[i] == (Mword)&Thread::user_invoke) + state = s_user_invoke; + else if (ktop[i] == (Mword)&in_handle_fputrap) + state = s_fputrap; + else if (ktop[i] == (Mword)&in_interrupt) + state = s_interrupt; + else if ((ktop[i] == (Mword)&in_timer_interrupt) || + (ktop[i] == (Mword)&in_timer_interrupt_slow)) + state = s_timer_interrupt; + else if (ktop[i] == (Mword)&in_slowtrap) + state = s_slowtrap; + if (state != s_unknown) + break; + } + } + + if (state == s_unknown && (t->state(false) & Thread_ipc_mask)) + state = s_ipc; + + return state; +} + +PUBLIC static +void +Jdb::set_single_step(unsigned cpu, int on) +{ + if (on) + entry_frame.cpu(cpu)->flags(entry_frame.cpu(cpu)->flags() | EFLAGS_TF); + else + entry_frame.cpu(cpu)->flags(entry_frame.cpu(cpu)->flags() & ~EFLAGS_TF); + + permanent_single_step.cpu(cpu) = on; +} + + +static bool +Jdb::handle_special_cmds(int c) +{ + foreach_cpu(&analyze_code); + + switch (c) + { + case 'j': // do restricted "go" + switch (putchar(c=getchar())) + { + case 'b': // go until next branch + case 'r': // go until current function returns + ss_level.cpu(current_cpu) = 0; + if (code_call.cpu(current_cpu)) + { + // increase call level because currently we + // stay on a call instruction + ss_level.cpu(current_cpu)++; + } + ss_state.cpu(current_cpu) = (c == 'b') ? SS_BRANCH : SS_RETURN; + // if we have lbr feature, the processor treats the single + // step flag as step on branches instead of step on instruction + Cpu::boot_cpu()->btf_enable(true); + // fall through + case 's': // do one single step + entry_frame.cpu(current_cpu)->flags(entry_frame.cpu(current_cpu)->flags() | EFLAGS_TF); + hide_statline = false; + return 0; + default: + abort_command(); + break; + } + break; + default: + backspace(); + // ignore character and get next input + break; + } + + return 1; + +} + + +IMPLEMENTATION[ia32]: + +// take a look at the code of the current thread eip +// set global indicators code_call, code_ret, code_bra, code_int +// This can fail if the current page is still not mapped +static void +Jdb::analyze_code(unsigned cpu) +{ + Jdb_entry_frame *entry_frame = Jdb::entry_frame.cpu(cpu); + Space *task = get_task(cpu); + // do nothing if page not mapped into this address space + if (entry_frame->ip()+1 > Kmem::user_max()) + return; + + Unsigned8 op1, op2; + + if ( !peek((Unsigned8*)entry_frame->ip(), task, op1) + || !peek((Unsigned8*)(entry_frame->ip()+1), task, op2)) + return; + + if (op1 != 0x0f && op1 != 0xff) + op2 = 0; + + code_ret.cpu(cpu) = + ( ((op1 & 0xf6) == 0xc2) // ret/lret /xxxx + || (op1 == 0xcf)); // iret + + code_call.cpu(cpu) = + ( (op1 == 0xe8) // call near + || ((op1 == 0xff) + && ((op2 & 0x30) == 0x10)) // call/lcall *(...) + || (op1 == 0x9a)); // lcall xxxx:xxxx + + code_bra.cpu(cpu) = + ( ((op1 & 0xfc) == 0xe0) // loop/jecxz + || ((op1 & 0xf0) == 0x70) // jxx rel 8 bit + || (op1 == 0xeb) // jmp rel 8 bit + || (op1 == 0xe9) // jmp rel 16/32 bit + || ((op1 == 0x0f) + && ((op2 & 0xf0) == 0x80)) // jxx rel 16/32 bit + || ((op1 == 0xff) + && ((op2 & 0x30) == 0x20)) // jmp/ljmp *(...) + || (op1 == 0xea)); // ljmp xxxx:xxxx + + code_int.cpu(cpu) = + ( (op1 == 0xcc) // int3 + || (op1 == 0xcd) // int xx + || (op1 == 0xce)); // into +} + +IMPLEMENTATION[amd64]: + +static void +Jdb::analyze_code(unsigned) +{} + +IMPLEMENTATION[ia32,amd64]: + +// entered debugger because of single step trap +static inline NOEXPORT int +Jdb::handle_single_step(unsigned cpu) +{ + int really_break = 1; + + analyze_code(cpu); + + Cpu const &ccpu = Cpu::cpus.cpu(cpu); + + // special single_step ('j' command): go until branch/return + if (ss_state.cpu(cpu) != SS_NONE) + { + if (ccpu.lbr_type() != Cpu::Lbr_unsupported) + { + // don't worry, the CPU always knows what she is doing :-) + } + else + { + // we have to emulate lbr looking at the code ... + switch (ss_state.cpu(cpu)) + { + case SS_RETURN: + // go until function return + really_break = 0; + if (code_call.cpu(cpu)) + { + // increase call level + ss_level.cpu(cpu)++; + } + else if (code_ret.cpu(cpu)) + { + // decrease call level + really_break = (ss_level.cpu(cpu)-- == 0); + } + break; + case SS_BRANCH: + default: + // go until next branch + really_break = (code_ret.cpu(cpu) || code_call.cpu(cpu) || code_bra.cpu(cpu) || code_int.cpu(cpu)); + break; + } + } + + if (really_break) + { + // condition met + ss_state.cpu(cpu) = SS_NONE; + snprintf(error_buffer.cpu(cpu), sizeof(error_buffer.cpu(0)), "%s", "Branch/Call"); + } + } + else // (ss_state == SS_NONE) + // regular single_step + snprintf(error_buffer.cpu(cpu), sizeof(error_buffer.cpu(0)), "%s", "Singlestep"); + + return really_break; +} + +// entered debugger due to debug exception +static inline NOEXPORT int +Jdb::handle_trap1(unsigned cpu) +{ + // FIXME: currently only on bot cpu + if (cpu != 0) + return 0; + + if (bp_test_sstep && bp_test_sstep()) + return handle_single_step(cpu); + + if (bp_test_break + && bp_test_break(error_buffer.cpu(cpu), sizeof(error_buffer.cpu(0)))) + return 1; + + if (bp_test_other + && bp_test_other(error_buffer.cpu(cpu), sizeof(error_buffer.cpu(0)))) + return 1; + + return 0; +} + +// entered debugger due to software breakpoint +static inline NOEXPORT int +Jdb::handle_trap3(unsigned cpu) +{ + Jdb_entry_frame *entry_frame = Jdb::entry_frame.cpu(cpu); + Space *task = get_task(cpu); + Unsigned8 op; + Unsigned8 len; + + snprintf(error_buffer.cpu(cpu), sizeof(error_buffer.cpu(0)), "%s", "INT 3"); + if ( !peek((Unsigned8*)entry_frame->ip(), task, op) + || !peek((Unsigned8*)(entry_frame->ip()+1), task, len) + || op != 0xeb) + return 1; + + char const *msg = (char const*)(entry_frame->ip()+2); + char buffer[3]; + if (!peek(msg, task, buffer[0])) + return 1; + + if (len > 1 && !peek(msg+1, task, buffer[1])) + return 1; + + // we are entering here because enter_kdebugger("*#..."); failed + if (len > 1 && buffer[0] == '*' && buffer[1] == '#') + { + unsigned i; + char ctrl[29]; + + len-=2; + msg+=2; + if (len && peek(msg, task, buffer[2])) + { + char tmp; + if (buffer[2] == '#') + { + // the ``-jdb_cmd='' sequence + msg = (char const*)entry_frame->value(); + for (i=0; i 0) + { + unsigned i; + len = len < 47 ? len : 47; + len = len < sizeof(error_buffer.cpu(0))-1 + ? len + : sizeof(error_buffer.cpu(0))-1; + + for(i=0; i_trapno)) + 1; + if ( pos < sizeof(error_buffer.cpu(0)) + && entry_frame.cpu(cpu)->_trapno >= 10 + && entry_frame.cpu(cpu)->_trapno <= 14) + snprintf(error_buffer.cpu(cpu)+pos, sizeof(error_buffer.cpu(0))-pos, + "(ERR=" L4_PTR_FMT ")", entry_frame.cpu(cpu)->_err); + + return 1; +} + +/** Int3 debugger interface. This function is called immediately + * after entering the kernel debugger. + * @return 1 if command was successfully interpreted + */ +IMPLEMENT +bool +Jdb::handle_user_request(unsigned cpu) +{ + Jdb_entry_frame *entry_frame = Jdb::entry_frame.cpu(cpu); + + if (entry_frame->_trapno == 3) + { + Space *task = get_task(cpu); + Unsigned8 todo; + if (!peek((Unsigned8*)entry_frame->ip(), task, todo)) + return false; + + // jmp == enter_kdebug() + if (todo == 0xeb) + { + Unsigned8 len; + if (!peek((Unsigned8*)(entry_frame->ip()+1), task, len)) + return false; + + char const *str = (char const *)(entry_frame->ip()+2); + char tmp; + + if (len <= 2) + return false; + + if (!peek(str, task, tmp) || tmp !='*') + return false; + + if (!peek(str+1, task, tmp) || tmp != '#') + return false; + + int ret; + + if (peek(str+2, task, tmp) && tmp == '#') + ret = execute_command_ni(task, (char const *)entry_frame->value()); + else + ret = execute_command_ni(task, str+2, len-2); + + if (ret) + return 1; + } + // cmpb + else if (todo == 0x3c) + { + if (!peek((Unsigned8*)(entry_frame->ip()+1), task, todo)) + return false; + + switch (todo) + { + case 29: + if (entry_frame->value() == 3) + { + Watchdog::disable(); + execute_command("Tgzip"); + Watchdog::enable(); + return 1; + } + break; + } + } + } + return 0; +} + +IMPLEMENT +void +Jdb::enter_trap_handler(unsigned cpu) +{ Cpu::cpus.cpu(cpu).debugctl_disable(); } + +IMPLEMENT +void +Jdb::leave_trap_handler(unsigned cpu) +{ Cpu::cpus.cpu(cpu).debugctl_enable(); } + +IMPLEMENT +bool +Jdb::handle_conditional_breakpoint(unsigned cpu) +{ return entry_frame.cpu(cpu)->_trapno == 1 && bp_test_log_only && bp_test_log_only(); } + +IMPLEMENT +void +Jdb::handle_nested_trap(Jdb_entry_frame *e) +{ + // re-enable interrupts if we need them because they are disabled + if (Config::getchar_does_hlt_works_ok) + Proc::sti(); + + switch (e->_trapno) + { + case 2: + cursor(Jdb_screen::height(), 1); + printf("\nNMI occured\n"); + break; + case 3: + cursor(Jdb_screen::height(), 1); + printf("\nSoftware breakpoint inside jdb at " L4_PTR_FMT "\n", + e->ip()-1); + break; + case 13: + switch (msr_test) + { + case Msr_test_fail_warn: + printf(" MSR does not exist or invalid value\n"); + msr_test = Msr_test_default; + msr_fail = 1; + break; + case Msr_test_fail_ignore: + msr_test = Msr_test_default; + msr_fail = 1; + break; + default: + cursor(Jdb_screen::height(), 1); + printf("\nGeneral Protection (eip=" L4_PTR_FMT "," + " err=" L4_PTR_FMT ") -- jdb bug?\n", + e->ip(), e->_err); + break; + } + break; + default: + cursor(Jdb_screen::height(), 1); + printf("\nInvalid access (trap=%02lx err=" L4_PTR_FMT + " pfa=" L4_PTR_FMT " eip=" L4_PTR_FMT ") " + "-- jdb bug?\n", + e->_trapno, e->_err, e->_cr2, e->ip()); + break; + } +} + +IMPLEMENT +bool +Jdb::handle_debug_traps(unsigned cpu) +{ + bool really_break = true; + + if (entry_frame.cpu(cpu)->_trapno == 1) + really_break = handle_trap1(cpu); + else if (entry_frame.cpu(cpu)->_trapno == 3) + really_break = handle_trap3(cpu); + else + really_break = handle_trapX(cpu); + + if (really_break) + { + for (unsigned i = 0; i < Config::Max_num_cpus; ++i) + { + if (!Cpu::online(i) || !running.cpu(i)) + continue; + // else S+ mode + if (!permanent_single_step.cpu(i)) + entry_frame.cpu(i)->flags(entry_frame.cpu(i)->flags() & ~EFLAGS_TF); + } + } + + return really_break; +} + +IMPLEMENT +bool +Jdb::test_checksums() +{ return Boot_info::get_checksum_ro() == Checksum::get_checksum_ro(); } + +PUBLIC static inline +void +Jdb::enter_getchar() +{} + +PUBLIC static inline +void +Jdb::leave_getchar() +{} + +//---------------------------------------------------------------------------- +IMPLEMENTATION [(ia32 || amd64) && mp]: + +static +void +Jdb::send_nmi(unsigned cpu) +{ + Apic::mp_send_ipi(Cpu::cpus.cpu(cpu).phys_id(), 0, Apic::APIC_IPI_NMI); +} diff --git a/kernel/fiasco/src/jdb/ia32/jdb-ia32-ux.cpp b/kernel/fiasco/src/jdb/ia32/jdb-ia32-ux.cpp new file mode 100644 index 00000000..1bb704ba --- /dev/null +++ b/kernel/fiasco/src/jdb/ia32/jdb-ia32-ux.cpp @@ -0,0 +1,126 @@ +INTERFACE[ia32,amd64,ux]: + +#include "jdb_core.h" +#include "jdb_handler_queue.h" +#include "jdb_entry_frame.h" +#include "trap_state.h" + +class Space; +class Thread; + +// ------------------------------------------------------------------------ +IMPLEMENTATION[ia32 || amd64 || ux]: + +#include "config.h" +#include "div32.h" +#include "kernel_console.h" +#include "paging.h" +#include "jdb_screen.h" + +PUBLIC static +void +Jdb::write_tsc_s(Signed64 tsc, char *buf, int maxlen, bool sign) +{ + Unsigned64 uns = Cpu::boot_cpu()->tsc_to_ns(tsc < 0 ? -tsc : tsc); + Unsigned32 ums = div32(uns, 1000000); + + if (tsc < 0) + uns = -uns; + + if (ums >= 3600000000U) + { + snprintf(buf, maxlen, ">999 h "); + return; + } + + if (sign) + { + *buf++ = (tsc < 0) ? '-' : (tsc == 0) ? ' ' : '+'; + maxlen--; + } + + if (ums >= 60000000) + { + // 1:00...999:00 h + Mword _h = ums / 3600000; + Mword _m = (ums - 3600000 * _h) / 60000; + snprintf(buf, maxlen, "%3lu:%02lu h ", _h, _m); + return; + } + + if (ums >= 1000000) + { + // 1:00...999:00 min + Mword _m = ums / 60000; + Mword _s = (ums - 60000 * _m) / 1000; + snprintf(buf, maxlen, "%3lu:%02lu min", _m, _s); + return; + } + + if (ums >= 1000) + { + // 1.000000...999.000000 s + Mword _s = ums / 1000; + Mword _us = div32(uns, 1000) - 1000000 * _s; + snprintf(buf, maxlen, "%3lu.%06lu s ", _s, _us); + return; + } + + if (uns == 0) + { + snprintf(buf, maxlen, " 0 "); + return; + } + + // 1.000000...999.000000 ms + Mword _ms = ums; + Mword _ns = ((Mword)uns - 1000000 * _ms); + snprintf(buf, maxlen, "%3lu.%06lu ms", _ms, _ns); +} + +PUBLIC static +void +Jdb::write_tsc(Signed64 tsc, char *buf, int maxlen, bool sign) +{ + Unsigned64 ns = Cpu::boot_cpu()->tsc_to_ns(tsc < 0 ? -tsc : tsc); + if (tsc < 0) + ns = -ns; + write_ll_ns(ns, buf, maxlen, sign); +} + +PUBLIC +static int +Jdb::get_register(char *reg) +{ + union + { + char c[4]; + Unsigned32 v; + } reg_name; + int i; + reg_name.v = 0; + + putchar(reg_name.c[0] = Jdb_screen::Reg_prefix); + + for (i = 1; i < 3; i++) + { + int c = getchar(); + if (c == KEY_ESC) + return false; + putchar(reg_name.c[i] = c & 0xdf); + if (c == '8' || c == '9') + break; + } + + reg_name.c[3] = '\0'; + + for (i = 0; i < Jdb_screen::num_regs(); i++) + if (reg_name.v == *((Unsigned32 *)(Jdb_screen::Reg_names[i]))) + break; + + if (i == Jdb_screen::num_regs()) + return false; + + *reg = i + 1; + return true; +} diff --git a/kernel/fiasco/src/jdb/ia32/jdb-int3-ia32-amd64.cpp b/kernel/fiasco/src/jdb/ia32/jdb-int3-ia32-amd64.cpp new file mode 100644 index 00000000..2a7098d5 --- /dev/null +++ b/kernel/fiasco/src/jdb/ia32/jdb-int3-ia32-amd64.cpp @@ -0,0 +1,70 @@ +IMPLEMENTATION[ia32,amd64]: + +#include "thread.h" + +/** + * Handle int3 extensions in the current thread's context. All functions + * for which we don't need/want to switch to the debugging stack. + * \return 0 if this function should be handled in the context of Jdb + * 1 successfully handled + */ +PRIVATE static +int +Jdb::handle_int3_threadctx(Trap_state *ts) +{ + if (handle_int3_threadctx_generic(ts)) + return 1; + + Thread *t = current_thread(); + Mem_space *s = t->mem_space(); + Address ip = ts->ip(); + Jdb_entry_frame *jef = reinterpret_cast(ts); + Address_type user = jef->from_user(); + + switch (s->peek((Unsigned8*)ip, user)) + { + case 0x3c: // cmpb + switch (s->peek((Unsigned8*)(ip+1), user)) + { + case 13: + ts->value(Vkey::get()); + Vkey::clear(); + break; + + case 31: // kernel watchdog + switch (ts->value2()) + { + case 1: + // enable watchdog + Watchdog::user_enable(); + break; + case 2: + // disable watchdog + Watchdog::user_disable(); + break; + case 3: + // user takes over the control of watchdog and is from now on + // responsible for calling "I'm still alive" events (function 5) + Watchdog::user_takeover_control(); + break; + case 4: + // user returns control of watchdog to kernel + Watchdog::user_giveback_control(); + break; + case 5: + // I'm still alive + Watchdog::touch(); + break; + } + break; + default: + return 0; // => Jdb + } + break; + + default: + return 0; // => Jdb + } + + return 1; +} diff --git a/kernel/fiasco/src/jdb/ia32/jdb-int3-ia32-ux.cpp b/kernel/fiasco/src/jdb/ia32/jdb-int3-ia32-ux.cpp new file mode 100644 index 00000000..eae3c6ee --- /dev/null +++ b/kernel/fiasco/src/jdb/ia32/jdb-int3-ia32-ux.cpp @@ -0,0 +1,239 @@ +IMPLEMENTATION[ia32,amd64,ux]: + +#include "jdb_dbinfo.h" +#include "jdb_lines.h" +#include "jdb_symbol.h" +#include "jdb_tbuf.h" +#include "thread.h" +#include "timer.h" + +/** + * Handle int3 extensions in the current thread's context. All functions + * for which we don't need/want to switch to the debugging stack. + * \return 0 if this function should be handled in the context of Jdb + * 1 successfully handled + */ +PRIVATE static +int +Jdb::handle_int3_threadctx_generic(Trap_state *ts) +{ + Thread *t = current_thread(); + Mem_space *s = t->mem_space(); + + //Obj_space *os = t->space()->obj_space(); + Address ip = ts->ip(); + Address_type user; + Unsigned8 *str, todo; + int len; + char c; + + Jdb_entry_frame *jef = reinterpret_cast(ts); + user = jef->from_user(); + todo = s->peek((Unsigned8*)ip, user); + + switch (todo) + { + case 0xeb: // jmp == enter_kdebug() + len = s->peek((Unsigned8*)(ip+1), user); + str = (Unsigned8*)(ip + 2); + + if ((len > 0) && s->peek(str, user) == '*') + { + int i; + + // skip '*' + len--; str++; + + if ((len > 0) && s->peek(str, user) == '#') + // special: enter_kdebug("*#...") + return 0; // => Jdb + + if (s->peek(str, user) == '+') + { + // special: enter_kdebug("*+...") => extended log msg + // skip '+' + len--; str++; + Tb_entry_ke_reg *tb = + static_cast(Jdb_tbuf::new_entry()); + tb->set(t, ip-1, ts); + for (i=0; iset_buf(i, s->peek(str++, user)); + tb->term_buf(len); + } + else + { + // special: enter_kdebug("*...") => log entry + // fill in entry + Tb_entry_ke *tb = + static_cast(Jdb_tbuf::new_entry()); + tb->set(t, ip-1); + for (i=0; iset_buf(i, s->peek(str++, user)); + tb->term_buf(len); + } + Jdb_tbuf::commit_entry(); + break; + } + return 0; // => Jdb + + case 0x90: // nop == l4kd_display() + if ( s->peek((Unsigned8*)(ip+1), user) != 0xeb /*jmp*/ + || (len = s->peek((Unsigned8*)(ip+2), user)) <= 0) + return 0; // => Jdb + str = (Unsigned8*)(ip + 3); + for (; len; len--) + putchar(s->peek(str++, user)); + break; + + case 0x3c: // cmpb + { + todo = s->peek((Unsigned8*)(ip+1), user); + Jdb_output_frame *regs = reinterpret_cast(ts); + switch (todo) + { + case 0: // l4kd_outchar + putchar(regs->value() & 0xff); + break; + case 1: // l4kd_outnstring + str = regs->str(); + len = regs->len(); + for(; len > 0; len--) + putchar(s->peek(str++, user)); + break; + case 2: // l4kd_outstr + str = regs->str(); + for (; (c=s->peek(str++, user)); ) + putchar(c); + break; + case 5: // l4kd_outhex32 + printf("%08lx", regs->value() & 0xffffffff); + break; + case 6: // l4kd_outhex20 + printf("%05lx", regs->value() & 0xfffff); + break; + case 7: // l4kd_outhex16 + printf("%04lx", regs->value() & 0xffff); + break; + case 8: // L4kd_outhex12 + printf("%03lx", regs->value() & 0xfff); + break; + case 9: // l4kd_outhex8 + printf("%02lx", regs->value() & 0xff); + break; + case 11: // l4kd_outdec + printf("%ld", regs->value()); + break; + case 13: // l4kd_inchar + return 0; // => Jdb + case 29: + switch (jef->param()) + { + case 0: // fiasco_tbuf_get_status() + { + Jdb_status_page_frame *regs = + reinterpret_cast(ts); + regs->set(Mem_layout::Tbuf_ustatus_page); + } + break; + case 1: // fiasco_tbuf_log() + { + // interrupts are disabled in handle_slow_trap() + Jdb_log_frame *regs = reinterpret_cast(ts); + Tb_entry_ke *tb = + static_cast(Jdb_tbuf::new_entry()); + str = regs->str(); + tb->set(t, ip-1); + for (len=0; (c = s->peek(str++, user)); len++) + tb->set_buf(len, c); + tb->term_buf(len); + regs->set_tb_entry(tb); + Jdb_tbuf::commit_entry(); + } + break; + case 2: // fiasco_tbuf_clear() + Jdb_tbuf::clear_tbuf(); + break; + case 3: // fiasco_tbuf_dump() + return 0; // => Jdb + case 4: // fiasco_tbuf_log_3val() + { + // interrupts are disabled in handle_slow_trap() + Jdb_log_3val_frame *regs = + reinterpret_cast(ts); + Tb_entry_ke_reg *tb = + static_cast(Jdb_tbuf::new_entry()); + str = regs->str(); + tb->set(t, ip-1, regs->val1(), regs->val2(), regs->val3()); + for (len=0; (c = s->peek(str++, user)); len++) + tb->set_buf(len, c); + tb->term_buf(len); + regs->set_tb_entry(tb); + Jdb_tbuf::commit_entry(); + } + break; + case 5: // fiasco_tbuf_get_status_phys() + { + Jdb_status_page_frame *regs = + reinterpret_cast(ts); + regs->set(s->virt_to_phys(Mem_layout::Tbuf_ustatus_page)); + } + break; + case 6: // fiasco_timer_disable + // XXX: no longer do Timer_tick::disable(0); + break; + case 7: // fiasco_timer_enable + // XXX: no longer do Timer_tick::enable(0); + break; + case 8: // fiasco_tbuf_log_binary() + // interrupts are disabled in handle_slow_trap() + Jdb_log_frame *regs = reinterpret_cast(ts); + Tb_entry_ke_bin *tb = + static_cast(Jdb_tbuf::new_entry()); + str = regs->str(); + tb->set(t, ip-1); + for (len=0; len < Tb_entry_ke_bin::SIZE; len++) + tb->set_buf(len, s->peek(str++, user)); + regs->set_tb_entry(tb); + Jdb_tbuf::commit_entry(); + break; + } + break; + case 30: +#if 0 + switch (ts->value2()) + { + case 1: // fiasco_register_symbols + { + Jdb_symbols_frame *regs = + reinterpret_cast(ts); + Jdb_dbinfo::set(Jdb_symbol::lookup(Kobject::dcast(os->lookup(regs->task()))), + regs->addr(), regs->size()); + } + break; + case 2: // fiasco_register_lines + { + Jdb_lines_frame *regs = + reinterpret_cast(ts); + Jdb_dbinfo::set(Jdb_lines::lookup(regs->task()), + regs->addr(), regs->size()); + } + break; + } +#endif + break; + default: // ko + if (todo < ' ') + return 0; // => Jdb + + putchar(todo); + break; + } + break; + } + + default: + return 0; // => Jdb + } + + return 1; +} diff --git a/kernel/fiasco/src/jdb/ia32/jdb_bp-ia32-amd64.cpp b/kernel/fiasco/src/jdb/ia32/jdb_bp-ia32-amd64.cpp new file mode 100644 index 00000000..5d8e70e3 --- /dev/null +++ b/kernel/fiasco/src/jdb/ia32/jdb_bp-ia32-amd64.cpp @@ -0,0 +1,175 @@ +INTERFACE[ia32,amd64]: + +EXTENSION class Jdb_bp +{ +private: + static int test_sstep(); + static int test_break(char *errbuf, size_t bufsize); + static int test_other(char *errbuf, size_t bufsize); + static int test_log_only(); + static Mword dr7; +}; + +#define write_debug_register(num, val) \ + asm volatile("mov %0, %%db" #num : : "r" ((Mword)val)) + +#define read_debug_register(num) \ + ({Mword val; asm volatile("mov %%db" #num ",%0" : "=r"(val)); val;}) + +IMPLEMENTATION[ia32,amd64]: + +#include "kmem.h" + +Mword Jdb_bp::dr7; + +PUBLIC inline NEEDS["kmem.h"] +void +Breakpoint::set(Address _addr, Mword _len, Mode _mode, Log _log) +{ + addr = _addr; + mode = _mode; + user = Kmem::is_kmem_page_fault(_addr, 0) ? ADDR_KERNEL : ADDR_USER; + log = _log; + len = _len; +} + +PUBLIC static inline +Mword +Jdb_bp::get_dr(Mword i) +{ + switch (i) + { + case 0: return read_debug_register(0); + case 1: return read_debug_register(1); + case 2: return read_debug_register(2); + case 3: return read_debug_register(3); + case 6: return read_debug_register(6); + case 7: return dr7; + default: return 0; + } +} + +IMPLEMENT +int +Jdb_bp::global_breakpoints() +{ + return 1; +} + +static +int +Jdb_bp::set_debug_address_register(int num, Mword addr, Mword len, + Breakpoint::Mode mode, Space *) +{ + clr_dr7(num, dr7); + set_dr7(num, len, mode, dr7); + switch (num) + { + case 0: write_debug_register(0, addr); break; + case 1: write_debug_register(1, addr); break; + case 2: write_debug_register(2, addr); break; + case 3: write_debug_register(3, addr); break; + default:; + } + return 1; +} + +static +void +Jdb_bp::clr_debug_address_register(int num) +{ + clr_dr7(num, dr7); +} + +IMPLEMENT +void +Jdb_bp::at_jdb_enter() +{ + dr7 = read_debug_register(7); + // disable breakpoints while we are in kernel debugger + write_debug_register(7, dr7 & Val_enter); +} + +IMPLEMENT +void +Jdb_bp::at_jdb_leave() +{ + write_debug_register(6, Val_leave); + write_debug_register(7, dr7); +} + +/** @return 1 if single step occured */ +IMPLEMENT +int +Jdb_bp::test_sstep() +{ + Mword dr6 = read_debug_register(6); + if (!(dr6 & Val_test_sstep)) + return 0; + + // single step has highest priority, don't consider other conditions + write_debug_register(6, Val_leave); + return 1; +} + +/** @return 1 if breakpoint occured */ +IMPLEMENT +int +Jdb_bp::test_break(char *errbuf, size_t bufsize) +{ + Mword dr6 = read_debug_register(6); + if (!(dr6 & Val_test)) + return 0; + + int ret = test_break(dr6, errbuf, bufsize); + write_debug_register(6, dr6 & ~Val_test); + return ret; +} + +/** @return 1 if other debug exception occured */ +IMPLEMENT +int +Jdb_bp::test_other(char *errbuf, size_t bufsize) +{ + Mword dr6 = read_debug_register(6); + if (!(dr6 & Val_test_other)) + return 0; + + snprintf(errbuf, bufsize, "unknown trap 1 (dr6=" L4_PTR_FMT ")", dr6); + write_debug_register(6, Val_leave); + return 1; +} + +/** @return 0 if only breakpoints were logged and jdb should not be entered */ +IMPLEMENT +int +Jdb_bp::test_log_only() +{ + Mword dr6 = read_debug_register(6); + + if (dr6 & Val_test) + { + dr7 = read_debug_register(7); + // disable breakpoints -- we might trigger a r/w breakpoint again + write_debug_register(7, dr7 & Val_enter); + test_log(dr6); + write_debug_register(6, dr6); + write_debug_register(7, dr7); + if (!(dr6 & Val_test_other)) + // don't enter jdb, breakpoints only logged + return 1; + } + // enter jdb + return 0; +} + +IMPLEMENT +void +Jdb_bp::init_arch() +{ + Jdb::bp_test_log_only = test_log_only; + Jdb::bp_test_break = test_break; + Jdb::bp_test_sstep = test_sstep; + Jdb::bp_test_other = test_other; +} + diff --git a/kernel/fiasco/src/jdb/ia32/jdb_bp-ia32-ux.cpp b/kernel/fiasco/src/jdb/ia32/jdb_bp-ia32-ux.cpp new file mode 100644 index 00000000..94ffab90 --- /dev/null +++ b/kernel/fiasco/src/jdb/ia32/jdb_bp-ia32-ux.cpp @@ -0,0 +1,838 @@ +INTERFACE[ia32,amd64,ux]: + +#include "initcalls.h" +#include "l4_types.h" + +class Thread; +class Task; +class Space; + +class Breakpoint +{ +public: + enum Mode { INSTRUCTION=0, WRITE=1, PORTIO=2, ACCESS=3 }; + enum Log { BREAK=0, LOG=1 }; + +private: + typedef struct + { + int other; + Mword thread; + } Bp_thread_res; + + typedef struct + { + int other; + Mword task; + } Bp_task_res; + + typedef struct + { + char reg; + Address y, z; + } Bp_reg_res; + + typedef struct + { + unsigned char len; + Address addr; + Address y, z; + } Bp_mem_res; + + typedef struct + { + Bp_thread_res thread; + Bp_task_res task; + Bp_reg_res reg; + Bp_mem_res mem; + } Restriction; + + Address addr; + Unsigned8 len; + Address_type user; + Mode mode; + Log log; + Restriction restrict; + static char const * const mode_names[4]; +}; + +class Jdb_bp +{ +public: + static int global_breakpoints(); + static void init_arch(); + +private: + static void at_jdb_enter(); + static void at_jdb_leave(); + static Breakpoint bps[4]; +}; + + +IMPLEMENTATION[ia32,amd64,ux]: + +#include + +#include "jdb.h" +#include "jdb_input.h" +#include "jdb_module.h" +#include "jdb_handler_queue.h" +#include "jdb_screen.h" +#include "jdb_tbuf.h" +#include "l4_types.h" +#include "static_init.h" +#include "task.h" +#include "thread.h" + +class Jdb_set_bp : public Jdb_module, public Jdb_input_task_addr +{ +public: + Jdb_set_bp() FIASCO_INIT; +private: + static char breakpoint_cmd; + static char breakpoint_restrict_cmd; + static Mword breakpoint_number; + static Mword breakpoint_length; + static Mword breakpoint_restrict_task; + static Mword breakpoint_restrict_thread; + typedef struct + { + char reg; + Mword low; + Mword high; + } Restrict_reg; + static Restrict_reg breakpoint_restrict_reg; + typedef struct + { + Address addr; + Mword low; + Mword high; + } Restrict_addr; + static Restrict_addr breakpoint_restrict_addr; + static int state; +}; + +Breakpoint Jdb_bp::bps[4]; + +char const * const Breakpoint::mode_names[4] = +{ + "instruction", "write access", "i/o access", "r/w access" +}; + +char Jdb_set_bp::breakpoint_cmd; +char Jdb_set_bp::breakpoint_restrict_cmd; +Mword Jdb_set_bp::breakpoint_number; +Mword Jdb_set_bp::breakpoint_length; +Mword Jdb_set_bp::breakpoint_restrict_task; +Mword Jdb_set_bp::breakpoint_restrict_thread; +Jdb_set_bp::Restrict_reg Jdb_set_bp::breakpoint_restrict_reg; +Jdb_set_bp::Restrict_addr Jdb_set_bp::breakpoint_restrict_addr; +int Jdb_set_bp::state; + +PUBLIC +Breakpoint::Breakpoint() +{ + restrict.thread.thread = 0; + restrict.task.task = 0; +} + +PUBLIC inline NOEXPORT +void +Breakpoint::kill() +{ + addr = 0; +} + +PUBLIC inline NOEXPORT +int +Breakpoint::unused() +{ + return addr == 0; +} + +PUBLIC inline NOEXPORT +int +Breakpoint::break_at_instruction() +{ + return mode == INSTRUCTION; +} + +PUBLIC inline NOEXPORT +int +Breakpoint::match_addr(Address virt, Mode m) +{ + return !unused() && addr == virt && mode == m; +} + +PUBLIC inline NOEXPORT +void +Breakpoint::set_logmode(char m) +{ + log = (m == '*') ? LOG : BREAK; +} + +PUBLIC inline NOEXPORT +int +Breakpoint::is_break() +{ + return !unused() && log == BREAK; +} + +PUBLIC inline +void +Breakpoint::restrict_task(int other, Mword task) +{ + restrict.task.other = other; + restrict.task.task = task; +} + +PUBLIC inline NOEXPORT +void +Breakpoint::restrict_thread(int other, Mword thread) +{ + restrict.thread.other = other; + restrict.thread.thread = thread; +} + +PUBLIC inline NOEXPORT +void +Breakpoint::restrict_register(char reg, Mword y, Mword z) +{ + restrict.reg.reg = reg; + restrict.reg.y = y; + restrict.reg.z = z; +} + +PUBLIC inline NOEXPORT +void +Breakpoint::restrict_memory(Mword addr, Mword len, Mword y, Mword z) +{ + restrict.mem.addr = addr; + restrict.mem.len = len; + restrict.mem.y = y; + restrict.mem.z = z; +} + +PUBLIC inline NOEXPORT +void +Breakpoint::clear_restriction() +{ + restrict.thread.thread = 0; + restrict.task.task = 0; + restrict.reg.reg = 0; + restrict.mem.len = 0; +} + +PUBLIC +void +Breakpoint::show() +{ + if (addr) + { + printf("%5s on %12s at " L4_PTR_FMT, + log ? "LOG" : "BREAK", mode_names[mode & 3], addr); + if (mode != INSTRUCTION) + printf(" len %d", len); + else + putstr(" "); + + if ( restrict.thread.thread == 0 + && restrict.task.task == 0 + && restrict.reg.reg == 0 + && restrict.mem.len == 0) + puts(" (not restricted)"); + else + { + int j = 0; +#if 0 + printf("\n%32s", "restricted to "); + if (restrict.thread.thread != (GThread_num)-1) + { + j++; + printf("thread%s %x.%x\n", + restrict.thread.other ? " !=" : "", + L4_uid::task_from_gthread (restrict.thread.thread), + L4_uid::lthread_from_gthread (restrict.thread.thread)); + } + if (restrict.task.task) + { + if (j++) + printf("%32s", "and "); + printf("task%s %p\n", + restrict.task.other ? " !=" : "", + restrict.task.task); + } +#endif + if (restrict.reg.reg != 0) + { + if (j++) + printf("%32s", "and "); + printf("register %s in [" L4_PTR_FMT ", " L4_PTR_FMT "]\n", + (restrict.reg.reg > 0) && (restrict.reg.reg < 10) + ? Jdb_screen::Reg_names[restrict.reg.reg-1] + : "???", + restrict.reg.y, restrict.reg.z); + } + if (restrict.mem.len != 0) + { + if (j++) + printf("%32s", "and "); + printf("%d-byte var at " L4_PTR_FMT " in [" L4_PTR_FMT ", " + L4_PTR_FMT "]\n", + restrict.mem.len, restrict.mem.addr, + restrict.mem.y, restrict.mem.z); + } + } + } + else + puts("disabled"); +} + +// return TRUE if the breakpoint does NOT match +// return FALSE if all restrictions do match +PUBLIC +int +Breakpoint::restricted(Thread *t) +{ + Jdb_entry_frame *e = Jdb::get_entry_frame(Jdb::current_cpu); + + Space *task = t->space(); +#if 0 + // investigate for thread restriction + if (restrict.thread.thread != (GThread_num)-1) + { + if (restrict.thread.other ^ (restrict.thread.thread != t->id().gthread())) + return 1; + } + + // investigate for task restriction + if (restrict.task.task) + { + if (restrict.task.other ^ (restrict.task.task != task)) + return 1; + } +#endif + // investigate for register restriction + if (restrict.reg.reg) + { + Mword val = e->get_reg(restrict.reg.reg); + Mword y = restrict.reg.y; + Mword z = restrict.reg.z; + + // return true if rules do NOT match + if ( (y <= z && (val < y || val > z)) + ||(y > z && (val >= z || val <= y))) + return 1; + } + + // investigate for variable restriction + if (restrict.mem.len) + { + Mword val = 0; + Mword y = restrict.mem.y; + Mword z = restrict.mem.z; + + if (Jdb::peek_task(restrict.mem.addr, task, &val, restrict.mem.len) != 0) + return 0; + + // return true if rules do NOT match + if ( (y <= z && (val < y || val > z)) + ||(y > z && (val >= z || val <= y))) + return 1; + } + + return 0; +} + +PUBLIC +int +Breakpoint::test_break(Thread *t, char *errbuf, size_t bufsize) +{ + if (restricted(t)) + return 0; + + Space *task = t->space(); + + snprintf(errbuf, bufsize, "break on %s at " L4_PTR_FMT, + mode_names[mode], addr); + if (mode==WRITE || mode==ACCESS) + { + // If it's a write or access (read) breakpoint, we look at the + // appropriate place and print the bytes we find there. We do + // not need to look if the page is present because the x86 CPU + // enters the debug exception immediately _after_ the memory + // access was performed. + size_t size = strlen(errbuf); + errbuf += size; + bufsize -= size; + Mword val = 0; + if (len > sizeof(Mword)) + return 0; + + if (Jdb::peek_task(addr, task, &val, len) != 0) + return 0; + + snprintf(errbuf, bufsize, " [%08lx]", val); + } + return 1; +} + +// Create log entry if breakpoint matches +PUBLIC +void +Breakpoint::test_log(Thread *t) +{ + Jdb_entry_frame *e = Jdb::get_entry_frame(Jdb::current_cpu); + + if (log && !restricted(t)) + { + Space *task = t->space(); + // log breakpoint + Mword value = 0; + + if (mode == WRITE || mode == ACCESS) + { + // If it's a write or access (read) breakpoint, we look at the + // appropriate place and print the bytes we find there. We do + // not need to look if the page is present because the x86 CPU + // enters the debug exception immediately _after_ the memory + // access was performed. + if (len > sizeof(Mword)) + return; + + if (Jdb::peek_task(addr, task, &value, len) != 0) + return; + } + + // is called with disabled interrupts + Tb_entry_bp *tb = static_cast(Jdb_tbuf::new_entry()); + tb->set(t, e->ip(), mode, len, value, addr); + Jdb_tbuf::commit_entry(); + } +} + + +STATIC_INITIALIZE_P(Jdb_bp, JDB_MODULE_INIT_PRIO); + +PUBLIC static FIASCO_INIT +void +Jdb_bp::init() +{ + static Jdb_handler enter(at_jdb_enter); + static Jdb_handler leave(at_jdb_leave); + + Jdb::jdb_enter.add(&enter); + Jdb::jdb_leave.add(&leave); + + init_arch(); +} + +static inline +void +Jdb_bp::clr_dr7(int num, Mword &dr7) +{ + dr7 &= ~(((3 + (3 <<2)) << (16 + 4*num)) + (3 << (2*num))); +} + +static inline +void +Jdb_bp::set_dr7(int num, Mword len, Breakpoint::Mode mode, Mword &dr7) +{ + // the encoding of length 8 is special + if (len == 8) + len = 3; + + dr7 |= ((((mode & 3) + ((len-1)<<2)) << (16 + 4*num)) + (2 << (2*num))); + dr7 |= 0x200; /* exact breakpoint enable (not available on P6 and below) */ +} + +PUBLIC static +int +Jdb_bp::set_breakpoint(int num, Address addr, Mword len, + Breakpoint::Mode mode, Breakpoint::Log log, + Task *task) +{ + if (set_debug_address_register(num, addr, len, mode, task)) + { + bps[num].set(addr, len, mode, log); + return 1; + } + + return 0; +} + +PUBLIC static +void +Jdb_bp::clr_breakpoint(int num) +{ + clr_debug_address_register(num); + bps[num].kill(); +} + +PUBLIC static inline NOEXPORT +void +Jdb_bp::logmode_breakpoint(int num, char mode) +{ + bps[num].set_logmode(mode); +} + +PUBLIC static +int +Jdb_bp::first_unused() +{ + int i; + + for (i=0; i<4 && !bps[i].unused(); i++) + ; + + return i; +} + +// Return 1 if a breakpoint hits +PUBLIC static +int +Jdb_bp::test_break(Mword dr6, char *errbuf, size_t bufsize) +{ + Thread *t = Jdb::get_thread(0); + Jdb_entry_frame *e = Jdb::get_entry_frame(0); + + for (int i=0; i<4; i++) + if (dr6 & (1<flags(e->flags() | EFLAGS_RF); + if (bps[i].test_break(t, errbuf, bufsize)) + return 1; + } + + return 0; +} + +// Create log entry if breakpoint matches. +// Return 1 if debugger should stop +PUBLIC static +void +Jdb_bp::test_log(Mword &dr6) +{ + Thread *t = Jdb::get_thread(0); + Jdb_entry_frame *e = Jdb::get_entry_frame(0); + + for (int i=0; i<4; i++) + if (dr6 & (1<flags(e->flags() | EFLAGS_RF); + // clear condition + dr6 &= ~(1<features() & FEAT_DE)) + { + puts(" I/O breakpoints not supported by this CPU"); + return NOTHING; + } + // fall through + case 'a': + case 'i': + case 'w': + if ((breakpoint_number = Jdb_bp::first_unused()) < 4) + { + fmt = " addr=%C"; + args = &Jdb_input_task_addr::first_char; + state = 1; // breakpoints are global for all tasks + return EXTRA_INPUT; + } + puts(" No breakpoints available"); + return NOTHING; + case 'l': + // show all breakpoints + Jdb_bp::list(); + return NOTHING; + case '-': + // delete breakpoint + case '+': + // set logmode of breakpoint to + case '*': + // set logmode of breakpoint to + case 'r': + // restrict breakpoint + fmt = " bpn=%1x"; + args = &breakpoint_number; + state = 2; + return EXTRA_INPUT; + case 't': + Jdb::execute_command("bt"); + break; + default: + return ERROR; + } + } + else switch (state) + { + case 1: + code = Jdb_input_task_addr::action(args, fmt, next_char); + if (code == ERROR) + return ERROR; + if (code == NOTHING) + // ok, continue + goto got_address; + // more input for Jdb_input_task_addr + return code; + case 2: + if (breakpoint_number < 1 || breakpoint_number > 4) + return ERROR; + // input is 1..4 but numbers are 0..3 + breakpoint_number -= 1; + // we know the breakpoint number + switch (breakpoint_cmd) + { + case '-': + Jdb_bp::clr_breakpoint(breakpoint_number); + putchar('\n'); + return NOTHING; + case '+': + case '*': + Jdb_bp::logmode_breakpoint(breakpoint_number, breakpoint_cmd); + putchar('\n'); + return NOTHING; + case 'r': + fmt = " %C"; + args = &breakpoint_restrict_cmd; + state = 5; + return EXTRA_INPUT; + default: + return ERROR; + } + break; + case 3: +got_address: + // address/task read + if (breakpoint_cmd != 'i') + { + fmt = " len (1, 2, 4...)=%1x"; + args = &breakpoint_length; + state = 4; + return EXTRA_INPUT; + } + breakpoint_length = 1; // must be 1 for instruction breakpoints + // fall through + case 4: + // length read + if (breakpoint_length & (breakpoint_length - 1)) + break; + if (breakpoint_length > sizeof(Mword)) + break; + switch (breakpoint_cmd) + { + default : return ERROR; + case 'i': mode = Breakpoint::INSTRUCTION; break; + case 'w': mode = Breakpoint::WRITE; break; + case 'p': mode = Breakpoint::PORTIO; break; + case 'a': mode = Breakpoint::ACCESS; break; + } + // abort if no address was given + if (Jdb_input_task_addr::addr() == (Address)-1) + return ERROR; + Jdb_bp::set_breakpoint(breakpoint_number, Jdb_input_task_addr::addr(), + breakpoint_length, mode, Breakpoint::BREAK, + Jdb_input_task_addr::task()); + putchar('\n'); + break; + case 5: + // restrict command read + switch (breakpoint_restrict_cmd) + { + case 'a': + case 'A': + fmt = (breakpoint_restrict_cmd=='A') + ? "task!=" L4_ADDR_INPUT_FMT "\n" + : "task==" L4_ADDR_INPUT_FMT "\n"; + args = &breakpoint_restrict_task; + state = 6; + return EXTRA_INPUT; + case 't': + case 'T': + fmt = (breakpoint_restrict_cmd=='T') + ? "thread!=%t\n" : "thread==%t\n"; + args = &breakpoint_restrict_thread; + state = 7; + return EXTRA_INPUT; + case 'e': + if (!Jdb::get_register(&breakpoint_restrict_reg.reg)) + return NOTHING; + fmt = " in [" L4_ADDR_INPUT_FMT "-" L4_ADDR_INPUT_FMT "]\n"; + args = &breakpoint_restrict_reg.low; + state = 8; + return EXTRA_INPUT; + case '1': + case '2': + case '4': + putchar(breakpoint_restrict_cmd); + fmt = "-byte addr=" L4_ADDR_INPUT_FMT + " between[" L4_ADDR_INPUT_FMT "-" L4_ADDR_INPUT_FMT "]\n"; + args = &breakpoint_restrict_addr; + state = 9; + return EXTRA_INPUT; + case '-': + Jdb_bp::clear_restriction(breakpoint_number); + putchar('\n'); + break; + default: + return ERROR; + } + break; + case 6: + // breakpoint restrict task read + Jdb_bp::restrict_task(breakpoint_number, + breakpoint_restrict_cmd == 'A', + breakpoint_restrict_task); + break; + case 7: + // breakpoint restrict thread read + Jdb_bp::restrict_thread(breakpoint_number, + breakpoint_restrict_cmd == 'T', + breakpoint_restrict_thread); + break; + case 8: + // breakpoint restrict register in range + Jdb_bp::restrict_register(breakpoint_number, + breakpoint_restrict_reg.reg, + breakpoint_restrict_reg.low, + breakpoint_restrict_reg.high); + break; + case 9: + // breakpoint restrict x-byte-value in range + Jdb_bp::restrict_memory(breakpoint_number, + breakpoint_restrict_addr.addr, + breakpoint_restrict_cmd - '0', + breakpoint_restrict_addr.low, + breakpoint_restrict_addr.high); + break; + } + } + return NOTHING; +} + +PUBLIC +Jdb_module::Cmd const * +Jdb_set_bp::cmds() const +{ + static Cmd cs[] = + { + { 0, "b", "bp", "%c", + "b{i|a|w|p}\tset breakpoint on instruction/access/write/io " + "access\n" + "b{-|+|*}\tdisable/enable/log breakpoint\n" + "bl\tlist breakpoints\n" + "br{t|T|a|A|e|1|2|4}\trestrict breakpoint to " + "(!)thread/(!)task/reg/mem", + &breakpoint_cmd }, + }; + + return cs; +} + +PUBLIC +int +Jdb_set_bp::num_cmds() const +{ + return 1; +} + +static Jdb_set_bp jdb_set_bp INIT_PRIORITY(JDB_MODULE_INIT_PRIO); diff --git a/kernel/fiasco/src/jdb/ia32/jdb_bt-ia32-ux.cpp b/kernel/fiasco/src/jdb/ia32/jdb_bt-ia32-ux.cpp new file mode 100644 index 00000000..cffb0127 --- /dev/null +++ b/kernel/fiasco/src/jdb/ia32/jdb_bt-ia32-ux.cpp @@ -0,0 +1,440 @@ +IMPLEMENTATION[ia32,amd64,ux]: + +#include +#include + +#include "config.h" +#include "jdb.h" +#include "jdb_input.h" +#include "jdb_kobject.h" +#include "jdb_lines.h" +#include "jdb_module.h" +#include "jdb_symbol.h" +#include "mem_layout.h" +#include "keycodes.h" +#include "thread_object.h" +#include "task.h" + +class Jdb_bt : public Jdb_module, public Jdb_input_task_addr +{ +public: + Jdb_bt() FIASCO_INIT; +private: + static char dummy; + static char first_char; + static char first_char_addr; + static Address addr; + static Thread * tid; + static Kobject *ko_tid; + static Space * task; +}; + +char Jdb_bt::dummy; +char Jdb_bt::first_char; +char Jdb_bt::first_char_addr; +Address Jdb_bt::addr; +Thread * Jdb_bt::tid; +Space *Jdb_bt::task; +Kobject *Jdb_bt::ko_tid; + +// determine the user level ebp and eip considering the current thread state +static void +Jdb_bt::get_user_eip_ebp(Address &eip, Address &ebp) +{ + if (!task) + { + // kernel thread doesn't execute user code -- at least we hope so :-) + ebp = eip = 0; + return; + } + + Thread *t = tid; + Address tcb_next = (Address)context_of(t->get_kernel_sp()) + Context::Size; + Mword *ktop = (Mword *)(Cpu::stack_align(tcb_next)); + Jdb::Guessed_thread_state state = Jdb::guess_thread_state(t); + + eip = ktop[-5]; + + if (state == Jdb::s_ipc) + { + // If thread is in IPC, EBP lays on the stack (see C-bindings). EBP + // location is by now dependent from ipc-type, maybe different for + // other syscalls, maybe unstable during calls but only for user EBP. + Mword entry_esp = ktop[-2]; + Mword entry_ss = ktop[-1]; + + if (entry_ss & 3) + { + // kernel entered from user level + if (eip >= Mem_layout::Syscalls) + { + if ((entry_esp & (sizeof(Mword)-1)) + || !Jdb::peek((Address*)entry_esp, task, eip)) + { + printf("\n esp page invalid"); + ebp = eip = 0; + return; + } + entry_esp += sizeof(Mword); + } + + if ((entry_esp & (sizeof(Mword)-1)) + ||!Jdb::peek((Mword*)entry_esp, task, ebp)) + { + printf("\n esp page invalid"); + ebp = eip = 0; + return; + } + } + } + else if (state == Jdb::s_pagefault) + { + // see pagefault handler gate stack layout + ebp = ktop[-6]; + } + else if (state == Jdb::s_slowtrap) + { + // see slowtrap handler gate stack layout + ebp = ktop[-13]; + } + else + { + // Thread is doing (probaly) no IPC currently so we guess the + // user ebp by following the kernel ebp upwards. Some kernel + // entry pathes (e.g. timer interrupt) push the ebp register + // like gcc. + ebp = get_user_ebp_following_kernel_stack(); + } + +} + +static Mword +Jdb_bt::get_user_ebp_following_kernel_stack() +{ + if (!Config::Have_frame_ptr) + return 0; + + Mword ebp, dummy; + + get_kernel_eip_ebp(dummy, dummy, ebp); + + for (int i=0; i<30 /* sanity check */; i++) + { + Mword m1, m2; + + if ( (ebp == 0) || (ebp & (sizeof(Mword)-1)) + || !Jdb::peek((Address*)ebp, 0 /*kernel*/, m1) + || !Jdb::peek((Address*)ebp+1, 0 /*kernel*/, m2)) + // invalid ebp -- leaving + return 0; + + ebp = m1; + + if (!Mem_layout::in_kernel_code(m2)) + { + if (m2 < Kmem::mem_user_max) + // valid user ebp found + return m1; + else + // invalid ebp + return 0; + } + } + + return 0; +} + +struct Is_current +{ + Thread *tid; + mutable Thread *c; + mutable unsigned cpu; + + void operator () (unsigned _cpu) const + { + Thread *t = Jdb::get_thread(_cpu); + if (t == tid) + { c = t; cpu = _cpu; } + } + +}; + +static void +Jdb_bt::get_kernel_eip_ebp(Mword &eip1, Mword &eip2, Mword &ebp) +{ + if (tid == Jdb::get_current_active()) + { + ebp = (Mword)__builtin_frame_address(3); + eip1 = eip2 = 0; + } + else + { + Is_current is_current; + + is_current.tid = tid; + is_current.c = 0; + is_current.cpu = 0; + + Jdb::foreach_cpu(is_current); + + Mword *ksp; + Mword tcb; + + if (is_current.c) + { + ksp = (Mword*)Jdb::entry_frame.cpu(is_current.cpu)->sp(); + tcb = (Mword)is_current.c; + printf("\n current on cpu %u\n", is_current.cpu); + } + else + { + ksp = (Mword*) tid->get_kernel_sp(); + tcb = Mword(tid); //Mem_layout::Tcbs + tid.gthread()*Context::size; + } + + Mword tcb_next = tcb + Context::Size; + + // search for valid ebp/eip + for (int i=0; (Address)(ksp+i+1)= tcb+0x180 && + ksp[i] < tcb_next-20 && + ksp[i] > (Address)(ksp+i)) + { + // valid frame pointer found + ebp = ksp[i ]; + eip1 = ksp[i+1]; + eip2 = ksp[0]; + return; + } + } + ebp = eip1 = eip2 = 0; + } +} + +/** Show one backtrace item we found. Add symbol name and line info */ +static void +Jdb_bt::show_item(int nr, Address ksp, Address addr, Address_type user) +{ + char buffer[74]; + + printf(" %s#%d " L4_PTR_FMT " " L4_PTR_FMT "", nr<10 ? " ": "", nr, ksp, addr); + + Address sym_addr = addr; + if (Jdb_symbol::match_addr_to_symbol_fuzzy(&sym_addr, + user == ADDR_KERNEL ? 0 : task, + buffer, + 56 < sizeof(buffer) + ? 56 : sizeof(buffer)) + // if the previous symbol is to far away assume that there is no + // symbol for that entry + && (addr-sym_addr < 1024)) + { + printf(" : %s", buffer); + if (addr-sym_addr) + printf(" %s+ 0x%lx\033[m", Jdb::esc_line, addr-sym_addr); + } + + // search appropriate line backwards starting from addr-1 because we + // don't want to see the line info for the next statement after the + // call but the line info for the call itself + Address line_addr = addr-1; + if (Jdb_lines::match_addr_to_line_fuzzy(&line_addr, + user == ADDR_KERNEL ? 0 : task, + buffer, sizeof(buffer)-1, 0) + // if the previous line is to far away assume that there is no + // line for that entry + && (addr-line_addr < 128)) + printf("\n%6s%s%s\033[m", "", Jdb::esc_line, buffer); + + putchar('\n'); +} + +static void +Jdb_bt::show_without_ebp() +{ + Mword *ksp = (Mword*) tid->get_kernel_sp(); + Mword tcb_next = Mword(tid) + Context::Size; + + // search for valid eip + for (int i=0, j=1; (Address)(ksp+i) 1) + { + if ( (ebp == 0) || (ebp & (sizeof(Mword)-1)) + || !Jdb::peek((Address*)ebp, task, m1) + || !Jdb::peek((Address*)ebp+1, task, m2)) + // invalid ebp -- leaving + return; + + ebp = m1; + + if ( (user==ADDR_KERNEL && !Mem_layout::in_kernel_code(m2)) + ||(user==ADDR_USER && (m2==0 || m2>Kmem::mem_user_max))) + // no valid eip found -- leaving + return; + } + else if (i == 1) + { + if (eip1 == 0) + continue; + m2 = eip1; + } + else + { + if (eip2 == 0) + continue; + m2 = eip2; + } + + show_item(i, ebp, m2, user); + } +} + +PUBLIC +Jdb_module::Action_code +Jdb_bt::action(int cmd, void *&args, char const *&fmt, int &next_char) +{ + if (cmd == 0) + { + Address eip, ebp; + + if (args == &dummy) + { + // default value for thread + tid = Jdb::get_current_active(); + fmt = "%C"; + args = &first_char; + return EXTRA_INPUT; + } + else if (args == &first_char) + { + if (first_char == 't') + { + putstr("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\033[K"); + fmt = " thread=%q"; + args = &ko_tid; + return EXTRA_INPUT; + } + else if (first_char == 'a') + { + putstr("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\033[K"); + fmt = " addr=%C"; + args = &Jdb_input_task_addr::first_char; + return EXTRA_INPUT; + } + else if (first_char != KEY_RETURN && first_char != ' ') + { + // ignore wrong input + fmt = "%C"; + return EXTRA_INPUT; + } + else + // backtrace from current thread + goto start_backtrace; + } + else if (args == &ko_tid) + { + { + tid = 0; + Kobject* o = ko_tid; + + if (o) + tid = Kobject::dcast(o); + + if (!tid) + { + puts(" Invalid thread id"); + return NOTHING; + } + } + +start_backtrace: + task = tid->space(); + get_user_eip_ebp(eip, ebp); + +start_backtrace_known_ebp: + printf("\n\nbacktrace (thread %lx, fp=" L4_PTR_FMT + ", pc=" L4_PTR_FMT "):\n", + tid->dbg_info()->dbg_id(), ebp, eip); + if (task != 0) + show(ebp, eip, 0, ADDR_USER); + if (!Config::Have_frame_ptr) + { + puts("\n --kernel-bt-follows-- " + "(don't trust w/o frame pointer!!)"); + task = 0; + show_without_ebp(); + } + else + { + Mword eip2; + puts("\n --kernel-bt-follows--"); + get_kernel_eip_ebp(eip, eip2, ebp); + task = 0; + show(ebp, eip, eip2, ADDR_KERNEL); + } + putchar('\n'); + } + else + { + Jdb_module::Action_code code; + + switch ((code = Jdb_input_task_addr::action(args, fmt, next_char))) + { + case ERROR: + return ERROR; + case NOTHING: + task = Jdb_input_task_addr::space(); + eip = 0; + ebp = Jdb_input_task_addr::addr(); + goto start_backtrace_known_ebp; + default: + return code; + } + } + } + return NOTHING; +} + +PUBLIC +Jdb_module::Cmd const * +Jdb_bt::cmds() const +{ + static Cmd cs[] = + { + { 0, "bt", "backtrace", " [a]ddr/[t]hread", + "bt[t][]\tshow backtrace of current/given " + "thread/addr", + &dummy }, + }; + return cs; +} + +PUBLIC +int +Jdb_bt::num_cmds() const +{ + return 1; +} + +IMPLEMENT +Jdb_bt::Jdb_bt() + : Jdb_module("INFO") +{} + +static Jdb_bt jdb_bt INIT_PRIORITY(JDB_MODULE_INIT_PRIO); + diff --git a/kernel/fiasco/src/jdb/ia32/jdb_entry_frame-ia32.cpp b/kernel/fiasco/src/jdb/ia32/jdb_entry_frame-ia32.cpp new file mode 100644 index 00000000..098e3ee4 --- /dev/null +++ b/kernel/fiasco/src/jdb/ia32/jdb_entry_frame-ia32.cpp @@ -0,0 +1,194 @@ +INTERFACE: + +#include "cpu.h" +#include "tb_entry.h" +#include "trap_state.h" +#include "tb_entry.h" + +class Jdb_entry_frame : public Trap_state +{}; + +class Jdb_output_frame : public Jdb_entry_frame +{}; + +class Jdb_status_page_frame : public Jdb_entry_frame +{}; + +class Jdb_log_frame : public Jdb_entry_frame +{}; + +class Jdb_log_3val_frame : public Jdb_log_frame +{}; + +class Jdb_debug_frame : public Jdb_entry_frame +{}; + +class Jdb_symbols_frame : public Jdb_debug_frame +{}; + +class Jdb_lines_frame : public Jdb_debug_frame +{}; + +//--------------------------------------------------------------------------- +IMPLEMENTATION[ia32,ux,amd64]: + +PUBLIC inline +bool +Jdb_entry_frame::debug_ipi() const +{ return _trapno == 0xee; } + +PUBLIC inline +Address_type +Jdb_entry_frame::from_user() const +{ return cs() & 3 ? ADDR_USER : ADDR_KERNEL; } + +PUBLIC inline +Address +Jdb_entry_frame::ksp() const +{ return (Address)&_sp; } + +PUBLIC inline +Address +Jdb_entry_frame::sp() const +{ return from_user() ? _sp : ksp(); } + +PUBLIC inline +Mword +Jdb_entry_frame::param() const +{ return _ax; } + + +//--------------------------------------------------------------------------- +IMPLEMENTATION[ia32,ux]: + +PUBLIC inline +Mword +Jdb_entry_frame::get_reg(unsigned reg) const +{ + Mword val = 0; + + switch (reg) + { + case 1: val = _ax; break; + case 2: val = _bx; break; + case 3: val = _cx; break; + case 4: val = _dx; break; + case 5: val = _bp; break; + case 6: val = _si; break; + case 7: val = _di; break; + case 8: val = _ip; break; + case 9: val = _sp; break; + case 10: val = _flags; break; + } + + return val; +} + + +//--------------------------------------------------------------------------- +IMPLEMENTATION[amd64]: + +PUBLIC inline +Mword +Jdb_entry_frame::get_reg(unsigned reg) const +{ + Mword val = 0; + + switch (reg) + { + case 1: val = _ax; break; + case 2: val = _bx; break; + case 3: val = _cx; break; + case 4: val = _dx; break; + case 5: val = _bp; break; + case 6: val = _si; break; + case 7: val = _di; break; + case 8: val = _r8; break; + case 9: val = _r9; break; + case 10: val = _r10; break; + case 11: val = _r11; break; + case 12: val = _r12; break; + case 13: val = _r13; break; + case 14: val = _r14; break; + case 15: val = _r15; break; + case 16: val = _ip; break; + case 17: val = _sp; break; + case 18: val = _flags; break; + } + + return val; +} + +//--------------------------------------------------------------------------- +IMPLEMENTATION[ia32,amd64]: + +PUBLIC inline NEEDS["cpu.h"] +Mword +Jdb_entry_frame::ss() const +{ return from_user() ? _ss : Cpu::get_ss(); } + +//--------------------------------------------------------------------------- +IMPLEMENTATION[ux]: + +PUBLIC +Mword +Jdb_entry_frame::ss() const +{ return _ss; } + +//--------------------------------------------------------------------------- +IMPLEMENTATION[ia32,ux,amd64]: + +PUBLIC inline +Unsigned8* +Jdb_output_frame::str() const +{ return (Unsigned8*)_ax; } + +PUBLIC inline +int +Jdb_output_frame::len() const +{ return (unsigned)_bx; } + +//--------------------------------------------------------------------------- +PUBLIC inline +void +Jdb_status_page_frame::set(Address status_page) +{ _ax = (Mword)status_page; } + +//--------------------------------------------------------------------------- +PUBLIC inline +Unsigned8* +Jdb_log_frame::str() const +{ return (Unsigned8*)_dx; } + +PUBLIC inline NEEDS["tb_entry.h"] +void +Jdb_log_frame::set_tb_entry(Tb_entry* tb_entry) +{ _ax = (Mword)tb_entry; } + +//--------------------------------------------------------------------------- +PUBLIC inline +Mword +Jdb_log_3val_frame::val1() const +{ return _cx; } + +PUBLIC inline +Mword +Jdb_log_3val_frame::val2() const +{ return _si; } + +PUBLIC inline +Mword +Jdb_log_3val_frame::val3() const +{ return _di; } + +//--------------------------------------------------------------------------- +PUBLIC inline +Mword +Jdb_debug_frame::addr() const +{ return _ax; } + +PUBLIC inline +Mword +Jdb_debug_frame::size() const +{ return _dx; } + diff --git a/kernel/fiasco/src/jdb/ia32/jdb_io_ports.cpp b/kernel/fiasco/src/jdb/ia32/jdb_io_ports.cpp new file mode 100644 index 00000000..aa74b25e --- /dev/null +++ b/kernel/fiasco/src/jdb/ia32/jdb_io_ports.cpp @@ -0,0 +1,235 @@ +IMPLEMENTATION[ia32,amd64]: + +#include +#include "simpleio.h" + +#include "io.h" +#include "jdb_module.h" +#include "jdb.h" +#include "pci.h" +#include "pic.h" +#include "static_init.h" + +/** + * Private IA32-I/O module. + */ +class Io_m : public Jdb_module +{ +public: + Io_m() FIASCO_INIT; + +private: + static char porttype; + + struct Port_io_buf { + unsigned adr; + unsigned val; + }; + + struct Pci_port_buf { + unsigned bus; + unsigned dev; + unsigned subdev; + unsigned reg; + unsigned val; + }; + + struct Irq_buf { + unsigned irq; + }; + + union Input_buffer { + Port_io_buf io; + Pci_port_buf pci; + Irq_buf irq; + }; + + static Input_buffer buf; +}; + +static Io_m io_m INIT_PRIORITY(JDB_MODULE_INIT_PRIO); + +char Io_m::porttype; +Io_m::Input_buffer Io_m::buf; + + +PUBLIC +Jdb_module::Action_code +Io_m::action( int cmd, void *&args, char const *&fmt, int &) +{ + static char const *const port_in_fmt = " addr=%8p"; + static char const *const port_out_fmt = " addr=%8p, val=%8x"; + static char const *const pci_in_fmt = + "\b\b\b\b\b\bPCI conf: bus=%2x, dev=%2x, subdev=%2x, reg=%2x"; + static char const *const pci_out_fmt = + "\b\b\b\b\b\bPCI conf: bus=%2x, dev=%2x, subdev=%2x, reg=%2x, val=%8x"; + static char const *const ack_irq_fmt = " ack IRQ=%2x"; + static char const *const mask_irq_fmt = " mask IRQ=%2x"; + static char const *const unmask_irq_fmt = " unmask IRQ=%2x"; + + unsigned answer = 0xffffffff; + + if(args != &buf) + { + args = &buf; + if (cmd==0) // in + { + switch (porttype) + { + case '1': + case '2': + case '4': fmt = port_in_fmt; return EXTRA_INPUT; + case 'p': fmt = pci_in_fmt; return EXTRA_INPUT; + default: + puts(" - unknown port type (must be 1,2,4 or p)"); + return NOTHING; + } + } + else // out + { + switch (porttype) + { + case '1': + case '2': + case '4': fmt = port_out_fmt; return EXTRA_INPUT; + case 'p': fmt = pci_out_fmt; return EXTRA_INPUT; + case 'a': fmt = ack_irq_fmt; return EXTRA_INPUT; + case 'm': fmt = mask_irq_fmt; return EXTRA_INPUT; + case 'u': fmt = unmask_irq_fmt; return EXTRA_INPUT; + default: + puts(" - unknown port type (must be 1,2,4,p,a,m or u)"); + return NOTHING; + } + } + } + else + { + switch (porttype) + { + case '1': // in/out 8bit + case '2': // in/out 16bit + case '4': // in/out 32bit + if (buf.io.adr == 0xffffffff) + return NOTHING; + if(cmd==0) // in + putstr(" => "); + switch (porttype) + { + case '1': + if (cmd==0) // in + { + if (buf.io.adr == Pic::MASTER_OCW) + printf("%02x (shadow of master-PIC register)\n", + Jdb::pic_status & 0x0ff); + else if (buf.io.adr == Pic::SLAVES_OCW) + printf("%02x (shadow of slave-PIC register)\n", + Jdb::pic_status >> 8); + else + { + answer = Io::in8(buf.io.adr); + printf("%02x\n", (int)answer); + } + } + else // out + { + if (buf.io.adr == Pic::MASTER_OCW) + { + Jdb::pic_status = + (Jdb::pic_status & 0xff00) | buf.io.val; + putstr(" (PIC mask will be set on \"g\")"); + } + else if (buf.io.adr == Pic::SLAVES_OCW) + { + Jdb::pic_status = + (Jdb::pic_status & 0x00ff) | (buf.io.val<<8); + putstr(" (PIC mask will be set on \"g\")"); + } + else + Io::out8(buf.io.val, buf.io.adr ); + } + break; + case '2': + if(cmd==0) // in + { + answer = Io::in16(buf.io.adr); + printf("%04x\n", answer); + } + else + Io::out16(buf.io.val, buf.io.adr); + break; + case '4': + if(cmd==0) // in + { + answer = Io::in32(buf.io.adr); + printf("%08x\n", answer); + } + else + Io::out32(buf.io.val, buf.io.adr ); + break; + } + if (cmd==1) + putchar('\n'); + break; + + case 'p': // pci + if (cmd == 0) + printf(" => 0x%08x", + Pci::read_cfg32 (buf.pci.bus, buf.pci.dev, buf.pci.subdev, + buf.pci.reg)); + else + Pci::write_cfg32 (buf.pci.bus, buf.pci.dev, buf.pci.subdev, + buf.pci.reg, buf.pci.val); + putchar('\n'); + break; + + case 'a': // manual acknowledge IRQ at pic + if (buf.irq.irq < 8) + Io::out8(0x60 + buf.irq.irq, Pic::MASTER_ICW); + else + { + Io::out8(0x60 + (buf.irq.irq & 7), Pic::SLAVES_ICW); + Io::out8(0x60 + 2, Pic::MASTER_ICW); + } + putchar('\n'); + break; + + case 'm': // manual mask IRQ + Jdb::pic_status |= (1 << buf.irq.irq); + puts(" (PIC mask will be set on \"g\")"); + break; + + case 'u': // manual unmask IRQ + Jdb::pic_status &= ~(Unsigned16)(1 << buf.irq.irq); + puts(" (PIC mask will be set on \"g\")"); + break; + } + } + return NOTHING; +} + +PUBLIC +int Io_m::num_cmds() const +{ + return 2; +} + +PUBLIC +Jdb_module::Cmd const * Io_m::cmds() const +{ + static Cmd cs[] = + { + { 0, "i", "in", " type:%c", + "i{1|2|4|p}\tin port", + &porttype }, + { 1, "o", "out", " type:%c", + "o{1|2|4|a|u|m}\tout port, ack/(un)mask/ack irq", + &porttype }, + }; + return cs; +} + +IMPLEMENT +Io_m::Io_m() + : Jdb_module("INFO") +{} + diff --git a/kernel/fiasco/src/jdb/ia32/jdb_iomap.cpp b/kernel/fiasco/src/jdb/ia32/jdb_iomap.cpp new file mode 100644 index 00000000..69317fee --- /dev/null +++ b/kernel/fiasco/src/jdb/ia32/jdb_iomap.cpp @@ -0,0 +1,156 @@ +IMPLEMENTATION[io]: + +#include +#include + +#include "config.h" +#include "jdb.h" +#include "jdb_module.h" +#include "kmem.h" +#include "mem_layout.h" +#include "simpleio.h" +#include "space.h" +#include "static_init.h" +#include "task.h" + +class Jdb_iomap : public Jdb_module +{ +public: + Jdb_iomap() FIASCO_INIT; +private: + static char first_char; + static Space *space; + Address task; +}; + +char Jdb_iomap::first_char; +Space *Jdb_iomap::space; + + +static void +Jdb_iomap::show() +{ + // base addresses of the two IO bitmap pages + Address bitmap_1, bitmap_2; + bitmap_1 = space->virt_to_phys(Mem_layout::Io_bitmap); + bitmap_2 = space->virt_to_phys(Mem_layout::Io_bitmap + Config::PAGE_SIZE); + + Jdb::clear_screen(); + + printf("\nIO bitmap for space %p ", space); + if(bitmap_1 == ~0UL && bitmap_2 == ~0UL) + { // no memory mapped for the IO bitmap + puts("not mapped"); + return; + } + else + { + putstr("mapped to ["); + if (bitmap_1 != ~0UL) + printf(L4_PTR_FMT " ", (Address)Kmem::phys_to_virt(bitmap_1)); + else + putstr(" -- "); + + if (bitmap_2 != ~0UL) + printf("/ " L4_PTR_FMT, (Address)Kmem::phys_to_virt(bitmap_2)); + else + putstr("/ -- "); + } + + puts("]\n\nPorts assigned:"); + + bool mapped = false, any_mapped = false; + unsigned count=0; + + for(unsigned i = 0; i < Mem_layout::Io_port_max; i++ ) + { + if (space->io_lookup(i) != mapped) + { + if(! mapped) + { + mapped = any_mapped = true; + printf("%04x-", i); + } + else + { + mapped = false; + printf("%04x ", i-1); + } + } + if(mapped) + count++; + } + if(mapped) + printf("%04x ", Mem_layout::Io_port_max -1); + + if (!any_mapped) + putstr(""); + + printf("\n\nPort counter: %ld ", space->get_io_counter() ); + if(count == space->get_io_counter()) + puts("(correct)"); + else + printf("%sshould be %d\033[m\n", Jdb::esc_emph, count); +} + +PUBLIC +Jdb_module::Action_code +Jdb_iomap::action(int cmd, void *&args, char const *&fmt, int &next_char) +{ + if (cmd == 0) + { + if (args == &first_char) + { + if (isxdigit(first_char)) + { + fmt = "%q"; + args = &task; + next_char = first_char; + return EXTRA_INPUT_WITH_NEXTCHAR; + } + else + task = 0; + } + else if (args != &task) + return NOTHING; + + if (!task) + return NOTHING; + + space = Kobject::dcast(reinterpret_cast(task)); + if (!space) + return NOTHING; + + show(); + } + + return NOTHING; +} + +PUBLIC +Jdb_module::Cmd const * +Jdb_iomap::cmds() const +{ + static Cmd cs[] = + { + { 0, "r", "iomap", "%C", + "r[]\tdisplay IO bitmap of current/given task", + &first_char }, + }; + return cs; +} + +PUBLIC +int +Jdb_iomap::num_cmds() const +{ + return 1; +} + +IMPLEMENT +Jdb_iomap::Jdb_iomap() + : Jdb_module("INFO") +{} + +static Jdb_iomap jdb_iomap INIT_PRIORITY(JDB_MODULE_INIT_PRIO); + diff --git a/kernel/fiasco/src/jdb/ia32/jdb_kern_info-dr.cpp b/kernel/fiasco/src/jdb/ia32/jdb_kern_info-dr.cpp new file mode 100644 index 00000000..71710bdf --- /dev/null +++ b/kernel/fiasco/src/jdb/ia32/jdb_kern_info-dr.cpp @@ -0,0 +1,38 @@ +IMPLEMENTATION[ia32,amd64]: + +#include +#include "simpleio.h" + +#include "jdb_bp.h" +#include "static_init.h" + +class Jdb_kern_info_dr : public Jdb_kern_info_module +{ +}; + +static Jdb_kern_info_dr k_d INIT_PRIORITY(JDB_MODULE_INIT_PRIO+1); + +PUBLIC +Jdb_kern_info_dr::Jdb_kern_info_dr() + : Jdb_kern_info_module('d', "Debug registers") +{ + Jdb_kern_info::register_subcmd(this); +} + +PUBLIC +void +Jdb_kern_info_dr::show() +{ + printf("dr0: " L4_PTR_FMT "\n" + "dr1: " L4_PTR_FMT "\n" + "dr2: " L4_PTR_FMT "\n" + "dr3: " L4_PTR_FMT "\n" + "dr6: " L4_PTR_FMT "\n" + "dr7: " L4_PTR_FMT "\n", + Jdb_bp::get_dr(0), + Jdb_bp::get_dr(1), + Jdb_bp::get_dr(2), + Jdb_bp::get_dr(3), + Jdb_bp::get_dr(6), + Jdb_bp::get_dr(7)); +} diff --git a/kernel/fiasco/src/jdb/ia32/jdb_kern_info-ia32-amd64.cpp b/kernel/fiasco/src/jdb/ia32/jdb_kern_info-ia32-amd64.cpp new file mode 100644 index 00000000..6135c247 --- /dev/null +++ b/kernel/fiasco/src/jdb/ia32/jdb_kern_info-ia32-amd64.cpp @@ -0,0 +1,399 @@ +IMPLEMENTATION[ia32,amd64,ux]: + +#include +#include +#include "simpleio.h" + +#include "config.h" +#include "cpu.h" +#include "gdt.h" +#include "idt.h" +#include "jdb_symbol.h" +#include "perf_cnt.h" +#include "pic.h" +#include "space.h" +#include "tss.h" + + +class Jdb_kern_info_idt : public Jdb_kern_info_module +{ +}; + +static Jdb_kern_info_idt k_I INIT_PRIORITY(JDB_MODULE_INIT_PRIO + 1); + +PUBLIC +Jdb_kern_info_idt::Jdb_kern_info_idt() + : Jdb_kern_info_module('I', "Interrupt Descriptor Table (IDT)") +{ + Jdb_kern_info::register_subcmd(this); +} + +PUBLIC +void +Jdb_kern_info_idt::show() +{ + Pseudo_descriptor idt_pseudo; + unsigned line = 0; + + Idt::get (&idt_pseudo); + + printf("idt base=" L4_PTR_FMT " limit=%04x (%04x bytes)\n", + idt_pseudo.base(), + (unsigned)((idt_pseudo.limit() + 1) / sizeof(Idt_entry)), + idt_pseudo.limit() + 1); + if (!Jdb_core::new_line(line)) + return; + + Idt_entry *ie = reinterpret_cast(idt_pseudo.base()); + for (unsigned i=0; i<(idt_pseudo.limit()+1)/sizeof(Idt_entry); i++) + { + printf("%3x: ",i); + ie[i].show(); + if (!Jdb_core::new_line(line)) + return; + } +} + +class Jdb_kern_info_test_tsc_scaler : public Jdb_kern_info_module +{ +}; + +static Jdb_kern_info_test_tsc_scaler k_tts INIT_PRIORITY(JDB_MODULE_INIT_PRIO+1); + +PUBLIC +Jdb_kern_info_test_tsc_scaler::Jdb_kern_info_test_tsc_scaler() + : Jdb_kern_info_module('T', "Test TSC scaler") +{ + Jdb_kern_info::register_subcmd(this); +} + +PUBLIC +void +Jdb_kern_info_test_tsc_scaler::show() +{ + while (Kconsole::console()->getchar(false) == -1) + { + Unsigned64 t; + t = Cpu::boot_cpu()->ns_to_tsc(Cpu::boot_cpu()->tsc_to_ns(Cpu::rdtsc())); + printf("Diff (press any key to stop): %lld\n", Cpu::rdtsc() - t); + } +} + +//--------------------------------------------------------------------------- +IMPLEMENTATION[ia32,amd64]: + +#include "io.h" + +class Jdb_kern_info_pic_state : public Jdb_kern_info_module +{ +}; + +static Jdb_kern_info_pic_state k_p INIT_PRIORITY(JDB_MODULE_INIT_PRIO+1); + +PUBLIC +Jdb_kern_info_pic_state::Jdb_kern_info_pic_state() + : Jdb_kern_info_module('p', "PIC ports") +{ + Jdb_kern_info::register_subcmd(this); +} + +void +Jdb_kern_info_pic_state::show() +{ + int i; + static char const hex[] = "0123456789ABCDEF"; + + // show important I/O ports + Io::out8_p(Pic::OCW_TEMPLATE | Pic::READ_NEXT_RD | Pic::READ_IS_ONRD, + Pic::MASTER_ICW ); + unsigned in_service = Io::in8(Pic::MASTER_ICW); + Io::out8_p(Pic::OCW_TEMPLATE | Pic::READ_NEXT_RD | Pic::READ_IR_ONRD, + Pic::MASTER_ICW); + unsigned requested = Io::in8(Pic::MASTER_ICW); + unsigned mask = Jdb::pic_status & 0x0ff; + printf("master PIC: in service:"); + for (i=7; i>=0; i--) + putchar((in_service & (1<=0; i--) + putchar((requested & (1<=0; i--) + putchar((mask & (1<> 8; + printf(" slave PIC: in service:"); + for (i=7; i>=0; i--) + putchar((in_service & (1<=0; i--) + putchar((requested & (1<=0; i--) + putchar((mask & (1<clock >> 32), + (unsigned) (Kip::k()->clock)); + + show_pdir(); + + Pseudo_descriptor gdt_pseudo, idt_pseudo; + Gdt::get (&gdt_pseudo); + Idt::get (&idt_pseudo); + printf ("idt : base=" L4_PTR_FMT " limit=%04x\n" + "gdt : base=" L4_PTR_FMT " limit=%04x\n", + idt_pseudo.base(), (idt_pseudo.limit()+1)/8, + gdt_pseudo.base(), (gdt_pseudo.limit()+1)/8); + + // print LDT + printf("ldt : %04x", Cpu::get_ldt()); + if (Cpu::get_ldt() != 0) + { + Gdt_entry *e = Cpu::boot_cpu()->get_gdt()->entries() + (Cpu::boot_cpu()->get_ldt() >> 3); + printf(": " L4_PTR_FMT "-" L4_PTR_FMT, + e->base(), e->base()+ e->size()); + } + + // print TSS + printf("\n" + "tr : %04x", Cpu::boot_cpu()->get_tr()); + if(Cpu::get_tr() != 0) + { + Gdt_entry *e = Cpu::boot_cpu()->get_gdt()->entries() + (Cpu::boot_cpu()->get_tr() >> 3); + printf(": " L4_PTR_FMT "-" L4_PTR_FMT ", iobitmap at " L4_PTR_FMT, + e->base(), e->base()+ e->size(), + e->base() + (reinterpret_cast(e->base())->_io_bit_map_offset)); + } + printf("\n" + "cr0 : " L4_PTR_FMT "\n" + "cr4 : " L4_PTR_FMT "\n", + Cpu::get_cr0(), Cpu::get_cr4()); +} + +class Jdb_kern_info_cpu : public Jdb_kern_info_module +{ +}; + +static Jdb_kern_info_cpu k_c INIT_PRIORITY(JDB_MODULE_INIT_PRIO + 1); + +PUBLIC +Jdb_kern_info_cpu::Jdb_kern_info_cpu() + : Jdb_kern_info_module('c', "CPU features") +{ + Jdb_kern_info::register_subcmd(this); +} + +PUBLIC +void +Jdb_kern_info_cpu::show() +{ + const char *perf_type = Perf_cnt::perf_type(); + char cpu_mhz[32]; + char time[32]; + unsigned hz; + static char const * const scheduler_mode[] + = { "PIT", "RTC", "APIC", "HPET" }; + + cpu_mhz[0] = '\0'; + if ((hz = Cpu::boot_cpu()->frequency())) + { + unsigned mhz = hz / 1000000; + hz -= mhz * 1000000; + unsigned khz = hz / 1000; + snprintf(cpu_mhz, sizeof(cpu_mhz), "%d.%03d MHz", mhz, khz); + } + + printf ("CPU: %s %s (%s)\n", + Cpu::boot_cpu()->model_str(), cpu_mhz, + Config::found_vmware ? "vmware" : "native"); + Cpu::boot_cpu()->show_cache_tlb_info(" "); + show_features(); + + if (Cpu::boot_cpu()->tsc()) + { + Unsigned32 hour, min, sec, ns; + Cpu::boot_cpu()->tsc_to_s_and_ns(Cpu::rdtsc(), &sec, &ns); + hour = sec / 3600; + sec -= hour * 3600; + min = sec / 60; + sec -= min * 60; + snprintf(time, sizeof(time), "%02d:%02d:%02d.%06d", + hour, min, sec, ns/1000); + } + else + strcpy(time, "not available"); + + printf("\nTimer interrupt source: %s (irq vector 0x%02x)" + "\nPerformance counters: %s" + "\nLast branch recording: %s" + "\nDebug store to memory: %s" + "\nTime stamp counter: %s" + "\n", + scheduler_mode[Config::Scheduler_mode], + Config::scheduler_irq_vector, + perf_type ? perf_type : "no", + Cpu::boot_cpu()->lbr_type() != Cpu::Lbr_unsupported + ? Cpu::boot_cpu()->lbr_type() == Cpu::Lbr_pentium_4 ? "P4" : "P6" + : "no", + Cpu::boot_cpu()->bts_type() != Cpu::Bts_unsupported + ? Cpu::boot_cpu()->bts_type() == Cpu::Bts_pentium_4 ? "P4" : "Pentium-M" + : "no", + time + ); +} + +class Jdb_kern_info_gdt : public Jdb_kern_info_module +{ +private: + static unsigned line; +}; + +static Jdb_kern_info_gdt k_g INIT_PRIORITY(JDB_MODULE_INIT_PRIO + 1); + +unsigned Jdb_kern_info_gdt::line; + +PUBLIC +Jdb_kern_info_gdt::Jdb_kern_info_gdt() + : Jdb_kern_info_module('g', "Global Descriptor Table (GDT)") +{ + Jdb_kern_info::register_subcmd(this); +} + +PRIVATE static +void +Jdb_kern_info_gdt::show_gdt(unsigned cpu) +{ + Gdt *gdt = Cpu::cpus.cpu(cpu).get_gdt(); + unsigned entries = Gdt::gdt_max / 8; + + if (Config::Max_num_cpus > 1) + printf("CPU%d: GDT base=" L4_PTR_FMT " limit=%04x (%04x bytes)\n", + cpu, (Mword)gdt, entries, Gdt::gdt_max); + else + printf("GDT base=" L4_PTR_FMT " limit=%04x (%04x bytes)\n", + (Mword)gdt, entries, Gdt::gdt_max); + + if (!Jdb_core::new_line(line)) + return; + + for (unsigned i = 0; i < entries; i++) + { + printf(" %02x: ", i * 8); + (*gdt)[i].show(); + if (!Jdb_core::new_line(line)) + return; + } +} + +PUBLIC +void +Jdb_kern_info_gdt::show() +{ + line = 0; + Jdb::foreach_cpu(&show_gdt); +} + +// ------------------------------------------------------------------------ +IMPLEMENTATION [(ia32 || amd64) && hpet_timer]: + +#include "hpet.h" + +class Jdb_kern_info_hpet_smm : public Jdb_kern_info_module +{}; + +static Jdb_kern_info_hpet_smm ki_smm INIT_PRIORITY(JDB_MODULE_INIT_PRIO + 1); + +PUBLIC +Jdb_kern_info_hpet_smm::Jdb_kern_info_hpet_smm() + : Jdb_kern_info_module('S', "SMM loop using HPET") +{ + Jdb_kern_info::register_subcmd(this); +} + +PUBLIC +void +Jdb_kern_info_hpet_smm::show() +{ + const unsigned config_spin_loops = 10000; + const unsigned config_hist_loops = 60; + unsigned delta = 1; + Mword counter_good = 0; + Mword histsum = 0; + Mword hist_loops = config_hist_loops; + + printf("HPET SMM Check: Press key to stop.\n"); + printf("HPET SMM Check Loop testing (loops=%d)\n", config_spin_loops); + + Hpet::hpet()->dump(); + Hpet::hpet()->enable(); + while (1) + { + Unsigned64 x1 = Hpet::hpet()->counter_val; + + int i = config_spin_loops; + while (i--) + asm volatile("" : : : "memory"); + + Unsigned64 diff = Hpet::hpet()->counter_val - x1; + + if (hist_loops) + { + histsum += diff; + --hist_loops; + + if (hist_loops == 0) + { + delta = (histsum + histsum / 9) / config_hist_loops; + printf("HPET SMM Check threshold=%dhpet-clks %lldus\n", + delta, + (delta * Hpet::hpet()->counter_clk_period()) / 1000000000ULL); + } + } + else + { + if (diff > delta && diff < (~0UL - delta * 2)) + { + printf("%lld %lldus (before %ld good iterations)\n", diff, + (diff * Hpet::hpet()->counter_clk_period()) / 1000000000ULL, + counter_good); + counter_good = 0; + if (Kconsole::console()->getchar(false) != -1) + break; + } + else + ++counter_good; + + if (counter_good % 30000 == 2) + if (Kconsole::console()->getchar(false) != -1) + break; + } + } +} diff --git a/kernel/fiasco/src/jdb/ia32/jdb_kern_info-ia32-ux.cpp b/kernel/fiasco/src/jdb/ia32/jdb_kern_info-ia32-ux.cpp new file mode 100644 index 00000000..28cb9c02 --- /dev/null +++ b/kernel/fiasco/src/jdb/ia32/jdb_kern_info-ia32-ux.cpp @@ -0,0 +1,142 @@ +IMPLEMENTATION[ia32,ux,amd64]: + +#include +#include +#include "simpleio.h" +#include "jdb_screen.h" + +PUBLIC +void +Jdb_kern_info_cpu::show_f_bits(unsigned features, const char *const *table, + unsigned first_pos, unsigned &last_pos, + unsigned &colon) +{ + unsigned i, count; + + for (i = count = 0; *table != (char *)-1; i++, table++) + if ((features & (1 << i)) && *table) + { + int slen = strlen(*table); + if (last_pos+colon + slen > 78) + { + colon = 0; + last_pos = first_pos; + printf("\n%*s", first_pos, ""); + } + printf ("%s%s", colon ? ", " : "", *table); + last_pos += slen + colon; + colon = 2; + } +} + +PUBLIC +void +Jdb_kern_info_cpu::show_features() +{ + static const char *const simple[] = + { + "fpu (fpu on chip)", + "vme (virtual-8086 mode enhancements)", + "de (I/O breakpoints)", + "pse (4MB pages)", + "tsc (rdtsc instruction)", + "msr (rdmsr/rdwsr instructions)", + "pae (physical address extension)", + "mce (machine check exception #18)", + "cx8 (cmpxchg8 instruction)", + "apic (on-chip APIC)", + NULL, + "sep (sysenter/sysexit instructions)", + "mtrr (memory type range registers)", + "pge (global TLBs)", + "mca (machine check architecture)", + "cmov (conditional move instructions)", + "pat (page attribute table)", + "pse36 (32-bit page size extension)", + "psn (processor serial number)", + "clfsh (flush cache line instruction)", + NULL, + "ds (debug store to memory)", + "acpi (thermal monitor and soft controlled clock)", + "mmx (MMX technology)", + "fxsr (fxsave/fxrstor instructions)", + "sse (SSE extensions)", + "sse2 (SSE2 extensions)", + "ss (self snoop of own cache structures)", + "htt (hyper-threading technology)", + "tm (thermal monitor)", + NULL, + "pbe (pending break enable)", + (char *)(-1) + }; + static const char *const extended[] = + { + "pni (prescott new instructions)", + NULL, NULL, + "monitor (monitor/mwait instructions)", + "dscpl (CPL qualified debug store)", + "vmx (virtual machine technology)", + NULL, + "est (enhanced speedstep technology)", + "tm2 (thermal monitor 2)", + NULL, + "cid (L1 context id)", + NULL, NULL, + "cmpxchg16b", + "xtpr (send task priority messages)", + NULL, NULL, NULL, NULL, + "sse41", "sse42", + NULL, NULL, + "popcnt", NULL, + "aes", "xsave", "osxsave", + "avx", "f16c", + (char *)(-1) + }; + static const char *const ext_81_ecx[] = + { + NULL, NULL, "svm (secure virtual machine)", NULL, NULL, + "abm (adv bit manipulation)", "SSE4A", NULL, + NULL, "OSVW (OS visible workaround)", NULL, NULL, + "SKINIT", "WDT (watchdog timer support)", NULL, + "lwp", "fmaa", NULL, NULL, "nodeid", NULL, "tbm", "topext", + (char *)(-1) + }; + static const char *const ext_81_edx[] = + { + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, + "syscall (syscall/sysret instructions)", + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, + "mp (MP capable)", + "nx (no-execute page protection)", + NULL, + "mmxext (AMD extensions to MMX)", + NULL, NULL, + "fxsr_opt (FXSR optimizations)", + "Page1GB", + "RDTSCP", + NULL, // reserved + "lm (Long mode)", + "3dnowext (AMD 3DNow! extenstion)", + "3dnow (3DNow! instructions)", + (char *)(-1) + }; + + unsigned position = 5, colon = 0; + putstr("CPU features:\n "); + show_f_bits (Cpu::boot_cpu()->features(), simple, 5, position, colon); + show_f_bits (Cpu::boot_cpu()->ext_features(), extended, 5, position, colon); + show_f_bits (Cpu::boot_cpu()->ext_8000_0001_ecx(), ext_81_ecx, 5, position, colon); + show_f_bits (Cpu::boot_cpu()->ext_8000_0001_edx(), ext_81_edx, 5, position, colon); +} + +PRIVATE inline NEEDS["jdb_screen.h"] +void +Jdb_kern_info_misc::show_pdir() +{ + Mem_space *s = Mem_space::current_mem_space(0); + printf("%s" L4_PTR_FMT "\n", + Jdb_screen::Root_page_table, (Address)s->dir()); +} diff --git a/kernel/fiasco/src/jdb/ia32/jdb_kern_info-mtrr.cpp b/kernel/fiasco/src/jdb/ia32/jdb_kern_info-mtrr.cpp new file mode 100644 index 00000000..49533443 --- /dev/null +++ b/kernel/fiasco/src/jdb/ia32/jdb_kern_info-mtrr.cpp @@ -0,0 +1,83 @@ +IMPLEMENTATION: + +#include "static_init.h" + +class Jdb_kern_info_mtrr : public Jdb_kern_info_module +{ + Address size_or_mask; +}; + +static Jdb_kern_info_mtrr k_M INIT_PRIORITY(JDB_MODULE_INIT_PRIO+1); + +PUBLIC +Jdb_kern_info_mtrr::Jdb_kern_info_mtrr() + : Jdb_kern_info_module('M', "Memory type range registers (MTRRs)") +{ + if (!(Cpu::boot_cpu()->features() & FEAT_MTRR)) + return; + + size_or_mask = ~((1 << (Cpu::boot_cpu()->phys_bits() - Config::PAGE_SHIFT)) - 1); + Jdb_kern_info::register_subcmd(this); +} + +PRIVATE +void +Jdb_kern_info_mtrr::get_var_mtrr(int reg, Address *ret_base, + Address *ret_size, int *ret_type) +{ + Unsigned64 mask = Cpu::rdmsr(0x201 + 2*reg); + Unsigned64 base; + + if ((mask & 0x800) == 0) + { + /* MTRR not active */ + *ret_size = 0; + return; + } + + Jdb::msr_fail = 0; + Jdb::msr_test = Jdb::Msr_test_fail_ignore; + base = Cpu::rdmsr(0x200 + 2*reg); + Jdb::msr_test = Jdb::Msr_test_default; + if (Jdb::msr_fail) + { + /* invalid MSR */ + *ret_size = 0; + return; + } + + *ret_size = (-(size_or_mask | mask >> Config::PAGE_SHIFT)) + << Config::PAGE_SHIFT; + *ret_base = base & Config::PAGE_MASK; + *ret_type = base & 0x0f; +} + +PUBLIC +void +Jdb_kern_info_mtrr::show() +{ + int num_mtrr; + static const char * const typestr[] = + { + "uncacheable (UC)", "write combining (WC)", "??", "??", + "write-through (WT)", "write-protected (WP)", "write back (WB)", "??" + }; + Jdb::msr_fail = 0; + Jdb::msr_test = Jdb::Msr_test_fail_ignore; + num_mtrr = Cpu::rdmsr(0xfe) & 0xff; + Jdb::msr_test = Jdb::Msr_test_default; + if (Jdb::msr_fail) + num_mtrr = 8; + for (int i=0; i= 8 << 20 ? (size+(1<<19)-1) >> 20 : (size+(1<<9)-1) >> 10, + size >= 8 << 20 ? 'M' : 'K', + typestr[type]); + } +} diff --git a/kernel/fiasco/src/jdb/ia32/jdb_kern_info-pci.cpp b/kernel/fiasco/src/jdb/ia32/jdb_kern_info-pci.cpp new file mode 100644 index 00000000..de0f1f12 --- /dev/null +++ b/kernel/fiasco/src/jdb/ia32/jdb_kern_info-pci.cpp @@ -0,0 +1,66 @@ +IMPLEMENTATION[ia32,amd64]: + +#include +#include "pci.h" +#include "simpleio.h" +#include "static_init.h" + +class Jdb_kern_info_pci : public Jdb_kern_info_module +{ +}; + +static Jdb_kern_info_pci k_P INIT_PRIORITY(JDB_MODULE_INIT_PRIO+1); + +PUBLIC +Jdb_kern_info_pci::Jdb_kern_info_pci() + : Jdb_kern_info_module('P', "PCI devices") +{ + Jdb_kern_info::register_subcmd(this); +} + +PUBLIC +void +Jdb_kern_info_pci::show() +{ + static const char * const classes[] = + { "unknown", "mass storage contoller", "network controller", + "display controller", "multimedia device", "memory controller", + "bridge device", "simple communication controller", + "system peripheral", "input device", "docking station", + "processor", "serial bus controller", "wireless controller", + "intelligent I/O controller", "satellite communication controller", + "encryption/decryption controller", + "data aquisition/signal processing controller" }; + Mword bus, buses, dev, subdev, subdevs; + + for (bus=0, buses=1; bus +#include "config.h" +#include "cpu.h" +#include "jdb.h" +#include "jdb_ktrace.h" +#include "jdb_module.h" +#include "jdb_symbol.h" +#include "jdb_screen.h" +#include "static_init.h" +#include "task.h" +#include "x86desc.h" + +class Jdb_misc_general : public Jdb_module +{ +public: + Jdb_misc_general() FIASCO_INIT; +private: + static char first_char; +}; + +char Jdb_misc_general::first_char; + + +PUBLIC +Jdb_module::Action_code +Jdb_misc_general::action(int cmd, void *&, char const *&, int &) +{ + switch (cmd) + { + case 0: + // escape key + if (first_char == '+' || first_char == '-') + { + putchar(first_char); + Config::esc_hack = (first_char == '+'); + putchar('\n'); + return NOTHING; + } + return ERROR; + } + + return NOTHING; +} + +PUBLIC +Jdb_module::Cmd const * +Jdb_misc_general::cmds() const +{ + static Cmd cs[] = + { + { 0, "E", "esckey", "%C", + "E{+|-}\ton/off enter jdb by pressing ", + &first_char }, + }; + return cs; +} + +PUBLIC +int +Jdb_misc_general::num_cmds() const +{ + return 1; +} + +IMPLEMENT +Jdb_misc_general::Jdb_misc_general() + : Jdb_module("GENERAL") +{ +} + +static Jdb_misc_general jdb_misc_general INIT_PRIORITY(JDB_MODULE_INIT_PRIO); + + +//---------------------------------------------------------------------------// + +class Jdb_misc_debug : public Jdb_module +{ +public: + Jdb_misc_debug() FIASCO_INIT; +private: + static char first_char; + static Mword task; +}; + +char Jdb_misc_debug::first_char; +Mword Jdb_misc_debug::task; + +static void +Jdb_misc_debug::show_lbr_entry(const char *str, Address addr) +{ + char symbol[60]; + + printf("%s " L4_PTR_FMT " ", str, addr); + if (Jdb_symbol::match_addr_to_symbol_fuzzy(&addr, 0, symbol, sizeof(symbol))) + printf("(%s)", symbol); +} + +PUBLIC +Jdb_module::Action_code +Jdb_misc_debug::action(int cmd, void *&args, char const *&fmt, int &) +{ + switch (cmd) + { + case 0: + // single step + if (first_char == '+' || first_char == '-') + { + putchar(first_char); + Jdb::set_single_step(Jdb::current_cpu, first_char == '+'); + putchar('\n'); + } + break; + case 1: + // ldt + if (args == &task) + { + show_ldt(); + putchar('\n'); + return NOTHING; + } + + // lbr/ldt + if (first_char == '+' || first_char == '-') + { + Cpu::boot_cpu()->lbr_enable(first_char == '+'); + putchar(first_char); + putchar('\n'); + } + else if (first_char == 'd') + { + printf("d task="); + fmt = "%q"; + args = &task; + return EXTRA_INPUT; + } + else + { + Jdb::msr_test = Jdb::Msr_test_fail_warn; + if (Cpu::boot_cpu()->lbr_type() == Cpu::Lbr_pentium_4 || + Cpu::boot_cpu()->lbr_type() == Cpu::Lbr_pentium_4_ext) + { + Unsigned64 msr; + Unsigned32 branch_tos; + + msr = Cpu::rdmsr(MSR_LER_FROM_LIP); + show_lbr_entry("\nbefore exc:", (Address)msr); + msr = Cpu::rdmsr(MSR_LER_TO_LIP); + show_lbr_entry(" =>", (Address)msr); + + msr = Cpu::rdmsr(MSR_LASTBRANCH_TOS); + branch_tos = (Unsigned32)msr; + + if (Cpu::boot_cpu()->lbr_type() == Cpu::Lbr_pentium_4) + { + // older P4 models provide a stack of 4 MSRs + for (int i=0, j=branch_tos & 3; i<4; i++) + { + j = (j+1) & 3; + msr = Cpu::rdmsr(MSR_LASTBRANCH_0+j); + show_lbr_entry("\nbranch/exc:", (Address)(msr >> 32)); + show_lbr_entry(" =>", (Address)msr); + } + } + else + { + // newer P4 models provide a stack of 16 MSR pairs + for (int i=0, j=branch_tos & 15; i<16; i++) + { + j = (j+1) & 15; + msr = Cpu::rdmsr(0x680+j); + show_lbr_entry("\nbranch/exc:", (Address)msr); + msr = Cpu::rdmsr(0x6c0+j); + show_lbr_entry(" =>", (Address)msr); + } + } + } + else if (Cpu::boot_cpu()->lbr_type() == Cpu::Lbr_pentium_6) + { + Unsigned64 msr; + + msr = Cpu::rdmsr(MSR_LASTBRANCHFROMIP); + show_lbr_entry("\nbranch:", (Address)msr); + msr = Cpu::rdmsr(MSR_LASTBRANCHTOIP); + show_lbr_entry(" =>", (Address)msr); + msr = Cpu::rdmsr(MSR_LASTINTFROMIP); + show_lbr_entry("\n int:", (Address)msr); + msr = Cpu::rdmsr(MSR_LASTINTTOIP); + show_lbr_entry(" =>", (Address)msr); + } + else + printf("Last branch recording feature not available"); + + Jdb::msr_test = Jdb::Msr_test_default; + putchar('\n'); + break; + } + } + + return NOTHING; +} + +PUBLIC +Jdb_module::Cmd const * +Jdb_misc_debug::cmds() const +{ + static Cmd cs[] = + { + { 0, "S", "singlestep", "%C", + "S{+|-}\ton/off permanent single step mode", + &first_char }, + { 1, "L", "lbr", "%C", + "L\tshow last branch recording information\n" + "Ld\tshow LDT of specific task", + &first_char }, + }; + return cs; +} + +PUBLIC +int +Jdb_misc_debug::num_cmds() const +{ + return 2; +} + +IMPLEMENT +Jdb_misc_debug::Jdb_misc_debug() + : Jdb_module("DEBUGGING") +{ +} + +static Jdb_misc_debug jdb_misc_debug INIT_PRIORITY(JDB_MODULE_INIT_PRIO); + + +static void +Jdb_misc_debug::show_ldt() +{ + Space *s = Kobject::dcast(reinterpret_cast(task)); + Address addr, size; + + if (!s) + { + printf(" -- invalid task number '%lx'", task); + return; + } + + addr = s->_ldt.addr(); + size = s->_ldt.size(); + + if (!size) + { + printf(" -- no LDT active"); + return; + } + + printf("\nLDT of space %lx at " L4_PTR_FMT "-" L4_PTR_FMT "\n", task, addr, addr+size-1); + + Gdt_entry *desc = reinterpret_cast(addr); + + for (; size>=Cpu::Ldt_entry_size; size-=Cpu::Ldt_entry_size, desc++) + { + if (desc->present()) + { + printf(" %5lx: ", (Mword)desc - addr); + desc->show(); + } + } +} + +class Jdb_misc_info : public Jdb_module +{ +public: + Jdb_misc_info() FIASCO_INIT; +private: + static char first_char; + static Address addr; + static Mword value; + static Unsigned64 value64; +}; + +char Jdb_misc_info::first_char; +Address Jdb_misc_info::addr; +Mword Jdb_misc_info::value; +Unsigned64 Jdb_misc_info::value64; + +PUBLIC +Jdb_module::Action_code +Jdb_misc_info::action(int cmd, void *&args, char const *&fmt, int &) +{ + switch (cmd) + { + case 0: + // read/write physical memory + if (args == &first_char) + { + if (first_char == 'r' || first_char == 'w') + { + putchar(first_char); + fmt = "%8x"; + args = &addr; + return EXTRA_INPUT; + } + } + else if (args == &addr || args == &value) + { + addr &= ~(sizeof(Mword)-1); + if (args == &value) + Jdb::poke_phys(addr, &value, sizeof(value)); + if (first_char == 'w' && args == &addr) + putstr(" ("); + else + putstr(" => "); + Jdb::peek_phys(addr, &value, sizeof(value)); + printf(L4_MWORD_FMT, value); + if (first_char == 'w' && args == &addr) + { + putstr(") new value="); + fmt = L4_MWORD_FMT; + args = &value; + return EXTRA_INPUT; + } + putchar('\n'); + } + break; + + case 1: + // read/write machine status register + if (!Cpu::boot_cpu()->can_wrmsr()) + { + puts("MSR not supported"); + return NOTHING; + } + + if (args == &first_char) + { + if (first_char == 'r' || first_char == 'w') + { + putchar(first_char); + fmt = L4_ADDR_INPUT_FMT; + args = &addr; + return EXTRA_INPUT; + } + } + else if (args == &addr || args == &value64) + { + Jdb::msr_test = Jdb::Msr_test_fail_warn; + if (args == &value64) + Cpu::wrmsr(value64, addr); + if (first_char == 'w' && (args == &addr)) + putstr(" ("); + else + putstr(" => "); + value64 = Cpu::rdmsr(addr); + printf(L4_X64_FMT, value64); + if (first_char == 'w' && (args == &addr)) + { + putstr(") new value="); + fmt = L4_X64_FMT; + args = &value64; + return EXTRA_INPUT; + } + putchar('\n'); + Jdb::msr_test = Jdb::Msr_test_default; + } + break; + } + + return NOTHING; +} + +PUBLIC +Jdb_module::Cmd const * +Jdb_misc_info::cmds() const +{ + static Cmd cs[] = + { + { 0, "A", "adapter", "%C", + "A{r|w}\tread/write any physical address", + &first_char }, + { 1, "M", "msr", "%C", + "M{r|w}\tread/write machine status register", + &first_char }, + }; + return cs; +} + +PUBLIC +int +Jdb_misc_info::num_cmds() const +{ + return 2; +} + +IMPLEMENT +Jdb_misc_info::Jdb_misc_info() + : Jdb_module("INFO") +{ +} + +static Jdb_misc_info jdb_misc_info INIT_PRIORITY(JDB_MODULE_INIT_PRIO); diff --git a/kernel/fiasco/src/jdb/ia32/jdb_screen-ia32.cpp b/kernel/fiasco/src/jdb/ia32/jdb_screen-ia32.cpp new file mode 100644 index 00000000..212d681f --- /dev/null +++ b/kernel/fiasco/src/jdb/ia32/jdb_screen-ia32.cpp @@ -0,0 +1,32 @@ +IMPLEMENTATION [ia32 || ux]: + +const char* const Jdb_screen::Reg_names[] = { "EAX", "EBX", "ECX", "EDX", + "EBP", "ESI", "EDI", "EIP", + "ESP", "EFL" }; +const char Jdb_screen::Reg_prefix = 'E'; + +const char* Jdb_screen::Root_page_table = "pdir: "; + +//---------------------------------------------------------------------------- +IMPLEMENTATION [amd64]: + +const char * const Jdb_screen::Reg_names[] = { "RAX", "RBX", "RCX", "RDX", + "RBP", "RSI", "RDI", "R8\0", + "R9\0", "R10", "R11", "R12", + "R13", "R14", "R15", "RIP", + "RSP", "RFL" }; +const char Jdb_screen::Reg_prefix = 'R'; + +const char* Jdb_screen::Root_page_table = "pml4: "; + + +//---------------------------------------------------------------------------- +IMPLEMENTATION: + +PUBLIC +static +int +Jdb_screen::num_regs() +{ + return sizeof(Jdb_screen::Reg_names) / sizeof(Jdb_screen::Reg_names[0]); +} diff --git a/kernel/fiasco/src/jdb/ia32/jdb_trace_set-ia32-ux.cpp b/kernel/fiasco/src/jdb/ia32/jdb_trace_set-ia32-ux.cpp new file mode 100644 index 00000000..af34436b --- /dev/null +++ b/kernel/fiasco/src/jdb/ia32/jdb_trace_set-ia32-ux.cpp @@ -0,0 +1,153 @@ +IMPLEMENTATION: +#include "syscalls.h" +#include "idt.h" +#include "jdb.h" + +extern "C" void entry_sys_ipc_log (void); +extern "C" void entry_sys_ipc_c (void); +extern "C" void entry_sys_ipc (void); +extern "C" void entry_sys_fast_ipc_log (void); +extern "C" void entry_sys_fast_ipc_c (void); +extern "C" void entry_sys_fast_ipc (void); + +extern "C" void sys_ipc_wrapper (void); +extern "C" void ipc_short_cut_wrapper (void); +extern "C" void sys_ipc_log_wrapper (void); +extern "C" void sys_ipc_trace_wrapper (void); + +typedef void (Fast_entry_func)(void); + +PUBLIC static +void +Jdb_set_trace::ia32_set_fast_entry(unsigned cpu, void *entry) +{ + Cpu::cpus.cpu(cpu).set_fast_entry((Fast_entry_func*)entry); +} + +struct Set_fast_entry +{ + void *entry; + Set_fast_entry(Fast_entry_func *entry) : entry((void*)entry) {} + void operator () (unsigned cpu) const + { Jdb::remote_work(cpu, Jdb_set_trace::ia32_set_fast_entry, entry, true); } +}; + +static +void +Jdb_set_trace::set_ipc_vector() +{ + void (*int30_entry)(void); + void (*fast_entry)(void); + + if (Jdb_ipc_trace::_trace || Jdb_ipc_trace::_slow_ipc || + Jdb_ipc_trace::_log || Jdb_nextper_trace::_log) + { + int30_entry = entry_sys_ipc_log; + fast_entry = entry_sys_fast_ipc_log; + } + else + { + int30_entry = entry_sys_ipc_c; + fast_entry = entry_sys_fast_ipc_c; + } + + Idt::set_entry(0x30, (Address) int30_entry, true); + Jdb::foreach_cpu(Set_fast_entry(fast_entry)); + + if (Jdb_ipc_trace::_trace) + syscall_table[0] = sys_ipc_trace_wrapper; + else if ((Jdb_ipc_trace::_log && !Jdb_ipc_trace::_slow_ipc) || + Jdb_nextper_trace::_log) + syscall_table[0] = sys_ipc_log_wrapper; + else + syscall_table[0] = sys_ipc_wrapper; +} + +PUBLIC static FIASCO_NOINLINE +void +Jdb_set_trace::set_cpath() +{ + Jdb_ipc_trace::_cpath = 0; + BEGIN_LOG_EVENT("Context switches", "csw", 0) + Jdb_ipc_trace::_cpath = 1; + END_LOG_EVENT; + BEGIN_LOG_EVENT("Shortcut", "sc", 0) + Jdb_ipc_trace::_cpath = 1; + END_LOG_EVENT; + set_ipc_vector(); +} + +void +jdb_trace_set_cpath(void) +{ + Jdb_set_trace::set_cpath(); +} + +IMPLEMENT void +Jdb_set_trace::next_preiod_tracing(bool enable) +{ + if (enable) + Jdb_nextper_trace::_log = 1; + else + Jdb_nextper_trace::_log = 0; + + set_ipc_vector(); +} + +IMPLEMENT void +Jdb_set_trace::page_fault_tracing(bool /*enable*/) +{ +} + +IMPLEMENT void +Jdb_set_trace::ipc_tracing(Mode mode) +{ + switch (mode) + { + case Off: + Jdb_ipc_trace::_trace = 0; + Jdb_ipc_trace::_log = 0; + Jdb_ipc_trace::_cshortcut = 0; + Jdb_ipc_trace::_slow_ipc = 0; + break; + case Log: + Jdb_ipc_trace::_trace = 0; + Jdb_ipc_trace::_log = 1; + Jdb_ipc_trace::_log_to_buf = 0; + Jdb_ipc_trace::_cshortcut = 0; + Jdb_ipc_trace::_slow_ipc = 0; + break; + case Log_to_buf: + Jdb_ipc_trace::_trace = 0; + Jdb_ipc_trace::_log = 1; + Jdb_ipc_trace::_log_to_buf = 1; + Jdb_ipc_trace::_cshortcut = 0; + Jdb_ipc_trace::_slow_ipc = 0; + break; + case Trace: + Jdb_ipc_trace::_trace = 1; + Jdb_ipc_trace::_cshortcut = 0; + Jdb_ipc_trace::_log = 0; + Jdb_ipc_trace::_slow_ipc = 0; + break; + case Use_c_short_cut: + Jdb_ipc_trace::_cshortcut = 1; + break; + case Use_slow_path: + Jdb_ipc_trace::_slow_ipc = 1; + break; + } + set_ipc_vector(); +} + + +static +void +Jdb_set_trace::set_unmap_vector() +{ +} + +IMPLEMENT void +Jdb_set_trace::unmap_tracing(bool /*enable*/) +{ +} diff --git a/kernel/fiasco/src/jdb/jdb-ansi.cpp b/kernel/fiasco/src/jdb/jdb-ansi.cpp new file mode 100644 index 00000000..d9b91a93 --- /dev/null +++ b/kernel/fiasco/src/jdb/jdb-ansi.cpp @@ -0,0 +1,120 @@ + +/* + * JDB Module implementing ANSI/vt100 functions + */ + +INTERFACE: + +EXTENSION class Jdb +{ +public: + enum + { + NOFANCY=0, + FANCY=1 + }; + + enum Direction + { + Cursor_up = 'A', + Cursor_down = 'B', + Cursor_right = 'C', + Cursor_left = 'D' + }; +}; + +IMPLEMENTATION: + +#include +#include +#include "jdb_screen.h" + +PUBLIC static inline +void +Jdb::cursor( Direction d, unsigned n = 1) +{ + printf("\033[%u%c", n, (char)d); +} + + +PUBLIC static +void +Jdb::cursor (unsigned int row=0, unsigned int col=0) +{ + if (row || col) + printf ("\033[%u;%uH", row, col); + else + printf ("\033[%u;%uH", 1, 1); +} + +PUBLIC static inline NEEDS[] +void +Jdb::blink_cursor (unsigned int row, unsigned int col) +{ + printf ("\033[%d;%df", row, col); +} + +PUBLIC static inline NEEDS[] +void +Jdb::cursor_save() +{ + putstr ("\0337"); +} + +PUBLIC static inline NEEDS[] +void +Jdb::cursor_restore() +{ + putstr ("\0338"); +} + +PUBLIC static inline NEEDS[] +void +Jdb::screen_erase() +{ + putstr ("\033[2J"); +} + +PUBLIC static +void +Jdb::screen_scroll (unsigned int start, unsigned int end) +{ + if (start || end) + printf ("\033[%u;%ur", start, end); + else + printf ("\033[r"); +} + +PUBLIC static inline NEEDS[] +void +Jdb::clear_to_eol() +{ + putstr("\033[K"); +} + +// preserve the history of the serial console if fancy != 0 +PUBLIC static +void +Jdb::clear_screen(int fancy=FANCY) +{ + if (fancy == FANCY) + { + cursor(Jdb_screen::height(), 1); + for (unsigned i=0; i(context_of(c)); +} + +//--------------------------------------------------------------------------- +IMPLEMENTATION: + +#include "jdb.h" +#include "thread.h" + +PUBLIC +static void +Jdb::get_current(unsigned cpu) +{ + current_active = get_thread(cpu); +} + +PUBLIC static inline NEEDS["thread.h"] +Space* +Jdb::get_current_space() +{ + return current_active ? current_active->space() : 0; +} diff --git a/kernel/fiasco/src/jdb/jdb.cpp b/kernel/fiasco/src/jdb/jdb.cpp new file mode 100644 index 00000000..461ef1f1 --- /dev/null +++ b/kernel/fiasco/src/jdb/jdb.cpp @@ -0,0 +1,1413 @@ +INTERFACE: + +#include "l4_types.h" +#include "jdb_core.h" +#include "jdb_handler_queue.h" +#include "per_cpu_data.h" + +class Context; +class Thread; +class Push_console; + +class Jdb_entry_frame; + +class Jdb : public Jdb_core +{ +public: + static Per_cpu entry_frame; + static unsigned current_cpu; + static Per_cpu remote_func; + static Per_cpu remote_func_data; + static Per_cpu remote_func_running; + + static int FIASCO_FASTCALL enter_jdb(Jdb_entry_frame *e, unsigned cpu); + static void cursor_end_of_screen(); + static void cursor_home(); + static void printf_statline(const char *prompt, const char *help, + const char *format, ...) + __attribute__((format(printf, 3, 4))); + static void save_disable_irqs(unsigned cpu); + static void restore_irqs(unsigned cpu); + +private: + Jdb(); // default constructors are undefined + Jdb(const Jdb&); + + static char hide_statline; + static char last_cmd; + static char next_cmd; + static Per_cpu error_buffer; + static bool was_input_error; + + static Thread *current_active; + + static const char *toplevel_cmds; + static const char *non_interactive_cmds; + + // state for traps in JDB itself + static Per_cpu running; + static bool in_service; + static bool leave_barrier; + static unsigned long cpus_in_debugger; + static bool never_break; + static bool jdb_active; + + static void enter_trap_handler(unsigned cpu); + static void leave_trap_handler(unsigned cpu); + static bool handle_conditional_breakpoint(unsigned cpu); + static void handle_nested_trap(Jdb_entry_frame *e); + static bool handle_user_request(unsigned cpu); + static bool handle_debug_traps(unsigned cpu); + static bool test_checksums(); + +public: + static Jdb_handler_queue jdb_enter; + static Jdb_handler_queue jdb_leave; + + // esc sequences for highligthing + static char esc_iret[]; + static char esc_bt[]; + static char esc_emph[]; + static char esc_emph2[]; + static char esc_mark[]; + static char esc_line[]; + static char esc_symbol[]; + +}; + +//--------------------------------------------------------------------------- +IMPLEMENTATION: + +#include +#include +#include + +#include "config.h" +#include "delayloop.h" +#include "feature.h" +#include "jdb_core.h" +#include "jdb_entry_frame.h" +#include "jdb_screen.h" +#include "kernel_console.h" +#include "processor.h" +#include "push_console.h" +#include "static_init.h" +#include "keycodes.h" + +KIP_KERNEL_FEATURE("jdb"); + +Jdb_handler_queue Jdb::jdb_enter; +Jdb_handler_queue Jdb::jdb_leave; + +DEFINE_PER_CPU Per_cpu Jdb::error_buffer; +char Jdb::next_cmd; // next global command to execute +char Jdb::last_cmd; + +char Jdb::hide_statline; // show status line on enter_kdebugger +DEFINE_PER_CPU Per_cpu Jdb::entry_frame; +unsigned Jdb::current_cpu; // current CPU JDB is running on +Thread *Jdb::current_active; // current running thread +bool Jdb::was_input_error; // error in command sequence + +DEFINE_PER_CPU Per_cpu Jdb::remote_func; +DEFINE_PER_CPU Per_cpu Jdb::remote_func_data; +DEFINE_PER_CPU Per_cpu Jdb::remote_func_running; + +// holds all commands executable in top level (regardless of current mode) +const char *Jdb::toplevel_cmds = "j_"; + +// a short command must be included in this list to be enabled for non- +// interactive execution +const char *Jdb::non_interactive_cmds = "bEIJLMNOPSU^Z"; + +DEFINE_PER_CPU Per_cpu Jdb::running; // JDB is already running +bool Jdb::never_break; // never enter JDB +bool Jdb::jdb_active; +bool Jdb::in_service; +bool Jdb::leave_barrier; +unsigned long Jdb::cpus_in_debugger; + + +PUBLIC static +bool +Jdb::cpu_in_jdb(unsigned cpu) +{ return Cpu::online(cpu) && running.cpu(cpu); } + + +PUBLIC static +template< typename Func > +void +Jdb::foreach_cpu(Func const &f) +{ + for (unsigned i = 0; i < Config::Max_num_cpus; ++i) + { + if (!Cpu::online(i) || !running.cpu(i)) + continue; + f(i); + } +} + +PUBLIC static +template< typename Func > +bool +Jdb::foreach_cpu(Func const &f, bool positive) +{ + bool r = positive; + for (unsigned i = 0; i < Config::Max_num_cpus; ++i) + { + if (!Cpu::online(i) || !running.cpu(i)) + continue; + + bool res = f(i); + + if (positive) + r = r && res; + else + r = r || res; + } + + return r; +} + +PUBLIC static inline +void +Jdb::set_next_cmd(char cmd) +{ next_cmd = cmd; } + +PUBLIC static inline +int +Jdb::was_last_cmd() +{ return last_cmd; } + +PUBLIC static inline +int +Jdb::get_next_cmd() +{ return next_cmd; } + +/** Command aborted. If we are interpreting a debug command like + * enter_kdebugger("*#...") this is an error + */ +PUBLIC +static void +Jdb::abort_command() +{ + cursor(Jdb_screen::height(), 6); + clear_to_eol(); + + was_input_error = true; +} + + +// go to bottom of screen and print some text in the form "jdb: ..." +// if no text follows after the prompt, prefix the current thread number +IMPLEMENT +void +Jdb::printf_statline(const char *prompt, const char *help, + const char *format, ...) +{ + cursor(Jdb_screen::height(), 1); + unsigned w = Jdb_screen::width(); + prompt_start(); + if (prompt) + { + putstr(prompt); + putstr(": "); + w -= strlen(prompt) + 2; + } + else + { + Jdb::prompt(); + w -= Jdb::prompt_len(); + } + prompt_end(); + // work around for ealier gccs complaining about "empty format strings" + if (format && (format[0] != '_' || format[1] != '\0')) + { + char s[w]; + va_list list; + va_start(list, format); + vsnprintf(s, sizeof(s), format, list); + va_end(list); + s[sizeof(s) - 1] = 0; + putstr(s); + w -= print_len(s); + } + if (help && print_len(help) < w) + printf("%*.*s", w, w, help); + else + clear_to_eol(); +} + +PUBLIC static +bool Jdb::is_toplevel_cmd(char c) +{ + char cm[] = {c, 0}; + Jdb_core::Cmd cmd = Jdb_core::has_cmd(cm); + + if (cmd.cmd || (0 != strchr(toplevel_cmds, c))) + { + set_next_cmd(c); + return true; + } + + return false; +} + + +PUBLIC static +int +Jdb::execute_command(const char *s, int first_char = -1) +{ + Jdb_core::Cmd cmd = Jdb_core::has_cmd(s); + + if (cmd.cmd) + return Jdb_core::exec_cmd(cmd, 0, first_char) == 2 ? 1 : 0; + + return 0; +} + +PUBLIC static +Push_console * +Jdb::push_cons() +{ + static Push_console c; + return &c; +} + +// Interprete str as non interactive commands for Jdb. We allow mostly +// non-interactive commands here (e.g. we don't allow d, t, l, u commands) +PRIVATE static +int +Jdb::execute_command_ni(Space *task, char const *str, int len = 1000) +{ + char tmp = 0; + for (; len && peek(str, task, tmp) && tmp; ++str, --len) + if ((unsigned char)tmp != 0xff) + push_cons()->push(tmp); + + if ((unsigned char)tmp != 0xff) + push_cons()->push('_'); // terminating return + + + // prevent output of sequences + Kconsole::console()->change_state(0, 0, ~Console::OUTENABLED, 0); + + for (;;) + { + int c = getchar(); + + was_input_error = true; + if (0 != strchr(non_interactive_cmds, c)) + { + char _cmd[] = {(char)c, 0}; + Jdb_core::Cmd cmd = Jdb_core::has_cmd(_cmd); + + if (cmd.cmd) + { + if (Jdb_core::exec_cmd (cmd, 0) != 3) + was_input_error = false; + } + } + + if (c == KEY_RETURN || c == ' ' || was_input_error) + { + push_cons()->flush(); + // re-enable all consoles but GZIP + Kconsole::console()->change_state(0, Console::GZIP, + ~0U, Console::OUTENABLED); + return c == KEY_RETURN || c == ' '; + } + } +} + +PRIVATE static +bool +Jdb::input_short_mode(Jdb::Cmd *cmd, char const **args, int &cmd_key) +{ + *args = 0; + for (;;) + { + int c; + do + { + if ((c = get_next_cmd())) + set_next_cmd(0); + else + c = getchar(); + } + while (c < ' ' && c != KEY_RETURN); + + if (c == KEY_F1) + c = 'h'; + + printf("\033[K%c", c); // clreol + print key + + char cmd_buffer[2] = { (char)c, 0 }; + + *cmd = Jdb_core::has_cmd(cmd_buffer); + if (cmd->cmd) + { + cmd_key = c; + return false; // do not leave the debugger + } + else if (!handle_special_cmds(c)) + return true; // special command triggered a JDB leave + else if (c == KEY_RETURN) + { + hide_statline = false; + cmd_key = c; + return false; + } + } +} + + +class Cmd_buffer +{ +private: + unsigned _l; + char _b[256]; + +public: + Cmd_buffer() {} + char *buffer() { return _b; } + int len() const { return _l; } + void flush() { _l = 0; _b[0] = 0; } + void cut(int l) + { + if (l < 0) + l = _l + l; + + if (l >= 0 && (unsigned)l < _l) + { + _l = l; + _b[l] = 0; + } + } + + void append(int c) { if (_l + 1 < sizeof(_b)) { _b[_l++] = c; _b[_l] = 0; } } + void append(char const *str, int len) + { + if (_l + len >= sizeof(_b)) + len = sizeof(_b) - _l - 1; + + memcpy(_b + _l, str, len); + _l += len; + _b[_l] = 0; + } + + void overlay(char const *str, unsigned len) + { + if (len + 1 > sizeof(_b)) + len = sizeof(_b) - 1; + + if (len < _l) + return; + + str += _l; + len -= _l; + + memcpy(_b + _l, str, len); + _l = len + _l; + } + +}; + + +PRIVATE static +bool +Jdb::input_long_mode(Jdb::Cmd *cmd, char const **args) +{ + static Cmd_buffer buf; + buf.flush(); + for (;;) + { + int c = getchar(); + + switch (c) + { + case KEY_BACKSPACE: + if (buf.len() > 0) + { + cursor(Cursor_left); + clear_to_eol(); + buf.cut(-1); + } + continue; + + case ' ': + if (buf.len() == 0) + continue; + break; + + case KEY_TAB: + { + bool multi_match = false; + *cmd = Jdb_core::complete_cmd(buf.buffer(), multi_match); + if (cmd->cmd && multi_match) + { + printf("\n"); + unsigned prefix_len = Jdb_core::print_alternatives(buf.buffer()); + print_prompt(); + buf.overlay(cmd->cmd->cmd, prefix_len); + putnstr(buf.buffer(), buf.len()); + } + else if (cmd->cmd) + { + putstr(cmd->cmd->cmd + buf.len()); + putchar(' '); + buf.overlay(cmd->cmd->cmd, strlen(cmd->cmd->cmd)); + buf.append(' '); + } + continue; + } + break; + + case KEY_RETURN: + puts(""); + if (!buf.len()) + { + hide_statline = false; + cmd->cmd = 0; + return false; + } + break; + + default: + buf.append(c); + printf("\033[K%c", c); + continue; + } + + *cmd = Jdb_core::has_cmd(buf.buffer()); + if (cmd->cmd) + { + unsigned cmd_len = strlen(cmd->cmd->cmd); + *args = buf.buffer() + cmd_len; + while (**args == ' ') + ++(*args); + return false; // do not leave the debugger + } + else + { + printf("unknown command: '%s'\n", buf.buffer()); + print_prompt(); + buf.flush(); + } + } +} + +PRIVATE static +int +Jdb::execute_command() +{ + char const *args; + Jdb_core::Cmd cmd(0,0); + bool leave; + int cmd_key; + + if (short_mode) + leave = input_short_mode(&cmd, &args, cmd_key); + else + leave = input_long_mode(&cmd, &args); + + if (leave) + return 0; + + if (cmd.cmd) + { + int ret = Jdb_core::exec_cmd( cmd, args ); + + if (!ret) + hide_statline = false; + + last_cmd = cmd_key; + return ret; + } + + last_cmd = 0; + return 1; +} + +PRIVATE static +bool +Jdb::open_debug_console(unsigned cpu) +{ + in_service = 1; + save_disable_irqs(cpu); + if (cpu == 0) + jdb_enter.execute(); + + if (!stop_all_cpus(cpu)) + return false; // CPUs other than 0 never become interacitve + + if (!Jdb_screen::direct_enabled()) + Kconsole::console()-> + change_state(Console::DIRECT, 0, ~Console::OUTENABLED, 0); + + return true; +} + + +PRIVATE static +void +Jdb::close_debug_console(unsigned cpu) +{ + Proc::cli(); + Mem::barrier(); + if (cpu == 0) + { + running.cpu(cpu) = 0; + // eat up input from console + while (Kconsole::console()->getchar(false)!=-1) + ; + + Kconsole::console()-> + change_state(Console::DIRECT, 0, ~0UL, Console::OUTENABLED); + + in_service = 0; + leave_wait_for_others(); + jdb_leave.execute(); + } + + Mem::barrier(); + restore_irqs(cpu); +} + +PUBLIC static +void +Jdb::remote_work(unsigned cpu, void (*func)(unsigned, void *), void *data, + bool sync = true) +{ + if (cpu == 0) + func(cpu, data); + else + { + while (1) + { + Mem::barrier(); + if (!Jdb::remote_func_running.cpu(cpu)) + break; + Proc::pause(); + } + + Jdb::remote_func_running.cpu(cpu) = 1; + Jdb::remote_func_data.cpu(cpu) = data; + Mem::barrier(); + set_monitored_address(&Jdb::remote_func.cpu(cpu), func); + Mem::barrier(); + + while (sync) + { + Mem::barrier(); + if (!Jdb::remote_func_running.cpu(cpu)) + break; + Proc::pause(); + } + } +} + +PUBLIC +static int +Jdb::getchar(void) +{ + int res = Kconsole::console()->getchar(); + check_for_cpus(false); + return res; +} + +IMPLEMENT +void Jdb::cursor_home() +{ + putstr("\033[H"); +} + +IMPLEMENT +void Jdb::cursor_end_of_screen() +{ + putstr("\033[127;1H"); +} + +//-------- pretty print functions ------------------------------ +PUBLIC static +void +Jdb::write_ll_ns(Signed64 ns, char *buf, int maxlen, bool sign) +{ + Unsigned64 uns = (ns < 0) ? -ns : ns; + + if (uns >= 3600000000000000ULL) + { + snprintf(buf, maxlen, ">999 h "); + return; + } + + if (maxlen && sign) + { + *buf++ = (ns < 0) ? '-' : (ns == 0) ? ' ' : '+'; + maxlen--; + } + + if (uns >= 60000000000000ULL) + { + // 1000min...999h + Mword _h = uns / 3600000000000ULL; + Mword _m = (uns % 3600000000000ULL) / 60000000000ULL; + snprintf(buf, maxlen, "%3lu:%02lu h ", _h, _m); + return; + } + + if (uns >= 1000000000000ULL) + { + // 1000s...999min + Mword _m = uns / 60000000000ULL; + Mword _s = (uns % 60000000000ULL) / 1000ULL; + snprintf(buf, maxlen, "%3lu:%02lu M ", _m, _s); + return; + } + + if (uns >= 1000000000ULL) + { + // 1...1000s + Mword _s = uns / 1000000000ULL; + Mword _ms = (uns % 1000000000ULL) / 1000000ULL; + snprintf(buf, maxlen, "%3lu.%03lu s ", _s, _ms); + return; + } + + if (uns >= 1000000) + { + // 1...1000ms + Mword _ms = uns / 1000000UL; + Mword _us = (uns % 1000000UL) / 1000UL; + snprintf(buf, maxlen, "%3lu.%03lu ms", _ms, _us); + return; + } + + if (uns == 0) + { + snprintf(buf, maxlen, " 0 "); + return; + } + + Console* gzip = Kconsole::console()->find_console(Console::GZIP); + Mword _us = uns / 1000UL; + Mword _ns = uns % 1000UL; + snprintf(buf, maxlen, "%3lu.%03lu %c ", _us, _ns, + gzip && gzip->state() & Console::OUTENABLED + ? '\265' + : Config::char_micro); +} + +PUBLIC static +void +Jdb::write_ll_hex(Signed64 x, char *buf, int maxlen, bool sign) +{ + // display 40 bits + Unsigned64 xu = (x < 0) ? -x : x; + + if (sign) + snprintf(buf, maxlen, "%s%03lx" L4_PTR_FMT, + (x < 0) ? "-" : (x == 0) ? " " : "+", + (Mword)((xu >> 32) & 0xfff), (Mword)xu); + else + snprintf(buf, maxlen, "%04lx" L4_PTR_FMT, + (Mword)((xu >> 32) & 0xffff), (Mword)xu); +} + +PUBLIC static +void +Jdb::write_ll_dec(Signed64 x, char *buf, int maxlen, bool sign) +{ + Unsigned64 xu = (x < 0) ? -x : x; + + // display no more than 11 digits + if (xu >= 100000000000ULL) + { + snprintf(buf, maxlen, "%12s", ">= 10^11"); + return; + } + + if (sign && x != 0) + snprintf(buf, maxlen, "%+12lld", x); + else + snprintf(buf, maxlen, "%12llu", xu); +} + +PUBLIC static inline +Thread* +Jdb::get_current_active() +{ + return current_active; +} + +PUBLIC static inline +Jdb_entry_frame* +Jdb::get_entry_frame(unsigned cpu) +{ + return entry_frame.cpu(cpu); +} + +/// handling of standard cursor keys (Up/Down/PgUp/PgDn) +PUBLIC static +int +Jdb::std_cursor_key(int c, Mword cols, Mword lines, Mword max_absy, Mword *absy, + Mword *addy, Mword *addx, bool *redraw) +{ + switch (c) + { + case KEY_CURSOR_LEFT: + case 'h': + if (addx) + { + if (*addx > 0) + (*addx)--; + else if (*addy > 0) + { + (*addy)--; + *addx = cols - 1; + } + else if (*absy > 0) + { + (*absy)--; + *addx = cols - 1; + *redraw = true; + } + } + else + return 0; + break; + case KEY_CURSOR_RIGHT: + case 'l': + if (addx) + { + if (*addx < cols - 1) + (*addx)++; + else if (*addy < lines - 1) + { + (*addy)++; + *addx = 0; + } + else if (*absy < max_absy) + { + (*absy)++; + *addx = 0; + *redraw = true; + } + } + else + return 0; + break; + case KEY_CURSOR_UP: + case 'k': + if (*addy > 0) + (*addy)--; + else if (*absy > 0) + { + (*absy)--; + *redraw = true; + } + break; + case KEY_CURSOR_DOWN: + case 'j': + if (*addy < lines-1) + (*addy)++; + else if (*absy < max_absy) + { + (*absy)++; + *redraw = true; + } + break; + case KEY_CURSOR_HOME: + case 'H': + *addy = 0; + if (addx) + *addx = 0; + if (*absy > 0) + { + *absy = 0; + *redraw = true; + } + break; + case KEY_CURSOR_END: + case 'L': + *addy = lines-1; + if (addx) + *addx = cols - 1; + if (*absy < max_absy) + { + *absy = max_absy; + *redraw = true; + } + break; + case KEY_PAGE_UP: + case 'K': + if (*absy >= lines) + { + *absy -= lines; + *redraw = true; + } + else + { + if (*absy > 0) + { + *absy = 0; + *redraw = true; + } + else if (*addy > 0) + *addy = 0; + else if (addx) + *addx = 0; + } + break; + case KEY_PAGE_DOWN: + case 'J': + if (*absy+lines-1 < max_absy) + { + *absy += lines; + *redraw = true; + } + else + { + if (*absy < max_absy) + { + *absy = max_absy; + *redraw = true; + } + else if (*addy < lines-1) + *addy = lines-1; + else if (addx) + *addx = cols - 1; + } + break; + default: + return 0; + } + + return 1; +} + +PUBLIC static inline +Space * +Jdb::get_task(unsigned cpu) +{ + if (!get_thread(cpu)) + return 0; + else + return get_thread(cpu)->space(); +} + + +// +// memory access wrappers +// + +PUBLIC static +template< typename T > +bool +Jdb::peek(T const *addr, Space *task, T &value) +{ + // use an Mword here instead of T as some implementations of peek_task use + // an Mword in their operation which is potentially bigger than T + // XXX: should be fixed + Mword tmp; + bool ret = peek_task((Address)addr, task, &tmp, sizeof(T)) == 0; + value = tmp; + return ret; +} + +PUBLIC static +template< typename T > +bool +Jdb::poke(T *addr, Space *task, T const &value) +{ return poke_task((Address)addr, task, &value, sizeof(T)) == 0; } + + +class Jdb_base_cmds : public Jdb_module +{ +public: + Jdb_base_cmds() FIASCO_INIT; +}; + +static Jdb_base_cmds jdb_base_cmds INIT_PRIORITY(JDB_MODULE_INIT_PRIO); + +PUBLIC +Jdb_module::Action_code +Jdb_base_cmds::action (int cmd, void *&, char const *&, int &) +{ + if (cmd!=0) + return NOTHING; + + Jdb_core::short_mode = !Jdb_core::short_mode; + printf("\ntoggle mode: now in %s command mode (use %s) to switch back\n", + Jdb_core::short_mode ? "short" : "long", + Jdb_core::short_mode ? "*" : "mode"); + return NOTHING; +} + +PUBLIC +int +Jdb_base_cmds::num_cmds() const +{ + return 1; +} + +PUBLIC +Jdb_module::Cmd const * +Jdb_base_cmds::cmds() const +{ + static Cmd cs[] = + { { 0, "*", "mode", "", "*|mode\tswitch long and short command mode", + (void*)0 } }; + + return cs; +} + +IMPLEMENT +Jdb_base_cmds::Jdb_base_cmds() + : Jdb_module("GENERAL") +{} + + +//--------------------------------------------------------------------------- +IMPLEMENTATION [ux]: + +PRIVATE inline static void Jdb::rcv_uart_enable() {} + +//--------------------------------------------------------------------------- +IMPLEMENTATION [!ux]: + +#include "kernel_uart.h" + +PRIVATE inline static +void +Jdb::rcv_uart_enable() +{ + if (Config::serial_esc == Config::SERIAL_ESC_IRQ) + Kernel_uart::enable_rcv_irq(); +} + +//--------------------------------------------------------------------------- +IMPLEMENTATION: + +#include "ipi.h" +#include "logdefs.h" + +char Jdb::esc_iret[] = "\033[36;1m"; +char Jdb::esc_bt[] = "\033[31m"; +char Jdb::esc_emph[] = "\033[33;1m"; +char Jdb::esc_emph2[] = "\033[32;1m"; +char Jdb::esc_mark[] = "\033[35;1m"; +char Jdb::esc_line[] = "\033[37m"; +char Jdb::esc_symbol[] = "\033[33;1m"; + + + + + +IMPLEMENT int +Jdb::enter_jdb(Jdb_entry_frame *e, unsigned cpu) +{ + if (e->debug_ipi()) + { + if (!remote_work_ipi_process(cpu)) + return 0; + if (!in_service) + return 0; + } + + enter_trap_handler(cpu); + + if (handle_conditional_breakpoint(cpu)) + { + // don't enter debugger, only logged breakpoint + leave_trap_handler(cpu); + return 0; + } + + if (!running.cpu(cpu)) + entry_frame.cpu(cpu) = e; + + volatile bool really_break = true; + + static jmp_buf recover_buf; + static Jdb_entry_frame nested_trap_frame; + + if (running.cpu(cpu)) + { + nested_trap_frame = *e; + + // Since we entered the kernel debugger a second time, + // Thread::nested_trap_recover + // has a value of 2 now. We don't leave this function so correct the + // entry counter + Thread::nested_trap_recover.cpu(cpu)--; + + longjmp(recover_buf, 1); + } + + // all following exceptions are handled by jdb itself + running.cpu(cpu) = true; + + if (!open_debug_console(cpu)) + { // not on the master CPU just wait + close_debug_console(cpu); + leave_trap_handler(cpu); + return 0; + } + + Jdb::current_cpu = cpu; + // check for int $3 user debugging interface + if (foreach_cpu(&handle_user_request, true)) + { + close_debug_console(cpu); + leave_trap_handler(cpu); + return 0; + } + + hide_statline = false; + + // clear error message + *error_buffer.cpu(cpu) = '\0'; + + really_break = foreach_cpu(&handle_debug_traps, false); + + while (setjmp(recover_buf)) + { + // handle traps which occured while we are in Jdb + Kconsole::console()->end_exclusive(Console::GZIP); + handle_nested_trap(&nested_trap_frame); + } + + if (!never_break && really_break) + { + // determine current task/thread from stack pointer + update_prompt(); + + LOG_MSG(current_active, "=== enter jdb ==="); + + do + { + screen_scroll(1, Jdb_screen::height()); + if (!hide_statline) + { + cursor(Jdb_screen::height(), 1); + printf("\n%s%s %.*s\033[m \n", + esc_prompt, + test_checksums() + ? "" + : " WARNING: Fiasco kernel checksum differs -- " + "read-only data has changed!\n", + Jdb_screen::width()-11, + Jdb_screen::Line); + for (unsigned i = 0; i < Config::Max_num_cpus; ++i) + if (Cpu::online(i)) + { + if (running.cpu(i)) + printf(" CPU%2u [" L4_PTR_FMT "]: %s\n", i, + entry_frame.cpu(i)->ip(), error_buffer.cpu(i)); + else + printf(" CPU%2u: is not in JDB (not responding)\n", i); + } + hide_statline = true; + } + + printf_statline(0, 0, "_"); + + } while (execute_command()); + + // reset scrolling region of serial terminal + screen_scroll(1,127); + + // reset cursor + blink_cursor(Jdb_screen::height(), 1); + + // goto end of screen + Jdb::cursor(127, 1); + } + + // reenable interrupts + close_debug_console(cpu); + + rcv_uart_enable(); + + leave_trap_handler(cpu); + return 0; +} + + +//-------------------------------------------------------------------------- +IMPLEMENTATION [!mp]: + +PRIVATE static +bool +Jdb::stop_all_cpus(unsigned /*current_cpu*/) +{ return true; } + +PRIVATE +static +void +Jdb::leave_wait_for_others() +{} + +PRIVATE static +bool +Jdb::check_for_cpus(bool) +{ return true; } + +PRIVATE static inline +int +Jdb::remote_work_ipi_process(unsigned) +{ return 1; } + + +//--------------------------------------------------------------------------- +INTERFACE [mp]: + +#include "spin_lock.h" + +EXTENSION class Jdb +{ + // remote call + static Spin_lock<> _remote_call_lock; + static void (*_remote_work_ipi_func)(unsigned, void *); + static void *_remote_work_ipi_func_data; + static unsigned long _remote_work_ipi_done; +}; + +//-------------------------------------------------------------------------- +IMPLEMENTATION [mp]: + +void (*Jdb::_remote_work_ipi_func)(unsigned, void *); +void *Jdb::_remote_work_ipi_func_data; +unsigned long Jdb::_remote_work_ipi_done; +Spin_lock<> Jdb::_remote_call_lock; + +PRIVATE static +bool +Jdb::check_for_cpus(bool try_nmi) +{ + enum { Max_wait_cnt = 1000 }; + for (unsigned c = 1; c < Config::Max_num_cpus; ++c) + { + if (Cpu::online(c) && !running.cpu(c)) + Ipi::send(Ipi::Debug, 0, c); + } + Mem::barrier(); +retry: + unsigned long wait_cnt = 0; + for (;;) + { + bool all_there = true; + cpus_in_debugger = 0; + // skip boot cpu 0 + for (unsigned c = 1; c < Config::Max_num_cpus; ++c) + { + if (Cpu::online(c)) + { + if (!running.cpu(c)) + all_there = false; + else + ++cpus_in_debugger; + } + } + + if (!all_there) + { + Proc::pause(); + Mem::barrier(); + if (++wait_cnt == Max_wait_cnt) + break; + Delay::delay(1); + continue; + } + + break; + } + + bool do_retry = false; + for (unsigned c = 1; c < Config::Max_num_cpus; ++c) + { + if (Cpu::online(c)) + { + if (!running.cpu(c)) + { + printf("JDB: CPU %d: is not responding ... %s\n",c, + try_nmi ? "trying NMI" : ""); + if (try_nmi) + { + do_retry = true; + send_nmi(c); + } + } + } + } + if (do_retry) + { + try_nmi = false; + goto retry; + } + // All CPUs entered JDB, so go on and become interactive + return true; +} + +PRIVATE static +bool +Jdb::stop_all_cpus(unsigned current_cpu) +{ + enum { Max_wait_cnt = 1000 }; + // JDB allways runs on CPU 0, if any other CPU enters the debugger + // CPU 0 is notified to do enter the debugger too + if (current_cpu == 0) + { + // I'm CPU 0 stop all other CPUs and wait for them to enter the JDB + jdb_active = 1; + Mem::barrier(); + check_for_cpus(true); + // All CPUs entered JDB, so go on and become interactive + return true; + } + else + { + // Huh, not CPU 0, so notify CPU 0 to enter JDB too + // The notification is ignored if CPU 0 is already within JDB + jdb_active = true; + Ipi::send(Ipi::Debug, current_cpu, 0); + + unsigned long wait_count = Max_wait_cnt; + while (!running.cpu(0) && wait_count) + { + Proc::pause(); + Delay::delay(1); + Mem::barrier(); + --wait_count; + } + + if (wait_count == 0) + send_nmi(0); + + // Wait for messages from CPU 0 + while ((volatile bool)jdb_active) + { + Mem::barrier(); + void (**func)(unsigned, void *) = &remote_func.cpu(current_cpu); + void (*f)(unsigned, void *); + + if ((f = monitor_address(current_cpu, func))) + { + // Execute functions from queued from another CPU + *func = 0; + f(current_cpu, remote_func_data.cpu(current_cpu)); + Mem::barrier(); + remote_func_running.cpu(current_cpu) = 0; + Mem::barrier(); + } + Proc::pause(); + } + + // This CPU defacto left JDB + running.cpu(current_cpu) = 0; + + // Signal CPU 0, that we are ready to leve the debugger + // This is the second door of the airlock + atomic_mp_add(&cpus_in_debugger, -1UL); + + // Wait for CPU 0 to leave us out + while ((volatile bool)leave_barrier) + { + Mem::barrier(); + Proc::pause(); + } + + // CPU 0 signaled us to leave JDB + return false; + } +} + +PRIVATE +static +void +Jdb::leave_wait_for_others() +{ + leave_barrier = 1; + jdb_active = 0; + Mem::barrier(); + for (;;) + { + bool all_there = true; + for (unsigned c = 0; c < Config::Max_num_cpus; ++c) + { + if (Cpu::online(c) && running.cpu(c)) + { + // notify other CPU + set_monitored_address(&Jdb::remote_func.cpu(c), + (void (*)(unsigned, void *))0); +// printf("JDB: wait for CPU[%2u] to leave\n", c); + all_there = false; + } + } + + if (!all_there) + { + Proc::pause(); + Mem::barrier(); + continue; + } + + break; + } + + while ((volatile unsigned long)cpus_in_debugger) + { + Mem::barrier(); + Proc::pause(); + } + + Mem::barrier(); + leave_barrier = 0; +} + +// The remote_work_ipi* functions are for the IPI round-trip benchmark (only) +PRIVATE static +int +Jdb::remote_work_ipi_process(unsigned cpu) +{ + if (_remote_work_ipi_func) + { + _remote_work_ipi_func(cpu, _remote_work_ipi_func_data); + Mem::barrier(); + _remote_work_ipi_done = 1; + return 0; + } + return 1; +} + +PUBLIC static +bool +Jdb::remote_work_ipi(unsigned this_cpu, unsigned to_cpu, + void (*f)(unsigned, void *), void *data, bool wait = true) +{ + if (to_cpu == this_cpu) + { + f(this_cpu, data); + return true; + } + + if (!Cpu::online(to_cpu)) + return false; + + Lock_guard > guard(&_remote_call_lock); + + _remote_work_ipi_func = f; + _remote_work_ipi_func_data = data; + _remote_work_ipi_done = 0; + + Ipi::send(Ipi::Debug, this_cpu, to_cpu); + + if (wait) + while (!*(volatile unsigned long *)&_remote_work_ipi_done) + Proc::pause(); + + _remote_work_ipi_func = 0; + + return true; +} diff --git a/kernel/fiasco/src/jdb/jdb_attach_irq.cpp b/kernel/fiasco/src/jdb/jdb_attach_irq.cpp new file mode 100644 index 00000000..788ddbbb --- /dev/null +++ b/kernel/fiasco/src/jdb/jdb_attach_irq.cpp @@ -0,0 +1,205 @@ +IMPLEMENTATION: + +#include + +#include "irq_chip.h" +#include "irq.h" +#include "irq_mgr.h" +#include "jdb_module.h" +#include "kernel_console.h" +#include "static_init.h" +#include "thread.h" +#include "types.h" + + +//=================== +// Std JDB modules +//=================== + +/** + * 'IRQ' module. + * + * This module handles the 'R' command that + * provides IRQ attachment and listing functions. + */ +class Jdb_attach_irq : public Jdb_module +{ +public: + Jdb_attach_irq() FIASCO_INIT; +private: + static char subcmd; +}; + +char Jdb_attach_irq::subcmd; +static Jdb_attach_irq jdb_attach_irq INIT_PRIORITY(JDB_MODULE_INIT_PRIO); + +IMPLEMENT +Jdb_attach_irq::Jdb_attach_irq() + : Jdb_module("INFO") +{} + +PUBLIC +Jdb_module::Action_code +Jdb_attach_irq::action( int cmd, void *&args, char const *&, int & ) +{ + if (cmd) + return NOTHING; + + if ((char*)args == &subcmd) + { + switch (subcmd) + { + case 'l': // list + { + Irq_base *r; + putchar('\n'); + unsigned n = Irq_mgr::mgr->nr_irqs(); + for (unsigned i = 0; i < n; ++i) + { + r = static_cast(Irq_mgr::mgr->irq(i)); + if (!r) + continue; + printf("IRQ %02x/%02d\n", i, i); + } + return NOTHING; + } + } + } + return NOTHING; +} + +PUBLIC +int +Jdb_attach_irq::num_cmds() const +{ + return 1; +} + +PUBLIC +Jdb_module::Cmd const * +Jdb_attach_irq::cmds() const +{ + static Cmd cs[] = + { { 0, "R", "irq", " [l]ist/[a]ttach: %c", + "R{l}\tlist IRQ threads", &subcmd } + }; + + return cs; +} + + +IMPLEMENTATION: + +#include "jdb_kobject.h" +#include "irq.h" + +class Jdb_kobject_irq : public Jdb_kobject_handler +{ +}; + + +/* This macro does kind of hacky magic, It uses heuristics to compare + * If a C++ object object has a desired type. Therefore the vtable pointer + * (*z) of an object is compared to a desired vtable pointer (with some fuzz). + * The fuzz is necessary because there is usually a prefix data structure + * in each vtable and the size depends on the compiler. + * We use a range from x to x + 6 * wordsize. + * + * It is generally uncritical if this macro delivers a false negative. In + * such a case the JDB may deliver less information to the user. However, it + * critical to have a false positive, because JDB would probably crash. + */ +#define FIASCO_JDB_CMP_VTABLE(n, o) \ + extern char n[]; \ + char const *const *z = reinterpret_cast(o); \ + return (*z >= n && *z <= n + 6 * sizeof(Mword)) ? (o) : 0 + + +PUBLIC static +Irq_sender * +Jdb_kobject_irq::dcast_h(Irq_sender *i) +{ + FIASCO_JDB_CMP_VTABLE(_ZTV10Irq_sender, i); +} + +PUBLIC static +Irq_muxer * +Jdb_kobject_irq::dcast_h(Irq_muxer *i) +{ + FIASCO_JDB_CMP_VTABLE(_ZTV9Irq_muxer, i); +} + +PUBLIC template +static +T +Jdb_kobject_irq::dcast(Kobject_common *o) +{ + Irq *i = Kobject::dcast(o); + if (!i) + return 0; + + return dcast_h(static_cast(i)); +} + +PUBLIC inline +Jdb_kobject_irq::Jdb_kobject_irq() + : Jdb_kobject_handler(Irq::static_kobj_type) +{ + Jdb_kobject::module()->register_handler(this); +} + +PUBLIC +char const * +Jdb_kobject_irq::kobject_type() const +{ + return JDB_ANSI_COLOR(white) "IRQ" JDB_ANSI_COLOR(default); +} + + +PUBLIC +bool +Jdb_kobject_irq::handle_key(Kobject_common *o, int key) +{ + (void)o; (void)key; + return false; +} + + + +PUBLIC +Kobject_common * +Jdb_kobject_irq::follow_link(Kobject_common *o) +{ + Irq_sender *t = Jdb_kobject_irq::dcast(o); + Kobject_common *k = t ? Kobject::from_dbg(Kobject_dbg::pointer_to_obj(t->owner())) : 0; + return k ? k : o; +} + +PUBLIC +bool +Jdb_kobject_irq::show_kobject(Kobject_common *, int) +{ return true; } + +PUBLIC +int +Jdb_kobject_irq::show_kobject_short(char *buf, int max, Kobject_common *o) +{ + Irq *i = Kobject::dcast(o); + Kobject_common *w = follow_link(o); + Irq_sender *t = Jdb_kobject_irq::dcast(o); + + return snprintf(buf, max, " I=%3lx %s L=%lx T=%lx F=%x Q=%d", + i->pin(), i->chip()->chip_type(), i->obj_id(), + w != o ? w->dbg_info()->dbg_id() : 0, + (unsigned)i->flags(), + t ? t->queued() : -1); +} + +static +bool +filter_irqs(Kobject_common const *o) +{ return Kobject::dcast(o); } + +static Jdb_kobject_list::Mode INIT_PRIORITY(JDB_MODULE_INIT_PRIO) tnt("[IRQs]", filter_irqs); + +static Jdb_kobject_irq jdb_kobject_irq INIT_PRIORITY(JDB_MODULE_INIT_PRIO); diff --git a/kernel/fiasco/src/jdb/jdb_bp.cpp b/kernel/fiasco/src/jdb/jdb_bp.cpp new file mode 100644 index 00000000..9f318916 --- /dev/null +++ b/kernel/fiasco/src/jdb/jdb_bp.cpp @@ -0,0 +1,8 @@ +// Implementation for those who do not provide a breakpoint implementation +INTERFACE: + +class Jdb_bp +{ +public: + static int instruction_bp_at_addr(Address) { return 0; } +}; diff --git a/kernel/fiasco/src/jdb/jdb_bts.cpp b/kernel/fiasco/src/jdb/jdb_bts.cpp new file mode 100644 index 00000000..84c35d8c --- /dev/null +++ b/kernel/fiasco/src/jdb/jdb_bts.cpp @@ -0,0 +1,331 @@ +IMPLEMENTATION: + +#include +#include "config.h" +#include "cpu.h" +#include "initcalls.h" +#include "jdb.h" +#include "jdb_input.h" +#include "jdb_module.h" +#include "jdb_screen.h" +#include "jdb_symbol.h" +#include "keycodes.h" +#include "kernel_console.h" +#include "mem_layout.h" +#include "panic.h" +#include "regdefs.h" +#include "static_init.h" +#include "vmem_alloc.h" + +class Bts_entry; + +class Jdb_bts : public Jdb_module +{ +public: + Jdb_bts() FIASCO_INIT; +private: + static char first_char; + static Mword _absy; + static Mword _addy; +}; + +enum +{ + Bts_entries = 44000, + Bts_ctrl = Mem_layout::Jdb_bts_area, + Bts_start = Mem_layout::Jdb_bts_area + 0x80, + Bts_size = Bts_entries * 12, +}; + +class Bts_entry +{ +public: + Unsigned32 from; + Unsigned32 to; + Unsigned32 predicted; +}; + +char Jdb_bts::first_char; +Mword Jdb_bts::_absy = 0; +Mword Jdb_bts::_addy = 0; + +PUBLIC inline +Space * +Bts_entry::task() +{ + return 0; //(predicted & 0xffff0000) >> 16; +} + +PUBLIC inline +void +Bts_entry::task(Space * /*nr*/) +{ + //predicted = (predicted & 0x0000ffff) | (nr << 16); +} + +PUBLIC inline +int +Bts_entry::pred() +{ + return (predicted & 0x10); +} + +IMPLEMENT +Jdb_bts::Jdb_bts() + : Jdb_module("MONITORING") +{ + if (Cpu::boot_cpu()->bts_type() != Cpu::Bts_unsupported) + allocate(); +} + +FIASCO_INIT +void +Jdb_bts::allocate() +{ + for (Address addr=Bts_ctrl; addr= Bts_entries) + return 0; + + Unsigned32 *dsm = (Unsigned32*)Bts_ctrl; + Unsigned32 curr = (dsm[1] - Bts_start) / 12 - 1; + + if (curr >= Bts_entries) + curr = Bts_entries-1; + if (idx > curr) + idx = Bts_entries - idx + curr; + else + idx = curr - idx; + + return (Bts_entry*)(Bts_start + 12*idx); +} + +Mword +Jdb_bts::search_next_user_kernel(Mword idx) +{ + Bts_entry *e = lookup(idx), *e_end = lookup(Bts_entries-1); + + if (!e) + return idx; + + bool in_kernel = Mem_layout::in_kernel(e->from); + + while (in_kernel == Mem_layout::in_kernel(e->from)) + { + idx++; + e--; + if (e < (Bts_entry*)Bts_start) + e = (Bts_entry*)(Bts_start + Bts_size - 12); + if (e == e_end) + break; + } + + return idx; +} + +void +Jdb_bts::set_task(Mword idx, Space *task) +{ + Bts_entry *e = lookup(idx), *e_end = lookup(Bts_entries-1); + + if (!e) + return; + + while (!Mem_layout::in_kernel(e->from)) + { + e->task(task); + e--; + if (e < (Bts_entry*)Bts_start) + e = (Bts_entry*)(Bts_start + Bts_size - 12); + if (e == e_end) + break; + } +} + +bool +Jdb_bts::show_entry(Mword idx) +{ + Bts_entry *e; + + Kconsole::console()->getchar_chance(); + + if (!(e = lookup(idx))) + return false; + + printf(" %5ld: %08x => %08x %c", + idx, e->from, e->to, e->pred() ? 'p' : ' '); + + Space *task = e->task(); + + if (Mem_layout::in_kernel(e->from) || task != 0) + { + Address sym_addr = e->from; + char buffer[64]; + + if (Jdb_symbol::match_addr_to_symbol_fuzzy(&sym_addr, task, + buffer, + 46 < sizeof(buffer) + ? 46 : sizeof(buffer)) + && e->from-sym_addr < 1024) + { + printf(" %s", buffer); + if (e->from-sym_addr) + printf(" %s+ 0x%lx\033[m", Jdb::esc_line, e->from-sym_addr); + } + } + puts("\033[K"); + + return true; +} + +void +Jdb_bts::show() +{ + Mword lines = Jdb_screen::height()-1; + bool status_redraw = true; + + Jdb::clear_screen(); + + for (;;) + { + Mword i; + int c; + + Jdb::cursor(1, 1); + for (i=0; i=next usr/krnl =set task", + "_"); + status_redraw = false; + } + Jdb::cursor(_addy+1, 1); + putstr(Jdb::esc_emph); + show_entry(_absy+_addy); + putstr("\033[m"); + Jdb::cursor(_addy+1, 1); + c = Jdb_core::getchar(); + show_entry(_absy+_addy); + + if (Jdb::std_cursor_key(c, 0, lines, Bts_entries - lines, + &_absy, &_addy, 0, &redraw)) + continue; + + switch (c) + { + case KEY_ESC: + return; + case ' ': + Jdb::printf_statline("bts", "=commit change", "task="); + Jdb::cursor(Jdb_screen::height(), 11); + Mword new_task; + if (Jdb_input::get_mword(&new_task, 8, 16)) + { + set_task(_absy+_addy, (Space*)new_task); + redraw = true; + } + break; + case KEY_RETURN: + if (Jdb_disasm::avail()) + { + Bts_entry *e = Jdb_bts::lookup(_absy+_addy); + if (e) + { + if (!Jdb_disasm::show(e->from, e->task(), 1)) + return; + redraw = true; + status_redraw = true; + } + } + break; + case KEY_TAB: + _absy = search_next_user_kernel(_absy); + if (_absy > Bts_entries - lines) + _absy = Bts_entries - lines; + _addy = 0; + redraw = true; + break; + default: + if (Jdb::is_toplevel_cmd(c)) + return; + break; + } + } + } +} + +PUBLIC +Jdb_module::Action_code +Jdb_bts::action(int, void *&, char const *&, int &) +{ + if (Cpu::boot_cpu()->bts_type() == Cpu::Bts_unsupported) + { + printf("Branch trace store unsupported\n"); + return NOTHING; + } + + switch (first_char) + { + case '+': + case '-': + Cpu::boot_cpu()->bts_enable(first_char == '+'); + putchar(first_char); + putchar('\n'); + break; + + default: + show(); + break; + } + + return NOTHING; +} + +PUBLIC +int +Jdb_bts::num_cmds() const +{ + return 1; +} + +PUBLIC +Jdb_module::Cmd const * Jdb_bts::cmds() const +{ + static Cmd cs[] = + { + { 0, "Z", "bts", "%C", + "Z[{+|-}]\tshow BTS records, enable/disable BTS recording", + &first_char }, + }; + return cs; +} + +static Jdb_bts jdb_bts INIT_PRIORITY(JDB_MODULE_INIT_PRIO); diff --git a/kernel/fiasco/src/jdb/jdb_console_buffer.cpp b/kernel/fiasco/src/jdb/jdb_console_buffer.cpp new file mode 100644 index 00000000..d03bac3f --- /dev/null +++ b/kernel/fiasco/src/jdb/jdb_console_buffer.cpp @@ -0,0 +1,431 @@ +IMPLEMENTATION: + +#include +#include +#include + +#include "config.h" +#include "jdb_module.h" +#include "jdb.h" +#include "kernel_console.h" +#include "keycodes.h" +#include "kmem_alloc.h" +#include "koptions.h" +#include "static_init.h" + +/** + * A output console that stores the output in a buffer. + * + * This buffer can be useful for accessing older the debugging + * output without a serial console. + */ +class Console_buffer : public Console +{ +private: + static bool _enabled; + static size_t out_buf_size; + static size_t out_buf_len; + static char *out_buf; + static char *out_buf_w; +}; + +bool Console_buffer::_enabled; +size_t Console_buffer::out_buf_size; +size_t Console_buffer::out_buf_len; +char* Console_buffer::out_buf; +char* Console_buffer::out_buf_w; + +PRIVATE static +void +Console_buffer::at_jdb_enter() +{ + _enabled = false; +} + +PRIVATE static +void +Console_buffer::at_jdb_leave() +{ + _enabled = true; +} + +PUBLIC +Console_buffer::Console_buffer() +{ + static Jdb_handler enter(at_jdb_enter); + static Jdb_handler leave(at_jdb_leave); + + Jdb::jdb_enter.add(&enter); + Jdb::jdb_leave.add(&leave); + + size_t len = 2 * Config::PAGE_SIZE; + + if (Koptions::o()->opt(Koptions::F_out_buf)) + len = Koptions::o()->out_buf; + + alloc(len); +} + +/** + * Allocates a buffer of the given size. + * @param size the buffer size in bytes. + */ +PUBLIC static +void +Console_buffer::alloc(size_t size) +{ + if (!out_buf) + { + out_buf_size = (size + Config::PAGE_SIZE - 1) & Config::PAGE_MASK; + if (out_buf_size) + out_buf = (char *)Kmem_alloc::allocator()-> + unaligned_alloc(out_buf_size); + + out_buf_w = out_buf; + + _enabled = true; + } +} + +PUBLIC +Console_buffer::~Console_buffer() +{ + if(out_buf) + Kmem_alloc::allocator()-> + unaligned_free(out_buf_size, out_buf); + out_buf = 0; +} + +PUBLIC +int +Console_buffer::write( char const *str, size_t len ) +{ + if (_enabled && out_buf) + { + while(len) + { + size_t s; + s = out_buf_size - (out_buf_w - out_buf); + if (s>len) + s = len; + memcpy( out_buf_w, str, s ); + if (out_buf_w + s >= out_buf + out_buf_size) + out_buf_w = out_buf; + else + out_buf_w += s; + len -= s; + out_buf_len += s; + if (out_buf_len > out_buf_size) + out_buf_len = out_buf_size; + } + } + return len; +} + +PRIVATE static inline +void +Console_buffer::inc_ptr(char **c) +{ + if (++*c >= out_buf + out_buf_size) + *c = out_buf; +} + +PRIVATE static inline +void +Console_buffer::dec_out_ptr(char **c) +{ + if (--*c < out_buf) + *c += out_buf_size; +} + +PUBLIC +int +Console_buffer::getchar(bool) +{ + return -1; +} + +/** + * Prints the buffer to the standard I/O. + * @param lines the number of lines to skip. + * This method prints the buffer contents to the normal I/O. + * Before doing this the buffer is disabled, that no recursion + * appers even if the buffer is part of the muxed I/O. + */ +PUBLIC static +int +Console_buffer::print_buffer(unsigned lines) +{ + if (out_buf) + { + bool page = (lines == 0); + char *c = out_buf_w; + size_t len = out_buf_len; + + if (out_buf_len == 0) + { + puts("\n"); + return 1; + } + + // go back lines + if (lines) + { + size_t l = out_buf_len; + + // skip terminating 0x00, 0x0a ... + while ((*c == '\0' || *c == '\r') && (l > 0)) + { + dec_out_ptr(&c); + l--; + } + + while (lines-- && (l > 0)) + { + dec_out_ptr(&c); + l--; + + while ((*c != '\n') && (l > 0)) + { + dec_out_ptr(&c); + l--; + } + } + + if (*c == '\n') + { + inc_ptr(&c); + l++; + } + + len = out_buf_len - l; + } + else + { + c -= out_buf_len; + if (c < out_buf) + c += out_buf_size; + } + + lines = 0; + while (len > 0) + { + putchar(*c); + if (*c == '\n') + { + if (page && !Jdb_core::new_line(lines)) + return 1; + } + inc_ptr(&c); + len--; + } + + putchar('\n'); + return 1; + } + + printf("use -out_buf= to enable output buffer\n"); + return 0; +} + + +PRIVATE static +int +Console_buffer::strncmp(char *start, const char *search, size_t len) +{ + while (len && *search && *start == *search) + { + len--; + inc_ptr(&start); + search++; + } + + return *search == '\0'; +} + +/** + * Prints the buffer to the standard I/O. + * @param str the string the output should be filtered for + * This method prints the buffer contents to the normal I/O. + * Before doing this the buffer is disabled, that no recursion + * appers even if the buffer is part of the muxed I/O. + */ +PUBLIC static +int +Console_buffer::print_buffer(const char *str) +{ + if (out_buf) + { + char *bol = out_buf_w; + size_t len = out_buf_len; + + if (out_buf_len == 0) + { + puts("\n"); + return 1; + } + + bol -= out_buf_len; + if (bol < out_buf) + bol += out_buf_size; + +next_line: + while (len > 0) + { + char *bos = bol; + size_t lens = len; + const char *s; + + while (lens > 0) + { + if (*bos == '\n') + { + bol = bos; + inc_ptr(&bol); + len = lens-1; + goto next_line; + } + if (strncmp(bos, str, lens)) + { + // found => print whole line + for (; len && bol != bos; len--) + { + putchar(*bol); + inc_ptr(&bol); + } + found_again: + putstr(Jdb::esc_emph); + for (s=str; *s && len; len--, s++) + { + putchar(*bol); + inc_ptr(&bol); + } + putstr("\033[m"); + for (; len && *bol != '\n'; len--) + { + if (*str && strncmp(bol, str, len)) + goto found_again; + putchar(*bol); + inc_ptr(&bol); + } + if (len) + { + putchar(*bol); + inc_ptr(&bol); + len--; + } + goto next_line; + } + inc_ptr(&bos); + lens--; + } + } + + putchar('\n'); + return 1; + } + + printf("use -out_buf= to enable output buffer\n"); + return 0; +} + +PUBLIC +Mword Console_buffer::get_attributes() const +{ + return BUFFER | OUT; +} + + +PUBLIC static FIASCO_INIT +void +Console_buffer::init() +{ + static Console_buffer cb; + Kconsole::console()->register_console(&cb); +} + +STATIC_INITIALIZE(Console_buffer); + + + +/// Jdb module + +class Jdb_cb : public Jdb_module +{ +public: + Jdb_cb() FIASCO_INIT; +private: + static char first_char; + static char search_str[30]; + static Mword output_lines; +}; + +char Jdb_cb::first_char; +char Jdb_cb::search_str[30]; +Mword Jdb_cb::output_lines; + +PUBLIC +Jdb_module::Action_code +Jdb_cb::action(int cmd, void *&args, char const *&fmt, int &next_char) +{ + if (cmd != 0) + return NOTHING; + + if (args == &first_char) + { + if (first_char == '/') + { + putchar(first_char); + fmt = "%30s"; + args = search_str; + return EXTRA_INPUT; + } + output_lines = 0; + if (first_char != ' ' && first_char != KEY_RETURN) + { + next_char = first_char; + args = &output_lines; + fmt = "%4d"; + return EXTRA_INPUT_WITH_NEXTCHAR; + } + } + else if (args == search_str) + { + putchar('\n'); + Console_buffer::print_buffer(search_str); + return NOTHING; + } + + putchar('\n'); + Console_buffer::print_buffer(output_lines); + + return NOTHING; +} + +PUBLIC +Jdb_module::Cmd const * +Jdb_cb::cmds() const +{ + static const Cmd cs[] = + { + { 0, "B", "consolebuffer", "%C", + "B[|/]\tshow (last n lines of) console buffer/search", + &first_char }, + }; + return cs; +} + +PUBLIC +int +Jdb_cb::num_cmds() const +{ + return 1; +} + +IMPLEMENT +Jdb_cb::Jdb_cb() + : Jdb_module("GENERAL") +{ +} + +static Jdb_cb jdb_cb INIT_PRIORITY(JDB_MODULE_INIT_PRIO); diff --git a/kernel/fiasco/src/jdb/jdb_core.cpp b/kernel/fiasco/src/jdb/jdb_core.cpp new file mode 100644 index 00000000..b7f86a1c --- /dev/null +++ b/kernel/fiasco/src/jdb/jdb_core.cpp @@ -0,0 +1,962 @@ +INTERFACE: + +#include "static_init.h" +#include "jdb_module.h" + +/** + * The core of the modularized Jdb. + * @see Jdb_module + * @see Jdb_category + * + * This class provides the core functions for handling + * Jdb_modules and providing them with the right input. + * + */ +class Jdb_core +{ +public: + + /** + * The command structure for Jdb_core. + * + * This structure consists of a pointer to the Jdb_module + * and a Jdb_module::Cmd structure. It is used in exec_cmd() + * and returned from has_cmd(). + */ + struct Cmd + { + /** + * Pointer to the module providing this command. + */ + Jdb_module *mod; + + /** + * The Jdb_module::Cmd structure, describing the command. + * + * If this is a null pointer the command is invalid. + * @see Jdb_module + * @see Jdb_module::Cmd + */ + Jdb_module::Cmd const *cmd; + + /** + * Create a Jdb_core::Cmd. + * @param _mod the Jdb_module providing the command. + * @param _cmd the command structure (see Jdb_module::Cmd). + */ + Cmd(Jdb_module *_mod, Jdb_module::Cmd const *_cmd = 0) + : mod(_mod), cmd(_cmd) + {} + }; + + /** + * Get the command structure accoring to the given name. + * @param cmd the command to look for. + * @return A valid Cmd structure if cmd was found, or a + * Cmd structure where Cmd::cmd is a null pointer if + * no module provides such a command. + */ + static Cmd has_cmd(char const *cmd); + + /** + * Execute the command according to cmd. + * @param cmd the command structure (see Jdb_core::Cmd), which + * describes the command to execute. + * @return 0 if Jdb_module::action() returned LEAVE + * 1 if Jdb_module::action() returned NOTHING + * 2 if Jdb_module::action() returned GO_BACK (KEY_HOME entered) + * 3 if the input was aborted (KEY_ESC entered) or was invalid + * + * This method is actually responsible for reading the input + * with respect to the commands format string and calling + * the Jdb_module::action() method after that. + * + */ + static int exec_cmd(Cmd const cmd, char const *str, int push_next_char = -1); + + /** + * Overwritten getchar() to be able to handle next_char. + */ + static int getchar(void); + + /** + * Call this function every time a `\n' is written to the + * console and it stops output when the screen is full. + * @return 0 if user wants to abort the output (escape or 'q' pressed) + */ + static int new_line(unsigned &line); + + static void prompt_start(); + static void prompt_end(); + static void prompt(); + static int prompt_len(); + static void update_prompt(); + static int set_prompt_color(char v); + + /** + * Like strlen but do not count ESC sequences. + */ + static unsigned print_len(const char *s); + + static char esc_prompt[]; + + +public: + static bool short_mode; + typedef int (Input_fmt)(char fmt, int *size, char const *cmd_str, void *buf); + +private: + static int next_char; + static Input_fmt *_fmt_list[26]; +}; + +#define JDB_ANSI_black "30" +#define JDB_ANSI_gray "30;1" +#define JDB_ANSI_red "31" +#define JDB_ANSI_lightred "31;1" +#define JDB_ANSI_green "32" +#define JDB_ANSI_lightgreen "32;1" +#define JDB_ANSI_brown "33" +#define JDB_ANSI_yellow "33;1" +#define JDB_ANSI_blue "34" +#define JDB_ANSI_lightblue "34;1" +#define JDB_ANSI_magenta "35" +#define JDB_ANSI_lightmagenta "35;1" +#define JDB_ANSI_cyan "36" +#define JDB_ANSI_lightcyan "36;1" +#define JDB_ANSI_white "37" +#define JDB_ANSI_brightwhite "37;1" +#define JDB_ANSI_default "" + +#define JDB_ANSI_COLOR(color) "\033[" JDB_ANSI_##color "m" + +#define JDB_ANSI_END "\033[m" + + +IMPLEMENTATION: + +#include +#include +#include +#include +#include +#include + +#include "div32.h" +#include "l4_types.h" +#include "kernel_console.h" +#include "keycodes.h" +#include "jdb_prompt_ext.h" +#include "jdb_screen.h" + +bool Jdb_core::short_mode = true; +int Jdb_core::next_char = -1; +char Jdb_core::esc_prompt[32] = JDB_ANSI_COLOR(green); +Jdb_core::Input_fmt *Jdb_core::_fmt_list[26]; + +PUBLIC static +bool +Jdb_core::add_fmt_handler(char fmt, Input_fmt* hdlr) +{ + if (fmt < 'a' || (fmt - 'a') >= (int)(sizeof(_fmt_list)/sizeof(_fmt_list[0]))) + return false; + + if (_fmt_list[fmt - 'a']) + return false; + + _fmt_list[fmt - 'a'] = hdlr; + return true; +} + +PUBLIC static +void +Jdb_core::print_prompt() +{ prompt_start(); prompt(); prompt_end(); } + +IMPLEMENT +void Jdb_core::update_prompt() +{ + Jdb_prompt_ext::update_all(); +} + +IMPLEMENT +void Jdb_core::prompt_start() +{ + putstr(esc_prompt); +} + +IMPLEMENT +void Jdb_core::prompt_end() +{ + putstr(JDB_ANSI_END); +} + +IMPLEMENT +void Jdb_core::prompt() +{ + Jdb_prompt_ext::do_all(); + if (short_mode) + putstr("jdb: "); + else + putstr("jdb# "); +} + +IMPLEMENT +int Jdb_core::prompt_len() +{ + return 5; +} + +IMPLEMENT +unsigned Jdb_core::print_len(const char *s) +{ + unsigned l = 0; + while (*s) + { + if (s[0] == '\033' && s[1] == '[') + { + s += 2; + while (*s && *s != 'm') + s++; + if (*s) + s++; // skip 'm' + } + else + { + l++; + s++; + } + } + return l; +} + +PUBLIC static +int +Jdb_core::get_ansi_color(char c) +{ + switch(c) + { + case 'N': case 'n': return 30; + case 'R': case 'r': return 31; + case 'G': case 'g': return 32; + case 'Y': case 'y': return 33; + case 'B': case 'b': return 34; + case 'M': case 'm': return 35; + case 'C': case 'c': return 36; + case 'W': case 'w': return 37; + default: return 0; + } +} + + +IMPLEMENT +int Jdb_core::set_prompt_color(char x) +{ + unsigned pc = get_ansi_color(x); + + if (pc == 0) + return 0; + + if (x >= 'A' && x <= 'Z') + snprintf(esc_prompt, sizeof(esc_prompt) - 1, "\033[%d;%dm", pc, 1); + else + snprintf(esc_prompt, sizeof(esc_prompt) - 1, "\033[%dm", pc); + + return 1; + +} + +IMPLEMENT +Jdb_core::Cmd Jdb_core::has_cmd(char const *cmd) +{ + for (Jdb_module::List::Const_iterator m = Jdb_module::modules.begin(); + m != Jdb_module::modules.end(); ++m) + { + Cmd c(*m); + c.cmd = m->has_cmd(cmd, short_mode); + if (c.cmd) + return c; + } + + return Cmd(0); +} + +PRIVATE static +unsigned +Jdb_core::match_len(char const *a, char const *b, unsigned l) +{ + unsigned p = 0; + while (*a && *b && p < l && *a == *b) + { + ++a; ++b; ++p; + } + return p; +} + +PUBLIC static +unsigned +Jdb_core::print_alternatives(char const *prefix) +{ + unsigned prefix_len = 0; + char const *match = 0; + typedef Jdb_module::List::Const_iterator Iter; + for (Iter m = Jdb_module::modules.begin(); m != Jdb_module::modules.end(); ++m) + { + unsigned sc_max = m->num_cmds(); + Jdb_module::Cmd const *cmds = m->cmds(); + for (unsigned sc = 0; sc < sc_max; ++sc) + { + if (!Jdb_module::match(cmds[sc].cmd, prefix, false)) + continue; + + if (!match) + { + match = cmds[sc].cmd; + prefix_len = strlen(match); + } + else + prefix_len = match_len(match, cmds[sc].cmd, prefix_len); + printf("%s %s\n", cmds[sc].cmd, cmds[sc].fmt); + } + } + return prefix_len; +} + +PUBLIC static +Jdb_core::Cmd +Jdb_core::complete_cmd(char const *prefix, bool &multi_match) +{ + Cmd match(0,0); + multi_match = false; + typedef Jdb_module::List::Const_iterator Iter; + for (Iter m = Jdb_module::modules.begin(); m != Jdb_module::modules.end(); ++m) + { + unsigned sc_max = m->num_cmds(); + Jdb_module::Cmd const *cmds = m->cmds(); + for (unsigned sc = 0; sc < sc_max; ++sc) + { + if (!Jdb_module::match(cmds[sc].cmd, prefix, false)) + continue; + + if (match.cmd) + multi_match = true; + else + match = Cmd(*m, cmds + sc); + } + } + + return match; +} + +IMPLEMENT +int Jdb_core::getchar( void ) +{ + if (next_char != -1) + { + int c = next_char; + next_char = -1; + return c; + } + + return Kconsole::console()->getchar(); +} + +PUBLIC static +int +Jdb_core::cmd_getchar(char const *&str) +{ + if (next_char != -1) + { + int c = next_char; + next_char = -1; + return c; + } + + if (short_mode) + return getchar(); + + if (!str) + return KEY_RETURN; + + if (!*str) + return KEY_RETURN; + + return *(str++); +} + +PRIVATE static inline +void +Jdb_core::cmd_putchar(int c) +{ if (short_mode) putchar(c); } + +IMPLEMENT +int Jdb_core::exec_cmd(Cmd const cmd, char const *str, int push_next_char = -1) +{ + char const* f = cmd.cmd->fmt; + char const* f1; + + //char args[256]; + void *argbuf = (void*)cmd.cmd->argbuf; + + enum { + NORMAL, + UNSIGNED, + MULTI, + } num_mode; + + int num_base = 10; + int num_pos = 0, num_digit = 0; + int max_len = 0, max_digit = 0; + int c, cv; + char fm; + + next_char = push_next_char; + + do { + + char *next_arg = (char*)argbuf; + char const *old_f = f; + while(*f) + { + f1 = f; + + while(*f && *f!='%') + ++f; + + putnstr( f1, (f-f1) ); + + if(*(f++)) + { + int long_fmt = sizeof(long long int) == sizeof(void*); + bool negative = false; + long long int val = 0; + max_len = 0; + + next_fmt: + if(*(f)) + switch((fm=*(f++))) + // Attention: Each case statement must finish with "continue" + // else it falls through to int_done! + { + case '0': case '1': case '2': + case '3': case '4': case '5': + case '6': case '7': case '8': + case '9': + max_len = max_len * 10 + fm - '0'; + goto next_fmt; + case '%': + cmd_putchar('%'); + continue; + + case 'l': + long_fmt++; + if(long_fmt > 2) + long_fmt = 2; + goto next_fmt; + + case 'h': + long_fmt--; + if(long_fmt < -1) + long_fmt = -1; + goto next_fmt; + + case 'i': + num_base = 10; + num_mode = MULTI; + goto input_num; + + case 'p': + num_base = 16; + num_mode = UNSIGNED; + if(sizeof(short int)==sizeof(void*)) + long_fmt = -1; + else if(sizeof(int)==sizeof(void*)) + long_fmt = 0; + else if(sizeof(long int)==sizeof(void*)) + long_fmt = 1; + else //if(sizeof(long long int)==sizeof(void*)) + long_fmt = 2; + goto input_num; + + case 'o': + cmd_putchar('0'); + num_mode = UNSIGNED; + num_base = 8; + goto input_num; + + case 'X': + case 'x': + num_mode = UNSIGNED; + num_base = 16; + goto input_num; + + case 'd': + num_mode = NORMAL; + num_base = 10; + goto input_num; + + case 'u': + num_mode = UNSIGNED; + num_base = 10; + goto input_num; + + input_num: + num_pos = num_digit = 0; + max_digit = 0; + if (num_base == 16) + { + if (long_fmt == -1) + max_digit = 2*sizeof(short int); + else if (long_fmt == 0) + max_digit = 2*sizeof(int); + else if (long_fmt == 1) + max_digit = 2*sizeof(long int); + else + max_digit = 2*sizeof(long long int); + } + while((c = cmd_getchar(str)) != ' ' && c!=KEY_RETURN) + { + if(c==KEY_ESC) + return 3; + + if(c==KEY_BACKSPACE && num_pos>0) + { + putstr("\b \b"); + if(num_pos == 1 && negative) + negative = false; + else if(num_pos==1 && num_mode==MULTI && num_base==8) + num_base = 10; + else if(num_pos==2 && num_mode==MULTI && num_base==16) + num_base = 8; + else + { + val = div32(val, num_base); + num_digit--; + } + + num_pos--; + continue; + } + else if(num_mode!=UNSIGNED && num_pos==0 && c=='-') + { + num_pos++; + cmd_putchar(c); + negative = true; + continue; + } + else if(num_mode==MULTI && num_pos==0 && c=='0') + { + num_pos++; + cmd_putchar(c); + num_base = 8; + continue; + } + else if(num_mode==MULTI && num_pos==1 && num_base==8 + && (c=='x' || c=='X')) + { + num_pos++; + cmd_putchar(c); + num_base = 16; + continue; + } + else if(num_pos==1 && (c=='x' || c=='X')) + { + // ignore 0x to allow direct pasting of addresses + num_pos--; + num_digit--; + putstr("\b \b"); + continue; + } + else if(c>='0' && c<='9') + { + cv = c-'0'; + } + else if((c|0x20)>='a' && (c|0x20)<='f') + { + cv = (c|0x20) - 'a' + 10; + } + else + continue; + + if(cv < num_base) + { + num_pos++; + num_digit++; + cmd_putchar(c); + val = val * num_base + cv; + if ((max_len != 0 && num_pos >= max_len) || + (max_digit != 0 && num_digit >= max_digit)) + break; + } + } + if (num_pos == 0) + return 3; + goto int_done; + + case 't': printf("%%t is not supported...\n"); + continue; + + case 'C': + case 'c': + { + int c = cmd_getchar(str); + if(c==KEY_ESC) + return 3; + + if(fm == 'c' && isprint(c)) + cmd_putchar(c); + if(next_arg) + *next_arg++ = c; + } + continue; + + case 's': + case 'S': + if(!max_len) + continue; + + num_pos = 0; + while((c = cmd_getchar(str)) != KEY_RETURN && c!=' ') + { + if(c==KEY_ESC) + return 3; + + if(c==KEY_BACKSPACE && num_pos) + { + putstr("\b \b"); + num_pos--; + } + else if(isprint(c) && (num_pos+1 < max_len)) + { + cmd_putchar(c); + next_arg[num_pos++] = c; + } + + next_arg[num_pos] = '\0'; + + if (fm=='S') + { + int oldlen = num_pos; + (**(Jdb_module::Gotkey**)(next_arg+max_len)) + (next_arg, max_len, c); + int newlen = strlen(next_arg); + if (newlen > oldlen) + printf("%s", next_arg + oldlen); + else if (newlen < oldlen) + for (int i=newlen; i 'a' + && (fm - 'a') < (int)(sizeof(_fmt_list)/sizeof(_fmt_list[0])) + && _fmt_list[fm -'a']) + { + int size = sizeof(int); + switch(long_fmt) + { + default: break; + case 1: size = sizeof(long int); break; + case 2: size = sizeof(long long int); break; + case -1: size = sizeof(short int); break; + } + int res = (_fmt_list[fm - 'a'])(fm, &size, str, next_arg); + if (res) + return res; + + next_arg += size; + continue; + } + + puts(" unknown format! "); + return 3; + } + + int_done: + if(negative) val = -val; + + if(next_arg) + switch(long_fmt) + { + default: + { + int *v = (int*)next_arg; + *v = val; + next_arg += sizeof(int); + } + break; + case 1: + { + long int *v = (long int*)next_arg; + *v = val; + next_arg += sizeof(long int); + } + break; + case 2: + { + long long int *v = (long long int*)next_arg; + *v = val; + next_arg += sizeof(long long int); + } + break; + case -1: + { + short int *v = (short int*)next_arg; + *v = val; + next_arg += sizeof(short int); + } + break; + } + } + else + break; + } + + f = old_f; + + switch (cmd.mod->action(cmd.cmd->id, argbuf, f, next_char)) + { + case Jdb_module::EXTRA_INPUT: + // more input expected + next_char = -1; + // fall through + case Jdb_module::EXTRA_INPUT_WITH_NEXTCHAR: + // more input expected, also consider previously entered key + break; + case Jdb_module::LEAVE: + // leave kernel debugger + return 0; + case Jdb_module::GO_BACK: + // user entered KEY_HOME + return 2; + case Jdb_module::NOTHING: + // finished successfully + return 1; + default: + // there was an error + return 3; + } + } while(1); + +} + +IMPLEMENT +int +Jdb_core::new_line( unsigned &line ) +{ + if (line++ > Jdb_screen::height()-3) + { + putstr("--- CR: line, SPACE: page, ESC: abort ---"); + int a = Kconsole::console()->getchar(); + putstr("\r\033[K"); + + switch (a) + { + case KEY_ESC: + case 'q': + case '^': + cmd_putchar('\n'); + return 0; + case KEY_RETURN: + line--; + return 1; + default: + line=0; + return 1; + } + } + return 1; +} + + +//=================== +// Std JDB modules +//=================== + + +/** + * Private 'go' module. + * + * This module handles the 'go' or 'g' command + * that continues normal program execution. + */ +class Go_m : public Jdb_module +{ +public: + Go_m() FIASCO_INIT; +}; + +static Go_m go_m INIT_PRIORITY(JDB_MODULE_INIT_PRIO); + +IMPLEMENT +Go_m::Go_m() + : Jdb_module("GENERAL") +{} + +PUBLIC +Jdb_module::Action_code Go_m::action( int, void *&, char const *&, int & ) +{ + return LEAVE; +} + +PUBLIC +int Go_m::num_cmds() const +{ + return 1; +} + +PUBLIC +Jdb_module::Cmd const * Go_m::cmds() const +{ + static Cmd cs[] = + { + { 0, "g", "go", "", + "g\tleave kernel debugger\n" + "Return\tshow debug message", 0 }, + }; + + return cs; +} + + +/** + * Private 'help' module. + * + * This module handles the 'help' or 'h' command and + * prints out a help screen. + */ +class Help_m : public Jdb_module +{ +public: + Help_m() FIASCO_INIT; +}; + + +static Help_m help_m INIT_PRIORITY(JDB_MODULE_INIT_PRIO); + + +PUBLIC +Jdb_module::Action_code Help_m::action( int, void *&, char const *&, int & ) +{ + size_t const tab_width = 27; + + if(Jdb_category::categories.begin() == Jdb_category::categories.end()) + { + printf("No debugger commands seem to have been registered\n"); + return NOTHING; + } + + unsigned line = 0; + + puts(""); + for (Jdb_category::List::Const_iterator c = Jdb_category::categories.begin(); + c != Jdb_category::categories.end(); ++c) + { + bool first = true; + for (Jdb_module::List::Const_iterator m = Jdb_module::modules.begin(); + m != Jdb_module::modules.end(); ++m) + { + if (m->category() != *c) + continue; + + if(first) + { + if(!Jdb_core::new_line(line)) + return NOTHING; + printf("\033[1m[%s]\033[0m %s", c->name(), c->description()); + putchar('\n'); + if(!Jdb_core::new_line(line)) + return NOTHING; + first = false; + } + unsigned ncmds = m->num_cmds(); + Jdb_module::Cmd const *cmds = m->cmds(); + for(unsigned x = 0; x < ncmds; x++) + { + char const *descr = cmds[x].descr; + if (!descr) + continue; + size_t pos = strcspn(descr, "\n\t"); + size_t xpos = 2; + putstr(" "); + while( pos < strlen(descr)) + { + putnstr(descr, pos); + xpos += pos; + switch(descr[pos]) + { + case '\n': + putchar('\n'); + if(!Jdb_core::new_line(line)) + return NOTHING; + putstr(" "); + xpos = 2; + break; + case '\t': + if(xpos +#include +#include "config.h" +#include "jdb_tbuf.h" +#include "jdb_module.h" +#include "kern_cnt.h" +#include "simpleio.h" +#include "static_init.h" + +class Jdb_counters : public Jdb_module +{ +public: + Jdb_counters() FIASCO_INIT; +private: + static char counters_cmd; +}; + +char Jdb_counters::counters_cmd; + +PRIVATE +void +Jdb_counters::show() +{ + putchar('\n'); + for (unsigned i=0; ikerncnts, 0, + sizeof(Jdb_tbuf::status()->kerncnts)); +} + +PUBLIC +Jdb_module::Action_code +Jdb_counters::action(int cmd, void *&, char const *&, int &) +{ + if (!Config::Jdb_accounting) + { + puts(" accounting disabled"); + return ERROR; + } + + if (cmd == 0) + { + switch (counters_cmd) + { + case 'l': + show(); + break; + case 'r': + reset(); + putchar('\n'); + break; + } + } + return NOTHING; +} + +PUBLIC +Jdb_counters::Cmd const * +Jdb_counters::cmds() const +{ + static Cmd cs[] = + { + { 0, "C", "cnt", "%c", + "C{l|r}\tshow/reset kernel event counters", &counters_cmd }, + }; + return cs; +} + +PUBLIC +int +Jdb_counters::num_cmds() const +{ + return 1; +} + +IMPLEMENT +Jdb_counters::Jdb_counters() + : Jdb_module("MONITORING") +{} + +static Jdb_counters jdb_counters INIT_PRIORITY(JDB_MODULE_INIT_PRIO); diff --git a/kernel/fiasco/src/jdb/jdb_dbinfo.cpp b/kernel/fiasco/src/jdb/jdb_dbinfo.cpp new file mode 100644 index 00000000..1fefbe5f --- /dev/null +++ b/kernel/fiasco/src/jdb/jdb_dbinfo.cpp @@ -0,0 +1,297 @@ +INTERFACE: + +#include "initcalls.h" +#include "types.h" + +class Jdb_symbol_info; +class Jdb_lines_info; + +class Jdb_dbinfo +{ +}; + + +//--------------------------------------------------------------------------- +IMPLEMENTATION: + +#include "config.h" + +// We have to do this here because Jdb_symbol and Jdb_lines must not depend +// on Kmem_alloc. +PRIVATE static inline NOEXPORT +void +Jdb_dbinfo::init_symbols_lines () +{ + Mword p; + + p = (sizeof(Jdb_symbol_info)*Jdb_symbol::Max_tasks) >> Config::PAGE_SHIFT; + Jdb_symbol::init(Kmem_alloc::allocator() + ->unaligned_alloc(p*Config::PAGE_SIZE), p); + p = (sizeof(Jdb_lines_info) *Jdb_lines::Max_tasks) >> Config::PAGE_SHIFT; + Jdb_lines::init(Kmem_alloc::allocator() + ->unaligned_alloc(p*Config::PAGE_SIZE), p); +} + + +//--------------------------------------------------------------------------- +IMPLEMENTATION[ia32,amd64]: + +#include "cpu_lock.h" +#include "jdb_lines.h" +#include "jdb_symbol.h" +#include "kmem.h" +#include "kmem_alloc.h" +#include "mem_layout.h" +#include "mem_unit.h" +#include "paging.h" +#include "space.h" +#include "static_init.h" + +const Address area_start = Mem_layout::Jdb_debug_start; +const Address area_end = Mem_layout::Jdb_debug_end; +const unsigned area_size = area_end - area_start; +const unsigned bitmap_size = (area_size / Config::PAGE_SIZE) / 8; + +// We don't use the amm library here anymore since it is nearly impossible +// to debug it and I got some strange behavior. Instead of this we use a +// simple bitfield here that takes 2k for a virtual memory size of 64MB +// which is enough for the Jdb debug info. Speed for allocating/deallocating +// pages is not an issue here. +static unsigned char bitmap[bitmap_size]; + +STATIC_INITIALIZE(Jdb_dbinfo); + +//--------------------------------------------------------------------------- +IMPLEMENTATION[ia32, amd64]: + +PUBLIC static FIASCO_INIT +void +Jdb_dbinfo::init() +{ + Address addr; + + for (addr = area_start; addr < area_end; addr += Config::SUPERPAGE_SIZE) + Kmem::kdir->walk(Virt_addr(addr), 100, pdir_alloc(Kmem_alloc::allocator())); + + init_symbols_lines(); +} + + +PRIVATE static +Address +Jdb_dbinfo::reserve_pages(unsigned pages) +{ + Lock_guard guard(&cpu_lock); + + Unsigned8 *ptr, bit; + + for (ptr=bitmap, bit=0; ptr=bitmap+bitmap_size) + return 0; + + c = *ptr1 & (1<= 8) + { + bit1 = 0; + ptr1++; + } + + if (c) + { + ptr = ptr1; + bit = bit1; + break; + } + + if (!--pages1) + { + // found area -- make it as reserved + for (ptr1=ptr, bit1=bit, pages1=pages; pages1>0; pages1--) + { + *ptr1 |= (1<= 8) + { + bit1 = 0; + ptr1++; + } + } + return area_start + Config::PAGE_SIZE * (8*(ptr-bitmap) + bit); + } + } + } + + return 0; +} + +PRIVATE static +void +Jdb_dbinfo::return_pages(Address addr, unsigned pages) +{ + Lock_guard guard(&cpu_lock); + + unsigned nr_page = (addr-area_start) / Config::PAGE_SIZE; + Unsigned8 *ptr = bitmap + nr_page/8, bit = nr_page % 8; + + for (; pages && ptr < bitmap+bitmap_size; pages--) + { + assert (*ptr & (1<= 8) + { + bit = 0; + ptr++; + } + } +} + +//--------------------------------------------------------------------------- +IMPLEMENTATION[ia32, amd64]: + +PUBLIC static +bool +Jdb_dbinfo::map(Address phys, size_t &size, Address &virt) +{ + Address offs = phys & ~Config::PAGE_MASK; + + size = (offs + size + Config::PAGE_SIZE - 1) & Config::PAGE_MASK; + virt = reserve_pages (size / Config::PAGE_SIZE); + if (!virt) + return false; + + phys &= Config::PAGE_MASK; + + Kmem::kdir->map(phys, Virt_addr(virt), Virt_size(size), + Pt_entry::Valid | Pt_entry::Writable | Pt_entry::Referenced + | Pt_entry::Dirty, 100, Ptab::Null_alloc()); + + virt += offs; + return true; +} + +PUBLIC static +void +Jdb_dbinfo::unmap(Address virt, size_t size) +{ + if (virt && size) + { + virt &= Config::PAGE_MASK; + + Kmem::kdir->unmap(Virt_addr(virt), Virt_size(size), 100); + Mem_unit::tlb_flush (); + + return_pages(virt, size/Config::PAGE_SIZE); + } +} + +PUBLIC static +void +Jdb_dbinfo::set(Jdb_symbol_info *sym, Address phys, size_t size) +{ + Address virt; + + if (!sym) + return; + + if (!phys) + { + sym->get (virt, size); + if (! virt) + return; + + unmap (virt, size); + sym->reset (); + return; + } + + if (! map (phys, size, virt)) + return; + + if (! sym->set (virt, size)) + { + unmap (virt, size); + sym->reset (); + } +} + +PUBLIC static +void +Jdb_dbinfo::set(Jdb_lines_info *lin, Address phys, size_t size) +{ + Address virt; + + if (!lin) + return; + + if (!phys) + { + lin->get(virt, size); + if (! virt) + return; + + unmap(virt, size); + lin->reset (); + } + + if (!map(phys, size, virt)) + return; + + if (!lin->set(virt, size)) + { + unmap(virt, size); + lin->reset(); + } +} + + +//--------------------------------------------------------------------------- +IMPLEMENTATION[ux]: + +// No special mapping required for UX since all physical memory is mapped + +#include "jdb_lines.h" +#include "jdb_symbol.h" +#include "kmem_alloc.h" +#include "mem_layout.h" +#include "static_init.h" + +STATIC_INITIALIZE(Jdb_dbinfo); + +PUBLIC static +void +Jdb_dbinfo::init() +{ + init_symbols_lines(); +} + +PUBLIC static +void +Jdb_dbinfo::set(Jdb_symbol_info *sym, Address phys, size_t size) +{ + if (!sym) + return; + + if (!phys) + sym->reset(); + else + sym->set(Mem_layout::phys_to_pmem(phys), size); +} + +PUBLIC static +void +Jdb_dbinfo::set(Jdb_lines_info *lin, Address phys, size_t size) +{ + if (!lin) + return; + + if (!phys) + lin->reset(); + else + lin->set(Mem_layout::phys_to_pmem(phys), size); +} diff --git a/kernel/fiasco/src/jdb/jdb_disasm.cpp b/kernel/fiasco/src/jdb/jdb_disasm.cpp new file mode 100644 index 00000000..4a1ff53f --- /dev/null +++ b/kernel/fiasco/src/jdb/jdb_disasm.cpp @@ -0,0 +1,358 @@ +INTERFACE: + +#include "jdb_module.h" +#include "l4_types.h" +#include "types.h" + +class Space; + +// ------------------------------------------------------------------------ +INTERFACE [!jdb_disasm]: + +class Jdb_disasm : public Jdb_module +{ +public: + static bool avail() { return false; } +}; + +// ------------------------------------------------------------------------ +INTERFACE [jdb_disasm]: + +class Jdb_disasm : public Jdb_module +{ +public: + Jdb_disasm() FIASCO_INIT; + static bool avail() { return true; } +private: + static char show_intel_syntax; + static char show_lines; +}; + + +// ------------------------------------------------------------------------ +IMPLEMENTATION [!jdb_disasm]: + +PUBLIC static +Jdb_module::Action_code +Jdb_disasm::show(Address, Space *, int, bool = false) +{ + return Jdb_module::NOTHING; +} + +PUBLIC static +bool +Jdb_disasm::show_disasm_line(int, Address &, int, Space *) +{ + return false; +} + +// ------------------------------------------------------------------------ +IMPLEMENTATION [jdb_disasm]: + +#include +#include +#include + +#include "disasm.h" +#include "jdb.h" +#include "jdb_bp.h" +#include "jdb_input.h" +#include "jdb_lines.h" +#include "jdb_module.h" +#include "jdb_screen.h" +#include "jdb_symbol.h" +#include "kernel_console.h" +#include "keycodes.h" +#include "static_init.h" +#include "task.h" + +char Jdb_disasm::show_intel_syntax; +char Jdb_disasm::show_lines = 2; + +static +bool +Jdb_disasm::disasm_line(char *buffer, int buflen, Address &addr, + int show_symbols, Space *task) +{ + int len; + + if ((len = disasm_bytes(buffer, buflen, addr, task, show_symbols, + show_intel_syntax, &Jdb::peek_task, + &Jdb_symbol::match_addr_to_symbol)) < 0) + { + addr += 1; + return false; + } + + addr += len; + return true; +} + +static +int +Jdb_disasm::at_symbol(Address addr, Space *task) +{ + return Jdb_symbol::match_addr_to_symbol(addr, task) != 0; +} + +static +int +Jdb_disasm::at_line(Address addr, Space *task) +{ + return (show_lines && + Jdb_lines::match_addr_to_line(addr, task, 0, 0, show_lines==2)); +} + +static +Address +Jdb_disasm::disasm_offset(Address &start, int offset, Space *task) +{ + if (offset>0) + { + Address addr = start; + while (offset--) + { + if (!disasm_line(0, 0, addr, 0, task)) + { + start = addr + offset; + return false; + } + if (at_symbol(addr, task) && !offset--) + break; + if (at_line(addr, task) && !offset--) + break; + } + start = addr; + return true; + } + + while (offset++) + { + Address addr = start-64, va_start; + for (;;) + { + va_start = addr; + if (!disasm_line(0, 0, addr, 0, task)) + { + start += offset-1; + return false; + } + if (addr >= start) + break; + } + start = va_start; + if (at_symbol(addr, task) && !offset++) + break; + if (at_line(addr, task) && !offset++) + break; + } + return true; +} + +PUBLIC static +bool +Jdb_disasm::show_disasm_line(int len, Address &addr, + int show_symbols, Space *task) +{ + int clreol = 0; + if (len < 0) + { + len = -len; + clreol = 1; + } + + char line[len]; + if (disasm_line(line, len, addr, show_symbols, task)) + { + if (clreol) + printf("%.*s\033[K\n", len, line); + else + printf("%-*s\n", len, line); + return true; + } + + if (clreol) + puts("........\033[K"); + else + printf("........%*s", len-8, "\n"); + return false; +} + +PUBLIC static +Jdb_module::Action_code +Jdb_disasm::show(Address virt, Space *task, int level, bool do_clear_screen = false) +{ + Address enter_addr = virt; + Space *trans_task = Jdb::translate_task(virt, task); + + for (;;) + { + if (do_clear_screen) + Jdb::clear_screen(); + + Jdb::cursor(); + + Address addr; + Mword i; + for (i=Jdb_screen::height()-1, addr=virt; i>0; i--) + { + const char *symbol; + char str[78], *nl; + char stat_str[4] = { " " }; + + Kconsole::console()->getchar_chance(); + + if ((symbol = Jdb_symbol::match_addr_to_symbol(addr, trans_task))) + { + snprintf(str, sizeof(str)-2, "<%s", symbol); + + // cut symbol at newline + for (nl=str; *nl!='\0' && *nl!='\n'; nl++) + ; + *nl++ = '>'; + *nl++ = ':'; + *nl++ = '\0'; + + printf("%s%s\033[m\033[K\n", Jdb::esc_symbol, str); + if (!--i) + break; + } + + if (show_lines) + { + if (Jdb_lines::match_addr_to_line(addr, trans_task, str, + sizeof(str)-1, show_lines==2)) + { + printf("%s%s\033[m\033[K\n", Jdb::esc_line, str); + if (!--i) + break; + } + } + + // show instruction breakpoint + if (Mword i = Jdb_bp::instruction_bp_at_addr(addr)) + { + stat_str[0] = '#'; + stat_str[1] = '0'+i; + } + + printf("%s" L4_PTR_FMT "%s%s ", + addr == enter_addr ? Jdb::esc_emph : "", addr, stat_str, + addr == enter_addr ? "\033[m" : ""); + show_disasm_line( +#ifdef CONFIG_BIT32 + -64, +#else + -58, +#endif + addr, 1, task); + } + + static char const * const line_mode[] = { "", "[Source]", "[Headers]" }; + static char const * const syntax_mode[] = { "[AT&T]", "[Intel]" }; + Jdb::printf_statline("dis", "=lines mode", + "<" L4_PTR_FMT "> task %-3p %-9s %-7s", + virt, task, line_mode[(int)show_lines], + syntax_mode[(int)show_intel_syntax]); + + Jdb::cursor(Jdb_screen::height(), 6); + switch (int c = Jdb_core::getchar()) + { + case KEY_CURSOR_LEFT: + case 'h': + virt -= 1; + break; + case KEY_CURSOR_RIGHT: + case 'l': + virt += 1; + break; + case KEY_CURSOR_DOWN: + case 'j': + disasm_offset(virt, +1, task); + break; + case KEY_CURSOR_UP: + case 'k': + disasm_offset(virt, -1, task); + break; + case KEY_PAGE_UP: + case 'K': + disasm_offset(virt, -Jdb_screen::height()+2, task); + break; + case KEY_PAGE_DOWN: + case 'J': + disasm_offset(virt, +Jdb_screen::height()-2, task); + break; + case ' ': + show_lines = (show_lines+1) % 3; + break; + case KEY_TAB: + show_intel_syntax ^= 1; + break; + case KEY_CURSOR_HOME: + case 'H': + if (level > 0) + return GO_BACK; + break; + case KEY_ESC: + Jdb::abort_command(); + return NOTHING; + default: + if (Jdb::is_toplevel_cmd(c)) + return NOTHING; + break; + } + } + + return GO_BACK; +} + +PUBLIC +Jdb_module::Action_code +Jdb_disasm::action(int cmd, void *&args, char const *&fmt, int &next_char) +{ + if (cmd == 0) + { + Jdb_module::Action_code code; + + code = Jdb_input_task_addr::action(args, fmt, next_char); + if (code == Jdb_module::NOTHING + && Jdb_input_task_addr::space() != 0) + { + Address addr = Jdb_input_task_addr::addr(); + Space *space = Jdb_input_task_addr::space(); + if (addr == (Address)-1) + addr = Jdb::get_entry_frame(Jdb::current_cpu)->ip(); + return show(addr, space, 0) ? GO_BACK : NOTHING; + } + + return code; + } + + return NOTHING; +} + +PUBLIC +Jdb_module::Cmd const * +Jdb_disasm::cmds() const +{ + static Cmd cs[] = + { + { 0, "u", "u", "%C", + "u[t]\tdisassemble bytes of given/current task addr", + &Jdb_input_task_addr::first_char } + }; + + return cs; +} + +PUBLIC +int +Jdb_disasm::num_cmds() const +{ return 1; } + +IMPLEMENT +Jdb_disasm::Jdb_disasm() + : Jdb_module("INFO") +{} + +static Jdb_disasm jdb_disasm INIT_PRIORITY(JDB_MODULE_INIT_PRIO); diff --git a/kernel/fiasco/src/jdb/jdb_dump.cpp b/kernel/fiasco/src/jdb/jdb_dump.cpp new file mode 100644 index 00000000..049e1c12 --- /dev/null +++ b/kernel/fiasco/src/jdb/jdb_dump.cpp @@ -0,0 +1,425 @@ +INTERFACE: + +#include "types.h" +#include "l4_types.h" + +class Space; + + +IMPLEMENTATION: + +#include +#include + +#include "config.h" +#include "jdb.h" +#include "jdb_disasm.h" +#include "jdb_table.h" +#include "jdb_input.h" +#include "jdb_module.h" +#include "jdb_screen.h" +#include "jdb_symbol.h" +#include "kernel_console.h" +#include "keycodes.h" +#include "simpleio.h" +#include "static_init.h" +#include "types.h" +#include "task.h" + +class Jdb_dump : public Jdb_module, public Jdb_table +{ +public: + Jdb_dump() FIASCO_INIT; + unsigned long cols() const { return Jdb_screen::cols(); } + unsigned long rows() const { return Jdb_screen::rows(); } + void draw_entry(unsigned long row, unsigned long col); + void print_statline(); + +private: + enum + { + B_MODE = 'b', // byte + C_MODE = 'c', // char + D_MODE = 'd', // word + }; + + static const unsigned elb = sizeof(Mword); + static char show_adapter_memory; + static Address highlight_start, highlight_end; + + int level; + Space *task; + char dump_type; + static Address virt_addr; +}; + +char Jdb_dump::show_adapter_memory; +Address Jdb_dump::highlight_start; +Address Jdb_dump::highlight_end; +Address Jdb_dump::virt_addr; + +// if we have the APIC module +extern int ignore_invalid_apic_reg_access + __attribute__((weak)); + +PRIVATE inline +Address +Jdb_dump::virt(unsigned long row, unsigned long col) +{ + return (col-1) * elb + row * (cols()-1) * elb; +} + +PUBLIC +unsigned +Jdb_dump::col_width(unsigned col) const +{ + if (col == 0) + return Jdb_screen::Col_head_size; + if (dump_type == C_MODE) + return Jdb_screen::Mword_size_cmode; + else + return Jdb_screen::Mword_size_bmode; +} + +PUBLIC +void +Jdb_dump::print_statline(unsigned long row, unsigned long col) +{ + Jdb::printf_statline("dump", + (dump_type==D_MODE) + ? "e=edit u=disasm D=dump =mode =goto addr" + : "=mode", + task ? "%c<" L4_PTR_FMT "> task %p" : "%c<" L4_PTR_FMT "> physical", + dump_type, virt(row,col), task); +} + +IMPLEMENT +void +Jdb_dump::draw_entry(unsigned long row, unsigned long col) +{ + if (col == 0) + { + printf("%0*lx", col_width(col), row * (cols()-1) * elb); + return; + } + + Address entry = virt(row, col); + + // prevent apic from getting confused by invalid register accesses + if (&ignore_invalid_apic_reg_access) + ignore_invalid_apic_reg_access = 1; + + Mword dummy; + bool mapped = Jdb::peek((Mword*)entry, task, dummy); + bool ram = !Jdb::is_adapter_memory(entry, task); + + if (mapped) + { + if (ram || show_adapter_memory) + { + Mword mword; + Jdb::peek((Mword*)entry, task, mword); + + if (dump_type==D_MODE) + { + if (mword == 0) + printf("%*lu", Jdb_screen::Mword_size_bmode, mword); + else if (mword == (Mword)~0UL) + printf("%*d", Jdb_screen::Mword_size_bmode, -1); + else + { + if (highlight_start <= mword && mword <= highlight_end) + printf("%s" L4_PTR_FMT "\033[m", Jdb::esc_emph, mword); + else + printf(L4_PTR_FMT, mword); + } + } + else if (dump_type==B_MODE) + { + for (Mword u=0; u> (8*u)) & 0xff; + printf("%02x", b); + } + } + else if (dump_type==C_MODE) + { + for (Mword u=0; u> (8*u)) & 0xff; + putchar(b>=32 && b<=126 ? b : '.'); + } + } + } + else // is_adapter_memory + { + if (dump_type == C_MODE) + printf("%.*s", Jdb_screen::Mword_size_cmode, Jdb_screen::Mword_adapter); + else + printf("%.*s", Jdb_screen::Mword_size_bmode, Jdb_screen::Mword_adapter); + } + } + else // !mapped + { + if (dump_type == C_MODE) + printf("%.*s", Jdb_screen::Mword_size_cmode, Jdb_screen::Mword_not_mapped); + else + printf("%.*s", Jdb_screen::Mword_size_bmode, Jdb_screen::Mword_not_mapped); + } + + if (&ignore_invalid_apic_reg_access) + ignore_invalid_apic_reg_access = 0; +} + +PUBLIC +Jdb_module::Action_code +Jdb_dump::dump(Address virt, Space *task, int level) +{ //printf("DU: %p %lx\n", task, virt); Jdb::getchar(); + int old_l = this->level; + this->level = level; + this->task = task; + dump_type = D_MODE; + if (!level) + Jdb::clear_screen(); + + unsigned long row = virt / ((cols()-1) * elb); + unsigned long col = (virt % ((cols()-1) * elb)) / elb + 1; + bool r = show(row, col); + this->level = old_l; + return r ? EXTRA_INPUT : NOTHING; +} + +PUBLIC +bool +Jdb_dump::edit_entry(unsigned long row, unsigned long col, unsigned cx, unsigned cy) +{ + Address entry = virt(row,col); + + Mword mword; + if (!Jdb::peek((Mword*)entry, task, mword)) + return false; + + putstr(Jdb_screen::Mword_blank); + Jdb::printf_statline("dump", "=commit change", + "edit <" L4_PTR_FMT "> = " L4_PTR_FMT, entry, mword); + + Jdb::cursor(cy, cx); + Mword new_mword; + if (Jdb_input::get_mword(&new_mword, sizeof(Mword)*2, 16)) + Jdb::poke((Mword*)entry, task, new_mword); + + return true; // redraw +} + +PUBLIC +unsigned +Jdb_dump::key_pressed(int c, unsigned long &row, unsigned long &col) +{ + switch (c) + { + default: + return Nothing; + + case KEY_CURSOR_HOME: // return to previous or go home + if (level == 0) + { + Address v = virt(row, col); + if (v == 0) + return Handled; + + if ((v & ~Config::PAGE_MASK) == 0) + row -= Config::PAGE_SIZE / 32; + else + { + col = 1; + row = (v & Config::PAGE_MASK) / 32; + } + return Redraw; + } + return Back; + + case KEY_CURSOR_END: + { + Address v = virt(row, col); + if ((v & ~Config::PAGE_MASK) >> 2 == 0x3ff) + row += Config::PAGE_SIZE / 32; + else + { + col = Jdb_screen::cols() - 1; + row = ((v & Config::PAGE_MASK) + Config::PAGE_SIZE - 4) / 32; + } + } + return Redraw; + + case 'D': + if (Kconsole::console()->find_console(Console::GZIP)) + { + Address low_addr, high_addr; + + Jdb::cursor(Jdb_screen::height(), 27); + putchar('['); + Jdb::clear_to_eol(); + + if (Jdb_input::get_mword(&low_addr, sizeof(Mword)*2, 16)) + { + putchar('-'); + if (Jdb_input::get_mword(&high_addr, sizeof(Mword)*2, 16)) + { + unsigned l_row = low_addr / ((cols()-1) * elb); + unsigned l_col = (low_addr % ((cols()-1) * elb)) / elb; + unsigned h_row = high_addr / ((cols()-1) * elb); + + if (low_addr <= high_addr) + { + Mword lines = h_row - l_row; + if (lines < 1) + lines = 1; + // enable gzip console + Kconsole::console()-> + start_exclusive(Console::GZIP); + char old_mode = dump_type; + dump_type = D_MODE; + draw_table(l_row, l_col, lines, cols()); + dump_type = old_mode; + Kconsole::console()-> + end_exclusive(Console::GZIP); + } + } + } + return Redraw; + } + return Handled; + + case ' ': // change viewing mode + switch (dump_type) + { + case D_MODE: dump_type=B_MODE; return Redraw; + case B_MODE: dump_type=C_MODE; return Redraw; + case C_MODE: dump_type=D_MODE; return Redraw; + } + break; + + case KEY_TAB: + show_adapter_memory = !show_adapter_memory; + return Redraw; + + case KEY_RETURN: // goto address under cursor + if (level<=7 && dump_type==D_MODE) + { + Address virt1; + if (Jdb::peek((Address*)virt(row,col), task, virt1)) + { + if (!dump(virt1, task, level +1)) + return Exit; + return Redraw; + } + } + break; + + case 'u': // disassemble using address the cursor points to + if (Jdb_disasm::avail() && level<=7 && dump_type == D_MODE) + { + Address virt1; + if (Jdb::peek((Address*)virt(row,col), task, virt1)) + { + Jdb::printf_statline("dump", "=disassemble here", + "u[address=" L4_PTR_FMT " task=%p] ", + virt1, task); + int c1 = Jdb_core::getchar(); + if (c1 != KEY_RETURN && c1 != ' ') + { + Jdb::printf_statline("dump", 0, "u"); + Jdb::execute_command("u", c1); + return Exit; + } + + return Jdb_disasm::show(virt1, task, level+1, 1) + ? Redraw + : Exit; + } + } + return Handled; + + case 'e': // poke memory + if (dump_type == D_MODE) + return Edit; + break; + + case 'c': // set boundaries for highlighting memory contents + if (level <= 7 && dump_type == D_MODE) + { + Address a; + if (Jdb::peek((Address*)virt(row,col), task, a)) + { + const Address pm = 0x100000; + highlight_start = (a > pm) ? a - pm : 0; + highlight_end = (a <= ~1UL - pm) ? a + pm : ~1UL; + return Redraw; + } + } + break; + + case 'r': + return Redraw; + } + + return Handled; + +} + +PUBLIC +Jdb_module::Action_code +Jdb_dump::action(int cmd, void *&args, char const *&fmt, int &next_char) +{ + if (cmd == 0) + { + Jdb_module::Action_code code; + + code = Jdb_input_task_addr::action(args, fmt, next_char); + if (code == Jdb_module::NOTHING) + { + Address addr = Jdb_input_task_addr::addr(); + Space *space = Jdb_input_task_addr::space(); + if (addr == (Address)~0UL) + addr = 0; + + return dump(addr, space, 0); + } + + if (code != ERROR) + return code; + } + + return NOTHING; +} + +PUBLIC +Jdb_module::Cmd const * +Jdb_dump::cmds() const +{ + static Cmd cs[] = + { + { 0, "d", "dump", "%C", + "d[t|p]\tdump memory of given/current task at , or physical", + &Jdb_input_task_addr::first_char }, + }; + return cs; +} + +PUBLIC +int +Jdb_dump::num_cmds() const +{ + return 1; +} + +IMPLEMENT +Jdb_dump::Jdb_dump() + : Jdb_module("INFO"), dump_type(D_MODE) +{} + +static Jdb_dump jdb_dump INIT_PRIORITY(JDB_MODULE_INIT_PRIO); + +int +jdb_dump_addr_task(Address addr, Space *task, int level) +{ return jdb_dump.dump(addr, task, level); } diff --git a/kernel/fiasco/src/jdb/jdb_exit_module.cpp b/kernel/fiasco/src/jdb/jdb_exit_module.cpp new file mode 100644 index 00000000..0e8a9858 --- /dev/null +++ b/kernel/fiasco/src/jdb/jdb_exit_module.cpp @@ -0,0 +1,107 @@ +IMPLEMENTATION: + +#include +#include "simpleio.h" + +#include "jdb.h" +#include "jdb_module.h" +#include "jdb_screen.h" +#include "kernel_console.h" +#include "static_init.h" +#include "terminate.h" +#include "types.h" + +/** + * Private 'exit' module. + * + * This module handles the 'exit' or '^' command that + * makes a call to exit() and virtually reboots the system. + */ +class Jdb_exit_module : public Jdb_module +{ +public: + Jdb_exit_module() FIASCO_INIT; +}; + +static Jdb_exit_module jdb_exit_module INIT_PRIORITY(JDB_MODULE_INIT_PRIO); + +PUBLIC +Jdb_module::Action_code +Jdb_exit_module::action (int cmd, void *&, char const *&, int &) +{ + if (cmd != 0) + return NOTHING; + + // re-enable output of all consoles but GZIP and DEBUG + Kconsole::console()->change_state(0, Console::GZIP | Console::DEBUG, + ~0UL, Console::OUTENABLED); + // re-enable input of all consoles but PUSH and DEBUG + Kconsole::console()->change_state(0, Console::PUSH | Console::DEBUG, + ~0UL, Console::INENABLED); + + Jdb::screen_scroll(1, 127); + Jdb::blink_cursor(Jdb_screen::height(), 1); + Jdb::cursor(127, 1); + vmx_off(); + terminate(1); + return LEAVE; +} + +PUBLIC +int +Jdb_exit_module::num_cmds() const +{ + return 1; +} + +PUBLIC +Jdb_module::Cmd const * +Jdb_exit_module::cmds() const +{ + static Cmd cs[] = + { { 0, "^", "exit", "", "^\treboot the system", 0 } }; + + return cs; +} + +IMPLEMENT +Jdb_exit_module::Jdb_exit_module() + : Jdb_module("GENERAL") +{} + +// ------------------------------------------------------------------------ +IMPLEMENTATION [vmx]: + +// VT might need some special treatment, switching VT off seems to be +// necessary to do a (keyboard) reset + +#include "cpu.h" + +PRIVATE static +void +Jdb_exit_module::do_vmxoff(unsigned, void *) +{ + asm volatile("vmxoff"); +} + +PRIVATE static +void +Jdb_exit_module::remote_vmxoff(unsigned cpu) +{ + Jdb::remote_work(cpu, do_vmxoff, 0); +} + +PRIVATE +void +Jdb_exit_module::vmx_off() const +{ + if (Cpu::boot_cpu()->vmx()) + Jdb::foreach_cpu(&remote_vmxoff); +} + +// ------------------------------------------------------------------------ +IMPLEMENTATION [!vmx]: + +PRIVATE +void +Jdb_exit_module::vmx_off() const {} diff --git a/kernel/fiasco/src/jdb/jdb_factory.cpp b/kernel/fiasco/src/jdb/jdb_factory.cpp new file mode 100644 index 00000000..741487d0 --- /dev/null +++ b/kernel/fiasco/src/jdb/jdb_factory.cpp @@ -0,0 +1,53 @@ +IMPLEMENTATION: + +#include +#include +#include + +#include "jdb.h" +#include "jdb_core.h" +#include "jdb_module.h" +#include "jdb_screen.h" +#include "jdb_kobject.h" +#include "kernel_console.h" +#include "keycodes.h" +#include "factory.h" +#include "simpleio.h" +#include "static_init.h" + +class Jdb_factory : public Jdb_kobject_handler +{ +public: + Jdb_factory() FIASCO_INIT; +}; + +IMPLEMENT +Jdb_factory::Jdb_factory() + : Jdb_kobject_handler(Factory::static_kobj_type) +{ + Jdb_kobject::module()->register_handler(this); +} + +PUBLIC +bool +Jdb_factory::show_kobject(Kobject_common *, int ) +{ + return true; +} + +PUBLIC +char const * +Jdb_factory::kobject_type() const +{ + return JDB_ANSI_COLOR(yellow) "Factory" JDB_ANSI_COLOR(default); +} + +PUBLIC +int +Jdb_factory::show_kobject_short(char *buf, int max, Kobject_common *o) +{ + Factory *t = Kobject::dcast(o); + return snprintf(buf, max, " c=%ld l=%ld", t->current(), t->limit()); +} + +static Jdb_factory jdb_factory INIT_PRIORITY(JDB_MODULE_INIT_PRIO); diff --git a/kernel/fiasco/src/jdb/jdb_gzip.cpp b/kernel/fiasco/src/jdb/jdb_gzip.cpp new file mode 100644 index 00000000..1e2e22e8 --- /dev/null +++ b/kernel/fiasco/src/jdb/jdb_gzip.cpp @@ -0,0 +1,110 @@ +IMPLEMENTATION: + +#include +#include + +#include "config.h" +#include "console.h" +#include "gzip.h" +#include "kernel_console.h" +#include "kmem_alloc.h" +#include "panic.h" +#include "static_init.h" + +class Jdb_gzip : public Console +{ + static const unsigned heap_pages = 28; + char active; + char init_done; + static Console *uart; +}; + +Console *Jdb_gzip::uart; + +Jdb_gzip::Jdb_gzip() +{ + _state = Console::DISABLED_INIT; + char *heap = (char*)Kmem_alloc::allocator()-> + unaligned_alloc(heap_pages*Config::PAGE_SIZE); + if (!heap) + panic("No memory for gzip heap"); + gz_init(heap, heap_pages * Config::PAGE_SIZE, raw_write); +} + +static void +Jdb_gzip::raw_write(const char *s, size_t len) +{ + if (uart) + uart->write(s, len); +} + +PUBLIC inline NOEXPORT +void +Jdb_gzip::enable() +{ + if (!init_done) + { + uart = Kconsole::console()->find_console(Console::UART); + init_done = 1; + } + + gz_open("jdb.gz"); + active = 1; +} + +PUBLIC inline NOEXPORT +void +Jdb_gzip::disable() +{ + if (active) + { + gz_close(); + active = 0; + } +} + +PUBLIC void +Jdb_gzip::state(Mword new_state) +{ + if ((_state ^ new_state) & OUTENABLED) + { + if (new_state & OUTENABLED) + enable(); + else + disable(); + } + + _state = new_state; +} + +PUBLIC +int +Jdb_gzip::write(char const *str, size_t len) +{ + gz_write(str, len); + return len; +} + +PUBLIC static +Console* +Jdb_gzip::console() +{ + static Jdb_gzip c; + return &c; +} + +PUBLIC +Mword +Jdb_gzip::get_attributes() const +{ + return GZIP | OUT; +} + +PUBLIC static FIASCO_INIT +void +Jdb_gzip::init() +{ + Kconsole::console()->register_console(console()); +} + +STATIC_INITIALIZE(Jdb_gzip); diff --git a/kernel/fiasco/src/jdb/jdb_halt_thread.cpp b/kernel/fiasco/src/jdb/jdb_halt_thread.cpp new file mode 100644 index 00000000..2160f0eb --- /dev/null +++ b/kernel/fiasco/src/jdb/jdb_halt_thread.cpp @@ -0,0 +1,66 @@ +IMPLEMENTATION: + +#include +#include "entry_frame.h" +#include "gdt.h" +#include "jdb_module.h" +#include "jdb_kobject.h" +#include "static_init.h" +#include "thread_object.h" + +class Jdb_halt_thread : public Jdb_module +{ +public: + Jdb_halt_thread() FIASCO_INIT; +private: + static Kobject *threadid; +}; + +Kobject *Jdb_halt_thread::threadid; + +PUBLIC +Jdb_module::Action_code +Jdb_halt_thread::action(int cmd, void *&, char const *&, int &) +{ + if (cmd != 0) + return NOTHING; + + Thread *t = Kobject::dcast(threadid); + + if (!t) + return NOTHING; + + t->regs()->cs(Gdt::gdt_code_kernel | Gdt::Selector_kernel); + t->regs()->ip(reinterpret_cast
(&Thread::halt_current)); + t->regs()->flags(0); // disable interrupts + putchar('\n'); + + return NOTHING; +} + +PUBLIC +Jdb_module::Cmd const * +Jdb_halt_thread::cmds() const +{ + static Cmd cs[] = + { + { 0, "H", "halt", "%q", "H\thalt a specific thread", + &threadid }, + }; + + return cs; +} + +PUBLIC +int +Jdb_halt_thread::num_cmds() const +{ + return 1; +} + +IMPLEMENT +Jdb_halt_thread::Jdb_halt_thread() + : Jdb_module("MISC") +{} + +static Jdb_halt_thread jdb_halt_thread INIT_PRIORITY(JDB_MODULE_INIT_PRIO); diff --git a/kernel/fiasco/src/jdb/jdb_handler_queue.cpp b/kernel/fiasco/src/jdb/jdb_handler_queue.cpp new file mode 100644 index 00000000..c093aeb0 --- /dev/null +++ b/kernel/fiasco/src/jdb/jdb_handler_queue.cpp @@ -0,0 +1,46 @@ +INTERFACE: + +// XXX If there is a constructor needed for this class make sure that it is +// called with a priority higher than JDB_MODULE_INIT_PRIO! + +class Jdb_handler +{ + friend class Jdb_handler_queue; + +public: + Jdb_handler( void (*handler)() ) : handler(handler), next(0) {} + void execute() { handler(); } + +private: + void (*handler)(); + Jdb_handler *next; +}; + +class Jdb_handler_queue +{ +private: + Jdb_handler *first; +}; + +IMPLEMENTATION: + +PUBLIC inline +void +Jdb_handler_queue::add (Jdb_handler *handler) +{ + handler->next = first; + first = handler; +} + +PUBLIC +void +Jdb_handler_queue::execute () const +{ + Jdb_handler *h = first; + while(h) + { + h->execute(); + h = h->next; + } +} + diff --git a/kernel/fiasco/src/jdb/jdb_idle_stats.cpp b/kernel/fiasco/src/jdb/jdb_idle_stats.cpp new file mode 100644 index 00000000..a05b99d4 --- /dev/null +++ b/kernel/fiasco/src/jdb/jdb_idle_stats.cpp @@ -0,0 +1,55 @@ +IMPLEMENTATION [tickless_idle]: + +#include +#include +#include + +#include "jdb.h" +#include "jdb_module.h" +#include "kernel_thread.h" +#include "static_init.h" + + +class Jdb_idle_stats : public Jdb_module +{ +public: + Jdb_idle_stats() FIASCO_INIT; +}; + +IMPLEMENT +Jdb_idle_stats::Jdb_idle_stats() : Jdb_module("INFO") {} + +PUBLIC +Jdb_module::Action_code +Jdb_idle_stats::action(int, void *&, char const *&, int &) +{ + printf("\nIDLE STATISTICS --------------------------\n"); + for (unsigned i = 0; i < Config::Max_num_cpus; ++i) + { + if (!Cpu::online(i)) + continue; + + printf("CPU[%2u]: %lu times idle, %lu times deep sleep\n", i, + Kernel_thread::_idle_counter.cpu(i), + Kernel_thread::_deep_idle_counter.cpu(i)); + } + return NOTHING; +} + +PUBLIC +Jdb_module::Cmd const * +Jdb_idle_stats::cmds() const +{ + static Cmd cs[] = + { + { 0, 0, "idle", "", "idle\tshow IDLE statistics", 0}, + }; + return cs; +} + +PUBLIC +int +Jdb_idle_stats::num_cmds() const +{ return 1; } + +static Jdb_idle_stats jdb_idle_stats INIT_PRIORITY(JDB_MODULE_INIT_PRIO); diff --git a/kernel/fiasco/src/jdb/jdb_input.cpp b/kernel/fiasco/src/jdb/jdb_input.cpp new file mode 100644 index 00000000..0fe8d7d3 --- /dev/null +++ b/kernel/fiasco/src/jdb/jdb_input.cpp @@ -0,0 +1,238 @@ +INTERFACE: + +#include "jdb_module.h" +#include "types.h" +#include "l4_types.h" + +class Jdb_input +{ +}; + +class Task; +class Space; +class Kobject; + +class Jdb_input_task_addr +{ +public: + static char first_char; + static char first_char_have_task; +private: + static Kobject *_task; + static Space *_space; + static Address _addr; +public: + typedef struct + { + char str[32]; + Jdb_module::Gotkey *gotkey; + } Symbol; + static Symbol symbol; +}; + + +IMPLEMENTATION: + +#include +#include +#include +#include "kernel_console.h" +#include "keycodes.h" +#include "jdb.h" +#include "jdb_kobject.h" +#include "jdb_symbol.h" +#include "simpleio.h" +#include "task.h" + + +char Jdb_input_task_addr::first_char; +char Jdb_input_task_addr::first_char_have_task; +Kobject *Jdb_input_task_addr::_task; +Space *Jdb_input_task_addr::_space; +Address Jdb_input_task_addr::_addr; +Jdb_input_task_addr::Symbol Jdb_input_task_addr::symbol; + + +static +void +Jdb_input_task_addr::gotkey_complete_symbol(char *&str, int maxlen, int c) +{ (void)str; (void)maxlen; + if (c == KEY_TAB) + printf("XXX\n"); //Jdb_symbol::complete_symbol(str, maxlen, task); +} + +PUBLIC static +Task * +Jdb_input_task_addr::task() +{ return Kobject::dcast(_task); } + +PUBLIC static +Space * +Jdb_input_task_addr::space() +{ return _space; } + +PUBLIC static +Address +Jdb_input_task_addr::addr() +{ return _addr; } + +PUBLIC static +Jdb_module::Action_code +Jdb_input_task_addr::action(void *&args, char const *&fmt, int &next_char) +{ + if (args == &first_char) + { + // initialize + // so _task is only valid if it is explicitly set + _task = 0; + _space = Jdb::get_current_space(); + _addr = (Address)-1; + symbol.str[0] = '\0'; + symbol.gotkey = gotkey_complete_symbol; + } + + if (args == &first_char_have_task) + first_char = first_char_have_task; + + if (args == &first_char && first_char == 't') + { + args = &_task; + fmt = strcmp(fmt, " addr=%C") ? " task=%q" : " \b\b\b\b\b\btask=%q"; + return Jdb_module::EXTRA_INPUT; + } + else if (args == &_task) + { + _space = Kobject::dcast(_task); + + if (_task && !space()) + { + _task = 0; + puts(" invalid task"); + return Jdb_module::ERROR; + } + + args = &first_char_have_task; + fmt = " addr=%C"; + return Jdb_module::EXTRA_INPUT; + } + else if (first_char == 'p') + { + _task = 0; + _space = 0; + putstr(" [phys-mem]"); + + args = &first_char_have_task; + fmt = " addr=%C"; + return Jdb_module::EXTRA_INPUT; + } + else if (args == &first_char || args == &first_char_have_task) + { + if (first_char == 's') + { + args = &symbol; + fmt = strcmp(fmt, " addr=%C") ? " symbol=%32S" + : " \b\b\b\b\b\bsymbol=%32S"; + return Jdb_module::EXTRA_INPUT; + } + else if (isxdigit(first_char)) + { + next_char = first_char; + args = &_addr; + fmt = L4_ADDR_INPUT_FMT; + return Jdb_module::EXTRA_INPUT_WITH_NEXTCHAR; + } + else if (first_char != KEY_RETURN && first_char != ' ') + { + fmt = "%C"; + return Jdb_module::EXTRA_INPUT; + } + } + else if (args == &symbol) + { +#if 0 + // XXX: Fix symbols + Address sym_addr; + bool instr = strlen(symbol.str)>=sizeof(symbol.str)-1; + if ((sym_addr = Jdb_symbol::match_symbol_to_addr(symbol.str, + instr, task))) + _addr = sym_addr; + else + { + _addr = (Address)-1; + puts(" not found"); + return Jdb_module::ERROR; + } +#endif + } + + return Jdb_module::NOTHING; +} + +PUBLIC static +int +Jdb_input::get_mword(Mword *mword, int digits, int base, int first_char = 0) +{ + Mword val=0; + + for(int digit=0; digitgetchar(); + switch(c) + { + case 'a': case 'b': case 'c': + case 'd': case 'e': case 'f': + if (base == 16) + v -= 'a' - '9' - 1; + else + continue; + case '0': case '1': case '2': + case '3': case '4': case '5': + case '6': case '7': case '8': + case '9': + val = (val * base) + (v - '0'); + digit++; + putchar(c); + break; + case KEY_BACKSPACE: + if (digit) + { + putstr("\b \b"); + digit--; + val /= base; + } + break; + case 'x': + // If last digit was 0, delete it. This makes it easier to cut + // 'n paste hex values like 0x12345678 into the serial terminal + if (base == 16 && digit && ((val & 0x10) == 0)) + { + putstr("\b \b"); + digit--; + val /= base; + } + break; + case ' ': + case KEY_RETURN: + if (digit) + { + *mword = val; + return true; + } + *mword = 0; + return false; + case KEY_ESC: + return 0; + } + } + *mword = val; + return 1; +} + diff --git a/kernel/fiasco/src/jdb/jdb_io_apic.cpp b/kernel/fiasco/src/jdb/jdb_io_apic.cpp new file mode 100644 index 00000000..fbc01764 --- /dev/null +++ b/kernel/fiasco/src/jdb/jdb_io_apic.cpp @@ -0,0 +1,129 @@ +IMPLEMENTATION: + +#include +#include "simpleio.h" + +#include "apic.h" +#include "io_apic.h" +#include "jdb.h" +#include "jdb_module.h" +#include "jdb_screen.h" +#include "static_init.h" +#include "types.h" + + +/** + * Private 'exit' module. + * + * This module handles the 'exit' or '^' command that + * makes a call to exit() and virtually reboots the system. + */ +class Jdb_io_apic_module : public Jdb_module +{ +public: + Jdb_io_apic_module() FIASCO_INIT; +}; + +static Jdb_io_apic_module jdb_io_apic_module INIT_PRIORITY(JDB_MODULE_INIT_PRIO); + +PRIVATE static +void +Jdb_io_apic_module::print_lapic(unsigned cpu, void *) +{ + printf("\nLocal APIC [%u, %08x]: tpr=%2x ppr=%2x\n", cpu, Apic::get_id(), Apic::tpr(), + Apic::reg_read(0xa0)); + printf(" Running: tpr=%02x\n", Jdb::apic_tpr.cpu(cpu)); + + unsigned const regs[] = { 0x200, 0x100, 0x180 }; + char const *const regn[] = { "IRR", "ISR", "TMR" }; + for (unsigned r = 0; r < 3; ++r) + { + printf(" %s:", regn[r]); + for (int i = 3; i >= 0; --i) + { + unsigned long v = Apic::reg_read(regs[r] + i * 0x10); + printf(" %08lx", v); + } + puts(""); + } +} + +PRIVATE static +void +Jdb_io_apic_module::remote_print_lapic(unsigned cpu) +{ + Jdb::remote_work(cpu, print_lapic, 0); +} + +PUBLIC +Jdb_module::Action_code +Jdb_io_apic_module::action (int cmd, void *&, char const *&, int &) +{ + if (cmd!=0) + return NOTHING; + + if (!Io_apic::active()) + { + printf("\nIO APIC not present!\n"); + return NOTHING; + } + printf("\nState of IO APIC\n"); + for (Io_apic *a = Io_apic::_first; a; a = a->_next) + a->dump(); + + // print global LAPIC state + unsigned khz; + char apic_state[80]; + int apic_disabled; + strcpy (apic_state, "N/A"); + if ((apic_disabled = Apic::test_present_but_disabled())) + strcpy (apic_state, "disabled by BIOS"); + if ((khz = Apic::get_frequency_khz())) + { + unsigned mhz = khz / 1000; + khz -= mhz * 1000; + snprintf(apic_state, sizeof(apic_state), "yes (%d.%03d MHz)" + "\n local APIC spurious interrupts/bug/error: %d/%d/%d", + mhz, khz, + apic_spurious_interrupt_cnt, + apic_spurious_interrupt_bug_cnt, + apic_error_cnt); + } + printf("\nLocal APIC (general): %s" + "\nWatchdog: %s" + "\n", + apic_state, + Config::watchdog + ? "active" + : Apic::is_present() + ? "disabled" + : apic_disabled + ? "not supported (Local APIC disabled)" + : "not supported (no Local APIC)" + ); + Jdb::foreach_cpu(&remote_print_lapic); + + return NOTHING; +} + +PUBLIC +int +Jdb_io_apic_module::num_cmds() const +{ + return 1; +} + +PUBLIC +Jdb_module::Cmd const * +Jdb_io_apic_module::cmds() const +{ + static Cmd cs[] = + { { 0, "A", "apic", "", "apic\tdump state of IOAPIC", (void*)0 } }; + + return cs; +} + +IMPLEMENT +Jdb_io_apic_module::Jdb_io_apic_module() + : Jdb_module("INFO") +{} diff --git a/kernel/fiasco/src/jdb/jdb_ipc_gate.cpp b/kernel/fiasco/src/jdb/jdb_ipc_gate.cpp new file mode 100644 index 00000000..bfab4a40 --- /dev/null +++ b/kernel/fiasco/src/jdb/jdb_ipc_gate.cpp @@ -0,0 +1,63 @@ +IMPLEMENTATION: + +#include +#include +#include + +#include "jdb.h" +#include "jdb_core.h" +#include "jdb_module.h" +#include "jdb_screen.h" +#include "jdb_kobject.h" +#include "simpleio.h" +#include "static_init.h" +#include "ipc_gate.h" + +class Jdb_ipc_gate : public Jdb_kobject_handler +{ +public: + Jdb_ipc_gate() FIASCO_INIT; +}; + +IMPLEMENT +Jdb_ipc_gate::Jdb_ipc_gate() + : Jdb_kobject_handler(Ipc_gate_obj::static_kobj_type) +{ + Jdb_kobject::module()->register_handler(this); +} + +PUBLIC +Kobject_common * +Jdb_ipc_gate::follow_link(Kobject_common *o) +{ + Ipc_gate_obj *g = Kobject::dcast(Kobject::from_dbg(o->dbg_info())); + return g->thread() ? Kobject::from_dbg(g->thread()->dbg_info()) : o; +} + +PUBLIC +bool +Jdb_ipc_gate::show_kobject(Kobject_common *, int) +{ return true; } + +PUBLIC +int +Jdb_ipc_gate::show_kobject_short(char *buf, int max, Kobject_common *o) +{ + Ipc_gate_obj *g = Kobject::dcast(Kobject::from_dbg(o->dbg_info())); + if (!g) + return 0; + + return snprintf(buf, max, " L=%s%08lx\033[0m D=%lx", + (g->id() & 3) ? JDB_ANSI_COLOR(lightcyan) : "", + g->id(), g->thread() ? g->thread()->dbg_info()->dbg_id() : 0); +} + +PUBLIC +char const * +Jdb_ipc_gate::kobject_type() const +{ + return JDB_ANSI_COLOR(magenta) "Gate" JDB_ANSI_COLOR(default); +} + +static Jdb_ipc_gate jdb_space INIT_PRIORITY(JDB_MODULE_INIT_PRIO); + diff --git a/kernel/fiasco/src/jdb/jdb_ipi.cpp b/kernel/fiasco/src/jdb/jdb_ipi.cpp new file mode 100644 index 00000000..94f3d036 --- /dev/null +++ b/kernel/fiasco/src/jdb/jdb_ipi.cpp @@ -0,0 +1,58 @@ +IMPLEMENTATION [mp]: + +#include +#include "simpleio.h" + +#include "jdb.h" +#include "jdb_module.h" +#include "static_init.h" +#include "types.h" + +class Jdb_ipi_module : public Jdb_module +{ +public: + Jdb_ipi_module() FIASCO_INIT; +}; + +static Jdb_ipi_module jdb_ipi_module INIT_PRIORITY(JDB_MODULE_INIT_PRIO); + +PRIVATE static +void +Jdb_ipi_module::print_info(unsigned cpu) +{ + Ipi &ipi = Ipi::_ipi.cpu(cpu); + printf("CPU%02u sent/rcvd: %ld/%ld\n", + cpu, ipi._stat_sent, ipi._stat_received); +} + +PUBLIC +Jdb_module::Action_code +Jdb_ipi_module::action(int cmd, void *&, char const *&, int &) +{ + if (cmd) + return NOTHING; + + Jdb::foreach_cpu(&print_info); + + return NOTHING; +} + +PUBLIC +int +Jdb_ipi_module::num_cmds() const +{ return 1; } + +PUBLIC +Jdb_module::Cmd const * +Jdb_ipi_module::cmds() const +{ + static Cmd cs[] = + { { 0, "", "ipi", "", "ipi\tIPI information", 0 } }; + + return cs; +} + +IMPLEMENT +Jdb_ipi_module::Jdb_ipi_module() + : Jdb_module("INFO") +{} diff --git a/kernel/fiasco/src/jdb/jdb_jaf_module.cpp b/kernel/fiasco/src/jdb/jdb_jaf_module.cpp new file mode 100644 index 00000000..461dc735 --- /dev/null +++ b/kernel/fiasco/src/jdb/jdb_jaf_module.cpp @@ -0,0 +1,84 @@ +IMPLEMENTATION: + +#include + +#include "jdb.h" +#include "jdb_module.h" +#include "static_init.h" +#include "types.h" +#include "cpu.h" +#include "globals.h" +#include "context.h" + +/** + * Jdb-bsod module + * + * This module makes fun. + */ +class Bsod_m + : public Jdb_module +{ +public: + Bsod_m() FIASCO_INIT; +}; + +static Bsod_m bsod_m INIT_PRIORITY(JDB_MODULE_INIT_PRIO); + +IMPLEMENT +Bsod_m::Bsod_m() + : Jdb_module("GENERAL") +{} + +PUBLIC +Jdb_module::Action_code Bsod_m::action( int, void *&, char const *& ) +{ + const char *bsod_unstable = + "\033[H\033[44;37;1m\033[2J\n\n\n\n\n\n" + " \033[47;34;1m WARNING! \033[44;37;1m\n\n" + " The system is either busy or has become unstable. You can wait and\n" + " see if it becomes available again, or you can restart your computer.\n\n" + " * Press any key to return to Fiasco and wait.\n" + " * Press '^' to restart your computer. You will\n" + " lose unsaved information in any programs that are running.\n\n" + " Press any key to continue \n" + "\n\n\n\n\n\n\n\n " + "\033[16;51H"; + + const char *bsod_dll = + "\033[H\033[44;37;1m\033[2J\n\n\n\n\n\n" + " \033[47;34;1m Fiasco \033[44;37;1m\n\n" + " A fatal exception OE has occurred at %x in JDB.dll + \n" + " %x. The current application will be terminated.\n\n" + " * Press any key to terminate the current application.\n" + " * Press '^' to restart your computer. You will\n" + " lose any unsaved information in all applications.\n\n" + " Press any key to continue \n" + "\n\n\n\n\n\n\n\n " + "\033[16;52H"; + + Unsigned64 tsc = Cpu::rdtsc (); + + if (tsc & 0x10) + printf(bsod_unstable); + else + printf(bsod_dll, current()->regs()->pc()); + + getchar(); + + return NOTHING; +} + +PUBLIC +int const Bsod_m::num_cmds() const +{ + return 1; +} + +PUBLIC +Jdb_module::Cmd const *const Bsod_m::cmds() const +{ + static Cmd cs[] = + { { 0, "t", "t", "\n", NULL, 0 }, }; + + return cs; +} diff --git a/kernel/fiasco/src/jdb/jdb_kern_info-apic.cpp b/kernel/fiasco/src/jdb/jdb_kern_info-apic.cpp new file mode 100644 index 00000000..1518ad1a --- /dev/null +++ b/kernel/fiasco/src/jdb/jdb_kern_info-apic.cpp @@ -0,0 +1,39 @@ +IMPLEMENTATION[apic]: + +#include +#include "simpleio.h" + +#include "apic.h" +#include "static_init.h" + +class Jdb_kern_info_apic : public Jdb_kern_info_module +{ +}; + +static Jdb_kern_info_apic k_a INIT_PRIORITY(JDB_MODULE_INIT_PRIO+1); + +PUBLIC +Jdb_kern_info_apic::Jdb_kern_info_apic() + : Jdb_kern_info_module('a', "Local APIC state") +{ + Jdb_kern_info::register_subcmd(this); +} + +PUBLIC +void +Jdb_kern_info_apic::show() +{ + if (!Config::apic) + { + puts("Local APIC disabled/not available"); + return; + } + + Apic::id_show(); + Apic::timer_show(); + Apic::regs_show(); + putchar('\n'); + Apic::irr_show(); + Apic::isr_show(); +} + diff --git a/kernel/fiasco/src/jdb/jdb_kern_info-bench.cpp b/kernel/fiasco/src/jdb/jdb_kern_info-bench.cpp new file mode 100644 index 00000000..1c7b516d --- /dev/null +++ b/kernel/fiasco/src/jdb/jdb_kern_info-bench.cpp @@ -0,0 +1,164 @@ +INTERFACE: + +#include "jdb.h" + +class Jdb_kern_info_bench : public Jdb_kern_info_module +{ +private: + static Unsigned64 get_time_now(); + static void show_arch(); +}; + +//--------------------------------------------------------------------------- +IMPLEMENTATION: + +static Jdb_kern_info_bench k_a INIT_PRIORITY(JDB_MODULE_INIT_PRIO+1); + +PUBLIC +Jdb_kern_info_bench::Jdb_kern_info_bench() + : Jdb_kern_info_module('b', "Benchmark privileged instructions") +{ + Jdb_kern_info::register_subcmd(this); +} + +PUBLIC +void +Jdb_kern_info_bench::show() +{ + do_mp_benchmark(); + show_arch(); +} + +//--------------------------------------------------------------------------- +IMPLEMENTATION [!mp]: + +PRIVATE +void +Jdb_kern_info_bench::do_mp_benchmark() +{} + +//--------------------------------------------------------------------------- +IMPLEMENTATION [mp && (ia32 || amd64)]: + +#include "idt.h" + +PRIVATE static inline +void +Jdb_kern_info_bench::stop_timer() +{ + Timer_tick::set_vectors_stop(); +} + +//--------------------------------------------------------------------------- +IMPLEMENTATION [mp && !(ia32 || amd64)]: + +PRIVATE static inline +void +Jdb_kern_info_bench::stop_timer() +{} + +//--------------------------------------------------------------------------- +IMPLEMENTATION [mp]: + +#include "ipi.h" + +static int volatile ipi_bench_spin_done; +static int ipi_cnt; + +PRIVATE static +void +Jdb_kern_info_bench::wait_for_ipi(unsigned cpu, void *) +{ + Jdb::restore_irqs(cpu); + stop_timer(); + Proc::sti(); + + while (!ipi_bench_spin_done) + Proc::pause(); + + Proc::cli(); + Jdb::save_disable_irqs(cpu); +} + +PRIVATE static +void +Jdb_kern_info_bench::empty_func(unsigned, void *) +{ + ++ipi_cnt; +} + +PRIVATE static +void +Jdb_kern_info_bench::do_ipi_bench(unsigned my_cpu, void *_partner) +{ + Unsigned64 time; + unsigned partner = (unsigned long)_partner; + enum { + Runs2 = 3, + Warmup = 4, + Rounds = (1 << Runs2) + Warmup, + }; + unsigned i; + + ipi_cnt = 0; + Mem::barrier(); + + for (i = 0; i < Warmup; ++i) + Jdb::remote_work_ipi(my_cpu, partner, empty_func, 0, true); + + time = get_time_now(); + for (i = 0; i < (1 << Runs2); i++) + Jdb::remote_work_ipi(my_cpu, partner, empty_func, 0, true); + + printf(" %2u:%8lld", partner, (get_time_now() - time) >> Runs2); + + if (ipi_cnt != Rounds) + printf("\nCounter mismatch: cnt=%d v %d\n", ipi_cnt, Rounds); + + ipi_bench_spin_done = 1; + Mem::barrier(); +} + +PRIVATE +void +Jdb_kern_info_bench::do_mp_benchmark() +{ + // IPI bench matrix + printf("IPI round-trips:\n"); + for (unsigned u = 0; u < Config::Max_num_cpus; ++u) + if (Cpu::online(u)) + { + printf("l%2u(p%8u): ", u, Cpu::cpus.cpu(u).phys_id()); + + for (unsigned v = 0; v < Config::Max_num_cpus; ++v) + if (Cpu::online(v)) + { + if (u == v) + printf(" %2u:%8s", u, "X"); + else + { + ipi_bench_spin_done = 0; + + // v is waiting for IPIs + if (v != 0) + Jdb::remote_work(v, wait_for_ipi, 0, false); + + // u is doing benchmark + if (u == 0) + do_ipi_bench(0, (void *)v); + else + Jdb::remote_work(u, do_ipi_bench, (void *)v, false); + + // v is waiting for IPIs + if (v == 0) + wait_for_ipi(0, 0); + + Mem::barrier(); + + while (!ipi_bench_spin_done) + Proc::pause(); + } + } + printf("\n"); + } +} diff --git a/kernel/fiasco/src/jdb/jdb_kern_info.cpp b/kernel/fiasco/src/jdb/jdb_kern_info.cpp new file mode 100644 index 00000000..a236586b --- /dev/null +++ b/kernel/fiasco/src/jdb/jdb_kern_info.cpp @@ -0,0 +1,136 @@ +INTERFACE: + +#include "jdb_module.h" +#include + +class Jdb_kern_info_module; + +/** + * 'kern info' module. + * + * This module handles the 'k' command, which + * prints out various kernel information. + */ +class Jdb_kern_info : public Jdb_module +{ +public: + Jdb_kern_info() FIASCO_INIT; +private: + typedef cxx::S_list_bss Module_list; + typedef Module_list::Iterator Module_iter; + static char _subcmd; + static Module_list modules; +}; + + +class Jdb_kern_info_module : public cxx::S_list_item +{ + friend class Jdb_kern_info; +public: + Jdb_kern_info_module(char subcmd, char const *descr) FIASCO_INIT; +private: + virtual void show(void) = 0; + char _subcmd; + char const *_descr; +}; + + +IMPLEMENTATION: + +#include +#include + +#include "cpu.h" +#include "jdb.h" +#include "jdb_module.h" +#include "static_init.h" +#include "kmem_alloc.h" + + +//=================== +// Std JDB modules +//=================== + + +IMPLEMENT +Jdb_kern_info_module::Jdb_kern_info_module(char subcmd, char const *descr) +{ + _subcmd = subcmd; + _descr = descr; +} + + +char Jdb_kern_info::_subcmd; +Jdb_kern_info::Module_list Jdb_kern_info::modules; + +PUBLIC static +void +Jdb_kern_info::register_subcmd(Jdb_kern_info_module *m) +{ + Module_iter p; + for (p = modules.begin(); + p != modules.end() + && (tolower(p->_subcmd) < tolower(m->_subcmd) + || (tolower(p->_subcmd) == tolower(m->_subcmd) + && p->_subcmd > m->_subcmd)); + ++p) + ; + + modules.insert_before(m, p); +} + +PUBLIC +Jdb_module::Action_code +Jdb_kern_info::action(int cmd, void *&args, char const *&, int &) +{ + if (cmd != 0) + return NOTHING; + + char c = *(char*)(args); + Module_iter kim; + + for (kim = modules.begin(); kim != modules.end(); ++kim) + { + if (kim->_subcmd == c) + { + putchar('\n'); + kim->show(); + putchar('\n'); + return NOTHING; + } + } + + putchar('\n'); + for (kim = modules.begin(); kim != modules.end(); ++kim) + printf(" k%c %s\n", kim->_subcmd, kim->_descr); + + putchar('\n'); + return NOTHING; +} + +PUBLIC +int +Jdb_kern_info::num_cmds() const +{ + return 1; +} + +PUBLIC +Jdb_module::Cmd const * +Jdb_kern_info::cmds() const +{ + static Cmd cs[] = + { + { 0, "k", "k", "%c", + "k\tshow various kernel information (kh=help)", &_subcmd } + }; + + return cs; +} + +IMPLEMENT +Jdb_kern_info::Jdb_kern_info() + : Jdb_module("INFO") +{} + +static Jdb_kern_info jdb_kern_info INIT_PRIORITY(JDB_MODULE_INIT_PRIO); diff --git a/kernel/fiasco/src/jdb/jdb_kern_info_config.cpp b/kernel/fiasco/src/jdb/jdb_kern_info_config.cpp new file mode 100644 index 00000000..9f0b7a3e --- /dev/null +++ b/kernel/fiasco/src/jdb/jdb_kern_info_config.cpp @@ -0,0 +1,31 @@ +IMPLEMENTATION: + +#include +#include "jdb_kern_info.h" +#include "static_init.h" + +class Jdb_kern_info_config : public Jdb_kern_info_module +{ +}; + +static Jdb_kern_info_config k_C INIT_PRIORITY(JDB_MODULE_INIT_PRIO+1); + +PUBLIC +Jdb_kern_info_config::Jdb_kern_info_config() + : Jdb_kern_info_module('C', "Kernel config") +{ + Jdb_kern_info::register_subcmd(this); +} + +extern "C" const char _binary_gblcfg_o_txt_start; +extern "C" const char _binary_gblcfg_o_txt_end; + +PUBLIC +void +Jdb_kern_info_config::show() +{ + printf("%*.*s", + (unsigned)(&_binary_gblcfg_o_txt_end - &_binary_gblcfg_o_txt_start), + (unsigned)(&_binary_gblcfg_o_txt_end - &_binary_gblcfg_o_txt_start), + &_binary_gblcfg_o_txt_start); +} diff --git a/kernel/fiasco/src/jdb/jdb_kern_info_kip.cpp b/kernel/fiasco/src/jdb/jdb_kern_info_kip.cpp new file mode 100644 index 00000000..ac925d8a --- /dev/null +++ b/kernel/fiasco/src/jdb/jdb_kern_info_kip.cpp @@ -0,0 +1,27 @@ +IMPLEMENTATION: + +#include "jdb_kern_info.h" +#include "kip.h" +#include "static_init.h" + +class Jdb_kern_info_kip : public Jdb_kern_info_module +{ +}; + +static Jdb_kern_info_kip k_f INIT_PRIORITY(JDB_MODULE_INIT_PRIO+1); + +PUBLIC +Jdb_kern_info_kip::Jdb_kern_info_kip() + : Jdb_kern_info_module('f', "Kernel Interface Page (KIP)") +{ + Jdb_kern_info::register_subcmd(this); +} + +PUBLIC +void +Jdb_kern_info_kip::show() +{ + Kip::k()->print(); +} + + diff --git a/kernel/fiasco/src/jdb/jdb_kern_info_kmem_alloc.cpp b/kernel/fiasco/src/jdb/jdb_kern_info_kmem_alloc.cpp new file mode 100644 index 00000000..aa85fe23 --- /dev/null +++ b/kernel/fiasco/src/jdb/jdb_kern_info_kmem_alloc.cpp @@ -0,0 +1,33 @@ +IMPLEMENTATION: + +#include "static_init.h" +#include "jdb_kern_info.h" +#include "kmem_alloc.h" +#include "kmem_slab.h" + +class Jdb_kern_info_memory : public Jdb_kern_info_module +{}; + +static Jdb_kern_info_memory k_m INIT_PRIORITY(JDB_MODULE_INIT_PRIO+1); + +PUBLIC +Jdb_kern_info_memory::Jdb_kern_info_memory() + : Jdb_kern_info_module('m', "kmem_alloc::debug_dump") +{ + Jdb_kern_info::register_subcmd(this); +} + +PUBLIC +void +Jdb_kern_info_memory::show() +{ + ((Kmem_alloc*)Kmem_alloc::allocator())->debug_dump(); + typedef Kmem_slab::Reap_list::Const_iterator Iter; + + // Slab allocators + for (Iter alloc = Kmem_slab::reap_list.begin(); + alloc != Kmem_slab::reap_list.end(); ++alloc) + alloc->debug_dump(); +} + + diff --git a/kernel/fiasco/src/jdb/jdb_kern_info_region.cpp b/kernel/fiasco/src/jdb/jdb_kern_info_region.cpp new file mode 100644 index 00000000..f8cc8a53 --- /dev/null +++ b/kernel/fiasco/src/jdb/jdb_kern_info_region.cpp @@ -0,0 +1,26 @@ +IMPLEMENTATION: + +#include "jdb_kern_info.h" +#include "region.h" +#include "static_init.h" + +class Jdb_kern_info_region : public Jdb_kern_info_module +{ +}; + +static Jdb_kern_info_region k_r INIT_PRIORITY(JDB_MODULE_INIT_PRIO+1); + +PUBLIC +Jdb_kern_info_region::Jdb_kern_info_region() + : Jdb_kern_info_module('r', "region::debug_dump") +{ + Jdb_kern_info::register_subcmd(this); +} + +PUBLIC +void +Jdb_kern_info_region::show() +{ + Region::debug_dump(); +} + diff --git a/kernel/fiasco/src/jdb/jdb_kobject.cpp b/kernel/fiasco/src/jdb/jdb_kobject.cpp new file mode 100644 index 00000000..db249840 --- /dev/null +++ b/kernel/fiasco/src/jdb/jdb_kobject.cpp @@ -0,0 +1,614 @@ +INTERFACE: + +#include "jdb_module.h" +#include "jdb_list.h" +#include "kobject.h" +#include + +class Kobject; +class Jdb_kobject_handler; + +class Jdb_kobject : public Jdb_module +{ +public: + typedef cxx::S_list_tail Handler_list; + typedef Handler_list::Const_iterator Handler_iter; + + Jdb_kobject(); + + Handler_list handlers; + Handler_list global_handlers; + +private: + static void *kobjp; +}; + + +class Jdb_kobject_handler : public cxx::S_list_item +{ + friend class Jdb_kobject; + +public: + Jdb_kobject_handler(char const *type) : kobj_type(type) {} + char const *kobj_type; + virtual bool show_kobject(Kobject_common *o, int level) = 0; + virtual int show_kobject_short(char *, int, Kobject_common *) { return 0; } + virtual Kobject_common *follow_link(Kobject_common *o) { return o; } + virtual ~Jdb_kobject_handler() {} + virtual bool invoke(Kobject_common *o, Syscall_frame *f, Utcb *utcb); + virtual bool handle_key(Kobject_common *, int /*keycode*/) { return false; } + virtual Kobject *parent(Kobject_common *) { return 0; } + virtual char const *kobject_type() const { return kobj_type; } + + bool is_global() const { return !kobj_type; } + +protected: + enum { + Op_set_name = 0, + Op_global_id = 1, + Op_kobj_to_id = 2, + Op_query_log_typeid = 3, + Op_switch_log = 4, + Op_get_name = 5, + Op_query_log_name = 6, + }; +}; + +class Jdb_kobject_extension : public Kobject_dbg::Dbg_extension +{ +public: + virtual ~Jdb_kobject_extension() {} + virtual char const *type() const = 0; +}; + +class Jdb_kobject_list : public Jdb_list +{ +public: + typedef bool Filter_func(Kobject_common const *); + + struct Mode : cxx::S_list_item + { + char const *name; + Filter_func *filter; + typedef cxx::S_list_bss Mode_list; + static Mode_list modes; + + Mode(char const *name, Filter_func *filter) + : name(name), filter(filter) + { + // make sure that non-filtered mode is first in the list so that we + // get this one displayed initially + if (!filter) + modes.push_front(this); + else + { + Mode_list::Iterator i = modes.begin(); + if (i != modes.end()) + ++i; + modes.insert_before(this, i); + } + } + }; + + void *get_head() const + { return Kobject::from_dbg(Kobject_dbg::begin()); } + +private: + Mode::Mode_list::Const_iterator _current_mode; + Filter_func *_filter; +}; + +//-------------------------------------------------------------------------- +IMPLEMENTATION: + +#include +#include +#include +#include + +#include "entry_frame.h" +#include "jdb.h" +#include "jdb_core.h" +#include "jdb_module.h" +#include "jdb_screen.h" +#include "kernel_console.h" +#include "kobject.h" +#include "keycodes.h" +#include "ram_quota.h" +#include "simpleio.h" +#include "space.h" +#include "static_init.h" + +Jdb_kobject_list::Mode::Mode_list Jdb_kobject_list::Mode::modes; + +class Jdb_kobject_id_hdl : public Jdb_kobject_handler +{ +public: + Jdb_kobject_id_hdl() : Jdb_kobject_handler(0) {} + virtual bool show_kobject(Kobject_common *, int) { return false; } + virtual ~Jdb_kobject_id_hdl() {} +}; + +PUBLIC +bool +Jdb_kobject_id_hdl::invoke(Kobject_common *o, Syscall_frame *f, Utcb *utcb) +{ + if ( utcb->values[0] != Op_global_id + && utcb->values[0] != Op_kobj_to_id) + return false; + + if (utcb->values[0] == Op_global_id) + utcb->values[0] = o->dbg_info()->dbg_id(); + else + utcb->values[0] = Kobject_dbg::pointer_to_id((void *)utcb->values[1]); + f->tag(Kobject_iface::commit_result(0, 1)); + return true; +} + + +PRIVATE +void * +Jdb_kobject_list::get_first() +{ + Kobject_dbg::Iterator f = Kobject_dbg::begin(); + while (f != Kobject_dbg::end() && _filter && !_filter(Kobject::from_dbg(f))) + ++f; + return Kobject::from_dbg(f); +} + +PUBLIC explicit +Jdb_kobject_list::Jdb_kobject_list(Filter_func *filt) +: Jdb_list(), _current_mode(Mode::modes.end()), _filter(filt) +{ set_start(get_first()); } + +PUBLIC +Jdb_kobject_list::Jdb_kobject_list() +: Jdb_list(), _current_mode(Mode::modes.begin()) +{ + if (_current_mode != Mode::modes.end()) + _filter = _current_mode->filter; + + set_start(get_first()); +} + +PUBLIC +int +Jdb_kobject_list::show_item(char *buffer, int max, void *item) const +{ + return Jdb_kobject::obj_description(buffer, max, false, static_cast(item)->dbg_info()); +} + +PUBLIC +bool +Jdb_kobject_list::enter_item(void *item) const +{ + Kobject *o = static_cast(item); + return Jdb_kobject::module()->handle_obj(o, 1); +} + +PUBLIC +void * +Jdb_kobject_list::follow_link(void *item) +{ + Kobject *o = static_cast(item); + if (Jdb_kobject_handler *h = Jdb_kobject::module()->find_handler(o)) + return h->follow_link(o); + + return item; +} + +PUBLIC +bool +Jdb_kobject_list::handle_key(void *item, int keycode) +{ + Kobject *o = static_cast(item); + bool handled = false; + for (Jdb_kobject::Handler_iter h = Jdb_kobject::module()->global_handlers.begin(); + h != Jdb_kobject::module()->global_handlers.end(); ++h) + handled |= h->handle_key(o, keycode); + + if (Jdb_kobject_handler *h = Jdb_kobject::module()->find_handler(o)) + handled |= h->handle_key(o, keycode); + + return handled; +} + +PRIVATE inline NOEXPORT +Kobject * +Jdb_kobject_list::next(Kobject *obj) +{ + if (!obj) + return 0; + + Kobject_dbg::Iterator o = Kobject_dbg::Kobject_list::iter(obj->dbg_info()); + + do + { + ++o; + if (o == Kobject_dbg::end()) + return 0; + } + while (_filter && !_filter(Kobject::from_dbg(*o))); + return Kobject::from_dbg(*o); +} + +PRIVATE inline NOEXPORT +Kobject * +Jdb_kobject_list::prev(Kobject *obj) +{ + if (!obj) + return 0; + + Kobject_dbg::Iterator o = Kobject_dbg::Kobject_list::iter(obj->dbg_info()); + + do + { + --o; + if (o == Kobject_dbg::end()) + return 0; + } + while (_filter && !_filter(Kobject::from_dbg(*o))); + return Kobject::from_dbg(*o); +} + +PUBLIC +int +Jdb_kobject_list::seek(int cnt, void **item) +{ + Kobject *c = static_cast(*item); + int i; + if (cnt > 0) + { + for (i = 0; i < cnt; ++i) + { + Kobject *n = next(c); + if (!n) + break; + c = n; + } + } + else if (cnt < 0) + { + for (i = 0; i < -cnt; ++i) + { + Kobject *n = prev(c); + if (!n) + break; + c = n; + } + } + else + return 0; + + if (*item != c) + { + *item = c; + return i; + } + + return 0; +} + +PUBLIC +char const * +Jdb_kobject_list::show_head() const +{ + return "[Objects]"; +} + + +PUBLIC +char const * +Jdb_kobject_list::get_mode_str() const +{ + if (_current_mode == Mode::modes.end()) + return "[Objects]"; + return _current_mode->name; +} + + + +PUBLIC +void +Jdb_kobject_list::next_mode() +{ + if (_current_mode == Mode::modes.end()) + return; + + ++_current_mode; + if (_current_mode == Mode::modes.end()) + _current_mode = Mode::modes.begin(); + + _filter = _current_mode->filter; +} + +/* When the mode changes the current object may get invisible, + * get a new visible one */ +PUBLIC +void * +Jdb_kobject_list::get_valid(void *o) +{ + if (!_filter) + return o; + + if (_filter && _filter(static_cast(o))) + return o; + return get_first(); +} + +IMPLEMENT +bool +Jdb_kobject_handler::invoke(Kobject_common *, Syscall_frame *, Utcb *) +{ return false; } + +void *Jdb_kobject::kobjp; + +IMPLEMENT +Jdb_kobject::Jdb_kobject() + : Jdb_module("INFO") +{} + + +PUBLIC +void +Jdb_kobject::register_handler(Jdb_kobject_handler *h) +{ + if (h->is_global()) + global_handlers.push_back(h); + else + handlers.push_back(h); +} + +PUBLIC +Jdb_kobject_handler * +Jdb_kobject::find_handler(Kobject_common *o) +{ + for (Handler_iter h = handlers.begin(); h != handlers.end(); ++h) + if (o->kobj_type() == h->kobj_type) + return *h; + + return 0; +} + +PUBLIC +bool +Jdb_kobject::handle_obj(Kobject *o, int lvl) +{ + if (Jdb_kobject_handler *h = find_handler(o)) + return h->show_kobject(o, lvl); + + return true; +} + +PUBLIC static +char const * +Jdb_kobject::kobject_type(Kobject_common *o) +{ + if (Jdb_kobject_handler *h = module()->find_handler(o)) + return h->kobject_type(); + + return o->kobj_type(); +} + + +PUBLIC static +int +Jdb_kobject::obj_description(char *buffer, int max, bool dense, Kobject_dbg *o) +{ + int pos = snprintf(buffer, max, + dense ? "%lx %lx [%-*s]" : "%8lx %08lx [%-*s]", + o->dbg_id(), (Mword)Kobject::from_dbg(o), 7, kobject_type(Kobject::from_dbg(o))); + + for (Handler_iter h = module()->global_handlers.begin(); + h != module()->global_handlers.end(); ++h) + pos += h->show_kobject_short(buffer + pos, max-pos, Kobject::from_dbg(o)); + + if (Jdb_kobject_handler *oh = Jdb_kobject::module()->find_handler(Kobject::from_dbg(o))) + pos += oh->show_kobject_short(buffer + pos, max-pos, Kobject::from_dbg(o)); + + return pos; +} + +PRIVATE static +void +Jdb_kobject::print_kobj(Kobject *o) +{ + printf("%p [type=%s]", o, o->kobj_type()); +} + +PUBLIC +Jdb_module::Action_code +Jdb_kobject::action(int cmd, void *&, char const *&, int &) +{ + if (cmd == 0) + { + puts(""); + Kobject_dbg::Iterator i = Kobject_dbg::pointer_to_obj(kobjp); + if (i == Kobject_dbg::end()) + printf("Not a kobj.\n"); + else + { + Kobject *k = Kobject::from_dbg(i); + if (!handle_obj(k, 0)) + printf("Kobj w/o handler: "); + print_kobj(k); + puts(""); + } + return NOTHING; + } + else if (cmd == 1) + { + Jdb_kobject_list list; + list.do_list(); + } + return NOTHING; +} + +PUBLIC +Jdb_module::Cmd const * +Jdb_kobject::cmds() const +{ + static Cmd cs[] = + { + { 0, "K", "kobj", "%p", "K\tshow information for kernel object", + &kobjp }, + { 1, "Q", "listkobj", "", "Q\tshow information for kernel objects", 0 }, + }; + return cs; +} + +PUBLIC +int +Jdb_kobject::num_cmds() const +{ return 2; } + +STATIC_INITIALIZE_P(Jdb_kobject, JDB_MODULE_INIT_PRIO); + +PRIVATE static +int +Jdb_kobject::fmt_handler(char /*fmt*/, int *size, char const *cmd_str, void *arg) +{ + char buffer[20]; + + int pos = 0; + int c; + Address n; + + *size = sizeof(void*); + + while((c = Jdb_core::cmd_getchar(cmd_str)) != ' ' && c!=KEY_RETURN) + { + if(c==KEY_ESC) + return 3; + + if(c==KEY_BACKSPACE && pos>0) + { + putstr("\b \b"); + --pos; + } + + if (pos < (int)sizeof(buffer) - 1) + { + putchar(c); + buffer[pos++] = c; + buffer[pos] = 0; + } + } + + Kobject **a = (Kobject**)arg; + + if (!pos) + { + *a = 0; + return 0; + } + + char const *num = buffer; + if (buffer[0] == 'P') + num = buffer + 1; + + n = strtoul(num, 0, 16); + + Kobject_dbg::Iterator ko; + + if (buffer[0] != 'P') + ko = Kobject_dbg::id_to_obj(n); + else + ko = Kobject_dbg::pointer_to_obj((void*)n); + + if (ko != Kobject_dbg::end()) + *a = Kobject::from_dbg(ko); + else + *a = 0; + + return 0; +} + +PUBLIC static +void +Jdb_kobject::init() +{ + module(); + + Jdb_core::add_fmt_handler('q', fmt_handler); + +// static Jdb_handler enter(at_jdb_enter); + + static Jdb_kobject_id_hdl id_hdl; + module()->register_handler(&id_hdl); +} + +PUBLIC static +Jdb_kobject * +Jdb_kobject::module() +{ + static Jdb_kobject jdb_kobj_module; + return &jdb_kobj_module; +} + +// Be robust if this object is invalid +PUBLIC static +void +Jdb_kobject::print_uid(Kobject_common *o, int task_format = 0) +{ + if (!o) + { + printf("%*.s", task_format, "---"); + return; + } + + if (Kobject_dbg::is_kobj(o)) + { + printf("%*.lx", task_format, o->dbg_info()->dbg_id()); + return; + } + + printf("\033[31;1m%*s%p\033[m", task_format, "???", o); + return; +} + + +extern "C" void +sys_invoke_debug(Kobject_iface *o, Syscall_frame *f) +{ + if (!o) + { + f->tag(Kobject_iface::commit_result(-L4_err::EInval)); + return; + } + + Utcb *utcb = current_thread()->utcb().access(); + //printf("sys_invoke_debug: [%p] -> %p\n", o, f); + Jdb_kobject_handler *h = Jdb_kobject::module()->find_handler(o); + if (h && h->invoke(o, f, utcb)) + return; + + for (Jdb_kobject::Handler_iter i = Jdb_kobject::module()->global_handlers.begin(); + i != Jdb_kobject::module()->global_handlers.end(); ++i) + if (i->invoke(o, f, utcb)) + return; + + f->tag(Kobject_iface::commit_result(-L4_err::ENosys)); +} + +PUBLIC +template< typename T > +static +T * +Jdb_kobject_extension::find_extension(Kobject_common const *o) +{ + typedef Kobject_dbg::Dbg_ext_list::Iterator Iterator; + for (Iterator ex = o->dbg_info()->_jdb_data.begin(); + ex != o->dbg_info()->_jdb_data.end(); ++ex) + { + Jdb_kobject_extension *je = static_cast(*ex); + if (je->type() == T::static_type) + return static_cast(je); + } + + return 0; +} + +static Jdb_kobject_list::Mode INIT_PRIORITY(JDB_MODULE_INIT_PRIO) all("[ALL]", 0); + + diff --git a/kernel/fiasco/src/jdb/jdb_kobject_names.cpp b/kernel/fiasco/src/jdb/jdb_kobject_names.cpp new file mode 100644 index 00000000..30e63c70 --- /dev/null +++ b/kernel/fiasco/src/jdb/jdb_kobject_names.cpp @@ -0,0 +1,212 @@ +//----------------------------------------------------------------------- +INTERFACE: + +#include "config.h" +#include "jdb_kobject.h" +#include "l4_types.h" +#include "initcalls.h" + + +class Jdb_kobject_name : public Jdb_kobject_extension +{ +public: + static char const *const static_type; + virtual char const *type() const { return static_type; } + + ~Jdb_kobject_name() {} + + void *operator new (size_t) throw(); + void operator delete (void *); + +private: + + char _name[16]; + + static Jdb_kobject_name *_names; +}; + +//----------------------------------------------------------------------- +IMPLEMENTATION: + +#include + +#include +#include "context.h" +#include "kmem_alloc.h" +#include "minmax.h" +#include "panic.h" +#include "space.h" +#include "thread.h" +#include "static_init.h" + + + +enum +{ + Name_buffer_size = 8192, + Name_entries = Name_buffer_size / sizeof(Jdb_kobject_name), +}; + + +char const *const Jdb_kobject_name::static_type = "Jdb_kobject_names"; +Jdb_kobject_name *Jdb_kobject_name::_names; + + +PUBLIC +unsigned +Jdb_kobject_name::max_len() +{ return sizeof(_name); } + +PUBLIC +void +Jdb_kobject_name::name(char const *name) +{ + strncpy(_name, name, sizeof(_name)); +} + +PUBLIC +Jdb_kobject_name::Jdb_kobject_name() +{ _name[0] = 0; } + +static Spin_lock<> allocator_lock; + +IMPLEMENT +void * +Jdb_kobject_name::operator new (size_t) throw() +{ + Jdb_kobject_name *n = _names; + while (1) + { + void **o = reinterpret_cast(n); + if (!*o) + { + Lock_guard > g(&allocator_lock); + if (!*o) + { + *o = (void*)10; + return n; + } + } + + ++n; + + if ((n - _names) >= Name_entries) + return 0; + } +} + +IMPLEMENT +void +Jdb_kobject_name::operator delete (void *p) +{ + Lock_guard > g(&allocator_lock); + void **o = reinterpret_cast(p); + *o = 0; +} + +PUBLIC +void +Jdb_kobject_name::clear_name() +{ + for (unsigned i = 0; i < max_len(); ++i) + _name[i] = 0; +} + +PUBLIC inline +char const * +Jdb_kobject_name::name() const +{ return _name; } + +PUBLIC inline +char * +Jdb_kobject_name::name() +{ return _name; } + +class Jdb_name_hdl : public Jdb_kobject_handler +{ +public: + Jdb_name_hdl() : Jdb_kobject_handler(0) {} + virtual bool show_kobject(Kobject_common *, int) { return true; } + virtual ~Jdb_name_hdl() {} +}; + +PUBLIC +int +Jdb_name_hdl::show_kobject_short(char *buf, int max, Kobject_common *o) +{ + Jdb_kobject_name *ex + = Jdb_kobject_extension::find_extension(o); + + if (ex) + return snprintf(buf, max, " {%-*.*s}", ex->max_len(), ex->max_len(), ex->name()); + + return 0; +} + +PUBLIC +bool +Jdb_name_hdl::invoke(Kobject_common *o, Syscall_frame *f, Utcb *utcb) +{ + switch (utcb->values[0]) + { + case Op_set_name: + { + Jdb_kobject_name *ne = new Jdb_kobject_name(); + if (!ne) + { + f->tag(Kobject_iface::commit_result(-L4_err::ENomem)); + return true; + } + + char const *name = reinterpret_cast(&utcb->values[1]); + ne->clear_name(); + strncpy(ne->name(), name, ne->max_len()); + o->dbg_info()->_jdb_data.add(ne); + f->tag(Kobject_iface::commit_result(0)); + return true; + } + case Op_get_name: + { + Kobject_dbg::Iterator o = Kobject_dbg::id_to_obj(utcb->values[1]); + if (o == Kobject_dbg::end()) + { + f->tag(Kobject_iface::commit_result(-L4_err::ENoent)); + return true; + } + Jdb_kobject_name *n = Jdb_kobject_extension::find_extension(Kobject::from_dbg(o)); + if (!n) + { + f->tag(Kobject_iface::commit_result(-L4_err::ENoent)); + return true; + } + + unsigned l = min(n->max_len(), sizeof(utcb->values)); + char *dst = reinterpret_cast(utcb->values); + strncpy(dst, n->name(), l); + dst[l - 1] = 0; + + f->tag(Kobject_iface::commit_result(0)); + return true; + } + } + return false; +} + +PUBLIC static FIASCO_INIT +void +Jdb_kobject_name::init() +{ + _names = (Jdb_kobject_name*)Kmem_alloc::allocator()->unaligned_alloc(Name_buffer_size); + if (!_names) + panic("No memory for thread names"); + + for (int i=0; i(_names + i) = 0; + + static Jdb_name_hdl hdl; + Jdb_kobject::module()->register_handler(&hdl); +} + + +STATIC_INITIALIZE(Jdb_kobject_name); + diff --git a/kernel/fiasco/src/jdb/jdb_lines.cpp b/kernel/fiasco/src/jdb/jdb_lines.cpp new file mode 100644 index 00000000..39b2e186 --- /dev/null +++ b/kernel/fiasco/src/jdb/jdb_lines.cpp @@ -0,0 +1,323 @@ +INTERFACE: + +#include "l4_types.h" +class Space; + +class Jdb_lines_line +{ +public: + unsigned long addr; + unsigned short line; +} __attribute__((packed)); + +class Jdb_lines_info +{ +private: + Address _virt; + size_t _size; + Address _beg_line; + Address _end_line; +}; + +class Jdb_lines +{ +public: + enum + { + // don't allow more than 2048 tasks to register their lines to save space + Max_tasks = 2048, + }; + +private: + static Jdb_lines_info *_task_lines; +}; + + +IMPLEMENTATION: + +#include +#include +#include "panic.h" +#include "warn.h" + +Jdb_lines_info *Jdb_lines::_task_lines; + +PUBLIC static +void +Jdb_lines::init (void *mem, Mword pages) +{ + if (!mem || pages < (Max_tasks*sizeof(Jdb_lines_info))>>Config::PAGE_SHIFT) + panic("No memory for lines"); + + _task_lines = (Jdb_lines_info*)mem; + memset(_task_lines, 0, Max_tasks * sizeof(Jdb_lines_info)); +} + +PUBLIC inline NOEXPORT +Jdb_lines_line* +Jdb_lines_info::lin () +{ + return (Jdb_lines_line*)_virt; +} + +PUBLIC inline NOEXPORT +const char* +Jdb_lines_info::str () +{ + return (const char*)_virt; +} + +PUBLIC inline +void +Jdb_lines_info::get (Address &virt, size_t &size) +{ + virt = _virt; + size = _size; +} + +PUBLIC inline +void +Jdb_lines_info::reset () +{ + _virt = 0; +} + +PUBLIC inline NOEXPORT +bool +Jdb_lines_info::in_range (Address addr) +{ + return _virt != 0 && _beg_line <= addr && _end_line >= addr; +} + +// register lines for a specific task (called by user mode application) +PUBLIC +bool +Jdb_lines_info::set (Address virt, size_t size) +{ + _virt = virt; + _size = size; + + Address min_addr = 0xffffffff, max_addr = 0; + Jdb_lines_line *l; + + // search lines with lowest / highest address + for (l = lin(); l->addr || l->line; l++) + { + if (l->line < 0xfffd) + { + Address addr = l->addr; + if (addr < min_addr) + min_addr = addr; + if (addr > max_addr) + max_addr = addr; + } + } + + _beg_line = min_addr; + _end_line = max_addr; + + return true; +} + +PUBLIC static +Jdb_lines_info* +Jdb_lines::lookup (Space * task) +{ + (void)task; +#if 0 + if (task >= Max_tasks) + { + WARN ("register_lines: task value #%x out of range (0-%x)\n", + task, Max_tasks-1); + return 0; + } + + return _task_lines + task; +#endif + return 0; +} + +IMPLEMENTATION[!arm]: + +// search line name that matches for a specific address +PUBLIC static +bool +Jdb_lines::match_addr_to_line(Address addr, Space * task, + char *line, unsigned line_size, + int show_header_files) +{ + (void)addr; (void)task; (void)line; (void)line_size; (void)show_header_files; +#if 0 + if (task >= Max_tasks) + return false; + + if (! _task_lines[task].in_range (addr)) + return false; + + int show_file = 1; + Jdb_lines_line *lin = _task_lines[task].lin(); + const char *dir="", *file="", *str = _task_lines[task].str(); + + for (; lin->addr || lin->line; lin++) + { + if (lin->line == 0xfffe) + { + // this is a directory entry + dir = str + lin->addr; + } + else if (lin->line == 0xffff) + { + // this is a file name entry + file = str + lin->addr; + show_file = 1; + } + else if (lin->line == 0xfffd) + { + // this is a header file name entry + file = str + lin->addr; + show_file = show_header_files; + } + else if ((lin->addr == addr) && show_file) + { + // this is a line + sprint_line(dir, file, lin->line, line, line_size); + return true; + } + } +#endif + return false; +} + +// search line name that matches for a specific address +PUBLIC static +bool +Jdb_lines::match_addr_to_line_fuzzy(Address *addr_ptr, Space * task, + char *line, unsigned line_size, + int show_header_files) +{ + (void)addr_ptr; (void)task; (void)line; (void)line_size; (void)show_header_files; +#if 0 + if (task >= Max_tasks) + return false; + + if (! _task_lines[task].in_range (*addr_ptr)) + return false; + + int show_file = 1; + Address best_addr = (Address)-1, best_line = 0; + Jdb_lines_line *lin = _task_lines[task].lin(); + const char *dir="", *file="", *best_dir=0, *best_file=0; + const char *str=_task_lines[task].str(); + + for (; lin->addr || lin->line; lin++) + { + if (lin->line == 0xfffe) + { + // this is a directory entry + dir = str + lin->addr; + } + else if (lin->line == 0xffff) + { + // this is a file name entry + file = str + lin->addr; + show_file = 1; + } + else if (lin->line == 0xfffd) + { + // this is a header file name entry + file = str + lin->addr; + show_file = show_header_files; + } + else if ((lin->addr <= *addr_ptr) + && (*addr_ptr-lin->addr < best_addr) + && show_file) + { + best_addr = *addr_ptr-lin->addr; + best_dir = dir; + best_file = file; + best_line = lin->line; + } + } + + if (best_addr < (Address)-1) + { + sprint_line(best_dir, best_file, best_line, line, line_size); + *addr_ptr -= best_addr; + return true; + } +#endif + return false; +} + +// truncate string if its length exceeds strsize and create line +static +void +Jdb_lines::sprint_line(const char *dir, const char *fname, unsigned line, + char *str, size_t strsize) +{ + unsigned d = strlen(dir); + unsigned f = strlen(fname); + + if (!str) + return; + + if (fname[0]=='/') + d=0; + + // handle fname in form of ../../../../foo/bar.h + while (d>1 && f>2 && fname[0]=='.' && fname[1]=='.' && fname[2]=='/') + { + // cut last directory + while ((d>1) && (dir[d-2]!='/')) + d--; + d--; + // cut first ../ directory of fname + fname+=3; + f-=3; + } + + if (strsize < 10) + { + *str = '\0'; + return; + } + + strsize -= 6; // for line number + + if ((d+f) > strsize) + { + // abbreviate line in a sane way + memcpy(str, "... ", 4); + str += 4; + strsize -= 4; + + if (strsize > f) + { + unsigned dp = strsize-f; + memcpy(str, dir+d-dp, dp); + str += dp; + strsize -= dp; + } + memcpy(str, fname+f-strsize, strsize); + str += strsize; + } + else + { + memcpy(str, dir, d); + memcpy(str+d, fname, f); + str += d+f; + } + + snprintf(str, strsize, ":%d", line); +} + +IMPLEMENTATION[arm]: + +PUBLIC static +bool +Jdb_lines::match_addr_to_line(Address , Space * , + char * , unsigned , int ) +{ + return 0; +} + diff --git a/kernel/fiasco/src/jdb/jdb_list.cpp b/kernel/fiasco/src/jdb/jdb_list.cpp new file mode 100644 index 00000000..54294a97 --- /dev/null +++ b/kernel/fiasco/src/jdb/jdb_list.cpp @@ -0,0 +1,417 @@ +INTERFACE: + +class Jdb_list +{ +public: + virtual char const *get_mode_str() const { return "[std mode]"; } + virtual void next_mode() {} + virtual void next_sort() {} + virtual void *get_head() const = 0; + virtual int show_item(char *buffer, int max, void *item) const = 0; + virtual char const *show_head() const = 0; + virtual int seek(int cnt, void **item) = 0; + virtual bool enter_item(void * /*item*/) const { return true; } + virtual void *follow_link(void *a) { return a; } + virtual bool handle_key(void * /*item*/, int /*keycode*/) { return false; } + virtual void *parent(void * /*item*/) { return 0; } + virtual void *get_valid(void *a) { return a; } + +private: + void *_start, *_last; + void *_current; + +}; + + +// --------------------------------------------------------------------------- +IMPLEMENTATION: + +#include +#include +#include + +#include "jdb.h" +#include "jdb_core.h" +#include "jdb_screen.h" +#include "kernel_console.h" +#include "keycodes.h" +#include "simpleio.h" +#include + + + +PUBLIC +Jdb_list::Jdb_list() + : _start(0), _current(0) +{} + +// set _t_start element of list +PUBLIC +void +Jdb_list::set_start(void *start) +{ + _start = start; +} + +// _t_start-- if possible +PUBLIC inline +bool +Jdb_list::line_back() +{ return seek(-1, &_start); } + +// _t_start++ if possible +PUBLIC inline +bool +Jdb_list::line_forw() +{ + if (seek(1, &_last)) + return seek(1, &_start); + else + return false; +} +#if 0 + Thread *t = _t_start; + iter(+Jdb_screen::height()-2, &_t_start); + iter(-Jdb_screen::height()+3, &_t_start); + return t != _t_start; +} +#endif + +// _t_start -= 24 if possible +PUBLIC +bool +Jdb_list::page_back() +{ return seek(-Jdb_screen::height()+2, &_start); } + +// _t_start += 24 if possible +PUBLIC +bool +Jdb_list::page_forw() +{ + int fwd = seek(Jdb_screen::height()-2, &_last); + if (fwd) + return seek(fwd, &_start); + return false; +} + +#if 0 + Thread *t = _t_start; + iter(+Jdb_screen::height()*2-5, &_t_start); + iter(-Jdb_screen::height() +3, &_t_start); + return t != _t_start; +} +#endif + +// _t_start = first element of list +PUBLIC +bool +Jdb_list::goto_home() +{ return seek(-99999, &_start); } + +// _t_start = last element of list +PUBLIC +bool +Jdb_list::goto_end() +{ return seek(99999, &_start); } +#if 0 + Thread *t = _t_start; + iter(+9999, &_t_start); + iter(-Jdb_screen::height()+2, &_t_start); + return t != _t_start; +} +#endif + +// search index of t_search starting from _t_start +PUBLIC +int +Jdb_list::lookup_in_visible_area(void *search) +{ + unsigned i; + void *t; + + for (i=0, t = _start; i < Jdb_screen::height()-3; ++i) + { + if (t == search) + return i; + + seek(1, &t); + } + + return -1; +} + +// get y'th element of thread list starting from _t_start +PUBLIC +void * +Jdb_list::index(int y) +{ + void *t = _start; + + seek(y, &t); + return t; +} + + +PUBLIC +void +Jdb_list::show_line(void *i) +{ + static char buffer[256]; + Kconsole::console()->getchar_chance(); + int pos = 0; + void *p = i; + while ((p = parent(p))) + { + buffer[pos] = ' '; + ++pos; + } + + pos += show_item(buffer + pos, sizeof(buffer) - pos, i); + if (i) + printf("%.*s\033[K\n", min((int)Jdb_screen::width(), pos), buffer); +} + +// show complete page using show callback function +PUBLIC +int +Jdb_list::page_show() +{ + void *t = _start; + unsigned i = 0; + for (i = 0; i < Jdb_screen::height()-3; ++i) + { + if (!t) + break; + else + _last = t; + + show_line(t); + + if (!seek(1,&t)) + return i; + } + + return i - 1; +} + +// show complete list using show callback function +PUBLIC +int +Jdb_list::complete_show() +{ + void *t = _start; + int i = 0; + for (i = 0; ; ++i, seek(1, &t)) + { + if (!t) + break; + + show_line(t); + } + + return i; +} + +#if 0 +PUBLIC +Jdb_module::Action_code +Jdb_thread_list::action(int cmd, void *&argbuf, char const *&fmt, int &) +{ + static char const *const cpu_fmt = " cpu=%i\n"; + static char const *const nfmt = "\n"; + if (cmd == 0) + { + if (fmt != cpu_fmt && fmt != nfmt) + { + if (subcmd == 'c') + { + argbuf = &cpu; + fmt = cpu_fmt; + } + else + fmt = nfmt; + return EXTRA_INPUT; + } + + Thread *t = Jdb::get_current_active(); + switch (subcmd) + { + case 'r': cpu = 0; list_threads(t, 'r'); break; + case 'p': list_threads(t, 'p'); break; + case 'c': + if (Cpu::online(cpu)) + list_threads(Jdb::get_thread(cpu), 'r'); + else + printf("\nCPU %u is not online!\n", cpu); + cpu = 0; + break; + case 't': Jdb::execute_command("lt"); break; // other module + } + } + else if (cmd == 1) + { + Console *gzip = Kconsole::console()->find_console(Console::GZIP); + if (gzip) + { + Thread *t = Jdb::get_current_active(); + gzip->state(gzip->state() | Console::OUTENABLED); + long_output = 1; + Jdb_thread_list::init('p', t); + Jdb_thread_list::set_start(t); + Jdb_thread_list::goto_home(); + Jdb_thread_list::complete_show(list_threads_show_thread); + long_output = 0; + gzip->state(gzip->state() & ~Console::OUTENABLED); + } + else + puts(" gzip module not available"); + } + + return NOTHING; +} +#endif + + +PUBLIC +void +Jdb_list::show_header() +{ + Jdb::cursor(); + printf("%.*s\033[K\n", Jdb_screen::width(), show_head()); +} + + +PUBLIC +void +Jdb_list::do_list() +{ + int y, y_max; + void *t; + + if (!_start) + _start = get_head(); + + if (!_current) + _current = _start; + + Jdb::clear_screen(); + show_header(); + + if (!_start) + { + printf("[EMPTY]\n"); + return; + } + + + for (;;) + { + // set y to position of t_current in current displayed list + y = lookup_in_visible_area(_current); + if (y == -1) + { + _start = _current; + y = 0; + } + + for (bool resync=false; !resync;) + { + Jdb::cursor(2, 1); + y_max = page_show(); + + // clear rest of screen (if where less than 24 lines) + for (unsigned i = y_max; i < Jdb_screen::height()-3; ++i) + putstr("\033[K\n"); + + Jdb::printf_statline("Objs", + "=mode =link =select", + "%-15s", get_mode_str()); + + // key event loop + for (bool redraw=false; !redraw; ) + { + Jdb::cursor(y+2, 1); + switch (int c=Jdb_core::getchar()) + { + case KEY_CURSOR_UP: + case 'k': + if (y > 0) + y--; + else + redraw = line_back(); + break; + case KEY_CURSOR_DOWN: + case 'j': + if (y < y_max) + y++; + else + redraw = line_forw(); + break; + case KEY_PAGE_UP: + case 'K': + if (!(redraw = page_back())) + y = 0; + break; + case KEY_PAGE_DOWN: + case 'J': + if (!(redraw = page_forw())) + y = y_max; + break; + case KEY_CURSOR_HOME: + case 'H': + redraw = goto_home(); + y = 0; + break; + case KEY_CURSOR_END: + case 'L': + redraw = goto_end(); + y = y_max; + break; + case 's': // switch sort + _current = index(y); + next_sort(); + redraw = true; + resync = true; + break; + case ' ': // switch mode + _current = index(y); + next_mode(); + _current = get_valid(_current); + _start = get_valid(_start); + redraw = true; + resync = true; + break; + case KEY_TAB: // go to associated object + _current = index(y); + t = follow_link(_current); + if (t != _current) + { + _current = t; + redraw = true; + resync = true; + } + break; + case KEY_RETURN: + _current = index(y); + if (!enter_item(_current)) + return; + show_header(); + redraw = 1; + break; + case KEY_ESC: + Jdb::abort_command(); + return; + default: + _current = index(y); + if (!handle_key(_current, c) && Jdb::is_toplevel_cmd(c)) + return; + + show_header(); + redraw = 1; + break; + } + } + } + } +} + diff --git a/kernel/fiasco/src/jdb/jdb_log.cpp b/kernel/fiasco/src/jdb/jdb_log.cpp new file mode 100644 index 00000000..936b7c0e --- /dev/null +++ b/kernel/fiasco/src/jdb/jdb_log.cpp @@ -0,0 +1,373 @@ +IMPLEMENTATION: + +#include +#include +#include + +#include "jdb.h" +#include "jdb_core.h" +#include "jdb_module.h" +#include "jdb_kobject.h" +#include "jdb_list.h" +#include "jdb_screen.h" +#include "kernel_console.h" +#include "keycodes.h" +#include "mem_unit.h" +#include "ram_quota.h" +#include "simpleio.h" +#include "task.h" +#include "static_init.h" + + +class Jdb_log_list : public Jdb_list +{ + friend class Jdb_log_list_hdl; +public: + void *get_head() const { return _log_table; } + char const *show_head() const { return "[Log]"; } + +private: + static Tb_log_table_entry *_end; +}; + +Tb_log_table_entry *Jdb_log_list::_end; + +class Jdb_log_list_hdl : public Jdb_kobject_handler +{ +public: + Jdb_log_list_hdl() : Jdb_kobject_handler(0) {} + virtual bool show_kobject(Kobject_common *, int) { return true; } +}; + +PUBLIC +bool +Jdb_log_list_hdl::invoke(Kobject_common *, Syscall_frame *f, Utcb *utcb) +{ + switch (utcb->values[0]) + { + case Op_query_log_typeid: + { + unsigned char const idx = utcb->values[1]; + if (f->tag().words() < 3 || _log_table + idx >= &_log_table_end) + { + f->tag(Kobject_iface::commit_result(-L4_err::EInval)); + return true; + } + + char nbuf[32]; + strncpy(nbuf, (char const *)&utcb->values[2], sizeof(nbuf)); + nbuf[sizeof(nbuf) - 1] = 0; + + Tb_log_table_entry *r; + r = Jdb_log_list::find_next_log(nbuf, nbuf, _log_table + idx); + + utcb->values[0] = r ? (r - _log_table) + Tbuf_dynentries : ~0UL; + f->tag(Kobject_iface::commit_result(0, 1)); + return true; + } + case Op_query_log_name: + { + unsigned char const idx = utcb->values[1]; + if (f->tag().words() != 2 || _log_table + idx >= &_log_table_end) + { + f->tag(Kobject_iface::commit_result(-L4_err::EInval)); + return true; + } + + Tb_log_table_entry *e = _log_table + idx; + char *dst = (char *)&utcb->values[0]; + unsigned sz = strlen(e->name) + 1; + sz += strlen(e->name + sz) + 1; + if (sz > sizeof(utcb->values)) + sz = sizeof(utcb->values); + memcpy(dst, e->name, sz); + dst[sz - 1] = 0; + + f->tag(Kobject_iface::commit_result(0)); + return true; + } + case Op_switch_log: + { + if (f->tag().words() < 3) + { + f->tag(Kobject_iface::commit_result(-L4_err::EInval)); + return true; + } + + bool on = utcb->values[1]; + char nbuf[32]; + strncpy(nbuf, (char const *)&utcb->values[2], sizeof(nbuf)); + nbuf[sizeof(nbuf) - 1] = 0; + + Tb_log_table_entry *r = _log_table; + while ((r = Jdb_log_list::find_next_log(nbuf, nbuf, r))) + { + Jdb_log_list::patch_item(r, on ? Jdb_log_list::patch_val(r) : 0); + r++; + } + + f->tag(Kobject_iface::commit_result(0)); + return true; + } + } + + return false; +} + +PUBLIC +int +Jdb_log_list::show_item(char *buffer, int max, void *item) const +{ + Tb_log_table_entry const *e = static_cast(item); + char const *sc = e->name; + sc += strlen(e->name) + 1; + int pos = snprintf(buffer, max, "%s %s (%s)", + *(e->patch) ? "[on ]" : "[off]", e->name, sc); + return pos; +} + +PRIVATE static inline +unsigned +Jdb_log_list::patch_val(Tb_log_table_entry const *e) +{ return (e - _log_table) + Tbuf_dynentries; } + +PRIVATE static +Tb_log_table_entry * +Jdb_log_list::find_next_log(const char *name, const char *sc, + Tb_log_table_entry *i) +{ + for (; i < _end; ++i) + if ( !strcmp(name, i->name) + || !strcmp(sc, i->name + strlen(i->name) + 1)) + return i; + return 0; +} + +PUBLIC +bool +Jdb_log_list::enter_item(void *item) const +{ + Tb_log_table_entry const *e = static_cast(item); + patch_item(e, *(e->patch) ? 0 : patch_val(e)); + return true; +} + +PRIVATE static +void +Jdb_log_list::patch_item(Tb_log_table_entry const *e, unsigned char val) +{ + if (e->patch) + { + *(e->patch) = val; + Mem_unit::clean_dcache(e->patch); + } + + for (Tb_log_table_entry *x = _end; x < &_log_table_end; ++x) + { + if (equal(x, e) && x->patch) + { + *(x->patch) = val; + Mem_unit::clean_dcache(x->patch); + } + } +} + +PRIVATE static +bool +Jdb_log_list::equal(Tb_log_table_entry const *a, Tb_log_table_entry const *b) +{ + if (strcmp(a->name, b->name)) + return false; + + char const *sca = a->name; sca += strlen(sca) + 1; + char const *scb = b->name; scb += strlen(scb) + 1; + + if (strcmp(sca, scb)) + return false; + + return a->fmt == b->fmt; +} + +PRIVATE +bool +Jdb_log_list::next(void **item) +{ + Tb_log_table_entry *e = static_cast(*item); + + while (e + 1 < &_log_table_end) + { +#if 0 + if (equal(e, e+1)) + ++e; + else +#endif + { + *item = e+1; + return true; + } + } + + return false; +} + +PRIVATE +bool +Jdb_log_list::pref(void **item) +{ + Tb_log_table_entry *e = static_cast(*item); + + if (e > _log_table) + --e; + else + return false; +#if 0 + while (e > _log_table) + { + if (equal(e, e-1)) + --e; + else + break; + } +#endif + + *item = e; + return true; +} + +PUBLIC +int +Jdb_log_list::seek(int cnt, void **item) +{ + Tb_log_table_entry *e = static_cast(*item); + if (cnt > 0) + { + if (e + cnt >= _end) + cnt = _end - e - 1; + } + else if (cnt < 0) + { + if (e + cnt < _log_table) + cnt = _log_table - e; + } + + if (cnt) + { + *item = e + cnt; + return cnt; + } + + return 0; +} + +class Jdb_log : public Jdb_module +{ +public: + Jdb_log() FIASCO_INIT; +private: +}; + + +static void swap(Tb_log_table_entry *a, Tb_log_table_entry *b) +{ + Tb_log_table_entry x = *a; + *a = *b; + *b = x; +} + +static bool lt_cmp(Tb_log_table_entry *a, Tb_log_table_entry *b) +{ + if (strcmp(a->name, b->name) < 0) + return true; + else + return false; +} + +static void sort_tb_log_table() +{ + for (Tb_log_table_entry *p = _log_table; p < &_log_table_end; ++p) + { + for (Tb_log_table_entry *x = &_log_table_end -1; x > p; --x) + if (lt_cmp(x, x - 1)) + swap(x - 1, x); + } +} + +PUBLIC +static +void +Jdb_log_list::move_dups() +{ + _end = &_log_table_end; + Tb_log_table_entry *const tab_end = &_log_table_end; + for (Tb_log_table_entry *p = _log_table + 1; p < _end;) + { + if (equal(p-1, p)) + { + --_end; + if (p < _end) + { + Tb_log_table_entry tmp = *p; + memmove(p, p + 1, sizeof(Tb_log_table_entry) * (tab_end - p - 1)); + *(tab_end - 1) = tmp; + } + else + break; + } + else + ++p; + } +} + +#if 0 +static void disable_all() +{ + for (Tb_log_table_entry *p = _log_table; p < _log_table_end; ++p) + *(p->patch) = 0; +} +#endif + + +IMPLEMENT +Jdb_log::Jdb_log() + : Jdb_module("MONITORING") +{ + //disable_all(); + sort_tb_log_table(); + Jdb_log_list::move_dups(); + + static Jdb_log_list_hdl hdl; + Jdb_kobject::module()->register_handler(&hdl); +} + +PUBLIC +Jdb_module::Action_code +Jdb_log::action(int, void *&, char const *&, int &) +{ + if (_log_table >= &_log_table_end) + return NOTHING; + + Jdb_log_list list; + list.set_start(_log_table); + list.do_list(); + + return NOTHING; +} + +PUBLIC +Jdb_module::Cmd const * +Jdb_log::cmds() const +{ + static Cmd cs[] = + { + { 0, "O", "log", "", "O\tselect log events", 0 }, + }; + return cs; +} + +PUBLIC +int +Jdb_log::num_cmds() const +{ return 1; } + +static Jdb_log jdb_log INIT_PRIORITY(JDB_MODULE_INIT_PRIO); + diff --git a/kernel/fiasco/src/jdb/jdb_mapdb.cpp b/kernel/fiasco/src/jdb/jdb_mapdb.cpp new file mode 100644 index 00000000..1f8abbc3 --- /dev/null +++ b/kernel/fiasco/src/jdb/jdb_mapdb.cpp @@ -0,0 +1,544 @@ +IMPLEMENTATION: + +#include + +#include "jdb.h" +#include "jdb_input.h" +#include "jdb_screen.h" +#include "kernel_console.h" +#include "kobject.h" +#include "keycodes.h" +#include "mapdb.h" +#include "mapdb_i.h" +#include "map_util.h" +#include "simpleio.h" +#include "static_init.h" +#include "task.h" +#include "jdb_kobject.h" +#include "jdb_kobject_names.h" + +class Jdb_mapdb : public Jdb_module +{ + friend class Jdb_kobject_mapdb_hdl; +public: + Jdb_mapdb() FIASCO_INIT; +private: + static Mword pagenum; + static char subcmd; +}; + +char Jdb_mapdb::subcmd; +Mword Jdb_mapdb::pagenum; + +static +const char* +size_str (Mword size) +{ + static char scratchbuf[6]; + unsigned mult = 0; + while (size >= 1024) + { + size >>= 10; + mult++; + } + snprintf (scratchbuf, 6, "%u%c", unsigned(size), "BKMGTPX"[mult]); + return scratchbuf; +} + +static +bool +Jdb_mapdb::show_tree(Treemap* pages, Page_number address, + unsigned &screenline, unsigned indent = 1) +{ + Page_number page = address >> pages->_page_shift; + Physframe* f = pages->frame(page); + Mapping_tree* t = f->tree.get(); + unsigned i; + int c; + + if (! t) + { + printf(" no mapping tree registered for frame number 0x%x\033[K\n", + (unsigned) page.value()); + screenline++; + return true; + } + + printf(" mapping tree for %s-page " L4_PTR_FMT " of task %p - header at " + L4_PTR_FMT "\033[K\n", + size_str (1UL << pages->_page_shift), + pages->vaddr(t->mappings()).value(), t->mappings()[0].space(), (Address)t); +#ifdef NDEBUG + // If NDEBUG is active, t->_empty_count is undefined + printf(" header info: " + "entries used: %u free: -- total: %u lock=%u\033[K\n", + t->_count, t->number_of_entries(), + f->lock.test()); + + if (t->_count > t->number_of_entries()) + { + printf("\033[K\n" + "\033[K\n" + " seems to be a wrong tree ! ...exiting"); + // clear rest of page + for (i=6; i_count, t->_empty_count, t->number_of_entries(), + f->lock.test()); + + if (unsigned (t->_count) + t->_empty_count > t->number_of_entries()) + { + printf("\033[K\n" + "\033[K\n" + " seems to be a wrong tree ! ...exiting"); + // clear rest of page + for (i=6; imappings(); + + screenline += 2; + + for (i=0; i < t->_count; i++, m++) + { + Kconsole::console()->getchar_chance(); + + if (m->depth() == Mapping::Depth_submap) + printf("%*u: %lx subtree@" L4_PTR_FMT, + indent + m->parent()->depth() > 10 + ? 0 : indent + m->parent()->depth(), + i+1, (Address) m->data(), (Mword) m->submap()); + else + { + printf("%*u: %lx va=" L4_PTR_FMT " task=%lx depth=", + indent + m->depth() > 10 ? 0 : indent + m->depth(), + i+1, (Address) m->data(), + pages->vaddr(m).value(), + Kobject_dbg::pointer_to_id(m->space())); + + if (m->depth() == Mapping::Depth_root) + printf("root"); + else if (m->depth() == Mapping::Depth_empty) + printf("empty"); + else if (m->depth() == Mapping::Depth_end) + printf("end"); + else + printf("%lu", static_cast(m->depth())); + } + + puts("\033[K"); + screenline++; + + if (screenline >= (m->depth() == Mapping::Depth_submap + ? Jdb_screen::height() - 3 + : Jdb_screen::height())) + { + printf(" any key for next page or "); + Jdb::cursor(screenline, 33); + c = Jdb_core::getchar(); + printf("\r\033[K"); + if (c == KEY_ESC) + return false; + screenline = 3; + Jdb::cursor(3, 1); + } + + if (m->depth() == Mapping::Depth_submap) + { + if (! Jdb_mapdb::show_tree(m->submap(), + address.offset(Page_count::create(1UL << pages->_page_shift)), + screenline, indent + m->parent()->depth())) + return false; + } + } + + return true; +} + +static +Address +Jdb_mapdb::end_address (Mapdb* mapdb) +{ + return mapdb->_treemap->end_addr().value(); +} + +static +void +Jdb_mapdb::show (Page_number page, char which_mapdb) +{ + unsigned j; + int c; + + Jdb::clear_screen(); + + for (;;) + { + Mapdb* mapdb; + const char* type; + Mword page_shift; + Page_count super_inc; + + switch (which_mapdb) + { + case 'm': + type = "Phys frame"; + mapdb = mapdb_mem.get(); + page_shift = 0; //Config::PAGE_SHIFT; + super_inc = Page_count::create(Config::SUPERPAGE_SIZE / Config::PAGE_SIZE); + break; +#ifdef CONFIG_IO_PROT + case 'i': + type = "I/O port"; + mapdb = mapdb_io.get(); + page_shift = 0; + super_inc = Page_count::create(0x100); + break; +#endif + default: + return; + } + + if (! mapdb->valid_address (page << page_shift)) + page = Page_number::create(0); + + Jdb::cursor(); + printf ("%s " L4_PTR_FMT "\033[K\n\033[K\n", + type, page.value() << page_shift); + + j = 3; + + if (! Jdb_mapdb::show_tree (mapdb->_treemap, + (page << page_shift) + - mapdb->_treemap->_page_offset, + j)) + return; + + for (; jvalid_address(++page << page_shift)) + page = Page_number::create(0); + redraw = true; + break; + case 'p': + case KEY_CURSOR_UP: + if (! mapdb->valid_address(--page << page_shift)) + page = Page_number::create(end_address (mapdb) - 1) >> page_shift; + redraw = true; + break; + case 'N': + case KEY_PAGE_DOWN: + page = (page + super_inc).trunc(super_inc); + if (! mapdb->valid_address(page << page_shift)) + page = Page_number::create(0); + redraw = true; + break; + case 'P': + case KEY_PAGE_UP: + page = (page - super_inc).trunc(super_inc); + if (! mapdb->valid_address(page << page_shift)) + page = Page_number::create(end_address (mapdb) - 1) >> page_shift; + redraw = true; + break; + case ' ': + if (which_mapdb == 'm') +#ifdef CONFIG_IO_PROT + which_mapdb = 'i'; + else if (which_mapdb == 'i') +#endif + which_mapdb = 'm'; + redraw = true; + break; + case KEY_ESC: + Jdb::abort_command(); + return; + default: + if (Jdb::is_toplevel_cmd(c)) + return; + } + } + } +} + +PUBLIC +Jdb_module::Action_code +Jdb_mapdb::action(int cmd, void *&args, char const *&fmt, int &next_char) +{ + static char which_mapdb = 'm'; + + if (cmd == 1) + { + dump_all_cap_trees(); + return NOTHING; + } + + if (cmd != 0) + return NOTHING; + + if (args == (void*) &subcmd) + { + switch (subcmd) + { + default: + return NOTHING; + + case '\r': + case ' ': + goto doit; + + case '0' ... '9': + case 'a' ... 'f': + case 'A' ... 'F': + which_mapdb = 'm'; + fmt = " frame: " L4_FRAME_INPUT_FMT; + args = &pagenum; + next_char = subcmd; + return EXTRA_INPUT_WITH_NEXTCHAR; + + case 'm': + fmt = " frame: " L4_FRAME_INPUT_FMT; + break; + +#ifdef CONFIG_IO_PROT + case 'i': + fmt = " port: " L4_FRAME_INPUT_FMT; + break; +#endif + + case 'o': + fmt = " object: %x"; + break; + } + + which_mapdb = subcmd; + args = &pagenum; + return EXTRA_INPUT; + } + + else if (args != (void*) &pagenum) + return NOTHING; + + doit: + if (which_mapdb == 'o') + Jdb_mapdb::show_simple_tree((Kobject_common*)pagenum); + else + show(Page_number::create(pagenum), which_mapdb); + return NOTHING; +} + +PUBLIC +Jdb_module::Cmd const * +Jdb_mapdb::cmds() const +{ + static Cmd cs[] = + { + { 0, "m", "mapdb", "%c", + "m[it]\tshow [I/O,task] mapping database starting at address", + &subcmd }, + { 1, "", "dumpmapdbobjs", "", + "dumpmapdbobjs\tDump complete object mapping database", 0 }, + }; + return cs; +} + +PUBLIC +int +Jdb_mapdb::num_cmds() const +{ + return 2; +} + +IMPLEMENT +Jdb_mapdb::Jdb_mapdb() + : Jdb_module("INFO") +{} + +static Jdb_mapdb jdb_mapdb INIT_PRIORITY(JDB_MODULE_INIT_PRIO); + +// -------------------------------------------------------------------------- +// Handler for kobject list + +class Jdb_kobject_mapdb_hdl : public Jdb_kobject_handler +{ +public: + Jdb_kobject_mapdb_hdl() : Jdb_kobject_handler(0) {} + virtual bool show_kobject(Kobject_common *, int) { return true; } + virtual ~Jdb_kobject_mapdb_hdl() {} +}; + +PUBLIC static FIASCO_INIT +void +Jdb_kobject_mapdb_hdl::init() +{ + static Jdb_kobject_mapdb_hdl hdl; + Jdb_kobject::module()->register_handler(&hdl); +} + +PUBLIC +bool +Jdb_kobject_mapdb_hdl::handle_key(Kobject_common *o, int keycode) +{ + if (keycode == 'm') + { + Jdb_mapdb::show_simple_tree(o); + Jdb::getchar(); + return true; + } + else + return false; +} + + + +STATIC_INITIALIZE(Jdb_kobject_mapdb_hdl); + +#if 0 // keep this for reanimation +static +void +Jdb_mapdb::dump_all_cap_trees() +{ + printf("========= OBJECT DUMP BEGIN ===================\n"); + Kobject *f = static_cast(Kobject::_jdb_head.get_unused()); + for (; f; f = static_cast(f->_next)) + { + char s[130]; + + Jdb_kobject::obj_description(s, sizeof(s), true, f); + s[sizeof(s) - 1] = 0; + printf("%s", s); + + Mapping_tree *t = f->tree.get(); + + if (!t) + { + printf("\n"); + continue; + } + + Mapping *m = t->mappings(); + + printf(" intask="); + for (int i = 0; i < t->_count; i++, m++) + { + if (m->depth() == Mapping::Depth_submap) + printf("%s[subtree]", i ? "," : ""); + else + printf("%s[%lx:%d]", + i ? "," : "", Kobject::pointer_to_id(m->space()), + m->depth()); + } + printf("\n"); + + if (m->depth() == Mapping::Depth_submap) + { + printf("not good, submap in simple mapping tree\n"); + } + } + printf("========= OBJECT DUMP END ===================\n"); +} +#endif + +// -------------------------------------------------------------------------- +IMPLEMENTATION: + +#include "dbg_page_info.h" + +static +bool +Jdb_mapdb::show_simple_tree(Kobject_common *f, unsigned indent = 1) +{ + (void)indent; + (void)f; + + unsigned screenline = 0; + int c; + + puts(Jdb_screen::Line); + if (!f || f->map_root()->_root.empty()) + { + printf(" no mapping tree registered for frame number 0x%lx\033[K\n", + (unsigned long) f); + screenline++; + puts(Jdb_screen::Line); + return true; + } + + printf(" mapping tree for object D:%lx (%p) ref_cnt=%ld\n", + f->dbg_info()->dbg_id(), f, f->map_root()->_cnt); + + screenline += 2; + + for (Obj::Mapping::List::Iterator m = f->map_root()->_root.begin(); + m != f->map_root()->_root.end(); ++m) + { + Kconsole::console()->getchar_chance(); + + Obj::Entry *e = static_cast(*m); + Dbg_page_info *pi = Dbg_page_info::table()[Virt_addr(e)]; + + Mword space_id = ~0UL; + Address cap_idx = ((Address)e % Config::PAGE_SIZE) / sizeof(Obj::Entry); + + if (pi) + { + space_id = static_cast(pi->info()->s)->dbg_info()->dbg_id(); + cap_idx += pi->info()->offset; + } + + printf(" " L4_PTR_FMT "[C:%lx]: space=D:%lx rights=%x flags=%lx obj=%p", + (Address)*m, cap_idx, space_id, (unsigned)e->rights(), e->_flags, + e->obj()); + + puts("\033[K"); + screenline++; + + if (screenline >= Jdb_screen::height()) + { + printf(" any key for next page or "); + Jdb::cursor(screenline, 33); + c = Jdb_core::getchar(); + printf("\r\033[K"); + if (c == KEY_ESC) + return false; + screenline = 3; + Jdb::cursor(3, 1); + } + } + + puts(Jdb_screen::Line); + + + + return true; +} + +static +void +Jdb_mapdb::dump_all_cap_trees() +{ + printf("========= OBJECT DUMP BEGIN ===================\n"); + printf("========= OBJECT DUMP END ===================\n"); +} + + diff --git a/kernel/fiasco/src/jdb/jdb_module.cpp b/kernel/fiasco/src/jdb/jdb_module.cpp new file mode 100644 index 00000000..8a649c24 --- /dev/null +++ b/kernel/fiasco/src/jdb/jdb_module.cpp @@ -0,0 +1,427 @@ +INTERFACE: + +#include +#include +#include + +#include "initcalls.h" + +class Jdb_category; + +/** + * Base class for any kernel debugger module. + * + * This class is the base for any module of the + * modularized Jdb. Ths idea is that Jdb can be + * extended by plugging in a new module, which + * provides one ore more commands and their + * implementations to Jdb. + * + * A new module can be created by + * deriving from Jdb_module and providing the neccessary + * methods (num_cmds, cmds, action, and maybe the + * constructor). To plug the module into Jdb a static + * instance of the module must be created, with + * "INIT_PRIORITY(JDB_MODULE_INIT_PRIO)". + * + */ +class Jdb_module : public cxx::H_list_item +{ +public: + + /** + * A Jdb command description. + * + * A Jdb_module provides an array of such Cmd + * structures, where each structure describes + * one command. + */ + struct Cmd { + /** + * The unique ID of the command within the module. + * + * This ID is handed to action(). + */ + int id; + + /** + * The short command. + */ + char const *scmd; + + /** + * The normal (long) command. + */ + char const *cmd; + + /** + * The command format (possible options). + * + * This format string is somewhat like a "scanf" + * format. It may contain normal text interleaved with + * input format descriptions (like \%c). After the Jdb core + * recognized the command the format string is printed + * up to the first format descriptor, then input according + * to the given format is requested, after this input the + * procedure is repeated until there are no more format + * descriptors and action() is called. + * + * The values read via the format input are stored into + * Cmd::argbuf, which must provide enough space for storing + * all the data according to the whole format string. + * + * Format descriptors:\n + * A format descriptor always starts with \%; the \% may be + * followed by an unsigned decimal number (len argument) which + * specifies the maximum number of characters to read. + * The integer formats ('d', 'i', 'o', 'u', 'X', and 'x') may be prefixed + * with one or two 'l's, for reading "long int" or "long long int". + * + * The integer read formats require an int, long int, or long long int + * sized buffer according to the number of 'l' modifiers; for the others + * see the respective format description. + * + * @li '\%' print the "\%" character + * @li 'i' read an integer (optionally as hexadecimal number, + * if it starts with "0x" or as octal number, if it + * starts with "0") + * @li 'p' read a pointer in hexadecimal format ('void*' buffer) + * @li 'o' read an octal integer + * @li 'X', 'x' read a hexadecimal integer + * @li 'd' read a decimal (optionally signed) integer + * @li 'u' read a decimal unsigned integer + * @li 'c' read a character and continue immediately ('char' + * buffer) + * @li 's' read a string (the len argument must be given) + * ('char[len]' buffer) + * + */ + char const *fmt; + + /** + * The description of the command. + * + * The description of a command must contain the command + * syntax itself and followed by "\\t" the description. + * If more than one line is needed "\\n" can be used to switch + * to a new line and "\\t" again to align the description. + */ + char const *descr; + + /** + * The buffer for the read arguments. + * + * This buffer is used to store the data read via the + * format description (see Cmd::fmt). + */ + void *argbuf; + + /** + * Creates a Jdb command. + * @param _id command ID (see Cmd::id) + * @param _scmd short command (see Cmd::scmd) + * @param _cmd long command (see Cmd::cmd) + * @param _fmt input format (see Cmd::fmt) + * @param _descr command description (see Cmd::descr) + * @param _argbuf pointer to argument buffer (see Cmd::argbuf) + */ + }; + + /** + * Possible return codes from action(). + * + * The actual handler of the Jdb_module (action()) + * may return any value of this type. + * + */ + enum Action_code { + + /// Do nothing, wait for the next command. + NOTHING = 0, + + /// Leave the kernel debugger + LEAVE, + + /// got KEY_HOME + GO_BACK, + + /// there was an error (abort or invalid input) + ERROR, + + /** + * Wait for new input arguments + * @see action() for detailed information. + */ + EXTRA_INPUT, + + /** + * Wait for new input arguments and interpret character + * in next_char as next keystroke + * @see action() for detailed information. + */ + EXTRA_INPUT_WITH_NEXTCHAR, + }; + + typedef void (Gotkey)(char *&str, int maxlen, int c); + + /** + * Create a new instance of an Jdb_module. + * @param category the name of the category the module + * fits in. This category must exist (see + * Jdb_category) or the module is added to the + * "MISC" category. + * + * This constructor automatically registers the module at the + * Jdb_core. The derived modules must provide an own constructor + * if another category than "MISC" should be used. + * + * @see Jdb_core + * @see Jdb_category + * + */ + Jdb_module(char const *category = "MISC") FIASCO_INIT; + + /// dtor + virtual ~Jdb_module() = 0; + + /** + * The actual handler of the module. + * @param cmd the command ID (see Cmd::id) of the executed command. + * @param args a reference to the argument buffer pointer. + * @param fmt a reference to the format string pointer. + * + * This method is pure virtual and must be provided by the + * specific derivate of the Jdb_module. action() is called + * if one of the module's commands was issued and the input + * according to the format string is read. + * + * The args and fmt arguments are references because they may + * be modified by the action() method and extra input may be + * requested by returning Action_code::EXTRA_INPUT. In the + * case where Action_code::EXTRA_INPUT is returned the Jdb_core + * reads again the values according to the given format (fmt) + * and enters action(). With this mechanism it is possible to + * request further input depending on the already given input. + * + */ + virtual Action_code action(int cmd, void *&args, char const* &fmt, + int &next_char) = 0; + + /** + * The number of commands this modules provides. + * + * This method must return how many Cmd structures can be + * found in the array returned by cmds(). + * + * @see cmds() + * + */ + virtual int num_cmds() const = 0; + + /** + * The commands this module provides. + * + * An array of Cmd structures must be returned, + * where each entry describes a single command. + * The command IDs (see Cmd::id) should be unique + * within the module, so that action() can distinguish + * between the different commands. + * + * @see num_cmds() + * @see Cmd + * @see action() + */ + virtual Cmd const * cmds() const = 0; + + /** + * Get the category of this module. + */ + Jdb_category const *category() const; + + /** + * Get Cmd structure according to cmd. + * @param cmd the command you are looking for. + * @param short_mode if true the short commands are looked up + * (see Cmd::scmd). + * @return A pointer to the Cmd structure if the command is + * found, or a null pointer otherwise. + */ + Cmd const* has_cmd( char const* cmd, bool short_mode = false, + bool full = true) const; + + typedef cxx::H_list_bss List; + static List modules; + +private: + Jdb_category const *_cat; +}; + +/** + * A category that may contain some Jdb_modules. + * + * Each registered Jdb_module must be a member of one + * category. The help-module Help_m uses this categories + * for displaying sorted help. + * + */ +class Jdb_category : public cxx::S_list_item +{ +public: + /** + * Create a new category. + * @param name the name of the new category, also used + * at Jdb_module creation (see Jdb_module::Jdb_module()) + * @param desc the short description of this category. + * @param order the ordering number of the category. + */ + Jdb_category(char const *name, char const *desc, + unsigned order = 0 ) FIASCO_INIT; + + /** + * Get the name of this category. + */ + char const * name() const; + + /** + * Get the description of this category. + */ + char const * description() const; + +public: + + /** + * Look for the category with the given name. + * @param name the name of the category you are lokking for. + * @param _default if set to true the default ("MISC") + * category is returned if no category with the given + * name is found. + * + */ + static Jdb_category *find(char const *name, bool _default = false); + + typedef cxx::S_list_bss List; + static List categories; + +private: + char const *const _name; + char const *const _desc; + unsigned const _order; +}; + + +IMPLEMENTATION: + +#include +#include + +#include "static_init.h" + +Jdb_category::List Jdb_category::categories; +Jdb_module::List Jdb_module::modules; + +static Jdb_category INIT_PRIORITY(JDB_CATEGORY_INIT_PRIO) + misc_cat("MISC", "misc debugger commands", 2000); + +IMPLEMENT +Jdb_category::Jdb_category(char const *const name, + char const *const desc, + unsigned order) + : _name(name), _desc(desc), _order(order) +{ + List::Iterator c = categories.begin(); + + for (; c != categories.end(); ++c) + if (c->_order >= order) + break; + categories.insert_before(this, c); +} + +IMPLEMENT inline +char const * Jdb_category::name() const +{ + return _name; +} + +IMPLEMENT inline +char const * Jdb_category::description() const +{ + return _desc; +} + +IMPLEMENT +Jdb_category *Jdb_category::find(char const* name, bool _default) +{ + List::Const_iterator a; + for (a = categories.begin(); + a != categories.end() && strcmp(a->name(), name) != 0; ++a) + ; + + if (_default && a == categories.end()) + return &misc_cat; + + return *a; +} + + +IMPLEMENT +Jdb_module::Jdb_module(char const *category) + : _cat(Jdb_category::find(category, true)) +{ + modules.push_front(this); +} + +IMPLEMENT inline Jdb_module::~Jdb_module() {} + +PUBLIC static +bool +Jdb_module::match(char const *cmd, char const *match, bool full = true) +{ + if (!cmd || !*cmd || !match) + return false; + + while (*cmd && *match && *match != ' ') + { + if (*cmd != *match) + return false; + + ++cmd; + ++match; + } + + if ((!*match || *match == ' ') && !*cmd) + return true; + + if (!full && !*match) + return true; + + return false; +} + +IMPLEMENT +Jdb_module::Cmd const* +Jdb_module::has_cmd(char const* cmd, bool short_mode, bool full) const +{ + int n = num_cmds(); + Cmd const* cs = cmds(); + for (int i = 0; i < n; ++i) + { + if (short_mode) + { + if (match(cs[i].scmd, cmd)) + return cs + i; + } + else + { + if (match(cs[i].cmd, cmd, full)) + return cs + i; + } + } + + return 0; +} + +IMPLEMENT inline +Jdb_category const * +Jdb_module::category() const +{ return _cat; } + diff --git a/kernel/fiasco/src/jdb/jdb_mp_request_sl.cpp b/kernel/fiasco/src/jdb/jdb_mp_request_sl.cpp new file mode 100644 index 00000000..2e4dcd6f --- /dev/null +++ b/kernel/fiasco/src/jdb/jdb_mp_request_sl.cpp @@ -0,0 +1,147 @@ +IMPLEMENTATION [mp]: + +#include +#include "simpleio.h" + +#include "jdb.h" +#include "jdb_module.h" +#include "static_init.h" +#include "types.h" +#include "mp_request.h" + + +class Jdb_mp_request_module : public Jdb_module +{ + typedef Mp_request_queue::Fifo Fifo; + typedef Fifo::Item Item; +public: + Jdb_mp_request_module() FIASCO_INIT; + struct Find_cpu + { + Item const *r; + mutable unsigned cpu; + Find_cpu(Item const *i) : r(i), cpu(~0U) {} + void operator()(unsigned _cpu) const + { + if (&Mp_request_queue::rq.cpu(_cpu) == r) + { + cpu = _cpu; + return; + } + } + }; +}; + +static Jdb_mp_request_module jdb_mp_request_module INIT_PRIORITY(JDB_MODULE_INIT_PRIO); + +PRIVATE static +unsigned +Jdb_mp_request_module::find_cpu(Item const *r) +{ + if (!r) + return 0; + + Find_cpu _find_cpu(r); + Jdb::foreach_cpu(_find_cpu); + return _find_cpu.cpu; +} + +PRIVATE static +void +Jdb_mp_request_module::print_request(Item const *item) +{ + printf(" Request item of cpu %u [%p]:\n" + " value = { func = %p, arg = %p, _lock=%lu }\n" + " next = %p (cpu %u)\n", + find_cpu(item), item, item->value.func, item->value.arg, item->value._lock, + item->next, find_cpu(item->next)); +} + +PRIVATE static +void +Jdb_mp_request_module::print_queue(unsigned cpu) +{ + + if (!Jdb::cpu_in_jdb(cpu)) + { + bool online = Cpu::online(cpu); + if (!online) + { + printf("CPU %u is not online...\n", cpu); + return; + } + printf("CPU %u has not entered JDB (try to display queue...\n", cpu); + } + + Item const *item = &Mp_request_queue::rq.cpu(cpu); + Fifo const *fifo = &Mp_request_queue::fifo.cpu(cpu); + + + printf("CPU[%2u]: Mp request item @%p, Mp request FIFO @%p\n" + " Local queue Item:\n", + cpu, item, fifo); + + print_request(item); + + printf(" Request FIFO: head = %p(%u), tail = { %p(%u) }\n", + fifo->_head, find_cpu(fifo->_head), + fifo->_tail, find_cpu(fifo->_tail)); + + item = fifo->_head; + while (item) + { + print_request(item); + item = item->next; + } + + puts(""); +} + +PUBLIC +Jdb_module::Action_code +Jdb_mp_request_module::action (int cmd, void *&argbuf, char const *&fmt, int &next) +{ + char const *c = (char const *)argbuf; + unsigned cpu; + if (cmd!=0) + return NOTHING; + + if (argbuf != &cpu) + { + if (*c == 'a') + Jdb::foreach_cpu(&print_queue); + else if (*c >= '0' && *c <= '9') + { + next = *c; argbuf = &cpu; fmt = "%i"; + return EXTRA_INPUT_WITH_NEXTCHAR; + } + } + else + print_queue(cpu); + + return NOTHING; +} + +PUBLIC +int +Jdb_mp_request_module::num_cmds() const +{ + return 1; +} + +PUBLIC +Jdb_module::Cmd const * +Jdb_mp_request_module::cmds() const +{ + static char c; + static Cmd cs[] = + { { 0, "", "mpqueue", "%C", "mpqueue all|\tdump X-CPU " + "request queues", &c } }; + + return cs; +} + +IMPLEMENT +Jdb_mp_request_module::Jdb_mp_request_module() + : Jdb_module("INFO") +{} diff --git a/kernel/fiasco/src/jdb/jdb_obj_space.cpp b/kernel/fiasco/src/jdb/jdb_obj_space.cpp new file mode 100644 index 00000000..26e2fb35 --- /dev/null +++ b/kernel/fiasco/src/jdb/jdb_obj_space.cpp @@ -0,0 +1,262 @@ +IMPLEMENTATION: + +#include + +#include "config.h" +#include "jdb.h" +#include "jdb_screen.h" +#include "jdb_table.h" +#include "jdb_kobject.h" +#include "kernel_console.h" +#include "kmem.h" +#include "keycodes.h" +#include "space.h" +#include "task.h" +#include "thread_object.h" +#include "static_init.h" +#include "types.h" + + +class Jdb_obj_space : public Jdb_table, public Jdb_kobject_handler +{ +public: + enum Mode + { + Name, + Raw, + End_mode + }; + +private: + Address _base; + Space *_task; + Mode _mode; + + bool show_kobject(Kobject_common *, int) { return false; } + +}; + +static inline +Jdb_obj_space::Mode +operator ++ (Jdb_obj_space::Mode &m) +{ + long _m = m; + ++_m; + if (_m >= Jdb_obj_space::End_mode) + _m = 0; + + m = Jdb_obj_space::Mode(_m); + + return m; +} + +//char Jdb_obj_space_m::first_char; + +PUBLIC +Jdb_obj_space::Jdb_obj_space(Address base = 0, int level = 0) +: Jdb_kobject_handler(0), + _base(base), + _task(0), + _mode(Name) +{ + (void)level; + Jdb_kobject::module()->register_handler(this); +} + +PUBLIC +unsigned +Jdb_obj_space::col_width(unsigned column) const +{ + if (column == 0) + return Jdb_screen::Col_head_size; + else + return 16; +} + +PUBLIC +unsigned long +Jdb_obj_space::cols() const +{ + return 5; +} + +PUBLIC +unsigned long +Jdb_obj_space::rows() const +{ return Obj_space::Map_max_address / (cols()-1); } + +PUBLIC +void +Jdb_obj_space::print_statline(unsigned long row, unsigned long col) +{ + static char buf[128]; + unsigned rights; + + Kobject_iface *o = item(index(row,col), &rights); + if (!o) + { + Jdb::printf_statline("objs", "=mode", "%lx: -- INVALID --", + index(row,col)); + return; + } + + unsigned len = Jdb_kobject::obj_description(buf, sizeof(buf), true, o->dbg_info()); + Jdb::printf_statline("objs", "=mode", + "%lx: %-*s", index(row,col), len, buf); +} + +PUBLIC +void +Jdb_obj_space::print_entry(Address entry) +{ + unsigned rights; + Kobject_iface *o = item(entry, &rights); + + if (!o) + printf(" -- "); + else + { + char r = '-'; + switch (_mode) + { + case Name: + switch (rights) + { + case L4_fpage::WX: r = '*'; break; + case L4_fpage::W: r = 'w'; break; + case L4_fpage::X: r = 'x'; break; + } + printf("%05lx%c %-*s", o->dbg_info()->dbg_id(), r, 9, Jdb_kobject::kobject_type(o)); + break; + case Raw: + default: + printf("%16lx", Mword(o) | rights); + break; + } + } +} + +PUBLIC +void +Jdb_obj_space::draw_entry(unsigned long row, unsigned long col) +{ + if (col==0) + printf("%06lx ", index(row, 1)); + else + print_entry(index(row, col)); +} + +PRIVATE +Address +Jdb_obj_space::index(unsigned long row, unsigned long col) +{ + Mword e = (col-1) + (row * (cols()-1)); + return _base + e; +} + +PRIVATE +bool +Jdb_obj_space::handle_user_keys(int c, Kobject_iface *o) +{ + if (!o) + return false; + + bool handled = false; + for (Jdb_kobject::Handler_iter h = Jdb_kobject::module()->global_handlers.begin(); + h != Jdb_kobject::module()->global_handlers.end(); ++h) + handled |= h->handle_key(o, c); + + if (Jdb_kobject_handler *h = Jdb_kobject::module()->find_handler(o)) + handled |= h->handle_key(o, c); + + return handled; +} + + +PUBLIC +unsigned +Jdb_obj_space::key_pressed(int c, unsigned long &row, unsigned long &col) +{ + switch (c) + { + default: + { + unsigned rights; + if (handle_user_keys(c, item(index(row, col), &rights))) + return Redraw; + return Nothing; + } + + case KEY_CURSOR_HOME: // return to previous or go home + return Back; + + case ' ': + ++_mode; + return Redraw; + } +} + +PUBLIC +bool +Jdb_obj_space::handle_key(Kobject_common *o, int code) +{ + if (code != 'o') + return false; + + Space *t = Kobject::dcast(o); + if (!t) + { + Thread *th = Kobject::dcast(o); + if (!th || !th->space()) + return false; + + t = th->space(); + } + + _task = t; + show(0,0); + + return true; +} + +static Jdb_obj_space jdb_obj_space INIT_PRIORITY(JDB_MODULE_INIT_PRIO); + +// ------------------------------------------------------------------------ +IMPLEMENTATION [obj_space_virt]: + +PUBLIC +Kobject_iface * +Jdb_obj_space::item(Address entry, unsigned *rights) +{ + Mword dummy; + Obj_space::Capability *c = _task->cap_virt(entry); + if (!c) + return 0; + + Mword mapped = Jdb::peek((Mword*)c, _task, dummy); + + if (!mapped) + return 0; + + Kobject_iface *o = (Kobject_iface*)(dummy & ~3UL); + *rights = dummy & 3; + + return o; +} + +// ------------------------------------------------------------------------ +IMPLEMENTATION [obj_space_phys]: +PUBLIC +Kobject_iface * +Jdb_obj_space::item(Address entry, unsigned *rights) +{ + Obj_space::Capability *c = _task->get_cap(entry); + + if (!c) + return 0; + + Kobject_iface *o = c->obj(); + *rights = c->rights(); + + return o; +} diff --git a/kernel/fiasco/src/jdb/jdb_pic.cpp b/kernel/fiasco/src/jdb/jdb_pic.cpp new file mode 100644 index 00000000..768d2652 --- /dev/null +++ b/kernel/fiasco/src/jdb/jdb_pic.cpp @@ -0,0 +1,89 @@ +IMPLEMENTATION: + +#include + +#include "pic.h" +#include "jdb_module.h" +#include "jdb_handler_queue.h" +#include "static_init.h" +#include "types.h" + + +//=================== +// Std JDB modules +//=================== + +/** + * 'IRQ' module. + * + * This module handles the 'R' command that + * provides IRQ attachment and listing functions. + */ +class Jdb_pic + : public Jdb_module +{ +}; + +static Jdb_pic jdb_pic INIT_PRIORITY(JDB_MODULE_INIT_PRIO); + +static Pic::Status pic_state; + +PRIVATE static +void Jdb_pic::at_enter() +{ + pic_state = Pic::disable_all_save(); +} + +PRIVATE static +void Jdb_pic::at_leave() +{ + Pic::restore_all(pic_state); +} + +PUBLIC +Jdb_pic::Jdb_pic() +{ + static Jdb_handler enter(at_enter); + static Jdb_handler leave(at_leave); + register_handlers(enter,leave); +} + + +PUBLIC Jdb_module::Action_code +Jdb_pic::action( int cmd, void *&/*args*/, char const *&/*fmt*/, int & ) +{ + if (cmd!=0) + return NOTHING; + + printf("PIC state: %08x\n", pic_state); + + return NOTHING; +} + +PUBLIC +int Jdb_pic::num_cmds() const +{ + return 1; +} + +PUBLIC +Jdb_module::Cmd const *Jdb_pic::cmds() const +{ + static Cmd cs[] = + {{ 0, "i", "pic", "", "i\tshow pic state", 0 }}; + + return cs; +} + +IMPLEMENTATION [jdb]: + +#include "jdb.h" + +PRIVATE +void +Jdb_pic::register_handlers( Jdb_handler &enter, Jdb_handler &leave ) +{ + Jdb::jdb_enter.add(&enter); + Jdb::jdb_leave.add(&leave); +} + diff --git a/kernel/fiasco/src/jdb/jdb_prompt_ext.cpp b/kernel/fiasco/src/jdb/jdb_prompt_ext.cpp new file mode 100644 index 00000000..e62dfa54 --- /dev/null +++ b/kernel/fiasco/src/jdb/jdb_prompt_ext.cpp @@ -0,0 +1,51 @@ +INTERFACE: + +#include + +class Jdb_prompt_ext : public cxx::H_list_item +{ +public: + Jdb_prompt_ext(); + virtual void ext() = 0; + virtual void update(); + virtual ~Jdb_prompt_ext() = 0; + + static void do_all(); + static void update_all(); + +private: + typedef cxx::H_list_bss List; + typedef List::Const_iterator Iter; + static List exts; +}; + +IMPLEMENTATION: + +Jdb_prompt_ext::List Jdb_prompt_ext::exts; + +IMPLEMENT +Jdb_prompt_ext::Jdb_prompt_ext() +{ + exts.push_front(this); +} + +IMPLEMENT inline Jdb_prompt_ext::~Jdb_prompt_ext() {} + +IMPLEMENT +void Jdb_prompt_ext::update() +{} + +IMPLEMENT +void Jdb_prompt_ext::do_all() +{ + for (Iter e = exts.begin(); e != exts.end(); ++e) + e->ext(); +} + +IMPLEMENT +void Jdb_prompt_ext::update_all() +{ + for (Iter e = exts.begin(); e != exts.end(); ++e) + e->update(); +} + diff --git a/kernel/fiasco/src/jdb/jdb_prompt_module.cpp b/kernel/fiasco/src/jdb/jdb_prompt_module.cpp new file mode 100644 index 00000000..44b4bed4 --- /dev/null +++ b/kernel/fiasco/src/jdb/jdb_prompt_module.cpp @@ -0,0 +1,258 @@ +IMPLEMENTATION: + +#include +#include + +#include "jdb.h" +#include "jdb_module.h" +#include "jdb_screen.h" +#include "kernel_console.h" +#include "static_init.h" + + +//=================== +// Std JDB modules +//=================== + +/** + * Jdb-prompt module. + * + * This module handles some commands that + * change Jdb prompt and screen settings. + */ +class Jdb_pcm : public Jdb_module +{ +public: + Jdb_pcm() FIASCO_INIT; +private: + static char subcmd; + static char prompt_color; + static char direct_enable; + static int screen_height; + static int screen_width; +}; + +char Jdb_pcm::subcmd; +char Jdb_pcm::prompt_color; +char Jdb_pcm::direct_enable; +int Jdb_pcm::screen_height; +int Jdb_pcm::screen_width; + +static Jdb_pcm jdb_pcm INIT_PRIORITY(JDB_MODULE_INIT_PRIO); + +PRIVATE +int +Jdb_pcm::get_coords(Console *cons, unsigned &x, unsigned &y) +{ + cons->write("\033[6n", 4); + + if (!wait_for_escape(cons)) + return 0; + + if (cons->getchar(true) != '[') + return 0; + + for (y=0; ;) + { + int c = cons->getchar(true); + if (c == ';') + break; + if (c < '0' || c > '9') + return 0; + y = y*10+c-'0'; + } + for (x=0; ;) + { + int c = cons->getchar(true); + if (c == 'R') + break; + if (c < '0' || c > '9') + return 0; + x = x*10+c-'0'; + } + return 1; +} + +PRIVATE +void +Jdb_pcm::detect_screensize() +{ + unsigned x, y, max_x, max_y; + char str[20]; + Console *uart; + + if (!(uart = Kconsole::console()->find_console(Console::UART))) + return; + + while (uart->getchar(false) != -1) + ; + if (!get_coords(uart, x, y)) + return; + // set scroll region to the max + set cursor to the max + uart->write("\033[1;199r\033[199;199H", 18); + if (!get_coords(uart, max_x, max_y)) + return; + Jdb_screen::set_width(max_x); + Jdb_screen::set_height(max_y); + // adapt scroll region, restore cursor + snprintf(str, sizeof(str), "\033[1;%ur\033[%u;%uH", max_y, y, x); + uart->write(str, strlen(str)); +} + +PUBLIC +Jdb_module::Action_code +Jdb_pcm::action(int cmd, void *&args, char const *&fmt, int &) +{ + if (cmd) + return NOTHING; + + if (args == &subcmd) + { + switch (subcmd) + { + case 'c': + fmt = " promptcolor=%c"; + args = &prompt_color; + return EXTRA_INPUT; + case 'd': + fmt = "%c"; + args = &direct_enable; + return EXTRA_INPUT; + case 'h': + fmt = " screenheight=%d"; + args = &screen_height; + return EXTRA_INPUT; + case 'w': + fmt = " screenwidth=%d"; + args = &screen_width; + return EXTRA_INPUT; + case 'H': + case 'S': + detect_screensize(); + return NOTHING; + case 'o': + printf("\nConnected consoles:\n"); + Kconsole::console()->list_consoles(); + return NOTHING; + case 'i': + printf("\nScreen dimensions: %dx%d Cols: %ld\n", + Jdb_screen::width(), Jdb_screen::height(), + Jdb_screen::cols()); + return NOTHING; + default: + return ERROR; + } + } + else if (args == &screen_height) + { + // set screen height + if (24 < screen_height && screen_height < 100) + Jdb_screen::set_height(screen_height); + } + else if (args == &screen_width) + { + // set screen height + if (80 < screen_width && screen_width < 600) + Jdb_screen::set_width(screen_width); + } + else if (args == &prompt_color) + { + if (!Jdb::set_prompt_color(prompt_color) ) + { + putchar(prompt_color); + puts(" - color expected (lLrRgGbByYmMcCwW)!"); + } + } + else if (args == &direct_enable) + { + printf(" Direct console %s\n", + direct_enable == '+' ? "enabled" : "disabled"); + Jdb_screen::enable_direct(direct_enable == '+'); + if (direct_enable == '+') + Kconsole::console()->change_state(Console::DIRECT, 0, + ~0U, Console::OUTENABLED); + else + Kconsole::console()->change_state(Console::DIRECT, 0, + ~Console::OUTENABLED, 0); + } + + return NOTHING; +} + +PUBLIC +int Jdb_pcm::num_cmds() const +{ + return 1; +} + +PUBLIC +Jdb_module::Cmd const * Jdb_pcm::cmds() const +{ + static Cmd cs[] = + { + { 0, "J", "Jdb options", "%c", + "Jc\tset the Jdb prompt color, must be:\n" + "\tnN: noir(black), rR: red, gG: green, bB: blue,\n" + "\tyY: yellow, mM: magenta, cC: cyan, wW: white;\n" + "\tthe capital letters are for bold text.\n" + "Jd{+|-}\ton/off Jdb output to VGA/Hercules console\n" + "Jh\tset Jdb screen height\n" + "Jw\tset Jdb screen width\n" + "JS\tdetect screen size using ESCape sequence ESC [ 6 n\n" + "Ji\tshow screen information\n" + "Jo\tlist attached consoles", + &subcmd } + }; + + return cs; +} + +IMPLEMENT +Jdb_pcm::Jdb_pcm() + : Jdb_module("GENERAL") +{} + + +IMPLEMENTATION[ia32 || ux || amd64]: + +#include "cpu.h" + +PRIVATE +int +Jdb_pcm::wait_for_escape(Console *cons) +{ + Unsigned64 to = Cpu::boot_cpu()->ns_to_tsc (Cpu::boot_cpu()->tsc_to_ns (Cpu::rdtsc()) + 200000000); + + // This is just a sanity check to ensure that a tool like minicom is attached + // at the other end of the serial line and this tools responds to the magical + // escape sequence. + for (;;) + { + int c = cons->getchar(false); + if (c == '\033') + return 1; + if (c != -1 || Cpu::rdtsc() > to) + return 0; + Proc::pause(); + } +} + + +IMPLEMENTATION[arm || ppc32 || sparc]: + +#include "processor.h" + +PRIVATE +int +Jdb_pcm::wait_for_escape(Console *cons) +{ + for (Mword cnt=100000; ; cnt--) + { + int c = cons->getchar(false); + if (c == '\033') + return 1; + if (!cnt) + return 0; + Proc::pause(); + } +} diff --git a/kernel/fiasco/src/jdb/jdb_ptab-ia32-ux-arm.cpp b/kernel/fiasco/src/jdb/jdb_ptab-ia32-ux-arm.cpp new file mode 100644 index 00000000..01e1bca9 --- /dev/null +++ b/kernel/fiasco/src/jdb/jdb_ptab-ia32-ux-arm.cpp @@ -0,0 +1,127 @@ +IMPLEMENTATION [ia32,ux]: + +#include "paging.h" + +unsigned Jdb_ptab::max_pt_level = Pdir::Depth; + +static unsigned long _leaf_check[] += { Pt_entry::Pse_bit | Pt_entry::Valid, 0 }; +static unsigned long next_level_mask[] += { 0xfffff000, 0 }; + + +static inline bool leaf_check(unsigned long entry, unsigned level) +{ return (_leaf_check[level] & entry) == _leaf_check[level]; } + +IMPLEMENT +unsigned +Jdb_ptab::entry_is_pt_ptr(Mword entry, unsigned level, + unsigned *entries, unsigned *next_level) +{ + if (leaf_check(entry, level)) + return 0; + *entries = Ptab::Level::length(level); + *next_level = level+1; + return 1; +} + +IMPLEMENT +Address +Jdb_ptab::entry_phys(Mword entry, unsigned level) +{ + if (!leaf_check(entry, level)) + return entry & next_level_mask[level]; + + return Ptab::Level::addr(level, entry); +} + +IMPLEMENT inline NEEDS ["paging.h"] +unsigned +Jdb_ptab::entry_valid(Mword entry, unsigned) +{ return entry & Pt_entry::Valid; } + +IMPLEMENT +void +Jdb_ptab::print_entry(Mword entry, unsigned level) +{ + if (dump_raw) + { + printf(L4_PTR_FMT, entry); + return; + } + + if (!entry_valid(entry,level)) + { + putstr(" - "); + return; + } + + Address phys = entry_phys(entry, level); + + if (level == Pdir::Super_level && entry & Pt_entry::Pse_bit) + printf((phys >> 20) > 0xFF + ? "%03lX/4" : " %02lX/4", phys >> 20); + else + printf((phys >> Config::PAGE_SHIFT) > 0xFFFF + ? "%05lx" : " %04lx", phys >> Config::PAGE_SHIFT); + + putchar(((cur_pt_level>=max_pt_level || (entry & Pt_entry::Pse_bit)) && + (entry & Pt_entry::Cpu_global)) ? '+' : '-'); + printf("%s%c%s", entry & Pt_entry::Noncacheable ? JDB_ANSI_COLOR(lightblue) : "", + entry & Pt_entry::Noncacheable + ? 'n' : (entry & Pt_entry::Write_through) ? 't' : '-', + entry & Pt_entry::Noncacheable ? JDB_ANSI_END : ""); + putchar(entry & Pt_entry::User + ? (entry & Pt_entry::Writable) ? 'w' : 'r' + : (entry & Pt_entry::Writable) ? 'W' : 'R'); +} + +PUBLIC +unsigned long +Jdb_ptab::rows() const +{ return entries/8; } + +IMPLEMENTATION [ia32,ux,arm]: + +#if 0 +// calculate row from virtual address +PRIVATE +unsigned +Jdb_ptab::disp_virt_to_r(Address v) +{ + v = Ptab::Level::index(cur_pt_level, v >> Pdir::Va::Shift); + return v / (cols()-1); +} + +// calculate column from virtual address +PRIVATE +unsigned +Jdb_ptab::disp_virt_to_c(Address v) +{ + v = Ptab::Level::index(cur_pt_level, v >> Pdir::Va::Shift); + return (v % (cols()-1)) + 1; +} +#endif + +PRIVATE +Address +Jdb_ptab::disp_virt(unsigned row, unsigned col) +{ + Pdir::Va e((col-1) + (row * (cols()-1))); + e <<= Ptab::Level::shift(cur_pt_level); + return Virt_addr(e).value() + virt_base; +} + +PUBLIC +void +Jdb_ptab::print_statline(unsigned long row, unsigned long col) +{ + unsigned long sid = Kobject_dbg::pointer_to_id(_task); + + if (cur_pt_level=mode =goto ptab/superpage", + "<" L4_PTR_FMT "> task D:%lx", disp_virt(row,col), sid); + else // PT_MODE + Jdb::printf_statline("ptab", "=mode =goto page", + "<" L4_PTR_FMT "> task D:%lx", disp_virt(row,col), sid); +} diff --git a/kernel/fiasco/src/jdb/jdb_ptab.cpp b/kernel/fiasco/src/jdb/jdb_ptab.cpp new file mode 100644 index 00000000..4b99fe18 --- /dev/null +++ b/kernel/fiasco/src/jdb/jdb_ptab.cpp @@ -0,0 +1,274 @@ +IMPLEMENTATION: + +#include + +#include "config.h" +#include "jdb.h" +#include "jdb_kobject.h" +#include "jdb_module.h" +#include "jdb_screen.h" +#include "jdb_table.h" +#include "kernel_console.h" +#include "kmem.h" +#include "keycodes.h" +#include "space.h" +#include "task.h" +#include "thread_object.h" +#include "static_init.h" +#include "types.h" + +class Jdb_ptab_m : public Jdb_module, public Jdb_kobject_handler +{ +public: + Jdb_ptab_m() FIASCO_INIT; +private: + Address task; + static char first_char; + bool show_kobject(Kobject_common *, int) { return false; } +}; + +class Jdb_ptab : public Jdb_table +{ +private: + Address base; + Address virt_base; + int _level; + Space *_task; + unsigned entries; + unsigned char cur_pt_level; + char dump_raw; + + static unsigned max_pt_level; + + static unsigned entry_valid(Mword entry, unsigned level); + static unsigned entry_is_pt_ptr(Mword entry, unsigned level, + unsigned *entries, unsigned *next_level); + static Address entry_phys(Mword entry, unsigned level); + + void print_entry(Mword entry, unsigned level); + void print_head(Mword entry); +}; + +char Jdb_ptab_m::first_char; + +typedef Mword My_pte; // shoud be replaced by + // arch-dependent type + +PUBLIC +Jdb_ptab::Jdb_ptab(void *pt_base = 0, Space *task = 0, + unsigned char pt_level = 0, unsigned entries = 0, + Address virt_base = 0, int level = 0) +: base((Address)pt_base), virt_base(virt_base), _level(level), + _task(task), entries(entries), cur_pt_level(pt_level), dump_raw(0) +{ + if (!pt_level && entries == 0) + this->entries = 1UL << Ptab::Level::Traits::Size; +} + +PUBLIC +unsigned +Jdb_ptab::col_width(unsigned column) const +{ + if (column == 0) + return Jdb_screen::Col_head_size; + else + return Jdb_screen::Mword_size_bmode; +} + +PUBLIC +unsigned long +Jdb_ptab::cols() const +{ + return Jdb_screen::cols(); +} + + +// available from the jdb_dump module +int jdb_dump_addr_task(Address addr, Space *task, int level) + __attribute__((weak)); + + +PUBLIC +void +Jdb_ptab::draw_entry(unsigned long row, unsigned long col) +{ + if (col==0) + print_head(virt(row, 1)); + else + print_entry(*(My_pte*)(virt(row,col)), cur_pt_level); +} + +PRIVATE +Address +Jdb_ptab::virt(unsigned long row, unsigned long col) +{ + Mword e = (col-1) + (row * (cols()-1)); + return base + e * sizeof(Mword); +} + +IMPLEMENT +void +Jdb_ptab::print_head(Mword entry) +{ + printf(L4_PTR_FMT, entry); +} + +PUBLIC +bool +Jdb_ptab_m::handle_key(Kobject_common *o, int code) +{ + if (code != 'p') + return false; + + Space *t = Kobject::dcast(o); + if (!t) + { + Thread *th = Kobject::dcast(o); + if (!th || !th->space()) + return false; + + t = th->space(); + } + + Jdb_ptab pt_view(static_cast(t)->dir(), t, 0, 0, 0, 1); + pt_view.show(0,0); + + return true; +} + +PUBLIC +unsigned +Jdb_ptab::key_pressed(int c, unsigned long &row, unsigned long &col) +{ + switch (c) + { + default: + return Nothing; + + case KEY_CURSOR_HOME: // return to previous or go home + if (_level == 0) + return Nothing; + return Back; + + case ' ': + dump_raw ^= 1; + return Redraw; + + case KEY_RETURN: // goto ptab/address under cursor + if (_level<=7) + { + My_pte pt_entry = *(My_pte*)virt(row,col); + if (!entry_valid(pt_entry, cur_pt_level)) + break; + + Address pd_virt = (Address) + Mem_layout::phys_to_pmem(entry_phys(pt_entry, cur_pt_level)); + + unsigned next_level, entries; + + if (cur_pt_level < max_pt_level + && entry_is_pt_ptr(pt_entry, cur_pt_level, &entries, &next_level)) + { + Jdb_ptab pt_view((void *)pd_virt, _task, next_level, entries, + disp_virt(row,col), _level+1); + if (!pt_view.show(0,1)) + return Exit; + return Redraw; + } + else if (jdb_dump_addr_task != 0) + { + if (!jdb_dump_addr_task(disp_virt(row,col), _task, _level+1)) + return Exit; + return Redraw; + } + } + break; + } + + return Handled; +} + +PUBLIC +Jdb_module::Action_code +Jdb_ptab_m::action(int cmd, void *&args, char const *&fmt, int &next_char) +{ + if (cmd == 0) + { + if (args == &first_char) + { + if (first_char != KEY_RETURN && first_char != ' ') + { + fmt = "%q"; + args = &task; + next_char = first_char; + return EXTRA_INPUT_WITH_NEXTCHAR; + } + else + { + task = 0; //Jdb::get_current_task(); + } + } + else if (args == &task) + { +#if 0 + if (!Jdb::is_valid_task(task)) + { + puts(" invalid task"); + return NOTHING; + } +#endif + } + else + return NOTHING; + + Space *s; + if (task) + { + s = Kobject::dcast(reinterpret_cast(task)); + if (!s) + return Jdb_module::NOTHING; + } + else + s = Kernel_task::kernel_task(); + + void *ptab_base; + if (!(ptab_base = ((void*)static_cast(s)->dir()))) + return Jdb_module::NOTHING; + + Jdb::clear_screen(); + Jdb_ptab pt_view(ptab_base, s); + pt_view.show(0,1); + + } + + return NOTHING; +} + +PUBLIC +Jdb_module::Cmd const * +Jdb_ptab_m::cmds() const +{ + static Cmd cs[] = + { + { 0, "p", "ptab", "%C", + "p[]\tshow pagetable of current/given task", + &first_char }, + }; + return cs; +} + +PUBLIC +int +Jdb_ptab_m::num_cmds() const +{ + return 1; +} + +IMPLEMENT +Jdb_ptab_m::Jdb_ptab_m() + : Jdb_module("INFO"), Jdb_kobject_handler(0) +{ + Jdb_kobject::module()->register_handler(this); +} + +static Jdb_ptab_m jdb_ptab_m INIT_PRIORITY(JDB_MODULE_INIT_PRIO); diff --git a/kernel/fiasco/src/jdb/jdb_rcupdate.cpp b/kernel/fiasco/src/jdb/jdb_rcupdate.cpp new file mode 100644 index 00000000..a3f08185 --- /dev/null +++ b/kernel/fiasco/src/jdb/jdb_rcupdate.cpp @@ -0,0 +1,94 @@ +IMPLEMENTATION: + +#include +#include +#include + +#include "jdb.h" +#include "jdb_core.h" +#include "jdb_module.h" +#include "jdb_screen.h" +#include "kernel_console.h" +#include "keycodes.h" +#include "ram_quota.h" +#include "simpleio.h" +#include "rcupdate.h" +#include "static_init.h" + +class Jdb_rcupdate : public Jdb_module +{ +public: + Jdb_rcupdate() FIASCO_INIT; +}; + +IMPLEMENT +Jdb_rcupdate::Jdb_rcupdate() + : Jdb_module("INFO") +{} + +PRIVATE static +void +Jdb_rcupdate::print_batch(Rcu_batch const &b) +{ + printf("#%ld", b._b); +} + +PUBLIC +Jdb_module::Action_code +Jdb_rcupdate::action(int cmd, void *&, char const *&, int &) +{ printf("\nRCU--------------------------\n"); + if (cmd == 0) + { + printf("RCU:\n current batch="); + print_batch(Rcu::_rcu._current); puts(""); + printf(" completed="); + print_batch(Rcu::_rcu._completed); puts(""); + printf(" next_pending=%s\n" + " cpus=", Rcu::_rcu._next_pending?"yes":"no"); + for (unsigned i = 0; i < Config::Max_num_cpus; ++i) + printf("%s%s", Rcu::_rcu._cpus.get(i)?"1":"0", i%4 == 3?" ":""); + + puts(""); + + for (unsigned i = 0; i < Config::Max_num_cpus; ++i) + { + if (!Cpu::online(i)) + continue; + + printf(" CPU[%2u]:", i); + Rcu_data const *d = &Rcu::_rcu_data.cpu(i); + printf(" quiescent batch="); + print_batch(d->_q_batch); puts(""); + printf(" quiescent state passed: %s\n", d->_q_passed?"yes":"no"); + printf(" wait for quiescent state: %s\n", d->_pending?"yes":"no"); + printf(" batch="); + print_batch(d->_batch); puts(""); + printf(" next list: h=%p len=%ld\n", d->_n.front(), d->_len); + printf(" current list: h=%p \n", d->_c.front()); + printf(" done list: h=%p\n", d->_d.front()); + } + + return NOTHING; + } + return NOTHING; +} + +PUBLIC +Jdb_module::Cmd const * +Jdb_rcupdate::cmds() const +{ + static Cmd cs[] = + { + { 0, 0, "rcupdate", "", "rcupdate\tshow RCU information", 0}, + }; + return cs; +} + +PUBLIC +int +Jdb_rcupdate::num_cmds() const +{ return 1; } + +static Jdb_rcupdate jdb_rcupdate INIT_PRIORITY(JDB_MODULE_INIT_PRIO); + + diff --git a/kernel/fiasco/src/jdb/jdb_regex.cpp b/kernel/fiasco/src/jdb/jdb_regex.cpp new file mode 100644 index 00000000..640cec8a --- /dev/null +++ b/kernel/fiasco/src/jdb/jdb_regex.cpp @@ -0,0 +1,102 @@ +INTERFACE: + +// ------------------------------------------------------------------------ +INTERFACE [!jdb_regex]: + +class Jdb_regex +{ +public: + static bool avail() { return false; } +}; + +// ------------------------------------------------------------------------ +INTERFACE [jdb_regex]: + +#include "initcalls.h" +#include "regex.h" + +class Jdb_regex +{ +private: + static const unsigned heap_size = 64 * 1024; + static char _init_done; + +public: + static bool avail() { return true; } + + static regex_t _r; + static regmatch_t _matches[1]; +}; + +// ------------------------------------------------------------------------ +IMPLEMENTATION [!jdb_regex]: + +PUBLIC static +int +Jdb_regex::start(const char *) +{ return 0; } + +PUBLIC static +int +Jdb_regex::find(const char *, const char **, const char **) +{ return 0; } + +// ------------------------------------------------------------------------ +IMPLEMENTATION [jdb_regex]: + +#include "config.h" +#include "jdb_module.h" +#include "kmem_alloc.h" +#include "panic.h" +#include "static_init.h" + +char Jdb_regex::_init_done; +regex_t Jdb_regex::_r; +regmatch_t Jdb_regex::_matches[1]; + + +STATIC_INITIALIZE_P(Jdb_regex, JDB_MODULE_INIT_PRIO); + +PUBLIC static +void FIASCO_INIT +Jdb_regex::init() +{ + if (!_init_done) + { + char *heap = (char*)Kmem_alloc::allocator()->unaligned_alloc(heap_size); + if (!heap) + panic("No memory for regex heap"); + regex_init(heap, heap_size); + _init_done = 1; + } +} + +PUBLIC static +int +Jdb_regex::start(const char *searchstr) +{ + // clear regex heap + regex_reset(); + // compile expression + return regcomp(&Jdb_regex::_r, searchstr, REG_EXTENDED) ? 0 : 1; +} + +PUBLIC static +int +Jdb_regex::find(const char *buffer, const char **beg, const char **end) +{ + // execute expression + int ret = regexec(&Jdb_regex::_r, buffer, + sizeof(Jdb_regex::_matches)/sizeof(Jdb_regex::_matches[0]), + Jdb_regex::_matches, 0); + + if (ret == REG_NOMATCH) + return 0; + + if (beg) + *beg = buffer + Jdb_regex::_matches[0].rm_so; + if (end) + *end = buffer + Jdb_regex::_matches[0].rm_eo; + return 1; +} + diff --git a/kernel/fiasco/src/jdb/jdb_scheduler.cpp b/kernel/fiasco/src/jdb/jdb_scheduler.cpp new file mode 100644 index 00000000..eee7ee49 --- /dev/null +++ b/kernel/fiasco/src/jdb/jdb_scheduler.cpp @@ -0,0 +1,56 @@ +IMPLEMENTATION: + +#include +#include +#include + +#include "scheduler.h" +#include "jdb.h" +#include "jdb_core.h" +#include "jdb_module.h" +#include "jdb_screen.h" +#include "jdb_kobject.h" +#include "kernel_console.h" +#include "keycodes.h" +#include "simpleio.h" +#include "static_init.h" + +class Jdb_cpu : public Jdb_kobject_handler +{ +public: + Jdb_cpu() FIASCO_INIT; +}; + +IMPLEMENT +Jdb_cpu::Jdb_cpu() + : Jdb_kobject_handler(Scheduler::static_kobj_type) +{ + Jdb_kobject::module()->register_handler(this); +} + +PUBLIC +bool +Jdb_cpu::show_kobject(Kobject_common *, int ) +{ + return true; +} + +PUBLIC +char const * +Jdb_cpu::kobject_type() const +{ + return JDB_ANSI_COLOR(blue) "Sched" JDB_ANSI_COLOR(default); +} + +#if 0 +PUBLIC +int +Jdb_cpu::show_kobject_short(char *buf, int max, Kobject_common *o) +{ + Cpu_object *co = Kobject::dcast(o); + return snprintf(buf, max, " id=%d o%sline", co->id(), + Cpu::online(co->id()) ? "n" : "ff"); +} +#endif + +static Jdb_cpu jdb_cpu INIT_PRIORITY(JDB_MODULE_INIT_PRIO); diff --git a/kernel/fiasco/src/jdb/jdb_screen.cpp b/kernel/fiasco/src/jdb/jdb_screen.cpp new file mode 100644 index 00000000..fda50fa8 --- /dev/null +++ b/kernel/fiasco/src/jdb/jdb_screen.cpp @@ -0,0 +1,78 @@ +INTERFACE: + +#include "types.h" + +class Jdb_screen +{ +public: + static const unsigned Mword_size_bmode = sizeof(Mword)*2; + static const unsigned Mword_size_cmode = sizeof(Mword); + static const unsigned Col_head_size = sizeof(Mword)*2; + + static const char *Mword_adapter; + static const char *Mword_not_mapped; + static const char *Mword_blank; + + static const char* const Reg_names[]; + static const char Reg_prefix; + static const char *Line; + + static const char* Root_page_table; + +private: + static unsigned int _height; + static unsigned int _width; + static bool _direct_enabled; +}; + +IMPLEMENTATION: + +unsigned int Jdb_screen::_height = 25; // default for native +unsigned int Jdb_screen::_width = 80; // default +bool Jdb_screen::_direct_enabled = true; + +const char* Jdb_screen::Mword_adapter = "~~~~~~~~~~~~~~~~"; +const char* Jdb_screen::Mword_not_mapped = "----------------"; +const char* Jdb_screen::Mword_blank = " "; +const char* Jdb_screen::Line = "---------------------------" + "---------------------------" + "-----------------"; +PUBLIC static +void +Jdb_screen::set_height(unsigned int h) +{ _height = h; } + +PUBLIC static +void +Jdb_screen::set_width(unsigned int w) +{ _width = w; } + +PUBLIC static inline +unsigned int +Jdb_screen::width() +{ return _width; } + +PUBLIC static inline +unsigned int +Jdb_screen::height() +{ return _height; } + +PUBLIC static inline +unsigned long +Jdb_screen::cols() +{ return (width()-Col_head_size)/(Mword_size_bmode + 1) + 1; } + +PUBLIC static inline +unsigned long +Jdb_screen::rows() +{ return ((unsigned long)-1)/ ((cols()-1)*4) + 1; } + +PUBLIC static inline +void +Jdb_screen::enable_direct(bool enable) +{ _direct_enabled = enable; } + +PUBLIC static inline +bool +Jdb_screen::direct_enabled() +{ return _direct_enabled; } diff --git a/kernel/fiasco/src/jdb/jdb_sender_list.cpp b/kernel/fiasco/src/jdb/jdb_sender_list.cpp new file mode 100644 index 00000000..60a1de33 --- /dev/null +++ b/kernel/fiasco/src/jdb/jdb_sender_list.cpp @@ -0,0 +1,126 @@ +IMPLEMENTATION: + +#include +#include + +#include "thread_object.h" +#include "jdb.h" +#include "jdb_kobject.h" +#include "jdb_module.h" +#include "ipc_gate.h" + + +class Jdb_sender_list : public Jdb_module, public Jdb_kobject_handler +{ +public: + Jdb_sender_list() FIASCO_INIT; + + virtual bool show_kobject(Kobject_common *, int) { return true; } +private: + static Kobject *object; +}; + +static Jdb_sender_list jdb_sender_list INIT_PRIORITY(JDB_MODULE_INIT_PRIO); + +Kobject *Jdb_sender_list::object; + + +PRIVATE +void +Jdb_sender_list::show_sender_list(Prio_list *t, int printlines) +{ + puts(printlines ? Jdb_screen::Line : ""); + Jdb::clear_to_eol(); + + Prio_list::P_list::Iterator p = t->begin(); + if (p == t->end()) + { + Jdb::clear_to_eol(); + printf("Nothing in sender list\n"); + if (printlines) + puts(Jdb_screen::Line); + return; + } + + for (; p != t->end(); ++p) + { + Jdb::clear_to_eol(); + printf("%02x: ", p->prio()); + Prio_list::S_list::Iterator s = Prio_list::S_list::iter(*p); + do + { + Thread *ts = static_cast(Sender::cast(*s)); + printf("%s %lx", *s == *p ? "" : ",", ts->dbg_info()->dbg_id()); + ++s; + } while (*s != *p); + puts(""); + } + + if (printlines) + puts(Jdb_screen::Line); +} + +PUBLIC +Jdb_module::Action_code +Jdb_sender_list::action(int cmd, void *&, char const *&, int &) +{ + if (cmd) + return NOTHING; + + if (Thread *t = Kobject::dcast(object)) + { + printf("Thread: %lx\n", t->dbg_id()); + show_sender_list(t->sender_list(), 0); + return NOTHING; + } + else if (Ipc_gate *g = Kobject::dcast(object)) + { + printf("Ipc_gate: %lx\n", g->dbg_id()); + show_sender_list(&g->_wait_q, 0); + return NOTHING; + } + + printf(" Invalid object\n"); + return NOTHING; +} + +PUBLIC +bool +Jdb_sender_list::handle_key(Kobject_common *o, int keycode) +{ + if (keycode != 'S') + return false; + + if (Thread *t = Kobject::dcast(o)) + show_sender_list(t->sender_list(), 1); + else if (Ipc_gate *g = Kobject::dcast(o)) + show_sender_list(&g->_wait_q, 1); + else + return false; + + Jdb::getchar(); + return true; +} + +PUBLIC +int Jdb_sender_list::num_cmds() const +{ return 1; } + +PUBLIC +Jdb_module::Cmd const * Jdb_sender_list::cmds() const +{ + static Cmd cs[] = + { + { 0, "ls", "senderlist", "%q", + "senderlist\tshow sender-list of thread", &object } + }; + + return cs; +} + +IMPLEMENT +Jdb_sender_list::Jdb_sender_list() + : Jdb_module("INFO"), Jdb_kobject_handler(0) +{ + Jdb_kobject::module()->register_handler(this); +} diff --git a/kernel/fiasco/src/jdb/jdb_space.cpp b/kernel/fiasco/src/jdb/jdb_space.cpp new file mode 100644 index 00000000..c7fd760d --- /dev/null +++ b/kernel/fiasco/src/jdb/jdb_space.cpp @@ -0,0 +1,138 @@ +IMPLEMENTATION: + +#include +#include +#include + +#include "jdb.h" +#include "jdb_core.h" +#include "jdb_module.h" +#include "jdb_screen.h" +#include "jdb_kobject.h" +#include "kernel_console.h" +#include "kernel_task.h" +#include "keycodes.h" +#include "ram_quota.h" +#include "simpleio.h" +#include "task.h" +#include "thread_object.h" +#include "static_init.h" + +class Jdb_space : public Jdb_module, public Jdb_kobject_handler +{ +public: + Jdb_space() FIASCO_INIT; +private: + static Task *task; +}; + +Task *Jdb_space::task; + +IMPLEMENT +Jdb_space::Jdb_space() + : Jdb_module("INFO"), Jdb_kobject_handler(Task::static_kobj_type) +{ + Jdb_kobject::module()->register_handler(this); +} + +PUBLIC +bool +Jdb_space::show_kobject(Kobject_common *o, int lvl) +{ + Task *t = Kobject::dcast(o); + show(t); + if (lvl) + { + Jdb::getchar(); + return true; + } + + return false; +} + +PUBLIC +char const * +Jdb_space::kobject_type() const +{ + return JDB_ANSI_COLOR(red) "Task" JDB_ANSI_COLOR(default); +} + +PUBLIC +int +Jdb_space::show_kobject_short(char *buf, int max, Kobject_common *o) +{ + Task *t = Kobject::dcast(o); + int cnt = 0; + if (t == Kernel_task::kernel_task()) + { + cnt = snprintf(buf, max, " {KERNEL}"); + max -= cnt; + buf += cnt; + } + return cnt + snprintf(buf, max, " R=%ld", t->ref_cnt()); +} + +PRIVATE static +void +Jdb_space::print_space(Space *s) +{ + printf("%p", s); +} + +PRIVATE +void +Jdb_space::show(Task *t) +{ + printf("Space %p (Kobject*)%p\n", t, static_cast(t)); + + for (Space::Ku_mem_list::Const_iterator m = t->_ku_mem.begin(); m != t->_ku_mem.end(); + ++m) + printf(" utcb area: user_va=%p kernel_va=%p size=%x\n", + m->u_addr.get(), m->k_addr, m->size); + + unsigned long m = t->ram_quota()->current(); + unsigned long l = t->ram_quota()->limit(); + printf(" mem usage: %ld (%ldKB) of %ld (%ldKB) @%p\n", + m, m/1024, l, l/1024, t->ram_quota()); +} + +static bool space_filter(Kobject_common const *o) +{ return Kobject::dcast(o); } + +PUBLIC +Jdb_module::Action_code +Jdb_space::action(int cmd, void *&, char const *&, int &) +{ + if (cmd == 0) + { + Jdb_kobject_list list(space_filter); + list.do_list(); + } + return NOTHING; +} + +PUBLIC +Jdb_module::Cmd const * +Jdb_space::cmds() const +{ + static Cmd cs[] = + { + { 0, "s", "spacelist", "", "s\tshow task list", 0 }, + }; + return cs; +} + +PUBLIC +int +Jdb_space::num_cmds() const +{ return 1; } + +static +bool +filter_task_thread(Kobject_common const *o) +{ + return Kobject::dcast(o) || Kobject::dcast(o); +} +static Jdb_space jdb_space INIT_PRIORITY(JDB_MODULE_INIT_PRIO); +static Jdb_kobject_list::Mode INIT_PRIORITY(JDB_MODULE_INIT_PRIO) tnt("[Tasks + Threads]", filter_task_thread); + diff --git a/kernel/fiasco/src/jdb/jdb_symbol.cpp b/kernel/fiasco/src/jdb/jdb_symbol.cpp new file mode 100644 index 00000000..146436b8 --- /dev/null +++ b/kernel/fiasco/src/jdb/jdb_symbol.cpp @@ -0,0 +1,484 @@ +INTERFACE: + +#include +#include "l4_types.h" + +class Space; + +class Jdb_symbol_info +{ +private: + Address _virt; + size_t _size; + Address _beg_sym; + Address _end_sym; +}; + +class Jdb_symbol +{ +public: + enum + { + // don't allow more than 2048 tasks to register their symbols to save space + Max_tasks = 2048, +#ifdef CONFIG_BIT32 + Digits = 8, + Start = 11, +#else + Digits = 16, + Start = 19, +#endif + }; + +private: + static Jdb_symbol_info *_task_symbols; +}; + + +IMPLEMENTATION: + +#include +#include +#include "config.h" +#include "mem_layout.h" +#include "panic.h" +#include "warn.h" +#include "kdb_ke.h" + +Jdb_symbol_info *Jdb_symbol::_task_symbols; + +PUBLIC static +void +Jdb_symbol::init (void *mem, Mword pages) +{ + if (!mem || pages < (Max_tasks*sizeof(Jdb_symbol_info))>>Config::PAGE_SHIFT) + panic("No memory for symbols"); + + _task_symbols = (Jdb_symbol_info*)mem; + memset(_task_symbols, 0, Max_tasks * sizeof(Jdb_symbol_info)); +} + +PUBLIC inline NOEXPORT +char* +Jdb_symbol_info::str () +{ + return (char*) _virt; +} + +PUBLIC inline +void +Jdb_symbol_info::get (Address &virt, size_t &size) +{ + virt = _virt; + size = _size; +} + +PUBLIC inline +void +Jdb_symbol_info::reset () +{ + _virt = 0; +} + +PUBLIC inline NOEXPORT +bool +Jdb_symbol_info::in_range (Address addr) +{ + return _virt != 0 && _beg_sym <= addr && _end_sym >= addr; +} + +// read address from current position and return its value +PRIVATE static inline NOEXPORT +Address +Jdb_symbol_info::string_to_addr (const char *symstr) +{ + Address addr = 0; + + for (int i=0; i< Jdb_symbol::Digits; i++) + { + switch (Address c = *symstr++) + { + case 'a': case 'b': case 'c': + case 'd': case 'e': case 'f': + c -= 'a' - '9' - 1; + case '0': case '1': case '2': + case '3': case '4': case '5': + case '6': case '7': case '8': + case '9': + c -= '0'; + addr <<= 4; + addr += c; + } + } + + return addr; +} + +// Optimize symbol table to speed up address-to-symbol search. +// Replace stringified address (8/16 characters) by 2/4 dwords of 32/64 bit: +// The symbol value and the absolute address of the next symbol (or 0 if end +// of list) +PRIVATE +bool +Jdb_symbol_info::transform () +{ + char *symstr = str(); + size_t s = _size; + + for (int line=0; ; line++) + { + char *sym = symstr; + + // set symstr to the end of the current line + while (s && (*symstr != '\0') && (*symstr != '\n')) + { + symstr++; + s--; + } + + if (!s || (symstr-sym < Jdb_symbol::Start)) + { + if (line == 0) + { + WARN("Invalid symbol table at " L4_PTR_FMT + " -- disabling symbols.\n", (Address)sym); + return false; + } + + ((Address*)sym)[0] = 0; // terminate list + ((Address*)sym)[1] = 0; // terminate list + if (s) + *symstr = '\0'; // terminate string + return true; + } + + // write binary value of symbol string + Address addr = string_to_addr(sym); + Address *sym_addr = (Address*)sym; + *sym_addr = addr; + + sym += sizeof(Address); + sym_addr = (Address*)sym; + + if (!*symstr || !*(symstr+1)) + { + *symstr = '\0'; // terminate symbol + *sym_addr = 0; // terminate list + return true; + } + + // terminate current symbol -- overwrite '\n' + *symstr = '\0'; + + // write link address to next symbol + *sym_addr = (Address)++symstr; + sym += sizeof(Address); + s--; + } +} + +// register symbols for a specific task (called by user mode application) +PUBLIC +bool +Jdb_symbol_info::set (Address virt, size_t size) +{ + _virt = virt; + _size = size; + + if (! transform()) + return false; + + if (this == Jdb_symbol::lookup(0)) + { + // kernel symbols are special + Address sym_start, sym_end; + + if ( !(sym_start = Jdb_symbol::match_symbol_to_addr("_start", false, 0)) + ||!(sym_end = Jdb_symbol::match_symbol_to_addr("_end", false, 0))) + { + WARN ("Missing \"_start\" or \"_end\" in kernel symbols " + "-- disabling kernel symbols\n"); + return false; + } + + if (sym_end != (Address)&Mem_layout::end) + { + WARN("Fiasco symbol table does not match kernel " + "-- disabling kernel symbols\n"); + return false; + } + + _beg_sym = sym_start; + _end_sym = sym_end; + } + else + { + Address min_addr = ~0UL, max_addr = 0; + const char *sym; + + for (sym = str(); sym; sym = *((const char**)sym+1)) + { + Address addr = *(Address*)sym; + if (addr < min_addr) + min_addr = addr; + if (addr > max_addr) + max_addr = addr; + } + + _beg_sym = min_addr; + _end_sym = max_addr; + } + + return true; +} + +PUBLIC static +Jdb_symbol_info* +Jdb_symbol::lookup (Space *task) +{ + (void)task; +#if 0 + if (task >= Max_tasks) + { + WARN ("register_symbols: task value #%x out of range (0-%x).\n", + task, Max_tasks-1); + return 0; + } + return _task_symbols + task; +#endif + return 0; +} + +// search symbol in task's symbols, return pointer to symbol name +static +const char* +Jdb_symbol::match_symbol (const char *symbol, bool search_instr, Space *task) +{ + (void)symbol; (void)search_instr; (void)task; +#if 0 + const char *sym, *symnext; + + if (task >= Max_tasks) + return 0; + + // walk through list of symbols + for (sym=_task_symbols[task].str(); sym; sym=symnext) + { + symnext = *((const char**)sym+1); + + // search symbol + if ( ( search_instr && ( strstr(sym+Jdb_symbol::Start, symbol) == + sym+Jdb_symbol::Start)) + ||(!search_instr && (!strcmp(sym+Jdb_symbol::Start, symbol)))) + return sym; + } +#endif + return 0; +} + +// Search a symbol in symbols of a specific task. If the symbol +// was not found, search in kernel symbols too (if exists) +PUBLIC static +Address +Jdb_symbol::match_symbol_to_addr (const char *symbol, bool search_instr, + Space *task) +{ + (void)symbol; (void)search_instr; (void)task; +#if 0 + const char *sym; + + if (task >= Max_tasks) + return 0; + + for (;;) + { + if ( !_task_symbols[task].str() + || !(sym = match_symbol(symbol, search_instr, task))) + { + // no symbols for task or symbol not found in symbols + if (task != 0) + { + task = 0; // not yet searched in kernel symbols, do it now + continue; + } + return 0; // already searched in kernel symbols so we fail + } + + return *(Address*)sym; + } +#endif + return 0; +} + +// try to search a possible symbol completion +PUBLIC static +bool +Jdb_symbol::complete_symbol (char *symbol, unsigned size, Space *task) +{ + (void)symbol; (void)size; (void)task; +#if 0 + unsigned equal_len = 0xffffffff, symbol_len = strlen(symbol); + const char *sym, *symnext, *equal_sym = 0; + + if (symbol_len >= --size) + return false; + +repeat: + if (task < Max_tasks && _task_symbols[task].str() != 0) + { + // walk through list of symbols + for (sym=_task_symbols[task].str(); sym; sym=symnext) + { + symnext = *((const char**)sym+1); + sym += Start; + + // search symbol + if (strstr(sym, symbol) == sym) + { + if (!equal_sym) + { + equal_len = strlen(sym); + equal_sym = sym; + } + else + { + unsigned c = 0; + const char *s1 = sym, *s2 = equal_sym; + + while (*s1++ == *s2++) + c++; + + if (c < equal_len) + { + equal_len = c; + equal_sym = sym; + } + } + } + } + } + + if (equal_sym) + { + if (equal_len > symbol_len) + { + snprintf(symbol, size < equal_len+1 ? size : equal_len+1, "%s", equal_sym); + return true; + } + } + else + { + // no completion found or no symbols + if (task != 0) + { + // repeat search with kernel symbols + task = 0; + goto repeat; + } + + int c; + if ( (symbol_len < 1) + || (((c = symbol[symbol_len-1]) != '?') && (c != '*'))) + { + symbol[symbol_len++] = '?'; + symbol[symbol_len] = '\0'; + return true; + } + } +#endif + return false; +} + +IMPLEMENTATION[!arm]: + +// search symbol name that matches for a specific address +PUBLIC static +const char* +Jdb_symbol::match_addr_to_symbol (Address addr, Space *task) +{ + (void)addr; (void)task; +#if 0 + if (task >= Max_tasks) + return 0; + + if (!_task_symbols || !_task_symbols[task].in_range (addr)) + return 0; + + const char *sym; + + for (sym = _task_symbols[task].str(); sym; sym = *((const char**)sym+1)) + { + if ( (*(Address*)sym == addr) + && (memcmp((void*)(sym+Start), "Letext", 6)) // ignore + && (memcmp((void*)(sym+Start), "patch_log_", 10)) // ignore + ) + return sym+Start; + } +#endif + return 0; +} + +IMPLEMENTATION: + +// search last symbol before eip +PUBLIC static +bool +Jdb_symbol::match_addr_to_symbol_fuzzy (Address *addr_ptr, Space *task, + char *t_symbol, int s_symbol) +{ + (void)addr_ptr; (void)task; (void)t_symbol; (void)s_symbol; +#if 0 + if (task >= Max_tasks) + return false; + + if (!_task_symbols || !_task_symbols[task].in_range (*addr_ptr)) + return false; + + const char *sym, *max_sym = 0; + Address max_addr = 0; + + for (sym = _task_symbols[task].str(); sym; sym = *((const char**)sym+1)) + { + Address addr = *(Address*)sym; + if ( addr > max_addr && addr <= *addr_ptr + && (memcmp((void*)(sym+Start), "Letext", 6)) // ignore + && (memcmp((void*)(sym+Start), "patch_log_", 10)) // ignore + ) + { + max_addr = addr; + max_sym = sym; + } + } + + if (max_sym) + { + const char *t = max_sym + Start; + + while (*t != '\n' && *t != '\0' && --s_symbol) + { + *t_symbol++ = *t++; + + // print functions with arguments as () + if (*(t-1) == '(') + while (*t != ')' && *t != '\n' && *t != '\0') + t++; + } + + // terminate string + *t_symbol = '\0'; + + *addr_ptr = max_addr; + return true; + } +#endif + return false; +} + +IMPLEMENTATION[arm]: + +PUBLIC static +const char* +Jdb_symbol::match_addr_to_symbol (Address , Space *) +{ + return 0; +} diff --git a/kernel/fiasco/src/jdb/jdb_table.cpp b/kernel/fiasco/src/jdb/jdb_table.cpp new file mode 100644 index 00000000..cf830b53 --- /dev/null +++ b/kernel/fiasco/src/jdb/jdb_table.cpp @@ -0,0 +1,384 @@ +INTERFACE: + +class Jdb_table +{ +public: + enum + { + Nothing = 0, + Handled, + Redraw, + Edit, + Back, + Exit, + }; + + virtual unsigned col_width(unsigned col) const = 0; + virtual unsigned long cols() const = 0; + virtual unsigned long rows() const = 0; + virtual char col_sep(unsigned col) const; + virtual void draw_entry(unsigned long row, unsigned long col) = 0; + virtual unsigned key_pressed(int key, unsigned long &row, unsigned long &col); + virtual void print_statline(unsigned long row, unsigned long col) = 0; + virtual bool has_row_labels() const; + virtual bool has_col_labels() const; + virtual unsigned width() const; + virtual unsigned height() const; + + virtual bool edit_entry(unsigned long row, unsigned long col, unsigned cx, unsigned cy); +}; + + +IMPLEMENTATION: + +#include +#include "jdb.h" +#include "jdb_screen.h" +#include "kernel_console.h" +#include "keycodes.h" +#include "simpleio.h" + +IMPLEMENT +bool +Jdb_table::edit_entry(unsigned long, unsigned long, unsigned, unsigned) +{ return false; } + +IMPLEMENT +bool +Jdb_table::has_row_labels() const +{ return true; } + +IMPLEMENT +bool +Jdb_table::has_col_labels() const +{ return false; } + + +IMPLEMENT +unsigned +Jdb_table::key_pressed(int, unsigned long &, unsigned long &) +{ return Nothing; } + +IMPLEMENT +char +Jdb_table::col_sep(unsigned col) const +{ return col?' ':':'; } + +IMPLEMENT +unsigned +Jdb_table::width() const +{ return Jdb_screen::width(); } + +IMPLEMENT +unsigned +Jdb_table::height() const +{ return Jdb_screen::height()-1; } + +PRIVATE +unsigned long +Jdb_table::vis_cols(unsigned long first_col, unsigned long *w) +{ + unsigned c = 0; + *w = 0; + unsigned const max_w = width(); + for (;c max_w) + return c; + + *w += cw; + if (*w == max_w) + return c + 1; + else + *w += 1; + } + return c; +} + +PRIVATE +unsigned +Jdb_table::col_ofs(unsigned long first_col, unsigned long col) +{ + unsigned long c = 0; + unsigned long w = 0; + for (;crows()) drows = rows(); + + unsigned long max_absr = 0, max_absc = 0; + if (rows() > drows) max_absr = rows() - drows; + if (cols() > dcols) max_absc = cols() - dcols; + + unsigned long min_row, min_col; + min_row = has_col_labels()?1:0; + min_col = has_row_labels()?1:0; + + absr = crow; + absc = ccol; + + if (absr>max_absr) absr = max_absr; + if (absc>max_absc) absc = max_absc; + + bool redraw = true; + + while(1) + { +screen: + if (crow >= rows()) crow = rows()-1; + if (ccol >= cols()) ccol = cols()-1; + if (crow < min_row) crow = min_row; + if (ccol < min_col) ccol = min_col; + + if (redraw || old_absc != absc || old_absr != absr) + { + dcols = vis_cols(absc, &tmp); + old_absr = absr; + old_absc = absc; + Jdb::cursor(); // go home + draw_table(absr, absc, drows, dcols); + redraw = false; + } + + print_statline(crow, ccol); + + Jdb::cursor(crow - absr + 1, + col_ofs(absc, ccol)+1); + + int c = Kconsole::console()->getchar(); + + unsigned long nrow = crow; + unsigned long ncol = ccol; + unsigned kp = key_pressed(c, nrow, ncol); + if (ncol > ccol) + { + ccol = ncol; + if (ccol - absc >= dcols) + absc = ccol - dcols + 1; + } + else if (ncol < ccol) + { + ccol = ncol; + if (ccol < absc) + absc = ccol; + } + + if (nrow > crow) + { + crow = nrow; + if (crow - absr >= drows) + absr = crow - drows + 1; + } + else if (nrow < crow) + { + crow = nrow; + if (crow < absr) + absr = crow; + } + + switch (kp) + { + case Redraw: + redraw = true; + goto screen; + case Exit: + return false; + case Back: + return true; + case Handled: + goto screen; + case Edit: + { + unsigned col_o = col_ofs(absc, ccol) + 1; + if (edit_entry(crow, ccol, col_o, + crow - absr + 1)) + { + Jdb::cursor(crow - absr + 1, col_o); + draw_entry(crow,ccol); + Jdb::cursor(crow - absr + 1, col_o); + } + } + goto screen; + + default: + break; + } + + switch (c) + { + case KEY_CURSOR_HOME: + case 'H': + crow = absr = min_row; + ccol = absc = min_col; + break; + case KEY_CURSOR_END: + case 'L': + absr = max_absr; + absc = max_absc; + crow = rows() - 1; + ccol = cols() - 1; + break; + case KEY_CURSOR_LEFT: + case 'h': + if (ccol > min_col) + { + --ccol; + if (ccol < absc) + absc = ccol; + } + else if (crow > min_row) + { + ccol = cols() -1; + if (ccol - absc > dcols) + absc = ccol - dcols; + --crow; + if (crow < absr) + absr = crow; + } + break; + case KEY_CURSOR_RIGHT: + case 'l': + if (ccol + 1 < cols()) + { + ++ccol; + if (ccol - absc > dcols) + absc = ccol - dcols; + } + else if (crow + 1 < rows()) + { + absc = ccol = min_col; + ++crow; + if (crow - absr >= drows) + absr = crow - drows + 1; + } + break; + case KEY_CURSOR_UP: + case 'k': + if (crow > min_row) + { + --crow; + if (crow < absr) + absr = crow; + } + break; + case KEY_CURSOR_DOWN: + case 'j': + if (crow + 1 < rows()) + { + ++crow; + if (crow - absr >= drows) + absr = crow - drows + 1; + } + break; + case KEY_PAGE_UP: + case 'K': + if (crow >= drows + min_row) + { + crow -= drows; + if (absr >= drows) + absr -= drows; + else + absr = 0; + } + else + { + crow = min_row; + absr = 0; + } + break; + case KEY_PAGE_DOWN: + case 'J': + if (crow + 1 + drows < rows()) + { + crow += drows; + if (absr + drows <= max_absr) + absr += drows; + else + absr = max_absr; + } + else + { + crow = rows() -1; + absr = max_absr; + } + break; + case KEY_ESC: + Jdb::abort_command(); + return false; + default: + if (Jdb::is_toplevel_cmd(c)) + return false; + break; + } + + if (absc > max_absc) absc = max_absc; + if (absr > max_absr) absr = max_absr; + } +} + +PUBLIC +void +Jdb_table::draw_table(unsigned long row, unsigned long col, + unsigned lines, unsigned columns) +{ + for (unsigned long y = 0; y < lines; ++y) + { + unsigned long w = 0; + unsigned long r; + if (has_col_labels() && y == 0) + r = 0; + else + r = row + y; + + Kconsole::console()->getchar_chance(); + for (unsigned long x = 0; x < columns; ++x) + { + unsigned long c; + if (has_row_labels() && x == 0) + c = 0; + else + c = col + x; + + draw_entry(r, c); + w += col_width(c); + if (x+1 _lock; +}; + +#ifdef CONFIG_JDB_LOGGING + +#ifdef CONFIG_PF_UX + +// We don't want to patch the text segment of Fiasco-UX. + +#define BEGIN_LOG_EVENT(name, sc, fmt) \ + do \ + { \ + register Unsigned8 __do_log__; \ + asm volatile (".pushsection \".data\" \n\t" \ + "1: .byte 0 \n\t" \ + ".section \".debug.jdb.log_table\" \n\t" \ + ".long 2f \n\t" \ + ".long 1b \n\t" \ + ".long "#fmt" \n\t" \ + ".section \".rodata.log.str\" \n\t" \ + "2: .asciz "#name" \n\t" \ + " .asciz "#sc" \n\t" \ + ".popsection \n\t" \ + "movb 1b,%0 \n\t" \ + : "=q"(__do_log__) ); \ + if (EXPECT_FALSE( __do_log__ )) \ + { + +#elif defined(CONFIG_ARM) + +#define BEGIN_LOG_EVENT(name, sc, fmt) \ + do \ + { \ + register Mword __do_log__; \ + asm volatile ("1: mov %0, #0 \n\t" \ + ".pushsection \".debug.jdb.log_table\" \n\t" \ + "3: .long 2f \n\t" \ + " .long 1b \n\t" \ + " .long "#fmt" \n\t" \ + ".section \".rodata.log.str\" \n\t" \ + "2: .asciz "#name" \n\t" \ + " .asciz "#sc" \n\t" \ + ".popsection \n\t" \ + : "=r"(__do_log__)); \ + if (EXPECT_FALSE( __do_log__ )) \ + { + +#elif defined(CONFIG_IA32) // IA32 + +#define BEGIN_LOG_EVENT(name, sc, fmt) \ + do \ + { \ + register Unsigned8 __do_log__; \ + asm volatile ("1: movb $0,%0 \n\t" \ + ".pushsection \".debug.jdb.log_table\" \n\t" \ + "3: .long 2f \n\t" \ + " .long 1b + 1 \n\t" \ + " .long "#fmt" \n\t" \ + ".section \".rodata.log.str\" \n\t" \ + "2: .asciz "#name" \n\t" \ + " .asciz "#sc" \n\t" \ + ".popsection \n\t" \ + : "=b"(__do_log__)); \ + if (EXPECT_FALSE( __do_log__ )) \ + { + +#elif defined(CONFIG_AMD64) +#define BEGIN_LOG_EVENT(name, sc, fmt) \ + do \ + { \ + register Unsigned8 __do_log__; \ + asm volatile ("1: movb $0,%0 \n\t" \ + ".pushsection \".debug.jdb.log_table\" \n\t" \ + "3: .quad 2f \n\t" \ + " .quad 1b + 1 \n\t" \ + " .quad "#fmt" \n\t" \ + ".section \".rodata.log.str\" \n\t" \ + "2: .asciz "#name" \n\t" \ + " .asciz "#sc" \n\t" \ + ".popsection \n\t" \ + : "=b"(__do_log__)); \ + if (EXPECT_FALSE( __do_log__ )) \ + { +#elif defined(CONFIG_PPC32) +//#warning TODO: Dummy implementation for PPC32 +#define BEGIN_LOG_EVENT(name, sc, fmt) \ + do \ + { \ + register Unsigned8 __do_log__ = 0; \ + if (EXPECT_FALSE( __do_log__ )) \ + { + +#else +#error Unknown Arch for LOG macros +#endif + +#define END_LOG_EVENT \ + } \ + } while (0) + +#else // ! CONFIG_JDB_LOGGING + +#define BEGIN_LOG_EVENT(name, sc, fmt) \ + if (0) \ + { char __do_log__ = 0; (void)__do_log__; + +#define END_LOG_EVENT \ + } + +#endif // ! CONFIG_JDB_LOGGING + + +IMPLEMENTATION: + +#include "config.h" +#include "cpu_lock.h" +#include "initcalls.h" +#include "lock_guard.h" +#include "mem_layout.h" +#include "std_macros.h" + +Tb_entry *Jdb_tbuf::_tbuf_act; +Tb_entry *Jdb_tbuf::_tbuf_max; +Mword Jdb_tbuf::_entries; +Mword Jdb_tbuf::_max_entries; +Mword Jdb_tbuf::_filter_enabled; +Mword Jdb_tbuf::_number; +Mword Jdb_tbuf::_count_mask1; +Mword Jdb_tbuf::_count_mask2; +Address Jdb_tbuf::_size; +Spin_lock<> Jdb_tbuf::_lock; + +static void direct_log_dummy(Tb_entry*, const char*) +{} + +void (*Jdb_tbuf::direct_log_entry)(Tb_entry*, const char*) = &direct_log_dummy; + +PUBLIC static inline NEEDS["mem_layout.h"] +Tracebuffer_status * +Jdb_tbuf::status() +{ + return (Tracebuffer_status*) Mem_layout::Tbuf_status_page; +} + +PROTECTED static inline NEEDS["mem_layout.h"] +Tb_entry * +Jdb_tbuf::buffer() +{ + return (Tb_entry*)Mem_layout::Tbuf_buffer_area; +} + +PUBLIC static inline +Address +Jdb_tbuf::size() +{ + return _size; +} + +/** Clear tracebuffer. */ +PUBLIC static +void +Jdb_tbuf::clear_tbuf() +{ + Mword i; + + for (i=0; i<_max_entries; i++) + buffer()[i].clear(); + + _tbuf_act = buffer(); + _entries = 0; +} + +/** Return pointer to new tracebuffer entry. */ +PUBLIC static +Tb_entry* +Jdb_tbuf::new_entry() +{ + Tb_entry *tb; + { + Lock_guard guard(&_lock); + + tb = _tbuf_act; + + status()->current = (Address)tb; + + if (++_tbuf_act >= _tbuf_max) + _tbuf_act = buffer(); + + if (_entries < _max_entries) + _entries++; + + tb->number(++_number); + } + + tb->rdtsc(); + tb->rdpmc1(); + tb->rdpmc2(); + + return tb; +} + +/** Commit tracebuffer entry. */ +PUBLIC static +void +Jdb_tbuf::commit_entry() +{ + if (EXPECT_FALSE((_number & _count_mask2) == 0)) + { + if (_number & _count_mask1) + status()->window[0].version++; // 64-bit value! + else + status()->window[1].version++; // 64-bit value! + +#if 0 // disbale Tbuf vIRQ for the time beeing (see bug #357) + // fire the virtual 'buffer full' irq + if (_observer) + { + Lock_guard guard(&cpu_lock); + _observer->notify(); + } +#endif + } +} + +/** Return number of entries currently allocated in tracebuffer. + * @return number of entries */ +PUBLIC static inline +Mword +Jdb_tbuf::unfiltered_entries() +{ + return _entries; +} + +PUBLIC static +Mword +Jdb_tbuf::entries() +{ + if (!_filter_enabled) + return unfiltered_entries(); + + Mword cnt = 0; + + for (Mword idx=0; idx(e); +} + +/** Return pointer to tracebuffer event. + * Don't count hidden events. + * @param position of event in tracebuffer: + * 0 is last event, 1 the event before and so on + * @return pointer to tracebuffer event + * + * event with idx == 0 is the last event queued in + * event with idx == 1 is the event before */ +PUBLIC static +Tb_entry* +Jdb_tbuf::lookup(Mword look_idx) +{ + if (!_filter_enabled) + return unfiltered_lookup(look_idx); + + for (Mword idx=0;; idx++) + { + Tb_entry *e = unfiltered_lookup(idx); + + if (!e) + return 0; + if (e->hidden()) + continue; + if (!look_idx--) + return e; + } +} + +PUBLIC static +Mword +Jdb_tbuf::unfiltered_idx(Tb_entry *e) +{ + Tb_entry *ef = static_cast(e); + Mword idx = _tbuf_act - ef - 1; + + if (idx > _max_entries) + idx += _max_entries; + + return idx; +} + +/** Tb_entry => tracebuffer index. */ +PUBLIC static +Mword +Jdb_tbuf::idx(Tb_entry *e) +{ + if (!_filter_enabled) + return unfiltered_idx(e); + + Tb_entry *ef = static_cast(e); + Mword idx = (Mword)-1; + + for (;;) + { + if (!ef->hidden()) + idx++; + ef++; + if (ef >= buffer() + _max_entries) + ef -= _max_entries; + if (ef == _tbuf_act) + break; + } + + return idx; +} + +/** Event number => Tb_entry. */ +PUBLIC static inline +Tb_entry* +Jdb_tbuf::search(Mword nr) +{ + Tb_entry *e; + + for (Mword idx=0; (e = unfiltered_lookup(idx)); idx++) + if (e->number() == nr) + return e; + + return 0; +} + +/** Event number => tracebuffer index. + * @param nr number of event + * @return tracebuffer index of event which has the number nr or + * -1 if there is no event with this number or + * -2 if the event is currently hidden. */ +PUBLIC static +Mword +Jdb_tbuf::search_to_idx(Mword nr) +{ + if (nr == (Mword)-1) + return (Mword)-1; + + Tb_entry *e; + + if (!_filter_enabled) + { + e = search(nr); + if (!e) + return (Mword)-1; + return unfiltered_idx(e); + } + + for (Mword idx_u=0, idx_f=0; (e = unfiltered_lookup(idx_u)); idx_u++) + { + if (e->number() == nr) + return e->hidden() ? (Mword)-2 : idx_f; + + if (!e->hidden()) + idx_f++; + } + + return (Mword)-1; +} + +/** Return some information about log event. + * @param idx number of event to determine the info + * @retval number event number + * @retval tsc event value of CPU cycles + * @retval pmc event value of perf counter cycles + * @return 0 if something wrong, 1 if everything ok */ +PUBLIC static +int +Jdb_tbuf::event(Mword idx, Mword *number, Unsigned32 *kclock, + Unsigned64 *tsc, Unsigned32 *pmc1, Unsigned32 *pmc2) +{ + Tb_entry *e = lookup(idx); + + if (!e) + return false; + + *number = e->number(); + if (kclock) + *kclock = e->kclock(); + if (tsc) + *tsc = e->tsc(); + if (pmc1) + *pmc1 = e->pmc1(); + if (pmc2) + *pmc2 = e->pmc2(); + return true; +} + +/** Search the paired event to an ipc event or ipc result event. + * @param idx number of event to search the pair event for + * @retval type type of pair event + * @return number of pair event */ +PUBLIC static +Tb_entry* +Jdb_tbuf::ipc_pair_event(Mword idx, Unsigned8 *type) +{ + Tb_entry *e = lookup(idx); + + if (!e) + return 0; + + if (e->type() == Tbuf_ipc_res) + { + *type = Event; + return search(static_cast(e)->pair_event()); + } + + if (e->type() != Tbuf_ipc) + return 0; + + Tb_entry_ipc *e0 = static_cast(e); + Tb_entry_ipc_res *e1; + + // start at e and go until future until current event + while (idx > 0 && ((e1 = static_cast(lookup(--idx))))) + { + if (e1->type() == Tbuf_ipc_res && e1->pair_event() == e0->number()) + { + *type = Result; + return e1; + } + } + + return 0; +} + +/** Search the paired event to a pagefault / result event. + * @param idx position of event in tracebuffer to search the pair event for + * @retval type type of pair event + * @return number of pair event */ +PUBLIC static +Tb_entry* +Jdb_tbuf::pf_pair_event(Mword idx, Unsigned8 *type) +{ + Tb_entry *e = lookup(idx); + + if (!e) + return 0; + + if (e->type() == Tbuf_pf_res) + { + // we have a pf result event and we search the paired pf event + Tb_entry_pf_res *e0 = static_cast(e); + Tb_entry_pf *e1; + + // start at e and go into past until oldst event + while (((e1 = static_cast(lookup(++idx))))) + { + if (e1->type() == Tbuf_pf && + e1->ctx() == e0->ctx() && + e1->ip() == e0->ip() && + e1->pfa() == e0->pfa()) + { + *type = Event; + return e1; + } + } + } + else if (e->type() == Tbuf_pf) + { + // we have a pf event and we search the paired pf result event + Tb_entry_pf *e0 = static_cast(e); + Tb_entry_pf_res *e1; + + // start at e and go until future until current event + while (idx > 0 && ((e1 = static_cast(lookup(--idx))))) + { + if (e1->type() == Tbuf_pf_res && + e1->ctx() == e0->ctx() && + e1->ip() == e0->ip() && + e1->pfa() == e0->pfa()) + { + *type = Result; + return e1; + } + } + } + + return 0; +} + +/** Get difference CPU cycles between event idx and event idx+1. + * @param idx position of first event in tracebuffer + * @retval difference in CPU cycles + * @return 0 if something wrong, 1 if everything ok */ +PUBLIC static +int +Jdb_tbuf::diff_tsc(Mword idx, Signed64 *delta) +{ + Tb_entry *e = lookup(idx); + Tb_entry *e_prev = lookup(idx+1); + + if (!e || !e_prev) + return false; + + *delta = e->tsc() - e_prev->tsc(); + return true; +} + +/** Get difference perfcnt cycles between event idx and event idx+1. + * @param idx position of first event in tracebuffer + * @param nr number of perfcounter (0=first, 1=second) + * @retval difference in perfcnt cycles + * @return 0 if something wrong, 1 if everything ok */ +PUBLIC static +int +Jdb_tbuf::diff_pmc(Mword idx, Mword nr, Signed32 *delta) +{ + Tb_entry *e = lookup(idx); + Tb_entry *e_prev = lookup(idx+1); + + if (!e || !e_prev) + return false; + + switch (nr) + { + case 0: *delta = e->pmc1() - e_prev->pmc1(); break; + case 1: *delta = e->pmc2() - e_prev->pmc2(); break; + } + + return true; +} + +PUBLIC static inline +void +Jdb_tbuf::enable_filter() +{ + _filter_enabled = 1; +} + +PUBLIC static inline +void +Jdb_tbuf::disable_filter() +{ + _filter_enabled = 0; +} diff --git a/kernel/fiasco/src/jdb/jdb_tbuf_init.cpp b/kernel/fiasco/src/jdb/jdb_tbuf_init.cpp new file mode 100644 index 00000000..baaa0e9e --- /dev/null +++ b/kernel/fiasco/src/jdb/jdb_tbuf_init.cpp @@ -0,0 +1,91 @@ +INTERFACE: + +#include "jdb_tbuf.h" + +class Jdb_tbuf_init : public Jdb_tbuf +{ +public: + static void init(); +}; + + +IMPLEMENTATION: + +#include +#include +#include +#include + +#include "config.h" +#include "cpu.h" +#include "jdb_ktrace.h" +#include "koptions.h" +#include "mem_layout.h" +#include "vmem_alloc.h" + +STATIC_INITIALIZE_P(Jdb_tbuf_init, JDB_MODULE_INIT_PRIO); + +// init trace buffer +IMPLEMENT FIASCO_INIT +void Jdb_tbuf_init::init() +{ + //static Irq_sender tbuf_irq(Config::Tbuf_irq); + + static int init_done; + + if (!init_done) + { + init_done = 1; + + unsigned n; + unsigned want_entries = Config::tbuf_entries; + + if (Koptions::o()->opt(Koptions::F_tbuf_entries)) + want_entries = Koptions::o()->tbuf_entries; + + // minimum: 8KB ( 2 pages), maximum: 2MB (512 pages) + // must be a power of 2 (for performance reasons) + for (n = Config::PAGE_SIZE/sizeof(Tb_entry); + n < want_entries && n*sizeof(Tb_entry)<0x200000; + n<<=1) + ; + + if (n < want_entries) + panic("Cannot allocate more than %d entries for tracebuffer\n", n); + + max_entries(n); + unsigned size = n*sizeof(Tb_entry); + + if (! Vmem_alloc::page_alloc((void*) status(), Vmem_alloc::ZERO_FILL, Vmem_alloc::User)) + panic("jdb_tbuf: alloc status page at " L4_PTR_FMT " failed", + (Address)Mem_layout::Tbuf_status_page); + + Address va = (Address) buffer(); + for (unsigned i=0; iwindow[0].tracebuffer = (Address)Mem_layout::Tbuf_ubuffer_area; + status()->window[1].tracebuffer = (Address)Mem_layout::Tbuf_ubuffer_area + size/2; + status()->window[0].size = + status()->window[1].size = size / 2; + status()->window[0].version = + status()->window[1].version = 0; + + + status()->scaler_tsc_to_ns = Cpu::boot_cpu()->get_scaler_tsc_to_ns(); + status()->scaler_tsc_to_us = Cpu::boot_cpu()->get_scaler_tsc_to_us(); + status()->scaler_ns_to_tsc = Cpu::boot_cpu()->get_scaler_ns_to_tsc(); + + _tbuf_max = buffer() + max_entries(); + _count_mask1 = max_entries() - 1; + _count_mask2 = (max_entries())/2 - 1; + _size = size; + + clear_tbuf(); + } +} diff --git a/kernel/fiasco/src/jdb/jdb_tbuf_output.cpp b/kernel/fiasco/src/jdb/jdb_tbuf_output.cpp new file mode 100644 index 00000000..138bf9e5 --- /dev/null +++ b/kernel/fiasco/src/jdb/jdb_tbuf_output.cpp @@ -0,0 +1,273 @@ +INTERFACE: + +#include "initcalls.h" +#include "l4_types.h" +#include "thread.h" + +class Tb_entry; + +class Jdb_tbuf_output +{ +private: + typedef unsigned (Format_entry_fn)(Tb_entry *tb, const char *tidstr, + unsigned tidlen, char *buf, int maxlen); + static Format_entry_fn *_format_entry_fn[]; + static bool show_names; +}; + +IMPLEMENTATION: + +#include +#include +#include +#include + +#include "config.h" +#include "initcalls.h" +#include "jdb.h" +#include "jdb_kobject_names.h" +#include "jdb_regex.h" +#include "jdb_symbol.h" +#include "jdb_tbuf.h" +#include "kdb_ke.h" +#include "kernel_console.h" +#include "l4_types.h" +#include "processor.h" +#include "static_init.h" +#include "tb_entry.h" +#include "terminate.h" +#include "watchdog.h" + + +Jdb_tbuf_output::Format_entry_fn *Jdb_tbuf_output::_format_entry_fn[Tbuf_max]; +bool Jdb_tbuf_output::show_names; + +static void +console_log_entry(Tb_entry *e, const char *) +{ + static char log_message[80]; + + // disable all interrupts to stop other threads + Watchdog::disable(); + Proc::Status s = Proc::cli_save(); + + Jdb_tbuf_output::print_entry(e, log_message, sizeof(log_message)); + printf("%s\n", log_message); + + // do not use getchar here because we ran cli'd + // and getchar may do halt + int c; + Jdb::enter_getchar(); + while ((c=Kconsole::console()->getchar(false)) == -1) + Proc::pause(); + Jdb::leave_getchar(); + if (c == 'i') + kdb_ke("LOG"); + if (c == '^') + terminate(1); + + // enable interrupts we previously disabled + Proc::sti_restore(s); + Watchdog::enable(); +} + +PRIVATE static +unsigned +Jdb_tbuf_output::dummy_format_entry (Tb_entry *tb, const char *, unsigned, + char *buf, int maxlen) +{ + int len = snprintf(buf, maxlen, + " << no format_entry_fn for type %d registered >>", tb->type()); + return len >= maxlen ? maxlen-1 : len; +} + +STATIC_INITIALIZE(Jdb_tbuf_output); + +PUBLIC static +void FIASCO_INIT +Jdb_tbuf_output::init() +{ + unsigned i; + + Jdb_tbuf::direct_log_entry = &console_log_entry; + for (i=0; i +PUBLIC static +int +Jdb_tbuf_output::thread_ip(int e_nr, Thread const **th, Mword *ip) +{ + Tb_entry *e = Jdb_tbuf::lookup(e_nr); + + if (!e) + return false; + + *th = static_cast(e->ctx()); + + *ip = e->ip(); + + return true; +} + +PUBLIC static +void +Jdb_tbuf_output::toggle_names() +{ + show_names = !show_names; +} + +static +unsigned +formatter_default(Tb_entry *tb, const char *tidstr, unsigned tidlen, + char *buf, int maxlen) +{ + if (tb->type() < Tbuf_dynentries) + return 0; + + int idx = tb->type()-Tbuf_dynentries; + + Tb_entry_formatter *fmt = _log_table[idx].fmt; + char const *sc = _log_table[idx].name; + sc += strlen(sc) + 1; + + unsigned l = snprintf(buf, maxlen, "%-3s: %-*s ", sc, tidlen, tidstr); + buf += l; + maxlen -= l; + + if (!fmt) + { + Tb_entry_ke_reg *e = static_cast(tb); + char ip_buf[32]; + snprintf(ip_buf, sizeof(ip_buf), " @ " L4_PTR_FMT, e->ip()); + snprintf(buf, maxlen, "\"%s\" " + L4_PTR_FMT " " L4_PTR_FMT " " L4_PTR_FMT "%s", + e->msg(), e->val1(), e->val2(), e->val3(), + e->ip() ? ip_buf : ""); + + return maxlen; + } + + return fmt(tb, maxlen, buf); +} + +PUBLIC static +void +Jdb_tbuf_output::print_entry(int e_nr, char *buf, int maxlen) +{ + Tb_entry *tb = Jdb_tbuf::lookup(e_nr); + + if (tb) + print_entry(tb, buf, maxlen); +} + +PUBLIC static +void +Jdb_tbuf_output::print_entry(Tb_entry *tb, char *buf, int maxlen) +{ + assert(tb->type() < Tbuf_max); + + char tidstr[32]; + Thread const *t = static_cast(tb->ctx()); + + if (!t || !Kobject_dbg::is_kobj(t)) + strcpy(tidstr, "????"); + else + { + Jdb_kobject_name *ex + = Jdb_kobject_extension::find_extension(t); + if (show_names && ex) + snprintf(tidstr, sizeof(tidstr), "%04lx %-*.*s", t->dbg_info()->dbg_id(), ex->max_len(), ex->max_len(), ex->name()); + else + snprintf(tidstr, sizeof(tidstr), "%04lx", t->dbg_info()->dbg_id()); + } + + if (Config::Max_num_cpus > 1) + { + snprintf(buf, maxlen, Config::Max_num_cpus > 16 ? "%02d " : "%d ", tb->cpu()); + buf += 2 + (Config::Max_num_cpus > 16); + maxlen -= 2 + (Config::Max_num_cpus > 16); + } + + unsigned len; + + if (tb->type() >= Tbuf_dynentries) + len = formatter_default(tb, tidstr, show_names ? 21 : 4, buf, maxlen); + else + len = _format_entry_fn[tb->type()](tb, tidstr, + show_names ? 21 : 4, buf, maxlen); + + // terminate string + buf += maxlen-len; + while (len--) + *buf++ = ' '; + buf[-1] = '\0'; +} + +PUBLIC static +bool +Jdb_tbuf_output::set_filter(const char *filter_str, Mword *entries) +{ + if (*filter_str && Jdb_regex::avail() && !Jdb_regex::start(filter_str)) + return false; + + if (!*filter_str) + { + for (Mword n=0; nunhide(); + + Jdb_tbuf::disable_filter(); + if (entries) + *entries = Jdb_tbuf::unfiltered_entries(); + return true; + } + + Mword cnt = 0; + + for (Mword n=0; nunhide(); + cnt++; + continue; + } + } + else + { + if (strstr(s, filter_str)) + { + e->unhide(); + cnt++; + continue; + } + } + e->hide(); + } + + if (entries) + *entries = cnt; + Jdb_tbuf::enable_filter(); + return true; +} diff --git a/kernel/fiasco/src/jdb/jdb_tbuf_show.cpp b/kernel/fiasco/src/jdb/jdb_tbuf_show.cpp new file mode 100644 index 00000000..15c27014 --- /dev/null +++ b/kernel/fiasco/src/jdb/jdb_tbuf_show.cpp @@ -0,0 +1,1049 @@ +IMPLEMENTATION: + +#include +#include + +#include "config.h" +#include "cpu.h" +#include "jdb.h" +#include "jdb_disasm.h" +#include "jdb_input.h" +#include "jdb_module.h" +#include "jdb_screen.h" +#include "jdb_symbol.h" +#include "jdb_regex.h" +#include "jdb_tbuf.h" +#include "jdb_tbuf_output.h" +#include "kern_cnt.h" +#include "kernel_console.h" +#include "keycodes.h" +#include "perf_cnt.h" +#include "simpleio.h" +#include "static_init.h" +#include "thread.h" + +class Jdb_tbuf_show : public Jdb_module +{ +public: + Jdb_tbuf_show() FIASCO_INIT; + +private: + static char _search_str[40]; + static char _filter_str[40]; + static char _buffer_str[512]; + static Mword _status_type; + static Mword _absy; + static Mword _nr_cur; + static Mword _nr_ref; + static Mword _nr_pos[10]; + static Mword y_offset; + + enum + { + Index_mode = 0, // number of event + Tsc_delta_mode = 1, // tsc ticks starting from last event + Tsc_ref_mode = 2, // tsc ticks starting from reference event + Tsc_start_mode = 3, // tsc ticks starting from 0 + Kclock_ref_mode = 4, // kernel clock units (us) since reference event + Kclock_start_mode = 5, // kernel clock units (us) since start of system + Pmc1_delta_mode = 6, // ticks of ctr 1 starting from last event + Pmc2_delta_mode = 7, // ticks of ctr 2 starting from last event + Pmc1_ref_mode = 8, // ticks of ctr 1 starting from reference event + Pmc2_ref_mode = 9, // ticks of ctr 2 starting from reference event + }; + + enum + { + Tbuf_start_line = 3, + }; + + enum + { + Status_ok = 0, + Status_redraw = 1, + Status_error = 2, + }; + + enum + { + Nil = (Mword)-1, + }; +}; + +char Jdb_tbuf_show::_search_str[40]; +char Jdb_tbuf_show::_filter_str[40]; +char Jdb_tbuf_show::_buffer_str[512]; +Mword Jdb_tbuf_show::_status_type; +Mword Jdb_tbuf_show::_absy; +Mword Jdb_tbuf_show::_nr_cur; +Mword Jdb_tbuf_show::_nr_ref; +Mword Jdb_tbuf_show::_nr_pos[10] = { Nil, Nil, Nil, Nil, Nil, + Nil, Nil, Nil, Nil, Nil }; + +Mword Jdb_tbuf_show::y_offset = 0; + +static void +Jdb_tbuf_show::error(const char * const msg) +{ + Jdb::printf_statline("tbuf", 0, "\033[31;1m=== %s! ===\033[m", msg); + _status_type = Status_error; +} + +static int +Jdb_tbuf_show::get_string(char *string, unsigned size) +{ + for (unsigned pos=strlen(string); ; ) + { + switch(int c=Jdb_core::getchar()) + { + case KEY_BACKSPACE: + if (pos) + { + putstr("\b \b"); + string[--pos] = '\0'; + } + break; + case KEY_RETURN: + return 1; + case KEY_ESC: + Jdb::abort_command(); + return 0; + default: + if (c >= ' ') + { + if (pos < size-1) + { + putchar(c); + string[pos++] = c; + string[pos ] = '\0'; + } + } + } + } +} + +static void +Jdb_tbuf_show::show_perf_event_unit_mask_entry(Mword nr, Mword idx, + Mword unit_mask, int exclusive) +{ + const char *desc; + Mword value; + + Perf_cnt::get_unit_mask_entry(nr, idx, &value, &desc); + if (!desc || !*desc) + desc = "(no description?)"; + printf(" %c %02lx %.59s\033[K", + exclusive ? unit_mask == value ? '+' : ' ' + : unit_mask & value ? '+' : ' ', + value, desc); +} + +static void +Jdb_tbuf_show::show_perf_event(Mword nr) +{ + const char *name, *desc; + unsigned evntsel; + Mword add_kcnt = Config::Jdb_accounting ? Kern_cnt_max : 0; + + if (nr < add_kcnt) + { + const char * const s = Kern_cnt::get_str(nr); + printf(" %-26.26s %.49s\033[K", s, "(kernel event counter)"); + return; + } + + Perf_cnt::get_perf_event(nr - add_kcnt, &evntsel, &name, &desc); + if (!name || !*name) + name = "(no name?)"; + if (!desc || !*desc) + desc = "(no description)"; + + printf("%02x %-26.26s %.49s\033[K", evntsel, name, desc); +} + +static Mword +Jdb_tbuf_show::select_perf_event_unit_mask(Mword nr, Mword unit_mask) +{ + Mword absy = 0; + Mword addy = 0; + Mword max_absy = 0; + Mword lines = 10; + Mword cols = Jdb_screen::cols() - 1; + + Mword default_value, nvalues, value; + Perf_cnt::Unit_mask_type type; + const char *desc; + + Perf_cnt::get_unit_mask(nr, &type, &default_value, &nvalues); + int exclusive = (type == Perf_cnt::Exclusive); + + if (type == Perf_cnt::None) + return 0; + + if (type == Perf_cnt::Fixed || (nvalues < 1)) + return default_value; + + if (nvalues == 1) + { + Perf_cnt::get_unit_mask_entry(nr, 0, &value, &desc); + return value; + } + + if (nvalues < lines) + lines = nvalues; + + Jdb::printf_statline("tbuf", "=set mask =done", "P?"); + + Jdb::cursor(Tbuf_start_line, 1); + putstr("\033[32m"); + show_perf_event(nr + (Config::Jdb_accounting ? Kern_cnt_max : 0)); + printf("\033[m\033[K\n" + "\033[K\n" + " \033[1;32mSelect Event Mask (%s):\033[m\033[K\n" + "\033[K\n", exclusive ? "exclusive" : "bitmap"); + + for (;;) + { + Mword i; + + Jdb::cursor(Tbuf_start_line+4, 1); + for (i=0; i=select", "P?"); + + Jdb::cursor(Tbuf_start_line, 1); + printf("%sSelect Performance Counter\033[m\033[K\n\033[K", Jdb::esc_emph2); + + if (event & 0x80000000) + addy = event & 0xff; + else + { + Perf_cnt::split_event(event, &evntsel, &unit_mask); + addy = Perf_cnt::lookup_event(evntsel); + if (addy == Nil) + addy = 0; + else + addy += add_kcnt; + } + + if (addy > lines-1) + { + absy += (addy-lines+1); + addy = lines-1; + } + + for (;;) + { + Mword i; + + Jdb::cursor(Tbuf_start_line+2, 1); + for (i=0; igetchar_chance(); + + if (!Jdb_tbuf::event(n, &number, &kclock, &utsc, &upmc1, &upmc2)) + break; + + if (long_output) + { + char s[3]; + Jdb_tbuf_output::print_entry(n, _buffer_str, sizeof(_buffer_str)); + + if (!Jdb_tbuf::diff_tsc(n, &dtsc)) + dtsc = 0; + + strcpy(s, " "); + if (n == ref) + { + s[0] = 'R'; + s[1] = ' '; + } + else + { + for (int i=0; i<10; i++) + if (number == _nr_pos[i]) + { + s[0] = 'M'; + s[1] = i+'0'; + break; + } + } + + char s_tsc_dc[13], s_tsc_ds[15], s_tsc_sc[13], s_tsc_ss[15]; + Jdb::write_ll_dec(dtsc, s_tsc_dc, sizeof(s_tsc_dc), false); + Jdb::write_tsc_s (dtsc, s_tsc_ds, sizeof(s_tsc_ds), false); + Jdb::write_ll_dec(utsc, s_tsc_sc, sizeof(s_tsc_sc), false); + Jdb::write_tsc_s (utsc, s_tsc_ss, sizeof(s_tsc_ss), false); + + printf("%-3s%10lu. %120.120s %13.13s (%14.14s) %13.13s (%14.14s) kclk=%d\n", + s, number, _buffer_str+y_offset, s_tsc_dc, s_tsc_ds, s_tsc_sc, s_tsc_ss, kclock); + } + else + { + char s[13]; + Jdb_tbuf_output::print_entry(n, _buffer_str, sizeof(_buffer_str)); + switch (mode) + { + case Index_mode: + snprintf(s, sizeof(s), "%12lu", number); + break; + case Tsc_delta_mode: + if (!Jdb_tbuf::diff_tsc(n, &dtsc)) + dtsc = 0; + switch (time_mode) + { + case 0: Jdb::write_ll_hex(dtsc, s, sizeof(s), false); break; + case 1: Jdb::write_tsc (dtsc, s, sizeof(s), false); break; + case 2: Jdb::write_ll_dec(dtsc, s, sizeof(s), false); break; + } + break; + case Tsc_ref_mode: + dtsc = (n == ref) ? 0 : utsc - ref_tsc; + switch (time_mode) + { + case 0: Jdb::write_ll_hex(dtsc, s, sizeof(s), true); break; + case 1: Jdb::write_tsc (dtsc, s, sizeof(s), true); break; + case 2: Jdb::write_ll_dec(dtsc, s, sizeof(s), true); break; + } + break; + case Tsc_start_mode: + dtsc = utsc; + switch (time_mode) + { + case 0: Jdb::write_ll_hex(dtsc, s, sizeof(s), true); break; + case 1: Jdb::write_tsc (dtsc, s, sizeof(s), false); break; + case 2: Jdb::write_ll_dec(dtsc, s, sizeof(s), true); break; + } + break; + case Kclock_ref_mode: + if (kclock == ref_kclock) + snprintf(s, sizeof(s), "%12u", 0); + else + { + if (time_mode != 1) + Jdb::write_ll_hex((Unsigned64)kclock-ref_kclock, + s, sizeof(s), true); + else + snprintf(s, sizeof(s), "%+12d", kclock-ref_kclock); + } + break; + case Kclock_start_mode: + snprintf(s, sizeof(s), time_mode != 1 ? "%012x" : "%12u", + kclock); + break; + case Pmc1_delta_mode: + case Pmc2_delta_mode: + if (!Jdb_tbuf::diff_pmc(n, (mode-Pmc1_delta_mode), &dpmc)) + dpmc = 0; + Jdb::write_ll_dec((Signed64)dpmc, s, sizeof(s), false); + break; + case Pmc1_ref_mode: + dpmc = (n == ref) ? 0 : upmc1 - ref_pmc1; + Jdb::write_ll_dec((Signed64)dpmc, s, sizeof(s), true); + break; + case Pmc2_ref_mode: + dpmc = (n == ref) ? 0 : upmc2 - ref_pmc2; + Jdb::write_ll_dec((Signed64)dpmc, s, sizeof(s), true); + break; + } + + const char *c = ""; + if (n == ref) + c = Jdb::esc_emph2; + else + { + for (int i=0; i<10; i++) + if (number == _nr_pos[i]) + { + c = Jdb::esc_mark; + break; + } + } + printf("%s%-*.*s %12s\033[m%s", + c, Jdb_screen::width()-13, (int)Jdb_screen::width()-13, + _buffer_str+y_offset, s, count != 1 ? "\n" : ""); + } + n++; + } +} + +// search in tracebuffer +static Mword +Jdb_tbuf_show::search(Mword start, Mword entries, const char *str, + Unsigned8 direction) +{ + Mword found = Nil; + + if (!entries) + return found; + + if (Jdb_regex::avail() && !Jdb_regex::start(str)) + { + error("Error in regular expression"); + return found; + } + + for (Mword n=direction==1 ? start-1 : start+1; ; (direction==1) ? n-- : n++) + { + static char buffer[120]; + + // don't cycle through entries more than once + // (should not happen due to the following check) + if (n == start) + break; + // don't wrap around + if (!Jdb_tbuf::event_valid(n)) + { + error(direction ? "Begin of tracebuffer reached" + : "End of tracebuffer reached"); + return found; + } + + if (!Jdb_tbuf::event_valid(n)) + n = (direction==1) ? entries-1 : 0; + + Jdb_tbuf_output::print_entry(n, buffer, sizeof(buffer)); + + // progress bar + if ((n & 0x7f) == 0) + { + static int progress; + Jdb::cursor(Jdb_screen::height(), 79); + putchar("|/-\\"[progress++]); + progress &= 3; + } + + if (Jdb_regex::avail() && Jdb_regex::find(buffer, 0, 0)) + { + found = n; + break; + } + else if (strstr(buffer, str)) + { + found = n; + break; + } + } + + // restore screen + Jdb::cursor(Jdb_screen::height(), 79); + putchar('t'); + + return found; +} + +static void +Jdb_tbuf_show::show() +{ + static Unsigned8 mode = Index_mode; + static Unsigned8 time_mode = 1; + static Unsigned8 direction = 0; + Mword entries; + + Jdb_tbuf_output::set_filter(_filter_str, &entries); + Jdb::clear_screen(); + +restart: + Mword refy; // idx of reference event + Mword posy[10]; // idx of mark{0..9} + Mword addy; // cursor position starting from top of screen + Mword lines = Jdb_screen::height()-4; + Mword cols = Jdb_screen::cols() - 1; + Mword n; + Tb_entry *e; + + if (Jdb_tbuf::max_entries() < lines) + lines = Jdb_tbuf::max_entries(); + if (entries < lines) + lines = entries; + if (lines < 1) + lines = 1; + + Mword max_absy = entries > lines ? entries - lines : 0; + + // Search reference element. If not found, use last entry. + if ((refy = Jdb_tbuf::search_to_idx(_nr_ref)) >= (Mword)-2) + if (entries) + refy = entries-1; + else + refy = Nil; + + // Search mark {0..9}. If not found, set Nil. + for (n=0; n<10; n++) + posy[n] = Jdb_tbuf::search_to_idx(_nr_pos[n]); + + // Search current position. If beyond buffer, goto first entry. + if ((addy = Jdb_tbuf::search_to_idx(_nr_cur))) + addy -= _absy; + else + addy = _absy = 0; + if (addy >= lines-1) + addy = _absy = 0; + + for (;;) + { + Mword count, perf_event[2]; + Mword perf_user[2] = { 0, 0 }; + Mword perf_kern[2] = { 0, 0 }; + Mword perf_edge[2] = { 0, 0 }; + const char *perf_mode[2], *perf_name[2]; + + for (Mword i=0; i<2; i++) + if (Kern_cnt::mode (i, &perf_mode[i], &perf_name[i], &perf_event[i]) || + Perf_cnt::mode (i, &perf_mode[i], &perf_name[i], &perf_event[i], + &perf_user[i], &perf_kern[i], &perf_edge[i])) {} + + static const char * const mode_str[] = + { "index", "tsc diff", "tsc rel", "tsc start", "kclock rel", + "kclock", "pmc1 diff", "pmc2 diff", "pmc1 rel", "pmc2 rel" }; + + const char *perf_type = Perf_cnt::perf_type(); + + Jdb::cursor(); + printf("%3lu%% of %-6lu Perf:%-4s 1=" L4_PTR_FMT + "(%s%s\033[m%s%s%s\033[m)\033[K", + Jdb_tbuf::unfiltered_entries()*100/Jdb_tbuf::max_entries(), + Jdb_tbuf::max_entries(), + perf_type, perf_event[0], Jdb::esc_emph, perf_mode[0], + perf_name[0] && *perf_name[0] ? ":" : "", + mode==Pmc1_delta_mode || mode==Pmc1_ref_mode ? Jdb::esc_emph : "", + perf_name[0]); + + Jdb::cursor(1, 71); + printf("%10s\n" + "%24s 2=" L4_PTR_FMT "(%s%s\033[m%s%s%s\033[m)\033[K\n", + mode_str[(int)mode], "", + perf_event[1], Jdb::esc_emph, perf_mode[1], + perf_name[1] && *perf_name[1] ? ":" : "", + mode==Pmc2_delta_mode || mode==Pmc2_ref_mode ? Jdb::esc_emph : "", + perf_name[1]); + if (_filter_str[0]) + { + Jdb::cursor(2, 1); + printf("\033[31m%3lu%% filtered\033[m\n", + entries*100/Jdb_tbuf::max_entries()); + } + for (Mword i=3; i=select", "_"); + _status_type = Status_ok; + } + else if (_status_type == Status_error) + _status_type = Status_redraw; + + if (!_filter_str[0]) + { + // search for paired ipc event + pair_event = Jdb_tbuf::ipc_pair_event(_absy+addy, &type); + if (!pair_event) + // search for paired pagefault event + pair_event = Jdb_tbuf::pf_pair_event(_absy+addy, &type); + if (pair_event) + { + pair_y = Jdb_tbuf::idx(pair_event); + if (pair_y < _absy || pair_y >= _absy+lines) + pair_event = 0; + } + if (pair_event) + { + Jdb::cursor(pair_y-_absy+Tbuf_start_line, 1); + putstr(Jdb::esc_emph); + switch (type) + { + case Jdb_tbuf::Result: putstr("+++>"); break; + case Jdb_tbuf::Event: putstr("<+++"); break; + } + putstr("\033[m"); + } + } + + Jdb::cursor(addy+Tbuf_start_line, 1); + putstr(Jdb::esc_emph); + show_events(_absy+addy, refy, 1, mode, time_mode, 0); + putstr("\033[m"); + Jdb::cursor(addy+Tbuf_start_line, 1); + c=Jdb_core::getchar(); + show_events(_absy+addy, refy, 1, mode, time_mode, 0); + if (pair_event) + { + Jdb::cursor(pair_y-_absy+Tbuf_start_line, 1); + show_events(pair_y, refy, 1, mode, time_mode, 0); + } + + if (Jdb::std_cursor_key(c, cols, lines, max_absy, + &_absy, &addy, 0, &redraw)) + continue; + + switch (c) + { + case 'h': + if (y_offset>10) + y_offset -= 10; + else + y_offset = 0; + + redraw = true; + break; + case 'l': + if (y_offsetfind_console(Console::GZIP)) + break; + Jdb::cursor(Jdb_screen::height(), 10); + Jdb::clear_to_eol(); + printf("Count="); + if (Jdb_input::get_mword(&count, 7, 10)) + { + if (count == 0) + count = lines; + Kconsole::console()->start_exclusive(Console::GZIP); + show_events(_absy, refy, count, mode, time_mode, 1); + Kconsole::console()->end_exclusive(Console::GZIP); + redraw = true; + break; + } + _status_type = Status_redraw; + goto status_line; + case 'P': // set performance counter + { + Mword event, e; + int user, kern, edge, nr; + + Jdb::printf_statline("tbuf", "1..2=select counter", "P"); + Jdb::cursor(Jdb_screen::height(), 8); + for (;;) + { + nr = Jdb_core::getchar(); + if (nr == KEY_ESC) + goto exit; + if (nr >= '1' && nr <= '2') + { + nr -= '1'; + break; + } + } + + event = perf_event[nr]; + user = perf_user[nr]; + kern = perf_kern[nr]; + edge = perf_edge[nr]; + Jdb::printf_statline("tbuf", "d=duration e=edge u=user " + "k=kern +=both -=none ?=event", + "P%c", (char)'1'+nr); + + Jdb::cursor(Jdb_screen::height(), 9); + switch(c=Jdb_core::getchar()) + { + case '+': user = 1; kern = 1; break; + case '-': user = 0; kern = 0; event = 0; break; + case 'u': user = 1; kern = 0; break; + case 'k': user = 0; kern = 1; break; + case 'd': edge = 0; break; + case 'e': edge = 1; break; + case '?': + case '_': if ((e = select_perf_event(event)) == Nil) + { + redraw = true; + break; + } + event = e; + redraw = true; + break; + default: Jdb_input::get_mword(&event, 4, 16, c); + break; + } + + if (!Kern_cnt::setup_pmc(nr, event) && + !Perf_cnt::setup_pmc(nr, event, user, kern, edge)) + Tb_entry::set_rdcnt(nr, 0); + + redraw = true; + } + break; + case KEY_RETURN: // disassemble eip of current entry + { + Thread const *t = 0; + Mword eip; + if (Jdb_tbuf_output::thread_ip(_absy+addy, &t, &eip)) + { + if (Jdb_disasm::avail()) + { + if (!Jdb_disasm::show(eip, t->space(), 1, 1)) + goto exit; + } + else + { // hacky, we should get disasm working for arm too + // (at least without the disassembly itself) + printf("\n==========================\n" + " ip=%lx \n" + "==========================\n", eip); + Jdb_core::getchar(); + } + redraw = true; + } + } + break; + case KEY_TAB: + Jdb_tbuf_output::toggle_names(); + redraw = true; + break; + case KEY_CURSOR_LEFT: // mode switch + if (mode == Index_mode) + mode = Pmc2_ref_mode; + else + mode--; + redraw = true; + break; + case KEY_CURSOR_RIGHT: // mode switch + mode++; + if (mode > Pmc2_ref_mode) + mode = Index_mode; + redraw = true; + break; + case ' ': // mode switch + if (mode != Index_mode) + { + time_mode = (time_mode+1) % 3; + redraw = true; + } + break; + case 'c': // clear tracebuffer + Jdb_tbuf::clear_tbuf(); + _absy = 0; + _nr_cur = Nil; + _nr_ref = Nil; + entries = 0; + for (n=0; n<10; n++) + _nr_pos[n] = Nil; + goto restart; + case 's': // set mark + Jdb::printf_statline("tbuf", 0, "set mark [0-9] "); + _status_type = Status_redraw; + c = Jdb_core::getchar(); + if (!entries || c < '0' || c > '9') + { + error("Invalid marker"); + goto status_line; + } + n = c - '0'; + posy[n] = _absy + addy; + _nr_pos[n] = Jdb_tbuf::lookup(_absy+addy)->number(); + redraw = true; + break; + case 'r': // set reference entry + if (!entries) + break; + refy = _absy + addy; + _nr_ref = Jdb_tbuf::lookup(_absy+addy)->number(); + redraw = true; + break; + case 'j': // jump to mark or reference element + Jdb::printf_statline("tbuf", 0, "jump to mark [0-9] or ref [r] "); + _status_type = Status_redraw; + c = Jdb_core::getchar(); + if ((c < '0' || c > '9') && c != 'r') + { + error("Invalid marker"); + goto status_line; + } + n = (c == 'r') ? refy : posy[c-'0']; + if (n == Nil) + { + error("Mark unset"); + goto status_line; + } + else if (n == (Mword)-2) + { + error("Mark not visible within current filter"); + goto status_line; + } + goto jump_index; + case '?': // search backward + d = 1; + // fall through + case '/': // search forward + direction = d; + // search in tracebuffer events + Jdb::printf_statline("tbuf", 0, "%s=%s", + Jdb_regex::avail() ? "Regexp" : "Search", + _search_str); + _status_type = Status_redraw; + Jdb::cursor(Jdb_screen::height(), 14+strlen(_search_str)); + if (!get_string(_search_str, sizeof(_search_str)) || + !_search_str[0]) + goto status_line; + // fall through + case 'n': // search next + case 'N': // search next reverse + n = search(_absy+addy, entries, _search_str, + c == 'N' ? !direction : direction); + if (n != Nil) + { + // found + jump_index: + if (n < _absy || n > _absy+lines-1) + { + // screen crossed + addy = 4; + _absy = n - addy; + if (n < addy) + { + addy = n; + _absy = 0; + } + if (_absy > max_absy) + { + _absy = max_absy; + addy = n - _absy; + } + redraw = true; + break; + } + else + addy = n - _absy; + } + goto status_line; + case KEY_ESC: + Jdb::abort_command(); + goto exit; + default: + if (Jdb::is_toplevel_cmd(c)) + goto exit; + } + } + } + + exit: + _nr_cur = (e = Jdb_tbuf::lookup(_absy+addy)) ? e->number() : 0; +} + +PUBLIC +Jdb_module::Action_code +Jdb_tbuf_show::action(int cmd, void *&, char const *&, int &) +{ + switch (cmd) + { + case 0: + show(); + break; + + case 1: + if (Kconsole::console()->find_console(Console::GZIP)) + { + Jdb_tbuf_output::set_filter(_filter_str, 0); + Kconsole::console()->start_exclusive(Console::GZIP); + show_events(0, 0, 1000000, 0, 0, 1); + Kconsole::console()->end_exclusive(Console::GZIP); + } + break; + } + + return NOTHING; +} + +PUBLIC +Jdb_module::Cmd const * +Jdb_tbuf_show::cmds() const +{ + static Cmd cs[] = + { + { 0, "T", "tbuf", "", + "T{P{+|-|k|u|}}\tenter tracebuffer, on/off/kernel/user perf", + 0 }, + { 1, "Tgzip", "", "", 0 /* invisible */, 0 }, + }; + + return cs; +} + +PUBLIC +int +Jdb_tbuf_show::num_cmds() const +{ + return 2; +} + +IMPLEMENT +Jdb_tbuf_show::Jdb_tbuf_show() + : Jdb_module("MONITORING") +{} + +static Jdb_tbuf_show jdb_tbuf_show INIT_PRIORITY(JDB_MODULE_INIT_PRIO); diff --git a/kernel/fiasco/src/jdb/jdb_tcb.cpp b/kernel/fiasco/src/jdb/jdb_tcb.cpp new file mode 100644 index 00000000..8f33fde3 --- /dev/null +++ b/kernel/fiasco/src/jdb/jdb_tcb.cpp @@ -0,0 +1,990 @@ +INTERFACE: + +#include "l4_types.h" + +class Thread; + + +//----------------------------------------------------------------- +IMPLEMENTATION: + +#include +#include + +#include "entry_frame.h" +#include "jdb.h" +#include "jdb_disasm.h" +#include "jdb_handler_queue.h" +#include "jdb_input.h" +#include "jdb_kobject.h" +#include "jdb_kobject_names.h" +#include "jdb_module.h" +#include "jdb_screen.h" +#include "jdb_thread.h" +#include "jdb_util.h" +#include "kernel_console.h" +#include "kernel_task.h" +#include "keycodes.h" +#include "l4_types.h" +#include "push_console.h" +#include "simpleio.h" +#include "static_init.h" +#include "task.h" +#include "thread_object.h" +#include "thread_state.h" +#include "types.h" + +IMPLEMENTATION [32bit]: +#define ADDR_FMT "%08lx" + +IMPLEMENTATION [64bit]: +#define ADDR_FMT "%016lx" + + +IMPLEMENTATION: + +class Jdb_tcb_ptr +{ +public: + Jdb_tcb_ptr(Address addr = 0) + : _base(addr & ~(Context::Size-1)), + _offs(addr & (Context::Size-1)) + {} + + Jdb_tcb_ptr(Jdb_tcb_ptr const &p) + : _base(p.base()), _offs(p.offs()) + {} + + inline bool valid() const + { return _offs <= Context::Size-sizeof(Mword); } + + bool operator > (int offs) const + { + return offs < 0 ? _offs > Context::Size + offs*sizeof(Mword) + : _offs > offs*sizeof(Mword); + } + + Jdb_tcb_ptr &operator += (int offs) + { _offs += offs*sizeof(Mword); return *this; } + + inline Address addr() const + { return _base + _offs; } + + inline Mword value() const + { return *(Mword*)(_base + _offs); } + + inline void value(Mword v) + { *(Mword*)(_base + _offs) = v; } + + inline bool is_user_value() const; + + inline const char *user_value_desc() const; + + inline Mword top_value(int offs) const + { return *((Mword*)(Cpu::stack_align(_base + Context::Size)) + offs); } + + inline Address base() const + { return _base; } + + inline Address offs() const + { return _offs; } + + inline void offs(Address offs) + { _offs = offs; } + + inline bool is_kern_code() const + { return (Address)&Mem_layout::image_start <= value() + && value() <= (Address)&Mem_layout::ecode; }; + + inline bool is_kobject() const + { return Kobject_dbg::is_kobj(reinterpret_cast(value())); } + +private: + Address _base; + Address _offs; +}; + +class Jdb_disasm_view +{ +public: + unsigned _x, _y; +}; + + +class Jdb_stack_view +{ +public: + bool is_current; + Jdb_entry_frame *ef; + Jdb_tcb_ptr current; + unsigned start_y; + Address absy; + Address addy, addx; + bool memdump_is_colored; + + bool edit_registers(); +}; + + +class Jdb_tcb : public Jdb_module, public Jdb_kobject_handler +{ + static Kobject *threadid; + static Address address; + static char first_char; + static char auto_tcb; + +private: + static void print_return_frame_regs(Jdb_tcb_ptr const ¤t, Mword ksp); + static void print_entry_frame_regs(Thread *t); + static void info_thread_state(Thread *t); + + static Jdb_disasm_view _disasm_view; + static Jdb_stack_view _stack_view; +}; + + + +Kobject *Jdb_tcb::threadid; +Address Jdb_tcb::address; +char Jdb_tcb::first_char; +char Jdb_tcb::auto_tcb; +Jdb_disasm_view Jdb_tcb::_disasm_view(Jdb_tcb::Disasm_x, Jdb_tcb::Disasm_y); +Jdb_stack_view Jdb_tcb::_stack_view (Jdb_tcb::Stack_y); + + +// available from jdb_dump module +extern int jdb_dump_addr_task (Address addr, Space *task, int level) + __attribute__((weak)); + +PUBLIC +Jdb_stack_view::Jdb_stack_view(unsigned y) +: start_y(y), absy(0), memdump_is_colored(true) +{} + +PUBLIC static inline +Mword +Jdb_stack_view::cols() +{ + return Jdb_screen::cols() - 1; +} + +PUBLIC static inline +Mword +Jdb_stack_view::bytes_per_line() +{ return cols() * sizeof(Mword); } + +PUBLIC +void +Jdb_stack_view::init(Address ksp, Jdb_entry_frame *_ef, bool _is_current) +{ + current = Jdb_tcb_ptr(ksp); + + absy = current.offs() / bytes_per_line(); + addx = (current.offs() % bytes_per_line()) / sizeof(Mword); + addy = 0; + ef = _ef; + is_current = _is_current; +} + +PUBLIC +void +Jdb_stack_view::print_value(Jdb_tcb_ptr const &p, bool highl = false) +{ + if (!p.valid() || !Jdb_util::is_mapped((void const*)p.addr())) + { + printf(" %.*s", Jdb_screen::Mword_size_bmode, Jdb_screen::Mword_not_mapped); + return; + } + + const char *s1="", *s2=""; + if (highl) + { + s1 = Jdb::esc_emph; + s2 = JDB_ANSI_END; + } + else if (p.is_user_value()) + { + s1 = Jdb::esc_iret; + s2 = JDB_ANSI_END; + } + else if (memdump_is_colored) + { + if (p.is_kern_code()) + { + s1 = JDB_ANSI_COLOR(lightblue); + s2 = JDB_ANSI_END; + } + else if (p.is_kobject()) + { + s1 = JDB_ANSI_COLOR(lightgreen); + s2 = JDB_ANSI_END; + } + /* else if (p.in_backtrace(... + { + s1 = Jdb::esc_bt; + s2 = "\033[m"; + } */ + } + + printf(" %s" ADDR_FMT "%s", s1, p.value(), s2); +} + + +PUBLIC +void +Jdb_stack_view::dump()//Jdb_tcb_ptr const ¤t) +{ + Jdb_tcb_ptr p = current; + p.offs(absy * bytes_per_line()); + + Jdb::cursor(start_y, 1); + + for (unsigned y = 0; y < Jdb_screen::height() - start_y; ++y) + { + Kconsole::console()->getchar_chance(); + + if (p.valid()) + { + printf(" %03lx ", p.addr() & 0xfff); + for (unsigned x = 0; x < cols(); ++x, p+=1) + print_value(p); + putchar('\n'); + } + else + puts("\033[K"); + } +} + +PRIVATE inline +unsigned +Jdb_stack_view::posx() +{ return addx * (Jdb_screen::Mword_size_bmode + 1) + 9; } + +PRIVATE inline +unsigned +Jdb_stack_view::posy() +{ return addy + start_y; } + +PUBLIC +void +Jdb_stack_view::highlight(bool highl) +{ + current.offs(absy*bytes_per_line() + addy*bytes_per_line() + addx * sizeof(Mword)); + Jdb_tcb_ptr first_col = current; + first_col.offs(absy*bytes_per_line() + addy*bytes_per_line()); + + if (!current.valid()) + return; + + Jdb::cursor(posy(), 1); + if (highl) + printf("%08lx", current.addr() & 0xffffffff); + else + printf(" %03lx ", first_col.addr() & 0xfff); + Jdb::cursor(posy(), posx()); + print_value(current, highl); + + char kobj_desc[120]; + kobj_desc[0] = 0; + Kobject_dbg::Iterator o; + + if (current.is_kern_code()) + strcpy(kobj_desc, "Kernel code"); // todo: print kernel function name + else if (current.is_user_value()) + snprintf(kobj_desc, sizeof(kobj_desc), "Return frame: %s", + current.user_value_desc()); + else + if ((o = Kobject_dbg::pointer_to_obj(reinterpret_cast(current.value()))) != Kobject_dbg::end()) + { + Jdb_kobject::obj_description(kobj_desc, sizeof(kobj_desc), true, *o); + kobj_desc[sizeof(kobj_desc) - 1] = 0; + } + + Jdb::printf_statline("tcb", "=dump =Disas", + "%s", kobj_desc); +} + +PUBLIC +bool +Jdb_stack_view::handle_key(int key, bool *redraw) +{ + Mword lines = Jdb_screen::height() - start_y; + Mword max_lines = (Context::Size + bytes_per_line() - 1)/bytes_per_line(); + Address max_absy = max_lines - lines; + + if (lines > max_lines) + max_absy = 0; + + if (lines > max_lines - absy) + lines = max_lines - absy; + + if (key == 'e') + edit_stack(redraw); + else + return Jdb::std_cursor_key(key, this->cols(), lines, max_absy, + &absy, &addy, &addx, redraw); + + return true; +} + +PUBLIC +void +Jdb_stack_view::edit_stack(bool *redraw) +{ + if (current.valid()) + { + Mword value; + int c; + + Jdb::cursor(posy(), posx()); + printf(" %.*s", Jdb_screen::Mword_size_bmode, Jdb_screen::Mword_blank); + Jdb::printf_statline("tcb", + is_current ? "=edit registers" : 0, + "edit <" ADDR_FMT "> = " ADDR_FMT, + current.addr(), current.value()); + + Jdb::cursor(posy(), posx() + 1); + c = Jdb_core::getchar(); + + if (c==KEY_ESC) + { + *redraw = true; + return; + } + + if (c != ' ' || !is_current) + { + // edit memory + putchar(c); + Jdb::printf_statline("tcb", 0, "edit <" ADDR_FMT "> = " ADDR_FMT, + current.addr(), current.value()); + Jdb::cursor(posy(), posx() + 1); + if (!Jdb_input::get_mword(&value, c, 16)) + { + Jdb::cursor(posy(), posx()); + print_value(current); + return; + } + else + current.value(value); + } + else + { + // edit registers + Jdb::cursor(posy(), posx()); + print_value(current); + edit_registers(); + return; + } + *redraw = true; + } +} + +PUBLIC +Jdb_disasm_view::Jdb_disasm_view(unsigned x, unsigned y) +: _x(x), _y(y) +{} + +PUBLIC +void +Jdb_disasm_view::show(Jdb_tcb_ptr const &p, Space *s) +{ + if (!Jdb_disasm::avail()) + return; + + Address disass_addr = p.top_value(-5); + Jdb::cursor(_y, _x); + putstr(Jdb::esc_emph); + Jdb_disasm::show_disasm_line(-40, disass_addr, 0, s); + putstr("\033[m"); + Jdb::cursor(_y + 1, _x); + Jdb_disasm::show_disasm_line(-40, disass_addr, 0, s); +} + + +PUBLIC +Jdb_tcb::Jdb_tcb() + : Jdb_module("INFO"), Jdb_kobject_handler(Thread_object::static_kobj_type) +{ + static Jdb_handler enter(at_jdb_enter); + + Jdb::jdb_enter.add(&enter); + Jdb_kobject::module()->register_handler(this); +} + +static void +Jdb_tcb::at_jdb_enter() +{ + if (auto_tcb) + { + // clear any keystrokes in queue + Jdb::set_next_cmd(0); + Jdb::push_cons()->push('t'); + Jdb::push_cons()->push(' '); + } +} + + +PUBLIC virtual +Kobject * +Jdb_tcb::parent(Kobject *o) +{ + Thread *t = Kobject::dcast(o); + if (!t) + return 0; + + return static_cast(t->space()); +} + +PRIVATE static inline +char * +Jdb_tcb::vcpu_state_str(Mword state, char *s, int len) +{ + snprintf(s, len, "%c%c%c%c%c%c", + (state & Vcpu_state::F_fpu_enabled) ? 'F' : 'f', + (state & Vcpu_state::F_user_mode) ? 'U' : 'u', + (state & Vcpu_state::F_debug_exc) ? 'D' : 'd', + (state & Vcpu_state::F_exceptions) ? 'E' : 'e', + (state & Vcpu_state::F_page_faults) ? 'P' : 'p', + (state & Vcpu_state::F_irqs) ? 'I' : 'i'); + s[len - 1] = 0; + return s; +} + +PUBLIC static +Jdb_module::Action_code +Jdb_tcb::show(Thread *t, int level) +{ + Thread *t_current = Jdb::get_current_active(); + bool is_current_thread; + bool redraw_screen = true; + Jdb_entry_frame *ef = Jdb::get_entry_frame(Jdb::current_cpu); +#if 0 + Address bt_start = 0; +#endif + + if (!t && !t_current) + { +#if 0 + const Mword mask + = (Context::Size * Mem_layout::max_threads()) - 1; + const Mword tsksz = Context::Size*L4_uid::threads_per_task(); + LThread_num task = ((Address)Jdb::get_thread() & mask) / tsksz; +#endif +#if 0 + putchar('\n'); + print_entry_frame_regs(0); +#endif + return NOTHING; + } + + if (!t) + t = t_current; + + is_current_thread = t == t_current; + +#if 0 + if (!t->is_valid()) + { + puts(" Invalid thread"); + return NOTHING; + } +#endif + + if (level==0) + { + Jdb::clear_screen(Jdb::FANCY); + redraw_screen = false; + } + +whole_screen: + + if (redraw_screen) + { + Jdb::clear_screen(Jdb::NOFANCY); + redraw_screen = false; + } + + char time_str[12]; + + putstr("thread : "); + Jdb_kobject::print_uid(t, 3); + print_thread_uid_raw(t); + printf("\tCPU: %u ", t->cpu()); + + printf("\tprio: %02x mode: %s\n", + t->sched()->prio(), + t->mode() & Context::Periodic ? + t->mode() & Context::Nonstrict ? "Per (IRT)" : "Per (SP)" : "Con"); + + printf("state : %03lx ", t->state(false)); + Jdb_thread::print_state_long(t); + + putstr("\nwait for: "); + if (!t->partner()) + putstr("--- "); + else + Jdb_thread::print_partner(t, 4); + + putstr("\tpolling: "); + Jdb_thread::print_snd_partner(t, 3); + + putstr("\trcv descr: "); + + if ((t->state(false) & Thread_ipc_mask) == Thread_receive_wait) + printf("%08lx", t->rcv_regs()->from_spec()); + else + putstr(" "); + + putstr("\n" + "lcked by: "); + if (t->thread_lock()->lock_owner()) + Jdb_kobject::print_uid(static_cast(t->thread_lock()->lock_owner()), 3); + + putstr("\t\t\ttimeout : "); + if (t->_timeout && t->_timeout->is_set()) + { + Signed64 diff = (t->_timeout->get_timeout(Kip::k()->clock)) * 1000; + if (diff < 0) + strcpy(time_str, "over"); + else + Jdb::write_ll_ns(diff, time_str, + 11 < sizeof(time_str)-1 ? 11 : sizeof(time_str)-1, + false); + printf("%-13s", time_str); + } + + putstr("\ncpu time: "); + Jdb::write_ll_ns(t->consumed_time()*1000, time_str, + 11 < sizeof(time_str) ? 11 : sizeof(time_str), false); + printf("%-13s", time_str); + + printf("\t\ttimeslice: %llu/%llu %cs\n" + "pager\t: ", + t->sched()->left(), t->sched()->quantum(), Config::char_micro); + print_kobject(t, t->_pager.raw()); + + putstr("\ttask : "); + if (t->space() == Kernel_task::kernel_task()) + putstr(" kernel "); + else + print_kobject(static_cast(t->space())); + + putstr("\nexc-hndl: "); + print_kobject(t, t->_exc_handler.raw()); + + printf("\tUTCB : %08lx/%08lx", + (Mword)t->utcb().kern(), (Mword)t->utcb().usr().get()); + +#if 0 + putstr("\tready lnk: "); + if (t->state(false) & Thread_ready) + { + if (t->_ready_next) + Jdb_kobject::print_uid(Thread::lookup(t->_ready_next), 3); + else if (is_current_thread) + putstr(" ???.??"); + else + putstr("\033[31;1m???.??\033[m"); + if (t->_ready_prev) + Jdb_kobject::print_uid(Thread::lookup(t->_ready_prev), 4); + else if (is_current_thread) + putstr(" ???.??"); + else + putstr(" \033[31;1m???.??\033[m"); + putchar('\n'); + } + else + puts("--- ---"); +#endif + + putchar('\n'); + + putstr("vCPU : "); + if (t->state(false) & Thread_vcpu_enabled) + { + char st1[7]; + char st2[7]; + Vcpu_state *v = t->vcpu_state().kern(); + printf("%08lx/%08lx S=", (Mword)v, (Mword)t->vcpu_state().usr().get()); + print_kobject(static_cast(t->vcpu_user_space())); + putchar('\n'); + printf("vCPU : c=%s s=%s sf=%c e-ip=%08lx e-sp=%08lx\n", + vcpu_state_str(v->state, st1, sizeof(st1)), + vcpu_state_str(v->_saved_state, st2, sizeof(st2)), + (v->sticky_flags & Vcpu_state::Sf_irq_pending) ? 'P' : '-', + v->_entry_ip, v->_entry_sp); + } + else + putstr("---\nvCPU : ---\n"); + + Address ksp = is_current_thread ? ef->ksp() + : (Address)t->get_kernel_sp(); + +#if 0 + Address tcb = (Address)context_of((void*)ksp); +#endif + _stack_view.init(ksp, ef, is_current_thread); + + if (is_current_thread) + print_entry_frame_regs(t); + + else if (t->space() != Kernel_task::kernel_task()) + { + Jdb::cursor(11, 1); + info_thread_state(t); + putchar('\n'); + print_return_frame_regs(_stack_view.current, ksp); + + _disasm_view.show(_stack_view.current, t->space()); + } + else + { + // kernel thread + Jdb::cursor(15, 1); + printf("kernel SP=" ADDR_FMT, ksp); + } + +dump_stack: + + // dump the stack from ksp bottom right to tcb_top + _stack_view.dump(); + + for (bool redraw=false; ; ) + { + _stack_view.highlight(true); + int c=Jdb_core::getchar(); + _stack_view.highlight(false); + Jdb::cursor(Jdb_screen::height(), 6); + + if (c == KEY_CURSOR_HOME && level > 0) + return GO_BACK; + + if (!_stack_view.handle_key(c, &redraw)) + { + switch (c) + { + case KEY_RETURN: + if (jdb_dump_addr_task && _stack_view.current.valid()) + { + if (!jdb_dump_addr_task(_stack_view.current.value(), + _stack_view.current.is_user_value() ? t->space() : 0, level+1)) + return NOTHING; + redraw_screen = true; + } + break; + case KEY_TAB: + //bt_start = search_bt_start(tcb, (Mword*)ksp, is_current_thread); + redraw = true; + break; + case ' ': + if (Jdb_disasm::avail() && _stack_view.current.valid()) + { + printf("V %lx\n", _stack_view.current.value()); + if (!Jdb_disasm::show(_stack_view.current.value(), + _stack_view.current.is_user_value() ? t->space() : 0, level+1, true)) + return NOTHING; + redraw_screen = true; + } + break; + case 'u': + if (Jdb_disasm::avail() && _stack_view.current.valid()) + { + Jdb::printf_statline("tcb", "=disassemble here", + "u[address=%08lx task=%lx] ", + _stack_view.current.value(), + Kobject_dbg::pointer_to_id(t->space())); + int c1 = Jdb_core::getchar(); + if ((c1 != KEY_RETURN) && (c1 != ' ')) + { + Jdb::printf_statline("tcb", 0, "u"); + Jdb::execute_command("u", c1); + return NOTHING; + } + + if (!Jdb_disasm::show(_stack_view.current.value(), + _stack_view.current.is_user_value() ? t->space() : 0, level+1, true)) + return NOTHING; + redraw_screen = true; + } + break; +#if 0 + case 'r': // ready-list + putstr("[n]ext/[p]revious in ready list?"); + switch (Jdb_core::getchar()) + { + case 'n': + if (t->_ready_next) + { + t = static_cast(t->_ready_next); + goto new_tcb; + } + break; + case 'p': + if (t->_ready_prev) + { + t = static_cast(t->_ready_prev); + goto new_tcb; + } + break; + } + break; +#endif + case 'C': + _stack_view.memdump_is_colored = !_stack_view.memdump_is_colored; + redraw = true; + break; + case KEY_ESC: + Jdb::abort_command(); + return NOTHING; + default: + if (Jdb::is_toplevel_cmd(c)) + return NOTHING; + break; + } + } + if (redraw_screen) + goto whole_screen; + if (redraw) + goto dump_stack; + } +} + +/* --- original L4 screen ------------------------------------------------------ +thread: 0081 (001.01) <00020401 00080000> prio: 10 +state : 85, ready lists: 81 mcp: ff + +wait for: -- rcv descr: 00000000 partner: 00000000 +sndq : 0081 0081 timeouts: 00000000 waddr0/1: 000/000 +cpu time: 0000000000 timeslice: 01/0a + +pager : -- prsent lnk: 0080 0080 +ipreempt: -- ready link : 0080 0080 +xpreempt: -- + soon wakeup lnk: +EAX=00202dfe ESI=00020401 DS=0008 late wakeup lnk: +EBX=00000028 EDI=00080000 ES=0008 +ECX=00000003 EBP=e0020400 +EDX=00000001 ESP=e00207b4 + +700: +720: +740: +760: +780: +7a0: 0000897b 00000020 00240082 +7c0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 +7e0: 00000000 00000000 ffffff80 00000000 0000001b 00003200 00000000 00000013 +L4KD: +------------------------------------------------------------------------------*/ + +PUBLIC +Jdb_module::Action_code +Jdb_tcb::action(int cmd, void *&args, char const *&fmt, int &next_char) +{ + static Address tcb_addr = 0; + if (cmd == 0) + { + if (args == &first_char) + { + switch (first_char) + { + case '+': + case '-': + printf("%c\n", first_char); + auto_tcb = first_char == '+'; + break; + case '?': + args = &address; + fmt = " addr=" ADDR_FMT " => "; + putchar(first_char); + return Jdb_module::EXTRA_INPUT; + case 'a': + args = &tcb_addr; + fmt = " tcb=%x => "; + putchar(first_char); + return Jdb_module::EXTRA_INPUT; + case KEY_RETURN: + show(0, 0); + return NOTHING; + default: + args = &threadid; + fmt = "%q"; + next_char = first_char; + return Jdb_module::EXTRA_INPUT_WITH_NEXTCHAR; + } + } + else if (args == &address) + { + address &= ~(Context::Size-1); + Jdb_kobject::print_uid(reinterpret_cast(address), 3); + putchar('\n'); + } + else if (args == &tcb_addr) + show((Thread*)tcb_addr, 0); + else + { + Thread *t = Kobject::dcast(threadid); + if (t) + show(t, 0); + else + printf("\nNot a thread\n"); + } + } + + return NOTHING; +} + +PUBLIC +Kobject_common * +Jdb_tcb::follow_link(Kobject_common *o) +{ + Thread *t = Kobject::dcast(Kobject::from_dbg(o->dbg_info())); + if (t->space() == Kernel_task::kernel_task()) + return o; + return static_cast(static_cast(t->space())); +} + +PUBLIC +bool +Jdb_tcb::show_kobject(Kobject_common *o, int level) +{ + Thread *t = Kobject::dcast(Kobject::from_dbg(o->dbg_info())); + return show(t, level); +} + +PRIVATE static +bool +Jdb_tcb::is_current(Thread *t) +{ + return t == Jdb::get_thread(t->cpu()); +} + +PUBLIC +int +Jdb_tcb::show_kobject_short(char *buf, int max, Kobject_common *o) +{ + Thread *t = Kobject::dcast(Kobject::from_dbg(o->dbg_info())); + bool is_current = Jdb_tcb::is_current(t); + int cnt = 0; + if (t->space() == Kernel_task::kernel_task()) + { + cnt = snprintf(buf, max, " {KERNEL} C=%u", t->cpu()); + max -= cnt; + buf += cnt; + } + if (t->space() == Kernel_task::kernel_task()) + return cnt + snprintf(buf, max, " R=%ld%s", t->ref_cnt(), + is_current ? " " JDB_ANSI_COLOR(green) "current" JDB_ANSI_END : ""); + + return cnt + snprintf(buf, max, " C=%u S=D:%lx R=%ld %s", t->cpu(), + Kobject_dbg::pointer_to_id(t->space()), + t->ref_cnt(), + is_current ? " " JDB_ANSI_COLOR(green) "current" JDB_ANSI_END : ""); +} + +PUBLIC +char const * +Jdb_tcb::kobject_type() const +{ + return JDB_ANSI_COLOR(green) "Thread" JDB_ANSI_COLOR(default); +} + +PUBLIC +Jdb_module::Cmd const * +Jdb_tcb::cmds() const +{ + static Cmd cs[] = + { + { 0, "t", "tcb", "%C", + "t[]\tshow current/given thread control block (TCB)\n" + "t{+|-}\tshow current thread control block at Jdb every entry\n", + &first_char }, + }; + return cs; +} + +PUBLIC +int +Jdb_tcb::num_cmds() const +{ return 1; } + +static Jdb_tcb jdb_tcb INIT_PRIORITY(JDB_MODULE_INIT_PRIO); + +int +jdb_show_tcb(Thread *t, int level) +{ return Jdb_tcb::show(t, level); } + +static inline +void +Jdb_tcb::print_thread_uid_raw(Thread *t) +{ + printf(" <%p> ", t); +} + +PRIVATE static +void +Jdb_tcb::print_kobject(Mword n) +{ + printf("[C:%4lx] ", n); +} + +PRIVATE static +void +Jdb_tcb::print_kobject(Kobject *o) +{ + printf("D:%4lx ", o ? o->dbg_info()->dbg_id() : 0); +} + +PRIVATE static +void +Jdb_tcb::print_kobject(Thread *t, Mword capidx) +{ + Space *space = t->space(); + if (!space) + { + print_kobject(capidx); + return; + } + + Obj_space::Capability *c = space->get_cap(capidx); + if (!c || !c->valid()) + { + print_kobject(capidx); + return; + } + + printf("[C:%4lx] D:%4lx", capidx, c->obj()->dbg_info()->dbg_id()); +} + +// +//----------------------------------------------------------------------------- +// prompt extension for thread names +class Jdb_thread_name_ext : public Jdb_prompt_ext +{ +public: + void ext(); + void update(); +}; + +IMPLEMENT +void +Jdb_thread_name_ext::ext() +{ + if (Jdb::get_current_active()) + { + Jdb_kobject_name *nx = Jdb_kobject_extension::find_extension(Jdb::get_current_active()); + if (nx && nx->name()[0]) + printf("[%*.*s] ", nx->max_len(), nx->max_len(), nx->name()); + } +} + +IMPLEMENT +void +Jdb_thread_name_ext::update() +{ + Jdb::get_current(Jdb::current_cpu); +} + +static Jdb_thread_name_ext jdb_thread_name_ext INIT_PRIORITY(JDB_MODULE_INIT_PRIO); + diff --git a/kernel/fiasco/src/jdb/jdb_tetris.cpp b/kernel/fiasco/src/jdb/jdb_tetris.cpp new file mode 100644 index 00000000..bd24ae4e --- /dev/null +++ b/kernel/fiasco/src/jdb/jdb_tetris.cpp @@ -0,0 +1,331 @@ +IMPLEMENTATION: + +#include +#include +#include "simpleio.h" + +#include "jdb.h" +#include "jdb_module.h" +#include "static_init.h" +#include "types.h" +#include "cpu.h" +#include "globals.h" +#include "kernel_console.h" +#include "keycodes.h" + +static int lines, score, current_pos, mode, slice, + *current_tile, *next_tile, grid[264], next[48]; + +static int tiles[] = { 9, 9, -13, -12, 1, 4, + 10, 10, -11, -12, -1, 4, + 11, 13, -1, 1, 12, 6, + 3, 3, -13, -12, -1, 2, + 14, 16, -1, 11, 1, 5, + 17, 19, -1, 13, 1, 5, + 20, 20, -1, 1, 2, 1, + 23, 21, -12, 11, 13, 3, + 8, 8, 11, 13, 24, 1, + 0, 0, -12, -1, 11, 4, + 1, 1, -12, 1, 13, 4, + 12, 2, -12, 1, 12, 6, + 13, 11, -12, -1, 1, 6, + 2, 12, -12, -1, 12, 6, + 15, 4, -12, 12, 13, 5, + 16, 14, -11, -1, 1, 5, + 4, 15, -13, -12, 12, 5, + 18, 5, -11, -12, 12, 5, + 19, 17, -13, 1, -1, 5, + 5, 18, -12, 12, 11, 5, + 6, 6, -12, 12, 24, 1, + 7, 22, -13, 1, 11, 3, + 21, 23, -13, -11, 12, 3, + 22, 7, -11, -1, 13, 3 }; + +static const char *modes[] = { "", "Fiasco Mode", "Lars Mode" }; +static long unsigned int randseed; + +IMPLEMENTATION [ux]: + +static unsigned slice_to_timeout(unsigned slice) +{ + slice /= 50; + return slice < 2 ? 2 : slice; +} + +static void show_grid() +{ + int i, j; + + printf ("\033[H"); + + for (i = j = 0; i < 264; i++) + { + if (grid[i]) + printf ("\033[m\033[1;4%d;30m \033[40m", grid[i]); + else + putstr (" "); + + if (i % 12 == 11) + { + for (; j <= i && j < 48; j++) + if (next[j]) + printf ("\033[m\033[1;4%d;30m \033[40m", next[j]); + else + putstr ("\033[m\033[30m \033[m"); + + putchar ('\n'); + } + } + + printf ("\033[mLines: %d Score: %d %s\033[K", lines, score, modes[mode]); +} + +IMPLEMENTATION [!ux]: + +static unsigned slice_to_timeout(unsigned slice) +{ + return slice; +} + +static void show_grid() +{ + int i, j; + + printf ("\033[H"); + + for (i = j = 0; i < 264; i++) + { + if (grid[i]) + printf ("\033[1;3%dm\333\333", grid[i]); + else + putstr (" "); + + if (i % 12 == 11) + { + for (; j <= i && j < 48; j++) + if (next[j]) + printf ("\033[1;3%dm\333\333", next[j]); + else + putstr (" "); + + putchar ('\n'); + } + } + + printf ("Lines: %d Score: %d %s\033[K", lines, score, modes[mode]); +} + +IMPLEMENTATION: + +static int getchar_timeout() +{ + int c; + static unsigned to = slice; + + to = slice_to_timeout(to); + while (--to) + { + if ((c = Kconsole::console()->getchar (false)) != -1) + return c; + + if (Config::getchar_does_hlt_works_ok) + Proc::halt(); + else + Cpu::cpus.cpu(0).busy_wait_ns(1000000ULL); + } + + to = slice; + + return -1; +} + +static void add_score(int value) +{ + if ((score + value) / 1000 != score / 1000) + slice--; + + if (slice < 0) + slice = 0; + + score += value; +} + +static long unsigned int myrand() +{ + randseed = (randseed * 13561+14000) % 150001; + return randseed; +} + +static int *new_tile() +{ + return tiles + myrand() % (7 + mode) * 6; +} + +static int try_move (int pos, int *tile) +{ + if (grid[pos] + grid[pos+tile[2]] + grid[pos+tile[3]] + grid[pos+tile[4]]) + return 0; + + current_tile = tile; + current_pos = pos; + + return 1; +} + +static void set_grid (int color) +{ + grid[current_pos] = + grid[current_pos+current_tile[2]] = + grid[current_pos+current_tile[3]] = + grid[current_pos+current_tile[4]] = color; +} + +static void set_next (int color) +{ + next[17] = + next[17+next_tile[2]] = + next[17+next_tile[3]] = + next[17+next_tile[4]] = color; +} + +void show_tile (void) +{ + set_grid(current_tile[5]); + set_next(next_tile[5]); + + show_grid(); + + set_grid(0); + set_next(0); +} + +/** + * Jdb-tetris module + * + * This module makes fun. + */ +class Jdb_tetris_m + : public Jdb_module +{ +public: + Jdb_tetris_m() FIASCO_INIT; +}; + +static Jdb_tetris_m jdb_tetris_m INIT_PRIORITY(JDB_MODULE_INIT_PRIO); + +IMPLEMENT +Jdb_tetris_m::Jdb_tetris_m() + : Jdb_module("MISC") +{} + +PUBLIC +Jdb_module::Action_code +Jdb_tetris_m::action( int, void *&, char const *&, int & ) +{ + int i, j, k, c; + + lines = score = c = 0; + slice = 300; + randseed= Cpu::rdtsc() & 0xffffffff; + + puts ("\nDisabling output of serial console -- quit Tetris with 'q'!"); + Kconsole::console()->change_state(Console::UART, 0, ~Console::OUTENABLED, 0); + + printf ("\033[H\033[J"); + + // Setup grid borders + for (i = 0; i < 264; i++) + grid[i] = (i % 12 == 0 || i % 12 == 11 || i > 251) ? 7 : 0; + + try_move (17, new_tile()); + next_tile = new_tile(); + + while (1) + { + if (c < 0) + { + if (!try_move (current_pos + 12, current_tile)) + { + set_grid(current_tile[5]); + + for (i = k = 0; i < 252; i += 12) + for (j = i; grid[++j];) + if (j - i == 10) { + while (j > i) grid[j--] = 0; show_grid(); + while (--j) grid[j + 12] = grid[j]; show_grid(); + k++; + } + + lines += k; + add_score (k ? (1 << k) * 10 : 1); + + if (!try_move (17, next_tile)) + break; + + next_tile = new_tile(); + } + } + + // Move left + else if (c == KEY_CURSOR_LEFT) + try_move (current_pos - 1, current_tile); + + // Move right + else if (c == KEY_CURSOR_RIGHT) + try_move (current_pos + 1, current_tile); + + // Drop tile + else if (c == ' ') + while (try_move (current_pos + 12, current_tile)) + { + show_tile(); + add_score(3); + } + + // Left-turn tile + else if (c == KEY_CURSOR_DOWN) + try_move (current_pos, tiles + 6 ** current_tile); + + // Right-turn tile + else if (c == KEY_CURSOR_UP) + try_move (current_pos, tiles + 6 ** (current_tile+1)); + + // Quit + else if (c == 'q' || c == KEY_ESC) + break; + + else if (c == 'm') + if (++mode == 3) + mode = 0; + + show_tile(); + + c = getchar_timeout(); + } + + Kconsole::console()->change_state(Console::UART, 0, ~0U, Console::OUTENABLED); + printf ("\033[0m"); + + return NOTHING; +} + +PUBLIC +int +Jdb_tetris_m::num_cmds() const +{ + return 1; +} + +PUBLIC +Jdb_module::Cmd const * +Jdb_tetris_m::cmds() const +{ + static Cmd cs[] = + { + { 0, "X", "X", "", + "X\tPlay Tetris (cursor keys = left/right/rotate;\n" + "\t[space] = drop; q = quit)", 0 }, + }; + + return cs; +} diff --git a/kernel/fiasco/src/jdb/jdb_thread.cpp b/kernel/fiasco/src/jdb/jdb_thread.cpp new file mode 100644 index 00000000..a6cc9bc6 --- /dev/null +++ b/kernel/fiasco/src/jdb/jdb_thread.cpp @@ -0,0 +1,120 @@ +INTERFACE: + +#include "thread_object.h" + +class Jdb_thread +{ +}; + +IMPLEMENTATION: + +#include "irq.h" +#include "jdb_kobject.h" +#include "kobject.h" +#include "thread_state.h" +#include "vlog.h" + +#include + +PUBLIC static +void +Jdb_thread::print_state_long(Thread *t, unsigned cut_on_len = 0) +{ + static char const * const state_names[] = + { + "ready", "drq_rdy", "send", "rcv_wait", + "rcv_in_progr", "transfer", "", "cancel", + "timeout", "dead", "suspended", "", + "", "", "", "fpu", + "alien", "dealien", "exc_progr", "", + "drq", "lock_wait", "vcpu", "vcpu_user", + "vcpu_fpu_disabled", "vcpu_ext" + }; + + unsigned chars = 0; + bool comma = false; + + Mword bits = t->state(false); + + for (unsigned i = 0; i < sizeof (state_names) / sizeof (char *); + i++, bits >>= 1) + { + if (!(bits & 1)) + continue; + + if (cut_on_len) + { + unsigned add = strlen(state_names[i]) + comma; + if (chars + add > cut_on_len) + { + if (chars < cut_on_len - 4) + putstr(",..."); + break; + } + chars += add; + } + + printf("%s%s", &","[!comma], state_names[i]); + + comma = 1; + } +} + +PUBLIC static +bool +Jdb_thread::has_partner(Thread *t) +{ + return (t->state(false) & Thread_ipc_mask) == Thread_receive_wait; +} + +PUBLIC static +bool +Jdb_thread::has_snd_partner(Thread *t) +{ + return t->state(false) & Thread_send_wait; +} + +PUBLIC static +void +Jdb_thread::print_snd_partner(Thread *t, int task_format = 0) +{ + if (has_snd_partner(t)) + Jdb_kobject::print_uid(Kobject::from_dbg(Kobject_dbg::pointer_to_obj(t->wait_queue())), task_format); + else + // receiver() not valid + putstr(" "); +} + +PUBLIC static +void +Jdb_thread::print_partner(Thread *t, int task_format = 0) +{ + Sender *p = t->partner(); + + if (!has_partner(t)) + { + printf("%*s ", task_format, " "); + return; + } + + if (!p) + { + printf("%*s ", task_format, "-"); + return; + } + + if (Kobject *o = Kobject::from_dbg(Kobject_dbg::pointer_to_obj(p))) + { + char flag = '?'; + const char *n = o->kobj_type(); + + if (n == Thread_object::static_kobj_type) + flag = ' '; + else if (n == Irq::static_kobj_type) + flag = '*'; + + printf("%*.lx%c", task_format, o->dbg_info()->dbg_id(), flag); + } + else + printf("\033[31;1m%p\033[m ", p); +} diff --git a/kernel/fiasco/src/jdb/jdb_thread_list.cpp b/kernel/fiasco/src/jdb/jdb_thread_list.cpp new file mode 100644 index 00000000..58992d8f --- /dev/null +++ b/kernel/fiasco/src/jdb/jdb_thread_list.cpp @@ -0,0 +1,872 @@ +IMPLEMENTATION: + +#include +#include +#include + +#include "jdb.h" +#include "jdb_core.h" +#include "jdb_module.h" +#include "jdb_screen.h" +#include "jdb_thread.h" +#include "jdb_kobject_names.h" +#include "kernel_console.h" +#include "keycodes.h" +#include "minmax.h" +#include "simpleio.h" +#include "task.h" +#include "thread.h" +#include "thread_state.h" +#include "static_init.h" + +class Jdb_thread_list : public Jdb_module +{ +public: + Jdb_thread_list() FIASCO_INIT; +private: + static char subcmd; + static char long_output; + static unsigned cpu; + +private: + static int _mode; + static int _count; + static char _pr; + static Thread *_t_head, *_t_start; + + friend class _foo; + + enum { LIST_UNSORTED, LIST_SORT_PRIO, LIST_SORT_TID, LIST_SORT_SPACE, + LIST_SORT_END }; + +}; + +char Jdb_thread_list::subcmd; +char Jdb_thread_list::long_output; +unsigned Jdb_thread_list::cpu; + + +// available from the jdb_tcb module +extern int jdb_show_tcb(Thread* thread, int level) + __attribute__((weak)); + +char Jdb_thread_list::_pr; +int Jdb_thread_list::_mode = LIST_SORT_TID; +int Jdb_thread_list::_count; + +Thread *Jdb_thread_list::_t_head; +Thread *Jdb_thread_list::_t_start; + +PUBLIC static +void +Jdb_thread_list::init(char pr, Thread *t_head) +{ + _pr = pr; + _t_head = t_head; +} + +// return string describing current sorting mode of list +PUBLIC static inline NOEXPORT +const char* +Jdb_thread_list::get_mode_str(void) +{ + static const char * const mode_str[] = + { "(unsorted)", "(prio-sorted)", "(tid-sorted)", "(space-sorted)" }; + + return mode_str[_mode]; +} + +// switch to next sorting mode +PUBLIC static +void +Jdb_thread_list::switch_mode(void) +{ + if (++_mode >= LIST_SORT_END) + _mode = LIST_UNSORTED; +} + +// set _t_start element of list +PUBLIC static +void +Jdb_thread_list::set_start(Thread *t_start) +{ + _t_start = t_start; + iter(+Jdb_screen::height()-3, &_t_start); + iter(-Jdb_screen::height()+3, &_t_start); +} + +// _t_start-- if possible +PUBLIC static +int +Jdb_thread_list::line_back(void) +{ + return iter(-1, &_t_start); +} + +// _t_start++ if possible +PUBLIC static +int +Jdb_thread_list::line_forw(void) +{ + Thread *t = _t_start; + iter(+Jdb_screen::height()-2, &_t_start); + iter(-Jdb_screen::height()+3, &_t_start); + return t != _t_start; +} + +// _t_start -= 24 if possible +PUBLIC static +int +Jdb_thread_list::page_back(void) +{ + return iter(-Jdb_screen::height()+2, &_t_start); +} + +// _t_start += 24 if possible +PUBLIC static +int +Jdb_thread_list::page_forw(void) +{ + Thread *t = _t_start; + iter(+Jdb_screen::height()*2-5, &_t_start); + iter(-Jdb_screen::height() +3, &_t_start); + return t != _t_start; +} + +// _t_start = first element of list +PUBLIC static +int +Jdb_thread_list::goto_home(void) +{ + return iter(-9999, &_t_start); +} + +// _t_start = last element of list +PUBLIC static +int +Jdb_thread_list::goto_end(void) +{ + Thread *t = _t_start; + iter(+9999, &_t_start); + iter(-Jdb_screen::height()+2, &_t_start); + return t != _t_start; +} + +// search index of t_search starting from _t_start +PUBLIC static +int +Jdb_thread_list::lookup(Thread *t_search) +{ + unsigned i; + Thread *t; + + for (i=0, t=_t_start; isched()->prio(); +} + +// helper function for iter() -- use thread id as sorting key +static +long +Jdb_thread_list::get_tid(Thread *t) +{ + return t->dbg_info()->dbg_id(); +} + +// helper function for iter() -- use space as sorting key +static +long +Jdb_thread_list::get_space_dbgid(Thread *t) +{ + return Kobject_dbg::pointer_to_id(t->space()); +} + + +// -------------------------------------------------------------------------- +IMPLEMENTATION [sched_wfq || sched_fp_wfq]: + +template struct Jdb_thread_list_policy; + +template +static inline NOEXPORT +Sched_context * +Jdb_thread_list::sc_wfq_iter_prev(Sched_context *t) +{ + Sched_context::Ready_queue &rq = Sched_context::rq(cpu); + Sched_context **rl = RQP::link(t); + if (!rl || rl == RQP::idle(rq)) + return RQP::cnt(rq) ? RQP::heap(rq)[RQP::cnt(rq) - 1] : *RQP::idle(rq); + + if (rl == RQP::heap(rq)) + return *RQP::idle(rq); + + return *(rl - 1); +} + +template +static inline NOEXPORT +Sched_context * +Jdb_thread_list::sc_wfq_iter_next(Sched_context *t) +{ + Sched_context::Ready_queue &rq = Sched_context::rq(cpu); + Sched_context **rl = RQP::link(t); + if (!rl || rl == RQP::idle(rq)) + return RQP::cnt(rq) ? RQP::heap(rq)[0] : *RQP::idle(rq); + + if ((unsigned)(rl - RQP::heap(rq)) >= RQP::cnt(rq)) + return *RQP::idle(rq); + + return *(rl + 1); +} + + +// -------------------------------------------------------------------------- +IMPLEMENTATION [sched_fixed_prio || sched_fp_wfq]: + +template struct Jdb_thread_list_policy; + +template +static inline NOEXPORT +Sched_context * +Jdb_thread_list::sc_fp_iter_prev(Sched_context *t) +{ + unsigned prio = RQP::prio(t); + Sched_context::Ready_queue &rq = Sched_context::_ready_q.cpu(cpu); + + if (t != RQP::prio_next(rq, prio)) + return RQP::prev(t); + + for (;;) + { + if (++prio > RQP::prio_highest(rq)) + prio = 0; + if (RQP::prio_next(rq, prio)) + return RQP::prev(RQP::prio_next(rq, prio)); + } +} + +template +static inline NOEXPORT +Sched_context * +Jdb_thread_list::sc_fp_iter_next(Sched_context *t) +{ + unsigned prio = RQP::prio(t); + Sched_context::Ready_queue &rq = Sched_context::_ready_q.cpu(cpu); + + if (RQP::next(t) != RQP::prio_next(rq, prio)) + return RQP::next(t); + + for (;;) + { + if (--prio > RQP::prio_highest(rq)) // prio is unsigned + prio = RQP::prio_highest(rq); + if (RQP::prio_next(rq, prio)) + return RQP::prio_next(rq, prio); + } +} + +// -------------------------------------------------------------------------- +IMPLEMENTATION [sched_fixed_prio]: + +template<> +struct Jdb_thread_list_policy > +{ + typedef Ready_queue_fp Rq; + + static unsigned prio(Sched_context *t) + { return t->prio(); } + + static Sched_context *prio_next(Sched_context::Ready_queue &rq, unsigned prio) + { return rq.prio_next[prio].front(); } + + static unsigned prio_highest(Sched_context::Ready_queue &rq) + { return rq.prio_highest; } + + static Sched_context *prev(Sched_context *t) + { return *--Rq::List::iter(t); } + + static Sched_context *next(Sched_context *t) + { return *++Rq::List::iter(t); } +}; + +static inline NOEXPORT +Sched_context * +Jdb_thread_list::sc_iter_prev(Sched_context *t) +{ return sc_fp_iter_prev > >(t); } + +static inline NOEXPORT +Sched_context * +Jdb_thread_list::sc_iter_next(Sched_context *t) +{ return sc_fp_iter_next > >(t); } + +// -------------------------------------------------------------------------- +IMPLEMENTATION [sched_wfq]: + +template<> +struct Jdb_thread_list_policy > +{ + static Sched_context **link(Sched_context *t) + { return t->_ready_link; } + + static Sched_context **heap(Sched_context::Ready_queue &rq) + { return rq._heap; } + + static Sched_context **idle(Sched_context::Ready_queue &rq) + { return &rq.idle; } + + static unsigned cnt(Sched_context::Ready_queue &rq) + { return rq._cnt; } +}; + +static inline NOEXPORT +Sched_context * +Jdb_thread_list::sc_iter_prev(Sched_context *t) +{ return sc_wfq_iter_prev > >(t); } + +static inline NOEXPORT +Sched_context * +Jdb_thread_list::sc_iter_next(Sched_context *t) +{ return sc_wfq_iter_next > >(t); } + + +// -------------------------------------------------------------------------- +IMPLEMENTATION [sched_fp_wfq]: + +static inline NOEXPORT +Sched_context * +Jdb_thread_list::sc_iter_prev(Sched_context *) +{ + return 0; +} + +static inline NOEXPORT +Sched_context * +Jdb_thread_list::sc_iter_next(Sched_context *) +{ + return 0; +} + + +// -------------------------------------------------------------------------- +IMPLEMENTATION: + + +static inline NOEXPORT +Thread* +Jdb_thread_list::iter_prev(Thread *t) +{ + if (_pr == 'p') + { + Kobject_dbg::Iterator o = Kobject_dbg::Kobject_list::iter(t->dbg_info()); + do + { + --o; + if (o == Kobject_dbg::end()) + --o; + } + while (!Kobject::dcast(Kobject::from_dbg(*o))); + return Kobject::dcast(Kobject::from_dbg(*o)); + } + else + return static_cast(sc_iter_prev(t->sched())->context()); +} + + +static inline NOEXPORT +Thread* +Jdb_thread_list::iter_next(Thread *t) +{ + if (_pr == 'p') + { + Kobject_dbg::Iterator o = Kobject_dbg::Kobject_list::iter(t->dbg_info()); + do + { + ++o; + if (o == Kobject_dbg::end()) + ++o; + } + while (!Kobject::dcast(Kobject::from_dbg(*o))); + return Kobject::dcast(Kobject::from_dbg(*o)); + } + else + return static_cast(sc_iter_next(t->sched())->context()); +} + +// walk though list times +// abort walking if no more elements +// do iter if iter != 0 +static +bool +Jdb_thread_list::iter(int count, Thread **t_start, + void (*iter)(Thread *t)=0) +{ + int i = 0; + int forw = (count >= 0); + Thread *t, *t_new = *t_start, *t_head = _t_head; + long (*get_key)(Thread *t) = 0; + + if (count == 0) + return false; // nothing changed + + if (count < 0) + count = -count; + + // if we are stepping backwards, begin at end-of-list + if (!forw) + t_head = iter_prev(t_head); + + switch (_mode) + { + case LIST_UNSORTED: + // list threads in order of list + if (iter) + iter(*t_start); + + t = *t_start; + do + { + t = forw ? iter_next(t) : iter_prev(t); + + if (t == t_head) + break; + + if (iter) + iter(t); + + t_new = t; + i++; + + } while (i < count); + break; + + case LIST_SORT_PRIO: + // list threads sorted by priority + case LIST_SORT_SPACE: + // list threads sorted by space + if (!get_key) + get_key = (_mode == LIST_SORT_SPACE) ? get_space_dbgid : get_prio; + + // fall through + + case LIST_SORT_TID: + // list threads sorted by thread id + { + long key; + int start_skipped = 0; + + if (!get_key) + get_key = get_tid; + + long key_current = get_key(*t_start); + long key_next = (forw) ? LONG_MIN : LONG_MAX; + t = t_head; + if (iter) + iter(*t_start); + do + { + if (t == *t_start) + start_skipped = 1; + + key = get_key(t); + // while walking through the current list, look for next key + if ( ( forw && (key > key_next) && (key < key_current)) + || (!forw && (key < key_next) && (key > key_current))) + key_next = key; + + if (t_head == (t = (forw) ? iter_next(t) : iter_prev(t))) + { + if ( ( forw && (key_next == LONG_MIN)) + || (!forw && (key_next == LONG_MAX))) + break; + key_current = key_next; + key_next = forw ? LONG_MIN : LONG_MAX; + } + + if (start_skipped && (get_key(t) == key_current)) + { + if (iter) + iter(t); + + i++; + t_new = t; + } + } while (i < count); + } + break; + } + + _count = i; + + bool changed = (*t_start != t_new); + *t_start = t_new; + + return changed; +} + +// show complete page using show callback function +PUBLIC static +int +Jdb_thread_list::page_show(void (*show)(Thread *t)) +{ + Thread *t = _t_start; + + iter(Jdb_screen::height()-3, &t, show); + return _count; +} + +// show complete list using show callback function +PUBLIC static +int +Jdb_thread_list::complete_show(void (*show)(Thread *t)) +{ + Thread *t = _t_start; + + iter(9999, &t, show); + return _count; +} + +IMPLEMENT +Jdb_thread_list::Jdb_thread_list() + : Jdb_module("INFO") +{} + +PUBLIC +Jdb_module::Action_code +Jdb_thread_list::action(int cmd, void *&argbuf, char const *&fmt, int &) +{ + static char const *const cpu_fmt = " cpu=%i\n"; + static char const *const nfmt = ""; + if (cmd == 0) + { + if (fmt != cpu_fmt && fmt != nfmt) + { + if (subcmd == 'c') + { + argbuf = &cpu; + fmt = cpu_fmt; + } + else + fmt = nfmt; + return EXTRA_INPUT; + } + + Thread *t = Jdb::get_current_active(); + switch (subcmd) + { + case 'r': cpu = 0; list_threads(t, 'r'); break; + case 'p': list_threads(t, 'p'); break; + case 'c': + if (Cpu::online(cpu)) + list_threads(Jdb::get_thread(cpu), 'r'); + else + printf("\nCPU %u is not online!\n", cpu); + cpu = 0; + break; + case 't': Jdb::execute_command("lt"); break; // other module + case 's': Jdb::execute_command("ls"); break; // other module + } + } + else if (cmd == 1) + { + Console *gzip = Kconsole::console()->find_console(Console::GZIP); + if (gzip) + { + Thread *t = Jdb::get_current_active(); + gzip->state(gzip->state() | Console::OUTENABLED); + long_output = 1; + Jdb_thread_list::init('p', t); + Jdb_thread_list::set_start(t); + Jdb_thread_list::goto_home(); + Jdb_thread_list::complete_show(list_threads_show_thread); + long_output = 0; + gzip->state(gzip->state() & ~Console::OUTENABLED); + } + else + puts(" gzip module not available"); + } + + return NOTHING; +} + +PRIVATE static inline +void +Jdb_thread_list::print_thread_name(Kobject_common const * o) +{ + Jdb_kobject_name *nx = Jdb_kobject_extension::find_extension(o); + unsigned len = 15; + + if (nx) + { + len = min(nx->max_len(), len); + printf("%-*.*s", len, len, nx->name()); + } + else + printf("%-*.*s", len, len, "-----"); +} + +static void +Jdb_thread_list::list_threads_show_thread(Thread *t) +{ + char to[24]; + int waiting_for = 0; + + *to = '\0'; + + Kconsole::console()->getchar_chance(); + + Jdb_kobject::print_uid(t, 5); + + printf(" %-3u ", t->cpu()); + + print_thread_name(t); + + printf(" %2lx ", get_prio(t)); + + if (get_space_dbgid(t) == ~0L) + printf(" ----- "); + else + printf(" %5lx ", get_space_dbgid(t)); + + if (Jdb_thread::has_partner(t)) + { + Jdb_thread::print_partner(t, 5); + waiting_for = 1; + } + else if (Jdb_thread::has_snd_partner(t)) + { + Jdb_thread::print_snd_partner(t, 5); + putchar(' '); + waiting_for = 1; + } + else + putstr(" "); + + if (waiting_for) + { + if (t->_timeout && t->_timeout->is_set()) + { + Signed64 diff = (t->_timeout->get_timeout(Kip::k()->clock)); + if (diff < 0) + strcpy(to, " over"); + else if (diff >= 100000000LL) + strcpy(to, " >99s"); + else + { + int us = (int)diff; + if (us < 0) + us = 0; + if (us >= 1000000) + snprintf(to, sizeof(to), " %3us", us / 1000000); + else if (us >= 1000) + snprintf(to, sizeof(to), " %3um", us / 1000); + else + snprintf(to, sizeof(to), " %3u%c", us, Config::char_micro); + } + } + } + + printf("%-6s", to); + + if (long_output) + { + Jdb_thread::print_state_long(t, 47); + putchar('\n'); + } + else + { + if (Config::Stack_depth) + { + Mword i, stack_depth; + char *c = (char*)t + sizeof (Thread); + for (i = sizeof (Thread), stack_depth = Context::Size; + i < Context::Size; + i++, stack_depth--, c++) + if (*c != '5') + break; + + printf("(%4ld) ", stack_depth - sizeof (Thread)); + Jdb_thread::print_state_long(t, 23); + } + else + Jdb_thread::print_state_long(t, 30); + putstr("\033[K\n"); + } +} + +static void +Jdb_thread_list::show_header() +{ + Jdb::cursor(); + printf("%s id cpu name pr sp wait to%s state\033[m\033[K", + Jdb::esc_emph, Config::Stack_depth ? " stack" : ""); +} + +static void +Jdb_thread_list::list_threads(Thread *t_start, char pr) +{ + unsigned y, y_max; + Thread *t, *t_current = t_start; + + { + // Hm, we are in JDB, however we have to make the assertion in + // ready_enqueue happy. + Lock_guard g(&cpu_lock); + // enqueue current, which may not be in the ready list due to lazy queueing + if (!t_current->in_ready_list()) + t_current->ready_enqueue(false); + } + + Jdb::clear_screen(); + show_header(); + Jdb_thread_list::init(pr, t_current); + + for (;;) + { + Jdb_thread_list::set_start(t_current); + + // set y to position of t_current in current displayed list + y = Jdb_thread_list::lookup(t_current); + + for (bool resync=false; !resync;) + { + Jdb::cursor(2, 1); + y_max = Jdb_thread_list::page_show(list_threads_show_thread); + + // clear rest of screen (if where less than 24 lines) + for (unsigned i=y_max; i < Jdb_screen::height()-3; i++) + putstr("\033[K\n"); + + Jdb::printf_statline(pr=='r' ? "ready list" : "present list", + "=mode " /*"=partner "*/ "=select", + "%-15s", Jdb_thread_list::get_mode_str()); + + // key event loop + for (bool redraw=false; !redraw; ) + { + Jdb::cursor(y+2, 6); + switch (int c=Jdb_core::getchar()) + { + case KEY_CURSOR_UP: + case 'k': + if (y > 0) + y--; + else + redraw = Jdb_thread_list::line_back(); + break; + case KEY_CURSOR_DOWN: + case 'j': + if (y < y_max) + y++; + else + redraw = Jdb_thread_list::line_forw(); + break; + case KEY_PAGE_UP: + case 'K': + if (!(redraw = Jdb_thread_list::page_back())) + y = 0; + break; + case KEY_PAGE_DOWN: + case 'J': + if (!(redraw = Jdb_thread_list::page_forw())) + y = y_max; + break; + case KEY_CURSOR_HOME: + case 'H': + redraw = Jdb_thread_list::goto_home(); + y = 0; + break; + case KEY_CURSOR_END: + case 'L': + redraw = Jdb_thread_list::goto_end(); + y = y_max; + break; + case ' ': // switch mode + t_current = Jdb_thread_list::index(y); + Jdb_thread_list::switch_mode(); + redraw = true; + resync = true; + break; +#if 0 + case KEY_TAB: // goto thread we are waiting for + t = Jdb_thread_list::index(y); + if (t->partner() + && (t->state(false) & (Thread_receiving | + Thread_busy | + Thread_rcvlong_in_progress)) + && (!t->partner()->id().is_irq() || + t->partner()->id().irq() > Config::Max_num_dirqs)) + { + t_current = static_cast(t->partner()); + redraw = true; + resync = true; + } + break; +#endif + case KEY_RETURN: // show current tcb + if (jdb_show_tcb != 0) + { + t = Jdb_thread_list::index(y); + if (!jdb_show_tcb(t, 1)) + return; + show_header(); + redraw = 1; + } + break; + case KEY_ESC: + Jdb::abort_command(); + return; + default: + if (Jdb::is_toplevel_cmd(c)) + return; + } + } + } + } +} + + +PUBLIC +Jdb_module::Cmd const * +Jdb_thread_list::cmds() const +{ + static Cmd cs[] = + { + { 0, "l", "list", "%C", "l{r|p}\tshow ready/present list", &subcmd }, + { 1, "lgzip", "", "", 0 /* invisible */, 0 }, + }; + + return cs; +} + +PUBLIC +int +Jdb_thread_list::num_cmds() const +{ + return 2; +} + +static Jdb_thread_list jdb_list_threads INIT_PRIORITY(JDB_MODULE_INIT_PRIO); diff --git a/kernel/fiasco/src/jdb/jdb_timeout.cpp b/kernel/fiasco/src/jdb/jdb_timeout.cpp new file mode 100644 index 00000000..9b743d21 --- /dev/null +++ b/kernel/fiasco/src/jdb/jdb_timeout.cpp @@ -0,0 +1,447 @@ +IMPLEMENTATION: + +#include +#include + +#include "config.h" +#include "globals.h" +#include "ipc_timeout.h" +#include "jdb.h" +#include "jdb_kobject.h" +#include "jdb_kobject_names.h" +#include "jdb_module.h" +#include "jdb_screen.h" +#include "kernel_console.h" +#include "keycodes.h" +#include "kmem.h" +#include "simpleio.h" +#include "static_init.h" +#include "timeout.h" +#include "timeslice_timeout.h" +#include "thread.h" + +class Jdb_list_timeouts : public Jdb_module +{ +public: + Jdb_list_timeouts() FIASCO_INIT; +private: + enum + { + Timeout_ipc = 1, + Timeout_deadline = 2, + Timeout_timeslice = 3 + }; +}; + + +namespace { + +class Timeout_iter +{ +private: + typedef Timeout::To_list::Const_iterator To_iter; + + int skip_empty(To_iter *c, int i) + { + while (*c == _q->first(i).end() && i < (int)_q->queues()) + { + ++i; + *c = _q->first(i).begin(); + } + return i; + } + +public: + explicit Timeout_iter(Timeout_q *t) + : _q(t), _i(0) + { rewind(); } + + explicit Timeout_iter(Timeout_q *t, bool) + : _q(t), _c(t->first(0).end()), _i(0) + {} + + void rewind() + { + _i = 0; + _c = _q->first(0).begin(); + _i = skip_empty(&_c, _i); + } + + Timeout_iter const &operator ++ () + { + if (_c == _q->first(_i).end()) + return *this; + + ++_c; + _i = skip_empty(&_c, _i); + + return *this; + } + + Timeout *operator * () const { return *_c; } + + bool operator == (Timeout_iter const &o) const + { return _c == o._c; } + + bool operator != (Timeout_iter const &o) const + { return _c != o._c; } + +private: + Timeout_q *_q; + To_iter _c; + int _i; +}; + +template< typename FWD_ITER > +class Rnd_container +{ +public: + explicit Rnd_container(FWD_ITER const &b, FWD_ITER const &e) + : _b(b), _e(e), _cnt(0) + { + for (FWD_ITER i = b; i != e; ++i) + ++_cnt; + } + + class Iterator : public FWD_ITER + { + public: + Iterator() {} + + Iterator const &operator += (int offs) + { + if (offs < 0) + return operator -= (-offs); + + if (offs == 0) + return *this; + + for (; *this != _c->_e && offs > 0; --offs, ++_p) + this->operator ++ (); + + return *this; + } + + Iterator const &operator -= (int offs) + { + if (offs < 0) + return this->operator += (-offs); + + if (offs == 0) + return *this; + + int p = 0; + + if (_p > (unsigned)offs) + p = _p - offs; + + FWD_ITER i = _c->_b; + + for (int z = 0; z < p && i != _c->_e; ++i, ++z) + ; + + *this = Iterator(_c, p, i); + return *this; + } + + Iterator const &operator -- () + { return this->operator -= (1); } + + int pos() const { return _p; } + + private: + friend class Rnd_container; + + Iterator(Rnd_container *c, unsigned long pos, FWD_ITER const &i) + : FWD_ITER(i), _c(c), _p(pos) + {} + + Rnd_container *_c; + unsigned long _p; + }; + +public: + Iterator begin() { return Iterator(this, 0, _b); } + Iterator end() { return Iterator(this, _cnt, _e); } + unsigned long size() const { return _cnt; } + Iterator at(unsigned long pos) + { + if (pos >= _cnt) + return _e; + + Iterator i = _b; + i += pos; + return i; + } + +private: + FWD_ITER _b, _e; + unsigned long _cnt; +}; + +} + + +// available from the jdb_tcb module +extern int jdb_show_tcb(Thread *thread, int level) __attribute__((weak)); + +// use implicit knowledge to determine the type of a timeout because we +// cannot use dynamic_cast (we compile with -fno-rtti) +static +int +Jdb_list_timeouts::get_type(Timeout *t) +{ + Address addr = (Address)t; + + if (t == timeslice_timeout.cpu(0)) + // there is only one global timeslice timeout + return Timeout_timeslice; + + if ((addr % Context::Size) >= sizeof(Thread)) + // IPC timeouts are located at the kernel stack + return Timeout_ipc; + + // unknown + return 0; +} + +static +Thread* +Jdb_list_timeouts::get_owner(Timeout *t) +{ + switch (get_type(t)) + { + case Timeout_ipc: + return static_cast(context_of(t)); + case Timeout_deadline: + return static_cast(context_of(t)); + case Timeout_timeslice: + return static_cast(Context::kernel_context(0)); + // XXX: current_sched does not work from the debugger + if (Context::current_sched()) + return static_cast(Context::current_sched()->context()); + default: + return 0; + } +} + +static +void +Jdb_list_timeouts::show_header() +{ + Jdb::cursor(); + printf("%s type timeout owner name\033[m\033[K\n", + Jdb::esc_emph); +} + +static +void +Jdb_list_timeouts::list_timeouts_show_timeout(Timeout *t) +{ + char const *type; + char ownerstr[32] = ""; + Thread *owner; + Signed64 timeout = t->get_timeout(Kip::k()->clock); + + Kconsole::console()->getchar_chance(); + + switch (get_type(t)) + { + case Timeout_ipc: + type = "ipc"; + owner = get_owner(t); + snprintf(ownerstr, sizeof(ownerstr), " %p", owner); + break; + case Timeout_deadline: + type = "deadline"; + owner = get_owner(t); + snprintf(ownerstr, sizeof(ownerstr), " %p", owner); + break; + case Timeout_timeslice: + type = "timeslice"; + owner = get_owner(t); + if (owner) + snprintf(ownerstr, sizeof(ownerstr), " %p", owner); + else + strcpy (ownerstr, "destruct"); + break; + default: + snprintf(ownerstr, sizeof(ownerstr), L4_PTR_FMT, (Address)t); + type = "???"; + owner = 0; + break; + } + + printf(" %-10s ", type); + if (timeout < 0) + putstr(" over "); + else + { + char time_str[12]; + Jdb::write_ll_ns(timeout * 1000, time_str, + 11 < sizeof(time_str) - 1 ? 11 : sizeof(time_str) - 1, + false); + putstr(time_str); + } + + Jdb_kobject_name *nx = 0; + + if (owner) + nx = Jdb_kobject_extension::find_extension(owner); + + printf(" %s %s\033[K\n", ownerstr, nx ? nx->name() : ""); +} + +IMPLEMENT +Jdb_list_timeouts::Jdb_list_timeouts() + : Jdb_module("INFO") +{} + +static +void +Jdb_list_timeouts::list() +{ + unsigned y, y_max; + + typedef Rnd_container Cont; + typedef Cont::Iterator Iter; + + Cont to_cont(Timeout_iter(&Timeout_q::timeout_queue.cpu(0)), Timeout_iter(&Timeout_q::timeout_queue.cpu(0), true)); + Iter first = to_cont.begin(); + Iter current = first; + Iter end = to_cont.end(); + --end; + + Jdb::clear_screen(); + show_header(); + for (;;) + { + y = current.pos(); + + for (bool resync=false; !resync; ) + { + Jdb::cursor(2, 1); + y_max = 0; + for (Iter i = current; i != to_cont.end(); ++i, ++y_max) + list_timeouts_show_timeout(*i); + + for (unsigned i=y_max; i=select owner", "_"); + + for (bool redraw=false; !redraw; ) + { + Jdb::cursor(y+2, 1); + switch (int c=Jdb_core::getchar()) + { + case KEY_CURSOR_UP: + if (y > 0) + y--; + else + { + Iter i = current; + --current; + redraw = i != current; + } + break; + case KEY_CURSOR_DOWN: + if (y < y_max) + y++; + else + { + Iter i = current; + ++current; + + if (current == to_cont.end()) + current = i; + redraw = i != current; + } + break; + case KEY_PAGE_UP: + { + Iter i = current; + current -= Jdb_screen::height()-3; + redraw = i != current; + if (!redraw) + y = 0; + } + break; + case KEY_PAGE_DOWN: + { + Iter i = current; + current += Jdb_screen::height()-3; + if (current == to_cont.end()) + current = end; + redraw = i != current; + if (!redraw) + y = y_max; + } + break; + case KEY_CURSOR_HOME: + redraw = current != first; + current = first; + y = 0; + break; + case KEY_CURSOR_END: + redraw = current != end; + current = end; + y = y_max; + break; + case KEY_RETURN: + if (jdb_show_tcb != 0) + { + Thread *owner; + Iter i = current; + i += y; + if (i != to_cont.end() && (owner = get_owner(*i))) + { + if (!jdb_show_tcb(owner, 1)) + return; + show_header(); + redraw = 1; + } + } + break; + case KEY_ESC: + Jdb::abort_command(); + return; + default: + if (Jdb::is_toplevel_cmd(c)) + return; + } + } + } + } +} + +PUBLIC +Jdb_module::Action_code +Jdb_list_timeouts::action(int cmd, void *&, char const *&, int &) +{ + if (cmd == 0) + list(); + + return NOTHING; +} + +PUBLIC +Jdb_module::Cmd const * +Jdb_list_timeouts::cmds() const +{ + static Cmd cs[] = + { + { 0, "lt", "timeouts", "", "lt\tshow enqueued timeouts", 0 }, + }; + + return cs; +} + +PUBLIC +int +Jdb_list_timeouts::num_cmds() const +{ + return 1; +} + +static Jdb_list_timeouts jdb_list_timeouts INIT_PRIORITY(JDB_MODULE_INIT_PRIO); diff --git a/kernel/fiasco/src/jdb/jdb_trace.cpp b/kernel/fiasco/src/jdb/jdb_trace.cpp new file mode 100644 index 00000000..7e170f87 --- /dev/null +++ b/kernel/fiasco/src/jdb/jdb_trace.cpp @@ -0,0 +1,294 @@ +INTERFACE: + +#include "l4_types.h" + +class Syscall_frame; +typedef struct +{ + Address lo, hi; +} Addr_range; + +class Jdb_ipc_trace +{ +private: + static int _other_thread; + static Mword _gthread; + static int _other_task; + static Mword _task; + static int _snd_only; + static int _log; + static int _log_to_buf; + static int _log_result; + static int _trace; + static int _slow_ipc; + static int _cpath; + static int _cshortcut; + friend class Jdb_set_trace; +}; + +class Jdb_pf_trace +{ +private: + static int _other_thread; + static Mword _gthread; + static Addr_range _addr; + static int _log; + static int _log_to_buf; + friend class Jdb_set_trace; +}; + +class Jdb_unmap_trace +{ +private: + static int _other_thread; + static Mword _gthread; + static Addr_range _addr; + static int _log; + static int _log_to_buf; + friend class Jdb_set_trace; +}; + +class Jdb_nextper_trace +{ +private: + static int _log; + friend class Jdb_set_trace; +}; + + +IMPLEMENTATION: + +#include + +#include "config.h" +#include "entry_frame.h" +#include "jdb_ktrace.h" +#include "jdb_tbuf.h" +#include "simpleio.h" + +int Jdb_ipc_trace::_other_thread; +Mword Jdb_ipc_trace::_gthread; +int Jdb_ipc_trace::_other_task; +Mword Jdb_ipc_trace::_task; +int Jdb_ipc_trace::_snd_only; +int Jdb_ipc_trace::_log; +int Jdb_ipc_trace::_log_to_buf; +int Jdb_ipc_trace::_log_result; +int Jdb_ipc_trace::_trace; +int Jdb_ipc_trace::_slow_ipc; +int Jdb_ipc_trace::_cpath; +int Jdb_ipc_trace::_cshortcut; + +int Jdb_pf_trace::_other_thread; +Mword Jdb_pf_trace::_gthread; +Addr_range Jdb_pf_trace::_addr; +int Jdb_pf_trace::_log; +int Jdb_pf_trace::_log_to_buf; + +int Jdb_unmap_trace::_other_thread; +Mword Jdb_unmap_trace::_gthread; +Addr_range Jdb_unmap_trace::_addr; +int Jdb_unmap_trace::_log; +int Jdb_unmap_trace::_log_to_buf; + +int Jdb_nextper_trace::_log; + +PUBLIC static inline int Jdb_ipc_trace::log() { return _log; } +PUBLIC static inline int Jdb_ipc_trace::log_buf() { return _log_to_buf; } +PUBLIC static inline int Jdb_ipc_trace::log_result() { return _log_result; } + +PUBLIC static inline NEEDS ["entry_frame.h"] +int +Jdb_ipc_trace::check_restriction (Mword id, + Mword task, + Syscall_frame *ipc_regs, + Mword dst_task) +{ + return ( ((_gthread == 0) + || ((_other_thread) ^ (_gthread == id)) + ) + && ((!_snd_only || ipc_regs->ref().valid())) + && ((_task == 0) + || ((_other_task) + ^ ((_task == task) || (_task == dst_task)))) + ); +} + +PUBLIC static +void +Jdb_ipc_trace::clear_restriction() +{ + _other_thread = 0; + _gthread = 0; + _other_task = 0; + _task = 0; + _snd_only = 0; +} + +PUBLIC static +void +Jdb_ipc_trace::show() +{ + if (_trace) + putstr("IPC tracing to tracebuffer enabled"); + else if (_log) + { + printf("IPC logging%s%s enabled%s", + _log_result ? " incl. results" : "", + _log_to_buf ? " to tracebuffer" : "", + _log_to_buf ? "" : " (exit with 'i', proceed with other key)"); + if (_gthread != 0) + { + printf("\n restricted to thread%s %lx%s", + _other_thread ? "s !=" : "", + _gthread, + _snd_only ? ", snd-only" : ""); + } + if (_task != 0) + { + printf("\n restricted to task%s %lx", + _other_task ? "s !=" : "", _task); + } + } + else + { + printf("IPC logging disabled -- using the IPC %s path", + _slow_ipc + ? "slow" + : "C fast"); + } + + putchar('\n'); +} + +PUBLIC static inline int Jdb_pf_trace::log() { return _log; } +PUBLIC static inline int Jdb_pf_trace::log_buf() { return _log_to_buf; } + +PUBLIC static inline NEEDS[] +int +Jdb_pf_trace::check_restriction (Mword id, Address pfa) +{ + return ( (((_gthread == 0) + || ((_other_thread) ^ (_gthread == id)))) + && (!(_addr.lo | _addr.hi) + || (_addr.lo <= _addr.hi && pfa >= _addr.lo && pfa <= _addr.hi) + || (_addr.lo > _addr.hi && pfa < _addr.hi && pfa > _addr.lo))); +} + +PUBLIC static +void +Jdb_pf_trace::show() +{ + if (_log) + { + int res_enabled = 0; + BEGIN_LOG_EVENT("Page fault results", "pfr", 0) + res_enabled = 1; + END_LOG_EVENT; + printf("PF logging%s%s enabled", + res_enabled ? " incl. results" : "", + _log_to_buf ? " to tracebuffer" : ""); + if (_gthread != 0) + { + printf(", restricted to thread%s %lx", + _other_thread ? "s !=" : "", + _gthread); + } + if (_addr.lo || _addr.hi) + { + if (_gthread != 0) + putstr(" and "); + else + putstr(", restricted to "); + if (_addr.lo <= _addr.hi) + printf(L4_PTR_FMT " <= pfa <= " L4_PTR_FMT + , _addr.lo, _addr.hi); + else + printf("pfa < " L4_PTR_FMT " || pfa > " L4_PTR_FMT, + _addr.hi, _addr.lo); + } + } + else + putstr("PF logging disabled"); + putchar('\n'); +} + +PUBLIC static +void +Jdb_pf_trace::clear_restriction() +{ + _other_thread = 0; + _gthread = 0; + _addr.lo = 0; + _addr.hi = 0; +} + +PUBLIC static inline int Jdb_unmap_trace::log() { return _log; } +PUBLIC static inline int Jdb_unmap_trace::log_buf() { return _log_to_buf; } + +PUBLIC static inline +int +Jdb_unmap_trace::check_restriction(Mword id, Address addr) +{ + return ( (((_gthread == 0) + || ((_other_thread) ^ (_gthread == id)))) + && (!(_addr.lo | _addr.hi) + || (_addr.lo <= _addr.hi && addr >= _addr.lo && addr <= _addr.hi) + || (_addr.lo > _addr.hi && addr < _addr.hi && addr > _addr.lo) + )); +} + +PUBLIC static +void +Jdb_unmap_trace::show() +{ + if (_log) + { + printf("UNMAP logging%s enabled", + _log_to_buf ? " to tracebuffer" : ""); + if (_gthread != 0) + { + printf(", restricted to thread%s %lx", + _other_thread ? "s !=" : "", + _gthread); + } + if (_addr.lo | _addr.hi) + { + if (_gthread != 0) + putstr(" and "); + else + putstr(", restricted to "); + if (_addr.lo <= _addr.hi) + printf(L4_PTR_FMT " <= addr <= " L4_PTR_FMT, + _addr.lo, _addr.hi); + else + printf("addr < " L4_PTR_FMT " || addr > " L4_PTR_FMT + , _addr.hi, _addr.lo); + } + } + else + putstr("UNMAP logging disabled"); + putchar('\n'); +} + +PUBLIC static +void +Jdb_unmap_trace::clear_restriction() +{ + _other_thread = 0; + _gthread = 0; + _addr.lo = 0; + _addr.hi = 0; +} + +PUBLIC static inline int Jdb_nextper_trace::log() { return _log; } + +PUBLIC static +void +Jdb_nextper_trace::show() +{ + if (_log) + puts("Next period logging to tracebuffer enabled"); + else + puts("Next period logging to tracebuffer disabled"); +} diff --git a/kernel/fiasco/src/jdb/jdb_trace_set.cpp b/kernel/fiasco/src/jdb/jdb_trace_set.cpp new file mode 100644 index 00000000..29c40f91 --- /dev/null +++ b/kernel/fiasco/src/jdb/jdb_trace_set.cpp @@ -0,0 +1,374 @@ +IMPLEMENTATION: + +#include + +#include "config.h" +#include "cpu.h" +#include "jdb_module.h" +#include "jdb_tbuf.h" +#include "jdb_trace.h" +#include "keycodes.h" +#include "simpleio.h" +#include "static_init.h" + +class Jdb_set_trace : public Jdb_module +{ +public: + enum Mode { Off, Log, Log_to_buf, Trace, Use_c_short_cut, Use_slow_path }; + + Jdb_set_trace() FIASCO_INIT; + void ipc_tracing(Mode mode); + void next_preiod_tracing(bool enable); + void page_fault_tracing(bool enable); + void unmap_tracing(bool enable); + +private: + static char first_char; + static char second_char; +}; + +char Jdb_set_trace::first_char; +char Jdb_set_trace::second_char; + +IMPLEMENTATION[!{ia32,ux,amd64}]: + +PRIVATE inline +void +Jdb_set_trace::set_unmap_vector() +{} + + +IMPLEMENTATION: + +PUBLIC +Jdb_module::Action_code +Jdb_set_trace::action(int cmd, void *&args, char const *&fmt, int &) +{ + switch (cmd) + { + case 0: + // ipc tracing + if (args == &first_char) + { + switch (first_char) + { + case ' ': + case KEY_RETURN: + first_char = ' '; // print status + break; + case '+': // on + ipc_tracing(Log); + break; + case '-': // off + ipc_tracing(Off); + break; + case '*': // to buffer + ipc_tracing(Log_to_buf); + break; + case 'r': // restriction + case 'R': // results on + case 'S': // use slow ipc path + case 'C': // use C shortcut + case 'T': // use special tracing format + putchar(first_char); + fmt = "%C"; + args = &second_char; + return EXTRA_INPUT; + default: + return ERROR; + } + putchar(first_char); + } + else if (args == &second_char) + { + switch (first_char) + { + case 'r': + switch (second_char) + { + case 'a': + case 'A': + putstr(" restrict to task"); + fmt = second_char == 'A' ? "!=%3x" : "==%3x"; + args = &Jdb_ipc_trace::_task; + Jdb_ipc_trace::_other_task = second_char == 'A'; + return EXTRA_INPUT; + case 't': + case 'T': + putstr(" restrict to thread"); + fmt = second_char == 'T' ? "!=%x" : "==%x"; + args = &Jdb_ipc_trace::_gthread; + Jdb_ipc_trace::_other_thread = second_char == 'T'; + return EXTRA_INPUT; + case 's': + Jdb_ipc_trace::_snd_only = 1; + break; + case '-': + Jdb_ipc_trace::clear_restriction(); + puts(" IPC logging restrictions disabled"); + return NOTHING; + default: + return ERROR; + } + break; + case 'R': + if (second_char == '+') + Jdb_ipc_trace::_log_result = 1; + else if (second_char == '-') + Jdb_ipc_trace::_log_result = 0; + else + return ERROR; + putchar(second_char); + break; + case 'S': + if (second_char == '+') + ipc_tracing(Use_slow_path); + else if (second_char == '-') + ipc_tracing(Off); + else + return ERROR; + putchar(second_char); + break; + case 'C': + if (second_char == '+') + ipc_tracing(Use_c_short_cut); + else if (second_char == '-') + ipc_tracing(Off); + else + return ERROR; + putchar(second_char); + break; + case 'T': + if (second_char == '+') + ipc_tracing(Trace); + else if (second_char == '-') + ipc_tracing(Off); + else + return ERROR; + putchar(second_char); + break; + default: + return ERROR; + } + } + + putchar('\n'); + Jdb_ipc_trace::show(); + break; + + case 1: + // pagefault tracing + if (args == &first_char) + { + switch (first_char) + { + case ' ': + case KEY_RETURN: + first_char = ' '; // print status + break; + case '+': // on + Jdb_pf_trace::_log = 1; + Jdb_pf_trace::_log_to_buf = 0; + break; + case '-': // off + Jdb_pf_trace::_log = 0; + break; + case '*': // to buffer + Jdb_pf_trace::_log = 1; + Jdb_pf_trace::_log_to_buf = 1; + break; + case 'R': // results on + if (!Config::Jdb_logging) + { + puts(" logging disabled"); + return ERROR; + } + // fall through + case 'r': // restriction + putchar(first_char); + fmt = "%C"; + args = &second_char; + return EXTRA_INPUT; + default: + return ERROR; + } + putchar(first_char); + } + else if (args == &second_char) + { + switch (first_char) + { + case 'r': + switch (second_char) + { + case 't': + case 'T': + putstr(" restrict to thread"); + fmt = second_char == 'T' ? "!=%x" : "==%x"; + args = &Jdb_pf_trace::_gthread; + Jdb_pf_trace::_other_thread = second_char == 'T'; + return EXTRA_INPUT; + case 'x': + putstr(" restrict to addr in "); + fmt = "[%p-%p]"; + args = &Jdb_pf_trace::_addr; + return EXTRA_INPUT; + case '-': + Jdb_pf_trace::clear_restriction(); + puts(" pagefault restrictions disabled"); + return NOTHING; + default: + return ERROR; + } + break; + default: + return ERROR; + } + } + + putchar('\n'); + Jdb_pf_trace::show(); + break; + + case 2: + // unmap syscall tracing + if (args == &first_char) + { + switch (first_char) + { + case ' ': + case KEY_RETURN: + first_char = ' '; // print status + break; + case '+': // on + Jdb_unmap_trace::_log = 1; + Jdb_unmap_trace::_log_to_buf = 0; + break; + case '-': // off + Jdb_unmap_trace::_log = 0; + break; + case '*': // to buffer + Jdb_unmap_trace::_log = 1; + Jdb_unmap_trace::_log_to_buf = 1; + break; + case 'r': // restriction + fmt = "r%C"; + args = &second_char; + return EXTRA_INPUT; + default: + return ERROR; + } + set_unmap_vector(); + putchar(first_char); + } + else if (args == &second_char) + { + switch (first_char) + { + case 'r': + switch (second_char) + { + case 't': + case 'T': + putstr(" restrict to thread"); + fmt = second_char == 'T' ? "!=%x" : "==%x"; + args = &Jdb_unmap_trace::_gthread; + Jdb_unmap_trace::_other_thread = second_char == 'T'; + return EXTRA_INPUT; + case 'x': + putstr(" restrict to addr in "); + fmt = "[%p-%p]"; + args = &Jdb_unmap_trace::_addr; + return EXTRA_INPUT; + case '-': + Jdb_unmap_trace::clear_restriction(); + puts(" unmap syscall restrictions disabled"); + default: + return ERROR; + } + break; + default: + return ERROR; + } + } + + putchar('\n'); + Jdb_unmap_trace::show(); + break; + + case 3: + // next period tracing + if (args == &first_char) + { + switch (first_char) + { + case ' ': + case KEY_RETURN: + first_char = ' '; // print status + break; + case '+': // buffer + case '*': // buffer + next_preiod_tracing(true); + break; + case '-': // off + next_preiod_tracing(false); + break; + default: + return ERROR; + } + putchar(first_char); + } + + putchar('\n'); + Jdb_nextper_trace::show(); + break; + } + + return NOTHING; +} + +PUBLIC +Jdb_module::Cmd const * +Jdb_set_trace::cmds() const +{ + static Cmd cs[] = + { + { 0, "I", "I", "%C", + "I{+|-|*|R{+|-}|T{+|-}}\ton/off/buffer ipc logging, on/off result, " + "tracing\n" + "IS{+|-}\tipc \033[1mwithout\033[m shortcut on/off\n" + "IC{+|-}\tipc with C fast path / IPC with Assembler fast path\n" + "Ir{t|T|a|A|s|-}\trestrict ipc log to (!)thread/(!)task/snd-only/" + "clr", + &first_char }, + { 1, "P", "P", "%C", + "P{+|-|*}\ton/off/buffer pagefault logging\n" + "Pr{t|T|x|-}\trestrict pagefault log to (!)thread/!thread/addr/clr", + &first_char }, + { 2, "U", "U", "%C", + "U{+|-|*}\ton/off/buffer unmap logging\n" + "Ur{t|T|x|-}\trestrict unmap log to (!)thread/addr/clr", + &first_char }, + { 3, "N", "N", "%C", + "N{+|-|*}\tbuffer/off/buffer next period IPC", + &first_char }, + }; + + return cs; +} + +PUBLIC +int +Jdb_set_trace::num_cmds() const +{ + return 4; +} + +IMPLEMENT +Jdb_set_trace::Jdb_set_trace() + : Jdb_module("MONITORING") +{ +} + +static Jdb_set_trace jdb_set_trace INIT_PRIORITY(JDB_MODULE_INIT_PRIO); + diff --git a/kernel/fiasco/src/jdb/jdb_trap_state.cpp b/kernel/fiasco/src/jdb/jdb_trap_state.cpp new file mode 100644 index 00000000..4ada7aab --- /dev/null +++ b/kernel/fiasco/src/jdb/jdb_trap_state.cpp @@ -0,0 +1,88 @@ +IMPLEMENTATION: + +#include +#include "simpleio.h" + +#include "jdb.h" +#include "jdb_module.h" +#include "static_init.h" +#include "types.h" + + +/** + * Private 'exit' module. + * + * This module handles the 'exit' or '^' command that + * makes a call to exit() and virtually reboots the system. + */ +class Jdb_trap_state_module : public Jdb_module +{ +public: + Jdb_trap_state_module() FIASCO_INIT; +}; + +static Jdb_trap_state_module jdb_trap_state_module INIT_PRIORITY(JDB_MODULE_INIT_PRIO); + + +PRIVATE static +void +Jdb_trap_state_module::print_trap_state(unsigned cpu) +{ + Jdb_entry_frame *ef = Jdb::entry_frame.cpu(cpu); + if (!Jdb::cpu_in_jdb(cpu) || !ef) + printf("CPU %u has not entered JDB\n", cpu); + else + { + printf("Registers of CPU %u (before entering JDB)\n", cpu); + ef->dump(); + } +} + +PUBLIC +Jdb_module::Action_code +Jdb_trap_state_module::action (int cmd, void *&argbuf, char const *&fmt, int &next) +{ + char const *c = (char const *)argbuf; + static unsigned cpu; + + if (cmd != 0) + return NOTHING; + + if (argbuf != &cpu) + { + if (*c == 'a') + Jdb::foreach_cpu(&print_trap_state); + else if (*c >= '0' && *c <= '9') + { + next = *c; argbuf = &cpu; fmt = "%i"; + return EXTRA_INPUT_WITH_NEXTCHAR; + } + } + else + print_trap_state(cpu); + + return NOTHING; +} + +PUBLIC +int +Jdb_trap_state_module::num_cmds() const +{ + return 1; +} + +PUBLIC +Jdb_module::Cmd const * +Jdb_trap_state_module::cmds() const +{ + static char c; + static Cmd cs[] = + { { 0, "", "cpustate", "%C", "cpustate all|\tdump state of CPU", &c } }; + + return cs; +} + +IMPLEMENT +Jdb_trap_state_module::Jdb_trap_state_module() + : Jdb_module("INFO") +{} diff --git a/kernel/fiasco/src/jdb/jdb_utcb.cpp b/kernel/fiasco/src/jdb/jdb_utcb.cpp new file mode 100644 index 00000000..bb20cc3f --- /dev/null +++ b/kernel/fiasco/src/jdb/jdb_utcb.cpp @@ -0,0 +1,133 @@ +/** + * @brief Jdb-Utcb module + * + * This module shows the user tcbs and the vCPU state of a thread/vcpu + */ + +IMPLEMENTATION: + +#include +#include +#include "l4_types.h" +#include "config.h" +#include "jdb.h" +#include "jdb_kobject.h" +#include "jdb_module.h" +#include "space.h" +#include "static_init.h" +#include "thread_object.h" +#include "thread_state.h" + +class Jdb_utcb : public Jdb_module +{ +public: + Jdb_utcb() FIASCO_INIT; +private: + static Kobject *thread; +}; + + +static Jdb_utcb Jdb_utcb INIT_PRIORITY(JDB_MODULE_INIT_PRIO); + +Kobject *Jdb_utcb::thread; + +IMPLEMENT +Jdb_utcb::Jdb_utcb() + : Jdb_module("INFO") +{} + +PUBLIC static +void +Jdb_utcb::print(Thread *t) +{ + if (t->utcb().kern()) + { + printf("\nUtcb-addr: %p\n", t->utcb().kern()); + t->utcb().kern()->print(); + } + + if (t->state(false) & Thread_vcpu_enabled) + { + Vcpu_state *v = t->vcpu_state().kern(); + printf("\nVcpu-state-addr: %p\n", v); + printf("state: %x saved-state: %x sticky: %x\n", + (int)v->state, (int)v->_saved_state, (int)v->sticky_flags); + printf("entry_sp = %lx entry_ip = %lx sp = %lx\n", + v->_entry_sp, v->_entry_ip, v->_sp); + v->_ts.dump(); + } +} + +PUBLIC virtual +Jdb_module::Action_code +Jdb_utcb::action( int cmd, void *&, char const *&, int &) +{ + if (cmd) + return NOTHING; + + Thread *t = Kobject::dcast(thread); + if (!t) + { + printf(" Invalid thread\n"); + return NOTHING; + } + + print(t); + + return NOTHING; +} + +PUBLIC +int +Jdb_utcb::num_cmds() const +{ return 1; } + +PUBLIC +Jdb_module::Cmd +const * Jdb_utcb::cmds() const +{ + static Cmd cs[] = + { + { 0, "z", "z", "%q", "z\tshow UTCB and vCPU state", &thread } + }; + return cs; +} + +// -------------------------------------------------------------------------- +// Handler for kobject list + +class Jdb_kobject_utcb_hdl : public Jdb_kobject_handler +{ +public: + Jdb_kobject_utcb_hdl() : Jdb_kobject_handler(0) {} + virtual bool show_kobject(Kobject_common *, int) { return true; } + virtual ~Jdb_kobject_utcb_hdl() {} +}; + +PUBLIC static FIASCO_INIT +void +Jdb_kobject_utcb_hdl::init() +{ + static Jdb_kobject_utcb_hdl hdl; + Jdb_kobject::module()->register_handler(&hdl); +} + +PUBLIC +bool +Jdb_kobject_utcb_hdl::handle_key(Kobject_common *o, int keycode) +{ + if (keycode == 'z') + { + Thread *t = Kobject::dcast(o); + if (!t) + return false; + + Jdb_utcb::print(t); + Jdb::getchar(); + return true; + } + + return false; +} + +STATIC_INITIALIZE(Jdb_kobject_utcb_hdl); diff --git a/kernel/fiasco/src/jdb/jdb_util.cpp b/kernel/fiasco/src/jdb/jdb_util.cpp new file mode 100644 index 00000000..3c801e12 --- /dev/null +++ b/kernel/fiasco/src/jdb/jdb_util.cpp @@ -0,0 +1,48 @@ +INTERFACE: + +class Jdb_util +{ +public: + static bool is_mapped(void const *addr); +}; + +IMPLEMENTATION[ia32|ux|amd64]: + +#include "kmem.h" + +IMPLEMENT +bool +Jdb_util::is_mapped(void const *x) +{ + return Kmem::virt_to_phys(x) != ~0UL; +} + +IMPLEMENTATION[arm]: + +#include "pagetable.h" +#include "kmem_space.h" + +IMPLEMENT inline NEEDS["kmem_space.h", "pagetable.h"] +bool +Jdb_util::is_mapped(void const* addr) +{ + return Kmem_space::kdir()->walk(const_cast(addr), 0, false, Ptab::Null_alloc(), 0).valid(); +} + +IMPLEMENTATION[ppc32]: + +IMPLEMENT inline +bool +Jdb_util::is_mapped(void const * /*addr*/) +{ + return true; +} + +IMPLEMENTATION[sparc]: + +IMPLEMENT inline +bool +Jdb_util::is_mapped(void const * /*addr*/) +{ + return false; // TBD +} diff --git a/kernel/fiasco/src/jdb/ppc32/jdb-ppc32.cpp b/kernel/fiasco/src/jdb/ppc32/jdb-ppc32.cpp new file mode 100644 index 00000000..1f02f5d7 --- /dev/null +++ b/kernel/fiasco/src/jdb/ppc32/jdb-ppc32.cpp @@ -0,0 +1,245 @@ +IMPLEMENTATION [ppc32]: + +#include "globals.h" +#include "kmem_alloc.h" +#include "space.h" +#include "mem_layout.h" +#include "mem_unit.h" +#include "static_init.h" + + +STATIC_INITIALIZE_P(Jdb, JDB_INIT_PRIO); + +DEFINE_PER_CPU static Per_cpu jdb_irq_state; + +// disable interrupts before entering the kernel debugger +IMPLEMENT +void +Jdb::save_disable_irqs(unsigned cpu) +{ + jdb_irq_state.cpu(cpu) = Proc::cli_save(); +} + +// restore interrupts after leaving the kernel debugger +IMPLEMENT +void +Jdb::restore_irqs(unsigned cpu) +{ + Proc::sti_restore(jdb_irq_state.cpu(cpu)); +} + +IMPLEMENT inline +void +Jdb::enter_trap_handler(unsigned /*cpu*/) +{} + +IMPLEMENT inline +void +Jdb::leave_trap_handler(unsigned /*cpu*/) +{} + +IMPLEMENT inline +bool +Jdb::handle_conditional_breakpoint(unsigned /*cpu*/) +{ return false; } + +IMPLEMENT +void +Jdb::handle_nested_trap(Jdb_entry_frame *e) +{ + printf("Trap in JDB: IP:%08lx SRR1=%08lx\n", + e->ip(), e->srr1); +} + +IMPLEMENT +bool +Jdb::handle_debug_traps(unsigned cpu) +{ + Jdb_entry_frame *ef = entry_frame.cpu(cpu); + snprintf(error_buffer.cpu(cpu), sizeof(error_buffer.cpu(0)), "%s", + (char const *)ef->r[2]); + + return true; +} + +IMPLEMENT inline +bool +Jdb::handle_user_request(unsigned cpu) +{ + Jdb_entry_frame *ef = Jdb::entry_frame.cpu(cpu); + const char *str = (char const *)ef->r[2]; + Space * task = get_task(cpu); + char tmp; + + if (!peek(str, task, tmp) || tmp != '*') + return false; + if (!peek(str+1, task, tmp) || tmp != '#') + return false; + + return execute_command_ni(task, str+2); +} + +IMPLEMENT inline +bool +Jdb::test_checksums() +{ return true; } + +static +bool +Jdb::handle_special_cmds(int) +{ return 1; } + +PUBLIC static +FIASCO_INIT FIASCO_NOINLINE void +Jdb::init() +{ + static Jdb_handler enter(at_jdb_enter); + static Jdb_handler leave(at_jdb_leave); + + Jdb::jdb_enter.add(&enter); + Jdb::jdb_leave.add(&leave); + + Thread::nested_trap_handler = (Trap_state::Handler)enter_jdb; + Kconsole::console()->register_console(push_cons()); +} + + +PRIVATE static +void * +Jdb::access_mem_task(Address virt, Space * task) +{ + // align + + virt &= ~0x03; + + Address phys; + + if (!task) + { + if (Mem_layout::in_kernel(virt)) + { + phys = Kmem::virt_to_phys((void *)virt); + if (phys == (Address)-1) + return 0; + + } + else + phys = virt; + } + else + { + phys = Address(task->virt_to_phys(virt)); + + if(phys = (Address)-1) + phys = task->virt_to_phys_s0((void *)virt); + + if (phys == (Address)-1) + return 0; + } + + return (Mword*)phys; +} + +PUBLIC static +Space * +Jdb::translate_task(Address addr, Space * task) +{ + (void)addr; (void)task; +// return (Kmem::is_kmem_page_fault(addr, 0)) ? 0 : task; + + return task; +} + +PUBLIC static +int +Jdb::peek_task(Address virt, Space * task, void *value, int width) +{ + + void const *mem = access_mem_task(virt, task); + if (!mem) + return -1; + + switch (width) + { + case 1: + { + Mword dealign = (virt & 0x3) * 8; + *(Mword*)value = (*(Mword*)mem & (0xff << dealign)) >> dealign; + break; + } + case 2: + { + Mword dealign = ((virt & 0x2) >> 1) * 16; + *(Mword*)value = (*(Mword*)mem & (0xffff << dealign)) >> dealign; + break; + } + case 4: + memcpy(value, mem, width); + } + + return 0; +} + +PUBLIC static +int +Jdb::is_adapter_memory(Address, Space *) +{ + return 0; +} + +PUBLIC static +int +Jdb::poke_task(Address virt, Space * task, void const *val, int width) +{ + (void)virt; (void)task; (void)val; (void)width; + /* + void *mem = access_mem_task(virt, task); + if (!mem) + return -1; + + memcpy(mem, val, width);*/ + return 0; +} + + +PRIVATE static +void +Jdb::at_jdb_enter() +{ +// Mem_unit::clean_vdcache(); +} + +PRIVATE static +void +Jdb::at_jdb_leave() +{ +// Mem_unit::flush_vcache(); +} + +PUBLIC static inline +void +Jdb::enter_getchar() +{} + +PUBLIC static inline +void +Jdb::leave_getchar() +{} + +PUBLIC static +void +Jdb::write_tsc_s(Signed64 /*tsc*/, char * /*buf*/, int /*maxlen*/, bool /*sign*/) +{} + +PUBLIC static +void +Jdb::write_tsc(Signed64 /*tsc*/, char * /*buf*/, int /*maxlen*/, bool /*sign*/) +{} + +PROTECTED static inline +template< typename T > +void +Jdb::set_monitored_address(T *dest, T val) +{ + *dest = val; +} diff --git a/kernel/fiasco/src/jdb/ppc32/jdb_entry_frame-ppc32.cpp b/kernel/fiasco/src/jdb/ppc32/jdb_entry_frame-ppc32.cpp new file mode 100644 index 00000000..f40227f2 --- /dev/null +++ b/kernel/fiasco/src/jdb/ppc32/jdb_entry_frame-ppc32.cpp @@ -0,0 +1,120 @@ +INTERFACE [ppc32]: + +#include "msr.h" +#include "trap_state.h" +#include "tb_entry.h" + +class Jdb_entry_frame : public Trap_state +{ +public: + Address_type from_user() const; + Address ip() const; + bool debug_ipi() const; +}; + +class Jdb_output_frame : public Jdb_entry_frame +{}; + +class Jdb_status_page_frame : public Jdb_entry_frame +{}; + +class Jdb_log_frame : public Jdb_entry_frame +{}; + +class Jdb_log_3val_frame : public Jdb_log_frame +{}; + +class Jdb_debug_frame : public Jdb_entry_frame +{}; + +class Jdb_symbols_frame : public Jdb_debug_frame +{}; + +class Jdb_lines_frame : public Jdb_debug_frame +{}; + +class Jdb_get_cputime_frame : public Jdb_entry_frame +{}; + +class Jdb_thread_name_frame : public Jdb_entry_frame +{}; + +//--------------------------------------------------------------------------- +IMPLEMENTATION[ppc32]: + +#include +#include "processor.h" + +#if 0 +PUBLIC +void +Jdb_entry_frame::dump() const +{ + printf( + "R[ 0- 3]: %08lx %08lx %08lx %08lx\n" + "R[ 4- 7]: %08lx %08lx %08lx %08lx\n" + "R[ 8-11]: %08lx %08lx %08lx %08lx\n" + "R[12-15]: %08lx %08lx %08lx %08lx\n" + "kernel sp = %08lx cpsr = %08lx spsr = %08lx\n", + r[0], r[1], r[2], r[3], r[4], r[5], r[6], r[7], r[8], + r[9], r[10], r[11], r[12], r[13], r[14], pc, ksp, cpsr, spsr); +} +#endif + +IMPLEMENT inline +bool +Jdb_entry_frame::debug_ipi() const +{ return false; } + +IMPLEMENT inline NEEDS["msr.h"] +Address_type +Jdb_entry_frame::from_user() const +{ + return (srr1 & Msr::Msr_pr) ? ADDR_USER : ADDR_KERNEL; +} + +PUBLIC inline +Address Jdb_entry_frame::ksp() const +{ return Address(this); } + +IMPLEMENT inline +Address Jdb_entry_frame::ip() const +{ return srr0; } + +PUBLIC inline +Mword +Jdb_entry_frame::param() const +{ return r[2]; /*r3*/ } + + +PUBLIC inline +Unsigned8* +Jdb_log_frame::str() const +{ return (Unsigned8*)r[3]; /*r4*/ } + +PUBLIC inline NEEDS["tb_entry.h"] +void +Jdb_log_frame::set_tb_entry(Tb_entry* tb_entry) +{ r[2] = (Mword)tb_entry; } + +//--------------------------------------------------------------------------- +PUBLIC inline +Mword +Jdb_log_3val_frame::val1() const +{ return r[4]; } + +PUBLIC inline +Mword +Jdb_log_3val_frame::val2() const +{ return r[5]; } + +PUBLIC inline +Mword +Jdb_log_3val_frame::val3() const +{ return r[6]; } + +//--------------------------------------------------------------------------- +PUBLIC inline +void +Jdb_status_page_frame::set(Address status_page) +{ r[2] = (Mword)status_page; } diff --git a/kernel/fiasco/src/jdb/ppc32/jdb_tcb-ppc32.cpp b/kernel/fiasco/src/jdb/ppc32/jdb_tcb-ppc32.cpp new file mode 100644 index 00000000..64c33479 --- /dev/null +++ b/kernel/fiasco/src/jdb/ppc32/jdb_tcb-ppc32.cpp @@ -0,0 +1,111 @@ +IMPLEMENTATION [ppc32]: + +EXTENSION class Jdb_tcb +{ + enum + { + Disasm_x = 41, + Disasm_y = 11, + Stack_y = 20, + }; +}; + +IMPLEMENT +void Jdb_tcb::print_entry_frame_regs(Thread *) +{ + Jdb_entry_frame *ef = Jdb::get_entry_frame(Jdb::current_cpu); + int from_user = ef->from_user(); + + printf("\n\n\nRegisters (before debug entry from %s mode):\n" + "[0] %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n" + "[8] %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n" + "[16] %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n" + "[24] %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx" + "\033[m\n sp = %08lx\n", + from_user ? "user" : "kernel", + ef->r[0], ef->usp, ef->r[1], ef->r[2], ef->r[3], + ef->r[4], ef->r[5], ef->r[6], ef->r[7], ef->r[8], + ef->r[9], ef->r11, ef->r12 , ef->r[10], ef->r[11], + ef->r[12], ef->r[13], ef->r[14], ef->r[15], ef->r[16], + ef->r[17], ef->r[18], ef->r[19], ef->r[20], ef->r[21], + ef->r[22], ef->r[23], ef->r[24], ef->r[25], ef->r[26], + ef->r[27], ef->r[28], ef->usp); +} + +IMPLEMENT +void +Jdb_tcb::info_thread_state(Thread *t) +{ + Jdb_tcb_ptr current((Address)t->get_kernel_sp()); + + printf("\n\n\nSRR0=%s%08lx\033[m USP=%08lx ULR=%08lx ENTRY IP=%08lx\n", + Jdb::esc_emph, current.top_value(-5), current.top_value(-3), + current.top_value(-4), current.top_value(-10)); + + printf("[0] %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n" + "[8] %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n" + "[16] %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n" + "[24] %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx" + "\033[m\n", + current.top_value(-39), //0 + current.top_value(-3), //1 + current.top_value(-38), //2 + current.top_value(-37), //3 + current.top_value(-36), //4 + current.top_value(-35), //5 + current.top_value(-34), //6 + current.top_value(-33), //7 + current.top_value(-32), //8 + current.top_value(-31), //9 + current.top_value(-30), //10 + current.top_value(-2), //11 + current.top_value(-1), //12 + current.top_value(-29), //13 + current.top_value(-28), //14 + current.top_value(-27), //15 + current.top_value(-26), //16 + current.top_value(-25), //17 + current.top_value(-24), //18 + current.top_value(-23), //19 + current.top_value(-22), //20 + current.top_value(-21), //21 + current.top_value(-20), //22 + current.top_value(-19), //23 + current.top_value(-18), //24 + current.top_value(-17), //25 + current.top_value(-16), //26 + current.top_value(-15), //27 + current.top_value(-14), //28 + current.top_value(-13), //29 + current.top_value(-12), //30 + current.top_value(-11) //31 + ); +} + +IMPLEMENT +void +Jdb_tcb::print_return_frame_regs(Jdb_tcb_ptr const &, Address) +{} + +IMPLEMENT +bool +Jdb_stack_view::edit_registers() +{ + return false; +} + +IMPLEMENT inline +bool +Jdb_tcb_ptr::is_user_value() const +{ + return _offs >= Context::Size - 9 * sizeof(Mword); +} + +IMPLEMENT inline +const char * +Jdb_tcb_ptr::user_value_desc() const +{ + const char *desc[] = { "r12", "r11", "USP", "ULR", "SRR0", "SRR1", + "CR", "CTR", "XER" }; + return desc[(Context::Size - _offs) / sizeof(Mword) - 1]; +} diff --git a/kernel/fiasco/src/jdb/sparc/jdb-sparc.cpp b/kernel/fiasco/src/jdb/sparc/jdb-sparc.cpp new file mode 100644 index 00000000..a036666e --- /dev/null +++ b/kernel/fiasco/src/jdb/sparc/jdb-sparc.cpp @@ -0,0 +1,243 @@ +IMPLEMENTATION [sparc]: + +#include "globals.h" +#include "kmem_alloc.h" +#include "space.h" +#include "mem_layout.h" +#include "mem_unit.h" +#include "static_init.h" + + +STATIC_INITIALIZE_P(Jdb, JDB_INIT_PRIO); + +DEFINE_PER_CPU static Per_cpu jdb_irq_state; + +// disable interrupts before entering the kernel debugger +IMPLEMENT +void +Jdb::save_disable_irqs(unsigned cpu) +{ + jdb_irq_state.cpu(cpu) = Proc::cli_save(); +} + +// restore interrupts after leaving the kernel debugger +IMPLEMENT +void +Jdb::restore_irqs(unsigned cpu) +{ + Proc::sti_restore(jdb_irq_state.cpu(cpu)); +} + +IMPLEMENT inline +void +Jdb::enter_trap_handler(unsigned /*cpu*/) +{} + +IMPLEMENT inline +void +Jdb::leave_trap_handler(unsigned /*cpu*/) +{} + +IMPLEMENT inline +bool +Jdb::handle_conditional_breakpoint(unsigned /*cpu*/) +{ return false; } + +IMPLEMENT +void +Jdb::handle_nested_trap(Jdb_entry_frame *e) +{ + printf("Trap in JDB: IP:%08lx SRR1=%08lx\n", + e->ip(), e->srr1); +} + +IMPLEMENT +bool +Jdb::handle_debug_traps(unsigned cpu) +{ + Jdb_entry_frame *ef = entry_frame.cpu(cpu); + snprintf(error_buffer.cpu(cpu), sizeof(error_buffer.cpu(0)), "%s", + (char const *)ef->r[2]); + + return true; +} + +IMPLEMENT inline +bool +Jdb::handle_user_request(unsigned cpu) +{ + Jdb_entry_frame *ef = Jdb::entry_frame.cpu(cpu); + const char *str = (char const *)ef->r[2]; + Space * task = get_task(cpu); + char tmp; + + if (!peek(str, task, tmp) || tmp != '*') + return false; + if (!peek(str+1, task, tmp) || tmp != '#') + return false; + + return execute_command_ni(task, str+2); +} + +IMPLEMENT inline +bool +Jdb::test_checksums() +{ return true; } + +static +bool +Jdb::handle_special_cmds(int) +{ return 1; } + +PUBLIC static +FIASCO_INIT FIASCO_NOINLINE void +Jdb::init() +{ + static Jdb_handler enter(at_jdb_enter); + static Jdb_handler leave(at_jdb_leave); + + Jdb::jdb_enter.add(&enter); + Jdb::jdb_leave.add(&leave); + + Thread::nested_trap_handler = (Trap_state::Handler)enter_jdb; + Kconsole::console()->register_console(push_cons()); +} + + +PRIVATE static +void * +Jdb::access_mem_task(Address virt, Space * task) +{ + // align + + virt &= ~0x03; + + Address phys; + + if (!task) + { + if (Mem_layout::in_kernel(virt)) + { + phys = Kmem::virt_to_phys((void *)virt); + if (phys == (Address)-1) + return 0; + + } + else + phys = virt; + } + else + { + phys = Address(task->virt_to_phys(virt)); + + if(phys = (Address)-1) + phys = task->virt_to_phys_s0((void *)virt); + + if (phys == (Address)-1) + return 0; + } + + return (Mword*)phys; +} + +PUBLIC static +Space * +Jdb::translate_task(Address addr, Space * task) +{ +// return (Kmem::is_kmem_page_fault(addr, 0)) ? 0 : task; + + return task; +} + +PUBLIC static +int +Jdb::peek_task(Address virt, Space * task, void *value, int width) +{ + + void const *mem = access_mem_task(virt, task); + if (!mem) + return -1; + + switch (width) + { + case 1: + { + Mword dealign = (virt & 0x3) * 8; + *(Mword*)value = (*(Mword*)mem & (0xff << dealign)) >> dealign; + break; + } + case 2: + { + Mword dealign = ((virt & 0x2) >> 1) * 16; + *(Mword*)value = (*(Mword*)mem & (0xffff << dealign)) >> dealign; + break; + } + case 4: + memcpy(value, mem, width); + } + + return 0; +} + +PUBLIC static +int +Jdb::is_adapter_memory(Address, Space *) +{ + return 0; +} + +PUBLIC static +int +Jdb::poke_task(Address virt, Space * task, void const *val, int width) +{ + /* + void *mem = access_mem_task(virt, task); + if (!mem) + return -1; + + memcpy(mem, val, width);*/ + return 0; +} + + +PRIVATE static +void +Jdb::at_jdb_enter() +{ +// Mem_unit::clean_vdcache(); +} + +PRIVATE static +void +Jdb::at_jdb_leave() +{ +// Mem_unit::flush_vcache(); +} + +PUBLIC static inline +void +Jdb::enter_getchar() +{} + +PUBLIC static inline +void +Jdb::leave_getchar() +{} + +PUBLIC static +void +Jdb::write_tsc_s(Signed64 /*tsc*/, char * /*buf*/, int /*maxlen*/, bool /*sign*/) +{} + +PUBLIC static +void +Jdb::write_tsc(Signed64 /*tsc*/, char * /*buf*/, int /*maxlen*/, bool /*sign*/) +{} + +PROTECTED static inline +template< typename T > +void +Jdb::set_monitored_address(T *dest, T val) +{ + *dest = val; +} diff --git a/kernel/fiasco/src/jdb/sparc/jdb_entry_frame-sparc.cpp b/kernel/fiasco/src/jdb/sparc/jdb_entry_frame-sparc.cpp new file mode 100644 index 00000000..dbc07029 --- /dev/null +++ b/kernel/fiasco/src/jdb/sparc/jdb_entry_frame-sparc.cpp @@ -0,0 +1,120 @@ +INTERFACE [sparc]: + +#include "psr.h" +#include "trap_state.h" +#include "tb_entry.h" + +class Jdb_entry_frame : public Trap_state +{ +public: + Address_type from_user() const; + Address ip() const; + bool debug_ipi() const; +}; + +class Jdb_output_frame : public Jdb_entry_frame +{}; + +class Jdb_status_page_frame : public Jdb_entry_frame +{}; + +class Jdb_log_frame : public Jdb_entry_frame +{}; + +class Jdb_log_3val_frame : public Jdb_log_frame +{}; + +class Jdb_debug_frame : public Jdb_entry_frame +{}; + +class Jdb_symbols_frame : public Jdb_debug_frame +{}; + +class Jdb_lines_frame : public Jdb_debug_frame +{}; + +class Jdb_get_cputime_frame : public Jdb_entry_frame +{}; + +class Jdb_thread_name_frame : public Jdb_entry_frame +{}; + +//--------------------------------------------------------------------------- +IMPLEMENTATION[sparc]: + +#include +#include "processor.h" + +#if 0 +PUBLIC +void +Jdb_entry_frame::dump() const +{ + printf( + "R[ 0- 3]: %08lx %08lx %08lx %08lx\n" + "R[ 4- 7]: %08lx %08lx %08lx %08lx\n" + "R[ 8-11]: %08lx %08lx %08lx %08lx\n" + "R[12-15]: %08lx %08lx %08lx %08lx\n" + "kernel sp = %08lx cpsr = %08lx spsr = %08lx\n", + r[0], r[1], r[2], r[3], r[4], r[5], r[6], r[7], r[8], + r[9], r[10], r[11], r[12], r[13], r[14], pc, ksp, cpsr, spsr); +} +#endif + +IMPLEMENT inline +bool +Jdb_entry_frame::debug_ipi() const +{ return false; } + +IMPLEMENT inline NEEDS["psr.h"] +Address_type +Jdb_entry_frame::from_user() const +{ + return ADDR_KERNEL; // (srr1 & Msr::Msr_pr) ? ADDR_USER : ADDR_KERNEL; +} + +PUBLIC inline +Address Jdb_entry_frame::ksp() const +{ return Address(this); } + +IMPLEMENT inline +Address Jdb_entry_frame::ip() const +{ return srr0; } + +PUBLIC inline +Mword +Jdb_entry_frame::param() const +{ return r[2]; /*r3*/ } + + +PUBLIC inline +Unsigned8* +Jdb_log_frame::str() const +{ return (Unsigned8*)r[3]; /*r4*/ } + +PUBLIC inline NEEDS["tb_entry.h"] +void +Jdb_log_frame::set_tb_entry(Tb_entry* tb_entry) +{ r[2] = (Mword)tb_entry; } + +//--------------------------------------------------------------------------- +PUBLIC inline +Mword +Jdb_log_3val_frame::val1() const +{ return r[4]; } + +PUBLIC inline +Mword +Jdb_log_3val_frame::val2() const +{ return r[5]; } + +PUBLIC inline +Mword +Jdb_log_3val_frame::val3() const +{ return r[6]; } + +//--------------------------------------------------------------------------- +PUBLIC inline +void +Jdb_status_page_frame::set(Address status_page) +{ r[2] = (Mword)status_page; } diff --git a/kernel/fiasco/src/jdb/sparc/jdb_tcb-sparc.cpp b/kernel/fiasco/src/jdb/sparc/jdb_tcb-sparc.cpp new file mode 100644 index 00000000..43fc4ec6 --- /dev/null +++ b/kernel/fiasco/src/jdb/sparc/jdb_tcb-sparc.cpp @@ -0,0 +1,111 @@ +IMPLEMENTATION [sparc]: + +EXTENSION class Jdb_tcb +{ + enum + { + Disasm_x = 41, + Disasm_y = 11, + Stack_y = 20, + }; +}; + +IMPLEMENT +void Jdb_tcb::print_entry_frame_regs(Thread *) +{ + Jdb_entry_frame *ef = Jdb::get_entry_frame(Jdb::current_cpu); + int from_user = ef->from_user(); + + printf("\n\n\nRegisters (before debug entry from %s mode):\n" + "[0] %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n" + "[8] %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n" + "[16] %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n" + "[24] %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx" + "\033[m\n sp = %08lx\n", + from_user ? "user" : "kernel", + ef->r[0], ef->usp, ef->r[1], ef->r[2], ef->r[3], + ef->r[4], ef->r[5], ef->r[6], ef->r[7], ef->r[8], + ef->r[9], ef->r11, ef->r12 , ef->r[10], ef->r[11], + ef->r[12], ef->r[13], ef->r[14], ef->r[15], ef->r[16], + ef->r[17], ef->r[18], ef->r[19], ef->r[20], ef->r[21], + ef->r[22], ef->r[23], ef->r[24], ef->r[25], ef->r[26], + ef->r[27], ef->r[28], ef->usp); +} + +IMPLEMENT +void +Jdb_tcb::info_thread_state(Thread *t) +{ + Jdb_tcb_ptr current((Address)t->get_kernel_sp()); + + printf("\n\n\nSRR0=%s%08lx\033[m USP=%08lx ULR=%08lx ENTRY IP=%08lx\n", + Jdb::esc_emph, current.top_value(-5), current.top_value(-3), + current.top_value(-4), current.top_value(-10)); + + printf("[0] %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n" + "[8] %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n" + "[16] %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n" + "[24] %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx" + "\033[m\n", + current.top_value(-39), //0 + current.top_value(-3), //1 + current.top_value(-38), //2 + current.top_value(-37), //3 + current.top_value(-36), //4 + current.top_value(-35), //5 + current.top_value(-34), //6 + current.top_value(-33), //7 + current.top_value(-32), //8 + current.top_value(-31), //9 + current.top_value(-30), //10 + current.top_value(-2), //11 + current.top_value(-1), //12 + current.top_value(-29), //13 + current.top_value(-28), //14 + current.top_value(-27), //15 + current.top_value(-26), //16 + current.top_value(-25), //17 + current.top_value(-24), //18 + current.top_value(-23), //19 + current.top_value(-22), //20 + current.top_value(-21), //21 + current.top_value(-20), //22 + current.top_value(-19), //23 + current.top_value(-18), //24 + current.top_value(-17), //25 + current.top_value(-16), //26 + current.top_value(-15), //27 + current.top_value(-14), //28 + current.top_value(-13), //29 + current.top_value(-12), //30 + current.top_value(-11) //31 + ); +} + +IMPLEMENT +void +Jdb_tcb::print_return_frame_regs(Jdb_tcb_ptr const &, Address) +{} + +IMPLEMENT +bool +Jdb_stack_view::edit_registers() +{ + return false; +} + +IMPLEMENT inline +bool +Jdb_tcb_ptr::is_user_value() const +{ + return _offs >= Context::Size - 9 * sizeof(Mword); +} + +IMPLEMENT inline +const char * +Jdb_tcb_ptr::user_value_desc() const +{ + const char *desc[] = { "r12", "r11", "USP", "ULR", "SRR0", "SRR1", + "CR", "CTR", "XER" }; + return desc[(Context::Size - _offs) / sizeof(Mword) - 1]; +} diff --git a/kernel/fiasco/src/jdb/ux/jdb-int3.cpp b/kernel/fiasco/src/jdb/ux/jdb-int3.cpp new file mode 100644 index 00000000..dd5a2877 --- /dev/null +++ b/kernel/fiasco/src/jdb/ux/jdb-int3.cpp @@ -0,0 +1,14 @@ +IMPLEMENTATION: + +/** + * Handle int3 extensions in the current thread's context. All functions + * for which we don't need/want to switch to the debugging stack. + * \return 0 if this function should be handled in the context of Jdb + * 1 successfully handled + */ +PRIVATE static inline +int +Jdb::handle_int3_threadctx(Trap_state *ts) +{ + return handle_int3_threadctx_generic(ts); +} diff --git a/kernel/fiasco/src/jdb/ux/jdb-ux.cpp b/kernel/fiasco/src/jdb/ux/jdb-ux.cpp new file mode 100644 index 00000000..daf86de1 --- /dev/null +++ b/kernel/fiasco/src/jdb/ux/jdb-ux.cpp @@ -0,0 +1,456 @@ +INTERFACE [ux]: + +#include "types.h" +#include "l4_types.h" + +class Trap_state; +class Thread; +class Context; +class Jdb_entry_frame; +class Mem_space; + +EXTENSION class Jdb +{ +public: + typedef enum + { + s_unknown, s_ipc, s_syscall, s_pagefault, s_fputrap, + s_interrupt, s_timer_interrupt, s_slowtrap, s_user_invoke, + } Guessed_thread_state; + + enum { MIN_SCREEN_HEIGHT = 20, MIN_SCREEN_WIDTH = 80 }; + + template < typename T > static T peek(T const *addr, Address_type user); + + static int (*bp_test_log_only)(); + static int (*bp_test_break)(char *errbuf, size_t bufsize); + +private: + static unsigned short rows, cols; + +}; + +IMPLEMENTATION [ux]: + +#include +#include +#include +#include +#include + +#include "globals.h" +#include "initcalls.h" +#include "jdb_core.h" +#include "jdb_dbinfo.h" +#include "jdb_screen.h" +#include "kernel_console.h" +#include "kernel_task.h" +#include "kernel_thread.h" +#include "keycodes.h" +#include "kmem.h" +#include "libc_support.h" +#include "logdefs.h" +#include "mem_layout.h" +#include "push_console.h" +#include "simpleio.h" +#include "space.h" +#include "static_init.h" +#include "thread.h" +#include "thread_state.h" +#include "trap_state.h" +#include "usermode.h" +#include "vkey.h" + +int (*Jdb::bp_test_log_only)(); +int (*Jdb::bp_test_break)(char *errbuf, size_t bufsize); + +unsigned short Jdb::rows, Jdb::cols; + +static Proc::Status jdb_irq_state; + +IMPLEMENT inline +void +Jdb::enter_trap_handler(unsigned /*cpu*/) +{ + conf_screen(); + + // Set terminal raw mode + enter_getchar(); + + // Flush all output streams + fflush (NULL); +} + +IMPLEMENT inline +void +Jdb::leave_trap_handler(unsigned) +{ + // Restore terminal mode + leave_getchar(); + + // Flush all output streams + fflush (NULL); + +} + +PROTECTED static inline +void +Jdb::monitor_address(unsigned, void *) +{} + +IMPLEMENT inline +bool +Jdb::handle_user_request(unsigned /*cpu*/) +{ return false; } + +IMPLEMENT inline +bool +Jdb::test_checksums() +{ return true; } + + +// disable interrupts before entering the kernel debugger +IMPLEMENT +void +Jdb::save_disable_irqs(unsigned cpu) +{ + assert(cpu == 0); + jdb_irq_state = Proc::cli_save(); +} + +// restore interrupts after leaving the kernel debugger +IMPLEMENT +void +Jdb::restore_irqs(unsigned cpu) +{ + assert(cpu == 0); + Proc::sti_restore(jdb_irq_state); +} + +STATIC_INITIALIZE_P(Jdb,JDB_INIT_PRIO); + +PUBLIC static FIASCO_INIT +void +Jdb::init() +{ + // Install JDB handler + Trap_state::base_handler = (Trap_state::Handler)enter_jdb; + + // be sure that Push_console comes very first + Kconsole::console()->register_console(push_cons()), + + register_libc_atexit(leave_getchar); + atexit(leave_getchar); + + Thread::set_int3_handler(handle_int3_threadctx); +} + +PRIVATE +static void +Jdb::conf_screen() +{ + struct winsize win; + ioctl (fileno (stdin), TIOCGWINSZ, &win); + rows = win.ws_row; + cols = win.ws_col; + + if (rows < MIN_SCREEN_HEIGHT || cols < MIN_SCREEN_WIDTH) + printf ("%sTerminal probably too small, should be at least %dx%d!\033[0m\n", + esc_emph, MIN_SCREEN_WIDTH, MIN_SCREEN_HEIGHT); + + Jdb_screen::set_height(rows); + Jdb_screen::set_width(cols); +} + +/** handle int3 debug extension */ +PUBLIC static inline NOEXPORT +int +Jdb::int3_extension() +{ + Jdb_entry_frame *entry_frame = Jdb::entry_frame.cpu(0); + Address addr = entry_frame->ip(); + Address_type user = (entry_frame->cs() & 3) ? ADDR_USER : ADDR_KERNEL; + Unsigned8 todo = peek ((Unsigned8 *) addr, user); + Space *space = NULL; //get_task_id(0); + + if (todo == 0x3c && peek ((Unsigned8 *) (addr+1), user) == 13) + { + enter_getchar(); + entry_frame->_ax = Vkey::get(); + Vkey::clear(); + leave_getchar(); + return 1; + } + else if (todo != 0xeb) + { + snprintf (error_buffer.cpu(0), sizeof (error_buffer.cpu(0)), "INT 3"); + return 0; + } + + // todo == 0xeb => enter_kdebug() + Mword i; + Mword len = peek ((Unsigned8 *) ++addr, user); + + if (len > 2 && + peek (((Unsigned8 *) addr + 1), user) == '*' && + peek (((Unsigned8 *) addr + 2), user) == '#') + { + char c = peek (((Unsigned8 *) addr + 3), user); + + if ((c == '#') + ? execute_command_ni(space, (char const *) entry_frame->_ax) + : execute_command_ni(space, (char const *)(addr + 3), len-2)) + return 1; // => leave Jdb + } + + len = len < sizeof(error_buffer.cpu(0))-1 ? len : sizeof(error_buffer.cpu(0))-1; + for (i = 0; i < len; i++) + error_buffer.cpu(0)[i] = peek ((Unsigned8 *) ++addr, user); + error_buffer.cpu(0)[i] = 0; + return 0; +} + +static +bool +Jdb::handle_special_cmds(int) +{ return 1; } + +IMPLEMENT +bool +Jdb::handle_debug_traps(unsigned cpu) +{ + switch (entry_frame.cpu(cpu)->_trapno) + { + case 1: + snprintf (error_buffer.cpu(cpu), sizeof (error_buffer.cpu(cpu)), "Interception"); + break; + case 3: + if (int3_extension()) + return false; +#ifdef FIXME + if (get_thread(cpu)->d_taskno()) + { + if (bp_test_log_only && bp_test_log_only()) + return false; + if (bp_test_break + && bp_test_break(error_buffer.cpu(cpu), sizeof(error_buffer.cpu(cpu)))) + break; + } +#endif + } + + return true; +} + +IMPLEMENT +void +Jdb::handle_nested_trap(Jdb_entry_frame *e) +{ + printf("Trap in JDB: IP:%08lx\n", e->ip()); +} + +IMPLEMENT inline +bool +Jdb::handle_conditional_breakpoint(unsigned /*cpu*/) +{ return false; } + + +PUBLIC +static Space * +Jdb::translate_task(Address /*addr*/, Space *task) +{ + // we have no idea if addr belongs to kernel or user space + // since kernel and user occupy different address spaces + return task; +} + +PUBLIC +static Address +Jdb::virt_to_kvirt(Address virt, Mem_space* space) +{ + Mem_space::Phys_addr phys; + Mem_space::Size size; + + if (!space) + { + // Kernel address. + // We can directly access it via virtual addresses if it's kernel code + // (which is always mapped, but doesn't appear in the kernel pagetable) + // or if we find a mapping for it in the kernel's master pagetable. + return (virt >= (Address)&Mem_layout::load && + virt < (Kernel_thread::init_done() + ? (Address)&Mem_layout::end + : (Address)&Mem_layout::initcall_end) + || (Kernel_task::kernel_task()->virt_to_phys(virt) != ~0UL)) + ? virt + : (Address) -1; + } + else + { + // User address. + // We can't directly access it because it's in a different host process + // but if the task's pagetable has a mapping for it, we can translate + // task-virtual -> physical -> kernel-virtual address and then access. + return (space->v_lookup(Mem_space::Addr::create(virt), &phys, &size, 0)) + ? (Address) Kmem::phys_to_virt(phys.value() + (virt & (size.value()-1))) + : (Address) -1; + } +} + +IMPLEMENT inline NEEDS ["space.h"] +template +T +Jdb::peek (T const *addr, Address_type user) +{ + // FIXME: assume UP here (current_meme_space(0)) + return Mem_space::current_mem_space(0)->peek(addr, user); +} + +PUBLIC static +int +Jdb::peek_task(Address virt, Space *space, void *value, int width) +{ + // make sure we don't cross a page boundary + if (virt & (width-1)) + return -1; + + Address kvirt = virt_to_kvirt(virt, space); + if (kvirt == (Address)-1) + return -1; + + memcpy(value, (void*)kvirt, width); + return 0; +} + +PUBLIC static +int +Jdb::poke_task(Address virt, Space *space, void const *value, int width) +{ + // make sure we don't cross a page boundary + if (virt & (width-1)) + return -1; + + Address kvirt = virt_to_kvirt(virt, space); + + if (kvirt == (Address)-1) + return -1; + + memcpy((void*)kvirt, value, width); + return 0; +} + +PUBLIC +static int +Jdb::is_adapter_memory(Address /*addr*/, Space * /*task*/) +{ + return 0; +} + +#define WEAK __attribute__((weak)) +extern "C" char in_slowtrap, in_page_fault, in_handle_fputrap; +extern "C" char in_interrupt, in_timer_interrupt, in_timer_interrupt_slow; +extern "C" char i30_ret_switch WEAK, in_slow_ipc1 WEAK; +extern "C" char in_slow_ipc2 WEAK, in_slow_ipc4; +extern "C" char in_sc_ipc1 WEAK, in_sc_ipc2 WEAK, in_syscall WEAK; +#undef WEAK + +/** Try to guess the thread state of t by walking down the kernel stack and + * locking at the first return address we find. */ +PUBLIC +static Jdb::Guessed_thread_state +Jdb::guess_thread_state(Thread *t) +{ + Guessed_thread_state state = s_unknown; + Mword *ktop = (Mword*)((Mword)context_of(t->get_kernel_sp()) + + Context::Size); + + for (int i=-1; i>-26; i--) + { + if (ktop[i] != 0) + { + if (ktop[i] == (Mword)&in_page_fault) + state = s_pagefault; + if ((ktop[i] == (Mword)&i30_ret_switch) ||// shortcut.S, int 0x30 + (ktop[i] == (Mword)&in_slow_ipc1) || // shortcut.S, int 0x30 + (ktop[i] == (Mword)&in_slow_ipc4) || // entry.S, int 0x30 +#if !defined(CONFIG_ASSEMBLER_IPC_SHORTCUT) + (ktop[i] == (Mword)&in_sc_ipc1) || // entry.S, int 0x30 + (ktop[i] == (Mword)&in_sc_ipc2) || // entry.S, sysenter +#endif + 0) + state = s_ipc; + else if (ktop[i] == (Mword)&in_syscall) + state = s_syscall; + else if (ktop[i] == (Mword)&Thread::user_invoke) + state = s_user_invoke; + else if (ktop[i] == (Mword)&in_handle_fputrap) + state = s_fputrap; + else if (ktop[i] == (Mword)&in_interrupt) + state = s_interrupt; + else if ((ktop[i] == (Mword)&in_timer_interrupt) || + (ktop[i] == (Mword)&in_timer_interrupt_slow)) + state = s_timer_interrupt; + else if (ktop[i] == (Mword)&in_slowtrap) + state = s_slowtrap; + if (state != s_unknown) + break; + } + } + + if (state == s_unknown && (t->state() & Thread_ipc_mask)) + state = s_ipc; + + return state; +} + +// Don't make these members of Jdb else we have to include +// into the Jdb interface ... +static struct termios raw, new_raw; +static int getchar_entered; + +/** prepare Linux console for raw input */ +PUBLIC static +void +Jdb::enter_getchar() +{ + if (!getchar_entered++) + { + tcgetattr (fileno (stdin), &raw); + memcpy(&new_raw, &raw, sizeof(new_raw)); + new_raw.c_lflag &= ~(ICANON|ECHO); + new_raw.c_cc[VMIN] = 0; + new_raw.c_cc[VTIME] = 1; + tcsetattr (fileno (stdin), TCSAFLUSH, &new_raw); + } +} + +/** restore Linux console. */ +PUBLIC static +void +Jdb::leave_getchar() +{ + if (!--getchar_entered) + tcsetattr (fileno (stdin), TCSAFLUSH, &raw); +} + +PROTECTED static inline +template< typename T > +void +Jdb::set_monitored_address(T *dest, T val) +{ *dest = val; } + +PROTECTED static inline +template< typename T > +T Jdb::monitor_address(unsigned, T volatile *addr) +{ + return *addr; +} + +//---------------------------------------------------------------------------- +IMPLEMENTATION [ux && mp]: + +static +void +Jdb::send_nmi(unsigned /*cpu*/) +{ +} diff --git a/kernel/fiasco/src/jdb/ux/jdb_bp-ux.cpp b/kernel/fiasco/src/jdb/ux/jdb_bp-ux.cpp new file mode 100644 index 00000000..893c232b --- /dev/null +++ b/kernel/fiasco/src/jdb/ux/jdb_bp-ux.cpp @@ -0,0 +1,185 @@ +INTERFACE: + +EXTENSION class Jdb_bp +{ +private: + static int test_log_only(); + static int test_break(char *errbuf, size_t bufsize); +}; + + +IMPLEMENTATION[ux]: + +#include // for pid_t +#include "boot_info.h" +#include "task.h" +#include "usermode.h" +#include "jdb_kobject.h" + +PUBLIC inline +Mword +Breakpoint::restricted_task() +{ + return restrict.task.task; +} + +PUBLIC inline +void +Breakpoint::set(Address _addr, Mword _len, Mode _mode, Log _log) +{ + addr = _addr; + mode = _mode; + user = ADDR_USER; // we don't allow breakpoints in kernel space + log = _log; + len = _len; +} + +IMPLEMENT +int +Jdb_bp::global_breakpoints() +{ + return 0; +} + +PUBLIC static +Mword +Jdb_bp::read_debug_register(int reg, Space *s) +{ + pid_t pid = s ? s->pid() : Boot_info::pid(); + Mword val; + if (!Usermode::read_debug_register(pid, reg, val)) + printf("[read debugreg #%d task %p/%lx failed]\n", reg, s, + static_cast(s)->dbg_info()->dbg_id()); + + return val; +} + +static +void +Jdb_bp::write_debug_register(int reg, Mword val, Space *s) +{ + pid_t pid = s ? s->pid() : Boot_info::pid(); + if (!Usermode::write_debug_register(pid, reg, val)) + printf("[write %08lx to debugreg #%d task %p/%lx failed]\n", val, reg, s, + static_cast(s)->dbg_info()->dbg_id()); +} + +PUBLIC static inline +Mword +Jdb_bp::get_debug_control_register(Space *task) +{ + return read_debug_register(7, task); +} + +PUBLIC static inline +void +Jdb_bp::set_debug_control_register(Mword val, Space *task) +{ + printf("set_debug_control_register\n"); + for (int i=0; i<4; i++) + if (!(val & (2 << 2*i))) + val &= ~(0x0f << (16 + 4*i)); + write_debug_register(7, val, task); +} + +static +int +Jdb_bp::set_debug_address_register(int num, Mword addr, Mword len, + Breakpoint::Mode mode, Task *task) +{ + if (!task) + { + putstr(" => kernel task not allowed for breakpoints"); + return 0; + } + if (num >= 0 && num <= 3) + { + Mword local_dr7; + Task *old_task = Kobject::dcast(Kobject::from_dbg(Kobject_dbg::id_to_obj(bps[num].restricted_task()))); + + if (old_task) + { + // clear old breakpoint of other process + local_dr7 = get_debug_control_register(old_task); + clr_dr7(num, local_dr7); + set_debug_control_register(local_dr7, old_task); + } + bps[num].restrict_task(0, task->dbg_info()->dbg_id()); + write_debug_register(num, addr, task); + local_dr7 = get_debug_control_register(task); + clr_dr7(num, local_dr7); + set_dr7(num, len, mode, local_dr7); + set_debug_control_register(local_dr7, task); + return 1; + } + + return 0; +} + +static +void +Jdb_bp::clr_debug_address_register(int num) +{ + Task *task = Kobject::dcast(Kobject::from_dbg(Kobject_dbg::id_to_obj(bps[num].restricted_task()))); + Mword local_dr7 = get_debug_control_register(task); + clr_dr7(num, local_dr7); + set_debug_control_register(local_dr7, task); +} + +IMPLEMENT +void +Jdb_bp::at_jdb_enter() +{} + +IMPLEMENT +void +Jdb_bp::at_jdb_leave() +{ + if (Jdb::get_current_active() + && Jdb::get_current_active()->space() != Kernel_task::kernel_task()) + write_debug_register(6, 0, Jdb::get_current_active()->space()); +} + +IMPLEMENT +int +Jdb_bp::test_log_only() +{ + Space *t = Jdb::get_thread(0)->space(); + Mword dr6 = read_debug_register(6, t); + + if (dr6 & 0x0000000f) + { + test_log(dr6); + write_debug_register(6, dr6, t); + if (!(dr6 & 0x0000e00f)) + // don't enter jdb, breakpoints only logged + return 1; + } + // enter jdb + return 0; +} + +/** @return 1 if breakpoint occured */ +IMPLEMENT +int +Jdb_bp::test_break(char *errbuf, size_t bufsize) +{ + Space *t = Jdb::get_thread(0)->space(); + Mword dr6 = read_debug_register(6, t); + + if (!(dr6 & 0x000000f)) + return 0; + + test_break(dr6, errbuf, bufsize); + write_debug_register(6, dr6 & ~0x0000000f, t); + return 1; +} + +IMPLEMENT +void +Jdb_bp::init_arch() +{ + Jdb::bp_test_log_only = test_log_only; + Jdb::bp_test_break = test_break; +} + diff --git a/kernel/fiasco/src/jdb/ux/jdb_kern_info-ux.cpp b/kernel/fiasco/src/jdb/ux/jdb_kern_info-ux.cpp new file mode 100644 index 00000000..88610516 --- /dev/null +++ b/kernel/fiasco/src/jdb/ux/jdb_kern_info-ux.cpp @@ -0,0 +1,140 @@ +IMPLEMENTATION [ux]: + +#include +#include + +#include "cpu.h" +#include "perf_cnt.h" +#include "simpleio.h" +#include "space.h" +#include "jdb_kobject.h" + + +class Jdb_kern_info_misc : public Jdb_kern_info_module +{ +}; + +static Jdb_kern_info_misc k_i INIT_PRIORITY(JDB_MODULE_INIT_PRIO+1); + +PUBLIC +Jdb_kern_info_misc::Jdb_kern_info_misc() + : Jdb_kern_info_module('i', "Miscellaneous info") +{ + Jdb_kern_info::register_subcmd(this); +} + +PUBLIC +void +Jdb_kern_info_misc::show() +{ + printf ("clck: %08x.%08x\n", + (unsigned) (Kip::k()->clock >> 32), + (unsigned) (Kip::k()->clock)); + show_pdir(); +} + + +class Jdb_kern_info_cpu : public Jdb_kern_info_module +{ +}; + +static Jdb_kern_info_cpu k_c INIT_PRIORITY(JDB_MODULE_INIT_PRIO+1); + +PUBLIC +Jdb_kern_info_cpu::Jdb_kern_info_cpu() + : Jdb_kern_info_module('c', "CPU features") +{ + Jdb_kern_info::register_subcmd(this); +} + +PUBLIC +void +Jdb_kern_info_cpu::show() +{ + const char *perf_type = Perf_cnt::perf_type(); + char cpu_mhz[32]; + char time[32]; + unsigned hz; + + cpu_mhz[0] = '\0'; + if ((hz = Cpu::boot_cpu()->frequency())) + { + unsigned mhz = hz / 1000000; + hz -= mhz * 1000000; + unsigned khz = hz / 1000; + snprintf(cpu_mhz, sizeof(cpu_mhz), "%d.%03d MHz", mhz, khz); + } + + printf ("CPU: %s %s\n", Cpu::boot_cpu()->model_str(), cpu_mhz); + Cpu::boot_cpu()->show_cache_tlb_info(" "); + show_features(); + + if (Cpu::boot_cpu()->tsc()) + { + Unsigned32 hour, min, sec, ns; + Cpu::boot_cpu()->tsc_to_s_and_ns(Cpu::boot_cpu()->rdtsc(), &sec, &ns); + hour = sec / 3600; + sec -= hour * 3600; + min = sec / 60; + sec -= min * 60; + snprintf(time, sizeof(time), "%02d:%02d:%02d.%06d", + hour, min, sec, ns/1000); + } + else + strcpy(time, "not available"); + + printf("\nPerformance counters: %s" + "\nTime stamp counter: %s" + "\n", + perf_type ? perf_type : "no", + time); +} + +class Jdb_kern_info_host : public Jdb_kern_info_module +{ +}; + +static Jdb_kern_info_host k_H INIT_PRIORITY(JDB_MODULE_INIT_PRIO+1); + +PUBLIC +Jdb_kern_info_host::Jdb_kern_info_host() + : Jdb_kern_info_module('H', "Host information") +{ + Jdb_kern_info::register_subcmd(this); +} + +PUBLIC +void +Jdb_kern_info_host::show() +{ + for (Kobject_dbg::Iterator i = Kobject_dbg::begin(); i != Kobject_dbg::end(); ++i) + { + Task const *task = Kobject::dcast(Kobject::from_dbg(*i)); + if (!task) + continue; + + char buf[64]; + + Jdb_kobject::obj_description(buf, sizeof(buf), true, *i); + buf[sizeof(buf) - 1] = 0; + printf("%s, host-pid=%d\n", buf, task->pid()); + + snprintf(buf, sizeof(buf), "/proc/%d/maps", task->pid()); + buf[sizeof(buf) - 1] = 0; + int fd = open(buf, O_RDONLY); + if (fd >= 0) + { + int r; + do + { + r = read(fd, buf, sizeof(buf)); + if (r > 0) + printf("%.*s", r, buf); + } + while (r == sizeof(buf)); + close(fd); + } + + printf("\n"); + } +} diff --git a/kernel/fiasco/src/kern/acpi.cpp b/kernel/fiasco/src/kern/acpi.cpp new file mode 100644 index 00000000..66233def --- /dev/null +++ b/kernel/fiasco/src/kern/acpi.cpp @@ -0,0 +1,358 @@ +INTERFACE: + +#include + +class Acpi_gas +{ +public: + enum Type { System_mem = 0, System_io = 1, Pci_cfg_mem = 2 }; + Unsigned8 id; + Unsigned8 width; + Unsigned8 offset; + Unsigned8 access_size; + Unsigned64 addr; +} __attribute__((packed)); + + + +class Acpi_table_head +{ +public: + char signature[4]; + Unsigned32 len; + Unsigned8 rev; + Unsigned8 chk_sum; + char oem_id[6]; + char oem_tid[8]; + Unsigned32 oem_rev; + Unsigned32 creator_id; + Unsigned32 creator_rev; + + bool checksum_ok() const; +} __attribute__((packed)); + + +template< typename T > +class Acpi_sdt : public Acpi_table_head +{ +public: + T ptrs[0]; + +} __attribute__((packed)); + +typedef Acpi_sdt Acpi_rsdt; +typedef Acpi_sdt Acpi_xsdt; + +class Acpi_rsdp +{ +public: + char signature[8]; + Unsigned8 chk_sum; + char oem[6]; + Unsigned8 rev; + Unsigned32 rsdt_phys; + Unsigned32 len; + Unsigned64 xsdt_phys; + Unsigned8 ext_chk_sum; + char reserved[3]; + + Acpi_rsdt const *rsdt() const; + Acpi_xsdt const *xsdt() const; + + bool checksum_ok() const; + + static Acpi_rsdp const *locate(); +} __attribute__((packed)); + +class Acpi +{ +public: + static Acpi_rsdt const *rsdt() { return _rsdt; } + static Acpi_xsdt const *xsdt() { return _xsdt; } + +private: + static Acpi_rsdt const *_rsdt; + static Acpi_xsdt const *_xsdt; + static bool _init_done; +}; + +class Acpi_madt : public Acpi_table_head +{ +public: + enum Type + { LAPIC, IOAPIC, Irq_src_ovr, NMI, LAPIC_NMI, LAPIC_adr_ovr, IOSAPIC, + LSAPIC, Irq_src }; + + struct Apic_head + { + Unsigned8 type; + Unsigned8 len; + } __attribute__((packed)); + + struct Io_apic : public Apic_head + { + Unsigned8 id; + Unsigned8 res; + Unsigned32 adr; + Unsigned32 irq_base; + } __attribute__((packed)); + + struct Irq_source : public Apic_head + { + Unsigned8 bus; + Unsigned8 src; + Unsigned32 irq; + Unsigned16 flags; + } __attribute__((packed)); + +public: + Unsigned32 local_apic; + Unsigned32 apic_flags; + +private: + char data[0]; +} __attribute__((packed)); + + +IMPLEMENTATION: + +#include "kmem.h" +#include + +Acpi_rsdt const *Acpi::_rsdt; +Acpi_xsdt const *Acpi::_xsdt; +bool Acpi::_init_done; + + +static void +print_acpi_id(char const *id, unsigned len) +{ + char ID[len]; + for (unsigned i = 0; i < len; ++i) + ID[i] = isalnum(id[i]) ? id[i] : '.'; + printf("%.*s", len, ID); +} + +PUBLIC void +Acpi_rsdp::print_info() const +{ + printf("ACPI: RSDP[%p]\tr%02x OEM:", this, rev); + print_acpi_id(oem, 6); + printf("\n"); +} + +PUBLIC void +Acpi_table_head::print_info() const +{ + printf("ACPI: "); + print_acpi_id(signature, 4); + printf("[%p]\tr%02x OEM:", this, rev); + print_acpi_id(oem_id, 6); + printf(" OEMTID:"); + print_acpi_id(oem_tid, 8); + printf("\n"); +} + +PUBLIC template< typename T > +void +Acpi_sdt::print_summary() const +{ + for (unsigned i = 0; i < ((len-sizeof(Acpi_table_head))/sizeof(ptrs[0])); ++i) + { + Acpi_table_head const *t = Kmem::dev_map.map((Acpi_table_head const*)ptrs[i]); + if (t == (Acpi_table_head const *)~0UL) + continue; + + t->print_info(); + } +} + + +PUBLIC static +void +Acpi::init_virt() +{ + if (_init_done) + return; + _init_done = 1; + + printf("ACPI-Init\n"); + + Acpi_rsdp const *rsdp = Acpi_rsdp::locate(); + if (!rsdp) + { + printf("ACPI: Could not find RSDP, skip init\n"); + return; + } + + rsdp->print_info(); + + if (rsdp->rev && rsdp->xsdt_phys) + { + Acpi_xsdt const *x = Kmem::dev_map.map((const Acpi_xsdt *)rsdp->xsdt_phys); + if (x == (Acpi_xsdt const *)~0UL) + printf("ACPI: Could not map XSDT\n"); + else if (!x->checksum_ok()) + printf("ACPI: Checksum mismatch in XSDT\n"); + else + { + _xsdt = x; + x->print_info(); + } + } + + if (rsdp->rsdt_phys) + { + Acpi_rsdt const *r = Kmem::dev_map.map((const Acpi_rsdt *)rsdp->rsdt_phys); + if (r == (Acpi_rsdt const *)~0UL) + printf("ACPI: Could not map RSDT\n"); + else if (!r->checksum_ok()) + printf("ACPI: Checksum mismatch in RSDT\n"); + else + { + _rsdt = r; + r->print_info(); + } + } + + if (_xsdt) + _xsdt->print_summary(); + else if (_rsdt) + _rsdt->print_summary(); +} + +PUBLIC static +template< typename T > +T +Acpi::find(const char *s) +{ + T a = 0; + init_virt(); + if (_xsdt) + a = static_cast(_xsdt->find(s)); + else if (_rsdt) + a = static_cast(_rsdt->find(s)); + return a; +} + +IMPLEMENT +Acpi_rsdt const * +Acpi_rsdp::rsdt() const +{ + return (Acpi_rsdt const*)rsdt_phys; +} + +IMPLEMENT +Acpi_xsdt const * +Acpi_rsdp::xsdt() const +{ + if (rev == 0) + return 0; + return (Acpi_xsdt const*)xsdt_phys; +} + +IMPLEMENT +bool +Acpi_rsdp::checksum_ok() const +{ + // ACPI 1.0 checksum + Unsigned8 sum = 0; + for (unsigned i = 0; i < 20; i++) + sum += *((Unsigned8 *)this + i); + + if (sum) + return false; + + if (rev == 0) + return true; + + // Extended Checksum + for (unsigned i = 0; i < len && i < 4096; ++i) + sum += *((Unsigned8 *)this + i); + + return !sum; +} + +IMPLEMENT +bool +Acpi_table_head::checksum_ok() const +{ + Unsigned8 sum = 0; + for (unsigned i = 0; i < len && i < 4096; ++i) + sum += *((Unsigned8 *)this + i); + + return !sum; +} + +PUBLIC +template< typename T > +Acpi_table_head const * +Acpi_sdt::find(char const sig[4]) const +{ + for (unsigned i = 0; i < ((len-sizeof(Acpi_table_head))/sizeof(ptrs[0])); ++i) + { + Acpi_table_head const *t = Kmem::dev_map.map((Acpi_table_head const*)ptrs[i]); + if (t == (Acpi_table_head const *)~0UL) + continue; + + if (t->signature[0] == sig[0] + && t->signature[1] == sig[1] + && t->signature[2] == sig[2] + && t->signature[3] == sig[3] + && t->checksum_ok()) + return t; + } + + return 0; +} + +PUBLIC +Acpi_madt::Apic_head const * +Acpi_madt::find(Unsigned8 type, int idx) const +{ + for (unsigned i = 0; i < len-sizeof(Acpi_madt);) + { + Apic_head const *a = (Apic_head const *)(data + i); + //printf("a=%p, a->type=%u, a->len=%u\n", a, a->type, a->len); + if (a->type == type) + { + if (!idx) + return a; + --idx; + } + i += a->len; + } + + return 0; +} + +// ------------------------------------------------------------------------ +IMPLEMENTATION [ia32,amd64]: + +IMPLEMENT +Acpi_rsdp const * +Acpi_rsdp::locate() +{ + enum + { + ACPI20_PC99_RSDP_START = 0x0e0000, + ACPI20_PC99_RSDP_END = 0x100000 + }; + + for (Address p = ACPI20_PC99_RSDP_START; p < ACPI20_PC99_RSDP_END; p += 16) + { + Acpi_rsdp const* r = (Acpi_rsdp const *)p; + if (r->signature[0] == 'R' && + r->signature[1] == 'S' && + r->signature[2] == 'D' && + r->signature[3] == ' ' && + r->signature[4] == 'P' && + r->signature[5] == 'T' && + r->signature[6] == 'R' && + r->signature[7] == ' ' && + r->checksum_ok()) + return r; + } + + return 0; +} diff --git a/kernel/fiasco/src/kern/amd64/Makerules.SYMBOLS.amd64 b/kernel/fiasco/src/kern/amd64/Makerules.SYMBOLS.amd64 new file mode 100644 index 00000000..956ecab1 --- /dev/null +++ b/kernel/fiasco/src/kern/amd64/Makerules.SYMBOLS.amd64 @@ -0,0 +1,11 @@ +# -*- makefile -*- + +$(SYMBOLS): $(KERNEL) + $(COMP_MESSAGE) + $(VERBOSE)$(NM) -nC $(KERNEL)|grep "^f[0-9a-z]\{15,15\}">$@.new + $(VERBOSE)mv $@.new $@ + $(VERBOSE)chmod 644 $@ + $(call INSTALLFILE_RULE,$@,fiasco_symbols) + +clean-SYMBOLS: + rm -f $(SYMBOLS) diff --git a/kernel/fiasco/src/kern/app_cpu_thread.cpp b/kernel/fiasco/src/kern/app_cpu_thread.cpp new file mode 100644 index 00000000..6566708f --- /dev/null +++ b/kernel/fiasco/src/kern/app_cpu_thread.cpp @@ -0,0 +1,78 @@ +INTERFACE [mp]: + +#include "kernel_thread.h" + +class App_cpu_thread : public Kernel_thread +{ +private: + void bootstrap() asm ("call_ap_bootstrap") FIASCO_FASTCALL; +}; + +IMPLEMENTATION [mp]: + +#include +#include + +#include "config.h" +#include "delayloop.h" +#include "fpu.h" +#include "globals.h" +#include "helping_lock.h" +#include "kernel_task.h" +#include "processor.h" +#include "scheduler.h" +#include "task.h" +#include "thread.h" +#include "thread_state.h" +#include "timer.h" +#include "timer_tick.h" +#include "spin_lock.h" + + +PUBLIC inline +Mword * +App_cpu_thread::init_stack() +{ return _kernel_sp; } + +// the kernel bootstrap routine +IMPLEMENT +void +App_cpu_thread::bootstrap() +{ + extern Spin_lock _tramp_mp_spinlock; + + state_change_dirty(0, Thread_ready); // Set myself ready + + // Setup initial timeslice + set_current_sched(sched()); + + Fpu::init(cpu()); + + // initialize the current_mem_space function to point to the kernel space + Kernel_task::kernel_task()->make_current(); + + Mem_unit::tlb_flush(); + + Cpu::cpus.cpu(current_cpu()).set_online(1); + + _tramp_mp_spinlock.set(1); + + kernel_context(cpu(), this); + Sched_context::rq(cpu()).set_idle(this->sched()); + Rcu::leave_idle(cpu()); + + Timer_tick::setup(cpu(true)); + Timer_tick::enable(cpu(true)); + enable_tlb(cpu()); + + Per_cpu_data::run_late_ctors(cpu()); + + Scheduler::scheduler.trigger_hotplug_event(); + + cpu_lock.clear(); + + printf("CPU[%u]: goes to idle loop\n", cpu()); + + for (;;) + idle_op(); +} diff --git a/kernel/fiasco/src/kern/arm/Makerules.KERNEL b/kernel/fiasco/src/kern/arm/Makerules.KERNEL new file mode 100644 index 00000000..25f847f9 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/Makerules.KERNEL @@ -0,0 +1,27 @@ +# -*- makefile -*- + +ivt.o: $(TCBOFFSET) +tramp-mp.o: $(TCBOFFSET) + +# Add future prerequisites somewhere among the list of libraries. +# You really should not have to add anything in the $(LD) line. + +$(KERNEL).image: kernel.arm.lds $(CRT0) $(OBJ_KERNEL) $(JDB) $(LIBK) $(KERNEL_EXTRA_LIBS) $(LIBDISASM) $(ABI) libdrivers.a $(LIBUART) $(CXXLIB) $(MINILIBC) $(LIBGCC) $(MINILIBC) libgluedriverslibc.a + $(LINK_MESSAGE) + $(VERBOSE)$(LD) $(LDFLAGS) -N -defsym kernel_load_addr=$(CONFIG_KERNEL_LOAD_ADDR) \ + -T $< -o $@ $(filter-out $<,$+) + +$(KERNEL): $(KERNEL).image + $(LINK_MESSAGE) + $(VERBOSE)$(STRIP) $< -o $@ + chmod 755 $@ + +# $(OBJCOPY) -O binary $@ fiasco + +Symbols: $(KERNEL).image + $(NM) $(KERNEL).image | c++filt | sort > $@.new + mv $@.new $@ + chmod 755 $@ + + +clean-KERNEL: diff --git a/kernel/fiasco/src/kern/arm/__main.cpp b/kernel/fiasco/src/kern/arm/__main.cpp new file mode 100644 index 00000000..40f777e7 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/__main.cpp @@ -0,0 +1,23 @@ +INTERFACE [arm]: + +#include "types.h" + +//------------------------------------------------------------------------- +IMPLEMENTATION [arm]: + +#include +#include +#include +#include "boot_info.h" +#include "terminate.h" + +void kernel_main(void); + +extern "C" +void __main() +{ + atexit(&static_destruction); + static_construction(); + kernel_main(); + terminate(0); +} diff --git a/kernel/fiasco/src/kern/arm/boot_info-arch.cpp b/kernel/fiasco/src/kern/arm/boot_info-arch.cpp new file mode 100644 index 00000000..22d8a467 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/boot_info-arch.cpp @@ -0,0 +1,47 @@ +/* ARM specific boot_info */ + +INTERFACE [arm]: + +class Kip; + +EXTENSION class Boot_info +{ +public: + static void set_kip(Kip *kip); + static Kip *kip(); +}; + +//--------------------------------------------------------------------------- +IMPLEMENTATION [arm]: + +#include +#include // for debug printf's + +static Kip *boot_info_kip; + +IMPLEMENT +void Boot_info::set_kip(Kip *kip) +{ + boot_info_kip = kip; +} + +IMPLEMENT +Kip *Boot_info::kip() +{ + return boot_info_kip; +} + +extern "C" char _etext, _sstack, _stack, _edata, _end; + +IMPLEMENT static +void Boot_info::init() +{ + // We save the checksum for read-only data to be able to compare it against + // the kernel image later (in jdb::enter_kdebug()) + //saved_checksum_ro = boot_info::get_checksum_ro(); +} + +PUBLIC static +void +Boot_info::reset_checksum_ro(void) +{} diff --git a/kernel/fiasco/src/kern/arm/boot_uart_init.cpp b/kernel/fiasco/src/kern/arm/boot_uart_init.cpp new file mode 100644 index 00000000..173eb96f --- /dev/null +++ b/kernel/fiasco/src/kern/arm/boot_uart_init.cpp @@ -0,0 +1,10 @@ +IMPLEMENTATION [arm && serial]: + +#include "kernel_console.h" +#include "kernel_uart.h" +#include "static_init.h" + +STATIC_INITIALIZE_P(Kconsole, EARLY_INIT_PRIO); +STATIC_INITIALIZE_P(Kernel_uart, EARLY_INIT_PRIO); + + diff --git a/kernel/fiasco/src/kern/arm/bootstrap.cpp b/kernel/fiasco/src/kern/arm/bootstrap.cpp new file mode 100644 index 00000000..7db0355c --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bootstrap.cpp @@ -0,0 +1,183 @@ +INTERFACE [arm]: + +#include +#include "types.h" +#include "mem_layout.h" + +//--------------------------------------------------------------------------- +IMPLEMENTATION [arm]: + +#include "cpu.h" + +//--------------------------------------------------------------------------- +IMPLEMENTATION [arm && armv5]: + +enum +{ + Section_cachable = 0x40e, + Section_no_cache = 0x402, + Section_local = 0, + Section_global = 0, +}; + +void +set_asid() +{} + +//--------------------------------------------------------------------------- +IMPLEMENTATION [arm && armv6plus && (mpcore || armca9)]: + +enum +{ + Section_shared = 1UL << 16, +}; + +//--------------------------------------------------------------------------- +IMPLEMENTATION [arm && armv6plus && !(mpcore || armca9)]: + +enum +{ + Section_shared = 0, +}; + + +//--------------------------------------------------------------------------- +IMPLEMENTATION [arm && (armv6 || armv7)]: + +enum +{ + Section_cachable = 0x5406 | Section_shared, + Section_no_cache = 0x0402 | Section_shared, + Section_local = (1 << 17), + Section_global = 0, +}; + +void +set_asid() +{ + asm volatile ("MCR p15, 0, %0, c13, c0, 1" : : "r" (0)); // ASID 0 +} + +//--------------------------------------------------------------------------- +IMPLEMENTATION [arm && arm1176_cache_alias_fix]: + +static void +do_arm_1176_cache_alias_workaround() +{ + Mword v; + asm volatile ("mrc p15, 0, %0, c0, c0, 1 \n" : "=r" (v)); + if (v & ((1 << 23) | (1 << 11))) + { // P bits set + asm volatile ("mrc p15, 0, r0, c1, c0, 1 \n" + "orr r0, r0, #(1 << 6) \n" + "mcr p15, 0, r0, c1, c0, 1 \n" + : : : "r0"); + } +} + +//--------------------------------------------------------------------------- +IMPLEMENTATION [arm && !arm1176_cache_alias_fix]: + +static void do_arm_1176_cache_alias_workaround() {} + +//--------------------------------------------------------------------------- +IMPLEMENTATION [arm]: + +#include "kmem_space.h" +#include "pagetable.h" + +void +map_1mb(void *pd, Address va, Address pa, bool cache, bool local) +{ + Unsigned32 *const p = (Unsigned32*)pd; + p[va >> 20] = (pa & 0xfff00000) + | (cache ? Section_cachable : Section_no_cache) + | (local ? Section_local : Section_global); +} + +asm +( +".section .text.init,#alloc,#execinstr \n" +".global _start \n" +"_start: \n" +" ldr sp, __init_data \n" +" bl bootstrap_main \n" + +"__init_data: \n" +".long _stack \n" +".previous \n" +".section .bss \n" +" .space 2048 \n" +"_stack: \n" +".previous \n" +); + + +#include "mmu.h" + +#include "globalconfig.h" + +extern char bootstrap_bss_start[]; +extern char bootstrap_bss_end[]; +extern char __bss_start[]; +extern char __bss_end[]; + +enum +{ + Virt_ofs = Mem_layout::Sdram_phys_base - Mem_layout::Map_base, +}; + +extern "C" void bootstrap_main() +{ + extern char kernel_page_directory[]; + void *const page_dir = kernel_page_directory + Virt_ofs; + + Address va, pa; + // map sdram linear from 0xf0000000 + for (va = Mem_layout::Map_base, pa = Mem_layout::Sdram_phys_base; + va < Mem_layout::Map_base + (4 << 20); va += 0x100000, pa += 0x100000) + map_1mb(page_dir, va, pa, true, false); + + // map sdram 1:1 + for (va = Mem_layout::Sdram_phys_base; + va < Mem_layout::Sdram_phys_base + (4 << 20); va += 0x100000) + map_1mb(page_dir, va, va, true, true); + + map_hw(page_dir); + + unsigned domains = 0x55555555; // client for all domains + unsigned control = Config::Cache_enabled + ? Cpu::Cp15_c1_cache_enabled : Cpu::Cp15_c1_cache_disabled; + + Mmu::flush_cache(); + + extern char _start_kernel[]; + + do_arm_1176_cache_alias_workaround(); + set_asid(); + + asm volatile ( + "mcr p15, 0, %[null], c7, c10, 4\n" // dsb + "mcr p15, 0, %[null], c8, c7, 0 \n" // tlb flush + "mcr p15, 0, %[null], c7, c10, 4\n" // dsb + "mcr p15, 0, %[doms], c3, c0 \n" // domains + "mcr p15, 0, %[pdir], c2, c0 \n" // pdbr + "mcr p15, 0, %[control], c1, c0 \n" // control + + "mrc p15, 0, r0, c2, c0, 0 \n" // arbitrary read of cp15 + "mov r0, r0 \n" // wait for result + "sub pc, pc, #4 \n" + + "mov pc, %[start] \n" + : : + [pdir] "r"((Mword)page_dir | Page_table::Ttbr_bits), + [doms] "r"(domains), + [control] "r"(control), + [start] "r"(_start_kernel), + [null] "r"(0) + : "r0" + ); + + while(1) + ; +} diff --git a/kernel/fiasco/src/kern/arm/bsp/imx/Kconfig b/kernel/fiasco/src/kern/arm/bsp/imx/Kconfig new file mode 100644 index 00000000..6348b4f9 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/imx/Kconfig @@ -0,0 +1,34 @@ +# PF: IMX +# PFDESCR: Freescale i.MX +# PFDEPENDS: ARM + +choice + prompt "Freescale i.MX" + default PF_IMX_51 + +config PF_IMX_21 + bool "i.MX21" + depends on PF_IMX + select CAN_ARM_CPU_926 + help + Choose for i.MX21 + +config PF_IMX_35 + bool "i.MX35" + depends on PF_IMX + select CAN_ARM_CPU_1136 + +config PF_IMX_51 + bool "i.MX51" + depends on PF_IMX + select CAN_ARM_CPU_CORTEX_A8 + help + Choose for i.MX51 + +endchoice + +config PF_IMX_RAM_PHYS_BASE + hex + default 0xc0000000 if PF_IMX_21 + default 0x80000000 if PF_IMX_35 + default 0x90000000 if PF_IMX_51 diff --git a/kernel/fiasco/src/kern/arm/bsp/imx/Modules b/kernel/fiasco/src/kern/arm/bsp/imx/Modules new file mode 100644 index 00000000..7f3021f0 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/imx/Modules @@ -0,0 +1,27 @@ +# vim:set ft=make: + +SUBSYSTEMS += LIBUART +OBJECTS_LIBUART += uart_imx.o +PREPROCESS_PARTS += imx libuart generic_tickless_idle +PREPROCESS_PARTS += $(if $(CONFIG_PF_IMX_21),imx21 kern_start_0xd) +PREPROCESS_PARTS += $(if $(CONFIG_PF_IMX_35),imx35 imx_epit) +PREPROCESS_PARTS += $(if $(CONFIG_PF_IMX_51),imx51 imx_epit \ + pic_gic pic_gic_mxc_tzic) +CONFIG_KERNEL_LOAD_ADDR := $(CONFIG_PF_IMX_RAM_PHYS_BASE) + +INTERFACES_KERNEL += $(if $(CONFIG_PF_IMX_51),gic) + +uart_IMPL += uart-imx +config_IMPL += config-arm-imx +mem_layout_IMPL += mem_layout-arm-imx +pic_IMPL += $(if $(CONFIG_PF_IMX_21),pic-arm-imx) +pic_IMPL += $(if $(CONFIG_PF_IMX_35),pic-arm-imx) +pic_IMPL += $(if $(CONFIG_PF_IMX_51),pic-gic pic-arm-imx51) +bootstrap_IMPL += bootstrap-arm-imx +timer_IMPL += $(if $(CONFIG_PF_IMX_21),timer-arm-imx21) +timer_IMPL += $(if $(CONFIG_PF_IMX_35),timer-arm-imx_epit) +timer_IMPL += $(if $(CONFIG_PF_IMX_51),timer-arm-imx_epit) +timer_tick_IMPL += timer_tick-single-vector +kernel_uart_IMPL += kernel_uart-arm-imx +reset_IMPL += reset-arm-imx +clock_IMPL += clock-generic diff --git a/kernel/fiasco/src/kern/arm/bsp/imx/bootstrap-arm-imx.cpp b/kernel/fiasco/src/kern/arm/bsp/imx/bootstrap-arm-imx.cpp new file mode 100644 index 00000000..b3023a8e --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/imx/bootstrap-arm-imx.cpp @@ -0,0 +1,34 @@ +//----------------------------------------------------------------------------- +INTERFACE [arm && imx]: + +enum { + Cache_flush_area = 0xe0000000, +}; + +//----------------------------------------------------------------------------- +IMPLEMENTATION [arm && imx21]: +void +map_hw(void *pd) +{ + // map devices + map_1mb(pd, Mem_layout::Device_map_base_1, Mem_layout::Device_phys_base_1, false, false); +} + +//----------------------------------------------------------------------------- +IMPLEMENTATION [arm && imx35]: +void +map_hw(void *pd) +{ + map_1mb(pd, Mem_layout::Device_map_base_1, Mem_layout::Device_phys_base_1, false, false); + map_1mb(pd, Mem_layout::Device_map_base_2, Mem_layout::Device_phys_base_2, false, false); + map_1mb(pd, Mem_layout::Device_map_base_3, Mem_layout::Device_phys_base_3, false, false); +} + +//----------------------------------------------------------------------------- +IMPLEMENTATION [arm && imx51]: +void +map_hw(void *pd) +{ + map_1mb(pd, Mem_layout::Device_map_base_1, Mem_layout::Device_phys_base_1, false, false); + map_1mb(pd, Mem_layout::Device_map_base_2, Mem_layout::Device_phys_base_2, false, false); +} diff --git a/kernel/fiasco/src/kern/arm/bsp/imx/config-arm-imx.cpp b/kernel/fiasco/src/kern/arm/bsp/imx/config-arm-imx.cpp new file mode 100644 index 00000000..d4312141 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/imx/config-arm-imx.cpp @@ -0,0 +1,11 @@ +INTERFACE [arm && imx21]: + +#define TARGET_NAME "i.MX21" + +INTERFACE [arm && imx35]: + +#define TARGET_NAME "i.MX35" + +INTERFACE [arm && imx51]: + +#define TARGET_NAME "i.MX51" diff --git a/kernel/fiasco/src/kern/arm/bsp/imx/kernel_uart-arm-imx.cpp b/kernel/fiasco/src/kern/arm/bsp/imx/kernel_uart-arm-imx.cpp new file mode 100644 index 00000000..6dc29cca --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/imx/kernel_uart-arm-imx.cpp @@ -0,0 +1,12 @@ +INTERFACE: + +// On ARM the MMIO for the uart is accessible before the MMU is fully up +EXTENSION class Kernel_uart { enum { Bsp_init_mode = Init_before_mmu }; }; + +IMPLEMENTATION [arm && serial]: + +IMPLEMENT +bool Kernel_uart::startup(unsigned, int) +{ + return Uart::startup(); +} diff --git a/kernel/fiasco/src/kern/arm/bsp/imx/mem_layout-arm-imx.cpp b/kernel/fiasco/src/kern/arm/bsp/imx/mem_layout-arm-imx.cpp new file mode 100644 index 00000000..b86b2b06 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/imx/mem_layout-arm-imx.cpp @@ -0,0 +1,92 @@ +INTERFACE [arm && imx]: //---------------------------------------------- + +EXTENSION class Mem_layout +{ +public: + enum Virt_layout_imx { + Device_map_base_1 = Registers_map_start, + Device_map_base_2 = Registers_map_start + 0x100000, + Device_map_base_3 = Registers_map_start + 0x200000, + }; + + enum Phys_layout { + Sdram_phys_base = CONFIG_PF_IMX_RAM_PHYS_BASE, + Flush_area_phys_base = 0xe0000000, + }; +}; + +INTERFACE [arm && imx && imx21]: // --------------------------------------- + +EXTENSION class Mem_layout +{ +public: + enum Virt_layout_imx21 { + Uart_map_base = 0xef10a000, + Timer_map_base = 0xef103000, + Pll_map_base = 0xef127000, + Watchdog_map_base = 0xef102000, + Pic_map_base = 0xef140000, + Uart_base = Uart_map_base, + }; + + enum Phys_layout_imx21 { + Device_phys_base_1 = 0x10000000, + + Timer_phys_base = 0x10003000, + Uart_phys_base = 0x1000a000, + Pll_phys_base = 0x10027000, + Watchdog_phys_base = 0x10002000, + Pic_phys_base = 0x10040000, + }; +}; + +INTERFACE [arm && imx && imx35]: // --------------------------------------- + +EXTENSION class Mem_layout +{ +public: + enum Virt_layout_imx35 { + Uart_map_base = Device_map_base_1 + 0x90000, + Timer_map_base = Device_map_base_2 + 0x94000, + Watchdog_map_base = Device_map_base_2 + 0xdc000, + Pic_map_base = Device_map_base_3 + 0x0, + Uart_base = Uart_map_base, + }; + + enum Phys_layout_imx35 { + Device_phys_base_1 = 0x43f00000, + Device_phys_base_2 = 0x53f00000, + Device_phys_base_3 = 0x68000000, + + Timer_phys_base = 0x53f94000, // epit1 + Uart_phys_base = 0x43f90000, // uart1 + Watchdog_phys_base = 0x53fdc000, // wdog + Pic_phys_base = 0x68000000, + }; +}; + + +INTERFACE [arm && imx && imx51]: // --------------------------------------- + +EXTENSION class Mem_layout +{ +public: + enum Virt_layout_imx51 { + Timer_map_base = 0xef1ac000, + Uart_map_base = 0xef1bc000, + Watchdog_map_base = 0xef198000, + Gic_cpu_map_base = 0, + Gic_dist_map_base = 0xef200000, + Uart_base = Uart_map_base, + }; + + enum Phys_layout_imx51 { + Device_phys_base_1 = 0x73f00000, + Device_phys_base_2 = 0xe0000000, + + Watchdog_phys_base = 0x73f98000, // wdog1 + Timer_phys_base = 0x73fac000, // epit1 + Uart_phys_base = 0x73fbc000, // uart1 + Gic_dist_phys_base = 0xe0000000, + }; +}; diff --git a/kernel/fiasco/src/kern/arm/bsp/imx/pic-arm-imx.cpp b/kernel/fiasco/src/kern/arm/bsp/imx/pic-arm-imx.cpp new file mode 100644 index 00000000..b71b04dc --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/imx/pic-arm-imx.cpp @@ -0,0 +1,138 @@ +// --------------------------------------------------------------------- +INTERFACE [arm && (imx21 || imx35)]: + +#include "kmem.h" + +class Irq_base; + +EXTENSION class Pic +{ +public: + enum + { + INTCTL = Kmem::Pic_map_base + 0x00, + NIMASK = Kmem::Pic_map_base + 0x04, + INTENNUM = Kmem::Pic_map_base + 0x08, + INTDISNUM = Kmem::Pic_map_base + 0x0c, + INTENABLEH = Kmem::Pic_map_base + 0x10, + INTENABLEL = Kmem::Pic_map_base + 0x14, + INTTYPEH = Kmem::Pic_map_base + 0x18, + INTTYPEL = Kmem::Pic_map_base + 0x1c, + NIPRIORITY7 = Kmem::Pic_map_base + 0x20, + NIPRIORITY0 = Kmem::Pic_map_base + 0x3c, + NIVECSR = Kmem::Pic_map_base + 0x40, + FIVECSR = Kmem::Pic_map_base + 0x44, + INTSRCH = Kmem::Pic_map_base + 0x48, + INTSRCL = Kmem::Pic_map_base + 0x4c, + INTFRCH = Kmem::Pic_map_base + 0x50, + INTFRCL = Kmem::Pic_map_base + 0x54, + NIPNDH = Kmem::Pic_map_base + 0x58, + NIPNDL = Kmem::Pic_map_base + 0x5c, + FIPNDH = Kmem::Pic_map_base + 0x60, + FIPNDL = Kmem::Pic_map_base + 0x64, + + + INTCTL_FIAD = 1 << 19, // Fast Interrupt Arbiter Rise ARM Level + INTCTL_NIAD = 1 << 20, // Normal Interrupt Arbiter Rise ARM Level + INTCTL_FIDIS = 1 << 21, // Fast Interrupt Disable + INTCTL_NIDIS = 1 << 22, // Normal Interrupt Disable + }; +}; + +// --------------------------------------------------------------------- +IMPLEMENTATION [arm && (imx21 || imx35)]: + +#include "io.h" +#include "irq_chip_generic.h" +#include "irq_mgr.h" + +class Irq_chip_arm_imx : public Irq_chip_gen +{ +public: + Irq_chip_arm_imx() : Irq_chip_gen(64) {} + unsigned set_mode(Mword, unsigned) { return Irq_base::Trigger_level; } + void set_cpu(Mword, unsigned) {} + void ack(Mword) { /* ack is empty */ } +}; + +PUBLIC +void +Irq_chip_arm_imx::mask(Mword irq) +{ + assert(cpu_lock.test()); + Io::write(irq, Pic::INTDISNUM); // disable pin +} + +PUBLIC +void +Irq_chip_arm_imx::mask_and_ack(Mword irq) +{ + assert(cpu_lock.test()); + Io::write(irq, Pic::INTDISNUM); // disable pin + // ack is empty +} + +PUBLIC +void +Irq_chip_arm_imx::unmask(Mword irq) +{ + assert (cpu_lock.test()); + Io::write(irq, Pic::INTENNUM); +} + +static Static_object > mgr; + + +IMPLEMENT FIASCO_INIT +void Pic::init() +{ + Irq_mgr::mgr = mgr.construct(); + + Io::write(0, INTCTL); + Io::write(0x10, NIMASK); // Do not disable any normal interrupts + + Io::write(0, INTTYPEH); // All interrupts generate normal interrupts + Io::write(0, INTTYPEL); + + // Init interrupt priorities + for (int i = 0; i < 8; ++i) + Io::write(0x1111, NIPRIORITY7 + (i * 4)); // low addresses start with 7 +} + +IMPLEMENT inline +Pic::Status Pic::disable_all_save() +{ + Status s = 0; + return s; +} + +IMPLEMENT inline +void Pic::restore_all(Status) +{} + +PUBLIC static inline NEEDS["io.h"] +Unsigned32 Irq_chip_arm_imx::pending() +{ + return Io::read(Pic::NIVECSR) >> 16; +} + +PUBLIC inline NEEDS[Irq_chip_arm_imx::pending] +void +Irq_chip_arm_imx::irq_handler() +{ + Unsigned32 p = pending(); + if (EXPECT_TRUE(p != 0xffff)) + handle_irq(p, 0); +} + +extern "C" +void irq_handler() +{ mgr->c.irq_handler(); } + +//--------------------------------------------------------------------------- +IMPLEMENTATION [debug && imx]: + +PUBLIC +char const * +Irq_chip_arm_imx::chip_type() const +{ return "HW i.MX IRQ"; } diff --git a/kernel/fiasco/src/kern/arm/bsp/imx/pic-arm-imx51.cpp b/kernel/fiasco/src/kern/arm/bsp/imx/pic-arm-imx51.cpp new file mode 100644 index 00000000..02ec9450 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/imx/pic-arm-imx51.cpp @@ -0,0 +1,31 @@ +INTERFACE [arm && pic_gic && imx51]: + +#include "gic.h" + +// ------------------------------------------------------------------------ +IMPLEMENTATION [arm && pic_gic && imx51]: + +#include "irq_mgr_multi_chip.h" +#include "kmem.h" + +IMPLEMENT FIASCO_INIT +void +Pic::init() +{ + typedef Irq_mgr_multi_chip<7> M; + + M *m = new Boot_object(1); + + gic.construct(0, Kmem::Gic_dist_map_base); + m->add_chip(0, gic, gic->nr_irqs()); + + Irq_mgr::mgr = m; +} + +IMPLEMENT inline +Pic::Status Pic::disable_all_save() +{ return 0; } + +IMPLEMENT inline +void Pic::restore_all(Status) +{} diff --git a/kernel/fiasco/src/kern/arm/bsp/imx/reset-arm-imx.cpp b/kernel/fiasco/src/kern/arm/bsp/imx/reset-arm-imx.cpp new file mode 100644 index 00000000..7e7776f2 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/imx/reset-arm-imx.cpp @@ -0,0 +1,46 @@ +IMPLEMENTATION [arm && imx21]: + +#include "io.h" +#include "kmem.h" + +void __attribute__ ((noreturn)) +platform_reset(void) +{ + enum { + WCR = Kmem::Watchdog_map_base + 0, + WCR_SRS = 1 << 4, // Software Reset Signal + + PLL_PCCR1 = Kmem::Pll_map_base + 0x24, + PLL_PCCR1_WDT_EN = 1 << 24, + }; + + // WDT CLock Enable + Io::write(Io::read(PLL_PCCR1) | PLL_PCCR1_WDT_EN, PLL_PCCR1); + + // Assert Software reset signal by making the bit zero + Io::write(Io::read(WCR) & ~WCR_SRS, WCR); + + for (;;) + ; +} + +// ------------------------------------------------------------------------ +IMPLEMENTATION [arm && (imx35 || imx51)]: + +#include "io.h" +#include "kmem.h" + +void __attribute__ ((noreturn)) +platform_reset(void) +{ + enum { + WCR = Kmem::Watchdog_map_base + 0, + WCR_SRS = 1 << 4, // Software Reset Signal + }; + + // Assert Software reset signal by making the bit zero + Io::write(Io::read(WCR) & ~WCR_SRS, WCR); + + for (;;) + ; +} diff --git a/kernel/fiasco/src/kern/arm/bsp/imx/timer-arm-imx21.cpp b/kernel/fiasco/src/kern/arm/bsp/imx/timer-arm-imx21.cpp new file mode 100644 index 00000000..672af88d --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/imx/timer-arm-imx21.cpp @@ -0,0 +1,85 @@ +// -------------------------------------------------------------------------- +INTERFACE [arm && imx21]: + +#include "kmem.h" +#include "irq_chip.h" + +EXTENSION class Timer +{ +public: + static unsigned irq() { return 26; } + +private: + enum { + TCTL = Kmem::Timer_map_base + 0x00, + TPRER = Kmem::Timer_map_base + 0x04, + TCMP = Kmem::Timer_map_base + 0x08, + TCR = Kmem::Timer_map_base + 0x0c, + TCN = Kmem::Timer_map_base + 0x10, + TSTAT = Kmem::Timer_map_base + 0x14, + + TCTL_TEN = 1 << 0, + TCTL_CLKSOURCE_PERCLK1_TO_PRESCALER = 1 << 1, + TCTL_CLKSOURCE_32kHz = 1 << 3, + TCTL_COMP_EN = 1 << 4, + TCTL_SW_RESET = 1 << 15, + }; +}; + +// ---------------------------------------------------------------------- +IMPLEMENTATION [arm && imx21]: + +#include "config.h" +#include "kip.h" +#include "io.h" + +#include + +IMPLEMENT +void Timer::init(unsigned) +{ + Io::write(0, TCTL); // Disable + Io::write(TCTL_SW_RESET, TCTL); // reset timer + for (int i = 0; i < 10; ++i) + Io::read(TCN); // docu says reset takes 5 cycles + + Io::write(TCTL_CLKSOURCE_32kHz | TCTL_COMP_EN, TCTL); + Io::write(0, TPRER); + Io::write(32, TCMP); + + Io::set(TCTL_TEN, TCTL); +} + +static inline +Unsigned64 +Timer::timer_to_us(Unsigned32 /*cr*/) +{ return 0; } + +static inline +Unsigned64 +Timer::us_to_timer(Unsigned64 us) +{ (void)us; return 0; } + +PUBLIC static inline NEEDS["io.h"] +void +Timer::acknowledge() +{ + Io::write(1, TSTAT); +} + +IMPLEMENT inline NEEDS["kip.h", "io.h", Timer::timer_to_us, Timer::us_to_timer] +void +Timer::update_one_shot(Unsigned64 /*wakeup*/) +{ +} + +IMPLEMENT inline NEEDS["config.h", "kip.h", "io.h", Timer::timer_to_us] +Unsigned64 +Timer::system_clock() +{ + if (Config::Scheduler_one_shot) + //return Kip::k()->clock + timer_to_us(Io::read(OSCR)); + return 0; + else + return Kip::k()->clock; +} diff --git a/kernel/fiasco/src/kern/arm/bsp/imx/timer-arm-imx_epit.cpp b/kernel/fiasco/src/kern/arm/bsp/imx/timer-arm-imx_epit.cpp new file mode 100644 index 00000000..2231f5ac --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/imx/timer-arm-imx_epit.cpp @@ -0,0 +1,112 @@ +// -------------------------------------------------------------------------- +INTERFACE [arm && imx_epit]: + +#include "kmem.h" + +EXTENSION class Timer +{ +private: + enum { + EPITCR = Kmem::Timer_map_base + 0x00, + EPITSR = Kmem::Timer_map_base + 0x04, + EPITLR = Kmem::Timer_map_base + 0x08, + EPITCMPR = Kmem::Timer_map_base + 0x0c, + EPITCNR = Kmem::Timer_map_base + 0x10, + + EPITCR_ENABLE = 1 << 0, // enable EPIT + EPITCR_ENMOD = 1 << 1, // enable mode + EPITCR_OCIEN = 1 << 2, // output compare irq enable + EPITCR_RLD = 1 << 3, // reload + EPITCR_SWR = 1 << 16, // software reset + EPITCR_WAITEN = 1 << 19, // wait enabled + EPITCR_CLKSRC_IPG_CLK = 1 << 24, + EPITCR_CLKSRC_IPG_CLK_HIGHFREQ = 2 << 24, + EPITCR_CLKSRC_IPG_CLK_32K = 3 << 24, + EPITCR_PRESCALER_SHIFT = 4, + EPITCR_PRESCALER_MASK = ((1 << 12) - 1) << EPITCR_PRESCALER_SHIFT, + + EPITSR_OCIF = 1, + }; +}; + + +INTERFACE [arm && imx35]: // ---------------------------------------------- + +EXTENSION class Timer +{ +public: + static unsigned irq() { return 28; } +}; + + +INTERFACE [arm && imx51]: // ---------------------------------------------- + +EXTENSION class Timer +{ +public: + static unsigned irq() { return 40; } +}; + + +// ------------------------------------------------------------------------ +IMPLEMENTATION [arm && imx_epit]: + +#include "io.h" +#include "kip.h" + +IMPLEMENT +void Timer::init(unsigned) +{ + Io::write(0, EPITCR); // Disable + Io::write(EPITCR_SWR, EPITCR); + while (Io::read(EPITCR) & EPITCR_SWR) + ; + + Io::write(EPITSR_OCIF, EPITSR); + + Io::write(EPITCR_CLKSRC_IPG_CLK_32K + | (0 << EPITCR_PRESCALER_SHIFT) + | EPITCR_WAITEN + | EPITCR_RLD + | EPITCR_OCIEN + | EPITCR_ENMOD, + EPITCR); + + Io::write(0, EPITCMPR); + + Io::write(32, EPITLR); + + Io::set(EPITCR_ENABLE, EPITCR); +} + +static inline +Unsigned64 +Timer::timer_to_us(Unsigned32 /*cr*/) +{ return 0; } + +static inline +Unsigned64 +Timer::us_to_timer(Unsigned64 us) +{ (void)us; return 0; } + +PUBLIC static inline NEEDS["io.h"] +void +Timer::acknowledge() +{ + Io::write(EPITSR_OCIF, EPITSR); +} + +IMPLEMENT inline +void +Timer::update_one_shot(Unsigned64 /*wakeup*/) +{} + +IMPLEMENT inline NEEDS["config.h", "kip.h"] +Unsigned64 +Timer::system_clock() +{ + if (Config::Scheduler_one_shot) + return 0; + else + return Kip::k()->clock; +} diff --git a/kernel/fiasco/src/kern/arm/bsp/imx/uart-imx.cpp b/kernel/fiasco/src/kern/arm/bsp/imx/uart-imx.cpp new file mode 100644 index 00000000..2f55d22a --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/imx/uart-imx.cpp @@ -0,0 +1,44 @@ +IMPLEMENTATION [imx21]: + +#include "uart_imx.h" + +IMPLEMENT int Uart::irq() const { return 20; } + +IMPLEMENT L4::Uart *Uart::uart() +{ + static L4::Uart_imx21 uart; + return &uart; +} + +IMPLEMENTATION [imx35]: + +#include "uart_imx.h" + +// uart-1: 45 +// uart-2: 32 +// uart-3: 18 +IMPLEMENT int Uart::irq() const { return 45; } + +IMPLEMENT L4::Uart *Uart::uart() +{ + static L4::Uart_imx35 uart; + return &uart; +} + +IMPLEMENTATION [imx51]: + +#include "uart_imx.h" + +IMPLEMENT int Uart::irq() const { return 31; } + +IMPLEMENT L4::Uart *Uart::uart() +{ + static L4::Uart_imx51 uart; + return &uart; +} + +IMPLEMENTATION [imx21 || imx35 || imx51]: + +#include "mem_layout.h" + +IMPLEMENT Address Uart::base() const { return Mem_layout::Uart_base; } diff --git a/kernel/fiasco/src/kern/arm/bsp/integrator/Kconfig b/kernel/fiasco/src/kern/arm/bsp/integrator/Kconfig new file mode 100644 index 00000000..4352bcee --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/integrator/Kconfig @@ -0,0 +1,4 @@ +# PF: INTEGRATOR +# PFDESCR: ARM Integrator Platform +# PFCAN: CAN_ARM_CPU_926 CAN_ARM_CPU_1176 +# PFDEPENDS: ARM diff --git a/kernel/fiasco/src/kern/arm/bsp/integrator/Modules b/kernel/fiasco/src/kern/arm/bsp/integrator/Modules new file mode 100644 index 00000000..04adfc7e --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/integrator/Modules @@ -0,0 +1,18 @@ +# vim:set ft=make: + +SUBSYSTEMS += LIBUART +OBJECTS_LIBUART += uart_pl011.o +PREPROCESS_PARTS += integrator libuart generic_tickless_idle +CONFIG_KERNEL_LOAD_ADDR := 0x00000000 + + +uart_IMPL += uart-arm-integrator +config_IMPL += config-arm-integrator +mem_layout_IMPL += mem_layout-arm-integrator +pic_IMPL += pic-arm-integrator +bootstrap_IMPL += bootstrap-arm-integrator +timer_IMPL += timer-arm-integrator +timer_tick_IMPL += timer_tick-single-vector +kernel_uart_IMPL += kernel_uart-arm-integrator +reset_IMPL += reset-arm-integrator +clock_IMPL += clock-generic diff --git a/kernel/fiasco/src/kern/arm/bsp/integrator/bootstrap-arm-integrator.cpp b/kernel/fiasco/src/kern/arm/bsp/integrator/bootstrap-arm-integrator.cpp new file mode 100644 index 00000000..0facae8b --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/integrator/bootstrap-arm-integrator.cpp @@ -0,0 +1,21 @@ +//----------------------------------------------------------------------------- +INTERFACE [arm && integrator]: + +enum { + Cache_flush_area = 0xe0000000, +}; + +//----------------------------------------------------------------------------- +IMPLEMENTATION [arm && integrator]: +void +map_hw(void *pd) +{ + // map UART + map_1mb(pd, Mem_layout::Uart_map_base, Mem_layout::Uart_phys_base, false, false); + // map Timer + map_1mb(pd, Mem_layout::Timer_map_base, Mem_layout::Timer_phys_base, false, false); + // map Pic + map_1mb(pd, Mem_layout::Pic_map_base, Mem_layout::Pic_phys_base, false, false); + // map Integrator hdr + map_1mb(pd, Mem_layout::Integrator_map_base, Mem_layout::Integrator_phys_base, false, false); +} diff --git a/kernel/fiasco/src/kern/arm/bsp/integrator/config-arm-integrator.cpp b/kernel/fiasco/src/kern/arm/bsp/integrator/config-arm-integrator.cpp new file mode 100644 index 00000000..3fb4d645 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/integrator/config-arm-integrator.cpp @@ -0,0 +1,3 @@ +INTERFACE [arm && integrator]: + +#define TARGET_NAME "Integrator" diff --git a/kernel/fiasco/src/kern/arm/bsp/integrator/kernel_uart-arm-integrator.cpp b/kernel/fiasco/src/kern/arm/bsp/integrator/kernel_uart-arm-integrator.cpp new file mode 100644 index 00000000..5ccb9283 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/integrator/kernel_uart-arm-integrator.cpp @@ -0,0 +1,12 @@ +INTERFACE: + +// On ARM the MMIO for the uart is accessible before the MMU is fully up +EXTENSION class Kernel_uart { enum { Bsp_init_mode = Init_before_mmu }; }; + +IMPLEMENTATION [arm && integrator && serial]: + +IMPLEMENT +bool Kernel_uart::startup(unsigned, int) +{ + return Uart::startup(); +} diff --git a/kernel/fiasco/src/kern/arm/bsp/integrator/mem_layout-arm-integrator.cpp b/kernel/fiasco/src/kern/arm/bsp/integrator/mem_layout-arm-integrator.cpp new file mode 100644 index 00000000..9d204195 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/integrator/mem_layout-arm-integrator.cpp @@ -0,0 +1,23 @@ +INTERFACE [arm-integrator]: //---------------------------------------------- + +EXTENSION class Mem_layout +{ +public: + enum Virt_layout_integrator { + Uart_map_base = 0xef100000, + Timer_map_base = 0xef200000, + Pic_map_base = 0xef300000, + Integrator_map_base = 0xef400000, + Uart_base = Uart_map_base, + }; + + enum Phys_layout { + Uart_phys_base = 0x16000000, + Timer_phys_base = 0x13000000, + Pic_phys_base = 0x14000000, + Integrator_phys_base = 0x10000000, + Sdram_phys_base = 0x00000000, + Flush_area_phys_base = 0xe0000000, + }; +}; + diff --git a/kernel/fiasco/src/kern/arm/bsp/integrator/pic-arm-integrator.cpp b/kernel/fiasco/src/kern/arm/bsp/integrator/pic-arm-integrator.cpp new file mode 100644 index 00000000..f8b37df2 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/integrator/pic-arm-integrator.cpp @@ -0,0 +1,101 @@ +// --------------------------------------------------------------------- +INTERFACE [arm-integrator]: + +#include "kmem.h" + +EXTENSION class Pic +{ +public: + enum + { + IRQ_STATUS = Kmem::Pic_map_base + 0x00, + IRQ_ENABLE_SET = Kmem::Pic_map_base + 0x08, + IRQ_ENABLE_CLEAR = Kmem::Pic_map_base + 0x0c, + + FIQ_ENABLE_CLEAR = Kmem::Pic_map_base + 0x2c, + + PIC_START = 0, + PIC_END = 31, + }; +}; + +// --------------------------------------------------------------------- +IMPLEMENTATION [arm && integrator]: + +#include "io.h" +#include "irq_chip_generic.h" +#include "irq_mgr.h" + +class Irq_chip_arm_integr : public Irq_chip_gen +{ +public: + Irq_chip_arm_integr() : Irq_chip_gen(32) {} + unsigned set_mode(Mword, unsigned) { return Irq_base::Trigger_level; } + void set_cpu(Mword, unsigned) {} + void ack(Mword) { /* ack is empty */ } +}; + +PUBLIC +void +Irq_chip_arm_integr::mask(Mword irq) +{ + assert(cpu_lock.test()); + Io::write(1 << (irq - Pic::PIC_START), Pic::IRQ_ENABLE_CLEAR); +} + +PUBLIC +void +Irq_chip_arm_integr::mask_and_ack(Mword irq) +{ + assert(cpu_lock.test()); + Io::write(1 << (irq - Pic::PIC_START), Pic::IRQ_ENABLE_CLEAR); + // ack is empty +} + +PUBLIC +void +Irq_chip_arm_integr::unmask(Mword irq) +{ + assert(cpu_lock.test()); + Io::write(1 << (irq - Pic::PIC_START), Pic::IRQ_ENABLE_SET); +} + +static Static_object > mgr; + +IMPLEMENT FIASCO_INIT +void Pic::init() +{ + Irq_mgr::mgr = mgr.construct(); + + Io::write(0xffffffff, IRQ_ENABLE_CLEAR); + Io::write(0xffffffff, FIQ_ENABLE_CLEAR); +} + +IMPLEMENT inline +Pic::Status Pic::disable_all_save() +{ + Status s = 0; + return s; +} + +IMPLEMENT inline +void Pic::restore_all(Status) +{} + +PUBLIC static inline NEEDS["io.h"] +Unsigned32 Irq_chip_arm_integr::pending() +{ + return Io::read(Pic::IRQ_STATUS); +} + +extern "C" +void irq_handler() +{ mgr->c.handle_multi_pending(0); } + +//--------------------------------------------------------------------------- +IMPLEMENTATION [debug && integrator]: + +PUBLIC +char const * +Irq_chip_arm_integr::chip_type() const +{ return "Integrator"; } diff --git a/kernel/fiasco/src/kern/arm/bsp/integrator/reset-arm-integrator.cpp b/kernel/fiasco/src/kern/arm/bsp/integrator/reset-arm-integrator.cpp new file mode 100644 index 00000000..8c99e7f7 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/integrator/reset-arm-integrator.cpp @@ -0,0 +1,17 @@ +IMPLEMENTATION [arm && integrator]: + +#include "io.h" +#include "kmem.h" + +void __attribute__ ((noreturn)) +platform_reset(void) +{ + enum { + HDR_CTRL_OFFSET = Kmem::Integrator_map_base + 0xc, + }; + + Io::write(1 << 3, HDR_CTRL_OFFSET); + + for (;;) + ; +} diff --git a/kernel/fiasco/src/kern/arm/bsp/integrator/timer-arm-integrator.cpp b/kernel/fiasco/src/kern/arm/bsp/integrator/timer-arm-integrator.cpp new file mode 100644 index 00000000..a796a378 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/integrator/timer-arm-integrator.cpp @@ -0,0 +1,87 @@ +// -------------------------------------------------------------------------- +INTERFACE [arm && integrator]: + +#include "kmem.h" + +EXTENSION class Timer +{ +public: + static unsigned irq() { return 6; } + +private: + enum { + Base = Kmem::Timer_map_base, + + TIMER0_VA_BASE = Base + 0x000, + TIMER1_VA_BASE = Base + 0x100, + TIMER2_VA_BASE = Base + 0x200, + + TIMER_LOAD = 0x00, + TIMER_VALUE = 0x04, + TIMER_CTRL = 0x08, + TIMER_INTCLR = 0x0c, + + TIMER_CTRL_IE = 1 << 5, + TIMER_CTRL_PERIODIC = 1 << 6, + TIMER_CTRL_ENABLE = 1 << 7, + }; +}; + +// ---------------------------------------------------------------------- +IMPLEMENTATION [arm && integrator]: + +#include "config.h" +#include "kip.h" +#include "io.h" + +IMPLEMENT +void Timer::init(unsigned) +{ + /* Switch all timers off */ + Io::write(0, TIMER0_VA_BASE + TIMER_CTRL); + Io::write(0, TIMER1_VA_BASE + TIMER_CTRL); + Io::write(0, TIMER2_VA_BASE + TIMER_CTRL); + + unsigned timer_ctrl = TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC; + unsigned timer_reload = 1000000 / Config::Scheduler_granularity; + + Io::write(timer_reload, TIMER1_VA_BASE + TIMER_LOAD); + Io::write(timer_reload, TIMER1_VA_BASE + TIMER_VALUE); + Io::write(timer_ctrl | TIMER_CTRL_IE, TIMER1_VA_BASE + TIMER_CTRL); +} + +static inline +Unsigned64 +Timer::timer_to_us(Unsigned32 /*cr*/) +{ return 0; } + +static inline +Unsigned64 +Timer::us_to_timer(Unsigned64 us) +{ (void)us; return 0; } + +PUBLIC static inline NEEDS["io.h"] +void +Timer::acknowledge() +{ + Io::write(1, TIMER1_VA_BASE + TIMER_INTCLR); +} + +IMPLEMENT inline +void +Timer::update_one_shot(Unsigned64 wakeup) +{ + (void)wakeup; +} + +IMPLEMENT inline NEEDS["kip.h"] +Unsigned64 +Timer::system_clock() +{ + if (Config::Scheduler_one_shot) + //return Kip::k()->clock + timer_to_us(Io::read(OSCR)); + return 0; + else + return Kip::k()->clock; +} + diff --git a/kernel/fiasco/src/kern/arm/bsp/integrator/uart-arm-integrator.cpp b/kernel/fiasco/src/kern/arm/bsp/integrator/uart-arm-integrator.cpp new file mode 100644 index 00000000..78a837bd --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/integrator/uart-arm-integrator.cpp @@ -0,0 +1,14 @@ +IMPLEMENTATION [integrator]: + +#include "uart_pl011.h" +#include "mem_layout.h" + +IMPLEMENT Address Uart::base() const { return Mem_layout::Uart_base; } + +IMPLEMENT int Uart::irq() const { return 1; } + +IMPLEMENT L4::Uart *Uart::uart() +{ + static L4::Uart_pl011 uart; + return &uart; +} diff --git a/kernel/fiasco/src/kern/arm/bsp/kirkwood/Kconfig b/kernel/fiasco/src/kern/arm/bsp/kirkwood/Kconfig new file mode 100644 index 00000000..d74bf7e1 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/kirkwood/Kconfig @@ -0,0 +1,4 @@ +# PF: KIRKWOOD +# PFDESCR: Marvell Kirkwood platform +# PFCAN: CAN_ARM_CPU_926 +# PFDEPENDS: ARM diff --git a/kernel/fiasco/src/kern/arm/bsp/kirkwood/Modules b/kernel/fiasco/src/kern/arm/bsp/kirkwood/Modules new file mode 100644 index 00000000..8dfab3e2 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/kirkwood/Modules @@ -0,0 +1,15 @@ +# vim:set ft=make: + +PREPROCESS_PARTS += kirkwood 16550 generic_tickless_idle +CONFIG_KERNEL_LOAD_ADDR := 0x0 + +uart_IMPL += uart-16550 uart-16550-arm-kirkwood +config_IMPL += config-arm-kirkwood +mem_layout_IMPL += mem_layout-arm-kirkwood +pic_IMPL += pic-arm-kirkwood +bootstrap_IMPL += bootstrap-arm-kirkwood +timer_IMPL += timer-arm-kirkwood +timer_tick_IMPL += timer_tick-single-vector +kernel_uart_IMPL += kernel_uart-arm-kirkwood +reset_IMPL += reset-arm-kirkwood +clock_IMPL += clock-generic diff --git a/kernel/fiasco/src/kern/arm/bsp/kirkwood/bootstrap-arm-kirkwood.cpp b/kernel/fiasco/src/kern/arm/bsp/kirkwood/bootstrap-arm-kirkwood.cpp new file mode 100644 index 00000000..56b53dd1 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/kirkwood/bootstrap-arm-kirkwood.cpp @@ -0,0 +1,14 @@ +INTERFACE [arm && kirkwood]: + +#include "mem_layout.h" + +enum { Cache_flush_area = 0, }; + +//----------------------------------------------------------------------------- +IMPLEMENTATION [arm && kirkwood]: + +void +map_hw(void *pd) +{ + map_1mb(pd, Mem_layout::Devices0_map_base, Mem_layout::Devices0_phys_base, false, false); +} diff --git a/kernel/fiasco/src/kern/arm/bsp/kirkwood/config-arm-kirkwood.cpp b/kernel/fiasco/src/kern/arm/bsp/kirkwood/config-arm-kirkwood.cpp new file mode 100644 index 00000000..9ec02100 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/kirkwood/config-arm-kirkwood.cpp @@ -0,0 +1,3 @@ +INTERFACE[arm && kirkwood]: + +#define TARGET_NAME "Marvell Kirkwood" diff --git a/kernel/fiasco/src/kern/arm/bsp/kirkwood/kernel_uart-arm-kirkwood.cpp b/kernel/fiasco/src/kern/arm/bsp/kirkwood/kernel_uart-arm-kirkwood.cpp new file mode 100644 index 00000000..8796e234 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/kirkwood/kernel_uart-arm-kirkwood.cpp @@ -0,0 +1,14 @@ +INTERFACE: + +// On ARM the MMIO for the uart is accessible before the MMU is fully up +EXTENSION class Kernel_uart { enum { Bsp_init_mode = Init_before_mmu }; }; + +IMPLEMENTATION [arm && kirkwood && serial]: + +#include "mem_layout.h" + +IMPLEMENT +bool Kernel_uart::startup(unsigned port, int /*irq*/) +{ + return Uart::startup(Mem_layout::Uart_base, 33); +} diff --git a/kernel/fiasco/src/kern/arm/bsp/kirkwood/mem_layout-arm-kirkwood.cpp b/kernel/fiasco/src/kern/arm/bsp/kirkwood/mem_layout-arm-kirkwood.cpp new file mode 100644 index 00000000..b8caafd8 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/kirkwood/mem_layout-arm-kirkwood.cpp @@ -0,0 +1,23 @@ +INTERFACE [arm && kirkwood]: + +EXTENSION class Mem_layout +{ +public: + enum Virt_layout_kirkwood + { + Devices0_map_base = Registers_map_start, + Devices1_map_base = Registers_map_start + 0x00100000, + Devices2_map_base = Registers_map_start + 0x00200000, + + Uart_base = Devices0_map_base + 0x00012000, + Reset_map_base = Devices0_map_base, + Timer_map_base = Devices0_map_base, + Pic_map_base = Devices0_map_base, + }; + + enum Phys_layout_kirkwood + { + Devices0_phys_base = 0xf1000000, + Sdram_phys_base = 0x0, + }; +}; diff --git a/kernel/fiasco/src/kern/arm/bsp/kirkwood/pic-arm-kirkwood.cpp b/kernel/fiasco/src/kern/arm/bsp/kirkwood/pic-arm-kirkwood.cpp new file mode 100644 index 00000000..3ce54326 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/kirkwood/pic-arm-kirkwood.cpp @@ -0,0 +1,129 @@ +INTERFACE [arm && kirkwood]: + +#include "kmem.h" + +class Irq_base; + +EXTENSION class Pic +{ +public: + enum + { + Main_Irq_cause_low_reg = Mem_layout::Pic_map_base + 0x20200, + Main_Irq_mask_low_reg = Mem_layout::Pic_map_base + 0x20204, + Main_Fiq_mask_low_reg = Mem_layout::Pic_map_base + 0x20208, + Endpoint_irq_mask_low_reg = Mem_layout::Pic_map_base + 0x2020c, + Main_Irq_cause_high_reg = Mem_layout::Pic_map_base + 0x20210, + Main_Irq_mask_high_reg = Mem_layout::Pic_map_base + 0x20214, + Main_Fiq_mask_high_reg = Mem_layout::Pic_map_base + 0x20218, + Endpoint_irq_mask_high_reg = Mem_layout::Pic_map_base + 0x2021c, + + Bridge_int_num = 1, + }; +}; + +//------------------------------------------------------------------- +IMPLEMENTATION [arm && kirkwood]: + +#include "config.h" +#include "initcalls.h" +#include "io.h" +#include "irq_chip_generic.h" +#include "irq_mgr.h" + +class Irq_chip_kirkwood : public Irq_chip_gen +{ +public: + Irq_chip_kirkwood() : Irq_chip_gen(64) {} + unsigned set_mode(Mword, unsigned) { return Irq_base::Trigger_level; } + void set_cpu(Mword, unsigned) {} + void ack(Mword) { /* ack is empty */ } +}; + +PUBLIC +void +Irq_chip_kirkwood::mask(Mword irq) +{ + assert (cpu_lock.test()); + Io::clear(1 << (irq & 0x1f), + Pic::Main_Irq_mask_low_reg + ((irq & 0x20) >> 1)); +} + +PUBLIC +void +Irq_chip_kirkwood::mask_and_ack(Mword irq) +{ + assert(cpu_lock.test()); + mask(irq); + // ack is empty +} + +PUBLIC +void +Irq_chip_kirkwood::unmask(Mword irq) +{ + assert(cpu_lock.test()); + Io::set(1 << (irq & 0x1f), + Pic::Main_Irq_mask_low_reg + ((irq & 0x20) >> 1)); +} + +static Static_object > mgr; + +IMPLEMENT FIASCO_INIT +void Pic::init() +{ + Irq_mgr::mgr = mgr.construct(); + + // Disable all interrupts + Io::write(0U, Main_Irq_mask_low_reg); + Io::write(0U, Main_Fiq_mask_low_reg); + Io::write(0U, Main_Irq_mask_high_reg); + Io::write(0U, Main_Fiq_mask_high_reg); + + // enable bridge (chain) IRQ + Io::set(1 << Bridge_int_num, Main_Irq_mask_low_reg); +} + +IMPLEMENT inline +Pic::Status Pic::disable_all_save() +{ return 0; } + +IMPLEMENT inline +void Pic::restore_all(Status) +{} + +PUBLIC static inline NEEDS["io.h"] +Unsigned32 Irq_chip_kirkwood::pending() +{ + Unsigned32 v; + + v = Io::read(Pic::Main_Irq_cause_low_reg); + if (v & 1) + { + v = Io::read(Pic::Main_Irq_cause_high_reg); + for (int i = 1; i < 32; ++i) + if ((1 << i) & v) + return 32 + i; + } + for (int i = 1; i < 32; ++i) + if ((1 << i) & v) + return i; + + return 64; +} + +extern "C" +void irq_handler() +{ + Unsigned32 i; + while ((i = Irq_chip_kirkwood::pending()) < 64) + mgr->c.handle_irq(i, 0); +} + +//--------------------------------------------------------------------------- +IMPLEMENTATION [debug && kirkwood]: + +PUBLIC +char const * +Irq_chip_kirkwood::chip_type() const +{ return "HW Kirkwood IRQ"; } diff --git a/kernel/fiasco/src/kern/arm/bsp/kirkwood/reset-arm-kirkwood.cpp b/kernel/fiasco/src/kern/arm/bsp/kirkwood/reset-arm-kirkwood.cpp new file mode 100644 index 00000000..884b62fb --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/kirkwood/reset-arm-kirkwood.cpp @@ -0,0 +1,30 @@ +IMPLEMENTATION [arm && kirkwood]: + +#include "io.h" +#include "kmem.h" + +class Kirkwood_reset +{ +public: + enum + { + Mask_reg = Mem_layout::Reset_map_base + 0x20108, + Soft_reset_reg = Mem_layout::Reset_map_base + 0x2010c, + }; +}; + +// ------------------------------------------------------------------------ +IMPLEMENTATION [arm && kirkwood]: + +void __attribute__ ((noreturn)) +platform_reset(void) +{ + // enable software reset + Io::write(1 << 2, Kirkwood_reset::Mask_reg); + + // do software reset + Io::write(1, Kirkwood_reset::Soft_reset_reg); + + for (;;) + ; +} diff --git a/kernel/fiasco/src/kern/arm/bsp/kirkwood/timer-arm-kirkwood.cpp b/kernel/fiasco/src/kern/arm/bsp/kirkwood/timer-arm-kirkwood.cpp new file mode 100644 index 00000000..bda558af --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/kirkwood/timer-arm-kirkwood.cpp @@ -0,0 +1,84 @@ +// -------------------------------------------------------------------------- +INTERFACE [arm && kirkwood]: + +#include "kmem.h" + +EXTENSION class Timer +{ +public: + static unsigned irq() { return 1; } + +private: + enum { + Control_Reg = Mem_layout::Reset_map_base + 0x20300, + Reload0_Reg = Mem_layout::Reset_map_base + 0x20310, + Timer0_Reg = Mem_layout::Reset_map_base + 0x20314, + Reload1_Reg = Mem_layout::Reset_map_base + 0x20318, + Timer1_Reg = Mem_layout::Reset_map_base + 0x2031c, + + Bridge_cause = Mem_layout::Reset_map_base + 0x20110, + Bridge_mask = Mem_layout::Reset_map_base + 0x20114, + + Timer0_enable = 1 << 0, + Timer0_auto = 1 << 1, + + Timer0_bridge_num = 1 << 1, + Timer1_bridge_num = 1 << 2, + + Reload_value = 200000, + }; +}; + +// ---------------------------------------------------------------------- +IMPLEMENTATION [arm && kirkwood]: + +#include "config.h" +#include "kip.h" +#include "io.h" + +IMPLEMENT +void Timer::init(unsigned) +{ + // Disable timer + Io::write(0, Control_Reg); + + // Set current timer value and reload value + Io::write(Reload_value, Timer0_Reg); + Io::write(Reload_value, Reload0_Reg); + + Io::set(Timer0_enable | Timer0_auto, Control_Reg); + + Io::set(Timer0_bridge_num, Bridge_mask); +} + +static inline +Unsigned64 +Timer::timer_to_us(Unsigned32 /*cr*/) +{ return 0; } + +static inline +Unsigned64 +Timer::us_to_timer(Unsigned64 us) +{ (void)us; return 0; } + +PUBLIC static inline NEEDS["io.h"] +void +Timer::acknowledge() +{ + Io::clear(Timer0_bridge_num, Bridge_cause); +} + +IMPLEMENT inline +void +Timer::update_one_shot(Unsigned64 /*wakeup*/) +{ +} + +IMPLEMENT inline NEEDS["config.h", "kip.h"] +Unsigned64 +Timer::system_clock() +{ + if (Config::Scheduler_one_shot) + return 0; + return Kip::k()->clock; +} diff --git a/kernel/fiasco/src/kern/arm/bsp/kirkwood/uart-16550-arm-kirkwood.cpp b/kernel/fiasco/src/kern/arm/bsp/kirkwood/uart-16550-arm-kirkwood.cpp new file mode 100644 index 00000000..1dc7fcc6 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/kirkwood/uart-16550-arm-kirkwood.cpp @@ -0,0 +1,20 @@ +INTERFACE [16550 && kirkwood]: + +EXTENSION class Uart +{ +public: + enum { + Base_rate = 200000000 / 16, + Base_ier_bits = 1 << 6, + + Access_shift = 2, + }; +}; + +IMPLEMENTATION [16550 && kirkwood]: + +IMPLEMENT inline NEEDS[Uart::mcr, Uart::ier] +void Uart::enable_rcv_irq() +{ + ier(ier() | 1); +} diff --git a/kernel/fiasco/src/kern/arm/bsp/omap3/Kconfig b/kernel/fiasco/src/kern/arm/bsp/omap3/Kconfig new file mode 100644 index 00000000..af74ed8a --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/omap3/Kconfig @@ -0,0 +1,37 @@ +# PF: OMAP +# PFDESCR: TI OMAP +# PFDEPENDS: ARM + +choice + prompt "OMAP Platform" + default PF_OMAP3_EVM + +config PF_OMAP3_OMAP35XEVM + bool "TI OMAP35xEVM" + depends on PF_OMAP + select CAN_ARM_CPU_CORTEX_A8 + help + Choose for OMAP35xEVM platform. + +config PF_OMAP3_BEAGLEBOARD + bool "Beagle Board" + depends on PF_OMAP + select CAN_ARM_CPU_CORTEX_A8 + help + Choose for Beagleboard. + +config PF_OMAP3_AM33XX + bool "TI AM33xx" + depends on PF_OMAP + select CAN_ARM_CPU_CORTEX_A8 + help + Choose for AM33xx platforms (e.g. Beaglebone). + +config PF_OMAP4_PANDABOARD + bool "Pandaboard" + depends on PF_OMAP + select CAN_ARM_CPU_CORTEX_A9 + help + Choose for Pandaboard. + +endchoice diff --git a/kernel/fiasco/src/kern/arm/bsp/omap3/Modules b/kernel/fiasco/src/kern/arm/bsp/omap3/Modules new file mode 100644 index 00000000..e320c7c9 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/omap3/Modules @@ -0,0 +1,26 @@ +# vim:set ft=make: + +SUBSYSTEMS += LIBUART +OBJECTS_LIBUART += uart_omap35x.o +PREPROCESS_PARTS += omap libuart generic_tickless_idle +PREPROCESS_PARTS += $(if $(CONFIG_PF_OMAP3_OMAP35XEVM),omap3 omap3_35x omap3_35xevm) +PREPROCESS_PARTS += $(if $(CONFIG_PF_OMAP3_BEAGLEBOARD),omap3 omap3_35x omap3_beagleboard) +PREPROCESS_PARTS += $(if $(CONFIG_PF_OMAP3_AM33XX),omap3 omap3_am33xx) +PREPROCESS_PARTS += $(if $(CONFIG_PF_OMAP4_PANDABOARD),omap4 mptimer pic_gic omap4_pandaboard) +CONFIG_KERNEL_LOAD_ADDR := 0x80000000 +MPCORE_PHYS_BASE := 0x48240000 + +INTERFACES_KERNEL += $(if $(CONFIG_MP),boot_mp) +INTERFACES_KERNEL += $(if $(CONFIG_PF_OMAP4_PANDABOARD),gic) + +uart_IMPL += uart-arm-omap +config_IMPL += config-arm-omap +mem_layout_IMPL += mem_layout-arm-omap +pic_IMPL += $(if $(CONFIG_PF_OMAP4_PANDABOARD),pic-gic pic-arm-gic-omap4,pic-arm-omap3) +bootstrap_IMPL += bootstrap-arm-omap +timer_IMPL += $(if $(CONFIG_PF_OMAP4_PANDABOARD),timer-arm-mptimer timer-arm-mptimer-omap4,timer-arm-omap3) +timer_tick_IMPL += timer_tick-single-vector +kernel_uart_IMPL += kernel_uart-arm-omap +reset_IMPL += reset-arm-omap +clock_IMPL += clock-generic +boot_mp_IMPL += boot_mp-arm-omap4 diff --git a/kernel/fiasco/src/kern/arm/bsp/omap3/boot_mp-arm-omap4.cpp b/kernel/fiasco/src/kern/arm/bsp/omap3/boot_mp-arm-omap4.cpp new file mode 100644 index 00000000..e3cf796c --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/omap3/boot_mp-arm-omap4.cpp @@ -0,0 +1,60 @@ +INTERFACE [arm && mp && omap4]: + +#include "types.h" + +class Boot_mp +{ +}; + +IMPLEMENTATION [arm && mp && omap4]: + +#include "io.h" +#include "kmem.h" + +PRIVATE +void +Boot_mp::aux(unsigned cmd, Mword arg0, Mword arg1) +{ + register unsigned long r0 asm("r0") = arg0; + register unsigned long r1 asm("r1") = arg1; + register unsigned long r12 asm("r12") = cmd; + + asm volatile("dsb; smc #0" + : : "r" (r0), "r" (r1), "r" (r12) + : "r2", "r3", "r4", "r5", "r6", + "r7", "r8", "r9", "r10", "r11", "lr", "memory"); +} + +PUBLIC +void +Boot_mp::start_ap_cpus(Address phys_tramp_mp_addr) +{ + // two possibilities available, the memory mapped only in later board + // revisions + if (1) + { + enum { + AUX_CORE_BOOT_0 = 0x104, + AUX_CORE_BOOT_1 = 0x105, + }; + aux(AUX_CORE_BOOT_1, phys_tramp_mp_addr, 0); + asm volatile("dsb; sev" : : : "memory"); + aux(AUX_CORE_BOOT_0, 0x200, 0xfffffdff); + } + else + { + enum { + AUX_CORE_BOOT_0 = Kmem::Devices2_map_base + 0x81800, + AUX_CORE_BOOT_1 = Kmem::Devices2_map_base + 0x81804, + }; + Io::write(phys_tramp_mp_addr, AUX_CORE_BOOT_1); + asm volatile("dsb; sev" : : : "memory"); + Io::write((Io::read(AUX_CORE_BOOT_0) & ~0xfffffdff) | 0x200, + AUX_CORE_BOOT_0); + } +} + +PUBLIC +void +Boot_mp::cleanup() +{} diff --git a/kernel/fiasco/src/kern/arm/bsp/omap3/bootstrap-arm-omap.cpp b/kernel/fiasco/src/kern/arm/bsp/omap3/bootstrap-arm-omap.cpp new file mode 100644 index 00000000..403f86e8 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/omap3/bootstrap-arm-omap.cpp @@ -0,0 +1,21 @@ +INTERFACE [arm && omap]: + +enum { + Cache_flush_area = 0, +}; + +//----------------------------------------------------------------------------- +IMPLEMENTATION [arm && omap]: + +#include "mem_layout.h" +#include "io.h" + +void +map_hw(void *pd) +{ + // map devices + map_1mb(pd, Mem_layout::Devices1_map_base, Mem_layout::Devices1_phys_base, false, false); + map_1mb(pd, Mem_layout::Devices2_map_base, Mem_layout::Devices2_phys_base, false, false); + map_1mb(pd, Mem_layout::Devices3_map_base, Mem_layout::Devices3_phys_base, false, false); + map_1mb(pd, Mem_layout::Devices4_map_base, Mem_layout::Devices4_phys_base, false, false); +} diff --git a/kernel/fiasco/src/kern/arm/bsp/omap3/config-arm-omap.cpp b/kernel/fiasco/src/kern/arm/bsp/omap3/config-arm-omap.cpp new file mode 100644 index 00000000..0a24f732 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/omap3/config-arm-omap.cpp @@ -0,0 +1,11 @@ +INTERFACE[arm && omap3_35xevm]: //----------------------------------------- +#define TARGET_NAME "OMAP35xEVM" + +INTERFACE[arm && omap3_beagleboard]: //------------------------------------ +#define TARGET_NAME "Beagleboard" + +INTERFACE[arm && omap3_am33xx]: //----------------------------------------- +#define TARGET_NAME "AM33xx" + +INTERFACE[arm && omap4_pandaboard]: //------------------------------------- +#define TARGET_NAME "Pandaboard" diff --git a/kernel/fiasco/src/kern/arm/bsp/omap3/kernel_uart-arm-omap.cpp b/kernel/fiasco/src/kern/arm/bsp/omap3/kernel_uart-arm-omap.cpp new file mode 100644 index 00000000..6d834e56 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/omap3/kernel_uart-arm-omap.cpp @@ -0,0 +1,12 @@ +INTERFACE: + +// On ARM the MMIO for the uart is accessible before the MMU is fully up +EXTENSION class Kernel_uart { enum { Bsp_init_mode = Init_before_mmu }; }; + +IMPLEMENTATION [arm && omap && serial]: + +IMPLEMENT +bool Kernel_uart::startup(unsigned, int) +{ + return Uart::startup(); +} diff --git a/kernel/fiasco/src/kern/arm/bsp/omap3/mem_layout-arm-omap.cpp b/kernel/fiasco/src/kern/arm/bsp/omap3/mem_layout-arm-omap.cpp new file mode 100644 index 00000000..202fc5ff --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/omap3/mem_layout-arm-omap.cpp @@ -0,0 +1,115 @@ +INTERFACE [arm && omap3_35x]: //------------------------------------------- + +EXTENSION class Mem_layout +{ +public: + enum Virt_layout_omap3_35x { + Devices1_map_base = Registers_map_start, + L4_addr_prot_map_base = Devices1_map_base + 0x00040000, + Uart1_map_base = Devices1_map_base + 0x0006a000, + Gptimer10_map_base = Devices1_map_base + 0x00086000, + Wkup_cm_map_base = Devices1_map_base + 0x00004c00, + + Devices2_map_base = Registers_map_start + 0x00100000, + Intc_map_base = Devices2_map_base + 0x0, + + Devices3_map_base = Registers_map_start + 0x00200000, + Timer1ms_map_base = Devices3_map_base + 0x00018000, + Prm_global_reg_map_base = Devices3_map_base + 0x00007200, + + Devices4_map_base = Registers_map_start + 0x00300000, + Uart3_map_base = Devices4_map_base + 0x00020000, + }; + + enum Phys_layout_omap3_35x { + Devices1_phys_base = 0x48000000, + Devices2_phys_base = 0x48200000, + Devices3_phys_base = 0x48300000, + Devices4_phys_base = 0x49000000, + Sdram_phys_base = 0x80000000, + Flush_area_phys_base = 0xe0000000, + }; +}; + +INTERFACE [arm && omap3_35xevm]: //---------------------------------------- + +EXTENSION class Mem_layout +{ +public: + enum Virt_layout_omap3_35xevm { + Uart_base = Uart1_map_base, + }; +}; + +INTERFACE [arm && omap3_beagleboard]: //----------------------------------- + +EXTENSION class Mem_layout +{ +public: + enum Virt_layout_omap3_beagleboard { + Uart_base = Uart3_map_base, + }; +}; + +INTERFACE [arm && omap3_am33xx]: //---------------------------------------- + +EXTENSION class Mem_layout +{ +public: + enum Virt_layout_omap3_335x { + Devices1_map_base = Registers_map_start, + Devices2_map_base = Registers_map_start + 0x00100000, + Devices3_map_base = Registers_map_start + 0x00200000, + Devices4_map_base = Registers_map_start + 0x00300000, + + Cm_per_map_base = Devices1_map_base + 0x00000000, + Cm_wkup_map_base = Devices1_map_base + 0x00000400, + Cm_dpll_map_base = Devices1_map_base + 0x00000500, + Timergen_map_base = Devices1_map_base + 0x00005000, // DMTIMER0 + Timer1ms_map_base = Devices1_map_base + 0x00031000, + Uart1_map_base = Devices1_map_base + 0x00009000, + Prm_global_reg_map_base = Devices3_map_base + 0x00007200, + Intc_map_base = Devices4_map_base + 0x0, + Uart_base = Uart1_map_base, + }; + + enum Phys_layout_omap3_335x { + Devices1_phys_base = 0x44e00000, + Devices2_phys_base = 0x48000000, + Devices3_phys_base = 0x48100000, + Devices4_phys_base = 0x48200000, + Sdram_phys_base = 0x80000000, + Flush_area_phys_base = 0xe0000000, + }; +}; + +INTERFACE [arm && omap4]: //----------------------------------------------- + +EXTENSION class Mem_layout +{ +public: + enum Phys_layout_omap4 { + Devices1_phys_base = 0x48000000, + Devices2_phys_base = 0x48200000, + Devices3_phys_base = 0x4a300000, + Devices4_phys_base = 0x49000000, + Sdram_phys_base = 0x80000000, + }; + + enum Virt_layout_omap4_pandaboard { + Devices1_map_base = Registers_map_start, + Devices2_map_base = Registers_map_start + 0x00100000, + Devices3_map_base = Registers_map_start + 0x00200000, + Devices4_map_base = Registers_map_start + 0x00300000, + + Uart_base = Devices1_map_base + 0x20000, + Mp_scu_map_base = Devices2_map_base + 0x40000, + Gic_cpu_map_base = Devices2_map_base + 0x40100, + Gic_dist_map_base = Devices2_map_base + 0x41000, + + __Timer = Devices2_map_base + 0x40600, + __PL310 = Devices2_map_base + 0x42000, + + Prm_map_base = Devices3_map_base + 0x6000, + }; +}; diff --git a/kernel/fiasco/src/kern/arm/bsp/omap3/pic-arm-gic-omap4.cpp b/kernel/fiasco/src/kern/arm/bsp/omap3/pic-arm-gic-omap4.cpp new file mode 100644 index 00000000..a69bf612 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/omap3/pic-arm-gic-omap4.cpp @@ -0,0 +1,40 @@ +INTERFACE [arm && pic_gic && omap4]: + +#include "gic.h" + +// ------------------------------------------------------------------------ +IMPLEMENTATION [arm && pic_gic && omap4]: + +#include "irq_mgr_multi_chip.h" +#include "kmem.h" + +IMPLEMENT FIASCO_INIT +void +Pic::init() +{ + typedef Irq_mgr_multi_chip<8> M; + + M *m = new Boot_object(16); + + gic.construct(Kmem::Gic_cpu_map_base, Kmem::Gic_dist_map_base); + m->add_chip(0, gic, gic->nr_irqs()); + + Irq_mgr::mgr = m; +} + +IMPLEMENT inline +Pic::Status Pic::disable_all_save() +{ return 0; } + +IMPLEMENT inline +void Pic::restore_all(Status) +{} + +// ------------------------------------------------------------------------ +IMPLEMENTATION [arm && mp && pic_gic && omap4]: + +PUBLIC static +void Pic::init_ap() +{ + gic->init_ap(); +} diff --git a/kernel/fiasco/src/kern/arm/bsp/omap3/pic-arm-omap3.cpp b/kernel/fiasco/src/kern/arm/bsp/omap3/pic-arm-omap3.cpp new file mode 100644 index 00000000..b575a9e0 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/omap3/pic-arm-omap3.cpp @@ -0,0 +1,155 @@ +INTERFACE [arm && omap3]: + +#include "kmem.h" + +class Irq_base; + +EXTENSION class Pic +{ +public: + enum + { + INTCPS_SYSCONFIG = Kmem::Intc_map_base + 0x010, + INTCPS_SYSSTATUS = Kmem::Intc_map_base + 0x014, + INTCPS_CONTROL = Kmem::Intc_map_base + 0x048, + INTCPS_TRESHOLD = Kmem::Intc_map_base + 0x068, + INTCPS_ITRn_base = Kmem::Intc_map_base + 0x080, + INTCPS_MIRn_base = Kmem::Intc_map_base + 0x084, + INTCPS_MIR_CLEARn_base = Kmem::Intc_map_base + 0x088, + INTCPS_MIR_SETn_base = Kmem::Intc_map_base + 0x08c, + INTCPS_ISR_SETn_base = Kmem::Intc_map_base + 0x090, + INTCPS_ISR_CLEARn_base = Kmem::Intc_map_base + 0x094, + INTCPS_PENDING_IRQn_base = Kmem::Intc_map_base + 0x098, + INTCPS_ILRm_base = Kmem::Intc_map_base + 0x100, + }; +}; + +INTERFACE [arm && omap3_35x]: //------------------------------------------- + +EXTENSION class Pic +{ +public: + enum { Num_irqs = 96, }; +}; + +INTERFACE [arm && omap3_am33xx]: //---------------------------------------- + +EXTENSION class Pic +{ +public: + enum { Num_irqs = 128, }; +}; + +//------------------------------------------------------------------------- +IMPLEMENTATION [arm && omap3]: + +#include "config.h" +#include "io.h" +#include "irq_chip_generic.h" +#include "irq_mgr.h" + +class Irq_chip_arm_omap3 : public Irq_chip_gen +{ +public: + Irq_chip_arm_omap3() : Irq_chip_gen(Pic::Num_irqs) {} + unsigned set_mode(Mword, unsigned) { return Irq_base::Trigger_level; } + void set_cpu(Mword, unsigned) {} +}; + +PUBLIC +void +Irq_chip_arm_omap3::mask(Mword irq) +{ + assert(cpu_lock.test()); + Io::write(1 << (irq & 31), Pic::INTCPS_MIR_SETn_base + (irq & 0xe0)); +} + +PUBLIC +void +Irq_chip_arm_omap3::mask_and_ack(Mword irq) +{ + assert(cpu_lock.test()); + Io::write(1 << (irq & 31), Pic::INTCPS_MIR_SETn_base + (irq & 0xe0)); + Io::write(1, Pic::INTCPS_CONTROL); +} + +PUBLIC +void +Irq_chip_arm_omap3::ack(Mword irq) +{ + (void)irq; + Io::write(1, Pic::INTCPS_CONTROL); +} + +PUBLIC +void +Irq_chip_arm_omap3::unmask(Mword irq) +{ + assert(cpu_lock.test()); + Io::write(1 << (irq & 31), Pic::INTCPS_MIR_CLEARn_base + (irq & 0xe0)); +} + +static Static_object > mgr; + +IMPLEMENT FIASCO_INIT +void Pic::init() +{ + // Reset + Io::write(2, INTCPS_SYSCONFIG); + while (!Io::read(INTCPS_SYSSTATUS)) + ; + + // auto-idle + Io::write(1, INTCPS_SYSCONFIG); + + // disable treshold + Io::write(0xff, INTCPS_TRESHOLD); + + // set priority for each interrupt line, lets take 0x20 + // setting bit0 to 0 means IRQ (1 would mean FIQ) + for (int m = 0; m < Num_irqs; ++m) + Io::write(0x20 << 2, INTCPS_ILRm_base + (4 * m)); + + // mask all interrupts + for (int n = 0; n < 3; ++n) + Io::write(0xffffffff, INTCPS_MIR_SETn_base + 0x20 * n); + + Irq_mgr::mgr = mgr.construct(); +} + +IMPLEMENT inline +Pic::Status Pic::disable_all_save() +{ return 0; } + +IMPLEMENT inline +void Pic::restore_all(Status) +{} + +PUBLIC static inline NEEDS["io.h"] +Unsigned32 Irq_chip_arm_omap3::pending() +{ + for (int n = 0; n < (Pic::Num_irqs >> 5); ++n) + { + unsigned long x = Io::read(Pic::INTCPS_PENDING_IRQn_base + 0x20 * n); + for (int i = 0; i < 32; ++i) + if (x & (1 << i)) + return i + n * 32; + } + return 0; +} + +extern "C" +void irq_handler() +{ + Unsigned32 i; + while ((i = Irq_chip_arm_omap3::pending())) + mgr->c.handle_irq(i, 0); +} + +//--------------------------------------------------------------------------- +IMPLEMENTATION [debug && omap3]: + +PUBLIC +char const * +Irq_chip_arm_omap3::chip_type() const +{ return "HW OMAP3 IRQ"; } diff --git a/kernel/fiasco/src/kern/arm/bsp/omap3/reset-arm-omap.cpp b/kernel/fiasco/src/kern/arm/bsp/omap3/reset-arm-omap.cpp new file mode 100644 index 00000000..8d3ed70c --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/omap3/reset-arm-omap.cpp @@ -0,0 +1,54 @@ +IMPLEMENTATION [arm && omap3_35x]: //-------------------------------------- + +#include "io.h" +#include "kmem.h" + +void __attribute__ ((noreturn)) +platform_reset(void) +{ + enum + { + PRM_RSTCTRL = Kmem::Prm_global_reg_map_base + 0x50, + }; + + Io::write(2, PRM_RSTCTRL); + + for (;;) + ; +} + +IMPLEMENTATION [arm && omap3_am33xx]: //----------------------------------- + +#include "io.h" +#include "kmem.h" + +void __attribute__ ((noreturn)) +platform_reset(void) +{ + enum { PRM_RSTCTRL = Kmem::Devices1_map_base + 0xF00, }; + + Io::write(1, PRM_RSTCTRL); + + for (;;) + ; +} + +IMPLEMENTATION [arm && omap4]: //------------------------------------------ + +#include "io.h" +#include "kmem.h" + +void __attribute__ ((noreturn)) +platform_reset(void) +{ + enum + { + DEVICE_PRM = Kmem::Prm_map_base + 0x1b00, + PRM_RSTCTRL = DEVICE_PRM + 0, + }; + + Io::write(1, PRM_RSTCTRL); + + for (;;) + ; +} diff --git a/kernel/fiasco/src/kern/arm/bsp/omap3/timer-arm-mptimer-omap4.cpp b/kernel/fiasco/src/kern/arm/bsp/omap3/timer-arm-mptimer-omap4.cpp new file mode 100644 index 00000000..b721598a --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/omap3/timer-arm-mptimer-omap4.cpp @@ -0,0 +1,8 @@ +// -------------------------------------------------------------------------- +INTERFACE [arm && mptimer && omap4_pandaboard]: + +EXTENSION class Timer +{ +private: + static Mword interval() { return 499999; } +}; diff --git a/kernel/fiasco/src/kern/arm/bsp/omap3/timer-arm-omap3.cpp b/kernel/fiasco/src/kern/arm/bsp/omap3/timer-arm-omap3.cpp new file mode 100644 index 00000000..19857569 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/omap3/timer-arm-omap3.cpp @@ -0,0 +1,285 @@ +INTERFACE [omap3]: // ------------------------------------------------ + +#include "kmem.h" + +class Timer_omap_1mstimer +{ +public: + enum { + TIDR = Kmem::Timer1ms_map_base + 0x000, // IP revision code + TIOCP_CFG = Kmem::Timer1ms_map_base + 0x010, // config + TISTAT = Kmem::Timer1ms_map_base + 0x014, // non-interrupt status + TISR = Kmem::Timer1ms_map_base + 0x018, // pending interrupts + TIER = Kmem::Timer1ms_map_base + 0x01c, // enable/disable of interrupt events + TWER = Kmem::Timer1ms_map_base + 0x020, // wake-up features + TCLR = Kmem::Timer1ms_map_base + 0x024, // optional features + TCRR = Kmem::Timer1ms_map_base + 0x028, // internal counter + TLDR = Kmem::Timer1ms_map_base + 0x02c, // timer load value + TTGR = Kmem::Timer1ms_map_base + 0x030, // trigger reload by writing + TWPS = Kmem::Timer1ms_map_base + 0x034, // write-posted pending + TMAR = Kmem::Timer1ms_map_base + 0x038, // compare value + TCAR1 = Kmem::Timer1ms_map_base + 0x03c, // first capture value of the counter + TCAR2 = Kmem::Timer1ms_map_base + 0x044, // second capture value of the counter + TPIR = Kmem::Timer1ms_map_base + 0x048, // positive inc, gpt1, 2 and 10 only + TNIR = Kmem::Timer1ms_map_base + 0x04C, // negative inc, gpt1, 2 and 10 only + }; +}; + +// -------------------------------------------------------------------------- +INTERFACE [arm && omap3_35x]: + +EXTENSION class Timer +{ +public: + static unsigned irq() { return 37; } + +private: + enum { + CM_CLKSEL_WKUP = Kmem::Wkup_cm_map_base + 0x40, + }; +}; + +INTERFACE [arm && omap3_am33xx]: //---------------------------------------- + +class Timer_omap_gentimer +{ +public: + enum { + TIDR = Kmem::Timergen_map_base + 0x00, // ID + TIOCP_CFG = Kmem::Timergen_map_base + 0x10, // config + EOI = Kmem::Timergen_map_base + 0x20, + IRQSTATUS = Kmem::Timergen_map_base + 0x28, + IRQENABLE_SET = Kmem::Timergen_map_base + 0x2c, + IRQWAKEEN = Kmem::Timergen_map_base + 0x34, + TCLR = Kmem::Timergen_map_base + 0x38, + TCRR = Kmem::Timergen_map_base + 0x3c, + TLDR = Kmem::Timergen_map_base + 0x40, + }; +}; + +EXTENSION class Timer +{ +public: + enum Timer_type { Timer0, Timer1_1ms }; + static Timer_type type() { return Timer1_1ms; } + + static unsigned irq() + { + switch (type()) + { + case Timer0: default: return 66; + case Timer1_1ms: return 67; + } + } + + enum { + CM_WKUP_CLKSTCTRL = Kmem::Cm_wkup_map_base + 0x00, + CM_WKUP_TIMER0_CLKCTRL = Kmem::Cm_wkup_map_base + 0x10, + CM_WKUP_TIMER1_CLKCTRL = Kmem::Cm_wkup_map_base + 0xc4, + CLKSEL_TIMER1MS_CLK = Kmem::Cm_dpll_map_base + 0x28, + + CLKSEL_TIMER1MS_CLK_OSC = 0, + CLKSEL_TIMER1MS_CLK_32KHZ = 1, + CLKSEL_TIMER1MS_CLK_VALUE = CLKSEL_TIMER1MS_CLK_OSC, + }; +}; + +IMPLEMENTATION [omap3]: // ------------------------------------------------ + +PRIVATE static +void +Timer_omap_1mstimer::get_timer_values_32khz(unsigned &reload, int &tpir, int &tnir) +{ + tpir = 232000; + tnir = -768000; + reload = 0xffffffe0; + assert(Config::Scheduler_granularity == 1000); // need to adapt here +} + +IMPLEMENTATION [arm && omap3_35x]: // ------------------------------------- + +PRIVATE static +void +Timer_omap_1mstimer::get_timer_values(unsigned &reload, int &tpir, int &tnir) +{ + get_timer_values_32khz(reload, tpir, tnir); +} + +IMPLEMENTATION [arm && omap3_am33xx]: // ---------------------------------- + +PRIVATE static +void +Timer_omap_1mstimer::get_timer_values(unsigned &reload, int &tpir, int &tnir) +{ + if (Timer::CLKSEL_TIMER1MS_CLK_VALUE == Timer::CLKSEL_TIMER1MS_CLK_32KHZ) + get_timer_values_32khz(reload, tpir, tnir); + else + { + tpir = 100000; + tnir = 0; + reload = ~0 - 24 * Config::Scheduler_granularity + 1; // 24 MHz + } +} + +IMPLEMENTATION [omap3]: // ------------------------------------------------ + +#include "io.h" +#include + +PUBLIC static +void +Timer_omap_1mstimer::init() +{ + // reset + Io::write(1, TIOCP_CFG); + while (!Io::read(TISTAT)) + ; + // reset done + + // overflow mode + Io::write(0x2, TIER); + // no wakeup + Io::write(0x0, TWER); + + // program timer frequency + unsigned val; + int tpir, tnir; + get_timer_values(val, tpir, tnir); + + Io::write(tpir, TPIR); // gpt1, gpt2 and gpt10 only + Io::write(tnir, TNIR); // gpt1, gpt2 and gpt10 only + Io::write(val, TCRR); + Io::write(val, TLDR); + + // auto-reload + enable + Io::write(1 | 2, TCLR); +} + +PUBLIC static inline NEEDS["io.h"] +void +Timer_omap_1mstimer::acknowledge() +{ + Io::write(2, TISR); +} + +IMPLEMENTATION [arm && omap3_am33xx]: // ---------------------------------- + +PUBLIC static +void +Timer_omap_gentimer::init() +{ + // Mword idr = Io::read(TIDR); + // older timer: idr >> 16 == 0 + // newer timer: idr >> 16 != 0 + + // reset + Io::write(1, TIOCP_CFG); + while (Io::read(TIOCP_CFG) & 1) + ; + // reset done + + // overflow mode + Io::write(2, IRQENABLE_SET); + // no wakeup + Io::write(0, IRQWAKEEN); + + // program 1000 Hz timer frequency + // (FFFFFFFFh - TLDR + 1) * timer-clock-period * clock-divider(ps) + Mword val = 0xffffffda; + Io::write(val, TLDR); + Io::write(val, TCRR); + + Io::write(1 | 2, TCLR); +} + +PUBLIC static inline NEEDS["io.h"] +void +Timer_omap_gentimer::acknowledge() +{ + Io::write(2, IRQSTATUS); + Io::write(0, EOI); +} + +// ----------------------------------------------------------------------- +IMPLEMENTATION [arm && omap3_35x]: + +IMPLEMENT +void Timer::init(unsigned) +{ + // select 32768 Hz input to GPTimer1 (timer1 only!) + Io::write(~1 & Io::read(CM_CLKSEL_WKUP), CM_CLKSEL_WKUP); + Timer_omap_1mstimer::init(); +} + +PUBLIC static inline NEEDS[Timer_omap_1mstimer::acknowledge] +void Timer::acknowledge() +{ + Timer_omap_1mstimer::acknowledge(); +} + +// ----------------------------------------------------------------------- +IMPLEMENTATION [arm && omap3_am33xx]: + +IMPLEMENT +void +Timer::init(unsigned) +{ + switch (type()) + { + case Timer1_1ms: + // enable DMTIMER1_1MS + Io::write(2, CM_WKUP_TIMER1_CLKCTRL); + Io::read(CM_WKUP_TIMER1_CLKCTRL); + Io::write(CLKSEL_TIMER1MS_CLK_VALUE, CLKSEL_TIMER1MS_CLK); + for (int i = 0; i < 1000000; ++i) // instead, poll proper reg + asm volatile("" : : : "memory"); + Timer_omap_1mstimer::init(); + break; + case Timer0: + Io::write(2, CM_WKUP_TIMER0_CLKCTRL); + Timer_omap_gentimer::init(); + break; + } +} + +PUBLIC static inline NEEDS[Timer_omap_gentimer::acknowledge] +void Timer::acknowledge() +{ + if (type() == Timer1_1ms) + Timer_omap_1mstimer::acknowledge(); + else + Timer_omap_gentimer::acknowledge(); +} + +// ----------------------------------------------------------------------- +IMPLEMENTATION [arm && omap3]: + +#include "config.h" +#include "kip.h" + +static inline +Unsigned64 +Timer::timer_to_us(Unsigned32 /*cr*/) +{ return 0; } + +static inline +Unsigned64 +Timer::us_to_timer(Unsigned64 us) +{ (void)us; return 0; } + +IMPLEMENT inline +void +Timer::update_one_shot(Unsigned64 wakeup) +{ + (void)wakeup; +} + +IMPLEMENT inline NEEDS["config.h", "kip.h"] +Unsigned64 +Timer::system_clock() +{ + if (Config::Scheduler_one_shot) + return 0; + else + return Kip::k()->clock; +} diff --git a/kernel/fiasco/src/kern/arm/bsp/omap3/uart-arm-omap.cpp b/kernel/fiasco/src/kern/arm/bsp/omap3/uart-arm-omap.cpp new file mode 100644 index 00000000..53e8db3d --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/omap3/uart-arm-omap.cpp @@ -0,0 +1,24 @@ +IMPLEMENTATION [arm && (omap3_35xevm || omap3_am33xx)]: // ---------------- + +IMPLEMENT int Uart::irq() const { return 72; } + +IMPLEMENTATION [arm && omap3_beagleboard]: // ----------------------------- + +IMPLEMENT int Uart::irq() const { return 74; } + +IMPLEMENTATION [arm && omap4_pandaboard]: // ------------------------------ + +IMPLEMENT int Uart::irq() const { return 32 + 74; } + +IMPLEMENTATION: // -------------------------------------------------------- + +#include "mem_layout.h" +#include "uart_omap35x.h" + +IMPLEMENT Address Uart::base() const { return Mem_layout::Uart_base; } + +IMPLEMENT L4::Uart *Uart::uart() +{ + static L4::Uart_omap35x uart; + return &uart; +} diff --git a/kernel/fiasco/src/kern/arm/bsp/pxa-sa/config-arm-pxa_sa1100.cpp b/kernel/fiasco/src/kern/arm/bsp/pxa-sa/config-arm-pxa_sa1100.cpp new file mode 100644 index 00000000..3ab8384b --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/pxa-sa/config-arm-pxa_sa1100.cpp @@ -0,0 +1,5 @@ +INTERFACE[arm && pxa]: +#define TARGET_NAME "XScale" + +INTERFACE[arm && sa1100]: +#define TARGET_NAME "StrongARM" diff --git a/kernel/fiasco/src/kern/arm/bsp/pxa-sa/pic-arm-pxa_sa1100.cpp b/kernel/fiasco/src/kern/arm/bsp/pxa-sa/pic-arm-pxa_sa1100.cpp new file mode 100644 index 00000000..f01396bc --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/pxa-sa/pic-arm-pxa_sa1100.cpp @@ -0,0 +1,126 @@ +INTERFACE [arm && pxa]: // ------------------------------------- + +#include "kmem.h" + +EXTENSION class Pic +{ +public: + enum { + ICIP = Kmem::Pic_map_base + 0x000000, + ICMR = Kmem::Pic_map_base + 0x000004, + ICLR = Kmem::Pic_map_base + 0x000008, + ICCR = Kmem::Pic_map_base + 0x000014, + ICFP = Kmem::Pic_map_base + 0x00000c, + ICPR = Kmem::Pic_map_base + 0x000010, + }; +}; + +INTERFACE [arm && sa1100]: // ---------------------------------- + +#include "kmem.h" + +EXTENSION class Pic +{ +public: + enum { + ICIP = Kmem::Pic_map_base + 0x00000, + ICMR = Kmem::Pic_map_base + 0x00004, + ICLR = Kmem::Pic_map_base + 0x00008, + ICCR = Kmem::Pic_map_base + 0x0000c, + ICFP = Kmem::Pic_map_base + 0x00010, + ICPR = Kmem::Pic_map_base + 0x00020, + }; +}; + +// ------------------------------------------------------------- +IMPLEMENTATION [arm && (sa1100 || pxa)]: + +#include "config.h" +#include "io.h" +#include "irq.h" +#include "irq_chip_generic.h" +#include "irq_mgr.h" + +class Chip : public Irq_chip_gen +{ +public: + Chip() : Irq_chip_gen(32) {} + unsigned set_mode(Mword, unsigned) { return Irq_base::Trigger_level; } + void set_cpu(Mword, unsigned) {} + void ack(Mword) { /* ack is empty */ } +}; + +PUBLIC +void +Chip::mask(Mword irq) +{ + assert(cpu_lock.test()); + Io::write(Io::read(Pic::ICMR) & ~(1 << irq), Pic::ICMR); +} + +PUBLIC +void +Chip::mask_and_ack(Mword irq) +{ + assert (cpu_lock.test()); + Io::write(Io::read(Pic::ICMR) & ~(1 << irq), Pic::ICMR); + // ack is empty +} + +PUBLIC +void +Chip::unmask(Mword irq) +{ + Io::write(Io::read(Pic::ICMR) | (1 << irq), Pic::ICMR); +} + +static Static_object > mgr; + +IMPLEMENT FIASCO_INIT +void Pic::init() +{ + Irq_mgr::mgr = mgr.construct(); + + // only unmasked interrupts wakeup from idle + Io::write(0x01, ICCR); + // mask all interrupts + Io::write(0x00, ICMR); + // all interrupts are IRQ's (no FIQ) + Io::write(0x00, ICLR); +} + +IMPLEMENT inline NEEDS["io.h"] +Pic::Status Pic::disable_all_save() +{ + Status s = Io::read(ICMR); + Io::write(0, ICMR); + return s; +} + +IMPLEMENT inline NEEDS["io.h"] +void Pic::restore_all(Status s) +{ + Io::write(s, ICMR); +} + +PUBLIC static inline NEEDS["io.h"] +Unsigned32 Chip::pending() +{ + return Io::read(Pic::ICIP); +} + +extern "C" +void irq_handler() +{ + Unsigned32 i = Chip::pending(); + if (i) + mgr->c.handle_irq(i, 0); +} + +// ------------------------------------------------------------- +IMPLEMENTATION [arm && debug && (sa1100 || pxa)]: + +PUBLIC +char const * +Chip::chip_type() const +{ return "HW PXA/SA IRQ"; } diff --git a/kernel/fiasco/src/kern/arm/bsp/pxa-sa/timer-arm-pxa_sa1100.cpp b/kernel/fiasco/src/kern/arm/bsp/pxa-sa/timer-arm-pxa_sa1100.cpp new file mode 100644 index 00000000..1cfe0516 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/pxa-sa/timer-arm-pxa_sa1100.cpp @@ -0,0 +1,110 @@ +// ------------------------------------------------------------------------ +INTERFACE [arm && (sa1100 || pxa)]: + +#include "kmem.h" + +EXTENSION class Timer +{ +public: + static unsigned irq() { return 26; } + +private: + enum { + OSMR0 = Kmem::Timer_map_base + 0x00, + OSMR1 = Kmem::Timer_map_base + 0x04, + OSMR2 = Kmem::Timer_map_base + 0x08, + OSMR3 = Kmem::Timer_map_base + 0x0c, + OSCR = Kmem::Timer_map_base + 0x10, + OSSR = Kmem::Timer_map_base + 0x14, + OWER = Kmem::Timer_map_base + 0x18, + OIER = Kmem::Timer_map_base + 0x1c, + + Timer_diff = (36864 * Config::Scheduler_granularity) / 10000, // 36864MHz*1ms + }; +}; + + +// ------------------------------------------------------------- +IMPLEMENTATION [arm && (sa1100 || pxa)]: + +#include "config.h" +#include "kip.h" +#include "pic.h" +#include "io.h" + +IMPLEMENT +void Timer::init(unsigned) +{ + Io::write(1, OIER); // enable OSMR0 + Io::write(0, OWER); // disable Watchdog + Io::write(Timer_diff, OSMR0); + Io::write(0, OSCR); // set timer counter to zero + Io::write(~0U, OSSR); // clear all status bits +} + +static inline +Unsigned64 +Timer::timer_to_us(Unsigned32 cr) +{ return (((Unsigned64)cr) << 14) / 60398; } + +static inline +Unsigned64 +Timer::us_to_timer(Unsigned64 us) +{ return (us * 60398) >> 14; } + +PUBLIC static inline NEEDS["io.h", "config.h", Timer::timer_to_us] +void +Timer::acknowledge() +{ + if (Config::Scheduler_one_shot) + { + Kip::k()->clock += timer_to_us(Io::read(OSCR)); + //puts("Reset timer"); + Io::write(0, OSCR); + Io::write(0xffffffff, OSMR0); + } + else + Io::write(0, OSCR); + Io::write(1, OSSR); // clear all status bits + + // hmmm? + //enable(); +} + +IMPLEMENT inline NEEDS["kip.h", "io.h", Timer::timer_to_us, Timer::us_to_timer] +void +Timer::update_one_shot(Unsigned64 wakeup) +{ + Unsigned32 apic; + Kip::k()->clock += timer_to_us(Io::read(OSCR)); + Io::write(0, OSCR); + Unsigned64 now = Kip::k()->clock; + + if (EXPECT_FALSE (wakeup <= now) ) + // already expired + apic = 1; + else + { + apic = us_to_timer(wakeup - now); + if (EXPECT_FALSE(apic > 0x0ffffffff)) + apic = 0x0ffffffff; + if (EXPECT_FALSE (apic < 1) ) + // timeout too small + apic = 1; + } + + //printf("%15lld: Set Timer to %lld [%08x]\n", now, wakeup, apic); + + Io::write(apic, OSMR0); + Io::write(1, OSSR); // clear all status bits +} + +IMPLEMENT inline NEEDS["config.h", "kip.h", "io.h", Timer::timer_to_us] +Unsigned64 +Timer::system_clock() +{ + if (Config::Scheduler_one_shot) + return Kip::k()->clock + timer_to_us(Io::read(OSCR)); + else + return Kip::k()->clock; +} diff --git a/kernel/fiasco/src/kern/arm/bsp/pxa/Kconfig b/kernel/fiasco/src/kern/arm/bsp/pxa/Kconfig new file mode 100644 index 00000000..4965f959 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/pxa/Kconfig @@ -0,0 +1,4 @@ +# PF: XSCALE +# PFDESCR: Intel XScale Platform +# PFCAN: CAN_ARM_CPU_XSCALE +# PFDEPENDS: ARM diff --git a/kernel/fiasco/src/kern/arm/bsp/pxa/Modules b/kernel/fiasco/src/kern/arm/bsp/pxa/Modules new file mode 100644 index 00000000..61406844 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/pxa/Modules @@ -0,0 +1,17 @@ +# vim:set ft=make: + +PREPROCESS_PARTS += pxa 16550 vcache armv5 generic_tickless_idle +CONFIG_KERNEL_LOAD_ADDR := 0xa0000000 +VPATH += kern/arm/bsp/pxa-sa + +uart_IMPL += uart-16550 uart-16550-arm-pxa +config_IMPL += config-arm-pxa_sa1100 +mem_layout_IMPL += mem_layout-arm-pxa +pic_IMPL += pic-arm-pxa_sa1100 +bootstrap_IMPL += bootstrap-arm-pxa +timer_IMPL += timer-arm-pxa_sa1100 +timer_tick_IMPL += timer_tick-single-vector +kernel_uart_IMPL += kernel_uart-arm-pxa +reset_IMPL += reset-arm-pxa +timestamp_IMPL += timestamp-generic +clock_IMPL += clock-generic diff --git a/kernel/fiasco/src/kern/arm/bsp/pxa/bootstrap-arm-pxa.cpp b/kernel/fiasco/src/kern/arm/bsp/pxa/bootstrap-arm-pxa.cpp new file mode 100644 index 00000000..2c535f71 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/pxa/bootstrap-arm-pxa.cpp @@ -0,0 +1,23 @@ +//----------------------------------------------------------------------------- +INTERFACE [arm && pxa]: + +enum { + Cache_flush_area = 0xa0100000, // XXX: hacky +}; + +//----------------------------------------------------------------------------- +IMPLEMENTATION [arm && pxa]: + +void +map_hw(void *pd) +{ + // map the cache flush area to 0xef000000 + map_1mb(pd, Mem_layout::Cache_flush_area, Mem_layout::Flush_area_phys_base, true, false); + // map UART + map_1mb(pd, Mem_layout::Uart_map_base, Mem_layout::Uart_phys_base, false, false); + map_1mb(pd, Mem_layout::Uart_phys_base, Mem_layout::Uart_phys_base, false, false); + // map Timer + map_1mb(pd, Mem_layout::Timer_map_base, Mem_layout::Timer_phys_base, false, false); + // map Pic + map_1mb(pd, Mem_layout::Pic_map_base, Mem_layout::Pic_phys_base, false, false); +} diff --git a/kernel/fiasco/src/kern/arm/bsp/pxa/kernel_uart-arm-pxa.cpp b/kernel/fiasco/src/kern/arm/bsp/pxa/kernel_uart-arm-pxa.cpp new file mode 100644 index 00000000..b3864f24 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/pxa/kernel_uart-arm-pxa.cpp @@ -0,0 +1,13 @@ +INTERFACE: + +// On ARM the MMIO for the uart is accessible before the MMU is fully up +EXTENSION class Kernel_uart { enum { Bsp_init_mode = Init_before_mmu }; }; + +IMPLEMENTATION [arm && pxa && serial]: +#include "mem_layout.h" + +IMPLEMENT +bool Kernel_uart::startup(unsigned port, int /*irq*/) +{ + return Uart::startup(Mem_layout::Uart_base, 22); +} diff --git a/kernel/fiasco/src/kern/arm/bsp/pxa/mem_layout-arm-pxa.cpp b/kernel/fiasco/src/kern/arm/bsp/pxa/mem_layout-arm-pxa.cpp new file mode 100644 index 00000000..4baa51bd --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/pxa/mem_layout-arm-pxa.cpp @@ -0,0 +1,21 @@ +INTERFACE [arm-pxa]: //------------------------------------------------------ + +EXTENSION class Mem_layout +{ +public: + enum Virt_layout_pxa { + Timer_map_base = 0xef100000, + Pic_map_base = 0xef200000, + Uart_map_base = 0xef300000, + Uart_base = Uart_map_base, + }; + + enum Phys_layout { + Timer_phys_base = 0x40a00000, + Pic_phys_base = 0x40d00000, + Uart_phys_base = 0x40100000, + Sdram_phys_base = 0xa0000000, + Flush_area_phys_base = 0xe0000000, + }; +}; + diff --git a/kernel/fiasco/src/kern/arm/bsp/pxa/reset-arm-pxa.cpp b/kernel/fiasco/src/kern/arm/bsp/pxa/reset-arm-pxa.cpp new file mode 100644 index 00000000..bd5dba4e --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/pxa/reset-arm-pxa.cpp @@ -0,0 +1,18 @@ +IMPLEMENTATION [arm && pxa]: + +#include "timer.h" +#include "io.h" + +void __attribute__ ((noreturn)) +platform_reset(void) +{ + enum { + OSCR = Kmem::Timer_map_base + 0x10, + OWER = Kmem::Timer_map_base + 0x18, + }; + Io::write(1, OWER); + Io::write(0xffffff00, OSCR); + + for (;;) + ; +} diff --git a/kernel/fiasco/src/kern/arm/bsp/pxa/uart-16550-arm-pxa.cpp b/kernel/fiasco/src/kern/arm/bsp/pxa/uart-16550-arm-pxa.cpp new file mode 100644 index 00000000..df79fdb7 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/pxa/uart-16550-arm-pxa.cpp @@ -0,0 +1,22 @@ +INTERFACE [16550 && pxa]: + +EXTENSION class Uart +{ +public: + enum { + Base_rate = 921600, + Base_ier_bits = 1 << 6, + + Access_shift = 2, + }; +}; + +IMPLEMENTATION [16550 && pxa]: + +IMPLEMENT inline NEEDS[Uart::mcr, Uart::ier] +void Uart::enable_rcv_irq() +{ + //mcr(mcr() & ~0x08); //XScale DOC is WRONG + mcr(mcr() | 0x08); + ier(ier() | 1); +} diff --git a/kernel/fiasco/src/kern/arm/bsp/realview/Kconfig b/kernel/fiasco/src/kern/arm/bsp/realview/Kconfig new file mode 100644 index 00000000..1b42875b --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/realview/Kconfig @@ -0,0 +1,71 @@ +# PF: REALVIEW +# PFDESCR: ARM RealView Platform +# PFDEPENDS: ARM + +choice + prompt "Realview Platform" + default PF_REALVIEW_EB + +config PF_REALVIEW_EB + bool "Emulation Baseboard (EB)" + depends on PF_REALVIEW + select CAN_ARM_CPU_926 + select CAN_ARM_CPU_1176 + select CAN_ARM_CPU_MPCORE + select CAN_ARM_CPU_CORTEX_A8 + select CAN_ARM_CPU_CORTEX_A9 + select CAN_ARM_CACHE_L2CXX0 if ARM_MPCORE + help + Choose for Emulation Baseboard (EB) + +config PF_REALVIEW_PB11MP + bool "PB11MP" + depends on PF_REALVIEW + select CAN_ARM_CPU_MPCORE + select CAN_ARM_CACHE_L2CXX0 + help + Choose for PB11MP + +config PF_REALVIEW_PBX + bool "PBX" + depends on PF_REALVIEW + select CAN_ARM_CPU_CORTEX_A9 + select CAN_ARM_CACHE_L2CXX0 + help + Choose for PBX-A9. + +config PF_REALVIEW_VEXPRESS + bool "Versatile Express" + depends on PF_REALVIEW + select CAN_ARM_CPU_CORTEX_A9 + help + Choose for Versatile Express. + +endchoice + +choice + prompt "Start of RAM (physical address)" if !PF_REALVIEW_EB + default PF_REALVIEW_RAM_PHYS_BASE_0x0 + +config PF_REALVIEW_RAM_PHYS_BASE_0x0 + bool "0x00000000" + +config PF_REALVIEW_RAM_PHYS_BASE_0x2 + bool "0x20000000" + depends on PF_REALVIEW_PBX + +config PF_REALVIEW_RAM_PHYS_BASE_0x6 + bool "0x60000000" + depends on PF_REALVIEW_VEXPRESS + +config PF_REALVIEW_RAM_PHYS_BASE_0x7 + bool "0x70000000" + depends on PF_REALVIEW_PBX || PF_REALVIEW_PB11MP +endchoice + +config PF_REALVIEW_RAM_PHYS_BASE + hex + default 0x0 if !PF_REALVIEW_RAM_PHYS_BASE_0x2 && !PF_REALVIEW_RAM_PHYS_BASE_0x6 && !PF_REALVIEW_RAM_PHYS_BASE_0x7 + default 0x20000000 if PF_REALVIEW_RAM_PHYS_BASE_0x2 + default 0x60000000 if PF_REALVIEW_RAM_PHYS_BASE_0x6 + default 0x70000000 if PF_REALVIEW_RAM_PHYS_BASE_0x7 diff --git a/kernel/fiasco/src/kern/arm/bsp/realview/Modules b/kernel/fiasco/src/kern/arm/bsp/realview/Modules new file mode 100644 index 00000000..d5a7336d --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/realview/Modules @@ -0,0 +1,36 @@ +# vim:set ft=make: + +SUBSYSTEMS += LIBUART +OBJECTS_LIBUART += uart_pl011.o +PREPROCESS_PARTS += realview libuart pic_gic +PREPROCESS_PARTS += $(if $(CONFIG_PF_REALVIEW_EB),realview_eb) +PREPROCESS_PARTS += $(if $(CONFIG_PF_REALVIEW_PB11MP),realview_pb11mp) +PREPROCESS_PARTS += $(if $(CONFIG_PF_REALVIEW_PBX),realview_pbx) +PREPROCESS_PARTS += $(if $(CONFIG_PF_REALVIEW_VEXPRESS),realview_vexpress) +PREPROCESS_PARTS += generic_tickless_idle +CONFIG_KERNEL_LOAD_ADDR := $(CONFIG_PF_REALVIEW_RAM_PHYS_BASE) + +MPCORE_PHYS_BASE := $(if $(CONFIG_PF_REALVIEW_VEXPRESS),0x1e000000,0x1f000000) + +timer_IMPL += timer-arm-realview +ifeq ($(CONFIG_ARM_MPCORE)$(CONFIG_ARM_CORTEX_A9),) + PREPROCESS_PARTS += sp804 +else + PREPROCESS_PARTS += mptimer + timer_IMPL += timer-arm-mptimer timer-arm-mptimer-realview +endif + +INTERFACES_KERNEL += gic boot_mp platform board_check-arm-realview + +timer_tick_IMPL += timer_tick-single-vector +uart_IMPL += uart-arm-realview +config_IMPL += config-arm-realview +mem_layout_IMPL += mem_layout-arm-realview +pic_IMPL += pic-gic pic-arm-realview +bootstrap_IMPL += bootstrap-arm-realview +kernel_uart_IMPL += kernel_uart-arm-realview +reset_IMPL += reset-arm-realview +clock_IMPL += clock-arm-realview +outer_cache_IMPL += outer_cache-arm-realview +boot_mp_IMPL += boot_mp-arm-realview +platform_IMPL += platform-arm-realview diff --git a/kernel/fiasco/src/kern/arm/bsp/realview/board_check-arm-realview.cpp b/kernel/fiasco/src/kern/arm/bsp/realview/board_check-arm-realview.cpp new file mode 100644 index 00000000..865fb5db --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/realview/board_check-arm-realview.cpp @@ -0,0 +1,96 @@ +INTERFACE [arm && realview]: + +#include "types.h" + +class Board_check +{ +public: + static void check_board(); + +private: + static Mword read_board_id(); + struct id_pair { + unsigned mask, id; + }; + static id_pair ids[]; +}; + +// ------------------------------------------------------------------------ +IMPLEMENTATION [arm && realview]: + +#include "initcalls.h" + +// ------------------------------------------------------------------------ +IMPLEMENTATION [arm && realview && realview_eb]: + +Board_check::id_pair Board_check::ids[] FIASCO_INITDATA = { + { 0x1ffffe00, 0x01400400 }, +}; + +// ------------------------------------------------------------------------ +IMPLEMENTATION [arm && realview && realview_pb11mp]: + +Board_check::id_pair Board_check::ids[] FIASCO_INITDATA = { + { 0x0fffff00, 0x0159f500 }, +}; + +// ------------------------------------------------------------------------ +IMPLEMENTATION [arm && realview && realview_pbx]: + +Board_check::id_pair Board_check::ids[] FIASCO_INITDATA = { + { 0xffffff00, 0x1182f500 }, // board + { 0xffffff00, 0x01780500 }, // qemu +}; + +// ------------------------------------------------------------------------ +IMPLEMENTATION [arm && realview && realview_vexpress]: + +Board_check::id_pair Board_check::ids[] FIASCO_INITDATA = { + { 0xcfffff00, 0x0190f500 }, +}; + +// ------------------------------------------------------------------------ +IMPLEMENTATION [arm && realview]: + +#include "kmem.h" +#include "io.h" +#include "static_init.h" +#include "processor.h" + +#include + +enum +{ + SYS_ID = Kmem::System_regs_map_base + 0x0, +}; + +IMPLEMENT static FIASCO_INIT +Mword +Board_check::read_board_id() +{ return Io::read(SYS_ID); } + +IMPLEMENT static FIASCO_INIT +void +Board_check::check_board() +{ + Mword id = read_board_id(); + + printf("Realview System ID: Rev=%lx HBI=%03lx Build=%lx Arch=%lx FPGA=%02lx\n", + id >> 28, (id >> 16) & 0xfff, (id >> 12) & 0xf, + (id >> 8) & 0xf, id & 0xff); + + for (unsigned i = 0; i < (sizeof(ids) / sizeof(ids[0])); ++i) + if ((id & ids[i].mask) == ids[i].id) + return; + + printf(" Invalid System ID for this kernel config\n"); + for (unsigned i = 0; i < (sizeof(ids) / sizeof(ids[0])); ++i) + printf(" Expected (%08lx & %08x) == %08x%s\n", + id, ids[i].mask, ids[i].id, + i + 1 < (sizeof(ids) / sizeof(ids[0])) ? ", or" : ""); + printf(" Stopping.\n"); + while (1) + Proc::halt(); +} + +STATIC_INITIALIZEX_P(Board_check, check_board, GDB_INIT_PRIO); diff --git a/kernel/fiasco/src/kern/arm/bsp/realview/boot_mp-arm-realview.cpp b/kernel/fiasco/src/kern/arm/bsp/realview/boot_mp-arm-realview.cpp new file mode 100644 index 00000000..2cf7be7b --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/realview/boot_mp-arm-realview.cpp @@ -0,0 +1,30 @@ +INTERFACE [arm && mp && realview]: + +#include "types.h" + +class Boot_mp +{ +}; + +IMPLEMENTATION [arm && mp && realview]: + +#include "io.h" +#include "ipi.h" +#include "platform.h" + +PUBLIC +void +Boot_mp::start_ap_cpus(Address phys_tramp_mp_addr) +{ + // set physical start address for AP CPUs + Platform::write(Platform::Sys::Flags_clr, 0xffffffff); + Platform::write(Platform::Sys::Flags, phys_tramp_mp_addr); + + // wake up AP CPUs, always from CPU 0 + Ipi::bcast(Ipi::Global_request, 0); +} + +PUBLIC +void +Boot_mp::cleanup() +{} diff --git a/kernel/fiasco/src/kern/arm/bsp/realview/bootstrap-arm-realview.cpp b/kernel/fiasco/src/kern/arm/bsp/realview/bootstrap-arm-realview.cpp new file mode 100644 index 00000000..8583757b --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/realview/bootstrap-arm-realview.cpp @@ -0,0 +1,51 @@ +INTERFACE [arm && realview]: + +#include "mem_layout.h" + +enum { Cache_flush_area = 0, }; + +//----------------------------------------------------------------------------- +IMPLEMENTATION [arm && realview && realview_eb && !(mpcore || (armca9 && mp))]: + +static void map_hw2(void *) +{} + +//----------------------------------------------------------------------------- +IMPLEMENTATION [arm && realview && realview_eb && (mpcore || (armca9 && mp))]: + +static void map_hw2(void *pd) +{ + map_1mb(pd, Mem_layout::Mp_scu_map_base, Mem_layout::Mp_scu_phys_base, + false, false); +} + +//----------------------------------------------------------------------------- +IMPLEMENTATION [arm && realview && (realview_pb11mp || realview_pbx)]: + +static void map_hw2(void *pd) +{ + map_1mb(pd, Mem_layout::Devices1_map_base, Mem_layout::Devices1_phys_base, + false, false); + map_1mb(pd, Mem_layout::Devices2_map_base, Mem_layout::Devices2_phys_base, + false, false); +} + +//----------------------------------------------------------------------------- +IMPLEMENTATION [arm && realview && realview_vexpress]: + +static void map_hw2(void *pd) +{ + map_1mb(pd, Mem_layout::Devices1_map_base, Mem_layout::Devices1_phys_base, + false, false); +} + +//----------------------------------------------------------------------------- +IMPLEMENTATION [arm && realview]: + +void +map_hw(void *pd) +{ + // map devices + map_1mb(pd, Mem_layout::Devices0_map_base, Mem_layout::Devices0_phys_base, false, false); + map_hw2(pd); +} diff --git a/kernel/fiasco/src/kern/arm/bsp/realview/clock-arm-realview.cpp b/kernel/fiasco/src/kern/arm/bsp/realview/clock-arm-realview.cpp new file mode 100644 index 00000000..ec70d662 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/realview/clock-arm-realview.cpp @@ -0,0 +1,34 @@ +INTERFACE [arm && realview]: + +#include "kmem.h" +#include "l4_types.h" + +EXTENSION class Clock_base +{ +protected: + enum { + SYS_24MHZ = Kmem::System_regs_map_base + 0x5c, + }; + + typedef Mword Counter; +}; + +// -------------------------------------------------------------- +IMPLEMENTATION [arm && realview]: + +#include "io.h" +#include + +IMPLEMENT inline NEEDS["io.h", ] +Clock::Counter +Clock::read_counter() const +{ + return Io::read(SYS_24MHZ); +} + +IMPLEMENT inline +Cpu_time +Clock::us(Time t) +{ + return t / 24; +} diff --git a/kernel/fiasco/src/kern/arm/bsp/realview/config-arm-realview.cpp b/kernel/fiasco/src/kern/arm/bsp/realview/config-arm-realview.cpp new file mode 100644 index 00000000..c770ef97 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/realview/config-arm-realview.cpp @@ -0,0 +1,3 @@ +INTERFACE [arm && realview]: + +#define TARGET_NAME "Realview" diff --git a/kernel/fiasco/src/kern/arm/bsp/realview/kernel_uart-arm-realview.cpp b/kernel/fiasco/src/kern/arm/bsp/realview/kernel_uart-arm-realview.cpp new file mode 100644 index 00000000..630e200c --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/realview/kernel_uart-arm-realview.cpp @@ -0,0 +1,12 @@ +INTERFACE: + +// On ARM the MMIO for the uart is accessible before the MMU is fully up +EXTENSION class Kernel_uart { enum { Bsp_init_mode = Init_before_mmu }; }; + +IMPLEMENTATION [arm && realview && serial]: + +IMPLEMENT +bool Kernel_uart::startup(unsigned, int) +{ + return Uart::startup(); +} diff --git a/kernel/fiasco/src/kern/arm/bsp/realview/mem_layout-arm-realview.cpp b/kernel/fiasco/src/kern/arm/bsp/realview/mem_layout-arm-realview.cpp new file mode 100644 index 00000000..5ee295aa --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/realview/mem_layout-arm-realview.cpp @@ -0,0 +1,185 @@ +INTERFACE [arm && realview]: // ------------------------------------------- + +#include "globalconfig.h" + +EXTENSION class Mem_layout +{ +public: + enum Phys_layout_realview_all { + Sdram_phys_base = CONFIG_PF_REALVIEW_RAM_PHYS_BASE, + Flush_area_phys_base = 0xe0000000, + + Devices0_map_base = Registers_map_start, + Devices1_map_base = Registers_map_start + 0x00100000, + Devices2_map_base = Registers_map_start + 0x00200000, + + }; +}; + +// ------------------------------------------------------------------------ +INTERFACE [arm && realview && (realview_eb || realview_pb11mp || realview_pbx || realview_vexpress)]: + +#include "globalconfig.h" + +EXTENSION class Mem_layout +{ +public: + enum Virt_layout_realview { + System_regs_map_base = Devices0_map_base, + System_ctrl_map_base = Devices0_map_base + 0x00001000, + Uart0_map_base = Devices0_map_base + 0x00009000, + Uart1_map_base = Devices0_map_base + 0x0000a000, + Uart2_map_base = Devices0_map_base + 0x0000b000, + Uart3_map_base = Devices0_map_base + 0x0000c000, + Timer0_map_base = Devices0_map_base + 0x00011000, + Timer1_map_base = Devices0_map_base + 0x00011020, + Timer2_map_base = Devices0_map_base + 0x00012000, + Timer3_map_base = Devices0_map_base + 0x00012020, + Uart_base = Uart0_map_base, + }; + + enum Phys_layout_realview { + Devices0_phys_base = 0x10000000, + System_regs_phys_base= Devices0_phys_base, + System_ctrl_phys_base= Devices0_phys_base + 0x00001000, + Uart0_phys_base = Devices0_phys_base + 0x00009000, + Timer0_1_phys_base = Devices0_phys_base + 0x00011000, + Timer2_3_phys_base = Devices0_phys_base + 0x00012000, + }; +}; + +// ------------------------------------------------------------------------ +INTERFACE [arm && realview && realview_eb && !(mpcore || armca9)]: + +EXTENSION class Mem_layout +{ +public: + enum Virt_layout_realview_single { + Gic_cpu_map_base = Devices0_map_base + 0x00040000, + Gic_dist_map_base = Gic_cpu_map_base + 0x00001000, + }; + + enum Phys_layout_realview_single { + Gic_cpu_phys_base = Devices0_phys_base + 0x00040000, + Gic_dist_phys_base = Gic_cpu_phys_base + 0x00001000, + }; +}; + +// ------------------------------------------------------------------------ +INTERFACE [arm && realview && realview_eb && (mpcore || armca9)]: + +EXTENSION class Mem_layout +{ +public: + enum Virt_layout_realview_mp { + Mp_scu_map_base = Devices1_map_base, + Gic_cpu_map_base = Devices1_map_base + 0x00000100, + Gic_dist_map_base = Devices1_map_base + 0x00001000, + L2cxx0_map_base = Devices1_map_base + 0x00002000, + + Gic1_cpu_map_base = Devices0_map_base + 0x00040000, + Gic1_dist_map_base = Devices0_map_base + 0x00041000, + }; + + enum Phys_layout_realview_mp { + Mp_scu_phys_base = 0x1f000000, + Gic_cpu_phys_base = Mp_scu_phys_base + 0x00000100, + Gic_dist_phys_base = Mp_scu_phys_base + 0x00001000, + L2cxx0_phys_base = Mp_scu_phys_base + 0x00002000, + + Gic1_cpu_phys_base = Devices0_phys_base + 0x00040000, + Gic1_dist_phys_base = Devices0_phys_base + 0x00041000, + Gic2_cpu_phys_base = Devices0_phys_base + 0x00050000, + Gic2_dist_phys_base = Devices0_phys_base + 0x00051000, + Gic3_cpu_phys_base = Devices0_phys_base + 0x00060000, + Gic3_dist_phys_base = Devices0_phys_base + 0x00061000, + Gic4_cpu_phys_base = Devices0_phys_base + 0x00070000, + Gic4_dist_phys_base = Devices0_phys_base + 0x00071000, + }; +}; + +// ------------------------------------------------------------------------ +INTERFACE [arm && realview && realview_pb11mp]: + +EXTENSION class Mem_layout +{ +public: + enum Virt_layout_realview_pb11mp { + Mp_scu_map_base = Devices1_map_base, + Gic_cpu_map_base = Devices1_map_base + 0x00000100, + Gic_dist_map_base = Devices1_map_base + 0x00001000, + L2cxx0_map_base = Devices1_map_base + 0x00002000, + + Gic1_cpu_map_base = Devices2_map_base, + Gic1_dist_map_base = Devices2_map_base + 0x00001000, + }; + + enum Phys_layout_realview_pb11mp { + Devices1_phys_base = 0x1f000000, + Mp_scu_phys_base = 0x1f000000, + Gic_cpu_phys_base = Mp_scu_phys_base + 0x00000100, + Gic_dist_phys_base = Mp_scu_phys_base + 0x00001000, + L2cxx0_phys_base = Mp_scu_phys_base + 0x00002000, + + Devices2_phys_base = 0x1e000000, + Gic0_cpu_phys_base = 0x1e000000, + Gic0_dist_phys_base = Gic0_cpu_phys_base + 0x00001000, + Gic1_cpu_phys_base = 0x1e010000, + Gic1_dist_phys_base = Gic1_cpu_phys_base + 0x00001000, + }; +}; + +// ------------------------------------------------------------------------ +INTERFACE [arm && realview && realview_pbx]: + +EXTENSION class Mem_layout +{ +public: + enum Virt_layout_realview_pbx { + Mp_scu_map_base = Devices1_map_base, + Gic_cpu_map_base = Devices1_map_base + 0x00000100, + Gic_dist_map_base = Devices1_map_base + 0x00001000, + L2cxx0_map_base = Devices1_map_base + 0x00002000, + + Gic2_cpu_map_base = Devices2_map_base + 0x00020000, + Gic2_dist_map_base = Devices2_map_base + 0x00021000, + Gic3_cpu_map_base = Devices2_map_base + 0x00030000, + Gic3_dist_map_base = Devices2_map_base + 0x00031000, + }; + + enum Phys_layout_realview_pbx { + Devices1_phys_base = 0x1f000000, + Mp_scu_phys_base = 0x1f000000, + Gic_cpu_phys_base = Mp_scu_phys_base + 0x00000100, + Gic_dist_phys_base = Mp_scu_phys_base + 0x00001000, + L2cxx0_phys_base = Mp_scu_phys_base + 0x00002000, + + Devices2_phys_base = 0x1e000000, + Gic2_cpu_phys_base = 0x1e020000, + Gic2_dist_phys_base = Gic2_cpu_phys_base + 0x00001000, + Gic3_cpu_phys_base = 0x1e030000, + Gic3_dist_phys_base = Gic3_cpu_phys_base + 0x00001000, + }; +}; + +// ------------------------------------------------------------------------ +INTERFACE [arm && realview && realview_vexpress]: + +EXTENSION class Mem_layout +{ +public: + enum Virt_layout_realview_vexpress { + Mp_scu_map_base = Devices1_map_base, + Gic_cpu_map_base = Devices1_map_base + 0x00000100, + Gic_dist_map_base = Devices1_map_base + 0x00001000, + L2cxx0_map_base = Devices1_map_base + 0x00002000, + }; + + enum Phys_layout_realview_vexpress { + Devices1_phys_base = 0x1e000000, + Mp_scu_phys_base = 0x1e000000, + Gic_cpu_phys_base = Mp_scu_phys_base + 0x00000100, + Gic_dist_phys_base = Mp_scu_phys_base + 0x00001000, + L2cxx0_phys_base = Mp_scu_phys_base + 0x00002000, + }; +}; diff --git a/kernel/fiasco/src/kern/arm/bsp/realview/outer_cache-arm-realview.cpp b/kernel/fiasco/src/kern/arm/bsp/realview/outer_cache-arm-realview.cpp new file mode 100644 index 00000000..6e02784b --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/realview/outer_cache-arm-realview.cpp @@ -0,0 +1,31 @@ +// ------------------------------------------------------------------------ +IMPLEMENTATION [arm && realview && outer_cache_l2cxx0 && armca9]: + +IMPLEMENT +Mword +Outer_cache::platform_init(Mword aux_control) +{ + Io::write(0 , TAG_RAM_CONTROL); + Io::write(0 , DATA_RAM_CONTROL); + aux_control &= 0xc0000fff; + aux_control |= 1 << 17; // 16kb way size + aux_control |= 1 << 20; // event monitor bus enable + aux_control |= 1 << 22; // shared attribute ovr enable + aux_control |= 1 << 28; // data prefetch + aux_control |= 1 << 29; // insn prefetch + return aux_control; +} + +// ------------------------------------------------------------------------ +IMPLEMENTATION [arm && realview && outer_cache_l2cxx0 && mpcore]: + +IMPLEMENT +Mword +Outer_cache::platform_init(Mword aux_control) +{ + aux_control &= 0xfe000fff; // keep latencies, keep reserved, keep NS bits + aux_control |= 8 << 13; // 8-way associative + aux_control |= 4 << 17; // 128kb Way size + aux_control |= 1 << 22; // shared bit ignore + return aux_control; +} diff --git a/kernel/fiasco/src/kern/arm/bsp/realview/pic-arm-realview.cpp b/kernel/fiasco/src/kern/arm/bsp/realview/pic-arm-realview.cpp new file mode 100644 index 00000000..749a9745 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/realview/pic-arm-realview.cpp @@ -0,0 +1,129 @@ +INTERFACE [arm && realview]: + +#include "types.h" +#include "gic.h" + +class Irq_base; + +//------------------------------------------------------------------- +INTERFACE [arm && realview && (mpcore || armca9)]: + +EXTENSION class Pic +{ +private: + enum + { + INTMODE_NEW_NO_DDC = 1 << 23, + }; +}; + +//------------------------------------------------------------------- +IMPLEMENTATION [arm && !(mpcore || armca9)]: + +PRIVATE static inline +void Pic::configure_core() +{} + +//------------------------------------------------------------------- +IMPLEMENTATION [arm && pic_gic && realview && (realview_pb11mp || (realview_eb && (mpcore || (armca9 && mp))))]: + +#include "irq_mgr_multi_chip.h" +#include "cascade_irq.h" + +PUBLIC static +void Pic::init_ap() +{ + gic->init_ap(); + static_cast(Irq_mgr::mgr->chip(256).chip)->init_ap(); +} + + +IMPLEMENT FIASCO_INIT +void Pic::init() +{ + configure_core(); + typedef Irq_mgr_multi_chip<8> Mgr; + + Gic *g = gic.construct(Kmem::Gic_cpu_map_base, Kmem::Gic_dist_map_base); + Mgr *m = new Boot_object(2); + Irq_mgr::mgr = m; + + m->add_chip(0, g, g->nr_irqs()); + + g = new Boot_object(Kmem::Gic1_cpu_map_base, Kmem::Gic1_dist_map_base); + m->add_chip(256, g, g->nr_irqs()); + + // FIXME: Replace static local variable, use placement new + Cascade_irq *casc_irq = new Boot_object(g, &Gic::cascade_hit); + + gic->alloc(casc_irq, 42); + casc_irq->unmask(); +} + +//------------------------------------------------------------------- +IMPLEMENTATION [arm && pic_gic && !(realview && (realview_pb11mp || (realview_eb && (mpcore || (armca9 && mp)))))]: + +#include "irq_mgr_multi_chip.h" + +IMPLEMENT FIASCO_INIT +void Pic::init() +{ + configure_core(); + + typedef Irq_mgr_multi_chip<8> Mgr; + Gic *g = gic.construct(Kmem::Gic_cpu_map_base, Kmem::Gic_dist_map_base); + + Mgr *m = new Boot_object(1); + m->add_chip(0, g, g->nr_irqs()); + Irq_mgr::mgr = m; +} + +PUBLIC static +void Pic::init_ap() +{ + gic->init_ap(); +} + +PRIVATE static inline +void +Pic::init_ap_other_gics() +{} + +//------------------------------------------------------------------- +IMPLEMENTATION [arm && pic_gic]: + +#include "gic.h" +#include "initcalls.h" + +IMPLEMENT inline +Pic::Status Pic::disable_all_save() +{ return 0; } + +IMPLEMENT inline +void Pic::restore_all(Status) +{} + +//------------------------------------------------------------------- +IMPLEMENTATION [arm && pic_gic && (mpcore || armca9)]: + +#include "cpu.h" +#include "io.h" +#include "platform.h" + +PRIVATE static +void Pic::unlock_config() +{ Io::write(0xa05f, Platform::Sys::Lock); } + +PRIVATE static +void Pic::lock_config() +{ Io::write(0x0, Platform::Sys::Lock); } + +PRIVATE static +void Pic::configure_core() +{ + // Enable 'new' interrupt-mode, no DCC + unlock_config(); + Io::write(Io::read(Platform::Sys::Pld_ctrl1) | INTMODE_NEW_NO_DDC, + Platform::Sys::Pld_ctrl1); + lock_config(); +} diff --git a/kernel/fiasco/src/kern/arm/bsp/realview/platform-arm-realview.cpp b/kernel/fiasco/src/kern/arm/bsp/realview/platform-arm-realview.cpp new file mode 100644 index 00000000..0470b787 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/realview/platform-arm-realview.cpp @@ -0,0 +1,39 @@ +INTERFACE[arm && realview]: + +#include "mem_layout.h" + +class Platform +{ +public: + class Sys + { + public: + enum Registers + { + Id = Mem_layout::System_regs_map_base + 0x0, + Sw = Mem_layout::System_regs_map_base + 0x4, + Led = Mem_layout::System_regs_map_base + 0x8, + Lock = Mem_layout::System_regs_map_base + 0x20, + Flags = Mem_layout::System_regs_map_base + 0x30, + Flags_clr = Mem_layout::System_regs_map_base + 0x34, + Cnt_24mhz = Mem_layout::System_regs_map_base + 0x5c, + Pld_ctrl1 = Mem_layout::System_regs_map_base + 0x74, + Pld_ctrl2 = Mem_layout::System_regs_map_base + 0x78, + }; + }; + +}; + +IMPLEMENTATION[arm && realview]: + +#include "io.h" + +PUBLIC static inline NEEDS["io.h"] +void +Platform::write(enum Sys::Registers reg, Mword val) +{ Io::write(val, reg); } + +PUBLIC static inline NEEDS["io.h"] +Mword +Platform::read(enum Sys::Registers reg) +{ return Io::read(reg); } diff --git a/kernel/fiasco/src/kern/arm/bsp/realview/reset-arm-realview.cpp b/kernel/fiasco/src/kern/arm/bsp/realview/reset-arm-realview.cpp new file mode 100644 index 00000000..cb5a6c9f --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/realview/reset-arm-realview.cpp @@ -0,0 +1,51 @@ +IMPLEMENTATION [arm && realview]: + +#include "io.h" +#include "kmem.h" + +class Realview_reset +{ +public: + enum + { + LOCK = Kmem::System_regs_map_base + 0x20, + RESET = Kmem::System_regs_map_base + 0x40, + }; +}; + +// ------------------------------------------------------------------------ +IMPLEMENTATION [arm && realview && realview_eb]: + +static inline void do_reset() +{ + Io::write(0x108, Realview_reset::RESET); // the 0x100 is for Qemu +} + +// ------------------------------------------------------------------------ +IMPLEMENTATION [arm && realview && realview_pb11mp]: + +static inline void do_reset() +{ + Io::write(0x4, Realview_reset::RESET); // PORESET (0x8 would also be ok) +} + +// ------------------------------------------------------------------------ +IMPLEMENTATION [arm && realview && (realview_pbx || realview_vexpress)]: + +static inline void do_reset() +{ + Io::write(0x104, Realview_reset::RESET); // POWER reset, 0x100 for Qemu +} + +// ------------------------------------------------------------------------ +IMPLEMENTATION [arm && realview]: + +void __attribute__ ((noreturn)) +platform_reset(void) +{ + Io::write(0xa05f, Realview_reset::LOCK); // unlock for reset + do_reset(); + + for (;;) + ; +} diff --git a/kernel/fiasco/src/kern/arm/bsp/realview/timer-arm-mptimer-realview.cpp b/kernel/fiasco/src/kern/arm/bsp/realview/timer-arm-mptimer-realview.cpp new file mode 100644 index 00000000..0106124b --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/realview/timer-arm-mptimer-realview.cpp @@ -0,0 +1,28 @@ +// -------------------------------------------------------------------------- +IMPLEMENTATION[arm && mptimer]: + +PRIVATE static Mword Timer::interval() +{ + Mword v = Io::read(Timer_sp804::System_control); + v |= Timer_sp804::Timclk << Timer_sp804::Timer0_enable; + Io::write(v, Timer_sp804::System_control); + + Mword frequency = 1000000; + Mword timer_start = ~0UL; + unsigned factor = 5; + Mword sp_c = timer_start - frequency / 1000 * (1 << factor); + + Io::write(0, Timer_sp804::Ctrl_0); + Io::write(timer_start, Timer_sp804::Value_0); + Io::write(timer_start, Timer_sp804::Load_0); + Io::write( Timer_sp804::Ctrl_enable + | Timer_sp804::Ctrl_periodic, + Timer_sp804::Ctrl_0); + + Mword vc = start_as_counter(); + while (sp_c < Io::read(Timer_sp804::Value_0)) + ; + Mword interval = (vc - stop_counter()) >> factor; + Io::write(0, Timer_sp804::Ctrl_0); + return interval; +} diff --git a/kernel/fiasco/src/kern/arm/bsp/realview/timer-arm-realview.cpp b/kernel/fiasco/src/kern/arm/bsp/realview/timer-arm-realview.cpp new file mode 100644 index 00000000..8cbd1405 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/realview/timer-arm-realview.cpp @@ -0,0 +1,129 @@ +// -------------------------------------------------------------------------- +INTERFACE [arm]: + +#include "kmem.h" + +class Timer_sp804 +{ +public: + enum { + System_control = Kmem::System_ctrl_map_base, + + Refclk = 0, + Timclk = 1, + + Timer0_enable = 15, + Timer1_enable = 17, + Timer2_enable = 19, + Timer3_enable = 21, + + Timer_load = 0x00, + Timer_value = 0x04, + Timer_ctrl = 0x08, + Timer_intclr = 0x0c, + + Load_0 = Kmem::Timer0_map_base + Timer_load, + Load_1 = Kmem::Timer1_map_base + Timer_load, + Load_2 = Kmem::Timer2_map_base + Timer_load, + Load_3 = Kmem::Timer3_map_base + Timer_load, + + Value_0 = Kmem::Timer0_map_base + Timer_value, + Value_1 = Kmem::Timer1_map_base + Timer_value, + Value_2 = Kmem::Timer2_map_base + Timer_value, + Value_3 = Kmem::Timer3_map_base + Timer_value, + + Ctrl_0 = Kmem::Timer0_map_base + Timer_ctrl, + Ctrl_1 = Kmem::Timer1_map_base + Timer_ctrl, + Ctrl_2 = Kmem::Timer2_map_base + Timer_ctrl, + Ctrl_3 = Kmem::Timer3_map_base + Timer_ctrl, + + Intclr_0 = Kmem::Timer0_map_base + Timer_intclr, + Intclr_1 = Kmem::Timer1_map_base + Timer_intclr, + Intclr_2 = Kmem::Timer2_map_base + Timer_intclr, + Intclr_3 = Kmem::Timer3_map_base + Timer_intclr, + + Interval = 1000, + + Ctrl_ie = 1 << 5, + Ctrl_periodic = 1 << 6, + Ctrl_enable = 1 << 7, + }; +}; + +// -------------------------------------------------------------------------- +INTERFACE [arm && sp804]: + +EXTENSION class Timer +{ +public: + static unsigned irq() { return 36; } + +private: + enum { + Interval = 1000, + }; +}; + +// ----------------------------------------------------------------------- +IMPLEMENTATION [arm && sp804]: + +#include "config.h" +#include "kip.h" +#include "io.h" + +#include + +IMPLEMENT +void Timer::init(unsigned) +{ + Mword v = Io::read(Timer_sp804::System_control); + v |= Timer_sp804::Timclk << Timer_sp804::Timer0_enable; + Io::write(v, Timer_sp804::System_control); + + // all timers off + Io::write(0, Timer_sp804::Ctrl_0); + Io::write(0, Timer_sp804::Ctrl_1); + Io::write(0, Timer_sp804::Ctrl_2); + Io::write(0, Timer_sp804::Ctrl_3); + + Io::write(Interval, Timer_sp804::Load_0); + Io::write(Interval, Timer_sp804::Value_0); + Io::write (Timer_sp804::Ctrl_enable + | Timer_sp804::Ctrl_periodic + | Timer_sp804::Ctrl_ie, + Timer_sp804::Ctrl_0); +} + +static inline +Unsigned64 +Timer::timer_to_us(Unsigned32 /*cr*/) +{ return 0; } + +static inline +Unsigned64 +Timer::us_to_timer(Unsigned64 us) +{ (void)us; return 0; } + +PUBLIC static inline NEEDS["io.h"] +void +Timer::acknowledge() +{ + Io::write(0, Timer_sp804::Intclr_0); +} + +IMPLEMENT inline +void +Timer::update_one_shot(Unsigned64 wakeup) +{ + (void)wakeup; +} + +IMPLEMENT inline NEEDS["config.h", "kip.h"] +Unsigned64 +Timer::system_clock() +{ + if (Config::Scheduler_one_shot) + return 0; + else + return Kip::k()->clock; +} diff --git a/kernel/fiasco/src/kern/arm/bsp/realview/uart-arm-realview.cpp b/kernel/fiasco/src/kern/arm/bsp/realview/uart-arm-realview.cpp new file mode 100644 index 00000000..9572d744 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/realview/uart-arm-realview.cpp @@ -0,0 +1,24 @@ +IMPLEMENTATION [realview && (!(mpcore || armca9) || realview_pbx)]: + +IMPLEMENT int Uart::irq() const { return 44; } + +IMPLEMENTATION [realview && (mpcore || armca9) && !realview_pbx && !realview_vexpress]: + +IMPLEMENT int Uart::irq() const { return 36; } + +IMPLEMENTATION [realview && realview_vexpress]: + +IMPLEMENT int Uart::irq() const { return 37; } + +IMPLEMENTATION: // -------------------------------------------------------- + +#include "mem_layout.h" +#include "uart_pl011.h" + +IMPLEMENT Address Uart::base() const { return Mem_layout::Uart_base; } + +IMPLEMENT L4::Uart *Uart::uart() +{ + static L4::Uart_pl011 uart; + return &uart; +} diff --git a/kernel/fiasco/src/kern/arm/bsp/s3c/Kconfig b/kernel/fiasco/src/kern/arm/bsp/s3c/Kconfig new file mode 100644 index 00000000..7ae57fca --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/s3c/Kconfig @@ -0,0 +1,4 @@ +# PF: S3C2410 +# PFDESCR: Samsung S3C2410 Platform +# PFDEPENDS: ARM +# PFCAN: CAN_ARM_CPU_920T diff --git a/kernel/fiasco/src/kern/arm/bsp/s3c/Modules b/kernel/fiasco/src/kern/arm/bsp/s3c/Modules new file mode 100644 index 00000000..fea89534 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/s3c/Modules @@ -0,0 +1,17 @@ +# vim:set ft=make: + +SUBSYSTEMS += LIBUART +OBJECTS_LIBUART += uart_s3c2410.o +PREPROCESS_PARTS += libuart s3c2410 generic_tickless_idle +CONFIG_KERNEL_LOAD_ADDR := 0x30000000 + +uart_IMPL += uart-s3c2410 +config_IMPL += config-arm-s3c2410 +mem_layout_IMPL += mem_layout-arm-s3c2410 +pic_IMPL += pic-arm-s3c2410 +bootstrap_IMPL += bootstrap-arm-s3c2410 +timer_IMPL += timer-arm-s3c2410 +timer_tick_IMPL += timer_tick-single-vector +kernel_uart_IMPL += kernel_uart-arm-s3c2410 +reset_IMPL += reset-arm-s3c2410 +clock_IMPL += clock-generic diff --git a/kernel/fiasco/src/kern/arm/bsp/s3c/bootstrap-arm-s3c2410.cpp b/kernel/fiasco/src/kern/arm/bsp/s3c/bootstrap-arm-s3c2410.cpp new file mode 100644 index 00000000..a8194f0c --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/s3c/bootstrap-arm-s3c2410.cpp @@ -0,0 +1,24 @@ +//----------------------------------------------------------------------------- +INTERFACE [arm && s3c2410]: + +enum { + Cache_flush_area = 0x0, +}; + + +//----------------------------------------------------------------------------- +IMPLEMENTATION [arm && s3c2410]: + +void +map_hw(void *pd) +{ + // map UART + map_1mb(pd, Mem_layout::Uart_map_base, Mem_layout::Uart_phys_base, false, false); + // map Timer + map_1mb(pd, Mem_layout::Timer_map_base, Mem_layout::Timer_phys_base, false, false); + // map Pic + map_1mb(pd, Mem_layout::Pic_map_base, Mem_layout::Pic_phys_base, false, false); + + // map watchdog + map_1mb(pd, Mem_layout::Watchdog_map_base, Mem_layout::Watchdog_phys_base, false, false); +} diff --git a/kernel/fiasco/src/kern/arm/bsp/s3c/config-arm-s3c2410.cpp b/kernel/fiasco/src/kern/arm/bsp/s3c/config-arm-s3c2410.cpp new file mode 100644 index 00000000..fd41a3e7 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/s3c/config-arm-s3c2410.cpp @@ -0,0 +1,3 @@ +INTERFACE [arm && s3c2410]: + +#define TARGET_NAME "S3C2410" diff --git a/kernel/fiasco/src/kern/arm/bsp/s3c/kernel_uart-arm-s3c2410.cpp b/kernel/fiasco/src/kern/arm/bsp/s3c/kernel_uart-arm-s3c2410.cpp new file mode 100644 index 00000000..8dc38237 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/s3c/kernel_uart-arm-s3c2410.cpp @@ -0,0 +1,12 @@ +INTERFACE: + +// On ARM the MMIO for the uart is accessible before the MMU is fully up +EXTENSION class Kernel_uart { enum { Bsp_init_mode = Init_before_mmu }; }; + +IMPLEMENTATION [arm && s3c2410 && serial]: + +IMPLEMENT +bool Kernel_uart::startup(unsigned, int) +{ + return Uart::startup(); +} diff --git a/kernel/fiasco/src/kern/arm/bsp/s3c/mem_layout-arm-s3c2410.cpp b/kernel/fiasco/src/kern/arm/bsp/s3c/mem_layout-arm-s3c2410.cpp new file mode 100644 index 00000000..9fd3edab --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/s3c/mem_layout-arm-s3c2410.cpp @@ -0,0 +1,22 @@ +INTERFACE [arm && s3c2410]: //---------------------------------------------- + +EXTENSION class Mem_layout +{ +public: + enum Virt_layout_s3c2410 { + Uart_map_base = 0xef100000, + Timer_map_base = 0xef200000, + Pic_map_base = 0xef300000, + Watchdog_map_base = 0xef400000, + Uart_base = Uart_map_base, + }; + + enum Phys_layout { + Uart_phys_base = 0x50000000, + Timer_phys_base = 0x51000000, + Pic_phys_base = 0x4a000000, + Watchdog_phys_base = 0x53000000, + Sdram_phys_base = 0x30000000, + Flush_area_phys_base = 0xe0000000, + }; +}; diff --git a/kernel/fiasco/src/kern/arm/bsp/s3c/pic-arm-s3c2410.cpp b/kernel/fiasco/src/kern/arm/bsp/s3c/pic-arm-s3c2410.cpp new file mode 100644 index 00000000..a89d122c --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/s3c/pic-arm-s3c2410.cpp @@ -0,0 +1,254 @@ +INTERFACE [arm && s3c2410]: + +#include "kmem.h" + +EXTENSION class Pic +{ +public: + enum + { + SRCPND = Kmem::Pic_map_base + 0x00, + INTMODE = Kmem::Pic_map_base + 0x04, + INTMSK = Kmem::Pic_map_base + 0x08, + PRIORITY = Kmem::Pic_map_base + 0x0c, + INTPND = Kmem::Pic_map_base + 0x10, + INTOFFSET = Kmem::Pic_map_base + 0x14, + SUBSRCPND = Kmem::Pic_map_base + 0x18, + INTSUBMSK = Kmem::Pic_map_base + 0x1c, + }; + + enum + { + MAIN_0 = 0, + MAIN_EINT4_7 = 4, + MAIN_EINT8_23 = 5, + MAIN_UART2 = 15, + MAIN_LCD = 16, + MAIN_UART1 = 23, + MAIN_UART0 = 28, + MAIN_ADC = 31, + MAIN_31 = 31, + + SUB_RXD0 = 0, + SUB_TXD0 = 1, + SUB_ERR0 = 2, + SUB_RXD1 = 3, + SUB_TXD1 = 4, + SUB_ERR1 = 5, + SUB_RXD2 = 6, + SUB_TXD2 = 7, + SUB_ERR2 = 8, + SUB_TC = 9, + SUB_ADC = 10, + }; + + enum // Interrupts + { + // EINT4_7 + EINT4 = 32, + EINT7 = 35, + // EINT8_23 + EINT8 = 36, + EINT23 = 51, + // UART2 + INT_UART2_ERR = 52, + INT_UART2_RXD = 53, + INT_UART2_TXD = 54, + // LCD + INT_LCD_FRSYN = 55, + INT_LCD_FICNT = 56, + // UART1 + INT_UART1_ERR = 57, + INT_UART1_RXD = 58, + INT_UART1_TXD = 59, + // UART0 + INT_UART0_ERR = 60, + INT_UART0_RXD = 61, + INT_UART0_TXD = 62, + // ADC + INT_ADC = 63, + INT_TC = 64, + }; +}; + +// --------------------------------------------------------------------- +IMPLEMENTATION [arm && s3c2410]: + +#include "config.h" +#include "io.h" +#include "irq_chip_generic.h" +#include "irq_mgr.h" + +#include + +class S3c_chip : public Irq_chip_gen +{ +public: + S3c_chip() : Irq_chip_gen(32) {} + unsigned set_mode(Mword, unsigned) { return Irq_base::Trigger_level; } + void set_cpu(Mword, unsigned) {} +}; + + +PUBLIC +void +S3c_chip::mask(Mword irq) +{ + Mword mainirq; + + switch (irq) + { + case Pic::INT_TC: Io::set(1 << Pic::SUB_TC, Pic::INTSUBMSK); mainirq = Pic::MAIN_ADC; break; + case Pic::INT_ADC: Io::set(1 << Pic::SUB_ADC, Pic::INTSUBMSK); mainirq = Pic::MAIN_ADC; break; + case Pic::INT_UART0_RXD: Io::set(1 << Pic::SUB_RXD0, Pic::INTSUBMSK); mainirq = Pic::MAIN_UART0; break; + case Pic::INT_UART0_TXD: Io::set(1 << Pic::SUB_TXD0, Pic::INTSUBMSK); mainirq = Pic::MAIN_UART0; break; + case Pic::INT_UART0_ERR: Io::set(1 << Pic::SUB_ERR0, Pic::INTSUBMSK); mainirq = Pic::MAIN_UART0; break; + case Pic::INT_UART1_RXD: Io::set(1 << Pic::SUB_RXD1, Pic::INTSUBMSK); mainirq = Pic::MAIN_UART1; break; + case Pic::INT_UART1_TXD: Io::set(1 << Pic::SUB_TXD1, Pic::INTSUBMSK); mainirq = Pic::MAIN_UART1; break; + case Pic::INT_UART1_ERR: Io::set(1 << Pic::SUB_ERR1, Pic::INTSUBMSK); mainirq = Pic::MAIN_UART1; break; + case Pic::INT_UART2_RXD: Io::set(1 << Pic::SUB_RXD2, Pic::INTSUBMSK); mainirq = Pic::MAIN_UART2; break; + case Pic::INT_UART2_TXD: Io::set(1 << Pic::SUB_TXD2, Pic::INTSUBMSK); mainirq = Pic::MAIN_UART2; break; + case Pic::INT_UART2_ERR: Io::set(1 << Pic::SUB_ERR2, Pic::INTSUBMSK); mainirq = Pic::MAIN_UART2; break; + default: + if (irq > 31) + return; // XXX: need to add other cases + mainirq = irq; + }; + + Io::set(1 << mainirq, Pic::INTMSK); +} + +PUBLIC +void +S3c_chip::unmask(Mword irq) +{ + int mainirq; + + switch (irq) + { + case Pic::INT_TC: Io::clear(1 << Pic::SUB_TC, Pic::INTSUBMSK); mainirq = Pic::MAIN_ADC; break; + case Pic::INT_ADC: Io::clear(1 << Pic::SUB_ADC, Pic::INTSUBMSK); mainirq = Pic::MAIN_ADC; break; + case Pic::INT_UART0_RXD: Io::clear(1 << Pic::SUB_RXD0, Pic::INTSUBMSK); mainirq = Pic::MAIN_UART0; break; + case Pic::INT_UART0_TXD: Io::clear(1 << Pic::SUB_TXD0, Pic::INTSUBMSK); mainirq = Pic::MAIN_UART0; break; + case Pic::INT_UART0_ERR: Io::clear(1 << Pic::SUB_ERR0, Pic::INTSUBMSK); mainirq = Pic::MAIN_UART0; break; + case Pic::INT_UART1_RXD: Io::clear(1 << Pic::SUB_RXD1, Pic::INTSUBMSK); mainirq = Pic::MAIN_UART1; break; + case Pic::INT_UART1_TXD: Io::clear(1 << Pic::SUB_TXD1, Pic::INTSUBMSK); mainirq = Pic::MAIN_UART1; break; + case Pic::INT_UART1_ERR: Io::clear(1 << Pic::SUB_ERR1, Pic::INTSUBMSK); mainirq = Pic::MAIN_UART1; break; + case Pic::INT_UART2_RXD: Io::clear(1 << Pic::SUB_RXD2, Pic::INTSUBMSK); mainirq = Pic::MAIN_UART2; break; + case Pic::INT_UART2_TXD: Io::clear(1 << Pic::SUB_TXD2, Pic::INTSUBMSK); mainirq = Pic::MAIN_UART2; break; + case Pic::INT_UART2_ERR: Io::clear(1 << Pic::SUB_ERR2, Pic::INTSUBMSK); mainirq = Pic::MAIN_UART2; break; + default: + if (irq > 31) + return; // XXX: need to add other cases + mainirq = irq; + }; + + Io::clear(1 << mainirq, Pic::INTMSK); +} + +PUBLIC +void +S3c_chip::ack(Mword irq) +{ + int mainirq; + + switch (irq) + { + case Pic::INT_TC: Io::write(1 << Pic::SUB_TC, Pic::SUBSRCPND); mainirq = Pic::MAIN_ADC; break; + case Pic::INT_ADC: Io::write(1 << Pic::SUB_ADC, Pic::SUBSRCPND); mainirq = Pic::MAIN_ADC; break; + case Pic::INT_UART0_RXD: Io::write(1 << Pic::SUB_RXD0, Pic::SUBSRCPND); mainirq = Pic::MAIN_UART0; break; + case Pic::INT_UART0_TXD: Io::write(1 << Pic::SUB_TXD0, Pic::SUBSRCPND); mainirq = Pic::MAIN_UART0; break; + case Pic::INT_UART0_ERR: Io::write(1 << Pic::SUB_ERR0, Pic::SUBSRCPND); mainirq = Pic::MAIN_UART0; break; + case Pic::INT_UART1_RXD: Io::write(1 << Pic::SUB_RXD1, Pic::SUBSRCPND); mainirq = Pic::MAIN_UART1; break; + case Pic::INT_UART1_TXD: Io::write(1 << Pic::SUB_TXD1, Pic::SUBSRCPND); mainirq = Pic::MAIN_UART1; break; + case Pic::INT_UART1_ERR: Io::write(1 << Pic::SUB_ERR1, Pic::SUBSRCPND); mainirq = Pic::MAIN_UART1; break; + case Pic::INT_UART2_RXD: Io::write(1 << Pic::SUB_RXD2, Pic::SUBSRCPND); mainirq = Pic::MAIN_UART2; break; + case Pic::INT_UART2_TXD: Io::write(1 << Pic::SUB_TXD2, Pic::SUBSRCPND); mainirq = Pic::MAIN_UART2; break; + case Pic::INT_UART2_ERR: Io::write(1 << Pic::SUB_ERR2, Pic::SUBSRCPND); mainirq = Pic::MAIN_UART2; break; + default: + if (irq > 31) + return; // XXX: need to add other cases + mainirq = irq; + }; + + Io::write(1 << mainirq, Pic::SRCPND); // only 1s are set to 0 + Io::write(1 << mainirq, Pic::INTPND); // clear pending interrupt +} + +PUBLIC +void +S3c_chip::mask_and_ack(Mword irq) +{ + assert(cpu_lock.test()); + mask(irq); + ack(irq); +} + + +static Static_object > mgr; + + +IMPLEMENT FIASCO_INIT +void Pic::init() +{ + Irq_mgr::mgr = mgr.construct(); + + Io::write(0xffffffff, INTMSK); // all masked + Io::write(0x7fe, INTSUBMSK); // all masked + Io::write(0, INTMODE); // all IRQs, no FIQs + Io::write(Io::read(SRCPND), SRCPND); // clear source pending + Io::write(Io::read(SUBSRCPND), SUBSRCPND); // clear sub src pnd + Io::write(Io::read(INTPND), INTPND); // clear pending interrupt +} + + +IMPLEMENT inline +Pic::Status Pic::disable_all_save() +{ + Status s = 0; + return s; +} + +IMPLEMENT inline +void Pic::restore_all(Status) +{} + +PUBLIC static inline NEEDS["io.h"] +Unsigned32 Pic::pending() +{ + int mainirq = Io::read(INTOFFSET); + + switch (mainirq) + { + case MAIN_ADC: + { + int subirq = Io::read(SUBSRCPND); + if ((1 << SUB_ADC) & subirq) + return INT_ADC; + else if ((1 << SUB_TC) & subirq) + return INT_TC; + } + break; + // more: tbd + default: + return mainirq; + } + return 32; +} + +extern "C" +void irq_handler() +{ + Unsigned32 i = Pic::pending(); + if (i != 32) + mgr->c.handle_irq(i, 0); +} + +//--------------------------------------------------------------------------- +IMPLEMENTATION [debug && s3c2410]: + +PUBLIC +char const * +S3c_chip::chip_type() const +{ return "HW S3C2410 IRQ"; } + diff --git a/kernel/fiasco/src/kern/arm/bsp/s3c/reset-arm-s3c2410.cpp b/kernel/fiasco/src/kern/arm/bsp/s3c/reset-arm-s3c2410.cpp new file mode 100644 index 00000000..79fdff4f --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/s3c/reset-arm-s3c2410.cpp @@ -0,0 +1,28 @@ +IMPLEMENTATION [arm && s3c2410]: + +#include "io.h" +#include "kmem.h" + +void __attribute__ ((noreturn)) +platform_reset(void) +{ + enum { + WTCON = Kmem::Watchdog_map_base + 0x0, + WTDAT = Kmem::Watchdog_map_base + 0x4, + WTCNT = Kmem::Watchdog_map_base + 0x8, + + WTCON_RST_EN = 1 << 0, + WTCON_EN = 1 << 5, + WTCON_PRESCALER = (0x10 << 8), + }; + + Io::write(0, WTCON); // disable + Io::write(200, WTDAT); // set initial values + Io::write(200, WTCNT); + + Io::write(WTCON_RST_EN | WTCON_EN | WTCON_PRESCALER, WTCON); + + // we should reboot now + while (1) + ; +} diff --git a/kernel/fiasco/src/kern/arm/bsp/s3c/timer-arm-s3c2410.cpp b/kernel/fiasco/src/kern/arm/bsp/s3c/timer-arm-s3c2410.cpp new file mode 100644 index 00000000..592a53fa --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/s3c/timer-arm-s3c2410.cpp @@ -0,0 +1,83 @@ +INTERFACE [arm && s3c2410]: + +#include "kmem.h" + +EXTENSION class Timer +{ +public: + static unsigned irq() { return 14; } + +private: + enum { + TCFG0 = Kmem::Timer_map_base + 0x00, + TCFG1 = Kmem::Timer_map_base + 0x04, + TCON = Kmem::Timer_map_base + 0x08, + TCNTB0 = Kmem::Timer_map_base + 0x0c, + TCMPB0 = Kmem::Timer_map_base + 0x10, + TCNTO0 = Kmem::Timer_map_base + 0x14, + TCNTB1 = Kmem::Timer_map_base + 0x18, + TCMPB1 = Kmem::Timer_map_base + 0x1c, + TCNTO1 = Kmem::Timer_map_base + 0x20, + TCNTB2 = Kmem::Timer_map_base + 0x24, + TCMPB2 = Kmem::Timer_map_base + 0x28, + TCNTO2 = Kmem::Timer_map_base + 0x2c, + TCNTB3 = Kmem::Timer_map_base + 0x30, + TCMPB3 = Kmem::Timer_map_base + 0x34, + TCNTO3 = Kmem::Timer_map_base + 0x38, + TCNTB4 = Kmem::Timer_map_base + 0x3c, + TCNTO4 = Kmem::Timer_map_base + 0x40, + + }; +}; + +// ----------------------------------------------------------------------- +IMPLEMENTATION [arm && s3c2410]: + +#include "config.h" +#include "kip.h" +#include "io.h" + +#include + +IMPLEMENT +void Timer::init(unsigned) +{ + Io::write(0, TCFG0); // prescaler config + Io::write(0, TCFG1); // mux select + Io::write(33333, TCNTB4); // reload value + + Io::write(5 << 20, TCON); // start + autoreload +} + +PUBLIC static inline +void +Timer::acknowledge() +{} + +static inline +Unsigned64 +Timer::timer_to_us(Unsigned32 /*cr*/) +{ return 0; } + +static inline +Unsigned64 +Timer::us_to_timer(Unsigned64 us) +{ (void)us; return 0; } + +IMPLEMENT inline +void +Timer::update_one_shot(Unsigned64 wakeup) +{ + (void)wakeup; +} + +IMPLEMENT inline NEEDS["config.h", "kip.h", "io.h", Timer::timer_to_us] +Unsigned64 +Timer::system_clock() +{ + if (Config::Scheduler_one_shot) + //return Kip::k()->clock + timer_to_us(Io::read(OSCR)); + return 0; + else + return Kip::k()->clock; +} diff --git a/kernel/fiasco/src/kern/arm/bsp/s3c/uart-s3c2410.cpp b/kernel/fiasco/src/kern/arm/bsp/s3c/uart-s3c2410.cpp new file mode 100644 index 00000000..fd7f50b5 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/s3c/uart-s3c2410.cpp @@ -0,0 +1,14 @@ +IMPLEMENTATION [s3c2410]: + +#include "uart_s3c2410.h" +#include "mem_layout.h" + +IMPLEMENT Address Uart::base() const { return Mem_layout::Uart_base; } + +IMPLEMENT int Uart::irq() const { return 28; } + +IMPLEMENT L4::Uart *Uart::uart() +{ + static L4::Uart_s3c2410 uart; + return &uart; +} diff --git a/kernel/fiasco/src/kern/arm/bsp/sa1100/Kconfig b/kernel/fiasco/src/kern/arm/bsp/sa1100/Kconfig new file mode 100644 index 00000000..1583fb5f --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/sa1100/Kconfig @@ -0,0 +1,4 @@ +# PF: SA1100 +# PFDESCR: Intel StrongARM +# PFCAN: CAN_ARM_CPU_SA1100 +# PFDEPENDS: ARM diff --git a/kernel/fiasco/src/kern/arm/bsp/sa1100/Modules b/kernel/fiasco/src/kern/arm/bsp/sa1100/Modules new file mode 100644 index 00000000..ffb338ce --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/sa1100/Modules @@ -0,0 +1,16 @@ +# vim:set ft=make: + +PREPROCESS_PARTS += sa1100 vcache armv5 kern_start_0xd generic_tickless_idle +CONFIG_KERNEL_LOAD_ADDR := 0xc0000000 +VPATH += kern/arm/bsp/pxa-sa + +uart_IMPL += uart-sa1100 +config_IMPL += config-arm-pxa_sa1100 +mem_layout_IMPL += mem_layout-arm-sa1100 +pic_IMPL += pic-arm-pxa_sa1100 +bootstrap_IMPL += bootstrap-arm-sa1100 +timer_IMPL += timer-arm-pxa_sa1100 +timer_tick_IMPL += timer_tick-single-vector +kernel_uart_IMPL += kernel_uart-arm-sa1100 +reset_IMPL += reset-arm-sa1100 +clock_IMPL += clock-generic diff --git a/kernel/fiasco/src/kern/arm/bsp/sa1100/bootstrap-arm-sa1100.cpp b/kernel/fiasco/src/kern/arm/bsp/sa1100/bootstrap-arm-sa1100.cpp new file mode 100644 index 00000000..31eef57e --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/sa1100/bootstrap-arm-sa1100.cpp @@ -0,0 +1,23 @@ +//--------------------------------------------------------------------------- +INTERFACE[arm && sa1100]: + +enum { + Cache_flush_area = 0xe0000000, +}; + +//--------------------------------------------------------------------------- +IMPLEMENTATION[arm && sa1100]: + +#include "mem_layout.h" + +void +map_hw(void *pd) +{ + // map the cache flush area to 0xef000000 + map_1mb(pd, Mem_layout::Cache_flush_area, Mem_layout::Flush_area_phys_base, true, false); + // map UART + map_1mb(pd, Mem_layout::Uart_map_base, Mem_layout::Uart_phys_base, false, false); + map_1mb(pd, Mem_layout::Uart_phys_base, Mem_layout::Uart_phys_base, false, false); + // map Timer and Pic + map_1mb(pd, Mem_layout::Timer_map_base, Mem_layout::Timer_phys_base, false, false); +} diff --git a/kernel/fiasco/src/kern/arm/bsp/sa1100/kernel_uart-arm-sa1100.cpp b/kernel/fiasco/src/kern/arm/bsp/sa1100/kernel_uart-arm-sa1100.cpp new file mode 100644 index 00000000..3dbab3a7 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/sa1100/kernel_uart-arm-sa1100.cpp @@ -0,0 +1,14 @@ +INTERFACE: + +// On ARM the MMIO for the uart is accessible before the MMU is fully up +EXTENSION class Kernel_uart { enum { Bsp_init_mode = Init_before_mmu }; }; + +IMPLEMENTATION [arm && sa1100 && serial]: + +#include "mem_layout.h" + +IMPLEMENT +bool Kernel_uart::startup(unsigned port, int /*irq*/) +{ + return Uart::startup(Mem_layout::Uart_base, 17); +} diff --git a/kernel/fiasco/src/kern/arm/bsp/sa1100/mem_layout-arm-sa1100.cpp b/kernel/fiasco/src/kern/arm/bsp/sa1100/mem_layout-arm-sa1100.cpp new file mode 100644 index 00000000..578c6607 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/sa1100/mem_layout-arm-sa1100.cpp @@ -0,0 +1,23 @@ +//--------------------------------------------------------------------------- +INTERFACE [arm-sa1100]: + +EXTENSION class Mem_layout +{ +public: + enum Virt_layout_sa1100 { + Uart_map_base = 0xef100000, + Timer_map_base = 0xef200000, + Pic_map_base = 0xef250000, + Uart_base = Uart_map_base + 0x50000, + }; + + enum Phys_layout { + Uart_phys_base = 0x80050000, + Timer_phys_base = 0x90000000, + Pic_phys_base = 0x90050000, + Sdram_phys_base = 0xc0000000, + Flush_area_phys_base = 0xe0000000, + }; +}; + + diff --git a/kernel/fiasco/src/kern/arm/bsp/sa1100/reset-arm-sa1100.cpp b/kernel/fiasco/src/kern/arm/bsp/sa1100/reset-arm-sa1100.cpp new file mode 100644 index 00000000..d1920e75 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/sa1100/reset-arm-sa1100.cpp @@ -0,0 +1,15 @@ +IMPLEMENTATION [arm && sa1100]: + +#include +#include "kmem.h" +#include "io.h" + +typedef Sa1100_generic Sa1100; + +void __attribute__ ((noreturn)) +platform_reset(void) +{ + Io::write( (Mword)Sa1100::RSRR_SWR, (Address)Sa1100::RSRR ); + for (;;) + ; +} diff --git a/kernel/fiasco/src/kern/arm/bsp/tegra2/Kconfig b/kernel/fiasco/src/kern/arm/bsp/tegra2/Kconfig new file mode 100644 index 00000000..66d0ed9a --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/tegra2/Kconfig @@ -0,0 +1,4 @@ +# PF: TEGRA2 +# PFDESCR: NVIDIA Tegra 2xx platform +# PFCAN: CAN_ARM_CPU_CORTEX_A9 CAN_ARM_CACHE_L2CXX0 +# PFDEPENDS: ARM diff --git a/kernel/fiasco/src/kern/arm/bsp/tegra2/Modules b/kernel/fiasco/src/kern/arm/bsp/tegra2/Modules new file mode 100644 index 00000000..71c6144c --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/tegra2/Modules @@ -0,0 +1,19 @@ +# vim:set ft=make: + +PREPROCESS_PARTS += tegra2 16550 pic_gic mptimer generic_tickless_idle +CONFIG_KERNEL_LOAD_ADDR := 0x0 +INTERFACES_KERNEL += gic boot_mp +MPCORE_PHYS_BASE := 0x50040000 + +uart_IMPL += uart-16550 uart-16550-arm-tegra2 +config_IMPL += config-arm-tegra2 +mem_layout_IMPL += mem_layout-arm-tegra2 +pic_IMPL += pic-gic pic-arm-tegra2 +bootstrap_IMPL += bootstrap-arm-tegra2 +timer_IMPL += timer-arm-tegra2 timer-arm-mptimer +timer_tick_IMPL += timer_tick-single-vector +kernel_uart_IMPL += kernel_uart-arm-tegra2 +reset_IMPL += reset-arm-tegra2 +clock_IMPL += clock-generic +boot_mp_IMPL += boot_mp-arm-tegra2 +outer_cache_IMPL += outer_cache-arm-tegra2 diff --git a/kernel/fiasco/src/kern/arm/bsp/tegra2/boot_mp-arm-tegra2.cpp b/kernel/fiasco/src/kern/arm/bsp/tegra2/boot_mp-arm-tegra2.cpp new file mode 100644 index 00000000..8430399b --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/tegra2/boot_mp-arm-tegra2.cpp @@ -0,0 +1,48 @@ +INTERFACE [arm && mp && tegra2]: + +#include "mem_layout.h" + +class Boot_mp +{ +private: + enum + { + Reset_vector_addr = Mem_layout::Devices1_map_base + 0xf100, + Clk_rst_ctrl_clk_cpu_cmplx = Mem_layout::Devices1_map_base + 0x604c, + Clk_rst_ctrl_rst_cpu_cmplx_clr = Mem_layout::Devices1_map_base + 0x6344, + Unhalt_addr = Mem_layout::Devices1_map_base + 0x7014, + }; + + Mword _orig_reset_vector; +}; + +IMPLEMENTATION [arm && mp && tegra2]: + +#include "io.h" + +PUBLIC +void +Boot_mp::start_ap_cpus(Address phys_reset_vector) +{ + // remember original reset vector + _orig_reset_vector = Io::read(Reset_vector_addr); + + // set (temporary) new reset vector + Io::write(phys_reset_vector, Reset_vector_addr); + + // clocks on other cpu + Mword r = Io::read(Clk_rst_ctrl_clk_cpu_cmplx); + Io::write(r & ~(1 << 9), Clk_rst_ctrl_clk_cpu_cmplx); + Io::write((1 << 13) | (1 << 9) | (1 << 5) | (1 << 1), + Clk_rst_ctrl_rst_cpu_cmplx_clr); + + // kick cpu1 + Io::write(0, Unhalt_addr); +} + +PUBLIC +void +Boot_mp::cleanup() +{ + Io::write(_orig_reset_vector, Reset_vector_addr); +} diff --git a/kernel/fiasco/src/kern/arm/bsp/tegra2/bootstrap-arm-tegra2.cpp b/kernel/fiasco/src/kern/arm/bsp/tegra2/bootstrap-arm-tegra2.cpp new file mode 100644 index 00000000..eb52d614 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/tegra2/bootstrap-arm-tegra2.cpp @@ -0,0 +1,16 @@ +INTERFACE [arm && tegra2]: + +#include "mem_layout.h" + +enum { Cache_flush_area = 0, }; + +//----------------------------------------------------------------------------- +IMPLEMENTATION [arm && tegra2]: + +void +map_hw(void *pd) +{ + map_1mb(pd, Mem_layout::Devices0_map_base, Mem_layout::Devices0_phys_base, false, false); + map_1mb(pd, Mem_layout::Devices1_map_base, Mem_layout::Devices1_phys_base, false, false); + map_1mb(pd, Mem_layout::Devices2_map_base, Mem_layout::Devices2_phys_base, false, false); +} diff --git a/kernel/fiasco/src/kern/arm/bsp/tegra2/config-arm-tegra2.cpp b/kernel/fiasco/src/kern/arm/bsp/tegra2/config-arm-tegra2.cpp new file mode 100644 index 00000000..7c332c93 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/tegra2/config-arm-tegra2.cpp @@ -0,0 +1,3 @@ +INTERFACE[arm && tegra2]: + +#define TARGET_NAME "Tegra2" diff --git a/kernel/fiasco/src/kern/arm/bsp/tegra2/kernel_uart-arm-tegra2.cpp b/kernel/fiasco/src/kern/arm/bsp/tegra2/kernel_uart-arm-tegra2.cpp new file mode 100644 index 00000000..e30f7cc9 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/tegra2/kernel_uart-arm-tegra2.cpp @@ -0,0 +1,14 @@ +INTERFACE: + +// On ARM the MMIO for the uart is accessible before the MMU is fully up +EXTENSION class Kernel_uart { enum { Bsp_init_mode = Init_before_mmu }; }; + +IMPLEMENTATION [arm && tegra2 && serial]: + +#include "mem_layout.h" + +IMPLEMENT +bool Kernel_uart::startup(unsigned port, int /*irq*/) +{ + return Uart::startup(Mem_layout::Uart_base, 122); +} diff --git a/kernel/fiasco/src/kern/arm/bsp/tegra2/mem_layout-arm-tegra2.cpp b/kernel/fiasco/src/kern/arm/bsp/tegra2/mem_layout-arm-tegra2.cpp new file mode 100644 index 00000000..ff50b924 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/tegra2/mem_layout-arm-tegra2.cpp @@ -0,0 +1,30 @@ +INTERFACE [arm && tegra2]: + +EXTENSION class Mem_layout +{ +public: + enum Virt_layout_tegra2 { + + Devices0_map_base = Registers_map_start, + Devices1_map_base = Registers_map_start + 0x00100000, + Devices2_map_base = Registers_map_start + 0x00200000, + + Mp_scu_map_base = Devices2_map_base + 0x00040000, + L2cxx0_map_base = Devices2_map_base + 0x00043000, + + Gic_cpu_map_base = Devices2_map_base + 0x00040100, + Gic_dist_map_base = Devices2_map_base + 0x00041000, + Gic2_cpu_map_base = Devices2_map_base + 0x00020000, + Gic2_dist_map_base = Devices2_map_base + 0x00021000, + + Uart_base = Devices0_map_base + 0x00006300, + Clock_reset_map_base = Devices1_map_base + 0x00006000, + }; + + enum Phys_layout_tegra2 { + Devices0_phys_base = 0x70000000, + Devices1_phys_base = 0x60000000, + Devices2_phys_base = 0x50000000, + Sdram_phys_base = 0x0, + }; +}; diff --git a/kernel/fiasco/src/kern/arm/bsp/tegra2/outer_cache-arm-tegra2.cpp b/kernel/fiasco/src/kern/arm/bsp/tegra2/outer_cache-arm-tegra2.cpp new file mode 100644 index 00000000..56b760b8 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/tegra2/outer_cache-arm-tegra2.cpp @@ -0,0 +1,18 @@ +IMPLEMENTATION [arm && tegra2 && outer_cache_l2cxx0]: + +IMPLEMENT +Mword +Outer_cache::platform_init(Mword aux_control) +{ + Io::write(0x331, TAG_RAM_CONTROL); + Io::write(0x441, DATA_RAM_CONTROL); + + aux_control &= 0x8200c3fe; + aux_control |= (1 << 0) // Full Line of Zero Enable + | (4 << 17) // 128kb waysize + | (1 << 28) // data prefetch + | (1 << 29) // insn prefetch + | (1 << 30) // early BRESP enable + ; + return aux_control; +} diff --git a/kernel/fiasco/src/kern/arm/bsp/tegra2/pic-arm-tegra2.cpp b/kernel/fiasco/src/kern/arm/bsp/tegra2/pic-arm-tegra2.cpp new file mode 100644 index 00000000..f7177133 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/tegra2/pic-arm-tegra2.cpp @@ -0,0 +1,41 @@ +INTERFACE [arm && pic_gic && tegra2]: + +#include "gic.h" + +//------------------------------------------------------------------- +IMPLEMENTATION [arm && pic_gic && tegra2]: + +#include "irq_chip.h" +#include "irq_mgr_multi_chip.h" +#include "gic.h" +#include "kmem.h" + +IMPLEMENT FIASCO_INIT +void Pic::init() +{ + typedef Irq_mgr_multi_chip<8> M; + + M *m = new Boot_object(16); + + gic.construct(Kmem::Gic_cpu_map_base, Kmem::Gic_dist_map_base); + m->add_chip(0, gic, gic->nr_irqs()); + + Irq_mgr::mgr = m; +} + +IMPLEMENT inline +Pic::Status Pic::disable_all_save() +{ return 0; } + +IMPLEMENT inline +void Pic::restore_all(Status) +{} + +//------------------------------------------------------------------- +IMPLEMENTATION [arm && mp && pic_gic && tegra2]: + +PUBLIC static +void Pic::init_ap() +{ + gic->init_ap(); +} diff --git a/kernel/fiasco/src/kern/arm/bsp/tegra2/reset-arm-tegra2.cpp b/kernel/fiasco/src/kern/arm/bsp/tegra2/reset-arm-tegra2.cpp new file mode 100644 index 00000000..e7e042a1 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/tegra2/reset-arm-tegra2.cpp @@ -0,0 +1,24 @@ +IMPLEMENTATION [arm && tegra2]: + +#include "io.h" +#include "kmem.h" + +class Tegra2_reset +{ +public: + enum + { + RESET = Kmem::Clock_reset_map_base + 0x4, + }; +}; + +// ------------------------------------------------------------------------ +IMPLEMENTATION [arm && tegra2]: + +void __attribute__ ((noreturn)) +platform_reset(void) +{ + Io::write(Io::read(Tegra2_reset::RESET) | 4, Tegra2_reset::RESET); + for (;;) + ; +} diff --git a/kernel/fiasco/src/kern/arm/bsp/tegra2/timer-arm-tegra2.cpp b/kernel/fiasco/src/kern/arm/bsp/tegra2/timer-arm-tegra2.cpp new file mode 100644 index 00000000..3ddb07eb --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/tegra2/timer-arm-tegra2.cpp @@ -0,0 +1,8 @@ +// -------------------------------------------------------------------------- +INTERFACE [arm && tegra2 && mptimer]: + +EXTENSION class Timer +{ +private: + static Mword interval() { return 249999; } +}; diff --git a/kernel/fiasco/src/kern/arm/bsp/tegra2/uart-16550-arm-tegra2.cpp b/kernel/fiasco/src/kern/arm/bsp/tegra2/uart-16550-arm-tegra2.cpp new file mode 100644 index 00000000..410ee5a7 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/tegra2/uart-16550-arm-tegra2.cpp @@ -0,0 +1,20 @@ +INTERFACE [16550 && tegra2]: + +EXTENSION class Uart +{ +public: + enum { + Base_rate = 13478400, + Base_ier_bits = 1 << 6, + + Access_shift = 2, + }; +}; + +IMPLEMENTATION [16550 && tegra2]: + +IMPLEMENT inline NEEDS[Uart::mcr, Uart::ier] +void Uart::enable_rcv_irq() +{ + ier(ier() | 1); +} diff --git a/kernel/fiasco/src/kern/arm/config-arm.cpp b/kernel/fiasco/src/kern/arm/config-arm.cpp new file mode 100644 index 00000000..25795c5a --- /dev/null +++ b/kernel/fiasco/src/kern/arm/config-arm.cpp @@ -0,0 +1,87 @@ +/* ARM specific */ +INTERFACE [arm]: + +EXTENSION class Config +{ +public: + + enum + { + Access_user_mem = Must_access_user_mem_direct, + + PAGE_SHIFT = ARCH_PAGE_SHIFT, + PAGE_SIZE = 1 << PAGE_SHIFT, + PAGE_MASK = ~(PAGE_SIZE - 1), + + SUPERPAGE_SHIFT = 20, + SUPERPAGE_SIZE = 1 << SUPERPAGE_SHIFT, + SUPERPAGE_MASK = ~(SUPERPAGE_SIZE -1), + + hlt_works_ok = 1, + Irq_shortcut = 1, + }; + + enum + { +#ifdef CONFIG_ONE_SHOT + Scheduler_one_shot = 1, + Scheduler_granularity = 1UL, + Default_time_slice = 10000 * scheduler_granularity, +#else + Scheduler_one_shot = 0, + Scheduler_granularity = 1000UL, + Default_time_slice = 10 * Scheduler_granularity, +#endif + }; + + enum + { + KMEM_SIZE = 16 << 20, + }; + + // the default uart to use for serial console + static unsigned const default_console_uart = 3; + static unsigned const default_console_uart_baudrate = 115200; + + enum + { + Cache_enabled = true, + }; + static const char char_micro; + + + enum + { +#ifdef CONFIG_ARM_CA9_ENABLE_SWP + Cp15_c1_use_a9_swp_enable = 1, +#else + Cp15_c1_use_a9_swp_enable = 0, +#endif +#ifdef CONFIG_ARM_ALIGNMENT_CHECK + Cp15_c1_use_alignment_check = 1, +#else + Cp15_c1_use_alignment_check = 0, +#endif + + Support_arm_linux_cache_API = 1, + }; + +}; + +//--------------------------------------------------------------------------- +IMPLEMENTATION [arm]: + +char const Config::char_micro = '\265'; +const char *const Config::kernel_warn_config_string = 0; + +IMPLEMENT FIASCO_INIT +void +Config::init_arch() +{} + +//--------------------------------------------------------------------------- +IMPLEMENTATION [armv6plus]: + +#include "feature.h" + +KIP_KERNEL_FEATURE("armv6plus"); diff --git a/kernel/fiasco/src/kern/arm/context-arm.cpp b/kernel/fiasco/src/kern/arm/context-arm.cpp new file mode 100644 index 00000000..15a49930 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/context-arm.cpp @@ -0,0 +1,168 @@ +INTERFACE [arm]: + +EXTENSION class Context +{ +public: + void set_ignore_mem_op_in_progress(bool val); + bool is_ignore_mem_op_in_progress() const { return _ignore_mem_op_in_progess; } + +private: + bool _ignore_mem_op_in_progess; +}; + +// ------------------------------------------------------------------------ +INTERFACE [armv6plus]: + +EXTENSION class Context +{ +private: + Mword _tpidrurw; +}; + +// ------------------------------------------------------------------------ +IMPLEMENTATION [arm]: + +#include +#include + +#include "globals.h" // current() +#include "l4_types.h" +#include "cpu_lock.h" +#include "kmem.h" +#include "lock_guard.h" +#include "space.h" +#include "thread_state.h" +#include "utcb_support.h" + + +IMPLEMENT inline NEEDS[Context::load_tpidrurw] +void +Context::fill_user_state() +{ + // do not use 'Return_frame const *rf = regs();' here as it triggers an + // optimization bug in gcc-4.4(.1) + Entry_frame const *ef = regs(); + asm volatile ("ldmia %[rf], {sp, lr}^" + : : "m"(ef->usp), "m"(ef->ulr), [rf] "r" (&ef->usp)); +} + +IMPLEMENT inline NEEDS[Context::store_tpidrurw] +void +Context::spill_user_state() +{ + Entry_frame *ef = regs(); + assert_kdb (current() == this); + asm volatile ("stmia %[rf], {sp, lr}^" + : "=m"(ef->usp), "=m"(ef->ulr) : [rf] "r" (&ef->usp)); +} + + +PROTECTED inline void Context::arch_setup_utcb_ptr() {} + +IMPLEMENT inline NEEDS[Context::spill_user_state] +void +Context::switch_cpu(Context *t) +{ + update_consumed_time(); + + spill_user_state(); + store_tpidrurw(); + t->fill_user_state(); + t->load_tpidrurw(); + + { + register Mword _old_this asm("r1") = (Mword)this; + register Mword _new_this asm("r0") = (Mword)t; + unsigned long dummy1, dummy2; + + asm volatile + (// save context of old thread + " stmdb sp!, {fp} \n" + " adr lr, 1f \n" + " str lr, [sp, #-4]! \n" + " str sp, [%[old_sp]] \n" + + // switch to new stack + " mov sp, %[new_sp] \n" + + // deliver requests to new thread + " bl switchin_context_label \n" // call Context::switchin_context(Context *) + + // return to new context + " ldr pc, [sp], #4 \n" + "1: ldmia sp!, {fp} \n" + + : + "=r" (_old_this), + "=r" (_new_this), + [old_sp] "=r" (dummy1), + [new_sp] "=r" (dummy2) + : + "0" (_old_this), + "1" (_new_this), + "2" (&_kernel_sp), + "3" (t->_kernel_sp) + : "r4", "r5", "r6", "r7", "r8", "r9", + "r10", "r12", "r14", "memory"); + } +} + +/** Thread context switchin. Called on every re-activation of a + thread (switch_exec()). This method is public only because it is + called by an ``extern "C"'' function that is called + from assembly code (call_switchin_context). + */ +IMPLEMENT +void Context::switchin_context(Context *from) +{ + assert_kdb (this == current()); + assert_kdb (state() & Thread_ready_mask); + +#if 0 + printf("switch in address space: %p\n",_space); +#endif + + // switch to our page directory if nessecary + vcpu_aware_space()->switchin_context(from->vcpu_aware_space()); + + Utcb_support::current(utcb().usr()); +} + + +IMPLEMENT inline +void +Context::set_ignore_mem_op_in_progress(bool val) +{ + _ignore_mem_op_in_progess = val; + Mem::barrier(); +} + +// ------------------------------------------------------------------------ +IMPLEMENTATION [armv6plus]: + +PRIVATE inline +void +Context::store_tpidrurw() +{ + asm volatile ("mrc p15, 0, %0, c13, c0, 2" : "=r" (_tpidrurw)); +} + +PRIVATE inline +void +Context::load_tpidrurw() const +{ + asm volatile ("mcr p15, 0, %0, c13, c0, 2" : : "r" (_tpidrurw)); +} + +// ------------------------------------------------------------------------ +IMPLEMENTATION [!armv6plus]: + +PRIVATE inline +void +Context::store_tpidrurw() +{} + +PRIVATE inline +void +Context::load_tpidrurw() const +{} diff --git a/kernel/fiasco/src/kern/arm/continuation-arm.cpp b/kernel/fiasco/src/kern/arm/continuation-arm.cpp new file mode 100644 index 00000000..065cd289 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/continuation-arm.cpp @@ -0,0 +1,75 @@ +INTERFACE[arm]: + +#include "types.h" +#include "entry_frame.h" +#include "member_offs.h" +#include "processor.h" + +class Continuation +{ + MEMBER_OFFSET(); + +private: + Address _ip; + Mword _psr; + +public: + Continuation() : _ip(~0UL) {} + + typedef Return_frame User_return_frame; + + bool valid() const + { return _ip != ~0UL; } + + Address ip() const { return _ip; } + void ip(Address ip) { _ip = ip; } + + Mword flags(Return_frame const *) const { return _psr; } + void flags(Return_frame *, Mword psr) { _psr = psr; } + + Mword sp(Return_frame const *o) const { return o->usp; } + void sp(Return_frame *o, Mword sp) { o->usp = sp; } + + void save(Return_frame const *regs) + { + _ip = regs->ip(); + _psr = regs->psr; + } + + void activate(Return_frame *regs, void *cont_func) + { + save(regs); + regs->pc = Mword(cont_func); + regs->psr &= ~(Proc::Status_mode_mask | Proc::Status_thumb); // clear mode + regs->psr |= Proc::Status_mode_supervisor | Proc::Status_interrupts_disabled; + } + + void set(Return_frame *dst, User_return_frame const *src) + { + dst->usp = src->usp; + dst->ulr = src->ulr; + dst->km_lr = src->km_lr; + _ip = src->pc; + _psr = src->psr; + } + + void get(User_return_frame *dst, Return_frame const *src) const + { + dst->usp = src->usp; + dst->ulr = src->ulr; + dst->km_lr = src->km_lr; + dst->pc = _ip; + dst->psr = _psr; + } + + void clear() { _ip = ~0UL; } + + void restore(Return_frame *regs) + { + regs->pc = _ip; + regs->psr = _psr; + clear(); + } + +}; + diff --git a/kernel/fiasco/src/kern/arm/cpu-arm.cpp b/kernel/fiasco/src/kern/arm/cpu-arm.cpp new file mode 100644 index 00000000..2cb659bc --- /dev/null +++ b/kernel/fiasco/src/kern/arm/cpu-arm.cpp @@ -0,0 +1,679 @@ +INTERFACE [arm]: + +#include "io.h" +#include "mem_layout.h" +#include "mem_unit.h" +#include "types.h" +#include "per_cpu_data.h" +#include "processor.h" + +EXTENSION +class Cpu +{ +public: + void init(bool is_boot_cpu = false); + + static void early_init(); + + static Per_cpu cpus; + static Cpu *boot_cpu() { return _boot_cpu; } + + enum { + Cp15_c1_mmu = 1 << 0, + Cp15_c1_alignment_check = 1 << 1, + Cp15_c1_cache = 1 << 2, + Cp15_c1_branch_predict = 1 << 11, + Cp15_c1_insn_cache = 1 << 12, + Cp15_c1_high_vector = 1 << 13, + }; + + Cpu(unsigned id) { set_id(id); } + + + struct Ids { + Mword _pfr[2], _dfr0, _afr0, _mmfr[4]; + }; + void id_init(); + + enum { + Copro_dbg_model_not_supported = 0, + Copro_dbg_model_v6 = 2, + Copro_dbg_model_v6_1 = 3, + Copro_dbg_model_v7 = 4, + }; + + unsigned copro_dbg_model() const { return _cpu_id._dfr0 & 0xf; } + +private: + static Cpu *_boot_cpu; + + unsigned _phys_id; + Ids _cpu_id; +}; + +// ------------------------------------------------------------------------ +INTERFACE [arm && armv5]: + +EXTENSION class Cpu +{ +public: + enum { + Cp15_c1_write_buffer = 1 << 3, + Cp15_c1_prog32 = 1 << 4, + Cp15_c1_data32 = 1 << 5, + Cp15_c1_late_abort = 1 << 6, + Cp15_c1_big_endian = 1 << 7, + Cp15_c1_system_protect = 1 << 8, + Cp15_c1_rom_protect = 1 << 9, + Cp15_c1_f = 1 << 10, + Cp15_c1_rr = 1 << 14, + Cp15_c1_l4 = 1 << 15, + + Cp15_c1_generic = Cp15_c1_mmu + | (Config::Cp15_c1_use_alignment_check ? Cp15_c1_alignment_check : 0) + | Cp15_c1_write_buffer + | Cp15_c1_prog32 + | Cp15_c1_data32 + | Cp15_c1_late_abort + | Cp15_c1_rom_protect + | Cp15_c1_high_vector, + + Cp15_c1_cache_bits = Cp15_c1_cache + | Cp15_c1_insn_cache + | Cp15_c1_write_buffer, + + }; +}; + +INTERFACE [arm && armv6]: + +EXTENSION class Cpu +{ +public: + enum { + Cp15_c1_l4 = 1 << 15, + Cp15_c1_u = 1 << 22, + Cp15_c1_xp = 1 << 23, + Cp15_c1_ee = 1 << 25, + Cp15_c1_nmfi = 1 << 27, + Cp15_c1_tex = 1 << 28, + Cp15_c1_force_ap = 1 << 29, + + Cp15_c1_generic = Cp15_c1_mmu + | (Config::Cp15_c1_use_alignment_check ? Cp15_c1_alignment_check : 0) + | Cp15_c1_branch_predict + | Cp15_c1_high_vector + | Cp15_c1_u + | Cp15_c1_xp, + + Cp15_c1_cache_bits = Cp15_c1_cache + | Cp15_c1_insn_cache, + }; +}; + +INTERFACE [arm && armv7 && armca8]: + +EXTENSION class Cpu +{ +public: + enum { + Cp15_c1_ee = 1 << 25, + Cp15_c1_nmfi = 1 << 27, + Cp15_c1_te = 1 << 30, + Cp15_c1_rao_sbop = (0xf << 3) | (1 << 16) | (1 << 18) | (1 << 22) | (1 << 23), + + Cp15_c1_cache_bits = Cp15_c1_cache + | Cp15_c1_insn_cache, + + Cp15_c1_generic = Cp15_c1_mmu + | (Config::Cp15_c1_use_alignment_check ? Cp15_c1_alignment_check : 0) + | Cp15_c1_branch_predict + | Cp15_c1_rao_sbop + | Cp15_c1_high_vector, + }; +}; + +INTERFACE [arm && armv7 && armca9]: + +EXTENSION class Cpu +{ +public: + enum { + Cp15_c1_sw = 1 << 10, + Cp15_c1_ha = 1 << 17, + Cp15_c1_ee = 1 << 25, + Cp15_c1_nmfi = 1 << 27, + Cp15_c1_te = 1 << 30, + Cp15_c1_rao_sbop = (0xf << 3) | (1 << 16) | (1 << 18) | (1 << 22) | (1 << 23), + + Cp15_c1_cache_bits = Cp15_c1_cache + | Cp15_c1_insn_cache, + + Cp15_c1_generic = Cp15_c1_mmu + | (Config::Cp15_c1_use_alignment_check ? Cp15_c1_alignment_check : 0) + | Cp15_c1_branch_predict + | Cp15_c1_high_vector + | Cp15_c1_rao_sbop + | (Config::Cp15_c1_use_a9_swp_enable ? Cp15_c1_sw : 0), + }; +}; + +INTERFACE [arm]: + +EXTENSION class Cpu +{ +public: + enum { + Cp15_c1_cache_enabled = Cp15_c1_generic | Cp15_c1_cache_bits, + Cp15_c1_cache_disabled = Cp15_c1_generic, + }; +}; + +//------------------------------------------------------------------------- +IMPLEMENTATION [arm]: + +PRIVATE static inline +Mword +Cpu::midr() +{ + Mword m; + asm volatile ("mrc p15, 0, %0, c0, c0, 0" : "=r" (m)); + return m; +} + +IMPLEMENTATION [arm && armv6]: // ----------------------------------------- + +PUBLIC static inline void +Cpu::enable_smp() +{ + asm volatile ("mrc p15, 0, %0, c1, c0, 1 \n" + "orr %0, %1 \n" + "mcr p15, 0, %0, c1, c0, 1 \n" + : : "r" (0), "i" (0x20)); +} + +PUBLIC static inline void +Cpu::disable_smp() +{ + asm volatile ("mrc p15, 0, %0, c1, c0, 1 \n" + "bic %0, %1 \n" + "mcr p15, 0, %0, c1, c0, 1 \n" + : : "r" (0), "i" (0x20)); +} + +IMPLEMENTATION [arm && armv7]: //------------------------------------------ + +PUBLIC static inline NEEDS[Cpu::midr] +bool +Cpu::is_smp_capable() +{ + // ACTRL is implementation defined + return (midr() & 0xff0ffff0) == 0x410fc090; +} + +PUBLIC static inline +void +Cpu::enable_smp() +{ + if (!is_smp_capable()) + return; + + Mword actrl; + asm volatile ("mrc p15, 0, %0, c1, c0, 1" : "=r" (actrl)); + if (!(actrl & 0x40)) + asm volatile ("mcr p15, 0, %0, c1, c0, 1" : : "r" (actrl | 0x41)); +} + +PUBLIC static inline +void +Cpu::disable_smp() +{ + if (!is_smp_capable()) + return; + + asm volatile ("mrc p15, 0, %0, c1, c0, 1 \n" + "bic %0, %1 \n" + "mcr p15, 0, %0, c1, c0, 1 \n" + : : "r" (0), "i" (0x40)); +} + +//--------------------------------------------------------------------------- +IMPLEMENTATION [arm && (mpcore || armca9)]: + +PRIVATE static inline void +Cpu::early_init_platform() +{ + enum { + Scu_control = Mem_layout::Mp_scu_map_base + 0x0, + Scu_config = Mem_layout::Mp_scu_map_base + 0x4, + Scu_power_status = Mem_layout::Mp_scu_map_base + 0x8, + Scu_inv = Mem_layout::Mp_scu_map_base + 0xc, + }; + + Io::write(0xffffffff, Scu_inv); + Io::write(Io::read(Scu_control) | 1, Scu_control); + + Io::write(Io::read(Mem_layout::Gic_cpu_map_base + 0) | 1, + Mem_layout::Gic_cpu_map_base + 0); + Io::write(Io::read(Mem_layout::Gic_dist_map_base + 0) | 1, + Mem_layout::Gic_dist_map_base + 0); + + Mem_unit::clean_dcache(); + + enable_smp(); +} + +//--------------------------------------------------------------------------- +IMPLEMENTATION [arm && !(mpcore || armca9)]: + +PRIVATE static inline void Cpu::early_init_platform() +{} + +//--------------------------------------------------------------------------- +IMPLEMENTATION [arm]: + +#include +#include +#include + +#include "io.h" +#include "pagetable.h" +#include "kmem_space.h" +#include "kmem_alloc.h" +#include "mem_unit.h" +#include "processor.h" +#include "ram_quota.h" + +DEFINE_PER_CPU_P(0) Per_cpu Cpu::cpus(true); +Cpu *Cpu::_boot_cpu; + +PUBLIC static inline +Mword +Cpu::stack_align(Mword stack) +{ return stack & ~0x3; } + + +IMPLEMENT +void Cpu::early_init() +{ + // switch to supervisor mode and intialize the memory system + asm volatile ( " mov r2, r13 \n" + " mov r3, r14 \n" + " msr cpsr_c, %1 \n" + " mov r13, r2 \n" + " mov r14, r3 \n" + + " mcr p15, 0, %0, c1, c0 \n" + : + : "r" (Config::Cache_enabled + ? Cp15_c1_cache_enabled : Cp15_c1_cache_disabled), + "I" (0x0d3) + : "r2", "r3"); + + early_init_platform(); + + Mem_unit::flush_cache(); +} + + +PUBLIC static inline +bool +Cpu::have_superpages() +{ return true; } + +PUBLIC static inline +void +Cpu::debugctl_enable() +{} + +PUBLIC static inline +void +Cpu::debugctl_disable() +{} + +PUBLIC static inline NEEDS["types.h"] +Unsigned32 +Cpu::get_scaler_tsc_to_ns() +{ return 0; } + +PUBLIC static inline NEEDS["types.h"] +Unsigned32 +Cpu::get_scaler_tsc_to_us() +{ return 0; } + +PUBLIC static inline NEEDS["types.h"] +Unsigned32 +Cpu::get_scaler_ns_to_tsc() +{ return 0; } + +PUBLIC static inline +bool +Cpu::tsc() +{ return 0; } + +PUBLIC static inline +Unsigned64 +Cpu::rdtsc (void) +{ return 0; } + +PUBLIC static +void Cpu::init_mmu() +{ + extern char ivt_start; + // map the interrupt vector table to 0xffff0000 + Pte pte = Kmem_space::kdir()->walk((void*)Kmem_space::Ivt_base, 4096, + true, Kmem_alloc::q_allocator(Ram_quota::root), Kmem_space::kdir()); + + pte.set((unsigned long)&ivt_start, 4096, + Mem_page_attr(Page::KERN_RW | Page::CACHEABLE), + true); + + Mem_unit::tlb_flush(); +} + +IMPLEMENT inline +unsigned +Cpu::phys_id() const +{ return _phys_id; } + +IMPLEMENT +void +Cpu::init(bool is_boot_cpu) +{ + if (is_boot_cpu) + { + _boot_cpu = this; + set_online(1); + } + + _phys_id = Proc::cpu_id(); + + init_tz(); + id_init(); + init_errata_workarounds(); + + print_infos(); +} + +PUBLIC static inline +void +Cpu::enable_dcache() +{ + asm volatile("mrc p15, 0, %0, c1, c0, 0 \n" + "orr %0, %1 \n" + "mcr p15, 0, %0, c1, c0, 0 \n" + : : "r" (0), "i" (1 << 2)); +} + +PUBLIC static inline +void +Cpu::disable_dcache() +{ + asm volatile("mrc p15, 0, %0, c1, c0, 0 \n" + "bic %0, %1 \n" + "mcr p15, 0, %0, c1, c0, 0 \n" + : : "r" (0), "i" (1 << 2)); +} + +//--------------------------------------------------------------------------- +IMPLEMENTATION [arm && !armv6plus]: + +IMPLEMENT +void +Cpu::id_init() +{ +} + +PRIVATE static inline +void Cpu::init_errata_workarounds() {} + +//--------------------------------------------------------------------------- +IMPLEMENTATION [arm && armv6plus]: + +PRIVATE static inline +void +Cpu::set_actrl(Mword bit_mask) +{ + Mword t; + asm volatile("mrc p15, 0, %0, c1, c0, 1 \n\t" + "orr %0, %0, %1 \n\t" + "mcr p15, 0, %0, c1, c0, 1 \n\t" + : "=r"(t) : "r" (bit_mask)); +} + +PRIVATE static inline +void +Cpu::set_c15_c0_1(Mword bits_mask) +{ + Mword t; + asm volatile("mrc p15, 0, %0, c15, c0, 1 \n\t" + "orr %0, %0, %1 \n\t" + "mcr p15, 0, %0, c15, c0, 1 \n\t" + : "=r"(t) : "r" (bits_mask)); +} + +PRIVATE static inline NEEDS[Cpu::midr] +void +Cpu::init_errata_workarounds() +{ + Mword mid = midr(); + + if ((mid & 0xff000000) == 0x41000000) // ARM CPU + { + Mword rev = ((mid & 0x00f00000) >> 16) | (mid & 0x0f); + Mword part = (mid & 0x0000fff0) >> 4; + + if (part == 0xc08) // Cortex A8 + { + // errata: 430973 + if ((rev & 0xf0) == 0x10) + set_actrl(1 << 6); // IBE to 1 + + // errata: 458693 + if (rev == 0x20) + set_actrl((1 << 5) | (1 << 9)); // L1NEON & PLDNOP + + // errata: 460075 + if (rev == 0x20) + { + Mword t; + asm volatile ("mrc p15, 1, %0, c9, c0, 2 \n\t" + "orr %0, %0, #1 << 22 \n\t" // Write alloc disable + "mcr p15, 1, %0, c9, c0, 2 \n\t" : "=r"(t)); + } + } + + if (part == 0xc09) // Cortex A9 + { + // errata: 742230 (DMB errata) + // make DMB a DSB to fix behavior + if (rev <= 0x22) // <= r2p2 + set_c15_c0_1(1 << 4); + + // errata: 742231 + if (rev == 0x20 || rev == 0x21 || rev == 0x22) + set_c15_c0_1((1 << 12) | (1 << 22)); + + // errata: 743622 + if ((rev & 0xf0) == 0x20) + set_c15_c0_1(1 << 6); + + // errata: 751472 + if (rev < 0x30) + set_c15_c0_1(1 << 11); + } + } +} + +IMPLEMENT +void +Cpu::id_init() +{ + __asm__("mrc p15, 0, %0, c0, c1, 0": "=r" (_cpu_id._pfr[0])); + __asm__("mrc p15, 0, %0, c0, c1, 1": "=r" (_cpu_id._pfr[1])); + __asm__("mrc p15, 0, %0, c0, c1, 2": "=r" (_cpu_id._dfr0)); + __asm__("mrc p15, 0, %0, c0, c1, 3": "=r" (_cpu_id._afr0)); + __asm__("mrc p15, 0, %0, c0, c1, 4": "=r" (_cpu_id._mmfr[0])); + __asm__("mrc p15, 0, %0, c0, c1, 5": "=r" (_cpu_id._mmfr[1])); + __asm__("mrc p15, 0, %0, c0, c1, 6": "=r" (_cpu_id._mmfr[2])); + __asm__("mrc p15, 0, %0, c0, c1, 7": "=r" (_cpu_id._mmfr[3])); +} + +//--------------------------------------------------------------------------- +IMPLEMENTATION [arm && !tz]: + +PRIVATE static inline +void +Cpu::init_tz() +{} + +//--------------------------------------------------------------------------- +INTERFACE [arm && tz]: + +EXTENSION class Cpu +{ +public: + + static char monitor_vector_base asm ("monitor_vector_base"); +}; + +//--------------------------------------------------------------------------- +IMPLEMENTATION [arm && tz]: + +#include + +PRIVATE inline NEEDS[] +void +Cpu::init_tz() +{ + // set monitor vector base address + assert(!((Mword)&monitor_vector_base & 31)); + tz_mvbar((Mword)&monitor_vector_base); + + // enable nonsecure access to vfp coprocessor + asm volatile("mov r0, #0xc00;" + "mcr p15, 0, r0, c1, c1, 2;" + : : : "r0" + ); + + enable_irq_ovrr(); +} + +PUBLIC inline +void +Cpu::tz_switch_to_ns(Mword *nonsecure_state) +{ + volatile register Mword r0 asm("r0") = (Mword)nonsecure_state; + extern char go_nonsecure; + + asm volatile("stmdb sp!, {fp} \n" + "stmdb sp!, {r0} \n" + "mov r2, sp \n" // copy sp_svc to sp_mon + "cps #0x16 \n" // switch to monitor mode + "mov sp, r2 \n" + "adr r3, 1f \n" // save return eip + "mrs r4, cpsr \n" // save return psr + "mov pc, r1 \n" // go nonsecure! + "1: \n" + "mov r0, sp \n" // copy sp_mon to sp_svc + "cps #0x13 \n" // switch to svc mode + "mov sp, r0 \n" + "ldmia sp!, {r0} \n" + "ldmia sp!, {fp} \n" + : : "r" (r0), "r" (&go_nonsecure) + : "r2", "r3", "r4", "r5", "r6", "r7", + "r8", "r9", "r10", "r12", "r14", "memory"); +} + +PUBLIC static inline +Mword +Cpu::tz_scr() +{ + Mword r; + asm volatile ("mrc p15, 0, %0, c1, c1, 0" : "=r" (r)); + return r; +} + +PUBLIC static inline +void +Cpu::tz_scr(Mword val) +{ + asm volatile ("mcr p15, 0, %0, c1, c1, 0" : : "r" (val)); +} + +PUBLIC static inline +Mword +Cpu::tz_mvbar() +{ + Mword r; + asm volatile ("mrc p15, 0, %0, c12, c0, 1" : "=r" (r)); + return r; +} + +PUBLIC static inline +void +Cpu::tz_mvbar(Mword val) +{ + asm volatile ("mcr p15, 0, %0, c12, c0, 1" : : "r" (val)); +} + +// ------------------------------------------------------------------------ +IMPLEMENTATION [arm && tz && armca9]: + +PUBLIC static inline +void +Cpu::enable_irq_ovrr() +{ + // set IRQ/FIQ/Abort override bits + asm volatile("mov r0, #0x1c0 \n" + "mcr p15, 0, r0, c1, c1, 3 \n" + : : : "r0"); +} + +IMPLEMENTATION [!tz || !armca9]: + +PUBLIC static inline +void +Cpu::enable_irq_ovrr() +{} + +// ------------------------------------------------------------------------ +IMPLEMENTATION [!debug]: + +PRIVATE static inline +void +Cpu::print_infos() +{} + +// ------------------------------------------------------------------------ +IMPLEMENTATION [debug && armv6plus]: + +PRIVATE +void +Cpu::id_print_infos() +{ + printf("ID_PFR[01]: %08lx %08lx", _cpu_id._pfr[0], _cpu_id._pfr[1]); + printf(" ID_[DA]FR0: %08lx %08lx\n", _cpu_id._dfr0, _cpu_id._afr0); + printf("ID_MMFR[04]: %08lx %08lx %08lx %08lx\n", + _cpu_id._mmfr[0], _cpu_id._mmfr[1], _cpu_id._mmfr[2], _cpu_id._mmfr[3]); +} + +// ------------------------------------------------------------------------ +IMPLEMENTATION [debug && !armv6plus]: + +PRIVATE +void +Cpu::id_print_infos() +{ +} + +// ------------------------------------------------------------------------ +IMPLEMENTATION [debug]: + +PRIVATE +void +Cpu::print_infos() +{ + printf("Cache config: %s\n", Config::Cache_enabled ? "ON" : "OFF"); + id_print_infos(); +} diff --git a/kernel/fiasco/src/kern/arm/crt0.S b/kernel/fiasco/src/kern/arm/crt0.S new file mode 100644 index 00000000..452905fd --- /dev/null +++ b/kernel/fiasco/src/kern/arm/crt0.S @@ -0,0 +1,27 @@ +/* -*- c -*- */ + +#include "asm.h" +.section .text.init,#alloc,#execinstr +.type start,#function +ENTRY(_start_kernel) +ENTRY(start) + + ldr sp, __init_data; + bl __main + + /* never returns */ + + +.type __init_data, %object +__init_data: +.long SYMBOL_NAME(_stack-4) + + + +.section ".init.data" +.globl _sstack +_sstack: + .space 2048 +.globl _stack +.type _stack,#object +_stack: diff --git a/kernel/fiasco/src/kern/arm/entry_frame-arm.cpp b/kernel/fiasco/src/kern/arm/entry_frame-arm.cpp new file mode 100644 index 00000000..dc4ad74f --- /dev/null +++ b/kernel/fiasco/src/kern/arm/entry_frame-arm.cpp @@ -0,0 +1,108 @@ +/* + * Fiasco Kernel-Entry Frame-Layout Code for ARM + */ +INTERFACE [arm]: + +#include "types.h" + +EXTENSION class Syscall_frame +{ +public: + //protected: + Mword r[13]; + void dump(); +}; + +EXTENSION class Return_frame +{ +public: + //protected: + Mword usp; + Mword ulr; + Mword km_lr; + Mword pc; + Mword psr; +}; + +//--------------------------------------------------------------------------- +IMPLEMENTATION [arm]: + +#include + +IMPLEMENT +void Syscall_frame::dump() +{ + printf(" R0: %08lx R1: %08lx R2: %08lx R3: %08lx\n", + r[0], r[1], r[2], r[3]); + printf(" R4: %08lx R5: %08lx R6: %08lx R7: %08lx\n", + r[4], r[5], r[6], r[7]); + printf(" R8: %08lx R9: %08lx R10: %08lx R11: %08lx\n", + r[8], r[9], r[10], r[11]); + printf("R12: %08lx\n", r[12]); +} + +IMPLEMENT inline +Mword +Return_frame::ip() const +{ return Return_frame::pc; } + +IMPLEMENT inline +Mword +Return_frame::ip_syscall_page_user() const +{ return Return_frame::pc; } + +IMPLEMENT inline +void +Return_frame::ip(Mword _pc) +{ Return_frame::pc = _pc; } + +IMPLEMENT inline +Mword +Return_frame::sp() const +{ return Return_frame::usp; } + +IMPLEMENT inline +void +Return_frame::sp(Mword sp) +{ Return_frame::usp = sp; } + +//--------------------------------------------------------------------------- +IMPLEMENT inline +Mword Syscall_frame::next_period() const +{ return false; } + +IMPLEMENT inline +void Syscall_frame::from(Mword id) +{ r[4] = id; } + +IMPLEMENT inline +Mword Syscall_frame::from_spec() const +{ return r[4]; } + + +IMPLEMENT inline +L4_obj_ref Syscall_frame::ref() const +{ return L4_obj_ref::from_raw(r[2]); } + +IMPLEMENT inline +void Syscall_frame::ref(L4_obj_ref const &ref) +{ r[2] = ref.raw(); } + +IMPLEMENT inline +L4_timeout_pair Syscall_frame::timeout() const +{ return L4_timeout_pair(r[3]); } + +IMPLEMENT inline +void Syscall_frame::timeout(L4_timeout_pair const &to) +{ r[3] = to.raw(); } + +IMPLEMENT inline Utcb *Syscall_frame::utcb() const +{ return reinterpret_cast(r[1]); } + +IMPLEMENT inline L4_msg_tag Syscall_frame::tag() const +{ return L4_msg_tag(r[0]); } + +IMPLEMENT inline +void Syscall_frame::tag(L4_msg_tag const &tag) +{ r[0] = tag.raw(); } + diff --git a/kernel/fiasco/src/kern/arm/fpu-arm.cpp b/kernel/fiasco/src/kern/arm/fpu-arm.cpp new file mode 100644 index 00000000..60084830 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/fpu-arm.cpp @@ -0,0 +1,306 @@ +INTERFACE [arm && fpu]: + +EXTENSION class Fpu +{ +public: + struct Exception_state_user + { + Mword fpexc; + Mword fpinst; + Mword fpinst2; + }; + + Mword fpsid() const { return _fpsid; } + + enum + { + FPEXC_EN = 1 << 30, + FPEXC_EX = 1 << 31, + }; + + struct Fpu_regs + { + Mword fpexc, fpscr; + Mword state[32 * 4]; // 4*32 bytes for each FP-reg + }; + + static Mword fpsid_rev(Mword v) { return v & 0xf; } + static Mword fpsid_variant(Mword v) { return (v >> 4) & 0xf; } + static Mword fpsid_part_number(Mword v) { return (v >> 8) & 0xff; } + static Mword fpsid_arch_version(Mword v) { return (v >> 16) & 0xf; } + static Mword fpsid_precision(Mword v) { return (v >> 20) & 1; } + static Mword fpsid_format(Mword v) { return (v >> 21) & 3; } + static Mword fpsid_hw_sw(Mword v) { return (v >> 23) & 1; } + static Mword fpsid_implementer(Mword v) { return v >> 24; } + +private: + Mword _fpsid; +}; + +// ------------------------------------------------------------------------ +INTERFACE [arm && !fpu]: + +EXTENSION class Fpu +{ +public: + struct Exception_state_user + { + }; +}; + +// ------------------------------------------------------------------------ +IMPLEMENTATION [arm && !fpu]: + +#include "trap_state.h" + +PUBLIC static inline NEEDS["trap_state.h"] +void +Fpu::save_user_exception_state(Trap_state *, Exception_state_user *) +{} + +// ------------------------------------------------------------------------ +IMPLEMENTATION [arm && fpu]: + +#include +#include +#include + +#include "fpu_state.h" +#include "mem.h" +#include "processor.h" +#include "static_assert.h" +#include "trap_state.h" + +PUBLIC static inline +Mword +Fpu::fpsid_read() +{ + Mword v; + asm volatile("mrc p10, 7, %0, cr0, cr0" : "=r" (v)); + return v; +} + +PUBLIC static inline +Mword +Fpu::mvfr0() +{ + Mword v; + asm volatile("mrc p10, 7, %0, cr7, cr0" : "=r" (v)); + return v; +} + +PUBLIC static inline +Mword +Fpu::mvfr1() +{ + Mword v; + asm volatile("mrc p10, 7, %0, cr6, cr0" : "=r" (v)); + return v; +} + + +PRIVATE static inline +void +Fpu::fpexc(Mword v) +{ + asm volatile("mcr p10, 7, %0, cr8, cr0" : : "r" (v)); +} + +PUBLIC static inline +Mword +Fpu::fpexc() +{ + Mword v; + asm volatile("mrc p10, 7, %0, cr8, cr0" : "=r" (v)); + return v; +} + +PUBLIC static inline +Mword +Fpu::fpinst() +{ + Mword i; + asm volatile("mcr p10, 7, %0, cr9, cr0" : "=r" (i)); + return i; +} + +PUBLIC static inline +Mword +Fpu::fpinst2() +{ + Mword i; + asm volatile("mcr p10, 7, %0, cr10, cr0" : "=r" (i)); + return i; +} + +PUBLIC static inline +bool +Fpu::exc_pending() +{ + return fpexc() & FPEXC_EX; +} + +IMPLEMENT +void +Fpu::enable() +{ + fpexc((fpexc() | FPEXC_EN) & ~FPEXC_EX); +} + +IMPLEMENT +void +Fpu::disable() +{ + fpexc(fpexc() & ~FPEXC_EN); +} + +PUBLIC static inline +int +Fpu::is_emu_insn(Mword opcode) +{ + return (opcode & 0x0ff00f90) == 0x0ef00a10; +} + +PUBLIC static inline +bool +Fpu::emulate_insns(Mword opcode, Trap_state *ts, unsigned cpu) +{ + unsigned reg = (opcode >> 16) & 0xf; + unsigned rt = (opcode >> 12) & 0xf; + Mword fpsid = Fpu::fpu(cpu).fpsid(); + switch (reg) + { + case 0: // FPSID + ts->r[rt] = fpsid; + break; + case 6: // MVFR1 + if (Fpu::fpsid_arch_version(fpsid) < 2) + return false; + ts->r[rt] = Fpu::mvfr1(); + break; + case 7: // MVFR0 + if (Fpu::fpsid_arch_version(fpsid) < 2) + return false; + ts->r[rt] = Fpu::mvfr0(); + break; + default: + break; + } + + if (ts->psr & Proc::Status_thumb) + ts->pc += 2; + + return true; +} + + + +IMPLEMENT +void +Fpu::init(unsigned cpu) +{ + asm volatile(" mcr p15, 0, %0, c1, c0, 2 \n" : : "r"(0x00f00000)); + Mem::dsb(); + + Mword s = fpsid_read(); + + _fpu.cpu(cpu)._fpsid = s; + + printf("FPU%d: Arch: %s(%lx), Part: %s(%lx), r: %lx, v: %lx, i: %lx, t: %s, p: %s\n", + cpu, fpsid_arch_version(s) == 1 + ? "VFPv2" + : (fpsid_arch_version(s) == 3 ? "VFPv3" : "Unkn"), + fpsid_arch_version(s), + fpsid_part_number(s) == 0x20 + ? "VFP11" + : (fpsid_part_number(s) == 0x30 ? "VFPv3" : "Unkn"), + fpsid_part_number(s), + fpsid_rev(s), fpsid_variant(s), fpsid_implementer(s), + fpsid_hw_sw(s) ? "soft" : "hard", + fpsid_precision(s) ? "sngl" : "dbl/sngl"); + + disable(); + + set_owner(cpu, 0); +} + +IMPLEMENT inline NEEDS ["fpu_state.h", "mem.h", "static_assert.h", ] +void +Fpu::init_state (Fpu_state *s) +{ + Fpu_regs *fpu_regs = reinterpret_cast(s->state_buffer()); + static_assert(!(sizeof (*fpu_regs) % sizeof(Mword)), + "Non-mword size of Fpu_regs"); + Mem::memset_mwords(fpu_regs, 0, sizeof (*fpu_regs) / sizeof(Mword)); +} + +IMPLEMENT +void +Fpu::save_state(Fpu_state *s) +{ + assert(s->state_buffer()); + Fpu_regs *fpu_regs = reinterpret_cast(s->state_buffer()); + + asm volatile ("stc p11, cr0, [%0], #32*4 \n" + : : "r" (fpu_regs->state)); + asm volatile ("mrc p10, 7, %0, cr8, cr0, 0 \n" + "mrc p10, 7, %1, cr1, cr0, 0 \n" + : "=r" (fpu_regs->fpexc), + "=r" (fpu_regs->fpscr)); +} + +IMPLEMENT +void +Fpu::restore_state (Fpu_state *s) +{ + assert (s->state_buffer()); + Fpu_regs *fpu_regs = reinterpret_cast(s->state_buffer()); + + asm volatile ("ldc p11, cr0, [%0], #32*4 \n" + : : "r" (fpu_regs->state)); + asm volatile ("mcr p10, 7, %0, cr8, cr0, 0 \n" + "mcr p10, 7, %1, cr1, cr0, 0 \n" + : + : "r" (fpu_regs->fpexc | FPEXC_EN), + "r" (fpu_regs->fpscr)); + +#if 0 + asm volatile("mcr p10, 7, %2, cr9, cr0, 0 \n" + "mcr p10, 7, %3, cr10, cr0, 0 \n" + : + : "r" (fpu_regs->fpinst), + "r" (fpu_regs->fpinst2)); +#endif +} + +IMPLEMENT inline +unsigned +Fpu::state_size() +{ return sizeof (Fpu_regs); } + +IMPLEMENT inline +unsigned +Fpu::state_align() +{ return 4; } + +PUBLIC static +bool +Fpu::is_enabled() +{ + return fpexc() & FPEXC_EN; +} + +PUBLIC static inline NEEDS["trap_state.h"] +void +Fpu::save_user_exception_state(Trap_state *ts, Exception_state_user *esu) +{ + if ((ts->error_code & 0x01f00000) == 0x01100000) + { + esu->fpexc = Fpu::fpexc(); + if (ts->error_code == 0x03100000) + { + esu->fpinst = Fpu::fpinst(); + esu->fpinst2 = Fpu::fpinst2(); + } + } +} diff --git a/kernel/fiasco/src/kern/arm/gic.cpp b/kernel/fiasco/src/kern/arm/gic.cpp new file mode 100644 index 00000000..da65e415 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/gic.cpp @@ -0,0 +1,335 @@ +INTERFACE [arm && pic_gic]: + +#include "kmem.h" +#include "irq_chip_generic.h" + + +class Gic : public Irq_chip_gen +{ +private: + Address _cpu_base; + Address _dist_base; + +public: + enum + { + DIST_CTRL = 0x000, + DIST_CTR = 0x004, + DIST_IRQ_SEC = 0x080, + DIST_ENABLE_SET = 0x100, + DIST_ENABLE_CLEAR = 0x180, + DIST_PRI = 0x400, + DIST_TARGET = 0x800, + DIST_CONFIG = 0xc00, + DIST_SOFTINT = 0xf00, + + MXC_TZIC_PRIOMASK = 0x00c, + MXC_TZIC_SYNCCTRL = 0x010, + MXC_TZIC_PND = 0xd00, + + CPU_CTRL = 0x00, + CPU_PRIMASK = 0x04, + CPU_BPR = 0x08, + CPU_INTACK = 0x0c, + CPU_EOI = 0x10, + CPU_RUNINT = 0x14, + CPU_PENDING = 0x18, + + DIST_CTRL_ENABLE = 1, + + MXC_TZIC_CTRL_NSEN = 1 << 16, + MXC_TZIC_CTRL_NSENMASK = 1 << 31, + + CPU_CTRL_ENABLE = 1, + CPU_CTRL_USE_FIQ_FOR_SEC = 8, + }; + +}; + +// ------------------------------------------------------------------------ +INTERFACE [arm && pic_gic && pic_gic_mxc_tzic]: + +EXTENSION class Gic { enum { Config_mxc_tzic = 1 }; }; + +// ------------------------------------------------------------------------ +INTERFACE [arm && pic_gic && !pic_gic_mxc_tzic]: + +EXTENSION class Gic { enum { Config_mxc_tzic = 0 }; }; + +// ------------------------------------------------------------------------ +INTERFACE [arm && tz]: + +EXTENSION class Gic { enum { Config_tz = 1 }; }; + +// ------------------------------------------------------------------------ +INTERFACE [arm && !tz]: + +EXTENSION class Gic { enum { Config_tz = 0 }; }; + + +//------------------------------------------------------------------- +IMPLEMENTATION [arm && pic_gic]: + +#include +#include +#include + +#include "cascade_irq.h" +#include "io.h" +#include "irq_chip_generic.h" +#include "panic.h" + +PUBLIC inline NEEDS["io.h"] +unsigned +Gic::hw_nr_irqs() +{ return ((Io::read(_dist_base + DIST_CTR) & 0x1f) + 1) * 32; } + +PUBLIC inline NEEDS["io.h"] +bool +Gic::has_sec_ext() +{ return Io::read(_dist_base + DIST_CTR) & (1 << 10); } + +PUBLIC inline +void Gic::softint_cpu(unsigned callmap, unsigned m) +{ + Io::write((callmap & 0xff) << 16 | m, _dist_base + DIST_SOFTINT); +} + +PUBLIC inline +void Gic::softint_bcast(unsigned m) +{ Io::write(1 << 24 | m, _dist_base + DIST_SOFTINT); } + +PUBLIC +void +Gic::init_ap() +{ + Io::write(CPU_CTRL_ENABLE, _cpu_base + CPU_CTRL); + Io::write(0xf0, _cpu_base + CPU_PRIMASK); +} + +PUBLIC +Gic::Gic(Address cpu_base, Address dist_base, int nr_irqs_override = -1) + : _cpu_base(cpu_base), _dist_base(dist_base) +{ + Io::write(0, _dist_base + DIST_CTRL); + + unsigned num = hw_nr_irqs(); + if (nr_irqs_override != -1) + num = nr_irqs_override; + printf("Number of IRQs available at this GIC: %d\n", num); + + if (!Config_mxc_tzic) + { + unsigned int intmask = 1 << Proc::cpu_id(); + intmask |= intmask << 8; + intmask |= intmask << 16; + + for (unsigned i = 32; i < num; i += 16) + Io::write(0, _dist_base + DIST_CONFIG + i * 4 / 16); + for (unsigned i = 32; i < num; i += 4) + Io::write(intmask, _dist_base + DIST_TARGET + i); + } + for (unsigned i = 0; i < num; i += 4) + Io::write(0xa0a0a0a0, _dist_base + DIST_PRI + i); + for (unsigned i = 0; i < num; i += 32) + Io::write(0xffffffff, _dist_base + DIST_ENABLE_CLEAR + i * 4 / 32); + + if (Config_mxc_tzic && !Config_tz) + for (unsigned i = 0; i < num; i += 32) + Io::write(0xffffffff, _dist_base + DIST_IRQ_SEC + i * 4 / 32); + + Mword dist_enable = DIST_CTRL_ENABLE; + if (Config_mxc_tzic && !Config_tz) + dist_enable |= MXC_TZIC_CTRL_NSEN | MXC_TZIC_CTRL_NSENMASK; + + Io::write(dist_enable, _dist_base + DIST_CTRL); + + if (Config_mxc_tzic) + { + Io::write(0x0, _dist_base + MXC_TZIC_SYNCCTRL); + Io::write(0xf0, _dist_base + MXC_TZIC_PRIOMASK); + } + else + { + Io::write(CPU_CTRL_ENABLE, _cpu_base + CPU_CTRL); + Io::write(0xf0, _cpu_base + CPU_PRIMASK); + } + + Irq_chip_gen::init(num); + + //enable_tz_support(); +} + +PUBLIC inline NEEDS["io.h"] +void Gic::disable_locked( unsigned irq ) +{ Io::write(1 << (irq % 32), _dist_base + DIST_ENABLE_CLEAR + (irq / 32) * 4); } + +PUBLIC inline NEEDS["io.h"] +void Gic::enable_locked(unsigned irq, unsigned /*prio*/) +{ Io::write(1 << (irq % 32), _dist_base + DIST_ENABLE_SET + (irq / 32) * 4); } + +PUBLIC inline +void Gic::acknowledge_locked(unsigned irq) +{ + if (!Config_mxc_tzic) + Io::write(irq, _cpu_base + CPU_EOI); +} + +PUBLIC +void +Gic::mask(Mword pin) +{ + assert (cpu_lock.test()); + disable_locked(pin); +} + +PUBLIC +void +Gic::mask_and_ack(Mword pin) +{ + assert (cpu_lock.test()); + disable_locked(pin); + acknowledge_locked(pin); +} + +PUBLIC +void +Gic::ack(Mword pin) +{ + acknowledge_locked(pin); +} + + +PUBLIC +void +Gic::unmask(Mword pin) +{ + assert (cpu_lock.test()); + enable_locked(pin, 0xa); +} + +PUBLIC +unsigned +Gic::set_mode(Mword, unsigned) +{ return Irq_base::Trigger_level; } + +PUBLIC inline +void +Gic::hit(Upstream_irq const *u) +{ + Unsigned32 num = pending(); + if (EXPECT_FALSE(num == 0x3ff)) + return; + + handle_irq(num, u); +} + +PUBLIC static +void +Gic::cascade_hit(Irq_base *_self, Upstream_irq const *u) +{ + // this function calls some virtual functions that might be + // ironed out + Cascade_irq *self = nonull_static_cast(_self); + Gic *gic = nonull_static_cast(self->child()); + Upstream_irq ui(self, u); + gic->hit(&ui); +} + +//------------------------------------------------------------------- +IMPLEMENTATION [arm && !mp && pic_gic]: + +PUBLIC +void +Gic::set_cpu(Mword, unsigned) +{} + +PUBLIC inline NEEDS["io.h"] +Unsigned32 Gic::pending() +{ + if (Config_mxc_tzic) + { + Address a = _dist_base + MXC_TZIC_PND; + for (unsigned g = 0; g < 128; g += 32, a += 4) + { + Mword v = Io::read(a); + if (v) + return g + 31 - __builtin_clz(v); + } + return 0; + } + + return Io::read(_cpu_base + CPU_INTACK) & 0x3ff; +} + +//------------------------------------------------------------------- +IMPLEMENTATION [arm && mp && pic_gic]: + +#include "cpu.h" + +PUBLIC inline NEEDS["io.h"] +Unsigned32 Gic::pending() +{ + Unsigned32 ack = Io::read(_cpu_base + CPU_INTACK); + + // IPIs/SGIs need to take the whole ack value + if ((ack & 0x3ff) < 16) + Io::write(ack, _cpu_base + CPU_EOI); + + return ack & 0x3ff; +} + +PUBLIC inline NEEDS["cpu.h"] +void +Gic::set_cpu(Mword pin, unsigned cpu) +{ + Mword reg = _dist_base + DIST_TARGET + (pin & ~3); + Mword val = Io::read(reg); + + int shift = (pin % 4) * 8; + val = (val & ~(0xf << shift)) | (1 << (Cpu::cpus.cpu(cpu).phys_id() + shift)); + + Io::write(val, reg); +} + + +//------------------------------------------------------------------- +IMPLEMENTATION [arm && pic_gic && tz]: + +#if 0 +PRIVATE +void +Gic::set_irq_nonsecure(unsigned irqnum) +{ + Io::set(1 << (irqnum % 32), + _dist_base + DIST_IRQ_SEC + ((irqnum & ~31) / 8)); +} +#endif + +PUBLIC inline NEEDS[] +void +Gic::enable_tz_support() +{ + if (has_sec_ext()) + printf("GIC:Has security extension\n"); + + printf("GIC: Signal secure Interrupts as FIQs!\n"); + Io::write(CPU_CTRL_ENABLE | CPU_CTRL_USE_FIQ_FOR_SEC, + _cpu_base + CPU_CTRL); +} + +//------------------------------------------------------------------- +IMPLEMENTATION [arm && pic_gic && !tz]: + +PUBLIC inline +void +Gic::enable_tz_support() +{} + +//--------------------------------------------------------------------------- +IMPLEMENTATION [debug]: + +PUBLIC +char const * +Gic::chip_type() const +{ return "GIC"; } diff --git a/kernel/fiasco/src/kern/arm/ipi-arm.cpp b/kernel/fiasco/src/kern/arm/ipi-arm.cpp new file mode 100644 index 00000000..c1198c1a --- /dev/null +++ b/kernel/fiasco/src/kern/arm/ipi-arm.cpp @@ -0,0 +1,63 @@ +IMPLEMENTATION [mp]: + +#include "cpu.h" +#include "pic.h" +#include "gic.h" +#include "processor.h" + +EXTENSION class Ipi +{ +private: + Unsigned32 _phys_id; + +public: + enum Message + { + Ipi_start = 1, + Global_request = Ipi_start, Request, Debug, + Ipi_end + }; +}; + + +PUBLIC inline +Ipi::Ipi() : _phys_id(~0) +{} + +IMPLEMENT inline NEEDS["processor.h"] +void +Ipi::init(unsigned cpu) +{ + _ipi.cpu(cpu)._phys_id = Proc::cpu_id(); +} + +PUBLIC static +void Ipi::ipi_call_debug_arch() +{ +} + +PUBLIC static inline +void Ipi::eoi(Message, unsigned on_cpu) +{ + // with the ARM-GIC we have to do the EOI right after the ACK + stat_received(on_cpu); +} + +// --------------------------------------------------------------------------- +IMPLEMENTATION [mp && !irregular_gic]: + +PUBLIC static inline NEEDS["pic.h"] +void Ipi::send(Message m, unsigned from_cpu, unsigned to_cpu) +{ + Pic::gic->softint_cpu(1 << _ipi.cpu(to_cpu)._phys_id, m); + stat_sent(from_cpu); +} + +PUBLIC static inline +void +Ipi::bcast(Message m, unsigned from_cpu) +{ + (void)from_cpu; + Pic::gic->softint_bcast(m); +} + diff --git a/kernel/fiasco/src/kern/arm/ivt.S b/kernel/fiasco/src/kern/arm/ivt.S new file mode 100644 index 00000000..9bedb922 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/ivt.S @@ -0,0 +1,1192 @@ +/* -*- asm -*- */ + +#include "globalconfig.h" +#include "config_tcbsize.h" +#include "tcboffset.h" + + + +/********************************************************************** + * calculate the TCB address from a stack pointer + */ +.macro CONTEXT_OF reg, ptr + bic \reg, \ptr, #((THREAD_BLOCK_SIZE-1) & 0xff) + bic \reg, \reg, #((THREAD_BLOCK_SIZE-1) & 0xff00) +.endm + +/********************************************************************** + * Reset the thread cancel flag. + * Register r0 is scratched and contains the thread state afterwards + */ +.macro RESET_THREAD_CANCEL_AT tcb + ldr r0, [\tcb, #(OFS__THREAD__STATE)] + bic r0, r0, #0x100 + str r0, [\tcb, #(OFS__THREAD__STATE)] +.endm + +/**************************** + * some handy definitions + */ +#define RF_SIZE 20 +#define RF_PSR 16 +#define RF_PC 12 +#define RF_SVC_LR 8 +#define RF_USR_LR 4 +#define RF_USR_SP 0 +#define RF(reg, offs) (RF_##reg + (offs)) + +/************************************************************************** + * Enter kernel mode (i.e. switch from any exception mode to the + * kernel mode and transfer the exception state). + */ + +.macro atomic_fixup insn do_store_pc +#ifndef CONFIG_ARM_V6PLUS + @ Adjust PC if it is in the special atomic insns area + @ Zero-flag set after this fixup code + cmp \insn, #0xffffe000 + bls 1f + cmp \insn, #0xfffff000 + bhs 1f + tst \insn, #0x10 + biceq \insn, \insn, #0x0ff +.if \do_store_pc + str \insn, [sp, #RF(PC, RF_SIZE)] +.endif +1: + @ --------------------------------------------------- +#endif +.endm + +.macro __switch_to_kernel reg adjust atomic_fixup not_svc +.if \adjust != 0 + sub lr, lr, #\adjust +.endif +#ifdef CONFIG_ARM_V6PLUS +#ifdef CONFIG_ARM_1136 + // todo: do clrex with strex for CPUs without clrex +#else + clrex +#endif +#endif +.if \atomic_fixup + atomic_fixup lr 0 +.endif +#if defined(CONFIG_ARM_V6PLUS) + srsdb #0x13! + msr cpsr_c, #0xd3 @cpsid f, #0x13 + str lr, [sp, #-4]! +#else +.if \not_svc + str lr, s_lr + mrs \reg, spsr + str \reg, s_spsr + msr cpsr_c, #0xd3 +.endif @ syscall (already in svc mode) + str lr, [sp, #-12]! +.if \not_svc + ldr lr, s_spsr + str lr, [sp, #RF(PSR, -8)] + ldr lr, s_lr + str lr, [sp, #RF(PC, -8)] +.else + str lr, [sp, #RF(PC, -8)] + mrs lr, spsr + str lr, [sp, #RF(PSR, -8)] +.endif +#endif +.endm +.macro switch_to_kernel adjust atomic_fixup not_svc + __switch_to_kernel r14 \adjust \atomic_fixup \not_svc +.endm + +/************************************************************************* + * return from an exception + */ +.macro return_from_exception + ldr lr, [sp, #RF(PSR,0)] @ Unstack SPSR + tst lr, #0x0f @ Mask all but relevant mode bits + add sp, sp, #RF_SIZE @ SP to top of stack +#if defined(CONFIG_ARM_V6PLUS) + ldrne lr, [sp, #RF(SVC_LR, -RF_SIZE)] @ load old kernel lr + rfedb sp +#else + msr spsr_cfsx, lr @ Load SPSR from kernel_lr + ldr lr, [sp, #RF(PC, -RF_SIZE)] @ copy PC on psr field for + str lr, [sp, #RF(PSR, -RF_SIZE)] @ final ldmdb and proper ksp + ldrne lr, [sp, #RF(SVC_LR, -RF_SIZE)] @ load old kernel lr + ldmdb sp, {pc}^ @ go back to interrupted insn + @ (load psr) +#endif +.endm + + +/*********************************************************************** + * Enter the kernel slowtrap handler + * + * Stack the state and call 'slowtrap_entry' with sp and error code + */ +.macro enter_slowtrap_w_stack errorcode + mov r1, #\errorcode + stmdb sp!, {r0, r1} + mov r0, sp + adr lr, exception_return + ldr pc, .LCslowtrap_entry +.endm + +.macro enter_slowtrap errorcode + stmdb sp!, {r0 - r12} + enter_slowtrap_w_stack \errorcode +.endm + +/* + * Stack layout: + * + * after SWITCH_TO_SVC !!!! + * + * | | + * +-------+ + * | lr' | (pc after syscall) + * +-------+ + * old sp -> | spsr | + * +-------+ + * | km_lr | + * +-------+ + * | lr^ | (user lr) + * +-------+ + * sp -> | sp^ | (user sp) + * +-------+ + * | | + * + */ + + +/************************************************************************* + * + * Generate stack for exception entries + * - Adjust return address + * - Store return address at [sp + 8] + * - Store spsr at [sp + 4] + * - sp := sp - 8 + * - Store user sp at [sp] + * - Store user lr at [sp + 4] + */ +.macro exceptionframe + sub sp, sp, #8 +@ stmia sp, {sp,lr}^ @ now done lazy +.endm + + +/*************************************************************************** + * Generate stack for system call entries + * + * Stack layout: + * + * after SWITCH_TO_SVC !!!! + * + * | | + * +-------+ + * | lr^ | (pc after syscall) + * +-------+ + * old sp -> | spsr | + * +-------+ + * | km_lr | + * +-------+ + * | xx | + * +-------+ + * sp -> | sp^ | (user sp) + * +-------+ + * | | + * + * + * lr: must contain fault addr (from switch_to_kernel) + */ +.macro syscallframe + add lr, sp, #RF(PC, -8) + stmia lr, {lr}^ + sub sp, sp, #8 +@ stmia sp, {sp}^ @ now done lazy +.endm + +.macro enter_sys_call no_sys_call + ldr lr, [sp, #RF(PC, -8)] + cmn lr, #0x2a @ Range Check !!! UNSIGNED !!! + bls \no_sys_call @ no syscall + cmn lr, #0x08 + bhi \no_sys_call + syscallframe + stmdb sp!, {r0 - r12} + CONTEXT_OF r1, sp + RESET_THREAD_CANCEL_AT r1 @ sets r0 to state + tst r0, #0x810000 + bne alien_syscall + ldr r0, [sp, #RF(SVC_LR, 13*4)] @ read exception PC from stack (km_lr) + adr r1, sys_call_table + sub r0, r1, r0 + adr lr, 2f +1: ldr pc, [r0] +.global fast_ret_from_irq +fast_ret_from_irq: +2: ldmia sp, {r0 - r12}^ + msr cpsr_c, #0xd3 // disable IRQs + add sp, sp, #13*4 + + /* Return */ + ldr lr, [sp, #RF(PSR,0)] + msr spsr_cfsx, lr +@ ldmia sp, {sp,lr}^ @ done lazy + add sp, sp, #RF_SIZE + ldr lr, [sp, #RF(PC, -RF_SIZE)] + movs pc, lr +.endm + + +/************************************************************************** + * The Exception vector table. + */ +.section .vect,"a" +.globl exception_vector +exception_vector: + nop /* RESET */ + b undef_entry /* UNDEF */ + b swi_entry /* SWI */ + b inst_abort_entry /* IABORT */ + b data_abort_entry /* DABORT */ + nop /* reserved */ + b irq_entry /* IRQ */ + b fiq_entry /* FIQ */ + + +/* locations to pass lr and spsr from one mode to the other + these are globally shared !!! */ +.section .excp.text,"xa" +#if !defined(CONFIG_ARM_V6PLUS) +s_lr: .word 0 +s_spsr: .word 0 +#endif + +/*************************************************************************** +** +** Exception entry points. +** +*/ + +/*************************************************************************** + * Exception undef () + * + * Exception is an undefined instruction. + * + */ +undef_entry: + switch_to_kernel 0 0 1 + exceptionframe + enter_slowtrap 0x00100000 + +/************************************************************************** + * Exception swi () + * + * Exception is a software interrupt (typically a syscall in normal + * OSes). + * + */ +swi_entry: + switch_to_kernel 0 0 0 + enter_sys_call no_sys_call +no_sys_call: + exceptionframe + enter_slowtrap 0x00200000 + +.align 4 + +/*************************************************************************** + * Exception inst_abort () + * + * Exception is a prefetch (instruction) abort. This exception is also + * used for L4 syscalls. If the exception address is in the range 0x00 + * to 0x24 (in the exception vector page), this is interpreted as a + * syscall number. Some platforms allow the exception vector to be + * relocated to the beginning of the last 64K of memory. For these + * platforms, we use a negative (i.e. end of address space) value to + * indicate the syscall number. If exception is not within the syscall + * range, generate a pager IPC (or panic if within the kernel). + * + */ +inst_abort_entry: + + switch_to_kernel 4 0 1 + + +/**************************************************************************/ +prefetch_abort: @ A real prefetch abort occured --- handled as a page fault + exceptionframe + stmdb sp!, {r0 - r3, r12} @ Stack rest of user state + ldr lr, [sp, #RF(PSR, 5*4)] @ get spsr from stack + ands lr, lr, #0x0f @ Mask all but relevant mode bits + bne kernel_prefetch_abort @ Kernel abort? + /* user prefetch abort */ + mrc p15, 0, r1, c5, c0, 1 @ Load IFSR into r1 + bic r1, r1, #0x00ff0000 + orr r1, r1, #0x00330000 @ Set read bit and prefetch abort +#if defined(CONFIG_ARM_V6PLUS) && !defined(CONFIG_ARM_1136) && !defined(CONFIG_ARM_MPCORE) + mrc p15, 0, r0, c6, c0, 2 @ Read fault address, for T2: pfa != pc +#else + ldr r0, [sp, #RF(PC, 5*4)] @ Get PC from RF and use as pfa +#endif + mov r2, r0 + add r3, sp, #(5*4) + stmdb sp!, {r0, r1} + adr lr, pagefault_return + ldr pc, .LCpagefault_entry @ Jump to C code + +kernel_prefetch_abort: @ Kernel generated IAbort + @ Should not get IAborts in kernel + @ Kernel Panic + adr r0, kernel_prefetch_abort_label + b kern_kdebug_entry + + + + + +/**************************************************************************** + * Exception data_abort () + * + * Exception is a data abort. If exception happened in user mode, + * generate pager IPC. If exception happened in kernel mode, it is + * probably due to a non-mapped TCB (or else we panic). + * + * + * Stack layout: + * + * old sp-> | | + * +-------+ + * | lr' | +68 + * +-------+ + * | spsr | +64 + * +-------+ + * | km_lr | +60 + * +-------+ + * | ulr | +56 + * +-------+ + * | usp | +52 + * +-------+ + * | r12 | +48 + * +-------+ + * : : + * +-------+ + * sp -> | r0 | +0 + * +-------+ + * | | + * + * + * + */ + +.macro check_ldrd_insn jmp_to_if_ldrd + tst r3, #0x0e000000 + bne 1f + and r12, r3, #0x000000f0 + cmp r12, #0x000000d0 + bne 1f + tst r3, #(1<<20) + beq \jmp_to_if_ldrd +1: +.endm + +data_abort_entry: + switch_to_kernel 8 0 1 + + exceptionframe + stmdb sp!, {r0 - r3, r12} @ Stack rest of user state + + /* user data abort */ +#ifdef CONFIG_ARM_V6PLUS + mrc p15, 0, r1, c5, c0, 0 @ Load DFSR into r1 + bic r1, r1, #0x00ff0000 + mrc p15, 0, r0, c6, c0, 0 @ Load DFAR into r0 + + ldr r2, [sp, #RF(PC, 5*4)] @ Load PC into r2 + ldr lr, [sp, #RF(PSR, 5*4)] @ load spsr, from stack + + ands lr, lr, #0x0f @ Mask all but relevant mode bits + @ NE -> kernel + add r3, sp, #(5*4) + orreq r1, r1, #0x00010000 + orr r1, r1, #0x00400000 @ Set error code to data abort + + stmdb sp!, {r0, r1} + adr lr, pagefault_return @ set return address + + ldr pc, .LCpagefault_entry @ page fault +#else + mrc p15, 0, r1, c5, c0, 0 @ Load FSR into r1 + bic r1, r1, #(1 << 11) @ clear bit 11 (write indicator) + bic r1, r1, #0x00ff0000 + mrc p15, 0, r0, c6, c0, 0 @ Load FAR into r0 + ldr r2, [sp, #RF(PC, 5*4)] @ Load PC into r2 + ldr lr, [sp, #RF(PSR, 5*4)] @ load spsr, from stack + tst lr, #0x20 @ comes from thumb mode? + bne .LChandle_thumb + @ arm insns + ldr r3, [r2] @ Load faulting insn + check_ldrd_insn .LCwas_ldrd + tst r3, #(1<<20) + orreq r1, r1, #(1 << 11) @ Set FSR write bit +.LCret_handle_thumb: +.LCwas_ldrd: + atomic_fixup r2 1 + ands lr, lr, #0x0f @ Mask all but relevant mode bits + @ NE -> kernel + add r3, sp, #(5*4) + orreq r1, r1, #0x00010000 + orr r1, r1, #0x00400000 @ Set error code to data abort + stmdb sp!, {r0, r1} + adr lr, pagefault_return @ set return address + + ldr pc, .LCpagefault_entry @ page fault + +.LChandle_thumb: + @ thumb insns + ldrh r3, [r2] + and r3, r3, #0xfe00 + teq r3, #0x5600 + beq .LCret_handle_thumb + tst r3, #(1<<11) + orreq r1, r1, #(1 << 11) @ Set FSR write bit + b .LCret_handle_thumb +#endif + +.LCpagefault_entry: .word pagefault_entry +.LCslowtrap_entry: .word slowtrap_entry + + +/*************************************************************************** + * Generic return code for restoring the thread state after exceptions. + * + * Stack layout: + * + * sp-> | | + * +-------+ + * | lr' | +68 + * +-------+ + * | spsr | +64 + * +-------+ + * | km_lr | +60 + * +-------+ + * | ulr | +56 + * +-------+ + * | usp | +52 + * +-------+ + * | r12 | +48 + * +-------+ + * : : + * +-------+ + * old sp -> | r0 | +0 + * +-------+ + * | | + * + * + */ +pagefault_return: + cmp r0, #0 + ldmia sp!, {r12, lr} + beq slowtrap_from_pagefault + + msrne cpsr_c, #0xd3 // disable IRQs + ldmneia sp!, {r0 - r3, r12} @ Restore user state + return_from_exception + +slowtrap_from_pagefault: + msr cpsr_c, #0xd3 // disable IRQs + ldmia sp!, {r0 - r3} + stmdb sp!, {r0 - r11} + stmdb sp!, {r12, lr} + mov r0, sp + adr lr, exception_return + ldr pc, .LCslowtrap_entry @ slow trap + + .global __return_from_exception +__return_from_exception: +exception_return: + msr cpsr_c, #0xd3 // disable IRQs + add sp, sp, #8 + ldmia sp!, {r0 - r12} + return_from_exception + + .align 4 + .global __iret +__iret: + return_from_exception + + +/*************************************************************************** + * Exception irq () + * + * Exception is an interrupt. Generate interrupt IPC. + * + */ +irq_entry: + switch_to_kernel 4 1 1 + exceptionframe + + stmdb sp!, {r0 - r3, r12} @ Stack rest of user state + @ add r0, sp, #(5*4) @ debug + mov lr, pc + ldr pc, 1f + ldmia sp, {r0 - r3, r12} @ Restore user state + msr cpsr_c, #0xd3 // disable IRQs + add sp, sp, #20 + return_from_exception +1: .word irq_handler + + +/****************************************************************************** + * Exception fiq () + * + * Exception is a fast interrupt. + * + */ +fiq_entry: + switch_to_kernel 4 1 1 + exceptionframe + + stmdb sp!, {r0 - r3, r12} @ Stack rest of user state + @ add r0, sp, #(5*4) @ debug + mov lr, pc + ldr pc, 1f + ldmia sp, {r0 - r3, r12} @ Restore user state + msr cpsr_c, #0xd3 // disable IRQs + add sp, sp, #20 + return_from_exception +1: .word irq_handler + + +/**************************************************************************/ +/* The alien stuff is below */ +/**************************************************************************/ +alien_syscall: @ Do it for an alien --------------------------------------- + tst r0, #0x20000 + bicne r0, r0, #0x20000 + bne 1f + @ Trap alien before system call ----------------------------------- + @ The trap is an insn abort on the syscall address in the kernel. + ldr lr, [sp, #RF(PC, 13*4)] + str lr, [sp, #RF(USR_LR, 13*4)] + ldr lr, [sp, #RF(SVC_LR, 13*4)] @ read orig exception PC + sub lr, lr, #4 @ adjust pc to be on insn + str lr, [sp, #RF(PC, 13*4)] @ store to entry_stack_PC + enter_slowtrap_w_stack 0x00300000 + @ Never reach this -- end up in user land after exception reply + +1: @ Resume the alien system call ------------------------------------ + str r0, [r1, #(OFS__THREAD__STATE)] + ldr r0, [sp, #RF(SVC_LR, 13*4)] @ read orig excpetion PC + adr r1, sys_call_table + sub r0, r1, r0 + adr lr, 2f + ldr pc, [r0] +2: nop @ The return point after the resumed alien system call -------- + msr cpsr_c, #0xd3 // disable IRQs + @ Trap after the resumed alien system call ------------------------ + @ The trap occurs at the insn where the system call returns to. + @ Set the bit 0x00010000 to indicate a trap after the resumed + @ system call. + enter_slowtrap_w_stack 0x00310000 + + +/*****************************************************************************/ +/* The syscall table stuff */ +/*****************************************************************************/ +#define SYSCALL(name) .word sys_##name##_wrapper + +.globl sys_call_table +sys_call_table: + .word sys_kdb_ke + .word sys_kdb_ke +/*SYSCALL(ipc)*/ + .word sys_ipc_wrapper + .word sys_arm_mem_op +SYSCALL(invoke_debug) + .word sys_kdb_ke + .word sys_kdb_ke + .word sys_kdb_ke + .word sys_kdb_ke + .word sys_kdb_ke + .word sys_kdb_ke + + .align 4 + .global leave_by_trigger_exception + +leave_by_trigger_exception: + sub sp, sp, #RF_SIZE @ restore old return frame + stmdb sp!, {r0 - r12} + + /* restore original IP */ + CONTEXT_OF r1, sp + ldr r0, [r1, #(OFS__THREAD__EXCEPTION_IP)] + str r0, [sp, #RF(PC, 13*4)] + + ldr r0, [r1, #(OFS__THREAD__EXCEPTION_PSR)] + str r0, [sp, #RF(PSR, 13*4)] + + mov r0, #~0 + str r0, [r1, #(OFS__THREAD__EXCEPTION_IP)] + + enter_slowtrap_w_stack 0x00500000 + + .align 4 + .global leave_by_vcpu_upcall; + +leave_by_vcpu_upcall: + sub sp, sp, #RF_SIZE @ restore old return frame + stmdb sp!, {r0 - r2} + + /* restore original IP */ + CONTEXT_OF r1, sp + + /* access_vcpu() for the local case */ + ldr r2, [r1, #(OFS__THREAD__USER_VCPU)] + add r2, r2, #(VAL__SIZEOF_TRAP_STATE - RF_SIZE) + + ldr r0, [r1, #(OFS__THREAD__EXCEPTION_IP)] + str r0, [r2, #RF(PC, 0)] + + ldr r0, [r1, #(OFS__THREAD__EXCEPTION_PSR)] + str r0, [r2, #RF(PSR, 0)] + bic r0, #0x20 // force ARM mode + str r0, [sp, #RF(PSR, 3*4)] + + mov r0, #~0 + str r0, [r1, #(OFS__THREAD__EXCEPTION_IP)] + + ldr r0, [sp, #RF(USR_LR, 3*4)] + str r0, [r2, #RF(USR_LR, 0)] + + ldr r0, [sp, #RF(USR_SP, 3*4)] + str r0, [r2, #RF(USR_SP, 0)] + + stmdb r2!, {r3-r12} + + ldr r0, [sp, #8] + str r0, [r2, #-4] + + ldr r0, [sp, #4] + str r0, [r2, #-8] + + ldr r0, [sp] + str r0, [r2, #-12]! + + add sp, sp, #(3*4) + + add r0, r2, #(-8 + OFS__VCPU_STATE__ENTRY_SP) + ldm r0, {sp}^ + + ldr r0, [r2, #(-8 + OFS__VCPU_STATE__ENTRY_IP)] + + str r0, [sp, #RF(PC, 0)] + add r0, r2, #(-8) + + b __iret + + +kernel_prefetch_abort_label: .string "Kernel prefetch abort" +missed_excpt_ret_label: .string "ERROR in exception return" +fiq_label: .string "FIQ entry" + +/********************************************************************** + kdebug entry + **********************************************************************/ + +.macro DEBUGGER_ENTRY type +#ifdef CONFIG_JDB + str sp, [sp, #(RF(USR_SP, -RF_SIZE))] @ save r[13] + sub sp, sp, #(RF_SIZE) + + str lr, [sp, #RF(SVC_LR, 0)] + str lr, [sp, #RF(PC, 0)] + mrs lr, cpsr + str lr, [sp, #RF(PSR, 0)] + + stmdb sp!, {r0 - r12} + mov r0, #-1 @ pfa + mov r1, #0x00e00000 @ err + orr r1, #\type @ + type + stmdb sp!, {r0, r1} + + mov r0, sp + adr lr, 1f + ldr pc, 3f + +1: + add sp, sp, #8 @ pfa and err + ldmia sp!, {r0 - r12} + ldr lr, [sp, #RF(PSR, 0)] + msr cpsr, lr + ldr lr, [sp, #RF(SVC_LR, 0)] + + ldr sp, [sp, #(RF(USR_SP, 0))] + mov pc, lr + + +3: .word call_nested_trap_handler +#else + mov pc, lr +#endif +.endm + + .global kern_kdebug_entry + .align 4 +kern_kdebug_entry: + DEBUGGER_ENTRY 0 + + .global kern_kdebug_sequence_entry + .align 4 +kern_kdebug_sequence_entry: + DEBUGGER_ENTRY 1 + + +#ifdef CONFIG_MP + .section ".text" + .global kern_kdebug_ipi_entry + .align 4 +kern_kdebug_ipi_entry: + DEBUGGER_ENTRY 2 + .previous +#endif + + + +#ifdef CONFIG_ARM_TZ + +.macro ISB_OP reg +#ifdef CONFIG_ARM_V7 + isb +#else + mcr p15, 0, lr, c7, c5, 4 @ cp15isb +#endif +.endm + +/********************************************************************** + * Secure and Nonsecure switching stuff + * + *********************************************************************/ +.macro SAVE_NONSECURE_STATE off + + // save exit reason temporarily on stack + str lr, [sp,#-12] + + // switch to secure world + mov lr, #0 + mcr p15, 0, lr, c1, c1, 0 + + // save gen-regs + ldr lr, [sp, #\off] + //add lr, lr, #8 + stmia lr!, {r0 - r12} + + mov r0, lr + + // usr + stmia r0, {sp, lr}^ + add r0, r0, #8 + + // irq + cps #0x12 + stmia r0!, {sp, lr} + mrs r1, spsr + stmia r0!, {r1} + + // fiq + cps #0x11 + stmia r0!, {r8 - r12, sp, lr} + mrs r1, spsr + stmia r0!, {r1} + + // abt + cps #0x17 + stmia r0!, {sp, lr} + mrs r1, spsr + stmia r0!, {r1} + + // und + cps #0x1b + stmia r0!, {sp, lr} + mrs r1, spsr + stmia r0!, {r1} + + // svc + cps #0x13 + stmia r0!, {sp, lr} + mrs r1, spsr + stmia r0!, {r1} + + cps #0x16 + + // copy return pc/cpsr from stack + sub lr, sp, #8 + ldmia lr, {r1, r2} + stmia r0!, {r1, r2} + + // save pending virtual interrupt state + mrc p15, 0, r1, c12, c1, 1 + stmia r0!, {r1} + + // switch to non-secure world + mov r1, #1 + mcr p15, 0, r1, c1, c1, 0 + ISB_OP r1 + + mrc p15, 0, r1, c2, c0, 0 @ read CP15_TTB0 + stmia r0!, {r1} + + mrc p15, 0, r1, c2, c0, 1 @ read CP15_TTB1 + stmia r0!, {r1} + + mrc p15, 0, r1, c2, c0, 2 @ read CP15_TTBC + stmia r0!, {r1} + + mrc p15, 0, r1, c12, c0, 0 @ read CP15_VECTOR_BASE + stmia r0!, {r1} + + mrc p15, 0, r1, c5, c0, 0 @ read CP15_DFSR + stmia r0!, {r1} + + mrc p15, 0, r1, c6, c0, 0 @ read CP15_DFAR + stmia r0!, {r1} + + mrc p15, 0, r1, c5, c0, 1 @ read CP15_IFSR + stmia r0!, {r1} + + mrc p15, 0, r1, c6, c0, 2 @ read CP15_IFAR + stmia r0!, {r1} + + mrc p15, 0, r1, c1, c0, 0 @ read CP15_CONTROL + stmia r0!, {r1} + + mrc p15, 0, r1, c10, c2, 0 @ read CP15_PRIM_REGION_REMAP + stmia r0!, {r1} + + mrc p15, 0, r1, c10, c2, 1 @ read CP15_NORM_REGION_REMAP + stmia r0!, {r1} + + mrc p15, 0, r1, c13, c0, 1 @ read CP15_CID + stmia r0!, {r1} + + // tls regs are banked + mrc p15, 0, r1, c13, c0, 2 @ read CP15_TLS1 + stmia r0!, {r1} + + mrc p15, 0, r1, c13, c0, 3 @ read CP15_TLS2 + stmia r0!, {r1} + + mrc p15, 0, r1, c13, c0, 4 @ read CP15_TLS3 + stmia r0!, {r1} + + mrc p10, 7, r1, cr8, cr0, 0 @ fpexc + stmia r0!, {r1} + + // switch to secure world + mov r1, #0 + mcr p15, 0, r1, c1, c1, 0 + ISB_OP r1 + + mrc p15, 0, r1, c5, c0, 0 @ read CP15_DFSR + stmia r0!, {r1} + + mrc p15, 0, r1, c6, c0, 0 @ read CP15_DFAR + stmia r0!, {r1} + + // copy the exit reason from stack + ldr r1, [sp, #-12] + stmia r0!,{r1} +.endm + +.macro RESTORE_NONSECURE_STATE off + + ldr r0, [sp, #\off] + + // jump over general purpose register + add r0, r0, #13*4 + + // usr + ldmia r0, {sp, lr}^ + add r0, r0, #8 + + // irq + cps #0x12 + ldmia r0!, {sp, lr} + ldmia r0!, {r1} + msr spsr, r1 + + // fiq + cps #0x11 + ldmia r0!, {r8 - r12, sp, lr} + ldmia r0!, {r1} + msr spsr, r1 + + // abt + cps #0x17 + ldmia r0!, {sp, lr} + ldmia r0!, {r1} + mrs r1, spsr + + // und + cps #0x1b + ldmia r0!, {sp, lr} + ldmia r0!, {r1} + msr spsr, r1 + + // svc + cps #0x13 + ldmia r0!, {sp, lr} + ldmia r0!, {r1} + msr spsr, r1 + + cps #0x16 + + // copy return pc/cpsr on stack + ldmia r0!, {r1, r2} + stmdb sp, {r1, r2} + + // set pending events + ldmia r0!, {r1} + and r1, r1, #0x1c0 + mcr p15, 0, r1, c12, c1, 1 + +#if 1 + // switch to non-secure world + mov r1, #1 + mcr p15, 0, r1, c1, c1, 0 + ISB_OP r1 + + ldmia r0!, {r1} + mcr p15, 0, r1, c2, c0, 0 @ write CP15_TTB0 + + ldmia r0!, {r1} + mcr p15, 0, r1, c2, c0, 1 @ write CP15_TTB1 + + ldmia r0!, {r1} + mcr p15, 0, r1, c2, c0, 2 @ write CP15_TTBC + + ldmia r0!, {r1} + mcr p15, 0, r1, c12, c0, 0 @ write CP15_VECTOR_BASE + + ldmia r0!, {r1} + mcr p15, 0, r1, c5, c0, 0 @ write CP15_DFSR + + ldmia r0!, {r1} + mcr p15, 0, r1, c6, c0, 0 @ write CP15_DFAR + + ldmia r0!, {r1} + mcr p15, 0, r1, c5, c0, 1 @ write CP15_IFSR + + ldmia r0!, {r1} + mcr p15, 0, r1, c6, c0, 2 @ write CP15_IFAR + + ldmia r0!, {r1} + mcr p15, 0, r1, c1, c0, 0 @ write CP15_CONTROL + + ldmia r0!, {r1} + mcr p15, 0, r1, c10, c2, 0 @ write CP15_PRIM_REGION_REMAP + + ldmia r0!, {r1} + mcr p15, 0, r1, c10, c2, 1 @ write CP15_NORM_REGION_REMAP + + ldmia r0!, {r1} + mcr p15, 0, r1, c13, c0, 1 @ write CP15_CID + + // tls regs are banked + ldmia r0!, {r1} + mcr p15, 0, r1, c13, c0, 2 @ write CP15_TLS1 + + ldmia r0!, {r1} + mcr p15, 0, r1, c13, c0, 3 @ write CP15_TLS2 + + ldmia r0!, {r1} + mcr p15, 0, r1, c13, c0, 4 @ write CP15_TLS3 + + ldmia r0!, {r1} + mcr p10, 7, r1, cr8, cr0, 0 @ fpexc + + // switch to secure world + mov r1, #0 + mcr p15, 0, r1, c1, c1, 0 + ISB_OP r1 +#endif + + // load gen-regs + ldr lr, [sp, #\off] + ldmia lr!, {r0 - r12} +.endm + +/********************************************************************** + * Save secure state on top of the stack. + * + * We save also the user-level registers here, because we need to + * restore some on FIQ. + * + */ +.macro SAVE_SECURE_STATE + + stmdb sp!, {r3, r4} @ save supervisor return values + stmdb sp, {sp, lr}^ @ save user-level return values + sub sp, sp, #8 +.endm + +/********************************************************************** + * Restore secure state when guest returns with monitor call. + * + * This removes the secure state from the top of the stack. + */ +.macro RESTORE_SECURE_STATE + + mov r0, sp @ restore stack pointer from supervisor mode + cps #0x13 + mov sp, r0 + cps #0x16 + ldmia sp, {sp, lr}^ @ restore user-level return values + add sp, sp, #8 + ldmia sp!, {r3, r4} @ restore supervisor return values +.endm + +/********************************************************************** + * Restore secure state when guest is interrupted by FIQ + * + * Don't remove secure state from stack as we need it + * when application guest exits. + * Just restore user-level state as this is spilled by the irq handler + */ +.macro RESTORE_SECURE_STATE_FIQ + + mov r0, sp @ restore stack pointer from supervisor mode + cps #0x13 + mov sp, r0 + cps #0x16 + ldmia sp, {sp, lr}^ @ restore user-level return values +.endm + +.macro SWITCH_TO_NONSECURE_MODE + mov lr, #0xf + mcr p15, 0, lr, c1, c1, 0 + ISB_OP lr +.endm + +.macro SWITCH_TO_SECURE_MODE + mov lr, #0x0 + mcr p15, 0, lr, c1, c1, 0 + ISB_OP lr +.endm + + +/*****************************************************************************/ +/* The monitor entry table stuff */ +/*****************************************************************************/ +.p2align 5 +.globl monitor_vector_base +monitor_vector_base: + nop /* RESET */ + b mon_undef_entry /* UNDEF */ + b mon_swi_entry /* SWI */ + b mon_inst_abort_entry /* IABORT */ + b mon_data_abort_entry /* DABORT */ + nop /* reserved */ + b mon_irq_entry /* IRQ */ + b mon_fiq_entry /* FIQ */ + + +mon_undef_entry: +1: b 1b + +mon_swi_entry: + srsdb sp, #0x16 @ save return state temporarily on stack + mov lr, #1 @ set exit reason + b go_secure + +mon_inst_abort_entry: + sub lr, lr, #4 + srsdb sp, #0x16 + mov lr, #2 @ set exit reason + b go_secure + +mon_data_abort_entry: + sub lr, lr, #4 + srsdb sp, #0x16 + mov lr, #3 @ set exit reason + b go_secure + +mon_irq_entry: + sub lr, lr, #4 + srsdb sp, #0x16 + mov lr, #4 @ set exit reason + b go_secure + +mon_fiq_entry: + sub lr, lr, #4 @ adjust saved ip + srsdb sp, #0x16 + mov lr, #4 @ set exit reason + b go_secure + +// cps #0x12 @ switch to irq mode +// adr lr, go_nonsecure_after_fiq + 4 @ set lr_irq +// msr spsr, #0xd3 @ set spsr_irq +// b fiq_entry + +/********************************************************************** + * Go to secure world + * + */ +go_secure: + SAVE_NONSECURE_STATE 16 + RESTORE_SECURE_STATE + + mov lr, r3 + msr spsr_cfsx, r4 + movs pc, lr + +/********************************************************************** + * Go to nonsecure world + * + * When the guest was interrupted by an FIQ, we don't need to save + * secure state again, because it is still on top of the stack. + * + */ +//go_nonsecure_after_fiq: +// mov r2, sp @ copy sp_svc to sv_mon +// cps #0x16 +// mov sp, r2 +// cps #0x13 +// b go_nonsecure_after_fiq_2 + +.globl go_nonsecure +go_nonsecure: + SAVE_SECURE_STATE + RESTORE_NONSECURE_STATE 16 + SWITCH_TO_NONSECURE_MODE + +// mcr p15, 0, lr, c7, c10, 4 @ drain write buffer +// mcr p15, 0, lr, c8, c7, 0 @ flush TLB entry + + ldr lr, [sp, #-4] + msr spsr, lr @ set spsr_mon with unsecure spsr + ldr lr, [sp, #-8] @ set lr_mon with unsecure ip + movs pc, lr +#endif + +/* -------------------------------------- TEXT ---------------------------*/ + +.text + .global vcpu_resume +vcpu_resume: + add sp, r1, #RF_SIZE + add lr, r0, #8 + ldr r1, [lr, #RF(PSR, 13*4)] @ Unstack SPSR + msr spsr, r1 @ Load SPSR from kernel_lr + ldmia lr!, {r0 - r12} + ldmia lr, {sp,lr}^ @ restore user sp and lr (now lazy) +#if defined(CONFIG_ARM_V6PLUS) + add lr, lr, #RF_SIZE @ Read return address + rfedb lr +#else + add lr, lr, #(RF_SIZE - 4) @ Read return address + ldmdb lr, {pc}^ @ go back to interrupted insn +#endif diff --git a/kernel/fiasco/src/kern/arm/kdb_ke-arm.cpp b/kernel/fiasco/src/kern/arm/kdb_ke-arm.cpp new file mode 100644 index 00000000..edf4b33a --- /dev/null +++ b/kernel/fiasco/src/kern/arm/kdb_ke-arm.cpp @@ -0,0 +1,8 @@ +INTERFACE [arm]: + +void kdb_ke(const char *msg) asm ("kern_kdebug_entry") +__attribute__((long_call)); + +void kdb_ke_sequence(const char *msg) asm ("kern_kdebug_sequence_entry") +__attribute__((long_call)); + diff --git a/kernel/fiasco/src/kern/arm/kern_lib_page.cpp b/kernel/fiasco/src/kern/arm/kern_lib_page.cpp new file mode 100644 index 00000000..72738b36 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/kern_lib_page.cpp @@ -0,0 +1,144 @@ +INTERFACE [arm]: + +class Kern_lib_page +{ +public: + static void init(); +}; + + +//--------------------------------------------------------------------------- +IMPLEMENTATION [arm]: + +#include + +#include "kmem_alloc.h" +#include "kmem_space.h" +#include "pagetable.h" +#include "ram_quota.h" + +IMPLEMENT +void Kern_lib_page::init() +{ + extern char kern_lib_start; + Pte pte = Kmem_space::kdir()->walk((void *)Kmem_space::Kern_lib_base, + Config::PAGE_SIZE, true, + Kmem_alloc::q_allocator(Ram_quota::root), + Kmem_space::kdir()); + + if (pte.lvl() == 0) // allocation of second level faild + panic("FATAL: Error mapping kernel-lib page to %p\n", + (void *)Kmem_space::Kern_lib_base); + + pte.set((Address)&kern_lib_start - Mem_layout::Map_base + + Mem_layout::Sdram_phys_base, + Config::PAGE_SIZE, Mem_page_attr(Page::USER_RO | Page::CACHEABLE), + true); +} + +//--------------------------------------------------------------------------- +IMPLEMENTATION [arm && !armv6plus]: + +asm ( + ".p2align(12) \n" + "kern_lib_start: \n" + + // atomic add + // r0: memory reference + // r1: delta value + " ldr r2, [r0] \n" + " add r2, r2, r1 \n" + " nop \n" + " str r2, [r0] \n" + // forward point + " mov r0, r2 \n" + " mov pc, lr \n" + // return: always succeeds, new value + + // compare exchange + // r0: memory reference + // r1: cmp value + // r2: new value + ".p2align(8) \n" + " ldr r3, [r0] \n" + " cmp r3, r1 \n" + " nop \n" + " streq r2, [r0] \n" + // forward point + " moveq r0, #1 \n" + " movne r0, #0 \n" + " mov pc, lr \n" + // return result: 1 success, 0 failure + + // exchange + // in-r0: memory reference + // in-r1: new value + // out-r0: old value + ".p2align(8) \n" + " ldr r2, [r0] \n" + " nop \n" + " nop \n" + " str r1, [r0] \n" + // forward point + " mov r0, r2 \n" + " mov pc, lr \n" + // return: always succeeds, old value + ); + +//--------------------------------------------------------------------------- +IMPLEMENTATION [arm && armv6plus]: + +asm ( + ".p2align(12) \n" + "kern_lib_start: \n" + + // no restart through kernel entry code + + // atomic add + // r0: memory reference + // r1: delta value + // r2: temp register + // r3: temp register + " 1: \n" + " ldrex r2, [r0] \n" + " add r2, r2, r1 \n" + " strex r3, r2, [r0] \n" + " teq r3, #0 \n" + " bne 1b \n" + " mov r0, r2 \n" + " mov pc, lr \n" + // return: always succeeds, new value + + + // compare exchange + // r0: memory reference + // r1: cmp value + // r2: new value + // r3: tmp reg + ".p2align(8) \n" + " 1: ldrex r3, [r0] \n" + " cmp r3, r1 \n" + " movne r0, #0 \n" + " movne pc, lr \n" + " strex r3, r2, [r0] \n" + " teq r3, #0 \n" + " bne 1b \n" + " mov r0, #1 \n" + " mov pc, lr \n" + // return result: 1 success, 0 failure + + + // exchange + // in-r0: memory reference + // in-r1: new value + // out-r0: old value + ".p2align(8) \n" + " 1: \n" + " ldrex r2, [r0] \n" + " strex r3, r1, [r0] \n" + " cmp r3, #0 \n" + " bne 1b \n" + " mov r0, r2 \n" + " mov pc, lr \n" + // return: always succeeds, old value + ); diff --git a/kernel/fiasco/src/kern/arm/kernel_task-arm.cpp b/kernel/fiasco/src/kern/arm/kernel_task-arm.cpp new file mode 100644 index 00000000..0160508d --- /dev/null +++ b/kernel/fiasco/src/kern/arm/kernel_task-arm.cpp @@ -0,0 +1,11 @@ +IMPLEMENTATION[arm]: + +#include "config.h" +#include "globals.h" +#include "kmem_space.h" + +PRIVATE inline NEEDS["globals.h", "kmem_space.h"] +Kernel_task::Kernel_task() +: Task(Ram_quota::root, Kmem_space::kdir()) +{} + diff --git a/kernel/fiasco/src/kern/arm/kernel_thread-arm.cpp b/kernel/fiasco/src/kern/arm/kernel_thread-arm.cpp new file mode 100644 index 00000000..10a00413 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/kernel_thread-arm.cpp @@ -0,0 +1,103 @@ +IMPLEMENTATION [arm]: + +#include "boot_info.h" +#include "config.h" + +IMPLEMENT inline +void +Kernel_thread::free_initcall_section() +{ + //memset( &_initcall_start, 0, &_initcall_end - &_initcall_start ); +} + +IMPLEMENT FIASCO_INIT +void +Kernel_thread::bootstrap_arch() +{ + Proc::sti(); + + boot_app_cpus(); +} + +//-------------------------------------------------------------------------- +IMPLEMENTATION [!mp]: + +static void inline +Kernel_thread::boot_app_cpus() +{} + + +//-------------------------------------------------------------------------- +IMPLEMENTATION [mp]: + +#include "boot_mp.h" +#include "io.h" +#include "pagetable.h" +#include "outer_cache.h" + +#include + +static void +Kernel_thread::boot_app_cpus() +{ + Boot_mp bmp; + + extern char _tramp_mp_entry[]; + extern volatile Mword _tramp_mp_startup_cp15_c1; + extern volatile Mword _tramp_mp_startup_pdbr; + extern volatile Mword _tramp_mp_start_dcr; + + unsigned num_ap_cpus = (Io::read(Mem_layout::Mp_scu_map_base + 4) & 3); + + printf("Number of CPUs: %d\n", num_ap_cpus + 1); + + _tramp_mp_startup_cp15_c1 = Config::Cache_enabled + ? Cpu::Cp15_c1_cache_enabled : Cpu::Cp15_c1_cache_disabled; + _tramp_mp_startup_pdbr + = Mem_space::kernel_space()->virt_to_phys((Address)Mem_space::kernel_space()->dir()) + | Page_table::Ttbr_bits; + _tramp_mp_start_dcr = 0x55555555; + + __asm__ __volatile__ ("" : : : "memory"); + Mem_unit::clean_dcache(); + + Outer_cache::clean(Mem_space::kernel_space()->virt_to_phys((Address)&_tramp_mp_startup_cp15_c1)); + Outer_cache::clean(Mem_space::kernel_space()->virt_to_phys((Address)&_tramp_mp_startup_pdbr)); + Outer_cache::clean(Mem_space::kernel_space()->virt_to_phys((Address)&_tramp_mp_start_dcr)); + + bmp.start_ap_cpus(Mem_space::kernel_space()->virt_to_phys((Address)_tramp_mp_entry)); + + printf("Waiting for %d CPUs to come up\n", num_ap_cpus); + while (1) + { + Mem::dmb(); + if (num_ap_cpus == Config::num_ap_cpus) + break; + for (unsigned i = 0; i < 1000; ++i) + asm volatile("nop"); + } + + bmp.cleanup(); + + printf("Done waiting CPUs\n"); +} + +//-------------------------------------------------------------------------- +IMPLEMENTATION [arm && generic_tickless_idle]: + +#include "mem_unit.h" +#include "processor.h" + +PROTECTED inline NEEDS["processor.h", "mem_unit.h"] +void +Kernel_thread::arch_tickless_idle(unsigned) +{ + Mem_unit::tlb_flush(); + Proc::halt(); +} + +PROTECTED inline NEEDS["processor.h"] +void +Kernel_thread::arch_idle(unsigned) +{ Proc::halt(); } + diff --git a/kernel/fiasco/src/kern/arm/kip_init.cpp b/kernel/fiasco/src/kern/arm/kip_init.cpp new file mode 100644 index 00000000..534b6cd9 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/kip_init.cpp @@ -0,0 +1,74 @@ +INTERFACE [arm]: + +#include "kip.h" + +class Kip_init +{ +public: + static void init(); +}; + + +//--------------------------------------------------------------------------- +IMPLEMENTATION [arm]: + +#include + +#include "config.h" +#include "panic.h" +#include "boot_info.h" +#include "kmem.h" + + +// Make the stuff below apearing only in this compilation unit. +// Trick Preprocess to let the struct reside in the cc file rather +// than putting it into the _i.h file which is perfectly wrong in +// this case. +namespace KIP_namespace +{ + enum + { + Num_mem_descs = 20, + Max_len_version = 512, + + Size_mem_descs = sizeof(Mword) * 2 * Num_mem_descs, + }; + + struct KIP + { + Kip kip; + char mem_descs[Size_mem_descs]; + }; + + KIP my_kernel_info_page asm("my_kernel_info_page") __attribute__((section(".kernel_info_page"))) = + { + { + /* 00/00 */ L4_KERNEL_INFO_MAGIC, + Config::Kernel_version_id, + (Size_mem_descs + sizeof(Kip)) >> 4, + {}, 0, {}, + /* 10/20 */ 0, {}, + /* 20/40 */ 0, 0, {}, + /* 30/60 */ 0, 0, {}, + /* 40/80 */ 0, 0, {}, + /* 50/A0 */ 0, (sizeof(Kip) << (sizeof(Mword)*4)) | Num_mem_descs, {}, + /* 60/C0 */ {}, + /* A0/140 */ 0, 0, 0, 0, + /* B0/160 */ {}, + /* E0/1C0 */ 0, 0, {}, + /* F0/1D0 */ {0, 0}, {}, + }, + {} + }; +}; + +IMPLEMENT +void Kip_init::init() +{ + Kip *kinfo = reinterpret_cast(&KIP_namespace::my_kernel_info_page); + Kip::init_global_kip(kinfo); + kinfo->add_mem_region(Mem_desc(0, Mem_layout::User_max - 1, + Mem_desc::Conventional, true)); + asm volatile("mrc p15, 0, %0, c0, c0, 0" : "=r" (kinfo->platform_info.cpuid)); + kinfo->platform_info.mp = Config::Max_num_cpus > 1; +} diff --git a/kernel/fiasco/src/kern/arm/kmem.cpp b/kernel/fiasco/src/kern/arm/kmem.cpp new file mode 100644 index 00000000..d58fa6d8 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/kmem.cpp @@ -0,0 +1,30 @@ +INTERFACE [arm]: + +#include "kip.h" +#include "mem_layout.h" + +class Kmem : public Mem_layout +{ +public: + + static Mword is_kmem_page_fault( Mword pfa, Mword error ); + static Mword is_ipc_page_fault( Mword pfa, Mword error ); + static Mword is_io_bitmap_page_fault( Mword pfa ); + + static Mword ipc_window( unsigned num ); +}; + +//--------------------------------------------------------------------------- +IMPLEMENTATION [arm]: + +IMPLEMENT inline +Mword Kmem::is_kmem_page_fault( Mword pfa, Mword /*error*/ ) +{ + return in_kernel(pfa); +} + +IMPLEMENT inline +Mword Kmem::is_io_bitmap_page_fault( Mword /*pfa*/ ) +{ + return 0; +} diff --git a/kernel/fiasco/src/kern/arm/kmem_alloc-arm.cpp b/kernel/fiasco/src/kern/arm/kmem_alloc-arm.cpp new file mode 100644 index 00000000..8d3bd290 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/kmem_alloc-arm.cpp @@ -0,0 +1,87 @@ +IMPLEMENTATION [arm]: + +#include "mem_unit.h" +#include "kmem_space.h" +#include "pagetable.h" +#include "ram_quota.h" + + +PRIVATE //inline +bool +Kmem_alloc::map_pmem(unsigned long phy, unsigned long size) +{ + static unsigned long next_map = Mem_layout::Map_base + (4 << 20); + size = Mem_layout::round_superpage(size + (phy & ~Config::SUPERPAGE_MASK)); + phy = Mem_layout::trunc_superpage(phy); + + if (next_map + size > Mem_layout::Map_end) + return false; + + for (unsigned long i = 0; i walk((char*)next_map+i, + Config::SUPERPAGE_SIZE, false, Ptab::Null_alloc(), + Kmem_space::kdir()); + pte.set(phy+i, Config::SUPERPAGE_SIZE, + Mem_page_attr(Page::KERN_RW | Page::CACHEABLE), + true); + + } + Mem_layout::add_pmem(phy, next_map, size); + next_map += size; + return true; +} + +IMPLEMENT +Kmem_alloc::Kmem_alloc() +{ + // The -Wframe-larger-than= warning for this function is known and + // no problem, because the function runs only on our boot stack. + Mword alloc_size = Config::KMEM_SIZE; + a->init(Mem_layout::Map_base); + Mem_region_map<64> map; + unsigned long available_size = create_free_map(Kip::k(), &map); + + // sanity check whether the KIP has been filled out, number is arbitrary + if (available_size < (1 << 18)) + panic("Kmem_alloc: No kernel memory available (%ld)\n", + available_size); + + for (int i = map.length() - 1; i >= 0 && alloc_size > 0; --i) + { + Mem_region f = map[i]; + if (f.size() > alloc_size) + f.start += (f.size() - alloc_size); + + Kip::k()->add_mem_region(Mem_desc(f.start, f.end, + Mem_desc::Reserved)); + //printf("ALLOC1: [%08lx; %08lx] sz=%ld\n", f.start, f.end, f.size()); + if (Mem_layout::phys_to_pmem(f.start) == ~0UL) + if (!map_pmem(f.start, f.size())) + panic("Kmem_alloc: cannot map physical memory %p\n", (void*)f.start); + a->add_mem((void*)Mem_layout::phys_to_pmem(f.start), f.size()); + alloc_size -= f.size(); + } + + if (alloc_size) + WARNX(Warning, "Kmem_alloc: cannot allocate sufficient kernel memory\n"); +} + +//---------------------------------------------------------------------------- +IMPLEMENTATION [arm && debug]: + +#include + +#include "kip_init.h" +#include "panic.h" + +PUBLIC +void Kmem_alloc::debug_dump() +{ + a->dump(); + + unsigned long free = a->avail(); + printf("Used %ldKB out of %dKB of Kmem\n", + (Config::KMEM_SIZE - free + 1023)/1024, + (Config::KMEM_SIZE + 1023)/1024); +} diff --git a/kernel/fiasco/src/kern/arm/kmem_space.cpp b/kernel/fiasco/src/kern/arm/kmem_space.cpp new file mode 100644 index 00000000..9a993379 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/kmem_space.cpp @@ -0,0 +1,48 @@ +INTERFACE [arm]: + +#include "kmem.h" + +class Page_table; + +class Kmem_space : public Kmem +{ +public: + static void init(); + static void init_hw(); + static Page_table *kdir(); + +private: + static Page_table *_kdir; +}; + +//--------------------------------------------------------------------------- +IMPLEMENTATION [arm]: + +#include +#include + +#include "console.h" +#include "pagetable.h" +#include "kmem.h" +#include "kip_init.h" +#include "mem_unit.h" + +#include + +char kernel_page_directory[sizeof(Page_table)] __attribute__((aligned(0x4000))); + +Page_table *Kmem_space::_kdir = (Page_table*)&kernel_page_directory; + +IMPLEMENT inline +Page_table *Kmem_space::kdir() +{ return _kdir; } + +// initialze the kernel space (page table) +IMPLEMENT +void Kmem_space::init() +{ + Page_table::init(); + + Mem_unit::clean_vdcache(); +} + diff --git a/kernel/fiasco/src/kern/arm/logdefs.h b/kernel/fiasco/src/kern/arm/logdefs.h new file mode 100644 index 00000000..7e46d2bc --- /dev/null +++ b/kernel/fiasco/src/kern/arm/logdefs.h @@ -0,0 +1,238 @@ +#ifndef LOGDEFS_H +#define LOGDEFS_H + +// ### How to create a tracebuffer entry ### +// +// If you only need a temporary debugging aid then you can use one of +// the standard kernel logging events: +// +// LOG_MSG(Context *context, const char *msg) +// - context is something like context_of(this) or current_context() +// or 0 if there is no context available +// - msg should be displayed in the tracebuffer view +// +// LOG_MSG_3VAL(Context *context, const char *msg, +// Mword val1, Mword val2, Mword val3) +// - context and msg can be used the same way LOG_MSG does +// - val1, val2, and val3 are values that will be displayed in +// the tracebuffer view as hexadecimal values +// +// If you want to create a permanent log event xyz, you have to follow +// these instructions: +// - create enum Log_event_xyz (see jdb_ktrace.cpp) +// - create class Tb_entry_xyz derived from Tb_entry (see tb_entry.cpp) +// with an appropriate ::set method and with accessor methods +// - create function formatter_xyz (see tb_entry_output.cpp) and don't +// forget to register it (add an appropriate line to init_formatters) +// - create macro LOG_XYZ (see the following example) +// #define LOG_XYZ +// BEGIN_LOG_EVENT(log_xyz) +// Lock_guard guard (&cpu_lock); +// Tb_entry_xyz *tb = +// static_cast(Jdb_tbuf::new_entry()); +// tb->set (this, ) +// Jdb_tbuf::commit_entry(); +// END_LOG_EVENT +// (grabbing the cpu_lock isn't necessary if it is still grabbed) +// - create an empty macro declaration for CONFIG_JDB_LOGGING=n +// - insert the macro call into the code +// - WARNING: permanent log events should _not_ be placed into an inline +// function! +// - add +// DECLARE_PATCH (lp, log_xyz); +// static Log_event le(, +// Log_event_xyz, 1, &lp); +// and create an entry le for Jdb_tbuf_events::log_events[] +// (see jdb_tbuf_events.cpp) + +#include "globalconfig.h" + +#if defined(CONFIG_JDB) + +#include "globals.h" +#include "jdb_tbuf.h" +#include "cpu_lock.h" +#include "lock_guard.h" +#include "processor.h" + +#define LOG_CONTEXT_SWITCH \ + BEGIN_LOG_EVENT("Context switch", "csw", 0) \ + Tb_entry_ctx_sw *tb = \ + static_cast(Jdb_tbuf::new_entry()); \ + tb->set(this, space(), regs()->ip(), t, t_orig, \ + t_orig->lock_cnt(), current_sched(), \ + current_sched() ? current_sched()->prio() : 0, \ + (Mword)__builtin_return_address(0)); \ + Jdb_tbuf::commit_entry(); \ + END_LOG_EVENT + +#define LOG_TRAP \ + BEGIN_LOG_EVENT("Exceptions", "exc", 0) \ + Tb_entry_trap *tb = \ + static_cast(Jdb_tbuf::new_entry()); \ + tb->set(current_thread(), ts); \ + Jdb_tbuf::commit_entry(); \ + END_LOG_EVENT + +#define LOG_TRAP_N(n) \ + BEGIN_LOG_EVENT("Exception n", "exc", 0) \ + Tb_entry_trap *tb = \ + static_cast(Jdb_tbuf::new_entry()); \ + Mword ip = (Mword)(__builtin_return_address(0)); \ + tb->set(current(), ip, n); \ + Jdb_tbuf::commit_entry(); \ + END_LOG_EVENT + +#define LOG_PF_RES_USER \ + BEGIN_LOG_EVENT("Page-fault results", "pfr", 0) \ + Tb_entry_pf_res *tb = \ + static_cast(Jdb_tbuf::new_entry()); \ + tb->set(this, regs()->ip(), pfa, err, ret); \ + Jdb_tbuf::commit_entry(); \ + END_LOG_EVENT + +#define LOG_SCHED_SAVE(cs) \ + BEGIN_LOG_EVENT("Scheduling context save", "sch", 0) \ + Tb_entry_sched *tb = \ + static_cast(Jdb_tbuf::new_entry()); \ + tb->set (current(), 0, 0, \ + cs->context(), \ + 0, \ + cs->prio(), \ + cs->left(), \ + cs->quantum()); \ + Jdb_tbuf::commit_entry(); \ + END_LOG_EVENT + +#define LOG_SCHED_LOAD(cs) \ + BEGIN_LOG_EVENT("Scheduling context load", "sch", 0) \ + Tb_entry_sched *tb = \ + static_cast(Jdb_tbuf::new_entry()); \ + tb->set (current(), 0, 1, \ + cs->context(), \ + 0, \ + cs->prio(), \ + cs->left(), \ + cs->quantum()); \ + Jdb_tbuf::commit_entry(); \ + END_LOG_EVENT + +#define LOG_SCHED_INVALIDATE \ + BEGIN_LOG_EVENT("Schduling context invalidate", "sch", 0) \ + Tb_entry_sched *tb = \ + static_cast(Jdb_tbuf::new_entry()); \ + tb->set (current(), current()->regs()->ip(), 2, \ + current_sched()->context(), \ + current_sched()->id(), \ + current_sched()->prio(), \ + timeslice_timeout.cpu(cpu())->get_timeout(Kip::k()->clock), \ + current_sched()->quantum()); \ + Jdb_tbuf::commit_entry(); \ + END_LOG_EVENT + +#define LOG_SEND_PREEMPTION \ + BEGIN_LOG_EVENT("Preemption events", "pre", 0) \ + Lock_guard guard (&cpu_lock); \ + Tb_entry_preemption *tb = \ + static_cast(Jdb_tbuf::new_entry()); \ + tb->set (context_of(this), _receiver.raw(), current()->regs()->ip()); \ + Jdb_tbuf::commit_entry(); \ + END_LOG_EVENT + +/* + * Kernel instrumentation macro used by fm3. Do not remove! + */ +#define LOG_MSG(context, text) \ + do { \ + /* The cpu_lock is needed since virq::hit() depends on it */ \ + Lock_guard guard (&cpu_lock); \ + Tb_entry_ke *tb = static_cast(Jdb_tbuf::new_entry()); \ + tb->set_const(context, Proc::program_counter(), text); \ + Jdb_tbuf::commit_entry(); \ + } while (0) + +/* + * Kernel instrumentation macro used by fm3. Do not remove! + */ +#define LOG_MSG_3VAL(context, text, v1, v2, v3) \ + do { \ + /* The cpu_lock is needed since virq::hit() depends on it */ \ + Lock_guard guard (&cpu_lock); \ + Tb_entry_ke_reg *tb = \ + static_cast(Jdb_tbuf::new_entry()); \ + tb->set_const(context, Proc::program_counter(), text, v1, v2, v3); \ + Jdb_tbuf::commit_entry(); \ + } while (0) + + +#define LOG_TRACE(name, sc, ctx, fmt, code...) \ + BEGIN_LOG_EVENT(name, sc, fmt) \ + Tb_entry *tbe = Jdb_tbuf::new_entry(); \ + tbe->set_global(__do_log__, ctx, Proc::program_counter()); \ + code ; \ + Jdb_tbuf::commit_entry(); \ + END_LOG_EVENT + + +#else + +#define LOG_TRACE(name, sc, ctx, fmt, code...) do { } while (0) +#define LOG_CONTEXT_SWITCH do { } while (0) +#define LOG_TRAP do { } while (0) +#define LOG_TRAP_N(n) do { } while (0) +#define LOG_PF_RES_USER do { } while (0) +#define LOG_SCHED do { } while (0) +#define LOG_SCHED_SAVE(n) do { } while (0) +#define LOG_SCHED_LOAD(n) do { } while (0) +#define LOG_SCHED_INVALIDATE do { } while (0) +#define LOG_SEND_PREEMPTION do { } while (0) + +#endif // CONFIG_JDB + +#if defined(CONFIG_JDB) && defined(CONFIG_JDB_ACCOUNTING) + +#error ARM does not have CONFIG_JDB_ACCOUNTING + +#define CNT_CONTEXT_SWITCH \ + Jdb_tbuf::status()->kerncnts[Kern_cnt_context_switch]++; +#define CNT_ADDR_SPACE_SWITCH \ + Jdb_tbuf::status()->kerncnts[Kern_cnt_addr_space_switch]++; +#define CNT_SHORTCUT_FAILED \ + Jdb_tbuf::status()->kerncnts[Kern_cnt_shortcut_failed]++; +#define CNT_SHORTCUT_SUCCESS \ + Jdb_tbuf::status()->kerncnts[Kern_cnt_shortcut_success]++; +#define CNT_IRQ \ + Jdb_tbuf::status()->kerncnts[Kern_cnt_irq]++; +#define CNT_IPC_LONG \ + Jdb_tbuf::status()->kerncnts[Kern_cnt_ipc_long]++; +#define CNT_PAGE_FAULT \ + Jdb_tbuf::status()->kerncnts[Kern_cnt_page_fault]++; +#define CNT_IO_FAULT \ + Jdb_tbuf::status()->kerncnts[Kern_cnt_io_fault]++; +#define CNT_TASK_CREATE \ + Jdb_tbuf::status()->kerncnts[Kern_cnt_task_create]++; +#define CNT_SCHEDULE \ + Jdb_tbuf::status()->kerncnts[Kern_cnt_schedule]++; +#define CNT_IOBMAP_TLB_FLUSH \ + Jdb_tbuf::status()->kerncnts[Kern_cnt_iobmap_tlb_flush]++; +#define CNT_EXC_IPC \ + Jdb_tbuf::status()->kerncnts[Kern_cnt_exc_ipc]++; + +#else + +#define CNT_CONTEXT_SWITCH do { } while (0) +#define CNT_ADDR_SPACE_SWITCH do { } while (0) +#define CNT_SHORTCUT_FAILED do { } while (0) +#define CNT_SHORTCUT_SUCCESS do { } while (0) +#define CNT_IRQ do { } while (0) +#define CNT_IPC_LONG do { } while (0) +#define CNT_PAGE_FAULT do { } while (0) +#define CNT_IO_FAULT do { } while (0) +#define CNT_TASK_CREATE do { } while (0) +#define CNT_SCHEDULE do { } while (0) +#define CNT_IOBMAP_TLB_FLUSH do { } while (0) +#define CNT_EXC_IPC do { } while (0) + +#endif // CONFIG_JDB && CONFIG_JDB_ACCOUNTING + +#endif diff --git a/kernel/fiasco/src/kern/arm/main.cpp b/kernel/fiasco/src/kern/arm/main.cpp new file mode 100644 index 00000000..aead15ad --- /dev/null +++ b/kernel/fiasco/src/kern/arm/main.cpp @@ -0,0 +1,152 @@ +INTERFACE [arm]: +#include + +//--------------------------------------------------------------------------- +IMPLEMENTATION [arm]: + +#include +#include +#include + +#include "config.h" +#include "globals.h" +#include "initcalls.h" +#include "kmem_alloc.h" +#include "kip_init.h" +#include "pagetable.h" +#include "kdb_ke.h" +#include "kernel_thread.h" +#include "kernel_task.h" +#include "kernel_console.h" +#include "reset.h" +#include "space.h" +#include "terminate.h" + +#include "processor.h" + +static int exit_question_active = 0; + +extern "C" void __attribute__ ((noreturn)) +_exit(int) +{ + if (exit_question_active) + platform_reset(); + + while (1) + { + Proc::halt(); + Proc::pause(); + } +} + + +static void exit_question() +{ + exit_question_active = 1; + + while (1) + { + puts("\nReturn reboots, \"k\" enters L4 kernel debugger..."); + + char c = Kconsole::console()->getchar(); + + if (c == 'k' || c == 'K') + { + kdb_ke("_exit"); + } + else + { + // it may be better to not call all the destruction stuff + // because of unresolved static destructor dependency + // problems. + // SO just do the reset at this point. + puts("\033[1mRebooting...\033[0m"); + platform_reset(); + break; + } + } +} + +void +kernel_main() +{ + // caution: no stack variables in this function because we're going + // to change the stack pointer! + + // make some basic initializations, then create and run the kernel + // thread + set_exit_question(&exit_question); + + printf("%s\n", Kip::k()->version_string()); + + // disallow all interrupts before we selectively enable them + // pic_disable_all(); + + // create kernel thread + static Kernel_thread *kernel = new (Ram_quota::root) Kernel_thread; + Task *const ktask = Kernel_task::kernel_task(); + check(kernel->bind(ktask, User::Ptr(0))); + + Mem_unit::tlb_flush(); + + // switch to stack of kernel thread and bootstrap the kernel + asm volatile + (" mov sp,%0 \n" // switch stack + " mov r0,%1 \n" // push "this" pointer + " bl call_bootstrap \n" + : : "r" (kernel->init_stack()), "r" (kernel)); +} + +//------------------------------------------------------------------------ +IMPLEMENTATION[arm && mp]: + +#include +#include "config.h" +#include "cpu.h" +#include "globals.h" +#include "app_cpu_thread.h" +#include "ipi.h" +#include "per_cpu_data_alloc.h" +#include "perf_cnt.h" +#include "pic.h" +#include "spin_lock.h" +#include "timer.h" +#include "utcb_init.h" + + +int boot_ap_cpu(unsigned cpu) __asm__("BOOT_AP_CPU"); + +int boot_ap_cpu(unsigned _cpu) +{ + if (!Per_cpu_data_alloc::alloc(_cpu)) + { + extern Spin_lock _tramp_mp_spinlock; + printf("CPU allocation failed for CPU%u, disabling CPU.\n", _cpu); + _tramp_mp_spinlock.clear(); + while (1) + Proc::halt(); + } + Per_cpu_data::run_ctors(_cpu); + Cpu &cpu = Cpu::cpus.cpu(_cpu); + cpu.init(); + + Pic::init_ap(); + Ipi::init(_cpu); + Timer::init(_cpu); + Perf_cnt::init_ap(); + + // create kernel thread + App_cpu_thread *kernel = new (Ram_quota::root) App_cpu_thread(); + set_cpu_of(kernel, _cpu); + check(kernel->bind(Kernel_task::kernel_task(), User::Ptr(0))); + + // switch to stack of kernel thread and bootstrap the kernel + asm volatile + (" mov sp,%0 \n" // switch stack + " mov r0,%1 \n" // push "this" pointer + " bl call_ap_bootstrap \n" + : + : "r" (kernel->init_stack()), "r" (kernel)); + return 0; +} + diff --git a/kernel/fiasco/src/kern/arm/mapping-arm.cpp b/kernel/fiasco/src/kern/arm/mapping-arm.cpp new file mode 100644 index 00000000..ff8d324b --- /dev/null +++ b/kernel/fiasco/src/kern/arm/mapping-arm.cpp @@ -0,0 +1,25 @@ +INTERFACE [arm]: + +#include "types.h" +class Treemap; +class Space; + +class Mapping_entry +{ +public: + enum { Alignment = 4 }; + union + { + struct + { + unsigned long _space:32; ///< Address-space number +/* unsigned long _pad:1; */ + unsigned long address:20; ///< Virtual address in address space + } data; + Treemap *_submap; + }; + Unsigned8 _depth; + void set_space(Space *s) { data._space = (unsigned long)s; } + Space *space() const { return (Space *)data._space; } +}; + diff --git a/kernel/fiasco/src/kern/arm/mem_layout-arm.cpp b/kernel/fiasco/src/kern/arm/mem_layout-arm.cpp new file mode 100644 index 00000000..0637460c --- /dev/null +++ b/kernel/fiasco/src/kern/arm/mem_layout-arm.cpp @@ -0,0 +1,135 @@ +INTERFACE [arm && !kern_start_0xd]: + +EXTENSION class Mem_layout +{ +public: + enum Virt_layout_umax { + User_max = 0xc0000000, + }; +}; + + +//--------------------------------------------------------------------------- +INTERFACE [arm && kern_start_0xd]: + +EXTENSION class Mem_layout +{ +public: + enum Virt_layout_umax { + User_max = 0xd0000000, + }; +}; + + +//--------------------------------------------------------------------------- +INTERFACE [arm]: + +#include "template_math.h" + +EXTENSION class Mem_layout +{ +public: + enum Virt_layout { + Utcb_addr = User_max - 0x10000, + Service_page = 0xeac00000, + Tbuf_status_page = Service_page + 0x5000, + Tbuf_ustatus_page = Tbuf_status_page, + Tbuf_buffer_area = Service_page + 0x200000, + Tbuf_ubuffer_area = Tbuf_buffer_area, + Jdb_tmp_map_area = Service_page + 0x400000, + __free_1_start = 0xee000000, + __free_1_end = 0xef000000, + Cache_flush_area = 0xef000000, + Cache_flush_area_end = 0xef100000, + Registers_map_start = 0xef100000, + Registers_map_end = 0xef500000, + Map_base = 0xf0000000, + Map_end = 0xf5000000, + Caps_start = 0xf5000000, + Caps_end = 0xfd000000, + Utcb_ptr_page = 0xffffd000, + // don't care about caches here, because arm uses a register on MP + utcb_ptr_align = Tl_math::Ld::Res, + Kern_lib_base = 0xffffe000, + Ivt_base = 0xffff0000, + Syscalls = 0xfffff000, + + Kernel_max = 0x00000000, + }; +}; + +// ------------------------------------------------------------------------- +IMPLEMENTATION [arm]: + +//--------------------------------- +// Workaround GCC BUG 33661 +// Do not use register asm ("r") in a template function, it will be ignored +//--------------------------------- +PUBLIC static inline +bool +Mem_layout::_read_special_safe(Mword const *address, Mword &v) +{ + register Mword a asm("r14") = (Mword)address; + Mword ret; + asm volatile ("msr cpsr_f, #0 \n" // clear flags + "ldr %[a], [%[a]] \n" + "movne %[ret], #1 \n" + "moveq %[ret], #0 \n" + + : [a] "=r" (a), [ret] "=r" (ret) + : "0" (a) + : "cc"); + v = a; + return ret; +} + +PUBLIC static inline +template< typename V > +bool +Mem_layout::read_special_safe(V const *address, V &v) +{ + Mword _v; + bool ret = _read_special_safe(reinterpret_cast(address), _v); + v = V(_v); + return ret; +} + +//--------------------------------- +// Workaround GCC BUG 33661 +// Do not use register asm ("r") in a template function, it will be ignored +//--------------------------------- +PUBLIC static inline +Mword +Mem_layout::_read_special_safe(Mword const *a) +{ + register Mword const *res __asm__ ("r14") = a; + __asm__ __volatile__ ("ldr %0, [%0]\n" : "=r" (res) : "r" (res) : "cc" ); + return Mword(res); +} + +PUBLIC static inline +template< typename T > +T +Mem_layout::read_special_safe(T const *a) +{ + return T(_read_special_safe((Mword const *)a)); +#if 0 + Mword res; + asm volatile ("msr cpsr_f, #0; ldr %0, [%1]; moveq %0, #0\n" + : "=r" (res) : "r" (a) : "cc"); + return T(res); +#endif +} + +PUBLIC static inline +bool +Mem_layout::is_special_mapped(void const *a) +{ + register Mword pagefault_if_0 asm("r14"); + asm volatile ("msr cpsr_f, #0 \n" // clear flags + "ldr %0, [%0] \n" + "movne %0, #1 \n" + "moveq %0, #0 \n" + : "=r" (pagefault_if_0) : "0" (a) : "cc"); + return pagefault_if_0; +} diff --git a/kernel/fiasco/src/kern/arm/mem_layout-noncont.cpp b/kernel/fiasco/src/kern/arm/mem_layout-noncont.cpp new file mode 100644 index 00000000..7781a2d8 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/mem_layout-noncont.cpp @@ -0,0 +1,69 @@ +INTERFACE [noncont_mem]: + +#include + +EXTENSION class Mem_layout +{ +public: + static Address phys_to_pmem(Address addr); + static void add_pmem(Address phys, Address virt, unsigned long size); + + static inline unsigned long round_superpage(unsigned long addr) + { return (addr + Config::SUPERPAGE_SIZE - 1) & ~(Config::SUPERPAGE_SIZE-1); } + static inline unsigned long trunc_superpage(unsigned long addr) + { return addr & ~(Config::SUPERPAGE_SIZE-1); } +private: + static unsigned short __ph_to_pm[1<<(32-Config::SUPERPAGE_SHIFT)]; +}; + + +IMPLEMENTATION [noncont_mem]: + +#include +#include + +PUBLIC static +Address +Mem_layout::pmem_to_phys (Address addr) +{ + printf("Mem_layout::pmem_to_phys(Address addr=%lx) is not implemented\n", + addr); + return 0; +} + +PUBLIC static inline +Address +Mem_layout::pmem_to_phys(void const *addr) +{ + return pmem_to_phys(Address(addr)); +} +unsigned short Mem_layout::__ph_to_pm[1<<(32-Config::SUPERPAGE_SHIFT)]; + +IMPLEMENT inline NEEDS[] +Address +Mem_layout::phys_to_pmem(Address phys) +{ + Address virt = ((unsigned long)__ph_to_pm[phys >> Config::SUPERPAGE_SHIFT]) + << 16; + + if (!virt) + return ~0UL; + + return virt | (phys & (Config::SUPERPAGE_SIZE-1)); +} + + + +IMPLEMENT inline NEEDS[] +void +Mem_layout::add_pmem(Address phys, Address virt, unsigned long size) +{ + for (;size >= Config::SUPERPAGE_SIZE; size -= Config::SUPERPAGE_SIZE) + { + __ph_to_pm[phys >> Config::SUPERPAGE_SHIFT] = virt >> 16; + phys += Config::SUPERPAGE_SIZE; + virt += Config::SUPERPAGE_SIZE; + } + +} + diff --git a/kernel/fiasco/src/kern/arm/mem_op.cpp b/kernel/fiasco/src/kern/arm/mem_op.cpp new file mode 100644 index 00000000..2b973147 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/mem_op.cpp @@ -0,0 +1,257 @@ +INTERFACE [arm]: + +#include "types.h" + +class Mem_op +{ +public: + enum Op_cache + { + Op_cache_clean_data = 0x00, + Op_cache_flush_data = 0x01, + Op_cache_inv_data = 0x02, + Op_cache_coherent = 0x03, + Op_cache_dma_coherent = 0x04, + Op_cache_dma_coherent_full = 0x05, + Op_cache_l2_clean = 0x06, + Op_cache_l2_flush = 0x07, + Op_cache_l2_inv = 0x08, + }; + + enum Op_mem + { + Op_mem_read_data = 0x10, + Op_mem_write_data = 0x11, + }; +}; + +// ------------------------------------------------------------------------ +IMPLEMENTATION [arm]: + +#include "context.h" +#include "entry_frame.h" +#include "globals.h" +#include "mem.h" +#include "mem_space.h" +#include "mem_unit.h" +#include "outer_cache.h" +#include "space.h" +#include "warn.h" + +PRIVATE static void +Mem_op::l1_inv_dcache(Address start, Address end) +{ + if (start & Mem_unit::Cache_line_mask) + { + Mem_unit::flush_dcache((void *)start, (void *)start); + start += Mem_unit::Cache_line_size; + start &= ~Mem_unit::Cache_line_mask; + } + if (end & Mem_unit::Cache_line_mask) + { + Mem_unit::flush_dcache((void *)end, (void *)end); + end &= ~Mem_unit::Cache_line_mask; + } + + Mem_unit::inv_dcache((void *)start, (void *)end); +} + +PRIVATE static void +Mem_op::inv_icache(Address start, Address end) +{ + if (Address(end) - Address(start) > 0x2000) + asm volatile("mcr p15, 0, r0, c7, c5, 0"); + else + { + for (start &= ~Mem_unit::Icache_line_mask; + start < end; start += Mem_unit::Icache_line_size) + asm volatile("mcr p15, 0, %0, c7, c5, 1" : : "r" (start)); + } +} + +PUBLIC static void +Mem_op::arm_mem_cache_maint(int op, void const *start, void const *end) +{ + Context *c = current(); + + if (EXPECT_FALSE(start > end)) + return; + + c->set_ignore_mem_op_in_progress(true); + + switch (op) + { + case Op_cache_clean_data: + Mem_unit::clean_dcache(start, end); + break; + + case Op_cache_flush_data: + Mem_unit::flush_dcache(start, end); + break; + + case Op_cache_inv_data: + l1_inv_dcache((Address)start, (Address)end); + break; + + case Op_cache_coherent: + Mem_unit::clean_dcache(start, end); + Mem::dsb(); + Mem_unit::btc_inv(); + inv_icache(Address(start), Address(end)); + Mem::dsb(); + break; + + case Op_cache_l2_clean: + case Op_cache_l2_flush: + case Op_cache_l2_inv: + outer_cache_op(op, Address(start), Address(end)); + break; + + case Op_cache_dma_coherent: + { + Mem_unit::flush_dcache(Virt_addr(Address(start)), Virt_addr(Address(end))); + outer_cache_op(Op_cache_l2_flush, Address(start), Address(end)); + } + break; + + // We might not want to implement this one but single address outer + // cache flushing can be really slow + case Op_cache_dma_coherent_full: + Mem_unit::flush_dcache(); + Outer_cache::flush(); + break; + + default: + break; + }; + + c->set_ignore_mem_op_in_progress(false); +} + +PUBLIC static void +Mem_op::arm_mem_access(Mword *r) +{ + Address a = r[1]; + unsigned w = r[2]; + + if (w > 2) + return; + + if (!current()->space()->is_user_memory(a, 1 << w)) + return; + + jmp_buf pf_recovery; + int e; + + if ((e = setjmp(pf_recovery)) == 0) + { + current()->recover_jmp_buf(&pf_recovery); + + switch (r[0]) + { + case Op_mem_read_data: + switch (w) + { + case 0: + r[3] = *(unsigned char *)a; + break; + case 1: + r[3] = *(unsigned short *)a; + break; + case 2: + r[3] = *(unsigned int *)a; + break; + default: + break; + }; + break; + + case Op_mem_write_data: + switch (w) + { + case 0: + *(unsigned char *)a = r[3]; + break; + case 1: + *(unsigned short *)a = r[3]; + break; + case 2: + *(unsigned int *)a = r[3]; + break; + default: + break; + }; + break; + + default: + break; + }; + } + else + WARN("Unresolved memory access, skipping\n"); + + current()->recover_jmp_buf(0); +} + +extern "C" void sys_arm_mem_op() +{ + Entry_frame *e = current()->regs(); + if (EXPECT_FALSE(e->r[0] & 0x10)) + Mem_op::arm_mem_access(e->r); + else + Mem_op::arm_mem_cache_maint(e->r[0], (void *)e->r[1], (void *)e->r[2]); +} + +// ------------------------------------------------------------------------ +IMPLEMENTATION [arm && !outer_cache]: + +PRIVATE static inline +void +Mem_op::outer_cache_op(int, Address, Address) +{} + +// ------------------------------------------------------------------------ +IMPLEMENTATION [arm && outer_cache]: + +PRIVATE static +void +Mem_op::outer_cache_op(int op, Address start, Address end) +{ + Mem_space::Vaddr v = Virt_addr(Address(start)); + Mem_space::Vaddr e = Virt_addr(Address(end)); + + Context *c = current(); + + while (v < e) + { + Mem_space::Size phys_size; + Mem_space::Phys_addr phys_addr; + unsigned attrs; + + if ( c->mem_space()->v_lookup(v, &phys_addr, + &phys_size, &attrs) + && (attrs & Mem_space::Page_user_accessible)) + { + unsigned long sz = Virt_size(phys_size).value(); + if (Address(end) - Address(start) < sz) + sz = Address(end) - Address(start); + switch (op) + { + case Op_cache_l2_clean: + Outer_cache::clean(Virt_addr(phys_addr).value(), + Virt_addr(phys_addr).value() + sz, false); + break; + case Op_cache_l2_flush: + Outer_cache::flush(Virt_addr(phys_addr).value(), + Virt_addr(phys_addr).value() + sz, false); + break; + case Op_cache_l2_inv: + Outer_cache::invalidate(Virt_addr(phys_addr).value(), + Virt_addr(phys_addr).value() + sz, false); + break; + } + } + v += phys_size; + } + Outer_cache::sync(); +} diff --git a/kernel/fiasco/src/kern/arm/mem_space-arm.cpp b/kernel/fiasco/src/kern/arm/mem_space-arm.cpp new file mode 100644 index 00000000..91668f6a --- /dev/null +++ b/kernel/fiasco/src/kern/arm/mem_space-arm.cpp @@ -0,0 +1,572 @@ +INTERFACE [arm]: + +#include "auto_quota.h" +#include "kmem.h" // for "_unused_*" virtual memory regions +#include "member_offs.h" +#include "paging.h" +#include "types.h" +#include "pagetable.h" +#include "ram_quota.h" + +EXTENSION class Mem_space +{ + friend class Jdb; + +public: + typedef Page_table Dir_type; + + /** Return status of v_insert. */ + enum // Status + { + Insert_ok = Page_table::E_OK, ///< Mapping was added successfully. + Insert_err_nomem = Page_table::E_NOMEM, ///< Couldn't alloc new page table + Insert_err_exists = Page_table::E_EXISTS, ///< A mapping already exists at the target addr + Insert_warn_attrib_upgrade = Page_table::E_UPGRADE, ///< Mapping already existed, attribs upgrade + Insert_warn_exists, ///< Mapping already existed + + }; + + /** Attribute masks for page mappings. */ + enum Page_attrib + { + Page_no_attribs = 0, + /// Page is writable. + Page_writable = Mem_page_attr::Write, + Page_user_accessible = Mem_page_attr::User, + /// Page is noncacheable. + Page_noncacheable = Page::NONCACHEABLE, + Page_cacheable = Page::CACHEABLE, + /// it's a user page (USER_NO | USER_RO = USER_RW). + /// A mask which contains all mask bits + Page_all_attribs = Page_user_accessible | Page_writable | Page_cacheable, + Page_referenced = 0, + Page_dirty = 0, + Page_references = 0, + }; + + // Mapping utilities + + enum // Definitions for map_util + { + Need_insert_tlb_flush = 1, + Map_page_size = Config::PAGE_SIZE, + Page_shift = Config::PAGE_SHIFT, + Map_superpage_size = Config::SUPERPAGE_SIZE, + Map_max_address = Mem_layout::User_max, + Whole_space = 32, + Identity_map = 0, + }; + + + static void kernel_space(Mem_space *); + static bool has_superpages() { return true; } + + +private: + // DATA + Dir_type *_dir; +}; + +//--------------------------------------------------------------------------- +IMPLEMENTATION [arm]: + +#include +#include +#include + +#include "atomic.h" +#include "bug.h" +#include "config.h" +#include "globals.h" +#include "kdb_ke.h" +#include "l4_types.h" +#include "panic.h" +#include "paging.h" +#include "kmem.h" +#include "kmem_alloc.h" +#include "mem_unit.h" + + +PUBLIC static inline +Mword +Mem_space::xlate_flush(unsigned char rights) +{ + Mword a = Page_references; + if (rights & L4_fpage::RX) + a |= Page_all_attribs; + else if (rights & L4_fpage::W) + a |= Page_writable; + return a; +} + +PUBLIC static inline +Mword +Mem_space::is_full_flush(unsigned char rights) +{ + return rights & L4_fpage::RX; +} + +PUBLIC static inline +unsigned char +Mem_space::xlate_flush_result(Mword attribs) +{ + unsigned char r = 0; + if (attribs & Page_referenced) + r |= L4_fpage::RX; + + if (attribs & Page_dirty) + r |= L4_fpage::W; + + return r; +} + +// Mapping utilities + +PUBLIC inline NEEDS["mem_unit.h"] +void +Mem_space::tlb_flush(bool force = false) +{ + if (!Have_asids) + Mem_unit::tlb_flush(); + else if (force && c_asid() != ~0UL) + Mem_unit::tlb_flush(c_asid()); + + // else do nothing, we manage ASID local flushes in v_* already + // Mem_unit::tlb_flush(); +} + +PUBLIC static inline NEEDS["mem_unit.h"] +void +Mem_space::tlb_flush_spaces(bool all, Mem_space *s1, Mem_space *s2) +{ + if (all || !Have_asids) + Mem_unit::tlb_flush(); + else + { + if (s1) + s1->tlb_flush(true); + if (s2) + s2->tlb_flush(true); + } +} + + +IMPLEMENT inline +Mem_space *Mem_space::current_mem_space(unsigned cpu) +{ + return _current.cpu(cpu); +} + + +IMPLEMENT inline NEEDS ["kmem.h", Mem_space::c_asid] +void Mem_space::switchin_context(Mem_space *from) +{ +#if 0 + // never switch to kernel space (context of the idle thread) + if (this == kernel_space()) + return; +#endif + + if (from != this) + make_current(); + else + tlb_flush(true); +#if 0 + _dir->invalidate((void*)Kmem::ipc_window(0), Config::SUPERPAGE_SIZE * 4, + c_asid()); +#endif + +} + + +IMPLEMENT inline +void Mem_space::kernel_space(Mem_space *_k_space) +{ + _kernel_space = _k_space; +} + + +inline +static unsigned pd_index(void const *address) +{ return (Mword)address >> 20; /* 1MB steps */ } + +inline +static unsigned pt_index(void const *address) +{ return ((Mword)address >> 12) & 255; /* 4KB steps for coarse pts */ } + + +IMPLEMENT +Mem_space::Status +Mem_space::v_insert(Phys_addr phys, Vaddr virt, Vsize size, unsigned page_attribs, + bool upgrade_ignore_size) +{ + Mem_space *c = _current.current(); + bool flush = c == this; + + Pte pte = _dir->walk((void*)virt.value(), size.value(), flush, + Kmem_alloc::q_allocator(ram_quota()), + c->dir()); + if (pte.valid()) + { + if (EXPECT_FALSE(!upgrade_ignore_size + && (pte.size() != size.value() || pte.phys() != phys.value()))) + return Insert_err_exists; + if (pte.attr().get_abstract() == page_attribs) + return Insert_warn_exists; + + Mem_page_attr a = pte.attr(); + a.set_abstract(a.get_abstract() | page_attribs); + pte.set(phys.value(), size.value(), a, flush); + + BUG_ON(pte.phys() != phys.value(), "overwrite phys addr: %lx with %lx\n", + pte.phys(), phys.value()); + + if (Have_asids) + Mem_unit::tlb_flush((void*)virt.value(), c_asid()); + + return Insert_warn_attrib_upgrade; + } + else if (pte.size() != size.value()) + return Insert_err_nomem; + else + { + // we found an invalid entry for the right size + Mem_page_attr a(Page::Local_page); + a.set_abstract(page_attribs); + pte.set(phys.value(), size.value(), a, flush); + return Insert_ok; + } +} + + +/** + * Simple page-table lookup. + * + * @param virt Virtual address. This address does not need to be page-aligned. + * @return Physical address corresponding to a. + */ +PUBLIC inline +Address +Mem_space::virt_to_phys(Address virt) const +{ + Pte pte = _dir->walk((void*)virt, 0, false, Ptab::Null_alloc(), 0); + if (EXPECT_FALSE(!pte.valid())) + return ~0UL; + + return (Address)pte.phys((void*)virt); +} + +PUBLIC inline NEEDS [Mem_space::virt_to_phys] +Address +Mem_space::pmem_to_phys(Address virt) const +{ + return virt_to_phys(virt); +} + +/** Simple page-table lookup. This method is similar to Mem_space's + lookup(). The difference is that this version handles + Sigma0's address space with a special case: For Sigma0, we do not + actually consult the page table -- it is meaningless because we + create new mappings for Sigma0 transparently; instead, we return the + logically-correct result of physical address == virtual address. + @param a Virtual address. This address does not need to be page-aligned. + @return Physical address corresponding to a. + */ +PUBLIC inline +virtual Address +Mem_space::virt_to_phys_s0(void *a) const +{ + return virt_to_phys((Address)a); +} + +IMPLEMENT +bool +Mem_space::v_lookup(Vaddr virt, Phys_addr *phys, + Size *size, unsigned *page_attribs) +{ + Pte p = _dir->walk( (void*)virt.value(), 0, false, Ptab::Null_alloc(), 0); + + if (size) *size = Size(p.size()); + if (page_attribs) *page_attribs = p.attr().get_abstract(); + // FIXME: we should not use virt but 0 as offset for phys return value! + if (phys) *phys = Phys_addr(p.phys((void*)virt.value())); + return p.valid(); +} + +IMPLEMENT +unsigned long +Mem_space::v_delete(Vaddr virt, Vsize size, + unsigned long del_attribs) +{ + (void)size; + bool flush = _current.current() == this; + Pte pte = _dir->walk((void*)virt.value(), 0, false, Ptab::Null_alloc(), 0); + if (EXPECT_FALSE(!pte.valid())) + return 0; + + BUG_ON(pte.size() != size.value(), "size mismatch: va=%lx sz=%lx dir=%p\n", + virt.value(), size.value(), _dir); + + Mem_unit::flush_vcache((void*)(virt.value() & ~(pte.size()-1)), + (void*)((virt.value() & ~(pte.size()-1)) + pte.size())); + + Mem_page_attr a = pte.attr(); + unsigned long abs_a = a.get_abstract(); + + if (!(del_attribs & Page_user_accessible)) + { + a.set_ap(abs_a & ~del_attribs); + pte.attr(a, flush); + } + else + pte.set_invalid(0, flush); + + if (Have_asids) + Mem_unit::tlb_flush((void*)virt.value(), c_asid()); + + return abs_a & del_attribs; +} + + +PUBLIC inline +bool +Mem_space::set_attributes(Address virt, unsigned page_attribs) +{ + Pte p = _dir->walk( (void*)virt, 0, false, Ptab::Null_alloc(), 0); + if (!p.valid()) + // copy current shared kernel page directory + return false; + + Mem_page_attr a = p.attr(); + a.set_ap(page_attribs); + p.attr(a, true); + return true; +} + +PROTECTED +void +Mem_space::destroy() +{ + reset_asid(); +} + +/** + * \brief Free all memory allocated for this Mem_space. + * \pre Runs after the destructor! + */ +PUBLIC +Mem_space::~Mem_space() +{ + if (_dir) + { + _dir->free_page_tables(0, (void*)Mem_layout::User_max, + Kmem_alloc::q_allocator(ram_quota())); + Kmem_alloc::allocator()->q_unaligned_free(ram_quota(), sizeof(Page_table), _dir); + } +} + + +/** Constructor. Creates a new address space and registers it with + * Space_index. + * + * Registration may fail (if a task with the given number already + * exists, or if another thread creates an address space for the same + * task number concurrently). In this case, the newly-created + * address space should be deleted again. + */ +PUBLIC inline +Mem_space::Mem_space(Ram_quota *q) +: _quota(q), _dir(0) +{ + asid(~0UL); +} + +PROTECTED inline NEEDS[, "kmem_alloc.h", Mem_space::asid] +bool +Mem_space::initialize() +{ + Auto_quota q(ram_quota(), sizeof(Page_table)); + if (EXPECT_FALSE(!q)) + return false; + + _dir = (Page_table*)Kmem_alloc::allocator()->unaligned_alloc(sizeof(Page_table)); + if (!_dir) + return false; + + new (_dir) Page_table; + + q.release(); + return true; +} + +PROTECTED inline +void +Mem_space::sync_kernel() +{ + // copy current shared kernel page directory + _dir->copy_in((void*)Mem_layout::User_max, + kernel_space()->_dir, + (void*)Mem_layout::User_max, + Mem_layout::Kernel_max - Mem_layout::User_max); +} + +PUBLIC +Mem_space::Mem_space(Ram_quota *q, Dir_type* pdir) + : _quota(q), _dir (pdir) +{ + asid(~0UL); + _current.cpu(0) = this; +} + +PUBLIC static inline +Page_number +Mem_space::canonize(Page_number v) +{ return v; } + +//---------------------------------------------------------------------------- +IMPLEMENTATION [armv5]: + +PRIVATE inline +void +Mem_space::asid(unsigned long) +{} + +PRIVATE inline +void +Mem_space::reset_asid() +{} + +PUBLIC inline +unsigned long +Mem_space::c_asid() const +{ return 0; } + +IMPLEMENT inline +void Mem_space::make_current() +{ + _dir->activate(); + _current.current() = this; +} + + +//---------------------------------------------------------------------------- +INTERFACE [armv6 || armv7]: + +EXTENSION class Mem_space +{ +public: + enum { Have_asids = 1 }; +private: + unsigned long _asid[Config::Max_num_cpus]; + + static Per_cpu _next_free_asid; + static Per_cpu _active_asids; +}; + +//---------------------------------------------------------------------------- +INTERFACE [!(armv6 || armv7)]: + +EXTENSION class Mem_space +{ +public: + enum { Have_asids = 0 }; +}; + +//---------------------------------------------------------------------------- +IMPLEMENTATION [armv6 || armca8]: + +PRIVATE inline static +unsigned long +Mem_space::next_asid(unsigned cpu) +{ + return _next_free_asid.cpu(cpu)++; +} + +//---------------------------------------------------------------------------- +IMPLEMENTATION [armv7 && armca9]: + +PRIVATE inline static +unsigned long +Mem_space::next_asid(unsigned cpu) +{ + if (_next_free_asid.cpu(cpu) == 0) + ++_next_free_asid.cpu(cpu); + return _next_free_asid.cpu(cpu)++; +} + +//---------------------------------------------------------------------------- +IMPLEMENTATION [armv6 || armv7]: + +DEFINE_PER_CPU Per_cpu Mem_space::_next_free_asid; +DEFINE_PER_CPU Per_cpu Mem_space::_active_asids; + +PRIVATE inline +void +Mem_space::asid(unsigned long a) +{ + for (unsigned i = 0; i < Config::Max_num_cpus; ++i) + _asid[i] = a; +} + +PUBLIC inline +unsigned long +Mem_space::c_asid() const +{ return _asid[current_cpu()]; } + +PRIVATE inline NEEDS[Mem_space::next_asid, "types.h"] +unsigned long +Mem_space::asid() +{ + unsigned cpu = current_cpu(); + if (EXPECT_FALSE(_asid[cpu] == ~0UL)) + { + // FIFO ASID replacement strategy + unsigned char new_asid = next_asid(cpu); + Mem_space **bad_guy = &_active_asids.cpu(cpu)[new_asid]; + while (Mem_space *victim = access_once(*bad_guy)) + { + // need ASID replacement + if (victim == current_mem_space(cpu)) + { + // do not replace the ASID of the current space + new_asid = next_asid(cpu); + bad_guy = &_active_asids.cpu(cpu)[new_asid]; + continue; + } + + //LOG_MSG_3VAL(current(), "ASIDr", new_asid, (Mword)*bad_guy, (Mword)this); + Mem_unit::tlb_flush(new_asid); + if (victim != reinterpret_cast(~0UL)) + victim->_asid[cpu] = ~0UL; + break; + } + + *bad_guy = this; + _asid[cpu] = new_asid; + } + + //LOG_MSG_3VAL(current(), "ASID", (Mword)this, _asid[cpu], (Mword)__builtin_return_address(0)); + return _asid[cpu]; +}; + +PRIVATE inline +void +Mem_space::reset_asid() +{ + for (unsigned i = 0; i < Config::Max_num_cpus; ++i) + { + unsigned asid = access_once(_asid[i]); + if (asid == ~0UL) + continue; + + Mem_space **a = &_active_asids.cpu(i)[asid]; + mp_cas(a, this, reinterpret_cast(~0UL)); + } +} + +IMPLEMENT inline NEEDS[Mem_space::asid] +void Mem_space::make_current() +{ + _dir->activate(asid()); + _current.current() = this; +} diff --git a/kernel/fiasco/src/kern/arm/mem_unit.cpp b/kernel/fiasco/src/kern/arm/mem_unit.cpp new file mode 100644 index 00000000..36413e61 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/mem_unit.cpp @@ -0,0 +1,125 @@ +INTERFACE [arm]: + +#include "kmem.h" +#include "mmu.h" + +class Mem_unit : public Mmu< Kmem::Cache_flush_area > +{ +public: + static void tlb_flush(); + static void dtlb_flush( void* va ); + static void dtlb_flush(); + static void tlb_flush(unsigned long asid); + static void dtlb_flush(unsigned long asid); +}; + +//--------------------------------------------------------------------------- +IMPLEMENTATION [arm]: + +IMPLEMENT inline +void Mem_unit::tlb_flush() +{ + asm volatile ( + "mcr p15, 0, %0, c8, c7, 0x00 \n" + : + : "r" (0) + : "memory" ); // TLB flush +} + + +IMPLEMENT inline +void Mem_unit::dtlb_flush( void* va ) +{ + asm volatile ( + "mcr p15, 0, %0, c8, c6, 0x01 \n" + : + : "r"((unsigned long)va & 0xfffff000) + : "memory" ); // TLB flush +} + +IMPLEMENT inline +void Mem_unit::dtlb_flush() +{ + asm volatile ( + "mcr p15, 0, %0, c8, c6, 0x0 \n" + : + : "r"(0) + : "memory" ); // TLB flush +} + +//--------------------------------------------------------------------------- +IMPLEMENTATION [arm && armv5]: + +PUBLIC static inline +void Mem_unit::tlb_flush( void* va, unsigned long) +{ + asm volatile ( + "mcr p15, 0, %0, c8, c7, 0x01 \n" + : + : "r"((unsigned long)va & 0xfffff000) + : "memory" ); // TLB flush +} + + +IMPLEMENT inline +void Mem_unit::tlb_flush(unsigned long) +{ + asm volatile ( + "mcr p15, 0, r0, c8, c7, 0x00 \n" + : + : + : "memory" ); // TLB flush +} + +IMPLEMENT inline +void Mem_unit::dtlb_flush(unsigned long) +{ + asm volatile ( + "mcr p15, 0, %0, c8, c6, 0x0 \n" + : + : "r"(0) + : "memory" ); // TLB flush +} + + +//--------------------------------------------------------------------------- +IMPLEMENTATION [arm && (armv6 || armv7)]: + +PUBLIC static inline +void Mem_unit::tlb_flush( void* va, unsigned long asid ) +{ + if (asid == ~0UL) return; + btc_flush(); + asm volatile ( + "mcr p15, 0, %1, c7, c10, 4 \n" // drain write buffer + "mcr p15, 0, %0, c8, c7, 1 \n" // flush both TLB entry + : + : "r"(((unsigned long)va & 0xfffff000) | (asid & 0xff)), + "r" (0) + : "memory" ); +} + +IMPLEMENT inline +void Mem_unit::tlb_flush(unsigned long asid) +{ + btc_flush(); + asm volatile ( + "mcr p15, 0, %1, c7, c10, 4 \n" // drain write buffer + "mcr p15, 0, %0, c8, c7, 2 \n" // flush both TLB with asid + : + : "r"(asid), + "r" (0) + : "memory" ); +} + +IMPLEMENT inline +void Mem_unit::dtlb_flush(unsigned long asid) +{ + asm volatile ( + "mcr p15, 0, r0, c7, c10, 4 \n" // drain write buffer + "mcr p15, 0, %0, c8, c6, 2 \n" // flush data TLB with asid + : + : "r"(asid) + : "memory" ); +} + diff --git a/kernel/fiasco/src/kern/arm/outer_cache-l2cxx0.cpp b/kernel/fiasco/src/kern/arm/outer_cache-l2cxx0.cpp new file mode 100644 index 00000000..41b295a3 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/outer_cache-l2cxx0.cpp @@ -0,0 +1,227 @@ +INTERFACE [arm && outer_cache_l2cxx0]: + +#include "mem_layout.h" +#include "spin_lock.h" + +EXTENSION class Outer_cache +{ +private: + enum + { + Cache_line_shift = 5, + + CACHE_ID = Mem_layout::L2cxx0_map_base + 0x000, + CACHE_TYPE = Mem_layout::L2cxx0_map_base + 0x004, + CONTROL = Mem_layout::L2cxx0_map_base + 0x100, + AUX_CONTROL = Mem_layout::L2cxx0_map_base + 0x104, + TAG_RAM_CONTROL = Mem_layout::L2cxx0_map_base + 0x108, + DATA_RAM_CONTROL = Mem_layout::L2cxx0_map_base + 0x10c, + EVENT_COUNTER_CONTROL = Mem_layout::L2cxx0_map_base + 0x200, + EVENT_COUTNER1_CONFIG = Mem_layout::L2cxx0_map_base + 0x204, + EVENT_COUNTER0_CONFIG = Mem_layout::L2cxx0_map_base + 0x208, + EVENT_COUNTER1_VALUE = Mem_layout::L2cxx0_map_base + 0x20c, + EVENT_COUNTER0_VALUE = Mem_layout::L2cxx0_map_base + 0x210, + INTERRUPT_MASK = Mem_layout::L2cxx0_map_base + 0x214, + MASKED_INTERRUPT_STATUS = Mem_layout::L2cxx0_map_base + 0x218, + RAW_INTERRUPT_STATUS = Mem_layout::L2cxx0_map_base + 0x21c, + INTERRUPT_CLEAR = Mem_layout::L2cxx0_map_base + 0x220, + CACHE_SYNC = Mem_layout::L2cxx0_map_base + 0x730, + INVALIDATE_LINE_BY_PA = Mem_layout::L2cxx0_map_base + 0x770, + INVALIDATE_BY_WAY = Mem_layout::L2cxx0_map_base + 0x77c, + CLEAN_LINE_BY_PA = Mem_layout::L2cxx0_map_base + 0x7b0, + CLEAN_LINE_BY_INDEXWAY = Mem_layout::L2cxx0_map_base + 0x7bb, + CLEAN_BY_WAY = Mem_layout::L2cxx0_map_base + 0x7bc, + CLEAN_AND_INV_LINE_BY_PA = Mem_layout::L2cxx0_map_base + 0x7f0, + CLEAN_AND_INV_LINE_BY_INDEXWAY = Mem_layout::L2cxx0_map_base + 0x7f8, + CLEAN_AND_INV_BY_WAY = Mem_layout::L2cxx0_map_base + 0x7fc, + LOCKDOWN_BY_WAY_D_SIDE = Mem_layout::L2cxx0_map_base + 0x900, + LOCKDOWN_BY_WAY_I_SIDE = Mem_layout::L2cxx0_map_base + 0x904, + TEST_OPERATION = Mem_layout::L2cxx0_map_base + 0xf00, + LINE_TAG = Mem_layout::L2cxx0_map_base + 0xf30, + DEBUG_CONTROL_REGISTER = Mem_layout::L2cxx0_map_base + 0xf40, + }; + + static Spin_lock<> _lock; + + static Mword platform_init(Mword aux); + + static bool need_sync; + static unsigned waymask; + +public: + enum + { + Cache_line_size = 1 << Cache_line_shift, + Cache_line_mask = Cache_line_size - 1, + }; +}; + +// ------------------------------------------------------------------------ +IMPLEMENTATION [arm && outer_cache_l2cxx0]: + +#include "io.h" +#include "lock_guard.h" +#include "static_init.h" + +Spin_lock<> Outer_cache::_lock; +bool Outer_cache::need_sync; +unsigned Outer_cache::waymask; + +IMPLEMENT inline NEEDS ["io.h"] +void +Outer_cache::sync() +{ + while (Io::read(CACHE_SYNC)) + Proc::preemption_point(); +} + +PRIVATE static inline NEEDS ["io.h", "lock_guard.h"] +void +Outer_cache::write(Address reg, Mword val, bool before = false) +{ + Lock_guard > guard(&_lock); + if (before) + while (Io::read(reg) & 1) + ; + Io::write(val, reg); + if (!before) + while (Io::read(reg) & 1) + ; +} + +IMPLEMENT inline NEEDS[Outer_cache::write] +void +Outer_cache::clean() +{ + write(CLEAN_BY_WAY, waymask); + sync(); +} + +IMPLEMENT inline NEEDS[Outer_cache::write] +void +Outer_cache::clean(Mword phys_addr, bool do_sync = true) +{ + write(CLEAN_LINE_BY_PA, phys_addr & (~0UL << Cache_line_shift)); + if (need_sync && do_sync) + sync(); +} + +IMPLEMENT inline NEEDS[Outer_cache::write] +void +Outer_cache::flush() +{ + write(CLEAN_AND_INV_BY_WAY, waymask); + sync(); +} + +IMPLEMENT inline NEEDS[Outer_cache::write] +void +Outer_cache::flush(Mword phys_addr, bool do_sync = true) +{ + write(CLEAN_AND_INV_LINE_BY_PA, phys_addr & (~0UL << Cache_line_shift)); + if (need_sync && do_sync) + sync(); +} + +IMPLEMENT inline NEEDS[Outer_cache::write] +void +Outer_cache::invalidate() +{ + write(INVALIDATE_BY_WAY, waymask); + sync(); +} + +IMPLEMENT inline NEEDS[Outer_cache::write] +void +Outer_cache::invalidate(Address phys_addr, bool do_sync = true) +{ + write(INVALIDATE_LINE_BY_PA, phys_addr & (~0UL << Cache_line_shift)); + if (need_sync && do_sync) + sync(); +} + +PUBLIC static +void +Outer_cache::init() +{ + Mword cache_id = Io::read(CACHE_ID); + Mword aux = Io::read(AUX_CONTROL); + unsigned ways = 8; + + need_sync = true; + + aux = platform_init(aux); + + switch ((cache_id >> 6) & 0xf) + { + case 1: + ways = (aux >> 13) & 0xf; + break; + case 3: + need_sync = false; + ways = aux & (1 << 16) ? 16 : 8; + break; + default: + break; + } + + waymask = (1 << ways) - 1; + + Io::write(0, INTERRUPT_MASK); + Io::write(~0UL, INTERRUPT_CLEAR); + + if (!(Io::read(CONTROL) & 1)) + { + Io::write(aux, AUX_CONTROL); + invalidate(); + Io::write(1, CONTROL); + } + + show_info(ways, cache_id, aux); +} + +STATIC_INITIALIZE_P(Outer_cache, STARTUP_INIT_PRIO); + +// ------------------------------------------------------------------------ +IMPLEMENTATION [arm && outer_cache_l2cxx0 && !debug]: + +PRIVATE static +void +Outer_cache::show_info(unsigned, Mword, Mword) +{} + +// ------------------------------------------------------------------------ +IMPLEMENTATION [arm && outer_cache_l2cxx0 && debug]: + +#include "io.h" +#include + +PRIVATE static +void +Outer_cache::show_info(unsigned ways, Mword cache_id, Mword aux) +{ + printf("L2: ID=%08lx Type=%08lx Aux=%08lx WMask=%x S=%d\n", + cache_id, Io::read(CACHE_TYPE), aux, waymask, need_sync); + + const char *type; + switch ((cache_id >> 6) & 0xf) + { + case 1: + type = "210"; + break; + case 2: + type = "220"; + break; + case 3: + type = "310"; + if (cache_id & 0x3f == 5) + printf("L2: r3p0\n"); + break; + default: + type = "Unknown"; + break; + } + + unsigned waysize = 16 << (((aux >> 17) & 7) - 1); + printf("L2: Type L2C-%s Size = %dkB\n", type, ways * waysize); +} diff --git a/kernel/fiasco/src/kern/arm/outer_cache.cpp b/kernel/fiasco/src/kern/arm/outer_cache.cpp new file mode 100644 index 00000000..e07d642a --- /dev/null +++ b/kernel/fiasco/src/kern/arm/outer_cache.cpp @@ -0,0 +1,121 @@ +INTERFACE: + +#include "types.h" + +class Outer_cache +{ +public: + static void invalidate(); + static void invalidate(Address phys, bool sync = true); + static void invalidate(Address start_phys, Address end_phys, bool do_sync = true); + + static void clean(); + static void clean(Address phys, bool do_sync = true); + static void clean(Address start_phys, Address end_phys, bool do_sync = true); + + static void flush(); + static void flush(Address phys, bool do_sync = true); + static void flush(Address start_phys, Address end_phys, bool do_sync = true); + + static void sync(); +}; + +// ------------------------------------------------------------------------ +IMPLEMENTATION [!outer_cache]: + +IMPLEMENT inline +void +Outer_cache::invalidate() +{} + +IMPLEMENT inline +void +Outer_cache::invalidate(Address, bool) +{} + +IMPLEMENT inline +void +Outer_cache::clean() +{} + +IMPLEMENT inline +void +Outer_cache::clean(Address, bool) +{} + +IMPLEMENT inline +void +Outer_cache::flush() +{} + +IMPLEMENT inline +void +Outer_cache::flush(Address, bool) +{} + +IMPLEMENT inline +void +Outer_cache::sync() +{} + +IMPLEMENT inline +void +Outer_cache::invalidate(Address, Address, bool) +{} + +IMPLEMENT inline +void +Outer_cache::clean(Address, Address, bool) +{} + +IMPLEMENT inline +void +Outer_cache::flush(Address, Address, bool) +{} + +// ------------------------------------------------------------------------ +IMPLEMENTATION [outer_cache]: + +IMPLEMENT inline +void +Outer_cache::invalidate(Address start, Address end, bool do_sync) +{ + if (start & Cache_line_mask) + { + flush(start, false); + start += Cache_line_size; + } + if (end & Cache_line_mask) + { + flush(end, false); + end &= ~Cache_line_mask; + } + + for (Address a = start & ~Cache_line_mask; a < end; a += Cache_line_size) + invalidate(a, false); + + if (do_sync) + sync(); +} + +IMPLEMENT inline +void +Outer_cache::clean(Address start, Address end, bool do_sync) +{ + for (Address a = start & ~Cache_line_mask; + a < end; a += Cache_line_size) + clean(a, false); + if (do_sync) + sync(); +} + +IMPLEMENT inline +void +Outer_cache::flush(Address start, Address end, bool do_sync) +{ + for (Address a = start & ~Cache_line_mask; + a < end; a += Cache_line_size) + flush(a, false); + if (do_sync) + sync(); +} diff --git a/kernel/fiasco/src/kern/arm/pagetable-arch.cpp b/kernel/fiasco/src/kern/arm/pagetable-arch.cpp new file mode 100644 index 00000000..e3681591 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/pagetable-arch.cpp @@ -0,0 +1,732 @@ +//--------------------------------------------------------------------------- +INTERFACE[arm]: + +class Mem_page_attr +{ + friend class Pte; + +public: + unsigned long get_ap() const; + void set_ap(unsigned long ap); + +private: + unsigned long _a; +}; + +//--------------------------------------------------------------------------- +INTERFACE[arm && armv5]: + +EXTENSION class Mem_page_attr +{ +public: + enum + { + Write = 0x400, + User = 0x800, + Ap_mask = 0xc00, + }; +}; + +//--------------------------------------------------------------------------- +INTERFACE[arm && (armv6 || armv7)]: + +EXTENSION class Mem_page_attr +{ +public: + enum + { + Write = 0x200, + User = 0x020, + Ap_mask = 0x220, + }; +}; + +//--------------------------------------------------------------------------- +INTERFACE[arm && !(mpcore || armca9)]: + +EXTENSION class Mem_page_attr +{ +public: + // do not use Shaed bit on non MP CPUs because this leads to uncached memory + // accesses most of the time! + enum { Shared = 0 }; +}; + +EXTENSION class Page_table +{ +public: + enum { Ttbr_bits = 0x0 }; +}; + +//--------------------------------------------------------------------------- +INTERFACE[arm && (mpcore || armca9)]: + +EXTENSION class Mem_page_attr +{ +public: + // use shared bit on MP CPUs as we need cache coherency + enum { Shared = 0x400 }; +}; + +//--------------------------------------------------------------------------- +INTERFACE[arm && mpcore]: + +EXTENSION class Page_table +{ +public: + enum { Ttbr_bits = 0xa }; +}; + +//--------------------------------------------------------------------------- +INTERFACE[arm && armca9]: + +EXTENSION class Page_table +{ +public: + enum + { + Ttbr_bits = (1 << 1) // S, Shareable bit + | (1 << 3) // RGN, Region bits, Outer WriteBackWriteAlloc + | (0 << 0) | (1 << 6) // IRGN, Inner region bits, WB-WA + | (1 << 5) // NOS + , + }; +}; + +//--------------------------------------------------------------------------- +INTERFACE [arm]: + +#include "paging.h" +#include "per_cpu_data.h" + +class Ram_quota; + +class Pte +{ +public: +//private: + unsigned long _pt; + Mword *_pte; + +public: + Pte(Page_table *pt, unsigned level, Mword *pte) + : _pt((unsigned long)pt | level), _pte(pte) + {} +}; + + +EXTENSION class Page_table +{ +private: + Mword raw[4096]; + enum + { + Pt_base_mask = 0xfffffc00, + Pde_type_coarse = 0x01, + }; +}; + +//--------------------------------------------------------------------------- +IMPLEMENTATION [arm && vcache]: + +PUBLIC static inline +bool +Pte::need_cache_clean() +{ + return false; +} + +//--------------------------------------------------------------------------- +IMPLEMENTATION [arm && !vcache && !armca9]: + +PUBLIC static inline +bool +Pte::need_cache_clean() +{ + return true; +} + +//--------------------------------------------------------------------------- +IMPLEMENTATION [arm && !vcache && armca9]: + +PUBLIC static inline +bool +Pte::need_cache_clean() +{ + return false; +} + +//--------------------------------------------------------------------------- +IMPLEMENTATION [arm]: + +#include +#include + +#include "mem_unit.h" +#include "kdb_ke.h" +#include "ram_quota.h" + +PUBLIC inline explicit +Mem_page_attr::Mem_page_attr(unsigned long attr) : _a(attr) +{} + +PRIVATE inline +unsigned long +Mem_page_attr::raw() const +{ return _a; } + +PUBLIC inline +void +Mem_page_attr::set_caching(unsigned long del, unsigned long set) +{ + del &= Page::Cache_mask; + set &= Page::Cache_mask; + _a = (_a & ~del) | set; +} + +PUBLIC inline NEEDS[Mem_page_attr::get_ap] +unsigned long +Mem_page_attr::get_abstract() const +{ return get_ap() | (_a & Page::Cache_mask); } + +PUBLIC inline NEEDS[Mem_page_attr::set_ap] +void +Mem_page_attr::set_abstract(unsigned long a) +{ + _a = (_a & ~Page::Cache_mask) | (a & Page::Cache_mask); + set_ap(a); +} + +PUBLIC inline NEEDS[Mem_page_attr::get_ap] +bool +Mem_page_attr::permits(unsigned long attr) +{ return (get_ap() & attr) == attr; } + +PUBLIC inline +unsigned long +Pte::valid() const +{ return *_pte & 3; } + +PUBLIC inline +unsigned long +Pte::phys() const +{ + switch(_pt & 3) + { + case 0: + switch (*_pte & 3) + { + case 2: return *_pte & ~((1 << 20) - 1); // 1MB + default: return ~0UL; + } + case 1: + switch (*_pte & 3) + { + case 2: return *_pte & ~((4 << 10) - 1); + default: return ~0UL; + } + default: return ~0UL; + } +} + +PUBLIC inline +unsigned long +Pte::phys(void *virt) +{ + unsigned long p = phys(); + return p | (((unsigned long)virt) & (size()-1)); +} + +PUBLIC inline +unsigned long +Pte::lvl() const +{ return (_pt & 3); } + +PUBLIC inline +unsigned long +Pte::raw() const +{ return *_pte; } + +PUBLIC inline +bool +Pte::superpage() const +{ return !(_pt & 3) && ((*_pte & 3) == 2); } + +PUBLIC inline +unsigned long +Pte::size() const +{ + switch(_pt & 3) + { + case 0: + switch (*_pte & 3) + { + case 2: return 1 << 20; // 1MB + default: return 1 << 20; + } + case 1: + switch (*_pte & 3) + { + case 1: return 64 << 10; + case 2: return 4 << 10; + case 3: return 1 << 10; + default: return 4 << 10; + } + default: return 0; + } +} + + +PRIVATE inline NEEDS["mem_unit.h"] +void +Pte::__set(unsigned long v, bool write_back) +{ + *_pte = v; + if (write_back || need_cache_clean()) + Mem_unit::clean_dcache(_pte); +} + +PUBLIC inline NEEDS[Pte::__set] +void +Pte::set_invalid(unsigned long val, bool write_back) +{ __set(val & ~3, write_back); } + + +//----------------------------------------------------------------------------- +IMPLEMENTATION [arm && armv5]: + +IMPLEMENT inline +unsigned long +Mem_page_attr::get_ap() const +{ + static unsigned char const _map[4] = { 0x8, 0x4, 0x0, 0xc }; + return ((unsigned long)_map[(_a >> 10) & 0x3]) << 8UL; +} + +IMPLEMENT inline +void +Mem_page_attr::set_ap(unsigned long ap) +{ + static unsigned char const _map[4] = { 0x4, 0x4, 0x0, 0xc }; + _a = (_a & ~0xc00) | (((unsigned long)_map[(ap >> 10) & 0x3]) << 8UL); +} + +PUBLIC inline NEEDS[Pte::__set, Mem_page_attr::raw] +void +Pte::set(Address phys, unsigned long size, Mem_page_attr const &attr, + bool write_back) +{ + switch (_pt & 3) + { + case 0: + if (size != (1 << 20)) + return; + __set(phys | (attr.raw() & Page::MAX_ATTRIBS) | 2, write_back); + break; + case 1: + { + if (size != (4 << 10)) + return; + unsigned long ap = attr.raw() & 0xc00; ap |= ap >> 2; ap |= ap >> 4; + __set(phys | (attr.raw() & 0x0c) | ap | 2, write_back); + } + break; + } +} + +PUBLIC inline NEEDS[Mem_page_attr::Mem_page_attr] +Mem_page_attr +Pte::attr() const { return Mem_page_attr(*_pte & 0xc0c); } + +PUBLIC inline NEEDS["mem_unit.h"] +void +Pte::attr(Mem_page_attr const &attr, bool write_back) +{ + switch (_pt & 3) + { + case 0: + __set((*_pte & ~0xc0c) | (attr.raw() & 0xc0c), write_back); + break; + case 1: + { + unsigned long ap = attr.raw() & 0xc00; ap |= ap >> 2; ap |= ap >> 4; + __set((*_pte & ~0xffc) | (attr.raw() & 0x0c) | ap, write_back); + } + break; + } +} + +PUBLIC /*inline*/ +void Page_table::activate() +{ + Pte p = walk(this, 0, false, Ptab::Null_alloc(), 0); + Mem_unit::flush_vcache(); + asm volatile ( + "mcr p15, 0, r0, c8, c7, 0 \n" // TLB flush + "mcr p15, 0, %0, c2, c0 \n" // pdbr + + "mrc p15, 0, r1, c2, c0 \n" + "mov r1, r1 \n" + "sub pc, pc, #4 \n" + : + : "r" (p.phys(this)) + : "r1"); +} + + +//----------------------------------------------------------------------------- +IMPLEMENTATION [arm && (armv6 || armv7)]: + +IMPLEMENT inline +unsigned long +Mem_page_attr::get_ap() const +{ + return (_a & User) | ((_a & Write) ^ Write); +} + +IMPLEMENT inline NEEDS[Mem_page_attr::raw] +void +Mem_page_attr::set_ap(unsigned long ap) +{ + _a = (_a & ~(User | Write)) | (ap & User) | ((ap & Write) ^ Write) | 0x10; +} + +PUBLIC inline NEEDS[Pte::__set] +void +Pte::set(Address phys, unsigned long size, Mem_page_attr const &attr, + bool write_back) +{ + switch (_pt & 3) + { + case 0: + if (size != (1 << 20)) + return; + { + unsigned long a = attr.raw() & 0x0c; // C & B + a |= ((attr.raw() & 0xff0) | Mem_page_attr::Shared) << 6; + __set(phys | a | 0x2, write_back); + } + break; + case 1: + if (size != (4 << 10)) + return; + __set(phys | (attr.raw() & Page::MAX_ATTRIBS) | 0x2 | Mem_page_attr::Shared, write_back); + break; + } +} + +PUBLIC inline NEEDS[Mem_page_attr::raw] +Mem_page_attr +Pte::attr() const +{ + switch (_pt & 3) + { + case 0: + { + unsigned long a = *_pte & 0x0c; // C & B + a |= (*_pte >> 6) & 0xff0; + return Mem_page_attr(a); + } + case 1: + default: + return Mem_page_attr(*_pte & Page::MAX_ATTRIBS); + } +} + +PUBLIC inline NEEDS["mem_unit.h", Mem_page_attr::raw] +void +Pte::attr(Mem_page_attr const &attr, bool write_back) +{ + switch (_pt & 3) + { + case 1: + __set((*_pte & ~Page::MAX_ATTRIBS) + | (attr.raw() & Page::MAX_ATTRIBS), write_back); + break; + case 0: + { + unsigned long a = attr.raw() & 0x0c; + a |= (attr.raw() & 0xff0) << 6; + __set((*_pte & ~0x3fcc) | a, write_back); + } + break; + } +} + +//----------------------------------------------------------------------------- +IMPLEMENTATION [armv6 || armca8]: + +PUBLIC +void Page_table::activate(unsigned long asid) +{ + Pte p = walk(this, 0, false, Ptab::Null_alloc(), 0); + asm volatile ( + "mcr p15, 0, %2, c7, c5, 6 \n" // bt flush + "mcr p15, 0, r0, c7, c10, 4 \n" // dsb + "mcr p15, 0, %0, c2, c0 \n" // set TTBR + "mcr p15, 0, r0, c7, c10, 4 \n" // dsb + "mcr p15, 0, %1, c13, c0, 1 \n" // set new ASID value + "mcr p15, 0, r0, c7, c5, 4 \n" // isb + "mcr p15, 0, %2, c7, c5, 6 \n" // bt flush + "mrc p15, 0, r1, c2, c0 \n" + "mov r1, r1 \n" + "sub pc, pc, #4 \n" + : + : "r" (p.phys(this) | Ttbr_bits), "r"(asid), "r" (0) + : "r1"); +} + +//----------------------------------------------------------------------------- +IMPLEMENTATION [armv7 && armca9]: + +PUBLIC +void Page_table::activate(unsigned long asid) +{ + Pte p = walk(this, 0, false, Ptab::Null_alloc(), 0); + asm volatile ( + "mcr p15, 0, %2, c7, c5, 6 \n" // bt flush + "dsb \n" + "mcr p15, 0, %2, c13, c0, 1 \n" // change ASID to 0 + "isb \n" + "mcr p15, 0, %0, c2, c0 \n" // set TTBR + "isb \n" + "mcr p15, 0, %1, c13, c0, 1 \n" // set new ASID value + "isb \n" + "mcr p15, 0, %2, c7, c5, 6 \n" // bt flush + "isb \n" + "mov r1, r1 \n" + "sub pc, pc, #4 \n" + : + : "r" (p.phys(this) | Ttbr_bits), "r"(asid), "r" (0) + : "r1"); +} + +//----------------------------------------------------------------------------- +IMPLEMENTATION [arm && !mp]: + +PRIVATE inline +Mword +Page_table::current_virt_to_phys(void *virt) +{ + return walk(virt, 0, false, Ptab::Null_alloc(), 0).phys(virt); +} + +//----------------------------------------------------------------------------- +IMPLEMENTATION [arm && mp]: + +/* + * This version for MP avoids calling Page_table::current() which calls + * current_cpu() which is not available on the boot-stack. That's why we use + * the following way of doing a virt->phys translation on the current page + * table. + */ +PRIVATE inline +Mword +Page_table::current_virt_to_phys(void *virt) +{ + Mword phys; + Mword offset = (Mword)virt & ~Config::PAGE_MASK; + asm volatile("mcr p15,0,%1,c7,c8,0 \n" + "mrc p15,0,%0,c7,c4,0 \n" + : "=r" (phys) + : "r" ((Mword)virt & Config::PAGE_MASK)); + return (phys & Config::PAGE_MASK) | offset; +} + + +//----------------------------------------------------------------------------- +IMPLEMENTATION [arm]: + +#include +#include "bug.h" +#include "auto_quota.h" +#include "mem.h" +#if 0 +IMPLEMENT +void *Page_table::operator new(size_t s) throw() +{ + (void)s; + assert(s == 16*1024); + return alloc()->alloc(14); // 2^14 = 16K +} + +IMPLEMENT +void Page_table::operator delete(void *b) +{ + alloc()->free(14, b); +} +#endif + +IMPLEMENT +Page_table::Page_table() +{ + Mem::memset_mwords(raw, 0, sizeof(raw) / sizeof(Mword)); + if (Pte::need_cache_clean()) + Mem_unit::clean_dcache(raw, (char *)raw + sizeof(raw)); +} + + +PUBLIC template< typename ALLOC > +void Page_table::free_page_tables(void *start, void *end, ALLOC const &a) +{ + for (unsigned i = (Address)start >> 20; i < ((Address)end >> 20); ++i) + { + Pte p(this, 0, raw + i); + if (p.valid() && !p.superpage()) + { + void *pt = (void*)Mem_layout::phys_to_pmem(p.raw() & Pt_base_mask); + + BUG_ON(pt == (void*)~0UL, "cannot get virtual (pmem) address for %lx (pte @ %p)\n", + p.raw() & Pt_base_mask, p._pte); + + a.free(pt, 1<<10); + } + } +} + +PRIVATE inline +static unsigned Page_table::pd_index( void const *const address ) +{ + return (Mword)address >> 20; // 1MB steps +} + +PRIVATE inline +static unsigned Page_table::pt_index( void const *const address ) +{ + return ((Mword)address >> 12) & 255; // 4KB steps for coarse pts +} + +PUBLIC template< typename Alloc > +inline NEEDS[, "bug.h", Page_table::pd_index, + Page_table::current_virt_to_phys, Page_table::pt_index] +Pte +Page_table::walk(void *va, unsigned long size, bool write_back, Alloc const &q, + Page_table *ldir) +{ + unsigned const pd_idx = pd_index(va); + + Mword *pt = 0; + + Pte pde(this, 0, raw + pd_idx); + + if (!pde.valid()) + { + if (size == (4 << 10)) + { + assert (q.valid()); + pt = (Mword*)q.alloc(1<<10); + if (EXPECT_FALSE(!pt)) + return pde; + + Mem::memset_mwords(pt, 0, 1024 >> 2); + + if (write_back || Pte::need_cache_clean()) + Mem_unit::clean_dcache(pt, (char*)pt + 1024); + + raw[pd_idx] = ldir->current_virt_to_phys(pt) | Pde_type_coarse; + + if (write_back || Pte::need_cache_clean()) + Mem_unit::clean_dcache(raw + pd_idx); + } + else + return pde; + } + else if (pde.superpage()) + return pde; + + if (!pt) + pt = (Mword *)Mem_layout::phys_to_pmem(pde.raw() & Pt_base_mask); + + BUG_ON(pt == (void*)~0UL, "could not get virtual address for %lx (from pte @%p)\n", + pde.raw(), pde._pte); + + return Pte(this, 1, pt + pt_index(va)); +} + + +IMPLEMENT +void Page_table::init() +{ + unsigned domains = 0x0001; + + asm volatile ( + "mcr p15, 0, %0, c3, c0 \n" // domains + : + : "r"(domains) ); +} + + +IMPLEMENT /*inline*/ +void Page_table::copy_in(void *my_base, Page_table *o, + void *base, size_t size, unsigned long asid) +{ + unsigned pd_idx = pd_index(my_base); + unsigned pd_idx_max = pd_index(my_base) + pd_index((void*)size); + unsigned o_pd_idx = pd_index(base); + bool need_flush = false; + + //printf("copy_in: %03x-%03x from %03x\n", pd_idx, pd_idx_max, o_pd_idx); + + if (asid != ~0UL) + { + for (unsigned i = pd_idx; i < pd_idx_max; ++i) + if (Pte(this, 0, raw + i).valid()) + { + Mem_unit::flush_vdcache(); + need_flush = true; + break; + } + } + + for (unsigned i = pd_idx; i < pd_idx_max; ++i, ++o_pd_idx) + raw[i] = o->raw[o_pd_idx]; + + if (Pte::need_cache_clean()) + Mem_unit::clean_dcache(raw + pd_idx, raw + pd_idx_max); + + if (need_flush && (asid != ~0UL)) + Mem_unit::dtlb_flush(asid); +} + +#if 0 +PUBLIC +void +Page_table::invalidate(void *my_base, unsigned size, unsigned long asid = ~0UL) +{ + unsigned pd_idx = pd_index(my_base); + unsigned pd_idx_max = pd_index(my_base) + pd_index((void*)size); + bool need_flush = false; + + //printf("invalidate: %03x-%03x\n", pd_idx, pd_idx_max); + + if (asid != ~0UL) + { + for (unsigned i = pd_idx; i < pd_idx_max; ++i) + if (Pte(this, 0, raw + i).valid()) + { + Mem_unit::flush_vdcache(); + need_flush = true; + break; + } + } + + for (unsigned i = pd_idx; i < pd_idx_max; ++i) + raw[i] = 0; + + // clean the caches if manipulating the current pt or in the case if phys. + // tagged caches. + if ((asid != ~0UL) || Pte::need_cache_clean()) + Mem_unit::clean_dcache(raw + pd_idx, raw + pd_idx_max); + + if (need_flush && (asid != ~0UL)) + Mem_unit::tlb_flush(asid); +} +#endif + +IMPLEMENT +void * +Page_table::dir() const +{ + return const_cast(this); +} + diff --git a/kernel/fiasco/src/kern/arm/pagetable-arch_defs.h b/kernel/fiasco/src/kern/arm/pagetable-arch_defs.h new file mode 100644 index 00000000..3d216139 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/pagetable-arch_defs.h @@ -0,0 +1,97 @@ +#ifndef __PAGETABLE_ARCH_DEFS_H__ +#define __PAGETABLE_ARCH_DEFS_H__ + +struct Fld_coarse +{ + mword_t type : 2; // must be 0x01 + mword_t imp : 3; // Implementation defined + mword_t domain : 4; + mword_t sbz : 1; // should be zero + mword_t ptb : MWORD_BITS - 10; // ptb >> 10 +}; + +struct Fld_fine +{ + mword_t type : 2; // must be 0x03 + mword_t imp : 3; // Implementation defined + mword_t domain : 4; + mword_t sbz : 3; // should be zero + mword_t ptb : MWORD_BITS - 12;// ptb >> 12 +}; + +struct Fld_section +{ + mword_t type : 2; // must be 0x02 + mword_t cb : 2; // cachable and bufferable + mword_t imp : 1; // implementation defined + mword_t domain : 4; + mword_t sbz1 : 1; // should be zero + mword_t ap : 2; // protection + mword_t sbz2 : 8; // should be zero 2 + mword_t sb : MWORD_BITS - 20; // sb >> 20 +}; + +struct Fld_empty +{ + mword_t type : 2; // must bew 0x00 + mword_t udef : MWORD_BITS - 2; +}; + +union Fld +{ + Fld_empty e; + Fld_section s; + Fld_coarse c; + Fld_fine f; + mword_t raw; +}; + + +struct Sld_large +{ + mword_t type : 2; // must be 0x01 + mword_t cb : 2; // cache & buffer + mword_t ap0 : 2; + mword_t ap1 : 2; + mword_t ap2 : 2; + mword_t ap3 : 2; + mword_t sbz : 4; // should be zwero + mword_t pb : MWORD_BITS - 16; +}; + +struct Sld_small +{ + mword_t type : 2; // must be 0x02 + mword_t cb : 2; // cache & buffer + mword_t ap0 : 2; + mword_t ap1 : 2; + mword_t ap2 : 2; + mword_t ap3 : 2; + mword_t pb : MWORD_BITS - 12; +}; + +struct Sld_tiny +{ + mword_t type : 2; // must be 0x03 + mword_t cb : 2; // cache & buffer + mword_t ap : 2; + mword_t sbz : 4; + mword_t pb : MWORD_BITS - 10; +}; + +struct Sld_empty +{ + mword_t type : 2; // must be 0x00 + mword_t udef : MWORD_BITS - 2; +}; + +union Sld +{ + Sld_empty e; + Sld_tiny t; + Sld_small s; + Sld_large l; + mword_t raw; +}; + +#endif // __PAGETABLE_ARCH_DEFS_H__ diff --git a/kernel/fiasco/src/kern/arm/pagetable.cpp b/kernel/fiasco/src/kern/arm/pagetable.cpp new file mode 100644 index 00000000..dccb383d --- /dev/null +++ b/kernel/fiasco/src/kern/arm/pagetable.cpp @@ -0,0 +1,37 @@ +INTERFACE: + +#include "paging.h" + +class Pte; +class Mem_page_attr; + +class Page_table //: public Page_table_defs +{ +public: + + enum Status { + E_OK = 0, + E_NOMEM, + E_EXISTS, + E_UPGRADE, + E_INVALID, + }; + +#if 0 + void * operator new(size_t) throw(); + void operator delete(void *); +#endif + static void init(); + + Page_table(); + + void copy_in(void *my_base, Page_table *o, + void *base, size_t size = 0, unsigned long asid = ~0UL); + + void *dir() const; + + static size_t num_page_sizes(); + static size_t const *page_sizes(); + static size_t const *page_shifts(); +}; + diff --git a/kernel/fiasco/src/kern/arm/paging-arm.cpp b/kernel/fiasco/src/kern/arm/paging-arm.cpp new file mode 100644 index 00000000..731da328 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/paging-arm.cpp @@ -0,0 +1,186 @@ +INTERFACE [arm]: + + +class PF {}; + +//----------------------------------------------------------------------------- +INTERFACE [arm && armv5]: + +#include "types.h" + + +namespace Page +{ + typedef Unsigned32 Attribs; + + enum Attribs_enum + { + KERN_RW = 0x0400, ///< User No access + USER_RO = 0x0000, ///< User Read only + USER_RW = 0x0c00, ///< User Read/Write + + USER_BIT = 0x00800, + + Cache_mask = 0x0c, + NONCACHEABLE = 0x00, ///< Caching is off + CACHEABLE = 0x0c, ///< Cache is enabled + + // The next are ARM specific + WRITETHROUGH = 0x08, ///< Write through cached + BUFFERED = 0x04, ///< Write buffer enabled + + MAX_ATTRIBS = 0x0dec, + Local_page = 0, + }; +}; + + + + + +//---------------------------------------------------------------------------- +INTERFACE [arm && (armv6 || armv7)]: + +#include "types.h" + +namespace Page +{ + typedef Unsigned32 Attribs; + + enum Attribs_enum + { + KERN_RO = 0x0210, + KERN_RW = 0x0010, ///< User No access + USER_RO = 0x0230, ///< User Read only + USER_RW = 0x0030, ///< User Read/Write + + USER_BIT = 0x0020, + + Cache_mask = 0x1cc, + NONCACHEABLE = 0x000, ///< Caching is off + CACHEABLE = 0x144, ///< Cache is enabled + + // The next are ARM specific + WRITETHROUGH = 0x08, ///< Write through cached + BUFFERED = 0x40, ///< Write buffer enabled -- Normal, non-cached + + MAX_ATTRIBS = 0x0ffc, + Local_page = 0x800, + }; +}; + + +//----------------------------------------------------------------------------- +INTERFACE [arm]: + +#include "ptab_base.h" + + +// dummy for JDB +class Pte_base +{ +public: + enum + { + Super_level = 0, + Valid = 0x3, + Type_mask = 0x3, + Type_1MB = 0x2, + Type_4KB = 0x2, + Type_coarse_pt = 0x1, + }; + typedef Mword Raw; + Raw raw() const { return _raw; } + Address addr() const { return _raw & (~0UL << 12); } + +protected: + Raw _raw; +}; + +class Pd_entry : public Pte_base +{ +public: + enum { Page_shift = Config::SUPERPAGE_SHIFT }; + Mword leaf() const { return (_raw & Type_mask) == Type_1MB; } + void set(Address p, bool intermed, bool present, unsigned long attrs = 0) + { + _raw = (p & (~0UL << Page_shift)) + | (present ? (intermed ? Type_coarse_pt : Type_1MB) : 0) | attrs; + } +}; + +class Pt_entry : public Pte_base +{ +public: + enum { Page_shift = Config::PAGE_SHIFT }; + Mword leaf() const { return true; } + void set(Address p, bool, bool present, unsigned long attrs = 0) + { + _raw = (p & (~0UL << Page_shift)) | (present ? Type_4KB : 0) | attrs; + } +}; + +typedef Ptab::List< Ptab::Traits< Pd_entry, 20, 12, true>, + Ptab::Traits< Pt_entry, 12, 8, true> > Ptab_traits; + +typedef Ptab_traits Ptab_traits_vpn; +typedef Ptab::Page_addr_wrap Ptab_va_vpn; + +//--------------------------------------------------------------------------- +IMPLEMENTATION [arm && armv5]: + +PUBLIC static inline +Mword PF::is_alignment_error(Mword error) +{ return (error & 0xf0000d) == 0x400001; } + +//--------------------------------------------------------------------------- +IMPLEMENTATION [arm && (armv6 || armv7)]: + +PUBLIC static inline +Mword PF::is_alignment_error(Mword error) +{ return (error & 0xf0040f) == 0x400001; } + +//--------------------------------------------------------------------------- +IMPLEMENTATION [arm]: + +PUBLIC inline +void +Pte_base::clear() +{ _raw = 0; } + +PUBLIC inline +int +Pte_base::valid() const +{ + return _raw & Valid; +} + +IMPLEMENT inline +Mword PF::is_translation_error( Mword error ) +{ + return (error & 0x0d/*FSR_STATUS_MASK*/) == 0x05/*FSR_TRANSL*/; +} + +IMPLEMENT inline +Mword PF::is_usermode_error( Mword error ) +{ + return (error & 0x00010000/*PF_USERMODE*/); +} + +IMPLEMENT inline +Mword PF::is_read_error( Mword error ) +{ + return !(error & (1UL << 11)); +} + +IMPLEMENT inline +Mword PF::addr_to_msgword0( Address pfa, Mword error ) +{ + Mword a = pfa & ~3; + if(is_translation_error( error )) + a |= 1; + if(!is_read_error(error)) + a |= 2; + return a; +} + diff --git a/kernel/fiasco/src/kern/arm/perf_cnt-arm.cpp b/kernel/fiasco/src/kern/arm/perf_cnt-arm.cpp new file mode 100644 index 00000000..cbb81d26 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/perf_cnt-arm.cpp @@ -0,0 +1,496 @@ +INTERFACE [arm && perf_cnt]: + +#include "initcalls.h" + +EXTENSION class Perf_cnt +{ +public: + static Perf_read_fn read_pmc[Max_slot]; + + static const char *perf_type_str; +}; + +// ------------------------------------------------------------------------ +INTERFACE [arm && perf_cnt && !(mpcore || armca8 || armca9)]: + +EXTENSION class Perf_cnt +{ +private: + enum + { + Nr_of_events = 0, + }; + +}; + +// ------------------------------------------------------------------------ +INTERFACE [arm && perf_cnt && mpcore]: + +#include "mem_layout.h" + +EXTENSION class Perf_cnt +{ +private: + enum { + CPU_CONTROL = Mem_layout::Mp_scu_map_base + 0x00, + CONFIG = Mem_layout::Mp_scu_map_base + 0x04, + CPU_STATUS = Mem_layout::Mp_scu_map_base + 0x08, + MON_CONTROL = Mem_layout::Mp_scu_map_base + 0x10, + + MON_CONTROL_ENABLE = 1, + MON_CONTROL_RESET = 2, + + EVENT_DISABLED = 0, + // data not available in any other CPU + EVENT_EXTMEM_CPU0 = 1, + EVENT_EXTMEM_CPU1 = 2, + EVENT_EXTMEM_CPU2 = 3, + EVENT_EXTMEM_CPU3 = 4, + // data available in another CPU cache + EVENT_OTHER_CACHE_HIT_CPU0 = 5, + EVENT_OTHER_CACHE_HIT_CPU1 = 6, + EVENT_OTHER_CACHE_HIT_CPU2 = 7, + EVENT_OTHER_CACHE_HIT_CPU3 = 8, + // non-present + EVENT_NON_PRESENT_CPU0 = 9, + EVENT_NON_PRESENT_CPU1 = 10, + EVENT_NON_PRESENT_CPU2 = 11, + EVENT_NON_PRESENT_CPU3 = 12, + + // line migration instead of sharing + EVENT_LINE_MIGRATION = 13, + + // memory + EVENT_READ_BUSY_MASTER0 = 14, + EVENT_READ_BUSY_MASTER1 = 15, + EVENT_WRITE_BUSY_MASTER0 = 16, + EVENT_WRITE_BUSY_MASTER1 = 17, + EVENT_EXTMEM_TRANSFER_READ = 18, + EVENT_EXTMEM_TRANSFER_WRITE = 19, + + EVENT_CYCLE_COUNT = 31, + + Nr_of_events = 32, + }; + + static Address mon_event_type_addr(int nr) + { return Mem_layout::Mp_scu_map_base + 0x14 + nr; } + + static Address mon_counter(int nr) + { return Mem_layout::Mp_scu_map_base + 0x1c + nr * 4; } +}; + +// ------------------------------------------------------------------------ +INTERFACE [arm && perf_cnt && (armca8 || armca9)]: + +EXTENSION class Perf_cnt +{ +private: + static void pmnc(Mword val) + { asm volatile ("mcr p15, 0, %0, c9, c12, 0" : : "r" (val)); } + + static Mword pmnc() + { Mword val; asm volatile ("mrc p15, 0, %0, c9, c12, 0" : "=r" (val)); return val;} + + + static void cntens(Mword val) + { asm volatile ("mcr p15, 0, %0, c9, c12, 1" : : "r" (val)); } + + static Mword cntens() + { Mword val; asm volatile ("mrc p15, 0, %0, c9, c12, 1" : "=r" (val)); return val;} + + + static void cntenc(Mword val) + { asm volatile ("mcr p15, 0, %0, c9, c12, 2" : : "r" (val)); } + + static Mword cntenc() + { Mword val; asm volatile ("mrc p15, 0, %0, c9, c12, 2" : "=r" (val)); return val;} + + + static void flag(Mword val) + { asm volatile ("mcr p15, 0, %0, c9, c12, 3" : : "r" (val)); } + + static Mword flag() + { Mword val; asm volatile ("mrc p15, 0, %0, c9, c12, 3" : "=r" (val)); return val;} + + static void pmnxsel(Mword val) + { asm volatile ("mcr p15, 0, %0, c9, c12, 5" : : "r" (val)); } + + static Mword pmnxsel() + { Mword val; asm volatile ("mrc p15, 0, %0, c9, c12, 5" : "=r" (val)); return val;} + + + static void ccnt(Mword val) + { asm volatile ("mcr p15, 0, %0, c9, c13, 0" : : "r" (val)); } + + static Mword ccnt() + { Mword val; asm volatile ("mrc p15, 0, %0, c9, c13, 0" : "=r" (val)); return val;} + + + static void evtsel(Mword val) + { asm volatile ("mcr p15, 0, %0, c9, c13, 1" : : "r" (val)); } + + static Mword evtsel() + { Mword val; asm volatile ("mrc p15, 0, %0, c9, c13, 1" : "=r" (val)); return val;} + + + static void pmcnt(Mword val) + { asm volatile ("mcr p15, 0, %0, c9, c13, 2" : : "r" (val)); } + + static Mword pmcnt() + { Mword val; asm volatile ("mrc p15, 0, %0, c9, c13, 2" : "=r" (val)); return val;} + + + static void useren(Mword val) + { asm volatile ("mcr p15, 0, %0, c9, c14, 0" : : "r" (val)); } + + static Mword useren() + { Mword val; asm volatile ("mrc p15, 0, %0, c9, c14, 0" : "=r" (val)); return val;} + + + static void intens(Mword val) + { asm volatile ("mcr p15, 0, %0, c9, c14, 1" : : "r" (val)); } + + static Mword intens() + { Mword val; asm volatile ("mrc p15, 0, %0, c9, c14, 1" : "=r" (val)); return val;} + + static void intenc(Mword val) + { asm volatile ("mcr p15, 0, %0, c9, c14, 2" : : "r" (val)); } + + static Mword intenc() + { Mword val; asm volatile ("mrc p15, 0, %0, c9, c14, 2" : "=r" (val)); return val;} + + enum + { + PMNC_ENABLE = 1 << 0, + PMNC_PERF_RESET = 1 << 1, + PMNC_CNT_RESET = 1 << 2, + }; + + + static int _nr_counters; +}; + +// ------------------------------------------------------------------------ +INTERFACE [arm && perf_cnt && armca8]: + +EXTENSION class Perf_cnt +{ +private: + enum + { + Nr_of_events = 0x73, + }; +}; + +// ------------------------------------------------------------------------ +INTERFACE [arm && perf_cnt && armca9]: + +EXTENSION class Perf_cnt +{ +private: + enum + { + Nr_of_events = 0x94, + }; +}; + +// ------------------------------------------------------------------------ +IMPLEMENTATION [arm && perf_cnt]: + +// ------------------------------------------------------------------------ +IMPLEMENTATION [arm && perf_cnt && !(mpcore || armca8 || armca9)]: + +char const *Perf_cnt::perf_type_str = "none"; + +PUBLIC static FIASCO_INIT_CPU +void +Perf_cnt::init_cpu() +{} + +PUBLIC static inline +Mword +Perf_cnt::read_cycle_cnt() +{ return 0; } + +PUBLIC static inline +unsigned +Perf_cnt::mon_event_type(int) +{ return 0; } + +PUBLIC static inline +unsigned long +Perf_cnt::read_counter(int) +{ return 0; } + +PRIVATE static inline +void +Perf_cnt::set_event_type(int, int) +{} + +// ------------------------------------------------------------------------ +IMPLEMENTATION [arm && perf_cnt && mpcore]: + +#include "io.h" + +char const *Perf_cnt::perf_type_str = "MP-C"; + +PRIVATE static +void +Perf_cnt::set_event_type(int counter_nr, int event) +{ Io::write(event, mon_event_type_addr(counter_nr)); } + +PUBLIC static +unsigned long +Perf_cnt::read_counter(int counter_nr) +{ return Io::read(mon_counter(counter_nr)); } + +PUBLIC static FIASCO_INIT_CPU +void +Perf_cnt::init_cpu() +{ + Io::write(0xff << 16 // clear overflow flags + | MON_CONTROL_RESET | MON_CONTROL_ENABLE, + MON_CONTROL); + + // static config for now... + set_event_type(7, EVENT_CYCLE_COUNT); + + //set_event_type(0, EVENT_EXTMEM_TRANSFER_READ); + //set_event_type(1, EVENT_EXTMEM_TRANSFER_WRITE); + +#if 0 + set_event_type(3, EVENT_EXTMEM_TRANSFER_READ); + set_event_type(4, EVENT_LINE_MIGRATION); + set_event_type(5, EVENT_EXTMEM_CPU2); + set_event_type(6, EVENT_OTHER_CACHE_HIT_CPU2); + set_event_type(7, EVENT_NON_PRESENT_CPU2); +#endif + + //set_event_type(3, EVENT_READ_BUSY_MASTER0); + //set_event_type(4, EVENT_READ_BUSY_MASTER1); + //set_event_type(5, EVENT_WRITE_BUSY_MASTER0); + //set_event_type(6, EVENT_WRITE_BUSY_MASTER1); +} + +PUBLIC static +Mword +Perf_cnt::read_cycle_cnt() +{ return read_counter(7); } + +PUBLIC static +unsigned +Perf_cnt::mon_event_type(int nr) +{ return Io::read(mon_event_type_addr(nr)); } + +// ------------------------------------------------------------------------ +IMPLEMENTATION [arm && perf_cnt && (armca8 || armca9)]: + +#include "cpu.h" + +char const *Perf_cnt::perf_type_str = "ACor"; +int Perf_cnt::_nr_counters; + +PRIVATE static +bool +Perf_cnt::is_avail() +{ return Cpu::boot_cpu()->copro_dbg_model() == Cpu::Copro_dbg_model_v7; } + +PRIVATE static +void +Perf_cnt::set_event_type(int counter_nr, int event) +{ + if (!is_avail()) + return; + + pmnxsel(counter_nr); + evtsel(event); +} + +PUBLIC static +Mword +Perf_cnt::read_cycle_cnt() +{ + if (!is_avail()) + return 0; + return ccnt(); +} + +PUBLIC static +unsigned long +Perf_cnt::read_counter(int counter_nr) +{ + if (!is_avail()) + return 0; + if (counter_nr >= _nr_counters) + return ccnt(); + pmnxsel(counter_nr); + return pmcnt(); +} + +PUBLIC static +unsigned +Perf_cnt::mon_event_type(int nr) +{ + if (!is_avail()) + return 0; + + if (nr >= _nr_counters) + return 0xff; + pmnxsel(nr); + return evtsel(); +} + +PUBLIC static FIASCO_INIT_CPU +void +Perf_cnt::init_cpu() +{ + if (!is_avail()) + return; + + _nr_counters = (pmnc() >> 11) & 0x1f; + + pmnc(PMNC_ENABLE | PMNC_PERF_RESET | PMNC_CNT_RESET); + + cntens((1 << 31) | ((1 << _nr_counters) - 1)); + + //set_event_type(0, 8); + + // allow user to access events + useren(1); +} + +// ------------------------------------------------------------------------ +IMPLEMENTATION [arm && perf_cnt]: + +#include +#include "static_init.h" +#include "tb_entry.h" + +Perf_cnt::Perf_read_fn Perf_cnt::read_pmc[Max_slot] = +{ dummy_read_pmc, dummy_read_pmc }; + +static Mword dummy_read_pmc() { return 0; } + +PUBLIC static +Mword +Perf_cnt::read_counter_0() +{ return read_counter(0); } + +PRIVATE static +Mword +Perf_cnt::read_counter_1() +{ return read_counter(1); } + +PUBLIC static void +Perf_cnt::get_unit_mask(Mword, Unit_mask_type *type, Mword *, Mword *) +{ + *type = Perf_cnt::Fixed; +} + + +PUBLIC static void +Perf_cnt::get_unit_mask_entry(Mword, Mword, Mword *value, const char **desc) +{ + *value = 0; + *desc = 0; +} + + +PUBLIC static void +Perf_cnt::get_perf_event(Mword nr, unsigned *evntsel, + const char **name, const char **desc) +{ + // having one set of static strings in here should be ok + static char _name[20]; + static char _desc[50]; + + snprintf(_name, sizeof(_name), "Event_%lx", nr); + _name[sizeof(_name) - 1] = 0; + + snprintf(_desc, sizeof(_desc), "Check manual for description of event %lx", nr); + _desc[sizeof(_desc) - 1] = 0; + + *name = (const char *)&_name; + *desc = (const char *)&_desc; + *evntsel = nr; +} + +PUBLIC static Mword +Perf_cnt::get_max_perf_event() +{ + return Nr_of_events; +} + +PUBLIC static void +Perf_cnt::split_event(Mword event, unsigned *evntsel, Mword *) +{ + *evntsel = event; +} + +PUBLIC static Mword +Perf_cnt::lookup_event(Mword) { return 0; } + +PUBLIC static void +Perf_cnt::combine_event(Mword evntsel, Mword, Mword *event) +{ + *event = evntsel; +} + +PUBLIC static char const * +Perf_cnt::perf_type() { return perf_type_str; } + +STATIC_INITIALIZE_P(Perf_cnt, PERF_CNT_INIT_PRIO); + +PUBLIC static FIASCO_INIT_CPU +void +Perf_cnt::init() +{ + init_cpu(); + + read_pmc[0] = read_counter_0; + read_pmc[1] = read_counter_1; + + Tb_entry::set_cycle_read_func(read_cycle_cnt); +} + +PUBLIC static inline void +Perf_cnt::init_ap() +{ + init_cpu(); +} + +PUBLIC static int +Perf_cnt::mode(Mword slot, const char **mode, const char **name, + Mword *event, Mword *user, Mword *kern, Mword *edge) +{ + static char _n[Max_slot][5]; + + if (slot >= Max_slot) + return 0; + + *event = mon_event_type(slot); + + snprintf(_n[slot], sizeof(_n[slot]), "e%lx", *event); + _n[slot][sizeof(_n[slot]) - 1] = 0; + *name = _n[slot]; + + *mode = ""; + *user = *kern = *edge = 0; + + return 1; +} + +PUBLIC static +int +Perf_cnt::setup_pmc(Mword slot, Mword event, Mword, Mword, Mword) +{ + if (slot >= Max_slot) + return 0; + + set_event_type(slot, event); + + Tb_entry::set_rdcnt(slot, read_pmc[slot]); + + return 1; +} diff --git a/kernel/fiasco/src/kern/arm/pic-gic.cpp b/kernel/fiasco/src/kern/arm/pic-gic.cpp new file mode 100644 index 00000000..cf7a1bd3 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/pic-gic.cpp @@ -0,0 +1,18 @@ +//------------------------------------------------------------------- +IMPLEMENTATION [arm && pic_gic]: + +#include "gic.h" +#include "initcalls.h" + +EXTENSION class Pic +{ +public: + static Static_object gic; +}; + +Static_object Pic::gic; + +extern "C" +void irq_handler() +{ Pic::gic->hit(0); } + diff --git a/kernel/fiasco/src/kern/arm/space-arm.cpp b/kernel/fiasco/src/kern/arm/space-arm.cpp new file mode 100644 index 00000000..92698f36 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/space-arm.cpp @@ -0,0 +1,6 @@ +IMPLEMENTATION [arm]: // -------------------------------------------------- + +IMPLEMENT inline +void +Space::switchin_ldt() const +{} diff --git a/kernel/fiasco/src/kern/arm/spin_lock-arm.cpp b/kernel/fiasco/src/kern/arm/spin_lock-arm.cpp new file mode 100644 index 00000000..d1ea9a6a --- /dev/null +++ b/kernel/fiasco/src/kern/arm/spin_lock-arm.cpp @@ -0,0 +1,66 @@ +//--------------------------------------------------------------------------- +INTERFACE [arm && mp]: + +EXTENSION class Spin_lock +{ +public: + enum { Arch_lock = 2 }; +}; +//--------------------------------------------------------------------------- +IMPLEMENTATION [arm && mp]: + +#include "processor.h" + +PRIVATE template inline NEEDS["processor.h"] +void +Spin_lock::lock_arch() +{ + Lock_t dummy, tmp; + +#define L(z) \ + __asm__ __volatile__ ( \ + "1: ldr" #z " %[d], [%[lock]] \n" \ + " tst %[d], #2 \n" /* Arch_lock == #2 */ \ + " wfene \n" \ + " bne 1b \n" \ + " ldrex"#z" %[d], [%[lock]] \n" \ + " tst %[d], #2 \n" \ + " orr %[tmp], %[d], #2 \n" \ + " strex"#z"eq %[d], %[tmp], [%[lock]] \n" \ + " teqeq %[d], #0 \n" \ + " bne 1b \n" \ + : [d] "=&r" (dummy), [tmp] "=&r"(tmp), "+m" (_lock) \ + : [lock] "r" (&_lock) \ + : "cc" \ + ) + if (sizeof(Lock_t) == sizeof(char)) + L(b); + else if (sizeof(Lock_t) == sizeof(short)) + L(h); + else + L(); + +#undef L +} + +PRIVATE template inline +void +Spin_lock::unlock_arch() +{ + Lock_t tmp; +#define UNL(z) \ + __asm__ __volatile__( \ + "ldr"#z " %[tmp], %[lock] \n" \ + "bic %[tmp], %[tmp], #2 \n" /* Arch_lock == #2 */ \ + "str"#z " %[tmp], %[lock] \n" \ + "mcr p15, 0, %[tmp], c7, c10, 4 \n" /* drain write buffer */ \ + "sev \n" \ + : [lock] "=m" (_lock), [tmp] "=&r" (tmp)) + if (sizeof(Lock_t) == sizeof(char)) + UNL(b); + else if (sizeof(Lock_t) == sizeof(short)) + UNL(h); + else + UNL(); +#undef UNL +} diff --git a/kernel/fiasco/src/kern/arm/startup-arm.cpp b/kernel/fiasco/src/kern/arm/startup-arm.cpp new file mode 100644 index 00000000..bfed9f26 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/startup-arm.cpp @@ -0,0 +1,64 @@ +IMPLEMENTATION [arm]: + +#include "boot_info.h" +#include "config.h" +#include "cpu.h" +#include "fpu.h" +#include "ipi.h" +#include "kern_lib_page.h" +#include "kernel_task.h" +#include "kip_init.h" +#include "kmem_alloc.h" +#include "kmem_space.h" +#include "per_cpu_data.h" +#include "per_cpu_data_alloc.h" +#include "perf_cnt.h" +#include "pic.h" +#include "processor.h" +#include "static_init.h" +#include "timer.h" +#include "utcb_init.h" + +#include +#include + +IMPLEMENT FIASCO_INIT FIASCO_NOINLINE +void +Startup::stage1() +{ + Proc::cli(); + Boot_info::init(); + Cpu::early_init(); + Config::init(); +} + +IMPLEMENT FIASCO_INIT FIASCO_NOINLINE +void +Startup::stage2() +{ + puts("Hello from Startup::stage2"); + + // The first 4MB of phys memory are always mapped to Map_base + Mem_layout::add_pmem(Mem_layout::Sdram_phys_base, Mem_layout::Map_base, + 4 << 20); + Kip_init::init(); + Kmem_alloc::init(); + + // Initialize cpu-local data management and run constructors for CPU 0 + Per_cpu_data::init_ctors(); + Per_cpu_data_alloc::alloc(0); + Per_cpu_data::run_ctors(0); + + Kmem_space::init(); + Kernel_task::init(); + Mem_space::kernel_space(Kernel_task::kernel_task()); + Pic::init(); + + Cpu::init_mmu(); + Cpu::cpus.cpu(0).init(true); + Fpu::init(0); + Ipi::init(0); + Timer::init(0); + Kern_lib_page::init(); + Utcb_init::init(); +} diff --git a/kernel/fiasco/src/kern/arm/sys_call_page-arm.cpp b/kernel/fiasco/src/kern/arm/sys_call_page-arm.cpp new file mode 100644 index 00000000..814d0ea5 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/sys_call_page-arm.cpp @@ -0,0 +1,56 @@ +INTERFACE: + +#include "types.h" + +//---------------------------------------------------------------------------- +IMPLEMENTATION[arm && armv5]: + +PRIVATE static inline NOEXPORT NEEDS["types.h"] +void +Sys_call_page::set_utcb_get_code(Mword *sys_calls) +{ + *(sys_calls++) = 0xe3e00a02; // mvn r0, #8192 + *(sys_calls++) = 0xe5100fff; // ldr r0, [r0, -#4095] + *(sys_calls++) = 0xe1a0f00e; // mov pc, lr +} + +//---------------------------------------------------------------------------- +IMPLEMENTATION[arm && (armv6 || armv7)]: + +PRIVATE static inline NOEXPORT NEEDS["types.h"] +void +Sys_call_page::set_utcb_get_code(Mword *sys_calls) +{ + *(sys_calls++) = 0xee1d0f70; // mrc 15, 0, r0, cr13, cr0, {3} + *(sys_calls++) = 0xe1a0f00e; // mov pc, lr +} + +//---------------------------------------------------------------------------- +IMPLEMENTATION: + +#include +#include "kernel_task.h" +#include "mem_layout.h" +#include "vmem_alloc.h" +#include "panic.h" + +IMPLEMENT static +void +Sys_call_page::init() +{ + Mword *sys_calls = (Mword*)Mem_layout::Syscalls; + if (!Vmem_alloc::page_alloc(sys_calls, + Vmem_alloc::NO_ZERO_FILL, Vmem_alloc::User)) + panic("FIASCO: can't allocate system-call page.\n"); + + for (unsigned i = 0; i < Config::PAGE_SIZE; i += sizeof(Mword)) + *(sys_calls++) = 0xef000000; // svc + + set_utcb_get_code((Mword*)(Mem_layout::Syscalls + 0xf00)); + + Kernel_task::kernel_task() + ->set_attributes(Mem_layout::Syscalls, + Mem_space::Page_cacheable | Mem_space::Page_user_accessible); + + Mem_unit::flush_cache(); +} diff --git a/kernel/fiasco/src/kern/arm/task-arm.cpp b/kernel/fiasco/src/kern/arm/task-arm.cpp new file mode 100644 index 00000000..d952fbbf --- /dev/null +++ b/kernel/fiasco/src/kern/arm/task-arm.cpp @@ -0,0 +1,8 @@ +IMPLEMENTATION [arm]: + +PRIVATE inline +bool +Task::invoke_arch(L4_msg_tag &, Utcb *) +{ + return false; +} diff --git a/kernel/fiasco/src/kern/arm/tb_entry-arm.cpp b/kernel/fiasco/src/kern/arm/tb_entry-arm.cpp new file mode 100644 index 00000000..4ae64eb4 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/tb_entry-arm.cpp @@ -0,0 +1,158 @@ +INTERFACE [arm]: + +EXTENSION class Tb_entry_base +{ +public: + enum + { + Tb_entry_size = 64, + }; + static Mword (*read_cycle_counter)(); +}; + +/** logged kernel event plus register content. */ +class Tb_entry_ke_reg : public Tb_entry +{ +private: + struct Payload + { + union { + char _msg[16]; ///< debug message + struct { + char _dsc[2]; + char const*_const_msg; + }; + }; + Mword _r0, _r1, _r2; ///< registers + }; +}; + +/** logged trap. */ +class Tb_entry_trap : public Tb_entry +{ +private: + struct Payload + { + Unsigned32 _error; + Mword _cpsr, _sp; + }; +}; + +// -------------------------------------------------------------------- +IMPLEMENTATION [arm]: + +PROTECTED static Mword Tb_entry_base::dummy_read_cycle_counter() { return 0; } + +Mword (*Tb_entry_base::read_cycle_counter)() = dummy_read_cycle_counter; + +PUBLIC static +void +Tb_entry_base::set_cycle_read_func(Mword (*f)()) +{ read_cycle_counter = f; } + +PUBLIC inline +void +Tb_entry::rdtsc() +{ _tsc = read_cycle_counter(); } + +PUBLIC inline +const char * +Tb_entry_ke_reg::msg() const +{ + return payload()->_dsc[0] == 0 && payload()->_dsc[1] == 1 + ? payload()->_const_msg : payload()->_msg; +} + +PUBLIC inline +Mword +Tb_entry_ke_reg::val1() const +{ return payload()->_r0; } + +PUBLIC inline +Mword +Tb_entry_ke_reg::val2() const +{ return payload()->_r1; } + +PUBLIC inline +Mword +Tb_entry_ke_reg::val3() const +{ return payload()->_r2; } + +PUBLIC inline +void +Tb_entry_ke_reg::set(Context const *ctx, Mword eip, Mword v1, Mword v2, Mword v3) +{ + set_global(Tbuf_ke_reg, ctx, eip); + payload()->_r0 = v1; payload()->_r1 = v2; payload()->_r2 = v3; +} + +PUBLIC inline +void +Tb_entry_ke_reg::set_const(Context const *ctx, Mword eip, const char * const msg, + Mword v1, Mword v2, Mword v3) +{ + set(ctx, eip, v1, v2, v3); + payload()->_dsc[0] = 0; payload()->_dsc[1] = 1; + payload()->_const_msg = msg; +} + +PUBLIC inline +void +Tb_entry_ke_reg::set_buf(unsigned i, char c) +{ + if (i < sizeof(payload()->_msg)-1) + payload()->_msg[i] = c >= ' ' ? c : '.'; +} + +PUBLIC inline +void +Tb_entry_ke_reg::term_buf(unsigned i) +{ payload()->_msg[i < sizeof(payload()->_msg)-1 ? i : sizeof(payload()->_msg)-1] = '\0'; } + +// ------------------ +PUBLIC inline +Unsigned16 +Tb_entry_trap::cs() const +{ return 0; } + +PUBLIC inline +Unsigned8 +Tb_entry_trap::trapno() const +{ return 0; } + +PUBLIC inline +Unsigned32 +Tb_entry_trap::error() const +{ return payload()->_error; } + +PUBLIC inline +Mword +Tb_entry_trap::sp() const +{ return payload()->_sp; } + +PUBLIC inline +Mword +Tb_entry_trap::cr2() const +{ return 0; } + +PUBLIC inline +Mword +Tb_entry_trap::eax() const +{ return 0; } + +PUBLIC inline NEEDS ["trap_state.h"] +void +Tb_entry_trap::set(Context const *ctx, Trap_state *ts) +{ + set_global(Tbuf_trap, ctx, ts->ip()); + payload()->_error = ts->error_code; + payload()->_cpsr = ts->psr; + payload()->_sp = ts->sp(); +} + +PUBLIC inline NEEDS ["trap_state.h"] +void +Tb_entry_trap::set(Context const *ctx, Mword pc, Mword ) +{ + set_global(Tbuf_trap, ctx, pc); +} diff --git a/kernel/fiasco/src/kern/arm/thread-arm.cpp b/kernel/fiasco/src/kern/arm/thread-arm.cpp new file mode 100644 index 00000000..f73f2372 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/thread-arm.cpp @@ -0,0 +1,732 @@ +INTERFACE [arm]: + +class Trap_state; + +EXTENSION class Thread +{ +private: + bool _in_exception; + +}; + +// ------------------------------------------------------------------------ +IMPLEMENTATION [arm]: + +#include +#include + +#include "globals.h" +#include "kmem_space.h" +#include "mem_op.h" +#include "static_assert.h" +#include "thread_state.h" +#include "types.h" + +enum { + FSR_STATUS_MASK = 0x0d, + FSR_TRANSL = 0x05, + FSR_DOMAIN = 0x09, + FSR_PERMISSION = 0x0d, +}; + +DEFINE_PER_CPU Per_cpu Thread::dbg_stack; + +PRIVATE static +void +Thread::print_page_fault_error(Mword e) +{ + char const *const excpts[] = + { "reset","undef. insn", "swi", "pref. abort", "data abort", + "XXX", "XXX", "XXX" }; + + unsigned ex = (e >> 20) & 0x07; + + printf("(%lx) %s, %s(%c)",e & 0xff, excpts[ex], + (e & 0x00010000)?"user":"kernel", + (e & 0x00020000)?'r':'w'); +} + +PUBLIC inline +void FIASCO_NORETURN +Thread::fast_return_to_user(Mword ip, Mword sp, Vcpu_state *arg) +{ + extern char __iret[]; + Entry_frame *r = regs(); + assert_kdb((r->psr & Proc::Status_mode_mask) == Proc::Status_mode_user); + + r->ip(ip); + r->sp(sp); // user-sp is in lazy user state and thus handled by + // fill_user_state() + fill_user_state(); + + r->psr &= ~Proc::Status_thumb; + + { + register Vcpu_state *r0 asm("r0") = arg; + + asm volatile + ("mov sp, %0 \t\n" + "mov pc, %1 \t\n" + : + : "r" (nonull_static_cast(r)), "r" (__iret), "r"(r0) + ); + } + panic("__builtin_trap()"); +} + +// +// Public services +// + +IMPLEMENT +void +Thread::user_invoke() +{ + user_invoke_generic(); + assert (current()->state() & Thread_ready); + + Trap_state *ts = nonull_static_cast + (nonull_static_cast(current()->regs())); + + static_assert(sizeof(ts->r[0]) == sizeof(Mword), "Size mismatch"); + Mem::memset_mwords(&ts->r[0], 0, sizeof(ts->r) / sizeof(ts->r[0])); + + if (current()->space()->is_sigma0()) + ts->r[0] = Kmem_space::kdir()->walk(Kip::k(), 0, false, Ptab::Null_alloc(), + 0).phys(Kip::k()); + + extern char __return_from_exception; + + asm volatile + (" mov sp, %[stack_p] \n" // set stack pointer to regs structure + " mov pc, %[rfe] \n" + : + : + [stack_p] "r" (ts), + [rfe] "r" (&__return_from_exception) + ); + + panic("should never be reached"); + while (1) + { + current()->state_del(Thread_ready); + current()->schedule(); + }; + + // never returns here +} + +IMPLEMENT inline NEEDS["space.h", , "types.h" ,"config.h"] +bool Thread::handle_sigma0_page_fault( Address pfa ) +{ + return (mem_space()->v_insert( + Mem_space::Phys_addr::create((pfa & Config::SUPERPAGE_MASK)), + Mem_space::Addr::create(pfa & Config::SUPERPAGE_MASK), + Mem_space::Size(Config::SUPERPAGE_SIZE), + Mem_space::Page_writable | Mem_space::Page_user_accessible + | Mem_space::Page_cacheable) + != Mem_space::Insert_err_nomem); +} + +PUBLIC static +bool +Thread::no_copro_handler(Unsigned32, Trap_state *) +{ return false; } + +typedef bool (*Coproc_insn_handler)(Unsigned32 opcode, Trap_state *ts); +static Coproc_insn_handler handle_copro_fault[16] = + { + Thread::no_copro_handler, + Thread::no_copro_handler, + Thread::no_copro_handler, + Thread::no_copro_handler, + Thread::no_copro_handler, + Thread::no_copro_handler, + Thread::no_copro_handler, + Thread::no_copro_handler, + Thread::no_copro_handler, + Thread::no_copro_handler, + Thread::no_copro_handler, + Thread::no_copro_handler, + Thread::no_copro_handler, + Thread::no_copro_handler, + Thread::no_copro_handler, + Thread::no_copro_handler, + }; + + +extern "C" { + + /** + * The low-level page fault handler called from entry.S. We're invoked with + * interrupts turned off. Apart from turning on interrupts in almost + * all cases (except for kernel page faults in TCB area), just forwards + * the call to Thread::handle_page_fault(). + * @param pfa page-fault virtual address + * @param error_code CPU error code + * @return true if page fault could be resolved, false otherwise + */ + Mword pagefault_entry(const Mword pfa, Mword error_code, + const Mword pc, Return_frame *ret_frame) + { +#if 0 // Double PF detect + static unsigned long last_pfa = ~0UL; + LOG_MSG_3VAL(current(),"PF", pfa, error_code, pc); + if (last_pfa == pfa || pfa == 0) + kdb_ke("DBF"); + last_pfa = pfa; +#endif + if (EXPECT_FALSE(PF::is_alignment_error(error_code))) + { + printf("KERNEL%d: alignment error at %08lx (PC: %08lx, SP: %08lx, FSR: %lx, PSR: %lx)\n", + current_cpu(), pfa, pc, ret_frame->usp, error_code, ret_frame->psr); + return false; + } + + Thread *t = current_thread(); + + // Pagefault in user mode + if (PF::is_usermode_error(error_code)) + { + if (t->vcpu_pagefault(pfa, error_code, pc)) + return 1; + t->state_del(Thread_cancel); + Proc::sti(); + } + // or interrupts were enabled + else if (!(ret_frame->psr & Proc::Status_IRQ_disabled)) + Proc::sti(); + + // Pagefault in kernel mode and interrupts were disabled + else + { + // page fault in kernel memory region, not present, but mapping exists + if (Kmem::is_kmem_page_fault (pfa, error_code)) + { + // We've interrupted a context in the kernel with disabled interrupts, + // the page fault address is in the kernel region, the error code is + // "not mapped" (as opposed to "access error"), and the region is + // actually valid (that is, mapped in Kmem's shared page directory, + // just not in the currently active page directory) + // Remain cli'd !!! + } + else if (!Kmem::is_kmem_page_fault (pfa, error_code)) + { + // No error -- just enable interrupts. + Proc::sti(); + } + else + { + // Error: We interrupted a cli'd kernel context touching kernel space + if (!Thread::log_page_fault()) + printf("*P[%lx,%lx,%lx] ", pfa, error_code, pc); + + kdb_ke ("page fault in cli mode"); + } + + } + + // cache operations we carry out for user space might cause PFs, we just + // ignore those + if (EXPECT_FALSE(t->is_ignore_mem_op_in_progress())) + { + ret_frame->pc += 4; + return 1; + } + + // PFs in the kern_lib_page are always write PFs due to rollbacks and + // insn decoding + if (EXPECT_FALSE((pc & Kmem::Kern_lib_base) == Kmem::Kern_lib_base)) + error_code |= (1UL << 11); + + return t->handle_page_fault(pfa, error_code, pc, ret_frame); + } + + void slowtrap_entry(Trap_state *ts) + { + Thread *t = current_thread(); + + LOG_TRAP; + + if (Config::Support_arm_linux_cache_API) + { + if ( ts->error_code == 0x00200000 + && ts->r[7] == 0xf0002) + { + if (ts->r[2] == 0) + Mem_op::arm_mem_cache_maint(Mem_op::Op_cache_coherent, + (void *)ts->r[0], (void *)ts->r[1]); + ts->r[0] = 0; + return; + } + } + + if (ts->exception_is_undef_insn()) + { + Unsigned32 opcode; + + if (ts->psr & Proc::Status_thumb) + { + Unsigned16 v = *(Unsigned16 *)(ts->pc - 2); + if ((v >> 11) <= 0x1c) + goto undef_insn; + + opcode = (v << 16) | *(Unsigned16 *)ts->pc; + } + else + opcode = *(Unsigned32 *)(ts->pc - 4); + + if (ts->psr & Proc::Status_thumb) + { + if ( (opcode & 0xef000000) == 0xef000000 // A6.3.18 + || (opcode & 0xff100000) == 0xf9000000) + { + if (handle_copro_fault[10](opcode, ts)) + return; + goto undef_insn; + } + } + else + { + if ( (opcode & 0xfe000000) == 0xf2000000 // A5.7.1 + || (opcode & 0xff100000) == 0xf4000000) + { + if (handle_copro_fault[10](opcode, ts)) + return; + goto undef_insn; + } + } + + if ((opcode & 0x0c000000) == 0x0c000000) + { + unsigned copro = (opcode >> 8) & 0xf; + if (handle_copro_fault[copro](opcode, ts)) + return; + } + } + +undef_insn: + // send exception IPC if requested + if (t->send_exception(ts)) + return; + + t->halt(); + } + +}; + +IMPLEMENT inline +bool +Thread::pagein_tcb_request(Return_frame *regs) +{ + //if ((*(Mword*)regs->pc & 0xfff00fff ) == 0xe5900000) + if (*(Mword*)regs->pc == 0xe59ee000) + { + // printf("TCBR: %08lx\n", *(Mword*)regs->pc); + // skip faulting instruction + regs->pc += 4; + // tell program that a pagefault occured we cannot handle + regs->psr |= 0x40000000; // set zero flag in psr + regs->km_lr = 0; + + return true; + } + return false; +} + +//--------------------------------------------------------------------------- +IMPLEMENTATION [arm]: + +#include "trap_state.h" + + +/** Constructor. + @param space the address space + @param id user-visible thread ID of the sender + @param init_prio initial priority + @param mcp thread's maximum controlled priority + @post state() != Thread_invalid + */ +IMPLEMENT +Thread::Thread() + : Sender(0), // select optimized version of constructor + _pager(Thread_ptr::Invalid), + _exc_handler(Thread_ptr::Invalid), + _del_observer(0) +{ + assert (state(false) == Thread_invalid); + + inc_ref(); + _space.space(Kernel_task::kernel_task()); + + if (Config::Stack_depth) + std::memset((char*)this + sizeof(Thread), '5', + Thread::Size-sizeof(Thread)-64); + + // set a magic value -- we use it later to verify the stack hasn't + // been overrun + _magic = magic; + _recover_jmpbuf = 0; + _timeout = 0; + _in_exception = false; + + *reinterpret_cast (--_kernel_sp) = user_invoke; + + // clear out user regs that can be returned from the thread_ex_regs + // system call to prevent covert channel + Entry_frame *r = regs(); + r->sp(0); + r->ip(0); + r->psr = Proc::Status_mode_user; + + state_add(Thread_dead | Thread_suspended); + + // ok, we're ready to go! +} + +IMPLEMENT inline +Mword +Thread::user_sp() const +{ return regs()->sp(); } + +IMPLEMENT inline +void +Thread::user_sp(Mword sp) +{ return regs()->sp(sp); } + +IMPLEMENT inline NEEDS[Thread::exception_triggered] +Mword +Thread::user_ip() const +{ return exception_triggered() ? _exc_cont.ip() : regs()->ip(); } + +IMPLEMENT inline +Mword +Thread::user_flags() const +{ return 0; } + +IMPLEMENT inline NEEDS[Thread::exception_triggered] +void +Thread::user_ip(Mword ip) +{ + if (exception_triggered()) + _exc_cont.ip(ip); + else + { + Entry_frame *r = regs(); + r->ip(ip); + r->psr = (r->psr & ~Proc::Status_mode_mask) | Proc::Status_mode_user; + } +} + + +PUBLIC inline NEEDS ["trap_state.h"] +int +Thread::send_exception_arch(Trap_state *) +{ + // nothing to tweak on ARM + return 1; +} + +PRIVATE static inline +void +Thread::save_fpu_state_to_utcb(Trap_state *ts, Utcb *u) +{ + char *esu = (char *)&u->values[21]; + Fpu::save_user_exception_state(ts, (Fpu::Exception_state_user *)esu); +} + +PRIVATE inline +bool +Thread::invalid_ipc_buffer(void const *a) +{ + if (!_in_exception) + return Mem_layout::in_kernel(((Address)a & Config::SUPERPAGE_MASK) + + Config::SUPERPAGE_SIZE - 1); + + return false; +} + +PROTECTED inline +int +Thread::do_trigger_exception(Entry_frame *r, void *ret_handler) +{ + if (!_exc_cont.valid()) + { + _exc_cont.activate(r, ret_handler); + return 1; + } + return 0; +} + + +PRIVATE static inline +bool FIASCO_WARN_RESULT +Thread::copy_utcb_to_ts(L4_msg_tag const &tag, Thread *snd, Thread *rcv, + unsigned char rights) +{ + Trap_state *ts = (Trap_state*)rcv->_utcb_handler; + Utcb *snd_utcb = snd->utcb().access(); + Mword s = tag.words(); + + if (EXPECT_FALSE(rcv->exception_triggered())) + { + // triggered exception pending + Mem::memcpy_mwords (ts, snd_utcb->values, s > 15 ? 15 : s); + if (EXPECT_TRUE(s > 19)) + { + // sanitize processor mode + // XXX: fix race + snd_utcb->values[19] &= ~Proc::Status_mode_mask; // clear mode + snd_utcb->values[19] |= Proc::Status_mode_supervisor + | Proc::Status_interrupts_disabled; + + Continuation::User_return_frame const *s + = reinterpret_cast((char*)&snd_utcb->values[15]); + + rcv->_exc_cont.set(ts, s); + } + } + else + { + Mem::memcpy_mwords (ts, snd_utcb->values, s > 18 ? 18 : s); + if (EXPECT_TRUE(s > 18)) + ts->pc = snd_utcb->values[18]; + if (EXPECT_TRUE(s > 19)) + { + // sanitize processor mode + Mword p = snd_utcb->values[19]; + p &= ~(Proc::Status_mode_mask | Proc::Status_interrupts_mask); // clear mode & irqs + p |= Proc::Status_mode_user; + ts->psr = p; + } + } + + if (tag.transfer_fpu() && (rights & L4_fpage::W)) + snd->transfer_fpu(rcv); + + if ((tag.flags() & 0x8000) && (rights & L4_fpage::W)) + rcv->utcb().access()->user[2] = snd_utcb->values[25]; + + bool ret = transfer_msg_items(tag, snd, snd_utcb, + rcv, rcv->utcb().access(), rights); + + rcv->state_del(Thread_in_exception); + return ret; +} + + +PRIVATE static inline NEEDS[Thread::save_fpu_state_to_utcb] +bool FIASCO_WARN_RESULT +Thread::copy_ts_to_utcb(L4_msg_tag const &, Thread *snd, Thread *rcv, + unsigned char rights) +{ + Trap_state *ts = (Trap_state*)snd->_utcb_handler; + + { + Lock_guard guard (&cpu_lock); + Utcb *rcv_utcb = rcv->utcb().access(); + + Mem::memcpy_mwords (rcv_utcb->values, ts, 15); + Continuation::User_return_frame *d + = reinterpret_cast((char*)&rcv_utcb->values[15]); + + snd->_exc_cont.get(d, ts); + + + if (EXPECT_TRUE(!snd->exception_triggered())) + { + rcv_utcb->values[18] = ts->pc; + rcv_utcb->values[19] = ts->psr; + } + + if (rcv_utcb->inherit_fpu() && (rights & L4_fpage::W)) + snd->transfer_fpu(rcv); + + save_fpu_state_to_utcb(ts, rcv_utcb); + } + return true; +} + +PROTECTED inline +L4_msg_tag +Thread::invoke_arch(L4_msg_tag /*tag*/, Utcb * /*utcb*/) +{ + return commit_result(-L4_err::ENosys); +} + +PROTECTED inline +int +Thread::sys_control_arch(Utcb *) +{ + return 0; +} + +PUBLIC static inline +bool +Thread::condition_valid(Unsigned32 insn, Unsigned32 psr) +{ + // Matrix of instruction conditions and PSR flags, + // index into the table is the condition from insn + Unsigned16 v[16] = + { + 0xf0f0, + 0x0f0f, + 0xcccc, + 0x3333, + 0xff00, + 0x00ff, + 0xaaaa, + 0x5555, + 0x0c0c, + 0xf3f3, + 0xaa55, + 0x55aa, + 0x0a05, + 0xf5fa, + 0xffff, + 0xffff + }; + + return (v[insn >> 28] >> (psr >> 28)) & 1; +} + +// ------------------------------------------------------------------------ +IMPLEMENTATION [arm && armv6plus]: + +PROTECTED inline +void +Thread::vcpu_resume_user_arch() +{ + // just an experiment for now, we cannot really take the + // user-writable register because user-land might already use it + asm volatile("mcr p15, 0, %0, c13, c0, 2" + : : "r" (utcb().access(true)->values[25]) : "memory"); +} + +// ------------------------------------------------------------------------ +IMPLEMENTATION [arm && !armv6plus]: + +PROTECTED inline +void +Thread::vcpu_resume_user_arch() +{} + +//----------------------------------------------------------------------------- +IMPLEMENTATION [mp]: + +#include "ipi.h" +#include "irq_mgr.h" + +EXTENSION class Thread +{ +public: + static void kern_kdebug_ipi_entry() asm("kern_kdebug_ipi_entry"); +}; + +class Thread_remote_rq_irq : public Irq_base +{ +public: + // we assume IPIs to be top level, no upstream IRQ chips + void handle(Upstream_irq const *) + { Thread::handle_remote_requests_irq(); } + + Thread_remote_rq_irq() + { set_hit(&handler_wrapper); } + + void switch_mode(unsigned) {} +}; + +class Thread_glbl_remote_rq_irq : public Irq_base +{ +public: + // we assume IPIs to be top level, no upstream IRQ chips + void handle(Upstream_irq const *) + { Thread::handle_global_remote_requests_irq(); } + + Thread_glbl_remote_rq_irq() + { set_hit(&handler_wrapper); } + + void switch_mode(unsigned) {} +}; + +class Thread_debug_ipi : public Irq_base +{ +public: + // we assume IPIs to be top level, no upstream IRQ chips + void handle(Upstream_irq const *) + { + Ipi::eoi(Ipi::Debug, current_cpu()); + Thread::kern_kdebug_ipi_entry(); + } + + Thread_debug_ipi() + { set_hit(&handler_wrapper); } + + void switch_mode(unsigned) {} +}; + +//----------------------------------------------------------------------------- +IMPLEMENTATION [mp && !irregular_gic]: + +class Arm_ipis +{ +public: + Arm_ipis() + { + Irq_mgr::mgr->alloc(&remote_rq_ipi, Ipi::Request); + Irq_mgr::mgr->alloc(&glbl_remote_rq_ipi, Ipi::Global_request); + Irq_mgr::mgr->alloc(&debug_ipi, Ipi::Debug); + } + + Thread_remote_rq_irq remote_rq_ipi; + Thread_glbl_remote_rq_irq glbl_remote_rq_ipi; + Thread_debug_ipi debug_ipi; +}; + +static Arm_ipis _arm_ipis; + + +//----------------------------------------------------------------------------- +IMPLEMENTATION [arm && fpu]: + +PUBLIC static +bool +Thread::handle_fpu_trap(Unsigned32 opcode, Trap_state *ts) +{ + if (!condition_valid(opcode, ts->psr)) + { + if (ts->psr & Proc::Status_thumb) + ts->pc += 2; + return true; + } + + if (Fpu::is_enabled()) + { + assert(Fpu::owner(current_cpu()) == current_thread()); + if (Fpu::is_emu_insn(opcode)) + return Fpu::emulate_insns(opcode, ts, current_cpu()); + } + else if (current_thread()->switchin_fpu()) + { + if (Fpu::is_emu_insn(opcode)) + return Fpu::emulate_insns(opcode, ts, current_cpu()); + ts->pc -= (ts->psr & Proc::Status_thumb) ? 2 : 4; + return true; + } + + ts->error_code |= 0x01000000; // tag fpu undef insn + if (Fpu::exc_pending()) + ts->error_code |= 0x02000000; // fpinst and fpinst2 in utcb will be valid + + return false; +} + +PUBLIC static +void +Thread::init_fpu_trap_handling() +{ + handle_copro_fault[10] = Thread::handle_fpu_trap; + handle_copro_fault[11] = Thread::handle_fpu_trap; +} + +STATIC_INITIALIZEX(Thread, init_fpu_trap_handling); diff --git a/kernel/fiasco/src/kern/arm/thread-entry.cpp b/kernel/fiasco/src/kern/arm/thread-entry.cpp new file mode 100644 index 00000000..2d31677b --- /dev/null +++ b/kernel/fiasco/src/kern/arm/thread-entry.cpp @@ -0,0 +1,15 @@ +INTERFACE: + +IMPLEMENTATION[entry]: + +#include +#include "kdb_ke.h" + +extern "C" void kernel_entry(Mword pc, Mword) +{ + Mword pfa; + asm volatile (" mrc p15, 0, %0, c6, c0 \n" : "=r"(pfa) ); + printf("PF: @%08x PC=%08x\n",pfa,pc); + + kdb_ke("page fault"); +}; diff --git a/kernel/fiasco/src/kern/arm/thread-jdb.cpp b/kernel/fiasco/src/kern/arm/thread-jdb.cpp new file mode 100644 index 00000000..1be7a5c8 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/thread-jdb.cpp @@ -0,0 +1,131 @@ +INTERFACE [arm-debug]: + +#include "trap_state.h" + +EXTENSION class Thread +{ +public: + typedef void (*Dbg_extension_entry)(Thread *t, Entry_frame *r); + static Dbg_extension_entry dbg_extension[64]; + +private: + static int call_nested_trap_handler(Trap_state *ts) asm ("call_nested_trap_handler"); + static Trap_state::Handler nested_trap_handler FIASCO_FASTCALL; +}; + + +//----------------------------------------------------------------------------- +IMPLEMENTATION [arm && debug]: + +#include "kernel_task.h" +#include "mem_layout.h" +#include "mmu.h" + +#include + +Thread::Dbg_extension_entry Thread::dbg_extension[64]; + +Trap_state::Handler Thread::nested_trap_handler FIASCO_FASTCALL; + +extern "C" void sys_kdb_ke() +{ + cpu_lock.lock(); + Thread *t = current_thread(); + unsigned *x = (unsigned*)t->regs()->ip(); + + if ((*x & 0xffff0000) == 0xe35e0000) + { + unsigned func = (*x) & 0x3f; + if (Thread::dbg_extension[func]) + { + Thread::dbg_extension[func](t, t->regs()); + t->regs()->ip(t->regs()->ip() + 4); + return; + } + } + + char str[32] = "USER ENTRY"; + if ((*x & 0xfffffff0) == 0xea000000) + // check for always branch, no return, maximum 32 bytes forward + { + strncpy(str, (char *)(x + 1), sizeof(str)); + str[sizeof(str)-1] = 0; + } + + kdb_ke(str); +} + +IMPLEMENT +int +Thread::call_nested_trap_handler(Trap_state *ts) +{ + unsigned phys_cpu = Proc::cpu_id(); + unsigned log_cpu = Cpu::p2l(phys_cpu); + if (log_cpu == ~0U) + { + printf("Trap on unknown CPU phys_id=%x\n", phys_cpu); + log_cpu = 0; + } + + unsigned long &ntr = nested_trap_recover.cpu(log_cpu); + + void *stack = 0; + + if (!ntr) + stack = dbg_stack.cpu(log_cpu).stack_top; + + Mem_space *m = Mem_space::current_mem_space(log_cpu); + + if (Kernel_task::kernel_task() != m) + Kernel_task::kernel_task()->make_current(); + + Mword dummy1, tmp, ret; + { + register Mword _ts asm("r0") = (Mword)ts; + register Mword _lcpu asm("r1") = log_cpu; + + asm volatile( + "mov %[origstack], sp \n" + "ldr %[tmp], [%[ntr]] \n" + "teq %[tmp], #0 \n" + "moveq sp, %[stack] \n" + "add %[tmp], %[tmp], #1 \n" + "str %[tmp], [%[ntr]] \n" + "str %[origstack], [sp, #-4]! \n" + "str %[ntr], [sp, #-4]! \n" + "adr lr, 1f \n" + "mov pc, %[handler] \n" + "1: \n" + "ldr %[ntr], [sp], #4 \n" + "ldr sp, [sp] \n" + "ldr %[tmp], [%[ntr]] \n" + "sub %[tmp], %[tmp], #1 \n" + "str %[tmp], [%[ntr]] \n" + : [origstack] "=&r" (dummy1), [tmp] "=&r" (tmp), + "=r" (_ts), "=r" (_lcpu) + : [ntr] "r" (&ntr), [stack] "r" (stack), + [handler] "r" (*nested_trap_handler), + "2" (_ts), "3" (_lcpu) + : "memory", "r2", "r3", "r4"); + + ret = _ts; + } + + // the jdb-cpu might have changed things we shouldn't miss! + Mmu::flush_cache(); + Mem::isb(); + + if (m != Kernel_task::kernel_task()) + m->make_current(); + + return ret; +} + +//----------------------------------------------------------------------------- +IMPLEMENTATION [arm-!debug]: + +extern "C" void sys_kdb_ke() +{} + +extern "C" void enter_jdb() +{} diff --git a/kernel/fiasco/src/kern/arm/timer-arm-mptimer.cpp b/kernel/fiasco/src/kern/arm/timer-arm-mptimer.cpp new file mode 100644 index 00000000..e9cb29e4 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/timer-arm-mptimer.cpp @@ -0,0 +1,108 @@ +// -------------------------------------------------------------------------- +INTERFACE [arm && mptimer]: + +#include "irq_chip.h" +#include "kmem.h" + +EXTENSION class Timer +{ +public: + static unsigned irq() { return 29; } + +private: + enum + { + Timer_load_reg = Kmem::Mp_scu_map_base + 0x600 + 0x0, + Timer_counter_reg = Kmem::Mp_scu_map_base + 0x600 + 0x4, + Timer_control_reg = Kmem::Mp_scu_map_base + 0x600 + 0x8, + Timer_int_stat_reg = Kmem::Mp_scu_map_base + 0x600 + 0xc, + + Prescaler = 0, + + Timer_control_enable = 1 << 0, + Timer_control_reload = 1 << 1, + Timer_control_itenable = 1 << 2, + Timer_control_prescaler = (Prescaler & 0xff) << 8, + + Timer_int_stat_event = 1, + }; +}; + +// -------------------------------------------------------------- +IMPLEMENTATION [arm && mptimer]: + +#include +#include "config.h" +#include "io.h" +#include "irq_chip.h" +#include "kip.h" + +#include "globals.h" + +PRIVATE static +Mword +Timer::start_as_counter() +{ + Io::write(Timer_control_prescaler | Timer_control_reload + | Timer_control_enable, + Timer_control_reg); + + Mword v = ~0UL; + Io::write(v, Timer_counter_reg); + return v; +} + +PRIVATE static +Mword +Timer::stop_counter() +{ + Mword v = Io::read(Timer_counter_reg); + Io::write(0, Timer_control_reg); + return v; +} + +IMPLEMENT +void +Timer::init(unsigned) +{ + Mword i = interval(); + + Io::write(i, Timer_load_reg); + Io::write(i, Timer_counter_reg); + Io::write(Timer_control_prescaler | Timer_control_reload + | Timer_control_enable | Timer_control_itenable, + Timer_control_reg); +} + +static inline +Unsigned64 +Timer::timer_to_us(Unsigned32 /*cr*/) +{ return 0; } + +static inline +Unsigned64 +Timer::us_to_timer(Unsigned64 us) +{ (void)us; return 0; } + +PUBLIC static inline NEEDS["io.h"] +void +Timer::acknowledge() +{ + Io::write(Timer_int_stat_event, Timer_int_stat_reg); +} + +IMPLEMENT inline +void +Timer::update_one_shot(Unsigned64 wakeup) +{ + (void)wakeup; +} + +IMPLEMENT inline NEEDS["config.h", "kip.h"] +Unsigned64 +Timer::system_clock() +{ + if (Config::Scheduler_one_shot) + return 0; + return Kip::k()->clock; +} diff --git a/kernel/fiasco/src/kern/arm/timer-arm.cpp b/kernel/fiasco/src/kern/arm/timer-arm.cpp new file mode 100644 index 00000000..685038d4 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/timer-arm.cpp @@ -0,0 +1,44 @@ +INTERFACE [arm]: + +EXTENSION class Timer +{ +public: + static unsigned irq_mode() { return 0; } + +private: + static inline void update_one_shot(Unsigned64 wakeup); +}; + +// ------------------------------------------------------------------------ +IMPLEMENTATION [arm]: + +#include "config.h" +#include "globals.h" +#include "kip.h" +#include "watchdog.h" + +IMPLEMENT inline NEEDS["kip.h"] +void +Timer::init_system_clock() +{ + Kip::k()->clock = 0; +} + +IMPLEMENT inline NEEDS["config.h", "globals.h", "kip.h", "watchdog.h"] +void +Timer::update_system_clock(unsigned cpu) +{ + if (cpu == 0) + { + Kip::k()->clock += Config::Scheduler_granularity; + Watchdog::touch(); + } +} + +IMPLEMENT inline NEEDS[Timer::update_one_shot, "config.h"] +void +Timer::update_timer(Unsigned64 wakeup) +{ + if (Config::Scheduler_one_shot) + update_one_shot(wakeup); +} diff --git a/kernel/fiasco/src/kern/arm/timer_tick-arm.cpp b/kernel/fiasco/src/kern/arm/timer_tick-arm.cpp new file mode 100644 index 00000000..22097278 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/timer_tick-arm.cpp @@ -0,0 +1,11 @@ +IMPLEMENTATION [arm]: + +#include "irq_mgr.h" + + +// Do the ARM specific way, really use an IRQ object and its hit +// function to handle timer IRQs as normal IRQs +IMPLEMENT bool +Timer_tick::allocate_irq(Irq_base *irq, unsigned irqnum) +{ return Irq_mgr::mgr->alloc(irq, irqnum); } + diff --git a/kernel/fiasco/src/kern/arm/tramp-mp.S b/kernel/fiasco/src/kern/arm/tramp-mp.S new file mode 100644 index 00000000..96f87b1f --- /dev/null +++ b/kernel/fiasco/src/kern/arm/tramp-mp.S @@ -0,0 +1,178 @@ +#include "globalconfig.h" +#include "tcboffset.h" + + .section .mp_tramp, "awx" + .p2align 12 + +#ifdef CONFIG_ARM_V7 +/* See cache_func_gen.cpp */ + .global v7_invalidate_l1 +invalidate_l1_v7: + mov r3, #0 + mcr p15, 2, r3, c0, c0, 0 + mrc p15, 1, r2, c0, c0, 0 + mov r3, r2, lsr #3 + mov r0, r2, lsr #13 + mov r3, r3, asl #22 + mov r3, r3, lsr #22 + and r2, r2, #7 + mov r0, r0, asl #17 + add ip, r2, #4 + mov r0, r0, lsr #17 + mov r2, r3 + clz r3, r3 +.L3: + mov r4, r2, asl r3 + mov r1, r0 +.L2: + orr r5, r4, r1, asl ip + mcr p15, 0, r5, c7, c6, 2 + subs r1, r1, #1 + bcs .L2 + subs r2, r2, #1 + bcs .L3 + isb + dsb + mov pc, lr +#endif + + .global _tramp_mp_entry +_tramp_mp_entry: + // IRQs off, SVC + mrs r0, cpsr + orr r0, #0xd3 + msr cpsr_c, r0 + + // enable SMP + adr r0, .Lmpcore_phys_base + ldr r0, [r0] + ldr r1, [r0] + orr r1, #1 + str r1, [r0] + +#ifdef CONFIG_ARM_V7 + bl invalidate_l1_v7 +#endif + + mcr p15, 0, r0, c7, c5, 0 // ICIALLU + mcr p15, 0, r0, c7, c5, 6 // BPIALL + + mcr p15, 0, r0, c7, c10, 4 // dsb +#ifdef CONFIG_ARM_V6 + mcr p15, 0, r0, c7, c7, 0 // inv both +#endif + +#ifdef CONFIG_ARM_V7 + // ACTRL is implementation defined + mrc p15, 0, r0, c0, c0, 0 // read MIDR + adr r3, .Lactrl_cpuid_a9 // load addr + ldm r3, {r1,r2} // load mask + val + and r0, r1 // apply mask + teq r0, r2 // check value + bne 2f // only do mcr on this CPU +#endif + + mrc p15, 0, r0, c1, c0, 1 +#ifdef CONFIG_ARM_V7 + tst r0, #0x40 + bne 2f + orr r0, r0, #0x41 +#else + orr r0, r0, #0x20 +#endif + mcr p15, 0, r0, c1, c0, 1 + +2: + + // TLB flush + mcr p15, 0, r0, c8, c7, 0 + + adr r0, _tramp_mp_start_dcr + ldr r0, [r0] + mcr p15, 0, r0, c3, c0 + + // init TTBCR + mov r0, #0 + mcr p15, 0, r0, c2, c0, 2 + + adr r0, _tramp_mp_startup_pdbr + ldr r0, [r0] + mcr p15, 0, r0, c2, c0 + + adr r0, _tramp_mp_startup_cp15_c1 + ldr r0, [r0] + mcr p15, 0, r0, c1, c0 + + // barrier + mrc p15, 0, r0, c2, c0, 0 + mov r0, r0 + ldr r0, 1f + mov pc, r0 +1: + .long _tramp_mp_virt + +.Lmpcore_phys_base: + .long MPCORE_PHYS_BASE + +// only one currently +.Lactrl_cpuid_a9: + .long 0xff0ffff0 + .long 0x410fc090 + + // we run paged now +_tramp_mp_virt: + ldr r0, _cpu_counter_address +1: ldrex r3, [r0] + add r3, r3, #1 + strex r2, r3, [r0] + teq r2, #0 + bne 1b + + // spinlock on cpu-init + adr r0, _tramp_mp_spinlock +1: ldr r1, [r0] + teq r1, #0 + wfene + bne 1b + +2: ldrex r1, [r0] + teq r1, #0 + bne 1b + mov r1, #2 + strex r2, r1, [r0] + teq r2, #0 + bne 1b + + // TLB flush + mcr p15, 0, r0, c8, c7, 0 + + adr sp, _tramp_mp_init_stack_top + mov r0, r3 + nop + ldr pc, [pc, #-4] + + .long BOOT_AP_CPU + +_cpu_counter_address: + .long config_num_ap_cpus + +.global _tramp_mp_startup_cp15_c1 +_tramp_mp_startup_cp15_c1: + .long 0x00000000 + +.global _tramp_mp_startup_pdbr +_tramp_mp_startup_pdbr: + .long 0x00000000 + +.global _tramp_mp_start_dcr +_tramp_mp_start_dcr: + .long 0x00000000 + +.global _tramp_mp_spinlock +_tramp_mp_spinlock: + .long 0 + +_tramp_mp_init_stack: + .space 1024 +_tramp_mp_init_stack_top: + diff --git a/kernel/fiasco/src/kern/arm/trap_state.cpp b/kernel/fiasco/src/kern/arm/trap_state.cpp new file mode 100644 index 00000000..1a309417 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/trap_state.cpp @@ -0,0 +1,95 @@ + +INTERFACE: + +#include "l4_types.h" +#include "entry_frame.h" + +class Trap_state_regs +{ +public: +// static int (*base_handler)(Trap_state *) asm ("BASE_TRAP_HANDLER"); + + Mword pf_address; + Mword error_code; + + Mword r[13]; +}; + + +class Trap_state : public Trap_state_regs, public Return_frame +{ +public: + typedef int (*Handler)(Trap_state*, unsigned cpu); +}; + + +IMPLEMENTATION: + +#include +#include "processor.h" + +PUBLIC inline NEEDS["processor.h"] +void +Trap_state::sanitize_user_state() +{ + psr &= ~(Proc::Status_mode_mask | Proc::Status_interrupts_mask); + psr |= Proc::Status_mode_user; +} + +PUBLIC inline +void +Trap_state::set_ipc_upcall() +{ + error_code = 0x00600000; +} + +PUBLIC inline +void +Trap_state::set_pagefault(Mword pfa, Mword error) +{ + pf_address = pfa; + error_code = error; +} + +PUBLIC inline +unsigned long +Trap_state::ip() const +{ return pc; } + +PUBLIC inline +unsigned long +Trap_state::trapno() const +{ return error_code >> 16; } + +PUBLIC inline +Mword +Trap_state::error() const +{ return error_code; } + +PUBLIC inline +bool +Trap_state::exception_is_undef_insn() const +{ return (error_code & 0x00f00000) == 0x00100000; } + +PUBLIC inline +bool +Trap_state::is_debug_exception() const +{ return false; } + +PUBLIC +void +Trap_state::dump() +{ + char const *excpts[] = + { "reset", "undefined insn", "swi", "prefetch abort", + "data abort", "trigexc", "%&#", "%&#" }; + + printf("EXCEPTION: %s pfa=%08lx, error=%08lx\n", + excpts[(error_code & 0x00700000) >> 20], pf_address, error_code); + + printf("R[0]: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n" + "R[8]: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n", + r[0], r[1], r[2], r[3], r[4], r[5], r[6], r[7], + r[8], r[9], r[10], r[11], r[12], usp, ulr, pc); +} + diff --git a/kernel/fiasco/src/kern/arm/utcb_init-arm.cpp b/kernel/fiasco/src/kern/arm/utcb_init-arm.cpp new file mode 100644 index 00000000..151ec1e3 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/utcb_init-arm.cpp @@ -0,0 +1,20 @@ +IMPLEMENTATION [arm && !armv6plus]: + +#include "mem_layout.h" +#include "paging.h" +#include "panic.h" +#include "vmem_alloc.h" + +IMPLEMENT +void +Utcb_init::init() +{ + if (!Vmem_alloc::page_alloc ((void *)Mem_layout::Utcb_ptr_page, + Vmem_alloc::ZERO_FILL, Vmem_alloc::User)) + panic ("UTCB pointer page allocation failure"); +} + +//----------------------------------------------------------------------------- +IMPLEMENTATION [arm && armv6plus]: + +IMPLEMENT inline void Utcb_init::init() {} diff --git a/kernel/fiasco/src/kern/arm/utcb_support-arm.cpp b/kernel/fiasco/src/kern/arm/utcb_support-arm.cpp new file mode 100644 index 00000000..21b536ea --- /dev/null +++ b/kernel/fiasco/src/kern/arm/utcb_support-arm.cpp @@ -0,0 +1,33 @@ +// ------------------------------------------------------------------------ +IMPLEMENTATION [arm && !armv6plus]: + +#include "mem_layout.h" + +IMPLEMENT inline NEEDS["mem_layout.h"] +User::Ptr +Utcb_support::current() +{ return *reinterpret_cast::Ptr*>(Mem_layout::Utcb_ptr_page); } + +IMPLEMENT inline NEEDS["mem_layout.h"] +void +Utcb_support::current(User::Ptr const &utcb) +{ *reinterpret_cast::Ptr*>(Mem_layout::Utcb_ptr_page) = utcb; } + +// ------------------------------------------------------------------------ +IMPLEMENTATION [arm && armv6plus]: + +IMPLEMENT inline +User::Ptr +Utcb_support::current() +{ + Utcb *u; + asm volatile ("mrc p15, 0, %0, c13, c0, 3" : "=r" (u)); + return User::Ptr(u); +} + +IMPLEMENT inline +void +Utcb_support::current(User::Ptr const &utcb) +{ + asm volatile ("mcr p15, 0, %0, c13, c0, 3" : : "r" (utcb.get()) : "memory"); +} diff --git a/kernel/fiasco/src/kern/arm/vm.cpp b/kernel/fiasco/src/kern/arm/vm.cpp new file mode 100644 index 00000000..9ed2fce5 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/vm.cpp @@ -0,0 +1,440 @@ +INTERFACE: + +#include "mapping_tree.h" +#include "kobject.h" +#include "kmem_slab.h" +#include "l4_types.h" +#include "prio_list.h" +#include "slab_cache.h" +#include "ref_obj.h" + +class Ram_quota; + +class Vm : public Kobject, public Ref_cnt_obj +{ + FIASCO_DECLARE_KOBJ(); + + struct machine_state + { + Mword r[13]; + + Mword sp_usr; + Mword lr_usr; + + Mword sp_irq; + Mword lr_irq; + Mword spsr_irq; + + Mword r_fiq[5]; // r8 - r12 + Mword sp_fiq; + Mword lr_fiq; + Mword spsr_fiq; + + Mword sp_abt; + Mword lr_abt; + Mword spsr_abt; + + Mword sp_und; + Mword lr_und; + Mword spsr_und; + + Mword sp_svc; + Mword lr_svc; + Mword spsr_svc; + + Mword pc; + Mword cpsr; + + Mword pending_events; + + Mword cp15_ttbr0; + Mword cp15_ttbr1; + Mword cp15_ttbcr; + Mword cp15_vector_base; + Mword cp15_dfsr; + Mword cp15_dfar; + Mword cp15_ifsr; + Mword cp15_ifar; + Mword cp15_control; + Mword cp15_prim_region_remap; + Mword cp15_norm_region_remap; + Mword cp15_cid; + Mword cp15_tls[3]; + Mword cp10_fpexc; + + Mword pfs; + Mword pfa; + Mword exit_reason; + }; + +private: + typedef Slab_cache Allocator; + + Mword *_state; + Space *_space; // space the state is contained in +}; + +//----------------------------------------------------------------------------- +INTERFACE [debug]: + +EXTENSION class Vm +{ +public: + struct Vm_log + { + bool is_entry; + Mword pc; + Mword cpsr; + Mword exit_reason; + Mword pending_events; + Mword r0; + Mword r1; + }; + + static unsigned vm_log_fmt(Tb_entry *tbe, int maxlen, char *buf) + asm ("__vm_log_fmt"); +}; + +//----------------------------------------------------------------------------- + +IMPLEMENTATION: + +#include "cpu.h" +#include "cpu_lock.h" +#include "entry_frame.h" +#include "ipc_timeout.h" +#include "logdefs.h" +#include "mem_space.h" +#include "thread_state.h" +#include "timer.h" +#include "ref_ptr.h" + +FIASCO_DEFINE_KOBJ(Vm); + +PUBLIC +static +Vm * +Vm::create(Ram_quota *quota) +{ + if (void *a = allocator()->q_alloc(quota)) + { + Vm *vm = new (a) Vm; + return vm; + } + + return 0; +} + +PUBLIC +Vm::Vm() : _state(0), _space(0) +{ inc_ref(); } + +PUBLIC virtual +bool +Vm::put() +{ return dec_ref() == 0; } + +PUBLIC +inline +Vm::machine_state * +Vm::state() +{ return reinterpret_cast(_state); }; + +// ------------------------------------------------------------------------ +IMPLEMENTATION [arm && tz]: + +#include "thread.h" + +void +Vm::run(Syscall_frame *f, Utcb *utcb) +{ + assert(cpu_lock.test()); + Ref_ptr ref_ptr(this); + + L4_msg_tag const &tag = f->tag(); + + if (tag.words() != 3) + { + WARN("tz: Invalid message length\n"); + f->tag(commit_result(-L4_err::EInval)); + return; + } + + // FIXME: use a send item (fpage) for vm_state. this implementation is wrong! + L4_fpage state_fpage(utcb->values[1]); + + if (!state_fpage.is_mempage() + || state_fpage.order() != 12) + { + WARN("tz: Fpage invalid\n"); + f->tag(commit_result(-L4_err::EInval)); + return; + } + + _state = (Mword *)(Virt_addr(state_fpage.mem_address()).value()); + + { + bool resident; + Mem_space::Phys_addr phys; + Mem_space::Size size; + unsigned int attribs; + + _space = current()->space(); + assert_opt (_space); + Mem_space *const curr_mem_space = _space; + resident = curr_mem_space->v_lookup(Virt_addr(_state), &phys, &size, &attribs); + + if (!resident) + { + WARN("tz: Vm_state not mapped\n"); + f->tag(commit_result(-L4_err::EInval)); + return; + } + } + + // set the temporary label for this VM + Mword label = f->from_spec(); + + while (true) + { + Proc::preemption_point(); + + if (current_thread()->sender_list()->first()) + { + current_thread()->do_ipc(L4_msg_tag(), 0, 0, true, 0, + L4_timeout_pair(L4_timeout::Zero, L4_timeout::Zero), f, 7); + if (EXPECT_TRUE(!f->tag().has_error())) + return; + WARN("tz: Receive event failed\n"); + } + + log_vm(this, 1); + + if (!get_fpu()) + { + f->tag(commit_result(-L4_err::EInval)); + return; + } + + Cpu::cpus.cpu(current()->cpu()).tz_switch_to_ns(_state); + + assert(cpu_lock.test()); + + log_vm(this, 0); + + if ((state()->exit_reason != 1) || + ((state()->exit_reason == 1) && + ((state()->r[0] & 0xffff0000) == 0xffff0000))) + continue; + else + break; + } + + // set label as return value for this vm + f->from(label); + f->tag(L4_msg_tag(L4_msg_tag::Label_task, 0, 0, 0)); + return; +} + +IMPLEMENTATION [arm && tz && fpu]: + +PUBLIC +bool +Vm::get_fpu() +{ + if (!(current()->state() & Thread_fpu_owner)) + { + if (!current_thread()->switchin_fpu()) + { + printf("tz: switchin_fpu failed\n"); + return false; + } + } + return true; +} + +// -------------------------------------------------------------------------- +IMPLEMENTATION [arm && tz && !fpu]: + +PUBLIC +bool +Vm::get_fpu() +{ return true; } + +IMPLEMENTATION [arm && !tz]: + +PUBLIC +L4_msg_tag +Vm::run(Utcb *u) +{ + return L4_msg_tag(0, 0, 0, 0); +} + +// -------------------------------------------------------------------------- +IMPLEMENTATION: + +PUBLIC +void * +Vm::operator new (size_t, void *p) throw() +{ return p; } + +PUBLIC +void +Vm::operator delete (void *_l) +{ + Vm *l = reinterpret_cast(_l); + allocator()->free(l); +} + +static Kmem_slab_t _vm_allocator("Vm"); + +PRIVATE static +Vm::Allocator * +Vm::allocator() +{ return &_vm_allocator; } + +PUBLIC +void +Vm::invoke(L4_obj_ref, Mword, Syscall_frame *f, Utcb *u) +{ + switch (f->tag().proto()) + { + case 0: + case L4_msg_tag::Label_task: + run(nonull_static_cast(f), u); + return; + default: + break; + } + + f->tag(L4_msg_tag(0,0,0,-L4_err::EInval)); +} + +// -------------------------------------------------------------------------- +IMPLEMENTATION [debug]: + +#include "jdb.h" + +PRIVATE +Mword +Vm::jdb_get(Mword *state_ptr) +{ + Mword v = ~0UL; + Jdb::peek(state_ptr, _space, v); + return v; +} + +PUBLIC +void +Vm::dump_machine_state() +{ + machine_state *s = reinterpret_cast(_state); + printf("pc: %08lx cpsr: %08lx exit_reason:%ld \n", + jdb_get(&s->pc), jdb_get(&s->cpsr), jdb_get(&s->exit_reason)); + printf("r0: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n", + jdb_get(&s->r[0]), jdb_get(&s->r[1]), jdb_get(&s->r[2]), jdb_get(&s->r[3]), + jdb_get(&s->r[4]), jdb_get(&s->r[5]), jdb_get(&s->r[6]), jdb_get(&s->r[7])); + printf("r8: %08lx %08lx %08lx %08lx %08lx\n", + jdb_get(&s->r[8]), jdb_get(&s->r[9]), jdb_get(&s->r[10]), jdb_get(&s->r[11]), + jdb_get(&s->r[12])); + + printf("usr: sp %08lx lr %08lx\n", + jdb_get(&s->sp_usr), jdb_get(&s->lr_usr)); + printf("irq: sp %08lx lr %08lx psr %08lx\n", + jdb_get(&s->sp_irq), jdb_get(&s->lr_irq), jdb_get(&s->spsr_irq)); + printf("fiq: sp %08lx lr %08lx psr %08lx\n", + jdb_get(&s->sp_fiq), jdb_get(&s->lr_fiq), jdb_get(&s->spsr_fiq)); + printf("r8: %08lx %08lx %08lx %08lx %08lx\n", + jdb_get(&s->r_fiq[0]), jdb_get(&s->r_fiq[1]), jdb_get(&s->r_fiq[2]), + jdb_get(&s->r_fiq[3]), jdb_get(&s->r_fiq[4])); + + printf("abt: sp %08lx lr %08lx psr %08lx\n", + jdb_get(&s->sp_abt), jdb_get(&s->lr_abt), jdb_get(&s->spsr_abt)); + printf("und: sp %08lx lr %08lx psr %08lx\n", + jdb_get(&s->sp_und), jdb_get(&s->lr_und), jdb_get(&s->spsr_und)); + printf("svc: sp %08lx lr %08lx psr %08lx\n", + jdb_get(&s->sp_svc), jdb_get(&s->lr_svc), jdb_get(&s->spsr_svc)); + printf("cp15_sctlr:%08lx\n", jdb_get(&s->cp15_control)); + printf("cp15_ttbr0:%08lx\n", jdb_get(&s->cp15_ttbr0)); + printf("cp15_ttbr1:%08lx\n", jdb_get(&s->cp15_ttbr1)); + printf("cp15_ttbcr:%08lx\n", jdb_get(&s->cp15_ttbcr)); + printf("dfar: %08lx dfsr: %08lx ifar: %08lx ifsr: %08lx\n", + jdb_get(&s->cp15_dfar), jdb_get(&s->cp15_dfsr), jdb_get(&s->cp15_ifar), + jdb_get(&s->cp15_ifsr)); +} + +PUBLIC +int +Vm::show_short(char *buf, int max) +{ + return snprintf(buf, max, " utcb:%lx pc:%lx ", (Mword)_state, (Mword)jdb_get(&state()->pc)); +} + +IMPLEMENT +unsigned +Vm::vm_log_fmt(Tb_entry *e, int maxlen, char *buf) +{ + Vm_log *l = e->payload(); + if (l->is_entry) + return vm_entry_log_fmt(l, maxlen, buf); + else + return vm_exit_log_fmt(l, maxlen, buf); +} + +PRIVATE static +unsigned +Vm::vm_entry_log_fmt(Vm_log *l, int maxlen, char *buf) +{ + if (l->r0 == 0x1110) + return snprintf(buf, maxlen, "entry: pc:%08lx/%03lx intack irq: %lx", l->pc, l->pending_events, l->r1); + + return snprintf(buf, maxlen, "entry: pc:%08lx/%03lx r0:%lx", l->pc, l->pending_events, l->r0); +} + +PRIVATE static +unsigned +Vm::vm_exit_log_fmt(Vm_log *l, int maxlen, char *buf) +{ + if ((l->r0 & 0xffff0000) == 0xffff0000) + return snprintf(buf, maxlen, "=====: pc:%08lx/%03lx [%04lx]", l->pc, l->pending_events, l->r0 & 0xffff); + if (l->r0 == 0x1105) + return snprintf(buf, maxlen, "exit: pc:%08lx/%03lx enable irq: %lx", l->pc, l->pending_events, l->r1); + if (l->r0 == 0x1109) + return snprintf(buf, maxlen, "exit: pc:%08lx/%03lx disable irq: %lx", l->pc, l->pending_events, l->r1); + if (l->r0 == 0x1110) + return snprintf(buf, maxlen, "exit: pc:%08lx/%03lx intack", l->pc, l->pending_events); + if (l->r0 == 0x1115) + return snprintf(buf, maxlen, "exit: pc:%08lx/%03lx send ipi:%lx", l->pc, l->pending_events, l->r1); + + return snprintf(buf, maxlen, "exit: pc:%08lx/%03lx r0:%lx", l->pc, l->pending_events, l->r0); +} + +PUBLIC static inline +void +Vm::log_vm(Vm *vm, bool is_entry) +{ + if (vm->state()->exit_reason != 1) + return; + if ((vm->state()->r[0] & 0xf000) == 0x7000) + return; + if ((is_entry && (vm->state()->r[0] & 0xffff0000) == 0xffff0000)) + return; + LOG_TRACE("VM entry/entry", "VM", current(), __vm_log_fmt, + Vm::Vm_log *l = tbe->payload(); + l->is_entry = is_entry; + l->pc = vm->state()->pc; + l->cpsr = vm->state()->cpsr; + l->exit_reason = vm->state()->exit_reason; + l->pending_events = vm->state()->pending_events; + l->r0 = vm->state()->r[0]; + l->r1 = vm->state()->r[1]; + ); +} + +// -------------------------------------------------------------------------- +IMPLEMENTATION [!debug]: + +PUBLIC static inline +void +Vm::log_vm(Vm *, bool) +{} diff --git a/kernel/fiasco/src/kern/arm/vmem_alloc-arch.cpp b/kernel/fiasco/src/kern/arm/vmem_alloc-arch.cpp new file mode 100644 index 00000000..4f0c01fa --- /dev/null +++ b/kernel/fiasco/src/kern/arm/vmem_alloc-arch.cpp @@ -0,0 +1,52 @@ +//--------------------------------------------------------------------------- +IMPLEMENTATION [arm]: + +#include "mem.h" +#include "pagetable.h" +#include "mem_space.h" +#include "kmem_alloc.h" +#include "config.h" +#include "panic.h" +#include "kdb_ke.h" +#include "mem_unit.h" +#include "ram_quota.h" +#include "static_init.h" + +#include +#include +#include + + +IMPLEMENT +void *Vmem_alloc::page_alloc(void *address, Zero_fill zf, unsigned mode) +{ + void *vpage = Kmem_alloc::allocator()->alloc(Config::PAGE_SHIFT); + + if (EXPECT_FALSE(!vpage)) + return 0; + + Address page = Mem_space::kernel_space()->virt_to_phys((Address)vpage); + //printf(" allocated page (virt=%p, phys=%08lx\n", vpage, page); + Mem_unit::inv_dcache(vpage, ((char*)vpage) + Config::PAGE_SIZE); + + // insert page into master page table + Pte pte = Mem_space::kernel_space()->dir()->walk(address, Config::PAGE_SIZE, true, + Kmem_alloc::q_allocator(Ram_quota::root), + Mem_space::kernel_space()->dir()); + + unsigned long pa = Page::CACHEABLE; + if (mode & User) + pa |= Page::USER_RW; + else + pa |= Page::KERN_RW; + + pte.set(page, Config::PAGE_SIZE, Mem_page_attr(pa), true); + + Mem_unit::dtlb_flush(address); + + if (zf == ZERO_FILL) + Mem::memset_mwords((unsigned long *)address, 0, Config::PAGE_SIZE >> 2); + + return address; +} + diff --git a/kernel/fiasco/src/kern/auto_quota.h b/kernel/fiasco/src/kern/auto_quota.h new file mode 100644 index 00000000..a8fdc03f --- /dev/null +++ b/kernel/fiasco/src/kern/auto_quota.h @@ -0,0 +1,65 @@ +#pragma once + +class Ram_quota; + +template +class Auto_quota +{ +private: + struct _unspec; + typedef _unspec* _unspec_bool_type; + +public: + Auto_quota(Auto_quota const &) = delete; + Auto_quota operator = (Auto_quota const &) = delete; + + Auto_quota(T *quota, unsigned long size) + : _quota(0), _bytes(size) + { + if (quota->alloc(size)) + _quota = quota; + } + + Auto_quota(Auto_quota &&o) : _quota(o.release()), _bytes(o._bytes) {} + Auto_quota &operator = (Auto_quota &&o) + { + if (*this == o) + return *this; + + reset(o.release(), o._bytes); + return *this; + } + + void reset() + { + if (_quota) + _quota->free(_bytes); + + _quota = 0; + } + + ~Auto_quota() { reset(); } + + T *release() + { + T *q = _quota; + _quota = 0; + return q; + } + + operator _unspec_bool_type () const + { return reinterpret_cast<_unspec_bool_type>(_quota); } + +private: + void reset(T *quota, unsigned long size) + { + if (_quota) + _quota->free(_bytes); + + _quota = quota; + _bytes = size; + } + + T *_quota; + unsigned long _bytes; +}; diff --git a/kernel/fiasco/src/kern/banner.cpp b/kernel/fiasco/src/kern/banner.cpp new file mode 100644 index 00000000..522ee597 --- /dev/null +++ b/kernel/fiasco/src/kern/banner.cpp @@ -0,0 +1,25 @@ +INTERFACE: + +#include "initcalls.h" + +class Banner +{ +}; + + +IMPLEMENTATION: + +#include +#include "config.h" + +PUBLIC static FIASCO_INIT +void +Banner::init() +{ + extern char _initkip_start[]; + printf("\n%s\n", _initkip_start); + if (Config::kernel_warn_config_string && *Config::kernel_warn_config_string) + printf("\033[31mPerformance-critical config option(s) detected:\n" + "%s\033[m", Config::kernel_warn_config_string); + putchar('\n'); +} diff --git a/kernel/fiasco/src/kern/boot_alloc.cpp b/kernel/fiasco/src/kern/boot_alloc.cpp new file mode 100644 index 00000000..458a39c4 --- /dev/null +++ b/kernel/fiasco/src/kern/boot_alloc.cpp @@ -0,0 +1,115 @@ +INTERFACE: + +#include +#include + +class Boot_alloced +{ +private: + struct Block : cxx::S_list_item + { size_t size; }; + + typedef cxx::S_list_bss Block_list; + + static Block_list _free; +}; + +template< typename Base > +class Boot_object : public Base, public Boot_alloced +{ +public: + Boot_object() : Base() {} + + template< typename A1 > + Boot_object(A1 const &a1) : Base(a1) {} + + template< typename A1, typename A2 > + Boot_object(A1 const &a1, A2 const &a2) : Base(a1, a2) {} + + template< typename A1, typename A2, typename A3 > + Boot_object(A1 const &a1, A2 const &a2, A3 const &a3) : Base(a1, a2, a3) {} +}; + + +IMPLEMENTATION: + +#include + +#include "kmem_alloc.h" +#include "warn.h" + +Boot_alloced::Block_list Boot_alloced::_free; + +PUBLIC static +void * +Boot_alloced::alloc(size_t size) +{ + printf("Boot_alloc: size=0x%lx\n", (unsigned long)size); + + // this is best fit list-based allocation + + Block_list::Iterator best = _free.end(); + for (Block_list::Iterator curr = _free.begin(); curr != _free.end(); ++curr) + { + if (((best == _free.end()) || curr->size < best->size) + && curr->size >= size) + best = curr; + } + + if (best == _free.end()) + { + // start from 1k + unsigned long alloc_size = 1024; + + // look for a size suitable and buddy friendly + while (alloc_size < size) + alloc_size <<= 1; + + Block *b = (Block*)Kmem_alloc::allocator()->unaligned_alloc(alloc_size); + printf("Boot_alloc: allocated extra memory block @%p (size=%lx)\n", + b, alloc_size); + + if (!b) + return 0; + + b->size = alloc_size; + _free.add(b); + best = _free.begin(); + } + + + void *b = *best; + Block *rem = (Block *)(((Address)b + size + sizeof(Block) - 1) & ~(sizeof(Block) - 1)); + long rem_sz = (Address)b + (*best)->size - (Address)rem; + printf("Boot_alloc: @ %p\n", b); + if (rem_sz > (long)sizeof(Block)) + { + rem->size = rem_sz; + _free.replace(best, rem); + printf("Boot_alloc: remaining free block @ %p (size=%lx)\n", rem, rem_sz); + } + else + _free.erase(best); + return b; +} + +PUBLIC inline void * +Boot_alloced::operator new (size_t size) throw() +{ return alloc(size); } + +PUBLIC inline void * +Boot_alloced::operator new [] (size_t size) throw() +{ return alloc(size); } + +PUBLIC void +Boot_alloced::operator delete (void *b) +{ + WARN("Boot_alloc: trying to delete boot-time allocated object @ %p\n", b); +} + +PUBLIC void +Boot_alloced::operator delete [] (void *b) +{ + WARN("Boot_alloc: trying to delete boot-time allocated object @ %p\n", b); +} + diff --git a/kernel/fiasco/src/kern/boot_info.cpp b/kernel/fiasco/src/kern/boot_info.cpp new file mode 100644 index 00000000..80a1f894 --- /dev/null +++ b/kernel/fiasco/src/kern/boot_info.cpp @@ -0,0 +1,12 @@ +INTERFACE: + +#include "initcalls.h" + +class Boot_info +{ +public: + static void init() FIASCO_INIT; +}; + +IMPLEMENTATION: +//- diff --git a/kernel/fiasco/src/kern/buddy_alloc.cpp b/kernel/fiasco/src/kern/buddy_alloc.cpp new file mode 100644 index 00000000..803eb72f --- /dev/null +++ b/kernel/fiasco/src/kern/buddy_alloc.cpp @@ -0,0 +1,266 @@ +INTERFACE: + +#include +#include +#include "bitmap.h" +#include "config.h" + +class Buddy_base +{ +protected: + unsigned long _base; + + struct Head : cxx::H_list_item + { + unsigned long index; + + static void link(cxx::H_list &h, void *b, unsigned idx) + { + Head *n = (Head*)b; + n->index = idx; + h.add(n); + } + }; + + typedef cxx::H_list_bss B_list; +}; + +template< int MIN_LOG2_SIZE, int NUM_SIZES, int MAX_MEM > +class Buddy_t_base : public Buddy_base +{ +public: + enum + { + Min_log2_size = MIN_LOG2_SIZE, + Min_size = 1UL << MIN_LOG2_SIZE, + Num_sizes = NUM_SIZES, + Max_size = Min_size << (NUM_SIZES - 1), + Max_mem = MAX_MEM, + }; + +private: + enum + { + // the number of bits in the bitmap is given by the amount of the smallest + // supported blocks. We need an extra bit in the case that the Max_mem + // is no multiple of Max_size to ensure that buddy() does not access + // beyond the bitmap. + Buddy_bits = (Max_mem + Min_size - 1)/Min_size + + !!(Max_mem & (Max_size-1)) + }; + B_list _free[Num_sizes]; + Bitmap _free_map; +}; + + +class Buddy_alloc : public Buddy_t_base<10, 8, Config::kernel_mem_max> +{ +}; + + +//---------------------------------------------------------------------------- +IMPLEMENTATION: + +#include +#include +#include "kdb_ke.h" +#include "warn.h" + +PRIVATE +template +inline +Buddy_base::Head * +Buddy_t_base::buddy(void *block, unsigned long index, Head **new_block) +{ + //printf("buddy(%p, %ld)\n", block, index); + unsigned long const size = Min_size << index; + unsigned long const n_size = size << 1; + if (index + 1 >= Num_sizes) + return 0; + unsigned long b = (unsigned long)block; + unsigned long _buddy = b & ~(n_size-1); + *new_block = (Head*)_buddy; + if (_buddy == b) + _buddy += size; + + Head * const _buddy_h = (Head*)_buddy; + + // this test may access one bit behind our maximum, this is safe because + // we allocated an extra bit + if (_free_map[(_buddy - _base)/Min_size] && _buddy_h->index == index) + return _buddy_h; + + return 0; +} + +PUBLIC +template +inline +void +Buddy_t_base::free(void *block, unsigned long size) +{ + assert_kdb ((unsigned long)block >= _base); + assert_kdb ((unsigned long)block - _base < Max_mem); + assert_kdb (!_free_map[((unsigned long)block - _base) / Min_size]); + //bool _b = 0; + //if (_debug) printf("Buddy::free(%p, %ld)\n", block, size); + unsigned size_index = 0; + while (((unsigned long)Min_size << size_index) < size) + ++size_index; + + if (size != (unsigned long)Min_size << size_index) + WARNX(Info, "Buddy::free: Size mismatch: %lx v %lx\n", + size, (unsigned long)Min_size << size_index); + + + // no need to look for a buddy if we already have the biggest block size + while (size_index + 1 < Num_sizes) + { + Head *n, *b; + b = buddy(block, size_index, &n); + if (b) + { + //if (!_b && _debug) dump(); + //if (_debug) printf(" found buddy %p (n=%p size=%ld)\n", b, n, size_index+1); + B_list::remove(b); + block = n; + ++size_index; + //_b = 1; + } + else + break; + } + + //printf(" link free %p\n", block); + Head::link(_free[size_index], block, size_index); + _free_map.set_bit(((unsigned long)block - _base) / Min_size); + //if (_b && _debug) dump(); +} + + +PUBLIC +template +void +Buddy_t_base::add_mem(void *b, unsigned long size) +{ + unsigned long start = (unsigned long)b; + unsigned long al_start; + al_start = (start + Min_size - 1) & ~(Min_size -1); + + //printf("Buddy::add_mem(%p, %lx): al_start=%lx; _base=%lx\n", b, size, al_start, _base); + + // _debug = 0; + if (size <= al_start-start) + return; + + size -= (al_start-start); + size &= ~(Min_size -1); + + while (size) + { + free((void*)al_start, Min_size); + al_start += Min_size; + size -= Min_size; + } + // _debug = 1; + //dump(); +} + + + +PRIVATE +template +inline +void +Buddy_t_base::split(Head *b, unsigned size_index, unsigned i) +{ + //unsigned si = size_index; + //printf("Buddy::split(%p, %d, %d)\n", b, size_index, i); + for (; i > size_index; ++size_index) + { + unsigned long buddy = (unsigned long)b + (Min_size << size_index); + Head::link(_free[size_index], (void*)buddy, size_index); + _free_map.set_bit((buddy - _base) / Min_size); + } + + //if (si!=i) dump(); +} + +PUBLIC +template +inline +void * +Buddy_t_base::alloc(unsigned long size) +{ + unsigned size_index = 0; + while (((unsigned long)Min_size << size_index) < size) + ++size_index; + + if (size != (unsigned long)Min_size << size_index) + WARNX(Info, "Buddy::alloc: Size mismatch: %lx v %lx\n", + size, (unsigned long)Min_size << size_index); + + //printf("[%u]: Buddy::alloc(%ld)[ret=%p]: size_index=%d\n", Proc::cpu_id(), size, __builtin_return_address(0), size_index); + + for (unsigned i = size_index; i < Num_sizes; ++i) + { + Head *f = _free[i].front(); + if (f) + { + B_list::remove(f); + split(f, size_index, i); + _free_map.clear_bit(((unsigned long)f - _base) / Min_size); + //printf("[%u]: =%p\n", Proc::cpu_id(), f); + return f; + } + } + return 0; +} + +PUBLIC +template< int A, int B, int M > +void +Buddy_t_base::dump() const +{ + printf("Buddy_alloc [%d,%d]\n", Min_size, Num_sizes); + for (unsigned i = 0; i < Num_sizes; ++i) + { + unsigned c = 0; + B_list::Const_iterator h = _free[i].begin(); + printf(" [%d] %p(%ld)", Min_size << i, *h, h != _free[i].end() ? h->index : 0UL); + while (h != _free[i].end()) + { + ++h; + if (c < 5) + printf(" -> %p(%ld)", *h, *h?h->index:0UL); + else + { + printf(" ..."); + break; + } + + ++c; + } + printf("\n"); + } +} + +PUBLIC +void +Buddy_base::init(unsigned long base) +{ _base = base; } + +PUBLIC +template< int A, int B, int M > +unsigned long +Buddy_t_base::avail() const +{ + unsigned long a = 0; + for (unsigned i = 0; i < Num_sizes; ++i) + { + for (B_list::Const_iterator h = _free[i].begin(); h != _free[i].end(); ++h) + a += (Min_size << i); + } + return a; +} + diff --git a/kernel/fiasco/src/kern/bug.h b/kernel/fiasco/src/kern/bug.h new file mode 100644 index 00000000..f04037c4 --- /dev/null +++ b/kernel/fiasco/src/kern/bug.h @@ -0,0 +1,17 @@ +#pragma once + +#ifdef NDEBUG + +# define BUG_ON(expr, ...) + +#else + +# define BUG_ON(expr, ...) \ +if (EXPECT_FALSE(!!(expr))) \ + { \ + printf("%s:%d: BUG (%s): ", __FILE__, __LINE__, #expr); \ + printf(__VA_ARGS__); kdb_ke("bug"); \ + } + +#endif + diff --git a/kernel/fiasco/src/kern/cascade_irq.cpp b/kernel/fiasco/src/kern/cascade_irq.cpp new file mode 100644 index 00000000..7d8b1cc0 --- /dev/null +++ b/kernel/fiasco/src/kern/cascade_irq.cpp @@ -0,0 +1,25 @@ +INTERFACE: + +#include "irq_chip.h" + +/** + * Internal object to cascade a second IRQ controller on a pin of + * another IRQ controller. + */ +class Cascade_irq : public Irq_base +{ +public: + explicit Cascade_irq(Irq_chip_icu *cld, Irq_base::Hit_func hit_f) + : _child(cld) + { + set_hit(hit_f); + } + + Irq_chip_icu *child() const { return _child; } + void switch_mode(unsigned) {} + +private: + Irq_chip_icu *_child; +}; + + diff --git a/kernel/fiasco/src/kern/checksum.cpp b/kernel/fiasco/src/kern/checksum.cpp new file mode 100644 index 00000000..c91267d7 --- /dev/null +++ b/kernel/fiasco/src/kern/checksum.cpp @@ -0,0 +1,44 @@ +INTERFACE: + +class Checksum +{ +}; + + +IMPLEMENTATION: + +#include "mem_layout.h" +#include "boot_info.h" + +// calculate simple checksum over kernel text section and read-only data +PUBLIC static +unsigned Checksum::get_checksum_ro() +{ + unsigned *p, sum = 0; + + for (p = (unsigned*)&Mem_layout::start; + p < (unsigned*)&Mem_layout::etext; sum += *p++) + ; + + return sum; +} + +PUBLIC static +bool +Checksum::check_ro() +{ return Boot_info::get_checksum_ro() == get_checksum_ro(); } + + +// calculate simple checksum over kernel data section +PUBLIC static +unsigned Checksum::get_checksum_rw() +{ + unsigned *p, sum = 0; + + for (p = (unsigned*)&Mem_layout::data_start; + p < (unsigned*)&Mem_layout::edata; sum += *p++) + ; + + return sum; +} + diff --git a/kernel/fiasco/src/kern/clock-generic.cpp b/kernel/fiasco/src/kern/clock-generic.cpp new file mode 100644 index 00000000..20b0a9c5 --- /dev/null +++ b/kernel/fiasco/src/kern/clock-generic.cpp @@ -0,0 +1,28 @@ +INTERFACE: + +#include "l4_types.h" + +EXTENSION class Clock_base +{ +protected: + typedef Cpu_time Counter; +}; + +// ------------------------------------------------------------------------ +IMPLEMENTATION: + +#include "kip.h" + +IMPLEMENT inline NEEDS["kip.h"] +Clock::Counter +Clock::read_counter() const +{ + return Kip::k()->clock; +} + +IMPLEMENT inline +Cpu_time +Clock::us(Time t) +{ + return t; +} diff --git a/kernel/fiasco/src/kern/clock.cpp b/kernel/fiasco/src/kern/clock.cpp new file mode 100644 index 00000000..64e3ef3f --- /dev/null +++ b/kernel/fiasco/src/kern/clock.cpp @@ -0,0 +1,44 @@ +INTERFACE: + +#include "l4_types.h" + +class Clock_base +{ +}; + +class Clock : public Clock_base +{ +public: + typedef Unsigned64 Time; + + Clock(unsigned cpu); + + Time delta(); + + Cpu_time us(Time t); + + +private: + unsigned _cpu_id; + Counter _last_value; + + Counter read_counter() const; +}; + +IMPLEMENTATION: + +IMPLEMENT inline +Clock::Clock(unsigned cpu) + : _cpu_id(cpu), _last_value(read_counter()) +{} + + +IMPLEMENT inline +Clock::Time +Clock::delta() +{ + Counter t = read_counter(); + Counter r = t - _last_value; + _last_value = t; + return Time(r); +} diff --git a/kernel/fiasco/src/kern/config.cpp b/kernel/fiasco/src/kern/config.cpp new file mode 100644 index 00000000..3d601a7a --- /dev/null +++ b/kernel/fiasco/src/kern/config.cpp @@ -0,0 +1,243 @@ +/* + * Global kernel configuration + */ + +INTERFACE: + +#include +#include "config_tcbsize.h" +#include "l4_types.h" + +// special magic to allow old compilers to inline constants + +#define STRINGIFY_(x) #x +#define STRINGIFY(x) STRINGIFY_(x) + +#if defined(__GNUC__) +# if defined(__GNUC_PATCHLEVEL__) +# define COMPILER STRINGIFY(__GNUC__) "." STRINGIFY(__GNUC_MINOR__) "." STRINGIFY(__GNUC_PATCHLEVEL__) +# else +# define COMPILER STRINGIFY(__GNUC__) "." STRINGIFY(__GNUC_MINOR__) +# endif +# define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__) +#else +# define COMPILER "Non-GCC" +# define GCC_VERSION 0 +#endif + +#define GREETING_COLOR_ANSI_OFF "\033[0m" + +#define FIASCO_KERNEL_SUBVERSION 0 + +class Config +{ +public: + + static const char *const kernel_warn_config_string; + enum User_memory_access_type + { + No_access_user_mem = 0, + Access_user_mem_direct, + Must_access_user_mem_direct + }; + + enum { + SERIAL_ESC_IRQ = 2, + SERIAL_ESC_NOIRQ = 1, + SERIAL_NO_ESC = 0, + }; + + static void init(); + static void init_arch(); + + // global kernel configuration + enum + { + Kernel_version_id = 0x87004444 | (FIASCO_KERNEL_SUBVERSION << 16), // "DD....." + // kernel (idle) thread prio + Kernel_prio = 0, + // default prio + Default_prio = 1, + + Warn_level = CONFIG_WARN_LEVEL, + + Kip_syscalls = 1, + + One_shot_min_interval_us = 200, + One_shot_max_interval_us = 10000, + + +#ifdef CONFIG_FINE_GRAINED_CPUTIME + Fine_grained_cputime = true, +#else + Fine_grained_cputime = false, +#endif + +#ifdef CONFIG_STACK_DEPTH + Stack_depth = true, +#else + Stack_depth = false, +#endif +#ifdef CONFIG_NO_FRAME_PTR + Have_frame_ptr = 0, +#else + Have_frame_ptr = 1, +#endif + Mapdb_ram_only = 0, +#ifdef CONFIG_DEBUG_KERNEL_PAGE_FAULTS + Log_kernel_page_faults = 1, +#else + Log_kernel_page_faults = 0, +#endif +#ifdef CONFIG_JDB + Jdb = 1, +#else + Jdb = 0, +#endif +#ifdef CONFIG_JDB_LOGGING + Jdb_logging = 1, +#else + Jdb_logging = 0, +#endif +#ifdef CONFIG_JDB_ACCOUNTING + Jdb_accounting = 1, +#else + Jdb_accounting = 0, +#endif +#ifdef CONFIG_MP + Max_num_cpus = CONFIG_MP_MAX_CPUS, +#else + Max_num_cpus = 1, +#endif + }; + + static bool getchar_does_hlt_works_ok; + static bool esc_hack; + static unsigned tbuf_entries; + static unsigned num_ap_cpus asm("config_num_ap_cpus"); +}; + +#define GREETING_COLOR_ANSI_TITLE "\033[1;32m" +#define GREETING_COLOR_ANSI_INFO "\033[0;32m" + +INTERFACE[ia32,ux]: +#define ARCH_NAME "ia32" +#define TARGET_NAME CONFIG_IA32_TARGET + +INTERFACE[arm]: +#define ARCH_NAME "arm" + +INTERFACE[amd64]: +#define ARCH_NAME "amd64" +#define TARGET_NAME CONFIG_IA32_TARGET + +INTERFACE[ppc32]: +#define ARCH_NAME "ppc32" + +INTERFACE[sparc]: +#define ARCH_NAME "sparc" +#define TARGET_NAME "" + +INTERFACE: +#define CONFIG_KERNEL_VERSION_STRING \ + GREETING_COLOR_ANSI_TITLE "Welcome to Fiasco.OC (" CONFIG_XARCH ")!\\n" \ + GREETING_COLOR_ANSI_INFO "L4/Fiasco.OC " ARCH_NAME " " \ + "microkernel (C) 1998-2012 TU Dresden\\n" \ + "Rev: " CODE_VERSION " compiled with gcc " COMPILER \ + " for " TARGET_NAME " [" CONFIG_LABEL "]\\n" \ + "Build: #" BUILD_NR " " BUILD_DATE "\\n" \ + GREETING_COLOR_ANSI_OFF + + +//--------------------------------------------------------------------------- +INTERFACE [ux]: + +EXTENSION class Config +{ +public: + // 32MB RAM => 2.5MB kmem, 128MB RAM => 16MB kmem, >=512MB RAM => 64MB kmem + static const unsigned kernel_mem_per_cent = 8; + enum + { + kernel_mem_max = 64 << 20 + }; +}; + +//--------------------------------------------------------------------------- +INTERFACE [!ux]: + +EXTENSION class Config +{ +public: + // 32MB RAM => 2.5MB kmem, 128MB RAM => 16MB kmem, >=512MB RAM => 60MB kmem + static const unsigned kernel_mem_per_cent = 8; + enum + { + kernel_mem_max = 60 << 20 + }; +}; + +//--------------------------------------------------------------------------- +INTERFACE [serial]: + +EXTENSION class Config +{ +public: + static int serial_esc; +}; + +//--------------------------------------------------------------------------- +INTERFACE [!serial]: + +EXTENSION class Config +{ +public: + static const int serial_esc = 0; +}; + +//--------------------------------------------------------------------------- +IMPLEMENTATION: + +#include +#include +#include "feature.h" +#include "initcalls.h" +#include "koptions.h" +#include "panic.h" + +KIP_KERNEL_ABI_VERSION(STRINGIFY(FIASCO_KERNEL_SUBVERSION)); + +// class variables +bool Config::esc_hack = false; +#ifdef CONFIG_SERIAL +int Config::serial_esc = Config::SERIAL_NO_ESC; +#endif + +unsigned Config::tbuf_entries = 0x20000 / sizeof(Mword); //1024; +bool Config::getchar_does_hlt_works_ok = false; +unsigned Config::num_ap_cpus; + +//----------------------------------------------------------------------------- +IMPLEMENTATION: + +IMPLEMENT FIASCO_INIT +void Config::init() +{ + init_arch(); + + if (Koptions::o()->opt(Koptions::F_esc)) + esc_hack = true; + +#ifdef CONFIG_SERIAL + if ( Koptions::o()->opt(Koptions::F_serial_esc) + && !Koptions::o()->opt(Koptions::F_noserial) +# ifdef CONFIG_KDB + && Koptions::o()->opt(Koptions::F_nokdb) +# endif + && !Koptions::o()->opt(Koptions::F_nojdb)) + { + serial_esc = SERIAL_ESC_IRQ; + } +#endif +} + diff --git a/kernel/fiasco/src/kern/config_gdt.h b/kernel/fiasco/src/kern/config_gdt.h new file mode 100644 index 00000000..50047928 --- /dev/null +++ b/kernel/fiasco/src/kern/config_gdt.h @@ -0,0 +1,40 @@ +#ifndef CONFIG_GDT_H +#define CONFIG_GDT_H + +#include "globalconfig.h" + +// We want to be Hazelnut compatible, because we want to use the same +// sysenter IPC bindings. When doing sysenter they push 0x1b and the +// returning EIP. The 0x1b value is used for small address spaces where +// the code segment has to be reloaded after a sysexit was performed +// (sysexit loads a flat 4GB segment into CS and SS). +// +// Furthermore, the order of GDT_CODE_KERNEL, GDT_DATA_KERNEL, GDT_CODE_USER, +// GDT_DATA_USER is important since the sysenter/sysexit instruction pair +// assumes this layout (see Intel Reference Manual about sysenter/sysexit) + +#ifdef CONFIG_AMD64 +# define NEXT_SYS_DESC(x) (x + 16) +#else +# define NEXT_SYS_DESC(x) (x + 8) +#endif +#define NEXT_SEG_DESC(x) (x + 8) + +#define GDT_CODE_KERNEL (0x08) // #1 +#define GDT_DATA_KERNEL NEXT_SEG_DESC(GDT_CODE_KERNEL) // #2 + +#define GDT_CODE_USER NEXT_SEG_DESC(GDT_DATA_KERNEL) // #3 +#define GDT_DATA_USER NEXT_SEG_DESC(GDT_CODE_USER) // #4 +#define GDT_TSS NEXT_SEG_DESC(GDT_DATA_USER) // #5: hardware task segment +#define GDT_TSS_DBF NEXT_SYS_DESC(GDT_TSS) // #6: tss for dbf handler + +#define GDT_LDT NEXT_SYS_DESC(GDT_TSS_DBF) // #7 + +#define GDT_UTCB NEXT_SYS_DESC(GDT_LDT) // #8 segment for UTCB pointer +#define GDT_USER_ENTRY1 NEXT_SEG_DESC(GDT_UTCB) // #9 +#define GDT_USER_ENTRY2 NEXT_SEG_DESC(GDT_USER_ENTRY1) // #10 +#define GDT_USER_ENTRY3 NEXT_SEG_DESC(GDT_USER_ENTRY2) // #11 +#define GDT_USER_ENTRY4 NEXT_SEG_DESC(GDT_USER_ENTRY3) // #11 +#define GDT_MAX NEXT_SEG_DESC(GDT_USER_ENTRY4) + +#endif // CONFIG_GDT_H diff --git a/kernel/fiasco/src/kern/config_tcbsize.h b/kernel/fiasco/src/kern/config_tcbsize.h new file mode 100644 index 00000000..bdc1c351 --- /dev/null +++ b/kernel/fiasco/src/kern/config_tcbsize.h @@ -0,0 +1,12 @@ +#ifndef CONFIG_TCBSIZE_H +#define CONFIG_TCBSIZE_H + +#include + +#ifdef CONFIG_CONTEXT_4K +#define THREAD_BLOCK_SIZE (0x1000) +#else +#define THREAD_BLOCK_SIZE (0x800) +#endif + +#endif diff --git a/kernel/fiasco/src/kern/context-vcpu.cpp b/kernel/fiasco/src/kern/context-vcpu.cpp new file mode 100644 index 00000000..2b37303d --- /dev/null +++ b/kernel/fiasco/src/kern/context-vcpu.cpp @@ -0,0 +1,170 @@ +INTERFACE: + +#include "vcpu.h" + +EXTENSION class Context +{ +protected: + Ku_mem_ptr _vcpu_state; +}; + + +IMPLEMENTATION: + +PUBLIC inline +Context::Ku_mem_ptr const & +Context::vcpu_state() const +{ return _vcpu_state; } + + +PUBLIC inline +Mword +Context::vcpu_disable_irqs() +{ + if (EXPECT_FALSE(state() & Thread_vcpu_enabled)) + { + Vcpu_state *vcpu = vcpu_state().access(); + Mword s = vcpu->state; + vcpu->state = s & ~Vcpu_state::F_irqs; + return s & Vcpu_state::F_irqs; + } + return 0; +} + +PUBLIC inline +void +Context::vcpu_restore_irqs(Mword irqs) +{ + if (EXPECT_FALSE((irqs & Vcpu_state::F_irqs) + && (state() & Thread_vcpu_enabled))) + vcpu_state().access()->state |= Vcpu_state::F_irqs; +} + +PUBLIC inline +void +Context::vcpu_save_state_and_upcall() +{ + extern char leave_by_vcpu_upcall[]; + _exc_cont.activate(regs(), leave_by_vcpu_upcall); +} + +PUBLIC inline NEEDS["fpu.h", "space.h"] +bool +Context::vcpu_enter_kernel_mode(Vcpu_state *vcpu) +{ + if (EXPECT_FALSE(state() & Thread_vcpu_enabled)) + { + state_del_dirty(Thread_vcpu_user); + vcpu->_saved_state = vcpu->state; + Mword flags = Vcpu_state::F_traps + | Vcpu_state::F_user_mode; + vcpu->state &= ~flags; + + if (vcpu->_saved_state & Vcpu_state::F_user_mode) + vcpu->_sp = vcpu->_entry_sp; + else + vcpu->_sp = regs()->sp(); + + if (_space.user_mode()) + { + _space.user_mode(false); + state_del_dirty(Thread_vcpu_fpu_disabled); + + if (current() == this) + { + if (state() & Thread_fpu_owner) + Fpu::enable(); + + space()->switchin_context(vcpu_user_space()); + return true; + } + } + } + return false; +} + + + +PUBLIC inline +bool +Context::vcpu_irqs_enabled(Vcpu_state *vcpu) const +{ + return EXPECT_FALSE(state() & Thread_vcpu_enabled) + && vcpu->state & Vcpu_state::F_irqs; +} + +PUBLIC inline +bool +Context::vcpu_pagefaults_enabled(Vcpu_state *vcpu) const +{ + return EXPECT_FALSE(state() & Thread_vcpu_enabled) + && vcpu->state & Vcpu_state::F_page_faults; +} + +PUBLIC inline +bool +Context::vcpu_exceptions_enabled(Vcpu_state *vcpu) const +{ + return EXPECT_FALSE(state() & Thread_vcpu_enabled) + && vcpu->state & Vcpu_state::F_exceptions; +} + +PUBLIC inline +void +Context::vcpu_set_irq_pending() +{ + if (EXPECT_FALSE(state() & Thread_vcpu_enabled)) + vcpu_state().access()->sticky_flags |= Vcpu_state::Sf_irq_pending; +} + +/** Return the space context. + @return space context used for this execution context. + Set with set_space_context(). + */ +PUBLIC inline +Space * +Context::vcpu_user_space() const +{ return _space.vcpu_user(); } + + +// -------------------------------------------------------------------------- +INTERFACE [debug]: + +EXTENSION class Context +{ + static unsigned vcpu_log_fmt(Tb_entry *, int, char *) + asm ("__context_vcpu_log_fmt"); +}; + + +// -------------------------------------------------------------------------- +IMPLEMENTATION [debug]: + +#include "kobject_dbg.h" + +IMPLEMENT +unsigned +Context::vcpu_log_fmt(Tb_entry *e, int maxlen, char *buf) +{ + Vcpu_log *l = e->payload(); + + switch (l->type) + { + case 0: + case 4: + return snprintf(buf, maxlen, "%sret pc=%lx sp=%lx state=%lx task=D:%lx", + l->type == 4 ? "f" : "", l->ip, l->sp, l->state, l->space); + case 1: + return snprintf(buf, maxlen, "ipc from D:%lx task=D:%lx sp=%lx", + Kobject_dbg::pointer_to_id((Kobject*)l->ip), l->state, l->sp); + case 2: + return snprintf(buf, maxlen, "exc #%x err=%lx pc=%lx sp=%lx state=%lx task=D:%lx", + (unsigned)l->trap, l->err, l->ip, l->sp, l->state, l->space); + case 3: + return snprintf(buf, maxlen, "pf pc=%lx pfa=%lx state=%lx task=D:%lx", + l->ip, l->sp, l->state, l->space); + default: + return snprintf(buf, maxlen, "unknown"); + } +} + diff --git a/kernel/fiasco/src/kern/context.cpp b/kernel/fiasco/src/kern/context.cpp new file mode 100644 index 00000000..fbcd6b27 --- /dev/null +++ b/kernel/fiasco/src/kern/context.cpp @@ -0,0 +1,2106 @@ +INTERFACE: + +#include // typedef jmp_buf +#include "types.h" +#include "clock.h" +#include "config.h" +#include "continuation.h" +#include "fpu_state.h" +#include "globals.h" +#include "l4_types.h" +#include "member_offs.h" +#include "per_cpu_data.h" +#include "queue.h" +#include "queue_item.h" +#include "rcupdate.h" +#include "sched_context.h" +#include "space.h" +#include "spin_lock.h" +#include "timeout.h" +#include + +class Entry_frame; +class Thread_lock; +class Context; +class Kobject_iface; + +class Context_ptr +{ +public: + explicit Context_ptr(unsigned long id) : _t(id) {} + Context_ptr() {} + Context_ptr(Context_ptr const &o) : _t(o._t) {} + Context_ptr const &operator = (Context_ptr const &o) + { _t = o._t; return *this; } + + Kobject_iface *ptr(Space *, unsigned char *) const; + + bool is_kernel() const { return false; } + bool is_valid() const { return _t != ~0UL; } + + // only for debugging use + Mword raw() const { return _t;} + +private: + Mword _t; + +}; + +template< typename T > +class Context_ptr_base : public Context_ptr +{ +public: + enum Invalid_type { Invalid }; + explicit Context_ptr_base(Invalid_type) : Context_ptr(0) {} + explicit Context_ptr_base(unsigned long id) : Context_ptr(id) {} + Context_ptr_base() {} + Context_ptr_base(Context_ptr_base const &o) : Context_ptr(o) {} + template< typename X > + Context_ptr_base(Context_ptr_base const &o) : Context_ptr(o) + { X*x = 0; T*t = x; (void)t; } + + Context_ptr_base const &operator = (Context_ptr_base const &o) + { Context_ptr::operator = (o); return *this; } + + template< typename X > + Context_ptr_base const &operator = (Context_ptr_base const &o) + { X*x=0; T*t=x; (void)t; Context_ptr::operator = (o); return *this; } + + //T *ptr(Space *s) const { return static_cast(Context_ptr::ptr(s)); } +}; + +class Context_space_ref +{ +public: + typedef Spin_lock_coloc Space_n_lock; + +private: + Space_n_lock _s; + Address _v; + +public: + Space *space() const { return _s.get_unused(); } + Space_n_lock *lock() { return &_s; } + Address user_mode() const { return _v & 1; } + Space *vcpu_user() const { return reinterpret_cast(_v & ~3); } + Space *vcpu_aware() const { return user_mode() ? vcpu_user() : space(); } + + void space(Space *s) { _s.set_unused(s); } + void vcpu_user(Space *s) { _v = (Address)s; } + void user_mode(bool enable) + { + if (enable) + _v |= (Address)1; + else + _v &= (Address)(~1); + } +}; + +/** An execution context. A context is a runnable, schedulable activity. + It carries along some state used by other subsystems: A lock count, + and stack-element forward/next pointers. + */ +class Context : + public Context_base, + protected Rcu_item +{ + MEMBER_OFFSET(); + friend class Jdb_thread_list; + friend class Context_ptr; + friend class Jdb_utcb; + +protected: + virtual void finish_migration() = 0; + virtual void initiate_migration() = 0; + + struct State_request + { + Mword add; + Mword del; + }; + +public: + /** + * \brief Encapsulate an aggregate of Context. + * + * Allow to get a back reference to the aggregating Context object. + */ + class Context_member + { + private: + Context_member(Context_member const &); + + public: + Context_member() {} + /** + * \brief Get the aggregating Context object. + */ + Context *context() const; + }; + + /** + * \brief Deffered Request. + * + * Represents a request that can be queued for each Context + * and is executed by the target context just after switching to the + * target context. + */ + class Drq : public Queue_item, public Context_member + { + public: + typedef unsigned (Request_func)(Drq *, Context *target, void *); + enum { Need_resched = 1, No_answer = 2 }; + enum Wait_mode { No_wait = 0, Wait = 1 }; + enum Exec_mode { Target_ctxt = 0, Any_ctxt = 1 }; + // enum State { Idle = 0, Handled = 1, Reply_handled = 2 }; + + Request_func *func; + Request_func *reply; + void *arg; + // State state; + }; + + /** + * \brief Queue for deffered requests (Drq). + * + * A FIFO queue each Context aggregates to queue incomming Drq's + * that have to be executed directly after switching to a context. + */ + class Drq_q : public Queue, public Context_member + { + public: + enum Drop_mode { Drop = true, No_drop = false }; + void enq(Drq *rq); + bool handle_requests(Drop_mode drop = No_drop); + bool execute_request(Drq *r, Drop_mode drop, bool local); + }; + + struct Migration_info + { + Mword quantum; + unsigned cpu; + unsigned short prio; + }; + + template + class Ku_mem_ptr : public Context_member + { + MEMBER_OFFSET(); + + private: + typename User::Ptr _u; + T *_k; + + public: + Ku_mem_ptr() : _u(0), _k(0) {} + Ku_mem_ptr(typename User::Ptr const &u, T *k) : _u(u), _k(k) {} + + void set(typename User::Ptr const &u, T *k) + { _u = u; _k = k; } + + T *access(bool is_current = false) const + { + // assert_kdb (!is_current || current() == context()); + if (is_current + && (int)Config::Access_user_mem == Config::Access_user_mem_direct) + return _u.get(); + + unsigned const cpu = current_cpu(); + if ((int)Config::Access_user_mem == Config::Must_access_user_mem_direct + && cpu == context()->cpu() + && Mem_space::current_mem_space(cpu) == context()->space()) + return _u.get(); + return _k; + } + + typename User::Ptr usr() const { return _u; } + T* kern() const { return _k; } + }; + +public: + /** + * Definition of different scheduling modes + */ + enum Sched_mode + { + Periodic = 0x1, ///< 0 = Conventional, 1 = Periodic + Nonstrict = 0x2, ///< 0 = Strictly Periodic, 1 = Non-strictly periodic + }; + + /** + * Definition of different helping modes + */ + enum Helping_mode + { + Helping, + Not_Helping, + Ignore_Helping + }; + + /** + * Return consumed CPU time. + * @return Consumed CPU time in usecs + */ + Cpu_time consumed_time(); + + virtual bool kill() = 0; + + void spill_user_state(); + void fill_user_state(); + + Space * FIASCO_PURE space() const { return _space.space(); } + Mem_space * FIASCO_PURE mem_space() const { return static_cast(space()); } + +protected: + /** + * Update consumed CPU time during each context switch and when + * reading out the current thread's consumed CPU time. + */ + void update_consumed_time(); + + Mword *_kernel_sp; + void *_utcb_handler; + Ku_mem_ptr _utcb; + +private: + friend class Jdb; + friend class Jdb_tcb; + + /// low level page table switching stuff + void switchin_context(Context *) asm ("switchin_context_label") FIASCO_FASTCALL; + + /// low level fpu switching stuff + void switch_fpu(Context *t); + + /// low level cpu switching stuff + void switch_cpu(Context *t); + +protected: + Context_space_ref _space; + +private: + Context *_donatee; + Context *_helper; + + // Lock state + // how many locks does this thread hold on other threads + // incremented in Thread::lock, decremented in Thread::clear + // Thread::kill needs to know + int _lock_cnt; + + + // The scheduling parameters. We would only need to keep an + // anonymous reference to them as we do not need them ourselves, but + // we aggregate them for performance reasons. + Sched_context _sched_context; + Sched_context *_sched; + Unsigned64 _period; + Sched_mode _mode; + + // Pointer to floating point register state + Fpu_state _fpu_state; + // Implementation-specific consumed CPU time (TSC ticks or usecs) + Clock::Time _consumed_time; + + Drq _drq; + Drq_q _drq_q; + +protected: + // for trigger_exception + Continuation _exc_cont; + + jmp_buf *_recover_jmpbuf; // setjmp buffer for page-fault recovery + + struct Migration_rq + { + Migration_info inf; + Spin_lock<> affinity_lock; + bool pending; + bool in_progress; + + Migration_rq() : pending(false), in_progress(false) + { affinity_lock.init(); } + } _migration_rq; + +protected: + // XXX Timeout for both, sender and receiver! In normal case we would have + // to define own timeouts in Receiver and Sender but because only one + // timeout can be set at one time we use the same timeout. The timeout + // has to be defined here because Dirq::hit has to be able to reset the + // timeout (Irq::_irq_thread is of type Receiver). + Timeout *_timeout; + +private: + static Per_cpu _clock; + static Per_cpu _kernel_ctxt; +}; + + +INTERFACE [debug]: + +#include "tb_entry.h" + +EXTENSION class Context +{ +public: + struct Drq_log + { + void *func; + void *reply; + Context *thread; + unsigned target_cpu; + char const *type; + bool wait; + }; + + + struct Vcpu_log + { + Mword state; + Mword ip; + Mword sp; + Mword space; + Mword err; + unsigned char type; + unsigned char trap; + }; + + static unsigned drq_log_fmt(Tb_entry *, int, char *) + asm ("__context_drq_log_fmt"); + +}; + +// -------------------------------------------------------------------------- +IMPLEMENTATION: + +#include +#include "atomic.h" +#include "cpu.h" +#include "cpu_lock.h" +#include "entry_frame.h" +#include "fpu.h" +#include "globals.h" // current() +#include "kdb_ke.h" +#include "lock_guard.h" +#include "logdefs.h" +#include "mem.h" +#include "mem_layout.h" +#include "processor.h" +#include "space.h" +#include "std_macros.h" +#include "thread_state.h" +#include "timer.h" +#include "timeout.h" + +DEFINE_PER_CPU Per_cpu Context::_clock(true); +DEFINE_PER_CPU Per_cpu Context::_kernel_ctxt; + +IMPLEMENT inline NEEDS["kdb_ke.h"] +Kobject_iface * __attribute__((nonnull(1, 2))) +Context_ptr::ptr(Space *s, unsigned char *rights) const +{ + assert_kdb (cpu_lock.test()); + + return static_cast(s)->lookup_local(_t, rights); +} + + + +#include + +/** Initialize a context. After setup, a switch_exec to this context results + in a return to user code using the return registers at regs(). The + return registers are not initialized however; neither is the space_context + to be used in thread switching (use set_space_context() for that). + @pre (_kernel_sp == 0) && (* (stack end) == 0) + @param thread_lock pointer to lock used to lock this context + @param space_context the space context + */ +PUBLIC inline NEEDS ["atomic.h", "entry_frame.h", ] +Context::Context() +: _kernel_sp(reinterpret_cast(regs())), + _utcb_handler(0), + _helper(this), + _sched_context(), + _sched(&_sched_context), + _mode(Sched_mode(0)) +{ + // NOTE: We do not have to synchronize the initialization of + // _space_context because it is constant for all concurrent + // invocations of this constructor. When two threads concurrently + // try to create a new task, they already synchronize in + // sys_task_new() and avoid calling us twice with different + // space_context arguments. + + set_cpu_of(this, current_cpu()); +} + + +PUBLIC inline +void +Context::do_kill() +{ + // If this context owned the FPU, noone owns it now + if (Fpu::is_owner(cpu(), this)) + { + Fpu::set_owner(cpu(), 0); + Fpu::disable(); + } +} + +/** Destroy context. + */ +PUBLIC virtual +Context::~Context() +{} + + +PUBLIC inline +Mword +Context::state(bool check = true) const +{ + (void)check; + assert_kdb(!check || cpu() == current_cpu()); + return _state; +} + +PUBLIC static inline +Context* +Context::kernel_context(unsigned cpu) +{ return _kernel_ctxt.cpu(cpu); } + +PROTECTED static inline +void +Context::kernel_context(unsigned cpu, Context *ctxt) +{ _kernel_ctxt.cpu(cpu) = ctxt; } + + +/** @name State manipulation */ +//@{ +//- + + +/** + * Does the context exist? . + * @return true if this context has been initialized. + */ +PUBLIC inline NEEDS ["thread_state.h"] +Mword +Context::exists() const +{ + return state() != Thread_invalid; +} + +/** + * Is the context about to be deleted. + * @return true if this context is in deletion. + */ +PUBLIC inline NEEDS ["thread_state.h"] +bool +Context::is_invalid() const +{ return state() == Thread_invalid; } + +/** + * Atomically add bits to state flags. + * @param bits bits to be added to state flags + * @return 1 if none of the bits that were added had been set before + */ +PUBLIC inline NEEDS ["atomic.h"] +void +Context::state_add(Mword bits) +{ + assert_kdb(cpu() == current_cpu()); + atomic_or(&_state, bits); +} + +/** + * Add bits in state flags. Unsafe (non-atomic) and + * fast version -- you must hold the kernel lock when you use it. + * @pre cpu_lock.test() == true + * @param bits bits to be added to state flags + */ +PUBLIC inline +void +Context::state_add_dirty(Mword bits) +{ + assert_kdb(cpu() == current_cpu()); + _state |= bits; +} + +/** + * Atomically delete bits from state flags. + * @param bits bits to be removed from state flags + * @return 1 if all of the bits that were removed had previously been set + */ +PUBLIC inline NEEDS ["atomic.h"] +void +Context::state_del(Mword bits) +{ + assert_kdb (current_cpu() == cpu()); + atomic_and(&_state, ~bits); +} + +/** + * Delete bits in state flags. Unsafe (non-atomic) and + * fast version -- you must hold the kernel lock when you use it. + * @pre cpu_lock.test() == true + * @param bits bits to be removed from state flags + */ +PUBLIC inline +void +Context::state_del_dirty(Mword bits, bool check = true) +{ + (void)check; + assert_kdb(!check || cpu() == current_cpu()); + _state &= ~bits; +} + +/** + * Atomically delete and add bits in state flags, provided the + * following rules apply (otherwise state is not changed at all): + * - Bits that are to be set must be clear in state or clear in mask + * - Bits that are to be cleared must be set in state + * @param mask Bits not set in mask shall be deleted from state flags + * @param bits Bits to be added to state flags + * @return 1 if state was changed, 0 otherwise + */ +PUBLIC inline NEEDS ["atomic.h"] +Mword +Context::state_change_safely(Mword mask, Mword bits) +{ + assert_kdb (current_cpu() == cpu()); + Mword old; + + do + { + old = _state; + if (old & bits & mask | ~old & ~mask) + return 0; + } + while (!cas(&_state, old, old & mask | bits)); + + return 1; +} + +/** + * Atomically delete and add bits in state flags. + * @param mask bits not set in mask shall be deleted from state flags + * @param bits bits to be added to state flags + */ +PUBLIC inline NEEDS ["atomic.h"] +Mword +Context::state_change(Mword mask, Mword bits) +{ + assert_kdb (current_cpu() == cpu()); + return atomic_change(&_state, mask, bits); +} + +/** + * Delete and add bits in state flags. Unsafe (non-atomic) and + * fast version -- you must hold the kernel lock when you use it. + * @pre cpu_lock.test() == true + * @param mask Bits not set in mask shall be deleted from state flags + * @param bits Bits to be added to state flags + */ +PUBLIC inline +void +Context::state_change_dirty(Mword mask, Mword bits, bool check = true) +{ + (void)check; + assert_kdb(!check || cpu() == current_cpu()); + _state &= mask; + _state |= bits; +} + +//@} +//- + + +PUBLIC inline +Context_space_ref * +Context::space_ref() +{ return &_space; } + +PUBLIC inline +Space * +Context::vcpu_aware_space() const +{ return _space.vcpu_aware(); } +#if 0 +/** Convenience function: Return memory space. */ +PUBLIC inline NEEDS["space.h"] +Mem_space* +Context::mem_space() const +{ + return space()->mem_space(); +} +#endif + +/** Registers used when iret'ing to user mode. + @return return registers + */ +PUBLIC inline NEEDS["cpu.h", "entry_frame.h"] +Entry_frame * +Context::regs() const +{ + return reinterpret_cast + (Cpu::stack_align(reinterpret_cast(this) + Size)) - 1; +} + +/** @name Lock counting + These functions count the number of locks + this context holds. A context must not be deleted if its lock + count is nonzero. */ +//@{ +//- + +/** Increment lock count. + @post lock_cnt() > 0 */ +PUBLIC inline +void +Context::inc_lock_cnt() +{ + _lock_cnt++; +} + +/** Decrement lock count. + @pre lock_cnt() > 0 + */ +PUBLIC inline +void +Context::dec_lock_cnt() +{ + _lock_cnt--; +} + +/** Lock count. + @return lock count + */ +PUBLIC inline +int +Context::lock_cnt() const +{ + return _lock_cnt; +} + +//@} + +/** + * Switch active timeslice of this Context. + * @param next Sched_context to switch to + */ +PUBLIC +void +Context::switch_sched(Sched_context * const next) +{ + // Ensure CPU lock protection + assert_kdb (cpu_lock.test()); + + // If we're leaving the global timeslice, invalidate it + // This causes schedule() to select a new timeslice via set_current_sched() + if (sched() == current_sched()) + invalidate_sched(); +#if 0 + // Ensure the new timeslice has a full quantum + assert_kdb (next->left() == next->quantum()); +#endif + if (in_ready_list()) + ready_dequeue(); + + set_sched(next); + ready_enqueue(); +} + +/** + * Select a different context for running and activate it. + */ +PUBLIC +void +Context::schedule() +{ + Lock_guard guard(&cpu_lock); + + CNT_SCHEDULE; + + // Ensure only the current thread calls schedule + assert_kdb (this == current()); + + unsigned current_cpu = ~0U; + Sched_context::Ready_queue *rq = 0; + + // Enqueue current thread into ready-list to schedule correctly + update_ready_list(); + + // Select a thread for scheduling. + Context *next_to_run; + + do + { + // I may've been migrated during the switch_exec_locked in the while + // statement below. So cxheck out if I've to use a new ready queue. + if (cpu() != current_cpu) + { + current_cpu = cpu(); + rq = &Sched_context::rq(current_cpu); + if (rq->schedule_in_progress) + return; + // Nested invocations of schedule() are bugs + assert_kdb (!rq->schedule_in_progress); + } + + for (;;) + { + next_to_run = rq->next_to_run()->context(); + + // Ensure ready-list sanity + assert_kdb (next_to_run); + + if (EXPECT_TRUE (next_to_run->state() & Thread_ready_mask)) + break; + + next_to_run->ready_dequeue(); + + rq->schedule_in_progress = this; + + cpu_lock.clear(); + Proc::irq_chance(); + cpu_lock.lock(); + + // check if we've been migrated meanwhile + if (EXPECT_FALSE(current_cpu != cpu())) + { + current_cpu = cpu(); + rq = &Sched_context::rq(current_cpu); + if (rq->schedule_in_progress) + return; + } + else + rq->schedule_in_progress = 0; + } + } + while (EXPECT_FALSE(schedule_switch_to_locked(next_to_run))); +} + +/** + * Return if there is currently a schedule() in progress + */ +PUBLIC inline +Context * +Context::schedule_in_progress() +{ + return sched()->schedule_in_progress(cpu()); +} + +PUBLIC inline NEEDS[Context::schedule_in_progress] +void +Context::schedule_if(bool s) +{ + if (!s || schedule_in_progress()) + return; + + schedule(); +} + +PROTECTED inline +void +Context::reset_schedule_in_progress() +{ sched()->reset_schedule_in_progress(cpu()); } + +/** + * Return currently active global Sched_context. + */ +PUBLIC static inline +Sched_context * +Context::current_sched() +{ + return Sched_context::rq(current_cpu()).current_sched(); +} + +/** + * Set currently active global Sched_context. + */ +PROTECTED +void +Context::set_current_sched(Sched_context *sched) +{ + assert_kdb (sched); + // Save remainder of previous timeslice or refresh it, unless it had + // been invalidated + unsigned cpu = this->cpu(); + Sched_context::Ready_queue &rq = Sched_context::rq(cpu); + + Timeout * const tt = timeslice_timeout.cpu(cpu); + Unsigned64 clock = Timer::system_clock(); + if (Sched_context *s = rq.current_sched()) + { + Signed64 left = tt->get_timeout(clock); + if (left > 0) + s->set_left(left); + else + s->replenish(); + + LOG_SCHED_SAVE(s); + } + + // Program new end-of-timeslice timeout + tt->reset(); + tt->set(clock + sched->left(), cpu); + + // Make this timeslice current + rq.activate(sched); + + LOG_SCHED_LOAD(sched); +} + +/** + * Invalidate (expire) currently active global Sched_context. + */ +PROTECTED inline NEEDS["logdefs.h","timeout.h"] +void +Context::invalidate_sched() +{ + //LOG_SCHED_INVALIDATE; + sched()->invalidate_sched(cpu()); +} + +/** + * Return Context's Sched_context with id 'id'; return time slice 0 as default. + * @return Sched_context with id 'id' or 0 + */ +PUBLIC inline +Sched_context * +Context::sched_context(unsigned short const id = 0) const +{ + if (EXPECT_TRUE (!id)) + return const_cast(&_sched_context); +#if 0 + for (Sched_context *tmp = _sched_context.next(); + tmp != &_sched_context; tmp = tmp->next()) + if (tmp->id() == id) + return tmp; +#endif + return 0; +} + +/** + * Return Context's currently active Sched_context. + * @return Active Sched_context + */ +PUBLIC inline +Sched_context * +Context::sched() const +{ + return _sched; +} + +/** + * Set Context's currently active Sched_context. + * @param sched Sched_context to be activated + */ +PROTECTED inline +void +Context::set_sched(Sched_context * const sched) +{ + _sched = sched; +} + +/** + * Return Context's real-time period length. + * @return Period length in usecs + */ +PUBLIC inline +Unsigned64 +Context::period() const +{ + return _period; +} + +/** + * Set Context's real-time period length. + * @param period New period length in usecs + */ +PROTECTED inline +void +Context::set_period(Unsigned64 const period) +{ + _period = period; +} + +/** + * Return Context's scheduling mode. + * @return Scheduling mode + */ +PUBLIC inline +Context::Sched_mode +Context::mode() const +{ + return _mode; +} + +/** + * Set Context's scheduling mode. + * @param mode New scheduling mode + */ +PUBLIC inline +void +Context::set_mode(Context::Sched_mode const mode) +{ + _mode = mode; +} + +// queue operations + +// XXX for now, synchronize with global kernel lock +//- + +/** + * Enqueue current() if ready to fix up ready-list invariant. + */ +PRIVATE inline NOEXPORT +void +Context::update_ready_list() +{ + assert_kdb (this == current()); + + if (state() & Thread_ready_mask) + ready_enqueue(); +} + +/** + * Check if Context is in ready-list. + * @return 1 if thread is in ready-list, 0 otherwise + */ +PUBLIC inline +Mword +Context::in_ready_list() const +{ + return sched()->in_ready_list(); +} + +/** + * Enqueue context in ready-list. + */ +PUBLIC +void +Context::ready_enqueue(bool check = true) +{ + (void)check; + assert_kdb(!check || current_cpu() == cpu()); + //Lock_guard guard (&cpu_lock); + + // Don't enqueue threads that are not ready or have no own time + if (EXPECT_FALSE (!(state(check) & Thread_ready_mask) || !sched()->left())) + return; + + sched()->ready_enqueue(cpu()); +} + + +/** + * \brief Activate a newly created thread. + * + * This function sets a new thread onto the ready list and switches to + * the thread if it can preempt the currently running thread. + */ +PUBLIC +bool +Context::activate() +{ + Lock_guard guard(&cpu_lock); + if (cpu() == current_cpu()) + { + state_add_dirty(Thread_ready); + if (sched()->deblock(cpu(), current()->sched(), true)) + { + current()->switch_to_locked(this); + return true; + } + } + else + remote_ready_enqueue(); + + return false; +} + +/** + * Remove context from ready-list. + */ +PUBLIC inline NEEDS ["cpu_lock.h", "lock_guard.h", "std_macros.h"] +void +Context::ready_dequeue() +{ + assert_kdb(current_cpu() == cpu()); + sched()->ready_dequeue(); +} + + +/** Helper. Context that helps us by donating its time to us. It is + set by switch_exec() if the calling thread says so. + @return context that helps us and should be activated after freeing a lock. +*/ +PUBLIC inline +Context * +Context::helper() const +{ + return _helper; +} + + +PUBLIC inline +void +Context::set_helper(Helping_mode const mode) +{ + switch (mode) + { + case Helping: + _helper = current(); + break; + case Not_Helping: + _helper = this; + break; + case Ignore_Helping: + // don't change _helper value + break; + } +} + +/** Donatee. Context that receives our time slices, for example + because it has locked us. + @return context that should be activated instead of us when we're + switch_exec()'ed. +*/ +PUBLIC inline +Context * +Context::donatee() const +{ + return _donatee; +} + +PUBLIC inline +void +Context::set_donatee(Context * const donatee) +{ + _donatee = donatee; +} + +PUBLIC inline +Mword * +Context::get_kernel_sp() const +{ + return _kernel_sp; +} + +PUBLIC inline +void +Context::set_kernel_sp(Mword * const esp) +{ + _kernel_sp = esp; +} + +PUBLIC inline +Fpu_state * +Context::fpu_state() +{ + return &_fpu_state; +} + +/** + * Add to consumed CPU time. + * @param quantum Implementation-specific time quantum (TSC ticks or usecs) + */ +PUBLIC inline +void +Context::consume_time(Clock::Time quantum) +{ + _consumed_time += quantum; +} + +/** + * Update consumed CPU time during each context switch and when + * reading out the current thread's consumed CPU time. + */ +IMPLEMENT inline NEEDS ["cpu.h"] +void +Context::update_consumed_time() +{ + if (Config::Fine_grained_cputime) + consume_time (_clock.cpu(cpu()).delta()); +} + +IMPLEMENT inline NEEDS ["config.h", "cpu.h"] +Cpu_time +Context::consumed_time() +{ + if (Config::Fine_grained_cputime) + return _clock.cpu(cpu()).us(_consumed_time); + + return _consumed_time; +} + +/** + * Switch to scheduling context and execution context while not running under + * CPU lock. + */ +PUBLIC inline NEEDS [] +void +Context::switch_to(Context *t) +{ + // Call switch_to_locked if CPU lock is already held + assert (!cpu_lock.test()); + + // Grab the CPU lock + Lock_guard guard(&cpu_lock); + + switch_to_locked(t); +} + +/** + * Switch scheduling context and execution context. + * @param t Destination thread whose scheduling context and execution context + * should be activated. + */ +PRIVATE inline NEEDS ["kdb_ke.h"] +bool FIASCO_WARN_RESULT +Context::schedule_switch_to_locked(Context *t) +{ + // Must be called with CPU lock held + assert_kdb (cpu_lock.test()); + + // Switch to destination thread's scheduling context + if (current_sched() != t->sched()) + set_current_sched(t->sched()); + + // XXX: IPC dependency tracking belongs here. + + // Switch to destination thread's execution context, no helping involved + if (t != this) + return switch_exec_locked(t, Not_Helping); + + return handle_drq(); +} + +PUBLIC inline NEEDS [Context::schedule_switch_to_locked] +void +Context::switch_to_locked(Context *t) +{ + if (EXPECT_FALSE(schedule_switch_to_locked(t))) + schedule(); +} + + +/** + * Switch execution context while not running under CPU lock. + */ +PUBLIC inline NEEDS ["kdb_ke.h"] +bool FIASCO_WARN_RESULT +Context::switch_exec(Context *t, enum Helping_mode mode) +{ + // Call switch_exec_locked if CPU lock is already held + assert_kdb (!cpu_lock.test()); + + // Grab the CPU lock + Lock_guard guard(&cpu_lock); + + return switch_exec_locked(t, mode); +} + + +PRIVATE inline +Context * +Context::handle_helping(Context *t) +{ + // XXX: maybe we do not need this on MP, because we have no helping there + assert_kdb (current() == this); + // Time-slice lending: if t is locked, switch to its locker + // instead, this is transitive + while (t->donatee() && // target thread locked + t->donatee() != t) // not by itself + { + // Special case for Thread::kill(): If the locker is + // current(), switch to the locked thread to allow it to + // release other locks. Do this only when the target thread + // actually owns locks. + if (t->donatee() == this) + { + if (t->lock_cnt() > 0) + break; + + return this; + } + + t = t->donatee(); + } + return t; +} + + +/** + * Switch to a specific different execution context. + * If that context is currently locked, switch to its locker instead + * (except if current() is the locker) + * @pre current() == this && current() != t + * @param t thread that shall be activated. + * @param mode helping mode; we either help, don't help or leave the + * helping state unchanged + */ +PUBLIC +bool FIASCO_WARN_RESULT //L4_IPC_CODE +Context::switch_exec_locked(Context *t, enum Helping_mode mode) +{ + // Must be called with CPU lock held + assert_kdb (cpu_lock.test()); + assert_kdb (current() != t); + assert_kdb (current() == this); + assert_kdb (timeslice_timeout.cpu(cpu())->is_set()); // Coma check + + // only for logging + Context *t_orig = t; + (void)t_orig; + + // Time-slice lending: if t is locked, switch to its locker + // instead, this is transitive + t = handle_helping(t); + + if (t == this) + return handle_drq(); + + LOG_CONTEXT_SWITCH; + CNT_CONTEXT_SWITCH; + + // Can only switch to ready threads! + if (EXPECT_FALSE (!(t->state() & Thread_ready_mask))) + { + assert_kdb (state() & Thread_ready_mask); + return false; + } + + + // Ensure kernel stack pointer is non-null if thread is ready + assert_kdb (t->_kernel_sp); + + t->set_helper(mode); + + update_ready_list(); + assert_kdb (!(state() & Thread_ready_mask) || !sched()->left() + || in_ready_list()); + + switch_fpu(t); + switch_cpu(t); + + return handle_drq(); +} + +PUBLIC inline NEEDS[Context::switch_exec_locked, Context::schedule] +void +Context::switch_exec_schedule_locked(Context *t, enum Helping_mode mode) +{ + if (EXPECT_FALSE(switch_exec_locked(t, mode))) + schedule(); +} + +PUBLIC inline +Context::Ku_mem_ptr const & +Context::utcb() const +{ return _utcb; } + +IMPLEMENT inline NEEDS["globals.h"] +Context * +Context::Context_member::context() const +{ return context_of(this); } + +IMPLEMENT inline NEEDS["lock_guard.h", "kdb_ke.h"] +void +Context::Drq_q::enq(Drq *rq) +{ + assert_kdb(cpu_lock.test()); + Lock_guard guard(q_lock()); + enqueue(rq); +} + +PRIVATE inline +bool +Context::do_drq_reply(Drq *r, Drq_q::Drop_mode drop) +{ + state_change_dirty(~Thread_drq_wait, Thread_ready); + // r->state = Drq::Reply_handled; + if (drop == Drq_q::No_drop && r->reply) + return r->reply(r, this, r->arg) & Drq::Need_resched; + + return false; +} + +IMPLEMENT inline NEEDS[Context::do_drq_reply] +bool +Context::Drq_q::execute_request(Drq *r, Drop_mode drop, bool local) +{ + bool need_resched = false; + Context *const self = context(); + // printf("CPU[%2u:%p]: context=%p: handle request for %p (func=%p, arg=%p)\n", current_cpu(), current(), context(), r->context(), r->func, r->arg); + if (r->context() == self) + { + LOG_TRACE("DRQ handling", "drq", current(), __context_drq_log_fmt, + Drq_log *l = tbe->payload(); + l->type = "reply"; + l->func = (void*)r->func; + l->reply = (void*)r->reply; + l->thread = r->context(); + l->target_cpu = current_cpu(); + l->wait = 0; + ); + //LOG_MSG_3VAL(current(), "hrP", current_cpu() | (drop ? 0x100: 0), (Mword)r->context(), (Mword)r->func); + return self->do_drq_reply(r, drop); + } + else + { + LOG_TRACE("DRQ handling", "drq", current(), __context_drq_log_fmt, + Drq_log *l = tbe->payload(); + l->type = "request"; + l->func = (void*)r->func; + l->reply = (void*)r->reply; + l->thread = r->context(); + l->target_cpu = current_cpu(); + l->wait = 0; + ); + // r->state = Drq::Idle; + unsigned answer = 0; + //LOG_MSG_3VAL(current(), "hrq", current_cpu() | (drop ? 0x100: 0), (Mword)r->context(), (Mword)r->func); + if (EXPECT_TRUE(drop == No_drop && r->func)) + answer = r->func(r, self, r->arg); + else if (EXPECT_FALSE(drop == Drop)) + // flag DRQ abort for requester + r->arg = (void*)-1; + // LOG_MSG_3VAL(current(), "hrq-", answer, current()->state() /*(Mword)r->context()*/, (Mword)r->func); + need_resched |= answer & Drq::Need_resched; + //r->state = Drq::Handled; + + // enqueue answer + if (!(answer & Drq::No_answer)) + { + if (local) + return r->context()->do_drq_reply(r, drop) || need_resched; + else + need_resched |= r->context()->enqueue_drq(r, Drq::Target_ctxt); + } + } + return need_resched; +} + +IMPLEMENT inline NEEDS["mem.h", "lock_guard.h"] +bool +Context::Drq_q::handle_requests(Drop_mode drop) +{ + // printf("CPU[%2u:%p]: > Context::Drq_q::handle_requests() context=%p\n", current_cpu(), current(), context()); + bool need_resched = false; + while (1) + { + Queue_item *qi; + { + Lock_guard guard(q_lock()); + qi = first(); + if (!qi) + return need_resched; + + check_kdb (dequeue(qi, Queue_item::Ok)); + } + + Drq *r = static_cast(qi); + // printf("CPU[%2u:%p]: context=%p: handle request for %p (func=%p, arg=%p)\n", current_cpu(), current(), context(), r->context(), r->func, r->arg); + need_resched |= execute_request(r, drop, false); + } +} +/** + * \biref Forced dequeue from lock wait queue, or DRQ queue. + */ +PRIVATE +void +Context::force_dequeue() +{ + Queue_item *const qi = queue_item(); + + if (qi->queued()) + { + // we're waiting for a lock or have a DRQ pending + Queue *const q = qi->queue(); + { + Lock_guard guard(q->q_lock()); + // check again, with the queue lock held. + // NOTE: we may be already removed from the queue on another CPU + if (qi->queued() && qi->queue()) + { + // we must never be taken from one queue to another on a + // different CPU + assert_kdb(q == qi->queue()); + // pull myself out of the queue, mark reason as invalidation + q->dequeue(qi, Queue_item::Invalid); + } + } + } +} + +/** + * \brief Dequeue from lock and DRQ queues, abort pending DRQs + */ +PROTECTED +void +Context::shutdown_queues() +{ + force_dequeue(); + shutdown_drqs(); +} + + +/** + * \brief Check for pending DRQs. + * \return true if there are DRQs pending, false if not. + */ +PUBLIC inline +bool +Context::drq_pending() const +{ return _drq_q.first(); } + +PUBLIC inline +void +Context::try_finish_migration() +{ + if (EXPECT_FALSE(_migration_rq.in_progress)) + { + _migration_rq.in_progress = false; + finish_migration(); + } +} + + +/** + * \brief Handle all pending DRQs. + * \pre cpu_lock.test() (The CPU lock must be held). + * \pre current() == this (only the currently running context is allowed to + * call this function). + * \return true if re-scheduling is needed (ready queue has changed), + * false if not. + */ +PUBLIC //inline +bool +Context::handle_drq() +{ + assert_kdb (current_cpu() == this->cpu()); + assert_kdb (cpu_lock.test()); + + try_finish_migration(); + + if (EXPECT_TRUE(!drq_pending())) + return false; + + Mem::barrier(); + bool ret = false; + while (true) + { + ret |= _drq_q.handle_requests(); + + Lock_guard guard(_drq_q.q_lock()); + if (EXPECT_TRUE(!drq_pending())) + { + state_del_dirty(Thread_drq_ready); + break; + } + } + + //LOG_MSG_3VAL(this, "xdrq", state(), ret, cpu_lock.test()); + + /* + * When the context is marked as dead (Thread_dead) then we must not execute + * any usual context code, however DRQ handlers may run. + */ + if (state() & Thread_dead) + { + // so disable the context after handling all DRQs and flag a reschedule. + state_del_dirty(Thread_ready_mask); + return true; + } + + return ret || !(state() & Thread_ready_mask); +} + + +/** + * \brief Get the queue item of the context. + * \pre The context must currently not be in any queue. + * \return The queue item of the context. + * + * The queue item can be used to enqueue the context to a Queue. + * a context must be in at most one queue at a time. + * To figure out the context corresponding to a queue item + * context_of() can be used. + */ +PUBLIC inline NEEDS["kdb_ke.h"] +Queue_item * +Context::queue_item() +{ + return &_drq; +} + +/** + * \brief DRQ handler for state_change. + * + * This function basically wraps Context::state_change(). + */ +PRIVATE static +unsigned +Context::handle_drq_state_change(Drq * /*src*/, Context *self, void * _rq) +{ + State_request *rq = reinterpret_cast(_rq); + self->state_change_dirty(rq->del, rq->add); + //LOG_MSG_3VAL(c, "dsta", c->state(), (Mword)src, (Mword)_rq); + return false; +} + + +/** + * \brief Queue a DRQ for changing the contexts state. + * \param mask bit mask for the state (state &= mask). + * \param add bits to add to the state (state |= add). + * \note This function is a preemption point. + * + * This function must be used to change the state of contexts that are + * potentially running on a different CPU. + */ +PUBLIC inline NEEDS[Context::drq] +void +Context::drq_state_change(Mword mask, Mword add) +{ + if (current() == this) + { + state_change_dirty(mask, add); + return; + } + + State_request rq; + rq.del = mask; + rq.add = add; + drq(handle_drq_state_change, &rq); +} + + +/** + * \brief Initiate a DRQ for the context. + * \pre \a src must be the currently running context. + * \param src the source of the DRQ (the context who initiates the DRQ). + * \param func the DRQ handler. + * \param arg the argument for the DRQ handler. + * \param reply the reply handler (called in the context of \a src immediately + * after receiving a successful reply). + * + * DRQs are requests than any context can queue to any other context. DRQs are + * the basic mechanism to initiate actions on remote CPUs in an MP system, + * however, are also allowed locally. + * DRQ handlers of pending DRQs are executed by Context::handle_drq() in the + * context of the target context. Context::handle_drq() is basically called + * after switching to a context in Context::switch_exec_locked(). + * + * This function enqueues a DRQ and blocks the current context for a reply DRQ. + */ +PUBLIC inline NEEDS[Context::enqueue_drq] +void +Context::drq(Drq *drq, Drq::Request_func *func, void *arg, + Drq::Request_func *reply = 0, + Drq::Exec_mode exec = Drq::Target_ctxt, + Drq::Wait_mode wait = Drq::Wait) +{ + // printf("CPU[%2u:%p]: > Context::drq(this=%p, src=%p, func=%p, arg=%p)\n", current_cpu(), current(), this, src, func,arg); + Context *cur = current(); + LOG_TRACE("DRQ Stuff", "drq", cur, __context_drq_log_fmt, + Drq_log *l = tbe->payload(); + l->type = "send"; + l->func = (void*)func; + l->reply = (void*)reply; + l->thread = this; + l->target_cpu = cpu(); + l->wait = wait; + ); + //assert_kdb (current() == src); + assert_kdb (!(wait == Drq::Wait && (cur->state() & Thread_drq_ready)) || cur->cpu() == cpu()); + assert_kdb (!((wait == Drq::Wait || drq == &_drq) && cur->state() & Thread_drq_wait)); + assert_kdb (!drq->queued()); + + drq->func = func; + drq->reply = reply; + drq->arg = arg; + cur->state_add(wait == Drq::Wait ? Thread_drq_wait : 0); + + + enqueue_drq(drq, exec); + + //LOG_MSG_3VAL(src, "state(), Mword(this), 0); + while (wait == Drq::Wait && cur->state() & Thread_drq_wait) + { + cur->state_del(Thread_ready_mask); + cur->schedule(); + } + + LOG_TRACE("DRQ Stuff", "drq", cur, __context_drq_log_fmt, + Drq_log *l = tbe->payload(); + l->type = "done"; + l->func = (void*)func; + l->reply = (void*)reply; + l->thread = this; + l->target_cpu = cpu(); + ); + //LOG_MSG_3VAL(src, "drq>", src->state(), Mword(this), 0); +} + +PROTECTED inline +void +Context::kernel_context_drq(Drq::Request_func *func, void *arg, + Drq::Request_func *reply = 0) +{ + char align_buffer[2*sizeof(Drq)]; + Drq *mdrq = (Drq*)((Address(align_buffer) + __alignof__(Drq) - 1) & ~(__alignof__(Drq)-1)); + + mdrq->func = func; + mdrq->arg = arg; + mdrq->reply = reply; + Context *kc = kernel_context(current_cpu()); + kc->_drq_q.enq(mdrq); + bool resched = schedule_switch_to_locked(kc); + (void)resched; +} + +PUBLIC inline NEEDS[Context::drq] +void +Context::drq(Drq::Request_func *func, void *arg, + Drq::Request_func *reply = 0, + Drq::Exec_mode exec = Drq::Target_ctxt, + Drq::Wait_mode wait = Drq::Wait) +{ return drq(¤t()->_drq, func, arg, reply, exec, wait); } + +PRIVATE static +bool +Context::rcu_unblock(Rcu_item *i) +{ + assert_kdb(cpu_lock.test()); + Context *const c = static_cast(i); + c->state_change_dirty(~Thread_waiting, Thread_ready); + c->sched()->deblock(c->cpu()); + return true; +} + +PUBLIC inline +void +Context::recover_jmp_buf(jmp_buf *b) +{ _recover_jmpbuf = b; } + +PUBLIC static +void +Context::xcpu_tlb_flush(...) +{ + // This should always be optimized away + assert(0); +} + +//---------------------------------------------------------------------------- +IMPLEMENTATION [!mp]: + +#include "warn.h" +#include "kdb_ke.h" + +PUBLIC inline +unsigned +Context::cpu(bool = false) const +{ return 0; } + +PUBLIC static inline +void +Context::enable_tlb(unsigned) +{} + +PUBLIC static inline +void +Context::disable_tlb(unsigned) +{} + + +PROTECTED +void +Context::remote_ready_enqueue() +{ + WARN("Context::remote_ready_enqueue(): in UP system !\n"); + kdb_ke("Fiasco BUG"); +} + +PUBLIC +bool +Context::enqueue_drq(Drq *rq, Drq::Exec_mode) +{ + bool sched = _drq_q.execute_request(rq, Drq_q::No_drop, true); + if (!in_ready_list() && (state() & Thread_ready_mask)) + { + ready_enqueue(); + return true; + } + + return sched; +} + + +PRIVATE inline NOEXPORT +void +Context::shutdown_drqs() +{ _drq_q.handle_requests(Drq_q::Drop); } + + +PUBLIC inline +void +Context::rcu_wait() +{ + // The UP case does not need to block for the next grace period, because + // the CPU is always in a quiescent state when the interrupts where enabled +} + +PUBLIC static inline +void +Context::xcpu_tlb_flush(bool, Mem_space *, Mem_space *) +{} + + + +//---------------------------------------------------------------------------- +INTERFACE [mp]: + +#include "queue.h" +#include "queue_item.h" + +EXTENSION class Context +{ +protected: + + class Pending_rqq : public Queue + { + public: + static void enq(Context *c); + bool handle_requests(Context **); + }; + + class Pending_rq : public Queue_item, public Context_member + {} _pending_rq; + +protected: + static Per_cpu _pending_rqq; + static Per_cpu _glbl_drq_q; + static Cpu_mask _tlb_active; + +}; + + + +//---------------------------------------------------------------------------- +IMPLEMENTATION [mp]: + +#include "globals.h" +#include "ipi.h" +#include "kdb_ke.h" +#include "lock_guard.h" +#include "mem.h" + +DEFINE_PER_CPU Per_cpu Context::_pending_rqq; +DEFINE_PER_CPU Per_cpu Context::_glbl_drq_q; +Cpu_mask Context::_tlb_active; + +PUBLIC static inline +void +Context::enable_tlb(unsigned cpu) +{ _tlb_active.atomic_set(cpu); } + +PUBLIC static inline +void +Context::disable_tlb(unsigned cpu) +{ _tlb_active.atomic_clear(cpu); } + +/** + * \brief Enqueue the given \a c into its CPUs queue. + * \param c the context to enqueue for DRQ handling. + */ +IMPLEMENT inline NEEDS["globals.h", "lock_guard.h", "kdb_ke.h"] +void +Context::Pending_rqq::enq(Context *c) +{ + // FIXME: is it safe to do the check without a locked queue, or may + // we loose DRQs then? + + //if (!c->_pending_rq.queued()) + { + Queue &q = Context::_pending_rqq.cpu(c->cpu()); + Lock_guard guard(q.q_lock()); + if (c->_pending_rq.queued()) + return; + q.enqueue(&c->_pending_rq); + } +} + + +/** + * \brief Wakeup all contexts with pending DRQs. + * + * This function wakes up all context from the pending queue. + */ +IMPLEMENT +bool +Context::Pending_rqq::handle_requests(Context **mq) +{ + //LOG_MSG_3VAL(current(), "phq", current_cpu(), 0, 0); + // printf("CPU[%2u:%p]: Context::Pending_rqq::handle_requests() this=%p\n", current_cpu(), current(), this); + bool resched = false; + Context *curr = current(); + while (1) + { + Queue_item *qi; + { + Lock_guard guard(q_lock()); + qi = first(); + if (!qi) + return resched; + check_kdb (dequeue(qi, Queue_item::Ok)); + } + Context *c = static_cast(qi)->context(); + //LOG_MSG_3VAL(c, "pick", c->state(), c->cpu(), current_cpu()); + // Drop migrated threads + assert_kdb (EXPECT_FALSE(c->cpu() == current_cpu())); + + if (EXPECT_TRUE(c->drq_pending())) + c->state_add(Thread_drq_ready); + + if (EXPECT_FALSE(c->_migration_rq.pending)) + { + if (c != curr) + { + c->initiate_migration(); + continue; + } + else + { + *mq = c; + resched = true; + } + } + else + c->try_finish_migration(); + + if (EXPECT_TRUE((c->state() & Thread_ready_mask))) + { + //printf("CPU[%2u:%p]: Context::Pending_rqq::handle_requests() dequeded %p(%u)\n", current_cpu(), current(), c, qi->queued()); + resched |= c->sched()->deblock(current_cpu(), current()->sched(), false); + } + } +} + +PUBLIC +void +Context::global_drq(unsigned cpu, Drq::Request_func *func, void *arg, + Drq::Request_func *reply = 0, bool wait = true) +{ + assert_kdb (this == current()); + + _drq.func = func; + _drq.reply = reply; + _drq.arg = arg; + + state_add(wait ? Thread_drq_wait : 0); + + _glbl_drq_q.cpu(cpu).enq(&_drq); + + Ipi::send(Ipi::Global_request, this->cpu(), cpu); + + //LOG_MSG_3VAL(src, "state(), Mword(this), 0); + while (wait && (state() & Thread_drq_wait)) + { + state_del(Thread_ready_mask); + schedule(); + } +} + + +PUBLIC +static bool +Context::handle_global_requests() +{ + return _glbl_drq_q.cpu(current_cpu()).handle_requests(); +} + +PUBLIC +bool +Context::enqueue_drq(Drq *rq, Drq::Exec_mode /*exec*/) +{ + assert_kdb (cpu_lock.test()); + // printf("CPU[%2u:%p]: Context::enqueue_request(this=%p, src=%p, func=%p, arg=%p)\n", current_cpu(), current(), this, src, func,arg); + + if (cpu() != current_cpu()) + { + bool ipi = true; + _drq_q.enq(rq); + + // ready cpu again we may've been migrated meanwhile + unsigned cpu = this->cpu(); + + { + Queue &q = Context::_pending_rqq.cpu(cpu); + Lock_guard g(q.q_lock()); + + + // migrated between getting the lock and reading the CPU, so the + // new CPU is responsible for executing our request + if (this->cpu() != cpu) + return false; + + if (q.first()) + ipi = false; + + if (!_pending_rq.queued()) + q.enqueue(&_pending_rq); + } + + if (ipi) + { + //LOG_MSG_3VAL(this, "sipi", current_cpu(), cpu(), (Mword)current()); + Ipi::send(Ipi::Request, current_cpu(), cpu); + } + } + else + { // LOG_MSG_3VAL(this, "adrq", state(), (Mword)current(), (Mword)rq); + + bool sched = _drq_q.execute_request(rq, Drq_q::No_drop, true); + if (!in_ready_list() && (state() & Thread_ready_mask)) + { + ready_enqueue(); + return true; + } + + return sched; + } + return false; +} + + +PRIVATE inline NOEXPORT +void +Context::shutdown_drqs() +{ + if (_pending_rq.queued()) + { + Lock_guard guard(_pending_rq.queue()->q_lock()); + if (_pending_rq.queued()) + _pending_rq.queue()->dequeue(&_pending_rq, Queue_item::Ok); + } + + _drq_q.handle_requests(Drq_q::Drop); +} + + +PUBLIC inline +unsigned +Context::cpu(bool running = false) const +{ + (void)running; + return _cpu; +} + + +/** + * Remote helper for doing remote CPU ready enqueue. + * + * See remote_ready_enqueue(). + */ +PRIVATE static +unsigned +Context::handle_remote_ready_enqueue(Drq *, Context *self, void *) +{ + self->state_add_dirty(Thread_ready); + return 0; +} + + +PROTECTED inline NEEDS[Context::handle_remote_ready_enqueue] +void +Context::remote_ready_enqueue() +{ drq(&handle_remote_ready_enqueue, 0); } + + + +/** + * Block and wait for the next grace period. + */ +PUBLIC inline NEEDS["cpu_lock.h", "lock_guard.h"] +void +Context::rcu_wait() +{ + Lock_guard gurad(&cpu_lock); + state_change_dirty(~Thread_ready, Thread_waiting); + Rcu::call(this, &rcu_unblock); + schedule(); +} + + + +PRIVATE static +unsigned +Context::handle_remote_tlb_flush(Drq *, Context *, void *_s) +{ + Mem_space **s = (Mem_space **)_s; + Mem_space::tlb_flush_spaces((bool)s[0], s[1], s[2]); + return 0; +} + + +PUBLIC static +void +Context::xcpu_tlb_flush(bool flush_all_spaces, Mem_space *s1, Mem_space *s2) +{ + Lock_guard g(&cpu_lock); + Mem_space *s[3] = { (Mem_space *)flush_all_spaces, s1, s2 }; + unsigned ccpu = current_cpu(); + for (unsigned i = 0; i < Config::Max_num_cpus; ++i) + if (ccpu != i && _tlb_active.get(i)) + current()->global_drq(i, Context::handle_remote_tlb_flush, s); +} + + +//---------------------------------------------------------------------------- +IMPLEMENTATION [fpu && !ux]: + +#include "fpu.h" + +/** + * When switching away from the FPU owner, disable the FPU to cause + * the next FPU access to trap. + * When switching back to the FPU owner, enable the FPU so we don't + * get an FPU trap on FPU access. + */ +IMPLEMENT inline NEEDS ["fpu.h"] +void +Context::switch_fpu(Context *t) +{ + if (Fpu::is_owner(cpu(), this)) + Fpu::disable(); + else if (Fpu::is_owner(cpu(), t) && !(t->state() & Thread_vcpu_fpu_disabled)) + Fpu::enable(); +} + +//---------------------------------------------------------------------------- +IMPLEMENTATION [!fpu]: + +IMPLEMENT inline +void +Context::switch_fpu(Context *) +{} + +// -------------------------------------------------------------------------- +IMPLEMENTATION [debug]: + +#include "kobject_dbg.h" + +IMPLEMENT +unsigned +Context::drq_log_fmt(Tb_entry *e, int maxlen, char *buf) +{ + Drq_log *l = e->payload(); + return snprintf(buf, maxlen, "drq %s(%s) to ctxt=%lx/%p (func=%p, reply=%p) cpu=%u", + l->type, l->wait ? "wait" : "no-wait", Kobject_dbg::pointer_to_id(l->thread), + l->thread, l->func, l->reply, l->target_cpu); +} + diff --git a/kernel/fiasco/src/kern/context_base.cpp b/kernel/fiasco/src/kern/context_base.cpp new file mode 100644 index 00000000..aeb5f4e1 --- /dev/null +++ b/kernel/fiasco/src/kern/context_base.cpp @@ -0,0 +1,89 @@ +INTERFACE: + +#include "types.h" +#include "config_tcbsize.h" + +class Context; + +class Context_base +{ +public: + enum + { + Size = THREAD_BLOCK_SIZE + }; + + // This virtual dtor enforces that Context / Thread / Context_base + // all start at offset 0 + virtual ~Context_base() = 0; + +protected: + Mword _state; +}; + +//--------------------------------------------------------------------------- +INTERFACE [mp]: + +EXTENSION class Context_base +{ +protected: + friend unsigned &__cpu_of(const void *); + unsigned _cpu; +}; + +//--------------------------------------------------------------------------- +IMPLEMENTATION [!mp]: + +inline +void set_cpu_of(const void *ptr, unsigned cpu) +{ (void)ptr; (void)cpu; } + +inline +unsigned cpu_of(const void *) +{ return 0; } + +inline +unsigned current_cpu() +{ return 0; } + +//--------------------------------------------------------------------------- +IMPLEMENTATION: + +#include "config.h" +#include "processor.h" + +IMPLEMENT inline Context_base::~Context_base() {} + +inline NEEDS ["config.h"] +Context *context_of(const void *ptr) +{ + return reinterpret_cast + (reinterpret_cast(ptr) & ~(Context_base::Size - 1)); +} + +inline NEEDS [context_of, "processor.h"] +Context *current() +{ return context_of((void *)Proc::stack_pointer()); } + +//--------------------------------------------------------------------------- +IMPLEMENTATION [mp]: + +#include "config.h" + +inline NEEDS ["config.h"] +unsigned &__cpu_of(const void *ptr) +{ return reinterpret_cast(context_of(ptr))->_cpu; } + +inline NEEDS [__cpu_of] +void set_cpu_of(const void *ptr, unsigned cpu) +{ __cpu_of(ptr) = cpu; } + + +inline NEEDS [__cpu_of] +unsigned cpu_of(const void *ptr) +{ return __cpu_of(ptr); } + +inline NEEDS [current, cpu_of] +unsigned current_cpu() +{ return cpu_of(current()); } + diff --git a/kernel/fiasco/src/kern/cpu.cpp b/kernel/fiasco/src/kern/cpu.cpp new file mode 100644 index 00000000..af9cd981 --- /dev/null +++ b/kernel/fiasco/src/kern/cpu.cpp @@ -0,0 +1,144 @@ +INTERFACE: + +#include "cpu_mask.h" +#include "member_offs.h" + +class Cpu +{ + MEMBER_OFFSET(); + +public: + /** Get the locical ID of this CPU */ + unsigned id() const; + + + /** + * Set this CPU to online state. + * NOTE: This does not activate an inactive CPU, Just set the given state. + */ + void set_online(bool o); + + /** Get the physical ID of the CPU, for inter processor communication */ + unsigned phys_id() const; + + /** Convienience for Cpu::cpus.cpu(cpu).online() */ + static bool online(unsigned cpu); + + /** + * Get logical CPU id from physical ID + * NOTE: This call is SLOW, use only for debugging/bootup + */ + static unsigned p2l(unsigned phys_id); + + static Cpu_mask const &online_mask(); + + +private: + /** Is this CPU online ? */ + bool online() const; + + static Cpu_mask _online_mask; +}; + + +//-------------------------------------------------------------------------- +INTERFACE[mp]: + +EXTENSION class Cpu +{ + +private: + void set_id(unsigned id) { _id = id; } + unsigned _id; +}; + +//-------------------------------------------------------------------------- +INTERFACE[!mp]: + +EXTENSION class Cpu +{ +private: + void set_id(unsigned) {} +}; + + +// -------------------------------------------------------------------------- +IMPLEMENTATION: + +Cpu_mask Cpu::_online_mask(Cpu_mask::Init::Bss); + +IMPLEMENT inline +Cpu_mask const & +Cpu::online_mask() +{ return _online_mask; } + +// -------------------------------------------------------------------------- +IMPLEMENTATION [mp]: + +#include "kdb_ke.h" + +IMPLEMENT inline +unsigned +Cpu::id() const +{ return _id; } + +IMPLEMENT inline +bool +Cpu::online() const +{ return _online_mask.get(_id); } + +IMPLEMENT inline +void +Cpu::set_online(bool o) +{ + if (o) + _online_mask.set(_id); + else + _online_mask.clear(_id); +} + +IMPLEMENT +unsigned +Cpu::p2l(unsigned phys_id) +{ + for (unsigned i = 0; i < Config::Max_num_cpus; ++i) + if (Per_cpu_data::valid(i) && Cpu::cpus.cpu(i).phys_id() == phys_id) + return i; + + return ~0U; +} + +IMPLEMENT static inline NEEDS["kdb_ke.h"] +bool +Cpu::online(unsigned _cpu) +{ return _online_mask.get(_cpu); } + + +// -------------------------------------------------------------------------- +IMPLEMENTATION [!mp]: + +IMPLEMENT inline +unsigned +Cpu::id() const +{ return 0; } + +IMPLEMENT inline +bool +Cpu::online() const +{ return true; } + +IMPLEMENT inline +void +Cpu::set_online(bool) +{} + +IMPLEMENT +unsigned +Cpu::p2l(unsigned) +{ return 0; } + +IMPLEMENT static inline +bool +Cpu::online(unsigned _cpu) +{ return _cpu == 0; } + diff --git a/kernel/fiasco/src/kern/cpu_lock-generic.cpp b/kernel/fiasco/src/kern/cpu_lock-generic.cpp new file mode 100644 index 00000000..5384f92c --- /dev/null +++ b/kernel/fiasco/src/kern/cpu_lock-generic.cpp @@ -0,0 +1,32 @@ +IMPLEMENTATION: +/** + * Generic implementation of the CPU lock. + * This implementation uses Proc::cli and + * Proc::sti from the processor headers. + * + */ + +#include "processor.h" + +IMPLEMENT inline +Cpu_lock::Cpu_lock() +{} + +IMPLEMENT inline NEEDS ["processor.h"] +void Cpu_lock::lock() +{ + Proc::cli(); +} + +IMPLEMENT inline NEEDS ["processor.h"] +void +Cpu_lock::clear() +{ + Proc::sti(); +} + +IMPLEMENT inline NEEDS ["processor.h"] +Cpu_lock::Status Cpu_lock::test() const +{ + return ! Proc::interrupts(); +} diff --git a/kernel/fiasco/src/kern/cpu_lock.cpp b/kernel/fiasco/src/kern/cpu_lock.cpp new file mode 100644 index 00000000..7c691c60 --- /dev/null +++ b/kernel/fiasco/src/kern/cpu_lock.cpp @@ -0,0 +1,94 @@ +INTERFACE: + +#include "types.h" + +/** + * Global CPU lock. When held, irqs are disabled on the current CPU + * (preventing nested irq handling, and preventing the current + * thread from being preempted). It must only be held for very short + * amounts of time. + * + * A generic (cli, sti) implementation of the lock can be found in + * cpu_lock-generic.cpp. + */ +class Cpu_lock +{ +public: + /// The return type of test methods + typedef Mword Status; + + enum { Locked = 1, Not_locked = 0 }; + + /// ctor. + inline Cpu_lock(); + + /** + * Test if the lock is already held. + * @return 0 if the lock is not held, not 0 if it already is held. + */ + Status test() const; + + /** + * Acquire the CPU lock. + * The CPU lock disables IRQ's it should be held only for a very + * short amount of time. + */ + void lock(); + + /** + * Release the CPU lock. + */ + void clear(); + + /** + * Acquire the CPU lock and return the old status. + * @return something else that 0 if the lock was already held and + * 0 if it was not held. + */ + Status test_and_set(); + + /** + * Set the CPU lock according to the given status. + * @param state the state to set (0 clear, else lock). + */ + void set(Status state); + +private: + /// Default copy constructor not implemented. + Cpu_lock (const Cpu_lock&); + +}; + +/** + * The global CPU lock, contains the locking data necessary for some + * special implementations. + */ +extern Cpu_lock cpu_lock; + +IMPLEMENTATION: + +#include "static_init.h" + +Cpu_lock cpu_lock INIT_PRIORITY(EARLY_INIT_PRIO); + + +IMPLEMENT inline //NEEDS [Cpu_lock::lock, Cpu_lock::test] +Cpu_lock::Status Cpu_lock::test_and_set() +{ + Status ret = test(); + lock(); + return ret; +} + + + +IMPLEMENT inline //NEEDS [Cpu_lock::lock, Cpu_lock::clear] +void Cpu_lock::set(Cpu_lock::Status state) +{ + if (state) + lock(); + else + clear(); +} + + diff --git a/kernel/fiasco/src/kern/cpu_mask.cpp b/kernel/fiasco/src/kern/cpu_mask.cpp new file mode 100644 index 00000000..e020d152 --- /dev/null +++ b/kernel/fiasco/src/kern/cpu_mask.cpp @@ -0,0 +1,24 @@ +INTERFACE: + +#include "bitmap.h" +#include "config.h" + +class Cpu_mask +{ +public: + enum class Init { Bss }; + Cpu_mask(Init) {} + Cpu_mask() { _b.clear_all(); } + + bool empty() const { return _b.is_empty(); } + bool get(unsigned cpu) const { return _b[cpu]; } + void clear(unsigned cpu) { return _b.clear_bit(cpu); } + void set(unsigned cpu) { _b.set_bit(cpu); }; + void atomic_set(unsigned cpu) {_b.atomic_set_bit(cpu); } + void atomic_clear(unsigned cpu) {_b.atomic_clear_bit(cpu); } + bool atomic_get_and_clear(unsigned cpu) + { return _b.atomic_get_and_clear(cpu); } + +private: + Bitmap _b; +}; diff --git a/kernel/fiasco/src/kern/dbg_page_info.cpp b/kernel/fiasco/src/kern/dbg_page_info.cpp new file mode 100644 index 00000000..eb907bee --- /dev/null +++ b/kernel/fiasco/src/kern/dbg_page_info.cpp @@ -0,0 +1,129 @@ +INTERFACE [debug]: + +#include "types.h" +#include "lock_guard.h" +#include "spin_lock.h" +#include "slab_cache.h" +#include + +class Dbg_page_info_table; + +class Dbg_page_info : public cxx::S_list_item +{ + friend class Dbg_page_info_table; + +private: + Page_number const _pfn; + typedef unsigned long Buf[5]; + Buf _buf; + + char *b() { return reinterpret_cast(_buf); } + char const *b() const { return reinterpret_cast(_buf); } + + typedef Slab_cache Allocator; + +public: + void *operator new (size_t) throw() { return alloc()->alloc(); } + void operator delete (void *p, size_t) { alloc()->free(p); } + + enum { Buffer_size = sizeof(Buf) }; + + Dbg_page_info(Page_number pfn) : _pfn(pfn) {} + + bool match(Page_number p) { return _pfn == p; } + + template + T *info() + { return reinterpret_cast(b()); } + + template + T const *info() const + { return reinterpret_cast(b()); } +}; + +class Dbg_page_info_table +{ +private: + typedef cxx::S_list_bss List; + +public: + struct Entry + { + List h; + Spin_lock<> l; + }; + enum { Hash_tab_size = 1024 }; + +private: + Entry _tab[Hash_tab_size]; + static unsigned hash(Page_number p) { return p.value() % Hash_tab_size; } +}; + + + +IMPLEMENTATION [debug]: + +#include "kmem_slab.h" + + +static Dbg_page_info_table _t; + +PUBLIC static +Dbg_page_info_table & +Dbg_page_info::table() +{ + return _t; +} + +static Kmem_slab_t _dbg_page_info_allocator("Dbg_page_info"); + +PRIVATE static +Dbg_page_info::Allocator * +Dbg_page_info::alloc() +{ return &_dbg_page_info_allocator; } + + +PUBLIC template static inline +B +Dbg_page_info_table::find(B const &b, E const &e, Page_number p) +{ + for (B i = b; i != e; ++i) + if (i->match(p)) + return i; + return e; +} + +PUBLIC +Dbg_page_info * +Dbg_page_info_table::operator [] (Page_number pfn) const +{ + Entry &e = const_cast(this)->_tab[hash(pfn)]; + Lock_guard g(&e.l); + // we know that *end() is NULL + return *find(e.h.begin(), e.h.end(), pfn); +} + +PUBLIC +void +Dbg_page_info_table::insert(Dbg_page_info *i) +{ + Entry *e = &_tab[hash(i->_pfn)]; + Lock_guardl)> g(&e->l); + e->h.add(i); +} + +PUBLIC +Dbg_page_info * +Dbg_page_info_table::remove(Page_number pfn) +{ + Entry *e = &_tab[hash(pfn)]; + Lock_guardl)> g(&e->l); + + List::Iterator i = find(e->h.begin(), e->h.end(), pfn); + if (i == e->h.end()) + return 0; + + Dbg_page_info *r = *i; + e->h.erase(i); + return r; +} diff --git a/kernel/fiasco/src/kern/dump_tcboffsets.cc b/kernel/fiasco/src/kern/dump_tcboffsets.cc new file mode 100644 index 00000000..bdcbaadd --- /dev/null +++ b/kernel/fiasco/src/kern/dump_tcboffsets.cc @@ -0,0 +1,59 @@ +#include +#include +#include +#include +#include +#include +#include "globalconfig.h" + +#ifndef CONFIG_BIG_ENDIAN +#define TARGET_BYTE_ORDER(a) a +#else +#define TARGET_BYTE_ORDER(a) len == 4 ? htonl(a) : a +#endif + +#define READ_VAL \ + ({read(fd, &val, len); TARGET_BYTE_ORDER(val);}) + + +#define DUMP_OFFSET(prefix,name,offset) \ + printf("#define OFS__" #prefix "__" #name " 0x%llx\n", READ_VAL); + +#define DUMP_BITSHIFT(prefix, value) \ + printf("#define SHIFT__" #prefix " 0x%llx\n", log2(READ_VAL)); + +#define DUMP_MEMBER1(prefix, type1, member1, name) \ + DUMP_OFFSET(prefix, name, READ_VAL) + +#define DUMP_CONSTANT(prefix, value) \ + printf("#define VAL__" #prefix " 0x%llx\n", READ_VAL); + +#define DUMP_CAST_OFFSET(type, subtype) \ + printf("#define CAST__" #type "_TO_" #subtype " 0x%llx\n", READ_VAL); + +/** + * Calculates the logarithm base 2 from the given 2^n integer. + * @param value the 2^n integer + * @return the log base 2 of value, the exponent n + */ +int log2(int value) +{ + unsigned c = 0; // c will be lg(v) + while (value >>= 1) + c++; + return c; +} + +int main(int /*argc*/, char **argv) +{ + /* Only little endian supported if build architecture is 32 bit and + * target architecture 64 bit! */ + unsigned long long val = 0; + int fd = open(argv[1], O_RDONLY); + char len = 1; + len = READ_VAL; + lseek(fd, 32, SEEK_SET); +#include "tcboffset_in.h" + close(fd); + return 0; +} diff --git a/kernel/fiasco/src/kern/entry_frame-abs-timeout-hack.cpp b/kernel/fiasco/src/kern/entry_frame-abs-timeout-hack.cpp new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/kernel/fiasco/src/kern/entry_frame-abs-timeout-hack.cpp @@ -0,0 +1 @@ + diff --git a/kernel/fiasco/src/kern/entry_frame.cpp b/kernel/fiasco/src/kern/entry_frame.cpp new file mode 100644 index 00000000..1630dfad --- /dev/null +++ b/kernel/fiasco/src/kern/entry_frame.cpp @@ -0,0 +1,53 @@ +INTERFACE: + +#include "l4_types.h" + +/** + * Encapsulation of syscall data. + * + * This class must be defined in arch dependent parts + * and has to represent the data necessary for a + * system call as layed out on the kernel stack. + */ +class Syscall_frame +{ +public: + + L4_obj_ref ref() const; + void ref(L4_obj_ref const &ref); + Utcb *utcb() const; + L4_msg_tag tag() const; + void tag(L4_msg_tag const &tag); + + L4_timeout_pair timeout() const; + void timeout(L4_timeout_pair const &to); + + Mword from_spec() const; + void from(Mword id); + + Mword next_period() const; +}; + + +class Return_frame +{ +public: + Mword ip() const; + Mword ip_syscall_page_user() const; + void ip(Mword _pc); + + Mword sp() const; + void sp(Mword _sp); +}; + +/** + * Encapsulation of a syscall entry kernel stack. + * + * This class encapsulates the complete top of the + * kernel stack after a syscall (including the + * iret return frame). + */ +class Entry_frame : public Syscall_frame, public Return_frame +{}; + + diff --git a/kernel/fiasco/src/kern/factory.cpp b/kernel/fiasco/src/kern/factory.cpp new file mode 100644 index 00000000..4261cae7 --- /dev/null +++ b/kernel/fiasco/src/kern/factory.cpp @@ -0,0 +1,347 @@ +INTERFACE: + +#include "fiasco_defs.h" +#include "ram_quota.h" +#include "slab_cache.h" +#include "kobject_helper.h" + +class Factory : public Ram_quota, public Kobject_h +{ + FIASCO_DECLARE_KOBJ(); + +private: + typedef Slab_cache Self_alloc; +}; + +//--------------------------------------------------------------------------- +IMPLEMENTATION: + +#include "ipc_gate.h" +#include "kmem_slab.h" +#include "task.h" +#include "thread_object.h" +#include "static_init.h" +#include "l4_buf_iter.h" +#include "l4_types.h" +#include "irq.h" +#include "map_util.h" +#include "logdefs.h" +#include "entry_frame.h" + +static Factory _root_factory INIT_PRIORITY(ROOT_FACTORY_INIT_PRIO); +FIASCO_DEFINE_KOBJ(Factory); + +PUBLIC inline +Factory::Factory() + : Ram_quota() +{} + +PRIVATE inline +Factory::Factory(Ram_quota *q, unsigned long max) + : Ram_quota(q, max) +{} + + +static Kmem_slab_t _factory_allocator("Factory"); + +PRIVATE static +Factory::Self_alloc * +Factory::allocator() +{ return &_factory_allocator; } + +PUBLIC static inline +Factory * FIASCO_PURE +Factory::root() +{ return nonull_static_cast(Ram_quota::root); } + + +PRIVATE +Factory * +Factory::create_factory(unsigned long max) +{ + Auto_quota q(this, sizeof(Factory) + max); + if (EXPECT_FALSE(!q)) + return 0; + + void *nq = allocator()->alloc(); + if (EXPECT_FALSE(!nq)) + return 0; + + q.release(); + return new (nq) Factory(this, max); +} + +PUBLIC +void Factory::operator delete (void *_f) +{ + Factory *f = (Factory*)_f; + LOG_TRACE("Factory delete", "fa del", ::current(), 0, {}); + + if (!f->parent()) + return; + + Ram_quota *p = f->parent(); + + allocator()->free(f); + if (p) + p->free(sizeof(Factory) + f->limit()); +} + +PRIVATE +L4_msg_tag +Factory::map_obj(Kobject_iface *o, Mword cap, Space *c_space, + Obj_space *o_space) +{ + Reap_list rl; + + if (!map(o, o_space, c_space, cap, rl.list())) + { + delete o; + return commit_result(-L4_err::ENomem); + } + + // return a tag with one typed item for the returned capability + return commit_result(0, 0, 1); +} + + + +PRIVATE inline NOEXPORT +Kobject_iface * +Factory::new_factory(Utcb const *u, int *) +{ + // XXX: should check for type tag in new call + return create_factory(u->values[2]); +} + + +PRIVATE inline NOEXPORT +Kobject_iface * +Factory::new_task(Utcb const *u, int *) +{ + L4_fpage utcb_area(0); + // XXX: should check for type tag in new call + utcb_area = L4_fpage(u->values[2]); + + if (Task *new_t = Task::create(this, utcb_area)) + return new_t; + + return 0; +} + +PRIVATE inline NOEXPORT +Kobject_iface * +Factory::new_thread(Utcb const *, int *) +{ return new (this) Thread_object(); } + +PRIVATE inline NOEXPORT +Kobject_iface * +Factory::new_gate(L4_msg_tag const &tag, Utcb const *utcb, Obj_space *o_space, + int *err) +{ + L4_snd_item_iter snd_items(utcb, tag.words()); + Thread *thread = 0; + + if (tag.items() && snd_items.next()) + { + L4_fpage bind_thread(snd_items.get()->d); + *err = L4_err::EInval; + if (EXPECT_FALSE(!bind_thread.is_objpage())) + return 0; + + unsigned char thread_rights = 0; + thread = Kobject::dcast(o_space->lookup_local(bind_thread.obj_index(), &thread_rights)); + + *err = L4_err::EPerm; + if (EXPECT_FALSE(!(thread_rights & L4_fpage::W))) + return 0; + } +#if 0 + if (!thread) + return reinterpret_cast(-L4_err::EInval); +#endif + // should check type tag of varg + *err = L4_err::ENomem; + return static_cast(Ipc_gate::create(this, thread, utcb->values[2])); +} + +PRIVATE inline NOEXPORT +Kobject_iface * +Factory::new_irq(unsigned w, Utcb const *utcb, int *) +{ + if (w >= 3 && utcb->values[2]) + return Irq::allocate(this); + else + return Irq::allocate(this); +} + +PUBLIC +L4_msg_tag +Factory::kinvoke(L4_obj_ref ref, Mword rights, Syscall_frame *f, + Utcb const *utcb, Utcb *) +{ + register Context *const c_thread = ::current(); + register Task *const c_space = static_cast(c_thread->space()); + + if (EXPECT_FALSE(f->tag().proto() != L4_msg_tag::Label_factory)) + return commit_result(-L4_err::EBadproto); + + if (EXPECT_FALSE(!(rights & L4_fpage::W))) + return commit_result(-L4_err::EPerm); + + if (EXPECT_FALSE(!ref.have_recv())) + return commit_result(0); + + if (f->tag().words() < 1) + return commit_result(-L4_err::EInval); + + L4_fpage buffer(0); + + { + L4_buf_iter buf(utcb, utcb->buf_desc.obj()); + L4_buf_iter::Item const *const b = buf.get(); + if (EXPECT_FALSE(b->b.is_void() + || b->b.type() != L4_msg_item::Map)) + return commit_error(utcb, L4_error(L4_error::Overflow, L4_error::Rcv)); + + buffer = L4_fpage(b->d); + } + + if (EXPECT_FALSE(!buffer.is_objpage())) + return commit_error(utcb, L4_error(L4_error::Overflow, L4_error::Rcv)); + + Kobject_iface *new_o; + int err = L4_err::ENomem; + + Lock_guardexistence_lock)> space_lock_guard; + + // We take the existence_lock for syncronizing maps... + // This is kind of coarse grained + // try_lock fails if the lock is neither locked nor unlocked + if (!space_lock_guard.try_lock(&c_space->existence_lock)) + return commit_error(utcb, L4_error(L4_error::Overflow, L4_error::Rcv)); + + Lock_guard cpu_lock_guard(&cpu_lock); + + switch ((long)utcb->values[0]) + { + case 0: // new IPC Gate + new_o = new_gate(f->tag(), utcb, c_space, &err); + break; + + case L4_msg_tag::Label_factory: + new_o = new_factory(utcb, &err); + break; + + case L4_msg_tag::Label_task: + new_o = new_task(utcb, &err); + break; + + case L4_msg_tag::Label_thread: + new_o = new_thread(utcb, &err); + break; + + case L4_msg_tag::Label_irq: + new_o = new_irq(f->tag().words(), utcb, &err); + break; + + case L4_msg_tag::Label_vm: + new_o = new_vm(utcb, &err); + break; + + default: + return commit_result(-L4_err::ENodev); + } + + LOG_TRACE("Kobject create", "new", ::current(), __factory_log_fmt, + Log_entry *le = tbe->payload(); + le->op = utcb->values[0]; + le->buffer = buffer.obj_index(); + le->id = dbg_info()->dbg_id(); + le->ram = current(); + le->newo = new_o ? new_o->dbg_info()->dbg_id() : ~0); + + if (new_o) + return map_obj(new_o, buffer.obj_index(), c_space, c_space); + else + return commit_result(-err); + +} + + +//---------------------------------------------------------------------------- +IMPLEMENTATION [svm || vmx]: + +#include "vm_factory.h" + +PRIVATE inline NOEXPORT +Kobject_iface * +Factory::new_vm(Utcb const *, int *err) +{ + if (Vm *new_t = Vm_factory::create(this, err)) + return new_t; + + return 0; +} + +IMPLEMENTATION [tz]: + +#include "vm.h" + +PRIVATE inline NOEXPORT +Kobject_iface * +Factory::new_vm(Utcb const *, int *err) +{ + *err = L4_err::ENomem; + return Vm::create(this); +} + +//---------------------------------------------------------------------------- +IMPLEMENTATION [!svm && !tz && !vmx]: + +PRIVATE inline NOEXPORT +Kobject_iface * +Factory::new_vm(Utcb const *, int *err) +{ + *err = L4_err::ENodev; + return 0; +} + +// ------------------------------------------------------------------------ +INTERFACE [debug]: + +#include "tb_entry.h" + +EXTENSION class Factory +{ +private: + struct Log_entry + { + Smword op; + Mword buffer; + Mword id; + Mword ram; + Mword newo; + }; + static unsigned log_fmt(Tb_entry *, int, char *) asm ("__factory_log_fmt"); +}; + +// ------------------------------------------------------------------------ +IMPLEMENTATION [debug]: + +IMPLEMENT +unsigned +Factory::log_fmt(Tb_entry *e, int maxlen, char *buf) +{ + static char const *const ops[] = + { /* 0 */ "gate", "irq", 0, 0, 0, 0, 0, 0, + /* -8 */ 0, 0, 0, "task", "thread", 0, 0, "factory", + /* -16 */ "vm", 0, 0, 0, "sem" }; + Log_entry *le = e->payload(); + char const *op = -le->op <= (int)(sizeof(ops)/sizeof(ops[0])) + ? ops[-le->op] : "invalid op"; + if (!op) + op = "(nan)"; + + return snprintf(buf, maxlen, "factory=%lx [%s] new=%lx cap=[C:%lx] ram=%lx", le->id, op, le->newo, le->buffer, le->ram); +} diff --git a/kernel/fiasco/src/kern/feature.h b/kernel/fiasco/src/kern/feature.h new file mode 100644 index 00000000..3dbbe2f4 --- /dev/null +++ b/kernel/fiasco/src/kern/feature.h @@ -0,0 +1,14 @@ +#ifndef FEATURE_H__ +#define FEATURE_H__ + +#define KIP_KERNEL_FEATURE(s) \ + asm(".section .initkip.features, \"a\", %progbits \n" \ + ".string \"" s "\" \n" \ + ".previous \n") + +#define KIP_KERNEL_ABI_VERSION(nr) \ + asm(".section .initkip.features, \"a\", %progbits \n" \ + ".string \"abiver:" nr "\" \n" \ + ".previous \n") + +#endif // FEATURE_H__ diff --git a/kernel/fiasco/src/kern/fpu.cpp b/kernel/fiasco/src/kern/fpu.cpp new file mode 100644 index 00000000..1a0c7f34 --- /dev/null +++ b/kernel/fiasco/src/kern/fpu.cpp @@ -0,0 +1,105 @@ +/* + * Fiasco + * Floating point unit code + */ + +INTERFACE: + +#include "initcalls.h" +#include "per_cpu_data.h" +#include "types.h" + +class Context; +class Fpu_state; +class Trap_state; + + +class Fpu +{ +public: + + static Context *owner(unsigned cpu); + static void set_owner(unsigned cpu, Context *owner); + static bool is_owner(unsigned cpu, Context *owner); + + // all the following methods are arch dependent + static void init(unsigned cpu) FIASCO_INIT_CPU; + static unsigned state_size(); + static unsigned state_align(); + static void init_state(Fpu_state *); + static void restore_state(Fpu_state *); + static void save_state(Fpu_state *); + static void disable(); + static void enable(); + +private: + Context *_owner; + + static Per_cpu _fpu; +}; + +IMPLEMENTATION: + +#include "fpu_state.h" + +DEFINE_PER_CPU Per_cpu Fpu::_fpu; + +IMPLEMENT inline +Context * Fpu::owner(unsigned cpu) +{ + return _fpu.cpu(cpu)._owner; +} + +IMPLEMENT inline +void Fpu::set_owner(unsigned cpu, Context *owner) +{ + _fpu.cpu(cpu)._owner = owner; +} + +IMPLEMENT inline +bool Fpu::is_owner(unsigned cpu, Context *owner) +{ + return _fpu.cpu(cpu)._owner == owner; +} + +PUBLIC static inline +Fpu & +Fpu::fpu(unsigned cpu) +{ + return _fpu.cpu(cpu); +} + +//--------------------------------------------------------------------------- +IMPLEMENTATION [!fpu]: + +IMPLEMENT inline +void Fpu::init_state(Fpu_state *) +{} + +IMPLEMENT inline +unsigned Fpu::state_size() +{ return 0; } + +IMPLEMENT inline +unsigned Fpu::state_align() +{ return 1; } + +IMPLEMENT +void Fpu::init(unsigned) +{} + +IMPLEMENT inline +void Fpu::save_state(Fpu_state *) +{} + +IMPLEMENT inline +void Fpu::restore_state(Fpu_state *) +{} + +IMPLEMENT inline +void Fpu::disable() +{} + +IMPLEMENT inline +void Fpu::enable() +{} diff --git a/kernel/fiasco/src/kern/fpu_alloc.cpp b/kernel/fiasco/src/kern/fpu_alloc.cpp new file mode 100644 index 00000000..01155342 --- /dev/null +++ b/kernel/fiasco/src/kern/fpu_alloc.cpp @@ -0,0 +1,61 @@ +INTERFACE: + +#include "fpu.h" +#include "slab_cache.h" + +class Ram_quota; + +class Fpu_alloc : public Fpu +{ +}; + +IMPLEMENTATION: + +#include "fpu_state.h" +#include "kmem_slab.h" +#include "ram_quota.h" + +static Kmem_slab _fpu_state_allocator(Fpu::state_size() + sizeof(Ram_quota*), + Fpu::state_align(), "Fpu state"); + +PRIVATE static +Slab_cache * +Fpu_alloc::slab_alloc() +{ + return &_fpu_state_allocator; +} + +PUBLIC static +bool +Fpu_alloc::alloc_state(Ram_quota *q, Fpu_state *s) +{ + unsigned long sz = Fpu::state_size(); + void *b; + if (!(b = slab_alloc()->q_alloc(q))) + return false; + + *((Ram_quota **)((char*)b + sz)) = q; + s->_state_buffer = b; + Fpu::init_state(s); + + return true; +} + +PUBLIC static +void +Fpu_alloc::free_state(Fpu_state *s) +{ + if (s->_state_buffer) + { + unsigned long sz = Fpu::state_size(); + Ram_quota *q = *((Ram_quota **)((char*)(s->_state_buffer) + sz)); + slab_alloc()->q_free (q, s->_state_buffer); + s->_state_buffer = 0; + + // transferred FPU state may leed to quotas w/o a task but only FPU + // contexts allocated + if (q->current()==0) + delete q; + } +} + diff --git a/kernel/fiasco/src/kern/fpu_state.cpp b/kernel/fiasco/src/kern/fpu_state.cpp new file mode 100644 index 00000000..55448776 --- /dev/null +++ b/kernel/fiasco/src/kern/fpu_state.cpp @@ -0,0 +1,59 @@ +INTERFACE: + +class Fpu_state +{ +public: +#if 0 + void save_state(); + void restore_state(); +#endif + void *state_buffer(); + void state_buffer(void *b); + + Fpu_state(); + ~Fpu_state(); + +private: + friend class Fpu_alloc; + + void *_state_buffer; +}; + +IMPLEMENTATION: + +IMPLEMENT inline +Fpu_state::Fpu_state() : _state_buffer(0) +{} + +IMPLEMENT inline +Fpu_state::~Fpu_state() +{ + //free_state(); +} + +IMPLEMENT inline +void *Fpu_state::state_buffer() +{ + return _state_buffer; +} + +IMPLEMENT inline +void Fpu_state::state_buffer(void *b) +{ + _state_buffer = b; +} + + +#if 0 +IMPLEMENT inline +void Fpu_state::save_state() +{ + Fpu::save_state(this); +} + +IMPLEMENT inline +void Fpu_state::restore_state() +{ + Fpu::restore_state(this); +} +#endif diff --git a/kernel/fiasco/src/kern/genchecksum.cc b/kernel/fiasco/src/kern/genchecksum.cc new file mode 100644 index 00000000..400ed15b --- /dev/null +++ b/kernel/fiasco/src/kern/genchecksum.cc @@ -0,0 +1,168 @@ + +#include +#include +#include +#include + +static char buffer[128]; +static int buf_idx; +static int buf_chars; + +static char const *hexchars = "0123456789abcdef"; + +extern "C" void exit(int status); + +int +fill_buffer(int fd) +{ + buf_chars = read(fd, buffer, sizeof(buffer)); + buf_idx = 0; + + return buf_chars >= 1; +} + +int +this_char(int fd, char *c) +{ + if (buf_idx >= buf_chars) + { + if (!fill_buffer(fd)) + return 0; + } + + *c = buffer[buf_idx]; + return 1; +} + +int +skip_line(int fd) +{ + for (;;) + { + char c; + + if (! this_char(fd, &c)) + return 0; + + buf_idx++; + + if (c == '\n') + return 1; + } +} + +int +skip_to_hex(int fd) +{ + for (;;) + { + char c; + + if (! this_char(fd, &c)) + return 0; + + if (strchr(hexchars, c)) + return 1; + + if (! skip_line(fd)) + return 0; + } +} + +int +skip_preamble(int fd) +{ + for (;;) + { + char c; + + if (! this_char(fd, &c)) + return 0; + + if (!strchr(hexchars, c)) + { + if (!skip_line(fd)) + return 0; + + continue; + } + + return 1; + } +} + +int +read_byte(int fd, unsigned *byte) +{ + unsigned hex = 0; + int i; + + for (i=0; i<2; i++) + { + char c; + const char *idx; + + if (! this_char(fd, &c)) + return 0; + + if (!(idx = strchr(hexchars, c))) + exit(-1); + + hex *= 16; + hex += (idx-hexchars); + + buf_idx++; + } + + *byte = hex; + return 1; +} + +int +read_dword(int fd, unsigned *dword) +{ + char c; + unsigned hex = 0; + unsigned factor = 1; + int i; + + if (! skip_to_hex(fd)) + return 0; + + for (i=0, factor=1; i<4; i++, factor*=256) + { + unsigned byte; + + if (! read_byte(fd, &byte)) + return 0; + + hex += byte * factor; + } + + this_char(fd, &c); + buf_idx++; // skip/\n space after dword + + *dword = hex; + return 1; +} + +int +main(int argc, char **argv) +{ + static char buf[20]; + int ret; + int fd; + unsigned dword; + unsigned checksum; + + skip_preamble(STDIN_FILENO); + + checksum = 0; + while (read_dword(STDIN_FILENO, &dword)) + checksum += dword; + + printf("%08x", checksum); + + return 0; +} + diff --git a/kernel/fiasco/src/kern/genlines.c b/kernel/fiasco/src/kern/genlines.c new file mode 100644 index 00000000..c20bce76 --- /dev/null +++ b/kernel/fiasco/src/kern/genlines.c @@ -0,0 +1,323 @@ + +/* Extract debug lines info from an ELF binary stab section */ + +/* + * Adam: Note, this file works on 32-bit files only. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PAGESIZE 4096 +#define MAX_PAGES 512 +#define LIN_PER_PAGE (PAGESIZE/sizeof(Stab_entry)) + +typedef struct +{ + unsigned int n_strx; /* index into string table of name */ + unsigned char n_type; /* type of symbol */ + unsigned char n_other; /* misc info (usually empty) */ + unsigned short n_desc; /* description field */ + unsigned int n_value; /* value of symbol */ +} __attribute__ ((packed)) Stab_entry; + +typedef struct +{ + unsigned int addr; + unsigned short line; +} __attribute__ ((packed)) Stab_line; + +const unsigned str_max = MAX_PAGES*PAGESIZE; +const unsigned lin_max = MAX_PAGES*PAGESIZE/sizeof(Stab_line); + +static char *str_field; +static Stab_line *lin_field; +static unsigned str_end; +static unsigned lin_end; +static unsigned func_offset; +static int have_func; + +static Elf32_Shdr* +elf_sh_lookup(unsigned char *elf_image, int n) +{ + Elf32_Ehdr *ehdr = (Elf32_Ehdr*)elf_image; + + return (n < ehdr->e_shnum) + ? (Elf32_Shdr*)(elf_image + ehdr->e_shoff + n*ehdr->e_shentsize) + : 0; +} + +static int +search_str(const char *str, unsigned len, unsigned *idx) +{ + const char *c_next, *c, *d; + + if (!str_field || !*str_field) + return 0; + + for (c_next=str_field; ; ) + { + // goto end of string + for (; *c_next; c_next++) + ; + + // compare strings + for (c=c_next, d=str+len; d>=str && (*c == *d); c--, d--) + ; + + if (d= str_max) + { + fprintf(stderr, "Not enough memory for debug lines (str space)\n"); + return 0; + } + + *idx = str_end; + + // add string to end of str_field + strcpy(str_field+str_end, str); + str_end += len+1; + + // terminate string field + str_field[str_end] = '\0'; + + return 1; +} + +// see documentation in "info stabs" +static int +add_entry(const Stab_entry *se, const char *se_str) +{ + const char *se_name = se_str + se->n_strx; + int se_name_len = strlen(se_name); + unsigned se_name_idx = 0; + + if (se_name_len + && ((se->n_type == 0x64) || (se->n_type == 0x84))) + { + if (!add_str(se_name, se_name_len, &se_name_idx)) + return 0; + } + + if (lin_end >= lin_max) + { + fprintf(stderr, "Not enough temporary memory for lines (lin space)\n"); + return 0; + } + + switch (se->n_type) + { + case 0x24: // N_FUN: function name + func_offset = se->n_value; // start address of function + have_func = 1; + break; + case 0x44: // N_SLINE: line number in text segment + if (have_func && (se->n_desc < 0xfffd)) // sanity check + { + // Search last SLINE entry and compare addresses. If they are + // same, overwrite the last entry because we display only one + // line number per address + unsigned addr = se->n_value + func_offset; + + unsigned l = lin_end; + while ((l > 0) && (lin_field[l-1].line>=0xfffd)) + l--; + + if ((l > 0) && (lin_field[l-1].addr == addr)) + { + // found, delete array entry + while (l < lin_end) + { + lin_field[l-1] = lin_field[l]; + l++; + } + lin_end--; + } + // append + lin_field[lin_end].addr = addr; + lin_field[lin_end].line = se->n_desc; + lin_end++; + } + break; + case 0x64: // N_SO: main file name / directory + if (se_name_len) + { + if (lin_end>0 && lin_field[lin_end-1].line == 0xffff) + { + // mark last entry as directory, this is a file name + lin_field[lin_end-1].line = 0xfffe; + } + } + else + have_func = 0; + // fall through + case 0x84: // N_SOL: name of include file + if (se_name_len) + { + int type = 0xffff; + char c = se_name[se_name_len-1]; + + if (c=='h' || c=='H') + type = 0xfffd; // mark as header file + + lin_field[lin_end].addr = se_name_idx; + lin_field[lin_end].line = type; + lin_end++; + } + break; + } + + return 1; +} + +static int +add_section(const Stab_entry *se, const char *str, unsigned n) +{ + unsigned int i; + + func_offset = 0; + have_func = 0; + + for (i=0; ie_shstrndx == SHN_UNDEF) + { + fprintf(stderr, "Error in ELF header\n"); + return -3; + } + + if (0 == (sh_str = elf_sh_lookup(elf_image, ehdr->e_shstrndx))) + { + fprintf(stderr, "Error in ELF stab section\n"); + return -3; + } + + strtab = (const char*)(elf_image + sh_str->sh_offset); + + for (i=0; ie_shnum; i++) + { + sh_sym = elf_sh_lookup(elf_image, i); + if ( ( sh_sym->sh_type == SHT_PROGBITS + || sh_sym->sh_type == SHT_STRTAB) + && (!strcmp(sh_sym->sh_name + strtab, ".stab"))) + { + if (0 == (sh_str = elf_sh_lookup(elf_image, sh_sym->sh_link))) + { + fprintf(stderr, "Error in ELF stab section\n"); + return -3; + } + + if (!add_section((const Stab_entry*)(elf_image+sh_sym->sh_offset), + (const char*) (elf_image+sh_str->sh_offset), + sh_sym->sh_size/sh_sym->sh_entsize)) + return -3; + } + } + + if (lin_end > 0) + { + // add terminating entry + if (lin_end >= lin_max) + { + fprintf(stderr, "Not enough temporary memory for lines " + "(terminating line entry)\n"); + return -3; + } + lin_field[lin_end].addr = 0; + lin_field[lin_end].line = 0; + lin_end++; + + // string offset relativ to begin of lines + for (i=0; i= 0xfffd) + lin_field[i].addr += lin_end*sizeof(Stab_line); + + fwrite(lin_field, lin_end*sizeof(Stab_line), 1, stdout); + fwrite(str_field, str_end, 1, stdout); + + return 0; + } + + fprintf(stderr, "No lines stored\n"); + return -3; +} + +int +main(int argc, char **argv) +{ + int fd; + unsigned size; + unsigned char *image; + + if (argc != 2) + { + fprintf(stderr, "Usage: %s \n", argv[0]); + return -1; + } + + if ((fd = open(argv[1], O_RDONLY)) < 0) + { + fprintf(stderr, "Cannot open %s\n", argv[1]); + return -2; + } + + size = lseek(fd, 0, SEEK_END); + + if ((image = mmap(0, size, PROT_READ, MAP_SHARED, fd, 0)) + == (unsigned char*)-1) + { + fprintf(stderr, "Cannot map ELF file\n"); + return -3; + } + + return extract_lines(image); +} + diff --git a/kernel/fiasco/src/kern/globals.cpp b/kernel/fiasco/src/kern/globals.cpp new file mode 100644 index 00000000..4dc88b3d --- /dev/null +++ b/kernel/fiasco/src/kern/globals.cpp @@ -0,0 +1,78 @@ +INTERFACE: + +#include + +#include "panic.h" +#include "per_cpu_data.h" +#include "types.h" + +class Timeout; + +extern Per_cpu timeslice_timeout; + +/* the check macro is like assert(), but it evaluates its argument + even if NDEBUG is defined */ +#ifndef check +#ifdef NDEBUG +# define check(expression) ((void)(expression)) +#else /* ! NDEBUG */ +# ifdef ASSERT_KDB_KE +# define check(expression) assert(expression) +# else +# define check(expression) \ + ((void)((expression) ? 0 : \ + (panic(__FILE__":%u: failed check `"#expression"'", \ + __LINE__), 0))) +# endif +#endif /* ! NDEBUG */ +#endif /* check */ + +class Kobject_iface; + +class Initial_kobjects +{ +public: + enum + { + Max = 5, + First_cap = 5, + + End_cap = First_cap + Max, + }; + + void register_obj(Kobject_iface *o, unsigned cap) + { + assert (cap >= First_cap); + assert (cap < End_cap); + + cap -= First_cap; + + assert (!_v[cap]); + + _v[cap] = o; + } + + Kobject_iface *obj(unsigned cap) const + { + assert (cap >= First_cap); + assert (cap < End_cap); + + cap -= First_cap; + + return _v[cap]; + } + +private: + Kobject_iface *_v[Max]; +}; + + +extern Initial_kobjects initial_kobjects; + + +//--------------------------------------------------------------------------- +IMPLEMENTATION: + +Initial_kobjects initial_kobjects; + + diff --git a/kernel/fiasco/src/kern/helping_lock.cpp b/kernel/fiasco/src/kern/helping_lock.cpp new file mode 100644 index 00000000..f229f04e --- /dev/null +++ b/kernel/fiasco/src/kern/helping_lock.cpp @@ -0,0 +1,124 @@ +INTERFACE: + +#include "lock_guard.h" +#include "switch_lock.h" + +#ifdef NO_INSTRUMENT +#undef NO_INSTRUMENT +#endif +#define NO_INSTRUMENT __attribute__((no_instrument_function)) + +/** A wrapper for Switch_lock that works even when the threading system + has not been intialized yet. + This wrapper is necessary because most lock-protected objects are + initialized before the threading system has been fired up. + */ +class Helping_lock : private Switch_lock +{ + +public: + using Switch_lock::Status; + using Switch_lock::Not_locked; + using Switch_lock::Locked; + using Switch_lock::Invalid; + + using Switch_lock::invalidate; + using Switch_lock::valid; + using Switch_lock::wait_free; + + static bool threading_system_active; +}; + +typedef Lock_guard Helping_lock_guard; + +#undef NO_INSTRUMENT +#define NO_INSTRUMENT + +IMPLEMENTATION: + +#include "globals.h" +#include "panic.h" +#include "std_macros.h" + + +/** Threading system activated. */ +bool Helping_lock::threading_system_active = false; + +/** Constructor. */ +PUBLIC inline +Helping_lock::Helping_lock () +{ + Switch_lock::initialize(); +} + +/** Acquire the lock with priority inheritance. + @return true if we owned the lock already. false otherwise. + */ +PUBLIC inline +Helping_lock::Status NO_INSTRUMENT +Helping_lock::test_and_set () +{ + if (! threading_system_active) // still initializing? + return Not_locked; + + return Switch_lock::test_and_set(); +} + +/** Acquire the lock with priority inheritance. + If the lock is occupied, enqueue in list of helpers and lend CPU + to current lock owner until we are the lock owner. + */ +PUBLIC inline NEEDS ["panic.h"] +Helping_lock::Status NO_INSTRUMENT +Helping_lock::lock () +{ + return test_and_set(); +} + +/** Is lock set?. + @return true if lock is set. + */ +PUBLIC inline NEEDS["std_macros.h"] +Helping_lock::Status NO_INSTRUMENT +Helping_lock::test () +{ + if (EXPECT_FALSE( ! threading_system_active) ) // still initializing? + return Not_locked; + + return Switch_lock::test(); +} + +/** Free the lock. + Return the CPU to helper or next lock owner, whoever has the higher + priority, given that thread's priority is higher that our's. + */ +PUBLIC inline NEEDS["std_macros.h"] +void NO_INSTRUMENT +Helping_lock::clear() +{ + if (EXPECT_FALSE( ! threading_system_active) ) // still initializing? + return; + + Switch_lock::clear(); +} + +PUBLIC inline NEEDS[Helping_lock::clear] +void +Helping_lock::set(Status s) +{ + if (!s) + clear(); +} + +/** Lock owner. + @return current owner of the lock. 0 if there is no owner. + */ +PUBLIC inline NEEDS["std_macros.h", "globals.h"] +Context* NO_INSTRUMENT +Helping_lock::lock_owner () const +{ + if (EXPECT_FALSE( ! threading_system_active) ) // still initializing? + return current(); + + return Switch_lock::lock_owner(); +} diff --git a/kernel/fiasco/src/kern/hpet.cpp b/kernel/fiasco/src/kern/hpet.cpp new file mode 100644 index 00000000..3f23b350 --- /dev/null +++ b/kernel/fiasco/src/kern/hpet.cpp @@ -0,0 +1,230 @@ +INTERFACE: + +#include "acpi.h" +#include "div32.h" +#include "mem.h" + +class Acpi_hpet : public Acpi_table_head +{ +public: + Unsigned32 event_timer_block_id; + Acpi_gas base_address; + Unsigned8 hpet_number; + Unsigned16 min_clock_ticks_for_irq; + Unsigned8 page_prot_and_oem_attr; +} __attribute__((packed)); + +class Hpet_timer +{ +public: + Unsigned64 config_and_cap; + Unsigned64 comp_val; + Unsigned64 irq_route; + Unsigned64 _pad0; + + enum + { + Tn_INT_TYPE_CNF = 1 << 1, + Tn_INT_ENB_CNF = 1 << 2, + Tn_TYPE_CNF = 1 << 3, + Tn_PER_INT_CAP = 1 << 4, + Tn_SIZE_CAP = 1 << 5, + Tn_VAL_SET_CNF = 1 << 6, + Tn_32MODE_CNF = 1 << 8, + Tn_FSB_EN_CNF = 1 << 14, + Tn_FSB_INT_DEL_CAP = 1 << 15, + Tn_INT_ROUTE_CNF_MASK = 31 << 9, + }; + + void enable_int() { config_and_cap |= Tn_INT_ENB_CNF; } + void disable_int() { config_and_cap &= ~Tn_INT_ENB_CNF; } + void set_int(int irq) + { config_and_cap = (config_and_cap & ~Tn_INT_ROUTE_CNF_MASK) | (irq << 9); } + + int get_int() const { return (config_and_cap & Tn_INT_ROUTE_CNF_MASK) >> 9; } + + bool can_periodic() const { return config_and_cap & Tn_PER_INT_CAP; } + void set_periodic() { config_and_cap |= Tn_TYPE_CNF; } + + void set_level_irq() { config_and_cap |= Tn_INT_TYPE_CNF; } + void set_edge_irq() { config_and_cap &= ~Tn_INT_TYPE_CNF; } + + bool can_64bit() const { return config_and_cap & Tn_SIZE_CAP; } + void force_32bit() { config_and_cap |= Tn_32MODE_CNF; } + void val_set() { config_and_cap |= Tn_VAL_SET_CNF; } + + Unsigned32 int_route_cap() const { return config_and_cap >> 32; } + bool int_avail(int i) const { return int_route_cap() & i; } + + int get_first_int() + { + Unsigned32 cap = int_route_cap(); + for (int i = 0; i < 32; ++i) + if (cap & (1 << i)) + return i; + return ~0U; + } + +} __attribute__((packed)); + +class Hpet_device +{ +private: +public: + Unsigned64 cap_and_id; // offset 0x00 + Unsigned64 _pad0; + Unsigned64 config; // offset 0x10 + Unsigned64 _pad1; + Unsigned64 irq_status; // offset 0x20 + Unsigned64 _pad2[1 + 2 * 12]; + Unsigned64 counter_val; // 0ffset 0xf0 + + enum Config + { + ENABLE_CNF = 1 << 0, + LEG_RT_CNF = 1 << 1, + }; + +public: + + int num_timers() const { return ((cap_and_id >> 8) & 0xf) + 1; } + + Hpet_timer *timer(int idx) const + { return reinterpret_cast((char *)this + 0x100 + idx * 0x20); } + + void enable() { config |= ENABLE_CNF; Mem::mb(); } + void disable() { config &= ~ENABLE_CNF; Mem::mb(); } + + Unsigned32 counter_clk_period() const { return cap_and_id >> 32; } + void reset_counter() { counter_val = 0; Mem::mb(); } + + void clear_level_irq(int timer_nr) + { irq_status = 1 << timer_nr; Mem::mb(); } + +} __attribute__((packed)); + +class Hpet +{ +public: + static void set_periodic() { _hpet_timer->set_periodic(); } + static void enable_timer() { _hpet_timer->enable_int(); } + static void disable_timer() { _hpet_timer->disable_int(); } + static void clear_timer() { /* _hpet->clear_level_irq(2); */ } + static int int_num() { return _hpet_timer->get_int(); } + static bool int_avail(int i) { return _hpet_timer->int_avail(i); } + + static void enable() { _hpet->enable(); } + static void dump() { _hpet->dump(); } + +private: + static Acpi_hpet const *_acpi_hpet; + static Hpet_device *_hpet; + static Hpet_timer *_hpet_timer; +}; + +IMPLEMENTATION: + +Acpi_hpet const *Hpet::_acpi_hpet; +Hpet_device *Hpet::_hpet; +Hpet_timer *Hpet::_hpet_timer; + +PUBLIC +void +Hpet_device::dump() +{ + printf("HPET: cap+id : %016llx\n", cap_and_id); + printf(" clk-per: %d femtosecs\n", counter_clk_period()); + printf(" gen-config: %llx\n", config); +} + +PUBLIC static +void +Hpet::dump_acpi_infos() +{ + if (!_acpi_hpet) + return; + + printf("ACPI-HPET = %p\n", _acpi_hpet); + + printf(" event_timer_block_id: %x\n", _acpi_hpet->event_timer_block_id); + printf(" base_address: %llx (as: %d, off: %d, w: %d, id: %d)\n", + _acpi_hpet->base_address.addr, + _acpi_hpet->base_address.access_size, + _acpi_hpet->base_address.offset, + _acpi_hpet->base_address.width, + _acpi_hpet->base_address.id); + printf(" hpet_number: %d\n", _acpi_hpet->hpet_number); + printf(" min_clock_ticks_for_irq: %d\n", _acpi_hpet->min_clock_ticks_for_irq); + printf(" page_prot_and_oem_attr: %x\n", _acpi_hpet->page_prot_and_oem_attr); +} + +PUBLIC static FIASCO_INIT +bool +Hpet::init() +{ + _acpi_hpet = Acpi::find("HPET"); + + if (!_acpi_hpet) + { + printf("Could not find HPET in RSDT nor XSDT, skipping init\n"); + return false; + } + + dump_acpi_infos(); + + Address offs; + Address a = _acpi_hpet->base_address.addr; + Address va = Mem_layout::alloc_io_vmem(Config::PAGE_SIZE); + assert (va); + + Kmem::map_phys_page(a, va, false, true, &offs); + + Kip::k()->add_mem_region(Mem_desc(a, a + 1023, Mem_desc::Reserved)); + + _hpet = (Hpet_device *)(va + offs); + + _hpet->dump(); + + _hpet->disable(); + _hpet->reset_counter(); + + int i = 2; + Hpet_timer *t = 0; + for (; i < _hpet->num_timers(); ++i) + { + t = _hpet->timer(i); + + if (t->can_periodic() && t->int_route_cap()) + { + t->force_32bit(); + t->set_periodic(); + t->set_edge_irq(); + t->val_set(); + t->set_int(t->get_first_int()); + + t->comp_val = div32(1000000000000ULL, _hpet->counter_clk_period()); + + break; + } + } + + if (!t) + { + printf("ERROR: Did not find a HPET timer that can do periodic mode.\n"); + return false; + } + + _hpet_timer = t; + + _hpet->dump(); + + return true; +} + +// ------------------------------------------------------------------------ +IMPLEMENTATION [debug]: + +PUBLIC static +Hpet_device * +Hpet::hpet() +{ return _hpet; } diff --git a/kernel/fiasco/src/kern/ia32/32/config-ia32-32.cpp b/kernel/fiasco/src/kern/ia32/32/config-ia32-32.cpp new file mode 100644 index 00000000..7e3a4067 --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/32/config-ia32-32.cpp @@ -0,0 +1,18 @@ +INTERFACE[ia32,ux]: + +EXTENSION class Config +{ +public: + + enum { + PAGE_SHIFT = ARCH_PAGE_SHIFT, + PAGE_SIZE = 1 << PAGE_SHIFT, + PAGE_MASK = ~( PAGE_SIZE - 1), + + SUPERPAGE_SHIFT = 22, + SUPERPAGE_SIZE = 1 << SUPERPAGE_SHIFT, + SUPERPAGE_MASK = ~( SUPERPAGE_SIZE - 1 ), + + Irq_shortcut = 1, + }; +}; diff --git a/kernel/fiasco/src/kern/ia32/32/context-ia32-32.cpp b/kernel/fiasco/src/kern/ia32/32/context-ia32-32.cpp new file mode 100644 index 00000000..aae3ef98 --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/32/context-ia32-32.cpp @@ -0,0 +1,76 @@ +INTERFACE[ia32]: + +#include "x86desc.h" + +EXTENSION class Context +{ +protected: + enum { Gdt_user_entries = 4 }; + Gdt_entry _gdt_user_entries[Gdt_user_entries+1]; + Unsigned32 _es, _fs, _gs; +}; + + +//----------------------------------------------------------------------------- +IMPLEMENTATION[ia32]: + +#include "cpu.h" +#include "gdt.h" + +PROTECTED inline NEEDS ["cpu.h", "gdt.h"] +void +Context::switch_gdt_user_entries(Context *to) +{ + Gdt &gdt = *Cpu::cpus.cpu(to->cpu()).get_gdt(); + for (unsigned i = 0; i < Gdt_user_entries; ++i) + gdt[(Gdt::gdt_user_entry1 / 8) + i] = to->_gdt_user_entries[i]; + + gdt[Gdt::gdt_utcb/8] = to->_gdt_user_entries[Gdt_user_entries]; +} + +PROTECTED inline +void +Context::arch_setup_utcb_ptr() +{ + _utcb.access()->utcb_addr = (Mword)_utcb.usr().get(); + _gdt_user_entries[Gdt_user_entries] = Gdt_entry((Address)&_utcb.usr()->utcb_addr, 0xfffff, Gdt_entry::Access_user + | Gdt_entry::Access_data_write | Gdt_entry::Accessed, Gdt_entry::Size_32 | 0x80); + _gs = _fs = Gdt::gdt_utcb | 3; +} + +//--------------------------------------------------------------------------- +IMPLEMENTATION [ia32 || ux]: + + +IMPLEMENT inline NEEDS [Context::update_consumed_time, + Context::store_segments] +void +Context::switch_cpu(Context *t) +{ + Mword dummy1, dummy2, dummy3, dummy4; + + update_consumed_time(); + + store_segments(); + + switch_gdt_user_entries(t); + + asm volatile + ( + " pushl %%ebp \n\t" // save base ptr of old thread + " pushl $1f \n\t" // restart addr to old stack + " movl %%esp, (%0) \n\t" // save stack pointer + " movl (%1), %%esp \n\t" // load new stack pointer + // in new context now (cli'd) + " movl %2, %%eax \n\t" // new thread's "this" + " call switchin_context_label \n\t" // switch pagetable + " popl %%eax \n\t" // don't do ret here -- we want + " jmp *%%eax \n\t" // to preserve the return stack + // restart code + " .p2align 4 \n\t" // start code at new cache line + "1: popl %%ebp \n\t" // restore base ptr + + : "=c" (dummy1), "=S" (dummy2), "=D" (dummy3), "=d" (dummy4) + : "c" (&_kernel_sp), "S" (&t->_kernel_sp), "D" (t), "d" (this) + : "eax", "ebx", "memory"); +} diff --git a/kernel/fiasco/src/kern/ia32/32/continuation-ia32-32-ux.cpp b/kernel/fiasco/src/kern/ia32/32/continuation-ia32-32-ux.cpp new file mode 100644 index 00000000..d744a8a7 --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/32/continuation-ia32-32-ux.cpp @@ -0,0 +1,75 @@ +INTERFACE[ux]: + +#include "gdt.h" +#include "emulation.h" +#include "entry_frame.h" +#include "member_offs.h" +#include "regdefs.h" +#include "types.h" + +class Continuation +{ + MEMBER_OFFSET(); + +private: + Address _ip; + Mword _flags; + +public: + Continuation() : _ip(~0UL) {} + + typedef Return_frame User_return_frame; + + bool valid() const + { return _ip != ~0UL; } + + Address ip() const { return _ip; } + void ip(Address ip) { _ip = ip; } + + Mword flags(Return_frame const *) const { return _flags; } + void flags(Return_frame *, Mword flags) { _flags = flags; } + + Mword sp(Return_frame const *o) const { return o->sp(); } + void sp(Return_frame *o, Mword sp) { o->sp(sp); } + + void save(Return_frame const *regs) + { + _ip = regs->ip(); + _flags = regs->flags(); + } + + void activate(Return_frame *regs, void *cont_func) + { + save(regs); + regs->ip(Mword(cont_func)); + regs->flags(regs->flags() & ~EFLAGS_TF); // do not singlestep inkernel code + regs->cs(Gdt::gdt_code_kernel | Gdt::Selector_kernel); + } + + void set(Return_frame *dst, User_return_frame const *src) + { + _ip = src->ip(); + _flags = src->flags(); + dst->sp(src->sp()); + } + + void get(User_return_frame *dst, Return_frame const *src) const + { + dst->ip(_ip); + dst->flags(_flags); + dst->sp(src->sp()); + } + + void clear() { _ip = ~0UL; } + + void restore(Return_frame *regs) + { + //LOG_MSG_3VAL(current(), "rst", _ip, _flags, 0); + regs->ip(_ip); + regs->flags(_flags); + regs->cs(Emulation::kernel_cs() & ~1); + clear(); + } + +}; + diff --git a/kernel/fiasco/src/kern/ia32/32/continuation-ia32-32.cpp b/kernel/fiasco/src/kern/ia32/32/continuation-ia32-32.cpp new file mode 100644 index 00000000..ab453422 --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/32/continuation-ia32-32.cpp @@ -0,0 +1,76 @@ +INTERFACE[ia32]: + +#include "entry_frame.h" +#include "gdt.h" +#include "member_offs.h" +#include "regdefs.h" +#include "types.h" + +class Continuation +{ + MEMBER_OFFSET(); + +private: + Address _ip; + Mword _flags; + +public: + Continuation() : _ip(~0UL) {} + + typedef Return_frame User_return_frame; + + bool valid() const + { return _ip != ~0UL; } + + Address ip() const { return _ip; } + void ip(Address ip) { _ip = ip; } + + Mword flags(Return_frame const *) const { return _flags; } + void flags(Return_frame *, Mword flags) { _flags = flags; } + + Mword sp(Return_frame const *o) const { return o->sp(); } + void sp(Return_frame *o, Mword sp) { o->sp(sp); } + + void save(Return_frame const *regs) + { + _ip = regs->ip(); + _flags = regs->flags(); + // LOG_MSG_3VAL(current(), "sav", _ip, _flags, 0); + } + + void activate(Return_frame *regs, void *cont_func) + { + save(regs); + regs->ip(Mword(cont_func)); + regs->flags(regs->flags() & ~EFLAGS_TF); // do not singlestep inkernel code + regs->cs(Gdt::gdt_code_kernel | Gdt::Selector_kernel); + // LOG_MSG_3VAL(current(), "act", regs->ip(), regs->flags(), regs->cs()); + } + + void set(Return_frame *dst, User_return_frame const *src) + { + _ip = src->ip(); + _flags = src->flags(); + dst->sp(src->sp()); + } + + void get(User_return_frame *dst, Return_frame const *src) const + { + dst->ip(_ip); + dst->flags(_flags); + dst->sp(src->sp()); + } + + void clear() { _ip = ~0UL; } + + void restore(Return_frame *regs) + { + // LOG_MSG_3VAL(current(), "rst", _ip, _flags, 0); + regs->ip(_ip); + regs->flags(_flags); + regs->cs(Gdt::gdt_code_user | Gdt::Selector_user); + clear(); + } + +}; + diff --git a/kernel/fiasco/src/kern/ia32/32/cpu-32.cpp b/kernel/fiasco/src/kern/ia32/32/cpu-32.cpp new file mode 100644 index 00000000..42fad374 --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/32/cpu-32.cpp @@ -0,0 +1,208 @@ +IMPLEMENTATION [ia32,ux]: + +#include "mem_layout.h" +#include "tss.h" + +PUBLIC static inline +Mword +Cpu::stack_align(Mword stack) +{ return stack & ~0x3; } + + +PUBLIC inline +Unsigned64 +Cpu::ns_to_tsc(Unsigned64 ns) const +{ + Unsigned32 dummy; + Unsigned64 tsc; + asm volatile + ("movl %%edx, %%ecx \n\t" + "mull %3 \n\t" + "movl %%ecx, %%eax \n\t" + "movl %%edx, %%ecx \n\t" + "mull %3 \n\t" + "addl %%ecx, %%eax \n\t" + "adcl $0, %%edx \n\t" + "shld $5, %%eax, %%edx \n\t" + "shll $5, %%eax \n\t" + :"=A" (tsc), "=&c" (dummy) + : "0" (ns), "b" (scaler_ns_to_tsc) + ); + return tsc; +} + +PUBLIC inline +Unsigned64 +Cpu::tsc_to_ns(Unsigned64 tsc) const +{ + Unsigned32 dummy; + Unsigned64 ns; + asm volatile + ("movl %%edx, %%ecx \n\t" + "mull %3 \n\t" + "movl %%ecx, %%eax \n\t" + "movl %%edx, %%ecx \n\t" + "mull %3 \n\t" + "addl %%ecx, %%eax \n\t" + "adcl $0, %%edx \n\t" + "shld $5, %%eax, %%edx \n\t" + "shll $5, %%eax \n\t" + :"=A" (ns), "=&c" (dummy) + : "0" (tsc), "b" (scaler_tsc_to_ns) + ); + return ns; +} + +PUBLIC inline +Unsigned64 +Cpu::tsc_to_us(Unsigned64 tsc) const +{ + Unsigned32 dummy; + Unsigned64 us; + asm volatile + ("movl %%edx, %%ecx \n\t" + "mull %3 \n\t" + "movl %%ecx, %%eax \n\t" + "movl %%edx, %%ecx \n\t" + "mull %3 \n\t" + "addl %%ecx, %%eax \n\t" + "adcl $0, %%edx \n\t" + :"=A" (us), "=&c" (dummy) + : "0" (tsc), "S" (scaler_tsc_to_us) + ); + return us; +} + + +PUBLIC inline +void +Cpu::tsc_to_s_and_ns(Unsigned64 tsc, Unsigned32 *s, Unsigned32 *ns) const +{ + Unsigned32 dummy; + __asm__ + (" \n\t" + "movl %%edx, %%ecx \n\t" + "mull %4 \n\t" + "movl %%ecx, %%eax \n\t" + "movl %%edx, %%ecx \n\t" + "mull %4 \n\t" + "addl %%ecx, %%eax \n\t" + "adcl $0, %%edx \n\t" + "movl $1000000000, %%ecx \n\t" + "shld $5, %%eax, %%edx \n\t" + "shll $5, %%eax \n\t" + "divl %%ecx \n\t" + :"=a" (*s), "=d" (*ns), "=&c" (dummy) + : "A" (tsc), "g" (scaler_tsc_to_ns) + ); +} + + +PUBLIC static inline +Unsigned64 +Cpu::rdtsc() +{ + Unsigned64 tsc; + asm volatile ("rdtsc" : "=A" (tsc)); + return tsc; +} + +PUBLIC static inline +Unsigned32 +Cpu::get_flags() +{ Unsigned32 efl; asm volatile ("pushfl ; popl %0" : "=r"(efl)); return efl; } + +PUBLIC static inline +void +Cpu::set_flags(Unsigned32 efl) +{ asm volatile ("pushl %0 ; popfl" : : "rm" (efl) : "memory"); } + +IMPLEMENT inline NEEDS["tss.h"] +Address volatile & +Cpu::kernel_sp() const +{ return *reinterpret_cast
(&get_tss()->_esp0); } + + +//---------------------------------------------------------------------------- +IMPLEMENTATION[ia32]: + +PUBLIC static inline +void +Cpu:: set_cs() +{ + asm volatile ("ljmp %0,$1f ; 1:" + : : "i"(Gdt::gdt_code_kernel | Gdt::Selector_kernel)); +} + +extern "C" void entry_vec08_dbf (); +extern "C" Address dbf_stack_top; + +PUBLIC FIASCO_INIT_CPU +void +Cpu::init_tss_dbf(Address tss_dbf_mem, Address kdir) +{ + tss_dbf = reinterpret_cast(tss_dbf_mem); + + gdt->set_entry_byte(Gdt::gdt_tss_dbf/8, tss_dbf_mem, sizeof(Tss)-1, + Gdt_entry::Access_kernel | Gdt_entry::Access_tss | + Gdt_entry::Accessed, 0); + + tss_dbf->_cs = Gdt::gdt_code_kernel; + tss_dbf->_ss = Gdt::gdt_data_kernel; + tss_dbf->_ds = Gdt::gdt_data_kernel; + tss_dbf->_es = Gdt::gdt_data_kernel; + tss_dbf->_fs = Gdt::gdt_data_kernel; + tss_dbf->_gs = Gdt::gdt_data_kernel; + tss_dbf->_eip = (Address)entry_vec08_dbf; + tss_dbf->_esp = (Address)&dbf_stack_top; + tss_dbf->_ldt = 0; + tss_dbf->_eflags = 0x00000082; + tss_dbf->_cr3 = kdir; + tss_dbf->_io_bit_map_offset = 0x8000; +} + + +PUBLIC FIASCO_INIT_CPU +void +Cpu::init_tss(Address tss_mem, size_t tss_size) +{ + tss = reinterpret_cast(tss_mem); + + gdt->set_entry_byte(Gdt::gdt_tss/8, tss_mem, tss_size, + Gdt_entry::Access_kernel | Gdt_entry::Access_tss, 0); + + tss->set_ss0(Gdt::gdt_data_kernel); + tss->_io_bit_map_offset = Mem_layout::Io_bitmap - tss_mem; +} + + +PUBLIC FIASCO_INIT_CPU +void +Cpu::init_gdt(Address gdt_mem, Address user_max) +{ + gdt = reinterpret_cast(gdt_mem); + + // make sure kernel cs/ds and user cs/ds are placed in the same + // cache line, respectively; pre-set all "accessed" flags so that + // the CPU doesn't need to do this later + + gdt->set_entry_4k(Gdt::gdt_code_kernel/8, 0, 0xffffffff, + Gdt_entry::Access_kernel | + Gdt_entry::Access_code_read | + Gdt_entry::Accessed, Gdt_entry::Size_32); + gdt->set_entry_4k(Gdt::gdt_data_kernel/8, 0, 0xffffffff, + Gdt_entry::Access_kernel | + Gdt_entry::Access_data_write | + Gdt_entry::Accessed, Gdt_entry::Size_32); + gdt->set_entry_4k(Gdt::gdt_code_user/8, 0, user_max, + Gdt_entry::Access_user | + Gdt_entry::Access_code_read | + Gdt_entry::Accessed, Gdt_entry::Size_32); + gdt->set_entry_4k(Gdt::gdt_data_user/8, 0, user_max, + Gdt_entry::Access_user | + Gdt_entry::Access_data_write | + Gdt_entry::Accessed, Gdt_entry::Size_32); +} + + + diff --git a/kernel/fiasco/src/kern/ia32/32/crt0.S b/kernel/fiasco/src/kern/ia32/32/crt0.S new file mode 100644 index 00000000..11e7694f --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/32/crt0.S @@ -0,0 +1,14 @@ +/* -*- c -*- */ + + .globl _start +_start: + addl $4,%esp /* throw away return address */ + /* Clear the base pointer so that stack backtraces will work. */ + xorl %ebp,%ebp + leal _stack_end,%esp + call __main + /* never returns */ + + .bss + .space 2048 +_stack_end: diff --git a/kernel/fiasco/src/kern/ia32/32/entry-native.S b/kernel/fiasco/src/kern/ia32/32/entry-native.S new file mode 100644 index 00000000..d61d0610 --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/32/entry-native.S @@ -0,0 +1,312 @@ + +#include "config_tcbsize.h" +#include "config_gdt.h" +#include "globalconfig.h" +#include "idt_init.h" +#include +#include "regdefs.h" +#include "shortcut.h" +#include "tcboffset.h" + +.macro PRE_FAST_ALIEN_IPC + btrl $17, OFS__THREAD__STATE (%ebx) /* Thread_dis_alien */ + jc 1f + RESTORE_STATE + popl %eax + andl $0x7f,4(%esp) + orl $EFLAGS_IF,8(%esp) + pushl $(0x30 << 3 | 2) + pushl $(0xd) + pusha + /* emulate entry code in KIP */ + mov 40(%esp), %ebp /* offset 40: eip */ + mov %ebp, 16(%esp) /* offset 16: ebx */ + movl $(VAL__MEM_LAYOUT__SYSCALLS + 4f - 3f), 40(%esp) + mov 52(%esp), %ebp /* offset 52: sp */ + mov %ebp, 8(%esp) /* offset 8: ebp */ + jmp slowtraps +3: /* must be the same code as code before sysenter in syscall-page.... */ + pop %ebx + mov %esp, %ebp +4: /* the code between 3 and 4 shall never be executed, it is just to calculate + * the offset for the sysenter insn in the KIP / syscall page + */ +1: /* do alien IPC and raise a trap afterwards */ + RESET_THREAD_CANCEL_AT %ebx +.endm + +.macro POST_FAST_ALIEN_IPC + RESTORE_STATE_AFTER_IPC + popl %eax + andl $0x7f,4(%esp) + orl $EFLAGS_IF, 8(%esp) + pushl $(0x30 << 3 | 6) + pushl $(0xd) + pusha + jmp slowtraps +.endm + + .p2align 4 + .globl entry_vec01_debug +entry_vec01_debug: + /* Check whether user entered the kernel with TF enabled, + * check priv-level to verify that a priv-change happened */ + testb $3, 4(%esp) + jnz 1f + cmpl $entry_sys_fast_ipc_c, (%esp) + je 2f +#if defined(CONFIG_JDB) + cmpl $entry_sys_fast_ipc_log, (%esp) + je 2f +#endif +1: pushl $0 + pushl $1 + pusha + jmp slowtraps + + +2: mov 12(%esp), %esp + pushl $(GDT_DATA_USER|SEL_PL_U) + push %ebp + pushl $(EFLAGS_IOPL_U|EFLAGS_IF|EFLAGS_TF) + pushl $(GDT_CODE_USER|SEL_PL_U) + push %ebx + cld + + pushl %eax + pushl $0 // %ebp + pushl $0 // %ebx + pushl %edi + pushl %esi + pushl %edx + pushl %ecx + + ESP_TO_TCB_AT %ebx + testl $Thread_alien_or_vcpu_user, OFS__THREAD__STATE (%ebx) + jnz dbg_alien_sys_fast_ipc_log + RESET_THREAD_CANCEL_AT %ebx + call *syscall_table + CHECK_SANITY $3 /* scratches ecx */ + RESTORE_STATE_AFTER_IPC + popl %eax + iret + +dbg_alien_sys_fast_ipc_log: + PRE_FAST_ALIEN_IPC + push $ret_from_fast_alien_ipc + jmp *syscall_table + + + + + .globl entry_vec0a_invalid_tss +entry_vec0a_invalid_tss: + andl $0xffffbfff, 12(%esp) + addl $4, %esp /* skip error code */ + iret + + + .globl entry_vec08_dbf +entry_vec08_dbf: +#if 0 /* XXX: disable debug feature reset on double fault */ + testl $0xffffffff,CPU_DEBUGCTL_BUSY + jnz thread_handle_double_fault + SAVE_SCRATCH + movl CPU_DEBUGCTL_RESET, %eax + xorl %edx, %edx + movl $0x1d9,%ecx + wrmsr + RESTORE_SCRATCH +#endif + jmp thread_handle_double_fault + + +/* PPro spurious interrupt bug: + * See "Pentium Pro Processor Specification Update / January 1999" + * Erratum "Virtual Wire mode through local APIC may cause int 15" + * This exception can be silently ignored */ + .p2align(4) + .globl entry_vec0f_apic_spurious_interrupt_bug +entry_vec0f_apic_spurious_interrupt_bug: + pushl %ecx + pushl %edx + incl apic_spurious_interrupt_bug_cnt + popl %edx + popl %ecx + iret + +/* APIC error interrupt */ + .p2align(4) + .globl entry_apic_error_interrupt +entry_apic_error_interrupt: + cld + SAVE_SCRATCH + leal SCRATCH_REGISTER_SIZE(%esp), %eax /* &Return_frame */ + call apic_error_interrupt + RESTORE_SCRATCH + iret + +/* Intel Architecture Software Developer's Manual Volume 3, + * Advanced Programmable Interrupt Controller (APIC): + * Spurious Interrupt: "If at the time the INTA cycle is issued, the + * interupt that was to be dispensed has become masked (programmed by + * software), the local APIC will deliver a spurious-interrupt vector." */ + .p2align(4) + .globl entry_apic_spurious_interrupt +entry_apic_spurious_interrupt: + pushl %ecx + pushl %edx + incl apic_spurious_interrupt_cnt + popl %edx + popl %ecx + iret + + .p2align(4) + .global entry_int_apic_ignore +entry_int_apic_ignore: + pushl %ecx + pushl %edx + mov apic_io_base, %ecx + mov 0xf0(%ecx), %edx + movl $0, 0xb0(%ecx) + popl %edx + popl %ecx + iret + +#if defined(CONFIG_JDB) + + .p2align(4) + .global entry_sys_fast_ipc_log +entry_sys_fast_ipc_log: + pop %esp + pushl $(GDT_DATA_USER|SEL_PL_U) /* user ss */ + pushl %ebp // user esp + // Fake user eflags, set IOPL to 3 + pushl $(EFLAGS_IOPL_U | EFLAGS_IF) + cld + // Fake user cs. This cs value is never used with exception + // that the thread is ex_regs'd before we leave with sysexit. + // lthread_ex_regs has to check user cs for that value. If + // it is faked, the thread would leave the kernel by sysexit + // and the thread is in the slow ipc path. Sysexit would + // adapt the user eip (by subtracting 2) to ensure the user + // executes the "mov %ebp,%edx" sequence. This is wrong if + // the thread is ex_regs'd. In that case, we modify the return + // value from "call dispatch_syscall" to an alternate exit + // path using "iret". + pushl $(GDT_CODE_USER|SEL_PL_U|0x80) /* user cs */ + pushl %ebx /* user eip */ + + pushl %eax + pushl $0 // %ebp + pushl $0 // %ebx + pushl %edi + pushl %esi + pushl %edx + pushl %ecx + + ESP_TO_TCB_AT %ebx + testl $Thread_alien_or_vcpu_user, OFS__THREAD__STATE (%ebx) + jnz alien_sys_fast_ipc_log + RESET_THREAD_CANCEL_AT %ebx + call *syscall_table +in_slow_ipc5: + DO_SYSEXIT + +alien_sys_fast_ipc_log: + PRE_FAST_ALIEN_IPC + push $ret_from_fast_alien_ipc + jmp *syscall_table + + .globl in_slow_ipc5 + +#endif // CONFIG_JDB + + +#if (defined (CONFIG_JDB_LOGGING) || !defined(CONFIG_ASSEMBLER_IPC_SHORTCUT)) + .p2align(4) + .global entry_sys_fast_ipc_c +entry_sys_fast_ipc_c: + pop %esp + pushl $(GDT_DATA_USER|SEL_PL_U) /* user ss */ + pushl %ebp // push user SP (get in ebp) + // Fake user eflags, set IOPL to 3 + pushl $(EFLAGS_IOPL_U | EFLAGS_IF) + cld + // Fake user cs. This cs value is never used with exception + // that the thread is ex_regs'd before we leave with sysexit. + // lthread_ex_regs has to check user cs for that value. If + // it is faked, the thread would leave the kernel by sysexit + // and the thread is in the slow ipc path. Sysexit would + // adapt the user eip (by subtracting 2) to ensure the user + // executes the "mov %ebp,%edx" sequence. This is wrong if + // the thread is ex_regs'd. In that case, we modify the return + // value from "call dispatch_syscall" to an alternate exit + // path using "iret". + pushl $(GDT_CODE_USER|SEL_PL_U|0x80) /* user cs */ + pushl %ebx // push user return address + + pushl %eax + pushl $0 // ebp + pushl $0 // %ebx + pushl %edi + pushl %esi + pushl %edx + pushl %ecx /* save ecx */ + ESP_TO_TCB_AT %ebx + testl $Thread_alien_or_vcpu_user, OFS__THREAD__STATE (%ebx) + jnz alien_sys_fast_ipc_c + RESET_THREAD_CANCEL_AT %ebx + call sys_ipc_wrapper +in_sc_ipc2: + DO_SYSEXIT +#endif + + .globl alien_sys_fast_ipc_c /* Also used in shortcut */ + .global ret_from_fast_alien_ipc /* used in ex-regs */ +/* ex-regs patches the return address of the call to the 'sys_ipc' function + * in the case of sysenter, because we need to leave the kernel by iret + * to prevent the need of user-level trampoline code. + * In the case of alien ipc there must be a special case because otherwise the + * second alien exception is not generated. Therefore ex-regs uses + * 'ret_from_fast_alien_ipc' to determine this case and patches the return + * address with 'leave_alien_from_sysenter_by_iret' instead of + * 'leave_from_sysenter_by_iret'. (see Thread::user_ip in thread-ia32-ux.cpp) + */ + + +alien_sys_fast_ipc_c: + cld + PRE_FAST_ALIEN_IPC + call sys_ipc_wrapper +ret_from_fast_alien_ipc: + POST_FAST_ALIEN_IPC + + .globl in_sc_ipc2 + +.macro LEAVE_SE_BY_IRET + ESP_TO_TCB_AT %ebx + RESET_THREAD_IPC_MASK_AT %ebx + RESTORE_STATE_AFTER_IPC + popl %eax + orl $EFLAGS_IF, 8(%esp) +.endm + + .p2align(4) + .globl leave_from_sysenter_by_iret +leave_from_sysenter_by_iret: + LEAVE_SE_BY_IRET + iret + + .globl leave_alien_from_sysenter_by_iret +leave_alien_from_sysenter_by_iret: + LEAVE_SE_BY_IRET + pushl $(0x30 << 3 | 6) + pushl $(0xd) + pusha + jmp slowtraps + + .bss + .space 4096 + .global dbf_stack_top +dbf_stack_top: diff --git a/kernel/fiasco/src/kern/ia32/32/entry-ux.S b/kernel/fiasco/src/kern/ia32/32/entry-ux.S new file mode 100644 index 00000000..1453a723 --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/32/entry-ux.S @@ -0,0 +1,11 @@ + + /* dummy functions to make the linker happy, they are never used */ + .globl leave_from_sysenter_by_iret +leave_from_sysenter_by_iret: + .globl entry_sys_fast_ipc +entry_sys_fast_ipc: + .globl entry_sys_fast_ipc_log +entry_sys_fast_ipc_log: + .globl entry_sys_fast_ipc_c +entry_sys_fast_ipc_c: + diff --git a/kernel/fiasco/src/kern/ia32/32/entry.S b/kernel/fiasco/src/kern/ia32/32/entry.S new file mode 100644 index 00000000..8fbe1db9 --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/32/entry.S @@ -0,0 +1,676 @@ +/* + * This file contains a 'gate_init' initialization table + * to initialize the x86 processor trap vectors to default entrypoints. + * These entrypoints simply push a standard trap_state frame + * and jump to the 'trap_handler' routine. + */ + +#include "config_tcbsize.h" +#include "config_gdt.h" +#include "globalconfig.h" +#include "idt_init.h" +#include +#include "shortcut.h" +#include "tcboffset.h" +#include "regdefs.h" + +#include "asm.h" + +/* We make the trap handler an interrupt gate, because for debugging + purposes, we don't want any interrupts to occur until they're + explicitly enabled in the base_trap_handler (usually + Thread::handle_slow_trap). */ + +/* + * No error code. Clear error code and push trap number. + */ +#define EXCEPTION(n,name) \ + GATE_ENTRY(n,entry_##name,ACC_PL_K | ACC_INTR_GATE) ;\ + .p2align 3 ;\ +entry_##name: ;\ + pushl $(0) ;\ + pushl $(n) ;\ + pusha ;\ + jmp _slowtraps + +/* + * User-accessible exception. Otherwise, same as above. + */ +#define EXCEP_USR(n,name) \ + GATE_ENTRY(n,entry_##name,ACC_PL_U | ACC_INTR_GATE) ;\ + .p2align 3 ;\ +entry_##name: ;\ + pushl $(0) ;\ + pushl $(n) ;\ + pusha ;\ + jmp _slowtraps + +/* + * Error code has been pushed. Just push trap number. + */ +#define EXCEP_ERR(n,name) \ + GATE_ENTRY(n,entry_##name,ACC_PL_K | ACC_INTR_GATE) ;\ + .p2align 3 ;\ +entry_##name: ;\ + pushl $(n) ;\ + pusha ;\ + jmp _slowtraps + +.macro PRE_ALIEN_IPC + btrl $17, OFS__THREAD__STATE (%ebx) /* Thread_dis_alien */ + jc 1f + RESTORE_STATE + sub $2, 4(%esp) /* Correct EIP to point to insn */ + popl %eax + pushl $(0x30 << 3 | 2) + pushl $(0xd) + pusha + jmp _slowtraps + +1: /* do alien IPC and raise a trap afterwards */ + RESET_THREAD_CANCEL_AT %ebx +.endm + +.macro POST_ALIEN_IPC + CHECK_SANITY $3 /* scratches ecx */ + RESTORE_STATE_AFTER_IPC + popl %eax + pushl $(0x30 << 3 | 6) + pushl $(0xd) + pusha + jmp _slowtraps +.endm + +GATE_INITTAB_BEGIN(idt_init_table) + +EXCEPTION(0x00,vec00_zero_div) +#ifdef CONFIG_PF_UX +EXCEPTION(0x01,vec01_debug) +#else +/* IA32 has to handle breakpoint exceptions if occured exactly at + entry_sys_fast_ipc -- see ia32/entry-ia32.S */ +GATE_ENTRY(0x01,entry_vec01_debug,ACC_PL_K | ACC_INTR_GATE) +#endif +/* XXX IA32 has to handle NMI occured exactly at entry_sys_fast_ipc */ +EXCEP_USR(0x02,vec02_nmi) +EXCEP_USR(0x03,vec03_breakpoint) +EXCEP_USR(0x04,vec04_into) +EXCEP_USR(0x05,vec05_bounds) +EXCEPTION(0x06,vec06_invop) +/* EXCEPTION(0x07,nofpu) */ +#ifdef CONFIG_PF_UX +EXCEP_ERR(0x08,vec08_dbl_fault) +#else +GATE_ENTRY(0x08, GDT_TSS_DBF, ACC_PL_K | ACC_TASK_GATE) +#endif +EXCEPTION(0x09,vec09_fpu_ovfl) +/* EXCEP_ERR(0x0a,vec0a_inv_tss) */ +EXCEP_ERR(0x0b,vec0b_segnp) +EXCEP_ERR(0x0c,vec0c_stack_fault) +EXCEP_ERR(0x0d,vec0d_gen_prot) +/* EXCEP_ERR(0x0e,vec0e_page_fault) */ +/* EXCEPTION(0x0f,vec0f_trap_0f) */ +EXCEPTION(0x10,vec10_fpu_err) +EXCEP_ERR(0x11,vec11_align) +EXCEPTION(0x12,vec12_mcheck) +EXCEPTION(0x13,vec13_simd_err) + + + .p2align 4 + .type slowtraps,@function + .globl slowtraps + /* We have to introduce the label _slowtraps besides the label + slowtraps to achive that jmps from exception entry points + are optimized to two-byte jmps. The label slowtraps is visible + from outside. */ +_slowtraps: +slowtraps: +#ifdef CONFIG_PF_UX +# define REG_GS CPU_GS +# define REG_FS CPU_FS +#else +# define REG_GS %gs +# define REG_FS %fs +#endif + + pushl REG_FS /* we save the segment regs in the trap */ + pushl REG_GS /* state, but we do not restore them. We */ + pushl %ds /* rather reload them using */ + pushl %es /* RESET_{KERNEL,USER}_SEGMENTS */ + + cld + + /* Load the kernel's segment registers. */ + RESET_KERNEL_SEGMENTS_FORCE_DS_ES /* scratches ecx, edx */ + + /* Note: we do not use RESET_THREAD_CANCEL_* here as that is + needed only when an I/O-page-fault IPC is sent and when the + thread is killed. Resetting Thread_cancel here could + be harmful when using this trap handler in debugging. + Instead, we clear this flag in Thread::handle_slow_trap() + just before sending the IPC message or before killing the + thread. That's OK, because it is still atomic -- we never + enable IRQs (sti) before that point. */ + + movl %esp,%eax /* ARG1: address of trap_state */ + xorl %edx,%edx /* ARG2: default CPU = 0 */ +#ifndef CONFIG_NO_FRAME_PTR + pushl 56(%esp) /* create artificial stack frame */ + pushl %ebp + leal (%esp),%ebp +#endif + + /* Call the C handler function if one has been installed. */ + movl BASE_TRAP_HANDLER, %ecx + orl %ecx,%ecx + jz unexpected_trap_pop + call *%ecx +in_slowtrap: + +#ifndef CONFIG_NO_FRAME_PTR + leal 8(%esp),%esp +#endif + + /* If the handler function returned zero (success), + then resume execution as if the trap never happened. + Otherwise, just panic. */ + orl %eax,%eax + jnz unexpected_trap + + CHECK_SANITY 60(%esp) /* scratches ecx */ + + addl $4*2,%esp /* Pop ds, es segment registers */ + popl REG_GS + popl REG_FS /* Restore segment registers */ + popa + addl $4*2,%esp /* Pop trap number and error code */ + iret + +unexpected_trap_pop: +#ifndef CONFIG_NO_FRAME_PTR + leal 8(%esp), %esp +#endif + +unexpected_trap: + movw %ss,%ax + movw %ax,%ds + movw %ax,%es + movl %esp,%eax + call trap_dump_panic + +GATE_ENTRY(0x0e,entry_vec0e_page_fault,ACC_PL_K | ACC_INTR_GATE) + +/* we must save %cr2 before we can be preempted -- therefore we're an + interrupt gate (invoked with interrupts turned off). Also, we + don't turn them on again here, but only after checking for + page-ins from the global page directory in thread_page_fault(). + XXX: If you make changes to stack layout here, fix thread_page_fault */ + +/* XXX slow version - sets up nice stack frame for debugger */ + + .p2align 4 + .type entry_vec0e_page_fault,@function +entry_vec0e_page_fault: + cld + SAVE_SCRATCH + RESET_KERNEL_SEGMENTS_FORCE_DS_ES + movl 12(%esp),%edx /* save error code in ARG2 ... */ + movl PAGE_FAULT_ADDR,%eax /* save page fault address in ARG1 */ + +/* We must reset the cancel flag here atomically + if we are entering fresh from user mode and an IPC might occur. + NOTE: We cannot test the user-mode bit in the error code because + it will flag "kernel" in case an I/O-bitmap page is not mapped + during an I/O access. */ + + movl 20(%esp),%ecx /* get CS from stack */ + andb $3,%cl /* retrieve current privilege level (CPL) */ + jz 1f /* CPL == 0 -> kernel, skip resetting state */ + ESP_TO_TCB_AT %ecx + RESET_THREAD_CANCEL_AT %ecx +1: movl %ebp,12(%esp) /* save frame pointer */ + leal 12(%esp),%ebp /* load new frame pointer */ + pushl %eax /* save pf address */ + pushl %edx /* save error code */ + leal 24(%esp),%ecx /* ARG5: ptr to Return_frame */ + pushl %ecx + pushl 36(%esp) /* ARG4: eflags */ + movl 32(%esp),%ecx /* ARG3: eip */ + call thread_page_fault +in_page_fault: + + orl %eax,%eax + jz bad_page_fault + lea 16(%esp),%esp + CHECK_SANITY 20(%esp) /* scratches ecx */ + RESTORE_SCRATCH + popl %ebp + iret + +/* recover from a bad page fault by invoking the slow_trap handler */ + .p2align 4 +bad_page_fault: + cli + addl $8,%esp /* pop ARG4 and ARG5 */ + movl (%ebp),%eax /* old ebp */ + popl (%ebp) /* error code */ + popl %edx /* page fault address */ + movl %eax,%ebp + + /* we have on stack: error code, eax, ecx, edx + move registers down to make room for trap number */ + subl $4,%esp + movl 4(%esp),%eax + movl %eax,(%esp) + movl 8(%esp),%eax + movl %eax,4(%esp) + movl 12(%esp),%eax + movl %eax,8(%esp) + movl $0x0e,12(%esp) /* error code */ + pushl %ebx /* rest of trap state */ + pushl %edx /* page fault address */ + pushl %ebp + pushl %esi + pushl %edi + jmp slowtraps + + +/* FPU not available in this context. */ +GATE_ENTRY(0x07,entry_vec07_fpu_unavail, ACC_PL_K | ACC_INTR_GATE) + +/* do all of this with disabled interrupts */ + .p2align 4 + .type entry_vec07_fpu_unavail,@function +entry_vec07_fpu_unavail: + cld + SAVE_SCRATCH + call thread_handle_fputrap +in_handle_fputrap: + CHECK_SANITY 16(%esp) /* scratches ecx */ + test %eax, %eax + jz real_fpu_exception + RESTORE_SCRATCH + iret +real_fpu_exception: + RESTORE_SCRATCH + pushl $(0) + pushl $(7) + pusha + jmp _slowtraps + + +/* timer interrupt */ +#ifdef CONFIG_SCHED_PIT +GATE_ENTRY(0x20,entry_int_timer,ACC_PL_K | ACC_INTR_GATE) +#endif +#ifdef CONFIG_SCHED_RTC +GATE_ENTRY(0x28,entry_int_timer,ACC_PL_K | ACC_INTR_GATE) +#endif +#ifdef CONFIG_SCHED_APIC +GATE_ENTRY(APIC_IRQ_BASE, entry_int_timer,ACC_PL_K | ACC_INTR_GATE) +#endif +#ifdef CONFIG_SCHED_HPET +/* HPET is set at startup */ +#endif + + .p2align 4 + .globl entry_int_timer +entry_int_timer: +#ifndef CONFIG_NO_FRAME_PTR + pushl %ebp + movl %esp,%ebp +#endif + SAVE_SCRATCH +do_timer_interrupt: + cld +#ifdef CONFIG_NO_FRAME_PTR + movl 12(%esp), %eax /* ARG1: eip for logging */ +#else + movl 16(%esp), %eax /* ARG1: eip for logging */ +#endif + call thread_timer_interrupt /* enter with disabled irqs */ +in_timer_interrupt: +#ifndef CONFIG_NO_FRAME_PTR + CHECK_SANITY 20(%esp) /* scratches ecx */ +#else + CHECK_SANITY 16(%esp) /* scratches ecx */ +#endif + RESTORE_SCRATCH +#ifndef CONFIG_NO_FRAME_PTR + popl %ebp +#endif + iret + + .p2align 4 + .globl entry_int_timer_slow +entry_int_timer_slow: +#ifndef CONFIG_NO_FRAME_PTR + pushl %ebp + movl %esp,%ebp +#endif + SAVE_SCRATCH + cld + + call thread_timer_interrupt_slow /* enter with disabled irqs */ +in_timer_interrupt_slow: + jmp do_timer_interrupt + + + .p2align 4 + .globl entry_int_timer_stop +entry_int_timer_stop: +#ifndef CONFIG_NO_FRAME_PTR + pushl %ebp + movl %esp,%ebp +#endif + SAVE_SCRATCH + cld + call thread_timer_interrupt_stop +#ifndef CONFIG_NO_FRAME_PTR + CHECK_SANITY 20(%esp) /* scratches ecx */ +#else + CHECK_SANITY 16(%esp) /* scratches ecx */ +#endif + RESTORE_SCRATCH +#ifndef CONFIG_NO_FRAME_PTR + popl %ebp +#endif + iret + + +/* other interrupts */ + +#define INTERRUPT(int,name) \ + GATE_ENTRY(int,entry_##name,ACC_PL_K | ACC_INTR_GATE) ;\ + .p2align 3 ;\ +entry_##name: ;\ + pushl %eax ;\ + movl $ (int - 0x20), %eax /* ARG1: irqnum */ ;\ + jmp all_irqs + +#ifndef CONFIG_SCHED_PIT +INTERRUPT(0x20,int0) +#endif +/* spurious IRQ handlers */ +GATE_ENTRY(0x27,entry_int_pic_ignore,ACC_PL_K | ACC_INTR_GATE) +GATE_ENTRY(0x2f,entry_int_pic_ignore,ACC_PL_K | ACC_INTR_GATE) +#ifndef CONFIG_SCHED_RTC +INTERRUPT(0x28,int8) +#endif + + .p2align 4 + .type all_irqs,@function + .type __generic_irq_entry,@function + .global __generic_irq_entry +all_irqs: +__generic_irq_entry: + cld + pushl %edx + pushl %ecx + movl 12(%esp), %edx /* ARG2: eip */ + call irq_interrupt /* enter with disabled irqs */ +in_interrupt: + CHECK_SANITY 16(%esp) /* scratches ecx */ + popl %ecx + popl %edx + popl %eax + +entry_int_pic_ignore: + iret + + .global entry_int_pic_ignore + .global entry_int7 + .global entry_intf + +/****************************************************************************/ +/* system calls */ +/****************************************************************************/ + +#ifdef CONFIG_ASSEMBLER_IPC_SHORTCUT +GATE_ENTRY(0x30,entry_sys_ipc,ACC_PL_U | ACC_INTR_GATE); +#else +GATE_ENTRY(0x30,entry_sys_ipc_c,ACC_PL_U | ACC_INTR_GATE); +#endif + +#if defined (CONFIG_JDB_LOGGING) || !defined(CONFIG_ASSEMBLER_IPC_SHORTCUT) + .p2align 4 + .globl entry_sys_ipc_c +entry_sys_ipc_c: + cld + pushl %eax + SAVE_STATE + ESP_TO_TCB_AT %ebx + testl $Thread_alien_or_vcpu_user, OFS__THREAD__STATE (%ebx) + jnz alien_sys_ipc_c + RESET_THREAD_CANCEL_AT %ebx + call sys_ipc_wrapper //ipc_short_cut_wrapper +in_sc_ipc1: + CHECK_SANITY $3 /* scratches ecx */ + RESTORE_STATE_AFTER_IPC + popl %eax + iret + + .globl in_sc_ipc1 +#endif + +#ifdef CONFIG_JDB + /* The slow variant of sys_ipc_entry is used when logging IPC */ + .p2align 4 + .globl entry_sys_ipc_log +entry_sys_ipc_log: + cld + pushl %eax + SAVE_STATE + ESP_TO_TCB_AT %ebx + testl $Thread_alien_or_vcpu_user, OFS__THREAD__STATE (%ebx) + jnz alien_sys_ipc_log + RESET_THREAD_CANCEL_AT %ebx + call *syscall_table +in_slow_ipc4: + CHECK_SANITY $3 /* scratches ecx */ + RESTORE_STATE_AFTER_IPC + popl %eax + iret + + .globl in_slow_ipc4 +#endif // CONFIG_JDB + + // these labels help show_tcb to guess the thread state + .globl in_syscall + .globl in_slowtrap + .globl in_page_fault + .globl in_handle_fputrap + .globl in_interrupt + .globl in_timer_interrupt + .globl in_timer_interrupt_slow + +#define SYSTEM_CALL(int,name) \ + GATE_ENTRY(int,entry_##name,ACC_PL_U | ACC_INTR_GATE) ;\ + .p2align 3 ;\ +entry_##name: ;\ + pushl %eax ;\ + movl $(syscall_table+4*(int-0x30)), %eax ;\ + jmp all_syscalls + + .p2align 4 + .type all_syscalls,@function +all_syscalls: + SAVE_STATE ;\ + cld + ESP_TO_TCB_AT %ebx + testl $Thread_alien_or_vcpu_user, OFS__THREAD__STATE (%ebx) + jnz alien_sys_call + RESET_THREAD_CANCEL_AT %ebx + call *(%eax) /* interrupts enabled in wrappers */ +in_syscall: + +ret_from_syscall: + CHECK_SANITY $3 /* scratches ecx */ + RESTORE_STATE + popl %eax + iret + + +SYSTEM_CALL(0x32,sys_invoke_debug) + +#ifndef CONFIG_PF_UX +/* these functions are implemented in entry-native.S */ +GATE_ENTRY(0x0a,entry_vec0a_invalid_tss,ACC_PL_K | ACC_INTR_GATE) +GATE_ENTRY(0x0f,entry_vec0f_apic_spurious_interrupt_bug,ACC_PL_K | ACC_INTR_GATE) +GATE_ENTRY(APIC_IRQ_BASE + 3,entry_apic_error_interrupt,ACC_PL_K | ACC_INTR_GATE) +GATE_ENTRY(APIC_IRQ_BASE + 0xf,entry_apic_spurious_interrupt,ACC_PL_K | ACC_INTR_GATE) +#endif + +#ifdef CONFIG_MP +GATE_ENTRY(APIC_IRQ_BASE + 2, entry_ipi, ACC_PL_K | ACC_INTR_GATE) +GATE_ENTRY(APIC_IRQ_BASE - 2, entry_debug_ipi, ACC_PL_K | ACC_INTR_GATE) +GATE_ENTRY(APIC_IRQ_BASE - 1, entry_ipi_remote_request, ACC_PL_K | ACC_INTR_GATE) +#endif + +GATE_INITTAB_END + + .globl alien_sys_ipc_c /* Also used in shortcut */ +alien_sys_ipc_c: + cld + PRE_ALIEN_IPC + call sys_ipc_wrapper + POST_ALIEN_IPC + +#if defined (CONFIG_JDB) +alien_sys_ipc_log: + cld + PRE_ALIEN_IPC + call *syscall_table + POST_ALIEN_IPC +#endif + +/* + * input: eax: address to syscall function + * output: eax: error code + */ +.macro SC_ADDR_TO_ERR val + sub $syscall_table , %eax /* eax = byte offset to syscall */ + shr $2, %eax /* convert eax to syscall nr */ + add $0x30, %eax /* convert eax to syscall int nr */ + shl $3, %eax /* construct error code */ + orl $\val, %eax /* -"- */ +.endm + +alien_sys_call: + btrl $17, OFS__THREAD__STATE (%ebx) /* Thread_dis_alien */ + jc 1f + RESTORE_STATE + sub $2, 4(%esp) /* Correct EIP to point to insn */ + SC_ADDR_TO_ERR 2 +2: pushl $0xd + xchgl 4(%esp), %eax + pusha + jmp _slowtraps + +1: /* do alien syscall and trap afterwards */ + RESET_THREAD_CANCEL_AT %ebx + pushl %eax + call *(%eax) /* call with ENABLED interrupts */ + cli + CHECK_SANITY $3 /* scratches ecx */ + popl %eax + RESTORE_STATE + SC_ADDR_TO_ERR 6 + jmp 2b + + + .p2align + .globl leave_by_trigger_exception +leave_by_trigger_exception: + cli + subl $12,%esp /* clean up stack from previous + * CPL0-CPL0 iret */ + SAVE_SCRATCH + call thread_restore_exc_state + RESTORE_SCRATCH + pushl $0x00 + pushl $0xff + pusha + jmp _slowtraps + + .p2align + .globl leave_by_vcpu_upcall +leave_by_vcpu_upcall: + cli + subl $12,%esp /* clean up stack from previous + * CPL0-CPL0 iret */ + SAVE_SCRATCH + call thread_restore_exc_state + + ESP_TO_TCB_AT %ecx + mov OFS__THREAD__USER_VCPU(%ecx), %eax /* vcpu state pointer from TCB */ + mov OFS__THREAD__VCPU_STATE(%ecx), %ecx /* vcpu state pointer from TCB */ + addl $(VAL__SIZEOF_TRAP_STATE - 20), %ecx /* skip return frame */ + mov SCRATCH_REGISTER_SIZE(%esp), %edx + mov %edx, (%ecx) /* EIP */ + mov 8 + SCRATCH_REGISTER_SIZE(%esp), %edx + mov %edx, 8(%ecx) /* EFLAGS */ + mov 12 + SCRATCH_REGISTER_SIZE(%esp), %edx + mov %edx, 12(%ecx) /* ESP */ + mov 16 + SCRATCH_REGISTER_SIZE(%esp), %edx + mov %edx, 16(%ecx) /* SS */ + + mov 0(%esp), %edx /* EDX */ + mov %edx, -20(%ecx) + mov 4(%esp), %edx /* ECX */ + mov %edx, -16(%ecx) + mov 8(%esp), %edx /* EAX */ + mov %edx, -12(%ecx) + + lea 12(%esp), %edx + lea -20(%ecx), %esp + + push %ebx /* EBX */ + sub $4, %esp /* SKIP PFA */ + push %ebp /* EBP */ + push %esi /* ESI */ + push %edi /* EDI */ + + /*add SCRATCH_REGISTER_SIZE, %esp*/ + + pushl REG_FS /* we save the segment regs in the trap */ + pushl REG_GS /* state, but we do not restore them. We */ + pushl %ds /* rather reload them using */ + pushl %es /* RESET_{KERNEL,USER}_SEGMENTS */ + + mov %edx, %esp + mov -VAL__SIZEOF_TRAP_STATE + 20 + OFS__VCPU_STATE__ENTRY_SP(%ecx), %edx + mov %edx, 12(%esp) + mov -VAL__SIZEOF_TRAP_STATE + 20 + OFS__VCPU_STATE__ENTRY_IP(%ecx), %edx + mov %edx, 0(%esp) + movl $EFLAGS_IF, 8(%esp) + iret + + .p2align + .globl vcpu_resume +vcpu_resume: + mov %eax, %esp + addl $(2*4), %esp // skip es and ds for now + //popl %es + //popl %ds + popl REG_GS + popl REG_FS + popa + addl $(2*4), %esp + iret + + // fast return from Dirq::hit + .align 16 + .globl fast_ret_from_irq +fast_ret_from_irq: + CHECK_SANITY $3 // scratches ecx + RESTORE_STATE_AFTER_IPC + popl %eax + andl $0x7f, 4(%esp) // if entered using sysenter + orl $EFLAGS_IF, 8(%esp) // if entered using sysenter + iret + + + + + diff --git a/kernel/fiasco/src/kern/ia32/32/entry_frame-ia32-ux.cpp b/kernel/fiasco/src/kern/ia32/32/entry_frame-ia32-ux.cpp new file mode 100644 index 00000000..b2a09123 --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/32/entry_frame-ia32-ux.cpp @@ -0,0 +1,187 @@ +/* + * Fiasco Kernel-Entry Frame-Layout Code + * Shared between UX and native IA32. + */ + +INTERFACE[ia32,ux]: + +#include "types.h" + +EXTENSION class Syscall_frame +{ +protected: + Mword _ecx; + Mword _edx; + Mword _esi; + Mword _edi; + Mword _ebx; + Mword _ebp; + Mword _eax; +}; + +EXTENSION class Return_frame +{ +private: + Mword _eip; + Unsigned16 _cs, __attribute__((unused)) __csu; + Mword _eflags; + Mword _esp; + Unsigned16 _ss, __attribute__((unused)) __ssu; + +public: + enum { Pf_ax_offset = 0 }; +}; + +IMPLEMENTATION[ia32,ux]: + +//--------------------------------------------------------------------------- +// basic Entry_frame methods for IA32 +// +#include "mem_layout.h" + +IMPLEMENT inline +Address +Return_frame::ip() const +{ return _eip; } + +IMPLEMENT inline NEEDS["mem_layout.h"] +Address +Return_frame::ip_syscall_page_user() const +{ + Address eip = ip(); + if ((eip & Mem_layout::Syscalls) == Mem_layout::Syscalls) + eip = *(Mword*)sp(); + return eip; +} + + +IMPLEMENT inline +Address +Return_frame::sp() const +{ return _esp; } + +IMPLEMENT inline +void +Return_frame::sp(Mword sp) +{ _esp = sp; } + +PUBLIC inline +Mword +Return_frame::flags() const +{ return _eflags; } + +PUBLIC inline +void +Return_frame::flags(Mword flags) +{ _eflags = flags; } + +PUBLIC inline +Mword +Return_frame::cs() const +{ return _cs; } + +PUBLIC inline +void +Return_frame::cs(Mword cs) +{ _cs = cs; } + +PUBLIC inline +Mword +Return_frame::ss() const +{ return _ss; } + +PUBLIC inline +void +Return_frame::ss(Mword ss) +{ _ss = ss; } + +//--------------------------------------------------------------------------- +IMPLEMENTATION [ia32,ux]: + +//--------------------------------------------------------------------------- +// IPC frame methods for IA32 +// +IMPLEMENT inline +Mword Syscall_frame::next_period() const +{ return false; } + +IMPLEMENT inline +Mword Syscall_frame::from_spec() const +{ return _esi; } + +IMPLEMENT inline +void Syscall_frame::from(Mword f) +{ _esi = f; } + +IMPLEMENT inline +L4_obj_ref Syscall_frame::ref() const +{ return L4_obj_ref::from_raw(_edx); } + +IMPLEMENT inline +void Syscall_frame::ref(L4_obj_ref const &ref) +{ _edx = ref.raw(); } + +IMPLEMENT inline +L4_timeout_pair Syscall_frame::timeout() const +{ return L4_timeout_pair(_ecx); } + +IMPLEMENT inline +void Syscall_frame::timeout(L4_timeout_pair const &to) +{ _ecx = to.raw(); } + +IMPLEMENT inline Utcb *Syscall_frame::utcb() const +{ return reinterpret_cast(_edi); } + +IMPLEMENT inline L4_msg_tag Syscall_frame::tag() const +{ return L4_msg_tag(_eax); } + +IMPLEMENT inline +void Syscall_frame::tag(L4_msg_tag const &tag) +{ _eax = tag.raw(); } + + +// --------------------------------------------------------------------------- +IMPLEMENTATION [ia32]: + +IMPLEMENT inline +void +Return_frame::ip(Mword ip) +{ + // We have to consider a special case where we have to leave the kernel + // with iret instead of sysexit: If the target thread entered the kernel + // through sysenter, it would leave using sysexit. This is not possible + // for two reasons: Firstly, the sysexit instruction needs special user- + // land code to load the right value into the edx register (see user- + // level sysenter bindings). And secondly, the sysexit instruction + // decrements the user-level eip value by two to ensure that the fixup + // code is executed. One solution without kernel support would be to add + // the instructions "movl %ebp, %edx" just _before_ the code the target + // eip is set to. + if (cs() & 0x80) + { + // this cannot happen in Fiasco UX + /* symbols from the assember entry code */ + extern Mword leave_from_sysenter_by_iret; + extern Mword leave_alien_from_sysenter_by_iret; + extern Mword ret_from_fast_alien_ipc; + Mword **ret_from_disp_syscall = reinterpret_cast(static_cast(this))-1; + cs(cs() & ~0x80); + if (*ret_from_disp_syscall == &ret_from_fast_alien_ipc) + *ret_from_disp_syscall = &leave_alien_from_sysenter_by_iret; + else + *ret_from_disp_syscall = &leave_from_sysenter_by_iret; + } + + _eip = ip; +} + + +// --------------------------------------------------------------------------- +IMPLEMENTATION [ux]: + +IMPLEMENT inline +void +Return_frame::ip(Mword ip) +{ + _eip = ip; +} diff --git a/kernel/fiasco/src/kern/ia32/32/kmem-ia32-32.cpp b/kernel/fiasco/src/kern/ia32/32/kmem-ia32-32.cpp new file mode 100644 index 00000000..fbcd7eca --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/32/kmem-ia32-32.cpp @@ -0,0 +1,13 @@ +IMPLEMENTATION [ia32]: + +PRIVATE static inline FIASCO_INIT_CPU +void +Kmem::init_cpu_arch(Cpu &cpu, void **cpu_mem) +{ + // allocate the task segment for the double fault handler + cpu.init_tss_dbf (__alloc(cpu_mem, sizeof(Tss)), + Mem_layout::pmem_to_phys(Kmem::dir())); + + cpu.init_sysenter(); +} + diff --git a/kernel/fiasco/src/kern/ia32/32/linking.h b/kernel/fiasco/src/kern/ia32/32/linking.h new file mode 100644 index 00000000..c07efce2 --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/32/linking.h @@ -0,0 +1,8 @@ +#pragma once + +#define FIASCO_MP_TRAMP_PAGE 0x1000 // must be below 1MB +#define FIASCO_IMAGE_PHYS_START 0x400000 +//#define FIASCO_IMAGE_PHYS_START 0x2000 +#define FIASCO_IMAGE_VIRT_START 0xf0000000 + +#define FIASCO_IMAGE_PHYS_OFFSET (FIASCO_IMAGE_VIRT_START - (FIASCO_IMAGE_PHYS_START & 0xffc00000)) diff --git a/kernel/fiasco/src/kern/ia32/32/low_level.h b/kernel/fiasco/src/kern/ia32/32/low_level.h new file mode 100644 index 00000000..d2f8746b --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/32/low_level.h @@ -0,0 +1,119 @@ +#ifndef LOW_LEVEL_H +#define LOW_LEVEL_H + +#include "asm.h" +#include "regdefs.h" +#include "shortcut.h" +#include "tcboffset.h" + +#define REGISTER_SIZE 4 + + .macro save_all_regs + pusha + .endm + + .macro restore_all_regs + popa + .endm + +/* be sure that we do not enable the interrupts here! */ + .macro RESTORE_IOPL + pushl 16(%esp) + andl $~EFLAGS_IF,(%esp) + popf + .endm + +/** Some shared macros and stuff shared by the two different + * assembler kernel entry sources. + */ + +/** Setting up ds/es resp. fs/gs when entering/ + * leaving the kernel is not neccessary anymore + * since the user can only load the null selector + * without exception. But then, the first access + * to code/data with the wrong selector loaded + * raises an exception 13 which is handled properly. + */ + .macro RESET_KERNEL_SEGMENTS_FORCE_DS_ES + movw $ (GDT_DATA_USER|SEL_PL_U), %cx + movl %ecx,%ds + movl %ecx,%es + .endm + + .macro DO_SYSEXIT + addl $8, %esp /* skip ecx & edx */ + popl %esi + popl %edi + popl %ebx + //CHECK_SANITY $3 /* scratches ecx */ + RESTORE_IOPL + movl 4(%esp), %eax + movl 8(%esp), %edx /* user eip */ + movl 20(%esp), %ecx /* user esp */ + //subl $2, %edx /* adj. eip */ + sti /* the interrupts are enabled _after_ the + * next instruction (see Intel Ref-Manual) */ + sysexit + .endm + + .macro RESET_THREAD_CANCEL_AT reg + andl $~(Thread_cancel), OFS__THREAD__STATE (\reg) + .endm + + .macro RESET_THREAD_IPC_MASK_AT reg + andl $~Thread_ipc_mask, OFS__THREAD__STATE (\reg) + .endm + + .macro ESP_TO_TCB_AT reg + movl %esp, \reg + andl $~(THREAD_BLOCK_SIZE - 1), \reg + .endm + + .macro SAVE_STATE + pushl %ebp + pushl %ebx + pushl %edi + pushl %esi + pushl %edx + pushl %ecx + .endm + + .macro RESTORE_STATE + popl %ecx + popl %edx + popl %esi + popl %edi + popl %ebx + popl %ebp + .endm + + .macro RESTORE_STATE_AFTER_IPC + addl $4, %esp + popl %edx + popl %esi + popl %edi + popl %ebx + addl $4, %esp + .endm + +#define SCRATCH_REGISTER_SIZE 12 + .macro SAVE_SCRATCH + push %eax + push %ecx + push %edx + .endm + + .macro RESTORE_SCRATCH + pop %edx + pop %ecx + pop %eax + .endm + + .macro IRET_INSN + iret + .endm + +#define PAGE_FAULT_ADDR %cr2 +#define PAGE_DIR_ADDR %cr3 + +#endif //LOW_LEVEL_H diff --git a/kernel/fiasco/src/kern/ia32/32/main-ia32-32.cpp b/kernel/fiasco/src/kern/ia32/32/main-ia32-32.cpp new file mode 100644 index 00000000..f46294c0 --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/32/main-ia32-32.cpp @@ -0,0 +1,78 @@ +/* + * Fiasco ia32 / UX + * Shared main startup/shutdown code + */ + +INTERFACE[ia32,ux]: + +#include "initcalls.h" +#include "std_macros.h" + +class Kernel_thread; + + +IMPLEMENTATION[ia32,ux]: + +#include + +#include "assert_opt.h" +#include "config.h" +#include "cpu.h" +#include "div32.h" +#include "globals.h" +#include "kernel_task.h" +#include "kernel_thread.h" + + +FIASCO_INIT +void +kernel_main(void) +{ + unsigned dummy; + + Cpu const &cpu = *Cpu::boot_cpu(); + + // caution: no stack variables in this function because we're going + // to change the stack pointer! + cpu.print(); + cpu.show_cache_tlb_info(""); + + printf ("\nFreeing init code/data: %lu bytes (%lu pages)\n\n", + (Address)(&Mem_layout::initcall_end - &Mem_layout::initcall_start), + (Address)(&Mem_layout::initcall_end - &Mem_layout::initcall_start + >> Config::PAGE_SHIFT)); + + // Perform architecture specific initialization + main_arch(); + + // create kernel thread + static Kernel_thread *kernel = new (Ram_quota::root) Kernel_thread; + assert_opt (kernel); + Task *const ktask = Kernel_task::kernel_task(); + check(kernel->bind(ktask, User::Ptr(0))); + + // switch to stack of kernel thread and bootstrap the kernel + asm volatile + (" movl %%esi, %%esp \n\t" // switch stack + " call call_bootstrap \n\t" // bootstrap kernel thread + : "=a" (dummy), "=c" (dummy), "=d" (dummy) + : "a"(kernel), "S" (kernel->init_stack())); +} + +//------------------------------------------------------------------------ +IMPLEMENTATION[(ia32 || ux) && mp]: + +#include "kernel_thread.h" + +void +main_switch_ap_cpu_stack(Kernel_thread *kernel) +{ + Mword dummy; + + // switch to stack of kernel thread and bootstrap the kernel + asm volatile + (" movl %%esi, %%esp \n\t" // switch stack + " call call_ap_bootstrap \n\t" // bootstrap kernel thread + : "=a" (dummy), "=c" (dummy), "=d" (dummy) + : "a"(kernel), "S" (kernel->init_stack())); +} diff --git a/kernel/fiasco/src/kern/ia32/32/mapping-ia32-32.cpp b/kernel/fiasco/src/kern/ia32/32/mapping-ia32-32.cpp new file mode 100644 index 00000000..4d07ebeb --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/32/mapping-ia32-32.cpp @@ -0,0 +1,27 @@ +INTERFACE [ia32,ux]: + +#include "types.h" + +class Treemap; + +class Mapping_entry +{ +public: + enum { Alignment = 1 }; + + union + { + struct + { + unsigned long _space:32; ///< Address-space number + unsigned long address:20; ///< Virtual address in address space + } __attribute__((packed)) data; + Treemap *_submap; + } __attribute__((packed)); + Unsigned8 _depth; + + void set_space(Space *s) { data._space = (unsigned long)s; } + Space *space() const { return (Space *)data._space; } +} __attribute__((packed)); + + diff --git a/kernel/fiasco/src/kern/ia32/32/mem_layout-ia32-32.cpp b/kernel/fiasco/src/kern/ia32/32/mem_layout-ia32-32.cpp new file mode 100644 index 00000000..03895c26 --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/32/mem_layout-ia32-32.cpp @@ -0,0 +1,134 @@ +INTERFACE [ia32]: + +#include "types.h" +#include "config.h" +#include "linking.h" +#include "template_math.h" + +EXTENSION class Mem_layout +{ +public: + enum Flags + { + /// Is the adapter memory in the kernel image super page? + Adap_in_kernel_image = FIASCO_IMAGE_PHYS_START < Config::SUPERPAGE_SIZE, + }; + + enum + { + Utcb_addr = 0xbff00000, ///< % 4KB UTCB map address + Kip_auto_map = 0xbfff2000, ///< % 4KB + User_max = 0xc0000000, + Service_page = 0xeac00000, ///< % 4MB global mappings + Local_apic_page = Service_page + 0x0000, ///< % 4KB + Kmem_tmp_page_1 = Service_page + 0x2000, ///< % 4KB size 8KB + Kmem_tmp_page_2 = Service_page + 0x4000, ///< % 4KB size 8KB + Tbuf_status_page = Service_page + 0x6000, ///< % 4KB + Tbuf_ustatus_page = Tbuf_status_page, + Jdb_bench_page = Service_page + 0x8000, ///< % 4KB + Jdb_bts_area = Service_page + 0xf000, ///< % 4KB size 0x81000 + utcb_ptr_align = Tl_math::Ld<64>::Res, // 64byte cachelines + Idt = Service_page + 0xfe000, ///< % 4KB + Syscalls = Service_page + 0xff000, ///< % 4KB syscall page + Tbuf_buffer_area = Service_page + 0x200000, ///< % 2MB + Tbuf_ubuffer_area = Tbuf_buffer_area, + // 0xeb800000-0xec000000 (8MB) free + Io_map_area_start = 0xec000000, + Io_map_area_end = 0xec800000, + __free_4 = 0xec880000, ///< % 4MB + Jdb_debug_start = 0xecc00000, ///< % 4MB JDB symbols/lines + Jdb_debug_end = 0xee000000, ///< % 4MB + // 0xee000000-0xef800000 (24MB) free + Kstatic = 0xef800000, ///< Io_bitmap - 4MB + Io_bitmap = 0xefc00000, ///< % 4MB + Vmem_end = 0xf0000000, + + Kernel_image = FIASCO_IMAGE_VIRT_START, // usually 0xf0000000 + Kernel_image_end = Kernel_image + Config::SUPERPAGE_SIZE, + + Adap_image = Adap_in_kernel_image + ? Kernel_image + : Kernel_image + Config::SUPERPAGE_SIZE, + + Adap_vram_mda_beg = Adap_image + 0xb0000, ///< % 8KB video RAM MDA memory + Adap_vram_mda_end = Adap_image + 0xb8000, + Adap_vram_cga_beg = Adap_image + 0xb8000, ///< % 8KB video RAM CGA memory + Adap_vram_cga_end = Adap_image + 0xc0000, + + Caps_start = 0xf0800000, ///< % 4MB + Caps_end = 0xf3000000, ///< % 4MB == Caps_start + (1<<20) * 4 + Physmem = 0xfc400000, ///< % 4MB kernel memory + }; + + enum Offsets + { + Kernel_image_offset = FIASCO_IMAGE_PHYS_OFFSET, + }; + + enum Phys_addrs + { + Kernel_image_phys = FIASCO_IMAGE_PHYS_START & Config::SUPERPAGE_MASK, + Adap_image_phys = 0, + }; + + template < typename T > static T* boot_data (T const *addr); + + static Address pmem_size; +private: + static Address physmem_offs asm ("PHYSMEM_OFFS"); +}; + +IMPLEMENTATION [ia32]: + +#include +#include + +Address Mem_layout::physmem_offs; +Address Mem_layout::pmem_size; + + +PUBLIC static inline +void +Mem_layout::kphys_base(Address base) +{ + physmem_offs = (Address)Physmem - base; +} + +PUBLIC static inline NEEDS[] +Address +Mem_layout::pmem_to_phys(Address addr) +{ + assert (in_pmem(addr)); + return addr - physmem_offs; +} + +PUBLIC static inline NEEDS[] +Address +Mem_layout::pmem_to_phys(const void *ptr) +{ + Address addr = reinterpret_cast
(ptr); + + assert_kdb (in_pmem(addr)); + return addr - physmem_offs; +} + +PUBLIC static inline +Address +Mem_layout::phys_to_pmem(Address addr) +{ + return addr + physmem_offs; +} + +PUBLIC static inline +Mword +Mem_layout::in_kernel_image(Address addr) +{ + return addr >= Kernel_image && addr < Kernel_image_end; +} + +PUBLIC static inline +Mword +Mem_layout::in_pmem(Address addr) +{ + return addr >= Physmem; +} diff --git a/kernel/fiasco/src/kern/ia32/32/mem_unit-ia32.cpp b/kernel/fiasco/src/kern/ia32/32/mem_unit-ia32.cpp new file mode 100644 index 00000000..e8f3c50e --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/32/mem_unit-ia32.cpp @@ -0,0 +1,35 @@ +INTERFACE[ia32]: + +#include "types.h" + +class Mem_unit +{ +}; + + +IMPLEMENTATION[ia32]: + +/** Flush the whole TLB. + */ +PUBLIC static inline +void +Mem_unit::tlb_flush() +{ + unsigned dummy; + asm volatile ("mov %%cr3,%0; mov %0,%%cr3 " : "=r"(dummy)); +} + + +/** Flush TLB at virtual address. + */ +PUBLIC static inline +void +Mem_unit::tlb_flush(Address addr) +{ + asm volatile ("invlpg %0" : : "m" (*(char*)addr) : "memory"); +} + +PUBLIC static inline +void +Mem_unit::clean_dcache(void *) +{} diff --git a/kernel/fiasco/src/kern/ia32/32/paging-ia32-32.cpp b/kernel/fiasco/src/kern/ia32/32/paging-ia32-32.cpp new file mode 100644 index 00000000..b05eddbc --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/32/paging-ia32-32.cpp @@ -0,0 +1,71 @@ +INTERFACE[ia32,ux]: + +#include +#include "types.h" +#include "config.h" +#include "ptab_base.h" + +class PF {}; + +class Pte_base +{ +public: + typedef Mword Raw; + + enum + { + Super_level = 0, + Valid = 0x00000001, ///< Valid + Writable = 0x00000002, ///< Writable + User = 0x00000004, ///< User accessible + Write_through = 0x00000008, ///< Write through + Cacheable = 0x00000000, ///< Cache is enabled + Noncacheable = 0x00000010, ///< Caching is off + Referenced = 0x00000020, ///< Page was referenced + Dirty = 0x00000040, ///< Page was modified + Pse_bit = 0x00000080, ///< Indicates a super page + Cpu_global = 0x00000100, ///< pinned in the TLB + L4_global = 0x00000200, ///< pinned in the TLB + Pfn = 0xfffff000, ///< page frame number + }; + + Mword addr() const { return _raw & Pfn; } + +protected: + Raw _raw; + +private: + static Unsigned32 _cpu_global; +}; + +class Pt_entry : public Pte_base +{ +public: + enum { Page_shift = Config::PAGE_SHIFT }; + Mword leaf() const { return true; } + void set(Address p, bool intermed, bool present, unsigned long attrs = 0) + { + _raw = (p & Pfn) | (present ? 1 : 0) + | (intermed ? (Writable | User | Cacheable) : 0) | attrs; + } +}; + +class Pd_entry : public Pte_base +{ +public: + enum { Page_shift = Config::SUPERPAGE_SHIFT }; + Mword leaf() const { return _raw & Pse_bit; } + void set(Address p, bool intermed, bool present, unsigned long attrs = 0) + { + _raw = (p & Pfn) | (present ? 1 : 0) + | (intermed ? (Writable | User | Cacheable) : Pse_bit) | attrs; + } +}; + + + +typedef Ptab::List< Ptab::Traits, + Ptab::Traits > Ptab_traits; + +typedef Ptab::Shift::List Ptab_traits_vpn; +typedef Ptab::Page_addr_wrap Ptab_va_vpn; diff --git a/kernel/fiasco/src/kern/ia32/32/sys_call_page-abs-ia32.cpp b/kernel/fiasco/src/kern/ia32/32/sys_call_page-abs-ia32.cpp new file mode 100644 index 00000000..d244f081 --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/32/sys_call_page-abs-ia32.cpp @@ -0,0 +1,70 @@ +/* + * Fiasco Syscall-Page Code (absolute addressing) + */ + +IMPLEMENTATION [ia32-abs_syscalls]: + +#include +#include +#include "config.h" +#include "cpu.h" +#include "kernel_task.h" +#include "mem_layout.h" +#include "panic.h" +#include "paging.h" +#include "space.h" +#include "types.h" +#include "vmem_alloc.h" + +enum +{ + Offs_invoke = 0x000, + Offs_se_invoke = 0x000, + Offs_kip_invoke = 0x800, + Offs_kip_se_invoke = 0x800, + Offs_debugger = 0x200, + Offs_kip_debugger = 0x900, +}; + + +#define INV_SYSCALL(sysc) \ + *reinterpret_cast(Mem_layout::Syscalls + Offs_##sysc) = 0x0b0f + +#define SYSCALL_SYMS(sysc) \ +extern char sys_call_##sysc, sys_call_##sysc##_end + +#define COPY_SYSCALL(sysc) do { \ +memcpy( (char*)Mem_layout::Syscalls + Offs_##sysc, &sys_call_##sysc, \ + &sys_call_##sysc##_end- &sys_call_##sysc ); \ +memcpy( (char*)Kip::k() + Offs_kip_##sysc, &sys_call_##sysc, \ + &sys_call_##sysc##_end- &sys_call_##sysc ); } while (0) + + +IMPLEMENT +void +Sys_call_page::init() +{ + SYSCALL_SYMS(invoke); + SYSCALL_SYMS(se_invoke); + SYSCALL_SYMS(debugger); + + if (!Vmem_alloc::page_alloc((void*)Mem_layout::Syscalls, + Vmem_alloc::ZERO_FILL, Vmem_alloc::User)) + panic("FIASCO: can't allocate system-call page.\n"); + + printf ("Absolute KIP Syscalls using: %s\n", + Cpu::have_sysenter() ? "Sysenter" : "int 0x30"); + + Kip::k()->kip_sys_calls = 2; + + if (Cpu::have_sysenter()) + COPY_SYSCALL(se_invoke); + else + COPY_SYSCALL(invoke); + + COPY_SYSCALL(debugger); + + Kernel_task::kernel_task()->set_attributes( + Mem_space::Addr(Mem_layout::Syscalls), + Page::USER_RO); +} diff --git a/kernel/fiasco/src/kern/ia32/32/sys_call_page-asm.S b/kernel/fiasco/src/kern/ia32/32/sys_call_page-asm.S new file mode 100644 index 00000000..da6e8586 --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/32/sys_call_page-asm.S @@ -0,0 +1,40 @@ + +#include "tcboffset.h" + + .section ".initcall.data","aw" + +sys_call_invoke: + int $0x30 + ret +sys_call_invoke_end: + +sys_call_debugger: + int $0x32 + ret +sys_call_debugger_end: + +sys_call_se_invoke: + pop %ebx + mov %esp, %ebp + sysenter +/* + 0: + push %ecx + subl $4,%esp + pushl $0x1b + pushl $(1f-0b+VAL__MEM_LAYOUT__SYSCALLS) + mov %esp,%ecx + sysenter + mov %ebp,%edx + 1: + ret */ +sys_call_se_invoke_end: + + .global sys_call_invoke + .global sys_call_invoke_end + .global sys_call_debugger + .global sys_call_debugger_end + .global sys_call_se_invoke + .global sys_call_se_invoke_end + + .previous diff --git a/kernel/fiasco/src/kern/ia32/32/tb_entry-ia32-32.cpp b/kernel/fiasco/src/kern/ia32/32/tb_entry-ia32-32.cpp new file mode 100644 index 00000000..ae6aa88a --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/32/tb_entry-ia32-32.cpp @@ -0,0 +1,183 @@ +INTERFACE [ia32,ux]: + +EXTENSION class Tb_entry_base +{ +public: + enum + { + Tb_entry_size = 64, + }; +}; + +/** logged kernel event plus register content. */ +class Tb_entry_ke_reg : public Tb_entry +{ +private: + struct Payload + { + union { + char _msg[18]; ///< debug message + struct { + char _pad[3]; + const char *_m; + } _const_msg __attribute__((packed)); + }; + Mword _eax, _ecx, _edx; ///< registers + } __attribute__((packed)); +}; + +/** logged trap. */ +class Tb_entry_trap : public Tb_entry +{ +private: + struct Payload + { + Unsigned8 _trapno; + Unsigned16 _error; + Mword _ebp, _cr2, _eax, _eflags, _esp; + Unsigned16 _cs, _ds; + } __attribute__((packed)); +}; + +IMPLEMENTATION [ia32,ux]: + +#include "cpu.h" + +PUBLIC inline NEEDS ["cpu.h"] +void +Tb_entry::rdtsc() +{ _tsc = Cpu::rdtsc(); } + + + +PUBLIC inline +void +Tb_entry_ke_reg::set(Context const *ctx, Mword eip, Mword v1, Mword v2, Mword v3) +{ + set_global(Tbuf_ke_reg, ctx, eip); + payload()->_eax = v1; payload()->_ecx = v2; payload()->_edx = v3; +} + +PUBLIC inline NEEDS [] +void +Tb_entry_ke_reg::set(Context const *ctx, Mword eip, Trap_state *ts) +{ set(ctx, eip, ts->value(), ts->value2(), ts->value3()); } + +PUBLIC inline +void +Tb_entry_ke_reg::set_const(Context const *ctx, Mword eip, + const char * const msg, + Mword eax, Mword ecx, Mword edx) +{ + set(ctx, eip, eax, ecx, edx); + payload()->_msg[0] = 0; + payload()->_msg[1] = 1; + payload()->_const_msg._m = msg; +} + +PUBLIC inline +void +Tb_entry_ke_reg::set_buf(unsigned i, char c) +{ + if (i < sizeof(payload()->_msg) - 1) + payload()->_msg[i] = c >= ' ' ? c : '.'; +} + +PUBLIC inline +void +Tb_entry_ke_reg::term_buf(unsigned i) +{ payload()->_msg[i < sizeof(payload()->_msg)-1 ? i : sizeof(payload()->_msg)-1] = '\0'; } + +PUBLIC inline +const char * +Tb_entry_ke_reg::msg() const +{ + return payload()->_msg[0] == 0 && + payload()->_msg[1] == 1 ? payload()->_const_msg._m + : payload()->_msg; +} + +PUBLIC inline +Mword +Tb_entry_ke_reg::val1() const +{ return payload()->_eax; } + +PUBLIC inline +Mword +Tb_entry_ke_reg::val2() const +{ return payload()->_ecx; } + +PUBLIC inline +Mword +Tb_entry_ke_reg::val3() const +{ return payload()->_edx; } + + +PUBLIC inline NEEDS ["trap_state.h"] +void +Tb_entry_trap::set(Context const *ctx, Mword eip, Trap_state *ts) +{ + set_global(Tbuf_trap, ctx, eip); + payload()->_trapno = ts->_trapno; + payload()->_error = ts->_err; + payload()->_cr2 = ts->_cr2; + payload()->_eax = ts->_ax; + payload()->_cs = (Unsigned16)ts->cs(); + payload()->_ds = (Unsigned16)ts->_ds; + payload()->_esp = ts->sp(); + payload()->_eflags = ts->flags(); +} + +PUBLIC inline +void +Tb_entry_trap::set(Context const *ctx, Mword eip, Mword trapno) +{ + set_global(Tbuf_trap, ctx, eip); + payload()->_trapno = trapno; + payload()->_cs = 0; +} + +PUBLIC inline +Unsigned8 +Tb_entry_trap::trapno() const +{ return payload()->_trapno; } + +PUBLIC inline +Unsigned16 +Tb_entry_trap::error() const +{ return payload()->_error; } + +PUBLIC inline +Mword +Tb_entry_trap::eax() const +{ return payload()->_eax; } + +PUBLIC inline +Mword +Tb_entry_trap::cr2() const +{ return payload()->_cr2; } + +PUBLIC inline +Mword +Tb_entry_trap::ebp() const +{ return payload()->_ebp; } + +PUBLIC inline +Unsigned16 +Tb_entry_trap::cs() const +{ return payload()->_cs; } + +PUBLIC inline +Unsigned16 +Tb_entry_trap::ds() const +{ return payload()->_ds; } + +PUBLIC inline +Mword +Tb_entry_trap::sp() const +{ return payload()->_esp; } + +PUBLIC inline +Mword +Tb_entry_trap::flags() const +{ return payload()->_eflags; } diff --git a/kernel/fiasco/src/kern/ia32/32/thread-dbf.cpp b/kernel/fiasco/src/kern/ia32/32/thread-dbf.cpp new file mode 100644 index 00000000..4b427057 --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/32/thread-dbf.cpp @@ -0,0 +1,100 @@ +INTERFACE: + +EXTENSION class Thread +{ +private: + static void handle_double_fault (void) asm ("thread_handle_double_fault"); + +public: + static bool may_enter_jdb; +}; + + +IMPLEMENTATION: + +#include +#include "cpu.h" +#include "kernel_console.h" +#include "processor.h" +#include "reset.h" +#include "trap_state.h" +#include "tss.h" +#include "watchdog.h" + + +bool Thread::may_enter_jdb = false; + +IMPLEMENT +void +Thread::handle_double_fault (void) +{ + // cannot use currnt_cpu() here because this must run on a thread stack, + // not on a dbf stack + volatile Tss *tss = Cpu::boot_cpu()->get_tss(); + int c; + + Watchdog::disable(); + + printf ("\n" + "\033[1;31mDOUBLE FAULT!\033[m\n" + "EAX=%08x ESI=%08x DS=%04x \n" + "EBX=%08x EDI=%08x ES=%04x\n" + "ECX=%08x EBP=%08x GS=%04x\n" + "EDX=%08x ESP=%08x SS=%04x ESP0=%08lx\n" + "EFL=%08x EIP=%08x CS=%04x\n", + tss->_eax, tss->_esi, tss->_ds & 0xffff, + tss->_ebx, tss->_edi, tss->_es & 0xffff, + tss->_ecx, tss->_ebp, tss->_gs & 0xffff, + tss->_edx, tss->_esp, tss->_ss & 0xffff, tss->_esp0, + tss->_eflags, tss->_eip, tss->_cs & 0xffff); + + if (may_enter_jdb) + { + puts ("Return reboots, \"k\" tries to enter the L4 kernel debugger..."); + + while ((c=Kconsole::console()->getchar(false)) == -1) + Proc::pause(); + + if (c == 'k' || c == 'K') + { + Mword dummy; + Trap_state ts; + + // built a nice trap state the jdb can work with + ts._ax = tss->_eax; + ts._bx = tss->_ebx; + ts._cx = tss->_ecx; + ts._dx = tss->_edx; + ts._si = tss->_esi; + ts._di = tss->_edi; + ts._bp = tss->_ebp; + ts.sp(tss->_esp); + ts.cs(tss->_cs); + ts._ds = tss->_ds; + ts._es = tss->_es; + ts.ss(tss->_ss); + ts._fs = tss->_fs; + ts._gs = tss->_gs; + ts._trapno = 8; + ts._err = 0; + ts.ip(tss->_eip); + ts.flags(tss->_eflags); + + asm volatile + ( + "call *%2 \n\t" + : "=a"(dummy) + : "a"(&ts), "m"(nested_trap_handler) + : "ecx", "edx", "memory"); + } + } + else + { + puts ("Return reboots"); + while ((Kconsole::console()->getchar(false)) == -1) + Proc::pause(); + } + + puts ("\033[1mRebooting...\033[0m"); + platform_reset(); +} diff --git a/kernel/fiasco/src/kern/ia32/32/thread-ia32-32.cpp b/kernel/fiasco/src/kern/ia32/32/thread-ia32-32.cpp new file mode 100644 index 00000000..3307b83a --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/32/thread-ia32-32.cpp @@ -0,0 +1,372 @@ +IMPLEMENTATION[ia32 || ux]: + +PUBLIC template inline +void FIASCO_NORETURN +Thread::fast_return_to_user(Mword ip, Mword sp, T arg) +{ + assert_kdb(cpu_lock.test()); + assert_kdb(current() == this); + assert_kdb(Config::Is_ux || (regs()->cs() & 3 == 3)); + + regs()->ip(ip); + regs()->sp(sp); + regs()->flags(EFLAGS_IF); + asm volatile + ("mov %0, %%esp \t\n" + "iret \t\n" + : + : "r" (static_cast(regs())), "a" (arg) + ); + __builtin_trap(); +} + +IMPLEMENT inline +Mword +Thread::user_sp() const +{ return regs()->sp(); } + +IMPLEMENT inline +void +Thread::user_sp(Mword sp) +{ regs()->sp(sp); } + +PROTECTED inline +int +Thread::do_trigger_exception(Entry_frame *r, void *ret_handler) +{ + if (!exception_triggered()) + { + _exc_cont.activate(r, ret_handler); + return 1; + } + // else ignore change of IP because triggered exception already pending + return 0; +} + + +PUBLIC inline +void +Thread::restore_exc_state() +{ + assert (cpu_lock.test()); + _exc_cont.restore(regs()); +#if 0 + +#ifdef CONFIG_PF_UX + r->cs (exception_cs() & ~1); +#else + r->cs (exception_cs()); +#endif + r->ip (_exc_ip); + r->flags (_exc_flags); + _exc_ip = ~0UL; +#endif +} + +PRIVATE static inline +Return_frame * +Thread::trap_state_to_rf(Trap_state *ts) +{ + char *im = reinterpret_cast(ts + 1); + return reinterpret_cast(im)-1; +} + +PRIVATE static inline NEEDS[Thread::trap_state_to_rf] +bool FIASCO_WARN_RESULT +Thread::copy_utcb_to_ts(L4_msg_tag const &tag, Thread *snd, Thread *rcv, + unsigned char rights) +{ + Trap_state *ts = (Trap_state*)rcv->_utcb_handler; + Mword s = tag.words(); + Unsigned32 cs = ts->cs(); + Utcb *snd_utcb = snd->utcb().access(); + + // XXX: check that gs and fs point to valid user_entry only, for gdt and + // ldt! + if (EXPECT_FALSE(rcv->exception_triggered())) + { + // triggered exception pending + Mem::memcpy_mwords(&ts->_gs, snd_utcb->values, s > 12 ? 12 : s); + if (EXPECT_TRUE(s > 15)) + { + Continuation::User_return_frame const *s + = reinterpret_cast((char*)&snd_utcb->values[12]); + + rcv->_exc_cont.set(trap_state_to_rf(ts), s); + } + } + else + Mem::memcpy_mwords (&ts->_gs, snd_utcb->values, s > 16 ? 16 : s); + + // reset segments + rcv->_gs = rcv->_fs = 0; + + if (tag.transfer_fpu() && (rights & L4_fpage::W)) + snd->transfer_fpu(rcv); + + // sanitize eflags + ts->flags((ts->flags() & ~(EFLAGS_IOPL | EFLAGS_NT)) | EFLAGS_IF); + + // don't allow to overwrite the code selector! + ts->cs(cs); + + bool ret = transfer_msg_items(tag, snd, snd_utcb, + rcv, rcv->utcb().access(), rights); + + rcv->state_del(Thread_in_exception); + return ret; +} + +PRIVATE static inline +bool FIASCO_WARN_RESULT +Thread::copy_ts_to_utcb(L4_msg_tag const &, Thread *snd, Thread *rcv, + unsigned char rights) +{ + Utcb *rcv_utcb = rcv->utcb().access(); + Trap_state *ts = (Trap_state*)snd->_utcb_handler; + Mword r = Utcb::Max_words; + + { + Lock_guard guard (&cpu_lock); + if (EXPECT_FALSE(snd->exception_triggered())) + { + Mem::memcpy_mwords (rcv_utcb->values, &ts->_gs, r > 12 ? 12 : r); + Continuation::User_return_frame *d + = reinterpret_cast((char*)&rcv_utcb->values[12]); + + snd->_exc_cont.get(d, trap_state_to_rf(ts)); + } + else + Mem::memcpy_mwords (rcv_utcb->values, &ts->_gs, r > 16 ? 16 : r); + + if (rcv_utcb->inherit_fpu() && (rights & L4_fpage::W)) + snd->transfer_fpu(rcv); + } + return true; +} + + +//---------------------------------------------------------------------------- +IMPLEMENTATION [ia32 && !ux]: + +IMPLEMENT inline NEEDS[Thread::exception_triggered] +void +Thread::user_ip(Mword ip) +{ + if (exception_triggered()) + _exc_cont.ip(ip); + else + regs()->ip(ip); +} + + +PRIVATE inline +int +Thread::check_trap13_kernel(Trap_state *ts) +{ + if (EXPECT_FALSE(ts->_trapno == 13 && (ts->_err & 3) == 0)) + { + // First check if user loaded a segment register with 0 because the + // resulting exception #13 can be raised from user _and_ kernel. If + // the user tried to load another segment selector, the thread gets + // killed. + // XXX Should we emulate this too? Michael Hohmuth: Yes, we should. + if (EXPECT_FALSE(!(ts->_ds & 0xffff))) + { + Cpu::set_ds(Gdt::data_segment()); + return 0; + } + if (EXPECT_FALSE(!(ts->_es & 0xffff))) + { + Cpu::set_es(Gdt::data_segment()); + return 0; + } + if (EXPECT_FALSE(ts->_ds & 0xfff8) == Gdt::gdt_code_user) + { + WARN("%p eip=%08lx: code selector ds=%04lx", + this, ts->ip(), ts->_ds & 0xffff); + Cpu::set_ds(Gdt::data_segment()); + return 0; + } + if (EXPECT_FALSE(ts->_es & 0xfff8) == Gdt::gdt_code_user) + { + WARN("%p eip=%08lx: code selector es=%04lx", + this, ts->ip(), ts->_es & 0xffff); + Cpu::set_es(Gdt::data_segment()); + return 0; + } + if (EXPECT_FALSE(ts->_fs & 0xfff8) == Gdt::gdt_code_user) + { + WARN("%p eip=%08lx: code selector fs=%04lx", + this, ts->ip(), ts->_fs & 0xffff); + ts->_fs = 0; + return 0; + } + if (EXPECT_FALSE(ts->_gs & 0xfff8) == Gdt::gdt_code_user) + { + WARN("%p eip=%08lx: code selector gs=%04lx", + this, ts->ip(), ts->_gs & 0xffff); + ts->_gs = 0; + return 0; + } + } + + return 1; +} + + +IMPLEMENT +void +Thread::user_invoke() +{ + user_invoke_generic(); + + asm volatile + (" movl %%eax,%%esp \n" // set stack pointer to regs structure + " movl %%ecx,%%es \n" + " movl %%ecx,%%ds \n" + " xorl %%eax,%%eax \n" // clean out user regs + " xorl %%ecx,%%ecx \n" + " xorl %%edx,%%edx \n" + " xorl %%esi,%%esi \n" + " xorl %%edi,%%edi \n" + " xorl %%ebx,%%ebx \n" + " xorl %%ebp,%%ebp \n" + " iret \n" + : // no output + : "a" (nonull_static_cast(current()->regs())), + "c" (Gdt::gdt_data_user | Gdt::Selector_user) + ); + + // never returns here +} + +//--------------------------------------------------------------------------- +IMPLEMENTATION [ia32]: + +#include +KIP_KERNEL_FEATURE("segments"); + +PROTECTED inline +L4_msg_tag +Thread::invoke_arch(L4_msg_tag tag, Utcb *utcb) +{ + switch (utcb->values[0] & Opcode_mask) + { + case Op_gdt_x86: + + // if no words given then return the first gdt entry + if (EXPECT_FALSE(tag.words() == 1)) + { + utcb->values[0] = Gdt::gdt_user_entry1 >> 3; + return Kobject_iface::commit_result(0, 1); + } + + { + unsigned entry_number = utcb->values[1]; + unsigned idx = 2; + + for (; entry_number < Gdt_user_entries + && idx < tag.words() + ; idx += 2, ++entry_number) + { + Gdt_entry *d = (Gdt_entry *)&utcb->values[idx]; + if (!d->unsafe()) + _gdt_user_entries[entry_number] = *d; + } + + if (this == current_thread()) + switch_gdt_user_entries(this); + + return Kobject_iface::commit_result((utcb->values[1] << 3) + Gdt::gdt_user_entry1 + 3); + } + + default: + return commit_result(-L4_err::ENosys); + }; +} + +//--------------------------------------------------------------------------- +IMPLEMENTATION [ia32 & (debug | kdb)]: + +#include "ipi.h" +#include "kernel_task.h" + +/** Call the nested trap handler (either Jdb::enter_kdebugger() or the + * gdb stub. Setup our own stack frame */ +PRIVATE static +int +Thread::call_nested_trap_handler(Trap_state *ts) +{ + unsigned long phys_cpu = Cpu::phys_id_direct(); + unsigned log_cpu = Cpu::p2l(phys_cpu); + if (log_cpu == ~0U) + { + printf("Trap on unknown CPU phys_id=%lx\n", phys_cpu); + log_cpu = 0; + } + + unsigned long &ntr = nested_trap_recover.cpu(log_cpu); + +#if 0 + printf("%s: lcpu%u sp=%p t=%lu nested_trap_recover=%ld\n", + __func__, log_cpu, (void*)Proc::stack_pointer(), ts->_trapno, ntr); +#endif + + int ret; + + unsigned dummy1, dummy2, dummy3; + + struct + { + Mword pdir; + FIASCO_FASTCALL int (*handler)(Trap_state*, unsigned); + void *stack; + } p; + + if (!ntr) + p.stack = dbg_stack.cpu(log_cpu).stack_top; + else + p.stack = 0; + + p.pdir = Kernel_task::kernel_task()->virt_to_phys((Address)Kmem::dir()); + p.handler = nested_trap_handler; + + + // don't set %esp if gdb fault recovery to ensure that exceptions inside + // kdb/jdb don't overwrite the stack + asm volatile + ("mov %%esp,%[d2] \n\t" + "cmpl $0,(%[ntr]) \n\t" + "jne 1f \n\t" + "mov 8(%[p]),%%esp \n\t" + "1: \n\t" + "incl (%[ntr]) \n\t" + "mov %%cr3, %[d1] \n\t" + "push %[d2] \n\t" + "push %[p] \n\t" + "push %[d1] \n\t" + "mov (%[p]), %[d1] \n\t" + "mov %[d1], %%cr3 \n\t" + "call *4(%[p]) \n\t" + "pop %[d1] \n\t" + "mov %[d1], %%cr3 \n\t" + "pop %[p] \n\t" + "pop %%esp \n\t" + "cmpl $0,(%[ntr]) \n\t" + "je 1f \n\t" + "decl (%[ntr]) \n\t" + "1: \n\t" + + : [ret] "=a" (ret), + [d1] "=&c" (dummy1), + [d2] "=&r" (dummy2), + "=d" (dummy3) + : [ts] "a" (ts), + [cpu] "d" (log_cpu), + [p] "r" (&p), + [ntr] "r" (&ntr) + : "memory"); + + return ret == 0 ? 0 : -1; +} diff --git a/kernel/fiasco/src/kern/ia32/32/trap_state.cpp b/kernel/fiasco/src/kern/ia32/32/trap_state.cpp new file mode 100644 index 00000000..a8289049 --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/32/trap_state.cpp @@ -0,0 +1,249 @@ + +INTERFACE: + +#include "l4_types.h" + +class Trap_state +{ + friend class Jdb_tcb; + friend class Jdb_stack_view; + +public: + typedef FIASCO_FASTCALL int (*Handler)(Trap_state*, unsigned cpu); + static Handler base_handler asm ("BASE_TRAP_HANDLER"); + + // Saved segment registers + Mword _es; + Mword _ds; + Mword _gs; // => utcb->values[ 0] + Mword _fs; // => utcb->values[ 1] + + // PUSHA register state frame + Mword _di; // => utcb->values[ 2] + Mword _si; // => utcb->values[ 3] + Mword _bp; // => utcb->values[ 4] + Mword _cr2; // we save cr2 over esp for PFs // => utcb->values[ 5] + Mword _bx; // => utcb->values[ 6] + Mword _dx; // => utcb->values[ 7] + Mword _cx; // => utcb->values[ 8] + Mword _ax; // => utcb->values[ 9] + + // Processor trap number, 0-31 + Mword _trapno; // => utcb->values[10] + + // Error code pushed by the processor, 0 if none + Mword _err; // => utcb->values[11] + +protected: + // Processor state frame + Mword _ip; // => utcb->values[12] + Mword _cs; // => utcb->values[13] + Mword _flags; // => utcb->values[14] + Mword _sp; // => utcb->values[15] + Mword _ss; +}; + + +//--------------------------------------------------------------------------- +IMPLEMENTATION [ia32]: + +#include "regdefs.h" +#include "gdt.h" + +PUBLIC inline NEEDS["regdefs.h", "gdt.h"] +void +Trap_state::sanitize_user_state() +{ + _cs = Gdt::gdt_code_user | Gdt::Selector_user; + _ss = Gdt::gdt_data_user | Gdt::Selector_user; + _flags = (_flags & ~(EFLAGS_IOPL | EFLAGS_NT)) | EFLAGS_IF; +} + +//--------------------------------------------------------------------------- +IMPLEMENTATION [ux]: + +#include "emulation.h" +#include "regdefs.h" + +PUBLIC inline NEEDS["emulation.h", "regdefs.h"] +void +Trap_state::sanitize_user_state() +{ + _cs = Emulation::kernel_cs() & ~1; + _ss = Emulation::kernel_ss(); + _flags = (_flags & ~(EFLAGS_IOPL | EFLAGS_NT)) | EFLAGS_IF; +} + +//--------------------------------------------------------------------------- +IMPLEMENTATION [ia32 || ux]: + +#include +#include +#include "cpu.h" +#include "atomic.h" + +Trap_state::Handler Trap_state::base_handler FIASCO_FASTCALL; + +PUBLIC inline +void +Trap_state::set_ipc_upcall() +{ + _err = 0; + _trapno = 0xfe; +} + +PUBLIC inline +void +Trap_state::set_pagefault(Mword pfa, Mword error) +{ + _cr2 = pfa; + _trapno = 0xe; + _err = error; +} + +PUBLIC inline +Mword +Trap_state::trapno() const +{ return _trapno; } + +PUBLIC inline +Mword +Trap_state::error() const +{ return _err; } + +PUBLIC inline +Mword +Trap_state::ip() const +{ return _ip; } + +PUBLIC inline +Mword +Trap_state::cs() const +{ return _cs; } + +PUBLIC inline +Mword +Trap_state::flags() const +{ return _flags; } + +PUBLIC inline +Mword +Trap_state::sp() const +{ return _sp; } + +PUBLIC inline +Mword +Trap_state::ss() const +{ return _ss; } + +PUBLIC inline +Mword +Trap_state::value() const +{ return _ax; } + +PUBLIC inline +Mword +Trap_state::value2() const +{ return _cx; } + +PUBLIC inline +Mword +Trap_state::dx() const +{ return _dx; } + +PUBLIC inline +Mword +Trap_state::value3() const +{ return _dx; } + +PUBLIC inline +Mword +Trap_state::value4() const +{ return _bx; } + +PUBLIC inline +void +Trap_state::ip(Mword ip) +{ _ip = ip; } + +PUBLIC inline +void +Trap_state::cs(Mword cs) +{ _cs = cs; } + +PUBLIC inline +void +Trap_state::flags(Mword flags) +{ _flags = flags; } + +PUBLIC inline +void +Trap_state::sp(Mword sp) +{ _sp = sp; } + +PUBLIC inline +void +Trap_state::ss(Mword ss) +{ _ss = ss; } + +PUBLIC inline +void +Trap_state::value(Mword value) +{ _ax = value; } + +PUBLIC inline +void +Trap_state::value3(Mword value) +{ _dx = value; } + +PUBLIC inline NEEDS["atomic.h"] +void +Trap_state::consume_instruction(unsigned count) +{ cas ((Address*)(&_ip), _ip, _ip + count); } + +PUBLIC inline +bool +Trap_state::is_debug_exception() const +{ return _trapno == 1 || _trapno == 3; } + +PUBLIC +void +Trap_state::dump() +{ + int from_user = _cs & 3; + + printf("EAX %08lx EBX %08lx ECX %08lx EDX %08lx\n" + "ESI %08lx EDI %08lx EBP %08lx ESP %08lx\n" + "EIP %08lx EFLAGS %08lx\n" + "CS %04lx SS %04lx DS %04lx ES %04lx FS %04lx GS %04lx\n" + "trap %ld (%s), error %08lx, from %s mode\n", + _ax, _bx, _cx, _dx, + _si, _di, _bp, from_user ? _sp : (Unsigned32)&_sp, + _ip, _flags, + _cs & 0xffff, from_user ? _ss & 0xffff : Cpu::get_ss() & 0xffff, + _ds & 0xffff, _es & 0xffff, _fs & 0xffff, _gs & 0xffff, + _trapno, Cpu::exception_string(_trapno), _err, from_user ? "user" : "kernel"); + + if (_trapno == 13) + { + if (_err & 1) + printf("(external event"); + else + printf("(internal event"); + if (_err & 2) + printf(" regarding IDT gate descriptor no. 0x%02lx)\n", _err >> 3); + else + printf(" regarding %s entry no. 0x%02lx)\n", + _err & 4 ? "LDT" : "GDT", _err >> 3); + } + else if (_trapno == 14) + printf("page fault linear address %08lx\n", _cr2); +} + +extern "C" FIASCO_FASTCALL +void +trap_dump_panic(Trap_state *ts) +{ + ts->dump(); + panic("terminated due to trap"); +} diff --git a/kernel/fiasco/src/kern/ia32/32/tss.cpp b/kernel/fiasco/src/kern/ia32/32/tss.cpp new file mode 100644 index 00000000..3c12f136 --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/32/tss.cpp @@ -0,0 +1,44 @@ + +INTERFACE: + +#include "l4_types.h" + +class Tss +{ +public: + Unsigned32 _back_link; + Address _esp0; + Unsigned32 _ss0; + Address _esp1; + Unsigned32 _ss1; + Address _esp2; + Unsigned32 _ss2; + Unsigned32 _cr3; + Unsigned32 _eip; + Unsigned32 _eflags; + Unsigned32 _eax; + Unsigned32 _ecx; + Unsigned32 _edx; + Unsigned32 _ebx; + Unsigned32 _esp; + Unsigned32 _ebp; + Unsigned32 _esi; + Unsigned32 _edi; + Unsigned32 _es; + Unsigned32 _cs; + Unsigned32 _ss; + Unsigned32 _ds; + Unsigned32 _fs; + Unsigned32 _gs; + Unsigned32 _ldt; + Unsigned16 _trace_trap; + Unsigned16 _io_bit_map_offset; +} __attribute__((packed)); + +IMPLEMENTATION: + +PUBLIC inline +void +Tss::set_ss0(unsigned ss) +{ _ss0 = ss; } + diff --git a/kernel/fiasco/src/kern/ia32/32/vm_svm_asm.S b/kernel/fiasco/src/kern/ia32/32/vm_svm_asm.S new file mode 100644 index 00000000..95e4322f --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/32/vm_svm_asm.S @@ -0,0 +1,64 @@ +/** + * Function resume_vm_svm, arguments: + * - eax: physical VMCB address + * - edx: Pointer to registers (layout specific...) + * + * Note: To be called with interrupts disabled! + */ + + .p2align(4) + .globl resume_vm_svm +resume_vm_svm: + + // save callee saved regs + pushl %edi + pushl %esi + pushl %ebx + pushl %ebp + + pushl %edx // store pointer to register struct + + clgi // super CLI + + sti + mov 0x10(%edx), %edi + mov 0x14(%edx), %esi + mov 0x18(%edx), %ebp + mov 0x20(%edx), %ebx + mov 0x28(%edx), %ecx + mov 0x24(%edx), %edx + // EAX is in the vmcb + + // TODO: Debugregs etc. + + // eax used as implicit operand for vm* instructions + vmload + vmrun + vmsave + + pushl %edx + movl 4(%esp), %edx // get previously saved register struct pointer + + movl %ecx, 0x28(%edx) + movl %ebx, 0x20(%edx) + movl %ebp, 0x18(%edx) + movl %esi, 0x14(%edx) + movl %edi, 0x10(%edx) + + movl (%esp), %ecx // guest EDX to ECX + movl %ecx, 0x24(%edx) + + // TODO: restore task register, clear busy flag + + cli + stgi + + addl $8, %esp // adjust stack after two pushs + + // restore callee saved registers + popl %ebp + popl %ebx + popl %esi + popl %edi + + ret diff --git a/kernel/fiasco/src/kern/ia32/32/vm_vmx_asm.S b/kernel/fiasco/src/kern/ia32/32/vm_vmx_asm.S new file mode 100644 index 00000000..6b2a073f --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/32/vm_vmx_asm.S @@ -0,0 +1,75 @@ +/** + * Function resume_vm_vmx, arguments: + * - eax: Pointer to registers (layout specific...) + */ + .p2align(4) + .globl resume_vm_vmx + .globl vm_vmx_exit_vec +resume_vm_vmx: + // save callee saved regs + push %edi + push %esi + push %ebx + push %ebp + push %ds + push %es + push %gs + push %fs + + push %eax // store pointer to register struct + mov $0x6c14, %eax // save esp in vmcs + vmwrite %esp, %eax + mov (%esp), %esp + + // load guest GPs + mov 16(%esp), %edi + mov 20(%esp), %esi + mov 24(%esp), %ebp + mov 32(%esp), %ebx + mov 36(%esp), %edx + mov 40(%esp), %ecx + mov 44(%esp), %eax + + vmresume + jnz 1f + vmlaunch +1: // error path + mov $0x6c14, %eax + vmread %eax, %esp + pushf + pop %eax + add $20, %esp // pushed regs pointer and gs+fs+ds+es + pop %ebp + pop %ebx + pop %esi + pop %edi + ret + +vm_vmx_exit_vec: + push %eax + mov 4(%esp), %eax // get previously saved register struct pointer + + // eax is saved below + mov %edi, 16(%eax) + mov %esi, 20(%eax) + mov %ebp, 24(%eax) + mov %ebx, 32(%eax) + mov %edx, 36(%eax) + mov %ecx, 40(%eax) + pop %ecx // guest EAX to ECX + mov %ecx, 44(%eax) + + add $4, %esp // adjust stack after regs pointer push on stack + + // restore callee saved registers + pop %fs + pop %gs + pop %es + pop %ds + pop %ebp + pop %ebx + pop %esi + pop %edi + + xor %eax, %eax + ret diff --git a/kernel/fiasco/src/kern/ia32/64/config-ia32-64.cpp b/kernel/fiasco/src/kern/ia32/64/config-ia32-64.cpp new file mode 100644 index 00000000..cc357960 --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/64/config-ia32-64.cpp @@ -0,0 +1,30 @@ +INTERFACE[amd64]: + +EXTENSION class Config +{ +public: + + enum { + PAGE_SHIFT = ARCH_PAGE_SHIFT, + PAGE_SIZE = 1 << PAGE_SHIFT, + PAGE_MASK = ~( PAGE_SIZE - 1), + + SUPERPAGE_SHIFT = 21, + SUPERPAGE_SIZE = 1 << SUPERPAGE_SHIFT, + SUPERPAGE_MASK = ~( SUPERPAGE_SIZE -1 ), + + PDP_SIZE = 1LL << 30, + PML4_SIZE = 1LL << 39, + + PML4E_SHIFT = 39, + PML4E_MASK = 0x1ff, + PDPE_SHIFT = 30, + PDPE_MASK = 0x1ff, + PDE_SHIFT = 21, + PDE_MASK = 0x1ff, + PTE_SHIFT = 12, + PTE_MASK = 0x1ff, + + Irq_shortcut = 1, + }; +}; diff --git a/kernel/fiasco/src/kern/ia32/64/context-ia32-64.cpp b/kernel/fiasco/src/kern/ia32/64/context-ia32-64.cpp new file mode 100644 index 00000000..ce13abf9 --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/64/context-ia32-64.cpp @@ -0,0 +1,71 @@ +INTERFACE [amd64]: + +EXTENSION class Context +{ +protected: + Mword _gs_base, _fs_base; +}; + +// ------------------------------------------------------------------------ +IMPLEMENTATION [amd64]: + +IMPLEMENT inline NEEDS [Context::update_consumed_time, + Context::store_segments] +void +Context::switch_cpu (Context *t) +{ + Mword dummy1, dummy2, dummy3, dummy4; + + update_consumed_time(); + + store_segments(); + + asm volatile + ( + " push %%rbp \n\t" // save base ptr of old thread + " pushq $1f \n\t" // push restart addr on old stack + " mov %%rsp, (%[old_ksp]) \n\t" // save stack pointer + " mov (%[new_ksp]), %%rsp \n\t" // load new stack pointer + // in new context now (cli'd) + " call switchin_context_label \n\t" // switch pagetable + " pop %%rax \n\t" // don't do ret here -- we want + " jmp *%%rax \n\t" // to preserve the return stack + // restart code + " .p2align 4 \n\t" // start code at new cache line + "1: pop %%rbp \n\t" // restore base ptr + + : "=c" (dummy1), "=a" (dummy2), "=D" (dummy3), "=S" (dummy4) + : [old_ksp] "c" (&_kernel_sp), + [new_ksp] "a" (&t->_kernel_sp), + [new_thread] "D" (t), + [old_thread] "S" (this) + : "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "rbx", "rdx", "memory"); +} + +PROTECTED inline +void +Context::arch_setup_utcb_ptr() +{ + _utcb.access()->utcb_addr = (Mword)_utcb.usr().get(); + _gs_base = (Address)&_utcb.usr()->utcb_addr; +} + +PROTECTED inline +void +Context::load_segments() +{ + Cpu::set_fs(0); + Cpu::wrmsr(_fs_base, MSR_FS_BASE); + Cpu::set_gs(0); + Cpu::wrmsr(_gs_base, MSR_GS_BASE); +} + +PROTECTED inline +void +Context::store_segments() +{} + +PROTECTED inline +void +Context::switch_gdt_user_entries(Context *) +{} diff --git a/kernel/fiasco/src/kern/ia32/64/continuation-ia32-64.cpp b/kernel/fiasco/src/kern/ia32/64/continuation-ia32-64.cpp new file mode 100644 index 00000000..edaa57b8 --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/64/continuation-ia32-64.cpp @@ -0,0 +1,81 @@ +INTERFACE[amd64]: + +#include "entry_frame.h" +#include "gdt.h" +#include "member_offs.h" +#include "regdefs.h" +#include "types.h" + +class Continuation +{ + MEMBER_OFFSET(); + +private: + Address _ip; + Mword _flags; + Mword _sp; + Mword _ss; + +public: + Continuation() : _ip(~0UL) {} + + typedef Return_frame User_return_frame; + + bool valid() const + { return _ip != ~0UL; } + + Address ip() const { return _ip; } + void ip(Address ip) { _ip = ip; } + + Mword flags(Return_frame const *) const { return _flags; } + void flags(Return_frame *, Mword flags) { _flags = flags; } + + Mword sp(Return_frame const *) const { return _sp; } + void sp(Return_frame *, Mword sp) { _sp = sp; } + + void save(Return_frame const *regs) + { + _ip = regs->ip(); + _flags = regs->flags(); + _sp = regs->sp(); + _ss = regs->ss(); + } + + void activate(Return_frame *regs, void *cont_func) + { + save(regs); + regs->ip(Mword(cont_func)); + regs->flags(regs->flags() & ~EFLAGS_TF); // do not singlestep inkernel code + regs->sp((Address)(regs + 1)); + regs->ss(Gdt::gdt_data_kernel | Gdt::Selector_kernel); + regs->cs(Gdt::gdt_code_kernel | Gdt::Selector_kernel); + } + + void set(Return_frame *dst, User_return_frame const *src) + { + _ip = src->ip(); + _flags = src->flags(); + dst->sp(src->sp()); + } + + void get(User_return_frame *dst, Return_frame const *src) const + { + dst->ip(_ip); + dst->flags(_flags); + dst->sp(src->sp()); + } + + void clear() { _ip = ~0UL; } + + void restore(Return_frame *regs) + { + regs->ip(_ip); + regs->flags(_flags); + regs->sp(_sp); + regs->ss(_ss); + regs->cs(Gdt::gdt_code_user | Gdt::Selector_user); + clear(); + } + +}; + diff --git a/kernel/fiasco/src/kern/ia32/64/cpu-64.cpp b/kernel/fiasco/src/kern/ia32/64/cpu-64.cpp new file mode 100644 index 00000000..05b44b0a --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/64/cpu-64.cpp @@ -0,0 +1,176 @@ +IMPLEMENTATION[amd64]: + +#include "mem_layout.h" +#include "tss.h" + +PUBLIC inline +Unsigned64 +Cpu::ns_to_tsc (Unsigned64 ns) const +{ + Unsigned64 tsc, dummy; + __asm__ + (" \n\t" + "mulq %3 \n\t" + "shrd $27, %%rdx, %%rax \n\t" + :"=a" (tsc), "=d" (dummy) + :"a" (ns), "r" ((Unsigned64)scaler_ns_to_tsc) + ); + return tsc; +} + +PUBLIC inline +Unsigned64 +Cpu::tsc_to_ns (Unsigned64 tsc) const +{ + Unsigned64 ns, dummy; + __asm__ + (" \n\t" + "mulq %3 \n\t" + "shrd $27, %%rdx, %%rax \n\t" + :"=a" (ns), "=d"(dummy) + :"a" (tsc), "r" ((Unsigned64)scaler_tsc_to_ns) + ); + return ns; +} + +PUBLIC inline +Unsigned64 +Cpu::tsc_to_us (Unsigned64 tsc) const +{ + Unsigned64 ns, dummy; + __asm__ + (" \n\t" + "mulq %3 \n\t" + "shrd $32, %%rdx, %%rax \n\t" + :"=a" (ns), "=d" (dummy) + :"a" (tsc), "r" ((Unsigned64)scaler_tsc_to_us) + ); + return ns; +} + + +PUBLIC inline +void +Cpu::tsc_to_s_and_ns(Unsigned64 tsc, Unsigned32 *s, Unsigned32 *ns) const +{ + __asm__ + (" \n\t" + "mulq %3 \n\t" + "shrd $27, %%rdx, %%rax \n\t" + "xorq %%rdx, %%rdx \n\t" + "divq %4 \n\t" + :"=a" (*s), "=&d" (*ns) + : "a" (tsc), "r" ((Unsigned64)scaler_tsc_to_ns), + "rm"(1000000000ULL) + ); +} + +PUBLIC static inline +Unsigned64 +Cpu::rdtsc (void) +{ + Unsigned64 tsc; + asm volatile ( + "rdtsc \n\t" + "and %1,%%rax \n\t" + "shl $32,%%rdx \n\t" + "or %%rdx,%%rax \n\t" + : "=&a" (tsc) + : "r" (0xffffffffUL) + :"rdx" + ); + return tsc; +} + + +PUBLIC static inline +Unsigned64 +Cpu::get_flags() +{ + Unsigned64 efl; + asm volatile ("pushf ; popq %0" : "=r"(efl)); + return efl; +} + + +PUBLIC static inline +void +Cpu::set_flags (Unsigned64 efl) +{ + asm volatile ("pushq %0 ; popf" : : "rm" (efl) : "memory"); +} + + +IMPLEMENT inline NEEDS["tss.h"] +Address volatile & +Cpu::kernel_sp() const +{ return *reinterpret_cast
(&get_tss()->_rsp0); } + +PUBLIC static inline +void +Cpu:: set_cs () +{ + // XXX have only memory indirect far jmp in 64Bit mode + asm volatile ( + "movabsq $1f, %%rax \n" + "pushq %%rbx \n" + "pushq %%rax \n" + "lretq \n" + "1: \n" + : + : "b" (Gdt::gdt_code_kernel | Gdt::Selector_kernel) + : "rax", "memory"); +} + + +extern "C" Address dbf_stack_top; + +PUBLIC FIASCO_INIT_CPU +void +Cpu::init_tss (Address tss_mem, size_t tss_size) +{ + tss = reinterpret_cast(tss_mem); + + gdt->set_entry_tss (Gdt::gdt_tss/8, tss_mem, tss_size, + Gdt_entry::Access_kernel | Gdt_entry::Access_tss, 0); + + // XXX setup pointer for clean double fault stack + tss->_ist1 = (Address)&dbf_stack_top; + tss->_io_bit_map_offset = Mem_layout::Io_bitmap - tss_mem; +} + + +PUBLIC FIASCO_INIT_CPU +void +Cpu::init_gdt (Address gdt_mem, Address user_max) +{ + gdt = reinterpret_cast(gdt_mem); + + // make sure kernel cs/ds and user cs/ds are placed in the same + // cache line, respectively; pre-set all "accessed" flags so that + // the CPU doesn't need to do this later + + gdt->set_entry_4k (Gdt::gdt_code_kernel/8, 0, 0xffffffff, + Gdt_entry::Access_kernel | + Gdt_entry::Access_code_read | + Gdt_entry::Accessed, Gdt_entry::Long_mode); + gdt->set_entry_4k (Gdt::gdt_data_kernel/8, 0, 0xffffffff, + Gdt_entry::Access_kernel | + Gdt_entry::Access_data_write | + Gdt_entry::Accessed, Gdt_entry::Size_32); + gdt->set_entry_4k (Gdt::gdt_code_user/8, 0, user_max, + Gdt_entry::Access_user | + Gdt_entry::Access_code_read | + Gdt_entry::Accessed, Gdt_entry::Long_mode); + gdt->set_entry_4k (Gdt::gdt_data_user/8, 0, user_max, + Gdt_entry::Access_user | + Gdt_entry::Access_data_write | + Gdt_entry::Accessed, Gdt_entry::Size_32); +} + + +PUBLIC static inline +Mword +Cpu::stack_align(Mword stack) +{ return stack & ~0xf; } + diff --git a/kernel/fiasco/src/kern/ia32/64/crt0.S b/kernel/fiasco/src/kern/ia32/64/crt0.S new file mode 100644 index 00000000..ee48a0d2 --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/64/crt0.S @@ -0,0 +1,13 @@ +/* -*- c -*- */ + + .globl _start +_start: + /* Clear the base pointer so that stack backtraces will work. */ + xor %rbp,%rbp + lea _stack_end,%rsp + call __main + /* never returns */ + + .bss + .space 2048 +_stack_end: diff --git a/kernel/fiasco/src/kern/ia32/64/entry-native.S b/kernel/fiasco/src/kern/ia32/64/entry-native.S new file mode 100644 index 00000000..791da956 --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/64/entry-native.S @@ -0,0 +1,221 @@ + +#include "config_tcbsize.h" +#include "config_gdt.h" +#include "globalconfig.h" +#include "idt_init.h" +#include +#include "regdefs.h" +#include "shortcut.h" +#include "tcboffset.h" + + .p2align 4 + .globl entry_vec01_debug +entry_vec01_debug: +/* XXX we have to check single step bug */ +1: push $(0) + push $(1) + push %rax + push %rcx + push %rdx + push %rbx + mov %cr2,%rax + push %rax + push %rbp + push %rsi + push %rdi + push %r8 + push %r9 + push %r10 + push %r11 + push %r12 + push %r13 + push %r14 + push %r15 + jmp slowtraps + + + .p2align(4) + .globl entry_vec08_dbf +entry_vec08_dbf: + push $(0) + push $(8) + push %rax + push %rcx + push %rdx + push %rbx + mov %cr2,%rax + push %rax + push %rbp + push %rsi + push %rdi + push %r8 + push %r9 + push %r10 + push %r11 + push %r12 + push %r13 + push %r14 + push %r15 + mov %rsp,%rdi // 1st arg: trap state + call thread_handle_double_fault + jmp entry_vec08_dbf + + + .p2align(4) + .globl entry_vec0a_invalid_tss +entry_vec0a_invalid_tss: + andq $0xffffffffffffbfff, 24(%rsp) + add $8, %rsp /* skip error code */ + iretq + +/* PPro spurious interrupt bug: + * See "Pentium Pro Processor Specification Update / January 1999" + * Erratum "Virtual Wire mode through local APIC may cause int 15" + * This exception can be silently ignored */ + .p2align(4) + .globl entry_vec0f_apic_spurious_interrupt_bug +entry_vec0f_apic_spurious_interrupt_bug: + incl apic_spurious_interrupt_bug_cnt + iretq + + +/* XXX has to be fixed */ +/* APIC error interrupt */ + .p2align(4) + .globl entry_apic_error_interrupt +entry_apic_error_interrupt: + cld + SAVE_SCRATCH + lea SCRATCH_REGISTER_SIZE(%rsp), %rdi + call apic_error_interrupt + RESTORE_SCRATCH + iretq + +/* Intel Architecture Software Developer's Manual Volume 3, + * Advanced Programmable Interrupt Controller (APIC): + * Spurious Interrupt: "If at the time the INTA cycle is issued, the + * interupt that was to be dispensed has become masked (programmed by + * software), the local APIC will deliver a spurious-interrupt vector." */ + .p2align(4) + .globl entry_apic_spurious_interrupt +entry_apic_spurious_interrupt: + incl apic_spurious_interrupt_cnt + iretq + + .p2align(4) + .global entry_int_apic_ignore +entry_int_apic_ignore: + push %rcx + push %rdx + mov apic_io_base, %rcx + mov 0xf0(%rcx), %edx + movl $0, 0xb0(%rcx) + pop %rdx + pop %rcx + iretq + +#if defined(CONFIG_JDB) + + .p2align(4) + .global entry_syscall_log + .global entry_sys_fast_ipc_log +entry_syscall_log: +entry_sys_fast_ipc_log: + mov %rsp,%r15 /* save user rsp */ + mov syscall_rsp0, %rsp /* get address of kernel stack */ + pop %rsp /* set kernel stack */ + + push $(GDT_DATA_USER | SEL_PL_U) /* fake user ss */ + push %r15 /* save user rsp */ + push %r11 /* save user rflags */ + push $(GDT_CODE_USER | SEL_PL_U) /* fake user cs */ + push %rcx /* save user rip */ + + cld + SAVE_STATE_SYSEXIT + ESP_TO_TCB_AT %rbx + RESET_THREAD_CANCEL_AT %rbx + + call *syscall_table +in_slow_ipc5: + RESTORE_STATE_SYSEXIT + + pop %rcx /* load user rsp */ + /* make RIP canonical, workaround for intel IA32e flaw */ + shl $16, %rcx + sar $16, %rcx + add $8,%rsp /* through away cs */ + pop %r11 /* load user rflags */ + pop %r15 /* load user rsp */ + add $8,%rsp /* through away ss */ + + mov %r15,%rsp /* restore user rsp */ + sysretq + + .globl in_slow_ipc5 + +#endif // CONFIG_JDB + + +#if (defined (CONFIG_JDB_LOGGING) || !defined(CONFIG_ASSEMBLER_IPC_SHORTCUT)) + .p2align(4) + .global entry_syscall_c + .global entry_sys_fast_ipc_c +entry_syscall_c: +entry_sys_fast_ipc_c: + mov %rsp,%r15 /* save user rsp */ + mov syscall_rsp0,%rsp /* get address of kernel stack */ + pop %rsp /* set kernel stack */ + + push $(GDT_DATA_USER | SEL_PL_U) /* fake user ss */ + push %r15 /* save user rsp */ + push %r11 /* save user rflags */ + push $(GDT_CODE_USER | SEL_PL_U) /* fake user cs */ + push %rcx /* save user rip */ + + cld + SAVE_STATE_SYSEXIT + ESP_TO_TCB_AT %rbx + RESET_THREAD_CANCEL_AT %rbx + + call sys_ipc_wrapper +in_sc_ipc2: + RESTORE_STATE_SYSEXIT + + pop %rcx /* load user rsp */ + /* make RIP canonical, workaround for intel IA32e flaw */ + shl $16, %rcx + sar $16, %rcx + add $8,%rsp /* through away cs */ + pop %r11 /* load user rflags */ + pop %r15 /* load user rsp */ + add $8,%rsp /* through away ss */ + + mov %r15,%rsp /* restore user rsp */ + sysretq + + .globl in_sc_ipc2 +#endif + + .bss + .align 8 + .globl syscall_rsp0 +syscall_rsp0: + .space 8 /* address of esp0 in tss */ + .text + + .p2align(4) + .globl leave_from_sysenter_by_iret +leave_from_sysenter_by_iret: + ESP_TO_TCB_AT %rbx + RESET_THREAD_IPC_MASK_AT %rbx + RESTORE_STATE + pop %rax + orq $EFLAGS_IF, 8(%rsp) + iretq + + .bss + .space 4096 + .global dbf_stack_top +dbf_stack_top: + diff --git a/kernel/fiasco/src/kern/ia32/64/entry.S b/kernel/fiasco/src/kern/ia32/64/entry.S new file mode 100644 index 00000000..4a009037 --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/64/entry.S @@ -0,0 +1,512 @@ +/* + * This file contains a 'gate_init' initialization table + * to initialize the x86 processor trap vectors to default entrypoints. + * These entrypoints simply push a standard trap_state frame + * and jump to the 'trap_handler' routine. + */ + +#include "config_tcbsize.h" +#include "config_gdt.h" +#include "globalconfig.h" +#include "idt_init.h" +#include +#include "shortcut.h" +#include "tcboffset.h" + +#include "asm.h" + + +/* We make the trap handler an interrupt gate, because for debugging + purposes, we don't want any interrupts to occur until they're + explicitly enabled in the base_trap_handler (usually + Thread::handle_slow_trap). */ + +/* + * No error code. Clear error code and push trap number. + */ +#define EXCEPTION(n,name) \ + GATE_ENTRY(n,entry_##name,ACC_PL_K | ACC_INTR_GATE) ;\ + .p2align 3 ;\ +entry_##name: ;\ + push $(0) ;\ + push $(n) ;\ + save_all_regs ;\ + jmp _slowtraps + +/* + * User-accessible exception. Otherwise, same as above. + */ +#define EXCEP_USR(n,name) \ + GATE_ENTRY(n,entry_##name,ACC_PL_U | ACC_INTR_GATE) ;\ + .p2align 3 ;\ +entry_##name: ;\ + push $(0) ;\ + push $(n) ;\ + save_all_regs ;\ + jmp _slowtraps + +/* + * Error code has been pushed. Just push trap number. + */ +#define EXCEP_ERR(n,name) \ + GATE_ENTRY(n,entry_##name,ACC_PL_K | ACC_INTR_GATE) ;\ + .p2align 3 ;\ +entry_##name: ;\ + push $(n) ;\ + save_all_regs ;\ + jmp _slowtraps + +GATE_INITTAB_BEGIN(idt_init_table) + +EXCEPTION(0x00,vec00_zero_div) +/* IA32 has to handle breakpoint exceptions if occured exactly at + entry_sys_fast_ipc -- see ia32/entry-ia32.S */ +GATE_ENTRY(0x01,entry_vec01_debug,ACC_PL_K | ACC_INTR_GATE) +/* XXX IA32 has to handle NMI occured exactly at entry_sys_fast_ipc */ +EXCEP_USR(0x02,vec02_nmi) +EXCEP_USR(0x03,vec03_breakpoint) +EXCEP_USR(0x04,vec04_into) +EXCEP_USR(0x05,vec05_bounds) +EXCEPTION(0x06,vec06_invop) +/* EXCEPTION(0x07,nofpu) */ +// XXX we can't use a task gate, instead we must use IST +GATE_ENTRY(0x08,entry_vec08_dbf, ACC_PL_K | ACC_INTR_GATE) +EXCEPTION(0x09,vec09_fpu_ovfl) +/* EXCEP_ERR(0x0a,vec0a_inv_tss) */ +EXCEP_ERR(0x0b,vec0b_segnp) +EXCEP_ERR(0x0c,vec0c_stack_fault) +EXCEP_ERR(0x0d,vec0d_gen_prot) +/* EXCEP_ERR(0x0e,vec0e_page_fault) */ +/* EXCEPTION(0x0f,vec0f_trap_0f) */ +EXCEPTION(0x10,vec10_fpu_err) +EXCEP_ERR(0x11,vec11_align) +EXCEPTION(0x12,vec12_mcheck) +EXCEPTION(0x13,vec13_simd_err) + + + .p2align 4 + .type slowtraps,@function + .globl slowtraps + /* We have to introduce the label _slowtraps besides the label + slowtraps to achive that jmps from exception entry points + are optimized to two-byte jmps. The label slowtraps is visible + from outside. */ +_slowtraps: +slowtraps: + mov %rsp,%rdi /* ARG1: address of trap_state */ + mov $0, %esi /* ARG2: default CPU = 0 */ + cld +#ifndef CONFIG_NO_FRAME_PTR + mov 0x90(%rsp),%rax /* create artificial stack frame */ + push %rax /* push rip */ + push %rbp + lea (%rsp),%rbp +#endif + + /* Call the C handler function if one has been installed. */ + mov BASE_TRAP_HANDLER, %rax + or %rax,%rax + jz unexpected_trap_pop + call *%rax +in_slowtrap: + +#ifndef CONFIG_NO_FRAME_PTR + lea 0x10(%rsp),%rsp /* remove frame pointer */ +#endif + + /* If the handler function returned zero (success), + then resume execution as if the trap never happened. + Otherwise, just panic. */ + or %rax,%rax + jnz unexpected_trap + + restore_all_regs + add $0x10,%rsp /* pop trap number and error code */ + iretq + +unexpected_trap_pop: +#ifndef CONFIG_NO_FRAME_PTR + lea 0x10(%rsp), %rsp /* remove stack frame */ +#endif + +unexpected_trap: + mov %rsp,%rdi /* 1st arg: trap state */ + call trap_dump_panic + +GATE_ENTRY(0x0e,entry_vec0e_page_fault,ACC_PL_K | ACC_INTR_GATE) + +/* we must save %cr2 before we can be preempted -- therefore we're an + interrupt gate (invoked with interrupts turned off). Also, we + don't turn them on again here, but only after checking for + page-ins from the global page directory in thread_page_fault(). + XXX: If you make changes to stack layout here, fix thread_page_fault */ + +/* XXX slow version - sets up nice stack frame for debugger */ + + .p2align 4 + .type entry_vec0e_page_fault,@function +.globl entry_vec0e_page_fault +entry_vec0e_page_fault: + cld + SAVE_SCRATCH + +/* We must reset the cancel flag here atomically + if we are entering fresh from user mode and an IPC might occur. + NOTE: We cannot test the user-mode bit in the error code because + it will flag "kernel" in case an I/O-bitmap page is not mapped + during an I/O access. */ + + mov 0x58(%rsp),%rcx /* get CS from stack */ + andb $3,%cl /* retrieve current privilege level (CPL) */ + jz 1f /* CPL == 0 -> kernel, skip resetting state */ + ESP_TO_TCB_AT %rcx + RESET_THREAD_CANCEL_AT %rcx +1: + leaq 0x50(%rsp),%r8 /* arg5: ptr to return frame */ + mov PAGE_FAULT_ADDR,%rdi /* arg1: page fault address */ + mov 0x48(%rsp),%rsi /* arg2: error code */ + mov 0x50(%rsp),%rdx /* arg3: rip */ + mov 0x60(%rsp),%rcx /* arg4: rflags */ + call thread_page_fault + +in_page_fault: + or %rax,%rax + jz bad_page_fault + RESTORE_SCRATCH + add $8,%rsp /* remove error code */ + iretq + +/* If code or stack from a small address space are not yet mapped in the + current page directory we might get a page fault on return from the + trampoline page. In this case we cannot return to the trampoline page + after handling the fault because we are already in user mode (with + segment limits below kernel space) while the trampoline code is located + in kernel data space. So instead we change ESP and EIP to point to the + address the trampoline wanted to return to and do the normal IRET. */ + +/* recover from a bad page fault by invoking the slow_trap handler */ + .p2align 4 +bad_page_fault: + cli + /* we have on stack: r8, rdi, rsi, rdx, rcx, rax, error code + move registers down to make room for trap number + and build complete trap state before jumping to trap handler */ + RESTORE_SCRATCH + pushq $0x0e + save_all_regs + jmp slowtraps + + +/* FPU not available in this context. */ +GATE_ENTRY(0x07,entry_vec07_fpu_unavail, ACC_PL_K | ACC_INTR_GATE) + +/* do all of this with disabled interrupts */ + .p2align 4 + .type entry_vec07_fpu_unavail,@function +entry_vec07_fpu_unavail: + cld + SAVE_SCRATCH + mov SCRATCH_REGISTER_SIZE(%rsp), %rdi + call thread_handle_fputrap +in_handle_fputrap: + test %eax,%eax + jz real_fpu_exception + RESTORE_SCRATCH + iretq +real_fpu_exception: + RESTORE_SCRATCH + pushq $(0) + pushq $(7) + save_all_regs + jmp _slowtraps + + +/* timer interrupt */ +#ifdef CONFIG_SCHED_PIT +GATE_ENTRY(0x20,entry_int_timer,ACC_PL_K | ACC_INTR_GATE) +#endif +#ifdef CONFIG_SCHED_RTC +GATE_ENTRY(0x28,entry_int_timer,ACC_PL_K | ACC_INTR_GATE) +#endif +#ifdef CONFIG_SCHED_APIC +GATE_ENTRY(APIC_IRQ_BASE, entry_int_timer,ACC_PL_K | ACC_INTR_GATE) +#endif +#ifdef CONFIG_SCHED_HPET +/* HPET is set at startup */ +#endif + + .p2align 4 + .globl entry_int_timer +entry_int_timer: + SAVE_SCRATCH +do_timer_interrupt: + cld + mov SCRATCH_REGISTER_SIZE(%rsp),%rdi /* pass rip for logging */ + call thread_timer_interrupt /* enter with disabled irqs */ +in_timer_interrupt: + RESTORE_SCRATCH + iretq + + .p2align 4 + .globl entry_int_timer_slow +entry_int_timer_slow: + cld + SAVE_SCRATCH + call thread_timer_interrupt_slow /* enter with disabled irqs */ +in_timer_interrupt_slow: + jmp do_timer_interrupt + + + .p2align 4 + .globl entry_int_timer_stop +entry_int_timer_stop: + cld + SAVE_SCRATCH + call thread_timer_interrupt_stop + RESTORE_SCRATCH + iretq + +/* other interrupts */ + +#define INTERRUPT(int,name) \ + GATE_ENTRY(int,entry_##name,ACC_PL_K | ACC_INTR_GATE) ;\ + .p2align 3 ;\ +entry_##name: ;\ + SAVE_SCRATCH ;\ + mov 0x28(%rsp),%rsi ;\ + mov $ (int - 0x20),%rdi ;\ + jmp all_irqs + + .type __generic_irq_entry,@function + .global __generic_irq_entry + +__generic_irq_entry: + push %rsi + push %rax + push %rcx + push %rdx + push %r8 + push %r9 + push %r10 + push %r11 + + .p2align 4 + .type all_irqs,@function +all_irqs: + cld + call irq_interrupt /* enter with disabled irqs */ +in_interrupt: + RESTORE_SCRATCH + +entry_int_pic_ignore: + iretq + + .global entry_int_pic_ignore + .global entry_int7 + .global entry_intf + +#ifndef CONFIG_SCHED_PIT +INTERRUPT(0x20,int0) +#endif +INTERRUPT(0x27,int7) +INTERRUPT(0x2f,intf) +#ifndef CONFIG_SCHED_RTC +INTERRUPT(0x28,int8) +#endif + +/* system calls */ +#define SYSTEM_CALL(int,name) \ + GATE_ENTRY(int,entry_##name,ACC_PL_U | ACC_INTR_GATE) ;\ + .p2align 4 ;\ +entry_##name: ;\ + push %rax ;\ + mov $(syscall_table+8*(int-0x30)), %rax ;\ + jmp all_syscalls + + .p2align 4 + .type all_syscalls,@function +all_syscalls: + cld + SAVE_STATE + ESP_TO_TCB_AT %rbx + RESET_THREAD_CANCEL_AT %rbx + + call *(%rax) +in_syscall: +ret_from_syscall: + RESTORE_STATE + pop %rax + iretq + +#ifdef CONFIG_ASSEMBLER_IPC_SHORTCUT +GATE_ENTRY(0x30,entry_sys_ipc,ACC_PL_U | ACC_INTR_GATE); +#else +GATE_ENTRY(0x30,entry_sys_ipc_c,ACC_PL_U | ACC_INTR_GATE); +#endif + +#if defined (CONFIG_JDB_LOGGING) || !defined(CONFIG_ASSEMBLER_IPC_SHORTCUT) + .p2align 4 + .globl entry_sys_ipc_c +entry_sys_ipc_c: + cld + push %rax + SAVE_STATE + ESP_TO_TCB_AT %rbx + RESET_THREAD_CANCEL_AT %rbx + + + call sys_ipc_wrapper +in_sc_ipc1: + RESTORE_STATE + pop %rax + iretq + + .globl in_sc_ipc1 +#endif + +#ifdef CONFIG_JDB + /* The slow variant of sys_ipc_entry is used when logging IPC */ + .p2align 4 + .globl entry_sys_ipc_log + +entry_sys_ipc_log: + cld + push %rax + SAVE_STATE + ESP_TO_TCB_AT %rbx + RESET_THREAD_CANCEL_AT %rbx + call *syscall_table + +in_slow_ipc4: + RESTORE_STATE + pop %rax + iretq + + .globl in_slow_ipc4 +#endif // CONFIG_JDB + + // these labels help show_tcb to guess the thread state + .globl in_syscall + .globl in_slowtrap + .globl in_page_fault + .globl in_handle_fputrap + .globl in_interrupt + .globl in_timer_interrupt + .globl in_timer_interrupt_slow + + +SYSTEM_CALL(0x32,sys_invoke_debug) + +/* these functions are implemented in entry-native.S */ +GATE_ENTRY(0x0a,entry_vec0a_invalid_tss,ACC_PL_K | ACC_INTR_GATE) +GATE_ENTRY(0x0f,entry_vec0f_apic_spurious_interrupt_bug,ACC_PL_K | ACC_INTR_GATE) +GATE_ENTRY(APIC_IRQ_BASE + 3,entry_apic_error_interrupt,ACC_PL_K | ACC_INTR_GATE) +GATE_ENTRY(APIC_IRQ_BASE + 0xf,entry_apic_spurious_interrupt,ACC_PL_K | ACC_INTR_GATE) + +#ifdef CONFIG_MP +GATE_ENTRY(APIC_IRQ_BASE + 2, entry_ipi, ACC_PL_K | ACC_INTR_GATE) +GATE_ENTRY(APIC_IRQ_BASE - 2, entry_debug_ipi, ACC_PL_K | ACC_INTR_GATE) +GATE_ENTRY(APIC_IRQ_BASE - 1, entry_ipi_remote_request, ACC_PL_K | ACC_INTR_GATE) +#endif + +GATE_INITTAB_END + + .p2align + .globl leave_by_trigger_exception +leave_by_trigger_exception: + sub $40, %rsp + pushq $0x00 + pushq $0xff + save_all_regs + pushq $_slowtraps + jmp thread_restore_exc_state + + + .p2align + .globl leave_by_vcpu_upcall +leave_by_vcpu_upcall: + cli + sub $40,%rsp /* clean up stack from previous + * CPL0-CPL0 iret */ + SAVE_SCRATCH + call thread_restore_exc_state + + ESP_TO_TCB_AT %rcx + mov OFS__THREAD__USER_VCPU(%rcx), %rdi + mov OFS__THREAD__VCPU_STATE(%rcx), %rcx + add $(VAL__SIZEOF_TRAP_STATE - 40), %rcx + mov SCRATCH_REGISTER_SIZE(%rsp), %rdx + mov %rdx, (%rcx) /* RIP */ + mov 16 + SCRATCH_REGISTER_SIZE(%rsp), %rdx + mov %rdx, 16(%rcx) /* RFLAGS */ + mov 24 + SCRATCH_REGISTER_SIZE(%rsp), %rdx + mov %rdx, 24(%rcx) /* RSP */ + mov 32 + SCRATCH_REGISTER_SIZE(%rsp), %rdx + mov %rdx, 32(%rcx) /* SS */ + + mov (0*8)(%rsp), %rdx /* r11 */ + mov %rdx, -(14*8)(%rcx) + mov (1*8)(%rsp), %rdx /* r10 */ + mov %rdx, -(13*8)(%rcx) + mov (2*8)(%rsp), %rdx + mov %rdx, -(12*8)(%rcx) /* r9 */ + mov (3*8)(%rsp), %rdx + mov %rdx, -(11*8)(%rcx) /* r8 */ + mov (4*8)(%rsp), %rdx + mov %rdx, -(5*8)(%rcx) /* rdx */ + mov (5*8)(%rsp), %rdx + mov %rdx, -(4*8)(%rcx) /* rcx */ + mov (6*8)(%rsp), %rdx + mov %rdx, -(3*8)(%rcx) /* rax */ + mov (7*8)(%rsp), %rdx + mov %rdx, -(9*8)(%rcx) /* rsi */ + mov (8*8)(%rsp), %rdx + mov %rdx, -(10*8)(%rcx) /* rdi */ + + lea SCRATCH_REGISTER_SIZE(%rsp), %rdx + lea -(5*8)(%rcx), %rsp + + push %rbx + sub $8, %rsp + push %rbp + sub $(6*8), %rsp + push %r12 + push %r13 + push %r14 + push %r15 + + /*add SCRATCH_REGISTER_SIZE, %esp*/ +#if 0 +#ifdef CONFIG_PF_UX +# define REG_GS CPU_GS +#else +# define REG_GS %gs +#endif + + pushq %fs /* we save the segment regs in the trap */ + pushq REG_GS /* state, but we do not restore them. We */ + pushq %ds /* rather reload them using */ + pushq %es /* RESET_{KERNEL,USER}_SEGMENTS */ +#endif + mov %rdx, %rsp + mov -VAL__SIZEOF_TRAP_STATE + 40 + OFS__VCPU_STATE__ENTRY_SP(%rcx), %rax + mov %rax, 24(%rsp) + mov -VAL__SIZEOF_TRAP_STATE + 40 + OFS__VCPU_STATE__ENTRY_IP(%rcx), %rax + mov %rax, 0(%rsp) + movq $EFLAGS_IF, 16(%rsp) + iretq + + .p2align + .globl vcpu_resume +vcpu_resume: + mov %rdi, %rsp +#if 0 + popq %es + popq %ds + popq REG_GS + popq %fs +#endif + restore_all_regs + add $(2*8), %rsp + iretq + diff --git a/kernel/fiasco/src/kern/ia32/64/entry_frame-amd64.cpp b/kernel/fiasco/src/kern/ia32/64/entry_frame-amd64.cpp new file mode 100644 index 00000000..c19fa67e --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/64/entry_frame-amd64.cpp @@ -0,0 +1,153 @@ +/* + * Fiasco Kernel-Entry Frame-Layout Code + * Shared between UX and native IA32. + */ + +INTERFACE[amd64]: + +#include "types.h" + +EXTENSION class Syscall_frame +{ +protected: + Mword _r15; + Mword _r14; + Mword _r13; + Mword _r12; + Mword _r11; + Mword _r10; + Mword _r9; + Mword _r8; + Mword _rcx; + Mword _rdx; + Mword _rsi; + Mword _rdi; + Mword _rbx; + Mword _rbp; + Mword _rax; +}; + +EXTENSION class Return_frame +{ +private: + Mword _rip; + Mword _cs; + Mword _rflags; + Mword _rsp; + Mword _ss; + +public: + enum { Pf_ax_offset = 2 }; +}; + +IMPLEMENTATION[ux,amd64]: + +//--------------------------------------------------------------------------- +// basic Entry_frame methods for IA32 +// +#include "mem_layout.h" + +IMPLEMENT inline +Address +Return_frame::ip() const +{ return _rip; } + +IMPLEMENT inline NEEDS["mem_layout.h"] +Address +Return_frame::ip_syscall_page_user() const +{ + Address rip = ip(); + if ((rip & Mem_layout::Syscalls) == Mem_layout::Syscalls) + rip = *(Mword*)sp(); + return rip; +} + +IMPLEMENT inline +void +Return_frame::ip(Mword ip) +{ _rip = ip; } + +IMPLEMENT inline +Address +Return_frame::sp() const +{ return _rsp; } + +IMPLEMENT inline +void +Return_frame::sp(Mword sp) +{ _rsp = sp; } + +PUBLIC inline +Mword +Return_frame::flags() const +{ return _rflags; } + +PUBLIC inline +void +Return_frame::flags(Mword flags) +{ _rflags = flags; } + +PUBLIC inline +Mword +Return_frame::cs() const +{ return _cs; } + +PUBLIC inline +void +Return_frame::cs(Mword cs) +{ _cs = cs; } + +PUBLIC inline +Mword +Return_frame::ss() const +{ return _ss; } + +PUBLIC inline +void +Return_frame::ss(Mword ss) +{ _ss = ss; } + +//--------------------------------------------------------------------------- +IMPLEMENTATION [ux,amd64]: + +//--------------------------------------------------------------------------- +// IPC frame methods for IA32 +// +IMPLEMENT inline +Mword Syscall_frame::next_period() const +{ return false; } + +IMPLEMENT inline +Mword Syscall_frame::from_spec() const +{ return _rsi; } + +IMPLEMENT inline +void Syscall_frame::from(Mword f) +{ _rsi = f; } + +IMPLEMENT inline +L4_obj_ref Syscall_frame::ref() const +{ return L4_obj_ref::from_raw(_rdx); } + +IMPLEMENT inline +void Syscall_frame::ref(L4_obj_ref const &r) +{ _rdx = r.raw(); } + +IMPLEMENT inline +L4_timeout_pair Syscall_frame::timeout() const +{ return L4_timeout_pair(_rcx); } + +IMPLEMENT inline +void Syscall_frame::timeout(L4_timeout_pair const &to) +{ _rcx = to.raw(); } + +IMPLEMENT inline Utcb *Syscall_frame::utcb() const +{ return reinterpret_cast(_rdi); } + +IMPLEMENT inline L4_msg_tag Syscall_frame::tag() const +{ return L4_msg_tag(_rax); } + +IMPLEMENT inline +void Syscall_frame::tag(L4_msg_tag const &tag) +{ _rax = tag.raw(); } + diff --git a/kernel/fiasco/src/kern/ia32/64/kmem-ia32-64.cpp b/kernel/fiasco/src/kern/ia32/64/kmem-ia32-64.cpp new file mode 100644 index 00000000..7ad8c7a0 --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/64/kmem-ia32-64.cpp @@ -0,0 +1,7 @@ +IMPLEMENTATION [amd64]: + +PRIVATE static inline FIASCO_INIT_CPU +void +Kmem::init_cpu_arch(Cpu &, void **) +{} + diff --git a/kernel/fiasco/src/kern/ia32/64/linking.h b/kernel/fiasco/src/kern/ia32/64/linking.h new file mode 100644 index 00000000..f4877895 --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/64/linking.h @@ -0,0 +1,8 @@ +#pragma once + +#define FIASCO_MP_TRAMP_PAGE 0x1000 // must be below 1MB +#define FIASCO_IMAGE_PHYS_START 0x400000 +//#define FIASCO_IMAGE_PHYS_START 0x2000 +#define FIASCO_IMAGE_VIRT_START 0xfffffffff0000000 + +#define FIASCO_IMAGE_PHYS_OFFSET (FIASCO_IMAGE_VIRT_START - (FIASCO_IMAGE_PHYS_START & 0xffffffffffc00000)) diff --git a/kernel/fiasco/src/kern/ia32/64/low_level.h b/kernel/fiasco/src/kern/ia32/64/low_level.h new file mode 100644 index 00000000..eda811ef --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/64/low_level.h @@ -0,0 +1,185 @@ +#ifndef LOW_LEVEL_H +#define LOW_LEVEL_H + +#include "asm.h" +#include "regdefs.h" +#include "shortcut.h" +#include "tcboffset.h" + + +#define REGISTER_SIZE 8 + + .macro save_all_regs + push %rax + push %rcx + push %rdx + push %rbx + mov %cr2,%rax + push %rax + push %rbp + push %rsi + push %rdi + push %r8 + push %r9 + push %r10 + push %r11 + push %r12 + push %r13 + push %r14 + push %r15 + .endm + + .macro restore_all_regs + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %r11 + pop %r10 + pop %r9 + pop %r8 + pop %rdi + pop %rsi + pop %rbp + add $0x08,%rsp /* pop cr2 */ + pop %rbx + pop %rdx + pop %rcx + pop %rax + .endm + + .macro SAVE_STATE_SYSEXIT + push %rax + push %rbp + push %rbx + push %rdi + push %rsi + push %rdx + push $0 /* rcx contains user rip */ + push %r8 + push %r9 + push %r10 + push $0 /* r11 contains user rflags */ + push %r12 + push %r13 + push %r14 + push $0 /* r15 contains user rsp */ + .endm + + .macro RESTORE_STATE_SYSEXIT + add $8,%rsp /* r15 contains user rsp */ + pop %r14 + pop %r13 + pop %r12 + add $8,%rsp /* r11 contains user rflags */ + pop %r10 + pop %r9 + pop %r8 + add $8,%rsp /* rcx contains user eip */ + pop %rdx + pop %rsi + pop %rdi + pop %rbx + pop %rbp + pop %rax + .endm + + + .macro DO_SYSEXIT + RESTORE_STATE_SYSEXIT + // CHECK_SANITY $3 /* scratches ecx */ + // RESTORE_IOPL + mov (%rsp), %rcx + /* make RIP canonical, workaround for intel IA32e flaw */ + shl $16, %rcx + sar $16, %rcx + mov 16(%rsp), %r11 /* load user rflags */ + mov 24(%rsp), %rsp /* user esp */ + /* mmh, maybe weird things will + happen, if we set an hardware breakpoint before the sysretq + maybe we should use the IST stuff to enforce always + an good kernel stack + */ + sysretq + .endm + + .macro RESET_THREAD_CANCEL_AT reg + andl $~(Thread_cancel | Thread_dis_alien), OFS__THREAD__STATE (\reg) + .endm + + .macro RESET_THREAD_IPC_MASK_AT reg + andl $~Thread_ipc_mask, OFS__THREAD__STATE (\reg) + .endm + + .macro ESP_TO_TCB_AT reg + mov %rsp, \reg + andq $~(THREAD_BLOCK_SIZE - 1), \reg + .endm + + .macro SAVE_STATE + push %rbp + push %rbx + push %rdi + push %rsi + push %rdx + push %rcx + push %r8 + push %r9 + push %r10 + push %r11 + push %r12 + push %r13 + push %r14 + push %r15 + .endm + + .macro RESTORE_STATE + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %r11 + pop %r10 + pop %r9 + pop %r8 + pop %rcx + pop %rdx + pop %rsi + pop %rdi + pop %rbx + pop %rbp + .endm + +#define SCRATCH_REGISTER_SIZE 72 + .macro SAVE_SCRATCH + push %rdi + push %rsi + push %rax /* must be ax cx dx for pagein_tcb_request */ + push %rcx + push %rdx + push %r8 + push %r9 + push %r10 + push %r11 + .endm + + .macro RESTORE_SCRATCH + pop %r11 + pop %r10 + pop %r9 + pop %r8 + pop %rdx + pop %rcx + pop %rax + pop %rsi + pop %rdi + .endm + + .macro IRET_INSN + iretq + .endm + +#define PAGE_FAULT_ADDR %cr2 +#define PAGE_DIR_ADDR %cr3 + +#endif //LOW_LEVEL_H diff --git a/kernel/fiasco/src/kern/ia32/64/main-ia32-64.cpp b/kernel/fiasco/src/kern/ia32/64/main-ia32-64.cpp new file mode 100644 index 00000000..ef756f5b --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/64/main-ia32-64.cpp @@ -0,0 +1,77 @@ +/* + * Fiasco AMD64 + * Shared main startup/shutdown code + */ + +INTERFACE[amd64]: + +#include "initcalls.h" +#include "std_macros.h" + +class Kernel_thread; + + +IMPLEMENTATION[amd64]: + +#include +#include "config.h" +#include "cpu.h" +#include "div32.h" +#include "globals.h" +#include "kernel_thread.h" +#include "kernel_task.h" + +FIASCO_INIT +void +kernel_main(void) +{ + unsigned dummy; + + Cpu const &cpu = *Cpu::boot_cpu(); + + // caution: no stack variables in this function because we're going + // to change the stack pointer! + cpu.print(); + cpu.show_cache_tlb_info(""); + + printf ("\nFreeing init code/data: %lu bytes (%lu pages)\n\n", + (Address)(&Mem_layout::initcall_end - &Mem_layout::initcall_start), + (Address)(&Mem_layout::initcall_end - &Mem_layout::initcall_start + >> Config::PAGE_SHIFT)); + + // Perform architecture specific initialization + main_arch(); + + // create kernel thread + static Kernel_thread *kernel = new (Ram_quota::root) Kernel_thread; + Task *const ktask = Kernel_task::kernel_task(); + check(kernel->bind(ktask, User::Ptr(0))); + + // switch to stack of kernel thread and bootstrap the kernel + asm volatile + (" movq %%rax, %%cr3 \n\t" // restore proper cr3 after running on the mp boot dir + " movq %3, %%rsp \n\t" // switch stack + " call call_bootstrap \n\t" // bootstrap kernel thread + : "=a" (dummy), "=c" (dummy), "=d" (dummy) + : "S" (kernel->init_stack()), "D" (kernel), + "a" (Mem_layout::pmem_to_phys(Kmem::dir()))); +} + + +//------------------------------------------------------------------------ +IMPLEMENTATION[amd64 && mp]: + +#include "kernel_thread.h" + +void +main_switch_ap_cpu_stack(Kernel_thread *kernel) +{ + Mword dummy; + + // switch to stack of kernel thread and bootstrap the kernel + asm volatile + (" mov %%rsi, %%rsp \n\t" // switch stack + " call call_ap_bootstrap \n\t" // bootstrap kernel thread + : "=a" (dummy), "=c" (dummy), "=d" (dummy) + : "a"(kernel), "S" (kernel->init_stack())); +} diff --git a/kernel/fiasco/src/kern/ia32/64/mapping-ia32-64.cpp b/kernel/fiasco/src/kern/ia32/64/mapping-ia32-64.cpp new file mode 100644 index 00000000..3ecdfa02 --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/64/mapping-ia32-64.cpp @@ -0,0 +1,28 @@ +INTERFACE [amd64]: + +#include "types.h" +class Space; +class Treemap; + +class Mapping_entry +{ +public: + enum { Alignment = 1 }; + union + { + struct + { + unsigned long _space:32; ///< Address-space number +/* unsigned long _pad:1;*/ + unsigned long address:36; ///< Virtual address in address space + } data; + Treemap *_submap; + }; + Unsigned8 _depth; + + void set_space(Space *s) { data._space = (unsigned long)s & 0x0ffffffffUL; } + Space *space() const + { return (Space*)(0xffffffff00000000UL | (unsigned long)data._space); } +} __attribute__((packed)); + + diff --git a/kernel/fiasco/src/kern/ia32/64/mem_layout-ia32-64.cpp b/kernel/fiasco/src/kern/ia32/64/mem_layout-ia32-64.cpp new file mode 100644 index 00000000..301ded99 --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/64/mem_layout-ia32-64.cpp @@ -0,0 +1,135 @@ +INTERFACE [amd64]: + +#include "types.h" +#include "config.h" +#include "linking.h" +#include "template_math.h" + +EXTENSION class Mem_layout +{ +public: + enum Flags + { + /// Is the adapter memory in the kernel image super page? + Adap_in_kernel_image = FIASCO_IMAGE_PHYS_START < Config::SUPERPAGE_SIZE, + }; + + enum + { + Utcb_addr = 0xffffffff8ff00000UL, ///< % 4kB UTCB map address + Kip_auto_map = 0xffffffff8fff2000UL, ///< % 4kB + User_max = 0x0000800000000000UL, + Service_page = 0xffffffffeac00000UL, ///< % 4MB global mappings + Local_apic_page = Service_page + 0x0000, ///< % 4KB + Kmem_tmp_page_1 = Service_page + 0x2000, ///< % 4KB size 8KB + Kmem_tmp_page_2 = Service_page + 0x4000, ///< % 4KB size 8KB + Tbuf_status_page = Service_page + 0x6000, ///< % 4KB + Tbuf_ustatus_page = Tbuf_status_page, + Jdb_bench_page = Service_page + 0x8000, ///< % 4KB + utcb_ptr_align = Tl_math::Ld<64>::Res, // 64byte cachelines + Idt = Service_page + 0xfe000, ///< % 4KB + Syscalls = Service_page + 0xff000, ///< % 4KB syscall page + Tbuf_buffer_area = Service_page + 0x200000, ///< % 2MB + Tbuf_ubuffer_area = Tbuf_buffer_area, + // 0xffffffffeb800000-0xfffffffffec000000 (8MB) free + Io_map_area_start = 0xffffffffec000000UL, + Io_map_area_end = 0xffffffffec800000UL, + ___free_3 = 0xffffffffec800000UL, ///< % 4MB + ___free_4 = 0xffffffffec880000UL, ///< % 4MB + Jdb_debug_start = 0xffffffffecc00000UL, ///< % 4MB JDB symbols/lines + Jdb_debug_end = 0xffffffffee000000UL, ///< % 4MB + // 0xffffffffee000000-0xffffffffef800000 (24MB) free + Kstatic = 0xffffffffef800000UL, ///< % 4MB Io_bitmap + Io_bitmap = 0xffffffffefc00000UL, ///< % 4MB + Vmem_end = 0xfffffffff0000000UL, + + Kernel_image = FIASCO_IMAGE_VIRT_START, + Kernel_image_end = Kernel_image + Config::SUPERPAGE_SIZE, + + Adap_image = Adap_in_kernel_image + ? Kernel_image + : Kernel_image + Config::SUPERPAGE_SIZE, + + Adap_vram_mda_beg = Adap_image + 0xb0000, ///< % 8KB video RAM MDA memory + Adap_vram_mda_end = Adap_image + 0xb8000, + Adap_vram_cga_beg = Adap_image + 0xb8000, ///< % 8KB video RAM CGA memory + Adap_vram_cga_end = Adap_image + 0xc0000, + + Caps_start = 0xfffffffff0800000UL, ///< % 4MB + Caps_end = 0xfffffffffc400000UL, ///< % 4MB + Physmem = 0xfffffffffc400000UL, ///< % 4MB kernel memory + Kernel_end = 0xffffffffffffffffUL+1, ///< % end of address space + }; + + enum Offsets + { + Kernel_image_offset = FIASCO_IMAGE_PHYS_OFFSET, + }; + + enum Phys_addrs + { + Kernel_image_phys = FIASCO_IMAGE_PHYS_START & Config::SUPERPAGE_MASK, + Adap_image_phys = 0, + }; + + template < typename T > static T* boot_data (T const *addr); + + static Address pmem_size; +private: + static Address physmem_offs asm ("PHYSMEM_OFFS"); +}; + +IMPLEMENTATION [amd64]: + +#include +#include + +Address Mem_layout::physmem_offs; +Address Mem_layout::pmem_size; + + +PUBLIC static inline +void +Mem_layout::kphys_base (Address base) +{ + physmem_offs = (Address)Physmem - base; +} + +PUBLIC static inline NEEDS[] +Address +Mem_layout::pmem_to_phys (Address addr) +{ + assert (in_pmem(addr)); + return addr - physmem_offs; +} + +PUBLIC static inline NEEDS[] +Address +Mem_layout::pmem_to_phys (const void *ptr) +{ + Address addr = reinterpret_cast
(ptr); + + assert_kdb (in_pmem(addr)); + return addr - physmem_offs; +} + +PUBLIC static inline +Address +Mem_layout::phys_to_pmem(Address addr) +{ + return addr + physmem_offs; +} + +PUBLIC static inline +Mword +Mem_layout::in_kernel_image(Address addr) +{ + return addr >= Kernel_image && addr < Kernel_image_end; +} + +PUBLIC static inline +Mword +Mem_layout::in_pmem(Address addr) +{ + return addr >= Physmem; +} diff --git a/kernel/fiasco/src/kern/ia32/64/mem_unit-amd64.cpp b/kernel/fiasco/src/kern/ia32/64/mem_unit-amd64.cpp new file mode 100644 index 00000000..cbe8bbe2 --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/64/mem_unit-amd64.cpp @@ -0,0 +1,35 @@ +INTERFACE[amd64]: + +#include "types.h" + +class Mem_unit +{ +}; + + +IMPLEMENTATION[amd64]: + +/** Flush the whole TLB. + */ +PUBLIC static inline +void +Mem_unit::tlb_flush() +{ + Unsigned64 dummy; + asm volatile ("movq %%cr3,%0; movq %0,%%cr3 " : "=r"(dummy)); +} + + +/** Flush TLB at virtual address. + */ +PUBLIC static inline +void +Mem_unit::tlb_flush(Address addr) +{ + asm volatile ("invlpg %0" : : "m" (*(char*)addr) : "memory"); +} + +PUBLIC static inline +void +Mem_unit::clean_dcache(void *) +{} diff --git a/kernel/fiasco/src/kern/ia32/64/paging-ia32-64.cpp b/kernel/fiasco/src/kern/ia32/64/paging-ia32-64.cpp new file mode 100644 index 00000000..1bc533ba --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/64/paging-ia32-64.cpp @@ -0,0 +1,86 @@ +INTERFACE[amd64]: + +#include +#include "types.h" +#include "config.h" +#include "mem_layout.h" +#include "ptab_base.h" + +class PF {}; + +class Pte_base +{ +public: + typedef Mword Raw; + + enum + { + Super_level = 2, + Valid = 0x00000001LL, ///< Valid + Writable = 0x00000002LL, ///< Writable + User = 0x00000004LL, ///< User accessible + Write_through = 0x00000008LL, ///< Write through + Cacheable = 0x00000000LL, ///< Cache is enabled + Noncacheable = 0x00000010LL, ///< Caching is off + Referenced = 0x00000020LL, ///< Page was referenced + Dirty = 0x00000040LL, ///< Page was modified + Pse_bit = 0x00000080LL, ///< Indicates a super page + Cpu_global = 0x00000100LL, ///< pinned in the TLB + L4_global = 0x00000200LL, ///< pinned in the TLB + Pfn = 0x000ffffffffff000LL, ///< page frame number + }; + + Mword addr() const { return _raw & Pfn; } + +protected: + Raw _raw; + +private: + static Unsigned32 _cpu_global; +}; + +class Pt_entry : public Pte_base +{ +public: + enum { Page_shift = Config::PAGE_SHIFT }; + Mword leaf() const { return true; } + void set(Address p, bool intermed, bool present, unsigned long attrs = 0) + { + _raw = (p & Pfn) | (present ? 1 : 0) + | (intermed ? (Writable | User | Cacheable) : 0) | attrs; + } +}; + +class Pd_entry : public Pte_base +{ +public: + enum { Page_shift = Config::SUPERPAGE_SHIFT }; + Mword leaf() const { return _raw & Pse_bit; } + void set(Address p, bool intermed, bool present, unsigned long attrs = 0) + { + _raw = (p & Pfn) | (present ? 1 : 0) + | (intermed ? (Writable | User | Cacheable) : Pse_bit) | attrs; + } +}; + +class Pdp_entry : public Pte_base +{ +public: + // this is just a dummy, because there are no real pages on level 0 and 1 + enum { Page_shift = 0 }; + Mword leaf() const { return false; } + void set(Address p, bool, bool present, unsigned long attrs = 0) + { + _raw = (p & Pfn) | (present ? 1 : 0) + | (Writable | User | Cacheable) | attrs; + } +}; + + +typedef Ptab::List< Ptab::Traits, + Ptab::List< Ptab::Traits, + Ptab::List< Ptab::Traits, + Ptab::Traits > > > Ptab_traits; + +typedef Ptab::Shift::List Ptab_traits_vpn; +typedef Ptab::Page_addr_wrap Ptab_va_vpn; diff --git a/kernel/fiasco/src/kern/ia32/64/shortcut.S b/kernel/fiasco/src/kern/ia32/64/shortcut.S new file mode 100644 index 00000000..268708e7 --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/64/shortcut.S @@ -0,0 +1,512 @@ + +#include "config_gdt.h" +#include "config_tcbsize.h" +#include "globalconfig.h" +#include "idt_init.h" +#include +#include "shortcut.h" +#include "tcboffset.h" +#include "regdefs.h" +#include "asm.h" + +#define L4_IPC_RECANCELED 0x40 +#define L4_IPC_RETIMEOUT 0x20 + +#define PDIR_IDX(virt) (((virt) >> 22) & 0x3ff) + +/* stack layout + SS + ESP + EFL + CS + EIP + + %rax + %rbp + %rbx + %rdi + %rsi + %rdx + %rcx + %r8 + %r9 + %r10 + %r11 + %r12 + %r13 + %r14 + %r15 +*/ + + +// XXXX: let save the user r8-r14 or use them as +// additional IPC registers (would be the best solution) +// then we can save and restore them lazily (only +// if we need will block. If we dont block, +// we can leave them in place. + +#define OFS__THREAD__SS (THREAD_BLOCK_SIZE - 1*8) +#define OFS__THREAD__ESP (THREAD_BLOCK_SIZE - 2*8) +#define OFS__THREAD__EFL (THREAD_BLOCK_SIZE - 3*8) +#define OFS__THREAD__CS (THREAD_BLOCK_SIZE - 4*8) +#define OFS__THREAD__EIP (THREAD_BLOCK_SIZE - 5*8) + +// In the SYSENTER path all kernel memory accesses go through stack +// segment ss. This way we do not need to RESET_KERNEL_SEGMENTS in +// SMAS. The RESET_KERNEL_SEGMENTS function is executed if the shortcut +// fails or we switch to another thread which is not in shortcut. + + // + // ready_enqueue + // + // Here we don't check if the context which is to be enqueued is + // not current() and has the same priority as current(). In this + // case, Context::ready_enqueue() enqueues current() first. We + // don't do this here but the location this macro is called from + // has to check this. + // + // precondition : ecx = thread->sched() + // rax = thread->sched()->prio() (upper 32bits 0) + // scratches : ecx, edx + .macro READY_ENQUEUE thread, label + // if (prio > prio_highest) + // prio_highest = prio + cmp CONTEXT_PRIO_HIGHEST, %eax + jbe 1f + mov %eax, CONTEXT_PRIO_HIGHEST + +1: mov CONTEXT_PRIO_NEXT (, %rax, 8), %rdx + // if (!prio_next[prio]) + or %rdx, %rdx + jnz 2f + // prio_next[prio] = this; + mov \thread, CONTEXT_PRIO_NEXT (, %rax, 8) + // ready_next = this; + mov \thread, OFS__THREAD__READY_NEXT (\thread) + // ready_prev = this; + mov \thread, OFS__THREAD__READY_PREV (\thread) + jmp \label +2: // ecx = prio_next[prio]->ready_prev + mov OFS__THREAD__READY_PREV (%rdx), %rcx + // ready_next = prio_next[prio] + mov %rdx, OFS__THREAD__READY_NEXT (\thread) + // ready_prev = prio_next[prio]->ready_prev + mov %rcx, OFS__THREAD__READY_PREV (\thread) + // prio_next[prio]->ready_prev = this + mov \thread, OFS__THREAD__READY_PREV (%rdx) + // ready_prev->ready_next = this + mov \thread, OFS__THREAD__READY_NEXT (%rcx) + .endm + + +# define KIP_SWITCH_TIME 0xA8 +# define KIP_CONSUMED_TIME 0xB8 + + // + // bookkeeping for the time a thread consumed + // + // precondition : ebx = THIS + // esi = DEST + // scratches : eax, ecx, edx, ebp + .macro CONSUME_TIME + .endm + + +#ifdef CONFIG_ASSEMBLER_IPC_SHORTCUT + +// only dummys + + .globl entry_sys_ipc +entry_sys_ipc: + push %rax + SAVE_STATE + ESP_TO_TCB_AT %rbx + RESET_THREAD_CANCEL_AT %rbx + +#define THIS_rbx %rbx + + call ipc_short_cut_wrapper +in_slow_ipc1: + RESTORE_STATE + pop %rax + iretq + .globl in_slow_ipc1 + +i30_ret_switch: + .globl i30_ret_switch + + +#ifndef CONFIG_PF_UX + +// IPC entry point for sysenter. + + .align 16 + .globl entry_sys_fast_ipc + .globl entry_syscall +entry_sys_fast_ipc: +entry_syscall: + mov %rsp,%r15 /* save user rsp */ + mov syscall_rsp0,%rsp /* get address of kernel stack */ + pop %rsp /* set kernel stack */ + +/* we dont need the segment stuff */ +// push $(GDT_DATA_USER | SEL_PL_U) /* fake user ss */ + sub $8, %rsp + push %r15 /* save user rsp */ + push %r11 /* save user rflags */ + +// push $(GDT_CODE_USER | SEL_PL_U) /* fake user cs */ + sub $8, %rsp + push %rcx /* save user rip */ + + SAVE_STATE_SYSEXIT + ESP_TO_TCB_AT %rbx +#define THIS_rbx %rbx + RESET_THREAD_CANCEL_AT %rbx + + + // test if long send or no send at all + test $~0, %rax + jnz se_shortcut_failed + + // test if destination is L4_INVALID_ID + + // because the default op-size is 32 bit + // i will use the 32bit regs if possible + // to save the 64bit op-prefix + // operations on the 32bit registers + // will zero out the upper 32bits. + + cmp $~0, %esi + je se_shortcut_failed + + // test if destination is L4_NIL_ID + test %esi, %esi + jz se_shortcut_failed + + // test if destination has ``next_period'' bit set + movabsq $0x0020000000000000, %rcx + test %rcx, %rsi + jnz se_shortcut_failed + +// int3 + +// at this point we need only the lower 32bits of the dest id +// the higher bits will masked out later + +// the ver0 field (the lower 10bits) of the ID spawns 1024 bytes, +// so multiply it by 4 + shl $2, %esi + and $TCB_ADDRESS_MASK, %rsi + +// this works, because the kernel lies in the top of the +// virt. address space, where all higher bits are 1 + or $VAL__MEM_LAYOUT__TCBS, %rsi // dst = dst_id.lookup +#define DEST_rsi %rsi + +// int3 + +#define RECV_DESC_rbp %rbp +#define RECV_DESC_rbp_low %ebp + + // test if have receive operation + cmp $~0, RECV_DESC_rbp +/* je se_test_tcb_mapped // no */ + // first version will handle only send+rcv + je se_shortcut_failed + + // test if short receive + cmp $1, RECV_DESC_rbp + ja se_shortcut_failed // more than 2 dwords + + // rdi contains the timeout + // test if simple timeout + testl $0x0f, %edi // rcv_to==inf => exp = 0 + jz 1f // rcv_to==inf => o.k. + testl $0xff000000, %edi + jnz se_shortcut_failed // (rcv_to!=inf) && (rcv_to!=0) + +1: // test if open wait and (irq attached or sender queued) + // ebp is 0 (receive) or 1 (open wait) here + test RECV_DESC_rbp_low, RECV_DESC_rbp_low + jz se_test_tcb_mapped // closed wait + + mov OFS__THREAD__SENDER_FIRST (THIS_rbx), %rax + test %rax, %rax + jnz se_shortcut_failed + or OFS__THREAD__IRQ (THIS_rbx), %rax + jnz se_shortcut_failed + jmp se_test_tcb_mapped + +// int3 + .align 8 +se_shortcut_failed: + // shortcut failed, execute normal ipc C++ pass + CNT_SHORTCUT_FAILED + call sys_ipc_wrapper +in_slow_ipc2: + DO_SYSEXIT + + + .align 16 +se_test_tcb_mapped: + + lea OFS__THREAD__STATE (DEST_rsi), %rcx // addr of dst tcb state + + // Here we could raise a pagefault. The pagefault handler notices + // that by looking at the pagefault address. In that case the pager + // sets the carry flag and returns immediatly. + andl $~0, %ss:(%rcx) // can raise pagefault + jc se_shortcut_failed_1 // tcb is not paged + + testl $(Thread_delayed_deadline | Thread_delayed_ipc), (%rcx) + jnz se_shortcut_failed_1 + + // we assume the thread state will fit in the first 32bit + mov (%rcx), %eax + + and $(Thread_receiving | Thread_send_in_progress | \ + Thread_ipc_in_progress), %eax + + mov OFS__THREAD__PARTNER (DEST_rsi), %rdx + + // dst->thread_lock()->test() + cmp $0, \ + OFS__THREAD__THREAD_LOCK__SWITCH_LOCK__LOCK_OWNER (DEST_rsi) + jne se_shortcut_failed_1 // dst is locked + + lea CAST__Thread_TO_Sender (THIS_rbx), %rcx // (Sender*)this + + // (ipc_state == (Thread_receiving | Thread_ipc_in_progress) + cmpb $(Thread_ipc_in_progress | Thread_receiving), %al + jne se_shortcut_failed_1 + + // see Receiver::sender_ok + mov OFS__THREAD__SENDER_FIRST (DEST_rsi), %rax + + // if DEST_esi->partner() == 0, openwait + test %rdx, %rdx + jne 1f + + // sender_queue empty? + test %rax, %rax + jnz 1f + jmp se_sender_ok + +1: // if DEST_esi->partner() == this, wait for me + cmp %rcx, %rdx + jne se_shortcut_failed_1 + + jmp se_sender_ok +se_shortcut_failed_1: + jmp se_shortcut_failed + + .align 16 + +se_sender_ok: + CNT_SHORTCUT_SUCCESS + + // clear, we need it later + xor %eax, %eax + + // wake up receiver + andl $~(Thread_ipc_receiving_mask | \ + Thread_ipc_in_progress), OFS__THREAD__STATE (DEST_rsi) + orb $Thread_ready, OFS__THREAD__STATE (DEST_rsi) + + // %eax=0 => default: no receive part => status ok + + // prepare a receive if we have one + cmp $~0, RECV_DESC_rbp + je se_do_switch_exec // no receive part + // we should jump, because we have ruled out receiving before + +// int3 + +#define REGS_rsp %rsp + // set_rcv_regs (regs) + mov REGS_rsp, OFS__THREAD__RCV_REGS (THIS_rbx) + + orb $(Thread_receiving | Thread_ipc_in_progress),\ + OFS__THREAD__STATE (THIS_rbx) + + // default: open wait + xor %ecx, %ecx + + test RECV_DESC_rbp_low, RECV_DESC_rbp_low // open wait? + jnz 1f // openwait cmp yes + + // set dst's partner + lea CAST__Thread_TO_Sender (DEST_rsi), %rcx // (Sender*)dst + +1: mov %rcx, OFS__THREAD__PARTNER (THIS_rbx) + + // timeout = 0 + movb $L4_IPC_RETIMEOUT, %al + testl $0x0f, %edi // rcv_to==inf => exp = 0 + jne se_do_switch_exec // timeout==inf? no + + // timeout = infinite ==> need wakeup + movb $L4_IPC_RECANCELED, %al + andb $~Thread_ready, OFS__THREAD__STATE (THIS_rbx) + + .align 16 +se_do_switch_exec: + + mov %rax, REG_RAX (REGS_rsp) // store ipc result + + CNT_CONTEXT_SWITCH + + mov OFS__THREAD__STATE (THIS_rbx), %eax + test $Thread_fpu_owner, %eax + jz 1f + // set ts + mov %cr0, %rdx + or $CR0_TS, %rdx + mov %rdx, %cr0 + jmp 2f + +1: testl $Thread_fpu_owner, OFS__THREAD__STATE (DEST_rsi) + jz 2f + // clear ts + clts + +2: // %eax=thread_state (THIS_ebx) + xor %edx, %edx + + // if (state() & Thread_ready && ! in_ready_list()) + // ready_enqueue() + cmp %rdx, OFS__THREAD__READY_NEXT (THIS_rbx) + jne se_no_enqueue + testb $Thread_ready, %al + jnz se_enqueue_this + + .align 8 +se_no_enqueue: + // not for performance kernels! + CONSUME_TIME // scratches eax, ecx, edx, ebp + + // push restart address onto old stack + +// mov $se_ret_switch, %rax + lea se_ret_switch(%rip), %rax + pushq %rax + + mov REGS_rsp, OFS__THREAD__KERNEL_SP (THIS_rbx) +#undef REGS_rsp +#define DEST_KERNEL_SP_rbp %rbp + mov OFS__THREAD__KERNEL_SP (DEST_rsi), DEST_KERNEL_SP_rbp + + // switch esp0 on TSS + mov CPUS_BASE + OFS__CPU__TSS, %rax + leaq THREAD_BLOCK_SIZE (DEST_rsi), %rcx + + mov %rcx, 4 (%rax) // x86_tss.esp0 + + // we dont clear the IPC window of the destination thread + // reason: ipc already finished and the destination thread + // will setup an new one before entering long IPC again + +// int3 + // pdir = space_context - kmem::mem_phys (needed later) + movq OFS__THREAD__SPACE (DEST_rsi), %rax + leaq OFS__SPACE__MEM_SPACE (%rax), %rax + sub PHYSMEM_OFFS, %rax + + mov PAGE_DIR_ADDR, %rcx // get_pdir() + cmp %rax, %rcx // get_pdir == pdir + jne se_flush_pdir // no => flush + +se_addr_space_switched: + + lea se_ret_switch(%rip), %rax + cmp %rax, (DEST_KERNEL_SP_rbp) + jne se_slow_switch + + RESET_THREAD_IPC_MASK_AT DEST_rsi + + // Setup return registers. We have to add 8 to each %rsp,%rbp reference + // since there is the return address pushed on the stack. + + mov OFS__THREAD__EIP (DEST_rsi), %rcx + /* make RIP canonical, workaround for intel IA32e flaw */ + shl $16, %rcx + sar $16, %rcx + mov OFS__THREAD__ESP (DEST_rsi), %r15 + mov OFS__THREAD__EFL (DEST_rsi), %r11 + mov OFS__THREAD__ID (THIS_rbx), %rsi + + mov 8+REG_RDX (%rsp), %rdx + mov 8+REG_RBX (%rsp), %rbx + mov $RETURN_DOPE, %eax + + mov 8+REG_R14 (%rbp), %r14 + mov 8+REG_R13 (%rbp), %r13 + mov 8+REG_R12 (%rbp), %r12 + mov 8+REG_R10 (%rbp), %r10 + mov 8+REG_R9 (%rbp), %r9 + mov 8+REG_R8 (%rbp), %r8 + + mov %r15, %rsp + sysretq + +se_flush_pdir: + CNT_ADDR_SPACE_SWITCH + mov %rax, PAGE_DIR_ADDR // set pdir, flush TLBs + jmp se_addr_space_switched + +se_enqueue_this: + // ecx = sched(), eax = sched()->prio() + mov OFS__THREAD__SCHED (THIS_rbx), %rcx + + xor %eax, %eax + movl OFS__SCHED_CONTEXT__PRIO (%rcx), %eax + READY_ENQUEUE THIS_rbx, se_no_enqueue // scratches ecx, edx + jmp se_no_enqueue + + .align 16 +se_ret_switch: + // shortcut success + ESP_TO_TCB_AT %rbx + RESET_THREAD_IPC_MASK_AT %rbx + DO_SYSEXIT + + + // The destination thread is not in a shortcut IPC so we cannot + // throw it directly into user space since it may held a thread + // lock or does not return via sysexit (int-entered IPC or + // ex_regs manipulation) + .align 16 +se_slow_switch: + mov OFS__THREAD__RCV_REGS (DEST_rsi), %rax + mov 8+REG_RDX (%rsp), %rdx + mov 8+REG_RBX (%rsp), %rcx + mov %rdx, REG_RDX (%rax) // dst_regs->edx = dw1 + mov %rcx, REG_RBX (%rax) // dst_regs->ebx = dw2 + mov OFS__THREAD__ID (THIS_rbx), %rdx + movq $RETURN_DOPE, REG_RAX (%rax) + mov %rdx, REG_RSI (%rax) // dst_regs->esi = id.low + mov %rbp, %rsp // load new stack pointer + pop %rax + jmp *%rax + + .globl in_slow_ipc2 + .globl se_ret_switch + +#endif // CONFIG_PF_UX + + .globl in_slow_ipc1 + .globl i30_ret_switch + +#endif // CONFIG_ASSEMBLER_IPC_SHORTCUT + + // fast return from Dirq::hit + .align 16 + .globl fast_ret_from_irq +fast_ret_from_irq: + RESTORE_STATE + popq %rax + andq $0x7f, 8(%rsp) // if entered using syscall + orq $EFLAGS_IF, 16(%rsp) // if entered using syscall + iretq + diff --git a/kernel/fiasco/src/kern/ia32/64/tb_entry-ia32-64.cpp b/kernel/fiasco/src/kern/ia32/64/tb_entry-ia32-64.cpp new file mode 100644 index 00000000..a426111c --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/64/tb_entry-ia32-64.cpp @@ -0,0 +1,183 @@ +INTERFACE [amd64]: + +EXTENSION class Tb_entry_base +{ +public: + enum + { + Tb_entry_size = 128, + }; +}; + +/** logged kernel event plus register content. */ +class Tb_entry_ke_reg : public Tb_entry +{ +private: + struct Payload + { + union { + char _msg[19]; ///< debug message + struct { + char _pad[3]; + const char *_m; + } _const_msg __attribute__((packed)); + }; + Mword _rax, _rcx, _rdx; ///< registers + } __attribute__((packed)); +}; + +/** logged trap. */ +class Tb_entry_trap : public Tb_entry +{ +private: + struct Payload + { + char _trapno; + Unsigned16 _error; + Mword _rbp, _cr2, _rax, _rflags, _rsp; + Unsigned16 _cs, _ds; + } __attribute__((packed)); +}; + +IMPLEMENTATION [amd64]: + +#include "cpu.h" + +PUBLIC inline NEEDS ["cpu.h"] +void +Tb_entry::rdtsc() +{ _tsc = Cpu::rdtsc(); } + + + +PUBLIC inline +void +Tb_entry_ke_reg::set(Context const *ctx, Mword rip, Mword v1, Mword v2, Mword v3) +{ + set_global(Tbuf_ke_reg, ctx, rip); + payload()->_rax = v1; payload()->_rcx = v2; payload()->_rdx = v3; +} + +PUBLIC inline NEEDS [] +void +Tb_entry_ke_reg::set(Context const *ctx, Mword rip, Trap_state *ts) +{ set(ctx, rip, ts->_ax, ts->_cx, ts->_dx); } + +PUBLIC inline +void +Tb_entry_ke_reg::set_const(Context const *ctx, Mword rip, + const char * const msg, + Mword rax, Mword rcx, Mword rdx) +{ + set(ctx, rip, rax, rcx, rdx); + payload()->_msg[0] = 0; + payload()->_msg[1] = 1; + payload()->_const_msg._m = msg; +} + +PUBLIC inline +void +Tb_entry_ke_reg::set_buf(unsigned i, char c) +{ + if (i < sizeof(payload()->_msg) - 1) + payload()->_msg[i] = c >= ' ' ? c : '.'; +} + +PUBLIC inline +void +Tb_entry_ke_reg::term_buf(unsigned i) +{ payload()->_msg[i < sizeof(payload()->_msg)-1 ? i : sizeof(payload()->_msg)-1] = '\0'; } + +PUBLIC inline +const char * +Tb_entry_ke_reg::msg() const +{ + return payload()->_msg[0] == 0 && + payload()->_msg[1] == 1 ? payload()->_const_msg._m + : payload()->_msg; +} + +PUBLIC inline +Mword +Tb_entry_ke_reg::val1() const +{ return payload()->_rax; } + +PUBLIC inline +Mword +Tb_entry_ke_reg::val2() const +{ return payload()->_rcx; } + +PUBLIC inline +Mword +Tb_entry_ke_reg::val3() const +{ return payload()->_rdx; } + + +PUBLIC inline NEEDS ["trap_state.h"] +void +Tb_entry_trap::set(Context const *ctx, Mword rip, Trap_state *ts) +{ + set_global(Tbuf_trap, ctx, rip); + payload()->_trapno = ts->_trapno; + payload()->_error = ts->_err; + payload()->_cr2 = ts->_cr2; + payload()->_rax = ts->_ax; + payload()->_cs = (Unsigned16)ts->cs(); + payload()->_rsp = ts->sp(); + payload()->_rflags = ts->flags(); +} + +PUBLIC inline +void +Tb_entry_trap::set(Context const *ctx, Mword eip, Mword trapno) +{ + set_global(Tbuf_trap, ctx, eip); + payload()->_trapno = trapno | 0x80; +} + +PUBLIC inline +char +Tb_entry_trap::trapno() const +{ return payload()->_trapno; } + +PUBLIC inline +Unsigned16 +Tb_entry_trap::error() const +{ return payload()->_error; } + +PUBLIC inline +Mword +Tb_entry_trap::eax() const +{ return payload()->_rax; } + +PUBLIC inline +Mword +Tb_entry_trap::cr2() const +{ return payload()->_cr2; } + +PUBLIC inline +Mword +Tb_entry_trap::ebp() const +{ return payload()->_rbp; } + +PUBLIC inline +Unsigned16 +Tb_entry_trap::cs() const +{ return payload()->_cs; } + +PUBLIC inline +Unsigned16 +Tb_entry_trap::ds() const +{ return payload()->_ds; } + +PUBLIC inline +Mword +Tb_entry_trap::sp() const +{ return payload()->_rsp; } + +PUBLIC inline +Mword +Tb_entry_trap::flags() const +{ return payload()->_rflags; } + + diff --git a/kernel/fiasco/src/kern/ia32/64/thread-dbf.cpp b/kernel/fiasco/src/kern/ia32/64/thread-dbf.cpp new file mode 100644 index 00000000..6187b766 --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/64/thread-dbf.cpp @@ -0,0 +1,78 @@ +INTERFACE[amd64]: + +EXTENSION class Thread +{ +private: + static void handle_double_fault (Trap_state *) asm ("thread_handle_double_fault"); + +public: + static bool may_enter_jdb; +}; + + +IMPLEMENTATION[amd64]: + +#include +#include "cpu.h" +#include "kernel_console.h" +#include "processor.h" +#include "reset.h" +#include "trap_state.h" +#include "tss.h" +#include "watchdog.h" + + +bool Thread::may_enter_jdb = false; + +IMPLEMENT +void +Thread::handle_double_fault (Trap_state *ts) +{ + int c; + + Watchdog::disable(); + printf ("\n\033[1;31mDOUBLE FAULT!\033[m\n" + "RAX=%016lx RSI=%016lx\n" + "RBX=%016lx RDI=%016lx\n" + "RCX=%016lx RBP=%016lx\n" + "RDX=%016lx RSP=%016lx\n" + "R8= %016lx R9= %016lx\n" + "R10=%016lx R11=%016lx\n" + "R12=%016lx R13=%016lx\n" + "R14=%016lx R15=%016lx\n" + "RIP %016lx RFLAGS %016lx\n" + "CS %04lx SS %04lx\n\n", + ts->_ax, ts->_si, + ts->_bx, ts->_di, + ts->_cx, ts->_bp, + ts->_dx, ts->sp(), + ts->_r8, ts->_r9, + ts->_r10, ts->_r11, + ts->_r12, ts->_r13, + ts->_r14, ts->_r15, + ts->ip(), ts->flags(), + ts->cs() & 0xffff, ts->ss() & 0xffff); + if (may_enter_jdb) + { + puts ("Return reboots, \"k\" tries to enter the L4 kernel debugger..."); + + while ((c=Kconsole::console()->getchar(false)) == -1) + Proc::pause(); + + if (c == 'k' || c == 'K') + { + nested_trap_handler(ts,0); // XXX: 0 is possibly the wrong CPU + } + } + else + { + puts ("Return reboots"); + while ((Kconsole::console()->getchar(false)) == -1) + Proc::pause(); + } + + puts ("\033[1mRebooting...\033[0m"); + platform_reset(); +} + + diff --git a/kernel/fiasco/src/kern/ia32/64/thread-ia32-64.cpp b/kernel/fiasco/src/kern/ia32/64/thread-ia32-64.cpp new file mode 100644 index 00000000..73aa5eef --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/64/thread-ia32-64.cpp @@ -0,0 +1,263 @@ +//---------------------------------------------------------------------------- +IMPLEMENTATION [amd64]: + + +PUBLIC template inline +void FIASCO_NORETURN +Thread::fast_return_to_user(Mword ip, Mword sp, T arg) +{ + assert_kdb(cpu_lock.test()); + assert_kdb(current() == this); + assert_kdb(regs()->cs() & 3 == 3); + + regs()->ip(ip); + regs()->sp(sp); + regs()->flags(EFLAGS_IF); + asm volatile + ("mov %0, %%rsp \t\n" + "iretq \t\n" + : + : "r" (static_cast(regs())), "d"(arg) + ); + __builtin_trap(); +} + +PROTECTED inline +L4_msg_tag +Thread::invoke_arch(L4_msg_tag tag, Utcb *utcb) +{ + switch (utcb->values[0] & Opcode_mask) + { + case Op_set_fs_amd64: + if (tag.words() < 2) + return commit_result(-L4_err::EInval); + _fs_base = utcb->values[1]; + if (current() == this) + load_segments(); + return Kobject_iface::commit_result(0); + default: + return commit_result(-L4_err::ENosys); + }; +} + +IMPLEMENT inline +Mword +Thread::user_sp() const +{ return exception_triggered()?_exc_cont.sp(regs()):regs()->sp(); } + +IMPLEMENT inline +void +Thread::user_sp(Mword sp) +{ + if (exception_triggered()) + _exc_cont.sp(regs(), sp); + else + regs()->sp(sp); +} + +PROTECTED inline +int +Thread::do_trigger_exception(Entry_frame *r, void *ret_handler) +{ + if (!exception_triggered()) + { + _exc_cont.activate(r, ret_handler); + return 1; + } + // else ignore change of IP because triggered exception already pending + return 0; +} + +PUBLIC inline +void +Thread::restore_exc_state() +{ + _exc_cont.restore(regs()); +} + +PRIVATE static inline +Return_frame * +Thread::trap_state_to_rf(Trap_state *ts) +{ + char *im = reinterpret_cast(ts + 1); + return reinterpret_cast(im)-1; +} + +PRIVATE static inline NEEDS[Thread::trap_state_to_rf] +bool FIASCO_WARN_RESULT +Thread::copy_utcb_to_ts(L4_msg_tag const &tag, Thread *snd, Thread *rcv, + unsigned char rights) +{ + Trap_state *ts = (Trap_state*)rcv->_utcb_handler; + Mword s = tag.words(); + Unsigned32 cs = ts->cs(); + Utcb *snd_utcb = snd->utcb().access(); + + if (EXPECT_FALSE(rcv->exception_triggered())) + { + // triggered exception pending + Mem::memcpy_mwords (ts, snd_utcb->values, s > 19 ? 19 : s); + if (EXPECT_TRUE(s > 22)) + { + Continuation::User_return_frame const *s + = reinterpret_cast((char*)&snd_utcb->values[19]); + + rcv->_exc_cont.set(trap_state_to_rf(ts), s); + } + } + else + Mem::memcpy_mwords (ts, snd_utcb->values, s > 23 ? 23 : s); + + if (tag.transfer_fpu() && (rights & L4_fpage::W)) + snd->transfer_fpu(rcv); + + // sanitize eflags + ts->flags((ts->flags() & ~(EFLAGS_IOPL | EFLAGS_NT)) | EFLAGS_IF); + + // don't allow to overwrite the code selector! + ts->cs(cs); + + bool ret = transfer_msg_items(tag, snd, snd_utcb, + rcv, rcv->utcb().access(), rights); + + rcv->state_del(Thread_in_exception); + return ret; +} + +PRIVATE static inline NEEDS[Thread::trap_state_to_rf] +bool FIASCO_WARN_RESULT +Thread::copy_ts_to_utcb(L4_msg_tag const &, Thread *snd, Thread *rcv, + unsigned char rights) +{ + Trap_state *ts = (Trap_state*)snd->_utcb_handler; + Utcb *rcv_utcb = rcv->utcb().access(); + { + Lock_guard guard (&cpu_lock); + if (EXPECT_FALSE(snd->exception_triggered())) + { + Mem::memcpy_mwords (rcv_utcb->values, ts, 19); + Continuation::User_return_frame *d + = reinterpret_cast((char*)&rcv_utcb->values[19]); + + snd->_exc_cont.get(d, trap_state_to_rf(ts)); + } + else + Mem::memcpy_mwords (rcv_utcb->values, ts, 23); + + if (rcv_utcb->inherit_fpu() && (rights & L4_fpage::W)) + snd->transfer_fpu(rcv); +} + return true; +} + + +IMPLEMENT +void +Thread::user_invoke() +{ + user_invoke_generic(); + + asm volatile + (" mov %%rax,%%rsp \n" // set stack pointer to regs structure + " mov %%ecx,%%es \n" + " mov %%ecx,%%ds \n" + " xor %%rax,%%rax \n" + " xor %%rcx,%%rcx \n" // clean out user regs + " xor %%rdx,%%rdx \n" + " xor %%rsi,%%rsi \n" + " xor %%rdi,%%rdi \n" + " xor %%rbx,%%rbx \n" + " xor %%rbp,%%rbp \n" + " xor %%r8,%%r8 \n" + " xor %%r9,%%r9 \n" + " xor %%r10,%%r10 \n" + " xor %%r11,%%r11 \n" + " xor %%r12,%%r12 \n" + " xor %%r13,%%r13 \n" + " xor %%r14,%%r14 \n" + " xor %%r15,%%r15 \n" + + " iretq \n" + : // no output + : "a" (nonull_static_cast(current()->regs())), + "c" (Gdt::gdt_data_user | Gdt::Selector_user) + ); + + // never returns here +} + +PRIVATE inline +int +Thread::check_trap13_kernel (Trap_state * /*ts*/) +{ return 1; } + + +//---------------------------------------------------------------------------- +IMPLEMENTATION [amd64 & (debug | kdb)]: + +#include "kernel_task.h" + +/** Call the nested trap handler (either Jdb::enter_kdebugger() or the + * gdb stub. Setup our own stack frame */ +PRIVATE static +int +Thread::call_nested_trap_handler(Trap_state *ts) +{ + Proc::cli(); + + unsigned long phys_cpu = Cpu::phys_id_direct(); + unsigned log_cpu = Cpu::p2l(phys_cpu); + if (log_cpu == ~0U) + { + printf("Trap on unknown CPU phys_id=%lx\n", phys_cpu); + log_cpu = 0; + } + + unsigned long &ntr = nested_trap_recover.cpu(log_cpu); + +#if 0 + printf("%s: lcpu%u sp=%p t=%u nested_trap_recover=%ld\n", + __func__, log_cpu, (void*)Proc::stack_pointer(), ts->_trapno, + ntr); +#endif + + Unsigned64 ret; + void *stack = 0; + if (!ntr) + stack = dbg_stack.cpu(log_cpu).stack_top; + + Unsigned64 dummy1, dummy2, dummy3; + + // don't set %esp if gdb fault recovery to ensure that exceptions inside + // kdb/jdb don't overwrite the stack + asm volatile + ("mov %%rsp,%[d2] \n\t" // save old stack pointer + "cmpq $0,%[recover] \n\t" + "jne 1f \n\t" // check trap within trap handler + "mov %[stack],%%rsp \n\t" // setup clean stack pointer + "1: \n\t" + "incq %[recover] \n\t" + "mov %%cr3, %[d1] \n\t" + "push %[d2] \n\t" // save old stack pointer on new stack + "push %[d1] \n\t" // save old pdbr + "mov %[pdbr], %%cr3 \n\t" + "callq *%[handler] \n\t" + "pop %[d1] \n\t" + "mov %[d1], %%cr3 \n\t" + "pop %%rsp \n\t" // restore old stack pointer + "cmpq $0,%[recover] \n\t" // check trap within trap handler + "je 1f \n\t" + "decq %[recover] \n\t" + "1: \n\t" + : [ret] "=a"(ret), [d2] "=&r"(dummy2), [d1] "=&r"(dummy1), "=D"(dummy3), + [recover] "+m" (ntr) + : [ts] "D" (ts), + [pdbr] "r" (Kernel_task::kernel_task()->virt_to_phys((Address)Kmem::dir())), + [cpu] "S" (log_cpu), + [stack] "r" (stack), + [handler] "m" (nested_trap_handler) + : "rdx", "rcx", "r8", "r9", "memory"); + + return ret == 0 ? 0 : -1; +} + diff --git a/kernel/fiasco/src/kern/ia32/64/trap_state-amd64.cpp b/kernel/fiasco/src/kern/ia32/64/trap_state-amd64.cpp new file mode 100644 index 00000000..2bba048f --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/64/trap_state-amd64.cpp @@ -0,0 +1,237 @@ + +INTERFACE: + +#include "l4_types.h" + +class Trap_state +{ + friend class Jdb_tcb; + friend class Jdb_stack_view; +public: + typedef FIASCO_FASTCALL int (*Handler)(Trap_state*, unsigned cpu); + static Handler base_handler asm ("BASE_TRAP_HANDLER"); + + // No saved segment registers + + // register state frame + Mword _r15; + Mword _r14; + Mword _r13; + Mword _r12; + Mword _r11; + Mword _r10; + Mword _r9; + Mword _r8; + Mword _di; + Mword _si; + Mword _bp; + Mword _cr2; // we save cr2 over esp for page faults + Mword _bx; + Mword _dx; + Mword _cx; + Mword _ax; + + // Processor trap number, 0-31 + Mword _trapno; + + // Error code pushed by the processor, 0 if none + Mword _err; + +protected: + // Processor state frame + Mword _ip; + Mword _cs; + Mword _flags; + Mword _sp; + Mword _ss; +}; + +IMPLEMENTATION: + +#include +#include +#include "cpu.h" +#include "atomic.h" +#include "gdt.h" +#include "regdefs.h" + +Trap_state::Handler Trap_state::base_handler FIASCO_FASTCALL; + +PUBLIC inline NEEDS["regdefs.h", "gdt.h"] +void +Trap_state::sanitize_user_state() +{ + _cs = Gdt::gdt_code_user | Gdt::Selector_user; + _ss = Gdt::gdt_data_user | Gdt::Selector_user; + _flags = (_flags & ~(EFLAGS_IOPL | EFLAGS_NT)) | EFLAGS_IF; +} + +PUBLIC inline +void +Trap_state::set_ipc_upcall() +{ + _err = 0; + _trapno = 0xfe; +} + +PUBLIC inline +void +Trap_state::set_pagefault(Mword pfa, Mword error) +{ + _cr2 = pfa; + _trapno = 0xe; + _err = error; +} + +PUBLIC inline +Mword +Trap_state::trapno() const +{ return _trapno; } + +PUBLIC inline +Mword +Trap_state::error() const +{ return 0; } + +PUBLIC inline +Mword +Trap_state::ip() const +{ return _ip; } + +PUBLIC inline +Mword +Trap_state::cs() const +{ return _cs; } + +PUBLIC inline +Mword +Trap_state::flags() const +{ return _flags; } + +PUBLIC inline +Mword +Trap_state::sp() const +{ return _sp; } + +PUBLIC inline +Mword +Trap_state::ss() const +{ return _ss; } + +PUBLIC inline +Mword +Trap_state::value() const +{ return _ax; } + +PUBLIC inline +Mword +Trap_state::value2() const +{ return _cx; } + +PUBLIC inline +Mword +Trap_state::value3() const +{ return _dx; } + +PUBLIC inline +Mword +Trap_state::dx() const +{ return _dx; } + +PUBLIC inline +Mword +Trap_state::value4() const +{ return _bx; } + +PUBLIC inline +void +Trap_state::ip(Mword ip) +{ _ip = ip; } + +PUBLIC inline +void +Trap_state::cs(Mword cs) +{ _cs = cs; } + +PUBLIC inline +void +Trap_state::flags(Mword flags) +{ _flags = flags; } + +PUBLIC inline +void +Trap_state::sp(Mword sp) +{ _sp = sp; } + +PUBLIC inline +void +Trap_state::ss(Mword ss) +{ _ss = ss; } + +PUBLIC inline +void +Trap_state::value(Mword value) +{ _ax = value; } + +PUBLIC inline +void +Trap_state::value3(Mword value) +{ _dx = value; } + +PUBLIC inline NEEDS["atomic.h"] +void +Trap_state::consume_instruction(unsigned count) +{ cas ((Address*)(&_ip), _ip, _ip + count); } + +PUBLIC inline +bool +Trap_state::is_debug_exception() const +{ return _trapno == 1 || _trapno == 3; } + +PUBLIC +void +Trap_state::dump() +{ + int from_user = _cs & 3; + + printf("RAX %016lx RBX %016lx\n", _ax, _bx); + printf("RCX %016lx RDX %016lx\n", _cx, _dx); + printf("RSI %016lx RDI %016lx\n", _si, _di); + printf("RBP %016lx RSP %016lx\n", _bp, from_user ? _sp : (Address)&_sp); + printf("R8 %016lx R9 %016lx\n", _r8, _r9); + printf("R10 %016lx R11 %016lx\n", _r10, _r11); + printf("R12 %016lx R12 %016lx\n", _r12, _r13); + printf("R14 %016lx R15 %016lx\n", _r14, _r15); + printf("RIP %016lx RFLAGS %016lx\n", _ip, _flags); + printf("CS %04lx SS %04lx\n", _cs, _ss); + printf("\n"); + printf("trapno %d, error %lx, from %s mode\n", + (unsigned)_trapno, _err, from_user ? "user" : "kernel"); + + if (_trapno == 13) + { + if (_err & 1) + printf("(external event"); + else + printf("(internal event"); + if (_err & 2) + { + printf(" regarding IDT gate descriptor no. 0x%02lx)\n", _err >> 3); + } + else + { + printf(" regarding %s entry no. 0x%02lx)\n", + _err & 4 ? "LDT" : "GDT", _err >> 3); + } + } + else if (_trapno == 14) + printf("page fault linear address %16lx\n", _cr2); +} + +extern "C" FIASCO_FASTCALL +void +trap_dump_panic(Trap_state *ts) +{ + ts->dump(); + panic("terminated due to trap"); +} diff --git a/kernel/fiasco/src/kern/ia32/64/tss-amd64.cpp b/kernel/fiasco/src/kern/ia32/64/tss-amd64.cpp new file mode 100644 index 00000000..2cd26fb0 --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/64/tss-amd64.cpp @@ -0,0 +1,35 @@ + +INTERFACE[amd64]: + +#include "l4_types.h" + +class Tss +{ +public: + Unsigned32 _ign0; // ignored + Address _rsp0; + Address _rsp1; + Address _rsp2; + Unsigned32 _ign1; // ignored + Unsigned32 _ign2; // ignored + Address _ist1; + Address _ist2; + Address _ist3; + Address _ist4; + Address _ist5; + Address _ist6; + Address _ist7; + Unsigned32 _ign3; // ignored + Unsigned32 _ign4; // ignored + Unsigned16 _ign5; // ignored + Unsigned16 _io_bit_map_offset; +} __attribute__((packed)); + +IMPLEMENTATION: + +PUBLIC inline +void +Tss::set_ss0(unsigned) +{} + +//- diff --git a/kernel/fiasco/src/kern/ia32/64/vm_svm_asm.S b/kernel/fiasco/src/kern/ia32/64/vm_svm_asm.S new file mode 100644 index 00000000..30025838 --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/64/vm_svm_asm.S @@ -0,0 +1,79 @@ + .p2align(4) + .globl resume_vm_svm +resume_vm_svm: + + // save callee saved regs + push %rbx + push %r12 + push %r13 + push %r14 + push %r15 + push %rbp + + mov %rdi, %rax // first arg goes to rax for vm* + push %rsi // store pointer to register struct + + clgi + + sti + nop + + // restore guest GP regs + mov 0(%rsi), %r15 + mov 8(%rsi), %r14 + mov 16(%rsi), %r13 + mov 24(%rsi), %r12 + mov 32(%rsi), %r11 + mov 40(%rsi), %r10 + mov 48(%rsi), %r9 + mov 56(%rsi), %r8 + mov 64(%rsi), %rdi + // skip rsi for now + mov 80(%rsi), %rbp + mov 96(%rsi), %rbx + mov 104(%rsi), %rdx + mov 112(%rsi), %rcx + mov 72(%rsi), %rsi + + // TODO: Debugregs + + // rax used as implicit operand for vm* instructions + vmload + vmrun + vmsave + + push %rsi + mov 8(%rsp), %rsi // get previously saved register struct pointer + + mov %r15, 0(%rsi) + mov %r14, 8(%rsi) + mov %r13, 16(%rsi) + mov %r12, 24(%rsi) + mov %r11, 32(%rsi) + mov %r10, 40(%rsi) + mov %r9, 48(%rsi) + mov %r8, 56(%rsi) + mov %rdi, 64(%rsi) + // skip rsi for now + mov %rbp, 80(%rsi) + mov %rbx, 96(%rsi) + mov %rdx,104(%rsi) + mov %rcx,112(%rsi) + mov (%rsp), %rcx + mov %rcx, 72(%rsi) + + cli + nop + stgi + + add $16, %rsp + + // restore callee saved registers + pop %rbp + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %rbx + + ret diff --git a/kernel/fiasco/src/kern/ia32/64/vm_vmx_asm.S b/kernel/fiasco/src/kern/ia32/64/vm_vmx_asm.S new file mode 100644 index 00000000..04225ed7 --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/64/vm_vmx_asm.S @@ -0,0 +1,93 @@ +/** + * Function resume_vm_vmx, arguments: + * - rdi: Pointer to registers (layout specific...) + */ + .p2align(4) + .globl resume_vm_vmx + .globl vm_vmx_exit_vec +resume_vm_vmx: + // save callee saved regs + push %rbx + push %r12 + push %r13 + push %r14 + push %r15 + push %rbp + push %gs + push %fs + + push %rdi // store pointer to register struct + mov $0x6c14, %eax // save rsp in vmcs + vmwrite %rsp, %rax + mov (%rsp), %rsp + + // load guest GP registers + mov 0(%rsp), %r15 + mov 8(%rsp), %r14 + mov 16(%rsp), %r13 + mov 24(%rsp), %r12 + mov 32(%rsp), %r11 + mov 40(%rsp), %r10 + mov 48(%rsp), %r9 + mov 56(%rsp), %r8 + mov 64(%rsp), %rdi + mov 72(%rsp), %rsi + mov 80(%rsp), %rbp + mov 96(%rsp), %rbx + mov 104(%rsp), %rdx + mov 112(%rsp), %rcx + mov 120(%rsp), %rax + + vmresume + jnz 1f + vmlaunch +1: // error path + mov $0x6c14, %eax + vmread %rax, %rsp + pushf + pop %rax + add $24, %rsp // pushed regs pointer and gs+fs + pop %rbp + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %rbx + ret + +vm_vmx_exit_vec: + push %rsi + mov 8(%rsp), %rsi // get previously saved register struct pointer + mov %r15, 0(%rsi) + mov %r14, 8(%rsi) + mov %r13, 16(%rsi) + mov %r12, 24(%rsi) + mov %r11, 32(%rsi) + mov %r10, 40(%rsi) + mov %r9, 48(%rsi) + mov %r8, 56(%rsi) + mov %rdi, 64(%rsi) + // skip rsi for now + mov %rbp, 80(%rsi) + mov %rbx, 96(%rsi) + mov %rdx,104(%rsi) + mov %rcx,112(%rsi) + mov %rax,120(%rsi) + pop %rcx + mov %rcx, 72(%rsi) + + add $8, %rsp // adjust stack after regs pointer push on stack + + // restore callee saved registers + pop %fs + pop %gs + pop %rbp + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %rbx + + xor %rax, %rax + ret + diff --git a/kernel/fiasco/src/kern/ia32/Makerules.KERNEL b/kernel/fiasco/src/kern/ia32/Makerules.KERNEL new file mode 100644 index 00000000..ee5229f2 --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/Makerules.KERNEL @@ -0,0 +1,15 @@ +# -*- makefile -*- +# IA32 Kernel Makefile + +entry-native.o: $(TCBOFFSET) +entry.o: $(TCBOFFSET) +entry-mp.o: $(TCBOFFSET) +entry-ux.o: $(TCBOFFSET) +shortcut.o: $(TCBOFFSET) +tramp-mp.o: $(TCBOFFSET) +sys_call_page-asm.o: $(TCBOFFSET) + +# Add future prerequisites somewhere among the list of libraries. +# You really should not have to add anything in the $(LD) line. + +$(KERNEL): diff --git a/kernel/fiasco/src/kern/ia32/Makerules.SYMBOLS.ia32 b/kernel/fiasco/src/kern/ia32/Makerules.SYMBOLS.ia32 new file mode 100644 index 00000000..d736bfea --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/Makerules.SYMBOLS.ia32 @@ -0,0 +1,12 @@ +# -*- makefile -*- + +$(SYMBOLS): $(KERNEL) + $(COMP_MESSAGE) + $(VERBOSE)$(NM) -nC $(KERNEL) | \ + sed -e 's/^00000000//' | grep "^f[0-9a-z]\{7,7\}">$@.new + $(VERBOSE)mv $@.new $@ + $(VERBOSE)chmod 644 $@ + $(call INSTALLFILE_RULE,$@,fiasco_symbols) + +clean-SYMBOLS: + rm -f $(SYMBOLS) diff --git a/kernel/fiasco/src/kern/ia32/__main.cpp b/kernel/fiasco/src/kern/ia32/__main.cpp new file mode 100644 index 00000000..aaac238d --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/__main.cpp @@ -0,0 +1,29 @@ +INTERFACE[ia32,amd64]: +#include "types.h" +#include "initcalls.h" + +IMPLEMENTATION[ia32,amd64]: +#include "boot_info.h" +#include "initcalls.h" + +#include +#include +#include + +void kernel_main(void); + +extern "C" FIASCO_FASTCALL FIASCO_INIT +void +__main(Address /*mbi_phys*/, unsigned aflag, unsigned checksum_ro) +{ + /* set global to be used in the constructors */ + Boot_info::set_flags(aflag); + Boot_info::set_checksum_ro(checksum_ro); + Boot_info::init(); + + atexit(&static_destruction); + static_construction(); + + kernel_main(); + exit(0); +} diff --git a/kernel/fiasco/src/kern/ia32/apic-debug.cpp b/kernel/fiasco/src/kern/ia32/apic-debug.cpp new file mode 100644 index 00000000..7d6850f7 --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/apic-debug.cpp @@ -0,0 +1,134 @@ +IMPLEMENTATION[debug]: + +#include +#include "simpleio.h" + +static +const char* +Apic::reg_lvt_bit_str(unsigned reg, Unsigned32 val, int bit) +{ + static const char * const delivery_mode[] = + { "fixed", "???", "SMI", "???", "NMI", "INIT", "???", "ExtINT" }; + unsigned bits = 0; + + switch (reg) + { + case APIC_lvtt: bits = Mask | Delivery_state; break; + case APIC_lvt0: + case APIC_lvt1: bits = Mask | Trigger_mode | Remote_irr | Pin_polarity + | Delivery_state | Delivery_mode; break; + case APIC_lvterr: bits = Mask | Delivery_state; break; + case APIC_lvtpc: bits = Mask | Delivery_state | Trigger_mode; break; + case APIC_lvtthmr: bits = Mask | Delivery_state | Trigger_mode; break; + } + + if (bits & bit == 0) + return ""; + + switch (bit) + { + case Mask: + return val & APIC_lvt_masked ? "masked" : "unmasked"; + case Trigger_mode: + return val & APIC_lvt_level_trigger ? "level" : "edge"; + case Remote_irr: + return val & APIC_lvt_remote_irr ? "IRR" : ""; + case Pin_polarity: + return val & APIC_input_polarity ? "active low" : "active high"; + case Delivery_state: + return val & APIC_snd_pending ? "pending" : "idle"; + case Delivery_mode: + return delivery_mode[reg_delivery_mode(val)]; + } + + return ""; +} + +PUBLIC static +void +Apic::reg_show(unsigned reg) +{ + Unsigned32 tmp_val = reg_read(reg); + + printf("%-9s%-6s%-4s%-8s%-7s%02x", + reg_lvt_bit_str(reg, tmp_val, Mask), + reg_lvt_bit_str(reg, tmp_val, Trigger_mode), + reg_lvt_bit_str(reg, tmp_val, Remote_irr), + reg_lvt_bit_str(reg, tmp_val, Delivery_state), + reg_lvt_bit_str(reg, tmp_val, Delivery_mode), + reg_lvt_vector(tmp_val)); +} + +PUBLIC static +void +Apic::regs_show(void) +{ + putstr("\nVectors: LINT0: "); reg_show(APIC_lvt0); + putstr("\n LINT1: "); reg_show(APIC_lvt1); + putstr("\n Timer: "); reg_show(APIC_lvtt); + putstr("\n Error: "); reg_show(APIC_lvterr); + if (have_pcint()) + { + putstr("\n PerfCnt: "); + reg_show(APIC_lvtpc); + } + if (have_tsint()) + { + putstr("\n Thermal: "); + reg_show(APIC_lvtthmr); + } + putchar('\n'); +} + +PUBLIC static +void +Apic::timer_show(void) +{ + printf("Timer mode: %s counter: %08x/%08x\n", + reg_read(APIC_lvtt) & APIC_lvt_timer_periodic + ? "periodic" : "one-shot", + timer_reg_read_initial(), timer_reg_read()); +} + +PUBLIC static +void +Apic::id_show(void) +{ + printf("APIC id: %02x version: %02x\n", get_id() >> 24, get_version()); +} + +static +void +Apic::bitfield_show(unsigned reg, const char *name, char flag) +{ + int i, j; + Unsigned32 tmp_val; + + printf("%-11s 0123456789abcdef0123456789abcdef" + "0123456789abcdef0123456789abcdef\n", name); + for (i=0; i<8; i++) + { + if (!(i & 1)) + printf(" %02x ", i*0x20); + tmp_val = reg_read(reg + i*0x10); + for (j=0; j<32; j++) + putchar(tmp_val & (1< +#include "cpu.h" +#include "processor.h" + +PUBLIC static inline +Signed32 +Apic::apic_id() +{ + return ((reg_read(APIC_ID) >> 24) & 0xff); +} + +PUBLIC static inline +void +Apic::disable_external_ints() +{ + reg_write(APIC_lvt0, 0x0001003f); + reg_write(APIC_lvt1, 0x0001003f); +} + +PUBLIC static inline +bool +Apic::mp_ipi_idle() +{ + return ((reg_read(APIC_ICR) & 0x00001000) == 0); +} + +PRIVATE static inline +bool +Apic::mp_ipi_idle_timeout(Cpu const *c, Unsigned32 wait) +{ + Unsigned64 wait_till = c->time_us() + wait; + while (!mp_ipi_idle() && c->time_us() < wait_till) + Proc::pause(); + return mp_ipi_idle(); +} + +PUBLIC static inline NEEDS [] +void +Apic::mp_send_ipi(Unsigned32 dest, Unsigned32 vect, + Unsigned32 mode = APIC_IPI_FIXED) +{ + Unsigned32 tmp_val; + + assert((dest & 0x00f3ffff) == 0); + assert(vect <= 0xff); + + while (!mp_ipi_idle()) + Proc::pause(); + + // Set destination for no-shorthand destination type + if ((dest & APIC_IPI_DSTMSK) == APIC_IPI_NOSHRT) + { + tmp_val = reg_read(APIC_ICR2); + tmp_val &= 0x00ffffff; + tmp_val |= dest & 0xff000000; + reg_write(APIC_ICR2, tmp_val); + } + + // send the interrupt vector to the destination... + tmp_val = reg_read(APIC_ICR); + tmp_val &= 0xfff32000; + tmp_val |= (dest & 0x000c0000) | + ( 0x00004000) | // phys proc num, edge triggered, assert + (mode & 0x00000700) | + (vect & 0x000000ff); + reg_write(APIC_ICR, tmp_val); +} + +PUBLIC static inline +void +Apic::mp_ipi_ack() +{ + reg_write(APIC_eoi, 0); +} + + +PUBLIC static +void +Apic::init_ap() +{ + dump_info(); + // set some interrupt vectors to appropriate values + init_lvt(); + + // initialize APIC_spiv register + init_spiv(); + + // initialize task-priority register + init_tpr(); + + disable_external_ints(); + + // get timer going on this CPU + init_timer(); +} + +PUBLIC static +void +Apic::mp_startup(Cpu const *current_cpu, Unsigned32 dest, Address tramp_page) +{ + assert((tramp_page & 0xfff00fff) == 0); + + // XXX: should check for the apic version what to do exactly + // XXX: should check for some errors after sending ipi + + // Send INIT IPI + mp_send_ipi(dest, 0, APIC_IPI_INIT); + + // delay for 10ms (=10,000us) + if (!mp_ipi_idle_timeout(current_cpu, 10000)) + return; + + // Send STARTUP IPI + mp_send_ipi(dest, tramp_page >> 12, APIC_IPI_STRTUP); + + // delay for 200us + if (!mp_ipi_idle_timeout(current_cpu, 200)) + return; + + // Send STARTUP IPI + mp_send_ipi(dest, tramp_page >> 12, APIC_IPI_STRTUP); + + // delay for 200us + if (!mp_ipi_idle_timeout(current_cpu, 200)) + return; +} diff --git a/kernel/fiasco/src/kern/ia32/apic-ia32.cpp b/kernel/fiasco/src/kern/ia32/apic-ia32.cpp new file mode 100644 index 00000000..ef7ed5a1 --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/apic-ia32.cpp @@ -0,0 +1,838 @@ +INTERFACE: + +#include "types.h" +#include "initcalls.h" + +class Return_frame; +class Cpu; + +class Apic +{ +public: + static void init() FIASCO_INIT; + +private: + Apic(); // default constructors are undefined + Apic(const Apic&); + static void error_interrupt(Return_frame *regs) + asm ("apic_error_interrupt") FIASCO_FASTCALL; + + static int present; + static int good_cpu; + static const Address io_base; + static Address phys_base; + static unsigned timer_divisor; + static unsigned frequency_khz; + static Unsigned64 scaler_us_to_apic; + + enum + { + APIC_id = 0x20, + APIC_lvr = 0x30, + APIC_tpr = 0x80, + APIC_tpri_mask = 0xFF, + APIC_eoi = 0xB0, + APIC_ldr = 0xD0, + APIC_ldr_mask = (0xFF<<24), + APIC_dfr = 0xE0, + APIC_spiv = 0xF0, + APIC_isr = 0x100, + APIC_tmr = 0x180, + APIC_irr = 0x200, + APIC_esr = 0x280, + APIC_lvtt = 0x320, + APIC_lvtthmr = 0x330, + APIC_lvtpc = 0x340, + APIC_lvt0 = 0x350, + APIC_timer_base_div = 0x2, + APIC_lvt1 = 0x360, + APIC_lvterr = 0x370, + APIC_tmict = 0x380, + APIC_tmcct = 0x390, + APIC_tdcr = 0x3E0, + + APIC_snd_pending = (1<<12), + APIC_input_polarity = (1<<13), + APIC_lvt_remote_irr = (1<<14), + APIC_lvt_level_trigger = (1<<15), + APIC_lvt_masked = (1<<16), + APIC_lvt_timer_periodic = (1<<17), + APIC_tdr_div_1 = 0xB, + APIC_tdr_div_2 = 0x0, + APIC_tdr_div_4 = 0x1, + APIC_tdr_div_8 = 0x2, + APIC_tdr_div_16 = 0x3, + APIC_tdr_div_32 = 0x8, + APIC_tdr_div_64 = 0x9, + APIC_tdr_div_128 = 0xA, + }; + + enum + { + Mask = 1, + Trigger_mode = 2, + Remote_irr = 4, + Pin_polarity = 8, + Delivery_state = 16, + Delivery_mode = 32, + }; + + enum + { + APIC_base_msr = 0x1b, + }; +}; + +extern unsigned apic_spurious_interrupt_bug_cnt; +extern unsigned apic_spurious_interrupt_cnt; +extern unsigned apic_error_cnt; + + +//---------------------------------------------------------------------------- +IMPLEMENTATION: +#include "cpu.h" + +PRIVATE static +Cpu & +Apic::cpu() { return *Cpu::boot_cpu(); } + + +//---------------------------------------------------------------------------- +IMPLEMENTATION[ia32]: + +PUBLIC static inline +Unsigned32 +Apic::us_to_apic(Unsigned64 us) +{ + Unsigned32 apic, dummy1, dummy2; + asm ("movl %%edx, %%ecx \n\t" + "mull %4 \n\t" + "movl %%ecx, %%eax \n\t" + "movl %%edx, %%ecx \n\t" + "mull %4 \n\t" + "addl %%ecx, %%eax \n\t" + "shll $11, %%eax \n\t" + :"=a" (apic), "=d" (dummy1), "=&c" (dummy2) + : "A" (us), "g" (scaler_us_to_apic) + ); + return apic; +} + +IMPLEMENTATION[amd64]: + +PUBLIC static inline +Unsigned32 +Apic::us_to_apic(Unsigned64 us) +{ + Unsigned32 apic, dummy; + asm ("mulq %3 \n\t" + "shrq $21,%%rax \n\t" + :"=a"(apic), "=d"(dummy) + :"a"(us), "g"(scaler_us_to_apic) + ); + return apic; +} + +IMPLEMENTATION[ia32,amd64]: + +#include +#include +#include +#include + +#include "config.h" +#include "cpu.h" +#include "cpu_lock.h" +#include "entry_frame.h" +#include "globals.h" +#include "io.h" +#include "kmem.h" +#include "kip.h" +#include "lock_guard.h" +#include "panic.h" +#include "processor.h" +#include "regdefs.h" +#include "pic.h" +#include "pit.h" + +unsigned apic_spurious_interrupt_bug_cnt; +unsigned apic_spurious_interrupt_cnt; +unsigned apic_error_cnt; +Address apic_io_base; + +int Apic::present; +int Apic::good_cpu; +const Address Apic::io_base = Mem_layout::Local_apic_page; +Address Apic::phys_base; +unsigned Apic::timer_divisor = 1; +unsigned Apic::frequency_khz; +Unsigned64 Apic::scaler_us_to_apic; + +int ignore_invalid_apic_reg_access; + +PUBLIC static inline +Unsigned32 +Apic::get_id() +{ + return reg_read(APIC_id) & 0xff000000; +} + +PRIVATE static inline +Unsigned32 +Apic::get_version() +{ + return reg_read(APIC_lvr) & 0xFF; +} + +PRIVATE static inline NOEXPORT +int +Apic::is_integrated() +{ + return reg_read(APIC_lvr) & 0xF0; +} + +PRIVATE static inline NOEXPORT +Unsigned32 +Apic::get_max_lvt_local() +{ + return ((reg_read(APIC_lvr) >> 16) & 0xFF); +} + +PRIVATE static inline NOEXPORT +Unsigned32 +Apic::get_num_errors() +{ + reg_write(APIC_esr, 0); + return reg_read(APIC_esr); +} + +PRIVATE static inline NOEXPORT +void +Apic::clear_num_errors() +{ + reg_write(APIC_esr, 0); + reg_write(APIC_esr, 0); +} + +PUBLIC static inline +unsigned +Apic::get_frequency_khz() +{ + return frequency_khz; +} + +PUBLIC static inline +Unsigned32 +Apic::reg_read(unsigned reg) +{ + return *((volatile Unsigned32*)(io_base + reg)); +} + +PUBLIC static inline +void +Apic::reg_write(unsigned reg, Unsigned32 val) +{ + *((volatile Unsigned32*)(io_base + reg)) = val; +} + +PUBLIC static inline +int +Apic::reg_delivery_mode(Unsigned32 val) +{ + return (val >> 8) & 7; +} + +PUBLIC static inline +int +Apic::reg_lvt_vector(Unsigned32 val) +{ + return val & 0xff; +} + +PUBLIC static inline +Unsigned32 +Apic::timer_reg_read() +{ + return reg_read(APIC_tmcct); +} + +PUBLIC static inline +Unsigned32 +Apic::timer_reg_read_initial() +{ + return reg_read(APIC_tmict); +} + +PUBLIC static inline +void +Apic::timer_reg_write(Unsigned32 val) +{ + reg_read(APIC_tmict); + reg_write(APIC_tmict, val); +} + +PUBLIC static inline NEEDS["cpu.h"] +Address +Apic::apic_page_phys() +{ return Cpu::rdmsr(APIC_base_msr) & 0xfffff000; } + +// set the global pagetable entry for the Local APIC device registers +PUBLIC +static +void +Apic::map_apic_page() +{ + Address offs; + Address base = apic_page_phys(); + // We should not change the physical address of the Local APIC page if + // possible since some versions of VMware would complain about a + // non-implemented feature + Kmem::map_phys_page(base, Mem_layout::Local_apic_page, + false, true, &offs); + + Kip::k()->add_mem_region(Mem_desc(base, base + Config::PAGE_SIZE - 1, Mem_desc::Reserved)); + + assert(offs == 0); +} + +// check CPU type if APIC could be present +static FIASCO_INIT +int +Apic::test_cpu() +{ + if (!cpu().can_wrmsr() || !(cpu().features() & FEAT_TSC)) + return 0; + + if (cpu().vendor() == Cpu::Vendor_intel) + { + if (cpu().family() == 15) + return 1; + if (cpu().family() >= 6) + return 1; + } + if (cpu().vendor() == Cpu::Vendor_amd && cpu().family() >= 6) + return 1; + + return 0; +} + +// test if APIC present +static inline +int +Apic::test_present() +{ + return cpu().features() & FEAT_APIC; +} + +PUBLIC static inline +void +Apic::timer_enable_irq() +{ + Unsigned32 tmp_val; + + tmp_val = reg_read(APIC_lvtt); + tmp_val &= ~(APIC_lvt_masked); + reg_write(APIC_lvtt, tmp_val); +} + +PUBLIC static inline +void +Apic::timer_disable_irq() +{ + Unsigned32 tmp_val; + + tmp_val = reg_read(APIC_lvtt); + tmp_val |= APIC_lvt_masked; + reg_write(APIC_lvtt, tmp_val); +} + +PUBLIC static inline +int +Apic::timer_is_irq_enabled() +{ + return ~reg_read(APIC_lvtt) & APIC_lvt_masked; +} + +PUBLIC static inline +void +Apic::timer_set_periodic() +{ + Unsigned32 tmp_val = reg_read(APIC_lvtt); + tmp_val |= APIC_lvt_timer_periodic; + reg_write(APIC_lvtt, tmp_val); +} + +PUBLIC static inline +void +Apic::timer_set_one_shot() +{ + Unsigned32 tmp_val = reg_read(APIC_lvtt); + tmp_val &= ~APIC_lvt_timer_periodic; + reg_write(APIC_lvtt, tmp_val); +} + +PUBLIC static inline +void +Apic::timer_assign_irq_vector(unsigned vector) +{ + Unsigned32 tmp_val = reg_read(APIC_lvtt); + tmp_val &= 0xffffff00; + tmp_val |= vector; + reg_write(APIC_lvtt, tmp_val); +} + +PUBLIC static inline +void +Apic::irq_ack() +{ + reg_read(APIC_spiv); + reg_write(APIC_eoi, 0); +} + +static +void +Apic::timer_set_divisor(unsigned newdiv) +{ + int i; + int div = -1; + int divval = newdiv; + Unsigned32 tmp_value; + + static int divisor_tab[8] = + { + APIC_tdr_div_1, APIC_tdr_div_2, APIC_tdr_div_4, APIC_tdr_div_8, + APIC_tdr_div_16, APIC_tdr_div_32, APIC_tdr_div_64, APIC_tdr_div_128 + }; + + for (i=0; i<8; i++) + { + if (divval & 1) + { + if (divval & ~1) + { + printf("bad APIC divisor %d\n", newdiv); + return; + } + div = divisor_tab[i]; + break; + } + divval >>= 1; + } + + if (div != -1) + { + timer_divisor = newdiv; + tmp_value = reg_read(APIC_tdcr); + tmp_value &= ~0x1F; + tmp_value |= div; + reg_write(APIC_tdcr, tmp_value); + } +} + +static +int +Apic::get_max_lvt() +{ + return is_integrated() ? get_max_lvt_local() : 2; +} + +PUBLIC static inline +int +Apic::have_pcint() +{ + return (present && (get_max_lvt() >= 4)); +} + +PUBLIC static inline +int +Apic::have_tsint() +{ + return (present && (get_max_lvt() >= 5)); +} + +// check if APIC is working (check timer functionality) +static FIASCO_INIT +int +Apic::check_working() +{ + Unsigned64 tsc_until; + + timer_disable_irq(); + timer_set_divisor(1); + timer_reg_write(0x10000000); + + tsc_until = Cpu::rdtsc() + 0x100; // we only have to wait for one bus cycle + + do + { + if (timer_reg_read() != 0x10000000) + return 1; + } while (Cpu::rdtsc() < tsc_until); + + return 0; +} + +static FIASCO_INIT_CPU +void +Apic::init_spiv() +{ + Unsigned32 tmp_val; + + tmp_val = reg_read(APIC_spiv); + tmp_val |= (1<<8); // enable APIC + tmp_val &= ~(1<<9); // enable Focus Processor Checking + tmp_val &= ~0xff; + tmp_val |= APIC_IRQ_BASE + 0xf; // Set spurious IRQ vector to 0x3f + // bit 0..3 are hardwired to 1 on PPro! + reg_write(APIC_spiv, tmp_val); +} + +PUBLIC static inline NEEDS[Apic::reg_write] +void +Apic::tpr(unsigned prio) +{ reg_write(APIC_tpr, prio); } + +PUBLIC static inline NEEDS[Apic::reg_read] +unsigned +Apic::tpr() +{ return reg_read(APIC_tpr); } + +static FIASCO_INIT_CPU +void +Apic::init_tpr() +{ + reg_write (APIC_tpr, 0); +} + +// activate APIC error interrupt +static FIASCO_INIT_CPU +void +Apic::enable_errors() +{ + if (is_integrated()) + { + Unsigned32 tmp_val, before, after; + + if (get_max_lvt() > 3) + clear_num_errors(); + before = get_num_errors(); + + tmp_val = reg_read(APIC_lvterr); + tmp_val &= 0xfffeff00; // unmask error IRQ vector + tmp_val |= APIC_IRQ_BASE + 3; // Set error IRQ vector to 0x63 + reg_write(APIC_lvterr, tmp_val); + + if (get_max_lvt() > 3) + clear_num_errors(); + after = get_num_errors(); + printf("APIC ESR value before/after enabling: %08x/%08x\n", + before, after); + } +} + +// activate APIC after activating by MSR was successful +// see "Intel Architecture Software Developer's Manual, +// Volume 3: System Programming Guide, Appendix E" +static FIASCO_INIT +void +Apic::route_pic_through_apic() +{ + Unsigned32 tmp_val; + Lock_guard guard(&cpu_lock); + + // mask 8259 interrupts + Pic::Status old_irqs = Pic::disable_all_save(); + + // set LINT0 to ExtINT, edge triggered + tmp_val = reg_read(APIC_lvt0); + tmp_val &= 0xfffe5800; + tmp_val |= 0x00000700; + reg_write(APIC_lvt0, tmp_val); + + // set LINT1 to NMI, edge triggered + tmp_val = reg_read(APIC_lvt1); + tmp_val &= 0xfffe5800; + tmp_val |= 0x00000400; + reg_write(APIC_lvt1, tmp_val); + + // unmask 8259 interrupts + Pic::restore_all(old_irqs); + + printf("APIC was disabled --- routing PIC through APIC\n"); +} + +static FIASCO_INIT_CPU +void +Apic::init_lvt() +{ + Unsigned32 tmp_val; + Lock_guard guard(&cpu_lock); + + // mask timer interrupt and set vector to _not_ invalid value + tmp_val = reg_read(APIC_lvtt); + tmp_val |= APIC_lvt_masked; + tmp_val |= 0xff; + reg_write(APIC_lvtt, tmp_val); + if (have_pcint()) + { + // mask performance interrupt and set vector to a valid value + tmp_val = reg_read(APIC_lvtpc); + tmp_val |= APIC_lvt_masked; + tmp_val |= 0xff; + reg_write(APIC_lvtpc, tmp_val); + } + if (have_tsint()) + { + // mask thermal sensor interrupt and set vector to a valid value + tmp_val = reg_read(APIC_lvtthmr); + tmp_val |= APIC_lvt_masked; + tmp_val |= 0xff; + reg_write(APIC_lvtthmr, tmp_val); + } +} + +// give us a hint if we have an APIC but it is disabled +PUBLIC static +int +Apic::test_present_but_disabled() +{ + if (!good_cpu) + return 0; + + Unsigned64 msr = Cpu::rdmsr(APIC_base_msr); + return ((msr & 0xffffff000ULL) == 0xfee00000ULL); +} + +// activate APIC by writing to appropriate MSR +static FIASCO_INIT_CPU +void +Apic::activate_by_msr() +{ + Unsigned64 msr; + + msr = Cpu::rdmsr(APIC_base_msr); + phys_base = msr & 0xfffff000; + msr |= (1<<11); + Cpu::wrmsr(msr, APIC_base_msr); + + // now the CPU feature flags may have changed + cpu().identify(); +} + +// check if we still receive interrupts after we changed the IRQ routing +PUBLIC static FIASCO_INIT_CPU +int +Apic::check_still_getting_interrupts() +{ + if (!Config::apic) + return 0; + + Unsigned64 tsc_until; + Cpu_time clock_start = Kip::k()->clock; + + tsc_until = Cpu::rdtsc(); + tsc_until += 0x01000000; // > 10 Mio cycles should be sufficient until + // we have processors with more than 10 GHz + do + { + // kernel clock by timer interrupt updated? + if (Kip::k()->clock != clock_start) + // yes, succesful + return 1; + } while (Cpu::rdtsc() < tsc_until); + + // timeout + return 0; +} + +PUBLIC static +inline int +Apic::is_present() +{ + return present; +} + +PUBLIC static +void +Apic::set_perf_nmi() +{ + if (have_pcint()) + reg_write(APIC_lvtpc, 0x400); +} + +static FIASCO_INIT_CPU +void +Apic::calibrate_timer() +{ + const unsigned calibrate_time = 50; + Unsigned32 count, tt1, tt2, result, dummy; + Unsigned32 runs = 0, frequency_ok; + + do + { + frequency_khz = 0; + + timer_disable_irq(); + timer_set_divisor(1); + timer_reg_write(1000000000); + + { + Lock_guard guard(&cpu_lock); + + Pit::setup_channel2_to_20hz(); + + count = 0; + + tt1 = timer_reg_read(); + do + { + count++; + } + while ((Io::in8(0x61) & 0x20) == 0); + tt2 = timer_reg_read(); + } + + result = (tt1 - tt2) * timer_divisor; + + // APIC not running + if (count <= 1) + return; + + asm ("divl %2" + :"=a" (frequency_khz), "=d" (dummy) + : "r" (calibrate_time), "a" (result), "d" (0)); + + frequency_ok = (frequency_khz < (1000<<11)); + } + while (++runs < 10 && !frequency_ok); + + if (!frequency_ok) + panic("APIC frequency too high, adapt Apic::scaler_us_to_apic"); + + Kip::k()->frequency_bus = frequency_khz; + scaler_us_to_apic = Cpu::muldiv(1<<21, frequency_khz, 1000); +} + +IMPLEMENT +void +Apic::error_interrupt(Return_frame *regs) +{ + Unsigned32 err1, err2; + + // we are entering with disabled interrupts + err1 = Apic::get_num_errors(); + Apic::clear_num_errors(); + err2 = Apic::get_num_errors(); + Apic::irq_ack(); + + cpu_lock.clear(); + + if (err1 == 0x80 || err2 == 0x80) + { + // ignore possible invalid access which may happen in + // jdb::do_dump_memory() + if (ignore_invalid_apic_reg_access) + return; + + printf("cpu%d: APIC invalid register access error at " L4_PTR_FMT "\n", + current_cpu(), regs->ip()); + return; + } + + apic_error_cnt++; + printf("cpu%d: APIC error %08x(%08x)\n", current_cpu(), err1, err2); +} + +// deactivate APIC by writing to appropriate MSR +PUBLIC static +void +Apic::done() +{ + Unsigned64 val; + + if (!present) + return; + + val = reg_read(APIC_spiv); + val &= ~(1<<8); + reg_write(APIC_spiv, val); + + val = Cpu::rdmsr(APIC_base_msr); + val &= ~(1<<11); + Cpu::wrmsr(val, APIC_base_msr); +} + +PRIVATE static FIASCO_INIT_CPU +void +Apic::init_timer() +{ + calibrate_timer(); + timer_set_divisor(1); + enable_errors(); +} + +PUBLIC static +void +Apic::dump_info() +{ + printf("Local APIC[%02x]: version=%02x max_lvt=%d\n", + get_id() >> 24, get_version(), get_max_lvt()); +} + +IMPLEMENT +void +Apic::init() +{ + int was_present; + + was_present = present = test_present(); + + if (!was_present) + { + good_cpu = test_cpu(); + + if (good_cpu && Config::apic) + { + // activate; this could lead an disabled APIC to appear + // set base address of I/O registers to be able to access the registers + activate_by_msr(); + present = test_present(); + } + } + + if (!Config::apic) + return; + + // initialize if available + if (present) + { + // map the Local APIC device registers + map_apic_page(); + + // set some interrupt vectors to appropriate values + init_lvt(); + + // initialize APIC_spiv register + init_spiv(); + + // initialize task-priority register + init_tpr(); + + // test if local timer counts down + if ((present = check_working())) + { + if (!was_present) + // APIC _was_ not present before writing to msr so we have + // to set APIC_lvt0 and APIC_lvt1 to appropriate values + route_pic_through_apic(); + } + } + + if (!present) + panic("Local APIC not found"); + + dump_info(); + + apic_io_base = Mem_layout::Local_apic_page; + init_timer(); +} diff --git a/kernel/fiasco/src/kern/ia32/asm.h b/kernel/fiasco/src/kern/ia32/asm.h new file mode 100644 index 00000000..84a1105f --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/asm.h @@ -0,0 +1,78 @@ +#ifndef ASM_SANITY_CHECK_H +#define ASM_SANITY_CHECK_H + +#include "globalconfig.h" +#include "shortcut.h" +#include "tcboffset.h" + +#define kdb_ke_asm(msg) \ + int3 ;\ + jmp 9f ;\ + .ascii msg ;\ +9: + +//.macro REGS this_ptr, dst +// leal (THREAD_BLOCK_SIZE - OFS__ENTRY_FRAME__MAX)(\this_ptr), \dst +//.endm + +#ifdef CONFIG_BEFORE_IRET_SANITY + + // some sanity checks before return to user + // touches ecx and the thread-stack + .macro CHECK_SANITY csseg + + .ifnc \csseg,$3 + // don't check if we return to kernelmode + movl \csseg, %ecx + andb $3, %cl + jz 2f + .endif + + pushl %ebx + pushl %edx + ESP_TO_TCB_AT %ebx + + // are we holding locks? + cmpl $0, OFS__THREAD__LOCK_CNT(%ebx) + jne 1f + .text 1 +1: kdb_ke_asm("Before IRET: Thread holds a lock") + jmp 1f + .previous +1: + + // check for the right thread state + // (cancel and fpu_owner might also be set) + movl OFS__THREAD__STATE(%ebx), %edx + andl $~(Thread_cancel | Thread_fpu_owner | Thread_alien_or_vcpu_user | Thread_dis_alien), %edx + cmpl $(Thread_ready), %edx + jne 1f + .text 1 +1: kdb_ke_asm("Before IRET: Wrong thread state") + jmp 1f + .previous +1: + + // test if we are locked + cmpl $0, OFS__THREAD__THREAD_LOCK__SWITCH_LOCK__LOCK_OWNER (%ebx) + jne 1f + .text 1 +1: kdb_ke_asm("Before IRET: Thread is locked") + jmp 1f + .previous +1: + + popl %edx + popl %ebx +2: + + .endm + +#else // ! DO_SANITY_CHECKS_BEFORE_IRET + + .macro CHECK_SANITY csseg + .endm + +#endif // DO_SANITY_CHECKS_BEFORE_IRET + +#endif // ASM_SANITY_CHECK_H diff --git a/kernel/fiasco/src/kern/ia32/boot_console-ia32-amd64.cpp b/kernel/fiasco/src/kern/ia32/boot_console-ia32-amd64.cpp new file mode 100644 index 00000000..6e40cda2 --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/boot_console-ia32-amd64.cpp @@ -0,0 +1,52 @@ +INTERFACE[ia32,amd64]: + +class Console; + +class Boot_console +{ +public: + static void init(); +}; + +IMPLEMENTATION[ia32,amd64]: + +#include +#include + +#include "kernel_console.h" +#include "keyb.h" +#include "mux_console.h" +#include "initcalls.h" +#include "koptions.h" +#include "static_init.h" +#include "vga_console.h" +#include "mem_layout.h" + +static Static_object vga; +static Static_object keyb; + +IMPLEMENT FIASCO_INIT +void Boot_console::init() +{ + keyb.construct(); + Kconsole::console()->register_console(keyb); + + if (Koptions::o()->opt(Koptions::F_noscreen)) + return; + +#if defined(CONFIG_IRQ_SPINNER) + vga.construct((unsigned long)Mem_layout::Adap_vram_cga_beg,80,20,true,true); +#else + vga.construct((unsigned long)Mem_layout::Adap_vram_cga_beg,80,25,true,true); +#endif + + if (vga->is_working()) + Kconsole::console()->register_console(vga); + +#if defined(CONFIG_IRQ_SPINNER) + for (int y = 20; y < 25; ++y) + for (int x = 0; x < 80; ++x) + vga->printchar(x, y, ' ', 8); +#endif +}; + diff --git a/kernel/fiasco/src/kern/ia32/boot_info-ia32.cpp b/kernel/fiasco/src/kern/ia32/boot_info-ia32.cpp new file mode 100644 index 00000000..fb972199 --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/boot_info-ia32.cpp @@ -0,0 +1,85 @@ +INTERFACE[ia32,amd64]: + +#include "types.h" + +EXTENSION class Boot_info +{ +private: + static unsigned _flag; + static unsigned _checksum_ro; + static unsigned _checksum_rw; +}; + +//----------------------------------------------------------------------------- +IMPLEMENTATION[ia32,amd64]: + +#include +#include +#include +#include "checksum.h" +#include "mem_layout.h" + +// these members needs to be initialized with some +// data to go into the data section and not into bss +unsigned Boot_info::_flag = 3; +unsigned Boot_info::_checksum_ro = 15; +unsigned Boot_info::_checksum_rw = 16; + + +/// \defgroup pre init setup +/** + * The Boot_info object must be set up with these functions + * before Boot_info::init() is called! + * This can be done either in __main, if booted on hardware + * or in an initializer with a higher priority than BOOT_INFO_INIT_PRIO + * (e.g UX_STARTUP1_INIT_PRIO) if the kernel runs on software (FIASCO-UX) + */ +//@{ + +PUBLIC inline static +void Boot_info::set_flags(unsigned aflags) +{ _flag = aflags; } + +PUBLIC inline static +void Boot_info::set_checksum_ro(unsigned ro_cs) +{ _checksum_ro = ro_cs; } + +PUBLIC inline static +void Boot_info::set_checksum_rw(unsigned rw_cs) +{ _checksum_rw = rw_cs; } +//@} + + +IMPLEMENT +void +Boot_info::init() +{} + +PUBLIC inline static +unsigned +Boot_info::get_flags(void) +{ + return _flag; +} + +PUBLIC inline static +unsigned +Boot_info::get_checksum_ro(void) +{ + return _checksum_ro; +} + +PUBLIC inline static +unsigned +Boot_info::get_checksum_rw(void) +{ + return _checksum_rw; +} + +PUBLIC static +void +Boot_info::reset_checksum_ro(void) +{ + set_checksum_ro(Checksum::get_checksum_ro()); +} + diff --git a/kernel/fiasco/src/kern/ia32/clock-ia32.cpp b/kernel/fiasco/src/kern/ia32/clock-ia32.cpp new file mode 100644 index 00000000..438ea24e --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/clock-ia32.cpp @@ -0,0 +1,28 @@ +INTERFACE [ia32 || amd64 || ux]: + +#include "l4_types.h" + +EXTENSION class Clock_base +{ +protected: + typedef Unsigned64 Counter; +}; + +// ------------------------------------------------------------------------ +IMPLEMENTATION [ia32 || amd64 || ux]: + +#include "cpu.h" + +IMPLEMENT inline NEEDS["cpu.h"] +Clock::Counter +Clock::read_counter() const +{ + return Cpu::rdtsc(); +} + +IMPLEMENT inline NEEDS["cpu.h"] +Cpu_time +Clock::us(Time t) +{ + return Cpu::cpus.cpu(_cpu_id).tsc_to_us(t); +} diff --git a/kernel/fiasco/src/kern/ia32/config-ia32.cpp b/kernel/fiasco/src/kern/ia32/config-ia32.cpp new file mode 100644 index 00000000..8a32b753 --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/config-ia32.cpp @@ -0,0 +1,165 @@ +/* IA32/AMD64 specific */ +INTERFACE[ia32,amd64]: + +#include "idt_init.h" + +EXTENSION class Config +{ +public: + + enum + { + // can access user memory directly + Access_user_mem = Access_user_mem_direct, + + /// Timer vector used with APIC timer or IOAPIC + Apic_timer_vector = APIC_IRQ_BASE + 0, + }; + + static unsigned scheduler_irq_vector; + + enum Scheduler_config + { + SCHED_PIT = 0, + SCHED_RTC, + SCHED_APIC, + SCHED_HPET, + +#ifdef CONFIG_SCHED_PIT + Scheduler_mode = SCHED_PIT, + Scheduler_granularity = 1000U, + Default_time_slice = 10 * Scheduler_granularity, +#endif + +#ifdef CONFIG_ONE_SHOT + Scheduler_one_shot = true, +#else + Scheduler_one_shot = false, +#endif + +#ifdef CONFIG_SCHED_RTC + Scheduler_mode = SCHED_RTC, +# ifdef CONFIG_SLOW_RTC + Scheduler_granularity = 15625U, +# else + Scheduler_granularity = 976U, +# endif + Default_time_slice = 10 * Scheduler_granularity, +#endif + +#ifdef CONFIG_SCHED_APIC + Scheduler_mode = SCHED_APIC, +# ifdef CONFIG_ONE_SHOT + Scheduler_granularity = 1U, + Default_time_slice = 10000 * Scheduler_granularity, +# else + Scheduler_granularity = 1000U, + Default_time_slice = 10 * Scheduler_granularity, +# endif +#endif + +#ifdef CONFIG_SCHED_HPET + Scheduler_mode = SCHED_HPET, + Scheduler_granularity = 1000U, + Default_time_slice = 10 * Scheduler_granularity, +#endif + }; + + enum + { + Pic_prio_modify = true, +#ifdef CONFIG_SYNC_TSC + Kip_timer_uses_rdtsc = true, +#else + Kip_timer_uses_rdtsc = false, +#endif + }; + + static bool apic; + +#ifdef CONFIG_WATCHDOG + static bool watchdog; +#else + static const bool watchdog = false; +#endif + +// static const bool hlt_works_ok = false; + static bool hlt_works_ok; + + // the default uart to use for serial console + static const unsigned default_console_uart = 1; + static const unsigned default_console_uart_baudrate = 115200; + + static char const char_micro; + + static bool found_vmware; + + enum { + Is_ux = 0, + }; +}; + +IMPLEMENTATION[ia32,amd64]: + +#include + +bool Config::hlt_works_ok = true; + +bool Config::found_vmware = false; +char const Config::char_micro = '\265'; +bool Config::apic = false; +unsigned Config::scheduler_irq_vector; + +#ifdef CONFIG_WATCHDOG +bool Config::watchdog = false; +#endif + +const char *const Config::kernel_warn_config_string = +#ifdef CONFIG_SCHED_RTC + " CONFIG_SCHED_RTC is on\n" +#endif +#ifndef CONFIG_INLINE + " CONFIG_INLINE is off\n" +#endif +#ifndef CONFIG_NDEBUG + " CONFIG_NDEBUG is off\n" +#endif +#ifndef CONFIG_NO_FRAME_PTR + " CONFIG_NO_FRAME_PTR is off\n" +#endif +#ifdef CONFIG_LIST_ALLOC_SANITY + " CONFIG_LIST_ALLOC_SANITY is on\n" +#endif +#ifdef CONFIG_BEFORE_IRET_SANITY + " CONFIG_BEFORE_IRET_SANITY is on\n" +#endif +#ifdef CONFIG_FINE_GRAINED_CPUTIME + " CONFIG_FINE_GRAINED_CPUTIME is on\n" +#endif +#ifdef CONFIG_JDB_ACCOUNTING + " CONFIG_JDB_ACCOUNTING is on\n" +#endif + ""; + +IMPLEMENT FIASCO_INIT +void +Config::init_arch() +{ +#ifdef CONFIG_WATCHDOG + if (Koptions::o()->opt(Koptions::F_watchdog)) + { + watchdog = true; + apic = true; + } +#endif + + if (Koptions::o()->opt(Koptions::F_nohlt)) + hlt_works_ok = false; + + if (Koptions::o()->opt(Koptions::F_apic)) + apic = true; + + if (Scheduler_mode == SCHED_APIC) + apic = true; +} + diff --git a/kernel/fiasco/src/kern/ia32/context-ia32.cpp b/kernel/fiasco/src/kern/ia32/context-ia32.cpp new file mode 100644 index 00000000..98a42ec2 --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/context-ia32.cpp @@ -0,0 +1,67 @@ +IMPLEMENTATION [ia32,amd64,ux]: + +#include +#include + +#include "cpu.h" +#include "globals.h" // current() +#include "kmem.h" +#include "lock_guard.h" +#include "space.h" +#include "thread_state.h" + + +IMPLEMENT inline +void +Context::spill_user_state() +{} + +IMPLEMENT inline +void +Context::fill_user_state() +{} + +/** Thread context switchin. Called on every re-activation of a thread + (switch_exec()). This method is public only because it is called from + from assembly code in switch_cpu(). + */ +IMPLEMENT +void +Context::switchin_context(Context *from) +{ + assert_kdb (this == current()); + assert_kdb (state() & Thread_ready_mask); + + // Set kernel-esp in case we want to return to the user. + // kmem::kernel_sp() returns a pointer to the kernel SP (in the + // TSS) the CPU uses when next switching from user to kernel mode. + // regs() + 1 returns a pointer to the end of our kernel stack. + Cpu::cpus.cpu(cpu()).kernel_sp() = reinterpret_cast
(regs() + 1); + + // switch to our page directory if necessary + vcpu_aware_space()->switchin_context(from->vcpu_aware_space()); + + // load new segment selectors + load_segments(); +} + +//--------------------------------------------------------------------------- +IMPLEMENTATION [ia32 || ux]: + +PROTECTED inline NEEDS["cpu.h"] +void +Context::load_segments() +{ + Cpu::set_es((Unsigned32)_es); + Cpu::set_fs((Unsigned32)_fs); + Cpu::set_gs((Unsigned32)_gs); +} + +PROTECTED inline NEEDS["cpu.h"] +void +Context::store_segments() +{ + _es = Cpu::get_es(); + _fs = Cpu::get_fs(); + _gs = Cpu::get_gs(); +} diff --git a/kernel/fiasco/src/kern/ia32/cpu-ia32.cpp b/kernel/fiasco/src/kern/ia32/cpu-ia32.cpp new file mode 100644 index 00000000..5d080e28 --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/cpu-ia32.cpp @@ -0,0 +1,1707 @@ +INTERFACE[ia32,amd64,ux]: + +#include "types.h" +#include "initcalls.h" +#include "regdefs.h" +#include "per_cpu_data.h" + +EXTENSION +class Cpu +{ +public: + + enum Vendor + { + Vendor_unknown = 0, + Vendor_intel, + Vendor_amd, + Vendor_cyrix, + Vendor_via, + Vendor_umc, + Vendor_nexgen, + Vendor_rise, + Vendor_transmeta, + Vendor_sis, + Vendor_nsc + }; + + enum CacheTLB + { + Cache_unknown = 0, + Cache_l1_data, + Cache_l1_inst, + Cache_l1_trace, + Cache_l2, + Cache_l3, + Tlb_data_4k, + Tlb_inst_4k, + Tlb_data_4M, + Tlb_inst_4M, + Tlb_data_4k_4M, + Tlb_inst_4k_4M, + Tlb_data_2M_4M, + }; + + enum + { + Ldt_entry_size = 8, + }; + + enum Local_features + { + Lf_rdpmc = 0x00000001, + Lf_rdpmc32 = 0x00000002, + }; + + Unsigned64 time_us() const; + int can_wrmsr() const; + +private: + void init(); + Unsigned64 _frequency; + Unsigned32 _version; + Unsigned32 _brand; + Unsigned32 _features; + Unsigned32 _ext_features; + Unsigned32 _ext_8000_0001_ecx; + Unsigned32 _ext_8000_0001_edx; + Unsigned32 _local_features; + + Unsigned16 _inst_tlb_4k_entries; + Unsigned16 _data_tlb_4k_entries; + Unsigned16 _inst_tlb_4m_entries; + Unsigned16 _data_tlb_4m_entries; + Unsigned16 _inst_tlb_4k_4m_entries; + Unsigned16 _data_tlb_4k_4m_entries; + Unsigned16 _l2_inst_tlb_4k_entries; + Unsigned16 _l2_data_tlb_4k_entries; + Unsigned16 _l2_inst_tlb_4m_entries; + Unsigned16 _l2_data_tlb_4m_entries; + + Unsigned16 _l1_trace_cache_size; + Unsigned16 _l1_trace_cache_asso; + + Unsigned16 _l1_data_cache_size; + Unsigned16 _l1_data_cache_asso; + Unsigned16 _l1_data_cache_line_size; + + Unsigned16 _l1_inst_cache_size; + Unsigned16 _l1_inst_cache_asso; + Unsigned16 _l1_inst_cache_line_size; + + Unsigned16 _l2_cache_size; + Unsigned16 _l2_cache_asso; + Unsigned16 _l2_cache_line_size; + + Unsigned32 _l3_cache_size; + Unsigned16 _l3_cache_asso; + Unsigned16 _l3_cache_line_size; + + Unsigned8 _phys_bits; + Unsigned8 _virt_bits; + + Vendor _vendor; + char _model_str[52]; + + Unsigned32 _arch_perfmon_info_eax; + Unsigned32 _arch_perfmon_info_ebx; + Unsigned32 _arch_perfmon_info_ecx; + + Unsigned32 _monitor_mwait_eax; + Unsigned32 _monitor_mwait_ebx; + Unsigned32 _monitor_mwait_ecx; + Unsigned32 _monitor_mwait_edx; + + Unsigned32 scaler_tsc_to_ns; + Unsigned32 scaler_tsc_to_us; + Unsigned32 scaler_ns_to_tsc; + +public: + + void disable(unsigned cpu, char const *reason); + + char const *model_str() const { return _model_str; } + Vendor vendor() const { return _vendor; } + + unsigned family() const + { return (_version >> 8 & 0xf) + (_version >> 20 & 0xff); } + + char const *vendor_str() const + { return _vendor == Vendor_unknown ? "Unknown" : vendor_ident[_vendor]; } + + unsigned model() const + { return (_version >> 4 & 0xf) + (_version >> 12 & 0xf0); } + + unsigned stepping() const { return _version & 0xF; } + unsigned type() const { return (_version >> 12) & 0x3; } + Unsigned64 frequency() const { return _frequency; } + unsigned brand() const { return _brand & 0xFF; } + unsigned features() const { return _features; } + unsigned ext_features() const { return _ext_features; } + bool has_monitor_mwait() const { return _ext_features & (1 << 3); } + bool has_monitor_mwait_irq() const { return _monitor_mwait_ecx & 3; } + unsigned ext_8000_0001_ecx() const { return _ext_8000_0001_ecx; } + unsigned ext_8000_0001_edx() const { return _ext_8000_0001_edx; } + unsigned local_features() const { return _local_features; } + bool superpages() const { return features() & FEAT_PSE; } + bool tsc() const { return features() & FEAT_TSC; } + bool sysenter() const { return features() & FEAT_SEP; } + bool syscall() const { return ext_8000_0001_edx() & FEATA_SYSCALL; } + bool vmx() { return boot_cpu()->ext_features() & FEATX_VMX; } + bool svm() { return boot_cpu()->ext_8000_0001_ecx() & FEATA_SVM; } + bool has_amd_osvw() { return boot_cpu()->ext_8000_0001_ecx() & (1<<9); } + unsigned virt_bits() const { return _virt_bits; } + unsigned phys_bits() const { return _phys_bits; } + Unsigned32 get_scaler_tsc_to_ns() const { return scaler_tsc_to_ns; } + Unsigned32 get_scaler_tsc_to_us() const { return scaler_tsc_to_us; } + Unsigned32 get_scaler_ns_to_tsc() const { return scaler_ns_to_tsc; } + + Address volatile &kernel_sp() const; + +public: + static Per_cpu cpus asm ("CPUS_BASE"); + static Cpu *boot_cpu() { return _boot_cpu; } + + static bool have_superpages() { return boot_cpu()->superpages(); } + static bool have_sysenter() { return boot_cpu()->sysenter(); } + static bool have_syscall() { return boot_cpu()->syscall(); } + static bool have_fxsr() { return boot_cpu()->features() & FEAT_FXSR; } + static bool have_pge() { return boot_cpu()->features() & FEAT_PGE; } + +private: + + static Cpu *_boot_cpu; + + struct Vendor_table { + Unsigned32 vendor_mask; + Unsigned32 vendor_code; + Unsigned16 l2_cache; + char vendor_string[32]; + } __attribute__((packed)); + + struct Cache_table { + Unsigned8 desc; + Unsigned8 level; + Unsigned16 size; + Unsigned8 asso; + Unsigned8 line_size; + }; + + static Vendor_table const intel_table[]; + static Vendor_table const amd_table[]; + static Vendor_table const cyrix_table[]; + static Vendor_table const via_table[]; + static Vendor_table const umc_table[]; + static Vendor_table const nexgen_table[]; + static Vendor_table const rise_table[]; + static Vendor_table const transmeta_table[]; + static Vendor_table const sis_table[]; + static Vendor_table const nsc_table[]; + + static Cache_table const intel_cache_table[]; + + static char const * const vendor_ident[]; + static Vendor_table const * const vendor_table[]; + + static char const * const exception_strings[]; +}; + + +//----------------------------------------------------------------------------- +/* + * Fiasco ia32-native + * Architecture specific cpu init code + */ +INTERFACE [ia32, amd64]: + +#include "l4_types.h" +#include "initcalls.h" +#include "per_cpu_data.h" +#include "gdt.h" + +class Gdt; +class Tss; + + +EXTENSION class Cpu +{ +public: + enum Lbr + { + Lbr_uninitialized = 0, + Lbr_unsupported, + Lbr_pentium_6, + Lbr_pentium_4, + Lbr_pentium_4_ext, + }; + + enum Bts + { + Bts_uninitialized = 0, + Bts_unsupported, + Bts_pentium_m, + Bts_pentium_4, + }; + +private: + /** Flags if lbr or bts facilities are activated, used by double-fault + * handler to reset the debugging facilities + */ + Unsigned32 debugctl_busy; + + /** debugctl value for activating lbr or bts */ + Unsigned32 debugctl_set; + + /** debugctl value to reset activated lr/bts facilities in the double-faukt + * handler + */ + Unsigned32 debugctl_reset; + + /** supported lbr type */ + Lbr _lbr; + + /** supported bts type */ + Bts _bts; + + /** is lbr active ? */ + char lbr_active; + + /** is btf active ? */ + char btf_active; + + /** is bts active ? */ + char bts_active; + + Gdt *gdt; + Tss *tss; + Tss *tss_dbf; + +public: + Lbr lbr_type() const { return _lbr; } + Bts bts_type() const { return _bts; } + bool lbr_status() const { return lbr_active; } + bool bts_status() const { return bts_active; } + bool btf_status() const { return btf_active; } + + Gdt* get_gdt() const { return gdt; } + Tss* get_tss() const { return tss; } + void set_gdt() const + { + Pseudo_descriptor desc((Address)gdt, Gdt::gdt_max-1); + Gdt::set (&desc); + } + + static void set_tss() { set_tr(Gdt::gdt_tss); } + +private: + void init_lbr_type(); + void init_bts_type(); + +}; + +//----------------------------------------------------------------------------- +IMPLEMENTATION[ia32,amd64,ux]: + +#include +#include +#include "config.h" +#include "panic.h" +#include "processor.h" + +DEFINE_PER_CPU_P(0) Per_cpu Cpu::cpus(true); +Cpu *Cpu::_boot_cpu; + + +Cpu::Vendor_table const Cpu::intel_table[] FIASCO_INITDATA_CPU = +{ + { 0xf0fF0, 0x00400, 0xFFFF, "i486 DX-25/33" }, + { 0xf0fF0, 0x00410, 0xFFFF, "i486 DX-50" }, + { 0xf0fF0, 0x00420, 0xFFFF, "i486 SX" }, + { 0xf0fF0, 0x00430, 0xFFFF, "i486 DX/2" }, + { 0xf0fF0, 0x00440, 0xFFFF, "i486 SL" }, + { 0xf0fF0, 0x00450, 0xFFFF, "i486 SX/2" }, + { 0xf0fF0, 0x00470, 0xFFFF, "i486 DX/2-WB" }, + { 0xf0fF0, 0x00480, 0xFFFF, "i486 DX/4" }, + { 0xf0fF0, 0x00490, 0xFFFF, "i486 DX/4-WB" }, + { 0xf0fF0, 0x00500, 0xFFFF, "Pentium A-Step" }, + { 0xf0fF0, 0x00510, 0xFFFF, "Pentium P5" }, + { 0xf0fF0, 0x00520, 0xFFFF, "Pentium P54C" }, + { 0xf0fF0, 0x00530, 0xFFFF, "Pentium P24T Overdrive" }, + { 0xf0fF0, 0x00540, 0xFFFF, "Pentium P55C MMX" }, + { 0xf0fF0, 0x00570, 0xFFFF, "Pentium Mobile" }, + { 0xf0fF0, 0x00580, 0xFFFF, "Pentium MMX Mobile (Tillamook)" }, + { 0xf0fF0, 0x00600, 0xFFFF, "Pentium-Pro A-Step" }, + { 0xf0fF0, 0x00610, 0xFFFF, "Pentium-Pro" }, + { 0xf0fF0, 0x00630, 512, "Pentium II (Klamath)" }, + { 0xf0fF0, 0x00640, 512, "Pentium II (Deschutes)" }, + { 0xf0fF0, 0x00650, 1024, "Pentium II (Drake)" }, + { 0xf0fF0, 0x00650, 512, "Pentium II (Deschutes)" }, + { 0xf0fF0, 0x00650, 256, "Pentium II Mobile (Dixon)" }, + { 0xf0fF0, 0x00650, 0, "Celeron (Covington)" }, + { 0xf0fF0, 0x00660, 128, "Celeron (Mendocino)" }, + { 0xf0fF0, 0x00670, 1024, "Pentium III (Tanner)" }, + { 0xf0fF0, 0x00670, 512, "Pentium III (Katmai)" }, + { 0xf0fF0, 0x00680, 256, "Pentium III (Coppermine)" }, + { 0xf0fF0, 0x00680, 128, "Celeron (Coppermine)" }, + { 0xf0fF0, 0x00690, 1024, "Pentium-M (Banias)" }, + { 0xf0fF0, 0x00690, 512, "Celeron-M (Banias)" }, + { 0xf0fF0, 0x006a0, 1024, "Pentium III (Cascades)" }, + { 0xf0fF0, 0x006b0, 512, "Pentium III-S" }, + { 0xf0fF0, 0x006b0, 256, "Pentium III (Tualatin)" }, + { 0xf0fF0, 0x006d0, 2048, "Pentium-M (Dothan)" }, + { 0xf0fF0, 0x006d0, 1024, "Celeron-M (Dothan)" }, + { 0xf0fF0, 0x006e0, 2048, "Core (Yonah)" }, + { 0xf0fF0, 0x006f0, 2048, "Core 2 (Merom)" }, + { 0xf0f00, 0x00700, 0xFFFF, "Itanium (Merced)" }, + { 0xf0fF0, 0x00f00, 256, "Pentium 4 (Willamette/Foster)" }, + { 0xf0fF0, 0x00f10, 256, "Pentium 4 (Willamette/Foster)" }, + { 0xf0fF0, 0x00f10, 128, "Celeron (Willamette)" }, + { 0xf0fF0, 0x00f20, 512, "Pentium 4 (Northwood/Prestonia)" }, + { 0xf0fF0, 0x00f20, 128, "Celeron (Northwood)" }, + { 0xf0fF0, 0x00f30, 1024, "Pentium 4E (Prescott/Nocona)" }, + { 0xf0fF0, 0x00f30, 256, "Celeron D (Prescott)" }, + { 0xf0fF4, 0x00f40, 1024, "Pentium 4E (Prescott/Nocona)" }, + { 0xf0fF4, 0x00f44, 1024, "Pentium D (Smithfield)" }, + { 0xf0fF0, 0x00f40, 256, "Celeron D (Prescott)" }, + { 0xf0fF0, 0x00f60, 2048, "Pentium D (Cedarmill/Presler)" }, + { 0xf0fF0, 0x00f60, 512, "Celeron D (Cedarmill)" }, + { 0xf0ff0, 0x10600, 0, "Celeron, 65nm" }, + { 0xf0ff0, 0x10670, 2048, "Core2 / Xeon (Wolfdale), 45nm" }, + { 0xf0ff0, 0x106a0, 0xffff, "Core i7 / Xeon, 45nm" }, + { 0xf0ff0, 0x106b0, 0xffff, "Xeon MP, 45nm" }, + { 0xf0ff0, 0x106c0, 0xffff, "Atom" }, + { 0x0, 0x0, 0xFFFF, "" } +}; + +Cpu::Vendor_table const Cpu::amd_table[] FIASCO_INITDATA_CPU = +{ + { 0xFF0, 0x430, 0xFFFF, "Am486DX2-WT" }, + { 0xFF0, 0x470, 0xFFFF, "Am486DX2-WB" }, + { 0xFF0, 0x480, 0xFFFF, "Am486DX4-WT / Am5x86-WT" }, + { 0xFF0, 0x490, 0xFFFF, "Am486DX4-WB / Am5x86-WB" }, + { 0xFF0, 0x4a0, 0xFFFF, "SC400" }, + { 0xFF0, 0x4e0, 0xFFFF, "Am5x86-WT" }, + { 0xFF0, 0x4f0, 0xFFFF, "Am5x86-WB" }, + { 0xFF0, 0x500, 0xFFFF, "K5 (SSA/5) PR75/90/100" }, + { 0xFF0, 0x510, 0xFFFF, "K5 (Godot) PR120/133" }, + { 0xFF0, 0x520, 0xFFFF, "K5 (Godot) PR150/166" }, + { 0xFF0, 0x530, 0xFFFF, "K5 (Godot) PR200" }, + { 0xFF0, 0x560, 0xFFFF, "K6 (Little Foot)" }, + { 0xFF0, 0x570, 0xFFFF, "K6 (Little Foot)" }, + { 0xFF0, 0x580, 0xFFFF, "K6-II (Chomper)" }, + { 0xFF0, 0x590, 256, "K6-III (Sharptooth)" }, + { 0xFF0, 0x5c0, 128, "K6-2+" }, + { 0xFF0, 0x5d0, 256, "K6-3+" }, + { 0xFF0, 0x600, 0xFFFF, "Athlon K7 (Argon)" }, + { 0xFF0, 0x610, 0xFFFF, "Athlon K7 (Pluto)" }, + { 0xFF0, 0x620, 0xFFFF, "Athlon K75 (Orion)" }, + { 0xFF0, 0x630, 64, "Duron (Spitfire)" }, + { 0xFF0, 0x640, 256, "Athlon (Thunderbird)" }, + { 0xFF0, 0x660, 256, "Athlon (Palomino)" }, + { 0xFF0, 0x660, 64, "Duron (Morgan)" }, + { 0xFF0, 0x670, 64, "Duron (Morgan)" }, + { 0xFF0, 0x680, 256, "Athlon (Thoroughbred)" }, + { 0xFF0, 0x680, 64, "Duron (Applebred)" }, + { 0xFF0, 0x6A0, 512, "Athlon (Barton)" }, + { 0xFF0, 0x6A0, 256, "Athlon (Thorton)" }, + { 0xfff0ff0, 0x000f00, 0, "Athlon 64 (Clawhammer)" }, + { 0xfff0ff0, 0x000f10, 0, "Opteron (Sledgehammer)" }, + { 0xfff0ff0, 0x000f40, 0, "Athlon 64 (Clawhammer)" }, + { 0xfff0ff0, 0x000f50, 0, "Opteron (Sledgehammer)" }, + { 0xfff0ff0, 0x000fc0, 512, "Athlon64 (Newcastle)" }, + { 0xfff0ff0, 0x000fc0, 256, "Sempron (Paris)" }, + { 0xfff0ff0, 0x010f50, 0, "Opteron (Sledgehammer)" }, + { 0xfff0ff0, 0x010fc0, 0, "Sempron (Oakville)" }, + { 0xfff0ff0, 0x010ff0, 0, "Athlon 64 (Winchester)" }, + { 0xfff0ff0, 0x020f10, 0, "Opteron (Jackhammer)" }, + { 0xfff0ff0, 0x020f30, 0, "Athlon 64 X2 (Toledo)" }, + { 0xfff0ff0, 0x020f40, 0, "Turion 64 (Lancaster)" }, + { 0xfff0ff0, 0x020f50, 0, "Opteron (Venus)" }, + { 0xfff0ff0, 0x020f70, 0, "Athlon 64 (San Diego)" }, + { 0xfff0ff0, 0x020fb0, 0, "Athlon 64 X2 (Manchester)" }, + { 0xfff0ff0, 0x020fc0, 0, "Sempron (Palermo)" }, + { 0xfff0ff0, 0x020ff0, 0, "Athlon 64 (Venice)" }, + { 0xfff0ff0, 0x040f10, 0, "Opteron (Santa Rosa)" }, + { 0xfff0ff0, 0x040f30, 0, "Athlon 64 X2 (Windsor)" }, + { 0xfff0ff0, 0x040f80, 0, "Turion 64 X2 (Taylor)" }, + { 0xfff0ff0, 0x060fb0, 0, "Athlon 64 X2 (Brisbane)" }, + { 0x0, 0x0, 0, "" } +}; + +Cpu::Vendor_table const Cpu::cyrix_table[] FIASCO_INITDATA_CPU = +{ + { 0xFF0, 0x440, 0xFFFF, "Gx86 (Media GX)" }, + { 0xFF0, 0x490, 0xFFFF, "5x86" }, + { 0xFF0, 0x520, 0xFFFF, "6x86 (M1)" }, + { 0xFF0, 0x540, 0xFFFF, "GXm" }, + { 0xFF0, 0x600, 0xFFFF, "6x86MX (M2)" }, + { 0x0, 0x0, 0xFFFF, "" } +}; + +Cpu::Vendor_table const Cpu::via_table[] FIASCO_INITDATA_CPU = +{ + { 0xFF0, 0x540, 0xFFFF, "IDT Winchip C6" }, + { 0xFF0, 0x580, 0xFFFF, "IDT Winchip 2A/B" }, + { 0xFF0, 0x590, 0xFFFF, "IDT Winchip 3" }, + { 0xFF0, 0x650, 0xFFFF, "Via Jalapeno (Joshua)" }, + { 0xFF0, 0x660, 0xFFFF, "Via C5A (Samuel)" }, + { 0xFF8, 0x670, 0xFFFF, "Via C5B (Samuel 2)" }, + { 0xFF8, 0x678, 0xFFFF, "Via C5C (Ezra)" }, + { 0xFF0, 0x680, 0xFFFF, "Via C5N (Ezra-T)" }, + { 0xFF0, 0x690, 0xFFFF, "Via C5P (Nehemiah)" }, + { 0xFF0, 0x6a0, 0xFFFF, "Via C5J (Esther)" }, + { 0x0, 0x0, 0xFFFF, "" } +}; + +Cpu::Vendor_table const Cpu::umc_table[] FIASCO_INITDATA_CPU = +{ + { 0xFF0, 0x410, 0xFFFF, "U5D" }, + { 0xFF0, 0x420, 0xFFFF, "U5S" }, + { 0x0, 0x0, 0xFFFF, "" } +}; + +Cpu::Vendor_table const Cpu::nexgen_table[] FIASCO_INITDATA_CPU = +{ + { 0xFF0, 0x500, 0xFFFF, "Nx586" }, + { 0x0, 0x0, 0xFFFF, "" } +}; + +Cpu::Vendor_table const Cpu::rise_table[] FIASCO_INITDATA_CPU = +{ + { 0xFF0, 0x500, 0xFFFF, "mP6 (iDragon)" }, + { 0xFF0, 0x520, 0xFFFF, "mP6 (iDragon)" }, + { 0xFF0, 0x580, 0xFFFF, "mP6 (iDragon II)" }, + { 0xFF0, 0x590, 0xFFFF, "mP6 (iDragon II)" }, + { 0x0, 0x0, 0xFFFF, "" } +}; + +Cpu::Vendor_table const Cpu::transmeta_table[] FIASCO_INITDATA_CPU = +{ + { 0xFFF, 0x542, 0xFFFF, "TM3x00 (Crusoe)" }, + { 0xFFF, 0x543, 0xFFFF, "TM5x00 (Crusoe)" }, + { 0xFF0, 0xf20, 0xFFFF, "TM8x00 (Efficeon)" }, + { 0x0, 0x0, 0xFFFF, "" } +}; + +Cpu::Vendor_table const Cpu::sis_table[] FIASCO_INITDATA_CPU = +{ + { 0xFF0, 0x500, 0xFFFF, "55x" }, + { 0x0, 0x0, 0xFFFF, "" } +}; + +Cpu::Vendor_table const Cpu::nsc_table[] FIASCO_INITDATA_CPU = +{ + { 0xFF0, 0x540, 0xFFFF, "Geode GX1" }, + { 0xFF0, 0x550, 0xFFFF, "Geode GX2" }, + { 0xFF0, 0x680, 0xFFFF, "Geode NX" }, + { 0x0, 0x0, 0xFFFF, "" } +}; + +Cpu::Cache_table const Cpu::intel_cache_table[] FIASCO_INITDATA_CPU = +{ + { 0x01, Tlb_inst_4k, 32, 4, 0 }, + { 0x02, Tlb_inst_4M, 2, 4, 0 }, + { 0x03, Tlb_data_4k, 64, 4, 0 }, + { 0x04, Tlb_data_4M, 8, 4, 0 }, + { 0x05, Tlb_data_4M, 32, 4, 0 }, + { 0x06, Cache_l1_inst, 8, 4, 32 }, + { 0x08, Cache_l1_inst, 16, 4, 32 }, + { 0x09, Cache_l1_inst, 32, 4, 64 }, + { 0x0A, Cache_l1_data, 8, 2, 32 }, + { 0x0B, Tlb_inst_4M, 4, 4, 0 }, + { 0x0C, Cache_l1_data, 16, 4, 32 }, + { 0x0D, Cache_l1_data, 16, 4, 64 }, + { 0x0E, Cache_l1_data, 24, 6, 64 }, + { 0x21, Cache_l2, 256, 8, 64 }, + { 0x22, Cache_l3, 512, 4, 64 }, /* sectored */ + { 0x23, Cache_l3, 1024, 8, 64 }, /* sectored */ + { 0x25, Cache_l3, 2048, 8, 64 }, /* sectored */ + { 0x29, Cache_l3, 4096, 8, 64 }, /* sectored */ + { 0x2C, Cache_l1_data, 32, 8, 64 }, + { 0x30, Cache_l1_inst, 32, 8, 64 }, + { 0x39, Cache_l2, 128, 4, 64 }, /* sectored */ + { 0x3B, Cache_l2, 128, 2, 64 }, /* sectored */ + { 0x3C, Cache_l2, 256, 4, 64 }, /* sectored */ + { 0x41, Cache_l2, 128, 4, 32 }, + { 0x42, Cache_l2, 256, 4, 32 }, + { 0x43, Cache_l2, 512, 4, 32 }, + { 0x44, Cache_l2, 1024, 4, 32 }, + { 0x45, Cache_l2, 2048, 4, 32 }, + { 0x46, Cache_l3, 4096, 4, 64 }, + { 0x47, Cache_l3, 8192, 8, 64 }, + { 0x48, Cache_l2, 3072, 12, 64 }, + { 0x49, Cache_l2, 4096, 16, 64 }, + { 0x4A, Cache_l3, 6144, 12, 64 }, + { 0x4B, Cache_l3, 8192, 16, 64 }, + { 0x4C, Cache_l3, 12288, 12, 64 }, + { 0x4D, Cache_l3, 16384, 16, 64 }, + { 0x4E, Cache_l3, 6144, 24, 64 }, + { 0x4F, Tlb_inst_4k, 32, 0, 0 }, + { 0x50, Tlb_inst_4k_4M, 64, 0, 0 }, + { 0x51, Tlb_inst_4k_4M, 128, 0, 0 }, + { 0x52, Tlb_inst_4k_4M, 256, 0, 0 }, + { 0x56, Tlb_data_4M, 16, 4, 0 }, + { 0x57, Tlb_data_4k, 16, 4, 0 }, + { 0x59, Tlb_data_4k, 16, 0, 0 }, + { 0x5A, Tlb_data_2M_4M, 32, 4, 0 }, + { 0x5B, Tlb_data_4k_4M, 64, 0, 0 }, + { 0x5C, Tlb_data_4k_4M, 128, 0, 0 }, + { 0x5D, Tlb_data_4k_4M, 256, 0, 0 }, + { 0x60, Cache_l1_data, 16, 8, 64 }, + { 0x66, Cache_l1_data, 8, 4, 64 }, /* sectored */ + { 0x67, Cache_l1_data, 16, 4, 64 }, /* sectored */ + { 0x68, Cache_l1_data, 32, 4, 64 }, /* sectored */ + { 0x70, Cache_l1_trace, 12, 8, 0 }, + { 0x71, Cache_l1_trace, 16, 8, 0 }, + { 0x72, Cache_l1_trace, 32, 8, 0 }, + { 0x77, Cache_l1_inst, 16, 4, 64 }, + { 0x78, Cache_l2, 1024, 4, 64 }, + { 0x79, Cache_l2, 128, 8, 64 }, /* sectored */ + { 0x7A, Cache_l2, 256, 8, 64 }, /* sectored */ + { 0x7B, Cache_l2, 512, 8, 64 }, /* sectored */ + { 0x7C, Cache_l2, 1024, 8, 64 }, /* sectored */ + { 0x7D, Cache_l2, 2048, 8, 64 }, + { 0x7E, Cache_l2, 256, 8, 128 }, + { 0x7F, Cache_l2, 512, 2, 64 }, + { 0x80, Cache_l2, 512, 16, 64 }, + { 0x82, Cache_l2, 256, 8, 32 }, + { 0x83, Cache_l2, 512, 8, 32 }, + { 0x84, Cache_l2, 1024, 8, 32 }, + { 0x85, Cache_l2, 2048, 8, 32 }, + { 0x86, Cache_l2, 512, 4, 64 }, + { 0x87, Cache_l2, 1024, 8, 64 }, + { 0x8D, Cache_l3, 3072, 12, 128 }, + { 0xB0, Tlb_inst_4k, 128, 4, 0 }, + { 0xB3, Tlb_data_4k, 128, 4, 0 }, + { 0xB4, Tlb_data_4k, 256, 4, 0 }, + { 0xBA, Tlb_data_4k, 64, 4, 0 }, + { 0xC0, Tlb_data_4k_4M, 8, 4, 0 }, + { 0xCA, Tlb_data_4k_4M, 512, 4, 0 }, + { 0xD0, Cache_l3, 512, 4, 64 }, + { 0xD1, Cache_l3, 1024, 4, 64 }, + { 0xD2, Cache_l3, 2048, 4, 64 }, + { 0xD6, Cache_l3, 1024, 8, 64 }, + { 0xD7, Cache_l3, 2048, 8, 64 }, + { 0xD8, Cache_l3, 4096, 8, 64 }, + { 0xDC, Cache_l3, 1536, 12, 64 }, + { 0xDD, Cache_l3, 3072, 12, 64 }, + { 0xDE, Cache_l3, 6144, 12, 64 }, + { 0xE2, Cache_l3, 2048, 16, 64 }, + { 0xE3, Cache_l3, 4096, 16, 64 }, + { 0xE4, Cache_l3, 8192, 16, 64 }, + { 0xEA, Cache_l3, 12288, 24, 64 }, + { 0xEB, Cache_l3, 18432, 24, 64 }, + { 0xEC, Cache_l3, 24576, 24, 64 }, + { 0x0, Cache_unknown, 0, 0, 0 } +}; + +char const * const Cpu::vendor_ident[] = +{ + 0, + "GenuineIntel", + "AuthenticAMD", + "CyrixInstead", + "CentaurHauls", + "UMC UMC UMC ", + "NexGenDriven", + "RiseRiseRise", + "GenuineTMx86", + "SiS SiS SiS ", + "Geode by NSC" +}; + +Cpu::Vendor_table const * const Cpu::vendor_table[] = +{ + 0, + intel_table, + amd_table, + cyrix_table, + via_table, + umc_table, + nexgen_table, + rise_table, + transmeta_table, + sis_table, + nsc_table +}; + +char const * const Cpu::exception_strings[] = +{ + /* 0 */ "Divide Error", + /* 1 */ "Debug", + /* 2 */ "NMI Interrupt", + /* 3 */ "Breakpoint", + /* 4 */ "Overflow", + /* 5 */ "BOUND Range Exceeded", + /* 6 */ "Invalid Opcode", + /* 7 */ "Device Not Available", + /* 8 */ "Double Fault", + /* 9 */ "CoProcessor Segment Overrrun", + /* 10 */ "Invalid TSS", + /* 11 */ "Segment Not Present", + /* 12 */ "Stack Segment Fault", + /* 13 */ "General Protection", + /* 14 */ "Page Fault", + /* 15 */ "Reserved", + /* 16 */ "Floating-Point Error", + /* 17 */ "Alignment Check", + /* 18 */ "Machine Check", + /* 19 */ "SIMD Floating-Point Exception", + /* 20 */ "Reserved", + /* 21 */ "Reserved", + /* 22 */ "Reserved", + /* 23 */ "Reserved", + /* 24 */ "Reserved", + /* 25 */ "Reserved", + /* 26 */ "Reserved", + /* 27 */ "Reserved", + /* 28 */ "Reserved", + /* 29 */ "Reserved", + /* 30 */ "Reserved", + /* 31 */ "Reserved" +}; + +PUBLIC explicit FIASCO_INIT_CPU +Cpu::Cpu(unsigned cpu) +{ + set_id(cpu); + if (cpu == 0) + { + _boot_cpu = this; + set_online(1); + } + + init(); +} + + +PUBLIC static +void +Cpu::init_global_features() +{} + +PUBLIC static +char const * +Cpu::exception_string(Mword trapno) +{ + if (trapno > 32) + return "Maskable Interrupt"; + return exception_strings[trapno]; +} + +PUBLIC static inline FIASCO_INIT_CPU +void +Cpu::cpuid(Unsigned32 const mode, + Unsigned32 *const eax, Unsigned32 *const ebx, + Unsigned32 *const ecx, Unsigned32 *const edx) +{ + asm volatile ("cpuid" : "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx) + : "a" (mode)); +} + +PUBLIC static inline FIASCO_INIT_CPU +void +Cpu::cpuid_0xd(Unsigned32 const ecx_val, + Unsigned32 *const eax, Unsigned32 *const ebx, + Unsigned32 *const ecx, Unsigned32 *const edx) +{ + asm volatile ("cpuid" : "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx) + : "a" (0xd), "c" (ecx_val)); +} + +PUBLIC +void +Cpu::update_features_info() +{ + cpuid(1, &_version, &_brand, &_ext_features, &_features); +} + +PRIVATE FIASCO_INIT_CPU +void +Cpu::cache_tlb_intel() +{ + Unsigned8 desc[16]; + unsigned i, count = 0; + Cache_table const *table; + + do + { + cpuid(2, (Unsigned32 *)(desc), + (Unsigned32 *)(desc + 4), + (Unsigned32 *)(desc + 8), + (Unsigned32 *)(desc + 12)); + + for (i = 1; i < 16; i++) + { + // Null descriptor or register bit31 set (reserved) + if (!desc[i] || (desc[i / 4 * 4 + 3] & (1 << 7))) + continue; + + for (table = intel_cache_table; table->desc; table++) + { + if (table->desc == desc[i]) + { + switch (table->level) + { + case Cache_l1_data: + _l1_data_cache_size = table->size; + _l1_data_cache_asso = table->asso; + _l1_data_cache_line_size = table->line_size; + break; + case Cache_l1_inst: + _l1_inst_cache_size = table->size; + _l1_inst_cache_asso = table->asso; + _l1_inst_cache_line_size = table->line_size; + break; + case Cache_l1_trace: + _l1_trace_cache_size = table->size; + _l1_trace_cache_asso = table->asso; + break; + case Cache_l2: + _l2_cache_size = table->size; + _l2_cache_asso = table->asso; + _l2_cache_line_size = table->line_size; + break; + case Cache_l3: + _l3_cache_size = table->size; + _l3_cache_asso = table->asso; + _l3_cache_line_size = table->line_size; + break; + case Tlb_inst_4k: + _inst_tlb_4k_entries += table->size; + break; + case Tlb_data_4k: + _data_tlb_4k_entries += table->size; + break; + case Tlb_inst_4M: + _inst_tlb_4m_entries += table->size; + break; + case Tlb_data_4M: + _data_tlb_4m_entries += table->size; + break; + case Tlb_inst_4k_4M: + _inst_tlb_4k_4m_entries += table->size; + break; + case Tlb_data_4k_4M: + _data_tlb_4k_4m_entries += table->size; + break; + default: + break; + } + break; + } + } + } + } + while (++count < *desc); +} + +PRIVATE FIASCO_INIT_CPU +void +Cpu::cache_tlb_l1() +{ + Unsigned32 eax, ebx, ecx, edx; + cpuid(0x80000005, &eax, &ebx, &ecx, &edx); + + _l1_data_cache_size = (ecx >> 24) & 0xFF; + _l1_data_cache_asso = (ecx >> 16) & 0xFF; + _l1_data_cache_line_size = ecx & 0xFF; + + _l1_inst_cache_size = (edx >> 24) & 0xFF; + _l1_inst_cache_asso = (edx >> 16) & 0xFF; + _l1_inst_cache_line_size = edx & 0xFF; + + _data_tlb_4k_entries = (ebx >> 16) & 0xFF; + _inst_tlb_4k_entries = ebx & 0xFF; + _data_tlb_4m_entries = (eax >> 16) & 0xFF; + _inst_tlb_4m_entries = eax & 0xFF; +} + +PRIVATE FIASCO_INIT_CPU +void +Cpu::cache_tlb_l2_l3() +{ + Unsigned32 eax, ebx, ecx, edx; + cpuid(0x80000006, &eax, &ebx, &ecx, &edx); + + if (vendor() == Vendor_via) + { + _l2_cache_size = (ecx >> 24) & 0xFF; + _l2_cache_asso = (ecx >> 16) & 0xFF; + } + else + { + _l2_data_tlb_4m_entries = (eax >> 16) & 0xFFF; + _l2_inst_tlb_4m_entries = eax & 0xFFF; + _l2_data_tlb_4k_entries = (ebx >> 16) & 0xFFF; + _l2_inst_tlb_4k_entries = ebx & 0xFFF; + _l2_cache_size = (ecx >> 16) & 0xFFFF; + _l2_cache_asso = (ecx >> 12) & 0xF; + } + + _l2_cache_line_size = ecx & 0xFF; + + _l3_cache_size = (edx >> 18) << 9; + _l3_cache_asso = (edx >> 12) & 0xF; + _l3_cache_line_size = edx & 0xFF; +} + +PRIVATE FIASCO_INIT_CPU +void +Cpu::addr_size_info() +{ + Unsigned32 eax, ebx, ecx, edx; + cpuid(0x80000008, &eax, &ebx, &ecx, &edx); + + _phys_bits = eax & 0xff; + _virt_bits = (eax & 0xff00) >> 8; +} + +PUBLIC static +unsigned +Cpu::amd_cpuid_mnc() +{ + Unsigned32 eax, ebx, ecx, edx; + cpuid(0x80000008, &eax, &ebx, &ecx, &edx); + + unsigned apicidcoreidsize = (ecx >> 12) & 0xf; + if (apicidcoreidsize == 0) + return (ecx & 0xf) + 1; // NC + return 1 << apicidcoreidsize; +} + +PRIVATE FIASCO_INIT_CPU +void +Cpu::set_model_str() +{ + Vendor_table const *table; + + if (_model_str[0]) + return; + + for (table = vendor_table[vendor()]; table && table->vendor_mask; table++) + if ((_version & table->vendor_mask) == table->vendor_code && + (table->l2_cache == 0xFFFF || _l2_cache_size >= table->l2_cache)) + { + snprintf(_model_str, sizeof (_model_str), "%s", + table->vendor_string); + return; + } + + snprintf(_model_str, sizeof (_model_str), "Unknown CPU"); +} + +PUBLIC inline FIASCO_INIT_CPU +void +Cpu::arch_perfmon_info(Unsigned32 *eax, Unsigned32 *ebx, Unsigned32 *ecx) const +{ + *eax = _arch_perfmon_info_eax; + *ebx = _arch_perfmon_info_ebx; + *ecx = _arch_perfmon_info_ecx; +} + +PUBLIC static +unsigned long +Cpu::get_features() +{ + Unsigned32 eflags = get_flags(); + // Check for Alignment Check Support + set_flags(eflags ^ EFLAGS_AC); + if (((get_flags() ^ eflags) & EFLAGS_AC) == 0) + return 0; + + // Check for CPUID Support + set_flags(eflags ^ EFLAGS_ID); + if (!((get_flags() ^ eflags) & EFLAGS_ID)) + return 0; + + Unsigned32 max; + char vendor_id[12]; + + cpuid(0, &max, (Unsigned32 *)(vendor_id), + (Unsigned32 *)(vendor_id + 8), + (Unsigned32 *)(vendor_id + 4)); + + if (!max) + return 0; + + Unsigned32 dummy, dummy1, dummy2, features; + cpuid (1, &dummy, &dummy1, &dummy2, &features); + + return features; +} + + +/** Identify the CPU features. + Attention: This function may be called more than once. The reason is + that enabling a Local APIC that was previously disabled by the BIOS + may change the processor features. Therefore, this function has to + be called again after the Local APIC was enabled. + */ +PUBLIC FIASCO_INIT_CPU +void +Cpu::identify() +{ + Unsigned32 eflags = get_flags(); + + _phys_bits = 32; + _virt_bits = 32; + + // Reset members in case we get called more than once + _inst_tlb_4k_entries = + _data_tlb_4k_entries = + _inst_tlb_4m_entries = + _data_tlb_4m_entries = + _inst_tlb_4k_4m_entries = + _data_tlb_4k_4m_entries = 0; + + // Check for Alignment Check Support + set_flags(eflags ^ EFLAGS_AC); + if (((get_flags() ^ eflags) & EFLAGS_AC) == 0) + panic("CPU too old"); + + // Check for CPUID Support + set_flags(eflags ^ EFLAGS_ID); + if ((get_flags() ^ eflags) & EFLAGS_ID) { + + Unsigned32 max, i; + char vendor_id[12]; + + cpuid(0, &max, (Unsigned32 *)(vendor_id), + (Unsigned32 *)(vendor_id + 8), + (Unsigned32 *)(vendor_id + 4)); + + for (i = sizeof (vendor_ident) / sizeof (*vendor_ident) - 1; i; i--) + if (!memcmp(vendor_id, vendor_ident[i], 12)) + break; + + _vendor = (Cpu::Vendor)i; + + switch (max) + { + default: + // All cases fall through! + case 10: + cpuid(10, &_arch_perfmon_info_eax, + &_arch_perfmon_info_ebx, + &_arch_perfmon_info_ecx, &i); + case 2: + if (_vendor == Vendor_intel) + cache_tlb_intel(); + case 1: + update_features_info(); + } + + if (max >= 5 && has_monitor_mwait()) + cpuid(5, &_monitor_mwait_eax, &_monitor_mwait_ebx, + &_monitor_mwait_ecx, &_monitor_mwait_edx); + + if (_vendor == Vendor_intel) + { + switch (family()) + { + case 5: + // Avoid Pentium Erratum 74 + if ((_features & FEAT_MMX) && + (model() != 4 || + (stepping() != 4 && (stepping() != 3 || type() != 1)))) + _local_features |= Lf_rdpmc; + break; + case 6: + // Avoid Pentium Pro Erratum 26 + if (model() >= 3 || stepping() > 9) + _local_features |= Lf_rdpmc; + break; + case 15: + _local_features |= Lf_rdpmc; + _local_features |= Lf_rdpmc32; + break; + } + } + else if (_vendor == Vendor_amd) + { + switch (family()) + { + case 6: + case 15: + _local_features |= Lf_rdpmc; + break; + } + } + + // Get maximum number for extended functions + cpuid(0x80000000, &max, &i, &i, &i); + + if (max > 0x80000000) + { + switch (max) + { + default: + // All cases fall through! + case 0x80000008: + if (_vendor == Vendor_amd || _vendor == Vendor_intel) + addr_size_info(); + case 0x80000007: + case 0x80000006: + if (_vendor == Vendor_amd || _vendor == Vendor_via) + cache_tlb_l2_l3(); + case 0x80000005: + if (_vendor == Vendor_amd || _vendor == Vendor_via) + cache_tlb_l1(); + case 0x80000004: + { + Unsigned32 *s = (Unsigned32 *)_model_str; + for (unsigned i = 0; i < 3; ++i) + cpuid(0x80000002 + i, &s[0 + 4*i], &s[1 + 4*i], + &s[2 + 4*i], &s[3 + 4*i]); + _model_str[48] = 0; + } + case 0x80000003: + case 0x80000002: + case 0x80000001: + if (_vendor == Vendor_intel || _vendor == Vendor_amd) + cpuid(0x80000001, &i, &i, &_ext_8000_0001_ecx, + &_ext_8000_0001_edx); + break; + } + } + + // see Intel Spec on SYSENTER: + // Some Pentium Pro pretend to have it, but actually lack it + if ((_version & 0xFFF) < 0x633) + _features &= ~FEAT_SEP; + + } else + _version = 0x400; + + set_model_str(); + + set_flags(eflags); +} + +PUBLIC inline NEEDS["processor.h"] +void +Cpu::busy_wait_ns(Unsigned64 ns) +{ + Unsigned64 stop = rdtsc () + ns_to_tsc(ns); + + while (rdtsc() < stop) + Proc::pause(); +} + + +PUBLIC +void +Cpu::show_cache_tlb_info(const char *indent) const +{ + char s[16]; + + *s = '\0'; + if (_l2_inst_tlb_4k_entries) + snprintf(s, sizeof(s), "/%u", _l2_inst_tlb_4k_entries); + if (_inst_tlb_4k_entries) + printf("%s%4u%s Entry I TLB (4K pages)", indent, _inst_tlb_4k_entries, s); + *s = '\0'; + if (_l2_inst_tlb_4m_entries) + snprintf(s, sizeof(s), "/%u", _l2_inst_tlb_4k_entries); + if (_inst_tlb_4m_entries) + printf(" %4u%s Entry I TLB (4M pages)", _inst_tlb_4m_entries, s); + if (_inst_tlb_4k_4m_entries) + printf("%s%4u Entry I TLB (4K or 4M pages)", + indent, _inst_tlb_4k_4m_entries); + if (_inst_tlb_4k_entries || _inst_tlb_4m_entries || _inst_tlb_4k_4m_entries) + putchar('\n'); + *s = '\0'; + if (_l2_data_tlb_4k_entries) + snprintf(s, sizeof(s), "/%u", _l2_data_tlb_4k_entries); + if (_data_tlb_4k_entries) + printf("%s%4u%s Entry D TLB (4K pages)", indent, _data_tlb_4k_entries, s); + *s = '\0'; + if (_l2_data_tlb_4m_entries) + snprintf(s, sizeof(s), "/%u", _l2_data_tlb_4m_entries); + if (_data_tlb_4m_entries) + printf(" %4u%s Entry D TLB (4M pages)", _data_tlb_4m_entries, s); + if (_data_tlb_4k_4m_entries) + printf("%s%4u Entry D TLB (4k or 4M pages)", + indent, _data_tlb_4k_4m_entries); + if (_data_tlb_4k_entries || _data_tlb_4m_entries || _data_tlb_4k_4m_entries) + putchar('\n'); + + if (_l1_trace_cache_size) + printf("%s%3uK %c-ops T Cache (%u-way associative)\n", + indent, _l1_trace_cache_size, Config::char_micro, + _l1_trace_cache_asso); + + else if (_l1_inst_cache_size) + printf("%s%4u KB L1 I Cache (%u-way associative, %u bytes per line)\n", + indent, _l1_inst_cache_size, _l1_inst_cache_asso, + _l1_inst_cache_line_size); + + if (_l1_data_cache_size) + printf("%s%4u KB L1 D Cache (%u-way associative, %u bytes per line)\n" + "%s%4u KB L2 U Cache (%u-way associative, %u bytes per line)\n", + indent, _l1_data_cache_size, _l1_data_cache_asso, + _l1_data_cache_line_size, + indent, _l2_cache_size, _l2_cache_asso, _l2_cache_line_size); + + if (_l3_cache_size) + printf("%s%4u KB L3 U Cache (%u-way associative, %u bytes per line)\n", + indent, _l3_cache_size, _l3_cache_asso, _l3_cache_line_size); +} + +IMPLEMENT +void +Cpu::disable(unsigned cpu, char const *reason) +{ + printf("CPU%u: is disabled: %s\n", cpu, reason); +} + +// Function used for calculating apic scaler +PUBLIC static inline +Unsigned32 +Cpu::muldiv(Unsigned32 val, Unsigned32 mul, Unsigned32 div) +{ + Unsigned32 dummy; + + asm volatile ("mull %3 ; divl %4\n\t" + :"=a" (val), "=d" (dummy) + : "0" (val), "d" (mul), "c" (div)); + return val; +} + + +PUBLIC static inline +Unsigned32 +Cpu::get_cs() +{ + Unsigned32 val; + asm volatile ("mov %%cs, %0" : "=rm" (val)); + return val; +} + +PUBLIC static inline +Unsigned32 +Cpu::get_ds() +{ + Unsigned32 val; + asm volatile ("mov %%ds, %0" : "=rm" (val)); + return val; +} + +PUBLIC static inline +Unsigned32 +Cpu::get_es() +{ + Unsigned32 val; + asm volatile ("mov %%es, %0" : "=rm" (val)); + return val; +} + +PUBLIC static inline +Unsigned32 +Cpu::get_ss() +{ + Unsigned32 val; + asm volatile ("mov %%ss, %0" : "=rm" (val)); + return val; +} + +PUBLIC static inline +void +Cpu::set_ds(Unsigned32 val) +{ asm volatile ("mov %0, %%ds" : : "rm" (val)); } + +PUBLIC static inline +void +Cpu::set_es(Unsigned32 val) +{ asm volatile ("mov %0, %%es" : : "rm" (val)); } + +//---------------------------------------------------------------------------- +IMPLEMENTATION[ia32, amd64]: + +#include "boot_info.h" +#include "config.h" +#include "div32.h" +#include "gdt.h" +#include "globals.h" +#include "initcalls.h" +#include "io.h" +#include "pit.h" +#include "processor.h" +#include "regdefs.h" +#include "tss.h" + + +PUBLIC static inline +void +Cpu::set_cr0(unsigned long val) +{ asm volatile ("mov %0, %%cr0" : : "r" (val)); } + +PUBLIC static inline +void +Cpu::set_pdbr(unsigned long addr) +{ asm volatile ("mov %0, %%cr3" : : "r" (addr)); } + +PUBLIC static inline +void +Cpu::set_cr4(unsigned long val) +{ asm volatile ("mov %0, %%cr4" : : "r" (val)); } + +PUBLIC static inline +void +Cpu::set_ldt(Unsigned16 val) +{ asm volatile ("lldt %0" : : "rm" (val)); } + + +PUBLIC static inline +void +Cpu::set_ss(Unsigned32 val) +{ asm volatile ("mov %0, %%ss" : : "r" (val)); } + +PUBLIC static inline +void +Cpu::set_tr(Unsigned16 val) +{ asm volatile ("ltr %0" : : "rm" (val)); } + +PUBLIC static inline +Mword +Cpu::get_cr0() +{ + Mword val; + asm volatile ("mov %%cr0, %0" : "=r" (val)); + return val; +} + +PUBLIC static inline +Address +Cpu::get_pdbr() +{ Address addr; asm volatile ("mov %%cr3, %0" : "=r" (addr)); return addr; } + +PUBLIC static inline +Mword +Cpu::get_cr4() +{ Mword val; asm volatile ("mov %%cr4, %0" : "=r" (val)); return val; } + +PUBLIC static inline +Unsigned16 +Cpu::get_ldt() +{ Unsigned16 val; asm volatile ("sldt %0" : "=rm" (val)); return val; } + +PUBLIC static inline +Unsigned16 +Cpu::get_tr() +{ Unsigned16 val; asm volatile ("str %0" : "=rm" (val)); return val; } + +IMPLEMENT inline +int +Cpu::can_wrmsr() const +{ return features() & FEAT_MSR; } + +PUBLIC static inline +Unsigned64 +Cpu::rdmsr(Unsigned32 reg) +{ + Unsigned32 l,h; + + asm volatile ("rdmsr" : "=a" (l), "=d" (h) : "c" (reg)); + return ((Unsigned64)h << 32) + (Unsigned64)l; +} + +PUBLIC static inline +Unsigned64 +Cpu::rdpmc(Unsigned32 idx, Unsigned32) +{ + Unsigned32 l,h; + + asm volatile ("rdpmc" : "=a" (l), "=d" (h) : "c" (idx)); + return ((Unsigned64)h << 32) + (Unsigned64)l; +} + +PUBLIC static inline +void +Cpu::wrmsr(Unsigned32 low, Unsigned32 high, Unsigned32 reg) +{ asm volatile ("wrmsr" : : "a" (low), "d" (high), "c" (reg)); } + +PUBLIC static inline +void +Cpu::wrmsr(Unsigned64 msr, Unsigned32 reg) +{ asm volatile ("wrmsr" : : "a" ((Unsigned32)msr), "d" ((Unsigned32)(msr >> 32)), "c" (reg)); } + +PUBLIC static inline +void +Cpu::enable_rdpmc() +{ set_cr4(get_cr4() | CR4_PCE); } + + +IMPLEMENT FIASCO_INIT_CPU +void +Cpu::init_lbr_type() +{ + _lbr = Lbr_unsupported; + + if (can_wrmsr()) + { + // Intel + if (vendor() == Vendor_intel) + { + if (family() == 15) + _lbr = model() < 3 ? Lbr_pentium_4 : Lbr_pentium_4_ext; // P4 + else if (family() >= 6) + _lbr = Lbr_pentium_6; // PPro, PIII + } + else if (vendor() == Vendor_amd) + { + if ((family() == 6) || (family() == 15)) + _lbr = Lbr_pentium_6; // K7/K8 + } + } +} + + +IMPLEMENT FIASCO_INIT_CPU +void +Cpu::init_bts_type() +{ + _bts = Bts_unsupported; + + if (can_wrmsr() && vendor() == Vendor_intel) + { + if (family() == 15 && (rdmsr(0x1A0) & (1<<11)) == 0) + _bts = Bts_pentium_4; + if (family() == 6 && (model() == 9 || (model() >= 13 && + model() <= 15))) + _bts = Bts_pentium_m; + if (!(features() & FEAT_DS)) + _bts = Bts_unsupported; + } +} + + +PUBLIC inline +void +Cpu::lbr_enable(bool on) +{ + if (lbr_type() != Lbr_unsupported) + { + if (on) + { + lbr_active = true; + debugctl_set |= 1; + debugctl_busy = true; + } + else + { + lbr_active = false; + debugctl_set &= ~1; + debugctl_busy = lbr_active || bts_active; + wrmsr(debugctl_reset, MSR_DEBUGCTLA); + } + } +} + + +PUBLIC inline +void +Cpu::btf_enable(bool on) +{ + if (lbr_type() != Lbr_unsupported) + { + if (on) + { + btf_active = true; + debugctl_set |= 2; + debugctl_reset |= 2; /* don't disable bit in kernel */ + wrmsr(2, MSR_DEBUGCTLA); /* activate _now_ */ + } + else + { + btf_active = false; + debugctl_set &= ~2; + debugctl_busy = lbr_active || bts_active; + wrmsr(debugctl_reset, MSR_DEBUGCTLA); + } + } +} + + +PUBLIC +void +Cpu::bts_enable(bool on) +{ + if (bts_type() != Bts_unsupported) + { + if (on) + { + switch (bts_type()) + { + case Bts_pentium_4: bts_active = true; debugctl_set |= 0x0c; break; + case Bts_pentium_m: bts_active = true; debugctl_set |= 0xc0; break; + default:; + } + debugctl_busy = lbr_active || bts_active; + } + else + { + bts_active = false; + switch (bts_type()) + { + case Bts_pentium_4: debugctl_set &= ~0x0c; break; + case Bts_pentium_m: debugctl_set &= ~0xc0; break; + default:; + } + debugctl_busy = lbr_active || bts_active; + wrmsr(debugctl_reset, MSR_DEBUGCTLA); + } + } +} + +PUBLIC inline +void +Cpu::debugctl_enable() +{ + if (debugctl_busy) + wrmsr(debugctl_set, MSR_DEBUGCTLA); +} + +PUBLIC inline +void +Cpu::debugctl_disable() +{ + if (debugctl_busy) + wrmsr(debugctl_reset, MSR_DEBUGCTLA); +} + +/* + * AMD OS-Visible Workaround Information + * print a warning if a CPU is affected by any known erratum + */ +PUBLIC +void +Cpu::print_errata() +{ + if (vendor() == Vendor_amd && has_amd_osvw() && can_wrmsr()) + { + Unsigned16 osvw_id_length, i; + bool affected = false; + osvw_id_length = rdmsr(0xc0010140) & 0xff; + + for (i = 1; ((i - 1) * 64) < osvw_id_length; i++) + { + Unsigned64 osvw_msr = rdmsr(0xc0010140 + i); + if (osvw_msr != 0) + { + printf("\033[31mOSVW_MSR%d = 0x%016llx\033[m\n", + i, rdmsr(0xc0010140 + i)); + affected = true; + } + } + if (affected) + printf("\033[31m#Errata known %d, affected by at least one\033[m\n", + osvw_id_length); + } +} + +IMPLEMENT FIASCO_INIT_CPU +void +Cpu::init() +{ + identify(); + + init_lbr_type(); + init_bts_type(); + + calibrate_tsc(); + + if (scaler_tsc_to_ns) + _frequency = ns_to_tsc(1000000000UL); + + Unsigned32 cr4 = get_cr4(); + + if (features() & FEAT_FXSR) + cr4 |= CR4_OSFXSR; + + if (features() & FEAT_SSE) + cr4 |= CR4_OSXMMEXCPT; + + set_cr4 (cr4); + + // reset time stamp counter (better for debugging) + if ((features() & FEAT_TSC) && can_wrmsr()) + wrmsr(0, 0, MSR_TSC); + + if ((features() & FEAT_PAT) && can_wrmsr()) + wrmsr(0x00010406, 0x00070406, MSR_PAT); + + print_errata(); +} + +PUBLIC +void +Cpu::print() const +{ + printf ("CPU[%u:%u]: %s (%X:%X:%X:%X)[%08x] Model: %s at %llu MHz\n\n", + id(), phys_id() >> 24, + vendor_str(), family(), model(), stepping(), brand(), _version, model_str(), + div32(frequency(), 1000000)); +} + +PUBLIC +void +Cpu::set_sysenter(void (*func)(void)) +{ + // Check for Sysenter/Sysexit Feature + if (sysenter()) + wrmsr ((Mword) func, 0, MSR_SYSENTER_EIP); +} + + +PUBLIC +void +Cpu::set_fast_entry(void (*func)(void)) +{ + set_sysenter(func); +} + +extern "C" void entry_sys_fast_ipc (void); +extern "C" void entry_sys_fast_ipc_c (void); + +PUBLIC FIASCO_INIT_CPU +void +Cpu::init_sysenter() +{ + // Check for Sysenter/Sysexit Feature + if (sysenter()) + { + wrmsr (Gdt::gdt_code_kernel, 0, MSR_SYSENTER_CS); + wrmsr ((unsigned long)&kernel_sp(), 0, MSR_SYSENTER_ESP); + set_sysenter(entry_sys_fast_ipc_c); + } +} + + +// Return 2^32 / (tsc clocks per usec) +FIASCO_INIT_CPU +void +Cpu::calibrate_tsc () +{ + const unsigned calibrate_time = 50000 /*us*/ + 1; + + // sanity check + if (! (features() & FEAT_TSC)) + goto bad_ctc; + + Unsigned64 tsc_start, tsc_end; + Unsigned32 count, tsc_to_ns_div, dummy; + + { + // disable interrupts + Proc::Status o = Proc::cli_save(); + + Pit::setup_channel2_to_20hz(); + + tsc_start = rdtsc (); + count = 0; + do + { + count++; + } + while ((Io::in8 (0x61) & 0x20) == 0); + tsc_end = rdtsc (); + + // restore flags + Proc::sti_restore(o); + } + + // Error: ECTCNEVERSET + if (count <= 1) + goto bad_ctc; + + tsc_end -= tsc_start; + + // prevent overflow in division (CPU too fast) + if (tsc_end & 0xffffffff00000000LL) + goto bad_ctc; + + // prevent overflow in division (CPU too slow) + if ((tsc_end & 0xffffffffL) < calibrate_time) + goto bad_ctc; + + // tsc_to_ns_div = calibrate_time * 2^32 / tsc + asm ("divl %2" + :"=a" (tsc_to_ns_div), "=d" (dummy) + :"r" ((Unsigned32)tsc_end), "a" (0), "d" (calibrate_time)); + + // scaler_tsc_to_ns = (tsc_to_ns_div * 1000) / 32 + // not using muldiv(tsc_to_ns_div, 1000, 1 << 5), as div result > (1 << 32) + // will get trap0 if system frequency is too low + scaler_tsc_to_ns = tsc_to_ns_div * 31; + scaler_tsc_to_ns += tsc_to_ns_div / 4; + scaler_tsc_to_us = tsc_to_ns_div; + scaler_ns_to_tsc = muldiv(1 << 31, ((Unsigned32)tsc_end), + calibrate_time * 1000 >> 1 * 1 << 5); + + return; + +bad_ctc: + if (Config::Kip_timer_uses_rdtsc) + panic("Can't calibrate tsc"); +} + +IMPLEMENT inline +Unsigned64 +Cpu::time_us() const +{ + return tsc_to_us (rdtsc()); +} + + +PUBLIC inline +void +Cpu::enable_ldt(Address addr, int size) +{ + if (!size) + { + get_gdt()->clear_entry (Gdt::gdt_ldt / 8); + set_ldt(0); + } + else + { + get_gdt()->set_entry_byte(Gdt::gdt_ldt / 8, addr, size-1, 2/*=ldt*/, 0); + set_ldt(Gdt::gdt_ldt); + } +} + + +PUBLIC static inline +Unsigned32 +Cpu::get_fs() +{ Unsigned32 val; asm volatile ("mov %%fs, %0" : "=rm" (val)); return val; } + +PUBLIC static inline +Unsigned32 +Cpu::get_gs() +{ Unsigned32 val; asm volatile ("mov %%gs, %0" : "=rm" (val)); return val; } + +PUBLIC static inline +void +Cpu::set_fs(Unsigned32 val) +{ asm volatile ("mov %0, %%fs" : : "rm" (val)); } + +PUBLIC static inline +void +Cpu::set_gs(Unsigned32 val) +{ asm volatile ("mov %0, %%gs" : : "rm" (val)); } + +IMPLEMENT inline +unsigned +Cpu::phys_id() const +{ return _brand & 0xff000000; } + +PUBLIC static +unsigned +Cpu::phys_id_direct() +{ + Unsigned32 a,b,c,d; + cpuid (1, &a, &b, &c, &d); + return b & 0xff000000; +} diff --git a/kernel/fiasco/src/kern/ia32/dirq-ia32-ux.cpp b/kernel/fiasco/src/kern/ia32/dirq-ia32-ux.cpp new file mode 100644 index 00000000..153a5fa2 --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/dirq-ia32-ux.cpp @@ -0,0 +1,51 @@ +INTERFACE[ia32,amd64,ux]: +#include "std_macros.h" +#include "types.h" + +IMPLEMENTATION[ia32,amd64,ux]: + +#include + +#include "cpu_lock.h" +#include "globalconfig.h" +#include "globals.h" +#include "irq.h" +#include "logdefs.h" +#include "std_macros.h" +#include "thread.h" +#include "timer.h" + +// screen spinner for debugging purposes +static inline void irq_spinners(int irqnum) +{ +#ifdef CONFIG_IRQ_SPINNER + Unsigned16 *p = (Unsigned16 *)Mem_layout::Adap_vram_cga_beg; + p += (20 + current_cpu()) * 80 + irqnum; + if (p < (Unsigned16 *)Mem_layout::Adap_vram_cga_end) + (*p)++; +#else + (void)irqnum; +#endif +} + +/** Hardware interrupt entry point. Calls corresponding Dirq instance's + Dirq::hit() method. + @param irqobj hardware-interrupt object + */ +extern "C" FIASCO_FASTCALL +void +irq_interrupt(Mword _irqobj, Mword ip) +{ + Mword irqobj = (Smword)((Signed32)_irqobj); + Thread::assert_irq_entry(); + + CNT_IRQ; + (void)ip; + + // we're entered with disabled irqs + Irq_base *i = (Irq_base*)irqobj; + i->log(); + irq_spinners(i->pin()); + i->hit(0); +} + diff --git a/kernel/fiasco/src/kern/ia32/entry-mp.S b/kernel/fiasco/src/kern/ia32/entry-mp.S new file mode 100644 index 00000000..70f29131 --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/entry-mp.S @@ -0,0 +1,27 @@ +#include "idt_init.h" +#include "tcboffset.h" +#include + + .p2align 4 + .globl entry_ipi_remote_request +entry_ipi_remote_request: + SAVE_SCRATCH + call handle_remote_cpu_requests + RESTORE_SCRATCH + IRET_INSN + + .p2align 4 + .globl entry_ipi +entry_ipi: + SAVE_SCRATCH + call ipi_remote_call + RESTORE_SCRATCH + IRET_INSN + + .p2align 4 + .globl entry_debug_ipi +entry_debug_ipi: + push $(0) + push $(0xee) + save_all_regs + jmp slowtraps diff --git a/kernel/fiasco/src/kern/ia32/fpu-ia32-ux.cpp b/kernel/fiasco/src/kern/ia32/fpu-ia32-ux.cpp new file mode 100644 index 00000000..1c851689 --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/fpu-ia32-ux.cpp @@ -0,0 +1,182 @@ +/* + * Fiasco FPU Code + * Shared between UX and native IA32. + */ + +INTERFACE[ia32,amd64,ux]: + +EXTENSION class Fpu +{ + +private: + struct fpu_regs // saved FPU registers + { + long cwd; + long swd; + long twd; + long fip; + long fcs; + long foo; + long fos; + long st_space[20]; /* 8*10 bytes for each FP-reg = 80 bytes */ + }; + + struct sse_regs + { + Unsigned16 cwd; + Unsigned16 swd; + Unsigned16 twd; + Unsigned16 fop; + Unsigned32 fip; + Unsigned32 fcs; + Unsigned32 foo; + Unsigned32 fos; + Unsigned32 mxcsr; + Unsigned32 reserved; + Unsigned32 st_space[32]; /* 8*16 bytes for each FP-reg = 128 bytes */ + Unsigned32 xmm_space[64]; /* 16*16 bytes for each XMM-reg = 256 bytes */ + Unsigned32 padding[24]; + }; + + struct Xsave_buffer + { + sse_regs sse; + Unsigned64 header[8]; + }; + + enum Variants + { + Variant_fpu, + Variant_fxsr, + Variant_xsave, + }; + + enum Variants _variant; + + static unsigned _state_size; + static unsigned _state_align; +}; + +IMPLEMENTATION[ia32,amd64,ux]: + +#include +#include "cpu.h" +#include "fpu_state.h" +#include "regdefs.h" +#include "globals.h" +#include "static_assert.h" + +unsigned Fpu::_state_size; +unsigned Fpu::_state_align; + +/* + * Initialize FPU or SSE state + * We don't use finit, because it is slow. Initializing the context in + * memory and fetching it via restore_state is supposedly faster + */ +IMPLEMENT inline NEEDS ["cpu.h", "fpu_state.h", "globals.h", "regdefs.h", + "static_assert.h", ] +void +Fpu::init_state(Fpu_state *s) +{ + Cpu const &_cpu = Cpu::cpus.cpu(current_cpu()); + if (_cpu.features() & FEAT_FXSR) + { + assert (_state_size >= sizeof (sse_regs)); + sse_regs *sse = reinterpret_cast(s->state_buffer()); + + memset(sse, 0, sizeof (*sse)); + sse->cwd = 0x37f; + + if (_cpu.features() & FEAT_SSE) + sse->mxcsr = 0x1f80; + + if (_cpu.ext_features() & FEATX_XSAVE) + memset(reinterpret_cast(s->state_buffer())->header, 0, + sizeof (Xsave_buffer::header)); + + static_assert(sizeof (sse_regs) == 512, "SSE-regs size not 512 bytes"); + } + else + { + fpu_regs *fpu = reinterpret_cast(s->state_buffer()); + + assert (_state_size >= sizeof (*fpu)); + memset(fpu, 0, sizeof (*fpu)); + fpu->cwd = 0xffff037f; + fpu->swd = 0xffff0000; + fpu->twd = 0xffffffff; + fpu->fos = 0xffff0000; + } +} + +IMPLEMENT +void +Fpu::init(unsigned cpu) +{ + // Mark FPU busy, so that first FPU operation will yield an exception + disable(); + + // At first, noone owns the FPU + set_owner(cpu, 0); + + init_disable(); + + printf("FPU%d: %s%s\n", cpu, + Cpu::cpus.cpu(cpu).features() & FEAT_SSE ? "SSE " : "", + Cpu::cpus.cpu(cpu).ext_features() & FEATX_AVX ? "AVX " : ""); + + unsigned cpu_align = 0, cpu_size = 0; + + if (Cpu::cpus.cpu(cpu).ext_features() & FEATX_XSAVE) + { + init_xsave(cpu); + + Cpu::cpus.cpu(cpu).update_features_info(); + + Unsigned32 eax, ecx, edx; + Cpu::cpus.cpu(cpu).cpuid_0xd(0, &eax, &cpu_size, &ecx, &edx); + cpu_align = 64; + fpu(cpu)._variant = Variant_xsave; + } + else if (Cpu::have_fxsr()) + { + cpu_size = sizeof(sse_regs); + cpu_align = 16; + fpu(cpu)._variant = Variant_fxsr; + } + else + { + cpu_size = sizeof(fpu_regs); + cpu_align = 4; + fpu(cpu)._variant = Variant_fpu; + } + + if (cpu_size > _state_size) + _state_size = cpu_size; + if (cpu_align > _state_align) + _state_align = cpu_align; +} + + +/** + * Return size of FPU context structure, depending on i387 or SSE + * @return size of FPU context structure + */ +IMPLEMENT inline NEEDS ["cpu.h", "regdefs.h"] +unsigned +Fpu::state_size() +{ + return _state_size; +} + +/** + * Return recommended FPU context alignment, depending on i387 or SSE + * @return recommended FPU context alignment + */ +IMPLEMENT inline NEEDS ["cpu.h", "regdefs.h"] +unsigned +Fpu::state_align() +{ + return _state_align; +} diff --git a/kernel/fiasco/src/kern/ia32/fpu-ia32.cpp b/kernel/fiasco/src/kern/ia32/fpu-ia32.cpp new file mode 100644 index 00000000..6f1229ba --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/fpu-ia32.cpp @@ -0,0 +1,148 @@ +/* + * Fiasco ia32 + * Architecture specific floating point unit code + */ + +IMPLEMENTATION [{ia32,amd64}-fpu]: + +#include "cpu.h" +#include "globalconfig.h" +#include "globals.h" +#include "regdefs.h" + +#include +#include + +PRIVATE static +void +Fpu::init_xsave(unsigned cpu) +{ + Unsigned32 eax, ebx, ecx, edx; + + Cpu::cpus.cpu(cpu).cpuid_0xd(0, &eax, &ebx, &ecx, &edx); + + Unsigned64 valid_xcr0 = ((Unsigned64)edx << 32) | eax; + + // enable AVX and friends + Cpu::cpus.cpu(cpu).set_cr4(Cpu::cpus.cpu(cpu).get_cr4() | CR4_OSXSAVE); + asm volatile("xsetbv" + : + : "a" ((Mword)valid_xcr0), + "d" ((Mword)(valid_xcr0 >> 32)), + "c" (0)); +} + +PRIVATE static +void +Fpu::init_disable() +{ + // disable Coprocessor Emulation to allow exception #7/NM on TS + // enable Numeric Error (exception #16/MF, native FPU mode) + // enable Monitor Coprocessor + Cpu::set_cr0((Cpu::get_cr0() & ~CR0_EM) | CR0_NE | CR0_MP); +} + +/* + * Save FPU or SSE state + */ +IMPLEMENT inline NEEDS [,"globals.h", "regdefs.h", "cpu.h"] +void +Fpu::save_state(Fpu_state *s) +{ + assert (s->state_buffer()); + + // Both fxsave and fnsave are non-waiting instructions and thus + // cannot cause exception #16 for pending FPU exceptions. + + switch (fpu(current_cpu())._variant) + { + case Variant_xsave: + asm volatile("xsave (%2)" : : "a" (~0UL), "d" (~0UL), "r" (s->state_buffer()) : "memory"); + break; + case Variant_fxsr: + asm volatile ("fxsave (%0)" : : "r" (s->state_buffer()) : "memory"); + break; + case Variant_fpu: + asm volatile ("fnsave (%0)" : : "r" (s->state_buffer()) : "memory"); + break; + } +} + +/* + * Restore a saved FPU or SSE state + */ +IMPLEMENT inline NEEDS ["globals.h", "globalconfig.h", ,"regdefs.h", + "cpu.h"] +void +Fpu::restore_state(Fpu_state *s) +{ + assert (s->state_buffer()); + + // Only fxrstor is a non-waiting instruction and thus + // cannot cause exception #16 for pending FPU exceptions. + unsigned cpu = current_cpu(); + + switch (fpu(cpu)._variant) + { + case Variant_xsave: + asm volatile ("xrstor (%2)" : : "a" (~0UL), "d" (~0UL), "r" (s->state_buffer())); + break; + case Variant_fxsr: + { +#if !defined (CONFIG_WORKAROUND_AMD_FPU_LEAK) + asm volatile ("fxrstor (%0)" : : "r" (s->state_buffer())); +#else + /* The code below fixes a security leak on AMD CPUs, where + * some registers of the FPU are not restored from the state_buffer + * if there are no FPU exceptions pending. The old values, from the + * last FPU owner, are therefore leaked to the new FPU owner. + */ + static Mword int_dummy = 0; + + asm volatile( + "fnstsw %%ax \n\t" // save fpu flags in ax + "ffree %%st(7) \n\t" // make enough space for the fildl + "bt $7,%%ax \n\t" // test if exception bit is set + "jnc 1f \n\t" + "fnclex \n\t" // clear it + "1: fildl %1 \n\t" // dummy load which sets the + // affected to def. values + "fxrstor (%0) \n\t" // finally restore the state + : : "r" (s->state_buffer()), "m" (int_dummy) : "ax"); +#endif + } + break; + case Variant_fpu: + // frstor is a waiting instruction and we must make sure no + // FPU exceptions are pending here. We distinguish two cases: + // 1) If we had a previous FPU owner, we called save_state before and + // invoked fnsave which re-initialized the FPU and cleared exceptions + // 2) Otherwise we call fnclex instead to clear exceptions. + + if (!Fpu::owner(cpu)) + asm volatile ("fnclex"); + + asm volatile ("frstor (%0)" : : "r" (s->state_buffer())); + break; + } +} + +/* + * Mark the FPU busy. The next attempt to use it will yield a trap. + */ +IMPLEMENT inline NEEDS ["regdefs.h","cpu.h"] +void +Fpu::disable() +{ + Cpu::set_cr0(Cpu::get_cr0() | CR0_TS); +} + +/* + * Mark the FPU no longer busy. Subsequent FPU access won't trap. + */ +IMPLEMENT inline +void +Fpu::enable() +{ + asm volatile ("clts"); +} diff --git a/kernel/fiasco/src/kern/ia32/gdt.cpp b/kernel/fiasco/src/kern/ia32/gdt.cpp new file mode 100644 index 00000000..ef1131cf --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/gdt.cpp @@ -0,0 +1,119 @@ + +INTERFACE: + +#include "config_gdt.h" +#include "l4_types.h" +#include "x86desc.h" + +class Gdt +{ +public: + /** Segment numbers. */ + enum + { + gdt_tss = GDT_TSS, + gdt_code_kernel = GDT_CODE_KERNEL, + gdt_data_kernel = GDT_DATA_KERNEL, + gdt_code_user = GDT_CODE_USER, + gdt_data_user = GDT_DATA_USER, + gdt_tss_dbf = GDT_TSS_DBF, + gdt_utcb = GDT_UTCB, + gdt_ldt = GDT_LDT, + gdt_user_entry1 = GDT_USER_ENTRY1, + gdt_user_entry2 = GDT_USER_ENTRY2, + gdt_user_entry3 = GDT_USER_ENTRY3, + gdt_max = GDT_MAX, + }; + + enum + { + Selector_user = 0x03, + Selector_kernel = 0x00, + }; + +private: + Gdt_entry _entries[0]; +}; + +//------------------------------------------------------------------ +IMPLEMENTATION [amd64]: + + +PUBLIC inline +void +Gdt::set_entry_tss(int nr, Address base, Unsigned32 limit, + Unsigned8 access, Unsigned8 szbits) +{ + Address b = base >> 32; + // system-segment descriptor is 64 bit + _entries[nr] = Gdt_entry(base, limit >> 12, access, szbits | 0x08); + *reinterpret_cast(reinterpret_cast(&_entries[nr+1])) + = b; +} + + +//------------------------------------------------------------------ +IMPLEMENTATION: + + +PUBLIC inline +void +Gdt::set_entry_byte(int nr, Address base, Unsigned32 limit, + Unsigned8 access, Unsigned8 szbits) +{ + _entries[nr] = Gdt_entry(base, limit, access, szbits); +} + +PUBLIC inline +void +Gdt::set_entry_4k(int nr, Address base, Unsigned32 limit, + Unsigned8 access, Unsigned8 szbits) +{ + _entries[nr] = Gdt_entry(base, limit >> 12, access, szbits | 0x08); +} + +PUBLIC inline +void +Gdt::clear_entry(int nr) +{ + _entries[nr].clear(); +} + +PUBLIC inline +Gdt_entry* +Gdt::entries() +{ + return _entries; +} + +PUBLIC inline +Gdt_entry & +Gdt::operator [] (unsigned idx) +{ return _entries[idx]; } + +PUBLIC inline +Gdt_entry const & +Gdt::operator [] (unsigned idx) const +{ return _entries[idx]; } + + +IMPLEMENTATION[ia32 | amd64]: + +PUBLIC static inline +void +Gdt::set (Pseudo_descriptor *desc) +{ + asm volatile ("lgdt %0" : : "m" (*desc)); +} + +PUBLIC static inline +void +Gdt::get (Pseudo_descriptor *desc) +{ + asm volatile ("sgdt %0" : "=m" (*desc) : : "memory"); +} + +PUBLIC static inline +int +Gdt::data_segment () +{ return gdt_data_user | Selector_user; } diff --git a/kernel/fiasco/src/kern/ia32/idt.cpp b/kernel/fiasco/src/kern/ia32/idt.cpp new file mode 100644 index 00000000..be65a8ac --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/idt.cpp @@ -0,0 +1,237 @@ +/* + * Fiasco Interrupt Descriptor Table (IDT) Code + */ + +INTERFACE: + +#include "initcalls.h" +#include "kmem.h" +#include "mem_layout.h" +#include "types.h" +#include "x86desc.h" + +class Idt_init_entry; + +class Idt +{ + friend class Jdb_kern_info_bench; +public: + // idt entries for 0x20 CPU exceptions, 0x10 IRQs, 7 syscalls, + // 0x3e/0x3f for APIC exceptions + static const unsigned _idt_max = 0xa0; +private: + static const Address _idt = Mem_layout::Idt; +}; + +IMPLEMENTATION: + +#include +#include "gdt.h" +#include "idt_init.h" +#include "irq_chip.h" +#include "mem_unit.h" +#include "paging.h" +#include "panic.h" +#include "vmem_alloc.h" + +/** + * IDT write-protect/write-unprotect function. + * @param writable true if IDT should be made writable, false otherwise + */ +PRIVATE static +void +Idt::set_writable(bool writable) +{ + Pdir::Iter e = Kmem::dir()->walk(Virt_addr(_idt)); + + // Make sure page directory entry is valid and not a 4MB page + assert (e.e->valid() && e.shift() < Config::SUPERPAGE_SHIFT); + + if (writable) + e.e->add_attr(Pt_entry::Writable); // Make read-write + else + e.e->del_attr(Pt_entry::Writable); // Make read-only + + Mem_unit::tlb_flush (_idt); +} + +PUBLIC static FIASCO_INIT +void +Idt::init_table(Idt_init_entry *src) +{ + Idt_entry *entries = (Idt_entry*)_idt; + + while (src->entry) + { + entries[src->vector] = + ((src->type & 0x1f) == 0x05) // task gate? + ? Idt_entry(src->entry, src->type) + : Idt_entry(src->entry, Gdt::gdt_code_kernel, src->type); + src++; + } +} + +/** + * IDT initialization function. Sets up initial interrupt vectors. + * It also write-protects the IDT because of the infamous Pentium F00F bug. + */ +PUBLIC static FIASCO_INIT +void +Idt::init() +{ + if (!Vmem_alloc::page_alloc((void *) _idt, Vmem_alloc::ZERO_FILL)) + panic("IDT allocation failure"); + + init_table((Idt_init_entry*)&idt_init_table); + load(); + + set_writable(false); +} + + +PUBLIC static +void +Idt::load() +{ + Pseudo_descriptor desc(_idt, _idt_max*sizeof(Idt_entry)-1); + set(&desc); +} + +PUBLIC static +void +Idt::set_entry(unsigned vector, Idt_entry entry) +{ + assert (vector < _idt_max); + + set_writable(true); + + Idt_entry *entries = (Idt_entry*)_idt; + entries[vector] = entry; + set_writable(false); +} + +PUBLIC static +Idt_entry const & +Idt::get(unsigned vector) +{ + assert (vector < _idt_max); + + return ((Idt_entry*)_idt)[vector]; +} + +/** + * IDT patching function. + * Allows to change interrupt gate vectors at runtime. + * It makes the IDT writable for the duration of this operation. + * @param vector interrupt vector to be modified + * @param func new handler function for this interrupt vector + * @param user true if user mode can use this vector, false otherwise + */ +PUBLIC static +void +Idt::set_entry(unsigned vector, Address entry, bool user) +{ + assert (vector < _idt_max); + + set_writable(true); + + Idt_entry *entries = (Idt_entry*)_idt; + if (entry) + entries[vector] = Idt_entry(entry, Gdt::gdt_code_kernel, + Idt_entry::Access_intr_gate | + (user ? Idt_entry::Access_user + : Idt_entry::Access_kernel)); + else + entries[vector].clear(); + + set_writable(false); +} + +PUBLIC static +Address +Idt::get_entry(unsigned vector) +{ + assert (vector < _idt_max); + Idt_entry *entries = (Idt_entry*)_idt; + return entries[vector].offset(); +} + +PUBLIC static inline +Address +Idt::idt() +{ + return _idt; +} + + +//--------------------------------------------------------------------------- +IMPLEMENTATION[ia32 | amd64]: + +#include "config.h" + +/** + * IDT loading function. + * Loads IDT base and limit into the CPU. + * @param desc IDT descriptor (base address, limit) + */ +PUBLIC static inline +void +Idt::set(Pseudo_descriptor *desc) +{ + asm volatile ("lidt %0" : : "m" (*desc)); +} + +PUBLIC static inline +void +Idt::get(Pseudo_descriptor *desc) +{ + asm volatile ("sidt %0" : "=m" (*desc) : : "memory"); +} + +extern "C" void entry_int_timer(); +extern "C" void entry_int_timer_slow(); +extern "C" void entry_int7(); +extern "C" void entry_intf(); +extern "C" void entry_int_pic_ignore(); + +/** + * Set IDT vector to the normal timer interrupt handler. + */ +PUBLIC static +void +Idt::set_vectors_run() +{ + Address func = (Config::esc_hack || Config::watchdog || + Config::serial_esc==Config::SERIAL_ESC_NOIRQ) + ? (Address)entry_int_timer_slow // slower for debugging + : (Address)entry_int_timer; // non-debugging + + set_entry(Config::scheduler_irq_vector, func, false); +#if 0 + if (!Irq_chip::hw_chip->is_free(0x7)) + Irq_chip::hw_chip->reset(0x07); + + if (!Irq_chip::hw_chip->is_free(0xf)) + Irq_chip::hw_chip->reset(0x0f); +#endif +} + + +//--------------------------------------------------------------------------- +IMPLEMENTATION[ux]: + +#include "emulation.h" + +PUBLIC static +void +Idt::set(Pseudo_descriptor *desc) +{ + Emulation::lidt(desc); +} + +PUBLIC static +void +Idt::get(Pseudo_descriptor *desc) +{ + Emulation::sidt(desc); +} diff --git a/kernel/fiasco/src/kern/ia32/idt_init.h b/kernel/fiasco/src/kern/ia32/idt_init.h new file mode 100644 index 00000000..4b35301f --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/idt_init.h @@ -0,0 +1,78 @@ +#include + +#ifndef IDT_INIT +#define IDT_INIT + +#define APIC_IRQ_BASE 0x90 + +#ifdef ASSEMBLER + +#define GATE_INITTAB_BEGIN(name) \ + .section ".initcall.data", "aw", @progbits ;\ + .globl name ;\ + .align 8 ;\ +name: ;\ + .text + +#ifdef CONFIG_BIT32 +#define GATE_ENTRY(n,name,type) \ + .section ".initcall.data", "aw", @progbits ;\ + .long name ;\ + .word n ;\ + .word type ;\ + .text + +#define GATE_INITTAB_END \ + .section ".initcall.data" ;\ + .long 0 ;\ + .text +#else +#define GATE_ENTRY(n,name,type) \ + .section ".initcall.data" ;\ + .quad name ;\ + .word n ;\ + .word type ;\ + .text + +#define GATE_INITTAB_END \ + .section ".initcall.data" ;\ + .quad 0 ;\ + .text +#endif + +#define SEL_PL_U 0x03 +#define SEL_PL_K 0x00 + +#define ACC_TASK_GATE 0x05 +#define ACC_INTR_GATE 0x0e +#define ACC_TRAP_GATE 0x0f +#define ACC_PL_U 0x60 +#define ACC_PL_K 0x00 + +#else // !ASSEMBLER + +#include "l4_types.h" + +#ifdef CONFIG_BIT32 +class Idt_init_entry +{ +public: + Unsigned32 entry; + Unsigned16 vector; + Unsigned16 type; +} __attribute__((packed)); +#else +class Idt_init_entry +{ +public: + Unsigned64 entry; + Unsigned16 vector; + Unsigned16 type; +} __attribute__((packed)); +#endif + +extern Idt_init_entry idt_init_table[]; + +#endif + +#endif diff --git a/kernel/fiasco/src/kern/ia32/io_apic.cpp b/kernel/fiasco/src/kern/ia32/io_apic.cpp new file mode 100644 index 00000000..6ac6a299 --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/io_apic.cpp @@ -0,0 +1,475 @@ +INTERFACE: + +#include +#include "initcalls.h" +#include +#include "irq_chip_ia32.h" + +class Acpi_madt; + +class Io_apic_entry +{ + friend class Io_apic; +private: + Unsigned64 _e; + +public: + enum Delivery { Fixed, Lowest_prio, SMI, NMI = 4, INIT, ExtINT = 7 }; + enum Dest_mode { Physical, Logical }; + enum Polarity { High_active, Low_active }; + enum Trigger { Edge, Level }; + + Io_apic_entry() {} + Io_apic_entry(Unsigned8 vector, Delivery d, Dest_mode dm, Polarity p, + Trigger t, Unsigned8 dest) + : _e(vector | (d << 8) | (dm << 11) | (p << 13) | (t << 15) | (1<<16) + | (((Unsigned64)dest) << 56)) + {} + + unsigned delivery() const { return (_e >> 8) & 7; } + void delivery(unsigned m) { _e = (_e & ~(7 << 8)) | ((m & 7) << 8); } + unsigned dest_mode() const { return _e & (1 << 11); } + void dest_mode(bool p) { _e = (_e & ~(1<<11)) | ((unsigned long)p << 11); } + unsigned dest() const { return _e >> 56; } + void dest(unsigned d) { _e = (_e & ~(0xffULL << 56)) | ((Unsigned64)d << 56); } + unsigned mask() const { return _e & (1U << 16); } + void mask(bool m) { _e = (_e & ~(1ULL << 16)) | ((Unsigned64)m << 16); } + unsigned trigger() const { return _e & (1 << 15); } + unsigned polarity() const { return _e & (1 << 13); } + unsigned vector() const { return _e & 0xff; } + void vector(Unsigned8 v) { _e = (_e & ~0xff) | v; } + void trigger(Mword tr) { _e = (_e & ~(1UL << 15)) | ((tr & 1) << 15); } + void polarity(Mword pl) { _e = (_e & ~(1UL << 13)) | ((pl & 1) << 13); } +} __attribute__((packed)); + + +class Io_apic : public Irq_chip_ia32 +{ + friend class Jdb_io_apic_module; + +private: + struct Apic + { + Unsigned32 volatile adr; + Unsigned32 dummy[3]; + Unsigned32 volatile data; + + unsigned num_entries(); + Mword read(int reg); + void modify(int reg, Mword set_bits, Mword del_bits); + void write(int reg, Mword value); + } __attribute__((packed)); + + Apic *_apic; + Spin_lock<> _l; + unsigned _offset; + Io_apic *_next; + + static unsigned _nr_irqs; + static Io_apic *_first; + static Acpi_madt const *_madt; +}; + +IMPLEMENTATION: + +#include "acpi.h" +#include "apic.h" +#include "irq_mgr.h" +#include "kmem.h" +#include "kdb_ke.h" +#include "kip.h" +#include "lock_guard.h" +#include "boot_alloc.h" + +Acpi_madt const *Io_apic::_madt; +unsigned Io_apic::_nr_irqs; +Io_apic *Io_apic::_first; + + +class Io_apic_mgr : public Irq_mgr +{ +}; + +PUBLIC Irq_mgr::Irq +Io_apic_mgr::chip(Mword irq) const +{ + Io_apic *a = Io_apic::find_apic(irq); + if (a) + return Irq(a, irq - a->gsi_offset()); + + return Irq(0, 0); +} + +PUBLIC +unsigned +Io_apic_mgr::nr_irqs() const +{ + return Io_apic::total_irqs(); +} + +PUBLIC +unsigned +Io_apic_mgr::nr_msis() const +{ return 0; } + +PUBLIC unsigned +Io_apic_mgr::legacy_override(Mword i) +{ return Io_apic::legacy_override(i); } + + +IMPLEMENT inline +Mword +Io_apic::Apic::read(int reg) +{ + adr = reg; + asm volatile ("": : :"memory"); + return data; +} + +IMPLEMENT inline +void +Io_apic::Apic::modify(int reg, Mword set_bits, Mword del_bits) +{ + register Mword tmp; + adr = reg; + asm volatile ("": : :"memory"); + tmp = data; + tmp &= ~del_bits; + tmp |= set_bits; + data = tmp; +} + +IMPLEMENT inline +void +Io_apic::Apic::write(int reg, Mword value) +{ + adr = reg; + asm volatile ("": : :"memory"); + data = value; +} + +IMPLEMENT inline +unsigned +Io_apic::Apic::num_entries() +{ + return (read(1) >> 16) & 0xff; +} + +PUBLIC explicit inline +Io_apic::Io_apic(Io_apic::Apic *addr, unsigned irqs, unsigned gsi_base) +: Irq_chip_ia32(irqs), _apic(addr), _l(Spin_lock<>::Unlocked), + _offset(gsi_base), _next(0) +{} + + +PUBLIC inline NEEDS["kdb_ke.h", "lock_guard.h"] +Io_apic_entry +Io_apic::read_entry(unsigned i) +{ + Lock_guard g(&_l); + Io_apic_entry e; + //assert_kdb(i <= num_entries()); + e._e = (Unsigned64)_apic->read(0x10+2*i) | (((Unsigned64)_apic->read(0x11+2*i)) << 32); + return e; +} + + +PUBLIC inline NEEDS["kdb_ke.h", "lock_guard.h"] +void +Io_apic::write_entry(unsigned i, Io_apic_entry const &e) +{ + Lock_guard g(&_l); + //assert_kdb(i <= num_entries()); + _apic->write(0x10+2*i, e._e); + _apic->write(0x11+2*i, e._e >> 32); +} + +PUBLIC static FIASCO_INIT +bool +Io_apic::init() +{ + _madt = Acpi::find("APIC"); + + if (_madt == 0) + { + printf("Could not find APIC in RSDT nor XSDT, skipping init\n"); + return false; + } + printf("IO-APIC: MADT = %p\n", _madt); + + int n_apics = 0; + + for (n_apics = 0; + Acpi_madt::Io_apic const *ioapic = static_cast(_madt->find(Acpi_madt::IOAPIC, n_apics)); + ++n_apics) + { + printf("IO-APIC[%2d]: struct: %p adr=%x\n", n_apics, ioapic, ioapic->adr); + + Address offs; + Address va = Mem_layout::alloc_io_vmem(Config::PAGE_SIZE); + assert (va); + + Kmem::map_phys_page(ioapic->adr, va, false, true, &offs); + + Kip::k()->add_mem_region(Mem_desc(ioapic->adr, ioapic->adr + Config::PAGE_SIZE -1, Mem_desc::Reserved)); + + Io_apic::Apic *a = (Io_apic::Apic*)(va + offs); + a->write(0, 0); + + unsigned const irqs = a->num_entries() + 1; + Io_apic *apic = new Boot_object(a, irqs, ioapic->irq_base); + + if ((apic->_offset + irqs) > _nr_irqs) + _nr_irqs = apic->_offset + irqs; + + for (unsigned i = 0; i < irqs; ++i) + { + int v = 0x20+i; + Io_apic_entry e(v, Io_apic_entry::Fixed, Io_apic_entry::Physical, + Io_apic_entry::High_active, Io_apic_entry::Edge, 0); + apic->write_entry(i, e); + } + + Io_apic **c = &_first; + while (*c && (*c)->_offset < apic->_offset) + c = &((*c)->_next); + + apic->_next = *c; + *c = apic; + + printf("IO-APIC[%2d]: pins %u\n", n_apics, irqs); + apic->dump(); + } + + if (!n_apics) + { + printf("IO-APIC: Could not find IO-APIC in MADT, skip init\n"); + return false; + } + + + printf("IO-APIC: dual 8259: %s\n", _madt->apic_flags & 1 ? "yes" : "no"); + + for (unsigned tmp = 0;;++tmp) + { + Acpi_madt::Irq_source const *irq + = static_cast(_madt->find(Acpi_madt::Irq_src_ovr, tmp)); + + if (!irq) + break; + + printf("IO-APIC: ovr[%2u] %02x -> %x\n", tmp, irq->src, irq->irq); + } + + Irq_mgr::mgr = new Boot_object(); + + // in the case we use the IO-APIC not the PIC we can dynamically use + // INT vectors from 0x20 to 0x2f too + _vectors.add_free(0x20, 0x30); + return true; +}; + +PUBLIC static +unsigned +Io_apic::total_irqs() +{ return _nr_irqs; } + +PUBLIC static +unsigned +Io_apic::legacy_override(unsigned i) +{ + if (!_madt) + return i; + + unsigned tmp = 0; + for (;;++tmp) + { + Acpi_madt::Irq_source const *irq + = static_cast(_madt->find(Acpi_madt::Irq_src_ovr, tmp)); + + if (!irq) + break; + + if (irq->src == i) + return irq->irq; + } + return i; +} + +PUBLIC +void +Io_apic::dump() +{ + for (unsigned i = 0; i < _irqs; ++i) + { + Io_apic_entry e = read_entry(i); + printf(" PIN[%2u%c]: vector=%2x, del=%u, dm=%s, dest=%u (%s, %s)\n", + i, e.mask() ? 'm' : '.', + e.vector(), e.delivery(), e.dest_mode() ? "logical" : "physical", + e.dest(), + e.polarity() ? "low" : "high", + e.trigger() ? "level" : "edge"); + } + +} + +PUBLIC inline +bool +Io_apic::valid() const { return _apic; } + +PRIVATE inline NEEDS["kdb_ke.h", "lock_guard.h"] +void +Io_apic::_mask(unsigned irq) +{ + Lock_guard g(&_l); + //assert_kdb(irq <= _apic->num_entries()); + _apic->modify(0x10 + irq * 2, 1UL << 16, 0); +} + +PRIVATE inline NEEDS["kdb_ke.h", "lock_guard.h"] +void +Io_apic::_unmask(unsigned irq) +{ + Lock_guard g(&_l); + //assert_kdb(irq <= _apic->num_entries()); + _apic->modify(0x10 + irq * 2, 0, 1UL << 16); +} + +PUBLIC inline NEEDS["kdb_ke.h", "lock_guard.h"] +bool +Io_apic::masked(unsigned irq) +{ + Lock_guard g(&_l); + //assert_kdb(irq <= _apic->num_entries()); + return _apic->read(0x10 + irq * 2) & (1UL << 16); +} + +PUBLIC inline +void +Io_apic::sync() +{ + (void)_apic->data; +} + +PUBLIC inline NEEDS["kdb_ke.h", "lock_guard.h"] +void +Io_apic::set_dest(unsigned irq, Mword dst) +{ + Lock_guard g(&_l); + //assert_kdb(irq <= _apic->num_entries()); + _apic->modify(0x11 + irq * 2, dst & (~0UL << 24), ~0UL << 24); +} + +PUBLIC inline +unsigned +Io_apic::gsi_offset() const { return _offset; } + +PUBLIC static +Io_apic * +Io_apic::find_apic(unsigned irqnum) +{ + for (Io_apic *a = _first; a; a = a->_next) + { + if (a->_offset <= irqnum && a->_offset + a->_irqs > irqnum) + return a; + } + return 0; +}; + +PUBLIC void +Io_apic::mask(Mword irq) +{ + _mask(irq); + sync(); +} + +PUBLIC void +Io_apic::ack(Mword) +{ + ::Apic::irq_ack(); +} + +PUBLIC void +Io_apic::mask_and_ack(Mword irq) +{ + _mask(irq); + sync(); + ::Apic::irq_ack(); +} + +PUBLIC void +Io_apic::unmask(Mword irq) +{ + _unmask(irq); +} + +PUBLIC void +Io_apic::set_cpu(Mword irq, unsigned cpu) +{ + set_dest(irq, Cpu::cpus.cpu(cpu).phys_id()); +} + +static inline +Mword to_io_apic_trigger(unsigned mode) +{ + return (mode & Irq_base::Trigger_level) + ? Io_apic_entry::Level + : Io_apic_entry::Edge; +} + +static inline +Mword to_io_apic_polarity(unsigned mode) +{ + return (mode & Irq_base::Polarity_low) + ? Io_apic_entry::Low_active + : Io_apic_entry::High_active; +} + +PUBLIC unsigned +Io_apic::set_mode(Mword pin, unsigned mode) +{ + if ((mode & Irq_base::Polarity_mask) == Irq_base::Polarity_both) + mode = Irq_base::Polarity_low; + + Io_apic_entry e = read_entry(pin); + e.polarity(to_io_apic_polarity(mode)); + e.trigger(to_io_apic_trigger(mode)); + write_entry(pin, e); + return mode; +} + +PUBLIC +bool +Io_apic::alloc(Irq_base *irq, Mword pin) +{ + unsigned v = valloc(irq, pin, 0); + + if (!v) + return false; + + Io_apic_entry e = read_entry(pin); + e.vector(v); + write_entry(pin, e); + return true; +} + +PUBLIC +void +Io_apic::unbind(Irq_base *irq) +{ + extern char entry_int_apic_ignore[]; + Mword n = irq->pin(); + mask(n); + vfree(irq, &entry_int_apic_ignore); + Irq_chip_icu::unbind(irq); +} + +PUBLIC inline +char const * +Io_apic::chip_type() const +{ return "IO-APIC"; } + +PUBLIC static inline +bool +Io_apic::active() +{ return _first; } diff --git a/kernel/fiasco/src/kern/ia32/ipi-ia32.cpp b/kernel/fiasco/src/kern/ia32/ipi-ia32.cpp new file mode 100644 index 00000000..be32ed30 --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/ipi-ia32.cpp @@ -0,0 +1,103 @@ +INTERFACE [mp]: + +#include "per_cpu_data.h" + +EXTENSION class Ipi +{ +private: + Unsigned32 _apic_id; + unsigned _count; + +public: + enum Message + { + Request = APIC_IRQ_BASE - 1, + Global_request = APIC_IRQ_BASE + 2, + Debug = APIC_IRQ_BASE - 2 + }; +}; + + +//--------------------------------------------------------------------------- +IMPLEMENTATION[mp]: + +#include +#include "apic.h" +#include "kmem.h" + +PUBLIC inline +Ipi::Ipi() : _apic_id(~0) +{} + + +/** + * \param cpu the logical CPU number of the current CPU. + * \pre cpu == current CPU. + */ +IMPLEMENT static inline NEEDS["apic.h"] +void +Ipi::init(unsigned cpu) +{ + _ipi.cpu(cpu)._apic_id = Apic::get_id(); +} + + +PUBLIC static inline +void +Ipi::ipi_call_debug_arch() +{ + //ipi_call_spin(); // debug +} + +PUBLIC static inline NEEDS["apic.h"] +void +Ipi::eoi(Message, unsigned cpu) +{ + Apic::mp_ipi_ack(); + stat_received(cpu); +} + +PUBLIC static inline NEEDS["apic.h"] +void +Ipi::send(Message m, unsigned from_cpu, unsigned to_cpu) +{ + Apic::mp_send_ipi(_ipi.cpu(to_cpu)._apic_id, (Unsigned8)m); + stat_sent(from_cpu); +} + +PUBLIC static inline NEEDS["apic.h"] +void +Ipi::bcast(Message m, unsigned from_cpu) +{ + (void)from_cpu; + Apic::mp_send_ipi(Apic::APIC_IPI_OTHERS, (Unsigned8)m); +} + +#if defined(CONFIG_IRQ_SPINNER) + +// debug +PRIVATE static +void Ipi::ipi_call_spin() +{ + unsigned cpu; + Ipi *ipi = 0; + for (cpu = 0; cpu < Config::Max_num_cpus; ++cpu) + { + if (!Per_cpu_data::valid(cpu)) + continue; + + if (_ipi.cpu(cpu)._apic_id == Apic::get_id()) + { + ipi = &_ipi.cpu(cpu); + break; + } + } + + if (!ipi) + return; + + *(unsigned char*)(Mem_layout::Adap_vram_cga_beg + 22*160 + cpu*+2) + = '0' + (ipi->_count++ % 10); +} +#endif + diff --git a/kernel/fiasco/src/kern/ia32/irq_chip_ia32.cpp b/kernel/fiasco/src/kern/ia32/irq_chip_ia32.cpp new file mode 100644 index 00000000..a28a9b59 --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/irq_chip_ia32.cpp @@ -0,0 +1,290 @@ +INTERFACE: + +#include "globals.h" +#include "idt_init.h" +#include "irq_chip.h" +#include "boot_alloc.h" + +/** + * Allocator for IA32 interrupt vectors in the IDT. + * + * Some vectors are fixed purpose, others can be dynamically + * managed by this allocator to support MSIs and multiple IO-APICs. + */ +class Int_vector_allocator +{ +public: + bool empty() const { return !_first; } +private: + enum + { + /// Start at vector 0x20, note: <0x10 is vorbidden here + Base = 0x20, + + /// The Last vector + 1 that is managed + End = APIC_IRQ_BASE - 0x10 + }; + + /// array for free list + unsigned char _vectors[End - Base]; + + /// the first free vector + unsigned _first; +}; + +/** + * Entry point for a device IRQ IDT vector. + * + * IA32 IRQ Chips use arrays of this entry code pieces + * and dynamically assign adresses of Irq_base objects to them + * to directly pass device IRQs to an Irq_base object. + * + * The chips also use these objects to manage the assignment of Irq_base + * objects to the pins of the IRQ controller. + */ +class Irq_entry_code : public Boot_alloced +{ +private: + struct + { + char push; + char mov; + Signed32 irq_adr; + char jmp; + Unsigned32 jmp_adr; + unsigned char vector; + } __attribute__((packed)) _d; + +public: + Irq_entry_code() { free(); _d.vector = 0; } + + Irq_base *irq() const + { return (Irq_base*)((Smword)(_d.irq_adr)); } + + bool is_free() const + { return !_d.push; } + + void free() + { _d.push = 0; } + + unsigned char vector() const + { return _d.vector; } +}; + + +/** + * Generic IA32 IRQ chip class. + * + * Uses an array of Idt_entry_code objects to manage + * the IRQ entry points and the Irq_base objects assigned to the + * pins of a specific controller. + */ +class Irq_chip_ia32 : public Irq_chip_icu +{ +public: + /// Number of pins at this chip. + unsigned nr_irqs() const { return _irqs; } + +protected: + unsigned const _irqs; + Irq_entry_code *const _entry; + static Int_vector_allocator _vectors; +}; + + +IMPLEMENTATION [32bit]: +enum { Register_arg0 = 0 }; // eax + +IMPLEMENTATION [64bit]: +enum { Register_arg0 = 7 }; // rdi + +IMPLEMENTATION: + +#include + +#include "cpu_lock.h" +#include "idt.h" +#include "mem.h" + +// The global INT vector allocator for IRQs uses these data +Int_vector_allocator Irq_chip_ia32::_vectors; + +PUBLIC +void +Irq_entry_code::setup(Irq_base *irq = 0, unsigned char vector = 0) +{ + extern char __generic_irq_entry[]; + // push %eax/%rdi + _d.push = 0x50 + Register_arg0; + + // mov imm32, %eax/%rdi + _d.mov = 0xb8 + Register_arg0; + _d.irq_adr = (Address)irq; + + // jmp __generic_irq_entry + _d.jmp = 0xe9; + _d.jmp_adr = (Address)__generic_irq_entry - (Address)&_d - 11; + + + // no code, our currently assigned IRQ vector + // 0 means no vector allocated + _d.vector = vector; +} + +PUBLIC +void +Int_vector_allocator::add_free(unsigned start, unsigned end) +{ + assert (Base > 0x10); + assert (End > Base); + assert (start >= Base); + assert (end <= End); + + for (unsigned v = start - Base; v < end - Base - 1; ++v) + _vectors[v] = v + Base + 1; + + _vectors[end - Base - 1] = _first; + _first = start; +} + +PUBLIC inline +void +Int_vector_allocator::free(unsigned v) +{ + assert (Base <= v && v < End); + + _vectors[v - Base] = _first; + _first = v; +} + +PUBLIC inline +unsigned +Int_vector_allocator::alloc() +{ + if (!_first) + return 0; + + unsigned r = _first; + _first = _vectors[r - Base]; + return r; +} + +PUBLIC explicit inline +Irq_chip_ia32::Irq_chip_ia32(unsigned irqs) +: _irqs(irqs), + _entry(new Irq_entry_code[irqs]) +{ + // add vectors from 0x40 upo to APIC_IRQ_BASE - 0x10 as free + // if we are the first IA32 chip ctor running + if (_vectors.empty()) + _vectors.add_free(0x40, APIC_IRQ_BASE - 0x10); +} + + +PUBLIC +Irq_base * +Irq_chip_ia32::irq(Mword irqn) const +{ + if (irqn >= _irqs) + return 0; + + return _entry[irqn].irq(); +} + +/** + * Generic binding of an Irq_base object to a specific pin and a + * an INT vector. + * + * \param irq The Irq_base object to bind + * \param pin The pin number at this IRQ chip + * \param vector The INT vector to use, or 0 for dynamic allocation + * \return the INT vector used an success, or 0 on failure. + * + * This function does the following: + * 1. Some sanity checks + * 2. Check if PIN is unassigned + * 3. Check if no vector is given: + * a) Use vector that was formerly assigned to this PIN + * b) Try to allocate a new vector for the PIN + * 4. Prepare the entry code to point to \a irq + * 5. Point IDT entry to the PIN's entry code + * 6. Return the assigned vector number + */ +PROTECTED +unsigned +Irq_chip_ia32::valloc(Irq_base *irq, Mword pin, unsigned vector) +{ + if (pin >= _irqs) + return 0; + + if (vector >= APIC_IRQ_BASE - 0x10) + return 0; + + Irq_entry_code *const e = &_entry[pin]; + + if (!e->is_free()) + return 0; + + if (!vector) + vector = e->vector(); + + if (!vector) + vector = _vectors.alloc(); + + if (!vector) + return 0; + + Irq_chip::bind(irq, pin); + + e->setup(irq, vector); + + // force code to memory before setting IDT entry + Mem::barrier(); + + Idt::set_entry(vector, (Address)e, false); + return vector; +} + + +PROTECTED +bool +Irq_chip_ia32::vfree(Irq_base *irq, void *handler) +{ + Irq_entry_code *e = &_entry[irq->pin()]; + + assert (!e->is_free()); + assert (e->irq() == irq); + + Idt::set_entry(e->vector(), (Address)handler, false); + + e->free(); + + return true; +} + + +PUBLIC +bool +Irq_chip_ia32::reserve(Mword irqn) +{ + if (irqn >= _irqs) + return false; + + if (!_entry[irqn].is_free()) + return false; + + _entry[irqn].setup(); + return true; +} + +PUBLIC +void +Irq_chip_ia32::unbind(Irq_base *irq) +{ + extern char entry_int_pic_ignore[]; + Mword n = irq->pin(); + mask(n); + vfree(irq, &entry_int_pic_ignore); + Irq_chip_icu::unbind(irq); +} + diff --git a/kernel/fiasco/src/kern/ia32/irq_chip_pic.cpp b/kernel/fiasco/src/kern/ia32/irq_chip_pic.cpp new file mode 100644 index 00000000..323cafe7 --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/irq_chip_pic.cpp @@ -0,0 +1,153 @@ +INTERFACE: + +#include "irq_chip_ia32.h" + +/** + * IRQ Chip based on the IA32 legacy PIC. + * + * Vectors for the PIC are from 0x20 to 0x2f statically assigned. + */ +class Irq_chip_ia32_pic : public Irq_chip_ia32 +{ +public: + char const *chip_type() const { return "PIC"; } +}; + + +IMPLEMENTATION: + +#include + +#include "boot_alloc.h" +#include "cpu_lock.h" +#include "globalconfig.h" +#include "globals.h" +#include "irq_mgr.h" +#include "pic.h" + +PUBLIC inline +Irq_chip_ia32_pic::Irq_chip_ia32_pic() : Irq_chip_ia32(16) +{} + +PUBLIC +bool +Irq_chip_ia32_pic::alloc(Irq_base *irq, Mword irqn) +{ + // no mor than 16 IRQs + if (irqn > 0xf) + return false; + + // PIC uses vectors from 0x20 to 0x2f statically + unsigned vector = 0x20 + irqn; + + return valloc(irq, irqn, vector); +} + + +PUBLIC +void +Irq_chip_ia32_pic::mask(Mword irq) +{ + Pic::disable_locked(irq); +} + + +PUBLIC +void +Irq_chip_ia32_pic::mask_and_ack(Mword irq) +{ + Pic::disable_locked(irq); + Pic::acknowledge_locked(irq); +} + +PUBLIC +void +Irq_chip_ia32_pic::ack(Mword irq) +{ + Pic::acknowledge_locked(irq); +} + +PUBLIC +unsigned +Irq_chip_ia32_pic::set_mode(Mword, unsigned) +{ return Irq_base::Trigger_level | Irq_base::Polarity_low; } + +PUBLIC +void +Irq_chip_ia32_pic::unmask(Mword irq) +{ + Pic::enable_locked(irq, 0xa); //prio); +#if 0 + unsigned long prio; + + if (EXPECT_FALSE(!Irq::self(this)->owner())) + return; + if (Irq::self(this)->owner() == (Receiver*)-1) + prio = ~0UL; // highes prio for JDB IRQs + else + prio = Irq::self(this)->owner()->sched()->prio(); +#endif + +} + +PUBLIC +void +Irq_chip_ia32_pic::set_cpu(Mword, unsigned) +{} + + +class Pic_irq_mgr : public Irq_mgr +{ +private: + mutable Irq_chip_ia32_pic _pic; +}; + +PUBLIC Irq_mgr::Irq +Pic_irq_mgr::chip(Mword irq) const +{ + if (irq < 16) + return Irq(&_pic, irq); + + return Irq(); +} + +PUBLIC +unsigned +Pic_irq_mgr::nr_irqs() const +{ + return 16; +} + +PUBLIC +unsigned +Pic_irq_mgr::nr_msis() const +{ return 0; } + + +// ------------------------------------------------------------------------ +IMPLEMENTATION [ux]: + +PUBLIC static FIASCO_INIT +void +Irq_chip_ia32_pic::init() +{ + Irq_mgr::mgr = new Boot_object(); +} + +// ------------------------------------------------------------------------ +IMPLEMENTATION [!ux]: + +PUBLIC static FIASCO_INIT +void +Irq_chip_ia32_pic::init() +{ + Irq_mgr::mgr = new Boot_object(); + // + // initialize interrupts + // + Irq_mgr::mgr->reserve(2); // reserve cascade irq + Irq_mgr::mgr->reserve(7); // reserve spurious vect + Irq_mgr::mgr->reserve(0xf); // reserve spurious vect + + Pic::enable_locked(2); // allow cascaded irqs +} diff --git a/kernel/fiasco/src/kern/ia32/irq_msi.cpp b/kernel/fiasco/src/kern/ia32/irq_msi.cpp new file mode 100644 index 00000000..b9cc8a99 --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/irq_msi.cpp @@ -0,0 +1,137 @@ +IMPLEMENTATION: + +#include "idt.h" +#include "irq_chip.h" +#include "irq_mgr.h" +#include "irq_chip_ia32.h" + +#include "apic.h" +#include "static_init.h" +#include "boot_alloc.h" + +class Irq_chip_msi : public Irq_chip_ia32 +{ +public: + // this is somehow arbitrary + enum { Max_msis = 0x40 }; + Irq_chip_msi() : Irq_chip_ia32(Max_msis) {} +}; + +class Irq_mgr_msi : public Irq_mgr +{ +private: + mutable Irq_chip_msi _chip; + Irq_mgr *_orig; +}; + +PUBLIC inline +char const * +Irq_chip_msi::chip_type() const +{ return "MSI"; } + +PUBLIC +bool +Irq_chip_msi::alloc(Irq_base *irq, Mword pin) +{ + return valloc(irq, pin, 0); +} + +PUBLIC +void +Irq_chip_msi::unbind(Irq_base *irq) +{ + extern char entry_int_apic_ignore[]; + //Mword n = irq->pin(); + // hm: no way to mask an MSI: mask(n); + vfree(irq, &entry_int_apic_ignore); + Irq_chip_icu::unbind(irq); +} + +PUBLIC +Mword +Irq_chip_msi::msg(Mword pin) +{ + if (pin < _irqs) + return _entry[pin].vector(); + + return 0; +} + +PUBLIC unsigned +Irq_chip_msi::set_mode(Mword, unsigned) +{ return Irq_base::Trigger_edge | Irq_base::Polarity_low; } + +PUBLIC void +Irq_chip_msi::set_cpu(Mword, unsigned) +{} + +PUBLIC void +Irq_chip_msi::mask(Mword) +{} + +PUBLIC void +Irq_chip_msi::ack(Mword) +{ ::Apic::irq_ack(); } + +PUBLIC void +Irq_chip_msi::mask_and_ack(Mword) +{ ::Apic::irq_ack(); } + +PUBLIC void +Irq_chip_msi::unmask(Mword) +{} + + +PUBLIC inline explicit +Irq_mgr_msi::Irq_mgr_msi(Irq_mgr *o) : _orig(o) {} + +PUBLIC Irq_mgr::Irq +Irq_mgr_msi::chip(Mword irq) const +{ + if (irq & 0x80000000) + return Irq(&_chip, irq & ~0x80000000); + else + return _orig->chip(irq); +} + +PUBLIC +unsigned +Irq_mgr_msi::nr_irqs() const +{ return _orig->nr_irqs(); } + +PUBLIC +unsigned +Irq_mgr_msi::nr_msis() const +{ return _chip.nr_irqs(); } + +PUBLIC +Mword +Irq_mgr_msi::msg(Mword irq) const +{ + if (irq & 0x80000000) + return _chip.msg(irq & ~0x80000000); + else + return 0; +} + +PUBLIC unsigned +Irq_mgr_msi::legacy_override(Mword irq) +{ + if (irq & 0x80000000) + return irq; + else + return _orig->legacy_override(irq); +} + + +PUBLIC static FIASCO_INIT +void +Irq_mgr_msi::init() +{ + Irq_mgr_msi *m; + Irq_mgr::mgr = m = new Boot_object(Irq_mgr::mgr); + printf("Enable MSI support: chained IRQ mgr @ %p\n", m->_orig); +} + +STATIC_INITIALIZE(Irq_mgr_msi); + diff --git a/kernel/fiasco/src/kern/ia32/kdb_ke-ia32.cpp b/kernel/fiasco/src/kern/ia32/kdb_ke-ia32.cpp new file mode 100644 index 00000000..a685f597 --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/kdb_ke-ia32.cpp @@ -0,0 +1,15 @@ +INTERFACE [ia32,ux,amd64]: + +#define kdb_ke(msg) \ + asm ("int3 \n\t" \ + "jmp 1f \n\t" \ + ".ascii " #msg " \n\t" \ + "1: \n\t") + +#define kdb_ke_sequence(msg) \ + asm ("int3 \n\t" \ + "jmp 1f \n\t" \ + ".ascii \"*##\" \n\t" \ + "1: \n\t" \ + : : "a"(msg)) + diff --git a/kernel/fiasco/src/kern/ia32/kernel_thread-ia32.cpp b/kernel/fiasco/src/kern/ia32/kernel_thread-ia32.cpp new file mode 100644 index 00000000..3eb77420 --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/kernel_thread-ia32.cpp @@ -0,0 +1,122 @@ + +IMPLEMENTATION[ia32,amd64]: + +#include "apic.h" +#include "config.h" +#include "cpu.h" +#include "io_apic.h" +#include "irq_mgr.h" +#include "koptions.h" +#include "mem_layout.h" +#include "pic.h" +#include "trap_state.h" +#include "watchdog.h" + +IMPLEMENT inline NEEDS["mem_layout.h"] +void +Kernel_thread::free_initcall_section() +{ + // just fill up with invalid opcodes + for (unsigned short *i = (unsigned short *) &Mem_layout::initcall_start; + i < (unsigned short *) &Mem_layout::initcall_end; i++) + *i = 0x0b0f; // UD2 opcode +} + + +IMPLEMENT FIASCO_INIT +void +Kernel_thread::bootstrap_arch() +{ + // + // install our slow trap handler + // + nested_trap_handler = Trap_state::base_handler; + Trap_state::base_handler = thread_handle_trap; + + // initialize the profiling timer + bool user_irq0 = Koptions::o()->opt(Koptions::F_irq0); + + if ((int)Config::Scheduler_mode == Config::SCHED_PIT && user_irq0) + panic("option -irq0 not possible since irq 0 is used for scheduling"); + + boot_app_cpus(); +} + +//-------------------------------------------------------------------------- +IMPLEMENTATION [!mp]: + +static void inline +Kernel_thread::boot_app_cpus() +{} + + +//-------------------------------------------------------------------------- +IMPLEMENTATION [mp && amd64]: + +PRIVATE inline NOEXPORT +static Address +Kernel_thread::get_startup_pbdr() +{ + // for amd64 we need to make sure that our boot-up page directory is below + // 4GB in physical memory + static char _boot_pdir_page[Config::PAGE_SIZE] __attribute__((aligned(4096))); + memcpy(_boot_pdir_page, Kmem::dir(), sizeof(_boot_pdir_page)); + + return Kmem::virt_to_phys(_boot_pdir_page); +} + +//-------------------------------------------------------------------------- +IMPLEMENTATION [mp && ia32]: + +PRIVATE inline NOEXPORT +static Address +Kernel_thread::get_startup_pbdr() +{ + return Mem_layout::pmem_to_phys(Kmem::dir()); +} + +//-------------------------------------------------------------------------- +IMPLEMENTATION [mp]: + +static void +Kernel_thread::boot_app_cpus() +{ + // sending (INIT-)IPIs on non-MP systems might not work + if ( Cpu::boot_cpu()->vendor() == Cpu::Vendor_amd + && Cpu::amd_cpuid_mnc() < 2) + return; + + // where to start the APs for detection of the APIC-IDs + extern char _tramp_mp_entry[]; + + // feature enabling flags (esp. cache enabled flag and paging enabled flag) + extern volatile Mword _tramp_mp_startup_cr0; + + // feature enabling flags (esp. needed for big pages) + extern volatile Mword _tramp_mp_startup_cr4; + + // physical address of the page table directory to use + extern volatile Address _tramp_mp_startup_pdbr; + + // pseudo descriptor for the gdt to load + extern Pseudo_descriptor _tramp_mp_startup_gdt_pdesc; + + Address tramp_page; + + _tramp_mp_startup_pdbr = get_startup_pbdr(); + _tramp_mp_startup_cr4 = Cpu::get_cr4(); + _tramp_mp_startup_cr0 = Cpu::get_cr0(); + _tramp_mp_startup_gdt_pdesc + = Pseudo_descriptor((Address)Cpu::boot_cpu()->get_gdt(), Gdt::gdt_max -1); + + __asm__ __volatile__ ("" : : : "memory"); + + // Say what we do + printf("MP: detecting APs...\n"); + + // broadcast an AP startup via the APIC (let run the self-registration code) + tramp_page = (Address)&(_tramp_mp_entry[0]); + + // Send IPI-Sequency to startup the APs + Apic::mp_startup(Cpu::boot_cpu(), Apic::APIC_IPI_OTHERS, tramp_page); +} diff --git a/kernel/fiasco/src/kern/ia32/kip_init-ia32.cpp b/kernel/fiasco/src/kern/ia32/kip_init-ia32.cpp new file mode 100644 index 00000000..ab9f5e52 --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/kip_init-ia32.cpp @@ -0,0 +1,154 @@ +INTERFACE [ia32,ux,amd64]: + +#include "initcalls.h" +#include "types.h" +#include "kip.h" + +class Cpu; + + +class Kip_init +{ +public: + /** + * Insert memory descriptor for the Kmem region and finish the memory + * info field. + * @post no more memory descriptors may be added + */ + static void setup_kmem_region (Address kmem_base, Address kmem_size); +}; + +IMPLEMENTATION [!ux]: + +PRIVATE static inline +void +Kip_init::setup_ux(Kip *) +{} + +IMPLEMENTATION [ia32,ux,amd64]: + +#include +#include "boot_info.h" +#include "config.h" +#include "cpu.h" +#include "div32.h" +#include "kmem.h" +#include "panic.h" + + +/** KIP initialization. */ +PUBLIC static FIASCO_INIT +void +Kip_init::init_freq(Cpu const &cpu) +{ + Kip::k()->frequency_cpu = div32(cpu.frequency(), 1000); +} + + +namespace KIP_namespace +{ + enum + { + Num_mem_descs = 50, + Max_len_version = 512, + + Size_mem_descs = sizeof(Mword) * 2 * Num_mem_descs, + }; + + struct KIP + { + Kip kip; + char mem_descs[Size_mem_descs]; + }; + + KIP my_kernel_info_page asm("my_kernel_info_page") __attribute__((section(".kernel_info_page"))) = + { + { + /* 00/00 */ L4_KERNEL_INFO_MAGIC, + Config::Kernel_version_id, + (Size_mem_descs + sizeof(Kip)) >> 4, + {}, 0, {}, + /* 10/20 */ 0, {}, + /* 20/40 */ 0, 0, {}, + /* 30/60 */ 0, 0, {}, + /* 40/80 */ 0, 0, {}, + /* 50/A0 */ 0, (sizeof(Kip) << (sizeof(Mword)*4)) | Num_mem_descs, {}, + /* 60/C0 */ {}, + /* A0/140 */ 0, 0, 0, 0, + /* B0/160 */ {}, + /* E0/1C0 */ 0, 0, {}, + /* F0/1D0 */ {}, + }, + {} + }; +}; + +PUBLIC static FIASCO_INIT +//IMPLEMENT +void Kip_init::init() +{ + Kip *kinfo = reinterpret_cast(&KIP_namespace::my_kernel_info_page); + setup_ux(kinfo); + + Kip::init_global_kip(kinfo); + + Kip::k()->clock = 0; + Kip::k()->sched_granularity = Config::Scheduler_granularity; + + setup_user_virtual(kinfo); + + reserve_amd64_hole(); + + + Mem_desc *md = kinfo->mem_descs(); + Mem_desc *end = md + kinfo->num_mem_descs(); + + extern char _boot_sys_start[]; + extern char _boot_sys_end[]; + + for (;md != end; ++md) + { + if (md->type() != Mem_desc::Reserved || md->is_virtual()) + continue; + + if (md->start() == (Address)_boot_sys_start + && md->end() == (Address)_boot_sys_end - 1) + md->type(Mem_desc::Undefined); + + if (md->contains(Kmem::kernel_image_start()) + && md->contains(Kmem::kcode_end()-1)) + { + *md = Mem_desc(Kmem::kernel_image_start(), Kmem::kcode_end() -1, + Mem_desc::Reserved); + } + } +} + + +IMPLEMENTATION [amd64]: + +PRIVATE static inline NOEXPORT NEEDS["kip.h"] +void +Kip_init::reserve_amd64_hole() +{ + enum { Trigger = 0x0000800000000000UL }; + Kip::k()->add_mem_region(Mem_desc(Trigger, ~Trigger, + Mem_desc::Reserved, true)); +} + +IMPLEMENTATION [!amd64]: + +PRIVATE static inline NOEXPORT +void +Kip_init::reserve_amd64_hole() +{} + +IMPLEMENTATION [!ux]: + +PUBLIC static FIASCO_INIT +void +Kip_init::setup_user_virtual(Kip *kinfo) +{ + kinfo->add_mem_region(Mem_desc(0, Mem_layout::User_max - 1, + Mem_desc::Conventional, true)); +} diff --git a/kernel/fiasco/src/kern/ia32/kmem-ia32.cpp b/kernel/fiasco/src/kern/ia32/kmem-ia32.cpp new file mode 100644 index 00000000..d9c8d390 --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/kmem-ia32.cpp @@ -0,0 +1,575 @@ +// our own implementation of C++ memory management: disallow dynamic +// allocation (except where class-specific new/delete functions exist) +// +// more specialized memory allocation/deallocation functions follow +// below in the "Kmem" namespace + +INTERFACE [ia32,amd64,ux]: + +#include "globalconfig.h" +#include "initcalls.h" +#include "kip.h" +#include "mem_layout.h" + +class Cpu; +class Pdir; +class Tss; + +class Device_map +{ +public: + enum + { + Max = 16, + Virt_base = 0x20000000, + }; + +private: + Address _map[Max]; + +}; + +/** + * The system's base facilities for kernel-memory management. + * The kernel memory is a singleton object. We access it through a + * static class interface. + */ +class Kmem : public Mem_layout +{ + friend class Device_map; + friend class Jdb; + friend class Jdb_dbinfo; + friend class Jdb_kern_info_misc; + friend class Kdb; + friend class Profile; + friend class Vmem_alloc; + +private: + Kmem(); // default constructors are undefined + Kmem (const Kmem&); + static unsigned long pmem_cpu_page, cpu_page_vm; + +public: + static Device_map dev_map; + + enum + { + mem_user_max = Mem_layout::User_max, + }; + + static void init_pageing(Cpu const &boot_cpu); + static void init_boot_cpu(Cpu const &boot_cpu); + static void init_app_cpu(Cpu const &cpu); + static Mword is_kmem_page_fault(Address pfa, Mword error); + static Mword is_ipc_page_fault(Address pfa, Mword error); + static Mword is_io_bitmap_page_fault(Address pfa); + static Address kcode_start(); + static Address kcode_end(); + static Address virt_to_phys(const void *addr); + +}; + +typedef Kmem Kmem_space; + + +//---------------------------------------------------------------------------- +INTERFACE [ia32, amd64]: + +EXTENSION +class Kmem +{ + friend class Kernel_task; + +public: + static Address user_max(); + +private: + static Unsigned8 *io_bitmap_delimiter; + static Address kphys_start, kphys_end; + static Pdir *kdir; ///< Kernel page directory +}; + + +//-------------------------------------------------------------------------- +IMPLEMENTATION [ia32, amd64]: + +#include "cpu.h" +#include "l4_types.h" +#include "kmem_alloc.h" +#include "mem_unit.h" +#include "panic.h" +#include "paging.h" +#include "pic.h" +#include "std_macros.h" + +#include + +PUBLIC +void +Device_map::init() +{ + for (unsigned i = 0; i < Max; ++i) + _map[i] = ~0UL; +} + +PRIVATE +unsigned +Device_map::lookup_idx(Address phys) +{ + Address p = phys & (~0UL << Config::SUPERPAGE_SHIFT); + for (unsigned i = 0; i < Max; ++i) + if (p == _map[i]) + return i; + + return ~0U; +} + + +PUBLIC +template< typename T > +T * +Device_map::lookup(T *phys) +{ + unsigned idx = lookup_idx((Address)phys); + if (idx == ~0U) + return (T*)~0UL; + + return (T*)((Virt_base + idx * Config::SUPERPAGE_SIZE) + | ((Address)phys & ~(~0UL << Config::SUPERPAGE_SHIFT))); +} + +PRIVATE +Address +Device_map::map(Address phys, bool /*cache*/) +{ + unsigned idx = lookup_idx(phys); + if (idx != ~0U) + return (Virt_base + idx * Config::SUPERPAGE_SIZE) + | (phys & ~(~0UL << Config::SUPERPAGE_SHIFT)); + + Address p = phys & (~0UL << Config::SUPERPAGE_SHIFT); + Kmem_alloc *const alloc = Kmem_alloc::allocator(); + for (unsigned i = 0; i < Max; ++i) + if (_map[i] == ~0UL) + { + Kmem::kdir->map(p, + Virt_addr(Virt_base + (i*Config::SUPERPAGE_SIZE)), + Virt_size(Config::SUPERPAGE_SIZE), + Pt_entry::Dirty | Pt_entry::Writable | Pt_entry::Referenced, + Pdir::super_level(), pdir_alloc(alloc)); + _map[i] = p; + + return (Virt_base + (i*Config::SUPERPAGE_SIZE)) + | (phys & ~(~0UL << Config::SUPERPAGE_SHIFT)); + } + + return ~0UL; +} + +PUBLIC +template< typename T > +T * +Device_map::map(T *phys, bool cache = true) +{ return (T*)map((Address)phys, cache); } + +PUBLIC +void +Device_map::unmap(void const *phys) +{ + unsigned idx = lookup_idx((Address)phys); + if (idx == ~0U) + return; + + Address v = Virt_base + (idx * Config::SUPERPAGE_SIZE); + + Kmem::kdir->unmap(Virt_addr(v), Virt_size(Config::SUPERPAGE_SIZE), -1); +} + + +Unsigned8 *Kmem::io_bitmap_delimiter; +Address Kmem::kphys_start, Kmem::kphys_end; +Device_map Kmem::dev_map; + + +PUBLIC static inline +Address +Kmem::io_bitmap_delimiter_page() +{ + return reinterpret_cast
(io_bitmap_delimiter); +} + + +/** + * Compute physical address from a kernel-virtual address. + * @param addr a virtual address + * @return corresponding physical address if a mappings exists. + * -1 otherwise. + */ +IMPLEMENT inline NEEDS["paging.h","std_macros.h","mem_layout.h"] +Address +Kmem::virt_to_phys(const void *addr) +{ + Address a = reinterpret_cast
(addr); + + if (EXPECT_TRUE(Mem_layout::in_pmem(a))) + return Mem_layout::pmem_to_phys(a); + + if (EXPECT_TRUE(Mem_layout::in_kernel_image(a))) + return a - Mem_layout::Kernel_image_offset; + + return kdir->virt_to_phys(a); +} + + +// Only used for initialization and kernel debugger +PUBLIC static +Address +Kmem::map_phys_page_tmp(Address phys, Mword idx) +{ + unsigned long pte = phys & Pt_entry::Pfn; + Address virt; + + switch (idx) + { + case 0: virt = Mem_layout::Kmem_tmp_page_1; break; + case 1: virt = Mem_layout::Kmem_tmp_page_2; break; + default: return ~0UL; + } + + static unsigned long tmp_phys_pte[2] = { ~0UL, ~0UL }; + + if (pte != tmp_phys_pte[idx]) + { + // map two consecutive pages as to be able to access + map_phys_page(phys, virt, false, true); + map_phys_page(phys+0x1000, virt+0x1000, false, true); + tmp_phys_pte[idx] = pte; + } + + return virt + phys - pte; +} + +PUBLIC static inline +Address Kmem::kernel_image_start() +{ return virt_to_phys(&Mem_layout::image_start) & Config::PAGE_MASK; } + +IMPLEMENT inline Address Kmem::kcode_start() +{ return virt_to_phys(&Mem_layout::start) & Config::PAGE_MASK; } + +IMPLEMENT inline Address Kmem::kcode_end() +{ + return (virt_to_phys(&Mem_layout::end) + Config::PAGE_SIZE) + & Config::PAGE_MASK; +} + + +/** Return number of IPC slots to copy */ +PUBLIC static inline NEEDS["config.h"] +unsigned +Kmem::ipc_slots() +{ return (8 << 20) / Config::SUPERPAGE_SIZE; } + +IMPLEMENT inline NEEDS["mem_layout.h"] +Mword +Kmem::is_io_bitmap_page_fault(Address addr) +{ + return addr >= Mem_layout::Io_bitmap && + addr <= Mem_layout::Io_bitmap + Mem_layout::Io_port_max / 8; +} + +IMPLEMENT inline NEEDS["mem_layout.h"] +Mword +Kmem::is_kmem_page_fault(Address addr, Mword /*error*/) +{ + return addr >= mem_user_max; +} + + +// +// helper functions +// + +// Establish a 4k-mapping +PUBLIC static +void +Kmem::map_phys_page(Address phys, Address virt, + bool cached, bool global, Address *offs=0) +{ + Pdir::Iter i = kdir->walk(Virt_addr(virt), 100, pdir_alloc(Kmem_alloc::allocator())); + Pte_base *e = i.e; + Mword pte = phys & Config::PAGE_MASK; + + assert(i.shift() == Config::PAGE_SHIFT); + + *e = pte | Pt_entry::Valid | Pt_entry::Writable + | Pt_entry::Referenced | Pt_entry::Dirty + | (cached ? 0 : (Pt_entry::Write_through | Pt_entry::Noncacheable)) + | (global ? Pt_entry::global() : 0); + Mem_unit::tlb_flush(virt); + + if (offs) + *offs = phys - pte; +} + + +PUBLIC static FIASCO_INIT +void +Kmem::init_mmu() +{ + dev_map.init(); + Kmem_alloc *const alloc = Kmem_alloc::allocator(); + + kdir = (Pdir*)alloc->alloc(Config::PAGE_SHIFT); + memset (kdir, 0, Config::PAGE_SIZE); + + unsigned long cpu_features = Cpu::get_features(); + bool superpages = cpu_features & FEAT_PSE; + + printf("Superpages: %s\n", superpages?"yes":"no"); + + Pdir::have_superpages(superpages); + if (superpages) + Cpu::set_cr4(Cpu::get_cr4() | CR4_PSE); + + if (cpu_features & FEAT_PGE) + { + Pt_entry::enable_global(); + Cpu::set_cr4 (Cpu::get_cr4() | CR4_PGE); + } + + // set up the kernel mapping for physical memory. mark all pages as + // referenced and modified (so when touching the respective pages + // later, we save the CPU overhead of marking the pd/pt entries like + // this) + + // we also set up a one-to-one virt-to-phys mapping for two reasons: + // (1) so that we switch to the new page table early and re-use the + // segment descriptors set up by boot_cpu.cc. (we'll set up our + // own descriptors later.) we only need the first 4MB for that. + // (2) a one-to-one phys-to-virt mapping in the kernel's page directory + // sometimes comes in handy (mostly useful for debugging) + + // first 4MB page + kdir->map(0, Virt_addr(0), Virt_size(4 << 20), + Pt_entry::Dirty | Pt_entry::Writable | Pt_entry::Referenced, + Pdir::super_level(), pdir_alloc(alloc)); + + + kdir->map(Mem_layout::Kernel_image_phys, + Virt_addr(Mem_layout::Kernel_image), + Virt_size(Config::SUPERPAGE_SIZE), + Pt_entry::Dirty | Pt_entry::Writable | Pt_entry::Referenced + | Pt_entry::global(), Pdir::super_level(), pdir_alloc(alloc)); + + if (!Mem_layout::Adap_in_kernel_image) + kdir->map(Mem_layout::Adap_image_phys, + Virt_addr(Mem_layout::Adap_image), + Virt_size(Config::SUPERPAGE_SIZE), + Pt_entry::Dirty | Pt_entry::Writable | Pt_entry::Referenced + | Pt_entry::global(), Pdir::super_level(), pdir_alloc(alloc)); + + // map the last 64MB of physical memory as kernel memory + kdir->map(Mem_layout::pmem_to_phys(Mem_layout::Physmem), + Virt_addr(Mem_layout::Physmem), Virt_size(Mem_layout::pmem_size), + Pt_entry::Writable | Pt_entry::Referenced | Pt_entry::global(), + Pdir::super_level(), pdir_alloc(alloc)); + + // The service page directory entry points to an universal usable + // page table which is currently used for the Local APIC and the + // jdb adapter page. + assert((Mem_layout::Service_page & ~Config::SUPERPAGE_MASK) == 0); + + Pdir::Iter pt = kdir->walk(Virt_addr(Mem_layout::Service_page), 100, pdir_alloc(alloc)); + + // kernel mode should acknowledge write-protected page table entries + Cpu::set_cr0(Cpu::get_cr0() | CR0_WP); + + // now switch to our new page table + Cpu::set_pdbr(Mem_layout::pmem_to_phys(kdir)); + + assert((Mem_layout::Io_bitmap & ~Config::SUPERPAGE_MASK) == 0); + + long cpu_page_size + = 0x10 + Config::Max_num_cpus * (sizeof(Tss) + 256); + + if (cpu_page_size < Config::PAGE_SIZE) + cpu_page_size = Config::PAGE_SIZE; + + pmem_cpu_page = Mem_layout::pmem_to_phys(alloc->unaligned_alloc(cpu_page_size)); + + printf("Kmem:: cpu page at %lx (%ldBytes)\n", pmem_cpu_page, cpu_page_size); + + if (superpages + && Config::SUPERPAGE_SIZE - (pmem_cpu_page & ~Config::SUPERPAGE_MASK) < 0x10000) + { + // can map as 4MB page because the cpu_page will land within a + // 16-bit range from io_bitmap + *(kdir->walk(Virt_addr(Mem_layout::Io_bitmap - Config::SUPERPAGE_SIZE), + Pdir::Super_level, pdir_alloc(alloc)).e) + = (pmem_cpu_page & Config::SUPERPAGE_MASK) + | Pt_entry::Pse_bit + | Pt_entry::Writable | Pt_entry::Referenced + | Pt_entry::Dirty | Pt_entry::global() | Pt_entry::Valid; + + cpu_page_vm = (pmem_cpu_page & ~Config::SUPERPAGE_MASK) + + (Mem_layout::Io_bitmap - Config::SUPERPAGE_SIZE); + } + else + { + unsigned i; + for (i = 0; cpu_page_size > 0; ++i, cpu_page_size -= Config::PAGE_SIZE) + { + pt = kdir->walk(Virt_addr(Mem_layout::Io_bitmap - Config::PAGE_SIZE * (i+1)), + 100, pdir_alloc(alloc)); + + *pt.e = (pmem_cpu_page + i*Config::PAGE_SIZE) + | Pt_entry::Valid | Pt_entry::Writable + | Pt_entry::Referenced | Pt_entry::Dirty + | Pt_entry::global(); + } + + cpu_page_vm = Mem_layout::Io_bitmap - Config::PAGE_SIZE * i; + } + + // the IO bitmap must be followed by one byte containing 0xff + // if this byte is not present, then one gets page faults + // (or general protection) when accessing the last port + // at least on a Pentium 133. + // + // Therefore we write 0xff in the first byte of the cpu_page + // and map this page behind every IO bitmap + io_bitmap_delimiter = + reinterpret_cast(cpu_page_vm); + + cpu_page_vm += 0x10; + + // did we really get the first byte ?? + assert((reinterpret_cast
(io_bitmap_delimiter) + & ~Config::PAGE_MASK) == 0); + *io_bitmap_delimiter = 0xff; +} + + +PUBLIC static FIASCO_INIT_CPU +void +Kmem::init_cpu(Cpu &cpu) +{ + + void *cpu_mem = Kmem_alloc::allocator()->unaligned_alloc(1024); + printf("Allocate cpu_mem @ %p\n", cpu_mem); + + // now initialize the global descriptor table + cpu.init_gdt (__alloc(&cpu_mem, Gdt::gdt_max), user_max()); + + // Allocate the task segment as the last thing from cpu_page_vm + // because with IO protection enabled the task segment includes the + // rest of the page and the following IO bitmap (2 pages). + // + // Allocate additional 256 bytes for emergency stack right beneath + // the tss. It is needed if we get an NMI or debug exception at + // entry_sys_fast_ipc/entry_sys_fast_ipc_c/entry_sys_fast_ipc_log. + Address tss_mem = alloc_tss(sizeof(Tss) + 256); + assert(tss_mem + sizeof(Tss) + 256 < Mem_layout::Io_bitmap); + size_t tss_size; + tss_mem += 256; + + // this is actually tss_size +1, including the io_bitmap_delimiter byte + tss_size = Mem_layout::Io_bitmap + (Mem_layout::Io_port_max / 8) - tss_mem; + + assert(tss_size < 0x100000); // must fit into 20 Bits + + cpu.init_tss(tss_mem, tss_size); + + // force GDT... to memory before loading the registers + asm volatile ( "" : : : "memory" ); + + // set up the x86 CPU's memory model + cpu.set_gdt(); + cpu.set_ldt(0); + + cpu.set_ds(Gdt::data_segment()); + cpu.set_es(Gdt::data_segment()); + cpu.set_ss(Gdt::gdt_data_kernel | Gdt::Selector_kernel); + cpu.set_fs(Gdt::gdt_data_user | Gdt::Selector_user); + cpu.set_gs(Gdt::gdt_data_user | Gdt::Selector_user); + cpu.set_cs(); + + // and finally initialize the TSS + cpu.set_tss(); + + init_cpu_arch(cpu, &cpu_mem); +} + + +//--------------------------------------------------------------------------- +IMPLEMENTATION [ia32 || amd64]: + +IMPLEMENT inline Address Kmem::user_max() { return ~0UL; } + + +//-------------------------------------------------------------------------- +IMPLEMENTATION [ia32,ux,amd64]: + +#include +#include // size_t +#include // memset + +#include "boot_info.h" +#include "config.h" +#include "cpu.h" +#include "gdt.h" +#include "globals.h" +#include "paging.h" +#include "regdefs.h" +#include "std_macros.h" +#include "tss.h" + +// static class variables +unsigned long Kmem::pmem_cpu_page, Kmem::cpu_page_vm; +Pdir *Kmem::kdir; + + +static inline Address FIASCO_INIT_CPU +Kmem::__alloc(void **p, unsigned long size) +{ + Address r = ((unsigned long)*p + 0xf) & ~0xf; + *p = (void*)(r + size); + return r; +} + +/** + * Compute a kernel-virtual address for a physical address. + * This function always returns virtual addresses within the + * physical-memory region. + * @pre addr <= highest kernel-accessible RAM address + * @param addr a physical address + * @return kernel-virtual address. + */ +PUBLIC static inline +void * +Kmem::phys_to_virt(Address addr) +{ + return reinterpret_cast(Mem_layout::phys_to_pmem(addr)); +} + +/** Allocate some bytes from a memory page */ +PUBLIC static inline +Address +Kmem::alloc_tss(Address size) +{ + Address ret = cpu_page_vm; + cpu_page_vm += (size + 0xf) & ~0xf; + + return ret; +} + + +/** + * Return Global page directory. + * This is the master copy of the kernel's page directory. Kernel-memory + * allocations are kept here and copied to task page directories lazily + * upon page fault. + * @return kernel's global page directory + */ +PUBLIC static inline const Pdir* Kmem::dir() { return kdir; } + diff --git a/kernel/fiasco/src/kern/ia32/kmem_alloc-ia32.cpp b/kernel/fiasco/src/kern/ia32/kmem_alloc-ia32.cpp new file mode 100644 index 00000000..822a6e85 --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/kmem_alloc-ia32.cpp @@ -0,0 +1,171 @@ +// base_init() puts those Mem_region_map's on the stack which is slightly +// larger than our warning limit, it's init code only, so it's ok +#pragma GCC diagnostic ignored "-Wframe-larger-than=" + +IMPLEMENTATION [ia32,ux,amd64]: + +#include + +#include "kip.h" +#include "koptions.h" +#include "mem_region.h" +#include "panic.h" +#include "types.h" + +PUBLIC static FIASCO_INIT +bool +Kmem_alloc::base_init() +{ + //printf("Kmem_alloc::base_init(): kip=%p\n", Kip::k()); + unsigned long available_size = 0; + unsigned long requested_size; + + Mem_region_map<64> map; + //Kip::k()->add_mem_region(Mem_desc(0xc7ed000, 0xfeecfff, Mem_desc::Reserved)); + //Kip::k()->add_mem_region(Mem_desc(0xea00000, 0xfeecfff, Mem_desc::Reserved)); + + available_size = create_free_map(Kip::k(), &map); + + requested_size = Koptions::o()->kmemsize << 10; + if (!requested_size) + { + requested_size = available_size / 100 * Config::kernel_mem_per_cent; + if (requested_size > Config::kernel_mem_max) + requested_size = Config::kernel_mem_max; + } + + if (requested_size > (0-Mem_layout::Physmem)) + requested_size = 0-Mem_layout::Physmem; // maximum mappable memory + + requested_size = (requested_size + Config::PAGE_SIZE - 1) + & ~(Config::PAGE_SIZE - 1); + + //printf("Kmem_alloc: available_memory=%lu KB requested_size=%lu\n", + // available_size / 1024, requested_size / 1024); + + //printf("Kmem_alloc:: available blocks:\n"); + //for (unsigned i = 0; i < map.length(); ++i) + // printf(" %2u [%014lx; %014lx)\n", i, map[i].start, map[i].end+1); + + unsigned long base = 0; + unsigned long sp_base = 0; + unsigned long end = map[map.length()-1].end; + unsigned last = map.length(); + unsigned i; + unsigned long size = requested_size; + for (i = last; i > 0 && size > 0; --i) + { + if (map[i-1].size() >= size) + { // next block is sufficient + base = map[i-1].end - size + 1; + sp_base = base & ~(Config::SUPERPAGE_SIZE-1); + if ((end - sp_base + 1) > (0-Mem_layout::Physmem)) + { + if (last == i) + { // already a single block, try to align + if (sp_base >= map[i-1].start) + { + base = sp_base; + end = sp_base + size -1; + size = 0; + } + continue; + } + else if (last > 1) + { // too much virtual memory, try other blocks + // free last block + size += map[last-1].size(); + end = map[last-2].end; + --last; + ++i; // try same block again + continue; + } + } + else + size = 0; + } + else + size -= map[i-1].size(); + } + + if (size) + return false; + + //printf("Kmem_alloc: kernel memory from %014lx to %014lx\n", base, end+1); + //printf("Kmem_alloc: blocks %u-%u\n", i, last-1); + + Kip::k()->add_mem_region(Mem_desc(base, + end <= map[i].end ? end : map[i].end, Mem_desc::Kernel_tmp)); + ++i; + for (; i < last; ++i) + Kip::k()->add_mem_region(Mem_desc(map[i].start, map[i].end, Mem_desc::Kernel_tmp)); + + Mem_layout::kphys_base(sp_base); + Mem_layout::pmem_size = (end + 1 - sp_base + Config::SUPERPAGE_SIZE - 1) & ~(Config::SUPERPAGE_SIZE-1); + return true; +} + +IMPLEMENT +Kmem_alloc::Kmem_alloc() +{ + //printf("Kmem_alloc::Kmem_alloc()\n"); + Mem_desc *md = Kip::k()->mem_descs(); + Mem_desc const *const md_end = md + Kip::k()->num_mem_descs(); + bool initialized = false; + + for (; md < md_end; ++md) + { + if (md->is_virtual()) + continue; + + unsigned long s = md->start(), e = md->end(); + + // Speep out stupid descriptors (that have the end before the start) + if (s>=e) + { + md->type(Mem_desc::Undefined); + continue; + } + + if (md->type() == Mem_desc::Kernel_tmp) + { + unsigned long s_v = Mem_layout::phys_to_pmem(s); + if (!initialized) + { + initialized = true; + a->init(s_v & ~(Kmem_alloc::Alloc::Max_size - 1)); + //printf("Kmem_alloc: allocator base = %014lx\n", s_v & ~(Kmem_alloc::Alloc::Max_size - 1)); + } + //printf(" Kmem_alloc: block %014lx(%014lx) size=%lx\n", s_v, s, e - s + 1); + a->add_mem((void*)s_v, e - s + 1); + md->type(Mem_desc::Reserved); + _orig_free += e - s + 1; + } + } + //printf("Kmem_alloc: construction done\n"); +} + +//----------------------------------------------------------------------------- +IMPLEMENTATION [{ia32,ux,amd64}-debug]: + +#include "div32.h" + +PUBLIC +void +Kmem_alloc::debug_dump() +{ + a->dump(); + + unsigned long free = a->avail(); + printf("Used %ld%%, %ldKB out of %ldKB of Kmem\n", + (unsigned long) div32(100ULL * (orig_free() - free), orig_free()), + (orig_free() - free + 1023)/1024, + (orig_free() + 1023)/1024); +} + +PRIVATE inline +unsigned long +Kmem_alloc::orig_free() +{ + return _orig_free; +} diff --git a/kernel/fiasco/src/kern/ia32/loadcnt.cpp b/kernel/fiasco/src/kern/ia32/loadcnt.cpp new file mode 100644 index 00000000..fc714425 --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/loadcnt.cpp @@ -0,0 +1,20 @@ +IMPLEMENTATION[ia32,amd64]: + +#include +#include "koptions.h" +#include "perf_cnt.h" +#include "static_init.h" + +class Loadcnt +{ +}; + +STATIC_INITIALIZE_P(Loadcnt, WATCHDOG_INIT); + +PUBLIC static +void FIASCO_INIT_CPU +Loadcnt::init() +{ + if (Koptions::o()->opt(Koptions::F_loadcnt)) + Perf_cnt::setup_loadcnt(); +} diff --git a/kernel/fiasco/src/kern/ia32/logdefs.h b/kernel/fiasco/src/kern/ia32/logdefs.h new file mode 100644 index 00000000..7713a55c --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/logdefs.h @@ -0,0 +1,240 @@ +#ifndef LOGDEFS_H +#define LOGDEFS_H + +// ### How to create a tracebuffer entry ### +// +// If you only need a temporary debugging aid then you can use one of +// the standard kernel logging events: +// +// LOG_MSG(Context *context, const char *msg) +// - context is something like context_of(this) or current_context() +// or 0 if there is no context available +// - msg should be displayed in the tracebuffer view +// +// LOG_MSG_3VAL(Context *context, const char *msg, +// Mword val1, Mword val2, Mword val3) +// - context and msg can be used the same way LOG_MSG does +// - val1, val2, and val3 are values that will be displayed in +// the tracebuffer view as hexadecimal values +// +// If you want to create a permanent log event xyz, you have to follow +// these instructions: +// - create enum Log_event_xyz (see jdb_ktrace.cpp) +// - create class Tb_entry_xyz derived from Tb_entry (see tb_entry.cpp) +// with an appropriate ::set method and with accessor methods +// - create function formatter_xyz (see tb_entry_output.cpp) and don't +// forget to register it (add an appropriate line to init_formatters) +// - create macro LOG_XYZ (see the following example) +// #define LOG_XYZ +// BEGIN_LOG_EVENT(log_xyz) +// Lock_guard guard (&cpu_lock); +// Tb_entry_xyz *tb = +// static_cast(Jdb_tbuf::new_entry()); +// tb->set (this, ) +// Jdb_tbuf::commit_entry(); +// END_LOG_EVENT +// (grabbing the cpu_lock isn't necessary if it is still grabbed) +// - create an empty macro declaration for CONFIG_JDB_LOGGING=n +// - insert the macro call into the code +// - WARNING: permanent log events should _not_ be placed into an inline +// function! +// - add +// DECLARE_PATCH (lp, log_xyz); +// static Log_event le(, +// Log_event_xyz, 1, &lp); +// and create an entry le for Jdb_tbuf_events::log_events[] +// (see jdb_tbuf_events.cpp) + +#include "globalconfig.h" + +#if defined(CONFIG_JDB) + +#include "globals.h" +#include "jdb_tbuf.h" +#include "cpu_lock.h" +#include "lock_guard.h" +#include "processor.h" + +#define LOG_CONTEXT_SWITCH \ + BEGIN_LOG_EVENT("Context switch", "csw", 0) \ + Tb_entry_ctx_sw *tb = \ + static_cast(Jdb_tbuf::new_entry()); \ + tb->set(this, space(), regs()->ip_syscall_page_user(), t, t_orig, \ + t_orig->lock_cnt(), current_sched(), \ + current_sched() ? current_sched()->prio() : 0, \ + (Mword)__builtin_return_address(0)); \ + Jdb_tbuf::commit_entry(); \ + END_LOG_EVENT + + +#define LOG_TRAP \ + BEGIN_LOG_EVENT("Exceptions", "exc", 0) \ + if (ts->_trapno != 1 && ts->_trapno != 3) \ + { \ + Tb_entry_trap *tb = \ + static_cast(Jdb_tbuf::new_entry()); \ + tb->set(this, ts->ip(), ts); \ + Jdb_tbuf::commit_entry(); \ + } \ + END_LOG_EVENT + +#define LOG_TRAP_N(n) \ + BEGIN_LOG_EVENT("Exception n", "exc", 0) \ + Tb_entry_trap *tb = \ + static_cast(Jdb_tbuf::new_entry()); \ + Mword ip = (Mword)(__builtin_return_address(0)); \ + tb->set(current(), ip, n); \ + Jdb_tbuf::commit_entry(); \ + END_LOG_EVENT + +#define LOG_PF_RES_USER \ + BEGIN_LOG_EVENT("Page-fault results", "pfr", 0) \ + Tb_entry_pf_res *tb = \ + static_cast(Jdb_tbuf::new_entry()); \ + tb->set(this, regs()->ip_syscall_page_user(), pfa, err, ret); \ + Jdb_tbuf::commit_entry(); \ + END_LOG_EVENT + +#define LOG_SCHED_SAVE(cs) \ + BEGIN_LOG_EVENT("Scheduling context save", "sch", 0) \ + Tb_entry_sched *tb = \ + static_cast(Jdb_tbuf::new_entry()); \ + tb->set (current(), 0, 0, \ + cs->context(), \ + 0, \ + cs->prio(), \ + cs->left(), \ + cs->quantum()); \ + Jdb_tbuf::commit_entry(); \ + END_LOG_EVENT + +#define LOG_SCHED_LOAD(cs) \ + BEGIN_LOG_EVENT("Scheduling context load", "sch", 0) \ + Tb_entry_sched *tb = \ + static_cast(Jdb_tbuf::new_entry()); \ + tb->set (current(), 0, 1, \ + cs->context(), \ + 0, \ + cs->prio(), \ + cs->left(), \ + cs->quantum()); \ + Jdb_tbuf::commit_entry(); \ + END_LOG_EVENT + +#define LOG_SCHED_INVALIDATE \ + BEGIN_LOG_EVENT("Schduling context invalidate", "sch", 0) \ + Tb_entry_sched *tb = \ + static_cast(Jdb_tbuf::new_entry()); \ + tb->set (current(), current()->regs()->ip_syscall_page_user(), 2, \ + current_sched()->owner(), \ + current_sched()->id(), \ + current_sched()->prio(), \ + timeslice_timeout.cpu(cpu())->get_timeout(Kip::k()->clock), \ + current_sched()->quantum()); \ + Jdb_tbuf::commit_entry(); \ + END_LOG_EVENT + +#define LOG_SEND_PREEMPTION \ + BEGIN_LOG_EVENT("Preemption events", "pre", 0) \ + Lock_guard guard (&cpu_lock); \ + Tb_entry_preemption *tb = \ + static_cast(Jdb_tbuf::new_entry()); \ + tb->set (context_of(this), _receiver.raw(), current()->regs()->ip_syscall_page_user());\ + Jdb_tbuf::commit_entry(); \ + END_LOG_EVENT + +/* + * Kernel instrumentation macro used by fm3. Do not remove! + */ +#define LOG_MSG(context, text) \ + do { \ + /* The cpu_lock is needed since virq::hit() depends on it */ \ + Lock_guard guard (&cpu_lock); \ + Tb_entry_ke *tb = static_cast(Jdb_tbuf::new_entry()); \ + tb->set_const(context, Proc::program_counter(), text); \ + Jdb_tbuf::commit_entry(); \ + } while (0) + +/* + * Kernel instrumentation macro used by fm3. Do not remove! + */ +#define LOG_MSG_3VAL(context, text, v1, v2, v3) \ + do { \ + /* The cpu_lock is needed since virq::hit() depends on it */ \ + Lock_guard guard (&cpu_lock); \ + Tb_entry_ke_reg *tb = \ + static_cast(Jdb_tbuf::new_entry()); \ + tb->set_const(context, Proc::program_counter(), text, v1, v2, v3); \ + Jdb_tbuf::commit_entry(); \ + } while (0) + + +#define LOG_TRACE(name, sc, ctx, fmt, code...) \ + BEGIN_LOG_EVENT(name, sc, fmt) \ + Tb_entry *tbe = Jdb_tbuf::new_entry(); \ + tbe->set_global(__do_log__, ctx, Proc::program_counter()); \ + code; \ + Jdb_tbuf::commit_entry(); \ + END_LOG_EVENT + + +#else + +#define LOG_TRACE(name, sc, ctx, fmt, code...) do { } while (0) +#define LOG_CONTEXT_SWITCH do { } while (0) +#define LOG_TRAP do { } while (0) +#define LOG_TRAP_N(n) do { } while (0) +#define LOG_PF_RES_USER do { } while (0) +#define LOG_SCHED do { } while (0) +#define LOG_SCHED_SAVE(n) do { } while (0) +#define LOG_SCHED_LOAD(n) do { } while (0) +#define LOG_SCHED_INVALIDATE do { } while (0) +#define LOG_SEND_PREEMPTION do { } while (0) + +#endif // CONFIG_JDB + +#if defined(CONFIG_JDB) && defined(CONFIG_JDB_ACCOUNTING) + +#define CNT_CONTEXT_SWITCH \ + Jdb_tbuf::status()->kerncnts[Kern_cnt_context_switch]++; +#define CNT_ADDR_SPACE_SWITCH \ + Jdb_tbuf::status()->kerncnts[Kern_cnt_addr_space_switch]++; +#define CNT_SHORTCUT_FAILED \ + Jdb_tbuf::status()->kerncnts[Kern_cnt_shortcut_failed]++; +#define CNT_SHORTCUT_SUCCESS \ + Jdb_tbuf::status()->kerncnts[Kern_cnt_shortcut_success]++; +#define CNT_IRQ \ + Jdb_tbuf::status()->kerncnts[Kern_cnt_irq]++; +#define CNT_IPC_LONG \ + Jdb_tbuf::status()->kerncnts[Kern_cnt_ipc_long]++; +#define CNT_PAGE_FAULT \ + Jdb_tbuf::status()->kerncnts[Kern_cnt_page_fault]++; +#define CNT_IO_FAULT \ + Jdb_tbuf::status()->kerncnts[Kern_cnt_io_fault]++; +#define CNT_TASK_CREATE \ + Jdb_tbuf::status()->kerncnts[Kern_cnt_task_create]++; +#define CNT_SCHEDULE \ + Jdb_tbuf::status()->kerncnts[Kern_cnt_schedule]++; +#define CNT_IOBMAP_TLB_FLUSH \ + Jdb_tbuf::status()->kerncnts[Kern_cnt_iobmap_tlb_flush]++; +#define CNT_EXC_IPC \ + Jdb_tbuf::status()->kerncnts[Kern_cnt_exc_ipc]++; + +#else + +#define CNT_CONTEXT_SWITCH do { } while (0) +#define CNT_ADDR_SPACE_SWITCH do { } while (0) +#define CNT_SHORTCUT_FAILED do { } while (0) +#define CNT_SHORTCUT_SUCCESS do { } while (0) +#define CNT_IRQ do { } while (0) +#define CNT_IPC_LONG do { } while (0) +#define CNT_PAGE_FAULT do { } while (0) +#define CNT_IO_FAULT do { } while (0) +#define CNT_TASK_CREATE do { } while (0) +#define CNT_SCHEDULE do { } while (0) +#define CNT_IOBMAP_TLB_FLUSH do { } while (0) +#define CNT_EXC_IPC do { } while (0) + +#endif // CONFIG_JDB && CONFIG_JDB_ACCOUNTING + +#endif diff --git a/kernel/fiasco/src/kern/ia32/main-ia32.cpp b/kernel/fiasco/src/kern/ia32/main-ia32.cpp new file mode 100644 index 00000000..1e318c0f --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/main-ia32.cpp @@ -0,0 +1,146 @@ +/* + * Fiasco-IA32/AMD64 + * Architecture specific main startup/shutdown code + */ + +IMPLEMENTATION[ia32,amd64]: + +#include +#include +#include +#include "config.h" +#include "io.h" +#include "idt.h" +#include "kdb_ke.h" +#include "kernel_console.h" +#include "koptions.h" +#include "pic.h" +#include "processor.h" +#include "reset.h" +#include "timer.h" +#include "timer_tick.h" +#include "terminate.h" + +static int exit_question_active; + + +extern "C" void __attribute__ ((noreturn)) +_exit(int) +{ + if (exit_question_active) + platform_reset(); + + while (1) + { + Proc::halt(); + Proc::pause(); + } +} + + +static +void +exit_question() +{ + Proc::cli(); + exit_question_active = 1; + + Pic::Status irqs = Pic::disable_all_save(); + if (Config::getchar_does_hlt_works_ok) + { + Timer_tick::set_vectors_stop(); + Timer_tick::enable(0); // hmexit alway on CPU 0 + Proc::sti(); + } + + // make sure that we don't acknowledg the exit question automatically + Kconsole::console()->change_state(Console::PUSH, 0, ~Console::INENABLED, 0); + puts("\nReturn reboots, \"k\" enters L4 kernel debugger..."); + + char c = Kconsole::console()->getchar(); + + if (c == 'k' || c == 'K') + { + Pic::restore_all(irqs); + kdb_ke("_exit"); + } + else + { + // It may be better to not call all the destruction stuff because of + // unresolved static destructor dependency problems. So just do the + // reset at this point. + puts("\033[1mRebooting.\033[m"); + } +} + +void +main_arch() +{ + // console initialization + set_exit_question(&exit_question); + + //Pic::disable_all_save(); +} + + +//------------------------------------------------------------------------ +IMPLEMENTATION[(ia32,amd64) && mp]: + +#include +#include "apic.h" +#include "app_cpu_thread.h" +#include "config.h" +#include "cpu.h" +#include "div32.h" +#include "fpu.h" +#include "globals.h" +#include "ipi.h" +#include "kernel_task.h" +#include "processor.h" +#include "per_cpu_data_alloc.h" +#include "perf_cnt.h" +#include "spin_lock.h" +#include "utcb_init.h" + +int FIASCO_FASTCALL boot_ap_cpu(unsigned _cpu) __asm__("BOOT_AP_CPU"); + +int FIASCO_FASTCALL boot_ap_cpu(unsigned _cpu) +{ + if (!Per_cpu_data_alloc::alloc(_cpu)) + { + extern Spin_lock _tramp_mp_spinlock; + printf("CPU allocation failed for CPU%u, disabling CPU.\n", _cpu); + _tramp_mp_spinlock.clear(); + while (1) + Proc::halt(); + } + Per_cpu_data::run_ctors(_cpu); + Cpu &cpu = Cpu::cpus.cpu(_cpu); + + Kmem::init_cpu(cpu); + Idt::load(); + + Apic::init_ap(); + Ipi::init(_cpu); + Timer::init(_cpu); + Apic::check_still_getting_interrupts(); + + + // caution: no stack variables in this function because we're going + // to change the stack pointer! + cpu.print(); + cpu.show_cache_tlb_info(""); + + if (Koptions::o()->opt(Koptions::F_loadcnt)) + Perf_cnt::init_ap(); + + puts(""); + + // create kernel thread + App_cpu_thread *kernel = new (Ram_quota::root) App_cpu_thread(); + set_cpu_of(kernel, _cpu); + check(kernel->bind(Kernel_task::kernel_task(), User::Ptr(0))); + + main_switch_ap_cpu_stack(kernel); + return 0; +} diff --git a/kernel/fiasco/src/kern/ia32/map_util-io.cpp b/kernel/fiasco/src/kern/ia32/map_util-io.cpp new file mode 100644 index 00000000..dbde29e4 --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/map_util-io.cpp @@ -0,0 +1,121 @@ +/* + * Fiasco-ia32 + * Specific code for I/O port protection + */ +INTERFACE[(ia32|amd64) & io & debug]: + +#include "mapdb.h" +#include "types.h" + +extern Static_object mapdb_io; + +IMPLEMENTATION[(ia32|amd64) & io]: + +#include "l4_types.h" +#include "assert.h" +#include "space.h" +#include "io_space.h" + +Static_object mapdb_io; + +void init_mapdb_io(Space *sigma0) +{ + static size_t const io_page_sizes[] = + {Io_space::Map_superpage_shift, 9, Io_space::Page_shift}; + + mapdb_io.construct(sigma0, Page_number::create(0x10000 >> io_page_sizes[0]), io_page_sizes, 3); +} + +/** Map the IO port region described by "fp_from" of address space "from" + into address space "to". IO ports can only be mapped idempotently, + therefore there is no offset for fp_from and only those ports are mapped + that lay in the intersection of fp_from and fp_to + @param from source address space + @param fp_from... IO flexpage descripton for IO space range + in source IO space + @param to destination address space + @param fp_to... IO flexpage description for IO space range + in destination IO space + @return IPC error code that describes the status of the operation + */ +L4_error __attribute__((nonnull(1, 3))) +io_map(Space *from, L4_fpage const &fp_from, + Space *to, L4_fpage const &fp_to, L4_msg_item control) +{ +/* printf("io_map %u -> %u " + * "snd %08x base %x size %x rcv %08x base %x size %x\n", + * (unsigned)from->space(), (unsigned)to->space(), + * fp_from.fpage, + * fp_from.iofp.iopage, fp_from.iofp.iosize, + * fp_to.fpage, + * fp_to.iofp.iopage, fp_to.iofp.iosize); + * kdb_ke("io_fpage_map 1"); + */ + + typedef Map_traits Mt; + Mt::Addr rcv_pos = Mt::get_addr(fp_to); + Mt::Addr snd_pos = Mt::get_addr(fp_from); + + Mt::Size rcv_size = Mt::Size::from_shift(fp_to.order()); + Mt::Size snd_size = Mt::Size::from_shift(fp_from.order()); + + snd_pos = snd_pos.trunc(snd_size); + rcv_pos = rcv_pos.trunc(rcv_size); + Mt::constraint(snd_pos, snd_size, rcv_pos, rcv_size, Mt::Addr(0)); + + if (snd_size == 0) + return L4_error::None; + + //assert(snd_pos < L4_fpage::Io_port_max); + + unsigned long del_attribs, add_attribs; + Mt::attribs(control, fp_from, &del_attribs, &add_attribs); + + return map(mapdb_io.get(), from, from, snd_pos, + snd_size, + to, to, snd_pos, + control.is_grant(), add_attribs, del_attribs, + (Io_space::Reap_list**)0); +} + +/** Unmap IO mappings. + Unmap the region described by "fp" from the IO + space "space" and/or the IO spaces the mappings have been + mapped into. + XXX not implemented yet + @param space address space that should be flushed + @param fp IO flexpage descriptor of IO-space range that should + be flushed + @param me_too If false, only flush recursive mappings. If true, + additionally flush the region in the given address space. + @return true if successful +*/ +unsigned __attribute__((nonnull(1))) +io_fpage_unmap(Space *space, L4_fpage fp, L4_map_mask mask) +{ + typedef Map_traits Mt; + Mt::Size size = Mt::Size::from_shift(fp.order()); + Mt::Addr port = Mt::get_addr(fp); + port = port.trunc(size); + + // Here we _would_ reset IOPL to 0 but this doesn't make much sense + // for only one thread since this thread may have forwarded the right + // to other threads too. Therefore we had to walk through any thread + // of this space. + // + // current()->regs()->eflags &= ~EFLAGS_IOPL; + + return unmap(mapdb_io.get(), space, space, + port, size, + fp.rights(), mask, (Io_space::Reap_list**)0); +} + +static inline +void +save_access_attribs(Mapdb* /*mapdb*/, const Mapdb::Frame& /*mapdb_frame*/, + Mapping* /*mapping*/, Io_space* /*space*/, + unsigned /*page_rights*/, + Io_space::Addr /*virt*/, Io_space::Phys_addr /*phys*/, + Io_space::Size /*size*/, + bool /*me_too*/) +{} diff --git a/kernel/fiasco/src/kern/ia32/mem_layout-ia32.cpp b/kernel/fiasco/src/kern/ia32/mem_layout-ia32.cpp new file mode 100644 index 00000000..d31b902f --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/mem_layout-ia32.cpp @@ -0,0 +1,74 @@ +INTERFACE [ia32 || amd64 || ux]: + +EXTENSION class Mem_layout +{ +public: + enum { Io_port_max = (1UL << 16) }; + + static Address _io_map_ptr; +}; + +IMPLEMENTATION [ia32 || amd64 || ux]: + +#include "static_assert.h" + +Address Mem_layout::_io_map_ptr = Mem_layout::Io_map_area_end; + +PUBLIC static inline +Address +Mem_layout::alloc_io_vmem(unsigned long bytes) +{ + bytes = (bytes + Config::PAGE_SIZE - 1) & ~(Config::PAGE_SIZE - 1); + if (_io_map_ptr - bytes < Io_map_area_start) + return 0; + + _io_map_ptr -= bytes; + return _io_map_ptr; +} + +PUBLIC static inline NEEDS["static_assert.h"] +template< typename V > +bool +Mem_layout::read_special_safe(V const *address, V &v) +{ + static_assert(sizeof(v) <= sizeof(Mword), "wrong sized argument"); + Mword value; + bool res; + asm volatile ("clc; mov (%[adr]), %[val]; setnc %b[ex] \n" + : [val] "=acd" (value), [ex] "=r" (res) + : [adr] "acdbSD" (address) + : "cc"); + v = V(value); + return res; +} + +PUBLIC static inline NEEDS["static_assert.h"] +template< typename T > +T +Mem_layout::read_special_safe(T const *a) +{ + static_assert(sizeof(T) <= sizeof(Mword), "wrong sized return type"); + Mword res; + asm volatile ("mov (%1), %0 \n\t" + : "=acd" (res) : "acdbSD" (a) : "cc"); + return T(res); + +} + +PUBLIC static inline +bool +Mem_layout::is_special_mapped(void const *a) +{ + // Touch the state to page in the TCB. If we get a pagefault here, + // the handler doesn't handle it but returns immediatly after + // setting eax to 0xffffffff + Mword pagefault_if_0; + asm volatile ( + "clc; mov (%2), %0 \n\t" + "setnc %b0 \n\t" + : "=acd" (pagefault_if_0) + : "0"(0UL), "acdbSD"(a) + : "cc"); + return pagefault_if_0; +} + diff --git a/kernel/fiasco/src/kern/ia32/mem_space-ia32.cpp b/kernel/fiasco/src/kern/ia32/mem_space-ia32.cpp new file mode 100644 index 00000000..a3b3695a --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/mem_space-ia32.cpp @@ -0,0 +1,475 @@ +INTERFACE [ia32 || ux || amd64]: + +EXTENSION class Mem_space +{ +public: + typedef Pdir Dir_type; + + /** Return status of v_insert. */ + enum // Status + { + Insert_ok = 0, ///< Mapping was added successfully. + Insert_warn_exists, ///< Mapping already existed + Insert_warn_attrib_upgrade, ///< Mapping already existed, attribs upgrade + Insert_err_nomem, ///< Couldn't alloc new page table + Insert_err_exists ///< A mapping already exists at the target addr + }; + + /** Attribute masks for page mappings. */ + enum Page_attrib + { + Page_no_attribs = 0, + /// Page is writable. + Page_writable = Pt_entry::Writable, + Page_cacheable = 0, + /// Page is noncacheable. + Page_noncacheable = Pt_entry::Noncacheable | Pt_entry::Write_through, + /// it's a user page. + Page_user_accessible = Pt_entry::User, + /// Page has been referenced + Page_referenced = Pt_entry::Referenced, + /// Page is dirty + Page_dirty = Pt_entry::Dirty, + Page_references = Page_referenced | Page_dirty, + /// A mask which contains all mask bits + Page_all_attribs = Page_writable | Page_noncacheable | + Page_user_accessible | Page_referenced | Page_dirty, + }; + + // Mapping utilities + + enum // Definitions for map_util + { + Need_insert_tlb_flush = 0, + Map_page_size = Config::PAGE_SIZE, + Page_shift = Config::PAGE_SHIFT, + Map_superpage_size = Config::SUPERPAGE_SIZE, + Map_max_address = Mem_layout::User_max, + Whole_space = MWORD_BITS, + Identity_map = 0, + }; + + + void page_map (Address phys, Address virt, + Address size, unsigned page_attribs); + + void page_unmap (Address virt, Address size); + + void page_protect (Address virt, Address size, + unsigned page_attribs); + +protected: + // DATA + Dir_type *_dir; +}; + +//---------------------------------------------------------------------------- +IMPLEMENTATION [ia32 || ux || amd64]: + +#include +#include +#include "cpu.h" +#include "kdb_ke.h" +#include "l4_types.h" +#include "mem_layout.h" +#include "paging.h" +#include "std_macros.h" + + + + +PUBLIC explicit inline +Mem_space::Mem_space(Ram_quota *q) : _quota(q), _dir(0) {} + +PROTECTED inline +bool +Mem_space::initialize() +{ + void *b; + if (EXPECT_FALSE(!(b = Kmem_alloc::allocator() + ->q_alloc(_quota, Config::PAGE_SHIFT)))) + return false; + + _dir = static_cast(b); + _dir->clear(); // initialize to zero + return true; // success +} + +PUBLIC +Mem_space::Mem_space(Ram_quota *q, Dir_type* pdir) + : _quota(q), _dir(pdir) +{ + _kernel_space = this; + _current.cpu(0) = this; +} + + +PUBLIC static inline +Mword +Mem_space::xlate_flush(unsigned char rights) +{ + Mword a = Page_references; + if (rights & L4_fpage::RX) + a |= Page_all_attribs; + else if (rights & L4_fpage::W) + a |= Page_writable; + return a; +} + +PUBLIC static inline +Mword +Mem_space::is_full_flush(unsigned char rights) +{ + return rights & L4_fpage::RX; +} + +PUBLIC static inline +unsigned char +Mem_space::xlate_flush_result(Mword attribs) +{ + unsigned char r = 0; + if (attribs & Page_referenced) + r |= L4_fpage::RX; + + if (attribs & Page_dirty) + r |= L4_fpage::W; + + return r; +} + +PUBLIC inline NEEDS["cpu.h"] +static bool +Mem_space::has_superpages() +{ + return Cpu::have_superpages(); +} + + +PUBLIC static inline NEEDS["mem_unit.h"] +void +Mem_space::tlb_flush(bool = false) +{ + Mem_unit::tlb_flush(); +} + +PUBLIC static inline +void +Mem_space::tlb_flush_spaces(bool, Mem_space *, Mem_space *) +{ + tlb_flush(); +} + + +IMPLEMENT inline +Mem_space * +Mem_space::current_mem_space(unsigned cpu) /// XXX: do not fix, deprecated, remove! +{ + return _current.cpu(cpu); +} + +PUBLIC inline +bool +Mem_space::set_attributes(Addr virt, unsigned page_attribs) +{ + Pdir::Iter i = _dir->walk(virt); + + if (!i.e->valid() || i.shift() != Config::PAGE_SHIFT) + return 0; + + i.e->del_attr(Page::MAX_ATTRIBS); + i.e->add_attr(page_attribs); + return true; +} + + +PROTECTED inline +void +Mem_space::destroy() +{} + +/** + * Destructor. Deletes the address space and unregisters it from + * Space_index. + */ +PRIVATE +void +Mem_space::dir_shutdown() +{ + // free all page tables we have allocated for this address space + // except the ones in kernel space which are always shared + _dir->destroy(Virt_addr(0), + Virt_addr(Kmem::mem_user_max), Pdir::Depth - 1, + Kmem_alloc::q_allocator(_quota)); + +} + +IMPLEMENT +Mem_space::Status +Mem_space::v_insert(Phys_addr phys, Vaddr virt, Vsize size, + unsigned page_attribs, bool upgrade_ignore_size) +{ + // insert page into page table + + // XXX should modify page table using compare-and-swap + + assert_kdb (size == Size(Config::PAGE_SIZE) + || size == Size(Config::SUPERPAGE_SIZE)); + if (size == Size(Config::SUPERPAGE_SIZE)) + { + assert (Cpu::have_superpages()); + assert (virt.offset(Size(Config::SUPERPAGE_SIZE)) == 0); + assert (phys.offset(Size(Config::SUPERPAGE_SIZE)) == 0); + } + + unsigned level = (size == Size(Config::SUPERPAGE_SIZE) ? (int)Pdir::Super_level : (int)Pdir::Depth); + unsigned shift = (size == Size(Config::SUPERPAGE_SIZE) ? Config::SUPERPAGE_SHIFT : Config::PAGE_SHIFT); + unsigned attrs = (size == Size(Config::SUPERPAGE_SIZE) ? (unsigned long)Pt_entry::Pse_bit : 0); + + Pdir::Iter i = _dir->walk(virt, level, + Kmem_alloc::q_allocator(_quota)); + + if (EXPECT_FALSE(!i.e->valid() && i.shift() != shift)) + return Insert_err_nomem; + + if (EXPECT_FALSE(!upgrade_ignore_size + && i.e->valid() && (i.shift() != shift || i.addr() != phys.value()))) + return Insert_err_exists; + + if (i.e->valid()) + { + if (EXPECT_FALSE((i.e->raw() | page_attribs) == i.e->raw())) + return Insert_warn_exists; + + i.e->add_attr(page_attribs); + page_protect (Addr(virt).value(), Size(size).value(), i.e->raw() & Page_all_attribs); + + return Insert_warn_attrib_upgrade; + } + else + { + *i.e = Addr(phys).value() | Pt_entry::Valid | attrs | page_attribs; + page_map (Addr(phys).value(), Addr(virt).value(), Size(size).value(), page_attribs); + + return Insert_ok; + } +} + +/** + * Simple page-table lookup. + * + * @param virt Virtual address. This address does not need to be page-aligned. + * @return Physical address corresponding to a. + */ +PUBLIC inline NEEDS ["paging.h"] +Address +Mem_space::virt_to_phys(Address virt) const +{ + return dir()->virt_to_phys(virt); +} + +/** + * Simple page-table lookup. + * + * @param virt Virtual address. This address does not need to be page-aligned. + * @return Physical address corresponding to a. + */ +PUBLIC inline NEEDS ["mem_layout.h"] +Address +Mem_space::pmem_to_phys (Address virt) const +{ + return Mem_layout::pmem_to_phys(virt); +} + +/** + * Simple page-table lookup. + * + * This method is similar to Space_context's virt_to_phys(). + * The difference is that this version handles Sigma0's + * address space with a special case: For Sigma0, we do not + * actually consult the page table -- it is meaningless because we + * create new mappings for Sigma0 transparently; instead, we return the + * logically-correct result of physical address == virtual address. + * + * @param a Virtual address. This address does not need to be page-aligned. + * @return Physical address corresponding to a. + */ +PUBLIC inline +virtual Address +Mem_space::virt_to_phys_s0(void *a) const +{ + return dir()->virt_to_phys((Address)a); +} + +IMPLEMENT +bool +Mem_space::v_lookup(Vaddr virt, Phys_addr *phys, + Size *size, unsigned *page_attribs) +{ + Pdir::Iter i = _dir->walk(virt); + if (size) *size = Size(1UL << i.shift()); + + if (!i.e->valid()) + return false; + + if (phys) *phys = Addr(i.e->addr() & (~0UL << i.shift())); + if (page_attribs) *page_attribs = (i.e->raw() & Page_all_attribs); + + return true; +} + +IMPLEMENT +unsigned long +Mem_space::v_delete(Vaddr virt, Vsize size, + unsigned long page_attribs = Page_all_attribs) +{ + unsigned ret; + + // delete pages from page tables + assert (size == Size(Config::PAGE_SIZE) || size == Size(Config::SUPERPAGE_SIZE)); + + if (size == Size(Config::SUPERPAGE_SIZE)) + { + assert (Cpu::have_superpages()); + assert (!virt.offset(Size(Config::SUPERPAGE_SIZE))); + } + + Pdir::Iter i = _dir->walk(virt); + + if (EXPECT_FALSE (! i.e->valid())) + return 0; + + assert (! (i.e->raw() & Pt_entry::global())); // Cannot unmap shared ptables + + ret = i.e->raw() & page_attribs; + + if (! (page_attribs & Page_user_accessible)) + { + // downgrade PDE (superpage) rights + i.e->del_attr(page_attribs); + page_protect (Addr(virt).value(), Size(size).value(), i.e->raw() & Page_all_attribs); + } + else + { + // delete PDE (superpage) + *i.e = 0; + page_unmap (Addr(virt).value(), Size(size).value()); + } + + return ret; +} + +/** + * \brief Free all memory allocated for this Mem_space. + * \pre Runs after the destructor! + */ +PUBLIC +Mem_space::~Mem_space() +{ + if (_dir) + { + dir_shutdown(); + Kmem_alloc::allocator()->q_free(_quota, Config::PAGE_SHIFT, _dir); + } +} + + +// -------------------------------------------------------------------- +IMPLEMENTATION [ia32 || amd64]: + +#include +#include "l4_types.h" +#include "kmem.h" +#include "mem_unit.h" +#include "cpu_lock.h" +#include "lock_guard.h" +#include "logdefs.h" +#include "paging.h" + +#include +#include "config.h" +#include "kmem.h" + +IMPLEMENT inline NEEDS ["cpu.h", "kmem.h"] +void +Mem_space::make_current() +{ + Cpu::set_pdbr((Mem_layout::pmem_to_phys(_dir))); + _current.cpu(current_cpu()) = this; +} + +PUBLIC inline NEEDS ["kmem.h"] +Address +Mem_space::phys_dir() +{ + return Mem_layout::pmem_to_phys(_dir); +} + +/* + * The following functions are all no-ops on native ia32. + * Pages appear in an address space when the corresponding PTE is made + * ... unlike Fiasco-UX which needs these special tricks + */ + +IMPLEMENT inline +void +Mem_space::page_map (Address, Address, Address, unsigned) +{} + +IMPLEMENT inline +void +Mem_space::page_protect (Address, Address, unsigned) +{} + +IMPLEMENT inline +void +Mem_space::page_unmap (Address, Address) +{} + +IMPLEMENT inline NEEDS["kmem.h", "logdefs.h"] +void +Mem_space::switchin_context(Mem_space *from) +{ + // FIXME: this optimization breaks SMP task deletion, an idle thread + // may run on an already deleted page table +#if 0 + // never switch to kernel space (context of the idle thread) + if (dir() == Kmem::dir()) + return; +#endif + + if (from != this) + { + CNT_ADDR_SPACE_SWITCH; + make_current(); + } +} + +PROTECTED inline +void +Mem_space::sync_kernel() +{ + _dir->sync(Virt_addr(Mem_layout::User_max), Kmem::dir(), + Virt_addr(Mem_layout::User_max), + Virt_addr(-Mem_layout::User_max), Pdir::Super_level, + Kmem_alloc::q_allocator(_quota)); +} + +// -------------------------------------------------------------------- +IMPLEMENTATION [amd64]: + +PUBLIC static inline +Page_number +Mem_space::canonize(Page_number v) +{ + if (v & Virt_addr(1UL << 48)) + v = v | Virt_addr(~0UL << 48); + return v; +} + +// -------------------------------------------------------------------- +IMPLEMENTATION [ia32 || ux]: + +PUBLIC static inline +Page_number +Mem_space::canonize(Page_number v) +{ return v; } diff --git a/kernel/fiasco/src/kern/ia32/no_kdb_ke.cpp b/kernel/fiasco/src/kern/ia32/no_kdb_ke.cpp new file mode 100644 index 00000000..4ad73cfe --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/no_kdb_ke.cpp @@ -0,0 +1,11 @@ +IMPLEMENTATION[ia32,amd64]: + +#include + +inline NEEDS [] +bool kdb_ke(const char *msg) +{ + printf("NO KDB: %s\n" + "So go ahead.\n",msg); + return false; +} diff --git a/kernel/fiasco/src/kern/ia32/paging-ia32.cpp b/kernel/fiasco/src/kern/ia32/paging-ia32.cpp new file mode 100644 index 00000000..d35081ee --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/paging-ia32.cpp @@ -0,0 +1,148 @@ +INTERFACE [ia32 || amd64 || ux]: + +#include "types.h" +#include "config.h" + + +namespace Page +{ + typedef Unsigned32 Attribs; + + enum Attribs_enum + { + KERN_RW = 0x00000002, ///< User No access + USER_RO = 0x00000004, ///< User Read only + USER_RW = 0x00000006, ///< User Read/Write + USER_RX = 0x00000004, ///< User Read/Execute + USER_XO = 0x00000004, ///< User Execute only + USER_RWX = 0x00000006, ///< User Read/Write/Execute + MAX_ATTRIBS = 0x00000006, + Cache_mask = 0x00000018, ///< Cache attrbute mask + CACHEABLE = 0x00000000, + BUFFERED = 0x00000010, + NONCACHEABLE = 0x00000018, + }; +}; + +EXTENSION class Pte_base {}; + + +//--------------------------------------------------------------------------- +IMPLEMENTATION [ia32 || amd64 || ux]: + +PUBLIC inline +Pte_base & +Pte_base::operator = (Pte_base const &other) +{ + _raw = other.raw(); + return *this; +} + +PUBLIC inline +Pte_base & +Pte_base::operator = (Mword raw) +{ + _raw = raw; + return *this; +} + +PUBLIC inline +Mword +Pte_base::raw() const +{ + return _raw; +} + +PUBLIC inline +void +Pte_base::add_attr(Mword attr) +{ + _raw |= attr; +} + +PUBLIC inline +void +Pte_base::del_attr(Mword attr) +{ + _raw &= ~attr; +} + +PUBLIC inline +void +Pte_base::clear() +{ _raw = 0; } + +PUBLIC inline +int +Pte_base::valid() const +{ + return _raw & Valid; +} + +PUBLIC inline +int +Pte_base::writable() const +{ + return _raw & Writable; +} + +PUBLIC inline +Address +Pt_entry::pfn() const +{ + return _raw & Pfn; +} + +Unsigned32 Pte_base::_cpu_global = Pte_base::L4_global; + +PUBLIC static inline +void +Pte_base::enable_global() +{ + _cpu_global |= Pte_base::Cpu_global; +} + +/** + * Global entries are entries that are not automatically flushed when the + * page-table base register is reloaded. They are intended for kernel data + * that is shared between all tasks. + * @return global page-table--entry flags + */ +PUBLIC static inline +Unsigned32 +Pte_base::global() +{ + return _cpu_global; +} + + +//-------------------------------------------------------------------------- +#include "cpu.h" +#include "mem_layout.h" +#include "regdefs.h" + +IMPLEMENT inline NEEDS["regdefs.h"] +Mword PF::is_translation_error(Mword error) +{ + return !(error & PF_ERR_PRESENT); +} + +IMPLEMENT inline NEEDS["regdefs.h"] +Mword PF::is_usermode_error(Mword error) +{ + return (error & PF_ERR_USERMODE); +} + +IMPLEMENT inline NEEDS["regdefs.h"] +Mword PF::is_read_error(Mword error) +{ + return !(error & PF_ERR_WRITE); +} + +IMPLEMENT inline NEEDS["regdefs.h"] +Mword PF::addr_to_msgword0(Address pfa, Mword error) +{ + return (pfa & ~(PF_ERR_PRESENT | PF_ERR_WRITE)) + | (error & (PF_ERR_PRESENT | PF_ERR_WRITE)); +} + diff --git a/kernel/fiasco/src/kern/ia32/perf_cnt-ia32.cpp b/kernel/fiasco/src/kern/ia32/perf_cnt-ia32.cpp new file mode 100644 index 00000000..6993e46b --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/perf_cnt-ia32.cpp @@ -0,0 +1,1230 @@ +INTERFACE [{ia32,ux,amd64}-perf_cnt]: + +#include "cpu.h" +#include "types.h" + +EXTENSION class Perf_cnt +{ +public: + enum Perf_event_type + { P5, P6, P4, }; + + static Perf_read_fn read_pmc[Max_slot]; + virtual void init_loadcnt() = 0; + virtual void start_pmc(Mword) = 0; + + static Perf_cnt_arch *pcnt; + +private: + static Perf_read_fn *read_pmc_fns; + static Perf_read_fn read_pmc_fn[Max_slot]; + static char const *perf_type_str; + static Perf_event_type perf_event_type; +}; + +class Perf_cnt_arch +{ +public: + // basic initialization + virtual int init() = 0; + + // set event the counter should count + virtual void set_pmc_event(Mword slot) = 0; + + inline void touch_watchdog() + { Cpu::wrmsr(hold_watchdog, _ctr_reg0+pmc_watchdog); } + +protected: + Mword _nr_regs; + Mword _sel_reg0; + Mword _ctr_reg0; + Mword _watchdog; + + struct Event + { + char user; // 1=count in user mode + char kern; // 1=count in kernel mode + char edge; // 1=count edge / 0=count duration + Mword pmc; // # of performance counter + Mword bitmask; // counter bitmask + Mword evnt; // event selector + }; + + static Mword pmc_watchdog; // # perfcounter of watchdog + static Mword pmc_loadcnt; // # perfcounter of loadcnt + static Signed64 hold_watchdog; + static Event pmc_event[Perf_cnt::Max_slot]; // index is slot number + static char pmc_alloc[Perf_cnt::Max_pmc]; // index is # of perfcounter +}; + +class Perf_cnt_p5 : public Perf_cnt_arch {}; +class Perf_cnt_p6 : public Perf_cnt_arch {}; +class Perf_cnt_k7 : public Perf_cnt_p6 {}; +class Perf_cnt_p4 : public Perf_cnt_arch {}; +class Perf_cnt_ap : public Perf_cnt_p6 {}; + +IMPLEMENTATION [{ia32,ux,amd64}-perf_cnt]: + +#include +#include +#include +#include "cpu.h" +#include "regdefs.h" +#include "static_init.h" +#include "tb_entry.h" + +Perf_cnt::Perf_read_fn Perf_cnt::read_pmc[Perf_cnt::Max_slot] = +{ dummy_read_pmc, dummy_read_pmc }; +Perf_cnt::Perf_read_fn Perf_cnt::read_pmc_fn[Perf_cnt::Max_slot] = +{ dummy_read_pmc, dummy_read_pmc }; + +Perf_cnt::Perf_read_fn *Perf_cnt::read_pmc_fns; +Perf_cnt::Perf_event_type Perf_cnt::perf_event_type; +Perf_cnt_arch *Perf_cnt::pcnt; +char const *Perf_cnt::perf_type_str = "n/a"; + +Mword Perf_cnt_arch::pmc_watchdog = (Mword)-1; +Mword Perf_cnt_arch::pmc_loadcnt = (Mword)-1; +Signed64 Perf_cnt_arch::hold_watchdog; +Perf_cnt_arch::Event Perf_cnt_arch::pmc_event[Perf_cnt::Max_slot]; +char Perf_cnt_arch::pmc_alloc[Perf_cnt::Max_pmc]; + +static Perf_cnt_p5 perf_cnt_p5 __attribute__ ((init_priority(PERF_CNT_INIT_PRIO))); +static Perf_cnt_p6 perf_cnt_p6 __attribute__ ((init_priority(PERF_CNT_INIT_PRIO))); +static Perf_cnt_k7 perf_cnt_k7 __attribute__ ((init_priority(PERF_CNT_INIT_PRIO))); +static Perf_cnt_p4 perf_cnt_p4 __attribute__ ((init_priority(PERF_CNT_INIT_PRIO))); +static Perf_cnt_ap perf_cnt_ap __attribute__ ((init_priority(PERF_CNT_INIT_PRIO))); + +enum +{ + Alloc_none = 0, // unallocated + Alloc_perf = 1, // allocated as performance counter + Alloc_watchdog = 2, // allocated for watchdog +}; + +enum +{ + // Intel P5 + Msr_p5_cesr = 0x11, + Msr_p5_ctr0 = 0x12, + Msr_p5_ctr1 = 0x13, + P5_evntsel_user = 0x00000080, + P5_evntsel_kern = 0x00000040, + P5_evntsel_duration = 0x00000100, + + // Intel P6/PII/PIII + Msr_p6_perfctr0 = 0xC1, + Msr_p6_evntsel0 = 0x186, + P6_evntsel_enable = 0x00400000, + P6_evntsel_int = 0x00100000, + P6_evntsel_user = 0x00010000, + P6_evntsel_kern = 0x00020000, + P6_evntsel_edge = 0x00040000, + + // AMD K7/K8 + Msr_k7_evntsel0 = 0xC0010000, + Msr_k7_perfctr0 = 0xC0010004, + K7_evntsel_enable = P6_evntsel_enable, + K7_evntsel_int = P6_evntsel_int, + K7_evntsel_user = P6_evntsel_user, + K7_evntsel_kern = P6_evntsel_kern, + K7_evntsel_edge = P6_evntsel_edge, + + // Intel P4 + Msr_p4_misc_enable = 0x1A0, + Msr_p4_perfctr0 = 0x300, + Msr_p4_bpu_counter0 = 0x300, + Msr_p4_cccr0 = 0x360, + Msr_p4_fsb_escr0 = 0x3A2, + P4_escr_user = (1<<2), + P4_escr_kern = (1<<3), + Msr_p4_bpu_cccr0 = 0x360, + P4_cccr_ovf = (1<<31), + P4_cccr_ovf_pmi = (1<<26), + P4_cccr_complement = (1<<19), + P4_cccr_compare = (1<<18), + P4_cccr_required = (3<<16), + P4_cccr_enable = (1<<12), + + Msr_ap_perfctr0 = 0xC1, + Msr_ap_evntsel0 = 0x186, + AP_evntsel_enable = P6_evntsel_enable, + AP_evntsel_int = P6_evntsel_int, + AP_evntsel_user = P6_evntsel_user, + AP_evntsel_kern = P6_evntsel_kern, + AP_evntsel_edge = P6_evntsel_edge, +}; + +// ----------------------------------------------------------------------- + +enum +{ + Perfctr_x86_generic = 0, /* any x86 with rdtsc */ + Perfctr_x86_intel_p5 = 1, /* no rdpmc */ + Perfctr_x86_intel_p5mmx = 2, + Perfctr_x86_intel_p6 = 3, + Perfctr_x86_intel_pii = 4, + Perfctr_x86_intel_piii = 5, + Perfctr_x86_intel_p4 = 11, /* model 0 and 1 */ + Perfctr_x86_intel_p4m2 = 12, /* model 2 */ + Perfctr_x86_intel_p4m3 = 16, /* model 3 and above */ + Perfctr_x86_intel_pentm = 14, + Perfctr_x86_amd_k7 = 9, + Perfctr_x86_amd_k8 = 13, + Perfctr_x86_arch_perfmon = 14, +}; + +enum perfctr_unit_mask_type +{ + perfctr_um_type_fixed, /* one fixed (required) value */ + perfctr_um_type_exclusive, /* exactly one of N values */ + perfctr_um_type_bitmask, /* bitwise 'or' of N power-of-2 values */ +}; + +struct perfctr_unit_mask_value +{ + unsigned int value; + const char *description; /* [NAME:]text */ +}; + +struct perfctr_unit_mask +{ + unsigned int default_value; + enum perfctr_unit_mask_type type:16; + unsigned short nvalues; + struct perfctr_unit_mask_value values[1/*nvalues*/]; +}; + +struct perfctr_event +{ + unsigned int evntsel; + unsigned int counters_set; /* P4 force this to be CPU-specific */ + const struct perfctr_unit_mask *unit_mask; + const char *name; + const char *description; +}; + +struct perfctr_event_set +{ + unsigned int cpu_type; + const char *event_prefix; + const struct perfctr_event_set *include; + unsigned int nevents; + const struct perfctr_event *events; +}; + +// The following functions are only available if the perfctr module +// is linked into the kernel. If not, all symbols perfctr_* are 0. */ +// +// show all events +extern "C" void perfctr_set_cputype(unsigned) + __attribute__((weak)); +extern "C" const struct perfctr_event* perfctr_lookup_event(unsigned, + unsigned*) + __attribute__((weak)); +extern "C" const struct perfctr_event* perfctr_index_event(unsigned) + __attribute__((weak)); +extern "C" unsigned perfctr_get_max_event(void) + __attribute__((weak)); +extern "C" const struct perfctr_event_set *perfctr_cpu_event_set(unsigned) + __attribute__((weak)); + +static inline +void +clear_msr_range(Mword base, Mword n) +{ + for (Mword i=0; iarch_perfmon_info(&eax, &ebx, &ecx); + _nr_regs = (eax & 0x0000ff00) >> 8; +} + +void +Perf_cnt_ap::start_pmc(Mword reg_nr) +{ + Unsigned64 msr; + + msr = Cpu::rdmsr(_sel_reg0 + reg_nr); + msr |= AP_evntsel_enable; + Cpu::wrmsr(msr, _sel_reg0 + reg_nr); +} + +void +Perf_cnt_ap::init_watchdog() +{ + Unsigned64 msr; + + msr = AP_evntsel_int // Int enable: enable interrupt on overflow + | AP_evntsel_kern // Monitor kernel-level events + | AP_evntsel_user // Monitor user-level events + | 0x3C; // #clocks CPU is running + Cpu::wrmsr(msr, _sel_reg0 + pmc_watchdog); +} + +void +Perf_cnt_ap::init_loadcnt() +{ + Unsigned64 msr; + + msr = AP_evntsel_kern // Monitor kernel-level events + | AP_evntsel_user // Monitor user-level events + | 0x3C; // #clocks CPU is running + Cpu::wrmsr(msr, _sel_reg0 + pmc_loadcnt); + + printf("Load counter initialized (read with rdpmc(0x%02lX))\n", pmc_loadcnt); +} + + +//-------------------------------------------------------------------- +// Intel P4 +PUBLIC inline NOEXPORT +Perf_cnt_p4::Perf_cnt_p4() + : Perf_cnt_arch(Msr_p4_bpu_cccr0, Msr_p4_bpu_counter0, 2, 1) +{} + +static inline NOEXPORT +Mword +Perf_cnt_p4::escr_event_select(Mword n) +{ return n << 25; } + +static inline NOEXPORT +Mword +Perf_cnt_p4::escr_event_mask(Mword n) +{ return n << 9; } + +static inline NOEXPORT +Mword +Perf_cnt_p4::cccr_threshold(Mword n) +{ return n << 20; } + +static inline NOEXPORT +Mword +Perf_cnt_p4::cccr_escr_select(Mword n) +{ return n << 13; } + +FIASCO_INIT_CPU +int +Perf_cnt_p4::init() +{ + Unsigned32 misc_enable = Cpu::rdmsr(Msr_p4_misc_enable); + + // performance monitoring available? + if (!(misc_enable & (1<<7))) + return 0; + + // disable precise event based sampling + if (!(misc_enable & (1<<12))) + clear_msr_range(0x3F1, 2); + + // ensure sane state of performance counter registers + clear_msr_range(0x3A0, 26); + if (Cpu::boot_cpu()->model() <= 2) + clear_msr_range(0x3BA, 2); + clear_msr_range(0x3BC, 3); + clear_msr_range(0x3C0, 6); + clear_msr_range(0x3C8, 6); + clear_msr_range(0x3E0, 2); + clear_msr_range(Msr_p4_cccr0, 18); + clear_msr_range(Msr_p4_perfctr0, 18); + + return 1; +} + +void +Perf_cnt_p4::set_pmc_event(Mword /*slot*/) +{} + +void +Perf_cnt_p4::start_pmc(Mword reg_nr) +{ + Unsigned64 msr; + + msr = Cpu::rdmsr(Msr_p4_bpu_cccr0 + reg_nr); + msr |= P4_cccr_enable; + Cpu::wrmsr(msr, Msr_p4_bpu_cccr0 + reg_nr); +} + +void +Perf_cnt_p4::init_watchdog() +{ + Unsigned64 msr; + + msr = escr_event_select(0x13) // global power events + | escr_event_mask(1) // the processor is active (non-halted) + | P4_escr_kern // Monitor kernel-level events + | P4_escr_user; // Monitor user-level events + Cpu::wrmsr(msr, Msr_p4_fsb_escr0); + + msr = P4_cccr_ovf_pmi // performance monitor interrupt on overflow + | P4_cccr_required // must be set + | cccr_escr_select(6); // select ESCR to select events to be counted + Cpu::wrmsr(msr, Msr_p4_bpu_cccr0 + pmc_watchdog); +} + +void +Perf_cnt_p4::init_loadcnt() +{ + Unsigned64 msr; + + msr = escr_event_select(0x13) // global power events + | escr_event_mask(1) // the processor is active (non-halted) + | P4_escr_kern // Monitor kernel-level events + | P4_escr_user; // Monitor user-level events + Cpu::wrmsr(msr, Msr_p4_fsb_escr0); + + msr = P4_cccr_required // must be set + | cccr_escr_select(6); // select ESCR to select events to be counted + + Cpu::wrmsr(msr, Msr_p4_bpu_cccr0 + pmc_loadcnt); + + printf("Load counter initialized (read with rdpmc(0x%02lX))\n", + pmc_loadcnt + 0); +} + +void +Perf_cnt_p4::start_watchdog() +{ + Unsigned64 msr; + + msr = Cpu::rdmsr(Msr_p4_bpu_cccr0); + msr |= P4_cccr_ovf_pmi | P4_cccr_enable; // Int enable, Ctr enable + msr &= ~P4_cccr_ovf; // clear Overflow + Cpu::wrmsr(msr, Msr_p4_bpu_cccr0 + pmc_watchdog); +} + +void +Perf_cnt_p4::stop_watchdog() +{ + Unsigned64 msr; + + msr = Cpu::rdmsr(Msr_p4_bpu_cccr0); + msr &= ~(P4_cccr_ovf_pmi | P4_cccr_enable); // Int disable, Ctr disable + Cpu::wrmsr(msr, Msr_p4_bpu_cccr0 + pmc_watchdog); +} + +static +Mword +p4_read_pmc() { return 0; } + +static Perf_cnt::Perf_read_fn p4_read_pmc_fns[] = { &p4_read_pmc }; + + +//-------------------------------------------------------------------- + +PROTECTED inline +Perf_cnt_arch::Perf_cnt_arch(Mword sel_reg0, Mword ctr_reg0, + Mword nr_regs, Mword watchdog) +{ + _sel_reg0 = sel_reg0; + _ctr_reg0 = ctr_reg0; + _nr_regs = nr_regs; + _watchdog = watchdog; + + for (Mword slot=0; slotfrequency() >> 16) * timeout)) << 16; + // The maximum value a performance counter register can be written to + // is 0x7ffffffff. The 31st bit is extracted to the bits 32-39 (see + // "IA-32 Intel Architecture Software Developer's Manual. Volume 3: + // Programming Guide" section 14.10.2: PerfCtr0 and PerfCtr1 MSRs. + if (hold_watchdog > 0x7fffffff) + hold_watchdog = 0x7fffffff; + hold_watchdog = -hold_watchdog; + init_watchdog(); + touch_watchdog(); + start_watchdog(); + start_pmc(pmc_watchdog); + } +} + +PUBLIC +void +Perf_cnt_arch::setup_loadcnt() +{ + alloc_loadcnt(); + if (loadcnt_allocated()) + { + init_loadcnt(); + start_pmc(pmc_loadcnt); + } +} + +PUBLIC virtual +void +Perf_cnt_arch::init_watchdog() +{} // no watchdog per default + +PUBLIC virtual +void +Perf_cnt_arch::init_loadcnt() +{ panic("Cannot initialize load counter"); } + +// start watchdog (enable generation of overflow interrupt) +PUBLIC virtual +void +Perf_cnt_arch::start_watchdog() +{} // no watchdog per default + +// stop watchdog (disable generation of overflow interrupt) +PUBLIC virtual +void +Perf_cnt_arch::stop_watchdog() +{} // no watchdog per default + +//-------------------------------------------------------------------- + +STATIC_INITIALIZE_P(Perf_cnt, PERF_CNT_INIT_PRIO); + +// basic perfcounter detection +PUBLIC static FIASCO_INIT_CPU +void +Perf_cnt::init() +{ + Cpu const &cpu = *Cpu::boot_cpu(); + Mword perfctr_type = Perfctr_x86_generic; + Unsigned32 eax, ebx, ecx; + + for (Mword i=0; i>8) & 0xff) > 1)) + { + perfctr_type = Perfctr_x86_arch_perfmon; + perf_type_str = "PA"; + read_pmc_fns = p6_read_pmc_fns; + pcnt = &perf_cnt_ap; + } + if (perfctr_type == Perfctr_x86_generic) + { + if (cpu.vendor() == cpu.Vendor_intel) + { + // Intel + switch (cpu.family()) + { + case 5: + perf_event_type = P5; + if (cpu.local_features() & Cpu::Lf_rdpmc) + { + perfctr_type = Perfctr_x86_intel_p5mmx; + perf_type_str = "P5MMX"; + read_pmc_fns = p6_read_pmc_fns; + } + else + { + perfctr_type = Perfctr_x86_intel_p5; + perf_type_str = "P5"; + read_pmc_fns = p5_read_pmc_fns; + } + pcnt = &perf_cnt_p5; + break; + + case 6: + perf_event_type = P6; + if (cpu.model() == 9 || cpu.model() == 13) + { + perfctr_type = Perfctr_x86_intel_pentm; + perf_type_str = "PntM"; + } + else if (cpu.model() >= 7) + { + perfctr_type = Perfctr_x86_intel_piii; + perf_type_str = "PIII"; + } + else if (cpu.model() >= 3) + { + perfctr_type = Perfctr_x86_intel_pii; + perf_type_str = "PII"; + } + else + { + perfctr_type = Perfctr_x86_intel_p6; + perf_type_str = "PPro"; + } + read_pmc_fns = p6_read_pmc_fns; + pcnt = &perf_cnt_p6; + break; + + case 15: + perf_event_type = P4; + if (cpu.model() >= 3) + { + perfctr_type = Perfctr_x86_intel_p4m3; + perf_type_str = "P4M3"; + } + else if (cpu.model() >= 2) + { + perfctr_type = Perfctr_x86_intel_p4m2; + perf_type_str = "P4M2"; + } + else + { + perfctr_type = Perfctr_x86_intel_p4; + perf_type_str = "P4"; + } + read_pmc_fns = p4_read_pmc_fns; + pcnt = &perf_cnt_p4; + break; + } + } + else if (cpu.vendor() == Cpu::Vendor_amd) + { + // AMD + switch (cpu.family()) + { + case 6: + case 15: + case 16: + if (cpu.family() == 15) + { + perf_type_str = "K8"; + perfctr_type = Perfctr_x86_amd_k8; + } + else + { + perf_type_str = "K7"; + perfctr_type = Perfctr_x86_amd_k7; + } + perf_event_type = P6; + read_pmc_fns = k7_read_pmc_fns; + pcnt = &perf_cnt_k7; + break; + } + } + } + + // set PCE-Flag in CR4 to enable read of performace measurement + // counters in usermode. PMC were introduced in Pentium MMX and + // PPro processors. + if (cpu.local_features() & Cpu::Lf_rdpmc) + cpu.enable_rdpmc(); + } + + if (pcnt && !pcnt->init()) + { + perfctr_type = Perfctr_x86_generic; + pcnt = 0; // init failed, no performance counters available + } + + if (perfctr_cpu_event_set != 0 && perfctr_cpu_event_set(perfctr_type) == 0) + { + perfctr_type = Perfctr_x86_generic; + pcnt = 0; // init failed, no performance counters available + } + + // tell perflib the cpu type + if (perfctr_set_cputype != 0) + perfctr_set_cputype(perfctr_type); + +} + +PUBLIC static inline void FIASCO_INIT_CPU +Perf_cnt::init_ap() +{ + Perf_cnt::pcnt->init(); + Perf_cnt::pcnt->init_loadcnt(); + Perf_cnt::pcnt->start_pmc(0); +} + +PUBLIC static inline NOEXPORT void +Perf_cnt::set_pmc_fn(Mword slot, Mword nr) +{ read_pmc_fn[slot] = read_pmc_fns[nr]; } + +// watchdog supported by performance counter architecture? +PUBLIC static inline +int +Perf_cnt::have_watchdog() +{ return (pcnt && pcnt->have_watchdog()); } + +// setup watchdog function with timeout in seconds +PUBLIC static inline +void +Perf_cnt::setup_watchdog(Mword timeout) +{ + if (pcnt) + pcnt->setup_watchdog(timeout); +} + +PUBLIC static inline +void +Perf_cnt::setup_loadcnt() +{ + if (pcnt) + pcnt->setup_loadcnt(); +} + +PUBLIC static inline +void +Perf_cnt::start_watchdog() +{ + if (pcnt && pcnt->watchdog_allocated()) + { + pcnt->touch_watchdog(); + pcnt->start_watchdog(); + } +} + +PUBLIC static inline +void +Perf_cnt::stop_watchdog() +{ + if (pcnt && pcnt->watchdog_allocated()) + pcnt->stop_watchdog(); +} + +PUBLIC static inline +void +Perf_cnt::touch_watchdog() +{ + if (pcnt && pcnt->watchdog_allocated()) + pcnt->touch_watchdog(); +} + +// return human-readable type of performance counters +PUBLIC static inline +char const * +Perf_cnt::perf_type() +{ return perf_type_str; } + +// set performance counter counting the selected event in slot #slot +PUBLIC static +int +Perf_cnt::setup_pmc(Mword slot, Mword event, Mword user, Mword kern, Mword edge) +{ + if (!pcnt) + return 0; + + unsigned nr, evntsel; + Mword bitmask, unit_mask; + const struct perfctr_event *pe = 0; + + split_event(event, &evntsel, &unit_mask); + if (perfctr_lookup_event != 0) + pe = perfctr_lookup_event(evntsel, &nr); + bitmask = pe ? pe->counters_set : 0xffff; + pcnt->setup_pmc(slot, bitmask, event, user, kern, edge); + Tb_entry::set_rdcnt(slot, (kern | user) ? read_pmc_fn[slot] : 0); + return 1; +} + +// return current selected event for a slot #slot +PUBLIC static +int +Perf_cnt::mode(Mword slot, const char **mode, const char **name, + Mword *event, Mword *user, Mword *kern, Mword *edge) +{ + if (!perf_type() || !pcnt) + { + *mode = "off"; + *event = *user = *kern = 0; + return 0; + } + + unsigned nr, evntsel; + Mword unit_mask; + const struct perfctr_event *pe = 0; + + pcnt->mode(slot, mode, event, user, kern, edge); + split_event(*event, &evntsel, &unit_mask); + if (perfctr_lookup_event != 0) + pe = perfctr_lookup_event(evntsel, &nr); + *name = pe ? pe->name : ""; + return 1; +} + +PUBLIC static Mword +Perf_cnt::get_max_perf_event() +{ return (perfctr_get_max_event != 0) ? perfctr_get_max_event() : 0; } + +PUBLIC static void +Perf_cnt::get_perf_event(Mword nr, unsigned *evntsel, + const char **name, const char **desc) +{ + const struct perfctr_event *pe = 0; + + if (perfctr_index_event != 0) + pe = perfctr_index_event(nr); + + *name = pe ? pe->name : 0; + *desc = pe ? pe->description : 0; + *evntsel = pe ? pe->evntsel : 0; +} + +PUBLIC static Mword +Perf_cnt::lookup_event(unsigned evntsel) +{ + unsigned nr; + + if (perfctr_lookup_event != 0 && perfctr_lookup_event(evntsel, &nr) != 0) + return nr; + return (Mword)-1; +} + +PUBLIC static void +Perf_cnt::get_unit_mask(Mword nr, Unit_mask_type *type, + Mword *default_value, Mword *nvalues) +{ + const struct perfctr_event *event = 0; + + if (perfctr_index_event != 0) + event = perfctr_index_event(nr); + + *type = None; + if (event && event->unit_mask) + { + *default_value = event->unit_mask->default_value; + switch (event->unit_mask->type) + { + case perfctr_um_type_fixed: *type = Fixed; break; + case perfctr_um_type_exclusive: *type = Exclusive; break; + case perfctr_um_type_bitmask: *type = Bitmask; break; + } + *nvalues = event->unit_mask->nvalues; + } +} + +PUBLIC static void +Perf_cnt::get_unit_mask_entry(Mword nr, Mword idx, + Mword *value, const char **desc) +{ + const struct perfctr_event *event = 0; + + if (perfctr_index_event != 0) + event = perfctr_index_event(nr); + + *value = 0; + *desc = 0; + if (event && event->unit_mask && (idx < event->unit_mask->nvalues)) + { + *value = event->unit_mask->values[idx].value; + *desc = event->unit_mask->values[idx].description; + } +} + +/** Split event into event selector and unit mask (depending on perftype). */ +PUBLIC static +void +Perf_cnt::split_event(Mword event, unsigned *evntsel, Mword *unit_mask) +{ + switch (perf_event_type) + { + case P5: + *evntsel = event; + *unit_mask = 0; + break; + case P6: + *evntsel = event & 0x000000ff; + *unit_mask = (event & 0x0000ff00) >> 8; + break; + case P4: + default: + *evntsel = 0; + *unit_mask = 0; + break; + } +} + +/** Combine event from selector and unit mask. */ +PUBLIC static +void +Perf_cnt::combine_event(Mword evntsel, Mword unit_mask, Mword *event) +{ + switch (perf_event_type) + { + case P5: + *event = evntsel; + break; + case P6: + *event = (evntsel & 0x000000ff) + ((unit_mask & 0x000000ff) << 8); + break; + case P4: + break; + } +} diff --git a/kernel/fiasco/src/kern/ia32/rtc-ia32.cpp b/kernel/fiasco/src/kern/ia32/rtc-ia32.cpp new file mode 100644 index 00000000..be7c4b90 --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/rtc-ia32.cpp @@ -0,0 +1,124 @@ +INTERFACE[ia32,amd64]: + +class Rtc +{ +private: + Rtc(); + Rtc(const Rtc&); +}; + +IMPLEMENTATION[ia32,amd64]: + +#include "io.h" +#include "globalconfig.h" + +#define RTC_STATUSA 0x0a /* status register A */ +#define RTCSA_TUP 0x80 /* time update, don't look now */ +#define RTCSA_DIVIDER 0x20 /* divider correct for 32768 Hz */ +#define RTCSA_8192 0x03 +#define RTCSA_4096 0x04 +#define RTCSA_2048 0x05 +#define RTCSA_1024 0x06 +#define RTCSA_512 0x07 +#define RTCSA_256 0x08 +#define RTCSA_128 0x09 +#define RTCSA_64 0x0a +#define RTCSA_32 0x0b + +#define RTC_STATUSB 0x0b /* status register B */ +#define RTCSB_DST 0x01 /* Daylight Savings Time enable */ +#define RTCSB_24HR 0x02 /* 0 = 12 hours, 1 = 24 hours */ +#define RTCSB_BCD 0x04 /* 0 = BCD, 1 = Binary coded time */ +#define RTCSB_SQWE 0x08 /* 1 = output sqare wave at SQW pin */ +#define RTCSB_UINTR 0x10 /* 1 = enable update-ended interrupt */ +#define RTCSB_AINTR 0x20 /* 1 = enable alarm interrupt */ +#define RTCSB_PINTR 0x40 /* 1 = enable periodic clock interrupt */ +#define RTCSB_HALT 0x80 /* stop clock updates */ + +#define RTC_INTR 0x0c /* status register C (R) interrupt source */ +#define RTCIR_UPDATE 0x10 /* update intr */ +#define RTCIR_ALARM 0x20 /* alarm intr */ +#define RTCIR_PERIOD 0x40 /* periodic intr */ +#define RTCIR_INT 0x80 /* interrupt output signal */ + + +static inline +unsigned char +Rtc::reg_read(unsigned char reg) +{ + Io::out8_p(reg, 0x70); + return Io::in8_p(0x71); +} + +static inline +void +Rtc::reg_write(unsigned char reg, unsigned char val) +{ + Io::out8_p(reg,0x70); + Io::out8_p(val,0x71); +} + +// set up timer interrupt (~ 1ms) +PUBLIC static +void +Rtc::init() +{ + while (reg_read(RTC_STATUSA) & RTCSA_TUP) + ; // wait till RTC ready + +#ifdef CONFIG_SLOW_RTC + // set divider to 64 Hz + reg_write(RTC_STATUSA, RTCSA_DIVIDER | RTCSA_64); +#else + // set divider to 1024 Hz + reg_write(RTC_STATUSA, RTCSA_DIVIDER | RTCSA_1024); +#endif + + // set up interrupt + reg_write(RTC_STATUSB, reg_read(RTC_STATUSB) | RTCSB_PINTR | RTCSB_SQWE); + + // reset + reg_read(RTC_INTR); +} + +PUBLIC static +void +Rtc::done() +{ + // disable all potential interrupt sources + reg_write(RTC_STATUSB, + reg_read(RTC_STATUSB) & ~(RTCSB_PINTR | RTCSB_AINTR | RTCSB_UINTR)); + + // reset + reg_read(RTC_INTR); +} + +PUBLIC static +void +Rtc::set_freq_slow() +{ + // set divider to 32 Hz + reg_write(RTC_STATUSA, RTCSA_DIVIDER | RTCSA_32); +} + +PUBLIC static +void +Rtc::set_freq_normal() +{ + // set divider to 1024 Hz + reg_write(RTC_STATUSA, RTCSA_DIVIDER | RTCSA_1024); +} + +// acknowledge RTC interrupt +PUBLIC static inline +void +Rtc::reset() +{ + // reset irq by reading the cmos port + // do it fast because we are cli'd + asm volatile ("movb $0xc, %%al\n\t" + "outb %%al,$0x70\n\t" + "outb %%al,$0x80\n\t" + "inb $0x71,%%al\n\t" : : : "eax"); +} + diff --git a/kernel/fiasco/src/kern/ia32/shortcut.h b/kernel/fiasco/src/kern/ia32/shortcut.h new file mode 100644 index 00000000..4eaff71a --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/shortcut.h @@ -0,0 +1,125 @@ +#ifndef SHORTCUT_H +#define SHORTCUT_H + +#include "globalconfig.h" + +// thread_state consts +#define Thread_ready 0x1 +#define Thread_utcb_ip_sp 0x2 +#define Thread_receiving 0x4 +#define Thread_polling 0x8 +#define Thread_ipc_in_progress 0x10 +#define Thread_send_in_progress 0x20 +#define Thread_busy 0x40 +#define Thread_cancel 0x100 +#define Thread_dead 0x200 +#define Thread_delayed_deadline 0x2000 +#define Thread_delayed_ipc 0x4000 +#define Thread_fpu_owner 0x8000 +#define Thread_alien_or_vcpu_user 0x810000 +#define Thread_dis_alien 0x20000 +#define Thread_transfer_in_progress 0x80000 + +#define Thread_ipc_sending_mask (Thread_send_in_progress | \ + Thread_polling) +#define Thread_ipc_receiving_mask (Thread_receiving | \ + Thread_busy | \ + Thread_transfer_in_progress) +#define Thread_ipc_mask (Thread_ipc_in_progress | \ + Thread_ipc_sending_mask | \ + Thread_ipc_receiving_mask) + +// stackframe structure +#ifdef CONFIG_BIT32 +#define REG_ECX +#define REG_EDX (1*4) +#define REG_ESI (2*4) +#define REG_EDI (3*4) +#define REG_EBX (4*4) +#define REG_EBP (5*4) +#define REG_EAX (6*4) +#define REG_EIP (7*4) +#define REG_CS (8*4) +#define REG_EFL (9*4) +#define REG_ESP (10*4) +#define REG_SS (11*4) +#else + + + +/* +#define REG_RAX (THREAD_BLOCK_SIZE - 6*8) +#define REG_RBP (THREAD_BLOCK_SIZE - 7*8) +#define REG_RBX (THREAD_BLOCK_SIZE - 8*8) +#define REG_RDI (THREAD_BLOCK_SIZE - 9*8) +#define REG_RSI (THREAD_BLOCK_SIZE - 10*8) + +#define REG_RDX (THREAD_BLOCK_SIZE - 11*8) +#define REG_RCX (THREAD_BLOCK_SIZE - 12*8) + +#define REG_R8 (THREAD_BLOCK_SIZE - 13*8) +#define REG_R9 (THREAD_BLOCK_SIZE - 14*8) +#define REG_R10 (THREAD_BLOCK_SIZE - 15*8) +#define REG_R11 (THREAD_BLOCK_SIZE - 16*8) +#define REG_R12 (THREAD_BLOCK_SIZE - 17*8) +#define REG_R13 (THREAD_BLOCK_SIZE - 18*8) +#define REG_R14 (THREAD_BLOCK_SIZE - 19*8) +#define REG_R15 (THREAD_BLOCK_SIZE - 20*8) +*/ + +#define REG_R15 +#define REG_R14 (1*8) +#define REG_R13 (2*8) +#define REG_R12 (3*8) +#define REG_R11 (4*8) +#define REG_R10 (5*8) +#define REG_R9 (6*8) +#define REG_R8 (7*8) +#define REG_RCX (8*8) +#define REG_RDX (9*8) +#define REG_RSI (10*8) +#define REG_RDI (11*8) +#define REG_RBX (12*8) +#define REG_RBP (13*8) +#define REG_RAX (14*8) +#define REG_RIP (15*8) +#define REG_CS (16*8) +#define REG_RFL (17*8) +#define REG_RSP (18*8) +#define REG_SS (19*8) + +#endif + +#ifdef CONFIG_ABI_X0 +# define RETURN_DOPE 0x6000 // three dwords +# define TCB_ADDRESS_MASK 0x01fff800 +#else +# define RETURN_DOPE 0x4000 // two dwords +# define TCB_ADDRESS_MASK 0x1ffff800 +#endif + + +#if defined(CONFIG_JDB) && defined(CONFIG_JDB_ACCOUNTING) + +#define CNT_CONTEXT_SWITCH incl (VAL__MEM_LAYOUT__TBUF_STATUS_PAGE+ \ + OFS__TBUF_STATUS__KERNCNTS) +#define CNT_ADDR_SPACE_SWITCH incl (VAL__MEM_LAYOUT__TBUF_STATUS_PAGE+ \ + OFS__TBUF_STATUS__KERNCNTS + 4) +#define CNT_SHORTCUT_FAILED incl (VAL__MEM_LAYOUT__TBUF_STATUS_PAGE+ \ + OFS__TBUF_STATUS__KERNCNTS + 8) +#define CNT_SHORTCUT_SUCCESS incl (VAL__MEM_LAYOUT__TBUF_STATUS_PAGE+ \ + OFS__TBUF_STATUS__KERNCNTS + 12) +#define CNT_IOBMAP_TLB_FLUSH incl (VAL__MEM_LAYOUT__TBUF_STATUS_PAGE+ \ + OFS__TBUF_STATUS__KERNCNTS + 40) + +#else + +#define CNT_CONTEXT_SWITCH +#define CNT_ADDR_SPACE_SWITCH +#define CNT_SHORTCUT_FAILED +#define CNT_SHORTCUT_SUCCESS +#define CNT_IOBMAP_TLB_FLUSH + +#endif + +#endif diff --git a/kernel/fiasco/src/kern/ia32/space-ia32.cpp b/kernel/fiasco/src/kern/ia32/space-ia32.cpp new file mode 100644 index 00000000..eeff4cac --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/space-ia32.cpp @@ -0,0 +1,66 @@ +INTERFACE [ia32 || amd64]: + +#include "spin_lock.h" + +EXTENSION class Space +{ +protected: + class Ldt + { + public: + Ldt() : _addr(0), _size(0) {} + Address addr() const { return (Address)_addr; } + Mword size() const { return _size; } + + void size(Mword); + void alloc(); + + ~Ldt(); + + private: + void *_addr; + Mword _size; + }; + + friend class Jdb_misc_debug; + + Ldt _ldt; +}; + +// --------------------------------------------------------------- +IMPLEMENTATION [ia32 || amd64]: + +#include "cpu.h" +#include "globals.h" +#include "mem.h" + +IMPLEMENT inline +void +Space::Ldt::size(Mword size) +{ _size = size; } + +IMPLEMENT inline NEEDS["mem.h"] +void +Space::Ldt::alloc() +{ + // LDT maximum size is one page + _addr = Kmem_alloc::allocator()->alloc(Config::PAGE_SHIFT); + Mem::memset_mwords(reinterpret_cast(addr()), 0, + Config::PAGE_SIZE / sizeof(Mword)); +} + +IMPLEMENT inline +Space::Ldt::~Ldt() +{ + if (addr()) + Kmem_alloc::allocator()->free(Config::PAGE_SHIFT, + reinterpret_cast(addr())); +} + + +IMPLEMENT inline NEEDS["cpu.h", "globals.h"] +void +Space::switchin_ldt() const +{ + Cpu::cpus.cpu(current_cpu()).enable_ldt(_ldt.addr(), _ldt.size()); +} diff --git a/kernel/fiasco/src/kern/ia32/spin_lock-ia32.cpp b/kernel/fiasco/src/kern/ia32/spin_lock-ia32.cpp new file mode 100644 index 00000000..8e488d91 --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/spin_lock-ia32.cpp @@ -0,0 +1,43 @@ +//--------------------------------------------------------------------------- +INTERFACE [(ia32|ux|amd64) && mp]: + +EXTENSION class Spin_lock +{ +public: + enum { Arch_lock = 2 }; +}; + +//-------------------------------------------------------------------------- +IMPLEMENTATION [(ia32|ux|amd64) && mp]: + +PRIVATE template inline +void +Spin_lock::lock_arch() +{ + Lock_t dummy, tmp; +#define L(z) \ + __asm__ __volatile__ ( \ + "1: mov %[lock], %[tmp] \n" \ + " test $2, %[tmp] \n" /* Arch_lock == #2 */ \ + " jz 2f \n" \ + " pause \n" \ + " jmp 1b \n" \ + "2: mov %[tmp], %[d] \n" \ + " or $2, %[d] \n" \ + " lock; cmpxchg %[d], %[lock] \n" \ + " jnz 1b \n" \ + : [d] "=&"#z (dummy), [tmp] "=&a" (tmp), [lock] "+m" (_lock)) + + if (sizeof(Lock_t) > sizeof(char)) + L(r); + else + L(q); +#undef L +} + +PRIVATE template inline +void +Spin_lock::unlock_arch() +{ + _lock &= ~Arch_lock; +} diff --git a/kernel/fiasco/src/kern/ia32/startup-ia32.cpp b/kernel/fiasco/src/kern/ia32/startup-ia32.cpp new file mode 100644 index 00000000..2d07d40e --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/startup-ia32.cpp @@ -0,0 +1,119 @@ +IMPLEMENTATION[ia32,amd64]: + +#include +#include + +#include "apic.h" +#include "banner.h" +#include "boot_console.h" +#include "boot_info.h" +#include "config.h" +#include "cpu.h" +#include "fpu.h" +#include "idt.h" +#include "initcalls.h" +#include "io_apic.h" +#include "ipi.h" +#include "irq_chip_pic.h" +#include "irq_mgr.h" +#include "kernel_console.h" +#include "kernel_task.h" +#include "kip_init.h" +#include "kernel_uart.h" +#include "kmem.h" +#include "kmem_alloc.h" +#include "per_cpu_data.h" +#include "per_cpu_data_alloc.h" +#include "pic.h" +#include "static_init.h" +#include "std_macros.h" +#include "thread.h" +#include "timer.h" +#include "utcb_init.h" + +#include "io_apic.h" + +IMPLEMENT FIASCO_INIT FIASCO_NOINLINE +void +Startup::stage1() +{ + Boot_info::init(); + Config::init(); + if (Kernel_uart::init(Kernel_uart::Init_before_mmu)) + Banner::init(); +} + +IMPLEMENT FIASCO_INIT FIASCO_NOINLINE +void +Startup::stage2() +{ + Kip_init::init(); + Kmem_alloc::init(); + + // initialize initial page tables (also used for other CPUs later) + Kmem::init_mmu(); + + if (Kernel_uart::init(Kernel_uart::Init_after_mmu)) + Banner::init(); + + // Initialize cpu-local data management and run constructors for CPU 0 + Per_cpu_data::init_ctors(); + Per_cpu_data_alloc::alloc(0); + Per_cpu_data::run_ctors(0); + + // set frequency in KIP to that of the boot CPU + Kip_init::init_freq(Cpu::cpus.cpu(0)); + + bool use_io_apic = Io_apic::init(); + if (use_io_apic) + { + Config::apic = true; + Pic::disable_all_save(); + } + else + { + Pic::init(); + Irq_chip_ia32_pic::init(); + } + + Kernel_task::init(); // enables current_mem_space() + + // initialize initial TSS, GDT, IDT + Kmem::init_cpu(Cpu::cpus.cpu(0)); + Utcb_init::init(); + Idt::init(); + Fpu::init(0); + Apic::init(); + Ipi::init(0); + Timer::init(0); + int timer_irq = Timer::irq(); + if (use_io_apic) + { + // If we use the IOAPIC, we route our timer IRQ to + // Config::Apic_timer_vector, even with PIT or RTC + Config::scheduler_irq_vector = Config::Apic_timer_vector; + + if (timer_irq >= 0) + { + Irq_mgr *const m = Irq_mgr::mgr; + Irq_mgr::Irq const irq = m->chip(m->legacy_override(timer_irq)); + Io_apic *const apic = static_cast(irq.chip); + + Io_apic_entry e = apic->read_entry(irq.pin); + e.vector(Config::Apic_timer_vector); + apic->write_entry(irq.pin, e); + } + } + else + { + if (timer_irq >= 0) + Config::scheduler_irq_vector = 0x20 + timer_irq; + else + Config::scheduler_irq_vector = Config::Apic_timer_vector; + } + + Idt::set_vectors_run(); + Timer::master_cpu(0); + Apic::check_still_getting_interrupts(); +// Cpu::init_global_features(); +} diff --git a/kernel/fiasco/src/kern/ia32/svm.cpp b/kernel/fiasco/src/kern/ia32/svm.cpp new file mode 100644 index 00000000..65ae3ed0 --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/svm.cpp @@ -0,0 +1,244 @@ +INTERFACE: + +class Svm +{ +}; + +//----------------------------------------------------------------------------- +INTERFACE[svm]: + +#include "per_cpu_data.h" +#include "virt.h" +#include "cpu_lock.h" + +EXTENSION class Svm +{ +public: + static Per_cpu cpus; + + enum Msr_perms + { + Msr_intercept = 3, + Msr_ro = 2, + Msr_wo = 1, + Msr_rw = 0, + }; + +private: + void *_vm_hsave_area; + void *_iopm; + void *_msrpm; + Unsigned32 _next_asid; + Unsigned32 _global_asid_generation; + Unsigned32 _max_asid; + bool _flush_all_asids; + bool _svm_enabled; + bool _has_npt; + Unsigned64 _iopm_base_pa; + Unsigned64 _msrpm_base_pa; + Vmcb *_kernel_vmcb; + Address _kernel_vmcb_pa; +}; + +//----------------------------------------------------------------------------- +INTERFACE [svm && ia32]: + +EXTENSION class Svm +{ +public: + enum { Gpregs_words = 10 }; +}; + +//----------------------------------------------------------------------------- +INTERFACE [svm && amd64]: + +EXTENSION class Svm +{ +public: + enum { Gpregs_words = 18 }; +}; + +// ----------------------------------------------------------------------- +IMPLEMENTATION[svm]: + +#include "cpu.h" +#include "kmem.h" +#include "l4_types.h" +#include "warn.h" +#include + +DEFINE_PER_CPU Per_cpu Svm::cpus(true); + +PUBLIC +Svm::Svm(unsigned cpu) +{ + Cpu &c = Cpu::cpus.cpu(cpu); + _svm_enabled = false; + _next_asid = 1; + _global_asid_generation = 0; + _max_asid = 0; + _flush_all_asids = true; + _has_npt = false; + + if (!c.svm()) + return; + + Unsigned64 efer, vmcr; + + vmcr = c.rdmsr(MSR_VM_CR); + if (vmcr & (1 << 4)) // VM_CR.SVMDIS + { + printf("SVM supported but locked.\n"); + return; + } + + printf("Enabling SVM support\n"); + + efer = c.rdmsr(MSR_EFER); + efer |= 1 << 12; + c.wrmsr(efer, MSR_EFER); + + Unsigned32 eax, ebx, ecx, edx; + c.cpuid (0x8000000a, &eax, &ebx, &ecx, &edx); + if (edx & 1) + { + printf("Nested Paging supported\n"); + _has_npt = true; + } + printf("NASID: 0x%x\n", ebx); + _max_asid = ebx - 1; + assert(_max_asid > 0); + + enum + { + Vmcb_size = 0x1000, + Io_pm_size = 0x3000, + Msr_pm_size = 0x2000, + State_save_area_size = 0x1000, + }; + + /* 16kB IO permission map and Vmcb (16kB are good for the buddy allocator)*/ + check(_iopm = Kmem_alloc::allocator()->unaligned_alloc(Io_pm_size + Vmcb_size)); + _iopm_base_pa = Kmem::virt_to_phys(_iopm); + _kernel_vmcb = (Vmcb*)((char*)_iopm + Io_pm_size); + _kernel_vmcb_pa = Kmem::virt_to_phys(_kernel_vmcb); + _svm_enabled = true; + + /* disbale all ports */ + memset(_iopm, ~0, Io_pm_size); + + /* clean out vmcb */ + memset(_kernel_vmcb, 0, Vmcb_size); + + /* 8kB MSR permission map */ + check(_msrpm = Kmem_alloc::allocator()->unaligned_alloc(Msr_pm_size)); + _msrpm_base_pa = Kmem::virt_to_phys(_msrpm); + memset(_msrpm, ~0, Msr_pm_size); + + // allow the sysenter MSRs for the guests + set_msr_perm(MSR_SYSENTER_CS, Msr_rw); + set_msr_perm(MSR_SYSENTER_EIP, Msr_rw); + set_msr_perm(MSR_SYSENTER_ESP, Msr_rw); + + /* 4kB Host state-safe area */ + check(_vm_hsave_area = Kmem_alloc::allocator()->unaligned_alloc(State_save_area_size)); + Unsigned64 vm_hsave_pa = Kmem::virt_to_phys(_vm_hsave_area); + + c.wrmsr(vm_hsave_pa, MSR_VM_HSAVE_PA); +} + +PUBLIC +void +Svm::set_msr_perm(Unsigned32 msr, Msr_perms perms) +{ + unsigned offs; + if (msr <= 0x1fff) + offs = 0; + else if (0xc0000000 <= msr && msr <= 0xc0001fff) + offs = 0x800; + else if (0xc0010000 <= msr && msr <= 0xc0011fff) + offs = 0x1000; + else + { + WARN("Illegal MSR %x\n", msr); + return; + } + + msr &= 0x1fff; + offs += msr / 4; + + unsigned char *pm = (unsigned char *)_msrpm; + + unsigned shift = (msr & 3) * 2; + pm[offs] = (pm[offs] & ~(3 << shift)) | ((unsigned char)perms << shift); +} + +PUBLIC +Unsigned64 +Svm::iopm_base_pa() +{ return _iopm_base_pa; } + +PUBLIC +Unsigned64 +Svm::msrpm_base_pa() +{ return _msrpm_base_pa; } + +PUBLIC +Vmcb * +Svm::kernel_vmcb() +{ return _kernel_vmcb; } + +PUBLIC +Address +Svm::kernel_vmcb_pa() +{ return _kernel_vmcb_pa; } + +PUBLIC +bool +Svm::svm_enabled() +{ return _svm_enabled; } + +PUBLIC +bool +Svm::has_npt() +{ return _has_npt; } + +PUBLIC +bool +Svm::asid_valid (Unsigned32 asid, Unsigned32 generation) +{ + return ((asid > 0) && + (asid <= _max_asid) && + (generation <= _global_asid_generation)); +} + +PUBLIC +bool +Svm::flush_all_asids() +{ return _flush_all_asids; } + +PUBLIC +void +Svm::flush_all_asids(bool val) +{ _flush_all_asids = val; } + +PUBLIC +Unsigned32 +Svm::global_asid_generation() +{ return _global_asid_generation; } + +PUBLIC +Unsigned32 +Svm::next_asid () +{ + assert(cpu_lock.test()); + _flush_all_asids = false; + if (_next_asid > _max_asid) + { + _global_asid_generation++; + _next_asid = 1; + assert (_global_asid_generation < ~0U); + _flush_all_asids = true; + } + return _next_asid++; +} diff --git a/kernel/fiasco/src/kern/ia32/task-ia32-amd64.cpp b/kernel/fiasco/src/kern/ia32/task-ia32-amd64.cpp new file mode 100644 index 00000000..da04e5b2 --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/task-ia32-amd64.cpp @@ -0,0 +1,76 @@ +IMPLEMENTATION [ia32 || amd64]: + +#include "gdt.h" +#include "std_macros.h" +#include "x86desc.h" + +PRIVATE inline NEEDS["gdt.h"] +bool +Task::invoke_arch(L4_msg_tag &tag, Utcb *utcb) +{ + switch (utcb->values[0]) + { + case Ldt_set_x86: + { + enum + { + Utcb_values_per_ldt_entry + = Cpu::Ldt_entry_size / sizeof(utcb->values[0]), + }; + if (EXPECT_FALSE(tag.words() < 3 + || tag.words() % Utcb_values_per_ldt_entry)) + { + tag = commit_result(-L4_err::EInval); + return true; + } + + unsigned entry_number = utcb->values[1]; + unsigned size = (tag.words() - 2) * sizeof(utcb->values[0]); + + // Allocate the memory if not yet done + if (!_ldt.addr()) + _ldt.alloc(); + + if (entry_number * Cpu::Ldt_entry_size + size > Config::PAGE_SIZE) + { + WARN("set_ldt: LDT size exceeds one page, not supported."); + tag = commit_result(-L4_err::EInval); + return true; + } + + _ldt.size(size + Cpu::Ldt_entry_size * entry_number); + + Address desc_addr = reinterpret_cast
(&utcb->values[2]); + Gdt_entry desc; + Gdt_entry *ldtp + = reinterpret_cast(_ldt.addr()) + entry_number; + + while (size >= Cpu::Ldt_entry_size) + { + desc = *reinterpret_cast(desc_addr); + if (desc.unsafe()) + { + WARN("set_ldt: Bad descriptor."); + tag = commit_result(-L4_err::EInval); + return true; + } + + *ldtp = desc; + size -= Cpu::Ldt_entry_size; + desc_addr += Cpu::Ldt_entry_size; + ldtp++; + } + + if (this == current()->space()) + Cpu::cpus.cpu(current_cpu()).enable_ldt(_ldt.addr(), _ldt.size()); + + tag = commit_result(0); + } + return true; + } + + + + + return false; +} diff --git a/kernel/fiasco/src/kern/ia32/thread-ia32.cpp b/kernel/fiasco/src/kern/ia32/thread-ia32.cpp new file mode 100644 index 00000000..d2320f9d --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/thread-ia32.cpp @@ -0,0 +1,821 @@ +/* + * Fiasco Thread Code + * Shared between UX and native IA32. + */ +INTERFACE [ia32,amd64,ux]: + +#include "trap_state.h" + +class Idt_entry; + +EXTENSION class Thread +{ +private: + /** + * Return code segment used for exception reflection to user mode + */ + static Mword exception_cs(); + +protected: + static Trap_state::Handler nested_trap_handler FIASCO_FASTCALL; +}; + + +//---------------------------------------------------------------------------- +INTERFACE [ia32,amd64]: + +class Trap_state; + +EXTENSION class Thread +{ +private: + static int (*int3_handler)(Trap_state*); +}; + + +//---------------------------------------------------------------------------- +IMPLEMENTATION [ia32,amd64,ux]: + +#include "config.h" +#include "cpu.h" +#include "cpu_lock.h" +#include "gdt.h" +#include "idt.h" +#include "ipi.h" +#include "mem_layout.h" +#include "logdefs.h" +#include "paging.h" +#include "processor.h" // for cli/sti +#include "regdefs.h" +#include "std_macros.h" +#include "thread.h" +#include "timer.h" +#include "trap_state.h" + +Trap_state::Handler Thread::nested_trap_handler FIASCO_FASTCALL; + +IMPLEMENT +Thread::Thread() +: Receiver(), + Sender(0), // select optimized version of constructor + _pager(Thread_ptr::Invalid), + _exc_handler(Thread_ptr::Invalid), + _del_observer(0) +{ + //assert (current() == thread_lock()->lock_owner()); + assert (state() == Thread_invalid); + + inc_ref(); + _space.space(Kernel_task::kernel_task()); + + if (Config::Stack_depth) + std::memset((char*)this + sizeof(Thread), '5', + Thread::Size-sizeof(Thread)-64); + + _magic = magic; + _recover_jmpbuf = 0; + _timeout = 0; + + *reinterpret_cast (--_kernel_sp) = user_invoke; + + arch_init(); + + state_add_dirty(Thread_dead | Thread_suspended); + + // ok, we're ready to go! +} + +IMPLEMENT inline NEEDS[Thread::exception_triggered] +Mword +Thread::user_ip() const +{ return exception_triggered()?_exc_cont.ip():regs()->ip(); } + +IMPLEMENT inline +Mword +Thread::user_flags() const +{ return regs()->flags(); } + +/** Check if the pagefault occured at a special place: At some places in the + kernel we want to ensure that a specific address is mapped. The regular + case is "mapped", the exception or slow case is "not mapped". The fastest + way to check this is to touch into the memory. If there is no mapping for + the address we get a pagefault. Now the pagefault exception handler can + recognize that situation by scanning the code. The trick is that the + assembler instruction "andl $0xffffffff, %ss:(%ecx)" _clears_ the carry + flag normally (see Intel reference manual). The pager wants to inform the + code that there was a pagefault and therefore _sets_ the carry flag. So + the code has only to check if the carry flag is set. If yes, there was + a pagefault at this instruction. + @param ip pagefault address */ +IMPLEMENT inline +bool +Thread::pagein_tcb_request(Return_frame *regs) +{ + unsigned long new_ip = regs->ip(); + if (*(Unsigned8*)new_ip == 0x48) // REX.W + new_ip += 1; + + register Unsigned16 op = *(Unsigned16*)new_ip; + //LOG_MSG_3VAL(current(),"TCB", op, new_ip, 0); + if ((op & 0xc0ff) == 0x8b) // Context::is_tcb_mapped() and Context::state() + { + regs->ip(new_ip + 2); + // stack layout: + // user eip + // PF error code + // reg => eax/rax + // ecx/rcx + // edx/rdx + // ... + Mword *reg = ((Mword*)regs) - 2 - Return_frame::Pf_ax_offset; +#if 0 + LOG_MSG_3VAL(current(),"TCB", op, regs->ip(), (Mword)reg); + LOG_MSG_3VAL(current(),"TCBX", reg[-3], reg[-4], reg[-5]); + LOG_MSG_3VAL(current(),"TCB0", reg[0], reg[-1], reg[-2]); + LOG_MSG_3VAL(current(),"TCB1", reg[1], reg[2], reg[3]); +#endif + assert((op >> 11) <= 2); + reg[-(op>>11)] = 0; // op==0 => eax, op==1 => ecx, op==2 => edx + + // tell program that a pagefault occured we cannot handle + regs->flags(regs->flags() | 0x41); // set carry and zero flag in EFLAGS + return true; + } + else if (*(Unsigned32*)regs->ip() == 0xff01f636) // used in shortcut.S + { + regs->ip(regs->ip() + 4); + regs->flags(regs->flags() | 1); // set carry flag in EFLAGS + return true; + } + + return false; +} + + +extern "C" FIASCO_FASTCALL +void +thread_restore_exc_state() +{ + current_thread()->restore_exc_state(); +} + +PRIVATE static +void +Thread::print_page_fault_error(Mword e) +{ + printf("%lx", e); +} + +/** + * The global trap handler switch. + * This function handles CPU-exception reflection, emulation of CPU + * instructions (LIDT, WRMSR, RDMSR), int3 debug messages, + * kernel-debugger invocation, and thread crashes (if a trap cannot be + * handled). + * @param state trap state + * @return 0 if trap has been consumed by handler; + * -1 if trap could not be handled. + */ +PUBLIC +int +Thread::handle_slow_trap(Trap_state *ts) +{ + Address ip; + int from_user = ts->cs() & 3; + + if (EXPECT_FALSE(ts->_trapno == 0xee)) //debug IPI + { + Ipi::eoi(Ipi::Debug, cpu()); + goto generic_debug; + } + + if (from_user && _space.user_mode()) + { + if (ts->_trapno == 14 && Kmem::is_io_bitmap_page_fault(ts->_cr2)) + { + ts->_trapno = 13; + ts->_err = 0; + } + + if (send_exception(ts)) + goto success; + } + + // XXX We might be forced to raise an excepton. In this case, our return + // CS:IP points to leave_by_trigger_exception() which will trigger the + // exception just before returning to userland. But if we were inside an + // IPC while we was ex-regs'd, we will generate the 'exception after the + // syscall' _before_ we leave the kernel. + if (ts->_trapno == 13 && (ts->_err & 6) == 6) + goto check_exception; + + LOG_TRAP; + + if (!check_trap13_kernel (ts)) + return 0; + + if (EXPECT_FALSE(!from_user)) + { + // get also here if a pagefault was not handled by the user level pager + if (ts->_trapno == 14) + goto check_exception; + + goto generic_debug; // we were in kernel mode -- nothing to emulate + } + + if (EXPECT_FALSE(ts->_trapno == 2)) + goto generic_debug; // NMI always enters kernel debugger + + if (EXPECT_FALSE(ts->_trapno == 0xffffffff)) + goto generic_debug; // debugger interrupt + + check_f00f_bug(ts); + + // so we were in user mode -- look for something to emulate + + // We continue running with interrupts off -- no sti() here. But + // interrupts may be enabled by the pagefault handler if we get a + // pagefault in peek_user(). + + // Set up exception handling. If we suffer an un-handled user-space + // page fault, kill the thread. + jmp_buf pf_recovery; + unsigned error; + if (EXPECT_FALSE ((error = setjmp(pf_recovery)) != 0) ) + { + WARN ("%p killed:\n" + "\033[1mUnhandled page fault, code=%08x\033[m\n", + this, error); + goto fail_nomsg; + } + + _recover_jmpbuf = &pf_recovery; + + switch (handle_io_page_fault(ts)) + { + case 1: goto success; + case 2: goto fail; + default: break; + } + + ip = ts->ip(); + + // just print out some warning, we do the normal exception handling + handle_sysenter_trap(ts, ip, from_user); + _recover_jmpbuf = 0; + +check_exception: + + // send exception IPC if requested + if (send_exception(ts)) + goto success; + + // backward compatibility cruft: check for those insane "int3" debug + // messaging command sequences + if (ts->_trapno == 3) + { + if (int3_handler && int3_handler(ts)) + goto success; + + goto generic_debug; + } + + // privileged tasks also may invoke the kernel debugger with a debug + // exception + if (ts->_trapno == 1) + goto generic_debug; + + +fail: + // can't handle trap -- kill the thread + WARN ("%p killed:\n" + "\033[1mUnhandled trap \033[m\n", + this); + +fail_nomsg: + if ((int)Config::Warn_level >= Warning) + ts->dump(); + + halt(); + +success: + _recover_jmpbuf = 0; + return 0; + +generic_debug: + _recover_jmpbuf = 0; + + if (!nested_trap_handler) + return handle_not_nested_trap(ts); + + return call_nested_trap_handler(ts); +} + +/** + * The low-level page fault handler called from entry.S. We're invoked with + * interrupts turned off. Apart from turning on interrupts in almost + * all cases (except for kernel page faults in TCB area), just forwards + * the call to Thread::handle_page_fault(). + * @param pfa page-fault virtual address + * @param error_code CPU error code + * @return true if page fault could be resolved, false otherwise + */ +extern "C" FIASCO_FASTCALL +int +thread_page_fault(Address pfa, Mword error_code, Address ip, Mword flags, + Return_frame *regs) +{ + + // XXX: need to do in a different way, if on debug stack e.g. +#if 0 + // If we're in the GDB stub -- let generic handler handle it + if (EXPECT_FALSE (!in_context_area((void*)Proc::stack_pointer()))) + return false; +#endif + + // Pagefault in user mode or interrupts were enabled + if (PF::is_usermode_error(error_code)) + { + if (current_thread()->vcpu_pagefault(pfa, error_code, ip)) + return 1; + + Proc::sti(); + } + else if(flags & EFLAGS_IF) + Proc::sti(); + + // Pagefault in kernel mode and interrupts were disabled + else + { + // page fault in kernel memory region + if (Kmem::is_kmem_page_fault(pfa, error_code)) + { + // We've interrupted a context in the kernel with disabled interrupts, + // the page fault address is in the kernel region, the error code is + // "not mapped" (as opposed to "access error"), and the region is + // actually valid (that is, mapped in Kmem's shared page directory, + // just not in the currently active page directory) + // Remain cli'd !!! + } + else if (!Kmem::is_kmem_page_fault(pfa, error_code)) + { + // No error -- just enable interrupts. + Proc::sti(); + } + else + { + // Error: We interrupted a cli'd kernel context touching kernel space + if (!Thread::log_page_fault()) + printf("*P[%lx,%lx,%lx] ", pfa, error_code & 0xffff, ip); + + kdb_ke ("page fault in cli mode"); + } + } + + return current_thread()->handle_page_fault(pfa, error_code, ip, regs); +} + +/** The catch-all trap entry point. Called by assembly code when a + CPU trap (that's not specially handled, such as system calls) occurs. + Just forwards the call to Thread::handle_slow_trap(). + @param state trap state + @return 0 if trap has been consumed by handler; + -1 if trap could not be handled. + */ +extern "C" FIASCO_FASTCALL +int +thread_handle_trap(Trap_state *ts, unsigned) +{ + return current_thread()->handle_slow_trap(ts); +} + + +// +// Public services +// + +IMPLEMENT inline +bool +Thread::handle_sigma0_page_fault(Address pfa) +{ + size_t size; + + // Check if mapping a superpage doesn't exceed the size of physical memory + if (Cpu::have_superpages() + // Some distributions do not allow to mmap below a certain threshold + // (like 64k on Ubuntu 8.04) so we cannot map a superpage at 0 if + // we're Fiasco-UX + && (!Config::Is_ux || !(pfa < Config::SUPERPAGE_SIZE))) + { + pfa &= Config::SUPERPAGE_MASK; + size = Config::SUPERPAGE_SIZE; + } + else + { + pfa &= Config::PAGE_MASK; + size = Config::PAGE_SIZE; + } + + return mem_space()->v_insert(Mem_space::Phys_addr(pfa), Mem_space::Addr(pfa), + Mem_space::Size(size), + Mem_space::Page_writable + | Mem_space::Page_user_accessible) + != Mem_space::Insert_err_nomem; +} + +PRIVATE static inline +void +Thread::save_fpu_state_to_utcb(Trap_state *, Utcb *) +{} + +/* return 1 if this exception should be sent, return 0 if not + */ +PUBLIC inline NEEDS["trap_state.h"] +int +Thread::send_exception_arch(Trap_state *ts) +{ + // Do not send exception IPC but return 'not for us' if thread is a normal + // thread (not alien) and it's a debug trap, + // debug traps for aliens are always reflected as exception IPCs + if (!(state() & Thread_alien) + && (ts->_trapno == 1 || ts->_trapno == 3)) + return 0; // we do not handle this + + if (ts->_trapno == 3) + { + if (state() & Thread_dis_alien) + { + state_del(Thread_dis_alien); + return 0; // no exception + } + + // set IP back on the int3 instruction + ts->ip(ts->ip() - 1); + } + + return 1; // make it an exception +} + + +//---------------------------------------------------------------------------- +IMPLEMENTATION [ia32 || amd64]: + +PROTECTED inline +void +Thread::vcpu_resume_user_arch() +{} + +//---------------------------------------------------------------------------- +IMPLEMENTATION [ux]: + +PROTECTED inline +void +Thread::vcpu_resume_user_arch() +{ + switch_gdt_user_entries(this); +} + +//---------------------------------------------------------------------------- +IMPLEMENTATION [ux || amd64]: + +IMPLEMENT inline NEEDS[Thread::exception_triggered] +void +Thread::user_ip(Mword ip) +{ + if (exception_triggered()) + _exc_cont.ip(ip); + else + { + Entry_frame *r = regs(); + r->ip(ip); + } +} + +//---------------------------------------------------------------------------- +IMPLEMENTATION [(ia32,amd64,ux) && !io]: + +PRIVATE inline +int +Thread::handle_io_page_fault(Trap_state *) +{ return 0; } + +PRIVATE inline +bool +Thread::get_ioport(Address /*eip*/, Trap_state * /*ts*/, + unsigned * /*port*/, unsigned * /*size*/) +{ return false; } + + +//--------------------------------------------------------------------------- +IMPLEMENTATION[ia32 || amd64]: + +#include "fpu.h" +#include "fpu_alloc.h" +#include "fpu_state.h" +#include "gdt.h" +#include "globalconfig.h" +#include "idt.h" +#include "simpleio.h" +#include "static_init.h" +#include "terminate.h" + +int (*Thread::int3_handler)(Trap_state*); +DEFINE_PER_CPU Per_cpu Thread::dbg_stack; + +STATIC_INITIALIZER_P (int3_handler_init, KDB_INIT_PRIO); + +static +void +int3_handler_init() +{ + Thread::set_int3_handler(Thread::handle_int3); +} + +IMPLEMENT static inline NEEDS ["gdt.h"] +Mword +Thread::exception_cs() +{ + return Gdt::gdt_code_user | Gdt::Selector_user; +} + +/** + * The ia32 specific part of the thread constructor. + */ +PRIVATE inline NEEDS ["gdt.h"] +void +Thread::arch_init() +{ + // clear out user regs that can be returned from the thread_ex_regs + // system call to prevent covert channel + Entry_frame *r = regs(); + r->flags(EFLAGS_IOPL_K | EFLAGS_IF | 2); // ei + r->cs(Gdt::gdt_code_user | Gdt::Selector_user); + r->ss(Gdt::gdt_data_user | Gdt::Selector_user); + + r->sp(0); + // after cs initialisation as ip() requires proper cs + r->ip(0); +} + + +/** A C interface for Context::handle_fpu_trap, callable from assembly code. + @relates Context + */ +// The "FPU not available" trap entry point +extern "C" +int +thread_handle_fputrap() +{ + LOG_TRAP_N(7); + + return current_thread()->switchin_fpu(); +} + +PUBLIC static inline +void +Thread::set_int3_handler(int (*handler)(Trap_state *ts)) +{ + int3_handler = handler; +} + +/** + * Default handle for int3 extensions if JDB is disabled. If the JDB is + * available, Jdb::handle_int3_threadctx is called instead. + * @return 0 not handled, wait for user response + * 1 successfully handled + */ +PUBLIC static +int +Thread::handle_int3(Trap_state *ts) +{ + Mem_space *s = current()->mem_space(); + int from_user = ts->cs() & 3; + Address ip = ts->ip(); + Unsigned8 todo = s->peek((Unsigned8*)ip, from_user); + Unsigned8 *str; + int len; + char c; + + switch (todo) + { + case 0xeb: // jmp == enter_kdebug() + len = s->peek((Unsigned8*)(ip+1), from_user); + str = (Unsigned8*)(ip + 2); + + putstr("KDB: "); + if (len > 0) + { + for (; len; len--) + putchar(s->peek(str++, from_user)); + } + putchar('\n'); + return 0; // => Jdb + + case 0x90: // nop == l4kd_display() + if ( s->peek((Unsigned8*)(ip+1), from_user) != 0xeb /*jmp*/ + || (len = s->peek((Unsigned8*)(ip+2), from_user)) <= 0) + return 0; // => Jdb + + str = (Unsigned8*)(ip + 3); + for (; len; len--) + putchar(s->peek(str++, from_user)); + break; + + case 0x3c: // cmpb + todo = s->peek((Unsigned8*)(ip+1), from_user); + switch (todo) + { + case 0: // l4kd_outchar + putchar(ts->value() & 0xff); + break; + case 1: // l4kd_outnstring + str = (Unsigned8*)ts->value(); + len = ts->value4(); + for(; len > 0; len--) + putchar(s->peek(str++, from_user)); + break; + case 2: // l4kd_outstr + str = (Unsigned8*)ts->value(); + for (; (c=s->peek(str++, from_user)); ) + putchar(c); + break; + case 5: // l4kd_outhex32 + printf("%08lx", ts->value() & 0xffffffff); + break; + case 6: // l4kd_outhex20 + printf("%05lx", ts->value() & 0xfffff); + break; + case 7: // l4kd_outhex16 + printf("%04lx", ts->value() & 0xffff); + break; + case 8: // l4kd_outhex12 + printf("%03lx", ts->value() & 0xfff); + break; + case 9: // l4kd_outhex8 + printf("%02lx", ts->value() & 0xff); + break; + case 11: // l4kd_outdec + printf("%ld", ts->value()); + break; + case 31: // Watchdog + switch (ts->value2()) + { + case 1: + // enable watchdog + Watchdog::user_enable(); + break; + case 2: + // disable watchdog + Watchdog::user_disable(); + break; + case 3: + // user takes over the control of watchdog and is from now on + // responsible for calling "I'm still alive" events (function 5) + Watchdog::user_takeover_control(); + break; + case 4: + // user returns control of watchdog to kernel + Watchdog::user_giveback_control(); + break; + case 5: + // I'm still alive + Watchdog::touch(); + break; + } + break; + + default: // ko + if (todo < ' ') + return 0; // => Jdb + + putchar(todo); + break; + } + break; + + default: + return 0; // => Jdb + } + + return 1; +} + + +PRIVATE inline +void +Thread::check_f00f_bug(Trap_state *ts) +{ + // If we page fault on the IDT, it must be because of the F00F bug. + // Figure out exception slot and raise the corresponding exception. + // XXX: Should we also modify the error code? + if (ts->_trapno == 14 // page fault? + && ts->_cr2 >= Idt::idt() + && ts->_cr2 < Idt::idt() + Idt::_idt_max * 8) + ts->_trapno = (ts->_cr2 - Idt::idt()) / 8; +} + + +PRIVATE inline +unsigned +Thread::check_io_bitmap_delimiter_fault(Trap_state *ts) +{ + // check for page fault at the byte following the IO bitmap + if (ts->_trapno == 14 // page fault? + && (ts->_err & 4) == 0 // in supervisor mode? + && ts->ip() < Kmem::mem_user_max // delimiter byte accessed? + && (ts->_cr2 == Mem_layout::Io_bitmap + Mem_layout::Io_port_max / 8)) + { + // page fault in the first byte following the IO bitmap + // map in the cpu_page read_only at the place + Mem_space::Status result = + mem_space()->v_insert( + Mem_space::Phys_addr(mem_space()->virt_to_phys_s0((void*)Kmem::io_bitmap_delimiter_page())), + Mem_space::Addr::create(Mem_layout::Io_bitmap + Mem_layout::Io_port_max / 8), + Mem_space::Size::create(Config::PAGE_SIZE), + Pt_entry::global()); + + switch (result) + { + case Mem_space::Insert_ok: + return 1; // success + case Mem_space::Insert_err_nomem: + // kernel failure, translate this into a general protection + // violation and hope that somebody handles it + ts->_trapno = 13; + ts->_err = 0; + return 0; // fail + default: + // no other error code possible + assert (false); + } + } + + return 1; +} + +PRIVATE inline +bool +Thread::handle_sysenter_trap(Trap_state *ts, Address eip, bool from_user) +{ + if (EXPECT_FALSE + ((ts->_trapno == 6 || ts->_trapno == 13) + && (ts->_err & 0xffff) == 0 + && (eip < Kmem::mem_user_max - 2) + && (mem_space()->peek((Unsigned16*) eip, from_user)) == 0x340f)) + { + // somebody tried to do sysenter on a machine without support for it + WARN("tcb=%p killed:\n" + "\033[1;31mSYSENTER not supported on this machine\033[0m", + this); + + if (Cpu::have_sysenter()) + // GP exception if sysenter is not correctly set up.. + WARN("MSR_SYSENTER_CS: %llx", Cpu::rdmsr(MSR_SYSENTER_CS)); + else + // We get UD exception on processors without SYSENTER/SYSEXIT. + WARN("SYSENTER/EXIT not available."); + + return false; + } + + return true; +} + +PRIVATE inline +int +Thread::handle_not_nested_trap(Trap_state *ts) +{ + // no kernel debugger present + printf(" %p IP=" L4_PTR_FMT " Trap=%02lx [Ret/Esc]\n", + this, ts->ip(), ts->_trapno); + + int r; + // cannot use normal getchar because it may block with hlt and irq's + // are off here + while ((r=Kconsole::console()->getchar(false)) == -1) + Proc::pause(); + + if (r == '\033') + terminate (1); + + return 0; +} + +PROTECTED inline +int +Thread::sys_control_arch(Utcb *) +{ + return 0; +} + + +//--------------------------------------------------------------------------- +IMPLEMENTATION [(ia32 |amd64) & !(debug | kdb)]: + +/** There is no nested trap handler if both jdb and kdb are disabled. + * Important: We don't need the nested_handler_stack here. + */ +PRIVATE static inline +int +Thread::call_nested_trap_handler(Trap_state *) +{ return -1; } diff --git a/kernel/fiasco/src/kern/ia32/thread-io.cpp b/kernel/fiasco/src/kern/ia32/thread-io.cpp new file mode 100644 index 00000000..11c1198a --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/thread-io.cpp @@ -0,0 +1,198 @@ +IMPLEMENTATION [io && (ia32 || amd64 || ux)]: + +// +// disassamble IO statements to compute the port address and +// the number of ports accessed +// + +/** Compute port number and size for an IO instruction. + @param eip address of the instruction + @param ts thread state with registers + @param port return port address + @param size return number of ports accessed + @return true if the instruction was handled successfully + false otherwise +*/ + +bool +Thread::get_ioport(Address eip, Trap_state *ts, unsigned *port, unsigned *size) +{ + int from_user = ts->cs() & 3; + + // handle 1 Byte IO + switch (mem_space()->peek((Unsigned8*)eip, from_user)) + { + case 0xec: // in dx, al + case 0x6c: // insb + case 0xee: // out dx, al + case 0x6e: // outb + *size = 0; + *port = ts->dx() & 0xffff; + return true; + case 0xed: // in dx, eax + case 0x6d: // insd + case 0xef: // out eax, dx + case 0x6f: // outd + *size = 2; + *port = ts->dx() & 0xffff; + if (*port +4 <= Mem_layout::Io_port_max) + return true; + else // Access beyond L4_IOPORT_MAX + return false; + case 0xfa: // cli + case 0xfb: // sti + *size = 16; /* 16bit IO space */ + *port = 0; + return true; + } + + // handle 2 Byte IO + if (! (eip < Kmem::mem_user_max -1)) + return false; + + switch (mem_space()->peek((Unsigned8*)eip, from_user)) + { + case 0xe4: // in imm8, al + case 0xe6: // out al, imm8 + *size = 0; + *port = mem_space()->peek((Unsigned8*)(eip+1), from_user); + return true; + case 0xe5: // in imm8, eax + case 0xe7: // out eax, imm8 + *size = 2; + *port = mem_space()->peek((Unsigned8*)(eip+1), from_user); + return *port +4 <= Mem_layout::Io_port_max ? true : false; + + case 0x66: // operand size override + switch (mem_space()->peek((Unsigned8*)(eip+1), from_user)) + { + case 0xed: // in dx, ax + case 0xef: // out ax, dx + case 0x6d: // insw + case 0x6f: // outw + *size = 1; + *port = ts->dx() & 0xffff; + if (*port +2 <= Mem_layout::Io_port_max) + return true; + else // Access beyond L4_IOPORT_MAX + return false; + case 0xe5: // in imm8, ax + case 0xe7: // out ax,imm8 + *size = 1; + *port = mem_space()->peek((Unsigned8*)(eip + 2), from_user); + if (*port +2 <= Mem_layout::Io_port_max) + return true; + else + return false; + } + + case 0xf3: // REP + switch (mem_space()->peek((Unsigned8*)(eip +1), from_user)) + { + case 0x6c: // REP insb + case 0x6e: // REP outb + *size = 0; + *port = ts->dx() & 0xffff; + return true; + case 0x6d: // REP insd + case 0x6f: // REP outd + *size = 2; + *port = ts->dx() & 0xffff; + if(*port +4 <= Mem_layout::Io_port_max) + return true; + else // Access beyond L4_IOPORT_MAX + return false; + } + } + + // handle 3 Byte IO + if (! (eip < Kmem::mem_user_max -2)) + return false; + + Unsigned16 w = mem_space()->peek((Unsigned16*)eip, from_user); + if (w == 0x66f3 || // sizeoverride REP + w == 0xf366) // REP sizeoverride + { + switch (mem_space()->peek((Unsigned8*)(eip +2), from_user)) + { + case 0x6d: // REP insw + case 0x6f: // REP outw + *size = 1; + *port = ts->dx() & 0xffff; + if (*port +2 <= Mem_layout::Io_port_max) + return true; + else // Access beyond L4_IOPORT_MAX + return false; + } + } + + // nothing appropriate found + return false; +} + +PRIVATE inline +int +Thread::handle_io_page_fault(Trap_state *ts) +{ + Address eip = ts->ip(); + if (!check_io_bitmap_delimiter_fault(ts)) + return 0; + + // Check for IO page faults. If we got exception #14, the IO bitmap page is + // not available. If we got exception #13, the IO bitmap is available but + // the according bit is set. In both cases we have to dispatch the code at + // the faulting eip to deterine the IO port and send an IO flexpage to our + // pager. If it was a page fault, check the faulting address to prevent + // touching userland. + if (eip < Kmem::mem_user_max && + (ts->_trapno == 13 && (ts->_err & 7) == 0 || + ts->_trapno == 14 && Kmem::is_io_bitmap_page_fault(ts->_cr2))) + { + unsigned port, size; + if (get_ioport(eip, ts, &port, &size)) + { + Mword io_page = L4_fpage::io(port, size).raw(); + + // set User mode flag to get correct IP in handle_page_fault_pager + // pretend a write page fault + static const unsigned io_error_code = PF_ERR_WRITE | PF_ERR_USERMODE; + + CNT_IO_FAULT; + + if (EXPECT_FALSE (log_page_fault())) + page_fault_log(io_page, io_error_code, eip); + + // treat it as a page fault in the region above 0xf0000000, + + // We could also reset the Thread_cancel at slowtraps entry but it + // could be harmful for debugging (see also comment at slowtraps:). + // + // This must be done while interrupts are off to prevent that an + // other thread sets the flag again. + state_del(Thread_cancel); + + // set cr2 in ts so that we also get the io_page value in an + // consecutive exception + ts->_cr2 = io_page; + + if (EXPECT_FALSE(state() & Thread_alien)) + { + // special case for alien tasks: Don't generate pagefault but + // send (pagefault) exception to pager. + ts->_trapno = 14; + if (send_exception(ts)) + return 1; + else + return 2; // fail, don't send exception again + } + + bool ipc_code = handle_page_fault_pager(_pager, io_page, + io_error_code, + L4_msg_tag::Label_io_page_fault); + + if (ipc_code) + return 1; + } + } + return 0; // fail +} diff --git a/kernel/fiasco/src/kern/ia32/timer-apic.cpp b/kernel/fiasco/src/kern/ia32/timer-apic.cpp new file mode 100644 index 00000000..cb302280 --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/timer-apic.cpp @@ -0,0 +1,83 @@ +IMPLEMENTATION [apic_timer]: + +#include + +#include "apic.h" +#include "config.h" +#include "cpu.h" +#include "logdefs.h" +#include "pit.h" +#include "std_macros.h" + +// no IRQ line for the LAPIC +PUBLIC static inline int Timer::irq() { return -1; } + +IMPLEMENT +void +Timer::init(unsigned) +{ + Apic::timer_assign_irq_vector(Config::Apic_timer_vector); + + if (Config::Scheduler_one_shot) + { + Apic::timer_set_one_shot(); + Apic::timer_reg_write(0xffffffff); + } + else + { + Apic::timer_set_periodic(); + Apic::timer_reg_write(Apic::us_to_apic(Config::Scheduler_granularity)); + } + + // make sure that PIT does pull its interrupt line + Pit::done(); + + if (!Config::Scheduler_one_shot) + // from now we can save energy in getchar() + Config::getchar_does_hlt_works_ok = Config::hlt_works_ok; + + printf ("Using the Local APIC timer on vector %x (%s Mode) for scheduling\n", + Config::Apic_timer_vector, + Config::Scheduler_one_shot ? "One-Shot" : "Periodic"); +} + +PUBLIC static inline +void +Timer::acknowledge() +{} + +static +void +Timer::update_one_shot(Unsigned64 wakeup) +{ + //unsigned cpu = current_cpu(); + Unsigned32 apic; + Unsigned64 now = Kip::k()->clock; //Cpu::cpus.cpu(cpu).time_us(); + if (EXPECT_FALSE (wakeup <= now)) + // already expired + apic = 1; + else + { + Unsigned64 delta = wakeup - now; + if (delta < Config::One_shot_min_interval_us) + apic = Apic::us_to_apic(Config::One_shot_min_interval_us); + else if (delta > Config::One_shot_max_interval_us) + apic = Apic::us_to_apic(Config::One_shot_max_interval_us); + else + apic = Apic::us_to_apic(delta); + + if (EXPECT_FALSE (apic < 1)) + // timeout too small + apic = 1; + } + + Apic::timer_reg_write(apic); +} + +IMPLEMENT inline +void +Timer::update_timer(Unsigned64 wakeup) +{ + if (Config::Scheduler_one_shot) + update_one_shot(wakeup); +} diff --git a/kernel/fiasco/src/kern/ia32/timer-ia32-amd64-ux.cpp b/kernel/fiasco/src/kern/ia32/timer-ia32-amd64-ux.cpp new file mode 100644 index 00000000..192a84f9 --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/timer-ia32-amd64-ux.cpp @@ -0,0 +1,39 @@ +IMPLEMENTATION[ia32,ux,amd64]: + +#include "cpu.h" +#include "config.h" +#include "globals.h" +#include "kip.h" + +IMPLEMENT inline NEEDS ["config.h", "cpu.h", "kip.h"] +void +Timer::init_system_clock() +{ + if (Config::Kip_timer_uses_rdtsc) + Kip::k()->clock = Cpu::cpus.cpu(_cpu).time_us(); + else + Kip::k()->clock = 0; +} + +IMPLEMENT inline NEEDS ["config.h", "cpu.h", "globals.h", "kip.h"] +Unsigned64 +Timer::system_clock() +{ + if (!current_cpu() && Config::Kip_timer_uses_rdtsc) + Kip::k()->clock = Cpu::cpus.cpu(_cpu).time_us(); + + return Kip::k()->clock; +} + +IMPLEMENT inline NEEDS ["config.h", "cpu.h", "globals.h", "kip.h"] +void +Timer::update_system_clock(unsigned cpu) +{ + if (cpu != 0) + return; + + if (Config::Kip_timer_uses_rdtsc) + Kip::k()->clock = Cpu::cpus.cpu(0).time_us(); + else + Kip::k()->clock += Config::Scheduler_granularity; +} diff --git a/kernel/fiasco/src/kern/ia32/timer-pit.cpp b/kernel/fiasco/src/kern/ia32/timer-pit.cpp new file mode 100644 index 00000000..55217b36 --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/timer-pit.cpp @@ -0,0 +1,35 @@ +IMPLEMENTATION[{ia32,amd64}-pit_timer]: + +#include "irq_chip.h" +#include "pit.h" + +#include + +IMPLEMENT +void +Timer::init(unsigned) +{ + printf("Using the PIT (i8254) on IRQ %d for scheduling\n", irq()); + + // set up timer interrupt (~ 1ms) + Pit::init(); +} + +PUBLIC static inline +unsigned Timer::irq() { return 0; } + +PUBLIC static inline NEEDS["irq_chip.h"] +unsigned Timer::irq_mode() +{ return Irq_base::Trigger_edge | Irq_base::Polarity_high; } + +PUBLIC static inline +void +Timer::acknowledge() +{} + +IMPLEMENT inline +void +Timer::update_timer(Unsigned64) +{ + // does nothing in periodic mode +} diff --git a/kernel/fiasco/src/kern/ia32/timer-rtc.cpp b/kernel/fiasco/src/kern/ia32/timer-rtc.cpp new file mode 100644 index 00000000..92d7392e --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/timer-rtc.cpp @@ -0,0 +1,54 @@ +IMPLEMENTATION[{ia32,amd64}-rtc_timer]: + +#include "irq_chip.h" +#include "rtc.h" +#include "pit.h" + +#include + +//IMPLEMENT inline int Timer::irq() { return 8; } + +PUBLIC static inline +unsigned Timer::irq() { return 8; } + +PUBLIC static inline NEEDS["irq_chip.h"] +unsigned Timer::irq_mode() +{ return Irq_base::Trigger_edge | Irq_base::Polarity_high; } + +IMPLEMENT +void +Timer::init(unsigned) +{ + printf("Using the RTC on IRQ %d (%sHz) for scheduling\n", 8, +#ifdef CONFIG_SLOW_RTC + "64" +#else + "1k" +#endif + ); + + // set up timer interrupt (~ 1ms) + Rtc::init(); + + // make sure that PIT does pull its interrupt line + Pit::done(); +} + +PUBLIC static inline NEEDS["rtc.h"] +void +Timer::acknowledge() +{ + // periodic scheduling is triggered by irq 8 connected with RTC + // irq.mask(); + Rtc::reset(); + // irq.ack(); + // Rtc::reset(); + // irq.unmask(); +} + +IMPLEMENT inline +void +Timer::update_timer(Unsigned64) +{ + // does nothing in periodic mode +} diff --git a/kernel/fiasco/src/kern/ia32/timer_irq.cpp b/kernel/fiasco/src/kern/ia32/timer_irq.cpp new file mode 100644 index 00000000..f0211efb --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/timer_irq.cpp @@ -0,0 +1,54 @@ +//--------------------------------------------------------------------------- +IMPLEMENTATION[ia32 || amd64]: + +#include "config.h" +#include "globals.h" +#include "kernel_console.h" +#include "kdb_ke.h" +#include "timer.h" +#include "vkey.h" +#include "watchdog.h" + + +/** Slow version of timer interrupt. Activated on every clock tick. + Checks if something related to debugging is to do. After returning + from this function, the real timer interrupt handler is called. + */ +extern "C" +void +thread_timer_interrupt_slow(void) +{ + if (!current_cpu()) + { + if (Config::esc_hack) + { + // timer hack: check if ESC key hit at keyboard + int v = Kconsole::console()->getchar(false); + if (v != -1) + { + if (v == 27) + kdb_ke("ESC"); + else + Vkey::add_char(v); + } + } + + if (Config::serial_esc != Config::SERIAL_NO_ESC) + { + // Here we have to check for serial characters because the + // serial interrupt could have an lower priority than a not + // acknowledged interrupt. The regular case is to stop when + // receiving the serial interrupt. + if (Kconsole::console()->char_avail() == 1 && !Vkey::check_()) + kdb_ke("SERIAL_ESC"); + } + + if (Config::watchdog) + { + // tell doggy that we are alive + Watchdog::touch(); + } + } +} + + diff --git a/kernel/fiasco/src/kern/ia32/timer_tick-apic.cpp b/kernel/fiasco/src/kern/ia32/timer_tick-apic.cpp new file mode 100644 index 00000000..ddbbda9e --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/timer_tick-apic.cpp @@ -0,0 +1,73 @@ +IMPLEMENTATION [ia32 || amd64]: + +#include "apic.h" +#include "idt.h" + +IMPLEMENT +void +Timer_tick::setup(unsigned) +{} + +IMPLEMENT +void +Timer_tick::enable(unsigned) +{ + Apic::timer_enable_irq(); + Apic::irq_ack(); +} + +IMPLEMENT +void +Timer_tick::disable(unsigned) +{ + Apic::timer_disable_irq(); +} + +PUBLIC static inline NEEDS["apic.h"] +void +Timer_tick::ack() +{ + Apic::irq_ack(); +} + +PUBLIC static +void +Timer_tick::set_vectors_stop() +{ + extern char entry_int_timer_stop[]; + // acknowledge timer interrupt once to keep timer interrupt alive because + // we could be called from thread_timer_interrupt_slow() before ack + Apic::irq_ack(); + + // set timer interrupt to dummy doing nothing + Idt::set_entry(Config::scheduler_irq_vector, (Address)entry_int_timer_stop, false); +#if 0 + // From ``8259A PROGRAMMABLE INTERRUPT CONTROLLER (8259A 8259A-2)'': If no + // interrupt request is present at step 4 of either sequence (i. e. the + // request was too short in duration) the 8259A will issue an interrupt + // level 7. Both the vectoring bytes and the CAS lines will look like an + // interrupt level 7 was requested. + set_entry(0x27, (Address)entry_int_pic_ignore, false); + set_entry(0x2f, (Address)entry_int_pic_ignore, false); +#endif +} + +// We are entering with disabled interrupts! +extern "C" FIASCO_FASTCALL +void +thread_timer_interrupt(Address ip) +{ + (void)ip; + Timer_tick::handler_all(0, 0); //Timer_tick::_glbl_timer); +} + +/** Extra version of timer interrupt handler which is used when the jdb is + active to prevent busy waiting. */ +extern "C" +void +thread_timer_interrupt_stop(void) +{ + Apic::irq_ack(); +} + + diff --git a/kernel/fiasco/src/kern/ia32/timer_tick-ia32.cpp b/kernel/fiasco/src/kern/ia32/timer_tick-ia32.cpp new file mode 100644 index 00000000..88ed5243 --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/timer_tick-ia32.cpp @@ -0,0 +1,70 @@ +IMPLEMENTATION [ia32 || amd64 || ux]: + +#include "config.h" +#include "irq_mgr.h" +#include "idt.h" + +// On IA32 we do not use a real IRQ object but a special vector +IMPLEMENT bool +Timer_tick::allocate_irq(Irq_base *irq, unsigned irqnum) +{ + // we do not use the alloc function of the chip, because this would + // actually route the IRQ vector through the IRQ object. + // However, IA32 uses a vector that points to thread_timer_interrupt below, + // bypassing the IRQ object infrastructure + irqnum = Irq_mgr::mgr->legacy_override(irqnum); + bool res = Irq_mgr::mgr->reserve(irqnum); + if (res) + { + Irq_mgr::Irq i = Irq_mgr::mgr->chip(irqnum); + i.chip->bind(irq, i.pin); + + // from now we can save energy in getchar() + if (!Config::Scheduler_one_shot) + Config::getchar_does_hlt_works_ok = Config::hlt_works_ok; + } + return res; +} + +PUBLIC static +void +Timer_tick::set_vectors_stop() +{ + extern char entry_int_timer_stop[]; + // acknowledge timer interrupt once to keep timer interrupt alive because + // we could be called from thread_timer_interrupt_slow() before ack + Timer_tick::_glbl_timer->ack(); + + // set timer interrupt to dummy doing nothing + Idt::set_entry(Config::scheduler_irq_vector, (Address)entry_int_timer_stop, false); +#if 0 + // From ``8259A PROGRAMMABLE INTERRUPT CONTROLLER (8259A 8259A-2)'': If no + // interrupt request is present at step 4 of either sequence (i. e. the + // request was too short in duration) the 8259A will issue an interrupt + // level 7. Both the vectoring bytes and the CAS lines will look like an + // interrupt level 7 was requested. + set_entry(0x27, (Address)entry_int_pic_ignore, false); + set_entry(0x2f, (Address)entry_int_pic_ignore, false); +#endif +} + +// We are entering with disabled interrupts! +extern "C" FIASCO_FASTCALL +void +thread_timer_interrupt(Address ip) +{ + //putchar('T'); + (void)ip; + Timer_tick::handler_all(Timer_tick::_glbl_timer, 0); +} + +/** Extra version of timer interrupt handler which is used when the jdb is + active to prevent busy waiting. */ +extern "C" +void +thread_timer_interrupt_stop(void) +{ + Timer_tick::_glbl_timer->ack(); +} + + diff --git a/kernel/fiasco/src/kern/ia32/tramp-mp.S b/kernel/fiasco/src/kern/ia32/tramp-mp.S new file mode 100644 index 00000000..88893a5b --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/tramp-mp.S @@ -0,0 +1,165 @@ +/* -*- c -*- */ +#include "config_gdt.h" +#include "tcboffset.h" +#include "linking.h" + +#define OFFS(x) ((x)-(_tramp_mp_entry)) +#define PHYS(x) (x) + +#ifdef CONFIG_AMD64 +# define CX rcx +# define SP rsp +#else +# define CX ecx +# define SP esp +#endif + +#define CPU_NR_COUNTER (config_num_ap_cpus) + + .section .mp_tramp , "awx", @progbits +#ifndef CONFIG_PF_UX + .code16 + .p2align 12 +#endif + .global _tramp_mp_entry +_tramp_mp_entry: + + /* Basic setup of the processor (stack not yet needed) */ +#ifndef CONFIG_PF_UX + cli + cld + movw %cs, %ax + movw %ax, %ds + + /* Switch to protected mode (needed to read APIC-ID) */ + lgdtl OFFS(_tramp_mp_init_gdt_pdesc) + movl %cr0, %eax + orl $0x00000001, %eax + movl %eax, %cr0 + ljmpl $0x08, $PHYS(_tramp_mp_entry32) + + .code32 +_tramp_mp_entry32: + movw $0x10, %ax + movw %ax, %ds + + /* Initialize paging, needs linear mapping of this page! (first 4MB are linear mapped, due to lucky cirumstances) */ + movl PHYS(_tramp_mp_startup_pdbr), %eax + movl %eax, %cr3 + // Initialize cr4 before, because we may run on a 4MB-page and need the extension enabled before + movl PHYS(_tramp_mp_startup_cr4), %eax + movl %eax, %cr4 + +#ifdef CONFIG_AMD64 + mov %edx, %edi + mov $0xc0000080, %ecx + rdmsr + bts $8,%eax + wrmsr + mov %edi, %edx + + movl PHYS(_tramp_mp_startup_cr0), %eax + movl %eax, %cr0 + + ljmpl $0x18, $PHYS(_tramp_mp_entry64) + + .code64 +_tramp_mp_entry64: + jmp *PHYS(_ptr_64virt) + + .align 8 +_ptr_64virt: + .quad _entry_64virt + +_entry_64virt: +#endif /* AMD64 */ + /* Reinitialize the gdt, reloads segments with kernel values */ + lgdt PHYS(_tramp_mp_startup_gdt_pdesc) +#ifndef CONFIG_AMD64 + movl PHYS(_tramp_mp_startup_cr0), %eax + movl %eax, %cr0 + ljmp $GDT_CODE_KERNEL, $1f +1: movw $GDT_DATA_KERNEL, %ax + movw %ax, %ds + movw %ax, %es + movw %ax, %ss +#endif /* ! AMD64 */ +#endif /* ! UX */ + + /* Increase CPU counter */ +1: mov CPU_NR_COUNTER, %eax + mov %eax, %edi + inc %edi + lock ; cmpxchg %edi, CPU_NR_COUNTER + jnz 1b + + /* Acquire spinlock */ +1: cmpl $0, _tramp_mp_spinlock + je 2f + pause + jmp 1b +2: mov $2, %CX + xchg _tramp_mp_spinlock, %CX + cmp $0, %CX + jne 1b + + /* we've the lock, can run on the init_stack */ + mov $_tramp_mp_init_stack_top, %SP + mov %edi, %eax /* IA32: cpu-num in %eax, AMD64: %rdi */ + jmp BOOT_AP_CPU + + +#ifndef CONFIG_PF_UX + /* + * Pseudo_descriptor for the initial GDT + */ + .align 4 +_tramp_mp_init_gdt_pdesc: + .word 0x1f + .long PHYS(_tramp_mp_init_gdt) + .word 0 + + /* + * Initial GDT, used for switch to protected mode, will be + * used only until startup sequence (from this point we use + * the OS provided GDT). + */ + .align 8 +_tramp_mp_init_gdt: + .long 0x00000000, 0x00000000 /* dummy */ + .long 0x0000FFFF, 0x00CF9A00 /* r-x/0..4GB/PL0/32bit */ + .long 0x0000FFFF, 0x00CF9200 /* rw-/0..4GB/PL0/32bit */ + .long 0x0000FFFF, 0x00AF9B00 /* r-x/0..4GB/PL0/64bit */ + +.global _tramp_mp_startup_cr0 +_tramp_mp_startup_cr0: + .quad 0x00000000 + +.global _tramp_mp_startup_cr4 +_tramp_mp_startup_cr4: + .quad 0x00000000 + +.global _tramp_mp_startup_pdbr +_tramp_mp_startup_pdbr: + .quad 0x00000000 + +.global _tramp_mp_startup_gdt_pdesc +_tramp_mp_startup_gdt_pdesc: + .quad 0 + .quad 0 +#endif /* ! UX */ + +.global _tramp_mp_spinlock +_tramp_mp_spinlock: + .quad 0 + + .align 16 +_tramp_mp_init_stack: +#ifdef CONFIG_PF_UX + /* glibc *printf-functions */ + .space 4096 +#else + .space 2048 +#endif +_tramp_mp_init_stack_top: + diff --git a/kernel/fiasco/src/kern/ia32/utcb_init-ia32.cpp b/kernel/fiasco/src/kern/ia32/utcb_init-ia32.cpp new file mode 100644 index 00000000..370ae22a --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/utcb_init-ia32.cpp @@ -0,0 +1,35 @@ +INTERFACE [ia32 || amd64]: + +class Cpu; + +EXTENSION class Utcb_init +{ +public: + /** + * Value for GS and FS. + * @return Value the GS and FS register has to be loaded with when + * entering user mode. + */ + static Unsigned32 utcb_segment(); +}; + +//----------------------------------------------------------------------------- +IMPLEMENTATION [ia32 || amd64]: + +#include +#include "gdt.h" +#include "paging.h" +#include "panic.h" +#include "space.h" +#include "vmem_alloc.h" + +IMPLEMENT static inline NEEDS ["gdt.h"] +Unsigned32 +Utcb_init::utcb_segment() +{ return Gdt::gdt_utcb | Gdt::Selector_user; } + + +IMPLEMENT inline +void +Utcb_init::init() +{} diff --git a/kernel/fiasco/src/kern/ia32/vm.cpp b/kernel/fiasco/src/kern/ia32/vm.cpp new file mode 100644 index 00000000..60408ad7 --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/vm.cpp @@ -0,0 +1,49 @@ +INTERFACE: + +#include "task.h" + +class Vm : public Task +{ +public: + explicit Vm(Ram_quota *q) : Task(q) {} + int resume_vcpu(Context *, Vcpu_state *, bool) = 0; +}; + +template< typename VM > +struct Vm_allocator +{ + static Kmem_slab_t a; +}; + +template +Kmem_slab_t Vm_allocator::a("Vm"); + +// ------------------------------------------------------------------------ +IMPLEMENTATION: + +PUBLIC inline virtual +Page_number +Vm::map_max_address() const +{ return Page_number::create(1UL << (MWORD_BITS - Mem_space::Page_shift)); } + +PUBLIC static +template< typename VM > +Slab_cache * +Vm::allocator() +{ return &Vm_allocator::a; } + +// ------------------------------------------------------------------------ +IMPLEMENTATION [ia32]: + +PROTECTED static inline +bool +Vm::is_64bit() +{ return false; } + +// ------------------------------------------------------------------------ +IMPLEMENTATION [amd64]: + +PROTECTED static inline +bool +Vm::is_64bit() +{ return true; } diff --git a/kernel/fiasco/src/kern/ia32/vm_factory-ia32.cpp b/kernel/fiasco/src/kern/ia32/vm_factory-ia32.cpp new file mode 100644 index 00000000..b06b8d39 --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/vm_factory-ia32.cpp @@ -0,0 +1,39 @@ +IMPLEMENTATION [vmx && svm]: + +#include "ram_quota.h" +#include "svm.h" +#include "vm_svm.h" +#include "vmx.h" +#include "vm_vmx.h" + +PRIVATE static inline +template< typename VM > +VM * +Vm_factory::allocate(Ram_quota *quota) +{ + if (void *t = Vm::allocator()->q_alloc(quota)) + { + VM *a = new (t) VM(quota); + if (a->initialize()) + return a; + + delete a; + } + + return 0; +} + +IMPLEMENT +Vm * +Vm_factory::create(Ram_quota *quota, int *err) +{ + *err = -L4_err::ENomem; + if (Svm::cpus.cpu(current_cpu()).svm_enabled()) + return allocate(quota); + if (Vmx::cpus.cpu(current_cpu()).vmx_enabled()) + return allocate(quota); + + *err = L4_err::ENodev; + return 0; +} + diff --git a/kernel/fiasco/src/kern/ia32/vm_svm.cpp b/kernel/fiasco/src/kern/ia32/vm_svm.cpp new file mode 100644 index 00000000..f7072856 --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/vm_svm.cpp @@ -0,0 +1,718 @@ +INTERFACE [svm]: + +#include "config.h" +#include "vm.h" + +class Vmcb; + +class Vm_svm : public Vm +{ +private: + static void resume_vm_svm(Mword phys_vmcb, Vcpu_state *regs) + asm("resume_vm_svm") __attribute__((__regparm__(3))); + Unsigned8 _asid[Config::Max_num_cpus]; + Unsigned32 _asid_generation[Config::Max_num_cpus]; + + enum + { + EFER_LME = 1 << 8, + EFER_LMA = 1 << 10, + }; +}; + +// ------------------------------------------------------------------------ +INTERFACE [svm && debug]: + +EXTENSION class Vm_svm +{ +protected: + struct Log_vm_svm_exit + { + Mword exitcode, exitinfo1, exitinfo2, rip; + }; + + static unsigned log_fmt_svm(Tb_entry *, int max, char *buf) asm ("__fmt_vm_svm_exit"); +}; + +// ------------------------------------------------------------------------ +IMPLEMENTATION [svm]: + +#include "context.h" +#include "mem_space.h" +#include "fpu.h" +#include "ref_ptr.h" +#include "svm.h" +#include "thread.h" // XXX: circular dep, move this out here! +#include "thread_state.h" // XXX: circular dep, move this out here! + + +// ------------------------------------------------------------------------ +IMPLEMENTATION [svm && ia32]: + +#include "virt.h" + +PRIVATE inline NEEDS["virt.h"] +Address +Vm_svm::get_vm_cr3(Vmcb *) +{ + // When running in 32bit mode we already return the page-table of our Vm + // object, whether we're running with shadow or nested paging + return phys_dir(); +} + +//---------------------------------------------------------------------------- +IMPLEMENTATION [svm && amd64]: + +#include "assert_opt.h" +#include "virt.h" + +PRIVATE inline NEEDS["assert_opt.h", "virt.h"] +Address +Vm_svm::get_vm_cr3(Vmcb *v) +{ + // When we have nested paging, we just return the 4lvl host page-table of + // our Vm. + if (v->np_enabled()) + return phys_dir(); + + // When running with shadow paging and the guest is running in long mode + // and has paging enabled, we can just return the 4lvl page table of our + // host Vm object. + if ( (v->state_save_area.efer & EFER_LME) + && (v->state_save_area.cr0 & CR0_PG)) + return phys_dir(); + + // Now it's getting tricky when running with shadow paging. + // We need to obey the following rules: + // - When the guest is not running in 64bit mode the CR3 one can set for + // the page-table must be below 4G physical memory (i.e. bit 32-63 must + // be zero). This is unfortunate when the host has memory above 4G as + // Fiasco gets its memory from the end of physical memory, i.e. + // page-table memory is above 4G. + // - We need an appropriate page-table format for 32bit! + // That means either a 2lvl page-table or a 3lvl PAE one. That would + // require to maintain two page-tables for the guest, one for 32bit + // mode execution and one for 64 bit execution. It is needed either for + // the transition from real to long-mode via protected mode or for + // 32bit only guests. + // There's one trick to avoid having two PTs: 4lvl-PTs and 3lvl-PAE-PTs + // have much in common so that it's possible to just take the the PDPE + // one of the host as the 3lvl-PAE-PT for the guest. Well, not quite. + // The problem is that SVM checks that MBZ bits in the PAE-PT entries + // are really 0 as written in the spec. Now the 4lvl PT contains rights + // bits there, so that this type of PT is refused and does not work on + // real hardware. + // So why is the code still here? Well, QEmu isn't so picky about the + // bits in the PDPE and it thus works there... + assert_opt (this); + Address vm_cr3 = static_cast(this)->dir()->walk(Virt_addr(0), 0).e->addr(); + if (EXPECT_FALSE(!vm_cr3)) + { + // force allocation of new secondary page-table level + static_cast(this)->dir() + ->walk(Virt_addr(0), 1, Kmem_alloc::q_allocator(ram_quota())); + vm_cr3 = static_cast(this)->dir()->walk(Virt_addr(0), 0).e->addr(); + } + + if (EXPECT_FALSE(vm_cr3 >= 1UL << 32)) + { + WARN("svm: Host page-table not under 4G, sorry.\n"); + return 0; + } + + return vm_cr3; +} + +//---------------------------------------------------------------------------- +IMPLEMENTATION [svm]: + +PRIVATE inline +Unsigned8 +Vm_svm::asid () +{ + return _asid[current_cpu()]; +} + +PRIVATE inline +void +Vm_svm::asid(Unsigned8 asid) +{ + _asid[current_cpu()] = asid; +} + +PRIVATE inline +Unsigned32 +Vm_svm::asid_generation() +{ + return _asid_generation[current_cpu()]; +} + +PRIVATE inline +void +Vm_svm::asid_generation(Unsigned32 generation) +{ + _asid_generation[current_cpu()] = generation; +} + +PUBLIC +Vm_svm::Vm_svm(Ram_quota *q) + : Vm(q) +{ + memset(_asid, 0, sizeof(_asid)); + memset(_asid_generation, 0, sizeof(_asid_generation)); +} + +PUBLIC inline +void * +Vm_svm::operator new (size_t size, void *p) throw() +{ + (void)size; + assert (size == sizeof (Vm_svm)); + return p; +} + +PUBLIC +void +Vm_svm::operator delete (void *ptr) +{ + Vm_svm *t = reinterpret_cast(ptr); + allocator()->q_free(t->ram_quota(), ptr); +} + + +// to do: +// - handle cr2 +// - force fpu ownership +// - debug registers not covered by VMCB + +PRIVATE +void +Vm_svm::copy_state_save_area(Vmcb *dest, Vmcb *src) +{ + Vmcb_state_save_area *d = &dest->state_save_area; + Vmcb_state_save_area *s = &src->state_save_area; + + d->es_sel = s->es_sel; + d->es_attrib = s->es_attrib; + d->es_limit = s->es_limit; + d->es_base = s->es_base; + + d->cs_sel = s->cs_sel; + d->cs_attrib = s->cs_attrib; + d->cs_limit = s->cs_limit; + d->cs_base = s->cs_base; + + d->ss_sel = s->ss_sel; + d->ss_attrib = s->ss_attrib; + d->ss_limit = s->ss_limit; + d->ss_base = s->ss_base; + + d->ds_sel = s->ds_sel; + d->ds_attrib = s->ds_attrib; + d->ds_limit = s->ds_limit; + d->ds_base = s->ds_base; + + d->fs_sel = s->fs_sel; + d->fs_attrib = s->fs_attrib; + d->fs_limit = s->fs_limit; + d->fs_base = s->fs_base; + + d->gs_sel = s->gs_sel; + d->gs_attrib = s->gs_attrib; + d->gs_limit = s->gs_limit; + d->gs_base = s->gs_base; + + d->gdtr_sel = s->gdtr_sel; + d->gdtr_attrib = s->gdtr_attrib; + d->gdtr_limit = s->gdtr_limit; + d->gdtr_base = s->gdtr_base; + + d->ldtr_sel = s->ldtr_sel; + d->ldtr_attrib = s->ldtr_attrib; + d->ldtr_limit = s->ldtr_limit; + d->ldtr_base = s->ldtr_base; + + d->idtr_sel = s->idtr_sel; + d->idtr_attrib = s->idtr_attrib; + d->idtr_limit = s->idtr_limit; + d->idtr_base = s->idtr_base; + + d->tr_sel = s->tr_sel; + d->tr_attrib = s->tr_attrib; + d->tr_limit = s->tr_limit; + d->tr_base = s->tr_base; + + d->cpl = s->cpl; + d->efer = s->efer; + + d->cr4 = s->cr4; + d->cr3 = s->cr3; + d->cr0 = s->cr0; + d->dr7 = s->dr7; + d->dr6 = s->dr6; + d->rflags = s->rflags; + + d->rip = s->rip; + d->rsp = s->rsp; + d->rax = s->rax; + + d->star = s->star; + d->lstar = s->lstar; + d->cstar = s->cstar; + d->sfmask = s->sfmask; + d->kernelgsbase = s->kernelgsbase; + d->sysenter_cs = s->sysenter_cs; + d->sysenter_esp = s->sysenter_esp; + d->sysenter_eip = s->sysenter_eip; + d->cr2 = s->cr2; + + d->g_pat = s->g_pat; + d->dbgctl = s->dbgctl; + d->br_from = s->br_from; + d->br_to = s->br_to; + d->lastexcpfrom = s->lastexcpfrom; + d->last_excpto = s->last_excpto; +} + + +PRIVATE +void +Vm_svm::copy_control_area(Vmcb *dest, Vmcb *src) +{ + Vmcb_control_area *d = &dest->control_area; + Vmcb_control_area *s = &src->control_area; + + d->intercept_rd_crX = s->intercept_rd_crX; + d->intercept_wr_crX = s->intercept_wr_crX; + + d->intercept_rd_drX = s->intercept_rd_drX; + d->intercept_wr_drX = s->intercept_wr_drX; + + d->intercept_exceptions = s->intercept_exceptions; + + d->intercept_instruction0 = s->intercept_instruction0; + d->intercept_instruction1 = s->intercept_instruction1; + + // skip iopm_base_pa and msrpm_base_pa + + d->tsc_offset = s->tsc_offset; + d->guest_asid_tlb_ctl = s->guest_asid_tlb_ctl; + d->interrupt_ctl = s->interrupt_ctl; + d->interrupt_shadow = s->interrupt_shadow; + d->exitcode = s->exitcode; + d->exitinfo1 = s->exitinfo1; + d->exitinfo2 = s->exitinfo2; + d->exitintinfo = s->exitintinfo; + d->np_enable = s->np_enable; + + d->eventinj = s->eventinj; + d->n_cr3 = s->n_cr3; + d->lbr_virtualization_enable = s->lbr_virtualization_enable; +} + + +/* skip anything that does not change */ +PRIVATE +void +Vm_svm::copy_control_area_back(Vmcb *dest, Vmcb *src) +{ + Vmcb_control_area *d = &dest->control_area; + Vmcb_control_area *s = &src->control_area; + + d->interrupt_ctl = s->interrupt_ctl; + d->interrupt_shadow = s->interrupt_shadow; + + d->exitcode = s->exitcode; + d->exitinfo1 = s->exitinfo1; + d->exitinfo2 = s->exitinfo2; + d->exitintinfo = s->exitintinfo; + + d->eventinj = s->eventinj; +} + +/** \brief Choose an ASID for this Vm. + * + * Choose an ASID for this Vm. The ASID provided by userspace is ignored + * instead the kernel picks one. + * Userspace uses the flush-bit to receive a new ASID for this Vm. + * All ASIDs are flushed as soon as the kernel runs out of ASIDs. + * + * @param vmcb_s external VMCB provided by userspace + * @param kernel_vmcb_s our VMCB + * + */ +PRIVATE +void +Vm_svm::configure_asid(Vmcb *vmcb_s, Vmcb *kernel_vmcb_s) +{ + assert (cpu_lock.test()); + + Svm &s = Svm::cpus.cpu(current_cpu()); + + if (// vmm requests flush + ((vmcb_s->control_area.guest_asid_tlb_ctl >> 32) & 1) == 1 || + // our asid is not valid or expired + !(s.asid_valid(asid(), asid_generation()))) + { + asid(s.next_asid()); + asid_generation(s.global_asid_generation()); + } + + assert(s.asid_valid(asid(), asid_generation())); +#if 1 + kernel_vmcb_s->control_area.guest_asid_tlb_ctl = asid(); + if (s.flush_all_asids()) + { + kernel_vmcb_s->control_area.guest_asid_tlb_ctl |= (1ULL << 32); + s.flush_all_asids(false); + } +#else + kernel_vmcb_s->control_area.guest_asid_tlb_ctl = 1; + kernel_vmcb_s->control_area.guest_asid_tlb_ctl |= (1ULL << 32); +#endif +} + +PRIVATE inline NOEXPORT +int +Vm_svm::do_resume_vcpu(Context *ctxt, Vcpu_state *vcpu, Vmcb *vmcb_s) +{ + //Mword host_cr0; + Unsigned64 orig_cr3, orig_ncr3; + + assert (cpu_lock.test()); + + /* these 4 must not use ldt entries */ + assert (!(Cpu::get_cs() & (1 << 2))); + assert (!(Cpu::get_ss() & (1 << 2))); + assert (!(Cpu::get_ds() & (1 << 2))); + assert (!(Cpu::get_es() & (1 << 2))); + + Svm &s = Svm::cpus.cpu(current_cpu()); + + // FIXME: this can be an assertion I think, however, think about MP + if (EXPECT_FALSE(!s.svm_enabled())) + { + WARN("svm: not supported/enabled\n"); + return -L4_err::EInval; + } + + if (EXPECT_FALSE(vmcb_s->np_enabled() && !s.has_npt())) + { + WARN("svm: No NPT available\n"); + return -L4_err::EInval; + } + + Address vm_cr3 = get_vm_cr3(vmcb_s); + // can only fail on 64bit, will be optimized away on 32bit + if (EXPECT_FALSE(is_64bit() && !vm_cr3)) + return -L4_err::ENomem; + + // neither EFER.LME nor EFER.LMA must be set + if (EXPECT_FALSE(!is_64bit() + && (vmcb_s->state_save_area.efer & (EFER_LME | EFER_LMA)))) + { + WARN("svm: EFER invalid %llx\n", vmcb_s->state_save_area.efer); + return -L4_err::EInval; + } + + // EFER.SVME must be set + if (!(vmcb_s->state_save_area.efer & 0x1000)) + { + WARN("svm: EFER invalid %llx\n", vmcb_s->state_save_area.efer); + return -L4_err::EInval; + } + // allow PAE in combination with NPT +#if 0 + // CR4.PAE must be clear + if(vmcb_s->state_save_area.cr4 & 0x20) + return -L4_err::EInval; +#endif + + // XXX: + // This generates a circular dep between thread<->task, this cries for a + // new abstraction... + if (!(ctxt->state() & Thread_fpu_owner)) + { + if (!static_cast(ctxt)->switchin_fpu()) + { + WARN("svm: switchin_fpu failed\n"); + return -L4_err::EInval; + } + } + +#if 0 //should never happen + host_cr0 = Cpu::get_cr0(); + // the VMM does not currently own the fpu but wants to + // make it available for the guest. This may happen + // if it was descheduled between activating the fpu and + // executing the vm_run operation + if (!(vmcb_s->state_save_area.cr0 & 0x8) && (host_cr0 & 0x8)) + { + WARN("svm: FPU TS\n"); + return commit_result(-L4_err::EInval); + } +#endif + + // increment our refcount, and drop it at the end automatically + Ref_ptr pin_myself(this); + + // sanitize VMCB + + orig_cr3 = vmcb_s->state_save_area.cr3; + orig_ncr3 = vmcb_s->control_area.n_cr3; + + Vmcb *kernel_vmcb_s = s.kernel_vmcb(); + + copy_control_area(kernel_vmcb_s, vmcb_s); + copy_state_save_area(kernel_vmcb_s, vmcb_s); + + if (EXPECT_FALSE(is_64bit() && !kernel_vmcb_s->np_enabled() + && (kernel_vmcb_s->state_save_area.cr0 & CR0_PG) + && !(kernel_vmcb_s->state_save_area.cr4 & CR4_PAE))) + { + WARN("svm: No 32bit shadow page-tables on AMD64, use PAE!\n"); + return -L4_err::EInval; + } + + // set MCE according to host + kernel_vmcb_s->state_save_area.cr4 |= Cpu::get_cr4() & CR4_MCE; + + // allow w access to cr0, cr2, cr3 + // allow r access to cr0, cr2, cr3, cr4 + // to do: check if enabling PAE in cr4 needs to be controlled + + // allow r/w access to dr[0-7] + kernel_vmcb_s->control_area.intercept_rd_drX |= 0xff00; + kernel_vmcb_s->control_area.intercept_wr_drX |= 0xff00; + +#if 0 + // intercept exception vectors 0-31 + kernel_vmcb_s->control_area.intercept_exceptions = 0xffffffff; +#endif + + // enable iopm and msrpm + kernel_vmcb_s->control_area.intercept_instruction0 |= 0x18000000; + // intercept FERR_FREEZE and shutdown events + kernel_vmcb_s->control_area.intercept_instruction0 |= 0xc0000000; + // intercept INTR/NMI/SMI/INIT + kernel_vmcb_s->control_area.intercept_instruction0 |= 0xf; + // intercept INVD + kernel_vmcb_s->control_area.intercept_instruction0 |= (1 << 22); + // intercept HLT + kernel_vmcb_s->control_area.intercept_instruction0 |= (1 << 24); + // intercept task switch + kernel_vmcb_s->control_area.intercept_instruction0 |= (1 << 29); + // intercept shutdown + kernel_vmcb_s->control_area.intercept_instruction0 |= (1 << 31); + // intercept MONITOR/MWAIT + kernel_vmcb_s->control_area.intercept_instruction1 |= (1 << 10) | (1 << 11); + + // intercept virtualization related instructions + // vmrun interception is required by the hardware + kernel_vmcb_s->control_area.intercept_instruction1 |= 0xff; + + Mword kernel_vmcb_pa = s.kernel_vmcb_pa(); + Unsigned64 iopm_base_pa = s.iopm_base_pa(); + Unsigned64 msrpm_base_pa = s.msrpm_base_pa(); + + kernel_vmcb_s->control_area.iopm_base_pa = iopm_base_pa; + kernel_vmcb_s->control_area.msrpm_base_pa = msrpm_base_pa; + + configure_asid(vmcb_s, kernel_vmcb_s); + + // 7:0 V_TPR, 8 V_IRQ, 15:9 reserved SBZ, + // 19:16 V_INTR_PRIO, 20 V_IGN_TPR, 23:21 reserved SBZ + // 24 V_INTR_MASKING 31:25 reserved SBZ + // 39:32 V_INTR_VECTOR, 63:40 reserved SBZ +#if 0 + kernel_vmcb_s->control_area.interrupt_ctl = 0x10f0000; +#endif + // enable IRQ masking virtualization + kernel_vmcb_s->control_area.interrupt_ctl |= 0x01000000; + +#if 0 + // 0 INTERRUPT_SHADOW, 31:1 reserved SBZ + // 63:32 reserved SBZ + kernel_vmcb_s->control_area.interrupt_shadow = 0; +#endif + + kernel_vmcb_s->control_area.exitcode = 0; + kernel_vmcb_s->control_area.exitinfo1 = 0; + kernel_vmcb_s->control_area.exitinfo2 = 0; + kernel_vmcb_s->control_area.exitintinfo = 0; + +#if 0 + // 0/1 NP_ENABLE, 31:1 reserved SBZ + kernel_vmcb_s->control_area.np_enable = 1; + + // 31 VALID, EVENTINJ + kernel_vmcb_s->control_area.eventinj = 0; +#endif + + // N_CR3 + kernel_vmcb_s->control_area.n_cr3 = vm_cr3; + + if (!kernel_vmcb_s->np_enabled()) + { + // to do: check that the vmtask has the + // VM property set, i.e. does not contain mappings + // to the fiasco kernel regions or runs with PL 3 + + // printf("nested paging disabled, use n_cr3 as cr3\n"); + kernel_vmcb_s->state_save_area.cr3 = vm_cr3; + + // intercept accesses to cr0, cr3 and cr4 + kernel_vmcb_s->control_area.intercept_rd_crX = 0xfff9; + kernel_vmcb_s->control_area.intercept_wr_crX = 0xfff9; + } + +#if 0 + kernel_vmcb_s->control_area.lbr_virtualization_enable = 0; +#endif + + + // to do: + // - initialize VM_HSAVE_PA (done) + // - supply trusted msrpm_base_pa and iopm_base_pa (done) + // - save host state not covered by VMRUN/VMEXIT (ldt, some segments etc) (done) + // - disable interupts (done) + // - trigger interecepted device and timer interrupts (done, not necessary) + // - check host CR0.TS (floating point registers) (done) + + Unsigned64 sysenter_cs, sysenter_eip, sysenter_esp; + Unsigned32 fs, gs; + Unsigned16 tr, ldtr; + //Unsigned32 cr4; + + sysenter_cs = Cpu::rdmsr(MSR_SYSENTER_CS); + sysenter_eip = Cpu::rdmsr(MSR_SYSENTER_EIP); + sysenter_esp = Cpu::rdmsr(MSR_SYSENTER_ESP); + + fs = Cpu::get_fs(); + gs = Cpu::get_gs(); + tr = Cpu::get_tr(); + ldtr = Cpu::get_ldt(); + + Gdt_entry tr_entry; + + tr_entry = (*Cpu::cpus.cpu(current_cpu()).get_gdt())[tr / 8]; + +#if 0 + // to do: check if the nested page table walker looks + // into the TLB. if so, global pages have to be disabled in + // the host + cr4 = Cpu::get_cr4(); + + if (cr4 & CR4_PGE) + // disable support for global pages as the vm task has + // a divergent upper memory region from the regular tasks + Cpu::set_cr4(cr4 & ~CR4_PGE); +#endif + + resume_vm_svm(kernel_vmcb_pa, vcpu); + + +#if 0 + if (cr4 & CR4_PGE) + Cpu::set_cr4(cr4); +#endif + + Cpu::wrmsr(sysenter_cs, MSR_SYSENTER_CS); + Cpu::wrmsr(sysenter_eip, MSR_SYSENTER_EIP); + Cpu::wrmsr(sysenter_esp, MSR_SYSENTER_ESP); + + Cpu::set_ldt(ldtr); + Cpu::set_fs(fs); + Cpu::set_gs(gs); + + // clear busy flag + Gdt_entry tss_entry; + + tss_entry = (*Cpu::cpus.cpu(current_cpu()).get_gdt())[tr / 8]; + tss_entry.access &= 0xfd; + (*Cpu::cpus.cpu(current_cpu()).get_gdt())[tr / 8] = tss_entry; + + Cpu::set_tr(tr); // TODO move under stgi in asm + + copy_state_save_area(vmcb_s, kernel_vmcb_s); + copy_control_area_back(vmcb_s, kernel_vmcb_s); + + if (!(vmcb_s->np_enabled())) + vmcb_s->state_save_area.cr3 = orig_cr3; + + vmcb_s->control_area.n_cr3 = orig_ncr3; + + LOG_TRACE("VM-SVM", "svm", current(), __fmt_vm_svm_exit, + Log_vm_svm_exit *l = tbe->payload(); + l->exitcode = vmcb_s->control_area.exitcode; + l->exitinfo1 = vmcb_s->control_area.exitinfo1; + l->exitinfo2 = vmcb_s->control_area.exitinfo2; + l->rip = vmcb_s->state_save_area.rip; + ); + + // check for IRQ exit + if (kernel_vmcb_s->control_area.exitcode == 0x60) + return 1; + + vcpu->state &= ~(Vcpu_state::F_traps | Vcpu_state::F_user_mode); + return 0; +} + +PUBLIC +int +Vm_svm::resume_vcpu(Context *ctxt, Vcpu_state *vcpu, bool user_mode) +{ + (void)user_mode; + assert_kdb (user_mode); + + if (EXPECT_FALSE(!(ctxt->state(true) & Thread_ext_vcpu_enabled))) + return -L4_err::EInval; + + Vmcb *vmcb_s = reinterpret_cast(reinterpret_cast(vcpu) + 0x400); + for (;;) + { + // in the case of disabled IRQs and a pending IRQ directly simulate an + // external interrupt intercept + if ( !(vcpu->_saved_state & Vcpu_state::F_irqs) + && (vcpu->sticky_flags & Vcpu_state::Sf_irq_pending)) + { + vmcb_s->control_area.exitcode = 0x60; + return 1; // return 1 to indicate pending IRQs (IPCs) + } + + int r = do_resume_vcpu(ctxt, vcpu, vmcb_s); + + // test for error or non-IRQ exit reason + if (r <= 0) + return r; + + // check for IRQ exits and allow to handle the IRQ + if (r == 1) + Proc::preemption_point(); + + // Check if the current context got a message delivered. + // This is done by testing for a valid continuation. + // When a continuation is set we have to directly + // leave the kernel to not overwrite the vcpu-regs + // with bogus state. + Thread *t = nonull_static_cast(ctxt); + + if (t->continuation_test_and_restore()) + t->fast_return_to_user(vcpu->_entry_ip, vcpu->_entry_sp, + t->vcpu_state().usr().get()); + } +} + + + +// ------------------------------------------------------------------------ +IMPLEMENTATION [svm && debug]: + +IMPLEMENT +unsigned +Vm_svm::log_fmt_svm(Tb_entry *e, int max, char *buf) +{ + Log_vm_svm_exit *l = e->payload(); + return snprintf(buf, max, "ec=%lx ei1=%08lx ei2=%08lx rip=%08lx", + l->exitcode, l->exitinfo1, l->exitinfo2, l->rip); +} diff --git a/kernel/fiasco/src/kern/ia32/vm_vmx.cpp b/kernel/fiasco/src/kern/ia32/vm_vmx.cpp new file mode 100644 index 00000000..6d8ebd6d --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/vm_vmx.cpp @@ -0,0 +1,520 @@ +INTERFACE [vmx]: + +#include "config.h" +#include "per_cpu_data.h" +#include "vm.h" +#include "vmx.h" + +class Vmcs; + +class Vm_vmx : public Vm +{ +private: + static unsigned long resume_vm_vmx(Vcpu_state *regs) + asm("resume_vm_vmx") __attribute__((__regparm__(3))); + + enum + { + EFER_LME = 1 << 8, + EFER_LMA = 1 << 10, + }; + +}; + +//---------------------------------------------------------------------------- +IMPLEMENTATION [vmx]: + +#include "context.h" +#include "mem_space.h" +#include "fpu.h" +#include "ref_ptr.h" +#include "thread.h" // XXX: circular dep, move this out here! +#include "thread_state.h" // XXX: circular dep, move this out here! +#include "virt.h" +#include "idt.h" + + +PUBLIC +Vm_vmx::Vm_vmx(Ram_quota *q) + : Vm(q) +{} + +PUBLIC inline +void * +Vm_vmx::operator new (size_t size, void *p) throw() +{ + (void)size; + assert (size == sizeof (Vm_vmx)); + return p; +} + +PUBLIC +void +Vm_vmx::operator delete (void *ptr) +{ + Vm_vmx *t = reinterpret_cast(ptr); + allocator()->q_free(t->ram_quota(), ptr); +} + + + + +PRIVATE static inline +void * +Vm_vmx::field_offset(void *vmcs, unsigned field) +{ + return (void *)((char *)vmcs + + ((field >> 13) * 4 + ((field >> 10) & 3) + 1) * 0x80); +} + +PRIVATE static inline +unsigned +Vm_vmx::field_width(unsigned field) +{ + static const char widths[4] = { 2, 8, 4, sizeof(Mword) }; + return widths[field >> 13]; +} + + +PRIVATE inline +template +Vmx_info::Flags +Vm_vmx::load(unsigned field, void *vmcs, Vmx_info::Bit_defs const &m) +{ + T res = m.apply(read(vmcs, field)); + Vmx::vmwrite(field, res); + return Vmx_info::Flags(res); +} + +PRIVATE inline +void +Vm_vmx::load(unsigned field_first, unsigned field_last, void *vmcs) +{ + for (; field_first <= field_last; field_first += 2) + load(field_first, vmcs); +} + +PRIVATE inline static +template< typename T > +T +Vm_vmx::_internal_read(void *vmcs, unsigned field) +{ + vmcs = field_offset(vmcs, field); + return *((T *)vmcs + ((field >> 1) & 0xff)); +} + +PRIVATE inline static +template< typename T > +void +Vm_vmx::_internal_write(void *vmcs, unsigned field, T value) +{ + vmcs = field_offset(vmcs, field); + *((T*)vmcs + ((field >> 1) & 0xff)) = value; +} + +PRIVATE inline +void +Vm_vmx::load(unsigned field, void *vmcs) +{ + switch (field >> 13) + { + case 0: Vmx::vmwrite(field, _internal_read(vmcs, field)); break; + case 1: Vmx::vmwrite(field, _internal_read(vmcs, field)); break; + case 2: Vmx::vmwrite(field, _internal_read(vmcs, field)); break; + case 3: Vmx::vmwrite(field, _internal_read(vmcs, field)); break; + } +} + +PRIVATE inline +void +Vm_vmx::store(unsigned field, void *vmcs) +{ + switch (field >> 13) + { + case 0: _internal_write(vmcs, field, Vmx::vmread(field)); break; + case 1: _internal_write(vmcs, field, Vmx::vmread(field)); break; + case 2: _internal_write(vmcs, field, Vmx::vmread(field)); break; + case 3: _internal_write(vmcs, field, Vmx::vmread(field)); break; + } +} + +PRIVATE inline +void +Vm_vmx::store(unsigned field_first, unsigned field_last, void *vmcs) +{ + for (; field_first <= field_last; field_first += 2) + store(field_first, vmcs); +} + +PRIVATE inline static +template< typename T > +void +Vm_vmx::write(void *vmcs, unsigned field, T value) +{ + switch (field >> 13) + { + case 0: _internal_write(vmcs, field, (Unsigned16)value); break; + case 1: _internal_write(vmcs, field, (Unsigned64)value); break; + case 2: _internal_write(vmcs, field, (Unsigned32)value); break; + case 3: _internal_write(vmcs, field, (Mword)value); break; + } +} + +PRIVATE inline static +template< typename T > +T +Vm_vmx::read(void *vmcs, unsigned field) +{ + switch (field >> 13) + { + case 0: return _internal_read(vmcs, field); + case 1: return _internal_read(vmcs, field); + case 2: return _internal_read(vmcs, field); + case 3: return _internal_read(vmcs, field); + } + return 0; +} + + +PRIVATE +void +Vm_vmx::load_guest_state(unsigned cpu, void *src) +{ + Vmx &vmx = Vmx::cpus.cpu(cpu); + + // read VM-entry controls, apply filter and keep for later + Vmx_info::Flags entry_ctls + = load(Vmx::F_entry_ctls, src, vmx.info.entry_ctls); + + Vmx_info::Flags pinbased_ctls + = load(Vmx::F_pin_based_ctls, src, vmx.info.pinbased_ctls); + + Vmx_info::Flags procbased_ctls + = load(Vmx::F_proc_based_ctls, src, vmx.info.procbased_ctls); + + Vmx_info::Flags procbased_ctls_2; + if (procbased_ctls.test(Vmx::PRB1_enable_proc_based_ctls_2)) + procbased_ctls_2 = load(Vmx::F_proc_based_ctls_2, src, vmx.info.procbased_ctls2); + else + procbased_ctls_2 = Vmx_info::Flags(0); + + load(Vmx::F_exit_ctls, src, vmx.info.exit_ctls); + + // write 16-bit fields + load(0x800, 0x80e, src); + + // write 64-bit fields + load(0x2802, src); + + // check if the following bits are allowed to be set in entry_ctls + if (entry_ctls.test(14)) // PAT load requested + load(0x2804, src); + + if (entry_ctls.test(15)) // EFER load requested + load(0x2806, src); + + if (entry_ctls.test(13)) // IA32_PERF_GLOBAL_CTRL load requested + load(0x2808, src); + + // this is Fiasco.OC internal state +#if 0 + if (vmx.has_ept()) + load(0x280a, 0x2810, src); +#endif + + // write 32-bit fields + load(0x4800, 0x482a, src); + + if (pinbased_ctls.test(6)) // activate vmx-preemption timer + load(0x482e, src); + + // write natural-width fields + load(0x6800, src, vmx.info.cr0_defs); + + if (sizeof(long) > sizeof(int)) + { + if (read(src, 0x2806) & EFER_LME) + Vmx::vmwrite(0x6802, (Mword)phys_dir()); + else + WARN("VMX: No, not possible\n"); + } + else + { + // for 32bit we can just load the Vm pdbr + Vmx::vmwrite(0x6802, (Mword)phys_dir()); + } + + load(0x6804, src, vmx.info.cr4_defs); + load(0x6806, 0x6826, src); + + // VPID must be virtualized in Fiasco +#if 0 + if (procbased_ctls_2 & Vmx::PB2_enable_vpid) + load(Vmx::F_vpid, src); +#endif + + // currently io-bitmaps are unsupported + // currently msr-bitmaps are unsupported + + // load(0x200C, src); for SMM virtualization + load(Vmx::F_tsc_offset, src); + + // no virtual APIC yet, and has to be managed in kernel somehow +#if 0 + if (procbased_ctls.test(Vmx::PRB1_tpr_shadow)) + load(0x2012, src); +#endif + + if (procbased_ctls_2.test(Vmx::PRB2_virtualize_apic)) + load(Vmx::F_apic_access_addr, src); + + // exception bit map and pf error-code stuff + load(0x4004, 0x4008, src); + + // vm entry control stuff + Unsigned32 irq_info = read(src, Vmx::F_entry_int_info); + if (irq_info & (1UL << 31)) + { + // do event injection + + // load error code, if required + if (irq_info & (1UL << 11)) + load(Vmx::F_entry_exc_error_code, src); + + // types, that require an insn length have bit 10 set (type 4, 5, and 6) + if (irq_info & (1UL << 10)) + load(Vmx::F_entry_insn_len, src); + + Vmx::vmwrite(Vmx::F_entry_int_info, irq_info); + } + + // hm, we have to check for sanitizing the cr0 and cr4 shadow stuff + load(0x6000, 0x6006, src); + + // no cr3 target values supported +} + + +PRIVATE +void +Vm_vmx::store_guest_state(unsigned cpu, void *dest) +{ + // read 16-bit fields + store(0x800, 0x80e, dest); + + // read 64-bit fields + store(0x2802, dest); + + Vmx_info &vmx_info = Vmx::cpus.cpu(cpu).info; + Vmx_info::Flags exit_ctls + = Vmx_info::Flags(vmx_info.exit_ctls.apply(read(dest, Vmx::F_exit_ctls))); + + if (exit_ctls.test(18)) store(Vmx::F_guest_pat, dest); + if (exit_ctls.test(20)) store(Vmx::F_guest_efer, dest); + if (exit_ctls.test(22)) store(Vmx::F_preempt_timer, dest); + + // EPT and PAE handling missing +#if 0 + if (Vmx::cpus.cpu(cpu).has_ept()) + store(0x280a, 0x2810, dest); +#endif + + // read 32-bit fields + store(0x4800, 0x4826, dest); + + // sysenter msr is not saved here, because we trap all msr accesses right now + if (0) + { + store(0x482a, dest); + store(0x6824, 0x6826, dest); + } + + // read natural-width fields + store(0x6800, dest); + // skip cr3 + store(0x6804, 0x6822, dest); +} + +PRIVATE +void +Vm_vmx::store_exit_info(unsigned cpu, void *dest) +{ + (void)cpu; + // read 64-bit fields, that is a EPT pf thing +#if 0 + if (Vmx::cpus.cpu(cpu).has_ept()) + store(0x2400, dest); +#endif + + // clear the valid bit in Vm-entry interruption information + { + Unsigned32 tmp = read(dest, Vmx::F_entry_int_info); + if (tmp & (1UL << 31)) + write(dest, Vmx::F_entry_int_info, tmp & ~((Unsigned32)1 << 31)); + } + + // read 32-bit fields + store(0x4400, 0x440e, dest); + + // read natural-width fields + store(0x6400, 0x640a, dest); +} + +PRIVATE +void +Vm_vmx::dump(void *v, unsigned f, unsigned t) +{ + for (; f <= t; f += 2) + printf("%04x: VMCS: %16lx V: %16lx\n", + f, Vmx::vmread(f), read(v, f)); +} + +PRIVATE +void +Vm_vmx::dump_state(void *v) +{ + dump(v, 0x0800, 0x080e); + dump(v, 0x0c00, 0x0c0c); + dump(v, 0x2000, 0x201a); + dump(v, 0x2800, 0x2810); + dump(v, 0x2c00, 0x2804); + dump(v, 0x4000, 0x4022); + dump(v, 0x4400, 0x4420); + dump(v, 0x4800, 0x482a); + dump(v, 0x6800, 0x6826); + dump(v, 0x6c00, 0x6c16); +} + +PRIVATE inline NOEXPORT +int +Vm_vmx::do_resume_vcpu(Context *ctxt, Vcpu_state *vcpu, void *vmcs_s) +{ + assert (cpu_lock.test()); + + /* these 4 must not use ldt entries */ + assert (!(Cpu::get_cs() & (1 << 2))); + assert (!(Cpu::get_ss() & (1 << 2))); + assert (!(Cpu::get_ds() & (1 << 2))); + assert (!(Cpu::get_es() & (1 << 2))); + + unsigned cpu = current_cpu(); + Vmx &v = Vmx::cpus.cpu(cpu); + + if (!v.vmx_enabled()) + { + WARNX(Info, "VMX: not supported/enabled\n"); + return -L4_err::ENodev; + } + + // XXX: + // This generates a circular dep between thread<->task, this cries for a + // new abstraction... + if (!(ctxt->state() & Thread_fpu_owner)) + { + if (EXPECT_FALSE(!static_cast(ctxt)->switchin_fpu())) + { + WARN("VMX: switchin_fpu failed\n"); + return -L4_err::EInval; + } + } + +#if 0 + if (EXPECT_FALSE(read(vmcs_s, 0x201a) != 0)) // EPT POINTER + { + WARN("VMX: no nested paging available\n"); + return commit_result(-L4_err::EInval); + } +#endif + + // increment our refcount, and drop it at the end automatically + Ref_ptr pin_myself(this); + + // set volatile host state + Vmx::vmwrite(Vmx::F_host_cr3, Cpu::get_pdbr()); // host_area.cr3 + + load_guest_state(cpu, vmcs_s); + + Unsigned16 ldt = Cpu::get_ldt(); + + // set guest CR2 + asm volatile("mov %0, %%cr2" : : "r" (read(vmcs_s, Vmx::F_guest_cr2))); + + unsigned long ret = resume_vm_vmx(vcpu); + // vmread error? + if (EXPECT_FALSE(ret & 0x40)) + return -L4_err::EInval; + + // save guest cr2 + { + Mword cpu_cr2; + asm volatile("mov %%cr2, %0" : "=r" (cpu_cr2)); + write(vmcs_s, Vmx::F_guest_cr2, cpu_cr2); + } + + Cpu::set_ldt(ldt); + + // reload TSS, we use I/O bitmaps + // ... do this lazy ... + { + // clear busy flag + Gdt_entry *e = &(*Cpu::cpus.cpu(cpu).get_gdt())[Gdt::gdt_tss / 8]; + e->access &= ~(1 << 1); + asm volatile("" : : "m" (*e)); + Cpu::set_tr(Gdt::gdt_tss); + } + + store_guest_state(cpu, vmcs_s); + store_exit_info(cpu, vmcs_s); + + if ((read(vmcs_s, Vmx::F_exit_reason) & 0xffff) == 1) + return 1; + + vcpu->state &= ~(Vcpu_state::F_traps | Vcpu_state::F_user_mode); + return 0; +} + +PUBLIC +int +Vm_vmx::resume_vcpu(Context *ctxt, Vcpu_state *vcpu, bool user_mode) +{ + (void)user_mode; + assert_kdb (user_mode); + + if (EXPECT_FALSE(!(ctxt->state(true) & Thread_ext_vcpu_enabled))) + return -L4_err::EInval; + + void *vmcs_s = reinterpret_cast(vcpu) + 0x400; + + for (;;) + { + // in the case of disabled IRQs and a pending IRQ directly simulate an + // external interrupt intercept + if ( !(vcpu->_saved_state & Vcpu_state::F_irqs) + && (vcpu->sticky_flags & Vcpu_state::Sf_irq_pending)) + { + // XXX: check if this is correct, we set external irq exit as reason + write(vmcs_s, Vmx::F_exit_reason, 1); + return 1; // return 1 to indicate pending IRQs (IPCs) + } + + int r = do_resume_vcpu(ctxt, vcpu, vmcs_s); + + // test for error or non-IRQ exit reason + if (r <= 0) + return r; + + // check for IRQ exits and allow to handle the IRQ + if (r == 1) + Proc::preemption_point(); + + // Check if the current context got a message delivered. + // This is done by testing for a valid continuation. + // When a continuation is set we have to directly + // leave the kernel to not overwrite the vcpu-regs + // with bogus state. + Thread *t = nonull_static_cast(ctxt); + if (t->continuation_test_and_restore()) + t->fast_return_to_user(vcpu->_entry_ip, vcpu->_entry_sp, + t->vcpu_state().usr().get()); + } +} diff --git a/kernel/fiasco/src/kern/ia32/vmem_alloc-ia32.cpp b/kernel/fiasco/src/kern/ia32/vmem_alloc-ia32.cpp new file mode 100644 index 00000000..183483c0 --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/vmem_alloc-ia32.cpp @@ -0,0 +1,69 @@ +IMPLEMENTATION[ia32,ux,amd64]: + +#include +#include +#include +#include "config.h" +#include "kdb_ke.h" +#include "kmem.h" +#include "kmem_alloc.h" +#include "mem_layout.h" +#include "mem_unit.h" +#include "paging.h" +#include "static_init.h" +#include "initcalls.h" +#include "space.h" + +IMPLEMENT +void* +Vmem_alloc::page_alloc(void *address, Zero_fill zf, unsigned mode) +{ + void *vpage = 0; + Address page; + + vpage = Kmem_alloc::allocator()->alloc(Config::PAGE_SHIFT); + + if (EXPECT_FALSE(!vpage)) + return 0; + + // insert page into master page table + Pdir::Iter e = Kmem::kdir->walk(Virt_addr(address), 100, + pdir_alloc(Kmem_alloc::allocator())); + if (EXPECT_FALSE(e.e->valid())) + { + kdb_ke("page_alloc: address already mapped"); + goto error; + } + + if (e.shift() != Config::PAGE_SHIFT) + goto error; + + if (zf == ZERO_FILL) + memset(vpage, 0, Config::PAGE_SIZE); + + page = Mem_layout::pmem_to_phys((Address)vpage); + + *e.e = page | Pt_entry::Writable | Pt_entry::Dirty + | Pt_entry::Valid | Pt_entry::Referenced | Pt_entry::global(); + page_map (address, 0, zf, page); + + if (mode & User) + e.e->add_attr(Pt_entry::User); + + return address; + +error: + Kmem_alloc::allocator()->free(Config::PAGE_SHIFT, vpage); // 2^0 = 1 page + return 0; +} + + +//---------------------------------------------------------------------------- +IMPLEMENTATION[ia32,amd64]: + +IMPLEMENT inline +void +Vmem_alloc::page_map(void * /*address*/, int /*order*/, Zero_fill /*zf*/, + Address /*phys*/) +{} + diff --git a/kernel/fiasco/src/kern/ia32/vmx.cpp b/kernel/fiasco/src/kern/ia32/vmx.cpp new file mode 100644 index 00000000..b93723c2 --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/vmx.cpp @@ -0,0 +1,578 @@ +INTERFACE [vmx]: + +#include "per_cpu_data.h" +#include + +class Vmx_info +{ +public: + static bool nested_paging() { return false; } + + template + class Bit_defs + { + protected: + T _or; + T _and; + + public: + Bit_defs() {} + Bit_defs(T _or, T _and) : _or(_or), _and(_and) {} +#if 0 + template + explicit Bit_defs(Bit_defs const &o) + : _or(o.must_be_one()), _and(o.may_be_one()) {} +#endif + T must_be_one() const { return _or; } + T may_be_one() const { return _and; } + + private: + void enforce_bits(T m, bool value = true) + { + if (value) + _or |= m; + else + _and &= ~m; + } + + bool allowed_bits(T m, bool value = true) const + { + if (value) + return _and & m; + else + return !(_or & m); + } + + public: + void enforce(unsigned char bit, bool value = true) + { enforce_bits((T)1 << (T)bit, value); } + + bool allowed(unsigned char bit, bool value = true) const + { return allowed_bits((T)1 << (T)bit, value); } + + T apply(T v) const { return (v | _or) & _and; } + + void print(char const *name) const + { + if (sizeof(T) <= 4) + printf("%20s = %8x %8x\n", name, (unsigned)_and, (unsigned)_or); + else if (sizeof(T) <= 8) + printf("%20s = %16llx %16llx\n", name, (unsigned long long)_and, (unsigned long long)_or); + } + }; + + class Bit_defs_32 : public Bit_defs + { + public: + Bit_defs_32() {} + Bit_defs_32(Unsigned64 v) : Bit_defs(v, v >> 32) {} + }; + + typedef Bit_defs Bit_defs_64; + + template + class Flags + { + public: + Flags() {} + explicit Flags(T v) : _f(v) {} + + T test(unsigned char bit) const { return _f & ((T)1 << (T)bit); } + private: + T _f; + }; + + Unsigned64 basic; + + Bit_defs_32 pinbased_ctls; + Bit_defs_32 procbased_ctls; + + Bit_defs_32 exit_ctls; + Bit_defs_32 entry_ctls; + Unsigned64 misc; + + Bit_defs cr0_defs; + Bit_defs cr4_defs; + Bit_defs_32 procbased_ctls2; + + Unsigned64 ept_vpid_cap; + Unsigned64 true_pinbased_ctls; + Unsigned64 true_procbased_ctls; + Unsigned64 true_exit_ctls; + Unsigned64 true_entry_ctls; +}; + +INTERFACE: + +class Vmx +{ +public: + enum Vmcs_fields + { + F_vpid = 0x0, + + F_host_es_selector = 0x0c00, + F_host_cs_selector = 0x0c02, + F_host_ss_selector = 0x0c04, + F_host_ds_selector = 0x0c06, + F_host_fs_selector = 0x0c08, + F_host_gs_selector = 0x0c0a, + F_host_tr_selector = 0x0c0c, + + F_tsc_offset = 0x2010, + F_apic_access_addr = 0x2014, + + F_guest_pat = 0x2804, + F_guest_efer = 0x2806, + + F_host_ia32_pat = 0x2c00, + F_host_ia32_efer = 0x2c02, + F_host_ia32_perf_global_ctrl = 0x2c04, + + + F_pin_based_ctls = 0x4000, + F_proc_based_ctls = 0x4002, + + F_cr3_target_cnt = 0x400a, + F_exit_ctls = 0x400c, + F_exit_msr_store_cnt = 0x400e, + F_exit_msr_load_cnt = 0x4010, + F_entry_ctls = 0x4012, + F_entry_msr_load_cnt = 0x4014, + F_entry_int_info = 0x4016, + F_entry_exc_error_code = 0x4018, + F_entry_insn_len = 0x401a, + F_proc_based_ctls_2 = 0x401e, + + F_vm_instruction_error = 0x4400, + F_exit_reason = 0x4402, + + F_preempt_timer = 0x482e, + + F_host_sysenter_cs = 0x4c00, + + F_guest_cr2 = 0x6830, + + F_host_cr0 = 0x6c00, + F_host_cr3 = 0x6c02, + F_host_cr4 = 0x6c04, + F_host_fs_base = 0x6c06, + F_host_gs_base = 0x6c08, + F_host_tr_base = 0x6c0a, + F_host_gdtr_base = 0x6c0c, + F_host_idtr_base = 0x6c0e, + F_host_sysenter_esp = 0x6c10, + F_host_sysenter_eip = 0x6c12, + F_host_rip = 0x6c16, + }; + + enum Pin_based_ctls + { + PIB_ext_int_exit = 0, + PIB_nmi_exit = 3, + }; + + enum Primary_proc_based_ctls + { + PRB1_tpr_shadow = 21, + PRB1_unconditional_io_exit = 24, + PRB1_use_io_bitmaps = 25, + PRB1_use_msr_bitmaps = 28, + PRB1_enable_proc_based_ctls_2 = 31, + }; + + enum Secondary_proc_based_ctls + { + PRB2_virtualize_apic = 0, + PRB2_enable_ept = 1, + PRB2_enable_vpid = 5, + }; + +}; + +INTERFACE [vmx]: + +#include "virt.h" +#include "cpu_lock.h" + +class Vmx_info; + +EXTENSION class Vmx +{ +public: + static Per_cpu cpus; + Vmx_info info; +private: + void *_vmxon; + bool _vmx_enabled; + bool _has_vpid; + Unsigned64 _vmxon_base_pa; + void *_kernel_vmcs; + Unsigned64 _kernel_vmcs_pa; +}; + +class Vmx_info_msr +{ +private: + Unsigned64 _data; +}; + +//----------------------------------------------------------------------------- +INTERFACE [vmx && ia32]: + +EXTENSION class Vmx +{ +public: + enum { Gpregs_words = 11 }; +}; + +//----------------------------------------------------------------------------- +INTERFACE [vmx && amd64]: + +EXTENSION class Vmx +{ +public: + enum { Gpregs_words = 19 }; +}; + + +// ----------------------------------------------------------------------- +IMPLEMENTATION[vmx]: + +#include "cpu.h" +#include "kmem.h" +#include "l4_types.h" +#include +#include "idt.h" +#include "warn.h" + +DEFINE_PER_CPU_LATE Per_cpu Vmx::cpus(true); + +PUBLIC +void +Vmx_info::init() +{ + basic = Cpu::rdmsr(0x480); + pinbased_ctls = Cpu::rdmsr(0x481); + procbased_ctls = Cpu::rdmsr(0x482); + exit_ctls = Cpu::rdmsr(0x483); + entry_ctls = Cpu::rdmsr(0x484); + misc = Cpu::rdmsr(0x485); + + cr0_defs = Bit_defs(Cpu::rdmsr(0x486), Cpu::rdmsr(0x487)); + cr4_defs = Bit_defs(Cpu::rdmsr(0x488), Cpu::rdmsr(0x489)); + + if (basic & (1ULL << 55)) + { + true_pinbased_ctls = Cpu::rdmsr(0x48d); + true_procbased_ctls = Cpu::rdmsr(0x48e); + true_exit_ctls = Cpu::rdmsr(0x48f); + true_entry_ctls = Cpu::rdmsr(0x490); + } + + if (0) + dump("as read from hardware"); + + pinbased_ctls.enforce(Vmx::PIB_ext_int_exit); + pinbased_ctls.enforce(Vmx::PIB_nmi_exit); + + + // currently we IO-passthrough is missing, disable I/O bitmaps and enforce + // unconditional io exiting + procbased_ctls.enforce(Vmx::PRB1_use_io_bitmaps, false); + procbased_ctls.enforce(Vmx::PRB1_unconditional_io_exit); + + // virtual APIC not yet supported + procbased_ctls.enforce(Vmx::PRB1_tpr_shadow, false); + + if (procbased_ctls.allowed(31)) + { + procbased_ctls2 = Cpu::rdmsr(0x48b); + if (procbased_ctls2.allowed(1)) + ept_vpid_cap = Cpu::rdmsr(0x48c); + + // we disable VPID so far, need to handle virtualize it in Fiasco, + // as done for AMDs ASIDs + procbased_ctls2.enforce(Vmx::PRB2_enable_vpid, false); + + // no EPT support yet + procbased_ctls2.enforce(Vmx::PRB2_enable_ept, false); + } + else + procbased_ctls2 = 0; + + // never automatically ack interrupts on exit + exit_ctls.enforce(15, false); + + // host-state is 64bit or not + exit_ctls.enforce(9, sizeof(long) > sizeof(int)); + + if (!nested_paging()) // needs to be per VM + { + // always enable paging + cr0_defs.enforce(31); + // always PE + cr0_defs.enforce(0); + cr4_defs.enforce(4); // PSE + + // enforce PAE on 64bit, and disallow it on 32bit + cr4_defs.enforce(5, sizeof(long) > sizeof(int)); + } + + if (0) + dump("as modified"); +} + +PUBLIC +void +Vmx_info::dump(const char *tag) const +{ + printf("VMX MSRs %s:\n", tag); + printf("basic = %16llx\n", basic); + pinbased_ctls.print("pinbased_ctls"); + procbased_ctls.print("procbased_ctls"); + exit_ctls.print("exit_ctls"); + entry_ctls.print("entry_ctls"); + printf("misc = %16llx\n", misc); + cr0_defs.print("cr0_fixed"); + cr4_defs.print("cr4_fixed"); + procbased_ctls2.print("procbased_ctls2"); + printf("ept_vpid_cap = %16llx\n", ept_vpid_cap); + printf("true_pinbased_ctls = %16llx\n", true_pinbased_ctls); + printf("true_procbased_ctls = %16llx\n", true_procbased_ctls); + printf("true_exit_ctls = %16llx\n", true_exit_ctls); + printf("true_entry_ctls = %16llx\n", true_entry_ctls); +} + +PRIVATE static inline +Mword +Vmx::vmread_insn(Mword field) +{ + Mword val; + asm volatile("vmread %1, %0" : "=r" (val) : "r" (field)); + return val; +} + +PUBLIC static inline NEEDS[Vmx::vmread_insn] +template< typename T > +T +Vmx::vmread(Mword field) +{ + if (sizeof(T) <= sizeof(Mword)) + return vmread_insn(field); + + return vmread_insn(field) | ((Unsigned64)vmread_insn(field + 1) << 32); +} + +PUBLIC static inline NEEDS["warn.h"] +template< typename T > +void +Vmx::vmwrite(Mword field, T value) +{ + Mword err; + asm volatile("vmwrite %1, %2; pushf; pop %0" : "=r" (err) : "r" ((Mword)value), "r" (field)); + if (EXPECT_FALSE(err & 0x1)) + WARNX(Info, "VMX: VMfailInvalid vmwrite(0x%04lx, %llx) => %lx\n", + field, (Unsigned64)value, err); + else if (EXPECT_FALSE(err & 0x40)) + WARNX(Info, "VMX: VMfailValid vmwrite(0x%04lx, %llx) => %lx, insn error: 0x%x\n", + field, (Unsigned64)value, err, vmread(F_vm_instruction_error)); + if (sizeof(T) > sizeof(Mword)) + asm volatile("vmwrite %0, %1" : : "r" ((Unsigned64)value >> 32), "r" (field + 1)); +} + +PUBLIC +Vmx::Vmx(unsigned cpu) + : _vmx_enabled(false), _has_vpid(false) +{ + Cpu &c = Cpu::cpus.cpu(cpu); + if (!c.vmx()) + { + if (!cpu) + WARNX(Info, "VMX: Not supported\n"); + return; + } + + // check whether vmx is enabled by BIOS + Unsigned64 feature = 0; + feature = Cpu::rdmsr(MSR_IA32_FEATURE_CONTROL); + + enum + { + Msr_ia32_feature_control_lock = 1 << 0, + Msr_ia32_feature_control_vmx_inside_SMX = 1 << 1, + Msr_ia32_feature_control_vmx_outside_SMX = 1 << 2, + }; + + if (feature & Msr_ia32_feature_control_lock) + { + if (!(feature & Msr_ia32_feature_control_vmx_outside_SMX)) + { + if (!cpu) + WARNX(Info, "VMX: CPU has VMX support but it is disabled\n"); + return; + } + } + else + c.wrmsr(feature | Msr_ia32_feature_control_vmx_outside_SMX | Msr_ia32_feature_control_lock, + MSR_IA32_FEATURE_CONTROL); + + if (!cpu) + WARNX(Info, "VMX: Enabled\n"); + + info.init(); + + // check for EPT support + if (!cpu) + { + if (info.procbased_ctls2.allowed(1)) + WARNX(Info, "VMX: EPT supported\n"); + else + WARNX(Info, "VMX: No EPT available\n"); + } + + // check for vpid support + if (info.procbased_ctls2.allowed(5)) + _has_vpid = true; + + c.set_cr4(c.get_cr4() | (1 << 13)); // set CR4.VMXE to 1 + + // if NE bit is not set vmxon will fail + c.set_cr0(c.get_cr0() | (1 << 5)); + + enum + { + Vmcs_size = 0x1000, // actual size may be different + }; + + Unsigned32 vmcs_size = ((info.basic & (0x1fffULL << 32)) >> 32); + + if (vmcs_size > Vmcs_size) + { + WARN("VMX: VMCS size of %d bytes not supported\n", vmcs_size); + return; + } + + // allocate a 4kb region for kernel vmcs + check(_kernel_vmcs = Kmem_alloc::allocator()->alloc(12)); + _kernel_vmcs_pa = Kmem::virt_to_phys(_kernel_vmcs); + // clean vmcs + memset(_kernel_vmcs, 0, vmcs_size); + // init vmcs with revision identifier + *(int *)_kernel_vmcs = (info.basic & 0xFFFFFFFF); + + // allocate a 4kb aligned region for VMXON + check(_vmxon = Kmem_alloc::allocator()->alloc(12)); + + _vmxon_base_pa = Kmem::virt_to_phys(_vmxon); + + // init vmxon region with vmcs revision identifier + // which is stored in the lower 32 bits of MSR 0x480 + *(unsigned *)_vmxon = (info.basic & 0xFFFFFFFF); + + // enable vmx operation + asm volatile("vmxon %0" : :"m"(_vmxon_base_pa):); + _vmx_enabled = true; + + if (cpu == 0) + WARNX(Info, "VMX: initialized\n"); + + Mword eflags; + asm volatile("vmclear %1 \n\t" + "pushf \n\t" + "pop %0 \n\t" : "=r"(eflags) : "m"(_kernel_vmcs_pa):); + if (eflags & 0x41) + panic("VMX: vmclear: VMFailInvalid, vmcs pointer not valid\n"); + + // make kernel vmcs current + asm volatile("vmptrld %1 \n\t" + "pushf \n\t" + "pop %0 \n\t" : "=r"(eflags) : "m"(_kernel_vmcs_pa):); + + if (eflags & 0x41) + panic("VMX: vmptrld: VMFailInvalid, vmcs pointer not valid\n"); + + extern char entry_sys_fast_ipc_c[]; + extern char vm_vmx_exit_vec[]; + + vmwrite(F_host_es_selector, GDT_DATA_KERNEL); + vmwrite(F_host_cs_selector, GDT_CODE_KERNEL); + vmwrite(F_host_ss_selector, GDT_DATA_KERNEL); + vmwrite(F_host_ds_selector, GDT_DATA_KERNEL); + + Unsigned16 tr = c.get_tr(); + vmwrite(F_host_tr_selector, tr); + + vmwrite(F_host_tr_base, ((*c.get_gdt())[tr / 8]).base()); + vmwrite(F_host_rip, vm_vmx_exit_vec); + vmwrite(F_host_sysenter_cs, Gdt::gdt_code_kernel); + vmwrite(F_host_sysenter_esp, &c.kernel_sp()); + vmwrite(F_host_sysenter_eip, entry_sys_fast_ipc_c); + + if (c.features() & FEAT_PAT && info.exit_ctls.allowed(19)) + vmwrite(F_host_ia32_pat, Cpu::rdmsr(MSR_PAT)); + else + { + // We have no proper PAT support, so disallow PAT load store for + // guest too + info.exit_ctls.enforce(18, false); + info.entry_ctls.enforce(14, false); + } + + if (info.exit_ctls.allowed(21)) // Load IA32_EFER + vmwrite(F_host_ia32_efer, Cpu::rdmsr(MSR_EFER)); + else + { + // We have no EFER load for host, so disallow EFER load store for + // guest too + info.exit_ctls.enforce(20, false); + info.entry_ctls.enforce(15, false); + } + + if (info.exit_ctls.allowed(12)) + vmwrite(F_host_ia32_perf_global_ctrl, Cpu::rdmsr(0x199)); + else + // do not allow Load IA32_PERF_GLOBAL_CTRL on entry + info.entry_ctls.enforce(13, false); + + vmwrite(F_host_cr0, info.cr0_defs.apply(Cpu::get_cr0())); + vmwrite(F_host_cr4, info.cr4_defs.apply(Cpu::get_cr4())); + + Pseudo_descriptor pseudo; + c.get_gdt()->get(&pseudo); + + vmwrite(F_host_gdtr_base, pseudo.base()); + + Idt::get(&pseudo); + vmwrite(F_host_idtr_base, pseudo.base()); + + // init static guest area stuff + vmwrite(0x2800, ~0ULL); // link pointer + vmwrite(F_cr3_target_cnt, 0); + + // MSR load / store disabled + vmwrite(F_exit_msr_load_cnt, 0); + vmwrite(F_exit_msr_store_cnt, 0); + vmwrite(F_entry_msr_load_cnt, 0); + +} + +PUBLIC +void * +Vmx::kernel_vmcs() const +{ return _kernel_vmcs; } + +PUBLIC +Address +Vmx::kernel_vmcs_pa() const +{ return _kernel_vmcs_pa; } + +PUBLIC +bool +Vmx::vmx_enabled() const +{ return _vmx_enabled; } + +PUBLIC +bool +Vmx::has_vpid() const +{ return _has_vpid; } diff --git a/kernel/fiasco/src/kern/ia32/watchdog-ia32.cpp b/kernel/fiasco/src/kern/ia32/watchdog-ia32.cpp new file mode 100644 index 00000000..88a4650a --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/watchdog-ia32.cpp @@ -0,0 +1,141 @@ +INTERFACE [watchdog && (ia32 || amd64)]: + +#include "types.h" +#include "initcalls.h" + +class Watchdog +{ +public: + static void (*touch)(void); + static void (*enable)(void); + static void (*disable)(void); + +private: + Watchdog(); // default constructors are undefined + Watchdog(const Watchdog&); + + typedef struct + { + unsigned active:1; + unsigned user_active:1; + unsigned no_user_control:1; + } Watchdog_flags; + + static Watchdog_flags flags; +}; + +// ------------------------------------------------------------------------ +IMPLEMENTATION [watchdog && (ia32 || amd64)]: + +#include +#include + +#include "apic.h" +#include "config.h" +#include "cpu.h" +#include "panic.h" +#include "perf_cnt.h" +#include "static_init.h" + +#define WATCHDOG_TIMEOUT_S 2 + +void (*Watchdog::touch)(void) = Watchdog::do_nothing; +void (*Watchdog::enable)(void) = Watchdog::do_nothing; +void (*Watchdog::disable)(void) = Watchdog::do_nothing; + +Watchdog::Watchdog_flags Watchdog::flags; + +static void +Watchdog::do_nothing() +{} + +static void +Watchdog::perf_enable() +{ + if (flags.active && flags.user_active) + { + Perf_cnt::touch_watchdog(); + Perf_cnt::start_watchdog(); + Apic::set_perf_nmi(); + } +} + +static void +Watchdog::perf_disable() +{ + if (flags.active) + Perf_cnt::stop_watchdog(); +} + +static void +Watchdog::perf_touch() +{ + if (flags.active && flags.user_active && flags.no_user_control) + Perf_cnt::touch_watchdog(); +} + +// user enables Watchdog +PUBLIC static inline NEEDS["perf_cnt.h"] +void +Watchdog::user_enable() +{ + flags.user_active = 1; + Perf_cnt::start_watchdog(); +} + +// user disables Watchdog +PUBLIC static inline NEEDS["perf_cnt.h"] +void +Watchdog::user_disable() +{ + flags.user_active = 0; + Perf_cnt::stop_watchdog(); +} + +// user takes over control of Watchdog +PUBLIC static inline +void +Watchdog::user_takeover_control() +{ flags.no_user_control = 0; } + +// user gives back control of Watchdog +PUBLIC static inline +void +Watchdog::user_giveback_control() +{ flags.no_user_control = 0; } + +STATIC_INITIALIZE_P(Watchdog, WATCHDOG_INIT); + +PUBLIC static +void FIASCO_INIT +Watchdog::init() +{ + if (!Config::watchdog) + return; + + printf("Watchdog: LAPIC=%s, PCINT=%s, PC=%s\n", + Apic::is_present() ? "yes" : "no", + Apic::have_pcint() ? "yes" : "no", + Perf_cnt::have_watchdog() ? "yes" : "no"); + + if ( !Apic::is_present() + || !Apic::have_pcint() + || !Perf_cnt::have_watchdog()) + panic("Cannot initialize watchdog (no/bad Local APIC)"); + + // attach performance counter interrupt tom NMI + Apic::set_perf_nmi(); + + // start counter + Perf_cnt::setup_watchdog(WATCHDOG_TIMEOUT_S); + + touch = perf_touch; + enable = perf_enable; + disable = perf_disable; + + flags.active = 1; + flags.user_active = 1; + flags.no_user_control = 1; + + printf("Watchdog initialized\n"); +} diff --git a/kernel/fiasco/src/kern/ia32/x86desc.cpp b/kernel/fiasco/src/kern/ia32/x86desc.cpp new file mode 100644 index 00000000..2c2c3e87 --- /dev/null +++ b/kernel/fiasco/src/kern/ia32/x86desc.cpp @@ -0,0 +1,423 @@ + +INTERFACE: + +#include "l4_types.h" + +class X86desc +{ +public: + enum + { + Accessed = 0x01, + Access_kernel = 0x00, + Access_user = 0x60, + Access_present = 0x80, + + Access_tss = 0x09, + Access_intr_gate = 0x0e, + Access_trap_gate = 0x0f, + + Long_mode = 0x02, // XXX for code segments + }; +}; + + +class Gdt_entry : public X86desc +{ +public: + enum + { + Access_type_user = 0x10, + Access_code_read = 0x1a, + Access_data_write = 0x12, + Size_32 = 0x04, + }; + + Unsigned16 limit_low; + Unsigned16 base_low; + Unsigned8 base_med; + Unsigned8 access; + Unsigned8 limit_high; + Unsigned8 base_high; + + +} __attribute__((packed)); + + +class Idt_entry : public X86desc +{ +private: + Unsigned16 _offset_low; + Unsigned16 _selector; + Unsigned8 _ist; + Unsigned8 _access; + Unsigned16 _offset_high; +} __attribute__((packed)); + + + +class Pseudo_descriptor +{ + Unsigned16 _limit; + Mword _base; +} __attribute__((packed)); + + + +//---------------------------------------------------------------------------- +IMPLEMENTATION [ia32 | ux]: + +PUBLIC inline +Address Idt_entry::offset() const +{ return (Address)_offset_low | ((Address)_offset_high << 16); } + +PUBLIC inline +Idt_entry::Idt_entry() +{} + +// interrupt gate +PUBLIC inline +Idt_entry::Idt_entry(Address entry, Unsigned16 selector, Unsigned8 access, unsigned = 0) +{ + _offset_low = entry & 0x0000ffff; + _selector = selector; + _ist = 0; + _access = access | X86desc::Access_present; + _offset_high = (entry & 0xffff0000) >> 16; +} + +// task gate +PUBLIC inline +Idt_entry::Idt_entry(Unsigned16 selector, Unsigned8 access) +{ + _offset_low = 0; + _selector = selector; + _ist = 0; + _access = access | X86desc::Access_present; + _offset_high = 0; +} + +PUBLIC static inline +Idt_entry +Idt_entry::free(Unsigned16 val) +{ + Idt_entry e; + e._access = 0; + e._offset_low = val; + return e; +} + +PUBLIC inline +Unsigned16 +Idt_entry::get_free_val() const +{ return _offset_low; } + +PUBLIC inline +Address +Gdt_entry::base() const +{ + return (Address)base_low | ((Address)base_med << 16) + | ((Address)base_high << 24); +} + +//---------------------------------------------------------------------------- +INTERFACE [amd64]: +EXTENSION +class Idt_entry +{ +private: + Unsigned32 _offset_high1; + Unsigned32 _ignored; +}; + + +//----------------------------------------------------------------------------- +IMPLEMENTATION [amd64]: + +#include + +PUBLIC inline +Address Idt_entry::offset() const +{ + return (Address)_offset_low | ((Address)_offset_high << 16) + | ((Address)_offset_high1 << 32); +} + +// interrupt gate +PUBLIC inline +Idt_entry::Idt_entry(Address entry, Unsigned16 selector, Unsigned8 access, Unsigned8 ist_entry = 0) +{ + _offset_low = entry & 0x000000000000ffffLL; + _selector = selector; + _ist = ist_entry; + _access = access | Access_present; + _offset_high = (entry & 0x00000000ffff0000LL) >> 16; + _offset_high1 = (entry & 0xffffffff00000000LL) >> 32; + _ignored = 0; +} + + +PUBLIC inline +Address +Gdt_entry::base() const +{ + Address b = (Address)base_low | ((Address)base_med << 16) + | ((Address)base_high << 24); + if (access & 0x10) + return b; + + return b | ((Unsigned64 const *)this)[1] << 32; +} + +// task gate +PUBLIC +Idt_entry::Idt_entry(Unsigned16, Unsigned8) +{ panic("AMD64 does not support task gates"); } + + +IMPLEMENTATION[debug]: + +#include + + +PUBLIC +const char* +X86desc::type_str() const +{ + static char const * const desc_type[32] = + { + "reserved", "16-bit tss (avail)", + "ldt", "16-bit tss (busy)", + "16-bit call gate", "task gate", + "16-bit int gate", "16-bit trap gate", + "reserved", "32-bit tss (avail)", + "reserved", "32-bit tss (busy)", + "32-bit call gate", "reserved", + "32-bit int gate", "32-bit trap gate", + "data r/o", "data r/o acc", + "data r/w", "data r/w acc", + "data r/o exp-dn", "data r/o exp-dn", + "data r/w exp-dn", "data r/w exp-dn acc", + "code x/o", "code x/o acc", + "code x/r", "code x/r acc", + "code x/r conf", "code x/o conf acc", + "code x/r conf", "code x/r conf acc" + }; + + Unsigned8 const *t = (Unsigned8 const *)this; + + return desc_type[t[5] & 0x1f]; +} + +PUBLIC +void +Gdt_entry::show() const +{ + static char const modes[] = { 16, 64, 32, -1 }; + // segment descriptor + Address b = base(); + printf("%016lx-%016lx dpl=%d %dbit %s %02X (\033[33;1m%s\033[m)\n", + b, b + size(), (access & 0x60) >> 5, + modes[mode()], + access & 0x10 ? "code/data" : "system ", + access & 0x1f, type_str()); +} + +PUBLIC inline +unsigned +Idt_entry::selector() const +{ return _selector; } + +PUBLIC +void +Idt_entry::show() const +{ + if (type() == 0x5) + { + // Task gate + + printf("-------- sel=%04x dpl=%d %02X (\033[33;1m%s\033[m)\n", + selector(), dpl(), type(), type_str()); + } + else + { + Address o = offset(); + + printf("%016lx sel=%04x dpl=%d %02X (\033[33;1m%s\033[m)\n", + o, selector(), dpl(), type(), type_str()); + } +} + + +PUBLIC +void +X86desc::show() const +{ + if (present()) + { + if ((access() & 0x16) == 0x06) + static_cast(this)->show(); + else + static_cast(this)->show(); + } + else + { + printf("-------- dpl=%d %02X (\033[33;1m%s\033[m)\n", + dpl(), type(), type_str()); + } +} + +IMPLEMENTATION: + +#include + +PUBLIC inline +X86desc::X86desc() +{} + +PUBLIC inline +unsigned X86desc::access() const +{ return ((Unsigned8 const *)this)[5]; } + +PUBLIC inline NEEDS[X86desc::access] +int +X86desc::present() const +{ + return (access() & 0x80) >> 7; +} + +PUBLIC inline NEEDS[X86desc::access] +Unsigned8 +X86desc::type() const +{ + return access() & 0x1f; +} + +PUBLIC inline NEEDS[X86desc::access] +Unsigned8 +X86desc::dpl() const +{ + return (access() & 0x60) >> 5; +} + +PUBLIC inline NEEDS[X86desc::present, X86desc::dpl] +bool +X86desc::unsafe() const +{ return present() && (dpl() != 3); } + +PUBLIC inline +Pseudo_descriptor::Pseudo_descriptor() +{} + +PUBLIC inline +Pseudo_descriptor::Pseudo_descriptor(Address base, Unsigned16 limit) + : _limit(limit), _base(base) +{} + +PUBLIC inline +Address +Pseudo_descriptor::base() const +{ + return _base; +} + +PUBLIC inline +unsigned +Idt_entry::ist() const +{ return _ist; } + +PUBLIC inline +Unsigned16 +Pseudo_descriptor::limit() const +{ return _limit; } + +PUBLIC inline NEEDS [] +void +Idt_entry::clear() +{ memset(this, 0, sizeof(*this)); } + +PUBLIC inline +Gdt_entry::Gdt_entry(Address base, Unsigned32 limit, + Unsigned8 _access, Unsigned8 szbits) +{ + limit_low = limit & 0x0000ffff; + base_low = base & 0x0000ffff; + base_med = (base & 0x00ff0000) >> 16; + access = _access | Access_present; + limit_high = ((limit & 0x000f0000) >> 16) | + (((Unsigned16)szbits) << 4); + base_high = (base & 0xff000000) >> 24; +} + +PUBLIC inline +Gdt_entry::Gdt_entry() +{} + + +PUBLIC inline +Mword +Gdt_entry::limit() const +{ return (Mword)limit_low | (((Mword)limit_high & 0x0f) << 16); } + +PUBLIC inline NEEDS[Gdt_entry::granularity, Gdt_entry::limit] +Mword +Gdt_entry::size() const +{ + Mword l = limit(); + return granularity() ? ((l+1) << 12)-1 : l; +} + +PUBLIC inline +bool +Gdt_entry::avl() const +{ + return (limit_high & 0x10); +} + +PUBLIC inline +bool +Gdt_entry::seg64() const +{ + return (limit_high & 0x20); +} + +PUBLIC inline +bool +Gdt_entry::seg32() const +{ + return (limit_high & 0x40); +} + +PUBLIC inline +unsigned +Gdt_entry::mode() const +{ return (limit_high >> 5) & 3; } + +PUBLIC inline +bool +Gdt_entry::granularity() const +{ + return (limit_high & 0x80); +} + +PUBLIC inline +bool +Gdt_entry::writable() const +{ + return (type() & 0x02); +} + +PUBLIC inline +int +Gdt_entry::contents() const +{ + return (type() & 0x0c) >> 2; +} + +PUBLIC inline +void +Gdt_entry::clear() +{ + *(Unsigned64*)this = 0; +} + diff --git a/kernel/fiasco/src/kern/icu_helper.cpp b/kernel/fiasco/src/kern/icu_helper.cpp new file mode 100644 index 00000000..fdc15f15 --- /dev/null +++ b/kernel/fiasco/src/kern/icu_helper.cpp @@ -0,0 +1,203 @@ +INTERFACE: + +#include "irq.h" +#include "kobject_helper.h" +#include "l4_buf_iter.h" + +class Icu_h_base +{ +public: + enum Op + { + Op_bind = 0, + Op_unbind = 1, + Op_info = 2, + Op_msi_info = 3, + Op_eoi = Irq::Op_eoi_2, // 4 + Op_unmask = Op_eoi, + Op_mask = 5, + Op_set_mode = 6, + }; + + enum Feature + { + Msi_bit = 0x80000000 + }; +}; + + +template< typename REAL_ICU > +class Icu_h : public Kobject_h, public Icu_h_base +{ +protected: + REAL_ICU const *this_icu() const + { return nonull_static_cast(this); } + + REAL_ICU *this_icu() + { return nonull_static_cast(this); } +}; + + +IMPLEMENTATION: + + +PROTECTED +Irq * +Icu_h_base::deref_irq(L4_msg_tag *tag, Utcb const *utcb) +{ + L4_snd_item_iter snd_items(utcb, tag->words()); + Irq *irq; + + if (!tag->items() || !snd_items.next()) + { + *tag = Kobject_iface::commit_result(-L4_err::EInval); + return 0; + } + + L4_fpage bind_irq(snd_items.get()->d); + if (EXPECT_FALSE(!bind_irq.is_objpage())) + { + *tag = Kobject_iface::commit_error(utcb, L4_error::Overflow); + return 0; + } + + register Context *const c_thread = ::current(); + register Space *const c_space = c_thread->space(); + unsigned char irq_rights = 0; + irq = Kobject::dcast(c_space->lookup_local(bind_irq.obj_index(), &irq_rights)); + + if (!irq) + { + *tag = Kobject_iface::commit_result(-L4_err::EInval); + return 0; + } + + if (EXPECT_FALSE(!(irq_rights & L4_fpage::X))) + { + *tag = Kobject_iface::commit_result(-L4_err::EPerm); + return 0; + } + + return irq; +} + + +PUBLIC inline +template +void +Icu_h::icu_mask_irq(bool mask, unsigned irqnum) +{ + Irq_base *i = this_icu()->icu_get_irq(irqnum); + + if (EXPECT_FALSE(!i)) + return; + + if (mask) + i->mask(); + else + i->unmask(); +} + +PUBLIC inline +template +L4_msg_tag +Icu_h::icu_unbind_irq(unsigned irqnum) +{ + Irq_base *irq = this_icu()->icu_get_irq(irqnum); + + if (irq) + irq->unbind(); + + return Kobject_iface::commit_result(0); +} + +PUBLIC inline +template +L4_msg_tag +Icu_h::icu_get_msi_info(Mword msi, Utcb *out) +{ + (void) msi; + (void) out; + return Kobject_iface::commit_result(-L4_err::EInval); +} + +PUBLIC template< typename REAL_ICU > +inline +L4_msg_tag +Icu_h::icu_invoke(L4_obj_ref, Mword /*rights*/, + Syscall_frame *f, + Utcb const *utcb, Utcb *out) +{ + L4_msg_tag tag = f->tag(); + + switch (utcb->values[0]) + { + case Op_bind: + if (tag.words() < 2) + return Kobject_iface::commit_result(-L4_err::EInval); + + if (Irq *irq = deref_irq(&tag, utcb)) + return this_icu()->icu_bind_irq(irq, utcb->values[1]); + else + return tag; + + case Op_unbind: + if (tag.words() < 2) + return Kobject_iface::commit_result(-L4_err::EInval); + + if (deref_irq(&tag, utcb)) + return this_icu()->icu_unbind_irq(utcb->values[1]); + else + return tag; + + case Op_info: + this_icu()->icu_get_info(&out->values[0], &out->values[1], &out->values[2]); + return Kobject_iface::commit_result(0, 3); + + case Op_msi_info: + if (tag.words() < 2) + return Kobject_iface::commit_result(-L4_err::EInval); + return this_icu()->icu_get_msi_info(utcb->values[1], out); + + case Op_unmask: + case Op_mask: + if (tag.words() < 2) + return Kobject_h::no_reply(); + + this_icu()->icu_mask_irq(utcb->values[0] == Op_mask, utcb->values[1]); + return Kobject_h::no_reply(); + + case Op_set_mode: + if (tag.words() >= 3) + { + Irq_base *irq = this_icu()->icu_get_irq(utcb->values[1]); + + if (irq) + { + irq->set_mode(utcb->values[2]); + return Kobject_iface::commit_result(0); + } + } + + return Kobject_iface::commit_result(-L4_err::EInval); + + default: + return Kobject_iface::commit_result(-L4_err::ENosys); + } +} + +PUBLIC +template< typename REAL_ICU > +L4_msg_tag +Icu_h::kinvoke(L4_obj_ref ref, Mword rights, + Syscall_frame *f, + Utcb const *in, Utcb *out) +{ + L4_msg_tag tag = f->tag(); + + if (EXPECT_FALSE(tag.proto() != L4_msg_tag::Label_irq)) + return Kobject_iface::commit_result(-L4_err::EBadproto); + + return icu_invoke(ref, rights, f, in, out); +} + diff --git a/kernel/fiasco/src/kern/initcalls.h b/kernel/fiasco/src/kern/initcalls.h new file mode 100644 index 00000000..55a45d77 --- /dev/null +++ b/kernel/fiasco/src/kern/initcalls.h @@ -0,0 +1,17 @@ +#ifndef INITCALLS_H__ +#define INITCALLS_H__ + +#include "globalconfig.h" + +#define FIASCO_INIT __attribute__ ((__section__ (".initcall.text"))) +#define FIASCO_INITDATA __attribute__ ((__section__ (".initcall.data"))) + +#ifdef CONFIG_MP +# define FIASCO_INIT_CPU +# define FIASCO_INITDATA_CPU +#else +# define FIASCO_INIT_CPU FIASCO_INIT +# define FIASCO_INITDATA_CPU FIASCO_INITDATA +#endif + +#endif // INITCALLS_H__ diff --git a/kernel/fiasco/src/kern/io_space.cpp b/kernel/fiasco/src/kern/io_space.cpp new file mode 100644 index 00000000..b46ef356 --- /dev/null +++ b/kernel/fiasco/src/kern/io_space.cpp @@ -0,0 +1,472 @@ +INTERFACE [io]: + +#include "types.h" +#include "mem_space.h" + +class Mem_space; +class Space; + +/** Wrapper class for io_{map,unmap}. This class serves as an adapter + for map to Mem_space. + */ +template< typename SPACE > +class Generic_io_space +{ + friend class Jdb_iomap; + +public: + static char const * const name; + + typedef Page_number Addr; + typedef Page_count Size; + typedef Page_number Phys_addr; + typedef void Reap_list; + + enum + { + Need_insert_tlb_flush = 0, + Need_xcpu_tlb_flush = 0, + Map_page_size = 1, + Page_shift = 0, + Map_superpage_shift = 16, + Map_superpage_size = 0x10000, + Map_max_address = 0x10000, + Whole_space = 16, + Identity_map = 1, + }; + + // We'd rather like to use a "using Mem_space::Status" declaration here, + // but that wouldn't make the enum values accessible as + // Generic_io_space::Insert_ok and so on. + enum Status + { + Insert_ok = 0, ///< Mapping was added successfully. + Insert_warn_exists, ///< Mapping already existed + Insert_warn_attrib_upgrade, ///< Mapping already existed, attribs upgrade + Insert_err_nomem, ///< Couldn't alloc new page table + Insert_err_exists ///< A mapping already exists at the target addr + }; + + enum Page_attribs + { + Page_writable = Mem_space::Page_writable, + Page_user_accessible = Mem_space::Page_user_accessible, + Page_references = 0, + Page_all_attribs = Page_writable | Page_user_accessible + }; + + static Addr map_max_address() + { return Addr(Map_max_address); } + + static Address superpage_size() + { return Map_superpage_size; } + + static bool has_superpages() + { return true; } + + static Phys_addr page_address(Phys_addr o, Size s) + { return o.trunc(s); } + + static Phys_addr subpage_address(Phys_addr addr, Size offset) + { return addr | offset; } + +private: + // DATA + Mword _io_counter; + + Mem_space const *mem_space() const + { return static_cast(this); } + + Mem_space *mem_space() + { return static_cast(this); } +}; + +template< typename SPACE> +char const * const Generic_io_space::name = "Io_space"; + + +//---------------------------------------------------------------------------- +IMPLEMENTATION [io]: + +#include +#include + +#include "atomic.h" +#include "config.h" +#include "l4_types.h" +#include "kmem_alloc.h" +#include "panic.h" +#include "paging.h" + + +PUBLIC template< typename SPACE > +static inline +Mword +Generic_io_space::xlate_flush(unsigned char rights) +{ + if (rights) + return Page_all_attribs; + else + return 0; +} + +PUBLIC template< typename SPACE > +static inline +Mword +Generic_io_space::is_full_flush(unsigned char rights) +{ + return rights; +} + +PUBLIC template< typename SPACE > +static inline +Mword +Generic_io_space::xlate_flush_result(Mword /*attribs*/) +{ return 0; } + +PUBLIC template< typename SPACE > +inline +Generic_io_space::Generic_io_space() + : _io_counter(0) +{} + + +PUBLIC template< typename SPACE > +Generic_io_space::~Generic_io_space() +{ + if (!mem_space()->dir()) + return; + + Pdir::Iter iopte = mem_space()->dir()->walk(Virt_addr(Mem_layout::Io_bitmap)); + + // do we have an IO bitmap? + if (iopte.e->valid()) + { + // sanity check + assert (iopte.shift() != Config::SUPERPAGE_SHIFT); + + Kmem_alloc::allocator() + ->q_free_phys(ram_quota(), Config::PAGE_SHIFT, + iopte.e[0].addr()); + + if (iopte.e[1].valid()) + Kmem_alloc::allocator() + ->q_free_phys(ram_quota(), Config::PAGE_SHIFT, + iopte.e[1].addr()); + + Pdir::Iter iopde = mem_space()->dir()->walk(Virt_addr(Mem_layout::Io_bitmap), 0); + + // free the page table + Kmem_alloc::allocator() + ->q_free_phys(ram_quota(), Config::PAGE_SHIFT, + iopde.e->addr()); + + // free reference + *iopde.e = 0; + } +} + +PUBLIC template< typename SPACE > +inline +Ram_quota * +Generic_io_space::ram_quota() const +{ return static_cast(this)->ram_quota(); } + +PRIVATE template< typename SPACE > +inline +bool +Generic_io_space::is_superpage() +{ return _io_counter & 0x10000000; } + + +// +// Utilities for map and unmap +// + +PUBLIC template< typename SPACE > +virtual +bool +Generic_io_space::v_fabricate(Addr address, Phys_addr *phys, + Size *size, unsigned *attribs = 0) +{ + return Generic_io_space::v_lookup(address.trunc(Size(Map_page_size)), + phys, size, attribs); + +} + +PUBLIC template< typename SPACE > +inline NEEDS[Generic_io_space::is_superpage] +bool +Generic_io_space::v_lookup(Addr virt, Phys_addr *phys = 0, + Size *size = 0, unsigned *attribs = 0) +{ + if (is_superpage()) + { + if (size) *size = Size(Map_superpage_size); + if (phys) *phys = Phys_addr(0); + if (attribs) *attribs = Page_writable | Page_user_accessible; + return true; + } + + if (size) *size = Size(1); + + if (io_lookup(virt.value())) + { + if (phys) *phys = virt; + if (attribs) *attribs = Page_writable | Page_user_accessible; + return true; + } + + if (get_io_counter() == 0) + { + if (size) *size = Size(Map_superpage_size); + if (phys) *phys = Phys_addr(0); + } + + return false; +} + +PUBLIC template< typename SPACE > +inline NEEDS [Generic_io_space::is_superpage] +unsigned long +Generic_io_space::v_delete(Addr virt, Size size, + unsigned long page_attribs = Page_all_attribs) +{ + (void)size; + (void)page_attribs; + assert (page_attribs == Page_all_attribs); + + if (is_superpage()) + { + assert (size.value() == Map_superpage_size); + + for (unsigned p = 0; p < Map_max_address; ++p) + io_delete(p); + + _io_counter = 0; + return Page_writable | Page_user_accessible; + } + + assert (size.value() == 1); + + return io_delete(virt.value()); +} + +PUBLIC template< typename SPACE > +inline +typename Generic_io_space::Status +Generic_io_space::v_insert(Phys_addr phys, Addr virt, Size size, + unsigned page_attribs) +{ + (void)phys; + (void)size; + (void)page_attribs; + + assert (phys == virt); + if (is_superpage() && size.value() == Map_superpage_size) + return Insert_warn_exists; + + if (get_io_counter() == 0 && size.value() == Map_superpage_size) + { + for (unsigned p = 0; p < Map_max_address; ++p) + io_insert(p); + _io_counter |= 0x10000000; + + return Insert_ok; + } + + assert (size.value() == 1); + + return typename Generic_io_space::Status(io_insert(virt.value())); +} + + +PUBLIC template< typename SPACE > +inline static +void +Generic_io_space::tlb_flush() +{} + +PUBLIC template< typename SPACE > +inline static +bool +Generic_io_space::need_tlb_flush() +{ return false; } + +// +// IO lookup / insert / delete / counting +// + +/** return the IO counter. + * @return number of IO ports mapped / 0 if not mapped + */ +PUBLIC template< typename SPACE > +inline NEEDS["paging.h"] +Mword +Generic_io_space::get_io_counter() const +{ + return _io_counter & ~0x10000000; +} + + +/** Add something the the IO counter. + @param incr number to add + @pre 2nd level page table for IO bitmap is present +*/ +template< typename SPACE > +inline NEEDS["paging.h"] +void +Generic_io_space::addto_io_counter(int incr) +{ + atomic_add (&_io_counter, incr); +} + + +/** Lookup one IO port in the IO space. + @param port_number port address to lookup; + @return true if mapped + false if not + */ +PROTECTED template< typename SPACE > +bool +Generic_io_space::io_lookup(Address port_number) +{ + assert(port_number < Mem_layout::Io_port_max); + + // be careful, do not cause page faults here + // there might be nothing mapped in the IO bitmap + + Address port_addr = get_phys_port_addr(port_number); + + if(port_addr == ~0UL) + return false; // no bitmap -> no ports + + // so there is memory mapped in the IO bitmap + char * port = static_cast(Kmem::phys_to_virt(port_addr)); + + // bit == 1 disables the port + // bit == 0 enables the port + return !(*port & get_port_bit(port_number)); +} + + +/** Enable one IO port in the IO space. + This function is called in the context of the IPC sender! + @param port_number address of the port + @return Insert_warn_exists if some ports were mapped in that IO page + Insert_err_nomem if memory allocation failed + Insert_ok if otherwise insertion succeeded + */ +PROTECTED template< typename SPACE > +typename Generic_io_space::Status +Generic_io_space::io_insert(Address port_number) +{ + assert(port_number < Mem_layout::Io_port_max); + + Address port_virt = Mem_layout::Io_bitmap + (port_number >> 3); + Address port_phys = mem_space()->virt_to_phys(port_virt); + + if (port_phys == ~0UL) + { + // nothing mapped! Get a page and map it in the IO bitmap + void *page; + if (!(page=Kmem_alloc::allocator()->q_alloc(ram_quota(), + Config::PAGE_SHIFT))) + return Insert_err_nomem; + + // clear all IO ports + // bit == 1 disables the port + // bit == 0 enables the port + memset(page, 0xff, Config::PAGE_SIZE); + + Mem_space::Status status = + mem_space()->v_insert( + Mem_space::Phys_addr(Mem_layout::pmem_to_phys(page)), + Mem_space::Addr(port_virt & Config::PAGE_MASK), + Mem_space::Size(Config::PAGE_SIZE), Page_writable); + + if (status == Mem_space::Insert_err_nomem) + { + Kmem_alloc::allocator()->free(Config::PAGE_SHIFT,page); + ram_quota()->free(Config::PAGE_SIZE); + return Insert_err_nomem; + } + + // we've been careful, so insertion should have succeeded + assert(status == Mem_space::Insert_ok); + + port_phys = mem_space()->virt_to_phys(port_virt); + assert(port_phys != ~0UL); + } + + // so there is memory mapped in the IO bitmap -- write the bits now + Unsigned8 *port = static_cast (Kmem::phys_to_virt(port_phys)); + + if (*port & get_port_bit(port_number)) // port disabled? + { + *port &= ~ get_port_bit(port_number); + addto_io_counter(1); + return Insert_ok; + } + + // already enabled + return Insert_warn_exists; +} + + +/** Disable one IO port in the IO space. + @param port_number port to disable + */ +PROTECTED template< typename SPACE > +unsigned +Generic_io_space::io_delete(Address port_number) +{ + assert(port_number < Mem_layout::Io_port_max); + + // be careful, do not cause page faults here + // there might be nothing mapped in the IO bitmap + + Address port_addr = get_phys_port_addr(port_number); + + if (port_addr == ~0UL) + // nothing mapped -> nothing to delete + return 0; + + // so there is memory mapped in the IO bitmap -> disable the ports + char * port = static_cast (Kmem::phys_to_virt(port_addr)); + + // bit == 1 disables the port + // bit == 0 enables the port + if(!(*port & get_port_bit(port_number))) // port enabled ?? + { + *port |= get_port_bit(port_number); + addto_io_counter(-1); + + return Page_writable | Page_user_accessible; + } + + return 0; +} + +template< typename SPACE > +INLINE NEEDS["config.h"] +Address +Generic_io_space::get_phys_port_addr(Address const port_number) const +{ + return mem_space()->virt_to_phys(Mem_layout::Io_bitmap + (port_number >> 3)); +} + +template< typename SPACE > +INLINE +Unsigned8 +Generic_io_space::get_port_bit(Address const port_number) const +{ + return 1 << (port_number & 7); +} + + +PUBLIC template< typename SPACE > +inline static +Page_number +Generic_io_space::canonize(Page_number v) +{ return v; } diff --git a/kernel/fiasco/src/kern/ipc_gate.cpp b/kernel/fiasco/src/kern/ipc_gate.cpp new file mode 100644 index 00000000..a53b7da1 --- /dev/null +++ b/kernel/fiasco/src/kern/ipc_gate.cpp @@ -0,0 +1,383 @@ +INTERFACE: + +#include "kobject.h" +#include "kobject_helper.h" +#include "ref_ptr.h" +#include "slab_cache.h" +#include "thread_object.h" + +class Ram_quota; + +class Ipc_gate_obj; + +class Ipc_gate_ctl : public Kobject_h +{ +private: + enum Operation + { + Op_bind = 0x10, + Op_get_info = 0x11, + }; +}; + +class Ipc_gate : public Kobject +{ + friend class Ipc_gate_ctl; + friend class Jdb_sender_list; +protected: + + Ref_ptr _thread; + Mword _id; + Ram_quota *_quota; + Locked_prio_list _wait_q; +}; + +class Ipc_gate_obj : public Ipc_gate, public Ipc_gate_ctl +{ + FIASCO_DECLARE_KOBJ(); + +private: + friend class Ipc_gate; + typedef Slab_cache Self_alloc; + +public: + bool put() { return Ipc_gate::put(); } + + Thread *thread() const { return _thread.ptr(); } + Mword id() const { return _id; } + Mword obj_id() const { return _id; } + bool is_local(Space *s) const { return _thread && _thread->space() == s; } +}; + +//--------------------------------------------------------------------------- +INTERFACE [debug]: + +EXTENSION class Ipc_gate +{ +protected: + struct Log_ipc_gate_invoke + { + Mword gate_dbg_id; + Mword thread_dbg_id; + Mword label; + }; + + static unsigned log_fmt(Tb_entry *, int max, char *buf) asm ("__fmt_ipc_gate_invoke"); +}; + +//--------------------------------------------------------------------------- +IMPLEMENTATION: + +#include + +#include "assert_opt.h" +#include "entry_frame.h" +#include "ipc_timeout.h" +#include "kmem_slab.h" +#include "logdefs.h" +#include "ram_quota.h" +#include "static_init.h" +#include "thread.h" +#include "thread_state.h" +#include "timer.h" + +FIASCO_DEFINE_KOBJ(Ipc_gate_obj); + +PUBLIC +::Kobject_mappable * +Ipc_gate_obj::map_root() +{ return Ipc_gate::map_root(); } + +PUBLIC +Kobject_iface * +Ipc_gate_obj::downgrade(unsigned long attr) +{ + if (attr & L4_msg_item::C_obj_right_1) + return static_cast(this); + else + return static_cast(this); +} + +PUBLIC inline +Ipc_gate::Ipc_gate(Ram_quota *q, Thread *t, Mword id) + : _thread(t), _id(id), _quota(q), _wait_q() +{} + +PUBLIC inline +Ipc_gate_obj::Ipc_gate_obj(Ram_quota *q, Thread *t, Mword id) + : Ipc_gate(q, t, id) +{} + +PUBLIC +void +Ipc_gate_obj::unblock_all() +{ + while (::Prio_list_elem *h = _wait_q.first()) + { + Lock_guard g1(&cpu_lock); + Thread *w; + { + Lock_guard g2(_wait_q.lock()); + if (EXPECT_FALSE(h != _wait_q.first())) + continue; + + w = static_cast(Sender::cast(h)); + w->sender_dequeue(&_wait_q); + } + w->activate(); + } +} + +PUBLIC virtual +void +Ipc_gate_obj::initiate_deletion(Kobject ***r) +{ + if (_thread) + _thread->ipc_gate_deleted(_id); + + Kobject::initiate_deletion(r); +} + +PUBLIC virtual +void +Ipc_gate_obj::destroy(Kobject ***r) +{ + Kobject::destroy(r); + _thread = 0; + unblock_all(); +} + +PUBLIC +Ipc_gate_obj::~Ipc_gate_obj() +{ + unblock_all(); +} + +PUBLIC inline NEEDS[] +void * +Ipc_gate_obj::operator new (size_t, void *b) throw() +{ return b; } + +static Kmem_slab_t _ipc_gate_allocator("Ipc_gate"); + +PRIVATE static +Ipc_gate_obj::Self_alloc * +Ipc_gate_obj::allocator() +{ return &_ipc_gate_allocator; } + +PUBLIC static +Ipc_gate_obj * +Ipc_gate::create(Ram_quota *q, Thread *t, Mword id) +{ + Auto_quota quota(q, sizeof(Ipc_gate_obj)); + + if (EXPECT_FALSE(!quota)) + return 0; + + void *nq = Ipc_gate_obj::allocator()->alloc(); + if (EXPECT_FALSE(!nq)) + return 0; + + quota.release(); + return new (nq) Ipc_gate_obj(q, t, id); +} + +PUBLIC +void Ipc_gate_obj::operator delete (void *_f) +{ + register Ipc_gate_obj *f = (Ipc_gate_obj*)_f; + Ram_quota *p = f->_quota; + + allocator()->free(f); + if (p) + p->free(sizeof(Ipc_gate_obj)); +} + +PRIVATE inline NOEXPORT NEEDS["assert_opt.h"] +L4_msg_tag +Ipc_gate_ctl::bind_thread(L4_obj_ref, Mword, Syscall_frame *f, Utcb const *in, Utcb *) +{ + L4_msg_tag tag = f->tag(); + L4_snd_item_iter snd_items(in, tag.words()); + + if (tag.words() < 2 || !tag.items() || !snd_items.next()) + return commit_result(-L4_err::EInval); + + L4_fpage bind_thread(snd_items.get()->d); + if (EXPECT_FALSE(!bind_thread.is_objpage())) + return commit_error(in, L4_error::Overflow); + + register Context *const c_thread = ::current(); + assert_opt(c_thread); + register Space *const c_space = c_thread->space(); + assert_opt (c_space); + unsigned char t_rights = 0; + Thread *t = Kobject::dcast(c_space->lookup_local(bind_thread.obj_index(), &t_rights)); + + if (!(t_rights & L4_fpage::CS)) + return commit_result(-L4_err::EPerm); + + + Ipc_gate_obj *g = static_cast(this); + g->_id = in->values[1]; + Mem::mp_wmb(); + g->_thread = t; + Mem::mp_wmb(); + g->unblock_all(); + c_thread->rcu_wait(); + g->unblock_all(); + + return commit_result(0); +} + +PRIVATE inline NOEXPORT +L4_msg_tag +Ipc_gate_ctl::get_infos(L4_obj_ref, Mword, Syscall_frame *, Utcb const *, Utcb *out) +{ + Ipc_gate_obj *g = static_cast(this); + out->values[0] = g->_id; + return commit_result(0, 1); +} + +PUBLIC +void +Ipc_gate_ctl::invoke(L4_obj_ref self, Mword rights, Syscall_frame *f, Utcb *utcb) +{ + if (f->tag().proto() == L4_msg_tag::Label_kobject) + Kobject_h::invoke(self, rights, f, utcb); + else + static_cast(this)->Ipc_gate::invoke(self, rights, f, utcb); +} + + +PUBLIC +L4_msg_tag +Ipc_gate_ctl::kinvoke(L4_obj_ref self, Mword rights, Syscall_frame *f, Utcb const *in, Utcb *out) +{ + L4_msg_tag tag = f->tag(); + + if (EXPECT_FALSE(tag.proto() != L4_msg_tag::Label_kobject)) + return commit_result(-L4_err::EBadproto); + + if (EXPECT_FALSE(tag.words() < 1)) + return commit_result(-L4_err::EInval); + + switch (in->values[0]) + { + case Op_bind: + return bind_thread(self, rights, f, in, out); + case Op_get_info: + return get_infos(self, rights, f, in, out); + default: + return static_cast(this)->kobject_invoke(self, rights, f, in, out); + } +} + +PRIVATE inline NOEXPORT +L4_error +Ipc_gate::block(Thread *ct, L4_timeout const &to, Utcb *u) +{ + Unsigned64 t = 0; + if (!to.is_never()) + { + t = to.microsecs(Timer::system_clock(), u); + if (!t) + return L4_error::Timeout; + } + + { + Lock_guard g(_wait_q.lock()); + ct->set_wait_queue(&_wait_q); + ct->sender_enqueue(&_wait_q, ct->sched_context()->prio()); + } + ct->state_change_dirty(~Thread_ready, Thread_send_wait); + + IPC_timeout timeout; + if (t) + { + timeout.set(t, ct->cpu()); + ct->set_timeout(&timeout); + } + + ct->schedule(); + + ct->state_change(~Thread_ipc_mask, Thread_ready); + ct->reset_timeout(); + + if (EXPECT_FALSE(ct->in_sender_list() && timeout.has_hit())) + { + Lock_guard g(_wait_q.lock()); + if (!ct->in_sender_list()) + return L4_error::None; + + ct->sender_dequeue(&_wait_q); + return L4_error::Timeout; + } + return L4_error::None; +} + + +PUBLIC +void +Ipc_gate::invoke(L4_obj_ref /*self*/, Mword rights, Syscall_frame *f, Utcb *utcb) +{ + Syscall_frame *ipc_f = f; + //LOG_MSG_3VAL(current(), "gIPC", Mword(_thread), _id, f->obj_2_flags()); + //printf("Invoke: Ipc_gate(%lx->%p)...\n", _id, _thread); + Thread *ct = current_thread(); + Thread *sender = 0; + Thread *partner = 0; + bool have_rcv = false; + + if (EXPECT_FALSE(!_thread.ptr())) + { + L4_error e = block(ct, f->timeout().snd, utcb); + if (!e.ok()) + { + f->tag(commit_error(utcb, e)); + return; + } + + if (EXPECT_FALSE(!_thread.ptr())) + { + f->tag(commit_error(utcb, L4_error::Not_existent)); + return; + } + } + + bool ipc = _thread->check_sys_ipc(f->ref().op(), &partner, &sender, &have_rcv); + + LOG_TRACE("IPC Gate invoke", "gate", current(), __fmt_ipc_gate_invoke, + Log_ipc_gate_invoke *l = tbe->payload(); + l->gate_dbg_id = dbg_id(); + l->thread_dbg_id = _thread->dbg_id(); + l->label = _id | rights; + ); + + if (EXPECT_FALSE(!ipc)) + f->tag(commit_error(utcb, L4_error::Not_existent)); + else + { + ipc_f->from(_id | rights); + ct->do_ipc(f->tag(), partner, partner, have_rcv, sender, + f->timeout(), f, rights); + } +} + +//--------------------------------------------------------------------------- +IMPLEMENTATION [debug]: + +PUBLIC +::Kobject_dbg * +Ipc_gate_obj::dbg_info() const +{ return Ipc_gate::dbg_info(); } + +IMPLEMENT +unsigned +Ipc_gate::log_fmt(Tb_entry *e, int max, char *buf) +{ + Log_ipc_gate_invoke *l = e->payload(); + return snprintf(buf, max, "D-gate=%lx D-thread=%lx L=%lx", + l->gate_dbg_id, l->thread_dbg_id, l->label); +} + diff --git a/kernel/fiasco/src/kern/ipc_sender.cpp b/kernel/fiasco/src/kern/ipc_sender.cpp new file mode 100644 index 00000000..646f0808 --- /dev/null +++ b/kernel/fiasco/src/kern/ipc_sender.cpp @@ -0,0 +1,177 @@ +INTERFACE: + +#include "sender.h" +#include "receiver.h" + +class Ipc_sender_base : public Sender +{ +public: + virtual ~Ipc_sender_base() = 0; +}; + +template< typename Derived > +class Ipc_sender : public Ipc_sender_base +{ +private: + Derived *derived() { return static_cast(this); } + static bool dequeue_sender() { return true; } + static bool requeue_sender() { return false; } + +public: + virtual ~Ipc_sender() = 0; +}; + +extern "C" void fast_ret_from_irq(void); + +IMPLEMENTATION: + +#include "config.h" +#include "entry_frame.h" +#include "globals.h" +#include "kdb_ke.h" +#include "thread_state.h" +#include + +IMPLEMENT inline Ipc_sender_base::~Ipc_sender_base() {} +IMPLEMENT inline template Ipc_sender::~Ipc_sender() {} + +PUBLIC +virtual void +Ipc_sender_base::ipc_receiver_aborted() +{ + assert (wait_queue()); + set_wait_queue(0); +} + +/** Sender-activation function called when receiver gets ready. + Irq::hit() actually ensures that this method is always called + when an interrupt occurs, even when the receiver was already + waiting. + */ +PUBLIC template< typename Derived > +virtual void +Ipc_sender::ipc_send_msg(Receiver *recv) +{ + derived()->transfer_msg(recv); + if (derived()->dequeue_sender()) + { + sender_dequeue(recv->sender_list()); + recv->vcpu_update_state(); + } +} + +PROTECTED inline NEEDS["config.h", "globals.h", "thread_state.h"] +bool +Ipc_sender_base::handle_shortcut(Syscall_frame *dst_regs, + Receiver *receiver) +{ + if (EXPECT_TRUE + ((current() != receiver + && receiver->sched()->deblock(current_cpu(), current()->sched(), true) + // avoid race in do_ipc() after Thread_send_in_progress + // flag was deleted from receiver's thread state + // also: no shortcut for alien threads, they need to see the + // after-syscall exception + && !(receiver->state() + & (Thread_ready_mask | Thread_alien)) + && !current()->schedule_in_progress()))) // no schedule in progress + { + // we don't need to manipulate the state in a safe way + // because we are still running with interrupts turned off + receiver->state_add_dirty(Thread_ready); + + if (!Config::Irq_shortcut) + { + // no shortcut: switch to the interrupt thread which will + // calls Irq::ipc_receiver_ready + current()->switch_to_locked(receiver); + return true; + } + + // At this point we are sure that the connected interrupt + // thread is waiting for the next interrupt and that its + // thread priority is higher than the current one. So we + // choose a short cut: Instead of doing the full ipc handshake + // we simply build up the return stack frame and go out as + // quick as possible. + // + // XXX We must own the kernel lock for this optimization! + // + + Mword *esp = reinterpret_cast(dst_regs); + + // set return address of irq_thread + *--esp = reinterpret_cast(fast_ret_from_irq); + + // XXX set stack pointer of irq_thread + receiver->set_kernel_sp(esp); + + // directly switch to the interrupt thread context and go out + // fast using fast_ret_from_irq (implemented in assembler). + // kernel-unlock is done in switch_exec() (on switchee's side). + + // no shortcut if profiling: switch to the interrupt thread + current()->switch_to_locked (receiver); + return true; + } + return false; +} + + +PROTECTED template< typename Derived > +inline NEEDS["config.h","globals.h", "thread_state.h", + Ipc_sender_base::handle_shortcut] +void +Ipc_sender::send_msg(Receiver *receiver) +{ + set_wait_queue(receiver->sender_list()); + + if (!Config::Irq_shortcut) + { + // enqueue _after_ shortcut if still necessary + sender_enqueue(receiver->sender_list(), 255); + receiver->vcpu_set_irq_pending(); + } + + // if the thread is waiting for this interrupt, make it ready; + // this will cause it to run irq->receiver_ready(), which + // handles the rest + + // XXX careful! This code may run in midst of an do_ipc() + // operation (or similar)! + if (Receiver::Rcv_state s = receiver->sender_ok(this)) + { + Syscall_frame *dst_regs = derived()->transfer_msg(receiver); + + if (derived()->requeue_sender()) + { + sender_enqueue(receiver->sender_list(), 255); + receiver->vcpu_set_irq_pending(); + } + + // ipc completed + receiver->state_change_dirty(~Thread_ipc_mask, 0); + + // in case a timeout was set + receiver->reset_timeout(); + + if (s == Receiver::Rs_ipc_receive) + { + if (handle_shortcut(dst_regs, receiver)) + return; + } + // we don't need to manipulate the state in a safe way + // because we are still running with interrupts turned off + receiver->state_add_dirty(Thread_ready); + receiver->sched()->deblock(receiver->cpu()); + return; + } + + if (Config::Irq_shortcut) + { + // enqueue after shortcut if still necessary + sender_enqueue(receiver->sender_list(), 255); + receiver->vcpu_set_irq_pending(); + } +} + diff --git a/kernel/fiasco/src/kern/ipc_timeout.cpp b/kernel/fiasco/src/kern/ipc_timeout.cpp new file mode 100644 index 00000000..3cbf780c --- /dev/null +++ b/kernel/fiasco/src/kern/ipc_timeout.cpp @@ -0,0 +1,64 @@ + +INTERFACE: + +#include "timeout.h" + +class Receiver; + +class IPC_timeout : public Timeout +{ + friend class Jdb_list_timeouts; +}; + +IMPLEMENTATION: + +#include "context.h" +#include "globals.h" +#include "receiver.h" +#include "thread_state.h" + +/** + * IPC_timeout constructor + */ +PUBLIC inline +IPC_timeout::IPC_timeout() +{} + +/** + * IPC_timeout destructor + */ +PUBLIC virtual inline NEEDS [IPC_timeout::owner, "receiver.h"] +IPC_timeout::~IPC_timeout() +{ + owner()->set_timeout (0); // reset owner's timeout field +} + +PRIVATE inline NEEDS ["globals.h"] +Receiver * +IPC_timeout::owner() +{ + // We could have saved our context in our constructor, but computing + // it this way is easier and saves space. We can do this as we know + // that IPC_timeouts are always created on the kernel stack of the + // owner context. + + return reinterpret_cast(context_of (this)); +} + +/** + * Timeout expiration callback function + * @return true if reschedule is necessary, false otherwise + */ +PRIVATE +bool +IPC_timeout::expired() +{ + Receiver * const _owner = owner(); + + // Set thread ready + _owner->state_change_dirty(~Thread_ipc_mask, Thread_ready | Thread_timeout); + + // Flag reschedule if owner's priority is higher than the current + // thread's (own or timeslice-donated) priority. + return _owner->sched()->deblock(current_cpu(), current()->sched(), false); +} diff --git a/kernel/fiasco/src/kern/ipi.cpp b/kernel/fiasco/src/kern/ipi.cpp new file mode 100644 index 00000000..76b0ca14 --- /dev/null +++ b/kernel/fiasco/src/kern/ipi.cpp @@ -0,0 +1,91 @@ +INTERFACE: + +class Ipi +{ +public: + static void init(unsigned cpu); +}; + +INTERFACE[!mp]: + +EXTENSION class Ipi +{ +public: + enum Message { Request, Global_request, Debug }; +}; + +INTERFACE[mp]: + +#include "per_cpu_data.h" +#include "spin_lock.h" + +EXTENSION class Ipi +{ +private: + static Per_cpu _ipi; +}; + +// ------------------------------------------------------------------------ +IMPLEMENTATION[!mp]: + +IMPLEMENT inline +void +Ipi::init(unsigned cpu) +{ (void)cpu; } + +PUBLIC static inline +void +Ipi::send(Message, unsigned from_cpu, unsigned to_cpu) +{ (void)from_cpu; (void)to_cpu; } + +PUBLIC static inline +void +Ipi::eoi(Message, unsigned on_cpu) +{ (void)on_cpu; } + +PUBLIC static inline +void +Ipi::bcast(Message, unsigned from_cpu) +{ (void)from_cpu; } + + +// ------------------------------------------------------------------------ +IMPLEMENTATION[mp]: + +DEFINE_PER_CPU Per_cpu Ipi::_ipi; + +// ------------------------------------------------------------------------ +IMPLEMENTATION[!(mp && debug)]: + +PUBLIC static inline +void +Ipi::stat_sent(unsigned from_cpu) +{ (void)from_cpu; } + +PUBLIC static inline +void +Ipi::stat_received(unsigned on_cpu) +{ (void)on_cpu; } + +// ------------------------------------------------------------------------ +IMPLEMENTATION[mp && debug]: + +#include "globals.h" + +EXTENSION class Ipi +{ +private: + friend class Jdb_ipi_module; + Mword _stat_sent; + Mword _stat_received; +}; + +PUBLIC static inline +void +Ipi::stat_sent(unsigned from_cpu) +{ atomic_mp_add(&_ipi.cpu(from_cpu)._stat_sent, 1); } + +PUBLIC static inline +void +Ipi::stat_received(unsigned on_cpu) +{ _ipi.cpu(on_cpu)._stat_received++; } diff --git a/kernel/fiasco/src/kern/irq.cpp b/kernel/fiasco/src/kern/irq.cpp new file mode 100644 index 00000000..387cd556 --- /dev/null +++ b/kernel/fiasco/src/kern/irq.cpp @@ -0,0 +1,717 @@ +INTERFACE: + +#include "ipc_sender.h" +#include "irq_chip.h" +#include "kobject_helper.h" +#include "member_offs.h" +#include "sender.h" +#include "context.h" + +class Ram_quota; +class Receiver; + + +/** Hardware interrupts. This class encapsulates handware IRQs. Also, + it provides a registry that ensures that only one receiver can sign up + to receive interrupt IPC messages. + */ +class Irq : public Irq_base, public Kobject +{ + MEMBER_OFFSET(); + FIASCO_DECLARE_KOBJ(); + +private: + typedef Slab_cache Allocator; + +public: + enum Op + { + Op_eoi_1 = 0, + Op_attach = 1, + Op_trigger = 2, + Op_chain = 3, + Op_eoi_2 = 4, + }; + +private: + Irq(Irq&); + +protected: + Ram_quota *_q; + Context::Drq _drq; +}; + + +/** + * IRQ Kobject to send IPC messages to a receiving thread. + */ +class Irq_sender +: public Kobject_h, + public Ipc_sender +{ +public: + Mword kobject_size() const { return sizeof(*this); } + +private: + Irq_sender(Irq_sender &); + +protected: + Smword _queued; + Receiver *_irq_thread; + +private: + Mword _irq_id; +}; + + +/** + * IRQ Kobject to broadcast IRQs to multiple other IRQ objects. + * + * This is useful for PCI shared IRQs. + */ +class Irq_muxer : public Kobject_h, private Irq_chip +{ +public: + unsigned set_mode(Mword, unsigned mode) { return mode; } + void switch_mode(unsigned) + { + // the irq object is assumed to be always handled as + // level triggered + } + + void set_cpu(Mword, unsigned) + { + // don't know what to do here, may be multiple targets on different + // CPUs! + } + + void ack(Mword) {} + + char const *chip_type() const { return "Bcast"; } + +private: + Smword _mask_cnt; +}; + +//----------------------------------------------------------------------------- +IMPLEMENTATION: + +#include "assert_opt.h" +#include "atomic.h" +#include "config.h" +#include "cpu_lock.h" +#include "entry_frame.h" +#include "globals.h" +#include "ipc_sender.h" +#include "kdb_ke.h" +#include "kmem_slab.h" +#include "lock_guard.h" +#include "minmax.h" +#include "receiver.h" +#include "std_macros.h" +#include "thread_object.h" +#include "thread_state.h" +#include "l4_buf_iter.h" +#include "vkey.h" + +FIASCO_DEFINE_KOBJ(Irq); + +namespace { +static Irq_base *irq_base_dcast(Kobject_iface *o) +{ return Kobject::dcast(o); } + +struct Irq_base_cast +{ + Irq_base_cast() + { Irq_base::dcast = &irq_base_dcast; } +}; + +static Irq_base_cast register_irq_base_cast; +} + + +PUBLIC +void +Irq_muxer::unmask(Mword) +{ + Smword old; + do + old = _mask_cnt; + while (!mp_cas(&_mask_cnt, old, old - 1)); + + if (old == 1) + Irq_base::unmask(); +} + + +PUBLIC +void +Irq_muxer::mask(Mword) +{ + Smword old; + do + old = _mask_cnt; + while (!mp_cas(&_mask_cnt, old, old + 1)); + + if (old == 0) + Irq_base::mask(); +} + + +PUBLIC +void +Irq_muxer::unbind(Irq_base *irq) +{ + Irq_base *n; + for (n = this; n->_next && n->_next != irq; n = n->_next) + ; + + assert (n->_next == irq); + n->_next = n->_next->_next; + if (irq->masked()) + static_cast(*this).unmask(0); + + Irq_chip::unbind(irq); +} + + +PUBLIC +void +Irq_muxer::mask_and_ack(Mword) +{} + +PUBLIC inline +void +Irq_muxer::handle(Upstream_irq const *ui) +{ + assert (cpu_lock.test()); + Irq_base::mask_and_ack(); + ui->ack(); + + if (EXPECT_FALSE (!Irq_base::_next)) + return; + + int irqs = 0; + for (Irq_base *n = Irq_base::_next; n;) + { + ++irqs; + n->__mask(); + n = n->Irq_base::_next; + } + + { + Smword old; + do + old = _mask_cnt; + while (!mp_cas(&_mask_cnt, old, old + irqs)); + } + + for (Irq_base *n = Irq_base::_next; n;) + { + Irq *i = nonull_static_cast(n); + i->hit(0); + n = i->Irq_base::_next; + } +} + +PUBLIC explicit +Irq_muxer::Irq_muxer(Ram_quota *q = 0) +: Kobject_h(q), _mask_cnt(0) +{ + hit_func = &handler_wrapper; +} + +PUBLIC +void +Irq_muxer::destroy(Kobject ***rl) +{ + // FIXME: unchain IRQs + + Irq::destroy(rl); +} + +PRIVATE +L4_msg_tag +Irq_muxer::sys_attach(L4_msg_tag const &tag, Utcb const *utcb, Syscall_frame * /*f*/, + Obj_space *o_space) +{ + L4_snd_item_iter snd_items(utcb, tag.words()); + + Irq *irq = 0; + unsigned mode = utcb->values[0] >> 16; + + if (tag.items() == 0) + return commit_result(-L4_err::EInval); + + if (tag.items() && snd_items.next()) + { + L4_fpage bind_irq(snd_items.get()->d); + if (EXPECT_FALSE(!bind_irq.is_objpage())) + return commit_error(utcb, L4_error::Overflow); + + irq = Kobject::dcast(o_space->lookup_local(bind_irq.obj_index())); + } + + if (!irq) + return commit_result(-L4_err::EInval); + + if (mode & Set_irq_mode) + printf("DEPRECATED SET IRQ MODE\n"); + //pin()->set_mode(mode); + + irq->unbind(); + + if (!irq->masked()) + { + Smword old; + do + old = _mask_cnt; + while (!mp_cas(&_mask_cnt, old, old + 1)); + } + + bind(irq, 0); + + irq->Irq_base::_next = Irq_base::_next; + Irq_base::_next = irq; + + return commit_result(0); +} + +PUBLIC +L4_msg_tag +Irq_muxer::kinvoke(L4_obj_ref, Mword /*rights*/, Syscall_frame *f, + Utcb const *utcb, Utcb *) +{ + register Context *const c_thread = ::current(); + assert_opt (c_thread); + register Space *const c_space = c_thread->space(); + assert_opt (c_space); + + L4_msg_tag tag = f->tag(); + + if (EXPECT_FALSE(tag.proto() != L4_msg_tag::Label_irq)) + return commit_result(-L4_err::EBadproto); + + if (EXPECT_FALSE(tag.words() < 1)) + return commit_result(-L4_err::EInval); + + switch ((utcb->values[0] & 0xffff)) + { + case Op_chain: + return sys_attach(tag, utcb, f, c_space); + case Op_trigger: + log(); + hit(0); + return no_reply(); + default: + return commit_result(-L4_err::EInval); + } +} + + + +/** Bind a receiver to this device interrupt. + @param t the receiver that wants to receive IPC messages for this IRQ + @return true if the binding could be established + */ +PUBLIC inline NEEDS ["atomic.h", "cpu_lock.h", "lock_guard.h"] +bool +Irq_sender::alloc(Receiver *t) +{ + bool ret = mp_cas(&_irq_thread, reinterpret_cast(0), t); + + if (ret) + { + if (EXPECT_TRUE(t != 0)) + { + t->inc_ref(); + _chip->set_cpu(pin(), t->cpu()); + } + + _queued = 0; + } + + return ret; +} + +PUBLIC +Receiver * +Irq_sender::owner() const { return _irq_thread; } + +/** Release an device interrupt. + @param t the receiver that ownes the IRQ + @return true if t really was the owner of the IRQ and operation was + successful + */ +PUBLIC +bool +Irq_sender::free(Receiver *t) +{ + bool ret = mp_cas(&_irq_thread, t, reinterpret_cast(0)); + + if (ret) + { + Lock_guard guard(&cpu_lock); + mask(); + + if (EXPECT_TRUE(t != 0)) + { + t->abort_send(this); + + // release cpu-lock early, actually before delete + guard.reset(); + + if (t->dec_ref() == 0) + delete t; + } + } + + return ret; +} + +PUBLIC explicit +Irq_sender::Irq_sender(Ram_quota *q = 0) +: Kobject_h(q), _queued(0), _irq_thread(0), _irq_id(~0UL) +{ + hit_func = &hit_level_irq; +} + +PUBLIC +void +Irq_sender::switch_mode(unsigned mode) +{ + if ((mode & Trigger_mask) == Trigger_edge) + hit_func = &hit_edge_irq; + else + hit_func = &hit_level_irq; +} + +PUBLIC +void +Irq_sender::destroy(Kobject ***rl) +{ + Lock_guard g(&cpu_lock); + if (_irq_thread) + free(_irq_thread); + + Irq::destroy(rl); +} + + +/** Consume one interrupt. + @return number of IRQs that are still pending. + */ +PRIVATE inline NEEDS ["atomic.h"] +Smword +Irq_sender::consume() +{ + Smword old; + + do + { + old = _queued; + } + while (!mp_cas (&_queued, old, old - 1)); + + if (old == 2 && hit_func == &hit_edge_irq) + unmask(); + + return old - 1; +} + +PUBLIC inline +int +Irq_sender::queued() +{ + return _queued; +} + + +/** + * Predicate used to figure out if the sender shall be enqueued + * for sending a second message after sending the first. + */ +PUBLIC inline NEEDS[Irq_sender::consume] +bool +Irq_sender::requeue_sender() +{ return consume() > 0; } + +/** + * Predicate used to figure out if the sender shall be deqeued after + * sending the request. + */ +PUBLIC inline NEEDS[Irq_sender::consume] +bool +Irq_sender::dequeue_sender() +{ return consume() < 1; } + +PUBLIC inline +Syscall_frame * +Irq_sender::transfer_msg(Receiver *recv) +{ + Syscall_frame* dst_regs = recv->rcv_regs(); + + // set ipc return value: OK + dst_regs->tag(L4_msg_tag(0)); + + // set ipc source thread id + dst_regs->from(_irq_id); + + return dst_regs; +} + +PUBLIC void +Irq_sender::modify_label(Mword const *todo, int cnt) +{ + for (int i = 0; i < cnt*4; i += 4) + { + Mword const test_mask = todo[i]; + Mword const test = todo[i+1]; + if ((_irq_id & test_mask) == test) + { + Mword const set_mask = todo[i+2]; + Mword const set = todo[i+3]; + + _irq_id = (_irq_id & ~set_mask) | set; + return; + } + } +} + + +PRIVATE static +unsigned +Irq_sender::handle_remote_hit(Context::Drq *, Context *, void *arg) +{ + Irq_sender *irq = (Irq_sender*)arg; + irq->set_cpu(current_cpu()); + irq->send_msg(irq->_irq_thread); + return Context::Drq::No_answer; +} + +PRIVATE inline +Smword +Irq_sender::queue() +{ + Smword old; + do + old = _queued; + while (!mp_cas(&_queued, old, old + 1)); + return old; +} + + +PRIVATE inline +void +Irq_sender::count_and_send(Smword queued) +{ + if (EXPECT_TRUE (queued == 0) && EXPECT_TRUE(_irq_thread != 0)) // increase hit counter + { + if (EXPECT_FALSE(_irq_thread->cpu() != current_cpu())) + _irq_thread->drq(&_drq, handle_remote_hit, this, 0, + Context::Drq::Target_ctxt, Context::Drq::No_wait); + else + send_msg(_irq_thread); + } +} + + +PUBLIC inline NEEDS[Irq_sender::count_and_send, Irq_sender::queue] +void +Irq_sender::_hit_level_irq(Upstream_irq const *ui) +{ + // We're entered holding the kernel lock, which also means irqs are + // disabled on this CPU (XXX always correct?). We never enable irqs + // in this stack frame (except maybe in a nonnested invocation of + // switch_exec() -> switchin_context()) -- they will be re-enabled + // once we return from it (iret in entry.S:all_irqs) or we switch to + // a different thread. + + // LOG_MSG_3VAL(current(), "IRQ", dbg_id(), 0, _queued); + + assert (cpu_lock.test()); + mask_and_ack(); + ui->ack(); + count_and_send(queue()); +} + +PRIVATE static +void +Irq_sender::hit_level_irq(Irq_base *i, Upstream_irq const *ui) +{ nonull_static_cast(i)->_hit_level_irq(ui); } + +PUBLIC inline NEEDS[Irq_sender::count_and_send, Irq_sender::queue] +void +Irq_sender::_hit_edge_irq(Upstream_irq const *ui) +{ + // We're entered holding the kernel lock, which also means irqs are + // disabled on this CPU (XXX always correct?). We never enable irqs + // in this stack frame (except maybe in a nonnested invocation of + // switch_exec() -> switchin_context()) -- they will be re-enabled + // once we return from it (iret in entry.S:all_irqs) or we switch to + // a different thread. + + // LOG_MSG_3VAL(current(), "IRQ", dbg_id(), 0, _queued); + + assert (cpu_lock.test()); + Smword q = queue(); + + // if we get a second edge triggered IRQ before the first is + // handled we can mask the IRQ. The consume function will + // unmask the IRQ when the last IRQ is dequeued. + if (!q) + ack(); + else + mask_and_ack(); + + ui->ack(); + count_and_send(q); +} + +PRIVATE static +void +Irq_sender::hit_edge_irq(Irq_base *i, Upstream_irq const *ui) +{ nonull_static_cast(i)->_hit_edge_irq(ui); } + + +PRIVATE +L4_msg_tag +Irq_sender::sys_attach(L4_msg_tag const &tag, Utcb const *utcb, Syscall_frame * /*f*/, + Obj_space *o_space) +{ + L4_snd_item_iter snd_items(utcb, tag.words()); + + Receiver *thread = 0; + unsigned mode = utcb->values[0] >> 16; + + if (tag.items() == 0) + { + // detach + if (mode & Set_irq_mode) + printf("DEPRECATED SET IRQ MODE\n"); + //pin()->set_mode(mode); + else + { + free(_irq_thread); + _irq_id = ~0UL; + } + return commit_result(0); + } + + if (tag.items() && snd_items.next()) + { + L4_fpage bind_thread(snd_items.get()->d); + if (EXPECT_FALSE(!bind_thread.is_objpage())) + return commit_error(utcb, L4_error::Overflow); + + thread = Kobject::dcast(o_space->lookup_local(bind_thread.obj_index())); + } + + if (!thread) + thread = current_thread(); + + if (alloc(thread)) + { + if (mode & Set_irq_mode) + printf("DEPRECATED SET IRQ MODE\n"); + _irq_id = utcb->values[1]; + return commit_result(0); + } + + return commit_result(-L4_err::EInval); +} + + +PUBLIC +L4_msg_tag +Irq_sender::kinvoke(L4_obj_ref, Mword /*rights*/, Syscall_frame *f, + Utcb const *utcb, Utcb *) +{ + register Context *const c_thread = ::current(); + assert_opt (c_thread); + register Space *const c_space = c_thread->space(); + assert_opt (c_space); + + L4_msg_tag tag = f->tag(); + + if (EXPECT_FALSE(tag.proto() != L4_msg_tag::Label_irq)) + return commit_result(-L4_err::EBadproto); + + if (EXPECT_FALSE(tag.words() < 1)) + return commit_result(-L4_err::EInval); + + switch ((utcb->values[0] & 0xffff)) + { + case Op_eoi_1: + case Op_eoi_2: + if (_queued < 1) + unmask(); + + return no_reply(); + case Op_attach: /* ATTACH, DETACH */ + return sys_attach(tag, utcb, f, c_space); + case Op_trigger: + log(); + hit(0); + return no_reply(); + default: + return commit_result(-L4_err::EInval); + } +} + +PUBLIC +Mword +Irq_sender::obj_id() const +{ return _irq_id; } + + + + // Irq implementation + +static Kmem_slab _irq_allocator(max(sizeof (Irq_sender), sizeof(Irq_muxer)), + __alignof__ (Irq), "Irq"); + +PRIVATE static +Irq::Allocator * +Irq::allocator() +{ return &_irq_allocator; } + +PUBLIC inline +void * +Irq::operator new (size_t, void *p) +{ return p; } + +PUBLIC +void +Irq::operator delete (void *_l) +{ + Irq *l = reinterpret_cast(_l); + if (l->_q) + l->_q->free(sizeof(Irq)); + + allocator()->free(l); +} + +PUBLIC template inline NEEDS[Irq::allocator, Irq::operator new] +static +T* +Irq::allocate(Ram_quota *q) +{ + void *nq =allocator()->q_alloc(q); + if (nq) + return new (nq) T(q); + + return 0; +} + + +PUBLIC explicit inline +Irq::Irq(Ram_quota *q = 0) : _q(q) {} + +PUBLIC +void +Irq::destroy(Kobject ***rl) +{ + Irq_base::destroy(); + Kobject::destroy(rl); +} diff --git a/kernel/fiasco/src/kern/irq_chip.cpp b/kernel/fiasco/src/kern/irq_chip.cpp new file mode 100644 index 00000000..6bf168a9 --- /dev/null +++ b/kernel/fiasco/src/kern/irq_chip.cpp @@ -0,0 +1,336 @@ +INTERFACE: + +#include "types.h" + +class Irq_base; +class Irq_chip; + +class Upstream_irq +{ +private: + Irq_chip *const _c; + Mword const _p; + Upstream_irq const *const _prev; + +}; + +/** + * Abstraction for an IRQ controller chip. + */ +class Irq_chip +{ +public: + virtual void mask(Mword pin) = 0; + virtual void unmask(Mword pin) = 0; + virtual void ack(Mword pin) = 0; + virtual void mask_and_ack(Mword pin) = 0; + + /** + * Set the trigger mode and polarity. + */ + virtual unsigned set_mode(Mword pin, unsigned) = 0; + + /** + * Set the target CPU. + * \param pin the pin to configure + * \param cpu the logical CPU number. + */ + virtual void set_cpu(Mword pin, unsigned cpu) = 0; + virtual void unbind(Irq_base *irq); + virtual ~Irq_chip() = 0; +}; + +/** + * Artificial IRQ chip, used for SW IRQs. + */ +class Irq_chip_soft : public Irq_chip +{ +public: + void mask(Mword) {} + void unmask(Mword) {} + void mask_and_ack(Mword) {} + void ack(Mword) {} + + void set_cpu(Mword, unsigned) {} + unsigned set_mode(Mword, unsigned mode) { return mode; } + + char const *chip_type() const { return "Soft"; } + + static Irq_chip_soft sw_chip; +}; + +/** + * Abstract IRQ controller chip that is visble as part of the + * Icu to the user. + */ +class Irq_chip_icu : public Irq_chip +{ +public: + virtual bool reserve(Mword pin) = 0; + virtual bool alloc(Irq_base *irq, Mword pin) = 0; + virtual Irq_base *irq(Mword pin) const = 0; + virtual unsigned nr_irqs() const = 0; + virtual ~Irq_chip_icu() = 0; +}; + + +class Kobject_iface; + + +/** + * Base class for all kinds of IRQ consuming objects. + */ +class Irq_base +{ + friend class Irq_chip; + +public: + + typedef void (*Hit_func)(Irq_base *, Upstream_irq const *); + enum Flags + { + F_enabled = 1, + }; + + enum Mode + { + Set_irq_mode = 0x1, + Trigger_edge = 0x0, + Trigger_level = 0x2, + Trigger_mask = 0x2, + + Polarity_high = 0x0, + Polarity_low = 0x4, + Polarity_both = 0x8, + Polarity_mask = 0xc, + }; + + Irq_base() : _flags(Trigger_level), _next(0) + { + Irq_chip_soft::sw_chip.bind(this, 0, true); + mask(); + } + + void hit(Upstream_irq const *ui) { hit_func(this, ui); } + + Mword pin() const { return _pin; } + Irq_chip *chip() const { return _chip; } + + void mask() { if (!__mask()) _chip->mask(_pin); } + void mask_and_ack() { if (!__mask()) _chip->mask_and_ack(_pin); } + void unmask() { if (__unmask()) _chip->unmask(_pin); } + void ack() { _chip->ack(_pin); } + + + void set_mode(unsigned m) + { + unsigned mode = _chip->set_mode(_pin, m); + _flags = (_flags & ~0xe) | (mode & 0xe); + switch_mode(mode); + } + + void set_cpu(unsigned cpu) { _chip->set_cpu(_pin, cpu); } + + unsigned get_mode() const + { return _flags & 0xe; } + + bool masked() const { return !(_flags & F_enabled); } + Mword flags() const { return _flags; } + + void unbind() { _chip->unbind(this); } + + bool __mask() { bool o = masked(); _flags &= ~F_enabled; return o; } + bool __unmask() { bool o = masked(); _flags |= F_enabled; return o; } + + void set_hit(Hit_func f) { hit_func = f; } + virtual void switch_mode(unsigned mode) = 0; + virtual ~Irq_base() = 0; + +protected: + Hit_func hit_func; + + Irq_chip *_chip; + Mword _pin; + unsigned _flags; + + template + static void handler_wrapper(Irq_base *irq, Upstream_irq const *ui) + { nonull_static_cast(irq)->handle(ui); } + +public: + Irq_base *_next; + + static Irq_base *(*dcast)(Kobject_iface *); +}; + + + + +//---------------------------------------------------------------------------- +INTERFACE [debug]: + +EXTENSION class Irq_chip +{ +public: + virtual char const *chip_type() const = 0; +}; + + +//-------------------------------------------------------------------------- +IMPLEMENTATION: + +#include "types.h" +#include "cpu_lock.h" +#include "lock_guard.h" +#include "static_init.h" + +Irq_chip_soft Irq_chip_soft::sw_chip INIT_PRIORITY(EARLY_INIT_PRIO); +Irq_base *(*Irq_base::dcast)(Kobject_iface *); + +IMPLEMENT inline Irq_chip::~Irq_chip() {} +IMPLEMENT inline Irq_chip_icu::~Irq_chip_icu() {} +IMPLEMENT inline Irq_base::~Irq_base() {} + +PUBLIC inline explicit +Upstream_irq::Upstream_irq(Irq_base const *b, Upstream_irq const *prev) +: _c(b->chip()), _p(b->pin()), _prev(prev) +{} + +PUBLIC inline +void +Upstream_irq::ack() const +{ + for (Upstream_irq const *c = this; c; c = c->_prev) + c->_c->ack(c->_p); +} + + +PUBLIC inline +void +Irq_chip::bind(Irq_base *irq, Mword pin, bool ctor = false) +{ + irq->_pin = pin; + irq->_chip = this; + + if (ctor) + return; + + irq->set_mode(irq->get_mode()); + if (irq->masked()) + mask(pin); + else + unmask(pin); +} + +IMPLEMENT inline +void +Irq_chip::unbind(Irq_base *irq) +{ + Irq_chip_soft::sw_chip.bind(irq, 0, true); +} + + +/** + * \param CHIP must be the dynamic type of the object. + */ +PUBLIC inline +template +void +Irq_chip::handle_irq(Mword pin, Upstream_irq const *ui) +{ + // call the irq function of the chip avoiding the + // virtual function call overhead. + Irq_base *irq = nonull_static_cast(this)->CHIP::irq(pin); + irq->log(); + irq->hit(ui); +} + +PUBLIC inline +template +void +Irq_chip::handle_multi_pending(Upstream_irq const *ui) +{ + while (Mword pend = nonull_static_cast(this)->CHIP::pending()) + { + for (unsigned i = 0; i < sizeof(Mword)*8; ++i, pend >>= 1) + if (pend & 1) + { + handle_irq(i, ui); + break; // read the pending ints again + } + } +} + + +PUBLIC inline NEEDS["lock_guard.h", "cpu_lock.h"] +void +Irq_base::destroy() +{ + Lock_guard g(&cpu_lock); + unbind(); +} + + +// -------------------------------------------------------------------------- +IMPLEMENTATION [!debug]: + +PUBLIC inline void Irq_base::log() {} + +//----------------------------------------------------------------------------- +INTERFACE [debug]: + +#include "tb_entry.h" + +EXTENSION class Irq_base +{ +public: + struct Irq_log + { + Irq_base *obj; + Irq_chip *chip; + Mword pin; + }; + + static unsigned irq_log_fmt(Tb_entry *, int, char *) + asm ("__irq_log_fmt"); +}; + + +// -------------------------------------------------------------------------- +IMPLEMENTATION [debug]: + +#include + +#include "logdefs.h" +#include "kobject_dbg.h" + +IMPLEMENT +unsigned +Irq_base::irq_log_fmt(Tb_entry *e, int maxlen, char *buf) +{ + Irq_log *l = e->payload(); + Kobject_dbg::Const_iterator irq = Kobject_dbg::pointer_to_obj(l->obj); + + if (irq != Kobject_dbg::end()) + return snprintf(buf, maxlen, "0x%lx/%lu @ chip %s(%p) D:%lx", + l->pin, l->pin, l->chip->chip_type(), l->chip, + irq->dbg_id()); + else + return snprintf(buf, maxlen, "0x%lx/%lu @ chip %s(%p) irq=%p", + l->pin, l->pin, l->chip->chip_type(), l->chip, + l->obj); +} + +PUBLIC inline NEEDS["logdefs.h"] +void +Irq_base::log() +{ + Context *c = current(); + LOG_TRACE("IRQ-Object triggers", "irq", c, __irq_log_fmt, + Irq_base::Irq_log *l = tbe->payload(); + l->obj = this; + l->chip = chip(); + l->pin = pin(); + ); +} + diff --git a/kernel/fiasco/src/kern/irq_chip_generic.cpp b/kernel/fiasco/src/kern/irq_chip_generic.cpp new file mode 100644 index 00000000..bc9993b6 --- /dev/null +++ b/kernel/fiasco/src/kern/irq_chip_generic.cpp @@ -0,0 +1,88 @@ +INTERFACE: + +#include "irq_chip.h" + + +class Irq_chip_gen : public Irq_chip_icu +{ +public: + Irq_chip_gen() {} + explicit Irq_chip_gen(unsigned nirqs) { init(nirqs); } + +private: + unsigned _nirqs; + Irq_base **_irqs; +}; + + +// ------------------------------------------------------------------------- +IMPLEMENTATION: + +#include + +#include "boot_alloc.h" +#include "mem.h" + +PUBLIC +void +Irq_chip_gen::init(unsigned nirqs) +{ + _nirqs = nirqs; + _irqs = (Irq_base **)Boot_alloced::alloc(sizeof(Irq_base*) * nirqs); + memset(_irqs, 0, sizeof(Irq_base*) * nirqs); +} + +PUBLIC inline +unsigned +Irq_chip_gen::nr_irqs() const +{ return _nirqs; } + +PUBLIC +Irq_base * +Irq_chip_gen::irq(Mword pin) const +{ + if (pin >= _nirqs) + return 0; + + return _irqs[pin]; +} + +PUBLIC +bool +Irq_chip_gen::alloc(Irq_base *irq, Mword pin) +{ + if (pin >= _nirqs) + return false; + + if (_irqs[pin]) + return false; + + _irqs[pin] = irq; + bind(irq, pin); + return true; +} + +PUBLIC +void +Irq_chip_gen::unbind(Irq_base *irq) +{ + mask(irq->pin()); + Mem::barrier(); + _irqs[irq->pin()] = 0; + Irq_chip_icu::unbind(irq); +} + +PUBLIC +bool +Irq_chip_gen::reserve(Mword pin) +{ + if (pin >= _nirqs) + return false; + + if (_irqs[pin]) + return false; + + _irqs[pin] = (Irq_base*)1; + + return true; +} diff --git a/kernel/fiasco/src/kern/irq_controller.cpp b/kernel/fiasco/src/kern/irq_controller.cpp new file mode 100644 index 00000000..c2eeb650 --- /dev/null +++ b/kernel/fiasco/src/kern/irq_controller.cpp @@ -0,0 +1,82 @@ +INTERFACE: + +#include "irq.h" +#include "ram_quota.h" +#include "icu_helper.h" + +class Irq_chip; + +class Icu : public Icu_h +{ + FIASCO_DECLARE_KOBJ(); + + friend class Icu_h; +}; + + +//---------------------------------------------------------------------------- +IMPLEMENTATION: + +#include "entry_frame.h" +#include "irq.h" +#include "irq_chip.h" +#include "irq_mgr.h" +#include "l4_types.h" +#include "l4_buf_iter.h" + +FIASCO_DEFINE_KOBJ(Icu); + +PUBLIC void +Icu::operator delete (void *) +{ + printf("WARNING: tried to delete kernel ICU object.\n" + " The system is now useless\n"); +} + +PUBLIC inline NEEDS["irq_mgr.h"] +Irq_base * +Icu::icu_get_irq(unsigned irqnum) +{ + return Irq_mgr::mgr->irq(irqnum); +} + + +PUBLIC inline NEEDS["irq_mgr.h"] +L4_msg_tag +Icu::icu_bind_irq(Irq *irq, unsigned irqnum) +{ + irq->unbind(); + + if (!Irq_mgr::mgr->alloc(irq, irqnum)) + return commit_result(-L4_err::EPerm); + + return commit_result(0); +} + + +PUBLIC inline NEEDS["irq_mgr.h"] +void +Icu::icu_get_info(Mword *features, Mword *num_irqs, Mword *num_msis) +{ + *num_irqs = Irq_mgr::mgr->nr_irqs(); + *num_msis = Irq_mgr::mgr->nr_msis(); + *features = *num_msis ? (unsigned)Msi_bit : 0; +} + +PUBLIC inline NEEDS["irq_mgr.h"] +L4_msg_tag +Icu::icu_get_msi_info(Mword msi, Utcb *out) +{ + out->values[0] = Irq_mgr::mgr->msg(msi); + return commit_result(0, 1); +} + + +PUBLIC inline +Icu::Icu() +{ + initial_kobjects.register_obj(this, 6); +} + +static Icu icu; + diff --git a/kernel/fiasco/src/kern/irq_mgr.cpp b/kernel/fiasco/src/kern/irq_mgr.cpp new file mode 100644 index 00000000..77221fee --- /dev/null +++ b/kernel/fiasco/src/kern/irq_mgr.cpp @@ -0,0 +1,131 @@ +INTERFACE: + +#include "types.h" +#include "irq_chip.h" + +/** + * Interface used to manage harware IRQs on a platform. + * + * The main purpose of this interface is to allow an + * abstract mapping of global IRQ numbers to a chip + * and pin number pair. The interface provides also + * some global information about IRQs. + */ +class Irq_mgr +{ +public: + /** + * Chip and pin for an IRQ pin. + */ + struct Irq + { + // allow uninitialized instances + enum Init { Bss }; + Irq(Init) {} + + /// Invalid IRQ. + Irq() : chip(0) {} + + /// Create a chip-pin pair. + Irq(Irq_chip_icu *chip, Mword pin) : chip(chip), pin(pin) {} + + /// The chip. + Irq_chip_icu *chip; + + /// The pin number local to \a chip. + Mword pin; + }; + + /// Map legacy (IA32) IRQ numbers to valid IRQ numbers. + virtual unsigned legacy_override(Mword irqnum) { return irqnum; } + + /// Get the chip-pin pair for the given global IRQ number. + virtual Irq chip(Mword irqnum) const = 0; + + /// Get the highest available global IRQ number plus 1. + virtual unsigned nr_irqs() const = 0; + + /// Get the number of available entry points for MSIs. + virtual unsigned nr_msis() const = 0; + + /** Get the message to use for a given MSI. + * \pre The IRQ pin needs to be already allocated before using this function. + */ + virtual Mword msg(Mword irqnum) const { (void)irqnum; return 0; } + + virtual void set_cpu(Mword irqnum, unsigned cpu) const; + + /// The pointer to the single global instance of the actual IRQ manager. + static Irq_mgr *mgr; + + /// Prevent generation of a real virtual delete function + virtual ~Irq_mgr() = 0; +}; + +template< typename CHIP > +class Irq_mgr_single_chip : public Irq_mgr +{ +public: + Irq_mgr_single_chip() {} + + template + explicit Irq_mgr_single_chip(A1 const &a1) : c(a1) {} + + template + Irq_mgr_single_chip(A1 const &a1, A2 const &a2) : c(a1, a2) {} + + + Irq chip(Mword irqnum) const { return Irq(&c, irqnum); } + unsigned nr_irqs() const { return c.nr_irqs(); } + unsigned nr_msis() const { return 0; } + mutable CHIP c; +}; + +//-------------------------------------------------------------------------- +IMPLEMENTATION: + +#include "warn.h" + +Irq_mgr *Irq_mgr::mgr; + +IMPLEMENT inline Irq_mgr::~Irq_mgr() {} + +PUBLIC inline +bool +Irq_mgr::alloc(Irq_base *irq, Mword pin) +{ + Irq i = chip(pin); + if (!i.chip) + return false; + + return i.chip->alloc(irq, i.pin); +} + +PUBLIC inline +bool +Irq_mgr::reserve(Mword irqnum) +{ + Irq i = chip(irqnum); + if (!i.chip) + return false; + + return i.chip->reserve(i.pin); +} + +PUBLIC inline +Irq_base * +Irq_mgr::irq(Mword irqnum) const +{ + Irq i = chip(irqnum); + if (!i.chip) + return 0; + + return i.chip->irq(i.pin); +} + +IMPLEMENT +void +Irq_mgr::set_cpu(Mword irqnum, unsigned cpu) const +{ + WARNX(Warning, "IRQ%ld: ignoring CPU setting (%d).\n", irqnum, cpu); +} diff --git a/kernel/fiasco/src/kern/irq_mgr_multi_chip.cpp b/kernel/fiasco/src/kern/irq_mgr_multi_chip.cpp new file mode 100644 index 00000000..89f03fc6 --- /dev/null +++ b/kernel/fiasco/src/kern/irq_mgr_multi_chip.cpp @@ -0,0 +1,85 @@ +INTERFACE: + +#include "irq_mgr.h" + +template< unsigned Bits_per_entry > +class Irq_mgr_multi_chip : public Irq_mgr +{ +public: + unsigned nr_irqs() const { return _nchips << Bits_per_entry; } + unsigned nr_msis() const { return 0; } + +private: + struct Chip + { + unsigned mask; + Irq_chip_icu *chip; + }; + + unsigned _nchips; + Chip *_chips; +}; + +IMPLEMENTATION: + +#include +#include + +#include "boot_alloc.h" + +PUBLIC explicit +template< unsigned Bits_per_chip > +Irq_mgr_multi_chip::Irq_mgr_multi_chip(unsigned chips) + : _nchips(chips), + _chips((Chip*)Boot_alloced::alloc(sizeof(Chip) * chips)) +{ + memset(_chips, 0, sizeof(Chip) * chips); +} + +PUBLIC template< unsigned Bits_per_entry > +Irq_mgr::Irq +Irq_mgr_multi_chip::chip(Mword irqnum) const +{ + unsigned c = irqnum >> Bits_per_entry; + if (c >= _nchips) + return Irq(); + + Chip *ci = _chips + c; + + return Irq(ci->chip, irqnum & ci->mask); +} + + +PUBLIC +template< unsigned Bits_per_entry > +void +Irq_mgr_multi_chip::add_chip(unsigned irq_base, + Irq_chip_icu *c, unsigned pins) +{ + // check if the base is properly aligned + assert ((irq_base & ~(~0UL << Bits_per_entry)) == 0); + + unsigned idx = irq_base >> Bits_per_entry; + unsigned num = (pins + (1UL << Bits_per_entry) - 1) >> Bits_per_entry; + + unsigned mask = ~0UL; + while (mask & (pins - 1)) + mask <<= 1; + + assert (mask); + mask = ~mask; + + // base irq must be aligned according to the number of pins + assert (!(irq_base & mask)); + + assert (num); + assert (idx < _nchips); + assert (idx + num <= _nchips); + + for (unsigned i = idx; i < idx + num; ++i) + { + assert (!_chips[i].chip); + _chips[i].chip = c; + _chips[i].mask = mask; + } +} diff --git a/kernel/fiasco/src/kern/kdb_ke.cpp b/kernel/fiasco/src/kern/kdb_ke.cpp new file mode 100644 index 00000000..a065fc54 --- /dev/null +++ b/kernel/fiasco/src/kern/kdb_ke.cpp @@ -0,0 +1,17 @@ +INTERFACE: + +#include "std_macros.h" + +#ifdef NDEBUG +# define assert_kdb(expression) do {} while (0) +# define check_kdb(expr) (void)(expr) + +#else /* ! NDEBUG */ +# include +# define assert_kdb(expression) \ + do { if (EXPECT_FALSE(!(expression))) \ + { printf("%s:%d: ASSERTION FAILED (%s)\n", __FILE__, __LINE__, #expression); \ + kdb_ke("XXX");} } while (0) +# define check_kdb(expr) assert_kdb(expr) +#endif /* ! NDEBUG */ + diff --git a/kernel/fiasco/src/kern/kern_cnt.cpp b/kernel/fiasco/src/kern/kern_cnt.cpp new file mode 100644 index 00000000..a47c4797 --- /dev/null +++ b/kernel/fiasco/src/kern/kern_cnt.cpp @@ -0,0 +1,109 @@ +INTERFACE: + +#include "types.h" + +class Kern_cnt +{ +private: + enum { + Max_slot = 2, + }; + + static Mword *kcnt[Max_slot]; + static Mword (*read_kcnt_fn[Max_slot])(); +}; + + +IMPLEMENTATION: + +#include "jdb_ktrace.h" +#include "mem_layout.h" +#include "tb_entry.h" + +Mword *Kern_cnt::kcnt[Max_slot]; +Mword (*Kern_cnt::read_kcnt_fn[Max_slot])() = { read_kcnt1, read_kcnt2 }; + +static Mword Kern_cnt::read_kcnt1() { return *kcnt[0]; } +static Mword Kern_cnt::read_kcnt2() { return *kcnt[1]; } + +PUBLIC static +Mword* +Kern_cnt::get_ctr(int num) +{ + Tracebuffer_status *status = + (Tracebuffer_status*) Mem_layout::Tbuf_status_page; + + return (Mword*)(num < Kern_cnt_max ? status->kerncnts + num : 0); +} + +PUBLIC static +const char * +Kern_cnt::get_str(Mword num) +{ + switch (num) + { + case Kern_cnt_context_switch: return "Context switches"; + case Kern_cnt_addr_space_switch: return "Address space switches"; + case Kern_cnt_shortcut_failed: return "IPC shortcut failed"; + case Kern_cnt_shortcut_success: return "IPC shortcut success"; + case Kern_cnt_irq: return "Long IPCs"; + case Kern_cnt_ipc_long: return "Hardware interrupts"; + case Kern_cnt_page_fault: return "Page faults"; + case Kern_cnt_io_fault: return "IO bitmap faults"; + case Kern_cnt_task_create: return "Tasks created"; + case Kern_cnt_schedule: return "Scheduler calls"; + case Kern_cnt_iobmap_tlb_flush: return "IO bitmap TLB flushs"; + case Kern_cnt_exc_ipc: return "Exception IPCs"; + default: return 0; + } +} + +PUBLIC static +int +Kern_cnt::mode(Mword slot, const char **mode, const char **name, Mword *event) +{ + Mword *c = 0; + + switch (slot) + { + case 0: c = kcnt[0]; break; + case 1: c = kcnt[1]; break; + } + + if (c) + { + Mword num = c - get_ctr(0); + + *mode = "on"; + *name = get_str(num); + *event = 0x80000000 | num; + return 1; + } + + *mode = "off"; + *name = ""; + return 0; +} + +PUBLIC static +int +Kern_cnt::setup_pmc(Mword slot, Mword event) +{ + if (slot>=Max_slot) + return 0; + + if (!(event & 0x80000000)) + { + kcnt[slot] = 0; + Tb_entry::set_rdcnt(slot, 0); + return 0; + } + + event &= 0xff; + if (event >= Kern_cnt_max) + return 0; + + kcnt[slot] = get_ctr(event); + Tb_entry::set_rdcnt(slot, read_kcnt_fn[slot]); + return 1; +} diff --git a/kernel/fiasco/src/kern/kernel_console.cpp b/kernel/fiasco/src/kern/kernel_console.cpp new file mode 100644 index 00000000..097dfb0f --- /dev/null +++ b/kernel/fiasco/src/kern/kernel_console.cpp @@ -0,0 +1,64 @@ +INTERFACE: + +#include "mux_console.h" +#include "std_macros.h" + +class Kconsole : public Mux_console +{ +public: + int getchar(bool blocking = true); + void getchar_chance(); + + static Mux_console *console() FIASCO_CONST + { return _c; } + +private: + static Static_object _c; +}; + +IMPLEMENTATION: + +#include "config.h" +#include "console.h" +#include "mux_console.h" +#include "processor.h" + +Static_object Kconsole::_c; + + +IMPLEMENT +int Kconsole::getchar(bool blocking) +{ + if (!blocking) + return Mux_console::getchar(false); + + while (1) + { + int c; + if ((c = Mux_console::getchar(false)) != -1) + return c; + + if (Config::getchar_does_hlt_works_ok // wakeup timer is enabled + && Proc::interrupts()) // does'nt work without ints + Proc::halt(); + else + Proc::pause(); + } +} + + +PUBLIC inline +Kconsole::Kconsole() +{ + Console::stdout = this; + Console::stderr = this; + Console::stdin = this; +} + + +PUBLIC static FIASCO_NOINLINE +void +Kconsole::init() +{ _c.construct(); } + + diff --git a/kernel/fiasco/src/kern/kernel_panic.cc b/kernel/fiasco/src/kern/kernel_panic.cc new file mode 100644 index 00000000..96a65cd9 --- /dev/null +++ b/kernel/fiasco/src/kern/kernel_panic.cc @@ -0,0 +1,42 @@ +#include +#include +#include +#include +#include + +#include "kernel_console.h" +#include "simpleio.h" +#include "terminate.h" + + +void +__assert_fail (const char *__assertion, const char *__file, + unsigned int __line) +{ + // make sure that GZIP mode is off + Kconsole::console()->end_exclusive(Console::GZIP); + + printf("\nAssertion failed: '%s'\n" + " in %s:%i\n" + " at " L4_PTR_FMT "\n", + __assertion, __file, __line, (Address)__builtin_return_address(0)); + + terminate(1); +} + +void +panic(const char *format, ...) +{ + // make sure that GZIP mode is off + Kconsole::console()->end_exclusive(Console::GZIP); + + va_list args; + + putstr("\033[1mPanic: "); + va_start (args, format); + vprintf (format, args); + va_end (args); + putstr("\033[m"); + + terminate (EXIT_FAILURE); +} diff --git a/kernel/fiasco/src/kern/kernel_task.cpp b/kernel/fiasco/src/kern/kernel_task.cpp new file mode 100644 index 00000000..c5a2e2e1 --- /dev/null +++ b/kernel/fiasco/src/kern/kernel_task.cpp @@ -0,0 +1,39 @@ +INTERFACE: + +#include "task.h" +#include "types.h" + +class Kernel_thread; + +class Kernel_task : public Task +{ + friend class Kernel_thread; + friend class Static_object; +private: + static Static_object _t; +}; + +IMPLEMENTATION[!(arm || ppc32 || sparc)]: + +#include "config.h" +#include "globals.h" +#include "kmem.h" + +PRIVATE inline NEEDS["globals.h"] +Kernel_task::Kernel_task() +: Task(Ram_quota::root, Kmem::kdir) +{} + + +IMPLEMENTATION: + +Static_object Kernel_task::_t; + +PUBLIC static Task* +Kernel_task::kernel_task() +{ return _t; } + +PUBLIC static inline NEEDS[Kernel_task::Kernel_task] +void +Kernel_task::init() +{ _t.construct(); } diff --git a/kernel/fiasco/src/kern/kernel_thread-std.cpp b/kernel/fiasco/src/kern/kernel_thread-std.cpp new file mode 100644 index 00000000..e4eee6c9 --- /dev/null +++ b/kernel/fiasco/src/kern/kernel_thread-std.cpp @@ -0,0 +1,161 @@ +IMPLEMENTATION: + +#include "assert_opt.h" +#include "config.h" +#include "factory.h" +#include "initcalls.h" +#include "ipc_gate.h" +#include "irq.h" +#include "koptions.h" +#include "map_util.h" +#include "mem_layout.h" +#include "sigma0_task.h" +#include "task.h" +#include "thread_object.h" +#include "types.h" +#include "ram_quota.h" + +enum Default_base_caps +{ + C_task = 1, + C_factory = 2, + C_thread = 3, + C_pager = 4, + C_log = 5, + C_icu = 6, + C_scheduler = 7 + +}; + + +IMPLEMENT +void +Kernel_thread::init_workload() +{ + Lock_guard g(&cpu_lock); + + if (Config::Jdb && + !Koptions::o()->opt(Koptions::F_nojdb) && + Koptions::o()->opt(Koptions::F_jdb_cmd)) + { + // extract the control sequence from the command line + char ctrl[128]; + char const *s = Koptions::o()->jdb_cmd; + char *d; + + for (d=ctrl; d < ctrl+sizeof(ctrl)-1 && *s && *s != ' '; *d++ = *s++) + ; + *d = '\0'; + + kdb_ke_sequence(ctrl); + } + + // kernel debugger rendezvous + if (Koptions::o()->opt(Koptions::F_wait)) + kdb_ke("Wait"); + + // + // create sigma0 + // + + Task *sigma0 = Task::create(Ram_quota::root, + L4_fpage::mem(Mem_layout::Utcb_addr, Config::PAGE_SHIFT)); + + assert_opt (sigma0); + // prevent deletion of this thing + sigma0->inc_ref(); + + init_mapdb_mem(sigma0); + init_mapdb_io(sigma0); + + check (map(sigma0, sigma0, sigma0, C_task, 0)); + check (map(Factory::root(), sigma0, sigma0, C_factory, 0)); + + for (unsigned c = Initial_kobjects::First_cap; c < Initial_kobjects::End_cap; ++c) + { + Kobject_iface *o = initial_kobjects.obj(c); + if (o) + check(map(o, sigma0, sigma0, c, 0)); + } + + Thread_object *sigma0_thread = new (Ram_quota::root) Thread_object(); + + assert_kdb(sigma0_thread); + + // prevent deletion of this thing + sigma0_thread->inc_ref(); + check (map(sigma0_thread, sigma0, sigma0, C_thread, 0)); + + Address sp = init_workload_s0_stack(); + check (sigma0_thread->control(Thread_ptr(false), Thread_ptr(false)) == 0); + check (sigma0_thread->bind(sigma0, User::Ptr((Utcb*)Mem_layout::Utcb_addr))); + check (sigma0_thread->ex_regs(Kip::k()->sigma0_ip, sp)); + + // + // create the boot task + // + + Task *boot_task = Task::create(Ram_quota::root, + L4_fpage::mem(Mem_layout::Utcb_addr, Config::PAGE_SHIFT+2)); + + assert_opt (boot_task); + + // prevent deletion of this thing + boot_task->inc_ref(); + + Thread_object *boot_thread = new (Ram_quota::root) Thread_object(); + + assert_kdb (boot_thread); + + // prevent deletion of this thing + boot_thread->inc_ref(); + + check (map(boot_task, boot_task, boot_task, C_task, 0)); + check (map(boot_thread, boot_task, boot_task, C_thread, 0)); + + check (boot_thread->control(Thread_ptr(C_pager), Thread_ptr(~0UL)) == 0); + check (boot_thread->bind(boot_task, User::Ptr((Utcb*)Mem_layout::Utcb_addr))); + check (boot_thread->ex_regs(Kip::k()->root_ip, Kip::k()->root_sp)); + + Ipc_gate *s0_b_gate = Ipc_gate::create(Ram_quota::root, sigma0_thread, 4 << 4); + + check (s0_b_gate); + check (map(s0_b_gate, boot_task, boot_task, C_pager, 0)); + + set_cpu_of(sigma0_thread, 0); + set_cpu_of(boot_thread, 0); + sigma0_thread->state_del_dirty(Thread_suspended); + boot_thread->state_del_dirty(Thread_suspended); + + sigma0_thread->activate(); + check (obj_map(sigma0, C_factory, 1, boot_task, C_factory, 0).error() == 0); + for (unsigned c = Initial_kobjects::First_cap; c < Initial_kobjects::End_cap; ++c) + { + Kobject_iface *o = initial_kobjects.obj(c); + if (o) + check(obj_map(sigma0, c, 1, boot_task, c, 0).error() == 0); + } + + boot_thread->activate(); +} + +IMPLEMENTATION [ia32,amd64]: + +PRIVATE inline +Address +Kernel_thread::init_workload_s0_stack() +{ + // push address of kernel info page to sigma0's stack + Address sp = Kip::k()->sigma0_sp - sizeof(Mword); + // assume we run in kdir 1:1 mapping + *reinterpret_cast(sp) = Kmem::virt_to_phys(Kip::k()); + return sp; +} + +IMPLEMENTATION [ux,arm,ppc32,sparc]: + +PRIVATE inline +Address +Kernel_thread::init_workload_s0_stack() +{ return Kip::k()->sigma0_sp; } + diff --git a/kernel/fiasco/src/kern/kernel_thread.cpp b/kernel/fiasco/src/kern/kernel_thread.cpp new file mode 100644 index 00000000..4fc61c74 --- /dev/null +++ b/kernel/fiasco/src/kern/kernel_thread.cpp @@ -0,0 +1,186 @@ +INTERFACE: + +#include "thread_object.h" + +class Kernel_thread : public Thread_object +{ +private: + /** + * Frees the memory of the initcall sections. + * + * Virtually initcall sections are freed by not marking them + * reserved in the KIP. This method just invalidates the contents of + * the memory, by filling it with some invalid data and may be + * unmapping it. + */ + void free_initcall_section(); + void bootstrap() asm ("call_bootstrap") FIASCO_FASTCALL; + void bootstrap_arch(); + void run(); + void do_idle() __attribute__((noreturn)); + +protected: + void init_workload(); +}; + + +IMPLEMENTATION: + +#include +#include + +#include "config.h" +#include "cpu.h" +#include "delayloop.h" +#include "globals.h" +#include "helping_lock.h" +#include "kernel_task.h" +#include "processor.h" +#include "task.h" +#include "thread.h" +#include "thread_state.h" +#include "timer.h" +#include "timer_tick.h" +#include "watchdog.h" + + +PUBLIC +Kernel_thread::Kernel_thread() : Thread_object(Thread::Kernel) +{} + +PUBLIC inline +Mword * +Kernel_thread::init_stack() +{ return _kernel_sp; } + +// the kernel bootstrap routine +IMPLEMENT FIASCO_INIT +void +Kernel_thread::bootstrap() +{ + // Initializations done -- Helping_lock can now use helping lock + Helping_lock::threading_system_active = true; + + + set_cpu_of(this, Cpu::boot_cpu()->id()); + Mem::barrier(); + + state_change_dirty(0, Thread_ready); // Set myself ready + + Timer::init_system_clock(); + Sched_context::rq(cpu()).set_idle(this->sched()); + + Kernel_task::kernel_task()->make_current(); + + // Setup initial timeslice + set_current_sched(sched()); + + Timer_tick::setup(cpu()); assert (cpu() == 0); // currently the boot cpu must be 0 + Timer_tick::enable(cpu()); + enable_tlb(cpu()); + + bootstrap_arch(); + + Per_cpu_data::run_late_ctors(0); + + Proc::sti(); + Watchdog::enable(); + printf("Calibrating timer loop... "); + // Init delay loop, needs working timer interrupt + Delay::init(); + printf("done.\n"); + + run(); +} + +/** + * The idle loop + * NEVER inline this function, because our caller is an initcall + */ +IMPLEMENT FIASCO_NOINLINE FIASCO_NORETURN +void +Kernel_thread::run() +{ + free_initcall_section(); + + // No initcalls after this point! + + kernel_context(cpu(), this); + + Rcu::leave_idle(cpu()); + // init_workload cannot be an initcall, because it fires up the userland + // applications which then have access to initcall frames as per kinfo page. + init_workload(); + + for (;;) + idle_op(); +} + +// ------------------------------------------------------------------------ +IMPLEMENTATION [!arch_idle && !tickless_idle]: + +PUBLIC inline NEEDS["processor.h"] +void +Kernel_thread::idle_op() +{ + if (Config::hlt_works_ok) + Proc::halt(); // stop the CPU, waiting for an int + else + Proc::pause(); +} + + +// ------------------------------------------------------------------------ +IMPLEMENTATION [tickless_idle]: + +#include + +EXTENSION class Kernel_thread +{ +private: + friend class Jdb_idle_stats; + static Per_cpu _idle_counter; + static Per_cpu _deep_idle_counter; +}; + + +DEFINE_PER_CPU Per_cpu Kernel_thread::_idle_counter; +DEFINE_PER_CPU Per_cpu Kernel_thread::_deep_idle_counter; + +// template code for arch idle +PUBLIC +void +Kernel_thread::idle_op() +{ + // this version must run with disabled IRQs and a wakup must continue directly + // after the wait for event. + Lock_guard guard(&cpu_lock); + unsigned cpu = this->cpu(); + ++_idle_counter.cpu(cpu); + // 1. check for latency requirements that prevent low power modes + // 2. check for timouts on this CPU ignore the idle thread's timeslice + // 3. check for RCU work on this cpu + if (Rcu::idle(cpu) + && !Timeout_q::timeout_queue.cpu(cpu).have_timeouts(timeslice_timeout.cpu(cpu))) + { + ++_deep_idle_counter.cpu(cpu); + Rcu::enter_idle(cpu); + Timer_tick::disable(cpu); + disable_tlb(cpu); + + + // do everything to do to a deep sleep state: + // - flush tlbs + // - flush caches + // - ... + arch_tickless_idle(cpu); + + enable_tlb(cpu); + Rcu::leave_idle(cpu); + Timer_tick::enable(cpu); + } + else + arch_idle(cpu); +} + + diff --git a/kernel/fiasco/src/kern/kernel_uart-16550.cpp b/kernel/fiasco/src/kern/kernel_uart-16550.cpp new file mode 100644 index 00000000..a5790a5d --- /dev/null +++ b/kernel/fiasco/src/kern/kernel_uart-16550.cpp @@ -0,0 +1,12 @@ +INTERFACE[16550]: + +// The port-based 16550 UART can be used before the MMU is initialized +EXTENSION class Kernel_uart { enum { Bsp_init_mode = Init_before_mmu }; }; + +IMPLEMENTATION[16550]: + +IMPLEMENT +bool Kernel_uart::startup(unsigned port, int irq) +{ + return Uart::startup(port, irq); +} diff --git a/kernel/fiasco/src/kern/kernel_uart.cpp b/kernel/fiasco/src/kern/kernel_uart.cpp new file mode 100644 index 00000000..ce086afb --- /dev/null +++ b/kernel/fiasco/src/kern/kernel_uart.cpp @@ -0,0 +1,145 @@ +INTERFACE: + +class Kernel_uart +{ +public: + enum Init_mode + { + Init_before_mmu, + Init_after_mmu + }; + Kernel_uart(); + static void enable_rcv_irq(); +}; + +INTERFACE [serial]: + +#include "uart.h" +#include "std_macros.h" + +/** + * Glue between kernel and UART driver. + */ +EXTENSION class Kernel_uart : public Uart +{ +private: + /** + * Prototype for the UART specific startup implementation. + * @param uart, the instantiation to start. + * @param port, the com port number. + */ + bool startup(unsigned port, int irq=-1); +}; + +//--------------------------------------------------------------------------- +IMPLEMENTATION [serial]: + +#include +#include +#include + +#include "filter_console.h" +#include "irq_chip.h" +#include "irq_mgr.h" +#include "kdb_ke.h" +#include "kernel_console.h" +#include "uart.h" +#include "config.h" +#include "kip.h" +#include "koptions.h" +#include "panic.h" +#include "vkey.h" + +static Static_object _fcon; +static Static_object _kernel_uart; + +PUBLIC static FIASCO_CONST +Uart * +Kernel_uart::uart() +{ return _kernel_uart; } + +PUBLIC static +bool +Kernel_uart::init(Init_mode init_mode = Init_before_mmu) +{ + if ((int)init_mode != Bsp_init_mode) + return false; + + if (Koptions::o()->opt(Koptions::F_noserial)) // do not use serial uart + return true; + + _kernel_uart.construct(); + _fcon.construct(_kernel_uart); + + Kconsole::console()->register_console(_fcon, 0); + return true; +} + +IMPLEMENT +Kernel_uart::Kernel_uart() +{ + unsigned n = Config::default_console_uart_baudrate; + Uart::TransferMode m = Uart::MODE_8N1; + unsigned long long p = Config::default_console_uart; + int i = -1; + + if (Koptions::o()->opt(Koptions::F_uart_baud)) + n = Koptions::o()->uart.baud; + + if (Koptions::o()->opt(Koptions::F_uart_base)) + p = Koptions::o()->uart.base_address; + + if (Koptions::o()->opt(Koptions::F_uart_irq)) + i = Koptions::o()->uart.irqno; + + if (!startup(p, i)) + printf("Comport/base 0x%04llx is not accepted by the uart driver!\n", p); + else if (!change_mode(m, n)) + panic("Somthing is wrong with the baud rate (%d)!\n", n); +} + + +class Kuart_irq : public Irq_base +{ +public: + Kuart_irq() { hit_func = &handler_wrapper; } + void switch_mode(unsigned) {} + void handle(Upstream_irq const *ui) + { + mask_and_ack(); + ui->ack(); + if (!Vkey::check_()) + kdb_ke("IRQ ENTRY"); + unmask(); + } +}; + + +IMPLEMENT +void +Kernel_uart::enable_rcv_irq() +{ + static Kuart_irq uart_irq; + if (Irq_mgr::mgr->alloc(&uart_irq, uart()->irq())) + { + uart_irq.unmask(); + uart()->enable_rcv_irq(); + } +} + +//--------------------------------------------------------------------------- +IMPLEMENTATION [!serial]: + +PUBLIC static +bool +Kernel_uart::init(Init_mode = Init_before_mmu) +{ return false; } + +IMPLEMENT inline +Kernel_uart::Kernel_uart() +{} + +IMPLEMENT inline +void +Kernel_uart::enable_rcv_irq() +{} diff --git a/kernel/fiasco/src/kern/kmem_alloc.cpp b/kernel/fiasco/src/kern/kmem_alloc.cpp new file mode 100644 index 00000000..54c48e96 --- /dev/null +++ b/kernel/fiasco/src/kern/kmem_alloc.cpp @@ -0,0 +1,325 @@ +INTERFACE: + +#include +#include + +#include "spin_lock.h" +#include "lock_guard.h" +#include "initcalls.h" + +class Buddy_alloc; +class Mem_region_map_base; +class Kip; + +template class Kmem_q_alloc; + +class Kmem_alloc +{ + Kmem_alloc(); + +public: + typedef Buddy_alloc Alloc; +private: + typedef Spin_lock<> Lock; + static Lock lock; + static Alloc *a; + static unsigned long _orig_free; + static Kmem_alloc *_alloc; +}; + + +class Kmem_alloc_reaper : public cxx::S_list_item +{ + size_t (*_reap)(bool desperate); + +private: + typedef cxx::S_list_bss Reaper_list; + static Reaper_list mem_reapers; +}; + +template +class Kmem_q_alloc +{ +public: + Kmem_q_alloc(Q *q, Kmem_alloc *a) : _a(a), _q(q) {} + bool valid() const { return _a && _q; } + void *alloc(unsigned long size) const + { + Auto_quota q(_q, size); + if (EXPECT_FALSE(!q)) + return 0; + + void *b; + if (EXPECT_FALSE(!(b=_a->unaligned_alloc(size)))) + return 0; + + q.release(); + return b; + } + + void free(void *block, unsigned long size) const + { + _a->unaligned_free(size, block); + _q->free(size); + } + +private: + Kmem_alloc *_a; + Q *_q; +}; + + +IMPLEMENTATION: + +#include + +#include "config.h" +#include "kdb_ke.h" +#include "kip.h" +#include "mem_layout.h" +#include "mem_region.h" +#include "buddy_alloc.h" +#include "panic.h" + +static Kmem_alloc::Alloc _a; +Kmem_alloc::Alloc *Kmem_alloc::a = &_a; +unsigned long Kmem_alloc::_orig_free; +Kmem_alloc::Lock Kmem_alloc::lock; +Kmem_alloc* Kmem_alloc::_alloc; + +PUBLIC static inline NEEDS[] +Kmem_alloc * +Kmem_alloc::allocator() +{ + assert (_alloc /* uninitialized use of Kmem_alloc */); + return _alloc; +} + + +PUBLIC template static inline NEEDS[] +Kmem_q_alloc +Kmem_alloc::q_allocator(Q *quota) +{ + assert (_alloc /* uninitialized use of Kmem_alloc */); + return Kmem_q_alloc(quota, _alloc); +} + +PROTECTED static +void +Kmem_alloc::allocator(Kmem_alloc *a) +{ + _alloc=a; +} + +PUBLIC static FIASCO_INIT +void +Kmem_alloc::init() +{ + static Kmem_alloc al; + Kmem_alloc::allocator(&al); +} + +PUBLIC +void +Kmem_alloc::dump() const +{ a->dump(); } + +PUBLIC inline NEEDS [Kmem_alloc::unaligned_alloc] +void * +Kmem_alloc::alloc(size_t o) +{ + return unaligned_alloc(1UL << o); +} + + +PUBLIC inline NEEDS [Kmem_alloc::unaligned_free] +void +Kmem_alloc::free(size_t o, void *p) +{ + unaligned_free(1UL << o, p); +} + +PUBLIC +void * +Kmem_alloc::unaligned_alloc(unsigned long size) +{ + assert(size >=8 /*NEW INTERFACE PARANIOIA*/); + void* ret; + + { + Lock_guard guard(&lock); + ret = a->alloc(size); + } + + if (!ret) + { + Kmem_alloc_reaper::morecore (/* desperate= */ true); + + Lock_guard guard (&lock); + ret = a->alloc(size); + } + + return ret; +} + +PUBLIC +void +Kmem_alloc::unaligned_free(unsigned long size, void *page) +{ + assert(size >=8 /*NEW INTERFACE PARANIOIA*/); + Lock_guard guard (&lock); + a->free(page, size); +} + + +PRIVATE static FIASCO_INIT +unsigned long +Kmem_alloc::create_free_map(Kip const *kip, Mem_region_map_base *map) +{ + unsigned long available_size = 0; + Mem_desc const *md = kip->mem_descs(); + Mem_desc const *const md_end = md + kip->num_mem_descs(); + + for (; md < md_end; ++md) + { + if (!md->valid()) + { + const_cast(md)->type(Mem_desc::Undefined); + continue; + } + + if (md->is_virtual()) + continue; + + unsigned long s = md->start(); + unsigned long e = md->end(); + + // Sweep out stupid descriptors (that have the end before the start) + + switch (md->type()) + { + case Mem_desc::Conventional: + s = (s + Config::PAGE_SIZE - 1) & ~(Config::PAGE_SIZE - 1); + e = ((e + 1) & ~(Config::PAGE_SIZE - 1)) - 1; + if (e <= s) + break; + available_size += e - s + 1; + if (!map->add(Mem_region(s, e))) + panic("Kmem_alloc::create_free_map(): memory map too small"); + break; + case Mem_desc::Reserved: + case Mem_desc::Dedicated: + case Mem_desc::Shared: + case Mem_desc::Arch: + case Mem_desc::Bootloader: + s = s & ~(Config::PAGE_SIZE - 1); + e = ((e + Config::PAGE_SIZE) & ~(Config::PAGE_SIZE - 1)) - 1; + if (!map->sub(Mem_region(s, e))) + panic("Kmem_alloc::create_free_map(): memory map too small"); + break; + default: + break; + } + } + + return available_size; +} + + +PUBLIC template< typename Q > +inline +void * +Kmem_alloc::q_alloc(Q *quota, size_t order) +{ + Auto_quota q(quota, 1UL< +inline +void * +Kmem_alloc::q_unaligned_alloc(Q *quota, size_t size) +{ + Auto_quota q(quota, size); + if (EXPECT_FALSE(!q)) + return 0; + + void *b; + if (EXPECT_FALSE(!(b=unaligned_alloc(size)))) + return 0; + + q.release(); + return b; +} + + +PUBLIC inline NEEDS["mem_layout.h"] +void Kmem_alloc::free_phys(size_t s, Address p) +{ + void *va = (void*)Mem_layout::phys_to_pmem(p); + if((unsigned long)va != ~0UL) + free(s, va); +} + +PUBLIC template< typename Q > +inline +void +Kmem_alloc::q_free_phys(Q *quota, size_t order, Address obj) +{ + free_phys(order, obj); + quota->free(1UL< +inline +void +Kmem_alloc::q_free(Q *quota, size_t order, void *obj) +{ + free(order, obj); + quota->free(1UL< +inline +void +Kmem_alloc::q_unaligned_free(Q *quota, size_t size, void *obj) +{ + unaligned_free(size, obj); + quota->free(size); +} + + + +#include "atomic.h" + +Kmem_alloc_reaper::Reaper_list Kmem_alloc_reaper::mem_reapers; + +PUBLIC inline NEEDS["atomic.h"] +Kmem_alloc_reaper::Kmem_alloc_reaper(size_t (*reap)(bool desperate)) + : _reap(reap) +{ + mem_reapers.add(this, mp_cas); +} + +PUBLIC static +size_t +Kmem_alloc_reaper::morecore(bool desperate = false) +{ + size_t freed = 0; + + for (Reaper_list::Const_iterator reaper = mem_reapers.begin(); + reaper != mem_reapers.end(); ++reaper) + { + freed += reaper->_reap(desperate); + } + + return freed; +} diff --git a/kernel/fiasco/src/kern/kmem_slab.cpp b/kernel/fiasco/src/kern/kmem_slab.cpp new file mode 100644 index 00000000..6de15446 --- /dev/null +++ b/kernel/fiasco/src/kern/kmem_slab.cpp @@ -0,0 +1,122 @@ +INTERFACE: + +#include // size_t +#include "buddy_alloc.h" +#include "config.h" +#include "lock_guard.h" +#include "spin_lock.h" + +#include "slab_cache.h" // Slab_cache +#include + +class Kmem_slab : public Slab_cache, public cxx::S_list_item +{ + friend class Jdb_kern_info_memory; + typedef cxx::S_list_bss Reap_list; + + // STATIC DATA + static Reap_list reap_list; +}; + +template< typename T > +class Kmem_slab_t : public Kmem_slab +{ +public: + explicit Kmem_slab_t(char const *name) + : Kmem_slab(sizeof(T), __alignof(T), name) {} +}; + +IMPLEMENTATION: + +Kmem_slab::Reap_list Kmem_slab::reap_list; + +// Kmem_slab -- A type-independent slab cache allocator for Fiasco, +// derived from a generic slab cache allocator (Slab_cache in +// lib/slab.cpp). + +// This specialization adds low-level page allocation and locking to +// the slab allocator implemented in our base class (Slab_cache). +//- + +#include +#include "config.h" +#include "atomic.h" +#include "panic.h" +#include "kmem_alloc.h" + +// Specializations providing their own block_alloc()/block_free() can +// also request slab sizes larger than one page. +PROTECTED +Kmem_slab::Kmem_slab(unsigned long slab_size, + unsigned elem_size, + unsigned alignment, + char const *name) + : Slab_cache(slab_size, elem_size, alignment, name) +{ + reap_list.add(this, mp_cas); +} + +// Specializations providing their own block_alloc()/block_free() can +// also request slab sizes larger than one page. +PUBLIC +Kmem_slab::Kmem_slab(unsigned elem_size, + unsigned alignment, + char const *name, + unsigned long min_size = Buddy_alloc::Min_size, + unsigned long max_size = Buddy_alloc::Max_size) + : Slab_cache(elem_size, alignment, name, min_size, max_size) +{ + reap_list.add(this, mp_cas); +} + +PUBLIC +Kmem_slab::~Kmem_slab() +{ + destroy(); +} + + +// Callback functions called by our super class, Slab_cache, to +// allocate or free blocks + +virtual void * +Kmem_slab::block_alloc(unsigned long size, unsigned long) +{ + assert (size >= Buddy_alloc::Min_size); + assert (size <= Buddy_alloc::Max_size); + assert (!(size & (size - 1))); + (void)size; + return Kmem_alloc::allocator()->unaligned_alloc(size); +} + +virtual void +Kmem_slab::block_free(void *block, unsigned long size) +{ + Kmem_alloc::allocator()->unaligned_free(size, block); +} + +// +// Memory reaper +// +PUBLIC static +size_t +Kmem_slab::reap_all (bool desperate) +{ + size_t freed = 0; + + for (Reap_list::Const_iterator alloc = reap_list.begin(); + alloc != reap_list.end(); ++alloc) + { + size_t got; + do + { + got = alloc->reap(); + freed += got; + } + while (desperate && got); + } + + return freed; +} + +static Kmem_alloc_reaper kmem_slab_reaper(Kmem_slab::reap_all); diff --git a/kernel/fiasco/src/kern/kobject.cpp b/kernel/fiasco/src/kern/kobject.cpp new file mode 100644 index 00000000..cd109d3c --- /dev/null +++ b/kernel/fiasco/src/kern/kobject.cpp @@ -0,0 +1,249 @@ +INTERFACE: + +#include "lock.h" +#include "obj_space.h" +#include + + +class Kobject_mappable +{ +private: + friend class Kobject_mapdb; + friend class Jdb_mapdb; + + Obj::Mapping::List _root; + Smword _cnt; + Lock _lock; + +public: + Kobject_mappable() : _cnt(0) {} + bool no_mappings() const { return _root.empty(); } + + /** + * Insert the root mapping of an object. + */ + template + bool insert(void *, Space *, M &m) + { + m._c->put_as_root(); + _root.add(m._c); + _cnt = 1; + return true; + } + + Smword cap_ref_cnt() const { return _cnt; } +}; + + +//---------------------------------------------------------------------------- +INTERFACE: + +#include "context.h" +#include "kobject_dbg.h" +#include "kobject_iface.h" +#include "l4_error.h" +#include "rcupdate.h" +#include "space.h" + +class Kobject : + public Kobject_iface, + private Kobject_mappable, + private Kobject_dbg +{ + template + friend class Map_traits; + +private: + template + class Tconv {}; + + template + class Tconv { public: typedef T Base; }; + +public: + template + static T dcast(Kobject_common *_o) + { + if (EXPECT_FALSE(!_o)) + return 0; + + if (EXPECT_TRUE(_o->kobj_type() == Tconv::Base::static_kobj_type)) + return reinterpret_cast(_o->kobject_start_addr()); + return 0; + } + + template + static T dcast(Kobject_common const *_o) + { + if (EXPECT_FALSE(!_o)) + return 0; + + if (EXPECT_TRUE(_o->kobj_type() == Tconv::Base::static_kobj_type)) + return reinterpret_cast(_o->kobject_start_addr()); + return 0; + } + + using Kobject_dbg::dbg_id; + + Lock existence_lock; + +public: + Kobject *_next_to_reap; + +public: + enum Op { + O_dec_refcnt = 0, + }; + +}; + +#define FIASCO_DECLARE_KOBJ() \ + public: static char const *const static_kobj_type; \ + char const *kobj_type() const; \ + Address kobject_start_addr() const; \ + Mword kobject_size() const; + +#define FIASCO_DEFINE_KOBJ(t) \ + char const *const t::static_kobj_type = #t; \ + char const *t::kobj_type() const { return static_kobj_type; } \ + Address t::kobject_start_addr() const { return (Address)this; } \ + Mword t::kobject_size() const { return sizeof(*this); } + + +//--------------------------------------------------------------------------- +IMPLEMENTATION: + +#include "logdefs.h" +#include "l4_buf_iter.h" +#include "lock_guard.h" + + +PUBLIC bool Kobject::is_local(Space *) const { return false; } +PUBLIC Mword Kobject::obj_id() const { return ~0UL; } +PUBLIC virtual bool Kobject::put() { return true; } +PUBLIC Kobject_mappable *Kobject::map_root() { return this; } + +PUBLIC inline NEEDS["lock_guard.h"] +Smword +Kobject_mappable::dec_cap_refcnt(Smword diff) +{ + Lock_guard g(&_lock); + _cnt -= diff; + return _cnt; +} + +PUBLIC +void +Kobject::initiate_deletion(Kobject ***reap_list) +{ + existence_lock.invalidate(); + + _next_to_reap = 0; + **reap_list = this; + *reap_list = &_next_to_reap; +} + +PUBLIC virtual +void +Kobject::destroy(Kobject ***) +{ + LOG_TRACE("Kobject destroy", "des", current(), __fmt_kobj_destroy, + Log_destroy *l = tbe->payload(); + l->id = dbg_id(); + l->obj = this; + l->type = kobj_type()); + existence_lock.wait_free(); +} + +PUBLIC virtual +Kobject::~Kobject() +{ + LOG_TRACE("Kobject delete (generic)", "del", current(), __fmt_kobj_destroy, + Log_destroy *l = tbe->payload(); + l->id = dbg_id(); + l->obj = this; + l->type = "unk"); +} + + +PRIVATE inline NOEXPORT +L4_msg_tag +Kobject::sys_dec_refcnt(L4_msg_tag tag, Utcb const *in, Utcb *out) +{ + if (tag.words() < 2) + return Kobject_iface::commit_result(-L4_err::EInval); + + Smword diff = in->values[1]; + out->values[0] = dec_cap_refcnt(diff); + return Kobject_iface::commit_result(0); +} + +PUBLIC +L4_msg_tag +Kobject::kobject_invoke(L4_obj_ref, Mword /*rights*/, + Syscall_frame *f, + Utcb const *in, Utcb *out) +{ + L4_msg_tag tag = f->tag(); + + if (EXPECT_FALSE(tag.words() < 1)) + return Kobject_iface::commit_result(-L4_err::EInval); + + switch (in->values[0]) + { + case O_dec_refcnt: + return sys_dec_refcnt(tag, in, out); + default: + return Kobject_iface::commit_result(-L4_err::ENosys); + } + +} + +//--------------------------------------------------------------------------- +INTERFACE [debug]: + +#include "tb_entry.h" + +EXTENSION class Kobject +{ +protected: + struct Log_destroy + { + Kobject *obj; + Mword id; + char const *type; + Mword ram; + }; + + static unsigned log_fmt(Tb_entry *, int max, char *buf) asm ("__fmt_kobj_destroy"); +}; + +//--------------------------------------------------------------------------- +IMPLEMENTATION [debug]: + +PUBLIC static inline +Kobject * +Kobject::from_dbg(Kobject_dbg *d) +{ return static_cast(d); } + +PUBLIC static inline +Kobject * +Kobject::from_dbg(Kobject_dbg::Iterator const &d) +{ + if (d != Kobject_dbg::end()) + return static_cast(*d); + return 0; +} + +PUBLIC +Kobject_dbg * +Kobject::dbg_info() const +{ return const_cast(this); } + +IMPLEMENT +unsigned +Kobject::log_fmt(Tb_entry *e, int max, char *buf) +{ + Log_destroy *l = e->payload(); + return snprintf(buf, max, "obj=%lx [%s] (%p) ram=%lx", l->id, l->type, l->obj, l->ram); +} diff --git a/kernel/fiasco/src/kern/kobject_dbg.cpp b/kernel/fiasco/src/kern/kobject_dbg.cpp new file mode 100644 index 00000000..7d1b1503 --- /dev/null +++ b/kernel/fiasco/src/kern/kobject_dbg.cpp @@ -0,0 +1,175 @@ +INTERFACE: + +class Kobject_dbg +{ +}; + +//---------------------------------------------------------------------------- +INTERFACE[debug]: + +#include "spin_lock.h" +#include "lock_guard.h" +#include +#include + +class Kobject; + +EXTENSION class Kobject_dbg : public cxx::D_list_item +{ + friend class Jdb_kobject; + friend class Jdb_kobject_list; + friend class Jdb_mapdb; + +public: + class Dbg_extension : public cxx::H_list_item + { + public: + virtual ~Dbg_extension() = 0; + }; + +public: + typedef cxx::H_list Dbg_ext_list; + Dbg_ext_list _jdb_data; + +private: + Mword _dbg_id; + +public: + Mword dbg_id() const { return _dbg_id; } + virtual Address kobject_start_addr() const = 0; + virtual Mword kobject_size() const = 0; + virtual ~Kobject_dbg() = 0; + + + typedef cxx::D_list Kobject_list; + typedef Kobject_list::Iterator Iterator; + typedef Kobject_list::Const_iterator Const_iterator; + + static Spin_lock<> _kobjects_lock; + static Kobject_list _kobjects; + + static Iterator begin() { return _kobjects.begin(); } + static Iterator end() { return _kobjects.end(); } + +private: + static unsigned long _next_dbg_id; +}; + + +//---------------------------------------------------------------------------- +IMPLEMENTATION[debug]: +#include "static_init.h" +Spin_lock<> Kobject_dbg::_kobjects_lock; +Kobject_dbg::Kobject_list Kobject_dbg::_kobjects INIT_PRIORITY(101); +unsigned long Kobject_dbg::_next_dbg_id; + +IMPLEMENT inline Kobject_dbg::Dbg_extension::~Dbg_extension() {} + +PUBLIC static +Kobject_dbg::Iterator +Kobject_dbg::pointer_to_obj(void const *p) +{ + for (Iterator l = _kobjects.begin(); l != _kobjects.end(); ++l) + { + Mword a = l->kobject_start_addr(); + if (a <= Mword(p) && Mword(p) < (a + l->kobject_size())) + return l; + } + return _kobjects.end(); +} + +PUBLIC static +unsigned long +Kobject_dbg::pointer_to_id(void const *p) +{ + Iterator o = pointer_to_obj(p); + if (o != _kobjects.end()) + return o->dbg_id(); + return ~0UL; +} + +PUBLIC static +bool +Kobject_dbg::is_kobj(void const *o) +{ + return pointer_to_obj(o) != _kobjects.end(); +} + +PUBLIC static +Kobject_dbg::Iterator +Kobject_dbg::id_to_obj(unsigned long id) +{ + for (Iterator l = _kobjects.begin(); l != _kobjects.end(); ++l) + { + if (l->dbg_id() == id) + return l; + } + return end(); +} + +PUBLIC static +unsigned long +Kobject_dbg::obj_to_id(void const *o) +{ + return pointer_to_id(o); +} + + +PROTECTED +Kobject_dbg::Kobject_dbg() +{ + Lock_guard guard(&_kobjects_lock); + + _dbg_id = _next_dbg_id++; + _kobjects.push_back(this); +} + +IMPLEMENT inline +Kobject_dbg::~Kobject_dbg() +{ + { + Lock_guard guard(&_kobjects_lock); + _kobjects.remove(this); + } + + while (Dbg_extension *ex = _jdb_data.front()) + delete ex; +} + +//--------------------------------------------------------------------------- +IMPLEMENTATION [!debug]: + +PUBLIC inline +unsigned long +Kobject_dbg::dbg_id() const +{ return 0; } + +PUBLIC static inline +unsigned long +Kobject_dbg::dbg_id(void const *) +{ return ~0UL; } + +PUBLIC static inline +Kobject_dbg * +Kobject_dbg::pointer_to_obj(void const *) +{ return 0; } + +PUBLIC static inline +unsigned long +Kobject_dbg::pointer_to_id(void const *) +{ return ~0UL; } + +PUBLIC static +bool +Kobject_dbg::is_kobj(void const *) +{ return false; } + +PUBLIC static +Kobject_dbg * +Kobject_dbg::id_to_obj(unsigned long) +{ return 0; } + +PUBLIC static +unsigned long +Kobject_dbg::obj_to_id(void const *) +{ return ~0UL; } diff --git a/kernel/fiasco/src/kern/kobject_helper.cpp b/kernel/fiasco/src/kern/kobject_helper.cpp new file mode 100644 index 00000000..8ec6a804 --- /dev/null +++ b/kernel/fiasco/src/kern/kobject_helper.cpp @@ -0,0 +1,67 @@ +INTERFACE: + +#include "kobject.h" +#include "thread.h" + +class Kobject_helper_base +{ +protected: + static Mword _utcb_dummy[]; + static Utcb *utcb_dummy() + { + char *x = reinterpret_cast(&_utcb_dummy); + return reinterpret_cast(x); + } + + static L4_msg_tag no_reply() { return L4_msg_tag(L4_msg_tag::Schedule); } + static bool have_receive(Utcb *rcv) { return rcv != utcb_dummy(); } +}; + +template +class Kobject_h : public Base, protected Kobject_helper_base +{ +private: + static Sender *_sender(Thread *, Sender *t) { return t; } + static Sender *_sender(Thread *ct, ...) { return ct; } + +public: + + explicit Kobject_h() : Base() {} + + template< typename A > + explicit Kobject_h(A a) : Base(a) {} + + void invoke(L4_obj_ref self, Mword rights, Syscall_frame *f, Utcb *u) + { + L4_msg_tag res(0); + if (EXPECT_TRUE(self.op() & L4_obj_ref::Ipc_send)) + res = static_cast(this)->T::kinvoke(self, rights, f, (Utcb const *)u, + self.have_recv() ? u : utcb_dummy()); + + if (EXPECT_FALSE(res.has_error())) + { + f->tag(res); + return; + } + + if (self.have_recv()) + { + if (!res.do_switch()) + { + Thread *t = current_thread(); + Sender *s = (self.op() & L4_obj_ref::Ipc_open_wait) ? 0 : _sender(t, static_cast(this)); + t->do_ipc(f->tag(), 0, 0, true, s, f->timeout(), f, rights); + return; + } + else + f->tag(res); + } + } + +}; + + +IMPLEMENTATION: + +Mword Kobject_helper_base::_utcb_dummy[(sizeof(Utcb) + sizeof(Mword) - 1) / sizeof(Mword)]; + diff --git a/kernel/fiasco/src/kern/kobject_iface.cpp b/kernel/fiasco/src/kern/kobject_iface.cpp new file mode 100644 index 00000000..73850393 --- /dev/null +++ b/kernel/fiasco/src/kern/kobject_iface.cpp @@ -0,0 +1,63 @@ +INTERFACE: + +#include "l4_types.h" + +class Kobject; +class Kobject_dbg; +class Kobject_mappable; + +class Space; +class Syscall_frame; +class Utcb; + +class Kobject_common +{ +public: + virtual char const *kobj_type() const = 0; + virtual Address kobject_start_addr() const = 0; + + virtual bool is_local(Space *) const = 0; + virtual Mword obj_id() const = 0; + virtual void initiate_deletion(Kobject ***) = 0; + + virtual Kobject_mappable *map_root() = 0; + virtual ~Kobject_common() = 0; +}; + +class Kobject_iface : public Kobject_common +{ +public: + virtual void invoke(L4_obj_ref self, Mword rights, Syscall_frame *, Utcb *) = 0; +}; + +IMPLEMENTATION: + +IMPLEMENT inline Kobject_common::~Kobject_common() {} + +PUBLIC static inline +L4_msg_tag +Kobject_iface::commit_result(Mword error, + unsigned words = 0, unsigned items = 0) +{ + return L4_msg_tag(words, items, 0, error); +} + +PUBLIC static inline +L4_msg_tag +Kobject_iface::commit_error(Utcb const *utcb, L4_error const &e, + L4_msg_tag const &tag = L4_msg_tag(0, 0, 0, 0)) +{ + const_cast(utcb)->error = e; + return L4_msg_tag(tag, L4_msg_tag::Error); +} + +PUBLIC virtual +Kobject_iface * +Kobject_iface::downgrade(unsigned long del_attribs) +{ (void)del_attribs; return this; } + + +// ------------------------------------------------------------------------ +IMPLEMENTATION [debug]: + +PUBLIC virtual Kobject_dbg *Kobject_common::dbg_info() const = 0; diff --git a/kernel/fiasco/src/kern/kobject_mapdb.cpp b/kernel/fiasco/src/kern/kobject_mapdb.cpp new file mode 100644 index 00000000..3e78478f --- /dev/null +++ b/kernel/fiasco/src/kern/kobject_mapdb.cpp @@ -0,0 +1,184 @@ +INTERFACE: + +#include "types.h" +#include "space.h" +#include "kobject.h" + +class Kobject; + +/** A mapping database. + */ +class Kobject_mapdb +{ +public: + // TYPES + + typedef Obj_space::Phys_addr Phys_addr; + typedef Obj_space::Addr Vaddr; + typedef Obj::Mapping Mapping; + + class Iterator; + class Frame + { + friend class Kobject_mapdb; + friend class Kobject_mapdb::Iterator; + Kobject_mappable* frame; + + public: + inline size_t size() const; + }; + + /** + * We'll never iterate over some thing, because we have + * no child relationship for capability passing. + */ + class Iterator + { + public: + inline Mapping* operator->() const { return 0; } + inline Mapping* operator * () const { return 0; } + inline operator Mapping*() const { return 0; } + Iterator() {} + + Iterator(Frame const &, Mapping *, Page_number, Page_number) {} + + Iterator &operator ++ () { return *this; } + }; +}; + + +// --------------------------------------------------------------------------- +IMPLEMENTATION: + +#include + +#include "config.h" +#include "globals.h" +#include "std_macros.h" + +PUBLIC inline static +bool +Kobject_mapdb::lookup(Space *, Vaddr va, Phys_addr obj, + Mapping** out_mapping, Frame* out_lock) +{ + Kobject_mappable *rn = obj->map_root(); + rn->_lock.lock(); + if (va._c->obj() == obj) + { + *out_mapping = va._c; + out_lock->frame = rn; + return true; + } + + rn->_lock.clear(); + return false; +} + +PUBLIC static inline +bool +Kobject_mapdb::valid_address(Phys_addr obj) +{ return obj; } + + +// FAKE +PUBLIC static inline +Page_number +Kobject_mapdb::vaddr(const Frame&, Mapping*) +{ return Page_number(0); } + +PUBLIC inline +Kobject_mapdb::Mapping * +Kobject_mapdb::check_for_upgrade(Obj_space::Phys_addr, + Space *, Page_number, + Space *, Page_number, + Frame *) +{ + // Hm we never or seldomly do upgrades on cap anyway + return 0; +} + +PUBLIC inline static +Kobject_mapdb::Mapping * +Kobject_mapdb::insert(const Frame&, Mapping*, Space *, + Vaddr va, Obj_space::Phys_addr o, Page_count size) +{ + (void)size; + (void)o; + assert (size.value() == 1); + + Mapping *m = va._c; + Kobject_mappable *rn = o->map_root(); + //LOG_MSG_3VAL(current(), "ins", o->dbg_id(), (Mword)m, (Mword)va._a.value()); + rn->_root.add(m); + + Obj::Entry *e = static_cast(m); + if (e->ref_cnt()) // counted + ++rn->_cnt; + + return m; +} + +PUBLIC inline static +bool +Kobject_mapdb::grant(const Frame &f, Mapping *sm, Space *, + Vaddr va) +{ + Obj::Entry *re = va._c; + Obj::Entry *se = static_cast(sm); + //LOG_MSG_3VAL(current(), "gra", f.frame->dbg_id(), (Mword)sm, (Mword)va._a.value()); + + // replace the source cap with the destination cap in the list + Mapping::List::replace(se, re); + + if (se->ref_cnt() && !re->ref_cnt()) + --f.frame->_cnt; + + return true; +} + +PUBLIC inline +static void +Kobject_mapdb::free (const Frame& f) +{ + f.frame->_lock.clear(); +} // free() + +PUBLIC static +void +Kobject_mapdb::flush(const Frame& f, Mapping *m, L4_map_mask mask, + Page_number, Page_number) +{ + //LOG_MSG_3VAL(current(), "unm", f.frame->dbg_id(), (Mword)m, 0); + if (!mask.self_unmap()) + return; + + bool flush = false; + + if (mask.do_delete() && m->delete_rights()) + flush = true; + else + { + Obj::Entry *e = static_cast(m); + if (e->ref_cnt()) // counted + flush = --f.frame->_cnt <= 0; + + if (!flush) + Mapping::List::remove(m); + } + + if (flush) + { + for (Mapping::List::Iterator i = f.frame->_root.begin(); + i != Mapping::List::end(); ++i) + { + Obj::Entry *e = static_cast(*i); + if (e->ref_cnt()) // counted + --f.frame->_cnt; + e->invalidate(); + } + f.frame->_root.clear(); + } + +} // flush() + + diff --git a/kernel/fiasco/src/kern/koptions-def.h b/kernel/fiasco/src/kern/koptions-def.h new file mode 100644 index 00000000..e3e8bf0b --- /dev/null +++ b/kernel/fiasco/src/kern/koptions-def.h @@ -0,0 +1,75 @@ +#pragma once + +#include "types.h" + +// To generate the kernel version: +// perl -p -e 's/l4_uint(\d+)_t/Unsigned$1/;s/^#inc.+/#include "types.h"/' koptions-def.h + +namespace L4_kernel_options +{ + enum Flags + { + F_wait = 1 << 0, + F_serial_esc = 1 << 1, + F_noserial = 1 << 2, + F_noscreen = 1 << 3, + F_esc = 1 << 4, + F_nojdb = 1 << 5, + F_nokdb = 1 << 6, + F_nohlt = 1 << 7, + F_apic = 1 << 8, + F_loadcnt = 1 << 9, + F_watchdog = 1 << 10, + F_irq0 = 1 << 13, + F_nosfn = 1 << 15, + F_jdb_never_stop = 1 << 16, + + F_kmemsize = 1 << 17, + F_tbuf_entries = 1 << 18, + F_out_buf = 1 << 19, + F_uart_baud = 1 << 20, + F_uart_base = 1 << 21, + F_uart_irq = 1 << 22, + + F_jdb_cmd = 1 << 23, + }; + + enum + { + Magic = 0x4C344B43, + }; + + enum Uart_type + { + Uart_type_invalid = 0, + Uart_type_ioport = 1, + Uart_type_mmio = 2, + }; + + struct Uart + { + Unsigned32 access_type; ///< Accesstype of UART: unset, MMIO or ports + Unsigned32 baud; ///< Baud rate + Unsigned32 irqno; ///< (Receive) IRQ + Unsigned64 base_address; ///< Start address of UART + } __attribute__((packed)); + + struct Options + { + Unsigned32 magic; ///< Magic value + Unsigned32 version; ///< Version of this structure + + Unsigned32 flags; ///< Option flags + + Unsigned32 kmemsize; ///< Wanted kernel memory size in KiB + + Uart uart; ///< Kernel UART + + char jdb_cmd[128]; + Unsigned32 tbuf_entries; + Unsigned32 out_buf; + + Unsigned32 opt(Flags flag) const { return flags & flag; } + + } __attribute__((packed)); +}; diff --git a/kernel/fiasco/src/kern/koptions.cpp b/kernel/fiasco/src/kern/koptions.cpp new file mode 100644 index 00000000..b94b5968 --- /dev/null +++ b/kernel/fiasco/src/kern/koptions.cpp @@ -0,0 +1,30 @@ +INTERFACE: + +#include "koptions-def.h" + +namespace Koptions { + using namespace L4_kernel_options; + + Options *o(); +}; + +IMPLEMENTATION: + +namespace Koptions_ns +{ + Koptions::Options o __attribute__((section(".koptions"))) = + { + Koptions::Magic, + 0, // version + 0, // flags + 0, // kmemsize + { 0, 0, 0, 0 }, // uart + "", // jdb_cmd + 0, // tbuf_entries + 0, // out_buf + }; +} + +namespace Koptions { + Options *o() { return &Koptions_ns::o; } +}; diff --git a/kernel/fiasco/src/kern/l4_buf_iter.cpp b/kernel/fiasco/src/kern/l4_buf_iter.cpp new file mode 100644 index 00000000..7da0a801 --- /dev/null +++ b/kernel/fiasco/src/kern/l4_buf_iter.cpp @@ -0,0 +1,112 @@ +INTERFACE: + +#include +#include +#include +#include + +class L4_buf_iter +{ +public: + struct Item + { + L4_msg_item b; + Mword d; + + Item() : b(0) +#ifndef NDEBUG + , d(0) +#endif + {} + }; + + explicit L4_buf_iter(Utcb const *utcb, unsigned start) + : _buf(&utcb->buffers[start]), _max(&utcb->buffers[Utcb::Max_buffers]) + { next(); } + bool more() const { return _buf < _max; } + Item const *get() const { return &c; } + bool next(); + +private: + Mword const *_buf; + Mword const *const _max; + Item c; +}; + +class L4_snd_item_iter +{ +public: + struct Item + { + L4_msg_item b; + Mword d; + + Item() + : b(0) +#ifndef NDEBUG + , d(0) +#endif + {} + }; + + explicit L4_snd_item_iter(Utcb const *utcb, unsigned offset) + : _buf(&utcb->values[offset]), + _max(&utcb->values[Utcb::Max_words]) {} + bool more() const { return _buf < _max; } + Item const *get() const { return &c; } + bool next(); + +private: + Mword const *_buf; + Mword const *const _max; + Item c; +}; + +//---------------------------------------------------------------------------- +IMPLEMENTATION: + +IMPLEMENT inline +bool +L4_buf_iter::next() +{ + c.b = L4_msg_item(_buf[0]); + if (EXPECT_FALSE(c.b.is_void())) + return false; + + if (c.b.type() == L4_msg_item::Map && c.b.is_small_obj()) + c.d = c.b.get_small_buf().raw(); + else + { + ++_buf; + if (EXPECT_FALSE(_buf >= _max)) + { + c.b = L4_msg_item(0); + return false; + } + + c.d = _buf[0]; + } + ++_buf; + return true; +} + + +IMPLEMENT inline +bool +L4_snd_item_iter::next() +{ + c.b = L4_msg_item(_buf[0]); + + ++_buf; + + if (EXPECT_FALSE(c.b.is_void())) + return true; + + if (EXPECT_FALSE(_buf >= _max)) + return false; + + c.d = _buf[0]; + + ++_buf; + return true; +} diff --git a/kernel/fiasco/src/kern/libc_backend_lock.cc b/kernel/fiasco/src/kern/libc_backend_lock.cc new file mode 100644 index 00000000..df3658e1 --- /dev/null +++ b/kernel/fiasco/src/kern/libc_backend_lock.cc @@ -0,0 +1,15 @@ +#include + +#include + +static Spin_lock<> __libc_backend_printf_spinlock; + +unsigned long __libc_backend_printf_lock() +{ + return __libc_backend_printf_spinlock.test_and_set(); +} + +void __libc_backend_printf_unlock(unsigned long state) +{ + __libc_backend_printf_spinlock.set(state); +} diff --git a/kernel/fiasco/src/kern/lock.cpp b/kernel/fiasco/src/kern/lock.cpp new file mode 100644 index 00000000..f4fc244e --- /dev/null +++ b/kernel/fiasco/src/kern/lock.cpp @@ -0,0 +1,11 @@ +INTERFACE [!mp]: + +#include + +typedef Helping_lock Lock; + +INTERFACE [mp]: + +#include + +typedef Mp_lock Lock; diff --git a/kernel/fiasco/src/kern/map_util-mem.cpp b/kernel/fiasco/src/kern/map_util-mem.cpp new file mode 100644 index 00000000..32110b5d --- /dev/null +++ b/kernel/fiasco/src/kern/map_util-mem.cpp @@ -0,0 +1,186 @@ +INTERFACE [debug]: + +#include "mapdb.h" +#include "types.h" + +extern Static_object mapdb_mem; + + +IMPLEMENTATION: + +#include "config.h" +#include "mapdb.h" + +Static_object mapdb_mem; + +/** Map the region described by "fp_from" of address space "from" into + region "fp_to" at offset "offs" of address space "to", updating the + mapping database as we do so. + @param from source address space + @param fp_from_{page, size, write, grant} flexpage description for + virtual-address space range in source address space + @param to destination address space + @param fp_to_{page, size} flexpage descripton for virtual-address + space range in destination address space + @param offs sender-specified offset into destination flexpage + @return IPC error code that describes the status of the operation + */ +L4_error __attribute__((nonnull(1, 3))) +mem_map(Space *from, L4_fpage const &fp_from, + Space *to, L4_fpage const &fp_to, L4_msg_item control) +{ + typedef Map_traits Mt; + + if (EXPECT_FALSE(fp_from.order() < L4_fpage::Mem_addr::Shift + || fp_to.order() < L4_fpage::Mem_addr::Shift)) + return L4_error::None; + + // loop variables + Mt::Addr rcv_addr = fp_to.mem_address(); + Mt::Addr snd_addr = fp_from.mem_address(); + Mt::Addr offs = Virt_addr(control.address()); + + Mt::Size snd_size = Mt::Size::from_shift(fp_from.order() - L4_fpage::Mem_addr::Shift); + Mt::Size rcv_size = Mt::Size::from_shift(fp_to.order() - L4_fpage::Mem_addr::Shift); + + // calc size in bytes from power of tows + snd_addr = snd_addr.trunc(snd_size); + rcv_addr = rcv_addr.trunc(rcv_size); + Mt::constraint(snd_addr, snd_size, rcv_addr, rcv_size, offs); + + if (snd_size == 0) + return L4_error::None; + + unsigned long del_attribs, add_attribs; + Mt::attribs(control, fp_from, &del_attribs, &add_attribs); + + return map(mapdb_mem.get(), + from, from, snd_addr, + snd_size, to, to, + rcv_addr, control.is_grant(), add_attribs, del_attribs, + (Mem_space::Reap_list**)0); +} + +/** Unmap the mappings in the region described by "fp" from the address + space "space" and/or the address spaces the mappings have been + mapped into. + @param space address space that should be flushed + @param fp flexpage descriptor of address-space range that should + be flushed + @param me_too If false, only flush recursive mappings. If true, + additionally flush the region in the given address space. + @param restriction Only flush specific task ID. + @param flush_mode determines which access privileges to remove. + @return combined (bit-ORed) access status of unmapped physical pages +*/ +unsigned __attribute__((nonnull(1))) +mem_fpage_unmap(Space *space, L4_fpage fp, L4_map_mask mask) +{ + typedef Map_traits Mt; + Mt::Size size = Mt::Size::from_shift(fp.order() - L4_fpage::Mem_addr::Shift); + Mt::Addr start = Mt::get_addr(fp); + + start = start.trunc(size); + + return unmap(mapdb_mem.get(), space, space, + start, size, + fp.rights(), mask, (Mem_space::Reap_list**)0); +} + +static inline +void +save_access_attribs(Mapdb* mapdb, const Mapdb::Frame& mapdb_frame, + Mapping* mapping, Mem_space* space, unsigned page_rights, + Mem_space::Addr virt, Mem_space::Phys_addr phys, + Mem_space::Size size, + bool me_too) +{ + typedef Mem_space::Size Size; + typedef Mem_space::Addr Addr; + typedef Mem_space::Phys_addr Phys_addr; + + if (unsigned page_accessed + = page_rights & (Mem_space::Page_referenced | Mem_space::Page_dirty)) + { + Mem_space::Status status; + + // When flushing access attributes from our space as well, + // cache them in parent space, otherwise in our space. + if (! me_too || !mapping->parent()) + { + status = space->v_insert(phys, virt, size, + page_accessed); + } + else + { + Mapping *parent = mapping->parent(); + + assert (parent->space()); + Mem_space *parent_space = parent->space(); + + Address parent_shift = mapdb->shift(mapdb_frame, parent) + Mem_space::Page_shift; + Address parent_address = parent->page().value() << parent_shift; + + status = + parent_space->v_insert(phys.trunc(Phys_addr::create(1UL << parent_shift)), + Addr::create(parent_address), + Size::create(1UL << parent_shift), + page_accessed, true); + } + + assert (status == Mem_space::Insert_ok + || status == Mem_space::Insert_warn_exists + || status == Mem_space::Insert_warn_attrib_upgrade + /*|| s->is_sigma0()*/); + // Be forgiving to sigma0 because it's address + // space is not kept in sync with its mapping-db + // entries. + } +} + +//--------------------------------------------------------------------------- +IMPLEMENTATION[!64bit]: + +/** The mapping database. + This is the system's instance of the mapping database. + */ +void +init_mapdb_mem(Space *sigma0) +{ + static size_t const page_sizes[] + = { Config::SUPERPAGE_SHIFT - Config::PAGE_SHIFT, 0 }; + + mapdb_mem.construct(sigma0, + Page_number::create(1U << (32 - Config::SUPERPAGE_SHIFT)), + page_sizes, 2); +} + +//--------------------------------------------------------------------------- +IMPLEMENTATION[amd64]: + +#include "cpu.h" + +/** The mapping database. + This is the system's instance of the mapping database. + */ +void +init_mapdb_mem(Space *sigma0) +{ + static size_t const amd64_page_sizes[] = + { Config::PML4E_SHIFT - Config::PAGE_SHIFT, + Config::PDPE_SHIFT - Config::PAGE_SHIFT, + Config::SUPERPAGE_SHIFT - Config::PAGE_SHIFT, + 0}; + + unsigned const num_page_sizes = Cpu::boot_cpu()->phys_bits() >= 42 ? 4 : 3; + + Address const largest_page_max_index = num_page_sizes == 4 ? + Config::PML4E_MASK + 1ULL + : 1ULL << (Cpu::boot_cpu()->phys_bits() - Config::PDPE_SHIFT); + + size_t const *const page_sizes = num_page_sizes == 4 ? amd64_page_sizes : amd64_page_sizes + 1; + + mapdb_mem.construct(sigma0, Page_number::create(largest_page_max_index), + page_sizes, num_page_sizes); +} + diff --git a/kernel/fiasco/src/kern/map_util-objs.cpp b/kernel/fiasco/src/kern/map_util-objs.cpp new file mode 100644 index 00000000..d8b0c27a --- /dev/null +++ b/kernel/fiasco/src/kern/map_util-objs.cpp @@ -0,0 +1,152 @@ +INTERFACE: + +#include "kobject_mapdb.h" + + +IMPLEMENTATION: + +#include "assert.h" +#include "assert_opt.h" + +#include "obj_space.h" +#include "l4_types.h" +#include "mappable.h" + +inline NEEDS["assert_opt.h"] +void +save_access_attribs (Kobject_mapdb* /*mapdb*/, + const Kobject_mapdb::Frame& /*mapdb_frame*/, + Kobject_mapdb::Mapping* /*mapping*/, Obj_space* /*space*/, + unsigned /*page_rights*/, + Obj_space::Addr /*virt*/, Obj_space::Phys_addr /*phys*/, Obj_space::Size /*size*/, + bool /*me_too*/) +{} + +L4_error +obj_map(Space *from, L4_fpage const &fp_from, + Space *to, L4_fpage const &fp_to, L4_msg_item control, + Kobject ***reap_list) +{ + assert_opt (from); + assert_opt (to); + + typedef Map_traits Mt; + Mt::Addr rcv_addr = Mt::get_addr(fp_to); + Mt::Addr snd_addr = Mt::get_addr(fp_from); + Mt::Size snd_size = Mt::Size::from_shift(fp_from.order()); + Mt::Size rcv_size = Mt::Size::from_shift(fp_to.order()); + Mt::Addr offs(control.index()); + + snd_addr = snd_addr.trunc(snd_size); + rcv_addr = rcv_addr.trunc(rcv_size); + + Mt::constraint(snd_addr, snd_size, rcv_addr, rcv_size, offs); + + if (snd_size == 0) + return L4_error::None; + + unsigned long del_attribs, add_attribs; + Mt::attribs(control, fp_from, &del_attribs, &add_attribs); + + return map((Kobject_mapdb*)0, + from, from, snd_addr, + snd_size, + to, to, rcv_addr, + control.is_grant(), add_attribs, del_attribs, + reap_list); +} + +unsigned __attribute__((nonnull(1))) +obj_fpage_unmap(Space * space, L4_fpage fp, L4_map_mask mask, + Kobject ***reap_list) +{ + assert_opt (space); + typedef Map_traits Mt; + Mt::Size size = Mt::Size::from_shift(fp.order()); + Mt::Addr addr = Mt::get_addr(fp); + addr = addr.trunc(size); + + // XXX prevent unmaps when a task has no caps enabled + + return unmap((Kobject_mapdb*)0, space, space, + addr, size, + fp.rights(), mask, reap_list); +} + + +L4_error +obj_map(Space *from, unsigned long snd_addr, unsigned long snd_size, + Space *to, unsigned long rcv_addr, + Kobject ***reap_list, bool grant = false, + unsigned attrib_add = 0, unsigned attrib_del = 0) +{ + assert_opt (from); + assert_opt (to); + typedef Map_traits Mt; + + return map((Kobject_mapdb*)0, + from, from, Mt::Addr(snd_addr), + Mt::Size(snd_size), + to, to, Mt::Addr(rcv_addr), + grant, attrib_add, attrib_del, reap_list); +} + +bool +map(Kobject_iface *o, Obj_space* to, Space *to_id, Address _rcv_addr, + Kobject ***reap_list, unsigned attribs = L4_fpage::CRWSD) +{ + assert_opt (o); + assert_opt (to); + assert_opt (to_id); + + typedef Obj_space SPACE; + typedef Obj_space::Addr Addr; + typedef Obj_space::Size Size; + + Page_number const rcv_addr = Page_number::create(_rcv_addr); + + if (EXPECT_FALSE(rcv_addr >= to->map_max_address())) + return 0; + + // Receiver lookup. + Obj_space::Phys_addr r_phys; + Size r_size; + unsigned r_attribs; + + Addr ra(rcv_addr); + if (to->v_lookup(ra, &r_phys, &r_size, &r_attribs)) + unmap((Kobject_mapdb*)0, to, to_id, ra, r_size, + L4_fpage::RWX, L4_map_mask::full(), reap_list); + + attribs &= L4_fpage::WX; + // Do the actual insertion. + Obj_space::Status status + = to->v_insert(o, ra, Size::create(1), attribs); + + switch (status) + { + case SPACE::Insert_warn_exists: + case SPACE::Insert_warn_attrib_upgrade: + case SPACE::Insert_ok: + + if (status == SPACE::Insert_ok) + { + if (! o->map_root()->insert(0, to_id, ra)) + { + to->v_delete(rcv_addr, Obj_space::Size::create(1)); + return 0; + } + } + break; + + case SPACE::Insert_err_nomem: + return 0; + + case SPACE::Insert_err_exists: + // Do not flag an error here -- because according to L4 + // semantics, it isn't. + break; + } + + return 1; +} diff --git a/kernel/fiasco/src/kern/map_util.cpp b/kernel/fiasco/src/kern/map_util.cpp new file mode 100644 index 00000000..41127a13 --- /dev/null +++ b/kernel/fiasco/src/kern/map_util.cpp @@ -0,0 +1,812 @@ +INTERFACE: + +#include "assert_opt.h" +#include "l4_types.h" +#include "space.h" + +class Mapdb; + +namespace Mu { +template +struct Virt_addr { typedef Page_number Type; }; + +template<> +struct Virt_addr { typedef Obj_space::Addr Type; }; + + +template< typename SPACE, typename M > +inline +Mword v_delete(M &m, Mword flush_rights, bool full_flush) +{ + SPACE* child_space = m->space(); + assert_opt (child_space); + Mword res = child_space->v_delete(m.page(), m.size(), flush_rights); + (void) full_flush; + assert_kdb (full_flush != child_space->v_lookup(m.page())); + return res; +} + + +} + +template< typename SPACE > +class Map_traits +{ +public: + typedef Page_number Addr; + typedef Page_count Size; + + static Addr get_addr(L4_fpage const &fp); + static void constraint(Addr &snd_addr, Size &snd_size, + Addr &rcv_addr, Size const &rcv_size, + Addr const &hot_spot); + static bool match(L4_fpage const &from, L4_fpage const &to); + static bool free_object(typename SPACE::Phys_addr o, + typename SPACE::Reap_list **reap_list); +}; + + +class Reap_list +{ +private: + Kobject *_h; + Kobject **_t; + +public: + Reap_list() : _h(0), _t(&_h) {} + Kobject ***list() { return &_t; } +}; + +namespace Mu { +template<> +inline +Mword v_delete(Kobject_mapdb::Iterator &m, Mword flush_rights, bool /*full_flush*/) +{ + Obj_space::Entry *c = static_cast(*m); + + if (c->valid()) + { + if (flush_rights & L4_fpage::R) + c->invalidate(); + else + c->del_rights(flush_rights & L4_fpage::WX); + } + return 0; +} +} + +//------------------------------------------------------------------------ +IMPLEMENTATION: + +#include + +#include "config.h" +#include "context.h" +#include "kobject.h" +#include "paging.h" +#include "warn.h" + + +IMPLEMENT template +inline +bool +Map_traits::match(L4_fpage const &, L4_fpage const &) +{ return false; } + +IMPLEMENT template +inline +bool +Map_traits::free_object(typename SPACE::Phys_addr, + typename SPACE::Reap_list **) +{ return false; } + + +PUBLIC template< typename SPACE > +static inline +void +Map_traits::attribs(L4_msg_item /*control*/, L4_fpage const &/*fp*/, + unsigned long *del_attr, unsigned long *set_attr) +{ *del_attr = 0; *set_attr = 0; } + +PUBLIC template< typename SPACE > +static inline +unsigned long +Map_traits::apply_attribs(unsigned long attribs, + typename SPACE::Phys_addr &, + unsigned long set_attr, unsigned long del_attr) +{ return (attribs & ~del_attr) | set_attr; } + +PRIVATE template +static inline +void +Map_traits::identity_constraint(Addr &snd_addr, Size &snd_size, + Addr rcv_addr, Size rcv_size) +{ + if (rcv_addr > snd_addr) + { + if (rcv_addr - snd_addr < snd_size) + snd_size -= rcv_addr - snd_addr; + else + snd_size = Size(0); + snd_addr = rcv_addr; + } + + if (snd_size > rcv_size) + snd_size = rcv_size; +} + +PRIVATE template +static inline +void +Map_traits::free_constraint(Addr &snd_addr, Size &snd_size, + Addr &rcv_addr, Size rcv_size, + Addr const &hot_spot) +{ + if (rcv_size >= snd_size) + rcv_addr += hot_spot.offset(rcv_size).trunc(snd_size); + else + { + snd_addr += hot_spot.offset(snd_size).trunc(rcv_size); + snd_size = rcv_size; + // reduce size of address range + } +} + +IMPLEMENT template +inline +void +Map_traits::constraint(Addr &snd_addr, Size &snd_size, + Addr &rcv_addr, Size const &rcv_size, + Addr const &hot_spot) +{ + if (SPACE::Identity_map) + identity_constraint(snd_addr, snd_size, rcv_addr, rcv_size); + else + free_constraint(snd_addr, snd_size, rcv_addr, rcv_size, hot_spot); +} + + + +//------------------------------------------------------------------------- +IMPLEMENTATION [io]: + +IMPLEMENT template<> +inline +bool +Map_traits::match(L4_fpage const &from, L4_fpage const &to) +{ return from.is_iopage() && (to.is_iopage() || to.is_all_spaces()); } + +IMPLEMENT template<> +inline +Map_traits::Addr +Map_traits::get_addr(L4_fpage const &fp) +{ return Addr(fp.io_address()); } + + + +//------------------------------------------------------------------------- +IMPLEMENTATION: + +IMPLEMENT template<> +inline +bool +Map_traits::match(L4_fpage const &from, L4_fpage const &to) +{ + return from.is_mempage() && (to.is_all_spaces() || to.is_mempage()); +} + +IMPLEMENT template<> +inline +Map_traits::Addr +Map_traits::get_addr(L4_fpage const &fp) +{ return Addr(fp.mem_address()); } + +IMPLEMENT template<> +inline +void +Map_traits::attribs(L4_msg_item control, L4_fpage const &fp, + unsigned long *del_attr, unsigned long *set_attr) +{ + *del_attr = (fp.rights() & L4_fpage::W) ? 0 : Mem_space::Page_writable; + short cache = control.attr() & 0x70; + + if (cache & L4_msg_item::Caching_opt) + { + *del_attr |= Page::Cache_mask; + + if (cache == L4_msg_item::Cached) + *set_attr = Page::CACHEABLE; + else if (cache == L4_msg_item::Buffered) + *set_attr = Page::BUFFERED; + else + *set_attr = Page::NONCACHEABLE; + } + else + *set_attr = 0; +} + + +IMPLEMENT template<> +inline +bool +Map_traits::match(L4_fpage const &from, L4_fpage const &to) +{ return from.is_objpage() && (to.is_objpage() || to.is_all_spaces()); } + + +IMPLEMENT template<> +inline +Map_traits::Addr +Map_traits::get_addr(L4_fpage const &fp) +{ return Addr(fp.obj_index()); } + +IMPLEMENT template<> +inline +bool +Map_traits::free_object(Obj_space::Phys_addr o, + Obj_space::Reap_list **reap_list) +{ + if (o->map_root()->no_mappings()) + { + o->initiate_deletion(reap_list); + return true; + } + + return false; +} + +IMPLEMENT template<> +inline +void +Map_traits::attribs(L4_msg_item control, L4_fpage const &fp, + unsigned long *del_attr, unsigned long *set_attr) +{ + *set_attr = 0; + *del_attr = (~(fp.rights() | (L4_msg_item::C_weak_ref ^ control.attr()))); +} + +IMPLEMENT template<> +static inline +unsigned long +Map_traits::apply_attribs(unsigned long attribs, + Obj_space::Phys_addr &a, + unsigned long set_attr, + unsigned long del_attr) +{ + if (attribs & del_attr & L4_msg_item::C_obj_specific_rights) + a = a->downgrade(del_attr); + + return (attribs & ~del_attr) | set_attr; +} + + +/** Flexpage mapping. + divert to mem_map (for memory fpages) or io_map (for IO fpages) + @param from source address space + @param fp_from flexpage descriptor for virtual-address space range + in source address space + @param to destination address space + @param fp_to flexpage descriptor for virtual-address space range + in destination address space + @param offs sender-specified offset into destination flexpage + @param grant if set, grant the fpage, otherwise map + @pre page_aligned(offs) + @return IPC error + L4_fpage from_fp, to_fp; + Mword control;code that describes the status of the operation +*/ +// Don't inline -- it eats too much stack. +// inline NEEDS ["config.h", io_map] +L4_error +fpage_map(Space *from, L4_fpage fp_from, Space *to, + L4_fpage fp_to, L4_msg_item control, Reap_list *r) +{ + if (Map_traits::match(fp_from, fp_to)) + return mem_map(from, fp_from, to, fp_to, control); + +#ifdef CONFIG_IO_PROT + if (Map_traits::match(fp_from, fp_to)) + return io_map(from, fp_from, to, fp_to, control); +#endif + + if (Map_traits::match(fp_from, fp_to)) + return obj_map(from, fp_from, to, fp_to, control, r->list()); + + return L4_error::None; +} + +/** Flexpage unmapping. + divert to mem_fpage_unmap (for memory fpages) or + io_fpage_unmap (for IO fpages) + @param space address space that should be flushed + @param fp flexpage descriptor of address-space range that should + be flushed + @param me_too If false, only flush recursive mappings. If true, + additionally flush the region in the given address space. + @param flush_mode determines which access privileges to remove. + @return combined (bit-ORed) access status of unmapped physical pages +*/ +// Don't inline -- it eats too much stack. +// inline NEEDS ["config.h", io_fpage_unmap] +unsigned +fpage_unmap(Space *space, L4_fpage fp, L4_map_mask mask, Kobject ***rl) +{ + unsigned ret = 0; + + if (fp.is_iopage() || fp.is_all_spaces()) + ret |= io_fpage_unmap(space, fp, mask); + + if (fp.is_objpage() || fp.is_all_spaces()) + ret |= obj_fpage_unmap(space, fp, mask, rl); + + if (fp.is_mempage() || fp.is_all_spaces()) + ret |= mem_fpage_unmap(space, fp, mask); + + return ret; +} + +PUBLIC +void +Reap_list::del() +{ + if (EXPECT_TRUE(!_h)) + return; + + for (Kobject *reap = _h; reap; reap = reap->_next_to_reap) + reap->destroy(list()); + + current()->rcu_wait(); + + for (Kobject *reap = _h; reap;) + { + Kobject *d = reap; + reap = reap->_next_to_reap; + if (d->put()) + delete d; + } + + _h = 0; + _t = &_h; +} + +PUBLIC inline +Reap_list::~Reap_list() +{ del(); } + +////////////////////////////////////////////////////////////////////// +// +// Utility functions for all address-space types +// + +#include "mapdb.h" + +inline +template +L4_error +map(MAPDB* mapdb, + SPACE* from, Space *from_id, + Page_number _snd_addr, + Page_count snd_size, + SPACE* to, Space *to_id, + Page_number _rcv_addr, + bool grant, unsigned attrib_add, unsigned attrib_del, + typename SPACE::Reap_list **reap_list = 0) +{ + enum + { + PAGE_SIZE = SPACE::Map_page_size, + PAGE_MASK = ~(PAGE_SIZE - 1), + SUPERPAGE_SIZE = SPACE::Map_superpage_size, + SUPERPAGE_MASK = ~((SUPERPAGE_SIZE - 1) >> SPACE::Page_shift) + }; + + typedef typename SPACE::Size Size; + typedef typename MAPDB::Mapping Mapping; + typedef typename MAPDB::Frame Frame; + typedef typename Mu::Virt_addr::Type Vaddr; + typedef Map_traits Mt; + + L4_error condition = L4_error::None; + + // FIXME: make this debugging code optional + bool no_page_mapped = true; + + Vaddr rcv_addr(_rcv_addr); + Vaddr snd_addr(_snd_addr); + const Vaddr rcv_start = rcv_addr; + const Page_count rcv_size = snd_size; + // We now loop through all the pages we want to send from the + // sender's address space, looking up appropriate parent mappings in + // the mapping data base, and entering a child mapping and a page + // table entry for the receiver. + + // Special care is taken for 4MB page table entries we find in the + // sender's address space: If what we will create in the receiver is + // not a 4MB-mapping, too, we have to find the correct parent + // mapping for the new mapping database entry: This is the sigma0 + // mapping for all addresses != the 4MB page base address. + + // When overmapping an existing page, flush the interfering + // physical page in the receiver, even if it is larger than the + // mapped page. + + // verify sender and receiver virtual addresses are still within + // bounds; if not, bail out. Sigma0 may send from any address (even + // from an out-of-bound one) + Page_count size; + bool need_tlb_flush = false; + bool need_xcpu_tlb_flush = false; + Page_number const to_max = to->map_max_address(); + Page_number const from_max = from->map_max_address(); + Size const from_superpage_size(from->superpage_size()); + bool const has_superpages = to->has_superpages(); + + for (; + snd_size // pages left for sending? + && rcv_addr < to_max + && snd_addr < from_max; + + rcv_addr += size, + snd_addr += size, + snd_size -= size) + { + // Reset the increment size to one page. + size = Size(PAGE_SIZE); + + // First, look up the page table entries in the sender and + // receiver address spaces. + + // Sender lookup. + // make gcc happy, initialized later anyway + typename SPACE::Phys_addr s_phys; + Size s_size(0); + unsigned s_attribs = 0; + + // Sigma0 special case: Sigma0 doesn't need to have a + // fully-constructed page table, and it can fabricate mappings + // for all physical addresses.:435 + if (EXPECT_FALSE(! from->v_fabricate(snd_addr, &s_phys, + &s_size, &s_attribs))) + continue; + + // We have a mapping in the sender's address space. + // FIXME: make this debugging code optional + no_page_mapped = false; + + // Receiver lookup. + + // The may be used uninitialized warning for this variable is bogus + // the v_lookup function must initialize the value if it returns true. + typename SPACE::Phys_addr r_phys; + Size r_size; + unsigned r_attribs; + + // Compute attributes for to-be-inserted frame + typename SPACE::Phys_addr i_phys = s_phys; + Size i_size = s_size; + bool const rcv_page_mapped + = to->v_lookup(rcv_addr, &r_phys, &r_size, &r_attribs); + // See if we have to degrade to non-superpage mappings + if (has_superpages && i_size == from_superpage_size) + { + if (i_size > snd_size + // want to send less that a superpage? + || i_size > r_size // not enough space for superpage map? + || snd_addr.offset(Size(SUPERPAGE_SIZE)) // snd page not aligned? + || rcv_addr.offset(Size(SUPERPAGE_SIZE)) // rcv page not aligned? + || (rcv_addr + from_superpage_size > rcv_start + rcv_size)) + // rcv area to small? + { + // We map a 4K mapping from a 4MB mapping + i_size = Size(PAGE_SIZE); + + if (Size super_offset = snd_addr.offset(Size(SUPERPAGE_SIZE))) + { + // Just use OR here because i_phys may already contain + // the offset. (As is on ARM) + i_phys = SPACE::subpage_address(i_phys, super_offset); + } + + if (grant) + { + WARN("XXX Can't GRANT page from superpage (%p: " L4_PTR_FMT + " -> %p: " L4_PTR_FMT "), demoting to MAP\n", + from_id, snd_addr.value(), to_id, rcv_addr.value()); + grant = 0; + } + } + } + + // Also, look up mapping database entry. Depending on whether + // we can overmap, either look up the destination mapping first + // (and compute the sender mapping from it) or look up the + // sender mapping directly. + Mapping* sender_mapping = 0; + // mapdb_frame will be initialized by the mapdb lookup function when + // it returns true, so don't care about "may be use uninitialized..." + Frame mapdb_frame; + bool doing_upgrade = false; + + if (rcv_page_mapped) + { + // We have something mapped. + + // Check if we can upgrade mapping. Otherwise, flush target + // mapping. + if (! grant // Grant currently always flushes + && r_size <= i_size // Rcv frame in snd frame + && SPACE::page_address(r_phys, i_size) == i_phys + && (sender_mapping = mapdb->check_for_upgrade(r_phys, from_id, snd_addr, to_id, rcv_addr, &mapdb_frame))) + doing_upgrade = true; + + if (! sender_mapping) // Need flush + { + unmap(mapdb, to, to_id, rcv_addr.trunc(r_size), r_size, + L4_fpage::RWX, L4_map_mask::full(), reap_list); + } + } + + if (! sender_mapping && mapdb->valid_address(s_phys)) + { + if (EXPECT_FALSE(! mapdb->lookup(from_id, + snd_addr.trunc(s_size), s_phys, + &sender_mapping, &mapdb_frame))) + continue; // someone deleted this mapping in the meantime + } + + // from here mapdb_frame is always initialized, so ignore the warning + // in grant / insert + + // At this point, we have a lookup for the sender frame (s_phys, + // s_size, s_attribs), the max. size of the receiver frame + // (r_phys), the sender_mapping, and whether a receiver mapping + // already exists (doing_upgrade). + + unsigned i_attribs + = Mt::apply_attribs(s_attribs, i_phys, attrib_add, attrib_del); + + // Loop increment is size of insertion + size = i_size; + + // Do the actual insertion. + typename SPACE::Status status + = to->v_insert(i_phys, rcv_addr, i_size, i_attribs); + + switch (status) + { + case SPACE::Insert_warn_exists: + case SPACE::Insert_warn_attrib_upgrade: + case SPACE::Insert_ok: + + assert_kdb (mapdb->valid_address(s_phys) || status == SPACE::Insert_ok); + // Never doing upgrades for mapdb-unmanaged memory + + if (grant) + { + if (mapdb->valid_address(s_phys)) + if (EXPECT_FALSE(!mapdb->grant(mapdb_frame, sender_mapping, + to_id, rcv_addr))) + { + // Error -- remove mapping again. + to->v_delete(rcv_addr, i_size); + + // may fail due to quota limits + condition = L4_error::Map_failed; + break; + } + + from->v_delete(snd_addr.trunc(s_size), s_size); + need_tlb_flush = true; + } + else if (status == SPACE::Insert_ok) + { + assert_kdb (!doing_upgrade); + + if (mapdb->valid_address(s_phys) + && !mapdb->insert(mapdb_frame, sender_mapping, + to_id, rcv_addr, + i_phys, i_size)) + { + // Error -- remove mapping again. + to->v_delete(rcv_addr, i_size); + + // XXX This is not race-free as the mapping could have + // been used in the mean-time, but we do not care. + condition = L4_error::Map_failed; + break; + } + } + + if (SPACE::Need_xcpu_tlb_flush && SPACE::Need_insert_tlb_flush) + need_xcpu_tlb_flush = true; + + break; + + case SPACE::Insert_err_nomem: + condition = L4_error::Map_failed; + break; + + case SPACE::Insert_err_exists: + WARN("map (%s) skipping area (%p/%lx): " L4_PTR_FMT + " -> %p/%lx: " L4_PTR_FMT "(%lx)", SPACE::name, + from_id, Kobject_dbg::pointer_to_id(from_id), snd_addr.value(), + to_id, Kobject_dbg::pointer_to_id(to_id), rcv_addr.value(), i_size.value()); + // Do not flag an error here -- because according to L4 + // semantics, it isn't. + break; + } + + if (sender_mapping) + mapdb->free(mapdb_frame); + + if (!condition.ok()) + break; + } + + if (need_tlb_flush) + from->tlb_flush(); + + if (SPACE::Need_xcpu_tlb_flush && need_xcpu_tlb_flush) + Context::xcpu_tlb_flush(false, to, from); + + // FIXME: make this debugging code optional + if (EXPECT_FALSE(no_page_mapped)) + { + WARN("nothing mapped: (%s) from [%p/%lx]: " L4_PTR_FMT + " size: " L4_PTR_FMT " to [%p/%lx]\n", SPACE::name, + from_id, Kobject_dbg::pointer_to_id(from_id), snd_addr.value(), rcv_size.value(), + to_id, Kobject_dbg::pointer_to_id(to_id)); + } + + return condition; +} + + +template +unsigned +unmap(MAPDB* mapdb, SPACE* space, Space *space_id, + Page_number start, Page_count size, unsigned char rights, + L4_map_mask mask, typename SPACE::Reap_list **reap_list) +{ + + typedef typename SPACE::Size Size; + typedef typename SPACE::Addr Addr; + typedef typename MAPDB::Mapping Mapping; + typedef typename MAPDB::Iterator Iterator; + typedef typename MAPDB::Frame Frame; + typedef typename Mu::Virt_addr::Type Vaddr; + + bool me_too = mask.self_unmap(); + + Mword flushed_rights = 0; + Page_number end = start + size; + Page_number const map_max = space->map_max_address(); + + // make gcc happy, initialized later anyway + typename SPACE::Phys_addr phys; + Page_count phys_size; + Vaddr page_address; + + Mword const flush_rights = SPACE::xlate_flush(rights); + bool const full_flush = SPACE::is_full_flush(rights); + bool need_tlb_flush = false; + bool need_xcpu_tlb_flush = false; + + // iterate over all pages in "space"'s page table that are mapped + // into the specified region + for (Vaddr address(start); + address < end && address < map_max; + address = page_address + phys_size) + { + // for amd64-mem_space's this will skip the hole in the address space + address = SPACE::canonize(address); + + bool have_page; + + { + Size ps; + have_page = space->v_fabricate(address, &phys, &ps); + phys_size = ps; + } + + page_address = address.trunc(phys_size); + + // phys_size and page_address have now been set up, allowing the + // use of continue (which evaluates the for-loop's iteration + // expression involving these to variables). + + if (! have_page) + continue; + + if (me_too) + { + assert_kdb (address == page_address + || phys_size == Size(SPACE::Map_superpage_size)); + + // Rewind flush address to page address. We always flush + // the whole page, even if it is larger than the specified + // flush area. + address = page_address; + if (end < address + phys_size) + end = address + phys_size; + } + + // all pages shall be handled by our mapping data base + assert_kdb (mapdb->valid_address(phys)); + + Mapping *mapping; + Frame mapdb_frame; + + if (! mapdb->lookup(space_id, page_address, phys, + &mapping, &mapdb_frame)) + // someone else unmapped faster + continue; // skip + + Mword page_rights = 0; + + // Delete from this address space + if (me_too) + { + page_rights |= + space->v_delete(address, phys_size, flush_rights); + + // assert_kdb (full_flush != space->v_lookup(address)); + need_tlb_flush = true; + need_xcpu_tlb_flush = true; + } + + // now delete from the other address spaces + for (Iterator m(mapdb_frame, mapping, address, end); + m; + ++m) + { + page_rights |= Mu::v_delete(m, flush_rights, full_flush); + need_xcpu_tlb_flush = true; + } + + flushed_rights |= page_rights; + + // Store access attributes for later retrieval + save_access_attribs(mapdb, mapdb_frame, mapping, + space, page_rights, page_address, phys, phys_size, + me_too); + + if (full_flush) + mapdb->flush(mapdb_frame, mapping, mask, address, end); + + if (full_flush) + Map_traits::free_object(phys, reap_list); + + mapdb->free(mapdb_frame); + } + + if (need_tlb_flush) + space->tlb_flush(); + + if (SPACE::Need_xcpu_tlb_flush && need_xcpu_tlb_flush) + Context::xcpu_tlb_flush(true, space, 0); + + return SPACE::xlate_flush_result(flushed_rights); +} + +//---------------------------------------------------------------------------- +IMPLEMENTATION[!io || ux]: + +// Empty dummy functions when I/O protection is disabled +inline +void init_mapdb_io(Space *) +{} + +inline +L4_error +io_map(Space *, L4_fpage const &, Space *, L4_fpage const &, L4_msg_item) +{ + return L4_error::None; +} + +inline +unsigned +io_fpage_unmap(Space * /*space*/, L4_fpage const &/*fp*/, L4_map_mask) +{ + return 0; +} + diff --git a/kernel/fiasco/src/kern/mapdb.cpp b/kernel/fiasco/src/kern/mapdb.cpp new file mode 100644 index 00000000..3dd64ed2 --- /dev/null +++ b/kernel/fiasco/src/kern/mapdb.cpp @@ -0,0 +1,1120 @@ +INTERFACE: + +#include "slab_cache.h" +#include "l4_types.h" +#include "types.h" +#include "mapping.h" +#include "auto_quota.h" + +struct Mapping_tree; // forward decls +class Physframe; +class Treemap; +class Space; + +/** A mapping database. + */ +class Mapdb +{ + friend class Jdb_mapdb; + +public: + typedef ::Mapping Mapping; + class Frame; + /** Iterator for mapping trees. This iterator knows how to descend + into Treemap nodes. + */ + class Iterator + { + Mapping_tree* _mapping_tree; + Mapping* _parent; + Mapping* _cursor; + size_t _page_shift; + Treemap *_submap; + Physframe *_subframe; + Page_number _submap_index; + Page_number _offs_begin, _offs_end; + + public: + inline Mapping* operator->() const { return _cursor; } + inline operator Mapping*() const { return _cursor; } + inline Iterator() : _submap (0), _submap_index(Page_number::create(0)) {} + inline Iterator(const Mapdb::Frame& f, Mapping* parent, + Page_number va_begin, Page_number va_end); + inline ~Iterator(); + inline void neutralize(); + inline Page_count size() const; + inline size_t shift() const { return _page_shift; } + inline Page_number page() const + { return Page_number(_cursor->page() << shift()); } + + inline Iterator &operator++ (); + }; + + // TYPES + class Frame + { + friend class Mapdb; + friend class Mapdb::Iterator; + Treemap* treemap; + Physframe* frame; + + public: + inline Page_number vaddr(Mapping* m) const; + }; + +private: + // DATA + Treemap* const _treemap; +}; + + +IMPLEMENTATION: + +/* The mapping database. + + * This implementation encodes mapping trees in very compact arrays of + * fixed sizes, prefixed by a tree header (Mapping_tree). Array + * sizes can vary from 4 mappings to 4<<15 mappings. For each size, + * we set up a slab allocator. To grow or shrink the size of an + * array, we have to allocate a larger or smaller tree from the + * corresponding allocator and then copy the array elements. + * + * The array elements (Mapping) contain a tree depth element. This + * depth and the relative position in the array is all information we + * need to derive tree structure information. Here is an example: + * + * array + * element depth + * number value comment + * -------------------------- + * 0 0 Sigma0 mapping + * 1 1 child of element #0 with depth 0 + * 2 2 child of element #1 with depth 1 + * 3 2 child of element #1 with depth 1 + * 4 3 child of element #3 with depth 2 + * 5 2 child of element #1 with depth 1 + * 6 3 child of element #5 with depth 2 + * 7 1 child of element #0 with depth 0 + * + * This array is a pre-order encoding of the following tree: + * + * 0 + * / \ + * 1 7 + * / | \ + * 2 3 5 + * | | + * 4 6 + + * The mapping database (Mapdb) is organized in a hierarchy of + * frame-number-keyed maps of Mapping_trees (Treemap). The top-level + * Treemap contains mapping trees for superpages. These mapping trees + * may contain references to Treemaps for subpages. (Original credits + * for this idea: Christan Szmajda.) + * + * Treemap + * ------------------------------- + * | | | | | | | | | | | | | | | | array of ptr to 4M Mapping_tree's + * ---|--------------------------- + * | + * v a Mapping_tree + * --------------- + * | | tree header + * |-------------| + * | | 4M Mapping *or* ptr to nested Treemap + * | | e.g. + * | ----------------| Treemap + * | | v array of ptr to 4K Mapping_tree's + * --------------- ------------------------------- + * | | | | | | | | | | | | | | | | + * ---|--------------------------- + * | + * v a Mapping_tree + * --------------- + * | | tree header + * |-------------| + * | | 4K Mapping + * | | + * | | + * | | + * --------------- + + * IDEAS for enhancing this implementation: + + * We often have to find a tree header corresponding to a mapping. + * Currently, we do this by iterating backwards over the array + * containing the mappings until we find the Sigma0 mapping, from + * whose address we can compute the address of the tree header. If + * this becomes a problem, we could add one more byte to the mappings + * with a hint (negative array offset) where to find the sigma0 + * mapping. (If the hint value overflows, just iterate using the hint + * value of the mapping we find with the first hint value.) Another + * idea (from Adam) would be to just look up the tree header by using + * the physical address from the page-table lookup, but we would need + * to change the interface of the mapping database for that (pass in + * the physical address at all times), or we would have to include the + * physical address (or just the address of the tree header) in the + * Mapdb-user-visible Mapping (which could be different from the + * internal tree representation). (XXX: Implementing one of these + * ideas is probably worthwile doing!) + + * Instead of copying whole trees around when they grow or shrink a + * lot, or copying parts of trees when inserting an element, we could + * give up the array representation and add a "next" pointer to the + * elements -- that is, keep the tree of mappings in a + * pre-order-encoded singly-linked list (credits to: Christan Szmajda + * and Adam Wiggins). 24 bits would probably be enough to encode that + * pointer. Disadvantages: Mapping entries would be larger, and the + * cache-friendly space-locality of tree entries would be lost. + */ + +#include +#include + +#include "config.h" +#include "globals.h" +#include "helping_lock.h" +#include "kmem_alloc.h" +#include "mapping_tree.h" +#include "paging.h" +#include "kmem_slab.h" +#include "ram_quota.h" +#include "std_macros.h" +#include + +// +// class Physframe +// + +/** Array elements for holding frame-specific data. */ +class Physframe : public Base_mappable +{ + friend class Mapdb; + friend class Mapdb::Iterator; + friend class Treemap; + friend class Jdb_mapdb; +}; // struct Physframe + +#if 0 // Optimization: do this using memset in Physframe::alloc() +inline +Physframe::Physframe () +{} + +inline +void * +Physframe::operator new (size_t, void *p) +{ return p; } +#endif + +PUBLIC static inline +unsigned long +Physframe::mem_size(size_t size) +{ + return (size*sizeof(Physframe) + 1023) & ~1023; +} + +static inline +Physframe * +Physframe::alloc(size_t size) +{ + Physframe* block + = (Physframe*)Kmem_alloc::allocator()->unaligned_alloc(mem_size(size)); + +#if 1 // Optimization: See constructor + if (block) + memset(block, 0, size * sizeof(Physframe)); +#else + assert (block); + for (unsigned i = 0; i < size; ++i) + new (block + i) Physframe(); +#endif + + return block; +} + +inline NOEXPORT + NEEDS["mapping_tree.h", Treemap::~Treemap, Treemap::operator delete] +Physframe::~Physframe() +{ + if (tree) + { + Lock_guard guard(&lock); + + // Find next-level trees. + for (Mapping* m = tree->mappings(); + m && !m->is_end_tag(); + m = tree->next(m)) + { + if (m->submap()) + delete m->submap(); + } + + tree.reset(); + } +} + +static // inline NEEDS[Physframe::~Physframe] +void +Physframe::free(Physframe *block, size_t size) +{ + for (unsigned i = 0; i < size; ++i) + block[i].~Physframe(); + + Kmem_alloc::allocator()->unaligned_free(Physframe::mem_size(size), block); +} + +// +// class Treemap +// + +class Treemap +{ + friend class Jdb_mapdb; + friend class Treemap_ops; + + // DATA + Page_count _key_end; ///< Number of Physframe entries + Space *_owner_id; ///< ID of owner of mapping trees + Page_number _page_offset; ///< Virt. page address in owner's addr space + size_t _page_shift; ///< Page size of mapping trees + Physframe* _physframe; ///< Pointer to Physframe array + const size_t* const _sub_shifts; ///< Pointer to array of sub-page sizes + const unsigned _sub_shifts_max; ///< Number of valid _page_sizes entries + + friend class Mapdb::Iterator; + Mapdb::Iterator _unwind; ///< Chaining information for Mapdb_iterator +}; + +// +// class Treemap_ops +// +// Helper operations for Treemaps (used in Mapping_tree::flush) + +class Treemap_ops +{ + unsigned long _page_shift; +}; + +PUBLIC inline +Treemap_ops::Treemap_ops(unsigned long page_shift) +: _page_shift(page_shift) +{} + +PUBLIC +unsigned long +Treemap_ops::mem_size(Treemap const *submap) const +{ + unsigned long quota + = submap->_key_end.value() * sizeof(Physframe) + sizeof(Treemap); + + for (Page_number key = Page_number::create(0); + key < submap->_key_end; + ++key) + { + Physframe* subframe = submap->frame(key); + if (subframe->tree) + quota += sizeof(Mapping); + } + + return quota; +} + +PUBLIC +void +Treemap_ops::grant(Treemap *submap, Space *new_space, Page_number va) const +{ + submap->_owner_id = new_space; + submap->_page_offset = va << _page_shift; + + for (Page_number key = Page_number::create(0); + key < submap->_key_end; + ++key) + { + Physframe* subframe = submap->frame(key); + if (Mapping_tree* tree = subframe->tree.get()) + { + Lock_guard guard(&subframe->lock); + tree->mappings()->set_space(new_space); + tree->mappings()->set_page(va + (key >> (_page_shift - submap->_page_shift))); + } + } +} + +PUBLIC inline +Space * +Treemap_ops::owner(Treemap const *submap) const +{ return submap->owner(); } + +PUBLIC inline +bool +Treemap_ops::is_partial(Treemap const *submap, Page_count offs_begin, + Page_count offs_end) const +{ + return offs_begin > Page_count::create(0) + || offs_end < (submap->_key_end << submap->_page_shift); +} + +PUBLIC inline +void +Treemap_ops::del(Treemap *submap) const +{ delete submap; } + +PUBLIC inline +void +Treemap_ops::flush(Treemap *submap, + Page_number offs_begin, Page_number offs_end) const +{ + for (Page_number i = offs_begin >> submap->_page_shift; + i < (offs_end + Page_count::create((1UL << submap->_page_shift) - 1) + >> submap->_page_shift); + i++) + { + Page_count page_offs_begin = i << submap->_page_shift; + Page_count page_offs_end = page_offs_begin; + page_offs_end += Page_count::create(1UL << submap->_page_shift); + + Physframe* subframe = submap->frame(i); + + Lock_guard guard(&subframe->lock); + + if (offs_begin <= page_offs_begin && offs_end >= page_offs_end) + subframe->tree.reset(); + else + { + Page_count psz = Page_count::create(1UL << _page_shift); + // FIXME: do we have to check for subframe->tree != 0 here ? + submap->flush(subframe, subframe->tree->mappings(), false, + page_offs_begin > offs_begin + ? Page_number::create(0) : offs_begin.offset(psz), + page_offs_end < offs_end + ? psz + : (offs_end - Page_count::create(1)).offset(psz) + + Page_count::create(1)); + } + } +} + + +// +// Treemap members +// + +PRIVATE inline +Treemap::Treemap(Page_number key_end, Space *owner_id, + Page_number page_offset, size_t page_shift, + const size_t* sub_shifts, unsigned sub_shifts_max, + Physframe *physframe) + : _key_end(key_end), + _owner_id(owner_id), + _page_offset(page_offset), + _page_shift(page_shift), + _physframe(physframe), + _sub_shifts(sub_shifts), + _sub_shifts_max(sub_shifts_max) +{ + assert (_physframe); +} + +PRIVATE static inline +unsigned long +Treemap::quota_size(Page_number key_end) +{ return Physframe::mem_size(key_end.value()) + sizeof(Treemap); } + +PUBLIC static +Treemap * +Treemap::create(Page_number key_end, Space *owner_id, + Page_number page_offset, size_t page_shift, + const size_t* sub_shifts, unsigned sub_shifts_max) +{ + Auto_quota quota(Mapping_tree::quota(owner_id), quota_size(key_end)); + + if (EXPECT_FALSE(!quota)) + return 0; + + + Physframe *pf = Physframe::alloc(key_end.value()); + + if (EXPECT_FALSE(!pf)) + return 0; + + void *m = allocator()->alloc(); + if (EXPECT_FALSE(!m)) + { + Physframe::free(pf, key_end.value()); + return 0; + } + + quota.release(); + return new (m) Treemap(key_end, owner_id, page_offset, page_shift, sub_shifts, + sub_shifts_max, pf); +} + + + +PUBLIC +inline NEEDS[Physframe::free, Mapdb] //::Iterator::neutralize] +Treemap::~Treemap() +{ + Physframe::free(_physframe, _key_end.value()); + + // Make sure that _unwind.~Mapdb_iterator is harmless: Reinitialize it. + _unwind.neutralize(); +} + +static Kmem_slab_t _treemap_allocator("Treemap"); + +static +Slab_cache * +Treemap::allocator() +{ return &_treemap_allocator; } + + +PUBLIC +inline +void +Treemap::operator delete (void *block) +{ + Treemap *t = reinterpret_cast(block); + Space *id = t->_owner_id; + allocator()->free(block); + Mapping_tree::quota(id)->free(Treemap::quota_size(t->_key_end)); +} + +PUBLIC inline +size_t +Treemap::page_shift() const +{ + return _page_shift; +} + +PUBLIC inline +Space * +Treemap::owner() const +{ + return _owner_id; +} + +PUBLIC inline +Page_number +Treemap::end_addr() const +{ + return (_key_end << _page_shift) + _page_offset; +} + +PUBLIC inline NEEDS["paging.h"] +Page_number +Treemap::vaddr(Mapping* m) const +{ + return m->page() << _page_shift; +} + +PUBLIC inline +void +Treemap::set_vaddr(Mapping* m, Page_number address) const +{ + m->set_page(address >> _page_shift); +} + +PUBLIC +Physframe* +Treemap::tree(Page_number key) +{ + assert (key < _key_end); + + Physframe *f = &_physframe[key.value()]; + + f->lock.lock(); + + if (! f->tree) + { + Auto_quota q(Mapping_tree::quota(_owner_id), sizeof(Mapping)); + if (EXPECT_FALSE(!q)) + { + f->lock.clear(); + return 0; + } + + cxx::unique_ptr new_tree + (new (Mapping_tree::Size_id_min) Mapping_tree(Mapping_tree::Size_id_min, key + (_page_offset >> _page_shift), + _owner_id)); + + if (EXPECT_FALSE(!new_tree)) + { + f->lock.clear(); + return 0; + } + + q.release(); + f->tree = cxx::move(new_tree); + } + + return f; +} + +PUBLIC +Physframe* +Treemap::frame(Page_number key) const +{ + assert (key < _key_end); + + return &_physframe[key.value()]; +} + +PUBLIC +bool +Treemap::lookup(Page_number key, Space *search_space, Page_number search_va, + Mapping** out_mapping, Treemap** out_treemap, + Physframe** out_frame) +{ + // get and lock the tree. + assert (key >> _page_shift < _key_end); + Physframe *f = tree(key >> _page_shift); // returns locked frame + assert (f); + + Mapping_tree *t = f->tree.get(); + Page_count const psz = Page_count::create(1UL << _page_shift); + + assert (t); + assert (t->mappings()[0].space() == _owner_id); + assert (vaddr(t->mappings()) == key.trunc(psz) + _page_offset); + + Mapping *m; + bool ret = false; + + for (m = t->mappings(); m; m = t->next (m)) + { + if (Treemap *sub = m->submap()) + { + // XXX Recursion. The max. recursion depth should better be + // limited! + if ((ret = sub->lookup(key.offset(psz), + search_space, search_va, + out_mapping, out_treemap, out_frame))) + break; + } + else if (m->space() == search_space + && vaddr(m) == search_va.trunc(psz)) + { + *out_mapping = m; + *out_treemap = this; + *out_frame = f; + return true; // found! -- return locked + } + } + + // not found, or found in submap -- unlock tree + f->lock.clear(); + + return ret; +} + +PUBLIC +Mapping * +Treemap::insert(Physframe* frame, Mapping* parent, Space *space, + Page_number va, Page_number phys, Page_count size) +{ + Mapping_tree* t = frame->tree.get(); + Treemap* submap = 0; + Ram_quota *payer; + Page_count const psz = Page_count::create(1UL << _page_shift); + bool insert_submap = psz != size; + + // Inserting subpage mapping? See if we can find a submap. If so, + // we don't have to allocate a new Mapping entry. + if (insert_submap) + { + assert (psz > size); + + submap = t->find_submap(parent); + } + + if (! submap) // Need allocation of new entry -- for submap or + // normal mapping + { + // first check quota! In case of a new submap the parent pays for + // the node... + payer = Mapping_tree::quota(insert_submap ? parent->space() : space); + + Mapping *free = t->allocate(payer, parent, insert_submap); + if (EXPECT_FALSE(!free)) + return 0; + + // Check for submap entry. + if (! insert_submap) // Not a submap entry + { + free->set_space(space); + set_vaddr(free, va); + + t->check_integrity(_owner_id); + return free; + } + + assert (_sub_shifts_max > 0); + + submap + = Treemap::create(Page_number::create(1UL << (_page_shift - _sub_shifts[0])), + parent->space(), vaddr(parent), _sub_shifts[0], + _sub_shifts + 1, _sub_shifts_max - 1); + if (! submap) + { + // free the mapping got with allocate + t->free_mapping(payer, free); + return 0; + } + + free->set_submap(submap); + } + + Physframe* subframe = submap->tree(phys.offset(psz) >> submap->_page_shift); + if (! subframe) + return 0; + + Mapping_tree* subtree = subframe->tree.get(); + + if (! subtree) + return 0; + + // XXX recurse. + Mapping* ret = submap->insert(subframe, subtree->mappings(), space, va, + phys.offset(psz), size); + submap->free(subframe); + + return ret; +} // Treemap::insert() + +PUBLIC +void +Treemap::free(Physframe* f) +{ + f->pack(); + f->tree->check_integrity(_owner_id); + + // Unlock tree. + f->lock.clear(); +} // Treemap::free() + + +PUBLIC +void +Treemap::flush(Physframe* f, Mapping* parent, bool me_too, + Page_number offs_begin, Page_number offs_end) +{ + assert (! parent->unused()); + + // This is easy to do: We just have to iterate over the array + // encoding the tree. + Mapping_tree *t = f->tree.get(); + t->flush(parent, me_too, offs_begin, offs_end, Treemap_ops(_page_shift)); + + t->check_integrity(_owner_id); + return; +} // Treemap::flush() + +PUBLIC +bool +Treemap::grant(Physframe* f, Mapping* m, Space *new_space, Page_number va) +{ + return f->tree->grant(m, new_space, va >> _page_shift, + Treemap_ops(_page_shift)); +} + + + +// +// class Mapdb_iterator +// + +/** Create a new mapping-tree iterator. If parent is the result of a + fresh lookup (and not the result of an insert operation), you can + pass the corresponding Mapdb::Frame for optimization. + */ +IMPLEMENT inline NEEDS[Treemap::vaddr] +Mapdb::Iterator::Iterator(const Mapdb::Frame& f, Mapping* parent, + Page_number va_begin, Page_number va_end) + : _mapping_tree(f.frame->tree.get()), + _parent(parent), + _cursor(parent), + _page_shift(f.treemap->_page_shift), + _submap(0), + _subframe(0), + _submap_index(Page_number::create(0)) +{ + assert (_mapping_tree == Mapping_tree::head_of(parent)); + assert (! parent->submap()); + + if (va_begin < f.treemap->vaddr(parent)) + va_begin = f.treemap->vaddr(parent); + if (va_begin > va_end) + va_begin = va_end; + + _offs_begin = va_begin - f.treemap->vaddr(parent); + _offs_end = va_end - f.treemap->vaddr(parent); + + ++*this; +} + +IMPLEMENT inline NEEDS[Physframe, "helping_lock.h", Treemap] +Mapdb::Iterator::~Iterator() +{ + // unwind lock information + while (_submap) + { + if (_subframe) + _subframe->lock.clear(); + + *this = _submap->_unwind; + } +} + +/** Make sure that the destructor does nothing. Handy for scratch + iterators such as Treemap::_unwind. */ +IMPLEMENT inline +void +Mapdb::Iterator::neutralize() +{ + _submap = 0; +} + +IMPLEMENT inline +Page_count +Mapdb::Iterator::size() const +{ + return Page_count(1UL << _page_shift); +} + +IMPLEMENT inline NEEDS ["mapping_tree.h"] +Mapdb::Iterator& +Mapdb::Iterator::operator++ () +{ + for (;;) + { + _cursor = _mapping_tree->next_child(_parent, _cursor); + + if (_cursor && ! _cursor->submap()) + { // Found a new regular child mapping. + if (_cursor) + return *this; + } + + if (_cursor) // _cursor is a submap + { + Treemap* submap = _cursor->submap(); + assert (submap); + + // Before descending into array of subpages, save iterator + // state for later unwinding to this point. + submap->_unwind = *this; + + // For subpages of original parent mapping, apply possible tag and + // virtual-address restrictions. (Do not apply restrictions + // to other subpages because operations on a part of a + // superpage always affect *complete* child-superpages, as + // we do not support splitting out parts of superpages. + Page_count parent_size = submap->_key_end << submap->_page_shift; + + if (_offs_end > parent_size) + _offs_end = parent_size; + + if (_cursor->parent() == _parent) + { // Submap of iteration root + _offs_begin = _offs_begin.offset(parent_size); + _offs_end = (_offs_end - Page_count::create(1)).offset(parent_size) + Page_count::create(1); + } + else // Submap of a child mapping + { + _offs_begin = Page_number::create(0); + _offs_end = parent_size; + } + + // Initialize rest of iterator for subframe iteration + _submap = submap; + _page_shift = _submap->_page_shift; + _subframe = 0; + _submap_index = _offs_begin >> _page_shift; + _mapping_tree = 0; + _parent = _cursor = 0; + } + + else if (! _submap) // End of iteration + return *this; + + // Clear previously acquired lock. + if (_subframe) + { + _subframe->lock.clear(); + _subframe = 0; + } + + // Find a new subframe. + Physframe* f = 0; + + Page_count end_offs = _offs_end; + end_offs += Page_count::create((1UL << _submap->_page_shift) - 1); + end_offs >>= _submap->_page_shift; + + assert (end_offs <= _submap->_key_end); + + for (; _submap_index < end_offs;) + { + f = _submap->frame(_submap_index++); + if (f->tree.get()) + break; + } + + if (f && f->tree) // Found a subframe + { + _subframe = f; + f->lock.lock(); // Lock it + _mapping_tree = f->tree.get(); + _parent = _cursor = _mapping_tree->mappings(); + continue; + } + + // No new subframes found -- unwind to superpage tree + *this = _submap->_unwind; + } +} + + +// +// class Mapdb +// + +/** Constructor. + @param End physical end address of RAM. (Used only if + Config::Mapdb_ram_only is true.) + */ +PUBLIC +Mapdb::Mapdb(Space *owner, Page_number end_frame, size_t const *page_shifts, + unsigned page_shifts_max) +: _treemap(Treemap::create(end_frame, owner, + Page_number::create(0), + page_shifts[0], page_shifts + 1, + page_shifts_max - 1)) +{ + // assert (boot_time); + assert (_treemap); +} // Mapdb() + +/** Destructor. */ +PUBLIC +Mapdb::~Mapdb() +{ + delete _treemap; +} + +/** Insert a new mapping entry with the given values as child of + "parent". + We assume that there is at least one free entry at the end of the + array so that at least one insert() operation can succeed between a + lookup()/free() pair of calls. This is guaranteed by the free() + operation which allocates a larger tree if the current one becomes + to small. + @param parent Parent mapping of the new mapping. + @param space Number of the address space into which the mapping is entered + @param va Virtual address of the mapped page. + @param size Size of the mapping. For memory mappings, 4K or 4M. + @return If successful, new mapping. If out of memory or mapping + tree full, 0. + @post All Mapping* pointers pointing into this mapping tree, + except "parent" and its parents, will be invalidated. + */ +PUBLIC +Mapping * +Mapdb::insert(const Mapdb::Frame& frame, Mapping* parent, Space *space, + Page_number va, Page_number phys, Page_count size) +{ + return frame.treemap->insert(frame.frame, parent, space, va, phys, size); +} // insert() + + +/** + * Lookup a mapping and lock the corresponding mapping tree. The returned + * mapping pointer, and all other mapping pointers derived from it, remain + * valid until free() is called on one of them. We guarantee that at most + * one insert() operation succeeds between one lookup()/free() pair of calls + * (it succeeds unless the mapping tree is fu68,ll). + * @param space Number of virtual address space in which the mapping + * was entered + * @param va Virtual address of the mapping + * @param phys Physical address of the mapped pag frame + * @return mapping, if found; otherwise, 0 + */ +PUBLIC +bool +Mapdb::lookup(Space *space, Page_number va, Page_number phys, + Mapping** out_mapping, Mapdb::Frame* out_lock) +{ + return _treemap->lookup(phys, space, va, out_mapping, + & out_lock->treemap, & out_lock->frame); +} + +/** Unlock the mapping tree to which the mapping belongs. Once a tree + has been unlocked, all Mapping instances pointing into it become + invalid. + + A mapping tree is locked during lookup(). When the tree is + locked, the tree may be traversed (using member functions of + Mapping, which serves as an iterator over the tree) or + manipulated (using insert(), free(), flush(), grant()). Note that + only one insert() is allowed during each locking cycle. + + @param mapping_of_tree Any mapping belonging to a mapping tree. + */ +PUBLIC +static void +Mapdb::free(const Mapdb::Frame& f) +{ + f.treemap->free(f.frame); +} // free() + +/** Delete mappings from a tree. This function deletes mappings + recusively. + @param m Mapping that denotes the subtree that should be deleted. + @param me_too If true, delete m as well; otherwise, delete only + submappings. + */ +PUBLIC static +void +Mapdb::flush(const Mapdb::Frame& f, Mapping *m, L4_map_mask mask, + Page_number va_start, Page_number va_end) +{ + Page_count size = Page_count::create(1UL << f.treemap->page_shift()); + Page_number offs_begin = va_start > f.treemap->vaddr(m) + ? va_start - f.treemap->vaddr(m) : Page_number::create(0); + Page_number offs_end = va_end > f.treemap->vaddr(m) + size + ? size : va_end - f.treemap->vaddr(m); + + f.treemap->flush(f.frame, m, mask.self_unmap(), offs_begin, offs_end); +} // flush() + +/** Change ownership of a mapping. + @param m Mapping to be modified. + @param new_space Number of address space the mapping should be + transferred to + @param va Virtual address of the mapping in the new address space + */ +PUBLIC +bool +Mapdb::grant(const Mapdb::Frame& f, Mapping *m, Space *new_space, + Page_number va) +{ + return f.treemap->grant(f.frame, m, new_space, va); +} + +/** Return page size of given mapping and frame. */ +PUBLIC static inline NEEDS[Treemap::page_shift] +size_t +Mapdb::shift(const Mapdb::Frame& f, Mapping * /*m*/) +{ + // XXX add special case for _mappings[0]: Return superpage size. + return f.treemap->page_shift(); +} + +PUBLIC static inline NEEDS[Treemap::vaddr] +Page_number +Mapdb::vaddr(const Mapdb::Frame& f, Mapping* m) +{ + return f.treemap->vaddr(m); +} + +// +// class Mapdb::Frame +// + +IMPLEMENT inline NEEDS[Treemap::vaddr] +Page_number +Mapdb::Frame::vaddr(Mapping* m) const +{ + return treemap->vaddr(m); + +} + +PUBLIC inline NEEDS [Treemap::end_addr] +bool +Mapdb::valid_address(Page_number phys) +{ + return phys < _treemap->end_addr(); +} + + +PUBLIC inline +Mapdb::Mapping * +Mapdb::check_for_upgrade(Page_number phys, + Space *from_id, Page_number snd_addr, + Space *to_id, Page_number rcv_addr, + Frame *mapdb_frame) +{ + // Check if we can upgrade mapping. Otherwise, flush target + // mapping. + Mapping* receiver_mapping; + if (valid_address(phys) // Can lookup in mapdb + && lookup(to_id, rcv_addr, phys, &receiver_mapping, mapdb_frame)) + { + Mapping* receiver_parent = receiver_mapping->parent(); + if (receiver_parent->space() == from_id + && vaddr(*mapdb_frame, receiver_parent) == snd_addr) + return receiver_parent; + else // Not my child -- cannot upgrade + free(*mapdb_frame); + } + return 0; +} + + +IMPLEMENTATION [debug]: + +PUBLIC +bool +Treemap::find_space(Space *s) +{ + bool bug = _owner_id == s; + for (unsigned i = 0; i < _key_end.value(); ++i) + { + bool tree_bug = false; + Mapping_tree *t = _physframe[i].tree.get(); + if (!t) + continue; + + t->check_integrity(); + Mapping *m = t->mappings(); + for (unsigned mx = 0; mx < t->number_of_entries(); ++mx) + { + bool mapping_bug = false; + Mapping *ma = m + mx; + if (ma->is_end_tag()) + break; + + if (ma->unused()) + continue; + + if (ma->submap()) + mapping_bug = ma->submap()->find_space(s); + else if (ma->space() == s) + { + mapping_bug = true; + printf("MAPDB: found space %p in mapdb (idx=%d, mapping=%p, depth=%d, page=%lx)\n", + s, mx, ma, ma->depth(), ma->page().value()); + } + + tree_bug |= mapping_bug; + } + + if (tree_bug) + printf("MAPDB: error in mapping tree: index=%d\n", i); + + bug |= tree_bug; + } + + if (bug) + printf("MAPDB: error in treemap: owner(space)=%p, offset=%lx, size=%lx, pageshift=%zd\n", + _owner_id, _page_offset.value(), _key_end.value(), _page_shift); + + return bug; +} + +PUBLIC +bool +Mapdb::find_space(Space *s) +{ return _treemap->find_space(s); } + diff --git a/kernel/fiasco/src/kern/mappable.cpp b/kernel/fiasco/src/kern/mappable.cpp new file mode 100644 index 00000000..e6969c41 --- /dev/null +++ b/kernel/fiasco/src/kern/mappable.cpp @@ -0,0 +1,21 @@ +INTERFACE: + +#include "mapping_tree.h" + +class Mappable : public Base_mappable +{ +public: + bool no_mappings() const; + virtual ~Mappable() = 0; +}; + +IMPLEMENTATION: + +IMPLEMENT inline Mappable::~Mappable() {} + +IMPLEMENT +inline bool +Mappable::no_mappings() const +{ + return !tree.get() || tree.get()->is_empty(); +} diff --git a/kernel/fiasco/src/kern/mapping.cpp b/kernel/fiasco/src/kern/mapping.cpp new file mode 100644 index 00000000..a7d4090a --- /dev/null +++ b/kernel/fiasco/src/kern/mapping.cpp @@ -0,0 +1,178 @@ +INTERFACE: + +#include "types.h" + +class Space; +/** Represents one mapping in a mapping tree. + Instances of Mapping ("mappings") work as an iterator over a + mapping tree. Mapping trees are never visible on the user level. + Mappings are looked up directly in the mapping database (class + Mapdb) using Mapdb::lookup(). When carrying out such a + lookup, the mapping database locks the corresponding mapping tree + before returning the mapping. This mapping can the be used to + iterate over the tree and to look up other mappings in the tree. + The mapping tree is unlocked (and all mappings pointing into it + become invalid) when Mapdb::free is called with any one of its + mappings. + */ +class Mapping +{ + friend class Jdb_mapdb; +public: + enum Mapping_depth + { + Depth_root = 0, Depth_max = 252, + Depth_submap = 253, Depth_empty = 254, Depth_end = 255 + }; + + enum { Alignment = Mapping_entry::Alignment }; + + // CREATORS + Mapping(const Mapping&); // this constructor is undefined. + + // DATA + Mapping_entry _data; +} __attribute__((packed)); + + +IMPLEMENTATION: + +#include "config.h" + +PUBLIC inline +Mapping::Mapping() +{} + +inline +Mapping_entry * +Mapping::data() +{ + return &_data; +} + +inline +const Mapping_entry * +Mapping::data() const +{ + return &_data; +} + +/** Address space. + @return the address space into which the frame is mapped. + */ +PUBLIC inline NEEDS [Mapping::data] +Space * +Mapping::space() const +{ + return data()->space(); +} + +/** Set address space. + @param space the address space into which the frame is mapped. + */ +PUBLIC inline NEEDS [Mapping::data] +void +Mapping::set_space(Space *space) +{ + data()->set_space(space); +} + +/** Virtual address. + @return the virtual address at which the frame is mapped. + */ +PUBLIC inline NEEDS[Mapping::data] +Page_number +Mapping::page() const +{ + return Page_number::create(data()->data.address); +} + +/** Set virtual address. + @param address the virtual address at which the frame is mapped. + */ +PUBLIC inline NEEDS[Mapping::data] +void +Mapping::set_page(Page_number address) +{ + data()->data.address = address.value(); +} + +/** Depth of mapping in mapping tree. */ +PUBLIC inline +unsigned +Mapping::depth() const +{ + return data()->_depth; +} + +/** Set depth of mapping in mapping tree. */ +PUBLIC inline +void +Mapping::set_depth(unsigned depth) +{ + data()->_depth = depth; +} + +/** free entry?. + @return true if this is unused. + */ +PUBLIC inline NEEDS [Mapping::data] +bool +Mapping::unused() const +{ + return depth() >= Depth_empty; +} + +PUBLIC inline +bool +Mapping::is_end_tag() const +{ + return depth() == Depth_end; +} + +PUBLIC inline +Treemap * +Mapping::submap() const +{ + return (data()->_depth == Depth_submap) + ? data()->_submap + : 0; +} + +PUBLIC inline +void +Mapping::set_submap(Treemap *treemap) +{ + data()->_submap = treemap; + data()->_depth = Depth_submap; +} + +PUBLIC inline +void +Mapping::set_unused() +{ + data()->_depth = Depth_empty; +} + +/** Parent. + @return parent mapping of this mapping. + */ +PUBLIC Mapping * +Mapping::parent() +{ + if (depth() <= Depth_root) + return 0; // Sigma0 mappings don't have a parent. + + // Iterate over mapping entries of this tree backwards until we find + // an entry with a depth smaller than ours. (We assume here that + // "special" depths (empty, end) are larger than Depth_max.) + Mapping *m = this - 1; + + // NOTE: Depth_unused / Depth_submap are high, so no need to test + // for them + while (m->depth() >= depth()) + m--; + + return m; +} + diff --git a/kernel/fiasco/src/kern/mapping_tree.cpp b/kernel/fiasco/src/kern/mapping_tree.cpp new file mode 100644 index 00000000..f9ec5665 --- /dev/null +++ b/kernel/fiasco/src/kern/mapping_tree.cpp @@ -0,0 +1,1007 @@ +INTERFACE: + +#include "config.h" +#include "l4_types.h" +#include "lock.h" +#include "mapping.h" +#include "types.h" + +#include + +class Ram_quota; + +class Simple_tree_submap_ops +{ +}; + +/* The mapping database. + + * This implementation encodes mapping trees in very compact arrays of + * fixed sizes, prefixed by a tree header (Mapping_tree). Array + * sizes can vary from 4 mappings to 4<<15 mappings. For each size, + * we set up a slab allocator. To grow or shrink the size of an + * array, we have to allocate a larger or smaller tree from the + * corresponding allocator and then copy the array elements. + * + * The array elements (Mapping) contain a tree depth element. This + * depth and the relative position in the array is all information we + * need to derive tree structure information. Here is an example: + * + * array + * element depth + * number value comment + * -------------------------- + * 0 0 Sigma0 mapping + * 1 1 child of element #0 with depth 0 + * 2 2 child of element #1 with depth 1 + * 3 2 child of element #1 with depth 1 + * 4 3 child of element #3 with depth 2 + * 5 2 child of element #1 with depth 1 + * 6 3 child of element #5 with depth 2 + * 7 1 child of element #0 with depth 0 + * + * This array is a pre-order encoding of the following tree: + * + * 0 + * / \ + * 1 7 + * / | \ + * 2 3 5 + * | | + * 4 6 + + * The mapping database (Mapdb) is organized in a hierarchy of + * frame-number-keyed maps of Mapping_trees (Treemap). The top-level + * Treemap contains mapping trees for superpages. These mapping trees + * may contain references to Treemaps for subpages. (Original credits + * for this idea: Christan Szmajda.) + * + * Treemap + * ------------------------------- + * | | | | | | | | | | | | | | | | array of ptr to 4M Mapping_tree's + * ---|--------------------------- + * | + * v a Mapping_tree + * --------------- + * | | tree header + * |-------------| + * | | 4M Mapping *or* ptr to nested Treemap + * | | e.g. + * | ----------------| Treemap + * | | v array of ptr to 4K Mapping_tree's + * --------------- ------------------------------- + * | | | | | | | | | | | | | | | | + * ---|--------------------------- + * | + * v a Mapping_tree + * --------------- + * | | tree header + * |-------------| + * | | 4K Mapping + * | | + * | | + * | | + * --------------- + + * IDEAS for enhancing this implementation: + + * We often have to find a tree header corresponding to a mapping. + * Currently, we do this by iterating backwards over the array + * containing the mappings until we find the Sigma0 mapping, from + * whose address we can compute the address of the tree header. If + * this becomes a problem, we could add one more byte to the mappings + * with a hint (negative array offset) where to find the sigma0 + * mapping. (If the hint value overflows, just iterate using the hint + * value of the mapping we find with the first hint value.) Another + * idea (from Adam) would be to just look up the tree header by using + * the physical address from the page-table lookup, but we would need + * to change the interface of the mapping database for that (pass in + * the physical address at all times), or we would have to include the + * physical address (or just the address of the tree header) in the + * Mapdb-user-visible Mapping (which could be different from the + * internal tree representation). (XXX: Implementing one of these + * ideas is probably worthwile doing!) + + * Instead of copying whole trees around when they grow or shrink a + * lot, or copying parts of trees when inserting an element, we could + * give up the array representation and add a "next" pointer to the + * elements -- that is, keep the tree of mappings in a + * pre-order-encoded singly-linked list (credits to: Christan Szmajda + * and Adam Wiggins). 24 bits would probably be enough to encode that + * pointer. Disadvantages: Mapping entries would be larger, and the + * cache-friendly space-locality of tree entries would be lost. + */ + + +INTERFACE [!big_endian]: +// +// Mapping_tree +// FIXME: do we need this depending on endianess ? +struct Mapping_tree +{ + enum Size_id + { + Size_id_min = 0, + Size_id_max = 9 // can be up to 15 (4 bits) + }; + // DATA + unsigned _count: 16; ///< Number of live entries in this tree. + unsigned _size_id: 4; ///< Tree size -- see number_of_entries(). + unsigned _empty_count: 11; ///< Number of dead entries in this tree. + // XXX currently never read, except in + // sanity checks + + unsigned _unused: 1; // (make this 32 bits to avoid a compiler bug) + + Mapping _mappings[0]; + +}; + + +INTERFACE [big_endian]: +// +// Mapping_tree +// FIXME: do we need this depending on endianess ? +struct Mapping_tree +{ + enum Size_id + { + Size_id_min = 0, + Size_id_max = 9 // can be up to 15 (4 bits) + }; + // DATA + unsigned _unused: 1; // (make this 32 bits to avoid a compiler bug) + unsigned _size_id: 4; ///< Tree size -- see number_of_entries(). + unsigned _empty_count: 11; ///< Number of dead entries in this tree. + // XXX currently never read, except in + // sanity checks + + unsigned _count: 16; ///< Number of live entries in this tree. + Mapping _mappings[0]; +}; + +INTERFACE: +// +// class Physframe +// + +/** Array elements for holding frame-specific data. */ +class Base_mappable +{ +public: + // DATA + cxx::unique_ptr tree; + typedef ::Lock Lock; + Lock lock; +}; // struct Physframe + + +//--------------------------------------------------------------------------- +IMPLEMENTATION: + +#include +#include + +#include "config.h" +#include "globals.h" +#include "kmem_slab.h" +#include "ram_quota.h" +#include "space.h" +#include "std_macros.h" + + +// Helpers + +PUBLIC inline +unsigned long +Simple_tree_submap_ops::mem_size(Treemap const *) const +{ return 0; } + +PUBLIC inline +void +Simple_tree_submap_ops::grant(Treemap *, Space *, Page_number) const +{} + +PUBLIC inline +Space * +Simple_tree_submap_ops::owner(Treemap const *) const +{ return 0; } + +PUBLIC inline +bool +Simple_tree_submap_ops::is_partial(Treemap const *, Page_number, Page_number) const +{ return false; } + +PUBLIC inline +void +Simple_tree_submap_ops::del(Treemap *) const +{} + +PUBLIC inline +void +Simple_tree_submap_ops::flush(Treemap *, Page_number, Page_number) const +{} + +// +// Mapping-tree allocators +// + +enum Mapping_tree_size +{ + Size_factor = 4, + Size_id_max = 9 // can be up to 15 (4 bits) +}; + +PUBLIC inline +Mapping_tree::Size_id +Mapping_tree::shrink() +{ + unsigned sid = _size_id - 1; + while (sid > 0 && ((static_cast(_count) << 2) < ((unsigned)Size_factor << sid))) + --sid; + + return Size_id(sid); +} + +PUBLIC inline +Mapping_tree::Size_id +Mapping_tree::bigger() +{ return Mapping_tree::Size_id(_size_id + 1); } + +template +struct Mapping_tree_allocator +{ + Kmem_slab a; + enum + { + Elem_size = (Size_factor << SIZE_ID) * sizeof (Mapping) + + sizeof(Mapping_tree) + }; + + Mapping_tree_allocator(Kmem_slab **array) + : a(Elem_size, Mapping::Alignment, "Mapping_tree") + { array[SIZE_ID] = &a; } +}; + +template +struct Mapping_tree_allocators; + +template<> +struct Mapping_tree_allocators<0> +{ + Mapping_tree_allocator<0> a; + Mapping_tree_allocators(Kmem_slab **array) : a(array) {} +}; + +template +struct Mapping_tree_allocators +{ + + Mapping_tree_allocator a; + Mapping_tree_allocators n; + + Mapping_tree_allocators(Kmem_slab **array) : a(array), n(array) {} +}; + +static Kmem_slab *_allocators[Size_id_max + 1]; +static Mapping_tree_allocators _mapping_tree_allocators(_allocators); + +static +Kmem_slab * +allocator_for_treesize(int size) +{ + return _allocators[size]; +} + +// +// class Mapping_tree +// + +PUBLIC static +inline NEEDS["space.h"] +Ram_quota * +Mapping_tree::quota(Space *space) +{ + return space->ram_quota(); +} + +PUBLIC +void* +Mapping_tree::operator new (size_t, Mapping_tree::Size_id size_id) throw() +{ return allocator_for_treesize(size_id)->alloc(); } + +PUBLIC +void +Mapping_tree::operator delete (void* block) +{ + if (!block) + return; + + // Try to guess right allocator object -- XXX unportable! + Mapping_tree* t = static_cast(block); + + t->check_integrity(); + + allocator_for_treesize(t->_size_id)->free(block); +} + +PUBLIC //inline NEEDS[Mapping_depth, Mapping_tree::last] +Mapping_tree::Mapping_tree(Size_id size_id, Page_number page, + Space *owner) +{ + _count = 1; // 1 valid mapping + _size_id = size_id; // size is equal to Size_factor << 0 +#ifndef NDEBUG + _empty_count = 0; // no gaps in tree representation +#endif + + _mappings[0].set_depth(Mapping::Depth_root); + _mappings[0].set_page(page); + _mappings[0].set_space(owner); + + _mappings[1].set_depth(Mapping::Depth_end); + + // We also always set the end tag on last entry so that we can + // check whether it has been overwritten. + last()->set_depth(Mapping::Depth_end); +} + +PUBLIC +Mapping_tree::~Mapping_tree() +{ + // special case for copied mapping trees + for (Mapping *m = _mappings; m < end() && !m->is_end_tag(); ++m) + { + if (!m->submap() && !m->unused()) + quota(m->space())->free(sizeof(Mapping)); + } +} + +PUBLIC //inline NEEDS[Mapping_depth, Mapping_tree::last] +Mapping_tree::Mapping_tree(Size_id size_id, Mapping_tree* from_tree) +{ + _size_id = size_id; + last()->set_depth(Mapping::Depth_end); + + copy_compact_tree(this, from_tree); +} + +// public routines with inline implementations +PUBLIC inline NEEDS[Mapping_tree_size] +unsigned +Mapping_tree::number_of_entries() const +{ + return Size_factor << (unsigned long)_size_id; +} + +PUBLIC inline +Mapping * +Mapping_tree::mappings() +{ + return & _mappings[0]; +} + +PUBLIC inline +bool +Mapping_tree::is_empty() const +{ + return _count == 0; +} + +PUBLIC inline NEEDS[Mapping_tree::mappings, Mapping_tree::number_of_entries] +Mapping * +Mapping_tree::end() +{ + return mappings() + number_of_entries(); +} + +PUBLIC inline NEEDS[Mapping_tree::end] +Mapping * +Mapping_tree::last() +{ + return end() - 1; +} + +// A utility function to find the tree header belonging to a mapping. + +/** Our Mapping_tree. + @return the Mapping_tree we are in. + */ +PUBLIC static +Mapping_tree * +Mapping_tree::head_of(Mapping *m) +{ + while (m->depth() > Mapping::Depth_root) + { + // jump in bigger steps if this is not a free mapping + if (m->depth() <= Mapping::Depth_max) + { + m -= m->depth(); + continue; + } + + m--; + } + + return reinterpret_cast + (reinterpret_cast(m) - sizeof(Mapping_tree)); + // We'd rather like to use offsetof as follows, but it's unsupported + // for non-POD classes. So we instead rely on GCC's zero-length + // array magic (sizeof(Mapping_tree) is the size of the header + // without the array). + // return reinterpret_cast + // (reinterpret_cast(m) - offsetof(Mapping_tree, _mappings)); +} + +/** Next mapping in the mapping tree. + @param t head of mapping tree, if available + @return the next mapping in the mapping tree. If the mapping has + children, it is the first child. Otherwise, if the mapping has a + sibling, it's the next sibling. Otherwise, if the mapping is the + last sibling or only child, it's the mapping's parent. + */ +PUBLIC inline +Mapping * +Mapping_tree::next(Mapping *m) +{ + for (m++; m < end() && ! m->is_end_tag(); m++) + if (! m->unused()) + return m; + + return 0; +} + +/** Next child mapping of a given parent mapping. This + function traverses the mapping tree like next(); however, it + stops (and returns 0) if the next mapping is outside the subtree + starting with parent. + @param parent Parent mapping + @return the next child mapping of a given parent mapping + */ +PUBLIC inline NEEDS[Mapping_tree::next] +Mapping * +Mapping_tree::next_child(Mapping *parent, Mapping *current_child) +{ + // Find the next valid entry in the tree structure. + Mapping *m = next(current_child); + + // If we didn't find an entry, or if the entry cannot be a child of + // "parent", return 0 + if (m == 0 || m->depth() <= parent->depth()) + return 0; + + return m; // Found! +} + +// This function copies the elements of mapping tree src to mapping +// tree dst, ignoring empty elements (that is, compressing the +// source tree. In-place compression is supported. +PUBLIC static +void +Mapping_tree::copy_compact_tree(Mapping_tree *dst, Mapping_tree *src) +{ + unsigned src_count = src->_count; // Store in local variable before + // it can get overwritten + + // Special case: cannot in-place compact a full tree + if (src == dst && src->number_of_entries() == src_count) + return; + + // Now we can assume the resulting tree will not be full. + assert (src_count < dst->number_of_entries()); + + dst->_count = 0; +#ifndef NDEBUG + dst->_empty_count = 0; +#endif + + Mapping *d = dst->mappings(); + + for (Mapping *s = src->mappings(); + s && !s->is_end_tag(); + s = src->next(s)) + { + *d++ = *s; + dst->_count += 1; + } + + assert (dst->_count == src_count); // Same number of entries + assert (d < dst->end()); + // Room for one more entry (the Mapping::Depth_end entry) + + d->set_depth(Mapping::Depth_end); + dst->last()->set_depth(Mapping::Depth_end); +} // copy_compact_tree() + +// Don't inline this function -- it eats a lot of stack space! +PUBLIC // inline NEEDS[Mapping::data, Mapping::unused, Mapping::is_end_tag, + // Mapping_tree::end, Mapping_tree::number_of_entries] +void +Mapping_tree::check_integrity(Space *owner = (Space*)-1) +{ + (void)owner; +#ifndef NDEBUG + // Sanity checking + assert (// Either each entry is used + number_of_entries() == static_cast(_count) + _empty_count + // Or the last used entry is end tag + || mappings()[_count + _empty_count].is_end_tag()); + + Mapping* m = mappings(); + + if (!(m->is_end_tag() // When the tree was copied to a new one + || (! m->unused() // The first entry is never unused. + && m->depth() == 0 + && (owner == (Space *)-1 || m->space() == owner)))) + { + printf("mapdb corrupted: owner=%p\n" + " m=%p (end: %s depth: %d space: %p page: %lx)\n", + owner, m, m->is_end_tag()?"yes":"no", m->depth(), m->space(), + m->page().value()); + kdb_ke("XXX"); + } + + unsigned + used = 0, + dead = 0; + + while (m < end() && ! m->is_end_tag()) + { + if (m->unused()) + dead++; + else + used++; + + m++; + } + + assert_kdb (_count == used); + assert_kdb (_empty_count == dead); +#endif // ! NDEBUG +} + + +/** + * Use this function to reset a the tree to empty. + * + * In the case where a tree was copied to a new one you have to use + * this function to prevent the node iteration in the destructor. + */ +PUBLIC inline +void +Mapping_tree::reset() +{ + _count = 0; + _empty_count = 0; + _mappings[0].set_depth(Mapping::Depth_end); +} + +PUBLIC inline NEEDS[Mapping_tree::next, ] +Treemap * +Mapping_tree::find_submap(Mapping* parent) +{ + assert (! parent->submap()); + + // We need just one step to find a possible submap, because they are + // always a parent's first child. + Mapping* m = next(parent); + + if (m && m->submap()) + return m->submap(); + + return 0; +} + +PUBLIC inline NEEDS["ram_quota.h"] +Mapping * +Mapping_tree::allocate(Ram_quota *payer, Mapping *parent, + bool insert_submap = false) +{ + Auto_quota q(payer, sizeof(Mapping)); + if (EXPECT_FALSE(!q)) + return 0; + + // After locating the right place for the new entry, it will be + // stored there (if this place is empty) or the following entries + // moved by one entry. + + // We cannot continue if the last array entry is not free. This + // only happens if an earlier call to free() with this mapping tree + // couldn't allocate a bigger array. In this case, signal an + // out-of-memory condition. + if (EXPECT_FALSE (! last()->unused())) + return 0; + + // If the parent mapping already has the maximum depth, we cannot + // insert a child. + if (EXPECT_FALSE (parent->depth() == Mapping::Depth_max)) + return 0; + + //allocation is done, so... + q.release(); + + Mapping *insert = 0, *free = 0; + // - Find an insertion point for the new entry. Acceptable insertion + // points are either before a sibling (same depth) or at the end + // of the subtree; for submap insertions, it's always before + // the first sibling. "insert" keeps track of the last + // acceptable insertion point. + // - Find a free entry in the array encoding the subtree ("free"). + // There might be none; in this case, we stop at the end of the + // subtree. + + for (Mapping* m = parent + 1; m < end(); m++) + { + // End of subtree? If we reach this point, this is our insert spot. + if (m->is_end_tag() + || m->depth() <= (insert_submap + ? parent->depth() + 1 + : parent->depth())) + { + insert = m; + break; + } + + if (m->unused()) + free = m; + else if (free // Only look for insert spots after free + && m->depth() <= parent->depth() + 1) + { + insert = m; + break; + } + } + + assert (insert); + assert (free == 0 || (free->unused() && free < insert)); + + // We now update "free" to point to a free spot that is acceptable + // as well. + + if (free) + { + // "free" will be the latest free spot before the "insert" spot. + // If there is anything between "free" and "insert", move it + // upward to make space just before insert. + while (free + 1 != insert) + { + *free = *(free + 1); + free++; + } + +#ifndef NDEBUG + // Tree-header maintenance + _empty_count -= 1; // Allocated dead entry +#endif + } + else // free == 0 + { + // There was no free spot in the subtree. Move everything + // downward until we have free space. This is guaranteed to + // succeed, because we ensured earlier that the last entry of + // the array is free. + + free = insert; // This will be the free spot + + // Find empty spot + while (! insert->unused()) + insert++; + + // Tree maintenance: handle end tag, empty count + if (insert->is_end_tag()) + { + // Need to move end tag. + if (insert + 1 < end()) + insert++; // Arrange for copying end tag as well + } +#ifndef NDEBUG + else + _empty_count -= 1; // Allocated dead entry +#endif + + // Move mappings + while (insert > free) + { + *insert = *(insert - 1); + --insert; + } + } + + _count += 1; // Adding an alive entry + + // found a place to insert new child (free). + free->set_depth(insert_submap ? (unsigned)Mapping::Depth_submap + : parent->depth() + 1); + + return free; +} + +PUBLIC inline NEEDS["ram_quota.h"] +void +Mapping_tree::free_mapping(Ram_quota *q, Mapping *m) +{ + assert (!m->unused() && !m->is_end_tag()); + q->free(sizeof(Mapping)); + m->set_unused(); +} + +PUBLIC template< typename SUBMAP_OPS > +void +Mapping_tree::flush(Mapping *parent, bool me_too, + Page_number offs_begin, Page_number offs_end, + SUBMAP_OPS const &submap_ops = SUBMAP_OPS()) +{ + assert (! parent->unused()); + + // This is easy to do: We just have to iterate over the array + // encoding the tree. + Mapping *start_of_deletions = parent; + unsigned p_depth = parent->depth(); + unsigned deleted = 0; +#ifndef NDEBUG + unsigned empty_elems_passed = 0; +#endif + + if (me_too) + { + free_mapping(quota(parent->space()), parent); + _count -= 1; + deleted++; + } + else + start_of_deletions++; + + unsigned m_depth = p_depth; + + for (Mapping* m = parent + 1; + m < end() && ! m->is_end_tag(); + m++) + { + if (unsigned (m->depth()) <= p_depth) + { + // Found another data element -- stop deleting. Since we + // created holes in the tree representation, account for it. +#ifndef NDEBUG + _empty_count += deleted; +#endif + return; + } + + if (m->unused()) + { +#ifndef NDEBUG + empty_elems_passed++; +#endif + continue; + } + + Space *space; + if (Treemap* submap = m->submap()) + { + space = submap_ops.owner(submap); + if (! me_too + // Check for immediate child. Note: It's a bad idea to + // call m->parent() because that would iterate backwards + // over already-deleted entries. + && m_depth == p_depth + && submap_ops.is_partial(submap, offs_begin, offs_end)) + { + submap_ops.flush(submap, offs_begin, offs_end); + + start_of_deletions++; + continue; + } + else + submap_ops.del(submap); + } + else // Found a real mapping + { + space = m->space(); + m_depth = m->depth(); + } + + // Delete the element. + free_mapping(quota(space), m); + _count -= 1; + deleted++; + } + + // We deleted stuff at the end of the array -- move end tag + if (start_of_deletions < end()) + { + start_of_deletions->set_depth(Mapping::Depth_end); + +#ifndef NDEBUG + // also, reduce number of free entries + _empty_count -= empty_elems_passed; +#endif + } +} + +PUBLIC template< typename SUBMAP_OPS > +bool +Mapping_tree::grant(Mapping* m, Space *new_space, Page_number va, + SUBMAP_OPS const &submap_ops = SUBMAP_OPS()) +{ + unsigned long _quota = sizeof(Mapping); + Treemap* submap = find_submap(m); + if (submap) + _quota += submap_ops.mem_size(submap); + + if (!quota(new_space)->alloc(_quota)) + return false; + + Space *old_space = m->space(); + + m->set_space(new_space); + m->set_page(va); + + if (submap) + submap_ops.grant(submap, new_space, va); + + quota(old_space)->free(_quota); + return true; +} + +PUBLIC inline +Mapping * +Mapping_tree::lookup(Space *space, Page_number page) +{ + + Mapping *m; + + for (m = mappings(); m; m = next(m)) + { + assert (!m->submap()); + if (m->space() == space && m->page() == page) + return m; + } + + return 0; +} + + +PUBLIC +Mapping * +Base_mappable::lookup(Space *space, Page_number va) +{ + // get and lock the tree. + lock.lock(); + Mapping_tree *t = tree.get(); + assert (t); + if (Mapping *m = t->lookup(space, va)) + return m; + + lock.clear(); + return 0; +} + +PUBLIC inline +Mapping * +Base_mappable::insert(Mapping* parent, Space *space, Page_number page) +{ + Mapping_tree* t = tree.get(); + if (!t) + { + assert (parent == 0); + Auto_quota q(Mapping_tree::quota(space), sizeof(Mapping)); + if (EXPECT_FALSE(!q)) + return 0; + + Mapping_tree::Size_id min_size = Mapping_tree::Size_id_min; + cxx::unique_ptr new_tree(new (min_size) Mapping_tree (min_size, page, space)); + + if (EXPECT_FALSE(!new_tree)) + return 0; + + tree = cxx::move(new_tree); + q.release(); + return tree->mappings(); + } + + Mapping *free = t->allocate(Mapping_tree::quota(space), parent, false); + + if (EXPECT_FALSE(!free)) + return 0; + + free->set_space(space); + free->set_page(page); + + t->check_integrity(); + return free; +} + + +PUBLIC +void +Base_mappable::pack() +{ + // Before we unlock the tree, we need to make sure that there is + // room for at least one new mapping. In particular, this means + // that the last entry of the array encoding the tree must be free. + + // (1) When we use up less than a quarter of all entries of the + // array encoding the tree, copy to a smaller tree. Otherwise, (2) + // if the last entry is free, do nothing. Otherwise, (3) if less + // than 3/4 of the entries are used, compress the tree. Otherwise, + // (4) copy to a larger tree. + + Mapping_tree *t = tree.get(); + bool maybe_out_of_memory = false; + + do // (this is not actually a loop, just a block we can "break" out of) + { + // (1) Do we need to allocate a smaller tree? + if (t->_size_id > Mapping_tree::Size_id_min // must not be smallest size + && (static_cast(t->_count) << 2) < t->number_of_entries()) + { + Mapping_tree::Size_id sid = t->Mapping_tree::shrink(); + cxx::unique_ptr new_t(new (sid) Mapping_tree(sid, t)); + + if (new_t) + { + // ivalidate node 0 because we must not free the quota for it + t->reset(); + t = new_t.get(); + + // Register new tree. + tree = cxx::move(new_t); + + break; + } + } + + // (2) Is last entry is free? + if (t->last()->unused()) + break; // OK, last entry is free. + + // Last entry is not free -- either compress current array + // (i.e., move free entries to end of array), or allocate bigger + // array. + + // (3) Should we compress the tree? + // We also try to compress if we cannot allocate a bigger + // tree because there is no bigger tree size. + if (t->_count < (t->number_of_entries() >> 2) + + (t->number_of_entries() >> 1) + || t->_size_id == Size_id_max) // cannot enlarge? + { + if (t->_size_id == Size_id_max) + maybe_out_of_memory = true; + + Mapping_tree::copy_compact_tree(t, t); // in-place compression + + break; + } + + // (4) OK, allocate a bigger array. + + Mapping_tree::Size_id sid = t->bigger(); + cxx::unique_ptr new_t(new (sid) Mapping_tree(sid, t)); + + if (new_t) + { + // ivalidate node 0 because we must not free the quota for it + t->reset(); + t = new_t.get(); + + // Register new tree. + tree = cxx::move(new_t); + } + else + { + // out of memory -- just do tree compression and hope that helps. + maybe_out_of_memory = true; + + Mapping_tree::copy_compact_tree(t, t); // in-place compression + } + } + while (false); + + // The last entry of the tree should now be free -- exept if we're + // out of memory. + assert (t->last()->unused() || maybe_out_of_memory); +} + + + diff --git a/kernel/fiasco/src/kern/mem_layout.cpp b/kernel/fiasco/src/kern/mem_layout.cpp new file mode 100644 index 00000000..cc1d2857 --- /dev/null +++ b/kernel/fiasco/src/kern/mem_layout.cpp @@ -0,0 +1,46 @@ +INTERFACE: + +#include "l4_types.h" + +class Mem_layout +{ +public: + /// reflect symbols in linker script + static const char load asm ("_load"); + static const char image_start asm ("_kernel_image_start"); + static const char start asm ("_start"); + static const char end asm ("_end"); + static const char ecode asm ("_ecode"); + static const char etext asm ("_etext"); + static const char data_start asm ("_kernel_data_start"); + static const char edata asm ("_edata"); + static const char initcall_start asm ("_initcall_start"); + static const char initcall_end asm ("_initcall_end"); + + static Mword in_tcbs (Address a); // FIXME + static Mword in_kernel (Address a); // XXX: not right for UX +}; + +IMPLEMENTATION: + +#include "config.h" + +PUBLIC static inline +bool +Mem_layout::is_caps_area(Address a) +{ return (a >= Caps_start) && (a < Caps_end); } + +IMPLEMENT inline +Mword +Mem_layout::in_kernel (Address a) +{ + return a >= User_max; +} + +PUBLIC static inline +Mword +Mem_layout::in_kernel_code (Address a) +{ + return a >= (Address)&start && a < (Address)&ecode; +} + diff --git a/kernel/fiasco/src/kern/mem_space-user.cpp b/kernel/fiasco/src/kern/mem_space-user.cpp new file mode 100644 index 00000000..681c626a --- /dev/null +++ b/kernel/fiasco/src/kern/mem_space-user.cpp @@ -0,0 +1,67 @@ +/** + * Functions to access user address space from inside the kernel. + */ + +INTERFACE: + +EXTENSION class Mem_space +{ +public: + /** + * Read integral type at any virtual address. + * @param addr Virtual address in user or kernel address space. + * @param user_space Location of virtual address (user or kernel space). + * @return Integral value read from address. + */ + template< typename T > + T peek(T const *addr, bool user_space); + + /** + * Read integral type at virtual address in user space. + * @param addr Virtual address in user address space. + * @return Integral value read from address. + */ + template< typename T > + T peek_user(T const *addr); + + /** + * Set integral type at virtual address in user space to value. + * @param addr Virtual address in user address space. + * @param value New value to be set. + */ + template< typename T > + void poke_user(T *addr, T value); +}; + +//---------------------------------------------------------------------------- +IMPLEMENTATION: + +#include +#include "mem.h" + +IMPLEMENT inline +template< typename T > +T +Mem_space::peek(T const *addr, bool user_space) +{ + return user_space ? peek_user(addr) : *addr; +} + +//---------------------------------------------------------------------------- +IMPLEMENTATION[arm || ia32 || amd64]: + +IMPLEMENT inline NEEDS [] +template< typename T > +T +Mem_space::peek_user(T const *addr) +{ + return *addr; +} + +IMPLEMENT inline NEEDS [] +template< typename T > +void +Mem_space::poke_user(T *addr, T value) +{ + *addr = value; +} diff --git a/kernel/fiasco/src/kern/mem_space.cpp b/kernel/fiasco/src/kern/mem_space.cpp new file mode 100644 index 00000000..ae1bdf1b --- /dev/null +++ b/kernel/fiasco/src/kern/mem_space.cpp @@ -0,0 +1,219 @@ +INTERFACE: + +#include "auto_quota.h" +#include "paging.h" // for page attributes +#include "mem_layout.h" +#include "member_offs.h" +#include "per_cpu_data.h" +#include "ram_quota.h" +#include "types.h" + +class Space; + +/** + * An address space. + * + * Insertion and lookup functions. + */ +class Mem_space +{ + MEMBER_OFFSET(); + + // Space reverse lookup + friend inline Mem_space* current_mem_space(); + +public: + typedef int Status; + + static char const *const name; + + typedef Pdir::Va Vaddr; + typedef Pdir::Va Vsize; + + typedef Virt_addr Addr; + typedef Virt_size Size; + typedef Page_addr Phys_addr; + typedef void Reap_list; + + // Each architecture must provide these members: + void switchin_context(Mem_space *from); + + /** Insert a page-table entry, or upgrade an existing entry with new + * attributes. + * + * @param phys Physical address (page-aligned). + * @param virt Virtual address for which an entry should be created. + * @param size Size of the page frame -- 4KB or 4MB. + * @param page_attribs Attributes for the mapping (see + * Mem_space::Page_attrib). + * @return Insert_ok if a new mapping was created; + * Insert_warn_exists if the mapping already exists; + * Insert_warn_attrib_upgrade if the mapping already existed but + * attributes could be upgraded; + * Insert_err_nomem if the mapping could not be inserted because + * the kernel is out of memory; + * Insert_err_exists if the mapping could not be inserted because + * another mapping occupies the virtual-address + * range + * @pre phys and virt need to be size-aligned according to the size argument. + */ + Status v_insert(Phys_addr phys, Vaddr virt, Vsize size, + unsigned page_attribs, bool upgrade_ignore_size = false); + + /** Look up a page-table entry. + * + * @param virt Virtual address for which we try the look up. + * @param phys Meaningful only if we find something (and return true). + * If not 0, we fill in the physical address of the found page + * frame. + * @param page_attribs Meaningful only if we find something (and return + * true). If not 0, we fill in the page attributes for the + * found page frame (see Mem_space::Page_attrib). + * @param size If not 0, we fill in the size of the page-table slot. If an + * entry was found (and we return true), this is the size + * of the page frame. If no entry was found (and we + * return false), this is the size of the free slot. In + * either case, it is either 4KB or 4MB. + * @return True if an entry was found, false otherwise. + */ + bool v_lookup(Vaddr virt, Phys_addr *phys = 0, Size *size = 0, + unsigned *page_attribs = 0); + + /** Delete page-table entries, or some of the entries' attributes. + * + * This function works for one or multiple mappings (in contrast to + * v_insert!). + * + * @param virt Virtual address of the memory region that should be changed. + * @param size Size of the memory region that should be changed. + * @param page_attribs If nonzero, delete only the given page attributes. + * Otherwise, delete the whole entries. + * @return Combined (bit-ORed) page attributes that were removed. In + * case of errors, ~Page_all_attribs is additionally bit-ORed in. + */ + unsigned long v_delete(Vaddr virt, Vsize size, + unsigned long page_attribs = Page_all_attribs); + + /** Set this memory space as the current on on this CPU. */ + void make_current(); + + static Mem_space *kernel_space() + { return _kernel_space; } + + static inline Mem_space *current_mem_space(unsigned cpu); + + virtual Page_number map_max_address() const + { return Addr::create(Map_max_address); } + + static Address superpage_size() + { return Map_superpage_size; } + + static Phys_addr page_address(Phys_addr o, Size s) + { return o.trunc(s); } + + static Phys_addr subpage_address(Phys_addr addr, Size offset) + { return addr | offset; } + +private: + Mem_space(const Mem_space &) = delete; + + Ram_quota *_quota; + + static Per_cpu _current; + static Mem_space *_kernel_space; +}; + + +//--------------------------------------------------------------------------- +INTERFACE [mp]: + +#include "cpu_mask.h" + +EXTENSION class Mem_space +{ +public: + enum { Need_xcpu_tlb_flush = true }; +}; + + + +//--------------------------------------------------------------------------- +INTERFACE [!mp]: + +EXTENSION class Mem_space +{ +public: + enum { Need_xcpu_tlb_flush = false }; +}; + + +//--------------------------------------------------------------------------- +IMPLEMENTATION: + +// +// class Mem_space +// + +#include "config.h" +#include "globals.h" +#include "l4_types.h" +#include "kmem_alloc.h" +#include "mem_unit.h" +#include "paging.h" +#include "panic.h" + +DEFINE_PER_CPU Per_cpu Mem_space::_current; + + +char const * const Mem_space::name = "Mem_space"; +Mem_space *Mem_space::_kernel_space; + + +PUBLIC inline +Ram_quota * +Mem_space::ram_quota() const +{ return _quota; } + + +/// Avoid deallocation of page table upon Mem_space destruction. +PUBLIC +void +Mem_space::reset_dirty () +{ _dir = 0; } + +PUBLIC inline +Mem_space::Dir_type* +Mem_space::dir () +{ return _dir; } + +PUBLIC inline +const Mem_space::Dir_type* +Mem_space::dir() const +{ return _dir; } + +PUBLIC +virtual bool +Mem_space::v_fabricate(Vaddr address, + Phys_addr* phys, Size* size, unsigned* attribs = 0) +{ + return Mem_space::v_lookup(address.trunc(Size(Map_page_size)), + phys, size, attribs); +} + +PUBLIC virtual +bool +Mem_space::is_sigma0() const +{ return false; } + +//--------------------------------------------------------------------------- +IMPLEMENTATION [!io]: + +PUBLIC inline +Mword +Mem_space::get_io_counter (void) +{ return 0; } + +PUBLIC inline +bool +Mem_space::io_lookup (Address) +{ return false; } diff --git a/kernel/fiasco/src/kern/member_offs.h b/kernel/fiasco/src/kern/member_offs.h new file mode 100644 index 00000000..273a373e --- /dev/null +++ b/kernel/fiasco/src/kern/member_offs.h @@ -0,0 +1,7 @@ +#ifndef __MEMBER_OFFSET_H__ +#define __MEMBER_OFFSET_H__ + +#define MEMBER_OFFSET() \ + friend void offsets_func(char **a, unsigned long **b) + +#endif // __MEMBER_OFFSET_H__ diff --git a/kernel/fiasco/src/kern/mp_lock.cpp b/kernel/fiasco/src/kern/mp_lock.cpp new file mode 100644 index 00000000..78988bcb --- /dev/null +++ b/kernel/fiasco/src/kern/mp_lock.cpp @@ -0,0 +1,182 @@ +INTERFACE: + +#include "queue.h" + +class Mp_lock +{ +public: + enum Status { Not_locked, Locked, Invalid }; + +private: + /** queue of blocked threads */ + Queue _q; +}; + + +//---------------------------------------------------------------------------- +IMPLEMENTATION: + +#include "context.h" +#include "cpu_lock.h" +#include "globals.h" +#include "kdb_ke.h" +#include "lock_guard.h" +#include "thread_state.h" +//#include "logdefs.h" + +PUBLIC inline NEEDS["context.h", "cpu_lock.h", "globals.h", + "kdb_ke.h", "lock_guard.h", "thread_state.h"] +Mp_lock::Status +Mp_lock::test_and_set() +{ + //assert_kdb (cpu_lock.test()); + + Context *const c = current(); + + Lock_guard g(&cpu_lock); + + { + Lock_guard guard(_q.q_lock()); + if (EXPECT_FALSE(_q.invalid())) + return Invalid; + + if (!_q.blocked()) + { + // lock was free, take it + _q.block(); + return Not_locked; + } + + _q.enqueue(c->queue_item()); + } + // LOG_MSG_3VAL(c, "block", (Mword)this, current_cpu(), *((Mword*)this)); + assert_kdb (!(c->state() & Thread_drq_ready)); + while (1) + { + c->state_change_dirty(~Thread_ready, Thread_waiting); + c->schedule(); + + if (!c->queue_item()->queued()) + break; + } + + c->state_del_dirty(Thread_waiting); + + // LOG_MSG_3VAL(c, "woke", (Mword)this, current_cpu(), 0); + + switch (c->queue_item()->status()) + { + case Queue_item::Ok: return Not_locked; + case Queue_item::Invalid: return Invalid; + case Queue_item::Retry: assert_kdb (false); + } + + return Invalid; +} + +PUBLIC inline NEEDS[Mp_lock::test_and_set] +Mp_lock::Status +Mp_lock::lock() +{ return test_and_set(); } + +PUBLIC inline NEEDS["context.h", "cpu_lock.h", "globals.h", + "kdb_ke.h", "lock_guard.h"] +void +Mp_lock::clear() +{ + //assert_kdb (cpu_lock.test()); + + Queue_item *f; + + { + Lock_guard guard(_q.q_lock()); + //LOG_MSG_3VAL(current(), "clear", (Mword)this, current_cpu(), *((Mword*)this)); + assert_kdb (_q.blocked()); + + f = _q.first(); + if (!f) + { + _q.unblock(); + return; + } + + _q.dequeue(f, Queue_item::Ok); + } + // LOG_MSG_3VAL(current(), "wake", Mword(context_of(f)), (Mword)this, current_cpu()); + assert_kdb (current()->state() & Thread_ready_mask); + context_of(f)->activate(); +} + +PUBLIC inline NEEDS["kdb_ke.h"] +void +Mp_lock::wait_free() +{ + + Context *const c = current(); + + Lock_guard g(&cpu_lock); + + { + Lock_guard guard(_q.q_lock()); + assert_kdb (invalid()); + + if (!_q.blocked()) + return; + + _q.enqueue(c->queue_item()); + } + + while (1) + { + c->state_change_dirty(~Thread_ready, Thread_waiting); + c->schedule(); + + if (!c->queue_item()->queued()) + break; + } + + c->state_del_dirty(Thread_waiting); +} + +PUBLIC inline +bool +Mp_lock::test() const +{ return _q.blocked(); } + + +PUBLIC inline NEEDS[Mp_lock::clear] +void +Mp_lock::set(Status s) +{ + if (s == Not_locked) + clear(); +} + +PUBLIC +void +Mp_lock::invalidate() +{ + { + Lock_guard guard(_q.q_lock()); + _q.invalidate(); + } + + Queue_item *f; + while (1) + { + Lock_guard guard(_q.q_lock()); + f = _q.first(); + + //LOG_MSG_3VAL(current(), "deq", Mword(f), 0, 0); + if (!f) + break; + + _q.dequeue(f, Queue_item::Invalid); + context_of(f)->activate(); + } +} + +PUBLIC inline +bool +Mp_lock::invalid() const +{ return _q.invalid(); } diff --git a/kernel/fiasco/src/kern/obj_helping_lock.cpp b/kernel/fiasco/src/kern/obj_helping_lock.cpp new file mode 100644 index 00000000..d616fa84 --- /dev/null +++ b/kernel/fiasco/src/kern/obj_helping_lock.cpp @@ -0,0 +1,76 @@ +INTERFACE: + +#include "switch_lock.h" + +#ifdef NO_INSTRUMENT +#undef NO_INSTRUMENT +#endif +#define NO_INSTRUMENT __attribute__((no_instrument_function)) + +class Obj_lock_valid +{ +}; + +/** A wrapper for Switch_lock that works even when the threading system + has not been intialized yet. + This wrapper is necessary because most lock-protected objects are + initialized before the threading system has been fired up. + */ +class Obj_helping_lock : private Switch_lock +{ +private: + typedef Switch_lock Lock; + +public: + using Lock::Status; + using Lock::Invalid; + using Lock::Locked; + using Lock::Not_locked; + + using Lock::Lock_context; + + using Lock::test_and_set; + using Lock::test_and_set_dirty; + using Lock::lock; + using Lock::lock_dirty; + using Lock::clear; + using Lock::clear_dirty; + + using Lock::test; + using Lock::lock_owner; + + /* + * Can use the Switch_lock version, because we assume the context + * is invalid during switch_dirty and we do not need to consider it + * for scheduling any more. + */ + using Lock::clear_no_switch_dirty; + using Lock::switch_dirty; + +private: + friend class Obj_lock_valid; + bool _valid; + +}; + +#undef NO_INSTRUMENT +#define NO_INSTRUMENT + +IMPLEMENTATION: + +PUBLIC inline +Obj_helping_lock::Obj_helping_lock() +: _valid(true) +{} + +PUBLIC inline static +bool Obj_lock_valid::valid(Switch_lock const *lock) +{ + Obj_helping_lock const *l = static_cast(lock); + return l->_valid; +} + +PUBLIC inline +void +Obj_helping_lock::invalidate() +{ _valid = false; } diff --git a/kernel/fiasco/src/kern/obj_ref_ptr.cpp b/kernel/fiasco/src/kern/obj_ref_ptr.cpp new file mode 100644 index 00000000..fe38d442 --- /dev/null +++ b/kernel/fiasco/src/kern/obj_ref_ptr.cpp @@ -0,0 +1,44 @@ +INTERFACE: + +class Ram_quota; + +template< typename T > +class Ref_ptr +{ +public: + class Inv_ptr; + Ref_ptr(Ref_ptr const &o) : _o(o._o) { inc_ref_cnt(); } + Ref_ptr(T *o = 0) : _o(o) { inc_ref_cnt(); } + ~Ref_ptr() { dec_ref_cnt(); } + + void operator = (Ref_ptr const &o) + { dec_ref_cnt(); _o = o._o; inc_ref_cnt(); } + + void operator = (T *o) + { dec_ref_cnt(); _o = o; inc_ref_cnt(); } + + T *operator -> () const { return _o; } + T *operator * () const { return _o; } + operator Inv_ptr const * () const + { return reinterpret_cast(_o); } + +private: + T *_o; + + void inc_ref_cnt() + { + if (_o) + { + Lock_guard guard(&cpu_lock); + _o->inc_ref_cnt(); + } + } + + void dec_ref_cnt() const + { + if (_o && _o->dec_ref_cnt() == 0) + delete _o; + } + +}; + diff --git a/kernel/fiasco/src/kern/obj_space-phys.cpp b/kernel/fiasco/src/kern/obj_space-phys.cpp new file mode 100644 index 00000000..0fbd2bdc --- /dev/null +++ b/kernel/fiasco/src/kern/obj_space-phys.cpp @@ -0,0 +1,243 @@ +INTERFACE: + +#include "assert_opt.h" + +EXTENSION class Generic_obj_space +{ +private: + enum + { + Slots_per_dir = Config::PAGE_SIZE / sizeof(void*) + }; + + struct Cap_table { Entry e[Caps_per_page]; }; + struct Cap_dir { Cap_table *d[Slots_per_dir]; }; + Cap_dir *_dir; + + Ram_quota *ram_quota() const + { + assert_opt (this); + return static_cast(this)->ram_quota(); + } +}; + + +//---------------------------------------------------------------------------- +IMPLEMENTATION: + +#include +#include + +#include "atomic.h" +#include "config.h" +#include "cpu.h" +#include "kdb_ke.h" +#include "kmem_alloc.h" +#include "mem.h" +#include "mem_layout.h" +#include "ram_quota.h" +#include "static_assert.h" + + +PUBLIC template< typename SPACE > +inline NEEDS["static_assert.h"] +Generic_obj_space::Generic_obj_space() +{ + static_assert(sizeof(Cap_dir) == Config::PAGE_SIZE, "cap_dir size mismatch"); + _dir = (Cap_dir*)Kmem_alloc::allocator()->q_unaligned_alloc(ram_quota(), Config::PAGE_SIZE); + if (_dir) + Mem::memset_mwords(_dir, 0, Config::PAGE_SIZE / sizeof(Mword)); +} + +PRIVATE template< typename SPACE > +typename Generic_obj_space::Entry * +Generic_obj_space::get_cap(Address index) +{ + if (EXPECT_FALSE(!_dir)) + return 0; + + unsigned d_idx = index / Caps_per_page; + if (EXPECT_FALSE(d_idx >= Slots_per_dir)) + return 0; + + Cap_table *tab = _dir->d[d_idx]; + + if (EXPECT_FALSE(!tab)) + return 0; + + unsigned offs = index % Caps_per_page; + return &tab->e[offs]; +} + +PRIVATE template< typename SPACE > +typename Generic_obj_space::Entry * +Generic_obj_space::caps_alloc(Address virt) +{ + static_assert(sizeof(Cap_table) == Config::PAGE_SIZE, "cap table size mismatch"); + unsigned d_idx = virt / Caps_per_page; + if (EXPECT_FALSE(d_idx >= Slots_per_dir)) + return 0; + + void *mem = Kmem_alloc::allocator()->q_unaligned_alloc(ram_quota(), Config::PAGE_SIZE); + + if (!mem) + return 0; + + add_dbg_info(mem, this, virt); + + Mem::memset_mwords(mem, 0, Config::PAGE_SIZE / sizeof(Mword)); + + + + Cap_table *tab = _dir->d[d_idx] = (Cap_table*)mem; + + return &tab->e[virt % Caps_per_page]; +} + +PRIVATE template< typename SPACE > +void +Generic_obj_space::caps_free() +{ + if (!_dir) + return; + + Cap_dir *d = _dir; + _dir = 0; + + Kmem_alloc *a = Kmem_alloc::allocator(); + for (unsigned i = 0; i < Slots_per_dir; ++i) + { + if (!d->d[i]) + continue; + + remove_dbg_info(d->d[i]); + a->q_unaligned_free(ram_quota(), Config::PAGE_SIZE, d->d[i]); + } + + a->q_unaligned_free(ram_quota(), Config::PAGE_SIZE, d); +} + +// +// Utilities for map and unmap +// + +PUBLIC template< typename SPACE > +inline NEEDS[Generic_obj_space::get_cap] +bool +Generic_obj_space::v_lookup(Addr const &virt, Phys_addr *phys = 0, + Size *size = 0, unsigned *attribs = 0) +{ + if (size) *size = Size::create(1); + Entry *cap = get_cap(virt.value()); + + if (EXPECT_FALSE(!cap)) + { + if (size) *size = Size::create(Caps_per_page); + return false; + } + + Capability c = *cap; + + Obj::set_entry(virt, cap); + if (phys) *phys = c.obj(); + if (c.valid() && attribs) *attribs = cap->rights(); + return c.valid(); +} + +PUBLIC template< typename SPACE > +inline NEEDS [Generic_obj_space::get_cap] +typename Generic_obj_space::Capability +Generic_obj_space::lookup(Address virt) +{ + Capability *c = get_cap(virt); + + if (EXPECT_FALSE(!c)) + return Capability(0); // void + + return *c; +} + +PUBLIC template< typename SPACE > +inline +Kobject_iface * +Generic_obj_space::lookup_local(Address virt, unsigned char *rights = 0) +{ + Entry *c = get_cap(virt); + + if (EXPECT_FALSE(!c)) + return 0; + + Capability cap = *c; + + if (rights) + *rights = cap.rights(); + + return cap.obj(); +} + + +PUBLIC template< typename SPACE > +inline NEEDS[, Generic_obj_space::get_cap] +unsigned long +Generic_obj_space::v_delete(Page_number virt, Size size, + unsigned long page_attribs = L4_fpage::RWX) +{ + (void)size; + assert (size.value() == 1); + Capability *c = get_cap(virt.value()); + + if (c && c->valid()) + { + if (page_attribs & L4_fpage::R) + c->invalidate(); + else + c->del_rights(page_attribs & L4_fpage::WX); + } + + return 0; +} + +PUBLIC template< typename SPACE > +inline NEEDS[Generic_obj_space::caps_alloc, "kdb_ke.h"] +typename Generic_obj_space::Status +Generic_obj_space::v_insert(Phys_addr phys, Addr const &virt, Size size, + unsigned char page_attribs) +{ + (void)size; + assert (size.value() == 1); + + Entry *c = get_cap(virt.value()); + + if (!c && !(c = caps_alloc(virt.value()))) + return Insert_err_nomem; + + assert (size.value() == 1); + + if (c->valid()) + { + if (c->obj() == phys) + { + if (EXPECT_FALSE(c->rights() == page_attribs)) + return Insert_warn_exists; + + c->add_rights(page_attribs); + return Insert_warn_attrib_upgrade; + } + else + return Insert_err_exists; + } + + Obj::set_entry(virt, c); + c->set(phys, page_attribs); + return Insert_ok; +} + + +PUBLIC template< typename SPACE > +static inline +typename Generic_obj_space::Addr +Generic_obj_space::map_max_address() +{ + return Addr(Slots_per_dir * Caps_per_page); +} + diff --git a/kernel/fiasco/src/kern/obj_space-virt.cpp b/kernel/fiasco/src/kern/obj_space-virt.cpp new file mode 100644 index 00000000..d42f551a --- /dev/null +++ b/kernel/fiasco/src/kern/obj_space-virt.cpp @@ -0,0 +1,315 @@ +INTERFACE: + +#include "mem.h" +#include "mem_space.h" +#include "ram_quota.h" + +EXTENSION class Generic_obj_space +{ + // do not use the virtually mapped cap table in + // v_lookup and v_insert, because the map logic needs the kernel + // address for link pointers in the map-nodes and these addresses must + // be valid in all address spaces. + enum { Optimize_local = 0 }; +}; + +IMPLEMENTATION: + +#include +#include + +#include "atomic.h" +#include "config.h" +#include "cpu.h" +#include "kdb_ke.h" +#include "kmem_alloc.h" +#include "mem_layout.h" + +PRIVATE template< typename SPACE > inline +Mem_space * +Generic_obj_space::mem_space() +{ return static_cast(this); } + +PRIVATE template< typename SPACE > +static inline NEEDS["mem_layout.h"] +typename Generic_obj_space::Entry * +Generic_obj_space::cap_virt(Address index) +{ return reinterpret_cast(Mem_layout::Caps_start) + index; } + +PRIVATE template< typename SPACE > +inline NEEDS["mem_space.h", "mem_layout.h", Generic_obj_space::cap_virt] +typename Generic_obj_space::Entry * +Generic_obj_space::alien_lookup(Address index) +{ + Mem_space *ms = mem_space(); + + Address phys = Address(ms->virt_to_phys((Address)cap_virt(index))); + if (EXPECT_FALSE(phys == ~0UL)) + return 0; + + return reinterpret_cast(Mem_layout::phys_to_pmem(phys)); +} + +PRIVATE template< typename SPACE > +typename Generic_obj_space::Entry * +Generic_obj_space::get_cap(Address index) +{ return alien_lookup(index); } + +PUBLIC template< typename SPACE > +inline NEEDS["mem_space.h"] +Ram_quota * +Generic_obj_space::ram_quota() const +{ return static_cast(this)->ram_quota(); } + + +PRIVATE template< typename SPACE > +/*inline NEEDS["kmem_alloc.h", , "ram_quota.h", + Generic_obj_space::cap_virt]*/ +typename Generic_obj_space::Entry * +Generic_obj_space::caps_alloc(Address virt) +{ + Address cv = (Address)cap_virt(virt); + void *mem = Kmem_alloc::allocator()->q_unaligned_alloc(ram_quota(), Config::PAGE_SIZE); + + if (!mem) + return 0; + + add_dbg_info(mem, this, virt); + + Mem::memset_mwords(mem, 0, Config::PAGE_SIZE / sizeof(Mword)); + + Mem_space::Status s; + s = mem_space()->v_insert( + Mem_space::Phys_addr::create(Mem_space::kernel_space()->virt_to_phys((Address)mem)), + Mem_space::Addr::create(cv).trunc(Mem_space::Size::create(Config::PAGE_SIZE)), + Mem_space::Size::create(Config::PAGE_SIZE), + Mem_space::Page_cacheable | Mem_space::Page_writable + | Mem_space::Page_referenced | Mem_space::Page_dirty); + + switch (s) + { + case Insert_ok: + break; + case Insert_warn_exists: + case Insert_warn_attrib_upgrade: + assert (false); + break; + case Insert_err_exists: + case Insert_err_nomem: + Kmem_alloc::allocator()->q_unaligned_free(ram_quota(), + Config::PAGE_SIZE, mem); + return 0; + }; + + unsigned long cap = cv & (Config::PAGE_SIZE - 1) | (unsigned long)mem; + + return reinterpret_cast(cap); +} + +PRIVATE template< typename SPACE > +void +Generic_obj_space::caps_free() +{ + Mem_space *ms = mem_space(); + if (EXPECT_FALSE(!ms || !ms->dir())) + return; + + Kmem_alloc *a = Kmem_alloc::allocator(); + for (unsigned long i = 0; i < map_max_address().value(); + i += Caps_per_page) + { + Entry *c = get_cap(i); + if (!c) + continue; + + Address cp = Address(ms->virt_to_phys(Address(c))); + assert_kdb (cp != ~0UL); + void *cv = (void*)Mem_layout::phys_to_pmem(cp); + remove_dbg_info(cv); + + a->q_unaligned_free(ram_quota(), Config::PAGE_SIZE, cv); + } +#if defined (CONFIG_ARM) + ms->dir()->free_page_tables((void*)Mem_layout::Caps_start, (void*)Mem_layout::Caps_end, Kmem_alloc::q_allocator(ram_quota())); +#else + ms->dir()->destroy(Virt_addr(Mem_layout::Caps_start), + Virt_addr(Mem_layout::Caps_end), Pdir::Depth - 1, + Kmem_alloc::q_allocator(ram_quota())); +#endif +} + +// +// Utilities for map and unmap +// + +PUBLIC template< typename SPACE > +inline NEEDS[Generic_obj_space::cap_virt, Generic_obj_space::get_cap] +bool +Generic_obj_space::v_lookup(Addr const &virt, Phys_addr *phys = 0, + Size *size = 0, unsigned *attribs = 0) +{ + if (size) size->set_value(1); + Entry *cap; + + if (Optimize_local + && mem_space() == Mem_space::current_mem_space(current_cpu())) + cap = cap_virt(virt.value()); + else + cap = get_cap(virt.value()); + + if (EXPECT_FALSE(!cap)) + { + if (size) size->set_value(Caps_per_page); + return false; + } + + if (Optimize_local) + { + Capability c = Mem_layout::read_special_safe((Capability*)cap); + + if (phys) *phys = c.obj(); + if (c.valid() && attribs) *attribs = c.rights(); + return c.valid(); + } + else + { + Obj::set_entry(virt, cap); + if (phys) *phys = cap->obj(); + if (cap->valid() && attribs) *attribs = cap->rights(); + return cap->valid(); + } +} + +PUBLIC template< typename SPACE > +inline NEEDS [Generic_obj_space::cap_virt, Generic_obj_space::get_cap] +typename Generic_obj_space::Capability +Generic_obj_space::lookup(Address virt) +{ + Capability *c; + virt &= ~(~0UL << Whole_space); + + if (mem_space() == Mem_space::current_mem_space(current_cpu())) + c = reinterpret_cast(cap_virt(virt)); + else + c = get_cap(virt); + + if (EXPECT_FALSE(!c)) + return Capability(0); // void + + return Mem_layout::read_special_safe(c); +} + +PUBLIC template< typename SPACE > +inline NEEDS [Generic_obj_space::cap_virt] +Kobject_iface * +Generic_obj_space::lookup_local(Address virt, unsigned char *rights = 0) +{ + virt &= ~(~0UL << Whole_space); + Capability *c = reinterpret_cast(cap_virt(virt)); + Capability cap = Mem_layout::read_special_safe(c); + if (rights) *rights = cap.rights(); + return cap.obj(); +} + + +PUBLIC template< typename SPACE > +inline NEEDS[, Generic_obj_space::cap_virt, Generic_obj_space::get_cap] +unsigned long +Generic_obj_space::v_delete(Page_number virt, Size size, + unsigned long page_attribs = L4_fpage::CRWSD) +{ + (void)size; + assert (size.value() == 1); + + Entry *c; + if (Optimize_local + && mem_space() == Mem_space::current_mem_space(current_cpu())) + { + c = cap_virt(virt.value()); + if (!c) + return 0; + + Capability cap = Mem_layout::read_special_safe((Capability*)c); + if (!cap.valid()) + return 0; + } + else + c = get_cap(virt.value()); + + if (c && c->valid()) + { + if (page_attribs & L4_fpage::R) + c->invalidate(); + else + c->del_rights(page_attribs & L4_fpage::CWSD); + } + + return 0; +} + +PUBLIC template< typename SPACE > +inline NEEDS[Generic_obj_space::cap_virt, Generic_obj_space::caps_alloc, + Generic_obj_space::alien_lookup, "kdb_ke.h"] +typename Generic_obj_space::Status +Generic_obj_space::v_insert(Phys_addr phys, Addr const &virt, Size size, + unsigned char page_attribs) +{ + (void)size; + assert (size.value() == 1); + + Entry *c; + + if (Optimize_local + && mem_space() == Mem_space::current_mem_space(current_cpu())) + { + c = cap_virt(virt.value()); + if (!c) + return Insert_err_nomem; + + Capability cap; + if (!Mem_layout::read_special_safe((Capability*)c, cap) + && !caps_alloc(virt.value())) + return Insert_err_nomem; + } + else + { + c = alien_lookup(virt.value()); + if (!c && !(c = caps_alloc(virt.value()))) + return Insert_err_nomem; + Obj::set_entry(virt, c); + } + + if (c->valid()) + { + if (c->obj() == phys) + { + if (EXPECT_FALSE(c->rights() == page_attribs)) + return Insert_warn_exists; + + c->add_rights(page_attribs); + return Insert_warn_attrib_upgrade; + } + else + return Insert_err_exists; + } + + c->set(phys, page_attribs); + return Insert_ok; +} + + +PUBLIC template< typename SPACE > +static inline +typename Generic_obj_space::Addr +Generic_obj_space::map_max_address() +{ + Mword r; + + r = (Mem_layout::Caps_end - Mem_layout::Caps_start) / sizeof(Entry); + if (Map_max_address < r) + r = Map_max_address; + + return Addr(r); +} + + diff --git a/kernel/fiasco/src/kern/obj_space.cpp b/kernel/fiasco/src/kern/obj_space.cpp new file mode 100644 index 00000000..e8b110d2 --- /dev/null +++ b/kernel/fiasco/src/kern/obj_space.cpp @@ -0,0 +1,321 @@ +INTERFACE: + +#include "config.h" +#include "l4_types.h" +#include "l4_msg_item.h" +#include + +class Kobject_mapdb; +class Jdb_mapdb; +class Kobject_iface; +class Kobject; +class Space; +class Ram_quota; +class Mem_space; + + +namespace Obj { + + class Capability + { + private: + Mword _obj; + + public: + Capability() {} + explicit Capability(Mword v) : _obj(v) {} + Kobject_iface *obj() const { return (Kobject_iface *)(_obj & ~3UL); } + //void obj(Phys_addr obj) { _obj = Mword(obj); } + void set(Kobject_iface *obj, unsigned char rights) + { _obj = Mword(obj) | rights; } + bool valid() const { return _obj; } + void invalidate() { _obj = 0; } + unsigned char rights() const { return _obj & 3; } + void add_rights(unsigned char r) { _obj |= r & L4_fpage::CWS; } + void del_rights(unsigned char r) { _obj &= ~(r & L4_fpage::CWS); } + + bool operator == (Capability const &c) const { return _obj == c._obj; } + }; + + /** + * Tn the case of a flat copy model for capabilities, we have some + * extra mapping information directly colocated within the cap tables. + */ + class Mapping : public cxx::H_list_item + { + friend class ::Kobject_mapdb; + friend class ::Jdb_mapdb; + + public: + typedef cxx::H_list List; + + enum Flag + { + Delete = L4_fpage::CD, + Ref_cnt = 0x10, + + Initial_flags = Delete | Ref_cnt | L4_msg_item::C_ctl_rights + }; + + protected: + Mword _flags : 8; + Mword _pad : 24; + + public: + Mapping() : _flags(0) {} + // fake this really badly + Mapping *parent() { return this; } + Mword delete_rights() const { return _flags & Delete; } + Mword ref_cnt() const { return _flags & Ref_cnt; } + + void put_as_root() { _flags = Initial_flags; } + }; + + + class Entry : public Capability, public Mapping + { + public: + Entry() {} + explicit Entry(Mword v) : Capability(v) {} + + unsigned rights() const + { return Capability::rights() | (_flags & ~3); } + + void set(Kobject_iface *obj, unsigned char rights) + { + Capability::set(obj, rights & 3); + _flags = rights & 0xf8; + } + void add_rights(unsigned char r) + { + Capability::add_rights(r & 3); + _flags |= (r & 0xf8); + } + + void del_rights(unsigned char r) + { + Capability::del_rights(r & 3); + _flags &= ~(r & 0xf8); + } + }; + + + struct Cap_addr + { + public: + Page_number _a; + mutable Entry *_c; + Cap_addr() {} + Cap_addr(Page_number a, Entry *c) : _a(a), _c(c) {} + + explicit Cap_addr(Page_number a) : _a(a), _c(0) {} + explicit Cap_addr(Address adr) : _a(adr), _c(0) {} + + Address value() const { return _a.value(); } + void set_entry(Entry *e) const { _c = e; } + + bool operator == (Cap_addr const &o) const { return _a == o._a; } + bool operator < (Cap_addr const &o) const { return _a < o._a; } + bool operator > (Cap_addr const &o) const { return _a > o._a; } + + void operator += (Page_number o) { _a += o; } + void operator += (Cap_addr const &o) { operator += (o._a); } + + Cap_addr operator + (Page_number o) const { return Cap_addr(_a + o); } + + Cap_addr offset(Page_number s) const { return Cap_addr(_a.offset(s)); } + Cap_addr trunc(Page_number s) const + { + if (s == Page_number(1)) + return *this; + return Cap_addr(_a.trunc(s)); + } + + operator Page_number::Type_conversion_error const * () const + { return (Page_number::Type_conversion_error const *)_a; } + + operator Page_number () const { return _a; } + }; + + inline void set_entry(Cap_addr const &ca, Entry *e) + { ca.set_entry(e); } +}; + + + +template< typename SPACE > +class Generic_obj_space +{ + friend class Jdb_obj_space; + friend class Jdb_tcb; + +public: + enum { Caps_per_page = Config::PAGE_SIZE / sizeof(Obj::Entry) }; + + static char const * const name; + + typedef Obj::Capability Capability; + typedef Obj::Entry Entry; + typedef Kobject *Reap_list; + typedef Kobject_iface *Phys_addr; + typedef Obj::Cap_addr Addr; + typedef Page_count Size; + + enum + { + Need_insert_tlb_flush = 0, + Need_xcpu_tlb_flush = 0, + Map_page_size = 1, + Page_shift = 0, + Map_superpage_size = 1, + Map_max_address = 1UL << 20, /* 20bit obj index */ + Whole_space = 20, + Identity_map = 0, + }; + + enum Status + { + Insert_ok = 0, ///< Mapping was added successfully. + Insert_warn_exists, ///< Mapping already existed + Insert_warn_attrib_upgrade, ///< Mapping already existed, attribs upgrade + Insert_err_nomem, ///< Couldn't alloc new page table + Insert_err_exists ///< A mapping already exists at the target addr + }; + + enum Page_attrib + { + /// A mask which contains all mask bits + //Page_user_accessible = 1, + //Page_writable = 2, + Page_references = 0, + Page_all_attribs = 3 + }; + + static Address superpage_size() { return Map_superpage_size; } + static bool has_superpages() { return false; } + static Phys_addr page_address(Phys_addr o, Size) { return o; } + static Phys_addr subpage_address(Phys_addr addr, Size) { return addr; } +}; + +template< typename SPACE > +char const * const Generic_obj_space::name = "Obj_space"; + + +// ------------------------------------------------------------------------- +IMPLEMENTATION: + +PUBLIC template< typename SPACE > +static inline +Mword +Generic_obj_space::xlate_flush(unsigned char rights) +{ return rights; } + +PUBLIC template< typename SPACE > +static inline +Mword +Generic_obj_space::is_full_flush(unsigned char rights) +{ return rights & L4_fpage::R; } + +PUBLIC template< typename SPACE > +static inline +Mword +Generic_obj_space::xlate_flush_result(Mword /*attribs*/) +{ return 0; } + +PUBLIC template< typename SPACE > +inline NEEDS[Generic_obj_space::caps_free] +Generic_obj_space::~Generic_obj_space() +{ + caps_free(); +} + +PUBLIC template< typename SPACE > +inline +bool +Generic_obj_space::v_fabricate(Addr const &address, + Phys_addr *phys, Size *size, + unsigned* attribs = 0) +{ + return Generic_obj_space::v_lookup(address, phys, size, attribs); +} + + +PUBLIC template< typename SPACE > +inline static +void +Generic_obj_space::tlb_flush () +{} + +PUBLIC template< typename SPACE > +inline static +typename Generic_obj_space::Addr +Generic_obj_space::canonize(Addr v) +{ return v; } + +// ------------------------------------------------------------------------ +INTERFACE [debug]: + +EXTENSION class Generic_obj_space +{ +public: + struct Dbg_info + { + Address offset; + Generic_obj_space *s; + }; + +}; + + +// ------------------------------------------------------------------------ +IMPLEMENTATION [debug]: + +#include "dbg_page_info.h" +#include "warn.h" + +PUBLIC template< typename SPACE > +static +void +Generic_obj_space::add_dbg_info(void *p, Generic_obj_space *s, + Address cap) +{ + Dbg_page_info *info = new Dbg_page_info(Virt_addr((Address)p)); + + if (EXPECT_FALSE(!info)) + { + WARN("oom: could not allocate debug info fo page %p\n", p); + return; + } + + info->info()->s = s; + info->info()->offset = (cap / Caps_per_page) * Caps_per_page; + Dbg_page_info::table().insert(info); +} + +PUBLIC template< typename SPACE > +static +void +Generic_obj_space::remove_dbg_info(void *p) +{ + Dbg_page_info *info = Dbg_page_info::table().remove(Virt_addr((Address)p)); + if (info) + delete info; + else + WARN("could not find debug info for page %p\n", p); +} + + +// ------------------------------------------------------------------------ +IMPLEMENTATION [!debug]: + +PUBLIC template< typename SPACE > inline +static +void +Generic_obj_space::add_dbg_info(void *, Generic_obj_space *, Address) +{} + +PUBLIC template< typename SPACE > inline +static +void +Generic_obj_space::remove_dbg_info(void *) +{} diff --git a/kernel/fiasco/src/kern/paging.cpp b/kernel/fiasco/src/kern/paging.cpp new file mode 100644 index 00000000..a482d9c6 --- /dev/null +++ b/kernel/fiasco/src/kern/paging.cpp @@ -0,0 +1,137 @@ +INTERFACE: + +#include "types.h" + +namespace Page { + + /* These things must be defined in arch part in + the most efficent way according to the architecture. + + typedef int Attribs; + + enum Attribs_enum { + USER_NO = xxx, ///< User No access + USER_RO = xxx, ///< User Read only + USER_RW = xxx, ///< User Read/Write + USER_RX = xxx, ///< User Read/Execute + USER_XO = xxx, ///< User Execute only + USER_RWX = xxx, ///< User Read/Write/Execute + + NONCACHEABLE = xxx, ///< Caching is off + CACHEABLE = xxx, ///< Cahe is enabled + }; + + + */ + + +}; + +EXTENSION class PF { +public: + static Mword is_translation_error( Mword error ); + static Mword is_usermode_error( Mword error ); + static Mword is_read_error( Mword error ); + static Mword addr_to_msgword0( Address pfa, Mword error ); + static Mword pc_to_msgword1( Address pc, Mword error ); +}; + + +class Pdir_alloc_null +{ +public: + Pdir_alloc_null() {} + void *alloc(unsigned long) const { return 0; } + void free(void *, unsigned long) const {} + bool valid() const { return false; } +}; + +template +class Pdir_alloc_simple +{ +public: + Pdir_alloc_simple(ALLOC *a = 0) : _a(a) {} + + void *alloc(unsigned long size) const + { return _a->unaligned_alloc(size); } + + void free(void *block, unsigned long size) const + { return _a->unaligned_free(size, block); } + + bool valid() const { return _a; } + +private: + ALLOC *_a; +}; + + +class Pdir : public Ptab::Base +{ +public: + enum { Super_level = Pte_base::Super_level }; + +private: + static bool _have_superpages; + static unsigned _super_level; +}; + +IMPLEMENTATION: +//--------------------------------------------------------------------------- + +bool Pdir::_have_superpages; +unsigned Pdir::_super_level; + +template +inline Pdir_alloc_simple pdir_alloc(ALLOC *a) +{ return Pdir_alloc_simple(a); } + +PUBLIC static inline +void +Pdir::have_superpages(bool yes) +{ + _have_superpages = yes; + _super_level = yes ? Super_level : (Super_level + 1); +} + +PUBLIC static inline +unsigned +Pdir::super_level() +{ return _super_level; } + + +IMPLEMENT inline NEEDS[PF::is_usermode_error] +Mword PF::pc_to_msgword1(Address pc, Mword error) +{ + return is_usermode_error(error) ? pc : (Mword)-1; +} + +//--------------------------------------------------------------------------- +IMPLEMENTATION[!ppc32]: + +PUBLIC +Address +Pdir::virt_to_phys(Address virt) const +{ + Iter i = walk(Virt_addr(virt)); + if (!i.e->valid()) + return ~0; + + return i.e->addr() | (virt & ~(~0UL << i.shift())); +} + +//--------------------------------------------------------------------------- +IMPLEMENTATION[ppc32]: + +PUBLIC +Address +Pdir::virt_to_phys(Address virt) const +{ + Iter i = walk(Virt_addr(virt)); + + if (!i.e->valid()) + return ~0UL; + + Address phys; + Pte_htab::pte_lookup(i.e, &phys); + return phys | (virt & ~(~0UL << i.shift())); +} diff --git a/kernel/fiasco/src/kern/per_cpu_data.cpp b/kernel/fiasco/src/kern/per_cpu_data.cpp new file mode 100644 index 00000000..90b5a139 --- /dev/null +++ b/kernel/fiasco/src/kern/per_cpu_data.cpp @@ -0,0 +1,319 @@ +INTERFACE [mp]: + +struct Per_cpu_ctor_data +{ + void (*func)(void *, unsigned); + void *base; +}; + +#define DEFINE_PER_CPU_CTOR_UID(b) __per_cpu_ctor_ ## b +#define DEFINE_PER_CPU_CTOR_DATA(id) \ + __attribute__((section(".bss.per_cpu_ctor_data"),used)) \ + static Per_cpu_ctor_data DEFINE_PER_CPU_CTOR_UID(id); + +INTERFACE [!mp]: + +#define DEFINE_PER_CPU_CTOR_DATA(id) + +INTERFACE: + +#include "static_init.h" +#include "context_base.h" +#include + +#define DEFINE_PER_CPU_P(p) \ + DEFINE_PER_CPU_CTOR_DATA(__COUNTER__) \ + __attribute__((section(".per_cpu.data"),init_priority(0xfffe - p))) + +#define DEFINE_PER_CPU DEFINE_PER_CPU_P(9) +#define DEFINE_PER_CPU_LATE DEFINE_PER_CPU_P(19) + +class Per_cpu_data +{ +public: + static void init_ctors(); + static void run_ctors(unsigned cpu); + static void run_late_ctors(unsigned cpu); + static bool valid(unsigned cpu); +}; + +template< typename T > class Per_cpu_ptr; + +template< typename T > +class Per_cpu : private Per_cpu_data +{ + friend class Per_cpu_ptr; +public: + typedef T Type; + + T const &cpu(unsigned) const; + T &cpu(unsigned); + + T const ¤t() const { return cpu(current_cpu()); } + T ¤t() { return cpu(current_cpu()); } + + Per_cpu(); + explicit Per_cpu(bool); + +private: + T _d; +}; + +template< typename T > +class Per_cpu_ptr : private Per_cpu_data +{ +public: + typedef typename cxx::conditional< + cxx::is_const::value, + Per_cpu::type> const, + Per_cpu::type> >::type Per_cpu_type; + + Per_cpu_ptr() {} + Per_cpu_ptr(Per_cpu_type *o) : _p(&o->_d) {} + Per_cpu_ptr &operator = (Per_cpu_type *o) + { + _p = &o->_d; + return *this; + } + + T &cpu(unsigned cpu); + T ¤t() { return cpu(current_cpu()); } + +private: + T *_p; +}; + + +//--------------------------------------------------------------------------- +IMPLEMENTATION [!mp]: + +#include + +IMPLEMENT inline +bool +Per_cpu_data::valid(unsigned cpu) +{ +#if defined NDEBUG + (void)cpu; + return 1; +#else + return cpu == 0; +#endif +} + +IMPLEMENT inline +template< typename T > +T const &Per_cpu::cpu(unsigned) const { return _d; } + +IMPLEMENT inline +template< typename T > +T &Per_cpu::cpu(unsigned) { return _d; } + +IMPLEMENT +template< typename T > +Per_cpu::Per_cpu() +{} + +IMPLEMENT +template< typename T > +Per_cpu::Per_cpu(bool) : _d(0) +{} + +IMPLEMENT inline +template< typename T > +T &Per_cpu_ptr::cpu(unsigned) { return *_p; } + + +IMPLEMENT +void +Per_cpu_data::init_ctors() +{ +} + +IMPLEMENT inline +void +Per_cpu_data::run_ctors(unsigned) +{ + extern ctor_function_t __PER_CPU_INIT_ARRAY_START__[]; + extern ctor_function_t __PER_CPU_INIT_ARRAY_END__[]; + run_ctor_functions(__PER_CPU_INIT_ARRAY_START__, __PER_CPU_INIT_ARRAY_END__); + + extern ctor_function_t __PER_CPU_CTORS_LIST__[]; + extern ctor_function_t __PER_CPU_CTORS_END__[]; + run_ctor_functions(__PER_CPU_CTORS_LIST__, __PER_CPU_CTORS_END__); +} + +IMPLEMENT inline +void +Per_cpu_data::run_late_ctors(unsigned) +{ + extern ctor_function_t __PER_CPU_LATE_INIT_ARRAY_START__[]; + extern ctor_function_t __PER_CPU_LATE_INIT_ARRAY_END__[]; + run_ctor_functions(__PER_CPU_LATE_INIT_ARRAY_START__, + __PER_CPU_LATE_INIT_ARRAY_END__); + + extern ctor_function_t __PER_CPU_LATE_CTORS_LIST__[]; + extern ctor_function_t __PER_CPU_LATE_CTORS_END__[]; + run_ctor_functions(__PER_CPU_LATE_CTORS_LIST__, __PER_CPU_LATE_CTORS_END__); +} + + +//--------------------------------------------------------------------------- +INTERFACE [mp]: + +#include +#include + +#include "config.h" + +EXTENSION +class Per_cpu_data +{ +private: + typedef Per_cpu_ctor_data Ctor; + + struct Ctor_vector + { + public: + void push_back(void (*func)(void*,unsigned), void *base); + unsigned len() const { return _len; } + Ctor const &operator [] (unsigned idx) const + { + extern Ctor _per_cpu_ctor_data_start[]; + return _per_cpu_ctor_data_start[idx]; + } + + private: + unsigned _len; + }; +protected: + static long _offsets[Config::Max_num_cpus] asm ("PER_CPU_OFFSETS"); + static unsigned late_ctor_start; + static Ctor_vector ctors; +}; + + +//--------------------------------------------------------------------------- +IMPLEMENTATION [mp]: + +#include "panic.h" +#include +#include + +long Per_cpu_data::_offsets[Config::Max_num_cpus]; +unsigned Per_cpu_data::late_ctor_start; +Per_cpu_data::Ctor_vector Per_cpu_data::ctors; + +IMPLEMENT +void +Per_cpu_data::Ctor_vector::push_back(void (*func)(void*,unsigned), void *base) +{ + extern Ctor _per_cpu_ctor_data_start[]; + extern Ctor _per_cpu_ctor_data_end[]; + + if (_per_cpu_ctor_data_start + _len >= _per_cpu_ctor_data_end) + panic("out of per_cpu_ctor_space"); + + Ctor &c = _per_cpu_ctor_data_start[_len++]; + c.func = func; + c.base = base; +} + + +IMPLEMENT inline +bool +Per_cpu_data::valid(unsigned cpu) +{ return cpu < Config::Max_num_cpus && _offsets[cpu] != -1; } + +IMPLEMENT inline template< typename T > +T const &Per_cpu::cpu(unsigned cpu) const +{ return *reinterpret_cast((char const *)&_d + _offsets[cpu]); } + +IMPLEMENT inline template< typename T > +T &Per_cpu::cpu(unsigned cpu) +{ return *reinterpret_cast((char *)&_d + _offsets[cpu]); } + +IMPLEMENT +template< typename T > +Per_cpu::Per_cpu() +{ + //printf(" Per_cpu() [this=%p])\n", this); + ctors.push_back(&ctor_wo_arg, this); +} + +IMPLEMENT +template< typename T > +Per_cpu::Per_cpu(bool) : _d(0) +{ + //printf(" Per_cpu(bool) [this=%p])\n", this); + ctors.push_back(&ctor_w_arg, this); +} + +PRIVATE static +template< typename T > +void Per_cpu::ctor_wo_arg(void *obj, unsigned cpu) +{ + //printf("Per_cpu::ctor_wo_arg(obj=%p, cpu=%u -> %p)\n", obj, cpu, &(reinterpret_cast*>(obj)->cpu(cpu))); + new (&reinterpret_cast*>(obj)->cpu(cpu)) T(); +} + +PRIVATE static +template< typename T > +void Per_cpu::ctor_w_arg(void *obj, unsigned cpu) +{ + //printf("Per_cpu::ctor_w_arg(obj=%p, cpu=%u -> %p)\n", obj, cpu, &reinterpret_cast*>(obj)->cpu(cpu)); + new (&reinterpret_cast*>(obj)->cpu(cpu)) T(cpu); +} + +IMPLEMENT inline +template< typename T > +T &Per_cpu_ptr::cpu(unsigned cpu) +{ return *reinterpret_cast(reinterpret_cast
(_p) + _offsets[cpu]); } + +IMPLEMENT +void +Per_cpu_data::init_ctors() +{ + for (unsigned i = 0; i < Config::Max_num_cpus; ++i) + _offsets[i] = -1; +} + +IMPLEMENT inline +void +Per_cpu_data::run_ctors(unsigned cpu) +{ + extern ctor_function_t __PER_CPU_INIT_ARRAY_START__[]; + extern ctor_function_t __PER_CPU_INIT_ARRAY_END__[]; + extern ctor_function_t __PER_CPU_CTORS_LIST__[]; + extern ctor_function_t __PER_CPU_CTORS_END__[]; + if (cpu == 0) + { + run_ctor_functions(__PER_CPU_INIT_ARRAY_START__, __PER_CPU_INIT_ARRAY_END__); + run_ctor_functions(__PER_CPU_CTORS_LIST__, __PER_CPU_CTORS_END__); + late_ctor_start = ctors.len(); + return; + } + + for (unsigned i = 0; i < late_ctor_start; ++i) + ctors[i].func(ctors[i].base, cpu); +} + +IMPLEMENT inline +void +Per_cpu_data::run_late_ctors(unsigned cpu) +{ + extern ctor_function_t __PER_CPU_LATE_INIT_ARRAY_START__[]; + extern ctor_function_t __PER_CPU_LATE_INIT_ARRAY_END__[]; + extern ctor_function_t __PER_CPU_LATE_CTORS_LIST__[]; + extern ctor_function_t __PER_CPU_LATE_CTORS_END__[]; + if (cpu == 0) + { + run_ctor_functions(__PER_CPU_LATE_INIT_ARRAY_START__, __PER_CPU_LATE_INIT_ARRAY_END__); + run_ctor_functions(__PER_CPU_LATE_CTORS_LIST__, __PER_CPU_LATE_CTORS_END__); + return; + } + + unsigned c = ctors.len(); + for (unsigned i = late_ctor_start; i < c; ++i) + ctors[i].func(ctors[i].base, cpu); +} diff --git a/kernel/fiasco/src/kern/per_cpu_data_alloc.cpp b/kernel/fiasco/src/kern/per_cpu_data_alloc.cpp new file mode 100644 index 00000000..8ce44663 --- /dev/null +++ b/kernel/fiasco/src/kern/per_cpu_data_alloc.cpp @@ -0,0 +1,62 @@ +INTERFACE: + +#include "per_cpu_data.h" + +class Per_cpu_data_alloc : public Per_cpu_data +{ +public: + static bool alloc(unsigned cpu); +}; + + +IMPLEMENTATION [!mp]: + +IMPLEMENT inline +bool Per_cpu_data_alloc::alloc(unsigned) +{ return true; } + + +//--------------------------------------------------------------------------- +IMPLEMENTATION [mp]: + +#include +#include + +#include "config.h" +#include "kmem_alloc.h" + +IMPLEMENT +bool Per_cpu_data_alloc::alloc(unsigned cpu) +{ + if (cpu >= Config::Max_num_cpus || valid(cpu)) + return false; + + extern char _per_cpu_data_start[]; + extern char _per_cpu_data_end[]; + + printf("Per_cpu_data_alloc: (orig: %p-%p)\n", _per_cpu_data_start, _per_cpu_data_end); + + if (cpu == 0) + { + // we use the master copy for CPU 0 + _offsets[0] = 0; + return true; + } + + unsigned size = _per_cpu_data_end - _per_cpu_data_start; + + char *per_cpu = (char*)Kmem_alloc::allocator()->unaligned_alloc(size); + + if (!per_cpu) + return false; + + memset(per_cpu, 0, size); + + _offsets[cpu] = per_cpu - _per_cpu_data_start; + printf("Allocate %u bytes (%uKB) for CPU[%u] local storage (offset=%lx)\n", + size, (size + 513) / 1024, cpu, _offsets[cpu]); + + return true; + +} + diff --git a/kernel/fiasco/src/kern/perf_cnt.cpp b/kernel/fiasco/src/kern/perf_cnt.cpp new file mode 100644 index 00000000..888e797a --- /dev/null +++ b/kernel/fiasco/src/kern/perf_cnt.cpp @@ -0,0 +1,95 @@ +INTERFACE: + +#include "types.h" + +class Perf_cnt_arch; + +class Perf_cnt +{ +public: + enum { + Max_slot = 2, + Max_pmc = 4, + }; + + enum Unit_mask_type + { None, Fixed, Exclusive, Bitmask, }; + + typedef Mword (*Perf_read_fn)(); +}; + + +// ----------------------------------------------------------------------- +INTERFACE [!perf_cnt]: + +EXTENSION class Perf_cnt +{ +public: + static Perf_read_fn read_pmc[Max_slot]; +}; + +// ----------------------------------------------------------------------- +IMPLEMENTATION [!perf_cnt]: + +Perf_cnt::Perf_read_fn Perf_cnt::read_pmc[Max_slot] = +{ dummy_read_pmc, dummy_read_pmc }; + +static Mword dummy_read_pmc() { return 0; } + +PUBLIC static void +Perf_cnt::get_unit_mask(Mword, Unit_mask_type *, Mword *, Mword *) {} +PUBLIC static void +Perf_cnt::get_unit_mask_entry(Mword, Mword, Mword *, const char **) {} +PUBLIC static void +Perf_cnt::get_perf_event(Mword, unsigned *, const char **, const char **) {} +PUBLIC static Mword +Perf_cnt::get_max_perf_event() { return 0; } +PUBLIC static void +Perf_cnt::split_event(Mword, unsigned *, Mword *) {} +PUBLIC static Mword +Perf_cnt::lookup_event(Mword) { return 0; } +PUBLIC static void +Perf_cnt::combine_event(Mword, Mword, Mword *) {} + +PUBLIC static char const * +Perf_cnt::perf_type() { return "nothing"; } + +PUBLIC static int +Perf_cnt::mode(Mword /*slot*/, const char **mode, const char **name, + Mword *event, Mword *user, Mword *kern, Mword *edge) +{ + *mode = *name = ""; + *user = *kern = *edge = *event = 0; + return 0; +} + +PUBLIC static +int +Perf_cnt::setup_pmc(Mword, Mword, Mword, Mword, Mword) +{ + return 0; +} + +PUBLIC static inline void +Perf_cnt::start_watchdog() +{} + +PUBLIC static inline void +Perf_cnt::stop_watchdog() +{} + +PUBLIC static inline void +Perf_cnt::touch_watchdog() +{} + +PUBLIC static inline int +Perf_cnt::have_watchdog() +{ return 0; } + +PUBLIC static inline void +Perf_cnt::setup_watchdog(Mword) +{} + +PUBLIC static inline void +Perf_cnt::init_ap() +{} diff --git a/kernel/fiasco/src/kern/pic-i8259.cpp b/kernel/fiasco/src/kern/pic-i8259.cpp new file mode 100644 index 00000000..b1680410 --- /dev/null +++ b/kernel/fiasco/src/kern/pic-i8259.cpp @@ -0,0 +1,355 @@ +INTERFACE[i8259]: + +#include "initcalls.h" + +EXTENSION class Pic +{ +public: + enum + { + MASTER_PIC_BASE = 0x20, + SLAVES_PIC_BASE = 0xa0, + OFF_ICW = 0x00, + OFF_OCW = 0x01, + + MASTER_ICW = MASTER_PIC_BASE + OFF_ICW, + MASTER_OCW = MASTER_PIC_BASE + OFF_OCW, + SLAVES_ICW = SLAVES_PIC_BASE + OFF_ICW, + SLAVES_OCW = SLAVES_PIC_BASE + OFF_OCW, + + + /* + ** ICW1 + */ + + ICW_TEMPLATE = 0x10, + + LEVL_TRIGGER = 0x08, + EDGE_TRIGGER = 0x00, + ADDR_INTRVL4 = 0x04, + ADDR_INTRVL8 = 0x00, + SINGLE__MODE = 0x02, + CASCADE_MODE = 0x00, + ICW4__NEEDED = 0x01, + NO_ICW4_NEED = 0x00, + + /* + ** ICW3 + */ + + SLAVE_ON_IR0 = 0x01, + SLAVE_ON_IR1 = 0x02, + SLAVE_ON_IR2 = 0x04, + SLAVE_ON_IR3 = 0x08, + SLAVE_ON_IR4 = 0x10, + SLAVE_ON_IR5 = 0x20, + SLAVE_ON_IR6 = 0x40, + SLAVE_ON_IR7 = 0x80, + + I_AM_SLAVE_0 = 0x00, + I_AM_SLAVE_1 = 0x01, + I_AM_SLAVE_2 = 0x02, + I_AM_SLAVE_3 = 0x03, + I_AM_SLAVE_4 = 0x04, + I_AM_SLAVE_5 = 0x05, + I_AM_SLAVE_6 = 0x06, + I_AM_SLAVE_7 = 0x07, + + /* + ** ICW4 + */ + + SNF_MODE_ENA = 0x10, + SNF_MODE_DIS = 0x00, + BUFFERD_MODE = 0x08, + NONBUFD_MODE = 0x00, + AUTO_EOI_MOD = 0x02, + NRML_EOI_MOD = 0x00, + I8086_EMM_MOD = 0x01, + SET_MCS_MODE = 0x00, + + /* + ** OCW1 + */ + + PICM_MASK = 0xFF, + PICS_MASK = 0xFF, + + /* + ** OCW2 + */ + + NON_SPEC_EOI = 0x20, + SPECIFIC_EOI = 0x60, + ROT_NON_SPEC = 0xa0, + SET_ROT_AEOI = 0x80, + RSET_ROTAEOI = 0x00, + ROT_SPEC_EOI = 0xe0, + SET_PRIORITY = 0xc0, + NO_OPERATION = 0x40, + + SND_EOI_IR0 = 0x00, + SND_EOI_IR1 = 0x01, + SND_EOI_IR2 = 0x02, + SND_EOI_IR3 = 0x03, + SND_EOI_IR4 = 0x04, + SND_EOI_IR5 = 0x05, + SND_EOI_IR6 = 0x06, + SND_EOI_IR7 = 0x07, + + /* + ** OCW3 + */ + + OCW_TEMPLATE = 0x08, + SPECIAL_MASK = 0x40, + MASK_MDE_SET = 0x20, + MASK_MDE_RST = 0x00, + POLL_COMMAND = 0x04, + NO_POLL_CMND = 0x00, + READ_NEXT_RD = 0x02, + READ_IR_ONRD = 0x00, + READ_IS_ONRD = 0x01, + + /* + ** Standard PIC initialization values for PCs. + */ + PICM_ICW1 = (ICW_TEMPLATE | EDGE_TRIGGER | ADDR_INTRVL8 + | CASCADE_MODE | ICW4__NEEDED), + PICM_ICW3 = SLAVE_ON_IR2, + PICM_ICW4 = (SNF_MODE_DIS | NONBUFD_MODE | NRML_EOI_MOD + | I8086_EMM_MOD), + + PICS_ICW1 = (ICW_TEMPLATE | EDGE_TRIGGER | ADDR_INTRVL8 + | CASCADE_MODE | ICW4__NEEDED), + PICS_ICW3 = I_AM_SLAVE_2, + PICS_ICW4 = (SNF_MODE_DIS | NONBUFD_MODE | NRML_EOI_MOD + | I8086_EMM_MOD), + }; + + static int special_fully_nested_mode; +}; + +IMPLEMENTATION[i8259]: + +#include +#include +#include + +#include "io.h" +#include "config.h" +#include "initcalls.h" +#include "koptions.h" +#include "mem_layout.h" + +int Pic::special_fully_nested_mode = 1; // be compatible with Jochen's L4 + +IMPLEMENT FIASCO_INIT +void +Pic::init() +{ + pic_init(0x20,0x28); +} + +PUBLIC static inline +unsigned +Pic::nr_irqs() +{ return 16; } + + +// +// this version of pic_init() overrides the OSKIT's. +// +// differences to standard AT initialization: +// . we use the "special fully nested mode" to let irq sources on the +// slave irq raise nested +// . we give irq 2 (= slave pic) the highest prio on the master pic; this +// results in the following sequence of prios: 8-15,3-7,0,1 +// this way, the timer interrupt on irq 8 always gets thru (even if +// some user irq handler doesn't acknowledge its irq!) +// +static FIASCO_INIT +void +Pic::pic_init(unsigned char master_base, unsigned char slave_base) +{ + // disallow all interrupts before we selectively enable them + Pic::disable_all_save(); + /* + * Set the LINTEN bit in the HyperTransport Transaction + * Control Register. + * + * This will cause EXTINT and NMI interrupts routed over the + * hypertransport bus to be fed into the LAPIC LINT0/LINT1. If + * the bit isn't set, the interrupts will go to the general cpu + * INTR/NMI pins. On a dual-core cpu the interrupt winds up + * going to BOTH cpus. The first cpu that does the interrupt ack + * cycle will get the correct interrupt. The second cpu that does + * it will get a spurious interrupt vector (typically IRQ 7). + */ +#if 0 + if ((cpu_id & 0xff0) == 0xf30) +#endif + { +#if 0 + Unsigned32 tcr; + Io::out32(0x0cf8, + (1 << 31) | /* enable */ + (0 << 16) | /* bus */ + (24 << 11) | /* dev (cpu + 24) */ + (0 << 8) | /* func */ + 0x68 /* reg */ + ); + tcr = Io::in32(0xcfc); + if ((tcr & 0x00010000) == 0) { + Io::out32(0xcfc, tcr|0x00010000); + printf("AMD: Rerouting HyperTransport " + "EXTINT/NMI to APIC\n"); + } + Io::out32(0x0cf8, 0); +#endif + } + // VMware isn't able to deal with the special fully nested mode + // correctly so we simply don't use it while running under + // VMware. Otherwise VMware will barf with + // *** VMware Workstation internal monitor error *** + // BUG F(152):393 bugNr=4388 + + if (Koptions::o()->opt(Koptions::F_nosfn)) + special_fully_nested_mode = 0; + + if (special_fully_nested_mode) + { + puts ("Enabling special fully nested mode for PIC"); + /* Initialize the master. */ + + Io::out8_p(PICM_ICW1, MASTER_ICW); + Io::out8_p(master_base, MASTER_OCW); + Io::out8_p(PICM_ICW3, MASTER_OCW); + Io::out8_p(SNF_MODE_ENA | PICM_ICW4, MASTER_OCW); + + /* Initialize the slave. */ + Io::out8_p(PICS_ICW1, SLAVES_ICW); + Io::out8_p(slave_base, SLAVES_OCW); + Io::out8_p(PICS_ICW3, SLAVES_OCW); + Io::out8_p(SNF_MODE_ENA | PICS_ICW4, SLAVES_OCW); + + // the timer interrupt should have the highest priority so that it + // always gets through + if (Config::Pic_prio_modify + && (int)Config::Scheduler_mode == Config::SCHED_RTC) + { + // setting specific rotation (specific priority) + // -- see Intel 8259A reference manual + // irq 1 on master hast lowest prio + // => irq 2 (cascade) = irqs 8..15 have highest prio + Io::out8_p(SET_PRIORITY | 1, MASTER_ICW); + // irq 7 on slave has lowest prio + // => irq 0 on slave (= irq 8) has highest prio + Io::out8_p(SET_PRIORITY | 7, SLAVES_ICW); + } + } + else + { + printf("%sUsing (normal) fully nested PIC mode\n", + Config::found_vmware ? "Found VMware: " : ""); + + /* Initialize the master. */ + Io::out8_p(PICM_ICW1, MASTER_ICW); + Io::out8_p(master_base, MASTER_OCW); + Io::out8_p(PICM_ICW3, MASTER_OCW); + Io::out8_p(PICM_ICW4, MASTER_OCW); + + /* Initialize the slave. */ + Io::out8_p(PICS_ICW1, SLAVES_ICW); + Io::out8_p(slave_base, SLAVES_OCW); + Io::out8_p(PICS_ICW3, SLAVES_OCW); + Io::out8_p(PICS_ICW4, SLAVES_OCW); + } + + // set initial masks + Io::out8_p(0xfb, MASTER_OCW); // unmask irq2 + Io::out8_p(0xff, SLAVES_OCW); // mask everything + + /* Ack any bogus intrs by setting the End Of Interrupt bit. */ + Io::out8_p(NON_SPEC_EOI, MASTER_ICW); + Io::out8_p(NON_SPEC_EOI, SLAVES_ICW); + + // disallow all interrupts before we selectively enable them + Pic::disable_all_save(); + +} + +IMPLEMENT inline NEEDS["io.h"] +void +Pic::disable_locked(unsigned irq) +{ + if (irq < 8) + Io::out8(Io::in8(MASTER_OCW) | (1 << irq), MASTER_OCW); + else + Io::out8(Io::in8(SLAVES_OCW) | (1 << (irq-8)), SLAVES_OCW); +} + +IMPLEMENT inline NEEDS["io.h"] +void +Pic::enable_locked(unsigned irq, unsigned /*prio*/) +{ + if (irq < 8) + Io::out8(Io::in8(MASTER_OCW) & ~(1 << irq), MASTER_OCW); + else + { + Io::out8(Io::in8(MASTER_OCW) & ~(1 << 2), MASTER_OCW); + Io::out8(Io::in8(SLAVES_OCW) & ~(1 << (irq-8)), SLAVES_OCW); + } +} + +IMPLEMENT inline NEEDS["io.h"] +void +Pic::acknowledge_locked(unsigned irq) +{ + if (irq >= 8) + { + Io::out8(NON_SPEC_EOI, SLAVES_ICW); // EOI slave + if (special_fully_nested_mode) + { + Io::out8(OCW_TEMPLATE | READ_NEXT_RD | READ_IS_ONRD, SLAVES_ICW); + if (Io::in8(SLAVES_ICW)) // slave still active? + return; // -- don't EOI master + } + } + Io::out8(NON_SPEC_EOI, MASTER_ICW); // EOI master +} + +IMPLEMENT inline +void +Pic::block_locked(unsigned) +{} + +IMPLEMENT inline NEEDS["io.h"] +Pic::Status +Pic::disable_all_save() +{ + Status s; + s = Io::in8(MASTER_OCW); + s |= Io::in8(SLAVES_OCW) << 8; + Io::out8( 0xff, MASTER_OCW ); + Io::out8( 0xff, SLAVES_OCW ); + + return s; +} + +IMPLEMENT inline NEEDS["io.h"] +void +Pic::restore_all( Status s ) +{ + Io::out8( s & 0x0ff, MASTER_OCW ); + Io::out8( (s >> 8) & 0x0ff, SLAVES_OCW ); +} + + +IMPLEMENT inline NEEDS[] +void +Pic::set_cpu(unsigned, unsigned cpu) +{ + (void)cpu; + assert(cpu == 0); +} diff --git a/kernel/fiasco/src/kern/pic.cpp b/kernel/fiasco/src/kern/pic.cpp new file mode 100644 index 00000000..f98e0512 --- /dev/null +++ b/kernel/fiasco/src/kern/pic.cpp @@ -0,0 +1,75 @@ +INTERFACE: + +/** + * Encapsulation of the platforms interrupt controller + */ +class Pic +{ +public: + /** + * The type holding the saved Pic state. + */ + typedef unsigned Status; + + /** + * Static initalization of the interrupt controller + */ + static void init(); + + /** + * Disable the given irq (without lock protection). + * @pre The Cpu_lock must be locked (cli'ed) + * + * This function must be implemented in the + * architecture specific part (e.g. pic-i8259.cpp). + */ + static void disable_locked( unsigned irqnum ); + + /** + * Enable the given irq (without lock protection). + * @pre The Cpu_lock must be locked (cli'ed) + * + * This function must be implemented in the + * architecture specific part (e.g. pic-i8259.cpp). + */ + static void enable_locked(unsigned irqnum, unsigned prio = 0); + + /** + * Temporarily block the IRQ til the next ACK. + * @pre The Cpu_lock must be locked (cli'ed) + * + * This function must be implemented in the + * architecture specific part (e.g. pic-i8259.cpp). + */ + static void block_locked(unsigned irqnum); + + /** + * Disable all IRQ's and and return the old Pic state. + * @pre Must be done with disabled interrupts. + */ + static Status disable_all_save(); + + /** + * Restore the IRQ's to the saved state s. + * @pre Must be done with disabled interrupts. + * @param s, the saved state. + */ + static void restore_all( Status s ); + + /** + * Acknowledge the given IRQ. + * @pre The Cpu_lock must be locked (cli'ed). + * @param irq, the irq to acknowledge. + * + * This function must be implemented in the + * architecture specific part (e.g. pic-i8259.cpp). + */ + static void acknowledge_locked( unsigned irq ); + + /** + * Set CPU affinity of IRQ. + * @param irq IRQ. + * @param cpu Logical CPU. + */ + static void set_cpu(unsigned irq, unsigned cpu); +}; diff --git a/kernel/fiasco/src/kern/pit-i8254.cpp b/kernel/fiasco/src/kern/pit-i8254.cpp new file mode 100644 index 00000000..f4151261 --- /dev/null +++ b/kernel/fiasco/src/kern/pit-i8254.cpp @@ -0,0 +1,102 @@ +INTERFACE: + +#include "initcalls.h" + +class Pit +{ + enum + { + Clock_tick_rate = 1193180, + }; +}; + + +//---------------------------------------------------------------------------- +IMPLEMENTATION[i8254]: + +#include "io.h" + +PUBLIC static inline NEEDS ["io.h"] +void +Pit::done() +{ + // set counter channel 0 to one-shot mode + Io::out8_p(0x30, 0x43); +} + +PUBLIC static FIASCO_INIT_CPU +void +Pit::setup_channel2_to_20hz() +{ + // set gate high, disable speaker + Io::out8((Io::in8(0x61) & ~0x02) | 0x01, 0x61); + + // set counter channel 2 to binary, mode0, lsb/msb + Io::out8(0xb0, 0x43); + + // set counter frequency + const unsigned latch = Clock_tick_rate / 20; // 50ms + Io::out8(latch & 0xff, 0x42); + Io::out8(latch >> 8, 0x42); +} + + +//---------------------------------------------------------------------------- +IMPLEMENTATION[i8254 & pit_timer]: + +// set up timer interrupt (~ 1ms) +PUBLIC static inline NEEDS ["io.h", Pit::set_freq_normal] +void +Pit::init() +{ + // set counter frequency to ~1000 Hz (1000.151 Hz) + set_freq_normal(); +} + +PUBLIC static inline NEEDS ["io.h", Pit::set_freq] +void +Pit::init(unsigned freq) +{ + set_freq(freq); +} + +PUBLIC static inline NEEDS ["io.h"] +void +Pit::set_freq_slow() +{ + // set counter channel 0 to binary, mode2, lsb/msb + Io::out8_p(0x34, 0x43); + + // set counter frequency to 32 Hz + const unsigned latch = Clock_tick_rate / 32; + Io::out8_p(latch & 0xff, 0x40); + Io::out8_p(latch >> 8, 0x40); +} + +PUBLIC static inline NEEDS ["io.h"] +void +Pit::set_freq_normal() +{ + // set counter channel 0 to binary, mode2, lsb/msb + Io::out8_p(0x34, 0x43); + + // set counter frequency to ~1000 Hz (1000.151 Hz) + const unsigned latch = Clock_tick_rate / 1000; + Io::out8_p(latch & 0xff, 0x40); + Io::out8_p(latch >> 8, 0x40); +} + +PUBLIC static inline NEEDS ["io.h"] +void +Pit::set_freq(unsigned freq) +{ + // set counter channel 0 to binary, mode2, lsb/msb + Io::out8_p(0x34, 0x43); + + // set counter frequency + const unsigned latch = Clock_tick_rate / freq; + Io::out8_p(latch & 0xff, 0x40); + Io::out8_p(latch >> 8, 0x40); +} + + diff --git a/kernel/fiasco/src/kern/ppc32/Makerules.KERNEL b/kernel/fiasco/src/kern/ppc32/Makerules.KERNEL new file mode 100644 index 00000000..c50ef6e6 --- /dev/null +++ b/kernel/fiasco/src/kern/ppc32/Makerules.KERNEL @@ -0,0 +1,34 @@ +# -*- makefile -*- + +exception.o: $(TCBOFFSET) +phys_mem.o: $(TCBOFFSET) + +# Add future prerequisites somewhere among the list of libraries. +# You really should not have to add anything in the $(LD) line. + +#TODO: strip +#boot_img.o: bootstrap.o $(LIBUART) $(CXXLIB) $(MINILIBC) $(LIBK) boot_libc_glue.o +# $(LINK_MESSAGE) +# $(VERBOSE)$(LD) -m elf32ppc -o $@_x.o -q \ +# -T $(srcdir)/kern/ppc32/bootstrap.ld $^ +# $(VERBOSE)$(OBJCOPY) -G _boot_start $@_x.o $@ +# $(VERBOSE)$(RM) $@_x.o + +$(KERNEL).image: $(srcdir)/kernel.ppc32.ld $(CRT0) $(OBJ_KERNEL) $(LIBK) $(LIBDISASM) libdrivers.a $(ABI) $(LIBUART) $(CXXLIB) $(MINILIBC) libgluedriverslibc.a + $(LINK_MESSAGE) + $(VERBOSE)$(LD) $(LDFLAGS) -N -T $< -o $@ $(filter-out $<,$+) $(LIBGCC) + +$(KERNEL): $(KERNEL).image + $(LINK_MESSAGE) + $(VERBOSE)$(STRIP) $< -o $@ + chmod 755 $@ + +# $(OBJCOPY) -O binary $@ fiasco + +Symbols: $(KERNEL).image + $(NM) $(KERNEL).image | c++filt | sort > $@.new + mv $@.new $@ + chmod 755 $@ + + +clean-KERNEL: diff --git a/kernel/fiasco/src/kern/ppc32/boot_info-ppc32.cpp b/kernel/fiasco/src/kern/ppc32/boot_info-ppc32.cpp new file mode 100644 index 00000000..d98dc0a8 --- /dev/null +++ b/kernel/fiasco/src/kern/ppc32/boot_info-ppc32.cpp @@ -0,0 +1,73 @@ +INTERFACE [ppc32]: + +#include "types.h" +#include "ppc_types.h" + +EXTENSION class Boot_info +{ + public: + /** + * Return memory-mapped base address of uart/pic + */ + static Address uart_base(); + static Address pic_base(); + + private: + static Address _prom_ptr; +}; + + +//------------------------------------------------------------------------------ +IMPLEMENTATION [ppc32]: + +#include "boot_info.h" +#include + +Address Boot_info::_prom_ptr; + +PUBLIC static +Of_device * +Boot_info::get_device(const char *name, const char *type) +{ +#if 0 + Of_device *dev = reinterpret_cast(_mbi.drives_addr); + + for (Unsigned32 i = 0; i < _mbi.drives_length/sizeof(Of_device); i ++) + if ((!type || !strncmp(type, (dev + i)->type, strlen(type))) && + (!name || !strncmp(name, (dev + i)->name, strlen(name)))) + return dev + i; +#endif + + return NULL; +} + +/** + * Return OF prom pointer + */ +PUBLIC static inline +Address Boot_info::get_prom() +{ + return (Address)_prom_ptr; +} + +PUBLIC static inline +void Boot_info::set_prom(Address prom_ptr) +{ + _prom_ptr = prom_ptr; +} + +/** + * Returns time base freuqency + */ +PUBLIC static inline +unsigned long Boot_info::get_time_base() +{ + return get_device(NULL, "cpu")->freq.time_freq; +} + +IMPLEMENT static +void Boot_info::init() +{ +} + + diff --git a/kernel/fiasco/src/kern/ppc32/boot_uart_init.cpp b/kernel/fiasco/src/kern/ppc32/boot_uart_init.cpp new file mode 100644 index 00000000..d228f0f3 --- /dev/null +++ b/kernel/fiasco/src/kern/ppc32/boot_uart_init.cpp @@ -0,0 +1,14 @@ +IMPLEMENTATION [ppc32 && serial]: + +#include "kernel_uart.h" +#include "static_init.h" + +STATIC_INITIALIZER_P(boot_console_init, EARLY_INIT_PRIO); + +static void boot_console_init() +{ + Console::stdout = Kernel_uart::uart(); + Console::stderr = Console::stdout; + Console::stdin = Console::stdout; +} + diff --git a/kernel/fiasco/src/kern/ppc32/bootstrap.cpp b/kernel/fiasco/src/kern/ppc32/bootstrap.cpp new file mode 100644 index 00000000..c4621e42 --- /dev/null +++ b/kernel/fiasco/src/kern/ppc32/bootstrap.cpp @@ -0,0 +1,34 @@ +INTERFACE [ppc32]: +#include "types.h" +#include "initcalls.h" + +IMPLEMENTATION [ppc32]: +#include "uart.h" +#include "boot_info.h" +#include "terminate.h" + +#include +#include +#include + +//XXX cbass: implement me +extern "C" void __attribute__ ((noreturn)) +_exit(int) +{ + printf("Exiting\n"); + while(1){}; +} + +extern "C" int main(void); + +extern "C" FIASCO_INIT +int bootstrap_main(void * /* r3 */, Address prom_ptr /* r4 */) +{ + Boot_info::set_prom(prom_ptr); + atexit(&static_destruction); + static_construction(); + printf("Bootstrapped\n"); + terminate(main()); + return 0; +} + diff --git a/kernel/fiasco/src/kern/ppc32/bsp/mpc52xx/Kconfig b/kernel/fiasco/src/kern/ppc32/bsp/mpc52xx/Kconfig new file mode 100644 index 00000000..48f9b590 --- /dev/null +++ b/kernel/fiasco/src/kern/ppc32/bsp/mpc52xx/Kconfig @@ -0,0 +1,3 @@ +# PF: MPC52XX +# PFDESCR: Freescale MPC52xx (POWER2/G2/603e) platform +# PFDEPENDS: PPC32 diff --git a/kernel/fiasco/src/kern/ppc32/bsp/mpc52xx/Modules b/kernel/fiasco/src/kern/ppc32/bsp/mpc52xx/Modules new file mode 100644 index 00000000..ef762428 --- /dev/null +++ b/kernel/fiasco/src/kern/ppc32/bsp/mpc52xx/Modules @@ -0,0 +1,9 @@ +# vim:set ft=make: + +PREPROCESS_PARTS += mpc52xx uart_mpc52xx +clock_IMPL += clock-generic +config_IMPL += config-ppc32-mpc52xx +uart_IMPL += uart-mpc52xx +boot_info_IMPL += boot_info-mpc52xx +pic_IMPL += pic-mpc52xx +timer_tick_IMPL += timer_tick-single-vector diff --git a/kernel/fiasco/src/kern/ppc32/bsp/mpc52xx/boot_info-mpc52xx.cpp b/kernel/fiasco/src/kern/ppc32/bsp/mpc52xx/boot_info-mpc52xx.cpp new file mode 100644 index 00000000..60dadc53 --- /dev/null +++ b/kernel/fiasco/src/kern/ppc32/bsp/mpc52xx/boot_info-mpc52xx.cpp @@ -0,0 +1,25 @@ +IMPLEMENTATION[ppc32 && mpc52xx]: + +#include + +IMPLEMENT static +Address Boot_info::uart_base() +{ + Of_device *dev = get_device((char*)"serial", (char*)"serial"); + return dev ? dev->reg : 0; +} + +IMPLEMENT static +Address Boot_info::pic_base() +{ + Of_device *dev = get_device((char*)"pic", NULL); + return dev ? dev->reg : 0; +} + +PUBLIC static +Address Boot_info::mbar() +{ + Of_device *dev = get_device("builtin", NULL); + + return dev ? dev->reg : 0; +} diff --git a/kernel/fiasco/src/kern/ppc32/bsp/mpc52xx/config-ppc32-mpc52xx.cpp b/kernel/fiasco/src/kern/ppc32/bsp/mpc52xx/config-ppc32-mpc52xx.cpp new file mode 100644 index 00000000..cca82fa3 --- /dev/null +++ b/kernel/fiasco/src/kern/ppc32/bsp/mpc52xx/config-ppc32-mpc52xx.cpp @@ -0,0 +1,11 @@ +INTERFACE [ppc32 && mpc52xx]: + +#define TARGET_NAME "MPC52xx" + +EXTENSION class Config +{ +public: + enum + { + }; +}; diff --git a/kernel/fiasco/src/kern/ppc32/bsp/mpc52xx/pic-mpc52xx.cpp b/kernel/fiasco/src/kern/ppc32/bsp/mpc52xx/pic-mpc52xx.cpp new file mode 100644 index 00000000..a0df1132 --- /dev/null +++ b/kernel/fiasco/src/kern/ppc32/bsp/mpc52xx/pic-mpc52xx.cpp @@ -0,0 +1,385 @@ +INTERFACE [ppc32 && mpc52xx]: + +#include "types.h" + +class Irq_chip_icu; + +EXTENSION class Pic +{ +private: + /** Pic interrupt control registers (incomplete) */ + ///+0x00: Peripheral Interrupt Mask Register + static Address per_mask() { return _pic_base; } + ///+0x04: Peripheral Priority & HI/LO Select Register1 + static Address per_prio1() { return _pic_base + 0x04; } + ///+0x08: Peripheral Priority & HI/LO Select Register2 + static Address per_prio2() { return _pic_base + 0x08; } + ///+0x0c: Peripheral Priority & HI/LO Select Register3 + static Address per_prio3() { return _pic_base + 0x0c; } + ///+0x10: External Enable & External Types Register + static Address ext() { return _pic_base + 0x10; } + ///+0x14: Critical Priority & Main Inter. Mask Register + static Address main_mask() { return _pic_base + 0x14; } + ///+0x18: Main Inter. Priority1 + static Address main_prio1() { return _pic_base + 0x18; } + ///+0x1c: Main Inter. Priority2 + static Address main_prio2() { return _pic_base + 0x1c; } + ///+0x24: PerStat, MainStat, CritStat Encoded Registers + static Address stat() { return _pic_base + 0x24; } + + + /** Interrupt lines (sdma is missing) */ + enum Pic_lines + { + IRQ_CRIT = 0x0, ///Critical line + IRQ_MAIN = 0x1, ///Main line + IRQ_PER = 0x2, ///Periphal line + IRQ_SHIFT = 0x4 + }; + + enum Pic_num_per_line + { + NUM_CRIT = 4, + NUM_MAIN = 17, + NUM_PER = 24, + }; + + /** Interrupt senses */ + enum Pic_sense + { + SENSE_LEVEL_HIGH = 0, + SENSE_EDGE_RISING = 1, + SENSE_EDGE_FALLING = 2, + SENSE_LEVEL_LOW = 3 + }; + + static Address _pic_base; + +public: + enum { IRQ_MAX = (IRQ_PER << IRQ_SHIFT) + NUM_PER}; + enum { No_irq_pending = ~0U }; + + static Irq_chip_icu *main; +}; + +//------------------------------------------------------------------------------ +IMPLEMENTATION [ppc32 && mpc52xx]: + +#include "boot_info.h" +#include "io.h" +#include "irq.h" +#include "irq_chip_generic.h" +#include "irq_mgr.h" +#include "mmu.h" +#include "panic.h" +#include "ppc_types.h" + +#include +#include + +Irq_chip_icu *Pic::main; + +class Chip : public Irq_chip_gen +{ +public: + Chip() : Irq_chip_gen(Pic::IRQ_MAX) {} + unsigned set_mode(Mword, unsigned) { return Irq_base::Trigger_level; } + void set_cpu(Mword, unsigned) {} +}; + +PUBLIC +void +Chip::mask(Mword) +{ + assert(cpu_lock.test()); + //Pic::disable_locked(irq); +} + +PUBLIC +void +Chip::ack(Mword) +{ + assert(cpu_lock.test()); + //Pic::acknowledge_locked(irq); +} + +PUBLIC +void +Chip::mask_and_ack(Mword) +{ + assert(cpu_lock.test()); + //Pic::disable_locked(irq()); + //Pic::acknowledge_locked(irq()); +} + +PUBLIC +void +Chip::unmask(Mword) +{ + assert(cpu_lock.test()); + //Pic::enable_locked(irq()); +} + +class Mgr : public Irq_mgr +{ +public: + unsigned nr_irqs() const { return Pic::IRQ_MAX; } + unsigned nr_msis() const { return 0; } + Irq chip(Mword irqnum) const + { return Irq(_chip, irqnum); } + + Chip *_chip; +}; + +static Static_object mgr; +static Static_object chip; + + +Address Pic::_pic_base = 0; + +IMPLEMENT FIASCO_INIT +void +Pic::init() +{ + _pic_base = Boot_info::pic_base(); + assert(_pic_base != 0); + + Mmu_guard dcache; + Io::write_dirty(0xffffe000, per_mask()); //disable 0-19 + Io::write_dirty(0x00010fff, main_mask()); //disable 15, 20-31 + + Unsigned32 ext_val = Io::read_dirty(ext()); + ext_val &= 0x00ff0000; //keep sense configuration + ext_val |= 0x0f000000; //clear IRQ 0-3 + ext_val |= 0x00001000; //enable Master External Enable + ext_val |= 0x00000f00; //enable all interrupt lines (IRQ 0-3) + ext_val |= 0x00000001; //CEb route critical interrupt normally + Io::write_dirty(ext_val, ext()); + + //zero priority registers + Io::write_dirty(0, per_prio1()); + Io::write_dirty(0, per_prio2()); + Io::write_dirty(0, per_prio3()); + Io::write_dirty(0, main_prio1()); + Io::write_dirty(0, main_prio2()); + + Irq_mgr::mgr = mgr.construct(); + mgr->_chip = chip.construct(); +} + +//------------------------------------------------------------------------------ +/** + * Irq number translations + */ +PUBLIC static inline +unsigned +Pic::irq_num(unsigned line, unsigned pic_num) +{ return (line << IRQ_SHIFT) | pic_num; } + + +PUBLIC static +int +Pic::get_irq_num(const char *name, const char *type) +{ + Of_device *dev = Boot_info::get_device(name, type); + + if(!dev) + return -1; + + return (int)irq_num(dev->interrupt[0], dev->interrupt[1]); +} + +PRIVATE static inline NEEDS[] +unsigned +Pic::pic_line(unsigned irq_num) +{ + unsigned line = irq_num >> IRQ_SHIFT; + assert(line < 3); + return line; +} + +PRIVATE static inline NEEDS[Pic::pic_line] +unsigned +Pic::pic_num(unsigned irq_num) +{ + unsigned line = pic_line(irq_num); + unsigned num = irq_num & ~(~0U << IRQ_SHIFT); + + switch(line) + { + case IRQ_CRIT: + assert(num < NUM_CRIT); + break; + case IRQ_MAIN: + assert(num < NUM_MAIN); + break; + default: + assert(num < NUM_PER); + } + + return num; +} + + +//------------------------------------------------------------------------------- +/** + * Interface implementation + */ +IMPLEMENT inline +void +Pic::block_locked (unsigned irq_num) +{ + disable_locked(irq_num); +} + +IMPLEMENT inline NEEDS["io.h", Pic::pic_line, Pic::pic_num, Pic::set_stat_msb] +void +Pic::acknowledge_locked(unsigned irq_num) +{ + unsigned line = pic_line(irq_num); + unsigned num = pic_num(irq_num); + + if((line == IRQ_MAIN && (num >= 1 || num <= 3)) || + (line == IRQ_CRIT && num == 0)) + Io::set(1U << (27 - num), ext()); + + set_stat_msb(irq_num); +} + +PRIVATE static inline +void +Pic::dispatch_mask(unsigned irq_num, Address *addr, unsigned *bit_offs) +{ + switch(pic_line(irq_num)) + { + case IRQ_MAIN: + *addr = main_mask(); + *bit_offs = 16; + break; + case IRQ_PER: + *addr = per_mask(); + *bit_offs = 31; + break; + default: + panic("%s: Cannot handle IRQ %u", __PRETTY_FUNCTION__, irq_num); + } +} + +PRIVATE static inline +void +Pic::set_stat_msb(unsigned irq_num) +{ + switch(pic_line(irq_num)) + { + case IRQ_MAIN: + Io::set(0x00200000, stat()); + break; + case IRQ_PER: + Io::set(0x20000000, stat()); + break; + default: + panic("CRIT not implemented"); + } +} + +IMPLEMENT inline NEEDS[Pic::pic_num, Pic::dispatch_mask] +void +Pic::disable_locked (unsigned irq_num) +{ + Address addr; + unsigned bit_offs; + dispatch_mask(irq_num, &addr, &bit_offs); + Io::set(1U << (bit_offs - pic_num(irq_num)), addr); +} + +IMPLEMENT inline NEEDS[Pic::dispatch_mask] +void +Pic::enable_locked (unsigned irq_num, unsigned /*prio*/) +{ + Address addr; + unsigned bit_offs; + dispatch_mask(irq_num, &addr, &bit_offs); + + Io::clear(1U << (bit_offs - pic_num(irq_num)), addr); +} + +PUBLIC static inline NEEDS["panic.h"] +unsigned +Pic::nr_irqs() +{ return IRQ_MAX; } + +PRIVATE static inline +Unsigned32 +Pic::pending_per(Unsigned32 state) +{ + Unsigned32 irq = state >> 24 & 0x1f; //5 bit + + if(irq == 0) + panic("No support for bestcomm interrupt, yet\n"); + + return irq_num(IRQ_PER, irq); +} + +PRIVATE static inline +Unsigned32 +Pic::pending_main(Unsigned32 state) +{ + Unsigned32 irq = state >> 16 & 0x1f; + + //low periphal + if(irq == 4) + return pending_per(state); + + return irq_num(IRQ_MAIN, irq); +} + +PUBLIC static inline NEEDS[Pic::pending_main, Pic::pending_per] +Unsigned32 +Pic::pending() +{ + Unsigned32 irq = No_irq_pending; + Unsigned32 state = Io::read(stat()); + + //critical interupt + if(state & 0x00000400) + panic("No support for critical interrupt, yet"); + //main interrupt + else if(state & 0x00200000) + irq = pending_main(state); + //periphal interrupt + else if(state & 0x20000000) + irq = pending_per(state); + + return irq; +} + +/** + * disable interrupt lines [0-3] + */ +IMPLEMENT inline +Pic::Status +Pic::disable_all_save() +{ + Status s; + Mmu_guard dcache; + + s = Io::read_dirty(ext()); + Io::write_dirty(s & ~0x1f00, ext()); + + return s; +} + +IMPLEMENT inline +void +Pic::restore_all(Status s) +{ + Io::write(s, ext()); +} + +// ------------------------------------------------------------------------ +IMPLEMENTATION [debug && ppc32]: + +PUBLIC +char const * +Chip::chip_type() const +{ return "HW Mpc52xx IRQ"; } diff --git a/kernel/fiasco/src/kern/ppc32/bsp/qemu/Kconfig b/kernel/fiasco/src/kern/ppc32/bsp/qemu/Kconfig new file mode 100644 index 00000000..986cbd90 --- /dev/null +++ b/kernel/fiasco/src/kern/ppc32/bsp/qemu/Kconfig @@ -0,0 +1,3 @@ +# PF: QEMU +# PFDESCR: Qemu platform (testing) +# PFDEPENDS: PPC32 diff --git a/kernel/fiasco/src/kern/ppc32/bsp/qemu/Modules b/kernel/fiasco/src/kern/ppc32/bsp/qemu/Modules new file mode 100644 index 00000000..eed3e6fd --- /dev/null +++ b/kernel/fiasco/src/kern/ppc32/bsp/qemu/Modules @@ -0,0 +1,8 @@ +# vim:set ft=make: + +PREPROCESS_PARTS += qemu uart_of +config_IMPL += config-ppc32-qemu +uart_IMPL += uart-of +pic_IMPL += pic-ppc32-qemu +boot_info_IMPL += boot_info-ppc32-qemu +clock_IMPL += clock-generic diff --git a/kernel/fiasco/src/kern/ppc32/bsp/qemu/boot_info-ppc32-qemu.cpp b/kernel/fiasco/src/kern/ppc32/bsp/qemu/boot_info-ppc32-qemu.cpp new file mode 100644 index 00000000..06e0041e --- /dev/null +++ b/kernel/fiasco/src/kern/ppc32/bsp/qemu/boot_info-ppc32-qemu.cpp @@ -0,0 +1,9 @@ +IMPLEMENTATION[ppc32 && qemu]: + +#include + +IMPLEMENT static +Address Boot_info::uart_base() +{ + return 0; +} diff --git a/kernel/fiasco/src/kern/ppc32/bsp/qemu/config-ppc32-qemu.cpp b/kernel/fiasco/src/kern/ppc32/bsp/qemu/config-ppc32-qemu.cpp new file mode 100644 index 00000000..8c516c92 --- /dev/null +++ b/kernel/fiasco/src/kern/ppc32/bsp/qemu/config-ppc32-qemu.cpp @@ -0,0 +1,11 @@ +INTERFACE [ppc32 && qemu]: + +#define TARGET_NAME "QEMU" + +EXTENSION class Config +{ +public: + enum + { + }; +}; diff --git a/kernel/fiasco/src/kern/ppc32/bsp/qemu/pic-ppc32-qemu.cpp b/kernel/fiasco/src/kern/ppc32/bsp/qemu/pic-ppc32-qemu.cpp new file mode 100644 index 00000000..03781b79 --- /dev/null +++ b/kernel/fiasco/src/kern/ppc32/bsp/qemu/pic-ppc32-qemu.cpp @@ -0,0 +1,49 @@ +INTERFACE [ppc32 && qemu]: + +#include "types.h" + +class Irq_base; + +EXTENSION class Pic +{ +public: + enum { No_irq_pending = ~0U }; +}; + +//------------------------------------------------------------------------------ +IMPLEMENTATION [ppc32 && qemu]: + +#include "initcalls.h" + +IMPLEMENT FIASCO_INIT +void +Pic::init() +{ +} + +PUBLIC static inline +Unsigned32 +Pic::pending() +{ + return 0; +} + +IMPLEMENT inline +void +Pic::block_locked (unsigned) +{} + +IMPLEMENT inline +void +Pic::acknowledge_locked(unsigned) +{} + +IMPLEMENT inline +void +Pic::enable_locked (unsigned, unsigned) +{} + +IMPLEMENT inline +void +Pic::disable_locked (unsigned) +{} diff --git a/kernel/fiasco/src/kern/ppc32/config-ppc32.cpp b/kernel/fiasco/src/kern/ppc32/config-ppc32.cpp new file mode 100644 index 00000000..5b8fabd6 --- /dev/null +++ b/kernel/fiasco/src/kern/ppc32/config-ppc32.cpp @@ -0,0 +1,53 @@ +INTERFACE [ppc32]: + +#include + +EXTENSION class Config +{ +public: + enum + { + // cannot access user memory directly + Access_user_mem = No_access_user_mem, + + PAGE_SHIFT = ARCH_PAGE_SHIFT, + PAGE_SIZE = 1 << PAGE_SHIFT, + PAGE_MASK = ~(PAGE_SIZE - 1), + + SUPERPAGE_SHIFT = 22, + SUPERPAGE_SIZE = 1 << SUPERPAGE_SHIFT, + SUPERPAGE_MASK = ~(SUPERPAGE_SIZE -1), + hlt_works_ok = 1, + Irq_shortcut = 0, //TODO: set + }; + + enum + { + Kmem_size = 8*1024*1024, //8 MB + Htab_entries = 8, //number of entries in page-table-entry group + //, min=1, max=8 + }; + + enum + { + Scheduler_one_shot = 0, + Scheduler_granularity = 1000UL, + Default_time_slice = 10 * Scheduler_granularity, + }; + + static unsigned const default_console_uart = 3; + static unsigned const default_console_uart_baudrate = 115200; + static const char char_micro; +}; + + +//--------------------------------------------------------------------------- +IMPLEMENTATION [ppc32]: + +char const Config::char_micro = '\265'; +const char *const Config::kernel_warn_config_string = 0; + +IMPLEMENT FIASCO_INIT +void +Config::init_arch() +{} diff --git a/kernel/fiasco/src/kern/ppc32/context-ppc32.cpp b/kernel/fiasco/src/kern/ppc32/context-ppc32.cpp new file mode 100644 index 00000000..cf545966 --- /dev/null +++ b/kernel/fiasco/src/kern/ppc32/context-ppc32.cpp @@ -0,0 +1,94 @@ +IMPLEMENTATION [ppc32]: + +/** Note: TCB pointer is located in sprg1 */ + +/* +#include +#include + +#include "l4_types.h" +#include "cpu_lock.h" +#include "lock_guard.h" +#include "space.h" +#include "thread_state.h" +*/ + +#include "kmem.h" +#include "utcb_support.h" + +IMPLEMENT inline +void +Context::spill_user_state() +{} + +IMPLEMENT inline +void +Context::fill_user_state() +{} + +PROTECTED inline void Context::arch_setup_utcb_ptr() {} + +IMPLEMENT inline +void +Context::switch_cpu(Context *t) +{ + unsigned long dummy1, dummy2, dummy3; + +// printf("Switch %p -> %p (sp %p -> %p)\n", this, t, _kernel_sp, t->_kernel_sp); +// WARNING: switchin_context_label needs a Context* parameter (old Context *) + asm volatile (" lis %%r5, 1f@ha \n" + " addi %%r5, %%r5, 1f@l \n" + + //save return addr + " stw %%r5, 0(%%r1) \n" + " stw %%r1, 0(%[kernel_sp]) \n" + + //switch stack + " mr %%r1, %[new_sp] \n" + " mr %%r3, %[new_thread] \n" + + //address space switch + " bl switchin_context_label \n" + " lwz %%r5, 0(%%r1) \n" + " mtctr %%r5 \n" + " bctr \n" + "1: \n" + : [new_thread]"=r" (dummy1), + [kernel_sp] "=r" (dummy2), + [new_sp] "=r" (dummy3) + : "0" (t), + "1" (&_kernel_sp), + "2" (t->_kernel_sp) + : "r0", "r2", "r3", "r4", "r5", "r6", "r7", + "r8", "r9", "r13", "r14", "r15", "r16", "r17", + "r18", "r19", "r20", "r21", "r22", "r23", "r24", + "r25", "r26", "r27", "r28", "r29", "r30", "r31", + "ctr", "lr", "cr2", "cr3", "cr4", "xer", "memory" + ); +} + +/** Thread context switchin. Called on every re-activation of a + thread (switch_exec()). This method is public only because it is + called by an ``extern "C"'' function that is called + from assembly code (call_switchin_context). + */ + +IMPLEMENT +void Context::switchin_context(Context *from) +{ + assert(this == current()); + assert(state() & Thread_ready); + // Set kernel-esp in case we want to return to the user. + // kmem::kernel_esp() returns a pointer to the kernel SP (in the + // TSS) the CPU uses when next switching from user to kernel mode. + // regs() + 1 returns a pointer to the end of our kernel stack. + Kmem::kernel_sp( reinterpret_cast(regs() + 1) ); +#if 0 + printf("switch in address space: %p\n",_space); +#endif + + // switch to our page directory if nessecary + vcpu_aware_space()->switchin_context(from->vcpu_aware_space()); + + Utcb_support::current(utcb().usr()); +} diff --git a/kernel/fiasco/src/kern/ppc32/continuation-ppc32.cpp b/kernel/fiasco/src/kern/ppc32/continuation-ppc32.cpp new file mode 100644 index 00000000..abfe720b --- /dev/null +++ b/kernel/fiasco/src/kern/ppc32/continuation-ppc32.cpp @@ -0,0 +1,82 @@ +INTERFACE[ppc32]: + +#include "entry_frame.h" +#include "member_offs.h" +#include "types.h" + +class Continuation +{ + MEMBER_OFFSET(); + +private: + Address _ip; + Mword _psr; + +public: + Continuation() : _ip(~0UL) {} + + struct User_return_frame + { + Mword usp; + Mword ulr; + Mword km_lr; + Mword psr; + Mword pc; + }; + + bool valid() const + { return _ip != ~0UL; } + + Address ip() const { return _ip; } + void ip(Address ip) { _ip = ip; } + + Mword flags(Return_frame const *) const { return _psr; } + void flags(Return_frame *, Mword psr) { _psr = psr; } + + Mword sp(Return_frame const *o) const { return o->usp; } + void sp(Return_frame *o, Mword sp) { o->usp = sp; } + + void save(Return_frame const *regs) + { + _ip = regs->ip(); + //_psr = regs->psr; + } + + void activate(Return_frame *regs, void *cont_func) + { + save(regs); + (void)cont_func; + //regs->pc = Mword(cont_func); + //regs->psr &= ...; + } + + void set(Return_frame *dst, User_return_frame const *src) + { + dst->usp = src->usp; + dst->ulr = src->ulr; + //dst->km_lr = src->km_lr; + _ip = src->pc; + _psr = src->psr; + } + + void get(User_return_frame *dst, Return_frame const *src) const + { + dst->usp = src->usp; + dst->ulr = src->ulr; + //dst->km_lr = src->km_lr; + dst->pc = _ip; + dst->psr = _psr; + } + + void clear() { _ip = ~0UL; } + + void restore(Return_frame *regs) + { + //regs->pc = _ip; + // regs->psr = _psr; + (void)regs; + clear(); + } + +}; + diff --git a/kernel/fiasco/src/kern/ppc32/cpu-ppc32.cpp b/kernel/fiasco/src/kern/ppc32/cpu-ppc32.cpp new file mode 100644 index 00000000..3d9aede5 --- /dev/null +++ b/kernel/fiasco/src/kern/ppc32/cpu-ppc32.cpp @@ -0,0 +1,213 @@ +INTERFACE [ppc32]: + +#include "per_cpu_data.h" +#include "types.h" + +EXTENSION class Cpu +{ +public: + void init(bool is_boot_cpu = false); + static void early_init(); + + static Per_cpu cpus; + static Cpu *boot_cpu() { return _boot_cpu; } + + Cpu(unsigned cpu) { set_id(cpu); } + +private: + static Cpu *_boot_cpu; + unsigned _phys_id; + static unsigned long _ns_per_cycle; + +}; + +namespace Segment +{ + enum Attribs_enum + { + Ks = 1UL << 30, + Kp = 1UL << 29, + N = 1UL << 28, + Default_attribs = Kp //Ks | Kp, + }; +}; +//------------------------------------------------------------------------------ +IMPLEMENTATION [ppc32]: + +#include "panic.h" +#include "boot_info.h" +#include "msr.h" + +#include + +DEFINE_PER_CPU Per_cpu Cpu::cpus(true); +Cpu *Cpu::_boot_cpu; +unsigned long Cpu::_ns_per_cycle; + +IMPLEMENT +void +Cpu::init(bool is_boot_cpu) +{ + if (is_boot_cpu) + { + _boot_cpu = this; + set_online(1); + } + _phys_id = 0; //Proc::cpu_id(); + _ns_per_cycle = 1000000000 / Boot_info::get_time_base(); + printf("Timebase: %lu\n", Boot_info::get_time_base()); +} + +IMPLEMENT +void +Cpu::early_init() +{ + asm volatile( "mtmsr %[msr] \n" //set kernel msr (disables paging) + "mtdbatu 0, %[zero] \n" //clear bat registers (good bye OF) + "mtdbatu 1, %[zero] \n" + "mtdbatu 2, %[zero] \n" + "mtdbatu 3, %[zero] \n" + "mtibatu 0, %[zero] \n" + "mtibatu 1, %[zero] \n" + "mtibatu 2, %[zero] \n" + "mtibatu 3, %[zero] \n" + : : [msr]"r" (Msr::Msr_kernel), [zero]"r" (0) + ); +} + +PUBLIC static inline +Mword +Cpu::read_vsid(unsigned sr = 0) +{ + Mword vsid; + asm volatile ("mfsrin %[vsid], %[sr] \n" + : [vsid] "=r"(vsid) + : [sr]"r" (sr << 28) + ); + + return (vsid & 0xffffff); +} + +/* set segment register 0-15 */ +PUBLIC static inline //NEEDS["paging.h"] +void +Cpu::set_vsid(Mword vsid) +{ + vsid |= Segment::Default_attribs; + Mword ret; + + asm volatile ( " isync \n" + " lis %%r5, 0 \n" + " li %%r5, 15 \n" + " mtctr %%r5 \n" + " li %%r5, 0 \n" + " mr %%r6, %%r5 \n" + " 1: \n" + " mtsrin %[vsid], %%r5 \n" //set srX + " addi %[vsid], %[vsid], 1 \n" //inc vsid + " addi %%r6, %%r6, 1 \n" + " rlwinm %%r5, %%r6, 28, 0, 3 \n" //extract sr index + " bdnz 1b \n" +// " isync \n" //rfi should be + //sufficient + : "=r" (ret) + : [vsid]"r" (vsid) + : "r5", "r6", "memory" + ); + +} + +PUBLIC static inline +Mword +Cpu::stack_align(Mword stack) +{ return stack & ~0xf; } + +PUBLIC static inline +bool +Cpu::have_superpages() +{ return true; } + +//------------------------------------------------------------------------------ +/* Time functions */ + +/** + * Read time base registers + */ +PUBLIC static inline +Unsigned64 +Cpu::rdtsc() +{ + Unsigned32 tb_upper, tb_lower; + Unsigned64 tb; + asm volatile ( "1: \n" + " mftbu %[upper] \n" + " mftb %[lower] \n" + " mftbu %%r12 \n" + " cmpw %[upper], %%r12 \n" + " bne 1b \n" + : [upper]"=r" (tb_upper), + [lower]"=r" (tb_lower) + : + : "r12" + ); + tb = tb_upper; + return (tb << 32) | tb_lower; +} + +PUBLIC static inline +void +Cpu::busy_wait_ns(Unsigned64 ns) +{ + Unsigned64 stop = rdtsc() + ns_to_tsc(ns); + + while(rdtsc() < stop) + ; +} + +PUBLIC static inline +Unsigned64 +Cpu::ns_to_tsc(Unsigned64 ns) +{ + return ns / _ns_per_cycle; +} + +PUBLIC static inline +Unsigned64 +Cpu::tsc_to_ns(Unsigned64 tsc) +{ + return tsc * _ns_per_cycle; +} + +PUBLIC static inline +Unsigned32 +Cpu::get_scaler_tsc_to_ns() +{ return 0; } + +PUBLIC static inline +Unsigned32 +Cpu::get_scaler_tsc_to_us() +{ return 0; } + +PUBLIC static inline +Unsigned32 +Cpu::get_scaler_ns_to_tsc() +{ return 0; } + +PUBLIC static inline +bool +Cpu::tsc() +{ return 0; } + +//------------------------------------------------------------------------------ +/* Unimplemented */ + +PUBLIC static inline +void +Cpu::debugctl_enable() +{} + +PUBLIC static inline +void +Cpu::debugctl_disable() +{} + diff --git a/kernel/fiasco/src/kern/ppc32/crt0.S b/kernel/fiasco/src/kern/ppc32/crt0.S new file mode 100644 index 00000000..f1634228 --- /dev/null +++ b/kernel/fiasco/src/kern/ppc32/crt0.S @@ -0,0 +1,18 @@ +/* -*- c -*- */ +.section .text.init, "ax" +.global _start +_start: + lis %r1, __init_stack@ha + addi %r1, %r1, __init_stack@l + addi %r1, %r1, 16 //first stack frame + b bootstrap_main +1: + b 1b +.previous +.section .bss +.align 12 +.space 4096 + __init_stack: +.previous + + diff --git a/kernel/fiasco/src/kern/ppc32/decrementer.cpp b/kernel/fiasco/src/kern/ppc32/decrementer.cpp new file mode 100644 index 00000000..15eecae5 --- /dev/null +++ b/kernel/fiasco/src/kern/ppc32/decrementer.cpp @@ -0,0 +1,69 @@ +INTERFACE: + +#include "types.h" + +class Decrementer +{ +public: + void init(unsigned long interval); + inline void set(); + inline void enable(); + inline void disable(); + Decrementer() : _interval(0), _enabled(false) {} + +private: + Unsigned32 _interval; + bool _enabled; +}; + + +//------------------------------------------------------------------------------ +IMPLEMENTATION[ppc32]: + +PUBLIC static inline +Decrementer * +Decrementer::d() +{ + static Decrementer _kernel_decr; + return &_kernel_decr; +} + +PRIVATE inline +void +Decrementer::set2(unsigned long interval) +{ + if (!_enabled && interval) + return; + + asm volatile("mtdec %0" : : "r"(interval) : "memory"); +} + +IMPLEMENT +void +Decrementer::init(unsigned long interval) +{ + _interval = interval; +} + +IMPLEMENT inline NEEDS[Decrementer::set2] +void +Decrementer::set() +{ + set2(_interval); +} + +IMPLEMENT inline +void +Decrementer::enable() +{ + _enabled = true; + set(); +} + +IMPLEMENT inline +void +Decrementer::disable() +{ + _enabled = false; + set2(0); +} diff --git a/kernel/fiasco/src/kern/ppc32/dirq-ppc32.cpp b/kernel/fiasco/src/kern/ppc32/dirq-ppc32.cpp new file mode 100644 index 00000000..4616f24e --- /dev/null +++ b/kernel/fiasco/src/kern/ppc32/dirq-ppc32.cpp @@ -0,0 +1,31 @@ +IMPLEMENTATION [ppc32]: +// --------------------------------------------------------------------------- +#include "std_macros.h" +#include "timer.h" +#include "processor.h" +#include "pic.h" + + +IMPLEMENTATION: + +#include "irq_chip_generic.h" +#include "irq.h" + +extern "C" +void irq_handler() +{ + Return_frame *rf = nonull_static_cast(current()->regs()); + + Mword irq; + + if (EXPECT_TRUE(rf->user_mode())) + rf->srr1 = Proc::wake(rf->srr1); + + irq = Pic::pending(); + if(EXPECT_FALSE(irq == Pic::No_irq_pending)) + return; + + Irq_base *i = nonull_static_cast(Pic::main->irq(irq)); +// Irq::log_irq(i, irq); + i->hit(0); +} diff --git a/kernel/fiasco/src/kern/ppc32/entry_frame-ppc32.cpp b/kernel/fiasco/src/kern/ppc32/entry_frame-ppc32.cpp new file mode 100644 index 00000000..551e2bd3 --- /dev/null +++ b/kernel/fiasco/src/kern/ppc32/entry_frame-ppc32.cpp @@ -0,0 +1,149 @@ +INTERFACE[ppc32]: + +#include "types.h" + +EXTENSION class Syscall_frame +{ + public: + Mword r[30]; //{r0, r2, r3, ..., r10, r13 .., r31, ip + void dump() const; +}; + +EXTENSION class Return_frame +{ + public: + Mword xer; //+32 + Mword ctr; //+28 + Mword cr; //+24 + Mword srr1; //+20 + Mword srr0; //+16 + Mword ulr; //+12 + Mword usp; //+8 + Mword r11; //+4 --two scratch registers for exception entry + Mword r12; //0 + void dump(); + void dump_scratch(); + bool user_mode(); +}; + +//------------------------------------------------------------------------------ +IMPLEMENTATION [ppc32]: + +#include "warn.h" +#include "msr.h" + +IMPLEMENT +void +Syscall_frame::dump() const +{ + printf("IP: %08lx\n", r[29]); + printf("R[%2d]: %08lx R[%2d]: %08lx R[%2d]: %08lx R[%2d]: %08lx R[%2d]: %08lx\n", + 0, r[0], 2, r[1], 3, r[2], 4, r[3], 5, r[4]); + printf("R[%2d]: %08lx R[%2d]: %08lx R[%2d]: %08lx R[%2d]: %08lx R[%2d]: %08lx\n", + 6, r[5], 7, r[6], 8, r[7], 9, r[8], 10, r[9]); +} + +PRIVATE +void +Return_frame::srr1_bit_scan() +{ + printf("SRR1 bits:"); + for(int i = 31; i >= 0; i--) + if(srr1 & (1 << i)) + printf(" %d", 31-i); + printf("\n"); +} + +IMPLEMENT +void +Return_frame::dump() +{ + printf("SRR0 %08lx SRR1 %08lx SP %08lx\n" + "LR %08lx CTR %08lx CR %08lx XER %08lx\n", + srr0, srr1, usp, ulr, ctr, cr, xer); + srr1_bit_scan(); +} + +IMPLEMENT +void +Return_frame::dump_scratch() +{ + printf("\nR[%2d]: %08lx\nR[%2d]: %08lx\n", 11, r11, 12, r12); +} + +IMPLEMENT inline +Mword +Return_frame::sp() const +{ + return Return_frame::usp; +} + +IMPLEMENT inline +void +Return_frame::sp(Mword _sp) +{ + Return_frame::usp = _sp; +} + +IMPLEMENT inline +Mword +Return_frame::ip() const +{ + return Return_frame::srr0; +} + +IMPLEMENT inline +void +Return_frame::ip(Mword _pc) +{ + Return_frame::srr0 = _pc; +} + +IMPLEMENT inline NEEDS ["msr.h"] +bool +Return_frame::user_mode() +{ + return Msr::Msr_pr & srr1; +} + +//--------------------------------------------------------------------------- +//TODO cbass: set registers properly +IMPLEMENT inline +Mword Syscall_frame::next_period() const +{ return false; } + +IMPLEMENT inline +void Syscall_frame::from(Mword id) +{ r[5] = id; /*r6*/ } + +IMPLEMENT inline +Mword Syscall_frame::from_spec() const +{ return r[5]; /*r6*/ } + + +IMPLEMENT inline +L4_obj_ref Syscall_frame::ref() const +{ return L4_obj_ref::from_raw(r[3]); /*r4*/ } + +IMPLEMENT inline +void Syscall_frame::ref(L4_obj_ref const &ref) +{ r[3] = ref.raw(); /*r4*/ } + +IMPLEMENT inline +L4_timeout_pair Syscall_frame::timeout() const +{ return L4_timeout_pair(r[4]); /*r5*/ } + +IMPLEMENT inline +void Syscall_frame::timeout(L4_timeout_pair const &to) +{ r[4] = to.raw(); /*r5*/ } + +IMPLEMENT inline Utcb *Syscall_frame::utcb() const +{ return reinterpret_cast(r[1]); /*r2*/} + +IMPLEMENT inline L4_msg_tag Syscall_frame::tag() const +{ return L4_msg_tag(r[2]); /*r3*/ } + +IMPLEMENT inline +void Syscall_frame::tag(L4_msg_tag const &tag) +{ r[2] = tag.raw(); /*r3*/ } + diff --git a/kernel/fiasco/src/kern/ppc32/exception.S b/kernel/fiasco/src/kern/ppc32/exception.S new file mode 100644 index 00000000..923be16f --- /dev/null +++ b/kernel/fiasco/src/kern/ppc32/exception.S @@ -0,0 +1,361 @@ +/* -*- asm -*- */ + +#include "tcboffset.h" +#include "config_tcbsize.h" + +#define SYSCALL(name) .long sys_##name##_wrapper + +/* Return frame offsets */ +#define RF_XER -36 +#define RF_CTR -32 +#define RF_CR -28 +#define RF_SRR1 -24 +#define RF_SRR0 -20 +#define RF_ULR -16 +#define RF_USP -12 + +.section .exceptcommon, "ax" + +/******************************************************************************* + * System-call table + */ +.global sys_call_table +sys_call_table: + .long sys_kdb_ke // +0x4 (== sys call binding offsets, not 0x0 since + .long sys_kdb_ke // +0x8 srr0 points to instr after 'sc', see + SYSCALL(ipc) // +0xC system_call function below) + .long sys_kdb_ke // +0x10 + SYSCALL(invoke_debug) // +0x14 + .long sys_kdb_ke // +0x18 + .long sys_kdb_ke // +0x1C + .long sys_kdb_ke // +0x20 + .long sys_kdb_ke // +0x24 + .long sys_kdb_ke // +0x28 + + +/******************************************************************************* + * Save volatile registers on return frame and system call frame. + * Separate section, because we only have 256 bytes or 64 instructions space per + * exception + */ + +.align 2 +.global _save_volatile_gpr +_save_volatile_gpr: + /* spill system-call frame */ + stmw 13, -76(%r11) //save r31 - r13 + stwu %r10, -80(%r11) //ip, r12, r11 already saved + stwu %r9 , -4(%r11) + stwu %r8 , -4(%r11) + stwu %r7 , -4(%r11) + stwu %r6 , -4(%r11) + stwu %r5 , -4(%r11) + stwu %r4 , -4(%r11) + stwu %r3 , -4(%r11) + stwu %r2 , -4(%r11) + stwu %r0 , -4(%r11) + + blr + +.align 2 +.global _save_volatile +_save_volatile: + + /* spill return frame */ + mfsrr0 %r12 //exception ip + stwu %r12, -4(%r11) + mfsrr1 %r12 //msr flags + stwu %r12, -4(%r11) + mfcr %r12 //cr + stwu %r12, -4(%r11) + mfctr %r12 //ctr + stwu %r12, -4(%r11) + mfxer %r12 //xer + stwu %r12, -4(%r11) + mfsrr0 %r12 //save ip in syscall frame + stwu %r12, -4(%r11) + + /* set KERNEL flags */ + lis %r12, VAL__MSR__KERNEL@ha + li %r12, VAL__MSR__KERNEL@l + mtmsr %r12 + isync + + b _save_volatile_gpr + +.align 2 +.global return_from_exception +return_from_exception: + mr %r12, %r1 + addi %r12, %r12, (VAL__STACK__FRAME - VAL__ENTRY__FRAME) + lwz %r0, 0(%r12) + lwzu %r3, 8(%r12) //skip r2 + lwzu %r4, 4(%r12) + lwzu %r5, 4(%r12) + lwzu %r6, 4(%r12) + lwzu %r7, 4(%r12) + lwzu %r8, 4(%r12) + lwzu %r9, 4(%r12) + lwzu %r10, 4(%r12) + lmw 13, 4(%r12) //load r13 - r31 + lwzu %r11, 84(%r12) //xer + skip ip register + //of syscall frame + mtxer %r11 + lwzu %r11, 4(%r12) //ctr + mtctr %r11 + lwzu %r11, 4(%r12) //cr + mtcr %r11 + lwzu %r11, 4(%r12) //srr1 + mtsrr1 %r11 + lwzu %r11, 4(%r12) //srr0 + mtsrr0 %r11 + blr + +.macro finish_exception opcode + lwzu %r11, 4(%r12) //ulr + mtlr %r11 + lwzu %r1, 4(%r12) //usp + lwzu %r11, 4(%r12) //r11 + addi %r12, %r12, 8 //should be stack frame + //beginning + mtsprg1 %r12 //save in stack-frame register + lwz %r12, -4(%r12) //r12 + \opcode +.endm + +.macro finish_rfi + finish_exception rfi +.endm + +.macro finish_blr + finish_exception blr +.endm + +.macro save_volatile + mtsprg2 %r1 //tmp save user stack + mtsprg3 %r12 //tmp save r12 + mfcr %r1 //cr + mfsrr1 %r12 //get srr1 + andi. %r12, %r12, VAL__MSR__PR@l //srr1 & Cpu::Msr_pr + beq 1f //if we are coming from kernel + //mode, don't load kernel sp + mtcr %r1 //restore cr + mfsprg1 %r1 //kernel sp + b 2f +1: + mtcr %r1 + mfsprg2 %r1 +2: + mfsprg3 %r12 //recover r12 + stw %r12, -4(%r1) //save r12 + mtsprg3 %r11 //tmp save r11 + mr %r11, %r1 //save r1 in r11 + subi %r1, %r1, VAL__STACK__FRAME //establish stack frame + mfsprg3 %r12 //restore r11 + stwu %r12, -8(%r11) //save r11 + mfsprg2 %r12 //restore r1 + stwu %r12, -4(%r11) //save usp + mflr %r12 + stwu %r12, -4(%r11) //save ulr + + bl _save_volatile +.endm + +/******************************************************************************* + * reset the Thread_cancel flag + * r11, r12 are scrached, r12 contains the thread state + */ +.macro RESET_THREAD_CANCEL + lis %r11, (THREAD_BLOCK_SIZE - 1)@ha + li %r11, (THREAD_BLOCK_SIZE - 1)@l + andc %r11, %r1, %r11 //apply mask to r1 + lwz %r12, OFS__THREAD__STATE(%r11) + rlwinm %r12, %r12, 0, 24, 22 //clear 0x100 (or bit 23) + stw %r12, OFS__THREAD__STATE(%r11) +.endm + +/******************************************************************************* + * system call, entry calculations + */ +/* TODO: implement range check */ +.align 2 +.global system_call +system_call: + RESET_THREAD_CANCEL + addi %r12, %r1, VAL__STACK__FRAME //Return frame + lwz %r11, RF_SRR0(%r12) //srr0/ip + lwz %r10, RF_ULR(%r12) //load ulr and overwrite srr0 on + //return frame + stw %r10, RF_SRR0(%r12) + mr %r12, %r11 + lis %r11, sys_call_table@ha //get offset in sys table + li %r11, sys_call_table@l + sub %r12, %r11, %r12 + lwz %r12, 0(%r12) //load address in sys table + mtctr %r12 + bctr + +/******************************************************************************* + * exception entries + */ +.section .except, "ax" + +.global _except_system_reset +. = 0x100 +_except_system_reset: + save_volatile + bl except_notimpl + bl return_from_exception + finish_rfi + +.global _except_machine_check +. = 0x200 +_except_machine_check: + save_volatile + bl except_notimpl + bl return_from_exception + finish_rfi + +/* TODO cbass: add handler if page-fault handling is unsuccessfull */ +.global _except_dsi +. = 0x300 +_except_dsi: + save_volatile + mfdar %r3 //pfa-address + mfdsisr %r4 //error codes + mfsrr1 %r12 + andi. %r12, %r12, VAL__MSR__PR@l //get privilege level + or %r4, %r4, %r12 //set privilege level in error code + mfsrr0 %r5 //pc + mfsprg1 %r6 //Return_frame + bl pagefault_entry + bl return_from_exception + finish_rfi + +/* TODO cbass: add handler if page-fault handling is unsuccessfull */ +.global _except_isi +. = 0x400 +_except_isi: + save_volatile + mfsrr0 %r3 //pfa-address + mfsrr1 %r4 //error codes + mfsrr0 %r5 //pc = pfa + mfsprg1 %r6 //Return_frame + bl pagefault_entry + bl return_from_exception + finish_rfi + +.global _except_interrupt +. = 0x500 +_except_interrupt: + save_volatile + bl irq_handler + bl return_from_exception + finish_rfi + +.global _except_align +. = 0x600 +_except_align: + save_volatile + bl except_notimpl + bl return_from_exception + finish_rfi + +.global _except_program +. = 0x700 +_except_program: + save_volatile + bl except_notimpl + bl return_from_exception + finish_rfi + +.global _except_float +. = 0x800 +_except_float: + save_volatile + bl except_notimpl + bl return_from_exception + finish_rfi + +/** + *decrementer (timer) exception + */ +.global _except_decrementer +. = 0x900 +_except_decrementer: + save_volatile + bl timer_handler + bl return_from_exception + finish_rfi + +.global _except_system_call +. = 0xc00 +_except_system_call: + save_volatile + bl system_call + bl return_from_exception + finish_rfi + +.global _except_trace +. = 0xd00 +_except_trace: + save_volatile + bl except_notimpl + bl return_from_exception + finish_rfi + +.global _except_float_assist +. = 0xe00 +_except_float_assist: + save_volatile + bl except_notimpl + bl return_from_exception + finish_rfi + +// XXX: just a build fix... +.align 4 + .global leave_by_trigger_exception +leave_by_trigger_exception: +// XXX: end of just a build fix... + +.text + .global vcpu_resume +vcpu_resume: +// XXX: end of just a build fix... + +/******************************************************************************* + * kdebug entry + */ +.section .exceptcommon, "ax" + +.macro DEBUGGER_ENTRY + mtsprg3 %r12 //set srr1 to msr + mfmsr %r12 + mtsrr1 %r12 + mfsprg3 %r12 + save_volatile + mflr %r12 //error-code + stwu %r12, -4(%r11) + lis %r12, 0 //pfa + li %r12, -1 + stwu %r12, -4(%r11) + subi %r1, %r1, 16 //adjust stack frame + mr %r3, %r11 //set Trap_state ptr + + bl call_nested_trap_handler + addi %r1, %r1, 16 + bl return_from_exception + finish_blr +.endm + +.align 2 +.global kern_kdebug_entry +kern_kdebug_entry: +#ifdef CONFIG_JDB + DEBUGGER_ENTRY +#else + blr +#endif + + + diff --git a/kernel/fiasco/src/kern/ppc32/kdb_ke-ppc32.cpp b/kernel/fiasco/src/kern/ppc32/kdb_ke-ppc32.cpp new file mode 100644 index 00000000..6f9c2b5f --- /dev/null +++ b/kernel/fiasco/src/kern/ppc32/kdb_ke-ppc32.cpp @@ -0,0 +1,4 @@ +INTERFACE [ppc32]: + +void kdb_ke(const char *msg) asm ("kern_kdebug_entry"); +void kdb_ke_sequence(const char *msg) asm ("kern_kdebug_entry"); diff --git a/kernel/fiasco/src/kern/ppc32/kernel_task-ppc32.cpp b/kernel/fiasco/src/kern/ppc32/kernel_task-ppc32.cpp new file mode 100644 index 00000000..8ecbc328 --- /dev/null +++ b/kernel/fiasco/src/kern/ppc32/kernel_task-ppc32.cpp @@ -0,0 +1,10 @@ +IMPLEMENTATION[ppc32]: + +#include "config.h" +#include "globals.h" +#include "space.h" + +PRIVATE inline NEEDS["globals.h"] +Kernel_task::Kernel_task() +: Task(Ram_quota::root, Kmem::kdir()) +{} diff --git a/kernel/fiasco/src/kern/ppc32/kernel_thread-ppc32.cpp b/kernel/fiasco/src/kern/ppc32/kernel_thread-ppc32.cpp new file mode 100644 index 00000000..e3f0aced --- /dev/null +++ b/kernel/fiasco/src/kern/ppc32/kernel_thread-ppc32.cpp @@ -0,0 +1,22 @@ +IMPLEMENTATION [ppc32]: + +#include "mem_layout.h" +#include "msr.h" +IMPLEMENT inline +void +Kernel_thread::free_initcall_section() +{ + memset( (void*)&Mem_layout::initcall_start, 0, &Mem_layout::initcall_end + - &Mem_layout::initcall_start ); + printf("%d KB kernel memory freed\n", (int)(&Mem_layout::initcall_end - + &Mem_layout::initcall_start)/1024); +} + +IMPLEMENT FIASCO_INIT +void +Kernel_thread::bootstrap_arch() +{ + //status for kernel thread + Return_frame *rf = nonull_static_cast(current()->regs()); + rf->srr1 = Msr::Msr_kernel; +} diff --git a/kernel/fiasco/src/kern/ppc32/kip_init.cpp b/kernel/fiasco/src/kern/ppc32/kip_init.cpp new file mode 100644 index 00000000..1d5f6d72 --- /dev/null +++ b/kernel/fiasco/src/kern/ppc32/kip_init.cpp @@ -0,0 +1,73 @@ +INTERFACE [ppc32]: + +#include "kip.h" + +class Kip_init +{ +public: + static void init(); +}; + + +//--------------------------------------------------------------------------- +IMPLEMENTATION [ppc32]: + +#include "config.h" +#include "mem_layout.h" + +// Make the stuff below apearing only in this compilation unit. +// Trick Preprocess to let the struct reside in the cc file rather +// than putting it into the _i.h file which is perfectly wrong in +// this case. +namespace KIP_namespace +{ + enum + { + Num_mem_descs = 20, + Max_len_version = 512, + + Size_mem_descs = sizeof(Mword) * 2 * Num_mem_descs, + }; + + struct KIP + { + Kip kip; + char mem_descs[Size_mem_descs]; + }; + + KIP ppc32_kernel_info_page asm("ppc32_kernel_info_page") __attribute__((section(".kernel_info_page"))) = + { + { + /* 00/00 */ L4_KERNEL_INFO_MAGIC, + Config::Kernel_version_id, + (Size_mem_descs + sizeof(Kip)) >> 4, + {}, 0, {}, + /* 10/20 */ 0, {}, + /* 20/40 */ 0, 0, {}, + /* 30/60 */ 0, 0, {}, + /* 40/80 */ 0, 0, {}, + /* 50/A0 */ 0, (sizeof(Kip) << (sizeof(Mword)*4)) | Num_mem_descs, {}, + /* 60/C0 */ {}, + /* A0/140 */ 0, 0, 0, 0, + /* B0/160 */ {}, + /* E0/1C0 */ 0, 0, {}, + /* F0/1D0 */ {}, + }, + {} + }; +}; + + +IMPLEMENT +void Kip_init::init() +{ + Kip *kinfo = reinterpret_cast(&KIP_namespace::ppc32_kernel_info_page); + Kip::init_global_kip(kinfo); + + /* add kernel image */ + kinfo->add_mem_region(Mem_desc(0,(Address)&Mem_layout::end - 1, + Mem_desc::Reserved)); + + kinfo->add_mem_region(Mem_desc(0, Mem_layout::User_max - 1, + Mem_desc::Conventional, true)); +} diff --git a/kernel/fiasco/src/kern/ppc32/kmem.cpp b/kernel/fiasco/src/kern/ppc32/kmem.cpp new file mode 100644 index 00000000..aafbc40b --- /dev/null +++ b/kernel/fiasco/src/kern/ppc32/kmem.cpp @@ -0,0 +1,88 @@ +INTERFACE [ppc32]: + +#include "paging.h" + +class Page_table; + +class Kmem : public Mem_layout +{ +public: + static Pdir *kdir(); + static Pdir *dir(); + + static Mword *kernel_sp(); + static void kernel_sp(Mword *); + + static Mword is_tcb_page_fault( Mword pfa, Mword error ); + static Mword is_kmem_page_fault( Mword pfa, Mword error ); + static Mword is_io_bitmap_page_fault( Mword pfa ); + + static Address virt_to_phys(const void *addr); +private: + static Pdir *_kdir; + static Mword *_sp; +}; + +//--------------------------------------------------------------------------- +IMPLEMENTATION [ppc32]: + +#include "mem_layout.h" +#include "paging.h" +#include "panic.h" + +char kernel_page_directory[sizeof(Pdir)]; +Pdir *Kmem::_kdir = (Pdir *)&kernel_page_directory; +Mword *Kmem::_sp = 0; + +IMPLEMENT inline +Pdir *Kmem::kdir() +{ return _kdir; } + +IMPLEMENT inline +Pdir *Kmem::dir() +{ return _kdir; } + +IMPLEMENT inline +Mword *Kmem::kernel_sp() +{ return _sp;} + +IMPLEMENT inline +void Kmem::kernel_sp(Mword *sp) +{ _sp = sp; } + +PUBLIC static inline NEEDS["mem_layout.h", "panic.h"] +Address Kmem::ipc_window(unsigned /*win*/) +{ + panic("%s not implemented", __PRETTY_FUNCTION__); + return 0; +} + +IMPLEMENT inline NEEDS["paging.h"] +Address Kmem::virt_to_phys(const void *addr) +{ + Address a = reinterpret_cast
(addr); + return kdir()->virt_to_phys(a); +} + +//------------------------------------------------------------------------------ +/* + * dummy implementations + */ + +IMPLEMENT inline +Mword Kmem::is_kmem_page_fault(Mword pfa, Mword /*error*/) +{ + return in_kernel(pfa); +} + +IMPLEMENT inline +Mword Kmem::is_tcb_page_fault(Mword /*pfa*/, Mword /*error*/ ) +{ + return 0; +} + +IMPLEMENT inline +Mword Kmem::is_io_bitmap_page_fault( Mword /*pfa*/ ) +{ + return 0; +} diff --git a/kernel/fiasco/src/kern/ppc32/kmem_alloc-ppc32.cpp b/kernel/fiasco/src/kern/ppc32/kmem_alloc-ppc32.cpp new file mode 100644 index 00000000..a8c199db --- /dev/null +++ b/kernel/fiasco/src/kern/ppc32/kmem_alloc-ppc32.cpp @@ -0,0 +1,51 @@ +//---------------------------------------------------------------------------- +IMPLEMENTATION [ppc32]: + +#include "mem_region.h" +IMPLEMENT +Kmem_alloc::Kmem_alloc() +{ + Mword alloc_size = Config::Kmem_size; + unsigned long max = ~0UL; +#warning This code needs adaption (see e.g. the arm version) + for (;;) + { + Mem_region r; r.start=3; r.end=1; // = Kip::k()->last_free(max); + + if (r.start > r.end + 1) + panic("Corrupt memory descscriptor in KIP..."); + + if (r.start == r.end + 1) + panic("Could not acquire enough kernel memory"); + + max = r.start; + Mword size = r.end - r.start + 1; + if(alloc_size <= size) + { + r.start += (size - alloc_size); + Kip::k()->add_mem_region(Mem_desc(r.start, r.end, + Mem_desc::Reserved)); + + /* init buddy allocator with physical addresses */ + a->init(r.start); + a->add_mem((void*)r.start, alloc_size); + printf("Buddy allocator at: [%08lx; %08lx] - %lu KB\n", + r.start, r.end, alloc_size / 1024); + break; + } + } +} + +//---------------------------------------------------------------------------- +IMPLEMENTATION [ppc32 && debug]: + +#include + +#include "kip_init.h" +#include "panic.h" + +PUBLIC +void Kmem_alloc::debug_dump() +{ + a->dump(); +} diff --git a/kernel/fiasco/src/kern/ppc32/main.cpp b/kernel/fiasco/src/kern/ppc32/main.cpp new file mode 100644 index 00000000..6bc721af --- /dev/null +++ b/kernel/fiasco/src/kern/ppc32/main.cpp @@ -0,0 +1,99 @@ +INTERFACE [ppc32]: +#include + +//--------------------------------------------------------------------------- +IMPLEMENTATION [ppc32]: + +#include +#include +#include + +#include "config.h" +#include "globals.h" +//#include "kmem_alloc.h" +#include "kip_init.h" +//#include "pagetable.h" +#include "kdb_ke.h" +#include "kernel_thread.h" +#include "kernel_task.h" +#include "kernel_console.h" +//#include "reset.h" //TODO cbass: implement +#include "space.h" +//#include "terminate.h" //TODO cbass: implement + +#include "processor.h" +#include "boot_info.h" +/* +static int exit_question_active = 0; + +extern "C" void __attribute__ ((noreturn)) +_exit(int) +{ + if (exit_question_active) + platform_reset(); + + while (1) + { + Proc::halt(); + Proc::pause(); + } +} + + +static void exit_question() +{ + exit_question_active = 1; + + while (1) + { + puts("\nReturn reboots, \"k\" enters L4 kernel debugger..."); + + char c = Kconsole::console()->getchar(); + + if (c == 'k' || c == 'K') + { + kdb_ke("_exit"); + } + else + { + // it may be better to not call all the destruction stuff + // because of unresolved static destructor dependency + // problems. + // SO just do the reset at this point. + puts("\033[1mRebooting...\033[0m"); + platform_reset(); + break; + } + } +} + +*/ +#include "thread_state.h" +int main() +{ + // caution: no stack variables in this function because we're going + // to change the stack pointer! + + // make some basic initializations, then create and run the kernel + // thread + //set_exit_question(&exit_question); + + // disallow all interrupts before we selectively enable them + // pic_disable_all(); + + // create kernel thread + static Kernel_thread *kernel = new (Ram_quota::root) Kernel_thread; + Task *const ktask = Kernel_task::kernel_task(); + check(kernel->bind(ktask, User::Ptr(0))); + //kdb_ke("init"); + + // switch to stack of kernel thread and bootstrap the kernel + asm volatile ( " mr %%r1, %[stack] \n" //new stack + " mr %%r3, %[kernel] \n" //"this" pointer + " bl call_bootstrap \n" + : + : [stack]"r" (kernel->init_stack()), + [kernel]"r" (kernel) + ); +} + diff --git a/kernel/fiasco/src/kern/ppc32/mapping-ppc32.cpp b/kernel/fiasco/src/kern/ppc32/mapping-ppc32.cpp new file mode 100644 index 00000000..e829af05 --- /dev/null +++ b/kernel/fiasco/src/kern/ppc32/mapping-ppc32.cpp @@ -0,0 +1,24 @@ +INTERFACE [ppc32]: + +#include "types.h" +class Treemap; + +class Mapping_entry +{ +public: + enum { Alignment = 4 }; + union + { + struct + { + unsigned long _space:32; ///< Address-space number +// unsigned long _pad:1; + unsigned long address:20; ///< Virtual address in address space + } __attribute__((packed)) data; + Treemap *_submap; + }; + Unsigned8 _depth; + void set_space(Space *s) { data._space = (unsigned long)s; } + Space *space() const { return (Space *)data._space; } +}; + diff --git a/kernel/fiasco/src/kern/ppc32/mem_layout-ppc32.cpp b/kernel/fiasco/src/kern/ppc32/mem_layout-ppc32.cpp new file mode 100644 index 00000000..ff39af03 --- /dev/null +++ b/kernel/fiasco/src/kern/ppc32/mem_layout-ppc32.cpp @@ -0,0 +1,147 @@ +//--------------------------------------------------------------------------- +INTERFACE [ppc32]: + +#include "initcalls.h" +#include "template_math.h" + +EXTENSION class Mem_layout +{ + +//TODO cbass: check what can be omitted +public: + enum Phys_layout { + Utcb_ptr_page = 0x3000, + Syscalls_phys = 0x4000, + Tbuf_status_page = 0x5000, + Kernel_start = 0x6000, //end phys pool + Syscalls = 0xfffff000, + + User_max = 0xf0000000, + Tcbs = 0xc0000000, + Utcb_addr = User_max - 0x2000, + utcb_ptr_align = Tl_math::Ld::Res, + Tcbs_end = 0xe0000000, + __free_1_start = 0xec000000, + __free_1_end = 0xed000000, + Htab = 0xee000000, ///< % 32MB hashed pgtab + Map_base = 0xf0000000, ///< % 80MB kernel memory + Map_end = 0xf5000000, + Caps_start = 0xf5000000, + Caps_end = 0xfd000000, + Kernel_image = 0xfd000000, + Kernel_max = 0x00000000, + }; + + static Address Tbuf_buffer_area; + static Address Tbuf_ubuffer_area; +}; + + + +// ------------------------------------------------------------------------ +IMPLEMENTATION [ppc32]: + +#include "panic.h" +#include + +Address Mem_layout::Tbuf_buffer_area = 0; +Address Mem_layout::Tbuf_ubuffer_area = 0; + + +//no virtual memory in kernel mode +PUBLIC static inline +Address +Mem_layout::phys_to_pmem (Address addr) +{ + return addr; +} + +PUBLIC static inline +Address +Mem_layout::pmem_to_phys (Address addr) +{ + return addr; +} + +PUBLIC static inline +Address +Mem_layout::pmem_to_phys (const void *ptr) +{ + return reinterpret_cast
(ptr); +} + +PUBLIC static inline +template< typename V > +bool +Mem_layout::read_special_safe(V const * /* *address */, V &/*v*/) +{ + panic("%s not implemented", __PRETTY_FUNCTION__); + return false; +} + +PUBLIC static inline +template< typename T > +T +Mem_layout::read_special_safe(T const *a) +{ + Mword res; + asm volatile( "lwz %0, 0(%1)\n" + : "=r"(res) : "r"(a)); + return T(res); +} + + +/* no page faults can occur, return true */ +PUBLIC static inline +bool +Mem_layout::is_special_mapped(void const * /*a*/) +{ + return true; +} + + +IMPLEMENTATION [ppc32 && debug]: + +#include "kip_init.h" + +PUBLIC static FIASCO_INIT +void +Mem_layout::init() +{ + Mword alloc_size = 0x200000; + unsigned long max = ~0UL; + for (;;) + { + Mem_region r; r.start=2;r.end=1;// = Kip::k()->last_free(max); + if (r.start > r.end) + panic("Corrupt memory descscriptor in KIP..."); + + if (r.start == r.end) + panic("not enough kernel memory"); + + max = r.start; + Mword size = r.end - r.start + 1; + if(alloc_size <= size) + { + r.start += (size - alloc_size); + Kip::k()->add_mem_region(Mem_desc(r.start, r.end, + Mem_desc::Reserved)); + + printf("TBuf installed at: [%08lx; %08lx] - %lu KB\n", + r.start, r.end, alloc_size / 1024); + + Tbuf_buffer_area = Tbuf_ubuffer_area = r.start; + break; + } + } + + if(!Tbuf_buffer_area) + panic("Could not allocate trace buffer"); +} + +IMPLEMENTATION [ppc32 && !debug]: + +PUBLIC static FIASCO_INIT +void +Mem_layout::init() +{} diff --git a/kernel/fiasco/src/kern/ppc32/mem_space-cache.cpp b/kernel/fiasco/src/kern/ppc32/mem_space-cache.cpp new file mode 100644 index 00000000..483269b7 --- /dev/null +++ b/kernel/fiasco/src/kern/ppc32/mem_space-cache.cpp @@ -0,0 +1,71 @@ +/* + * PPC page cache + */ +INTERFACE[ppc32]: + + +EXTENSION class Mem_space +{ +private: + Status v_insert_cache(Pte_base *e, Address virt, size_t size, unsigned page_attribs, + Dir_type *dir = 0); + unsigned long v_delete_cache(Pt_entry *e, unsigned page_attribs); +}; + + +//------------------------------------------------------------------------------ +IMPLEMENTATION[ppc32]: + +IMPLEMENT +Mem_space::Status +Mem_space::v_insert_cache(Pte_base *e, Address virt, size_t size, + unsigned page_attribs, Dir_type *dir = 0) +{ + if(!dir) dir = _dir; + + Pdir::Iter i = + dir->walk(Addr(virt), Pdir::Depth, Kmem_alloc::q_allocator(_quota)); + + if (EXPECT_FALSE(!i.e->valid() && i.shift() != Config::PAGE_SHIFT)) + return Insert_err_nomem; + + Address i_phys; + + //get physical addresses + Pte_htab::pte_lookup(i.e, &i_phys); + + if(i.e->valid() && e->addr() == i_phys) + { + Status state = pte_attrib_upgrade(i.e, size, page_attribs); + return state; + } + + *i.e = e->raw() | page_attribs; + + //if super-page, set Pse_bit in Pdir + if(size == Config::SUPERPAGE_SIZE) + { + i = dir->walk(Addr(virt), Pdir::Super_level); + *i.e = i.e->raw() | Pte_base::Pse_bit; + } + + return Insert_ok; +} + +IMPLEMENT +unsigned long +Mem_space::v_delete_cache(Pt_entry *e, unsigned page_attribs = Page_all_attribs) +{ + unsigned ret; + + ret = e->raw() & page_attribs; + + if (!(page_attribs & Page_user_accessible)) + // downgrade PDE (superpage) rights + e->del_attr(page_attribs); + else + // delete PDE (superpage) + e = 0; + + return ret; +} diff --git a/kernel/fiasco/src/kern/ppc32/mem_space-htab.cpp b/kernel/fiasco/src/kern/ppc32/mem_space-htab.cpp new file mode 100644 index 00000000..617dbf8e --- /dev/null +++ b/kernel/fiasco/src/kern/ppc32/mem_space-htab.cpp @@ -0,0 +1,439 @@ +/* + * PPC hashed page table + */ +INTERFACE [ppc32]: + +#include "types.h" +#include "initcalls.h" + +EXTENSION class Mem_space +{ + + public: + static void init(); + private: + typedef struct Evict { + Address virt; + Address phys; + Dir_type *dir; + } Evict; + + static Mword _htabmask; + static Mword _htaborg; + + Status v_insert_htab(Address phys, Address virt, Address *pte_ptr, + Evict *evict); + unsigned long v_delete_htab(Address pte_ptr, unsigned page_attribs); +}; + +IMPLEMENTATION [ppc32]: + +#include +#include "config.h" +#include "kip_init.h" +#include "panic.h" +#include "util.h" + +Mword Mem_space::_htabmask = 0; +Mword Mem_space::_htaborg = 0; + +// ea == virt - effective address (32 bit) +// pa - physical address + +//------------------------------------------------------------------------------ +/* + * Page-table handling + */ + +PRIVATE static inline +Address +Mem_space::page_index(Address ea) +{ + return (ea >> 12) & 0xffff; +} + +PRIVATE static inline +Address +Mem_space::_vsid(Address ea, Pdir *dir) +{ + //24 bits of pdir + segment selector of ea + return ((Address)dir >> 8) + (ea >> 28); +} + +PRIVATE inline NEEDS[Mem_space::_vsid] +Address +Mem_space::vsid(Address ea) +{ + Dir_type *dir = _dir; + + //kernel space + if(ea >= Mem_layout::User_max) + dir = Kmem::kdir(); + + return _vsid(ea, dir); +} + +PRIVATE static inline +Mem_space::Dir_type* +Mem_space::vsid_to_dir(Mword vsid) +{ + vsid &= ~0xf; + vsid <<= 8; + return reinterpret_cast(vsid); +} + +IMPLEMENT inline NEEDS["cpu.h", Mem_space::vsid] +void +Mem_space::make_current() +{ + Cpu::set_vsid(vsid(0)); + _current.cpu(current_cpu()) = this; +} + +PRIVATE static inline +Address +Mem_space::hash_to_pteg(Address hash) +{ + // high seven htaborg bits + Mword pteg = _htaborg & 0xfe000000; + //htabmask shifted 10 + hash &= (_htabmask << 10) | 0x3ff; + //low nine htaborg bits + hash |= (_htaborg & 0x01ff0000) >> 6; + return pteg | (hash << 6); +} + +PRIVATE inline NEEDS[Mem_space::vsid] +Address +Mem_space::hash_func(Address ea) +{ + return (vsid(ea) & 0x7ffff) ^ page_index(ea); +} + +/** + * Find page-table entry group + * + * primary and secondary pteg + */ +PRIVATE inline +Address * +Mem_space::pteg_p(Address ea) +{ + return reinterpret_cast(hash_to_pteg(hash_func(ea))); +} + +PRIVATE inline +Address * +Mem_space::pteg_s(Mword ea) +{ + Address hash_s = (~hash_func(ea)) & 0x7ffff; + return reinterpret_cast(hash_to_pteg(hash_s)); +} + +PRIVATE +Pte_htab * +Mem_space::locate(Pte_htab *pte, Address ea) +{ + Address *pteg[2] = {pteg_p(ea), pteg_s(ea)}; + Pte_htab *ret = NULL, *free = NULL; + Mword h = 0; + for(int i = 0; i < 2*Config::Htab_entries; i += 2) + { + for(int j = 0; j <= 1; j++) + { + ret = reinterpret_cast(pteg[j] + i); + pte->pte.h = j; + + if(pte->v_equal(ret)) + return ret; + + if(!ret->valid() && !free) + { + free = ret; + h = j; + } + } + + if(free) break; + } + + if(EXPECT_FALSE(!free)) + free = ret; + pte->pte.h = h; + return free; +} + +//------------------------------------------------------------------------------ +PRIVATE template< typename T > +inline +T +Mem_space::to_htab_fmt(T page_attribs) +{ + // if page attribs has the writable bit set, make sure to erase the readable + // bit because 0x11b is read-only on ppc + if(page_attribs & Page_writable) + page_attribs &= ~Page_user_accessible; + + return page_attribs & (~Pt_entry::Valid & ~Pt_entry::Htab_entry); +} + +PRIVATE template< typename T > +inline +T +Mem_space::to_kernel_fmt(T page_attribs, bool is_htab_entry) +{ + T attribs = page_attribs; + + attribs &= Page_all_attribs; + + if(!is_htab_entry) + attribs |= Pte_base::Valid; + + if(attribs & Page_writable) + attribs |= Page_user_accessible; + + return attribs; +} + +PRIVATE +Mem_space::Status +Mem_space::pte_attrib_upgrade(Pte_base *e, size_t size, unsigned page_attribs) +{ + Pte_base *e2 = e; + Status ret = Insert_warn_attrib_upgrade; + page_attribs = to_htab_fmt(page_attribs); + + for(Address offs = 0; offs < (size / Config::PAGE_SIZE) * sizeof(Mword); + offs += sizeof(Mword)) + { + e2 = reinterpret_cast(e2 + offs); + + if(!e2->valid()) + continue; + + if(e2->is_htab_entry()) + { + if(EXPECT_FALSE((e2->raw() | page_attribs) == e2->raw())) + { + ret = Insert_warn_exists; + continue; + } + e2->add_attr(page_attribs); + ret = Insert_warn_attrib_upgrade; + } + else + ret = pte_attrib_upgrade(e2->raw(), page_attribs); + } + + return ret; +} + + +PRIVATE inline +Mem_space::Status +Mem_space::pte_attrib_upgrade(Address pte_addr, unsigned page_attribs) +{ + Lock_guard guard(&cpu_lock); + Pte_htab * pte_phys = Pte_htab::addr_to_pte(pte_addr); + if(EXPECT_FALSE((pte_phys->phys() | page_attribs) + == pte_phys->phys())) + return Insert_warn_exists; + + pte_phys->pte.valid = 0; + Mem_unit::sync(); + pte_phys->raw.raw1 = to_htab_fmt(pte_phys->raw.raw1 | page_attribs); + Mem_unit::tlb_flush(pte_phys->pte_to_ea()); + pte_phys->pte.valid = 1; + Mem_unit::sync(); + +/* + printf("DBG: %s: phys %08lx virt: %08lx vsid: %lx raw0: %08lx raw1: %08lx ptr %lx\n", + __func__, pte_phys->phys() & Config::PAGE_MASK, pte_phys->pte_to_ea(), + vsid(pte_phys->pte_to_ea()), pte_phys->virt(), pte_phys->phys(), pte_phys); +*/ + return Insert_warn_attrib_upgrade; +} + +IMPLEMENT +Mem_space::Status +Mem_space::v_insert_htab(Address phys, Address virt, + Address *pte_ptr, Evict *evict) +{ + Pte_htab pte(to_htab_fmt(phys), virt, + vsid(virt)); + Pte_htab *pte_phys = locate(&pte, virt); +/* + if(EXPECT_FALSE(pte.v_equal(pte_phys) + && !pte.p_equal(pte_phys))) + return Insert_err_exists; +*/ + //set pte pointer + *pte_ptr = reinterpret_cast
(pte_phys); + + //we have to evict something + if(EXPECT_FALSE(pte_phys->valid())) + { + evict->virt = pte_phys->pte_to_ea(); + evict->phys = pte_phys->raw.raw1 | Pt_entry::Valid; + evict->dir = vsid_to_dir(pte_phys->pte.vsid); + *pte_phys = pte; + //flush tlb in case the page is in current address space + Mem_unit::tlb_flush(evict->virt); + Mem_unit::sync(); + return Insert_err_nomem;; + } + + *pte_phys = pte; + Mem_unit::sync(); + + +//DEBUG +#if 0 + printf("htab insert %s: phys %08lx virt: %08lx vsid: %lx raw0: %08lx raw1: %08lx ptr %lx\n", + __func__, phys, virt, vsid(virt), pte.virt(), pte.phys(), *pte_ptr); + printf("pte_addr: %p\n", pte_phys); + printf("vsid: %lx, dir %p, rev_dir %p\n", vsid(virt), _dir, vsid_to_dir(vsid(virt))); + printf("reverse virt: %lx\n", pte_to_ea(pte_phys)); + printf("raw0 %lx raw1 %lx\n", pte_phys->virt(), pte_phys->phys()); + printf("current pdir %p\n", current_pdir()); + printf("MBAR %lx\n", *((Address*)0x80000000)); + printf("vsid0 %lx\n", vsid(0)); + make_current(); + for(int i = 0; i < 16; i++) { + printf("vsid%d read %lx\n", i, Cpu::read_vsid(i)); + } + v_lookup_htab(virt, 0, 0); + v_delete_htab(virt, Page_user_accessible); +//END debug +#endif + + return Insert_ok; +} + + +IMPLEMENT +unsigned long +Mem_space::v_delete_htab(Address pte_addr, unsigned page_attribs = Page_all_attribs) +{ + Lock_guard guard(&cpu_lock); + unsigned long ret; + Pte_htab *pte_phys = Pte_htab::addr_to_pte(pte_addr); + + if(EXPECT_FALSE(!pte_phys->valid())) + return 0; + + ret = pte_phys->phys() & page_attribs; + + if(!(page_attribs & Page_user_accessible)) + pte_phys->raw.raw0 &= ~page_attribs; + else + pte_phys->raw.raw0 = pte_phys->raw.raw1 = 0; + + Mem_unit::tlb_flush(pte_phys->pte_to_ea()); + Mem_unit::sync(); + return ret; +} + +IMPLEMENT inline NEEDS["kmem.h"] +void +Mem_space::switchin_context(Mem_space *from) +{ + if(dir() == Kmem::dir()) + return; + + if (this != from) + make_current(); +} + +//------------------------------------------------------------------------------ +/* + * INIT FUNCITONS + */ + +/** + * Calculate htab size, as described in PPC reference + * manual, based on given memory + */ +PRIVATE static FIASCO_INIT +unsigned long +Mem_space::htab_size(Mword ram) +{ + ram >>= 7; + Mword log2 = Util::log2(ram); + + if(ram != 1UL << log2) + log2++; + + //min is 64 KB + log2 = (log2 < 16)? 16: log2; + return 1UL << log2; +} + +/** + * Find physical memory area. + * + * alloc_size has to be a multiple of two, result will be naturally aligned + */ +PRIVATE static FIASCO_INIT +Mword +Mem_space::alloc(Mword alloc_size) +{ + //unsigned long max = ~0UL; + Mword start; + for (;;) + { + Mem_region r; r.start=2; r.end=1;// = Kip::k()->last_free(max); + if (r.start > r.end) + panic("Corrupt memory descscriptor in KIP..."); + + if (r.start == r.end) + panic("not enough memory for page table"); + + //max = r.start; + Mword size = r.end - r.start + 1; + start = (r.end - alloc_size + 1) & ~(alloc_size - 1); + if(alloc_size <= size && start >= r.start) + { + Kip::k()->add_mem_region(Mem_desc(start, r.end, + Mem_desc::Reserved)); + break; + } + } + return start; +} + +/** + * Install htab + */ +PRIVATE static FIASCO_INIT +void +Mem_space::install() +{ + Mword kernel_vsid = _vsid(Mem_layout::User_max, Kmem::kdir()) + | Segment::Default_attribs; + + asm volatile( " sync \n" + " mtsdr1 %[sdr1] \n" //set SDR1 + " isync \n" + " mtsr 15, %[vsid] \n" //set kernel space + //(last 256 MB of address space) + : + : [sdr1]"r" (_htaborg | _htabmask), + [vsid]"r" (kernel_vsid) + ); +} + +IMPLEMENT static FIASCO_INIT +void +Mem_space::init() +{ + Mword alloc_size = 0; // tbd: get size from memory descriptors + _htaborg = alloc(alloc_size); + _htabmask = ((alloc_size >> 16) - 1) & 0x1ff; //9 bit + + install(); + + printf("Htab installed at: [%08lx; %08lx] - %lu KB\n", + _htaborg, _htaborg + alloc_size - 1, alloc_size/1024); +} + diff --git a/kernel/fiasco/src/kern/ppc32/mem_space-ppc32.cpp b/kernel/fiasco/src/kern/ppc32/mem_space-ppc32.cpp new file mode 100644 index 00000000..e4f77248 --- /dev/null +++ b/kernel/fiasco/src/kern/ppc32/mem_space-ppc32.cpp @@ -0,0 +1,465 @@ +INTERFACE [ppc32]: + +#include "entry_frame.h" + +extern "C" +Mword +pagefault_entry(Address, Mword, Mword, Return_frame *); + +EXTENSION class Mem_space +{ +public: + + typedef Pdir Dir_type; + + /** Return status of v_insert. */ + enum //Status + { + Insert_ok = 0, ///< Mapping was added successfully. + Insert_warn_exists, ///< Mapping already existed + Insert_warn_attrib_upgrade, ///< Mapping already existed, attribs upgrade + Insert_err_nomem, ///< Couldn't alloc new page table + Insert_err_exists ///< A mapping already exists at the target addr + }; + + /** Attribute masks for page mappings. */ + enum Page_attrib + { + Page_no_attribs = 0, + /// Page is writable. + Page_writable = Pt_entry::Writable, + Page_cacheable = 0, + /// Page is noncacheable. + Page_noncacheable = Pt_entry::Noncacheable | Pt_entry::Write_through, + /// it's a user page. + Page_user_accessible = Pt_entry::User, + /// Page has been referenced + Page_referenced = Pt_entry::Referenced, + /// Page is dirty + Page_dirty = Pt_entry::Dirty, + Page_references = Page_referenced | Page_dirty, + /// A mask which contains all mask bits + Page_all_attribs = Page_writable | Page_noncacheable | + Page_user_accessible | Page_referenced | Page_dirty, + }; + + // Mapping utilities + enum // Definitions for map_util + { + Need_insert_tlb_flush = 0, + Map_page_size = Config::PAGE_SIZE, + Page_shift = Config::PAGE_SHIFT, + Map_superpage_size = Config::SUPERPAGE_SIZE, + Map_max_address = Mem_layout::User_max, + Whole_space = MWORD_BITS, + Identity_map = 0, + }; + + bool try_htab_fault(Address virt); +protected: + // DATA + Dir_type *_dir; +}; + + +//---------------------------------------------------------------------------- +IMPLEMENTATION [ppc32]: + +#include +#include +#include "cpu.h" +#include "kdb_ke.h" +#include "l4_types.h" +#include "mem_layout.h" +#include "paging.h" +#include "std_macros.h" +#include "kmem.h" +#include "logdefs.h" +#include "panic.h" +#include "lock_guard.h" +#include "cpu_lock.h" +#include "warn.h" + + + + +PUBLIC explicit inline +Mem_space::Mem_space(Ram_quota *q) : _quota(q), _dir(0) {} + +PROTECTED inline +bool +Mem_space::initialize() +{ + void *b; + if (EXPECT_FALSE(!(b = Kmem_alloc::allocator() + ->q_alloc(_quota, Config::PAGE_SHIFT)))) + return false; + + _dir = static_cast(b); + _dir->clear(); // initialize to zero + return true; // success +} + +PROTECTED inline +void +Mem_space::sync_kernel() +{ +} + +PUBLIC +Mem_space::Mem_space(Ram_quota *q, Dir_type* pdir) + : _quota(q), _dir(pdir) +{ + _kernel_space = this; + _current.cpu(0) = this; +} + +//XXX cbass: check; +PUBLIC static inline +Mword +Mem_space::xlate_flush(unsigned char rights) +{ + Mword a = Page_references; + if (rights & L4_fpage::RX) + a |= Page_all_attribs; + else if (rights & L4_fpage::W) + a |= Page_writable; + + return a; +} + +//XXX cbass: check; +PUBLIC static inline +Mword +Mem_space::is_full_flush(unsigned char rights) +{ + return rights & L4_fpage::RX; +} + +PUBLIC static inline +unsigned char +Mem_space::xlate_flush_result(Mword attribs) +{ + unsigned char r = 0; + if (attribs & Page_referenced) + r |= L4_fpage::RX; + + if (attribs & Page_dirty) + r |= L4_fpage::W; + + return r; +} + +PUBLIC inline NEEDS["cpu.h"] +static bool +Mem_space::has_superpages() +{ + return Cpu::have_superpages(); +} + +//we flush tlb in htab implementation +PUBLIC static inline NEEDS["mem_unit.h"] +void +Mem_space::tlb_flush(bool = false) +{ + //Mem_unit::tlb_flush(); +} + + +PUBLIC inline +bool +Mem_space::set_attributes(Address virt, unsigned page_attribs) +{ +/* + Pdir::Iter i = _dir->walk(virt); + + if (!i.e->valid() || i.shift() != Config::PAGE_SHIFT) + return 0; + + i.e->del_attr(Page::MAX_ATTRIBS); + i.e->add_attr(page_attribs); + return true; +*/ + NOT_IMPL_PANIC; + (void)virt; (void)page_attribs; + return false; +} + +PROTECTED inline +void +Mem_space::destroy() +{} + + +/** + * Destructor. Deletes the address space and unregisters it from + * Space_index. + */ +PRIVATE +void +Mem_space::dir_shutdown() +{ + + // free ldt memory if it was allocated + //free_ldt_memory(); + + // free all page tables we have allocated for this address space + // except the ones in kernel space which are always shared + /* + _dir->alloc_cast() + ->destroy(0, Kmem::mem_user_max, Pdir::Depth - 1, + Mem_space_q_alloc(_quota, Kmem_alloc::allocator())); +*/ + NOT_IMPL_PANIC; +} + +IMPLEMENT inline +Mem_space * +Mem_space::current_mem_space(unsigned cpu) /// XXX: do not fix, deprecated, remove! +{ + return _current.cpu(cpu); +} + +/** Insert a page-table entry, or upgrade an existing entry with new + attributes. + @param phys Physical address (page-aligned). + @param virt Virtual address for which an entry should be created. + @param size Size of the page frame -- 4KB or 4MB. + @param page_attribs Attributes for the mapping (see + Mem_space::Page_attrib). + @return Insert_ok if a new mapping was created; + Insert_warn_exists if the mapping already exists; + Insert_warn_attrib_upgrade if the mapping already existed but + attributes could be upgraded; + Insert_err_nomem if the mapping could not be inserted because + the kernel is out of memory; + Insert_err_exists if the mapping could not be inserted because + another mapping occupies the virtual-address + range + @pre phys and virt need to be size-aligned according to the size argument. + */ +IMPLEMENT inline +Mem_space::Status +Mem_space::v_insert(Phys_addr phys, Vaddr virt, Vsize size, + unsigned page_attribs, bool /*upgrade_ignore_size*/) +{ + assert(size == Size(Config::PAGE_SIZE) + || size == Size(Config::SUPERPAGE_SIZE)); +/* + printf("v_insert: phys %08lx virt %08lx (%s) %p\n", phys, virt, + page_attribs & Page_writable?"rw":"ro", this);*/ + Pte_base e(phys.value()); + unsigned attribs = e.to_htab_entry(page_attribs); + + Status status = v_insert_cache(&e, Virt_addr(virt).value(), + Virt_size(size).value(), attribs); + return status; +} + +IMPLEMENT +bool +Mem_space::try_htab_fault(Address virt) +{ + bool super; + Evict evict; + Address pte_ptr, phys; + Dir_type *dir = _dir; + + if(virt >= Mem_layout::User_max) + dir = Kmem::kdir(); + + Pdir::Iter i = dir->walk(Addr(virt), Pdir::Super_level); + + if(!i.e->valid()) + return false; + + super = i.e->is_super_page(); + + i = dir->walk(Addr(virt)); + + if(!i.e->is_htab_entry() && !super) + return false; + + if(super && !i.e->valid()) + { + i = dir->walk(Addr(virt & Config::SUPERPAGE_MASK)); + phys = Pte_htab::pte_to_addr(i.e); + phys += (virt & Config::PAGE_MASK) - (phys & Config::PAGE_MASK); + } + else + phys = i.e->raw(); + + Status status; + // insert in htab + { + Lock_guard guard(&cpu_lock); + + status = v_insert_htab(phys, virt, &pte_ptr, &evict); + + // something had to be replaced update in cache-page table + if(EXPECT_FALSE(status == Insert_err_nomem)) + { + Pte_base e(evict.phys); + e.to_htab_entry(); + //printf("EVICTING: virt: %lx phys: %lx\n", evict.virt, e.raw()); + status = v_insert_cache(&e, evict.virt, Config::PAGE_SIZE, 0, evict.dir); + } + } + + + if(EXPECT_FALSE(status != Insert_ok)) + return false; + + // set pointer in cache + Pte_base e(pte_ptr); + e.to_htab_ptr(); + assert(e.addr()); + + status = v_insert_cache(&e, virt, Config::PAGE_SIZE, 0, dir); + + if(EXPECT_FALSE(status != Insert_ok)) + return false; + + return true; +} + +/** + * Simple page-table lookup. + * + * @param virt Virtual address. This address does not need to be page-aligned. + * @return Physical address corresponding to a. + */ +PUBLIC inline NEEDS ["paging.h"] +Address +Mem_space::virt_to_phys (Address virt) const +{ + return dir()->virt_to_phys(virt); +} + +PUBLIC inline +virtual Address +Mem_space::virt_to_phys_s0(void *a) const +{ + return dir()->virt_to_phys((Address)a); +} + +PUBLIC inline +Address +Mem_space::pmem_to_phys (Address virt) const +{ + return virt; +} + + + +/** Look up a page-table entry. + @param virt Virtual address for which we try the look up. + @param phys Meaningful only if we find something (and return true). + If not 0, we fill in the physical address of the found page + frame. + @param page_attribs Meaningful only if we find something (and return true). + If not 0, we fill in the page attributes for the found page + frame (see Mem_space::Page_attrib). + @param size If not 0, we fill in the size of the page-table slot. If an + entry was found (and we return true), this is the size + of the page frame. If no entry was found (and we + return false), this is the size of the free slot. In + either case, it is either 4KB or 4MB. + @return True if an entry was found, false otherwise. + */ +IMPLEMENT +bool +Mem_space::v_lookup(Vaddr virt, Phys_addr *phys = 0, Size *size = 0, + unsigned *page_attribs = 0) +{ + Pdir::Iter i = _dir->walk(virt, Pdir::Super_level); + + if(size) *size = Size(1UL << i.shift()); + + if(!i.e->valid()) + return false; + + unsigned shift = i.e->is_super_page() ? Config::SUPERPAGE_SHIFT + : Config::PAGE_SHIFT; + unsigned mask = (~0UL << shift); + + i = _dir->walk(virt & Addr(mask)); + + if(!i.e->valid()) + return false; + + if(size) *size = Size(1UL << i.shift()); + + if(phys || page_attribs) + { + Address addr = phys->value(); + Pte_htab::pte_lookup(i.e, &addr, page_attribs); + *phys = Phys_addr(addr); + } + if(page_attribs) + *page_attribs = to_kernel_fmt(*page_attribs, i.e->is_htab_entry()); + + return true; +} + +/** Delete page-table entries, or some of the entries' attributes. This + function works for one or multiple mappings (in contrast to v_insert!). + @param virt Virtual address of the memory region that should be changed. + @param size Size of the memory region that should be changed. + @param page_attribs If nonzero, delete only the given page attributes. + Otherwise, delete the whole entries. + @return Combined (bit-ORed) page attributes that were removed. In + case of errors, ~Page_all_attribs is additionally bit-ORed in. + */ +IMPLEMENT +unsigned long +Mem_space::v_delete(Vaddr virt, Vsize size, + unsigned long page_attribs = Page_all_attribs) +{ + unsigned ret = 0; + // delete pages from page tables + //printf("v_delete: %lx dir: %p\n", virt, _dir); + assert (size == Size(Config::PAGE_SIZE) + || size == Size(Config::SUPERPAGE_SIZE)); + + unsigned shift = (size == Virt_size(Config::SUPERPAGE_SIZE)) ? + Config::SUPERPAGE_SHIFT : Config::PAGE_SHIFT; + + Address offs = Virt_addr(virt).value() & (~0UL << shift); + Pdir::Iter i = _dir->walk(Addr(offs)); + Pt_entry *e = nonull_static_cast(i.e); + for(offs = 0; + offs < ((Virt_size(size).value() / Config::PAGE_SIZE) *sizeof(Mword)); + offs += sizeof(Mword)) + { + e = reinterpret_cast(e + offs); + + if(!e->valid()) + continue; + + //in htab ? + if(!e->is_htab_entry()) + { + ret = v_delete_htab(e->raw(), page_attribs); + + if(page_attribs & Page_user_accessible) + v_delete_cache(e, page_attribs); + } + else + ret = v_delete_cache(e, page_attribs); + } + + if(size != Virt_size(Config::SUPERPAGE_SIZE) && !(page_attribs & Page_user_accessible)) + return ret; + + //check for and delete super page + i = _dir->walk(virt, Pdir::Super_level); + i.e = 0; + + return ret; +} + +PUBLIC static inline +Page_number +Mem_space::canonize(Page_number v) +{ return v; } diff --git a/kernel/fiasco/src/kern/ppc32/mem_unit-ppc32.cpp b/kernel/fiasco/src/kern/ppc32/mem_unit-ppc32.cpp new file mode 100644 index 00000000..e4e622fd --- /dev/null +++ b/kernel/fiasco/src/kern/ppc32/mem_unit-ppc32.cpp @@ -0,0 +1,52 @@ +INTERFACE [ppc32]: + +#include "types.h" + +class Mem_unit +{ +}; + +//------------------------------------------------------------------------------ +IMPLEMENTATION[ppc32 && !mp]: + +/** Flush whole TLB + * + * Note: The 'tlbia' instruction is not implemented in G2 cores (causes a + * program exception). Therefore, we use 'tlbie' by iterating through EA + * bits [15-19] (see: G2 manual) + */ +PUBLIC static inline +void +Mem_unit::tlb_flush() +{ + +// for(Address ea_dummy = 0; ea_dummy < (1UL << 17) /*bit 14*/; +// ea_dummy += (1UL << 12) /* bit 19 */) +// tlb_flush(ea_dummy); +// +// asm volatile ("tlbsync"); +} + +/** Flush page at virtual address + */ +PUBLIC static inline +void +Mem_unit::tlb_flush(Address addr) +{ + asm volatile ("tlbie %0" : : "r"(addr)); +} + +PUBLIC static inline +void +Mem_unit::sync() +{ + asm volatile ("sync"); +} + +PUBLIC static inline +void +Mem_unit::isync() +{ + asm volatile ("isync"); +} + diff --git a/kernel/fiasco/src/kern/ppc32/msr.cpp b/kernel/fiasco/src/kern/ppc32/msr.cpp new file mode 100644 index 00000000..a2610a75 --- /dev/null +++ b/kernel/fiasco/src/kern/ppc32/msr.cpp @@ -0,0 +1,85 @@ +INTERFACE: + +#include "types.h" + +class Msr +{ +public: + enum Msr_bits { + Msr_ri = 1UL << 1, //(30)Recoverable exception + Msr_dr = 1UL << 4, //(27)Data-address translation + Msr_ir = 1UL << 5, //(26)Instruction-address translation + Msr_ce = 1UL << 4, //(24)Critical interrupt enable + Msr_ip = 1UL << 6, //(25)Interrupt prefix + Msr_fe1 = 1UL << 8, //(23)Floating-point exception mode 1 + Msr_be = 1UL << 9, //(22)branch trace enable + Msr_se = 1UL << 10, //(21)Signal-step trace enable + Msr_fe0 = 1UL << 11, //(20)Floating-point exception mode 0 + Msr_me = 1UL << 12, //(19)Machine check enable + Msr_fp = 1UL << 13, //(18)Floating-point available + Msr_pr = 1UL << 14, //(17)Privilege-level user + Msr_ee = 1UL << 15, //(16)External interrupt enable + Msr_pow = 1UL << 18, //(13)Power management enable + //Msr_fp is just enabled to not raise FPU load/store exceptions in user land + Msr_user = Msr_dr | Msr_ir | Msr_ee | Msr_me | Msr_pr | Msr_fp, + Msr_kernel = Msr_me | Msr_ri + }; + +private: + static void check_msr_sync(Mword bits); +}; + +//------------------------------------------------------------------------------ +IMPLEMENTATION: + + +IMPLEMENT inline +void +Msr::check_msr_sync(Mword bits) +{ + //for these context synchronization is mandatory + static Mword mask = ( Msr_pr | Msr_me | Msr_dr | Msr_fp | Msr_se | + Msr_be | Msr_ir | Msr_fe0 | Msr_fe1 ); + if(bits & mask) + asm volatile("isync \n" : : :); +} + +PUBLIC static inline +void +Msr::set_msr_bit(Mword bits) +{ + asm volatile ( " mfmsr %%r5 \n" + " or %%r5, %%r5, %[bits] \n" + " mtmsr %%r5 \n" + : + : [bits]"r" (bits) + : "r5", "memory" + ); + check_msr_sync(bits); +} + +PUBLIC static inline +void +Msr::clear_msr_bit(Mword bits) +{ + asm volatile ( " mfmsr %%r5 \n" + " andc %%r5, %%r5, %[bits] \n" + " mtmsr %%r5 \n" + : + : [bits]"r" (bits) + : "r5", "memory" + ); + check_msr_sync(bits); +} + +PUBLIC static inline +Mword +Msr::read_msr() +{ + Mword ret; + asm volatile ( " mfmsr %0 \n" + : "=r" (ret) + ); + return ret; +} + diff --git a/kernel/fiasco/src/kern/ppc32/paging-ppc32.cpp b/kernel/fiasco/src/kern/ppc32/paging-ppc32.cpp new file mode 100644 index 00000000..f9cacf04 --- /dev/null +++ b/kernel/fiasco/src/kern/ppc32/paging-ppc32.cpp @@ -0,0 +1,386 @@ +INTERFACE[ppc32]: + +#include "types.h" + +class PF {}; + +//------------------------------------------------------------------------------ +INTERFACE[ppc32]: + +#include +#include "types.h" +#include "ptab_base.h" +#include "kdb_ke.h" + +class Paging {}; + +class Pte_base +{ + public: + typedef Mword Raw; + enum + { + Super_level = 0, + Htab_entry = 0x00000400, ///< is raw entry of htab + Valid = 0x00000004, ///< Valid + Pse_bit = 0x00000800, ///< Indicates a super page in hierarch. pgt. + Writable = 0x00000002, ///< Writable + User = 0x00000001, ///< User accessible + Write_through = 0x00000050, ///< Write through + Cacheable = 0x00000000, ///< Cache is enabled + Cacheable_mask= 0xffffff87, + Noncacheable = 0x00000020, ///< Caching is off + Referenced = 0x00000100, ///< Page was referenced + Dirty = 0x00000080, ///< Page was modified + Pfn = 0xfffff000, ///< page frame number +// Cpu_global = 0x00000100, ///< pinned in the TLB +// L4_global = 0x00000200, ///< pinned in the TLB + }; + + Mword addr() const { return _raw & Pfn;} + bool is_super_page() const { return _raw & Pse_bit; } + protected: + Raw _raw; +}; + +class Pt_entry : public Pte_base +{ +public: + Mword leaf() const { return true; } + void set(Address p, bool intermed, bool /*present*/, unsigned long attrs = 0) + { + _raw = (p & Pfn) + | (intermed ? (Writable | User) : 0) | attrs; + _raw &= intermed ? (Mword)Cacheable_mask : ~0; + } +}; + +class Pd_entry : public Pte_base +{ +public: + Mword leaf() const { return false; } + void set(Address p, bool intermed, bool present, unsigned long attrs = 0) + { + _raw = (p & Pfn) | (present ? (Mword)Valid : 0) + | (intermed ? (Writable | User) : Pse_bit) | attrs; + _raw &= intermed ? (Mword)Cacheable_mask : ~0; + } +}; + +class Pte_htab { + public: + Pte_htab(Mword, Mword, Mword); + + union { + struct { + Mword valid : 1; // valid bit + Mword vsid :24; // address-space id + Mword h : 1; // hash-function bit + Mword api : 6; // abbreviated-page index + Mword rpn :20; // physical-page numer + Mword zero : 3; // reserved + Mword r : 1; // referenced bit + Mword c : 1; // changed bit + Mword wimg : 4; // cache controls + Mword zero1 : 1; // reserved + Mword pp : 2; // protection bits + } pte; + struct { + Unsigned32 raw0; + Unsigned32 raw1; + } raw; + }; + + bool inline valid() + { return this->pte.valid; } + + bool inline v_equal(Pte_htab *entry) + { return this->raw.raw0 == entry->raw.raw0; } + + bool inline p_equal(Pte_htab *entry) + { return this->raw.raw1 == entry->raw.raw1; } + + Address inline virt() + { return this->raw.raw0; } + + Address inline phys() + { return this->raw.raw1; } +}; + +namespace Page +{ + typedef Unsigned32 Attribs; + enum Attribs_enum + { + KERN_RW = 0x00000000, + USER_RO = 0x00000001, + USER_RW = 0x00000002, + Cache_mask = 0x00000078, + CACHEABLE = 0x00000000, + NONCACHEABLE = 0x00000040, + BUFFERED = 0x00000080, //XXX not sure + }; +}; + + +typedef Ptab::List< Ptab::Traits, + Ptab::Traits > Ptab_traits; + +typedef Ptab::Shift::List Ptab_traits_vpn; +typedef Ptab::Page_addr_wrap Ptab_va_vpn; + + +IMPLEMENTATION[ppc32]: + +#include "config.h" +#include "msr.h" +#include "lock_guard.h" +#include "cpu_lock.h" + + +/* this functions do nothing on PPC32 architecture */ +PUBLIC static inline +Address +Paging::canonize(Address addr) +{ + return addr; +} + +PUBLIC static inline +Address +Paging::decanonize(Address addr) +{ + return addr; +} + +//--------------------------------------------------------------------------- +IMPLEMENT inline +Mword PF::is_translation_error(Mword error) +{ + return !(error & 1 << 30) /* DSISR/SRR1 bit 1 */; +} + +IMPLEMENT inline NEEDS["msr.h"] +Mword PF::is_usermode_error(Mword error) +{ + return (error & Msr::Msr_pr); +} + +IMPLEMENT inline +Mword PF::is_read_error(Mword error) +{ + return !(error & (1 << 25)) /* DSISR bit 6*/; +} + +IMPLEMENT inline +Mword PF::addr_to_msgword0(Address pfa, Mword error) +{ + Mword a = pfa & ~3; + if(is_translation_error(error)) + a |= 1; + if(!is_read_error(error)) + a |= 2; + return a; +} + +//--------------------------------------------------------------------------- + +PUBLIC +Pte_base::Pte_base(Mword raw) : _raw(raw) {} + +PUBLIC +Pte_base::Pte_base() {} + +PUBLIC inline +Pte_base & +Pte_base::operator = (Pte_base const &other) +{ + _raw = other.raw(); + return *this; +} + +PUBLIC inline +Pte_base & +Pte_base::operator = (Mword raw) +{ + _raw = raw; + return *this; +} + +PUBLIC inline +Mword +Pte_base::raw() const +{ + return _raw; +} + +PUBLIC inline +void +Pte_base::add_attr(Mword attr) +{ + _raw |= attr; +} + +PUBLIC inline +void +Pte_base::del_attr(Mword attr) +{ + _raw &= ~attr; +} + +PUBLIC inline +void +Pte_base::clear() +{ _raw = 0; } + +PUBLIC inline +int +Pte_base::valid() const +{ + return + _raw & Valid || is_htab_entry(); +} + +PUBLIC inline +int +Pte_base::writable() const +{ + return _raw & Writable; +} + +PUBLIC inline +bool +Pte_base::is_htab_entry() const +{ + return ((_raw & Htab_entry) && !(_raw & Valid)); +} + +PUBLIC inline +unsigned +Pte_base::to_htab_entry(unsigned page_attribs = 0) +{ + _raw |= Htab_entry; + _raw &= ~Valid; + return page_attribs & ~Valid; +} + +PUBLIC inline +bool +Pte_base::is_htab_ptr() const +{ + return (_raw & Valid); +} + +PUBLIC inline +void +Pte_base::to_htab_ptr() +{ + _raw |= Valid; +} + +PUBLIC inline +Address +Pt_entry::pfn() const +{ + return _raw & Pfn; +} + +//------------------------------------------------------------------------------ +/* + * Hash Page-table entries + */ +IMPLEMENT inline NEEDS[Pte_htab::api] +Pte_htab::Pte_htab(Address pa, Address ea, Address vsid) +{ + this->raw.raw0 = 0; + this->pte.valid = 1; + this->pte.vsid = vsid; + this->pte.api = api(ea); + this->raw.raw1 = pa; +} + +PRIVATE static inline +Address +Pte_htab::api(Address ea) +{ + //bits 4-9 + return (ea >> 22) & 0x3f; +} + +PRIVATE inline +Address +Pte_htab::api_reverse() +{ + return this->pte.api << 22; +} + +PUBLIC inline NEEDS[Pte_htab::api_reverse, "config.h"] +Address +Pte_htab::pte_to_ea() +{ + Address pteg = (Address)this; + //if secondary hash + if(this->pte.h) + pteg = ~pteg; + + Address va = 0x3ff /*10bit*/ & (this->pte.vsid ^ (pteg >> 6)); + va <<= Config::PAGE_SHIFT; + va |= this->api_reverse(); + va |= (this->pte.vsid & 0xf) << 28; + return va; +} + + +PUBLIC static inline +Pte_htab * +Pte_htab::addr_to_pte(Address pte_addr) +{ + return reinterpret_cast(pte_addr & ~Pte_base::Valid); +} + +PUBLIC static inline +Address +Pte_htab::pte_to_addr(Pte_base *e) +{ + Address raw; + + if(e->is_htab_entry()) + raw = e->raw(); + else + { + Pte_htab *pte_phys = addr_to_pte(e->raw()); + raw = pte_phys->phys(); + } + + return raw; +} + +PUBLIC static +bool +Pte_htab::pte_lookup(Pte_base *e, Address *phys = 0, + unsigned *page_attribs = 0) +{ + Lock_guard guard(&cpu_lock); + + Address raw; + + if(e->is_htab_entry()) + { + raw = e->raw(); + } + else + { + Pte_htab *pte = addr_to_pte(e->raw()); + raw = pte->phys(); + + if(!pte->valid()) + return false; + } + + assert(raw); + + if(phys) *phys = raw & (~0UL << Config::PAGE_SHIFT); + if(page_attribs) *page_attribs = raw; + + return true; +} diff --git a/kernel/fiasco/src/kern/ppc32/phys_mem.S b/kernel/fiasco/src/kern/ppc32/phys_mem.S new file mode 100644 index 00000000..d66d03e2 --- /dev/null +++ b/kernel/fiasco/src/kern/ppc32/phys_mem.S @@ -0,0 +1,7 @@ +/* Section of reserved physical-page frames */ + +#include "tcboffset.h" + +.section .physmem, "aw", @progbits +/* 0x0000 - 0x3000 is system reserved */ +.space(VAL__KERNEL__START-0x3000) diff --git a/kernel/fiasco/src/kern/ppc32/space-ppc32.cpp b/kernel/fiasco/src/kern/ppc32/space-ppc32.cpp new file mode 100644 index 00000000..da7e5525 --- /dev/null +++ b/kernel/fiasco/src/kern/ppc32/space-ppc32.cpp @@ -0,0 +1,6 @@ +IMPLEMENTATION [ppc32]: // ------------------------------------------------- + +IMPLEMENT inline +void +Space::switchin_ldt() const +{} diff --git a/kernel/fiasco/src/kern/ppc32/startup-ppc32.cpp b/kernel/fiasco/src/kern/ppc32/startup-ppc32.cpp new file mode 100644 index 00000000..eab74c8c --- /dev/null +++ b/kernel/fiasco/src/kern/ppc32/startup-ppc32.cpp @@ -0,0 +1,58 @@ +IMPLEMENTATION [ppc32]: + +#include "banner.h" +#include "boot_info.h" +#include "config.h" +#include "cpu.h" +#include "kip_init.h" +#include "kernel_task.h" +#include "kmem_alloc.h" +#include "per_cpu_data.h" +#include "per_cpu_data_alloc.h" +#include "pic.h" +#include "static_init.h" +#include "timer.h" +#include "utcb_init.h" +#include + +IMPLEMENT FIASCO_INIT FIASCO_NOINLINE +void +Startup::stage1() +{ + Proc::cli(); + Boot_info::init(); + Cpu::early_init(); + Config::init(); +} + +IMPLEMENT FIASCO_INIT FIASCO_NOINLINE +void +Startup::stage2() +{ + Banner::init(); + puts("Hello from Startup::stage2"); + + Kip_init::init(); + //init htab + Mem_space::init(); + //init buddy allocator + Kmem_alloc::init(); + //init trace buffer + Mem_layout::init(); + + // Initialize cpu-local data management and run constructors for CPU 0 + Per_cpu_data::init_ctors(); + + // not really necessary for uni processor + Per_cpu_data_alloc::alloc(0); + Per_cpu_data::run_ctors(0); + Cpu::cpus.cpu(0).init(true); + + //idle task + Kernel_task::init(); + Pic::init(); + Timer::init(0); + Utcb_init::init(); + puts("Startup::stage2 finished"); +} + diff --git a/kernel/fiasco/src/kern/ppc32/sys_call_page-ppc32.cpp b/kernel/fiasco/src/kern/ppc32/sys_call_page-ppc32.cpp new file mode 100644 index 00000000..22126cb2 --- /dev/null +++ b/kernel/fiasco/src/kern/ppc32/sys_call_page-ppc32.cpp @@ -0,0 +1,47 @@ +INTERFACE: + +#include "types.h" + +//------------------------------------------------------------------------------ +IMPLEMENTATION: + +#include "mem_layout.h" +#include "kernel_task.h" +#include "mem_space.h" +#include "vmem_alloc.h" + +IMPLEMENT static +void +Sys_call_page::init() +{ +#if 0 + Mword *sys_calls = (Mword *)Mem_layout::Syscalls_phys; + for(unsigned i = 0; i < Config::PAGE_SIZE; i += sizeof(Mword)) + *(sys_calls++) = 0x44000002; //sc + + //insert in cache + Kernel_task::kernel_task()->mem_space()->v_insert( + Mem_space::Phys_addr(Mem_layout::Syscalls_phys), + Mem_space::Addr(Mem_layout::Syscalls), + Mem_space::Size(Config::PAGE_SIZE), + Mem_space::Page_cacheable | Mem_space::Page_user_accessible + ); + + //insert in htab + Kernel_task::kernel_task()->mem_space()->try_htab_fault(Mem_layout::Syscalls); +#endif + + + Mword *sys_calls = (Mword*)Mem_layout::Syscalls; + if (!Vmem_alloc::page_alloc(sys_calls, + Vmem_alloc::NO_ZERO_FILL, Vmem_alloc::User)) + panic("FIASCO: can't allocate system-call page.\n"); + for (unsigned i = 0; i < Config::PAGE_SIZE; i += sizeof(Mword)) + *(sys_calls++) = 0x44000002; //sc + + Kernel_task::kernel_task() + ->set_attributes(Mem_layout::Syscalls, + Mem_space::Page_cacheable | Mem_space::Page_user_accessible); + + //Mem_unit::flush_cache(); +} diff --git a/kernel/fiasco/src/kern/ppc32/task-ppc32.cpp b/kernel/fiasco/src/kern/ppc32/task-ppc32.cpp new file mode 100644 index 00000000..de3ea868 --- /dev/null +++ b/kernel/fiasco/src/kern/ppc32/task-ppc32.cpp @@ -0,0 +1,8 @@ +IMPLEMENTATION [ppc32]: + +PRIVATE inline +bool +Task::invoke_arch(L4_msg_tag &, Utcb *) +{ + return false; +} diff --git a/kernel/fiasco/src/kern/ppc32/tb_entry-ppc32.cpp b/kernel/fiasco/src/kern/ppc32/tb_entry-ppc32.cpp new file mode 100644 index 00000000..b5e2453a --- /dev/null +++ b/kernel/fiasco/src/kern/ppc32/tb_entry-ppc32.cpp @@ -0,0 +1,151 @@ +INTERFACE [ppc32]: + +EXTENSION class Tb_entry_base +{ +public: + enum + { + Tb_entry_size = 64, + }; +}; + +/** logged kernel event plus register content. */ +class Tb_entry_ke_reg : public Tb_entry +{ +private: + struct Payload + { + union { + char _msg[16]; ///< debug message + struct { + char _dsc[2]; + char const* _const_msg; + }; + }; + Mword _r3, _r4, _r5; ///< registers + }; +}; + +/** logged trap. */ +class Tb_entry_trap : public Tb_entry +{ +private: + struct Payload + { + Unsigned8 _trapno; + Unsigned16 _error; + Mword _cpsr, _sp; + }; +}; + +// -------------------------------------------------------------------- +IMPLEMENTATION [ppc32]: + +PUBLIC inline +void +Tb_entry::rdtsc() +{} + +PUBLIC inline +const char * +Tb_entry_ke_reg::msg() const +{ + return payload()->_dsc[0] == 0 && payload()->_dsc[1] == 1 + ? payload()->_const_msg : payload()->_msg; +} + +PUBLIC inline +Mword +Tb_entry_ke_reg::val1() const +{ return payload()->_r3; } + +PUBLIC inline +Mword +Tb_entry_ke_reg::val2() const +{ return payload()->_r4; } + +PUBLIC inline +Mword +Tb_entry_ke_reg::val3() const +{ return payload()->_r5; } + +PUBLIC inline +void +Tb_entry_ke_reg::set(Context const *ctx, Mword eip, Mword v1, Mword v2, Mword v3) +{ + set_global(Tbuf_ke_reg, ctx, eip); + payload()->_r3 = v1; + payload()->_r4 = v2; + payload()->_r5 = v3; +} + +PUBLIC inline +void +Tb_entry_ke_reg::set_const(Context const *ctx, Mword eip, const char * const msg, + Mword v1, Mword v2, Mword v3) +{ + set(ctx, eip, v1, v2, v3); + payload()->_dsc[0] = 0; payload()->_dsc[1] = 1; + payload()->_const_msg = msg; +} + +PUBLIC inline +void +Tb_entry_ke_reg::set_buf(unsigned i, char c) +{ + if (i < sizeof(payload()->_msg) - 1) + payload()->_msg[i] = c >= ' ' ? c : '.'; +} + +PUBLIC inline +void +Tb_entry_ke_reg::term_buf(unsigned i) +{payload()->_msg[i < sizeof(payload()->_msg)-1 ? i + : sizeof(payload()->_msg)-1] = '\0';} + +// ------------------ +PUBLIC inline +Unsigned16 +Tb_entry_trap::cs() const +{ return 0; } + +PUBLIC inline +Unsigned8 +Tb_entry_trap::trapno() const +{ return payload()->_trapno; } + +PUBLIC inline +Unsigned16 +Tb_entry_trap::error() const +{ return payload()->_error; } + +PUBLIC inline +Mword +Tb_entry_trap::sp() const +{ return payload()->_sp; } + +PUBLIC inline +Mword +Tb_entry_trap::cr2() const +{ return 0; } + +PUBLIC inline +Mword +Tb_entry_trap::eax() const +{ return 0; } + +PUBLIC inline NEEDS ["trap_state.h"] +void +Tb_entry_trap::set(Context const *ctx, Mword pc, Trap_state *) +{ + set_global(Tbuf_trap, ctx, pc); + // More... +} + +PUBLIC inline NEEDS ["trap_state.h"] +void +Tb_entry_trap::set(Context const *ctx, Mword pc, Mword ) +{ + set_global(Tbuf_trap, ctx, pc); +} + diff --git a/kernel/fiasco/src/kern/ppc32/thread-jdb.cpp b/kernel/fiasco/src/kern/ppc32/thread-jdb.cpp new file mode 100644 index 00000000..bcd8ee26 --- /dev/null +++ b/kernel/fiasco/src/kern/ppc32/thread-jdb.cpp @@ -0,0 +1,117 @@ +INTERFACE [ppc32 && debug]: + +#include "trap_state.h" +#include "util.h" + +EXTENSION class Thread +{ +public: + typedef void (*Dbg_extension_entry)(Thread *t, Entry_frame *r); + static Dbg_extension_entry dbg_extension[64]; +private: + static int call_nested_trap_handler(Trap_state *ts) asm ("call_nested_trap_handler"); + static Trap_state::Handler nested_trap_handler FIASCO_FASTCALL; +}; + +//------------------------------------------------------------------------------ +IMPLEMENTATION [ppc32 && debug]: + +Thread::Dbg_extension_entry Thread::dbg_extension[64]; +Trap_state::Handler Thread::nested_trap_handler FIASCO_FASTCALL; + +extern "C" void sys_kdb_ke() +{ + cpu_lock.lock(); + Thread *t = current_thread(); + + //arriving from outx function + unsigned *x = (unsigned *)t->regs()->ip(); + if(t->regs()->r[29] == (Mword)-0x24 && t->regs()->r[2] & (1 << 31)) //ip && r3 + { + NOT_IMPL_PANIC; + unsigned func = (unsigned)t->regs()->r[1] & 0xffff; //r4 + if(Thread::dbg_extension[func]) + { + Thread::dbg_extension[func](t, t->regs()); + return; + } + } + + char str[32] = "USER ENTRY"; + //arriving from enter_kdebug + if (t->regs()->r[29] == (Mword)-0x24 && t->regs()->r[2] & (1 << 30)) //ip && r3 + { + //t->mem_space()->copy_from_user(str, (char *)(x + 1), sizeof(str)); + strncpy(str, (char *)(x + 1), sizeof(str)); + str[sizeof(str)-1] = 0; + } + + kdb_ke(str); +} + +IMPLEMENT +int +Thread::call_nested_trap_handler(Trap_state *ts) +{ + unsigned phys_cpu = Proc::cpu_id(); + unsigned log_cpu = Cpu::p2l(phys_cpu); + if (log_cpu == ~0U) + { + printf("Trap on unknown CPU phys_id=%x\n", phys_cpu); + log_cpu = 0; + } + + unsigned long &ntr = nested_trap_recover.cpu(log_cpu); + + void *stack = 0; + + if (!ntr) + stack = dbg_stack.cpu(log_cpu).stack_top; + + Mword dummy1, tmp; + { + register Mword _ts asm("3") = (Mword)ts; + register Mword _lcpu asm("r4") = log_cpu; + + asm volatile( + " mr %[origstack], %%r1 \n" + " lwz %[tmp], 0(%[ntr]) \n" + " cmpwi %[tmp], 0 \n" + " bne 1f \n" + " mr %%r1, %[stack] \n" + "1: \n" + " mtsprg1 %%r1 \n" + " addi %[tmp], %[tmp], 1 \n" + " stw %[tmp], 0(%[ntr]) \n" + " subi %%r1, %%r1, 16 \n" //extent stack frame + " stw %[origstack], 16(%%r1) \n" + " stw %[ntr], 12(%%r1) \n" + " lis %[tmp], 2f@ha \n" + " addi %[tmp], %[tmp], 2f@l \n" + " mtlr %[tmp] \n" + " mtctr %[handler] \n" + " bctr \n" + "2: \n" + " lwz %[ntr], 12(%%r1) \n" + " lwz %%r1, 16(%%r1) \n" + " lwz %[tmp], 0(%[ntr]) \n" + " subi %[tmp], %[tmp], 1 \n" + " stw %[tmp], 0(%[ntr]) \n" + : [origstack] "=&r" (dummy1), [tmp] "=&r" (tmp), + "=r" (_ts), "=r" (_lcpu) + : [ntr] "r" (&ntr), [stack] "r" (stack), + [handler] "r" (*nested_trap_handler), + "2" (_ts), "3" (_lcpu) + : "memory"); + + return _ts; + } +} + +IMPLEMENTATION [ppc32 && !debug]: + +extern "C" void sys_kdb_ke() +{ +} +extern "C" void enter_jdb() +{} diff --git a/kernel/fiasco/src/kern/ppc32/thread-ppc32.cpp b/kernel/fiasco/src/kern/ppc32/thread-ppc32.cpp new file mode 100644 index 00000000..23f3d450 --- /dev/null +++ b/kernel/fiasco/src/kern/ppc32/thread-ppc32.cpp @@ -0,0 +1,377 @@ +INTERFACE [ppc32]: + +class Trap_state; + +IMPLEMENTATION [ppc32]: + +#include +#include +#include + +#include "globals.h" +#include "kmem.h" +#include "mem_space.h" +#include "thread_state.h" +#include "trap_state.h" +#include "types.h" + +enum { + FSR_STATUS_MASK = 0x0d, + FSR_TRANSL = 0x05, + FSR_DOMAIN = 0x09, + FSR_PERMISSION = 0x0d, +}; + +DEFINE_PER_CPU Per_cpu Thread::dbg_stack; + +PRIVATE static +void +Thread::print_page_fault_error(Mword e) +{ + char const *const excpts[] = + { "reset","undef. insn", "swi", "pref. abort", "data abort", + "XXX", "XXX", "XXX" }; + + unsigned ex = (e >> 20) & 0x07; + + printf("(%lx) %s, %s(%c)",e & 0xff, excpts[ex], + (e & 0x00010000)?"user":"kernel", + (e & 0x00020000)?'r':'w'); +} + +// +// Public services +// +PRIVATE static +void +Thread::dump_bats() +{ + Mword batu, batl; + asm volatile (" mfdbatl %0, %2 \n" + " mfdbatu %1, %2 \n" + : "=r"(batl), "=r"(batu) : "i"(0)); + printf("DBAT0 U:%08lx L:%08lx\n", batu, batl); + asm volatile (" mfdbatl %0, %2 \n" + " mfdbatu %1, %2 \n" + : "=r"(batl), "=r"(batu) : "i"(1)); + printf("DBAT1 U:%08lx L:%08lx\n", batu, batl); + asm volatile (" mfdbatl %0, %2 \n" + " mfdbatu %1, %2 \n" + : "=r"(batl), "=r"(batu) : "i"(2)); + printf("DBAT2 U:%08lx L:%08lx\n", batu, batl); + asm volatile (" mfdbatl %0, %2 \n" + " mfdbatu %1, %2 \n" + : "=r"(batl), "=r"(batu) : "i"(3)); + printf("DBAT3 U:%08lx L:%08lx\n", batu, batl); + + asm volatile (" mfibatl %0, %2 \n" + " mfibatu %1, %2 \n" + : "=r"(batl), "=r"(batu) : "i"(0)); + printf("IBAT0 U:%08lx L:%08lx\n", batu, batl); + asm volatile (" mfibatl %0, %2 \n" + " mfibatu %1, %2 \n" + : "=r"(batl), "=r"(batu) : "i"(1)); + printf("IBAT1 U:%08lx L:%08lx\n", batu, batl); + asm volatile (" mfibatl %0, %2 \n" + " mfibatu %1, %2 \n" + : "=r"(batl), "=r"(batu) : "i"(2)); + printf("IBAT2 U:%08lx L:%08lx\n", batu, batl); + asm volatile (" mfibatl %0, %2 \n" + " mfibatu %1, %2 \n" + : "=r"(batl), "=r"(batu) : "i"(3)); + printf("IBAT3 U:%08lx L:%08lx\n", batu, batl); +} + +PUBLIC template inline +void FIASCO_NORETURN +Thread::fast_return_to_user(Mword ip, Mword sp, T arg) +{ + (void)ip; (void)sp; (void)arg; + //assert_kdb(check that exiting privs are user privs); + // XXX: UNIMPLEMENTED + panic("__builtin_trap()"); +} + +IMPLEMENT +void +Thread::user_invoke() +{ + user_invoke_generic(); + assert(current()->state() & Thread_ready); + + Return_frame *r = nonull_static_cast(current()->regs()); + Kip *kip = (EXPECT_FALSE(current_thread()->mem_space()->is_sigma0())) ? + Kip::k() : 0; + + /* DEBUGGING */ + Mword vsid, utcb; + + asm volatile(" mfsr %0, 0 \n" + " mr %1, %%r2\n" + : "=r"(vsid), "=r"(utcb)); + printf("\n[%lx]leaving kernel ip %lx sp %lx vsid %lx\n", + current_thread()->dbg_id(), r->ip(), r->sp(), vsid); + printf("kernel_sp %p kip %p utcb %08lx\n", current_thread()->regs() + 1, kip, utcb); + + asm volatile ( " mtsprg1 %[kernel_sp] \n" //correct kernel stack + //pointer + " mtsrr0 %[ip] \n" + " mtsrr1 %[state] \n" + " mr %%r1, %[sp] \n" + " mr %%r3, %[kip] \n" + " rfi \n" + : + : [ip]"r" (r->ip()), + [sp]"r" (r->sp()), + [state]"r" (Msr::Msr_user), + [kip]"r" (kip), + [kernel_sp]"r" (current_thread()->regs() + 1) + : "r3" + ); + + // never returns +} + +IMPLEMENT inline NEEDS["space.h", , "types.h" ,"config.h"] +bool Thread::handle_sigma0_page_fault(Address pfa) +{ + bool ret = (mem_space()->v_insert(Mem_space::Phys_addr(pfa & Config::PAGE_MASK), + Mem_space::Addr(pfa & Config::PAGE_MASK), + Mem_space::Size(Config::PAGE_SIZE), + Mem_space::Page_writable | + Mem_space::Page_user_accessible | + Mem_space::Page_cacheable + ) + != Mem_space::Insert_err_nomem); + + return ret; +} + +extern "C" { + void except_notimpl(void) + { + Mword etype, dar, dsisr, vsid, msr, ksp; + asm volatile(" mflr %0 \n" + " mfdar %1 \n" + " mfdsisr %2 \n" + " mfsr %3, 0 \n" + " mfmsr %4 \n" + " mfsprg1 %5 \n" + : "=r"(etype), "=r"(dar), "=r"(dsisr), "=r"(vsid), "=r"(msr), "=r"(ksp) : : "memory"); + printf("\n\n[dbg_id: %lx] Exception: %lx\n", current_thread()->dbg_id(), etype & ~0xff); + Entry_frame *e = current()->regs(); + + e->Return_frame::dump(); + printf("MSR %08lx DAR %08lx DSISR %08lx VSID: %08lx KSP: %08lx\n\n", msr, dar, dsisr,vsid, ksp); + e->Syscall_frame::dump(); + e->Return_frame::dump_scratch(); + panic("STOPPED"); + } + +}; + +extern "C" { + + /** + * The low-level page fault handler called from entry.S. We're invoked with + * interrupts turned off. Apart from turning on interrupts + * all casesi, just forwards + * the call to Thread::handle_page_fault(). + * @param pfa page-fault virtual address + * @param error_code CPU error code + * @return true if page fault could be resolved, false otherwise + */ + Mword pagefault_entry(const Mword pfa, const Mword error_code, + const Mword pc, Return_frame *ret_frame) + { + //printf("Page fault at %08lx (%s)\n", pfa, PF::is_read_error(error_code)?"ro":"rw" ); + if(EXPECT_TRUE(PF::is_usermode_error(error_code))) + { + if (current_thread()->vcpu_pagefault(pfa, error_code, pc)) + return 1; + + current_thread()->state_del(Thread_cancel); + Proc::sti(); + } + + //lookup in page cache + if (Mem_space::current_mem_space(current_cpu())->try_htab_fault((Address)(pfa & Config::PAGE_MASK))) + return 1; + + int ret = current_thread()->handle_page_fault(pfa, error_code, pc, ret_frame); + + return ret; + } + + void slowtrap_entry(Trap_state * /*ts*/) + { + NOT_IMPL_PANIC; + } + +}; + +IMPLEMENT inline +bool +Thread::pagein_tcb_request(Return_frame * /*regs*/) +{ + NOT_IMPL_PANIC; + return false; +} + +extern "C" +{ + void timer_handler() + { + Return_frame *rf = nonull_static_cast(current()->regs()); + //disable power savings mode, when we come from privileged mode + if(EXPECT_FALSE(rf->user_mode())) + rf->srr1 = Proc::wake(rf->srr1); + + Timer::update_system_clock(current_cpu()); + current_thread()->handle_timer_interrupt(); + } +} +//--------------------------------------------------------------------------- +IMPLEMENTATION [ppc32]: + +/** Constructor. + @param id user-visible thread ID of the sender + @param init_prio initial priority + @param mcp thread's maximum controlled priority + @post state() != Thread_invalid + */ +IMPLEMENT +Thread::Thread() + : Sender (0), // select optimized version of constructor + _pager(Thread_ptr::Invalid), + _exc_handler(Thread_ptr::Invalid), + _del_observer(0) +{ + + assert(state() == Thread_invalid); + + inc_ref(); + _space.space(Kernel_task::kernel_task()); + + if (Config::Stack_depth) + std::memset((char*)this + sizeof(Thread), '5', + Thread::Size - sizeof(Thread) - 64); + + // set a magic value -- we use it later to verify the stack hasn't + // been overrun + _magic = magic; + _recover_jmpbuf = 0; + _timeout = 0; + + *reinterpret_cast (--_kernel_sp) = user_invoke; + + // clear out user regs that can be returned from the thread_ex_regs + // system call to prevent covert channel + Entry_frame *r = regs(); + r->sp(0); + r->ip(0); + + state_add(Thread_dead | Thread_suspended); + // ok, we're ready to go! +} + +IMPLEMENT inline +Mword +Thread::user_sp() const +{ return regs()->sp(); } + +IMPLEMENT inline +void +Thread::user_sp(Mword sp) +{ return regs()->sp(sp); } + +IMPLEMENT inline NEEDS[Thread::exception_triggered] +Mword +Thread::user_ip() const +{ return exception_triggered() ? _exc_cont.ip() : regs()->ip(); } + +IMPLEMENT inline +Mword +Thread::user_flags() const +{ return 0; } + +IMPLEMENT inline NEEDS[Thread::exception_triggered] +void +Thread::user_ip(Mword ip) +{ + if (exception_triggered()) + _exc_cont.ip(ip); + else + { + Entry_frame *r = regs(); + r->ip(ip); + } +} + +PUBLIC inline NEEDS ["trap_state.h"] +int +Thread::send_exception_arch(Trap_state * /*ts*/) +{ + NOT_IMPL_PANIC; + return 1; // We did it +} + +PROTECTED inline +void +Thread::vcpu_resume_user_arch() +{} + + +PRIVATE static inline +void +Thread::save_fpu_state_to_utcb(Trap_state *, Utcb *) +{ +} + +PROTECTED inline +int +Thread::do_trigger_exception(Entry_frame * /*r*/, void * /*ret_handler*/) +{ + NOT_IMPL_PANIC; + return 0; +} + +PRIVATE static inline +bool FIASCO_WARN_RESULT +Thread::copy_utcb_to_ts(L4_msg_tag const &/*tag*/, Thread * /*snd*/, + Thread * /*rcv*/, unsigned char /*rights*/) +{ + NOT_IMPL_PANIC; + return true; +} + +PRIVATE static inline +bool FIASCO_WARN_RESULT +Thread::copy_ts_to_utcb(L4_msg_tag const &, Thread * /*snd*/, Thread * /*rcv*/, + unsigned char /*rights*/) +{ + NOT_IMPL_PANIC; + return true; +} + +PROTECTED inline +L4_msg_tag +Thread::invoke_arch(L4_msg_tag /*tag*/, Utcb * /*utcb*/) +{ + return commit_result(-L4_err::ENosys); +} + +PROTECTED inline +int +Thread::sys_control_arch(Utcb *) +{ + return 0; +} + +//----------------------------------------------------------------------------- +IMPLEMENTATION [!mp]: + +PUBLIC static inline +bool +Thread::check_for_ipi(unsigned) +{ return false; } diff --git a/kernel/fiasco/src/kern/ppc32/timer-decr-ppc32.cpp b/kernel/fiasco/src/kern/ppc32/timer-decr-ppc32.cpp new file mode 100644 index 00000000..f3904ad0 --- /dev/null +++ b/kernel/fiasco/src/kern/ppc32/timer-decr-ppc32.cpp @@ -0,0 +1,86 @@ +/** + * PowerPC timer using internal decrementer + */ + +IMPLEMENTATION [ppc32]: + +#include "cpu.h" +#include "config.h" +#include "globals.h" +#include "kip.h" +#include "decrementer.h" +#include "warn.h" + +#include + +IMPLEMENT inline NEEDS ["decrementer.h", "kip.h", "config.h", ] +void +Timer::init(unsigned) +{ + printf("Using PowerPC decrementer for scheduling\n"); + + //1000 Hz + Decrementer::d()->init(Kip::k()->frequency_bus / + (4*Config::Scheduler_granularity)); + +} + +PUBLIC static inline +unsigned +Timer::irq() +{ return 0; } + +PUBLIC static inline +unsigned +Timer::irq_mode() +{ return 0; } + +PUBLIC static inline +void +Timer::acknowledge() +{ } + +//IMPLEMENT inline NEEDS ["decrementer.h"] +//void +//Timer::enable() +//{ +// Decrementer::d()->enable(); +//} + +//IMPLEMENT inline NEEDS ["decrementer.h"] +//void +//Timer::disable() +//{ +// Decrementer::d()->disable(); +//} + +IMPLEMENT inline NEEDS ["kip.h"] +void +Timer::init_system_clock() +{ + Kip::k()->clock = 0; +} + +IMPLEMENT inline NEEDS ["globals.h", "kip.h"] +Unsigned64 +Timer::system_clock() +{ + return Kip::k()->clock; +} + +IMPLEMENT inline NEEDS ["decrementer.h", "config.h", "kip.h"] +void +Timer::update_system_clock(unsigned cpu) +{ + if (cpu == 0) + { + Decrementer::d()->set(); + Kip::k()->clock += Config::Scheduler_granularity; + } +} + +IMPLEMENT inline +void +Timer::update_timer(Unsigned64) +{ +} diff --git a/kernel/fiasco/src/kern/ppc32/timer_tick-ppc32.cpp b/kernel/fiasco/src/kern/ppc32/timer_tick-ppc32.cpp new file mode 100644 index 00000000..7d2550a7 --- /dev/null +++ b/kernel/fiasco/src/kern/ppc32/timer_tick-ppc32.cpp @@ -0,0 +1,7 @@ +IMPLEMENTATION [ppc32]: + +#include "irq_mgr.h" + +IMPLEMENT bool +Timer_tick::allocate_irq(Irq_base *irq, unsigned irqnum) +{ return Irq_mgr::mgr->alloc(irq, irqnum); } diff --git a/kernel/fiasco/src/kern/ppc32/trap_state.cpp b/kernel/fiasco/src/kern/ppc32/trap_state.cpp new file mode 100644 index 00000000..3861b96a --- /dev/null +++ b/kernel/fiasco/src/kern/ppc32/trap_state.cpp @@ -0,0 +1,89 @@ + +INTERFACE: + +#include "l4_types.h" +#include "entry_frame.h" + +class Trap_state_regs +{ +// static int (*base_handler)(Trap_state *) asm ("BASE_TRAP_HANDLER"); +public: + Mword pf_address; + Mword error_code; +}; + + +class Trap_state : public Trap_state_regs, public Syscall_frame, + public Return_frame +{ +public: + typedef int (*Handler)(Trap_state*, unsigned cpu); +}; + + +IMPLEMENTATION: + +#include + +PUBLIC inline +void +Trap_state::sanitize_user_state() +{ + // implement me +} + +PUBLIC inline +unsigned long +Trap_state::ip() const +{ return srr0; } + +PUBLIC inline +unsigned long +Trap_state::trapno() const +{ return error_code; } + +PUBLIC inline +Mword +Trap_state::error() const +{ return 0; } + +PUBLIC inline +void +Trap_state::set_ipc_upcall() +{ + error_code = 0x10000000; // see Msr +} + +PUBLIC inline +void +Trap_state::set_pagefault(Mword pfa, Mword error) +{ + pf_address = pfa; + error_code = error; +} + +PUBLIC inline +bool +Trap_state::is_debug_exception() const +{ return false; } + +PUBLIC +void +Trap_state::dump() +{ + char const *excpts[] = + {"reset","machine check"}; + + printf("EXCEPTION: pfa=%08lx, error=%08lx\n", + //excpts[((error_code & ~0xff) >> 8) - 1] + pf_address, error_code); + + printf("SP: %08lx LR: %08lx SRR0: %08lx SRR1 %08lx\n\n" + "R[0] %08lx\n" + "R[3]: %08lx %08lx %08lx %08lx %08lx\n" + "R[8]: %08lx %08lx %08lx %08lx %08lx\n", + usp, ulr, srr0, srr1, + r[0], r[1], r[2], r[3], r[4], r[5], r[6], r[7], + r[8], r11, r12); +} + diff --git a/kernel/fiasco/src/kern/ppc32/utcb_init-ppc32.cpp b/kernel/fiasco/src/kern/ppc32/utcb_init-ppc32.cpp new file mode 100644 index 00000000..ac4e9123 --- /dev/null +++ b/kernel/fiasco/src/kern/ppc32/utcb_init-ppc32.cpp @@ -0,0 +1,20 @@ +IMPLEMENTATION [ppc32]: + +#include "mem_layout.h" +#include "config.h" +#include + + +IMPLEMENT +void +Utcb_init::init() +{ + //Utcb_ptr_page is physical address + memset((void*)Mem_layout::Utcb_ptr_page, 0, Config::PAGE_SIZE); +} + +PUBLIC static inline +void +Utcb_init::init_ap(Cpu const &) +{} + diff --git a/kernel/fiasco/src/kern/ppc32/utcb_support-ppc32.cpp b/kernel/fiasco/src/kern/ppc32/utcb_support-ppc32.cpp new file mode 100644 index 00000000..70b524ea --- /dev/null +++ b/kernel/fiasco/src/kern/ppc32/utcb_support-ppc32.cpp @@ -0,0 +1,18 @@ +//------------------------------------------------------------------------- +IMPLEMENTATION [ppc32]: + +IMPLEMENT inline +User::Ptr +Utcb_support::current() +{ + Utcb *u; + asm volatile ("mr %0, %%r2" : "=r" (u)); + return User::Ptr(u); +} + +IMPLEMENT inline +void +Utcb_support::current(User::Ptr const &utcb) +{ + asm volatile ("mr %%r2, %0" : : "r" (utcb.get()) : "memory"); +} diff --git a/kernel/fiasco/src/kern/ppc32/util.cpp b/kernel/fiasco/src/kern/ppc32/util.cpp new file mode 100644 index 00000000..98fd3856 --- /dev/null +++ b/kernel/fiasco/src/kern/ppc32/util.cpp @@ -0,0 +1,18 @@ +INTERFACE: +#include "types.h" + +class Util +{}; + +IMPLEMENTATION: + +PUBLIC static inline +template < typename T > +T +Util::log2(T value) +{ + unsigned long c = 0; + while(value >>= 1) + c++; + return T(c); +} diff --git a/kernel/fiasco/src/kern/ppc32/vmem_alloc-ppc32.cpp b/kernel/fiasco/src/kern/ppc32/vmem_alloc-ppc32.cpp new file mode 100644 index 00000000..925d603e --- /dev/null +++ b/kernel/fiasco/src/kern/ppc32/vmem_alloc-ppc32.cpp @@ -0,0 +1,29 @@ +//--------------------------------------------------------------------------- +IMPLEMENTATION [ppc32]: + +#include "config.h" +#include "panic.h" +#include "warn.h" +#include "mem.h" + +IMPLEMENT +void Vmem_alloc::init() +{ + NOT_IMPL_PANIC; +} + +IMPLEMENT +void *Vmem_alloc::page_alloc(void * address, Zero_fill zf, unsigned /*mode*/) +{ + if(zf == ZERO_FILL) + Mem::memset_mwords((unsigned long *)address, 0, Config::PAGE_SIZE >> 2); + return address; +} + +IMPLEMENT +void *Vmem_alloc::page_unmap(void * /*page*/) +{ + NOT_IMPL_PANIC; + return NULL; +} + diff --git a/kernel/fiasco/src/kern/ppc32/warn-ppc32.cpp b/kernel/fiasco/src/kern/ppc32/warn-ppc32.cpp new file mode 100644 index 00000000..f1aa18f3 --- /dev/null +++ b/kernel/fiasco/src/kern/ppc32/warn-ppc32.cpp @@ -0,0 +1,5 @@ +INTERFACE [ppc32]: +#include "panic.h" + +#define NOT_IMPL WARN "%s not implemented", __PRETTY_FUNCTION__ +#define NOT_IMPL_PANIC panic("%s not implemented\n", __PRETTY_FUNCTION__); diff --git a/kernel/fiasco/src/kern/prio_list.cpp b/kernel/fiasco/src/kern/prio_list.cpp new file mode 100644 index 00000000..8f6e2836 --- /dev/null +++ b/kernel/fiasco/src/kern/prio_list.cpp @@ -0,0 +1,200 @@ +INTERFACE: + +#include +#include +#include +#include "member_offs.h" +#include "spin_lock.h" +#include "types.h" + +/** + * Priority sorted list with insert complexity O(n) n = number of available + * priorities (256 in Fiasco). + */ + + +class Prio_list_elem; + +/** + * Priority sorted list. + * + * The list is organized in a way that the highest priority member can be + * found with O(1). Ever dequeue operation is also O(1). + * + * There is a forward iteratable list with at most one element per priority. + * Elements with the same priority are handled in a double-linked circular + * list for each priority. This double-linked list implements FIFO policy for + * finding the next element. + */ +class Prio_list : private cxx::H_list +{ + MEMBER_OFFSET(); + friend class Jdb_sender_list; +public: + typedef cxx::H_list P_list; + typedef cxx::D_list_cyclic S_list; + + using P_list::front; + using P_list::empty; + + Prio_list_elem *first() const { return front(); } +}; + +class Iteratable_prio_list : public Prio_list +{ +public: + Spin_lock<> *lock() { return &_lock; } + +private: + Prio_list_elem *_cursor; + Spin_lock<> _lock; +}; + +typedef Iteratable_prio_list Locked_prio_list; + + +/** + * Single element of a priority sorted list. + */ +class Prio_list_elem : public cxx::H_list_item, public cxx::D_list_item +{ + MEMBER_OFFSET(); +private: + friend class Prio_list; + friend class Jdb_sender_list; + typedef cxx::D_list_cyclic S_list; + + /** + * Priority, the higher the better. + */ + unsigned short _prio; +}; + + + +IMPLEMENTATION: + +/** + * Setup pointers for enqueue. + */ +PRIVATE inline +void +Prio_list_elem::init(unsigned short p) +{ + _prio = p; +} + +/** + * Get the priority. + */ +PUBLIC inline +unsigned short +Prio_list_elem::prio() const +{ return _prio; } + +PUBLIC inline +Prio_list_elem * +Prio_list::next(Prio_list_elem *e) const +{ + if (P_list::in_list(*++S_list::iter(e))) + return *++P_list::iter(e); + return *++S_list::iter(e); +} + +/** + * Insert a new element into the priority list. + * @param e the element to insert + * @param prio the priority for the element + */ +PUBLIC inline NEEDS[Prio_list_elem::init] +void +Prio_list::insert(Prio_list_elem *e, unsigned short prio) +{ + assert (e); + e->init(prio); + + Iterator pos = begin(); + + while (pos != end() && pos->prio() > prio) + ++pos; + + if (pos != end() && pos->prio() == prio) + S_list::insert_before(e, S_list::iter(*pos)); + else + { + S_list::self_insert(e); + insert_before(e, pos); + } +} + +/** + * Is the element actually enqueued? + * @return true if the element is actaully enqueued in a list. + */ +PUBLIC inline +bool Prio_list_elem::in_list() const { return S_list::in_list(this); } + +/** + * Dequeue a given element from the list. + * @param e the element to dequeue + */ +PUBLIC inline +void +Prio_list::dequeue(Prio_list_elem *e, Prio_list_elem **next = 0) +{ + if (P_list::in_list(e)) + { + assert (S_list::in_list(e)); + // yes we are the head of our priority + if (S_list::has_sibling(e)) + { + P_list::replace(e, *++S_list::iter(e)); + if (next) *next = *++S_list::iter(e); + } + else + { + if (next) *next = *++P_list::iter(e); + P_list::remove(e); + } + } + else + { + if (next) + { + if (P_list::in_list(*++S_list::iter(e))) // actually we are the last on our priority + *next = *++P_list::iter(e); + else + *next = *++S_list::iter(e); + } + } + S_list::remove(e); +} + +PUBLIC inline +Iteratable_prio_list::Iteratable_prio_list() : _cursor(0), _lock(Spin_lock<>::Unlocked) {} + +/** + * Dequeue a given element from the list. + * @param e the element to dequeue + */ +PUBLIC inline NEEDS[Prio_list::dequeue] +void +Iteratable_prio_list::dequeue(Prio_list_elem *e) +{ + Prio_list_elem **c = 0; + if (EXPECT_FALSE(_cursor != 0) && EXPECT_FALSE(_cursor == e)) + c = &_cursor; + + Prio_list::dequeue(e, c); +} + +PUBLIC inline +void +Iteratable_prio_list::cursor(Prio_list_elem *e) +{ _cursor = e; } + +PUBLIC inline +Prio_list_elem * +Iteratable_prio_list::cursor() const +{ return _cursor; } + diff --git a/kernel/fiasco/src/kern/ptab_base.cpp b/kernel/fiasco/src/kern/ptab_base.cpp new file mode 100644 index 00000000..2053ef1f --- /dev/null +++ b/kernel/fiasco/src/kern/ptab_base.cpp @@ -0,0 +1,597 @@ +INTERFACE: + +#include "mem_layout.h" + +namespace Ptab +{ + + struct Null_alloc + { + static void *alloc(unsigned long) { return 0; } + static void free(void *) {} + static bool valid() { return false; } + }; + + template< typename _Head, typename _Tail > + class List + { + public: + typedef _Head Head; + typedef _Tail Tail; + }; + + + template< typename _T, unsigned _Level > + class Level + { + public: + typedef _T Traits; + + static unsigned shift(unsigned) + { return Traits::Shift; } + + static Address addr(unsigned, Mword entry) + { + struct E : public Traits::Entry + { E(Mword raw) { Traits::Entry::_raw = raw; } }; + return E(entry).addr(); + } + + static unsigned size(unsigned) + { return Traits::Size; } + + static unsigned length(unsigned) + { return 1UL << Traits::Size; } + + static Address index(unsigned /*level*/, Address addr) + { return (addr >> Traits::Shift) & ((1UL << Traits::Size)-1); } + + }; + + template< typename _Head, typename _Tail, unsigned _Level > + class Level< List<_Head, _Tail>, _Level > + { + public: + typedef typename Level<_Tail, _Level - 1>::Traits Traits; + + static unsigned shift(unsigned level) + { + if (!level) + return _Head::Shift; + else + return Level<_Tail, _Level - 1>::shift(level - 1); + } + + static Address addr(unsigned level, Mword entry) + { + struct E : public Traits::Entry + { E(Mword raw) { Traits::Entry::_raw = raw; } }; + if (!level) + return E(entry).addr(); + else + return Level<_Tail, _Level - 1>::addr(level - 1, entry); + } + + static unsigned size(unsigned level) + { + if (!level) + return _Head::Size; + else + return Level<_Tail, _Level - 1>::size(level - 1); + } + + static unsigned length(unsigned level) + { + if (!level) + return 1UL << _Head::Size; + else + return Level<_Tail, _Level - 1>::length(level - 1); + } + + static Address index(unsigned level, Address addr) + { + if (!level) + return (addr >> Traits::Shift) & ((1UL << Traits::Size)-1); + else + return Level<_Tail, _Level - 1>::index(level - 1, addr); + } + + }; + + template< typename _Head, typename _Tail> + class Level< List<_Head, _Tail>, 0> : public Level<_Head, 0> + { + }; + + template< typename _Traits > + class Entry_vec + { + public: + typedef typename _Traits::Entry Entry; + enum + { + Length = 1UL << _Traits::Size, + Size = _Traits::Size, + Mask = _Traits::Mask, + Shift = _Traits::Shift, + }; + + + Entry _e[Length]; + + static unsigned idx(Address virt) + { + if (Mask) + return (virt >> Shift) & ~(~0UL << Size); + else + return (virt >> Shift); + } + + Entry &operator [] (unsigned idx) { return _e[idx]; } + Entry const &operator [] (unsigned idx) const { return _e[idx]; } + + void clear() { for (unsigned i=0; i < Length; ++i) _e[i].clear(); } + }; + + + template< typename _Last, typename Iter > + class Walk + { + public: + enum { Depth = 0 }; + typedef _Last Level; + typedef typename _Last::Entry Entry; + typedef _Last Traits; + + private: + typedef Walk<_Last, Iter> This; + typedef Entry_vec Vec; + Vec _e; + + public: + void clear() { _e.clear(); } + + template< typename _Alloc > + Iter walk(Address virt, unsigned, _Alloc const &) + { return Iter(&_e[Vec::idx(virt)], Level::Shift); } + + void unmap(Address &start, unsigned long &size, unsigned) + { + unsigned idx = Vec::idx(start); + unsigned cnt = size >> Traits::Shift; + if (cnt + idx > Vec::Length) + cnt = Vec::Length - idx; + unsigned const e = idx + cnt; + + for (; idx != e; ++idx) + _e[idx].clear(); + + start += (unsigned long)cnt << Traits::Shift; + size -= (unsigned long)cnt << Traits::Shift; + } + + template< typename _Alloc > + void map(Address &phys, Address &virt, unsigned long &size, + unsigned long attr, unsigned, _Alloc const &) + { + unsigned idx = Vec::idx(virt); + unsigned cnt = size >> Traits::Shift; + if (cnt + idx > Vec::Length) + cnt = Vec::Length - idx; + unsigned const e = idx + cnt; + + for (; idx != e; ++idx, phys += (1UL << Traits::Entry::Page_shift)) + _e[idx].set(phys, false, true, attr); + virt += (unsigned long)cnt << Traits::Shift; + size -= (unsigned long)cnt << Traits::Shift; + } + + template< typename _Alloc > + void destroy(Address, Address, unsigned, _Alloc const &) + {} + + template< typename _Alloc > + bool sync(Address &l_addr, This const &_r, Address &r_addr, + Address &size, unsigned, _Alloc const &) + { + unsigned count = size >> Traits::Shift; + unsigned const l = Vec::idx(l_addr); + unsigned const r = Vec::idx(r_addr); + unsigned const m = l > r ? l : r; + if (m + count >= Vec::Length) + count = Vec::Length - m; + + Entry *le = &_e[l]; + Entry const *re = &_r._e[r]; + + bool need_flush = false; + + for (unsigned n = count; n > 0; --n) + { + if (le[n-1].valid()) + need_flush = true; + + // This loop seems unnecessary, but remote_update is also used for + // updating the long IPC window. + // Now consider following scenario with super pages: + // Sender A makes long IPC to receiver B. + // A setups the IPC window by reading the pagedir slot from B in an + // temporary register. Now the sender is preempted by C. Then C unmaps + // the corresponding super page from B. C switch to A back, using + // switch_to, which clears the IPC window pde slots from A. BUT then A + // write the content of the temporary register, which contain the now + // invalid pde slot, in his own page directory and starts the long IPC. + // Because no pagefault will happen, A will write to now invalid memory. + // So we compare after storing the pde slot, if the copy is still + // valid. And this solution is much faster than grabbing the cpu lock, + // when updating the ipc window.h + for (;;) + { + typename Traits::Raw const volatile *rr + = reinterpret_cast(re + n - 1); + le[n - 1] = *(Entry *)rr; + if (EXPECT_TRUE(le[n - 1].raw() == *rr)) + break; + } + } + + l_addr += (unsigned long)count << Traits::Shift; + r_addr += (unsigned long)count << Traits::Shift; + size -= (unsigned long)count << Traits::Shift; + return need_flush; + } + }; + + + + template< typename _Head, typename _Tail, typename Iter > + class Walk , Iter > + { + public: + typedef Walk<_Tail, Iter> Next; + typedef typename Next::Level Level; + typedef typename _Head::Entry Entry; + typedef _Head Traits; + + enum { Depth = Next::Depth + 1 }; + + private: + typedef Walk<_Head, Iter> This; + typedef Walk< List< _Head, _Tail >, Iter> This2; + typedef Entry_vec<_Head> Vec; + Vec _e; + + template< typename _Alloc > + Next *alloc_next(Entry *e, _Alloc const &a) + { + Next *n = (Next*)a.alloc(sizeof(Next)); + if (EXPECT_FALSE(!n)) + return 0; + + n->clear(); + e->set(Mem_layout::pmem_to_phys(n), true, true); + + return n; + } + + public: + void clear() { _e.clear(); } + + template< typename _Alloc > + Iter walk(Address virt, unsigned level, _Alloc const &alloc) + { + Entry *e = &_e[Vec::idx(virt)]; + if (!level) + return Iter(e, _Head::Shift); + else if (!e->valid()) + { + Next *n; + if (alloc.valid() && (n = alloc_next(e, alloc))) + return n->walk(virt, level - 1, alloc); + + return Iter(e, _Head::Shift); + } + + + if (_Head::May_be_leaf && e->leaf()) + return Iter(e, _Head::Shift); + else + { + Next *n = (Next*)Mem_layout::phys_to_pmem(e->addr()); + return n->walk(virt, level - 1, alloc); + } + } + + void unmap(Address &start, unsigned long &size, unsigned level) + { + if (!level) + { + reinterpret_cast(this)->unmap(start, size, 0); + return; + } + + while (size) + { + Entry *e = &_e[Vec::idx(start)]; + + if (!e->valid() || e->leaf()) + continue; + + Next *n = (Next*)Mem_layout::phys_to_pmem(e->addr()); + n->unmap(start, size, level - 1); + } + } + + template< typename _Alloc > + void map(Address &phys, Address &virt, unsigned long &size, + unsigned long attr, unsigned level, _Alloc const &alloc) + { + if (!level) + { + reinterpret_cast(this)->map(phys, virt, size, attr, 0, alloc); + return; + } + + while (size) + { + Entry *e = &_e[Vec::idx(virt)]; + Next *n; + if (!e->valid()) + { + if (alloc.valid() && (n = alloc_next(e, alloc))) + n->map(phys, virt, size, attr, level - 1, alloc); + + continue; + } + + if (_Head::May_be_leaf && e->leaf()) + continue; + + n = (Next*)Mem_layout::phys_to_pmem(e->addr()); + n->map(phys, virt, size, attr, level - 1, alloc); + } + } + + template< typename _Alloc > + void destroy(Address start, Address end, unsigned level, _Alloc const &alloc) + { + if (!alloc.valid()) + return; + + unsigned idx_start = Vec::idx(start); + unsigned idx_end = Vec::idx(end + (1UL << Traits::Shift) - 1); + unsigned idx = idx_start; + + for (; idx < idx_end; ++idx) + { + Entry *e = &_e[idx]; + if (!e->valid() || (_Head::May_be_leaf && e->leaf())) + continue; + + Next *n = (Next*)Mem_layout::phys_to_pmem(e->addr()); + if (level) + n->destroy(idx > idx_start ? 0 : start, + idx + 1 < idx_end ? 1UL << Next::Traits::Shift : end, + level - 1, alloc); + + alloc.free(n, sizeof(Next)); + } + } + + template< typename _Alloc > + bool sync(Address &l_a, This2 const &_r, Address &r_a, + Address &size, unsigned level, _Alloc const &alloc) + { + if (!level) + return reinterpret_cast(this) + ->sync(l_a, reinterpret_cast(_r), r_a, size, 0, alloc); + + unsigned count = size >> Traits::Shift; + { + unsigned const lx = Vec::idx(l_a); + unsigned const rx = Vec::idx(r_a); + unsigned const mx = lx > rx ? lx : rx; + if (mx + count >= Vec::Length) + count = Vec::Length - mx; + } + + bool need_flush = false; + + for (unsigned i = count; size && i > 0; --i) //while (size) + { + Entry *l = &_e[Vec::idx(l_a)]; + Entry const *r = &_r._e[Vec::idx(r_a)]; + Next *n = 0; + if (!r->valid() + || (!l->valid() && (!alloc.valid() + || !(n = alloc_next(l,alloc))))) + { + l_a += 1UL << Traits::Shift; + r_a += 1UL << Traits::Shift; + if (size > 1UL << Traits::Shift) + { + size -= 1UL << Traits::Shift; + continue; + } + break; + } + + if (!n) + n = (Next*)Mem_layout::phys_to_pmem(l->addr()); + + Next *rn = (Next*)Mem_layout::phys_to_pmem(r->addr()); + + if (n->sync(l_a, *rn, r_a, size, level - 1, alloc)) + need_flush = true; + } + + return need_flush; + } + + }; + + template< typename _E, unsigned _Va_shift > + class Iter + { + public: + Iter(_E *e, unsigned char shift) : e(e), s(shift + _Va_shift) {} + + template< typename _I2 > + Iter(_I2 const &o) : e(o.e), s(o.s) {} + + unsigned char shift() const { return s; } + unsigned long addr() const { return e->addr() & (~0UL << s); } + + _E *e; + unsigned char s; + }; + + template + < + typename _Entry, + unsigned _Shift, + unsigned _Size, + bool _May_be_leaf, + bool _Mask = true + > + class Traits + { + public: + typedef _Entry Entry; + typedef typename Entry::Raw Raw; + + enum + { + May_be_leaf = _May_be_leaf, + Shift = _Shift, + Size = _Size, + Mask = _Mask + }; + }; + + template< typename _T, unsigned _Shift > + class Shift + { + public: + typedef _T Orig_list; + typedef Ptab::Traits + < typename _T::Entry, + _T::Shift - _Shift, + _T::Size, + _T::May_be_leaf, + _T::Mask + > List; + }; + + template< typename _Head, typename _Tail, unsigned _Shift > + class Shift< List<_Head, _Tail>, _Shift > + { + public: + typedef Ptab::List<_Head, _Tail> Orig_list; + typedef Ptab::List + < + typename Shift<_Head, _Shift>::List, + typename Shift<_Tail, _Shift>::List + > List; + }; + + class Address_wrap + { + public: + enum { Shift = 0 }; + typedef Address Value_type; + static Address val(Address a) { return a; } + }; + + template< typename N, int SHIFT > + class Page_addr_wrap + { + public: + enum { Shift = SHIFT }; + typedef N Value_type; + static Address val(N a) { return a.value(); } + }; + + template + < + typename _Base_entry, + typename _Traits, + typename _Addr = Address_wrap + > + class Base + { + public: + typedef typename _Addr::Value_type Va; + typedef _Traits Traits; + typedef _Base_entry Entry; + typedef Ptab::Iter Iter; + typedef typename _Traits::Head L0; + + private: + typedef Base<_Base_entry, _Traits> This; + typedef Ptab::Walk<_Traits, Iter> Walk; + + public: + enum { Depth = Walk::Depth }; + + template< typename _Alloc > + Iter walk(Va virt, unsigned level, _Alloc const &alloc) + { + return _base.walk(_Addr::val(virt), level, alloc); + } + + Iter walk(Va virt, unsigned level = 100) const + { + return const_cast(_base).walk(_Addr::val(virt), level, Null_alloc()); + } + + + template< typename _Alloc > + bool sync(Va l_addr, Base< _Base_entry, _Traits, _Addr> const *_r, + Va r_addr, Va size, unsigned level = 100, + _Alloc const &alloc = _Alloc()) + { + Address la = _Addr::val(l_addr); + Address ra = _Addr::val(r_addr); + Address sz = _Addr::val(size); + return _base.sync(la, _r->_base, + ra, sz, level, alloc); + } + + void clear() { _base.clear(); } + + void unmap(Va virt, Va size, unsigned level) + { + Address va = _Addr::val(virt); + unsigned long sz = _Addr::val(size); + _base.unmap(va, sz, level); + } + + template< typename _Alloc > + void map(Address phys, Va virt, Va size, unsigned long attr, + unsigned level, _Alloc const &alloc = _Alloc()) + { + Address va = _Addr::val(virt); + unsigned long sz = _Addr::val(size); + _base.map(phys, va, sz, attr, level, alloc); + } + + template< typename _Alloc > + void destroy(Va start, Va end, unsigned level, _Alloc const &alloc = _Alloc()) + { _base.destroy(_Addr::val(start), _Addr::val(end), level, alloc); } + +#if 0 + template< typename _New_alloc > + Base<_Base_entry, _Traits, _New_alloc, _Addr> *alloc_cast() + { return reinterpret_cast *>(this); } + + template< typename _New_alloc > + Base<_Base_entry, _Traits, _New_alloc, _Addr> const *alloc_cast() const + { return reinterpret_cast const *>(this); } +#endif + + private: + Walk _base; + }; + +}; diff --git a/kernel/fiasco/src/kern/push_console.cpp b/kernel/fiasco/src/kern/push_console.cpp new file mode 100644 index 00000000..eb0ce22d --- /dev/null +++ b/kernel/fiasco/src/kern/push_console.cpp @@ -0,0 +1,74 @@ +INTERFACE: + +#include "console.h" + +class Push_console : public Console +{ +private: + char _buffer[256]; + int _in; + int _out; +}; + +IMPLEMENTATION: + +#include "keycodes.h" + +PUBLIC +int +Push_console::getchar(bool /*blocking*/) +{ + if (_out != _in) + { + int c = _buffer[_out++]; + if (_out >= (int)sizeof(_buffer)) + _out = 0; + + return c == '_' ? KEY_RETURN : c; + } + + return -1; // no keystroke available +} + +PUBLIC +int +Push_console::char_avail() const +{ + return _in != _out; // unknown +} + +PUBLIC +int +Push_console::write(char const * /*str*/, size_t len) +{ + return len; +} + +PUBLIC +void +Push_console::push(char c) +{ + int _ni = _in + 1; + if (_ni >= (int)sizeof(_buffer)) + _ni = 0; + + if (_ni == _out) // buffer full + return; + + _buffer[_in] = c; + _in = _ni; +} + +PUBLIC inline +void +Push_console::flush() +{ + _in = _out = 0; +} + +PUBLIC inline +Mword +Push_console::get_attributes() const +{ + return PUSH | IN; +} diff --git a/kernel/fiasco/src/kern/queue.cpp b/kernel/fiasco/src/kern/queue.cpp new file mode 100644 index 00000000..f7b20d64 --- /dev/null +++ b/kernel/fiasco/src/kern/queue.cpp @@ -0,0 +1,136 @@ +INTERFACE: + +#include "spin_lock.h" +#include "queue_item.h" +#include "kdb_ke.h" +#include + +class Queue +{ +public: + typedef Spin_lock_coloc Inner_lock; + +private: + class Lock_n_ptr : public Inner_lock + { + public: + Queue_item *item() const + { return reinterpret_cast(get_unused() & ~5UL); } + + void set_item(Queue_item *i) + { + assert_kdb (!(Mword(i) & 5)); + set_unused((Mword)i | (get_unused() & 5)); + } + + bool blocked() const + { return get_unused() & 1; } + + void block() + { return set_unused(get_unused() | 1); } + + void unblock() + { set_unused(get_unused() & ~1); } + + bool invalid() const + { return get_unused() & 4; } + + void invalidate() + { set_unused(get_unused() | 4); } + }; + + struct Queue_head_policy + { + typedef Lock_n_ptr Head_type; + static Queue_item *head(Head_type const &h) { return h.item(); } + static void set_head(Head_type &h, Queue_item *v) { h.set_item(v); } + }; + + typedef cxx::Sd_list List; + + List _m; +}; + + +//-------------------------------------------------------------------------- +IMPLEMENTATION: + +#include "kdb_ke.h" +#include "std_macros.h" + +PUBLIC inline +Queue::Queue() +{ _m.head().init(); } + +PUBLIC inline +Queue::Inner_lock * +Queue::q_lock() +{ return &_m.head(); } + +PUBLIC inline NEEDS["kdb_ke.h"] +void +Queue::enqueue(Queue_item *i) +{ + // Queue i at the end of the list + assert_kdb (_m.head().test()); + i->_q = this; + _m.push_back(i); +} + +PUBLIC inline NEEDS["kdb_ke.h", "std_macros.h"] +bool +Queue::dequeue(Queue_item *i, Queue_item::Status reason) +{ + assert_kdb (_m.head().test()); + assert_kdb (i->queued()); + + if (EXPECT_FALSE(i->_q != this)) + return false; + + _m.remove(i); + i->_q = (Queue*)reason; + return true; +} + +PUBLIC inline +Queue_item * +Queue::first() const +{ return _m.front(); } + +PUBLIC inline +bool +Queue::blocked() const +{ return _m.head().blocked(); } + +PUBLIC inline NEEDS["kdb_ke.h"] +void +Queue::block() +{ + assert_kdb (_m.head().test()); + _m.head().block(); +} + +PUBLIC inline NEEDS["kdb_ke.h"] +void +Queue::unblock() +{ + assert_kdb (_m.head().test()); + _m.head().unblock(); +} + +PUBLIC inline NEEDS["kdb_ke.h"] +bool +Queue::invalid() const +{ + assert_kdb (_m.head().test()); + return _m.head().invalid(); +} + +PUBLIC inline NEEDS["kdb_ke.h"] +void +Queue::invalidate() +{ + assert_kdb (_m.head().test()); + _m.head().invalidate(); +} + diff --git a/kernel/fiasco/src/kern/queue_item.cpp b/kernel/fiasco/src/kern/queue_item.cpp new file mode 100644 index 00000000..579040fe --- /dev/null +++ b/kernel/fiasco/src/kern/queue_item.cpp @@ -0,0 +1,44 @@ +INTERFACE: + +#include + +class Queue; + +class Queue_item : public cxx::D_list_item +{ + friend class Queue; +public: + enum Status { Ok, Retry, Invalid }; + +private: + Queue *_q; +} __attribute__((aligned(16))); + + +//-------------------------------------------------------------------------- +IMPLEMENTATION: + +#include "kdb_ke.h" +#include "std_macros.h" + +PUBLIC inline +bool +Queue_item::queued() const +{ return cxx::D_list_cyclic::in_list(this); } + +PUBLIC inline NEEDS["kdb_ke.h"] +Queue * +Queue_item::queue() const +{ + assert_kdb (queued()); + return _q; +} + +PUBLIC inline NEEDS["kdb_ke.h"] +Queue_item::Status +Queue_item::status() const +{ + assert_kdb (!queued()); + return Status((unsigned long)_q); +} + diff --git a/kernel/fiasco/src/kern/ram_quota.cpp b/kernel/fiasco/src/kern/ram_quota.cpp new file mode 100644 index 00000000..60c52d0a --- /dev/null +++ b/kernel/fiasco/src/kern/ram_quota.cpp @@ -0,0 +1,83 @@ +INTERFACE: + +#include + +class Ram_quota +{ +public: + static Ram_quota *root; + virtual ~Ram_quota() = 0; + +private: + Ram_quota *_parent; + unsigned long _current; + unsigned long _max; +}; + + +IMPLEMENTATION: + +#include "cpu_lock.h" +#include "lock_guard.h" + +Ram_quota *Ram_quota::root; + +IMPLEMENT inline Ram_quota::~Ram_quota() {} + +PUBLIC inline NEEDS[] +void * +Ram_quota::operator new (size_t, void *b) throw() +{ return b; } + +PUBLIC +Ram_quota::Ram_quota() + : _parent(0), _current(0), _max (~0UL) +{ + root = this; +} + +PUBLIC +Ram_quota::Ram_quota(Ram_quota *p, unsigned long max) + : _parent(p), _current(0), _max (max) +{} + +PUBLIC +unsigned long +Ram_quota::current() const +{ return _current; } + +PUBLIC +bool +Ram_quota::alloc(signed long bytes) +{ + Lock_guard guard(&cpu_lock); + if (unlimited() || _current + bytes <= _max) + { + _current += bytes; + return true; + } + + return false; +} + +PUBLIC inline NEEDS[Ram_quota::alloc] +void +Ram_quota::free(signed long bytes) +{ alloc(-bytes); } + + +PUBLIC inline +Ram_quota* +Ram_quota::parent() const +{ return _parent; } + +PUBLIC inline +unsigned long +Ram_quota::limit() const +{ return _max; } + +PUBLIC inline +bool +Ram_quota::unlimited() const +{ return _max == ~0UL; } + diff --git a/kernel/fiasco/src/kern/rcupdate.cpp b/kernel/fiasco/src/kern/rcupdate.cpp new file mode 100644 index 00000000..1560d104 --- /dev/null +++ b/kernel/fiasco/src/kern/rcupdate.cpp @@ -0,0 +1,545 @@ +INTERFACE: + +#include "cpu_mask.h" +#include "per_cpu_data.h" +#include "spin_lock.h" +#include + +class Rcu_glbl; +class Rcu_data; + +/** + * \brief Encapsulation of RCU batch number. + */ +class Rcu_batch +{ + friend class Jdb_rcupdate; +public: + /// create uninitialized batch. + Rcu_batch() {} + /// create a btach initialized with \a b. + Rcu_batch(long b) : _b(b) {} + + /// less than comparison. + bool operator < (Rcu_batch const &o) const { return (_b - o._b) < 0; } + /// greater than comparison. + bool operator > (Rcu_batch const &o) const { return (_b - o._b) > 0; } + /// greater than comparison. + bool operator >= (Rcu_batch const &o) const { return (_b - o._b) >= 0; } + /// equelity check. + bool operator == (Rcu_batch const &o) const { return _b == o._b; } + /// inequality test. + bool operator != (Rcu_batch const &o) const { return _b != o._b; } + /// increment batch. + Rcu_batch &operator ++ () { ++_b; return *this; } + /// increase batch with \a r. + Rcu_batch operator + (long r) { return Rcu_batch(_b + r); } + + +private: + long _b; +}; + +/** + * \brief Item that can bequeued for the next grace period. + * + * An RCU item is basically a pointer to a callback which is called + * after one grace period. + */ +class Rcu_item : public cxx::S_list_item +{ + friend class Rcu_data; + friend class Rcu; + friend class Jdb_rcupdate; + +private: + bool (*_call_back)(Rcu_item *); +}; + + +/** + * \brief List of Rcu_items. + * + * RCU lists are used a lot of times in the RCU implementation and are + * implemented as single linked lists with FIFO semantics. + * + * \note Concurrent access to the list is not synchronized. + */ +class Rcu_list : public cxx::S_list_tail +{ +private: + typedef cxx::S_list_tail Base; +public: + Rcu_list() {} + Rcu_list(Rcu_list &&o) : Base(static_cast(o)) {} + Rcu_list &operator = (Rcu_list &&o) + { + Base::operator = (static_cast(o)); + return *this; + } + +private: + friend class Jdb_rcupdate; +}; + +/** + * \brief CPU local data structure for RCU. + */ +class Rcu_data +{ + friend class Jdb_rcupdate; +public: + + Rcu_batch _q_batch; ///< batch nr. for grace period + bool _q_passed; ///< quiescent state passed? + bool _pending; ///< wait for quiescent state + bool _idle; + + Rcu_batch _batch; + Rcu_list _n; + long _len; + Rcu_list _c; + Rcu_list _d; + unsigned _cpu; +}; + + +/** + * \brief Global RCU data structure. + */ +class Rcu_glbl +{ + friend class Rcu_data; + friend class Rcu; + friend class Jdb_rcupdate; + +private: + Rcu_batch _current; ///< current batch + Rcu_batch _completed; ///< last completed batch + bool _next_pending; ///< next batch already pending? + Spin_lock<> _lock; + Cpu_mask _cpus; + + Cpu_mask _active_cpus; + +}; + +/** + * \brief encapsulation of RCU implementation. + * + * This calss aggregates per CPU data structures as well as the global + * data structure for RCU and provides a common RCU interface. + */ +class Rcu +{ + friend class Rcu_data; + friend class Jdb_rcupdate; + +public: + /// The lock to prevent a quiescent state. + typedef Cpu_lock Lock; + enum { Period = 3000 /* 10ms */ }; + static Rcu_glbl *rcu() { return &_rcu; } +private: + static Rcu_glbl _rcu; + static Per_cpu _rcu_data; +}; + +// ------------------------------------------------------------------------ +INTERFACE [debug]: + +EXTENSION class Rcu +{ +public: + struct Log_rcu + { + unsigned cpu; + Rcu_item *item; + void *cb; + unsigned char event; + } __attribute__((packed)); + + enum Rcu_events + { + Rcu_call = 0, + Rcu_process = 1, + }; +}; + + +// -------------------------------------------------------------------------- +IMPLEMENTATION [debug]: + +#include "logdefs.h" + +unsigned log_fmt(Tb_entry *, int max, char *buf) asm ("__fmt_rcu"); + + +IMPLEMENT +unsigned log_fmt(Tb_entry *e, int max, char *buf) +{ + Rcu::Log_rcu *p = e->payload(); + char const *events[] = { "call", "process"}; + return snprintf(buf, max, "rcu-%s (cpu=%u) item=%p", events[p->event], p->cpu, p->item); +} + + +//-------------------------------------------------------------------------- +IMPLEMENTATION: + +#include "cpu.h" +#include "cpu_lock.h" +#include "globals.h" +#include "kdb_ke.h" +#include "lock_guard.h" +#include "mem.h" +#include "static_init.h" +#include "timeout.h" +#include "logdefs.h" + +// XXX: includes for debugging +// #include "logdefs.h" + + +class Rcu_timeout : public Timeout +{ +}; + +/** + * Timeout expiration callback function + * @return true if reschedule is necessary, false otherwise + */ +PRIVATE +bool +Rcu_timeout::expired() +{ return Rcu::process_callbacks(); } + + +Rcu_glbl Rcu::_rcu INIT_PRIORITY(EARLY_INIT_PRIO); +DEFINE_PER_CPU Per_cpu Rcu::_rcu_data(true); +DEFINE_PER_CPU static Per_cpu _rcu_timeout; + +PUBLIC +Rcu_glbl::Rcu_glbl() +: _current(-300), + _completed(-300) +{} + +PUBLIC +Rcu_data::Rcu_data(unsigned cpu) +: _idle(true), + _cpu(cpu) +{} + + +/** + * \brief Enqueue Rcu_item into the list (at the tail). + * \prarm i the RCU item to enqueue. + */ +PUBLIC inline void Rcu_list::enqueue(Rcu_item *i){ push_back(i); } + +/** + * \pre must run under cpu lock + */ +PUBLIC inline +void +Rcu_data::enqueue(Rcu_item *i) +{ + _n.enqueue(i); + ++_len; +} + +PRIVATE inline NOEXPORT NEEDS["cpu_lock.h", "lock_guard.h"] +bool +Rcu_data::do_batch() +{ + int count = 0; + bool need_resched = false; + for (Rcu_list::Const_iterator l = _d.begin(); l != _d.end();) + { + Rcu_item *i = *l; + ++l; + + need_resched |= i->_call_back(i); + ++count; + } + + // XXX: I do not know why this and the former stuff is w/o cpu lock + // but the couting needs it ? + _d.clear(); + + // XXX: we use clear, we seemingly worked through the whole list + //_d.head(l); + + { + Lock_guard guard(&cpu_lock); + _len -= count; + } +#if 0 + if (_d.full()) + { + Timeout *t = &_rcu_timeout.cpu(_cpu); + t->set(t->get_timeout(0) + Rcu::Period, _cpu); + } +#endif + return need_resched; +} + +PRIVATE inline NOEXPORT +void +Rcu_glbl::start_batch() +{ + if (_next_pending && _completed == _current) + { + _next_pending = 0; + Mem::mp_wmb(); + ++_current; + Mem::mp_mb(); + _cpus = _active_cpus; + } +} + +PUBLIC static inline +void +Rcu::enter_idle(unsigned cpu) +{ + Rcu_data *rdp = &_rcu_data.cpu(cpu); + if (EXPECT_TRUE(!rdp->_idle)) + { + rdp->_idle = true; + Lock_guard_lock)> guard(&rcu()->_lock); + rcu()->_active_cpus.clear(cpu); + } +} + +PUBLIC static inline +void +Rcu::leave_idle(unsigned cpu) +{ + Rcu_data *rdp = &_rcu_data.cpu(cpu); + if (EXPECT_FALSE(rdp->_idle)) + { + rdp->_idle = false; + Lock_guard_lock)> guard(&rcu()->_lock); + rcu()->_active_cpus.set(cpu); + rdp->_q_batch = Rcu::rcu()->_current; + } +} + + +PRIVATE inline NOEXPORT +void +Rcu_glbl::cpu_quiet(unsigned cpu) +{ + _cpus.clear(cpu); + if (_cpus.empty()) + { + _completed = _current; + start_batch(); + } +} + +PRIVATE +void +Rcu_data::check_quiescent_state(Rcu_glbl *rgp) +{ + if (_q_batch != rgp->_current) + { + // start new grace period + _pending = 1; + _q_passed = 0; + _q_batch = rgp->_current; + return; + } + + // Is the grace period already completed for this cpu? + // use _pending, not bitmap to avoid cache trashing + if (!_pending) + return; + + // Was there a quiescent state since the beginning of the grace period? + if (!_q_passed) + return; + + _pending = 0; + + Lock_guard_lock)> guard(&rgp->_lock); + + if (EXPECT_TRUE(_q_batch == rgp->_current)) + rgp->cpu_quiet(_cpu); +} + + +PUBLIC static //inline NEEDS["cpu_lock.h", "globals.h", "lock_guard.h", "logdefs.h"] +void +Rcu::call(Rcu_item *i, bool (*cb)(Rcu_item *)) +{ + i->_call_back = cb; + LOG_TRACE("Rcu call", "rcu", ::current(), __fmt_rcu, + Log_rcu *p = tbe->payload(); + p->cpu = current_cpu(); + p->event = Rcu_call; + p->item = i; + p->cb = (void*)cb); + + Lock_guard guard(&cpu_lock); + + Rcu_data *rdp = &_rcu_data.current(); + rdp->enqueue(i); +} + +PRIVATE +void +Rcu_data::move_batch(Rcu_list &l) +{ + Lock_guard guard(&cpu_lock); + _n.append(l); +} + + +PUBLIC +Rcu_data::~Rcu_data() +{ + if (current_cpu() == _cpu) + return; + + Rcu_data *current_rdp = &Rcu::_rcu_data.current(); + Rcu_glbl *rgp = Rcu::rcu(); + + { + Lock_guard_lock)> guard(&rgp->_lock); + if (rgp->_current != rgp->_completed) + rgp->cpu_quiet(_cpu); + } + + current_rdp->move_batch(_c); + current_rdp->move_batch(_n); + current_rdp->move_batch(_d); +} + +PUBLIC +bool FIASCO_WARN_RESULT +Rcu_data::process_callbacks(Rcu_glbl *rgp) +{ + LOG_TRACE("Rcu callbacks", "rcu", ::current(), __fmt_rcu, + Rcu::Log_rcu *p = tbe->payload(); + p->cpu = _cpu; + p->item = 0; + p->event = Rcu::Rcu_process); + + if (!_c.empty() && rgp->_completed >= _batch) + _d.append(_c); + + if (!_n.empty() && _c.empty()) + { + { + Lock_guard guard(&cpu_lock); + _c = cxx::move(_n); + } + + // start the next batch of callbacks + + _batch = rgp->_current + 1; + Mem::mp_rmb(); + + if (!rgp->_next_pending) + { + // start the batch and schedule start if it's a new batch + Lock_guard_lock)> guard(&rgp->_lock); + rgp->_next_pending = 1; + rgp->start_batch(); + } + } + + check_quiescent_state(rgp); + if (!_d.empty()) + return do_batch(); + + return false; +} + +PUBLIC inline +bool +Rcu_data::pending(Rcu_glbl *rgp) const +{ + // The CPU has pending RCU callbacks and the grace period for them + // has been completed. + if (!_c.empty() && rgp->_completed >= _batch) + return 1; + + // The CPU has no pending RCU callbacks, however there are new callbacks + if (_c.empty() && !_n.empty()) + return 1; + + // The CPU has callbacks to be invoked finally + if (!_d.empty()) + return 1; + + // RCU waits for a quiescent state from the CPU + if ((_q_batch != rgp->_current) || _pending) + return 1; + + // OK, no RCU work to do + return 0; + +} + +PUBLIC static inline NEEDS["globals.h"] +bool FIASCO_WARN_RESULT +Rcu::process_callbacks() +{ return _rcu_data.current().process_callbacks(&_rcu); } + +PUBLIC static inline NEEDS["globals.h"] +bool FIASCO_WARN_RESULT +Rcu::process_callbacks(unsigned cpu) +{ return _rcu_data.cpu(cpu).process_callbacks(&_rcu); } + +PUBLIC static inline +bool +Rcu::pending(unsigned cpu) +{ + return _rcu_data.cpu(cpu).pending(&_rcu); +} + +PUBLIC static inline +bool +Rcu::idle(unsigned cpu) +{ + Rcu_data const *d = &_rcu_data.cpu(cpu); + return d->_c.empty() && !d->pending(&_rcu); +} + +PUBLIC static inline +void +Rcu::inc_q_cnt(unsigned cpu) +{ _rcu_data.cpu(cpu)._q_passed = 1; } + +PUBLIC static +void +Rcu::schedule_callbacks(unsigned cpu, Unsigned64 clock) +{ + Timeout *t = &_rcu_timeout.cpu(cpu); + if (!t->is_set()) + t->set(clock, cpu); +} + +PUBLIC static inline NEEDS["cpu_lock.h"] +Rcu::Lock * +Rcu::lock() +{ return &cpu_lock; } + + +PUBLIC static inline +bool +Rcu::do_pending_work(unsigned cpu) +{ + if (pending(cpu)) + { + inc_q_cnt(cpu); + return process_callbacks(cpu); +#if 0 + Rcu::schedule_callbacks(cpu, Kip::k()->clock + Rcu::Period); +#endif + } + return false; +} diff --git a/kernel/fiasco/src/kern/ready_queue_fp.cpp b/kernel/fiasco/src/kern/ready_queue_fp.cpp new file mode 100644 index 00000000..e99d4ceb --- /dev/null +++ b/kernel/fiasco/src/kern/ready_queue_fp.cpp @@ -0,0 +1,101 @@ +INTERFACE [sched_fixed_prio || sched_fp_wfq]: + +#include "config.h" +#include +#include "member_offs.h" +#include "types.h" +#include "globals.h" + +template +class Ready_queue_fp +{ + friend class Jdb_thread_list; + template + friend struct Jdb_thread_list_policy; + +private: + typedef typename E::Fp_list List; + unsigned prio_highest; + List prio_next[256]; + +public: + void set_idle(E *sc) + { sc->_prio = Config::Kernel_prio; } + + void enqueue(E *, bool); + void dequeue(E *); + E *next_to_run() const; +}; + + +// --------------------------------------------------------------------------- +IMPLEMENTATION [sched_fixed_prio || sched_fp_wfq]: + +#include +#include "cpu_lock.h" +#include "kdb_ke.h" +#include "std_macros.h" +#include "config.h" + + +IMPLEMENT inline +template +E * +Ready_queue_fp::next_to_run() const +{ return prio_next[prio_highest].front(); } + +/** + * Enqueue context in ready-list. + */ +IMPLEMENT +template +void +Ready_queue_fp::enqueue(E *i, bool is_current_sched) +{ + assert_kdb(cpu_lock.test()); + + // Don't enqueue threads which are already enqueued + if (EXPECT_FALSE (i->in_ready_list())) + return; + + unsigned short prio = i->prio(); + + if (prio > prio_highest) + prio_highest = prio; + + prio_next[prio].push(i, is_current_sched ? List::Front : List::Back); +} + +/** + * Remove context from ready-list. + */ +IMPLEMENT inline NEEDS ["cpu_lock.h", "kdb_ke.h", "std_macros.h"] +template +void +Ready_queue_fp::dequeue(E *i) +{ + assert_kdb (cpu_lock.test()); + + // Don't dequeue threads which aren't enqueued + if (EXPECT_FALSE (!i->in_ready_list())) + return; + + unsigned short prio = i->prio(); + + prio_next[prio].remove(i); + + while (prio_next[prio_highest].empty() && prio_highest) + prio_highest--; +} + + +PUBLIC inline +template +void +Ready_queue_fp::requeue(E *i) +{ + if (!i->in_ready_list()) + enqueue(i, false); + + prio_next[i->prio()].rotate_to(*++List::iter(i)); +} diff --git a/kernel/fiasco/src/kern/ready_queue_wfq.cpp b/kernel/fiasco/src/kern/ready_queue_wfq.cpp new file mode 100644 index 00000000..5459a21a --- /dev/null +++ b/kernel/fiasco/src/kern/ready_queue_wfq.cpp @@ -0,0 +1,180 @@ +INTERFACE[sched_wfq || sched_fp_wfq]: + +#include "member_offs.h" +#include "types.h" +#include "globals.h" + +template< typename E > +class Ready_queue_wfq +{ + friend class Jdb_thread_list; + template + friend class Jdb_thread_list_policy; + +public: + E *current_sched() const { return _current_sched; } + void activate(E *s) { _current_sched = s; } + E *idle; + + void set_idle(E *sc) + { + idle = sc; + E::wfq_elem(sc)->_ready_link = &idle; + E::wfq_elem(sc)->_idle = 1; + } + + void enqueue(E *); + void dequeue(E *); + E *next_to_run() const; + +private: + void swap(unsigned a, unsigned b); + void heap_up(unsigned a); + void heap_down(unsigned a); + + E *_current_sched; + unsigned _cnt; + E *_heap[1024]; +}; + + +// -------------------------------------------------------------------------- +IMPLEMENTATION [sched_wfq || sched_fp_wfq]: + +#include +#include "config.h" +#include "cpu_lock.h" +#include "kdb_ke.h" +#include "std_macros.h" + + +IMPLEMENT inline +template +E * +Ready_queue_wfq::next_to_run() const +{ + if (_cnt) + return _heap[0]; + + if (_current_sched) + E::wfq_elem(idle)->_dl = E::wfq_elem(_current_sched)->_dl; + + return idle; +} + +IMPLEMENT inline +template +void +Ready_queue_wfq::swap(unsigned a, unsigned b) +{ + E::wfq_elem(_heap[a])->_ready_link = &_heap[b]; + E::wfq_elem(_heap[b])->_ready_link = &_heap[a]; + E *s = _heap[a]; + _heap[a] = _heap[b]; + _heap[b] = s; +} + +IMPLEMENT inline +template +void +Ready_queue_wfq::heap_up(unsigned a) +{ + for (;a > 0;) + { + unsigned p = (a-1)/2; + if (*E::wfq_elem(_heap[p]) < *E::wfq_elem(_heap[a])) + return; + swap(p, a); + a = p; + } +} + +IMPLEMENT inline +template +void +Ready_queue_wfq::heap_down(unsigned a) +{ + for (;;) + { + unsigned c1 = 2*a + 1; + unsigned c2 = 2*a + 2; + + if (_cnt <= c1) + return; + + if (_cnt > c2 && *E::wfq_elem(_heap[c2]) <= *E::wfq_elem(_heap[c1])) + c1 = c2; + + if (*E::wfq_elem(_heap[a]) <= *E::wfq_elem(_heap[c1])) + return; + + swap(c1, a); + + a = c1; + } +} + +/** + * Enqueue context in ready-list. + */ +IMPLEMENT +template +void +Ready_queue_wfq::enqueue(E *i) +{ + assert_kdb(cpu_lock.test()); + + // Don't enqueue threads which are already enqueued + if (EXPECT_FALSE (i->in_ready_list())) + return; + + unsigned n = _cnt++; + + E *&h = _heap[n]; + h = i; + E::wfq_elem(i)->_ready_link = &h; + + heap_up(n); +} + +/** + * Remove context from ready-list. + */ +IMPLEMENT inline NEEDS ["cpu_lock.h", "kdb_ke.h", "std_macros.h"] +template +void +Ready_queue_wfq::dequeue(E *i) +{ + assert_kdb (cpu_lock.test()); + + // Don't dequeue threads which aren't enqueued + if (EXPECT_FALSE (!i->in_ready_list() || i == idle)) + return; + + unsigned x = E::wfq_elem(i)->_ready_link - _heap; + + if (x == --_cnt) + { + E::wfq_elem(i)->_ready_link = 0; + return; + } + + swap(x, _cnt); + heap_down(x); + E::wfq_elem(i)->_ready_link = 0; +} + +/** + * Enqueue context in ready-list. + */ +PUBLIC +template +void +Ready_queue_wfq::requeue(E *i) +{ + if (!i->in_ready_list()) + enqueue(i); + + heap_down(E::wfq_elem(i)->_ready_link - _heap); +} + diff --git a/kernel/fiasco/src/kern/receiver.cpp b/kernel/fiasco/src/kern/receiver.cpp new file mode 100644 index 00000000..f4cbf106 --- /dev/null +++ b/kernel/fiasco/src/kern/receiver.cpp @@ -0,0 +1,332 @@ +INTERFACE: + +#include "context.h" +#include "l4_error.h" +#include "member_offs.h" +#include "timeout.h" +#include "prio_list.h" +#include "ref_obj.h" + +class Syscall_frame; +class Sender; + + +/** A receiver. This is a role class, and real receiver's must inherit from + it. The protected interface is intended for the receiver, and the public + interface is intended for the sender. + + The only reason this class inherits from Context is to force a specific + layout for Thread. Otherwise, Receiver could just embed or reference + a Context. + */ +class Receiver : public Context, public Ref_cnt_obj +{ + MEMBER_OFFSET(); + +public: + enum Rcv_state + { + Rs_not_receiving = false, + Rs_ipc_receive = true, + Rs_irq_receive = true + 1 + }; + + enum Abort_state + { + Abt_ipc_done, + Abt_ipc_cancel, + Abt_ipc_in_progress, + }; + + Rcv_state sender_ok(const Sender* sender) const; + + virtual ~Receiver() = 0; + +private: + // DATA + Sender *_partner; // IPC partner I'm waiting for/involved with + Syscall_frame *_rcv_regs; // registers used for receive + Mword _caller; + Iteratable_prio_list _sender_list; +}; + +typedef Context_ptr_base Receiver_ptr; + +IMPLEMENTATION: + +#include "l4_types.h" +#include + +#include "cpu_lock.h" +#include "globals.h" +#include "lock_guard.h" +#include "logdefs.h" +#include "sender.h" +#include "thread_lock.h" +#include "entry_frame.h" +#include "std_macros.h" +#include "thread_state.h" + +// Interface for receivers + +IMPLEMENT inline Receiver::~Receiver() {} +/** Constructor. + @param thread_lock the lock used for synchronizing access to this receiver + @param space_context the space context + */ +PROTECTED inline +Receiver::Receiver() +: Context(), _caller(0) +{} + +PUBLIC inline +Receiver * +Receiver::caller() const +{ return reinterpret_cast(_caller & ~0x03UL); } + +PUBLIC inline +unsigned char +Receiver::caller_rights() const +{ return _caller & 0x3; } + + +PUBLIC inline +void +Receiver::set_caller(Receiver *caller, unsigned char rights) +{ + register Mword nv = Mword(caller) | (rights & 0x3); + reinterpret_cast(_caller) = nv; +} +/** IPC partner (sender). + @return sender of ongoing or previous IPC operation + */ +PROTECTED inline +Sender* +Receiver::partner() const +{ + return _partner; +} + + +// Interface for senders + +/** Return a reference to receiver's IPC registers. + Senders call this function to poke values into the receiver's register set. + @pre state() & Thread_ipc_receiving_mask + @return pointer to receiver's IPC registers. + */ +PUBLIC inline NEEDS[] +Syscall_frame* +Receiver::rcv_regs() const +{ + //assert (state () & Thread_ipc_receiving_mask); + + return _rcv_regs; +} + +/** Head of sender list. + @return a reference to the receiver's list of senders + */ +PUBLIC inline +Iteratable_prio_list * +Receiver::sender_list() +{ + return &_sender_list; +} + +// MANIPULATORS + +PROTECTED inline +void +Receiver::set_rcv_regs(Syscall_frame* regs) +{ + _rcv_regs = regs; +} + +PUBLIC inline +void +Receiver::set_timeout(Timeout *t) +{ + _timeout = t; +} + +PUBLIC inline +void +Receiver::dequeue_timeout() +{ + if (_timeout) + _timeout->dequeue(_timeout->has_hit()); +} + +PUBLIC inline +void +Receiver::enqueue_timeout_again() +{ + if (_timeout) + _timeout->set_again(current_cpu()); +} + +PUBLIC inline +void +Receiver::reset_timeout() +{ + if (EXPECT_TRUE(!_timeout)) + return; + + _timeout->reset(); + _timeout = 0; +} + +PROTECTED inline +void Receiver::prepare_receive(Sender *partner, Syscall_frame *regs) +{ + set_rcv_regs(regs); // message should be poked in here + set_partner(partner); +} + +PROTECTED inline +bool Receiver::prepared() const +{ return _rcv_regs; } + +/** Set the IPC partner (sender). + @param partner IPC partner + */ +PUBLIC inline +void +Receiver::set_partner(Sender* partner) +{ + _partner = partner; +} + +PUBLIC inline +bool +Receiver::in_ipc(Sender *sender) +{ + return (state() & Thread_receive_in_progress) && (partner() == sender); +} + + +/** Return whether the receiver is ready to accept a message from the + given sender. + @param sender thread that wants to send a message to this receiver + @return true if receiver is in correct state to accept a message + right now (open wait, or closed wait and waiting for sender). + */ +IMPLEMENT inline NEEDS["std_macros.h", "thread_state.h", "sender.h", + Receiver::partner, Receiver::vcpu_async_ipc] +Receiver::Rcv_state +Receiver::sender_ok(const Sender *sender) const +{ + unsigned ipc_state = state() & Thread_ipc_mask; + + // If Thread_send_in_progress is still set, we're still in the send phase + if (EXPECT_FALSE(ipc_state != Thread_receive_wait)) + return vcpu_async_ipc(sender); + + // Check open wait; test if this sender is really the first in queue + if (EXPECT_TRUE(!partner() + && (_sender_list.empty() + || sender->is_head_of(&_sender_list)))) + return Rs_ipc_receive; + + // Check closed wait; test if this sender is really who we specified + if (EXPECT_TRUE(sender == partner())) + return Rs_ipc_receive; + + return Rs_not_receiving; +} + +//----------------------------------------------------------------------------- +// VCPU code: + +PRIVATE inline +Receiver::Rcv_state +Receiver::vcpu_async_ipc(Sender const *sender) const +{ + if (EXPECT_FALSE(state() & Thread_ipc_mask)) + return Rs_not_receiving; + + Vcpu_state *vcpu = vcpu_state().access(); + + if (EXPECT_FALSE(!vcpu_irqs_enabled(vcpu))) + return Rs_not_receiving; + + Receiver *self = const_cast(this); + + if (this == current()) + self->spill_user_state(); + + if (self->vcpu_enter_kernel_mode(vcpu)) + vcpu = vcpu_state().access(); + + LOG_TRACE("VCPU events", "vcpu", this, __context_vcpu_log_fmt, + Vcpu_log *l = tbe->payload(); + l->type = 1; + l->state = vcpu->_saved_state; + l->ip = Mword(sender); + l->sp = regs()->sp(); + l->space = ~0; //vcpu_user_space() ? static_cast(vcpu_user_space())->dbg_id() : ~0; + ); + + self->_rcv_regs = &vcpu->_ipc_regs; + vcpu->_ts.set_ipc_upcall(); + self->set_partner(const_cast(sender)); + self->state_add_dirty(Thread_receive_wait); + self->vcpu_save_state_and_upcall(); + return Rs_irq_receive; +} + + +PUBLIC inline +void +Receiver::vcpu_update_state() +{ + if (EXPECT_TRUE(!(state() & Thread_vcpu_enabled))) + return; + + if (sender_list()->empty()) + vcpu_state().access()->sticky_flags &= ~Vcpu_state::Sf_irq_pending; +} + + +// -------------------------------------------------------------------------- + +struct Ipc_remote_dequeue_request +{ + Receiver *partner; + Sender *sender; + Receiver::Abort_state state; +}; + +PRIVATE static +unsigned +Receiver::handle_remote_abort_send(Drq *, Context *, void *_rq) +{ + Ipc_remote_dequeue_request *rq = (Ipc_remote_dequeue_request*)_rq; + if (rq->sender->in_sender_list()) + { + // really cancled IPC + rq->state = Abt_ipc_cancel; + rq->sender->sender_dequeue(rq->partner->sender_list()); + rq->partner->vcpu_update_state(); + } + else if (rq->partner->in_ipc(rq->sender)) + rq->state = Abt_ipc_in_progress; + return 0; +} + +PUBLIC +Receiver::Abort_state +Receiver::abort_send(Sender *sender) +{ + Ipc_remote_dequeue_request rq; + rq.partner = this; + rq.sender = sender; + rq.state = Abt_ipc_done; + if (current_cpu() != cpu()) + drq(handle_remote_abort_send, &rq); + else + handle_remote_abort_send(0, 0, &rq); + return rq.state; +} + diff --git a/kernel/fiasco/src/kern/ref_obj.cpp b/kernel/fiasco/src/kern/ref_obj.cpp new file mode 100644 index 00000000..3fe864f0 --- /dev/null +++ b/kernel/fiasco/src/kern/ref_obj.cpp @@ -0,0 +1,49 @@ +INTERFACE: + +#include "types.h" + +class Ref_cnt_obj +{ +public: + Ref_cnt_obj() : _ref_cnt(0) {} +private: + Smword _ref_cnt; +}; + + +// ------------------------------------------------------------------------- +IMPLEMENTATION: + +#include "atomic.h" + +PUBLIC inline +Smword +Ref_cnt_obj::ref_cnt() const +{ return _ref_cnt; } + +PUBLIC inline NEEDS["atomic.h"] +bool +Ref_cnt_obj::inc_ref(bool from_zero = true) +{ + Smword old; + do + { + old = _ref_cnt; + if (!from_zero && !old) + return false; + } + while (!mp_cas(&_ref_cnt, old, old + 1)); + return true; +} + +PUBLIC inline NEEDS["atomic.h"] +Smword +Ref_cnt_obj::dec_ref() +{ + Smword old; + do + old = _ref_cnt; + while (!mp_cas(&_ref_cnt, old, old - 1)); + + return old - 1; +} diff --git a/kernel/fiasco/src/kern/ref_ptr.cpp b/kernel/fiasco/src/kern/ref_ptr.cpp new file mode 100644 index 00000000..f2c406da --- /dev/null +++ b/kernel/fiasco/src/kern/ref_ptr.cpp @@ -0,0 +1,70 @@ +INTERFACE: + +#include "kdb_ke.h" +#include "context.h" +#include "cpu_lock.h" +#include "globals.h" + + +template +class Ref_ptr +{ +public: + Ref_ptr(T *o = 0) : _p(o) + { __take_ref(); } + + T *ptr() const + { + // assert_kdb (cpu_lock.test()); + return _p; + } + + ~Ref_ptr() + { __drop_ref(); } + + Ref_ptr(Ref_ptr const &o) + { + __drop_ref(); + _p = o._p; + __take_ref(); + } + + void operator = (Ref_ptr const &o) + { + __drop_ref(); + _p = o._p; + __take_ref(); + } + + void operator = (T *o) + { + __drop_ref(); + _p = o; + __take_ref(); + } + + T *operator -> () const { return _p; } + + struct Null_type; + + operator Null_type const * () const + { return reinterpret_cast(_p); } + +private: + void __drop_ref() + { + if (_p && (_p->dec_ref() == 0)) + { + current()->rcu_wait(); + delete _p; + } + } + + void __take_ref() + { + if (_p) + _p->inc_ref(); + } + + T *_p; +}; diff --git a/kernel/fiasco/src/kern/regdefs.h b/kernel/fiasco/src/kern/regdefs.h new file mode 100644 index 00000000..81472c85 --- /dev/null +++ b/kernel/fiasco/src/kern/regdefs.h @@ -0,0 +1,160 @@ +#ifndef REGDEFS_H +#define REGDEFS_H + +// +// Register and register bit definitions for ia32, amd64 and UX architectures. +// + +#define CR0_PE 0x00000001 // Protection Enable +#define CR0_MP 0x00000002 // Monitor Coprocessor +#define CR0_EM 0x00000004 // Emulation Coprocessor +#define CR0_TS 0x00000008 // Task Switched +#define CR0_ET 0x00000010 // Extension Type +#define CR0_NE 0x00000020 // Numeric Error +#define CR0_WP 0x00010000 // Write Protect +#define CR0_AM 0x00040000 // Alignment Mask +#define CR0_NW 0x20000000 // Not Write-Through +#define CR0_CD 0x40000000 // Cache Disable +#define CR0_PG 0x80000000 // Paging + +#define CR3_PWT 0x00000008 // Page-Level Write Transparent +#define CR3_PCD 0x00000010 // Page-Level Cache Disable + +#define CR4_VME 0x00000001 // Virtual 8086 Mode Extensions +#define CR4_PVI 0x00000002 // Protected Mode Virtual Ints +#define CR4_TSD 0x00000004 // Time Stamp Disable +#define CR4_DE 0x00000008 // Debugging Extensions +#define CR4_PSE 0x00000010 // Page Size Extensions +#define CR4_PAE 0x00000020 // Physical Address Extensions +#define CR4_MCE 0x00000040 // Machine Check Exception +#define CR4_PGE 0x00000080 // Page Global Enable +#define CR4_PCE 0x00000100 // Perfmon Counter Enable +#define CR4_OSFXSR 0x00000200 // OS Supports FXSAVE/FXRSTOR +#define CR4_OSXMMEXCPT 0x00000400 // OS Supports SIMD Exceptions +#define CR4_VMXE 0x00002000 // VMX enable +#define CR4_OSXSAVE 0x00040000 // OS Support XSAVE + +#define EFLAGS_CF 0x00000001 // Carry Flag +#define EFLAGS_PF 0x00000004 // Parity Flag +#define EFLAGS_AF 0x00000010 // Adjust Flag +#define EFLAGS_ZF 0x00000040 // Zero Flag +#define EFLAGS_SF 0x00000080 // Sign Flag +#define EFLAGS_TF 0x00000100 // Trap Flag +#define EFLAGS_IF 0x00000200 // Interrupt Enable +#define EFLAGS_DF 0x00000400 // Direction Flag +#define EFLAGS_OF 0x00000800 // Overflow Flag +#define EFLAGS_IOPL 0x00003000 // I/O Privilege Level (12+13) +#define EFLAGS_IOPL_K 0x00000000 // kernel +#define EFLAGS_IOPL_U 0x00003000 // user +#define EFLAGS_NT 0x00004000 // Nested Task +#define EFLAGS_RF 0x00010000 // Resume +#define EFLAGS_VM 0x00020000 // Virtual 8086 Mode +#define EFLAGS_AC 0x00040000 // Alignment Check +#define EFLAGS_VIF 0x00080000 // Virtual Interrupt +#define EFLAGS_VIP 0x00100000 // Virtual Interrupt Pending +#define EFLAGS_ID 0x00200000 // Identification + +// CPU Feature Flags +#define FEAT_FPU 0x00000001 // FPU On Chip +#define FEAT_VME 0x00000002 // Virt. 8086 Mode Enhancements +#define FEAT_DE 0x00000004 // Debugging Extensions +#define FEAT_PSE 0x00000008 // Page Size Extension +#define FEAT_TSC 0x00000010 // Time Stamp Counter +#define FEAT_MSR 0x00000020 // Model Specific Registers +#define FEAT_PAE 0x00000040 // Physical Address Extension +#define FEAT_MCE 0x00000080 // Machine Check Exception +#define FEAT_CX8 0x00000100 // CMPXCHG8B Instruction +#define FEAT_APIC 0x00000200 // APIC On Chip +#define FEAT_SEP 0x00000800 // Sysenter/Sysexit Present +#define FEAT_MTRR 0x00001000 // Memory Type Range Registers +#define FEAT_PGE 0x00002000 // PTE Global Bit Extension +#define FEAT_MCA 0x00004000 // Machine Check Architecture +#define FEAT_CMOV 0x00008000 // Conditional Move Instruction +#define FEAT_PAT 0x00010000 // Page Attribute Table +#define FEAT_PSE36 0x00020000 // 32 bit Page Size Extension +#define FEAT_PSN 0x00040000 // Processor Serial Number +#define FEAT_CLFSH 0x00080000 // CLFLUSH Instruction +#define FEAT_DS 0x00200000 // Debug Store +#define FEAT_ACPI 0x00400000 // Thermal Monitor & Clock +#define FEAT_MMX 0x00800000 // MMX Technology +#define FEAT_FXSR 0x01000000 // FXSAVE/FXRSTOR Instructions +#define FEAT_SSE 0x02000000 // SSE +#define FEAT_SSE2 0x04000000 // SSE2 +#define FEAT_SS 0x08000000 // Self Snoop +#define FEAT_HTT 0x10000000 // Hyper-Threading Technology +#define FEAT_TM 0x20000000 // Thermal Monitor +#define FEAT_PBE 0x80000000 // Pending Break Enable + +// CPU Extended Feature Flags (Intel) +#define FEATX_SSE3 0x00000001 // SSE3 +#define FEATX_MONITOR 0x00000008 // MONITOR/MWAIT Support +#define FEATX_DSCPL 0x00000010 // CPL Qualified Debug Store +#define FEATX_VMX 0x00000020 // Virtual Machine Extensions +#define FEATX_EST 0x00000080 // Enhanced SpeedStep Technology +#define FEATX_TM2 0x00000100 // Thermal Monitor 2 +#define FEATX_SSSE3 0x00000200 // SSSE3 +#define FEATX_CID 0x00000400 // L1 Context ID (adaptive/shared) +#define FEATX_CX16 0x00002000 // CMPXCHG16B Instruction +#define FEATX_XTPR 0x00004000 // Disable Task Priority Messages +#define FEATX_PCID 0x00020000 // PCID +#define FEATX_SSE4_1 0x00080000 // SSE4_1 +#define FEATX_SSE4_2 0x00100000 // SSE4_2 +#define FEATX_X2APIC 0x00200000 // x2APIC +#define FEATX_AES 0x02000000 // AES instructions +#define FEATX_XSAVE 0x04000000 // XSAVE +#define FEATX_OSXSAVE 0x08000000 // OSXSAVE +#define FEATX_AVX 0x10000000 // AVX + +// AMD: CPU Feature Flags, Fn80000001_ECX +#define FEATA_SVM 0x00000004 + +// AMD: CPU Feature Flags, Fn80000001_EDX +#define FEATA_SYSCALL 0x00000800 // Syscall/Sysret Present +#define FEATA_MP 0x00080000 // MP Capable +#define FEATA_NX 0x00100000 // No-Execute Page Protection +#define FEATA_MMXEXT 0x00400000 // AMD Extensions to MMX +#define FEATA_LM 0x20000000 // Long Mode +#define FEATA_3DNOWEXT 0x40000000 // AMD 3DNow! extensions +#define FEATA_3DNOW 0x80000000 // 3DNow! + +// Page Fault Error Codes +// PF_ERR_REMTADDR and PF_ERR_USERADDR are UX-emulation only +#define PF_ERR_PRESENT 0x00000001 // PF: Page Is Present In PTE +#define PF_ERR_WRITE 0x00000002 // PF: Page Is Write Protected +#define PF_ERR_USERMODE 0x00000004 // PF: Caused By User Mode Code +#define PF_ERR_RESERVED 0x00000008 // PF: Reserved Bit Set in PDIR +#define PF_ERR_REMTADDR 0x40000000 // PF: In Remote Address Space +#define PF_ERR_USERADDR 0x80000000 // PF: In User Address Space + +// Model Specific Registers +#define MSR_TSC 0x010 // Time Stamp Counter +#define MSR_IA32_FEATURE_CONTROL 0x03a // Control Features in Intel 64 Processor +#define MSR_SYSENTER_CS 0x174 // Kernel Code Segment +#define MSR_SYSENTER_ESP 0x175 // Kernel Syscall Entry +#define MSR_SYSENTER_EIP 0x176 // Kernel Stack Pointer +#define MSR_LER_FROM_LIP 0x1d7 // Last Exception Record From Linear +#define MSR_LER_TO_LIP 0x1d8 // Last Exception Record To Linear +#define MSR_DEBUGCTLA 0x1d9 // Debug Control +#define MSR_LASTBRANCH_TOS 0x1da // (P4) Last Branch Record Stack TOS +#define MSR_LASTBRANCH_0 0x1db // (P4) Last Branch Record 0 +#define MSR_LASTBRANCH_1 0x1dc // (P4) Last Branch Record 1 +#define MSR_LASTBRANCH_2 0x1dd // (P4) Last Branch Record 2 +#define MSR_LASTBRANCH_3 0x1de // (P4) Last Branch Record 3 +#define MSR_LASTBRANCHFROMIP 0x1db // (P6) +#define MSR_LASTBRANCHTOIP 0x1dc // (P6) +#define MSR_LASTINTFROMIP 0x1dd // (P6) +#define MSR_LASTINTTOIP 0x1de // (P6) +#define MSR_PAT 0x277 // PAT + +// AMD64 Model Specific Registers +#define MSR_EFER 0xc0000080 // Extended Feature Enable Register +#define MSR_STAR 0xc0000081 // CS and SS for Syscall/Sysret +#define MSR_LSTAR 0xc0000082 // EIP for Syscall (64Bit-Mode) +#define MSR_CTAR 0xc0000083 // EIP for Syscall (Comp-Mode) +#define MSR_SFMASK 0xc0000084 // RFLAGS for Syscall +#define MSR_FS_BASE 0xc0000100 // FS-Base +#define MSR_GS_BASE 0xc0000101 // GS-Base +#define MSR_VM_CR 0xc0010114 // SVM +#define MSR_VM_HSAVE_PA 0xc0010117 // SVM host state-save area + +#endif diff --git a/kernel/fiasco/src/kern/reset-dummy.cpp b/kernel/fiasco/src/kern/reset-dummy.cpp new file mode 100644 index 00000000..7ccbb8a4 --- /dev/null +++ b/kernel/fiasco/src/kern/reset-dummy.cpp @@ -0,0 +1,10 @@ +IMPLEMENTATION: + +// reset PC +void __attribute__ ((noreturn)) +platform_reset() +{ + while(1) + ; +} + diff --git a/kernel/fiasco/src/kern/sched_context-fixed_prio.cpp b/kernel/fiasco/src/kern/sched_context-fixed_prio.cpp new file mode 100644 index 00000000..b8dfe41b --- /dev/null +++ b/kernel/fiasco/src/kern/sched_context-fixed_prio.cpp @@ -0,0 +1,225 @@ + +/* + * Timeslice infrastructure + */ + +INTERFACE [sched_fixed_prio]: + +#include +#include "member_offs.h" +#include "types.h" +#include "globals.h" +#include "ready_queue_fp.h" + + +class Sched_context : public cxx::D_list_item +{ + MEMBER_OFFSET(); + friend class Jdb_list_timeouts; + friend class Jdb_thread_list; + + template + friend struct Jdb_thread_list_policy; + +public: + typedef cxx::Sd_list Fp_list; + + class Ready_queue : public Ready_queue_fp + { + public: + Context *schedule_in_progress; + void activate(Sched_context *s) + { _current_sched = s; } + Sched_context *current_sched() const { return _current_sched; } + + private: + Sched_context *_current_sched; + }; + + Context *context() const { return context_of(this); } + +private: + unsigned short _prio; + Unsigned64 _quantum; + Unsigned64 _left; + + friend class Ready_queue_fp; +}; + + +IMPLEMENTATION [sched_fixed_prio]: + +#include +#include "cpu_lock.h" +#include "kdb_ke.h" +#include "std_macros.h" +#include "config.h" + + +/** + * Constructor + */ +PUBLIC +Sched_context::Sched_context() +: _prio(Config::Default_prio), + _quantum(Config::Default_time_slice), + _left(Config::Default_time_slice) +{} + + +/** + * Return priority of Sched_context + */ +PUBLIC inline +unsigned short +Sched_context::prio() const +{ + return _prio; +} + +/** + * Set priority of Sched_context + */ +PUBLIC inline +void +Sched_context::set_prio (unsigned short const prio) +{ + _prio = prio; +} + +/** + * Return full time quantum of Sched_context + */ +PUBLIC inline +Unsigned64 +Sched_context::quantum() const +{ + return _quantum; +} + +/** + * Set full time quantum of Sched_context + */ +PUBLIC inline +void +Sched_context::set_quantum (Unsigned64 const quantum) +{ + _quantum = quantum; +} + +/** + * Return remaining time quantum of Sched_context + */ +PUBLIC inline +Unsigned64 +Sched_context::left() const +{ + return _left; +} + +PUBLIC inline NEEDS[Sched_context::set_left, Sched_context::quantum] +void +Sched_context::replenish() +{ set_left(quantum()); } + +/** + * Set remaining time quantum of Sched_context + */ +PUBLIC inline +void +Sched_context::set_left (Unsigned64 const left) +{ + _left = left; +} + + +/** + * Check if Context is in ready-list. + * @return 1 if thread is in ready-list, 0 otherwise + */ +PUBLIC inline +Mword +Sched_context::in_ready_list() const +{ + return Fp_list::in_list(this); +} + +/** + * Remove context from ready-list. + */ +PUBLIC inline NEEDS ["cpu_lock.h", "kdb_ke.h", "std_macros.h"] +void +Sched_context::ready_dequeue() +{ + assert_kdb (cpu_lock.test()); + + // Don't dequeue threads which aren't enqueued + if (EXPECT_FALSE (!in_ready_list())) + return; + + unsigned cpu = current_cpu(); + + _ready_q.cpu(cpu).dequeue(this); +} + +/** + * Enqueue context in ready-list. + */ +PUBLIC inline +void +Sched_context::ready_enqueue(unsigned cpu) +{ + assert_kdb(cpu_lock.test()); + + // Don't enqueue threads which are already enqueued + if (EXPECT_FALSE (in_ready_list())) + return; + + Ready_queue &rq = _ready_q.cpu(cpu); + + rq.enqueue(this, this == rq.current_sched()); +} + +PUBLIC inline +void +Sched_context::requeue(unsigned cpu) +{ + _ready_q.cpu(cpu).requeue(this); +} + +/** + * Return if there is currently a schedule() in progress + */ +PUBLIC static inline +Context * +Sched_context::schedule_in_progress(unsigned cpu) +{ + return _ready_q.cpu(cpu).schedule_in_progress; +} + +PUBLIC static inline +void +Sched_context::reset_schedule_in_progress(unsigned cpu) +{ _ready_q.cpu(cpu).schedule_in_progress = 0; } + + +/** + * Invalidate (expire) currently active global Sched_context. + */ +PUBLIC static inline +void +Sched_context::invalidate_sched(unsigned cpu) +{ + _ready_q.cpu(cpu).activate(0); +} + +PUBLIC inline +bool +Sched_context::dominates(Sched_context *sc) +{ return prio() > sc->prio(); } + +PUBLIC inline +void +Sched_context::deblock_refill(unsigned) +{} + diff --git a/kernel/fiasco/src/kern/sched_context-fp_wfq.cpp b/kernel/fiasco/src/kern/sched_context-fp_wfq.cpp new file mode 100644 index 00000000..6610945d --- /dev/null +++ b/kernel/fiasco/src/kern/sched_context-fp_wfq.cpp @@ -0,0 +1,309 @@ +INTERFACE [sched_fp_wfq]: + +#include "ready_queue_fp.h" +#include "ready_queue_wfq.h" + +class Sched_context +{ + MEMBER_OFFSET(); + friend class Jdb_list_timeouts; + friend class Jdb_thread_list; + + struct Ready_list_item_concept + { + typedef Sched_context Item; + static Sched_context *&next(Sched_context *e) { return e->_sc.fp._ready_next; } + static Sched_context *&prev(Sched_context *e) { return e->_sc.fp._ready_prev; } + static Sched_context const *next(Sched_context const *e) + { return e->_sc.fp._ready_next; } + static Sched_context const *prev(Sched_context const *e) + { return e->_sc.fp._ready_prev; } + }; + +public: + enum Type { Fixed_prio, Wfq }; + + typedef cxx::Sd_list Fp_list; + +private: + Type _t; + + struct B_sc + { + unsigned short _p; + unsigned _q; + Unsigned64 _left; + + unsigned prio() const { return _p; } + }; + + + struct Fp_sc : public B_sc + { + Sched_context *_ready_next, *_ready_prev; + }; + + struct Wfq_sc : public B_sc + { + Sched_context **_ready_link; + bool _idle:1; + Unsigned64 _dl; + + unsigned _w; + unsigned _qdw; + bool operator <= (Wfq_sc const &o) const + { return _dl <= o._dl; } + + bool operator < (Wfq_sc const &o) const + { return _dl < o._dl; } + }; + + union Sc + { + Wfq_sc wfq; + Fp_sc fp; + }; + + Sc _sc; + +public: + static Wfq_sc *wfq_elem(Sched_context *x) { return &x->_sc.wfq; } + + struct Ready_queue + { + public: + Ready_queue_fp fp_rq; + Ready_queue_wfq wfq_rq; + Context *schedule_in_progress; + Sched_context *current_sched() const { return _current_sched; } + void activate(Sched_context *s) + { + if (s && s->_t == Wfq) + wfq_rq.activate(s); + _current_sched = s; + } + + private: + Sched_context *_current_sched; + + friend class Jdb_thread_list; + + public: + void set_idle(Sched_context *sc) + { sc->_t = Wfq; sc->_sc.wfq._p = 0; wfq_rq.set_idle(sc); } + + void enqueue(Sched_context *); + void dequeue(Sched_context *); + Sched_context *next_to_run() const; + }; + + Context *context() const { return context_of(this); } +}; + + +IMPLEMENTATION [sched_fp_wfq]: + +#include +#include "cpu_lock.h" +#include "kdb_ke.h" +#include "std_macros.h" +#include "config.h" + +/** + * Constructor + */ +PUBLIC +Sched_context::Sched_context() +{ + _t = Fixed_prio; + _sc.fp._p = Config::Default_prio; + _sc.fp._q = Config::Default_time_slice; + _sc.fp._left = Config::Default_time_slice; + _sc.fp._ready_next = 0; +} + +IMPLEMENT inline +Sched_context * +Sched_context::Ready_queue::next_to_run() const +{ + Sched_context *s = fp_rq.next_to_run(); + if (s) + return s; + + return wfq_rq.next_to_run(); +} + +/** + * Check if Context is in ready-list. + * @return 1 if thread is in ready-list, 0 otherwise + */ +PUBLIC inline +Mword +Sched_context::in_ready_list() const +{ + // this magically works for the fp list and the heap, + // because wfq._ready_link and fp._ready_next are the + // same memory location + return _sc.wfq._ready_link != 0; +} + +/** + * Return if there is currently a schedule() in progress + */ +PUBLIC static inline +Context * +Sched_context::schedule_in_progress(unsigned cpu) +{ + return _ready_q.cpu(cpu).schedule_in_progress; +} + +PUBLIC static inline +void +Sched_context::reset_schedule_in_progress(unsigned cpu) +{ _ready_q.cpu(cpu).schedule_in_progress = 0; } + + +PUBLIC inline +unsigned +Sched_context::prio() const +{ return _sc.fp._p; } + +PUBLIC inline +void +Sched_context::set_prio(unsigned p) +{ + if (_t == Fixed_prio) + _sc.fp._p = p; + else + _sc.fp._p = 0; +} + +/** + * Invalidate (expire) currently active global Sched_context. + */ +PUBLIC static inline +void +Sched_context::invalidate_sched(unsigned cpu) +{ + _ready_q.cpu(cpu).activate(0); +} + +PUBLIC inline +void +Sched_context::deblock_refill(unsigned cpu) +{ + if (_t != Wfq) + return; + + Unsigned64 da = 0; + Sched_context *cs = _ready_q.cpu(cpu).wfq_rq.current_sched(); + + if (EXPECT_TRUE(cs != 0)) + da = cs->_sc.wfq._dl; + + if (_sc.wfq._dl >= da) + return; + + _sc.wfq._left += (da - _sc.wfq._dl) * _sc.wfq._w; + if (_sc.wfq._left > _sc.wfq._q) + _sc.wfq._left = _sc.wfq._q; + _sc.wfq._dl = da; +} + +/** + * Enqueue context in ready-list. + */ +PUBLIC +void +Sched_context::ready_enqueue(unsigned cpu) +{ + assert_kdb(cpu_lock.test()); + + // Don't enqueue threads which are already enqueued + if (EXPECT_FALSE (in_ready_list())) + return; + + Ready_queue &rq = _ready_q.cpu(cpu); + + if (_t == Fixed_prio) + rq.fp_rq.enqueue(this, this == rq.current_sched()); + else + rq.wfq_rq.enqueue(this); +} + +/** + * Remove context from ready-list. + */ +PUBLIC inline NEEDS ["cpu_lock.h", "kdb_ke.h", "std_macros.h"] +void +Sched_context::ready_dequeue() +{ + assert_kdb (cpu_lock.test()); + + // Don't dequeue threads which aren't enqueued + if (EXPECT_FALSE (!in_ready_list())) + return; + + unsigned cpu = current_cpu(); + + if (_t == Fixed_prio) + _ready_q.cpu(cpu).fp_rq.dequeue(this); + else + _ready_q.cpu(cpu).wfq_rq.dequeue(this); +} + +PUBLIC +void +Sched_context::requeue(unsigned cpu) +{ + if (_t == Fixed_prio) + _ready_q.cpu(cpu).fp_rq.requeue(this); + else + _ready_q.cpu(cpu).wfq_rq.requeue(this); +} + +PUBLIC inline +bool +Sched_context::dominates(Sched_context *sc) +{ + if (_t == Fixed_prio) + return prio() > sc->prio(); + + if (_sc.wfq._idle) + return false; + + if (sc->_t == Fixed_prio) + return false; + + return _sc.wfq._dl < sc->_sc.wfq._dl; +} + +PUBLIC inline +void +Sched_context::replenish() +{ + _sc.fp._left = _sc.fp._q; + if (_t == Wfq) + _sc.wfq._dl += _sc.wfq._qdw; +} + + +PUBLIC inline +void +Sched_context::set_left(Unsigned64 l) +{ _sc.fp._left = l; } + +PUBLIC inline +Unsigned64 +Sched_context::left() const +{ return _sc.fp._left; } + +PUBLIC inline +Unsigned64 +Sched_context::quantum() const +{ return _sc.fp._q; } + +PUBLIC inline +void +Sched_context::set_quantum(Unsigned64 q) +{ _sc.fp._q = q; } diff --git a/kernel/fiasco/src/kern/sched_context-wfq.cpp b/kernel/fiasco/src/kern/sched_context-wfq.cpp new file mode 100644 index 00000000..9cf4a606 --- /dev/null +++ b/kernel/fiasco/src/kern/sched_context-wfq.cpp @@ -0,0 +1,254 @@ + +/* + * Timeslice infrastructure + */ + +INTERFACE[sched_wfq] : + +#include "member_offs.h" +#include "types.h" +#include "globals.h" +#include "ready_queue_wfq.h" + + +class Sched_context +{ + MEMBER_OFFSET(); + friend class Jdb_list_timeouts; + friend class Jdb_thread_list; + + template + friend class Jdb_thread_list_policy; + +public: + class Ready_queue : public Ready_queue_wfq + { + public: + Context *schedule_in_progress; + }; + + Context *context() const { return context_of(this); } + +private: + static Sched_context *wfq_elem(Sched_context *x) { return x; } + + Sched_context **_ready_link; + bool _idle:1; + Unsigned64 _dl; + Unsigned64 _left; + + unsigned _q; + unsigned _w; + unsigned _qdw; + + friend class Ready_queue_wfq; + + bool operator <= (Sched_context const &o) const + { return _dl <= o._dl; } + + bool operator < (Sched_context const &o) const + { return _dl < o._dl; } + +}; + +// -------------------------------------------------------------------------- +IMPLEMENTATION [sched_wfq]: + +#include +#include "config.h" +#include "cpu_lock.h" +#include "kdb_ke.h" +#include "std_macros.h" + + +/** + * Constructor + */ +PUBLIC +Sched_context::Sched_context() +: _ready_link(0), + _idle(0), + _dl(0), + _left(Config::Default_time_slice), + _q(Config::Default_time_slice), + _w(1), + _qdw(_q / _w) +{} + +/** + * Return owner of Sched_context + */ +PUBLIC inline +Context * +Sched_context::owner() const +{ + return context(); +} + +/** + * Return full time quantum of Sched_context + */ +PUBLIC inline +Unsigned64 +Sched_context::quantum() const +{ + return _q; +} + +/** + * Set full time quantum of Sched_context + */ +PUBLIC inline +void +Sched_context::set_quantum(Unsigned64 const quantum) +{ + _q = quantum; + _qdw = _q/_w; +} + +/** + * Return remaining time quantum of Sched_context + */ +PUBLIC inline +Unsigned64 +Sched_context::left() const +{ + return _left; +} + +PUBLIC inline NEEDS[Sched_context::set_left, Sched_context::quantum] +void +Sched_context::replenish() +{ + set_left(_q); + _dl += _qdw; +} + +/** + * Set remaining time quantum of Sched_context + */ +PUBLIC inline +void +Sched_context::set_left (Unsigned64 const left) +{ + _left = left; +} + +/** + * Check if Context is in ready-list. + * @return 1 if thread is in ready-list, 0 otherwise + */ +PUBLIC inline +Mword +Sched_context::in_ready_list() const +{ + return _ready_link != 0; +} + +/** + * Remove context from ready-list. + */ +PUBLIC inline NEEDS ["cpu_lock.h", "kdb_ke.h", "std_macros.h"] +void +Sched_context::ready_dequeue() +{ + assert_kdb (cpu_lock.test()); + + // Don't dequeue threads which aren't enqueued + if (EXPECT_FALSE (!in_ready_list())) + return; + + unsigned cpu = current_cpu(); + + _ready_q.cpu(cpu).dequeue(this); + +} + +/** + * Enqueue context in ready-list. + */ +PUBLIC inline NEEDS["kdb_ke.h"] +void +Sched_context::ready_enqueue(unsigned cpu) +{ + assert_kdb(cpu_lock.test()); + + // Don't enqueue threads which are already enqueued + if (EXPECT_FALSE (in_ready_list())) + return; + + _ready_q.cpu(cpu).enqueue(this);; +} + +PUBLIC +void +Sched_context::requeue(unsigned cpu) +{ + _ready_q.cpu(cpu).requeue(this); +} + +PUBLIC inline +bool +Sched_context::dominates(Sched_context *sc) +{ +#if 0 + if (_idle) + LOG_MSG_3VAL(current(), "idl", (Mword)sc, _dl, sc->_dl); +#endif + return !_idle && _dl < sc->_dl; +} + +PUBLIC inline +void +Sched_context::deblock_refill(unsigned cpu) +{ + Unsigned64 da = 0; + Sched_context *cs = rq(cpu).current_sched(); + if (EXPECT_TRUE(cs != 0)) + da = cs->_dl; + + if (_dl >= da) + return; + + _left += (da - _dl) * _w; + if (_left > _q) + _left = _q; + _dl = da; +} + + +/** + * Return if there is currently a schedule() in progress + */ +PUBLIC static inline +Context * +Sched_context::schedule_in_progress(unsigned cpu) +{ + return _ready_q.cpu(cpu).schedule_in_progress; +} + +PUBLIC static inline +void +Sched_context::reset_schedule_in_progress(unsigned cpu) +{ _ready_q.cpu(cpu).schedule_in_progress = 0; } + + +/** + * Invalidate (expire) currently active global Sched_context. + */ +PUBLIC static inline +void +Sched_context::invalidate_sched(unsigned cpu) +{ + _ready_q.cpu(cpu).activate(0); +} + + +PUBLIC static inline +unsigned +Sched_context::prio() { return 0; } + +PUBLIC static inline +void +Sched_context::set_prio(unsigned) +{} diff --git a/kernel/fiasco/src/kern/sched_context.cpp b/kernel/fiasco/src/kern/sched_context.cpp new file mode 100644 index 00000000..b402ceae --- /dev/null +++ b/kernel/fiasco/src/kern/sched_context.cpp @@ -0,0 +1,70 @@ +INTERFACE: +#include "per_cpu_data.h" + +EXTENSION class Sched_context +{ +private: + static Per_cpu _ready_q; +}; + +IMPLEMENTATION: + +#include "kdb_ke.h" + +DEFINE_PER_CPU Per_cpu Sched_context::_ready_q; + +PUBLIC static inline +Sched_context::Ready_queue & +Sched_context::rq(unsigned cpu) +{ return _ready_q.cpu(cpu); } + + +/** + * \param cpu must be current_cpu() + */ +PUBLIC inline NEEDS["kdb_ke.h"] +void +Sched_context::deblock(unsigned cpu) +{ + assert_kdb(cpu_lock.test()); + + Sched_context *cs = rq(cpu).current_sched(); + if (this != cs) + deblock_refill(cpu); + + ready_enqueue(cpu); +} + +/** + * \param cpu must be current_cpu() + * \param crs the Sched_context of the current context + * \param lazy_q queue lazily if applicable + */ +PUBLIC inline NEEDS["kdb_ke.h"] +bool +Sched_context::deblock(unsigned cpu, Sched_context *crs, bool lazy_q = false) +{ + assert_kdb(cpu_lock.test()); + + Sched_context *cs = rq(cpu).current_sched(); + bool res = true; + if (this == cs) + { + if (crs->dominates(this)) + res = false; + } + else + { + deblock_refill(cpu); + + if ((EXPECT_TRUE(cs != 0) && cs->dominates(this)) || crs->dominates(this)) + res = false; + } + + if (res && lazy_q) + return true; + + ready_enqueue(cpu); + return res; +} + diff --git a/kernel/fiasco/src/kern/scheduler.cpp b/kernel/fiasco/src/kern/scheduler.cpp new file mode 100644 index 00000000..82dd1f0f --- /dev/null +++ b/kernel/fiasco/src/kern/scheduler.cpp @@ -0,0 +1,266 @@ +INTERFACE: + +#include "context.h" +#include "icu_helper.h" +#include "types.h" + +class Scheduler : public Icu_h, public Irq_chip_soft +{ + FIASCO_DECLARE_KOBJ(); + typedef Icu_h Icu; + +public: + enum Operation + { + Info = 0, + Run_thread = 1, + Idle_time = 2, + }; + + class Cpu_set + { + private: + Mword _w; + + public: + Mword offset() const { return (_w & 0x00ffffff) & (~0 << granularity()); } + Mword granularity() const { return (_w >> 24) & (MWORD_BITS-1) ; } + bool contains(unsigned cpu, Mword map) const + { + if (offset() > cpu) + return false; + + cpu -= offset(); + cpu >>= granularity(); + if (cpu >= MWORD_BITS) + return false; + + return map & (1UL << cpu); + } + }; + + static Scheduler scheduler; +private: + Irq_base *_irq; +}; + +// ---------------------------------------------------------------------------- +IMPLEMENTATION: + +#include "thread_object.h" +#include "l4_buf_iter.h" +#include "entry_frame.h" + +FIASCO_DEFINE_KOBJ(Scheduler); + +Scheduler Scheduler::scheduler; + +PUBLIC void +Scheduler::operator delete (void *) +{ + printf("WARNING: tried to delete kernel scheduler object.\n" + " The system is now useless\n"); +} + +PUBLIC inline +Scheduler::Scheduler() : _irq(0) +{ + initial_kobjects.register_obj(this, 7); +} + +PRIVATE static +Mword +Scheduler::first_online(Cpu_set const *cpus, Mword bm) +{ + unsigned cpu = cpus->offset(); + + for (;;) + { + unsigned b = (cpu - cpus->offset()) >> cpus->granularity(); + if (cpu >= Config::Max_num_cpus || b >= MWORD_BITS) + return ~0UL; + + if (!(bm & (1UL << b))) + { + cpu += 1UL << cpus->granularity(); + continue; + } + + if (Cpu::online(cpu)) + return cpu; + + ++cpu; + } +} + +PRIVATE +L4_msg_tag +Scheduler::sys_run(unsigned char /*rights*/, Syscall_frame *f, Utcb const *utcb) +{ + L4_msg_tag const tag = f->tag(); + unsigned const curr_cpu = current_cpu(); + + Obj_space *s = current()->space(); + assert(s); + + L4_snd_item_iter snd_items(utcb, tag.words()); + + if (EXPECT_FALSE(tag.words() < 5)) + return commit_result(-L4_err::EInval); + + if (EXPECT_FALSE(!tag.items() || !snd_items.next())) + return commit_result(-L4_err::EInval); + + L4_fpage _thread(snd_items.get()->d); + if (EXPECT_FALSE(!_thread.is_objpage())) + return commit_result(-L4_err::EInval); + + Thread *thread = Kobject::dcast(s->lookup_local(_thread.obj_index())); + if (!thread) + return commit_result(-L4_err::EInval); + + Cpu_set const *cpus = reinterpret_cast(&utcb->values[1]); + + Thread::Migration_info info; + + unsigned t_cpu = thread->cpu(); + if (cpus->contains(t_cpu, utcb->values[2])) + info.cpu = t_cpu; + else if (cpus->contains(curr_cpu, utcb->values[2])) + info.cpu = curr_cpu; + else + info.cpu = first_online(cpus, utcb->values[2]); +#if 0 + if (info.cpu == Invalid_cpu) + return commit_result(-L4_err::EInval); +#endif + info.prio = utcb->values[3]; + info.quantum = utcb->values[4]; +#if 0 + printf("CPU[%lx]: current_cpu=%u run(thread=%lx, prio=%ld, quantum=%ld, cpu=%ld (%lx,%u,%u)\n", + dbg_id(), curr_cpu, thread->dbg_id(), info.prio, info.quantum, info.cpu, utcb->values[2], cpus->offset(), cpus->granularity()); +#endif + + if (info.prio > 255) + info.prio = 255; + if (!info.quantum) + info.quantum = Config::Default_time_slice; + + + thread->migrate(info); + + return commit_result(0); +} + +PRIVATE +L4_msg_tag +Scheduler::sys_idle_time(unsigned char, + Syscall_frame *f, Utcb *utcb) +{ + if (f->tag().words() < 3) + return commit_result(-L4_err::EInval); + + Cpu_set const *cpus = reinterpret_cast(&utcb->values[1]); + Mword const cpu = first_online(cpus, utcb->values[2]); + if (cpu == ~0UL) + return commit_result(-L4_err::EInval); + + reinterpret_cast(utcb->values)->t + = Context::kernel_context(cpu)->consumed_time(); + + return commit_result(0, Utcb::Time_val::Words); +} + +PRIVATE +L4_msg_tag +Scheduler::sys_info(unsigned char, Syscall_frame *f, + Utcb const *iutcb, Utcb *outcb) +{ + if (f->tag().words() < 2) + return commit_result(-L4_err::EInval); + + Cpu_set const *s = reinterpret_cast(&iutcb->values[1]); + Mword rm = 0; + Mword max = Config::Max_num_cpus; + Mword const offset = s->offset() << s->granularity(); + if (offset >= max) + return commit_result(-L4_err::EInval); + + if (max > offset + ((Mword)MWORD_BITS << s->granularity())) + max = offset + ((Mword)MWORD_BITS << s->granularity()); + + for (Mword i = 0; i < max - offset; ++i) + if (Cpu::online(i + offset)) + rm |= (1 << (i >> s->granularity())); + + outcb->values[0] = rm; + outcb->values[1] = Config::Max_num_cpus; + return commit_result(0, 2); +} + +PUBLIC inline +Irq_base * +Scheduler::icu_get_irq(unsigned irqnum) +{ + if (irqnum > 0) + return 0; + + return _irq; +} + + +PUBLIC inline +void +Scheduler::icu_get_info(Mword *features, Mword *num_irqs, Mword *num_msis) +{ + *features = 0; // supported features (only normal irqs) + *num_irqs = 1; + *num_msis = 0; +} + +PUBLIC +L4_msg_tag +Scheduler::icu_bind_irq(Irq *irq_o, unsigned irqnum) +{ + if (irqnum > 0) + return commit_result(-L4_err::EInval); + + if (_irq) + _irq->unbind(); + + Irq_chip_soft::bind(irq_o, irqnum); + _irq = irq_o; + return commit_result(0); +} + +PUBLIC inline +void +Scheduler::trigger_hotplug_event() +{ + if (_irq) + _irq->hit(0); +} + +PUBLIC +L4_msg_tag +Scheduler::kinvoke(L4_obj_ref ref, Mword rights, Syscall_frame *f, + Utcb const *iutcb, Utcb *outcb) +{ + switch (f->tag().proto()) + { + case L4_msg_tag::Label_irq: + return Icu::icu_invoke(ref, rights, f, iutcb,outcb); + case L4_msg_tag::Label_scheduler: + break; + default: + return commit_result(-L4_err::EBadproto); + } + + switch (iutcb->values[0]) + { + case Info: return sys_info(rights, f, iutcb, outcb); + case Run_thread: return sys_run(rights, f, iutcb); + case Idle_time: return sys_idle_time(rights, f, outcb); + default: return commit_result(-L4_err::ENosys); + } +} diff --git a/kernel/fiasco/src/kern/sender.cpp b/kernel/fiasco/src/kern/sender.cpp new file mode 100644 index 00000000..f1abe782 --- /dev/null +++ b/kernel/fiasco/src/kern/sender.cpp @@ -0,0 +1,166 @@ +INTERFACE: + +#include "l4_types.h" +#include "prio_list.h" + +class Receiver; + +/** A sender. This is a role class, so real senders need to inherit from it. + */ +class Sender : private Prio_list_elem +{ + MEMBER_OFFSET(); +public: + /** Receiver-ready callback. Receivers make sure to call this + function on waiting senders when they get ready to receive a + message from that sender. Senders need to overwrite this interface. */ + virtual void ipc_send_msg(Receiver *) = 0; + virtual void ipc_receiver_aborted() = 0; + virtual void modify_label(Mword const *todo, int cnt) = 0; + +protected: + Iteratable_prio_list *_wq; + +private: + + friend class Jdb; + friend class Jdb_thread_list; +}; + + +IMPLEMENTATION: + +#include + +#include "atomic.h" +#include "cpu_lock.h" +#include "lock_guard.h" +#include "mem.h" + +// +// state requests/manipulation +// + +/** Optimized constructor. This constructor assumes that the object storage + is zero-initialized. + @param id user-visible thread ID of the sender + @param ignored an integer argument. The value doesn't matter and + is used just to distinguish this constructor from the + default one. + */ +PROTECTED inline +explicit +Sender::Sender (int /*ignored*/) +: _wq(0) +{} + + +/** Current receiver. + @return receiver this sender is currently trying to send a message to. + */ +PUBLIC inline +Iteratable_prio_list * +Sender::wait_queue() const +{ return _wq; } + +/** Set current receiver. + @param receiver the receiver we're going to send a message to + */ +PUBLIC inline +void +Sender::set_wait_queue(Iteratable_prio_list *wq) +{ + _wq = wq; +} + +PUBLIC inline +unsigned short Sender::sender_prio() +{ + return Prio_list_elem::prio(); +} + +/** Sender in a queue of senders?. + @return true if sender has enqueued in a receiver's list of waiting + senders + */ +PUBLIC inline +bool +Sender::in_sender_list() const +{ + return Prio_list_elem::in_list(); +} + +PUBLIC inline +bool +Sender::is_head_of(Prio_list const *l) const +{ return l->first() == this; } + + +PUBLIC static inline +Sender * +Sender::cast(Prio_list_elem *e) +{ return static_cast(e); } + + +PUBLIC +//PROTECTED inline NEEDS [, "cpu_lock.h", "lock_guard.h", +// Sender::replace_node, Sender::tree_insert] +void Sender::sender_enqueue(Prio_list *head, unsigned short prio) +{ + assert(prio < 256); + + Lock_guard guard (&cpu_lock); + head->insert(this, prio); +} + +//PUBLIC inline NEEDS [, "cpu_lock.h", "lock_guard.h", +// Sender::remove_tree_elem, Sender::remove_head] +PUBLIC template< typename P_LIST > +void Sender::sender_dequeue(P_LIST list) +{ + + if (!in_sender_list()) + return; + + Lock_guard guard (&cpu_lock); + list->dequeue(this); +} + +// An special version, only to remove the head +// this is neccessary if the receiver removes the old know head +// after an unsuccessful ipc_receiver_ready. +PUBLIC template< typename P_LIST > +void Sender::sender_dequeue_head(P_LIST list) +{ + + if (!in_sender_list()) + return; + + Lock_guard guard (&cpu_lock); + + if (this == list->head()) + list->dequeue(this); +} + +PROTECTED template +void Sender::sender_update_prio(P_LIST list, unsigned short newprio) +{ + if(EXPECT_FALSE(sender_prio() == newprio)) + return; + + Lock_guard guard (&cpu_lock); + + if (!in_sender_list()) + return; + + sender_dequeue(list); + sender_enqueue(list, newprio); +} + +/** Constructor. + @param id user-visible thread ID of the sender + */ +PROTECTED inline +Sender::Sender() +{} + diff --git a/kernel/fiasco/src/kern/setchecksum.c b/kernel/fiasco/src/kern/setchecksum.c new file mode 100644 index 00000000..a2f4510f --- /dev/null +++ b/kernel/fiasco/src/kern/setchecksum.c @@ -0,0 +1,96 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +static void usage(void) +{ + printf("Usage: set_checksum \n"); +} + +static int fd; +static void *image; +static struct stat stats; +static char const * const match = "FIASCOCHECKSUM="; + + +int main(int argc, char *argv[]) +{ + + void *base; + uint32_t volatile *chksum; + unsigned long left; + + if (argc!=4) + { + usage(); + exit(1); + } + + fd = open(argv[1], O_RDWR | O_EXCL); + if (fd<0) + { + fprintf(stderr, "error opening kernel image: '%s': ", argv[1]); + perror(""); + exit(1); + } + + if (fstat(fd, &stats) < 0) + { + perror("error: can't stat kernel image: "); + exit(1); + } + + image = mmap(NULL, stats.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (image == MAP_FAILED) + { + perror("error: can't mmap kernel image: "); + exit(1); + } + + base = image; + left = stats.st_size; + while ((base = memchr(base, match[0], left))) + { + if (memcmp(match, base, strlen(match) + 1) == 0) + break; + else + base = (char*)base + 1; + + left = stats.st_size - (base - image); + } + + if (!base) + { + fprintf(stderr,"error: magic string '%s' not found in kernel image\n", match); + return 2; + } + + base = (char*)base + strlen(match) + 1; + + chksum = base; + *chksum = strtoul(argv[2], NULL, 0); + *(chksum + 1) = strtoul(argv[3], NULL, 0); + + if (munmap(image, stats.st_size) < 0) + { + perror("error: can't unmap kernel image: "); + exit(1); + } + + + if (close(fd) < 0) + { + fprintf(stderr, "error closing kernel image: '%s': ", argv[1]); + perror(""); + exit(2); + } + return 0; +} diff --git a/kernel/fiasco/src/kern/sigma0_task-io.cpp b/kernel/fiasco/src/kern/sigma0_task-io.cpp new file mode 100644 index 00000000..47bf2ba8 --- /dev/null +++ b/kernel/fiasco/src/kern/sigma0_task-io.cpp @@ -0,0 +1,15 @@ +IMPLEMENTATION [io]: + +PUBLIC +bool +Sigma0_task::v_fabricate(Io_space::Addr address, Io_space::Phys_addr* phys, + Io_space::Size* size, unsigned* attribs = 0) +{ + // special-cased because we don't do lookup for sigma0 + *phys = address.trunc(Io_space::Size(Io_space::Map_superpage_size)); + *size = Io_space::Size(Io_space::Map_superpage_size); + if (attribs) + *attribs = Io_space::Page_writable + | Io_space::Page_user_accessible; + return true; +} diff --git a/kernel/fiasco/src/kern/sigma0_task.cpp b/kernel/fiasco/src/kern/sigma0_task.cpp new file mode 100644 index 00000000..95cb1855 --- /dev/null +++ b/kernel/fiasco/src/kern/sigma0_task.cpp @@ -0,0 +1,40 @@ +INTERFACE: + +#include "task.h" + +class Sigma0_task : public Task +{ +public: + explicit Sigma0_task(Ram_quota *q) : Task(q) {} + bool is_sigma0() const { return true; } + Address virt_to_phys_s0(void *virt) const { return (Address)virt; } +}; + + +IMPLEMENTATION: + +PUBLIC +bool +Sigma0_task::v_fabricate(Mem_space::Vaddr address, + Mem_space::Phys_addr* phys, Mem_space::Size* size, + unsigned* attribs = 0) +{ + // special-cased because we don't do ptab lookup for sigma0 + *size = Mem_space::has_superpages() + ? Mem_space::Size(Config::SUPERPAGE_SIZE) + : Mem_space::Size(Config::PAGE_SIZE); + *phys = address.trunc(*size); + + if (attribs) + *attribs = Mem_space::Page_writable + | Mem_space::Page_user_accessible + | Mem_space::Page_cacheable; + + return true; +} + +PUBLIC inline virtual +Page_number +Sigma0_task::map_max_address() const +{ return Page_number::create(1UL << (MWORD_BITS - Mem_space::Page_shift)); } + diff --git a/kernel/fiasco/src/kern/space-io.cpp b/kernel/fiasco/src/kern/space-io.cpp new file mode 100644 index 00000000..f37b9f90 --- /dev/null +++ b/kernel/fiasco/src/kern/space-io.cpp @@ -0,0 +1,9 @@ +INTERFACE [io]: + +#include "config.h" +#include "io_space.h" +#include "l4_types.h" + +EXTENSION class Space : public Generic_io_space +{}; + diff --git a/kernel/fiasco/src/kern/space.cpp b/kernel/fiasco/src/kern/space.cpp new file mode 100644 index 00000000..b330f74a --- /dev/null +++ b/kernel/fiasco/src/kern/space.cpp @@ -0,0 +1,153 @@ +INTERFACE [!io]: + +class Io_space; + +//-------------------------------------------------------------------------- +INTERFACE [io]: + +#include "config.h" +#include "io_space.h" +#include "l4_types.h" + +class Space; + +/** Global definition of Io_space for map_util stuff. */ +typedef Generic_io_space Io_space; + +//-------------------------------------------------------------------------- +INTERFACE: + +#include "mem_space.h" +#include "member_offs.h" +#include "obj_space.h" +#include "spin_lock.h" +#include "ref_obj.h" +#include "slab_cache.h" +#include + +class Ram_quota; +class Context; +class Kobject; + +class Space; + +typedef Generic_obj_space Obj_space; + +class Space +: public Ref_cnt_obj, + public Mem_space, + public Generic_obj_space +{ + MEMBER_OFFSET(); + friend class Jdb_space; + +public: + explicit Space(Ram_quota *q) : Mem_space(q) {} + virtual ~Space() = 0; + + enum State + { // we must use values with the two lest significant bits == 0 + Starting = 0x00, + Ready = 0x08, + In_deletion = 0x10 + }; + + struct Ku_mem : public cxx::S_list_item + { + User::Ptr u_addr; + void *k_addr; + unsigned size; + + static Slab_cache *a; + + void *operator new (size_t, Ram_quota *q) throw() + { return a->q_alloc(q); } + + void free(Ram_quota *q) throw() + { a->q_free(q, this); } + + template + T *kern_addr(Smart_ptr ua) const + { + typedef Address A; + return (T*)((A)ua.get() - (A)u_addr.get() + (A)k_addr); + } + }; + +protected: + Space(Ram_quota *q, Mem_space::Dir_type* pdir) : Mem_space(q, pdir) {} + +private: + void switchin_ldt() const; + +protected: + typedef cxx::S_list Ku_mem_list; + Ku_mem_list _ku_mem; +}; + + +//--------------------------------------------------------------------------- +IMPLEMENTATION: + +#include "atomic.h" +#include "kdb_ke.h" +#include "lock_guard.h" +#include "config.h" +#include "globalconfig.h" +#include "l4_types.h" + +// +// class Space +// + +PUBLIC inline Ram_quota * Space::ram_quota() const +{ return Mem_space::ram_quota(); } + +IMPLEMENT inline Space::~Space() {} + +PUBLIC +Space::Ku_mem const * +Space::find_ku_mem(User::Ptr p, unsigned size) +{ + Address const pa = (Address)p.get(); + + // alignment check + if (EXPECT_FALSE(pa & (sizeof(double) - 1))) + return 0; + + // overflow check + if (EXPECT_FALSE(pa + size < pa)) + return 0; + + for (Ku_mem_list::Const_iterator f = _ku_mem.begin(); f != _ku_mem.end(); ++f) + { + Address const a = (Address)f->u_addr.get(); + if (a <= pa && (a + f->size) >= (pa + size)) + return *f; + } + + return 0; +} + +PUBLIC inline +void +Space::switchin_context(Space *from) +{ + assert_kdb (this); + if (this != from) + { + Mem_space::switchin_context(from); + switchin_ldt(); + } +} + + +PUBLIC static inline +bool +Space::is_user_memory(Address address, Mword len) +{ + return address < Mem_layout::User_max + && address < address + len // prevent overflow + && address + len <= Mem_layout::User_max; +} + diff --git a/kernel/fiasco/src/kern/sparc/Makerules.KERNEL b/kernel/fiasco/src/kern/sparc/Makerules.KERNEL new file mode 100644 index 00000000..38e155f6 --- /dev/null +++ b/kernel/fiasco/src/kern/sparc/Makerules.KERNEL @@ -0,0 +1,27 @@ +# -*- makefile -*- + +exception.o: $(TCBOFFSET) +phys_mem.o: $(TCBOFFSET) + +# Add future prerequisites somewhere among the list of libraries. +# You really should not have to add anything in the $(LD) line. + +$(KERNEL).image: $(srcdir)/kernel.sparc.ld $(CRT0) $(OBJ_KERNEL) $(JDB) $(LIBK) $(LIBDISASM) libdrivers.a $(ABI) $(LIBUART) $(CXXLIB) $(MINILIBC) libgluedriverslibc.a + $(LINK_MESSAGE) + $(VERBOSE)$(LD) $(LDFLAGS) -N -defsym kernel_load_addr=$(CONFIG_KERNEL_LOAD_ADDR) \ + -T $< -o $@ $(filter-out $<,$+) $(LIBGCC) + +$(KERNEL): $(KERNEL).image + $(LINK_MESSAGE) + $(VERBOSE)$(STRIP) $< -o $@ + chmod 755 $@ + +# $(OBJCOPY) -O binary $@ fiasco + +Symbols: $(KERNEL).image + $(NM) $(KERNEL).image | c++filt | sort > $@.new + mv $@.new $@ + chmod 755 $@ + + +clean-KERNEL: diff --git a/kernel/fiasco/src/kern/sparc/boot_info-sparc.cpp b/kernel/fiasco/src/kern/sparc/boot_info-sparc.cpp new file mode 100644 index 00000000..9cc170ef --- /dev/null +++ b/kernel/fiasco/src/kern/sparc/boot_info-sparc.cpp @@ -0,0 +1,28 @@ +INTERFACE [sparc]: + +#include "types.h" +#include "sparc_types.h" + +EXTENSION class Boot_info +{ + public: + /** + * Return memory-mapped base address of uart/pic + */ + static Address uart_base(); + static Address pic_base(); +}; + + +//------------------------------------------------------------------------------ +IMPLEMENTATION [sparc]: + +#include "boot_info.h" +#include + +IMPLEMENT static +void Boot_info::init() +{ +} + + diff --git a/kernel/fiasco/src/kern/sparc/boot_uart_init.cpp b/kernel/fiasco/src/kern/sparc/boot_uart_init.cpp new file mode 100644 index 00000000..39e98e36 --- /dev/null +++ b/kernel/fiasco/src/kern/sparc/boot_uart_init.cpp @@ -0,0 +1,17 @@ +IMPLEMENTATION [sparc && serial]: + +#include "kernel_console.h" +#include "kernel_uart.h" +#include "static_init.h" + +STATIC_INITIALIZER_P(boot_console_init, EARLY_INIT_PRIO); + +static void boot_console_init() +{ + Kconsole::init(); + Kernel_uart::init(); + Console::stdout = Kernel_uart::uart(); + Console::stderr = Console::stdout; + Console::stdin = Console::stdout; +} + diff --git a/kernel/fiasco/src/kern/sparc/bootstrap.cpp b/kernel/fiasco/src/kern/sparc/bootstrap.cpp new file mode 100644 index 00000000..2782f5d1 --- /dev/null +++ b/kernel/fiasco/src/kern/sparc/bootstrap.cpp @@ -0,0 +1,34 @@ +INTERFACE [sparc]: +#include "types.h" +#include "initcalls.h" + +IMPLEMENTATION [sparc]: +#include "uart.h" +#include "boot_info.h" +#include "terminate.h" + +#include +#include +#include + +//XXX cbass: implement me +extern "C" void __attribute__ ((noreturn)) +_exit(int) +{ + printf("Exiting\n"); + while(1){}; +} + +extern "C" int main(void); + +extern "C" FIASCO_INIT +int bootstrap_main(void * /* r3 */, Address prom_ptr /* r4 */) +{ + //Boot_info::set_prom(prom_ptr); + atexit(&static_destruction); + static_construction(); + puts("Bootstrapped"); + terminate(main()); + return 0; +} + diff --git a/kernel/fiasco/src/kern/sparc/bsp/leon3/Kconfig b/kernel/fiasco/src/kern/sparc/bsp/leon3/Kconfig new file mode 100644 index 00000000..e98a97d8 --- /dev/null +++ b/kernel/fiasco/src/kern/sparc/bsp/leon3/Kconfig @@ -0,0 +1,3 @@ +# PF: LEON3 +# PFDESCR: LEON3 platform (testing) +# PFDEPENDS: SPARC diff --git a/kernel/fiasco/src/kern/sparc/bsp/leon3/Modules b/kernel/fiasco/src/kern/sparc/bsp/leon3/Modules new file mode 100644 index 00000000..d9c77011 --- /dev/null +++ b/kernel/fiasco/src/kern/sparc/bsp/leon3/Modules @@ -0,0 +1,11 @@ +# vim:set ft=make: + +CONFIG_KERNEL_LOAD_ADDR := 0x60000000 + +PREPROCESS_PARTS += uart_leon3 +config_IMPL += config-sparc-leon3 +uart_IMPL += uart-leon3 +pic_IMPL += pic-sparc-leon3 +boot_info_IMPL += boot_info-sparc-leon3 +clock_IMPL += clock-generic +timer_tick_IMPL += timer_tick-single-vector timer_tick-sparc diff --git a/kernel/fiasco/src/kern/sparc/bsp/leon3/boot_info-sparc-leon3.cpp b/kernel/fiasco/src/kern/sparc/bsp/leon3/boot_info-sparc-leon3.cpp new file mode 100644 index 00000000..32bf7f6f --- /dev/null +++ b/kernel/fiasco/src/kern/sparc/bsp/leon3/boot_info-sparc-leon3.cpp @@ -0,0 +1,21 @@ +IMPLEMENTATION[sparc && leon3]: + +#include + +IMPLEMENT static +Address Boot_info::uart_base() +{ + return ~0; +} + +IMPLEMENT static +Address Boot_info::pic_base() +{ + return ~0; +} + +PUBLIC static +Address Boot_info::mbar() +{ + return ~0; +} diff --git a/kernel/fiasco/src/kern/sparc/bsp/leon3/config-sparc-leon3.cpp b/kernel/fiasco/src/kern/sparc/bsp/leon3/config-sparc-leon3.cpp new file mode 100644 index 00000000..33978c76 --- /dev/null +++ b/kernel/fiasco/src/kern/sparc/bsp/leon3/config-sparc-leon3.cpp @@ -0,0 +1,11 @@ +INTERFACE [sparc && leon3]: + +#define TARGET_NAME "LEON3" + +EXTENSION class Config +{ +public: + enum + { + }; +}; diff --git a/kernel/fiasco/src/kern/sparc/bsp/leon3/pic-sparc-leon3.cpp b/kernel/fiasco/src/kern/sparc/bsp/leon3/pic-sparc-leon3.cpp new file mode 100644 index 00000000..24a64b0c --- /dev/null +++ b/kernel/fiasco/src/kern/sparc/bsp/leon3/pic-sparc-leon3.cpp @@ -0,0 +1,322 @@ +INTERFACE [sparc && leon3]: + +#include "types.h" + +class Irq_chip_icu; + +EXTENSION class Pic +{ +private: + /** Pic interrupt control registers (incomplete) */ + ///+0x00: Peripheral Interrupt Mask Register + static Address per_mask() { return _pic_base; } + ///+0x04: Peripheral Priority & HI/LO Select Register1 + static Address per_prio1() { return _pic_base + 0x04; } + ///+0x08: Peripheral Priority & HI/LO Select Register2 + static Address per_prio2() { return _pic_base + 0x08; } + ///+0x0c: Peripheral Priority & HI/LO Select Register3 + static Address per_prio3() { return _pic_base + 0x0c; } + ///+0x10: External Enable & External Types Register + static Address ext() { return _pic_base + 0x10; } + ///+0x14: Critical Priority & Main Inter. Mask Register + static Address main_mask() { return _pic_base + 0x14; } + ///+0x18: Main Inter. Priority1 + static Address main_prio1() { return _pic_base + 0x18; } + ///+0x1c: Main Inter. Priority2 + static Address main_prio2() { return _pic_base + 0x1c; } + ///+0x24: PerStat, MainStat, CritStat Encoded Registers + static Address stat() { return _pic_base + 0x24; } + + + /** Interrupt lines (sdma is missing) */ + enum Pic_lines + { + IRQ_CRIT = 0x0, ///Critical line + IRQ_MAIN = 0x1, ///Main line + IRQ_PER = 0x2, ///Periphal line + IRQ_SHIFT = 0x4 + }; + + enum Pic_num_per_line + { + NUM_CRIT = 4, + NUM_MAIN = 17, + NUM_PER = 24, + }; + + /** Interrupt senses */ + enum Pic_sense + { + SENSE_LEVEL_HIGH = 0, + SENSE_EDGE_RISING = 1, + SENSE_EDGE_FALLING = 2, + SENSE_LEVEL_LOW = 3 + }; + + static Address _pic_base; + +public: + enum { IRQ_MAX = (IRQ_PER << IRQ_SHIFT) + NUM_PER}; + enum { No_irq_pending = ~0U }; + + static Irq_chip_icu *main; +}; + +//------------------------------------------------------------------------------ +IMPLEMENTATION [sparc && leon3]: + +#include "boot_info.h" +#include "io.h" +#include "irq.h" +#include "irq_chip_generic.h" +#include "irq_mgr.h" +#include "panic.h" +#include "sparc_types.h" + +#include +#include + +Irq_chip_icu *Pic::main; + +class Chip : public Irq_chip_gen +{ +public: + Chip() : Irq_chip_gen(Pic::IRQ_MAX) {} + unsigned set_mode(Mword, unsigned) { return Irq_base::Trigger_level; } + void set_cpu(Mword, unsigned) {} +}; + +PUBLIC +void +Chip::mask(Mword) +{ + assert(cpu_lock.test()); + //Pic::disable_locked(irq); +} + +PUBLIC +void +Chip::ack(Mword) +{ + assert(cpu_lock.test()); + //Pic::acknowledge_locked(irq); +} + +PUBLIC +void +Chip::mask_and_ack(Mword) +{ + assert(cpu_lock.test()); + //Pic::disable_locked(irq()); + //Pic::acknowledge_locked(irq()); +} + +PUBLIC +void +Chip::unmask(Mword) +{ + assert(cpu_lock.test()); + //Pic::enable_locked(irq()); +} + +IMPLEMENT FIASCO_INIT +void +Pic::init() +{ +} + +//------------------------------------------------------------------------------ +/** + * Irq number translations + */ +PUBLIC static inline +unsigned +Pic::irq_num(unsigned line, unsigned pic_num) +{ return (line << IRQ_SHIFT) | pic_num; } + + +PUBLIC static +int +Pic::get_irq_num(const char *name, const char *type) +{ + (void)name; (void)type; + return -1; +} + +PRIVATE static inline NEEDS[] +unsigned +Pic::pic_line(unsigned irq_num) +{ + unsigned line = irq_num >> IRQ_SHIFT; + assert(line < 3); + return line; +} + +PRIVATE static inline NEEDS[Pic::pic_line] +unsigned +Pic::pic_num(unsigned irq_num) +{ + unsigned line = pic_line(irq_num); + unsigned num = irq_num & ~(~0U << IRQ_SHIFT); + + switch(line) + { + case IRQ_CRIT: + assert(num < NUM_CRIT); + break; + case IRQ_MAIN: + assert(num < NUM_MAIN); + break; + default: + assert(num < NUM_PER); + } + + return num; +} + + +//------------------------------------------------------------------------------- +/** + * Interface implementation + */ +IMPLEMENT inline +void +Pic::block_locked (unsigned irq_num) +{ + disable_locked(irq_num); +} + +IMPLEMENT inline NEEDS["io.h", Pic::pic_line, Pic::pic_num, Pic::set_stat_msb] +void +Pic::acknowledge_locked(unsigned irq_num) +{ + unsigned line = pic_line(irq_num); + unsigned num = pic_num(irq_num); + + if((line == IRQ_MAIN && (num >= 1 || num <= 3)) || + (line == IRQ_CRIT && num == 0)) + Io::set(1U << (27 - num), ext()); + + set_stat_msb(irq_num); +} + +PRIVATE static inline +void +Pic::dispatch_mask(unsigned irq_num, Address *addr, unsigned *bit_offs) +{ + switch(pic_line(irq_num)) + { + case IRQ_MAIN: + *addr = main_mask(); + *bit_offs = 16; + break; + case IRQ_PER: + *addr = per_mask(); + *bit_offs = 31; + break; + default: + panic("%s: Cannot handle IRQ %u", __PRETTY_FUNCTION__, irq_num); + } +} + +PRIVATE static inline +void +Pic::set_stat_msb(unsigned irq_num) +{ + switch(pic_line(irq_num)) + { + case IRQ_MAIN: + Io::set(0x00200000, stat()); + break; + case IRQ_PER: + Io::set(0x20000000, stat()); + break; + default: + panic("CRIT not implemented"); + } +} + +IMPLEMENT inline NEEDS[Pic::pic_num, Pic::dispatch_mask] +void +Pic::disable_locked (unsigned irq_num) +{ + Address addr; + unsigned bit_offs; + dispatch_mask(irq_num, &addr, &bit_offs); + Io::set(1U << (bit_offs - pic_num(irq_num)), addr); +} + +IMPLEMENT inline NEEDS[Pic::dispatch_mask] +void +Pic::enable_locked (unsigned irq_num, unsigned /*prio*/) +{ + Address addr; + unsigned bit_offs; + dispatch_mask(irq_num, &addr, &bit_offs); + + Io::clear(1U << (bit_offs - pic_num(irq_num)), addr); +} + +PUBLIC static inline NEEDS["panic.h"] +unsigned +Pic::nr_irqs() +{ return IRQ_MAX; } + +PRIVATE static inline +Unsigned32 +Pic::pending_per(Unsigned32 state) +{ + Unsigned32 irq = state >> 24 & 0x1f; //5 bit + + if(irq == 0) + panic("No support for bestcomm interrupt, yet\n"); + + return irq_num(IRQ_PER, irq); +} + +PRIVATE static inline +Unsigned32 +Pic::pending_main(Unsigned32 state) +{ + Unsigned32 irq = state >> 16 & 0x1f; + + //low periphal + if(irq == 4) + return pending_per(state); + + return irq_num(IRQ_MAIN, irq); +} + +PUBLIC static inline NEEDS[Pic::pending_main, Pic::pending_per] +Unsigned32 +Pic::pending() +{ + Unsigned32 irq = No_irq_pending; + return irq; +} + +/** + * disable interrupt lines [0-3] + */ +IMPLEMENT inline +Pic::Status +Pic::disable_all_save() +{ + Status s; + return s; +} + +IMPLEMENT inline +void +Pic::restore_all(Status s) +{ + Io::write(s, ext()); +} + +// ------------------------------------------------------------------------ +IMPLEMENTATION [debug && sparc && leon3]: + +PUBLIC +char const * +Chip::chip_type() const +{ return "HW Mpc52xx IRQ"; } diff --git a/kernel/fiasco/src/kern/sparc/config-sparc.cpp b/kernel/fiasco/src/kern/sparc/config-sparc.cpp new file mode 100644 index 00000000..a5914653 --- /dev/null +++ b/kernel/fiasco/src/kern/sparc/config-sparc.cpp @@ -0,0 +1,51 @@ +INTERFACE [sparc]: + +#include + +EXTENSION class Config +{ +public: + enum + { + // cannot access user memory directly + Access_user_mem = No_access_user_mem, + + PAGE_SHIFT = ARCH_PAGE_SHIFT, + PAGE_SIZE = 1 << PAGE_SHIFT, + PAGE_MASK = ~(PAGE_SIZE - 1), + + SUPERPAGE_SHIFT = 22, + SUPERPAGE_SIZE = 1 << SUPERPAGE_SHIFT, + SUPERPAGE_MASK = ~(SUPERPAGE_SIZE -1), + hlt_works_ok = 1, + Irq_shortcut = 0, //TODO: set + }; + + enum + { + Kmem_size = 4*1024*1024, //4 MB + }; + + enum + { + Scheduler_one_shot = 0, + Scheduler_granularity = 1000UL, + Default_time_slice = 10 * Scheduler_granularity, + }; + + static unsigned const default_console_uart = 3; + static unsigned const default_console_uart_baudrate = 115200; + static const char char_micro; +}; + + +//--------------------------------------------------------------------------- +IMPLEMENTATION [sparc]: + +char const Config::char_micro = '\265'; +const char *const Config::kernel_warn_config_string = 0; + +IMPLEMENT FIASCO_INIT +void +Config::init_arch() +{} diff --git a/kernel/fiasco/src/kern/sparc/context-sparc.cpp b/kernel/fiasco/src/kern/sparc/context-sparc.cpp new file mode 100644 index 00000000..e73da5da --- /dev/null +++ b/kernel/fiasco/src/kern/sparc/context-sparc.cpp @@ -0,0 +1,48 @@ +IMPLEMENTATION [sparc]: + +/** Note: TCB pointer is located in sprg1 */ + +/* +#include +#include + +#include "l4_types.h" +#include "cpu_lock.h" +#include "lock_guard.h" +#include "space.h" +#include "thread_state.h" +*/ + +#include "kmem.h" +#include "utcb_support.h" + +IMPLEMENT inline +void +Context::spill_user_state() +{} + +IMPLEMENT inline +void +Context::fill_user_state() +{} + +PROTECTED inline void Context::arch_setup_utcb_ptr() {} + +IMPLEMENT inline +void +Context::switch_cpu(Context *t) +{ + (void)t; +} + +/** Thread context switchin. Called on every re-activation of a + thread (switch_exec()). This method is public only because it is + called by an ``extern "C"'' function that is called + from assembly code (call_switchin_context). + */ + +IMPLEMENT +void Context::switchin_context(Context *from) +{ + (void)from; +} diff --git a/kernel/fiasco/src/kern/sparc/continuation-sparc.cpp b/kernel/fiasco/src/kern/sparc/continuation-sparc.cpp new file mode 100644 index 00000000..cba5bc83 --- /dev/null +++ b/kernel/fiasco/src/kern/sparc/continuation-sparc.cpp @@ -0,0 +1,82 @@ +INTERFACE[sparc]: + +#include "entry_frame.h" +#include "member_offs.h" +#include "types.h" + +class Continuation +{ + MEMBER_OFFSET(); + +private: + Address _ip; + Mword _psr; + +public: + Continuation() : _ip(~0UL) {} + + struct User_return_frame + { + Mword usp; + Mword ulr; + Mword km_lr; + Mword psr; + Mword pc; + }; + + bool valid() const + { return _ip != ~0UL; } + + Address ip() const { return _ip; } + void ip(Address ip) { _ip = ip; } + + Mword flags(Return_frame const *) const { return _psr; } + void flags(Return_frame *, Mword psr) { _psr = psr; } + + Mword sp(Return_frame const *o) const { return o->usp; } + void sp(Return_frame *o, Mword sp) { o->usp = sp; } + + void save(Return_frame const *regs) + { + _ip = regs->ip(); + //_psr = regs->psr; + } + + void activate(Return_frame *regs, void *cont_func) + { + save(regs); + (void)cont_func; + //regs->pc = Mword(cont_func); + //regs->psr &= ...; + } + + void set(Return_frame *dst, User_return_frame const *src) + { + dst->usp = src->usp; + dst->ulr = src->ulr; + //dst->km_lr = src->km_lr; + _ip = src->pc; + _psr = src->psr; + } + + void get(User_return_frame *dst, Return_frame const *src) const + { + dst->usp = src->usp; + dst->ulr = src->ulr; + //dst->km_lr = src->km_lr; + dst->pc = _ip; + dst->psr = _psr; + } + + void clear() { _ip = ~0UL; } + + void restore(Return_frame *regs) + { + //regs->pc = _ip; + // regs->psr = _psr; + (void)regs; + clear(); + } + +}; + diff --git a/kernel/fiasco/src/kern/sparc/cpu-sparc.cpp b/kernel/fiasco/src/kern/sparc/cpu-sparc.cpp new file mode 100644 index 00000000..fce30900 --- /dev/null +++ b/kernel/fiasco/src/kern/sparc/cpu-sparc.cpp @@ -0,0 +1,167 @@ +INTERFACE [sparc]: + +#include "per_cpu_data.h" +#include "types.h" + +EXTENSION class Cpu +{ +public: + void init(bool is_boot_cpu = false); + static void early_init(); + + static Per_cpu cpus; + static Cpu *boot_cpu() { return _boot_cpu; } + + Cpu(unsigned cpu) { set_id(cpu); } + +private: + static Cpu *_boot_cpu; + unsigned _phys_id; + static unsigned long _ns_per_cycle; + +}; + +namespace Segment +{ + enum Attribs_enum + { + Ks = 1UL << 30, + Kp = 1UL << 29, + N = 1UL << 28, + Default_attribs = Kp //Ks | Kp, + }; +}; +//------------------------------------------------------------------------------ +IMPLEMENTATION [sparc]: + +#include "panic.h" +#include "boot_info.h" +#include "psr.h" + +#include + +DEFINE_PER_CPU Per_cpu Cpu::cpus(true); +Cpu *Cpu::_boot_cpu; +unsigned long Cpu::_ns_per_cycle; + +IMPLEMENT +void +Cpu::init(bool is_boot_cpu) +{ + if (is_boot_cpu) + { + _boot_cpu = this; + set_online(1); + } + _phys_id = 0; //Proc::cpu_id(); + _ns_per_cycle = 0; //1000000000 / Boot_info::get_time_base(); + //printf("Timebase: %lu\n", Boot_info::get_time_base()); +} + +IMPLEMENT +void +Cpu::early_init() +{ +} + +PUBLIC static inline +Mword +Cpu::read_vsid(unsigned sr = 0) +{ + Mword vsid; + (void)sr; + + return (vsid & 0xffffff); +} + +/* set segment register 0-15 */ +PUBLIC static inline //NEEDS["paging.h"] +void +Cpu::set_vsid(Mword vsid) +{ + vsid |= Segment::Default_attribs; +} + +PUBLIC static inline +Mword +Cpu::stack_align(Mword stack) +{ return stack & ~0xf; } + +PUBLIC static inline +bool +Cpu::have_superpages() +{ return true; } + +//------------------------------------------------------------------------------ +/* Time functions */ + +/** + * Read time base registers + */ +PUBLIC static inline +Unsigned64 +Cpu::rdtsc() +{ + Unsigned32 tb_upper, tb_lower; + Unsigned64 tb; + tb = tb_upper; + return (tb << 32) | tb_lower; +} + +PUBLIC static inline +void +Cpu::busy_wait_ns(Unsigned64 ns) +{ + Unsigned64 stop = rdtsc() + ns_to_tsc(ns); + + while(rdtsc() < stop) + ; +} + +PUBLIC static inline +Unsigned64 +Cpu::ns_to_tsc(Unsigned64 ns) +{ + return ns / _ns_per_cycle; +} + +PUBLIC static inline +Unsigned64 +Cpu::tsc_to_ns(Unsigned64 tsc) +{ + return tsc * _ns_per_cycle; +} + +PUBLIC static inline +Unsigned32 +Cpu::get_scaler_tsc_to_ns() +{ return 0; } + +PUBLIC static inline +Unsigned32 +Cpu::get_scaler_tsc_to_us() +{ return 0; } + +PUBLIC static inline +Unsigned32 +Cpu::get_scaler_ns_to_tsc() +{ return 0; } + +PUBLIC static inline +bool +Cpu::tsc() +{ return 0; } + +//------------------------------------------------------------------------------ +/* Unimplemented */ + +PUBLIC static inline +void +Cpu::debugctl_enable() +{} + +PUBLIC static inline +void +Cpu::debugctl_disable() +{} + diff --git a/kernel/fiasco/src/kern/sparc/crt0.S b/kernel/fiasco/src/kern/sparc/crt0.S new file mode 100644 index 00000000..c1496b70 --- /dev/null +++ b/kernel/fiasco/src/kern/sparc/crt0.S @@ -0,0 +1,172 @@ +/* -*- c -*- */ + +#define TRAP(H) mov %psr, %l0; sethi %hi(H), %l4; jmp %l4+%lo(H); nop; +#define TRAP_ENTRY(H) rd %psr, %l0; b H; rd %wim, %l3; nop; +#define TRAP_ENTRY_INTERRUPT(int_level) \ + mov int_level, %l7; rd %psr, %l0; b _prom_leonbare_irq_entry; rd %wim, %l3; +#define BAD_TRAP ta 0; nop; nop; nop; + +.data +.globl _leon_traphandlers + +.section .text.init, "ax" +.global _start +.global __init_stack + +/* + * Trap handler table -> must be aligned to page size + * as specified by the SPARC v8 manual (p. 31). + */ +.align(0x1000) +_leon_traphandlers: + BAD_TRAP + BAD_TRAP + BAD_TRAP + BAD_TRAP + BAD_TRAP + TRAP(sparc_window_overflow); + TRAP(sparc_window_underflow); + BAD_TRAP + BAD_TRAP + BAD_TRAP + BAD_TRAP + BAD_TRAP + BAD_TRAP + BAD_TRAP + BAD_TRAP + BAD_TRAP + BAD_TRAP + +_start: + + rd %asr17, %g1 + + /* + * setup trap handler table + */ + sethi %hi(_leon_traphandlers), %g2 + wr %g2, %tbr + + /* the TBR setup above comes into effect three instructions from now! + * Right now, we assume that no trap occurs in between. + */ + + /* set stack pointer */ + sethi %hi(__init_stack), %sp + or %sp, %lo(__init_stack), %sp + + /* + * setup task with enough space for registers %l0-%l7 and %i0-%i7 + */ + sub %sp, 64, %sp + + sethi %hi(__init_stack), %fp + or %fp, %lo(__init_stack), %fp + + ba bootstrap_main + nop + + ta 0 +1: + ba 1b + + +.globl sparc_window_overflow +sparc_window_overflow: + mov %wim, %l3 /* need to determine new WIM */ + mov %g1, %l7 + srl %l3, 1, %g1 + + /* + * Find out if we are on LEON3 (PSR[24:27] == 3) + * or on LEON2. For LEON3, we can read the number of + * register windows from ASR17 + */ + mov %psr, %l4 + srl %l4, 24, %l4 + and %l4, 3, %l4 + subcc %l4, 3, %g0 + bne 1f + nop + + /* + * It's a LEON3 + */ + mov %asr17, %l4 + + /* calculate new WIM */ + and %l4, 0x1f, %l4 + sll %l3, %l4, %l4 + or %l4, %g1, %g1 + + /* + * The trick here is to move to a valid stack frame + * and store the register window contents there. + */ + save + mov %g1, %wim + nop; nop; nop + + std %l0, [%sp + 0]; + std %l2, [%sp + 8]; + std %l4, [%sp + 16]; + std %l6, [%sp + 24]; + std %i0, [%sp + 32]; + std %i2, [%sp + 40]; + std %i4, [%sp + 48]; + std %i6, [%sp + 56]; + + restore + mov %l7, %g1 + jmp %l1 + rett %l2 + +1: ta 0 + +.globl sparc_window_underflow +sparc_window_underflow: + mov %wim, %l3 /* need to determine new WIM */ + sll %l3, 1, %l4 + + /* Determine LEON version */ + mov %psr, %l5 + srl %l5, 24, %l5 + and %l5, 3, %l5 + subcc %l5, 3, %g0 + bne 1f + nop + + mov %asr17, %l5 + and %l5, 0x1f, %l5 + srl %l3, %l5, %l5 + or %l5, %l4, %l5 + mov %l5, %wim + nop; nop; nop + + restore ! Two restores to get into the + restore ! window to restore + ldd [%sp + 0], %l0; ! Restore window from the stack + ldd [%sp + 8], %l2; + ldd [%sp + 16], %l4; + ldd [%sp + 24], %l6; + ldd [%sp + 32], %i0; + ldd [%sp + 40], %i2; + ldd [%sp + 48], %i4; + ldd [%sp + 56], %i6; + save ! Get back to the trap window. + save + + jmp %l1 + rett %l2 + +1: ta 0 + + +.previous +.section .bss +.align 16 +.space 4096 + __init_stack: +.previous + + diff --git a/kernel/fiasco/src/kern/sparc/decrementer.cpp b/kernel/fiasco/src/kern/sparc/decrementer.cpp new file mode 100644 index 00000000..d2a8dfc6 --- /dev/null +++ b/kernel/fiasco/src/kern/sparc/decrementer.cpp @@ -0,0 +1,67 @@ +INTERFACE: + +#include "types.h" + +class Decrementer +{ +public: + void init(unsigned long interval); + inline void set(); + inline void enable(); + inline void disable(); + Decrementer() : _interval(0), _enabled(false) {} + +private: + Unsigned32 _interval; + bool _enabled; +}; + + +//------------------------------------------------------------------------------ +IMPLEMENTATION[sparc]: + +PUBLIC static inline +Decrementer * +Decrementer::d() +{ + static Decrementer _kernel_decr; + return &_kernel_decr; +} + +PRIVATE inline +void +Decrementer::set2(unsigned long interval) +{ + if (!_enabled && interval) + return; +} + +IMPLEMENT +void +Decrementer::init(unsigned long interval) +{ + _interval = interval; +} + +IMPLEMENT inline NEEDS[Decrementer::set2] +void +Decrementer::set() +{ + set2(_interval); +} + +IMPLEMENT inline +void +Decrementer::enable() +{ + _enabled = true; + set(); +} + +IMPLEMENT inline +void +Decrementer::disable() +{ + _enabled = false; + set2(0); +} diff --git a/kernel/fiasco/src/kern/sparc/dirq-sparc.cpp b/kernel/fiasco/src/kern/sparc/dirq-sparc.cpp new file mode 100644 index 00000000..c115158f --- /dev/null +++ b/kernel/fiasco/src/kern/sparc/dirq-sparc.cpp @@ -0,0 +1,31 @@ +IMPLEMENTATION [sparc]: +// --------------------------------------------------------------------------- +#include "std_macros.h" +#include "timer.h" +#include "processor.h" +#include "pic.h" + + +IMPLEMENTATION: + +#include "irq_chip_generic.h" +#include "irq.h" + +extern "C" +void irq_handler() +{ + Return_frame *rf = nonull_static_cast(current()->regs()); + + Mword irq; + + if(EXPECT_TRUE(rf->user_mode())) + rf->srr1 = Proc::wake(rf->srr1); + + irq = Pic::pending(); + if(EXPECT_FALSE(irq == Pic::No_irq_pending)) + return; + + Irq *i = nonull_static_cast(Pic::main->irq(irq)); +// Irq::log_irq(i, irq); + i->hit(); +} diff --git a/kernel/fiasco/src/kern/sparc/entry_frame-sparc.cpp b/kernel/fiasco/src/kern/sparc/entry_frame-sparc.cpp new file mode 100644 index 00000000..6cfc5a3f --- /dev/null +++ b/kernel/fiasco/src/kern/sparc/entry_frame-sparc.cpp @@ -0,0 +1,150 @@ +INTERFACE[sparc]: + +#include "types.h" + +EXTENSION class Syscall_frame +{ + public: + Mword r[30]; //{r0, r2, r3, ..., r10, r13 .., r31, ip + void dump() const; +}; + +EXTENSION class Return_frame +{ + public: + Mword xer; //+32 + Mword ctr; //+28 + Mword cr; //+24 + Mword srr1; //+20 + Mword srr0; //+16 + Mword ulr; //+12 + Mword usp; //+8 + Mword r11; //+4 --two scratch registers for exception entry + Mword r12; //0 + void dump(); + void dump_scratch(); + bool user_mode(); +}; + +//------------------------------------------------------------------------------ +IMPLEMENTATION [sparc]: + +#include "warn.h" +#include "psr.h" + +IMPLEMENT +void +Syscall_frame::dump() const +{ + printf("IP: %08lx\n", r[29]); + printf("R[%2d]: %08lx R[%2d]: %08lx R[%2d]: %08lx R[%2d]: %08lx R[%2d]: %08lx\n", + 0, r[0], 2, r[1], 3, r[2], 4, r[3], 5, r[4]); + printf("R[%2d]: %08lx R[%2d]: %08lx R[%2d]: %08lx R[%2d]: %08lx R[%2d]: %08lx\n", + 6, r[5], 7, r[6], 8, r[7], 9, r[8], 10, r[9]); +} + +PRIVATE +void +Return_frame::srr1_bit_scan() +{ + printf("SRR1 bits:"); + for(int i = 31; i >= 0; i--) + if(srr1 & (1 << i)) + printf(" %d", 31-i); + printf("\n"); +} + +IMPLEMENT +void +Return_frame::dump() +{ + printf("SRR0 %08lx SRR1 %08lx SP %08lx\n" + "LR %08lx CTR %08lx CR %08lx XER %08lx\n", + srr0, srr1, usp, ulr, ctr, cr, xer); + srr1_bit_scan(); +} + +IMPLEMENT +void +Return_frame::dump_scratch() +{ + printf("\nR[%2d]: %08lx\nR[%2d]: %08lx\n", 11, r11, 12, r12); +} + +IMPLEMENT inline +Mword +Return_frame::sp() const +{ + return Return_frame::usp; +} + +IMPLEMENT inline +void +Return_frame::sp(Mword _sp) +{ + Return_frame::usp = _sp; +} + +IMPLEMENT inline +Mword +Return_frame::ip() const +{ + return Return_frame::srr0; +} + +IMPLEMENT inline +void +Return_frame::ip(Mword _pc) +{ + Return_frame::srr0 = _pc; +} + +IMPLEMENT inline NEEDS ["psr.h"] +bool +Return_frame::user_mode() +{ + return 0; + /*return Msr::Msr_pr & srr1;*/ +} + +//--------------------------------------------------------------------------- +//TODO cbass: set registers properly +IMPLEMENT inline +Mword Syscall_frame::next_period() const +{ return false; } + +IMPLEMENT inline +void Syscall_frame::from(Mword id) +{ r[5] = id; /*r6*/ } + +IMPLEMENT inline +Mword Syscall_frame::from_spec() const +{ return r[5]; /*r6*/ } + + +IMPLEMENT inline +L4_obj_ref Syscall_frame::ref() const +{ return L4_obj_ref::from_raw(r[3]); /*r4*/ } + +IMPLEMENT inline +void Syscall_frame::ref(L4_obj_ref const &ref) +{ r[3] = ref.raw(); /*r4*/ } + +IMPLEMENT inline +L4_timeout_pair Syscall_frame::timeout() const +{ return L4_timeout_pair(r[4]); /*r5*/ } + +IMPLEMENT inline +void Syscall_frame::timeout(L4_timeout_pair const &to) +{ r[4] = to.raw(); /*r5*/ } + +IMPLEMENT inline Utcb *Syscall_frame::utcb() const +{ return reinterpret_cast(r[1]); /*r2*/} + +IMPLEMENT inline L4_msg_tag Syscall_frame::tag() const +{ return L4_msg_tag(r[2]); /*r3*/ } + +IMPLEMENT inline +void Syscall_frame::tag(L4_msg_tag const &tag) +{ r[2] = tag.raw(); /*r3*/ } + diff --git a/kernel/fiasco/src/kern/sparc/exceptions.S b/kernel/fiasco/src/kern/sparc/exceptions.S new file mode 100644 index 00000000..7763cabb --- /dev/null +++ b/kernel/fiasco/src/kern/sparc/exceptions.S @@ -0,0 +1,8 @@ +.text +.global kern_kdebug_entry +kern_kdebug_entry: + ta 0 + +.global vcpu_resume +vcpu_resume: + ta 0 diff --git a/kernel/fiasco/src/kern/sparc/kdb_ke-sparc.cpp b/kernel/fiasco/src/kern/sparc/kdb_ke-sparc.cpp new file mode 100644 index 00000000..6e15db39 --- /dev/null +++ b/kernel/fiasco/src/kern/sparc/kdb_ke-sparc.cpp @@ -0,0 +1,4 @@ +INTERFACE [sparc]: + +void kdb_ke(const char *msg) asm ("kern_kdebug_entry"); +void kdb_ke_sequence(const char *msg) asm ("kern_kdebug_entry"); diff --git a/kernel/fiasco/src/kern/sparc/kernel_task-sparc.cpp b/kernel/fiasco/src/kern/sparc/kernel_task-sparc.cpp new file mode 100644 index 00000000..d144d688 --- /dev/null +++ b/kernel/fiasco/src/kern/sparc/kernel_task-sparc.cpp @@ -0,0 +1,10 @@ +IMPLEMENTATION[sparc]: + +#include "config.h" +#include "globals.h" +#include "space.h" + +PRIVATE inline NEEDS["globals.h"] +Kernel_task::Kernel_task() +: Task(Ram_quota::root, Kmem::kdir()) +{} diff --git a/kernel/fiasco/src/kern/sparc/kernel_thread-sparc.cpp b/kernel/fiasco/src/kern/sparc/kernel_thread-sparc.cpp new file mode 100644 index 00000000..58295fc5 --- /dev/null +++ b/kernel/fiasco/src/kern/sparc/kernel_thread-sparc.cpp @@ -0,0 +1,22 @@ +IMPLEMENTATION [sparc]: + +#include "mem_layout.h" +#include "psr.h" +IMPLEMENT inline +void +Kernel_thread::free_initcall_section() +{ + memset( (void*)&Mem_layout::initcall_start, 0, &Mem_layout::initcall_end + - &Mem_layout::initcall_start ); + printf("%d KB kernel memory freed\n", (int)(&Mem_layout::initcall_end - + &Mem_layout::initcall_start)/1024); +} + +IMPLEMENT FIASCO_INIT +void +Kernel_thread::bootstrap_arch() +{ + //status for kernel thread + Return_frame *rf = nonull_static_cast(current()->regs()); + //rf->srr1 = Msr::Msr_kernel; +} diff --git a/kernel/fiasco/src/kern/sparc/kip_init.cpp b/kernel/fiasco/src/kern/sparc/kip_init.cpp new file mode 100644 index 00000000..ec31871f --- /dev/null +++ b/kernel/fiasco/src/kern/sparc/kip_init.cpp @@ -0,0 +1,73 @@ +INTERFACE [sparc]: + +#include "kip.h" + +class Kip_init +{ +public: + static void init(); +}; + + +//--------------------------------------------------------------------------- +IMPLEMENTATION [sparc]: + +#include "mem_layout.h" +#include "config.h" + +// Make the stuff below apearing only in this compilation unit. +// Trick Preprocess to let the struct reside in the cc file rather +// than putting it into the _i.h file which is perfectly wrong in +// this case. +namespace KIP_namespace +{ + enum + { + Num_mem_descs = 20, + Max_len_version = 512, + + Size_mem_descs = sizeof(Mword) * 2 * Num_mem_descs, + }; + + struct KIP + { + Kip kip; + char mem_descs[Size_mem_descs]; + }; + + KIP sparc_kernel_info_page asm("sparc_kernel_info_page") __attribute__((section(".kernel_info_page"))) = + { + { + /* 00/00 */ L4_KERNEL_INFO_MAGIC, + Config::Kernel_version_id, + (Size_mem_descs + sizeof(Kip)) >> 4, + {}, 0, {}, + /* 10/20 */ 0, {}, + /* 20/40 */ 0, 0, {}, + /* 30/60 */ 0, 0, {}, + /* 40/80 */ 0, 0, {}, + /* 50/A0 */ 0, (sizeof(Kip) << (sizeof(Mword)*4)) | Num_mem_descs, {}, + /* 60/C0 */ {}, + /* A0/140 */ 0, 0, 0, 0, + /* B0/160 */ {}, + /* E0/1C0 */ 0, 0, {}, + /* F0/1D0 */ {}, + }, + {} + }; +}; + + +IMPLEMENT +void Kip_init::init() +{ + Kip *kinfo = reinterpret_cast(&KIP_namespace::sparc_kernel_info_page); + Kip::init_global_kip(kinfo); + + /* add kernel image */ + kinfo->add_mem_region(Mem_desc(0,(Address)&Mem_layout::end - 1, + Mem_desc::Reserved)); + + kinfo->add_mem_region(Mem_desc(0, Mem_layout::User_max - 1, + Mem_desc::Conventional, true)); +} diff --git a/kernel/fiasco/src/kern/sparc/kmem.cpp b/kernel/fiasco/src/kern/sparc/kmem.cpp new file mode 100644 index 00000000..70fa47e3 --- /dev/null +++ b/kernel/fiasco/src/kern/sparc/kmem.cpp @@ -0,0 +1,88 @@ +INTERFACE [sparc]: + +#include "paging.h" + +class Page_table; + +class Kmem : public Mem_layout +{ +public: + static Pdir *kdir(); + static Pdir *dir(); + + static Mword *kernel_sp(); + static void kernel_sp(Mword *); + + static Mword is_tcb_page_fault( Mword pfa, Mword error ); + static Mword is_kmem_page_fault( Mword pfa, Mword error ); + static Mword is_io_bitmap_page_fault( Mword pfa ); + + static Address virt_to_phys(const void *addr); +private: + static Pdir *_kdir; + static Mword *_sp; +}; + +//--------------------------------------------------------------------------- +IMPLEMENTATION [sparc]: + +#include "mem_layout.h" +#include "paging.h" +#include "panic.h" + +char kernel_page_directory[sizeof(Pdir)]; +Pdir *Kmem::_kdir = (Pdir *)&kernel_page_directory; +Mword *Kmem::_sp = 0; + +IMPLEMENT inline +Pdir *Kmem::kdir() +{ return _kdir; } + +IMPLEMENT inline +Pdir *Kmem::dir() +{ return _kdir; } + +IMPLEMENT inline +Mword *Kmem::kernel_sp() +{ return _sp;} + +IMPLEMENT inline +void Kmem::kernel_sp(Mword *sp) +{ _sp = sp; } + +PUBLIC static inline NEEDS["mem_layout.h", "panic.h"] +Address Kmem::ipc_window(unsigned /*win*/) +{ + panic("%s not implemented", __PRETTY_FUNCTION__); + return 0; +} + +IMPLEMENT inline NEEDS["paging.h"] +Address Kmem::virt_to_phys(const void *addr) +{ + Address a = reinterpret_cast
(addr); + return kdir()->virt_to_phys(a); +} + +//------------------------------------------------------------------------------ +/* + * dummy implementations + */ + +IMPLEMENT inline +Mword Kmem::is_kmem_page_fault(Mword pfa, Mword /*error*/) +{ + return in_kernel(pfa); +} + +IMPLEMENT inline +Mword Kmem::is_tcb_page_fault(Mword /*pfa*/, Mword /*error*/ ) +{ + return 0; +} + +IMPLEMENT inline +Mword Kmem::is_io_bitmap_page_fault( Mword /*pfa*/ ) +{ + return 0; +} diff --git a/kernel/fiasco/src/kern/sparc/kmem_alloc-sparc.cpp b/kernel/fiasco/src/kern/sparc/kmem_alloc-sparc.cpp new file mode 100644 index 00000000..4f78e4c1 --- /dev/null +++ b/kernel/fiasco/src/kern/sparc/kmem_alloc-sparc.cpp @@ -0,0 +1,31 @@ +//---------------------------------------------------------------------------- +IMPLEMENTATION [sparc]: + +#include "mem_region.h" + +IMPLEMENT +Kmem_alloc::Kmem_alloc() +{ + Mword alloc_size = Config::Kmem_size; + a->init(Mem_layout::Map_base); + + /* First, collect non-used physical memory chunks + * into a list. */ + Mem_region_map<64> map; + unsigned long avail_size = create_free_map(Kip::k(), &map); + printf("Available phys mem: %08lx\n", avail_size); + + for (int i = map.length() - 1; i >= 0 && alloc_size > 0; --i) + { + Mem_region f = map[i]; + if (f.size() > alloc_size) + f.start += (f.size() - alloc_size); + + printf(" [%08lx - %08lx %4ld kB]\n", f.start, f.end, f.size() >> 10); + Kip::k()->add_mem_region(Mem_desc(f.start, f.end, + Mem_desc::Reserved)); + printf(" -> %08lx\n", Mem_layout::phys_to_pmem(f.start)); + a->add_mem((void*)Mem_layout::phys_to_pmem(f.start), f.size()); + alloc_size -= f.size(); + } +} diff --git a/kernel/fiasco/src/kern/sparc/main.cpp b/kernel/fiasco/src/kern/sparc/main.cpp new file mode 100644 index 00000000..ef98dfdf --- /dev/null +++ b/kernel/fiasco/src/kern/sparc/main.cpp @@ -0,0 +1,92 @@ +INTERFACE [sparc]: +#include + +//--------------------------------------------------------------------------- +IMPLEMENTATION [sparc]: + +#include +#include +#include + +#include "config.h" +#include "globals.h" +//#include "kmem_alloc.h" +#include "kip_init.h" +//#include "pagetable.h" +#include "kdb_ke.h" +#include "kernel_thread.h" +#include "kernel_task.h" +#include "kernel_console.h" +//#include "reset.h" //TODO cbass: implement +#include "space.h" +//#include "terminate.h" //TODO cbass: implement + +#include "processor.h" +#include "boot_info.h" +/* +static int exit_question_active = 0; + +extern "C" void __attribute__ ((noreturn)) +_exit(int) +{ + if (exit_question_active) + platform_reset(); + + while (1) + { + Proc::halt(); + Proc::pause(); + } +} + + +static void exit_question() +{ + exit_question_active = 1; + + while (1) + { + puts("\nReturn reboots, \"k\" enters L4 kernel debugger..."); + + char c = Kconsole::console()->getchar(); + + if (c == 'k' || c == 'K') + { + kdb_ke("_exit"); + } + else + { + // it may be better to not call all the destruction stuff + // because of unresolved static destructor dependency + // problems. + // SO just do the reset at this point. + puts("\033[1mRebooting...\033[0m"); + platform_reset(); + break; + } + } +} + +*/ +#include "thread_state.h" +int main() +{ + // caution: no stack variables in this function because we're going + // to change the stack pointer! + + // make some basic initializations, then create and run the kernel + // thread + //set_exit_question(&exit_question); + + // disallow all interrupts before we selectively enable them + // pic_disable_all(); + + // create kernel thread + static Kernel_thread *kernel = new (Ram_quota::root) Kernel_thread; + Task *const ktask = Kernel_task::kernel_task(); + check(kernel->bind(ktask, User::Ptr(0))); + //kdb_ke("init"); + + // switch to stack of kernel thread and bootstrap the kernel +} + diff --git a/kernel/fiasco/src/kern/sparc/mapping-sparc.cpp b/kernel/fiasco/src/kern/sparc/mapping-sparc.cpp new file mode 100644 index 00000000..d6fa5de0 --- /dev/null +++ b/kernel/fiasco/src/kern/sparc/mapping-sparc.cpp @@ -0,0 +1,24 @@ +INTERFACE [sparc]: + +#include "types.h" +class Treemap; + +class Mapping_entry +{ +public: + enum { Alignment = 4 }; + union + { + struct + { + unsigned long _space:32; ///< Address-space number +// unsigned long _pad:1; + unsigned long address:20; ///< Virtual address in address space + } __attribute__((packed)) data; + Treemap *_submap; + }; + Unsigned8 _depth; + void set_space(Space *s) { data._space = (unsigned long)s; } + Space *space() const { return (Space *)data._space; } +}; + diff --git a/kernel/fiasco/src/kern/sparc/mem_layout-sparc.cpp b/kernel/fiasco/src/kern/sparc/mem_layout-sparc.cpp new file mode 100644 index 00000000..50f85eb3 --- /dev/null +++ b/kernel/fiasco/src/kern/sparc/mem_layout-sparc.cpp @@ -0,0 +1,166 @@ +//--------------------------------------------------------------------------- +INTERFACE [sparc]: + +#include "initcalls.h" +#include "template_math.h" + +EXTENSION class Mem_layout +{ + +//TODO cbass: check what can be omitted +public: + enum Phys_layout { + Utcb_ptr_page = 0x3000, + Syscalls_phys = 0x4000, + Tbuf_status_page = 0x5000, + Kernel_start = 0x6000, //end phys pool + Syscalls = 0xfffff000, + + User_max = 0xf0000000, + Tcbs = 0xc0000000, + Utcb_addr = User_max - 0x2000, + utcb_ptr_align = Tl_math::Ld::Res, + Tcbs_end = 0xe0000000, + __free_1_start = 0xec000000, + __free_1_end = 0xed000000, + Map_base = 0xf0000000, ///< % 80MB kernel memory + Map_end = 0xf5000000, + Caps_start = 0xf5000000, + Caps_end = 0xfd000000, + Kernel_image = 0xfd000000, + Kernel_max = 0x00000000, + }; + + static Address Tbuf_buffer_area; + static Address Tbuf_ubuffer_area; +}; + +//--------------------------------------------------------------------------- +INTERFACE [sparc]: + +EXTENSION class Mem_layout +{ +public: + enum { + Uart_base = 0x80000100, + }; +}; + + +// ------------------------------------------------------------------------ +IMPLEMENTATION [sparc]: + +#include "panic.h" +#include "paging.h" +#include + +Address Mem_layout::Tbuf_buffer_area = 0; +Address Mem_layout::Tbuf_ubuffer_area = 0; + +PUBLIC static +Address +Mem_layout::phys_to_pmem (Address addr) +{ + extern Mword kernel_srmmu_l1[256]; + for (unsigned i = 0xF0; i < 0xFF; ++i) + { + if (kernel_srmmu_l1[i] != 0) + { + Mword v_page = addr & (0xFF << Pte_base::Pdir_shift); + Mword entry = (kernel_srmmu_l1[i] & Pte_base::Ppn_mask) << Pte_base::Ppn_addr_shift; + if (entry == v_page) + return (i << Pte_base::Pdir_shift) | (addr & ~(0xFF << Pte_base::Pdir_shift)); + } + } + return ~0L; +} + +PUBLIC static inline +Address +Mem_layout::pmem_to_phys (Address addr) +{ + (void)addr; + return ~0L; +} + +PUBLIC static inline +Address +Mem_layout::pmem_to_phys (const void *ptr) +{ + return reinterpret_cast
(ptr); +} + +PUBLIC static inline +template< typename V > +bool +Mem_layout::read_special_safe(V const * /* *address */, V &/*v*/) +{ + panic("%s not implemented", __PRETTY_FUNCTION__); + return false; +} + +PUBLIC static inline +template< typename T > +T +Mem_layout::read_special_safe(T const *a) +{ + Mword res; + return T(res); +} + + +/* no page faults can occur, return true */ +PUBLIC static inline +bool +Mem_layout::is_special_mapped(void const * /*a*/) +{ + return true; +} + + +IMPLEMENTATION [sparc && debug]: + +#include "kip_init.h" + + +PUBLIC static FIASCO_INIT +void +Mem_layout::init() +{ + Mword alloc_size = 0x200000; + unsigned long max = ~0UL; + for (;;) + { + Mem_region r; r.start=2;r.end=1;// = Kip::k()->last_free(max); + if (r.start > r.end) + panic("Corrupt memory descscriptor in KIP..."); + + if (r.start == r.end) + panic("not enough kernel memory"); + + max = r.start; + Mword size = r.end - r.start + 1; + if(alloc_size <= size) + { + r.start += (size - alloc_size); + Kip::k()->add_mem_region(Mem_desc(r.start, r.end, + Mem_desc::Reserved)); + + printf("TBuf installed at: [%08lx; %08lx] - %lu KB\n", + r.start, r.end, alloc_size / 1024); + + Tbuf_buffer_area = Tbuf_ubuffer_area = r.start; + break; + } + } + + if(!Tbuf_buffer_area) + panic("Could not allocate trace buffer"); +} + +IMPLEMENTATION [sparc && !debug]: + +PUBLIC static FIASCO_INIT +void +Mem_layout::init() +{} diff --git a/kernel/fiasco/src/kern/sparc/mem_space-sparc.cpp b/kernel/fiasco/src/kern/sparc/mem_space-sparc.cpp new file mode 100644 index 00000000..b72eb620 --- /dev/null +++ b/kernel/fiasco/src/kern/sparc/mem_space-sparc.cpp @@ -0,0 +1,344 @@ +INTERFACE [sparc]: + +#include "entry_frame.h" +extern "C" +Mword +pagefault_entry(Address, Mword, Mword, Return_frame *); + +EXTENSION class Mem_space +{ +public: + + typedef Pdir Dir_type; + + /** Return status of v_insert. */ + enum //Status + { + Insert_ok = 0, ///< Mapping was added successfully. + Insert_warn_exists, ///< Mapping already existed + Insert_warn_attrib_upgrade, ///< Mapping already existed, attribs upgrade + Insert_err_nomem, ///< Couldn't alloc new page table + Insert_err_exists ///< A mapping already exists at the target addr + }; + + /** Attribute masks for page mappings. */ + enum Page_attrib + { + Page_no_attribs = 0, + /// Page is writable. + Page_writable = 0, // XXX + Page_cacheable = 0, + /// Page is noncacheable. + Page_noncacheable = 0, // XXX + /// it's a user page. + Page_user_accessible = 0, // XXX + /// Page has been referenced + Page_referenced = Pt_entry::Referenced, + /// Page is dirty + Page_dirty = Pt_entry::Modified, + Page_references = Pt_entry::Referenced| Page_dirty, + /// A mask which contains all mask bits + Page_all_attribs = Page_writable | Page_noncacheable | + Page_user_accessible | Page_referenced | Page_dirty, + }; + + // Mapping utilities + enum // Definitions for map_util + { + Need_insert_tlb_flush = 0, + Map_page_size = Config::PAGE_SIZE, + Page_shift = Config::PAGE_SHIFT, + Map_superpage_size = Config::SUPERPAGE_SIZE, + Map_max_address = Mem_layout::User_max, + Whole_space = MWORD_BITS, + Identity_map = 0, + }; + +protected: + // DATA + Dir_type *_dir; +}; + + +//---------------------------------------------------------------------------- +IMPLEMENTATION [sparc]: + +#include +#include +#include "cpu.h" +#include "kdb_ke.h" +#include "l4_types.h" +#include "mem_layout.h" +#include "paging.h" +#include "std_macros.h" +#include "kmem.h" +#include "logdefs.h" +#include "panic.h" +#include "lock_guard.h" +#include "cpu_lock.h" +#include "warn.h" + + + + +PUBLIC explicit inline +Mem_space::Mem_space(Ram_quota *q) : _quota(q), _dir(0) {} + +PROTECTED inline +bool +Mem_space::initialize() +{ + void *b; + if (EXPECT_FALSE(!(b = Kmem_alloc::allocator() + ->q_alloc(_quota, Config::PAGE_SHIFT)))) + return false; + + _dir = static_cast(b); + _dir->clear(); // initialize to zero + return true; // success +} + +PUBLIC +Mem_space::Mem_space(Ram_quota *q, Dir_type* pdir) + : _quota(q), _dir(pdir) +{ + _kernel_space = this; + _current.cpu(0) = this; +} + +IMPLEMENT inline +void +Mem_space::make_current() +{ + printf("%s FIXME\n", __func__); +} + + +PROTECTED inline +void +Mem_space::sync_kernel() +{ + printf("%s FIXME\n", __func__); +} + + +IMPLEMENT inline NEEDS ["kmem.h"] +void Mem_space::switchin_context(Mem_space *from) +{ + (void)from; + printf("%s FIXME\n", __func__); +} + +//XXX cbass: check; +PUBLIC static inline +Mword +Mem_space::xlate_flush(unsigned char rights) +{ + Mword a = Page_references; + if (rights & L4_fpage::RX) + a |= Page_all_attribs; + else if (rights & L4_fpage::W) + a |= Page_writable; + + return a; +} + +PUBLIC static inline +Mword +Mem_space::is_full_flush(unsigned char rights) +{ + return rights & L4_fpage::RX; +} + +PUBLIC static inline +unsigned char +Mem_space::xlate_flush_result(Mword attribs) +{ + unsigned char r = 0; + if (attribs & Page_referenced) + r |= L4_fpage::RX; + + if (attribs & Page_dirty) + r |= L4_fpage::W; + + return r; +} + +PUBLIC inline NEEDS["cpu.h"] +static bool +Mem_space::has_superpages() +{ + return Cpu::have_superpages(); +} + +//we flush tlb in htab implementation +PUBLIC static inline NEEDS["mem_unit.h"] +void +Mem_space::tlb_flush(bool = false) +{ + //Mem_unit::tlb_flush(); +} + + +/* +PUBLIC inline +bool +Mem_space::set_attributes(Address virt, unsigned page_attribs) +{*/ +/* + Pdir::Iter i = _dir->walk(virt); + + if (!i.e->valid() || i.shift() != Config::PAGE_SHIFT) + return 0; + + i.e->del_attr(Page::MAX_ATTRIBS); + i.e->add_attr(page_attribs); + return true; +*/ +/* NOT_IMPL_PANIC; + return false; +}*/ + +PROTECTED inline +void +Mem_space::destroy() +{} + +/** + * Destructor. Deletes the address space and unregisters it from + * Space_index. + */ +PRIVATE +void +Mem_space::dir_shutdown() +{ + + // free ldt memory if it was allocated + //free_ldt_memory(); + + // free all page tables we have allocated for this address space + // except the ones in kernel space which are always shared + /* + _dir->alloc_cast() + ->destroy(0, Kmem::mem_user_max, Pdir::Depth - 1, + Mem_space_q_alloc(_quota, Kmem_alloc::allocator())); +*/ + NOT_IMPL_PANIC; +} + +IMPLEMENT inline +Mem_space * +Mem_space::current_mem_space(unsigned cpu) /// XXX: do not fix, deprecated, remove! +{ + return _current.cpu(cpu); +} + +/** Insert a page-table entry, or upgrade an existing entry with new + attributes. + @param phys Physical address (page-aligned). + @param virt Virtual address for which an entry should be created. + @param size Size of the page frame -- 4KB or 4MB. + @param page_attribs Attributes for the mapping (see + Mem_space::Page_attrib). + @return Insert_ok if a new mapping was created; + Insert_warn_exists if the mapping already exists; + Insert_warn_attrib_upgrade if the mapping already existed but + attributes could be upgraded; + Insert_err_nomem if the mapping could not be inserted because + the kernel is out of memory; + Insert_err_exists if the mapping could not be inserted because + another mapping occupies the virtual-address + range + @pre phys and virt need to be size-aligned according to the size argument. + */ +IMPLEMENT inline +Mem_space::Status +Mem_space::v_insert(Phys_addr phys, Vaddr virt, Vsize size, + unsigned page_attribs, bool /*upgrade_ignore_size*/) +{ + (void)phys; (void)virt; (void)page_attribs; + assert(size == Size(Config::PAGE_SIZE) + || size == Size(Config::SUPERPAGE_SIZE)); +/* + printf("v_insert: phys %08lx virt %08lx (%s) %p\n", phys, virt, + page_attribs & Page_writable?"rw":"ro", this);*/ + return Insert_err_nomem; +} + + +/** + * Simple page-table lookup. + * + * @param virt Virtual address. This address does not need to be page-aligned. + * @return Physical address corresponding to a. + */ +PUBLIC inline NEEDS ["paging.h"] +Address +Mem_space::virt_to_phys (Address virt) const +{ + return dir()->virt_to_phys(virt); +} + +PUBLIC inline +virtual Address +Mem_space::virt_to_phys_s0(void *a) const +{ + return dir()->virt_to_phys((Address)a); +} + +PUBLIC inline +Address +Mem_space::pmem_to_phys (Address virt) const +{ + return virt; +} + + + +/** Look up a page-table entry. + @param virt Virtual address for which we try the look up. + @param phys Meaningful only if we find something (and return true). + If not 0, we fill in the physical address of the found page + frame. + @param page_attribs Meaningful only if we find something (and return true). + If not 0, we fill in the page attributes for the found page + frame (see Mem_space::Page_attrib). + @param size If not 0, we fill in the size of the page-table slot. If an + entry was found (and we return true), this is the size + of the page frame. If no entry was found (and we + return false), this is the size of the free slot. In + either case, it is either 4KB or 4MB. + @return True if an entry was found, false otherwise. + */ +IMPLEMENT +bool +Mem_space::v_lookup(Vaddr virt, Phys_addr *phys = 0, Size *size = 0, + unsigned *page_attribs = 0) +{ + (void)virt; (void)phys; (void)size; (void)page_attribs; + return false; +} + +/** Delete page-table entries, or some of the entries' attributes. This + function works for one or multiple mappings (in contrast to v_insert!). + @param virt Virtual address of the memory region that should be changed. + @param size Size of the memory region that should be changed. + @param page_attribs If nonzero, delete only the given page attributes. + Otherwise, delete the whole entries. + @return Combined (bit-ORed) page attributes that were removed. In + case of errors, ~Page_all_attribs is additionally bit-ORed in. + */ +IMPLEMENT +unsigned long +Mem_space::v_delete(Vaddr virt, Vsize size, + unsigned long page_attribs = Page_all_attribs) +{ + (void)virt; (void)size; (void)page_attribs; + unsigned ret = 0; + return ret; +} + +PUBLIC static inline +Page_number +Mem_space::canonize(Page_number v) +{ return v; } diff --git a/kernel/fiasco/src/kern/sparc/mem_unit-sparc.cpp b/kernel/fiasco/src/kern/sparc/mem_unit-sparc.cpp new file mode 100644 index 00000000..1345a8de --- /dev/null +++ b/kernel/fiasco/src/kern/sparc/mem_unit-sparc.cpp @@ -0,0 +1,94 @@ +INTERFACE [sparc]: + +#include "types.h" +#include "processor.h" + +namespace Mmu +{ + enum ASI + { + Cache_miss = 0x01, + Sys_control = 0x02, + Icache_tags = 0x0C, + Icache_data = 0x0D, + Dcache_tags = 0x0E, + Dcache_data = 0x0F, + Icache_flush = 0X10, + Dcache_flush = 0x11, + Flush_context = 0x13, + Diag_dcache = 0x14, + Diag_icache = 0x15, + Regs = 0x19, + Bypass = 0x1C, + Diagnostic = 0x1D, + Snoop_diag = 0x1E + }; + + enum Registers + { + Control = 0x000, + ContextTable = 0x100, + ContextNumber = 0x200, + }; +}; + +class Mem_unit { }; + +//------------------------------------------------------------------------------ +IMPLEMENTATION[sparc && !mp]: + +/** Flush whole TLB + * + * Note: The 'tlbia' instruction is not implemented in G2 cores (causes a + * program exception). Therefore, we use 'tlbie' by iterating through EA + * bits [15-19] (see: G2 manual) + */ +PUBLIC static inline +void +Mem_unit::tlb_flush() +{ +} + +/** Flush page at virtual address + */ +PUBLIC static inline +void +Mem_unit::tlb_flush(Address addr) +{ + (void)addr; +} + +PUBLIC static inline +void +Mem_unit::sync() +{ +} + +PUBLIC static inline +void +Mem_unit::isync() +{ +} + +PUBLIC static inline +void +Mem_unit::context(Mword number) +{ + Proc::write_alternative(Mmu::ContextNumber, number); +} + +PUBLIC static inline +void +Mem_unit::context_table(Address table) +{ + Proc::write_alternative(Mmu::ContextTable, (table >> 4) & ~0x3); +} + +PUBLIC static inline +void +Mem_unit::mmu_enable() +{ + Mword r = Proc::read_alternative(Mmu::Control); + r |= 1; + Proc::write_alternative(Mmu::Control, r); +} diff --git a/kernel/fiasco/src/kern/sparc/paging-sparc.cpp b/kernel/fiasco/src/kern/sparc/paging-sparc.cpp new file mode 100644 index 00000000..5240ba4b --- /dev/null +++ b/kernel/fiasco/src/kern/sparc/paging-sparc.cpp @@ -0,0 +1,326 @@ +INTERFACE[sparc]: + +#include "types.h" +#include "config.h" + +class PF {}; + +//------------------------------------------------------------------------------ +INTERFACE[sparc]: + +#include +#include "types.h" +#include "ptab_base.h" +#include "kdb_ke.h" +#include "mem_unit.h" + +class Paging {}; + +class Pte_base +{ + public: + typedef Mword Raw; + enum + { + ET_ptd = 1, ///< PT Descriptor is PTD + ET_pte = 2, ///< PT Descriptor is PTE + + Ptp_mask = 0xfffffffc, ///< PTD: page table pointer + Ppn_mask = 0xffffff00, ///< PTE: physical page number + Ppn_addr_shift = 4, ///< PTE/PTD: need to shift phys addr + Cacheable = 0x80, ///< PTE: is cacheable + Modified = 0x40, ///< PTE: modified + Referenced = 0x20, ///< PTE: referenced + Accperm_mask = 0x1C, ///< 3 bits for access permissions + Accperm_shift = 2, + Et_mask = 0x3, ///< 2 bits to determine entry type + Vfpa_mask = 0xfffff000, ///< Flush/Probe: virt. addr. mask + Flushtype_mask = 0xf00, ///< Flush/Probe: type + + Pdir_mask = 0xFF, + Pdir_shift = 24, + Ptab_mask = 0x3F, + Ptab_shift1 = 18, + Ptab_shift2 = 12, + Page_offset_mask = 0xFFF, + + Super_level = 0, + Valid = 0x3, + }; + + Mword addr() const { return _raw & Ppn_mask;} + //bool is_super_page() const { return _raw & Pse_bit; } + protected: + Raw _raw; +}; + +class Pt_entry : public Pte_base +{ +public: + Mword leaf() const { return true; } + void set(Address p, bool /*intermed*/, bool /*present*/, unsigned long attrs = 0) + { + _raw = ((p >> Ppn_addr_shift) & Ppn_mask) | attrs | ET_pte; + } +}; + +class Pd_entry : public Pte_base +{ +public: + Mword leaf() const { return false; } + void set(Address p, bool /*intermed*/, bool /*present*/, unsigned long /*attrs*/ = 0) + { + _raw = ((p >> Ppn_addr_shift) & Ptp_mask) | ET_ptd; + } +}; + +namespace Page +{ + typedef Unsigned32 Attribs; + enum Attribs_enum + { + KERN_RW = 0x00000000, + USER_RO = 0x00000001, + USER_RW = 0x00000002, + Cache_mask = 0x00000078, + CACHEABLE = 0x00000000, + NONCACHEABLE = 0x00000040, + BUFFERED = 0x00000080, //XXX not sure + }; +}; + + +typedef Ptab::List< Ptab::Traits, + Ptab::Traits > Ptab_traits; + +typedef Ptab::Shift::List Ptab_traits_vpn; +typedef Ptab::Page_addr_wrap Ptab_va_vpn; + + +IMPLEMENTATION[sparc]: + +#include "psr.h" +#include "lock_guard.h" +#include "cpu_lock.h" +#include "kip.h" + + +/* this functions do nothing on SPARC architecture */ +PUBLIC static inline +Address +Paging::canonize(Address addr) +{ + return addr; +} + +PUBLIC static inline +Address +Paging::decanonize(Address addr) +{ + return addr; +} + +//--------------------------------------------------------------------------- +IMPLEMENT inline +Mword PF::is_translation_error(Mword error) +{ + return !(error & 1 << 30) /* DSISR/SRR1 bit 1 */; +} + +IMPLEMENT inline NEEDS["psr.h"] +Mword PF::is_usermode_error(Mword error) +{ + return 0 & error;//(error & Msr::Msr_pr); +} + +IMPLEMENT inline +Mword PF::is_read_error(Mword error) +{ + return !(error & (1 << 25)) /* DSISR bit 6*/; +} + +IMPLEMENT inline +Mword PF::addr_to_msgword0(Address pfa, Mword error) +{ + Mword a = pfa & ~3; + if(is_translation_error(error)) + a |= 1; + if(!is_read_error(error)) + a |= 2; + return a; +} + +//--------------------------------------------------------------------------- + +PUBLIC +Pte_base::Pte_base(Mword raw) : _raw(raw) {} + +PUBLIC +Pte_base::Pte_base() {} + +PUBLIC inline +Pte_base & +Pte_base::operator = (Pte_base const &other) +{ + _raw = other.raw(); + return *this; +} + +PUBLIC inline +Pte_base & +Pte_base::operator = (Mword raw) +{ + _raw = raw; + return *this; +} + +PUBLIC inline +Mword +Pte_base::raw() const +{ + return _raw; +} + +PUBLIC inline +void +Pte_base::add_attr(Mword attr) +{ + _raw |= attr; +} + +PUBLIC inline +void +Pte_base::del_attr(Mword attr) +{ + _raw &= ~attr; +} + +PUBLIC inline +void +Pte_base::clear() +{ _raw = 0; } + +PUBLIC inline +int +Pte_base::valid() const +{ + return _raw & Valid; +} + +PUBLIC inline +int +Pte_base::writable() const +{ + Mword acc = ((_raw >> Accperm_shift) & Accperm_mask); + return (acc=1); // XXX (3 and 5 can also be valid, depending on access mode) +} + +PUBLIC inline +Address +Pt_entry::pfn() const +{ + return _raw & Ppn_mask; +} + +PUBLIC static inline +Mword +Pte_base::pdir(Address a) +{ + return (a & (Pdir_mask << Pdir_shift)) >> Pdir_shift; +} + + +PUBLIC static inline +Mword +Pte_base::ptab1(Address a) +{ + return (a & (Ptab_mask << Ptab_shift1)) >> Ptab_shift1; +} + + +PUBLIC static inline +Mword +Pte_base::ptab2(Address a) +{ + return (a & (Ptab_mask << Ptab_shift2)) >> Ptab_shift2; +} + + +PUBLIC static inline +Mword +Pte_base::offset(Address a) +{ + return a & Page_offset_mask; +} + +PUBLIC static inline +void +Paging::split_address(Address a) +{ + printf("%lx -> %lx : %lx : %lx : %lx\n", a, + Pte_base::pdir(a), Pte_base::ptab1(a), + Pte_base::ptab2(a), Pte_base::offset(a)); +} + +Pte_base context_table[16]; +Mword kernel_srmmu_l1[256] __attribute__((aligned(0x400))); + +PUBLIC static +void +Paging::init() +{ + Mem_desc const *md = Kip::k()->mem_descs(); + Address memstart, memend; + memstart = memend = 0; + /*printf("MD %p, num descs %d\n", md, Kip::k()->num_mem_descs());*/ + for (unsigned i = 0; i < Kip::k()->num_mem_descs(); ++i) + { + printf(" [%lx - %lx type %x]\n", md[i].start(), md[i].end(), md[i].type()); + if ((memstart == 0) && md[i].type() == 1) + { + memstart = md[i].start(); + memend = md[i].end(); + break; + } + } + + /* + printf("Context table: %p - %p\n", context_table, + context_table + sizeof(context_table)); + printf("Kernel PDir: %p - %p\n", kernel_srmmu_l1, + kernel_srmmu_l1 + sizeof(kernel_srmmu_l1)); + */ + memset(context_table, 0, sizeof(context_table)); + memset(kernel_srmmu_l1, 0, sizeof(kernel_srmmu_l1)); + Mem_unit::context_table(Address(context_table)); + Mem_unit::context(0); + + /* PD entry for root pdir */ + Pd_entry root; + root.set(Address(kernel_srmmu_l1), false, false); + context_table[0] = root; + + /* + * Map as many 16 MB chunks (1st level page table entries) + * as possible. + */ + unsigned superpage = 0xF0; + while (memend - memstart + 1 >= (1 << 24)) + { + Pt_entry pte; + pte.set(memstart, false, false, Pte_base::Cacheable | (0x3 << 2)); + printf("pte %08x\n", pte.raw()); + + /* map phys mem starting from VA 0xF0000000 */ + kernel_srmmu_l1[superpage] = pte.raw(); + /* 1:1 mapping */ + kernel_srmmu_l1[Pte_base::pdir(memstart)] = pte.raw(); + + memstart += (1 << 24); + ++superpage; + } + + Mem_unit::mmu_enable(); + + printf("Paging enabled...\n"); +} diff --git a/kernel/fiasco/src/kern/sparc/psr.cpp b/kernel/fiasco/src/kern/sparc/psr.cpp new file mode 100644 index 00000000..cc947b6e --- /dev/null +++ b/kernel/fiasco/src/kern/sparc/psr.cpp @@ -0,0 +1,52 @@ +INTERFACE: + +#include "types.h" + +class Psr +{ +public: + enum Psr_bits { + Impl = 28, // implementation ID (read-only) + Version = 24, // version (read-only) + Icc_neg = 23, // Integer cond. code: negative + Icc_zero = 22, // Integer cond. code: zero + Icc_overfl = 21, // Integer cond. code: overflow + Icc_carry = 20, // Integer cond. code: carry + Enable_copr = 13, // Enable Coprocessor + Enable_fpu = 12, // Enable FPU + Interrupt_lvl = 8, // Interrupt level (above which we accept interrupts) + Superuser = 7, // Kernel mode + Prev_superuser = 6, // Kernel mode state at most recent trap + Enable_trap = 5, // Traps on/off + }; + + enum Psr_masks { + Impl_mask = 0xF, + Version_mask = 0xF, + Irq_lvl_mask = 0xF, + Cwp_mask = 0x1F, + }; +}; + +//------------------------------------------------------------------------------ +IMPLEMENTATION: + +PUBLIC static inline +Mword +Psr::read() +{ + Mword psr = 0; + asm volatile ("mov %%psr, %0" + : "=r" (psr)); + return psr; +} + + +PUBLIC static inline +void +Psr::write(unsigned psr) +{ + asm volatile("mov %0, %%psr\n\t" + "nop;nop;nop;" + : : "r"(psr)); +} diff --git a/kernel/fiasco/src/kern/sparc/space-sparc.cpp b/kernel/fiasco/src/kern/sparc/space-sparc.cpp new file mode 100644 index 00000000..cf0f35f5 --- /dev/null +++ b/kernel/fiasco/src/kern/sparc/space-sparc.cpp @@ -0,0 +1,6 @@ +IMPLEMENTATION [sparc]: // ------------------------------------------------- + +IMPLEMENT inline +void +Space::switchin_ldt() const +{} diff --git a/kernel/fiasco/src/kern/sparc/startup-sparc.cpp b/kernel/fiasco/src/kern/sparc/startup-sparc.cpp new file mode 100644 index 00000000..aec1e8e3 --- /dev/null +++ b/kernel/fiasco/src/kern/sparc/startup-sparc.cpp @@ -0,0 +1,58 @@ +IMPLEMENTATION [sparc]: + +#include "banner.h" +#include "boot_info.h" +#include "config.h" +#include "cpu.h" +#include "kip_init.h" +#include "kernel_task.h" +#include "kmem_alloc.h" +#include "per_cpu_data.h" +#include "per_cpu_data_alloc.h" +#include "pic.h" +#include "static_init.h" +#include "timer.h" +#include "utcb_init.h" +#include + +IMPLEMENT FIASCO_INIT FIASCO_NOINLINE +void +Startup::stage1() +{ + Proc::cli(); + Boot_info::init(); + Cpu::early_init(); + Config::init(); +} + +IMPLEMENT FIASCO_INIT FIASCO_NOINLINE +void +Startup::stage2() +{ + Banner::init(); + puts("Hello from Startup::stage2"); + + Kip_init::init(); + Paging::init(); + puts("Kmem_alloc::init()"); + //init buddy allocator + Kmem_alloc::init(); + + // Initialize cpu-local data management and run constructors for CPU 0 + Per_cpu_data::init_ctors(); + + // not really necessary for uni processor + Per_cpu_data_alloc::alloc(0); + Per_cpu_data::run_ctors(0); + Cpu::cpus.cpu(0).init(true); + + //idle task + Kernel_task::init(); +#if 0 + Pic::init(); + Timer::init(0); +#endif + Utcb_init::init(); + puts("Startup::stage2 finished"); +} + diff --git a/kernel/fiasco/src/kern/sparc/sys_call_page-sparc.cpp b/kernel/fiasco/src/kern/sparc/sys_call_page-sparc.cpp new file mode 100644 index 00000000..539f926a --- /dev/null +++ b/kernel/fiasco/src/kern/sparc/sys_call_page-sparc.cpp @@ -0,0 +1,16 @@ +INTERFACE: + +#include "types.h" + +//------------------------------------------------------------------------------ +IMPLEMENTATION: + +#include "mem_layout.h" +#include "kernel_task.h" +#include "mem_space.h" +IMPLEMENT static +void +Sys_call_page::init() +{ + printf("%s fixme\n", __func__); +} diff --git a/kernel/fiasco/src/kern/sparc/task-sparc.cpp b/kernel/fiasco/src/kern/sparc/task-sparc.cpp new file mode 100644 index 00000000..d0252b50 --- /dev/null +++ b/kernel/fiasco/src/kern/sparc/task-sparc.cpp @@ -0,0 +1,8 @@ +IMPLEMENTATION [sparc]: + +PRIVATE inline +bool +Task::invoke_arch(L4_msg_tag &, Utcb *) +{ + return false; +} diff --git a/kernel/fiasco/src/kern/sparc/tb_entry-sparc.cpp b/kernel/fiasco/src/kern/sparc/tb_entry-sparc.cpp new file mode 100644 index 00000000..6a025e48 --- /dev/null +++ b/kernel/fiasco/src/kern/sparc/tb_entry-sparc.cpp @@ -0,0 +1,151 @@ +INTERFACE [sparc]: + +EXTENSION class Tb_entry_base +{ +public: + enum + { + Tb_entry_size = 64, + }; +}; + +/** logged kernel event plus register content. */ +class Tb_entry_ke_reg : public Tb_entry +{ +private: + struct Payload + { + union { + char _msg[16]; ///< debug message + struct { + char _dsc[2]; + char const* _const_msg; + }; + }; + Mword _r3, _r4, _r5; ///< registers + }; +}; + +/** logged trap. */ +class Tb_entry_trap : public Tb_entry +{ +private: + struct Payload + { + Unsigned8 _trapno; + Unsigned16 _error; + Mword _cpsr, _sp; + }; +}; + +// -------------------------------------------------------------------- +IMPLEMENTATION [sparc]: + +PUBLIC inline +void +Tb_entry::rdtsc() +{} + +PUBLIC inline +const char * +Tb_entry_ke_reg::msg() const +{ + return payload()->_dsc[0] == 0 && payload()->_dsc[1] == 1 + ? payload()->_const_msg : payload()->_msg; +} + +PUBLIC inline +Mword +Tb_entry_ke_reg::val1() const +{ return payload()->_r3; } + +PUBLIC inline +Mword +Tb_entry_ke_reg::val2() const +{ return payload()->_r4; } + +PUBLIC inline +Mword +Tb_entry_ke_reg::val3() const +{ return payload()->_r5; } + +PUBLIC inline +void +Tb_entry_ke_reg::set(Context const *ctx, Mword eip, Mword v1, Mword v2, Mword v3) +{ + set_global(Tbuf_ke_reg, ctx, eip); + payload()->_r3 = v1; + payload()->_r4 = v2; + payload()->_r5 = v3; +} + +PUBLIC inline +void +Tb_entry_ke_reg::set_const(Context const *ctx, Mword eip, const char * const msg, + Mword v1, Mword v2, Mword v3) +{ + set(ctx, eip, v1, v2, v3); + payload()->_dsc[0] = 0; payload()->_dsc[1] = 1; + payload()->_const_msg = msg; +} + +PUBLIC inline +void +Tb_entry_ke_reg::set_buf(unsigned i, char c) +{ + if (i < sizeof(payload()->_msg) - 1) + payload()->_msg[i] = c >= ' ' ? c : '.'; +} + +PUBLIC inline +void +Tb_entry_ke_reg::term_buf(unsigned i) +{payload()->_msg[i < sizeof(payload()->_msg)-1 ? i + : sizeof(payload()->_msg)-1] = '\0';} + +// ------------------ +PUBLIC inline +Unsigned16 +Tb_entry_trap::cs() const +{ return 0; } + +PUBLIC inline +Unsigned8 +Tb_entry_trap::trapno() const +{ return payload()->_trapno; } + +PUBLIC inline +Unsigned16 +Tb_entry_trap::error() const +{ return payload()->_error; } + +PUBLIC inline +Mword +Tb_entry_trap::sp() const +{ return payload()->_sp; } + +PUBLIC inline +Mword +Tb_entry_trap::cr2() const +{ return 0; } + +PUBLIC inline +Mword +Tb_entry_trap::eax() const +{ return 0; } + +PUBLIC inline NEEDS ["trap_state.h"] +void +Tb_entry_trap::set(Context const *ctx, Mword pc, Trap_state *) +{ + set_global(Tbuf_trap, ctx, pc); + // More... +} + +PUBLIC inline NEEDS ["trap_state.h"] +void +Tb_entry_trap::set(Context const *ctx, Mword pc, Mword ) +{ + set_global(Tbuf_trap, ctx, pc); +} + diff --git a/kernel/fiasco/src/kern/sparc/thread-jdb.cpp b/kernel/fiasco/src/kern/sparc/thread-jdb.cpp new file mode 100644 index 00000000..cb839915 --- /dev/null +++ b/kernel/fiasco/src/kern/sparc/thread-jdb.cpp @@ -0,0 +1,79 @@ +INTERFACE [sparc && debug]: + +#include "trap_state.h" +#include "util.h" + +EXTENSION class Thread +{ +public: + typedef void (*Dbg_extension_entry)(Thread *t, Entry_frame *r); + static Dbg_extension_entry dbg_extension[64]; +private: + static int call_nested_trap_handler(Trap_state *ts) asm ("call_nested_trap_handler"); + static Trap_state::Handler nested_trap_handler FIASCO_FASTCALL; +}; + +//------------------------------------------------------------------------------ +IMPLEMENTATION [sparc && debug]: + +Thread::Dbg_extension_entry Thread::dbg_extension[64]; +Trap_state::Handler Thread::nested_trap_handler FIASCO_FASTCALL; + +extern "C" void sys_kdb_ke() +{ + cpu_lock.lock(); + Thread *t = current_thread(); + + //arriving from outx function + unsigned *x = (unsigned *)t->regs()->ip(); + if(t->regs()->r[29] == (Mword)-0x24 && t->regs()->r[2] & (1 << 31)) //ip && r3 + { + NOT_IMPL_PANIC; + unsigned func = (unsigned)t->regs()->r[1] & 0xffff; //r4 + if(Thread::dbg_extension[func]) + { + Thread::dbg_extension[func](t, t->regs()); + return; + } + } + + char str[32] = "USER ENTRY"; + //arriving from enter_kdebug + if (t->regs()->r[29] == (Mword)-0x24 && t->regs()->r[2] & (1 << 30)) //ip && r3 + { + //t->mem_space()->copy_from_user(str, (char *)(x + 1), sizeof(str)); + str[sizeof(str)-1] = 0; + } + + kdb_ke(str); +} + +IMPLEMENT +int +Thread::call_nested_trap_handler(Trap_state *ts) +{ + unsigned phys_cpu = Proc::cpu_id(); + unsigned log_cpu = Cpu::p2l(phys_cpu); + if (log_cpu == ~0U) + { + printf("Trap on unknown CPU phys_id=%x\n", phys_cpu); + log_cpu = 0; + } + + unsigned long &ntr = nested_trap_recover.cpu(log_cpu); + + void *stack = 0; + + if (!ntr) + stack = dbg_stack.cpu(log_cpu).stack_top; + + return 0; +} + +IMPLEMENTATION [sparc && !debug]: + +extern "C" void sys_kdb_ke() +{ +} +extern "C" void enter_jdb() +{} diff --git a/kernel/fiasco/src/kern/sparc/thread-sparc.cpp b/kernel/fiasco/src/kern/sparc/thread-sparc.cpp new file mode 100644 index 00000000..35bd0fd6 --- /dev/null +++ b/kernel/fiasco/src/kern/sparc/thread-sparc.cpp @@ -0,0 +1,299 @@ +INTERFACE [sparc]: + +class Trap_state; + +IMPLEMENTATION [sparc]: + +#include +#include +#include + +#include "globals.h" +#include "kmem.h" +#include "thread_state.h" +#include "trap_state.h" +#include "types.h" + +enum { + FSR_STATUS_MASK = 0x0d, + FSR_TRANSL = 0x05, + FSR_DOMAIN = 0x09, + FSR_PERMISSION = 0x0d, +}; + +DEFINE_PER_CPU Per_cpu Thread::dbg_stack; + +PRIVATE static +void +Thread::print_page_fault_error(Mword e) +{ + char const *const excpts[] = + { "reset","undef. insn", "swi", "pref. abort", "data abort", + "XXX", "XXX", "XXX" }; + + unsigned ex = (e >> 20) & 0x07; + + printf("(%lx) %s, %s(%c)",e & 0xff, excpts[ex], + (e & 0x00010000)?"user":"kernel", + (e & 0x00020000)?'r':'w'); +} + +// +// Public services +// +PRIVATE static +void +Thread::dump_bats() +{ +} + +PUBLIC template inline +void FIASCO_NORETURN +Thread::fast_return_to_user(Mword ip, Mword sp, T arg) +{ + (void)ip; (void)sp; (void)arg; + //assert_kdb(check that exiting privs are user privs); + // XXX: UNIMPLEMENTED + panic("__builtin_trap()"); +} + +IMPLEMENT +void +Thread::user_invoke() +{ + user_invoke_generic(); + assert(current()->state() & Thread_ready); + + Return_frame *r = nonull_static_cast(current()->regs()); + Kip *kip = (EXPECT_FALSE(current_thread()->mem_space()->is_sigma0())) ? + Kip::k() : 0; + + /* DEBUGGING */ + Mword vsid = 0xF000, utcb = 0xBAAA; + + printf("\n[%lx]leaving kernel ip %lx sp %lx vsid %lx\n", + current_thread()->dbg_id(), r->ip(), r->sp(), vsid); + printf("kernel_sp %p kip %p utcb %08lx\n", current_thread()->regs() + 1, kip, utcb); + + // never returns +} + +IMPLEMENT inline NEEDS["space.h", , "types.h" ,"config.h"] +bool Thread::handle_sigma0_page_fault(Address pfa) +{ + bool ret = (mem_space()->v_insert(Mem_space::Phys_addr(pfa & Config::PAGE_MASK), + Mem_space::Addr(pfa & Config::PAGE_MASK), + Mem_space::Size(Config::PAGE_SIZE), + Mem_space::Page_writable | + Mem_space::Page_user_accessible | + Mem_space::Page_cacheable + ) + != Mem_space::Insert_err_nomem); + + return ret; +} + +extern "C" { + void except_notimpl(void) + { + } + +}; + +extern "C" { + + /** + * The low-level page fault handler called from entry.S. We're invoked with + * interrupts turned off. Apart from turning on interrupts + * all casesi, just forwards + * the call to Thread::handle_page_fault(). + * @param pfa page-fault virtual address + * @param error_code CPU error code + * @return true if page fault could be resolved, false otherwise + */ + Mword pagefault_entry(const Mword pfa, const Mword error_code, + const Mword pc, Return_frame *ret_frame) + { + //printf("Page fault at %08lx (%s)\n", pfa, PF::is_read_error(error_code)?"ro":"rw" ); + if(EXPECT_TRUE(PF::is_usermode_error(error_code))) + { + if (current_thread()->vcpu_pagefault(pfa, error_code, pc)) + return 1; + + current_thread()->state_del(Thread_cancel); + Proc::sti(); + } + + int ret = current_thread()->handle_page_fault(pfa, error_code, pc, ret_frame); + + return ret; + } + + void slowtrap_entry(Trap_state * /*ts*/) + { + NOT_IMPL_PANIC; + } + +}; + +IMPLEMENT inline +bool +Thread::pagein_tcb_request(Return_frame * /*regs*/) +{ + NOT_IMPL_PANIC; + return false; +} + +extern "C" +{ + void timer_handler() + { + Return_frame *rf = nonull_static_cast(current()->regs()); + //disable power savings mode, when we come from privileged mode + if(EXPECT_FALSE(rf->user_mode())) + rf->srr1 = Proc::wake(rf->srr1); + + Timer::update_system_clock(current_cpu()); + current_thread()->handle_timer_interrupt(); + } +} +//--------------------------------------------------------------------------- +IMPLEMENTATION [sparc]: + +/** Constructor. + @param id user-visible thread ID of the sender + @param init_prio initial priority + @param mcp thread's maximum controlled priority + @post state() != Thread_invalid + */ +IMPLEMENT +Thread::Thread() + : Sender (0), // select optimized version of constructor + _pager(Thread_ptr::Invalid), + _exc_handler(Thread_ptr::Invalid), + _del_observer(0) +{ + + assert(state() == Thread_invalid); + + inc_ref(); + _space.space(Kernel_task::kernel_task()); + + // set a magic value -- we use it later to verify the stack hasn't + // been overrun + _magic = magic; + _recover_jmpbuf = 0; + _timeout = 0; + + *reinterpret_cast (--_kernel_sp) = user_invoke; + + // clear out user regs that can be returned from the thread_ex_regs + // system call to prevent covert channel + Entry_frame *r = regs(); + r->sp(0); + r->ip(0); + + state_add(Thread_dead | Thread_suspended); + // ok, we're ready to go! +} + +IMPLEMENT inline +Mword +Thread::user_sp() const +{ return regs()->sp(); } + +IMPLEMENT inline +void +Thread::user_sp(Mword sp) +{ return regs()->sp(sp); } + +IMPLEMENT inline NEEDS[Thread::exception_triggered] +Mword +Thread::user_ip() const +{ return exception_triggered() ? _exc_cont.ip() : regs()->ip(); } + +IMPLEMENT inline +Mword +Thread::user_flags() const +{ return 0; } + +IMPLEMENT inline NEEDS[Thread::exception_triggered] +void +Thread::user_ip(Mword ip) +{ + if (exception_triggered()) + _exc_cont.ip(ip); + else + { + Entry_frame *r = regs(); + r->ip(ip); + } +} + +PUBLIC inline NEEDS ["trap_state.h"] +int +Thread::send_exception_arch(Trap_state * /*ts*/) +{ + NOT_IMPL_PANIC; + return 1; // We did it +} + +PROTECTED inline +void +Thread::vcpu_resume_user_arch() +{} + + +PRIVATE static inline +void +Thread::save_fpu_state_to_utcb(Trap_state *, Utcb *) +{ +} + +PROTECTED inline +int +Thread::do_trigger_exception(Entry_frame * /*r*/, void * /*ret_handler*/) +{ + NOT_IMPL_PANIC; + return 0; +} + +PRIVATE static inline +bool FIASCO_WARN_RESULT +Thread::copy_utcb_to_ts(L4_msg_tag const &/*tag*/, Thread * /*snd*/, + Thread * /*rcv*/, unsigned char /*rights*/) +{ + NOT_IMPL_PANIC; + return true; +} + +PRIVATE static inline +bool FIASCO_WARN_RESULT +Thread::copy_ts_to_utcb(L4_msg_tag const &, Thread * /*snd*/, Thread * /*rcv*/, + unsigned char /*rights*/) +{ + NOT_IMPL_PANIC; + return true; +} + +PROTECTED inline +L4_msg_tag +Thread::invoke_arch(L4_msg_tag /*tag*/, Utcb * /*utcb*/) +{ + return commit_result(-L4_err::ENosys); +} + +PROTECTED inline +int +Thread::sys_control_arch(Utcb *) +{ + return 0; +} + +//----------------------------------------------------------------------------- +IMPLEMENTATION [!mp]: + +PUBLIC static inline +bool +Thread::check_for_ipi(unsigned) +{ return false; } diff --git a/kernel/fiasco/src/kern/sparc/timer-decr-sparc.cpp b/kernel/fiasco/src/kern/sparc/timer-decr-sparc.cpp new file mode 100644 index 00000000..90d92188 --- /dev/null +++ b/kernel/fiasco/src/kern/sparc/timer-decr-sparc.cpp @@ -0,0 +1,86 @@ +/** + * PowerPC timer using internal decrementer + */ + +IMPLEMENTATION [sparc]: + +#include "cpu.h" +#include "config.h" +#include "globals.h" +#include "kip.h" +#include "decrementer.h" +#include "warn.h" + +#include + +IMPLEMENT inline NEEDS ["decrementer.h", "kip.h", "config.h", ] +void +Timer::init(unsigned) +{ + printf("Using PowerPC decrementer for scheduling\n"); + + //1000 Hz + Decrementer::d()->init(Kip::k()->frequency_bus / + (4*Config::Scheduler_granularity)); + +} + +PUBLIC static inline +unsigned +Timer::irq() +{ return 0; } + +PUBLIC static inline +unsigned +Timer::irq_mode() +{ return 0; } + +PUBLIC static inline +void +Timer::acknowledge() +{ } + +//IMPLEMENT inline NEEDS ["decrementer.h"] +//void +//Timer::enable() +//{ +// Decrementer::d()->enable(); +//} + +//IMPLEMENT inline NEEDS ["decrementer.h"] +//void +//Timer::disable() +//{ +// Decrementer::d()->disable(); +//} + +IMPLEMENT inline NEEDS ["kip.h"] +void +Timer::init_system_clock() +{ + Kip::k()->clock = 0; +} + +IMPLEMENT inline NEEDS ["globals.h", "kip.h"] +Unsigned64 +Timer::system_clock() +{ + return Kip::k()->clock; +} + +IMPLEMENT inline NEEDS ["decrementer.h", "config.h", "kip.h"] +void +Timer::update_system_clock(unsigned cpu) +{ + if (cpu == 0) + { + Decrementer::d()->set(); + Kip::k()->clock += Config::Scheduler_granularity; + } +} + +IMPLEMENT inline +void +Timer::update_timer(Unsigned64) +{ +} diff --git a/kernel/fiasco/src/kern/sparc/timer_tick-sparc.cpp b/kernel/fiasco/src/kern/sparc/timer_tick-sparc.cpp new file mode 100644 index 00000000..8d06de0b --- /dev/null +++ b/kernel/fiasco/src/kern/sparc/timer_tick-sparc.cpp @@ -0,0 +1,7 @@ +IMPLEMENTATION [sparc]: + +#include "irq_mgr.h" + +IMPLEMENT bool +Timer_tick::allocate_irq(Irq_base *irq, unsigned irqnum) +{ return Irq_mgr::mgr->alloc(irq, irqnum); } diff --git a/kernel/fiasco/src/kern/sparc/trap_state.cpp b/kernel/fiasco/src/kern/sparc/trap_state.cpp new file mode 100644 index 00000000..ede37845 --- /dev/null +++ b/kernel/fiasco/src/kern/sparc/trap_state.cpp @@ -0,0 +1,88 @@ + +INTERFACE: + +#include "l4_types.h" +#include "entry_frame.h" + +class Trap_state_regs +{ +public: + Mword pf_address; + Mword error_code; +}; + + +class Trap_state : public Trap_state_regs, public Syscall_frame, + public Return_frame +{ +public: + typedef int (*Handler)(Trap_state*, unsigned cpu); +}; + + +IMPLEMENTATION: + +#include + +PUBLIC inline +void +Trap_state::sanitize_user_state() +{ + // implement me +} + +PUBLIC inline +unsigned long +Trap_state::ip() const +{ return srr0; } + +PUBLIC inline +unsigned long +Trap_state::trapno() const +{ return error_code; } + +PUBLIC inline +Mword +Trap_state::error() const +{ return 0; } + +PUBLIC inline +void +Trap_state::set_ipc_upcall() +{ + error_code = 0x10000000; // see Msr +} + +PUBLIC inline +void +Trap_state::set_pagefault(Mword pfa, Mword error) +{ + pf_address = pfa; + error_code = error; +} + +PUBLIC inline +bool +Trap_state::is_debug_exception() const +{ return false; } + +PUBLIC +void +Trap_state::dump() +{ + char const *excpts[] = + {"reset","machine check"}; + + printf("EXCEPTION: pfa=%08lx, error=%08lx\n", + //excpts[((error_code & ~0xff) >> 8) - 1] + pf_address, error_code); + + printf("SP: %08lx LR: %08lx SRR0: %08lx SRR1 %08lx\n\n" + "R[0] %08lx\n" + "R[3]: %08lx %08lx %08lx %08lx %08lx\n" + "R[8]: %08lx %08lx %08lx %08lx %08lx\n", + usp, ulr, srr0, srr1, + r[0], r[1], r[2], r[3], r[4], r[5], r[6], r[7], + r[8], r11, r12); +} + diff --git a/kernel/fiasco/src/kern/sparc/uart-asi.cpp b/kernel/fiasco/src/kern/sparc/uart-asi.cpp new file mode 100644 index 00000000..a75ed046 --- /dev/null +++ b/kernel/fiasco/src/kern/sparc/uart-asi.cpp @@ -0,0 +1,15 @@ +IMPLEMENTATION [libuart]: + +#include "io_regblock_asi.h" + +EXTENSION class Uart +{ + L4::Io_register_block_asi _regs; +}; + +IMPLEMENT inline Uart::Uart() : _regs(base()) {} + +PUBLIC bool Uart::startup() +{ return uart()->startup(&_regs); } + + diff --git a/kernel/fiasco/src/kern/sparc/utcb_init-sparc.cpp b/kernel/fiasco/src/kern/sparc/utcb_init-sparc.cpp new file mode 100644 index 00000000..e0aa4994 --- /dev/null +++ b/kernel/fiasco/src/kern/sparc/utcb_init-sparc.cpp @@ -0,0 +1,20 @@ +IMPLEMENTATION [sparc]: + +#include "mem_layout.h" +#include "config.h" +#include + + +IMPLEMENT +void +Utcb_init::init() +{ + //Utcb_ptr_page is physical address + memset((void*)Mem_layout::Utcb_ptr_page, 0, Config::PAGE_SIZE); +} + +PUBLIC static inline +void +Utcb_init::init_ap(Cpu const &) +{} + diff --git a/kernel/fiasco/src/kern/sparc/utcb_support-sparc.cpp b/kernel/fiasco/src/kern/sparc/utcb_support-sparc.cpp new file mode 100644 index 00000000..678d7866 --- /dev/null +++ b/kernel/fiasco/src/kern/sparc/utcb_support-sparc.cpp @@ -0,0 +1,17 @@ +//------------------------------------------------------------------------- +IMPLEMENTATION [sparc]: + +IMPLEMENT inline +User::Ptr +Utcb_support::current() +{ + Utcb *u = (Utcb*)0xDEADBEEF; + return User::Ptr(u); +} + +IMPLEMENT inline +void +Utcb_support::current(User::Ptr const &utcb) +{ + (void)utcb; +} diff --git a/kernel/fiasco/src/kern/sparc/util.cpp b/kernel/fiasco/src/kern/sparc/util.cpp new file mode 100644 index 00000000..98fd3856 --- /dev/null +++ b/kernel/fiasco/src/kern/sparc/util.cpp @@ -0,0 +1,18 @@ +INTERFACE: +#include "types.h" + +class Util +{}; + +IMPLEMENTATION: + +PUBLIC static inline +template < typename T > +T +Util::log2(T value) +{ + unsigned long c = 0; + while(value >>= 1) + c++; + return T(c); +} diff --git a/kernel/fiasco/src/kern/sparc/vmem_alloc-sparc.cpp b/kernel/fiasco/src/kern/sparc/vmem_alloc-sparc.cpp new file mode 100644 index 00000000..181bb214 --- /dev/null +++ b/kernel/fiasco/src/kern/sparc/vmem_alloc-sparc.cpp @@ -0,0 +1,29 @@ +//--------------------------------------------------------------------------- +IMPLEMENTATION [sparc]: + +#include "config.h" +#include "panic.h" +#include "warn.h" +#include "mem.h" + +IMPLEMENT +void Vmem_alloc::init() +{ + NOT_IMPL_PANIC; +} + +IMPLEMENT +void *Vmem_alloc::page_alloc(void * address, Zero_fill zf, unsigned /*mode*/) +{ + if(zf == ZERO_FILL) + Mem::memset_mwords((unsigned long *)address, 0, Config::PAGE_SIZE >> 2); + return address; +} + +IMPLEMENT +void *Vmem_alloc::page_unmap(void * /*page*/) +{ + NOT_IMPL_PANIC; + return NULL; +} + diff --git a/kernel/fiasco/src/kern/sparc/warn-sparc.cpp b/kernel/fiasco/src/kern/sparc/warn-sparc.cpp new file mode 100644 index 00000000..1466fee0 --- /dev/null +++ b/kernel/fiasco/src/kern/sparc/warn-sparc.cpp @@ -0,0 +1,5 @@ +INTERFACE [sparc]: +#include "panic.h" + +#define NOT_IMPL WARN "%s not implemented", __PRETTY_FUNCTION__ +#define NOT_IMPL_PANIC panic("%s not implemented\n", __PRETTY_FUNCTION__); diff --git a/kernel/fiasco/src/kern/spin_lock.cpp b/kernel/fiasco/src/kern/spin_lock.cpp new file mode 100644 index 00000000..dc1fc165 --- /dev/null +++ b/kernel/fiasco/src/kern/spin_lock.cpp @@ -0,0 +1,149 @@ +INTERFACE: + +#include "cpu_lock.h" + +/** + * \brief Basic spin lock. + * + * Also disables lock IRQs for the time the lock is held. + * In the UP case it is in fact just the Cpu_lock. + */ +template +class Spin_lock : private Cpu_lock +{ +public: + enum Lock_init { Unlocked = 0 }; +}; + +//-------------------------------------------------------------------------- +INTERFACE [!mp]: + +EXTENSION class Spin_lock +{ +public: + Spin_lock() {} + explicit Spin_lock(Lock_init) {} + void init() {} + + using Cpu_lock::Status; + using Cpu_lock::test; + using Cpu_lock::lock; + using Cpu_lock::clear; + using Cpu_lock::test_and_set; + using Cpu_lock::set; + +}; + +/** + * \brief Version of a spin lock that is colocated with another value. + */ +template< typename T > +class Spin_lock_coloc : public Spin_lock +{ +private: + enum { Arch_lock = 1 }; + Mword _lock; +}; + + +//-------------------------------------------------------------------------- +INTERFACE [mp]: + +EXTENSION class Spin_lock +{ +public: + typedef Mword Status; + Spin_lock() {} + explicit Spin_lock(Lock_init i) : _lock((i == Unlocked) ? 0 : Arch_lock) {} + +protected: + Lock_t _lock; +}; + +/** + * \brief Version of a spin lock that is colocated with another value. + */ +template< typename T > +class Spin_lock_coloc : public Spin_lock +{ +}; + +//-------------------------------------------------------------------------- +IMPLEMENTATION: + +PUBLIC inline +template< typename T > +T +Spin_lock_coloc::get_unused() const +{ return (T)(_lock & ~Arch_lock); } + +PUBLIC inline +template< typename T > +void +Spin_lock_coloc::set_unused(T val) +{ _lock = (_lock & Arch_lock) | (Mword)val; } + + +//-------------------------------------------------------------------------- +IMPLEMENTATION [mp]: + +#include +#include "mem.h" + +PUBLIC template inline +void +Spin_lock::init() +{ + _lock = 0; +} + +PUBLIC template inline +typename Spin_lock::Status +Spin_lock::test() const +{ + return (!!cpu_lock.test()) | (_lock & Arch_lock); +} + +PUBLIC template inline NEEDS[, Spin_lock::lock_arch, "mem.h"] +void +Spin_lock::lock() +{ + assert(!cpu_lock.test()); + cpu_lock.lock(); + lock_arch(); + Mem::mp_mb(); +} + +PUBLIC template inline NEEDS[Spin_lock::unlock_arch, "mem.h"] +void +Spin_lock::clear() +{ + Mem::mp_mb(); + unlock_arch(); + Cpu_lock::clear(); +} + +PUBLIC template inline NEEDS[Spin_lock::lock_arch, "mem.h"] +typename Spin_lock::Status +Spin_lock::test_and_set() +{ + Status s = !!cpu_lock.test(); + cpu_lock.lock(); + lock_arch(); + Mem::mp_mb(); + return s; +} + +PUBLIC template inline +void +Spin_lock::set(Status s) +{ + Mem::mp_mb(); + if (!(s & Arch_lock)) + unlock_arch(); + + if (!(s & 1)) + cpu_lock.clear(); +} + + diff --git a/kernel/fiasco/src/kern/startup.cpp b/kernel/fiasco/src/kern/startup.cpp new file mode 100644 index 00000000..d3cf2400 --- /dev/null +++ b/kernel/fiasco/src/kern/startup.cpp @@ -0,0 +1,20 @@ +INTERFACE: + +class Startup +{ +public: + // startup code for the early startup phase + // this code is executed before anything else, inparticular before + // any I/O is initialized + static void stage1(); + + // startup code that runs after console I/O is initialized + static void stage2(); +}; + +IMPLEMENTATION: + +#include "static_init.h" + +STATIC_INITIALIZEX_P(Startup, stage1, STARTUP1_INIT_PRIO); +STATIC_INITIALIZEX_P(Startup, stage2, STARTUP_INIT_PRIO); diff --git a/kernel/fiasco/src/kern/static_assert.h b/kernel/fiasco/src/kern/static_assert.h new file mode 100644 index 00000000..9d7e72d6 --- /dev/null +++ b/kernel/fiasco/src/kern/static_assert.h @@ -0,0 +1,9 @@ +#ifndef __STATIC_ASSERT_H__ +#define __STATIC_ASSERT_H__ + +#ifndef __GXX_EXPERIMENTAL_CXX0X__ +#define static_assert(x, y) \ + do { (void)sizeof(char[-(!(x))]); } while (0) +#endif + +#endif diff --git a/kernel/fiasco/src/kern/static_init.h b/kernel/fiasco/src/kern/static_init.h new file mode 100644 index 00000000..0c6a9a19 --- /dev/null +++ b/kernel/fiasco/src/kern/static_init.h @@ -0,0 +1,120 @@ +/* -*- c++ -*- */ + +#include "initcalls.h" + +/** + * definitions for static, pre-main initialization stuff + */ +#ifndef STATIC_INIT_H +#define STATIC_INIT_H + +/// Priorities for ordered static initialization +//@{ + +#define DEPENDS_ON(SUBSYS) ((SUBSYS) + 2) + +#define LINKER_INTERNAL 100 // linker internal use +#define UX_STARTUP1_INIT_PRIO DEPENDS_ON(LINKER_INTERNAL) +#define EARLY_INIT_PRIO DEPENDS_ON(UX_STARTUP1_INIT_PRIO) +#define STARTUP1_INIT_PRIO DEPENDS_ON(EARLY_INIT_PRIO) +// at this stage spinlocks must be working +#define ROOT_FACTORY_INIT_PRIO DEPENDS_ON(STARTUP1_INIT_PRIO) +#define GDB_INIT_PRIO DEPENDS_ON(ROOT_FACTORY_INIT_PRIO) +#define STARTUP_INIT_PRIO DEPENDS_ON(GDB_INIT_PRIO) +#define CPU_LOCAL_BASE_INIT_PRIO DEPENDS_ON(STARTUP_INIT_PRIO) +#define CPU_LOCAL_INIT_PRIO DEPENDS_ON(CPU_LOCAL_BASE_INIT_PRIO) +#define POST_CPU_LOCAL_INIT_PRIO DEPENDS_ON(CPU_LOCAL_INIT_PRIO) +#define PERF_CNT_INIT_PRIO DEPENDS_ON(POST_CPU_LOCAL_INIT_PRIO) +#define JDB_CATEGORY_INIT_PRIO DEPENDS_ON(POST_CPU_LOCAL_INIT_PRIO) +#define JDB_MODULE_INIT_PRIO DEPENDS_ON(JDB_CATEGORY_INIT_PRIO) + +#define WATCHDOG_INIT DEPENDS_ON(PERF_CNT_INIT_PRIO) +#define KDB_INIT_PRIO DEPENDS_ON(JDB_MODULE_INIT_PRIO) +#define JDB_INIT_PRIO DEPENDS_ON(KDB_INIT_PRIO) + +#define INIT_PRIORITY(a) __attribute__((init_priority(a))) + +//@} + + + +/* ATTENTION: WARNING: DON'T READ ANY FURTHER !!! */ +/* The following definitions are likely to cause */ +/* extreme and irreparable BRAIN DAMAGE. */ +/* (I already tested this on my unsuspecting */ +/* colleagues) */ + +/** + * \defgroup Magic static initializer macros + */ +//@{ +#define __STATIC_INITIALIZER(_func, va) \ +class static_init_##va { \ +public: \ + static_init_##va() FIASCO_INIT; \ +};\ +static_init_##va::static_init_##va() { \ + _func(); \ +} \ +static static_init_##va __static_construction_of_##va##__ + +#define __STATIC_INITIALIZER_P(_func, va, prio) \ +class static_init_##va { \ +public: \ + static_init_##va() FIASCO_INIT; \ +};\ +static_init_##va::static_init_##va() { \ + _func(); \ +} \ +static static_init_##va __static_construction_of_##va##__ \ + __attribute__((init_priority(prio))) +//@} + + + +/** + * \defgroup Macros to define static init functions + */ +//@{ + +/// mark f as static initializer with priority p +#define STATIC_INITIALIZER_P(f, p) \ + __STATIC_INITIALIZER_P(f,func_##f,p) + +/// mark f as static initailizer +#define STATIC_INITIALIZER(f) \ + __STATIC_INITIALIZER(f,func_##f) +//@} + + +/// static initialization of singleton (static) classes +/** + * The classes that should be initialized must provide + * a init() member function that takes no arguments. + */ +//@{ + +/** mark class c to be statically initialized via its init + * function and with priority p + */ +#define STATIC_INITIALIZE_P(c,p) \ + __STATIC_INITIALIZER_P(c::init, class_##c,p) + +/// mark class c to be statically initialized via its init function +#define STATIC_INITIALIZE(c) \ + __STATIC_INITIALIZER(c::init, class_##c) + +/** mark class c to be statically initialized via its init + * function and with priority p + */ +#define STATIC_INITIALIZEX_P(c,func,p) \ + __STATIC_INITIALIZER_P(c::func, class_##c##_##func,p) + +/// mark class c to be statically initialized via its init function +#define STATIC_INITIALIZEX(c,func) \ + __STATIC_INITIALIZER(c::func, class_##c##_##func) +//@} + + + +#endif // __STATIC_INIT_H__ diff --git a/kernel/fiasco/src/kern/switch_lock.cpp b/kernel/fiasco/src/kern/switch_lock.cpp new file mode 100644 index 00000000..9253eef5 --- /dev/null +++ b/kernel/fiasco/src/kern/switch_lock.cpp @@ -0,0 +1,392 @@ +INTERFACE: + +#include "member_offs.h" +#include + +#ifdef NO_INSTRUMENT +#undef NO_INSTRUMENT +#endif +#define NO_INSTRUMENT __attribute__((no_instrument_function)) + +class Context; + + +/** A lock that implements priority inheritance. + * + * The lock uses a validity checker (VALID) for doing an existence check + * before the lock is actually acquired. With this mechanism the lock itself + * may disappear while it is locked (see clear_no_switch_dirty() and + * switch_dirty()), even if it is under contention. When the lock no longer + * exists VALID::valid(void const *lock) must return false, true if it + * exists (see Switch_lock_valid). This mechanism is used in Thread_lock + * when thread control blocks are deallocated. + * + * The operations lock(), lock_dirty(), try_lock(), test(), test_and_set(), + * and test_and_set_dirty() may return #Invalid if the lock does + * no longer exist. + * + * The operations initialize(), lock_owner(), clear(), clear_dirty(), and + * clear_no_switch_dirty() must not being called on and invalid lock, + * thus the lock itself must be held for using these operations. + * (Except initialize(), which is only useful for locks that are always + * valid.) + * + * @param VALID must be set to a validity checker for the lock. + * + * The validity checker is used while aquiring the lock to test + * if the lock itself existis. We assume that a lock may disappear + * while we are blocked on it. + */ +class Switch_lock +{ + MEMBER_OFFSET(); + +private: + // Warning: This lock's member variables must not need a + // constructor. Switch_lock instances must assume + // zero-initialization or be initialized using the initialize() + // member function. + // Reason: to avoid overwriting the lock in the thread-ctor + Address _lock_owner; + +public: + /** + * @brief The result type of lock operations. + */ + enum Status + { + Not_locked, ///< The lock was formerly not aquired and -- we got it + Locked, ///< The lock was already aquired by ourselves + Invalid ///< The lock does not exist (is invalid) + }; + + /** + * Stores the context of the lock for a later switch. + * (see clear_no_switch_dirty(), switch_dirty()) + */ + struct Lock_context + { + Context *owner; + }; +}; + +#undef NO_INSTRUMENT +#define NO_INSTRUMENT + + +IMPLEMENTATION: + +#include + +#include "cpu.h" +#include "atomic.h" +#include "cpu_lock.h" +#include "lock_guard.h" +#include "context.h" +#include "globals.h" +#include "processor.h" + + +// +// Switch_lock inlines +// + +/** + * Test if the lock is valid (uses the validity checker). + * @return true if the lock really exists, false if not. + */ +PUBLIC +inline +bool NO_INSTRUMENT +Switch_lock::valid() const +{ return (_lock_owner & 1) == 0; } + +/** Initialize Switch_lock. Call this function if you cannot + guarantee that your Switch_lock instance is allocated from + zero-initialized memory. */ +PUBLIC +inline +void NO_INSTRUMENT +Switch_lock::initialize() +{ + _lock_owner = 0; +} + +/** Lock owner. + * @pre The lock must be valid (see valid()). + * @return current owner of the lock. 0 if there is no owner. + */ +PUBLIC +inline +Context * NO_INSTRUMENT +Switch_lock::lock_owner() const +{ + Lock_guard guard(&cpu_lock); + return (Context*)(_lock_owner & ~1UL); +} + +/** Is lock set?. + @return #Locked if lock is set, #Not_locked if not locked, and #Invalid if + the lock does not exist (see valid()). + */ +PUBLIC +inline +Switch_lock::Status NO_INSTRUMENT +Switch_lock::test() const +{ + Lock_guard guard(&cpu_lock); + if (EXPECT_FALSE(!valid())) + return Invalid; + return (_lock_owner & ~1UL) ? Locked : Not_locked; +} + +/** Try to acquire the lock. + @return #Locked if successful: current context is now the owner of the lock. + #Not_locked if lock has previously been set. Returns Not_locked + even if the current context is already the lock owner. + The result is #Invalid if the lock does not exist (see valid()). + */ + +inline NEEDS["atomic.h"] +Switch_lock::Status NO_INSTRUMENT +Switch_lock::try_lock() +{ + Lock_guard guard(&cpu_lock); + + if (EXPECT_FALSE(!valid())) + return Invalid; + + bool ret = cas(&_lock_owner, (Address)0, Address(current())); + + if (ret) + current()->inc_lock_cnt(); // Do not lose this lock if current is deleted + + return ret ? Locked : Not_locked; +} + +/** Acquire the lock with priority inheritance. + * If the lock is occupied, enqueue in list of helpers and lend CPU + * to current lock owner until we are the lock owner. + * @return #Locked if the lock was already locked by the current context. + * #Not_locked if the current context got the lock (the usual case). + * #Invalid if the lock does not exist (see valid()). + */ +PUBLIC +Switch_lock::Status NO_INSTRUMENT +Switch_lock::lock() +{ + Lock_guard guard(&cpu_lock); + return lock_dirty(); +} + +/** Acquire the lock with priority inheritance. + * If the lock is occupied, enqueue in list of helpers and lend CPU + * to current lock owner until we are the lock owner (see lock()). + * @pre caller holds cpu lock + * @return #Locked if the lock was already locked by the current context. + * #Not_locked if the current context got the lock (the usual case). + * #Invalid if the lock does not exist (see valid()). + */ +PUBLIC +inline NEEDS["cpu.h","context.h", "processor.h", Switch_lock::set_lock_owner] +Switch_lock::Status NO_INSTRUMENT +Switch_lock::lock_dirty() +{ + assert(cpu_lock.test()); + + if (!valid()) + return Invalid; + + // have we already the lock? + if ((_lock_owner & ~1UL) == Address(current())) + return Locked; + + while (test()) + { + assert(cpu_lock.test()); + + // Help lock owner until lock becomes free + // while (test()) + bool tmp = current()->switch_exec_locked(lock_owner(), Context::Helping); + (void)tmp; + + Proc::irq_chance(); + + if (!valid()) + return Invalid; + } + + set_lock_owner(current()); + + current()->inc_lock_cnt(); // Do not lose this lock if current is deleted + return Not_locked; +} + + +/** Acquire the lock with priority inheritance. + * @return #Locked if we owned the lock already. #Not_locked otherwise. + * #Invalid is returned if the lock does not exist (see valid()). + */ +PUBLIC +inline NEEDS["globals.h"] +Switch_lock::Status NO_INSTRUMENT +Switch_lock::test_and_set() +{ + return lock(); +} + +/** Acquire the lock with priority inheritance (see test_and_set()). + * @return #Locked if we owned the lock already. #Not_locked otherwise. + * #Invalid is returned if the lock does not exist (see valid()). + * @pre caller holds cpu lock + */ +PUBLIC +inline NEEDS["globals.h"] +Switch_lock::Status NO_INSTRUMENT +Switch_lock::test_and_set_dirty() +{ + return lock_dirty(); +} + +PRIVATE inline +void NO_INSTRUMENT +Switch_lock::set_lock_owner(Context *o) +{ + _lock_owner = Address(o) | (_lock_owner & 1); +} + +/** + * Clear the lock, however do not switch to a potential helper yet. + * This function is used when the lock must be cleared and the object + * containing the lock will be deallocated atomically. We have to do the + * switch later using switch_dirty(Lock_context). + * @return the context for a later switch_dirty() + * @pre The lock must be valid (see valid()). + * @pre caller hold cpu lock + * @post switch_dirty() must be called in the same atomical section + */ +PROTECTED +inline NEEDS[Switch_lock::set_lock_owner] +Switch_lock::Lock_context NO_INSTRUMENT +Switch_lock::clear_no_switch_dirty() +{ + Lock_context c; + c.owner = lock_owner(); + set_lock_owner(0); + c.owner->dec_lock_cnt(); + return c; +} + +/** + * Do the switch part of clear() after a clear_no_switch_dirty(). + * This function does not touch the lock itself (may be called on + * an invalid lock). + * @param c the context returned by a former clear_no_switch_dirty(). + * @pre must be called atomically with clear_no_switch_dirty(), + * under the same cpu lock + */ +PROTECTED +static inline +void NO_INSTRUMENT +Switch_lock::switch_dirty(Lock_context const &c) +{ + assert_kdb (current() == c.owner); + + Context *h = c.owner->helper(); + /* + * If someone helped us by lending its time slice to us. + * Just switch back to the helper without changing its helping state. + */ + bool need_sched = false; + if (h != c.owner) + need_sched = c.owner->switch_exec_locked(h, Context::Ignore_Helping); + + /* + * Someone apparently tries to delete us. Therefore we aren't + * allowed to continue to run and therefore let the scheduler + * pick the next thread to execute. + */ + if (need_sched || (c.owner->lock_cnt() == 0 && c.owner->donatee())) + c.owner->schedule(); +} + +/** Free the lock. + Return the CPU to helper if there is one, since it had to have a + higher priority to be able to help (priority may be its own, it + may run on a donated timeslice or round robin scheduling may have + selected a thread on the same priority level as me) + + @pre The lock must be valid (see valid()). + */ +PUBLIC +void NO_INSTRUMENT +Switch_lock::clear() +{ + Lock_guard guard(&cpu_lock); + + switch_dirty(clear_no_switch_dirty()); +} + +PUBLIC +void NO_INSTRUMENT +Switch_lock::set(Status s) +{ + if (s == Not_locked) + clear(); +} + +/** Free the lock. + Return the CPU to helper if there is one, since it had to have a + higher priority to be able to help (priority may be its own, it + may run on a donated timeslice or round robin scheduling may have + selected a thread on the same priority level as me). + If _lock_owner is 0, then this is a no op + + @pre The lock must be valid (see valid()) + @pre caller holds cpu lock + */ +PUBLIC +inline +void NO_INSTRUMENT +Switch_lock::clear_dirty() +{ + assert(cpu_lock.test()); + + switch_dirty(clear_no_switch_dirty()); +} + +PUBLIC inline +void NO_INSTRUMENT +Switch_lock::invalidate() +{ + Lock_guard guard(&cpu_lock); + _lock_owner |= 1; +} + +PUBLIC +void NO_INSTRUMENT +Switch_lock::wait_free() +{ + Lock_guard guard(&cpu_lock); + + assert (!valid()); + + // have we already the lock? + if ((_lock_owner & ~1UL) == (Address)current()) + { + set_lock_owner(0); + current()->dec_lock_cnt(); + return; + } + + while (Address(_lock_owner) & ~1UL) + { + assert(cpu_lock.test()); + + // Help lock owner until lock becomes free + // while (test()) + check (!current()->switch_exec_locked((Context*)(Address(_lock_owner & ~1UL)), Context::Helping)); + + Proc::irq_chance(); + } +} diff --git a/kernel/fiasco/src/kern/sys_call_page.cpp b/kernel/fiasco/src/kern/sys_call_page.cpp new file mode 100644 index 00000000..a2b27480 --- /dev/null +++ b/kernel/fiasco/src/kern/sys_call_page.cpp @@ -0,0 +1,19 @@ +INTERFACE [abs_syscalls]: + +#include "initcalls.h" + +class Sys_call_page +{ +public: + + static void init() FIASCO_INIT; +}; + +IMPLEMENTATION [abs_syscalls]: + +#include "static_init.h" + +#include +KIP_KERNEL_FEATURE("kip_syscalls"); + +STATIC_INITIALIZE(Sys_call_page); diff --git a/kernel/fiasco/src/kern/syscalls-log.cpp b/kernel/fiasco/src/kern/syscalls-log.cpp new file mode 100644 index 00000000..9615a1f5 --- /dev/null +++ b/kernel/fiasco/src/kern/syscalls-log.cpp @@ -0,0 +1,126 @@ +IMPLEMENTATION [log]: + +#include +#include "config.h" +#include "jdb_trace.h" +#include "jdb_tbuf.h" +#include "types.h" +#include "cpu_lock.h" + + +/** IPC logging. + called from interrupt gate. + */ +extern "C" void sys_ipc_log_wrapper(void) +{ + Thread *curr = current_thread(); + Entry_frame *regs = reinterpret_cast(curr->regs()); + Syscall_frame *ipc_regs = reinterpret_cast(curr->regs()); + + Mword entry_event_num = (Mword)-1; + Unsigned8 have_snd = (ipc_regs->ref().op() & L4_obj_ref::Ipc_send) + || (ipc_regs->ref().op() == L4_obj_ref::Ipc_call); + Unsigned8 is_next_period = ipc_regs->next_period(); + Utcb *utcb = curr->utcb().access(true); + int do_log = Jdb_ipc_trace::log() && + Jdb_ipc_trace::check_restriction (curr->dbg_id(), + static_cast(curr->space())->dbg_id(), + ipc_regs, 0); + + if (Jdb_nextper_trace::log() && is_next_period) + { + Tb_entry_ipc *tb = static_cast(Jdb_tbuf::new_entry()); + tb->set(curr, regs->ip(), ipc_regs, utcb, + 0, curr->sched_context()->left()); + Jdb_tbuf::commit_entry(); + goto skip_ipc_log; + } + + if (do_log) + { + Mword dbg_id; + { + Obj_cap r = ipc_regs->ref(); + unsigned char rights; + Kobject_iface *o = r.deref(&rights, true); + if (o) + dbg_id = o->dbg_info()->dbg_id(); + else + dbg_id = ~0UL; + } + Tb_entry_ipc _local; + Tb_entry_ipc *tb = static_cast + (EXPECT_TRUE(Jdb_ipc_trace::log_buf()) ? Jdb_tbuf::new_entry() + : &_local); + tb->set(curr, regs->ip(), ipc_regs, utcb, + dbg_id, curr->sched_context()->left()); + + entry_event_num = tb->number(); + + if (EXPECT_TRUE(Jdb_ipc_trace::log_buf())) + Jdb_tbuf::commit_entry(); + else + Jdb_tbuf::direct_log_entry(tb, "IPC"); + } + +skip_ipc_log: + + // now pass control to regular sys_ipc() + sys_ipc_wrapper(); + + if (Jdb_nextper_trace::log() && is_next_period) + { + Tb_entry_ipc_res *tb = + static_cast(Jdb_tbuf::new_entry()); + tb->set(curr, regs->ip(), ipc_regs, utcb, 0, + entry_event_num, have_snd, is_next_period); + Jdb_tbuf::commit_entry(); + goto skip_ipc_res_log; + } + + if (Jdb_ipc_trace::log() && Jdb_ipc_trace::log_result() && do_log) + { + Tb_entry_ipc_res _local; + Tb_entry_ipc_res *tb = static_cast + (EXPECT_TRUE(Jdb_ipc_trace::log_buf()) ? Jdb_tbuf::new_entry() + : &_local); + tb->set(curr, regs->ip(), ipc_regs, utcb, utcb->error.raw(), + entry_event_num, have_snd, is_next_period); + + if (EXPECT_TRUE(Jdb_ipc_trace::log_buf())) + Jdb_tbuf::commit_entry(); + else + Jdb_tbuf::direct_log_entry(tb, "IPC result"); + } + +skip_ipc_res_log: + ; +} + +/** IPC tracing. + */ +extern "C" void sys_ipc_trace_wrapper(void) +{ + Thread *curr = current_thread(); + Entry_frame *ef = nonull_static_cast(curr->regs()); + Syscall_frame *regs = curr->regs(); + + //Mword from_spec = regs->from_spec(); + L4_obj_ref snd_dst = regs->ref(); + + Unsigned64 orig_tsc = Cpu::rdtsc(); + + // first try the fastpath, then the "slowpath" + sys_ipc_wrapper(); + + // kernel is locked here => no Lock_guard <...> needed + Tb_entry_ipc_trace *tb = + static_cast(Jdb_tbuf::new_entry()); + + tb->set(curr, ef->ip(), orig_tsc, snd_dst, regs->from_spec(), + L4_msg_tag(0,0,0,0), 0, 0); + + Jdb_tbuf::commit_entry(); +} + + diff --git a/kernel/fiasco/src/kern/syscalls.cpp b/kernel/fiasco/src/kern/syscalls.cpp new file mode 100644 index 00000000..b55ff86f --- /dev/null +++ b/kernel/fiasco/src/kern/syscalls.cpp @@ -0,0 +1,69 @@ +IMPLEMENTATION: + +#include "thread_object.h" +#include "thread_state.h" + +extern "C" +void __attribute__((flatten)) +sys_ipc_wrapper() +{ + assert_kdb (!(current()->state() & Thread_drq_ready)); + + Thread *curr = current_thread(); + Syscall_frame *f = curr->regs(); + + Obj_cap obj = f->ref(); + Utcb *utcb = curr->utcb().access(true); + unsigned char rights; + Kobject_iface *o = obj.deref(&rights); + L4_msg_tag e; + if (EXPECT_TRUE(o!=0)) + o->invoke(obj, rights, f, utcb); + else + f->tag(curr->commit_error(utcb, L4_error::Not_existent)); +} + + +//--------------------------------------------------------------------------- +IMPLEMENTATION [debug]: + +#include "space.h" +#include "task.h" + +extern "C" void sys_invoke_debug(Kobject_iface *o, Syscall_frame *f) __attribute__((weak)); + +extern "C" void __attribute__((flatten)) sys_invoke_debug_wrapper() +{ + Thread *curr = current_thread(); + Syscall_frame *f = curr->regs(); + //printf("sys_invoke_debugger(f=%p, obj=%lx)\n", f, f->ref().raw()); + Kobject_iface *o = curr->space()->lookup_local(f->ref().cap()); + if (o && &::sys_invoke_debug) + ::sys_invoke_debug(o, f); + else + f->tag(curr->commit_error(curr->utcb().access(true), L4_error::Not_existent)); +} + +//--------------------------------------------------------------------------- +IMPLEMENTATION [!debug]: + +#include "thread.h" + +extern "C" void sys_invoke_debug_wrapper() {} + +//--------------------------------------------------------------------------- +INTERFACE [ia32 || ux || amd64]: + +extern void (*syscall_table[])(); + + +//--------------------------------------------------------------------------- +IMPLEMENTATION [ia32 || ux || amd64]: + +void (*syscall_table[])() = +{ + sys_ipc_wrapper, + 0, + sys_invoke_debug_wrapper, +}; + diff --git a/kernel/fiasco/src/kern/task.cpp b/kernel/fiasco/src/kern/task.cpp new file mode 100644 index 00000000..f9d8c9a3 --- /dev/null +++ b/kernel/fiasco/src/kern/task.cpp @@ -0,0 +1,615 @@ +INTERFACE: + +#include "context.h" +#include "kobject.h" +#include "l4_types.h" +#include "rcupdate.h" +#include "space.h" +#include "spin_lock.h" + +/** + * \brief A task is a protection domain. + * + * A is derived from Space, which aggregates a set of address spaces. + * Additionally to a space, a task provides initialization and + * destruction functionality for a protection domain. + * Task is also derived from Rcu_item to provide RCU shutdown of tasks. + */ +class Task : + public Kobject, + public Space +{ + FIASCO_DECLARE_KOBJ(); + + friend class Jdb_space; + +private: + /// \brief Do host (platform) specific initialization. + void ux_init(); + +public: + enum Operation + { + Map = 0, + Unmap = 1, + Cap_info = 2, + Add_ku_mem = 3, + Ldt_set_x86 = 0x11, + }; + +private: + /// map the global utcb pointer page into this task + void map_utcb_ptr_page(); +}; + + +//--------------------------------------------------------------------------- +IMPLEMENTATION: + +#include "atomic.h" +#include "unique_ptr.h" +#include "config.h" +#include "entry_frame.h" +#include "globals.h" +#include "kdb_ke.h" +#include "kmem.h" +#include "kmem_slab.h" +#include "l4_types.h" +#include "l4_buf_iter.h" +#include "logdefs.h" +#include "map_util.h" +#include "mem_layout.h" +#include "ram_quota.h" +#include "thread_state.h" +#include "paging.h" + +FIASCO_DEFINE_KOBJ(Task); + +static Kmem_slab_t _k_u_mem_list_alloc("Ku_mem"); +Slab_cache *Space::Ku_mem::a = &_k_u_mem_list_alloc; + +extern "C" void vcpu_resume(Trap_state *, Return_frame *sp) + FIASCO_FASTCALL FIASCO_NORETURN; + +PUBLIC virtual +int +Task::resume_vcpu(Context *ctxt, Vcpu_state *vcpu, bool user_mode) +{ + Trap_state ts; + memcpy(&ts, &vcpu->_ts, sizeof(Trap_state)); + + assert_kdb(cpu_lock.test()); + + ts.sanitize_user_state(); + + // FIXME: UX is currently broken + /* UX:ctxt->vcpu_resume_user_arch(); */ + if (user_mode) + { + ctxt->state_add_dirty(Thread_vcpu_user); + vcpu->state |= Vcpu_state::F_traps | Vcpu_state::F_exceptions + | Vcpu_state::F_debug_exc; + } + + ctxt->space_ref()->user_mode(user_mode); + switchin_context(ctxt->space()); + vcpu_resume(&ts, ctxt->regs()); +} + +PUBLIC virtual +bool +Task::put() +{ return dec_ref() == 0; } + +PRIVATE +int +Task::alloc_ku_mem_chunk(User::Ptr u_addr, unsigned size, void **k_addr) +{ + assert_kdb ((size & (size - 1)) == 0); + + Kmem_alloc *const alloc = Kmem_alloc::allocator(); + void *p = alloc->q_unaligned_alloc(ram_quota(), size); + + if (EXPECT_FALSE(!p)) + return -L4_err::ENomem; + + // clean up utcbs + memset(p, 0, size); + + unsigned long page_size = Config::PAGE_SIZE; + + // the following works because the size is a power of two + // and once we have size larger than a super page we have + // always multiples of superpages + if (size >= Config::SUPERPAGE_SIZE) + page_size = Config::SUPERPAGE_SIZE; + + for (unsigned long i = 0; i < size; i += page_size) + { + Address kern_va = (Address)p + i; + Address user_va = (Address)u_addr.get() + i; + Address pa = pmem_to_phys(kern_va); + + // must be valid physical address + assert(pa != ~0UL); + + Mem_space::Status res = + static_cast(this)->v_insert(Mem_space::Phys_addr(pa), + Mem_space::Addr(user_va), Mem_space::Size(page_size), + Mem_space::Page_writable | Mem_space::Page_user_accessible + | Mem_space::Page_cacheable); + + switch (res) + { + case Mem_space::Insert_ok: break; + case Mem_space::Insert_err_nomem: + free_ku_mem_chunk(p, u_addr, size, i); + return -L4_err::ENomem; + + case Mem_space::Insert_err_exists: + free_ku_mem_chunk(p, u_addr, size, i); + return -L4_err::EExists; + + default: + printf("UTCB mapping failed: va=%p, ph=%p, res=%d\n", + (void*)user_va, (void*)kern_va, res); + kdb_ke("BUG in utcb allocation"); + free_ku_mem_chunk(p, u_addr, size, i); + return 0; + } + } + + *k_addr = p; + return 0; +} + + +PRIVATE +int +Task::alloc_ku_mem(L4_fpage ku_area) +{ + if (ku_area.order() < Config::PAGE_SHIFT || ku_area.order() > 20) + return -L4_err::EInval; + + Mword sz = 1UL << ku_area.order(); + + Ku_mem *m = new (ram_quota()) Ku_mem(); + + if (!m) + return -L4_err::ENomem; + + User::Ptr u_addr((void*)Virt_addr(ku_area.mem_address()).value()); + + void *p; + if (int e = alloc_ku_mem_chunk(u_addr, sz, &p)) + { + m->free(ram_quota()); + return e; + } + + m->u_addr = u_addr; + m->k_addr = p; + m->size = sz; + + _ku_mem.add(m, mp_cas); + + return 0; +} + +PRIVATE inline NOEXPORT +void +Task::free_ku_mem(Ku_mem *m) +{ + free_ku_mem_chunk(m->k_addr, m->u_addr, m->size, m->size); + m->free(ram_quota()); +} + +PRIVATE +void +Task::free_ku_mem_chunk(void *k_addr, User::Ptr u_addr, unsigned size, + unsigned mapped_size) +{ + + Kmem_alloc * const alloc = Kmem_alloc::allocator(); + unsigned long page_size = Config::PAGE_SIZE; + + // the following works because the size is a poer of two + // and once we have size larger than a super page we have + // always multiples of superpages + if (size >= Config::SUPERPAGE_SIZE) + page_size = Config::SUPERPAGE_SIZE; + + for (unsigned long i = 0; i < mapped_size; i += page_size) + { + Address user_va = (Address)u_addr.get() + i; + static_cast(this)->v_delete(Mem_space::Addr(user_va), + Mem_space::Size(page_size)); + } + + alloc->q_unaligned_free(ram_quota(), size, k_addr); +} + +PRIVATE +void +Task::free_ku_mem() +{ + while (Ku_mem *m = _ku_mem.pop_front()) + free_ku_mem(m); +} + + +/** Allocate space for the UTCBs of all threads in this task. + * @ return true on success, false if not enough memory for the UTCBs + */ +PUBLIC +bool +Task::initialize() +{ + if (!Mem_space::initialize()) + return false; + + // For UX, map the UTCB pointer page. For ia32, do nothing + map_utcb_ptr_page(); + + return true; +} + +/** + * \brief Create a normal Task. + * \pre \a parent must be valid and exist. + */ +PUBLIC explicit +Task::Task(Ram_quota *q) : Space(q) +{ + ux_init(); + + // increment reference counter from zero + inc_ref(true); +} + +PROTECTED +Task::Task(Ram_quota *q, Mem_space::Dir_type* pdir) +: Space(q, pdir) +{ + // increment reference counter from zero + inc_ref(true); +} + +// The allocator for tasks +static Kmem_slab_t _task_allocator("Task"); + +PROTECTED static +Slab_cache* +Task::allocator() +{ return &_task_allocator; } + + +PROTECTED inline +void * +Task::operator new (size_t size, void *p) throw() +{ + (void)size; + assert (size == sizeof (Task)); + return p; +} + + +PUBLIC //inline +void +Task::operator delete (void *ptr) +{ + Task *t = reinterpret_cast(ptr); + LOG_TRACE("Kobject delete", "del", current(), __fmt_kobj_destroy, + Log_destroy *l = tbe->payload(); + l->id = t->dbg_id(); + l->obj = t; + l->type = "Task"; + l->ram = t->ram_quota()->current()); + + allocator()->q_free(t->ram_quota(), ptr); +} + + +PUBLIC template< typename TARGET > +static +Task * +Task::create(Ram_quota *quota, L4_fpage const &utcb_area) +{ + void *t = allocator()->q_alloc(quota); + if (!t) + return 0; + + cxx::unique_ptr a(new (t) TARGET(quota)); + + if (!a->initialize()) + return 0; + + a->sync_kernel(); + + if (utcb_area.is_valid()) + { + int e = a->alloc_ku_mem(utcb_area); + if (e < 0) + return 0; + } + + return a.release(); +} + +/** + * \brief Shutdown the task. + * + * Currently: + * -# Unbind and delete all contexts bound to this task. + * -# Unmap everything from all spaces. + * -# Delete child tasks. + */ +PUBLIC +void +Task::destroy(Kobject ***reap_list) +{ + Kobject::destroy(reap_list); + + fpage_unmap(this, L4_fpage::all_spaces(L4_fpage::RWX), L4_map_mask::full(), reap_list); + Space::destroy(); +} + +PRIVATE inline NOEXPORT +L4_msg_tag +Task::sys_map(unsigned char rights, Syscall_frame *f, Utcb *utcb) +{ + LOG_TRACE("Task map", "map", ::current(), __task_unmap_fmt, + Log_unmap *lu = tbe->payload(); + lu->id = dbg_id(); + lu->mask = utcb->values[1]; + lu->fpage = utcb->values[2]); + + if (EXPECT_FALSE(!(rights & L4_fpage::W))) + return commit_result(-L4_err::EPerm); + + L4_msg_tag const tag = f->tag(); + + Obj_space *s = current()->space(); + assert (s); + L4_snd_item_iter snd_items(utcb, tag.words()); + + if (EXPECT_FALSE(!tag.items() || !snd_items.next())) + return commit_result(-L4_err::EInval); + + L4_fpage src_task(snd_items.get()->d); + if (EXPECT_FALSE(!src_task.is_objpage())) + return commit_result(-L4_err::EInval); + + Task *from = Kobject::dcast(s->lookup_local(src_task.obj_index())); + if (!from) + return commit_result(-L4_err::EInval); + + ::Reap_list rl; + L4_error ret; + + { + // enforce lock order to prevent deadlocks. + // always take lock from task with the lower memory address first + Lock_guard_2 guard; + + // FIXME: avoid locking the current task, it is not needed + if (!guard.lock(&existence_lock, &from->existence_lock)) + return commit_result(-L4_err::EInval); + + cpu_lock.clear(); + + ret = fpage_map(from, L4_fpage(utcb->values[2]), this, + L4_fpage::all_spaces(), L4_msg_item(utcb->values[1]), &rl); + cpu_lock.lock(); + } + + cpu_lock.clear(); + rl.del(); + cpu_lock.lock(); + + // FIXME: treat reaped stuff + if (ret.ok()) + return commit_result(0); + else + return commit_error(utcb, ret); +} + + +PRIVATE inline NOEXPORT +L4_msg_tag +Task::sys_unmap(Syscall_frame *f, Utcb *utcb) +{ + ::Reap_list rl; + unsigned words = f->tag().words(); + + LOG_TRACE("Task unmap", "unm", ::current(), __task_unmap_fmt, + Log_unmap *lu = tbe->payload(); + lu->id = dbg_id(); + lu->mask = utcb->values[1]; + lu->fpage = utcb->values[2]); + + { + Lock_guard guard; + + // FIXME: avoid locking the current task, it is not needed + if (!guard.try_lock(&existence_lock)) + return commit_error(utcb, L4_error::Not_existent); + + cpu_lock.clear(); + + L4_map_mask m(utcb->values[1]); + + for (unsigned i = 2; i < words; ++i) + { + unsigned const flushed = fpage_unmap(this, L4_fpage(utcb->values[i]), m, rl.list()); + utcb->values[i] = (utcb->values[i] & ~0xfUL) | flushed; + } + cpu_lock.lock(); + } + + cpu_lock.clear(); + rl.del(); + cpu_lock.lock(); + + return commit_result(0, words); +} + +PRIVATE inline NOEXPORT +L4_msg_tag +Task::sys_cap_valid(Syscall_frame *, Utcb *utcb) +{ + L4_obj_ref obj(utcb->values[1]); + + if (obj.special()) + return commit_result(0); + + Obj_space::Capability cap = lookup(obj.cap()); + if (EXPECT_TRUE(cap.valid())) + { + if (!(utcb->values[1] & 1)) + return commit_result(1); + else + return commit_result(cap.obj()->map_root()->cap_ref_cnt()); + } + else + return commit_result(0); +} + +PRIVATE inline NOEXPORT +L4_msg_tag +Task::sys_caps_equal(Syscall_frame *, Utcb *utcb) +{ + L4_obj_ref obj_a(utcb->values[1]); + L4_obj_ref obj_b(utcb->values[2]); + + if (obj_a == obj_b) + return commit_result(1); + + if (obj_a.special() || obj_b.special()) + return commit_result(obj_a.special_cap() == obj_b.special_cap()); + + Obj_space::Capability c_a = lookup(obj_a.cap()); + Obj_space::Capability c_b = lookup(obj_b.cap()); + + return commit_result(c_a == c_b); +} + +PRIVATE inline NOEXPORT +L4_msg_tag +Task::sys_add_ku_mem(Syscall_frame *f, Utcb *utcb) +{ + unsigned const w = f->tag().words(); + for (unsigned i = 1; i < w; ++i) + { + L4_fpage ku_fp(utcb->values[i]); + if (!ku_fp.is_valid() || !ku_fp.is_mempage()) + return commit_result(-L4_err::EInval); + + int e = alloc_ku_mem(ku_fp); + if (e < 0) + return commit_result(e); + } + + return commit_result(0); +} + +PRIVATE inline NOEXPORT +L4_msg_tag +Task::sys_cap_info(Syscall_frame *f, Utcb *utcb) +{ + L4_msg_tag const &tag = f->tag(); + + switch (tag.words()) + { + default: return commit_result(-L4_err::EInval); + case 2: return sys_cap_valid(f, utcb); + case 3: return sys_caps_equal(f, utcb); + } +} + + +PUBLIC +void +Task::invoke(L4_obj_ref, Mword rights, Syscall_frame *f, Utcb *utcb) +{ + if (EXPECT_FALSE(f->tag().proto() != L4_msg_tag::Label_task)) + { + f->tag(commit_result(-L4_err::EBadproto)); + return; + } + + switch (utcb->values[0]) + { + case Map: + f->tag(sys_map(rights, f, utcb)); + return; + case Unmap: + f->tag(sys_unmap(f, utcb)); + return; + case Cap_info: + f->tag(sys_cap_info(f, utcb)); + return; + case Add_ku_mem: + f->tag(sys_add_ku_mem(f, utcb)); + return; + default: + L4_msg_tag tag = f->tag(); + if (invoke_arch(tag, utcb)) + f->tag(tag); + else + f->tag(commit_result(-L4_err::ENosys)); + return; + } +} + + +//--------------------------------------------------------------------------- +IMPLEMENTATION [!ux]: + +IMPLEMENT inline void Task::map_utcb_ptr_page() {} +IMPLEMENT inline void Task::ux_init() {} + +PUBLIC inline +Task::~Task() +{ free_ku_mem(); } + + +// --------------------------------------------------------------------------- +INTERFACE [debug]: + +EXTENSION class Task +{ +private: + struct Log_unmap + { + Mword id; + Mword mask; + Mword fpage; + } __attribute__((packed)); + + static unsigned unmap_fmt(Tb_entry *, int max, char *buf) asm ("__task_unmap_fmt"); +}; + +// --------------------------------------------------------------------------- +IMPLEMENTATION [debug]: + +IMPLEMENT +unsigned +Task::unmap_fmt(Tb_entry *e, int max, char *buf) +{ + Log_unmap *l = e->payload(); + L4_fpage fp(l->fpage); + return snprintf(buf, max, "task=[U:%lx] mask=%lx fpage=[%u/%u]%lx", + l->id, l->mask, (unsigned)fp.order(), fp.type(), l->fpage); +} + +// --------------------------------------------------------------------------- +IMPLEMENTATION[!ia32 || !svm]: + +PRIVATE inline NOEXPORT +L4_msg_tag +Task::sys_vm_run(Syscall_frame *, Utcb *) +{ + return commit_result(-L4_err::ENosys); +} + diff --git a/kernel/fiasco/src/kern/tb_entry.cpp b/kernel/fiasco/src/kern/tb_entry.cpp new file mode 100644 index 00000000..31c06803 --- /dev/null +++ b/kernel/fiasco/src/kern/tb_entry.cpp @@ -0,0 +1,887 @@ +INTERFACE: + +#include "initcalls.h" +#include "l4_error.h" + +enum { + Tbuf_unused = 0, + Tbuf_pf = 1, + Tbuf_ipc = 2, + Tbuf_ipc_res = 3, + Tbuf_ipc_trace = 4, + Tbuf_ke = 5, + Tbuf_ke_reg = 6, + Tbuf_unmap = 7, + Tbuf_shortcut_failed = 8, + Tbuf_shortcut_succeeded = 9, + Tbuf_context_switch = 10, + Tbuf_exregs = 11, + Tbuf_breakpoint = 12, + Tbuf_trap = 13, + Tbuf_pf_res = 14, + Tbuf_sched = 15, + Tbuf_preemption = 16, + Tbuf_ke_bin = 17, + Tbuf_dynentries = 18, + Tbuf_max = 0x80, + Tbuf_hidden = 0x80, +}; + +#include "l4_types.h" + +class Tb_entry; + +typedef unsigned Tb_entry_formatter(Tb_entry *e, int max, char *buf); + +struct Tb_log_table_entry +{ + char const *name; + unsigned char *patch; + Tb_entry_formatter *fmt; +}; + +extern Tb_log_table_entry _log_table[]; +extern Tb_log_table_entry _log_table_end; + +class Context; +class Space; +class Sched_context; +class Syscall_frame; +class Trap_state; + +class Tb_entry_base +{ +protected: + Mword _number; ///< event number + Address _ip; ///< instruction pointer + Context const *_ctx; ///< Context + Unsigned64 _tsc; ///< time stamp counter + Unsigned32 _pmc1; ///< performance counter value 1 + Unsigned32 _pmc2; ///< performance counter value 2 + Unsigned32 _kclock; ///< lower 32 bits of kernel clock + Unsigned8 _type; ///< type of entry + Unsigned8 _cpu; ///< CPU + + static Mword (*rdcnt1)(); + static Mword (*rdcnt2)(); +} __attribute__((packed)); + +class Tb_entry : public Tb_entry_base +{ +public: + template + class Payload_traits + { + public: + enum + { + Align = __alignof__(T), //(sizeof(T) > sizeof(Mword)) ? sizeof(Mword) : sizeof(T), + Offset = sizeof(Tb_entry_base), + Payload_offset = ((Offset + Align -1) & ~(Align-1)) - Offset, + Total = Offset + Payload_offset + sizeof(T), + }; + + template + struct TTI + {}; + + static void tb_entry_size_mismatch(TTI const &) {} + static void payload_too_big(TTI const &) {} + static void payload_too_big() + { + tb_entry_size_mismatch(TTI<(sizeof(Tb_entry) != Tb_entry_size)>()); + payload_too_big(TTI<((int)Total > (int)Tb_entry_size)>()); + } + + }; + +private: + template< typename T > + T *addr_of_payload() const + { + Payload_traits::payload_too_big(); + + Address p = reinterpret_cast
(_payload); + return reinterpret_cast(p + Payload_traits::Payload_offset); + } + +public: + char _payload[Tb_entry_size-sizeof(Tb_entry_base)]; + + template + T *payload() { return addr_of_payload(); } + + template + T const *payload() const { return addr_of_payload(); } + + +} __attribute__((__aligned__(8))) ; + +/** logged ipc. */ +class Tb_entry_ipc : public Tb_entry +{ +private: + struct Payload + { + L4_msg_tag _tag; ///< message tag + Mword _dword[2]; ///< first two message words + L4_obj_ref _dst; ///< destination id + Mword _dbg_id; + Mword _label; + L4_timeout_pair _timeout; ///< timeout + }; +}; + +/** logged ipc result. */ +class Tb_entry_ipc_res : public Tb_entry +{ +private: + struct Payload + { + L4_msg_tag _tag; ///< message tag + Mword _dword[2]; ///< first two dwords + L4_error _result; ///< result + Mword _from; ///< receive descriptor + Mword _pair_event; ///< referred event + Unsigned8 _have_snd; ///< ipc had send part + Unsigned8 _is_np; ///< next period bit set + }; +}; + +/** logged ipc for user level tracing with Vampir. */ +class Tb_entry_ipc_trace : public Tb_entry +{ +private: + struct Payload + { + Unsigned64 _snd_tsc; ///< entry tsc + L4_msg_tag _result; ///< result + L4_obj_ref _snd_dst; ///< send destination + Mword _rcv_dst; ///< rcv partner + Unsigned8 _snd_desc; + Unsigned8 _rcv_desc; + }; +}; + +#if 0 +/** logged short-cut ipc failed. */ +class Tb_entry_ipc_sfl : public Tb_entry_base +{ +private: + Global_id _from; ///< short ipc rcv descriptor + L4_timeout_pair _timeout; ///< ipc timeout + Global_id _dst; ///< partner + Unsigned8 _is_irq, _snd_lst, _dst_ok, _dst_lck, _preempt; +}; +#endif + +/** logged pagefault. */ +class Tb_entry_pf : public Tb_entry +{ +private: + struct Payload + { + Address _pfa; ///< pagefault address + Mword _error; ///< pagefault error code + Space *_space; + }; +}; + +/** pagefault result. */ +class Tb_entry_pf_res : public Tb_entry +{ +private: + struct Payload + { + Address _pfa; + L4_error _err; + L4_error _ret; + }; +}; + + +/** logged kernel event. */ +class Tb_entry_ke : public Tb_entry +{ + enum { MSG_POINTER_PAYLOAD_OFFSET + = 5 - ((sizeof(Tb_entry_base) + 2 + 3) % sizeof(Mword)) }; +}; + +/** logged breakpoint. */ +class Tb_entry_bp : public Tb_entry +{ +private: + struct Payload + { + Address _address; ///< breakpoint address + int _len; ///< breakpoint length + Mword _value; ///< value at address + int _mode; ///< breakpoint mode + } __attribute__((packed)); +}; + +/** logged context switch. */ +class Tb_entry_ctx_sw : public Tb_entry +{ +private: + struct Payload + { + Context const *_dst; ///< switcher target + Context const *_dst_orig; + Address _kernel_ip; + Mword _lock_cnt; + Space *_from_space; + Sched_context *_from_sched; + Mword _from_prio; + } __attribute__((packed)); +}; + +/** logged scheduling event. */ +class Tb_entry_sched : public Tb_entry +{ +private: + struct Payload + { + unsigned short _mode; + Context const *_owner; + unsigned short _id; + unsigned short _prio; + signed long _left; + unsigned long _quantum; + } __attribute__((packed)); +}; + + +/** logged preemption */ +class Tb_entry_preemption : public Tb_entry +{ +private: + struct Payload + { + Mword _preempter; + }; +}; + + +/** logged binary kernel event. */ +class Tb_entry_ke_bin : public Tb_entry +{ +public: + enum { SIZE = 30 }; +}; + + + +IMPLEMENTATION: + +#include +#include + +#include "entry_frame.h" +#include "globals.h" +#include "kip.h" +#include "static_init.h" +#include "trap_state.h" + + +PROTECTED static Mword Tb_entry_base::dummy_read_pmc() { return 0; } + +Mword (*Tb_entry_base::rdcnt1)() = dummy_read_pmc; +Mword (*Tb_entry_base::rdcnt2)() = dummy_read_pmc; + + +PUBLIC static +void +Tb_entry::set_rdcnt(int num, Mword (*f)()) +{ + if (!f) + f = dummy_read_pmc; + + switch (num) + { + case 0: rdcnt1 = f; break; + case 1: rdcnt2 = f; break; + } +} + +PUBLIC inline +void +Tb_entry::clear() +{ _type = Tbuf_unused; } + +PUBLIC inline NEEDS["kip.h", "globals.h"] +void +Tb_entry::set_global(char type, Context const *ctx, Address ip) +{ + _type = type; + _ctx = ctx; + _ip = ip; + _kclock = (Unsigned32)Kip::k()->clock; + _cpu = current_cpu(); +} + +PUBLIC inline +void +Tb_entry::hide() +{ _type |= Tbuf_hidden; } + +PUBLIC inline +void +Tb_entry::unhide() +{ _type &= ~Tbuf_hidden; } + +PUBLIC inline +Address +Tb_entry::ip() const +{ return _ip; } + +PUBLIC inline +Context const * +Tb_entry::ctx() const +{ return _ctx; } + +PUBLIC inline +Unsigned8 +Tb_entry::type() const +{ return _type & (Tbuf_max-1); } + +PUBLIC inline +int +Tb_entry::hidden() const +{ return _type & Tbuf_hidden; } + +PUBLIC inline +Mword +Tb_entry::number() const +{ return _number; } + +PUBLIC inline +void +Tb_entry::number(Mword number) +{ _number = number; } + +PUBLIC inline +void +Tb_entry::rdpmc1() +{ _pmc1 = rdcnt1(); } + +PUBLIC inline +void +Tb_entry::rdpmc2() +{ _pmc2 = rdcnt2(); } + +PUBLIC inline +Unsigned32 +Tb_entry::kclock() const +{ return _kclock; } + +PUBLIC inline +Unsigned8 +Tb_entry::cpu() const +{ return _cpu; } + +PUBLIC inline +Unsigned64 +Tb_entry::tsc() const +{ return _tsc; } + +PUBLIC inline +Unsigned32 +Tb_entry::pmc1() const +{ return _pmc1; } + +PUBLIC inline +Unsigned32 +Tb_entry::pmc2() const +{ return _pmc2; } + + +PUBLIC inline NEEDS ["entry_frame.h"] +void +Tb_entry_ipc::set(Context const *ctx, Mword ip, Syscall_frame *ipc_regs, Utcb *utcb, + Mword dbg_id, Unsigned64 left) +{ + set_global(Tbuf_ipc, ctx, ip); + Payload *p = payload(); + p->_dst = ipc_regs->ref(); + p->_label = ipc_regs->from_spec(); + + + p->_dbg_id = dbg_id; + + p->_timeout = ipc_regs->timeout(); + p->_tag = ipc_regs->tag(); + if (ipc_regs->next_period()) + { + p->_dword[0] = (Unsigned32)(left & 0xffffffff); + p->_dword[1] = (Unsigned32)(left >> 32); + } + else + { + // hint for gcc + register Mword tmp0 = utcb->values[0]; + register Mword tmp1 = utcb->values[1]; + p->_dword[0] = tmp0; + p->_dword[1] = tmp1; + } +} + +PUBLIC inline +void +Tb_entry_ipc::set_sc(Context const *ctx, Mword ip, Syscall_frame *ipc_regs, + Utcb *utcb, Unsigned64 left) +{ + set_global(Tbuf_shortcut_succeeded, ctx, ip); + Payload *p = payload(); + p->_dst = ipc_regs->ref(); + p->_timeout = ipc_regs->timeout(); + if (ipc_regs->next_period()) + { + p->_dword[0] = (Unsigned32)(left & 0xffffffff); + p->_dword[1] = (Unsigned32)(left >> 32); + } + else + { + // hint for gcc + register Mword tmp0 = utcb->values[0]; + register Mword tmp1 = utcb->values[1]; + p->_dword[0] = tmp0; + p->_dword[1] = tmp1; + } +} + + +PUBLIC inline +Mword +Tb_entry_ipc::ipc_type() const +{ return payload()->_dst.op(); } + +PUBLIC inline +Mword +Tb_entry_ipc::dbg_id() const +{ return payload()->_dbg_id; } + +PUBLIC inline +L4_obj_ref +Tb_entry_ipc::dst() const +{ return payload()->_dst; } + +PUBLIC inline +L4_timeout_pair +Tb_entry_ipc::timeout() const +{ return payload()->_timeout; } + +PUBLIC inline +L4_msg_tag +Tb_entry_ipc::tag() const +{ return payload()->_tag; } + +PUBLIC inline +Mword +Tb_entry_ipc::label() const +{ return payload()->_label; } + +PUBLIC inline +Mword +Tb_entry_ipc::dword(unsigned index) const +{ return payload()->_dword[index]; } + + +PUBLIC inline NEEDS ["entry_frame.h"] +void +Tb_entry_ipc_res::set(Context const *ctx, Mword ip, Syscall_frame *ipc_regs, + Utcb *utcb, + Mword result, Mword pair_event, Unsigned8 have_snd, + Unsigned8 is_np) +{ + set_global(Tbuf_ipc_res, ctx, ip); + Payload *p = payload(); + // hint for gcc + register Mword tmp0 = utcb->values[0]; + register Mword tmp1 = utcb->values[1]; + p->_dword[0] = tmp0; + p->_dword[1] = tmp1; + p->_tag = ipc_regs->tag(); + p->_pair_event = pair_event; + p->_result = L4_error::from_raw(result); + p->_from = ipc_regs->from_spec(); + p->_have_snd = have_snd; + p->_is_np = is_np; +} + +PUBLIC inline +int +Tb_entry_ipc_res::have_snd() const +{ return payload()->_have_snd; } + +PUBLIC inline +int +Tb_entry_ipc_res::is_np() const +{ return payload()->_is_np; } + +PUBLIC inline +Mword +Tb_entry_ipc_res::from() const +{ return payload()->_from; } + +PUBLIC inline +L4_error +Tb_entry_ipc_res::result() const +{ return payload()->_result; } + +PUBLIC inline +L4_msg_tag +Tb_entry_ipc_res::tag() const +{ return payload()->_tag; } + +PUBLIC inline +Mword +Tb_entry_ipc_res::dword(unsigned index) const +{ return payload()->_dword[index]; } + +PUBLIC inline +Mword +Tb_entry_ipc_res::pair_event() const +{ return payload()->_pair_event; } + + +PUBLIC inline +void +Tb_entry_ipc_trace::set(Context const *ctx, Mword ip, Unsigned64 snd_tsc, + L4_obj_ref const &snd_dst, Mword rcv_dst, + L4_msg_tag result, Unsigned8 snd_desc, + Unsigned8 rcv_desc) +{ + set_global(Tbuf_ipc_trace, ctx, ip); + payload()->_snd_tsc = snd_tsc; + payload()->_snd_dst = snd_dst; + payload()->_rcv_dst = rcv_dst; + payload()->_result = result; + payload()->_snd_desc = snd_desc; + payload()->_rcv_desc = rcv_desc; +} + +#if 0 +PUBLIC inline +void +Tb_entry_ipc_sfl::set(Context *ctx, Mword ip, + Global_id from, + L4_timeout_pair timeout, Global_id dst, + Unsigned8 is_irq, Unsigned8 snd_lst, + Unsigned8 dst_ok, Unsigned8 dst_lck, + Unsigned8 preempt) +{ + set_global(Tbuf_shortcut_failed, ctx, ip); + Payload *p = payload(); + p->_from = from; + p->_timeout = timeout; + p->_dst = dst; + p->_is_irq = is_irq; + p->_snd_lst = snd_lst; + p->_dst_ok = dst_ok; + p->_dst_lck = dst_lck; + p->_preempt = preempt; +} + +PUBLIC inline +L4_timeout_pair +Tb_entry_ipc_sfl::timeout() const +{ return _timeout; } + +PUBLIC inline +Global_id +Tb_entry_ipc_sfl::from() const +{ return _from; } + +PUBLIC inline +Global_id +Tb_entry_ipc_sfl::dst() const +{ return _dst; } + +PUBLIC inline +Unsigned8 +Tb_entry_ipc_sfl::is_irq() const +{ return _is_irq; } + +PUBLIC inline +Unsigned8 +Tb_entry_ipc_sfl::snd_lst() const +{ return _snd_lst; } + +PUBLIC inline +Unsigned8 +Tb_entry_ipc_sfl::dst_ok() const +{ return _dst_ok; } + +PUBLIC inline +Unsigned8 +Tb_entry_ipc_sfl::dst_lck() const +{ return _dst_lck; } + +PUBLIC inline +Unsigned8 +Tb_entry_ipc_sfl::preempt() const +{ return _preempt; } +#endif + +PUBLIC inline +void +Tb_entry_pf::set(Context const *ctx, Address ip, Address pfa, + Mword error, Space *spc) +{ + set_global(Tbuf_pf, ctx, ip); + Payload *p = payload(); + p->_pfa = pfa; + p->_error = error; + p->_space = spc; +} + +PUBLIC inline +Mword +Tb_entry_pf::error() const +{ return payload()->_error; } + +PUBLIC inline +Address +Tb_entry_pf::pfa() const +{ return payload()->_pfa; } + +PUBLIC inline +Space* +Tb_entry_pf::space() const +{ return payload()->_space; } + + +PUBLIC inline +void +Tb_entry_pf_res::set(Context const *ctx, Address ip, Address pfa, + L4_error err, L4_error ret) +{ + set_global(Tbuf_pf_res, ctx, ip); + Payload *p = payload(); + p->_pfa = pfa; + p->_err = err; + p->_ret = ret; +} + +PUBLIC inline +Address +Tb_entry_pf_res::pfa() const +{ return payload()->_pfa; } + +PUBLIC inline +L4_error +Tb_entry_pf_res::err() const +{ return payload()->_err; } + +PUBLIC inline +L4_error +Tb_entry_pf_res::ret() const +{ return payload()->_ret; } + + +PUBLIC inline +void +Tb_entry_bp::set(Context const *ctx, Address ip, + int mode, int len, Mword value, Address address) +{ + set_global(Tbuf_breakpoint, ctx, ip); + payload()->_mode = mode; + payload()->_len = len; + payload()->_value = value; + payload()->_address = address; +} + + + +PUBLIC inline +int +Tb_entry_bp::mode() const +{ return payload()->_mode; } + +PUBLIC inline +int +Tb_entry_bp::len() const +{ return payload()->_len; } + +PUBLIC inline +Mword +Tb_entry_bp::value() const +{ return payload()->_value; } + +PUBLIC inline +Address +Tb_entry_bp::addr() const +{ return payload()->_address; } + + + +PUBLIC inline +void +Tb_entry_ke::set(Context const *ctx, Address ip) +{ set_global(Tbuf_ke, ctx, ip); } + +PUBLIC inline +void +Tb_entry_ke::set_const(Context const *ctx, Address ip, const char * const msg) +{ + set_global(Tbuf_ke, ctx, ip); + char *_msg = payload(); + _msg[0] = 0; _msg[1] = 1; + *(char const ** const)(_msg + MSG_POINTER_PAYLOAD_OFFSET) = msg; +} + +PUBLIC inline +void +Tb_entry_ke::set_buf(unsigned i, char c) +{ + char *_msg = payload(); + if (i < sizeof(_payload)-1) + _msg[i] = c >= ' ' ? c : '.'; +} + +PUBLIC inline +void +Tb_entry_ke::term_buf(unsigned i) +{ + char *_msg = payload(); + _msg[i < sizeof(_payload)-1 ? i : sizeof(_payload)-1] = '\0'; +} + +PUBLIC inline +const char * +Tb_entry_ke::msg() const +{ + char const *_msg = payload(); + return _msg[0] == 0 && _msg[1] == 1 + ? *(char const ** const)(_msg + MSG_POINTER_PAYLOAD_OFFSET) : _msg; +} + + +PUBLIC inline +void +Tb_entry_ctx_sw::set(Context const *ctx, Space *from_space, Address ip, + Context const *dst, Context const *dst_orig, + Mword lock_cnt, + Sched_context *from_sched, Mword from_prio, + Address kernel_ip) +{ + set_global(Tbuf_context_switch, ctx, ip); + payload()->_kernel_ip = kernel_ip; + payload()->_dst = dst; + payload()->_dst_orig = dst_orig; + payload()->_lock_cnt = lock_cnt; + payload()->_from_space = from_space; + payload()->_from_sched = from_sched; + payload()->_from_prio = from_prio; +} + +PUBLIC inline +Space* +Tb_entry_ctx_sw::from_space() const +{ return payload()->_from_space; } + +PUBLIC inline +Address +Tb_entry_ctx_sw::kernel_ip() const +{ return payload()->_kernel_ip; } + +PUBLIC inline +Mword +Tb_entry_ctx_sw::lock_cnt() const +{ return payload()->_lock_cnt; } + +PUBLIC inline +Context const * +Tb_entry_ctx_sw::dst() const +{ return payload()->_dst; } + +PUBLIC inline +Context const * +Tb_entry_ctx_sw::dst_orig() const +{ return payload()->_dst_orig; } + +PUBLIC inline +Mword +Tb_entry_ctx_sw::from_prio() const +{ return payload()->_from_prio; } + +PUBLIC inline +Sched_context* +Tb_entry_ctx_sw::from_sched() const +{ return payload()->_from_sched; } + +PUBLIC inline +void +Tb_entry_sched::set (Context const *ctx, Address ip, unsigned short mode, + Context const *owner, unsigned short id, unsigned short prio, + signed long left, unsigned long quantum) +{ + set_global (Tbuf_sched, ctx, ip); + payload()->_mode = mode; + payload()->_owner = owner; + payload()->_id = id; + payload()->_prio = prio; + payload()->_left = left; + payload()->_quantum = quantum; +} + +PUBLIC inline +unsigned short +Tb_entry_sched::mode() const +{ return payload()->_mode; } + +PUBLIC inline +Context const * +Tb_entry_sched::owner() const +{ return payload()->_owner; } + +PUBLIC inline +unsigned short +Tb_entry_sched::id() const +{ return payload()->_id; } + +PUBLIC inline +unsigned short +Tb_entry_sched::prio() const +{ return payload()->_prio; } + +PUBLIC inline +unsigned long +Tb_entry_sched::quantum() const +{ return payload()->_quantum; } + +PUBLIC inline +signed long +Tb_entry_sched::left() const +{ return payload()->_left; } + +PUBLIC inline +void +Tb_entry_preemption::set (Context const *ctx, Mword preempter, + Address ip) +{ + set_global (Tbuf_preemption, ctx, ip); + payload()->_preempter = preempter; +}; + +PUBLIC inline +Mword +Tb_entry_preemption::preempter() const +{ return payload()->_preempter; } + + + +PUBLIC inline +void +Tb_entry_ke_bin::set(Context const *ctx, Address ip) +{ set_global(Tbuf_ke_bin, ctx, ip); } + +PUBLIC inline +void +Tb_entry_ke_bin::set_buf(unsigned i, char c) +{ + char *_bin = payload(); + if (i < sizeof(_payload)-1) + _bin[i] = c; +} diff --git a/kernel/fiasco/src/kern/tb_entry_output.cpp b/kernel/fiasco/src/kern/tb_entry_output.cpp new file mode 100644 index 00000000..4e0da8e1 --- /dev/null +++ b/kernel/fiasco/src/kern/tb_entry_output.cpp @@ -0,0 +1,526 @@ +IMPLEMENTATION: + +#include +#include +#include +#include + +#include "config.h" +#include "jdb_symbol.h" +#include "jdb_tbuf_output.h" +#include "jdb_util.h" +#include "static_init.h" +#include "tb_entry.h" +#include "thread.h" + +static __attribute__((format(printf, 3, 4))) +void +my_snprintf(char *&buf, int &maxlen, const char *format, ...) +{ + int len; + va_list list; + + if (maxlen<=0) + return; + + va_start(list, format); + len = vsnprintf(buf, maxlen, format, list); + va_end(list); + + if (len<0 || len>=maxlen) + len = maxlen-1; + + buf += len; + maxlen -= len; +} + + +// timeout => x.x{ +static +void +format_timeout(Mword us, char *&buf, int &maxlen) +{ + if (us >= 1000000000) // =>100s + my_snprintf(buf, maxlen, ">99s"); + else if (us >= 10000000) // >=10s + my_snprintf(buf, maxlen, "%lds", us/1000000); + else if (us >= 1000000) // >=1s + my_snprintf(buf, maxlen, "%ld.%lds", us/1000000, (us%1000000)/100000); + else if (us >= 10000) // 10ms + my_snprintf(buf, maxlen, "%ldm", us/1000); + else if (us >= 1000) // 1ms + my_snprintf(buf, maxlen, "%ld.%ldm", us/1000, (us%1000)/100); + else + my_snprintf(buf, maxlen, "%ld%c", us, Config::char_micro); +} + +template< typename T > +static +char const * +get_ipc_type(T e) +{ + switch (e->ipc_type()) + { + case L4_obj_ref::Ipc_call: return "call"; + case L4_obj_ref::Ipc_call_ipc: return "call ipc"; + case L4_obj_ref::Ipc_send: return "send"; + case L4_obj_ref::Ipc_recv: return "recv"; + case L4_obj_ref::Ipc_send_and_wait: return "snd wait"; + case L4_obj_ref::Ipc_reply_and_wait: return "repl"; + case L4_obj_ref::Ipc_wait: return "wait"; + default: return "unk ipc"; + } +} + +static char const * const __tag_interpreter_strings_l4re[] = { + "ds", // 0 + "name", + "parent", + "goos", + "ma", + "rm", // 5 + "ev", + }; +static char const * const __tag_interpreter_strings_fiasco[] = { + "Kirq", // -1 + "Kpf", + "Kpreempt", + "Ksysexc", + "Kexc", // -5 + "Ksigma", + 0, + "Kiopf", + "Kcapfault", + 0, // -10 + "Ktask", + "Kthread", + "Klog", + "Ksched", + "Kfactory", // -15 + "Kvm", + 0, + 0, + 0, + "Ksem", // -20 + "Kmeta", + }; + +static +char const * +tag_to_string(L4_msg_tag const &tag) +{ + if (0x4000 <= tag.proto() && tag.proto() <= 0x4006) + return __tag_interpreter_strings_l4re[tag.proto() - 0x4000]; + if (-21L <= tag.proto() && tag.proto() <= -1) + return __tag_interpreter_strings_fiasco[-tag.proto() - 1]; + return 0; +} + +static +void +tag_interpreter_snprintf(char *&buf, int &maxlen, L4_msg_tag const &tag) +{ + int len; + char const *s; + + if (maxlen<=0) + return; + + s = tag_to_string(tag); + if (s) + len = snprintf(buf, maxlen, "%s%04lx", s, tag.raw() & 0xffff); + else + len = snprintf(buf, maxlen, L4_PTR_FMT, tag.raw()); + + if (len<0 || len>=maxlen) + len = maxlen-1; + + buf += len; + maxlen -= len; +} + +// ipc / irq / shortcut success +static +unsigned +formatter_ipc(Tb_entry *tb, const char *tidstr, unsigned tidlen, + char *buf, int maxlen) +{ + Tb_entry_ipc *e = static_cast(tb); + unsigned char type = e->ipc_type(); + if (!type) + type = L4_obj_ref::Ipc_call_ipc; + + // ipc operation / shortcut succeeded/failed + const char *m = get_ipc_type(e); + + my_snprintf(buf, maxlen, "%s: ", (e->type()==Tbuf_ipc) ? "ipc" : "sc "); + my_snprintf(buf, maxlen, "%s%-*s %s->", + /*e->dst().next_period() ? "[NP] " :*/ "", tidlen, tidstr, m); + + // print destination id + if (e->dst().special()) + my_snprintf(buf, maxlen, "[C:INV] DID=%lx", e->dbg_id()); + else + my_snprintf(buf, maxlen, "[C:%lx] DID=%lx", e->dst().raw(), e->dbg_id()); + + my_snprintf(buf, maxlen, " L=%lx", e->label()); + + // print mwords if have send part + if (type & L4_obj_ref::Ipc_send) + { + my_snprintf(buf, maxlen, " ["); + + tag_interpreter_snprintf(buf, maxlen, e->tag()); + + my_snprintf(buf, maxlen, "] (" L4_PTR_FMT "," L4_PTR_FMT ")", + e->dword(0), e->dword(1)); + } + + my_snprintf(buf, maxlen, " TO="); + L4_timeout_pair to = e->timeout(); + if (type & L4_obj_ref::Ipc_send) + { + if (to.snd.is_absolute()) + { + // absolute send timeout + Unsigned64 end = 0; // FIXME: to.snd.microsecs_abs (e->kclock()); + format_timeout((Mword)(end > e->kclock() ? end-e->kclock() : 0), + buf, maxlen); + } + else + { + // relative send timeout + if (to.snd.is_never()) + my_snprintf(buf, maxlen, "INF"); + else if (to.snd.is_zero()) + my_snprintf(buf, maxlen, "0"); + else + format_timeout((Mword)to.snd.microsecs_rel(0), buf, maxlen); + } + } + if (type & L4_obj_ref::Ipc_send + && type & L4_obj_ref::Ipc_recv) + my_snprintf(buf, maxlen, "/"); + if (type & L4_obj_ref::Ipc_recv) + { + if (to.rcv.is_absolute()) + { + // absolute receive timeout + Unsigned64 end = 0; // FIXME: to.rcv.microsecs_abs (e->kclock()); + format_timeout((Mword)(end > e->kclock() ? end-e->kclock() : 0), + buf, maxlen); + } + else + { + // relative receive timeout + if (to.rcv.is_never()) + my_snprintf(buf, maxlen, "INF"); + else if (to.rcv.is_zero()) + my_snprintf(buf, maxlen, "0"); + else + format_timeout((Mword)to.rcv.microsecs_rel(0), buf, maxlen); + } + } + + return maxlen; +} + +// result of ipc +static +unsigned +formatter_ipc_res(Tb_entry *tb, const char *tidstr, unsigned tidlen, + char *buf, int maxlen) +{ + Tb_entry_ipc_res *e = static_cast(tb); + L4_error error; + if (e->tag().has_error()) + error = e->result(); + else + error = L4_error::None; + const char *m = "answ"; //get_ipc_type(e); + + my_snprintf(buf, maxlen, " %s%-*s %s [%08lx] L=%lx err=%lx (%s) (%lx,%lx) ", + e->is_np() ? "[np] " : "", + tidlen, tidstr, m, e->tag().raw(), e->from(), + error.raw(), error.str_error(), e->dword(0), + e->dword(1)); + + return maxlen; +} + +IMPLEMENTATION: + +#include "kobject_dbg.h" + +// pagefault +static +unsigned +formatter_pf(Tb_entry *tb, const char *tidstr, unsigned tidlen, + char *buf, int maxlen) +{ + Tb_entry_pf *e = static_cast(tb); + char ip_buf[32]; + + snprintf(ip_buf, sizeof(ip_buf), L4_PTR_FMT, e->ip()); + my_snprintf(buf, maxlen, "pf: %-*s pfa=" L4_PTR_FMT " ip=%s (%c%c) spc=%p", + tidlen, tidstr, e->pfa(), e->ip() ? ip_buf : "unknown", + !PF::is_read_error(e->error()) ? (e->error() & 4 ? 'w' : 'W') + : (e->error() & 4 ? 'r' : 'R'), + !PF::is_translation_error(e->error()) ? 'p' : '-', + e->space()); + + return maxlen; +} + +// pagefault result +static +unsigned +formatter_pf_res(Tb_entry *tb, const char *tidstr, unsigned tidlen, + char *buf, int maxlen) +{ + Tb_entry_pf_res *e = static_cast(tb); + + // e->ret contains only an error code + // e->err contains only up to 3 dwords + my_snprintf(buf, maxlen, " %-*s pfa=" L4_PTR_FMT " dope=%02lx (%s%s) " + "err=%04lx (%s%s)", + tidlen, tidstr, e->pfa(), + e->ret().raw(), e->ret().error() ? "L4_IPC_" : "", + e->ret().str_error(), + e->err().raw(), e->err().error() ? "L4_IPC_" : "", + e->err().str_error()); + + return maxlen; +} + +// kernel event (enter_kdebug("*...")) +static +unsigned +formatter_ke(Tb_entry *tb, const char *tidstr, unsigned tidlen, + char *buf, int maxlen) +{ + Tb_entry_ke *e = static_cast(tb); + char ip_buf[32]; + + snprintf(ip_buf, sizeof(ip_buf), " @ " L4_PTR_FMT, e->ip()); + my_snprintf(buf, maxlen, "ke: %-*s \"%s\"%s", + tidlen, tidstr, e->msg(), e->ip() ? ip_buf : ""); + + return maxlen; +} + +// kernel event (enter_kdebug_verb("*+...", val1, val2, val3)) +static +unsigned +formatter_ke_reg(Tb_entry *tb, const char *tidstr, unsigned tidlen, + char *buf, int maxlen) +{ + Tb_entry_ke_reg *e = static_cast(tb); + + char ip_buf[32]; + snprintf(ip_buf, sizeof(ip_buf), " @ " L4_PTR_FMT, e->ip()); + my_snprintf(buf, maxlen, "ke: %-*s \"%s\" " + L4_PTR_FMT " " L4_PTR_FMT " " L4_PTR_FMT "%s", + tidlen, tidstr, e->msg(), e->val1(), e->val2(), e->val3(), + e->ip() ? ip_buf : ""); + + return maxlen; +} + + +// breakpoint +static +unsigned +formatter_bp(Tb_entry *tb, const char *tidstr, unsigned tidlen, + char *buf, int maxlen) +{ + Tb_entry_bp *e = static_cast(tb); + + my_snprintf(buf, maxlen, "b%c: %-*s @ " L4_PTR_FMT " ", + "iwpa"[e->mode() & 3], tidlen, tidstr, e->ip()); + switch (e->mode() & 3) + { + case 1: + case 3: + switch (e->len()) + { + case 1: + my_snprintf(buf, maxlen, "[" L4_PTR_FMT "]=%02lx", + e->addr(), e->value()); + break; + case 2: + my_snprintf(buf, maxlen, "[" L4_PTR_FMT "]=%04lx", + e->addr(), e->value()); + break; + case 4: + my_snprintf(buf, maxlen, "[" L4_PTR_FMT "]=" L4_PTR_FMT, + e->addr(), e->value()); + break; + } + break; + case 2: + my_snprintf(buf, maxlen, "[" L4_PTR_FMT "]", e->addr()); + break; + } + + return maxlen; +} + +// context switch +static +unsigned +formatter_ctx_switch(Tb_entry *tb, const char *tidstr, unsigned tidlen, + char *buf, int maxlen) +{ + char symstr[24], spcstr[16] = ""; + Tb_entry_ctx_sw *e = static_cast(tb); + + Context *sctx = 0; + Mword sctxid = ~0UL; + Mword dst; + Mword dst_orig; + + sctx = e->from_sched()->context(); + sctxid = static_cast(sctx)->dbg_id(); + + dst = static_cast(e->dst())->dbg_id(); + dst_orig = static_cast(e->dst_orig())->dbg_id(); + + Address addr = e->kernel_ip(); + + if (!Jdb_symbol::match_addr_to_symbol_fuzzy(&addr, 0 /*kernel*/, + symstr, sizeof(symstr))) + snprintf(symstr, sizeof(symstr), L4_PTR_FMT, e->kernel_ip()); + + my_snprintf(buf, maxlen, " %-*s%s '%02lx", + tidlen, tidstr, spcstr, e->from_prio()); + if (sctx != e->ctx()) + my_snprintf(buf, maxlen, "(%lx)", sctxid); + + my_snprintf(buf, maxlen, " ==> %lx ", dst); + + if (dst != dst_orig || e->lock_cnt()) + my_snprintf(buf, maxlen, "("); + + if (dst != dst_orig) + my_snprintf(buf, maxlen, "want %lx", + dst_orig); + + if (dst != dst_orig && e->lock_cnt()) + my_snprintf(buf, maxlen, " "); + + if (e->lock_cnt()) + my_snprintf(buf, maxlen, "lck %ld", e->lock_cnt()); + + if (dst != dst_orig || e->lock_cnt()) + my_snprintf(buf, maxlen, ") "); + + my_snprintf(buf, maxlen, " krnl %s", symstr); + + return maxlen; +} + + +// trap +static +unsigned +formatter_trap(Tb_entry *tb, const char *tidstr, unsigned tidlen, + char *buf, int maxlen) +{ + Tb_entry_trap *e = static_cast(tb); + + if (!e->cs()) + my_snprintf(buf, maxlen, "#%02x: %-*s err=%08x @ " L4_PTR_FMT, + e->trapno(), tidlen, tidstr, e->error(), e->ip()); + else + my_snprintf(buf, maxlen, + e->trapno() == 14 + ? "#%02x: %-*s err=%04x @ " L4_PTR_FMT + " cs=%04x sp=" L4_PTR_FMT " cr2=" L4_PTR_FMT + : "#%02x: %-*s err=%04x @ " L4_PTR_FMT + " cs=%04x sp=" L4_PTR_FMT " eax=" L4_PTR_FMT, + e->trapno(), + tidlen, tidstr, e->error(), e->ip(), e->cs(), e->sp(), + e->trapno() == 14 ? e->cr2() : e->eax()); + + return maxlen; +} + +// sched +static +unsigned +formatter_sched(Tb_entry *tb, const char *tidstr, unsigned tidlen, + char *buf, int maxlen) +{ + Tb_entry_sched *e = static_cast(tb); + Thread const *_t = static_cast(e->owner()); + Mword t = ~0UL; + if (Jdb_util::is_mapped(_t)) + t = _t->dbg_id(); + + + my_snprintf(buf, maxlen, + "%-*s (ts %s) owner:%lx id:%2x, prio:%2x, left:%6ld/%-6lu", + tidlen, tidstr, + e->mode() == 0 ? "save" : + e->mode() == 1 ? "load" : + e->mode() == 2 ? "invl" : "????", + t, + e->id(), e->prio(), e->left(), e->quantum()); + + return maxlen; +} + +// preemption +static +unsigned +formatter_preemption(Tb_entry *tb, const char *tidstr, unsigned tidlen, + char *buf, int maxlen) +{ + Tb_entry_preemption *e = static_cast(tb); + Mword t = e->preempter(); + + my_snprintf(buf, maxlen, + "pre: %-*s sent to %lx", + tidlen, tidstr, t); + + return maxlen; +} + +// kernel event log binary data +static +unsigned +formatter_ke_bin(Tb_entry *tb, const char *tidstr, unsigned tidlen, + char *buf, int maxlen) +{ + Tb_entry_ke_bin *e = static_cast(tb); + char ip_buf[32]; + + snprintf(ip_buf, sizeof(ip_buf), " @ " L4_PTR_FMT, e->ip()); + my_snprintf(buf, maxlen, "ke: %-*s BINDATA %s", + tidlen, tidstr, e->ip() ? ip_buf : ""); + + return maxlen; +} + +STATIC_INITIALIZER(init_formatters); + +// register all available format functions +static FIASCO_INIT +void +init_formatters() +{ + Jdb_tbuf_output::register_ff(Tbuf_pf, formatter_pf); + Jdb_tbuf_output::register_ff(Tbuf_pf_res, formatter_pf_res); + Jdb_tbuf_output::register_ff(Tbuf_ipc, formatter_ipc); + Jdb_tbuf_output::register_ff(Tbuf_ipc_res, formatter_ipc_res); + Jdb_tbuf_output::register_ff(Tbuf_ke, formatter_ke); + Jdb_tbuf_output::register_ff(Tbuf_ke_reg, formatter_ke_reg); + Jdb_tbuf_output::register_ff(Tbuf_shortcut_succeeded, formatter_ipc); + Jdb_tbuf_output::register_ff(Tbuf_context_switch, formatter_ctx_switch); + Jdb_tbuf_output::register_ff(Tbuf_breakpoint, formatter_bp); + Jdb_tbuf_output::register_ff(Tbuf_trap, formatter_trap); + Jdb_tbuf_output::register_ff(Tbuf_sched, formatter_sched); + Jdb_tbuf_output::register_ff(Tbuf_preemption, formatter_preemption); + Jdb_tbuf_output::register_ff(Tbuf_ke_bin, formatter_ke_bin); +} diff --git a/kernel/fiasco/src/kern/tcboffset.cc b/kernel/fiasco/src/kern/tcboffset.cc new file mode 100644 index 00000000..000d8932 --- /dev/null +++ b/kernel/fiasco/src/kern/tcboffset.cc @@ -0,0 +1,60 @@ +#include "irq.h" +#include "jdb_ktrace.h" +#include "thread.h" +#include "types.h" + +bool dumpzero; + +#define NAME_LEN 58 + +static int _t; + +#if 1 +#define DUMP_CAST_OFFSET(type, subtype) \ + ((unsigned long)((subtype *)((type *)(&_t))) - (unsigned long)&_t), +#endif + +#define DUMP_OFFSET(prefix,name,offset) (offset), + +#define DUMP_BITSHIFT(prefix, value) (value), + +#define GET_MEMBER_PTR(type,member) \ + ((unsigned long)(&(((type *) 1)->member)) - 1) + +#define DUMP_MEMBER1(prefix, \ + type1,member1, \ + name) (GET_MEMBER_PTR (type1, member1)), + +#define DUMP_CONSTANT(prefix, value) (value), + +#if 0 +#define DUMP_CAST_OFFSET(type, subtype, member) \ + (GET_MEMBER_PTR(type, member) - GET_MEMBER_PTR(subtype, member)), +#endif + +/** + * Calculates the logarithm base 2 from the given 2^n integer. + * @param value the 2^n integer + * @return the log base 2 of value, the exponent n + */ +int log2(int value) +{ + unsigned c = 0; // c will be lg(v) + while (value >>= 1) + c++; + return c; +} + + +void offsets_func(char **a, unsigned long **b) +{ +static char length[32] __attribute__((unused, section(".e_length"))) = + { sizeof(unsigned long), }; +static unsigned long offsets[] __attribute__((unused, section(".offsets"))) = +{ +#include "tcboffset_in.h" +}; + *a = length; + *b = offsets; + +} diff --git a/kernel/fiasco/src/kern/tcboffset_in.h b/kernel/fiasco/src/kern/tcboffset_in.h new file mode 100644 index 00000000..0d22a11a --- /dev/null +++ b/kernel/fiasco/src/kern/tcboffset_in.h @@ -0,0 +1,89 @@ + DUMP_MEMBER1 (THREAD, Context, _state, STATE) + DUMP_MEMBER1 (THREAD, Context, _kernel_sp, KERNEL_SP) + DUMP_MEMBER1 (THREAD, Context, _donatee, DONATEE) + DUMP_MEMBER1 (THREAD, Context, _lock_cnt, LOCK_CNT) + DUMP_MEMBER1 (THREAD, Context, _sched_context, SCHED_CONTEXT) + DUMP_MEMBER1 (THREAD, Context, _sched, SCHED) + DUMP_MEMBER1 (THREAD, Context, _period, PERIOD) + DUMP_MEMBER1 (THREAD, Context, _mode, MODE) + DUMP_MEMBER1 (THREAD, Context, _fpu_state, FPU_STATE) + DUMP_MEMBER1 (THREAD, Context, _consumed_time, CONSUMED_TIME) + DUMP_MEMBER1 (THREAD, Thread, _caller, REPLY_CAP) + DUMP_MEMBER1 (THREAD, Receiver, _partner, PARTNER) + DUMP_MEMBER1 (THREAD, Receiver, _rcv_regs, RCV_REGS) + DUMP_MEMBER1 (THREAD, Thread, _timeout, TIMEOUT) + DUMP_MEMBER1 (THREAD, Thread, _space, SPACE) + DUMP_MEMBER1 (THREAD, Thread, _thread_lock, THREAD_LOCK) + DUMP_MEMBER1 (THREAD, Thread, _thread_lock._lock_owner, + THREAD_LOCK__SWITCH_LOCK__LOCK_OWNER) + DUMP_MEMBER1 (THREAD, Thread, _thread_lock._switch_hint, + THREAD_LOCK__SWITCH_HINT) + DUMP_MEMBER1 (THREAD, Thread, _pager, PAGER) + DUMP_MEMBER1 (THREAD, Thread, _recover_jmpbuf, RECOVER_JMPBUF) +#if defined(CONFIG_ARM) + DUMP_MEMBER1 (THREAD, Thread, _exc_cont._ip, EXCEPTION_IP) + DUMP_MEMBER1 (THREAD, Thread, _exc_cont._psr, EXCEPTION_PSR) +#endif + DUMP_MEMBER1 (THREAD, Thread, _magic, MAGIC) + DUMP_OFFSET (THREAD, MAX, sizeof (Thread)) + + DUMP_MEMBER1 (THREAD, Context, _vcpu_state._u, USER_VCPU) +#if defined(CONFIG_ARM) + DUMP_OFFSET (THREAD, UTCB_SIZE, sizeof(Utcb)) +#else + DUMP_MEMBER1 (THREAD, Context, _vcpu_state._k, VCPU_STATE) +#endif +#if 0 + DUMP_MEMBER1 (SCHED_CONTEXT, Sched_context,_owner, OWNER) + DUMP_MEMBER1 (SCHED_CONTEXT, Sched_context,_id, ID) + DUMP_MEMBER1 (SCHED_CONTEXT, Sched_context,_prio, PRIO) + DUMP_MEMBER1 (SCHED_CONTEXT, Sched_context,_quantum, QUANTUM) + DUMP_MEMBER1 (SCHED_CONTEXT, Sched_context,_left , LEFT) + DUMP_MEMBER1 (SCHED_CONTEXT, Sched_context,_preemption_time, PREEMPTION_TIME) + DUMP_MEMBER1 (SCHED_CONTEXT, Sched_context,_prev, PREV) + DUMP_MEMBER1 (SCHED_CONTEXT, Sched_context,_next, NEXT) +#endif + DUMP_OFFSET (SCHED_CONTEXT, MAX, sizeof (Sched_context)) + + DUMP_MEMBER1 (MEM_SPACE, Mem_space, _dir, PGTABLE) + + + DUMP_MEMBER1 (TBUF_STATUS, Tracebuffer_status, kerncnts, KERNCNTS) + + DUMP_CAST_OFFSET (Thread, Receiver) + DUMP_CAST_OFFSET (Thread, Sender) + + DUMP_CONSTANT (SIZEOF_TRAP_STATE, sizeof(Trap_state)) + DUMP_MEMBER1 (VCPU_STATE, Vcpu_state, _entry_ip, ENTRY_IP) + DUMP_MEMBER1 (VCPU_STATE, Vcpu_state, _sp, ENTRY_SP) +#ifdef CONFIG_IA32 + DUMP_CONSTANT (MEM_LAYOUT__PHYSMEM, Mem_layout::Physmem) + DUMP_CONSTANT (MEM_LAYOUT__TBUF_STATUS_PAGE, Mem_layout::Tbuf_status_page) +#endif +#ifdef CONFIG_PF_PC + DUMP_CONSTANT (MEM_LAYOUT__LAPIC, Mem_layout::Local_apic_page) + DUMP_CONSTANT (MEM_LAYOUT__IO_BITMAP, Mem_layout::Io_bitmap) + DUMP_CONSTANT (MEM_LAYOUT__SYSCALLS, Mem_layout::Syscalls) +#endif +#ifdef CONFIG_PF_UX + DUMP_CONSTANT (MEM_LAYOUT__TRAMPOLINE_PAGE, Mem_layout::Trampoline_page) +#endif +#if defined(CONFIG_IA32) || defined(CONFIG_AMD64) + DUMP_MEMBER1 (CPU, Cpu, tss, TSS) +#endif + +#ifdef CONFIG_PPC32 + //offset of entry frame + DUMP_OFFSET (ENTRY, FRAME, THREAD_BLOCK_SIZE-4) + //offset of syscall frame + DUMP_OFFSET (SYSCALL, FRAME, sizeof(Return_frame)) + DUMP_CONSTANT(ENTRY__FRAME, (sizeof(Entry_frame))) + //Entry_frame size + SysV LR (16 byte aligned) + DUMP_CONSTANT(STACK__FRAME, ((sizeof(Entry_frame) + 8 + 0xf) & ~0xf)) + //SRR1 || MSR flags + DUMP_CONSTANT(MSR__KERNEL, Msr::Msr_kernel) + DUMP_CONSTANT(MSR__PR, Msr::Msr_pr) + + //physical atddress of kernel image + DUMP_CONSTANT(KERNEL__START, Mem_layout::Kernel_start) +#endif diff --git a/kernel/fiasco/src/kern/terminate.cpp b/kernel/fiasco/src/kern/terminate.cpp new file mode 100644 index 00000000..73417449 --- /dev/null +++ b/kernel/fiasco/src/kern/terminate.cpp @@ -0,0 +1,53 @@ +INTERFACE: + +#include "std_macros.h" + +IMPLEMENTATION: + +#include +#include +#include "helping_lock.h" +#include "kernel_console.h" +#include "reset.h" + +/** + * The exit handler as long as exit_question() is not installed. + */ +static +void +raw_exit() +{ + // make sure that we don't acknowledg the exit question automatically + Kconsole::console()->change_state(Console::PUSH, 0, + ~Console::INENABLED, 0); + puts("\nPress any key to reboot."); + Kconsole::console()->getchar(); + puts("\033[1mRebooting.\033[m"); + // Cpu::busy_wait_ns(10000000); + platform_reset(); +} + + +static void (*exit_question)(void) = &raw_exit; + +void set_exit_question(void (*eq)(void)) +{ + exit_question = eq; +} + + +extern "C" void FIASCO_NORETURN _exit(int); + +FIASCO_NORETURN +void +terminate (int exit_value) +{ + Helping_lock::threading_system_active = false; + + if (exit_question) + exit_question(); + + puts("\nShutting down..."); + + _exit(exit_value); +} diff --git a/kernel/fiasco/src/kern/thread-debug.cpp b/kernel/fiasco/src/kern/thread-debug.cpp new file mode 100644 index 00000000..6c9d9acd --- /dev/null +++ b/kernel/fiasco/src/kern/thread-debug.cpp @@ -0,0 +1,43 @@ +INTERFACE [debug]: + +EXTENSION class Thread +{ +protected: + struct Log_thread_exregs + { + Mword id, ip, sp, op; + }; + static unsigned fmt_exregs(Tb_entry *, int, char *) asm ("__fmt_thread_exregs"); +}; + +//-------------------------------------------------------------------------- +IMPLEMENTATION [debug]: + +#include +#include "config.h" +#include "kmem.h" +#include "mem_layout.h" +#include "simpleio.h" + + +//--------------------------------------------------------------------------- +IMPLEMENTATION [debug]: + +IMPLEMENT +unsigned +Thread::fmt_exregs(Tb_entry *e, int max, char *buf) +{ + Log_thread_exregs *l = e->payload(); + return snprintf(buf, max, "D=%lx ip=%lx sp=%lx op=%s%s%s", + l->id, l->ip, l->sp, + l->op & Exr_cancel ? "Cancel" : "", + ((l->op & (Exr_cancel | + Exr_trigger_exception)) + == (Exr_cancel | + Exr_trigger_exception)) + ? "," + : ((l->op & (Exr_cancel | + Exr_trigger_exception)) + == 0 ? "0" : "") , + l->op & Exr_trigger_exception ? "TrExc" : ""); +} diff --git a/kernel/fiasco/src/kern/thread-ipc.cpp b/kernel/fiasco/src/kern/thread-ipc.cpp new file mode 100644 index 00000000..f7900c0f --- /dev/null +++ b/kernel/fiasco/src/kern/thread-ipc.cpp @@ -0,0 +1,1237 @@ +INTERFACE: + +#include "l4_buf_iter.h" +#include "l4_error.h" + +class Syscall_frame; + +EXTENSION class Thread +{ +protected: + struct Log_pf_invalid + { + Mword pfa; + Mword cap_idx; + Mword err; + }; + + struct Log_exc_invalid + { + Mword cap_idx; + }; + + enum Check_sender_result + { + Ok = 0, + Queued = 2, + Done = 4, + Failed = 1, + }; + + Syscall_frame *_snd_regs; + unsigned char _ipc_send_rights; +}; + +class Buf_utcb_saver +{ +public: + Buf_utcb_saver(Utcb const *u); + void restore(Utcb *u); +private: + L4_buf_desc buf_desc; + Mword buf[2]; +}; + +/** + * Save critical contents of UTCB during nested IPC. + */ +class Pf_msg_utcb_saver : public Buf_utcb_saver +{ +public: + Pf_msg_utcb_saver(Utcb const *u); + void restore(Utcb *u); +private: + Mword msg[2]; +}; + +// ------------------------------------------------------------------------ +INTERFACE [debug]: + +#include "tb_entry.h" + +EXTENSION class Thread +{ +protected: + static unsigned log_fmt_pf_invalid(Tb_entry *, int max, char *buf) asm ("__fmt_page_fault_invalid_pager"); + static unsigned log_fmt_exc_invalid(Tb_entry *, int max, char *buf) asm ("__fmt_exception_invalid_handler"); +}; + +// ------------------------------------------------------------------------ +IMPLEMENTATION: + +// IPC setup, and handling of ``short IPC'' and page-fault IPC + +// IDEAS for enhancing this implementation: + +// Volkmar has suggested a possible optimization for +// short-flexpage-to-long-message-buffer transfers: Currently, we have +// to resort to long IPC in that case because the message buffer might +// contain a receive-flexpage option. An easy optimization would be +// to cache the receive-flexpage option in the TCB for that case. +// This would save us the long-IPC setup because we wouldn't have to +// touch the receiver's user memory in that case. Volkmar argues that +// cases like that are quite common -- for example, imagine a pager +// which at the same time is also a server for ``normal'' requests. + +// The handling of cancel and timeout conditions could be improved as +// follows: Cancel and Timeout should not reset the ipc_in_progress +// flag. Instead, they should just set and/or reset a flag of their +// own that is checked every time an (IPC) system call wants to go to +// sleep. That would mean that IPCs that do not block are not +// cancelled or aborted. +//- + +#include // panic() + +#include "l4_types.h" +#include "l4_msg_item.h" + +#include "config.h" +#include "cpu_lock.h" +#include "ipc_timeout.h" +#include "lock_guard.h" +#include "logdefs.h" +#include "map_util.h" +#include "processor.h" +#include "timer.h" +#include "kdb_ke.h" +#include "warn.h" + +PUBLIC +virtual void +Thread::ipc_receiver_aborted() +{ + assert_kdb (wait_queue()); + set_wait_queue(0); + + // remote_ready_enqueue(): is only for mp + activate(); +} + +PRIVATE +void +Thread::ipc_send_msg(Receiver *recv) +{ + Syscall_frame *regs = _snd_regs; + bool success = transfer_msg(regs->tag(), nonull_static_cast(recv), regs, + _ipc_send_rights); + sender_dequeue(recv->sender_list()); + recv->vcpu_update_state(); + //printf(" done\n"); + regs->tag(L4_msg_tag(regs->tag(), success ? 0 : L4_msg_tag::Error)); + + Mword state_del = Thread_ipc_mask | Thread_ipc_transfer; + Mword state_add = Thread_ready; + if (Receiver::prepared()) + // same as in Receiver::prepare_receive_dirty_2 + state_add |= Thread_receive_wait; + + if (cpu() == current_cpu()) + { + state_change_dirty(~state_del, state_add); + if (current_sched()->deblock(cpu(), current_sched(), true)) + recv->switch_to_locked(this); + } + else + { + drq_state_change(~state_del, state_add); + current()->schedule_if(current()->handle_drq()); + } +} + +PUBLIC virtual +void +Thread::modify_label(Mword const *todo, int cnt) +{ + assert_kdb (_snd_regs); + Mword l = _snd_regs->from_spec(); + for (int i = 0; i < cnt*4; i += 4) + { + Mword const test_mask = todo[i]; + Mword const test = todo[i+1]; + if ((l & test_mask) == test) + { + Mword const del_mask = todo[i+2]; + Mword const add_mask = todo[i+3]; + + l = (l & ~del_mask) | add_mask; + _snd_regs->from(l); + return; + } + } +} + +PRIVATE inline +void +Thread::snd_regs(Syscall_frame *r) +{ _snd_regs = r; } + + +/** Page fault handler. + This handler suspends any ongoing IPC, then sets up page-fault IPC. + Finally, the ongoing IPC's state (if any) is restored. + @param pfa page-fault virtual address + @param error_code page-fault error code. + */ +PRIVATE +bool +Thread::handle_page_fault_pager(Thread_ptr const &_pager, + Address pfa, Mword error_code, + L4_msg_tag::Protocol protocol) +{ +#ifndef NDEBUG + // do not handle user space page faults from kernel mode if we're + // already handling a request + if (EXPECT_FALSE(!PF::is_usermode_error(error_code) + && thread_lock()->test() == Thread_lock::Locked)) + { + kdb_ke("Fiasco BUG: page fault, under lock"); + panic("page fault in locked operation"); + } +#endif + + if (EXPECT_FALSE((state() & Thread_alien))) + return false; + + Lock_guard guard(&cpu_lock); + + unsigned char rights; + Kobject_iface *pager = _pager.ptr(space(), &rights); + + if (!pager) + { + WARN("CPU%d: Pager of %lx is invalid (pfa=" L4_PTR_FMT + ", errorcode=" L4_PTR_FMT ") to %lx (pc=%lx)\n", + current_cpu(), dbg_id(), pfa, error_code, + _pager.raw(), regs()->ip()); + + + LOG_TRACE("Page fault invalid pager", "pf", this, + __fmt_page_fault_invalid_pager, + Log_pf_invalid *l = tbe->payload(); + l->cap_idx = _pager.raw(); + l->err = error_code; + l->pfa = pfa); + + pager = this; // block on ourselves + } + + // set up a register block used as an IPC parameter block for the + // page fault IPC + Syscall_frame r; + + // save the UTCB fields affected by PF IPC + Mword vcpu_irqs = vcpu_disable_irqs(); + Mem::barrier(); + Utcb *utcb = this->utcb().access(true); + Pf_msg_utcb_saver saved_utcb_fields(utcb); + + + utcb->buf_desc = L4_buf_desc(0, 0, 0, L4_buf_desc::Inherit_fpu); + utcb->buffers[0] = L4_msg_item::map(0).raw(); + utcb->buffers[1] = L4_fpage::all_spaces().raw(); + + utcb->values[0] = PF::addr_to_msgword0 (pfa, error_code); + utcb->values[1] = regs()->ip(); //PF::pc_to_msgword1 (regs()->ip(), error_code)); + + L4_timeout_pair timeout(L4_timeout::Never, L4_timeout::Never); + + L4_msg_tag tag(2, 0, 0, protocol); + + r.timeout(timeout); + r.tag(tag); + r.from(0); + r.ref(L4_obj_ref(_pager.raw() << L4_obj_ref::Cap_shift, L4_obj_ref::Ipc_call_ipc)); + pager->invoke(r.ref(), rights, &r, utcb); + + + bool success = true; + + if (EXPECT_FALSE(r.tag().has_error())) + { + if (utcb->error.snd_phase() + && (utcb->error.error() == L4_error::Not_existent) + && PF::is_usermode_error(error_code) + && !(state() & Thread_cancel)) + { + success = false; + } + } + else // no error + { + // If the pager rejects the mapping, it replies -1 in msg.w0 + if (EXPECT_FALSE (utcb->values[0] == Mword(-1))) + success = false; + } + + // restore previous IPC state + + saved_utcb_fields.restore(utcb); + Mem::barrier(); + vcpu_restore_irqs(vcpu_irqs); + return success; +} + +PRIVATE inline +Mword +Thread::check_sender(Thread *sender, bool timeout) +{ + if (EXPECT_FALSE(is_invalid())) + { + sender->utcb().access()->error = L4_error::Not_existent; + return Failed; + } + + if (EXPECT_FALSE(!sender_ok(sender))) + { + if (!timeout) + { + sender->utcb().access()->error = L4_error::Timeout; + return Failed; + } + + sender->set_wait_queue(sender_list()); + sender->sender_enqueue(sender_list(), sender->sched_context()->prio()); + vcpu_set_irq_pending(); + return Queued; + } + + return Ok; +} + + +PRIVATE inline NEEDS["timer.h"] +void Thread::goto_sleep(L4_timeout const &t, Sender *sender, Utcb *utcb) +{ + IPC_timeout timeout; + + if (EXPECT_FALSE(t.is_finite() && !_timeout)) + { + state_del_dirty(Thread_ready); + + Unsigned64 sysclock = Timer::system_clock(); + Unsigned64 tval = t.microsecs(sysclock, utcb); + + if (EXPECT_TRUE((tval > sysclock))) + { + set_timeout(&timeout); + timeout.set(tval, cpu()); + } + else // timeout already hit + state_change_dirty(~Thread_ipc_mask, Thread_ready | Thread_timeout); + } + else + { + if (EXPECT_TRUE(t.is_never())) + state_del_dirty(Thread_ready); + else + state_change_dirty(~Thread_ipc_mask, Thread_ready | Thread_timeout); + } + + if (sender == this) + switch_sched(sched()); + + schedule(); + + if (EXPECT_FALSE((long)_timeout)) + { + timeout.reset(); + set_timeout(0); + } + + assert_kdb (state() & Thread_ready); +} + + + +/** + * @pre cpu_lock must be held + */ +PRIVATE inline NEEDS["logdefs.h"] +unsigned +Thread::handshake_receiver(Thread *partner, L4_timeout snd_t) +{ + assert_kdb(cpu_lock.test()); + + switch (__builtin_expect(partner->check_sender(this, !snd_t.is_zero()), Ok)) + { + case Failed: + return Failed; + case Queued: + state_add_dirty(Thread_send_wait); + return Queued; + default: + partner->state_change_dirty(~(Thread_ipc_mask | Thread_ready), Thread_ipc_transfer); + return Ok; + } +} + +PRIVATE inline +void +Thread::set_ipc_error(L4_error const &e, Thread *rcv) +{ + utcb().access()->error = e; + rcv->utcb().access()->error = L4_error(e, L4_error::Rcv); +} + + +PRIVATE inline +Sender * +Thread::get_next_sender(Sender *sender) +{ + if (!sender_list()->empty()) + { + if (sender) // closed wait + { + if (sender->in_sender_list() && sender_list() == sender->wait_queue()) + return sender; + } + else // open wait + { + Sender *next = Sender::cast(sender_list()->first()); + assert_kdb (next->in_sender_list()); + set_partner(next); + return next; + } + } + return 0; +} + + +/** + * Send an IPC message. + * Block until we can send the message or the timeout hits. + * @param partner the receiver of our message + * @param t a timeout specifier + * @param regs sender's IPC registers + * @pre cpu_lock must be held + * @return sender's IPC error code + */ +PUBLIC +void +Thread::do_ipc(L4_msg_tag const &tag, bool have_send, Thread *partner, + bool have_receive, Sender *sender, + L4_timeout_pair t, Syscall_frame *regs, + unsigned char rights) +{ + assert_kdb (cpu_lock.test()); + assert_kdb (this == current()); + + bool do_switch = false; + + assert_kdb (!(state() & Thread_ipc_mask)); + + prepare_receive(sender, have_receive ? regs : 0); + bool activate_partner = false; + + if (have_send) + { + assert_kdb(!in_sender_list()); + do_switch = tag.do_switch(); + + bool ok; + unsigned result; + + set_ipc_send_rights(rights); + + if (EXPECT_FALSE(partner->cpu() != current_cpu()) || + ((result = handshake_receiver(partner, t.snd)) == Failed + && partner->drq_pending())) + { + // we have either per se X-CPU IPC or we ran into a + // IPC during migration (indicated by the pending DRQ) + do_switch = false; + result = remote_handshake_receiver(tag, partner, have_receive, t.snd, + regs, rights); + } + + switch (__builtin_expect(result, Ok)) + { + case Done: + ok = true; + break; + + case Queued: + // set _snd_regs, to enable active receiving + snd_regs(regs); + ok = do_send_wait(partner, t.snd); // --- blocking point --- + break; + + case Failed: + state_del_dirty(Thread_ipc_mask); + ok = false; + break; + + default: + // mmh, we can reset the receivers timeout + // ping pong with timeouts will profit from it, because + // it will require much less sorting overhead + // if we dont reset the timeout, the possibility is very high + // that the receiver timeout is in the timeout queue + partner->reset_timeout(); + + ok = transfer_msg(tag, partner, regs, rights); + + // switch to receiving state + state_del_dirty(Thread_ipc_mask); + if (ok && have_receive) + state_add_dirty(Thread_receive_wait); + + activate_partner = partner != this; + break; + } + + if (EXPECT_FALSE(!ok)) + { + // send failed, so do not switch to receiver directly and skip receive phase + have_receive = false; + regs->tag(L4_msg_tag(0, 0, L4_msg_tag::Error, 0)); + } + } + else + { + assert_kdb (have_receive); + state_add_dirty(Thread_receive_wait); + } + + // only do direct switch on closed wait (call) or if we run on a foreign + // scheduling context + Sender *next = 0; + + have_receive = state() & Thread_receive_wait; + + if (have_receive) + { + assert_kdb (!in_sender_list()); + assert_kdb (!(state() & Thread_send_wait)); + next = get_next_sender(sender); + } + + if (activate_partner) + { + if (partner->cpu() == current_cpu()) + { + Sched_context *cs = Sched_context::rq(cpu()).current_sched(); + do_switch = do_switch && ((have_receive && sender) || cs->context() != this) + && !(next && current_sched()->dominates(cs)); + partner->state_change_dirty(~Thread_ipc_transfer, Thread_ready); + if (do_switch) + schedule_if(handle_drq() || switch_exec_locked(partner, Context::Not_Helping)); + else if (partner->current_sched()->deblock(current_cpu(), current_sched(), true)) + switch_to_locked(partner); + } + else + partner->drq_state_change(~Thread_ipc_transfer, Thread_ready); + } + + if (next) + { + state_change_dirty(~Thread_ipc_mask, Thread_receive_in_progress); + next->ipc_send_msg(this); + state_del_dirty(Thread_ipc_mask); + } + else if (have_receive) + { + if ((state() & Thread_full_ipc_mask) == Thread_receive_wait) + goto_sleep(t.rcv, sender, utcb().access(true)); + } + + if (EXPECT_TRUE (!(state() & Thread_full_ipc_mask))) + return; + + while (EXPECT_FALSE(state() & Thread_ipc_transfer)) + { + state_del_dirty(Thread_ready); + schedule(); + } + + if (EXPECT_TRUE (!(state() & Thread_full_ipc_mask))) + return; + + Utcb *utcb = this->utcb().access(true); + // the IPC has not been finished. could be timeout or cancel + // XXX should only modify the error-code part of the status code + + if (EXPECT_FALSE(state() & Thread_cancel)) + { + // we've presumably been reset! + regs->tag(commit_error(utcb, L4_error::R_canceled, regs->tag())); + } + else + regs->tag(commit_error(utcb, L4_error::R_timeout, regs->tag())); + state_del(Thread_full_ipc_mask); +} + + +PRIVATE inline NEEDS [Thread::copy_utcb_to] +bool +Thread::transfer_msg(L4_msg_tag tag, Thread *receiver, + Syscall_frame *sender_regs, unsigned char rights) +{ + Syscall_frame* dst_regs = receiver->rcv_regs(); + + bool success = copy_utcb_to(tag, receiver, rights); + tag.set_error(!success); + dst_regs->tag(tag); + dst_regs->from(sender_regs->from_spec()); + + // setup the reply capability in case of a call + if (success && partner() == receiver) + receiver->set_caller(this, rights); + + return success; +} + + + +IMPLEMENT inline +Buf_utcb_saver::Buf_utcb_saver(const Utcb *u) +{ + buf_desc = u->buf_desc; + buf[0] = u->buffers[0]; + buf[1] = u->buffers[1]; +} + +IMPLEMENT inline +void +Buf_utcb_saver::restore(Utcb *u) +{ + u->buf_desc = buf_desc; + u->buffers[0] = buf[0]; + u->buffers[1] = buf[1]; +} + +IMPLEMENT inline +Pf_msg_utcb_saver::Pf_msg_utcb_saver(Utcb const *u) : Buf_utcb_saver(u) +{ + msg[0] = u->values[0]; + msg[1] = u->values[1]; +} + +IMPLEMENT inline +void +Pf_msg_utcb_saver::restore(Utcb *u) +{ + Buf_utcb_saver::restore(u); + u->values[0] = msg[0]; + u->values[1] = msg[1]; +} + + +/** + * \pre must run with local IRQs disabled (CPU lock held) + * to ensure that handler does not dissapear meanwhile. + */ +PRIVATE +bool +Thread::exception(Kobject_iface *handler, Trap_state *ts, Mword rights) +{ + Syscall_frame r; + L4_timeout_pair timeout(L4_timeout::Never, L4_timeout::Never); + + CNT_EXC_IPC; + + Mword vcpu_irqs = vcpu_disable_irqs(); + Mem::barrier(); + + void *old_utcb_handler = _utcb_handler; + _utcb_handler = ts; + + // fill registers for IPC + Utcb *utcb = this->utcb().access(true); + Buf_utcb_saver saved_state(utcb); + + utcb->buf_desc = L4_buf_desc(0, 0, 0, L4_buf_desc::Inherit_fpu); + utcb->buffers[0] = L4_msg_item::map(0).raw(); + utcb->buffers[1] = L4_fpage::all_spaces().raw(); + + // clear regs + L4_msg_tag tag(L4_exception_ipc::Msg_size, 0, L4_msg_tag::Transfer_fpu, + L4_msg_tag::Label_exception); + + r.tag(tag); + r.timeout(timeout); + r.from(0); + r.ref(L4_obj_ref(_exc_handler.raw() << L4_obj_ref::Cap_shift, L4_obj_ref::Ipc_call_ipc)); + spill_user_state(); + handler->invoke(r.ref(), rights, &r, utcb); + fill_user_state(); + + saved_state.restore(utcb); + + if (EXPECT_FALSE(r.tag().has_error())) + state_del(Thread_in_exception); + else if (r.tag().proto() == L4_msg_tag::Label_allow_syscall) + state_add(Thread_dis_alien); + + // restore original utcb_handler + _utcb_handler = old_utcb_handler; + Mem::barrier(); + vcpu_restore_irqs(vcpu_irqs); + + // FIXME: handle not existing pager properly + // for now, just ignore any errors + return 1; +} + +/* return 1 if exception could be handled + * return 0 if not for send_exception and halt thread + */ +PUBLIC inline NEEDS["task.h", "trap_state.h", + Thread::fast_return_to_user, + Thread::save_fpu_state_to_utcb] +int +Thread::send_exception(Trap_state *ts) +{ + assert(cpu_lock.test()); + + Vcpu_state *vcpu = vcpu_state().access(); + + if (vcpu_exceptions_enabled(vcpu)) + { + // do not reflect debug exceptions to the VCPU but handle them in + // Fiasco + if (EXPECT_FALSE(ts->is_debug_exception() + && !(vcpu->state & Vcpu_state::F_debug_exc))) + return 0; + + if (_exc_cont.valid()) + return 1; + + // before entering kernel mode to have original fpu state before + // enabling fpu + save_fpu_state_to_utcb(ts, utcb().access()); + + spill_user_state(); + + if (vcpu_enter_kernel_mode(vcpu)) + { + // enter_kernel_mode has switched the address space from user to + // kernel space, so reevaluate the address of the VCPU state area + vcpu = vcpu_state().access(); + } + + LOG_TRACE("VCPU events", "vcpu", this, __context_vcpu_log_fmt, + Vcpu_log *l = tbe->payload(); + l->type = 2; + l->state = vcpu->_saved_state; + l->ip = ts->ip(); + l->sp = ts->sp(); + l->trap = ts->trapno(); + l->err = ts->error(); + l->space = vcpu_user_space() ? static_cast(vcpu_user_space())->dbg_id() : ~0; + ); + memcpy(&vcpu->_ts, ts, sizeof(Trap_state)); + fast_return_to_user(vcpu->_entry_ip, vcpu->_sp, vcpu_state().usr().get()); + } + + // local IRQs must be disabled because we dereference a Thread_ptr + if (EXPECT_FALSE(_exc_handler.is_kernel())) + return 0; + + if (!send_exception_arch(ts)) + return 0; // do not send exception + + unsigned char rights = 0; + Kobject_iface *pager = _exc_handler.ptr(space(), &rights); + + if (EXPECT_FALSE(!pager)) + { + /* no pager (anymore), just ignore the exception, return success */ + LOG_TRACE("Exception invalid handler", "exc", this, + __fmt_exception_invalid_handler, + Log_exc_invalid *l = tbe->payload(); + l->cap_idx = _exc_handler.raw()); + if (EXPECT_FALSE(space()->is_sigma0())) + { + ts->dump(); + WARNX(Error, "Sigma0 raised an exception --> HALT\n"); + panic("..."); + } + + pager = this; // block on ourselves + } + + state_change(~Thread_cancel, Thread_in_exception); + + return exception(pager, ts, rights); +} + +PRIVATE static +bool +Thread::try_transfer_local_id(L4_buf_iter::Item const *const buf, + L4_fpage sfp, Mword *rcv_word, Thread* snd, + Thread *rcv) +{ + if (buf->b.is_rcv_id()) + { + if (snd->space() == rcv->space()) + { + rcv_word[-2] |= 6; + rcv_word[-1] = sfp.raw(); + return true; + } + else + { + unsigned char rights = 0; + Obj_space::Capability cap = snd->space()->lookup(sfp.obj_index()); + Kobject_iface *o = cap.obj(); + rights = cap.rights(); + if (EXPECT_TRUE(o && o->is_local(rcv->space()))) + { + rcv_word[-2] |= 4; + rcv_word[-1] = o->obj_id() | Mword(rights); + return true; + } + } + } + return false; +} + +PRIVATE static inline +bool FIASCO_WARN_RESULT +Thread::copy_utcb_to_utcb(L4_msg_tag const &tag, Thread *snd, Thread *rcv, + unsigned char rights) +{ + assert (cpu_lock.test()); + + Utcb *snd_utcb = snd->utcb().access(); + Utcb *rcv_utcb = rcv->utcb().access(); + Mword s = tag.words(); + Mword r = Utcb::Max_words; + + Mem::memcpy_mwords(rcv_utcb->values, snd_utcb->values, r < s ? r : s); + + bool success = true; + if (tag.items()) + success = transfer_msg_items(tag, snd, snd_utcb, rcv, rcv_utcb, rights); + + if (tag.transfer_fpu() && rcv_utcb->inherit_fpu() && (rights & L4_fpage::W)) + snd->transfer_fpu(rcv); + + return success; +} + + +PUBLIC inline NEEDS[Thread::copy_utcb_to_ts, Thread::copy_utcb_to_utcb, + Thread::copy_ts_to_utcb] +bool FIASCO_WARN_RESULT +Thread::copy_utcb_to(L4_msg_tag const &tag, Thread* receiver, + unsigned char rights) +{ + // we cannot copy trap state to trap state! + assert_kdb (!this->_utcb_handler || !receiver->_utcb_handler); + if (EXPECT_FALSE(this->_utcb_handler != 0)) + return copy_ts_to_utcb(tag, this, receiver, rights); + else if (EXPECT_FALSE(receiver->_utcb_handler != 0)) + return copy_utcb_to_ts(tag, this, receiver, rights); + else + return copy_utcb_to_utcb(tag, this, receiver, rights); +} + +PRIVATE static +bool +Thread::transfer_msg_items(L4_msg_tag const &tag, Thread* snd, Utcb *snd_utcb, + Thread *rcv, Utcb *rcv_utcb, + unsigned char rights) +{ + // LOG_MSG_3VAL(current(), "map bd=", rcv_utcb->buf_desc.raw(), 0, 0); + Task *const rcv_t = nonull_static_cast(rcv->space()); + L4_buf_iter mem_buffer(rcv_utcb, rcv_utcb->buf_desc.mem()); + L4_buf_iter io_buffer(rcv_utcb, rcv_utcb->buf_desc.io()); + L4_buf_iter obj_buffer(rcv_utcb, rcv_utcb->buf_desc.obj()); + L4_snd_item_iter snd_item(snd_utcb, tag.words()); + register int items = tag.items(); + Mword *rcv_word = rcv_utcb->values + tag.words(); + + // XXX: damn X-CPU state modification + // snd->prepare_long_ipc(rcv); + Reap_list rl; + + for (;items > 0 && snd_item.more();) + { + if (EXPECT_FALSE(!snd_item.next())) + { + snd->set_ipc_error(L4_error::Overflow, rcv); + return false; + } + + L4_snd_item_iter::Item const *const item = snd_item.get(); + + if (item->b.is_void()) + { // XXX: not sure if void fpages are needed + // skip send item and current rcv_buffer + --items; + continue; + } + + L4_buf_iter *buf_iter = 0; + + switch (item->b.type()) + { + case L4_msg_item::Map: + switch (L4_fpage(item->d).type()) + { + case L4_fpage::Memory: buf_iter = &mem_buffer; break; + case L4_fpage::Io: buf_iter = &io_buffer; break; + case L4_fpage::Obj: buf_iter = &obj_buffer; break; + default: break; + } + break; + default: + break; + } + + if (EXPECT_FALSE(!buf_iter)) + { + // LOG_MSG_3VAL(snd, "lIPCm0", 0, 0, 0); + snd->set_ipc_error(L4_error::Overflow, rcv); + return false; + } + + L4_buf_iter::Item const *const buf = buf_iter->get(); + + if (EXPECT_FALSE(buf->b.is_void() || buf->b.type() != item->b.type())) + { + // LOG_MSG_3VAL(snd, "lIPCm1", buf->b.raw(), item->b.raw(), 0); + snd->set_ipc_error(L4_error::Overflow, rcv); + return false; + } + + { + assert_kdb (item->b.type() == L4_msg_item::Map); + L4_fpage sfp(item->d); + *rcv_word = (item->b.raw() & ~0x0ff7) | (sfp.raw() & 0x0ff0); + + rcv_word += 2; + + if (!try_transfer_local_id(buf, sfp, rcv_word, snd, rcv)) + { + // we need to do a real mapping¿ + + // diminish when sending via restricted ipc gates + if (sfp.type() == L4_fpage::Obj) + sfp.mask_rights(L4_fpage::Rights(rights | L4_fpage::RX)); + + L4_error err; + + { + // We take the existence_lock for syncronizing maps... + // This is kind of coarse grained + Lock_guardexistence_lock)> sp_lock; + if (!sp_lock.try_lock(&rcv_t->existence_lock)) + { + snd->set_ipc_error(L4_error::Overflow, rcv); + return false; + } + + Lock_guard c_lock(&cpu_lock); + err = fpage_map(snd->space(), sfp, + rcv->space(), L4_fpage(buf->d), item->b, &rl); + } + + if (EXPECT_FALSE(!err.ok())) + { + snd->set_ipc_error(err, rcv); + return false; + } + } + } + + --items; + + if (!item->b.compound()) + buf_iter->next(); + } + + if (EXPECT_FALSE(items)) + { + snd->set_ipc_error(L4_error::Overflow, rcv); + return false; + } + + return true; +} + + +/** + * \pre Runs on the sender CPU + */ +PRIVATE inline +bool +Thread::abort_send(L4_error const &e, Thread *partner) +{ + state_del_dirty(Thread_full_ipc_mask); + + if (_timeout && _timeout->is_set()) + _timeout->reset(); + + set_timeout(0); + Abort_state abt = Abt_ipc_done; + + if (partner->cpu() == current_cpu()) + { + if (in_sender_list()) + { + sender_dequeue(partner->sender_list()); + partner->vcpu_update_state(); + abt = Abt_ipc_cancel; + + } + else if (partner->in_ipc(this)) + abt = Abt_ipc_in_progress; + } + else + abt = partner->Receiver::abort_send(this); + + switch (abt) + { + default: + case Abt_ipc_done: + return true; + case Abt_ipc_cancel: + utcb().access()->error = e; + return false; + case Abt_ipc_in_progress: + state_add_dirty(Thread_ipc_transfer); + while (state() & Thread_ipc_transfer) + { + state_del_dirty(Thread_ready); + schedule(); + } + return true; + } +} + + + +/** + * \pre Runs on the sender CPU + */ +PRIVATE inline +bool +Thread::do_send_wait(Thread *partner, L4_timeout snd_t) +{ + IPC_timeout timeout; + + if (EXPECT_FALSE(snd_t.is_finite())) + { + Unsigned64 tval = snd_t.microsecs(Timer::system_clock(), utcb().access(true)); + // Zero timeout or timeout expired already -- give up + if (tval == 0) + return abort_send(L4_error::Timeout, partner); + + set_timeout(&timeout); + timeout.set(tval, cpu()); + } + + register Mword ipc_state; + + while (((ipc_state = state() & (Thread_send_wait | Thread_ipc_abort_mask))) == Thread_send_wait) + { + state_del_dirty(Thread_ready); + schedule(); + } + + if (EXPECT_FALSE(ipc_state == (Thread_cancel | Thread_send_wait))) + return abort_send(L4_error::Canceled, partner); + + if (EXPECT_FALSE(ipc_state == (Thread_timeout | Thread_send_wait))) + return abort_send(L4_error::Timeout, partner); + + timeout.reset(); + set_timeout(0); + + return true; +} + +PRIVATE inline +void +Thread::set_ipc_send_rights(unsigned char c) +{ + _ipc_send_rights = c; +} + +//--------------------------------------------------------------------- +IMPLEMENTATION [!mp]: + +PRIVATE inline NEEDS ["l4_types.h"] +unsigned +Thread::remote_handshake_receiver(L4_msg_tag const &, Thread *, + bool, L4_timeout, Syscall_frame *, unsigned char) +{ + kdb_ke("Remote IPC in UP kernel"); + return Failed; +} + +//--------------------------------------------------------------------- +INTERFACE [mp]: + +struct Ipc_remote_request; + +struct Ipc_remote_request +{ + L4_msg_tag tag; + Thread *partner; + Syscall_frame *regs; + unsigned char rights; + bool timeout; + bool have_rcv; + + unsigned result; +}; + +struct Ready_queue_request +{ + Thread *thread; + Mword state_add; + Mword state_del; + + enum Result { Done, Wrong_cpu, Not_existent }; + Result result; +}; + +//--------------------------------------------------------------------- +IMPLEMENTATION [mp]: + + +PRIVATE inline NOEXPORT +bool +Thread::remote_ipc_send(Context *src, Ipc_remote_request *rq) +{ + (void)src; + // LOG_MSG_3VAL(this, "rse", current_cpu(), (Mword)src, (Mword)this); +#if 0 + LOG_MSG_3VAL(this, "rsend", (Mword)src, 0, 0); + printf("CPU[%u]: remote IPC send ...\n" + " partner=%p [%u]\n" + " sender =%p [%u] regs=%p\n" + " timeout=%u\n", + current_cpu(), + rq->partner, rq->partner->cpu(), + src, src->cpu(), + rq->regs, + rq->timeout); +#endif + + switch (__builtin_expect(rq->partner->check_sender(this, rq->timeout), Ok)) + { + case Failed: + rq->result = Failed; + return false; + case Queued: + rq->result = Queued; + return false; + default: + break; + } + + // trigger remote_ipc_receiver_ready path, because we may need to grab locks + // and this is forbidden in a DRQ handler. So transfer the IPC in usual + // thread code. However, this induces a overhead of two extra IPIs. + if (rq->tag.items()) + { + //LOG_MSG_3VAL(rq->partner, "pull", dbg_id(), 0, 0); + rq->partner->state_change_dirty(~(Thread_ipc_mask | Thread_ready), Thread_ipc_transfer); + rq->result = Ok; + return true; + } + bool success = transfer_msg(rq->tag, rq->partner, rq->regs, _ipc_send_rights); + rq->result = success ? Done : Failed; + + rq->partner->state_change_dirty(~Thread_ipc_mask, Thread_ready); + // hm, should be done by lazy queueing: rq->partner->ready_enqueue(); + return true; +} + +PRIVATE static +unsigned +Thread::handle_remote_ipc_send(Drq *src, Context *, void *_rq) +{ + Ipc_remote_request *rq = (Ipc_remote_request*)_rq; + bool r = nonull_static_cast(src->context())->remote_ipc_send(src->context(), rq); + //LOG_MSG_3VAL(src, "rse<", current_cpu(), (Mword)src, r); + return r ? Drq::Need_resched : 0; +} + +/** + * \pre Runs on the sender CPU + */ +PRIVATE //inline NEEDS ["mp_request.h"] +unsigned +Thread::remote_handshake_receiver(L4_msg_tag const &tag, Thread *partner, + bool have_receive, + L4_timeout snd_t, Syscall_frame *regs, + unsigned char rights) +{ + // Flag that there must be no switch in the receive path. + // This flag also prevents the receive path from accessing + // the thread state of a remote sender. + Ipc_remote_request rq; + rq.tag = tag; + rq.have_rcv = have_receive; + rq.partner = partner; + rq.timeout = !snd_t.is_zero(); + rq.regs = regs; + rq.rights = rights; + _snd_regs = regs; + + set_wait_queue(partner->sender_list()); + + state_add_dirty(Thread_send_wait); + + partner->drq(handle_remote_ipc_send, &rq, + remote_prepare_receive); + + return rq.result; +} + +PRIVATE static +unsigned +Thread::remote_prepare_receive(Drq *src, Context *, void *arg) +{ + Context *c = src->context(); + Ipc_remote_request *rq = (Ipc_remote_request*)arg; + //printf("CPU[%2u:%p]: remote_prepare_receive (err=%x)\n", current_cpu(), c, rq->err.error()); + + // No atomic switch to receive state if we are queued, or the IPC must be done by + // the sender's CPU + if (EXPECT_FALSE(rq->result == Queued || rq->result == Ok)) + return 0; + + c->state_del(Thread_ipc_mask); + if (EXPECT_FALSE((rq->result & Failed) || !rq->have_rcv)) + return 0; + + c->state_add_dirty(Thread_receive_wait); + return 0; +} + +//--------------------------------------------------------------------------- +IMPLEMENTATION [debug]: + +IMPLEMENT +unsigned +Thread::log_fmt_pf_invalid(Tb_entry *e, int max, char *buf) +{ + Log_pf_invalid *l = e->payload(); + return snprintf(buf, max, "InvCap C:%lx pfa=%lx err=%lx", l->cap_idx, l->pfa, l->err); +} + +IMPLEMENT +unsigned +Thread::log_fmt_exc_invalid(Tb_entry *e, int max, char *buf) +{ + Log_exc_invalid *l = e->payload(); + return snprintf(buf, max, "InvCap C:%lx", l->cap_idx); +} diff --git a/kernel/fiasco/src/kern/thread-log.cpp b/kernel/fiasco/src/kern/thread-log.cpp new file mode 100644 index 00000000..37c56f69 --- /dev/null +++ b/kernel/fiasco/src/kern/thread-log.cpp @@ -0,0 +1,39 @@ +IMPLEMENTATION [log]: + +#include +#include "config.h" +#include "jdb_trace.h" +#include "jdb_tbuf.h" +#include "types.h" +#include "cpu_lock.h" + +PUBLIC static inline NEEDS["jdb_trace.h"] +int +Thread::log_page_fault() +{ + return Jdb_pf_trace::log(); +} + + +/** Page-fault logging. + */ +void +Thread::page_fault_log(Address pfa, unsigned error_code, unsigned long eip) +{ + if (Jdb_pf_trace::check_restriction(current_thread()->dbg_id(), pfa)) + { + Lock_guard guard (&cpu_lock); + + Tb_entry_pf _local; + Tb_entry_pf *tb = static_cast + (EXPECT_TRUE(Jdb_pf_trace::log_buf()) ? Jdb_tbuf::new_entry() + : &_local); + tb->set(this, eip, pfa, error_code, current()->space()); + + if (EXPECT_TRUE(Jdb_pf_trace::log_buf())) + Jdb_tbuf::commit_entry(); + else + Jdb_tbuf::direct_log_entry(tb, "PF"); + } +} + diff --git a/kernel/fiasco/src/kern/thread-pagefault.cpp b/kernel/fiasco/src/kern/thread-pagefault.cpp new file mode 100644 index 00000000..63966ce5 --- /dev/null +++ b/kernel/fiasco/src/kern/thread-pagefault.cpp @@ -0,0 +1,127 @@ +IMPLEMENTATION: + +#include + +#include "config.h" +#include "cpu.h" +#include "kdb_ke.h" +#include "kmem.h" +#include "logdefs.h" +#include "processor.h" +#include "regdefs.h" +#include "std_macros.h" +#include "thread.h" +#include "warn.h" + + +/** + * The global page fault handler switch. + * Handles page-fault monitoring, classification of page faults based on + * virtual-memory area they occured in, page-directory updates for kernel + * faults, IPC-window updates, and invocation of paging function for + * user-space page faults (handle_page_fault_pager). + * @param pfa page-fault virtual address + * @param error_code CPU error code + * @return true if page fault could be resolved, false otherwise + * @exception longjmp longjumps to recovery location if page-fault + * handling fails (i.e., return value would be false), + * but recovery location has been installed + */ +IMPLEMENT inline NEEDS[,"regdefs.h", "kdb_ke.h","processor.h", + "config.h","std_macros.h","logdefs.h", + "warn.h",Thread::page_fault_log] +int Thread::handle_page_fault (Address pfa, Mword error_code, Mword pc, + Return_frame *regs) +{ + //if (Config::Log_kernel_page_faults && !PF::is_usermode_error(error_code)) + if (0 && current_cpu() != 0) + { + Lock_guard guard(&cpu_lock); + printf("*KP[cpu=%u, sp=%lx, pfa=%lx, pc=%lx, error=(%lx)", current_cpu(), Proc::stack_pointer(), pfa, pc, error_code); + print_page_fault_error(error_code); + printf("]\n"); + } + +#if 0 + printf("Translation error ? %x\n" + " current space has mapping : %08x\n" + " Kernel space has mapping : %08x\n", + PF::is_translation_error(error_code), + current_mem_space()->lookup((void*)pfa), + Space::kernel_space()->lookup((void*)pfa)); +#endif + + + CNT_PAGE_FAULT; + + // TODO: put this into a debug_page_fault_handler + if (EXPECT_FALSE(log_page_fault())) + page_fault_log(pfa, error_code, pc); + + L4_msg_tag ipc_code = L4_msg_tag(0, 0, 0, 0); + + // Check for page fault in user memory area + if (EXPECT_TRUE (!Kmem::is_kmem_page_fault(pfa, error_code))) + { + // Make sure that we do not handle page faults that do not + // belong to this thread. + //assert_kdb (mem_space() == current_mem_space()); + + if (EXPECT_FALSE (mem_space()->is_sigma0())) + { + // special case: sigma0 can map in anything from the kernel + if(handle_sigma0_page_fault(pfa)) + return 1; + + ipc_code.set_error(); + goto error; + } + + // user mode page fault -- send pager request + if (handle_page_fault_pager(_pager, pfa, error_code, + L4_msg_tag::Label_page_fault)) + return 1; + + goto error; + } + + // Check for page fault in kernel memory region caused by user mode + else if (EXPECT_FALSE(PF::is_usermode_error(error_code))) + return 0; // disallow access after mem_user_max + + // Check for page fault in IO bit map or in delimiter byte behind IO bitmap + // assume it is caused by an input/output instruction and fall through to + // handle_slow_trap + else if (EXPECT_FALSE(Kmem::is_io_bitmap_page_fault(pfa))) + return 0; + + // We're in kernel code faulting on a kernel memory region + + // A page is not present but a mapping exists in the global page dir. + // Update our page directory by copying from the master pdir + // This is the only path that should be executed with interrupts + // disabled if the page faulter also had interrupts disabled. + // thread_page_fault() takes care of that. + else if (Mem_layout::is_caps_area(pfa)) + { + // Test for special case -- see function documentation + if (pagein_tcb_request(regs)) + return 2; + + printf("Fiasco BUG: Invalid CAP access (pc=%lx, pfa=%lx)\n", pc, pfa); + kdb_ke("Fiasco BUG: Invalid access to Caps area"); + return 0; + } + + WARN("No page-fault handler for 0x%lx, error 0x%lx, pc " L4_PTR_FMT "\n", + pfa, error_code, pc); + + // An error occurred. Our last chance to recover is an exception + // handler a kernel function may have set. + error: + + if (_recover_jmpbuf) + longjmp (*_recover_jmpbuf, 1); + + return 0; +} diff --git a/kernel/fiasco/src/kern/thread-vcpu.cpp b/kernel/fiasco/src/kern/thread-vcpu.cpp new file mode 100644 index 00000000..ac188e63 --- /dev/null +++ b/kernel/fiasco/src/kern/thread-vcpu.cpp @@ -0,0 +1,54 @@ +IMPLEMENTATION: + +#include "logdefs.h" +#include "task.h" +#include "vcpu.h" + +PUBLIC inline NEEDS["task.h"] +void +Thread::vcpu_set_user_space(Task *t) +{ + assert_kdb (current() == this); + if (t) + t->inc_ref(); + + Task *old = static_cast(_space.vcpu_user()); + _space.vcpu_user(t); + + if (old) + { + if (!old->dec_ref()) + { + rcu_wait(); + delete old; + } + } +} + +PUBLIC inline NEEDS["logdefs.h", "vcpu.h"] +bool +Thread::vcpu_pagefault(Address pfa, Mword err, Mword ip) +{ + (void)ip; + Vcpu_state *vcpu = vcpu_state().access(); + if (vcpu_pagefaults_enabled(vcpu)) + { + spill_user_state(); + vcpu_enter_kernel_mode(vcpu); + LOG_TRACE("VCPU events", "vcpu", this, __context_vcpu_log_fmt, + Vcpu_log *l = tbe->payload(); + l->type = 3; + l->state = vcpu->_saved_state; + l->ip = ip; + l->sp = pfa; + l->space = vcpu_user_space() ? static_cast(vcpu_user_space())->dbg_id() : ~0; + ); + vcpu->_ts.set_pagefault(pfa, err); + vcpu_save_state_and_upcall(); + return true; + } + + return false; +} + + diff --git a/kernel/fiasco/src/kern/thread.cpp b/kernel/fiasco/src/kern/thread.cpp new file mode 100644 index 00000000..9f1d0a45 --- /dev/null +++ b/kernel/fiasco/src/kern/thread.cpp @@ -0,0 +1,1210 @@ +INTERFACE: + +#include "l4_types.h" +#include "config.h" +#include "continuation.h" +#include "helping_lock.h" +#include "kobject.h" +#include "mem_layout.h" +#include "member_offs.h" +#include "receiver.h" +#include "ref_obj.h" +#include "sender.h" +#include "spin_lock.h" +#include "thread_lock.h" + +class Return_frame; +class Syscall_frame; +class Task; +class Thread; +class Vcpu_state; +class Irq_base; + +typedef Context_ptr_base Thread_ptr; + + +/** A thread. This class is the driver class for most kernel functionality. + */ +class Thread : + public Receiver, + public Sender, + public Kobject +{ + MEMBER_OFFSET(); + FIASCO_DECLARE_KOBJ(); + + friend class Jdb; + friend class Jdb_bt; + friend class Jdb_tcb; + friend class Jdb_thread; + friend class Jdb_thread_list; + friend class Jdb_list_threads; + friend class Jdb_list_timeouts; + friend class Jdb_tbuf_show; + +public: + enum Context_mode_kernel { Kernel = 0 }; + enum Operation + { + Opcode_mask = 0xffff, + Op_control = 0, + Op_ex_regs = 1, + Op_switch = 2, + Op_stats = 3, + Op_vcpu_resume = 4, + Op_register_del_irq = 5, + Op_modify_senders = 6, + Op_vcpu_control= 7, + Op_gdt_x86 = 0x10, + Op_set_fs_amd64 = 0x12, + }; + + enum Control_flags + { + Ctl_set_pager = 0x0010000, + Ctl_bind_task = 0x0200000, + Ctl_alien_thread = 0x0400000, + Ctl_ux_native = 0x0800000, + Ctl_set_exc_handler = 0x1000000, + }; + + enum Ex_regs_flags + { + Exr_cancel = 0x10000, + Exr_trigger_exception = 0x20000, + }; + + enum Vcpu_ctl_flags + { + Vcpu_ctl_extendet_vcpu = 0x10000, + }; + + + class Dbg_stack + { + public: + enum { Stack_size = Config::PAGE_SIZE }; + void *stack_top; + Dbg_stack(); + }; + + static Per_cpu dbg_stack; + +public: + typedef void (Utcb_copy_func)(Thread *sender, Thread *receiver); + + /** + * Constructor. + * + * @param task the task the thread should reside in. + * @param id user-visible thread ID of the sender. + * @param init_prio initial priority. + * @param mcp maximum controlled priority. + * + * @post state() != Thread_invalid. + */ + Thread(); + + int handle_page_fault (Address pfa, Mword error, Mword pc, + Return_frame *regs); + +private: + struct Migration_helper_info + { + Migration_info inf; + Thread *victim; + }; + + Thread(const Thread&); ///< Default copy constructor is undefined + void *operator new(size_t); ///< Default new operator undefined + + bool handle_sigma0_page_fault (Address pfa); + + /** + * Return to user. + * + * This function is the default routine run if a newly + * initialized context is being switch_exec()'ed. + */ + static void user_invoke(); + +public: + static bool pagein_tcb_request(Return_frame *regs); + + inline Mword user_ip() const; + inline void user_ip(Mword); + + inline Mword user_sp() const; + inline void user_sp(Mword); + + inline Mword user_flags() const; + + /** nesting level in debugger (always critical) if >1 */ + static Per_cpu nested_trap_recover; + static void handle_remote_requests_irq() asm ("handle_remote_cpu_requests"); + static void handle_global_remote_requests_irq() asm ("ipi_remote_call"); + +protected: + explicit Thread(Context_mode_kernel); + + // Another critical TCB cache line: + Thread_lock _thread_lock; + + // More ipc state + Thread_ptr _pager; + Thread_ptr _exc_handler; + +protected: + Ram_quota *_quota; + Irq_base *_del_observer; + + // debugging stuff + unsigned _magic; + static const unsigned magic = 0xf001c001; +}; + + +IMPLEMENTATION: + +#include +#include // panic() +#include +#include "atomic.h" +#include "entry_frame.h" +#include "fpu_alloc.h" +#include "globals.h" +#include "irq_chip.h" +#include "kdb_ke.h" +#include "kernel_task.h" +#include "kmem_alloc.h" +#include "logdefs.h" +#include "map_util.h" +#include "ram_quota.h" +#include "sched_context.h" +#include "space.h" +#include "std_macros.h" +#include "task.h" +#include "thread_state.h" +#include "timeout.h" + +FIASCO_DEFINE_KOBJ(Thread); + +DEFINE_PER_CPU Per_cpu Thread::nested_trap_recover; + + +IMPLEMENT +Thread::Dbg_stack::Dbg_stack() +{ + stack_top = Kmem_alloc::allocator()->unaligned_alloc(Stack_size); + if (stack_top) + stack_top = (char *)stack_top + Stack_size; + //printf("JDB STACK start= %p - %p\n", (char *)stack_top - Stack_size, (char *)stack_top); +} + + +PUBLIC inline NEEDS[Thread::thread_lock] +void +Thread::kill_lock() +{ thread_lock()->lock(); } + + +PUBLIC inline +void * +Thread::operator new(size_t, Ram_quota *q) throw () +{ + void *t = Kmem_alloc::allocator()->q_unaligned_alloc(q, Thread::Size); + if (t) + { + memset(t, 0, sizeof(Thread)); + reinterpret_cast(t)->_quota = q; + } + return t; +} + +PUBLIC +bool +Thread::bind(Task *t, User::Ptr utcb) +{ + // _utcb == 0 for all kernel threads + Space::Ku_mem const *u = t->find_ku_mem(utcb, sizeof(Utcb)); + + // kernel thread? + if (EXPECT_FALSE(utcb && !u)) + return false; + + Lock_guard guard(_space.lock()); + if (_space.space() != Kernel_task::kernel_task()) + return false; + + _space.space(t); + t->inc_ref(); + + if (u) + { + _utcb.set(utcb, u->kern_addr(utcb)); + arch_setup_utcb_ptr(); + } + + return true; +} + + +PUBLIC inline NEEDS["kdb_ke.h", "kernel_task.h", "cpu_lock.h", "space.h"] +bool +Thread::unbind() +{ + Task *old; + + { + Lock_guard guard(_space.lock()); + + if (_space.space() == Kernel_task::kernel_task()) + return true; + + old = static_cast(_space.space()); + _space.space(Kernel_task::kernel_task()); + + // switch to a safe page table + if (Mem_space::current_mem_space(current_cpu()) == old) + Kernel_task::kernel_task()->switchin_context(old); + + if (old->dec_ref()) + old = 0; + } + + if (old) + { + current()->rcu_wait(); + delete old; + } + + return true; +} + +/** Cut-down version of Thread constructor; only for kernel threads + Do only what's necessary to get a kernel thread started -- + skip all fancy stuff, no locking is necessary. + @param task the address space + @param id user-visible thread ID of the sender + */ +IMPLEMENT inline +Thread::Thread(Context_mode_kernel) + : Receiver(), Sender(), _del_observer(0), _magic(magic) +{ + *reinterpret_cast(--_kernel_sp) = user_invoke; + + inc_ref(); + _space.space(Kernel_task::kernel_task()); + + if (Config::Stack_depth) + std::memset((char*)this + sizeof(Thread), '5', + Thread::Size-sizeof(Thread)-64); +} + + +/** Destructor. Reestablish the Context constructor's precondition. + @pre current() == thread_lock()->lock_owner() + && state() == Thread_dead + @pre lock_cnt() == 0 + @post (_kernel_sp == 0) && (* (stack end) == 0) && !exists() + */ +PUBLIC virtual +Thread::~Thread() // To be called in locked state. +{ + + unsigned long *init_sp = reinterpret_cast + (reinterpret_cast(this) + Size - sizeof(Entry_frame)); + + + _kernel_sp = 0; + *--init_sp = 0; + Fpu_alloc::free_state(fpu_state()); + _state = Thread_invalid; +} + + +// IPC-gate deletion stuff ------------------------------------ + +/** + * Fake IRQ Chip class for IPC-gate-delete notifications. + * This chip uses the IRQ number as thread pointer and implements + * the bind and unbind functionality. + */ +class Del_irq_chip : public Irq_chip_soft +{ +public: + static Del_irq_chip chip; +}; + +Del_irq_chip Del_irq_chip::chip; + +PUBLIC static inline +Thread *Del_irq_chip::thread(Mword pin) +{ return (Thread*)pin; } + +PUBLIC static inline +Mword Del_irq_chip::pin(Thread *t) +{ return (Mword)t; } + +PUBLIC inline +void +Del_irq_chip::unbind(Irq_base *irq) +{ thread(irq->pin())->remove_delete_irq(); } + + +PUBLIC inline NEEDS["irq_chip.h"] +void +Thread::ipc_gate_deleted(Mword id) +{ + (void) id; + Lock_guard g(&cpu_lock); + if (_del_observer) + _del_observer->hit(0); +} + +PUBLIC +void +Thread::register_delete_irq(Irq_base *irq) +{ + irq->unbind(); + Del_irq_chip::chip.bind(irq, (Mword)this); + _del_observer = irq; +} + +PUBLIC +void +Thread::remove_delete_irq() +{ + if (!_del_observer) + return; + + Irq_base *tmp = _del_observer; + _del_observer = 0; + tmp->unbind(); +} + +// end of: IPC-gate deletion stuff ------------------------------- + + +/** Currently executing thread. + @return currently executing thread. + */ +inline +Thread* +current_thread() +{ return nonull_static_cast(current()); } + +PUBLIC inline +bool +Thread::exception_triggered() const +{ return _exc_cont.valid(); } + +PUBLIC inline +bool +Thread::continuation_test_and_restore() +{ + bool v = _exc_cont.valid(); + if (v) + _exc_cont.restore(regs()); + return v; +} + +// +// state requests/manipulation +// + + +/** Thread lock. + Overwrite Context's version of thread_lock() with a semantically + equivalent, but more efficient version. + @return lock used to synchronize accesses to the thread. + */ +PUBLIC inline +Thread_lock * +Thread::thread_lock() +{ return &_thread_lock; } + + +PUBLIC inline NEEDS ["config.h", "timeout.h"] +void +Thread::handle_timer_interrupt() +{ + unsigned _cpu = cpu(true); + // XXX: This assumes periodic timers (i.e. bogus in one-shot mode) + if (!Config::Fine_grained_cputime) + consume_time(Config::Scheduler_granularity); + + bool resched = Rcu::do_pending_work(_cpu); + + // Check if we need to reschedule due to timeouts or wakeups + if ((Timeout_q::timeout_queue.cpu(_cpu).do_timeouts() || resched) + && !schedule_in_progress()) + { + schedule(); + assert (timeslice_timeout.cpu(cpu(true))->is_set()); // Coma check + } +} + + +PUBLIC +void +Thread::halt() +{ + // Cancel must be cleared on all kernel entry paths. See slowtraps for + // why we delay doing it until here. + state_del(Thread_cancel); + + // we haven't been re-initialized (cancel was not set) -- so sleep + if (state_change_safely(~Thread_ready, Thread_cancel | Thread_dead)) + while (! (state() & Thread_ready)) + schedule(); +} + +PUBLIC static +void +Thread::halt_current() +{ + for (;;) + { + current_thread()->halt(); + kdb_ke("Thread not halted"); + } +} + +PRIVATE static inline +void +Thread::user_invoke_generic() +{ + Context *const c = current(); + assert_kdb (c->state() & Thread_ready_mask); + + if (c->handle_drq() && !c->schedule_in_progress()) + c->schedule(); + + // release CPU lock explicitly, because + // * the context that switched to us holds the CPU lock + // * we run on a newly-created stack without a CPU lock guard + cpu_lock.clear(); +} + + +PRIVATE static void +Thread::leave_and_kill_myself() +{ + current_thread()->do_kill(); +#ifdef CONFIG_JDB + WARN("dead thread scheduled: %lx\n", current_thread()->dbg_id()); +#endif + kdb_ke("DEAD SCHED"); +} + +PUBLIC static +unsigned +Thread::handle_kill_helper(Drq *src, Context *, void *) +{ + delete nonull_static_cast(src->context()); + return Drq::No_answer | Drq::Need_resched; +} + + +PRIVATE +bool +Thread::do_kill() +{ + Lock_guard guard(thread_lock()); + + if (state() == Thread_invalid) + return false; + + // + // Kill this thread + // + + // But first prevent it from being woken up by asynchronous events + + { + Lock_guard guard(&cpu_lock); + + // if IPC timeout active, reset it + if (_timeout) + _timeout->reset(); + + // Switch to time-sharing mode + set_mode(Sched_mode(0)); + + // Switch to time-sharing scheduling context + if (sched() != sched_context()) + switch_sched(sched_context()); + + if (!current_sched() || current_sched()->context() == this) + set_current_sched(current()->sched()); + } + + // if other threads want to send me IPC messages, abort these + // operations + { + Lock_guard guard(&cpu_lock); + while (Sender *s = Sender::cast(sender_list()->first())) + { + s->sender_dequeue(sender_list()); + vcpu_update_state(); + s->ipc_receiver_aborted(); + Proc::preemption_point(); + } + } + + // if engaged in IPC operation, stop it + if (in_sender_list()) + { + while (Locked_prio_list *q = wait_queue()) + { + Lock_guardlock())> g(q->lock()); + if (wait_queue() == q) + { + sender_dequeue(q); + set_wait_queue(0); + break; + } + } + } + + Context::do_kill(); + + vcpu_update_state(); + + unbind(); + vcpu_set_user_space(0); + + cpu_lock.lock(); + + state_change_dirty(0, Thread_dead); + + // dequeue from system queues + ready_dequeue(); + + if (_del_observer) + { + _del_observer->unbind(); + _del_observer = 0; + } + + if (dec_ref()) + while (1) + { + state_del_dirty(Thread_ready_mask); + schedule(); + WARN("woken up dead thread %lx\n", dbg_id()); + kdb_ke("X"); + } + + rcu_wait(); + + state_del_dirty(Thread_ready_mask); + + ready_dequeue(); + + kernel_context_drq(handle_kill_helper, 0); + kdb_ke("Im dead"); + return true; +} + +PRIVATE static +unsigned +Thread::handle_remote_kill(Drq *, Context *self, void *) +{ + Thread *c = nonull_static_cast(self); + c->state_add_dirty(Thread_cancel | Thread_ready); + c->_exc_cont.restore(c->regs()); + c->do_trigger_exception(c->regs(), (void*)&Thread::leave_and_kill_myself); + return 0; +} + + +PROTECTED +bool +Thread::kill() +{ + Lock_guard guard(&cpu_lock); + inc_ref(); + + + if (cpu() == current_cpu()) + { + state_add_dirty(Thread_cancel | Thread_ready); + sched()->deblock(cpu()); + _exc_cont.restore(regs()); // overwrite an already triggered exception + do_trigger_exception(regs(), (void*)&Thread::leave_and_kill_myself); +// current()->switch_exec (this, Helping); + return true; + } + + drq(Thread::handle_remote_kill, 0, 0, Drq::Any_ctxt); + + return true; +} + + +PUBLIC +void +Thread::set_sched_params(unsigned prio, Unsigned64 quantum) +{ + Sched_context *sc = sched_context(); + bool const change = prio != sc->prio() + || quantum != sc->quantum(); + bool const ready_queued = in_ready_list(); + + if (!change && (ready_queued || this == current())) + return; + + ready_dequeue(); + + sc->set_prio(prio); + sc->set_quantum(quantum); + sc->replenish(); + + if (sc == current_sched()) + set_current_sched(sc); + + if (state() & Thread_ready_mask) + { + if (this != current()) + ready_enqueue(); + else + schedule(); + } +} + +PUBLIC +long +Thread::control(Thread_ptr const &pager, Thread_ptr const &exc_handler) +{ + if (pager.is_valid()) + _pager = pager; + + if (exc_handler.is_valid()) + _exc_handler = exc_handler; + + return 0; +} + +// used by UX only +PUBLIC static inline +bool +Thread::is_tcb_address(Address a) +{ + a &= ~(Thread::Size - 1); + return reinterpret_cast(a)->_magic == magic; +} + +PUBLIC static inline +void +Thread::assert_irq_entry() +{ + assert_kdb(current_thread()->schedule_in_progress() + || current_thread()->state() & (Thread_ready_mask | Thread_drq_wait | Thread_waiting | Thread_ipc_transfer)); +} + + + +// --------------------------------------------------------------------------- + +PUBLIC inline +bool +Thread::check_sys_ipc(unsigned flags, Thread **partner, Thread **sender, + bool *have_recv) const +{ + if (flags & L4_obj_ref::Ipc_recv) + { + *sender = flags & L4_obj_ref::Ipc_open_wait ? 0 : const_cast(this); + *have_recv = true; + } + + if (flags & L4_obj_ref::Ipc_send) + *partner = const_cast(this); + + // FIXME: shall be removed flags == 0 is no-op + if (!flags) + { + *sender = const_cast(this); + *partner = const_cast(this); + *have_recv = true; + } + + return *have_recv || ((flags & L4_obj_ref::Ipc_send) && *partner); +} + +PUBLIC static +unsigned +Thread::handle_migration_helper(Drq *, Context *, void *p) +{ + Migration_helper_info const *inf = (Migration_helper_info const *)p; + return inf->victim->migration_helper(&inf->inf); +} + + +PRIVATE +void +Thread::do_migration() +{ + assert_kdb(cpu_lock.test()); + assert_kdb(current_cpu() == cpu(true)); + + Migration_helper_info inf; + + { + Lock_guard + g(&_migration_rq.affinity_lock); + inf.inf = _migration_rq.inf; + _migration_rq.pending = false; + _migration_rq.in_progress = true; + } + + unsigned on_cpu = cpu(); + + if (inf.inf.cpu == ~0U) + { + state_add_dirty(Thread_suspended); + set_sched_params(0, 0); + _migration_rq.in_progress = false; + return; + } + + state_del_dirty(Thread_suspended); + + if (inf.inf.cpu == on_cpu) + { + // stay here + set_sched_params(inf.inf.prio, inf.inf.quantum); + _migration_rq.in_progress = false; + return; + } + + // spill FPU state into memory before migration + if (state() & Thread_fpu_owner) + { + if (current() != this) + Fpu::enable(); + + spill_fpu(); + Fpu::set_owner(on_cpu, 0); + Fpu::disable(); + } + + + // if we are in the middle of the scheduler, leave it now + if (schedule_in_progress() == this) + reset_schedule_in_progress(); + + inf.victim = this; + + if (current() == this && Config::Max_num_cpus > 1) + kernel_context_drq(handle_migration_helper, &inf); + else + migration_helper(&inf.inf); +} + +PUBLIC +void +Thread::initiate_migration() +{ do_migration(); } + +PUBLIC +void +Thread::finish_migration() +{ enqueue_timeout_again(); } + + +PUBLIC +void +Thread::migrate(Migration_info const &info) +{ + assert_kdb (cpu_lock.test()); + + LOG_TRACE("Thread migration", "mig", this, __thread_migration_log_fmt, + Migration_log *l = tbe->payload(); + l->state = state(); + l->src_cpu = cpu(); + l->target_cpu = info.cpu; + l->user_ip = regs()->ip(); + ); + + { + Lock_guard + g(&_migration_rq.affinity_lock); + _migration_rq.inf = info; + _migration_rq.pending = true; + } + + unsigned cpu = this->cpu(); + + if (current_cpu() == cpu) + { + do_migration(); + return; + } + + migrate_xcpu(cpu); +} + + +//--------------------------------------------------------------------------- +IMPLEMENTATION [fpu && !ux]: + +#include "fpu.h" +#include "fpu_alloc.h" +#include "fpu_state.h" + +PUBLIC inline NEEDS ["fpu.h"] +void +Thread::spill_fpu() +{ + // If we own the FPU, we should never be getting an "FPU unavailable" trap + assert_kdb (Fpu::owner(cpu()) == this); + assert_kdb (state() & Thread_fpu_owner); + assert_kdb (fpu_state()); + + // Save the FPU state of the previous FPU owner (lazy) if applicable + Fpu::save_state (fpu_state()); + state_del_dirty (Thread_fpu_owner); +} + + +/* + * Handle FPU trap for this context. Assumes disabled interrupts + */ +PUBLIC inline NEEDS [Thread::spill_fpu, "fpu_alloc.h","fpu_state.h"] +int +Thread::switchin_fpu(bool alloc_new_fpu = true) +{ + unsigned cpu = this->cpu(true); + + if (state() & Thread_vcpu_fpu_disabled) + return 0; + + // If we own the FPU, we should never be getting an "FPU unavailable" trap + assert_kdb (Fpu::owner(cpu) != this); + + // Allocate FPU state slab if we didn't already have one + if (!fpu_state()->state_buffer() + && (EXPECT_FALSE((!alloc_new_fpu + || (state() & Thread_alien)) + || !Fpu_alloc::alloc_state(_quota, fpu_state())))) + return 0; + + // Enable the FPU before accessing it, otherwise recursive trap + Fpu::enable(); + + // Save the FPU state of the previous FPU owner (lazy) if applicable + if (Fpu::owner(cpu)) + nonull_static_cast(Fpu::owner(cpu))->spill_fpu(); + + // Become FPU owner and restore own FPU state + Fpu::restore_state(fpu_state()); + + state_add_dirty(Thread_fpu_owner); + Fpu::set_owner(cpu, this); + return 1; +} + +PUBLIC inline NEEDS["fpu.h", "fpu_alloc.h"] +void +Thread::transfer_fpu(Thread *to) +{ + unsigned cpu = this->cpu(); + if (cpu != to->cpu()) + return; + + if (to->fpu_state()->state_buffer()) + Fpu_alloc::free_state(to->fpu_state()); + + to->fpu_state()->state_buffer(fpu_state()->state_buffer()); + fpu_state()->state_buffer(0); + + assert (current() == this || current() == to); + + Fpu::disable(); // it will be reanabled in switch_fpu + + if (EXPECT_FALSE(Fpu::owner(cpu) == to)) + { + assert_kdb (to->state() & Thread_fpu_owner); + + Fpu::set_owner(cpu, 0); + to->state_del_dirty (Thread_fpu_owner); + } + else if (Fpu::owner(cpu) == this) + { + assert_kdb (state() & Thread_fpu_owner); + + state_del_dirty (Thread_fpu_owner); + + to->state_add_dirty (Thread_fpu_owner); + Fpu::set_owner(cpu, to); + if (EXPECT_FALSE(current() == to)) + Fpu::enable(); + } +} + +//--------------------------------------------------------------------------- +IMPLEMENTATION [!fpu]: + +PUBLIC inline +int +Thread::switchin_fpu(bool alloc_new_fpu = true) +{ + (void)alloc_new_fpu; + return 0; +} + +PUBLIC inline +void +Thread::spill_fpu() +{} + +//--------------------------------------------------------------------------- +IMPLEMENTATION [!fpu || ux]: + +PUBLIC inline +void +Thread::transfer_fpu(Thread *) +{} + +//--------------------------------------------------------------------------- +IMPLEMENTATION [!log]: + +PUBLIC inline +unsigned Thread::sys_ipc_log(Syscall_frame *) +{ return 0; } + +PUBLIC inline +unsigned Thread::sys_ipc_trace(Syscall_frame *) +{ return 0; } + +static inline +void Thread::page_fault_log(Address, unsigned, unsigned) +{} + +PUBLIC static inline +int Thread::log_page_fault() +{ return 0; } + +PUBLIC inline +unsigned Thread::sys_fpage_unmap_log(Syscall_frame *) +{ return 0; } + + +// ---------------------------------------------------------------------------- +IMPLEMENTATION [!mp]: + + +PRIVATE inline +unsigned +Thread::migration_helper(Migration_info const *inf) +{ + unsigned cpu = inf->cpu; + // LOG_MSG_3VAL(this, "MGi ", Mword(current()), (current_cpu() << 16) | cpu(), Context::current_sched()); + if (_timeout) + _timeout->reset(); + ready_dequeue(); + + { + // Not sure if this can ever happen + Sched_context *csc = Context::current_sched(); + if (!csc || csc->context() == this) + Context::set_current_sched(current()->sched()); + } + + Sched_context *sc = sched_context(); + sc->set_prio(inf->prio); + sc->set_quantum(inf->quantum); + sc->replenish(); + set_sched(sc); + + if (drq_pending()) + state_add_dirty(Thread_drq_ready); + + set_cpu_of(this, cpu); + return Drq::No_answer | Drq::Need_resched; +} + +PRIVATE inline +void +Thread::migrate_xcpu(unsigned cpu) +{ + (void)cpu; + assert_kdb (false); +} + + +//---------------------------------------------------------------------------- +INTERFACE [debug]: + +EXTENSION class Thread +{ +protected: + struct Migration_log + { + Mword state; + Address user_ip; + unsigned src_cpu; + unsigned target_cpu; + + static unsigned fmt(Tb_entry *, int, char *) + asm ("__thread_migration_log_fmt"); + }; +}; + + +// ---------------------------------------------------------------------------- +IMPLEMENTATION [mp]: + +#include "ipi.h" + +IMPLEMENT +void +Thread::handle_remote_requests_irq() +{ + assert_kdb (cpu_lock.test()); + // printf("CPU[%2u]: > RQ IPI (current=%p)\n", current_cpu(), current()); + Context *const c = current(); + Ipi::eoi(Ipi::Request, c->cpu()); + //LOG_MSG_3VAL(c, "ipi", c->cpu(), (Mword)c, c->drq_pending()); + Context *migration_q = 0; + bool resched = _pending_rqq.cpu(c->cpu()).handle_requests(&migration_q); + + resched |= Rcu::do_pending_work(c->cpu()); + + if (migration_q) + static_cast(migration_q)->do_migration(); + + if ((resched || c->handle_drq()) && !c->schedule_in_progress()) + { + //LOG_MSG_3VAL(c, "ipis", 0, 0, 0); + // printf("CPU[%2u]: RQ IPI sched %p\n", current_cpu(), current()); + c->schedule(); + } + // printf("CPU[%2u]: < RQ IPI (current=%p)\n", current_cpu(), current()); +} + +IMPLEMENT +void +Thread::handle_global_remote_requests_irq() +{ + assert_kdb (cpu_lock.test()); + // printf("CPU[%2u]: > RQ IPI (current=%p)\n", current_cpu(), current()); + Ipi::eoi(Ipi::Global_request, current_cpu()); + Context::handle_global_requests(); +} + +PRIVATE inline +unsigned +Thread::migration_helper(Migration_info const *inf) +{ + // LOG_MSG_3VAL(this, "MGi ", Mword(current()), (current_cpu() << 16) | cpu(), 0); + assert_kdb (cpu() == current_cpu()); + assert_kdb (current() != this); + assert_kdb (cpu_lock.test()); + + if (_timeout) + _timeout->reset(); + ready_dequeue(); + + { + // Not sure if this can ever happen + Sched_context *csc = Context::current_sched(); + if (!csc || csc->context() == this) + Context::set_current_sched(current()->sched()); + } + + unsigned cpu = inf->cpu; + + { + Queue &q = _pending_rqq.cpu(current_cpu()); + // The queue lock of the current CPU protects the cpu number in + // the thread + Lock_guard g(q.q_lock()); + + // potentailly dequeue from our local queue + if (_pending_rq.queued()) + check_kdb (q.dequeue(&_pending_rq, Queue_item::Ok)); + + Sched_context *sc = sched_context(); + sc->set_prio(inf->prio); + sc->set_quantum(inf->quantum); + sc->replenish(); + set_sched(sc); + + if (drq_pending()) + state_add_dirty(Thread_drq_ready); + + Mem::mp_wmb(); + + assert_kdb (!in_ready_list()); + + set_cpu_of(this, cpu); + // now we are migrated away fom current_cpu + } + + bool ipi = true; + + { + Queue &q = _pending_rqq.cpu(cpu); + Lock_guard g(q.q_lock()); + + // migrated meanwhile + if (this->cpu() != cpu || _pending_rq.queued()) + return Drq::No_answer | Drq::Need_resched; + + if (q.first()) + ipi = false; + + q.enqueue(&_pending_rq); + } + + if (ipi) + { + //LOG_MSG_3VAL(this, "sipi", current_cpu(), cpu(), (Mword)current()); + Ipi::send(Ipi::Request, current_cpu(), cpu); + } + + return Drq::No_answer | Drq::Need_resched; +} + +PRIVATE inline +void +Thread::migrate_xcpu(unsigned cpu) +{ + bool ipi = true; + + { + Queue &q = Context::_pending_rqq.cpu(cpu); + Lock_guard g(q.q_lock()); + + // already migrated + if (cpu != this->cpu()) + return; + + if (q.first()) + ipi = false; + + if (!_pending_rq.queued()) + q.enqueue(&_pending_rq); + else + ipi = false; + } + + if (ipi) + Ipi::send(Ipi::Request, current_cpu(), cpu); +} + +//---------------------------------------------------------------------------- +IMPLEMENTATION [debug]: + +IMPLEMENT +unsigned +Thread::Migration_log::fmt(Tb_entry *e, int maxlen, char *buf) +{ + Migration_log *l = e->payload(); + return snprintf(buf, maxlen, "migrate from %u to %u (state=%lx user ip=%lx)", + l->src_cpu, l->target_cpu, l->state, l->user_ip); +} + diff --git a/kernel/fiasco/src/kern/thread_lock.cpp b/kernel/fiasco/src/kern/thread_lock.cpp new file mode 100644 index 00000000..a1f80e52 --- /dev/null +++ b/kernel/fiasco/src/kern/thread_lock.cpp @@ -0,0 +1,284 @@ +INTERFACE: + +#include "member_offs.h" +#include "context.h" // Switch_hint +#include "panic.h" +#include "switch_lock.h" + +enum Switch_hint +{ + SWITCH_ACTIVATE_HIGHER = 0, // Activate thread with higher priority + SWITCH_ACTIVATE_LOCKEE, // Activate thread that was locked +}; + + +/** Thread lock. + This lock uses the basic priority-inheritance mechanism (Switch_lock) + and extends it in two ways: First, it has a hinting mechanism that + allows a locker to specify whether the clear() operation should + switch to the thread that was locked. Second, it maintains the current + locker for Context; this locker automatically gets CPU time allocated + to the locked thread (Context's ``donatee''); + Context::switch_exec() uses that hint. + To make clear, which stuff in the TCB the lock not protects: + -the thread state + -queues + -the raw kernelstack + The rest is protected with this lock, this includes the + kernelstackpointer (kernel_sp). + */ +class Thread_lock : private Switch_lock +{ + MEMBER_OFFSET(); + +private: + typedef Switch_lock Lock; + +public: + using Lock::Invalid; + using Lock::Locked; + using Lock::Not_locked; + + using Lock::Lock_context; + + using Lock::test; + using Lock::lock_owner; + using Lock::Status; + + /* + * Can use the Switch_lock version, because we assume the context + * is invalid during switch_dirty and we do not need to consider it + * for scheduling any more. + */ + using Lock::clear_no_switch_dirty; + using Lock::switch_dirty; + +private: + Switch_hint _switch_hint; +}; + +IMPLEMENTATION: + +#include "globals.h" +#include "lock_guard.h" +#include "cpu_lock.h" +#include "thread_state.h" +#include "cpu.h" + +/** Context this thread lock belongs to. + @return context locked by this thread lock + */ +PRIVATE inline +Context * +Thread_lock::context() const +{ + // We could have saved our context in our constructor, but computing + // it this way is easier and saves space. We can do this as we know + // that thread_locks are always embedded in their corresponding + // context. + return context_of (this); +} + +/** Set switch hint. + @param hint a hint to the clear() function + */ +PUBLIC inline +void +Thread_lock::set_switch_hint (Switch_hint const hint) +{ + _switch_hint = hint; +} + +/** Lock a context. + @return true if we owned the lock already. false otherwise. + */ +PUBLIC +Thread_lock::Status +Thread_lock::test_and_set() +{ + Lock_guard guard (&cpu_lock); + return test_and_set_dirty(); +} + +/** Lock a context. + @return true if we owned the lock already. false otherwise. + @pre caller holds cpu lock + */ +PRIVATE inline NEEDS["switch_lock.h","cpu_lock.h","globals.h", Thread_lock::context] +Thread_lock::Status +Thread_lock::test_and_set_dirty() +{ + assert(cpu_lock.test()); + + switch (Status r = Lock::test_and_set ()) + { + case Invalid: + case Locked: + return r; + case Not_locked: + break; + } + + context()->set_donatee (current()); // current get time of context + + set_switch_hint (SWITCH_ACTIVATE_HIGHER); + + return Not_locked; +} + + +/** Lock a thread. + If the lock is occupied, enqueue in list of helpers and lend CPU + to current lock owner until we are the lock owner. + */ +PUBLIC inline NEEDS["globals.h"] +Thread_lock::Status +Thread_lock::lock() +{ + return test_and_set(); +} + +/** Lock a thread. + If the lock is occupied, enqueue in list of helpers and lend CPU + to current lock owner until we are the lock owner. + @pre caller holds cpu lock + */ +PUBLIC inline NEEDS[Thread_lock::test_and_set_dirty, "globals.h"] +Thread_lock::Status +Thread_lock::lock_dirty() +{ + // removed assertion, because we do lazy locking + return test_and_set_dirty(); +} + +/** Free the lock. + First return the CPU to helper or next lock owner, whoever has the higher + priority, given that thread's priority is higher that ours. + Finally, switch to locked thread if that thread has a higher priority, + and/or the switch hint says we should. + */ +PUBLIC +void +Thread_lock::clear() +{ + Switch_hint hint = _switch_hint; // Save hint before unlocking + + Lock_guard guard (&cpu_lock); + + // Passing on the thread lock implies both passing _switch_lock + // and setting context()'s donatee to the new owner. This must be + // accomplished atomically. There are two cases to consider: + // 1. _switch_lock.clear() does not switch to the new owner. + // 2. _switch_lock.clear() switches to the new owner. + // To cope with both cases, we set the owner both here (*) and in + // Thread_lock::test_and_set(). The assignment that is executed + // first is always atomic with _switch_lock.clear(). The + // assignment that comes second is redundant. + // Note: Our assignment (*) might occur at a time when there is no + // lock owner or even when the context() has been killed. + // Fortunately, it works anyway because contexts live in + // type-stable memory. + Lock::clear(); + context()->set_donatee(lock_owner()); + + // We had locked ourselves, remain current + if (context() == current()) + return; + + // Unlocked thread not ready, remain current + if (!(context()->state() & Thread_ready)) + return; + + // Switch to lockee's execution context if the switch hint says so + if (hint == SWITCH_ACTIVATE_LOCKEE) + { + check(!current()->switch_exec_locked (context(), Context::Not_Helping)); + return; + } + + // Switch to lockee's execution context and timeslice if its priority + // is higher than the current priority + if (context()->sched()->deblock(current_cpu(), current()->sched(), true)) + current()->switch_to_locked(context()); +} + +PUBLIC inline +void +Thread_lock::set(Status s) +{ + if (s == Not_locked) + clear(); +} + +/** Free the lock. + First return the CPU to helper or next lock owner, whoever has the higher + priority, given that thread's priority is higher that ours. + Finally, switch to locked thread if that thread has a higher priority, + and/or the switch hint says we should. + Assumes caller hold cpu lock + */ +PUBLIC +void +Thread_lock::clear_dirty() +{ + assert(cpu_lock.test()); + + Switch_hint hint = _switch_hint; + + if(test()) + { + Lock::clear_dirty(); + context()->set_donatee(lock_owner()); + } + else + { + // assert(!context()->donatee()); + } + + assert(cpu_lock.test()); + + // We had locked ourselves, remain current + if (context() == current()) + return; + + // Unlocked thread not ready, remain current + if (!(context()->state() & Thread_ready)) + return; + + // Switch to lockee's execution context if the switch hint says so + if (hint == SWITCH_ACTIVATE_LOCKEE) + { + check(!current()->switch_exec_locked (context(), Context::Not_Helping)); + return; + } + + // Switch to lockee's execution context and timeslice if its priority + // is higher than the current priority + if (context()->sched()->deblock(current_cpu(), current()->sched(), true)) + current()->switch_to_locked(context()); +} + +/** Free the lock. + First return the CPU to helper or next lock owner, whoever has the higher + priority, given that thread's priority is higher that ours. + Finally, switch to locked thread if that thread has a higher priority, + and/or the switch hint says we should. + Assumes caller hold cpu lock + */ +PUBLIC inline +void +Thread_lock::clear_dirty_dont_switch() +{ + assert(cpu_lock.test()); + + if(EXPECT_TRUE(!test())) + return; + + Lock::clear_dirty(); + context()->set_donatee(lock_owner()); + + assert(cpu_lock.test()); +} + + + diff --git a/kernel/fiasco/src/kern/thread_object.cpp b/kernel/fiasco/src/kern/thread_object.cpp new file mode 100644 index 00000000..98eef88f --- /dev/null +++ b/kernel/fiasco/src/kern/thread_object.cpp @@ -0,0 +1,688 @@ +INTERFACE: + +#include "kobject.h" +#include "thread.h" + +class Thread_object : public Thread +{ +private: + struct Remote_syscall + { + Thread *thread; + L4_msg_tag result; + }; +}; + +class Obj_cap : public L4_obj_ref +{ +}; + + +// --------------------------------------------------------------------------- +IMPLEMENTATION: + +#include "context.h" +#include "fpu.h" +#include "irq_chip.h" +#include "map_util.h" +#include "processor.h" +#include "task.h" +#include "thread_state.h" +#include "timer.h" + + + +PUBLIC inline +Obj_cap::Obj_cap(L4_obj_ref const &o) : L4_obj_ref(o) {} + +PUBLIC inline NEEDS["kobject.h"] +Kobject_iface * +Obj_cap::deref(unsigned char *rights = 0, bool dbg = false) +{ + Thread *current = current_thread(); + if (op() & L4_obj_ref::Ipc_reply) + { + if (rights) *rights = current->caller_rights(); + Thread *ca = static_cast(current->caller()); + if (!dbg) + current->set_caller(0,0); + return ca; + } + + if (EXPECT_FALSE(special())) + { + if (!self()) + return 0; + + if (rights) *rights = L4_fpage::RWX; + return current_thread(); + } + + return current->space()->lookup_local(cap(), rights); +} + +PUBLIC inline NEEDS["kobject.h"] +bool +Obj_cap::revalidate(Kobject_iface *o) +{ + return deref() == o; +} + +PUBLIC +Thread_object::Thread_object() : Thread() {} + +PUBLIC +Thread_object::Thread_object(Context_mode_kernel k) : Thread(k) {} + +PUBLIC virtual +bool +Thread_object::put() +{ return dec_ref() == 0; } + + + +PUBLIC +void +Thread_object::operator delete(void *_t) +{ + Thread_object * const t = nonull_static_cast(_t); + Ram_quota * const q = t->_quota; + Kmem_alloc::allocator()->q_unaligned_free(q, Thread::Size, t); + + LOG_TRACE("Kobject delete", "del", current(), __fmt_kobj_destroy, + Log_destroy *l = tbe->payload(); + l->id = t->dbg_id(); + l->obj = t; + l->type = "Thread"; + l->ram = q->current()); +} + + +PUBLIC +void +Thread_object::destroy(Kobject ***rl) +{ + Kobject::destroy(rl); + check_kdb(kill()); + assert_kdb(_magic == magic); +} + +PUBLIC +void +Thread_object::invoke(L4_obj_ref /*self*/, Mword rights, Syscall_frame *f, Utcb *utcb) +{ + register L4_obj_ref::Operation op = f->ref().op(); + if (((op != 0) && !(op & L4_obj_ref::Ipc_send)) + || (op & L4_obj_ref::Ipc_reply) + || f->tag().proto() != L4_msg_tag::Label_thread) + { + /* we do IPC */ + Thread *ct = current_thread(); + Thread *sender = 0; + Thread *partner = 0; + bool have_rcv = false; + + if (EXPECT_FALSE(!check_sys_ipc(op, &partner, &sender, &have_rcv))) + { + utcb->error = L4_error::Not_existent; + return; + } + + ct->do_ipc(f->tag(), partner, partner, have_rcv, sender, + f->timeout(), f, rights); + return; + } + + switch (utcb->values[0] & Opcode_mask) + { + case Op_control: + f->tag(sys_control(rights, f->tag(), utcb)); + return; + case Op_ex_regs: + f->tag(sys_ex_regs(f->tag(), utcb)); + return; + case Op_switch: + f->tag(sys_thread_switch(f->tag(), utcb)); + return; + case Op_stats: + f->tag(sys_thread_stats(f->tag(), utcb)); + return; + case Op_vcpu_resume: + f->tag(sys_vcpu_resume(f->tag(), utcb)); + return; + case Op_register_del_irq: + f->tag(sys_register_delete_irq(f->tag(), utcb, utcb)); + return; + case Op_modify_senders: + f->tag(sys_modify_senders(f->tag(), utcb, utcb)); + return; + case Op_vcpu_control: + f->tag(sys_vcpu_control(rights, f->tag(), utcb)); + return; + default: + f->tag(invoke_arch(f->tag(), utcb)); + return; + } +} + + +PRIVATE inline +L4_msg_tag +Thread_object::sys_vcpu_resume(L4_msg_tag const &tag, Utcb *utcb) +{ + if (this != current() || !(state() & Thread_vcpu_enabled)) + return commit_result(-L4_err::EInval); + + Space *s = space(); + Vcpu_state *vcpu = vcpu_state().access(true); + + L4_obj_ref user_task = vcpu->user_task; + if (user_task.valid()) + { + unsigned char task_rights = 0; + Task *task = Kobject::dcast(s->lookup_local(user_task.cap(), + &task_rights)); + + if (EXPECT_FALSE(task && !(task_rights & L4_fpage::W))) + return commit_result(-L4_err::EPerm); + + if (task != vcpu_user_space()) + vcpu_set_user_space(task); + + vcpu->user_task = L4_obj_ref(); + } + else if (user_task.op() == L4_obj_ref::Ipc_reply) + vcpu_set_user_space(0); + + L4_snd_item_iter snd_items(utcb, tag.words()); + int items = tag.items(); + for (; items && snd_items.more(); --items) + { + if (EXPECT_FALSE(!snd_items.next())) + break; + + // XXX: need to take existance lock for map + cpu_lock.clear(); + + L4_snd_item_iter::Item const *const item = snd_items.get(); + L4_fpage sfp(item->d); + + Reap_list rl; + L4_error err = fpage_map(space(), sfp, + vcpu_user_space(), L4_fpage::all_spaces(), + item->b, &rl); + rl.del(); + + cpu_lock.lock(); + + if (EXPECT_FALSE(!err.ok())) + return commit_error(utcb, err); + } + + if ((vcpu->_saved_state & Vcpu_state::F_irqs) + && (vcpu->sticky_flags & Vcpu_state::Sf_irq_pending)) + { + assert_kdb(cpu_lock.test()); + do_ipc(L4_msg_tag(), 0, 0, true, 0, + L4_timeout_pair(L4_timeout::Zero, L4_timeout::Zero), + &vcpu->_ipc_regs, 3); + + vcpu = vcpu_state().access(true); + + if (EXPECT_TRUE(!vcpu->_ipc_regs.tag().has_error() + || this->utcb().access(true)->error.error() == L4_error::R_timeout)) + { + vcpu->_ts.set_ipc_upcall(); + + Address sp; + + // tried to resume to user mode, so an IRQ enters from user mode + if (vcpu->_saved_state & Vcpu_state::F_user_mode) + sp = vcpu->_entry_sp; + else + sp = vcpu->_ts.sp(); + + LOG_TRACE("VCPU events", "vcpu", this, __context_vcpu_log_fmt, + Vcpu_log *l = tbe->payload(); + l->type = 4; + l->state = vcpu->state; + l->ip = vcpu->_entry_ip; + l->sp = sp; + l->space = static_cast(_space.vcpu_aware())->dbg_id(); + ); + + fast_return_to_user(vcpu->_entry_ip, sp, vcpu_state().usr().get()); + } + } + + vcpu->state = vcpu->_saved_state; + Task *target_space = nonull_static_cast(space()); + bool user_mode = false; + + if (vcpu->state & Vcpu_state::F_user_mode) + { + if (!vcpu_user_space()) + return commit_result(-L4_err::EInval); + + user_mode = true; + + if (!(vcpu->state & Vcpu_state::F_fpu_enabled)) + { + state_add_dirty(Thread_vcpu_fpu_disabled); + Fpu::disable(); + } + else + state_del_dirty(Thread_vcpu_fpu_disabled); + + target_space = static_cast(vcpu_user_space()); + } + + LOG_TRACE("VCPU events", "vcpu", this, __context_vcpu_log_fmt, + Vcpu_log *l = tbe->payload(); + l->type = 0; + l->state = vcpu->state; + l->ip = vcpu->_ts.ip(); + l->sp = vcpu->_ts.sp(); + l->space = target_space->dbg_id(); + ); + + return commit_result(target_space->resume_vcpu(this, vcpu, user_mode)); +} + +PRIVATE inline NOEXPORT NEEDS["processor.h"] +L4_msg_tag +Thread_object::sys_modify_senders(L4_msg_tag tag, Utcb const *in, Utcb * /*out*/) +{ + if (sender_list()->cursor()) + return Kobject_iface::commit_result(-L4_err::EBusy); + + if (0) + printf("MODIFY ID (%08lx:%08lx->%08lx:%08lx\n", + in->values[1], in->values[2], + in->values[3], in->values[4]); + + + int elems = tag.words(); + + if (elems < 5) + return Kobject_iface::commit_result(0); + + --elems; + + elems = elems / 4; + + ::Prio_list_elem *c = sender_list()->first(); + while (c) + { + // this is kind of arbitrary + for (int cnt = 50; c && cnt > 0; --cnt) + { + Sender *s = Sender::cast(c); + s->modify_label(&in->values[1], elems); + c = sender_list()->next(c); + } + + if (!c) + return Kobject_iface::commit_result(0); + + sender_list()->cursor(c); + Proc::preemption_point(); + c = sender_list()->cursor(); + } + return Kobject_iface::commit_result(0); +} + +PRIVATE inline NOEXPORT +L4_msg_tag +Thread_object::sys_register_delete_irq(L4_msg_tag tag, Utcb const *in, Utcb * /*out*/) +{ + L4_snd_item_iter snd_items(in, tag.words()); + + if (!tag.items() || !snd_items.next()) + return Kobject_iface::commit_result(-L4_err::EInval); + + L4_fpage bind_irq(snd_items.get()->d); + if (EXPECT_FALSE(!bind_irq.is_objpage())) + return Kobject_iface::commit_error(in, L4_error::Overflow); + + register Context *const c_thread = ::current(); + register Space *const c_space = c_thread->space(); + unsigned char irq_rights = 0; + Irq_base *irq + = Irq_base::dcast(c_space->lookup_local(bind_irq.obj_index(), &irq_rights)); + + if (!irq) + return Kobject_iface::commit_result(-L4_err::EInval); + + if (EXPECT_FALSE(!(irq_rights & L4_fpage::X))) + return Kobject_iface::commit_result(-L4_err::EPerm); + + register_delete_irq(irq); + return Kobject_iface::commit_result(0); +} + + +PRIVATE inline NOEXPORT +L4_msg_tag +Thread_object::sys_control(unsigned char rights, L4_msg_tag const &tag, Utcb *utcb) +{ + if (EXPECT_FALSE(!(rights & L4_fpage::W))) + return commit_result(-L4_err::EPerm); + + if (EXPECT_FALSE(tag.words() < 6)) + return commit_result(-L4_err::EInval); + + Context *curr = current(); + Space *s = curr->space(); + L4_snd_item_iter snd_items(utcb, tag.words()); + Task *task = 0; + User::Ptr utcb_addr(0); + + Mword flags = utcb->values[0]; + + Mword _old_pager = _pager.raw() << L4_obj_ref::Cap_shift; + Mword _old_exc_handler = _exc_handler.raw() << L4_obj_ref::Cap_shift; + + Thread_ptr _new_pager(~0UL); + Thread_ptr _new_exc_handler(~0UL); + + if (flags & Ctl_set_pager) + _new_pager = Thread_ptr(utcb->values[1] >> L4_obj_ref::Cap_shift); + + if (flags & Ctl_set_exc_handler) + _new_exc_handler = Thread_ptr(utcb->values[2] >> L4_obj_ref::Cap_shift); + + if (flags & Ctl_bind_task) + { + if (EXPECT_FALSE(!tag.items() || !snd_items.next())) + return commit_result(-L4_err::EInval); + + L4_fpage bind_task(snd_items.get()->d); + + if (EXPECT_FALSE(!bind_task.is_objpage())) + return commit_result(-L4_err::EInval); + + unsigned char task_rights = 0; + task = Kobject::dcast(s->lookup_local(bind_task.obj_index(), &task_rights)); + + if (EXPECT_FALSE(!(task_rights & L4_fpage::W))) + return commit_result(-L4_err::EPerm); + + if (!task) + return commit_result(-L4_err::EInval); + + utcb_addr = User::Ptr((Utcb*)utcb->values[5]); + + if (EXPECT_FALSE(!bind(task, utcb_addr))) + return commit_result(-L4_err::EInval); // unbind first !! + } + + Mword del_state = 0; + Mword add_state = 0; + + long res = control(_new_pager, _new_exc_handler); + + if (res < 0) + return commit_result(res); + + if ((res = sys_control_arch(utcb)) < 0) + return commit_result(res); + + // FIXME: must be done xcpu safe, may be some parts above too + if (flags & Ctl_alien_thread) + { + if (utcb->values[4] & Ctl_alien_thread) + { + add_state |= Thread_alien; + del_state |= Thread_dis_alien; + } + else + del_state |= Thread_alien; + } + + if (del_state || add_state) + drq_state_change(~del_state, add_state); + + utcb->values[1] = _old_pager; + utcb->values[2] = _old_exc_handler; + + return commit_result(0, 3); +} + + +PRIVATE inline NOEXPORT +L4_msg_tag +Thread_object::sys_vcpu_control(unsigned char, L4_msg_tag const &tag, + Utcb *utcb) +{ + if (!space()) + return commit_result(-L4_err::EInval); + + User::Ptr vcpu(0); + + if (tag.words() >= 2) + vcpu = User::Ptr((Vcpu_state*)utcb->values[1]); + + Mword del_state = 0; + Mword add_state = 0; + + if (vcpu) + { + Mword size = sizeof(Vcpu_state); + if (utcb->values[0] & 0x10000) + { + size = Config::PAGE_SIZE; + add_state |= Thread_ext_vcpu_enabled; + } + + Space::Ku_mem const *vcpu_m + = space()->find_ku_mem(vcpu, size); + + if (!vcpu_m) + return commit_result(-L4_err::EInval); + + add_state |= Thread_vcpu_enabled; + _vcpu_state.set(vcpu, vcpu_m->kern_addr(vcpu)); + } + else + return commit_result(-L4_err::EInval); + + /* hm, we do not allow to disable vCPU mode, it's one way enable + else + { + del_state |= Thread_vcpu_enabled | Thread_vcpu_user_mode + | Thread_vcpu_fpu_disabled | Thread_ext_vcpu_enabled; + } + */ + + drq_state_change(~del_state, add_state); + + return commit_result(0); +} + + +// ------------------------------------------------------------------- +// Thread::ex_regs class system calls + +PUBLIC +bool +Thread_object::ex_regs(Address ip, Address sp, + Address *o_ip = 0, Address *o_sp = 0, Mword *o_flags = 0, + Mword ops = 0) +{ + if (state(false) == Thread_invalid || !space()) + return false; + + if (current() == this) + spill_user_state(); + + if (o_sp) *o_sp = user_sp(); + if (o_ip) *o_ip = user_ip(); + if (o_flags) *o_flags = user_flags(); + + // Changing the run state is only possible when the thread is not in + // an exception. + if (!(ops & Exr_cancel) && (state() & Thread_in_exception)) + // XXX Maybe we should return false here. Previously, we actually + // did so, but we also actually didn't do any state modification. + // If you change this value, make sure the logic in + // sys_thread_ex_regs still works (in particular, + // ex_regs_cap_handler and friends should still be called). + return true; + + if (state() & Thread_dead) // resurrect thread + state_change_dirty(~Thread_dead, Thread_ready); + + else if (ops & Exr_cancel) + // cancel ongoing IPC or other activity + state_add_dirty(Thread_cancel | Thread_ready); + + if (ops & Exr_trigger_exception) + { + extern char leave_by_trigger_exception[]; + do_trigger_exception(regs(), leave_by_trigger_exception); + } + + if (ip != ~0UL) + user_ip(ip); + + if (sp != ~0UL) + user_sp (sp); + + if (current() == this) + fill_user_state(); + + return true; +} + +PUBLIC inline +L4_msg_tag +Thread_object::ex_regs(Utcb *utcb) +{ + Address ip = utcb->values[1]; + Address sp = utcb->values[2]; + Mword flags; + Mword ops = utcb->values[0]; + + LOG_TRACE("Ex-regs", "exr", current(), __fmt_thread_exregs, + Log_thread_exregs *l = tbe->payload(); + l->id = dbg_id(); + l->ip = ip; l->sp = sp; l->op = ops;); + + if (!ex_regs(ip, sp, &ip, &sp, &flags, ops)) + return commit_result(-L4_err::EInval); + + utcb->values[0] = flags; + utcb->values[1] = ip; + utcb->values[2] = sp; + + return commit_result(0, 3); +} + +PRIVATE static +unsigned +Thread_object::handle_remote_ex_regs(Drq *, Context *self, void *p) +{ + Remote_syscall *params = reinterpret_cast(p); + params->result = nonull_static_cast(self)->ex_regs(params->thread->utcb().access()); + return params->result.proto() == 0 ? Drq::Need_resched : 0; +} + +PRIVATE inline NOEXPORT +L4_msg_tag +Thread_object::sys_ex_regs(L4_msg_tag const &tag, Utcb *utcb) +{ + if (tag.words() != 3) + return commit_result(-L4_err::EInval); + + if (current() == this) + return ex_regs(utcb); + + Remote_syscall params; + params.thread = current_thread(); + + drq(handle_remote_ex_regs, ¶ms, 0, Drq::Any_ctxt); + return params.result; +} + +PRIVATE inline NOEXPORT NEEDS["timer.h"] +L4_msg_tag +Thread_object::sys_thread_switch(L4_msg_tag const &/*tag*/, Utcb *utcb) +{ + Context *curr = current(); + + if (curr == this) + return commit_result(0); + + if (current_cpu() != cpu()) + return commit_result(0); + +#ifdef FIXME + Sched_context * const cs = current_sched(); +#endif + + if (curr != this + && ((state() & (Thread_ready | Thread_suspended)) == Thread_ready)) + { + curr->switch_exec_schedule_locked (this, Not_Helping); + reinterpret_cast(utcb->values)->t = 0; // Assume timeslice was used up + return commit_result(0, Utcb::Time_val::Words); + } + +#if 0 // FIXME: provide API for multiple sched contexts + // Compute remaining quantum length of timeslice + regs->left(timeslice_timeout.cpu(cpu())->get_timeout(Timer::system_clock())); + + // Yield current global timeslice + cs->owner()->switch_sched(cs->id() ? cs->next() : cs); +#endif + reinterpret_cast(utcb->values)->t + = timeslice_timeout.cpu(current_cpu())->get_timeout(Timer::system_clock()); + curr->schedule(); + + return commit_result(0, Utcb::Time_val::Words); +} + + + +// ------------------------------------------------------------------- +// Gather statistics information about thread execution + +PRIVATE +unsigned +Thread_object::sys_thread_stats_remote(void *data) +{ + update_consumed_time(); + *(Clock::Time *)data = consumed_time(); + return 0; +} + +PRIVATE static +unsigned +Thread_object::handle_sys_thread_stats_remote(Drq *, Context *self, void *data) +{ + return nonull_static_cast(self)->sys_thread_stats_remote(data); +} + +PRIVATE inline NOEXPORT +L4_msg_tag +Thread_object::sys_thread_stats(L4_msg_tag const &/*tag*/, Utcb *utcb) +{ + Clock::Time value; + + if (cpu() != current_cpu()) + drq(handle_sys_thread_stats_remote, &value, 0, Drq::Any_ctxt); + else + { + // Respect the fact that the consumed time is only updated on context switch + if (this == current()) + update_consumed_time(); + value = consumed_time(); + } + + reinterpret_cast(utcb->values)->t = value; + + return commit_result(0, Utcb::Time_val::Words); +} + + diff --git a/kernel/fiasco/src/kern/thread_state.cpp b/kernel/fiasco/src/kern/thread_state.cpp new file mode 100644 index 00000000..9dd46295 --- /dev/null +++ b/kernel/fiasco/src/kern/thread_state.cpp @@ -0,0 +1,51 @@ +INTERFACE: + +// When changing these constants, change them also in shared/shortcut.h! +enum Thread_state +{ + Thread_invalid = 0, // tcb unallocated + Thread_ready = 0x1, // can be scheduled + Thread_drq_ready = 0x2, + Thread_ready_mask = Thread_ready | Thread_drq_ready, + + Thread_send_wait = 0x4, // waiting to send a message + Thread_receive_wait = 0x8, // waiting for a message + Thread_receive_in_progress = 0x10, // receiving a message (passively) + + Thread_ipc_mask = Thread_send_wait | Thread_receive_wait + | Thread_receive_in_progress, + + Thread_ipc_transfer = 0x20, + + // the ipc handshake bits needs to be in the first byte, + // the shortcut depends on it + + Thread_cancel = 0x80,// state has been changed -- cancel activity + Thread_timeout = 0x100, + + Thread_full_ipc_mask = Thread_ipc_mask | Thread_cancel + | Thread_timeout | Thread_ipc_transfer, + + Thread_ipc_abort_mask = Thread_cancel | Thread_timeout | Thread_ipc_transfer, + + Thread_dead = 0x200,// tcb allocated, but inactive (not in any q) + Thread_suspended = 0x400,// thread must not execute user code + // 0x800, 0x1000 are free + //Thread_delayed_deadline = 0x2000, // delayed until periodic deadline + //Thread_delayed_ipc = 0x4000, // delayed until periodic ipc event + Thread_fpu_owner = 0x8000, // currently owns the fpu + Thread_alien = 0x10000, // Thread is an alien, is not allowed + // to do system calls + Thread_dis_alien = 0x20000, // Thread is an alien, however the next + // system call is allowed + Thread_in_exception = 0x40000, // Thread has sent an exception but still + // got no reply + + Thread_drq_wait = 0x100000, // Thread polls for DRQs + Thread_waiting = 0x200000, // Thread waits for a lock + + Thread_vcpu_enabled = 0x400000, + Thread_vcpu_user = 0x800000, + Thread_vcpu_fpu_disabled = 0x1000000, + Thread_ext_vcpu_enabled = 0x2000000, +}; diff --git a/kernel/fiasco/src/kern/timeout.cpp b/kernel/fiasco/src/kern/timeout.cpp new file mode 100644 index 00000000..cacd8dc4 --- /dev/null +++ b/kernel/fiasco/src/kern/timeout.cpp @@ -0,0 +1,374 @@ +INTERFACE: + +#include +#include "l4_types.h" +#include "per_cpu_data.h" + +/** A timeout basic object. It contains the necessary queues and handles + enqueuing, dequeuing and handling of timeouts. Real timeout classes + should overwrite expired(), which will do the real work, if an + timeout hits. + */ +class Timeout : public cxx::H_list_item +{ + friend class Jdb_timeout_list; + friend class Jdb_list_timeouts; + friend class Timeout_q; + +public: + typedef cxx::H_list To_list; + +protected: + /** + * Absolute system time we want to be woken up at. + */ + Unsigned64 _wakeup; + +private: + /** + * Default copy constructor (is undefined). + */ + Timeout(const Timeout&); + + /** + * Overwritten timeout handler function. + * @return true if a reschedule is necessary, false otherwise. + */ + virtual bool expired(); + + struct + { + bool hit : 1; + unsigned res : 6; // performance optimization + } _flags; +}; + + +class Timeout_q +{ +private: + /** + * Timeout queue count (2^n) and distance between two queues in 2^n. + */ + enum + { + Wakeup_queue_count = 8, + Wakeup_queue_distance = 12 // i.e. (1<<12)us + }; + + typedef Timeout::To_list To_list; + typedef To_list::Iterator Iterator; + typedef To_list::Const_iterator Const_iterator; + + /** + * The timeout queues. + */ + To_list _q[Wakeup_queue_count]; + + /** + * The current programmed timeout. + */ + Unsigned64 _current; + Unsigned64 _old_clock; + +public: + static Per_cpu timeout_queue; +}; + +//---------------------------------------------------------------------------------- +IMPLEMENTATION: + +#include +#include "cpu_lock.h" +#include "kip.h" +#include "lock_guard.h" +#include "timer.h" +#include "static_init.h" +#include +#include "config.h" +#include "kdb_ke.h" + + +DEFINE_PER_CPU Per_cpu Timeout_q::timeout_queue; + + +PUBLIC inline +Timeout_q::To_list & +Timeout_q::first(int index) +{ return _q[index & (Wakeup_queue_count-1)]; } + +PUBLIC inline +Timeout_q::To_list const & +Timeout_q::first(int index) const +{ return _q[index & (Wakeup_queue_count-1)]; } + +PUBLIC inline +unsigned +Timeout_q::queues() const { return Wakeup_queue_count; } + + +/** + * Enqueue a new timeout. + */ +PUBLIC inline NEEDS[Timeout_q::first, "timer.h", "config.h"] +void +Timeout_q::enqueue(Timeout *to) +{ + int queue = (to->_wakeup >> Wakeup_queue_distance) & (Wakeup_queue_count-1); + + To_list &q = first(queue); + Iterator tmp = q.begin(); + + while (tmp != q.end() && tmp->_wakeup < to->_wakeup) + ++tmp; + + q.insert_before(to, tmp); + + if (Config::Scheduler_one_shot && (to->_wakeup <= _current)) + { + _current = to->_wakeup; + Timer::update_timer(_current); + } +} + + +/** + * Timeout constructor. + */ +PUBLIC inline +Timeout::Timeout() +{ + _flags.hit = 0; + _flags.res = 0; +} + + +/** + * Initializes an timeout object. + */ +PUBLIC inline NEEDS[] +void +Timeout::init() +{ + _wakeup = ULONG_LONG_MAX; +} + +/* Yeah, i know, an derived and specialized timeout class for + the root node would be nicer. I already had done this, but + it was significantly slower than this solution */ +IMPLEMENT virtual bool +Timeout::expired() +{ + kdb_ke("Wakeup List Terminator reached"); + return false; +} + +/** + * Check if timeout is set. + */ +PUBLIC inline +bool +Timeout::is_set() +{ + return To_list::in_list(this); +} + +/** + * Check if timeout has hit. + */ +PUBLIC inline +bool +Timeout::has_hit() +{ + return _flags.hit; +} + + +PUBLIC inline NEEDS [, "cpu_lock.h", "lock_guard.h", + Timeout_q::enqueue, Timeout::is_set] +void +Timeout::set(Unsigned64 clock, unsigned cpu) +{ + // XXX uses global kernel lock + Lock_guard guard (&cpu_lock); + + assert (!is_set()); + + _wakeup = clock; + Timeout_q::timeout_queue.cpu(cpu).enqueue(this); +} + +/** + * Return remaining time of timeout. + */ +PUBLIC inline +Signed64 +Timeout::get_timeout(Unsigned64 clock) +{ + return _wakeup - clock; +} + +PUBLIC inline NEEDS [, "cpu_lock.h", "lock_guard.h", + Timeout::is_set, Timeout_q::enqueue, Timeout::has_hit] +void +Timeout::set_again(unsigned cpu) +{ + // XXX uses global kernel lock + Lock_guard guard (&cpu_lock); + + assert(! is_set()); + if (has_hit()) + return; + + Timeout_q::timeout_queue.cpu(cpu).enqueue(this); +} + +PUBLIC inline NEEDS ["cpu_lock.h", "lock_guard.h", "timer.h", + "kdb_ke.h", Timeout::is_set] +void +Timeout::reset() +{ + assert_kdb (cpu_lock.test()); + To_list::remove(this); + + // Normaly we should reprogramm the timer in one shot mode + // But we let the timer interrupt handler to do this "lazily", to save cycles +} + +/** + * Dequeue an expired timeout. + * @return true if a reschedule is necessary, false otherwise. + */ +PRIVATE inline +bool +Timeout::expire() +{ + _flags.hit = 1; + return expired(); +} +/** + * Dequeue an expired timeout. + * @return true if a reschedule is necessary, false otherwise. + */ +PUBLIC inline +bool +Timeout::dequeue(bool is_expired = true) +{ + To_list::remove(this); + + if (is_expired) + return expire(); + else + return false; +} + +/** + * Handles the timeouts, i.e. call expired() for the expired timeouts + * and programs the "oneshot timer" to the next timeout. + * @return true if a reschedule is necessary, false otherwise. + */ +PUBLIC inline NEEDS [, , "kip.h", "timer.h", "config.h", + Timeout::expire] +bool +Timeout_q::do_timeouts() +{ + bool reschedule = false; + + // We test if the time between 2 activiations of this function is greater + // than the distance between two timeout queues. + // To avoid to lose timeouts, we calculating the missed queues and + // scan them too. + // This can only happen, if we dont enter the timer interrupt for a long + // time, usual with one shot timer. + // Because we initalize old_dequeue_time with zero, + // we can get an "miss" on the first timerinterrupt. + // But this is booting the system, which is uncritical. + + // Calculate which timeout queues needs to be checked. + int start = (_old_clock >> Wakeup_queue_distance); + int diff = (Kip::k()->clock >> Wakeup_queue_distance) - start; + int end = (start + diff + 1) & (Wakeup_queue_count - 1); + + // wrap around + start = start & (Wakeup_queue_count - 1); + + // test if an complete miss + if (diff >= Wakeup_queue_count) + start = end = 0; // scan all queues + + // update old_clock for the next run + _old_clock = Kip::k()->clock; + + // ensure we always terminate + assert((end >= 0) && (end < Wakeup_queue_count)); + + for (;;) + { + To_list &q = first(start); + Iterator timeout = q.begin(); + + // now scan this queue for timeouts below current clock + while (timeout != q.end() && timeout->_wakeup <= (Kip::k()->clock)) + { + reschedule |= timeout->expire(); + timeout = q.erase(timeout); + } + + // next queue + start = (start + 1) & (Wakeup_queue_count - 1); + + if (start == end) + break; + } + + if (Config::Scheduler_one_shot) + { + // scan all queues for the next minimum + //_current = (Unsigned64) ULONG_LONG_MAX; + _current = Kip::k()->clock + 10000; //ms + bool update_timer = true; + + for (int i = 0; i < Wakeup_queue_count; i++) + { + // make sure that something enqueued other than the dummy element + if (first(i).empty()) + continue; + + update_timer = true; + + if (first(i).front()->_wakeup < _current) + _current = first(i).front()->_wakeup; + } + + if (update_timer) + Timer::update_timer(_current); + + } + return reschedule; +} + +PUBLIC inline +Timeout_q::Timeout_q() +: _current(ULONG_LONG_MAX), _old_clock(0) +{} + +PUBLIC inline +bool +Timeout_q::have_timeouts(Timeout const *ignore) const +{ + for (unsigned i = 0; i < Wakeup_queue_count; ++i) + { + To_list const &t = first(i); + if (!t.empty()) + { + To_list::Const_iterator f = t.begin(); + if (*f == ignore && (++f) == t.end()) + continue; + + return true; + } + } + + return false; +} + diff --git a/kernel/fiasco/src/kern/timer-hpet.cpp b/kernel/fiasco/src/kern/timer-hpet.cpp new file mode 100644 index 00000000..76a83807 --- /dev/null +++ b/kernel/fiasco/src/kern/timer-hpet.cpp @@ -0,0 +1,76 @@ +INTERFACE [hpet_timer]: + +EXTENSION class Timer +{ + static int hpet_irq; +}; + +IMPLEMENTATION [hpet_timer]: + +#include "config.h" +#include "cpu.h" +#include "hpet.h" +#include "irq_chip.h" +#include "logdefs.h" +#include "pit.h" +#include "std_macros.h" + +#include + +int Timer::hpet_irq; + +PUBLIC static inline int Timer::irq() { return hpet_irq; } + +PUBLIC static inline NEEDS["irq_chip.h"] +unsigned Timer::irq_mode() +{ return Irq_base::Trigger_level | Irq_base::Polarity_low; } + +IMPLEMENT +void +Timer::init(unsigned) +{ + hpet_irq = -1; + if (!Hpet::init()) + return; + + hpet_irq = Hpet::int_num(); + if (hpet_irq == 0 && Hpet::int_avail(2)) + hpet_irq = 2; + + if (Config::Scheduler_one_shot) + { + // tbd + } + else + { + // setup hpet for periodic here + } + + if (!Config::Scheduler_one_shot) + // from now we can save energy in getchar() + Config::getchar_does_hlt_works_ok = Config::hlt_works_ok; + + Hpet::enable(); + Hpet::dump(); + + printf("Using HPET timer on IRQ %d (%s Mode) for scheduling\n", + hpet_irq, + Config::Scheduler_one_shot ? "One-Shot" : "Periodic"); +} + +PUBLIC static inline +void +Timer::acknowledge() +{} + +static +void +Timer::update_one_shot(Unsigned64 /*wakeup*/) +{ +} + +IMPLEMENT inline +void +Timer::update_timer(Unsigned64 /*wakeup*/) +{ +} diff --git a/kernel/fiasco/src/kern/timer.cpp b/kernel/fiasco/src/kern/timer.cpp new file mode 100644 index 00000000..01711158 --- /dev/null +++ b/kernel/fiasco/src/kern/timer.cpp @@ -0,0 +1,46 @@ +INTERFACE: + +#include "initcalls.h" +#include "l4_types.h" + +class Timer +{ +public: + /** + * Static constructor for the interval timer. + * + * The implementation is platform specific. Two x86 implementations + * are timer-pit and timer-rtc. + */ + static void init(unsigned cpu) FIASCO_INIT_CPU; + + /** + * Initialize the system clock. + */ + static void init_system_clock(); + + /** + * Advances the system clock. + */ + static void update_system_clock(unsigned cpu); + + /** + * Get the current system clock. + */ + static Unsigned64 system_clock(); + + /** + * reprogram the one-shot timer to the next event. + */ + static void update_timer(Unsigned64 wakeup); + + static void master_cpu(unsigned cpu) { _cpu = cpu; } + +private: + static unsigned _cpu; +}; + + +IMPLEMENTATION: + +unsigned Timer::_cpu; diff --git a/kernel/fiasco/src/kern/timer_tick-single-vector.cpp b/kernel/fiasco/src/kern/timer_tick-single-vector.cpp new file mode 100644 index 00000000..7bcc051f --- /dev/null +++ b/kernel/fiasco/src/kern/timer_tick-single-vector.cpp @@ -0,0 +1,51 @@ +INTERFACE: + +#include "types.h" + +EXTENSION class Timer_tick +{ +public: + static Static_object _glbl_timer; +}; + +IMPLEMENTATION: + +#include "timer.h" + +Static_object Timer_tick::_glbl_timer; + +IMPLEMENT void +Timer_tick::setup(unsigned cpu) +{ + // all CPUs use the same timer IRQ, so initialize just on CPU 0 + if (cpu != 0) + return; + + _glbl_timer.construct(Any_cpu); + if (!allocate_irq(_glbl_timer, Timer::irq())) + panic("Could not allocate scheduling IRQ %d\n", Timer::irq()); + + _glbl_timer->set_mode(Timer::irq_mode()); +} + +IMPLEMENT +void +Timer_tick::enable(unsigned) +{ + _glbl_timer->chip()->unmask(_glbl_timer->pin()); +} + +IMPLEMENT +void +Timer_tick::disable(unsigned) +{ + _glbl_timer->chip()->mask(_glbl_timer->pin()); +} + +PUBLIC inline NEEDS["timer.h"] +void +Timer_tick::ack() +{ + Timer::acknowledge(); + Irq_base::ack(); +} diff --git a/kernel/fiasco/src/kern/timer_tick.cpp b/kernel/fiasco/src/kern/timer_tick.cpp new file mode 100644 index 00000000..43e8e53f --- /dev/null +++ b/kernel/fiasco/src/kern/timer_tick.cpp @@ -0,0 +1,127 @@ +INTERFACE: + +#include "irq_chip.h" + +class Timer_tick : public Irq_base +{ +public: + enum Mode + { + Any_cpu, ///< Might hit on any CPU + Sys_cpu, ///< Hit only on the CPU that manages the system time + App_cpu, ///< Hit only on application CPUs + }; + /// Create a timer IRQ object + explicit Timer_tick(Mode mode) + { + switch (mode) + { + case Any_cpu: set_hit(&handler_all); break; + case Sys_cpu: set_hit(&handler_sys_time); break; + case App_cpu: set_hit(&handler_app); break; + } + } + + static void setup(unsigned cpu); + static void enable(unsigned cpu); + static void disable(unsigned cpu); + +protected: + static bool allocate_irq(Irq_base *irq, unsigned irqnum); + +private: + // we do not support triggering modes + void switch_mode(unsigned) {} +}; + +// ------------------------------------------------------------------------ +INTERFACE [debug]: + +EXTENSION class Timer_tick +{ +public: + struct Log + { + Irq_base *obj; + Address user_ip; + }; + + static unsigned tt_log_fmt(Tb_entry *, int, char *) asm ("__tt_log_fmt"); +}; + +// ------------------------------------------------------------------------ +IMPLEMENTATION: + +#include "thread.h" +#include "timer.h" + +PUBLIC static inline NEEDS["thread.h", "timer.h"] +void +Timer_tick::handler_all(Irq_base *_s, Upstream_irq const *ui) +{ + Timer_tick *self = nonull_static_cast(_s); + self->ack(); + ui->ack(); + Thread *t = current_thread(); + Timer::update_system_clock(t->cpu(true)); + self->log_timer(); + t->handle_timer_interrupt(); +} + +PUBLIC static inline NEEDS["thread.h", "timer.h"] +void +Timer_tick::handler_sys_time(Irq_base *_s, Upstream_irq const *ui) +{ + Timer_tick *self = nonull_static_cast(_s); + self->ack(); + ui->ack(); + Timer::update_system_clock(0); // assume 0 to be the CPU that + // manages the system time + self->log_timer(); + current_thread()->handle_timer_interrupt(); +} + +PUBLIC static inline NEEDS["thread.h", "timer.h"] +void +Timer_tick::handler_app(Irq_base *_s, Upstream_irq const *ui) +{ + Timer_tick *self = nonull_static_cast(_s); + self->ack(); + ui->ack(); + self->log_timer(); + current_thread()->handle_timer_interrupt(); +} + +// -------------------------------------------------------------------------- +IMPLEMENTATION [!debug]: + +PUBLIC static inline +void +Timer_tick::log_timer() +{} + +// -------------------------------------------------------------------------- +IMPLEMENTATION [debug]: + +#include "logdefs.h" +#include "irq_chip.h" + +IMPLEMENT +unsigned +Timer_tick::tt_log_fmt(Tb_entry *e, int maxlen, char *buf) +{ + Log *l = e->payload(); + return snprintf(buf, maxlen, "u-ip=0x%lx", l->user_ip); +} + +PUBLIC inline NEEDS["logdefs.h"] +void +Timer_tick::log_timer() +{ + Context *c = current(); + LOG_TRACE("Timer IRQs (kernel scheduling)", "timer", c, __tt_log_fmt, + Log *l = tbe->payload(); + l->user_ip = c->regs()->ip(); + l->obj = this; + ); +} diff --git a/kernel/fiasco/src/kern/timeslice_timeout.cpp b/kernel/fiasco/src/kern/timeslice_timeout.cpp new file mode 100644 index 00000000..c3d412e7 --- /dev/null +++ b/kernel/fiasco/src/kern/timeslice_timeout.cpp @@ -0,0 +1,55 @@ + +INTERFACE: + +#include "timeout.h" + +class Timeslice_timeout : public Timeout +{ +}; + +IMPLEMENTATION: + +#include +#include "globals.h" +#include "sched_context.h" +#include "std_macros.h" + +/* Initialize global valiable timeslice_timeout */ +DEFINE_PER_CPU Per_cpu timeslice_timeout; +DEFINE_PER_CPU static Per_cpu the_timeslice_timeout(true); + +PUBLIC +Timeslice_timeout::Timeslice_timeout(unsigned cpu) +{ + timeslice_timeout.cpu(cpu) = this; +} + + +/** + * Timeout expiration callback function + * @return true to force a reschedule + */ +PRIVATE +bool +Timeslice_timeout::expired() +{ + unsigned cpu = current_cpu(); + Sched_context *sched = Sched_context::rq(cpu).current_sched(); + + if (sched) + { +#if 0 + Context *owner = sched->owner(); + + // Ensure sched is owner's current timeslice + assert (owner->sched() == sched); +#endif + sched->replenish(); + sched->requeue(cpu); + sched->invalidate_sched(cpu); + +// owner->switch_sched(sched); + } + + return true; // Force reschedule +} diff --git a/kernel/fiasco/src/kern/uart-mmio.cpp b/kernel/fiasco/src/kern/uart-mmio.cpp new file mode 100644 index 00000000..85339f7a --- /dev/null +++ b/kernel/fiasco/src/kern/uart-mmio.cpp @@ -0,0 +1,14 @@ +IMPLEMENTATION [libuart]: + +#include "io_regblock.h" + +EXTENSION class Uart +{ + L4::Io_register_block_mmio _regs; +}; + +IMPLEMENT inline Uart::Uart() : _regs(base()) {} + +PUBLIC bool Uart::startup() +{ return uart()->startup(&_regs); } + diff --git a/kernel/fiasco/src/kern/uart_console.cpp b/kernel/fiasco/src/kern/uart_console.cpp new file mode 100644 index 00000000..98a3583e --- /dev/null +++ b/kernel/fiasco/src/kern/uart_console.cpp @@ -0,0 +1,41 @@ +IMPLEMENTATION: + +#include +#include + +#include "config.h" +#include "filter_console.h" +#include "kernel_console.h" +#include "kernel_uart.h" +#include "static_init.h" +#include "irq.h" + +STATIC_INITIALIZER (uart_console_init_stage2); + +static void uart_console_init_stage2() +{ + if ((Kernel_uart::uart()->failed())) + return; + + int irq = -1; + if (Config::serial_esc == Config::SERIAL_ESC_IRQ + && (irq = Kernel_uart::uart()->irq()) == -1) + { + puts("SERIAL ESC: not supported"); + Config::serial_esc = Config::SERIAL_ESC_NOIRQ; + } + + switch (Config::serial_esc) + { + case Config::SERIAL_ESC_NOIRQ: + puts("SERIAL ESC: No IRQ for specified uart port."); + puts("Using serial hack in slow timer handler."); + break; + + case Config::SERIAL_ESC_IRQ: + Kernel_uart::enable_rcv_irq(); + printf("SERIAL ESC: allocated IRQ %d for serial uart\n", irq); + puts("Not using serial hack in slow timer handler."); + break; + } +} diff --git a/kernel/fiasco/src/kern/utcb_init.cpp b/kernel/fiasco/src/kern/utcb_init.cpp new file mode 100644 index 00000000..9ffc61f3 --- /dev/null +++ b/kernel/fiasco/src/kern/utcb_init.cpp @@ -0,0 +1,20 @@ +INTERFACE: + +#include "initcalls.h" +#include "types.h" + +class Cpu; + +class Utcb_init +{ +public: + /** + * UTCB access initialization. + * + * Allocates the UTCB pointer page and maps it to Kmem::utcb_ptr_page. + * Setup both segment selector and gs register to allow gs:0 access. + * + * @post user can access the utcb pointer via gs:0. + */ + static void init() FIASCO_INIT; +}; diff --git a/kernel/fiasco/src/kern/utcb_support.cpp b/kernel/fiasco/src/kern/utcb_support.cpp new file mode 100644 index 00000000..2f1ae7b4 --- /dev/null +++ b/kernel/fiasco/src/kern/utcb_support.cpp @@ -0,0 +1,10 @@ +INTERFACE: + +#include "l4_types.h" + +class Utcb_support +{ +public: + static User::Ptr current(); + static void current(User::Ptr const &utcb); +}; diff --git a/kernel/fiasco/src/kern/ux/Makerules.KERNEL b/kernel/fiasco/src/kern/ux/Makerules.KERNEL new file mode 100644 index 00000000..a8e203a0 --- /dev/null +++ b/kernel/fiasco/src/kern/ux/Makerules.KERNEL @@ -0,0 +1,75 @@ +# UX Kernel Makefile + +shortcut.o: $(TCBOFFSET) +sighandler.o: $(TCBOFFSET) +entry.o: $(TCBOFFSET) +sys_call_page-asm.o: $(TCBOFFSET) + + +# Add future prerequisites somewhere among the list of libraries. You really +# should not have to add anything in the $(CXX) line. +# +# Please don't add -gc-sections as linker option here. The reason is that +# properly working destructors of libc.a require __start_libc_atexit and +# __stop_libc_atexit to be defined by the linker. The ld linker defines +# these symbols by magic if it finds a 'libc section' -- the section name +# starts with '_'. However, if the section is completely purged, these +# symbols are not defined and therefore the libc destructors are not executed +# (_IO_cleanup so far). We could manually create the correct section by adding +# +# __libc_atexit : { +# PROVIDE(__start___libc_atexit = .); +# KEEP(*(__libc_atexit)) +# PROVIDE(__stop___libc_atexit = .); +# } +# +# to the linker script. We don't do this because we don't know which symbols +# are required by future versions of the libc. + +$(KERNEL): kernel.ux.lds $(OBJ_KERNEL) $(MINILIBC) $(LIBK) $(KERNEL_EXTRA_LIBS) $(ABI) $(JABI) $(DRIVERS) $(CXXLIB) + $(LINK_MESSAGE) + $(VERBOSE)$(CXX) -m32 -Wl,-T$< -static -o $@ -Wl,--whole-archive $(MINILIBC) -Wl,--no-whole-archive $(KERNEL_UNRES_SYMS) $(filter-out $<,$+) -lutil $(WRAP_SYMBOLS) + chmod 755 $@ + ln -sf $@ fiasco + +irq0.o: irq0.c + $(COMP_MESSAGE) + $(VERBOSE)$(CC) -O2 -Wall -W -c -o $@ $< + +irq0: irq0.o + $(LINK_MESSAGE) + $(VERBOSE)$(CC) -static -o $@ $< + $(STRIP_MESSAGE) + $(VERBOSE)$(STRIP) $@ + +ifeq ($(CONFIG_UX_CON),y) + +SDL_CFLAGS := $(shell $(SYSTEM_TARGET)sdl-config --cflags) +SDL_LDFLAGS := $(shell $(SYSTEM_TARGET)sdl-config --libs) + +ifeq ($(SDL_CFLAGS),) + $(error sdl-config not found. libsdl including header files installed?) +endif + +ux_con.o: ux_con.c + $(COMP_MESSAGE) + $(VERBOSE)$(CC) -O2 -Wall -W -g $(SDL_CFLAGS) -c $< + +ux_con: ux_con.o + $(LINK_MESSAGE) + $(VERBOSE)$(CC) $(SDL_LDFLAGS) $< -o $@ + $(STRIP_MESSAGE) + $(VERBOSE)$(STRIP) $@ +endif + +ifeq ($(CONFIG_UX_NET),y) +ux_net.o: ux_net.c + $(COMP_MESSAGE) + $(VERBOSE)$(CC) -O2 -Wall -W -g -c $< + +ux_net: ux_net.o + $(LINK_MESSAGE) + $(VERBOSE)$(CC) $< -o $@ + $(STRIP_MESSAGE) + $(VERBOSE)$(STRIP) $@ +endif diff --git a/kernel/fiasco/src/kern/ux/Makerules.SYMBOLS.ux b/kernel/fiasco/src/kern/ux/Makerules.SYMBOLS.ux new file mode 100644 index 00000000..c551e0a6 --- /dev/null +++ b/kernel/fiasco/src/kern/ux/Makerules.SYMBOLS.ux @@ -0,0 +1,11 @@ +# -*- makefile -*- + +$(SYMBOLS): $(KERNEL) + $(COMP_MESSAGE) + $(VERBOSE)$(NM) -nC $(KERNEL)|grep "^00[0-9a-z]\{6,6\}">$@.new + $(VERBOSE)mv $@.new $@ + $(VERBOSE)chmod 644 $@ + $(call INSTALLFILE_RULE,$@,fiasco_symbols) + +clean-SYMBOLS: + rm -f $(SYMBOLS) diff --git a/kernel/fiasco/src/kern/ux/boot_info-ux.cpp b/kernel/fiasco/src/kern/ux/boot_info-ux.cpp new file mode 100644 index 00000000..539512cc --- /dev/null +++ b/kernel/fiasco/src/kern/ux/boot_info-ux.cpp @@ -0,0 +1,749 @@ +/* + * Fiasco-UX + * Architecture specific bootinfo code + */ + +INTERFACE: + +#include // for pid_t +#include // for struct option +#include "l4_types.h" // for Global_id +#include "multiboot.h" + +EXTENSION class Boot_info +{ +public: + static Address mbi_phys(); + static Multiboot_info *mbi_virt(); + +private: + static int _fd; // Physmem FD + static pid_t _pid; // Process ID + static char ** _args; // Cmd Line Parameters + static bool _irq0_disabled; + static unsigned long _input_size; + static unsigned long _fb_size; + static Address _fb_virt; + static Address _fb_phys; + static unsigned int _fb_width; + static unsigned int _fb_height; + static unsigned int _fb_depth; + static const char * _fb_program; + static bool _net; + static const char * _net_program; + static void * _mbi_vbe; + static const char * _irq0_program; + static struct option _long_options[]; + static char _help[]; + static char const * _modules[]; + static bool _emulate_clisti; + static unsigned long _sigma0_start; + static unsigned long _sigma0_end; + static unsigned long _root_start; + static unsigned long _root_end; + static unsigned long _min_mappable_address; +}; + +IMPLEMENTATION[ux]: + +// for our init code we do not care about the stack size +#pragma GCC diagnostic ignored "-Wframe-larger-than=" + +#include // for assert +#include // for errno +#include // for CHAR_BIT +#include // for atol +#include // for stpcpy +#include // for printf +#include // for open +#include // for panic +#include // for getopt +#include // for mmap +#include // for open +#include +#include // for uname +#include + +#include "config.h" +#include "emulation.h" +#include "initcalls.h" +#include "kernel_console.h" +#include "koptions.h" +#include "loader.h" +#include "mem_layout.h" + +int Boot_info::_fd; +pid_t Boot_info::_pid; +char ** Boot_info::_args; +bool Boot_info::_irq0_disabled; +unsigned long Boot_info::_input_size; +unsigned long Boot_info::_fb_size; +Address Boot_info::_fb_virt = 0xc0000000; +Address Boot_info::_fb_phys; +unsigned int Boot_info::_fb_width; +unsigned int Boot_info::_fb_height; +unsigned int Boot_info::_fb_depth; +const char * Boot_info::_fb_program = "ux_con"; +bool Boot_info::_net; +const char * Boot_info::_net_program = "ux_net"; +void * Boot_info::_mbi_vbe; +const char * Boot_info::_irq0_program = "irq0"; +bool Boot_info::_emulate_clisti; +unsigned long Boot_info::_sigma0_start; +unsigned long Boot_info::_sigma0_end; +unsigned long Boot_info::_root_start; +unsigned long Boot_info::_root_end; +unsigned long Boot_info::_min_mappable_address; + + +// If you add options here, add them to getopt_long and help below +struct option Boot_info::_long_options[] FIASCO_INITDATA = +{ + { "physmem_file", required_argument, NULL, 'f' }, + { "help", no_argument, NULL, 'h' }, + { "jdb_cmd", required_argument, NULL, 'j' }, + { "kmemsize", required_argument, NULL, 'k' }, + { "load_module", required_argument, NULL, 'l' }, + { "memsize", required_argument, NULL, 'm' }, + { "native_task", required_argument, NULL, 'n' }, + { "quiet", no_argument, NULL, 'q' }, + { "tbuf_entries", required_argument, NULL, 't' }, + { "wait", no_argument, NULL, 'w' }, + { "fb_program", required_argument, NULL, 'F' }, + { "fb_geometry", required_argument, NULL, 'G' }, + { "net", no_argument, NULL, 'N' }, + { "net_program", required_argument, NULL, 'E' }, + { "irq0", required_argument, NULL, 'I' }, + { "roottask", required_argument, NULL, 'R' }, + { "sigma0", required_argument, NULL, 'S' }, + { "test", no_argument, NULL, 'T' }, + { "disable_irq0", no_argument, NULL, '0' }, + { "symbols", required_argument, NULL, 'Y' }, + { "roottaskconfig", required_argument, NULL, 'C' }, + { "lines", required_argument, NULL, 'L' }, + { "clisti", no_argument, NULL, 's' }, + { 0, 0, 0, 0 } +}; + +// Keep this in sync with the options above +char Boot_info::_help[] FIASCO_INITDATA = + "-f file : Specify the location of the physical memory backing store\n" + "-l module : Specify a module\n" + "-j jdb cmds : Specify non-interactive Jdb commands to be executed at startup\n" + "-k kmemsize : Specify size in KiB to be reserved for kernel\n" + "-m memsize : Specify physical memory size in MB (currently up to 1024)\n" + "-q : Suppress any startup message\n" + "-t number : Specify the number of trace buffer entries (up to 32768)\n" + "-w : Enter kernel debugger on startup and wait\n" + "-0 : Disable the timer interrupt generator\n" + "-F : Specify a different frame buffer program\n" + "-G : Geometry for frame buffer: widthxheight@depth\n" + "-N : Enable network support\n" + "-E : Specify net helper binary\n" + "-I : Specify different irq0 binary\n" + "-R : Specify different roottask binary\n" + "-S : Specify different sigma0 binary\n" + "-Y : Specify symbols path\n" + "-L : Specify lines path\n" + "-C : Specify roottask configuration file path\n" + "-T : Test mode -- do not load any modules\n" + "-s : Emulate cli/sti instructions\n"; + + +char const *Boot_info::_modules[64] FIASCO_INITDATA = +{ + "fiasco", + "sigma0", + "moe", + NULL, // Symbols + NULL, // Lines + NULL // Roottask configuration +}; + + +PUBLIC static +Address +Boot_info::kmem_start(Address mem_max) +{ + Address end_addr = (mbi_virt()->mem_upper + 1024) << 10; + Address size, base; + + if (end_addr > mem_max) + end_addr = mem_max; + + size = Koptions::o()->kmemsize << 10; + if (!size) + { + size = end_addr / 100 * Config::kernel_mem_per_cent; + if (size > Config::kernel_mem_max) + size = Config::kernel_mem_max; + } + + base = end_addr - size & Config::PAGE_MASK; + if (Mem_layout::phys_to_pmem(base) < Mem_layout::Physmem) + base = Mem_layout::pmem_to_phys(Mem_layout::Physmem); + + return base; +} + + + +IMPLEMENT FIASCO_INIT +void +Boot_info::init() +{ + extern int __libc_argc; + extern char ** __libc_argv; + register unsigned long _sp asm("esp"); + char const *physmem_file = "/tmp/physmem"; + char const *error, **m; + char *str, buffer[4096]; + int arg; + bool quiet = false; + unsigned int modcount = 6, skip = 3; + unsigned long int memsize = 64 << 20; + Multiboot_info * mbi; + Multiboot_module * mbm; + struct utsname uts; +#if 0 + char const * symbols_file = "Symbols"; + char const * lines_file = "Lines"; + char const * roottask_config_file = "roottask.config"; +#endif + + _args = __libc_argv; + _pid = getpid (); + + *(str = buffer) = 0; + + // Parse command line. Use getopt_long_only() to achieve more compatibility + // with command line switches in the IA32 architecture. + while ((arg = getopt_long_only (__libc_argc, __libc_argv, + "C:f:hj:k:l:m:qst:wE:F:G:I:L:NR:S:TY:0", + _long_options, NULL)) != -1) { + switch (arg) { + + case 'S': + _modules[1] = optarg; + break; + + case 'R': + _modules[2] = optarg; + break; + + case 'Y': // sYmbols path +#if 0 + symbols_file = optarg; +#endif + break; + + case 'L': // Lines path +#if 0 + lines_file = optarg; +#endif + break; + + case 'C': // roottask Configuration file +#if 0 + roottask_config_file = optarg; +#endif + break; + + case 'l': + if (modcount < sizeof (_modules) / sizeof (*_modules)) + _modules[modcount++] = optarg; + else + printf("WARNING: max modules exceeded (dropped '%s')\n", + optarg); + break; + + case 'f': + physmem_file = optarg; + break; + + case 'j': + set_jdb_cmd(optarg); + break; + + case 'k': + kmemsize(atol(optarg) << 10); + break; + + case 'm': + memsize = atol (optarg) << 20; + break; + + case 'q': + quiet = true; + Kconsole::console()->change_state(0, 0, ~Console::OUTENABLED, 0); + break; + + case 't': + Config::tbuf_entries = atol (optarg); + break; + + case 'w': + set_wait(); + break; + + case '0': + _irq0_disabled = true; + break; + + case 'F': + _fb_program = optarg; + break; + + case 'G': + if (sscanf (optarg, "%ux%u@%u", &_fb_width, &_fb_height, &_fb_depth) + == 3) + { + _fb_size = _fb_width * _fb_height * (_fb_depth + 7 >> 3); + _fb_size += ~Config::SUPERPAGE_MASK; + _fb_size &= Config::SUPERPAGE_MASK; // Round up to 4 MB + + _input_size = Config::PAGE_SIZE; + } + break; + + case 'N': + _net = 1; + break; + + case 'E': + _net_program = optarg; + break; + + case 'I': + _irq0_program = optarg; + break; + + case 'T': + modcount = 0; skip = 0; + break; + + case 's': + _emulate_clisti = 1; + break; + + default: + printf ("Usage: %s\n\n%s", *__libc_argv, _help); + exit (arg == 'h' ? EXIT_SUCCESS : EXIT_FAILURE); + } + } + + if (_sp < ((Mem_layout::Host_as_base - 1) & Config::SUPERPAGE_MASK) + && munmap((void *)((Mem_layout::Host_as_base - 1) & Config::PAGE_MASK), + Config::PAGE_SIZE) == -1 && errno == EINVAL) + { + printf(" Fiasco-UX does only run with %dGB user address space size.\n" + " Please make sure your host Linux kernel is configured for %dGB\n" + " user address space size. Check for\n" + " CONFIG_PAGE_OFFSET=0x%X\n" + " in your host Linux .config.\n", + Mem_layout::Host_as_base >> 30, Mem_layout::Host_as_base >> 30, + Mem_layout::Host_as_base); + exit(EXIT_FAILURE); + } + + // Check roottask command line for symbols and lines options +#if 0 + if (strstr (_modules[2], " -symbols")) + { + _modules[3] = symbols_file; + skip--; + } + if (strstr (_modules[2], " -lines")) + { + _modules[4] = lines_file; + skip--; + } + if (strstr (_modules[2], " -configfile")) + { + _modules[5] = roottask_config_file; + skip--; + } +#endif + + if (uname (&uts)) + panic("uname: %s", strerror (errno)); + + if (! quiet) + printf ("\n\nFiasco-UX on %s %s (%s)\n", + uts.sysname, uts.release, uts.machine); + + struct rlimit rl; + if (getrlimit(RLIMIT_STACK, &rl)) + perror("getrlimit"); + else + { + rl.rlim_max = rl.rlim_cur = 1 << 17; + if (setrlimit(RLIMIT_STACK, &rl)) + perror("setrlimit"); + } + + get_minimum_map_address(); + find_x86_tls_base(); + + if ((_fd = open (physmem_file, O_RDWR | O_CREAT | O_EXCL | O_TRUNC, 0700)) + == -1) + panic ("cannot create physmem: %s", strerror (errno)); + + // check if we really got exec-rights on physmem, /tmp might be mounted noexec + if (access(physmem_file, R_OK | W_OK | X_OK)) + { + unlink (physmem_file); + panic ("Invalid permissions for physmem file"); + } + + struct statvfs stvfs; + if (statvfs(physmem_file, &stvfs) < 0) + { + perror("statvfs"); + panic("Cannot query statistics on physmem file"); + } + + unlink (physmem_file); + + // Cannot handle more physical memory than roottask can handle (currently 1 GB). + // roottask considers anything greater than 0x40000000 as adapter page. +#ifdef CONFIG_CONTEXT_4K + // With 4k kernel thread context size we cannot handle more than 512MB + // physical memory (mapped to the virtual area 0x90000000..0xb0000000). + if (memsize > 1 << 29) + memsize = 1 << 29; +#else + if (memsize > 1 << 30) + memsize = 1 << 30; +#endif + + if (memsize + _fb_size + _input_size > stvfs.f_bavail * stvfs.f_bsize) + { + printf("WARNING: Available free space of %ldMB for '%s' might not be enough.\n", + (stvfs.f_bavail * stvfs.f_bsize) >> 20, physmem_file); + } + + // The framebuffer starts beyond the physical memory + _fb_phys = memsize; + + // Create a sparse file as backing store + if (lseek (_fd, memsize + _fb_size + _input_size - 1, SEEK_SET) == -1 || + write (_fd, "~", 1) != 1) + panic ("cannot resize physmem: %s", strerror (errno)); + + // Now map the beast in our virtual address space + if (mmap (reinterpret_cast(Mem_layout::Physmem), + memsize + _fb_size + _input_size, + PROT_READ | PROT_WRITE, + MAP_FIXED | MAP_SHARED, _fd, 0) == MAP_FAILED) + panic ("cannot mmap physmem: %s", strerror (errno)); + + if (! quiet) + printf ("Mapped %lu MB Memory + %lu KB Framebuffer + " + "%lu KB Input Area on FD %d\n\n", + memsize >> 20, _fb_size >> 10, _input_size >> 10, _fd); + + mbi = mbi_virt(); + mbi->flags = Multiboot_info::Memory | Multiboot_info::Cmdline | + Multiboot_info::Mods; + mbi->mem_lower = 0; + mbi->mem_upper = (memsize >> 10) - 1024; /* in KB */ + mbi->mods_count = modcount - skip; + mbi->mods_addr = mbi_phys() + sizeof (*mbi); + mbm = reinterpret_cast((char *) mbi + sizeof (*mbi)); + str = reinterpret_cast(mbm + modcount - skip); + + // Copying of modules starts at the top, right below the kmem reserved area + + // Skip an area of 1MB in order to allow sigma0 to allocate its memmap + // structures at top of physical memory. Note that the space the boot + // modules are loaded at is later freed in most cases so we prevent memory + // fragmentation here. + Address load_addr = kmem_start (0xffffffff) - (1 << 20); + + + // Load/copy the modules + for (m = _modules; m < _modules + modcount; m++) + { + unsigned long start, end; + char *cmd; + + if (!*m) + continue; + + // Cut off between module name and command line + if ((cmd = strchr (const_cast(*m), ' '))) + *cmd = 0; + + if (m == _modules) + { + mbm->mod_start = 0; + mbm->mod_end = 0; + error = 0; + } + else + // Load sigma0 and roottask, just copy the rest + error = m < _modules + 3 ? + Loader::load_module (*m, mbm, memsize, quiet, &start, &end) : + Loader::copy_module (*m, mbm, &load_addr, quiet); + + if (error) + { + printf ("%s: %s\n", error, *m); + exit (EXIT_FAILURE); + } + + // Reattach command line + if (cmd) + *cmd = ' '; + + mbm->string = str - (char *) mbi + mbi_phys(); + + // Copy module name with path and command line + str = stpcpy (str, *m) + 1; + + // sigma0: save memory region + if (m == _modules + 1) + { + _sigma0_start = start; + _sigma0_end = end; + } + else + // roottask: save memory region and pass in the extra command line + if (m == _modules + 2) + { + _root_start = start; + _root_end = end; + str--; + str = stpcpy (str, buffer) + 1; + } + + mbm++; + } + _mbi_vbe = str; + + if (! quiet) + puts ("\nBootstrapping..."); +} + +PRIVATE static +void +Boot_info::get_minimum_map_address() +{ + FILE *f = fopen("/proc/sys/vm/mmap_min_addr", "r"); + if (!f) + return; + + int r = fscanf(f, "%ld", &_min_mappable_address); + fclose(f); + + // funny thing is that although /proc/sys/vm/mmap_min_addr might be + // readable according to the file permissions it might not actually work + // (a read returns EPERM, seen with 2.6.33), since at at least Ubuntu sets + // mmap_min_addr to 0x10000 we take this as the default value here + if (r == -1) + _min_mappable_address = 0x10000; + + _min_mappable_address + = (_min_mappable_address + (Config::PAGE_SIZE - 1)) & Config::PAGE_MASK; +} + +PRIVATE static +void +Boot_info::find_x86_tls_base() +{ + // the base is different on 32 and 64 bit hosts, so we need to find the + // right one + // be very pessimistic and scan a larger range + + for (unsigned nr = 0; nr < 40; ++nr) + { + Ldt_user_desc desc; + int r = Emulation::get_thread_area(&desc, nr); + if (r == -38) + panic("get_thread_area not available"); + if (!r) + { + Emulation::set_host_tls_base(nr); + return; + } + } + + panic("finding TLS base did not work"); +} + +PUBLIC static inline +void +Boot_info::reset_checksum_ro() +{} + +IMPLEMENT inline NEEDS ["mem_layout.h"] +Address +Boot_info::mbi_phys() +{ + return Mem_layout::Multiboot_frame; +} + +IMPLEMENT inline NEEDS ["mem_layout.h"] +Multiboot_info * +Boot_info::mbi_virt() +{ + return reinterpret_cast + (Mem_layout::Physmem + mbi_phys()); +} + +PUBLIC static inline +Multiboot_vbe_controller * +Boot_info::mbi_vbe() +{ + return reinterpret_cast(_mbi_vbe); +} + +PUBLIC static inline +unsigned long +Boot_info::mbi_size() +{ + return (unsigned long)mbi_vbe() + + sizeof (Multiboot_vbe_controller) + sizeof (Multiboot_vbe_mode) + - (unsigned long)mbi_virt(); +} + +PUBLIC static inline +int +Boot_info::fd() +{ return _fd; } + +PUBLIC static inline +pid_t +Boot_info::pid() +{ return _pid; } + +PUBLIC static inline +char ** +Boot_info::args() +{ return _args; } + +PUBLIC static inline +bool +Boot_info::irq0_disabled() +{ return _irq0_disabled; } + +PUBLIC static inline +unsigned long +Boot_info::input_start() +{ return fb_virt() + fb_size(); } + +PUBLIC static inline +unsigned long +Boot_info::input_size() +{ return _input_size; } + +PUBLIC static inline +unsigned long +Boot_info::fb_size() +{ return _fb_size; } + +PUBLIC static inline +Address +Boot_info::fb_virt() +{ return _fb_virt; } + +PUBLIC static inline +Address +Boot_info::fb_phys() +{ return _fb_phys; } + +PUBLIC static inline +unsigned int +Boot_info::fb_width() +{ return _fb_width; } + +PUBLIC static inline +unsigned int +Boot_info::fb_height() +{ return _fb_height; } + +PUBLIC static inline +unsigned int +Boot_info::fb_depth() +{ return _fb_depth; } + +PUBLIC static inline +const char * +Boot_info::fb_program() +{ return _fb_program; } + +PUBLIC static inline +const char * +Boot_info::net_program() +{ return _net_program; } + +PUBLIC static inline +bool +Boot_info::net() +{ return _net; } + +PUBLIC static inline +const char * +Boot_info::irq0_path() +{ return _irq0_program; } + +PUBLIC static inline +bool +Boot_info::emulate_clisti() +{ return _emulate_clisti; } + +PUBLIC static inline +unsigned long +Boot_info::sigma0_start() +{ return _sigma0_start; } + +PUBLIC static inline +unsigned long +Boot_info::sigma0_end() +{ return _sigma0_end; } + +PUBLIC static inline +unsigned long +Boot_info::root_start() +{ return _root_start; } + +PUBLIC static inline +unsigned long +Boot_info::root_end() +{ return _root_end; } + +PUBLIC static inline +unsigned long +Boot_info::min_mappable_address() +{ return _min_mappable_address; } + +PUBLIC inline static +unsigned +Boot_info::get_checksum_ro(void) +{ return 0; } + +PUBLIC inline static +unsigned +Boot_info::get_checksum_rw(void) +{ return 0; } + + +PUBLIC static +void +Boot_info::set_wait() +{ Koptions::o()->flags |= Koptions::F_wait; } + +PUBLIC static +void +Boot_info::kmemsize(unsigned int k) +{ Koptions::o()->kmemsize = k; } + +PUBLIC static +void +Boot_info::set_jdb_cmd(const char *j) +{ + strncpy(Koptions::o()->jdb_cmd, j, sizeof(Koptions::o()->jdb_cmd)); + Koptions::o()->jdb_cmd[sizeof(Koptions::o()->jdb_cmd) - 1] = 0; +} + diff --git a/kernel/fiasco/src/kern/ux/config-ux.cpp b/kernel/fiasco/src/kern/ux/config-ux.cpp new file mode 100644 index 00000000..7a43cad4 --- /dev/null +++ b/kernel/fiasco/src/kern/ux/config-ux.cpp @@ -0,0 +1,55 @@ +/* + * Fiasco-UX + * Architecture specific config code + */ + +INTERFACE: + +#include "idt_init.h" + +EXTENSION class Config +{ +public: + enum + { + // cannot access user memory directly + Access_user_mem = No_access_user_mem, + + SCHED_PIT = 0, + + Scheduler_one_shot = false, + Scheduler_mode = SCHED_PIT, + Scheduler_granularity = 10000U, + Default_time_slice = 10 * Scheduler_granularity, + + scheduler_irq_vector = 0x20U, + + // Size of the host address space, change the following if your host + // address space size is different, do not go below 2GB (0x80000000) + Host_as_size = 0xc0000000U, + + Kip_timer_uses_rdtsc = false, + Pic_prio_modify = true, + }; + + static const bool hlt_works_ok = true; + + static const char char_micro; + + enum { + Is_ux = 1, + }; +}; + +IMPLEMENTATION[ux]: + +#include +KIP_KERNEL_FEATURE("io_prot"); + +char const Config::char_micro = '\265'; +const char *const Config::kernel_warn_config_string = 0; + +IMPLEMENT FIASCO_INIT +void +Config::init_arch() +{} diff --git a/kernel/fiasco/src/kern/ux/context-ux.cpp b/kernel/fiasco/src/kern/ux/context-ux.cpp new file mode 100644 index 00000000..32df2003 --- /dev/null +++ b/kernel/fiasco/src/kern/ux/context-ux.cpp @@ -0,0 +1,59 @@ +INTERFACE[ux]: + +EXTENSION class Context +{ +protected: + enum { Gdt_user_entries = 3 }; + struct { Unsigned64 v[2]; } _gdt_user_entries[Gdt_user_entries]; // type struct Ldt_user_desc + + bool _is_native; // thread can call Linux host system calls + Unsigned32 _es, _fs, _gs; +}; + +// --------------------------------------------------------------------- +IMPLEMENTATION[ux]: + +#include "utcb_init.h" + +IMPLEMENT inline +void +Context::switch_fpu (Context *) +{} + +PUBLIC inline +bool +Context::is_native() +{ return _is_native; } + +PROTECTED inline NEEDS["utcb_init.h"] +void +Context::arch_setup_utcb_ptr() +{ + _gs = _fs = Utcb_init::utcb_segment(); +} + +PROTECTED inline +void +Context::switch_gdt_user_entries(Context *to) +{ + Mword *trampoline_page = (Mword *) Kmem::phys_to_virt(Mem_layout::Trampoline_frame); + Space *tos = to->vcpu_aware_space(); + + if (EXPECT_FALSE(!tos)) + return; + + for (int i = 0; i < 3; i++) + if (to == this + || _gdt_user_entries[i].v[0] != to->_gdt_user_entries[i].v[0] + || _gdt_user_entries[i].v[1] != to->_gdt_user_entries[i].v[1]) + { + memcpy(trampoline_page + 1, &to->_gdt_user_entries[i], + sizeof(_gdt_user_entries[0])); + Trampoline::syscall(tos->pid(), 243, + Mem_layout::Trampoline_page + sizeof(Mword)); + } + + // update the global UTCB pointer to make the thread find its UTCB + // using fs:[0] + Mem_layout::user_utcb_ptr(current_cpu()) = to->utcb().usr(); +} diff --git a/kernel/fiasco/src/kern/ux/cpu-ux.cpp b/kernel/fiasco/src/kern/ux/cpu-ux.cpp new file mode 100644 index 00000000..dc3bb9e8 --- /dev/null +++ b/kernel/fiasco/src/kern/ux/cpu-ux.cpp @@ -0,0 +1,220 @@ +/* + * Fiasco-UX + * Architecture specific cpu init code + */ + +INTERFACE[ux]: + +class Tss; + +EXTENSION class Cpu +{ +public: + static Mword kern_ds() { return _kern_ds; } + static Mword kern_es() { return _kern_es; } +private: + static Tss *tss asm ("CPU_TSS"); + static int msr_dev; + static unsigned long _gs asm ("CPU_GS"); + static unsigned long _fs asm ("CPU_FS"); + static Mword _kern_ds asm ("KERN_DS"); + static Mword _kern_es asm ("KERN_ES"); + + int _tid; +}; + +// ----------------------------------------------------------------------- +IMPLEMENTATION[ux]: + +#include +#include +#include +#include + +#include "div32.h" +#include "emulation.h" +#include "gdt.h" +#include "initcalls.h" +#include "processor.h" +#include "regdefs.h" +#include "tss.h" + +Proc::Status volatile Proc::virtual_processor_state = 0; +Tss *Cpu::tss; +int Cpu::msr_dev = -1; +unsigned long Cpu::_gs; // for mp: percpu +unsigned long Cpu::_fs; // for mp: percpu +unsigned long Cpu::_kern_ds; +unsigned long Cpu::_kern_es; + +IMPLEMENT FIASCO_INIT_CPU +void +Cpu::init() +{ + identify(); + + // Get original es and ds to be used for RESET_KERNEL_SEGMENTS_FORCE_DS_ES + _kern_ds = get_ds(); + _kern_es = get_es(); + + // No Sysenter Support for Fiasco-UX + _features &= ~FEAT_SEP; + + // Determine CPU frequency + FILE *fp; + if ((fp = fopen ("/proc/cpuinfo", "r")) != NULL) + { + char buffer[128]; + float val; + + while (fgets (buffer, sizeof (buffer), fp)) + if (sscanf (buffer, "cpu MHz%*[^:]: %f", &val) == 1) + { + _frequency = (Unsigned64)(val * 1000) * 1000; + scaler_tsc_to_ns = muldiv (1 << 27, 1000000000, _frequency); + scaler_tsc_to_us = muldiv (1 << 27, 32 * 1000000, _frequency); + scaler_ns_to_tsc = muldiv (1 << 27, _frequency, 1000000000); + break; + } + + fclose (fp); + } + + if (this == _boot_cpu) + { + // XXX hardcoded + msr_dev = open("/dev/msr", O_RDWR); + if (msr_dev == -1) + msr_dev = open("/dev/cpu/0/msr", O_RDWR); + } + + _tid = phys_id_direct(); +} + +PUBLIC +void +Cpu::print() const +{ + printf ("CPU[%u:%u]: %s (%X:%X:%X:%X) Model: %s at %llu MHz\n\n", + id(), phys_id(), + vendor_str(), family(), model(), stepping(), brand(), model_str(), + div32(frequency(), 1000000)); +} + +IMPLEMENT inline +unsigned +Cpu::phys_id() const +{ return _tid; } + +PUBLIC static inline +void +Cpu::set_fast_entry (void (*)(void)) +{} + +PUBLIC static FIASCO_INIT +void +Cpu::init_tss (Address tss_mem) +{ + tss = reinterpret_cast(tss_mem); + tss->_ss0 = Gdt::gdt_data_kernel; +} + +PUBLIC static inline +Tss* +Cpu::get_tss () +{ return tss; } + +PUBLIC static inline +void +Cpu::enable_rdpmc() +{ +} + +IMPLEMENT inline +int +Cpu::can_wrmsr() const +{ + return msr_dev != -1; +} + +PUBLIC static +Unsigned64 +Cpu::rdmsr (Unsigned32 reg) +{ + Unsigned64 msr; + + if (lseek(msr_dev, reg, SEEK_SET) >= 0) + read(msr_dev, &msr, sizeof(msr)); + + return msr; +} + +PUBLIC static inline +Unsigned64 +Cpu::rdpmc (Unsigned32, Unsigned32 reg) +{ + return rdmsr(reg); +} + +PUBLIC static +void +Cpu::wrmsr (Unsigned64 msr, Unsigned32 reg) +{ + if (lseek(msr_dev, reg, SEEK_SET) >= 0) + write(msr_dev, &msr, sizeof(msr)); +} + +PUBLIC static inline +void +Cpu::wrmsr (Unsigned32 low, Unsigned32 high, Unsigned32 reg) +{ + Unsigned64 msr = ((Unsigned64)high << 32) | low; + wrmsr(msr, reg); +} + +PUBLIC static inline +void +Cpu::debugctl_enable() +{} + +PUBLIC static inline +void +Cpu::debugctl_disable() +{} + +PUBLIC static inline +void +Cpu::set_fs(Unsigned32 val) +{ _fs = val; } + +PUBLIC static inline +void +Cpu::set_gs(Unsigned32 val) +{ _gs = val; } + +PUBLIC static inline +Unsigned32 +Cpu::get_fs() +{ return _fs; } + +PUBLIC static inline +Unsigned32 +Cpu::get_gs() +{ return _gs; } + +// ------------------------------------------------------------------------ +IMPLEMENTATION[ux && !mp]: + +PUBLIC static inline +unsigned +Cpu::phys_id_direct() +{ return 0; } + +// ------------------------------------------------------------------------ +IMPLEMENTATION[ux && mp]: + +PUBLIC static inline NEEDS["emulation.h"] +unsigned +Cpu::phys_id_direct() +{ return Emulation::gettid(); } + diff --git a/kernel/fiasco/src/kern/ux/emulation.cpp b/kernel/fiasco/src/kern/ux/emulation.cpp new file mode 100644 index 00000000..ecec83c3 --- /dev/null +++ b/kernel/fiasco/src/kern/ux/emulation.cpp @@ -0,0 +1,286 @@ +/* + * Fiasco-UX + * Emulation Code for some processor internals (registers, instructions) + */ + +INTERFACE: + +#include +#include "mem_layout.h" + +class Idt_entry; + +struct Ldt_user_desc // work around glibc naming mess +{ + unsigned int entry_number; + unsigned long base_addr; + unsigned int limit; + unsigned int seg_32bit:1; + unsigned int contents:2; + unsigned int read_exec_only:1; + unsigned int limit_in_pages:1; + unsigned int seg_not_present:1; + unsigned int useable:1; +}; + +class Pseudo_descriptor; + +class Emulation +{ +private: + static Address _page_dir_addr asm ("PAGE_DIR_ADDR"); + static Address _page_fault_addr asm ("PAGE_FAULT_ADDR"); + static Idt_entry const *_idt_base; + static unsigned short _idt_limit; + static unsigned _host_tls_base; +}; + +IMPLEMENTATION: + +#include +#include +#include +#include "x86desc.h" + +Address Emulation::_page_dir_addr; +Address Emulation::_page_fault_addr; +Idt_entry const *Emulation::_idt_base; +unsigned short Emulation::_idt_limit; +unsigned Emulation::_host_tls_base; + +/** + * Return page directory base address (register cr3) + * @return Page Directory Base Address + */ +PUBLIC static inline +Address +Emulation::pdir_addr() +{ + return _page_dir_addr; +} + +/** + * Set page directory base address (register cr3) + * @param addr New Page Directory Base Address + */ +PUBLIC static inline +void +Emulation::set_pdir_addr (Address addr) +{ + _page_dir_addr = addr; +} + +/** + * Set page fault address (register cr2) + * @param addr Page Fault Address + */ +PUBLIC static inline +void +Emulation::set_page_fault_addr (Address addr) +{ + _page_fault_addr = addr; +} + +/** + * Emulate LIDT instruction + * @param desc IDT pseudo descriptor + */ +PUBLIC static inline NEEDS["x86desc.h"] +void +Emulation::lidt (Pseudo_descriptor *desc) +{ + _idt_base = reinterpret_cast(desc->base()); + _idt_limit = desc->limit(); +} + +/** + * Emulate SIDT instruction + * @param desc IDT pseudo descriptor + */ +PUBLIC static inline NEEDS["x86desc.h"] +void +Emulation::sidt (Pseudo_descriptor *desc) +{ + *desc = Pseudo_descriptor((Address)_idt_base, _idt_limit); +} + +PUBLIC static inline NEEDS["x86desc.h"] +Mword +Emulation::idt_vector (Mword trap, bool user) +{ + Idt_entry const *gate = _idt_base + trap; + + // IDT limit check + if (gate >= (_idt_base + _idt_limit)) + return 0; + + // Gate permission check + if (user && !(gate->access() & X86desc::Access_user)) + return 0; + + assert(gate->present()); + + return gate->offset(); +} + +PUBLIC static inline NEEDS["x86desc.h"] +bool +Emulation::idt_vector_present (Mword vector) +{ + Idt_entry const *gate = _idt_base + vector; + + if (gate >= (_idt_base + _idt_limit)) + return false; + + return gate->present(); +} + +PUBLIC static inline +Mword +Emulation::kernel_cs() +{ + unsigned short cs; + asm volatile ("movw %%cs, %0" : "=g" (cs)); + return cs; +} + +PUBLIC static inline +Mword +Emulation::kernel_ss() +{ + unsigned short ss; + asm volatile ("movw %%ss, %0" : "=g" (ss)); + return ss; +} + +PUBLIC static inline NEEDS [] +void +Emulation::modify_ldt (unsigned entry, unsigned long base_addr, unsigned limit) +{ + Ldt_user_desc ldt; + + ldt.entry_number = entry; + ldt.base_addr = base_addr; + ldt.limit = limit; + ldt.seg_32bit = 1; + ldt.contents = 0; + ldt.read_exec_only = 0; + ldt.limit_in_pages = 0; + ldt.seg_not_present = 0; + ldt.useable = 1; + + asm volatile ("int $0x80" : : "a" (__NR_modify_ldt), + "b" (1), + "c" (&ldt), "m" (ldt), + "d" (sizeof (ldt))); +} + +PUBLIC static +void +Emulation::set_host_tls_base(unsigned b) +{ + _host_tls_base = b; +} + +PUBLIC static inline +unsigned +Emulation::host_tls_base() +{ return _host_tls_base; } + +PUBLIC static inline +int +Emulation::get_thread_area(Ldt_user_desc *desc, unsigned entry_number) +{ + int result; + desc->entry_number = entry_number; + +#ifndef __NR_get_thread_area +#define __NR_get_thread_area 244 +#endif + asm volatile ("int $0x80" : "=a" (result) + : "0" (__NR_get_thread_area), + "b" (desc), "m" (*desc)); + + if (EXPECT_FALSE(result == -38)) // -ENOSYS + printf("Your kernel does not support the get/set_thread_area system calls!\n" + "The requested feature will not work.\n"); + return result; +} + +PUBLIC static inline NEEDS [, ] +void +Emulation::thread_area_host (unsigned entry) +{ + Ldt_user_desc desc; + int result; + enum { NUM_TLS = 3 }; + static int called[NUM_TLS]; + +#ifndef __NR_set_thread_area +#define __NR_set_thread_area 243 +#endif + + assert(_host_tls_base <= entry && entry < (_host_tls_base + NUM_TLS)); + + if (called[entry - _host_tls_base]) + return; + + called[entry - _host_tls_base] = 1; + + result = get_thread_area(&desc, entry); + assert(!result); + + if (!desc.base_addr || !desc.limit) + { + desc.base_addr = 2; + desc.limit = 3; + desc.seg_32bit = 1; + desc.contents = 0; + desc.read_exec_only = 0; + desc.limit_in_pages = 0; + desc.seg_not_present = 0; + desc.useable = 1; + } + + asm volatile ("int $0x80" : "=a" (result) + : "0" (__NR_set_thread_area), + "b" (&desc), "m" (desc)); + + assert(!result); +} + +// ------------------------------------------------------------------------ +IMPLEMENTATION[ux && mp]: + +PUBLIC static inline +int +Emulation::gettid() +{ + int tid; + asm volatile("int $0x80" : "=a" (tid) : "0" (__NR_gettid) : "memory"); + return tid; +} + +PUBLIC static +int +Emulation::spawn_cpu_thread(Address ip) +{ + int result; + + asm volatile ("int $0x80 \t\n" + "cmp $0, %%eax \t\n" + "jne 1f \t\n" + "jmp *%[ip] \t\n" + "1: \t\n" + : "=a" (result) + : "0" (__NR_clone), + "b" (CLONE_VM | CLONE_FILES), + "c" (0), + "d" (0), + "D" (0), + [ip] "r" (ip) + : "memory"); + + assert(result > 0); + return result; +} diff --git a/kernel/fiasco/src/kern/ux/fb.cpp b/kernel/fiasco/src/kern/ux/fb.cpp new file mode 100644 index 00000000..8c7f4412 --- /dev/null +++ b/kernel/fiasco/src/kern/ux/fb.cpp @@ -0,0 +1,150 @@ +// +// Framebuffer handling for Fiasco-UX +// + +INTERFACE: + +#include "multiboot.h" + +class Fb +{ +public: + static void init(); + static void enable(); + +private: + static void bootstrap(); + static void setup_mbi(); + static void set_color_mapping (Multiboot_vbe_mode *vbi); +}; + +// ------------------------------------------------------------------------ +IMPLEMENTATION: + +#include +#include +#include +#include "boot_info.h" +#include "initcalls.h" +#include "irq_chip.h" +#include "kmem.h" +#include "pic.h" +#include "warn.h" + +IMPLEMENT FIASCO_INIT +void +Fb::bootstrap() +{ + char s_fd[3]; + char s_width[5]; + char s_height[5]; + char s_depth[3]; + char s_fbaddr[15]; + + snprintf (s_fd, sizeof (s_fd), "%u", Boot_info::fd()); + snprintf (s_fbaddr, sizeof (s_fbaddr), "%lu", Boot_info::fb_phys()); + snprintf (s_width, sizeof (s_width), "%u", Boot_info::fb_width()); + snprintf (s_height, sizeof (s_height), "%u", Boot_info::fb_height()); + snprintf (s_depth, sizeof (s_depth), "%u", Boot_info::fb_depth()); + + execl (Boot_info::fb_program(), Boot_info::fb_program(), + "-f", s_fd, "-s", s_fbaddr, + "-x", s_width, "-y", s_height, + "-d", s_depth, NULL); +} + +IMPLEMENT FIASCO_INIT +void +Fb::set_color_mapping(Multiboot_vbe_mode *vbi) +{ + switch (Boot_info::fb_depth()) + { + case 15: + vbi->red_mask_size = 5; vbi->red_field_position = 10; + vbi->green_mask_size = 5; vbi->green_field_position = 5; + vbi->blue_mask_size = 5; vbi->blue_field_position = 0; + break; + case 16: + vbi->red_mask_size = 5; vbi->red_field_position = 11; + vbi->green_mask_size = 6; vbi->green_field_position = 5; + vbi->blue_mask_size = 5; vbi->blue_field_position = 0; + break; + case 24: + vbi->red_mask_size = 8; vbi->red_field_position = 16; + vbi->green_mask_size = 8; vbi->green_field_position = 8; + vbi->blue_mask_size = 8; vbi->blue_field_position = 0; + break; + case 32: + vbi->red_mask_size = 8; vbi->red_field_position = 16; + vbi->green_mask_size = 8; vbi->green_field_position = 8; + vbi->blue_mask_size = 8; vbi->blue_field_position = 0; + break; + default: + WARN("Unknown frame buffer color depth %d.", Boot_info::fb_depth()); + break; + } +} + + +IMPLEMENT FIASCO_INIT +void +Fb::setup_mbi() +{ + if (!Boot_info::fb_size()) + return; + + Multiboot_info *mbi = Boot_info::mbi_virt(); + + struct Multiboot_vbe_controller *vbe = reinterpret_cast + (Boot_info::mbi_vbe()); + struct Multiboot_vbe_mode *vbi = reinterpret_cast + ((char *) vbe + sizeof (*vbe)); + + mbi->flags |= Multiboot_info::Video_info; + mbi->vbe_control_info = Boot_info::mbi_phys() + + ((char *) vbe - (char *) mbi); + mbi->vbe_mode_info = Boot_info::mbi_phys() + + ((char *) vbi - (char *) mbi); + vbe->total_memory = Boot_info::fb_size() >> 16; /* 2^16 == 1024 * 64 */ + vbi->phys_base = Boot_info::fb_virt(); + vbi->y_resolution = Boot_info::fb_height(); + vbi->x_resolution = Boot_info::fb_width(); + vbi->bits_per_pixel = Boot_info::fb_depth(); + vbi->bytes_per_scanline = Boot_info::fb_width() + * (Boot_info::fb_depth() + 7 >> 3); + + set_color_mapping(vbi); +} + +IMPLEMENT FIASCO_INIT +void +Fb::init() +{ + // Check if frame buffer is available + if (!Boot_info::fb_depth()) + return; + + // setup multiboot info + setup_mbi(); + + // Setup virtual interrupt + if (!Pic::setup_irq_prov(Pic::Irq_con, + Boot_info::fb_program(), bootstrap)) + { + puts ("Problems setting up console interrupt!"); + exit (1); + } + + Kip::k()->vhw()->set_desc(Vhw_entry::TYPE_FRAMEBUFFER, + Boot_info::fb_virt(), Boot_info::fb_size(), + Pic::Irq_con, + Pic::get_pid_for_irq_prov(Pic::Irq_con), 0); + Kip::k()->vhw()->set_desc(Vhw_entry::TYPE_INPUT, + Boot_info::input_start(), Boot_info::input_size(), + Pic::Irq_con, + Pic::get_pid_for_irq_prov(Pic::Irq_con), 0); + + printf ("Starting Framebuffer: %ux%u@%u\n\n", + Boot_info::fb_width(), Boot_info::fb_height(), + Boot_info::fb_depth()); +} diff --git a/kernel/fiasco/src/kern/ux/format.h b/kernel/fiasco/src/kern/ux/format.h new file mode 100644 index 00000000..1e7140cf --- /dev/null +++ b/kernel/fiasco/src/kern/ux/format.h @@ -0,0 +1,20 @@ +#ifndef __FIASCO_FORMAT_H +#define __FIASCO_FORMAT_H + +#ifndef ASSEMBLER + +/* This declaration is needed since printf is not checked per default + * when using with C++ */ + +#include + +__BEGIN_DECLS + +int printf(const char *format, ...) __attribute__((format (printf,1,2) )); + +__END_DECLS + +#endif + +#endif + diff --git a/kernel/fiasco/src/kern/ux/fpu-ux.cpp b/kernel/fiasco/src/kern/ux/fpu-ux.cpp new file mode 100644 index 00000000..8b47c1c2 --- /dev/null +++ b/kernel/fiasco/src/kern/ux/fpu-ux.cpp @@ -0,0 +1,68 @@ +/* + * Fiasco-UX + * Architecture specific floating point unit code + */ + +IMPLEMENTATION[ux && fpu]: + +#include +#include +#include "cpu.h" +#include "regdefs.h" +#include "space.h" + +PRIVATE static +void +Fpu::init_xsave(unsigned) +{} + +PRIVATE static +void +Fpu::init_disable() +{} + +/** + * Save FPU state in Fpu_state s. Distinguish between i387 and SSE state + * @param s Fpu_state to save context in + */ +IMPLEMENT +void +Fpu::save_state(Fpu_state *s) +{ + assert (s->state_buffer()); + + // FIXME: assume UP here (current_meme_space(0)) + ptrace(Cpu::boot_cpu()->features() & FEAT_FXSR ? PTRACE_GETFPXREGS : PTRACE_GETFPREGS, + Mem_space::current_mem_space(0)->pid(), NULL, s->state_buffer()); +} + +/** + * Restore FPU state from Fpu_state s. Distinguish between i387 and SSE state + * @param s Fpu_state to restore context from + */ +IMPLEMENT +void +Fpu::restore_state(Fpu_state *s) +{ + assert (s->state_buffer()); + + // FIXME: assume UP here (current_meme_space(0)) + ptrace(Cpu::boot_cpu()->features() & FEAT_FXSR ? PTRACE_SETFPXREGS : PTRACE_SETFPREGS, + Mem_space::current_mem_space(0)->pid(), NULL, s->state_buffer()); +} + +/** + * Disable FPU. Does nothing here. + */ +IMPLEMENT inline +void +Fpu::disable() +{} + +/** + * Enable FPU. Does nothing here. + */ +IMPLEMENT inline +void +Fpu::enable() +{} diff --git a/kernel/fiasco/src/kern/ux/glibc_getchar.cpp b/kernel/fiasco/src/kern/ux/glibc_getchar.cpp new file mode 100644 index 00000000..1ea8ccb9 --- /dev/null +++ b/kernel/fiasco/src/kern/ux/glibc_getchar.cpp @@ -0,0 +1,45 @@ +IMPLEMENTATION: + +#include +#include "console.h" +#include "filter_console.h" +#include "glibc_getchar.h" +#include "kernel_console.h" +#include "static_init.h" + +class Glibc_getchar : public Console +{}; + +PUBLIC +int +Glibc_getchar::getchar(bool blocking) +{ + (void)blocking; + return ::getchar(); +} + +PUBLIC +int +Glibc_getchar::write(char const *str, size_t len) +{ + (void)str; (void)len; + return 1; +} + +PUBLIC +Mword +Glibc_getchar::get_attributes() const +{ + return UX | IN; +} + +static void +glibc_flt_getchar_init() +{ + static Glibc_getchar c; + static Filter_console fcon(&c, 0); + + Kconsole::console()->register_console(&fcon); +} + +STATIC_INITIALIZER_P(glibc_flt_getchar_init, GDB_INIT_PRIO); diff --git a/kernel/fiasco/src/kern/ux/glue_libc_ux.cc b/kernel/fiasco/src/kern/ux/glue_libc_ux.cc new file mode 100644 index 00000000..45816af4 --- /dev/null +++ b/kernel/fiasco/src/kern/ux/glue_libc_ux.cc @@ -0,0 +1,24 @@ +#include +#include "libc_backend.h" +#include "console.h" + +int __libc_backend_outs(const char *s, size_t len) +{ + return write(1, s, len); +} + +int __libc_backend_ins( char *s, size_t len ) +{ + if(Console::stdin) { + size_t act = 0; + for(; act < len; act++) { + s[act]=Console::stdin->getchar(); + if(s[act]=='\r') { + act++; + break; + } + } + return act; + } else + return 0; +} diff --git a/kernel/fiasco/src/kern/ux/hostproc.cpp b/kernel/fiasco/src/kern/ux/hostproc.cpp new file mode 100644 index 00000000..2d4befaf --- /dev/null +++ b/kernel/fiasco/src/kern/ux/hostproc.cpp @@ -0,0 +1,136 @@ + +/* + * Fiasco-UX + * Functions for setting up host processes implementing tasks + */ + +INTERFACE: + +class Hostproc +{}; + +IMPLEMENTATION: + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "boot_info.h" +#include "config.h" +#include "cpu_lock.h" +#include "globals.h" +#include "lock_guard.h" +#include "mem_layout.h" +#include "panic.h" +#include "trampoline.h" + +PRIVATE static +void +Hostproc::setup() +{ + char **args = Boot_info::args(); + size_t arglen = 0; + + // Zero all args, making ps output pretty + do arglen += strlen (*args) + 1; while (*++args); + memset (*Boot_info::args(), 0, arglen); + + // Put task number into argv[0] for ps + snprintf (*Boot_info::args(), arglen, "[Task]"); + + fclose (stdin); + fclose (stdout); + fclose (stderr); + + sigset_t mask; + sigfillset (&mask); + check (!sigprocmask (SIG_UNBLOCK, &mask, NULL)); + + stack_t stack; + stack.ss_sp = (void *) Mem_layout::Trampoline_page; + stack.ss_size = Config::PAGE_SIZE; + stack.ss_flags = 0; + check (!sigaltstack (&stack, NULL)); + + struct sigaction action; + sigfillset (&action.sa_mask); + action.sa_flags = SA_ONSTACK | SA_SIGINFO; + action.sa_restorer = (void (*)()) 0xDEADC0DE; + action.sa_sigaction = (void (*)(int,siginfo_t*,void*)) + Mem_layout::Trampoline_page; + check (!sigaction (SIGSEGV, &action, NULL)); + + // Map trampoline page + check (mmap ((void *) Mem_layout::Trampoline_page, + Config::PAGE_SIZE, + PROT_READ | PROT_WRITE | PROT_EXEC, + MAP_SHARED | MAP_FIXED, + Boot_info::fd(), + Mem_layout::Trampoline_frame) != MAP_FAILED); + + ptrace (PTRACE_TRACEME, 0, NULL, NULL); + + raise (SIGUSR1); +} + +PUBLIC static +unsigned +Hostproc::create() +{ + Lock_guard guard(&cpu_lock); + + static unsigned long esp; + static Mword _stack[256]; + register pid_t pid; + + /* + * Careful with local variables here because we are changing the + * stack pointer for the fork system call. This ensures that the + * child gets its own COW stack rather than running on the parent + * stack. + */ + asm volatile("movl %%esp, %0 \n\t" + "movl %2, %%esp \n\t" + "call _ZN8Hostproc7do_forkEv\n\t" + "movl %0, %%esp \n\t" + : "=m" (esp), "=a" (pid) + : "r" (&_stack[sizeof(_stack) / sizeof(_stack[0])])); + + switch (pid) + { + case -1: // Failed + return 0; + + default: // Parent + int status; + check (waitpid (pid, &status, 0) == pid); + assert (WIFSTOPPED (status) && WSTOPSIG (status) == SIGUSR1); + + Trampoline::syscall (pid, __NR_munmap, 0, Mem_layout::Trampoline_page); + return pid; + } +} + +PRIVATE static +int +Hostproc::do_fork() +{ + // Make sure the child doesn't inherit any of our unflushed output + fflush (NULL); + + switch (pid_t pid = fork()) + { + case 0: // Child + setup(); + _exit(1); // unreached + + default: + return pid; + } +} diff --git a/kernel/fiasco/src/kern/ux/ipi-ux.cpp b/kernel/fiasco/src/kern/ux/ipi-ux.cpp new file mode 100644 index 00000000..59a69550 --- /dev/null +++ b/kernel/fiasco/src/kern/ux/ipi-ux.cpp @@ -0,0 +1,75 @@ +INTERFACE [mp]: + +EXTENSION class Ipi +{ +private: + Unsigned32 _lcpu; + +public: + enum Message { Request = 'r', Global_request = 'g', Debug = 'd' }; +}; + +//--------------------------------------------------------------------------- +IMPLEMENTATION[!mp]: + +//--------------------------------------------------------------------------- +IMPLEMENTATION[mp]: + +#include + +#include "cpu.h" +#include "pic.h" + +PUBLIC inline +Ipi::Ipi() : _lcpu(~0) +{} + +IMPLEMENT +void +Ipi::init() +{ + _lcpu = current_cpu(); + Pic::setup_ipi(_lcpu, Cpu::cpus.cpu(_lcpu).phys_id()); +} + +PUBLIC static inline NEEDS[] +void +Ipi::eoi(Message) +{ +} + +PUBLIC static inline NEEDS[, "pic.h"] +void +Ipi::send(Message m, unsigned from_cpu, unsigned to_cpu) +{ + printf("Sending IPI:%d to cpu%d\n", m, _lcpu); + Pic::send_ipi(_lcpu, m); +} + +PUBLIC static inline NEEDS[, "cpu.h", "pic.h"] +void +Ipi::bcast(Message m, unsigned from_cpu) +{ + printf("Bcast IPI:%d\n", m); + for (unsigned i = 0; i < Config::Max_num_cpus; ++i) + if (Cpu::online(i)) + Pic::send_ipi(i, m); +} + +PUBLIC static +unsigned long +Ipi::gate(unsigned char data) +{ + Message m = (Message)data; + + switch (m) + { + case Global_request: return APIC_IRQ_BASE + 2; + case Request: return APIC_IRQ_BASE - 1; + case Debug: return APIC_IRQ_BASE - 2; + default: + printf("Unknown request: %c(%d)\n", m, m); + break; + } + return ~0UL; +} diff --git a/kernel/fiasco/src/kern/ux/irq-ux.cpp b/kernel/fiasco/src/kern/ux/irq-ux.cpp new file mode 100644 index 00000000..e69de29b diff --git a/kernel/fiasco/src/kern/ux/irq0.c b/kernel/fiasco/src/kern/ux/irq0.c new file mode 100644 index 00000000..601eda84 --- /dev/null +++ b/kernel/fiasco/src/kern/ux/irq0.c @@ -0,0 +1,38 @@ + +#include +#include +#include +#include +#include +#include + +int main (void) { + + sigset_t blocked; + struct itimerval t; + int sig; + + sigemptyset (&blocked); + sigaddset (&blocked, SIGALRM); + sigprocmask (SIG_BLOCK, &blocked, NULL); + + t.it_interval.tv_sec = t.it_value.tv_sec = 0; + t.it_interval.tv_usec = t.it_value.tv_usec = 10000; + setitimer (ITIMER_REAL, &t, NULL); + + for (;;) + { + switch (sigwait (&blocked, &sig)) + { + case 0: + if (write (0, "T", 1) != -1) + continue; + + case -1: + if (errno != EINTR) + return 1; + } + } + + return 0; +} diff --git a/kernel/fiasco/src/kern/ux/kernel_thread-ux.cpp b/kernel/fiasco/src/kern/ux/kernel_thread-ux.cpp new file mode 100644 index 00000000..a95e462e --- /dev/null +++ b/kernel/fiasco/src/kern/ux/kernel_thread-ux.cpp @@ -0,0 +1,106 @@ +INTERFACE: + +EXTENSION class Kernel_thread +{ +public: + static int init_done(); + +private: + static int free_initcall_section_done; +}; + +IMPLEMENTATION[ux]: + +#include +#include +#include "fb.h" +#include "kdb_ke.h" +#include "koptions.h" +#include "net.h" +#include "mem_layout.h" +#include "pic.h" +#include "trap_state.h" +#include "usermode.h" + +int Kernel_thread::free_initcall_section_done; + +IMPLEMENT inline +int +Kernel_thread::init_done() +{ + return free_initcall_section_done; +} + +IMPLEMENT inline NEEDS [, , "mem_layout.h"] +void +Kernel_thread::free_initcall_section() +{ + munmap((void*)&Mem_layout::initcall_start, + &Mem_layout::initcall_end - &Mem_layout::initcall_start); + free_initcall_section_done = 1; +} + +static void ux_termination_handler() +{ + puts ("\nExiting, wait..."); + + Helping_lock::threading_system_active = false; + signal (SIGIO, SIG_IGN); // Ignore hardware interrupts + // This is a great hack to delete the processes on fiasco UX + extern char _boot_sys_end[]; + ::Kobject_dbg::Iterator c = ::Kobject_dbg::_kobjects.begin(); + while (c != ::Kobject_dbg::_kobjects.end()) + { + ::Kobject_dbg::Iterator n = c; + ++n; + Kobject *o = Kobject::from_dbg(c); + if ((void*)o > (void*)_boot_sys_end) + { + // printf("Zapp: %p (%s)\n", o, o->kobj_type()); + delete o; + } + c = n; + } + + fflush(0); // Flush output stream +} + + +IMPLEMENT FIASCO_INIT +void +Kernel_thread::bootstrap_arch() +{ + // install slow trap handler + nested_trap_handler = Trap_state::base_handler; + Trap_state::base_handler = thread_handle_trap; + + if (Koptions::o()->opt(Koptions::F_jdb_cmd)) + kdb_ke_sequence(Koptions::o()->jdb_cmd); + + atexit(ux_termination_handler); + boot_app_cpus(); +} + +//-------------------------------------------------------------------------- +IMPLEMENTATION [!mp]: + +static void inline +Kernel_thread::boot_app_cpus() +{} + + +//-------------------------------------------------------------------------- +IMPLEMENTATION [mp]: + +static void +Kernel_thread::boot_app_cpus() +{ + printf("MP: launching APs...\n"); + if (0) + { + extern char _tramp_mp_entry[]; + printf("new child: %d [%d]\n", + Emulation::spawn_cpu_thread((Address)_tramp_mp_entry), + Emulation::gettid()); + } +} diff --git a/kernel/fiasco/src/kern/ux/kip_init-ux.cpp b/kernel/fiasco/src/kern/ux/kip_init-ux.cpp new file mode 100644 index 00000000..af0658fe --- /dev/null +++ b/kernel/fiasco/src/kern/ux/kip_init-ux.cpp @@ -0,0 +1,96 @@ +IMPLEMENTATION [ux]: + +#include "boot_info.h" +#include "multiboot.h" +#include "kip.h" +#include + +PUBLIC static FIASCO_INIT +void +Kip_init::setup_user_virtual(Kip *kinfo) +{ + // start at 64k because on some distributions (like Ubuntu 8.04) it's + // not allowed to map below a certain treshold + kinfo->add_mem_region(Mem_desc(Boot_info::min_mappable_address(), + Mem_layout::User_max - 1, + Mem_desc::Conventional, true)); +} + +PRIVATE static FIASCO_INIT +void +Kip_init::setup_ux(Kip *k) +{ + Multiboot_module *mbm = reinterpret_cast + (Kmem::phys_to_virt (Boot_info::mbi_virt()->mods_addr)); + k->user_ptr = Boot_info::mbi_phys(); + Mem_desc *m = k->mem_descs(); + + // start at 64k because on some distributions (like Ubuntu 8.04) it's + // not allowed to map below a certain treshold + *(m++) = Mem_desc(Boot_info::min_mappable_address(), + ((Boot_info::mbi_virt()->mem_upper + 1024) << 10) - 1, + Mem_desc::Conventional); + *(m++) = Mem_desc(Kmem::kernel_image_start(), Kmem::kcode_end() - 1, + Mem_desc::Reserved); + + mbm++; + k->sigma0_ip = mbm->reserved; + if ((Boot_info::sigma0_start() & Config::PAGE_MASK) + != ((Boot_info::sigma0_end() + (Config::PAGE_SIZE-1)) + & Config::PAGE_MASK)) + *(m++) = Mem_desc(Boot_info::sigma0_start() & Config::PAGE_MASK, + ((Boot_info::sigma0_end() + (Config::PAGE_SIZE - 1)) + & Config::PAGE_MASK) - 1, + Mem_desc::Reserved); + + mbm++; + k->root_ip = mbm->reserved; + if ((Boot_info::root_start() & Config::PAGE_MASK) + != ((Boot_info::root_end() + (Config::PAGE_SIZE-1)) & Config::PAGE_MASK)) + *(m++) = Mem_desc(Boot_info::root_start() & Config::PAGE_MASK, + ((Boot_info::root_end() + (Config::PAGE_SIZE - 1)) + & Config::PAGE_MASK) - 1, + Mem_desc::Bootloader); + + unsigned long version_size = 0; + for (char const *v = k->version_string(); *v; ) + { + unsigned l = strlen(v) + 1; + v += l; + version_size += l; + } + + version_size += 2; + + k->vhw_offset = (k->offset_version_strings << 4) + version_size; + + k->vhw()->init(); + + unsigned long mod_start = ~0UL; + unsigned long mod_end = 0; + + mbm++; + + if (Boot_info::mbi_virt()->mods_count <= 3) + return; + + for (unsigned i = 0; i < Boot_info::mbi_virt()->mods_count - 3; ++i) + { + if (mbm[i].mod_start < mod_start) + mod_start = mbm[i].mod_start; + + if (mbm[i].mod_end > mod_end) + mod_end = mbm[i].mod_end; + } + + mod_start &= ~(Config::PAGE_SIZE - 1); + mod_end = (mod_end + Config::PAGE_SIZE -1) & ~(Config::PAGE_SIZE - 1); + + if (mod_end > mod_start) + *(m++) = Mem_desc(mod_start, mod_end - 1, Mem_desc::Bootloader); + + *(m++) = Mem_desc(Boot_info::mbi_phys(), + ((Boot_info::mbi_phys() + Boot_info::mbi_size() + + Config::PAGE_SIZE-1) & Config::PAGE_MASK) - 1, + Mem_desc::Bootloader); +} diff --git a/kernel/fiasco/src/kern/ux/kmem-ux.cpp b/kernel/fiasco/src/kern/ux/kmem-ux.cpp new file mode 100644 index 00000000..ef384dcd --- /dev/null +++ b/kernel/fiasco/src/kern/ux/kmem-ux.cpp @@ -0,0 +1,133 @@ +INTERFACE [ux]: + +class Kernel_task; + +EXTENSION class Kmem +{ +protected: + static Pdir *kdir; ///< Kernel page directory + + friend class Kernel_task; +}; + +IMPLEMENTATION [ux]: + +#include +#include +#include + +#include "kmem_alloc.h" +#include "emulation.h" + + +IMPLEMENT inline Mword Kmem::is_io_bitmap_page_fault(Address) +{ return false; } + +IMPLEMENT inline +Mword +Kmem::is_ipc_page_fault(Address addr, Mword error) +{ return addr < mem_user_max && (error & PF_ERR_REMTADDR); } + +IMPLEMENT inline NEEDS ["regdefs.h"] +Mword +Kmem::is_kmem_page_fault(Address addr, Mword error) +{ return !(addr < mem_user_max && (error & PF_ERR_USERADDR)); } + +/** + * Compute physical address from a kernel-virtual address. + * @param addr a virtual address + * @return corresponding physical address if a mappings exists. + * -1 otherwise. + */ +IMPLEMENT inline NEEDS["paging.h","std_macros.h"] +Address +Kmem::virt_to_phys (const void *addr) +{ + Address a = reinterpret_cast
(addr); + + if (EXPECT_TRUE(Mem_layout::in_pmem(a))) + return Mem_layout::pmem_to_phys(a); + + return kdir->virt_to_phys(a); +} + +PUBLIC static inline +Address Kmem::kernel_image_start() +{ return Mem_layout::Kernel_start_frame; } + +IMPLEMENT inline Address Kmem::kcode_start() +{ return Mem_layout::Kernel_start_frame; } + +IMPLEMENT inline Address Kmem::kcode_end() +{ return Mem_layout::Kernel_end_frame; } + +PUBLIC static FIASCO_INIT +void +Kmem::init_mmu(Cpu const &boot_cpu) +{ + Kmem_alloc *const alloc = Kmem_alloc::allocator(); + + kdir = (Pdir*)alloc->alloc(Config::PAGE_SHIFT); + memset (kdir, 0, Config::PAGE_SIZE); + + Pdir::have_superpages(boot_cpu.superpages()); + if (boot_cpu.features() & FEAT_PGE) + { + Pt_entry::enable_global(); + } + + // set up the kernel mapping for physical memory. mark all pages as + // referenced and modified (so when touching the respective pages + // later, we save the CPU overhead of marking the pd/pt entries like + // this) + + // we also set up a one-to-one virt-to-phys mapping for two reasons: + // (1) so that we switch to the new page table early and re-use the + // segment descriptors set up by bootstrap.c. (we'll set up our own + // descriptors later.) (2) a one-to-one phys-to-virt mapping in the + // kernel's page directory sometimes comes in handy + kdir->map(0, Virt_addr(Mem_layout::Physmem), Virt_size(Mem_layout::pmem_size), + Pt_entry::Writable | Pt_entry::Referenced | Pt_entry::global(), + Pdir::super_level(), pdir_alloc(alloc)); + + // now switch to our new page table + Emulation::set_pdir_addr (Mem_layout::pmem_to_phys (kdir)); + + // map the cpu_page we allocated earlier just before io_bitmap + assert((Mem_layout::Io_bitmap & ~Config::SUPERPAGE_MASK) == 0); + + if (boot_cpu.superpages() + && Config::SUPERPAGE_SIZE - (pmem_cpu_page & ~Config::SUPERPAGE_MASK) < 0x10000) + { + // can map as 4MB page because the cpu_page will land within a + // 16-bit range from io_bitmap + *(kdir->walk(Virt_addr(Mem_layout::Io_bitmap - Config::SUPERPAGE_SIZE), + Pdir::Super_level, pdir_alloc(alloc)).e) + = (pmem_cpu_page & Config::SUPERPAGE_MASK) + | Pt_entry::Pse_bit + | Pt_entry::Writable | Pt_entry::Referenced + | Pt_entry::Dirty | Pt_entry::global(); + + cpu_page_vm = (pmem_cpu_page & ~Config::SUPERPAGE_MASK) + + (Mem_layout::Io_bitmap - Config::SUPERPAGE_SIZE); + } + else + { + Pdir::Iter pt = kdir->walk(Virt_addr(Mem_layout::Io_bitmap - Config::PAGE_SIZE), 100, pdir_alloc(alloc)); + + *pt.e = pmem_cpu_page | Pt_entry::Valid | Pt_entry::Writable + | Pt_entry::Referenced | Pt_entry::Dirty + | Pt_entry::global(); + + cpu_page_vm = Mem_layout::Io_bitmap - Config::PAGE_SIZE; + } + + if (mmap ((void *) cpu_page_vm, Config::PAGE_SIZE, PROT_READ + | PROT_WRITE, MAP_SHARED | MAP_FIXED, Boot_info::fd(), pmem_cpu_page) + == MAP_FAILED) + printf ("CPU page mapping failed: %s\n", strerror (errno)); + + Cpu::init_tss (alloc_tss(sizeof(Tss))); + +} + diff --git a/kernel/fiasco/src/kern/ux/libc_backend_nolock.cc b/kernel/fiasco/src/kern/ux/libc_backend_nolock.cc new file mode 100644 index 00000000..739a697a --- /dev/null +++ b/kernel/fiasco/src/kern/ux/libc_backend_nolock.cc @@ -0,0 +1,10 @@ +#include + +unsigned long __libc_backend_printf_lock() +{ + return 1; +} + +void __libc_backend_printf_unlock(unsigned long) +{ +} diff --git a/kernel/fiasco/src/kern/ux/libc_support.cpp b/kernel/fiasco/src/kern/ux/libc_support.cpp new file mode 100644 index 00000000..784cdaec --- /dev/null +++ b/kernel/fiasco/src/kern/ux/libc_support.cpp @@ -0,0 +1,47 @@ +INTERFACE: + +#include +#include + +void register_libc_atexit(void (*f)(void)); + + +IMPLEMENTATION: + +#include +#include +#include "kernel_console.h" +#include "panic.h" + + +static void (*libc_atexit)(void); + + +void +register_libc_atexit(void (*f)(void)) +{ + if (libc_atexit) + panic("libc_atexit already registered"); + libc_atexit = f; +} + +// Our own version of the assertion failure output function according +// to Linux Standard Base Specification. +// We need it since the standard glibc function calls printf, and doing +// that on a Fiasco kernel stack blows everything up. +extern "C" +void +__assert_fail (const char *assertion, const char *file, + unsigned int line, const char *function) +{ + Kconsole::console()->change_state(0, 0, ~0U, Console::OUTENABLED); + + printf ("ASSERTION_FAILED (%s)\n" + " in function %s\n" + " in file %s:%d\n", + assertion, function, file, line); + + if (libc_atexit) + libc_atexit(); + _exit (EXIT_FAILURE); // Fatal! No destructors +} diff --git a/kernel/fiasco/src/kern/ux/loader.cpp b/kernel/fiasco/src/kern/ux/loader.cpp new file mode 100644 index 00000000..820f3f0d --- /dev/null +++ b/kernel/fiasco/src/kern/ux/loader.cpp @@ -0,0 +1,236 @@ + +INTERFACE: + +#include // for FILE * +#include "types.h" + +class Multiboot_module; + +class Loader +{ +private: + static unsigned int phys_base; + static char const *errors[]; + +public: + static FILE *open_module (const char * const path); + + static char const * load_module (const char * const path, + Multiboot_module *module, + unsigned long int memsize, + bool quiet, + unsigned long *start, + unsigned long *end); + + static char const * copy_module (const char * const path, + Multiboot_module *module, + Address *load_addr, + bool quiet); +}; + +IMPLEMENTATION: + +#include +#include +#include +#include +#include +#include +#include "config.h" +#include "initcalls.h" +#include "mem_layout.h" +#include "multiboot.h" + +unsigned int Loader::phys_base = Mem_layout::Physmem; + +char const *Loader::errors[] FIASCO_INITDATA = +{ + "Failed to open file", + "Failed to load ELF header", + "Failed ELF magic check", + "Failed ELF version check", + "Failed to load program header", + "Failed to fit program section into memory", + "Failed to load program section from file", + "Failed to read module, out of memory?" +}; + +IMPLEMENT FIASCO_INIT +FILE * +Loader::open_module (const char * const path) +{ + char magic[3]; // 2 + 1 for the terminating \0 + FILE *fp; + + if ((fp = fopen (path, "r")) == NULL) + return NULL; + + fgets (magic, sizeof (magic), fp); + + if (magic[0] == '\037' && magic[1] == '\213') // GZIP + { + FILE *pp; + char pipecmd[256]; + int c; + + fclose (fp); + + snprintf (pipecmd, sizeof (pipecmd), "zcat %s", path); + + if ((pp = popen (pipecmd, "r")) == NULL) + return NULL; + + if ((fp = tmpfile()) == NULL) + { + pclose (pp); + return NULL; + } + + while ((c = fgetc (pp)) != EOF) + fputc (c, fp); + + pclose (pp); + } + + rewind (fp); + + return fp; +} + +IMPLEMENT FIASCO_INIT +char const * +Loader::load_module (const char * const path, + Multiboot_module *module, + unsigned long int memsize, + bool quiet, + unsigned long *start, + unsigned long *end) +{ + FILE *fp; + Elf32_Ehdr eh; + Elf32_Phdr ph; + long offset; + int i; + + if ((fp = open_module (path)) == NULL) + return errors[0]; + + // Load ELF Header + if (fread (&eh, sizeof (eh), 1, fp) != 1) + { + fclose (fp); + return errors[1]; + } + + // Check if valid ELF magic, 32bit, little endian + if (memcmp(eh.e_ident, ELFMAG, 4) != 0 || + eh.e_ident[EI_CLASS] != ELFCLASS32 || + eh.e_ident[EI_DATA] != ELFDATA2LSB) + { + fclose (fp); + return errors[2]; + } + + // Check if executable, i386 format, current ELF version + if (eh.e_type != ET_EXEC || + eh.e_machine != EM_386 || + eh.e_version != EV_CURRENT) + { + fclose (fp); + return errors[3]; + } + + // Record entry point (initial EIP) + module->reserved = eh.e_entry; + *start = 0xffffffff; + *end = 0; + + // Load all program sections + for (i = 0, offset = eh.e_phoff; i < eh.e_phnum; i++) { + + // Load Program Header + if (fseek (fp, offset, SEEK_SET) == -1 || + fread (&ph, sizeof (ph), 1, fp) != 1) + { + fclose (fp); + return errors[4]; + } + + offset += sizeof (ph); + + // Only consider non-empty load-sections + if (ph.p_type != PT_LOAD || !ph.p_memsz) + continue; + + // Check if section fits into memory + if (ph.p_paddr + ph.p_memsz > memsize) + { + fclose (fp); + return errors[5]; + } + + // Load Section with non-zero filesize + if (ph.p_filesz && (fseek (fp, ph.p_offset, SEEK_SET) == -1 || + fread ((void *)(phys_base + ph.p_paddr), ph.p_filesz, 1, fp) != 1)) + { + fclose (fp); + return errors[6]; + } + + // Zero-pad uninitialized data if filesize < memsize + if (ph.p_filesz < ph.p_memsz) + memset ((void *)(phys_base + ph.p_paddr + ph.p_filesz), 0, + ph.p_memsz - ph.p_filesz); + + if (ph.p_paddr < *start) + *start = ph.p_paddr; + if (ph.p_paddr + ph.p_memsz > *end) + *end = ph.p_paddr + ph.p_memsz; + } + + if (! quiet) + printf ("Loading Module 0x" L4_PTR_FMT "-0x" L4_PTR_FMT " [%s]\n", + (Address)*start, (Address)*end, path); + + fclose (fp); + return 0; +} + +IMPLEMENT FIASCO_INIT +char const * +Loader::copy_module (const char * const path, + Multiboot_module *module, + Address *load_addr, + bool quiet) +{ + FILE *fp; + struct stat s; + + if ((fp = open_module (path)) == NULL) + return errors[0]; + + if (fstat (fileno (fp), &s) == -1) + { + fclose (fp); + return errors[0]; + } + + *load_addr -= s.st_size; + *load_addr &= Config::PAGE_MASK; // this may not be necessary + + if (fread ((void *)(phys_base + *load_addr), s.st_size, 1, fp) != 1) + { + fclose (fp); + return errors[7]; + } + + module->mod_start = *load_addr; + module->mod_end = *load_addr + s.st_size; + + if (! quiet) + printf ("Copying Module 0x" L4_PTR_FMT "-0x" L4_PTR_FMT " [%s]\n", + (Address)module->mod_start, (Address)module->mod_end, path); + + fclose (fp); + return 0; +} diff --git a/kernel/fiasco/src/kern/ux/low_level.h b/kernel/fiasco/src/kern/ux/low_level.h new file mode 100644 index 00000000..5e479799 --- /dev/null +++ b/kernel/fiasco/src/kern/ux/low_level.h @@ -0,0 +1,86 @@ +#ifndef LOW_LEVEL_H +#define LOW_LEVEL_H + +#include "shortcut.h" +#include "tcboffset.h" + +/** Some shared macros and stuff shared by the two different + * assembler kernel entry sources. + */ + + .macro save_all_regs + pusha + .endm + + /* Reload Linux segments as user might have changed those */ + .macro RESET_KERNEL_SEGMENTS_FORCE_DS_ES + movw KERN_DS,%ds + movw KERN_ES,%es + .endm + + .macro SAVE_STATE + pushl %ebp + pushl %ebx + pushl %edi + pushl %esi + pushl %edx + pushl %ecx + .endm + + .macro RESTORE_STATE + popl %ecx + popl %edx + popl %esi + popl %edi + popl %ebx + popl %ebp + .endm + + .macro RESTORE_STATE_AFTER_IPC +#ifndef CONFIG_LOCAL_IPC + addl $4, %esp +#else + popl %ecx +#endif + popl %edx + popl %esi + popl %edi + popl %ebx + addl $4, %esp + .endm + + .macro RESET_THREAD_CANCEL_AT reg + andl $~Thread_cancel, OFS__THREAD__STATE (\reg) + .endm + + .macro RESET_THREAD_IPC_MASK_AT reg + andl $~Thread_ipc_mask, OFS__THREAD__STATE (\reg) + .endm + + .macro ESP_TO_TCB_AT reg + movl %esp, \reg + andl $~(THREAD_BLOCK_SIZE - 1), \reg + .endm + + +#define SCRATCH_REGISTER_SIZE 12 + .macro SAVE_SCRATCH + push %eax + push %ecx + push %edx + .endm + + .macro RESTORE_SCRATCH + pop %edx + pop %ecx + pop %eax + .endm + + .macro IRET_INSN + iret + .endm + +/** For Kmem::phys_to_virt() emulation. */ +#define PHYSMEM_OFFS $VAL__MEM_LAYOUT__PHYSMEM + +#endif //LOW_LEVEL_H diff --git a/kernel/fiasco/src/kern/ux/main-ux.cpp b/kernel/fiasco/src/kern/ux/main-ux.cpp new file mode 100644 index 00000000..7a3e3472 --- /dev/null +++ b/kernel/fiasco/src/kern/ux/main-ux.cpp @@ -0,0 +1,70 @@ +/* + * Fiasco-UX + * Architecture specific main startup/shutdown code + */ + +IMPLEMENTATION[ux && mp]: + +#include "app_cpu_thread.h" +#include "idt.h" +#include "ipi.h" +#include "per_cpu_data_alloc.h" +#include "usermode.h" + +int FIASCO_FASTCALL boot_ap_cpu(unsigned _cpu) __asm__("BOOT_AP_CPU"); + +int boot_ap_cpu(unsigned _cpu) +{ + if (!Per_cpu_data_alloc::alloc(_cpu)) + { + extern Spin_lock _tramp_mp_spinlock; + printf("CPU allocation failed for CPU%u, disabling CPU.\n", _cpu); + _tramp_mp_spinlock.clear(); + while (1) + Proc::halt(); + } + Per_cpu_data::run_ctors(_cpu); + Cpu &cpu = Cpu::cpus.cpu(_cpu); + + Usermode::init(_cpu); + Ipi::init(_cpu); + + //Kmem::init_cpu(cpu); + Idt::load(); + //Utcb_init::init_ap(cpu); + + //Timer::init(_cpu); + + // caution: no stack variables in this function because we're going + // to change the stack pointer! + cpu.print(); + cpu.show_cache_tlb_info(""); + + puts(""); + + // create kernel thread + App_cpu_thread *kernel = new (Ram_quota::root) App_cpu_thread(); + set_cpu_of(kernel, _cpu); + check(kernel->bind(Kernel_task::kernel_task(), User::Ptr(0))); + + main_switch_ap_cpu_stack(kernel); + return 0; +} + +IMPLEMENTATION[ux]: + +#include "kernel_console.h" + +void main_arch() +{ + // re-enable the console -- it might have been disabled + // by "-quiet" command line switch + Kconsole::console()->change_state(0, 0, ~0U, Console::OUTENABLED); +} + +FIASCO_INIT +int +main() +{ + kernel_main(); +} diff --git a/kernel/fiasco/src/kern/ux/mem_layout-ux.cpp b/kernel/fiasco/src/kern/ux/mem_layout-ux.cpp new file mode 100644 index 00000000..3c482261 --- /dev/null +++ b/kernel/fiasco/src/kern/ux/mem_layout-ux.cpp @@ -0,0 +1,179 @@ +INTERFACE[ux]: + +#include "config.h" + +EXTENSION class Mem_layout +{ +public: + + enum + { + Host_as_size = Config::Host_as_size, + + // keep those + Host_as_base = 0xc0000000, // Base for AS calculations + Host_as_offset = Host_as_base - Host_as_size, + }; + + static Address pmem_size; + +private: + static Address physmem_offs asm ("PHYSMEM_OFFS"); +}; + +INTERFACE[ux-!context_4k]: + +EXTENSION class Mem_layout +{ +public: + + /** Virtual memory layout for 2KB kernel thread context. */ + enum + { + Vmem_start = 0x20000000, + Glibc_mmap_start = 0x40000000, ///< fixed, Linux kernel spec. + Glibc_mmap_end = 0x50000000, ///< hoping that is enough + Caps_start = 0x58000000, + Caps_end = 0x5f000000, + Idt = 0x5f001000, + Tbuf_status_page = 0x5f002000, ///< % 4KB for jdb_tbuf + Io_map_area_start = 0x5f003000, + Io_map_area_end = 0x5f006000, + Tbuf_buffer_area = 0x5f200000, ///< % 2MB tracebuffer + Io_bitmap = 0x5f800000, ///< % 4MB dummy + _Free_1 = 0x5fc00000, ///< % 4MB dummy + Vmem_end = 0x60000000, + Physmem = Vmem_end, ///< % 4MB physical memory + Physmem_end = 0xa0000000 - Host_as_offset, + }; +}; + +INTERFACE[ux-context_4k]: + +EXTENSION class Mem_layout +{ +public: + + /** Virtual memory layout for 4KB kernel thread context. */ + enum + { + Vmem_start = 0x20000000, + Caps_start = 0x28000000, + Caps_end = 0x2f000000, + Idt = 0x2f001000, + Tbuf_status_page = 0x2f002000, ///< % 4KB for jdb_tbuf + Io_map_area_start = 0x2f003000, + Io_map_area_end = 0x2f006000, + Tbuf_buffer_area = 0x2f200000, ///< % 2MB tracebuffer + Io_bitmap = 0x2f800000, ///< % 4MB dummy + Glibc_mmap_start = 0x40000000, ///< fixed, Linux kernel spec. + Glibc_mmap_end = 0x50000000, ///< hoping that is enough + Vmem_end = 0x90000000, + Physmem = Vmem_end, ///< % 4MB physical memory + Physmem_end = 0xb0000000 - Host_as_offset, + }; +}; + +INTERFACE[ux]: + +#include "template_math.h" + +EXTENSION class Mem_layout +{ +public: + + /** Virtuel memory layout -- user address space. */ + enum + { + User_max = 0xc0000000 - Host_as_offset, + Tbuf_ubuffer_area = 0xbfd00000 - Host_as_offset, ///< % 1MB size 2MB + Utcb_addr = 0xbff00000 - Host_as_offset, ///< % 4KB UTCB map address + Utcb_ptr_page_user = 0xbfff0000 - Host_as_offset, ///< % 4KB + Trampoline_page = 0xbfff1000 - Host_as_offset, ///< % 4KB + Kip_auto_map = 0xbfff2000 - Host_as_offset, ///< % 4KB + Tbuf_ustatus_page = 0xbfff3000 - Host_as_offset, ///< % 4KB + Space_index = 0xc0000000, ///< % 4MB v2 + Kip_index = 0xc0800000, ///< % 4MB + Syscalls = 0xeacff000, ///< % 4KB syscall page + }; + + /** Physical memory layout. */ + enum + { + Kernel_start_frame = 0x1000, // Frame 0 special-cased by roottask + Trampoline_frame = 0x2000, // Trampoline Page + Utcb_ptr_frame = 0x3000, // UTCB pointer page + Sigstack_cpu0_start_frame = 0x4000, // Kernel Signal Altstack Start + Multiboot_frame = 0x10000, // Multiboot info + modules + Sigstack_log2_size = 15, // 32kb signal stack size + Sigstack_size = 1 << Sigstack_log2_size, + Sigstack_cpu0_end_frame = Sigstack_cpu0_start_frame // Kernel Signal Altstack End + + Sigstack_size, + Kernel_end_frame = Sigstack_cpu0_end_frame, + }; + + enum + { + Utcb_ptr_page = Physmem + Utcb_ptr_frame, + utcb_ptr_align = Tl_math::Ld::Res, + }; + + /// reflect symbols in linker script + static const char task_sighandler_start asm ("_task_sighandler_start"); + static const char task_sighandler_end asm ("_task_sighandler_end"); + + static Address const kernel_trampoline_page; +}; + +IMPLEMENTATION[ux]: + +Address Mem_layout::physmem_offs; +Address Mem_layout::pmem_size; +Address const Mem_layout::kernel_trampoline_page = + phys_to_pmem (Trampoline_frame); + + +PUBLIC static inline +User::Ptr & +Mem_layout::user_utcb_ptr(unsigned cpu) +{ + // Allocate each CPUs utcb ptr in a different cacheline to avoid + // false sharing. + return reinterpret_cast::Ptr*>(Utcb_ptr_page + (cpu << utcb_ptr_align))[0]; +} + + +PUBLIC static inline +void +Mem_layout::kphys_base (Address base) +{ + physmem_offs = (Address)Physmem - base; +} + +PUBLIC static inline +Address +Mem_layout::pmem_to_phys (void *addr) +{ + return (unsigned long)addr - Physmem; +} + +PUBLIC static inline +Address +Mem_layout::pmem_to_phys (Address addr) +{ + return addr - Physmem; +} + +PUBLIC static inline +Address +Mem_layout::phys_to_pmem (Address addr) +{ + return addr + Physmem; +} + +PUBLIC static inline +Mword +Mem_layout::in_pmem (Address addr) +{ + return (addr >= Physmem) && (addr < Physmem_end); +} diff --git a/kernel/fiasco/src/kern/ux/mem_space-ux.cpp b/kernel/fiasco/src/kern/ux/mem_space-ux.cpp new file mode 100644 index 00000000..55d34bfb --- /dev/null +++ b/kernel/fiasco/src/kern/ux/mem_space-ux.cpp @@ -0,0 +1,264 @@ +/* + * Fiasco-UX + * Architecture specific pagetable code + */ + +INTERFACE[ux]: + +#include "entry_frame.h" +#include // for pid_t +#include "kmem.h" +#include "mem_layout.h" +#include "paging.h" + +extern "C" FIASCO_FASTCALL +int +thread_page_fault(Address, Mword, Address, Mword, Return_frame *); + + +EXTENSION class Mem_space +{ +protected: + void sync_kernel() const {} + + pid_t _pid; +}; + +IMPLEMENTATION[ux]: + +#include +#include +#include +#include "boot_info.h" +#include "cpu_lock.h" +#include "lock_guard.h" +#include "mem_layout.h" +#include "processor.h" +#include "regdefs.h" +#include "trampoline.h" +#include +#include "config.h" +#include "emulation.h" +#include "logdefs.h" + +PROTECTED static inline NEEDS ["kmem.h", "emulation.h"] +Pdir * +Mem_space::current_pdir() +{ + return reinterpret_cast(Kmem::phys_to_virt(Emulation::pdir_addr())); +} + +IMPLEMENT inline NEEDS ["kmem.h", "emulation.h"] +void +Mem_space::make_current() +{ + Emulation::set_pdir_addr(Kmem::virt_to_phys(_dir)); + _current.cpu(current_cpu()) = this; +} + +// returns host pid number +PUBLIC inline +pid_t +Mem_space::pid() const +{ return _pid; } + +// sets host pid number +PUBLIC inline +void +Mem_space::set_pid(pid_t pid) +{ _pid = pid; } + +IMPLEMENT inline NEEDS["logdefs.h"] +void +Mem_space::switchin_context(Mem_space *from) +{ + if (this == from) + return; + + CNT_ADDR_SPACE_SWITCH; + make_current(); +} + +IMPLEMENT inline NEEDS [, , "boot_info.h", + "cpu_lock.h", "lock_guard.h", "mem_layout.h", + "trampoline.h"] +void +Mem_space::page_map(Address phys, Address virt, Address size, unsigned attr) +{ + Lock_guard guard(&cpu_lock); + + Mword *trampoline = (Mword *)Mem_layout::kernel_trampoline_page; + + *(trampoline + 1) = virt; + *(trampoline + 2) = size; + *(trampoline + 3) = PROT_READ | (attr & Page_writable ? PROT_WRITE : 0); + *(trampoline + 4) = MAP_SHARED | MAP_FIXED; + *(trampoline + 5) = Boot_info::fd(); + + if (phys >= Boot_info::fb_virt() && + phys + size <= Boot_info::fb_virt() + + Boot_info::fb_size() + + Boot_info::input_size()) + *(trampoline + 6) = Boot_info::fb_phys() + (phys - Boot_info::fb_virt()); + else + *(trampoline + 6) = phys; + + Trampoline::syscall(pid(), __NR_mmap, Mem_layout::Trampoline_page + 4); +} + +IMPLEMENT inline NEEDS [, "cpu_lock.h", "lock_guard.h", + "trampoline.h"] +void +Mem_space::page_unmap(Address virt, Address size) +{ + Lock_guard guard(&cpu_lock); + + Trampoline::syscall(pid(), __NR_munmap, virt, size); +} + +IMPLEMENT inline NEEDS [, "cpu_lock.h", "lock_guard.h", + "trampoline.h"] +void +Mem_space::page_protect(Address virt, Address size, unsigned attr) +{ + Lock_guard guard(&cpu_lock); + + Trampoline::syscall(pid(), __NR_mprotect, virt, size, + PROT_READ | (attr & Page_writable ? PROT_WRITE : 0)); +} + + +/** + * Translate virtual memory address in user space to virtual memory + * address in kernel space (requires all physical memory be mapped). + * @param addr Virtual address in user address space. + * @param write Type of memory access (read or write) for page-faults. + * @return Virtual address in kernel address space. + */ +PRIVATE inline NEEDS[Mem_space::current_pdir] +template< typename T > +T * +Mem_space::user_to_kernel(T const *addr, bool write) +{ + Phys_addr phys; + Addr virt = Addr::create((Address) addr); + unsigned attr, error = 0; + Size size; + + for (;;) + { + // See if there is a mapping for this address + if (v_lookup(virt, &phys, &size, &attr)) + { + // Add offset to frame + phys = phys | virt.offset(size); + + // See if we want to write and are not allowed to + // Generic check because INTEL_PTE_WRITE == INTEL_PDE_WRITE + if (!write || (attr & Pt_entry::Writable)) + return (T*)Mem_layout::phys_to_pmem(phys.value()); + + error |= PF_ERR_PRESENT; + } + + if (write) + error |= PF_ERR_WRITE; + + // If we tried to access user memory of a space other than current_mem_space() + // our Long-IPC partner must do a page-in. This is analogue to IA32 + // page-faulting in the IPC window. Set PF_ERR_REMTADDR hint. + // Otherwise we faulted on our own user memory. Set PF_ERR_USERADDR hint. + error |= (dir() == current_pdir() ? PF_ERR_USERADDR : PF_ERR_REMTADDR); + + // No mapping or insufficient access rights, raise pagefault. + // Pretend open interrupts, we restore the current state afterwards. + Cpu_lock::Status was_locked = cpu_lock.test(); + + thread_page_fault(virt.value(), error, 0, Proc::processor_state() | EFLAGS_IF, 0); + + cpu_lock.set (was_locked); + } +} + +IMPLEMENT inline NEEDS ["config.h", "cpu_lock.h", "lock_guard.h"] +template< typename T > +T +Mem_space::peek_user(T const *addr) +{ + T value; + + // Check if we cross page boundaries + if (((Address)addr & Config::PAGE_MASK) == + (((Address)addr + sizeof (T) - 1) & Config::PAGE_MASK)) + { + Lock_guard guard(&cpu_lock); + value = *user_to_kernel(addr, false); + } + else + copy_from_user(&value, addr, 1); + + return value; +} + +IMPLEMENT inline NEEDS ["config.h", "cpu_lock.h", "lock_guard.h"] +template< typename T > +void +Mem_space::poke_user(T *addr, T value) +{ + // Check if we cross page boundaries + if (((Address)addr & Config::PAGE_MASK) == + (((Address)addr + sizeof (T) - 1) & Config::PAGE_MASK)) + { + Lock_guard guard(&cpu_lock); + *user_to_kernel(addr, true) = value; + } + else + copy_to_user(addr, &value, 1); +} + +PRIVATE +template< typename T > +void +Mem_space::copy_from_user(T *kdst, T const *usrc, size_t n) +{ + Lock_guard guard(&cpu_lock); + + char *ptr = (char *)usrc; + char *dst = (char *)kdst; + char *src = 0; + + n *= sizeof (T); + + while (n--) + { + if (!src || ((Address)ptr & ~Config::PAGE_MASK) == 0) + src = user_to_kernel(ptr, false); + + *dst++ = *src++; + ptr++; + } +} + +PRIVATE inline NEEDS ["config.h", "cpu_lock.h", "lock_guard.h"] +template< typename T > +void +Mem_space::copy_to_user(T *udst, T const *ksrc, size_t n) +{ + Lock_guard guard(&cpu_lock); + + char *ptr = (char *)udst; + char *src = (char *)ksrc; + char *dst = 0; + + n *= sizeof (T); + + while (n--) + { + if (!dst || ((Address)ptr & ~Config::PAGE_MASK) == 0) + dst = user_to_kernel(ptr, true); + + *dst++ = *src++; + ptr++; + } +} + diff --git a/kernel/fiasco/src/kern/ux/mem_unit-ux.cpp b/kernel/fiasco/src/kern/ux/mem_unit-ux.cpp new file mode 100644 index 00000000..0e468450 --- /dev/null +++ b/kernel/fiasco/src/kern/ux/mem_unit-ux.cpp @@ -0,0 +1,13 @@ +INTERFACE: + +#include "types.h" + +class Mem_unit +{}; + + +IMPLEMENTATION: + +PUBLIC static inline void Mem_unit::tlb_flush () {} +PUBLIC static inline void Mem_unit::tlb_flush (Address) {} +PUBLIC static inline void Mem_unit::clean_dcache(void *) {} diff --git a/kernel/fiasco/src/kern/ux/multiboot.h b/kernel/fiasco/src/kern/ux/multiboot.h new file mode 100644 index 00000000..d38ef8aa --- /dev/null +++ b/kernel/fiasco/src/kern/ux/multiboot.h @@ -0,0 +1,259 @@ +#ifndef MULTIBOOT_H +#define MULTIBOOT_H + +#include "types.h" + +class Multiboot_header +{ +public: + enum + { + /* The entire multiboot_header must be contained + * within the first MULTIBOOT_SEARCH bytes of the kernel image. */ + Search = 8192, + + /* Magic value identifying the multiboot_header. */ + Magic = 0x1badb002, + + /* Features flags for 'flags'. + * If a boot loader sees a flag in MULTIBOOT_MUSTKNOW set + * and it doesn't understand it, it must fail. */ + Mustknow = 0x0000ffff, + + /* Align all boot modules on page (4KB) boundaries. */ + Page_align = 0x00000001, + + /* Must be provided memory information in multiboot_info structure */ + Memory_info = 0x00000002, + + /* Use the load address fields above instead of the ones in the a.out + * header to figure out what to load where, and what to do afterwards. + * This should only be needed for a.out kernel images (ELF and other + * formats can generally provide the needed information). */ + Aout_kludge = 0x00010000, + + /* The boot loader passes this value in register EAX to signal the kernel + * that the multiboot method is being used */ + Valid = 0x2badb002, + }; + + /* Must be MULTIBOOT_MAGIC */ + Unsigned32 magic; + + /* Feature flags - see below. */ + Unsigned32 flags; + + /* Checksum: magic + flags + checksum == 0 */ + Unsigned32 checksum; + + /* These are only valid if MULTIBOOT_AOUT_KLUDGE is set. */ + Unsigned32 header_addr; + Unsigned32 load_addr; + Unsigned32 load_end_addr; + Unsigned32 bss_end_addr; + Unsigned32 entry; +} __attribute__((packed)); + +/* VBE controller information. */ +class Multiboot_vbe_controller +{ +public: + Unsigned8 signature[4]; + Unsigned16 version; + Unsigned32 oem_string; + Unsigned32 capabilities; + Unsigned32 video_mode; + Unsigned16 total_memory; + Unsigned16 oem_software_rev; + Unsigned32 oem_vendor_name; + Unsigned32 oem_product_name; + Unsigned32 oem_product_rev; + Unsigned8 reserved[222]; + Unsigned8 oem_data[256]; +} __attribute__((packed)); + +/* VBE mode information. */ +class Multiboot_vbe_mode +{ +public: + Unsigned16 mode_attributes; + Unsigned8 win_a_attributes; + Unsigned8 win_b_attributes; + Unsigned16 win_granularity; + Unsigned16 win_size; + Unsigned16 win_a_segment; + Unsigned16 win_b_segment; + Unsigned32 win_func; + Unsigned16 bytes_per_scanline; + + /* >=1.2 */ + Unsigned16 x_resolution; + Unsigned16 y_resolution; + Unsigned8 x_char_size; + Unsigned8 y_char_size; + Unsigned8 number_of_planes; + Unsigned8 bits_per_pixel; + Unsigned8 number_of_banks; + Unsigned8 memory_model; + Unsigned8 bank_size; + Unsigned8 number_of_image_pages; + Unsigned8 reserved0; + + /* direct color */ + Unsigned8 red_mask_size; + Unsigned8 red_field_position; + Unsigned8 green_mask_size; + Unsigned8 green_field_position; + Unsigned8 blue_mask_size; + Unsigned8 blue_field_position; + Unsigned8 reserved_mask_size; + Unsigned8 reserved_field_position; + Unsigned8 direct_color_mode_info; + + /* >=2.0 */ + Unsigned32 phys_base; + Unsigned32 reserved1; + Unsigned16 reversed2; + + /* >=3.0 */ + Unsigned16 linear_bytes_per_scanline; + Unsigned8 banked_number_of_image_pages; + Unsigned8 linear_number_of_image_pages; + Unsigned8 linear_red_mask_size; + Unsigned8 linear_red_field_position; + Unsigned8 linear_green_mask_size; + Unsigned8 linear_green_field_position; + Unsigned8 linear_blue_mask_size; + Unsigned8 linear_blue_field_position; + Unsigned8 linear_reserved_mask_size; + Unsigned8 linear_reserved_field_position; + Unsigned32 max_pixel_clock; + + Unsigned8 reserved3[189]; +} __attribute__((packed)); + +class Multiboot_info +{ +public: + enum + { + Memory = (1L<<0), + Boot_device = (1L<<1), + Cmdline = (1L<<2), + Mods = (1L<<3), + Aout_syms = (1L<<4), + Elf_shdr = (1L<<5), + Mem_map = (1L<<6), + Drive_info = (1L<<7), + Cfg_table = (1L<<8), + Boot_ld_name = (1L<<9), + Apm_table = (1L<<10), + Video_info = (1L<<11), + }; + + /* These flags indicate which parts of the multiboot_info are valid; + * see below for the actual flag bit definitions. */ + Unsigned32 flags; + + /* Lower/Upper memory installed in the machine. + * Valid only if MULTIBOOT_MEMORY is set in flags word above. */ + Unsigned32 mem_lower; + Unsigned32 mem_upper; + + /* BIOS disk device the kernel was loaded from. + * Valid only if MULTIBOOT_BOOT_DEVICE is set in flags word above. */ + Unsigned8 boot_device[4]; + + /* Command-line for the OS kernel: a null-terminated ASCII string. + * Valid only if MULTIBOOT_CMDLINE is set in flags word above. */ + Unsigned32 cmdline; + + /* List of boot modules loaded with the kernel. + * Valid only if MULTIBOOT_MODS is set in flags word above. */ + Unsigned32 mods_count; + Unsigned32 mods_addr; + + /* Symbol information for a.out or ELF executables. */ + union + { + struct __attribute__((packed)) + { + /* a.out symbol information valid only if MULTIBOOT_AOUT_SYMS + is set in flags word above. */ + Unsigned32 tabsize; + Unsigned32 strsize; + Unsigned32 addr; + Unsigned32 reserved; + } a; + + struct __attribute__((packed)) + { + /* ELF section header information valid only if + MULTIBOOT_ELF_SHDR is set in flags word above. */ + Unsigned32 num; + Unsigned32 size; + Unsigned32 addr; + Unsigned32 shndx; + } e; + } syms; + + /* Memory map buffer. + Valid only if MULTIBOOT_MEM_MAP is set in flags word above. */ + Unsigned32 mmap_count; + Unsigned32 mmap_addr; + + /* Drive Info buffer */ + Unsigned32 drives_length; + Unsigned32 drives_addr; + + /* ROM configuration table */ + Unsigned32 config_table; + + /* Boot Loader Name */ + Unsigned32 boot_loader_name; + + /* APM table */ + Unsigned32 apm_table; + + /* Video */ + Unsigned32 vbe_control_info; + Unsigned32 vbe_mode_info; + Unsigned16 vbe_mode; + Unsigned16 vbe_interface_seg; + Unsigned16 vbe_interface_off; + Unsigned16 vbe_interface_len; +} __attribute__((packed)); + +/* The mods_addr field above contains the physical address of the first + of 'mods_count' multiboot_module structures. */ +class Multiboot_module +{ +public: + /* Physical start and end addresses of the module data itself. */ + Unsigned32 mod_start; + Unsigned32 mod_end; + + /* Arbitrary ASCII string associated with the module. */ + Unsigned32 string; + + /* Boot loader must set to 0; OS must ignore. */ + Unsigned32 reserved; +} __attribute__((packed)); + + +/* The mmap_addr field above contains the physical address of the first + of the AddrRangeDesc structure. "size" represents the size of the + rest of the structure and optional padding. The offset to the beginning + of the next structure is therefore "size + 4". */ +struct AddrRangeDesc +{ + Unsigned32 size; + Unsigned32 BaseAddrLow; + Unsigned32 BaseAddrHigh; + Unsigned32 LengthLow; + Unsigned32 LengthHigh; + Unsigned32 Type; + /* unspecified optional padding... */ +} __attribute__((packed)); + +#endif diff --git a/kernel/fiasco/src/kern/ux/net.cpp b/kernel/fiasco/src/kern/ux/net.cpp new file mode 100644 index 00000000..3a33e5dc --- /dev/null +++ b/kernel/fiasco/src/kern/ux/net.cpp @@ -0,0 +1,75 @@ +// +// Network handling for Fiasco-UX +// + +INTERFACE: + +class Net +{ +public: + static void init(); + static void enable(); + +private: + static int tunfd; + + static void bootstrap(); +}; + +// ------------------------------------------------------------------------ +IMPLEMENTATION: + +#include +#include +#include +#include +#include "boot_info.h" +#include "initcalls.h" +#include "irq_chip.h" +#include "kmem.h" +#include "pic.h" +#include "warn.h" + +int Net::tunfd; + +IMPLEMENT FIASCO_INIT +void +Net::bootstrap() +{ + char s_net_fd[3]; + + snprintf (s_net_fd, sizeof (s_net_fd), "%u", tunfd); + + execl (Boot_info::net_program(), Boot_info::net_program(), + "-t", s_net_fd, NULL); +} + +IMPLEMENT FIASCO_INIT +void +Net::init() +{ + // Check if frame buffer is available + if (!Boot_info::net()) + return; + + if ((tunfd = open("/dev/net/tun", O_RDWR)) < 0) + { + perror("open of /dev/net/tun"); + exit(1); + } + + // Setup virtual interrupt + if (!Pic::setup_irq_prov (Pic::Irq_net, + Boot_info::net_program(), bootstrap)) + { + puts("Problems setting up network interrupt!"); + exit(1); + } + + Kip::k()->vhw()->set_desc(Vhw_entry::TYPE_NET, + 0, 0, + Pic::Irq_net, + Pic::get_pid_for_irq_prov(Pic::Irq_net), tunfd); + + printf("Starting Network.\n\n"); +} diff --git a/kernel/fiasco/src/kern/ux/panic.cpp b/kernel/fiasco/src/kern/ux/panic.cpp new file mode 100644 index 00000000..5de79a50 --- /dev/null +++ b/kernel/fiasco/src/kern/ux/panic.cpp @@ -0,0 +1,30 @@ +INTERFACE: + +/* + * The generated headerfile is also exported to C code! + */ +#ifdef __cplusplus +#define EXT_DECL extern "C" +#else +#define EXT_DECL /* empty */ +#endif + +IMPLEMENTATION: + +#include +#include +#include + +EXT_DECL __attribute__ ((noreturn)) +void panic(const char *format, ...) +{ + va_list pvar; + + printf("\033[1mPanic: "); + va_start(pvar, format); + vprintf(format, pvar); + va_end(pvar); + puts("\033[m\n"); + + exit(EXIT_FAILURE); +} diff --git a/kernel/fiasco/src/kern/ux/pic-ux.cpp b/kernel/fiasco/src/kern/ux/pic-ux.cpp new file mode 100644 index 00000000..d6ea7453 --- /dev/null +++ b/kernel/fiasco/src/kern/ux/pic-ux.cpp @@ -0,0 +1,351 @@ +/* + * Fiasco-UX + * Architecture specific interrupt code + */ + +INTERFACE: + +#include "config.h" +#include + +EXTENSION class Pic +{ +public: + static int irq_pending(); + static void eat(unsigned); + static void set_owner(int); + static unsigned int map_irq_to_gate(unsigned); + static bool setup_irq_prov(unsigned irq, const char * const path, + void (*bootstrap_func)()); + static void irq_prov_shutdown(); + static unsigned int get_pid_for_irq_prov(unsigned); + static bool get_ipi_gate(unsigned irq, unsigned long &gate); + + enum + { + Irq_timer = 0, + Irq_con = 1, + Irq_net = 2, + Num_dev_irqs = 4, + Irq_ipi_base = 4, + Num_irqs = 4 + Config::Max_num_cpus, + }; + +private: + static unsigned int highest_irq; + static unsigned int pids[Pic::Num_irqs]; + static struct pollfd pfd[Pic::Num_irqs]; +}; + +// ------------------------------------------------------------------------ +INTERFACE[ux && mp]: + +EXTENSION class Pic +{ +public: + static void send_ipi(unsigned _cpu, unsigned char data); + static bool setup_ipi(unsigned _cpu, int _tid); + +private: + static unsigned int ipi_fds[Config::Max_num_cpus]; +}; + +// ------------------------------------------------------------------------ +IMPLEMENTATION[ux]: + +#include // for assert +#include // for SIGIO +#include // for stdin +#include // for EXIT_FAILURE +#include // for fcntl +#include // for termios +#include // for fork +#include // for fork + +#include "boot_info.h" // for boot_info::fd() +#include "emulation.h" +#include "initcalls.h" + +unsigned int Pic::highest_irq; +unsigned int Pic::pids[Num_irqs]; +struct pollfd Pic::pfd[Num_irqs]; + +PUBLIC static inline +unsigned +Pic::nr_irqs() +{ return Num_dev_irqs; } + +IMPLEMENT FIASCO_INIT +void +Pic::init() +{ + atexit (&irq_prov_shutdown); +} + +PRIVATE static +bool +Pic::prepare_irq(int sockets[2]) +{ + struct termios tt; + + if (openpty(&sockets[0], &sockets[1], NULL, NULL, NULL)) + { + perror("openpty"); + return false; + } + + if (tcgetattr(sockets[0], &tt) < 0) + { + perror("tcgetattr"); + return false; + } + + cfmakeraw(&tt); + + if (tcsetattr(sockets[0], TCSADRAIN, &tt) < 0) + { + perror("tcsetattr"); + return false; + } + + fflush(NULL); + + return true; +} + +IMPLEMENT +bool +Pic::setup_irq_prov(unsigned irq, const char * const path, + void (*bootstrap_func)()) +{ + int sockets[2]; + + if (access(path, X_OK | F_OK)) + { + perror(path); + return false; + } + + if (prepare_irq(sockets) == false) + return false; + + switch (pids[irq] = fork()) + { + case -1: + return false; + + case 0: + break; + + default: + close(sockets[1]); + fcntl(sockets[0], F_SETFD, FD_CLOEXEC); + pfd[irq].fd = sockets[0]; + return true; + } + + // Unblock all signals except SIGINT, we enter jdb with it and don't want + // the irq providers to die + sigset_t mask; + sigemptyset(&mask); + sigaddset(&mask, SIGINT); + sigprocmask(SIG_SETMASK, &mask, NULL); + + fclose(stdin); + fclose(stdout); + fclose(stderr); + + dup2(sockets[1], 0); + close(sockets[0]); + close(sockets[1]); + bootstrap_func(); + + _exit(EXIT_FAILURE); +} + +IMPLEMENT +void +Pic::irq_prov_shutdown() +{ + for (unsigned int i = 0; i < Num_irqs; i++) + if (pids[i]) + kill(pids[i], SIGTERM); +} + +IMPLEMENT inline NEEDS [, , , "boot_info.h"] +void +Pic::enable_locked(unsigned irq, unsigned /*prio*/) +{ + int flags; + + // If fd is zero, someone tried to activate an IRQ without provider + assert (pfd[irq].fd); + + if ((flags = fcntl(pfd[irq].fd, F_GETFL)) < 0 || + fcntl(pfd[irq].fd, F_SETFL, flags | O_NONBLOCK | O_ASYNC) < 0 || + fcntl(pfd[irq].fd, F_SETSIG, SIGIO) < 0 || + fcntl(pfd[irq].fd, F_SETOWN, Boot_info::pid()) < 0) + return; + + pfd[irq].events = POLLIN; + + if (irq >= highest_irq) + highest_irq = irq + 1; +} + +IMPLEMENT inline +void +Pic::disable_locked(unsigned) +{} + +IMPLEMENT inline +void +Pic::acknowledge_locked(unsigned) +{} + +IMPLEMENT inline +void +Pic::block_locked(unsigned) +{} + +IMPLEMENT +int +Pic::irq_pending() +{ + unsigned int i; + + for (i = 0; i < highest_irq; i++) + pfd[i].revents = 0; + + if (poll(pfd, highest_irq, 0) > 0) + for (i = 0; i < highest_irq; i++) + if (pfd[i].revents & POLLIN) + { + if (!Emulation::idt_vector_present(0x20 + i)) + eat(i); + else + return i; + } + + return -1; +} + +IMPLEMENT inline NEEDS [, ] +void +Pic::eat(unsigned irq) +{ + char buffer[8]; + + assert (pfd[irq].events & POLLIN); + + while (read(pfd[irq].fd, buffer, sizeof (buffer)) > 0) + ; +} + +/* + * Possible problem if an IRQ gets enabled and the system is already + * long running and the owner is set wrong? + */ +IMPLEMENT inline +void +Pic::set_owner(int pid) +{ + for (unsigned int i = 0; i < highest_irq; i++) + if (pfd[i].events & POLLIN) + fcntl(pfd[i].fd, F_SETOWN, pid); +} + +IMPLEMENT inline +unsigned int +Pic::map_irq_to_gate(unsigned irq) +{ + return 0x20 + irq; +} + +IMPLEMENT +unsigned int +Pic::get_pid_for_irq_prov(unsigned irq) +{ + return pids[irq]; +} + +// --------------------------------------------------------------------- +IMPLEMENTATION[ux && !mp]: + +IMPLEMENT static +bool +Pic::get_ipi_gate(unsigned, unsigned long &) +{ return false; } + + +// --------------------------------------------------------------------- +IMPLEMENTATION[ux && mp]: + +#include "ipi.h" + +unsigned int Pic::ipi_fds[Config::Max_num_cpus]; + +IMPLEMENT +void +Pic::set_cpu(unsigned irq_num, unsigned cpu) +{ + printf("Pic::set_cpu(%d, %d)\n", irq_num, cpu); +} + +IMPLEMENT static +bool +Pic::setup_ipi(unsigned _cpu, int _tid) +{ + int sockets[2], flags; + + if (prepare_irq(sockets) == false) + return false; + + unsigned i = Irq_ipi_base + _cpu; + + pfd[i].fd = sockets[0]; + ipi_fds[_cpu] = sockets[1]; + + if ((flags = fcntl(pfd[i].fd, F_GETFL)) < 0 || + fcntl(pfd[i].fd, F_SETFL, flags | O_NONBLOCK | O_ASYNC) < 0 || + fcntl(pfd[i].fd, F_SETSIG, SIGIO) < 0 || + fcntl(pfd[i].fd, F_SETOWN, _tid) < 0) + return false; + + pfd[i].events = POLLIN; + + if (i >= highest_irq) + highest_irq = i + 1; + + return true; +} + +IMPLEMENT +void +Pic::send_ipi(unsigned _cpu, unsigned char data) +{ + if (ipi_fds[_cpu]) + if (write(ipi_fds[_cpu], &data, sizeof(data)) != sizeof(data)) + printf("Write error\n"); +} + +IMPLEMENT static +bool +Pic::get_ipi_gate(unsigned irq, unsigned long &gate) +{ + if (irq < Irq_ipi_base) + return false; + + // XXX check if irq is the irq for our current context/cpu + unsigned char b; + if (read(pfd[irq].fd, &b, sizeof(b)) < 1) + { + printf("read failure\n"); + return false; + } + + printf("IPI message: %c\n", b); + gate = Ipi::gate(b); + + return true; +} diff --git a/kernel/fiasco/src/kern/ux/sighandler.S b/kernel/fiasco/src/kern/ux/sighandler.S new file mode 100644 index 00000000..96bb405c --- /dev/null +++ b/kernel/fiasco/src/kern/ux/sighandler.S @@ -0,0 +1,34 @@ + +/* + * Signal Handler Trampoline for traced tasks. + * + * This code is copied onto the task's trampoline page and runs in the task's + * address space. Therefore all addressing must be done with virtual addresses + * of the task. + * + * The whole purpose of this exercise is to get a pointer to the signal + * context of the task from inside the kernel process. The signal handler + * runs at the bottom of the trampoline page with the top of the trampoline + * page as signal stack. The handler receives the following 3 parameters: + * int signal, siginfo_t *, void *context + * We want the third parameter, relative to the beginning of the trampoline + * page and store it at offset 256 on the trampoline page so that code and data + * don't cacheline collide. + */ + +#include "tcboffset.h" + +.align 16 +.globl _task_sighandler_start +.globl _task_sighandler_end + +_task_sighandler_start: + movl $VAL__MEM_LAYOUT__TRAMPOLINE_PAGE, %ecx + // get trampoline page start address + movl 12(%esp), %eax // get context pointer from sighandler + andl $0xfff, %eax // calculate offset into trampolinepage + movl %eax, 0x100(%ecx) // save offset at trampoline page + 256 + addl $4, %esp // consume return address + movl $173, %eax // rt_sigreturn + int $0x80 // system call +_task_sighandler_end: diff --git a/kernel/fiasco/src/kern/ux/simpleio.cpp b/kernel/fiasco/src/kern/ux/simpleio.cpp new file mode 100644 index 00000000..43051a28 --- /dev/null +++ b/kernel/fiasco/src/kern/ux/simpleio.cpp @@ -0,0 +1,30 @@ + +#include + +int +putstr(const char *const s) +{ + return printf("%s", s); +} + +int +putnstr(const char *const s, int len) +{ + // the printf version in minilibc just doesn't seem to understand the + // printf below (doesn't cut the string after len but prints all of the + // string), so do it in another way +#if 1 + char *a = (char *)s; + int l = 0; + while (*a && len) + { + putchar(*a); + l++; + len--; + a++; + } + return l; +#else + printf("%*.*s", len, len, s); +#endif +} diff --git a/kernel/fiasco/src/kern/ux/space-ux.cpp b/kernel/fiasco/src/kern/ux/space-ux.cpp new file mode 100644 index 00000000..f2128754 --- /dev/null +++ b/kernel/fiasco/src/kern/ux/space-ux.cpp @@ -0,0 +1,6 @@ +IMPLEMENTATION[ux]: + +IMPLEMENT inline +void +Space::switchin_ldt() const +{} diff --git a/kernel/fiasco/src/kern/ux/startup.cpp b/kernel/fiasco/src/kern/ux/startup.cpp new file mode 100644 index 00000000..642d0d74 --- /dev/null +++ b/kernel/fiasco/src/kern/ux/startup.cpp @@ -0,0 +1,72 @@ +IMPLEMENTATION: + +#include "banner.h" +#include "boot_info.h" +#include "config.h" +#include "cpu.h" +#include "fb.h" +#include "fpu.h" +#include "idt.h" +#include "initcalls.h" +#include "irq_chip_pic.h" +#include "jdb.h" +#include "kernel_console.h" +#include "kernel_task.h" +#include "kip_init.h" +#include "kmem.h" +#include "kmem_alloc.h" +#include "net.h" +#include "per_cpu_data.h" +#include "per_cpu_data_alloc.h" +#include "pic.h" +#include "static_init.h" +#include "timer.h" +#include "usermode.h" +#include "utcb_init.h" + +STATIC_INITIALIZER_P(startup_system1, UX_STARTUP1_INIT_PRIO); +STATIC_INITIALIZER_P(startup_system2, STARTUP_INIT_PRIO); + +static void FIASCO_INIT +startup_system1() +{ + Kconsole::init(); + Usermode::init(0); + Boot_info::init(); + Config::init(); +} + +static void FIASCO_INIT +startup_system2() +{ + Banner::init(); + Kip_init::init(); + Kmem_alloc::base_init(); + Kmem_alloc::init(); + + // Initialize cpu-local data management and run constructors for CPU 0 + Per_cpu_data::init_ctors(); + Per_cpu_data_alloc::alloc(0); + Per_cpu_data::run_ctors(0); + + Kmem::init_mmu(*Cpu::boot_cpu()); + Kernel_task::init(); // enables current_mem_space() + Kip_init::init_freq(*Cpu::boot_cpu()); + + // must copy the KIP to allocated phys memory, because user apps cannot + // access the kernel image memory + Kip *kip = (Kip*)Kmem_alloc::allocator()->alloc(Config::PAGE_SHIFT); + memcpy(kip, Kip::k(), Config::PAGE_SIZE); + Kip::init_global_kip(kip); + + Utcb_init::init(); + Pic::init(); + Irq_chip_ia32_pic::init(); + Ipi::init(0); + Idt::init(); + Fpu::init(0); + Timer::init(0); + Fb::init(); + Net::init(); + Cpu::init_global_features(); +} diff --git a/kernel/fiasco/src/kern/ux/sys_call_page-abs-ux.cpp b/kernel/fiasco/src/kern/ux/sys_call_page-abs-ux.cpp new file mode 100644 index 00000000..5c7c88d4 --- /dev/null +++ b/kernel/fiasco/src/kern/ux/sys_call_page-abs-ux.cpp @@ -0,0 +1,47 @@ +/* + * Fiasco Syscall-Page Code (absolute addressing) + * Architecture specific UX code. + */ + +IMPLEMENTATION [ux-abs_syscalls]: + +#include "kmem.h" +#include "mem_layout.h" +#include "types.h" +#include + +enum +{ + Offs_invoke = 0x000, + Offs_se_invoke = 0x000, + Offs_kip_invoke = 0x800, + Offs_kip_se_invoke = 0x800, + Offs_debugger = 0x200, + Offs_kip_debugger = 0x900, +}; + + +#define INV_SYSCALL(sysc) \ + *reinterpret_cast(Mem_layout::Syscalls + Offs_##sysc) = 0x0b0f + +#define SYSCALL_SYMS(sysc) \ +extern char sys_call_##sysc, sys_call_##sysc##_end + +#define COPY_SYSCALL(sysc) do { \ +memcpy( (char*)Kip::k() + Offs_kip_##sysc, &sys_call_##sysc, \ + &sys_call_##sysc##_end- &sys_call_##sysc ); } while (0) + +IMPLEMENT +void +Sys_call_page::init() +{ + SYSCALL_SYMS(invoke); + SYSCALL_SYMS(debugger); + + Kip *ki = Kip::k(); + + ki->kip_sys_calls = 2; + + COPY_SYSCALL(invoke); + COPY_SYSCALL(debugger); +} diff --git a/kernel/fiasco/src/kern/ux/task-ux.cpp b/kernel/fiasco/src/kern/ux/task-ux.cpp new file mode 100644 index 00000000..0ca13129 --- /dev/null +++ b/kernel/fiasco/src/kern/ux/task-ux.cpp @@ -0,0 +1,120 @@ +IMPLEMENTATION [ux]: + +#include +#include + +#include "cpu_lock.h" +#include "hostproc.h" +#include "lock_guard.h" +#include "map_util.h" +#include "mem_layout.h" + +IMPLEMENT +void +Task::ux_init() +{ set_pid(Hostproc::create()); } + +PRIVATE inline +bool +Task::invoke_arch(L4_msg_tag &tag, Utcb *utcb) +{ + + switch (utcb->values[0]) + { + case Ldt_set_x86: + { + enum + { + Utcb_values_per_ldt_entry + = Cpu::Ldt_entry_size / sizeof(utcb->values[0]), + }; + if (EXPECT_FALSE(tag.words() < 3 + || tag.words() % Utcb_values_per_ldt_entry)) + { + tag = commit_result(-L4_err::EInval); + return true; + } + + unsigned entry_number = utcb->values[1]; + unsigned idx = 2; + Mword *trampoline_page = (Mword *)Kmem::kernel_trampoline_page; + + for (; idx < tag.words() + ; idx += Utcb_values_per_ldt_entry, + ++entry_number) + { + Gdt_entry *d = (Gdt_entry *)&utcb->values[idx]; + if (!d->limit()) + continue; + + Ldt_user_desc info; + info.entry_number = entry_number; + info.base_addr = d->base(); + info.limit = d->limit(); + info.seg_32bit = d->seg32(); + info.contents = d->contents(); + info.read_exec_only = !d->writable(); + info.limit_in_pages = d->granularity(); + info.seg_not_present = !d->present(); + info.useable = d->avl(); + + + // Set up data on trampoline + for (unsigned i = 0; i < sizeof(info) / sizeof(Mword); i++) + *(trampoline_page + i + 1) = *(((Mword *)&info) + i); + + // Call modify_ldt for given user process + Trampoline::syscall(pid(), __NR_modify_ldt, + 1, // write LDT + Mem_layout::Trampoline_page + sizeof(Mword), + sizeof(info)); + + // Also set this for the fiasco kernel so that + // segment registers can be set, this is necessary for signal + // handling, esp. for sigreturn to work in the Fiasco kernel + // with the context of the client (gs/fs values). + if (*(trampoline_page + 1)) + Emulation::modify_ldt(*(trampoline_page + 1), // entry + 0, // base + 1); // size + } + } + return true; + } + + return false; +} + +PUBLIC +Task::~Task() +{ + free_ku_mem(); + + Lock_guard guard (&cpu_lock); + + pid_t hostpid = pid(); + ptrace (PTRACE_KILL, hostpid, NULL, NULL); + + // If we crash very early in the boot process we might get a pid of 0 + if (EXPECT_FALSE(hostpid == 0)) + return; + + while (waitpid (hostpid, NULL, 0) != hostpid) + ; +} + + +IMPLEMENT +void +Task::map_utcb_ptr_page() +{ + //Mem_space::Status res = + static_cast(this)->v_insert( + Mem_space::Phys_addr::create(Mem_layout::Utcb_ptr_frame), + Mem_space::Addr::create(Mem_layout::Utcb_ptr_page_user), + Mem_space::Size::create(Config::PAGE_SIZE), + Mem_space::Page_writable + | Mem_space::Page_user_accessible + | Mem_space::Page_cacheable); +} + diff --git a/kernel/fiasco/src/kern/ux/terminate-ux.cpp b/kernel/fiasco/src/kern/ux/terminate-ux.cpp new file mode 100644 index 00000000..4d3a2929 --- /dev/null +++ b/kernel/fiasco/src/kern/ux/terminate-ux.cpp @@ -0,0 +1,12 @@ +IMPLEMENTATION[ux]: + +#include "context.h" +#include "globals.h" +#include + +void +terminate(int x) +{ + exit(x); +} + diff --git a/kernel/fiasco/src/kern/ux/thread-ux.cpp b/kernel/fiasco/src/kern/ux/thread-ux.cpp new file mode 100644 index 00000000..cab07f50 --- /dev/null +++ b/kernel/fiasco/src/kern/ux/thread-ux.cpp @@ -0,0 +1,279 @@ +INTERFACE [ux]: + +#include + +class Trap_state; + +EXTENSION class Thread +{ +private: + static int (*int3_handler)(Trap_state*); +}; + +IMPLEMENTATION [ux]: + +#include +#include +#include "boot_info.h" +#include "config.h" // for page sizes +#include "emulation.h" +#include "kdb_ke.h" +#include "lock_guard.h" +#include "panic.h" +#include "per_cpu_data.h" +#include "utcb_init.h" + +int (*Thread::int3_handler)(Trap_state*); +DEFINE_PER_CPU Per_cpu Thread::dbg_stack; + + +IMPLEMENT static inline NEEDS ["emulation.h"] +Mword +Thread::exception_cs() +{ + return Emulation::kernel_cs(); +} + +/** + * The ux specific part of the thread constructor. + */ +PRIVATE inline +void +Thread::arch_init() +{ + // Allocate FPU state now because it indirectly calls current() + // save_state runs on a signal stack and current() doesn't work there. + if (space()) + // FIXME, space()==0 for sigma0 (or even more) + Fpu_alloc::alloc_state(space()->ram_quota(), fpu_state()); + else + Fpu_alloc::alloc_state(Ram_quota::root, fpu_state()); + + // clear out user regs that can be returned from the thread_ex_regs + // system call to prevent covert channel + Entry_frame *r = regs(); + r->sp(0); + r->ip(0); + r->cs(Emulation::kernel_cs() & ~1); // force iret trap + r->ss(Emulation::kernel_ss()); + r->flags(EFLAGS_IOPL_K | EFLAGS_IF | 2); +} + +PUBLIC static inline +void +Thread::set_int3_handler(int (*handler)(Trap_state *ts)) +{ + int3_handler = handler; +} + +PRIVATE inline bool Thread::check_trap13_kernel(Trap_state *) +{ return 1; } + +PRIVATE inline void Thread::check_f00f_bug(Trap_state *) +{} + +PRIVATE inline +unsigned +Thread::check_io_bitmap_delimiter_fault(Trap_state *) +{ return 1; } + +PRIVATE inline bool Thread::handle_sysenter_trap(Trap_state *, Address, bool) +{ return true; } + +PRIVATE inline +int +Thread::handle_not_nested_trap(Trap_state *) +{ return -1; } + +PRIVATE +int +Thread::call_nested_trap_handler(Trap_state *ts) +{ + // run the nested trap handler on a separate stack + // equiv of: return nested_trap_handler(ts) == 0 ? true : false; + + //static char nested_handler_stack [Config::PAGE_SIZE]; + unsigned phys_cpu = Cpu::phys_id_direct(); + unsigned log_cpu = Cpu::p2l(phys_cpu); + + if (log_cpu == ~0U) + { + printf("Trap on unknown CPU host-thread=%x\n", phys_cpu); + log_cpu = 0; + } + + unsigned long &ntr = nested_trap_recover.cpu(log_cpu); + + //printf("%s: lcpu%u sp=%p t=%lu nested_trap_recover=%ld handler=%p\n", + // __func__, log_cpu, (void*)Proc::stack_pointer(), ts->_trapno, + // ntr, nested_trap_handler); + + int ret; + void *stack = 0; + + if (!ntr) + stack = dbg_stack.cpu(log_cpu).stack_top; + + unsigned dummy1, dummy2, dummy3; + + asm volatile + ("movl %%esp,%[d2] \n\t" + "cmpl $0, (%[ntrp]) \n\t" + "jne 1f \n\t" + "movl %[stack],%%esp \n\t" + "1: \n\t" + "incl (%[ntrp]) \n\t" + "pushl %[d2] \n\t" + "pushl %[ntrp] \n\t" + "call *%[handler] \n\t" + "popl %[ntrp] \n\t" + "popl %%esp \n\t" + "cmpl $0,(%[ntrp]) \n\t" + "je 1f \n\t" + "decl (%[ntrp]) \n\t" + "1: \n\t" + : [ret] "=a" (ret), + [d1] "=&c" (dummy1), + [d2] "=&r" (dummy2), + "=d" (dummy3) + : [ts] "a"(ts), + [cpu] "d" (log_cpu), + [ntrp] "r" (&ntr), + [stack] "r" (stack), + [handler] "m" (nested_trap_handler) + : "memory"); + + assert (_magic == magic); + + return ret == 0 ? 0 : -1; +} + +PUBLIC inline +void +Thread::spill_fpu() +{} + + +// The "FPU not available" trap entry point +extern "C" void thread_handle_fputrap (void) { panic ("fpu trap"); } + +extern "C" void thread_timer_interrupt_slow() {} + +IMPLEMENT +void +Thread::user_invoke() +{ + { + Mword dummy; + asm volatile + (" movl %%ds , %0 \n\t" + " movl %0, %%es \n\t" + : "=r"(dummy)); + } + + Cpu::set_gs(Utcb_init::utcb_segment()); + Cpu::set_fs(Utcb_init::utcb_segment()); + + user_invoke_generic(); + + asm volatile + (" movl %%eax , %%esp \n\t" + " xorl %%ebx , %%ebx \n\t" + " xorl %%edx , %%edx \n\t" + " xorl %%esi , %%esi \n\t" // clean out user regs + " xorl %%edi , %%edi \n\t" + " xorl %%ebp , %%ebp \n\t" + " xorl %%eax , %%eax \n\t" + " iret \n\t" + : // no output + : "a" (nonull_static_cast(current()->regs())), + "c" (current()->space()->is_sigma0() // only Sigma0 gets the KIP + ? Kmem::virt_to_phys(Kip::k()) : 0)); +} + +PROTECTED inline +int +Thread::sys_control_arch(Utcb *utcb) +{ + if (utcb->values[0] & Ctl_ux_native) + _is_native = utcb->values[4] & Ctl_ux_native; + return 0; +} + +//--------------------------------------------------------------------------- +IMPLEMENTATION [ux]: + +#include "gdt.h" +#include + +KIP_KERNEL_FEATURE("segments"); + +PROTECTED inline +L4_msg_tag +Thread::invoke_arch(L4_msg_tag tag, Utcb *utcb) +{ + switch (utcb->values[0] & Opcode_mask) + { + case Op_gdt_x86: // Gdt operation + + // if no words given then return the first gdt entry + if (tag.words() == 1) + { + utcb->values[0] = Emulation::host_tls_base(); + return commit_result(0, 1); + } + + { + unsigned entry_number = utcb->values[1]; + unsigned idx = 2; + Mword *trampoline_page = (Mword *) Kmem::phys_to_virt + (Mem_layout::Trampoline_frame); + + + for (; entry_number < Gdt_user_entries + && idx < tag.words() + ; idx += 2, ++entry_number) + { + Gdt_entry *d = (Gdt_entry *)&utcb->values[idx]; + if (!d->limit()) + continue; + + Ldt_user_desc info; + info.entry_number = entry_number + Emulation::host_tls_base(); + info.base_addr = d->base(); + info.limit = d->limit(); + info.seg_32bit = d->seg32(); + info.contents = d->contents(); + info.read_exec_only = !d->writable(); + info.limit_in_pages = d->granularity(); + info.seg_not_present = !d->present(); + info.useable = d->avl(); + + // Remember descriptor for reload on thread switch + memcpy(&_gdt_user_entries[entry_number], &info, + sizeof(_gdt_user_entries[0])); + + // Set up data on trampoline + memcpy(trampoline_page + 1, &info, sizeof(info)); + + // Call set_thread_area for given user process + Trampoline::syscall(space()->pid(), 243 /* __NR_set_thread_area */, + Mem_layout::Trampoline_page + sizeof(Mword)); + + // Also set this for the fiasco kernel so that + // segment registers can be set, this is necessary for signal + // handling, esp. for sigreturn to work in the Fiasco kernel + // with the context of the client (gs/fs values). + Emulation::thread_area_host(entry_number + Emulation::host_tls_base()); + } + + if (this == current_thread()) + switch_gdt_user_entries(this); + + return commit_result(((utcb->values[1] + Emulation::host_tls_base()) << 3) + 3); + } + + default: + return commit_result(-L4_err::ENosys); + }; +} diff --git a/kernel/fiasco/src/kern/ux/timer-ux.cpp b/kernel/fiasco/src/kern/ux/timer-ux.cpp new file mode 100644 index 00000000..2bcce1bd --- /dev/null +++ b/kernel/fiasco/src/kern/ux/timer-ux.cpp @@ -0,0 +1,64 @@ +// ------------------------------------------------------------------------ +INTERFACE[ux]: + +EXTENSION class Timer +{ +private: + static void bootstrap(); +}; + +// ------------------------------------------------------------------------ +IMPLEMENTATION[ux]: + +#include +#include +#include +#include +#include "boot_info.h" +#include "initcalls.h" +#include "irq_chip.h" +#include "irq_mgr.h" +#include "pic.h" + +PUBLIC static inline NEEDS["pic.h"] +unsigned +Timer::irq() { return Pic::Irq_timer; } + +PUBLIC static inline +unsigned +Timer::irq_mode() { return 0; } + +IMPLEMENT FIASCO_INIT_CPU +void +Timer::init(unsigned) +{ + if (Boot_info::irq0_disabled()) + return; + + if (!Pic::setup_irq_prov(Pic::Irq_timer, Boot_info::irq0_path(), bootstrap)) + { + puts ("Problems setting up timer interrupt!"); + exit (1); + } +} + +IMPLEMENT FIASCO_INIT_CPU +void +Timer::bootstrap() +{ + close(Boot_info::fd()); + execl(Boot_info::irq0_path(), "[I](irq0)", NULL); +} + +PUBLIC static inline +void +Timer::acknowledge() +{} + + +IMPLEMENT inline +void +Timer::update_timer(Unsigned64) +{ + // does nothing in periodic mode +} diff --git a/kernel/fiasco/src/kern/ux/trampoline.cpp b/kernel/fiasco/src/kern/ux/trampoline.cpp new file mode 100644 index 00000000..9d0a8aed --- /dev/null +++ b/kernel/fiasco/src/kern/ux/trampoline.cpp @@ -0,0 +1,70 @@ + +INTERFACE: + +#include // for pid_t +#include "types.h" // for Mword + +class Trampoline +{}; + +IMPLEMENTATION: + +#include +#include +#include +#include +#include +#include "undef_page.h" // this undef's crap in +#include "mem_layout.h" + +PRIVATE static inline NOEXPORT +void +Trampoline::wait_for_stop (pid_t pid) +{ + int status; + + do // Loop until we get SIGTRAP. We might get orphaned SIGIO in between + { + ptrace (PTRACE_SYSCALL, pid, NULL, NULL); + waitpid (pid, &status, 0); + } + while (WIFSTOPPED (status) && WSTOPSIG (status) != SIGTRAP); +} + +/* + * Trampoline Operations + * + * These run on the trampoline page which is shared between all tasks and + * mapped into their respective address space. phys_magic is the bottom of + * the magic page where the magic code runs, phys_magic + pagesize is the + * top of the magic page, which the code uses as stack. + */ +PUBLIC static +void +Trampoline::syscall (pid_t pid, Mword eax = 0, Mword ebx = 0, + Mword ecx = 0, Mword edx = 0) +{ + struct user_regs_struct regs, tramp_regs; + + // don't perform syscalls without PID -- should only happen in tests + if (!pid) + return; + + ptrace (PTRACE_GETREGS, pid, NULL, ®s); // Save registers + + tramp_regs = regs; // Copy registers + tramp_regs.eax = eax; + tramp_regs.ebx = ebx; + tramp_regs.ecx = ecx; + tramp_regs.edx = edx; + tramp_regs.eip = Mem_layout::Trampoline_page; + + *(Mword *) Mem_layout::kernel_trampoline_page = 0x80cd; + + ptrace (PTRACE_SETREGS, pid, NULL, &tramp_regs); // Setup trampoline + + wait_for_stop (pid); // Kernel entry + wait_for_stop (pid); // Kernel exit + + ptrace (PTRACE_SETREGS, pid, NULL, ®s); // Restore registers +} diff --git a/kernel/fiasco/src/kern/ux/undef_page.h b/kernel/fiasco/src/kern/ux/undef_page.h new file mode 100644 index 00000000..1e74fb19 --- /dev/null +++ b/kernel/fiasco/src/kern/ux/undef_page.h @@ -0,0 +1,5 @@ +// undefine constants defined in since they would re-define +// variables in the config class +#undef PAGE_SHIFT +#undef PAGE_SIZE +#undef PAGE_MASK diff --git a/kernel/fiasco/src/kern/ux/usermode.cpp b/kernel/fiasco/src/kern/ux/usermode.cpp new file mode 100644 index 00000000..30d87f6f --- /dev/null +++ b/kernel/fiasco/src/kern/ux/usermode.cpp @@ -0,0 +1,763 @@ + +INTERFACE: + +#include // for siginfo_t +#include "initcalls.h" +#include "types.h" + +class Usermode +{}; + +IMPLEMENTATION: + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "undef_page.h" + +#include "boot_info.h" +#include "config.h" +#include "config_tcbsize.h" +#include "context.h" +#include "emulation.h" +#include "fpu.h" +#include "globals.h" +#include "mem_layout.h" +#include "pic.h" +#include "processor.h" +#include "regdefs.h" +#include "task.h" +#include "thread.h" +#include "thread_state.h" + +PRIVATE static +Mword +Usermode::peek_at_addr (pid_t pid, Address addr, unsigned n) +{ + Mword val; + + if ((addr & sizeof (Mword) - 1) + n > sizeof (Mword)) + val = ptrace (PTRACE_PEEKTEXT, pid, addr, NULL); + else + val = ptrace (PTRACE_PEEKTEXT, pid, addr & ~(sizeof (Mword) - 1), NULL) >> + CHAR_BIT * (addr & sizeof (Mword) - 1); + + return val & (Mword) -1 >> CHAR_BIT * (sizeof (Mword) - n); +} + +/** + * Wait for host process to stop. + * @param pid process id to wait for. + * @return signal the host process stopped with. + */ +PRIVATE static inline NOEXPORT +int +Usermode::wait_for_stop (pid_t pid) +{ + int status; + + check (waitpid (pid, &status, 0) == pid && WIFSTOPPED (status)); + + return WSTOPSIG (status); +} + +/** + * Set emulated internal processor interrupt state. + * @param mask signal mask to modify + * @param eflags processor flags register + */ +PRIVATE static inline NOEXPORT +void +Usermode::sync_interrupt_state (sigset_t *mask, Mword eflags) +{ + Proc::ux_set_virtual_processor_state (eflags); + + if (!mask) + return; + + if (eflags & EFLAGS_IF) + sigdelset (mask, SIGIO); + else + sigaddset (mask, SIGIO); +} + +/** + * Cancel a native system call in the host. + * @param pid process id of the host process. + * @param regs register set at the time of the system call. + */ +PRIVATE static inline NOEXPORT +void +Usermode::cancel_syscall (pid_t pid, struct user_regs_struct *regs) +{ + ptrace (PTRACE_POKEUSER, pid, offsetof (struct user, regs.orig_eax), -1); + ptrace (PTRACE_SYSCALL, pid, NULL, NULL); + + wait_for_stop (pid); + + regs->eax = regs->orig_eax; + ptrace (PTRACE_POKEUSER, pid, offsetof (struct user, regs.eax), regs->eax); +} + +/** + * Read debug register + * @param pid process id of the host process. + * @param reg number of debug register (0..7) + * @param value reference to register value + * @return 0 is ok + */ +PUBLIC static +int +Usermode::read_debug_register (pid_t pid, Mword reg, Mword &value) +{ + if (reg > 7) + return 0; + + int ret = ptrace (PTRACE_PEEKUSER, pid, + ((struct user *) 0)->u_debugreg + reg, NULL); + + if (ret == -1 && errno == -1) + return 0; + + value = ret; + + return 1; +} + +/** + * Write debug register + * @param pid process id of the host process. + * @param reg number of debug register (0..7) + * @param value register value to be written. + * @return 0 is ok + */ +PUBLIC static +int +Usermode::write_debug_register (pid_t pid, Mword reg, Mword value) +{ + if (reg > 7) + return 0; + + if (ptrace (PTRACE_POKEUSER, pid, + ((struct user *) 0)->u_debugreg + reg, value) == -1) + return 0; + + return 1; +} + +/** + * Set up kernel stack for kernel entry through an interrupt gate. + * We are running on the signal stack and modifying the interrupted context + * on the signal stack to allow us to return anywhere. + * Depending on the value of the code segment (CS) we set up a processor + * context of 3 (kernel mode) or 5 (user mode) words on the respective kernel + * stack, which is the current stack (kernel mode) or the stack determined by + * the Task State Segment (user mode). For some traps we need to put an + * additional error code on the stack. + * This is precisely what an ia32 processor does in hardware. + * @param context Interrupted context on signal stack + * @param trap Trap number that caused kernel entry (0xffffffff == shutdown) + * @param xss Stack Segment + * @param esp Stack Pointer + * @param efl EFLAGS + * @param xcs Code Segment + * @param eip Instruction Pointer + * @param err Error Code + * @param cr2 Page Fault Address (if applicable) + */ +PRIVATE static +void +Usermode::kernel_entry (unsigned _cpu, + struct ucontext *context, + Mword trap, + Mword xss, + Mword esp, + Mword efl, + Mword xcs, + Mword eip, + Mword err, + Mword cr2) +{ + Mword *kesp = (xcs & 3) == 3 + ? (Mword *) Cpu::cpus.cpu(_cpu).kernel_sp() - 5 + : (Mword *) context->uc_mcontext.gregs[REG_ESP] - 3; + + if (!Thread::is_tcb_address((Address)kesp)) + { + printf("KERNEL BUG at EIP:%08x ESP:%08x -- PFA:%08lx kesp=%p trap=%lx xcs=%lx @ %p %lx\n", + context->uc_mcontext.gregs[REG_EIP], + context->uc_mcontext.gregs[REG_ESP], + context->uc_mcontext.cr2, kesp, trap, xcs, &Cpu::cpus.cpu(_cpu).kernel_sp(), Cpu::cpus.cpu(_cpu).kernel_sp()); + abort(); + } + + // Make sure the kernel stack is sane + assert (Thread::is_tcb_address((Address)kesp)); + + // Make sure the kernel stack has enough space + if ((Mword) kesp % THREAD_BLOCK_SIZE <= 512) + { + printf("KERNEL BUG: Kernel stack of thread "); + printf("DBGID=%lx\n", static_cast(context_of(kesp))->dbg_info()->dbg_id()); + panic(" exceeded (%p, %c). \n" + " As a workaround, please make sure that you built \n" + " Fiasco-UX with enabled CONTEXT_4K.", + kesp, (xcs & 3) == 2 ? 'k' : 'u'); + } + + efl &= ~EFLAGS_IF; + + switch (xcs & 3) + { + case 3: + *(kesp + 4) = xss; + *(kesp + 3) = esp; + + case 0: + *(kesp + 2) = efl | (Proc::processor_state() & EFLAGS_IF); + *(kesp + 1) = xcs & ~1; // trap on iret + *(kesp + 0) = eip; + } + + switch (trap) + { + case 0xe: // Page Fault + Emulation::set_page_fault_addr (cr2); + case 0x8: // Double Fault + case 0xa: // Invalid TSS + case 0xb: // Segment Not Present + case 0xc: // Stack Fault + case 0xd: // General Protection Fault + case 0x11: // Alignment Check + *--kesp = err; + } + + context->uc_mcontext.gregs[REG_ESP] = (Mword) kesp; + context->uc_mcontext.gregs[REG_EIP] = Emulation::idt_vector (trap, false); + context->uc_mcontext.gregs[REG_EFL] = efl & ~(EFLAGS_TF | EFLAGS_NT | EFLAGS_RF | EFLAGS_VM); + sync_interrupt_state (&context->uc_sigmask, efl); + + // Make sure interrupts are off + assert (!Proc::interrupts()); +} + +PRIVATE static inline NOEXPORT +Mword +Usermode::kip_syscall (Address eip) +{ + if ((eip & Config::PAGE_MASK) != Mem_layout::Syscalls || eip & 0xff) + return 0; + + Mword trap = 0x30 + (eip - Mem_layout::Syscalls >> 8); + + return Emulation::idt_vector (trap, true) ? trap : 0; +} + +PRIVATE static inline NOEXPORT +Mword +Usermode::l4_syscall (Mword opcode) +{ + if (EXPECT_FALSE ((opcode & 0xff) != 0xcd)) + return 0; + + Mword trap = opcode >> 8; + + return Emulation::idt_vector (trap, true) ? trap : 0; +} + +PRIVATE static inline NOEXPORT NEEDS["thread_state.h"] +bool +Usermode::user_exception (unsigned _cpu, pid_t pid, struct ucontext *context, + struct user_regs_struct *regs) +{ + Mword trap, error = 0, addr = 0; + + if (EXPECT_FALSE ((trap = kip_syscall (regs->eip)))) + { + Context *t = context_of(((Mword *)Cpu::cpus.cpu(_cpu).kernel_sp()) - 1); + + /* The alien syscall code in entry-*.S substracts 2 bytes from the + * EIP to put the EIP back on the instruction to reexecute it. + * 'int X' and sysenter etc. are 2 byte instructions. + * So we add 2 here to have the EIP in the right position afterwards. + * + * Furthermore we leave ESP and EIP (with the adjustment) where they + * are so that the syscall can be re-executed. + * + * This is not a problem for native as it does not trap on the + * 'call 0xea......' itself there but on the real int/sysenter/etc. + * instructions in the syscall page. + */ + if (EXPECT_FALSE((t->state() & (Thread_alien | Thread_dis_alien)) + == Thread_alien || t->space_ref()->user_mode())) + regs->eip += 2; + else + { + regs->eip = peek_at_addr (pid, regs->esp, 4); + regs->esp += 4; + } + } + + else if ((trap = l4_syscall (peek_at_addr (pid, regs->eip, 2)))) + regs->eip += 2; + + else + { + struct ucontext *exception_context; + + memcpy ((void *) Mem_layout::kernel_trampoline_page, + (void *) &Mem_layout::task_sighandler_start, + &Mem_layout::task_sighandler_end - + &Mem_layout::task_sighandler_start); + + ptrace (PTRACE_CONT, pid, NULL, SIGSEGV); + + wait_for_stop (pid); + + // See corresponding code in sighandler.S + exception_context = reinterpret_cast + (Mem_layout::kernel_trampoline_page + + *reinterpret_cast
+ (Mem_layout::kernel_trampoline_page + 0x100)); + + addr = exception_context->uc_mcontext.cr2; + trap = exception_context->uc_mcontext.gregs[REG_TRAPNO]; + error = exception_context->uc_mcontext.gregs[REG_ERR]; + + switch (trap) + { + case 0xd: + if (Boot_info::emulate_clisti()) + switch (peek_at_addr (pid, regs->eip, 1)) + { + case 0xfa: // cli + Pic::set_owner (Boot_info::pid()); + regs->eip++; + regs->eflags &= ~EFLAGS_IF; + sync_interrupt_state (0, regs->eflags); + check(ptrace (PTRACE_SETREGS, pid, NULL, regs)); + return false; + + case 0xfb: // sti + Pic::set_owner (pid); + regs->eip++; + regs->eflags |= EFLAGS_IF; + sync_interrupt_state (0, regs->eflags); + check(ptrace (PTRACE_SETREGS, pid, NULL, regs)); + return false; + } + break; + + case 0xe: + error |= PF_ERR_USERADDR; + break; + } + } + + kernel_entry (_cpu, context, trap, + regs->xss, /* XSS */ + regs->esp, /* ESP */ + regs->eflags, /* EFL */ + regs->xcs, /* XCS */ + regs->eip, /* EIP */ + error, /* ERR */ + addr); /* CR2 */ + + return true; +} + +PRIVATE static inline NOEXPORT +bool +Usermode::user_emulation (unsigned _cpu, int stop, pid_t pid, + struct ucontext *context, + struct user_regs_struct *regs) +{ + Mword trap, error = 0; + + switch (stop) + { + case SIGSEGV: + return user_exception (_cpu, pid, context, regs); + + case SIGIO: + int irq_pend; + if ((irq_pend = Pic::irq_pending()) == -1) + return false; + Pic::eat (irq_pend); + trap = Pic::map_irq_to_gate (irq_pend); + break; + + case SIGTRAP: + if (peek_at_addr (pid, regs->eip - 1, 1) == 0xcc) + { + trap = 0x3; + break; + } + else if (peek_at_addr (pid, regs->eip - 2, 2) == 0x80cd) + { + cancel_syscall (pid, regs); + trap = 0xd; + error = 0x80 << 3 | 2; + regs->eip -= 2; + break; + } + trap = 0x1; + break; + + case SIGILL: + trap = 0x6; + break; + + case SIGFPE: + trap = 0x10; + break; + + default: + trap = 0x1; + break; + } + + kernel_entry (_cpu, context, trap, + regs->xss, /* XSS */ + regs->esp, /* ESP */ + regs->eflags, /* EFL */ + regs->xcs, /* XCS */ + regs->eip, /* EIP */ + error, /* ERR */ + 0); /* CR2 */ + + return true; +} + +/** + * IRET to a user context. + * We restore the saved context on the stack, namely EIP, CS, EFLAGS, ESP, SS. + * Additionally all register values are transferred to the task's register set. + * @param ctx Kern context during iret + */ +PRIVATE static inline NOEXPORT +void +Usermode::iret_to_user_mode (unsigned _cpu, + struct ucontext *context, Mword *kesp) +{ + struct user_regs_struct regs; + int irq_pend; + Context *t = context_of (kesp); + pid_t pid = t->vcpu_aware_space()->pid(); + + Pic::set_owner (pid); + + /* + * If there are any interrupts pending up to this point, don't start the task + * but let it enter kernel immediately. Any interrupts occuring beyond this + * point will go directly to the task. + */ + if ((irq_pend = Pic::irq_pending()) != -1) + { + Pic::eat (irq_pend); + + Pic::set_owner (Boot_info::pid()); + + kernel_entry (_cpu, context, + Pic::map_irq_to_gate (irq_pend), + *(kesp + 4), /* XSS */ + *(kesp + 3), /* ESP */ + *(kesp + 2), /* EFL */ + *(kesp + 1) | 3,/* XCS */ + *(kesp + 0), /* EIP */ + 0, /* ERR */ + 0); /* CR2 */ + return; + } + + // Restore these from the kernel stack (iret context) + regs.eip = *(kesp + 0); + regs.xcs = *(kesp + 1) | 3; + regs.eflags = *(kesp + 2); + regs.esp = *(kesp + 3); + regs.xss = *(kesp + 4); + + // Copy these from the kernel + regs.eax = context->uc_mcontext.gregs[REG_EAX]; + regs.ebx = context->uc_mcontext.gregs[REG_EBX]; + regs.ecx = context->uc_mcontext.gregs[REG_ECX]; + regs.edx = context->uc_mcontext.gregs[REG_EDX]; + regs.esi = context->uc_mcontext.gregs[REG_ESI]; + regs.edi = context->uc_mcontext.gregs[REG_EDI]; + regs.ebp = context->uc_mcontext.gregs[REG_EBP]; + regs.xds = context->uc_mcontext.gregs[REG_DS]; + regs.xes = context->uc_mcontext.gregs[REG_ES]; + regs.xfs = Cpu::get_fs(); + regs.xgs = Cpu::get_gs(); + + // ptrace will return with an error if we try to load invalid values to + // segment registers + int r = ptrace (PTRACE_SETREGS, pid, NULL, ®s); + if (EXPECT_FALSE(r == -EPERM)) + { + WARN("Failure setting registers, probably invalid segment values.\n" + " Fixing up!\n"); + regs.xds = Cpu::kern_ds(); + regs.xes = Cpu::kern_es(); + regs.xgs = 0; + check(ptrace (PTRACE_SETREGS, pid, NULL, ®s)); + } + else + assert(r == 0); + + Fpu::restore_state (t->fpu_state()); + + for (;;) + { + ptrace (t->is_native() ? PTRACE_CONT : PTRACE_SYSCALL, pid, NULL, NULL); + + int stop = wait_for_stop (pid); + + if (EXPECT_FALSE (stop == SIGWINCH || stop == SIGTERM || stop == SIGINT)) + continue; + + check(ptrace (PTRACE_GETREGS, pid, NULL, ®s) == 0); + + if (EXPECT_TRUE (user_emulation (_cpu, stop, pid, context, ®s))) + break; + } + + Pic::set_owner (Boot_info::pid()); + + if (Pic::irq_pending() != -1) + kill (Boot_info::pid(), SIGIO); + + context->uc_mcontext.gregs[REG_EAX] = regs.eax; + context->uc_mcontext.gregs[REG_EBX] = regs.ebx; + context->uc_mcontext.gregs[REG_ECX] = regs.ecx; + context->uc_mcontext.gregs[REG_EDX] = regs.edx; + context->uc_mcontext.gregs[REG_ESI] = regs.esi; + context->uc_mcontext.gregs[REG_EDI] = regs.edi; + context->uc_mcontext.gregs[REG_EBP] = regs.ebp; + context->uc_mcontext.gregs[REG_DS] = regs.xds; + context->uc_mcontext.gregs[REG_ES] = regs.xes; + Cpu::set_fs(regs.xfs); + Cpu::set_gs(regs.xgs); + + Fpu::save_state (t->fpu_state()); +} + +/** + * IRET to a kernel context. + * We restore the saved context on the stack, namely EIP and EFLAGS. + * We do NOT restore CS, because the kernel thinks it has privilege level 0 + * but in usermode it has to have privilege level 3. We also adjust ESP by + * 3 words, thus clearing the context from the stack. + * @param ctx Kern context during iret + */ +PRIVATE static inline NOEXPORT +void +Usermode::iret_to_kern_mode (struct ucontext *context, Mword *kesp) +{ + context->uc_mcontext.gregs[REG_EIP] = *(kesp + 0); + context->uc_mcontext.gregs[REG_EFL] = *(kesp + 2); + context->uc_mcontext.gregs[REG_ESP] += 3 * sizeof (Mword); +} + +/** + * Emulate IRET instruction. + * Depending on the value of the saved code segment (CS) on the kernel stack + * we return to kernel mode (CPL == 0) or user mode (CPL == 2). + * @param ctx Kern context during iret + */ +PRIVATE static inline NOEXPORT +void +Usermode::iret (unsigned _cpu, struct ucontext *context) +{ + Mword *kesp = (Mword *) context->uc_mcontext.gregs[REG_ESP]; + + sync_interrupt_state (&context->uc_sigmask, *(kesp + 2)); + + switch (*(kesp + 1) & 3) + { + case 0: /* CPL 0 -> Kernel */ + iret_to_kern_mode (context, kesp); + break; + + case 2: /* CPL 2 -> User */ + iret_to_user_mode (_cpu, context, kesp); + break; + + default: + assert(0); + } +} + +PRIVATE static +void +Usermode::emu_handler (int, siginfo_t *, void *ctx) +{ + struct ucontext *context = reinterpret_cast(ctx); + unsigned int trap = context->uc_mcontext.gregs[REG_TRAPNO]; + + unsigned _cpu = Cpu::p2l(Cpu::phys_id_direct()); + + if (trap == 0xd) /* General protection fault */ + { + unsigned char opcode = *reinterpret_cast + (context->uc_mcontext.gregs[REG_EIP]); + + switch (opcode) + { + case 0xfa: /* cli */ + context->uc_mcontext.gregs[REG_EIP]++; + context->uc_mcontext.gregs[REG_EFL] &= ~EFLAGS_IF; + sync_interrupt_state (&context->uc_sigmask, + context->uc_mcontext.gregs[REG_EFL]); + return; + + case 0xfb: /* sti */ + context->uc_mcontext.gregs[REG_EIP]++; + context->uc_mcontext.gregs[REG_EFL] |= EFLAGS_IF; + sync_interrupt_state (&context->uc_sigmask, + context->uc_mcontext.gregs[REG_EFL]); + return; + + case 0xcf: /* iret */ + iret (_cpu, context); + return; + } + } + + kernel_entry (_cpu, context, trap, + context->uc_mcontext.gregs[REG_SS], + context->uc_mcontext.gregs[REG_ESP], + context->uc_mcontext.gregs[REG_EFL], + context->uc_mcontext.gregs[REG_CS] & ~3, + context->uc_mcontext.gregs[REG_EIP], + context->uc_mcontext.gregs[REG_ERR] & ~PF_ERR_USERMODE, + context->uc_mcontext.cr2); +} + +PRIVATE static +void +Usermode::int_handler (int, siginfo_t *, void *ctx) +{ + struct ucontext *context = reinterpret_cast(ctx); + int irq; + unsigned long gate; + + if ((irq = Pic::irq_pending()) == -1) + return; + + if (Pic::get_ipi_gate(irq, gate) == false) + gate = Pic::map_irq_to_gate(irq); + + Pic::eat (irq); + + kernel_entry (Cpu::p2l(Cpu::phys_id_direct()), + context, + gate, + context->uc_mcontext.gregs[REG_SS], /* XSS */ + context->uc_mcontext.gregs[REG_ESP], /* ESP */ + context->uc_mcontext.gregs[REG_EFL], /* EFL */ + context->uc_mcontext.gregs[REG_CS] & ~3,/* XCS */ + context->uc_mcontext.gregs[REG_EIP], /* EIP */ + 0, /* ERR */ + 0); /* CR2 */ +} + +PRIVATE static +void +Usermode::jdb_handler (int sig, siginfo_t *, void *ctx) +{ + struct ucontext *context = reinterpret_cast(ctx); + + if (!Thread::is_tcb_address(context->uc_mcontext.gregs[REG_ESP])) + return; + + /* + * If a SIGSEGV is pending at the same time as SIGINT, i.e. because + * someone pressed Ctrl-C on an sti instruction, SIGINT will be delivered + * first. Since we warp to a different execution path the pending SIGSEGV + * will then hit an innocent instruction elsewhere with fatal consequences. + * Therefore a pending SIGSEGV must be cancelled - it will later reoccur. + */ + + signal (SIGSEGV, SIG_IGN); // Cancel signal + set_signal (SIGSEGV); // Reinstall handler + + kernel_entry (Cpu::p2l(Cpu::phys_id_direct()), + context, sig == SIGTRAP ? 3 : 1, + context->uc_mcontext.gregs[REG_SS], /* XSS */ + context->uc_mcontext.gregs[REG_ESP], /* ESP */ + context->uc_mcontext.gregs[REG_EFL], /* EFL */ + context->uc_mcontext.gregs[REG_CS] & ~3,/* XCS */ + context->uc_mcontext.gregs[REG_EIP], /* EIP */ + 0, /* ERR */ + 0); /* CR2 */ +} + +PUBLIC static +void +Usermode::set_signal (int sig) +{ + void (*func)(int, siginfo_t *, void *); + struct sigaction action; + + switch (sig) + { + case SIGIO: func = int_handler; break; + case SIGSEGV: func = emu_handler; break; + default: func = jdb_handler; break; + } + + sigfillset (&action.sa_mask); /* No other signals while we run */ + action.sa_sigaction = func; + action.sa_flags = SA_RESTART | SA_ONSTACK | SA_SIGINFO; + + check (sigaction (sig, &action, NULL) == 0); +} + +PUBLIC static FIASCO_INIT_CPU +void +Usermode::init(unsigned cpu) +{ + stack_t stack; + + /* We want signals, aka interrupts to be delivered on an alternate stack */ + if (cpu == 0) + stack.ss_sp = (void *) Mem_layout::phys_to_pmem + (Mem_layout::Sigstack_cpu0_start_frame); + else + stack.ss_sp = Kmem_alloc::allocator()->alloc(Mem_layout::Sigstack_log2_size); + stack.ss_size = Mem_layout::Sigstack_size; + stack.ss_flags = 0; + + check (sigaltstack (&stack, NULL) == 0); + + signal (SIGWINCH, SIG_IGN); + signal (SIGPROF, SIG_IGN); + signal (SIGHUP, SIG_IGN); + signal (SIGUSR1, SIG_IGN); + signal (SIGUSR2, SIG_IGN); + + set_signal (SIGSEGV); + set_signal (SIGIO); + if (cpu == 0) + set_signal (SIGINT); + else + signal (SIGINT, SIG_IGN); + set_signal (SIGTRAP); + set_signal (SIGTERM); + set_signal (SIGXCPU); +} diff --git a/kernel/fiasco/src/kern/ux/utcb_init-ux.cpp b/kernel/fiasco/src/kern/ux/utcb_init-ux.cpp new file mode 100644 index 00000000..4a89cc95 --- /dev/null +++ b/kernel/fiasco/src/kern/ux/utcb_init-ux.cpp @@ -0,0 +1,35 @@ +INTERFACE [ux]: + +EXTENSION class Utcb_init +{ +public: + /** + * Value for GS and FS. + * @return Value the GS and FS register has to be loaded with when + * entering user mode. + */ + static Unsigned32 utcb_segment(); +}; + + +//----------------------------------------------------------------------------- +IMPLEMENTATION [ux]: + +#include "emulation.h" +#include "kip.h" +#include "kmem.h" +#include "vmem_alloc.h" + +IMPLEMENT static inline +Unsigned32 +Utcb_init::utcb_segment() +{ return 7; } // RPL=3, TI=LDT, Index=0 + +IMPLEMENT +void +Utcb_init::init() +{ + Emulation::modify_ldt (0, // entry + Mem_layout::Utcb_ptr_page_user, // address + sizeof (Address) - 1); // limit +} diff --git a/kernel/fiasco/src/kern/ux/vhw.cpp b/kernel/fiasco/src/kern/ux/vhw.cpp new file mode 100644 index 00000000..a96ac9b4 --- /dev/null +++ b/kernel/fiasco/src/kern/ux/vhw.cpp @@ -0,0 +1,110 @@ +/* + * Description for driver memory areas, used under UX. + */ + +INTERFACE[ux,ia32]: + +#include "types.h" + +class Vhw_entry +{ +public: + + enum Vhw_entry_type + { + TYPE_NONE, + TYPE_FRAMEBUFFER, + TYPE_INPUT, + TYPE_NET, + }; + +private: + Vhw_entry_type _type; // type of the descriptor + Unsigned32 _provider_pid; // Host PID of the program providing this area + + Address _mem_start; // start of a memory area in physical memory + Address _mem_size; // size of the memory area + + Unsigned32 _irq_no; // IRQ number for notification events + Unsigned32 _fd; // Communication file descriptor + +public: + + void type(enum Vhw_entry_type t) { _type = t; } + void provider_pid(Unsigned32 p) { _provider_pid = p; } + void mem_start(Address a) { _mem_start = a; } + void mem_size(Address a) { _mem_size = a; } + void irq_no(Unsigned32 i) { _irq_no = i; } + void fd(Unsigned32 i) { _fd = i; } +}; + +// ------- + +class Vhw_descriptor +{ +public: + Unsigned32 magic() const { return _magic; } + Unsigned8 version() const { return _version; } + Unsigned8 count() const { return _count; } + +private: + + static Unsigned8 const count_const = 3; // nr of descriptors + + Unsigned32 _magic; // magic value + Unsigned8 _version; // version of this description format + Unsigned8 _count; // nr of descriptors + Unsigned8 _pad1; + Unsigned8 _pad2; + + Vhw_entry descs[count_const]; +}; + +// ----------------------------------------------------------------- +IMPLEMENTATION[ux,ia32]: + +PUBLIC +void +Vhw_entry::reset() +{ + type(TYPE_NONE); +} + +PUBLIC +void +Vhw_entry::set(enum Vhw_entry_type t, + Address start, Address size, + Unsigned32 irqno, Unsigned32 provpid, Unsigned32 fdp) +{ + type(t); + mem_start(start); + mem_size(size); + irq_no(irqno); + provider_pid(provpid); + fd(fdp); +} + +// ------- + +PUBLIC +void +Vhw_descriptor::init() +{ + _magic = 0x56687765; + _version = 1; + _count = count_const; + + for (int i = 0; i < count_const; i++) + descs[i].reset(); +} + +PUBLIC +void +Vhw_descriptor::set_desc(Vhw_entry::Vhw_entry_type type, + Address mem_start, Address mem_size, + Unsigned32 irq_no, Unsigned32 provider_pid, + Unsigned32 fdp) +{ + if (type != Vhw_entry::TYPE_NONE) + descs[type - 1].set(type, mem_start, mem_size, irq_no, provider_pid, fdp); +} diff --git a/kernel/fiasco/src/kern/ux/vmem_alloc-ux.cpp b/kernel/fiasco/src/kern/ux/vmem_alloc-ux.cpp new file mode 100644 index 00000000..af0e250b --- /dev/null +++ b/kernel/fiasco/src/kern/ux/vmem_alloc-ux.cpp @@ -0,0 +1,24 @@ + +IMPLEMENTATION[ux]: + +#include +#include +#include +#include +#include "boot_info.h" +#include "panic.h" + +IMPLEMENT inline NEEDS [, , , , + "boot_info.h", "config.h", "panic.h"] +void +Vmem_alloc::page_map(void *address, int order, Zero_fill zf, Address phys) +{ + if (mmap (address, (1 << order) * Config::PAGE_SIZE, + PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, + Boot_info::fd(), phys) == MAP_FAILED) + panic ("mmap error: %s", strerror (errno)); + + if (zf == ZERO_FILL) + memset(address, 0, (1 << order) * Config::PAGE_SIZE); +} + diff --git a/kernel/fiasco/src/kern/vcpu.cpp b/kernel/fiasco/src/kern/vcpu.cpp new file mode 100644 index 00000000..8ceffc20 --- /dev/null +++ b/kernel/fiasco/src/kern/vcpu.cpp @@ -0,0 +1,39 @@ +INTERFACE: + +#include "entry_frame.h" +#include "trap_state.h" + +class Vcpu_state +{ + MEMBER_OFFSET(); +public: + enum State + { + F_irqs = 0x1, + F_page_faults = 0x2, + F_exceptions = 0x4, + F_debug_exc = 0x8, + F_user_mode = 0x20, + F_fpu_enabled = 0x80, + F_traps = F_irqs | F_page_faults, // | F_exceptions, + }; + + enum Sticky_flags + { + Sf_irq_pending = 0x01, + }; + + Trap_state _ts; + Syscall_frame _ipc_regs; + + Unsigned16 state; + Unsigned16 _saved_state; + Unsigned16 sticky_flags; + Unsigned16 _reserved; + + L4_obj_ref user_task; + + Mword _entry_sp; + Mword _entry_ip; + Mword _sp; +}; diff --git a/kernel/fiasco/src/kern/vkey.cpp b/kernel/fiasco/src/kern/vkey.cpp new file mode 100644 index 00000000..b4cfd7a6 --- /dev/null +++ b/kernel/fiasco/src/kern/vkey.cpp @@ -0,0 +1,236 @@ +INTERFACE: + +class Irq_base; + +class Vkey +{ +public: + enum Echo_type { Echo_off = 0, Echo_on = 1, Echo_crnl = 2 }; +}; + + +// --------------------------------------------------------------------------- +IMPLEMENTATION: + +#include "irq_chip.h" + +static Irq_base *vkey_irq; + +PUBLIC static +void +Vkey::irq(Irq_base *i) +{ vkey_irq = i; } + +// --------------------------------------------------------------------------- +IMPLEMENTATION [debug && serial && !ux]: + +#include + +#include "config.h" +#include "cpu.h" +#include "globals.h" +#include "kernel_console.h" +#include "keycodes.h" +#include "uart.h" + +static Vkey::Echo_type vkey_echo; +static char vkey_buffer[256]; +static unsigned vkey_tail, vkey_head; +static Console *uart = Kconsole::console()->find_console(Console::UART); + +PUBLIC static +void +Vkey::set_echo(Echo_type echo) +{ + vkey_echo = echo; +} + +PRIVATE static +bool +Vkey::add(int c) +{ + bool hit = false; + unsigned nh = (vkey_head + 1) % sizeof(vkey_buffer); + unsigned oh = vkey_head; + if (nh != vkey_tail) + { + vkey_buffer[vkey_head] = c; + vkey_head = nh; + } + + if (oh == vkey_tail) + hit = true; + + if (vkey_echo == Vkey::Echo_crnl && c == '\r') + c = '\n'; + + if (vkey_echo) + putchar(c); + + return hit; +} + +PRIVATE static +bool +Vkey::add(const char *seq) +{ + bool hit = false; + for (; *seq; ++seq) + hit |= add(*seq); + return hit; +} + +PRIVATE static +void +Vkey::trigger() +{ + if (vkey_irq) + vkey_irq->hit(0); +} + +PUBLIC static +void +Vkey::add_char(int v) +{ + if (add(v)) + trigger(); +} + +PUBLIC static +int +Vkey::check_() +{ + if (!uart) + return 1; + + int ret = 1; + bool hit = false; + + // disable last branch recording, branch trace recording ... + Cpu::cpus.cpu(current_cpu()).debugctl_disable(); + + while (1) + { + int c = uart->getchar(false); + + if (c == -1) + break; + + if (c == KEY_ESC) + { + ret = 0; // break into kernel debugger + break; + } + + switch (c) + { + case KEY_CURSOR_UP: hit |= add("\033[A"); break; + case KEY_CURSOR_DOWN: hit |= add("\033[B"); break; + case KEY_CURSOR_LEFT: hit |= add("\033[D"); break; + case KEY_CURSOR_RIGHT: hit |= add("\033[C"); break; + case KEY_CURSOR_HOME: hit |= add("\033[1~"); break; + case KEY_CURSOR_END: hit |= add("\033[4~"); break; + case KEY_PAGE_UP: hit |= add("\033[5~"); break; + case KEY_PAGE_DOWN: hit |= add("\033[6~"); break; + case KEY_INSERT: hit |= add("\033[2~"); break; + case KEY_DELETE: hit |= add("\033[3~"); break; + case KEY_F1: hit |= add("\033OP"); break; + case KEY_BACKSPACE: hit |= add(127); break; + case KEY_TAB: hit |= add(9); break; + case KEY_ESC: hit |= add(27); break; + case KEY_RETURN: hit |= add(13); break; + default: hit |= add(c); break; + } + } + + if (hit) + trigger(); + + // Hmmm, we assume that a console with the UART flag set is of type Uart + if (Config::serial_esc == Config::SERIAL_ESC_IRQ) + static_cast(uart)->enable_rcv_irq(); + + // reenable debug stuff (undo debugctl_disable) + Cpu::cpus.cpu(current_cpu()).debugctl_enable(); + + return ret; +} + +PUBLIC static +int +Vkey::get() +{ + if (vkey_tail != vkey_head) + return vkey_buffer[vkey_tail]; + + return -1; +} + +PUBLIC static +void +Vkey::clear() +{ + if (vkey_tail != vkey_head) + vkey_tail = (vkey_tail + 1) % sizeof(vkey_buffer); +} + +//---------------------------------------------------------------------------- +IMPLEMENTATION [!debug || !serial || ux]: + +PUBLIC static inline +void +Vkey::set_echo(Echo_type) +{} + +PUBLIC static inline +void +Vkey::clear() +{} + +PUBLIC static inline +void +Vkey::add_char(int) +{} + +//---------------------------------------------------------------------------- +IMPLEMENTATION [debug && (!serial || ux)]: + +#include "kernel_console.h" + +PUBLIC static +int +Vkey::get() +{ + return Kconsole::console()->getchar(0); +} + +//---------------------------------------------------------------------------- +IMPLEMENTATION [!debug && serial]: + +#include "kernel_console.h" +#include "kernel_uart.h" + +static Console *uart = Kconsole::console()->find_console(Console::UART); + +PUBLIC static +int +Vkey::get() +{ + return uart->getchar(false); +} + +//---------------------------------------------------------------------------- +IMPLEMENTATION[!debug && !serial]: + +PUBLIC static +int +Vkey::get() +{ return -1; } + +//---------------------------------------------------------------------------- +IMPLEMENTATION[!debug || !serial]: + +PUBLIC static inline +int +Vkey::check_(int = -1) +{ return 0; } diff --git a/kernel/fiasco/src/kern/vlog.cpp b/kernel/fiasco/src/kern/vlog.cpp new file mode 100644 index 00000000..13b75a66 --- /dev/null +++ b/kernel/fiasco/src/kern/vlog.cpp @@ -0,0 +1,244 @@ +INTERFACE: + +#include "icu_helper.h" + +class Irq; + +class Vlog : public Icu_h, public Irq_chip_soft +{ + FIASCO_DECLARE_KOBJ(); +public: + enum O_flags + { + F_ONLCR = 000004, ///< Map NL to CR-NL on output + F_OCRNL = 000010, ///< Map CR to NL on output + F_ONLRET = 000040, ///< Do not ouput CR + }; + + enum I_flags + { + F_INLCR = 000100, + F_IGNCR = 000200, + F_ICRNL = 000400, + }; + + enum L_flags + { + F_ECHO = 000010, + }; + +private: + Irq_base *_irq; + Mword _i_flags; + Mword _o_flags; + Mword _l_flags; +}; + +IMPLEMENTATION: + +#include "entry_frame.h" +#include "map_util.h" +#include "mem_space.h" +#include "l4_buf_iter.h" +#include "thread.h" +#include "vkey.h" +#include "irq.h" +#include "irq_controller.h" + + +FIASCO_DEFINE_KOBJ(Vlog); + +PUBLIC +Vlog::Vlog() +: _irq(0), + _i_flags(F_ICRNL), _o_flags(F_ONLCR), _l_flags(F_ECHO) +{ + Vkey::set_echo(Vkey::Echo_crnl); + // CAP idx 5 is the initial kernel stream + initial_kobjects.register_obj(this, 5); +} + +PUBLIC void +Vlog::operator delete (void *) +{ + printf("WARNING: tried to delete kernel Vlog object.\n"); +} + + +PRIVATE inline NOEXPORT +void +Vlog::log_string(Syscall_frame *f, Utcb const *u) +{ + L4_snd_item_iter snd_items(u, f->tag().words()); + + unsigned len = u->values[1]; + char const *str = (char const *)&u->values[2]; + + if (len > sizeof(u->values) - sizeof(u->values[0]) * 2) + return; + + while (len--) + { + int c = *str++; + + // the kernel does this anyway +#if 0 + if (_o_flags & F_ONLCR && c == '\n') + putchar('\r'); +#endif + + if (_o_flags & F_OCRNL && c == '\r') + c = '\n'; + + if (_o_flags & F_ONLRET && c == '\r') + continue; + + putchar(c); + } +} + +PRIVATE inline NOEXPORT +L4_msg_tag +Vlog::get_input(Mword rights, Syscall_frame *f, Utcb *u) +{ + (void)f; + + if (!have_receive(u)) + return commit_result(0); + + if (!(rights & L4_fpage::X)) + return commit_result(-L4_err::EPerm); + + char *buffer = reinterpret_cast(&u->values[1]); + long cnt_down = u->values[0] >> 16; + int i = 0; + while (cnt_down && (i = Vkey::get()) != -1) + { + Vkey::clear(); + + if (_i_flags & F_INLCR && i == '\n') + i = '\r'; + + if (_i_flags & F_IGNCR && i == '\r') + continue; + + if (_i_flags & F_ICRNL && i == '\r') + i = '\n'; + + *buffer = i; + ++buffer; + --cnt_down; + } + + u->values[0] = buffer - reinterpret_cast(&u->values[1]); + if (i == -1) + u->values[0] |= 1UL<<31; + return commit_result(0); +} + +PUBLIC +void +Vlog::bind(Irq_base *irq, Mword irqnum) +{ + Irq_chip_soft::bind(irq, irqnum); + _irq = irq; + Vkey::irq(irq); +} + +PUBLIC +L4_msg_tag +Vlog::icu_bind_irq(Irq *irq_o, unsigned irqnum) +{ + if (irqnum > 0) + return commit_result(-L4_err::EInval); + + if (_irq) + _irq->unbind(); + + bind(irq_o, irqnum); + return commit_result(0); +} + + +PRIVATE inline NOEXPORT +L4_msg_tag +Vlog::set_attr(Mword, Syscall_frame const *, Utcb const *u) +{ + _i_flags = u->values[1]; + _o_flags = u->values[2] | F_ONLCR; + _l_flags = u->values[3]; + Vkey::set_echo((!(_l_flags & F_ECHO)) + ? Vkey::Echo_off + : (_o_flags & F_OCRNL + ? Vkey::Echo_crnl + : Vkey::Echo_on)); + + return commit_result(0); +} + +PRIVATE inline NOEXPORT +L4_msg_tag +Vlog::get_attr(Mword, Syscall_frame *, Utcb *u) +{ + if (!have_receive(u)) + return commit_result(0); + + u->values[1] = _i_flags; + u->values[2] = _o_flags; + u->values[3] = _l_flags; + return commit_result(0, 4); +} + +PUBLIC inline +Irq_base * +Vlog::icu_get_irq(unsigned irqnum) +{ + if (irqnum > 0) + return 0; + + return _irq; +} + + +PUBLIC inline +void +Vlog::icu_get_info(Mword *features, Mword *num_irqs, Mword *num_msis) +{ + *features = 0; // supported features (only normal irqs) + *num_irqs = 1; + *num_msis = 0; +} + + +PUBLIC +L4_msg_tag +Vlog::kinvoke(L4_obj_ref ref, Mword rights, Syscall_frame *f, + Utcb const *r_msg, Utcb *s_msg) +{ + L4_msg_tag const t = f->tag(); + + if (t.proto() == L4_msg_tag::Label_irq) + return Icu_h::icu_invoke(ref, rights, f, r_msg, s_msg); + else if (t.proto() != L4_msg_tag::Label_log) + return commit_result(-L4_err::EBadproto); + + switch (r_msg->values[0]) + { + case 0: + log_string(f, r_msg); + return no_reply(); + + case 2: // set attr + return set_attr(rights, f, r_msg); + + case 3: // get attr + return get_attr(rights, f, s_msg); + + default: + return get_input(rights, f, s_msg); + } +} + + +static Vlog __vlog; + diff --git a/kernel/fiasco/src/kern/vm_factory.cpp b/kernel/fiasco/src/kern/vm_factory.cpp new file mode 100644 index 00000000..5f6d5e06 --- /dev/null +++ b/kernel/fiasco/src/kern/vm_factory.cpp @@ -0,0 +1,10 @@ +INTERFACE: + +class Vm; +class Ram_quota; + +class Vm_factory +{ +public: + static Vm *create(Ram_quota *quota, int *err); +}; diff --git a/kernel/fiasco/src/kern/vmem_alloc.cpp b/kernel/fiasco/src/kern/vmem_alloc.cpp new file mode 100644 index 00000000..e570ea60 --- /dev/null +++ b/kernel/fiasco/src/kern/vmem_alloc.cpp @@ -0,0 +1,42 @@ +INTERFACE: + +#include "paging.h" + +class Mem_space; + +class Vmem_alloc +{ +public: + + enum Zero_fill { + NO_ZERO_FILL = 0, + ZERO_FILL, ///< Fill the page with zeroes. + }; + + enum + { + Kernel = 0, + User = 1 + }; + + static void init(); + + static void *page_unmap(void *page); + + /** + * Allocate a page of kernel memory and insert it into the master + * page directory. + * + * @param address the virtual address where to map the page. + * @param zf zero fill or zero map. + * @param pa page attributes to use for the page table entry. + */ + static void *page_alloc(void *address, + Zero_fill zf = NO_ZERO_FILL, + unsigned mode = Kernel); + +private: + static void page_map(void *address, int order, Zero_fill zf, + Address phys); +}; + diff --git a/kernel/fiasco/src/kern/warn.cpp b/kernel/fiasco/src/kern/warn.cpp new file mode 100644 index 00000000..d81f0a1b --- /dev/null +++ b/kernel/fiasco/src/kern/warn.cpp @@ -0,0 +1,21 @@ +INTERFACE: + +#include + +#include "config.h" + +enum Warn_level +{ + Error = 0, + Warning = 1, + Info = 2, +}; + +#define WARNX(level,fmt...) \ + do { \ + if (level <= (int)Config::Warn_level) \ + printf("\n\033[31mKERNEL\033[m: Warning: " fmt); \ + } while (0) + +#define WARN(fmt...) WARNX(Warning, fmt) + diff --git a/kernel/fiasco/src/kern/watchdog.cpp b/kernel/fiasco/src/kern/watchdog.cpp new file mode 100644 index 00000000..3eed0390 --- /dev/null +++ b/kernel/fiasco/src/kern/watchdog.cpp @@ -0,0 +1,53 @@ +INTERFACE [!watchdog]: + +#include "types.h" + +class Watchdog +{ +}; + + +IMPLEMENTATION [!watchdog]: + +#include "initcalls.h" +#include + +PUBLIC static inline +void +Watchdog::touch() +{} + +// user enables Watchdog +PUBLIC static inline +void +Watchdog::user_enable() +{} + +// user disables Watchdog +PUBLIC static inline +void +Watchdog::user_disable() +{} + +// user takes over control of Watchdog +PUBLIC static inline +void +Watchdog::user_takeover_control() +{} + +// user gives back control of Watchdog +PUBLIC static inline +void +Watchdog::user_giveback_control() +{} + +PUBLIC static inline +void +Watchdog::disable() +{} + +PUBLIC static inline +void +Watchdog::enable() +{} + diff --git a/kernel/fiasco/src/kernel.amd64.ld b/kernel/fiasco/src/kernel.amd64.ld new file mode 100644 index 00000000..e10b898f --- /dev/null +++ b/kernel/fiasco/src/kernel.amd64.ld @@ -0,0 +1,229 @@ +/* -*- c -*- */ + +#include "globalconfig.h" +#include "linking.h" + +_boot_sys_start = 0x300000; +_kernel_image = FIASCO_IMAGE_VIRT_START; /* kernel link address */ +_load = FIASCO_IMAGE_PHYS_START & 0x1fffff; +/* +_load = 0x1000; /* skip page 0 to preserve BIOS data and + * page 1 to reserve space for the KIP */ + +/*_fiasco_image_offset = 0xf0000000;*/ +_fiasco_image_offset = FIASCO_IMAGE_PHYS_OFFSET; + +OUTPUT_FORMAT("elf64-x86-64") +OUTPUT_ARCH(i386:x86-64) +ENTRY(bootstrap__boot_start) + +PHDRS { + tramp PT_LOAD; + btext PT_LOAD; + bdata PT_LOAD; + kip PT_LOAD; + koptions PT_LOAD; + ktext PT_LOAD; + kdata PT_LOAD; + kitext PT_LOAD; + kidata PT_LOAD; +} + +SECTIONS { + . = FIASCO_MP_TRAMP_PAGE; + .mp_tramp : { + KEEP(*(.mp_tramp)) + . = ALIGN(0x1000); + } : tramp + + . = _boot_sys_start; + .text_boot : ALIGN(0x1000) { + *(.bootstrap.init) + *(.bootstrap.text .bootstrap.text.* .bootstrap.gnu.linkonce.t.*) + *(.bootstrap.fini) + + *(.bootstrap.rodata .bootstrap.rodata.* .bootstrap.gnu.linkonce.r.*) + *(.bootstrap.data .bootstrap.data.* .bootstrap.gnu.linkonce.d.*) + *(.bootstrap.anno) + + } : btext + + . = ALIGN(0x10); + .bss_boot : { + *(.bootstrap.bss .bootstrap.gnu.linkonce.b.*) + . = ALIGN(0x1000); + PROVIDE(_boot_sys_end = .); + } : bdata + + . = _kernel_image + _load; + + .kip : AT(ADDR(.kip) - _fiasco_image_offset) { + _kernel_image_start = .; + *(.kernel_info_page) + _initkip_start = .; + KEEP(*(.initkip.version)) + KEEP(*(.initkip.features)) + KEEP(*(.initkip.features.fini)) + _initkip_end = .; + . = ALIGN(4K); + } : kip = 0 + + .koptions : AT (ADDR(.koptions) - _fiasco_image_offset) { + *(.koptions) + } : koptions = 0 + +#ifdef CONFIG_ALLOW_RO_TEXT + . = ALIGN(4K); +#endif + .text : AT (ADDR(.text) - _fiasco_image_offset) { + PROVIDE ( _kernel_text_start = . ); + crt0.o(.text) + *(.init) + *(.text SORT(.text.*) .gnu.linkonce.t.*) + *(.fini) + + PROVIDE (_ecode = .); + + *(.rodata .rodata.* .gnu.linkonce.r.*) + + . = ALIGN(8); + PROVIDE (_log_table = .); + /* + * The section must start with ".debug" because else the linker + * complains about references to discarded sections + */ + KEEP(*(SORT(.debug.jdb.log_table))) + PROVIDE (_log_table_end = .); + + . = ALIGN(0x40); + + PROVIDE (_etext = .); + } : ktext = 0x90909090 + +#ifdef CONFIG_ALLOW_RO_TEXT + . = ALIGN(4K); +#else + . = ALIGN(0x10); +#endif + .data : AT (ADDR(.data) - _fiasco_image_offset) { + PROVIDE (_kernel_data_start = .); + *(.data .data.* .gnu.linkonce.d.*) + *(.anno) + + /* Constructor and destructor lists, ordered by priority. The lists + are traversed from end to start, therefore the *_END__ symbols + precede the *_LIST__ symbols. */ + + __PER_CPU_INIT_ARRAY_START__ = .; + KEEP (*(.init_array.65534)) + KEEP (*(.init_array.65533)) + KEEP (*(.init_array.65532)) + KEEP (*(.init_array.65531)) + KEEP (*(.init_array.65530)) + KEEP (*(.init_array.65529)) + KEEP (*(.init_array.65528)) + KEEP (*(.init_array.65527)) + KEEP (*(.init_array.65526)) + KEEP (*(.init_array.65525)) + __PER_CPU_INIT_ARRAY_END__ = .; + + __PER_CPU_LATE_INIT_ARRAY_START__ = .; + KEEP (*(.init_array.65524)) + KEEP (*(.init_array.65523)) + KEEP (*(.init_array.65522)) + KEEP (*(.init_array.65521)) + KEEP (*(.init_array.65520)) + KEEP (*(.init_array.65519)) + KEEP (*(.init_array.65518)) + KEEP (*(.init_array.65517)) + KEEP (*(.init_array.65516)) + KEEP (*(.init_array.65515)) + __PER_CPU_LATE_INIT_ARRAY_END__ = .; + + __INIT_ARRAY_START__ = .; + KEEP (*(SORT (.init_array.*))) + KEEP (*(.init_array)) + __INIT_ARRAY_END__ = .; + + __PER_CPU_CTORS_END__ = .; + KEEP (*(.ctors.00010)) + KEEP (*(.ctors.00009)) + KEEP (*(.ctors.00008)) + KEEP (*(.ctors.00007)) + KEEP (*(.ctors.00006)) + KEEP (*(.ctors.00005)) + KEEP (*(.ctors.00004)) + KEEP (*(.ctors.00003)) + KEEP (*(.ctors.00002)) + KEEP (*(.ctors.00001)) + __PER_CPU_CTORS_LIST__ = .; + + __PER_CPU_LATE_CTORS_END__ = .; + KEEP (*(.ctors.00020)) + KEEP (*(.ctors.00019)) + KEEP (*(.ctors.00018)) + KEEP (*(.ctors.00017)) + KEEP (*(.ctors.00016)) + KEEP (*(.ctors.00015)) + KEEP (*(.ctors.00014)) + KEEP (*(.ctors.00013)) + KEEP (*(.ctors.00012)) + KEEP (*(.ctors.00011)) + __PER_CPU_LATE_CTORS_LIST__ = .; + + __CTOR_END__ = .; + CONSTRUCTORS + KEEP (*(.ctors)) + KEEP (*(SORT (.ctors.*))) + __CTOR_LIST__ = .; + + __DTOR_END__ = .; + KEEP (*(SORT (.dtors.*))) + KEEP (*(.dtors)) + __DTOR_LIST__ = .; + + PROVIDE (_edata = .); + } : kdata + + . = ALIGN(32); + .per_cpu_data : AT (ADDR(.per_cpu_data) - _fiasco_image_offset) { + PROVIDE (_per_cpu_data_start = .); + *(.per_cpu.data) + . = ALIGN(8); + PROVIDE (_per_cpu_data_end = .); + } : kdata + + . = ALIGN(0x10); + .bss : AT (ADDR(.bss) - _fiasco_image_offset) { + PROVIDE (_bss_start = .); + . = ALIGN(8); + _per_cpu_ctor_data_start = .; + KEEP (*(.bss.per_cpu_ctor_data)) + _per_cpu_ctor_data_end = .; + + *(.bss .bss.* .gnu.linkonce.b.* COMMON) + PROVIDE (_bss_end = .); + } : kdata + + PROVIDE (_end = .); + + . = ALIGN(4096); + PROVIDE (_initcall_start = .); + .initcall.text : AT (ADDR(.initcall.text) - _fiasco_image_offset) { + *(.initcall.text*) + *(.text.*) + } : kitext = 0x90909090 + + .initcall.data : AT (ADDR(.initcall.data) - _fiasco_image_offset) { + *(.initcall.data*) + . = ALIGN(4096); + PROVIDE (_initcall_end = .); + } : kidata + + /DISCARD/ : { + *(.note) + *(.note.ABI-tag) + *(.comment) + *(.eh_frame) + } +} diff --git a/kernel/fiasco/src/kernel.arm.ld b/kernel/fiasco/src/kernel.arm.ld new file mode 100644 index 00000000..5c8d029e --- /dev/null +++ b/kernel/fiasco/src/kernel.arm.ld @@ -0,0 +1,251 @@ +/* -*- c -*- */ + +/* this file defines the construction of the kernel's virtual address + space */ + +_tcbs_1 = 0xd0000000; /* assumption: 256MB-aligned */ +/*_unused1_1 = _mappings_end_1; /* assumption: 4MB-aligned */ +_unused2_1 = 0xea400000; /* assumption: 4MB-aligned */ +_unused3_1 = 0xea800000; /* assumption: 4MB-aligned */ +_service = 0xeac00000; /* assumption: 4MB-aligned */ +/* 0xeb000000 - 0xef800000 unused */ +_kstatic1_1 = 0xef800000; /* assumption: 4MB-aligned */ +_iobitmap_1 = 0xefc00000; /* assumption: 4MB-aligned */ +_unused4_io_1 = 0xefc80000; /* assumption: 2nd level field in + page table for IO bitmap */ +_physmem_1 = 0x0000000; /* assumption: 256MB-aligned */ +_kernel_phys_start = _physmem_1; +_kernel_phys_end = 0xffffffff; + + +virt_address = 0xf0000000; +phys_offset = virt_address - kernel_load_addr; + + +OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", + "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) + +SECTIONS { + + + /DISCARD/ : { /* Exit code and data */ + *(.exitcall.exit) + } + + . = kernel_load_addr + 0x1000; + + .text : { + bootstrap*(.init) + bootstrap*(.text .text.* .gnu.linkonce.t.*) + bootstrap*(.glue_7t) *(.glue_7) + bootstrap*(.got .got.*) + bootstrap*(.fini) + + bootstrap*(.rodata .rodata.* .gnu.linkonce.r.* .rodata1) + + . = ALIGN(0x40); + + bootstrap*(.data .data.* .gnu.linkonce.d.*) + bootstrap*(.anno) + + bootstrap*(.data) + bootstrap*(.gnu.linkonce.d*) + } + + PROVIDE(bootstrap_bss_start = .); + .bss_bootstrap : { + bootstrap*(.bss .bss.* COMMON .gnu.linkonce.b.*) + } + PROVIDE(bootstrap_bss_end = .); + + . = ALIGN(4K); + end_of_loader = .; + + . = end_of_loader - kernel_load_addr + virt_address; + + .kip : AT (end_of_loader) { + _kernel_image_start = .; + *(.kernel_info_page) + _initkip_start = .; + KEEP(*(.initkip.version)) + KEEP(*(.initkip.features)) + KEEP(*(.initkip.features.fini)) + _initkip_end = .; + . = ALIGN(4K); + } + + .koptions : AT (ADDR(.koptions) - phys_offset) { + *(.koptions) + } + + .mp_tramp : AT (ADDR(.mp_tramp) - phys_offset) { + KEEP(*(.mp_tramp)) + } + + .text_kernel : AT (ADDR(.text_kernel) - phys_offset) { + crt0.o(.text) + *(.init) + *(.text .text.* .gnu.linkonce.t.*) + *(.glue_7t) *(.glue_7) + *(.got .got.*) + *(.fini) + + *(.text.jdb) + + PROVIDE (_ecode = .); + + *(.rodata .rodata.* .gnu.linkonce.r.* .rodata1) + + . = ALIGN(4); + PROVIDE (_log_table = .); + /* + * The section must start with ".debug" because else the linker + * complains about references to discarded sections + */ + KEEP(*(SORT(.debug.jdb.log_table))) + PROVIDE (_log_table_end = .); + + . = ALIGN(0x40); + + PROVIDE (_etext = .); + + *(.data .data.* .gnu.linkonce.d.*) + *(.anno) + + *(.data) + *(.gnu.linkonce.d*) + *(.anno) + *(.data.jdb) + + *(.init.data) + +/* Constructor and destructor lists, ordered by priority. The lists + are traversed from end to start, therefore the *_END__ symbols + precede the *_LIST__ symbols. */ + __PER_CPU_INIT_ARRAY_START__ = .; + KEEP (*(.init_array.65534)) + KEEP (*(.init_array.65533)) + KEEP (*(.init_array.65532)) + KEEP (*(.init_array.65531)) + KEEP (*(.init_array.65530)) + KEEP (*(.init_array.65529)) + KEEP (*(.init_array.65528)) + KEEP (*(.init_array.65527)) + KEEP (*(.init_array.65526)) + KEEP (*(.init_array.65525)) + __PER_CPU_INIT_ARRAY_END__ = .; + + __PER_CPU_LATE_INIT_ARRAY_START__ = .; + KEEP (*(.init_array.65524)) + KEEP (*(.init_array.65523)) + KEEP (*(.init_array.65522)) + KEEP (*(.init_array.65521)) + KEEP (*(.init_array.65520)) + KEEP (*(.init_array.65519)) + KEEP (*(.init_array.65518)) + KEEP (*(.init_array.65517)) + KEEP (*(.init_array.65516)) + KEEP (*(.init_array.65515)) + __PER_CPU_LATE_INIT_ARRAY_END__ = .; + + __INIT_ARRAY_START__ = .; + KEEP (*(SORT (.init_array.*))) + KEEP (*(.init_array)) + __INIT_ARRAY_END__ = .; + + __PER_CPU_CTORS_END__ = .; + KEEP (*(.ctors.00010)) + KEEP (*(.ctors.00009)) + KEEP (*(.ctors.00008)) + KEEP (*(.ctors.00007)) + KEEP (*(.ctors.00006)) + KEEP (*(.ctors.00005)) + KEEP (*(.ctors.00004)) + KEEP (*(.ctors.00003)) + KEEP (*(.ctors.00002)) + KEEP (*(.ctors.00001)) + __PER_CPU_CTORS_LIST__ = .; + + __PER_CPU_LATE_CTORS_END__ = .; + KEEP (*(.ctors.00020)) + KEEP (*(.ctors.00019)) + KEEP (*(.ctors.00018)) + KEEP (*(.ctors.00017)) + KEEP (*(.ctors.00016)) + KEEP (*(.ctors.00015)) + KEEP (*(.ctors.00014)) + KEEP (*(.ctors.00013)) + KEEP (*(.ctors.00012)) + KEEP (*(.ctors.00011)) + __PER_CPU_LATE_CTORS_LIST__ = .; + + __CTOR_END__ = .; + CONSTRUCTORS + KEEP (*(.ctors)) + KEEP (*(SORT (.ctors.*))) + __CTOR_LIST__ = .; + + __DTOR_END__ = .; + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + __DTOR_LIST__ = .; + + PROVIDE(_edata = .); + + } + + . = ALIGN(8); + .per_cpu_data : AT (ADDR(.per_cpu_data) - phys_offset) { + PROVIDE (_per_cpu_data_start = .); + *(.per_cpu.data) + . = ALIGN(8); + PROVIDE (_per_cpu_data_end = .); + } + + /* ARM AEABI */ + . = ALIGN(8); + .ARM.exidx : { *(.ARM.exidx.*) } + .ARM.extab : { *(.ARM.extab.*) } + + + + . = ALIGN(4K); + .bss : AT (ADDR(.bss) - phys_offset) { + PROVIDE(__bss_start = .); + . = ALIGN(4); + _per_cpu_ctor_data_start = .; + KEEP (*(.bss.per_cpu_ctor_data)) + _per_cpu_ctor_data_end = .; + *(.bss .bss.* COMMON .gnu.linkonce.b.*) + *(.bss.jdb) + PROVIDE(__bss_end = .); + . = ALIGN(4K); + } + __end_of_the_kernel = .; + + ivt_start = ADDR(.bss) + SIZEOF(.bss) - phys_offset; + .excp 0xffff0000 : AT (ivt_start) { + *(.vect .excp.text) + *(.vect.extra) + } + + . = __end_of_the_kernel + SIZEOF(.excp); + + PROVIDE( _end = . ); + + . = ALIGN(4K); + .initcall : AT(ADDR(.initcall) - phys_offset) { + _initcall_start = .; + *(.initcall.*) + . = ALIGN(4K); + _initcall_end = .; + } + + /DISCARD/ :{ + *(.stab .stabstr .stab.excl .stab.exclstr) + *(.stab.index .stab.indexstr .comment) + } + +} diff --git a/kernel/fiasco/src/kernel.ia32.ld b/kernel/fiasco/src/kernel.ia32.ld new file mode 100644 index 00000000..c0a77bf9 --- /dev/null +++ b/kernel/fiasco/src/kernel.ia32.ld @@ -0,0 +1,219 @@ +/* -*- c -*- */ + +#include "globalconfig.h" +#include "linking.h" + +_boot_sys_start = 0x300000; +_kernel_image = FIASCO_IMAGE_VIRT_START; /* kernel link address */ +_load = FIASCO_IMAGE_PHYS_START & 0x3fffff; +/* +_load = 0x1000; /* skip page 0 to preserve BIOS data and + * page 1 to reserve space for the KIP */ + +/*_fiasco_image_offset = 0xf0000000;*/ +_fiasco_image_offset = FIASCO_IMAGE_PHYS_OFFSET; + +ENTRY(bootstrap__boot_start) + +PHDRS { + tramp PT_LOAD; + btext PT_LOAD; + bdata PT_LOAD; + kip PT_LOAD; + koptions PT_LOAD; + ktext PT_LOAD; + kdata PT_LOAD; + kitext PT_LOAD; + kidata PT_LOAD; +} + +SECTIONS { + . = FIASCO_MP_TRAMP_PAGE; + .mp_tramp : { + KEEP(*(.mp_tramp)) + . = ALIGN(0x1000); + } : tramp + + . = _boot_sys_start; + .text_boot : ALIGN(0x1000) { + *(.bootstrap.text .bootstrap.text.* .bootstrap.gnu.linkonce.t.*) + } : btext + + . = ALIGN(0x10); + .bss_boot : { + *(.bootstrap.bss) + . = ALIGN(0x1000); + PROVIDE(_boot_sys_end = .); + } : bdata + + . = _kernel_image + _load; + + .kip : AT(ADDR(.kip) - _fiasco_image_offset) { + _kernel_image_start = .; + *(.kernel_info_page) + _initkip_start = .; + KEEP(*(.initkip.version)) + KEEP(*(.initkip.features)) + KEEP(*(.initkip.features.fini)) + _initkip_end = .; + . = ALIGN(4K); + } : kip = 0 + + .koptions : AT (ADDR(.koptions) - _fiasco_image_offset) { + *(.koptions) + } : koptions = 0 + +#ifdef CONFIG_ALLOW_RO_TEXT + . = ALIGN(4K); +#endif + .text : AT (ADDR(.text) - _fiasco_image_offset) { + PROVIDE ( _kernel_text_start = . ); + crt0.o(.text) + *(.init) + *(.text SORT(.text.*) .gnu.linkonce.t.*) + *(.fini) + + PROVIDE (_ecode = .); + + *(.rodata .rodata.* .gnu.linkonce.r.*) + + . = ALIGN(4); + PROVIDE (_log_table = .); + /* + * The section must start with ".debug" because else the linker + * complains about references to discarded sections + */ + KEEP(*(SORT(.debug.jdb.log_table))) + PROVIDE (_log_table_end = .); + + . = ALIGN(0x40); + + PROVIDE (_etext = .); + } : ktext = 0x90909090 + +#ifdef CONFIG_ALLOW_RO_TEXT + . = ALIGN(4K); +#else + . = ALIGN(0x10); +#endif + .data : AT (ADDR(.data) - _fiasco_image_offset) { + PROVIDE (_kernel_data_start = .); + *(.data .data.* .gnu.linkonce.d.*) + *(.anno) + + /* Constructor and destructor lists, ordered by priority. The lists + are traversed from end to start, therefore the *_END__ symbols + precede the *_LIST__ symbols. */ + + __PER_CPU_INIT_ARRAY_START__ = .; + KEEP (*(.init_array.65534)) + KEEP (*(.init_array.65533)) + KEEP (*(.init_array.65532)) + KEEP (*(.init_array.65531)) + KEEP (*(.init_array.65530)) + KEEP (*(.init_array.65529)) + KEEP (*(.init_array.65528)) + KEEP (*(.init_array.65527)) + KEEP (*(.init_array.65526)) + KEEP (*(.init_array.65525)) + __PER_CPU_INIT_ARRAY_END__ = .; + + __PER_CPU_LATE_INIT_ARRAY_START__ = .; + KEEP (*(.init_array.65524)) + KEEP (*(.init_array.65523)) + KEEP (*(.init_array.65522)) + KEEP (*(.init_array.65521)) + KEEP (*(.init_array.65520)) + KEEP (*(.init_array.65519)) + KEEP (*(.init_array.65518)) + KEEP (*(.init_array.65517)) + KEEP (*(.init_array.65516)) + KEEP (*(.init_array.65515)) + __PER_CPU_LATE_INIT_ARRAY_END__ = .; + + __INIT_ARRAY_START__ = .; + KEEP (*(SORT (.init_array.*))) + KEEP (*(.init_array)) + __INIT_ARRAY_END__ = .; + + __PER_CPU_CTORS_END__ = .; + KEEP (*(.ctors.00010)) + KEEP (*(.ctors.00009)) + KEEP (*(.ctors.00008)) + KEEP (*(.ctors.00007)) + KEEP (*(.ctors.00006)) + KEEP (*(.ctors.00005)) + KEEP (*(.ctors.00004)) + KEEP (*(.ctors.00003)) + KEEP (*(.ctors.00002)) + KEEP (*(.ctors.00001)) + __PER_CPU_CTORS_LIST__ = .; + + __PER_CPU_LATE_CTORS_END__ = .; + KEEP (*(.ctors.00020)) + KEEP (*(.ctors.00019)) + KEEP (*(.ctors.00018)) + KEEP (*(.ctors.00017)) + KEEP (*(.ctors.00016)) + KEEP (*(.ctors.00015)) + KEEP (*(.ctors.00014)) + KEEP (*(.ctors.00013)) + KEEP (*(.ctors.00012)) + KEEP (*(.ctors.00011)) + __PER_CPU_LATE_CTORS_LIST__ = .; + + __CTOR_END__ = .; + CONSTRUCTORS + KEEP (*(.ctors)) + KEEP (*(SORT (.ctors.*))) + __CTOR_LIST__ = .; + + __DTOR_END__ = .; + KEEP (*(SORT (.dtors.*))) + KEEP (*(.dtors)) + __DTOR_LIST__ = .; + + PROVIDE (_edata = .); + } : kdata + + . = ALIGN(8); + .per_cpu_data : AT (ADDR(.per_cpu_data) - _fiasco_image_offset) { + PROVIDE (_per_cpu_data_start = .); + *(.per_cpu.data) + . = ALIGN(8); + PROVIDE (_per_cpu_data_end = .); + } : kdata + + . = ALIGN(0x10); + .bss : AT (ADDR(.bss) - _fiasco_image_offset) { + PROVIDE (_bss_start = .); + . = ALIGN(4); + _per_cpu_ctor_data_start = .; + KEEP (*(.bss.per_cpu_ctor_data)) + _per_cpu_ctor_data_end = .; + + *(.bss .bss.* .gnu.linkonce.b.* COMMON) + PROVIDE (_bss_end = .); + } : kdata + + PROVIDE (_end = .); + + . = ALIGN(4096); + PROVIDE (_initcall_start = .); + .initcall.text : AT (ADDR(.initcall.text) - _fiasco_image_offset) { + *(.initcall.text*) + } : kitext = 0x90909090 + + .initcall.data : AT (ADDR(.initcall.data) - _fiasco_image_offset) { + *(.initcall.data*) + . = ALIGN(4096); + PROVIDE (_initcall_end = .); + } : kidata + + /DISCARD/ : { + *(.note) + *(.note.ABI-tag) + *(.comment) + *(.eh_frame) + } +} diff --git a/kernel/fiasco/src/kernel.ppc32.ld b/kernel/fiasco/src/kernel.ppc32.ld new file mode 100644 index 00000000..f4aaa1d0 --- /dev/null +++ b/kernel/fiasco/src/kernel.ppc32.ld @@ -0,0 +1,199 @@ +/* -*- c -*- */ + +/* TODO cbass: define in ppc32 Makerules.KERNEL */ +/*kernel_load_addr = 0xfd000000;*/ /* kernel link address */ + +ENTRY(_start) + +PHDRS { + etext PT_LOAD; + etextcommon PT_LOAD; + phys PT_LOAD; + kip PT_LOAD; + koptions PT_LOAD; + ktext PT_LOAD; + kdata PT_LOAD; + kitext PT_LOAD; + kidata PT_LOAD; +} + +SECTIONS { + /* 0x0 */ + .except : AT (0x0) { + *(.except) + } : etext = 0x0 + . = ALIGN(4K) + 8K; + + /* 0x3000 */ + PROVIDE (_kernel_image_start = .); + .physmem : AT(ADDR(.physmem)) { + } : phys = 0x0 + + .kip : AT(ADDR(.kip)) { + *(.kernel_info_page) + _initkip_start = .; + KEEP(*(.initkip.version)) + KEEP(*(.initkip.features)) + KEEP(*(.initkip.features.fini)) + _initkip_end = .; + . = ALIGN(4K); + } : kip = 0 + + .koptions : AT (ADDR(.koptions)) { + *(.koptions) + } : koptions = 0 + + .mp_tramp : AT (ADDR(.mp_tramp)) { + KEEP(*(.mp_tramp)) + } + + .exceptcommon : AT(ADDR(.exceptcommon)) { + *(.exceptcommon) + } : etextcommon = 0x0 + + .text : AT (ADDR(.text)) { + crt0.o(.text) + *(.init) + *(.text SORT(.text.*) .gnu.linkonce.t.*) + *(.fini) + + PROVIDE (_ecode = .); + + *(.rodata .rodata.* .gnu.linkonce.r.*) + + . = ALIGN(4); + PROVIDE (_log_table = .); + /* + * The section must start with ".debug" because else the linker + * complains about references to discarded sections + */ + KEEP(*(SORT(.debug.jdb.log_table))) + PROVIDE (_log_table_end = .); + + . = ALIGN(0x40); + + PROVIDE (_etext = .); + } : ktext = 0x0000000 + + . = ALIGN(0x10); + .data : AT (ADDR(.data)) { + *(.data .data.* .gnu.linkonce.d.*) + *(.anno) + + /* Constructor and destructor lists, ordered by priority. The lists + are traversed from end to start, therefore the *_END__ symbols + precede the *_LIST__ symbols. */ + . = ALIGN(8); + __PER_CPU_INIT_ARRAY_START__ = .; + KEEP (*(.init_array.65534)) + KEEP (*(.init_array.65533)) + KEEP (*(.init_array.65532)) + KEEP (*(.init_array.65531)) + KEEP (*(.init_array.65530)) + KEEP (*(.init_array.65529)) + KEEP (*(.init_array.65528)) + KEEP (*(.init_array.65527)) + KEEP (*(.init_array.65526)) + KEEP (*(.init_array.65525)) + __PER_CPU_INIT_ARRAY_END__ = .; + + __PER_CPU_LATE_INIT_ARRAY_START__ = .; + KEEP (*(.init_array.65524)) + KEEP (*(.init_array.65523)) + KEEP (*(.init_array.65522)) + KEEP (*(.init_array.65521)) + KEEP (*(.init_array.65520)) + KEEP (*(.init_array.65519)) + KEEP (*(.init_array.65518)) + KEEP (*(.init_array.65517)) + KEEP (*(.init_array.65516)) + KEEP (*(.init_array.65515)) + __PER_CPU_LATE_INIT_ARRAY_END__ = .; + + __INIT_ARRAY_START__ = .; + KEEP (*(SORT (.init_array.*))) + KEEP (*(.init_array)) + __INIT_ARRAY_END__ = .; + + __PER_CPU_CTORS_END__ = .; + KEEP (*(.ctors.00010)) + KEEP (*(.ctors.00009)) + KEEP (*(.ctors.00008)) + KEEP (*(.ctors.00007)) + KEEP (*(.ctors.00006)) + KEEP (*(.ctors.00005)) + KEEP (*(.ctors.00004)) + KEEP (*(.ctors.00003)) + KEEP (*(.ctors.00002)) + KEEP (*(.ctors.00001)) + __PER_CPU_CTORS_LIST__ = .; + + __PER_CPU_LATE_CTORS_END__ = .; + KEEP (*(.ctors.00020)) + KEEP (*(.ctors.00019)) + KEEP (*(.ctors.00018)) + KEEP (*(.ctors.00017)) + KEEP (*(.ctors.00016)) + KEEP (*(.ctors.00015)) + KEEP (*(.ctors.00014)) + KEEP (*(.ctors.00013)) + KEEP (*(.ctors.00012)) + KEEP (*(.ctors.00011)) + __PER_CPU_LATE_CTORS_LIST__ = .; + + __CTOR_END__ = .; + CONSTRUCTORS + KEEP (*(.ctors)) + KEEP (*(SORT (.ctors.*))) + __CTOR_LIST__ = .; + + __DTOR_END__ = .; + KEEP (*(SORT (.dtors.*))) + KEEP (*(.dtors)) + __DTOR_LIST__ = .; + + PROVIDE (_edata = .); + } : kdata + + . = ALIGN(8); + .per_cpu_data : AT (ADDR(.per_cpu_data)) { + PROVIDE (_per_cpu_data_start = .); + *(.per_cpu.data) + . = ALIGN(8); + PROVIDE (_per_cpu_data_end = .); + } : kdata + + . = ALIGN(0x10); + .bss : AT (ADDR(.bss)) { + PROVIDE (_bss_start = .); + . = ALIGN(4); + _per_cpu_ctor_data_start = .; + KEEP (*(.bss.per_cpu_ctor_data)) + _per_cpu_ctor_data_end = .; + + *(.bss .bss.* .gnu.linkonce.b.* COMMON) + PROVIDE (_bss_end = .); + } : kdata + + . = ALIGN(4K); + PROVIDE (_end = .); + + .initcall.text : AT (ADDR(.initcall.text)) { + PROVIDE (_initcall_start = .); + *(.initcall.text*) + } : kitext = 0x000000000 + + .initcall.data : AT (ADDR(.initcall.data)) { + *(.initcall.data*) + . = ALIGN(4K); + PROVIDE (_initcall_end = .); + } : kidata + + /DISCARD/ : { + *(.note) + *(.note.ABI-tag) + *(.comment) + *(.eh_frame) + *(.dummy) + } +} diff --git a/kernel/fiasco/src/kernel.sparc.ld b/kernel/fiasco/src/kernel.sparc.ld new file mode 100644 index 00000000..e918e19b --- /dev/null +++ b/kernel/fiasco/src/kernel.sparc.ld @@ -0,0 +1,197 @@ +/* -*- c -*- */ + +ENTRY(_start) + +PHDRS { + etext PT_LOAD; + etextcommon PT_LOAD; + phys PT_LOAD; + kip PT_LOAD; + koptions PT_LOAD; + ktext PT_LOAD; + kdata PT_LOAD; + kitext PT_LOAD; + kidata PT_LOAD; +} + +SECTIONS { + . = kernel_load_addr + 0x1000; + /* 0x0 */ + .except : AT (0x0) { + *(.except) + } : etext = 0x0 + . = ALIGN(4K) + 8K; + + /* 0x3000 */ + PROVIDE (_kernel_image_start = .); + .physmem : AT(ADDR(.physmem)) { + } : phys = 0x0 + + .kip : AT(ADDR(.kip)) { + *(.kernel_info_page) + _initkip_start = .; + KEEP(*(.initkip.version)) + KEEP(*(.initkip.features)) + KEEP(*(.initkip.features.fini)) + _initkip_end = .; + . = ALIGN(4K); + } : kip = 0 + + .koptions : AT (ADDR(.koptions)) { + *(.koptions) + } : koptions = 0 + + .mp_tramp : AT (ADDR(.mp_tramp)) { + KEEP(*(.mp_tramp)) + } + + .exceptcommon : AT(ADDR(.exceptcommon)) { + *(.exceptcommon) + } : etextcommon = 0x0 + + .text : AT (ADDR(.text)) { + crt0.o(.text) + *(.init) + *(.text SORT(.text.*) .gnu.linkonce.t.*) + *(.fini) + + PROVIDE (_ecode = .); + + *(.rodata .rodata.* .gnu.linkonce.r.*) + + . = ALIGN(4); + PROVIDE (_log_table = .); + /* + * The section must start with ".debug" because else the linker + * complains about references to discarded sections + */ + KEEP(*(SORT(.debug.jdb.log_table))) + PROVIDE (_log_table_end = .); + + . = ALIGN(0x40); + + PROVIDE (_etext = .); + } : ktext = 0x0000000 + + . = ALIGN(0x10); + .data : AT (ADDR(.data)) { + *(.data .data.* .gnu.linkonce.d.*) + *(.anno) + + /* Constructor and destructor lists, ordered by priority. The lists + are traversed from end to start, therefore the *_END__ symbols + precede the *_LIST__ symbols. */ + . = ALIGN(8); + __PER_CPU_INIT_ARRAY_START__ = .; + KEEP (*(.init_array.65534)) + KEEP (*(.init_array.65533)) + KEEP (*(.init_array.65532)) + KEEP (*(.init_array.65531)) + KEEP (*(.init_array.65530)) + KEEP (*(.init_array.65529)) + KEEP (*(.init_array.65528)) + KEEP (*(.init_array.65527)) + KEEP (*(.init_array.65526)) + KEEP (*(.init_array.65525)) + __PER_CPU_INIT_ARRAY_END__ = .; + + __PER_CPU_LATE_INIT_ARRAY_START__ = .; + KEEP (*(.init_array.65524)) + KEEP (*(.init_array.65523)) + KEEP (*(.init_array.65522)) + KEEP (*(.init_array.65521)) + KEEP (*(.init_array.65520)) + KEEP (*(.init_array.65519)) + KEEP (*(.init_array.65518)) + KEEP (*(.init_array.65517)) + KEEP (*(.init_array.65516)) + KEEP (*(.init_array.65515)) + __PER_CPU_LATE_INIT_ARRAY_END__ = .; + + __INIT_ARRAY_START__ = .; + KEEP (*(SORT (.init_array.*))) + KEEP (*(.init_array)) + __INIT_ARRAY_END__ = .; + + __PER_CPU_CTORS_END__ = .; + KEEP (*(.ctors.00010)) + KEEP (*(.ctors.00009)) + KEEP (*(.ctors.00008)) + KEEP (*(.ctors.00007)) + KEEP (*(.ctors.00006)) + KEEP (*(.ctors.00005)) + KEEP (*(.ctors.00004)) + KEEP (*(.ctors.00003)) + KEEP (*(.ctors.00002)) + KEEP (*(.ctors.00001)) + __PER_CPU_CTORS_LIST__ = .; + + __PER_CPU_LATE_CTORS_END__ = .; + KEEP (*(.ctors.00020)) + KEEP (*(.ctors.00019)) + KEEP (*(.ctors.00018)) + KEEP (*(.ctors.00017)) + KEEP (*(.ctors.00016)) + KEEP (*(.ctors.00015)) + KEEP (*(.ctors.00014)) + KEEP (*(.ctors.00013)) + KEEP (*(.ctors.00012)) + KEEP (*(.ctors.00011)) + __PER_CPU_LATE_CTORS_LIST__ = .; + + __CTOR_END__ = .; + CONSTRUCTORS + KEEP (*(.ctors)) + KEEP (*(SORT (.ctors.*))) + __CTOR_LIST__ = .; + + __DTOR_END__ = .; + KEEP (*(SORT (.dtors.*))) + KEEP (*(.dtors)) + __DTOR_LIST__ = .; + + PROVIDE (_edata = .); + } : kdata + + . = ALIGN(8); + .per_cpu_data : AT (ADDR(.per_cpu_data)) { + PROVIDE (_per_cpu_data_start = .); + *(.per_cpu.data) + . = ALIGN(8); + PROVIDE (_per_cpu_data_end = .); + } : kdata + + . = ALIGN(0x10); + .bss : AT (ADDR(.bss)) { + PROVIDE (_bss_start = .); + . = ALIGN(4); + _per_cpu_ctor_data_start = .; + KEEP (*(.bss.per_cpu_ctor_data)) + _per_cpu_ctor_data_end = .; + + *(.bss .bss.* .gnu.linkonce.b.* COMMON) + PROVIDE (_bss_end = .); + } : kdata + + . = ALIGN(4K); + PROVIDE (_end = .); + + .initcall.text : AT (ADDR(.initcall.text)) { + PROVIDE (_initcall_start = .); + *(.initcall.text*) + } : kitext = 0x000000000 + + .initcall.data : AT (ADDR(.initcall.data)) { + *(.initcall.data*) + . = ALIGN(4K); + PROVIDE (_initcall_end = .); + } : kidata + + /DISCARD/ : { + *(.note) + *(.note.ABI-tag) + *(.comment) + *(.eh_frame) + *(.dummy) + } +} diff --git a/kernel/fiasco/src/kernel.ux.ld b/kernel/fiasco/src/kernel.ux.ld new file mode 100644 index 00000000..489f8042 --- /dev/null +++ b/kernel/fiasco/src/kernel.ux.ld @@ -0,0 +1,227 @@ + +_load = 0x10000; /* kernel load address */ + +OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386") +OUTPUT_ARCH(i386) +ENTRY(_start) +SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); + +SECTIONS { + + . = _load + SIZEOF_HEADERS; + + .rel.plt : { + *(.rel.plt) + PROVIDE_HIDDEN (__rel_iplt_start = .); + *(.rel.iplt) + PROVIDE_HIDDEN (__rel_iplt_end = .); + } + + .init : { + _kernel_image_start = .; + KEEP (*(.init)) + } + + .text : { + *(.text .stub .text.* .gnu.linkonce.t.*) + } = 0x90 + + PROVIDE (_ecode = .); + + .fini : { + KEEP (*(.fini)) + } + + .rodata : { + *(.rodata .rodata.* .gnu.linkonce.r.*) + /* Discarding the build-id section will yield to an error from the + * linker so just put it here */ + *(.note.gnu.build-id) + } + + .preinit_array : { + PROVIDE (__preinit_array_start = .); + *(.preinit_array) + PROVIDE (__preinit_array_end = .); + } + + /* + .init_array : { + PROVIDE (__init_array_start = .); + KEEP (*(SORT (.init_array.*))) + KEEP (*(.init_array)) + PROVIDE (__init_array_end = .); + } + */ + + .fini_array : { + PROVIDE (__fini_array_start = .); + *(.fini_array) + *(.fini_array.*) + PROVIDE (__fini_array_end = .); + } + + PROVIDE (_etext = .); + + . = ALIGN(4K); + .kip : { + *(.kernel_info_page) + _initkip_start = .; + KEEP(*(.initkip.version)) + KEEP(*(.initkip.features)) + KEEP(*(.initkip.features.fini)) + _initkip_end = .; + . = ALIGN(4K); + } + + .data : { + PROVIDE (_kernel_data_start = .); + *(.data .data.* .gnu.linkonce.d.*) + + __PER_CPU_INIT_ARRAY_START__ = .; + KEEP (*(.init_array.65534)) + KEEP (*(.init_array.65533)) + KEEP (*(.init_array.65532)) + KEEP (*(.init_array.65531)) + KEEP (*(.init_array.65530)) + KEEP (*(.init_array.65529)) + KEEP (*(.init_array.65528)) + KEEP (*(.init_array.65527)) + KEEP (*(.init_array.65526)) + KEEP (*(.init_array.65525)) + __PER_CPU_INIT_ARRAY_END__ = .; + + __PER_CPU_LATE_INIT_ARRAY_START__ = .; + KEEP (*(.init_array.65524)) + KEEP (*(.init_array.65523)) + KEEP (*(.init_array.65522)) + KEEP (*(.init_array.65521)) + KEEP (*(.init_array.65520)) + KEEP (*(.init_array.65519)) + KEEP (*(.init_array.65518)) + KEEP (*(.init_array.65517)) + KEEP (*(.init_array.65516)) + KEEP (*(.init_array.65515)) + __PER_CPU_LATE_INIT_ARRAY_END__ = .; + + __INIT_ARRAY_START__ = .; + PROVIDE (__init_array_start = .); + KEEP (*(SORT (.init_array.*))) + KEEP (*(.init_array)) + PROVIDE (__init_array_end = .); + __INIT_ARRAY_END__ = .; + __CTOR_LIST__ = .; + __CTOR_END__ = .; + + SORT (CONSTRUCTORS) + + __PER_CPU_CTORS_END__ = .; + KEEP (*(.ctors.00010)) + KEEP (*(.ctors.00009)) + KEEP (*(.ctors.00008)) + KEEP (*(.ctors.00007)) + KEEP (*(.ctors.00006)) + KEEP (*(.ctors.00005)) + KEEP (*(.ctors.00004)) + KEEP (*(.ctors.00003)) + KEEP (*(.ctors.00002)) + KEEP (*(.ctors.00001)) + __PER_CPU_CTORS_LIST__ = .; + + __PER_CPU_LATE_CTORS_END__ = .; + KEEP (*(.ctors.00020)) + KEEP (*(.ctors.00019)) + KEEP (*(.ctors.00018)) + KEEP (*(.ctors.00017)) + KEEP (*(.ctors.00016)) + KEEP (*(.ctors.00015)) + KEEP (*(.ctors.00014)) + KEEP (*(.ctors.00013)) + KEEP (*(.ctors.00012)) + KEEP (*(.ctors.00011)) + __PER_CPU_LATE_CTORS_LIST__ = .; + + . = ALIGN(4); + PROVIDE (_log_table = .); + /* + * The section must start with ".debug" because else the linker + * complains about references to discarded sections + */ + KEEP(*(SORT(.debug.jdb.log_table))) + PROVIDE (_log_table_end = .); + } + + .tdata : { + *(.tdata .tdata.* .gnu.linkonce.td.*) + } + .tbss : { + *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) + } + + .eh_frame : { KEEP (*(.eh_frame)) } + .gcc_except_table : { *(.gcc_except_table) } + + .ctors : { + KEEP (*crtbegin.o(.ctors)) + KEEP (*(EXCLUDE_FILE (*crtend.o ) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + } + + .dtors : { + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o ) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + } + + .got : { + *(.got.plt) + *(.got) + } + + . = ALIGN(8); + .per_cpu_data : { + PROVIDE (_per_cpu_data_start = .); + *(.per_cpu.data) + . = ALIGN(8); + PROVIDE (_per_cpu_data_end = .); + } + + PROVIDE (_edata = .); + + . = ALIGN(4096); + .initcall : { + PROVIDE (_initcall_start = .); + *(.initcall.*) + . = ALIGN(4096); + PROVIDE (_initcall_end = .); + } + + . = ALIGN(4096); + .bss : { /* Linux 2.2 requires BSS to be last */ + *(.dynbss) + . = ALIGN(4); + _per_cpu_ctor_data_start = .; + KEEP (*(.bss.per_cpu_ctor_data)) + _per_cpu_ctor_data_end = .; + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + } + + PROVIDE (_end = .); + + /* make the kip_init code happy */ + PROVIDE (_boot_sys_start = .); + PROVIDE (_boot_sys_end = .); + + /* make the construction.cc code happy w/o dtros */ + PROVIDE (__DTOR_END__ = .); + PROVIDE (__DTOR_LIST__ = __DTOR_END__); + + /DISCARD/ : { + *(.note) + *(.note.ABI-tag) + *(.comment) + } +} diff --git a/kernel/fiasco/src/lib/cxxlib/paranoia.cpp b/kernel/fiasco/src/lib/cxxlib/paranoia.cpp new file mode 100644 index 00000000..d44d3ee0 --- /dev/null +++ b/kernel/fiasco/src/lib/cxxlib/paranoia.cpp @@ -0,0 +1,39 @@ +INTERFACE: + +#include + +IMPLEMENTATION: + +#include +#include +#include "panic.h" +#include "types.h" + +char __dso_handle __attribute__((weak)); + +extern "C" void __cxa_pure_virtual() +{ + panic("cxa pure virtual function called"); +} + +extern "C" void __pure_virtual() +{ + panic("pure virtual function called"); +} + +void operator delete(void *) +{ + // This must not happen: We never delete an object of the abstract + // class slab_cache_anon. If the compiler was clever, it wouldn't + // generate a call to this function (because all destructors of + // abstract base classes have been are marked abstract virtual), and + // we wouldn't need to define this. + panic("operator delete (aka __builtin_delete) called from " L4_PTR_FMT, + L4_PTR_ARG(__builtin_return_address(0))); +} + +extern "C" void __div0(void) +{ + panic("__div0"); +} + diff --git a/kernel/fiasco/src/lib/cxxlib/s_cruft.cpp b/kernel/fiasco/src/lib/cxxlib/s_cruft.cpp new file mode 100644 index 00000000..34927a1e --- /dev/null +++ b/kernel/fiasco/src/lib/cxxlib/s_cruft.cpp @@ -0,0 +1,20 @@ +INTERFACE: + +#include // for size_t + +IMPLEMENTATION: + +#include "panic.h" // for panic + +// do not allow calls to these OSKit routines. We have to provide +// these functions because libamm references them. + +extern "C" __attribute__((noreturn)) void *smalloc(size_t) +{ + panic("smalloc called"); +} + +extern "C" __attribute__((noreturn)) void sfree(void *, size_t) +{ + panic("sfree called"); +} diff --git a/kernel/fiasco/src/lib/disasm/COPYING b/kernel/fiasco/src/lib/disasm/COPYING new file mode 100644 index 00000000..60549be5 --- /dev/null +++ b/kernel/fiasco/src/lib/disasm/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/kernel/fiasco/src/lib/disasm/bfd/bfd.h b/kernel/fiasco/src/lib/disasm/bfd/bfd.h new file mode 100644 index 00000000..3191cc4f --- /dev/null +++ b/kernel/fiasco/src/lib/disasm/bfd/bfd.h @@ -0,0 +1,5405 @@ +/* DO NOT EDIT! -*- buffer-read-only: t -*- This file is automatically + generated from "bfd-in.h", "init.c", "opncls.c", "libbfd.c", + "bfdio.c", "bfdwin.c", "section.c", "archures.c", "reloc.c", + "syms.c", "bfd.c", "archive.c", "corefile.c", "targets.c", "format.c", + "linker.c" and "simple.c". + Run "make headers" in your build bfd/ to regenerate. */ + +/* Main header file for the bfd library -- portable access to object files. + + Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, + 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 + Free Software Foundation, Inc. + + Contributed by Cygnus Support. + + This file is part of BFD, the Binary File Descriptor library. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ + +#ifndef __BFD_H_SEEN__ +#define __BFD_H_SEEN__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "ansidecl.h" +#include "symcat.h" +#if defined (__STDC__) || defined (ALMOST_STDC) || defined (HAVE_STRINGIZE) +#ifndef SABER +/* This hack is to avoid a problem with some strict ANSI C preprocessors. + The problem is, "32_" is not a valid preprocessing token, and we don't + want extra underscores (e.g., "nlm_32_"). The XCONCAT2 macro will + cause the inner CONCAT2 macros to be evaluated first, producing + still-valid pp-tokens. Then the final concatenation can be done. */ +#undef CONCAT4 +#define CONCAT4(a,b,c,d) XCONCAT2(CONCAT2(a,b),CONCAT2(c,d)) +#endif +#endif + +/* This is a utility macro to handle the situation where the code + wants to place a constant string into the code, followed by a + comma and then the length of the string. Doing this by hand + is error prone, so using this macro is safer. */ +#define STRING_COMMA_LEN(STR) (STR), (sizeof (STR) - 1) +/* Unfortunately it is not possible to use the STRING_COMMA_LEN macro + to create the arguments to another macro, since the preprocessor + will mis-count the number of arguments to the outer macro (by not + evaluating STRING_COMMA_LEN and so missing the comma). This is a + problem for example when trying to use STRING_COMMA_LEN to build + the arguments to the strncmp() macro. Hence this alternative + definition of strncmp is provided here. + + Note - these macros do NOT work if STR2 is not a constant string. */ +#define CONST_STRNEQ(STR1,STR2) (strncmp ((STR1), (STR2), sizeof (STR2) - 1) == 0) + /* strcpy() can have a similar problem, but since we know we are + copying a constant string, we can use memcpy which will be faster + since there is no need to check for a NUL byte inside STR. We + can also save time if we do not need to copy the terminating NUL. */ +#define LITMEMCPY(DEST,STR2) memcpy ((DEST), (STR2), sizeof (STR2) - 1) +#define LITSTRCPY(DEST,STR2) memcpy ((DEST), (STR2), sizeof (STR2)) + + +/* The word size used by BFD on the host. This may be 64 with a 32 + bit target if the host is 64 bit, or if other 64 bit targets have + been selected with --enable-targets, or if --enable-64-bit-bfd. */ +#define BFD_ARCH_SIZE 32 + +/* The word size of the default bfd target. */ +#define BFD_DEFAULT_TARGET_SIZE 32 + +#define BFD_HOST_64BIT_LONG 0 +#define BFD_HOST_64BIT_LONG_LONG 0 +#define BFD_HOST_LONG_LONG 1 +#if 1 +#define BFD_HOST_64_BIT long long +#define BFD_HOST_U_64_BIT unsigned long long +typedef BFD_HOST_64_BIT bfd_int64_t; +typedef BFD_HOST_U_64_BIT bfd_uint64_t; +#endif + +#if BFD_ARCH_SIZE >= 64 +#define BFD64 +#endif + +#ifndef INLINE +#if __GNUC__ >= 2 +#define INLINE __inline__ +#else +#define INLINE +#endif +#endif + +/* Declaring a type wide enough to hold a host long and a host pointer. */ +#define BFD_HOSTPTR_T unsigned long +typedef BFD_HOSTPTR_T bfd_hostptr_t; + +/* Forward declaration. */ +typedef struct bfd bfd; + +/* Boolean type used in bfd. Too many systems define their own + versions of "boolean" for us to safely typedef a "boolean" of + our own. Using an enum for "bfd_boolean" has its own set of + problems, with strange looking casts required to avoid warnings + on some older compilers. Thus we just use an int. + + General rule: Functions which are bfd_boolean return TRUE on + success and FALSE on failure (unless they're a predicate). */ + +typedef int bfd_boolean; +#undef FALSE +#undef TRUE +#define FALSE 0 +#define TRUE 1 + +#ifdef BFD64 + +#ifndef BFD_HOST_64_BIT + #error No 64 bit integer type available +#endif /* ! defined (BFD_HOST_64_BIT) */ + +typedef BFD_HOST_U_64_BIT bfd_vma; +typedef BFD_HOST_64_BIT bfd_signed_vma; +typedef BFD_HOST_U_64_BIT bfd_size_type; +typedef BFD_HOST_U_64_BIT symvalue; + +#ifndef fprintf_vma +#if BFD_HOST_64BIT_LONG +#define sprintf_vma(s,x) sprintf (s, "%016lx", x) +#define fprintf_vma(f,x) fprintf (f, "%016lx", x) +#elif BFD_HOST_64BIT_LONG_LONG +#define sprintf_vma(s,x) sprintf (s, "%016llx", x) +#define fprintf_vma(f,x) fprintf (f, "%016llx", x) +#else +#define _bfd_int64_low(x) ((unsigned long) (((x) & 0xffffffff))) +#define _bfd_int64_high(x) ((unsigned long) (((x) >> 32) & 0xffffffff)) +#define fprintf_vma(s,x) \ + fprintf ((s), "%08lx%08lx", _bfd_int64_high (x), _bfd_int64_low (x)) +#define sprintf_vma(s,x) \ + sprintf ((s), "%08lx%08lx", _bfd_int64_high (x), _bfd_int64_low (x)) +#endif +#endif + +#else /* not BFD64 */ + +/* Represent a target address. Also used as a generic unsigned type + which is guaranteed to be big enough to hold any arithmetic types + we need to deal with. */ +typedef unsigned long bfd_vma; + +/* A generic signed type which is guaranteed to be big enough to hold any + arithmetic types we need to deal with. Can be assumed to be compatible + with bfd_vma in the same way that signed and unsigned ints are compatible + (as parameters, in assignment, etc). */ +typedef long bfd_signed_vma; + +typedef unsigned long symvalue; +typedef unsigned long bfd_size_type; + +/* Print a bfd_vma x on stream s. */ +#define fprintf_vma(s,x) fprintf (s, "%08lx", x) +#define sprintf_vma(s,x) sprintf (s, "%08lx", x) + +#endif /* not BFD64 */ + +#define HALF_BFD_SIZE_TYPE \ + (((bfd_size_type) 1) << (8 * sizeof (bfd_size_type) / 2)) + +#ifndef BFD_HOST_64_BIT +/* Fall back on a 32 bit type. The idea is to make these types always + available for function return types, but in the case that + BFD_HOST_64_BIT is undefined such a function should abort or + otherwise signal an error. */ +typedef bfd_signed_vma bfd_int64_t; +typedef bfd_vma bfd_uint64_t; +#endif + +/* An offset into a file. BFD always uses the largest possible offset + based on the build time availability of fseek, fseeko, or fseeko64. */ +typedef BFD_HOST_64_BIT file_ptr; +typedef unsigned BFD_HOST_64_BIT ufile_ptr; + +extern void bfd_sprintf_vma (bfd *, char *, bfd_vma); +extern void bfd_fprintf_vma (bfd *, void *, bfd_vma); + +#define printf_vma(x) fprintf_vma(stdout,x) +#define bfd_printf_vma(abfd,x) bfd_fprintf_vma (abfd,stdout,x) + +typedef unsigned int flagword; /* 32 bits of flags */ +typedef unsigned char bfd_byte; + +/* File formats. */ + +typedef enum bfd_format +{ + bfd_unknown = 0, /* File format is unknown. */ + bfd_object, /* Linker/assembler/compiler output. */ + bfd_archive, /* Object archive file. */ + bfd_core, /* Core dump. */ + bfd_type_end /* Marks the end; don't use it! */ +} +bfd_format; + +/* Values that may appear in the flags field of a BFD. These also + appear in the object_flags field of the bfd_target structure, where + they indicate the set of flags used by that backend (not all flags + are meaningful for all object file formats) (FIXME: at the moment, + the object_flags values have mostly just been copied from backend + to another, and are not necessarily correct). */ + +/* No flags. */ +#define BFD_NO_FLAGS 0x00 + +/* BFD contains relocation entries. */ +#define HAS_RELOC 0x01 + +/* BFD is directly executable. */ +#define EXEC_P 0x02 + +/* BFD has line number information (basically used for F_LNNO in a + COFF header). */ +#define HAS_LINENO 0x04 + +/* BFD has debugging information. */ +#define HAS_DEBUG 0x08 + +/* BFD has symbols. */ +#define HAS_SYMS 0x10 + +/* BFD has local symbols (basically used for F_LSYMS in a COFF + header). */ +#define HAS_LOCALS 0x20 + +/* BFD is a dynamic object. */ +#define DYNAMIC 0x40 + +/* Text section is write protected (if D_PAGED is not set, this is + like an a.out NMAGIC file) (the linker sets this by default, but + clears it for -r or -N). */ +#define WP_TEXT 0x80 + +/* BFD is dynamically paged (this is like an a.out ZMAGIC file) (the + linker sets this by default, but clears it for -r or -n or -N). */ +#define D_PAGED 0x100 + +/* BFD is relaxable (this means that bfd_relax_section may be able to + do something) (sometimes bfd_relax_section can do something even if + this is not set). */ +#define BFD_IS_RELAXABLE 0x200 + +/* This may be set before writing out a BFD to request using a + traditional format. For example, this is used to request that when + writing out an a.out object the symbols not be hashed to eliminate + duplicates. */ +#define BFD_TRADITIONAL_FORMAT 0x400 + +/* This flag indicates that the BFD contents are actually cached in + memory. If this is set, iostream points to a bfd_in_memory struct. */ +#define BFD_IN_MEMORY 0x800 + +/* The sections in this BFD specify a memory page. */ +#define HAS_LOAD_PAGE 0x1000 + +/* This BFD has been created by the linker and doesn't correspond + to any input file. */ +#define BFD_LINKER_CREATED 0x2000 + +/* Symbols and relocation. */ + +/* A count of carsyms (canonical archive symbols). */ +typedef unsigned long symindex; + +/* How to perform a relocation. */ +typedef const struct reloc_howto_struct reloc_howto_type; + +#define BFD_NO_MORE_SYMBOLS ((symindex) ~0) + +/* General purpose part of a symbol X; + target specific parts are in libcoff.h, libaout.h, etc. */ + +#define bfd_get_section(x) ((x)->section) +#define bfd_get_output_section(x) ((x)->section->output_section) +#define bfd_set_section(x,y) ((x)->section) = (y) +#define bfd_asymbol_base(x) ((x)->section->vma) +#define bfd_asymbol_value(x) (bfd_asymbol_base(x) + (x)->value) +#define bfd_asymbol_name(x) ((x)->name) +/*Perhaps future: #define bfd_asymbol_bfd(x) ((x)->section->owner)*/ +#define bfd_asymbol_bfd(x) ((x)->the_bfd) +#define bfd_asymbol_flavour(x) (bfd_asymbol_bfd(x)->xvec->flavour) + +/* A canonical archive symbol. */ +/* This is a type pun with struct ranlib on purpose! */ +typedef struct carsym +{ + char *name; + file_ptr file_offset; /* Look here to find the file. */ +} +carsym; /* To make these you call a carsymogen. */ + +/* Used in generating armaps (archive tables of contents). + Perhaps just a forward definition would do? */ +struct orl /* Output ranlib. */ +{ + char **name; /* Symbol name. */ + union + { + file_ptr pos; + bfd *abfd; + } u; /* bfd* or file position. */ + int namidx; /* Index into string table. */ +}; + +/* Linenumber stuff. */ +typedef struct lineno_cache_entry +{ + unsigned int line_number; /* Linenumber from start of function. */ + union + { + struct bfd_symbol *sym; /* Function name. */ + bfd_vma offset; /* Offset into section. */ + } u; +} +alent; + +/* Object and core file sections. */ + +#define align_power(addr, align) \ + (((addr) + ((bfd_vma) 1 << (align)) - 1) & ((bfd_vma) -1 << (align))) + +typedef struct bfd_section *sec_ptr; + +#define bfd_get_section_name(bfd, ptr) ((ptr)->name + 0) +#define bfd_get_section_vma(bfd, ptr) ((ptr)->vma + 0) +#define bfd_get_section_lma(bfd, ptr) ((ptr)->lma + 0) +#define bfd_get_section_alignment(bfd, ptr) ((ptr)->alignment_power + 0) +#define bfd_section_name(bfd, ptr) ((ptr)->name) +#define bfd_section_size(bfd, ptr) ((ptr)->size) +#define bfd_get_section_size(ptr) ((ptr)->size) +#define bfd_section_vma(bfd, ptr) ((ptr)->vma) +#define bfd_section_lma(bfd, ptr) ((ptr)->lma) +#define bfd_section_alignment(bfd, ptr) ((ptr)->alignment_power) +#define bfd_get_section_flags(bfd, ptr) ((ptr)->flags + 0) +#define bfd_get_section_userdata(bfd, ptr) ((ptr)->userdata) + +#define bfd_is_com_section(ptr) (((ptr)->flags & SEC_IS_COMMON) != 0) + +#define bfd_set_section_vma(bfd, ptr, val) (((ptr)->vma = (ptr)->lma = (val)), ((ptr)->user_set_vma = TRUE), TRUE) +#define bfd_set_section_alignment(bfd, ptr, val) (((ptr)->alignment_power = (val)),TRUE) +#define bfd_set_section_userdata(bfd, ptr, val) (((ptr)->userdata = (val)),TRUE) +/* Find the address one past the end of SEC. */ +#define bfd_get_section_limit(bfd, sec) \ + (((sec)->rawsize ? (sec)->rawsize : (sec)->size) \ + / bfd_octets_per_byte (bfd)) + +/* Return TRUE if section has been discarded. */ +#define elf_discarded_section(sec) \ + (!bfd_is_abs_section (sec) \ + && bfd_is_abs_section ((sec)->output_section) \ + && (sec)->sec_info_type != ELF_INFO_TYPE_MERGE \ + && (sec)->sec_info_type != ELF_INFO_TYPE_JUST_SYMS) + +/* Forward define. */ +struct stat; + +typedef enum bfd_print_symbol +{ + bfd_print_symbol_name, + bfd_print_symbol_more, + bfd_print_symbol_all +} bfd_print_symbol_type; + +/* Information about a symbol that nm needs. */ + +typedef struct _symbol_info +{ + symvalue value; + char type; + const char *name; /* Symbol name. */ + unsigned char stab_type; /* Stab type. */ + char stab_other; /* Stab other. */ + short stab_desc; /* Stab desc. */ + const char *stab_name; /* String for stab type. */ +} symbol_info; + +/* Get the name of a stabs type code. */ + +extern const char *bfd_get_stab_name (int); + +/* Hash table routines. There is no way to free up a hash table. */ + +/* An element in the hash table. Most uses will actually use a larger + structure, and an instance of this will be the first field. */ + +struct bfd_hash_entry +{ + /* Next entry for this hash code. */ + struct bfd_hash_entry *next; + /* String being hashed. */ + const char *string; + /* Hash code. This is the full hash code, not the index into the + table. */ + unsigned long hash; +}; + +/* A hash table. */ + +struct bfd_hash_table +{ + /* The hash array. */ + struct bfd_hash_entry **table; + /* A function used to create new elements in the hash table. The + first entry is itself a pointer to an element. When this + function is first invoked, this pointer will be NULL. However, + having the pointer permits a hierarchy of method functions to be + built each of which calls the function in the superclass. Thus + each function should be written to allocate a new block of memory + only if the argument is NULL. */ + struct bfd_hash_entry *(*newfunc) + (struct bfd_hash_entry *, struct bfd_hash_table *, const char *); + /* An objalloc for this hash table. This is a struct objalloc *, + but we use void * to avoid requiring the inclusion of objalloc.h. */ + void *memory; + /* The number of slots in the hash table. */ + unsigned int size; + /* The number of entries in the hash table. */ + unsigned int count; + /* The size of elements. */ + unsigned int entsize; + /* If non-zero, don't grow the hash table. */ + unsigned int frozen:1; +}; + +/* Initialize a hash table. */ +extern bfd_boolean bfd_hash_table_init + (struct bfd_hash_table *, + struct bfd_hash_entry *(*) (struct bfd_hash_entry *, + struct bfd_hash_table *, + const char *), + unsigned int); + +/* Initialize a hash table specifying a size. */ +extern bfd_boolean bfd_hash_table_init_n + (struct bfd_hash_table *, + struct bfd_hash_entry *(*) (struct bfd_hash_entry *, + struct bfd_hash_table *, + const char *), + unsigned int, unsigned int); + +/* Free up a hash table. */ +extern void bfd_hash_table_free + (struct bfd_hash_table *); + +/* Look up a string in a hash table. If CREATE is TRUE, a new entry + will be created for this string if one does not already exist. The + COPY argument must be TRUE if this routine should copy the string + into newly allocated memory when adding an entry. */ +extern struct bfd_hash_entry *bfd_hash_lookup + (struct bfd_hash_table *, const char *, bfd_boolean create, + bfd_boolean copy); + +/* Replace an entry in a hash table. */ +extern void bfd_hash_replace + (struct bfd_hash_table *, struct bfd_hash_entry *old, + struct bfd_hash_entry *nw); + +/* Base method for creating a hash table entry. */ +extern struct bfd_hash_entry *bfd_hash_newfunc + (struct bfd_hash_entry *, struct bfd_hash_table *, const char *); + +/* Grab some space for a hash table entry. */ +extern void *bfd_hash_allocate + (struct bfd_hash_table *, unsigned int); + +/* Traverse a hash table in a random order, calling a function on each + element. If the function returns FALSE, the traversal stops. The + INFO argument is passed to the function. */ +extern void bfd_hash_traverse + (struct bfd_hash_table *, + bfd_boolean (*) (struct bfd_hash_entry *, void *), + void *info); + +/* Allows the default size of a hash table to be configured. New hash + tables allocated using bfd_hash_table_init will be created with + this size. */ +extern void bfd_hash_set_default_size (bfd_size_type); + +/* This structure is used to keep track of stabs in sections + information while linking. */ + +struct stab_info +{ + /* A hash table used to hold stabs strings. */ + struct bfd_strtab_hash *strings; + /* The header file hash table. */ + struct bfd_hash_table includes; + /* The first .stabstr section. */ + struct bfd_section *stabstr; +}; + +#define COFF_SWAP_TABLE (void *) &bfd_coff_std_swap_table + +/* User program access to BFD facilities. */ + +/* Direct I/O routines, for programs which know more about the object + file than BFD does. Use higher level routines if possible. */ + +extern bfd_size_type bfd_bread (void *, bfd_size_type, bfd *); +extern bfd_size_type bfd_bwrite (const void *, bfd_size_type, bfd *); +extern int bfd_seek (bfd *, file_ptr, int); +extern file_ptr bfd_tell (bfd *); +extern int bfd_flush (bfd *); +extern int bfd_stat (bfd *, struct stat *); + +/* Deprecated old routines. */ +#if __GNUC__ +#define bfd_read(BUF, ELTSIZE, NITEMS, ABFD) \ + (warn_deprecated ("bfd_read", __FILE__, __LINE__, __FUNCTION__), \ + bfd_bread ((BUF), (ELTSIZE) * (NITEMS), (ABFD))) +#define bfd_write(BUF, ELTSIZE, NITEMS, ABFD) \ + (warn_deprecated ("bfd_write", __FILE__, __LINE__, __FUNCTION__), \ + bfd_bwrite ((BUF), (ELTSIZE) * (NITEMS), (ABFD))) +#else +#define bfd_read(BUF, ELTSIZE, NITEMS, ABFD) \ + (warn_deprecated ("bfd_read", (const char *) 0, 0, (const char *) 0), \ + bfd_bread ((BUF), (ELTSIZE) * (NITEMS), (ABFD))) +#define bfd_write(BUF, ELTSIZE, NITEMS, ABFD) \ + (warn_deprecated ("bfd_write", (const char *) 0, 0, (const char *) 0),\ + bfd_bwrite ((BUF), (ELTSIZE) * (NITEMS), (ABFD))) +#endif +extern void warn_deprecated (const char *, const char *, int, const char *); + +/* Cast from const char * to char * so that caller can assign to + a char * without a warning. */ +#define bfd_get_filename(abfd) ((char *) (abfd)->filename) +#define bfd_get_cacheable(abfd) ((abfd)->cacheable) +#define bfd_get_format(abfd) ((abfd)->format) +#define bfd_get_target(abfd) ((abfd)->xvec->name) +#define bfd_get_flavour(abfd) ((abfd)->xvec->flavour) +#define bfd_family_coff(abfd) \ + (bfd_get_flavour (abfd) == bfd_target_coff_flavour || \ + bfd_get_flavour (abfd) == bfd_target_xcoff_flavour) +#define bfd_big_endian(abfd) ((abfd)->xvec->byteorder == BFD_ENDIAN_BIG) +#define bfd_little_endian(abfd) ((abfd)->xvec->byteorder == BFD_ENDIAN_LITTLE) +#define bfd_header_big_endian(abfd) \ + ((abfd)->xvec->header_byteorder == BFD_ENDIAN_BIG) +#define bfd_header_little_endian(abfd) \ + ((abfd)->xvec->header_byteorder == BFD_ENDIAN_LITTLE) +#define bfd_get_file_flags(abfd) ((abfd)->flags) +#define bfd_applicable_file_flags(abfd) ((abfd)->xvec->object_flags) +#define bfd_applicable_section_flags(abfd) ((abfd)->xvec->section_flags) +#define bfd_my_archive(abfd) ((abfd)->my_archive) +#define bfd_has_map(abfd) ((abfd)->has_armap) + +#define bfd_valid_reloc_types(abfd) ((abfd)->xvec->valid_reloc_types) +#define bfd_usrdata(abfd) ((abfd)->usrdata) + +#define bfd_get_start_address(abfd) ((abfd)->start_address) +#define bfd_get_symcount(abfd) ((abfd)->symcount) +#define bfd_get_outsymbols(abfd) ((abfd)->outsymbols) +#define bfd_count_sections(abfd) ((abfd)->section_count) + +#define bfd_get_dynamic_symcount(abfd) ((abfd)->dynsymcount) + +#define bfd_get_symbol_leading_char(abfd) ((abfd)->xvec->symbol_leading_char) + +#define bfd_set_cacheable(abfd,bool) (((abfd)->cacheable = bool), TRUE) + +extern bfd_boolean bfd_cache_close + (bfd *abfd); +/* NB: This declaration should match the autogenerated one in libbfd.h. */ + +extern bfd_boolean bfd_cache_close_all (void); + +extern bfd_boolean bfd_record_phdr + (bfd *, unsigned long, bfd_boolean, flagword, bfd_boolean, bfd_vma, + bfd_boolean, bfd_boolean, unsigned int, struct bfd_section **); + +/* Byte swapping routines. */ + +bfd_uint64_t bfd_getb64 (const void *); +bfd_uint64_t bfd_getl64 (const void *); +bfd_int64_t bfd_getb_signed_64 (const void *); +bfd_int64_t bfd_getl_signed_64 (const void *); +bfd_vma bfd_getb32 (const void *); +bfd_vma bfd_getl32 (const void *); +bfd_signed_vma bfd_getb_signed_32 (const void *); +bfd_signed_vma bfd_getl_signed_32 (const void *); +bfd_vma bfd_getb16 (const void *); +bfd_vma bfd_getl16 (const void *); +bfd_signed_vma bfd_getb_signed_16 (const void *); +bfd_signed_vma bfd_getl_signed_16 (const void *); +void bfd_putb64 (bfd_uint64_t, void *); +void bfd_putl64 (bfd_uint64_t, void *); +void bfd_putb32 (bfd_vma, void *); +void bfd_putl32 (bfd_vma, void *); +void bfd_putb16 (bfd_vma, void *); +void bfd_putl16 (bfd_vma, void *); + +/* Byte swapping routines which take size and endiannes as arguments. */ + +bfd_uint64_t bfd_get_bits (const void *, int, bfd_boolean); +void bfd_put_bits (bfd_uint64_t, void *, int, bfd_boolean); + +extern bfd_boolean bfd_section_already_linked_table_init (void); +extern void bfd_section_already_linked_table_free (void); + +/* Externally visible ECOFF routines. */ + +#if defined(__STDC__) || defined(ALMOST_STDC) +struct ecoff_debug_info; +struct ecoff_debug_swap; +struct ecoff_extr; +struct bfd_symbol; +struct bfd_link_info; +struct bfd_link_hash_entry; +struct bfd_elf_version_tree; +#endif +extern bfd_vma bfd_ecoff_get_gp_value + (bfd * abfd); +extern bfd_boolean bfd_ecoff_set_gp_value + (bfd *abfd, bfd_vma gp_value); +extern bfd_boolean bfd_ecoff_set_regmasks + (bfd *abfd, unsigned long gprmask, unsigned long fprmask, + unsigned long *cprmask); +extern void *bfd_ecoff_debug_init + (bfd *output_bfd, struct ecoff_debug_info *output_debug, + const struct ecoff_debug_swap *output_swap, struct bfd_link_info *); +extern void bfd_ecoff_debug_free + (void *handle, bfd *output_bfd, struct ecoff_debug_info *output_debug, + const struct ecoff_debug_swap *output_swap, struct bfd_link_info *); +extern bfd_boolean bfd_ecoff_debug_accumulate + (void *handle, bfd *output_bfd, struct ecoff_debug_info *output_debug, + const struct ecoff_debug_swap *output_swap, bfd *input_bfd, + struct ecoff_debug_info *input_debug, + const struct ecoff_debug_swap *input_swap, struct bfd_link_info *); +extern bfd_boolean bfd_ecoff_debug_accumulate_other + (void *handle, bfd *output_bfd, struct ecoff_debug_info *output_debug, + const struct ecoff_debug_swap *output_swap, bfd *input_bfd, + struct bfd_link_info *); +extern bfd_boolean bfd_ecoff_debug_externals + (bfd *abfd, struct ecoff_debug_info *debug, + const struct ecoff_debug_swap *swap, bfd_boolean relocatable, + bfd_boolean (*get_extr) (struct bfd_symbol *, struct ecoff_extr *), + void (*set_index) (struct bfd_symbol *, bfd_size_type)); +extern bfd_boolean bfd_ecoff_debug_one_external + (bfd *abfd, struct ecoff_debug_info *debug, + const struct ecoff_debug_swap *swap, const char *name, + struct ecoff_extr *esym); +extern bfd_size_type bfd_ecoff_debug_size + (bfd *abfd, struct ecoff_debug_info *debug, + const struct ecoff_debug_swap *swap); +extern bfd_boolean bfd_ecoff_write_debug + (bfd *abfd, struct ecoff_debug_info *debug, + const struct ecoff_debug_swap *swap, file_ptr where); +extern bfd_boolean bfd_ecoff_write_accumulated_debug + (void *handle, bfd *abfd, struct ecoff_debug_info *debug, + const struct ecoff_debug_swap *swap, + struct bfd_link_info *info, file_ptr where); + +/* Externally visible ELF routines. */ + +struct bfd_link_needed_list +{ + struct bfd_link_needed_list *next; + bfd *by; + const char *name; +}; + +enum dynamic_lib_link_class { + DYN_NORMAL = 0, + DYN_AS_NEEDED = 1, + DYN_DT_NEEDED = 2, + DYN_NO_ADD_NEEDED = 4, + DYN_NO_NEEDED = 8 +}; + +enum notice_asneeded_action { + notice_as_needed, + notice_not_needed, + notice_needed +}; + +extern bfd_boolean bfd_elf_record_link_assignment + (bfd *, struct bfd_link_info *, const char *, bfd_boolean, + bfd_boolean); +extern struct bfd_link_needed_list *bfd_elf_get_needed_list + (bfd *, struct bfd_link_info *); +extern bfd_boolean bfd_elf_get_bfd_needed_list + (bfd *, struct bfd_link_needed_list **); +extern bfd_boolean bfd_elf_size_dynamic_sections + (bfd *, const char *, const char *, const char *, const char * const *, + struct bfd_link_info *, struct bfd_section **, + struct bfd_elf_version_tree *); +extern bfd_boolean bfd_elf_size_dynsym_hash_dynstr + (bfd *, struct bfd_link_info *); +extern void bfd_elf_set_dt_needed_name + (bfd *, const char *); +extern const char *bfd_elf_get_dt_soname + (bfd *); +extern void bfd_elf_set_dyn_lib_class + (bfd *, enum dynamic_lib_link_class); +extern int bfd_elf_get_dyn_lib_class + (bfd *); +extern struct bfd_link_needed_list *bfd_elf_get_runpath_list + (bfd *, struct bfd_link_info *); +extern bfd_boolean bfd_elf_discard_info + (bfd *, struct bfd_link_info *); +extern unsigned int _bfd_elf_default_action_discarded + (struct bfd_section *); + +/* Return an upper bound on the number of bytes required to store a + copy of ABFD's program header table entries. Return -1 if an error + occurs; bfd_get_error will return an appropriate code. */ +extern long bfd_get_elf_phdr_upper_bound + (bfd *abfd); + +/* Copy ABFD's program header table entries to *PHDRS. The entries + will be stored as an array of Elf_Internal_Phdr structures, as + defined in include/elf/internal.h. To find out how large the + buffer needs to be, call bfd_get_elf_phdr_upper_bound. + + Return the number of program header table entries read, or -1 if an + error occurs; bfd_get_error will return an appropriate code. */ +extern int bfd_get_elf_phdrs + (bfd *abfd, void *phdrs); + +/* Create a new BFD as if by bfd_openr. Rather than opening a file, + reconstruct an ELF file by reading the segments out of remote memory + based on the ELF file header at EHDR_VMA and the ELF program headers it + points to. If not null, *LOADBASEP is filled in with the difference + between the VMAs from which the segments were read, and the VMAs the + file headers (and hence BFD's idea of each section's VMA) put them at. + + The function TARGET_READ_MEMORY is called to copy LEN bytes from the + remote memory at target address VMA into the local buffer at MYADDR; it + should return zero on success or an `errno' code on failure. TEMPL must + be a BFD for an ELF target with the word size and byte order found in + the remote memory. */ +extern bfd *bfd_elf_bfd_from_remote_memory + (bfd *templ, bfd_vma ehdr_vma, bfd_vma *loadbasep, + int (*target_read_memory) (bfd_vma vma, bfd_byte *myaddr, int len)); + +/* Return the arch_size field of an elf bfd, or -1 if not elf. */ +extern int bfd_get_arch_size + (bfd *); + +/* Return TRUE if address "naturally" sign extends, or -1 if not elf. */ +extern int bfd_get_sign_extend_vma + (bfd *); + +extern struct bfd_section *_bfd_elf_tls_setup + (bfd *, struct bfd_link_info *); + +extern void _bfd_fix_excluded_sec_syms + (bfd *, struct bfd_link_info *); + +extern unsigned bfd_m68k_mach_to_features (int); + +extern int bfd_m68k_features_to_mach (unsigned); + +extern bfd_boolean bfd_m68k_elf32_create_embedded_relocs + (bfd *, struct bfd_link_info *, struct bfd_section *, struct bfd_section *, + char **); + +extern bfd_boolean bfd_bfin_elf32_create_embedded_relocs + (bfd *, struct bfd_link_info *, struct bfd_section *, struct bfd_section *, + char **); + +/* SunOS shared library support routines for the linker. */ + +extern struct bfd_link_needed_list *bfd_sunos_get_needed_list + (bfd *, struct bfd_link_info *); +extern bfd_boolean bfd_sunos_record_link_assignment + (bfd *, struct bfd_link_info *, const char *); +extern bfd_boolean bfd_sunos_size_dynamic_sections + (bfd *, struct bfd_link_info *, struct bfd_section **, + struct bfd_section **, struct bfd_section **); + +/* Linux shared library support routines for the linker. */ + +extern bfd_boolean bfd_i386linux_size_dynamic_sections + (bfd *, struct bfd_link_info *); +extern bfd_boolean bfd_m68klinux_size_dynamic_sections + (bfd *, struct bfd_link_info *); +extern bfd_boolean bfd_sparclinux_size_dynamic_sections + (bfd *, struct bfd_link_info *); + +/* mmap hacks */ + +struct _bfd_window_internal; +typedef struct _bfd_window_internal bfd_window_internal; + +typedef struct _bfd_window +{ + /* What the user asked for. */ + void *data; + bfd_size_type size; + /* The actual window used by BFD. Small user-requested read-only + regions sharing a page may share a single window into the object + file. Read-write versions shouldn't until I've fixed things to + keep track of which portions have been claimed by the + application; don't want to give the same region back when the + application wants two writable copies! */ + struct _bfd_window_internal *i; +} +bfd_window; + +extern void bfd_init_window + (bfd_window *); +extern void bfd_free_window + (bfd_window *); +extern bfd_boolean bfd_get_file_window + (bfd *, file_ptr, bfd_size_type, bfd_window *, bfd_boolean); + +/* XCOFF support routines for the linker. */ + +extern bfd_boolean bfd_xcoff_link_record_set + (bfd *, struct bfd_link_info *, struct bfd_link_hash_entry *, bfd_size_type); +extern bfd_boolean bfd_xcoff_import_symbol + (bfd *, struct bfd_link_info *, struct bfd_link_hash_entry *, bfd_vma, + const char *, const char *, const char *, unsigned int); +extern bfd_boolean bfd_xcoff_export_symbol + (bfd *, struct bfd_link_info *, struct bfd_link_hash_entry *); +extern bfd_boolean bfd_xcoff_link_count_reloc + (bfd *, struct bfd_link_info *, const char *); +extern bfd_boolean bfd_xcoff_record_link_assignment + (bfd *, struct bfd_link_info *, const char *); +extern bfd_boolean bfd_xcoff_size_dynamic_sections + (bfd *, struct bfd_link_info *, const char *, const char *, + unsigned long, unsigned long, unsigned long, bfd_boolean, + int, bfd_boolean, bfd_boolean, struct bfd_section **, bfd_boolean); +extern bfd_boolean bfd_xcoff_link_generate_rtinit + (bfd *, const char *, const char *, bfd_boolean); + +/* XCOFF support routines for ar. */ +extern bfd_boolean bfd_xcoff_ar_archive_set_magic + (bfd *, char *); + +/* Externally visible COFF routines. */ + +#if defined(__STDC__) || defined(ALMOST_STDC) +struct internal_syment; +union internal_auxent; +#endif + +extern bfd_boolean bfd_coff_get_syment + (bfd *, struct bfd_symbol *, struct internal_syment *); + +extern bfd_boolean bfd_coff_get_auxent + (bfd *, struct bfd_symbol *, int, union internal_auxent *); + +extern bfd_boolean bfd_coff_set_symbol_class + (bfd *, struct bfd_symbol *, unsigned int); + +extern bfd_boolean bfd_m68k_coff_create_embedded_relocs + (bfd *, struct bfd_link_info *, struct bfd_section *, struct bfd_section *, char **); + +/* ARM VFP11 erratum workaround support. */ +typedef enum +{ + BFD_ARM_VFP11_FIX_DEFAULT, + BFD_ARM_VFP11_FIX_NONE, + BFD_ARM_VFP11_FIX_SCALAR, + BFD_ARM_VFP11_FIX_VECTOR +} bfd_arm_vfp11_fix; + +extern void bfd_elf32_arm_init_maps + (bfd *); + +extern void bfd_elf32_arm_set_vfp11_fix + (bfd *, struct bfd_link_info *); + +extern bfd_boolean bfd_elf32_arm_vfp11_erratum_scan + (bfd *, struct bfd_link_info *); + +extern void bfd_elf32_arm_vfp11_fix_veneer_locations + (bfd *, struct bfd_link_info *); + +/* ARM Interworking support. Called from linker. */ +extern bfd_boolean bfd_arm_allocate_interworking_sections + (struct bfd_link_info *); + +extern bfd_boolean bfd_arm_process_before_allocation + (bfd *, struct bfd_link_info *, int); + +extern bfd_boolean bfd_arm_get_bfd_for_interworking + (bfd *, struct bfd_link_info *); + +/* PE ARM Interworking support. Called from linker. */ +extern bfd_boolean bfd_arm_pe_allocate_interworking_sections + (struct bfd_link_info *); + +extern bfd_boolean bfd_arm_pe_process_before_allocation + (bfd *, struct bfd_link_info *, int); + +extern bfd_boolean bfd_arm_pe_get_bfd_for_interworking + (bfd *, struct bfd_link_info *); + +/* ELF ARM Interworking support. Called from linker. */ +extern bfd_boolean bfd_elf32_arm_allocate_interworking_sections + (struct bfd_link_info *); + +extern bfd_boolean bfd_elf32_arm_process_before_allocation + (bfd *, struct bfd_link_info *); + +void bfd_elf32_arm_set_target_relocs + (bfd *, struct bfd_link_info *, int, char *, int, int, bfd_arm_vfp11_fix, + int, int); + +extern bfd_boolean bfd_elf32_arm_get_bfd_for_interworking + (bfd *, struct bfd_link_info *); + +extern bfd_boolean bfd_elf32_arm_add_glue_sections_to_bfd + (bfd *, struct bfd_link_info *); + +/* ELF ARM mapping symbol support */ +#define BFD_ARM_SPECIAL_SYM_TYPE_MAP (1 << 0) +#define BFD_ARM_SPECIAL_SYM_TYPE_TAG (1 << 1) +#define BFD_ARM_SPECIAL_SYM_TYPE_OTHER (1 << 2) +#define BFD_ARM_SPECIAL_SYM_TYPE_ANY (~0) +extern bfd_boolean bfd_is_arm_special_symbol_name + (const char * name, int type); + +extern void bfd_elf32_arm_set_byteswap_code (struct bfd_link_info *, int); + +/* ARM Note section processing. */ +extern bfd_boolean bfd_arm_merge_machines + (bfd *, bfd *); + +extern bfd_boolean bfd_arm_update_notes + (bfd *, const char *); + +extern unsigned int bfd_arm_get_mach_from_notes + (bfd *, const char *); + +/* TI COFF load page support. */ +extern void bfd_ticoff_set_section_load_page + (struct bfd_section *, int); + +extern int bfd_ticoff_get_section_load_page + (struct bfd_section *); + +/* H8/300 functions. */ +extern bfd_vma bfd_h8300_pad_address + (bfd *, bfd_vma); + +/* IA64 Itanium code generation. Called from linker. */ +extern void bfd_elf32_ia64_after_parse + (int); + +extern void bfd_elf64_ia64_after_parse + (int); + +/* This structure is used for a comdat section, as in PE. A comdat + section is associated with a particular symbol. When the linker + sees a comdat section, it keeps only one of the sections with a + given name and associated with a given symbol. */ + +struct coff_comdat_info +{ + /* The name of the symbol associated with a comdat section. */ + const char *name; + + /* The local symbol table index of the symbol associated with a + comdat section. This is only meaningful to the object file format + specific code; it is not an index into the list returned by + bfd_canonicalize_symtab. */ + long symbol; +}; + +extern struct coff_comdat_info *bfd_coff_get_comdat_section + (bfd *, struct bfd_section *); + +/* Extracted from init.c. */ +void bfd_init (void); + +/* Extracted from opncls.c. */ +bfd *bfd_fopen (const char *filename, const char *target, + const char *mode, int fd); + +bfd *bfd_openr (const char *filename, const char *target); + +bfd *bfd_fdopenr (const char *filename, const char *target, int fd); + +bfd *bfd_openstreamr (const char *, const char *, void *); + +bfd *bfd_openr_iovec (const char *filename, const char *target, + void *(*open) (struct bfd *nbfd, + void *open_closure), + void *open_closure, + file_ptr (*pread) (struct bfd *nbfd, + void *stream, + void *buf, + file_ptr nbytes, + file_ptr offset), + int (*close) (struct bfd *nbfd, + void *stream), + int (*stat) (struct bfd *abfd, + void *stream, + struct stat *sb)); + +bfd *bfd_openw (const char *filename, const char *target); + +bfd_boolean bfd_close (bfd *abfd); + +bfd_boolean bfd_close_all_done (bfd *); + +bfd *bfd_create (const char *filename, bfd *templ); + +bfd_boolean bfd_make_writable (bfd *abfd); + +bfd_boolean bfd_make_readable (bfd *abfd); + +unsigned long bfd_calc_gnu_debuglink_crc32 + (unsigned long crc, const unsigned char *buf, bfd_size_type len); + +char *bfd_follow_gnu_debuglink (bfd *abfd, const char *dir); + +struct bfd_section *bfd_create_gnu_debuglink_section + (bfd *abfd, const char *filename); + +bfd_boolean bfd_fill_in_gnu_debuglink_section + (bfd *abfd, struct bfd_section *sect, const char *filename); + +/* Extracted from libbfd.c. */ + +/* Byte swapping macros for user section data. */ + +#define bfd_put_8(abfd, val, ptr) \ + ((void) (*((unsigned char *) (ptr)) = (val) & 0xff)) +#define bfd_put_signed_8 \ + bfd_put_8 +#define bfd_get_8(abfd, ptr) \ + (*(unsigned char *) (ptr) & 0xff) +#define bfd_get_signed_8(abfd, ptr) \ + (((*(unsigned char *) (ptr) & 0xff) ^ 0x80) - 0x80) + +#define bfd_put_16(abfd, val, ptr) \ + BFD_SEND (abfd, bfd_putx16, ((val),(ptr))) +#define bfd_put_signed_16 \ + bfd_put_16 +#define bfd_get_16(abfd, ptr) \ + BFD_SEND (abfd, bfd_getx16, (ptr)) +#define bfd_get_signed_16(abfd, ptr) \ + BFD_SEND (abfd, bfd_getx_signed_16, (ptr)) + +#define bfd_put_32(abfd, val, ptr) \ + BFD_SEND (abfd, bfd_putx32, ((val),(ptr))) +#define bfd_put_signed_32 \ + bfd_put_32 +#define bfd_get_32(abfd, ptr) \ + BFD_SEND (abfd, bfd_getx32, (ptr)) +#define bfd_get_signed_32(abfd, ptr) \ + BFD_SEND (abfd, bfd_getx_signed_32, (ptr)) + +#define bfd_put_64(abfd, val, ptr) \ + BFD_SEND (abfd, bfd_putx64, ((val), (ptr))) +#define bfd_put_signed_64 \ + bfd_put_64 +#define bfd_get_64(abfd, ptr) \ + BFD_SEND (abfd, bfd_getx64, (ptr)) +#define bfd_get_signed_64(abfd, ptr) \ + BFD_SEND (abfd, bfd_getx_signed_64, (ptr)) + +#define bfd_get(bits, abfd, ptr) \ + ((bits) == 8 ? (bfd_vma) bfd_get_8 (abfd, ptr) \ + : (bits) == 16 ? bfd_get_16 (abfd, ptr) \ + : (bits) == 32 ? bfd_get_32 (abfd, ptr) \ + : (bits) == 64 ? bfd_get_64 (abfd, ptr) \ + : (abort (), (bfd_vma) - 1)) + +#define bfd_put(bits, abfd, val, ptr) \ + ((bits) == 8 ? bfd_put_8 (abfd, val, ptr) \ + : (bits) == 16 ? bfd_put_16 (abfd, val, ptr) \ + : (bits) == 32 ? bfd_put_32 (abfd, val, ptr) \ + : (bits) == 64 ? bfd_put_64 (abfd, val, ptr) \ + : (abort (), (void) 0)) + + +/* Byte swapping macros for file header data. */ + +#define bfd_h_put_8(abfd, val, ptr) \ + bfd_put_8 (abfd, val, ptr) +#define bfd_h_put_signed_8(abfd, val, ptr) \ + bfd_put_8 (abfd, val, ptr) +#define bfd_h_get_8(abfd, ptr) \ + bfd_get_8 (abfd, ptr) +#define bfd_h_get_signed_8(abfd, ptr) \ + bfd_get_signed_8 (abfd, ptr) + +#define bfd_h_put_16(abfd, val, ptr) \ + BFD_SEND (abfd, bfd_h_putx16, (val, ptr)) +#define bfd_h_put_signed_16 \ + bfd_h_put_16 +#define bfd_h_get_16(abfd, ptr) \ + BFD_SEND (abfd, bfd_h_getx16, (ptr)) +#define bfd_h_get_signed_16(abfd, ptr) \ + BFD_SEND (abfd, bfd_h_getx_signed_16, (ptr)) + +#define bfd_h_put_32(abfd, val, ptr) \ + BFD_SEND (abfd, bfd_h_putx32, (val, ptr)) +#define bfd_h_put_signed_32 \ + bfd_h_put_32 +#define bfd_h_get_32(abfd, ptr) \ + BFD_SEND (abfd, bfd_h_getx32, (ptr)) +#define bfd_h_get_signed_32(abfd, ptr) \ + BFD_SEND (abfd, bfd_h_getx_signed_32, (ptr)) + +#define bfd_h_put_64(abfd, val, ptr) \ + BFD_SEND (abfd, bfd_h_putx64, (val, ptr)) +#define bfd_h_put_signed_64 \ + bfd_h_put_64 +#define bfd_h_get_64(abfd, ptr) \ + BFD_SEND (abfd, bfd_h_getx64, (ptr)) +#define bfd_h_get_signed_64(abfd, ptr) \ + BFD_SEND (abfd, bfd_h_getx_signed_64, (ptr)) + +/* Aliases for the above, which should eventually go away. */ + +#define H_PUT_64 bfd_h_put_64 +#define H_PUT_32 bfd_h_put_32 +#define H_PUT_16 bfd_h_put_16 +#define H_PUT_8 bfd_h_put_8 +#define H_PUT_S64 bfd_h_put_signed_64 +#define H_PUT_S32 bfd_h_put_signed_32 +#define H_PUT_S16 bfd_h_put_signed_16 +#define H_PUT_S8 bfd_h_put_signed_8 +#define H_GET_64 bfd_h_get_64 +#define H_GET_32 bfd_h_get_32 +#define H_GET_16 bfd_h_get_16 +#define H_GET_8 bfd_h_get_8 +#define H_GET_S64 bfd_h_get_signed_64 +#define H_GET_S32 bfd_h_get_signed_32 +#define H_GET_S16 bfd_h_get_signed_16 +#define H_GET_S8 bfd_h_get_signed_8 + + +/* Extracted from bfdio.c. */ +long bfd_get_mtime (bfd *abfd); + +file_ptr bfd_get_size (bfd *abfd); + +/* Extracted from bfdwin.c. */ +/* Extracted from section.c. */ +typedef struct bfd_section +{ + /* The name of the section; the name isn't a copy, the pointer is + the same as that passed to bfd_make_section. */ + const char *name; + + /* A unique sequence number. */ + int id; + + /* Which section in the bfd; 0..n-1 as sections are created in a bfd. */ + int index; + + /* The next section in the list belonging to the BFD, or NULL. */ + struct bfd_section *next; + + /* The previous section in the list belonging to the BFD, or NULL. */ + struct bfd_section *prev; + + /* The field flags contains attributes of the section. Some + flags are read in from the object file, and some are + synthesized from other information. */ + flagword flags; + +#define SEC_NO_FLAGS 0x000 + + /* Tells the OS to allocate space for this section when loading. + This is clear for a section containing debug information only. */ +#define SEC_ALLOC 0x001 + + /* Tells the OS to load the section from the file when loading. + This is clear for a .bss section. */ +#define SEC_LOAD 0x002 + + /* The section contains data still to be relocated, so there is + some relocation information too. */ +#define SEC_RELOC 0x004 + + /* A signal to the OS that the section contains read only data. */ +#define SEC_READONLY 0x008 + + /* The section contains code only. */ +#define SEC_CODE 0x010 + + /* The section contains data only. */ +#define SEC_DATA 0x020 + + /* The section will reside in ROM. */ +#define SEC_ROM 0x040 + + /* The section contains constructor information. This section + type is used by the linker to create lists of constructors and + destructors used by <>. When a back end sees a symbol + which should be used in a constructor list, it creates a new + section for the type of name (e.g., <<__CTOR_LIST__>>), attaches + the symbol to it, and builds a relocation. To build the lists + of constructors, all the linker has to do is catenate all the + sections called <<__CTOR_LIST__>> and relocate the data + contained within - exactly the operations it would peform on + standard data. */ +#define SEC_CONSTRUCTOR 0x080 + + /* The section has contents - a data section could be + <> | <>; a debug section could be + <> */ +#define SEC_HAS_CONTENTS 0x100 + + /* An instruction to the linker to not output the section + even if it has information which would normally be written. */ +#define SEC_NEVER_LOAD 0x200 + + /* The section contains thread local data. */ +#define SEC_THREAD_LOCAL 0x400 + + /* The section has GOT references. This flag is only for the + linker, and is currently only used by the elf32-hppa back end. + It will be set if global offset table references were detected + in this section, which indicate to the linker that the section + contains PIC code, and must be handled specially when doing a + static link. */ +#define SEC_HAS_GOT_REF 0x800 + + /* The section contains common symbols (symbols may be defined + multiple times, the value of a symbol is the amount of + space it requires, and the largest symbol value is the one + used). Most targets have exactly one of these (which we + translate to bfd_com_section_ptr), but ECOFF has two. */ +#define SEC_IS_COMMON 0x1000 + + /* The section contains only debugging information. For + example, this is set for ELF .debug and .stab sections. + strip tests this flag to see if a section can be + discarded. */ +#define SEC_DEBUGGING 0x2000 + + /* The contents of this section are held in memory pointed to + by the contents field. This is checked by bfd_get_section_contents, + and the data is retrieved from memory if appropriate. */ +#define SEC_IN_MEMORY 0x4000 + + /* The contents of this section are to be excluded by the + linker for executable and shared objects unless those + objects are to be further relocated. */ +#define SEC_EXCLUDE 0x8000 + + /* The contents of this section are to be sorted based on the sum of + the symbol and addend values specified by the associated relocation + entries. Entries without associated relocation entries will be + appended to the end of the section in an unspecified order. */ +#define SEC_SORT_ENTRIES 0x10000 + + /* When linking, duplicate sections of the same name should be + discarded, rather than being combined into a single section as + is usually done. This is similar to how common symbols are + handled. See SEC_LINK_DUPLICATES below. */ +#define SEC_LINK_ONCE 0x20000 + + /* If SEC_LINK_ONCE is set, this bitfield describes how the linker + should handle duplicate sections. */ +#define SEC_LINK_DUPLICATES 0x40000 + + /* This value for SEC_LINK_DUPLICATES means that duplicate + sections with the same name should simply be discarded. */ +#define SEC_LINK_DUPLICATES_DISCARD 0x0 + + /* This value for SEC_LINK_DUPLICATES means that the linker + should warn if there are any duplicate sections, although + it should still only link one copy. */ +#define SEC_LINK_DUPLICATES_ONE_ONLY 0x80000 + + /* This value for SEC_LINK_DUPLICATES means that the linker + should warn if any duplicate sections are a different size. */ +#define SEC_LINK_DUPLICATES_SAME_SIZE 0x100000 + + /* This value for SEC_LINK_DUPLICATES means that the linker + should warn if any duplicate sections contain different + contents. */ +#define SEC_LINK_DUPLICATES_SAME_CONTENTS \ + (SEC_LINK_DUPLICATES_ONE_ONLY | SEC_LINK_DUPLICATES_SAME_SIZE) + + /* This section was created by the linker as part of dynamic + relocation or other arcane processing. It is skipped when + going through the first-pass output, trusting that someone + else up the line will take care of it later. */ +#define SEC_LINKER_CREATED 0x200000 + + /* This section should not be subject to garbage collection. + Also set to inform the linker that this section should not be + listed in the link map as discarded. */ +#define SEC_KEEP 0x400000 + + /* This section contains "short" data, and should be placed + "near" the GP. */ +#define SEC_SMALL_DATA 0x800000 + + /* Attempt to merge identical entities in the section. + Entity size is given in the entsize field. */ +#define SEC_MERGE 0x1000000 + + /* If given with SEC_MERGE, entities to merge are zero terminated + strings where entsize specifies character size instead of fixed + size entries. */ +#define SEC_STRINGS 0x2000000 + + /* This section contains data about section groups. */ +#define SEC_GROUP 0x4000000 + + /* The section is a COFF shared library section. This flag is + only for the linker. If this type of section appears in + the input file, the linker must copy it to the output file + without changing the vma or size. FIXME: Although this + was originally intended to be general, it really is COFF + specific (and the flag was renamed to indicate this). It + might be cleaner to have some more general mechanism to + allow the back end to control what the linker does with + sections. */ +#define SEC_COFF_SHARED_LIBRARY 0x10000000 + + /* This section contains data which may be shared with other + executables or shared objects. This is for COFF only. */ +#define SEC_COFF_SHARED 0x20000000 + + /* When a section with this flag is being linked, then if the size of + the input section is less than a page, it should not cross a page + boundary. If the size of the input section is one page or more, + it should be aligned on a page boundary. This is for TI + TMS320C54X only. */ +#define SEC_TIC54X_BLOCK 0x40000000 + + /* Conditionally link this section; do not link if there are no + references found to any symbol in the section. This is for TI + TMS320C54X only. */ +#define SEC_TIC54X_CLINK 0x80000000 + + /* End of section flags. */ + + /* Some internal packed boolean fields. */ + + /* See the vma field. */ + unsigned int user_set_vma : 1; + + /* A mark flag used by some of the linker backends. */ + unsigned int linker_mark : 1; + + /* Another mark flag used by some of the linker backends. Set for + output sections that have an input section. */ + unsigned int linker_has_input : 1; + + /* Mark flags used by some linker backends for garbage collection. */ + unsigned int gc_mark : 1; + unsigned int gc_mark_from_eh : 1; + + /* The following flags are used by the ELF linker. */ + + /* Mark sections which have been allocated to segments. */ + unsigned int segment_mark : 1; + + /* Type of sec_info information. */ + unsigned int sec_info_type:3; +#define ELF_INFO_TYPE_NONE 0 +#define ELF_INFO_TYPE_STABS 1 +#define ELF_INFO_TYPE_MERGE 2 +#define ELF_INFO_TYPE_EH_FRAME 3 +#define ELF_INFO_TYPE_JUST_SYMS 4 + + /* Nonzero if this section uses RELA relocations, rather than REL. */ + unsigned int use_rela_p:1; + + /* Bits used by various backends. The generic code doesn't touch + these fields. */ + + /* Nonzero if this section has TLS related relocations. */ + unsigned int has_tls_reloc:1; + + /* Nonzero if this section has a gp reloc. */ + unsigned int has_gp_reloc:1; + + /* Nonzero if this section needs the relax finalize pass. */ + unsigned int need_finalize_relax:1; + + /* Whether relocations have been processed. */ + unsigned int reloc_done : 1; + + /* End of internal packed boolean fields. */ + + /* The virtual memory address of the section - where it will be + at run time. The symbols are relocated against this. The + user_set_vma flag is maintained by bfd; if it's not set, the + backend can assign addresses (for example, in <>, where + the default address for <<.data>> is dependent on the specific + target and various flags). */ + bfd_vma vma; + + /* The load address of the section - where it would be in a + rom image; really only used for writing section header + information. */ + bfd_vma lma; + + /* The size of the section in octets, as it will be output. + Contains a value even if the section has no contents (e.g., the + size of <<.bss>>). */ + bfd_size_type size; + + /* For input sections, the original size on disk of the section, in + octets. This field is used by the linker relaxation code. It is + currently only set for sections where the linker relaxation scheme + doesn't cache altered section and reloc contents (stabs, eh_frame, + SEC_MERGE, some coff relaxing targets), and thus the original size + needs to be kept to read the section multiple times. + For output sections, rawsize holds the section size calculated on + a previous linker relaxation pass. */ + bfd_size_type rawsize; + + /* If this section is going to be output, then this value is the + offset in *bytes* into the output section of the first byte in the + input section (byte ==> smallest addressable unit on the + target). In most cases, if this was going to start at the + 100th octet (8-bit quantity) in the output section, this value + would be 100. However, if the target byte size is 16 bits + (bfd_octets_per_byte is "2"), this value would be 50. */ + bfd_vma output_offset; + + /* The output section through which to map on output. */ + struct bfd_section *output_section; + + /* The alignment requirement of the section, as an exponent of 2 - + e.g., 3 aligns to 2^3 (or 8). */ + unsigned int alignment_power; + + /* If an input section, a pointer to a vector of relocation + records for the data in this section. */ + struct reloc_cache_entry *relocation; + + /* If an output section, a pointer to a vector of pointers to + relocation records for the data in this section. */ + struct reloc_cache_entry **orelocation; + + /* The number of relocation records in one of the above. */ + unsigned reloc_count; + + /* Information below is back end specific - and not always used + or updated. */ + + /* File position of section data. */ + file_ptr filepos; + + /* File position of relocation info. */ + file_ptr rel_filepos; + + /* File position of line data. */ + file_ptr line_filepos; + + /* Pointer to data for applications. */ + void *userdata; + + /* If the SEC_IN_MEMORY flag is set, this points to the actual + contents. */ + unsigned char *contents; + + /* Attached line number information. */ + alent *lineno; + + /* Number of line number records. */ + unsigned int lineno_count; + + /* Entity size for merging purposes. */ + unsigned int entsize; + + /* Points to the kept section if this section is a link-once section, + and is discarded. */ + struct bfd_section *kept_section; + + /* When a section is being output, this value changes as more + linenumbers are written out. */ + file_ptr moving_line_filepos; + + /* What the section number is in the target world. */ + int target_index; + + void *used_by_bfd; + + /* If this is a constructor section then here is a list of the + relocations created to relocate items within it. */ + struct relent_chain *constructor_chain; + + /* The BFD which owns the section. */ + bfd *owner; + + /* A symbol which points at this section only. */ + struct bfd_symbol *symbol; + struct bfd_symbol **symbol_ptr_ptr; + + /* Early in the link process, map_head and map_tail are used to build + a list of input sections attached to an output section. Later, + output sections use these fields for a list of bfd_link_order + structs. */ + union { + struct bfd_link_order *link_order; + struct bfd_section *s; + } map_head, map_tail; +} asection; + +/* These sections are global, and are managed by BFD. The application + and target back end are not permitted to change the values in + these sections. New code should use the section_ptr macros rather + than referring directly to the const sections. The const sections + may eventually vanish. */ +#define BFD_ABS_SECTION_NAME "*ABS*" +#define BFD_UND_SECTION_NAME "*UND*" +#define BFD_COM_SECTION_NAME "*COM*" +#define BFD_IND_SECTION_NAME "*IND*" + +/* The absolute section. */ +extern asection bfd_abs_section; +#define bfd_abs_section_ptr ((asection *) &bfd_abs_section) +#define bfd_is_abs_section(sec) ((sec) == bfd_abs_section_ptr) +/* Pointer to the undefined section. */ +extern asection bfd_und_section; +#define bfd_und_section_ptr ((asection *) &bfd_und_section) +#define bfd_is_und_section(sec) ((sec) == bfd_und_section_ptr) +/* Pointer to the common section. */ +extern asection bfd_com_section; +#define bfd_com_section_ptr ((asection *) &bfd_com_section) +/* Pointer to the indirect section. */ +extern asection bfd_ind_section; +#define bfd_ind_section_ptr ((asection *) &bfd_ind_section) +#define bfd_is_ind_section(sec) ((sec) == bfd_ind_section_ptr) + +#define bfd_is_const_section(SEC) \ + ( ((SEC) == bfd_abs_section_ptr) \ + || ((SEC) == bfd_und_section_ptr) \ + || ((SEC) == bfd_com_section_ptr) \ + || ((SEC) == bfd_ind_section_ptr)) + +/* Macros to handle insertion and deletion of a bfd's sections. These + only handle the list pointers, ie. do not adjust section_count, + target_index etc. */ +#define bfd_section_list_remove(ABFD, S) \ + do \ + { \ + asection *_s = S; \ + asection *_next = _s->next; \ + asection *_prev = _s->prev; \ + if (_prev) \ + _prev->next = _next; \ + else \ + (ABFD)->sections = _next; \ + if (_next) \ + _next->prev = _prev; \ + else \ + (ABFD)->section_last = _prev; \ + } \ + while (0) +#define bfd_section_list_append(ABFD, S) \ + do \ + { \ + asection *_s = S; \ + bfd *_abfd = ABFD; \ + _s->next = NULL; \ + if (_abfd->section_last) \ + { \ + _s->prev = _abfd->section_last; \ + _abfd->section_last->next = _s; \ + } \ + else \ + { \ + _s->prev = NULL; \ + _abfd->sections = _s; \ + } \ + _abfd->section_last = _s; \ + } \ + while (0) +#define bfd_section_list_prepend(ABFD, S) \ + do \ + { \ + asection *_s = S; \ + bfd *_abfd = ABFD; \ + _s->prev = NULL; \ + if (_abfd->sections) \ + { \ + _s->next = _abfd->sections; \ + _abfd->sections->prev = _s; \ + } \ + else \ + { \ + _s->next = NULL; \ + _abfd->section_last = _s; \ + } \ + _abfd->sections = _s; \ + } \ + while (0) +#define bfd_section_list_insert_after(ABFD, A, S) \ + do \ + { \ + asection *_a = A; \ + asection *_s = S; \ + asection *_next = _a->next; \ + _s->next = _next; \ + _s->prev = _a; \ + _a->next = _s; \ + if (_next) \ + _next->prev = _s; \ + else \ + (ABFD)->section_last = _s; \ + } \ + while (0) +#define bfd_section_list_insert_before(ABFD, B, S) \ + do \ + { \ + asection *_b = B; \ + asection *_s = S; \ + asection *_prev = _b->prev; \ + _s->prev = _prev; \ + _s->next = _b; \ + _b->prev = _s; \ + if (_prev) \ + _prev->next = _s; \ + else \ + (ABFD)->sections = _s; \ + } \ + while (0) +#define bfd_section_removed_from_list(ABFD, S) \ + ((S)->next == NULL ? (ABFD)->section_last != (S) : (S)->next->prev != (S)) + +#define BFD_FAKE_SECTION(SEC, FLAGS, SYM, NAME, IDX) \ + /* name, id, index, next, prev, flags, user_set_vma, */ \ + { NAME, IDX, 0, NULL, NULL, FLAGS, 0, \ + \ + /* linker_mark, linker_has_input, gc_mark, gc_mark_from_eh, */ \ + 0, 0, 1, 0, \ + \ + /* segment_mark, sec_info_type, use_rela_p, has_tls_reloc, */ \ + 0, 0, 0, 0, \ + \ + /* has_gp_reloc, need_finalize_relax, reloc_done, */ \ + 0, 0, 0, \ + \ + /* vma, lma, size, rawsize */ \ + 0, 0, 0, 0, \ + \ + /* output_offset, output_section, alignment_power, */ \ + 0, (struct bfd_section *) &SEC, 0, \ + \ + /* relocation, orelocation, reloc_count, filepos, rel_filepos, */ \ + NULL, NULL, 0, 0, 0, \ + \ + /* line_filepos, userdata, contents, lineno, lineno_count, */ \ + 0, NULL, NULL, NULL, 0, \ + \ + /* entsize, kept_section, moving_line_filepos, */ \ + 0, NULL, 0, \ + \ + /* target_index, used_by_bfd, constructor_chain, owner, */ \ + 0, NULL, NULL, NULL, \ + \ + /* symbol, symbol_ptr_ptr, */ \ + (struct bfd_symbol *) SYM, &SEC.symbol, \ + \ + /* map_head, map_tail */ \ + { NULL }, { NULL } \ + } + +void bfd_section_list_clear (bfd *); + +asection *bfd_get_section_by_name (bfd *abfd, const char *name); + +asection *bfd_get_section_by_name_if + (bfd *abfd, + const char *name, + bfd_boolean (*func) (bfd *abfd, asection *sect, void *obj), + void *obj); + +char *bfd_get_unique_section_name + (bfd *abfd, const char *templat, int *count); + +asection *bfd_make_section_old_way (bfd *abfd, const char *name); + +asection *bfd_make_section_anyway_with_flags + (bfd *abfd, const char *name, flagword flags); + +asection *bfd_make_section_anyway (bfd *abfd, const char *name); + +asection *bfd_make_section_with_flags + (bfd *, const char *name, flagword flags); + +asection *bfd_make_section (bfd *, const char *name); + +bfd_boolean bfd_set_section_flags + (bfd *abfd, asection *sec, flagword flags); + +void bfd_map_over_sections + (bfd *abfd, + void (*func) (bfd *abfd, asection *sect, void *obj), + void *obj); + +asection *bfd_sections_find_if + (bfd *abfd, + bfd_boolean (*operation) (bfd *abfd, asection *sect, void *obj), + void *obj); + +bfd_boolean bfd_set_section_size + (bfd *abfd, asection *sec, bfd_size_type val); + +bfd_boolean bfd_set_section_contents + (bfd *abfd, asection *section, const void *data, + file_ptr offset, bfd_size_type count); + +bfd_boolean bfd_get_section_contents + (bfd *abfd, asection *section, void *location, file_ptr offset, + bfd_size_type count); + +bfd_boolean bfd_malloc_and_get_section + (bfd *abfd, asection *section, bfd_byte **buf); + +bfd_boolean bfd_copy_private_section_data + (bfd *ibfd, asection *isec, bfd *obfd, asection *osec); + +#define bfd_copy_private_section_data(ibfd, isection, obfd, osection) \ + BFD_SEND (obfd, _bfd_copy_private_section_data, \ + (ibfd, isection, obfd, osection)) +bfd_boolean bfd_generic_is_group_section (bfd *, const asection *sec); + +bfd_boolean bfd_generic_discard_group (bfd *abfd, asection *group); + +/* Extracted from archures.c. */ +enum bfd_architecture +{ + bfd_arch_unknown, /* File arch not known. */ + bfd_arch_obscure, /* Arch known, not one of these. */ + bfd_arch_m68k, /* Motorola 68xxx */ +#define bfd_mach_m68000 1 +#define bfd_mach_m68008 2 +#define bfd_mach_m68010 3 +#define bfd_mach_m68020 4 +#define bfd_mach_m68030 5 +#define bfd_mach_m68040 6 +#define bfd_mach_m68060 7 +#define bfd_mach_cpu32 8 +#define bfd_mach_fido 9 +#define bfd_mach_mcf_isa_a_nodiv 10 +#define bfd_mach_mcf_isa_a 11 +#define bfd_mach_mcf_isa_a_mac 12 +#define bfd_mach_mcf_isa_a_emac 13 +#define bfd_mach_mcf_isa_aplus 14 +#define bfd_mach_mcf_isa_aplus_mac 15 +#define bfd_mach_mcf_isa_aplus_emac 16 +#define bfd_mach_mcf_isa_b_nousp 17 +#define bfd_mach_mcf_isa_b_nousp_mac 18 +#define bfd_mach_mcf_isa_b_nousp_emac 19 +#define bfd_mach_mcf_isa_b 20 +#define bfd_mach_mcf_isa_b_mac 21 +#define bfd_mach_mcf_isa_b_emac 22 +#define bfd_mach_mcf_isa_b_float 23 +#define bfd_mach_mcf_isa_b_float_mac 24 +#define bfd_mach_mcf_isa_b_float_emac 25 +#define bfd_mach_mcf_isa_c 26 +#define bfd_mach_mcf_isa_c_mac 27 +#define bfd_mach_mcf_isa_c_emac 28 + bfd_arch_vax, /* DEC Vax */ + bfd_arch_i960, /* Intel 960 */ + /* The order of the following is important. + lower number indicates a machine type that + only accepts a subset of the instructions + available to machines with higher numbers. + The exception is the "ca", which is + incompatible with all other machines except + "core". */ + +#define bfd_mach_i960_core 1 +#define bfd_mach_i960_ka_sa 2 +#define bfd_mach_i960_kb_sb 3 +#define bfd_mach_i960_mc 4 +#define bfd_mach_i960_xa 5 +#define bfd_mach_i960_ca 6 +#define bfd_mach_i960_jx 7 +#define bfd_mach_i960_hx 8 + + bfd_arch_or32, /* OpenRISC 32 */ + + bfd_arch_sparc, /* SPARC */ +#define bfd_mach_sparc 1 +/* The difference between v8plus and v9 is that v9 is a true 64 bit env. */ +#define bfd_mach_sparc_sparclet 2 +#define bfd_mach_sparc_sparclite 3 +#define bfd_mach_sparc_v8plus 4 +#define bfd_mach_sparc_v8plusa 5 /* with ultrasparc add'ns. */ +#define bfd_mach_sparc_sparclite_le 6 +#define bfd_mach_sparc_v9 7 +#define bfd_mach_sparc_v9a 8 /* with ultrasparc add'ns. */ +#define bfd_mach_sparc_v8plusb 9 /* with cheetah add'ns. */ +#define bfd_mach_sparc_v9b 10 /* with cheetah add'ns. */ +/* Nonzero if MACH has the v9 instruction set. */ +#define bfd_mach_sparc_v9_p(mach) \ + ((mach) >= bfd_mach_sparc_v8plus && (mach) <= bfd_mach_sparc_v9b \ + && (mach) != bfd_mach_sparc_sparclite_le) +/* Nonzero if MACH is a 64 bit sparc architecture. */ +#define bfd_mach_sparc_64bit_p(mach) \ + ((mach) >= bfd_mach_sparc_v9 && (mach) != bfd_mach_sparc_v8plusb) + bfd_arch_spu, /* PowerPC SPU */ +#define bfd_mach_spu 256 + bfd_arch_mips, /* MIPS Rxxxx */ +#define bfd_mach_mips3000 3000 +#define bfd_mach_mips3900 3900 +#define bfd_mach_mips4000 4000 +#define bfd_mach_mips4010 4010 +#define bfd_mach_mips4100 4100 +#define bfd_mach_mips4111 4111 +#define bfd_mach_mips4120 4120 +#define bfd_mach_mips4300 4300 +#define bfd_mach_mips4400 4400 +#define bfd_mach_mips4600 4600 +#define bfd_mach_mips4650 4650 +#define bfd_mach_mips5000 5000 +#define bfd_mach_mips5400 5400 +#define bfd_mach_mips5500 5500 +#define bfd_mach_mips6000 6000 +#define bfd_mach_mips7000 7000 +#define bfd_mach_mips8000 8000 +#define bfd_mach_mips9000 9000 +#define bfd_mach_mips10000 10000 +#define bfd_mach_mips12000 12000 +#define bfd_mach_mips16 16 +#define bfd_mach_mips5 5 +#define bfd_mach_mips_sb1 12310201 /* octal 'SB', 01 */ +#define bfd_mach_mipsisa32 32 +#define bfd_mach_mipsisa32r2 33 +#define bfd_mach_mipsisa64 64 +#define bfd_mach_mipsisa64r2 65 + bfd_arch_i386, /* Intel 386 */ +#define bfd_mach_i386_i386 1 +#define bfd_mach_i386_i8086 2 +#define bfd_mach_i386_i386_intel_syntax 3 +#define bfd_mach_x86_64 64 +#define bfd_mach_x86_64_intel_syntax 65 + bfd_arch_we32k, /* AT&T WE32xxx */ + bfd_arch_tahoe, /* CCI/Harris Tahoe */ + bfd_arch_i860, /* Intel 860 */ + bfd_arch_i370, /* IBM 360/370 Mainframes */ + bfd_arch_romp, /* IBM ROMP PC/RT */ + bfd_arch_convex, /* Convex */ + bfd_arch_m88k, /* Motorola 88xxx */ + bfd_arch_m98k, /* Motorola 98xxx */ + bfd_arch_pyramid, /* Pyramid Technology */ + bfd_arch_h8300, /* Renesas H8/300 (formerly Hitachi H8/300) */ +#define bfd_mach_h8300 1 +#define bfd_mach_h8300h 2 +#define bfd_mach_h8300s 3 +#define bfd_mach_h8300hn 4 +#define bfd_mach_h8300sn 5 +#define bfd_mach_h8300sx 6 +#define bfd_mach_h8300sxn 7 + bfd_arch_pdp11, /* DEC PDP-11 */ + bfd_arch_powerpc, /* PowerPC */ +#define bfd_mach_ppc 32 +#define bfd_mach_ppc64 64 +#define bfd_mach_ppc_403 403 +#define bfd_mach_ppc_403gc 4030 +#define bfd_mach_ppc_505 505 +#define bfd_mach_ppc_601 601 +#define bfd_mach_ppc_602 602 +#define bfd_mach_ppc_603 603 +#define bfd_mach_ppc_ec603e 6031 +#define bfd_mach_ppc_604 604 +#define bfd_mach_ppc_620 620 +#define bfd_mach_ppc_630 630 +#define bfd_mach_ppc_750 750 +#define bfd_mach_ppc_860 860 +#define bfd_mach_ppc_a35 35 +#define bfd_mach_ppc_rs64ii 642 +#define bfd_mach_ppc_rs64iii 643 +#define bfd_mach_ppc_7400 7400 +#define bfd_mach_ppc_e500 500 + bfd_arch_rs6000, /* IBM RS/6000 */ +#define bfd_mach_rs6k 6000 +#define bfd_mach_rs6k_rs1 6001 +#define bfd_mach_rs6k_rsc 6003 +#define bfd_mach_rs6k_rs2 6002 + bfd_arch_hppa, /* HP PA RISC */ +#define bfd_mach_hppa10 10 +#define bfd_mach_hppa11 11 +#define bfd_mach_hppa20 20 +#define bfd_mach_hppa20w 25 + bfd_arch_d10v, /* Mitsubishi D10V */ +#define bfd_mach_d10v 1 +#define bfd_mach_d10v_ts2 2 +#define bfd_mach_d10v_ts3 3 + bfd_arch_d30v, /* Mitsubishi D30V */ + bfd_arch_dlx, /* DLX */ + bfd_arch_m68hc11, /* Motorola 68HC11 */ + bfd_arch_m68hc12, /* Motorola 68HC12 */ +#define bfd_mach_m6812_default 0 +#define bfd_mach_m6812 1 +#define bfd_mach_m6812s 2 + bfd_arch_z8k, /* Zilog Z8000 */ +#define bfd_mach_z8001 1 +#define bfd_mach_z8002 2 + bfd_arch_h8500, /* Renesas H8/500 (formerly Hitachi H8/500) */ + bfd_arch_sh, /* Renesas / SuperH SH (formerly Hitachi SH) */ +#define bfd_mach_sh 1 +#define bfd_mach_sh2 0x20 +#define bfd_mach_sh_dsp 0x2d +#define bfd_mach_sh2a 0x2a +#define bfd_mach_sh2a_nofpu 0x2b +#define bfd_mach_sh2a_nofpu_or_sh4_nommu_nofpu 0x2a1 +#define bfd_mach_sh2a_nofpu_or_sh3_nommu 0x2a2 +#define bfd_mach_sh2a_or_sh4 0x2a3 +#define bfd_mach_sh2a_or_sh3e 0x2a4 +#define bfd_mach_sh2e 0x2e +#define bfd_mach_sh3 0x30 +#define bfd_mach_sh3_nommu 0x31 +#define bfd_mach_sh3_dsp 0x3d +#define bfd_mach_sh3e 0x3e +#define bfd_mach_sh4 0x40 +#define bfd_mach_sh4_nofpu 0x41 +#define bfd_mach_sh4_nommu_nofpu 0x42 +#define bfd_mach_sh4a 0x4a +#define bfd_mach_sh4a_nofpu 0x4b +#define bfd_mach_sh4al_dsp 0x4d +#define bfd_mach_sh5 0x50 + bfd_arch_alpha, /* Dec Alpha */ +#define bfd_mach_alpha_ev4 0x10 +#define bfd_mach_alpha_ev5 0x20 +#define bfd_mach_alpha_ev6 0x30 + bfd_arch_arm, /* Advanced Risc Machines ARM. */ +#define bfd_mach_arm_unknown 0 +#define bfd_mach_arm_2 1 +#define bfd_mach_arm_2a 2 +#define bfd_mach_arm_3 3 +#define bfd_mach_arm_3M 4 +#define bfd_mach_arm_4 5 +#define bfd_mach_arm_4T 6 +#define bfd_mach_arm_5 7 +#define bfd_mach_arm_5T 8 +#define bfd_mach_arm_5TE 9 +#define bfd_mach_arm_XScale 10 +#define bfd_mach_arm_ep9312 11 +#define bfd_mach_arm_iWMMXt 12 +#define bfd_mach_arm_iWMMXt2 13 + bfd_arch_ns32k, /* National Semiconductors ns32000 */ + bfd_arch_w65, /* WDC 65816 */ + bfd_arch_tic30, /* Texas Instruments TMS320C30 */ + bfd_arch_tic4x, /* Texas Instruments TMS320C3X/4X */ +#define bfd_mach_tic3x 30 +#define bfd_mach_tic4x 40 + bfd_arch_tic54x, /* Texas Instruments TMS320C54X */ + bfd_arch_tic80, /* TI TMS320c80 (MVP) */ + bfd_arch_v850, /* NEC V850 */ +#define bfd_mach_v850 1 +#define bfd_mach_v850e 'E' +#define bfd_mach_v850e1 '1' + bfd_arch_arc, /* ARC Cores */ +#define bfd_mach_arc_5 5 +#define bfd_mach_arc_6 6 +#define bfd_mach_arc_7 7 +#define bfd_mach_arc_8 8 + bfd_arch_m32c, /* Renesas M16C/M32C. */ +#define bfd_mach_m16c 0x75 +#define bfd_mach_m32c 0x78 + bfd_arch_m32r, /* Renesas M32R (formerly Mitsubishi M32R/D) */ +#define bfd_mach_m32r 1 /* For backwards compatibility. */ +#define bfd_mach_m32rx 'x' +#define bfd_mach_m32r2 '2' + bfd_arch_mn10200, /* Matsushita MN10200 */ + bfd_arch_mn10300, /* Matsushita MN10300 */ +#define bfd_mach_mn10300 300 +#define bfd_mach_am33 330 +#define bfd_mach_am33_2 332 + bfd_arch_fr30, +#define bfd_mach_fr30 0x46523330 + bfd_arch_frv, +#define bfd_mach_frv 1 +#define bfd_mach_frvsimple 2 +#define bfd_mach_fr300 300 +#define bfd_mach_fr400 400 +#define bfd_mach_fr450 450 +#define bfd_mach_frvtomcat 499 /* fr500 prototype */ +#define bfd_mach_fr500 500 +#define bfd_mach_fr550 550 + bfd_arch_mcore, + bfd_arch_mep, +#define bfd_mach_mep 1 +#define bfd_mach_mep_h1 0x6831 + bfd_arch_ia64, /* HP/Intel ia64 */ +#define bfd_mach_ia64_elf64 64 +#define bfd_mach_ia64_elf32 32 + bfd_arch_ip2k, /* Ubicom IP2K microcontrollers. */ +#define bfd_mach_ip2022 1 +#define bfd_mach_ip2022ext 2 + bfd_arch_iq2000, /* Vitesse IQ2000. */ +#define bfd_mach_iq2000 1 +#define bfd_mach_iq10 2 + bfd_arch_mt, +#define bfd_mach_ms1 1 +#define bfd_mach_mrisc2 2 +#define bfd_mach_ms2 3 + bfd_arch_pj, + bfd_arch_avr, /* Atmel AVR microcontrollers. */ +#define bfd_mach_avr1 1 +#define bfd_mach_avr2 2 +#define bfd_mach_avr3 3 +#define bfd_mach_avr4 4 +#define bfd_mach_avr5 5 +#define bfd_mach_avr6 6 + bfd_arch_bfin, /* ADI Blackfin */ +#define bfd_mach_bfin 1 + bfd_arch_cr16, /* National Semiconductor CompactRISC (ie CR16). */ +#define bfd_mach_cr16 1 + bfd_arch_cr16c, /* National Semiconductor CompactRISC. */ +#define bfd_mach_cr16c 1 + bfd_arch_crx, /* National Semiconductor CRX. */ +#define bfd_mach_crx 1 + bfd_arch_cris, /* Axis CRIS */ +#define bfd_mach_cris_v0_v10 255 +#define bfd_mach_cris_v32 32 +#define bfd_mach_cris_v10_v32 1032 + bfd_arch_s390, /* IBM s390 */ +#define bfd_mach_s390_31 31 +#define bfd_mach_s390_64 64 + bfd_arch_score, /* Sunplus score */ + bfd_arch_openrisc, /* OpenRISC */ + bfd_arch_mmix, /* Donald Knuth's educational processor. */ + bfd_arch_xstormy16, +#define bfd_mach_xstormy16 1 + bfd_arch_msp430, /* Texas Instruments MSP430 architecture. */ +#define bfd_mach_msp11 11 +#define bfd_mach_msp110 110 +#define bfd_mach_msp12 12 +#define bfd_mach_msp13 13 +#define bfd_mach_msp14 14 +#define bfd_mach_msp15 15 +#define bfd_mach_msp16 16 +#define bfd_mach_msp21 21 +#define bfd_mach_msp31 31 +#define bfd_mach_msp32 32 +#define bfd_mach_msp33 33 +#define bfd_mach_msp41 41 +#define bfd_mach_msp42 42 +#define bfd_mach_msp43 43 +#define bfd_mach_msp44 44 + bfd_arch_xc16x, /* Infineon's XC16X Series. */ +#define bfd_mach_xc16x 1 +#define bfd_mach_xc16xl 2 +#define bfd_mach_xc16xs 3 + bfd_arch_xtensa, /* Tensilica's Xtensa cores. */ +#define bfd_mach_xtensa 1 + bfd_arch_maxq, /* Dallas MAXQ 10/20 */ +#define bfd_mach_maxq10 10 +#define bfd_mach_maxq20 20 + bfd_arch_z80, +#define bfd_mach_z80strict 1 /* No undocumented opcodes. */ +#define bfd_mach_z80 3 /* With ixl, ixh, iyl, and iyh. */ +#define bfd_mach_z80full 7 /* All undocumented instructions. */ +#define bfd_mach_r800 11 /* R800: successor with multiplication. */ + bfd_arch_last + }; + +typedef struct bfd_arch_info +{ + int bits_per_word; + int bits_per_address; + int bits_per_byte; + enum bfd_architecture arch; + unsigned long mach; + const char *arch_name; + const char *printable_name; + unsigned int section_align_power; + /* TRUE if this is the default machine for the architecture. + The default arch should be the first entry for an arch so that + all the entries for that arch can be accessed via <>. */ + bfd_boolean the_default; + const struct bfd_arch_info * (*compatible) + (const struct bfd_arch_info *a, const struct bfd_arch_info *b); + + bfd_boolean (*scan) (const struct bfd_arch_info *, const char *); + + const struct bfd_arch_info *next; +} +bfd_arch_info_type; + +const char *bfd_printable_name (bfd *abfd); + +const bfd_arch_info_type *bfd_scan_arch (const char *string); + +const char **bfd_arch_list (void); + +const bfd_arch_info_type *bfd_arch_get_compatible + (const bfd *abfd, const bfd *bbfd, bfd_boolean accept_unknowns); + +void bfd_set_arch_info (bfd *abfd, const bfd_arch_info_type *arg); + +enum bfd_architecture bfd_get_arch (bfd *abfd); + +unsigned long bfd_get_mach (bfd *abfd); + +unsigned int bfd_arch_bits_per_byte (bfd *abfd); + +unsigned int bfd_arch_bits_per_address (bfd *abfd); + +const bfd_arch_info_type *bfd_get_arch_info (bfd *abfd); + +const bfd_arch_info_type *bfd_lookup_arch + (enum bfd_architecture arch, unsigned long machine); + +const char *bfd_printable_arch_mach + (enum bfd_architecture arch, unsigned long machine); + +unsigned int bfd_octets_per_byte (bfd *abfd); + +unsigned int bfd_arch_mach_octets_per_byte + (enum bfd_architecture arch, unsigned long machine); + +/* Extracted from reloc.c. */ +typedef enum bfd_reloc_status +{ + /* No errors detected. */ + bfd_reloc_ok, + + /* The relocation was performed, but there was an overflow. */ + bfd_reloc_overflow, + + /* The address to relocate was not within the section supplied. */ + bfd_reloc_outofrange, + + /* Used by special functions. */ + bfd_reloc_continue, + + /* Unsupported relocation size requested. */ + bfd_reloc_notsupported, + + /* Unused. */ + bfd_reloc_other, + + /* The symbol to relocate against was undefined. */ + bfd_reloc_undefined, + + /* The relocation was performed, but may not be ok - presently + generated only when linking i960 coff files with i960 b.out + symbols. If this type is returned, the error_message argument + to bfd_perform_relocation will be set. */ + bfd_reloc_dangerous + } + bfd_reloc_status_type; + + +typedef struct reloc_cache_entry +{ + /* A pointer into the canonical table of pointers. */ + struct bfd_symbol **sym_ptr_ptr; + + /* offset in section. */ + bfd_size_type address; + + /* addend for relocation value. */ + bfd_vma addend; + + /* Pointer to how to perform the required relocation. */ + reloc_howto_type *howto; + +} +arelent; + +enum complain_overflow +{ + /* Do not complain on overflow. */ + complain_overflow_dont, + + /* Complain if the value overflows when considered as a signed + number one bit larger than the field. ie. A bitfield of N bits + is allowed to represent -2**n to 2**n-1. */ + complain_overflow_bitfield, + + /* Complain if the value overflows when considered as a signed + number. */ + complain_overflow_signed, + + /* Complain if the value overflows when considered as an + unsigned number. */ + complain_overflow_unsigned +}; + +struct reloc_howto_struct +{ + /* The type field has mainly a documentary use - the back end can + do what it wants with it, though normally the back end's + external idea of what a reloc number is stored + in this field. For example, a PC relative word relocation + in a coff environment has the type 023 - because that's + what the outside world calls a R_PCRWORD reloc. */ + unsigned int type; + + /* The value the final relocation is shifted right by. This drops + unwanted data from the relocation. */ + unsigned int rightshift; + + /* The size of the item to be relocated. This is *not* a + power-of-two measure. To get the number of bytes operated + on by a type of relocation, use bfd_get_reloc_size. */ + int size; + + /* The number of bits in the item to be relocated. This is used + when doing overflow checking. */ + unsigned int bitsize; + + /* Notes that the relocation is relative to the location in the + data section of the addend. The relocation function will + subtract from the relocation value the address of the location + being relocated. */ + bfd_boolean pc_relative; + + /* The bit position of the reloc value in the destination. + The relocated value is left shifted by this amount. */ + unsigned int bitpos; + + /* What type of overflow error should be checked for when + relocating. */ + enum complain_overflow complain_on_overflow; + + /* If this field is non null, then the supplied function is + called rather than the normal function. This allows really + strange relocation methods to be accommodated (e.g., i960 callj + instructions). */ + bfd_reloc_status_type (*special_function) + (bfd *, arelent *, struct bfd_symbol *, void *, asection *, + bfd *, char **); + + /* The textual name of the relocation type. */ + char *name; + + /* Some formats record a relocation addend in the section contents + rather than with the relocation. For ELF formats this is the + distinction between USE_REL and USE_RELA (though the code checks + for USE_REL == 1/0). The value of this field is TRUE if the + addend is recorded with the section contents; when performing a + partial link (ld -r) the section contents (the data) will be + modified. The value of this field is FALSE if addends are + recorded with the relocation (in arelent.addend); when performing + a partial link the relocation will be modified. + All relocations for all ELF USE_RELA targets should set this field + to FALSE (values of TRUE should be looked on with suspicion). + However, the converse is not true: not all relocations of all ELF + USE_REL targets set this field to TRUE. Why this is so is peculiar + to each particular target. For relocs that aren't used in partial + links (e.g. GOT stuff) it doesn't matter what this is set to. */ + bfd_boolean partial_inplace; + + /* src_mask selects the part of the instruction (or data) to be used + in the relocation sum. If the target relocations don't have an + addend in the reloc, eg. ELF USE_REL, src_mask will normally equal + dst_mask to extract the addend from the section contents. If + relocations do have an addend in the reloc, eg. ELF USE_RELA, this + field should be zero. Non-zero values for ELF USE_RELA targets are + bogus as in those cases the value in the dst_mask part of the + section contents should be treated as garbage. */ + bfd_vma src_mask; + + /* dst_mask selects which parts of the instruction (or data) are + replaced with a relocated value. */ + bfd_vma dst_mask; + + /* When some formats create PC relative instructions, they leave + the value of the pc of the place being relocated in the offset + slot of the instruction, so that a PC relative relocation can + be made just by adding in an ordinary offset (e.g., sun3 a.out). + Some formats leave the displacement part of an instruction + empty (e.g., m88k bcs); this flag signals the fact. */ + bfd_boolean pcrel_offset; +}; + +#define HOWTO(C, R, S, B, P, BI, O, SF, NAME, INPLACE, MASKSRC, MASKDST, PC) \ + { (unsigned) C, R, S, B, P, BI, O, SF, NAME, INPLACE, MASKSRC, MASKDST, PC } +#define NEWHOWTO(FUNCTION, NAME, SIZE, REL, IN) \ + HOWTO (0, 0, SIZE, 0, REL, 0, complain_overflow_dont, FUNCTION, \ + NAME, FALSE, 0, 0, IN) + +#define EMPTY_HOWTO(C) \ + HOWTO ((C), 0, 0, 0, FALSE, 0, complain_overflow_dont, NULL, \ + NULL, FALSE, 0, 0, FALSE) + +#define HOWTO_PREPARE(relocation, symbol) \ + { \ + if (symbol != NULL) \ + { \ + if (bfd_is_com_section (symbol->section)) \ + { \ + relocation = 0; \ + } \ + else \ + { \ + relocation = symbol->value; \ + } \ + } \ + } + +unsigned int bfd_get_reloc_size (reloc_howto_type *); + +typedef struct relent_chain +{ + arelent relent; + struct relent_chain *next; +} +arelent_chain; + +bfd_reloc_status_type bfd_check_overflow + (enum complain_overflow how, + unsigned int bitsize, + unsigned int rightshift, + unsigned int addrsize, + bfd_vma relocation); + +bfd_reloc_status_type bfd_perform_relocation + (bfd *abfd, + arelent *reloc_entry, + void *data, + asection *input_section, + bfd *output_bfd, + char **error_message); + +bfd_reloc_status_type bfd_install_relocation + (bfd *abfd, + arelent *reloc_entry, + void *data, bfd_vma data_start, + asection *input_section, + char **error_message); + +enum bfd_reloc_code_real { + _dummy_first_bfd_reloc_code_real, + + +/* Basic absolute relocations of N bits. */ + BFD_RELOC_64, + BFD_RELOC_32, + BFD_RELOC_26, + BFD_RELOC_24, + BFD_RELOC_16, + BFD_RELOC_14, + BFD_RELOC_8, + +/* PC-relative relocations. Sometimes these are relative to the address +of the relocation itself; sometimes they are relative to the start of +the section containing the relocation. It depends on the specific target. + +The 24-bit relocation is used in some Intel 960 configurations. */ + BFD_RELOC_64_PCREL, + BFD_RELOC_32_PCREL, + BFD_RELOC_24_PCREL, + BFD_RELOC_16_PCREL, + BFD_RELOC_12_PCREL, + BFD_RELOC_8_PCREL, + +/* Section relative relocations. Some targets need this for DWARF2. */ + BFD_RELOC_32_SECREL, + +/* For ELF. */ + BFD_RELOC_32_GOT_PCREL, + BFD_RELOC_16_GOT_PCREL, + BFD_RELOC_8_GOT_PCREL, + BFD_RELOC_32_GOTOFF, + BFD_RELOC_16_GOTOFF, + BFD_RELOC_LO16_GOTOFF, + BFD_RELOC_HI16_GOTOFF, + BFD_RELOC_HI16_S_GOTOFF, + BFD_RELOC_8_GOTOFF, + BFD_RELOC_64_PLT_PCREL, + BFD_RELOC_32_PLT_PCREL, + BFD_RELOC_24_PLT_PCREL, + BFD_RELOC_16_PLT_PCREL, + BFD_RELOC_8_PLT_PCREL, + BFD_RELOC_64_PLTOFF, + BFD_RELOC_32_PLTOFF, + BFD_RELOC_16_PLTOFF, + BFD_RELOC_LO16_PLTOFF, + BFD_RELOC_HI16_PLTOFF, + BFD_RELOC_HI16_S_PLTOFF, + BFD_RELOC_8_PLTOFF, + +/* Relocations used by 68K ELF. */ + BFD_RELOC_68K_GLOB_DAT, + BFD_RELOC_68K_JMP_SLOT, + BFD_RELOC_68K_RELATIVE, + +/* Linkage-table relative. */ + BFD_RELOC_32_BASEREL, + BFD_RELOC_16_BASEREL, + BFD_RELOC_LO16_BASEREL, + BFD_RELOC_HI16_BASEREL, + BFD_RELOC_HI16_S_BASEREL, + BFD_RELOC_8_BASEREL, + BFD_RELOC_RVA, + +/* Absolute 8-bit relocation, but used to form an address like 0xFFnn. */ + BFD_RELOC_8_FFnn, + +/* These PC-relative relocations are stored as word displacements -- +i.e., byte displacements shifted right two bits. The 30-bit word +displacement (<<32_PCREL_S2>> -- 32 bits, shifted 2) is used on the +SPARC. (SPARC tools generally refer to this as <>.) The +signed 16-bit displacement is used on the MIPS, and the 23-bit +displacement is used on the Alpha. */ + BFD_RELOC_32_PCREL_S2, + BFD_RELOC_16_PCREL_S2, + BFD_RELOC_23_PCREL_S2, + +/* High 22 bits and low 10 bits of 32-bit value, placed into lower bits of +the target word. These are used on the SPARC. */ + BFD_RELOC_HI22, + BFD_RELOC_LO10, + +/* For systems that allocate a Global Pointer register, these are +displacements off that register. These relocation types are +handled specially, because the value the register will have is +decided relatively late. */ + BFD_RELOC_GPREL16, + BFD_RELOC_GPREL32, + +/* Reloc types used for i960/b.out. */ + BFD_RELOC_I960_CALLJ, + +/* SPARC ELF relocations. There is probably some overlap with other +relocation types already defined. */ + BFD_RELOC_NONE, + BFD_RELOC_SPARC_WDISP22, + BFD_RELOC_SPARC22, + BFD_RELOC_SPARC13, + BFD_RELOC_SPARC_GOT10, + BFD_RELOC_SPARC_GOT13, + BFD_RELOC_SPARC_GOT22, + BFD_RELOC_SPARC_PC10, + BFD_RELOC_SPARC_PC22, + BFD_RELOC_SPARC_WPLT30, + BFD_RELOC_SPARC_COPY, + BFD_RELOC_SPARC_GLOB_DAT, + BFD_RELOC_SPARC_JMP_SLOT, + BFD_RELOC_SPARC_RELATIVE, + BFD_RELOC_SPARC_UA16, + BFD_RELOC_SPARC_UA32, + BFD_RELOC_SPARC_UA64, + +/* I think these are specific to SPARC a.out (e.g., Sun 4). */ + BFD_RELOC_SPARC_BASE13, + BFD_RELOC_SPARC_BASE22, + +/* SPARC64 relocations */ +#define BFD_RELOC_SPARC_64 BFD_RELOC_64 + BFD_RELOC_SPARC_10, + BFD_RELOC_SPARC_11, + BFD_RELOC_SPARC_OLO10, + BFD_RELOC_SPARC_HH22, + BFD_RELOC_SPARC_HM10, + BFD_RELOC_SPARC_LM22, + BFD_RELOC_SPARC_PC_HH22, + BFD_RELOC_SPARC_PC_HM10, + BFD_RELOC_SPARC_PC_LM22, + BFD_RELOC_SPARC_WDISP16, + BFD_RELOC_SPARC_WDISP19, + BFD_RELOC_SPARC_7, + BFD_RELOC_SPARC_6, + BFD_RELOC_SPARC_5, +#define BFD_RELOC_SPARC_DISP64 BFD_RELOC_64_PCREL + BFD_RELOC_SPARC_PLT32, + BFD_RELOC_SPARC_PLT64, + BFD_RELOC_SPARC_HIX22, + BFD_RELOC_SPARC_LOX10, + BFD_RELOC_SPARC_H44, + BFD_RELOC_SPARC_M44, + BFD_RELOC_SPARC_L44, + BFD_RELOC_SPARC_REGISTER, + +/* SPARC little endian relocation */ + BFD_RELOC_SPARC_REV32, + +/* SPARC TLS relocations */ + BFD_RELOC_SPARC_TLS_GD_HI22, + BFD_RELOC_SPARC_TLS_GD_LO10, + BFD_RELOC_SPARC_TLS_GD_ADD, + BFD_RELOC_SPARC_TLS_GD_CALL, + BFD_RELOC_SPARC_TLS_LDM_HI22, + BFD_RELOC_SPARC_TLS_LDM_LO10, + BFD_RELOC_SPARC_TLS_LDM_ADD, + BFD_RELOC_SPARC_TLS_LDM_CALL, + BFD_RELOC_SPARC_TLS_LDO_HIX22, + BFD_RELOC_SPARC_TLS_LDO_LOX10, + BFD_RELOC_SPARC_TLS_LDO_ADD, + BFD_RELOC_SPARC_TLS_IE_HI22, + BFD_RELOC_SPARC_TLS_IE_LO10, + BFD_RELOC_SPARC_TLS_IE_LD, + BFD_RELOC_SPARC_TLS_IE_LDX, + BFD_RELOC_SPARC_TLS_IE_ADD, + BFD_RELOC_SPARC_TLS_LE_HIX22, + BFD_RELOC_SPARC_TLS_LE_LOX10, + BFD_RELOC_SPARC_TLS_DTPMOD32, + BFD_RELOC_SPARC_TLS_DTPMOD64, + BFD_RELOC_SPARC_TLS_DTPOFF32, + BFD_RELOC_SPARC_TLS_DTPOFF64, + BFD_RELOC_SPARC_TLS_TPOFF32, + BFD_RELOC_SPARC_TLS_TPOFF64, + +/* SPU Relocations. */ + BFD_RELOC_SPU_IMM7, + BFD_RELOC_SPU_IMM8, + BFD_RELOC_SPU_IMM10, + BFD_RELOC_SPU_IMM10W, + BFD_RELOC_SPU_IMM16, + BFD_RELOC_SPU_IMM16W, + BFD_RELOC_SPU_IMM18, + BFD_RELOC_SPU_PCREL9a, + BFD_RELOC_SPU_PCREL9b, + BFD_RELOC_SPU_PCREL16, + BFD_RELOC_SPU_LO16, + BFD_RELOC_SPU_HI16, + BFD_RELOC_SPU_PPU32, + BFD_RELOC_SPU_PPU64, + +/* Alpha ECOFF and ELF relocations. Some of these treat the symbol or +"addend" in some special way. +For GPDISP_HI16 ("gpdisp") relocations, the symbol is ignored when +writing; when reading, it will be the absolute section symbol. The +addend is the displacement in bytes of the "lda" instruction from +the "ldah" instruction (which is at the address of this reloc). */ + BFD_RELOC_ALPHA_GPDISP_HI16, + +/* For GPDISP_LO16 ("ignore") relocations, the symbol is handled as +with GPDISP_HI16 relocs. The addend is ignored when writing the +relocations out, and is filled in with the file's GP value on +reading, for convenience. */ + BFD_RELOC_ALPHA_GPDISP_LO16, + +/* The ELF GPDISP relocation is exactly the same as the GPDISP_HI16 +relocation except that there is no accompanying GPDISP_LO16 +relocation. */ + BFD_RELOC_ALPHA_GPDISP, + +/* The Alpha LITERAL/LITUSE relocs are produced by a symbol reference; +the assembler turns it into a LDQ instruction to load the address of +the symbol, and then fills in a register in the real instruction. + +The LITERAL reloc, at the LDQ instruction, refers to the .lita +section symbol. The addend is ignored when writing, but is filled +in with the file's GP value on reading, for convenience, as with the +GPDISP_LO16 reloc. + +The ELF_LITERAL reloc is somewhere between 16_GOTOFF and GPDISP_LO16. +It should refer to the symbol to be referenced, as with 16_GOTOFF, +but it generates output not based on the position within the .got +section, but relative to the GP value chosen for the file during the +final link stage. + +The LITUSE reloc, on the instruction using the loaded address, gives +information to the linker that it might be able to use to optimize +away some literal section references. The symbol is ignored (read +as the absolute section symbol), and the "addend" indicates the type +of instruction using the register: +1 - "memory" fmt insn +2 - byte-manipulation (byte offset reg) +3 - jsr (target of branch) */ + BFD_RELOC_ALPHA_LITERAL, + BFD_RELOC_ALPHA_ELF_LITERAL, + BFD_RELOC_ALPHA_LITUSE, + +/* The HINT relocation indicates a value that should be filled into the +"hint" field of a jmp/jsr/ret instruction, for possible branch- +prediction logic which may be provided on some processors. */ + BFD_RELOC_ALPHA_HINT, + +/* The LINKAGE relocation outputs a linkage pair in the object file, +which is filled by the linker. */ + BFD_RELOC_ALPHA_LINKAGE, + +/* The CODEADDR relocation outputs a STO_CA in the object file, +which is filled by the linker. */ + BFD_RELOC_ALPHA_CODEADDR, + +/* The GPREL_HI/LO relocations together form a 32-bit offset from the +GP register. */ + BFD_RELOC_ALPHA_GPREL_HI16, + BFD_RELOC_ALPHA_GPREL_LO16, + +/* Like BFD_RELOC_23_PCREL_S2, except that the source and target must +share a common GP, and the target address is adjusted for +STO_ALPHA_STD_GPLOAD. */ + BFD_RELOC_ALPHA_BRSGP, + +/* Alpha thread-local storage relocations. */ + BFD_RELOC_ALPHA_TLSGD, + BFD_RELOC_ALPHA_TLSLDM, + BFD_RELOC_ALPHA_DTPMOD64, + BFD_RELOC_ALPHA_GOTDTPREL16, + BFD_RELOC_ALPHA_DTPREL64, + BFD_RELOC_ALPHA_DTPREL_HI16, + BFD_RELOC_ALPHA_DTPREL_LO16, + BFD_RELOC_ALPHA_DTPREL16, + BFD_RELOC_ALPHA_GOTTPREL16, + BFD_RELOC_ALPHA_TPREL64, + BFD_RELOC_ALPHA_TPREL_HI16, + BFD_RELOC_ALPHA_TPREL_LO16, + BFD_RELOC_ALPHA_TPREL16, + +/* Bits 27..2 of the relocation address shifted right 2 bits; +simple reloc otherwise. */ + BFD_RELOC_MIPS_JMP, + +/* The MIPS16 jump instruction. */ + BFD_RELOC_MIPS16_JMP, + +/* MIPS16 GP relative reloc. */ + BFD_RELOC_MIPS16_GPREL, + +/* High 16 bits of 32-bit value; simple reloc. */ + BFD_RELOC_HI16, + +/* High 16 bits of 32-bit value but the low 16 bits will be sign +extended and added to form the final result. If the low 16 +bits form a negative number, we need to add one to the high value +to compensate for the borrow when the low bits are added. */ + BFD_RELOC_HI16_S, + +/* Low 16 bits. */ + BFD_RELOC_LO16, + +/* High 16 bits of 32-bit pc-relative value */ + BFD_RELOC_HI16_PCREL, + +/* High 16 bits of 32-bit pc-relative value, adjusted */ + BFD_RELOC_HI16_S_PCREL, + +/* Low 16 bits of pc-relative value */ + BFD_RELOC_LO16_PCREL, + +/* MIPS16 high 16 bits of 32-bit value. */ + BFD_RELOC_MIPS16_HI16, + +/* MIPS16 high 16 bits of 32-bit value but the low 16 bits will be sign +extended and added to form the final result. If the low 16 +bits form a negative number, we need to add one to the high value +to compensate for the borrow when the low bits are added. */ + BFD_RELOC_MIPS16_HI16_S, + +/* MIPS16 low 16 bits. */ + BFD_RELOC_MIPS16_LO16, + +/* Relocation against a MIPS literal section. */ + BFD_RELOC_MIPS_LITERAL, + +/* MIPS ELF relocations. */ + BFD_RELOC_MIPS_GOT16, + BFD_RELOC_MIPS_CALL16, + BFD_RELOC_MIPS_GOT_HI16, + BFD_RELOC_MIPS_GOT_LO16, + BFD_RELOC_MIPS_CALL_HI16, + BFD_RELOC_MIPS_CALL_LO16, + BFD_RELOC_MIPS_SUB, + BFD_RELOC_MIPS_GOT_PAGE, + BFD_RELOC_MIPS_GOT_OFST, + BFD_RELOC_MIPS_GOT_DISP, + BFD_RELOC_MIPS_SHIFT5, + BFD_RELOC_MIPS_SHIFT6, + BFD_RELOC_MIPS_INSERT_A, + BFD_RELOC_MIPS_INSERT_B, + BFD_RELOC_MIPS_DELETE, + BFD_RELOC_MIPS_HIGHEST, + BFD_RELOC_MIPS_HIGHER, + BFD_RELOC_MIPS_SCN_DISP, + BFD_RELOC_MIPS_REL16, + BFD_RELOC_MIPS_RELGOT, + BFD_RELOC_MIPS_JALR, + BFD_RELOC_MIPS_TLS_DTPMOD32, + BFD_RELOC_MIPS_TLS_DTPREL32, + BFD_RELOC_MIPS_TLS_DTPMOD64, + BFD_RELOC_MIPS_TLS_DTPREL64, + BFD_RELOC_MIPS_TLS_GD, + BFD_RELOC_MIPS_TLS_LDM, + BFD_RELOC_MIPS_TLS_DTPREL_HI16, + BFD_RELOC_MIPS_TLS_DTPREL_LO16, + BFD_RELOC_MIPS_TLS_GOTTPREL, + BFD_RELOC_MIPS_TLS_TPREL32, + BFD_RELOC_MIPS_TLS_TPREL64, + BFD_RELOC_MIPS_TLS_TPREL_HI16, + BFD_RELOC_MIPS_TLS_TPREL_LO16, + + +/* MIPS ELF relocations (VxWorks extensions). */ + BFD_RELOC_MIPS_COPY, + BFD_RELOC_MIPS_JUMP_SLOT, + + +/* Fujitsu Frv Relocations. */ + BFD_RELOC_FRV_LABEL16, + BFD_RELOC_FRV_LABEL24, + BFD_RELOC_FRV_LO16, + BFD_RELOC_FRV_HI16, + BFD_RELOC_FRV_GPREL12, + BFD_RELOC_FRV_GPRELU12, + BFD_RELOC_FRV_GPREL32, + BFD_RELOC_FRV_GPRELHI, + BFD_RELOC_FRV_GPRELLO, + BFD_RELOC_FRV_GOT12, + BFD_RELOC_FRV_GOTHI, + BFD_RELOC_FRV_GOTLO, + BFD_RELOC_FRV_FUNCDESC, + BFD_RELOC_FRV_FUNCDESC_GOT12, + BFD_RELOC_FRV_FUNCDESC_GOTHI, + BFD_RELOC_FRV_FUNCDESC_GOTLO, + BFD_RELOC_FRV_FUNCDESC_VALUE, + BFD_RELOC_FRV_FUNCDESC_GOTOFF12, + BFD_RELOC_FRV_FUNCDESC_GOTOFFHI, + BFD_RELOC_FRV_FUNCDESC_GOTOFFLO, + BFD_RELOC_FRV_GOTOFF12, + BFD_RELOC_FRV_GOTOFFHI, + BFD_RELOC_FRV_GOTOFFLO, + BFD_RELOC_FRV_GETTLSOFF, + BFD_RELOC_FRV_TLSDESC_VALUE, + BFD_RELOC_FRV_GOTTLSDESC12, + BFD_RELOC_FRV_GOTTLSDESCHI, + BFD_RELOC_FRV_GOTTLSDESCLO, + BFD_RELOC_FRV_TLSMOFF12, + BFD_RELOC_FRV_TLSMOFFHI, + BFD_RELOC_FRV_TLSMOFFLO, + BFD_RELOC_FRV_GOTTLSOFF12, + BFD_RELOC_FRV_GOTTLSOFFHI, + BFD_RELOC_FRV_GOTTLSOFFLO, + BFD_RELOC_FRV_TLSOFF, + BFD_RELOC_FRV_TLSDESC_RELAX, + BFD_RELOC_FRV_GETTLSOFF_RELAX, + BFD_RELOC_FRV_TLSOFF_RELAX, + BFD_RELOC_FRV_TLSMOFF, + + +/* This is a 24bit GOT-relative reloc for the mn10300. */ + BFD_RELOC_MN10300_GOTOFF24, + +/* This is a 32bit GOT-relative reloc for the mn10300, offset by two bytes +in the instruction. */ + BFD_RELOC_MN10300_GOT32, + +/* This is a 24bit GOT-relative reloc for the mn10300, offset by two bytes +in the instruction. */ + BFD_RELOC_MN10300_GOT24, + +/* This is a 16bit GOT-relative reloc for the mn10300, offset by two bytes +in the instruction. */ + BFD_RELOC_MN10300_GOT16, + +/* Copy symbol at runtime. */ + BFD_RELOC_MN10300_COPY, + +/* Create GOT entry. */ + BFD_RELOC_MN10300_GLOB_DAT, + +/* Create PLT entry. */ + BFD_RELOC_MN10300_JMP_SLOT, + +/* Adjust by program base. */ + BFD_RELOC_MN10300_RELATIVE, + + +/* i386/elf relocations */ + BFD_RELOC_386_GOT32, + BFD_RELOC_386_PLT32, + BFD_RELOC_386_COPY, + BFD_RELOC_386_GLOB_DAT, + BFD_RELOC_386_JUMP_SLOT, + BFD_RELOC_386_RELATIVE, + BFD_RELOC_386_GOTOFF, + BFD_RELOC_386_GOTPC, + BFD_RELOC_386_TLS_TPOFF, + BFD_RELOC_386_TLS_IE, + BFD_RELOC_386_TLS_GOTIE, + BFD_RELOC_386_TLS_LE, + BFD_RELOC_386_TLS_GD, + BFD_RELOC_386_TLS_LDM, + BFD_RELOC_386_TLS_LDO_32, + BFD_RELOC_386_TLS_IE_32, + BFD_RELOC_386_TLS_LE_32, + BFD_RELOC_386_TLS_DTPMOD32, + BFD_RELOC_386_TLS_DTPOFF32, + BFD_RELOC_386_TLS_TPOFF32, + BFD_RELOC_386_TLS_GOTDESC, + BFD_RELOC_386_TLS_DESC_CALL, + BFD_RELOC_386_TLS_DESC, + +/* x86-64/elf relocations */ + BFD_RELOC_X86_64_GOT32, + BFD_RELOC_X86_64_PLT32, + BFD_RELOC_X86_64_COPY, + BFD_RELOC_X86_64_GLOB_DAT, + BFD_RELOC_X86_64_JUMP_SLOT, + BFD_RELOC_X86_64_RELATIVE, + BFD_RELOC_X86_64_GOTPCREL, + BFD_RELOC_X86_64_32S, + BFD_RELOC_X86_64_DTPMOD64, + BFD_RELOC_X86_64_DTPOFF64, + BFD_RELOC_X86_64_TPOFF64, + BFD_RELOC_X86_64_TLSGD, + BFD_RELOC_X86_64_TLSLD, + BFD_RELOC_X86_64_DTPOFF32, + BFD_RELOC_X86_64_GOTTPOFF, + BFD_RELOC_X86_64_TPOFF32, + BFD_RELOC_X86_64_GOTOFF64, + BFD_RELOC_X86_64_GOTPC32, + BFD_RELOC_X86_64_GOT64, + BFD_RELOC_X86_64_GOTPCREL64, + BFD_RELOC_X86_64_GOTPC64, + BFD_RELOC_X86_64_GOTPLT64, + BFD_RELOC_X86_64_PLTOFF64, + BFD_RELOC_X86_64_GOTPC32_TLSDESC, + BFD_RELOC_X86_64_TLSDESC_CALL, + BFD_RELOC_X86_64_TLSDESC, + +/* ns32k relocations */ + BFD_RELOC_NS32K_IMM_8, + BFD_RELOC_NS32K_IMM_16, + BFD_RELOC_NS32K_IMM_32, + BFD_RELOC_NS32K_IMM_8_PCREL, + BFD_RELOC_NS32K_IMM_16_PCREL, + BFD_RELOC_NS32K_IMM_32_PCREL, + BFD_RELOC_NS32K_DISP_8, + BFD_RELOC_NS32K_DISP_16, + BFD_RELOC_NS32K_DISP_32, + BFD_RELOC_NS32K_DISP_8_PCREL, + BFD_RELOC_NS32K_DISP_16_PCREL, + BFD_RELOC_NS32K_DISP_32_PCREL, + +/* PDP11 relocations */ + BFD_RELOC_PDP11_DISP_8_PCREL, + BFD_RELOC_PDP11_DISP_6_PCREL, + +/* Picojava relocs. Not all of these appear in object files. */ + BFD_RELOC_PJ_CODE_HI16, + BFD_RELOC_PJ_CODE_LO16, + BFD_RELOC_PJ_CODE_DIR16, + BFD_RELOC_PJ_CODE_DIR32, + BFD_RELOC_PJ_CODE_REL16, + BFD_RELOC_PJ_CODE_REL32, + +/* Power(rs6000) and PowerPC relocations. */ + BFD_RELOC_PPC_B26, + BFD_RELOC_PPC_BA26, + BFD_RELOC_PPC_TOC16, + BFD_RELOC_PPC_B16, + BFD_RELOC_PPC_B16_BRTAKEN, + BFD_RELOC_PPC_B16_BRNTAKEN, + BFD_RELOC_PPC_BA16, + BFD_RELOC_PPC_BA16_BRTAKEN, + BFD_RELOC_PPC_BA16_BRNTAKEN, + BFD_RELOC_PPC_COPY, + BFD_RELOC_PPC_GLOB_DAT, + BFD_RELOC_PPC_JMP_SLOT, + BFD_RELOC_PPC_RELATIVE, + BFD_RELOC_PPC_LOCAL24PC, + BFD_RELOC_PPC_EMB_NADDR32, + BFD_RELOC_PPC_EMB_NADDR16, + BFD_RELOC_PPC_EMB_NADDR16_LO, + BFD_RELOC_PPC_EMB_NADDR16_HI, + BFD_RELOC_PPC_EMB_NADDR16_HA, + BFD_RELOC_PPC_EMB_SDAI16, + BFD_RELOC_PPC_EMB_SDA2I16, + BFD_RELOC_PPC_EMB_SDA2REL, + BFD_RELOC_PPC_EMB_SDA21, + BFD_RELOC_PPC_EMB_MRKREF, + BFD_RELOC_PPC_EMB_RELSEC16, + BFD_RELOC_PPC_EMB_RELST_LO, + BFD_RELOC_PPC_EMB_RELST_HI, + BFD_RELOC_PPC_EMB_RELST_HA, + BFD_RELOC_PPC_EMB_BIT_FLD, + BFD_RELOC_PPC_EMB_RELSDA, + BFD_RELOC_PPC64_HIGHER, + BFD_RELOC_PPC64_HIGHER_S, + BFD_RELOC_PPC64_HIGHEST, + BFD_RELOC_PPC64_HIGHEST_S, + BFD_RELOC_PPC64_TOC16_LO, + BFD_RELOC_PPC64_TOC16_HI, + BFD_RELOC_PPC64_TOC16_HA, + BFD_RELOC_PPC64_TOC, + BFD_RELOC_PPC64_PLTGOT16, + BFD_RELOC_PPC64_PLTGOT16_LO, + BFD_RELOC_PPC64_PLTGOT16_HI, + BFD_RELOC_PPC64_PLTGOT16_HA, + BFD_RELOC_PPC64_ADDR16_DS, + BFD_RELOC_PPC64_ADDR16_LO_DS, + BFD_RELOC_PPC64_GOT16_DS, + BFD_RELOC_PPC64_GOT16_LO_DS, + BFD_RELOC_PPC64_PLT16_LO_DS, + BFD_RELOC_PPC64_SECTOFF_DS, + BFD_RELOC_PPC64_SECTOFF_LO_DS, + BFD_RELOC_PPC64_TOC16_DS, + BFD_RELOC_PPC64_TOC16_LO_DS, + BFD_RELOC_PPC64_PLTGOT16_DS, + BFD_RELOC_PPC64_PLTGOT16_LO_DS, + +/* PowerPC and PowerPC64 thread-local storage relocations. */ + BFD_RELOC_PPC_TLS, + BFD_RELOC_PPC_DTPMOD, + BFD_RELOC_PPC_TPREL16, + BFD_RELOC_PPC_TPREL16_LO, + BFD_RELOC_PPC_TPREL16_HI, + BFD_RELOC_PPC_TPREL16_HA, + BFD_RELOC_PPC_TPREL, + BFD_RELOC_PPC_DTPREL16, + BFD_RELOC_PPC_DTPREL16_LO, + BFD_RELOC_PPC_DTPREL16_HI, + BFD_RELOC_PPC_DTPREL16_HA, + BFD_RELOC_PPC_DTPREL, + BFD_RELOC_PPC_GOT_TLSGD16, + BFD_RELOC_PPC_GOT_TLSGD16_LO, + BFD_RELOC_PPC_GOT_TLSGD16_HI, + BFD_RELOC_PPC_GOT_TLSGD16_HA, + BFD_RELOC_PPC_GOT_TLSLD16, + BFD_RELOC_PPC_GOT_TLSLD16_LO, + BFD_RELOC_PPC_GOT_TLSLD16_HI, + BFD_RELOC_PPC_GOT_TLSLD16_HA, + BFD_RELOC_PPC_GOT_TPREL16, + BFD_RELOC_PPC_GOT_TPREL16_LO, + BFD_RELOC_PPC_GOT_TPREL16_HI, + BFD_RELOC_PPC_GOT_TPREL16_HA, + BFD_RELOC_PPC_GOT_DTPREL16, + BFD_RELOC_PPC_GOT_DTPREL16_LO, + BFD_RELOC_PPC_GOT_DTPREL16_HI, + BFD_RELOC_PPC_GOT_DTPREL16_HA, + BFD_RELOC_PPC64_TPREL16_DS, + BFD_RELOC_PPC64_TPREL16_LO_DS, + BFD_RELOC_PPC64_TPREL16_HIGHER, + BFD_RELOC_PPC64_TPREL16_HIGHERA, + BFD_RELOC_PPC64_TPREL16_HIGHEST, + BFD_RELOC_PPC64_TPREL16_HIGHESTA, + BFD_RELOC_PPC64_DTPREL16_DS, + BFD_RELOC_PPC64_DTPREL16_LO_DS, + BFD_RELOC_PPC64_DTPREL16_HIGHER, + BFD_RELOC_PPC64_DTPREL16_HIGHERA, + BFD_RELOC_PPC64_DTPREL16_HIGHEST, + BFD_RELOC_PPC64_DTPREL16_HIGHESTA, + +/* IBM 370/390 relocations */ + BFD_RELOC_I370_D12, + +/* The type of reloc used to build a constructor table - at the moment +probably a 32 bit wide absolute relocation, but the target can choose. +It generally does map to one of the other relocation types. */ + BFD_RELOC_CTOR, + +/* ARM 26 bit pc-relative branch. The lowest two bits must be zero and are +not stored in the instruction. */ + BFD_RELOC_ARM_PCREL_BRANCH, + +/* ARM 26 bit pc-relative branch. The lowest bit must be zero and is +not stored in the instruction. The 2nd lowest bit comes from a 1 bit +field in the instruction. */ + BFD_RELOC_ARM_PCREL_BLX, + +/* Thumb 22 bit pc-relative branch. The lowest bit must be zero and is +not stored in the instruction. The 2nd lowest bit comes from a 1 bit +field in the instruction. */ + BFD_RELOC_THUMB_PCREL_BLX, + +/* ARM 26-bit pc-relative branch for an unconditional BL or BLX instruction. */ + BFD_RELOC_ARM_PCREL_CALL, + +/* ARM 26-bit pc-relative branch for B or conditional BL instruction. */ + BFD_RELOC_ARM_PCREL_JUMP, + +/* Thumb 7-, 9-, 12-, 20-, 23-, and 25-bit pc-relative branches. +The lowest bit must be zero and is not stored in the instruction. +Note that the corresponding ELF R_ARM_THM_JUMPnn constant has an +"nn" one smaller in all cases. Note further that BRANCH23 +corresponds to R_ARM_THM_CALL. */ + BFD_RELOC_THUMB_PCREL_BRANCH7, + BFD_RELOC_THUMB_PCREL_BRANCH9, + BFD_RELOC_THUMB_PCREL_BRANCH12, + BFD_RELOC_THUMB_PCREL_BRANCH20, + BFD_RELOC_THUMB_PCREL_BRANCH23, + BFD_RELOC_THUMB_PCREL_BRANCH25, + +/* 12-bit immediate offset, used in ARM-format ldr and str instructions. */ + BFD_RELOC_ARM_OFFSET_IMM, + +/* 5-bit immediate offset, used in Thumb-format ldr and str instructions. */ + BFD_RELOC_ARM_THUMB_OFFSET, + +/* Pc-relative or absolute relocation depending on target. Used for +entries in .init_array sections. */ + BFD_RELOC_ARM_TARGET1, + +/* Read-only segment base relative address. */ + BFD_RELOC_ARM_ROSEGREL32, + +/* Data segment base relative address. */ + BFD_RELOC_ARM_SBREL32, + +/* This reloc is used for references to RTTI data from exception handling +tables. The actual definition depends on the target. It may be a +pc-relative or some form of GOT-indirect relocation. */ + BFD_RELOC_ARM_TARGET2, + +/* 31-bit PC relative address. */ + BFD_RELOC_ARM_PREL31, + +/* Low and High halfword relocations for MOVW and MOVT instructions. */ + BFD_RELOC_ARM_MOVW, + BFD_RELOC_ARM_MOVT, + BFD_RELOC_ARM_MOVW_PCREL, + BFD_RELOC_ARM_MOVT_PCREL, + BFD_RELOC_ARM_THUMB_MOVW, + BFD_RELOC_ARM_THUMB_MOVT, + BFD_RELOC_ARM_THUMB_MOVW_PCREL, + BFD_RELOC_ARM_THUMB_MOVT_PCREL, + +/* Relocations for setting up GOTs and PLTs for shared libraries. */ + BFD_RELOC_ARM_JUMP_SLOT, + BFD_RELOC_ARM_GLOB_DAT, + BFD_RELOC_ARM_GOT32, + BFD_RELOC_ARM_PLT32, + BFD_RELOC_ARM_RELATIVE, + BFD_RELOC_ARM_GOTOFF, + BFD_RELOC_ARM_GOTPC, + +/* ARM thread-local storage relocations. */ + BFD_RELOC_ARM_TLS_GD32, + BFD_RELOC_ARM_TLS_LDO32, + BFD_RELOC_ARM_TLS_LDM32, + BFD_RELOC_ARM_TLS_DTPOFF32, + BFD_RELOC_ARM_TLS_DTPMOD32, + BFD_RELOC_ARM_TLS_TPOFF32, + BFD_RELOC_ARM_TLS_IE32, + BFD_RELOC_ARM_TLS_LE32, + +/* ARM group relocations. */ + BFD_RELOC_ARM_ALU_PC_G0_NC, + BFD_RELOC_ARM_ALU_PC_G0, + BFD_RELOC_ARM_ALU_PC_G1_NC, + BFD_RELOC_ARM_ALU_PC_G1, + BFD_RELOC_ARM_ALU_PC_G2, + BFD_RELOC_ARM_LDR_PC_G0, + BFD_RELOC_ARM_LDR_PC_G1, + BFD_RELOC_ARM_LDR_PC_G2, + BFD_RELOC_ARM_LDRS_PC_G0, + BFD_RELOC_ARM_LDRS_PC_G1, + BFD_RELOC_ARM_LDRS_PC_G2, + BFD_RELOC_ARM_LDC_PC_G0, + BFD_RELOC_ARM_LDC_PC_G1, + BFD_RELOC_ARM_LDC_PC_G2, + BFD_RELOC_ARM_ALU_SB_G0_NC, + BFD_RELOC_ARM_ALU_SB_G0, + BFD_RELOC_ARM_ALU_SB_G1_NC, + BFD_RELOC_ARM_ALU_SB_G1, + BFD_RELOC_ARM_ALU_SB_G2, + BFD_RELOC_ARM_LDR_SB_G0, + BFD_RELOC_ARM_LDR_SB_G1, + BFD_RELOC_ARM_LDR_SB_G2, + BFD_RELOC_ARM_LDRS_SB_G0, + BFD_RELOC_ARM_LDRS_SB_G1, + BFD_RELOC_ARM_LDRS_SB_G2, + BFD_RELOC_ARM_LDC_SB_G0, + BFD_RELOC_ARM_LDC_SB_G1, + BFD_RELOC_ARM_LDC_SB_G2, + +/* These relocs are only used within the ARM assembler. They are not +(at present) written to any object files. */ + BFD_RELOC_ARM_IMMEDIATE, + BFD_RELOC_ARM_ADRL_IMMEDIATE, + BFD_RELOC_ARM_T32_IMMEDIATE, + BFD_RELOC_ARM_T32_ADD_IMM, + BFD_RELOC_ARM_T32_IMM12, + BFD_RELOC_ARM_T32_ADD_PC12, + BFD_RELOC_ARM_SHIFT_IMM, + BFD_RELOC_ARM_SMC, + BFD_RELOC_ARM_SWI, + BFD_RELOC_ARM_MULTI, + BFD_RELOC_ARM_CP_OFF_IMM, + BFD_RELOC_ARM_CP_OFF_IMM_S2, + BFD_RELOC_ARM_T32_CP_OFF_IMM, + BFD_RELOC_ARM_T32_CP_OFF_IMM_S2, + BFD_RELOC_ARM_ADR_IMM, + BFD_RELOC_ARM_LDR_IMM, + BFD_RELOC_ARM_LITERAL, + BFD_RELOC_ARM_IN_POOL, + BFD_RELOC_ARM_OFFSET_IMM8, + BFD_RELOC_ARM_T32_OFFSET_U8, + BFD_RELOC_ARM_T32_OFFSET_IMM, + BFD_RELOC_ARM_HWLITERAL, + BFD_RELOC_ARM_THUMB_ADD, + BFD_RELOC_ARM_THUMB_IMM, + BFD_RELOC_ARM_THUMB_SHIFT, + +/* Renesas / SuperH SH relocs. Not all of these appear in object files. */ + BFD_RELOC_SH_PCDISP8BY2, + BFD_RELOC_SH_PCDISP12BY2, + BFD_RELOC_SH_IMM3, + BFD_RELOC_SH_IMM3U, + BFD_RELOC_SH_DISP12, + BFD_RELOC_SH_DISP12BY2, + BFD_RELOC_SH_DISP12BY4, + BFD_RELOC_SH_DISP12BY8, + BFD_RELOC_SH_DISP20, + BFD_RELOC_SH_DISP20BY8, + BFD_RELOC_SH_IMM4, + BFD_RELOC_SH_IMM4BY2, + BFD_RELOC_SH_IMM4BY4, + BFD_RELOC_SH_IMM8, + BFD_RELOC_SH_IMM8BY2, + BFD_RELOC_SH_IMM8BY4, + BFD_RELOC_SH_PCRELIMM8BY2, + BFD_RELOC_SH_PCRELIMM8BY4, + BFD_RELOC_SH_SWITCH16, + BFD_RELOC_SH_SWITCH32, + BFD_RELOC_SH_USES, + BFD_RELOC_SH_COUNT, + BFD_RELOC_SH_ALIGN, + BFD_RELOC_SH_CODE, + BFD_RELOC_SH_DATA, + BFD_RELOC_SH_LABEL, + BFD_RELOC_SH_LOOP_START, + BFD_RELOC_SH_LOOP_END, + BFD_RELOC_SH_COPY, + BFD_RELOC_SH_GLOB_DAT, + BFD_RELOC_SH_JMP_SLOT, + BFD_RELOC_SH_RELATIVE, + BFD_RELOC_SH_GOTPC, + BFD_RELOC_SH_GOT_LOW16, + BFD_RELOC_SH_GOT_MEDLOW16, + BFD_RELOC_SH_GOT_MEDHI16, + BFD_RELOC_SH_GOT_HI16, + BFD_RELOC_SH_GOTPLT_LOW16, + BFD_RELOC_SH_GOTPLT_MEDLOW16, + BFD_RELOC_SH_GOTPLT_MEDHI16, + BFD_RELOC_SH_GOTPLT_HI16, + BFD_RELOC_SH_PLT_LOW16, + BFD_RELOC_SH_PLT_MEDLOW16, + BFD_RELOC_SH_PLT_MEDHI16, + BFD_RELOC_SH_PLT_HI16, + BFD_RELOC_SH_GOTOFF_LOW16, + BFD_RELOC_SH_GOTOFF_MEDLOW16, + BFD_RELOC_SH_GOTOFF_MEDHI16, + BFD_RELOC_SH_GOTOFF_HI16, + BFD_RELOC_SH_GOTPC_LOW16, + BFD_RELOC_SH_GOTPC_MEDLOW16, + BFD_RELOC_SH_GOTPC_MEDHI16, + BFD_RELOC_SH_GOTPC_HI16, + BFD_RELOC_SH_COPY64, + BFD_RELOC_SH_GLOB_DAT64, + BFD_RELOC_SH_JMP_SLOT64, + BFD_RELOC_SH_RELATIVE64, + BFD_RELOC_SH_GOT10BY4, + BFD_RELOC_SH_GOT10BY8, + BFD_RELOC_SH_GOTPLT10BY4, + BFD_RELOC_SH_GOTPLT10BY8, + BFD_RELOC_SH_GOTPLT32, + BFD_RELOC_SH_SHMEDIA_CODE, + BFD_RELOC_SH_IMMU5, + BFD_RELOC_SH_IMMS6, + BFD_RELOC_SH_IMMS6BY32, + BFD_RELOC_SH_IMMU6, + BFD_RELOC_SH_IMMS10, + BFD_RELOC_SH_IMMS10BY2, + BFD_RELOC_SH_IMMS10BY4, + BFD_RELOC_SH_IMMS10BY8, + BFD_RELOC_SH_IMMS16, + BFD_RELOC_SH_IMMU16, + BFD_RELOC_SH_IMM_LOW16, + BFD_RELOC_SH_IMM_LOW16_PCREL, + BFD_RELOC_SH_IMM_MEDLOW16, + BFD_RELOC_SH_IMM_MEDLOW16_PCREL, + BFD_RELOC_SH_IMM_MEDHI16, + BFD_RELOC_SH_IMM_MEDHI16_PCREL, + BFD_RELOC_SH_IMM_HI16, + BFD_RELOC_SH_IMM_HI16_PCREL, + BFD_RELOC_SH_PT_16, + BFD_RELOC_SH_TLS_GD_32, + BFD_RELOC_SH_TLS_LD_32, + BFD_RELOC_SH_TLS_LDO_32, + BFD_RELOC_SH_TLS_IE_32, + BFD_RELOC_SH_TLS_LE_32, + BFD_RELOC_SH_TLS_DTPMOD32, + BFD_RELOC_SH_TLS_DTPOFF32, + BFD_RELOC_SH_TLS_TPOFF32, + +/* ARC Cores relocs. +ARC 22 bit pc-relative branch. The lowest two bits must be zero and are +not stored in the instruction. The high 20 bits are installed in bits 26 +through 7 of the instruction. */ + BFD_RELOC_ARC_B22_PCREL, + +/* ARC 26 bit absolute branch. The lowest two bits must be zero and are not +stored in the instruction. The high 24 bits are installed in bits 23 +through 0. */ + BFD_RELOC_ARC_B26, + +/* ADI Blackfin 16 bit immediate absolute reloc. */ + BFD_RELOC_BFIN_16_IMM, + +/* ADI Blackfin 16 bit immediate absolute reloc higher 16 bits. */ + BFD_RELOC_BFIN_16_HIGH, + +/* ADI Blackfin 'a' part of LSETUP. */ + BFD_RELOC_BFIN_4_PCREL, + +/* ADI Blackfin. */ + BFD_RELOC_BFIN_5_PCREL, + +/* ADI Blackfin 16 bit immediate absolute reloc lower 16 bits. */ + BFD_RELOC_BFIN_16_LOW, + +/* ADI Blackfin. */ + BFD_RELOC_BFIN_10_PCREL, + +/* ADI Blackfin 'b' part of LSETUP. */ + BFD_RELOC_BFIN_11_PCREL, + +/* ADI Blackfin. */ + BFD_RELOC_BFIN_12_PCREL_JUMP, + +/* ADI Blackfin Short jump, pcrel. */ + BFD_RELOC_BFIN_12_PCREL_JUMP_S, + +/* ADI Blackfin Call.x not implemented. */ + BFD_RELOC_BFIN_24_PCREL_CALL_X, + +/* ADI Blackfin Long Jump pcrel. */ + BFD_RELOC_BFIN_24_PCREL_JUMP_L, + +/* ADI Blackfin FD-PIC relocations. */ + BFD_RELOC_BFIN_GOT17M4, + BFD_RELOC_BFIN_GOTHI, + BFD_RELOC_BFIN_GOTLO, + BFD_RELOC_BFIN_FUNCDESC, + BFD_RELOC_BFIN_FUNCDESC_GOT17M4, + BFD_RELOC_BFIN_FUNCDESC_GOTHI, + BFD_RELOC_BFIN_FUNCDESC_GOTLO, + BFD_RELOC_BFIN_FUNCDESC_VALUE, + BFD_RELOC_BFIN_FUNCDESC_GOTOFF17M4, + BFD_RELOC_BFIN_FUNCDESC_GOTOFFHI, + BFD_RELOC_BFIN_FUNCDESC_GOTOFFLO, + BFD_RELOC_BFIN_GOTOFF17M4, + BFD_RELOC_BFIN_GOTOFFHI, + BFD_RELOC_BFIN_GOTOFFLO, + +/* ADI Blackfin GOT relocation. */ + BFD_RELOC_BFIN_GOT, + +/* ADI Blackfin PLTPC relocation. */ + BFD_RELOC_BFIN_PLTPC, + +/* ADI Blackfin arithmetic relocation. */ + BFD_ARELOC_BFIN_PUSH, + +/* ADI Blackfin arithmetic relocation. */ + BFD_ARELOC_BFIN_CONST, + +/* ADI Blackfin arithmetic relocation. */ + BFD_ARELOC_BFIN_ADD, + +/* ADI Blackfin arithmetic relocation. */ + BFD_ARELOC_BFIN_SUB, + +/* ADI Blackfin arithmetic relocation. */ + BFD_ARELOC_BFIN_MULT, + +/* ADI Blackfin arithmetic relocation. */ + BFD_ARELOC_BFIN_DIV, + +/* ADI Blackfin arithmetic relocation. */ + BFD_ARELOC_BFIN_MOD, + +/* ADI Blackfin arithmetic relocation. */ + BFD_ARELOC_BFIN_LSHIFT, + +/* ADI Blackfin arithmetic relocation. */ + BFD_ARELOC_BFIN_RSHIFT, + +/* ADI Blackfin arithmetic relocation. */ + BFD_ARELOC_BFIN_AND, + +/* ADI Blackfin arithmetic relocation. */ + BFD_ARELOC_BFIN_OR, + +/* ADI Blackfin arithmetic relocation. */ + BFD_ARELOC_BFIN_XOR, + +/* ADI Blackfin arithmetic relocation. */ + BFD_ARELOC_BFIN_LAND, + +/* ADI Blackfin arithmetic relocation. */ + BFD_ARELOC_BFIN_LOR, + +/* ADI Blackfin arithmetic relocation. */ + BFD_ARELOC_BFIN_LEN, + +/* ADI Blackfin arithmetic relocation. */ + BFD_ARELOC_BFIN_NEG, + +/* ADI Blackfin arithmetic relocation. */ + BFD_ARELOC_BFIN_COMP, + +/* ADI Blackfin arithmetic relocation. */ + BFD_ARELOC_BFIN_PAGE, + +/* ADI Blackfin arithmetic relocation. */ + BFD_ARELOC_BFIN_HWPAGE, + +/* ADI Blackfin arithmetic relocation. */ + BFD_ARELOC_BFIN_ADDR, + +/* Mitsubishi D10V relocs. +This is a 10-bit reloc with the right 2 bits +assumed to be 0. */ + BFD_RELOC_D10V_10_PCREL_R, + +/* Mitsubishi D10V relocs. +This is a 10-bit reloc with the right 2 bits +assumed to be 0. This is the same as the previous reloc +except it is in the left container, i.e., +shifted left 15 bits. */ + BFD_RELOC_D10V_10_PCREL_L, + +/* This is an 18-bit reloc with the right 2 bits +assumed to be 0. */ + BFD_RELOC_D10V_18, + +/* This is an 18-bit reloc with the right 2 bits +assumed to be 0. */ + BFD_RELOC_D10V_18_PCREL, + +/* Mitsubishi D30V relocs. +This is a 6-bit absolute reloc. */ + BFD_RELOC_D30V_6, + +/* This is a 6-bit pc-relative reloc with +the right 3 bits assumed to be 0. */ + BFD_RELOC_D30V_9_PCREL, + +/* This is a 6-bit pc-relative reloc with +the right 3 bits assumed to be 0. Same +as the previous reloc but on the right side +of the container. */ + BFD_RELOC_D30V_9_PCREL_R, + +/* This is a 12-bit absolute reloc with the +right 3 bitsassumed to be 0. */ + BFD_RELOC_D30V_15, + +/* This is a 12-bit pc-relative reloc with +the right 3 bits assumed to be 0. */ + BFD_RELOC_D30V_15_PCREL, + +/* This is a 12-bit pc-relative reloc with +the right 3 bits assumed to be 0. Same +as the previous reloc but on the right side +of the container. */ + BFD_RELOC_D30V_15_PCREL_R, + +/* This is an 18-bit absolute reloc with +the right 3 bits assumed to be 0. */ + BFD_RELOC_D30V_21, + +/* This is an 18-bit pc-relative reloc with +the right 3 bits assumed to be 0. */ + BFD_RELOC_D30V_21_PCREL, + +/* This is an 18-bit pc-relative reloc with +the right 3 bits assumed to be 0. Same +as the previous reloc but on the right side +of the container. */ + BFD_RELOC_D30V_21_PCREL_R, + +/* This is a 32-bit absolute reloc. */ + BFD_RELOC_D30V_32, + +/* This is a 32-bit pc-relative reloc. */ + BFD_RELOC_D30V_32_PCREL, + +/* DLX relocs */ + BFD_RELOC_DLX_HI16_S, + +/* DLX relocs */ + BFD_RELOC_DLX_LO16, + +/* DLX relocs */ + BFD_RELOC_DLX_JMP26, + +/* Renesas M16C/M32C Relocations. */ + BFD_RELOC_M32C_HI8, + BFD_RELOC_M32C_RL_JUMP, + BFD_RELOC_M32C_RL_1ADDR, + BFD_RELOC_M32C_RL_2ADDR, + +/* Renesas M32R (formerly Mitsubishi M32R) relocs. +This is a 24 bit absolute address. */ + BFD_RELOC_M32R_24, + +/* This is a 10-bit pc-relative reloc with the right 2 bits assumed to be 0. */ + BFD_RELOC_M32R_10_PCREL, + +/* This is an 18-bit reloc with the right 2 bits assumed to be 0. */ + BFD_RELOC_M32R_18_PCREL, + +/* This is a 26-bit reloc with the right 2 bits assumed to be 0. */ + BFD_RELOC_M32R_26_PCREL, + +/* This is a 16-bit reloc containing the high 16 bits of an address +used when the lower 16 bits are treated as unsigned. */ + BFD_RELOC_M32R_HI16_ULO, + +/* This is a 16-bit reloc containing the high 16 bits of an address +used when the lower 16 bits are treated as signed. */ + BFD_RELOC_M32R_HI16_SLO, + +/* This is a 16-bit reloc containing the lower 16 bits of an address. */ + BFD_RELOC_M32R_LO16, + +/* This is a 16-bit reloc containing the small data area offset for use in +add3, load, and store instructions. */ + BFD_RELOC_M32R_SDA16, + +/* For PIC. */ + BFD_RELOC_M32R_GOT24, + BFD_RELOC_M32R_26_PLTREL, + BFD_RELOC_M32R_COPY, + BFD_RELOC_M32R_GLOB_DAT, + BFD_RELOC_M32R_JMP_SLOT, + BFD_RELOC_M32R_RELATIVE, + BFD_RELOC_M32R_GOTOFF, + BFD_RELOC_M32R_GOTOFF_HI_ULO, + BFD_RELOC_M32R_GOTOFF_HI_SLO, + BFD_RELOC_M32R_GOTOFF_LO, + BFD_RELOC_M32R_GOTPC24, + BFD_RELOC_M32R_GOT16_HI_ULO, + BFD_RELOC_M32R_GOT16_HI_SLO, + BFD_RELOC_M32R_GOT16_LO, + BFD_RELOC_M32R_GOTPC_HI_ULO, + BFD_RELOC_M32R_GOTPC_HI_SLO, + BFD_RELOC_M32R_GOTPC_LO, + +/* This is a 9-bit reloc */ + BFD_RELOC_V850_9_PCREL, + +/* This is a 22-bit reloc */ + BFD_RELOC_V850_22_PCREL, + +/* This is a 16 bit offset from the short data area pointer. */ + BFD_RELOC_V850_SDA_16_16_OFFSET, + +/* This is a 16 bit offset (of which only 15 bits are used) from the +short data area pointer. */ + BFD_RELOC_V850_SDA_15_16_OFFSET, + +/* This is a 16 bit offset from the zero data area pointer. */ + BFD_RELOC_V850_ZDA_16_16_OFFSET, + +/* This is a 16 bit offset (of which only 15 bits are used) from the +zero data area pointer. */ + BFD_RELOC_V850_ZDA_15_16_OFFSET, + +/* This is an 8 bit offset (of which only 6 bits are used) from the +tiny data area pointer. */ + BFD_RELOC_V850_TDA_6_8_OFFSET, + +/* This is an 8bit offset (of which only 7 bits are used) from the tiny +data area pointer. */ + BFD_RELOC_V850_TDA_7_8_OFFSET, + +/* This is a 7 bit offset from the tiny data area pointer. */ + BFD_RELOC_V850_TDA_7_7_OFFSET, + +/* This is a 16 bit offset from the tiny data area pointer. */ + BFD_RELOC_V850_TDA_16_16_OFFSET, + +/* This is a 5 bit offset (of which only 4 bits are used) from the tiny +data area pointer. */ + BFD_RELOC_V850_TDA_4_5_OFFSET, + +/* This is a 4 bit offset from the tiny data area pointer. */ + BFD_RELOC_V850_TDA_4_4_OFFSET, + +/* This is a 16 bit offset from the short data area pointer, with the +bits placed non-contiguously in the instruction. */ + BFD_RELOC_V850_SDA_16_16_SPLIT_OFFSET, + +/* This is a 16 bit offset from the zero data area pointer, with the +bits placed non-contiguously in the instruction. */ + BFD_RELOC_V850_ZDA_16_16_SPLIT_OFFSET, + +/* This is a 6 bit offset from the call table base pointer. */ + BFD_RELOC_V850_CALLT_6_7_OFFSET, + +/* This is a 16 bit offset from the call table base pointer. */ + BFD_RELOC_V850_CALLT_16_16_OFFSET, + +/* Used for relaxing indirect function calls. */ + BFD_RELOC_V850_LONGCALL, + +/* Used for relaxing indirect jumps. */ + BFD_RELOC_V850_LONGJUMP, + +/* Used to maintain alignment whilst relaxing. */ + BFD_RELOC_V850_ALIGN, + +/* This is a variation of BFD_RELOC_LO16 that can be used in v850e ld.bu +instructions. */ + BFD_RELOC_V850_LO16_SPLIT_OFFSET, + +/* This is a 32bit pcrel reloc for the mn10300, offset by two bytes in the +instruction. */ + BFD_RELOC_MN10300_32_PCREL, + +/* This is a 16bit pcrel reloc for the mn10300, offset by two bytes in the +instruction. */ + BFD_RELOC_MN10300_16_PCREL, + +/* This is a 8bit DP reloc for the tms320c30, where the most +significant 8 bits of a 24 bit word are placed into the least +significant 8 bits of the opcode. */ + BFD_RELOC_TIC30_LDP, + +/* This is a 7bit reloc for the tms320c54x, where the least +significant 7 bits of a 16 bit word are placed into the least +significant 7 bits of the opcode. */ + BFD_RELOC_TIC54X_PARTLS7, + +/* This is a 9bit DP reloc for the tms320c54x, where the most +significant 9 bits of a 16 bit word are placed into the least +significant 9 bits of the opcode. */ + BFD_RELOC_TIC54X_PARTMS9, + +/* This is an extended address 23-bit reloc for the tms320c54x. */ + BFD_RELOC_TIC54X_23, + +/* This is a 16-bit reloc for the tms320c54x, where the least +significant 16 bits of a 23-bit extended address are placed into +the opcode. */ + BFD_RELOC_TIC54X_16_OF_23, + +/* This is a reloc for the tms320c54x, where the most +significant 7 bits of a 23-bit extended address are placed into +the opcode. */ + BFD_RELOC_TIC54X_MS7_OF_23, + +/* This is a 48 bit reloc for the FR30 that stores 32 bits. */ + BFD_RELOC_FR30_48, + +/* This is a 32 bit reloc for the FR30 that stores 20 bits split up into +two sections. */ + BFD_RELOC_FR30_20, + +/* This is a 16 bit reloc for the FR30 that stores a 6 bit word offset in +4 bits. */ + BFD_RELOC_FR30_6_IN_4, + +/* This is a 16 bit reloc for the FR30 that stores an 8 bit byte offset +into 8 bits. */ + BFD_RELOC_FR30_8_IN_8, + +/* This is a 16 bit reloc for the FR30 that stores a 9 bit short offset +into 8 bits. */ + BFD_RELOC_FR30_9_IN_8, + +/* This is a 16 bit reloc for the FR30 that stores a 10 bit word offset +into 8 bits. */ + BFD_RELOC_FR30_10_IN_8, + +/* This is a 16 bit reloc for the FR30 that stores a 9 bit pc relative +short offset into 8 bits. */ + BFD_RELOC_FR30_9_PCREL, + +/* This is a 16 bit reloc for the FR30 that stores a 12 bit pc relative +short offset into 11 bits. */ + BFD_RELOC_FR30_12_PCREL, + +/* Motorola Mcore relocations. */ + BFD_RELOC_MCORE_PCREL_IMM8BY4, + BFD_RELOC_MCORE_PCREL_IMM11BY2, + BFD_RELOC_MCORE_PCREL_IMM4BY2, + BFD_RELOC_MCORE_PCREL_32, + BFD_RELOC_MCORE_PCREL_JSR_IMM11BY2, + BFD_RELOC_MCORE_RVA, + +/* Toshiba Media Processor Relocations. */ + BFD_RELOC_MEP_8, + BFD_RELOC_MEP_16, + BFD_RELOC_MEP_32, + BFD_RELOC_MEP_PCREL8A2, + BFD_RELOC_MEP_PCREL12A2, + BFD_RELOC_MEP_PCREL17A2, + BFD_RELOC_MEP_PCREL24A2, + BFD_RELOC_MEP_PCABS24A2, + BFD_RELOC_MEP_LOW16, + BFD_RELOC_MEP_HI16U, + BFD_RELOC_MEP_HI16S, + BFD_RELOC_MEP_GPREL, + BFD_RELOC_MEP_TPREL, + BFD_RELOC_MEP_TPREL7, + BFD_RELOC_MEP_TPREL7A2, + BFD_RELOC_MEP_TPREL7A4, + BFD_RELOC_MEP_UIMM24, + BFD_RELOC_MEP_ADDR24A4, + BFD_RELOC_MEP_GNU_VTINHERIT, + BFD_RELOC_MEP_GNU_VTENTRY, + + +/* These are relocations for the GETA instruction. */ + BFD_RELOC_MMIX_GETA, + BFD_RELOC_MMIX_GETA_1, + BFD_RELOC_MMIX_GETA_2, + BFD_RELOC_MMIX_GETA_3, + +/* These are relocations for a conditional branch instruction. */ + BFD_RELOC_MMIX_CBRANCH, + BFD_RELOC_MMIX_CBRANCH_J, + BFD_RELOC_MMIX_CBRANCH_1, + BFD_RELOC_MMIX_CBRANCH_2, + BFD_RELOC_MMIX_CBRANCH_3, + +/* These are relocations for the PUSHJ instruction. */ + BFD_RELOC_MMIX_PUSHJ, + BFD_RELOC_MMIX_PUSHJ_1, + BFD_RELOC_MMIX_PUSHJ_2, + BFD_RELOC_MMIX_PUSHJ_3, + BFD_RELOC_MMIX_PUSHJ_STUBBABLE, + +/* These are relocations for the JMP instruction. */ + BFD_RELOC_MMIX_JMP, + BFD_RELOC_MMIX_JMP_1, + BFD_RELOC_MMIX_JMP_2, + BFD_RELOC_MMIX_JMP_3, + +/* This is a relocation for a relative address as in a GETA instruction or +a branch. */ + BFD_RELOC_MMIX_ADDR19, + +/* This is a relocation for a relative address as in a JMP instruction. */ + BFD_RELOC_MMIX_ADDR27, + +/* This is a relocation for an instruction field that may be a general +register or a value 0..255. */ + BFD_RELOC_MMIX_REG_OR_BYTE, + +/* This is a relocation for an instruction field that may be a general +register. */ + BFD_RELOC_MMIX_REG, + +/* This is a relocation for two instruction fields holding a register and +an offset, the equivalent of the relocation. */ + BFD_RELOC_MMIX_BASE_PLUS_OFFSET, + +/* This relocation is an assertion that the expression is not allocated as +a global register. It does not modify contents. */ + BFD_RELOC_MMIX_LOCAL, + +/* This is a 16 bit reloc for the AVR that stores 8 bit pc relative +short offset into 7 bits. */ + BFD_RELOC_AVR_7_PCREL, + +/* This is a 16 bit reloc for the AVR that stores 13 bit pc relative +short offset into 12 bits. */ + BFD_RELOC_AVR_13_PCREL, + +/* This is a 16 bit reloc for the AVR that stores 17 bit value (usually +program memory address) into 16 bits. */ + BFD_RELOC_AVR_16_PM, + +/* This is a 16 bit reloc for the AVR that stores 8 bit value (usually +data memory address) into 8 bit immediate value of LDI insn. */ + BFD_RELOC_AVR_LO8_LDI, + +/* This is a 16 bit reloc for the AVR that stores 8 bit value (high 8 bit +of data memory address) into 8 bit immediate value of LDI insn. */ + BFD_RELOC_AVR_HI8_LDI, + +/* This is a 16 bit reloc for the AVR that stores 8 bit value (most high 8 bit +of program memory address) into 8 bit immediate value of LDI insn. */ + BFD_RELOC_AVR_HH8_LDI, + +/* This is a 16 bit reloc for the AVR that stores 8 bit value (most high 8 bit +of 32 bit value) into 8 bit immediate value of LDI insn. */ + BFD_RELOC_AVR_MS8_LDI, + +/* This is a 16 bit reloc for the AVR that stores negated 8 bit value +(usually data memory address) into 8 bit immediate value of SUBI insn. */ + BFD_RELOC_AVR_LO8_LDI_NEG, + +/* This is a 16 bit reloc for the AVR that stores negated 8 bit value +(high 8 bit of data memory address) into 8 bit immediate value of +SUBI insn. */ + BFD_RELOC_AVR_HI8_LDI_NEG, + +/* This is a 16 bit reloc for the AVR that stores negated 8 bit value +(most high 8 bit of program memory address) into 8 bit immediate value +of LDI or SUBI insn. */ + BFD_RELOC_AVR_HH8_LDI_NEG, + +/* This is a 16 bit reloc for the AVR that stores negated 8 bit value (msb +of 32 bit value) into 8 bit immediate value of LDI insn. */ + BFD_RELOC_AVR_MS8_LDI_NEG, + +/* This is a 16 bit reloc for the AVR that stores 8 bit value (usually +command address) into 8 bit immediate value of LDI insn. */ + BFD_RELOC_AVR_LO8_LDI_PM, + +/* This is a 16 bit reloc for the AVR that stores 8 bit value +(command address) into 8 bit immediate value of LDI insn. If the address +is beyond the 128k boundary, the linker inserts a jump stub for this reloc +in the lower 128k. */ + BFD_RELOC_AVR_LO8_LDI_GS, + +/* This is a 16 bit reloc for the AVR that stores 8 bit value (high 8 bit +of command address) into 8 bit immediate value of LDI insn. */ + BFD_RELOC_AVR_HI8_LDI_PM, + +/* This is a 16 bit reloc for the AVR that stores 8 bit value (high 8 bit +of command address) into 8 bit immediate value of LDI insn. If the address +is beyond the 128k boundary, the linker inserts a jump stub for this reloc +below 128k. */ + BFD_RELOC_AVR_HI8_LDI_GS, + +/* This is a 16 bit reloc for the AVR that stores 8 bit value (most high 8 bit +of command address) into 8 bit immediate value of LDI insn. */ + BFD_RELOC_AVR_HH8_LDI_PM, + +/* This is a 16 bit reloc for the AVR that stores negated 8 bit value +(usually command address) into 8 bit immediate value of SUBI insn. */ + BFD_RELOC_AVR_LO8_LDI_PM_NEG, + +/* This is a 16 bit reloc for the AVR that stores negated 8 bit value +(high 8 bit of 16 bit command address) into 8 bit immediate value +of SUBI insn. */ + BFD_RELOC_AVR_HI8_LDI_PM_NEG, + +/* This is a 16 bit reloc for the AVR that stores negated 8 bit value +(high 6 bit of 22 bit command address) into 8 bit immediate +value of SUBI insn. */ + BFD_RELOC_AVR_HH8_LDI_PM_NEG, + +/* This is a 32 bit reloc for the AVR that stores 23 bit value +into 22 bits. */ + BFD_RELOC_AVR_CALL, + +/* This is a 16 bit reloc for the AVR that stores all needed bits +for absolute addressing with ldi with overflow check to linktime */ + BFD_RELOC_AVR_LDI, + +/* This is a 6 bit reloc for the AVR that stores offset for ldd/std +instructions */ + BFD_RELOC_AVR_6, + +/* This is a 6 bit reloc for the AVR that stores offset for adiw/sbiw +instructions */ + BFD_RELOC_AVR_6_ADIW, + +/* Direct 12 bit. */ + BFD_RELOC_390_12, + +/* 12 bit GOT offset. */ + BFD_RELOC_390_GOT12, + +/* 32 bit PC relative PLT address. */ + BFD_RELOC_390_PLT32, + +/* Copy symbol at runtime. */ + BFD_RELOC_390_COPY, + +/* Create GOT entry. */ + BFD_RELOC_390_GLOB_DAT, + +/* Create PLT entry. */ + BFD_RELOC_390_JMP_SLOT, + +/* Adjust by program base. */ + BFD_RELOC_390_RELATIVE, + +/* 32 bit PC relative offset to GOT. */ + BFD_RELOC_390_GOTPC, + +/* 16 bit GOT offset. */ + BFD_RELOC_390_GOT16, + +/* PC relative 16 bit shifted by 1. */ + BFD_RELOC_390_PC16DBL, + +/* 16 bit PC rel. PLT shifted by 1. */ + BFD_RELOC_390_PLT16DBL, + +/* PC relative 32 bit shifted by 1. */ + BFD_RELOC_390_PC32DBL, + +/* 32 bit PC rel. PLT shifted by 1. */ + BFD_RELOC_390_PLT32DBL, + +/* 32 bit PC rel. GOT shifted by 1. */ + BFD_RELOC_390_GOTPCDBL, + +/* 64 bit GOT offset. */ + BFD_RELOC_390_GOT64, + +/* 64 bit PC relative PLT address. */ + BFD_RELOC_390_PLT64, + +/* 32 bit rel. offset to GOT entry. */ + BFD_RELOC_390_GOTENT, + +/* 64 bit offset to GOT. */ + BFD_RELOC_390_GOTOFF64, + +/* 12-bit offset to symbol-entry within GOT, with PLT handling. */ + BFD_RELOC_390_GOTPLT12, + +/* 16-bit offset to symbol-entry within GOT, with PLT handling. */ + BFD_RELOC_390_GOTPLT16, + +/* 32-bit offset to symbol-entry within GOT, with PLT handling. */ + BFD_RELOC_390_GOTPLT32, + +/* 64-bit offset to symbol-entry within GOT, with PLT handling. */ + BFD_RELOC_390_GOTPLT64, + +/* 32-bit rel. offset to symbol-entry within GOT, with PLT handling. */ + BFD_RELOC_390_GOTPLTENT, + +/* 16-bit rel. offset from the GOT to a PLT entry. */ + BFD_RELOC_390_PLTOFF16, + +/* 32-bit rel. offset from the GOT to a PLT entry. */ + BFD_RELOC_390_PLTOFF32, + +/* 64-bit rel. offset from the GOT to a PLT entry. */ + BFD_RELOC_390_PLTOFF64, + +/* s390 tls relocations. */ + BFD_RELOC_390_TLS_LOAD, + BFD_RELOC_390_TLS_GDCALL, + BFD_RELOC_390_TLS_LDCALL, + BFD_RELOC_390_TLS_GD32, + BFD_RELOC_390_TLS_GD64, + BFD_RELOC_390_TLS_GOTIE12, + BFD_RELOC_390_TLS_GOTIE32, + BFD_RELOC_390_TLS_GOTIE64, + BFD_RELOC_390_TLS_LDM32, + BFD_RELOC_390_TLS_LDM64, + BFD_RELOC_390_TLS_IE32, + BFD_RELOC_390_TLS_IE64, + BFD_RELOC_390_TLS_IEENT, + BFD_RELOC_390_TLS_LE32, + BFD_RELOC_390_TLS_LE64, + BFD_RELOC_390_TLS_LDO32, + BFD_RELOC_390_TLS_LDO64, + BFD_RELOC_390_TLS_DTPMOD, + BFD_RELOC_390_TLS_DTPOFF, + BFD_RELOC_390_TLS_TPOFF, + +/* Long displacement extension. */ + BFD_RELOC_390_20, + BFD_RELOC_390_GOT20, + BFD_RELOC_390_GOTPLT20, + BFD_RELOC_390_TLS_GOTIE20, + +/* Score relocations */ + BFD_RELOC_SCORE_DUMMY1, + +/* Low 16 bit for load/store */ + BFD_RELOC_SCORE_GPREL15, + +/* This is a 24-bit reloc with the right 1 bit assumed to be 0 */ + BFD_RELOC_SCORE_DUMMY2, + BFD_RELOC_SCORE_JMP, + +/* This is a 19-bit reloc with the right 1 bit assumed to be 0 */ + BFD_RELOC_SCORE_BRANCH, + +/* This is a 11-bit reloc with the right 1 bit assumed to be 0 */ + BFD_RELOC_SCORE16_JMP, + +/* This is a 8-bit reloc with the right 1 bit assumed to be 0 */ + BFD_RELOC_SCORE16_BRANCH, + +/* Undocumented Score relocs */ + BFD_RELOC_SCORE_GOT15, + BFD_RELOC_SCORE_GOT_LO16, + BFD_RELOC_SCORE_CALL15, + BFD_RELOC_SCORE_DUMMY_HI16, + +/* Scenix IP2K - 9-bit register number / data address */ + BFD_RELOC_IP2K_FR9, + +/* Scenix IP2K - 4-bit register/data bank number */ + BFD_RELOC_IP2K_BANK, + +/* Scenix IP2K - low 13 bits of instruction word address */ + BFD_RELOC_IP2K_ADDR16CJP, + +/* Scenix IP2K - high 3 bits of instruction word address */ + BFD_RELOC_IP2K_PAGE3, + +/* Scenix IP2K - ext/low/high 8 bits of data address */ + BFD_RELOC_IP2K_LO8DATA, + BFD_RELOC_IP2K_HI8DATA, + BFD_RELOC_IP2K_EX8DATA, + +/* Scenix IP2K - low/high 8 bits of instruction word address */ + BFD_RELOC_IP2K_LO8INSN, + BFD_RELOC_IP2K_HI8INSN, + +/* Scenix IP2K - even/odd PC modifier to modify snb pcl.0 */ + BFD_RELOC_IP2K_PC_SKIP, + +/* Scenix IP2K - 16 bit word address in text section. */ + BFD_RELOC_IP2K_TEXT, + +/* Scenix IP2K - 7-bit sp or dp offset */ + BFD_RELOC_IP2K_FR_OFFSET, + +/* Scenix VPE4K coprocessor - data/insn-space addressing */ + BFD_RELOC_VPE4KMATH_DATA, + BFD_RELOC_VPE4KMATH_INSN, + +/* These two relocations are used by the linker to determine which of +the entries in a C++ virtual function table are actually used. When +the --gc-sections option is given, the linker will zero out the entries +that are not used, so that the code for those functions need not be +included in the output. + +VTABLE_INHERIT is a zero-space relocation used to describe to the +linker the inheritance tree of a C++ virtual function table. The +relocation's symbol should be the parent class' vtable, and the +relocation should be located at the child vtable. + +VTABLE_ENTRY is a zero-space relocation that describes the use of a +virtual function table entry. The reloc's symbol should refer to the +table of the class mentioned in the code. Off of that base, an offset +describes the entry that is being used. For Rela hosts, this offset +is stored in the reloc's addend. For Rel hosts, we are forced to put +this offset in the reloc's section offset. */ + BFD_RELOC_VTABLE_INHERIT, + BFD_RELOC_VTABLE_ENTRY, + +/* Intel IA64 Relocations. */ + BFD_RELOC_IA64_IMM14, + BFD_RELOC_IA64_IMM22, + BFD_RELOC_IA64_IMM64, + BFD_RELOC_IA64_DIR32MSB, + BFD_RELOC_IA64_DIR32LSB, + BFD_RELOC_IA64_DIR64MSB, + BFD_RELOC_IA64_DIR64LSB, + BFD_RELOC_IA64_GPREL22, + BFD_RELOC_IA64_GPREL64I, + BFD_RELOC_IA64_GPREL32MSB, + BFD_RELOC_IA64_GPREL32LSB, + BFD_RELOC_IA64_GPREL64MSB, + BFD_RELOC_IA64_GPREL64LSB, + BFD_RELOC_IA64_LTOFF22, + BFD_RELOC_IA64_LTOFF64I, + BFD_RELOC_IA64_PLTOFF22, + BFD_RELOC_IA64_PLTOFF64I, + BFD_RELOC_IA64_PLTOFF64MSB, + BFD_RELOC_IA64_PLTOFF64LSB, + BFD_RELOC_IA64_FPTR64I, + BFD_RELOC_IA64_FPTR32MSB, + BFD_RELOC_IA64_FPTR32LSB, + BFD_RELOC_IA64_FPTR64MSB, + BFD_RELOC_IA64_FPTR64LSB, + BFD_RELOC_IA64_PCREL21B, + BFD_RELOC_IA64_PCREL21BI, + BFD_RELOC_IA64_PCREL21M, + BFD_RELOC_IA64_PCREL21F, + BFD_RELOC_IA64_PCREL22, + BFD_RELOC_IA64_PCREL60B, + BFD_RELOC_IA64_PCREL64I, + BFD_RELOC_IA64_PCREL32MSB, + BFD_RELOC_IA64_PCREL32LSB, + BFD_RELOC_IA64_PCREL64MSB, + BFD_RELOC_IA64_PCREL64LSB, + BFD_RELOC_IA64_LTOFF_FPTR22, + BFD_RELOC_IA64_LTOFF_FPTR64I, + BFD_RELOC_IA64_LTOFF_FPTR32MSB, + BFD_RELOC_IA64_LTOFF_FPTR32LSB, + BFD_RELOC_IA64_LTOFF_FPTR64MSB, + BFD_RELOC_IA64_LTOFF_FPTR64LSB, + BFD_RELOC_IA64_SEGREL32MSB, + BFD_RELOC_IA64_SEGREL32LSB, + BFD_RELOC_IA64_SEGREL64MSB, + BFD_RELOC_IA64_SEGREL64LSB, + BFD_RELOC_IA64_SECREL32MSB, + BFD_RELOC_IA64_SECREL32LSB, + BFD_RELOC_IA64_SECREL64MSB, + BFD_RELOC_IA64_SECREL64LSB, + BFD_RELOC_IA64_REL32MSB, + BFD_RELOC_IA64_REL32LSB, + BFD_RELOC_IA64_REL64MSB, + BFD_RELOC_IA64_REL64LSB, + BFD_RELOC_IA64_LTV32MSB, + BFD_RELOC_IA64_LTV32LSB, + BFD_RELOC_IA64_LTV64MSB, + BFD_RELOC_IA64_LTV64LSB, + BFD_RELOC_IA64_IPLTMSB, + BFD_RELOC_IA64_IPLTLSB, + BFD_RELOC_IA64_COPY, + BFD_RELOC_IA64_LTOFF22X, + BFD_RELOC_IA64_LDXMOV, + BFD_RELOC_IA64_TPREL14, + BFD_RELOC_IA64_TPREL22, + BFD_RELOC_IA64_TPREL64I, + BFD_RELOC_IA64_TPREL64MSB, + BFD_RELOC_IA64_TPREL64LSB, + BFD_RELOC_IA64_LTOFF_TPREL22, + BFD_RELOC_IA64_DTPMOD64MSB, + BFD_RELOC_IA64_DTPMOD64LSB, + BFD_RELOC_IA64_LTOFF_DTPMOD22, + BFD_RELOC_IA64_DTPREL14, + BFD_RELOC_IA64_DTPREL22, + BFD_RELOC_IA64_DTPREL64I, + BFD_RELOC_IA64_DTPREL32MSB, + BFD_RELOC_IA64_DTPREL32LSB, + BFD_RELOC_IA64_DTPREL64MSB, + BFD_RELOC_IA64_DTPREL64LSB, + BFD_RELOC_IA64_LTOFF_DTPREL22, + +/* Motorola 68HC11 reloc. +This is the 8 bit high part of an absolute address. */ + BFD_RELOC_M68HC11_HI8, + +/* Motorola 68HC11 reloc. +This is the 8 bit low part of an absolute address. */ + BFD_RELOC_M68HC11_LO8, + +/* Motorola 68HC11 reloc. +This is the 3 bit of a value. */ + BFD_RELOC_M68HC11_3B, + +/* Motorola 68HC11 reloc. +This reloc marks the beginning of a jump/call instruction. +It is used for linker relaxation to correctly identify beginning +of instruction and change some branches to use PC-relative +addressing mode. */ + BFD_RELOC_M68HC11_RL_JUMP, + +/* Motorola 68HC11 reloc. +This reloc marks a group of several instructions that gcc generates +and for which the linker relaxation pass can modify and/or remove +some of them. */ + BFD_RELOC_M68HC11_RL_GROUP, + +/* Motorola 68HC11 reloc. +This is the 16-bit lower part of an address. It is used for 'call' +instruction to specify the symbol address without any special +transformation (due to memory bank window). */ + BFD_RELOC_M68HC11_LO16, + +/* Motorola 68HC11 reloc. +This is a 8-bit reloc that specifies the page number of an address. +It is used by 'call' instruction to specify the page number of +the symbol. */ + BFD_RELOC_M68HC11_PAGE, + +/* Motorola 68HC11 reloc. +This is a 24-bit reloc that represents the address with a 16-bit +value and a 8-bit page number. The symbol address is transformed +to follow the 16K memory bank of 68HC12 (seen as mapped in the window). */ + BFD_RELOC_M68HC11_24, + +/* Motorola 68HC12 reloc. +This is the 5 bits of a value. */ + BFD_RELOC_M68HC12_5B, + +/* NS CR16C Relocations. */ + BFD_RELOC_16C_NUM08, + BFD_RELOC_16C_NUM08_C, + BFD_RELOC_16C_NUM16, + BFD_RELOC_16C_NUM16_C, + BFD_RELOC_16C_NUM32, + BFD_RELOC_16C_NUM32_C, + BFD_RELOC_16C_DISP04, + BFD_RELOC_16C_DISP04_C, + BFD_RELOC_16C_DISP08, + BFD_RELOC_16C_DISP08_C, + BFD_RELOC_16C_DISP16, + BFD_RELOC_16C_DISP16_C, + BFD_RELOC_16C_DISP24, + BFD_RELOC_16C_DISP24_C, + BFD_RELOC_16C_DISP24a, + BFD_RELOC_16C_DISP24a_C, + BFD_RELOC_16C_REG04, + BFD_RELOC_16C_REG04_C, + BFD_RELOC_16C_REG04a, + BFD_RELOC_16C_REG04a_C, + BFD_RELOC_16C_REG14, + BFD_RELOC_16C_REG14_C, + BFD_RELOC_16C_REG16, + BFD_RELOC_16C_REG16_C, + BFD_RELOC_16C_REG20, + BFD_RELOC_16C_REG20_C, + BFD_RELOC_16C_ABS20, + BFD_RELOC_16C_ABS20_C, + BFD_RELOC_16C_ABS24, + BFD_RELOC_16C_ABS24_C, + BFD_RELOC_16C_IMM04, + BFD_RELOC_16C_IMM04_C, + BFD_RELOC_16C_IMM16, + BFD_RELOC_16C_IMM16_C, + BFD_RELOC_16C_IMM20, + BFD_RELOC_16C_IMM20_C, + BFD_RELOC_16C_IMM24, + BFD_RELOC_16C_IMM24_C, + BFD_RELOC_16C_IMM32, + BFD_RELOC_16C_IMM32_C, + +/* NS CR16 Relocations. */ + BFD_RELOC_CR16_NUM8, + BFD_RELOC_CR16_NUM16, + BFD_RELOC_CR16_NUM32, + BFD_RELOC_CR16_NUM32a, + BFD_RELOC_CR16_REGREL0, + BFD_RELOC_CR16_REGREL4, + BFD_RELOC_CR16_REGREL4a, + BFD_RELOC_CR16_REGREL14, + BFD_RELOC_CR16_REGREL14a, + BFD_RELOC_CR16_REGREL16, + BFD_RELOC_CR16_REGREL20, + BFD_RELOC_CR16_REGREL20a, + BFD_RELOC_CR16_ABS20, + BFD_RELOC_CR16_ABS24, + BFD_RELOC_CR16_IMM4, + BFD_RELOC_CR16_IMM8, + BFD_RELOC_CR16_IMM16, + BFD_RELOC_CR16_IMM20, + BFD_RELOC_CR16_IMM24, + BFD_RELOC_CR16_IMM32, + BFD_RELOC_CR16_IMM32a, + BFD_RELOC_CR16_DISP4, + BFD_RELOC_CR16_DISP8, + BFD_RELOC_CR16_DISP16, + BFD_RELOC_CR16_DISP20, + BFD_RELOC_CR16_DISP24, + BFD_RELOC_CR16_DISP24a, + +/* NS CRX Relocations. */ + BFD_RELOC_CRX_REL4, + BFD_RELOC_CRX_REL8, + BFD_RELOC_CRX_REL8_CMP, + BFD_RELOC_CRX_REL16, + BFD_RELOC_CRX_REL24, + BFD_RELOC_CRX_REL32, + BFD_RELOC_CRX_REGREL12, + BFD_RELOC_CRX_REGREL22, + BFD_RELOC_CRX_REGREL28, + BFD_RELOC_CRX_REGREL32, + BFD_RELOC_CRX_ABS16, + BFD_RELOC_CRX_ABS32, + BFD_RELOC_CRX_NUM8, + BFD_RELOC_CRX_NUM16, + BFD_RELOC_CRX_NUM32, + BFD_RELOC_CRX_IMM16, + BFD_RELOC_CRX_IMM32, + BFD_RELOC_CRX_SWITCH8, + BFD_RELOC_CRX_SWITCH16, + BFD_RELOC_CRX_SWITCH32, + +/* These relocs are only used within the CRIS assembler. They are not +(at present) written to any object files. */ + BFD_RELOC_CRIS_BDISP8, + BFD_RELOC_CRIS_UNSIGNED_5, + BFD_RELOC_CRIS_SIGNED_6, + BFD_RELOC_CRIS_UNSIGNED_6, + BFD_RELOC_CRIS_SIGNED_8, + BFD_RELOC_CRIS_UNSIGNED_8, + BFD_RELOC_CRIS_SIGNED_16, + BFD_RELOC_CRIS_UNSIGNED_16, + BFD_RELOC_CRIS_LAPCQ_OFFSET, + BFD_RELOC_CRIS_UNSIGNED_4, + +/* Relocs used in ELF shared libraries for CRIS. */ + BFD_RELOC_CRIS_COPY, + BFD_RELOC_CRIS_GLOB_DAT, + BFD_RELOC_CRIS_JUMP_SLOT, + BFD_RELOC_CRIS_RELATIVE, + +/* 32-bit offset to symbol-entry within GOT. */ + BFD_RELOC_CRIS_32_GOT, + +/* 16-bit offset to symbol-entry within GOT. */ + BFD_RELOC_CRIS_16_GOT, + +/* 32-bit offset to symbol-entry within GOT, with PLT handling. */ + BFD_RELOC_CRIS_32_GOTPLT, + +/* 16-bit offset to symbol-entry within GOT, with PLT handling. */ + BFD_RELOC_CRIS_16_GOTPLT, + +/* 32-bit offset to symbol, relative to GOT. */ + BFD_RELOC_CRIS_32_GOTREL, + +/* 32-bit offset to symbol with PLT entry, relative to GOT. */ + BFD_RELOC_CRIS_32_PLT_GOTREL, + +/* 32-bit offset to symbol with PLT entry, relative to this relocation. */ + BFD_RELOC_CRIS_32_PLT_PCREL, + +/* Intel i860 Relocations. */ + BFD_RELOC_860_COPY, + BFD_RELOC_860_GLOB_DAT, + BFD_RELOC_860_JUMP_SLOT, + BFD_RELOC_860_RELATIVE, + BFD_RELOC_860_PC26, + BFD_RELOC_860_PLT26, + BFD_RELOC_860_PC16, + BFD_RELOC_860_LOW0, + BFD_RELOC_860_SPLIT0, + BFD_RELOC_860_LOW1, + BFD_RELOC_860_SPLIT1, + BFD_RELOC_860_LOW2, + BFD_RELOC_860_SPLIT2, + BFD_RELOC_860_LOW3, + BFD_RELOC_860_LOGOT0, + BFD_RELOC_860_SPGOT0, + BFD_RELOC_860_LOGOT1, + BFD_RELOC_860_SPGOT1, + BFD_RELOC_860_LOGOTOFF0, + BFD_RELOC_860_SPGOTOFF0, + BFD_RELOC_860_LOGOTOFF1, + BFD_RELOC_860_SPGOTOFF1, + BFD_RELOC_860_LOGOTOFF2, + BFD_RELOC_860_LOGOTOFF3, + BFD_RELOC_860_LOPC, + BFD_RELOC_860_HIGHADJ, + BFD_RELOC_860_HAGOT, + BFD_RELOC_860_HAGOTOFF, + BFD_RELOC_860_HAPC, + BFD_RELOC_860_HIGH, + BFD_RELOC_860_HIGOT, + BFD_RELOC_860_HIGOTOFF, + +/* OpenRISC Relocations. */ + BFD_RELOC_OPENRISC_ABS_26, + BFD_RELOC_OPENRISC_REL_26, + +/* H8 elf Relocations. */ + BFD_RELOC_H8_DIR16A8, + BFD_RELOC_H8_DIR16R8, + BFD_RELOC_H8_DIR24A8, + BFD_RELOC_H8_DIR24R8, + BFD_RELOC_H8_DIR32A16, + +/* Sony Xstormy16 Relocations. */ + BFD_RELOC_XSTORMY16_REL_12, + BFD_RELOC_XSTORMY16_12, + BFD_RELOC_XSTORMY16_24, + BFD_RELOC_XSTORMY16_FPTR16, + +/* Self-describing complex relocations. */ + BFD_RELOC_RELC, + + +/* Infineon Relocations. */ + BFD_RELOC_XC16X_PAG, + BFD_RELOC_XC16X_POF, + BFD_RELOC_XC16X_SEG, + BFD_RELOC_XC16X_SOF, + +/* Relocations used by VAX ELF. */ + BFD_RELOC_VAX_GLOB_DAT, + BFD_RELOC_VAX_JMP_SLOT, + BFD_RELOC_VAX_RELATIVE, + +/* Morpho MT - 16 bit immediate relocation. */ + BFD_RELOC_MT_PC16, + +/* Morpho MT - Hi 16 bits of an address. */ + BFD_RELOC_MT_HI16, + +/* Morpho MT - Low 16 bits of an address. */ + BFD_RELOC_MT_LO16, + +/* Morpho MT - Used to tell the linker which vtable entries are used. */ + BFD_RELOC_MT_GNU_VTINHERIT, + +/* Morpho MT - Used to tell the linker which vtable entries are used. */ + BFD_RELOC_MT_GNU_VTENTRY, + +/* Morpho MT - 8 bit immediate relocation. */ + BFD_RELOC_MT_PCINSN8, + +/* msp430 specific relocation codes */ + BFD_RELOC_MSP430_10_PCREL, + BFD_RELOC_MSP430_16_PCREL, + BFD_RELOC_MSP430_16, + BFD_RELOC_MSP430_16_PCREL_BYTE, + BFD_RELOC_MSP430_16_BYTE, + BFD_RELOC_MSP430_2X_PCREL, + BFD_RELOC_MSP430_RL_PCREL, + +/* IQ2000 Relocations. */ + BFD_RELOC_IQ2000_OFFSET_16, + BFD_RELOC_IQ2000_OFFSET_21, + BFD_RELOC_IQ2000_UHI16, + +/* Special Xtensa relocation used only by PLT entries in ELF shared +objects to indicate that the runtime linker should set the value +to one of its own internal functions or data structures. */ + BFD_RELOC_XTENSA_RTLD, + +/* Xtensa relocations for ELF shared objects. */ + BFD_RELOC_XTENSA_GLOB_DAT, + BFD_RELOC_XTENSA_JMP_SLOT, + BFD_RELOC_XTENSA_RELATIVE, + +/* Xtensa relocation used in ELF object files for symbols that may require +PLT entries. Otherwise, this is just a generic 32-bit relocation. */ + BFD_RELOC_XTENSA_PLT, + +/* Xtensa relocations to mark the difference of two local symbols. +These are only needed to support linker relaxation and can be ignored +when not relaxing. The field is set to the value of the difference +assuming no relaxation. The relocation encodes the position of the +first symbol so the linker can determine whether to adjust the field +value. */ + BFD_RELOC_XTENSA_DIFF8, + BFD_RELOC_XTENSA_DIFF16, + BFD_RELOC_XTENSA_DIFF32, + +/* Generic Xtensa relocations for instruction operands. Only the slot +number is encoded in the relocation. The relocation applies to the +last PC-relative immediate operand, or if there are no PC-relative +immediates, to the last immediate operand. */ + BFD_RELOC_XTENSA_SLOT0_OP, + BFD_RELOC_XTENSA_SLOT1_OP, + BFD_RELOC_XTENSA_SLOT2_OP, + BFD_RELOC_XTENSA_SLOT3_OP, + BFD_RELOC_XTENSA_SLOT4_OP, + BFD_RELOC_XTENSA_SLOT5_OP, + BFD_RELOC_XTENSA_SLOT6_OP, + BFD_RELOC_XTENSA_SLOT7_OP, + BFD_RELOC_XTENSA_SLOT8_OP, + BFD_RELOC_XTENSA_SLOT9_OP, + BFD_RELOC_XTENSA_SLOT10_OP, + BFD_RELOC_XTENSA_SLOT11_OP, + BFD_RELOC_XTENSA_SLOT12_OP, + BFD_RELOC_XTENSA_SLOT13_OP, + BFD_RELOC_XTENSA_SLOT14_OP, + +/* Alternate Xtensa relocations. Only the slot is encoded in the +relocation. The meaning of these relocations is opcode-specific. */ + BFD_RELOC_XTENSA_SLOT0_ALT, + BFD_RELOC_XTENSA_SLOT1_ALT, + BFD_RELOC_XTENSA_SLOT2_ALT, + BFD_RELOC_XTENSA_SLOT3_ALT, + BFD_RELOC_XTENSA_SLOT4_ALT, + BFD_RELOC_XTENSA_SLOT5_ALT, + BFD_RELOC_XTENSA_SLOT6_ALT, + BFD_RELOC_XTENSA_SLOT7_ALT, + BFD_RELOC_XTENSA_SLOT8_ALT, + BFD_RELOC_XTENSA_SLOT9_ALT, + BFD_RELOC_XTENSA_SLOT10_ALT, + BFD_RELOC_XTENSA_SLOT11_ALT, + BFD_RELOC_XTENSA_SLOT12_ALT, + BFD_RELOC_XTENSA_SLOT13_ALT, + BFD_RELOC_XTENSA_SLOT14_ALT, + +/* Xtensa relocations for backward compatibility. These have all been +replaced by BFD_RELOC_XTENSA_SLOT0_OP. */ + BFD_RELOC_XTENSA_OP0, + BFD_RELOC_XTENSA_OP1, + BFD_RELOC_XTENSA_OP2, + +/* Xtensa relocation to mark that the assembler expanded the +instructions from an original target. The expansion size is +encoded in the reloc size. */ + BFD_RELOC_XTENSA_ASM_EXPAND, + +/* Xtensa relocation to mark that the linker should simplify +assembler-expanded instructions. This is commonly used +internally by the linker after analysis of a +BFD_RELOC_XTENSA_ASM_EXPAND. */ + BFD_RELOC_XTENSA_ASM_SIMPLIFY, + +/* 8 bit signed offset in (ix+d) or (iy+d). */ + BFD_RELOC_Z80_DISP8, + +/* DJNZ offset. */ + BFD_RELOC_Z8K_DISP7, + +/* CALR offset. */ + BFD_RELOC_Z8K_CALLR, + +/* 4 bit value. */ + BFD_RELOC_Z8K_IMM4L, + BFD_RELOC_UNUSED }; +typedef enum bfd_reloc_code_real bfd_reloc_code_real_type; +reloc_howto_type *bfd_reloc_type_lookup + (bfd *abfd, bfd_reloc_code_real_type code); +reloc_howto_type *bfd_reloc_name_lookup + (bfd *abfd, const char *reloc_name); + +const char *bfd_get_reloc_code_name (bfd_reloc_code_real_type code); + +/* Extracted from syms.c. */ + +typedef struct bfd_symbol +{ + /* A pointer to the BFD which owns the symbol. This information + is necessary so that a back end can work out what additional + information (invisible to the application writer) is carried + with the symbol. + + This field is *almost* redundant, since you can use section->owner + instead, except that some symbols point to the global sections + bfd_{abs,com,und}_section. This could be fixed by making + these globals be per-bfd (or per-target-flavor). FIXME. */ + struct bfd *the_bfd; /* Use bfd_asymbol_bfd(sym) to access this field. */ + + /* The text of the symbol. The name is left alone, and not copied; the + application may not alter it. */ + const char *name; + + /* The value of the symbol. This really should be a union of a + numeric value with a pointer, since some flags indicate that + a pointer to another symbol is stored here. */ + symvalue value; + + /* Attributes of a symbol. */ +#define BSF_NO_FLAGS 0x00 + + /* The symbol has local scope; <> in <>. The value + is the offset into the section of the data. */ +#define BSF_LOCAL 0x01 + + /* The symbol has global scope; initialized data in <>. The + value is the offset into the section of the data. */ +#define BSF_GLOBAL 0x02 + + /* The symbol has global scope and is exported. The value is + the offset into the section of the data. */ +#define BSF_EXPORT BSF_GLOBAL /* No real difference. */ + + /* A normal C symbol would be one of: + <>, <>, <> or + <>. */ + + /* The symbol is a debugging record. The value has an arbitrary + meaning, unless BSF_DEBUGGING_RELOC is also set. */ +#define BSF_DEBUGGING 0x08 + + /* The symbol denotes a function entry point. Used in ELF, + perhaps others someday. */ +#define BSF_FUNCTION 0x10 + + /* Used by the linker. */ +#define BSF_KEEP 0x20 +#define BSF_KEEP_G 0x40 + + /* A weak global symbol, overridable without warnings by + a regular global symbol of the same name. */ +#define BSF_WEAK 0x80 + + /* This symbol was created to point to a section, e.g. ELF's + STT_SECTION symbols. */ +#define BSF_SECTION_SYM 0x100 + + /* The symbol used to be a common symbol, but now it is + allocated. */ +#define BSF_OLD_COMMON 0x200 + + /* The default value for common data. */ +#define BFD_FORT_COMM_DEFAULT_VALUE 0 + + /* In some files the type of a symbol sometimes alters its + location in an output file - ie in coff a <> symbol + which is also <> symbol appears where it was + declared and not at the end of a section. This bit is set + by the target BFD part to convey this information. */ +#define BSF_NOT_AT_END 0x400 + + /* Signal that the symbol is the label of constructor section. */ +#define BSF_CONSTRUCTOR 0x800 + + /* Signal that the symbol is a warning symbol. The name is a + warning. The name of the next symbol is the one to warn about; + if a reference is made to a symbol with the same name as the next + symbol, a warning is issued by the linker. */ +#define BSF_WARNING 0x1000 + + /* Signal that the symbol is indirect. This symbol is an indirect + pointer to the symbol with the same name as the next symbol. */ +#define BSF_INDIRECT 0x2000 + + /* BSF_FILE marks symbols that contain a file name. This is used + for ELF STT_FILE symbols. */ +#define BSF_FILE 0x4000 + + /* Symbol is from dynamic linking information. */ +#define BSF_DYNAMIC 0x8000 + + /* The symbol denotes a data object. Used in ELF, and perhaps + others someday. */ +#define BSF_OBJECT 0x10000 + + /* This symbol is a debugging symbol. The value is the offset + into the section of the data. BSF_DEBUGGING should be set + as well. */ +#define BSF_DEBUGGING_RELOC 0x20000 + + /* This symbol is thread local. Used in ELF. */ +#define BSF_THREAD_LOCAL 0x40000 + + /* This symbol represents a complex relocation expression, + with the expression tree serialized in the symbol name. */ +#define BSF_RELC 0x80000 + + /* This symbol represents a signed complex relocation expression, + with the expression tree serialized in the symbol name. */ +#define BSF_SRELC 0x100000 + + flagword flags; + + /* A pointer to the section to which this symbol is + relative. This will always be non NULL, there are special + sections for undefined and absolute symbols. */ + struct bfd_section *section; + + /* Back end special data. */ + union + { + void *p; + bfd_vma i; + } + udata; +} +asymbol; + +#define bfd_get_symtab_upper_bound(abfd) \ + BFD_SEND (abfd, _bfd_get_symtab_upper_bound, (abfd)) + +bfd_boolean bfd_is_local_label (bfd *abfd, asymbol *sym); + +bfd_boolean bfd_is_local_label_name (bfd *abfd, const char *name); + +#define bfd_is_local_label_name(abfd, name) \ + BFD_SEND (abfd, _bfd_is_local_label_name, (abfd, name)) + +bfd_boolean bfd_is_target_special_symbol (bfd *abfd, asymbol *sym); + +#define bfd_is_target_special_symbol(abfd, sym) \ + BFD_SEND (abfd, _bfd_is_target_special_symbol, (abfd, sym)) + +#define bfd_canonicalize_symtab(abfd, location) \ + BFD_SEND (abfd, _bfd_canonicalize_symtab, (abfd, location)) + +bfd_boolean bfd_set_symtab + (bfd *abfd, asymbol **location, unsigned int count); + +void bfd_print_symbol_vandf (bfd *abfd, void *file, asymbol *symbol); + +#define bfd_make_empty_symbol(abfd) \ + BFD_SEND (abfd, _bfd_make_empty_symbol, (abfd)) + +asymbol *_bfd_generic_make_empty_symbol (bfd *); + +#define bfd_make_debug_symbol(abfd,ptr,size) \ + BFD_SEND (abfd, _bfd_make_debug_symbol, (abfd, ptr, size)) + +int bfd_decode_symclass (asymbol *symbol); + +bfd_boolean bfd_is_undefined_symclass (int symclass); + +void bfd_symbol_info (asymbol *symbol, symbol_info *ret); + +bfd_boolean bfd_copy_private_symbol_data + (bfd *ibfd, asymbol *isym, bfd *obfd, asymbol *osym); + +#define bfd_copy_private_symbol_data(ibfd, isymbol, obfd, osymbol) \ + BFD_SEND (obfd, _bfd_copy_private_symbol_data, \ + (ibfd, isymbol, obfd, osymbol)) + +/* Extracted from bfd.c. */ +struct bfd +{ + /* A unique identifier of the BFD */ + unsigned int id; + + /* The filename the application opened the BFD with. */ + const char *filename; + + /* A pointer to the target jump table. */ + const struct bfd_target *xvec; + + /* The IOSTREAM, and corresponding IO vector that provide access + to the file backing the BFD. */ + void *iostream; + const struct bfd_iovec *iovec; + + /* Is the file descriptor being cached? That is, can it be closed as + needed, and re-opened when accessed later? */ + bfd_boolean cacheable; + + /* Marks whether there was a default target specified when the + BFD was opened. This is used to select which matching algorithm + to use to choose the back end. */ + bfd_boolean target_defaulted; + + /* The caching routines use these to maintain a + least-recently-used list of BFDs. */ + struct bfd *lru_prev, *lru_next; + + /* When a file is closed by the caching routines, BFD retains + state information on the file here... */ + ufile_ptr where; + + /* ... and here: (``once'' means at least once). */ + bfd_boolean opened_once; + + /* Set if we have a locally maintained mtime value, rather than + getting it from the file each time. */ + bfd_boolean mtime_set; + + /* File modified time, if mtime_set is TRUE. */ + long mtime; + + /* Reserved for an unimplemented file locking extension. */ + int ifd; + + /* The format which belongs to the BFD. (object, core, etc.) */ + bfd_format format; + + /* The direction with which the BFD was opened. */ + enum bfd_direction + { + no_direction = 0, + read_direction = 1, + write_direction = 2, + both_direction = 3 + } + direction; + + /* Format_specific flags. */ + flagword flags; + + /* Currently my_archive is tested before adding origin to + anything. I believe that this can become always an add of + origin, with origin set to 0 for non archive files. */ + ufile_ptr origin; + + /* Remember when output has begun, to stop strange things + from happening. */ + bfd_boolean output_has_begun; + + /* A hash table for section names. */ + struct bfd_hash_table section_htab; + + /* Pointer to linked list of sections. */ + struct bfd_section *sections; + + /* The last section on the section list. */ + struct bfd_section *section_last; + + /* The number of sections. */ + unsigned int section_count; + + /* Stuff only useful for object files: + The start address. */ + bfd_vma start_address; + + /* Used for input and output. */ + unsigned int symcount; + + /* Symbol table for output BFD (with symcount entries). */ + struct bfd_symbol **outsymbols; + + /* Used for slurped dynamic symbol tables. */ + unsigned int dynsymcount; + + /* Pointer to structure which contains architecture information. */ + const struct bfd_arch_info *arch_info; + + /* Flag set if symbols from this BFD should not be exported. */ + bfd_boolean no_export; + + /* Stuff only useful for archives. */ + void *arelt_data; + struct bfd *my_archive; /* The containing archive BFD. */ + struct bfd *archive_next; /* The next BFD in the archive. */ + struct bfd *archive_head; /* The first BFD in the archive. */ + bfd_boolean has_armap; + + /* A chain of BFD structures involved in a link. */ + struct bfd *link_next; + + /* A field used by _bfd_generic_link_add_archive_symbols. This will + be used only for archive elements. */ + int archive_pass; + + /* Used by the back end to hold private data. */ + union + { + struct aout_data_struct *aout_data; + struct artdata *aout_ar_data; + struct _oasys_data *oasys_obj_data; + struct _oasys_ar_data *oasys_ar_data; + struct coff_tdata *coff_obj_data; + struct pe_tdata *pe_obj_data; + struct xcoff_tdata *xcoff_obj_data; + struct ecoff_tdata *ecoff_obj_data; + struct ieee_data_struct *ieee_data; + struct ieee_ar_data_struct *ieee_ar_data; + struct srec_data_struct *srec_data; + struct ihex_data_struct *ihex_data; + struct tekhex_data_struct *tekhex_data; + struct elf_obj_tdata *elf_obj_data; + struct nlm_obj_tdata *nlm_obj_data; + struct bout_data_struct *bout_data; + struct mmo_data_struct *mmo_data; + struct sun_core_struct *sun_core_data; + struct sco5_core_struct *sco5_core_data; + struct trad_core_struct *trad_core_data; + struct som_data_struct *som_data; + struct hpux_core_struct *hpux_core_data; + struct hppabsd_core_struct *hppabsd_core_data; + struct sgi_core_struct *sgi_core_data; + struct lynx_core_struct *lynx_core_data; + struct osf_core_struct *osf_core_data; + struct cisco_core_struct *cisco_core_data; + struct versados_data_struct *versados_data; + struct netbsd_core_struct *netbsd_core_data; + struct mach_o_data_struct *mach_o_data; + struct mach_o_fat_data_struct *mach_o_fat_data; + struct bfd_pef_data_struct *pef_data; + struct bfd_pef_xlib_data_struct *pef_xlib_data; + struct bfd_sym_data_struct *sym_data; + void *any; + } + tdata; + + /* Used by the application to hold private data. */ + void *usrdata; + + /* Where all the allocated stuff under this BFD goes. This is a + struct objalloc *, but we use void * to avoid requiring the inclusion + of objalloc.h. */ + void *memory; +}; + +typedef enum bfd_error +{ + bfd_error_no_error = 0, + bfd_error_system_call, + bfd_error_invalid_target, + bfd_error_wrong_format, + bfd_error_wrong_object_format, + bfd_error_invalid_operation, + bfd_error_no_memory, + bfd_error_no_symbols, + bfd_error_no_armap, + bfd_error_no_more_archived_files, + bfd_error_malformed_archive, + bfd_error_file_not_recognized, + bfd_error_file_ambiguously_recognized, + bfd_error_no_contents, + bfd_error_nonrepresentable_section, + bfd_error_no_debug_section, + bfd_error_bad_value, + bfd_error_file_truncated, + bfd_error_file_too_big, + bfd_error_on_input, + bfd_error_invalid_error_code +} +bfd_error_type; + +bfd_error_type bfd_get_error (void); + +void bfd_set_error (bfd_error_type error_tag, ...); + +const char *bfd_errmsg (bfd_error_type error_tag); + +void bfd_perror (const char *message); + +typedef void (*bfd_error_handler_type) (const char *, ...); + +bfd_error_handler_type bfd_set_error_handler (bfd_error_handler_type); + +void bfd_set_error_program_name (const char *); + +bfd_error_handler_type bfd_get_error_handler (void); + +long bfd_get_reloc_upper_bound (bfd *abfd, asection *sect); + +long bfd_canonicalize_reloc + (bfd *abfd, asection *sec, arelent **loc, asymbol **syms); + +void bfd_set_reloc + (bfd *abfd, asection *sec, arelent **rel, unsigned int count); + +bfd_boolean bfd_set_file_flags (bfd *abfd, flagword flags); + +int bfd_get_arch_size (bfd *abfd); + +int bfd_get_sign_extend_vma (bfd *abfd); + +bfd_boolean bfd_set_start_address (bfd *abfd, bfd_vma vma); + +unsigned int bfd_get_gp_size (bfd *abfd); + +void bfd_set_gp_size (bfd *abfd, unsigned int i); + +bfd_vma bfd_scan_vma (const char *string, const char **end, int base); + +bfd_boolean bfd_copy_private_header_data (bfd *ibfd, bfd *obfd); + +#define bfd_copy_private_header_data(ibfd, obfd) \ + BFD_SEND (obfd, _bfd_copy_private_header_data, \ + (ibfd, obfd)) +bfd_boolean bfd_copy_private_bfd_data (bfd *ibfd, bfd *obfd); + +#define bfd_copy_private_bfd_data(ibfd, obfd) \ + BFD_SEND (obfd, _bfd_copy_private_bfd_data, \ + (ibfd, obfd)) +bfd_boolean bfd_merge_private_bfd_data (bfd *ibfd, bfd *obfd); + +#define bfd_merge_private_bfd_data(ibfd, obfd) \ + BFD_SEND (obfd, _bfd_merge_private_bfd_data, \ + (ibfd, obfd)) +bfd_boolean bfd_set_private_flags (bfd *abfd, flagword flags); + +#define bfd_set_private_flags(abfd, flags) \ + BFD_SEND (abfd, _bfd_set_private_flags, (abfd, flags)) +#define bfd_sizeof_headers(abfd, info) \ + BFD_SEND (abfd, _bfd_sizeof_headers, (abfd, info)) + +#define bfd_find_nearest_line(abfd, sec, syms, off, file, func, line) \ + BFD_SEND (abfd, _bfd_find_nearest_line, \ + (abfd, sec, syms, off, file, func, line)) + +#define bfd_find_line(abfd, syms, sym, file, line) \ + BFD_SEND (abfd, _bfd_find_line, \ + (abfd, syms, sym, file, line)) + +#define bfd_find_inliner_info(abfd, file, func, line) \ + BFD_SEND (abfd, _bfd_find_inliner_info, \ + (abfd, file, func, line)) + +#define bfd_debug_info_start(abfd) \ + BFD_SEND (abfd, _bfd_debug_info_start, (abfd)) + +#define bfd_debug_info_end(abfd) \ + BFD_SEND (abfd, _bfd_debug_info_end, (abfd)) + +#define bfd_debug_info_accumulate(abfd, section) \ + BFD_SEND (abfd, _bfd_debug_info_accumulate, (abfd, section)) + +#define bfd_stat_arch_elt(abfd, stat) \ + BFD_SEND (abfd, _bfd_stat_arch_elt,(abfd, stat)) + +#define bfd_update_armap_timestamp(abfd) \ + BFD_SEND (abfd, _bfd_update_armap_timestamp, (abfd)) + +#define bfd_set_arch_mach(abfd, arch, mach)\ + BFD_SEND ( abfd, _bfd_set_arch_mach, (abfd, arch, mach)) + +#define bfd_relax_section(abfd, section, link_info, again) \ + BFD_SEND (abfd, _bfd_relax_section, (abfd, section, link_info, again)) + +#define bfd_gc_sections(abfd, link_info) \ + BFD_SEND (abfd, _bfd_gc_sections, (abfd, link_info)) + +#define bfd_merge_sections(abfd, link_info) \ + BFD_SEND (abfd, _bfd_merge_sections, (abfd, link_info)) + +#define bfd_is_group_section(abfd, sec) \ + BFD_SEND (abfd, _bfd_is_group_section, (abfd, sec)) + +#define bfd_discard_group(abfd, sec) \ + BFD_SEND (abfd, _bfd_discard_group, (abfd, sec)) + +#define bfd_link_hash_table_create(abfd) \ + BFD_SEND (abfd, _bfd_link_hash_table_create, (abfd)) + +#define bfd_link_hash_table_free(abfd, hash) \ + BFD_SEND (abfd, _bfd_link_hash_table_free, (hash)) + +#define bfd_link_add_symbols(abfd, info) \ + BFD_SEND (abfd, _bfd_link_add_symbols, (abfd, info)) + +#define bfd_link_just_syms(abfd, sec, info) \ + BFD_SEND (abfd, _bfd_link_just_syms, (sec, info)) + +#define bfd_final_link(abfd, info) \ + BFD_SEND (abfd, _bfd_final_link, (abfd, info)) + +#define bfd_free_cached_info(abfd) \ + BFD_SEND (abfd, _bfd_free_cached_info, (abfd)) + +#define bfd_get_dynamic_symtab_upper_bound(abfd) \ + BFD_SEND (abfd, _bfd_get_dynamic_symtab_upper_bound, (abfd)) + +#define bfd_print_private_bfd_data(abfd, file)\ + BFD_SEND (abfd, _bfd_print_private_bfd_data, (abfd, file)) + +#define bfd_canonicalize_dynamic_symtab(abfd, asymbols) \ + BFD_SEND (abfd, _bfd_canonicalize_dynamic_symtab, (abfd, asymbols)) + +#define bfd_get_synthetic_symtab(abfd, count, syms, dyncount, dynsyms, ret) \ + BFD_SEND (abfd, _bfd_get_synthetic_symtab, (abfd, count, syms, \ + dyncount, dynsyms, ret)) + +#define bfd_get_dynamic_reloc_upper_bound(abfd) \ + BFD_SEND (abfd, _bfd_get_dynamic_reloc_upper_bound, (abfd)) + +#define bfd_canonicalize_dynamic_reloc(abfd, arels, asyms) \ + BFD_SEND (abfd, _bfd_canonicalize_dynamic_reloc, (abfd, arels, asyms)) + +extern bfd_byte *bfd_get_relocated_section_contents + (bfd *, struct bfd_link_info *, struct bfd_link_order *, bfd_byte *, + bfd_boolean, asymbol **); + +bfd_boolean bfd_alt_mach_code (bfd *abfd, int alternative); + +struct bfd_preserve +{ + void *marker; + void *tdata; + flagword flags; + const struct bfd_arch_info *arch_info; + struct bfd_section *sections; + struct bfd_section *section_last; + unsigned int section_count; + struct bfd_hash_table section_htab; +}; + +bfd_boolean bfd_preserve_save (bfd *, struct bfd_preserve *); + +void bfd_preserve_restore (bfd *, struct bfd_preserve *); + +void bfd_preserve_finish (bfd *, struct bfd_preserve *); + +bfd_vma bfd_emul_get_maxpagesize (const char *); + +void bfd_emul_set_maxpagesize (const char *, bfd_vma); + +bfd_vma bfd_emul_get_commonpagesize (const char *); + +void bfd_emul_set_commonpagesize (const char *, bfd_vma); + +char *bfd_demangle (bfd *, const char *, int); + +/* Extracted from archive.c. */ +symindex bfd_get_next_mapent + (bfd *abfd, symindex previous, carsym **sym); + +bfd_boolean bfd_set_archive_head (bfd *output, bfd *new_head); + +bfd *bfd_openr_next_archived_file (bfd *archive, bfd *previous); + +/* Extracted from corefile.c. */ +const char *bfd_core_file_failing_command (bfd *abfd); + +int bfd_core_file_failing_signal (bfd *abfd); + +bfd_boolean core_file_matches_executable_p + (bfd *core_bfd, bfd *exec_bfd); + +bfd_boolean generic_core_file_matches_executable_p + (bfd *core_bfd, bfd *exec_bfd); + +/* Extracted from targets.c. */ +#define BFD_SEND(bfd, message, arglist) \ + ((*((bfd)->xvec->message)) arglist) + +#ifdef DEBUG_BFD_SEND +#undef BFD_SEND +#define BFD_SEND(bfd, message, arglist) \ + (((bfd) && (bfd)->xvec && (bfd)->xvec->message) ? \ + ((*((bfd)->xvec->message)) arglist) : \ + (bfd_assert (__FILE__,__LINE__), NULL)) +#endif +#define BFD_SEND_FMT(bfd, message, arglist) \ + (((bfd)->xvec->message[(int) ((bfd)->format)]) arglist) + +#ifdef DEBUG_BFD_SEND +#undef BFD_SEND_FMT +#define BFD_SEND_FMT(bfd, message, arglist) \ + (((bfd) && (bfd)->xvec && (bfd)->xvec->message) ? \ + (((bfd)->xvec->message[(int) ((bfd)->format)]) arglist) : \ + (bfd_assert (__FILE__,__LINE__), NULL)) +#endif + +enum bfd_flavour +{ + bfd_target_unknown_flavour, + bfd_target_aout_flavour, + bfd_target_coff_flavour, + bfd_target_ecoff_flavour, + bfd_target_xcoff_flavour, + bfd_target_elf_flavour, + bfd_target_ieee_flavour, + bfd_target_nlm_flavour, + bfd_target_oasys_flavour, + bfd_target_tekhex_flavour, + bfd_target_srec_flavour, + bfd_target_ihex_flavour, + bfd_target_som_flavour, + bfd_target_os9k_flavour, + bfd_target_versados_flavour, + bfd_target_msdos_flavour, + bfd_target_ovax_flavour, + bfd_target_evax_flavour, + bfd_target_mmo_flavour, + bfd_target_mach_o_flavour, + bfd_target_pef_flavour, + bfd_target_pef_xlib_flavour, + bfd_target_sym_flavour +}; + +enum bfd_endian { BFD_ENDIAN_BIG, BFD_ENDIAN_LITTLE, BFD_ENDIAN_UNKNOWN }; + +/* Forward declaration. */ +typedef struct bfd_link_info _bfd_link_info; + +typedef struct bfd_target +{ + /* Identifies the kind of target, e.g., SunOS4, Ultrix, etc. */ + char *name; + + /* The "flavour" of a back end is a general indication about + the contents of a file. */ + enum bfd_flavour flavour; + + /* The order of bytes within the data area of a file. */ + enum bfd_endian byteorder; + + /* The order of bytes within the header parts of a file. */ + enum bfd_endian header_byteorder; + + /* A mask of all the flags which an executable may have set - + from the set <>, <>, ...<>. */ + flagword object_flags; + + /* A mask of all the flags which a section may have set - from + the set <>, <>, ...<>. */ + flagword section_flags; + + /* The character normally found at the front of a symbol. + (if any), perhaps `_'. */ + char symbol_leading_char; + + /* The pad character for file names within an archive header. */ + char ar_pad_char; + + /* The maximum number of characters in an archive header. */ + unsigned short ar_max_namelen; + + /* Entries for byte swapping for data. These are different from the + other entry points, since they don't take a BFD as the first argument. + Certain other handlers could do the same. */ + bfd_uint64_t (*bfd_getx64) (const void *); + bfd_int64_t (*bfd_getx_signed_64) (const void *); + void (*bfd_putx64) (bfd_uint64_t, void *); + bfd_vma (*bfd_getx32) (const void *); + bfd_signed_vma (*bfd_getx_signed_32) (const void *); + void (*bfd_putx32) (bfd_vma, void *); + bfd_vma (*bfd_getx16) (const void *); + bfd_signed_vma (*bfd_getx_signed_16) (const void *); + void (*bfd_putx16) (bfd_vma, void *); + + /* Byte swapping for the headers. */ + bfd_uint64_t (*bfd_h_getx64) (const void *); + bfd_int64_t (*bfd_h_getx_signed_64) (const void *); + void (*bfd_h_putx64) (bfd_uint64_t, void *); + bfd_vma (*bfd_h_getx32) (const void *); + bfd_signed_vma (*bfd_h_getx_signed_32) (const void *); + void (*bfd_h_putx32) (bfd_vma, void *); + bfd_vma (*bfd_h_getx16) (const void *); + bfd_signed_vma (*bfd_h_getx_signed_16) (const void *); + void (*bfd_h_putx16) (bfd_vma, void *); + + /* Format dependent routines: these are vectors of entry points + within the target vector structure, one for each format to check. */ + + /* Check the format of a file being read. Return a <> or zero. */ + const struct bfd_target *(*_bfd_check_format[bfd_type_end]) (bfd *); + + /* Set the format of a file being written. */ + bfd_boolean (*_bfd_set_format[bfd_type_end]) (bfd *); + + /* Write cached information into a file being written, at <>. */ + bfd_boolean (*_bfd_write_contents[bfd_type_end]) (bfd *); + + + /* Generic entry points. */ +#define BFD_JUMP_TABLE_GENERIC(NAME) \ + NAME##_close_and_cleanup, \ + NAME##_bfd_free_cached_info, \ + NAME##_new_section_hook, \ + NAME##_get_section_contents, \ + NAME##_get_section_contents_in_window + + /* Called when the BFD is being closed to do any necessary cleanup. */ + bfd_boolean (*_close_and_cleanup) (bfd *); + /* Ask the BFD to free all cached information. */ + bfd_boolean (*_bfd_free_cached_info) (bfd *); + /* Called when a new section is created. */ + bfd_boolean (*_new_section_hook) (bfd *, sec_ptr); + /* Read the contents of a section. */ + bfd_boolean (*_bfd_get_section_contents) + (bfd *, sec_ptr, void *, file_ptr, bfd_size_type); + bfd_boolean (*_bfd_get_section_contents_in_window) + (bfd *, sec_ptr, bfd_window *, file_ptr, bfd_size_type); + + /* Entry points to copy private data. */ +#define BFD_JUMP_TABLE_COPY(NAME) \ + NAME##_bfd_copy_private_bfd_data, \ + NAME##_bfd_merge_private_bfd_data, \ + _bfd_generic_init_private_section_data, \ + NAME##_bfd_copy_private_section_data, \ + NAME##_bfd_copy_private_symbol_data, \ + NAME##_bfd_copy_private_header_data, \ + NAME##_bfd_set_private_flags, \ + NAME##_bfd_print_private_bfd_data + + /* Called to copy BFD general private data from one object file + to another. */ + bfd_boolean (*_bfd_copy_private_bfd_data) (bfd *, bfd *); + /* Called to merge BFD general private data from one object file + to a common output file when linking. */ + bfd_boolean (*_bfd_merge_private_bfd_data) (bfd *, bfd *); + /* Called to initialize BFD private section data from one object file + to another. */ +#define bfd_init_private_section_data(ibfd, isec, obfd, osec, link_info) \ + BFD_SEND (obfd, _bfd_init_private_section_data, (ibfd, isec, obfd, osec, link_info)) + bfd_boolean (*_bfd_init_private_section_data) + (bfd *, sec_ptr, bfd *, sec_ptr, struct bfd_link_info *); + /* Called to copy BFD private section data from one object file + to another. */ + bfd_boolean (*_bfd_copy_private_section_data) + (bfd *, sec_ptr, bfd *, sec_ptr); + /* Called to copy BFD private symbol data from one symbol + to another. */ + bfd_boolean (*_bfd_copy_private_symbol_data) + (bfd *, asymbol *, bfd *, asymbol *); + /* Called to copy BFD private header data from one object file + to another. */ + bfd_boolean (*_bfd_copy_private_header_data) + (bfd *, bfd *); + /* Called to set private backend flags. */ + bfd_boolean (*_bfd_set_private_flags) (bfd *, flagword); + + /* Called to print private BFD data. */ + bfd_boolean (*_bfd_print_private_bfd_data) (bfd *, void *); + + /* Core file entry points. */ +#define BFD_JUMP_TABLE_CORE(NAME) \ + NAME##_core_file_failing_command, \ + NAME##_core_file_failing_signal, \ + NAME##_core_file_matches_executable_p + + char * (*_core_file_failing_command) (bfd *); + int (*_core_file_failing_signal) (bfd *); + bfd_boolean (*_core_file_matches_executable_p) (bfd *, bfd *); + + /* Archive entry points. */ +#define BFD_JUMP_TABLE_ARCHIVE(NAME) \ + NAME##_slurp_armap, \ + NAME##_slurp_extended_name_table, \ + NAME##_construct_extended_name_table, \ + NAME##_truncate_arname, \ + NAME##_write_armap, \ + NAME##_read_ar_hdr, \ + NAME##_openr_next_archived_file, \ + NAME##_get_elt_at_index, \ + NAME##_generic_stat_arch_elt, \ + NAME##_update_armap_timestamp + + bfd_boolean (*_bfd_slurp_armap) (bfd *); + bfd_boolean (*_bfd_slurp_extended_name_table) (bfd *); + bfd_boolean (*_bfd_construct_extended_name_table) + (bfd *, char **, bfd_size_type *, const char **); + void (*_bfd_truncate_arname) (bfd *, const char *, char *); + bfd_boolean (*write_armap) + (bfd *, unsigned int, struct orl *, unsigned int, int); + void * (*_bfd_read_ar_hdr_fn) (bfd *); + bfd * (*openr_next_archived_file) (bfd *, bfd *); +#define bfd_get_elt_at_index(b,i) BFD_SEND (b, _bfd_get_elt_at_index, (b,i)) + bfd * (*_bfd_get_elt_at_index) (bfd *, symindex); + int (*_bfd_stat_arch_elt) (bfd *, struct stat *); + bfd_boolean (*_bfd_update_armap_timestamp) (bfd *); + + /* Entry points used for symbols. */ +#define BFD_JUMP_TABLE_SYMBOLS(NAME) \ + NAME##_get_symtab_upper_bound, \ + NAME##_canonicalize_symtab, \ + NAME##_make_empty_symbol, \ + NAME##_print_symbol, \ + NAME##_get_symbol_info, \ + NAME##_bfd_is_local_label_name, \ + NAME##_bfd_is_target_special_symbol, \ + NAME##_get_lineno, \ + NAME##_find_nearest_line, \ + _bfd_generic_find_line, \ + NAME##_find_inliner_info, \ + NAME##_bfd_make_debug_symbol, \ + NAME##_read_minisymbols, \ + NAME##_minisymbol_to_symbol + + long (*_bfd_get_symtab_upper_bound) (bfd *); + long (*_bfd_canonicalize_symtab) + (bfd *, struct bfd_symbol **); + struct bfd_symbol * + (*_bfd_make_empty_symbol) (bfd *); + void (*_bfd_print_symbol) + (bfd *, void *, struct bfd_symbol *, bfd_print_symbol_type); +#define bfd_print_symbol(b,p,s,e) BFD_SEND (b, _bfd_print_symbol, (b,p,s,e)) + void (*_bfd_get_symbol_info) + (bfd *, struct bfd_symbol *, symbol_info *); +#define bfd_get_symbol_info(b,p,e) BFD_SEND (b, _bfd_get_symbol_info, (b,p,e)) + bfd_boolean (*_bfd_is_local_label_name) (bfd *, const char *); + bfd_boolean (*_bfd_is_target_special_symbol) (bfd *, asymbol *); + alent * (*_get_lineno) (bfd *, struct bfd_symbol *); + bfd_boolean (*_bfd_find_nearest_line) + (bfd *, struct bfd_section *, struct bfd_symbol **, bfd_vma, + const char **, const char **, unsigned int *); + bfd_boolean (*_bfd_find_line) + (bfd *, struct bfd_symbol **, struct bfd_symbol *, + const char **, unsigned int *); + bfd_boolean (*_bfd_find_inliner_info) + (bfd *, const char **, const char **, unsigned int *); + /* Back-door to allow format-aware applications to create debug symbols + while using BFD for everything else. Currently used by the assembler + when creating COFF files. */ + asymbol * (*_bfd_make_debug_symbol) + (bfd *, void *, unsigned long size); +#define bfd_read_minisymbols(b, d, m, s) \ + BFD_SEND (b, _read_minisymbols, (b, d, m, s)) + long (*_read_minisymbols) + (bfd *, bfd_boolean, void **, unsigned int *); +#define bfd_minisymbol_to_symbol(b, d, m, f) \ + BFD_SEND (b, _minisymbol_to_symbol, (b, d, m, f)) + asymbol * (*_minisymbol_to_symbol) + (bfd *, bfd_boolean, const void *, asymbol *); + + /* Routines for relocs. */ +#define BFD_JUMP_TABLE_RELOCS(NAME) \ + NAME##_get_reloc_upper_bound, \ + NAME##_canonicalize_reloc, \ + NAME##_bfd_reloc_type_lookup, \ + NAME##_bfd_reloc_name_lookup + + long (*_get_reloc_upper_bound) (bfd *, sec_ptr); + long (*_bfd_canonicalize_reloc) + (bfd *, sec_ptr, arelent **, struct bfd_symbol **); + /* See documentation on reloc types. */ + reloc_howto_type * + (*reloc_type_lookup) (bfd *, bfd_reloc_code_real_type); + reloc_howto_type * + (*reloc_name_lookup) (bfd *, const char *); + + + /* Routines used when writing an object file. */ +#define BFD_JUMP_TABLE_WRITE(NAME) \ + NAME##_set_arch_mach, \ + NAME##_set_section_contents + + bfd_boolean (*_bfd_set_arch_mach) + (bfd *, enum bfd_architecture, unsigned long); + bfd_boolean (*_bfd_set_section_contents) + (bfd *, sec_ptr, const void *, file_ptr, bfd_size_type); + + /* Routines used by the linker. */ +#define BFD_JUMP_TABLE_LINK(NAME) \ + NAME##_sizeof_headers, \ + NAME##_bfd_get_relocated_section_contents, \ + NAME##_bfd_relax_section, \ + NAME##_bfd_link_hash_table_create, \ + NAME##_bfd_link_hash_table_free, \ + NAME##_bfd_link_add_symbols, \ + NAME##_bfd_link_just_syms, \ + NAME##_bfd_final_link, \ + NAME##_bfd_link_split_section, \ + NAME##_bfd_gc_sections, \ + NAME##_bfd_merge_sections, \ + NAME##_bfd_is_group_section, \ + NAME##_bfd_discard_group, \ + NAME##_section_already_linked \ + + int (*_bfd_sizeof_headers) (bfd *, struct bfd_link_info *); + bfd_byte * (*_bfd_get_relocated_section_contents) + (bfd *, struct bfd_link_info *, struct bfd_link_order *, + bfd_byte *, bfd_boolean, struct bfd_symbol **); + + bfd_boolean (*_bfd_relax_section) + (bfd *, struct bfd_section *, struct bfd_link_info *, bfd_boolean *); + + /* Create a hash table for the linker. Different backends store + different information in this table. */ + struct bfd_link_hash_table * + (*_bfd_link_hash_table_create) (bfd *); + + /* Release the memory associated with the linker hash table. */ + void (*_bfd_link_hash_table_free) (struct bfd_link_hash_table *); + + /* Add symbols from this object file into the hash table. */ + bfd_boolean (*_bfd_link_add_symbols) (bfd *, struct bfd_link_info *); + + /* Indicate that we are only retrieving symbol values from this section. */ + void (*_bfd_link_just_syms) (asection *, struct bfd_link_info *); + + /* Do a link based on the link_order structures attached to each + section of the BFD. */ + bfd_boolean (*_bfd_final_link) (bfd *, struct bfd_link_info *); + + /* Should this section be split up into smaller pieces during linking. */ + bfd_boolean (*_bfd_link_split_section) (bfd *, struct bfd_section *); + + /* Remove sections that are not referenced from the output. */ + bfd_boolean (*_bfd_gc_sections) (bfd *, struct bfd_link_info *); + + /* Attempt to merge SEC_MERGE sections. */ + bfd_boolean (*_bfd_merge_sections) (bfd *, struct bfd_link_info *); + + /* Is this section a member of a group? */ + bfd_boolean (*_bfd_is_group_section) (bfd *, const struct bfd_section *); + + /* Discard members of a group. */ + bfd_boolean (*_bfd_discard_group) (bfd *, struct bfd_section *); + + /* Check if SEC has been already linked during a reloceatable or + final link. */ + void (*_section_already_linked) (bfd *, struct bfd_section *, + struct bfd_link_info *); + + /* Routines to handle dynamic symbols and relocs. */ +#define BFD_JUMP_TABLE_DYNAMIC(NAME) \ + NAME##_get_dynamic_symtab_upper_bound, \ + NAME##_canonicalize_dynamic_symtab, \ + NAME##_get_synthetic_symtab, \ + NAME##_get_dynamic_reloc_upper_bound, \ + NAME##_canonicalize_dynamic_reloc + + /* Get the amount of memory required to hold the dynamic symbols. */ + long (*_bfd_get_dynamic_symtab_upper_bound) (bfd *); + /* Read in the dynamic symbols. */ + long (*_bfd_canonicalize_dynamic_symtab) + (bfd *, struct bfd_symbol **); + /* Create synthetized symbols. */ + long (*_bfd_get_synthetic_symtab) + (bfd *, long, struct bfd_symbol **, long, struct bfd_symbol **, + struct bfd_symbol **); + /* Get the amount of memory required to hold the dynamic relocs. */ + long (*_bfd_get_dynamic_reloc_upper_bound) (bfd *); + /* Read in the dynamic relocs. */ + long (*_bfd_canonicalize_dynamic_reloc) + (bfd *, arelent **, struct bfd_symbol **); + + /* Opposite endian version of this target. */ + const struct bfd_target * alternative_target; + + /* Data for use by back-end routines, which isn't + generic enough to belong in this structure. */ + const void *backend_data; + +} bfd_target; + +bfd_boolean bfd_set_default_target (const char *name); + +const bfd_target *bfd_find_target (const char *target_name, bfd *abfd); + +const char ** bfd_target_list (void); + +const bfd_target *bfd_search_for_target + (int (*search_func) (const bfd_target *, void *), + void *); + +/* Extracted from format.c. */ +bfd_boolean bfd_check_format (bfd *abfd, bfd_format format); + +bfd_boolean bfd_check_format_matches + (bfd *abfd, bfd_format format, char ***matching); + +bfd_boolean bfd_set_format (bfd *abfd, bfd_format format); + +const char *bfd_format_string (bfd_format format); + +/* Extracted from linker.c. */ +bfd_boolean bfd_link_split_section (bfd *abfd, asection *sec); + +#define bfd_link_split_section(abfd, sec) \ + BFD_SEND (abfd, _bfd_link_split_section, (abfd, sec)) + +void bfd_section_already_linked (bfd *abfd, asection *sec, + struct bfd_link_info *info); + +#define bfd_section_already_linked(abfd, sec, info) \ + BFD_SEND (abfd, _section_already_linked, (abfd, sec, info)) + +/* Extracted from simple.c. */ +bfd_byte *bfd_simple_get_relocated_section_contents + (bfd *abfd, asection *sec, bfd_byte *outbuf, asymbol **symbol_table); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/kernel/fiasco/src/lib/disasm/bfd/elf-bfd.h b/kernel/fiasco/src/lib/disasm/bfd/elf-bfd.h new file mode 100644 index 00000000..5dea7f9a --- /dev/null +++ b/kernel/fiasco/src/lib/disasm/bfd/elf-bfd.h @@ -0,0 +1,2133 @@ +/* BFD back-end data structures for ELF files. + Copyright 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, + 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. + Written by Cygnus Support. + + This file is part of BFD, the Binary File Descriptor library. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + MA 02110-1301, USA. */ + +#ifndef _LIBELF_H_ +#define _LIBELF_H_ 1 + +#include "elf/common.h" +#include "elf/internal.h" +#include "elf/external.h" +#include "bfdlink.h" + +/* The number of entries in a section is its size divided by the size + of a single entry. This is normally only applicable to reloc and + symbol table sections. */ +#define NUM_SHDR_ENTRIES(shdr) ((shdr)->sh_size / (shdr)->sh_entsize) + +/* If size isn't specified as 64 or 32, NAME macro should fail. */ +#ifndef NAME +#if ARCH_SIZE == 64 +#define NAME(x, y) x ## 64 ## _ ## y +#endif +#if ARCH_SIZE == 32 +#define NAME(x, y) x ## 32 ## _ ## y +#endif +#endif + +#ifndef NAME +#define NAME(x, y) x ## NOSIZE ## _ ## y +#endif + +#define ElfNAME(X) NAME(Elf,X) +#define elfNAME(X) NAME(elf,X) + +/* Information held for an ELF symbol. The first field is the + corresponding asymbol. Every symbol is an ELF file is actually a + pointer to this structure, although it is often handled as a + pointer to an asymbol. */ + +typedef struct +{ + /* The BFD symbol. */ + asymbol symbol; + /* ELF symbol information. */ + Elf_Internal_Sym internal_elf_sym; + /* Backend specific information. */ + union + { + unsigned int hppa_arg_reloc; + void *mips_extr; + void *any; + } + tc_data; + + /* Version information. This is from an Elf_Internal_Versym + structure in a SHT_GNU_versym section. It is zero if there is no + version information. */ + unsigned short version; + +} elf_symbol_type; + +struct elf_strtab_hash; +struct got_entry; +struct plt_entry; + +/* ELF linker hash table entries. */ + +struct elf_link_hash_entry +{ + struct bfd_link_hash_entry root; + + /* Symbol index in output file. This is initialized to -1. It is + set to -2 if the symbol is used by a reloc. */ + long indx; + + /* Symbol index as a dynamic symbol. Initialized to -1, and remains + -1 if this is not a dynamic symbol. */ + /* ??? Note that this is consistently used as a synonym for tests + against whether we can perform various simplifying transformations + to the code. (E.g. changing a pc-relative jump to a PLT entry + into a pc-relative jump to the target function.) That test, which + is often relatively complex, and someplaces wrong or incomplete, + should really be replaced by a predicate in elflink.c. + + End result: this field -1 does not indicate that the symbol is + not in the dynamic symbol table, but rather that the symbol is + not visible outside this DSO. */ + long dynindx; + + /* If this symbol requires an entry in the global offset table, the + processor specific backend uses this field to track usage and + final offset. Two schemes are supported: The first assumes that + a symbol may only have one GOT entry, and uses REFCOUNT until + size_dynamic_sections, at which point the contents of the .got is + fixed. Afterward, if OFFSET is -1, then the symbol does not + require a global offset table entry. The second scheme allows + multiple GOT entries per symbol, managed via a linked list + pointed to by GLIST. */ + union gotplt_union + { + bfd_signed_vma refcount; + bfd_vma offset; + struct got_entry *glist; + struct plt_entry *plist; + } got; + + /* Same, but tracks a procedure linkage table entry. */ + union gotplt_union plt; + + /* Symbol size. */ + bfd_size_type size; + + /* Symbol type (STT_NOTYPE, STT_OBJECT, etc.). */ + unsigned int type : 8; + + /* Symbol st_other value, symbol visibility. */ + unsigned int other : 8; + + /* Symbol is referenced by a non-shared object. */ + unsigned int ref_regular : 1; + /* Symbol is defined by a non-shared object. */ + unsigned int def_regular : 1; + /* Symbol is referenced by a shared object. */ + unsigned int ref_dynamic : 1; + /* Symbol is defined by a shared object. */ + unsigned int def_dynamic : 1; + /* Symbol has a non-weak reference from a non-shared object. */ + unsigned int ref_regular_nonweak : 1; + /* Dynamic symbol has been adjustd. */ + unsigned int dynamic_adjusted : 1; + /* Symbol needs a copy reloc. */ + unsigned int needs_copy : 1; + /* Symbol needs a procedure linkage table entry. */ + unsigned int needs_plt : 1; + /* Symbol appears in a non-ELF input file. */ + unsigned int non_elf : 1; + /* Symbol should be marked as hidden in the version information. */ + unsigned int hidden : 1; + /* Symbol was forced to local scope due to a version script file. */ + unsigned int forced_local : 1; + /* Symbol was forced to be dynamic due to a version script file. */ + unsigned int dynamic : 1; + /* Symbol was marked during garbage collection. */ + unsigned int mark : 1; + /* Symbol is referenced by a non-GOT/non-PLT relocation. This is + not currently set by all the backends. */ + unsigned int non_got_ref : 1; + /* Symbol has a definition in a shared object. + FIXME: There is no real need for this field if def_dynamic is never + cleared and all places that test def_dynamic also test def_regular. */ + unsigned int dynamic_def : 1; + /* Symbol is weak in all shared objects. */ + unsigned int dynamic_weak : 1; + /* Symbol is referenced with a relocation where C/C++ pointer equality + matters. */ + unsigned int pointer_equality_needed : 1; + + /* String table index in .dynstr if this is a dynamic symbol. */ + unsigned long dynstr_index; + + union + { + /* If this is a weak defined symbol from a dynamic object, this + field points to a defined symbol with the same value, if there is + one. Otherwise it is NULL. */ + struct elf_link_hash_entry *weakdef; + + /* Hash value of the name computed using the ELF hash function. + Used part way through size_dynamic_sections, after we've finished + with weakdefs. */ + unsigned long elf_hash_value; + } u; + + /* Version information. */ + union + { + /* This field is used for a symbol which is not defined in a + regular object. It points to the version information read in + from the dynamic object. */ + Elf_Internal_Verdef *verdef; + /* This field is used for a symbol which is defined in a regular + object. It is set up in size_dynamic_sections. It points to + the version information we should write out for this symbol. */ + struct bfd_elf_version_tree *vertree; + } verinfo; + + struct + { + /* Virtual table entry use information. This array is nominally of size + size/sizeof(target_void_pointer), though we have to be able to assume + and track a size while the symbol is still undefined. It is indexed + via offset/sizeof(target_void_pointer). */ + size_t size; + bfd_boolean *used; + + /* Virtual table derivation info. */ + struct elf_link_hash_entry *parent; + } *vtable; +}; + +/* Will references to this symbol always reference the symbol + in this object? STV_PROTECTED is excluded from the visibility test + here so that function pointer comparisons work properly. Since + function symbols not defined in an app are set to their .plt entry, + it's necessary for shared libs to also reference the .plt even + though the symbol is really local to the shared lib. */ +#define SYMBOL_REFERENCES_LOCAL(INFO, H) \ + _bfd_elf_symbol_refs_local_p (H, INFO, 0) + +/* Will _calls_ to this symbol always call the version in this object? */ +#define SYMBOL_CALLS_LOCAL(INFO, H) \ + _bfd_elf_symbol_refs_local_p (H, INFO, 1) + +/* Common symbols that are turned into definitions don't have the + DEF_REGULAR flag set, so they might appear to be undefined. */ +#define ELF_COMMON_DEF_P(H) \ + (!(H)->def_regular \ + && !(H)->def_dynamic \ + && (H)->root.type == bfd_link_hash_defined) + +/* Records local symbols to be emitted in the dynamic symbol table. */ + +struct elf_link_local_dynamic_entry +{ + struct elf_link_local_dynamic_entry *next; + + /* The input bfd this symbol came from. */ + bfd *input_bfd; + + /* The index of the local symbol being copied. */ + long input_indx; + + /* The index in the outgoing dynamic symbol table. */ + long dynindx; + + /* A copy of the input symbol. */ + Elf_Internal_Sym isym; +}; + +struct elf_link_loaded_list +{ + struct elf_link_loaded_list *next; + bfd *abfd; +}; + +/* Structures used by the eh_frame optimization code. */ +struct eh_cie_fde +{ + /* For FDEs, this points to the CIE used. */ + struct eh_cie_fde *cie_inf; + unsigned int size; + unsigned int offset; + unsigned int new_offset; + unsigned char fde_encoding; + unsigned char lsda_encoding; + unsigned char lsda_offset; + unsigned int cie : 1; + unsigned int removed : 1; + unsigned int add_augmentation_size : 1; + unsigned int add_fde_encoding : 1; + unsigned int make_relative : 1; + unsigned int make_lsda_relative : 1; + unsigned int need_lsda_relative : 1; + unsigned int per_encoding_relative : 1; + unsigned int *set_loc; +}; + +struct eh_frame_sec_info +{ + unsigned int count; + struct eh_cie_fde entry[1]; +}; + +struct eh_frame_array_ent +{ + bfd_vma initial_loc; + bfd_vma fde; +}; + +struct htab; + +struct eh_frame_hdr_info +{ + struct htab *cies; + asection *hdr_sec; + unsigned int fde_count, array_count; + struct eh_frame_array_ent *array; + /* TRUE if .eh_frame_hdr should contain the sorted search table. + We build it if we successfully read all .eh_frame input sections + and recognize them. */ + bfd_boolean table; + bfd_boolean offsets_adjusted; +}; + +/* ELF linker hash table. */ + +struct elf_link_hash_table +{ + struct bfd_link_hash_table root; + + /* Whether we have created the special dynamic sections required + when linking against or generating a shared object. */ + bfd_boolean dynamic_sections_created; + + /* True if this target has relocatable executables, so needs dynamic + section symbols. */ + bfd_boolean is_relocatable_executable; + + /* The BFD used to hold special sections created by the linker. + This will be the first BFD found which requires these sections to + be created. */ + bfd *dynobj; + + /* The value to use when initialising got.refcount/offset and + plt.refcount/offset in an elf_link_hash_entry. Set to zero when + the values are refcounts. Set to init_got_offset/init_plt_offset + in size_dynamic_sections when the values may be offsets. */ + union gotplt_union init_got_refcount; + union gotplt_union init_plt_refcount; + + /* The value to use for got.refcount/offset and plt.refcount/offset + when the values may be offsets. Normally (bfd_vma) -1. */ + union gotplt_union init_got_offset; + union gotplt_union init_plt_offset; + + /* The number of symbols found in the link which must be put into + the .dynsym section. */ + bfd_size_type dynsymcount; + + /* The string table of dynamic symbols, which becomes the .dynstr + section. */ + struct elf_strtab_hash *dynstr; + + /* The number of buckets in the hash table in the .hash section. + This is based on the number of dynamic symbols. */ + bfd_size_type bucketcount; + + /* A linked list of DT_NEEDED names found in dynamic objects + included in the link. */ + struct bfd_link_needed_list *needed; + + /* Sections in the output bfd that provides a section symbol + to be used by relocations emitted against local symbols. + Most targets will not use data_index_section. */ + asection *text_index_section; + asection *data_index_section; + + /* The _GLOBAL_OFFSET_TABLE_ symbol. */ + struct elf_link_hash_entry *hgot; + + /* The _PROCEDURE_LINKAGE_TABLE_ symbol. */ + struct elf_link_hash_entry *hplt; + + /* A pointer to information used to merge SEC_MERGE sections. */ + void *merge_info; + + /* Used to link stabs in sections. */ + struct stab_info stab_info; + + /* Used by eh_frame code when editing .eh_frame. */ + struct eh_frame_hdr_info eh_info; + + /* A linked list of local symbols to be added to .dynsym. */ + struct elf_link_local_dynamic_entry *dynlocal; + + /* A linked list of DT_RPATH/DT_RUNPATH names found in dynamic + objects included in the link. */ + struct bfd_link_needed_list *runpath; + + /* Cached first output tls section and size of PT_TLS segment. */ + asection *tls_sec; + bfd_size_type tls_size; + + /* A linked list of BFD's loaded in the link. */ + struct elf_link_loaded_list *loaded; +}; + +/* Look up an entry in an ELF linker hash table. */ + +#define elf_link_hash_lookup(table, string, create, copy, follow) \ + ((struct elf_link_hash_entry *) \ + bfd_link_hash_lookup (&(table)->root, (string), (create), \ + (copy), (follow))) + +/* Traverse an ELF linker hash table. */ + +#define elf_link_hash_traverse(table, func, info) \ + (bfd_link_hash_traverse \ + (&(table)->root, \ + (bfd_boolean (*) (struct bfd_link_hash_entry *, void *)) (func), \ + (info))) + +/* Get the ELF linker hash table from a link_info structure. */ + +#define elf_hash_table(p) ((struct elf_link_hash_table *) ((p)->hash)) + +/* Returns TRUE if the hash table is a struct elf_link_hash_table. */ +#define is_elf_hash_table(htab) \ + (((struct bfd_link_hash_table *) (htab))->type == bfd_link_elf_hash_table) + +/* Used by bfd_section_from_r_symndx to cache a small number of local + symbol to section mappings. */ +#define LOCAL_SYM_CACHE_SIZE 32 +struct sym_sec_cache +{ + bfd *abfd; + unsigned long indx[LOCAL_SYM_CACHE_SIZE]; + unsigned int shndx[LOCAL_SYM_CACHE_SIZE]; +}; + +/* Constant information held for an ELF backend. */ + +struct elf_size_info { + unsigned char sizeof_ehdr, sizeof_phdr, sizeof_shdr; + unsigned char sizeof_rel, sizeof_rela, sizeof_sym, sizeof_dyn, sizeof_note; + + /* The size of entries in the .hash section. */ + unsigned char sizeof_hash_entry; + + /* The number of internal relocations to allocate per external + relocation entry. */ + unsigned char int_rels_per_ext_rel; + /* We use some fixed size arrays. This should be large enough to + handle all back-ends. */ +#define MAX_INT_RELS_PER_EXT_REL 3 + + unsigned char arch_size, log_file_align; + unsigned char elfclass, ev_current; + int (*write_out_phdrs) + (bfd *, const Elf_Internal_Phdr *, unsigned int); + bfd_boolean + (*write_shdrs_and_ehdr) (bfd *); + bfd_boolean (*checksum_contents) + (bfd * , void (*) (const void *, size_t, void *), void *); + void (*write_relocs) + (bfd *, asection *, void *); + bfd_boolean (*swap_symbol_in) + (bfd *, const void *, const void *, Elf_Internal_Sym *); + void (*swap_symbol_out) + (bfd *, const Elf_Internal_Sym *, void *, void *); + bfd_boolean (*slurp_reloc_table) + (bfd *, asection *, asymbol **, bfd_boolean); + long (*slurp_symbol_table) + (bfd *, asymbol **, bfd_boolean); + void (*swap_dyn_in) + (bfd *, const void *, Elf_Internal_Dyn *); + void (*swap_dyn_out) + (bfd *, const Elf_Internal_Dyn *, void *); + + /* This function is called to swap in a REL relocation. If an + external relocation corresponds to more than one internal + relocation, then all relocations are swapped in at once. */ + void (*swap_reloc_in) + (bfd *, const bfd_byte *, Elf_Internal_Rela *); + + /* This function is called to swap out a REL relocation. */ + void (*swap_reloc_out) + (bfd *, const Elf_Internal_Rela *, bfd_byte *); + + /* This function is called to swap in a RELA relocation. If an + external relocation corresponds to more than one internal + relocation, then all relocations are swapped in at once. */ + void (*swap_reloca_in) + (bfd *, const bfd_byte *, Elf_Internal_Rela *); + + /* This function is called to swap out a RELA relocation. */ + void (*swap_reloca_out) + (bfd *, const Elf_Internal_Rela *, bfd_byte *); +}; + +#define elf_symbol_from(ABFD,S) \ + (((S)->the_bfd->xvec->flavour == bfd_target_elf_flavour \ + && (S)->the_bfd->tdata.elf_obj_data != 0) \ + ? (elf_symbol_type *) (S) \ + : 0) + +enum elf_reloc_type_class { + reloc_class_normal, + reloc_class_relative, + reloc_class_plt, + reloc_class_copy +}; + +struct elf_reloc_cookie +{ + Elf_Internal_Rela *rels, *rel, *relend; + Elf_Internal_Sym *locsyms; + bfd *abfd; + size_t locsymcount; + size_t extsymoff; + struct elf_link_hash_entry **sym_hashes; + int r_sym_shift; + bfd_boolean bad_symtab; +}; + +/* The level of IRIX compatibility we're striving for. */ + +typedef enum { + ict_none, + ict_irix5, + ict_irix6 +} irix_compat_t; + +/* Mapping of ELF section names and types. */ +struct bfd_elf_special_section +{ + const char *prefix; + int prefix_length; + /* 0 means name must match PREFIX exactly. + -1 means name must start with PREFIX followed by an arbitrary string. + -2 means name must match PREFIX exactly or consist of PREFIX followed + by a dot then anything. + > 0 means name must start with the first PREFIX_LENGTH chars of + PREFIX and finish with the last SUFFIX_LENGTH chars of PREFIX. */ + int suffix_length; + int type; + int attr; +}; + +enum action_discarded + { + COMPLAIN = 1, + PRETEND = 2 + }; + +typedef asection * (*elf_gc_mark_hook_fn) + (asection *, struct bfd_link_info *, Elf_Internal_Rela *, + struct elf_link_hash_entry *, Elf_Internal_Sym *); + +struct elf_backend_data +{ + /* The architecture for this backend. */ + enum bfd_architecture arch; + + /* The ELF machine code (EM_xxxx) for this backend. */ + int elf_machine_code; + + /* EI_OSABI. */ + int elf_osabi; + + /* The maximum page size for this backend. */ + bfd_vma maxpagesize; + + /* The minimum page size for this backend. An input object will not be + considered page aligned unless its sections are correctly aligned for + pages at least this large. May be smaller than maxpagesize. */ + bfd_vma minpagesize; + + /* The common page size for this backend. */ + bfd_vma commonpagesize; + + /* The BFD flags applied to sections created for dynamic linking. */ + flagword dynamic_sec_flags; + + /* A function to translate an ELF RELA relocation to a BFD arelent + structure. */ + void (*elf_info_to_howto) + (bfd *, arelent *, Elf_Internal_Rela *); + + /* A function to translate an ELF REL relocation to a BFD arelent + structure. */ + void (*elf_info_to_howto_rel) + (bfd *, arelent *, Elf_Internal_Rela *); + + /* A function to determine whether a symbol is global when + partitioning the symbol table into local and global symbols. + This should be NULL for most targets, in which case the correct + thing will be done. MIPS ELF, at least on the Irix 5, has + special requirements. */ + bfd_boolean (*elf_backend_sym_is_global) + (bfd *, asymbol *); + + /* The remaining functions are hooks which are called only if they + are not NULL. */ + + /* A function to permit a backend specific check on whether a + particular BFD format is relevant for an object file, and to + permit the backend to set any global information it wishes. When + this is called elf_elfheader is set, but anything else should be + used with caution. If this returns FALSE, the check_format + routine will return a bfd_error_wrong_format error. */ + bfd_boolean (*elf_backend_object_p) + (bfd *); + + /* A function to do additional symbol processing when reading the + ELF symbol table. This is where any processor-specific special + section indices are handled. */ + void (*elf_backend_symbol_processing) + (bfd *, asymbol *); + + /* A function to do additional symbol processing after reading the + entire ELF symbol table. */ + bfd_boolean (*elf_backend_symbol_table_processing) + (bfd *, elf_symbol_type *, unsigned int); + + /* A function to set the type of the info field. Processor-specific + types should be handled here. */ + int (*elf_backend_get_symbol_type) + (Elf_Internal_Sym *, int); + + /* A function to return the linker hash table entry of a symbol that + might be satisfied by an archive symbol. */ + struct elf_link_hash_entry * (*elf_backend_archive_symbol_lookup) + (bfd *, struct bfd_link_info *, const char *); + + /* Return true if local section symbols should have a non-null st_name. + NULL implies false. */ + bfd_boolean (*elf_backend_name_local_section_symbols) + (bfd *); + + /* A function to do additional processing on the ELF section header + just before writing it out. This is used to set the flags and + type fields for some sections, or to actually write out data for + unusual sections. */ + bfd_boolean (*elf_backend_section_processing) + (bfd *, Elf_Internal_Shdr *); + + /* A function to handle unusual section types when creating BFD + sections from ELF sections. */ + bfd_boolean (*elf_backend_section_from_shdr) + (bfd *, Elf_Internal_Shdr *, const char *, int); + + /* A function to convert machine dependent ELF section header flags to + BFD internal section header flags. */ + bfd_boolean (*elf_backend_section_flags) + (flagword *, const Elf_Internal_Shdr *); + + /* A function that returns a struct containing ELF section flags and + type for the given BFD section. */ + const struct bfd_elf_special_section * (*get_sec_type_attr) + (bfd *, asection *); + + /* A function to handle unusual program segment types when creating BFD + sections from ELF program segments. */ + bfd_boolean (*elf_backend_section_from_phdr) + (bfd *, Elf_Internal_Phdr *, int, const char *); + + /* A function to set up the ELF section header for a BFD section in + preparation for writing it out. This is where the flags and type + fields are set for unusual sections. */ + bfd_boolean (*elf_backend_fake_sections) + (bfd *, Elf_Internal_Shdr *, asection *); + + /* A function to get the ELF section index for a BFD section. If + this returns TRUE, the section was found. If it is a normal ELF + section, *RETVAL should be left unchanged. If it is not a normal + ELF section *RETVAL should be set to the SHN_xxxx index. */ + bfd_boolean (*elf_backend_section_from_bfd_section) + (bfd *, asection *, int *retval); + + /* If this field is not NULL, it is called by the add_symbols phase + of a link just before adding a symbol to the global linker hash + table. It may modify any of the fields as it wishes. If *NAME + is set to NULL, the symbol will be skipped rather than being + added to the hash table. This function is responsible for + handling all processor dependent symbol bindings and section + indices, and must set at least *FLAGS and *SEC for each processor + dependent case; failure to do so will cause a link error. */ + bfd_boolean (*elf_add_symbol_hook) + (bfd *abfd, struct bfd_link_info *info, Elf_Internal_Sym *, + const char **name, flagword *flags, asection **sec, bfd_vma *value); + + /* If this field is not NULL, it is called by the elf_link_output_sym + phase of a link for each symbol which will appear in the object file. */ + bfd_boolean (*elf_backend_link_output_symbol_hook) + (struct bfd_link_info *info, const char *, Elf_Internal_Sym *, + asection *, struct elf_link_hash_entry *); + + /* The CREATE_DYNAMIC_SECTIONS function is called by the ELF backend + linker the first time it encounters a dynamic object in the link. + This function must create any sections required for dynamic + linking. The ABFD argument is a dynamic object. The .interp, + .dynamic, .dynsym, .dynstr, and .hash functions have already been + created, and this function may modify the section flags if + desired. This function will normally create the .got and .plt + sections, but different backends have different requirements. */ + bfd_boolean (*elf_backend_create_dynamic_sections) + (bfd *abfd, struct bfd_link_info *info); + + /* When creating a shared library, determine whether to omit the + dynamic symbol for the section. */ + bfd_boolean (*elf_backend_omit_section_dynsym) + (bfd *output_bfd, struct bfd_link_info *info, asection *osec); + + /* The CHECK_RELOCS function is called by the add_symbols phase of + the ELF backend linker. It is called once for each section with + relocs of an object file, just after the symbols for the object + file have been added to the global linker hash table. The + function must look through the relocs and do any special handling + required. This generally means allocating space in the global + offset table, and perhaps allocating space for a reloc. The + relocs are always passed as Rela structures; if the section + actually uses Rel structures, the r_addend field will always be + zero. */ + bfd_boolean (*check_relocs) + (bfd *abfd, struct bfd_link_info *info, asection *o, + const Elf_Internal_Rela *relocs); + + /* The CHECK_DIRECTIVES function is called once per input file by + the add_symbols phase of the ELF backend linker. The function + must inspect the bfd and create any additional symbols according + to any custom directives in the bfd. */ + bfd_boolean (*check_directives) + (bfd *abfd, struct bfd_link_info *info); + + /* The AS_NEEDED_CLEANUP function is called once per --as-needed + input file that was not needed by the add_symbols phase of the + ELF backend linker. The function must undo any target specific + changes in the symbol hash table. */ + bfd_boolean (*as_needed_cleanup) + (bfd *abfd, struct bfd_link_info *info); + + /* The ADJUST_DYNAMIC_SYMBOL function is called by the ELF backend + linker for every symbol which is defined by a dynamic object and + referenced by a regular object. This is called after all the + input files have been seen, but before the SIZE_DYNAMIC_SECTIONS + function has been called. The hash table entry should be + bfd_link_hash_defined ore bfd_link_hash_defweak, and it should be + defined in a section from a dynamic object. Dynamic object + sections are not included in the final link, and this function is + responsible for changing the value to something which the rest of + the link can deal with. This will normally involve adding an + entry to the .plt or .got or some such section, and setting the + symbol to point to that. */ + bfd_boolean (*elf_backend_adjust_dynamic_symbol) + (struct bfd_link_info *info, struct elf_link_hash_entry *h); + + /* The ALWAYS_SIZE_SECTIONS function is called by the backend linker + after all the linker input files have been seen but before the + section sizes have been set. This is called after + ADJUST_DYNAMIC_SYMBOL, but before SIZE_DYNAMIC_SECTIONS. */ + bfd_boolean (*elf_backend_always_size_sections) + (bfd *output_bfd, struct bfd_link_info *info); + + /* The SIZE_DYNAMIC_SECTIONS function is called by the ELF backend + linker after all the linker input files have been seen but before + the sections sizes have been set. This is called after + ADJUST_DYNAMIC_SYMBOL has been called on all appropriate symbols. + It is only called when linking against a dynamic object. It must + set the sizes of the dynamic sections, and may fill in their + contents as well. The generic ELF linker can handle the .dynsym, + .dynstr and .hash sections. This function must handle the + .interp section and any sections created by the + CREATE_DYNAMIC_SECTIONS entry point. */ + bfd_boolean (*elf_backend_size_dynamic_sections) + (bfd *output_bfd, struct bfd_link_info *info); + + /* Set TEXT_INDEX_SECTION and DATA_INDEX_SECTION, the output sections + we keep to use as a base for relocs and symbols. */ + void (*elf_backend_init_index_section) + (bfd *output_bfd, struct bfd_link_info *info); + + /* The RELOCATE_SECTION function is called by the ELF backend linker + to handle the relocations for a section. + + The relocs are always passed as Rela structures; if the section + actually uses Rel structures, the r_addend field will always be + zero. + + This function is responsible for adjust the section contents as + necessary, and (if using Rela relocs and generating a + relocatable output file) adjusting the reloc addend as + necessary. + + This function does not have to worry about setting the reloc + address or the reloc symbol index. + + LOCAL_SYMS is a pointer to the swapped in local symbols. + + LOCAL_SECTIONS is an array giving the section in the input file + corresponding to the st_shndx field of each local symbol. + + The global hash table entry for the global symbols can be found + via elf_sym_hashes (input_bfd). + + When generating relocatable output, this function must handle + STB_LOCAL/STT_SECTION symbols specially. The output symbol is + going to be the section symbol corresponding to the output + section, which means that the addend must be adjusted + accordingly. + + Returns FALSE on error, TRUE on success, 2 if successful and + relocations should be written for this section. */ + int (*elf_backend_relocate_section) + (bfd *output_bfd, struct bfd_link_info *info, bfd *input_bfd, + asection *input_section, bfd_byte *contents, Elf_Internal_Rela *relocs, + Elf_Internal_Sym *local_syms, asection **local_sections); + + /* The FINISH_DYNAMIC_SYMBOL function is called by the ELF backend + linker just before it writes a symbol out to the .dynsym section. + The processor backend may make any required adjustment to the + symbol. It may also take the opportunity to set contents of the + dynamic sections. Note that FINISH_DYNAMIC_SYMBOL is called on + all .dynsym symbols, while ADJUST_DYNAMIC_SYMBOL is only called + on those symbols which are defined by a dynamic object. */ + bfd_boolean (*elf_backend_finish_dynamic_symbol) + (bfd *output_bfd, struct bfd_link_info *info, + struct elf_link_hash_entry *h, Elf_Internal_Sym *sym); + + /* The FINISH_DYNAMIC_SECTIONS function is called by the ELF backend + linker just before it writes all the dynamic sections out to the + output file. The FINISH_DYNAMIC_SYMBOL will have been called on + all dynamic symbols. */ + bfd_boolean (*elf_backend_finish_dynamic_sections) + (bfd *output_bfd, struct bfd_link_info *info); + + /* A function to do any beginning processing needed for the ELF file + before building the ELF headers and computing file positions. */ + void (*elf_backend_begin_write_processing) + (bfd *, struct bfd_link_info *); + + /* A function to do any final processing needed for the ELF file + before writing it out. The LINKER argument is TRUE if this BFD + was created by the ELF backend linker. */ + void (*elf_backend_final_write_processing) + (bfd *, bfd_boolean linker); + + /* This function is called by get_program_header_size. It should + return the number of additional program segments which this BFD + will need. It should return -1 on error. */ + int (*elf_backend_additional_program_headers) + (bfd *, struct bfd_link_info *); + + /* This function is called to modify an existing segment map in a + backend specific fashion. */ + bfd_boolean (*elf_backend_modify_segment_map) + (bfd *, struct bfd_link_info *); + + /* This function is called to modify program headers just before + they are written. */ + bfd_boolean (*elf_backend_modify_program_headers) + (bfd *, struct bfd_link_info *); + + /* This function is called during section garbage collection to + mark sections that define global symbols. */ + bfd_boolean (*gc_mark_dynamic_ref) + (struct elf_link_hash_entry *h, void *inf); + + /* This function is called during section gc to discover the section a + particular relocation refers to. */ + elf_gc_mark_hook_fn gc_mark_hook; + + /* This function, if defined, is called after the first gc marking pass + to allow the backend to mark additional sections. */ + bfd_boolean (*gc_mark_extra_sections) + (struct bfd_link_info *info, elf_gc_mark_hook_fn gc_mark_hook); + + /* This function, if defined, is called during the sweep phase of gc + in order that a backend might update any data structures it might + be maintaining. */ + bfd_boolean (*gc_sweep_hook) + (bfd *abfd, struct bfd_link_info *info, asection *o, + const Elf_Internal_Rela *relocs); + + /* This function, if defined, is called after the ELF headers have + been created. This allows for things like the OS and ABI versions + to be changed. */ + void (*elf_backend_post_process_headers) + (bfd *, struct bfd_link_info *); + + /* This function, if defined, prints a symbol to file and returns the + name of the symbol to be printed. It should return NULL to fall + back to default symbol printing. */ + const char *(*elf_backend_print_symbol_all) + (bfd *, void *, asymbol *); + + /* This function, if defined, is called after all local symbols and + global symbols converted to locals are emitted into the symtab + section. It allows the backend to emit special local symbols + not handled in the hash table. */ + bfd_boolean (*elf_backend_output_arch_local_syms) + (bfd *, struct bfd_link_info *, void *, + bfd_boolean (*) (void *, const char *, Elf_Internal_Sym *, asection *, + struct elf_link_hash_entry *)); + + /* This function, if defined, is called after all symbols are emitted + into the symtab section. It allows the backend to emit special + global symbols not handled in the hash table. */ + bfd_boolean (*elf_backend_output_arch_syms) + (bfd *, struct bfd_link_info *, void *, + bfd_boolean (*) (void *, const char *, Elf_Internal_Sym *, asection *, + struct elf_link_hash_entry *)); + + /* Copy any information related to dynamic linking from a pre-existing + symbol to a newly created symbol. Also called to copy flags and + other back-end info to a weakdef, in which case the symbol is not + newly created and plt/got refcounts and dynamic indices should not + be copied. */ + void (*elf_backend_copy_indirect_symbol) + (struct bfd_link_info *, struct elf_link_hash_entry *, + struct elf_link_hash_entry *); + + /* Modify any information related to dynamic linking such that the + symbol is not exported. */ + void (*elf_backend_hide_symbol) + (struct bfd_link_info *, struct elf_link_hash_entry *, bfd_boolean); + + /* A function to do additional symbol fixup, called by + _bfd_elf_fix_symbol_flags. */ + bfd_boolean (*elf_backend_fixup_symbol) + (struct bfd_link_info *, struct elf_link_hash_entry *); + + /* Merge the backend specific symbol attribute. */ + void (*elf_backend_merge_symbol_attribute) + (struct elf_link_hash_entry *, const Elf_Internal_Sym *, bfd_boolean, + bfd_boolean); + + /* Decide whether an undefined symbol is special and can be ignored. + This is the case for OPTIONAL symbols on IRIX. */ + bfd_boolean (*elf_backend_ignore_undef_symbol) + (struct elf_link_hash_entry *); + + /* Emit relocations. Overrides default routine for emitting relocs, + except during a relocatable link, or if all relocs are being emitted. */ + bfd_boolean (*elf_backend_emit_relocs) + (bfd *, asection *, Elf_Internal_Shdr *, Elf_Internal_Rela *, + struct elf_link_hash_entry **); + + /* Count relocations. Not called for relocatable links + or if all relocs are being preserved in the output. */ + unsigned int (*elf_backend_count_relocs) + (asection *, Elf_Internal_Rela *); + + /* This function, if defined, is called when an NT_PRSTATUS note is found + in a core file. */ + bfd_boolean (*elf_backend_grok_prstatus) + (bfd *, Elf_Internal_Note *); + + /* This function, if defined, is called when an NT_PSINFO or NT_PRPSINFO + note is found in a core file. */ + bfd_boolean (*elf_backend_grok_psinfo) + (bfd *, Elf_Internal_Note *); + + /* This function, if defined, is called to write a note to a corefile. */ + char *(*elf_backend_write_core_note) + (bfd *abfd, char *buf, int *bufsiz, int note_type, ...); + + /* Functions to print VMAs. Special code to handle 64 bit ELF files. */ + void (* elf_backend_sprintf_vma) + (bfd *, char *, bfd_vma); + void (* elf_backend_fprintf_vma) + (bfd *, void *, bfd_vma); + + /* This function returns class of a reloc type. */ + enum elf_reloc_type_class (*elf_backend_reloc_type_class) + (const Elf_Internal_Rela *); + + /* This function, if defined, removes information about discarded functions + from other sections which mention them. */ + bfd_boolean (*elf_backend_discard_info) + (bfd *, struct elf_reloc_cookie *, struct bfd_link_info *); + + /* This function, if defined, signals that the function above has removed + the discarded relocations for this section. */ + bfd_boolean (*elf_backend_ignore_discarded_relocs) + (asection *); + + /* What to do when ld finds relocations against symbols defined in + discarded sections. */ + unsigned int (*action_discarded) + (asection *); + + /* This function returns the width of FDE pointers in bytes, or 0 if + that can't be determined for some reason. The default definition + goes by the bfd's EI_CLASS. */ + unsigned int (*elf_backend_eh_frame_address_size) + (bfd *, asection *); + + /* These functions tell elf-eh-frame whether to attempt to turn + absolute or lsda encodings into pc-relative ones. The default + definition enables these transformations. */ + bfd_boolean (*elf_backend_can_make_relative_eh_frame) + (bfd *, struct bfd_link_info *, asection *); + bfd_boolean (*elf_backend_can_make_lsda_relative_eh_frame) + (bfd *, struct bfd_link_info *, asection *); + + /* This function returns an encoding after computing the encoded + value (and storing it in ENCODED) for the given OFFSET into OSEC, + to be stored in at LOC_OFFSET into the LOC_SEC input section. + The default definition chooses a 32-bit PC-relative encoding. */ + bfd_byte (*elf_backend_encode_eh_address) + (bfd *abfd, struct bfd_link_info *info, + asection *osec, bfd_vma offset, + asection *loc_sec, bfd_vma loc_offset, + bfd_vma *encoded); + + /* This function, if defined, may write out the given section. + Returns TRUE if it did so and FALSE if the caller should. */ + bfd_boolean (*elf_backend_write_section) + (bfd *, struct bfd_link_info *, asection *, bfd_byte *); + + /* The level of IRIX compatibility we're striving for. + MIPS ELF specific function. */ + irix_compat_t (*elf_backend_mips_irix_compat) + (bfd *); + + reloc_howto_type *(*elf_backend_mips_rtype_to_howto) + (unsigned int, bfd_boolean); + + /* The swapping table to use when dealing with ECOFF information. + Used for the MIPS ELF .mdebug section. */ + const struct ecoff_debug_swap *elf_backend_ecoff_debug_swap; + + /* This function implements `bfd_elf_bfd_from_remote_memory'; + see elf.c, elfcode.h. */ + bfd *(*elf_backend_bfd_from_remote_memory) + (bfd *templ, bfd_vma ehdr_vma, bfd_vma *loadbasep, + int (*target_read_memory) (bfd_vma vma, bfd_byte *myaddr, int len)); + + /* This function is used by `_bfd_elf_get_synthetic_symtab'; + see elf.c. */ + bfd_vma (*plt_sym_val) (bfd_vma, const asection *, const arelent *); + + /* Is symbol defined in common section? */ + bfd_boolean (*common_definition) (Elf_Internal_Sym *); + + /* Return a common section index for section. */ + unsigned int (*common_section_index) (asection *); + + /* Return a common section for section. */ + asection *(*common_section) (asection *); + + /* Return TRUE if we can merge 2 definitions. */ + bfd_boolean (*merge_symbol) (struct bfd_link_info *, + struct elf_link_hash_entry **, + struct elf_link_hash_entry *, + Elf_Internal_Sym *, asection **, + bfd_vma *, unsigned int *, + bfd_boolean *, bfd_boolean *, + bfd_boolean *, bfd_boolean *, + bfd_boolean *, bfd_boolean *, + bfd_boolean *, bfd_boolean *, + bfd *, asection **, + bfd_boolean *, bfd_boolean *, + bfd_boolean *, bfd_boolean *, + bfd *, asection **); + + /* Return TRUE if symbol should be hashed in the `.gnu.hash' section. */ + bfd_boolean (*elf_hash_symbol) (struct elf_link_hash_entry *); + + /* Return TRUE if type is a function symbol type. */ + bfd_boolean (*is_function_type) (unsigned int type); + + /* Used to handle bad SHF_LINK_ORDER input. */ + bfd_error_handler_type link_order_error_handler; + + /* Name of the PLT relocation section. */ + const char *relplt_name; + + /* Alternate EM_xxxx machine codes for this backend. */ + int elf_machine_alt1; + int elf_machine_alt2; + + const struct elf_size_info *s; + + /* An array of target specific special sections. */ + const struct bfd_elf_special_section *special_sections; + + /* The size in bytes of the header for the GOT. This includes the + so-called reserved entries on some systems. */ + bfd_vma got_header_size; + + /* The vendor name to use for a processor-standard attributes section. */ + const char *obj_attrs_vendor; + + /* The section name to use for a processor-standard attributes section. */ + const char *obj_attrs_section; + + /* Return 1, 2 or 3 to indicate what type of arguments a + processor-specific tag takes. */ + int (*obj_attrs_arg_type) (int); + + /* The section type to use for an attributes section. */ + unsigned int obj_attrs_section_type; + + /* This is TRUE if the linker should act like collect and gather + global constructors and destructors by name. This is TRUE for + MIPS ELF because the Irix 5 tools can not handle the .init + section. */ + unsigned collect : 1; + + /* This is TRUE if the linker should ignore changes to the type of a + symbol. This is TRUE for MIPS ELF because some Irix 5 objects + record undefined functions as STT_OBJECT although the definitions + are STT_FUNC. */ + unsigned type_change_ok : 1; + + /* Whether the backend may use REL relocations. (Some backends use + both REL and RELA relocations, and this flag is set for those + backends.) */ + unsigned may_use_rel_p : 1; + + /* Whether the backend may use RELA relocations. (Some backends use + both REL and RELA relocations, and this flag is set for those + backends.) */ + unsigned may_use_rela_p : 1; + + /* Whether the default relocation type is RELA. If a backend with + this flag set wants REL relocations for a particular section, + it must note that explicitly. Similarly, if this flag is clear, + and the backend wants RELA relocations for a particular + section. */ + unsigned default_use_rela_p : 1; + + /* Set if RELA relocations for a relocatable link can be handled by + generic code. Backends that set this flag need do nothing in the + backend relocate_section routine for relocatable linking. */ + unsigned rela_normal : 1; + + /* TRUE if addresses "naturally" sign extend. This is used when + swapping in from Elf32 when BFD64. */ + unsigned sign_extend_vma : 1; + + unsigned want_got_plt : 1; + unsigned plt_readonly : 1; + unsigned want_plt_sym : 1; + unsigned plt_not_loaded : 1; + unsigned plt_alignment : 4; + unsigned can_gc_sections : 1; + unsigned can_refcount : 1; + unsigned want_got_sym : 1; + unsigned want_dynbss : 1; + + /* Targets which do not support physical addressing often require + that the p_paddr field in the section header to be set to zero. + This field indicates whether this behavior is required. */ + unsigned want_p_paddr_set_to_zero : 1; + + /* True if an object file lacking a .note.GNU-stack section + should be assumed to be requesting exec stack. At least one + other file in the link needs to have a .note.GNU-stack section + for a PT_GNU_STACK segment to be created. */ + unsigned default_execstack : 1; +}; + +/* Information stored for each BFD section in an ELF file. This + structure is allocated by elf_new_section_hook. */ + +struct bfd_elf_section_data +{ + /* The ELF header for this section. */ + Elf_Internal_Shdr this_hdr; + + /* The ELF header for the reloc section associated with this + section, if any. */ + Elf_Internal_Shdr rel_hdr; + + /* If there is a second reloc section associated with this section, + as can happen on Irix 6, this field points to the header. */ + Elf_Internal_Shdr *rel_hdr2; + + /* The number of relocations currently assigned to REL_HDR. */ + unsigned int rel_count; + + /* The number of relocations currently assigned to REL_HDR2. */ + unsigned int rel_count2; + + /* The ELF section number of this section. */ + int this_idx; + + /* The ELF section number of the reloc section indicated by + REL_HDR if any. Only used for an output file. */ + int rel_idx; + + /* The ELF section number of the reloc section indicated by + REL_HDR2 if any. Only used for an output file. */ + int rel_idx2; + + /* Used by the backend linker when generating a shared library to + record the dynamic symbol index for a section symbol + corresponding to this section. A value of 0 means that there is + no dynamic symbol for this section. */ + int dynindx; + + /* A pointer to the linked-to section for SHF_LINK_ORDER. */ + asection *linked_to; + + /* Used by the backend linker to store the symbol hash table entries + associated with relocs against global symbols. */ + struct elf_link_hash_entry **rel_hashes; + + /* A pointer to the swapped relocs. If the section uses REL relocs, + rather than RELA, all the r_addend fields will be zero. This + pointer may be NULL. It is used by the backend linker. */ + Elf_Internal_Rela *relocs; + + /* A pointer to a linked list tracking dynamic relocs copied for + local symbols. */ + void *local_dynrel; + + /* A pointer to the bfd section used for dynamic relocs. */ + asection *sreloc; + + union { + /* Group name, if this section is a member of a group. */ + const char *name; + + /* Group signature sym, if this is the SHT_GROUP section. */ + struct bfd_symbol *id; + } group; + + /* For a member of a group, points to the SHT_GROUP section. + NULL for the SHT_GROUP section itself and non-group sections. */ + asection *sec_group; + + /* A linked list of member sections in the group. Circular when used by + the linker. For the SHT_GROUP section, points at first member. */ + asection *next_in_group; + + /* A pointer used for various section optimizations. */ + void *sec_info; +}; + +#define elf_section_data(sec) ((struct bfd_elf_section_data*)(sec)->used_by_bfd) +#define elf_linked_to_section(sec) (elf_section_data(sec)->linked_to) +#define elf_section_type(sec) (elf_section_data(sec)->this_hdr.sh_type) +#define elf_section_flags(sec) (elf_section_data(sec)->this_hdr.sh_flags) +#define elf_group_name(sec) (elf_section_data(sec)->group.name) +#define elf_group_id(sec) (elf_section_data(sec)->group.id) +#define elf_next_in_group(sec) (elf_section_data(sec)->next_in_group) +#define elf_sec_group(sec) (elf_section_data(sec)->sec_group) + +#define xvec_get_elf_backend_data(xvec) \ + ((const struct elf_backend_data *) (xvec)->backend_data) + +#define get_elf_backend_data(abfd) \ + xvec_get_elf_backend_data ((abfd)->xvec) + +/* This struct is used to pass information to routines called via + elf_link_hash_traverse which must return failure. */ + +struct elf_info_failed +{ + bfd_boolean failed; + struct bfd_link_info *info; + struct bfd_elf_version_tree *verdefs; +}; + +/* This structure is used to pass information to + _bfd_elf_link_assign_sym_version. */ + +struct elf_assign_sym_version_info +{ + /* Output BFD. */ + bfd *output_bfd; + /* General link information. */ + struct bfd_link_info *info; + /* Version tree. */ + struct bfd_elf_version_tree *verdefs; + /* Whether we had a failure. */ + bfd_boolean failed; +}; + +/* This structure is used to pass information to + _bfd_elf_link_find_version_dependencies. */ + +struct elf_find_verdep_info +{ + /* Output BFD. */ + bfd *output_bfd; + /* General link information. */ + struct bfd_link_info *info; + /* The number of dependencies. */ + unsigned int vers; + /* Whether we had a failure. */ + bfd_boolean failed; +}; + +/* The maximum number of known object attributes for any target. */ +#define NUM_KNOWN_OBJ_ATTRIBUTES 32 + +/* The value of an object attribute. type & 1 indicates whether there + is an integer value; type & 2 indicates whether there is a string + value. */ + +typedef struct obj_attribute +{ + int type; + unsigned int i; + char *s; +} obj_attribute; + +typedef struct obj_attribute_list +{ + struct obj_attribute_list *next; + int tag; + obj_attribute attr; +} obj_attribute_list; + +/* Object attributes may either be defined by the processor ABI, index + OBJ_ATTR_PROC in the *_obj_attributes arrays, or be GNU-specific + (and possibly also processor-specific), index OBJ_ATTR_GNU. */ +#define OBJ_ATTR_PROC 0 +#define OBJ_ATTR_GNU 1 +#define OBJ_ATTR_FIRST OBJ_ATTR_PROC +#define OBJ_ATTR_LAST OBJ_ATTR_GNU + +/* The following object attribute tags are taken as generic, for all + targets and for "gnu" where there is no target standard. */ +enum +{ + Tag_NULL = 0, + Tag_File = 1, + Tag_Section = 2, + Tag_Symbol = 3, + Tag_compatibility = 32 +}; + +/* Some private data is stashed away for future use using the tdata pointer + in the bfd structure. */ + +struct elf_obj_tdata +{ + Elf_Internal_Ehdr elf_header[1]; /* Actual data, but ref like ptr */ + Elf_Internal_Shdr **elf_sect_ptr; + Elf_Internal_Phdr *phdr; + struct elf_segment_map *segment_map; + struct elf_strtab_hash *strtab_ptr; + int num_locals; + int num_globals; + unsigned int num_elf_sections; /* elf_sect_ptr size */ + int num_section_syms; + asymbol **section_syms; /* STT_SECTION symbols for each section */ + Elf_Internal_Shdr symtab_hdr; + Elf_Internal_Shdr shstrtab_hdr; + Elf_Internal_Shdr strtab_hdr; + Elf_Internal_Shdr dynsymtab_hdr; + Elf_Internal_Shdr dynstrtab_hdr; + Elf_Internal_Shdr dynversym_hdr; + Elf_Internal_Shdr dynverref_hdr; + Elf_Internal_Shdr dynverdef_hdr; + Elf_Internal_Shdr symtab_shndx_hdr; + unsigned int symtab_section, shstrtab_section; + unsigned int strtab_section, dynsymtab_section; + unsigned int symtab_shndx_section; + unsigned int dynversym_section, dynverdef_section, dynverref_section; + file_ptr next_file_pos; + bfd_vma gp; /* The gp value */ + unsigned int gp_size; /* The gp size */ + + /* Information grabbed from an elf core file. */ + int core_signal; + int core_pid; + int core_lwpid; + char* core_program; + char* core_command; + + /* A mapping from external symbols to entries in the linker hash + table, used when linking. This is indexed by the symbol index + minus the sh_info field of the symbol table header. */ + struct elf_link_hash_entry **sym_hashes; + + /* Track usage and final offsets of GOT entries for local symbols. + This array is indexed by symbol index. Elements are used + identically to "got" in struct elf_link_hash_entry. */ + union + { + bfd_signed_vma *refcounts; + bfd_vma *offsets; + struct got_entry **ents; + } local_got; + + /* The linker ELF emulation code needs to let the backend ELF linker + know what filename should be used for a dynamic object if the + dynamic object is found using a search. The emulation code then + sometimes needs to know what name was actually used. Until the + file has been added to the linker symbol table, this field holds + the name the linker wants. After it has been added, it holds the + name actually used, which will be the DT_SONAME entry if there is + one. */ + const char *dt_name; + + /* Records the result of `get_program_header_size'. */ + bfd_size_type program_header_size; + + /* Used by find_nearest_line entry point. */ + void *line_info; + + /* Used by MIPS ELF find_nearest_line entry point. The structure + could be included directly in this one, but there's no point to + wasting the memory just for the infrequently called + find_nearest_line. */ + struct mips_elf_find_line *find_line_info; + + /* A place to stash dwarf1 info for this bfd. */ + struct dwarf1_debug *dwarf1_find_line_info; + + /* A place to stash dwarf2 info for this bfd. */ + void *dwarf2_find_line_info; + + /* An array of stub sections indexed by symbol number, used by the + MIPS ELF linker. FIXME: We should figure out some way to only + include this field for a MIPS ELF target. */ + asection **local_stubs; + asection **local_call_stubs; + + /* Used to determine if PT_GNU_EH_FRAME segment header should be + created. */ + asection *eh_frame_hdr; + + Elf_Internal_Shdr **group_sect_ptr; + int num_group; + + /* Number of symbol version definitions we are about to emit. */ + unsigned int cverdefs; + + /* Number of symbol version references we are about to emit. */ + unsigned int cverrefs; + + /* Segment flags for the PT_GNU_STACK segment. */ + unsigned int stack_flags; + + /* Should the PT_GNU_RELRO segment be emitted? */ + bfd_boolean relro; + + /* Symbol version definitions in external objects. */ + Elf_Internal_Verdef *verdef; + + /* Symbol version references to external objects. */ + Elf_Internal_Verneed *verref; + + /* The Irix 5 support uses two virtual sections, which represent + text/data symbols defined in dynamic objects. */ + asymbol *elf_data_symbol; + asymbol *elf_text_symbol; + asection *elf_data_section; + asection *elf_text_section; + + /* Whether a dyanmic object was specified normally on the linker + command line, or was specified when --as-needed was in effect, + or was found via a DT_NEEDED entry. */ + enum dynamic_lib_link_class dyn_lib_class; + + /* This is set to TRUE if the object was created by the backend + linker. */ + bfd_boolean linker; + + /* Irix 5 often screws up the symbol table, sorting local symbols + after global symbols. This flag is set if the symbol table in + this BFD appears to be screwed up. If it is, we ignore the + sh_info field in the symbol table header, and always read all the + symbols. */ + bfd_boolean bad_symtab; + + /* Used to determine if the e_flags field has been initialized */ + bfd_boolean flags_init; + + /* Symbol buffer. */ + void *symbuf; + + obj_attribute known_obj_attributes[2][NUM_KNOWN_OBJ_ATTRIBUTES]; + obj_attribute_list *other_obj_attributes[2]; + + /* Called at the end of _bfd_elf_write_object_contents if not NULL. */ + bfd_boolean (*after_write_object_contents) (bfd *); + void *after_write_object_contents_info; + + /* NT_GNU_BUILD_ID note type. */ + bfd_size_type build_id_size; + bfd_byte *build_id; +}; + +#define elf_tdata(bfd) ((bfd) -> tdata.elf_obj_data) +#define elf_elfheader(bfd) (elf_tdata(bfd) -> elf_header) +#define elf_elfsections(bfd) (elf_tdata(bfd) -> elf_sect_ptr) +#define elf_numsections(bfd) (elf_tdata(bfd) -> num_elf_sections) +#define elf_shstrtab(bfd) (elf_tdata(bfd) -> strtab_ptr) +#define elf_onesymtab(bfd) (elf_tdata(bfd) -> symtab_section) +#define elf_symtab_shndx(bfd) (elf_tdata(bfd) -> symtab_shndx_section) +#define elf_dynsymtab(bfd) (elf_tdata(bfd) -> dynsymtab_section) +#define elf_dynversym(bfd) (elf_tdata(bfd) -> dynversym_section) +#define elf_dynverdef(bfd) (elf_tdata(bfd) -> dynverdef_section) +#define elf_dynverref(bfd) (elf_tdata(bfd) -> dynverref_section) +#define elf_num_locals(bfd) (elf_tdata(bfd) -> num_locals) +#define elf_num_globals(bfd) (elf_tdata(bfd) -> num_globals) +#define elf_section_syms(bfd) (elf_tdata(bfd) -> section_syms) +#define elf_num_section_syms(bfd) (elf_tdata(bfd) -> num_section_syms) +#define core_prpsinfo(bfd) (elf_tdata(bfd) -> prpsinfo) +#define core_prstatus(bfd) (elf_tdata(bfd) -> prstatus) +#define elf_gp(bfd) (elf_tdata(bfd) -> gp) +#define elf_gp_size(bfd) (elf_tdata(bfd) -> gp_size) +#define elf_sym_hashes(bfd) (elf_tdata(bfd) -> sym_hashes) +#define elf_local_got_refcounts(bfd) (elf_tdata(bfd) -> local_got.refcounts) +#define elf_local_got_offsets(bfd) (elf_tdata(bfd) -> local_got.offsets) +#define elf_local_got_ents(bfd) (elf_tdata(bfd) -> local_got.ents) +#define elf_dt_name(bfd) (elf_tdata(bfd) -> dt_name) +#define elf_dyn_lib_class(bfd) (elf_tdata(bfd) -> dyn_lib_class) +#define elf_bad_symtab(bfd) (elf_tdata(bfd) -> bad_symtab) +#define elf_flags_init(bfd) (elf_tdata(bfd) -> flags_init) +#define elf_known_obj_attributes(bfd) (elf_tdata (bfd) -> known_obj_attributes) +#define elf_other_obj_attributes(bfd) (elf_tdata (bfd) -> other_obj_attributes) +#define elf_known_obj_attributes_proc(bfd) \ + (elf_known_obj_attributes (bfd) [OBJ_ATTR_PROC]) +#define elf_other_obj_attributes_proc(bfd) \ + (elf_other_obj_attributes (bfd) [OBJ_ATTR_PROC]) + +extern void _bfd_elf_swap_verdef_in + (bfd *, const Elf_External_Verdef *, Elf_Internal_Verdef *); +extern void _bfd_elf_swap_verdef_out + (bfd *, const Elf_Internal_Verdef *, Elf_External_Verdef *); +extern void _bfd_elf_swap_verdaux_in + (bfd *, const Elf_External_Verdaux *, Elf_Internal_Verdaux *); +extern void _bfd_elf_swap_verdaux_out + (bfd *, const Elf_Internal_Verdaux *, Elf_External_Verdaux *); +extern void _bfd_elf_swap_verneed_in + (bfd *, const Elf_External_Verneed *, Elf_Internal_Verneed *); +extern void _bfd_elf_swap_verneed_out + (bfd *, const Elf_Internal_Verneed *, Elf_External_Verneed *); +extern void _bfd_elf_swap_vernaux_in + (bfd *, const Elf_External_Vernaux *, Elf_Internal_Vernaux *); +extern void _bfd_elf_swap_vernaux_out + (bfd *, const Elf_Internal_Vernaux *, Elf_External_Vernaux *); +extern void _bfd_elf_swap_versym_in + (bfd *, const Elf_External_Versym *, Elf_Internal_Versym *); +extern void _bfd_elf_swap_versym_out + (bfd *, const Elf_Internal_Versym *, Elf_External_Versym *); + +extern int _bfd_elf_section_from_bfd_section + (bfd *, asection *); +extern char *bfd_elf_string_from_elf_section + (bfd *, unsigned, unsigned); +extern char *bfd_elf_get_str_section + (bfd *, unsigned); +extern Elf_Internal_Sym *bfd_elf_get_elf_syms + (bfd *, Elf_Internal_Shdr *, size_t, size_t, Elf_Internal_Sym *, void *, + Elf_External_Sym_Shndx *); +extern const char *bfd_elf_sym_name + (bfd *, Elf_Internal_Shdr *, Elf_Internal_Sym *, asection *); + +extern bfd_boolean _bfd_elf_copy_private_bfd_data + (bfd *, bfd *); +extern bfd_boolean _bfd_elf_print_private_bfd_data + (bfd *, void *); +extern void bfd_elf_print_symbol + (bfd *, void *, asymbol *, bfd_print_symbol_type); + +extern void _bfd_elf_sprintf_vma + (bfd *, char *, bfd_vma); +extern void _bfd_elf_fprintf_vma + (bfd *, void *, bfd_vma); + +extern unsigned int _bfd_elf_eh_frame_address_size + (bfd *, asection *); +extern bfd_byte _bfd_elf_encode_eh_address + (bfd *abfd, struct bfd_link_info *info, asection *osec, bfd_vma offset, + asection *loc_sec, bfd_vma loc_offset, bfd_vma *encoded); +extern bfd_boolean _bfd_elf_can_make_relative + (bfd *input_bfd, struct bfd_link_info *info, asection *eh_frame_section); + +extern enum elf_reloc_type_class _bfd_elf_reloc_type_class + (const Elf_Internal_Rela *); +extern bfd_vma _bfd_elf_rela_local_sym + (bfd *, Elf_Internal_Sym *, asection **, Elf_Internal_Rela *); +extern bfd_vma _bfd_elf_rel_local_sym + (bfd *, Elf_Internal_Sym *, asection **, bfd_vma); +extern bfd_vma _bfd_elf_section_offset + (bfd *, struct bfd_link_info *, asection *, bfd_vma); + +extern unsigned long bfd_elf_hash + (const char *); +extern unsigned long bfd_elf_gnu_hash + (const char *); + +extern bfd_reloc_status_type bfd_elf_generic_reloc + (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **); +extern bfd_boolean bfd_elf_mkobject + (bfd *); +extern bfd_boolean bfd_elf_mkcorefile + (bfd *); +extern Elf_Internal_Shdr *bfd_elf_find_section + (bfd *, char *); +extern bfd_boolean _bfd_elf_make_section_from_shdr + (bfd *, Elf_Internal_Shdr *, const char *, int); +extern bfd_boolean _bfd_elf_make_section_from_phdr + (bfd *, Elf_Internal_Phdr *, int, const char *); +extern struct bfd_hash_entry *_bfd_elf_link_hash_newfunc + (struct bfd_hash_entry *, struct bfd_hash_table *, const char *); +extern struct bfd_link_hash_table *_bfd_elf_link_hash_table_create + (bfd *); +extern void _bfd_elf_link_hash_copy_indirect + (struct bfd_link_info *, struct elf_link_hash_entry *, + struct elf_link_hash_entry *); +extern void _bfd_elf_link_hash_hide_symbol + (struct bfd_link_info *, struct elf_link_hash_entry *, bfd_boolean); +extern bfd_boolean _bfd_elf_link_hash_fixup_symbol + (struct bfd_link_info *, struct elf_link_hash_entry *); +extern bfd_boolean _bfd_elf_link_hash_table_init + (struct elf_link_hash_table *, bfd *, + struct bfd_hash_entry *(*) + (struct bfd_hash_entry *, struct bfd_hash_table *, const char *), + unsigned int); +extern bfd_boolean _bfd_elf_slurp_version_tables + (bfd *, bfd_boolean); +extern bfd_boolean _bfd_elf_merge_sections + (bfd *, struct bfd_link_info *); +extern bfd_boolean _bfd_elf_match_sections_by_type + (bfd *, const asection *, bfd *, const asection *); +extern bfd_boolean bfd_elf_is_group_section + (bfd *, const struct bfd_section *); +extern void _bfd_elf_section_already_linked + (bfd *, struct bfd_section *, struct bfd_link_info *); +extern void bfd_elf_set_group_contents + (bfd *, asection *, void *); +extern asection *_bfd_elf_check_kept_section + (asection *, struct bfd_link_info *); +extern void _bfd_elf_link_just_syms + (asection *, struct bfd_link_info *); +extern bfd_boolean _bfd_elf_copy_private_header_data + (bfd *, bfd *); +extern bfd_boolean _bfd_elf_copy_private_symbol_data + (bfd *, asymbol *, bfd *, asymbol *); +#define _bfd_generic_init_private_section_data \ + _bfd_elf_init_private_section_data +extern bfd_boolean _bfd_elf_init_private_section_data + (bfd *, asection *, bfd *, asection *, struct bfd_link_info *); +extern bfd_boolean _bfd_elf_copy_private_section_data + (bfd *, asection *, bfd *, asection *); +extern bfd_boolean _bfd_elf_write_object_contents + (bfd *); +extern bfd_boolean _bfd_elf_write_corefile_contents + (bfd *); +extern bfd_boolean _bfd_elf_set_section_contents + (bfd *, sec_ptr, const void *, file_ptr, bfd_size_type); +extern long _bfd_elf_get_symtab_upper_bound + (bfd *); +extern long _bfd_elf_canonicalize_symtab + (bfd *, asymbol **); +extern long _bfd_elf_get_dynamic_symtab_upper_bound + (bfd *); +extern long _bfd_elf_canonicalize_dynamic_symtab + (bfd *, asymbol **); +extern long _bfd_elf_get_synthetic_symtab + (bfd *, long, asymbol **, long, asymbol **, asymbol **); +extern long _bfd_elf_get_reloc_upper_bound + (bfd *, sec_ptr); +extern long _bfd_elf_canonicalize_reloc + (bfd *, sec_ptr, arelent **, asymbol **); +extern long _bfd_elf_get_dynamic_reloc_upper_bound + (bfd *); +extern long _bfd_elf_canonicalize_dynamic_reloc + (bfd *, arelent **, asymbol **); +extern asymbol *_bfd_elf_make_empty_symbol + (bfd *); +extern void _bfd_elf_get_symbol_info + (bfd *, asymbol *, symbol_info *); +extern bfd_boolean _bfd_elf_is_local_label_name + (bfd *, const char *); +extern alent *_bfd_elf_get_lineno + (bfd *, asymbol *); +extern bfd_boolean _bfd_elf_set_arch_mach + (bfd *, enum bfd_architecture, unsigned long); +extern bfd_boolean _bfd_elf_find_nearest_line + (bfd *, asection *, asymbol **, bfd_vma, const char **, const char **, + unsigned int *); +extern bfd_boolean _bfd_elf_find_line + (bfd *, asymbol **, asymbol *, const char **, unsigned int *); +#define _bfd_generic_find_line _bfd_elf_find_line +extern bfd_boolean _bfd_elf_find_inliner_info + (bfd *, const char **, const char **, unsigned int *); +#define _bfd_elf_read_minisymbols _bfd_generic_read_minisymbols +#define _bfd_elf_minisymbol_to_symbol _bfd_generic_minisymbol_to_symbol +extern int _bfd_elf_sizeof_headers + (bfd *, struct bfd_link_info *); +extern bfd_boolean _bfd_elf_new_section_hook + (bfd *, asection *); +extern bfd_boolean _bfd_elf_init_reloc_shdr + (bfd *, Elf_Internal_Shdr *, asection *, bfd_boolean); +extern const struct bfd_elf_special_section *_bfd_elf_get_special_section + (const char *, const struct bfd_elf_special_section *, unsigned int); +extern const struct bfd_elf_special_section *_bfd_elf_get_sec_type_attr + (bfd *, asection *); + +/* If the target doesn't have reloc handling written yet: */ +extern void _bfd_elf_no_info_to_howto + (bfd *, arelent *, Elf_Internal_Rela *); + +extern bfd_boolean bfd_section_from_shdr + (bfd *, unsigned int shindex); +extern bfd_boolean bfd_section_from_phdr + (bfd *, Elf_Internal_Phdr *, int); + +extern int _bfd_elf_symbol_from_bfd_symbol + (bfd *, asymbol **); + +extern asection *bfd_section_from_r_symndx + (bfd *, struct sym_sec_cache *, asection *, unsigned long); +extern asection *bfd_section_from_elf_index + (bfd *, unsigned int); +extern struct bfd_strtab_hash *_bfd_elf_stringtab_init + (void); + +extern struct elf_strtab_hash * _bfd_elf_strtab_init + (void); +extern void _bfd_elf_strtab_free + (struct elf_strtab_hash *); +extern bfd_size_type _bfd_elf_strtab_add + (struct elf_strtab_hash *, const char *, bfd_boolean); +extern void _bfd_elf_strtab_addref + (struct elf_strtab_hash *, bfd_size_type); +extern void _bfd_elf_strtab_delref + (struct elf_strtab_hash *, bfd_size_type); +extern void _bfd_elf_strtab_clear_all_refs + (struct elf_strtab_hash *); +extern bfd_size_type _bfd_elf_strtab_size + (struct elf_strtab_hash *); +extern bfd_size_type _bfd_elf_strtab_offset + (struct elf_strtab_hash *, bfd_size_type); +extern bfd_boolean _bfd_elf_strtab_emit + (bfd *, struct elf_strtab_hash *); +extern void _bfd_elf_strtab_finalize + (struct elf_strtab_hash *); + +extern bfd_boolean _bfd_elf_discard_section_eh_frame + (bfd *, struct bfd_link_info *, asection *, + bfd_boolean (*) (bfd_vma, void *), struct elf_reloc_cookie *); +extern bfd_boolean _bfd_elf_discard_section_eh_frame_hdr + (bfd *, struct bfd_link_info *); +extern bfd_vma _bfd_elf_eh_frame_section_offset + (bfd *, struct bfd_link_info *, asection *, bfd_vma); +extern bfd_boolean _bfd_elf_write_section_eh_frame + (bfd *, struct bfd_link_info *, asection *, bfd_byte *); +extern bfd_boolean _bfd_elf_write_section_eh_frame_hdr + (bfd *, struct bfd_link_info *); +extern bfd_boolean _bfd_elf_maybe_strip_eh_frame_hdr + (struct bfd_link_info *); + +extern bfd_boolean _bfd_elf_merge_symbol + (bfd *, struct bfd_link_info *, const char *, Elf_Internal_Sym *, + asection **, bfd_vma *, unsigned int *, + struct elf_link_hash_entry **, bfd_boolean *, + bfd_boolean *, bfd_boolean *, bfd_boolean *); + +extern bfd_boolean _bfd_elf_hash_symbol (struct elf_link_hash_entry *); + +extern bfd_boolean _bfd_elf_add_default_symbol + (bfd *, struct bfd_link_info *, struct elf_link_hash_entry *, + const char *, Elf_Internal_Sym *, asection **, bfd_vma *, + bfd_boolean *, bfd_boolean); + +extern bfd_boolean _bfd_elf_export_symbol + (struct elf_link_hash_entry *, void *); + +extern bfd_boolean _bfd_elf_link_find_version_dependencies + (struct elf_link_hash_entry *, void *); + +extern bfd_boolean _bfd_elf_link_assign_sym_version + (struct elf_link_hash_entry *, void *); + +extern long _bfd_elf_link_lookup_local_dynindx + (struct bfd_link_info *, bfd *, long); +extern bfd_boolean _bfd_elf_compute_section_file_positions + (bfd *, struct bfd_link_info *); +extern void _bfd_elf_assign_file_positions_for_relocs + (bfd *); +extern file_ptr _bfd_elf_assign_file_position_for_section + (Elf_Internal_Shdr *, file_ptr, bfd_boolean); + +extern bfd_boolean _bfd_elf_validate_reloc + (bfd *, arelent *); + +extern bfd_boolean _bfd_elf_link_create_dynamic_sections + (bfd *, struct bfd_link_info *); +extern bfd_boolean _bfd_elf_link_omit_section_dynsym + (bfd *, struct bfd_link_info *, asection *); +extern bfd_boolean _bfd_elf_create_dynamic_sections + (bfd *, struct bfd_link_info *); +extern bfd_boolean _bfd_elf_create_got_section + (bfd *, struct bfd_link_info *); +extern struct elf_link_hash_entry *_bfd_elf_define_linkage_sym + (bfd *, struct bfd_link_info *, asection *, const char *); +extern void _bfd_elf_init_1_index_section + (bfd *, struct bfd_link_info *); +extern void _bfd_elf_init_2_index_sections + (bfd *, struct bfd_link_info *); + +extern bfd_boolean _bfd_elfcore_make_pseudosection + (bfd *, char *, size_t, ufile_ptr); +extern char *_bfd_elfcore_strndup + (bfd *, char *, size_t); + +extern Elf_Internal_Rela *_bfd_elf_link_read_relocs + (bfd *, asection *, void *, Elf_Internal_Rela *, bfd_boolean); + +extern bfd_boolean _bfd_elf_link_size_reloc_section + (bfd *, Elf_Internal_Shdr *, asection *); + +extern bfd_boolean _bfd_elf_link_output_relocs + (bfd *, asection *, Elf_Internal_Shdr *, Elf_Internal_Rela *, + struct elf_link_hash_entry **); + +extern bfd_boolean _bfd_elf_fix_symbol_flags + (struct elf_link_hash_entry *, struct elf_info_failed *); + +extern bfd_boolean _bfd_elf_adjust_dynamic_symbol + (struct elf_link_hash_entry *, void *); + +extern bfd_boolean _bfd_elf_adjust_dynamic_copy + (struct elf_link_hash_entry *, asection *); + +extern bfd_boolean _bfd_elf_link_sec_merge_syms + (struct elf_link_hash_entry *, void *); + +extern bfd_boolean _bfd_elf_dynamic_symbol_p + (struct elf_link_hash_entry *, struct bfd_link_info *, bfd_boolean); + +extern bfd_boolean _bfd_elf_symbol_refs_local_p + (struct elf_link_hash_entry *, struct bfd_link_info *, bfd_boolean); + +extern bfd_boolean bfd_elf_match_symbols_in_sections + (asection *, asection *, struct bfd_link_info *); + +extern void bfd_elf_perform_complex_relocation + (bfd * output_bfd ATTRIBUTE_UNUSED, + struct bfd_link_info * info, + bfd * input_bfd, + asection * input_section, + bfd_byte * contents, + Elf_Internal_Rela * rel, + Elf_Internal_Sym * local_syms, + asection ** local_sections); + +extern bfd_boolean _bfd_elf_setup_sections + (bfd *); + +extern void _bfd_elf_set_osabi (bfd * , struct bfd_link_info *); + +extern const bfd_target *bfd_elf32_object_p + (bfd *); +extern const bfd_target *bfd_elf32_core_file_p + (bfd *); +extern char *bfd_elf32_core_file_failing_command + (bfd *); +extern int bfd_elf32_core_file_failing_signal + (bfd *); +extern bfd_boolean bfd_elf32_core_file_matches_executable_p + (bfd *, bfd *); + +extern bfd_boolean bfd_elf32_swap_symbol_in + (bfd *, const void *, const void *, Elf_Internal_Sym *); +extern void bfd_elf32_swap_symbol_out + (bfd *, const Elf_Internal_Sym *, void *, void *); +extern void bfd_elf32_swap_reloc_in + (bfd *, const bfd_byte *, Elf_Internal_Rela *); +extern void bfd_elf32_swap_reloc_out + (bfd *, const Elf_Internal_Rela *, bfd_byte *); +extern void bfd_elf32_swap_reloca_in + (bfd *, const bfd_byte *, Elf_Internal_Rela *); +extern void bfd_elf32_swap_reloca_out + (bfd *, const Elf_Internal_Rela *, bfd_byte *); +extern void bfd_elf32_swap_phdr_in + (bfd *, const Elf32_External_Phdr *, Elf_Internal_Phdr *); +extern void bfd_elf32_swap_phdr_out + (bfd *, const Elf_Internal_Phdr *, Elf32_External_Phdr *); +extern void bfd_elf32_swap_dyn_in + (bfd *, const void *, Elf_Internal_Dyn *); +extern void bfd_elf32_swap_dyn_out + (bfd *, const Elf_Internal_Dyn *, void *); +extern long bfd_elf32_slurp_symbol_table + (bfd *, asymbol **, bfd_boolean); +extern bfd_boolean bfd_elf32_write_shdrs_and_ehdr + (bfd *); +extern int bfd_elf32_write_out_phdrs + (bfd *, const Elf_Internal_Phdr *, unsigned int); +extern bfd_boolean bfd_elf32_checksum_contents + (bfd * , void (*) (const void *, size_t, void *), void *); +extern void bfd_elf32_write_relocs + (bfd *, asection *, void *); +extern bfd_boolean bfd_elf32_slurp_reloc_table + (bfd *, asection *, asymbol **, bfd_boolean); + +extern const bfd_target *bfd_elf64_object_p + (bfd *); +extern const bfd_target *bfd_elf64_core_file_p + (bfd *); +extern char *bfd_elf64_core_file_failing_command + (bfd *); +extern int bfd_elf64_core_file_failing_signal + (bfd *); +extern bfd_boolean bfd_elf64_core_file_matches_executable_p + (bfd *, bfd *); + +extern bfd_boolean bfd_elf64_swap_symbol_in + (bfd *, const void *, const void *, Elf_Internal_Sym *); +extern void bfd_elf64_swap_symbol_out + (bfd *, const Elf_Internal_Sym *, void *, void *); +extern void bfd_elf64_swap_reloc_in + (bfd *, const bfd_byte *, Elf_Internal_Rela *); +extern void bfd_elf64_swap_reloc_out + (bfd *, const Elf_Internal_Rela *, bfd_byte *); +extern void bfd_elf64_swap_reloca_in + (bfd *, const bfd_byte *, Elf_Internal_Rela *); +extern void bfd_elf64_swap_reloca_out + (bfd *, const Elf_Internal_Rela *, bfd_byte *); +extern void bfd_elf64_swap_phdr_in + (bfd *, const Elf64_External_Phdr *, Elf_Internal_Phdr *); +extern void bfd_elf64_swap_phdr_out + (bfd *, const Elf_Internal_Phdr *, Elf64_External_Phdr *); +extern void bfd_elf64_swap_dyn_in + (bfd *, const void *, Elf_Internal_Dyn *); +extern void bfd_elf64_swap_dyn_out + (bfd *, const Elf_Internal_Dyn *, void *); +extern long bfd_elf64_slurp_symbol_table + (bfd *, asymbol **, bfd_boolean); +extern bfd_boolean bfd_elf64_write_shdrs_and_ehdr + (bfd *); +extern int bfd_elf64_write_out_phdrs + (bfd *, const Elf_Internal_Phdr *, unsigned int); +extern bfd_boolean bfd_elf64_checksum_contents + (bfd * , void (*) (const void *, size_t, void *), void *); +extern void bfd_elf64_write_relocs + (bfd *, asection *, void *); +extern bfd_boolean bfd_elf64_slurp_reloc_table + (bfd *, asection *, asymbol **, bfd_boolean); + +extern struct elf_link_hash_entry *_bfd_elf_archive_symbol_lookup + (bfd *, struct bfd_link_info *, const char *); +extern bfd_boolean bfd_elf_link_add_symbols + (bfd *, struct bfd_link_info *); +extern bfd_boolean _bfd_elf_add_dynamic_entry + (struct bfd_link_info *, bfd_vma, bfd_vma); + +extern bfd_boolean bfd_elf_link_record_dynamic_symbol + (struct bfd_link_info *, struct elf_link_hash_entry *); + +extern int bfd_elf_link_record_local_dynamic_symbol + (struct bfd_link_info *, bfd *, long); + +extern void bfd_elf_link_mark_dynamic_symbol + (struct bfd_link_info *, struct elf_link_hash_entry *, + Elf_Internal_Sym *); + +extern bfd_boolean _bfd_elf_close_and_cleanup + (bfd *); + +extern bfd_boolean _bfd_elf_common_definition + (Elf_Internal_Sym *); + +extern unsigned int _bfd_elf_common_section_index + (asection *); + +extern asection *_bfd_elf_common_section + (asection *); + +extern void _bfd_dwarf2_cleanup_debug_info + (bfd *); + +extern bfd_reloc_status_type _bfd_elf_rel_vtable_reloc_fn + (bfd *, arelent *, struct bfd_symbol *, void *, + asection *, bfd *, char **); + +extern bfd_boolean bfd_elf_final_link + (bfd *, struct bfd_link_info *); + +extern bfd_boolean bfd_elf_gc_mark_dynamic_ref_symbol + (struct elf_link_hash_entry *h, void *inf); + +extern bfd_boolean bfd_elf_gc_sections + (bfd *, struct bfd_link_info *); + +extern bfd_boolean bfd_elf_gc_record_vtinherit + (bfd *, asection *, struct elf_link_hash_entry *, bfd_vma); + +extern bfd_boolean bfd_elf_gc_record_vtentry + (bfd *, asection *, struct elf_link_hash_entry *, bfd_vma); + +extern asection *_bfd_elf_gc_mark_hook + (asection *, struct bfd_link_info *, Elf_Internal_Rela *, + struct elf_link_hash_entry *, Elf_Internal_Sym *); + +extern bfd_boolean _bfd_elf_gc_mark + (struct bfd_link_info *, asection *, + asection * (*) (asection *, struct bfd_link_info *, Elf_Internal_Rela *, + struct elf_link_hash_entry *, Elf_Internal_Sym *)); + +extern bfd_boolean bfd_elf_gc_common_finalize_got_offsets + (bfd *, struct bfd_link_info *); + +extern bfd_boolean bfd_elf_gc_common_final_link + (bfd *, struct bfd_link_info *); + +extern bfd_boolean bfd_elf_reloc_symbol_deleted_p + (bfd_vma, void *); + +extern struct elf_segment_map * _bfd_elf_make_dynamic_segment + (bfd *, asection *); + +extern bfd_boolean _bfd_elf_map_sections_to_segments + (bfd *, struct bfd_link_info *); + +extern bfd_boolean _bfd_elf_is_function_type (unsigned int); + +/* Exported interface for writing elf corefile notes. */ +extern char *elfcore_write_note + (bfd *, char *, int *, const char *, int, const void *, int); +extern char *elfcore_write_prpsinfo + (bfd *, char *, int *, const char *, const char *); +extern char *elfcore_write_prstatus + (bfd *, char *, int *, long, int, const void *); +extern char * elfcore_write_pstatus + (bfd *, char *, int *, long, int, const void *); +extern char *elfcore_write_prfpreg + (bfd *, char *, int *, const void *, int); +extern char *elfcore_write_prxfpreg + (bfd *, char *, int *, const void *, int); +extern char *elfcore_write_lwpstatus + (bfd *, char *, int *, long, int, const void *); + +extern bfd *_bfd_elf32_bfd_from_remote_memory + (bfd *templ, bfd_vma ehdr_vma, bfd_vma *loadbasep, + int (*target_read_memory) (bfd_vma, bfd_byte *, int)); +extern bfd *_bfd_elf64_bfd_from_remote_memory + (bfd *templ, bfd_vma ehdr_vma, bfd_vma *loadbasep, + int (*target_read_memory) (bfd_vma, bfd_byte *, int)); + +extern bfd_vma bfd_elf_obj_attr_size (bfd *); +extern void bfd_elf_set_obj_attr_contents (bfd *, bfd_byte *, bfd_vma); +extern int bfd_elf_get_obj_attr_int (bfd *, int, int); +extern void bfd_elf_add_obj_attr_int (bfd *, int, int, unsigned int); +#define bfd_elf_add_proc_attr_int(BFD, TAG, VALUE) \ + bfd_elf_add_obj_attr_int ((BFD), OBJ_ATTR_PROC, (TAG), (VALUE)) +extern void bfd_elf_add_obj_attr_string (bfd *, int, int, const char *); +#define bfd_elf_add_proc_attr_string(BFD, TAG, VALUE) \ + bfd_elf_add_obj_attr_string ((BFD), OBJ_ATTR_PROC, (TAG), (VALUE)) +extern void bfd_elf_add_obj_attr_compat (bfd *, int, unsigned int, + const char *); +#define bfd_elf_add_proc_attr_compat(BFD, INTVAL, STRVAL) \ + bfd_elf_add_obj_attr_compat ((BFD), OBJ_ATTR_PROC, (INTVAL), (STRVAL)) + +extern char *_bfd_elf_attr_strdup (bfd *, const char *); +extern void _bfd_elf_copy_obj_attributes (bfd *, bfd *); +extern int _bfd_elf_obj_attrs_arg_type (bfd *, int, int); +extern void _bfd_elf_parse_attributes (bfd *, Elf_Internal_Shdr *); +extern bfd_boolean _bfd_elf_merge_object_attributes (bfd *, bfd *); + +/* Large common section. */ +extern asection _bfd_elf_large_com_section; + +/* SH ELF specific routine. */ + +extern bfd_boolean _sh_elf_set_mach_from_flags + (bfd *); + +/* This is the condition under which finish_dynamic_symbol will be called. + If our finish_dynamic_symbol isn't called, we'll need to do something + about initializing any .plt and .got entries in relocate_section. */ +#define WILL_CALL_FINISH_DYNAMIC_SYMBOL(DYN, SHARED, H) \ + ((DYN) \ + && ((SHARED) || !(H)->forced_local) \ + && ((H)->dynindx != -1 || (H)->forced_local)) + +/* This macro is to avoid lots of duplicated code in the body + of xxx_relocate_section() in the various elfxx-xxxx.c files. */ +#define RELOC_FOR_GLOBAL_SYMBOL(info, input_bfd, input_section, rel, \ + r_symndx, symtab_hdr, sym_hashes, \ + h, sec, relocation, \ + unresolved_reloc, warned) \ + do \ + { \ + /* It seems this can happen with erroneous or unsupported \ + input (mixing a.out and elf in an archive, for example.) */ \ + if (sym_hashes == NULL) \ + return FALSE; \ + \ + h = sym_hashes[r_symndx - symtab_hdr->sh_info]; \ + \ + while (h->root.type == bfd_link_hash_indirect \ + || h->root.type == bfd_link_hash_warning) \ + h = (struct elf_link_hash_entry *) h->root.u.i.link; \ + \ + warned = FALSE; \ + unresolved_reloc = FALSE; \ + relocation = 0; \ + if (h->root.type == bfd_link_hash_defined \ + || h->root.type == bfd_link_hash_defweak) \ + { \ + sec = h->root.u.def.section; \ + if (sec == NULL \ + || sec->output_section == NULL) \ + /* Set a flag that will be cleared later if we find a \ + relocation value for this symbol. output_section \ + is typically NULL for symbols satisfied by a shared \ + library. */ \ + unresolved_reloc = TRUE; \ + else \ + relocation = (h->root.u.def.value \ + + sec->output_section->vma \ + + sec->output_offset); \ + } \ + else if (h->root.type == bfd_link_hash_undefweak) \ + ; \ + else if (info->unresolved_syms_in_objects == RM_IGNORE \ + && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT) \ + ; \ + else if (!info->relocatable) \ + { \ + bfd_boolean err; \ + err = (info->unresolved_syms_in_objects == RM_GENERATE_ERROR \ + || ELF_ST_VISIBILITY (h->other) != STV_DEFAULT); \ + if (!info->callbacks->undefined_symbol (info, \ + h->root.root.string, \ + input_bfd, \ + input_section, \ + rel->r_offset, err)) \ + return FALSE; \ + warned = TRUE; \ + } \ + } \ + while (0) + +/* Will a symbol be bound to the the definition within the shared + library, if any. */ +#define SYMBOLIC_BIND(INFO, H) \ + ((INFO)->symbolic || ((INFO)->dynamic && !(H)->dynamic)) + +#endif /* _LIBELF_H_ */ diff --git a/kernel/fiasco/src/lib/disasm/bfd/libbfd.c b/kernel/fiasco/src/lib/disasm/bfd/libbfd.c new file mode 100644 index 00000000..f2696f89 --- /dev/null +++ b/kernel/fiasco/src/lib/disasm/bfd/libbfd.c @@ -0,0 +1,28 @@ +#include "libbfd.h" +#include "bfd.h" + +bfd_vma +bfd_getb32 (const void *p) +{ + const bfd_byte *addr = p; + unsigned long v; + + v = (unsigned long) addr[0] << 24; + v |= (unsigned long) addr[1] << 16; + v |= (unsigned long) addr[2] << 8; + v |= (unsigned long) addr[3]; + return v; +} + +bfd_vma +bfd_getl32 (const void *p) +{ + const bfd_byte *addr = p; + unsigned long v; + + v = (unsigned long) addr[0]; + v |= (unsigned long) addr[1] << 8; + v |= (unsigned long) addr[2] << 16; + v |= (unsigned long) addr[3] << 24; + return v; +} diff --git a/kernel/fiasco/src/lib/disasm/bfd/libbfd.h b/kernel/fiasco/src/lib/disasm/bfd/libbfd.h new file mode 100644 index 00000000..337ec0a2 --- /dev/null +++ b/kernel/fiasco/src/lib/disasm/bfd/libbfd.h @@ -0,0 +1,7 @@ +#pragma once + +#include "bfd.h" + +bfd_vma bfd_getb32 (const void *p); +bfd_vma bfd_getl32 (const void *p); + diff --git a/kernel/fiasco/src/lib/disasm/disasm.cc b/kernel/fiasco/src/lib/disasm/disasm.cc new file mode 100644 index 00000000..3be28ca7 --- /dev/null +++ b/kernel/fiasco/src/lib/disasm/disasm.cc @@ -0,0 +1,242 @@ + +#include +#include +#include + +#include "include/dis-asm.h" +#include "disasm.h" + +/* local variables */ +static char *out_buf; +static int out_len; +static int use_syms; +static Space *dis_task; +static disassemble_info dis_info; +static Peek_task dis_peek_task; +static Get_symbol dis_get_symbol; + +extern int print_insn_i386 PARAMS ((bfd_vma, disassemble_info*)); + +/* read bytes starting at memaddr */ +static int +my_read_memory(bfd_vma memaddr, bfd_byte *myaddr, unsigned length, + disassemble_info *info __attribute__ ((unused))) +{ + unsigned i; + + for (i=0; ifprintf_func)(info->stream, "%s", buf); + } +} + +static int +my_printf(void* stream __attribute__ ((unused)), const char *format, ...) +{ + if (out_len) + { + int len; + va_list list; + + va_start(list, format); + len = vsnprintf(out_buf, out_len, format, list); + if (len >= out_len) + len = out_len - 1; + out_buf += len; + out_len -= len; + va_end(list); + } + + return 0; +} + +static void +my_putchar(int c) +{ + if (out_len) + { + out_len--; + *out_buf++ = c; + } +} + +/* check for special L4 int3-opcodes */ +static int +special_l4_ops(bfd_vma memaddr) +{ + int len, bytes, i; + const char *op; + bfd_vma str, s; + + switch (my_get_data(memaddr)) + { + case 0xeb: + op = "enter_kdebug"; + len = my_get_data(memaddr+1); + str = memaddr+2; + bytes = 3+len; + goto printstr; + case 0x90: + if (my_get_data(memaddr+1) != 0xeb) + break; + op = "kd_display"; + len = my_get_data(memaddr+2); + str = memaddr+3; + bytes = 4+len; + printstr: + /* do a quick test if it is really an int3-str function by + * analyzing the bytes we shall display. */ + for (i=len, s=str; i--; ) + if (my_get_data(s++) > 126) + return 0; + /* test well done */ + my_printf(0, "<%s (\"", op); + if ((out_len > 2) && (len > 0)) + { + out_len -= 3; + if (out_len > len) + out_len = len; + /* do not use my_printf here because the string + * can contain special characters (e.g. tabs) which + * we do not want to display */ + while (out_len) + { + unsigned char c = my_get_data(str++); + my_putchar((c<' ') ? ' ' : c); + } + out_len += 3; + } + my_printf(0, "\")>"); + return bytes; + case 0x3c: + op = NULL; + switch (my_get_data(memaddr+1)) + { + case 0: op = "outchar (%al)"; break; + case 2: op = "outstring (*%eax)"; break; + case 5: op = "outhex32 (%eax)"; break; + case 6: op = "outhex20 (%eax)"; break; + case 7: op = "outhex16 (%eax)"; break; + case 8: op = "outhex12 (%eax)"; break; + case 9: op = "outhex8 (%al)"; break; + case 11: op = "outdec (%eax)"; break; + case 13: op = "%al = inchar ()"; break; + case 24: op = "fiasco_start_profile()"; break; + case 25: op = "fiasco_stop_and_dump()"; break; + case 26: op = "fiasco_stop_profile()"; break; + case 29: op = "fiasco_tbuf (%eax)"; break; + case 30: op = "fiasco_register (%eax, %ecx)"; break; + } + if (op) + my_printf(0, "<%s>", op); + else if (my_get_data(memaddr+1) >= ' ') + my_printf(0, "", my_get_data(memaddr+1)); + else break; + return 3; + } + + return 0; +} + +/* WARNING: This function is not reentrant because it accesses some + * global static variables (out_buf, out_len, dis_task, ...) */ +unsigned int +disasm_bytes(char *buffer, unsigned len, Address addr, + Space *task, int show_symbols, int show_intel_syntax, + Peek_task peek_task, Get_symbol get_symbol) +{ + use_syms = show_symbols; + out_buf = buffer; + out_len = len; + dis_task = task; + dis_peek_task = peek_task; + dis_get_symbol = get_symbol; + + /* terminate string */ + if (out_len) + out_buf[--out_len] = '\0'; + + /* test for special L4 opcodes */ + if (my_get_data(addr) == 0xcc && (len = special_l4_ops(addr+1))) + return len; + + /* one step back for special L4 opcodes */ + if (my_get_data(addr-1) == 0xcc && (len = special_l4_ops(addr))) + return len-1; + + INIT_DISASSEMBLE_INFO(dis_info, NULL, my_printf); + + dis_info.print_address_func = my_print_address; + dis_info.read_memory_func = my_read_memory; + dis_info.buffer = (bfd_byte*)addr; + dis_info.buffer_length = 99; /* XXX */ + dis_info.buffer_vma = addr; +#if defined CONFIG_ARM + dis_info.mach = bfd_mach_arm_5; + return print_insn_little_arm (addr, &dis_info); +#elif defined CONFIG_PPC32 + dis_info.mach = bfd_mach_ppc_ec603e; + return print_insn_big_powerpc(addr, &dis_info); +#elif defined CONFIG_IA32 + dis_info.mach = show_intel_syntax ? bfd_mach_i386_i386_intel_syntax + : bfd_mach_i386_i386; + return print_insn_i386 (addr, &dis_info); +#elif defined CONFIG_AMD64 + dis_info.mach = show_intel_syntax ? bfd_mach_x86_64_intel_syntax + : bfd_mach_x86_64; + return print_insn_i386 (addr, &dis_info); +#elif defined CONFIG_SPARC + dis_info.mach = bfd_mach_sparc_v8plusa; + return print_insn_sparc(addr, &dis_info); +#else +#error Unknown architecture +#endif + (void)show_intel_syntax; +} diff --git a/kernel/fiasco/src/lib/disasm/disasm.h b/kernel/fiasco/src/lib/disasm/disasm.h new file mode 100644 index 00000000..647402d0 --- /dev/null +++ b/kernel/fiasco/src/lib/disasm/disasm.h @@ -0,0 +1,16 @@ +#pragma once + +#include "types.h" +#include "globalconfig.h" + +class Space; + +typedef int (*Peek_task)(Address addr, Space *task, void *value, int width); +typedef const char* (*Get_symbol)(Address addr, Space *task); + +extern unsigned int +disasm_bytes(char *buffer, unsigned len, Address addr, + Space *task, int show_symbols, int show_intel_syntax, + Peek_task peek_task, Get_symbol get_symbol); + + diff --git a/kernel/fiasco/src/lib/disasm/elf/arm.h b/kernel/fiasco/src/lib/disasm/elf/arm.h new file mode 100644 index 00000000..e7018833 --- /dev/null +++ b/kernel/fiasco/src/lib/disasm/elf/arm.h @@ -0,0 +1,287 @@ +/* ARM ELF support for BFD. + Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004 + Free Software Foundation, Inc. + + This file is part of BFD, the Binary File Descriptor library. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ + +#ifndef _ELF_ARM_H +#define _ELF_ARM_H + +#include "elf/reloc-macros.h" + +/* Processor specific flags for the ELF header e_flags field. */ +#define EF_ARM_RELEXEC 0x01 +#define EF_ARM_HASENTRY 0x02 +#define EF_ARM_INTERWORK 0x04 +#define EF_ARM_APCS_26 0x08 +#define EF_ARM_APCS_FLOAT 0x10 +#define EF_ARM_PIC 0x20 +#define EF_ARM_ALIGN8 0x40 /* 8-bit structure alignment is in use. */ +#define EF_ARM_NEW_ABI 0x80 +#define EF_ARM_OLD_ABI 0x100 +#define EF_ARM_SOFT_FLOAT 0x200 +#define EF_ARM_VFP_FLOAT 0x400 +#define EF_ARM_MAVERICK_FLOAT 0x800 + +/* Frame unwind information */ +#define PT_ARM_EXIDX (PT_LOPROC + 1) + +/* Other constants defined in the ARM ELF spec. version B-01. */ +#define EF_ARM_SYMSARESORTED 0x04 /* NB conflicts with EF_INTERWORK */ +#define EF_ARM_DYNSYMSUSESEGIDX 0x08 /* NB conflicts with EF_APCS26 */ +#define EF_ARM_MAPSYMSFIRST 0x10 /* NB conflicts with EF_APCS_FLOAT */ +#define EF_ARM_EABIMASK 0xFF000000 + +/* Constants defined in AAELF. */ +#define EF_ARM_BE8 0x00800000 +#define EF_ARM_LE8 0x00400000 + +#define EF_ARM_EABI_VERSION(flags) ((flags) & EF_ARM_EABIMASK) +#define EF_ARM_EABI_UNKNOWN 0x00000000 +#define EF_ARM_EABI_VER1 0x01000000 +#define EF_ARM_EABI_VER2 0x02000000 +#define EF_ARM_EABI_VER3 0x03000000 +#define EF_ARM_EABI_VER4 0x04000000 +#define EF_ARM_EABI_VER5 0x05000000 + +/* Local aliases for some flags to match names used by COFF port. */ +#define F_INTERWORK EF_ARM_INTERWORK +#define F_APCS26 EF_ARM_APCS_26 +#define F_APCS_FLOAT EF_ARM_APCS_FLOAT +#define F_PIC EF_ARM_PIC +#define F_SOFT_FLOAT EF_ARM_SOFT_FLOAT +#define F_VFP_FLOAT EF_ARM_VFP_FLOAT + +/* Additional symbol types for Thumb. */ +#define STT_ARM_TFUNC STT_LOPROC /* A Thumb function. */ +#define STT_ARM_16BIT STT_HIPROC /* A Thumb label. */ + +/* Additional section types. */ +#define SHT_ARM_EXIDX 0x70000001 /* Section holds ARM unwind info. */ +#define SHT_ARM_PREEMPTMAP 0x70000002 /* Section pre-emption details. */ +#define SHT_ARM_ATTRIBUTES 0x70000003 /* Section holds attributes. */ + +/* ARM-specific values for sh_flags. */ +#define SHF_ENTRYSECT 0x10000000 /* Section contains an entry point. */ +#define SHF_COMDEF 0x80000000 /* Section may be multiply defined in the input to a link step. */ + +/* ARM-specific program header flags. */ +#define PF_ARM_SB 0x10000000 /* Segment contains the location addressed by the static base. */ +#define PF_ARM_PI 0x20000000 /* Segment is position-independent. */ +#define PF_ARM_ABS 0x40000000 /* Segment must be loaded at its base address. */ + +/* Values for the Tag_CPU_arch EABI attribute. */ +#define TAG_CPU_ARCH_PRE_V4 0 +#define TAG_CPU_ARCH_V4 1 +#define TAG_CPU_ARCH_V4T 2 +#define TAG_CPU_ARCH_V5T 3 +#define TAG_CPU_ARCH_V5TE 4 +#define TAG_CPU_ARCH_V5TEJ 5 +#define TAG_CPU_ARCH_V6 6 +#define TAG_CPU_ARCH_V6KZ 7 +#define TAG_CPU_ARCH_V6T2 8 +#define TAG_CPU_ARCH_V6K 9 +#define TAG_CPU_ARCH_V7 10 + +/* Relocation types. */ + +START_RELOC_NUMBERS (elf_arm_reloc_type) +/* AAELF official names and numbers. */ + RELOC_NUMBER (R_ARM_NONE, 0) + RELOC_NUMBER (R_ARM_PC24, 1) /* deprecated */ + RELOC_NUMBER (R_ARM_ABS32, 2) + RELOC_NUMBER (R_ARM_REL32, 3) + RELOC_NUMBER (R_ARM_LDR_PC_G0, 4) + RELOC_NUMBER (R_ARM_ABS16, 5) + RELOC_NUMBER (R_ARM_ABS12, 6) + RELOC_NUMBER (R_ARM_THM_ABS5, 7) + RELOC_NUMBER (R_ARM_ABS8, 8) + RELOC_NUMBER (R_ARM_SBREL32, 9) + RELOC_NUMBER (R_ARM_THM_CALL, 10) + RELOC_NUMBER (R_ARM_THM_PC8, 11) + RELOC_NUMBER (R_ARM_BREL_ADJ, 12) + RELOC_NUMBER (R_ARM_SWI24, 13) /* obsolete */ + RELOC_NUMBER (R_ARM_THM_SWI8, 14) /* obsolete */ + RELOC_NUMBER (R_ARM_XPC25, 15) /* obsolete */ + RELOC_NUMBER (R_ARM_THM_XPC22, 16) /* obsolete */ + RELOC_NUMBER (R_ARM_TLS_DTPMOD32, 17) + RELOC_NUMBER (R_ARM_TLS_DTPOFF32, 18) + RELOC_NUMBER (R_ARM_TLS_TPOFF32, 19) + RELOC_NUMBER (R_ARM_COPY, 20) /* Copy symbol at runtime. */ + RELOC_NUMBER (R_ARM_GLOB_DAT, 21) /* Create GOT entry. */ + RELOC_NUMBER (R_ARM_JUMP_SLOT, 22) /* Create PLT entry. */ + RELOC_NUMBER (R_ARM_RELATIVE, 23) /* Adjust by program base. */ + RELOC_NUMBER (R_ARM_GOTOFF32, 24) /* 32 bit offset to GOT. */ + RELOC_NUMBER (R_ARM_BASE_PREL, 25) /* 32 bit PC relative offset to GOT. */ + RELOC_NUMBER (R_ARM_GOT_BREL, 26) /* 32 bit GOT entry. */ + RELOC_NUMBER (R_ARM_PLT32, 27) /* deprecated - 32 bit PLT address. */ + RELOC_NUMBER (R_ARM_CALL, 28) + RELOC_NUMBER (R_ARM_JUMP24, 29) + RELOC_NUMBER (R_ARM_THM_JUMP24, 30) + RELOC_NUMBER (R_ARM_BASE_ABS, 31) + RELOC_NUMBER (R_ARM_ALU_PCREL7_0, 32) /* obsolete */ + RELOC_NUMBER (R_ARM_ALU_PCREL15_8, 33) /* obsolete */ + RELOC_NUMBER (R_ARM_ALU_PCREL23_15, 34) /* obsolete */ + RELOC_NUMBER (R_ARM_LDR_SBREL_11_0, 35) /* deprecated, should have _NC suffix */ + RELOC_NUMBER (R_ARM_ALU_SBREL_19_12, 36) /* deprecated, should have _NC suffix */ + RELOC_NUMBER (R_ARM_ALU_SBREL_27_20, 37) /* deprecated, should have _CK suffix */ + RELOC_NUMBER (R_ARM_TARGET1, 38) + RELOC_NUMBER (R_ARM_SBREL31, 39) /* deprecated */ + RELOC_NUMBER (R_ARM_V4BX, 40) + RELOC_NUMBER (R_ARM_TARGET2, 41) + RELOC_NUMBER (R_ARM_PREL31, 42) + RELOC_NUMBER (R_ARM_MOVW_ABS_NC, 43) + RELOC_NUMBER (R_ARM_MOVT_ABS, 44) + RELOC_NUMBER (R_ARM_MOVW_PREL_NC, 45) + RELOC_NUMBER (R_ARM_MOVT_PREL, 46) + RELOC_NUMBER (R_ARM_THM_MOVW_ABS_NC, 47) + RELOC_NUMBER (R_ARM_THM_MOVT_ABS, 48) + RELOC_NUMBER (R_ARM_THM_MOVW_PREL_NC, 49) + RELOC_NUMBER (R_ARM_THM_MOVT_PREL, 50) + RELOC_NUMBER (R_ARM_THM_JUMP19, 51) + RELOC_NUMBER (R_ARM_THM_JUMP6, 52) + RELOC_NUMBER (R_ARM_THM_ALU_PREL_11_0, 53) + RELOC_NUMBER (R_ARM_THM_PC12, 54) + RELOC_NUMBER (R_ARM_ABS32_NOI, 55) + RELOC_NUMBER (R_ARM_REL32_NOI, 56) + RELOC_NUMBER (R_ARM_ALU_PC_G0_NC, 57) + RELOC_NUMBER (R_ARM_ALU_PC_G0, 58) + RELOC_NUMBER (R_ARM_ALU_PC_G1_NC, 59) + RELOC_NUMBER (R_ARM_ALU_PC_G1, 60) + RELOC_NUMBER (R_ARM_ALU_PC_G2, 61) + RELOC_NUMBER (R_ARM_LDR_PC_G1, 62) + RELOC_NUMBER (R_ARM_LDR_PC_G2, 63) + RELOC_NUMBER (R_ARM_LDRS_PC_G0, 64) + RELOC_NUMBER (R_ARM_LDRS_PC_G1, 65) + RELOC_NUMBER (R_ARM_LDRS_PC_G2, 66) + RELOC_NUMBER (R_ARM_LDC_PC_G0, 67) + RELOC_NUMBER (R_ARM_LDC_PC_G1, 68) + RELOC_NUMBER (R_ARM_LDC_PC_G2, 69) + RELOC_NUMBER (R_ARM_ALU_SB_G0_NC, 70) + RELOC_NUMBER (R_ARM_ALU_SB_G0, 71) + RELOC_NUMBER (R_ARM_ALU_SB_G1_NC, 72) + RELOC_NUMBER (R_ARM_ALU_SB_G1, 73) + RELOC_NUMBER (R_ARM_ALU_SB_G2, 74) + RELOC_NUMBER (R_ARM_LDR_SB_G0, 75) + RELOC_NUMBER (R_ARM_LDR_SB_G1, 76) + RELOC_NUMBER (R_ARM_LDR_SB_G2, 77) + RELOC_NUMBER (R_ARM_LDRS_SB_G0, 78) + RELOC_NUMBER (R_ARM_LDRS_SB_G1, 79) + RELOC_NUMBER (R_ARM_LDRS_SB_G2, 80) + RELOC_NUMBER (R_ARM_LDC_SB_G0, 81) + RELOC_NUMBER (R_ARM_LDC_SB_G1, 82) + RELOC_NUMBER (R_ARM_LDC_SB_G2, 83) + RELOC_NUMBER (R_ARM_MOVW_BREL_NC, 84) + RELOC_NUMBER (R_ARM_MOVT_BREL, 85) + RELOC_NUMBER (R_ARM_MOVW_BREL, 86) + RELOC_NUMBER (R_ARM_THM_MOVW_BREL_NC, 87) + RELOC_NUMBER (R_ARM_THM_MOVT_BREL, 88) + RELOC_NUMBER (R_ARM_THM_MOVW_BREL, 89) + /* 90-93 unallocated */ + RELOC_NUMBER (R_ARM_PLT32_ABS, 94) + RELOC_NUMBER (R_ARM_GOT_ABS, 95) + RELOC_NUMBER (R_ARM_GOT_PREL, 96) + RELOC_NUMBER (R_ARM_GOT_BREL12, 97) + RELOC_NUMBER (R_ARM_GOTOFF12, 98) + RELOC_NUMBER (R_ARM_GOTRELAX, 99) + RELOC_NUMBER (R_ARM_GNU_VTENTRY, 100) /* deprecated - old C++ abi */ + RELOC_NUMBER (R_ARM_GNU_VTINHERIT, 101) /* deprecated - old C++ abi */ + RELOC_NUMBER (R_ARM_THM_JUMP11, 102) + RELOC_NUMBER (R_ARM_THM_JUMP8, 103) + RELOC_NUMBER (R_ARM_TLS_GD32, 104) + RELOC_NUMBER (R_ARM_TLS_LDM32, 105) + RELOC_NUMBER (R_ARM_TLS_LDO32, 106) + RELOC_NUMBER (R_ARM_TLS_IE32, 107) + RELOC_NUMBER (R_ARM_TLS_LE32, 108) + RELOC_NUMBER (R_ARM_TLS_LDO12, 109) + RELOC_NUMBER (R_ARM_TLS_LE12, 110) + RELOC_NUMBER (R_ARM_TLS_IE12GP, 111) + /* 112 - 127 private range */ + RELOC_NUMBER (R_ARM_ME_TOO, 128) /* obsolete */ + + /* Extensions? R=read-only? */ + RELOC_NUMBER (R_ARM_RXPC25, 249) + RELOC_NUMBER (R_ARM_RSBREL32, 250) + RELOC_NUMBER (R_ARM_THM_RPC22, 251) + RELOC_NUMBER (R_ARM_RREL32, 252) + RELOC_NUMBER (R_ARM_RABS32, 253) + RELOC_NUMBER (R_ARM_RPC24, 254) + RELOC_NUMBER (R_ARM_RBASE, 255) + + /* Unofficial names for some of the relocs. */ + FAKE_RELOC (R_ARM_GOTOFF, R_ARM_GOTOFF32) /* 32 bit offset to GOT. */ + FAKE_RELOC (R_ARM_THM_PC22, R_ARM_THM_CALL) + FAKE_RELOC (R_ARM_THM_PC11, R_ARM_THM_JUMP11) + FAKE_RELOC (R_ARM_THM_PC9, R_ARM_THM_JUMP8) + + /* Relocs with both a different name, and (apparently) different meaning in + GNU usage. */ + FAKE_RELOC (R_ARM_GOTPC, R_ARM_BASE_PREL) /* 32 bit PC relative offset to GOT. */ + FAKE_RELOC (R_ARM_GOT32, R_ARM_GOT_BREL) /* 32 bit GOT entry. */ + FAKE_RELOC (R_ARM_ROSEGREL32, R_ARM_SBREL31) /* ??? */ + FAKE_RELOC (R_ARM_AMP_VCALL9, R_ARM_BREL_ADJ) /* Thumb-something. Not used. */ +END_RELOC_NUMBERS (R_ARM_max) + +#ifdef BFD_ARCH_SIZE +/* EABI object attributes. */ + +enum +{ + /* 0-3 are generic. */ + Tag_CPU_raw_name = 4, + Tag_CPU_name, + Tag_CPU_arch, + Tag_CPU_arch_profile, + Tag_ARM_ISA_use, + Tag_THUMB_ISA_use, + Tag_VFP_arch, + Tag_WMMX_arch, + Tag_NEON_arch, + Tag_PCS_config, + Tag_ABI_PCS_R9_use, + Tag_ABI_PCS_RW_data, + Tag_ABI_PCS_RO_data, + Tag_ABI_PCS_GOT_use, + Tag_ABI_PCS_wchar_t, + Tag_ABI_FP_rounding, + Tag_ABI_FP_denormal, + Tag_ABI_FP_exceptions, + Tag_ABI_FP_user_exceptions, + Tag_ABI_FP_number_model, + Tag_ABI_align8_needed, + Tag_ABI_align8_preserved, + Tag_ABI_enum_size, + Tag_ABI_HardFP_use, + Tag_ABI_VFP_args, + Tag_ABI_WMMX_args, + Tag_ABI_optimization_goals, + Tag_ABI_FP_optimization_goals, + /* 32 is generic. */ +}; + +#endif + +/* The name of the note section used to identify arm variants. */ +#define ARM_NOTE_SECTION ".note.gnu.arm.ident" + +/* Special section names. */ +#define ELF_STRING_ARM_unwind ".ARM.exidx" +#define ELF_STRING_ARM_unwind_info ".ARM.extab" +#define ELF_STRING_ARM_unwind_once ".gnu.linkonce.armexidx." +#define ELF_STRING_ARM_unwind_info_once ".gnu.linkonce.armextab." + +#endif /* _ELF_ARM_H */ diff --git a/kernel/fiasco/src/lib/disasm/elf/common.h b/kernel/fiasco/src/lib/disasm/elf/common.h new file mode 100644 index 00000000..5b71782f --- /dev/null +++ b/kernel/fiasco/src/lib/disasm/elf/common.h @@ -0,0 +1,785 @@ +/* ELF support for BFD. + Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, + 2001, 2002, 2003, 2004, 2005, 2006, 2007 + Free Software Foundation, Inc. + + Written by Fred Fish @ Cygnus Support, from information published + in "UNIX System V Release 4, Programmers Guide: ANSI C and + Programming Support Tools". + + This file is part of BFD, the Binary File Descriptor library. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ + + +/* This file is part of ELF support for BFD, and contains the portions + that are common to both the internal and external representations. + For example, ELFMAG0 is the byte 0x7F in both the internal (in-memory) + and external (in-file) representations. */ + +#ifndef _ELF_COMMON_H +#define _ELF_COMMON_H + +/* Fields in e_ident[]. */ + +#define EI_MAG0 0 /* File identification byte 0 index */ +#define ELFMAG0 0x7F /* Magic number byte 0 */ + +#define EI_MAG1 1 /* File identification byte 1 index */ +#define ELFMAG1 'E' /* Magic number byte 1 */ + +#define EI_MAG2 2 /* File identification byte 2 index */ +#define ELFMAG2 'L' /* Magic number byte 2 */ + +#define EI_MAG3 3 /* File identification byte 3 index */ +#define ELFMAG3 'F' /* Magic number byte 3 */ + +#define EI_CLASS 4 /* File class */ +#define ELFCLASSNONE 0 /* Invalid class */ +#define ELFCLASS32 1 /* 32-bit objects */ +#define ELFCLASS64 2 /* 64-bit objects */ + +#define EI_DATA 5 /* Data encoding */ +#define ELFDATANONE 0 /* Invalid data encoding */ +#define ELFDATA2LSB 1 /* 2's complement, little endian */ +#define ELFDATA2MSB 2 /* 2's complement, big endian */ + +#define EI_VERSION 6 /* File version */ + +#define EI_OSABI 7 /* Operating System/ABI indication */ +#define ELFOSABI_NONE 0 /* UNIX System V ABI */ +#define ELFOSABI_HPUX 1 /* HP-UX operating system */ +#define ELFOSABI_NETBSD 2 /* NetBSD */ +#define ELFOSABI_LINUX 3 /* GNU/Linux */ +#define ELFOSABI_HURD 4 /* GNU/Hurd */ +#define ELFOSABI_SOLARIS 6 /* Solaris */ +#define ELFOSABI_AIX 7 /* AIX */ +#define ELFOSABI_IRIX 8 /* IRIX */ +#define ELFOSABI_FREEBSD 9 /* FreeBSD */ +#define ELFOSABI_TRU64 10 /* TRU64 UNIX */ +#define ELFOSABI_MODESTO 11 /* Novell Modesto */ +#define ELFOSABI_OPENBSD 12 /* OpenBSD */ +#define ELFOSABI_OPENVMS 13 /* OpenVMS */ +#define ELFOSABI_NSK 14 /* Hewlett-Packard Non-Stop Kernel */ +#define ELFOSABI_AROS 15 /* Amiga Research OS */ +#define ELFOSABI_ARM 97 /* ARM */ +#define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */ + +#define EI_ABIVERSION 8 /* ABI version */ + +#define EI_PAD 9 /* Start of padding bytes */ + + +/* Values for e_type, which identifies the object file type. */ + +#define ET_NONE 0 /* No file type */ +#define ET_REL 1 /* Relocatable file */ +#define ET_EXEC 2 /* Executable file */ +#define ET_DYN 3 /* Shared object file */ +#define ET_CORE 4 /* Core file */ +#define ET_LOOS 0xFE00 /* Operating system-specific */ +#define ET_HIOS 0xFEFF /* Operating system-specific */ +#define ET_LOPROC 0xFF00 /* Processor-specific */ +#define ET_HIPROC 0xFFFF /* Processor-specific */ + +/* Values for e_machine, which identifies the architecture. These numbers + are officially assigned by registry@caldera.com. See below for a list of + ad-hoc numbers used during initial development. */ + +#define EM_NONE 0 /* No machine */ +#define EM_M32 1 /* AT&T WE 32100 */ +#define EM_SPARC 2 /* SUN SPARC */ +#define EM_386 3 /* Intel 80386 */ +#define EM_68K 4 /* Motorola m68k family */ +#define EM_88K 5 /* Motorola m88k family */ +#define EM_486 6 /* Intel 80486 *//* Reserved for future use */ +#define EM_860 7 /* Intel 80860 */ +#define EM_MIPS 8 /* MIPS R3000 (officially, big-endian only) */ +#define EM_S370 9 /* IBM System/370 */ +#define EM_MIPS_RS3_LE 10 /* MIPS R3000 little-endian (Oct 4 1999 Draft) Deprecated */ + +#define EM_PARISC 15 /* HPPA */ + +#define EM_VPP550 17 /* Fujitsu VPP500 */ +#define EM_SPARC32PLUS 18 /* Sun's "v8plus" */ +#define EM_960 19 /* Intel 80960 */ +#define EM_PPC 20 /* PowerPC */ +#define EM_PPC64 21 /* 64-bit PowerPC */ +#define EM_S390 22 /* IBM S/390 */ +#define EM_SPU 23 /* Sony/Toshiba/IBM SPU */ + +#define EM_V800 36 /* NEC V800 series */ +#define EM_FR20 37 /* Fujitsu FR20 */ +#define EM_RH32 38 /* TRW RH32 */ +#define EM_MCORE 39 /* Motorola M*Core */ /* May also be taken by Fujitsu MMA */ +#define EM_RCE 39 /* Old name for MCore */ +#define EM_ARM 40 /* ARM */ +#define EM_OLD_ALPHA 41 /* Digital Alpha */ +#define EM_SH 42 /* Renesas (formerly Hitachi) / SuperH SH */ +#define EM_SPARCV9 43 /* SPARC v9 64-bit */ +#define EM_TRICORE 44 /* Siemens Tricore embedded processor */ +#define EM_ARC 45 /* ARC Cores */ +#define EM_H8_300 46 /* Renesas (formerly Hitachi) H8/300 */ +#define EM_H8_300H 47 /* Renesas (formerly Hitachi) H8/300H */ +#define EM_H8S 48 /* Renesas (formerly Hitachi) H8S */ +#define EM_H8_500 49 /* Renesas (formerly Hitachi) H8/500 */ +#define EM_IA_64 50 /* Intel IA-64 Processor */ +#define EM_MIPS_X 51 /* Stanford MIPS-X */ +#define EM_COLDFIRE 52 /* Motorola Coldfire */ +#define EM_68HC12 53 /* Motorola M68HC12 */ +#define EM_MMA 54 /* Fujitsu Multimedia Accelerator */ +#define EM_PCP 55 /* Siemens PCP */ +#define EM_NCPU 56 /* Sony nCPU embedded RISC processor */ +#define EM_NDR1 57 /* Denso NDR1 microprocesspr */ +#define EM_STARCORE 58 /* Motorola Star*Core processor */ +#define EM_ME16 59 /* Toyota ME16 processor */ +#define EM_ST100 60 /* STMicroelectronics ST100 processor */ +#define EM_TINYJ 61 /* Advanced Logic Corp. TinyJ embedded processor */ +#define EM_X86_64 62 /* Advanced Micro Devices X86-64 processor */ + +#define EM_PDP10 64 /* Digital Equipment Corp. PDP-10 */ +#define EM_PDP11 65 /* Digital Equipment Corp. PDP-11 */ +#define EM_FX66 66 /* Siemens FX66 microcontroller */ +#define EM_ST9PLUS 67 /* STMicroelectronics ST9+ 8/16 bit microcontroller */ +#define EM_ST7 68 /* STMicroelectronics ST7 8-bit microcontroller */ +#define EM_68HC16 69 /* Motorola MC68HC16 Microcontroller */ +#define EM_68HC11 70 /* Motorola MC68HC11 Microcontroller */ +#define EM_68HC08 71 /* Motorola MC68HC08 Microcontroller */ +#define EM_68HC05 72 /* Motorola MC68HC05 Microcontroller */ +#define EM_SVX 73 /* Silicon Graphics SVx */ +#define EM_ST19 74 /* STMicroelectronics ST19 8-bit cpu */ +#define EM_VAX 75 /* Digital VAX */ +#define EM_CRIS 76 /* Axis Communications 32-bit embedded processor */ +#define EM_JAVELIN 77 /* Infineon Technologies 32-bit embedded cpu */ +#define EM_FIREPATH 78 /* Element 14 64-bit DSP processor */ +#define EM_ZSP 79 /* LSI Logic's 16-bit DSP processor */ +#define EM_MMIX 80 /* Donald Knuth's educational 64-bit processor */ +#define EM_HUANY 81 /* Harvard's machine-independent format */ +#define EM_PRISM 82 /* SiTera Prism */ +#define EM_AVR 83 /* Atmel AVR 8-bit microcontroller */ +#define EM_FR30 84 /* Fujitsu FR30 */ +#define EM_D10V 85 /* Mitsubishi D10V */ +#define EM_D30V 86 /* Mitsubishi D30V */ +#define EM_V850 87 /* NEC v850 */ +#define EM_M32R 88 /* Renesas M32R (formerly Mitsubishi M32R) */ +#define EM_MN10300 89 /* Matsushita MN10300 */ +#define EM_MN10200 90 /* Matsushita MN10200 */ +#define EM_PJ 91 /* picoJava */ +#define EM_OPENRISC 92 /* OpenRISC 32-bit embedded processor */ +#define EM_ARC_A5 93 /* ARC Cores Tangent-A5 */ +#define EM_XTENSA 94 /* Tensilica Xtensa Architecture */ +#define EM_IP2K 101 /* Ubicom IP2022 micro controller */ +#define EM_CR 103 /* National Semiconductor CompactRISC */ +#define EM_MSP430 105 /* TI msp430 micro controller */ +#define EM_BLACKFIN 106 /* ADI Blackfin */ +#define EM_ALTERA_NIOS2 113 /* Altera Nios II soft-core processor */ +#define EM_CRX 114 /* National Semiconductor CRX */ +#define EM_CR16 115 /* National Semiconductor CompactRISC - CR16 */ +#define EM_SCORE 135 /* Sunplus Score */ + +/* If it is necessary to assign new unofficial EM_* values, please pick large + random numbers (0x8523, 0xa7f2, etc.) to minimize the chances of collision + with official or non-GNU unofficial values. + + NOTE: Do not just increment the most recent number by one. + Somebody else somewhere will do exactly the same thing, and you + will have a collision. Instead, pick a random number. + + Normally, each entity or maintainer responsible for a machine with an + unofficial e_machine number should eventually ask registry@caldera.com for + an officially blessed number to be added to the list above. */ + +/* Old version of Sparc v9, from before the ABI; + This should be removed shortly. */ +#define EM_OLD_SPARCV9 11 + +/* Old version of PowerPC, this should be removed shortly. */ +#define EM_PPC_OLD 17 + +/* picoJava */ +#define EM_PJ_OLD 99 + +/* AVR magic number. Written in the absense of an ABI. */ +#define EM_AVR_OLD 0x1057 + +/* MSP430 magic number. Written in the absense of everything. */ +#define EM_MSP430_OLD 0x1059 + +/* Morpho MT. Written in the absense of an ABI. */ +#define EM_MT 0x2530 + +/* FR30 magic number - no EABI available. */ +#define EM_CYGNUS_FR30 0x3330 + +/* OpenRISC magic number. Written in the absense of an ABI. */ +#define EM_OPENRISC_OLD 0x3426 + +/* DLX magic number. Written in the absense of an ABI. */ +#define EM_DLX 0x5aa5 + +/* FRV magic number - no EABI available??. */ +#define EM_CYGNUS_FRV 0x5441 + +/* Infineon Technologies 16-bit microcontroller with C166-V2 core. */ +#define EM_XC16X 0x4688 + +/* D10V backend magic number. Written in the absence of an ABI. */ +#define EM_CYGNUS_D10V 0x7650 + +/* D30V backend magic number. Written in the absence of an ABI. */ +#define EM_CYGNUS_D30V 0x7676 + +/* Ubicom IP2xxx; Written in the absense of an ABI. */ +#define EM_IP2K_OLD 0x8217 + +/* (Deprecated) Temporary number for the OpenRISC processor. */ +#define EM_OR32 0x8472 + +/* Cygnus PowerPC ELF backend. Written in the absence of an ABI. */ +#define EM_CYGNUS_POWERPC 0x9025 + +/* Alpha backend magic number. Written in the absence of an ABI. */ +#define EM_ALPHA 0x9026 + +/* Cygnus M32R ELF backend. Written in the absence of an ABI. */ +#define EM_CYGNUS_M32R 0x9041 + +/* V850 backend magic number. Written in the absense of an ABI. */ +#define EM_CYGNUS_V850 0x9080 + +/* old S/390 backend magic number. Written in the absence of an ABI. */ +#define EM_S390_OLD 0xa390 + +/* Old, unofficial value for Xtensa. */ +#define EM_XTENSA_OLD 0xabc7 + +#define EM_XSTORMY16 0xad45 + +/* mn10200 and mn10300 backend magic numbers. + Written in the absense of an ABI. */ +#define EM_CYGNUS_MN10300 0xbeef +#define EM_CYGNUS_MN10200 0xdead + +/* Renesas M32C and M16C. */ +#define EM_M32C 0xFEB0 + +/* Vitesse IQ2000. */ +#define EM_IQ2000 0xFEBA + +/* NIOS magic number - no EABI available. */ +#define EM_NIOS32 0xFEBB + +#define EM_CYGNUS_MEP 0xF00D /* Toshiba MeP */ + +/* See the above comment before you add a new EM_* value here. */ + +/* Values for e_version. */ + +#define EV_NONE 0 /* Invalid ELF version */ +#define EV_CURRENT 1 /* Current version */ + +/* Values for program header, p_type field. */ + +#define PT_NULL 0 /* Program header table entry unused */ +#define PT_LOAD 1 /* Loadable program segment */ +#define PT_DYNAMIC 2 /* Dynamic linking information */ +#define PT_INTERP 3 /* Program interpreter */ +#define PT_NOTE 4 /* Auxiliary information */ +#define PT_SHLIB 5 /* Reserved, unspecified semantics */ +#define PT_PHDR 6 /* Entry for header table itself */ +#define PT_TLS 7 /* Thread local storage segment */ +#define PT_LOOS 0x60000000 /* OS-specific */ +#define PT_HIOS 0x6fffffff /* OS-specific */ +#define PT_LOPROC 0x70000000 /* Processor-specific */ +#define PT_HIPROC 0x7FFFFFFF /* Processor-specific */ + +#define PT_GNU_EH_FRAME (PT_LOOS + 0x474e550) /* Frame unwind information */ +#define PT_SUNW_EH_FRAME PT_GNU_EH_FRAME /* Solaris uses the same value */ +#define PT_GNU_STACK (PT_LOOS + 0x474e551) /* Stack flags */ +#define PT_GNU_RELRO (PT_LOOS + 0x474e552) /* Read-only after relocation */ + +/* Program segment permissions, in program header p_flags field. */ + +#define PF_X (1 << 0) /* Segment is executable */ +#define PF_W (1 << 1) /* Segment is writable */ +#define PF_R (1 << 2) /* Segment is readable */ +/* #define PF_MASKOS 0x0F000000 *//* OS-specific reserved bits */ +#define PF_MASKOS 0x0FF00000 /* New value, Oct 4, 1999 Draft */ +#define PF_MASKPROC 0xF0000000 /* Processor-specific reserved bits */ + +/* Values for section header, sh_type field. */ + +#define SHT_NULL 0 /* Section header table entry unused */ +#define SHT_PROGBITS 1 /* Program specific (private) data */ +#define SHT_SYMTAB 2 /* Link editing symbol table */ +#define SHT_STRTAB 3 /* A string table */ +#define SHT_RELA 4 /* Relocation entries with addends */ +#define SHT_HASH 5 /* A symbol hash table */ +#define SHT_DYNAMIC 6 /* Information for dynamic linking */ +#define SHT_NOTE 7 /* Information that marks file */ +#define SHT_NOBITS 8 /* Section occupies no space in file */ +#define SHT_REL 9 /* Relocation entries, no addends */ +#define SHT_SHLIB 10 /* Reserved, unspecified semantics */ +#define SHT_DYNSYM 11 /* Dynamic linking symbol table */ + +#define SHT_INIT_ARRAY 14 /* Array of ptrs to init functions */ +#define SHT_FINI_ARRAY 15 /* Array of ptrs to finish functions */ +#define SHT_PREINIT_ARRAY 16 /* Array of ptrs to pre-init funcs */ +#define SHT_GROUP 17 /* Section contains a section group */ +#define SHT_SYMTAB_SHNDX 18 /* Indicies for SHN_XINDEX entries */ + +#define SHT_LOOS 0x60000000 /* First of OS specific semantics */ +#define SHT_HIOS 0x6fffffff /* Last of OS specific semantics */ + +#define SHT_GNU_ATTRIBUTES 0x6ffffff5 /* Object attributes */ +#define SHT_GNU_HASH 0x6ffffff6 /* GNU style symbol hash table */ +#define SHT_GNU_LIBLIST 0x6ffffff7 /* List of prelink dependencies */ + +/* The next three section types are defined by Solaris, and are named + SHT_SUNW*. We use them in GNU code, so we also define SHT_GNU* + versions. */ +#define SHT_SUNW_verdef 0x6ffffffd /* Versions defined by file */ +#define SHT_SUNW_verneed 0x6ffffffe /* Versions needed by file */ +#define SHT_SUNW_versym 0x6fffffff /* Symbol versions */ + +#define SHT_GNU_verdef SHT_SUNW_verdef +#define SHT_GNU_verneed SHT_SUNW_verneed +#define SHT_GNU_versym SHT_SUNW_versym + +#define SHT_LOPROC 0x70000000 /* Processor-specific semantics, lo */ +#define SHT_HIPROC 0x7FFFFFFF /* Processor-specific semantics, hi */ +#define SHT_LOUSER 0x80000000 /* Application-specific semantics */ +/* #define SHT_HIUSER 0x8FFFFFFF *//* Application-specific semantics */ +#define SHT_HIUSER 0xFFFFFFFF /* New value, defined in Oct 4, 1999 Draft */ + +/* Values for section header, sh_flags field. */ + +#define SHF_WRITE (1 << 0) /* Writable data during execution */ +#define SHF_ALLOC (1 << 1) /* Occupies memory during execution */ +#define SHF_EXECINSTR (1 << 2) /* Executable machine instructions */ +#define SHF_MERGE (1 << 4) /* Data in this section can be merged */ +#define SHF_STRINGS (1 << 5) /* Contains null terminated character strings */ +#define SHF_INFO_LINK (1 << 6) /* sh_info holds section header table index */ +#define SHF_LINK_ORDER (1 << 7) /* Preserve section ordering when linking */ +#define SHF_OS_NONCONFORMING (1 << 8) /* OS specific processing required */ +#define SHF_GROUP (1 << 9) /* Member of a section group */ +#define SHF_TLS (1 << 10) /* Thread local storage section */ + +/* #define SHF_MASKOS 0x0F000000 *//* OS-specific semantics */ +#define SHF_MASKOS 0x0FF00000 /* New value, Oct 4, 1999 Draft */ +#define SHF_MASKPROC 0xF0000000 /* Processor-specific semantics */ + +/* Values of note segment descriptor types for core files. */ + +#define NT_PRSTATUS 1 /* Contains copy of prstatus struct */ +#define NT_FPREGSET 2 /* Contains copy of fpregset struct */ +#define NT_PRPSINFO 3 /* Contains copy of prpsinfo struct */ +#define NT_TASKSTRUCT 4 /* Contains copy of task struct */ +#define NT_AUXV 6 /* Contains copy of Elfxx_auxv_t */ +#define NT_PRXFPREG 0x46e62b7f /* Contains a user_xfpregs_struct; */ + /* note name must be "LINUX". */ + +/* Note segments for core files on dir-style procfs systems. */ + +#define NT_PSTATUS 10 /* Has a struct pstatus */ +#define NT_FPREGS 12 /* Has a struct fpregset */ +#define NT_PSINFO 13 /* Has a struct psinfo */ +#define NT_LWPSTATUS 16 /* Has a struct lwpstatus_t */ +#define NT_LWPSINFO 17 /* Has a struct lwpsinfo_t */ +#define NT_WIN32PSTATUS 18 /* Has a struct win32_pstatus */ + + +/* Note segments for core files on NetBSD systems. Note name + must start with "NetBSD-CORE". */ + +#define NT_NETBSDCORE_PROCINFO 1 /* Has a struct procinfo */ +#define NT_NETBSDCORE_FIRSTMACH 32 /* start of machdep note types */ + +/* Note segments for core files on SPU systems. Note name + must start with "SPU/". */ + +#define NT_SPU 1 + +/* Values of note segment descriptor types for object files. */ + +#define NT_VERSION 1 /* Contains a version string. */ +#define NT_ARCH 2 /* Contains an architecture string. */ + +/* Values for notes in non-core files using name "GNU". */ + +#define NT_GNU_ABI_TAG 1 +#define NT_GNU_HWCAP 2 /* Used by ld.so and kernel vDSO. */ +#define NT_GNU_BUILD_ID 3 /* Generated by ld --build-id. */ + +/* Values used in GNU .note.ABI-tag notes (NT_GNU_ABI_TAG). */ +#define GNU_ABI_TAG_LINUX 0 +#define GNU_ABI_TAG_HURD 1 +#define GNU_ABI_TAG_SOLARIS 2 +#define GNU_ABI_TAG_FREEBSD 3 +#define GNU_ABI_TAG_NETBSD 4 + +/* Values for NetBSD .note.netbsd.ident notes. Note name is "NetBSD". */ + +#define NT_NETBSD_IDENT 1 + +/* Values for OpenBSD .note.openbsd.ident notes. Note name is "OpenBSD". */ + +#define NT_OPENBSD_IDENT 1 + +/* Values for FreeBSD .note.ABI-tag notes. Note name is "FreeBSD". */ + +#define NT_FREEBSD_ABI_TAG 1 + +/* These three macros disassemble and assemble a symbol table st_info field, + which contains the symbol binding and symbol type. The STB_ and STT_ + defines identify the binding and type. */ + +#define ELF_ST_BIND(val) (((unsigned int)(val)) >> 4) +#define ELF_ST_TYPE(val) ((val) & 0xF) +#define ELF_ST_INFO(bind,type) (((bind) << 4) + ((type) & 0xF)) + +/* The 64bit and 32bit versions of these macros are identical, but + the ELF spec defines them, so here they are. */ +#define ELF32_ST_BIND ELF_ST_BIND +#define ELF32_ST_TYPE ELF_ST_TYPE +#define ELF32_ST_INFO ELF_ST_INFO +#define ELF64_ST_BIND ELF_ST_BIND +#define ELF64_ST_TYPE ELF_ST_TYPE +#define ELF64_ST_INFO ELF_ST_INFO + +/* This macro disassembles and assembles a symbol's visibility into + the st_other field. The STV_ defines specify the actual visibility. */ + +#define ELF_ST_VISIBILITY(v) ((v) & 0x3) +/* The remaining bits in the st_other field are not currently used. + They should be set to zero. */ + +#define ELF32_ST_VISIBILITY ELF_ST_VISIBILITY +#define ELF64_ST_VISIBILITY ELF_ST_VISIBILITY + + +#define STN_UNDEF 0 /* Undefined symbol index */ + +#define STB_LOCAL 0 /* Symbol not visible outside obj */ +#define STB_GLOBAL 1 /* Symbol visible outside obj */ +#define STB_WEAK 2 /* Like globals, lower precedence */ +#define STB_LOOS 10 /* OS-specific semantics */ +#define STB_HIOS 12 /* OS-specific semantics */ +#define STB_LOPROC 13 /* Application-specific semantics */ +#define STB_HIPROC 15 /* Application-specific semantics */ + +#define STT_NOTYPE 0 /* Symbol type is unspecified */ +#define STT_OBJECT 1 /* Symbol is a data object */ +#define STT_FUNC 2 /* Symbol is a code object */ +#define STT_SECTION 3 /* Symbol associated with a section */ +#define STT_FILE 4 /* Symbol gives a file name */ +#define STT_COMMON 5 /* An uninitialised common block */ +#define STT_TLS 6 /* Thread local data object */ +#define STT_RELC 8 /* Complex relocation expression */ +#define STT_SRELC 9 /* Signed Complex relocation expression */ +#define STT_LOOS 10 /* OS-specific semantics */ +#define STT_HIOS 12 /* OS-specific semantics */ +#define STT_LOPROC 13 /* Application-specific semantics */ +#define STT_HIPROC 15 /* Application-specific semantics */ + +/* Special section indices, which may show up in st_shndx fields, among + other places. */ + +#define SHN_UNDEF 0 /* Undefined section reference */ +#define SHN_LORESERVE 0xFF00 /* Begin range of reserved indices */ +#define SHN_LOPROC 0xFF00 /* Begin range of appl-specific */ +#define SHN_HIPROC 0xFF1F /* End range of appl-specific */ +#define SHN_LOOS 0xFF20 /* OS specific semantics, lo */ +#define SHN_HIOS 0xFF3F /* OS specific semantics, hi */ +#define SHN_ABS 0xFFF1 /* Associated symbol is absolute */ +#define SHN_COMMON 0xFFF2 /* Associated symbol is in common */ +#define SHN_XINDEX 0xFFFF /* Section index is held elsewhere */ +#define SHN_HIRESERVE 0xFFFF /* End range of reserved indices */ +#define SHN_BAD ((unsigned) -1) /* Used internally by bfd */ + +/* The following constants control how a symbol may be accessed once it has + become part of an executable or shared library. */ + +#define STV_DEFAULT 0 /* Visibility is specified by binding type */ +#define STV_INTERNAL 1 /* OS specific version of STV_HIDDEN */ +#define STV_HIDDEN 2 /* Can only be seen inside currect component */ +#define STV_PROTECTED 3 /* Treat as STB_LOCAL inside current component */ + +/* Relocation info handling macros. */ + +#define ELF32_R_SYM(i) ((i) >> 8) +#define ELF32_R_TYPE(i) ((i) & 0xff) +#define ELF32_R_INFO(s,t) (((s) << 8) + ((t) & 0xff)) + +#define ELF64_R_SYM(i) ((i) >> 32) +#define ELF64_R_TYPE(i) ((i) & 0xffffffff) +#define ELF64_R_INFO(s,t) (((bfd_vma) (s) << 31 << 1) + (bfd_vma) (t)) + +/* Dynamic section tags. */ + +#define DT_NULL 0 +#define DT_NEEDED 1 +#define DT_PLTRELSZ 2 +#define DT_PLTGOT 3 +#define DT_HASH 4 +#define DT_STRTAB 5 +#define DT_SYMTAB 6 +#define DT_RELA 7 +#define DT_RELASZ 8 +#define DT_RELAENT 9 +#define DT_STRSZ 10 +#define DT_SYMENT 11 +#define DT_INIT 12 +#define DT_FINI 13 +#define DT_SONAME 14 +#define DT_RPATH 15 +#define DT_SYMBOLIC 16 +#define DT_REL 17 +#define DT_RELSZ 18 +#define DT_RELENT 19 +#define DT_PLTREL 20 +#define DT_DEBUG 21 +#define DT_TEXTREL 22 +#define DT_JMPREL 23 +#define DT_BIND_NOW 24 +#define DT_INIT_ARRAY 25 +#define DT_FINI_ARRAY 26 +#define DT_INIT_ARRAYSZ 27 +#define DT_FINI_ARRAYSZ 28 +#define DT_RUNPATH 29 +#define DT_FLAGS 30 +#define DT_ENCODING 32 +#define DT_PREINIT_ARRAY 32 +#define DT_PREINIT_ARRAYSZ 33 + +/* Note, the Oct 4, 1999 draft of the ELF ABI changed the values + for DT_LOOS and DT_HIOS. Some implementations however, use + values outside of the new range (see below). */ +#define OLD_DT_LOOS 0x60000000 +#define DT_LOOS 0x6000000d +#define DT_HIOS 0x6ffff000 +#define OLD_DT_HIOS 0x6fffffff + +#define DT_LOPROC 0x70000000 +#define DT_HIPROC 0x7fffffff + +/* The next four dynamic tags are used on Solaris. We support them + everywhere. Note these values lie outside of the (new) range for + OS specific values. This is a deliberate special case and we + maintain it for backwards compatability. */ +#define DT_VALRNGLO 0x6ffffd00 +#define DT_GNU_PRELINKED 0x6ffffdf5 +#define DT_GNU_CONFLICTSZ 0x6ffffdf6 +#define DT_GNU_LIBLISTSZ 0x6ffffdf7 +#define DT_CHECKSUM 0x6ffffdf8 +#define DT_PLTPADSZ 0x6ffffdf9 +#define DT_MOVEENT 0x6ffffdfa +#define DT_MOVESZ 0x6ffffdfb +#define DT_FEATURE 0x6ffffdfc +#define DT_POSFLAG_1 0x6ffffdfd +#define DT_SYMINSZ 0x6ffffdfe +#define DT_SYMINENT 0x6ffffdff +#define DT_VALRNGHI 0x6ffffdff + +#define DT_ADDRRNGLO 0x6ffffe00 +#define DT_GNU_HASH 0x6ffffef5 +#define DT_TLSDESC_PLT 0x6ffffef6 +#define DT_TLSDESC_GOT 0x6ffffef7 +#define DT_GNU_CONFLICT 0x6ffffef8 +#define DT_GNU_LIBLIST 0x6ffffef9 +#define DT_CONFIG 0x6ffffefa +#define DT_DEPAUDIT 0x6ffffefb +#define DT_AUDIT 0x6ffffefc +#define DT_PLTPAD 0x6ffffefd +#define DT_MOVETAB 0x6ffffefe +#define DT_SYMINFO 0x6ffffeff +#define DT_ADDRRNGHI 0x6ffffeff + +#define DT_RELACOUNT 0x6ffffff9 +#define DT_RELCOUNT 0x6ffffffa +#define DT_FLAGS_1 0x6ffffffb +#define DT_VERDEF 0x6ffffffc +#define DT_VERDEFNUM 0x6ffffffd +#define DT_VERNEED 0x6ffffffe +#define DT_VERNEEDNUM 0x6fffffff + +/* This tag is a GNU extension to the Solaris version scheme. */ +#define DT_VERSYM 0x6ffffff0 + +#define DT_LOPROC 0x70000000 +#define DT_HIPROC 0x7fffffff + +/* These section tags are used on Solaris. We support them + everywhere, and hope they do not conflict. */ + +#define DT_AUXILIARY 0x7ffffffd +#define DT_USED 0x7ffffffe +#define DT_FILTER 0x7fffffff + + +/* Values used in DT_FEATURE .dynamic entry. */ +#define DTF_1_PARINIT 0x00000001 +/* From + + http://docs.sun.com:80/ab2/coll.45.13/LLM/@Ab2PageView/21165?Ab2Lang=C&Ab2Enc=iso-8859-1 + + DTF_1_CONFEXP is the same as DTF_1_PARINIT. It is a typo. The value + defined here is the same as the one in on Solaris 8. */ +#define DTF_1_CONFEXP 0x00000002 + +/* Flag values used in the DT_POSFLAG_1 .dynamic entry. */ +#define DF_P1_LAZYLOAD 0x00000001 +#define DF_P1_GROUPPERM 0x00000002 + +/* Flag value in in the DT_FLAGS_1 .dynamic entry. */ +#define DF_1_NOW 0x00000001 +#define DF_1_GLOBAL 0x00000002 +#define DF_1_GROUP 0x00000004 +#define DF_1_NODELETE 0x00000008 +#define DF_1_LOADFLTR 0x00000010 +#define DF_1_INITFIRST 0x00000020 +#define DF_1_NOOPEN 0x00000040 +#define DF_1_ORIGIN 0x00000080 +#define DF_1_DIRECT 0x00000100 +#define DF_1_TRANS 0x00000200 +#define DF_1_INTERPOSE 0x00000400 +#define DF_1_NODEFLIB 0x00000800 +#define DF_1_NODUMP 0x00001000 +#define DF_1_CONLFAT 0x00002000 + +/* Flag values for the DT_FLAGS entry. */ +#define DF_ORIGIN (1 << 0) +#define DF_SYMBOLIC (1 << 1) +#define DF_TEXTREL (1 << 2) +#define DF_BIND_NOW (1 << 3) +#define DF_STATIC_TLS (1 << 4) + +/* These constants are used for the version number of a Elf32_Verdef + structure. */ + +#define VER_DEF_NONE 0 +#define VER_DEF_CURRENT 1 + +/* These constants appear in the vd_flags field of a Elf32_Verdef + structure. */ + +#define VER_FLG_BASE 0x1 +#define VER_FLG_WEAK 0x2 + +/* These special constants can be found in an Elf32_Versym field. */ + +#define VER_NDX_LOCAL 0 +#define VER_NDX_GLOBAL 1 + +/* These constants are used for the version number of a Elf32_Verneed + structure. */ + +#define VER_NEED_NONE 0 +#define VER_NEED_CURRENT 1 + +/* This flag appears in a Versym structure. It means that the symbol + is hidden, and is only visible with an explicit version number. + This is a GNU extension. */ + +#define VERSYM_HIDDEN 0x8000 + +/* This is the mask for the rest of the Versym information. */ + +#define VERSYM_VERSION 0x7fff + +/* This is a special token which appears as part of a symbol name. It + indictes that the rest of the name is actually the name of a + version node, and is not part of the actual name. This is a GNU + extension. For example, the symbol name `stat@ver2' is taken to + mean the symbol `stat' in version `ver2'. */ + +#define ELF_VER_CHR '@' + +/* Possible values for si_boundto. */ + +#define SYMINFO_BT_SELF 0xffff /* Symbol bound to self */ +#define SYMINFO_BT_PARENT 0xfffe /* Symbol bound to parent */ +#define SYMINFO_BT_LOWRESERVE 0xff00 /* Beginning of reserved entries */ + +/* Possible bitmasks for si_flags. */ + +#define SYMINFO_FLG_DIRECT 0x0001 /* Direct bound symbol */ +#define SYMINFO_FLG_PASSTHRU 0x0002 /* Pass-thru symbol for translator */ +#define SYMINFO_FLG_COPY 0x0004 /* Symbol is a copy-reloc */ +#define SYMINFO_FLG_LAZYLOAD 0x0008 /* Symbol bound to object to be lazy loaded */ + +/* Syminfo version values. */ + +#define SYMINFO_NONE 0 +#define SYMINFO_CURRENT 1 +#define SYMINFO_NUM 2 + +/* Section Group Flags. */ + +#define GRP_COMDAT 0x1 /* A COMDAT group */ + +/* Auxv a_type values. */ + +#define AT_NULL 0 /* End of vector */ +#define AT_IGNORE 1 /* Entry should be ignored */ +#define AT_EXECFD 2 /* File descriptor of program */ +#define AT_PHDR 3 /* Program headers for program */ +#define AT_PHENT 4 /* Size of program header entry */ +#define AT_PHNUM 5 /* Number of program headers */ +#define AT_PAGESZ 6 /* System page size */ +#define AT_BASE 7 /* Base address of interpreter */ +#define AT_FLAGS 8 /* Flags */ +#define AT_ENTRY 9 /* Entry point of program */ +#define AT_NOTELF 10 /* Program is not ELF */ +#define AT_UID 11 /* Real uid */ +#define AT_EUID 12 /* Effective uid */ +#define AT_GID 13 /* Real gid */ +#define AT_EGID 14 /* Effective gid */ +#define AT_CLKTCK 17 /* Frequency of times() */ +#define AT_PLATFORM 15 /* String identifying platform. */ +#define AT_HWCAP 16 /* Machine dependent hints about + processor capabilities. */ +#define AT_FPUCW 18 /* Used FPU control word. */ +#define AT_DCACHEBSIZE 19 /* Data cache block size. */ +#define AT_ICACHEBSIZE 20 /* Instruction cache block size. */ +#define AT_UCACHEBSIZE 21 /* Unified cache block size. */ +#define AT_IGNOREPPC 22 /* Entry should be ignored */ +#define AT_SECURE 23 /* Boolean, was exec setuid-like? */ +/* Pointer to the global system page used for system calls and other + nice things. */ +#define AT_SYSINFO 32 +#define AT_SYSINFO_EHDR 33 /* Pointer to ELF header of system-supplied DSO. */ + +#define AT_SUN_UID 2000 /* Effective user ID. */ +#define AT_SUN_RUID 2001 /* Real user ID. */ +#define AT_SUN_GID 2002 /* Effective group ID. */ +#define AT_SUN_RGID 2003 /* Real group ID. */ +#define AT_SUN_LDELF 2004 /* Dynamic linker's ELF header. */ +#define AT_SUN_LDSHDR 2005 /* Dynamic linker's section headers. */ +#define AT_SUN_LDNAME 2006 /* String giving name of dynamic linker. */ +#define AT_SUN_LPAGESZ 2007 /* Large pagesize. */ +#define AT_SUN_PLATFORM 2008 /* Platform name string. */ +#define AT_SUN_HWCAP 2009 /* Machine dependent hints about + processor capabilities. */ +#define AT_SUN_IFLUSH 2010 /* Should flush icache? */ +#define AT_SUN_CPU 2011 /* CPU name string. */ +#define AT_SUN_EMUL_ENTRY 2012 /* COFF entry point address. */ +#define AT_SUN_EMUL_EXECFD 2013 /* COFF executable file descriptor. */ +#define AT_SUN_EXECNAME 2014 /* Canonicalized file name given to execve. */ +#define AT_SUN_MMU 2015 /* String for name of MMU module. */ +#define AT_SUN_LDDATA 2016 /* Dynamic linker's data segment address. */ + + +#endif /* _ELF_COMMON_H */ diff --git a/kernel/fiasco/src/lib/disasm/elf/external.h b/kernel/fiasco/src/lib/disasm/elf/external.h new file mode 100644 index 00000000..21450f00 --- /dev/null +++ b/kernel/fiasco/src/lib/disasm/elf/external.h @@ -0,0 +1,275 @@ +/* ELF support for BFD. + Copyright 1991, 1992, 1993, 1995, 1997, 1998, 1999, 2001, 2003, 2005 + Free Software Foundation, Inc. + + Written by Fred Fish @ Cygnus Support, from information published + in "UNIX System V Release 4, Programmers Guide: ANSI C and + Programming Support Tools". + +This file is part of BFD, the Binary File Descriptor library. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ + + +/* This file is part of ELF support for BFD, and contains the portions + that describe how ELF is represented externally by the BFD library. + I.E. it describes the in-file representation of ELF. It requires + the elf/common.h file which contains the portions that are common to + both the internal and external representations. */ + +/* The 64-bit stuff is kind of random. Perhaps someone will publish a + spec someday. */ + +#ifndef _ELF_EXTERNAL_H +#define _ELF_EXTERNAL_H + +/* ELF Header (32-bit implementations) */ + +typedef struct { + unsigned char e_ident[16]; /* ELF "magic number" */ + unsigned char e_type[2]; /* Identifies object file type */ + unsigned char e_machine[2]; /* Specifies required architecture */ + unsigned char e_version[4]; /* Identifies object file version */ + unsigned char e_entry[4]; /* Entry point virtual address */ + unsigned char e_phoff[4]; /* Program header table file offset */ + unsigned char e_shoff[4]; /* Section header table file offset */ + unsigned char e_flags[4]; /* Processor-specific flags */ + unsigned char e_ehsize[2]; /* ELF header size in bytes */ + unsigned char e_phentsize[2]; /* Program header table entry size */ + unsigned char e_phnum[2]; /* Program header table entry count */ + unsigned char e_shentsize[2]; /* Section header table entry size */ + unsigned char e_shnum[2]; /* Section header table entry count */ + unsigned char e_shstrndx[2]; /* Section header string table index */ +} Elf32_External_Ehdr; + +typedef struct { + unsigned char e_ident[16]; /* ELF "magic number" */ + unsigned char e_type[2]; /* Identifies object file type */ + unsigned char e_machine[2]; /* Specifies required architecture */ + unsigned char e_version[4]; /* Identifies object file version */ + unsigned char e_entry[8]; /* Entry point virtual address */ + unsigned char e_phoff[8]; /* Program header table file offset */ + unsigned char e_shoff[8]; /* Section header table file offset */ + unsigned char e_flags[4]; /* Processor-specific flags */ + unsigned char e_ehsize[2]; /* ELF header size in bytes */ + unsigned char e_phentsize[2]; /* Program header table entry size */ + unsigned char e_phnum[2]; /* Program header table entry count */ + unsigned char e_shentsize[2]; /* Section header table entry size */ + unsigned char e_shnum[2]; /* Section header table entry count */ + unsigned char e_shstrndx[2]; /* Section header string table index */ +} Elf64_External_Ehdr; + +/* Program header */ + +typedef struct { + unsigned char p_type[4]; /* Identifies program segment type */ + unsigned char p_offset[4]; /* Segment file offset */ + unsigned char p_vaddr[4]; /* Segment virtual address */ + unsigned char p_paddr[4]; /* Segment physical address */ + unsigned char p_filesz[4]; /* Segment size in file */ + unsigned char p_memsz[4]; /* Segment size in memory */ + unsigned char p_flags[4]; /* Segment flags */ + unsigned char p_align[4]; /* Segment alignment, file & memory */ +} Elf32_External_Phdr; + +typedef struct { + unsigned char p_type[4]; /* Identifies program segment type */ + unsigned char p_flags[4]; /* Segment flags */ + unsigned char p_offset[8]; /* Segment file offset */ + unsigned char p_vaddr[8]; /* Segment virtual address */ + unsigned char p_paddr[8]; /* Segment physical address */ + unsigned char p_filesz[8]; /* Segment size in file */ + unsigned char p_memsz[8]; /* Segment size in memory */ + unsigned char p_align[8]; /* Segment alignment, file & memory */ +} Elf64_External_Phdr; + +/* Section header */ + +typedef struct { + unsigned char sh_name[4]; /* Section name, index in string tbl */ + unsigned char sh_type[4]; /* Type of section */ + unsigned char sh_flags[4]; /* Miscellaneous section attributes */ + unsigned char sh_addr[4]; /* Section virtual addr at execution */ + unsigned char sh_offset[4]; /* Section file offset */ + unsigned char sh_size[4]; /* Size of section in bytes */ + unsigned char sh_link[4]; /* Index of another section */ + unsigned char sh_info[4]; /* Additional section information */ + unsigned char sh_addralign[4]; /* Section alignment */ + unsigned char sh_entsize[4]; /* Entry size if section holds table */ +} Elf32_External_Shdr; + +typedef struct { + unsigned char sh_name[4]; /* Section name, index in string tbl */ + unsigned char sh_type[4]; /* Type of section */ + unsigned char sh_flags[8]; /* Miscellaneous section attributes */ + unsigned char sh_addr[8]; /* Section virtual addr at execution */ + unsigned char sh_offset[8]; /* Section file offset */ + unsigned char sh_size[8]; /* Size of section in bytes */ + unsigned char sh_link[4]; /* Index of another section */ + unsigned char sh_info[4]; /* Additional section information */ + unsigned char sh_addralign[8]; /* Section alignment */ + unsigned char sh_entsize[8]; /* Entry size if section holds table */ +} Elf64_External_Shdr; + +/* Symbol table entry */ + +typedef struct { + unsigned char st_name[4]; /* Symbol name, index in string tbl */ + unsigned char st_value[4]; /* Value of the symbol */ + unsigned char st_size[4]; /* Associated symbol size */ + unsigned char st_info[1]; /* Type and binding attributes */ + unsigned char st_other[1]; /* No defined meaning, 0 */ + unsigned char st_shndx[2]; /* Associated section index */ +} Elf32_External_Sym; + +typedef struct { + unsigned char st_name[4]; /* Symbol name, index in string tbl */ + unsigned char st_info[1]; /* Type and binding attributes */ + unsigned char st_other[1]; /* No defined meaning, 0 */ + unsigned char st_shndx[2]; /* Associated section index */ + unsigned char st_value[8]; /* Value of the symbol */ + unsigned char st_size[8]; /* Associated symbol size */ +} Elf64_External_Sym; + +typedef struct { + unsigned char est_shndx[4]; /* Section index */ +} Elf_External_Sym_Shndx; + +/* Note segments */ + +typedef struct { + unsigned char namesz[4]; /* Size of entry's owner string */ + unsigned char descsz[4]; /* Size of the note descriptor */ + unsigned char type[4]; /* Interpretation of the descriptor */ + char name[1]; /* Start of the name+desc data */ +} Elf_External_Note; + +/* Relocation Entries */ +typedef struct { + unsigned char r_offset[4]; /* Location at which to apply the action */ + unsigned char r_info[4]; /* index and type of relocation */ +} Elf32_External_Rel; + +typedef struct { + unsigned char r_offset[4]; /* Location at which to apply the action */ + unsigned char r_info[4]; /* index and type of relocation */ + unsigned char r_addend[4]; /* Constant addend used to compute value */ +} Elf32_External_Rela; + +typedef struct { + unsigned char r_offset[8]; /* Location at which to apply the action */ + unsigned char r_info[8]; /* index and type of relocation */ +} Elf64_External_Rel; + +typedef struct { + unsigned char r_offset[8]; /* Location at which to apply the action */ + unsigned char r_info[8]; /* index and type of relocation */ + unsigned char r_addend[8]; /* Constant addend used to compute value */ +} Elf64_External_Rela; + +/* dynamic section structure */ + +typedef struct { + unsigned char d_tag[4]; /* entry tag value */ + union { + unsigned char d_val[4]; + unsigned char d_ptr[4]; + } d_un; +} Elf32_External_Dyn; + +typedef struct { + unsigned char d_tag[8]; /* entry tag value */ + union { + unsigned char d_val[8]; + unsigned char d_ptr[8]; + } d_un; +} Elf64_External_Dyn; + +/* The version structures are currently size independent. They are + named without a 32 or 64. If that ever changes, these structures + will need to be renamed. */ + +/* This structure appears in a SHT_GNU_verdef section. */ + +typedef struct { + unsigned char vd_version[2]; + unsigned char vd_flags[2]; + unsigned char vd_ndx[2]; + unsigned char vd_cnt[2]; + unsigned char vd_hash[4]; + unsigned char vd_aux[4]; + unsigned char vd_next[4]; +} Elf_External_Verdef; + +/* This structure appears in a SHT_GNU_verdef section. */ + +typedef struct { + unsigned char vda_name[4]; + unsigned char vda_next[4]; +} Elf_External_Verdaux; + +/* This structure appears in a SHT_GNU_verneed section. */ + +typedef struct { + unsigned char vn_version[2]; + unsigned char vn_cnt[2]; + unsigned char vn_file[4]; + unsigned char vn_aux[4]; + unsigned char vn_next[4]; +} Elf_External_Verneed; + +/* This structure appears in a SHT_GNU_verneed section. */ + +typedef struct { + unsigned char vna_hash[4]; + unsigned char vna_flags[2]; + unsigned char vna_other[2]; + unsigned char vna_name[4]; + unsigned char vna_next[4]; +} Elf_External_Vernaux; + +/* This structure appears in a SHT_GNU_versym section. This is not a + standard ELF structure; ELF just uses Elf32_Half. */ + +typedef struct { + unsigned char vs_vers[2]; +} ATTRIBUTE_PACKED Elf_External_Versym; + +/* Structure for syminfo section. */ +typedef struct +{ + unsigned char si_boundto[2]; + unsigned char si_flags[2]; +} Elf_External_Syminfo; + + +/* This structure appears on the stack and in NT_AUXV core file notes. */ +typedef struct +{ + unsigned char a_type[4]; + unsigned char a_val[4]; +} Elf32_External_Auxv; + +typedef struct +{ + unsigned char a_type[8]; + unsigned char a_val[8]; +} Elf64_External_Auxv; + +/* Size of SHT_GROUP section entry. */ + +#define GRP_ENTRY_SIZE 4 + +#endif /* _ELF_EXTERNAL_H */ diff --git a/kernel/fiasco/src/lib/disasm/elf/i386.h b/kernel/fiasco/src/lib/disasm/elf/i386.h new file mode 100644 index 00000000..e167871f --- /dev/null +++ b/kernel/fiasco/src/lib/disasm/elf/i386.h @@ -0,0 +1,78 @@ +/* ix86 ELF support for BFD. + Copyright 1998, 1999, 2000, 2002, 2004, 2005, 2006 + Free Software Foundation, Inc. + + This file is part of BFD, the Binary File Descriptor library. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ + +#ifndef _ELF_I386_H +#define _ELF_I386_H + +#include "elf/reloc-macros.h" + +START_RELOC_NUMBERS (elf_i386_reloc_type) + RELOC_NUMBER (R_386_NONE, 0) /* No reloc */ + RELOC_NUMBER (R_386_32, 1) /* Direct 32 bit */ + RELOC_NUMBER (R_386_PC32, 2) /* PC relative 32 bit */ + RELOC_NUMBER (R_386_GOT32, 3) /* 32 bit GOT entry */ + RELOC_NUMBER (R_386_PLT32, 4) /* 32 bit PLT address */ + RELOC_NUMBER (R_386_COPY, 5) /* Copy symbol at runtime */ + RELOC_NUMBER (R_386_GLOB_DAT, 6) /* Create GOT entry */ + RELOC_NUMBER (R_386_JUMP_SLOT, 7) /* Create PLT entry */ + RELOC_NUMBER (R_386_RELATIVE, 8) /* Adjust by program base */ + RELOC_NUMBER (R_386_GOTOFF, 9) /* 32 bit offset to GOT */ + RELOC_NUMBER (R_386_GOTPC, 10) /* 32 bit PC relative offset to GOT */ + RELOC_NUMBER (R_386_32PLT, 11) /* Used by Sun */ + FAKE_RELOC (FIRST_INVALID_RELOC, 12) + FAKE_RELOC (LAST_INVALID_RELOC, 13) + RELOC_NUMBER (R_386_TLS_TPOFF,14) + RELOC_NUMBER (R_386_TLS_IE, 15) + RELOC_NUMBER (R_386_TLS_GOTIE,16) + RELOC_NUMBER (R_386_TLS_LE, 17) + RELOC_NUMBER (R_386_TLS_GD, 18) + RELOC_NUMBER (R_386_TLS_LDM, 19) + RELOC_NUMBER (R_386_16, 20) + RELOC_NUMBER (R_386_PC16, 21) + RELOC_NUMBER (R_386_8, 22) + RELOC_NUMBER (R_386_PC8, 23) + RELOC_NUMBER (R_386_TLS_GD_32, 24) + RELOC_NUMBER (R_386_TLS_GD_PUSH, 25) + RELOC_NUMBER (R_386_TLS_GD_CALL, 26) + RELOC_NUMBER (R_386_TLS_GD_POP, 27) + RELOC_NUMBER (R_386_TLS_LDM_32, 28) + RELOC_NUMBER (R_386_TLS_LDM_PUSH, 29) + RELOC_NUMBER (R_386_TLS_LDM_CALL, 30) + RELOC_NUMBER (R_386_TLS_LDM_POP, 31) + RELOC_NUMBER (R_386_TLS_LDO_32, 32) + RELOC_NUMBER (R_386_TLS_IE_32, 33) + RELOC_NUMBER (R_386_TLS_LE_32, 34) + RELOC_NUMBER (R_386_TLS_DTPMOD32, 35) + RELOC_NUMBER (R_386_TLS_DTPOFF32, 36) + RELOC_NUMBER (R_386_TLS_TPOFF32, 37) +/* 38 */ + RELOC_NUMBER (R_386_TLS_GOTDESC, 39) + RELOC_NUMBER (R_386_TLS_DESC_CALL,40) + RELOC_NUMBER (R_386_TLS_DESC, 41) + + /* Used by Intel. */ + RELOC_NUMBER (R_386_USED_BY_INTEL_200, 200) + + /* These are GNU extensions to enable C++ vtable garbage collection. */ + RELOC_NUMBER (R_386_GNU_VTINHERIT, 250) + RELOC_NUMBER (R_386_GNU_VTENTRY, 251) +END_RELOC_NUMBERS (R_386_max) + +#endif diff --git a/kernel/fiasco/src/lib/disasm/elf/internal.h b/kernel/fiasco/src/lib/disasm/elf/internal.h new file mode 100644 index 00000000..15217113 --- /dev/null +++ b/kernel/fiasco/src/lib/disasm/elf/internal.h @@ -0,0 +1,299 @@ +/* ELF support for BFD. + Copyright 1991, 1992, 1993, 1994, 1995, 1997, 1998, 2000, 2001, 2002, + 2003, 2006, 2007 Free Software Foundation, Inc. + + Written by Fred Fish @ Cygnus Support, from information published + in "UNIX System V Release 4, Programmers Guide: ANSI C and + Programming Support Tools". + +This file is part of BFD, the Binary File Descriptor library. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ + + +/* This file is part of ELF support for BFD, and contains the portions + that describe how ELF is represented internally in the BFD library. + I.E. it describes the in-memory representation of ELF. It requires + the elf-common.h file which contains the portions that are common to + both the internal and external representations. */ + + +/* NOTE that these structures are not kept in the same order as they appear + in the object file. In some cases they've been reordered for more optimal + packing under various circumstances. */ + +#ifndef _ELF_INTERNAL_H +#define _ELF_INTERNAL_H + +/* ELF Header */ + +#define EI_NIDENT 16 /* Size of e_ident[] */ + +typedef struct elf_internal_ehdr { + unsigned char e_ident[EI_NIDENT]; /* ELF "magic number" */ + bfd_vma e_entry; /* Entry point virtual address */ + bfd_size_type e_phoff; /* Program header table file offset */ + bfd_size_type e_shoff; /* Section header table file offset */ + unsigned long e_version; /* Identifies object file version */ + unsigned long e_flags; /* Processor-specific flags */ + unsigned short e_type; /* Identifies object file type */ + unsigned short e_machine; /* Specifies required architecture */ + unsigned int e_ehsize; /* ELF header size in bytes */ + unsigned int e_phentsize; /* Program header table entry size */ + unsigned int e_phnum; /* Program header table entry count */ + unsigned int e_shentsize; /* Section header table entry size */ + unsigned int e_shnum; /* Section header table entry count */ + unsigned int e_shstrndx; /* Section header string table index */ +} Elf_Internal_Ehdr; + +/* Program header */ + +struct elf_internal_phdr { + unsigned long p_type; /* Identifies program segment type */ + unsigned long p_flags; /* Segment flags */ + bfd_vma p_offset; /* Segment file offset */ + bfd_vma p_vaddr; /* Segment virtual address */ + bfd_vma p_paddr; /* Segment physical address */ + bfd_vma p_filesz; /* Segment size in file */ + bfd_vma p_memsz; /* Segment size in memory */ + bfd_vma p_align; /* Segment alignment, file & memory */ +}; + +typedef struct elf_internal_phdr Elf_Internal_Phdr; + +/* Section header */ + +typedef struct elf_internal_shdr { + unsigned int sh_name; /* Section name, index in string tbl */ + unsigned int sh_type; /* Type of section */ + bfd_vma sh_flags; /* Miscellaneous section attributes */ + bfd_vma sh_addr; /* Section virtual addr at execution */ + bfd_size_type sh_size; /* Size of section in bytes */ + bfd_size_type sh_entsize; /* Entry size if section holds table */ + unsigned long sh_link; /* Index of another section */ + unsigned long sh_info; /* Additional section information */ + file_ptr sh_offset; /* Section file offset */ + unsigned int sh_addralign; /* Section alignment */ + + /* The internal rep also has some cached info associated with it. */ + asection * bfd_section; /* Associated BFD section. */ + unsigned char *contents; /* Section contents. */ +} Elf_Internal_Shdr; + +/* Symbol table entry */ + +struct elf_internal_sym { + bfd_vma st_value; /* Value of the symbol */ + bfd_vma st_size; /* Associated symbol size */ + unsigned long st_name; /* Symbol name, index in string tbl */ + unsigned char st_info; /* Type and binding attributes */ + unsigned char st_other; /* Visibilty, and target specific */ + unsigned int st_shndx; /* Associated section index */ +}; + +typedef struct elf_internal_sym Elf_Internal_Sym; + +/* Note segments */ + +typedef struct elf_internal_note { + unsigned long namesz; /* Size of entry's owner string */ + unsigned long descsz; /* Size of the note descriptor */ + unsigned long type; /* Interpretation of the descriptor */ + char * namedata; /* Start of the name+desc data */ + char * descdata; /* Start of the desc data */ + bfd_vma descpos; /* File offset of the descdata */ +} Elf_Internal_Note; + +/* Relocation Entries */ + +typedef struct elf_internal_rela { + bfd_vma r_offset; /* Location at which to apply the action */ + bfd_vma r_info; /* Index and Type of relocation */ + bfd_vma r_addend; /* Constant addend used to compute value */ +} Elf_Internal_Rela; + +/* dynamic section structure */ + +typedef struct elf_internal_dyn { + /* This needs to support 64-bit values in elf64. */ + bfd_vma d_tag; /* entry tag value */ + union { + /* This needs to support 64-bit values in elf64. */ + bfd_vma d_val; + bfd_vma d_ptr; + } d_un; +} Elf_Internal_Dyn; + +/* This structure appears in a SHT_GNU_verdef section. */ + +typedef struct elf_internal_verdef { + unsigned short vd_version; /* Version number of structure. */ + unsigned short vd_flags; /* Flags (VER_FLG_*). */ + unsigned short vd_ndx; /* Version index. */ + unsigned short vd_cnt; /* Number of verdaux entries. */ + unsigned long vd_hash; /* Hash of name. */ + unsigned long vd_aux; /* Offset to verdaux entries. */ + unsigned long vd_next; /* Offset to next verdef. */ + + /* These fields are set up when BFD reads in the structure. FIXME: + It would be cleaner to store these in a different structure. */ + bfd *vd_bfd; /* BFD. */ + const char *vd_nodename; /* Version name. */ + struct elf_internal_verdef *vd_nextdef; /* vd_next as pointer. */ + struct elf_internal_verdaux *vd_auxptr; /* vd_aux as pointer. */ + unsigned int vd_exp_refno; /* Used by the linker. */ +} Elf_Internal_Verdef; + +/* This structure appears in a SHT_GNU_verdef section. */ + +typedef struct elf_internal_verdaux { + unsigned long vda_name; /* String table offset of name. */ + unsigned long vda_next; /* Offset to next verdaux. */ + + /* These fields are set up when BFD reads in the structure. FIXME: + It would be cleaner to store these in a different structure. */ + const char *vda_nodename; /* vda_name as pointer. */ + struct elf_internal_verdaux *vda_nextptr; /* vda_next as pointer. */ +} Elf_Internal_Verdaux; + +/* This structure appears in a SHT_GNU_verneed section. */ + +typedef struct elf_internal_verneed { + unsigned short vn_version; /* Version number of structure. */ + unsigned short vn_cnt; /* Number of vernaux entries. */ + unsigned long vn_file; /* String table offset of library name. */ + unsigned long vn_aux; /* Offset to vernaux entries. */ + unsigned long vn_next; /* Offset to next verneed. */ + + /* These fields are set up when BFD reads in the structure. FIXME: + It would be cleaner to store these in a different structure. */ + bfd *vn_bfd; /* BFD. */ + const char *vn_filename; /* vn_file as pointer. */ + struct elf_internal_vernaux *vn_auxptr; /* vn_aux as pointer. */ + struct elf_internal_verneed *vn_nextref; /* vn_nextref as pointer. */ +} Elf_Internal_Verneed; + +/* This structure appears in a SHT_GNU_verneed section. */ + +typedef struct elf_internal_vernaux { + unsigned long vna_hash; /* Hash of dependency name. */ + unsigned short vna_flags; /* Flags (VER_FLG_*). */ + unsigned short vna_other; /* Unused. */ + unsigned long vna_name; /* String table offset to version name. */ + unsigned long vna_next; /* Offset to next vernaux. */ + + /* These fields are set up when BFD reads in the structure. FIXME: + It would be cleaner to store these in a different structure. */ + const char *vna_nodename; /* vna_name as pointer. */ + struct elf_internal_vernaux *vna_nextptr; /* vna_next as pointer. */ +} Elf_Internal_Vernaux; + +/* This structure appears in a SHT_GNU_versym section. This is not a + standard ELF structure; ELF just uses Elf32_Half. */ + +typedef struct elf_internal_versym { + unsigned short vs_vers; +} Elf_Internal_Versym; + +/* Structure for syminfo section. */ +typedef struct +{ + unsigned short int si_boundto; + unsigned short int si_flags; +} Elf_Internal_Syminfo; + +/* This structure appears on the stack and in NT_AUXV core file notes. */ +typedef struct +{ + bfd_vma a_type; + bfd_vma a_val; +} Elf_Internal_Auxv; + + +/* This structure is used to describe how sections should be assigned + to program segments. */ + +struct elf_segment_map +{ + /* Next program segment. */ + struct elf_segment_map *next; + /* Program segment type. */ + unsigned long p_type; + /* Program segment flags. */ + unsigned long p_flags; + /* Program segment physical address. */ + bfd_vma p_paddr; + /* Program segment virtual address offset from section vma. */ + bfd_vma p_vaddr_offset; + /* Program segment alignment. */ + bfd_vma p_align; + /* Whether the p_flags field is valid; if not, the flags are based + on the section flags. */ + unsigned int p_flags_valid : 1; + /* Whether the p_paddr field is valid; if not, the physical address + is based on the section lma values. */ + unsigned int p_paddr_valid : 1; + /* Whether the p_align field is valid; if not, PT_LOAD segment + alignment is based on the default maximum page size. */ + unsigned int p_align_valid : 1; + /* Whether this segment includes the file header. */ + unsigned int includes_filehdr : 1; + /* Whether this segment includes the program headers. */ + unsigned int includes_phdrs : 1; + /* Number of sections (may be 0). */ + unsigned int count; + /* Sections. Actual number of elements is in count field. */ + asection *sections[1]; +}; + +/* .tbss is special. It doesn't contribute memory space to normal + segments and it doesn't take file space in normal segments. */ +#define ELF_SECTION_SIZE(sec_hdr, segment) \ + (((sec_hdr->sh_flags & SHF_TLS) == 0 \ + || sec_hdr->sh_type != SHT_NOBITS \ + || segment->p_type == PT_TLS) ? sec_hdr->sh_size : 0) + +/* Decide if the given sec_hdr is in the given segment. PT_TLS segment + contains only SHF_TLS sections. Only PT_LOAD and PT_TLS segments + can contain SHF_TLS sections. */ +#define ELF_IS_SECTION_IN_SEGMENT(sec_hdr, segment) \ + (((((sec_hdr->sh_flags & SHF_TLS) != 0) \ + && (segment->p_type == PT_TLS \ + || segment->p_type == PT_LOAD)) \ + || ((sec_hdr->sh_flags & SHF_TLS) == 0 \ + && segment->p_type != PT_TLS)) \ + /* Any section besides one of type SHT_NOBITS must have a file \ + offset within the segment. */ \ + && (sec_hdr->sh_type == SHT_NOBITS \ + || ((bfd_vma) sec_hdr->sh_offset >= segment->p_offset \ + && (sec_hdr->sh_offset + ELF_SECTION_SIZE(sec_hdr, segment) \ + <= segment->p_offset + segment->p_filesz))) \ + /* SHF_ALLOC sections must have VMAs within the segment. */ \ + && ((sec_hdr->sh_flags & SHF_ALLOC) == 0 \ + || (sec_hdr->sh_addr >= segment->p_vaddr \ + && (sec_hdr->sh_addr + ELF_SECTION_SIZE(sec_hdr, segment) \ + <= segment->p_vaddr + segment->p_memsz)))) + +/* Decide if the given sec_hdr is in the given segment in file. */ +#define ELF_IS_SECTION_IN_SEGMENT_FILE(sec_hdr, segment) \ + (sec_hdr->sh_size > 0 \ + && ELF_IS_SECTION_IN_SEGMENT (sec_hdr, segment)) + +/* Decide if the given sec_hdr is in the given segment in memory. */ +#define ELF_IS_SECTION_IN_SEGMENT_MEMORY(sec_hdr, segment) \ + (ELF_SECTION_SIZE(sec_hdr, segment) > 0 \ + && ELF_IS_SECTION_IN_SEGMENT (sec_hdr, segment)) + +#endif /* _ELF_INTERNAL_H */ diff --git a/kernel/fiasco/src/lib/disasm/elf/reloc-macros.h b/kernel/fiasco/src/lib/disasm/elf/reloc-macros.h new file mode 100644 index 00000000..a67419d2 --- /dev/null +++ b/kernel/fiasco/src/lib/disasm/elf/reloc-macros.h @@ -0,0 +1,101 @@ +/* Generic relocation support for BFD. + Copyright 1998, 1999, 2000, 2003 Free Software Foundation, Inc. + + This file is part of BFD, the Binary File Descriptor library. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ + +/* These macros are used by the various *.h target specific header + files to either generate an enum containing all the known relocations + for that target, or if RELOC_MACROS_GEN_FUNC is defined, a recognition + function is generated instead. (This is used by binutils/readelf.c) + + Given a header file like this: + + START_RELOC_NUMBERS (foo) + RELOC_NUMBER (R_foo_NONE, 0) + RELOC_NUMBER (R_foo_32, 1) + EMPTY_RELOC (R_foo_good) + FAKE_RELOC (R_foo_illegal, 9) + END_RELOC_NUMBERS (R_foo_count) + + Then the following will be produced by default (ie if + RELOC_MACROS_GEN_FUNC is *not* defined). + + enum foo + { + R_foo_NONE = 0, + R_foo_32 = 1, + R_foo_good, + R_foo_illegal = 9, + R_foo_count + }; + + If RELOC_MACROS_GEN_FUNC *is* defined, then instead the + following function will be generated: + + static const char *foo (unsigned long rtype); + static const char * + foo (unsigned long rtype) + { + switch (rtype) + { + case 0: return "R_foo_NONE"; + case 1: return "R_foo_32"; + default: return NULL; + } + } + */ + +#ifndef _RELOC_MACROS_H +#define _RELOC_MACROS_H + +#ifdef RELOC_MACROS_GEN_FUNC + +/* This function takes the relocation number and returns the + string version name of the name of that relocation. If + the relocation is not recognised, NULL is returned. */ + +#define START_RELOC_NUMBERS(name) \ +static const char *name (unsigned long rtype); \ +static const char * \ +name (unsigned long rtype) \ +{ \ + switch (rtype) \ + { + +#define RELOC_NUMBER(name, number) \ + case number: return #name; + +#define FAKE_RELOC(name, number) +#define EMPTY_RELOC(name) + +#define END_RELOC_NUMBERS(name) \ + default: return NULL; \ + } \ +} + + +#else /* Default to generating enum. */ + +#define START_RELOC_NUMBERS(name) enum name { +#define RELOC_NUMBER(name, number) name = number, +#define FAKE_RELOC(name, number) name = number, +#define EMPTY_RELOC(name) name, +#define END_RELOC_NUMBERS(name) name }; + +#endif + +#endif /* _RELOC_MACROS_H */ diff --git a/kernel/fiasco/src/lib/disasm/elf/x86-64.h b/kernel/fiasco/src/lib/disasm/elf/x86-64.h new file mode 100644 index 00000000..b09a558a --- /dev/null +++ b/kernel/fiasco/src/lib/disasm/elf/x86-64.h @@ -0,0 +1,87 @@ +/* x86_64 ELF support for BFD. + Copyright (C) 2000, 2001, 2002, 2004, 2005, 2006 + Free Software Foundation, Inc. + Contributed by Jan Hubicka + + This file is part of BFD, the Binary File Descriptor library. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ + +#ifndef _ELF_X86_64_H +#define _ELF_X86_64_H + +#include "elf/reloc-macros.h" + +START_RELOC_NUMBERS (elf_x86_64_reloc_type) + RELOC_NUMBER (R_X86_64_NONE, 0) /* No reloc */ + RELOC_NUMBER (R_X86_64_64, 1) /* Direct 64 bit */ + RELOC_NUMBER (R_X86_64_PC32, 2) /* PC relative 32 bit signed */ + RELOC_NUMBER (R_X86_64_GOT32, 3) /* 32 bit GOT entry */ + RELOC_NUMBER (R_X86_64_PLT32, 4) /* 32 bit PLT address */ + RELOC_NUMBER (R_X86_64_COPY, 5) /* Copy symbol at runtime */ + RELOC_NUMBER (R_X86_64_GLOB_DAT, 6) /* Create GOT entry */ + RELOC_NUMBER (R_X86_64_JUMP_SLOT,7) /* Create PLT entry */ + RELOC_NUMBER (R_X86_64_RELATIVE, 8) /* Adjust by program base */ + RELOC_NUMBER (R_X86_64_GOTPCREL, 9) /* 32 bit signed pc relative + offset to GOT entry */ + RELOC_NUMBER (R_X86_64_32, 10) /* Direct 32 bit zero extended */ + RELOC_NUMBER (R_X86_64_32S, 11) /* Direct 32 bit sign extended */ + RELOC_NUMBER (R_X86_64_16, 12) /* Direct 16 bit zero extended */ + RELOC_NUMBER (R_X86_64_PC16, 13) /* 16 bit sign extended pc relative*/ + RELOC_NUMBER (R_X86_64_8, 14) /* Direct 8 bit sign extended */ + RELOC_NUMBER (R_X86_64_PC8, 15) /* 8 bit sign extended pc relative*/ + RELOC_NUMBER (R_X86_64_DTPMOD64, 16) /* ID of module containing symbol */ + RELOC_NUMBER (R_X86_64_DTPOFF64, 17) /* Offset in TLS block */ + RELOC_NUMBER (R_X86_64_TPOFF64, 18) /* Offset in initial TLS block */ + RELOC_NUMBER (R_X86_64_TLSGD, 19) /* PC relative offset to GD GOT block */ + RELOC_NUMBER (R_X86_64_TLSLD, 20) /* PC relative offset to LD GOT block */ + RELOC_NUMBER (R_X86_64_DTPOFF32, 21) /* Offset in TLS block */ + RELOC_NUMBER (R_X86_64_GOTTPOFF, 22) /* PC relative offset to IE GOT entry */ + RELOC_NUMBER (R_X86_64_TPOFF32, 23) /* Offset in initial TLS block */ + RELOC_NUMBER (R_X86_64_PC64, 24) /* PC relative 64 bit */ + RELOC_NUMBER (R_X86_64_GOTOFF64, 25) /* 64 bit offset to GOT */ + RELOC_NUMBER (R_X86_64_GOTPC32, 26) /* 32 bit signed pc relative + offset to GOT */ + RELOC_NUMBER (R_X86_64_GOT64, 27) /* 64 bit GOT entry offset */ + RELOC_NUMBER (R_X86_64_GOTPCREL64, 28) /* 64 bit signed pc relative + offset to GOT entry */ + RELOC_NUMBER (R_X86_64_GOTPC64, 29) /* 64 bit signed pc relative + offset to GOT */ + RELOC_NUMBER (R_X86_64_GOTPLT64, 30) /* like GOT64, but indicates + that PLT entry is needed */ + RELOC_NUMBER (R_X86_64_PLTOFF64, 31) /* 64 bit GOT relative offset + to PLT entry */ + /* 32 .. 33 */ + RELOC_NUMBER (R_X86_64_GOTPC32_TLSDESC, 34) + /* 32 bit signed pc relative + offset to TLS descriptor + in the GOT. */ + RELOC_NUMBER (R_X86_64_TLSDESC_CALL, 35) /* Relaxable call through TLS + descriptor. */ + RELOC_NUMBER (R_X86_64_TLSDESC, 36) /* 2x64-bit TLS descriptor. */ + RELOC_NUMBER (R_X86_64_GNU_VTINHERIT, 250) /* GNU C++ hack */ + RELOC_NUMBER (R_X86_64_GNU_VTENTRY, 251) /* GNU C++ hack */ +END_RELOC_NUMBERS (R_X86_64_max) + +/* Processor specific section types. */ + +#define SHT_X86_64_UNWIND 0x70000001 /* unwind information */ + +/* Like SHN_COMMON but the symbol will be allocated in the .lbss + section. */ +#define SHN_X86_64_LCOMMON 0xff02 + +#define SHF_X86_64_LARGE 0x10000000 +#endif diff --git a/kernel/fiasco/src/lib/disasm/include/ansidecl.h b/kernel/fiasco/src/lib/disasm/include/ansidecl.h new file mode 100644 index 00000000..c19955a9 --- /dev/null +++ b/kernel/fiasco/src/lib/disasm/include/ansidecl.h @@ -0,0 +1,393 @@ +/* ANSI and traditional C compatability macros + Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ + +/* ANSI and traditional C compatibility macros + + ANSI C is assumed if __STDC__ is #defined. + + Macro ANSI C definition Traditional C definition + ----- ---- - ---------- ----------- - ---------- + ANSI_PROTOTYPES 1 not defined + PTR `void *' `char *' + PTRCONST `void *const' `char *' + LONG_DOUBLE `long double' `double' + const not defined `' + volatile not defined `' + signed not defined `' + VA_START(ap, var) va_start(ap, var) va_start(ap) + + Note that it is safe to write "void foo();" indicating a function + with no return value, in all K+R compilers we have been able to test. + + For declaring functions with prototypes, we also provide these: + + PARAMS ((prototype)) + -- for functions which take a fixed number of arguments. Use this + when declaring the function. When defining the function, write a + K+R style argument list. For example: + + char *strcpy PARAMS ((char *dest, char *source)); + ... + char * + strcpy (dest, source) + char *dest; + char *source; + { ... } + + + VPARAMS ((prototype, ...)) + -- for functions which take a variable number of arguments. Use + PARAMS to declare the function, VPARAMS to define it. For example: + + int printf PARAMS ((const char *format, ...)); + ... + int + printf VPARAMS ((const char *format, ...)) + { + ... + } + + For writing functions which take variable numbers of arguments, we + also provide the VA_OPEN, VA_CLOSE, and VA_FIXEDARG macros. These + hide the differences between K+R and C89 more + thoroughly than the simple VA_START() macro mentioned above. + + VA_OPEN and VA_CLOSE are used *instead of* va_start and va_end. + Immediately after VA_OPEN, put a sequence of VA_FIXEDARG calls + corresponding to the list of fixed arguments. Then use va_arg + normally to get the variable arguments, or pass your va_list object + around. You do not declare the va_list yourself; VA_OPEN does it + for you. + + Here is a complete example: + + int + printf VPARAMS ((const char *format, ...)) + { + int result; + + VA_OPEN (ap, format); + VA_FIXEDARG (ap, const char *, format); + + result = vfprintf (stdout, format, ap); + VA_CLOSE (ap); + + return result; + } + + + You can declare variables either before or after the VA_OPEN, + VA_FIXEDARG sequence. Also, VA_OPEN and VA_CLOSE are the beginning + and end of a block. They must appear at the same nesting level, + and any variables declared after VA_OPEN go out of scope at + VA_CLOSE. Unfortunately, with a K+R compiler, that includes the + argument list. You can have multiple instances of VA_OPEN/VA_CLOSE + pairs in a single function in case you need to traverse the + argument list more than once. + + For ease of writing code which uses GCC extensions but needs to be + portable to other compilers, we provide the GCC_VERSION macro that + simplifies testing __GNUC__ and __GNUC_MINOR__ together, and various + wrappers around __attribute__. Also, __extension__ will be #defined + to nothing if it doesn't work. See below. + + This header also defines a lot of obsolete macros: + CONST, VOLATILE, SIGNED, PROTO, EXFUN, DEFUN, DEFUN_VOID, + AND, DOTS, NOARGS. Don't use them. */ + +#ifndef _ANSIDECL_H +#define _ANSIDECL_H 1 + +/* Every source file includes this file, + so they will all get the switch for lint. */ +/* LINTLIBRARY */ + +/* Using MACRO(x,y) in cpp #if conditionals does not work with some + older preprocessors. Thus we can't define something like this: + +#define HAVE_GCC_VERSION(MAJOR, MINOR) \ + (__GNUC__ > (MAJOR) || (__GNUC__ == (MAJOR) && __GNUC_MINOR__ >= (MINOR))) + +and then test "#if HAVE_GCC_VERSION(2,7)". + +So instead we use the macro below and test it against specific values. */ + +/* This macro simplifies testing whether we are using gcc, and if it + is of a particular minimum version. (Both major & minor numbers are + significant.) This macro will evaluate to 0 if we are not using + gcc at all. */ +#ifndef GCC_VERSION +#define GCC_VERSION (__GNUC__ * 1000 + __GNUC_MINOR__) +#endif /* GCC_VERSION */ + +#if defined (__STDC__) || defined (_AIX) || (defined (__mips) && defined (_SYSTYPE_SVR4)) || defined(_WIN32) || (defined(__alpha) && defined(__cplusplus)) +/* All known AIX compilers implement these things (but don't always + define __STDC__). The RISC/OS MIPS compiler defines these things + in SVR4 mode, but does not define __STDC__. */ +/* eraxxon@alumni.rice.edu: The Compaq C++ compiler, unlike many other + C++ compilers, does not define __STDC__, though it acts as if this + was so. (Verified versions: 5.7, 6.2, 6.3, 6.5) */ + +#define ANSI_PROTOTYPES 1 +#define PTR void * +#define PTRCONST void *const +#define LONG_DOUBLE long double + +/* PARAMS is often defined elsewhere (e.g. by libintl.h), so wrap it in + a #ifndef. */ +#ifndef PARAMS +#define PARAMS(ARGS) ARGS +#endif + +#define VPARAMS(ARGS) ARGS +#define VA_START(VA_LIST, VAR) va_start(VA_LIST, VAR) + +/* variadic function helper macros */ +/* "struct Qdmy" swallows the semicolon after VA_OPEN/VA_FIXEDARG's + use without inhibiting further decls and without declaring an + actual variable. */ +#define VA_OPEN(AP, VAR) { va_list AP; va_start(AP, VAR); { struct Qdmy +#define VA_CLOSE(AP) } va_end(AP); } +#define VA_FIXEDARG(AP, T, N) struct Qdmy + +#undef const +#undef volatile +#undef signed + +/* inline requires special treatment; it's in C99, and GCC >=2.7 supports + it too, but it's not in C89. */ +#undef inline +#if __STDC_VERSION__ > 199901L +/* it's a keyword */ +#else +# if GCC_VERSION >= 2007 +# define inline __inline__ /* __inline__ prevents -pedantic warnings */ +# else +# define inline /* nothing */ +# endif +#endif + +/* These are obsolete. Do not use. */ +#ifndef IN_GCC +#define CONST const +#define VOLATILE volatile +#define SIGNED signed + +#define PROTO(type, name, arglist) type name arglist +#define EXFUN(name, proto) name proto +#define DEFUN(name, arglist, args) name(args) +#define DEFUN_VOID(name) name(void) +#define AND , +#define DOTS , ... +#define NOARGS void +#endif /* ! IN_GCC */ + +#else /* Not ANSI C. */ + +#undef ANSI_PROTOTYPES +#define PTR char * +#define PTRCONST PTR +#define LONG_DOUBLE double + +#define PARAMS(args) () +#define VPARAMS(args) (va_alist) va_dcl +#define VA_START(va_list, var) va_start(va_list) + +#define VA_OPEN(AP, VAR) { va_list AP; va_start(AP); { struct Qdmy +#define VA_CLOSE(AP) } va_end(AP); } +#define VA_FIXEDARG(AP, TYPE, NAME) TYPE NAME = va_arg(AP, TYPE) + +/* some systems define these in header files for non-ansi mode */ +#undef const +#undef volatile +#undef signed +#undef inline +#define const +#define volatile +#define signed +#define inline + +#ifndef IN_GCC +#define CONST +#define VOLATILE +#define SIGNED + +#define PROTO(type, name, arglist) type name () +#define EXFUN(name, proto) name() +#define DEFUN(name, arglist, args) name arglist args; +#define DEFUN_VOID(name) name() +#define AND ; +#define DOTS +#define NOARGS +#endif /* ! IN_GCC */ + +#endif /* ANSI C. */ + +/* Define macros for some gcc attributes. This permits us to use the + macros freely, and know that they will come into play for the + version of gcc in which they are supported. */ + +#if (GCC_VERSION < 2007) +# define __attribute__(x) +#endif + +/* Attribute __malloc__ on functions was valid as of gcc 2.96. */ +#ifndef ATTRIBUTE_MALLOC +# if (GCC_VERSION >= 2096) +# define ATTRIBUTE_MALLOC __attribute__ ((__malloc__)) +# else +# define ATTRIBUTE_MALLOC +# endif /* GNUC >= 2.96 */ +#endif /* ATTRIBUTE_MALLOC */ + +/* Attributes on labels were valid as of gcc 2.93. */ +#ifndef ATTRIBUTE_UNUSED_LABEL +# if (!defined (__cplusplus) && GCC_VERSION >= 2093) +# define ATTRIBUTE_UNUSED_LABEL ATTRIBUTE_UNUSED +# else +# define ATTRIBUTE_UNUSED_LABEL +# endif /* !__cplusplus && GNUC >= 2.93 */ +#endif /* ATTRIBUTE_UNUSED_LABEL */ + +#ifndef ATTRIBUTE_UNUSED +#define ATTRIBUTE_UNUSED __attribute__ ((__unused__)) +#endif /* ATTRIBUTE_UNUSED */ + +/* Before GCC 3.4, the C++ frontend couldn't parse attributes placed after the + identifier name. */ +#if ! defined(__cplusplus) || (GCC_VERSION >= 3004) +# define ARG_UNUSED(NAME) NAME ATTRIBUTE_UNUSED +#else /* !__cplusplus || GNUC >= 3.4 */ +# define ARG_UNUSED(NAME) NAME +#endif /* !__cplusplus || GNUC >= 3.4 */ + +#ifndef ATTRIBUTE_NORETURN +#define ATTRIBUTE_NORETURN __attribute__ ((__noreturn__)) +#endif /* ATTRIBUTE_NORETURN */ + +/* Attribute `nonnull' was valid as of gcc 3.3. */ +#ifndef ATTRIBUTE_NONNULL +# if (GCC_VERSION >= 3003) +# define ATTRIBUTE_NONNULL(m) __attribute__ ((__nonnull__ (m))) +# else +# define ATTRIBUTE_NONNULL(m) +# endif /* GNUC >= 3.3 */ +#endif /* ATTRIBUTE_NONNULL */ + +/* Attribute `pure' was valid as of gcc 3.0. */ +#ifndef ATTRIBUTE_PURE +# if (GCC_VERSION >= 3000) +# define ATTRIBUTE_PURE __attribute__ ((__pure__)) +# else +# define ATTRIBUTE_PURE +# endif /* GNUC >= 3.0 */ +#endif /* ATTRIBUTE_PURE */ + +/* Use ATTRIBUTE_PRINTF when the format specifier must not be NULL. + This was the case for the `printf' format attribute by itself + before GCC 3.3, but as of 3.3 we need to add the `nonnull' + attribute to retain this behavior. */ +#ifndef ATTRIBUTE_PRINTF +#define ATTRIBUTE_PRINTF(m, n) __attribute__ ((__format__ (__printf__, m, n))) ATTRIBUTE_NONNULL(m) +#define ATTRIBUTE_PRINTF_1 ATTRIBUTE_PRINTF(1, 2) +#define ATTRIBUTE_PRINTF_2 ATTRIBUTE_PRINTF(2, 3) +#define ATTRIBUTE_PRINTF_3 ATTRIBUTE_PRINTF(3, 4) +#define ATTRIBUTE_PRINTF_4 ATTRIBUTE_PRINTF(4, 5) +#define ATTRIBUTE_PRINTF_5 ATTRIBUTE_PRINTF(5, 6) +#endif /* ATTRIBUTE_PRINTF */ + +/* Use ATTRIBUTE_FPTR_PRINTF when the format attribute is to be set on + a function pointer. Format attributes were allowed on function + pointers as of gcc 3.1. */ +#ifndef ATTRIBUTE_FPTR_PRINTF +# if (GCC_VERSION >= 3001) +# define ATTRIBUTE_FPTR_PRINTF(m, n) ATTRIBUTE_PRINTF(m, n) +# else +# define ATTRIBUTE_FPTR_PRINTF(m, n) +# endif /* GNUC >= 3.1 */ +# define ATTRIBUTE_FPTR_PRINTF_1 ATTRIBUTE_FPTR_PRINTF(1, 2) +# define ATTRIBUTE_FPTR_PRINTF_2 ATTRIBUTE_FPTR_PRINTF(2, 3) +# define ATTRIBUTE_FPTR_PRINTF_3 ATTRIBUTE_FPTR_PRINTF(3, 4) +# define ATTRIBUTE_FPTR_PRINTF_4 ATTRIBUTE_FPTR_PRINTF(4, 5) +# define ATTRIBUTE_FPTR_PRINTF_5 ATTRIBUTE_FPTR_PRINTF(5, 6) +#endif /* ATTRIBUTE_FPTR_PRINTF */ + +/* Use ATTRIBUTE_NULL_PRINTF when the format specifier may be NULL. A + NULL format specifier was allowed as of gcc 3.3. */ +#ifndef ATTRIBUTE_NULL_PRINTF +# if (GCC_VERSION >= 3003) +# define ATTRIBUTE_NULL_PRINTF(m, n) __attribute__ ((__format__ (__printf__, m, n))) +# else +# define ATTRIBUTE_NULL_PRINTF(m, n) +# endif /* GNUC >= 3.3 */ +# define ATTRIBUTE_NULL_PRINTF_1 ATTRIBUTE_NULL_PRINTF(1, 2) +# define ATTRIBUTE_NULL_PRINTF_2 ATTRIBUTE_NULL_PRINTF(2, 3) +# define ATTRIBUTE_NULL_PRINTF_3 ATTRIBUTE_NULL_PRINTF(3, 4) +# define ATTRIBUTE_NULL_PRINTF_4 ATTRIBUTE_NULL_PRINTF(4, 5) +# define ATTRIBUTE_NULL_PRINTF_5 ATTRIBUTE_NULL_PRINTF(5, 6) +#endif /* ATTRIBUTE_NULL_PRINTF */ + +/* Attribute `sentinel' was valid as of gcc 3.5. */ +#ifndef ATTRIBUTE_SENTINEL +# if (GCC_VERSION >= 3005) +# define ATTRIBUTE_SENTINEL __attribute__ ((__sentinel__)) +# else +# define ATTRIBUTE_SENTINEL +# endif /* GNUC >= 3.5 */ +#endif /* ATTRIBUTE_SENTINEL */ + + +#ifndef ATTRIBUTE_ALIGNED_ALIGNOF +# if (GCC_VERSION >= 3000) +# define ATTRIBUTE_ALIGNED_ALIGNOF(m) __attribute__ ((__aligned__ (__alignof__ (m)))) +# else +# define ATTRIBUTE_ALIGNED_ALIGNOF(m) +# endif /* GNUC >= 3.0 */ +#endif /* ATTRIBUTE_ALIGNED_ALIGNOF */ + +/* Useful for structures whose layout must much some binary specification + regardless of the alignment and padding qualities of the compiler. */ +#ifndef ATTRIBUTE_PACKED +# define ATTRIBUTE_PACKED __attribute__ ((packed)) +#endif + +/* Attribute `hot' and `cold' was valid as of gcc 4.3. */ +#ifndef ATTRIBUTE_COLD +# if (GCC_VERSION >= 4003) +# define ATTRIBUTE_COLD __attribute__ ((__cold__)) +# else +# define ATTRIBUTE_COLD +# endif /* GNUC >= 4.3 */ +#endif /* ATTRIBUTE_COLD */ +#ifndef ATTRIBUTE_HOT +# if (GCC_VERSION >= 4003) +# define ATTRIBUTE_HOT __attribute__ ((__hot__)) +# else +# define ATTRIBUTE_HOT +# endif /* GNUC >= 4.3 */ +#endif /* ATTRIBUTE_HOT */ + +/* We use __extension__ in some places to suppress -pedantic warnings + about GCC extensions. This feature didn't work properly before + gcc 2.8. */ +#if GCC_VERSION < 2008 +#define __extension__ +#endif + +#endif /* ansidecl.h */ diff --git a/kernel/fiasco/src/lib/disasm/include/bfdlink.h b/kernel/fiasco/src/lib/disasm/include/bfdlink.h new file mode 100644 index 00000000..66cec018 --- /dev/null +++ b/kernel/fiasco/src/lib/disasm/include/bfdlink.h @@ -0,0 +1,775 @@ +/* bfdlink.h -- header file for BFD link routines + Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, + 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. + Written by Steve Chamberlain and Ian Lance Taylor, Cygnus Support. + + This file is part of BFD, the Binary File Descriptor library. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + MA 02110-1301, USA. */ + +#ifndef BFDLINK_H +#define BFDLINK_H + +/* Which symbols to strip during a link. */ +enum bfd_link_strip +{ + strip_none, /* Don't strip any symbols. */ + strip_debugger, /* Strip debugging symbols. */ + strip_some, /* keep_hash is the list of symbols to keep. */ + strip_all /* Strip all symbols. */ +}; + +/* Which local symbols to discard during a link. This is irrelevant + if strip_all is used. */ +enum bfd_link_discard +{ + discard_sec_merge, /* Discard local temporary symbols in SEC_MERGE + sections. */ + discard_none, /* Don't discard any locals. */ + discard_l, /* Discard local temporary symbols. */ + discard_all /* Discard all locals. */ +}; + +/* Describes the type of hash table entry structure being used. + Different hash table structure have different fields and so + support different linking features. */ +enum bfd_link_hash_table_type + { + bfd_link_generic_hash_table, + bfd_link_elf_hash_table + }; + +/* These are the possible types of an entry in the BFD link hash + table. */ + +enum bfd_link_hash_type +{ + bfd_link_hash_new, /* Symbol is new. */ + bfd_link_hash_undefined, /* Symbol seen before, but undefined. */ + bfd_link_hash_undefweak, /* Symbol is weak and undefined. */ + bfd_link_hash_defined, /* Symbol is defined. */ + bfd_link_hash_defweak, /* Symbol is weak and defined. */ + bfd_link_hash_common, /* Symbol is common. */ + bfd_link_hash_indirect, /* Symbol is an indirect link. */ + bfd_link_hash_warning /* Like indirect, but warn if referenced. */ +}; + +enum bfd_link_common_skip_ar_aymbols +{ + bfd_link_common_skip_none, + bfd_link_common_skip_text, + bfd_link_common_skip_data, + bfd_link_common_skip_all +}; + +/* The linking routines use a hash table which uses this structure for + its elements. */ + +struct bfd_link_hash_entry +{ + /* Base hash table entry structure. */ + struct bfd_hash_entry root; + + /* Type of this entry. */ + enum bfd_link_hash_type type; + + /* A union of information depending upon the type. */ + union + { + /* Nothing is kept for bfd_hash_new. */ + /* bfd_link_hash_undefined, bfd_link_hash_undefweak. */ + struct + { + /* Undefined and common symbols are kept in a linked list through + this field. This field is present in all of the union element + so that we don't need to remove entries from the list when we + change their type. Removing entries would either require the + list to be doubly linked, which would waste more memory, or + require a traversal. When an undefined or common symbol is + created, it should be added to this list, the head of which is in + the link hash table itself. As symbols are defined, they need + not be removed from the list; anything which reads the list must + doublecheck the symbol type. + + Weak symbols are not kept on this list. + + Defined and defweak symbols use this field as a reference marker. + If the field is not NULL, or this structure is the tail of the + undefined symbol list, the symbol has been referenced. If the + symbol is undefined and becomes defined, this field will + automatically be non-NULL since the symbol will have been on the + undefined symbol list. */ + struct bfd_link_hash_entry *next; + bfd *abfd; /* BFD symbol was found in. */ + bfd *weak; /* BFD weak symbol was found in. */ + } undef; + /* bfd_link_hash_defined, bfd_link_hash_defweak. */ + struct + { + struct bfd_link_hash_entry *next; + asection *section; /* Symbol section. */ + bfd_vma value; /* Symbol value. */ + } def; + /* bfd_link_hash_indirect, bfd_link_hash_warning. */ + struct + { + struct bfd_link_hash_entry *next; + struct bfd_link_hash_entry *link; /* Real symbol. */ + const char *warning; /* Warning (bfd_link_hash_warning only). */ + } i; + /* bfd_link_hash_common. */ + struct + { + struct bfd_link_hash_entry *next; + /* The linker needs to know three things about common + symbols: the size, the alignment, and the section in + which the symbol should be placed. We store the size + here, and we allocate a small structure to hold the + section and the alignment. The alignment is stored as a + power of two. We don't store all the information + directly because we don't want to increase the size of + the union; this structure is a major space user in the + linker. */ + struct bfd_link_hash_common_entry + { + unsigned int alignment_power; /* Alignment. */ + asection *section; /* Symbol section. */ + } *p; + bfd_size_type size; /* Common symbol size. */ + } c; + } u; +}; + +/* This is the link hash table. It is a derived class of + bfd_hash_table. */ + +struct bfd_link_hash_table +{ + /* The hash table itself. */ + struct bfd_hash_table table; + /* The back end which created this hash table. This indicates the + type of the entries in the hash table, which is sometimes + important information when linking object files of different + types together. */ + const bfd_target *creator; + /* A linked list of undefined and common symbols, linked through the + next field in the bfd_link_hash_entry structure. */ + struct bfd_link_hash_entry *undefs; + /* Entries are added to the tail of the undefs list. */ + struct bfd_link_hash_entry *undefs_tail; + /* The type of the link hash table. */ + enum bfd_link_hash_table_type type; +}; + +/* Look up an entry in a link hash table. If FOLLOW is TRUE, this + follows bfd_link_hash_indirect and bfd_link_hash_warning links to + the real symbol. */ +extern struct bfd_link_hash_entry *bfd_link_hash_lookup + (struct bfd_link_hash_table *, const char *, bfd_boolean create, + bfd_boolean copy, bfd_boolean follow); + +/* Look up an entry in the main linker hash table if the symbol might + be wrapped. This should only be used for references to an + undefined symbol, not for definitions of a symbol. */ + +extern struct bfd_link_hash_entry *bfd_wrapped_link_hash_lookup + (bfd *, struct bfd_link_info *, const char *, bfd_boolean, + bfd_boolean, bfd_boolean); + +/* Traverse a link hash table. */ +extern void bfd_link_hash_traverse + (struct bfd_link_hash_table *, + bfd_boolean (*) (struct bfd_link_hash_entry *, void *), + void *); + +/* Add an entry to the undefs list. */ +extern void bfd_link_add_undef + (struct bfd_link_hash_table *, struct bfd_link_hash_entry *); + +/* Remove symbols from the undefs list that don't belong there. */ +extern void bfd_link_repair_undef_list + (struct bfd_link_hash_table *table); + +struct bfd_sym_chain +{ + struct bfd_sym_chain *next; + const char *name; +}; + +/* How to handle unresolved symbols. + There are four possibilities which are enumerated below: */ +enum report_method +{ + /* This is the initial value when then link_info structure is created. + It allows the various stages of the linker to determine whether they + allowed to set the value. */ + RM_NOT_YET_SET = 0, + RM_IGNORE, + RM_GENERATE_WARNING, + RM_GENERATE_ERROR +}; + +struct bfd_elf_dynamic_list; + +/* This structure holds all the information needed to communicate + between BFD and the linker when doing a link. */ + +struct bfd_link_info +{ + /* TRUE if BFD should generate a relocatable object file. */ + unsigned int relocatable: 1; + + /* TRUE if BFD should generate relocation information in the final + executable. */ + unsigned int emitrelocations: 1; + + /* TRUE if BFD should generate a "task linked" object file, + similar to relocatable but also with globals converted to + statics. */ + unsigned int task_link: 1; + + /* TRUE if BFD should generate a shared object. */ + unsigned int shared: 1; + + /* TRUE if BFD should pre-bind symbols in a shared object. */ + unsigned int symbolic: 1; + + /* TRUE if BFD should export all symbols in the dynamic symbol table + of an executable, rather than only those used. */ + unsigned int export_dynamic: 1; + + /* TRUE if shared objects should be linked directly, not shared. */ + unsigned int static_link: 1; + + /* TRUE if the output file should be in a traditional format. This + is equivalent to the setting of the BFD_TRADITIONAL_FORMAT flag + on the output file, but may be checked when reading the input + files. */ + unsigned int traditional_format: 1; + + /* TRUE if we want to produced optimized output files. This might + need much more time and therefore must be explicitly selected. */ + unsigned int optimize: 1; + + /* TRUE if ok to have multiple definition. */ + unsigned int allow_multiple_definition: 1; + + /* TRUE if ok to have version with no definition. */ + unsigned int allow_undefined_version: 1; + + /* TRUE if a default symbol version should be created and used for + exported symbols. */ + unsigned int create_default_symver: 1; + + /* TRUE if a default symbol version should be created and used for + imported symbols. */ + unsigned int default_imported_symver: 1; + + /* TRUE if symbols should be retained in memory, FALSE if they + should be freed and reread. */ + unsigned int keep_memory: 1; + + /* TRUE if every symbol should be reported back via the notice + callback. */ + unsigned int notice_all: 1; + + /* TRUE if executable should not contain copy relocs. + Setting this true may result in a non-sharable text segment. */ + unsigned int nocopyreloc: 1; + + /* TRUE if the new ELF dynamic tags are enabled. */ + unsigned int new_dtags: 1; + + /* TRUE if non-PLT relocs should be merged into one reloc section + and sorted so that relocs against the same symbol come together. */ + unsigned int combreloc: 1; + + /* TRUE if .eh_frame_hdr section and PT_GNU_EH_FRAME ELF segment + should be created. */ + unsigned int eh_frame_hdr: 1; + + /* TRUE if global symbols in discarded sections should be stripped. */ + unsigned int strip_discarded: 1; + + /* TRUE if generating a position independent executable. */ + unsigned int pie: 1; + + /* TRUE if generating an executable, position independent or not. */ + unsigned int executable : 1; + + /* TRUE if PT_GNU_STACK segment should be created with PF_R|PF_W|PF_X + flags. */ + unsigned int execstack: 1; + + /* TRUE if PT_GNU_STACK segment should be created with PF_R|PF_W + flags. */ + unsigned int noexecstack: 1; + + /* TRUE if PT_GNU_RELRO segment should be created. */ + unsigned int relro: 1; + + /* TRUE if we should warn when adding a DT_TEXTREL to a shared object. */ + unsigned int warn_shared_textrel: 1; + + /* TRUE if unreferenced sections should be removed. */ + unsigned int gc_sections: 1; + + /* TRUE if user shoudl be informed of removed unreferenced sections. */ + unsigned int print_gc_sections: 1; + + /* TRUE if .hash section should be created. */ + unsigned int emit_hash: 1; + + /* TRUE if .gnu.hash section should be created. */ + unsigned int emit_gnu_hash: 1; + + /* If TRUE reduce memory overheads, at the expense of speed. This will + cause map file generation to use an O(N^2) algorithm and disable + caching ELF symbol buffer. */ + unsigned int reduce_memory_overheads: 1; + + /* TRUE if all data symbols should be dynamic. */ + unsigned int dynamic_data: 1; + + /* TRUE if some symbols have to be dynamic, controlled by + --dynamic-list command line options. */ + unsigned int dynamic: 1; + + /* Non-NULL if .note.gnu.build-id section should be created. */ + char *emit_note_gnu_build_id; + + /* What to do with unresolved symbols in an object file. + When producing executables the default is GENERATE_ERROR. + When producing shared libraries the default is IGNORE. The + assumption with shared libraries is that the reference will be + resolved at load/execution time. */ + enum report_method unresolved_syms_in_objects; + + /* What to do with unresolved symbols in a shared library. + The same defaults apply. */ + enum report_method unresolved_syms_in_shared_libs; + + /* Which symbols to strip. */ + enum bfd_link_strip strip; + + /* Which local symbols to discard. */ + enum bfd_link_discard discard; + + /* Criteria for skipping symbols when detemining + whether to include an object from an archive. */ + enum bfd_link_common_skip_ar_aymbols common_skip_ar_aymbols; + + /* Char that may appear as the first char of a symbol, but should be + skipped (like symbol_leading_char) when looking up symbols in + wrap_hash. Used by PowerPC Linux for 'dot' symbols. */ + char wrap_char; + + /* Function callbacks. */ + const struct bfd_link_callbacks *callbacks; + + /* Hash table handled by BFD. */ + struct bfd_link_hash_table *hash; + + /* Hash table of symbols to keep. This is NULL unless strip is + strip_some. */ + struct bfd_hash_table *keep_hash; + + /* Hash table of symbols to report back via the notice callback. If + this is NULL, and notice_all is FALSE, then no symbols are + reported back. */ + struct bfd_hash_table *notice_hash; + + /* Hash table of symbols which are being wrapped (the --wrap linker + option). If this is NULL, no symbols are being wrapped. */ + struct bfd_hash_table *wrap_hash; + + /* The list of input BFD's involved in the link. These are chained + together via the link_next field. */ + bfd *input_bfds; + bfd **input_bfds_tail; + + /* If a symbol should be created for each input BFD, this is section + where those symbols should be placed. It must be a section in + the output BFD. It may be NULL, in which case no such symbols + will be created. This is to support CREATE_OBJECT_SYMBOLS in the + linker command language. */ + asection *create_object_symbols_section; + + /* List of global symbol names that are starting points for marking + sections against garbage collection. */ + struct bfd_sym_chain *gc_sym_list; + + /* If a base output file is wanted, then this points to it */ + void *base_file; + + /* The function to call when the executable or shared object is + loaded. */ + const char *init_function; + + /* The function to call when the executable or shared object is + unloaded. */ + const char *fini_function; + + /* Number of relaxation passes. Usually only one relaxation pass + is needed. But a backend can have as many relaxation passes as + necessary. During bfd_relax_section call, it is set to the + current pass, starting from 0. */ + int relax_pass; + + /* Number of relaxation trips. This number is incremented every + time the relaxation pass is restarted due to a previous + relaxation returning true in *AGAIN. */ + int relax_trip; + + /* Non-zero if auto-import thunks for DATA items in pei386 DLLs + should be generated/linked against. Set to 1 if this feature + is explicitly requested by the user, -1 if enabled by default. */ + int pei386_auto_import; + + /* Non-zero if runtime relocs for DATA items with non-zero addends + in pei386 DLLs should be generated. Set to 1 if this feature + is explicitly requested by the user, -1 if enabled by default. */ + int pei386_runtime_pseudo_reloc; + + /* How many spare .dynamic DT_NULL entries should be added? */ + unsigned int spare_dynamic_tags; + + /* May be used to set DT_FLAGS for ELF. */ + bfd_vma flags; + + /* May be used to set DT_FLAGS_1 for ELF. */ + bfd_vma flags_1; + + /* Start and end of RELRO region. */ + bfd_vma relro_start, relro_end; + + /* List of symbols should be dynamic. */ + struct bfd_elf_dynamic_list *dynamic_list; +}; + +/* This structures holds a set of callback functions. These are called + by the BFD linker routines. Except for the info functions, the first + argument to each callback function is the bfd_link_info structure + being used and each function returns a boolean value. If the + function returns FALSE, then the BFD function which called it should + return with a failure indication. */ + +struct bfd_link_callbacks +{ + /* A function which is called when an object is added from an + archive. ABFD is the archive element being added. NAME is the + name of the symbol which caused the archive element to be pulled + in. */ + bfd_boolean (*add_archive_element) + (struct bfd_link_info *, bfd *abfd, const char *name); + /* A function which is called when a symbol is found with multiple + definitions. NAME is the symbol which is defined multiple times. + OBFD is the old BFD, OSEC is the old section, OVAL is the old + value, NBFD is the new BFD, NSEC is the new section, and NVAL is + the new value. OBFD may be NULL. OSEC and NSEC may be + bfd_com_section or bfd_ind_section. */ + bfd_boolean (*multiple_definition) + (struct bfd_link_info *, const char *name, + bfd *obfd, asection *osec, bfd_vma oval, + bfd *nbfd, asection *nsec, bfd_vma nval); + /* A function which is called when a common symbol is defined + multiple times. NAME is the symbol appearing multiple times. + OBFD is the BFD of the existing symbol; it may be NULL if this is + not known. OTYPE is the type of the existing symbol, which may + be bfd_link_hash_defined, bfd_link_hash_defweak, + bfd_link_hash_common, or bfd_link_hash_indirect. If OTYPE is + bfd_link_hash_common, OSIZE is the size of the existing symbol. + NBFD is the BFD of the new symbol. NTYPE is the type of the new + symbol, one of bfd_link_hash_defined, bfd_link_hash_common, or + bfd_link_hash_indirect. If NTYPE is bfd_link_hash_common, NSIZE + is the size of the new symbol. */ + bfd_boolean (*multiple_common) + (struct bfd_link_info *, const char *name, + bfd *obfd, enum bfd_link_hash_type otype, bfd_vma osize, + bfd *nbfd, enum bfd_link_hash_type ntype, bfd_vma nsize); + /* A function which is called to add a symbol to a set. ENTRY is + the link hash table entry for the set itself (e.g., + __CTOR_LIST__). RELOC is the relocation to use for an entry in + the set when generating a relocatable file, and is also used to + get the size of the entry when generating an executable file. + ABFD, SEC and VALUE identify the value to add to the set. */ + bfd_boolean (*add_to_set) + (struct bfd_link_info *, struct bfd_link_hash_entry *entry, + bfd_reloc_code_real_type reloc, bfd *abfd, asection *sec, bfd_vma value); + /* A function which is called when the name of a g++ constructor or + destructor is found. This is only called by some object file + formats. CONSTRUCTOR is TRUE for a constructor, FALSE for a + destructor. This will use BFD_RELOC_CTOR when generating a + relocatable file. NAME is the name of the symbol found. ABFD, + SECTION and VALUE are the value of the symbol. */ + bfd_boolean (*constructor) + (struct bfd_link_info *, bfd_boolean constructor, const char *name, + bfd *abfd, asection *sec, bfd_vma value); + /* A function which is called to issue a linker warning. For + example, this is called when there is a reference to a warning + symbol. WARNING is the warning to be issued. SYMBOL is the name + of the symbol which triggered the warning; it may be NULL if + there is none. ABFD, SECTION and ADDRESS identify the location + which trigerred the warning; either ABFD or SECTION or both may + be NULL if the location is not known. */ + bfd_boolean (*warning) + (struct bfd_link_info *, const char *warning, const char *symbol, + bfd *abfd, asection *section, bfd_vma address); + /* A function which is called when a relocation is attempted against + an undefined symbol. NAME is the symbol which is undefined. + ABFD, SECTION and ADDRESS identify the location from which the + reference is made. FATAL indicates whether an undefined symbol is + a fatal error or not. In some cases SECTION may be NULL. */ + bfd_boolean (*undefined_symbol) + (struct bfd_link_info *, const char *name, bfd *abfd, + asection *section, bfd_vma address, bfd_boolean fatal); + /* A function which is called when a reloc overflow occurs. ENTRY is + the link hash table entry for the symbol the reloc is against. + NAME is the name of the local symbol or section the reloc is + against, RELOC_NAME is the name of the relocation, and ADDEND is + any addend that is used. ABFD, SECTION and ADDRESS identify the + location at which the overflow occurs; if this is the result of a + bfd_section_reloc_link_order or bfd_symbol_reloc_link_order, then + ABFD will be NULL. */ + bfd_boolean (*reloc_overflow) + (struct bfd_link_info *, struct bfd_link_hash_entry *entry, + const char *name, const char *reloc_name, bfd_vma addend, + bfd *abfd, asection *section, bfd_vma address); + /* A function which is called when a dangerous reloc is performed. + MESSAGE is an appropriate message. + ABFD, SECTION and ADDRESS identify the location at which the + problem occurred; if this is the result of a + bfd_section_reloc_link_order or bfd_symbol_reloc_link_order, then + ABFD will be NULL. */ + bfd_boolean (*reloc_dangerous) + (struct bfd_link_info *, const char *message, + bfd *abfd, asection *section, bfd_vma address); + /* A function which is called when a reloc is found to be attached + to a symbol which is not being written out. NAME is the name of + the symbol. ABFD, SECTION and ADDRESS identify the location of + the reloc; if this is the result of a + bfd_section_reloc_link_order or bfd_symbol_reloc_link_order, then + ABFD will be NULL. */ + bfd_boolean (*unattached_reloc) + (struct bfd_link_info *, const char *name, + bfd *abfd, asection *section, bfd_vma address); + /* A function which is called when a symbol in notice_hash is + defined or referenced. NAME is the symbol. ABFD, SECTION and + ADDRESS are the value of the symbol. If SECTION is + bfd_und_section, this is a reference. */ + bfd_boolean (*notice) + (struct bfd_link_info *, const char *name, + bfd *abfd, asection *section, bfd_vma address); + /* Error or warning link info message. */ + void (*einfo) + (const char *fmt, ...); + /* General link info message. */ + void (*info) + (const char *fmt, ...); + /* Message to be printed in linker map file. */ + void (*minfo) + (const char *fmt, ...); + /* This callback provides a chance for users of the BFD library to + override its decision about whether to place two adjacent sections + into the same segment. */ + bfd_boolean (*override_segment_assignment) + (struct bfd_link_info *, bfd * abfd, + asection * current_section, asection * previous_section, + bfd_boolean new_segment); +}; + +/* The linker builds link_order structures which tell the code how to + include input data in the output file. */ + +/* These are the types of link_order structures. */ + +enum bfd_link_order_type +{ + bfd_undefined_link_order, /* Undefined. */ + bfd_indirect_link_order, /* Built from a section. */ + bfd_data_link_order, /* Set to explicit data. */ + bfd_section_reloc_link_order, /* Relocate against a section. */ + bfd_symbol_reloc_link_order /* Relocate against a symbol. */ +}; + +/* This is the link_order structure itself. These form a chain + attached to the output section whose contents they are describing. */ + +struct bfd_link_order +{ + /* Next link_order in chain. */ + struct bfd_link_order *next; + /* Type of link_order. */ + enum bfd_link_order_type type; + /* Offset within output section. */ + bfd_vma offset; + /* Size within output section. */ + bfd_size_type size; + /* Type specific information. */ + union + { + struct + { + /* Section to include. If this is used, then + section->output_section must be the section the + link_order is attached to, section->output_offset must + equal the link_order offset field, and section->size + must equal the link_order size field. Maybe these + restrictions should be relaxed someday. */ + asection *section; + } indirect; + struct + { + /* Size of contents, or zero when contents size == size + within output section. + A non-zero value allows filling of the output section + with an arbitrary repeated pattern. */ + unsigned int size; + /* Data to put into file. */ + bfd_byte *contents; + } data; + struct + { + /* Description of reloc to generate. Used for + bfd_section_reloc_link_order and + bfd_symbol_reloc_link_order. */ + struct bfd_link_order_reloc *p; + } reloc; + } u; +}; + +/* A linker order of type bfd_section_reloc_link_order or + bfd_symbol_reloc_link_order means to create a reloc against a + section or symbol, respectively. This is used to implement -Ur to + generate relocs for the constructor tables. The + bfd_link_order_reloc structure describes the reloc that BFD should + create. It is similar to a arelent, but I didn't use arelent + because the linker does not know anything about most symbols, and + any asymbol structure it creates will be partially meaningless. + This information could logically be in the bfd_link_order struct, + but I didn't want to waste the space since these types of relocs + are relatively rare. */ + +struct bfd_link_order_reloc +{ + /* Reloc type. */ + bfd_reloc_code_real_type reloc; + + union + { + /* For type bfd_section_reloc_link_order, this is the section + the reloc should be against. This must be a section in the + output BFD, not any of the input BFDs. */ + asection *section; + /* For type bfd_symbol_reloc_link_order, this is the name of the + symbol the reloc should be against. */ + const char *name; + } u; + + /* Addend to use. The object file should contain zero. The BFD + backend is responsible for filling in the contents of the object + file correctly. For some object file formats (e.g., COFF) the + addend must be stored into in the object file, and for some + (e.g., SPARC a.out) it is kept in the reloc. */ + bfd_vma addend; +}; + +/* Allocate a new link_order for a section. */ +extern struct bfd_link_order *bfd_new_link_order (bfd *, asection *); + +/* These structures are used to describe version information for the + ELF linker. These structures could be manipulated entirely inside + BFD, but it would be a pain. Instead, the regular linker sets up + these structures, and then passes them into BFD. */ + +/* Glob pattern for a version. */ + +struct bfd_elf_version_expr +{ + /* Next glob pattern for this version. */ + struct bfd_elf_version_expr *next; + /* Glob pattern. */ + const char *pattern; + /* NULL for a glob pattern, otherwise a straight symbol. */ + const char *symbol; + /* Defined by ".symver". */ + unsigned int symver : 1; + /* Defined by version script. */ + unsigned int script : 1; + /* Pattern type. */ +#define BFD_ELF_VERSION_C_TYPE 1 +#define BFD_ELF_VERSION_CXX_TYPE 2 +#define BFD_ELF_VERSION_JAVA_TYPE 4 + unsigned int mask : 3; +}; + +struct bfd_elf_version_expr_head +{ + /* List of all patterns, both wildcards and non-wildcards. */ + struct bfd_elf_version_expr *list; + /* Hash table for non-wildcards. */ + void *htab; + /* Remaining patterns. */ + struct bfd_elf_version_expr *remaining; + /* What kind of pattern types are present in list (bitmask). */ + unsigned int mask; +}; + +/* Version dependencies. */ + +struct bfd_elf_version_deps +{ + /* Next dependency for this version. */ + struct bfd_elf_version_deps *next; + /* The version which this version depends upon. */ + struct bfd_elf_version_tree *version_needed; +}; + +/* A node in the version tree. */ + +struct bfd_elf_version_tree +{ + /* Next version. */ + struct bfd_elf_version_tree *next; + /* Name of this version. */ + const char *name; + /* Version number. */ + unsigned int vernum; + /* Regular expressions for global symbols in this version. */ + struct bfd_elf_version_expr_head globals; + /* Regular expressions for local symbols in this version. */ + struct bfd_elf_version_expr_head locals; + /* List of versions which this version depends upon. */ + struct bfd_elf_version_deps *deps; + /* Index of the version name. This is used within BFD. */ + unsigned int name_indx; + /* Whether this version tree was used. This is used within BFD. */ + int used; + /* Matching hook. */ + struct bfd_elf_version_expr *(*match) + (struct bfd_elf_version_expr_head *head, + struct bfd_elf_version_expr *prev, const char *sym); +}; + +struct bfd_elf_dynamic_list +{ + struct bfd_elf_version_expr_head head; + struct bfd_elf_version_expr *(*match) + (struct bfd_elf_version_expr_head *head, + struct bfd_elf_version_expr *prev, const char *sym); +}; + +#endif diff --git a/kernel/fiasco/src/lib/disasm/include/dis-asm.h b/kernel/fiasco/src/lib/disasm/include/dis-asm.h new file mode 100644 index 00000000..40afe17c --- /dev/null +++ b/kernel/fiasco/src/lib/disasm/include/dis-asm.h @@ -0,0 +1,353 @@ +/* Interface between the opcode library and its callers. + + Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 + Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, + Boston, MA 02110-1301, USA. + + Written by Cygnus Support, 1993. + + The opcode library (libopcodes.a) provides instruction decoders for + a large variety of instruction sets, callable with an identical + interface, for making instruction-processing programs more independent + of the instruction set being processed. */ + +#ifndef DIS_ASM_H +#define DIS_ASM_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include "bfd.h" + + typedef int (*fprintf_ftype) (void *, const char*, ...) /*ATTRIBUTE_FPTR_PRINTF_2*/; + +enum dis_insn_type +{ + dis_noninsn, /* Not a valid instruction */ + dis_nonbranch, /* Not a branch instruction */ + dis_branch, /* Unconditional branch */ + dis_condbranch, /* Conditional branch */ + dis_jsr, /* Jump to subroutine */ + dis_condjsr, /* Conditional jump to subroutine */ + dis_dref, /* Data reference instruction */ + dis_dref2 /* Two data references in instruction */ +}; + +/* This struct is passed into the instruction decoding routine, + and is passed back out into each callback. The various fields are used + for conveying information from your main routine into your callbacks, + for passing information into the instruction decoders (such as the + addresses of the callback functions), or for passing information + back from the instruction decoders to their callers. + + It must be initialized before it is first passed; this can be done + by hand, or using one of the initialization macros below. */ + +typedef struct disassemble_info +{ + fprintf_ftype fprintf_func; + void *stream; + void *application_data; + + /* Target description. We could replace this with a pointer to the bfd, + but that would require one. There currently isn't any such requirement + so to avoid introducing one we record these explicitly. */ + /* The bfd_flavour. This can be bfd_target_unknown_flavour. */ + enum bfd_flavour flavour; + /* The bfd_arch value. */ + enum bfd_architecture arch; + /* The bfd_mach value. */ + unsigned long mach; + /* Endianness (for bi-endian cpus). Mono-endian cpus can ignore this. */ + enum bfd_endian endian; + /* An arch/mach-specific bitmask of selected instruction subsets, mainly + for processors with run-time-switchable instruction sets. The default, + zero, means that there is no constraint. CGEN-based opcodes ports + may use ISA_foo masks. */ + void *insn_sets; + + /* Some targets need information about the current section to accurately + display insns. If this is NULL, the target disassembler function + will have to make its best guess. */ + asection *section; + + /* An array of pointers to symbols either at the location being disassembled + or at the start of the function being disassembled. The array is sorted + so that the first symbol is intended to be the one used. The others are + present for any misc. purposes. This is not set reliably, but if it is + not NULL, it is correct. */ + asymbol **symbols; + /* Number of symbols in array. */ + int num_symbols; + + /* Symbol table provided for targets that want to look at it. This is + used on Arm to find mapping symbols and determine Arm/Thumb code. */ + asymbol **symtab; + int symtab_pos; + int symtab_size; + + /* For use by the disassembler. + The top 16 bits are reserved for public use (and are documented here). + The bottom 16 bits are for the internal use of the disassembler. */ + unsigned long flags; +#define INSN_HAS_RELOC 0x80000000 + void *private_data; + + /* Function used to get bytes to disassemble. MEMADDR is the + address of the stuff to be disassembled, MYADDR is the address to + put the bytes in, and LENGTH is the number of bytes to read. + INFO is a pointer to this struct. + Returns an errno value or 0 for success. */ + int (*read_memory_func) + (bfd_vma memaddr, bfd_byte *myaddr, unsigned int length, + struct disassemble_info *info); + + /* Function which should be called if we get an error that we can't + recover from. STATUS is the errno value from read_memory_func and + MEMADDR is the address that we were trying to read. INFO is a + pointer to this struct. */ + void (*memory_error_func) + (int status, bfd_vma memaddr, struct disassemble_info *info); + + /* Function called to print ADDR. */ + void (*print_address_func) + (bfd_vma addr, struct disassemble_info *info); + + /* Function called to determine if there is a symbol at the given ADDR. + If there is, the function returns 1, otherwise it returns 0. + This is used by ports which support an overlay manager where + the overlay number is held in the top part of an address. In + some circumstances we want to include the overlay number in the + address, (normally because there is a symbol associated with + that address), but sometimes we want to mask out the overlay bits. */ + int (* symbol_at_address_func) + (bfd_vma addr, struct disassemble_info * info); + + /* Function called to check if a SYMBOL is can be displayed to the user. + This is used by some ports that want to hide special symbols when + displaying debugging outout. */ + bfd_boolean (* symbol_is_valid) + (asymbol *, struct disassemble_info * info); + + /* These are for buffer_read_memory. */ + bfd_byte *buffer; + bfd_vma buffer_vma; + unsigned int buffer_length; + + /* This variable may be set by the instruction decoder. It suggests + the number of bytes objdump should display on a single line. If + the instruction decoder sets this, it should always set it to + the same value in order to get reasonable looking output. */ + int bytes_per_line; + + /* The next two variables control the way objdump displays the raw data. */ + /* For example, if bytes_per_line is 8 and bytes_per_chunk is 4, the */ + /* output will look like this: + 00: 00000000 00000000 + with the chunks displayed according to "display_endian". */ + int bytes_per_chunk; + enum bfd_endian display_endian; + + /* Number of octets per incremented target address + Normally one, but some DSPs have byte sizes of 16 or 32 bits. */ + unsigned int octets_per_byte; + + /* The number of zeroes we want to see at the end of a section before we + start skipping them. */ + unsigned int skip_zeroes; + + /* The number of zeroes to skip at the end of a section. If the number + of zeroes at the end is between SKIP_ZEROES_AT_END and SKIP_ZEROES, + they will be disassembled. If there are fewer than + SKIP_ZEROES_AT_END, they will be skipped. This is a heuristic + attempt to avoid disassembling zeroes inserted by section + alignment. */ + unsigned int skip_zeroes_at_end; + + /* Whether the disassembler always needs the relocations. */ + bfd_boolean disassembler_needs_relocs; + + /* Results from instruction decoders. Not all decoders yet support + this information. This info is set each time an instruction is + decoded, and is only valid for the last such instruction. + + To determine whether this decoder supports this information, set + insn_info_valid to 0, decode an instruction, then check it. */ + + char insn_info_valid; /* Branch info has been set. */ + char branch_delay_insns; /* How many sequential insn's will run before + a branch takes effect. (0 = normal) */ + char data_size; /* Size of data reference in insn, in bytes */ + enum dis_insn_type insn_type; /* Type of instruction */ + bfd_vma target; /* Target address of branch or dref, if known; + zero if unknown. */ + bfd_vma target2; /* Second target address for dref2 */ + + /* Command line options specific to the target disassembler. */ + char * disassembler_options; + +} disassemble_info; + + +/* Standard disassemblers. Disassemble one instruction at the given + target address. Return number of octets processed. */ +typedef int (*disassembler_ftype) (bfd_vma, disassemble_info *); + +extern int print_insn_alpha (bfd_vma, disassemble_info *); +extern int print_insn_avr (bfd_vma, disassemble_info *); +extern int print_insn_bfin (bfd_vma, disassemble_info *); +extern int print_insn_big_arm (bfd_vma, disassemble_info *); +extern int print_insn_big_mips (bfd_vma, disassemble_info *); +extern int print_insn_big_or32 (bfd_vma, disassemble_info *); +extern int print_insn_big_powerpc (bfd_vma, disassemble_info *); +extern int print_insn_big_score (bfd_vma, disassemble_info *); +extern int print_insn_cr16 (bfd_vma, disassemble_info *); +extern int print_insn_crx (bfd_vma, disassemble_info *); +extern int print_insn_d10v (bfd_vma, disassemble_info *); +extern int print_insn_d30v (bfd_vma, disassemble_info *); +extern int print_insn_dlx (bfd_vma, disassemble_info *); +extern int print_insn_fr30 (bfd_vma, disassemble_info *); +extern int print_insn_frv (bfd_vma, disassemble_info *); +extern int print_insn_h8300 (bfd_vma, disassemble_info *); +extern int print_insn_h8300h (bfd_vma, disassemble_info *); +extern int print_insn_h8300s (bfd_vma, disassemble_info *); +extern int print_insn_h8500 (bfd_vma, disassemble_info *); +extern int print_insn_hppa (bfd_vma, disassemble_info *); +extern int print_insn_i370 (bfd_vma, disassemble_info *); +extern int print_insn_i386 (bfd_vma, disassemble_info *); +extern int print_insn_i386_att (bfd_vma, disassemble_info *); +extern int print_insn_i386_intel (bfd_vma, disassemble_info *); +extern int print_insn_i860 (bfd_vma, disassemble_info *); +extern int print_insn_i960 (bfd_vma, disassemble_info *); +extern int print_insn_ia64 (bfd_vma, disassemble_info *); +extern int print_insn_ip2k (bfd_vma, disassemble_info *); +extern int print_insn_iq2000 (bfd_vma, disassemble_info *); +extern int print_insn_little_arm (bfd_vma, disassemble_info *); +extern int print_insn_little_mips (bfd_vma, disassemble_info *); +extern int print_insn_little_or32 (bfd_vma, disassemble_info *); +extern int print_insn_little_powerpc (bfd_vma, disassemble_info *); +extern int print_insn_little_score (bfd_vma, disassemble_info *); +extern int print_insn_m32c (bfd_vma, disassemble_info *); +extern int print_insn_m32r (bfd_vma, disassemble_info *); +extern int print_insn_m68hc11 (bfd_vma, disassemble_info *); +extern int print_insn_m68hc12 (bfd_vma, disassemble_info *); +extern int print_insn_m68k (bfd_vma, disassemble_info *); +extern int print_insn_m88k (bfd_vma, disassemble_info *); +extern int print_insn_maxq_big (bfd_vma, disassemble_info *); +extern int print_insn_maxq_little (bfd_vma, disassemble_info *); +extern int print_insn_mcore (bfd_vma, disassemble_info *); +extern int print_insn_mep (bfd_vma, disassemble_info *); +extern int print_insn_mmix (bfd_vma, disassemble_info *); +extern int print_insn_mn10200 (bfd_vma, disassemble_info *); +extern int print_insn_mn10300 (bfd_vma, disassemble_info *); +extern int print_insn_msp430 (bfd_vma, disassemble_info *); +extern int print_insn_mt (bfd_vma, disassemble_info *); +extern int print_insn_ns32k (bfd_vma, disassemble_info *); +extern int print_insn_openrisc (bfd_vma, disassemble_info *); +extern int print_insn_pdp11 (bfd_vma, disassemble_info *); +extern int print_insn_pj (bfd_vma, disassemble_info *); +extern int print_insn_rs6000 (bfd_vma, disassemble_info *); +extern int print_insn_s390 (bfd_vma, disassemble_info *); +extern int print_insn_sh (bfd_vma, disassemble_info *); +extern int print_insn_sh64 (bfd_vma, disassemble_info *); +extern int print_insn_sh64x_media (bfd_vma, disassemble_info *); +extern int print_insn_sparc (bfd_vma, disassemble_info *); +extern int print_insn_spu (bfd_vma, disassemble_info *); +extern int print_insn_tic30 (bfd_vma, disassemble_info *); +extern int print_insn_tic4x (bfd_vma, disassemble_info *); +extern int print_insn_tic54x (bfd_vma, disassemble_info *); +extern int print_insn_tic80 (bfd_vma, disassemble_info *); +extern int print_insn_v850 (bfd_vma, disassemble_info *); +extern int print_insn_vax (bfd_vma, disassemble_info *); +extern int print_insn_w65 (bfd_vma, disassemble_info *); +extern int print_insn_xc16x (bfd_vma, disassemble_info *); +extern int print_insn_xstormy16 (bfd_vma, disassemble_info *); +extern int print_insn_xtensa (bfd_vma, disassemble_info *); +extern int print_insn_z80 (bfd_vma, disassemble_info *); +extern int print_insn_z8001 (bfd_vma, disassemble_info *); +extern int print_insn_z8002 (bfd_vma, disassemble_info *); + +extern disassembler_ftype arc_get_disassembler (void *); +extern disassembler_ftype cris_get_disassembler (bfd *); + +extern void print_i386_disassembler_options (FILE *); +extern void print_mips_disassembler_options (FILE *); +extern void print_ppc_disassembler_options (FILE *); +extern void print_arm_disassembler_options (FILE *); +extern void parse_arm_disassembler_option (char *); +extern int get_arm_regname_num_options (void); +extern int set_arm_regname_option (int); +extern int get_arm_regnames (int, const char **, const char **, const char *const **); +extern bfd_boolean arm_symbol_is_valid (asymbol *, struct disassemble_info *); + +/* Fetch the disassembler for a given BFD, if that support is available. */ +extern disassembler_ftype disassembler (bfd *); + +/* Amend the disassemble_info structure as necessary for the target architecture. + Should only be called after initialising the info->arch field. */ +extern void disassemble_init_for_target (struct disassemble_info * info); + +/* Document any target specific options available from the disassembler. */ +extern void disassembler_usage (FILE *); + + +/* This block of definitions is for particular callers who read instructions + into a buffer before calling the instruction decoder. */ + +/* Here is a function which callers may wish to use for read_memory_func. + It gets bytes from a buffer. */ +extern int buffer_read_memory + (bfd_vma, bfd_byte *, unsigned int, struct disassemble_info *); + +/* This function goes with buffer_read_memory. + It prints a message using info->fprintf_func and info->stream. */ +extern void perror_memory (int, bfd_vma, struct disassemble_info *); + + +/* Just print the address in hex. This is included for completeness even + though both GDB and objdump provide their own (to print symbolic + addresses). */ +extern void generic_print_address + (bfd_vma, struct disassemble_info *); + +/* Always true. */ +extern int generic_symbol_at_address + (bfd_vma, struct disassemble_info *); + +/* Also always true. */ +extern bfd_boolean generic_symbol_is_valid + (asymbol *, struct disassemble_info *); + +/* Method to initialize a disassemble_info struct. This should be + called by all applications creating such a struct. */ +extern void init_disassemble_info (struct disassemble_info *info, void *stream, + fprintf_ftype fprintf_func); + +/* For compatibility with existing code. */ +#define INIT_DISASSEMBLE_INFO(INFO, STREAM, FPRINTF_FUNC) \ + init_disassemble_info (&(INFO), (STREAM), (fprintf_ftype) (FPRINTF_FUNC)) +#define INIT_DISASSEMBLE_INFO_NO_ARCH(INFO, STREAM, FPRINTF_FUNC) \ + init_disassemble_info (&(INFO), (STREAM), (fprintf_ftype) (FPRINTF_FUNC)) + + +#ifdef __cplusplus +} +#endif + +#endif /* ! defined (DIS_ASM_H) */ diff --git a/kernel/fiasco/src/lib/disasm/include/floatformat.h b/kernel/fiasco/src/lib/disasm/include/floatformat.h new file mode 100644 index 00000000..f1bd7f60 --- /dev/null +++ b/kernel/fiasco/src/lib/disasm/include/floatformat.h @@ -0,0 +1,140 @@ +/* IEEE floating point support declarations, for GDB, the GNU Debugger. + Copyright 1991, 1994, 1995, 1997, 2000, 2003, 2005 + Free Software Foundation, Inc. + +This file is part of GDB. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ + +#if !defined (FLOATFORMAT_H) +#define FLOATFORMAT_H 1 + +#include "ansidecl.h" + +/* A floatformat consists of a sign bit, an exponent and a mantissa. Once the + bytes are concatenated according to the byteorder flag, then each of those + fields is contiguous. We number the bits with 0 being the most significant + (i.e. BITS_BIG_ENDIAN type numbering), and specify which bits each field + contains with the *_start and *_len fields. */ + +/* What is the order of the bytes? */ + +enum floatformat_byteorders { + /* Standard little endian byte order. + EX: 1.2345678e10 => 00 00 80 c5 e0 fe 06 42 */ + floatformat_little, + + /* Standard big endian byte order. + EX: 1.2345678e10 => 42 06 fe e0 c5 80 00 00 */ + floatformat_big, + + /* Little endian byte order but big endian word order. + EX: 1.2345678e10 => e0 fe 06 42 00 00 80 c5 */ + floatformat_littlebyte_bigword, + + /* VAX byte order. Little endian byte order with 16-bit words. The + following example is an illustration of the byte order only; VAX + doesn't have a fully IEEE compliant floating-point format. + EX: 1.2345678e10 => 80 c5 00 00 06 42 e0 fe */ + floatformat_vax +}; + +enum floatformat_intbit { floatformat_intbit_yes, floatformat_intbit_no }; + +struct floatformat +{ + enum floatformat_byteorders byteorder; + unsigned int totalsize; /* Total size of number in bits */ + + /* Sign bit is always one bit long. 1 means negative, 0 means positive. */ + unsigned int sign_start; + + unsigned int exp_start; + unsigned int exp_len; + /* Bias added to a "true" exponent to form the biased exponent. It + is intentionally signed as, otherwize, -exp_bias can turn into a + very large number (e.g., given the exp_bias of 0x3fff and a 64 + bit long, the equation (long)(1 - exp_bias) evaluates to + 4294950914) instead of -16382). */ + int exp_bias; + /* Exponent value which indicates NaN. This is the actual value stored in + the float, not adjusted by the exp_bias. This usually consists of all + one bits. */ + unsigned int exp_nan; + + unsigned int man_start; + unsigned int man_len; + + /* Is the integer bit explicit or implicit? */ + enum floatformat_intbit intbit; + + /* Internal name for debugging. */ + const char *name; + + /* Validator method. */ + int (*is_valid) (const struct floatformat *fmt, const void *from); +}; + +/* floatformats for IEEE single and double, big and little endian. */ + +extern const struct floatformat floatformat_ieee_single_big; +extern const struct floatformat floatformat_ieee_single_little; +extern const struct floatformat floatformat_ieee_double_big; +extern const struct floatformat floatformat_ieee_double_little; + +/* floatformat for ARM IEEE double, little endian bytes and big endian words */ + +extern const struct floatformat floatformat_ieee_double_littlebyte_bigword; + +/* floatformats for VAX. */ + +extern const struct floatformat floatformat_vax_f; +extern const struct floatformat floatformat_vax_d; +extern const struct floatformat floatformat_vax_g; + +/* floatformats for various extendeds. */ + +extern const struct floatformat floatformat_i387_ext; +extern const struct floatformat floatformat_m68881_ext; +extern const struct floatformat floatformat_i960_ext; +extern const struct floatformat floatformat_m88110_ext; +extern const struct floatformat floatformat_m88110_harris_ext; +extern const struct floatformat floatformat_arm_ext_big; +extern const struct floatformat floatformat_arm_ext_littlebyte_bigword; +/* IA-64 Floating Point register spilt into memory. */ +extern const struct floatformat floatformat_ia64_spill_big; +extern const struct floatformat floatformat_ia64_spill_little; +extern const struct floatformat floatformat_ia64_quad_big; +extern const struct floatformat floatformat_ia64_quad_little; + +/* Convert from FMT to a double. + FROM is the address of the extended float. + Store the double in *TO. */ + +extern void +floatformat_to_double (const struct floatformat *, const void *, double *); + +/* The converse: convert the double *FROM to FMT + and store where TO points. */ + +extern void +floatformat_from_double (const struct floatformat *, const double *, void *); + +/* Return non-zero iff the data at FROM is a valid number in format FMT. */ + +extern int +floatformat_is_valid (const struct floatformat *fmt, const void *from); + +#endif /* defined (FLOATFORMAT_H) */ diff --git a/kernel/fiasco/src/lib/disasm/include/opcode/arm.h b/kernel/fiasco/src/lib/disasm/include/opcode/arm.h new file mode 100644 index 00000000..24a89cfc --- /dev/null +++ b/kernel/fiasco/src/lib/disasm/include/opcode/arm.h @@ -0,0 +1,197 @@ +/* ARM assembler/disassembler support. + Copyright 2004 Free Software Foundation, Inc. + + This file is part of GDB and GAS. + + GDB and GAS are free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 1, or (at + your option) any later version. + + GDB and GAS are distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GDB or GAS; see the file COPYING. If not, write to the + Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA + 02110-1301, USA. */ + +/* The following bitmasks control CPU extensions: */ +#define ARM_EXT_V1 0x00000001 /* All processors (core set). */ +#define ARM_EXT_V2 0x00000002 /* Multiply instructions. */ +#define ARM_EXT_V2S 0x00000004 /* SWP instructions. */ +#define ARM_EXT_V3 0x00000008 /* MSR MRS. */ +#define ARM_EXT_V3M 0x00000010 /* Allow long multiplies. */ +#define ARM_EXT_V4 0x00000020 /* Allow half word loads. */ +#define ARM_EXT_V4T 0x00000040 /* Thumb. */ +#define ARM_EXT_V5 0x00000080 /* Allow CLZ, etc. */ +#define ARM_EXT_V5T 0x00000100 /* Improved interworking. */ +#define ARM_EXT_V5ExP 0x00000200 /* DSP core set. */ +#define ARM_EXT_V5E 0x00000400 /* DSP Double transfers. */ +#define ARM_EXT_V5J 0x00000800 /* Jazelle extension. */ +#define ARM_EXT_V6 0x00001000 /* ARM V6. */ +#define ARM_EXT_V6K 0x00002000 /* ARM V6K. */ +#define ARM_EXT_V6Z 0x00004000 /* ARM V6Z. */ +#define ARM_EXT_V6T2 0x00008000 /* Thumb-2. */ +#define ARM_EXT_DIV 0x00010000 /* Integer division. */ +/* The 'M' in Arm V7M stands for Microcontroller. + On earlier architecture variants it stands for Multiply. */ +#define ARM_EXT_V5E_NOTM 0x00020000 /* Arm V5E but not Arm V7M. */ +#define ARM_EXT_V6_NOTM 0x00040000 /* Arm V6 but not Arm V7M. */ +#define ARM_EXT_V7 0x00080000 /* Arm V7. */ +#define ARM_EXT_V7A 0x00100000 /* Arm V7A. */ +#define ARM_EXT_V7R 0x00200000 /* Arm V7R. */ +#define ARM_EXT_V7M 0x00400000 /* Arm V7M. */ + +/* Co-processor space extensions. */ +#define ARM_CEXT_XSCALE 0x00000001 /* Allow MIA etc. */ +#define ARM_CEXT_MAVERICK 0x00000002 /* Use Cirrus/DSP coprocessor. */ +#define ARM_CEXT_IWMMXT 0x00000004 /* Intel Wireless MMX technology coprocessor. */ +#define ARM_CEXT_IWMMXT2 0x00000008 /* Intel Wireless MMX technology coprocessor version 2. */ + +#define FPU_ENDIAN_PURE 0x80000000 /* Pure-endian doubles. */ +#define FPU_ENDIAN_BIG 0 /* Double words-big-endian. */ +#define FPU_FPA_EXT_V1 0x40000000 /* Base FPA instruction set. */ +#define FPU_FPA_EXT_V2 0x20000000 /* LFM/SFM. */ +#define FPU_MAVERICK 0x10000000 /* Cirrus Maverick. */ +#define FPU_VFP_EXT_V1xD 0x08000000 /* Base VFP instruction set. */ +#define FPU_VFP_EXT_V1 0x04000000 /* Double-precision insns. */ +#define FPU_VFP_EXT_V2 0x02000000 /* ARM10E VFPr1. */ +#define FPU_VFP_EXT_V3 0x01000000 /* VFPv3 insns. */ +#define FPU_NEON_EXT_V1 0x00800000 /* Neon (SIMD) insns. */ + +/* Architectures are the sum of the base and extensions. The ARM ARM (rev E) + defines the following: ARMv3, ARMv3M, ARMv4xM, ARMv4, ARMv4TxM, ARMv4T, + ARMv5xM, ARMv5, ARMv5TxM, ARMv5T, ARMv5TExP, ARMv5TE. To these we add + three more to cover cores prior to ARM6. Finally, there are cores which + implement further extensions in the co-processor space. */ +#define ARM_AEXT_V1 ARM_EXT_V1 +#define ARM_AEXT_V2 (ARM_AEXT_V1 | ARM_EXT_V2) +#define ARM_AEXT_V2S (ARM_AEXT_V2 | ARM_EXT_V2S) +#define ARM_AEXT_V3 (ARM_AEXT_V2S | ARM_EXT_V3) +#define ARM_AEXT_V3M (ARM_AEXT_V3 | ARM_EXT_V3M) +#define ARM_AEXT_V4xM (ARM_AEXT_V3 | ARM_EXT_V4) +#define ARM_AEXT_V4 (ARM_AEXT_V3M | ARM_EXT_V4) +#define ARM_AEXT_V4TxM (ARM_AEXT_V4xM | ARM_EXT_V4T) +#define ARM_AEXT_V4T (ARM_AEXT_V4 | ARM_EXT_V4T) +#define ARM_AEXT_V5xM (ARM_AEXT_V4xM | ARM_EXT_V5) +#define ARM_AEXT_V5 (ARM_AEXT_V4 | ARM_EXT_V5) +#define ARM_AEXT_V5TxM (ARM_AEXT_V5xM | ARM_EXT_V4T | ARM_EXT_V5T) +#define ARM_AEXT_V5T (ARM_AEXT_V5 | ARM_EXT_V4T | ARM_EXT_V5T) +#define ARM_AEXT_V5TExP (ARM_AEXT_V5T | ARM_EXT_V5ExP) +#define ARM_AEXT_V5TE (ARM_AEXT_V5TExP | ARM_EXT_V5E) +#define ARM_AEXT_V5TEJ (ARM_AEXT_V5TE | ARM_EXT_V5J) +#define ARM_AEXT_V6 (ARM_AEXT_V5TEJ | ARM_EXT_V6) +#define ARM_AEXT_V6K (ARM_AEXT_V6 | ARM_EXT_V6K) +#define ARM_AEXT_V6Z (ARM_AEXT_V6 | ARM_EXT_V6Z) +#define ARM_AEXT_V6ZK (ARM_AEXT_V6 | ARM_EXT_V6K | ARM_EXT_V6Z) +#define ARM_AEXT_V6T2 (ARM_AEXT_V6 | ARM_EXT_V6T2 | ARM_EXT_V6_NOTM) +#define ARM_AEXT_V6KT2 (ARM_AEXT_V6T2 | ARM_EXT_V6K) +#define ARM_AEXT_V6ZT2 (ARM_AEXT_V6T2 | ARM_EXT_V6Z) +#define ARM_AEXT_V6ZKT2 (ARM_AEXT_V6T2 | ARM_EXT_V6K | ARM_EXT_V6Z) +#define ARM_AEXT_V7_ARM (ARM_AEXT_V6ZKT2 | ARM_EXT_V7) +#define ARM_AEXT_V7A (ARM_AEXT_V7_ARM | ARM_EXT_V7A) +#define ARM_AEXT_V7R (ARM_AEXT_V7_ARM | ARM_EXT_V7R | ARM_EXT_DIV) +#define ARM_AEXT_NOTM \ + (ARM_AEXT_V4 | ARM_EXT_V5ExP | ARM_EXT_V5J | ARM_EXT_V6_NOTM) +#define ARM_AEXT_V7M \ + ((ARM_AEXT_V7_ARM | ARM_EXT_V7M | ARM_EXT_DIV) & ~(ARM_AEXT_NOTM)) +#define ARM_AEXT_V7 (ARM_AEXT_V7A & ARM_AEXT_V7R & ARM_AEXT_V7M) + +/* Processors with specific extensions in the co-processor space. */ +#define ARM_ARCH_XSCALE ARM_FEATURE (ARM_AEXT_V5TE, ARM_CEXT_XSCALE) +#define ARM_ARCH_IWMMXT \ + ARM_FEATURE (ARM_AEXT_V5TE, ARM_CEXT_XSCALE | ARM_CEXT_IWMMXT) +#define ARM_ARCH_IWMMXT2 \ + ARM_FEATURE (ARM_AEXT_V5TE, ARM_CEXT_XSCALE | ARM_CEXT_IWMMXT | ARM_CEXT_IWMMXT2) + +#define FPU_VFP_V1xD (FPU_VFP_EXT_V1xD | FPU_ENDIAN_PURE) +#define FPU_VFP_V1 (FPU_VFP_V1xD | FPU_VFP_EXT_V1) +#define FPU_VFP_V2 (FPU_VFP_V1 | FPU_VFP_EXT_V2) +#define FPU_VFP_V3 (FPU_VFP_V2 | FPU_VFP_EXT_V3) +#define FPU_VFP_HARD (FPU_VFP_EXT_V1xD | FPU_VFP_EXT_V1 | FPU_VFP_EXT_V2 \ + | FPU_VFP_EXT_V3 | FPU_NEON_EXT_V1) +#define FPU_FPA (FPU_FPA_EXT_V1 | FPU_FPA_EXT_V2) + +/* Deprecated */ +#define FPU_ARCH_VFP ARM_FEATURE (0, FPU_ENDIAN_PURE) + +#define FPU_ARCH_FPE ARM_FEATURE (0, FPU_FPA_EXT_V1) +#define FPU_ARCH_FPA ARM_FEATURE (0, FPU_FPA) + +#define FPU_ARCH_VFP_V1xD ARM_FEATURE (0, FPU_VFP_V1xD) +#define FPU_ARCH_VFP_V1 ARM_FEATURE (0, FPU_VFP_V1) +#define FPU_ARCH_VFP_V2 ARM_FEATURE (0, FPU_VFP_V2) +#define FPU_ARCH_VFP_V3 ARM_FEATURE (0, FPU_VFP_V3) +#define FPU_ARCH_NEON_V1 ARM_FEATURE (0, FPU_NEON_EXT_V1) +#define FPU_ARCH_VFP_V3_PLUS_NEON_V1 \ + ARM_FEATURE (0, FPU_VFP_V3 | FPU_NEON_EXT_V1) +#define FPU_ARCH_VFP_HARD ARM_FEATURE (0, FPU_VFP_HARD) + +#define FPU_ARCH_ENDIAN_PURE ARM_FEATURE (0, FPU_ENDIAN_PURE) + +#define FPU_ARCH_MAVERICK ARM_FEATURE (0, FPU_MAVERICK) + +#define ARM_ARCH_V1 ARM_FEATURE (ARM_AEXT_V1, 0) +#define ARM_ARCH_V2 ARM_FEATURE (ARM_AEXT_V2, 0) +#define ARM_ARCH_V2S ARM_FEATURE (ARM_AEXT_V2S, 0) +#define ARM_ARCH_V3 ARM_FEATURE (ARM_AEXT_V3, 0) +#define ARM_ARCH_V3M ARM_FEATURE (ARM_AEXT_V3M, 0) +#define ARM_ARCH_V4xM ARM_FEATURE (ARM_AEXT_V4xM, 0) +#define ARM_ARCH_V4 ARM_FEATURE (ARM_AEXT_V4, 0) +#define ARM_ARCH_V4TxM ARM_FEATURE (ARM_AEXT_V4TxM, 0) +#define ARM_ARCH_V4T ARM_FEATURE (ARM_AEXT_V4T, 0) +#define ARM_ARCH_V5xM ARM_FEATURE (ARM_AEXT_V5xM, 0) +#define ARM_ARCH_V5 ARM_FEATURE (ARM_AEXT_V5, 0) +#define ARM_ARCH_V5TxM ARM_FEATURE (ARM_AEXT_V5TxM, 0) +#define ARM_ARCH_V5T ARM_FEATURE (ARM_AEXT_V5T, 0) +#define ARM_ARCH_V5TExP ARM_FEATURE (ARM_AEXT_V5TExP, 0) +#define ARM_ARCH_V5TE ARM_FEATURE (ARM_AEXT_V5TE, 0) +#define ARM_ARCH_V5TEJ ARM_FEATURE (ARM_AEXT_V5TEJ, 0) +#define ARM_ARCH_V6 ARM_FEATURE (ARM_AEXT_V6, 0) +#define ARM_ARCH_V6K ARM_FEATURE (ARM_AEXT_V6K, 0) +#define ARM_ARCH_V6Z ARM_FEATURE (ARM_AEXT_V6Z, 0) +#define ARM_ARCH_V6ZK ARM_FEATURE (ARM_AEXT_V6ZK, 0) +#define ARM_ARCH_V6T2 ARM_FEATURE (ARM_AEXT_V6T2, 0) +#define ARM_ARCH_V6KT2 ARM_FEATURE (ARM_AEXT_V6KT2, 0) +#define ARM_ARCH_V6ZT2 ARM_FEATURE (ARM_AEXT_V6ZT2, 0) +#define ARM_ARCH_V6ZKT2 ARM_FEATURE (ARM_AEXT_V6ZKT2, 0) +#define ARM_ARCH_V7 ARM_FEATURE (ARM_AEXT_V7, 0) +#define ARM_ARCH_V7A ARM_FEATURE (ARM_AEXT_V7A, 0) +#define ARM_ARCH_V7R ARM_FEATURE (ARM_AEXT_V7R, 0) +#define ARM_ARCH_V7M ARM_FEATURE (ARM_AEXT_V7M, 0) + +/* Some useful combinations: */ +#define ARM_ARCH_NONE ARM_FEATURE (0, 0) +#define FPU_NONE ARM_FEATURE (0, 0) +#define ARM_ANY ARM_FEATURE (-1, 0) /* Any basic core. */ +#define FPU_ANY_HARD ARM_FEATURE (0, FPU_FPA | FPU_VFP_HARD | FPU_MAVERICK) +#define ARM_ARCH_THUMB2 ARM_FEATURE (ARM_EXT_V6T2 | ARM_EXT_V7 | ARM_EXT_V7A | ARM_EXT_V7R | ARM_EXT_V7M | ARM_EXT_DIV, 0) + +/* There are too many feature bits to fit in a single word, so use a + structure. For simplicity we put all core features in one word and + everything else in the other. */ +typedef struct +{ + unsigned long core; + unsigned long coproc; +} arm_feature_set; + +#define ARM_CPU_HAS_FEATURE(CPU,FEAT) \ + (((CPU).core & (FEAT).core) != 0 || ((CPU).coproc & (FEAT).coproc) != 0) + +#define ARM_MERGE_FEATURE_SETS(TARG,F1,F2) \ + do { \ + (TARG).core = (F1).core | (F2).core; \ + (TARG).coproc = (F1).coproc | (F2).coproc; \ + } while (0) + +#define ARM_CLEAR_FEATURE(TARG,F1,F2) \ + do { \ + (TARG).core = (F1).core &~ (F2).core; \ + (TARG).coproc = (F1).coproc &~ (F2).coproc; \ + } while (0) + +#define ARM_FEATURE(core, coproc) {(core), (coproc)} diff --git a/kernel/fiasco/src/lib/disasm/include/opcode/ppc.h b/kernel/fiasco/src/lib/disasm/include/opcode/ppc.h new file mode 100644 index 00000000..6771856f --- /dev/null +++ b/kernel/fiasco/src/lib/disasm/include/opcode/ppc.h @@ -0,0 +1,326 @@ +/* ppc.h -- Header file for PowerPC opcode table + Copyright 1994, 1995, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, + 2007 Free Software Foundation, Inc. + Written by Ian Lance Taylor, Cygnus Support + +This file is part of GDB, GAS, and the GNU binutils. + +GDB, GAS, and the GNU binutils are free software; you can redistribute +them and/or modify them under the terms of the GNU General Public +License as published by the Free Software Foundation; either version +1, or (at your option) any later version. + +GDB, GAS, and the GNU binutils are distributed in the hope that they +will be useful, but WITHOUT ANY WARRANTY; without even the implied +warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See +the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this file; see the file COPYING. If not, write to the Free +Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ + +#ifndef PPC_H +#define PPC_H + +/* The opcode table is an array of struct powerpc_opcode. */ + +struct powerpc_opcode +{ + /* The opcode name. */ + const char *name; + + /* The opcode itself. Those bits which will be filled in with + operands are zeroes. */ + unsigned long opcode; + + /* The opcode mask. This is used by the disassembler. This is a + mask containing ones indicating those bits which must match the + opcode field, and zeroes indicating those bits which need not + match (and are presumably filled in by operands). */ + unsigned long mask; + + /* One bit flags for the opcode. These are used to indicate which + specific processors support the instructions. The defined values + are listed below. */ + unsigned long flags; + + /* An array of operand codes. Each code is an index into the + operand table. They appear in the order which the operands must + appear in assembly code, and are terminated by a zero. */ + unsigned char operands[8]; +}; + +/* The table itself is sorted by major opcode number, and is otherwise + in the order in which the disassembler should consider + instructions. */ +extern const struct powerpc_opcode powerpc_opcodes[]; +extern const int powerpc_num_opcodes; + +/* Values defined for the flags field of a struct powerpc_opcode. */ + +/* Opcode is defined for the PowerPC architecture. */ +#define PPC_OPCODE_PPC 1 + +/* Opcode is defined for the POWER (RS/6000) architecture. */ +#define PPC_OPCODE_POWER 2 + +/* Opcode is defined for the POWER2 (Rios 2) architecture. */ +#define PPC_OPCODE_POWER2 4 + +/* Opcode is only defined on 32 bit architectures. */ +#define PPC_OPCODE_32 8 + +/* Opcode is only defined on 64 bit architectures. */ +#define PPC_OPCODE_64 0x10 + +/* Opcode is supported by the Motorola PowerPC 601 processor. The 601 + is assumed to support all PowerPC (PPC_OPCODE_PPC) instructions, + but it also supports many additional POWER instructions. */ +#define PPC_OPCODE_601 0x20 + +/* Opcode is supported in both the Power and PowerPC architectures + (ie, compiler's -mcpu=common or assembler's -mcom). */ +#define PPC_OPCODE_COMMON 0x40 + +/* Opcode is supported for any Power or PowerPC platform (this is + for the assembler's -many option, and it eliminates duplicates). */ +#define PPC_OPCODE_ANY 0x80 + +/* Opcode is supported as part of the 64-bit bridge. */ +#define PPC_OPCODE_64_BRIDGE 0x100 + +/* Opcode is supported by Altivec Vector Unit */ +#define PPC_OPCODE_ALTIVEC 0x200 + +/* Opcode is supported by PowerPC 403 processor. */ +#define PPC_OPCODE_403 0x400 + +/* Opcode is supported by PowerPC BookE processor. */ +#define PPC_OPCODE_BOOKE 0x800 + +/* Opcode is only supported by 64-bit PowerPC BookE processor. */ +#define PPC_OPCODE_BOOKE64 0x1000 + +/* Opcode is supported by PowerPC 440 processor. */ +#define PPC_OPCODE_440 0x2000 + +/* Opcode is only supported by Power4 architecture. */ +#define PPC_OPCODE_POWER4 0x4000 + +/* Opcode isn't supported by Power4 architecture. */ +#define PPC_OPCODE_NOPOWER4 0x8000 + +/* Opcode is only supported by POWERPC Classic architecture. */ +#define PPC_OPCODE_CLASSIC 0x10000 + +/* Opcode is only supported by e500x2 Core. */ +#define PPC_OPCODE_SPE 0x20000 + +/* Opcode is supported by e500x2 Integer select APU. */ +#define PPC_OPCODE_ISEL 0x40000 + +/* Opcode is an e500 SPE floating point instruction. */ +#define PPC_OPCODE_EFS 0x80000 + +/* Opcode is supported by branch locking APU. */ +#define PPC_OPCODE_BRLOCK 0x100000 + +/* Opcode is supported by performance monitor APU. */ +#define PPC_OPCODE_PMR 0x200000 + +/* Opcode is supported by cache locking APU. */ +#define PPC_OPCODE_CACHELCK 0x400000 + +/* Opcode is supported by machine check APU. */ +#define PPC_OPCODE_RFMCI 0x800000 + +/* Opcode is only supported by Power5 architecture. */ +#define PPC_OPCODE_POWER5 0x1000000 + +/* Opcode is supported by PowerPC e300 family. */ +#define PPC_OPCODE_E300 0x2000000 + +/* Opcode is only supported by Power6 architecture. */ +#define PPC_OPCODE_POWER6 0x4000000 + +/* Opcode is only supported by PowerPC Cell family. */ +#define PPC_OPCODE_CELL 0x8000000 + +/* A macro to extract the major opcode from an instruction. */ +#define PPC_OP(i) (((i) >> 26) & 0x3f) + +/* The operands table is an array of struct powerpc_operand. */ + +struct powerpc_operand +{ + /* A bitmask of bits in the operand. */ + unsigned int bitm; + + /* How far the operand is left shifted in the instruction. + -1 to indicate that BITM and SHIFT cannot be used to determine + where the operand goes in the insn. */ + int shift; + + /* Insertion function. This is used by the assembler. To insert an + operand value into an instruction, check this field. + + If it is NULL, execute + i |= (op & o->bitm) << o->shift; + (i is the instruction which we are filling in, o is a pointer to + this structure, and op is the operand value). + + If this field is not NULL, then simply call it with the + instruction and the operand value. It will return the new value + of the instruction. If the ERRMSG argument is not NULL, then if + the operand value is illegal, *ERRMSG will be set to a warning + string (the operand will be inserted in any case). If the + operand value is legal, *ERRMSG will be unchanged (most operands + can accept any value). */ + unsigned long (*insert) + (unsigned long instruction, long op, int dialect, const char **errmsg); + + /* Extraction function. This is used by the disassembler. To + extract this operand type from an instruction, check this field. + + If it is NULL, compute + op = (i >> o->shift) & o->bitm; + if ((o->flags & PPC_OPERAND_SIGNED) != 0) + sign_extend (op); + (i is the instruction, o is a pointer to this structure, and op + is the result). + + If this field is not NULL, then simply call it with the + instruction value. It will return the value of the operand. If + the INVALID argument is not NULL, *INVALID will be set to + non-zero if this operand type can not actually be extracted from + this operand (i.e., the instruction does not match). If the + operand is valid, *INVALID will not be changed. */ + long (*extract) (unsigned long instruction, int dialect, int *invalid); + + /* One bit syntax flags. */ + unsigned long flags; +}; + +/* Elements in the table are retrieved by indexing with values from + the operands field of the powerpc_opcodes table. */ + +extern const struct powerpc_operand powerpc_operands[]; +extern const unsigned int num_powerpc_operands; + +/* Values defined for the flags field of a struct powerpc_operand. */ + +/* This operand takes signed values. */ +#define PPC_OPERAND_SIGNED (0x1) + +/* This operand takes signed values, but also accepts a full positive + range of values when running in 32 bit mode. That is, if bits is + 16, it takes any value from -0x8000 to 0xffff. In 64 bit mode, + this flag is ignored. */ +#define PPC_OPERAND_SIGNOPT (0x2) + +/* This operand does not actually exist in the assembler input. This + is used to support extended mnemonics such as mr, for which two + operands fields are identical. The assembler should call the + insert function with any op value. The disassembler should call + the extract function, ignore the return value, and check the value + placed in the valid argument. */ +#define PPC_OPERAND_FAKE (0x4) + +/* The next operand should be wrapped in parentheses rather than + separated from this one by a comma. This is used for the load and + store instructions which want their operands to look like + reg,displacement(reg) + */ +#define PPC_OPERAND_PARENS (0x8) + +/* This operand may use the symbolic names for the CR fields, which + are + lt 0 gt 1 eq 2 so 3 un 3 + cr0 0 cr1 1 cr2 2 cr3 3 + cr4 4 cr5 5 cr6 6 cr7 7 + These may be combined arithmetically, as in cr2*4+gt. These are + only supported on the PowerPC, not the POWER. */ +#define PPC_OPERAND_CR (0x10) + +/* This operand names a register. The disassembler uses this to print + register names with a leading 'r'. */ +#define PPC_OPERAND_GPR (0x20) + +/* Like PPC_OPERAND_GPR, but don't print a leading 'r' for r0. */ +#define PPC_OPERAND_GPR_0 (0x40) + +/* This operand names a floating point register. The disassembler + prints these with a leading 'f'. */ +#define PPC_OPERAND_FPR (0x80) + +/* This operand is a relative branch displacement. The disassembler + prints these symbolically if possible. */ +#define PPC_OPERAND_RELATIVE (0x100) + +/* This operand is an absolute branch address. The disassembler + prints these symbolically if possible. */ +#define PPC_OPERAND_ABSOLUTE (0x200) + +/* This operand is optional, and is zero if omitted. This is used for + example, in the optional BF field in the comparison instructions. The + assembler must count the number of operands remaining on the line, + and the number of operands remaining for the opcode, and decide + whether this operand is present or not. The disassembler should + print this operand out only if it is not zero. */ +#define PPC_OPERAND_OPTIONAL (0x400) + +/* This flag is only used with PPC_OPERAND_OPTIONAL. If this operand + is omitted, then for the next operand use this operand value plus + 1, ignoring the next operand field for the opcode. This wretched + hack is needed because the Power rotate instructions can take + either 4 or 5 operands. The disassembler should print this operand + out regardless of the PPC_OPERAND_OPTIONAL field. */ +#define PPC_OPERAND_NEXT (0x800) + +/* This operand should be regarded as a negative number for the + purposes of overflow checking (i.e., the normal most negative + number is disallowed and one more than the normal most positive + number is allowed). This flag will only be set for a signed + operand. */ +#define PPC_OPERAND_NEGATIVE (0x1000) + +/* This operand names a vector unit register. The disassembler + prints these with a leading 'v'. */ +#define PPC_OPERAND_VR (0x2000) + +/* This operand is for the DS field in a DS form instruction. */ +#define PPC_OPERAND_DS (0x4000) + +/* This operand is for the DQ field in a DQ form instruction. */ +#define PPC_OPERAND_DQ (0x8000) + +/* Valid range of operand is 0..n rather than 0..n-1. */ +#define PPC_OPERAND_PLUS1 (0x10000) + +/* The POWER and PowerPC assemblers use a few macros. We keep them + with the operands table for simplicity. The macro table is an + array of struct powerpc_macro. */ + +struct powerpc_macro +{ + /* The macro name. */ + const char *name; + + /* The number of operands the macro takes. */ + unsigned int operands; + + /* One bit flags for the opcode. These are used to indicate which + specific processors support the instructions. The values are the + same as those for the struct powerpc_opcode flags field. */ + unsigned long flags; + + /* A format string to turn the macro into a normal instruction. + Each %N in the string is replaced with operand number N (zero + based). */ + const char *format; +}; + +extern const struct powerpc_macro powerpc_macros[]; +extern const int powerpc_num_macros; + +#endif /* PPC_H */ diff --git a/kernel/fiasco/src/lib/disasm/include/opcode/sparc.h b/kernel/fiasco/src/lib/disasm/include/opcode/sparc.h new file mode 100644 index 00000000..7ae3641c --- /dev/null +++ b/kernel/fiasco/src/lib/disasm/include/opcode/sparc.h @@ -0,0 +1,258 @@ +/* Definitions for opcode table for the sparc. + Copyright 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000, 2002, + 2003, 2005, 2010, 2011 Free Software Foundation, Inc. + + This file is part of GAS, the GNU Assembler, GDB, the GNU debugger, and + the GNU Binutils. + + GAS/GDB is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GAS/GDB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GAS or GDB; see the file COPYING3. If not, write to + the Free Software Foundation, 51 Franklin Street - Fifth Floor, + Boston, MA 02110-1301, USA. */ + +#include "ansidecl.h" + +/* The SPARC opcode table (and other related data) is defined in + the opcodes library in sparc-opc.c. If you change anything here, make + sure you fix up that file, and vice versa. */ + + /* FIXME-someday: perhaps the ,a's and such should be embedded in the + instruction's name rather than the args. This would make gas faster, pinsn + slower, but would mess up some macros a bit. xoxorich. */ + +/* List of instruction sets variations. + These values are such that each element is either a superset of a + preceding each one or they conflict in which case SPARC_OPCODE_CONFLICT_P + returns non-zero. + The values are indices into `sparc_opcode_archs' defined in sparc-opc.c. + Don't change this without updating sparc-opc.c. */ + +enum sparc_opcode_arch_val +{ + SPARC_OPCODE_ARCH_V6 = 0, + SPARC_OPCODE_ARCH_V7, + SPARC_OPCODE_ARCH_V8, + SPARC_OPCODE_ARCH_SPARCLET, + SPARC_OPCODE_ARCH_SPARCLITE, + /* V9 variants must appear last. */ + SPARC_OPCODE_ARCH_V9, + SPARC_OPCODE_ARCH_V9A, /* V9 with ultrasparc additions. */ + SPARC_OPCODE_ARCH_V9B, /* V9 with ultrasparc and cheetah additions. */ + SPARC_OPCODE_ARCH_BAD /* Error return from sparc_opcode_lookup_arch. */ +}; + +/* The highest architecture in the table. */ +#define SPARC_OPCODE_ARCH_MAX (SPARC_OPCODE_ARCH_BAD - 1) + +/* Given an enum sparc_opcode_arch_val, return the bitmask to use in + insn encoding/decoding. */ +#define SPARC_OPCODE_ARCH_MASK(arch) (1 << (arch)) + +/* Given a valid sparc_opcode_arch_val, return non-zero if it's v9. */ +#define SPARC_OPCODE_ARCH_V9_P(arch) ((arch) >= SPARC_OPCODE_ARCH_V9) + +/* Table of cpu variants. */ + +typedef struct sparc_opcode_arch +{ + const char *name; + /* Mask of sparc_opcode_arch_val's supported. + EG: For v7 this would be + (SPARC_OPCODE_ARCH_MASK (..._V6) | SPARC_OPCODE_ARCH_MASK (..._V7)). + These are short's because sparc_opcode.architecture is. */ + short supported; +} sparc_opcode_arch; + +extern const struct sparc_opcode_arch sparc_opcode_archs[]; + +/* Given architecture name, look up it's sparc_opcode_arch_val value. */ +extern enum sparc_opcode_arch_val sparc_opcode_lookup_arch (const char *); + +/* Return the bitmask of supported architectures for ARCH. */ +#define SPARC_OPCODE_SUPPORTED(ARCH) (sparc_opcode_archs[ARCH].supported) + +/* Non-zero if ARCH1 conflicts with ARCH2. + IE: ARCH1 as a supported bit set that ARCH2 doesn't, and vice versa. */ +#define SPARC_OPCODE_CONFLICT_P(ARCH1, ARCH2) \ + (((SPARC_OPCODE_SUPPORTED (ARCH1) & SPARC_OPCODE_SUPPORTED (ARCH2)) \ + != SPARC_OPCODE_SUPPORTED (ARCH1)) \ + && ((SPARC_OPCODE_SUPPORTED (ARCH1) & SPARC_OPCODE_SUPPORTED (ARCH2)) \ + != SPARC_OPCODE_SUPPORTED (ARCH2))) + +/* Structure of an opcode table entry. */ + +typedef struct sparc_opcode +{ + const char *name; + unsigned long match; /* Bits that must be set. */ + unsigned long lose; /* Bits that must not be set. */ + const char *args; + /* This was called "delayed" in versions before the flags. */ + unsigned int flags; + short architecture; /* Bitmask of sparc_opcode_arch_val's. */ +} sparc_opcode; + +/* FIXME: Add F_ANACHRONISTIC flag for v9. */ +#define F_DELAYED 0x00000001 /* Delayed branch. */ +#define F_ALIAS 0x00000002 /* Alias for a "real" instruction. */ +#define F_UNBR 0x00000004 /* Unconditional branch. */ +#define F_CONDBR 0x00000008 /* Conditional branch. */ +#define F_JSR 0x00000010 /* Subroutine call. */ +#define F_FLOAT 0x00000020 /* Floating point instruction (not a branch). */ +#define F_FBR 0x00000040 /* Floating point branch. */ +#define F_MUL32 0x00000100 /* umul/umulcc/smul/smulcc insns */ +#define F_DIV32 0x00000200 /* udiv/udivcc/sdiv/sdivcc insns */ +#define F_FSMULD 0x00000400 /* 'fsmuld' insn */ +#define F_V8PLUS 0x00000800 /* v9 insns available to 32bit */ +#define F_POPC 0x00001000 /* 'popc' insn */ +#define F_VIS 0x00002000 /* VIS insns */ +#define F_VIS2 0x00004000 /* VIS2 insns */ +#define F_ASI_BLK_INIT 0x00008000 /* block init ASIs */ +#define F_FMAF 0x00010000 /* fused multiply-add */ +#define F_VIS3 0x00020000 /* VIS3 insns */ +#define F_HPC 0x00040000 /* HPC insns */ +#define F_RANDOM 0x00080000 /* 'random' insn */ +#define F_TRANS 0x00100000 /* transaction insns */ +#define F_FJFMAU 0x00200000 /* unfused multiply-add */ +#define F_IMA 0x00400000 /* integer multiply-add */ +#define F_ASI_CACHE_SPARING \ + 0x00800000 /* cache sparing ASIs */ + +#define F_HWCAP_MASK 0x00ffff00 + +/* All sparc opcodes are 32 bits, except for the `set' instruction (really a + macro), which is 64 bits. It is handled as a special case. + + The match component is a mask saying which bits must match a particular + opcode in order for an instruction to be an instance of that opcode. + + The args component is a string containing one character for each operand of the + instruction. + + Kinds of operands: + # Number used by optimizer. It is ignored. + 1 rs1 register. + 2 rs2 register. + d rd register. + e frs1 floating point register. + v frs1 floating point register (double/even). + V frs1 floating point register (quad/multiple of 4). + f frs2 floating point register. + B frs2 floating point register (double/even). + R frs2 floating point register (quad/multiple of 4). + 4 frs3 floating point register. + 5 frs3 floating point register (doube/even). + g frsd floating point register. + H frsd floating point register (double/even). + J frsd floating point register (quad/multiple of 4). + b crs1 coprocessor register + c crs2 coprocessor register + D crsd coprocessor register + m alternate space register (asr) in rd + M alternate space register (asr) in rs1 + h 22 high bits. + X 5 bit unsigned immediate + Y 6 bit unsigned immediate + 3 SIAM mode (3 bits). (v9b) + K MEMBAR mask (7 bits). (v9) + j 10 bit Immediate. (v9) + I 11 bit Immediate. (v9) + i 13 bit Immediate. + n 22 bit immediate. + k 2+14 bit PC relative immediate. (v9) + G 19 bit PC relative immediate. (v9) + l 22 bit PC relative immediate. + L 30 bit PC relative immediate. + a Annul. The annul bit is set. + A Alternate address space. Stored as 8 bits. + C Coprocessor state register. + F floating point state register. + p Processor state register. + N Branch predict clear ",pn" (v9) + T Branch predict set ",pt" (v9) + z %icc. (v9) + Z %xcc. (v9) + q Floating point queue. + r Single register that is both rs1 and rd. + O Single register that is both rs2 and rd. + Q Coprocessor queue. + S Special case. + t Trap base register. + w Window invalid mask register. + y Y register. + u sparclet coprocessor registers in rd position + U sparclet coprocessor registers in rs1 position + E %ccr. (v9) + s %fprs. (v9) + P %pc. (v9) + W %tick. (v9) + o %asi. (v9) + 6 %fcc0. (v9) + 7 %fcc1. (v9) + 8 %fcc2. (v9) + 9 %fcc3. (v9) + ! Privileged Register in rd (v9) + ? Privileged Register in rs1 (v9) + * Prefetch function constant. (v9) + x OPF field (v9 impdep). + 0 32/64 bit immediate for set or setx (v9) insns + _ Ancillary state register in rd (v9a) + / Ancillary state register in rs1 (v9a) + ( entire floating point state register (%efsr). */ + +#define OP2(x) (((x) & 0x7) << 22) /* Op2 field of format2 insns. */ +#define OP3(x) (((x) & 0x3f) << 19) /* Op3 field of format3 insns. */ +#define OP(x) ((unsigned) ((x) & 0x3) << 30) /* Op field of all insns. */ +#define OPF(x) (((x) & 0x1ff) << 5) /* Opf field of float insns. */ +#define OPF_LOW5(x) OPF ((x) & 0x1f) /* V9. */ +#define OPF_LOW4(x) OPF ((x) & 0xf) /* V9. */ +#define F3F(x, y, z) (OP (x) | OP3 (y) | OPF (z)) /* Format3 float insns. */ +#define F3I(x) (((x) & 0x1) << 13) /* Immediate field of format 3 insns. */ +#define F2(x, y) (OP (x) | OP2(y)) /* Format 2 insns. */ +#define F3(x, y, z) (OP (x) | OP3(y) | F3I(z)) /* Format3 insns. */ +#define F1(x) (OP (x)) +#define DISP30(x) ((x) & 0x3fffffff) +#define ASI(x) (((x) & 0xff) << 5) /* Asi field of format3 insns. */ +#define RS2(x) ((x) & 0x1f) /* Rs2 field. */ +#define SIMM13(x) ((x) & 0x1fff) /* Simm13 field. */ +#define RD(x) (((x) & 0x1f) << 25) /* Destination register field. */ +#define RS1(x) (((x) & 0x1f) << 14) /* Rs1 field. */ +#define RS3(x) (((x) & 0x1f) << 9) /* Rs3 field. */ +#define ASI_RS2(x) (SIMM13 (x)) +#define MEMBAR(x) ((x) & 0x7f) +#define SLCPOP(x) (((x) & 0x7f) << 6) /* Sparclet cpop. */ + +#define ANNUL (1 << 29) +#define BPRED (1 << 19) /* V9. */ +#define IMMED F3I (1) +#define RD_G0 RD (~0) +#define RS1_G0 RS1 (~0) +#define RS2_G0 RS2 (~0) + +extern const struct sparc_opcode sparc_opcodes[]; +extern const int sparc_num_opcodes; + +extern int sparc_encode_asi (const char *); +extern const char *sparc_decode_asi (int); +extern int sparc_encode_membar (const char *); +extern const char *sparc_decode_membar (int); +extern int sparc_encode_prefetch (const char *); +extern const char *sparc_decode_prefetch (int); +extern int sparc_encode_sparclet_cpreg (const char *); +extern const char *sparc_decode_sparclet_cpreg (int); + +/* Local Variables: + fill-column: 131 + comment-column: 0 + End: */ + diff --git a/kernel/fiasco/src/lib/disasm/include/safe-ctype.h b/kernel/fiasco/src/lib/disasm/include/safe-ctype.h new file mode 100644 index 00000000..e59b357c --- /dev/null +++ b/kernel/fiasco/src/lib/disasm/include/safe-ctype.h @@ -0,0 +1,119 @@ +/* replacement macros. + + Copyright (C) 2000, 2001 Free Software Foundation, Inc. + Contributed by Zack Weinberg . + +This file is part of the libiberty library. +Libiberty is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +Libiberty is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with libiberty; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, +Boston, MA 02110-1301, USA. */ + +/* This is a compatible replacement of the standard C library's + with the following properties: + + - Implements all isxxx() macros required by C99. + - Also implements some character classes useful when + parsing C-like languages. + - Does not change behavior depending on the current locale. + - Behaves properly for all values in the range of a signed or + unsigned char. + + To avoid conflicts, this header defines the isxxx functions in upper + case, e.g. ISALPHA not isalpha. */ + +#ifndef SAFE_CTYPE_H +#define SAFE_CTYPE_H + +#ifdef isalpha + #error "safe-ctype.h and ctype.h may not be used simultaneously" +#endif + +/* Determine host character set. */ +#define HOST_CHARSET_UNKNOWN 0 +#define HOST_CHARSET_ASCII 1 +#define HOST_CHARSET_EBCDIC 2 + +#if '\n' == 0x0A && ' ' == 0x20 && '0' == 0x30 \ + && 'A' == 0x41 && 'a' == 0x61 && '!' == 0x21 +# define HOST_CHARSET HOST_CHARSET_ASCII +#else +# if '\n' == 0x15 && ' ' == 0x40 && '0' == 0xF0 \ + && 'A' == 0xC1 && 'a' == 0x81 && '!' == 0x5A +# define HOST_CHARSET HOST_CHARSET_EBCDIC +# else +# define HOST_CHARSET HOST_CHARSET_UNKNOWN +# endif +#endif + +/* Categories. */ + +enum { + /* In C99 */ + _sch_isblank = 0x0001, /* space \t */ + _sch_iscntrl = 0x0002, /* nonprinting characters */ + _sch_isdigit = 0x0004, /* 0-9 */ + _sch_islower = 0x0008, /* a-z */ + _sch_isprint = 0x0010, /* any printing character including ' ' */ + _sch_ispunct = 0x0020, /* all punctuation */ + _sch_isspace = 0x0040, /* space \t \n \r \f \v */ + _sch_isupper = 0x0080, /* A-Z */ + _sch_isxdigit = 0x0100, /* 0-9A-Fa-f */ + + /* Extra categories useful to cpplib. */ + _sch_isidst = 0x0200, /* A-Za-z_ */ + _sch_isvsp = 0x0400, /* \n \r */ + _sch_isnvsp = 0x0800, /* space \t \f \v \0 */ + + /* Combinations of the above. */ + _sch_isalpha = _sch_isupper|_sch_islower, /* A-Za-z */ + _sch_isalnum = _sch_isalpha|_sch_isdigit, /* A-Za-z0-9 */ + _sch_isidnum = _sch_isidst|_sch_isdigit, /* A-Za-z0-9_ */ + _sch_isgraph = _sch_isalnum|_sch_ispunct, /* isprint and not space */ + _sch_iscppsp = _sch_isvsp|_sch_isnvsp, /* isspace + \0 */ + _sch_isbasic = _sch_isprint|_sch_iscppsp /* basic charset of ISO C + (plus ` and @) */ +}; + +/* Character classification. */ +extern const unsigned short _sch_istable[256]; + +#define _sch_test(c, bit) (_sch_istable[(c) & 0xff] & (unsigned short)(bit)) + +#define ISALPHA(c) _sch_test(c, _sch_isalpha) +#define ISALNUM(c) _sch_test(c, _sch_isalnum) +#define ISBLANK(c) _sch_test(c, _sch_isblank) +#define ISCNTRL(c) _sch_test(c, _sch_iscntrl) +#define ISDIGIT(c) _sch_test(c, _sch_isdigit) +#define ISGRAPH(c) _sch_test(c, _sch_isgraph) +#define ISLOWER(c) _sch_test(c, _sch_islower) +#define ISPRINT(c) _sch_test(c, _sch_isprint) +#define ISPUNCT(c) _sch_test(c, _sch_ispunct) +#define ISSPACE(c) _sch_test(c, _sch_isspace) +#define ISUPPER(c) _sch_test(c, _sch_isupper) +#define ISXDIGIT(c) _sch_test(c, _sch_isxdigit) + +#define ISIDNUM(c) _sch_test(c, _sch_isidnum) +#define ISIDST(c) _sch_test(c, _sch_isidst) +#define IS_ISOBASIC(c) _sch_test(c, _sch_isbasic) +#define IS_VSPACE(c) _sch_test(c, _sch_isvsp) +#define IS_NVSPACE(c) _sch_test(c, _sch_isnvsp) +#define IS_SPACE_OR_NUL(c) _sch_test(c, _sch_iscppsp) + +/* Character transformation. */ +extern const unsigned char _sch_toupper[256]; +extern const unsigned char _sch_tolower[256]; +#define TOUPPER(c) _sch_toupper[(c) & 0xff] +#define TOLOWER(c) _sch_tolower[(c) & 0xff] + +#endif /* SAFE_CTYPE_H */ diff --git a/kernel/fiasco/src/lib/disasm/include/symcat.h b/kernel/fiasco/src/lib/disasm/include/symcat.h new file mode 100644 index 00000000..03a12921 --- /dev/null +++ b/kernel/fiasco/src/lib/disasm/include/symcat.h @@ -0,0 +1,49 @@ +/* Symbol concatenation utilities. + + Copyright (C) 1998, 2000 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ + +#ifndef SYM_CAT_H +#define SYM_CAT_H + +#if defined (__STDC__) || defined (ALMOST_STDC) || defined (HAVE_STRINGIZE) +#define CONCAT2(a,b) a##b +#define CONCAT3(a,b,c) a##b##c +#define CONCAT4(a,b,c,d) a##b##c##d +#define STRINGX(s) #s +#else +/* Note one should never pass extra whitespace to the CONCATn macros, + e.g. CONCAT2(foo, bar) because traditonal C will keep the space between + the two labels instead of concatenating them. Instead, make sure to + write CONCAT2(foo,bar). */ +#define CONCAT2(a,b) a/**/b +#define CONCAT3(a,b,c) a/**/b/**/c +#define CONCAT4(a,b,c,d) a/**/b/**/c/**/d +#define STRINGX(s) "s" +#endif + +#define XCONCAT2(a,b) CONCAT2(a,b) +#define XCONCAT3(a,b,c) CONCAT3(a,b,c) +#define XCONCAT4(a,b,c,d) CONCAT4(a,b,c,d) + +/* Note the layer of indirection here is typically used to allow + stringification of the expansion of macros. I.e. "#define foo + bar", "XSTRING(foo)", to yield "bar". Be aware that this only + works for __STDC__, not for traditional C which will still resolve + to "foo". */ +#define XSTRING(s) STRINGX(s) + +#endif /* SYM_CAT_H */ diff --git a/kernel/fiasco/src/lib/disasm/libiberty/safe-ctype.c b/kernel/fiasco/src/lib/disasm/libiberty/safe-ctype.c new file mode 100644 index 00000000..bc22b510 --- /dev/null +++ b/kernel/fiasco/src/lib/disasm/libiberty/safe-ctype.c @@ -0,0 +1,257 @@ +/* replacement macros. + + Copyright (C) 2000, 2001, 2002, 2003, 2004, + 2005 Free Software Foundation, Inc. + Contributed by Zack Weinberg . + +This file is part of the libiberty library. +Libiberty is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +Libiberty is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with libiberty; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, +Boston, MA 02110-1301, USA. */ + +/* + +@defvr Extension HOST_CHARSET +This macro indicates the basic character set and encoding used by the +host: more precisely, the encoding used for character constants in +preprocessor @samp{#if} statements (the C "execution character set"). +It is defined by @file{safe-ctype.h}, and will be an integer constant +with one of the following values: + +@ftable @code +@item HOST_CHARSET_UNKNOWN +The host character set is unknown - that is, not one of the next two +possibilities. + +@item HOST_CHARSET_ASCII +The host character set is ASCII. + +@item HOST_CHARSET_EBCDIC +The host character set is some variant of EBCDIC. (Only one of the +nineteen EBCDIC varying characters is tested; exercise caution.) +@end ftable +@end defvr + +@deffn Extension ISALPHA (@var{c}) +@deffnx Extension ISALNUM (@var{c}) +@deffnx Extension ISBLANK (@var{c}) +@deffnx Extension ISCNTRL (@var{c}) +@deffnx Extension ISDIGIT (@var{c}) +@deffnx Extension ISGRAPH (@var{c}) +@deffnx Extension ISLOWER (@var{c}) +@deffnx Extension ISPRINT (@var{c}) +@deffnx Extension ISPUNCT (@var{c}) +@deffnx Extension ISSPACE (@var{c}) +@deffnx Extension ISUPPER (@var{c}) +@deffnx Extension ISXDIGIT (@var{c}) + +These twelve macros are defined by @file{safe-ctype.h}. Each has the +same meaning as the corresponding macro (with name in lowercase) +defined by the standard header @file{ctype.h}. For example, +@code{ISALPHA} returns true for alphabetic characters and false for +others. However, there are two differences between these macros and +those provided by @file{ctype.h}: + +@itemize @bullet +@item These macros are guaranteed to have well-defined behavior for all +values representable by @code{signed char} and @code{unsigned char}, and +for @code{EOF}. + +@item These macros ignore the current locale; they are true for these +fixed sets of characters: +@multitable {@code{XDIGIT}} {yada yada yada yada yada yada yada yada} +@item @code{ALPHA} @tab @kbd{A-Za-z} +@item @code{ALNUM} @tab @kbd{A-Za-z0-9} +@item @code{BLANK} @tab @kbd{space tab} +@item @code{CNTRL} @tab @code{!PRINT} +@item @code{DIGIT} @tab @kbd{0-9} +@item @code{GRAPH} @tab @code{ALNUM || PUNCT} +@item @code{LOWER} @tab @kbd{a-z} +@item @code{PRINT} @tab @code{GRAPH ||} @kbd{space} +@item @code{PUNCT} @tab @kbd{`~!@@#$%^&*()_-=+[@{]@}\|;:'",<.>/?} +@item @code{SPACE} @tab @kbd{space tab \n \r \f \v} +@item @code{UPPER} @tab @kbd{A-Z} +@item @code{XDIGIT} @tab @kbd{0-9A-Fa-f} +@end multitable + +Note that, if the host character set is ASCII or a superset thereof, +all these macros will return false for all values of @code{char} outside +the range of 7-bit ASCII. In particular, both ISPRINT and ISCNTRL return +false for characters with numeric values from 128 to 255. +@end itemize +@end deffn + +@deffn Extension ISIDNUM (@var{c}) +@deffnx Extension ISIDST (@var{c}) +@deffnx Extension IS_VSPACE (@var{c}) +@deffnx Extension IS_NVSPACE (@var{c}) +@deffnx Extension IS_SPACE_OR_NUL (@var{c}) +@deffnx Extension IS_ISOBASIC (@var{c}) +These six macros are defined by @file{safe-ctype.h} and provide +additional character classes which are useful when doing lexical +analysis of C or similar languages. They are true for the following +sets of characters: + +@multitable {@code{SPACE_OR_NUL}} {yada yada yada yada yada yada yada yada} +@item @code{IDNUM} @tab @kbd{A-Za-z0-9_} +@item @code{IDST} @tab @kbd{A-Za-z_} +@item @code{VSPACE} @tab @kbd{\r \n} +@item @code{NVSPACE} @tab @kbd{space tab \f \v \0} +@item @code{SPACE_OR_NUL} @tab @code{VSPACE || NVSPACE} +@item @code{ISOBASIC} @tab @code{VSPACE || NVSPACE || PRINT} +@end multitable +@end deffn + +*/ + +#include "ansidecl.h" +#include +#include /* for EOF */ + +#if 0 +#if EOF != -1 + #error " requires EOF == -1" +#endif +#endif + +/* Shorthand */ +#define bl _sch_isblank +#define cn _sch_iscntrl +#define di _sch_isdigit +#define is _sch_isidst +#define lo _sch_islower +#define nv _sch_isnvsp +#define pn _sch_ispunct +#define pr _sch_isprint +#define sp _sch_isspace +#define up _sch_isupper +#define vs _sch_isvsp +#define xd _sch_isxdigit + +/* Masks. */ +#define L (const unsigned short) (lo|is |pr) /* lower case letter */ +#define XL (const unsigned short) (lo|is|xd|pr) /* lowercase hex digit */ +#define U (const unsigned short) (up|is |pr) /* upper case letter */ +#define XU (const unsigned short) (up|is|xd|pr) /* uppercase hex digit */ +#define D (const unsigned short) (di |xd|pr) /* decimal digit */ +#define P (const unsigned short) (pn |pr) /* punctuation */ +#define _ (const unsigned short) (pn|is |pr) /* underscore */ + +#define C (const unsigned short) ( cn) /* control character */ +#define Z (const unsigned short) (nv |cn) /* NUL */ +#define M (const unsigned short) (nv|sp |cn) /* cursor movement: \f \v */ +#define V (const unsigned short) (vs|sp |cn) /* vertical space: \r \n */ +#define T (const unsigned short) (nv|sp|bl|cn) /* tab */ +#define S (const unsigned short) (nv|sp|bl|pr) /* space */ + +/* Are we ASCII? */ +#if HOST_CHARSET == HOST_CHARSET_ASCII + +const unsigned short _sch_istable[256] = +{ + Z, C, C, C, C, C, C, C, /* NUL SOH STX ETX EOT ENQ ACK BEL */ + C, T, V, M, M, V, C, C, /* BS HT LF VT FF CR SO SI */ + C, C, C, C, C, C, C, C, /* DLE DC1 DC2 DC3 DC4 NAK SYN ETB */ + C, C, C, C, C, C, C, C, /* CAN EM SUB ESC FS GS RS US */ + S, P, P, P, P, P, P, P, /* SP ! " # $ % & ' */ + P, P, P, P, P, P, P, P, /* ( ) * + , - . / */ + D, D, D, D, D, D, D, D, /* 0 1 2 3 4 5 6 7 */ + D, D, P, P, P, P, P, P, /* 8 9 : ; < = > ? */ + P, XU, XU, XU, XU, XU, XU, U, /* @ A B C D E F G */ + U, U, U, U, U, U, U, U, /* H I J K L M N O */ + U, U, U, U, U, U, U, U, /* P Q R S T U V W */ + U, U, U, P, P, P, P, _, /* X Y Z [ \ ] ^ _ */ + P, XL, XL, XL, XL, XL, XL, L, /* ` a b c d e f g */ + L, L, L, L, L, L, L, L, /* h i j k l m n o */ + L, L, L, L, L, L, L, L, /* p q r s t u v w */ + L, L, L, P, P, P, P, C, /* x y z { | } ~ DEL */ + + /* high half of unsigned char is locale-specific, so all tests are + false in "C" locale */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +}; + +const unsigned char _sch_tolower[256] = +{ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 64, + + 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', + 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', + + 91, 92, 93, 94, 95, 96, + + 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', + 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', + + 123,124,125,126,127, + + 128,129,130,131, 132,133,134,135, 136,137,138,139, 140,141,142,143, + 144,145,146,147, 148,149,150,151, 152,153,154,155, 156,157,158,159, + 160,161,162,163, 164,165,166,167, 168,169,170,171, 172,173,174,175, + 176,177,178,179, 180,181,182,183, 184,185,186,187, 188,189,190,191, + + 192,193,194,195, 196,197,198,199, 200,201,202,203, 204,205,206,207, + 208,209,210,211, 212,213,214,215, 216,217,218,219, 220,221,222,223, + 224,225,226,227, 228,229,230,231, 232,233,234,235, 236,237,238,239, + 240,241,242,243, 244,245,246,247, 248,249,250,251, 252,253,254,255, +}; + +const unsigned char _sch_toupper[256] = +{ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 64, + + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', + 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', + + 91, 92, 93, 94, 95, 96, + + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', + 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', + + 123,124,125,126,127, + + 128,129,130,131, 132,133,134,135, 136,137,138,139, 140,141,142,143, + 144,145,146,147, 148,149,150,151, 152,153,154,155, 156,157,158,159, + 160,161,162,163, 164,165,166,167, 168,169,170,171, 172,173,174,175, + 176,177,178,179, 180,181,182,183, 184,185,186,187, 188,189,190,191, + + 192,193,194,195, 196,197,198,199, 200,201,202,203, 204,205,206,207, + 208,209,210,211, 212,213,214,215, 216,217,218,219, 220,221,222,223, + 224,225,226,227, 228,229,230,231, 232,233,234,235, 236,237,238,239, + 240,241,242,243, 244,245,246,247, 248,249,250,251, 252,253,254,255, +}; + +#else +# if HOST_CHARSET == HOST_CHARSET_EBCDIC + #error "FIXME: write tables for EBCDIC" +# else + #error "Unrecognized host character set" +# endif +#endif diff --git a/kernel/fiasco/src/lib/disasm/opcodes/arm-dis.c b/kernel/fiasco/src/lib/disasm/opcodes/arm-dis.c new file mode 100644 index 00000000..45036124 --- /dev/null +++ b/kernel/fiasco/src/lib/disasm/opcodes/arm-dis.c @@ -0,0 +1,4243 @@ +/* Instruction printing code for the ARM + Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 + 2007, Free Software Foundation, Inc. + Contributed by Richard Earnshaw (rwe@pegasus.esprit.ec.org) + Modification by James G. Smith (jsmith@cygnus.co.uk) + + This file is part of libopcodes. + + This library is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + It is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + MA 02110-1301, USA. */ + +#include "sysdep.h" + +#include "dis-asm.h" +#include "opcode/arm.h" +#include "opintl.h" +#include "safe-ctype.h" +#include "floatformat.h" + +/* FIXME: This shouldn't be done here. */ +//#include "coff/internal.h" +//#include "libcoff.h" +#include "elf-bfd.h" +#include "elf/internal.h" +#include "elf/arm.h" + +/* FIXME: Belongs in global header. */ +#ifndef strneq +#define strneq(a,b,n) (strncmp ((a), (b), (n)) == 0) +#endif + +#ifndef NUM_ELEM +#define NUM_ELEM(a) (sizeof (a) / sizeof (a)[0]) +#endif + +struct opcode32 +{ + unsigned long arch; /* Architecture defining this insn. */ + unsigned long value, mask; /* Recognise insn if (op&mask)==value. */ + const char *assembler; /* How to disassemble this insn. */ +}; + +struct opcode16 +{ + unsigned long arch; /* Architecture defining this insn. */ + unsigned short value, mask; /* Recognise insn if (op&mask)==value. */ + const char *assembler; /* How to disassemble this insn. */ +}; + +/* print_insn_coprocessor recognizes the following format control codes: + + %% % + + %c print condition code (always bits 28-31 in ARM mode) + %q print shifter argument + %u print condition code (unconditional in ARM mode) + %A print address for ldc/stc/ldf/stf instruction + %B print vstm/vldm register list + %C print vstr/vldr address operand + %I print cirrus signed shift immediate: bits 0..3|4..6 + %F print the COUNT field of a LFM/SFM instruction. + %P print floating point precision in arithmetic insn + %Q print floating point precision in ldf/stf insn + %R print floating point rounding mode + + %r print as an ARM register + %d print the bitfield in decimal + %k print immediate for VFPv3 conversion instruction + %x print the bitfield in hex + %X print the bitfield as 1 hex digit without leading "0x" + %f print a floating point constant if >7 else a + floating point register + %w print as an iWMMXt width field - [bhwd]ss/us + %g print as an iWMMXt 64-bit register + %G print as an iWMMXt general purpose or control register + %D print as a NEON D register + %Q print as a NEON Q register + + %y print a single precision VFP reg. + Codes: 0=>Sm, 1=>Sd, 2=>Sn, 3=>multi-list, 4=>Sm pair + %z print a double precision VFP reg + Codes: 0=>Dm, 1=>Dd, 2=>Dn, 3=>multi-list + + %'c print specified char iff bitfield is all ones + %`c print specified char iff bitfield is all zeroes + %?ab... select from array of values in big endian order + + %L print as an iWMMXt N/M width field. + %Z print the Immediate of a WSHUFH instruction. + %l like 'A' except use byte offsets for 'B' & 'H' + versions. + %i print 5-bit immediate in bits 8,3..0 + (print "32" when 0) + %r print register offset address for wldt/wstr instruction +*/ + +/* Common coprocessor opcodes shared between Arm and Thumb-2. */ + +static const struct opcode32 coprocessor_opcodes[] = +{ + /* XScale instructions. */ + {ARM_CEXT_XSCALE, 0x0e200010, 0x0fff0ff0, "mia%c\tacc0, %0-3r, %12-15r"}, + {ARM_CEXT_XSCALE, 0x0e280010, 0x0fff0ff0, "miaph%c\tacc0, %0-3r, %12-15r"}, + {ARM_CEXT_XSCALE, 0x0e2c0010, 0x0ffc0ff0, "mia%17'T%17`B%16'T%16`B%c\tacc0, %0-3r, %12-15r"}, + {ARM_CEXT_XSCALE, 0x0c400000, 0x0ff00fff, "mar%c\tacc0, %12-15r, %16-19r"}, + {ARM_CEXT_XSCALE, 0x0c500000, 0x0ff00fff, "mra%c\t%12-15r, %16-19r, acc0"}, + + /* Intel Wireless MMX technology instructions. */ +#define FIRST_IWMMXT_INSN 0x0e130130 +#define IWMMXT_INSN_COUNT 73 + {ARM_CEXT_IWMMXT, 0x0e130130, 0x0f3f0fff, "tandc%22-23w%c\t%12-15r"}, + {ARM_CEXT_XSCALE, 0x0e400010, 0x0ff00f3f, "tbcst%6-7w%c\t%16-19g, %12-15r"}, + {ARM_CEXT_XSCALE, 0x0e130170, 0x0f3f0ff8, "textrc%22-23w%c\t%12-15r, #%0-2d"}, + {ARM_CEXT_XSCALE, 0x0e100070, 0x0f300ff0, "textrm%3?su%22-23w%c\t%12-15r, %16-19g, #%0-2d"}, + {ARM_CEXT_XSCALE, 0x0e600010, 0x0ff00f38, "tinsr%6-7w%c\t%16-19g, %12-15r, #%0-2d"}, + {ARM_CEXT_XSCALE, 0x0e000110, 0x0ff00fff, "tmcr%c\t%16-19G, %12-15r"}, + {ARM_CEXT_XSCALE, 0x0c400000, 0x0ff00ff0, "tmcrr%c\t%0-3g, %12-15r, %16-19r"}, + {ARM_CEXT_XSCALE, 0x0e2c0010, 0x0ffc0e10, "tmia%17?tb%16?tb%c\t%5-8g, %0-3r, %12-15r"}, + {ARM_CEXT_XSCALE, 0x0e200010, 0x0fff0e10, "tmia%c\t%5-8g, %0-3r, %12-15r"}, + {ARM_CEXT_XSCALE, 0x0e280010, 0x0fff0e10, "tmiaph%c\t%5-8g, %0-3r, %12-15r"}, + {ARM_CEXT_XSCALE, 0x0e100030, 0x0f300fff, "tmovmsk%22-23w%c\t%12-15r, %16-19g"}, + {ARM_CEXT_XSCALE, 0x0e100110, 0x0ff00ff0, "tmrc%c\t%12-15r, %16-19G"}, + {ARM_CEXT_XSCALE, 0x0c500000, 0x0ff00ff0, "tmrrc%c\t%12-15r, %16-19r, %0-3g"}, + {ARM_CEXT_XSCALE, 0x0e130150, 0x0f3f0fff, "torc%22-23w%c\t%12-15r"}, + {ARM_CEXT_XSCALE, 0x0e130190, 0x0f3f0fff, "torvsc%22-23w%c\t%12-15r"}, + {ARM_CEXT_XSCALE, 0x0e2001c0, 0x0f300fff, "wabs%22-23w%c\t%12-15g, %16-19g"}, + {ARM_CEXT_XSCALE, 0x0e0001c0, 0x0f300fff, "wacc%22-23w%c\t%12-15g, %16-19g"}, + {ARM_CEXT_XSCALE, 0x0e000180, 0x0f000ff0, "wadd%20-23w%c\t%12-15g, %16-19g, %0-3g"}, + {ARM_CEXT_XSCALE, 0x0e2001a0, 0x0f300ff0, "waddbhus%22?ml%c\t%12-15g, %16-19g, %0-3g"}, + {ARM_CEXT_XSCALE, 0x0ea001a0, 0x0ff00ff0, "waddsubhx%c\t%12-15g, %16-19g, %0-3g"}, + {ARM_CEXT_XSCALE, 0x0e000020, 0x0f800ff0, "waligni%c\t%12-15g, %16-19g, %0-3g, #%20-22d"}, + {ARM_CEXT_XSCALE, 0x0e800020, 0x0fc00ff0, "walignr%20-21d%c\t%12-15g, %16-19g, %0-3g"}, + {ARM_CEXT_XSCALE, 0x0e200000, 0x0fe00ff0, "wand%20'n%c\t%12-15g, %16-19g, %0-3g"}, + {ARM_CEXT_XSCALE, 0x0e800000, 0x0fa00ff0, "wavg2%22?hb%20'r%c\t%12-15g, %16-19g, %0-3g"}, + {ARM_CEXT_XSCALE, 0x0e400000, 0x0fe00ff0, "wavg4%20'r%c\t%12-15g, %16-19g, %0-3g"}, + {ARM_CEXT_XSCALE, 0x0e000060, 0x0f300ff0, "wcmpeq%22-23w%c\t%12-15g, %16-19g, %0-3g"}, + {ARM_CEXT_XSCALE, 0x0e100060, 0x0f100ff0, "wcmpgt%21?su%22-23w%c\t%12-15g, %16-19g, %0-3g"}, + {ARM_CEXT_XSCALE, 0xfc500100, 0xfe500f00, "wldrd\t%12-15g, %r"}, + {ARM_CEXT_XSCALE, 0xfc100100, 0xfe500f00, "wldrw\t%12-15G, %A"}, + {ARM_CEXT_XSCALE, 0x0c100000, 0x0e100e00, "wldr%L%c\t%12-15g, %l"}, + {ARM_CEXT_XSCALE, 0x0e400100, 0x0fc00ff0, "wmac%21?su%20'z%c\t%12-15g, %16-19g, %0-3g"}, + {ARM_CEXT_XSCALE, 0x0e800100, 0x0fc00ff0, "wmadd%21?su%20'x%c\t%12-15g, %16-19g, %0-3g"}, + {ARM_CEXT_XSCALE, 0x0ec00100, 0x0fd00ff0, "wmadd%21?sun%c\t%12-15g, %16-19g, %0-3g"}, + {ARM_CEXT_XSCALE, 0x0e000160, 0x0f100ff0, "wmax%21?su%22-23w%c\t%12-15g, %16-19g, %0-3g"}, + {ARM_CEXT_XSCALE, 0x0e000080, 0x0f100fe0, "wmerge%c\t%12-15g, %16-19g, %0-3g, #%21-23d"}, + {ARM_CEXT_XSCALE, 0x0e0000a0, 0x0f800ff0, "wmia%21?tb%20?tb%22'n%c\t%12-15g, %16-19g, %0-3g"}, + {ARM_CEXT_XSCALE, 0x0e800120, 0x0f800ff0, "wmiaw%21?tb%20?tb%22'n%c\t%12-15g, %16-19g, %0-3g"}, + {ARM_CEXT_XSCALE, 0x0e100160, 0x0f100ff0, "wmin%21?su%22-23w%c\t%12-15g, %16-19g, %0-3g"}, + {ARM_CEXT_XSCALE, 0x0e000100, 0x0fc00ff0, "wmul%21?su%20?ml%23'r%c\t%12-15g, %16-19g, %0-3g"}, + {ARM_CEXT_XSCALE, 0x0ed00100, 0x0fd00ff0, "wmul%21?sumr%c\t%12-15g, %16-19g, %0-3g"}, + {ARM_CEXT_XSCALE, 0x0ee000c0, 0x0fe00ff0, "wmulwsm%20`r%c\t%12-15g, %16-19g, %0-3g"}, + {ARM_CEXT_XSCALE, 0x0ec000c0, 0x0fe00ff0, "wmulwum%20`r%c\t%12-15g, %16-19g, %0-3g"}, + {ARM_CEXT_XSCALE, 0x0eb000c0, 0x0ff00ff0, "wmulwl%c\t%12-15g, %16-19g, %0-3g"}, + {ARM_CEXT_XSCALE, 0x0e8000a0, 0x0f800ff0, "wqmia%21?tb%20?tb%22'n%c\t%12-15g, %16-19g, %0-3g"}, + {ARM_CEXT_XSCALE, 0x0e100080, 0x0fd00ff0, "wqmulm%21'r%c\t%12-15g, %16-19g, %0-3g"}, + {ARM_CEXT_XSCALE, 0x0ec000e0, 0x0fd00ff0, "wqmulwm%21'r%c\t%12-15g, %16-19g, %0-3g"}, + {ARM_CEXT_XSCALE, 0x0e000000, 0x0ff00ff0, "wor%c\t%12-15g, %16-19g, %0-3g"}, + {ARM_CEXT_XSCALE, 0x0e000080, 0x0f000ff0, "wpack%20-23w%c\t%12-15g, %16-19g, %0-3g"}, + {ARM_CEXT_XSCALE, 0xfe300040, 0xff300ef0, "wror%22-23w\t%12-15g, %16-19g, #%i"}, + {ARM_CEXT_XSCALE, 0x0e300040, 0x0f300ff0, "wror%22-23w%c\t%12-15g, %16-19g, %0-3g"}, + {ARM_CEXT_XSCALE, 0x0e300140, 0x0f300ff0, "wror%22-23wg%c\t%12-15g, %16-19g, %0-3G"}, + {ARM_CEXT_XSCALE, 0x0e000120, 0x0fa00ff0, "wsad%22?hb%20'z%c\t%12-15g, %16-19g, %0-3g"}, + {ARM_CEXT_XSCALE, 0x0e0001e0, 0x0f000ff0, "wshufh%c\t%12-15g, %16-19g, #%Z"}, + {ARM_CEXT_XSCALE, 0xfe100040, 0xff300ef0, "wsll%22-23w\t%12-15g, %16-19g, #%i"}, + {ARM_CEXT_XSCALE, 0x0e100040, 0x0f300ff0, "wsll%22-23w%8'g%c\t%12-15g, %16-19g, %0-3g"}, + {ARM_CEXT_XSCALE, 0x0e100148, 0x0f300ffc, "wsll%22-23w%8'g%c\t%12-15g, %16-19g, %0-3G"}, + {ARM_CEXT_XSCALE, 0xfe000040, 0xff300ef0, "wsra%22-23w\t%12-15g, %16-19g, #%i"}, + {ARM_CEXT_XSCALE, 0x0e000040, 0x0f300ff0, "wsra%22-23w%8'g%c\t%12-15g, %16-19g, %0-3g"}, + {ARM_CEXT_XSCALE, 0x0e000148, 0x0f300ffc, "wsra%22-23w%8'g%c\t%12-15g, %16-19g, %0-3G"}, + {ARM_CEXT_XSCALE, 0xfe200040, 0xff300ef0, "wsrl%22-23w\t%12-15g, %16-19g, #%i"}, + {ARM_CEXT_XSCALE, 0x0e200040, 0x0f300ff0, "wsrl%22-23w%8'g%c\t%12-15g, %16-19g, %0-3g"}, + {ARM_CEXT_XSCALE, 0x0e200148, 0x0f300ffc, "wsrl%22-23w%8'g%c\t%12-15g, %16-19g, %0-3G"}, + {ARM_CEXT_XSCALE, 0xfc400100, 0xfe500f00, "wstrd\t%12-15g, %r"}, + {ARM_CEXT_XSCALE, 0xfc000100, 0xfe500f00, "wstrw\t%12-15G, %A"}, + {ARM_CEXT_XSCALE, 0x0c000000, 0x0e100e00, "wstr%L%c\t%12-15g, %l"}, + {ARM_CEXT_XSCALE, 0x0e0001a0, 0x0f000ff0, "wsub%20-23w%c\t%12-15g, %16-19g, %0-3g"}, + {ARM_CEXT_XSCALE, 0x0ed001c0, 0x0ff00ff0, "wsubaddhx%c\t%12-15g, %16-19g, %0-3g"}, + {ARM_CEXT_XSCALE, 0x0e1001c0, 0x0f300ff0, "wabsdiff%22-23w%c\t%12-15g, %16-19g, %0-3g"}, + {ARM_CEXT_XSCALE, 0x0e0000c0, 0x0fd00fff, "wunpckeh%21?sub%c\t%12-15g, %16-19g"}, + {ARM_CEXT_XSCALE, 0x0e4000c0, 0x0fd00fff, "wunpckeh%21?suh%c\t%12-15g, %16-19g"}, + {ARM_CEXT_XSCALE, 0x0e8000c0, 0x0fd00fff, "wunpckeh%21?suw%c\t%12-15g, %16-19g"}, + {ARM_CEXT_XSCALE, 0x0e0000e0, 0x0f100fff, "wunpckel%21?su%22-23w%c\t%12-15g, %16-19g"}, + {ARM_CEXT_XSCALE, 0x0e1000c0, 0x0f300ff0, "wunpckih%22-23w%c\t%12-15g, %16-19g, %0-3g"}, + {ARM_CEXT_XSCALE, 0x0e1000e0, 0x0f300ff0, "wunpckil%22-23w%c\t%12-15g, %16-19g, %0-3g"}, + {ARM_CEXT_XSCALE, 0x0e100000, 0x0ff00ff0, "wxor%c\t%12-15g, %16-19g, %0-3g"}, + + /* Floating point coprocessor (FPA) instructions */ + {FPU_FPA_EXT_V1, 0x0e000100, 0x0ff08f10, "adf%c%P%R\t%12-14f, %16-18f, %0-3f"}, + {FPU_FPA_EXT_V1, 0x0e100100, 0x0ff08f10, "muf%c%P%R\t%12-14f, %16-18f, %0-3f"}, + {FPU_FPA_EXT_V1, 0x0e200100, 0x0ff08f10, "suf%c%P%R\t%12-14f, %16-18f, %0-3f"}, + {FPU_FPA_EXT_V1, 0x0e300100, 0x0ff08f10, "rsf%c%P%R\t%12-14f, %16-18f, %0-3f"}, + {FPU_FPA_EXT_V1, 0x0e400100, 0x0ff08f10, "dvf%c%P%R\t%12-14f, %16-18f, %0-3f"}, + {FPU_FPA_EXT_V1, 0x0e500100, 0x0ff08f10, "rdf%c%P%R\t%12-14f, %16-18f, %0-3f"}, + {FPU_FPA_EXT_V1, 0x0e600100, 0x0ff08f10, "pow%c%P%R\t%12-14f, %16-18f, %0-3f"}, + {FPU_FPA_EXT_V1, 0x0e700100, 0x0ff08f10, "rpw%c%P%R\t%12-14f, %16-18f, %0-3f"}, + {FPU_FPA_EXT_V1, 0x0e800100, 0x0ff08f10, "rmf%c%P%R\t%12-14f, %16-18f, %0-3f"}, + {FPU_FPA_EXT_V1, 0x0e900100, 0x0ff08f10, "fml%c%P%R\t%12-14f, %16-18f, %0-3f"}, + {FPU_FPA_EXT_V1, 0x0ea00100, 0x0ff08f10, "fdv%c%P%R\t%12-14f, %16-18f, %0-3f"}, + {FPU_FPA_EXT_V1, 0x0eb00100, 0x0ff08f10, "frd%c%P%R\t%12-14f, %16-18f, %0-3f"}, + {FPU_FPA_EXT_V1, 0x0ec00100, 0x0ff08f10, "pol%c%P%R\t%12-14f, %16-18f, %0-3f"}, + {FPU_FPA_EXT_V1, 0x0e008100, 0x0ff08f10, "mvf%c%P%R\t%12-14f, %0-3f"}, + {FPU_FPA_EXT_V1, 0x0e108100, 0x0ff08f10, "mnf%c%P%R\t%12-14f, %0-3f"}, + {FPU_FPA_EXT_V1, 0x0e208100, 0x0ff08f10, "abs%c%P%R\t%12-14f, %0-3f"}, + {FPU_FPA_EXT_V1, 0x0e308100, 0x0ff08f10, "rnd%c%P%R\t%12-14f, %0-3f"}, + {FPU_FPA_EXT_V1, 0x0e408100, 0x0ff08f10, "sqt%c%P%R\t%12-14f, %0-3f"}, + {FPU_FPA_EXT_V1, 0x0e508100, 0x0ff08f10, "log%c%P%R\t%12-14f, %0-3f"}, + {FPU_FPA_EXT_V1, 0x0e608100, 0x0ff08f10, "lgn%c%P%R\t%12-14f, %0-3f"}, + {FPU_FPA_EXT_V1, 0x0e708100, 0x0ff08f10, "exp%c%P%R\t%12-14f, %0-3f"}, + {FPU_FPA_EXT_V1, 0x0e808100, 0x0ff08f10, "sin%c%P%R\t%12-14f, %0-3f"}, + {FPU_FPA_EXT_V1, 0x0e908100, 0x0ff08f10, "cos%c%P%R\t%12-14f, %0-3f"}, + {FPU_FPA_EXT_V1, 0x0ea08100, 0x0ff08f10, "tan%c%P%R\t%12-14f, %0-3f"}, + {FPU_FPA_EXT_V1, 0x0eb08100, 0x0ff08f10, "asn%c%P%R\t%12-14f, %0-3f"}, + {FPU_FPA_EXT_V1, 0x0ec08100, 0x0ff08f10, "acs%c%P%R\t%12-14f, %0-3f"}, + {FPU_FPA_EXT_V1, 0x0ed08100, 0x0ff08f10, "atn%c%P%R\t%12-14f, %0-3f"}, + {FPU_FPA_EXT_V1, 0x0ee08100, 0x0ff08f10, "urd%c%P%R\t%12-14f, %0-3f"}, + {FPU_FPA_EXT_V1, 0x0ef08100, 0x0ff08f10, "nrm%c%P%R\t%12-14f, %0-3f"}, + {FPU_FPA_EXT_V1, 0x0e000110, 0x0ff00f1f, "flt%c%P%R\t%16-18f, %12-15r"}, + {FPU_FPA_EXT_V1, 0x0e100110, 0x0fff0f98, "fix%c%R\t%12-15r, %0-2f"}, + {FPU_FPA_EXT_V1, 0x0e200110, 0x0fff0fff, "wfs%c\t%12-15r"}, + {FPU_FPA_EXT_V1, 0x0e300110, 0x0fff0fff, "rfs%c\t%12-15r"}, + {FPU_FPA_EXT_V1, 0x0e400110, 0x0fff0fff, "wfc%c\t%12-15r"}, + {FPU_FPA_EXT_V1, 0x0e500110, 0x0fff0fff, "rfc%c\t%12-15r"}, + {FPU_FPA_EXT_V1, 0x0e90f110, 0x0ff8fff0, "cmf%c\t%16-18f, %0-3f"}, + {FPU_FPA_EXT_V1, 0x0eb0f110, 0x0ff8fff0, "cnf%c\t%16-18f, %0-3f"}, + {FPU_FPA_EXT_V1, 0x0ed0f110, 0x0ff8fff0, "cmfe%c\t%16-18f, %0-3f"}, + {FPU_FPA_EXT_V1, 0x0ef0f110, 0x0ff8fff0, "cnfe%c\t%16-18f, %0-3f"}, + {FPU_FPA_EXT_V1, 0x0c000100, 0x0e100f00, "stf%c%Q\t%12-14f, %A"}, + {FPU_FPA_EXT_V1, 0x0c100100, 0x0e100f00, "ldf%c%Q\t%12-14f, %A"}, + {FPU_FPA_EXT_V2, 0x0c000200, 0x0e100f00, "sfm%c\t%12-14f, %F, %A"}, + {FPU_FPA_EXT_V2, 0x0c100200, 0x0e100f00, "lfm%c\t%12-14f, %F, %A"}, + + /* Register load/store */ + {FPU_NEON_EXT_V1, 0x0d200b00, 0x0fb00f01, "vstmdb%c\t%16-19r%21'!, %B"}, + {FPU_NEON_EXT_V1, 0x0d300b00, 0x0fb00f01, "vldmdb%c\t%16-19r%21'!, %B"}, + {FPU_NEON_EXT_V1, 0x0c800b00, 0x0f900f01, "vstmia%c\t%16-19r%21'!, %B"}, + {FPU_NEON_EXT_V1, 0x0c900b00, 0x0f900f01, "vldmia%c\t%16-19r%21'!, %B"}, + {FPU_NEON_EXT_V1, 0x0d000b00, 0x0f300f00, "vstr%c\t%12-15,22D, %C"}, + {FPU_NEON_EXT_V1, 0x0d100b00, 0x0f300f00, "vldr%c\t%12-15,22D, %C"}, + + /* Data transfer between ARM and NEON registers */ + {FPU_NEON_EXT_V1, 0x0e800b10, 0x0ff00f70, "vdup%c.32\t%16-19,7D, %12-15r"}, + {FPU_NEON_EXT_V1, 0x0e800b30, 0x0ff00f70, "vdup%c.16\t%16-19,7D, %12-15r"}, + {FPU_NEON_EXT_V1, 0x0ea00b10, 0x0ff00f70, "vdup%c.32\t%16-19,7Q, %12-15r"}, + {FPU_NEON_EXT_V1, 0x0ea00b30, 0x0ff00f70, "vdup%c.16\t%16-19,7Q, %12-15r"}, + {FPU_NEON_EXT_V1, 0x0ec00b10, 0x0ff00f70, "vdup%c.8\t%16-19,7D, %12-15r"}, + {FPU_NEON_EXT_V1, 0x0ee00b10, 0x0ff00f70, "vdup%c.8\t%16-19,7Q, %12-15r"}, + {FPU_NEON_EXT_V1, 0x0c400b10, 0x0ff00fd0, "vmov%c\t%0-3,5D, %12-15r, %16-19r"}, + {FPU_NEON_EXT_V1, 0x0c500b10, 0x0ff00fd0, "vmov%c\t%12-15r, %16-19r, %0-3,5D"}, + {FPU_NEON_EXT_V1, 0x0e000b10, 0x0fd00f70, "vmov%c.32\t%16-19,7D[%21d], %12-15r"}, + {FPU_NEON_EXT_V1, 0x0e100b10, 0x0f500f70, "vmov%c.32\t%12-15r, %16-19,7D[%21d]"}, + {FPU_NEON_EXT_V1, 0x0e000b30, 0x0fd00f30, "vmov%c.16\t%16-19,7D[%6,21d], %12-15r"}, + {FPU_NEON_EXT_V1, 0x0e100b30, 0x0f500f30, "vmov%c.%23?us16\t%12-15r, %16-19,7D[%6,21d]"}, + {FPU_NEON_EXT_V1, 0x0e400b10, 0x0fd00f10, "vmov%c.8\t%16-19,7D[%5,6,21d], %12-15r"}, + {FPU_NEON_EXT_V1, 0x0e500b10, 0x0f500f10, "vmov%c.%23?us8\t%12-15r, %16-19,7D[%5,6,21d]"}, + + /* Floating point coprocessor (VFP) instructions */ + {FPU_VFP_EXT_V1xD, 0x0ef1fa10, 0x0fffffff, "fmstat%c"}, + {FPU_VFP_EXT_V1xD, 0x0ee00a10, 0x0fff0fff, "fmxr%c\tfpsid, %12-15r"}, + {FPU_VFP_EXT_V1xD, 0x0ee10a10, 0x0fff0fff, "fmxr%c\tfpscr, %12-15r"}, + {FPU_VFP_EXT_V1xD, 0x0ee60a10, 0x0fff0fff, "fmxr%c\tmvfr1, %12-15r"}, + {FPU_VFP_EXT_V1xD, 0x0ee70a10, 0x0fff0fff, "fmxr%c\tmvfr0, %12-15r"}, + {FPU_VFP_EXT_V1xD, 0x0ee80a10, 0x0fff0fff, "fmxr%c\tfpexc, %12-15r"}, + {FPU_VFP_EXT_V1xD, 0x0ee90a10, 0x0fff0fff, "fmxr%c\tfpinst, %12-15r\t@ Impl def"}, + {FPU_VFP_EXT_V1xD, 0x0eea0a10, 0x0fff0fff, "fmxr%c\tfpinst2, %12-15r\t@ Impl def"}, + {FPU_VFP_EXT_V1xD, 0x0ef00a10, 0x0fff0fff, "fmrx%c\t%12-15r, fpsid"}, + {FPU_VFP_EXT_V1xD, 0x0ef10a10, 0x0fff0fff, "fmrx%c\t%12-15r, fpscr"}, + {FPU_VFP_EXT_V1xD, 0x0ef60a10, 0x0fff0fff, "fmrx%c\t%12-15r, mvfr1"}, + {FPU_VFP_EXT_V1xD, 0x0ef70a10, 0x0fff0fff, "fmrx%c\t%12-15r, mvfr0"}, + {FPU_VFP_EXT_V1xD, 0x0ef80a10, 0x0fff0fff, "fmrx%c\t%12-15r, fpexc"}, + {FPU_VFP_EXT_V1xD, 0x0ef90a10, 0x0fff0fff, "fmrx%c\t%12-15r, fpinst\t@ Impl def"}, + {FPU_VFP_EXT_V1xD, 0x0efa0a10, 0x0fff0fff, "fmrx%c\t%12-15r, fpinst2\t@ Impl def"}, + {FPU_VFP_EXT_V1, 0x0e000b10, 0x0ff00fff, "fmdlr%c\t%z2, %12-15r"}, + {FPU_VFP_EXT_V1, 0x0e100b10, 0x0ff00fff, "fmrdl%c\t%12-15r, %z2"}, + {FPU_VFP_EXT_V1, 0x0e200b10, 0x0ff00fff, "fmdhr%c\t%z2, %12-15r"}, + {FPU_VFP_EXT_V1, 0x0e300b10, 0x0ff00fff, "fmrdh%c\t%12-15r, %z2"}, + {FPU_VFP_EXT_V1xD, 0x0ee00a10, 0x0ff00fff, "fmxr%c\t, %12-15r"}, + {FPU_VFP_EXT_V1xD, 0x0ef00a10, 0x0ff00fff, "fmrx%c\t%12-15r, "}, + {FPU_VFP_EXT_V1xD, 0x0e000a10, 0x0ff00f7f, "fmsr%c\t%y2, %12-15r"}, + {FPU_VFP_EXT_V1xD, 0x0e100a10, 0x0ff00f7f, "fmrs%c\t%12-15r, %y2"}, + {FPU_VFP_EXT_V1xD, 0x0eb50a40, 0x0fbf0f70, "fcmp%7'ezs%c\t%y1"}, + {FPU_VFP_EXT_V1, 0x0eb50b40, 0x0fbf0f70, "fcmp%7'ezd%c\t%z1"}, + {FPU_VFP_EXT_V1xD, 0x0eb00a40, 0x0fbf0fd0, "fcpys%c\t%y1, %y0"}, + {FPU_VFP_EXT_V1xD, 0x0eb00ac0, 0x0fbf0fd0, "fabss%c\t%y1, %y0"}, + {FPU_VFP_EXT_V1, 0x0eb00b40, 0x0fbf0fd0, "fcpyd%c\t%z1, %z0"}, + {FPU_VFP_EXT_V1, 0x0eb00bc0, 0x0fbf0fd0, "fabsd%c\t%z1, %z0"}, + {FPU_VFP_EXT_V1xD, 0x0eb10a40, 0x0fbf0fd0, "fnegs%c\t%y1, %y0"}, + {FPU_VFP_EXT_V1xD, 0x0eb10ac0, 0x0fbf0fd0, "fsqrts%c\t%y1, %y0"}, + {FPU_VFP_EXT_V1, 0x0eb10b40, 0x0fbf0fd0, "fnegd%c\t%z1, %z0"}, + {FPU_VFP_EXT_V1, 0x0eb10bc0, 0x0fbf0fd0, "fsqrtd%c\t%z1, %z0"}, + {FPU_VFP_EXT_V1, 0x0eb70ac0, 0x0fbf0fd0, "fcvtds%c\t%z1, %y0"}, + {FPU_VFP_EXT_V1, 0x0eb70bc0, 0x0fbf0fd0, "fcvtsd%c\t%y1, %z0"}, + {FPU_VFP_EXT_V1xD, 0x0eb80a40, 0x0fbf0fd0, "fuitos%c\t%y1, %y0"}, + {FPU_VFP_EXT_V1xD, 0x0eb80ac0, 0x0fbf0fd0, "fsitos%c\t%y1, %y0"}, + {FPU_VFP_EXT_V1, 0x0eb80b40, 0x0fbf0fd0, "fuitod%c\t%z1, %y0"}, + {FPU_VFP_EXT_V1, 0x0eb80bc0, 0x0fbf0fd0, "fsitod%c\t%z1, %y0"}, + {FPU_VFP_EXT_V1xD, 0x0eb40a40, 0x0fbf0f50, "fcmp%7'es%c\t%y1, %y0"}, + {FPU_VFP_EXT_V1, 0x0eb40b40, 0x0fbf0f50, "fcmp%7'ed%c\t%z1, %z0"}, + {FPU_VFP_EXT_V3, 0x0eba0a40, 0x0fbe0f50, "f%16?us%7?lhtos%c\t%y1, #%5,0-3k"}, + {FPU_VFP_EXT_V3, 0x0eba0b40, 0x0fbe0f50, "f%16?us%7?lhtod%c\t%z1, #%5,0-3k"}, + {FPU_VFP_EXT_V1xD, 0x0ebc0a40, 0x0fbe0f50, "fto%16?sui%7'zs%c\t%y1, %y0"}, + {FPU_VFP_EXT_V1, 0x0ebc0b40, 0x0fbe0f50, "fto%16?sui%7'zd%c\t%y1, %z0"}, + {FPU_VFP_EXT_V3, 0x0ebe0a40, 0x0fbe0f50, "fto%16?us%7?lhs%c\t%y1, #%5,0-3k"}, + {FPU_VFP_EXT_V3, 0x0ebe0b40, 0x0fbe0f50, "fto%16?us%7?lhd%c\t%z1, #%5,0-3k"}, + {FPU_VFP_EXT_V1, 0x0c500b10, 0x0fb00ff0, "fmrrd%c\t%12-15r, %16-19r, %z0"}, + {FPU_VFP_EXT_V3, 0x0eb00a00, 0x0fb00ff0, "fconsts%c\t%y1, #%0-3,16-19d"}, + {FPU_VFP_EXT_V3, 0x0eb00b00, 0x0fb00ff0, "fconstd%c\t%z1, #%0-3,16-19d"}, + {FPU_VFP_EXT_V2, 0x0c400a10, 0x0ff00fd0, "fmsrr%c\t%y4, %12-15r, %16-19r"}, + {FPU_VFP_EXT_V2, 0x0c400b10, 0x0ff00fd0, "fmdrr%c\t%z0, %12-15r, %16-19r"}, + {FPU_VFP_EXT_V2, 0x0c500a10, 0x0ff00fd0, "fmrrs%c\t%12-15r, %16-19r, %y4"}, + {FPU_VFP_EXT_V1xD, 0x0e000a00, 0x0fb00f50, "fmacs%c\t%y1, %y2, %y0"}, + {FPU_VFP_EXT_V1xD, 0x0e000a40, 0x0fb00f50, "fnmacs%c\t%y1, %y2, %y0"}, + {FPU_VFP_EXT_V1, 0x0e000b00, 0x0fb00f50, "fmacd%c\t%z1, %z2, %z0"}, + {FPU_VFP_EXT_V1, 0x0e000b40, 0x0fb00f50, "fnmacd%c\t%z1, %z2, %z0"}, + {FPU_VFP_EXT_V1xD, 0x0e100a00, 0x0fb00f50, "fmscs%c\t%y1, %y2, %y0"}, + {FPU_VFP_EXT_V1xD, 0x0e100a40, 0x0fb00f50, "fnmscs%c\t%y1, %y2, %y0"}, + {FPU_VFP_EXT_V1, 0x0e100b00, 0x0fb00f50, "fmscd%c\t%z1, %z2, %z0"}, + {FPU_VFP_EXT_V1, 0x0e100b40, 0x0fb00f50, "fnmscd%c\t%z1, %z2, %z0"}, + {FPU_VFP_EXT_V1xD, 0x0e200a00, 0x0fb00f50, "fmuls%c\t%y1, %y2, %y0"}, + {FPU_VFP_EXT_V1xD, 0x0e200a40, 0x0fb00f50, "fnmuls%c\t%y1, %y2, %y0"}, + {FPU_VFP_EXT_V1, 0x0e200b00, 0x0fb00f50, "fmuld%c\t%z1, %z2, %z0"}, + {FPU_VFP_EXT_V1, 0x0e200b40, 0x0fb00f50, "fnmuld%c\t%z1, %z2, %z0"}, + {FPU_VFP_EXT_V1xD, 0x0e300a00, 0x0fb00f50, "fadds%c\t%y1, %y2, %y0"}, + {FPU_VFP_EXT_V1xD, 0x0e300a40, 0x0fb00f50, "fsubs%c\t%y1, %y2, %y0"}, + {FPU_VFP_EXT_V1, 0x0e300b00, 0x0fb00f50, "faddd%c\t%z1, %z2, %z0"}, + {FPU_VFP_EXT_V1, 0x0e300b40, 0x0fb00f50, "fsubd%c\t%z1, %z2, %z0"}, + {FPU_VFP_EXT_V1xD, 0x0e800a00, 0x0fb00f50, "fdivs%c\t%y1, %y2, %y0"}, + {FPU_VFP_EXT_V1, 0x0e800b00, 0x0fb00f50, "fdivd%c\t%z1, %z2, %z0"}, + {FPU_VFP_EXT_V1xD, 0x0d200a00, 0x0fb00f00, "fstmdbs%c\t%16-19r!, %y3"}, + {FPU_VFP_EXT_V1xD, 0x0d200b00, 0x0fb00f00, "fstmdb%0?xd%c\t%16-19r!, %z3"}, + {FPU_VFP_EXT_V1xD, 0x0d300a00, 0x0fb00f00, "fldmdbs%c\t%16-19r!, %y3"}, + {FPU_VFP_EXT_V1xD, 0x0d300b00, 0x0fb00f00, "fldmdb%0?xd%c\t%16-19r!, %z3"}, + {FPU_VFP_EXT_V1xD, 0x0d000a00, 0x0f300f00, "fsts%c\t%y1, %A"}, + {FPU_VFP_EXT_V1, 0x0d000b00, 0x0f300f00, "fstd%c\t%z1, %A"}, + {FPU_VFP_EXT_V1xD, 0x0d100a00, 0x0f300f00, "flds%c\t%y1, %A"}, + {FPU_VFP_EXT_V1, 0x0d100b00, 0x0f300f00, "fldd%c\t%z1, %A"}, + {FPU_VFP_EXT_V1xD, 0x0c800a00, 0x0f900f00, "fstmias%c\t%16-19r%21'!, %y3"}, + {FPU_VFP_EXT_V1xD, 0x0c800b00, 0x0f900f00, "fstmia%0?xd%c\t%16-19r%21'!, %z3"}, + {FPU_VFP_EXT_V1xD, 0x0c900a00, 0x0f900f00, "fldmias%c\t%16-19r%21'!, %y3"}, + {FPU_VFP_EXT_V1xD, 0x0c900b00, 0x0f900f00, "fldmia%0?xd%c\t%16-19r%21'!, %z3"}, + + /* Cirrus coprocessor instructions. */ + {ARM_CEXT_MAVERICK, 0x0d100400, 0x0f500f00, "cfldrs%c\tmvf%12-15d, %A"}, + {ARM_CEXT_MAVERICK, 0x0c100400, 0x0f500f00, "cfldrs%c\tmvf%12-15d, %A"}, + {ARM_CEXT_MAVERICK, 0x0d500400, 0x0f500f00, "cfldrd%c\tmvd%12-15d, %A"}, + {ARM_CEXT_MAVERICK, 0x0c500400, 0x0f500f00, "cfldrd%c\tmvd%12-15d, %A"}, + {ARM_CEXT_MAVERICK, 0x0d100500, 0x0f500f00, "cfldr32%c\tmvfx%12-15d, %A"}, + {ARM_CEXT_MAVERICK, 0x0c100500, 0x0f500f00, "cfldr32%c\tmvfx%12-15d, %A"}, + {ARM_CEXT_MAVERICK, 0x0d500500, 0x0f500f00, "cfldr64%c\tmvdx%12-15d, %A"}, + {ARM_CEXT_MAVERICK, 0x0c500500, 0x0f500f00, "cfldr64%c\tmvdx%12-15d, %A"}, + {ARM_CEXT_MAVERICK, 0x0d000400, 0x0f500f00, "cfstrs%c\tmvf%12-15d, %A"}, + {ARM_CEXT_MAVERICK, 0x0c000400, 0x0f500f00, "cfstrs%c\tmvf%12-15d, %A"}, + {ARM_CEXT_MAVERICK, 0x0d400400, 0x0f500f00, "cfstrd%c\tmvd%12-15d, %A"}, + {ARM_CEXT_MAVERICK, 0x0c400400, 0x0f500f00, "cfstrd%c\tmvd%12-15d, %A"}, + {ARM_CEXT_MAVERICK, 0x0d000500, 0x0f500f00, "cfstr32%c\tmvfx%12-15d, %A"}, + {ARM_CEXT_MAVERICK, 0x0c000500, 0x0f500f00, "cfstr32%c\tmvfx%12-15d, %A"}, + {ARM_CEXT_MAVERICK, 0x0d400500, 0x0f500f00, "cfstr64%c\tmvdx%12-15d, %A"}, + {ARM_CEXT_MAVERICK, 0x0c400500, 0x0f500f00, "cfstr64%c\tmvdx%12-15d, %A"}, + {ARM_CEXT_MAVERICK, 0x0e000450, 0x0ff00ff0, "cfmvsr%c\tmvf%16-19d, %12-15r"}, + {ARM_CEXT_MAVERICK, 0x0e100450, 0x0ff00ff0, "cfmvrs%c\t%12-15r, mvf%16-19d"}, + {ARM_CEXT_MAVERICK, 0x0e000410, 0x0ff00ff0, "cfmvdlr%c\tmvd%16-19d, %12-15r"}, + {ARM_CEXT_MAVERICK, 0x0e100410, 0x0ff00ff0, "cfmvrdl%c\t%12-15r, mvd%16-19d"}, + {ARM_CEXT_MAVERICK, 0x0e000430, 0x0ff00ff0, "cfmvdhr%c\tmvd%16-19d, %12-15r"}, + {ARM_CEXT_MAVERICK, 0x0e100430, 0x0ff00fff, "cfmvrdh%c\t%12-15r, mvd%16-19d"}, + {ARM_CEXT_MAVERICK, 0x0e000510, 0x0ff00fff, "cfmv64lr%c\tmvdx%16-19d, %12-15r"}, + {ARM_CEXT_MAVERICK, 0x0e100510, 0x0ff00fff, "cfmvr64l%c\t%12-15r, mvdx%16-19d"}, + {ARM_CEXT_MAVERICK, 0x0e000530, 0x0ff00fff, "cfmv64hr%c\tmvdx%16-19d, %12-15r"}, + {ARM_CEXT_MAVERICK, 0x0e100530, 0x0ff00fff, "cfmvr64h%c\t%12-15r, mvdx%16-19d"}, + {ARM_CEXT_MAVERICK, 0x0e200440, 0x0ff00fff, "cfmval32%c\tmvax%12-15d, mvfx%16-19d"}, + {ARM_CEXT_MAVERICK, 0x0e100440, 0x0ff00fff, "cfmv32al%c\tmvfx%12-15d, mvax%16-19d"}, + {ARM_CEXT_MAVERICK, 0x0e200460, 0x0ff00fff, "cfmvam32%c\tmvax%12-15d, mvfx%16-19d"}, + {ARM_CEXT_MAVERICK, 0x0e100460, 0x0ff00fff, "cfmv32am%c\tmvfx%12-15d, mvax%16-19d"}, + {ARM_CEXT_MAVERICK, 0x0e200480, 0x0ff00fff, "cfmvah32%c\tmvax%12-15d, mvfx%16-19d"}, + {ARM_CEXT_MAVERICK, 0x0e100480, 0x0ff00fff, "cfmv32ah%c\tmvfx%12-15d, mvax%16-19d"}, + {ARM_CEXT_MAVERICK, 0x0e2004a0, 0x0ff00fff, "cfmva32%c\tmvax%12-15d, mvfx%16-19d"}, + {ARM_CEXT_MAVERICK, 0x0e1004a0, 0x0ff00fff, "cfmv32a%c\tmvfx%12-15d, mvax%16-19d"}, + {ARM_CEXT_MAVERICK, 0x0e2004c0, 0x0ff00fff, "cfmva64%c\tmvax%12-15d, mvdx%16-19d"}, + {ARM_CEXT_MAVERICK, 0x0e1004c0, 0x0ff00fff, "cfmv64a%c\tmvdx%12-15d, mvax%16-19d"}, + {ARM_CEXT_MAVERICK, 0x0e2004e0, 0x0fff0fff, "cfmvsc32%c\tdspsc, mvdx%12-15d"}, + {ARM_CEXT_MAVERICK, 0x0e1004e0, 0x0fff0fff, "cfmv32sc%c\tmvdx%12-15d, dspsc"}, + {ARM_CEXT_MAVERICK, 0x0e000400, 0x0ff00fff, "cfcpys%c\tmvf%12-15d, mvf%16-19d"}, + {ARM_CEXT_MAVERICK, 0x0e000420, 0x0ff00fff, "cfcpyd%c\tmvd%12-15d, mvd%16-19d"}, + {ARM_CEXT_MAVERICK, 0x0e000460, 0x0ff00fff, "cfcvtsd%c\tmvd%12-15d, mvf%16-19d"}, + {ARM_CEXT_MAVERICK, 0x0e000440, 0x0ff00fff, "cfcvtds%c\tmvf%12-15d, mvd%16-19d"}, + {ARM_CEXT_MAVERICK, 0x0e000480, 0x0ff00fff, "cfcvt32s%c\tmvf%12-15d, mvfx%16-19d"}, + {ARM_CEXT_MAVERICK, 0x0e0004a0, 0x0ff00fff, "cfcvt32d%c\tmvd%12-15d, mvfx%16-19d"}, + {ARM_CEXT_MAVERICK, 0x0e0004c0, 0x0ff00fff, "cfcvt64s%c\tmvf%12-15d, mvdx%16-19d"}, + {ARM_CEXT_MAVERICK, 0x0e0004e0, 0x0ff00fff, "cfcvt64d%c\tmvd%12-15d, mvdx%16-19d"}, + {ARM_CEXT_MAVERICK, 0x0e100580, 0x0ff00fff, "cfcvts32%c\tmvfx%12-15d, mvf%16-19d"}, + {ARM_CEXT_MAVERICK, 0x0e1005a0, 0x0ff00fff, "cfcvtd32%c\tmvfx%12-15d, mvd%16-19d"}, + {ARM_CEXT_MAVERICK, 0x0e1005c0, 0x0ff00fff, "cftruncs32%c\tmvfx%12-15d, mvf%16-19d"}, + {ARM_CEXT_MAVERICK, 0x0e1005e0, 0x0ff00fff, "cftruncd32%c\tmvfx%12-15d, mvd%16-19d"}, + {ARM_CEXT_MAVERICK, 0x0e000550, 0x0ff00ff0, "cfrshl32%c\tmvfx%16-19d, mvfx%0-3d, %12-15r"}, + {ARM_CEXT_MAVERICK, 0x0e000570, 0x0ff00ff0, "cfrshl64%c\tmvdx%16-19d, mvdx%0-3d, %12-15r"}, + {ARM_CEXT_MAVERICK, 0x0e000500, 0x0ff00f10, "cfsh32%c\tmvfx%12-15d, mvfx%16-19d, #%I"}, + {ARM_CEXT_MAVERICK, 0x0e200500, 0x0ff00f10, "cfsh64%c\tmvdx%12-15d, mvdx%16-19d, #%I"}, + {ARM_CEXT_MAVERICK, 0x0e100490, 0x0ff00ff0, "cfcmps%c\t%12-15r, mvf%16-19d, mvf%0-3d"}, + {ARM_CEXT_MAVERICK, 0x0e1004b0, 0x0ff00ff0, "cfcmpd%c\t%12-15r, mvd%16-19d, mvd%0-3d"}, + {ARM_CEXT_MAVERICK, 0x0e100590, 0x0ff00ff0, "cfcmp32%c\t%12-15r, mvfx%16-19d, mvfx%0-3d"}, + {ARM_CEXT_MAVERICK, 0x0e1005b0, 0x0ff00ff0, "cfcmp64%c\t%12-15r, mvdx%16-19d, mvdx%0-3d"}, + {ARM_CEXT_MAVERICK, 0x0e300400, 0x0ff00fff, "cfabss%c\tmvf%12-15d, mvf%16-19d"}, + {ARM_CEXT_MAVERICK, 0x0e300420, 0x0ff00fff, "cfabsd%c\tmvd%12-15d, mvd%16-19d"}, + {ARM_CEXT_MAVERICK, 0x0e300440, 0x0ff00fff, "cfnegs%c\tmvf%12-15d, mvf%16-19d"}, + {ARM_CEXT_MAVERICK, 0x0e300460, 0x0ff00fff, "cfnegd%c\tmvd%12-15d, mvd%16-19d"}, + {ARM_CEXT_MAVERICK, 0x0e300480, 0x0ff00ff0, "cfadds%c\tmvf%12-15d, mvf%16-19d, mvf%0-3d"}, + {ARM_CEXT_MAVERICK, 0x0e3004a0, 0x0ff00ff0, "cfaddd%c\tmvd%12-15d, mvd%16-19d, mvd%0-3d"}, + {ARM_CEXT_MAVERICK, 0x0e3004c0, 0x0ff00ff0, "cfsubs%c\tmvf%12-15d, mvf%16-19d, mvf%0-3d"}, + {ARM_CEXT_MAVERICK, 0x0e3004e0, 0x0ff00ff0, "cfsubd%c\tmvd%12-15d, mvd%16-19d, mvd%0-3d"}, + {ARM_CEXT_MAVERICK, 0x0e100400, 0x0ff00ff0, "cfmuls%c\tmvf%12-15d, mvf%16-19d, mvf%0-3d"}, + {ARM_CEXT_MAVERICK, 0x0e100420, 0x0ff00ff0, "cfmuld%c\tmvd%12-15d, mvd%16-19d, mvd%0-3d"}, + {ARM_CEXT_MAVERICK, 0x0e300500, 0x0ff00fff, "cfabs32%c\tmvfx%12-15d, mvfx%16-19d"}, + {ARM_CEXT_MAVERICK, 0x0e300520, 0x0ff00fff, "cfabs64%c\tmvdx%12-15d, mvdx%16-19d"}, + {ARM_CEXT_MAVERICK, 0x0e300540, 0x0ff00fff, "cfneg32%c\tmvfx%12-15d, mvfx%16-19d"}, + {ARM_CEXT_MAVERICK, 0x0e300560, 0x0ff00fff, "cfneg64%c\tmvdx%12-15d, mvdx%16-19d"}, + {ARM_CEXT_MAVERICK, 0x0e300580, 0x0ff00ff0, "cfadd32%c\tmvfx%12-15d, mvfx%16-19d, mvfx%0-3d"}, + {ARM_CEXT_MAVERICK, 0x0e3005a0, 0x0ff00ff0, "cfadd64%c\tmvdx%12-15d, mvdx%16-19d, mvdx%0-3d"}, + {ARM_CEXT_MAVERICK, 0x0e3005c0, 0x0ff00ff0, "cfsub32%c\tmvfx%12-15d, mvfx%16-19d, mvfx%0-3d"}, + {ARM_CEXT_MAVERICK, 0x0e3005e0, 0x0ff00ff0, "cfsub64%c\tmvdx%12-15d, mvdx%16-19d, mvdx%0-3d"}, + {ARM_CEXT_MAVERICK, 0x0e100500, 0x0ff00ff0, "cfmul32%c\tmvfx%12-15d, mvfx%16-19d, mvfx%0-3d"}, + {ARM_CEXT_MAVERICK, 0x0e100520, 0x0ff00ff0, "cfmul64%c\tmvdx%12-15d, mvdx%16-19d, mvdx%0-3d"}, + {ARM_CEXT_MAVERICK, 0x0e100540, 0x0ff00ff0, "cfmac32%c\tmvfx%12-15d, mvfx%16-19d, mvfx%0-3d"}, + {ARM_CEXT_MAVERICK, 0x0e100560, 0x0ff00ff0, "cfmsc32%c\tmvfx%12-15d, mvfx%16-19d, mvfx%0-3d"}, + {ARM_CEXT_MAVERICK, 0x0e000600, 0x0ff00f10, "cfmadd32%c\tmvax%5-7d, mvfx%12-15d, mvfx%16-19d, mvfx%0-3d"}, + {ARM_CEXT_MAVERICK, 0x0e100600, 0x0ff00f10, "cfmsub32%c\tmvax%5-7d, mvfx%12-15d, mvfx%16-19d, mvfx%0-3d"}, + {ARM_CEXT_MAVERICK, 0x0e200600, 0x0ff00f10, "cfmadda32%c\tmvax%5-7d, mvax%12-15d, mvfx%16-19d, mvfx%0-3d"}, + {ARM_CEXT_MAVERICK, 0x0e300600, 0x0ff00f10, "cfmsuba32%c\tmvax%5-7d, mvax%12-15d, mvfx%16-19d, mvfx%0-3d"}, + + /* Generic coprocessor instructions */ + {ARM_EXT_V2, 0x0c400000, 0x0ff00000, "mcrr%c\t%8-11d, %4-7d, %12-15r, %16-19r, cr%0-3d"}, + {ARM_EXT_V2, 0x0c500000, 0x0ff00000, "mrrc%c\t%8-11d, %4-7d, %12-15r, %16-19r, cr%0-3d"}, + {ARM_EXT_V2, 0x0e000000, 0x0f000010, "cdp%c\t%8-11d, %20-23d, cr%12-15d, cr%16-19d, cr%0-3d, {%5-7d}"}, + {ARM_EXT_V2, 0x0e100010, 0x0f100010, "mrc%c\t%8-11d, %21-23d, %12-15r, cr%16-19d, cr%0-3d, {%5-7d}"}, + {ARM_EXT_V2, 0x0e000010, 0x0f100010, "mcr%c\t%8-11d, %21-23d, %12-15r, cr%16-19d, cr%0-3d, {%5-7d}"}, + {ARM_EXT_V2, 0x0c000000, 0x0e100000, "stc%22'l%c\t%8-11d, cr%12-15d, %A"}, + {ARM_EXT_V2, 0x0c100000, 0x0e100000, "ldc%22'l%c\t%8-11d, cr%12-15d, %A"}, + + /* V6 coprocessor instructions */ + {ARM_EXT_V6, 0xfc500000, 0xfff00000, "mrrc2%c\t%8-11d, %4-7d, %12-15r, %16-19r, cr%0-3d"}, + {ARM_EXT_V6, 0xfc400000, 0xfff00000, "mcrr2%c\t%8-11d, %4-7d, %12-15r, %16-19r, cr%0-3d"}, + + /* V5 coprocessor instructions */ + {ARM_EXT_V5, 0xfc100000, 0xfe100000, "ldc2%22'l%c\t%8-11d, cr%12-15d, %A"}, + {ARM_EXT_V5, 0xfc000000, 0xfe100000, "stc2%22'l%c\t%8-11d, cr%12-15d, %A"}, + {ARM_EXT_V5, 0xfe000000, 0xff000010, "cdp2%c\t%8-11d, %20-23d, cr%12-15d, cr%16-19d, cr%0-3d, {%5-7d}"}, + {ARM_EXT_V5, 0xfe000010, 0xff100010, "mcr2%c\t%8-11d, %21-23d, %12-15r, cr%16-19d, cr%0-3d, {%5-7d}"}, + {ARM_EXT_V5, 0xfe100010, 0xff100010, "mrc2%c\t%8-11d, %21-23d, %12-15r, cr%16-19d, cr%0-3d, {%5-7d}"}, + + {0, 0, 0, 0} +}; + +/* Neon opcode table: This does not encode the top byte -- that is + checked by the print_insn_neon routine, as it depends on whether we are + doing thumb32 or arm32 disassembly. */ + +/* print_insn_neon recognizes the following format control codes: + + %% % + + %c print condition code + %A print v{st,ld}[1234] operands + %B print v{st,ld}[1234] any one operands + %C print v{st,ld}[1234] single->all operands + %D print scalar + %E print vmov, vmvn, vorr, vbic encoded constant + %F print vtbl,vtbx register list + + %r print as an ARM register + %d print the bitfield in decimal + %e print the 2^N - bitfield in decimal + %D print as a NEON D register + %Q print as a NEON Q register + %R print as a NEON D or Q register + %Sn print byte scaled width limited by n + %Tn print short scaled width limited by n + %Un print long scaled width limited by n + + %'c print specified char iff bitfield is all ones + %`c print specified char iff bitfield is all zeroes + %?ab... select from array of values in big endian order */ + +static const struct opcode32 neon_opcodes[] = +{ + /* Extract */ + {FPU_NEON_EXT_V1, 0xf2b00840, 0xffb00850, "vext%c.8\t%12-15,22R, %16-19,7R, %0-3,5R, #%8-11d"}, + {FPU_NEON_EXT_V1, 0xf2b00000, 0xffb00810, "vext%c.8\t%12-15,22R, %16-19,7R, %0-3,5R, #%8-11d"}, + + /* Move data element to all lanes */ + {FPU_NEON_EXT_V1, 0xf3b40c00, 0xffb70f90, "vdup%c.32\t%12-15,22R, %0-3,5D[%19d]"}, + {FPU_NEON_EXT_V1, 0xf3b20c00, 0xffb30f90, "vdup%c.16\t%12-15,22R, %0-3,5D[%18-19d]"}, + {FPU_NEON_EXT_V1, 0xf3b10c00, 0xffb10f90, "vdup%c.8\t%12-15,22R, %0-3,5D[%17-19d]"}, + + /* Table lookup */ + {FPU_NEON_EXT_V1, 0xf3b00800, 0xffb00c50, "vtbl%c.8\t%12-15,22D, %F, %0-3,5D"}, + {FPU_NEON_EXT_V1, 0xf3b00840, 0xffb00c50, "vtbx%c.8\t%12-15,22D, %F, %0-3,5D"}, + + /* Two registers, miscellaneous */ + {FPU_NEON_EXT_V1, 0xf2880a10, 0xfebf0fd0, "vmovl%c.%24?us8\t%12-15,22Q, %0-3,5D"}, + {FPU_NEON_EXT_V1, 0xf2900a10, 0xfebf0fd0, "vmovl%c.%24?us16\t%12-15,22Q, %0-3,5D"}, + {FPU_NEON_EXT_V1, 0xf2a00a10, 0xfebf0fd0, "vmovl%c.%24?us32\t%12-15,22Q, %0-3,5D"}, + {FPU_NEON_EXT_V1, 0xf3b00500, 0xffbf0f90, "vcnt%c.8\t%12-15,22R, %0-3,5R"}, + {FPU_NEON_EXT_V1, 0xf3b00580, 0xffbf0f90, "vmvn%c\t%12-15,22R, %0-3,5R"}, + {FPU_NEON_EXT_V1, 0xf3b20000, 0xffbf0f90, "vswp%c\t%12-15,22R, %0-3,5R"}, + {FPU_NEON_EXT_V1, 0xf3b20200, 0xffb30fd0, "vmovn%c.i%18-19T2\t%12-15,22D, %0-3,5Q"}, + {FPU_NEON_EXT_V1, 0xf3b20240, 0xffb30fd0, "vqmovun%c.s%18-19T2\t%12-15,22D, %0-3,5Q"}, + {FPU_NEON_EXT_V1, 0xf3b20280, 0xffb30fd0, "vqmovn%c.s%18-19T2\t%12-15,22D, %0-3,5Q"}, + {FPU_NEON_EXT_V1, 0xf3b202c0, 0xffb30fd0, "vqmovn%c.u%18-19T2\t%12-15,22D, %0-3,5Q"}, + {FPU_NEON_EXT_V1, 0xf3b20300, 0xffb30fd0, "vshll%c.i%18-19S2\t%12-15,22Q, %0-3,5D, #%18-19S2"}, + {FPU_NEON_EXT_V1, 0xf3bb0400, 0xffbf0e90, "vrecpe%c.%8?fu%18-19S2\t%12-15,22R, %0-3,5R"}, + {FPU_NEON_EXT_V1, 0xf3bb0480, 0xffbf0e90, "vrsqrte%c.%8?fu%18-19S2\t%12-15,22R, %0-3,5R"}, + {FPU_NEON_EXT_V1, 0xf3b00000, 0xffb30f90, "vrev64%c.%18-19S2\t%12-15,22R, %0-3,5R"}, + {FPU_NEON_EXT_V1, 0xf3b00080, 0xffb30f90, "vrev32%c.%18-19S2\t%12-15,22R, %0-3,5R"}, + {FPU_NEON_EXT_V1, 0xf3b00100, 0xffb30f90, "vrev16%c.%18-19S2\t%12-15,22R, %0-3,5R"}, + {FPU_NEON_EXT_V1, 0xf3b00400, 0xffb30f90, "vcls%c.s%18-19S2\t%12-15,22R, %0-3,5R"}, + {FPU_NEON_EXT_V1, 0xf3b00480, 0xffb30f90, "vclz%c.i%18-19S2\t%12-15,22R, %0-3,5R"}, + {FPU_NEON_EXT_V1, 0xf3b00700, 0xffb30f90, "vqabs%c.s%18-19S2\t%12-15,22R, %0-3,5R"}, + {FPU_NEON_EXT_V1, 0xf3b00780, 0xffb30f90, "vqneg%c.s%18-19S2\t%12-15,22R, %0-3,5R"}, + {FPU_NEON_EXT_V1, 0xf3b20080, 0xffb30f90, "vtrn%c.%18-19S2\t%12-15,22R, %0-3,5R"}, + {FPU_NEON_EXT_V1, 0xf3b20100, 0xffb30f90, "vuzp%c.%18-19S2\t%12-15,22R, %0-3,5R"}, + {FPU_NEON_EXT_V1, 0xf3b20180, 0xffb30f90, "vzip%c.%18-19S2\t%12-15,22R, %0-3,5R"}, + {FPU_NEON_EXT_V1, 0xf3b10000, 0xffb30b90, "vcgt%c.%10?fs%18-19S2\t%12-15,22R, %0-3,5R, #0"}, + {FPU_NEON_EXT_V1, 0xf3b10080, 0xffb30b90, "vcge%c.%10?fs%18-19S2\t%12-15,22R, %0-3,5R, #0"}, + {FPU_NEON_EXT_V1, 0xf3b10100, 0xffb30b90, "vceq%c.%10?fi%18-19S2\t%12-15,22R, %0-3,5R, #0"}, + {FPU_NEON_EXT_V1, 0xf3b10180, 0xffb30b90, "vcle%c.%10?fs%18-19S2\t%12-15,22R, %0-3,5R, #0"}, + {FPU_NEON_EXT_V1, 0xf3b10200, 0xffb30b90, "vclt%c.%10?fs%18-19S2\t%12-15,22R, %0-3,5R, #0"}, + {FPU_NEON_EXT_V1, 0xf3b10300, 0xffb30b90, "vabs%c.%10?fs%18-19S2\t%12-15,22R, %0-3,5R"}, + {FPU_NEON_EXT_V1, 0xf3b10380, 0xffb30b90, "vneg%c.%10?fs%18-19S2\t%12-15,22R, %0-3,5R"}, + {FPU_NEON_EXT_V1, 0xf3b00200, 0xffb30f10, "vpaddl%c.%7?us%18-19S2\t%12-15,22R, %0-3,5R"}, + {FPU_NEON_EXT_V1, 0xf3b00600, 0xffb30f10, "vpadal%c.%7?us%18-19S2\t%12-15,22R, %0-3,5R"}, + {FPU_NEON_EXT_V1, 0xf3b30600, 0xffb30e10, "vcvt%c.%7-8?usff%18-19Sa.%7-8?ffus%18-19Sa\t%12-15,22R, %0-3,5R"}, + + /* Three registers of the same length */ + {FPU_NEON_EXT_V1, 0xf2000110, 0xffb00f10, "vand%c\t%12-15,22R, %16-19,7R, %0-3,5R"}, + {FPU_NEON_EXT_V1, 0xf2100110, 0xffb00f10, "vbic%c\t%12-15,22R, %16-19,7R, %0-3,5R"}, + {FPU_NEON_EXT_V1, 0xf2200110, 0xffb00f10, "vorr%c\t%12-15,22R, %16-19,7R, %0-3,5R"}, + {FPU_NEON_EXT_V1, 0xf2300110, 0xffb00f10, "vorn%c\t%12-15,22R, %16-19,7R, %0-3,5R"}, + {FPU_NEON_EXT_V1, 0xf3000110, 0xffb00f10, "veor%c\t%12-15,22R, %16-19,7R, %0-3,5R"}, + {FPU_NEON_EXT_V1, 0xf3100110, 0xffb00f10, "vbsl%c\t%12-15,22R, %16-19,7R, %0-3,5R"}, + {FPU_NEON_EXT_V1, 0xf3200110, 0xffb00f10, "vbit%c\t%12-15,22R, %16-19,7R, %0-3,5R"}, + {FPU_NEON_EXT_V1, 0xf3300110, 0xffb00f10, "vbif%c\t%12-15,22R, %16-19,7R, %0-3,5R"}, + {FPU_NEON_EXT_V1, 0xf2000d00, 0xffa00f10, "vadd%c.f%20U0\t%12-15,22R, %16-19,7R, %0-3,5R"}, + {FPU_NEON_EXT_V1, 0xf2000d10, 0xffa00f10, "vmla%c.f%20U0\t%12-15,22R, %16-19,7R, %0-3,5R"}, + {FPU_NEON_EXT_V1, 0xf2000e00, 0xffa00f10, "vceq%c.f%20U0\t%12-15,22R, %16-19,7R, %0-3,5R"}, + {FPU_NEON_EXT_V1, 0xf2000f00, 0xffa00f10, "vmax%c.f%20U0\t%12-15,22R, %16-19,7R, %0-3,5R"}, + {FPU_NEON_EXT_V1, 0xf2000f10, 0xffa00f10, "vrecps%c.f%20U0\t%12-15,22R, %16-19,7R, %0-3,5R"}, + {FPU_NEON_EXT_V1, 0xf2200d00, 0xffa00f10, "vsub%c.f%20U0\t%12-15,22R, %16-19,7R, %0-3,5R"}, + {FPU_NEON_EXT_V1, 0xf2200d10, 0xffa00f10, "vmls%c.f%20U0\t%12-15,22R, %16-19,7R, %0-3,5R"}, + {FPU_NEON_EXT_V1, 0xf2200f00, 0xffa00f10, "vmin%c.f%20U0\t%12-15,22R, %16-19,7R, %0-3,5R"}, + {FPU_NEON_EXT_V1, 0xf2200f10, 0xffa00f10, "vrsqrts%c.f%20U0\t%12-15,22R, %16-19,7R, %0-3,5R"}, + {FPU_NEON_EXT_V1, 0xf3000d00, 0xffa00f10, "vpadd%c.f%20U0\t%12-15,22R, %16-19,7R, %0-3,5R"}, + {FPU_NEON_EXT_V1, 0xf3000d10, 0xffa00f10, "vmul%c.f%20U0\t%12-15,22R, %16-19,7R, %0-3,5R"}, + {FPU_NEON_EXT_V1, 0xf3000e00, 0xffa00f10, "vcge%c.f%20U0\t%12-15,22R, %16-19,7R, %0-3,5R"}, + {FPU_NEON_EXT_V1, 0xf3000e10, 0xffa00f10, "vacge%c.f%20U0\t%12-15,22R, %16-19,7R, %0-3,5R"}, + {FPU_NEON_EXT_V1, 0xf3000f00, 0xffa00f10, "vpmax%c.f%20U0\t%12-15,22R, %16-19,7R, %0-3,5R"}, + {FPU_NEON_EXT_V1, 0xf3200d00, 0xffa00f10, "vabd%c.f%20U0\t%12-15,22R, %16-19,7R, %0-3,5R"}, + {FPU_NEON_EXT_V1, 0xf3200e00, 0xffa00f10, "vcgt%c.f%20U0\t%12-15,22R, %16-19,7R, %0-3,5R"}, + {FPU_NEON_EXT_V1, 0xf3200e10, 0xffa00f10, "vacgt%c.f%20U0\t%12-15,22R, %16-19,7R, %0-3,5R"}, + {FPU_NEON_EXT_V1, 0xf3200f00, 0xffa00f10, "vpmin%c.f%20U0\t%12-15,22R, %16-19,7R, %0-3,5R"}, + {FPU_NEON_EXT_V1, 0xf2000800, 0xff800f10, "vadd%c.i%20-21S3\t%12-15,22R, %16-19,7R, %0-3,5R"}, + {FPU_NEON_EXT_V1, 0xf2000810, 0xff800f10, "vtst%c.%20-21S2\t%12-15,22R, %16-19,7R, %0-3,5R"}, + {FPU_NEON_EXT_V1, 0xf2000900, 0xff800f10, "vmla%c.i%20-21S2\t%12-15,22R, %16-19,7R, %0-3,5R"}, + {FPU_NEON_EXT_V1, 0xf2000b00, 0xff800f10, "vqdmulh%c.s%20-21S6\t%12-15,22R, %16-19,7R, %0-3,5R"}, + {FPU_NEON_EXT_V1, 0xf2000b10, 0xff800f10, "vpadd%c.i%20-21S2\t%12-15,22R, %16-19,7R, %0-3,5R"}, + {FPU_NEON_EXT_V1, 0xf3000800, 0xff800f10, "vsub%c.i%20-21S3\t%12-15,22R, %16-19,7R, %0-3,5R"}, + {FPU_NEON_EXT_V1, 0xf3000810, 0xff800f10, "vceq%c.i%20-21S2\t%12-15,22R, %16-19,7R, %0-3,5R"}, + {FPU_NEON_EXT_V1, 0xf3000900, 0xff800f10, "vmls%c.i%20-21S2\t%12-15,22R, %16-19,7R, %0-3,5R"}, + {FPU_NEON_EXT_V1, 0xf3000b00, 0xff800f10, "vqrdmulh%c.s%20-21S6\t%12-15,22R, %16-19,7R, %0-3,5R"}, + {FPU_NEON_EXT_V1, 0xf2000000, 0xfe800f10, "vhadd%c.%24?us%20-21S2\t%12-15,22R, %16-19,7R, %0-3,5R"}, + {FPU_NEON_EXT_V1, 0xf2000010, 0xfe800f10, "vqadd%c.%24?us%20-21S3\t%12-15,22R, %16-19,7R, %0-3,5R"}, + {FPU_NEON_EXT_V1, 0xf2000100, 0xfe800f10, "vrhadd%c.%24?us%20-21S2\t%12-15,22R, %16-19,7R, %0-3,5R"}, + {FPU_NEON_EXT_V1, 0xf2000200, 0xfe800f10, "vhsub%c.%24?us%20-21S2\t%12-15,22R, %16-19,7R, %0-3,5R"}, + {FPU_NEON_EXT_V1, 0xf2000210, 0xfe800f10, "vqsub%c.%24?us%20-21S3\t%12-15,22R, %16-19,7R, %0-3,5R"}, + {FPU_NEON_EXT_V1, 0xf2000300, 0xfe800f10, "vcgt%c.%24?us%20-21S2\t%12-15,22R, %16-19,7R, %0-3,5R"}, + {FPU_NEON_EXT_V1, 0xf2000310, 0xfe800f10, "vcge%c.%24?us%20-21S2\t%12-15,22R, %16-19,7R, %0-3,5R"}, + {FPU_NEON_EXT_V1, 0xf2000400, 0xfe800f10, "vshl%c.%24?us%20-21S3\t%12-15,22R, %0-3,5R, %16-19,7R"}, + {FPU_NEON_EXT_V1, 0xf2000410, 0xfe800f10, "vqshl%c.%24?us%20-21S3\t%12-15,22R, %0-3,5R, %16-19,7R"}, + {FPU_NEON_EXT_V1, 0xf2000500, 0xfe800f10, "vrshl%c.%24?us%20-21S3\t%12-15,22R, %0-3,5R, %16-19,7R"}, + {FPU_NEON_EXT_V1, 0xf2000510, 0xfe800f10, "vqrshl%c.%24?us%20-21S3\t%12-15,22R, %0-3,5R, %16-19,7R"}, + {FPU_NEON_EXT_V1, 0xf2000600, 0xfe800f10, "vmax%c.%24?us%20-21S2\t%12-15,22R, %16-19,7R, %0-3,5R"}, + {FPU_NEON_EXT_V1, 0xf2000610, 0xfe800f10, "vmin%c.%24?us%20-21S2\t%12-15,22R, %16-19,7R, %0-3,5R"}, + {FPU_NEON_EXT_V1, 0xf2000700, 0xfe800f10, "vabd%c.%24?us%20-21S2\t%12-15,22R, %16-19,7R, %0-3,5R"}, + {FPU_NEON_EXT_V1, 0xf2000710, 0xfe800f10, "vaba%c.%24?us%20-21S2\t%12-15,22R, %16-19,7R, %0-3,5R"}, + {FPU_NEON_EXT_V1, 0xf2000910, 0xfe800f10, "vmul%c.%24?pi%20-21S2\t%12-15,22R, %16-19,7R, %0-3,5R"}, + {FPU_NEON_EXT_V1, 0xf2000a00, 0xfe800f10, "vpmax%c.%24?us%20-21S2\t%12-15,22R, %16-19,7R, %0-3,5R"}, + {FPU_NEON_EXT_V1, 0xf2000a10, 0xfe800f10, "vpmin%c.%24?us%20-21S2\t%12-15,22R, %16-19,7R, %0-3,5R"}, + + /* One register and an immediate value */ + {FPU_NEON_EXT_V1, 0xf2800e10, 0xfeb80fb0, "vmov%c.i8\t%12-15,22R, %E"}, + {FPU_NEON_EXT_V1, 0xf2800e30, 0xfeb80fb0, "vmov%c.i64\t%12-15,22R, %E"}, + {FPU_NEON_EXT_V1, 0xf2800f10, 0xfeb80fb0, "vmov%c.f32\t%12-15,22R, %E"}, + {FPU_NEON_EXT_V1, 0xf2800810, 0xfeb80db0, "vmov%c.i16\t%12-15,22R, %E"}, + {FPU_NEON_EXT_V1, 0xf2800830, 0xfeb80db0, "vmvn%c.i16\t%12-15,22R, %E"}, + {FPU_NEON_EXT_V1, 0xf2800910, 0xfeb80db0, "vorr%c.i16\t%12-15,22R, %E"}, + {FPU_NEON_EXT_V1, 0xf2800930, 0xfeb80db0, "vbic%c.i16\t%12-15,22R, %E"}, + {FPU_NEON_EXT_V1, 0xf2800c10, 0xfeb80eb0, "vmov%c.i32\t%12-15,22R, %E"}, + {FPU_NEON_EXT_V1, 0xf2800c30, 0xfeb80eb0, "vmvn%c.i32\t%12-15,22R, %E"}, + {FPU_NEON_EXT_V1, 0xf2800110, 0xfeb809b0, "vorr%c.i32\t%12-15,22R, %E"}, + {FPU_NEON_EXT_V1, 0xf2800130, 0xfeb809b0, "vbic%c.i32\t%12-15,22R, %E"}, + {FPU_NEON_EXT_V1, 0xf2800010, 0xfeb808b0, "vmov%c.i32\t%12-15,22R, %E"}, + {FPU_NEON_EXT_V1, 0xf2800030, 0xfeb808b0, "vmvn%c.i32\t%12-15,22R, %E"}, + + /* Two registers and a shift amount */ + {FPU_NEON_EXT_V1, 0xf2880810, 0xffb80fd0, "vshrn%c.i16\t%12-15,22D, %0-3,5Q, #%16-18e"}, + {FPU_NEON_EXT_V1, 0xf2880850, 0xffb80fd0, "vrshrn%c.i16\t%12-15,22D, %0-3,5Q, #%16-18e"}, + {FPU_NEON_EXT_V1, 0xf2880810, 0xfeb80fd0, "vqshrun%c.s16\t%12-15,22D, %0-3,5Q, #%16-18e"}, + {FPU_NEON_EXT_V1, 0xf2880850, 0xfeb80fd0, "vqrshrun%c.s16\t%12-15,22D, %0-3,5Q, #%16-18e"}, + {FPU_NEON_EXT_V1, 0xf2880910, 0xfeb80fd0, "vqshrn%c.%24?us16\t%12-15,22D, %0-3,5Q, #%16-18e"}, + {FPU_NEON_EXT_V1, 0xf2880950, 0xfeb80fd0, "vqrshrn%c.%24?us16\t%12-15,22D, %0-3,5Q, #%16-18e"}, + {FPU_NEON_EXT_V1, 0xf2880a10, 0xfeb80fd0, "vshll%c.%24?us8\t%12-15,22D, %0-3,5Q, #%16-18d"}, + {FPU_NEON_EXT_V1, 0xf2900810, 0xffb00fd0, "vshrn%c.i32\t%12-15,22D, %0-3,5Q, #%16-19e"}, + {FPU_NEON_EXT_V1, 0xf2900850, 0xffb00fd0, "vrshrn%c.i32\t%12-15,22D, %0-3,5Q, #%16-19e"}, + {FPU_NEON_EXT_V1, 0xf2880510, 0xffb80f90, "vshl%c.%24?us8\t%12-15,22R, %0-3,5R, #%16-18d"}, + {FPU_NEON_EXT_V1, 0xf3880410, 0xffb80f90, "vsri%c.8\t%12-15,22R, %0-3,5R, #%16-18e"}, + {FPU_NEON_EXT_V1, 0xf3880510, 0xffb80f90, "vsli%c.8\t%12-15,22R, %0-3,5R, #%16-18d"}, + {FPU_NEON_EXT_V1, 0xf3880610, 0xffb80f90, "vqshlu%c.s8\t%12-15,22R, %0-3,5R, #%16-18d"}, + {FPU_NEON_EXT_V1, 0xf2900810, 0xfeb00fd0, "vqshrun%c.s32\t%12-15,22D, %0-3,5Q, #%16-19e"}, + {FPU_NEON_EXT_V1, 0xf2900850, 0xfeb00fd0, "vqrshrun%c.s32\t%12-15,22D, %0-3,5Q, #%16-19e"}, + {FPU_NEON_EXT_V1, 0xf2900910, 0xfeb00fd0, "vqshrn%c.%24?us32\t%12-15,22D, %0-3,5Q, #%16-19e"}, + {FPU_NEON_EXT_V1, 0xf2900950, 0xfeb00fd0, "vqrshrn%c.%24?us32\t%12-15,22D, %0-3,5Q, #%16-19e"}, + {FPU_NEON_EXT_V1, 0xf2900a10, 0xfeb00fd0, "vshll%c.%24?us16\t%12-15,22D, %0-3,5Q, #%16-19d"}, + {FPU_NEON_EXT_V1, 0xf2880010, 0xfeb80f90, "vshr%c.%24?us8\t%12-15,22R, %0-3,5R, #%16-18e"}, + {FPU_NEON_EXT_V1, 0xf2880110, 0xfeb80f90, "vsra%c.%24?us8\t%12-15,22R, %0-3,5R, #%16-18e"}, + {FPU_NEON_EXT_V1, 0xf2880210, 0xfeb80f90, "vrshr%c.%24?us8\t%12-15,22R, %0-3,5R, #%16-18e"}, + {FPU_NEON_EXT_V1, 0xf2880310, 0xfeb80f90, "vrsra%c.%24?us8\t%12-15,22R, %0-3,5R, #%16-18e"}, + {FPU_NEON_EXT_V1, 0xf2880710, 0xfeb80f90, "vqshl%c.%24?us8\t%12-15,22R, %0-3,5R, #%16-18d"}, + {FPU_NEON_EXT_V1, 0xf2a00810, 0xffa00fd0, "vshrn%c.i64\t%12-15,22D, %0-3,5Q, #%16-20e"}, + {FPU_NEON_EXT_V1, 0xf2a00850, 0xffa00fd0, "vrshrn%c.i64\t%12-15,22D, %0-3,5Q, #%16-20e"}, + {FPU_NEON_EXT_V1, 0xf2900510, 0xffb00f90, "vshl%c.%24?us16\t%12-15,22R, %0-3,5R, #%16-19d"}, + {FPU_NEON_EXT_V1, 0xf3900410, 0xffb00f90, "vsri%c.16\t%12-15,22R, %0-3,5R, #%16-19e"}, + {FPU_NEON_EXT_V1, 0xf3900510, 0xffb00f90, "vsli%c.16\t%12-15,22R, %0-3,5R, #%16-19d"}, + {FPU_NEON_EXT_V1, 0xf3900610, 0xffb00f90, "vqshlu%c.s16\t%12-15,22R, %0-3,5R, #%16-19d"}, + {FPU_NEON_EXT_V1, 0xf2a00a10, 0xfea00fd0, "vshll%c.%24?us32\t%12-15,22D, %0-3,5Q, #%16-20d"}, + {FPU_NEON_EXT_V1, 0xf2900010, 0xfeb00f90, "vshr%c.%24?us16\t%12-15,22R, %0-3,5R, #%16-19e"}, + {FPU_NEON_EXT_V1, 0xf2900110, 0xfeb00f90, "vsra%c.%24?us16\t%12-15,22R, %0-3,5R, #%16-19e"}, + {FPU_NEON_EXT_V1, 0xf2900210, 0xfeb00f90, "vrshr%c.%24?us16\t%12-15,22R, %0-3,5R, #%16-19e"}, + {FPU_NEON_EXT_V1, 0xf2900310, 0xfeb00f90, "vrsra%c.%24?us16\t%12-15,22R, %0-3,5R, #%16-19e"}, + {FPU_NEON_EXT_V1, 0xf2900710, 0xfeb00f90, "vqshl%c.%24?us16\t%12-15,22R, %0-3,5R, #%16-19d"}, + {FPU_NEON_EXT_V1, 0xf2800810, 0xfec00fd0, "vqshrun%c.s64\t%12-15,22D, %0-3,5Q, #%16-20e"}, + {FPU_NEON_EXT_V1, 0xf2800850, 0xfec00fd0, "vqrshrun%c.s64\t%12-15,22D, %0-3,5Q, #%16-20e"}, + {FPU_NEON_EXT_V1, 0xf2800910, 0xfec00fd0, "vqshrn%c.%24?us64\t%12-15,22D, %0-3,5Q, #%16-20e"}, + {FPU_NEON_EXT_V1, 0xf2800950, 0xfec00fd0, "vqrshrn%c.%24?us64\t%12-15,22D, %0-3,5Q, #%16-20e"}, + {FPU_NEON_EXT_V1, 0xf2a00510, 0xffa00f90, "vshl%c.%24?us32\t%12-15,22R, %0-3,5R, #%16-20d"}, + {FPU_NEON_EXT_V1, 0xf3a00410, 0xffa00f90, "vsri%c.32\t%12-15,22R, %0-3,5R, #%16-20e"}, + {FPU_NEON_EXT_V1, 0xf3a00510, 0xffa00f90, "vsli%c.32\t%12-15,22R, %0-3,5R, #%16-20d"}, + {FPU_NEON_EXT_V1, 0xf3a00610, 0xffa00f90, "vqshlu%c.s32\t%12-15,22R, %0-3,5R, #%16-20d"}, + {FPU_NEON_EXT_V1, 0xf2a00010, 0xfea00f90, "vshr%c.%24?us32\t%12-15,22R, %0-3,5R, #%16-20e"}, + {FPU_NEON_EXT_V1, 0xf2a00110, 0xfea00f90, "vsra%c.%24?us32\t%12-15,22R, %0-3,5R, #%16-20e"}, + {FPU_NEON_EXT_V1, 0xf2a00210, 0xfea00f90, "vrshr%c.%24?us32\t%12-15,22R, %0-3,5R, #%16-20e"}, + {FPU_NEON_EXT_V1, 0xf2a00310, 0xfea00f90, "vrsra%c.%24?us32\t%12-15,22R, %0-3,5R, #%16-20e"}, + {FPU_NEON_EXT_V1, 0xf2a00710, 0xfea00f90, "vqshl%c.%24?us32\t%12-15,22R, %0-3,5R, #%16-20d"}, + {FPU_NEON_EXT_V1, 0xf2800590, 0xff800f90, "vshl%c.%24?us64\t%12-15,22R, %0-3,5R, #%16-21d"}, + {FPU_NEON_EXT_V1, 0xf3800490, 0xff800f90, "vsri%c.64\t%12-15,22R, %0-3,5R, #%16-21e"}, + {FPU_NEON_EXT_V1, 0xf3800590, 0xff800f90, "vsli%c.64\t%12-15,22R, %0-3,5R, #%16-21d"}, + {FPU_NEON_EXT_V1, 0xf3800690, 0xff800f90, "vqshlu%c.s64\t%12-15,22R, %0-3,5R, #%16-21d"}, + {FPU_NEON_EXT_V1, 0xf2800090, 0xfe800f90, "vshr%c.%24?us64\t%12-15,22R, %0-3,5R, #%16-21e"}, + {FPU_NEON_EXT_V1, 0xf2800190, 0xfe800f90, "vsra%c.%24?us64\t%12-15,22R, %0-3,5R, #%16-21e"}, + {FPU_NEON_EXT_V1, 0xf2800290, 0xfe800f90, "vrshr%c.%24?us64\t%12-15,22R, %0-3,5R, #%16-21e"}, + {FPU_NEON_EXT_V1, 0xf2800390, 0xfe800f90, "vrsra%c.%24?us64\t%12-15,22R, %0-3,5R, #%16-21e"}, + {FPU_NEON_EXT_V1, 0xf2800790, 0xfe800f90, "vqshl%c.%24?us64\t%12-15,22R, %0-3,5R, #%16-21d"}, + {FPU_NEON_EXT_V1, 0xf2a00e10, 0xfea00e90, "vcvt%c.%24,8?usff32.%24,8?ffus32\t%12-15,22R, %0-3,5R, #%16-20e"}, + + /* Three registers of different lengths */ + {FPU_NEON_EXT_V1, 0xf2800e00, 0xfea00f50, "vmull%c.p%20S0\t%12-15,22Q, %16-19,7D, %0-3,5D"}, + {FPU_NEON_EXT_V1, 0xf2800400, 0xff800f50, "vaddhn%c.i%20-21T2\t%12-15,22D, %16-19,7Q, %0-3,5Q"}, + {FPU_NEON_EXT_V1, 0xf2800600, 0xff800f50, "vsubhn%c.i%20-21T2\t%12-15,22D, %16-19,7Q, %0-3,5Q"}, + {FPU_NEON_EXT_V1, 0xf2800900, 0xff800f50, "vqdmlal%c.s%20-21S6\t%12-15,22Q, %16-19,7D, %0-3,5D"}, + {FPU_NEON_EXT_V1, 0xf2800b00, 0xff800f50, "vqdmlsl%c.s%20-21S6\t%12-15,22Q, %16-19,7D, %0-3,5D"}, + {FPU_NEON_EXT_V1, 0xf2800d00, 0xff800f50, "vqdmull%c.s%20-21S6\t%12-15,22Q, %16-19,7D, %0-3,5D"}, + {FPU_NEON_EXT_V1, 0xf3800400, 0xff800f50, "vraddhn%c.i%20-21T2\t%12-15,22D, %16-19,7Q, %0-3,5Q"}, + {FPU_NEON_EXT_V1, 0xf3800600, 0xff800f50, "vrsubhn%c.i%20-21T2\t%12-15,22D, %16-19,7Q, %0-3,5Q"}, + {FPU_NEON_EXT_V1, 0xf2800000, 0xfe800f50, "vaddl%c.%24?us%20-21S2\t%12-15,22Q, %16-19,7D, %0-3,5D"}, + {FPU_NEON_EXT_V1, 0xf2800100, 0xfe800f50, "vaddw%c.%24?us%20-21S2\t%12-15,22Q, %16-19,7Q, %0-3,5D"}, + {FPU_NEON_EXT_V1, 0xf2800200, 0xfe800f50, "vsubl%c.%24?us%20-21S2\t%12-15,22Q, %16-19,7D, %0-3,5D"}, + {FPU_NEON_EXT_V1, 0xf2800300, 0xfe800f50, "vsubw%c.%24?us%20-21S2\t%12-15,22Q, %16-19,7Q, %0-3,5D"}, + {FPU_NEON_EXT_V1, 0xf2800500, 0xfe800f50, "vabal%c.%24?us%20-21S2\t%12-15,22Q, %16-19,7D, %0-3,5D"}, + {FPU_NEON_EXT_V1, 0xf2800700, 0xfe800f50, "vabdl%c.%24?us%20-21S2\t%12-15,22Q, %16-19,7D, %0-3,5D"}, + {FPU_NEON_EXT_V1, 0xf2800800, 0xfe800f50, "vmlal%c.%24?us%20-21S2\t%12-15,22Q, %16-19,7D, %0-3,5D"}, + {FPU_NEON_EXT_V1, 0xf2800a00, 0xfe800f50, "vmlsl%c.%24?us%20-21S2\t%12-15,22Q, %16-19,7D, %0-3,5D"}, + {FPU_NEON_EXT_V1, 0xf2800c00, 0xfe800f50, "vmull%c.%24?us%20-21S2\t%12-15,22Q, %16-19,7D, %0-3,5D"}, + + /* Two registers and a scalar */ + {FPU_NEON_EXT_V1, 0xf2800040, 0xff800f50, "vmla%c.i%20-21S6\t%12-15,22D, %16-19,7D, %D"}, + {FPU_NEON_EXT_V1, 0xf2800140, 0xff800f50, "vmla%c.f%20-21Sa\t%12-15,22D, %16-19,7D, %D"}, + {FPU_NEON_EXT_V1, 0xf2800340, 0xff800f50, "vqdmlal%c.s%20-21S6\t%12-15,22Q, %16-19,7D, %D"}, + {FPU_NEON_EXT_V1, 0xf2800440, 0xff800f50, "vmls%c.i%20-21S6\t%12-15,22D, %16-19,7D, %D"}, + {FPU_NEON_EXT_V1, 0xf2800540, 0xff800f50, "vmls%c.f%20-21S6\t%12-15,22D, %16-19,7D, %D"}, + {FPU_NEON_EXT_V1, 0xf2800740, 0xff800f50, "vqdmlsl%c.s%20-21S6\t%12-15,22Q, %16-19,7D, %D"}, + {FPU_NEON_EXT_V1, 0xf2800840, 0xff800f50, "vmul%c.i%20-21S6\t%12-15,22D, %16-19,7D, %D"}, + {FPU_NEON_EXT_V1, 0xf2800940, 0xff800f50, "vmul%c.f%20-21Sa\t%12-15,22D, %16-19,7D, %D"}, + {FPU_NEON_EXT_V1, 0xf2800b40, 0xff800f50, "vqdmull%c.s%20-21S6\t%12-15,22Q, %16-19,7D, %D"}, + {FPU_NEON_EXT_V1, 0xf2800c40, 0xff800f50, "vqdmulh%c.s%20-21S6\t%12-15,22D, %16-19,7D, %D"}, + {FPU_NEON_EXT_V1, 0xf2800d40, 0xff800f50, "vqrdmulh%c.s%20-21S6\t%12-15,22D, %16-19,7D, %D"}, + {FPU_NEON_EXT_V1, 0xf3800040, 0xff800f50, "vmla%c.i%20-21S6\t%12-15,22Q, %16-19,7Q, %D"}, + {FPU_NEON_EXT_V1, 0xf3800140, 0xff800f50, "vmla%c.f%20-21Sa\t%12-15,22Q, %16-19,7Q, %D"}, + {FPU_NEON_EXT_V1, 0xf3800440, 0xff800f50, "vmls%c.i%20-21S6\t%12-15,22Q, %16-19,7Q, %D"}, + {FPU_NEON_EXT_V1, 0xf3800540, 0xff800f50, "vmls%c.f%20-21Sa\t%12-15,22Q, %16-19,7Q, %D"}, + {FPU_NEON_EXT_V1, 0xf3800840, 0xff800f50, "vmul%c.i%20-21S6\t%12-15,22Q, %16-19,7Q, %D"}, + {FPU_NEON_EXT_V1, 0xf3800940, 0xff800f50, "vmul%c.f%20-21Sa\t%12-15,22Q, %16-19,7Q, %D"}, + {FPU_NEON_EXT_V1, 0xf3800c40, 0xff800f50, "vqdmulh%c.s%20-21S6\t%12-15,22Q, %16-19,7Q, %D"}, + {FPU_NEON_EXT_V1, 0xf3800d40, 0xff800f50, "vqrdmulh%c.s%20-21S6\t%12-15,22Q, %16-19,7Q, %D"}, + {FPU_NEON_EXT_V1, 0xf2800240, 0xfe800f50, "vmlal%c.%24?us%20-21S6\t%12-15,22Q, %16-19,7D, %D"}, + {FPU_NEON_EXT_V1, 0xf2800640, 0xfe800f50, "vmlsl%c.%24?us%20-21S6\t%12-15,22Q, %16-19,7D, %D"}, + {FPU_NEON_EXT_V1, 0xf2800a40, 0xfe800f50, "vmull%c.%24?us%20-21S6\t%12-15,22Q, %16-19,7D, %D"}, + + /* Element and structure load/store */ + {FPU_NEON_EXT_V1, 0xf4a00fc0, 0xffb00fc0, "vld4%c.32\t%C"}, + {FPU_NEON_EXT_V1, 0xf4a00c00, 0xffb00f00, "vld1%c.%6-7S2\t%C"}, + {FPU_NEON_EXT_V1, 0xf4a00d00, 0xffb00f00, "vld2%c.%6-7S2\t%C"}, + {FPU_NEON_EXT_V1, 0xf4a00e00, 0xffb00f00, "vld3%c.%6-7S2\t%C"}, + {FPU_NEON_EXT_V1, 0xf4a00f00, 0xffb00f00, "vld4%c.%6-7S2\t%C"}, + {FPU_NEON_EXT_V1, 0xf4000200, 0xff900f00, "v%21?ls%21?dt1%c.%6-7S3\t%A"}, + {FPU_NEON_EXT_V1, 0xf4000300, 0xff900f00, "v%21?ls%21?dt2%c.%6-7S2\t%A"}, + {FPU_NEON_EXT_V1, 0xf4000400, 0xff900f00, "v%21?ls%21?dt3%c.%6-7S2\t%A"}, + {FPU_NEON_EXT_V1, 0xf4000500, 0xff900f00, "v%21?ls%21?dt3%c.%6-7S2\t%A"}, + {FPU_NEON_EXT_V1, 0xf4000600, 0xff900f00, "v%21?ls%21?dt1%c.%6-7S3\t%A"}, + {FPU_NEON_EXT_V1, 0xf4000700, 0xff900f00, "v%21?ls%21?dt1%c.%6-7S3\t%A"}, + {FPU_NEON_EXT_V1, 0xf4000800, 0xff900f00, "v%21?ls%21?dt2%c.%6-7S2\t%A"}, + {FPU_NEON_EXT_V1, 0xf4000900, 0xff900f00, "v%21?ls%21?dt2%c.%6-7S2\t%A"}, + {FPU_NEON_EXT_V1, 0xf4000a00, 0xff900f00, "v%21?ls%21?dt1%c.%6-7S3\t%A"}, + {FPU_NEON_EXT_V1, 0xf4000000, 0xff900e00, "v%21?ls%21?dt4%c.%6-7S2\t%A"}, + {FPU_NEON_EXT_V1, 0xf4800000, 0xff900300, "v%21?ls%21?dt1%c.%10-11S2\t%B"}, + {FPU_NEON_EXT_V1, 0xf4800100, 0xff900300, "v%21?ls%21?dt2%c.%10-11S2\t%B"}, + {FPU_NEON_EXT_V1, 0xf4800200, 0xff900300, "v%21?ls%21?dt3%c.%10-11S2\t%B"}, + {FPU_NEON_EXT_V1, 0xf4800300, 0xff900300, "v%21?ls%21?dt4%c.%10-11S2\t%B"}, + + {0,0 ,0, 0} +}; + +/* Opcode tables: ARM, 16-bit Thumb, 32-bit Thumb. All three are partially + ordered: they must be searched linearly from the top to obtain a correct + match. */ + +/* print_insn_arm recognizes the following format control codes: + + %% % + + %a print address for ldr/str instruction + %s print address for ldr/str halfword/signextend instruction + %b print branch destination + %c print condition code (always bits 28-31) + %m print register mask for ldm/stm instruction + %o print operand2 (immediate or register + shift) + %p print 'p' iff bits 12-15 are 15 + %t print 't' iff bit 21 set and bit 24 clear + %B print arm BLX(1) destination + %C print the PSR sub type. + %U print barrier type. + %P print address for pli instruction. + + %r print as an ARM register + %d print the bitfield in decimal + %W print the bitfield plus one in decimal + %x print the bitfield in hex + %X print the bitfield as 1 hex digit without leading "0x" + + %'c print specified char iff bitfield is all ones + %`c print specified char iff bitfield is all zeroes + %?ab... select from array of values in big endian order + + %e print arm SMI operand (bits 0..7,8..19). + %E print the LSB and WIDTH fields of a BFI or BFC instruction. + %V print the 16-bit immediate field of a MOVT or MOVW instruction. */ + +static const struct opcode32 arm_opcodes[] = +{ + /* ARM instructions. */ + {ARM_EXT_V1, 0xe1a00000, 0xffffffff, "nop\t\t\t(mov r0,r0)"}, + {ARM_EXT_V4T | ARM_EXT_V5, 0x012FFF10, 0x0ffffff0, "bx%c\t%0-3r"}, + {ARM_EXT_V2, 0x00000090, 0x0fe000f0, "mul%20's%c\t%16-19r, %0-3r, %8-11r"}, + {ARM_EXT_V2, 0x00200090, 0x0fe000f0, "mla%20's%c\t%16-19r, %0-3r, %8-11r, %12-15r"}, + {ARM_EXT_V2S, 0x01000090, 0x0fb00ff0, "swp%22'b%c\t%12-15r, %0-3r, [%16-19r]"}, + {ARM_EXT_V3M, 0x00800090, 0x0fa000f0, "%22?sumull%20's%c\t%12-15r, %16-19r, %0-3r, %8-11r"}, + {ARM_EXT_V3M, 0x00a00090, 0x0fa000f0, "%22?sumlal%20's%c\t%12-15r, %16-19r, %0-3r, %8-11r"}, + + /* V7 instructions. */ + {ARM_EXT_V7, 0xf450f000, 0xfd70f000, "pli\t%P"}, + {ARM_EXT_V7, 0x0320f0f0, 0x0ffffff0, "dbg%c\t#%0-3d"}, + {ARM_EXT_V7, 0xf57ff050, 0xfffffff0, "dmb\t%U"}, + {ARM_EXT_V7, 0xf57ff040, 0xfffffff0, "dsb\t%U"}, + {ARM_EXT_V7, 0xf57ff060, 0xfffffff0, "isb\t%U"}, + + /* ARM V6T2 instructions. */ + {ARM_EXT_V6T2, 0x07c0001f, 0x0fe0007f, "bfc%c\t%12-15r, %E"}, + {ARM_EXT_V6T2, 0x07c00010, 0x0fe00070, "bfi%c\t%12-15r, %0-3r, %E"}, + {ARM_EXT_V6T2, 0x00600090, 0x0ff000f0, "mls%c\t%16-19r, %0-3r, %8-11r, %12-15r"}, + {ARM_EXT_V6T2, 0x006000b0, 0x0f7000f0, "strht%c\t%12-15r, %s"}, + {ARM_EXT_V6T2, 0x00300090, 0x0f300090, "ldr%6's%5?hbt%c\t%12-15r, %s"}, + {ARM_EXT_V6T2, 0x03000000, 0x0ff00000, "movw%c\t%12-15r, %V"}, + {ARM_EXT_V6T2, 0x03400000, 0x0ff00000, "movt%c\t%12-15r, %V"}, + {ARM_EXT_V6T2, 0x06ff0f30, 0x0fff0ff0, "rbit%c\t%12-15r, %0-3r"}, + {ARM_EXT_V6T2, 0x07a00050, 0x0fa00070, "%22?usbfx%c\t%12-15r, %0-3r, #%7-11d, #%16-20W"}, + + /* ARM V6Z instructions. */ + {ARM_EXT_V6Z, 0x01600070, 0x0ff000f0, "smc%c\t%e"}, + + /* ARM V6K instructions. */ + {ARM_EXT_V6K, 0xf57ff01f, 0xffffffff, "clrex"}, + {ARM_EXT_V6K, 0x01d00f9f, 0x0ff00fff, "ldrexb%c\t%12-15r, [%16-19r]"}, + {ARM_EXT_V6K, 0x01b00f9f, 0x0ff00fff, "ldrexd%c\t%12-15r, [%16-19r]"}, + {ARM_EXT_V6K, 0x01f00f9f, 0x0ff00fff, "ldrexh%c\t%12-15r, [%16-19r]"}, + {ARM_EXT_V6K, 0x01c00f90, 0x0ff00ff0, "strexb%c\t%12-15r, %0-3r, [%16-19r]"}, + {ARM_EXT_V6K, 0x01a00f90, 0x0ff00ff0, "strexd%c\t%12-15r, %0-3r, [%16-19r]"}, + {ARM_EXT_V6K, 0x01e00f90, 0x0ff00ff0, "strexh%c\t%12-15r, %0-3r, [%16-19r]"}, + + /* ARM V6K NOP hints. */ + {ARM_EXT_V6K, 0x0320f001, 0x0fffffff, "yield%c"}, + {ARM_EXT_V6K, 0x0320f002, 0x0fffffff, "wfe%c"}, + {ARM_EXT_V6K, 0x0320f003, 0x0fffffff, "wfi%c"}, + {ARM_EXT_V6K, 0x0320f004, 0x0fffffff, "sev%c"}, + {ARM_EXT_V6K, 0x0320f000, 0x0fffff00, "nop%c\t{%0-7d}"}, + + /* ARM V6 instructions. */ + {ARM_EXT_V6, 0xf1080000, 0xfffffe3f, "cpsie\t%8'a%7'i%6'f"}, + {ARM_EXT_V6, 0xf10a0000, 0xfffffe20, "cpsie\t%8'a%7'i%6'f,#%0-4d"}, + {ARM_EXT_V6, 0xf10C0000, 0xfffffe3f, "cpsid\t%8'a%7'i%6'f"}, + {ARM_EXT_V6, 0xf10e0000, 0xfffffe20, "cpsid\t%8'a%7'i%6'f,#%0-4d"}, + {ARM_EXT_V6, 0xf1000000, 0xfff1fe20, "cps\t#%0-4d"}, + {ARM_EXT_V6, 0x06800010, 0x0ff00ff0, "pkhbt%c\t%12-15r, %16-19r, %0-3r"}, + {ARM_EXT_V6, 0x06800010, 0x0ff00070, "pkhbt%c\t%12-15r, %16-19r, %0-3r, lsl #%7-11d"}, + {ARM_EXT_V6, 0x06800050, 0x0ff00ff0, "pkhtb%c\t%12-15r, %16-19r, %0-3r, asr #32"}, + {ARM_EXT_V6, 0x06800050, 0x0ff00070, "pkhtb%c\t%12-15r, %16-19r, %0-3r, asr #%7-11d"}, + {ARM_EXT_V6, 0x01900f9f, 0x0ff00fff, "ldrex%c\tr%12-15d, [%16-19r]"}, + {ARM_EXT_V6, 0x06200f10, 0x0ff00ff0, "qadd16%c\t%12-15r, %16-19r, %0-3r"}, + {ARM_EXT_V6, 0x06200f90, 0x0ff00ff0, "qadd8%c\t%12-15r, %16-19r, %0-3r"}, + {ARM_EXT_V6, 0x06200f30, 0x0ff00ff0, "qaddsubx%c\t%12-15r, %16-19r, %0-3r"}, + {ARM_EXT_V6, 0x06200f70, 0x0ff00ff0, "qsub16%c\t%12-15r, %16-19r, %0-3r"}, + {ARM_EXT_V6, 0x06200ff0, 0x0ff00ff0, "qsub8%c\t%12-15r, %16-19r, %0-3r"}, + {ARM_EXT_V6, 0x06200f50, 0x0ff00ff0, "qsubaddx%c\t%12-15r, %16-19r, %0-3r"}, + {ARM_EXT_V6, 0x06100f10, 0x0ff00ff0, "sadd16%c\t%12-15r, %16-19r, %0-3r"}, + {ARM_EXT_V6, 0x06100f90, 0x0ff00ff0, "sadd8%c\t%12-15r, %16-19r, %0-3r"}, + {ARM_EXT_V6, 0x06100f30, 0x0ff00ff0, "saddaddx%c\t%12-15r, %16-19r, %0-3r"}, + {ARM_EXT_V6, 0x06300f10, 0x0ff00ff0, "shadd16%c\t%12-15r, %16-19r, %0-3r"}, + {ARM_EXT_V6, 0x06300f90, 0x0ff00ff0, "shadd8%c\t%12-15r, %16-19r, %0-3r"}, + {ARM_EXT_V6, 0x06300f30, 0x0ff00ff0, "shaddsubx%c\t%12-15r, %16-19r, %0-3r"}, + {ARM_EXT_V6, 0x06300f70, 0x0ff00ff0, "shsub16%c\t%12-15r, %16-19r, %0-3r"}, + {ARM_EXT_V6, 0x06300ff0, 0x0ff00ff0, "shsub8%c\t%12-15r, %16-19r, %0-3r"}, + {ARM_EXT_V6, 0x06300f50, 0x0ff00ff0, "shsubaddx%c\t%12-15r, %16-19r, %0-3r"}, + {ARM_EXT_V6, 0x06100f70, 0x0ff00ff0, "ssub16%c\t%12-15r, %16-19r, %0-3r"}, + {ARM_EXT_V6, 0x06100ff0, 0x0ff00ff0, "ssub8%c\t%12-15r, %16-19r, %0-3r"}, + {ARM_EXT_V6, 0x06100f50, 0x0ff00ff0, "ssubaddx%c\t%12-15r, %16-19r, %0-3r"}, + {ARM_EXT_V6, 0x06500f10, 0x0ff00ff0, "uadd16%c\t%12-15r, %16-19r, %0-3r"}, + {ARM_EXT_V6, 0x06500f90, 0x0ff00ff0, "uadd8%c\t%12-15r, %16-19r, %0-3r"}, + {ARM_EXT_V6, 0x06500f30, 0x0ff00ff0, "uaddsubx%c\t%12-15r, %16-19r, %0-3r"}, + {ARM_EXT_V6, 0x06700f10, 0x0ff00ff0, "uhadd16%c\t%12-15r, %16-19r, %0-3r"}, + {ARM_EXT_V6, 0x06700f90, 0x0ff00ff0, "uhadd8%c\t%12-15r, %16-19r, %0-3r"}, + {ARM_EXT_V6, 0x06700f30, 0x0ff00ff0, "uhaddsubx%c\t%12-15r, %16-19r, %0-3r"}, + {ARM_EXT_V6, 0x06700f70, 0x0ff00ff0, "uhsub16%c\t%12-15r, %16-19r, %0-3r"}, + {ARM_EXT_V6, 0x06700ff0, 0x0ff00ff0, "uhsub8%c\t%12-15r, %16-19r, %0-3r"}, + {ARM_EXT_V6, 0x06700f50, 0x0ff00ff0, "uhsubaddx%c\t%12-15r, %16-19r, %0-3r"}, + {ARM_EXT_V6, 0x06600f10, 0x0ff00ff0, "uqadd16%c\t%12-15r, %16-19r, %0-3r"}, + {ARM_EXT_V6, 0x06600f90, 0x0ff00ff0, "uqadd8%c\t%12-15r, %16-19r, %0-3r"}, + {ARM_EXT_V6, 0x06600f30, 0x0ff00ff0, "uqaddsubx%c\t%12-15r, %16-19r, %0-3r"}, + {ARM_EXT_V6, 0x06600f70, 0x0ff00ff0, "uqsub16%c\t%12-15r, %16-19r, %0-3r"}, + {ARM_EXT_V6, 0x06600ff0, 0x0ff00ff0, "uqsub8%c\t%12-15r, %16-19r, %0-3r"}, + {ARM_EXT_V6, 0x06600f50, 0x0ff00ff0, "uqsubaddx%c\t%12-15r, %16-19r, %0-3r"}, + {ARM_EXT_V6, 0x06500f70, 0x0ff00ff0, "usub16%c\t%12-15r, %16-19r, %0-3r"}, + {ARM_EXT_V6, 0x06500ff0, 0x0ff00ff0, "usub8%c\t%12-15r, %16-19r, %0-3r"}, + {ARM_EXT_V6, 0x06500f50, 0x0ff00ff0, "usubaddx%c\t%12-15r, %16-19r, %0-3r"}, + {ARM_EXT_V6, 0x06bf0f30, 0x0fff0ff0, "rev%c\t\%12-15r, %0-3r"}, + {ARM_EXT_V6, 0x06bf0fb0, 0x0fff0ff0, "rev16%c\t\%12-15r, %0-3r"}, + {ARM_EXT_V6, 0x06ff0fb0, 0x0fff0ff0, "revsh%c\t\%12-15r, %0-3r"}, + {ARM_EXT_V6, 0xf8100a00, 0xfe50ffff, "rfe%23?id%24?ba\t\%16-19r%21'!"}, + {ARM_EXT_V6, 0x06bf0070, 0x0fff0ff0, "sxth%c\t%12-15r, %0-3r"}, + {ARM_EXT_V6, 0x06bf0470, 0x0fff0ff0, "sxth%c\t%12-15r, %0-3r, ror #8"}, + {ARM_EXT_V6, 0x06bf0870, 0x0fff0ff0, "sxth%c\t%12-15r, %0-3r, ror #16"}, + {ARM_EXT_V6, 0x06bf0c70, 0x0fff0ff0, "sxth%c\t%12-15r, %0-3r, ror #24"}, + {ARM_EXT_V6, 0x068f0070, 0x0fff0ff0, "sxtb16%c\t%12-15r, %0-3r"}, + {ARM_EXT_V6, 0x068f0470, 0x0fff0ff0, "sxtb16%c\t%12-15r, %0-3r, ror #8"}, + {ARM_EXT_V6, 0x068f0870, 0x0fff0ff0, "sxtb16%c\t%12-15r, %0-3r, ror #16"}, + {ARM_EXT_V6, 0x068f0c70, 0x0fff0ff0, "sxtb16%c\t%12-15r, %0-3r, ror #24"}, + {ARM_EXT_V6, 0x06af0070, 0x0fff0ff0, "sxtb%c\t%12-15r, %0-3r"}, + {ARM_EXT_V6, 0x06af0470, 0x0fff0ff0, "sxtb%c\t%12-15r, %0-3r, ror #8"}, + {ARM_EXT_V6, 0x06af0870, 0x0fff0ff0, "sxtb%c\t%12-15r, %0-3r, ror #16"}, + {ARM_EXT_V6, 0x06af0c70, 0x0fff0ff0, "sxtb%c\t%12-15r, %0-3r, ror #24"}, + {ARM_EXT_V6, 0x06ff0070, 0x0fff0ff0, "uxth%c\t%12-15r, %0-3r"}, + {ARM_EXT_V6, 0x06ff0470, 0x0fff0ff0, "uxth%c\t%12-15r, %0-3r, ror #8"}, + {ARM_EXT_V6, 0x06ff0870, 0x0fff0ff0, "uxth%c\t%12-15r, %0-3r, ror #16"}, + {ARM_EXT_V6, 0x06ff0c70, 0x0fff0ff0, "uxth%c\t%12-15r, %0-3r, ror #24"}, + {ARM_EXT_V6, 0x06cf0070, 0x0fff0ff0, "uxtb16%c\t%12-15r, %0-3r"}, + {ARM_EXT_V6, 0x06cf0470, 0x0fff0ff0, "uxtb16%c\t%12-15r, %0-3r, ror #8"}, + {ARM_EXT_V6, 0x06cf0870, 0x0fff0ff0, "uxtb16%c\t%12-15r, %0-3r, ror #16"}, + {ARM_EXT_V6, 0x06cf0c70, 0x0fff0ff0, "uxtb16%c\t%12-15r, %0-3r, ror #24"}, + {ARM_EXT_V6, 0x06ef0070, 0x0fff0ff0, "uxtb%c\t%12-15r, %0-3r"}, + {ARM_EXT_V6, 0x06ef0470, 0x0fff0ff0, "uxtb%c\t%12-15r, %0-3r, ror #8"}, + {ARM_EXT_V6, 0x06ef0870, 0x0fff0ff0, "uxtb%c\t%12-15r, %0-3r, ror #16"}, + {ARM_EXT_V6, 0x06ef0c70, 0x0fff0ff0, "uxtb%c\t%12-15r, %0-3r, ror #24"}, + {ARM_EXT_V6, 0x06b00070, 0x0ff00ff0, "sxtah%c\t%12-15r, %16-19r, %0-3r"}, + {ARM_EXT_V6, 0x06b00470, 0x0ff00ff0, "sxtah%c\t%12-15r, %16-19r, %0-3r, ror #8"}, + {ARM_EXT_V6, 0x06b00870, 0x0ff00ff0, "sxtah%c\t%12-15r, %16-19r, %0-3r, ror #16"}, + {ARM_EXT_V6, 0x06b00c70, 0x0ff00ff0, "sxtah%c\t%12-15r, %16-19r, %0-3r, ror #24"}, + {ARM_EXT_V6, 0x06800070, 0x0ff00ff0, "sxtab16%c\t%12-15r, %16-19r, %0-3r"}, + {ARM_EXT_V6, 0x06800470, 0x0ff00ff0, "sxtab16%c\t%12-15r, %16-19r, %0-3r, ror #8"}, + {ARM_EXT_V6, 0x06800870, 0x0ff00ff0, "sxtab16%c\t%12-15r, %16-19r, %0-3r, ror #16"}, + {ARM_EXT_V6, 0x06800c70, 0x0ff00ff0, "sxtab16%c\t%12-15r, %16-19r, %0-3r, ror #24"}, + {ARM_EXT_V6, 0x06a00070, 0x0ff00ff0, "sxtab%c\t%12-15r, %16-19r, %0-3r"}, + {ARM_EXT_V6, 0x06a00470, 0x0ff00ff0, "sxtab%c\t%12-15r, %16-19r, %0-3r, ror #8"}, + {ARM_EXT_V6, 0x06a00870, 0x0ff00ff0, "sxtab%c\t%12-15r, %16-19r, %0-3r, ror #16"}, + {ARM_EXT_V6, 0x06a00c70, 0x0ff00ff0, "sxtab%c\t%12-15r, %16-19r, %0-3r, ror #24"}, + {ARM_EXT_V6, 0x06f00070, 0x0ff00ff0, "uxtah%c\t%12-15r, %16-19r, %0-3r"}, + {ARM_EXT_V6, 0x06f00470, 0x0ff00ff0, "uxtah%c\t%12-15r, %16-19r, %0-3r, ror #8"}, + {ARM_EXT_V6, 0x06f00870, 0x0ff00ff0, "uxtah%c\t%12-15r, %16-19r, %0-3r, ror #16"}, + {ARM_EXT_V6, 0x06f00c70, 0x0ff00ff0, "uxtah%c\t%12-15r, %16-19r, %0-3r, ror #24"}, + {ARM_EXT_V6, 0x06c00070, 0x0ff00ff0, "uxtab16%c\t%12-15r, %16-19r, %0-3r"}, + {ARM_EXT_V6, 0x06c00470, 0x0ff00ff0, "uxtab16%c\t%12-15r, %16-19r, %0-3r, ror #8"}, + {ARM_EXT_V6, 0x06c00870, 0x0ff00ff0, "uxtab16%c\t%12-15r, %16-19r, %0-3r, ror #16"}, + {ARM_EXT_V6, 0x06c00c70, 0x0ff00ff0, "uxtab16%c\t%12-15r, %16-19r, %0-3r, ROR #24"}, + {ARM_EXT_V6, 0x06e00070, 0x0ff00ff0, "uxtab%c\t%12-15r, %16-19r, %0-3r"}, + {ARM_EXT_V6, 0x06e00470, 0x0ff00ff0, "uxtab%c\t%12-15r, %16-19r, %0-3r, ror #8"}, + {ARM_EXT_V6, 0x06e00870, 0x0ff00ff0, "uxtab%c\t%12-15r, %16-19r, %0-3r, ror #16"}, + {ARM_EXT_V6, 0x06e00c70, 0x0ff00ff0, "uxtab%c\t%12-15r, %16-19r, %0-3r, ror #24"}, + {ARM_EXT_V6, 0x06800fb0, 0x0ff00ff0, "sel%c\t%12-15r, %16-19r, %0-3r"}, + {ARM_EXT_V6, 0xf1010000, 0xfffffc00, "setend\t%9?ble"}, + {ARM_EXT_V6, 0x0700f010, 0x0ff0f0d0, "smuad%5'x%c\t%16-19r, %0-3r, %8-11r"}, + {ARM_EXT_V6, 0x0700f050, 0x0ff0f0d0, "smusd%5'x%c\t%16-19r, %0-3r, %8-11r"}, + {ARM_EXT_V6, 0x07000010, 0x0ff000d0, "smlad%5'x%c\t%16-19r, %0-3r, %8-11r, %12-15r"}, + {ARM_EXT_V6, 0x07400010, 0x0ff000d0, "smlald%5'x%c\t%12-15r, %16-19r, %0-3r, %8-11r"}, + {ARM_EXT_V6, 0x07000050, 0x0ff000d0, "smlsd%5'x%c\t%16-19r, %0-3r, %8-11r, %12-15r"}, + {ARM_EXT_V6, 0x07400050, 0x0ff000d0, "smlsld%5'x%c\t%12-15r, %16-19r, %0-3r, %8-11r"}, + {ARM_EXT_V6, 0x0750f010, 0x0ff0f0d0, "smmul%5'r%c\t%16-19r, %0-3r, %8-11r"}, + {ARM_EXT_V6, 0x07500010, 0x0ff000d0, "smmla%5'r%c\t%16-19r, %0-3r, %8-11r, %12-15r"}, + {ARM_EXT_V6, 0x075000d0, 0x0ff000d0, "smmls%5'r%c\t%16-19r, %0-3r, %8-11r, %12-15r"}, + {ARM_EXT_V6, 0xf84d0500, 0xfe5fffe0, "srs%23?id%24?ba\t%16-19r%21'!, #%0-4d"}, + {ARM_EXT_V6, 0x06a00010, 0x0fe00ff0, "ssat%c\t%12-15r, #%16-20W, %0-3r"}, + {ARM_EXT_V6, 0x06a00010, 0x0fe00070, "ssat%c\t%12-15r, #%16-20W, %0-3r, lsl #%7-11d"}, + {ARM_EXT_V6, 0x06a00050, 0x0fe00070, "ssat%c\t%12-15r, #%16-20W, %0-3r, asr #%7-11d"}, + {ARM_EXT_V6, 0x06a00f30, 0x0ff00ff0, "ssat16%c\t%12-15r, #%16-19W, %0-3r"}, + {ARM_EXT_V6, 0x01800f90, 0x0ff00ff0, "strex%c\t%12-15r, %0-3r, [%16-19r]"}, + {ARM_EXT_V6, 0x00400090, 0x0ff000f0, "umaal%c\t%12-15r, %16-19r, %0-3r, %8-11r"}, + {ARM_EXT_V6, 0x0780f010, 0x0ff0f0f0, "usad8%c\t%16-19r, %0-3r, %8-11r"}, + {ARM_EXT_V6, 0x07800010, 0x0ff000f0, "usada8%c\t%16-19r, %0-3r, %8-11r, %12-15r"}, + {ARM_EXT_V6, 0x06e00010, 0x0fe00ff0, "usat%c\t%12-15r, #%16-20d, %0-3r"}, + {ARM_EXT_V6, 0x06e00010, 0x0fe00070, "usat%c\t%12-15r, #%16-20d, %0-3r, lsl #%7-11d"}, + {ARM_EXT_V6, 0x06e00050, 0x0fe00070, "usat%c\t%12-15r, #%16-20d, %0-3r, asr #%7-11d"}, + {ARM_EXT_V6, 0x06e00f30, 0x0ff00ff0, "usat16%c\t%12-15r, #%16-19d, %0-3r"}, + + /* V5J instruction. */ + {ARM_EXT_V5J, 0x012fff20, 0x0ffffff0, "bxj%c\t%0-3r"}, + + /* V5 Instructions. */ + {ARM_EXT_V5, 0xe1200070, 0xfff000f0, "bkpt\t0x%16-19X%12-15X%8-11X%0-3X"}, + {ARM_EXT_V5, 0xfa000000, 0xfe000000, "blx\t%B"}, + {ARM_EXT_V5, 0x012fff30, 0x0ffffff0, "blx%c\t%0-3r"}, + {ARM_EXT_V5, 0x016f0f10, 0x0fff0ff0, "clz%c\t%12-15r, %0-3r"}, + + /* V5E "El Segundo" Instructions. */ + {ARM_EXT_V5E, 0x000000d0, 0x0e1000f0, "ldrd%c\t%12-15r, %s"}, + {ARM_EXT_V5E, 0x000000f0, 0x0e1000f0, "strd%c\t%12-15r, %s"}, + {ARM_EXT_V5E, 0xf450f000, 0xfc70f000, "pld\t%a"}, + {ARM_EXT_V5ExP, 0x01000080, 0x0ff000f0, "smlabb%c\t%16-19r, %0-3r, %8-11r, %12-15r"}, + {ARM_EXT_V5ExP, 0x010000a0, 0x0ff000f0, "smlatb%c\t%16-19r, %0-3r, %8-11r, %12-15r"}, + {ARM_EXT_V5ExP, 0x010000c0, 0x0ff000f0, "smlabt%c\t%16-19r, %0-3r, %8-11r, %12-15r"}, + {ARM_EXT_V5ExP, 0x010000e0, 0x0ff000f0, "smlatt%c\t%16-19r, %0-3r, %8-11r, %12-15r"}, + + {ARM_EXT_V5ExP, 0x01200080, 0x0ff000f0, "smlawb%c\t%16-19r, %0-3r, %8-11r, %12-15r"}, + {ARM_EXT_V5ExP, 0x012000c0, 0x0ff000f0, "smlawt%c\t%16-19r, %0-3r, %8-11r, %12-15r"}, + + {ARM_EXT_V5ExP, 0x01400080, 0x0ff000f0, "smlalbb%c\t%12-15r, %16-19r, %0-3r, %8-11r"}, + {ARM_EXT_V5ExP, 0x014000a0, 0x0ff000f0, "smlaltb%c\t%12-15r, %16-19r, %0-3r, %8-11r"}, + {ARM_EXT_V5ExP, 0x014000c0, 0x0ff000f0, "smlalbt%c\t%12-15r, %16-19r, %0-3r, %8-11r"}, + {ARM_EXT_V5ExP, 0x014000e0, 0x0ff000f0, "smlaltt%c\t%12-15r, %16-19r, %0-3r, %8-11r"}, + + {ARM_EXT_V5ExP, 0x01600080, 0x0ff0f0f0, "smulbb%c\t%16-19r, %0-3r, %8-11r"}, + {ARM_EXT_V5ExP, 0x016000a0, 0x0ff0f0f0, "smultb%c\t%16-19r, %0-3r, %8-11r"}, + {ARM_EXT_V5ExP, 0x016000c0, 0x0ff0f0f0, "smulbt%c\t%16-19r, %0-3r, %8-11r"}, + {ARM_EXT_V5ExP, 0x016000e0, 0x0ff0f0f0, "smultt%c\t%16-19r, %0-3r, %8-11r"}, + + {ARM_EXT_V5ExP, 0x012000a0, 0x0ff0f0f0, "smulwb%c\t%16-19r, %0-3r, %8-11r"}, + {ARM_EXT_V5ExP, 0x012000e0, 0x0ff0f0f0, "smulwt%c\t%16-19r, %0-3r, %8-11r"}, + + {ARM_EXT_V5ExP, 0x01000050, 0x0ff00ff0, "qadd%c\t%12-15r, %0-3r, %16-19r"}, + {ARM_EXT_V5ExP, 0x01400050, 0x0ff00ff0, "qdadd%c\t%12-15r, %0-3r, %16-19r"}, + {ARM_EXT_V5ExP, 0x01200050, 0x0ff00ff0, "qsub%c\t%12-15r, %0-3r, %16-19r"}, + {ARM_EXT_V5ExP, 0x01600050, 0x0ff00ff0, "qdsub%c\t%12-15r, %0-3r, %16-19r"}, + + /* ARM Instructions. */ + {ARM_EXT_V1, 0x00000090, 0x0e100090, "str%6's%5?hb%c\t%12-15r, %s"}, + {ARM_EXT_V1, 0x00100090, 0x0e100090, "ldr%6's%5?hb%c\t%12-15r, %s"}, + {ARM_EXT_V1, 0x00000000, 0x0de00000, "and%20's%c\t%12-15r, %16-19r, %o"}, + {ARM_EXT_V1, 0x00200000, 0x0de00000, "eor%20's%c\t%12-15r, %16-19r, %o"}, + {ARM_EXT_V1, 0x00400000, 0x0de00000, "sub%20's%c\t%12-15r, %16-19r, %o"}, + {ARM_EXT_V1, 0x00600000, 0x0de00000, "rsb%20's%c\t%12-15r, %16-19r, %o"}, + {ARM_EXT_V1, 0x00800000, 0x0de00000, "add%20's%c\t%12-15r, %16-19r, %o"}, + {ARM_EXT_V1, 0x00a00000, 0x0de00000, "adc%20's%c\t%12-15r, %16-19r, %o"}, + {ARM_EXT_V1, 0x00c00000, 0x0de00000, "sbc%20's%c\t%12-15r, %16-19r, %o"}, + {ARM_EXT_V1, 0x00e00000, 0x0de00000, "rsc%20's%c\t%12-15r, %16-19r, %o"}, + {ARM_EXT_V3, 0x0120f000, 0x0db0f000, "msr%c\t%22?SCPSR%C, %o"}, + {ARM_EXT_V3, 0x010f0000, 0x0fbf0fff, "mrs%c\t%12-15r, %22?SCPSR"}, + {ARM_EXT_V1, 0x01000000, 0x0de00000, "tst%p%c\t%16-19r, %o"}, + {ARM_EXT_V1, 0x01200000, 0x0de00000, "teq%p%c\t%16-19r, %o"}, + {ARM_EXT_V1, 0x01400000, 0x0de00000, "cmp%p%c\t%16-19r, %o"}, + {ARM_EXT_V1, 0x01600000, 0x0de00000, "cmn%p%c\t%16-19r, %o"}, + {ARM_EXT_V1, 0x01800000, 0x0de00000, "orr%20's%c\t%12-15r, %16-19r, %o"}, + {ARM_EXT_V1, 0x03a00000, 0x0fef0000, "mov%20's%c\t%12-15r, %o"}, + {ARM_EXT_V1, 0x01a00000, 0x0def0ff0, "mov%20's%c\t%12-15r, %0-3r"}, + {ARM_EXT_V1, 0x01a00000, 0x0def0060, "lsl%20's%c\t%12-15r, %q"}, + {ARM_EXT_V1, 0x01a00020, 0x0def0060, "lsr%20's%c\t%12-15r, %q"}, + {ARM_EXT_V1, 0x01a00040, 0x0def0060, "asr%20's%c\t%12-15r, %q"}, + {ARM_EXT_V1, 0x01a00060, 0x0def0ff0, "rrx%20's%c\t%12-15r, %0-3r"}, + {ARM_EXT_V1, 0x01a00060, 0x0def0060, "ror%20's%c\t%12-15r, %q"}, + {ARM_EXT_V1, 0x01c00000, 0x0de00000, "bic%20's%c\t%12-15r, %16-19r, %o"}, + {ARM_EXT_V1, 0x01e00000, 0x0de00000, "mvn%20's%c\t%12-15r, %o"}, + {ARM_EXT_V1, 0x052d0004, 0x0fff0fff, "push%c\t{%12-15r}\t\t; (str%c %12-15r, %a)"}, + {ARM_EXT_V1, 0x04000000, 0x0e100000, "str%22'b%t%c\t%12-15r, %a"}, + {ARM_EXT_V1, 0x06000000, 0x0e100ff0, "str%22'b%t%c\t%12-15r, %a"}, + {ARM_EXT_V1, 0x04000000, 0x0c100010, "str%22'b%t%c\t%12-15r, %a"}, + {ARM_EXT_V1, 0x06000010, 0x0e000010, "undefined"}, + {ARM_EXT_V1, 0x049d0004, 0x0fff0fff, "pop%c\t{%12-15r}\t\t; (ldr%c %12-15r, %a)"}, + {ARM_EXT_V1, 0x04100000, 0x0c100000, "ldr%22'b%t%c\t%12-15r, %a"}, + {ARM_EXT_V1, 0x092d0000, 0x0fff0000, "push%c\t%m"}, + {ARM_EXT_V1, 0x08800000, 0x0ff00000, "stm%c\t%16-19r%21'!, %m%22'^"}, + {ARM_EXT_V1, 0x08000000, 0x0e100000, "stm%23?id%24?ba%c\t%16-19r%21'!, %m%22'^"}, + {ARM_EXT_V1, 0x08bd0000, 0x0fff0000, "pop%c\t%m"}, + {ARM_EXT_V1, 0x08900000, 0x0f900000, "ldm%c\t%16-19r%21'!, %m%22'^"}, + {ARM_EXT_V1, 0x08100000, 0x0e100000, "ldm%23?id%24?ba%c\t%16-19r%21'!, %m%22'^"}, + {ARM_EXT_V1, 0x0a000000, 0x0e000000, "b%24'l%c\t%b"}, + {ARM_EXT_V1, 0x0f000000, 0x0f000000, "svc%c\t%0-23x"}, + + /* The rest. */ + {ARM_EXT_V1, 0x00000000, 0x00000000, "undefined instruction %0-31x"}, + {0, 0x00000000, 0x00000000, 0} +}; + +/* print_insn_thumb16 recognizes the following format control codes: + + %S print Thumb register (bits 3..5 as high number if bit 6 set) + %D print Thumb register (bits 0..2 as high number if bit 7 set) + %I print bitfield as a signed decimal + (top bit of range being the sign bit) + %N print Thumb register mask (with LR) + %O print Thumb register mask (with PC) + %M print Thumb register mask + %b print CZB's 6-bit unsigned branch destination + %s print Thumb right-shift immediate (6..10; 0 == 32). + %c print the condition code + %C print the condition code, or "s" if not conditional + %x print warning if conditional an not at end of IT block" + %X print "\t; unpredictable " if conditional + %I print IT instruction suffix and operands + %r print bitfield as an ARM register + %d print bitfield as a decimal + %H print (bitfield * 2) as a decimal + %W print (bitfield * 4) as a decimal + %a print (bitfield * 4) as a pc-rel offset + decoded symbol + %B print Thumb branch destination (signed displacement) + %c print bitfield as a condition code + %'c print specified char iff bit is one + %?ab print a if bit is one else print b. */ + +static const struct opcode16 thumb_opcodes[] = +{ + /* Thumb instructions. */ + + /* ARM V6K no-argument instructions. */ + {ARM_EXT_V6K, 0xbf00, 0xffff, "nop%c"}, + {ARM_EXT_V6K, 0xbf10, 0xffff, "yield%c"}, + {ARM_EXT_V6K, 0xbf20, 0xffff, "wfe%c"}, + {ARM_EXT_V6K, 0xbf30, 0xffff, "wfi%c"}, + {ARM_EXT_V6K, 0xbf40, 0xffff, "sev%c"}, + {ARM_EXT_V6K, 0xbf00, 0xff0f, "nop%c\t{%4-7d}"}, + + /* ARM V6T2 instructions. */ + {ARM_EXT_V6T2, 0xb900, 0xfd00, "cbnz\t%0-2r, %b%X"}, + {ARM_EXT_V6T2, 0xb100, 0xfd00, "cbz\t%0-2r, %b%X"}, + {ARM_EXT_V6T2, 0xbf00, 0xff00, "it%I%X"}, + + /* ARM V6. */ + {ARM_EXT_V6, 0xb660, 0xfff8, "cpsie\t%2'a%1'i%0'f%X"}, + {ARM_EXT_V6, 0xb670, 0xfff8, "cpsid\t%2'a%1'i%0'f%X"}, + {ARM_EXT_V6, 0x4600, 0xffc0, "mov%c\t%0-2r, %3-5r"}, + {ARM_EXT_V6, 0xba00, 0xffc0, "rev%c\t%0-2r, %3-5r"}, + {ARM_EXT_V6, 0xba40, 0xffc0, "rev16%c\t%0-2r, %3-5r"}, + {ARM_EXT_V6, 0xbac0, 0xffc0, "revsh%c\t%0-2r, %3-5r"}, + {ARM_EXT_V6, 0xb650, 0xfff7, "setend\t%3?ble%X"}, + {ARM_EXT_V6, 0xb200, 0xffc0, "sxth%c\t%0-2r, %3-5r"}, + {ARM_EXT_V6, 0xb240, 0xffc0, "sxtb%c\t%0-2r, %3-5r"}, + {ARM_EXT_V6, 0xb280, 0xffc0, "uxth%c\t%0-2r, %3-5r"}, + {ARM_EXT_V6, 0xb2c0, 0xffc0, "uxtb%c\t%0-2r, %3-5r"}, + + /* ARM V5 ISA extends Thumb. */ + {ARM_EXT_V5T, 0xbe00, 0xff00, "bkpt\t%0-7x"}, /* Is always unconditional. */ + /* This is BLX(2). BLX(1) is a 32-bit instruction. */ + {ARM_EXT_V5T, 0x4780, 0xff87, "blx%c\t%3-6r%x"}, /* note: 4 bit register number. */ + /* ARM V4T ISA (Thumb v1). */ + {ARM_EXT_V4T, 0x46C0, 0xFFFF, "nop%c\t\t\t(mov r8, r8)"}, + /* Format 4. */ + {ARM_EXT_V4T, 0x4000, 0xFFC0, "and%C\t%0-2r, %3-5r"}, + {ARM_EXT_V4T, 0x4040, 0xFFC0, "eor%C\t%0-2r, %3-5r"}, + {ARM_EXT_V4T, 0x4080, 0xFFC0, "lsl%C\t%0-2r, %3-5r"}, + {ARM_EXT_V4T, 0x40C0, 0xFFC0, "lsr%C\t%0-2r, %3-5r"}, + {ARM_EXT_V4T, 0x4100, 0xFFC0, "asr%C\t%0-2r, %3-5r"}, + {ARM_EXT_V4T, 0x4140, 0xFFC0, "adc%C\t%0-2r, %3-5r"}, + {ARM_EXT_V4T, 0x4180, 0xFFC0, "sbc%C\t%0-2r, %3-5r"}, + {ARM_EXT_V4T, 0x41C0, 0xFFC0, "ror%C\t%0-2r, %3-5r"}, + {ARM_EXT_V4T, 0x4200, 0xFFC0, "tst%c\t%0-2r, %3-5r"}, + {ARM_EXT_V4T, 0x4240, 0xFFC0, "neg%C\t%0-2r, %3-5r"}, + {ARM_EXT_V4T, 0x4280, 0xFFC0, "cmp%c\t%0-2r, %3-5r"}, + {ARM_EXT_V4T, 0x42C0, 0xFFC0, "cmn%c\t%0-2r, %3-5r"}, + {ARM_EXT_V4T, 0x4300, 0xFFC0, "orr%C\t%0-2r, %3-5r"}, + {ARM_EXT_V4T, 0x4340, 0xFFC0, "mul%C\t%0-2r, %3-5r"}, + {ARM_EXT_V4T, 0x4380, 0xFFC0, "bic%C\t%0-2r, %3-5r"}, + {ARM_EXT_V4T, 0x43C0, 0xFFC0, "mvn%C\t%0-2r, %3-5r"}, + /* format 13 */ + {ARM_EXT_V4T, 0xB000, 0xFF80, "add%c\tsp, #%0-6W"}, + {ARM_EXT_V4T, 0xB080, 0xFF80, "sub%c\tsp, #%0-6W"}, + /* format 5 */ + {ARM_EXT_V4T, 0x4700, 0xFF80, "bx%c\t%S%x"}, + {ARM_EXT_V4T, 0x4400, 0xFF00, "add%c\t%D, %S"}, + {ARM_EXT_V4T, 0x4500, 0xFF00, "cmp%c\t%D, %S"}, + {ARM_EXT_V4T, 0x4600, 0xFF00, "mov%c\t%D, %S"}, + /* format 14 */ + {ARM_EXT_V4T, 0xB400, 0xFE00, "push%c\t%N"}, + {ARM_EXT_V4T, 0xBC00, 0xFE00, "pop%c\t%O"}, + /* format 2 */ + {ARM_EXT_V4T, 0x1800, 0xFE00, "add%C\t%0-2r, %3-5r, %6-8r"}, + {ARM_EXT_V4T, 0x1A00, 0xFE00, "sub%C\t%0-2r, %3-5r, %6-8r"}, + {ARM_EXT_V4T, 0x1C00, 0xFE00, "add%C\t%0-2r, %3-5r, #%6-8d"}, + {ARM_EXT_V4T, 0x1E00, 0xFE00, "sub%C\t%0-2r, %3-5r, #%6-8d"}, + /* format 8 */ + {ARM_EXT_V4T, 0x5200, 0xFE00, "strh%c\t%0-2r, [%3-5r, %6-8r]"}, + {ARM_EXT_V4T, 0x5A00, 0xFE00, "ldrh%c\t%0-2r, [%3-5r, %6-8r]"}, + {ARM_EXT_V4T, 0x5600, 0xF600, "ldrs%11?hb%c\t%0-2r, [%3-5r, %6-8r]"}, + /* format 7 */ + {ARM_EXT_V4T, 0x5000, 0xFA00, "str%10'b%c\t%0-2r, [%3-5r, %6-8r]"}, + {ARM_EXT_V4T, 0x5800, 0xFA00, "ldr%10'b%c\t%0-2r, [%3-5r, %6-8r]"}, + /* format 1 */ + {ARM_EXT_V4T, 0x0000, 0xF800, "lsl%C\t%0-2r, %3-5r, #%6-10d"}, + {ARM_EXT_V4T, 0x0800, 0xF800, "lsr%C\t%0-2r, %3-5r, %s"}, + {ARM_EXT_V4T, 0x1000, 0xF800, "asr%C\t%0-2r, %3-5r, %s"}, + /* format 3 */ + {ARM_EXT_V4T, 0x2000, 0xF800, "mov%C\t%8-10r, #%0-7d"}, + {ARM_EXT_V4T, 0x2800, 0xF800, "cmp%c\t%8-10r, #%0-7d"}, + {ARM_EXT_V4T, 0x3000, 0xF800, "add%C\t%8-10r, #%0-7d"}, + {ARM_EXT_V4T, 0x3800, 0xF800, "sub%C\t%8-10r, #%0-7d"}, + /* format 6 */ + {ARM_EXT_V4T, 0x4800, 0xF800, "ldr%c\t%8-10r, [pc, #%0-7W]\t(%0-7a)"}, /* TODO: Disassemble PC relative "LDR rD,=" */ + /* format 9 */ + {ARM_EXT_V4T, 0x6000, 0xF800, "str%c\t%0-2r, [%3-5r, #%6-10W]"}, + {ARM_EXT_V4T, 0x6800, 0xF800, "ldr%c\t%0-2r, [%3-5r, #%6-10W]"}, + {ARM_EXT_V4T, 0x7000, 0xF800, "strb%c\t%0-2r, [%3-5r, #%6-10d]"}, + {ARM_EXT_V4T, 0x7800, 0xF800, "ldrb%c\t%0-2r, [%3-5r, #%6-10d]"}, + /* format 10 */ + {ARM_EXT_V4T, 0x8000, 0xF800, "strh%c\t%0-2r, [%3-5r, #%6-10H]"}, + {ARM_EXT_V4T, 0x8800, 0xF800, "ldrh%c\t%0-2r, [%3-5r, #%6-10H]"}, + /* format 11 */ + {ARM_EXT_V4T, 0x9000, 0xF800, "str%c\t%8-10r, [sp, #%0-7W]"}, + {ARM_EXT_V4T, 0x9800, 0xF800, "ldr%c\t%8-10r, [sp, #%0-7W]"}, + /* format 12 */ + {ARM_EXT_V4T, 0xA000, 0xF800, "add%c\t%8-10r, pc, #%0-7W\t(adr %8-10r, %0-7a)"}, + {ARM_EXT_V4T, 0xA800, 0xF800, "add%c\t%8-10r, sp, #%0-7W"}, + /* format 15 */ + {ARM_EXT_V4T, 0xC000, 0xF800, "stmia%c\t%8-10r!, %M"}, + {ARM_EXT_V4T, 0xC800, 0xF800, "ldmia%c\t%8-10r!, %M"}, + /* format 17 */ + {ARM_EXT_V4T, 0xDF00, 0xFF00, "svc%c\t%0-7d"}, + /* format 16 */ + {ARM_EXT_V4T, 0xDE00, 0xFE00, "undefined"}, + {ARM_EXT_V4T, 0xD000, 0xF000, "b%8-11c.n\t%0-7B%X"}, + /* format 18 */ + {ARM_EXT_V4T, 0xE000, 0xF800, "b%c.n\t%0-10B%x"}, + + /* The E800 .. FFFF range is unconditionally redirected to the + 32-bit table, because even in pre-V6T2 ISAs, BL and BLX(1) pairs + are processed via that table. Thus, we can never encounter a + bare "second half of BL/BLX(1)" instruction here. */ + {ARM_EXT_V1, 0x0000, 0x0000, "undefined"}, + {0, 0, 0, 0} +}; + +/* Thumb32 opcodes use the same table structure as the ARM opcodes. + We adopt the convention that hw1 is the high 16 bits of .value and + .mask, hw2 the low 16 bits. + + print_insn_thumb32 recognizes the following format control codes: + + %% % + + %I print a 12-bit immediate from hw1[10],hw2[14:12,7:0] + %M print a modified 12-bit immediate (same location) + %J print a 16-bit immediate from hw1[3:0,10],hw2[14:12,7:0] + %K print a 16-bit immediate from hw2[3:0],hw1[3:0],hw2[11:4] + %S print a possibly-shifted Rm + + %a print the address of a plain load/store + %w print the width and signedness of a core load/store + %m print register mask for ldm/stm + + %E print the lsb and width fields of a bfc/bfi instruction + %F print the lsb and width fields of a sbfx/ubfx instruction + %b print a conditional branch offset + %B print an unconditional branch offset + %s print the shift field of an SSAT instruction + %R print the rotation field of an SXT instruction + %U print barrier type. + %P print address for pli instruction. + %c print the condition code + %x print warning if conditional an not at end of IT block" + %X print "\t; unpredictable " if conditional + + %d print bitfield in decimal + %W print bitfield*4 in decimal + %r print bitfield as an ARM register + %c print bitfield as a condition code + + %'c print specified char iff bitfield is all ones + %`c print specified char iff bitfield is all zeroes + %?ab... select from array of values in big endian order + + With one exception at the bottom (done because BL and BLX(1) need + to come dead last), this table was machine-sorted first in + decreasing order of number of bits set in the mask, then in + increasing numeric order of mask, then in increasing numeric order + of opcode. This order is not the clearest for a human reader, but + is guaranteed never to catch a special-case bit pattern with a more + general mask, which is important, because this instruction encoding + makes heavy use of special-case bit patterns. */ +static const struct opcode32 thumb32_opcodes[] = +{ + /* V7 instructions. */ + {ARM_EXT_V7, 0xf910f000, 0xff70f000, "pli%c\t%a"}, + {ARM_EXT_V7, 0xf3af80f0, 0xfffffff0, "dbg%c\t#%0-3d"}, + {ARM_EXT_V7, 0xf3bf8f50, 0xfffffff0, "dmb%c\t%U"}, + {ARM_EXT_V7, 0xf3bf8f40, 0xfffffff0, "dsb%c\t%U"}, + {ARM_EXT_V7, 0xf3bf8f60, 0xfffffff0, "isb%c\t%U"}, + {ARM_EXT_DIV, 0xfb90f0f0, 0xfff0f0f0, "sdiv%c\t%8-11r, %16-19r, %0-3r"}, + {ARM_EXT_DIV, 0xfbb0f0f0, 0xfff0f0f0, "udiv%c\t%8-11r, %16-19r, %0-3r"}, + + /* Instructions defined in the basic V6T2 set. */ + {ARM_EXT_V6T2, 0xf3af8000, 0xffffffff, "nop%c.w"}, + {ARM_EXT_V6T2, 0xf3af8001, 0xffffffff, "yield%c.w"}, + {ARM_EXT_V6T2, 0xf3af8002, 0xffffffff, "wfe%c.w"}, + {ARM_EXT_V6T2, 0xf3af8003, 0xffffffff, "wfi%c.w"}, + {ARM_EXT_V6T2, 0xf3af9004, 0xffffffff, "sev%c.w"}, + {ARM_EXT_V6T2, 0xf3af8000, 0xffffff00, "nop%c.w\t{%0-7d}"}, + + {ARM_EXT_V6T2, 0xf3bf8f2f, 0xffffffff, "clrex%c"}, + {ARM_EXT_V6T2, 0xf3af8400, 0xffffff1f, "cpsie.w\t%7'a%6'i%5'f%X"}, + {ARM_EXT_V6T2, 0xf3af8600, 0xffffff1f, "cpsid.w\t%7'a%6'i%5'f%X"}, + {ARM_EXT_V6T2, 0xf3c08f00, 0xfff0ffff, "bxj%c\t%16-19r%x"}, + {ARM_EXT_V6T2, 0xe810c000, 0xffd0ffff, "rfedb%c\t%16-19r%21'!"}, + {ARM_EXT_V6T2, 0xe990c000, 0xffd0ffff, "rfeia%c\t%16-19r%21'!"}, + {ARM_EXT_V6T2, 0xf3ef8000, 0xffeff000, "mrs%c\t%8-11r, %D"}, + {ARM_EXT_V6T2, 0xf3af8100, 0xffffffe0, "cps\t#%0-4d%X"}, + {ARM_EXT_V6T2, 0xe8d0f000, 0xfff0fff0, "tbb%c\t[%16-19r, %0-3r]%x"}, + {ARM_EXT_V6T2, 0xe8d0f010, 0xfff0fff0, "tbh%c\t[%16-19r, %0-3r, lsl #1]%x"}, + {ARM_EXT_V6T2, 0xf3af8500, 0xffffff00, "cpsie\t%7'a%6'i%5'f, #%0-4d%X"}, + {ARM_EXT_V6T2, 0xf3af8700, 0xffffff00, "cpsid\t%7'a%6'i%5'f, #%0-4d%X"}, + {ARM_EXT_V6T2, 0xf3de8f00, 0xffffff00, "subs%c\tpc, lr, #%0-7d"}, + {ARM_EXT_V6T2, 0xf3808000, 0xffe0f000, "msr%c\t%C, %16-19r"}, + {ARM_EXT_V6T2, 0xe8500f00, 0xfff00fff, "ldrex%c\t%12-15r, [%16-19r]"}, + {ARM_EXT_V6T2, 0xe8d00f4f, 0xfff00fef, "ldrex%4?hb%c\t%12-15r, [%16-19r]"}, + {ARM_EXT_V6T2, 0xe800c000, 0xffd0ffe0, "srsdb%c\t%16-19r%21'!, #%0-4d"}, + {ARM_EXT_V6T2, 0xe980c000, 0xffd0ffe0, "srsia%c\t%16-19r%21'!, #%0-4d"}, + {ARM_EXT_V6T2, 0xfa0ff080, 0xfffff0c0, "sxth%c.w\t%8-11r, %0-3r%R"}, + {ARM_EXT_V6T2, 0xfa1ff080, 0xfffff0c0, "uxth%c.w\t%8-11r, %0-3r%R"}, + {ARM_EXT_V6T2, 0xfa2ff080, 0xfffff0c0, "sxtb16%c\t%8-11r, %0-3r%R"}, + {ARM_EXT_V6T2, 0xfa3ff080, 0xfffff0c0, "uxtb16%c\t%8-11r, %0-3r%R"}, + {ARM_EXT_V6T2, 0xfa4ff080, 0xfffff0c0, "sxtb%c.w\t%8-11r, %0-3r%R"}, + {ARM_EXT_V6T2, 0xfa5ff080, 0xfffff0c0, "uxtb%c.w\t%8-11r, %0-3r%R"}, + {ARM_EXT_V6T2, 0xe8400000, 0xfff000ff, "strex%c\t%8-11r, %12-15r, [%16-19r]"}, + {ARM_EXT_V6T2, 0xe8d0007f, 0xfff000ff, "ldrexd%c\t%12-15r, %8-11r, [%16-19r]"}, + {ARM_EXT_V6T2, 0xfa80f000, 0xfff0f0f0, "sadd8%c\t%8-11r, %16-19r, %0-3r"}, + {ARM_EXT_V6T2, 0xfa80f010, 0xfff0f0f0, "qadd8%c\t%8-11r, %16-19r, %0-3r"}, + {ARM_EXT_V6T2, 0xfa80f020, 0xfff0f0f0, "shadd8%c\t%8-11r, %16-19r, %0-3r"}, + {ARM_EXT_V6T2, 0xfa80f040, 0xfff0f0f0, "uadd8%c\t%8-11r, %16-19r, %0-3r"}, + {ARM_EXT_V6T2, 0xfa80f050, 0xfff0f0f0, "uqadd8%c\t%8-11r, %16-19r, %0-3r"}, + {ARM_EXT_V6T2, 0xfa80f060, 0xfff0f0f0, "uhadd8%c\t%8-11r, %16-19r, %0-3r"}, + {ARM_EXT_V6T2, 0xfa80f080, 0xfff0f0f0, "qadd%c\t%8-11r, %0-3r, %16-19r"}, + {ARM_EXT_V6T2, 0xfa80f090, 0xfff0f0f0, "qdadd%c\t%8-11r, %0-3r, %16-19r"}, + {ARM_EXT_V6T2, 0xfa80f0a0, 0xfff0f0f0, "qsub%c\t%8-11r, %0-3r, %16-19r"}, + {ARM_EXT_V6T2, 0xfa80f0b0, 0xfff0f0f0, "qdsub%c\t%8-11r, %0-3r, %16-19r"}, + {ARM_EXT_V6T2, 0xfa90f000, 0xfff0f0f0, "sadd16%c\t%8-11r, %16-19r, %0-3r"}, + {ARM_EXT_V6T2, 0xfa90f010, 0xfff0f0f0, "qadd16%c\t%8-11r, %16-19r, %0-3r"}, + {ARM_EXT_V6T2, 0xfa90f020, 0xfff0f0f0, "shadd16%c\t%8-11r, %16-19r, %0-3r"}, + {ARM_EXT_V6T2, 0xfa90f040, 0xfff0f0f0, "uadd16%c\t%8-11r, %16-19r, %0-3r"}, + {ARM_EXT_V6T2, 0xfa90f050, 0xfff0f0f0, "uqadd16%c\t%8-11r, %16-19r, %0-3r"}, + {ARM_EXT_V6T2, 0xfa90f060, 0xfff0f0f0, "uhadd16%c\t%8-11r, %16-19r, %0-3r"}, + {ARM_EXT_V6T2, 0xfa90f080, 0xfff0f0f0, "rev%c.w\t%8-11r, %16-19r"}, + {ARM_EXT_V6T2, 0xfa90f090, 0xfff0f0f0, "rev16%c.w\t%8-11r, %16-19r"}, + {ARM_EXT_V6T2, 0xfa90f0a0, 0xfff0f0f0, "rbit%c\t%8-11r, %16-19r"}, + {ARM_EXT_V6T2, 0xfa90f0b0, 0xfff0f0f0, "revsh%c.w\t%8-11r, %16-19r"}, + {ARM_EXT_V6T2, 0xfaa0f000, 0xfff0f0f0, "saddsubx%c\t%8-11r, %16-19r, %0-3r"}, + {ARM_EXT_V6T2, 0xfaa0f010, 0xfff0f0f0, "qaddsubx%c\t%8-11r, %16-19r, %0-3r"}, + {ARM_EXT_V6T2, 0xfaa0f020, 0xfff0f0f0, "shaddsubx%c\t%8-11r, %16-19r, %0-3r"}, + {ARM_EXT_V6T2, 0xfaa0f040, 0xfff0f0f0, "uaddsubx%c\t%8-11r, %16-19r, %0-3r"}, + {ARM_EXT_V6T2, 0xfaa0f050, 0xfff0f0f0, "uqaddsubx%c\t%8-11r, %16-19r, %0-3r"}, + {ARM_EXT_V6T2, 0xfaa0f060, 0xfff0f0f0, "uhaddsubx%c\t%8-11r, %16-19r, %0-3r"}, + {ARM_EXT_V6T2, 0xfaa0f080, 0xfff0f0f0, "sel%c\t%8-11r, %16-19r, %0-3r"}, + {ARM_EXT_V6T2, 0xfab0f080, 0xfff0f0f0, "clz%c\t%8-11r, %16-19r"}, + {ARM_EXT_V6T2, 0xfac0f000, 0xfff0f0f0, "ssub8%c\t%8-11r, %16-19r, %0-3r"}, + {ARM_EXT_V6T2, 0xfac0f010, 0xfff0f0f0, "qsub8%c\t%8-11r, %16-19r, %0-3r"}, + {ARM_EXT_V6T2, 0xfac0f020, 0xfff0f0f0, "shsub8%c\t%8-11r, %16-19r, %0-3r"}, + {ARM_EXT_V6T2, 0xfac0f040, 0xfff0f0f0, "usub8%c\t%8-11r, %16-19r, %0-3r"}, + {ARM_EXT_V6T2, 0xfac0f050, 0xfff0f0f0, "uqsub8%c\t%8-11r, %16-19r, %0-3r"}, + {ARM_EXT_V6T2, 0xfac0f060, 0xfff0f0f0, "uhsub8%c\t%8-11r, %16-19r, %0-3r"}, + {ARM_EXT_V6T2, 0xfad0f000, 0xfff0f0f0, "ssub16%c\t%8-11r, %16-19r, %0-3r"}, + {ARM_EXT_V6T2, 0xfad0f010, 0xfff0f0f0, "qsub16%c\t%8-11r, %16-19r, %0-3r"}, + {ARM_EXT_V6T2, 0xfad0f020, 0xfff0f0f0, "shsub16%c\t%8-11r, %16-19r, %0-3r"}, + {ARM_EXT_V6T2, 0xfad0f040, 0xfff0f0f0, "usub16%c\t%8-11r, %16-19r, %0-3r"}, + {ARM_EXT_V6T2, 0xfad0f050, 0xfff0f0f0, "uqsub16%c\t%8-11r, %16-19r, %0-3r"}, + {ARM_EXT_V6T2, 0xfad0f060, 0xfff0f0f0, "uhsub16%c\t%8-11r, %16-19r, %0-3r"}, + {ARM_EXT_V6T2, 0xfae0f000, 0xfff0f0f0, "ssubaddx%c\t%8-11r, %16-19r, %0-3r"}, + {ARM_EXT_V6T2, 0xfae0f010, 0xfff0f0f0, "qsubaddx%c\t%8-11r, %16-19r, %0-3r"}, + {ARM_EXT_V6T2, 0xfae0f020, 0xfff0f0f0, "shsubaddx%c\t%8-11r, %16-19r, %0-3r"}, + {ARM_EXT_V6T2, 0xfae0f040, 0xfff0f0f0, "usubaddx%c\t%8-11r, %16-19r, %0-3r"}, + {ARM_EXT_V6T2, 0xfae0f050, 0xfff0f0f0, "uqsubaddx%c\t%8-11r, %16-19r, %0-3r"}, + {ARM_EXT_V6T2, 0xfae0f060, 0xfff0f0f0, "uhsubaddx%c\t%8-11r, %16-19r, %0-3r"}, + {ARM_EXT_V6T2, 0xfb00f000, 0xfff0f0f0, "mul%c.w\t%8-11r, %16-19r, %0-3r"}, + {ARM_EXT_V6T2, 0xfb70f000, 0xfff0f0f0, "usad8%c\t%8-11r, %16-19r, %0-3r"}, + {ARM_EXT_V6T2, 0xfa00f000, 0xffe0f0f0, "lsl%20's%c.w\t%8-11r, %16-19r, %0-3r"}, + {ARM_EXT_V6T2, 0xfa20f000, 0xffe0f0f0, "lsr%20's%c.w\t%8-11r, %16-19r, %0-3r"}, + {ARM_EXT_V6T2, 0xfa40f000, 0xffe0f0f0, "asr%20's%c.w\t%8-11r, %16-19r, %0-3r"}, + {ARM_EXT_V6T2, 0xfa60f000, 0xffe0f0f0, "ror%20's%c.w\t%8-11r, %16-19r, %0-3r"}, + {ARM_EXT_V6T2, 0xe8c00f40, 0xfff00fe0, "strex%4?hb%c\t%0-3r, %12-15r, [%16-19r]"}, + {ARM_EXT_V6T2, 0xf3200000, 0xfff0f0e0, "ssat16%c\t%8-11r, #%0-4d, %16-19r"}, + {ARM_EXT_V6T2, 0xf3a00000, 0xfff0f0e0, "usat16%c\t%8-11r, #%0-4d, %16-19r"}, + {ARM_EXT_V6T2, 0xfb20f000, 0xfff0f0e0, "smuad%4'x%c\t%8-11r, %16-19r, %0-3r"}, + {ARM_EXT_V6T2, 0xfb30f000, 0xfff0f0e0, "smulw%4?tb%c\t%8-11r, %16-19r, %0-3r"}, + {ARM_EXT_V6T2, 0xfb40f000, 0xfff0f0e0, "smusd%4'x%c\t%8-11r, %16-19r, %0-3r"}, + {ARM_EXT_V6T2, 0xfb50f000, 0xfff0f0e0, "smmul%4'r%c\t%8-11r, %16-19r, %0-3r"}, + {ARM_EXT_V6T2, 0xfa00f080, 0xfff0f0c0, "sxtah%c\t%8-11r, %16-19r, %0-3r%R"}, + {ARM_EXT_V6T2, 0xfa10f080, 0xfff0f0c0, "uxtah%c\t%8-11r, %16-19r, %0-3r%R"}, + {ARM_EXT_V6T2, 0xfa20f080, 0xfff0f0c0, "sxtab16%c\t%8-11r, %16-19r, %0-3r%R"}, + {ARM_EXT_V6T2, 0xfa30f080, 0xfff0f0c0, "uxtab16%c\t%8-11r, %16-19r, %0-3r%R"}, + {ARM_EXT_V6T2, 0xfa40f080, 0xfff0f0c0, "sxtab%c\t%8-11r, %16-19r, %0-3r%R"}, + {ARM_EXT_V6T2, 0xfa50f080, 0xfff0f0c0, "uxtab%c\t%8-11r, %16-19r, %0-3r%R"}, + {ARM_EXT_V6T2, 0xfb10f000, 0xfff0f0c0, "smul%5?tb%4?tb%c\t%8-11r, %16-19r, %0-3r"}, + {ARM_EXT_V6T2, 0xf36f0000, 0xffff8020, "bfc%c\t%8-11r, %E"}, + {ARM_EXT_V6T2, 0xea100f00, 0xfff08f00, "tst%c.w\t%16-19r, %S"}, + {ARM_EXT_V6T2, 0xea900f00, 0xfff08f00, "teq%c\t%16-19r, %S"}, + {ARM_EXT_V6T2, 0xeb100f00, 0xfff08f00, "cmn%c.w\t%16-19r, %S"}, + {ARM_EXT_V6T2, 0xebb00f00, 0xfff08f00, "cmp%c.w\t%16-19r, %S"}, + {ARM_EXT_V6T2, 0xf0100f00, 0xfbf08f00, "tst%c.w\t%16-19r, %M"}, + {ARM_EXT_V6T2, 0xf0900f00, 0xfbf08f00, "teq%c\t%16-19r, %M"}, + {ARM_EXT_V6T2, 0xf1100f00, 0xfbf08f00, "cmn%c.w\t%16-19r, %M"}, + {ARM_EXT_V6T2, 0xf1b00f00, 0xfbf08f00, "cmp%c.w\t%16-19r, %M"}, + {ARM_EXT_V6T2, 0xea4f0000, 0xffef8000, "mov%20's%c.w\t%8-11r, %S"}, + {ARM_EXT_V6T2, 0xea6f0000, 0xffef8000, "mvn%20's%c.w\t%8-11r, %S"}, + {ARM_EXT_V6T2, 0xe8c00070, 0xfff000f0, "strexd%c\t%0-3r, %12-15r, %8-11r, [%16-19r]"}, + {ARM_EXT_V6T2, 0xfb000000, 0xfff000f0, "mla%c\t%8-11r, %16-19r, %0-3r, %12-15r"}, + {ARM_EXT_V6T2, 0xfb000010, 0xfff000f0, "mls%c\t%8-11r, %16-19r, %0-3r, %12-15r"}, + {ARM_EXT_V6T2, 0xfb700000, 0xfff000f0, "usada8%c\t%8-11r, %16-19r, %0-3r, %12-15r"}, + {ARM_EXT_V6T2, 0xfb800000, 0xfff000f0, "smull%c\t%12-15r, %8-11r, %16-19r, %0-3r"}, + {ARM_EXT_V6T2, 0xfba00000, 0xfff000f0, "umull%c\t%12-15r, %8-11r, %16-19r, %0-3r"}, + {ARM_EXT_V6T2, 0xfbc00000, 0xfff000f0, "smlal%c\t%12-15r, %8-11r, %16-19r, %0-3r"}, + {ARM_EXT_V6T2, 0xfbe00000, 0xfff000f0, "umlal%c\t%12-15r, %8-11r, %16-19r, %0-3r"}, + {ARM_EXT_V6T2, 0xfbe00060, 0xfff000f0, "umaal%c\t%12-15r, %8-11r, %16-19r, %0-3r"}, + {ARM_EXT_V6T2, 0xe8500f00, 0xfff00f00, "ldrex%c\t%12-15r, [%16-19r, #%0-7W]"}, + {ARM_EXT_V6T2, 0xf7f08000, 0xfff0f000, "smc%c\t%K"}, + {ARM_EXT_V6T2, 0xf04f0000, 0xfbef8000, "mov%20's%c.w\t%8-11r, %M"}, + {ARM_EXT_V6T2, 0xf06f0000, 0xfbef8000, "mvn%20's%c.w\t%8-11r, %M"}, + {ARM_EXT_V6T2, 0xf810f000, 0xff70f000, "pld%c\t%a"}, + {ARM_EXT_V6T2, 0xfb200000, 0xfff000e0, "smlad%4'x%c\t%8-11r, %16-19r, %0-3r, %12-15r"}, + {ARM_EXT_V6T2, 0xfb300000, 0xfff000e0, "smlaw%4?tb%c\t%8-11r, %16-19r, %0-3r, %12-15r"}, + {ARM_EXT_V6T2, 0xfb400000, 0xfff000e0, "smlsd%4'x%c\t%8-11r, %16-19r, %0-3r, %12-15r"}, + {ARM_EXT_V6T2, 0xfb500000, 0xfff000e0, "smmla%4'r%c\t%8-11r, %16-19r, %0-3r, %12-15r"}, + {ARM_EXT_V6T2, 0xfb600000, 0xfff000e0, "smmls%4'r%c\t%8-11r, %16-19r, %0-3r, %12-15r"}, + {ARM_EXT_V6T2, 0xfbc000c0, 0xfff000e0, "smlald%4'x%c\t%12-15r, %8-11r, %16-19r, %0-3r"}, + {ARM_EXT_V6T2, 0xfbd000c0, 0xfff000e0, "smlsld%4'x%c\t%12-15r, %8-11r, %16-19r, %0-3r"}, + {ARM_EXT_V6T2, 0xeac00000, 0xfff08030, "pkhbt%c\t%8-11r, %16-19r, %S"}, + {ARM_EXT_V6T2, 0xeac00020, 0xfff08030, "pkhtb%c\t%8-11r, %16-19r, %S"}, + {ARM_EXT_V6T2, 0xf3400000, 0xfff08020, "sbfx%c\t%8-11r, %16-19r, %F"}, + {ARM_EXT_V6T2, 0xf3c00000, 0xfff08020, "ubfx%c\t%8-11r, %16-19r, %F"}, + {ARM_EXT_V6T2, 0xf8000e00, 0xff900f00, "str%wt%c\t%12-15r, %a"}, + {ARM_EXT_V6T2, 0xfb100000, 0xfff000c0, "smla%5?tb%4?tb%c\t%8-11r, %16-19r, %0-3r, %12-15r"}, + {ARM_EXT_V6T2, 0xfbc00080, 0xfff000c0, "smlal%5?tb%4?tb%c\t%12-15r, %8-11r, %16-19r, %0-3r"}, + {ARM_EXT_V6T2, 0xf3600000, 0xfff08020, "bfi%c\t%8-11r, %16-19r, %E"}, + {ARM_EXT_V6T2, 0xf8100e00, 0xfe900f00, "ldr%wt%c\t%12-15r, %a"}, + {ARM_EXT_V6T2, 0xf3000000, 0xffd08020, "ssat%c\t%8-11r, #%0-4d, %16-19r%s"}, + {ARM_EXT_V6T2, 0xf3800000, 0xffd08020, "usat%c\t%8-11r, #%0-4d, %16-19r%s"}, + {ARM_EXT_V6T2, 0xf2000000, 0xfbf08000, "addw%c\t%8-11r, %16-19r, %I"}, + {ARM_EXT_V6T2, 0xf2400000, 0xfbf08000, "movw%c\t%8-11r, %J"}, + {ARM_EXT_V6T2, 0xf2a00000, 0xfbf08000, "subw%c\t%8-11r, %16-19r, %I"}, + {ARM_EXT_V6T2, 0xf2c00000, 0xfbf08000, "movt%c\t%8-11r, %J"}, + {ARM_EXT_V6T2, 0xea000000, 0xffe08000, "and%20's%c.w\t%8-11r, %16-19r, %S"}, + {ARM_EXT_V6T2, 0xea200000, 0xffe08000, "bic%20's%c.w\t%8-11r, %16-19r, %S"}, + {ARM_EXT_V6T2, 0xea400000, 0xffe08000, "orr%20's%c.w\t%8-11r, %16-19r, %S"}, + {ARM_EXT_V6T2, 0xea600000, 0xffe08000, "orn%20's%c\t%8-11r, %16-19r, %S"}, + {ARM_EXT_V6T2, 0xea800000, 0xffe08000, "eor%20's%c.w\t%8-11r, %16-19r, %S"}, + {ARM_EXT_V6T2, 0xeb000000, 0xffe08000, "add%20's%c.w\t%8-11r, %16-19r, %S"}, + {ARM_EXT_V6T2, 0xeb400000, 0xffe08000, "adc%20's%c.w\t%8-11r, %16-19r, %S"}, + {ARM_EXT_V6T2, 0xeb600000, 0xffe08000, "sbc%20's%c.w\t%8-11r, %16-19r, %S"}, + {ARM_EXT_V6T2, 0xeba00000, 0xffe08000, "sub%20's%c.w\t%8-11r, %16-19r, %S"}, + {ARM_EXT_V6T2, 0xebc00000, 0xffe08000, "rsb%20's%c\t%8-11r, %16-19r, %S"}, + {ARM_EXT_V6T2, 0xe8400000, 0xfff00000, "strex%c\t%8-11r, %12-15r, [%16-19r, #%0-7W]"}, + {ARM_EXT_V6T2, 0xf0000000, 0xfbe08000, "and%20's%c.w\t%8-11r, %16-19r, %M"}, + {ARM_EXT_V6T2, 0xf0200000, 0xfbe08000, "bic%20's%c.w\t%8-11r, %16-19r, %M"}, + {ARM_EXT_V6T2, 0xf0400000, 0xfbe08000, "orr%20's%c.w\t%8-11r, %16-19r, %M"}, + {ARM_EXT_V6T2, 0xf0600000, 0xfbe08000, "orn%20's%c\t%8-11r, %16-19r, %M"}, + {ARM_EXT_V6T2, 0xf0800000, 0xfbe08000, "eor%20's%c.w\t%8-11r, %16-19r, %M"}, + {ARM_EXT_V6T2, 0xf1000000, 0xfbe08000, "add%20's%c.w\t%8-11r, %16-19r, %M"}, + {ARM_EXT_V6T2, 0xf1400000, 0xfbe08000, "adc%20's%c.w\t%8-11r, %16-19r, %M"}, + {ARM_EXT_V6T2, 0xf1600000, 0xfbe08000, "sbc%20's%c.w\t%8-11r, %16-19r, %M"}, + {ARM_EXT_V6T2, 0xf1a00000, 0xfbe08000, "sub%20's%c.w\t%8-11r, %16-19r, %M"}, + {ARM_EXT_V6T2, 0xf1c00000, 0xfbe08000, "rsb%20's%c\t%8-11r, %16-19r, %M"}, + {ARM_EXT_V6T2, 0xe8800000, 0xffd00000, "stmia%c.w\t%16-19r%21'!, %m"}, + {ARM_EXT_V6T2, 0xe8900000, 0xffd00000, "ldmia%c.w\t%16-19r%21'!, %m"}, + {ARM_EXT_V6T2, 0xe9000000, 0xffd00000, "stmdb%c\t%16-19r%21'!, %m"}, + {ARM_EXT_V6T2, 0xe9100000, 0xffd00000, "ldmdb%c\t%16-19r%21'!, %m"}, + {ARM_EXT_V6T2, 0xe9c00000, 0xffd000ff, "strd%c\t%12-15r, %8-11r, [%16-19r]"}, + {ARM_EXT_V6T2, 0xe9d00000, 0xffd000ff, "ldrd%c\t%12-15r, %8-11r, [%16-19r]"}, + {ARM_EXT_V6T2, 0xe9400000, 0xff500000, "strd%c\t%12-15r, %8-11r, [%16-19r, #%23`-%0-7W]%21'!"}, + {ARM_EXT_V6T2, 0xe9500000, 0xff500000, "ldrd%c\t%12-15r, %8-11r, [%16-19r, #%23`-%0-7W]%21'!"}, + {ARM_EXT_V6T2, 0xe8600000, 0xff700000, "strd%c\t%12-15r, %8-11r, [%16-19r], #%23`-%0-7W"}, + {ARM_EXT_V6T2, 0xe8700000, 0xff700000, "ldrd%c\t%12-15r, %8-11r, [%16-19r], #%23`-%0-7W"}, + {ARM_EXT_V6T2, 0xf8000000, 0xff100000, "str%w%c.w\t%12-15r, %a"}, + {ARM_EXT_V6T2, 0xf8100000, 0xfe100000, "ldr%w%c.w\t%12-15r, %a"}, + + /* Filter out Bcc with cond=E or F, which are used for other instructions. */ + {ARM_EXT_V6T2, 0xf3c08000, 0xfbc0d000, "undefined (bcc, cond=0xF)"}, + {ARM_EXT_V6T2, 0xf3808000, 0xfbc0d000, "undefined (bcc, cond=0xE)"}, + {ARM_EXT_V6T2, 0xf0008000, 0xf800d000, "b%22-25c.w\t%b%X"}, + {ARM_EXT_V6T2, 0xf0009000, 0xf800d000, "b%c.w\t%B%x"}, + + /* These have been 32-bit since the invention of Thumb. */ + {ARM_EXT_V4T, 0xf000c000, 0xf800d000, "blx%c\t%B%x"}, + {ARM_EXT_V4T, 0xf000d000, 0xf800d000, "bl%c\t%B%x"}, + + /* Fallback. */ + {ARM_EXT_V1, 0x00000000, 0x00000000, "undefined"}, + {0, 0, 0, 0} +}; + +static const char *const arm_conditional[] = +{"eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc", + "hi", "ls", "ge", "lt", "gt", "le", "al", "", ""}; + +static const char *const arm_fp_const[] = +{"0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "0.5", "10.0"}; + +static const char *const arm_shift[] = +{"lsl", "lsr", "asr", "ror"}; + +typedef struct +{ + const char *name; + const char *description; + const char *reg_names[16]; +} +arm_regname; + +static const arm_regname regnames[] = +{ + { "raw" , "Select raw register names", + { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"}}, + { "gcc", "Select register names used by GCC", + { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "sl", "fp", "ip", "sp", "lr", "pc" }}, + { "std", "Select register names used in ARM's ISA documentation", + { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "sp", "lr", "pc" }}, + { "apcs", "Select register names used in the APCS", + { "a1", "a2", "a3", "a4", "v1", "v2", "v3", "v4", "v5", "v6", "sl", "fp", "ip", "sp", "lr", "pc" }}, + { "atpcs", "Select register names used in the ATPCS", + { "a1", "a2", "a3", "a4", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "IP", "SP", "LR", "PC" }}, + { "special-atpcs", "Select special register names used in the ATPCS", + { "a1", "a2", "a3", "a4", "v1", "v2", "v3", "WR", "v5", "SB", "SL", "FP", "IP", "SP", "LR", "PC" }}, +}; + +static const char *const iwmmxt_wwnames[] = +{"b", "h", "w", "d"}; + +static const char *const iwmmxt_wwssnames[] = +{"b", "bus", "bc", "bss", + "h", "hus", "hc", "hss", + "w", "wus", "wc", "wss", + "d", "dus", "dc", "dss" +}; + +static const char *const iwmmxt_regnames[] = +{ "wr0", "wr1", "wr2", "wr3", "wr4", "wr5", "wr6", "wr7", + "wr8", "wr9", "wr10", "wr11", "wr12", "wr13", "wr14", "wr15" +}; + +static const char *const iwmmxt_cregnames[] = +{ "wcid", "wcon", "wcssf", "wcasf", "reserved", "reserved", "reserved", "reserved", + "wcgr0", "wcgr1", "wcgr2", "wcgr3", "reserved", "reserved", "reserved", "reserved" +}; + +/* Default to GCC register name set. */ +static unsigned int regname_selected = 1; + +#define NUM_ARM_REGNAMES NUM_ELEM (regnames) +#define arm_regnames regnames[regname_selected].reg_names + +static bfd_boolean force_thumb = FALSE; + +/* Current IT instruction state. This contains the same state as the IT + bits in the CPSR. */ +static unsigned int ifthen_state; +/* IT state for the next instruction. */ +static unsigned int ifthen_next_state; +/* The address of the insn for which the IT state is valid. */ +static bfd_vma ifthen_address; +#define IFTHEN_COND ((ifthen_state >> 4) & 0xf) + +/* Cached mapping symbol state. */ +enum map_type { + MAP_ARM, + MAP_THUMB, + MAP_DATA +}; + +enum map_type last_type; +int last_mapping_sym = -1; +bfd_vma last_mapping_addr = 0; + + +/* Functions. */ +int +get_arm_regname_num_options (void) +{ + return NUM_ARM_REGNAMES; +} + +int +set_arm_regname_option (int option) +{ + int old = regname_selected; + regname_selected = option; + return old; +} + +int +get_arm_regnames (int option, const char **setname, const char **setdescription, + const char *const **register_names) +{ + *setname = regnames[option].name; + *setdescription = regnames[option].description; + *register_names = regnames[option].reg_names; + return 16; +} + +/* Decode a bitfield of the form matching regexp (N(-N)?,)*N(-N)?. + Returns pointer to following character of the format string and + fills in *VALUEP and *WIDTHP with the extracted value and number of + bits extracted. WIDTHP can be NULL. */ + +static const char * +arm_decode_bitfield (const char *ptr, unsigned long insn, + unsigned long *valuep, int *widthp) +{ + unsigned long value = 0; + int width = 0; + + do + { + int start, end; + int bits; + + for (start = 0; *ptr >= '0' && *ptr <= '9'; ptr++) + start = start * 10 + *ptr - '0'; + if (*ptr == '-') + for (end = 0, ptr++; *ptr >= '0' && *ptr <= '9'; ptr++) + end = end * 10 + *ptr - '0'; + else + end = start; + bits = end - start; + if (bits < 0) + abort (); + value |= ((insn >> start) & ((2ul << bits) - 1)) << width; + width += bits + 1; + } + while (*ptr++ == ','); + *valuep = value; + if (widthp) + *widthp = width; + return ptr - 1; +} + +static void +arm_decode_shift (long given, fprintf_ftype func, void *stream, + int print_shift) +{ + func (stream, "%s", arm_regnames[given & 0xf]); + + if ((given & 0xff0) != 0) + { + if ((given & 0x10) == 0) + { + int amount = (given & 0xf80) >> 7; + int shift = (given & 0x60) >> 5; + + if (amount == 0) + { + if (shift == 3) + { + func (stream, ", rrx"); + return; + } + + amount = 32; + } + + if (print_shift) + func (stream, ", %s #%d", arm_shift[shift], amount); + else + func (stream, ", #%d", amount); + } + else if (print_shift) + func (stream, ", %s %s", arm_shift[(given & 0x60) >> 5], + arm_regnames[(given & 0xf00) >> 8]); + else + func (stream, ", %s", arm_regnames[(given & 0xf00) >> 8]); + } +} + +/* Print one coprocessor instruction on INFO->STREAM. + Return TRUE if the instuction matched, FALSE if this is not a + recognised coprocessor instruction. */ + +static bfd_boolean +print_insn_coprocessor (bfd_vma pc, struct disassemble_info *info, long given, + bfd_boolean thumb) +{ + const struct opcode32 *insn; + void *stream = info->stream; + fprintf_ftype func = info->fprintf_func; + unsigned long mask; + unsigned long value; + int cond; + + for (insn = coprocessor_opcodes; insn->assembler; insn++) + { + if (insn->value == FIRST_IWMMXT_INSN + && info->mach != bfd_mach_arm_XScale + && info->mach != bfd_mach_arm_iWMMXt + && info->mach != bfd_mach_arm_iWMMXt2) + insn = insn + IWMMXT_INSN_COUNT; + + mask = insn->mask; + value = insn->value; + if (thumb) + { + /* The high 4 bits are 0xe for Arm conditional instructions, and + 0xe for arm unconditional instructions. The rest of the + encoding is the same. */ + mask |= 0xf0000000; + value |= 0xe0000000; + if (ifthen_state) + cond = IFTHEN_COND; + else + cond = 16; + } + else + { + /* Only match unconditional instuctions against unconditional + patterns. */ + if ((given & 0xf0000000) == 0xf0000000) + { + mask |= 0xf0000000; + cond = 16; + } + else + { + cond = (given >> 28) & 0xf; + if (cond == 0xe) + cond = 16; + } + } + if ((given & mask) == value) + { + const char *c; + + for (c = insn->assembler; *c; c++) + { + if (*c == '%') + { + switch (*++c) + { + case '%': + func (stream, "%%"); + break; + + case 'A': + func (stream, "[%s", arm_regnames [(given >> 16) & 0xf]); + + if ((given & (1 << 24)) != 0) + { + int offset = given & 0xff; + + if (offset) + func (stream, ", #%s%d]%s", + ((given & 0x00800000) == 0 ? "-" : ""), + offset * 4, + ((given & 0x00200000) != 0 ? "!" : "")); + else + func (stream, "]"); + } + else + { + int offset = given & 0xff; + + func (stream, "]"); + + if (given & (1 << 21)) + { + if (offset) + func (stream, ", #%s%d", + ((given & 0x00800000) == 0 ? "-" : ""), + offset * 4); + } + else + func (stream, ", {%d}", offset); + } + break; + + case 'B': + { + int regno = ((given >> 12) & 0xf) | ((given >> (22 - 4)) & 0x10); + int offset = (given >> 1) & 0x3f; + + if (offset == 1) + func (stream, "{d%d}", regno); + else if (regno + offset > 32) + func (stream, "{d%d-}", regno, regno + offset - 1); + else + func (stream, "{d%d-d%d}", regno, regno + offset - 1); + } + break; + + case 'C': + { + int rn = (given >> 16) & 0xf; + int offset = (given & 0xff) * 4; + int add = (given >> 23) & 1; + + func (stream, "[%s", arm_regnames[rn]); + + if (offset) + { + if (!add) + offset = -offset; + func (stream, ", #%d", offset); + } + func (stream, "]"); + if (rn == 15) + { + func (stream, "\t; "); + /* FIXME: Unsure if info->bytes_per_chunk is the + right thing to use here. */ + info->print_address_func (offset + pc + + info->bytes_per_chunk * 2, info); + } + } + break; + + case 'c': + func (stream, "%s", arm_conditional[cond]); + break; + + case 'I': + /* Print a Cirrus/DSP shift immediate. */ + /* Immediates are 7bit signed ints with bits 0..3 in + bits 0..3 of opcode and bits 4..6 in bits 5..7 + of opcode. */ + { + int imm; + + imm = (given & 0xf) | ((given & 0xe0) >> 1); + + /* Is ``imm'' a negative number? */ + if (imm & 0x40) + imm |= (-1 << 7); + + func (stream, "%d", imm); + } + + break; + + case 'F': + switch (given & 0x00408000) + { + case 0: + func (stream, "4"); + break; + case 0x8000: + func (stream, "1"); + break; + case 0x00400000: + func (stream, "2"); + break; + default: + func (stream, "3"); + } + break; + + case 'P': + switch (given & 0x00080080) + { + case 0: + func (stream, "s"); + break; + case 0x80: + func (stream, "d"); + break; + case 0x00080000: + func (stream, "e"); + break; + default: + func (stream, _("")); + break; + } + break; + case 'Q': + switch (given & 0x00408000) + { + case 0: + func (stream, "s"); + break; + case 0x8000: + func (stream, "d"); + break; + case 0x00400000: + func (stream, "e"); + break; + default: + func (stream, "p"); + break; + } + break; + case 'R': + switch (given & 0x60) + { + case 0: + break; + case 0x20: + func (stream, "p"); + break; + case 0x40: + func (stream, "m"); + break; + default: + func (stream, "z"); + break; + } + break; + + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + { + int width; + unsigned long value; + + c = arm_decode_bitfield (c, given, &value, &width); + + switch (*c) + { + case 'r': + func (stream, "%s", arm_regnames[value]); + break; + case 'D': + func (stream, "d%ld", value); + break; + case 'Q': + if (value & 1) + func (stream, "", value >> 1); + else + func (stream, "q%ld", value >> 1); + break; + case 'd': + func (stream, "%ld", value); + break; + case 'k': + { + int from = (given & (1 << 7)) ? 32 : 16; + func (stream, "%ld", from - value); + } + break; + + case 'f': + if (value > 7) + func (stream, "#%s", arm_fp_const[value & 7]); + else + func (stream, "f%ld", value); + break; + + case 'w': + if (width == 2) + func (stream, "%s", iwmmxt_wwnames[value]); + else + func (stream, "%s", iwmmxt_wwssnames[value]); + break; + + case 'g': + func (stream, "%s", iwmmxt_regnames[value]); + break; + case 'G': + func (stream, "%s", iwmmxt_cregnames[value]); + break; + + case 'x': + func (stream, "0x%lx", value); + break; + + case '`': + c++; + if (value == 0) + func (stream, "%c", *c); + break; + case '\'': + c++; + if (value == ((1ul << width) - 1)) + func (stream, "%c", *c); + break; + case '?': + func (stream, "%c", c[(1 << width) - (int)value]); + c += 1 << width; + break; + default: + abort (); + } + break; + + case 'y': + case 'z': + { + int single = *c++ == 'y'; + int regno; + + switch (*c) + { + case '4': /* Sm pair */ + func (stream, "{"); + /* Fall through. */ + case '0': /* Sm, Dm */ + regno = given & 0x0000000f; + if (single) + { + regno <<= 1; + regno += (given >> 5) & 1; + } + else + regno += ((given >> 5) & 1) << 4; + break; + + case '1': /* Sd, Dd */ + regno = (given >> 12) & 0x0000000f; + if (single) + { + regno <<= 1; + regno += (given >> 22) & 1; + } + else + regno += ((given >> 22) & 1) << 4; + break; + + case '2': /* Sn, Dn */ + regno = (given >> 16) & 0x0000000f; + if (single) + { + regno <<= 1; + regno += (given >> 7) & 1; + } + else + regno += ((given >> 7) & 1) << 4; + break; + + case '3': /* List */ + func (stream, "{"); + regno = (given >> 12) & 0x0000000f; + if (single) + { + regno <<= 1; + regno += (given >> 22) & 1; + } + else + regno += ((given >> 22) & 1) << 4; + break; + + default: + abort (); + } + + func (stream, "%c%d", single ? 's' : 'd', regno); + + if (*c == '3') + { + int count = given & 0xff; + + if (single == 0) + count >>= 1; + + if (--count) + { + func (stream, "-%c%d", + single ? 's' : 'd', + regno + count); + } + + func (stream, "}"); + } + else if (*c == '4') + func (stream, ", %c%d}", single ? 's' : 'd', + regno + 1); + } + break; + + case 'L': + switch (given & 0x00400100) + { + case 0x00000000: func (stream, "b"); break; + case 0x00400000: func (stream, "h"); break; + case 0x00000100: func (stream, "w"); break; + case 0x00400100: func (stream, "d"); break; + default: + break; + } + break; + + case 'Z': + { + int value; + /* given (20, 23) | given (0, 3) */ + value = ((given >> 16) & 0xf0) | (given & 0xf); + func (stream, "%d", value); + } + break; + + case 'l': + /* This is like the 'A' operator, except that if + the width field "M" is zero, then the offset is + *not* multiplied by four. */ + { + int offset = given & 0xff; + int multiplier = (given & 0x00000100) ? 4 : 1; + + func (stream, "[%s", arm_regnames [(given >> 16) & 0xf]); + + if (offset) + { + if ((given & 0x01000000) != 0) + func (stream, ", #%s%d]%s", + ((given & 0x00800000) == 0 ? "-" : ""), + offset * multiplier, + ((given & 0x00200000) != 0 ? "!" : "")); + else + func (stream, "], #%s%d", + ((given & 0x00800000) == 0 ? "-" : ""), + offset * multiplier); + } + else + func (stream, "]"); + } + break; + + case 'r': + { + int imm4 = (given >> 4) & 0xf; + int puw_bits = ((given >> 22) & 6) | ((given >> 21) & 1); + int ubit = (given >> 23) & 1; + const char *rm = arm_regnames [given & 0xf]; + const char *rn = arm_regnames [(given >> 16) & 0xf]; + + switch (puw_bits) + { + case 1: + /* fall through */ + case 3: + func (stream, "[%s], %c%s", rn, ubit ? '+' : '-', rm); + if (imm4) + func (stream, ", lsl #%d", imm4); + break; + + case 4: + /* fall through */ + case 5: + /* fall through */ + case 6: + /* fall through */ + case 7: + func (stream, "[%s, %c%s", rn, ubit ? '+' : '-', rm); + if (imm4 > 0) + func (stream, ", lsl #%d", imm4); + func (stream, "]"); + if (puw_bits == 5 || puw_bits == 7) + func (stream, "!"); + break; + + default: + func (stream, "INVALID"); + } + } + break; + + case 'i': + { + long imm5; + imm5 = ((given & 0x100) >> 4) | (given & 0xf); + func (stream, "%ld", (imm5 == 0) ? 32 : imm5); + } + break; + + default: + abort (); + } + } + } + else + func (stream, "%c", *c); + } + return TRUE; + } + } + return FALSE; +} + +static void +print_arm_address (bfd_vma pc, struct disassemble_info *info, long given) +{ + void *stream = info->stream; + fprintf_ftype func = info->fprintf_func; + + if (((given & 0x000f0000) == 0x000f0000) + && ((given & 0x02000000) == 0)) + { + int offset = given & 0xfff; + + func (stream, "[pc"); + + if (given & 0x01000000) + { + if ((given & 0x00800000) == 0) + offset = - offset; + + /* Pre-indexed. */ + func (stream, ", #%d]", offset); + + offset += pc + 8; + + /* Cope with the possibility of write-back + being used. Probably a very dangerous thing + for the programmer to do, but who are we to + argue ? */ + if (given & 0x00200000) + func (stream, "!"); + } + else + { + /* Post indexed. */ + func (stream, "], #%d", offset); + + /* ie ignore the offset. */ + offset = pc + 8; + } + + func (stream, "\t; "); + info->print_address_func (offset, info); + } + else + { + func (stream, "[%s", + arm_regnames[(given >> 16) & 0xf]); + if ((given & 0x01000000) != 0) + { + if ((given & 0x02000000) == 0) + { + int offset = given & 0xfff; + if (offset) + func (stream, ", #%s%d", + (((given & 0x00800000) == 0) + ? "-" : ""), offset); + } + else + { + func (stream, ", %s", + (((given & 0x00800000) == 0) + ? "-" : "")); + arm_decode_shift (given, func, stream, 1); + } + + func (stream, "]%s", + ((given & 0x00200000) != 0) ? "!" : ""); + } + else + { + if ((given & 0x02000000) == 0) + { + int offset = given & 0xfff; + if (offset) + func (stream, "], #%s%d", + (((given & 0x00800000) == 0) + ? "-" : ""), offset); + else + func (stream, "]"); + } + else + { + func (stream, "], %s", + (((given & 0x00800000) == 0) + ? "-" : "")); + arm_decode_shift (given, func, stream, 1); + } + } + } +} + +/* Print one neon instruction on INFO->STREAM. + Return TRUE if the instuction matched, FALSE if this is not a + recognised neon instruction. */ + +static bfd_boolean +print_insn_neon (struct disassemble_info *info, long given, bfd_boolean thumb) +{ + const struct opcode32 *insn; + void *stream = info->stream; + fprintf_ftype func = info->fprintf_func; + + if (thumb) + { + if ((given & 0xef000000) == 0xef000000) + { + /* move bit 28 to bit 24 to translate Thumb2 to ARM encoding. */ + unsigned long bit28 = given & (1 << 28); + + given &= 0x00ffffff; + if (bit28) + given |= 0xf3000000; + else + given |= 0xf2000000; + } + else if ((given & 0xff000000) == 0xf9000000) + given ^= 0xf9000000 ^ 0xf4000000; + else + return FALSE; + } + + for (insn = neon_opcodes; insn->assembler; insn++) + { + if ((given & insn->mask) == insn->value) + { + const char *c; + + for (c = insn->assembler; *c; c++) + { + if (*c == '%') + { + switch (*++c) + { + case '%': + func (stream, "%%"); + break; + + case 'c': + if (thumb && ifthen_state) + func (stream, "%s", arm_conditional[IFTHEN_COND]); + break; + + case 'A': + { + static const unsigned char enc[16] = + { + 0x4, 0x14, /* st4 0,1 */ + 0x4, /* st1 2 */ + 0x4, /* st2 3 */ + 0x3, /* st3 4 */ + 0x13, /* st3 5 */ + 0x3, /* st1 6 */ + 0x1, /* st1 7 */ + 0x2, /* st2 8 */ + 0x12, /* st2 9 */ + 0x2, /* st1 10 */ + 0, 0, 0, 0, 0 + }; + int rd = ((given >> 12) & 0xf) | (((given >> 22) & 1) << 4); + int rn = ((given >> 16) & 0xf); + int rm = ((given >> 0) & 0xf); + int align = ((given >> 4) & 0x3); + int type = ((given >> 8) & 0xf); + int n = enc[type] & 0xf; + int stride = (enc[type] >> 4) + 1; + int ix; + + func (stream, "{"); + if (stride > 1) + for (ix = 0; ix != n; ix++) + func (stream, "%sd%d", ix ? "," : "", rd + ix * stride); + else if (n == 1) + func (stream, "d%d", rd); + else + func (stream, "d%d-d%d", rd, rd + n - 1); + func (stream, "}, [%s", arm_regnames[rn]); + if (align) + func (stream, ", :%d", 32 << align); + func (stream, "]"); + if (rm == 0xd) + func (stream, "!"); + else if (rm != 0xf) + func (stream, ", %s", arm_regnames[rm]); + } + break; + + case 'B': + { + int rd = ((given >> 12) & 0xf) | (((given >> 22) & 1) << 4); + int rn = ((given >> 16) & 0xf); + int rm = ((given >> 0) & 0xf); + int idx_align = ((given >> 4) & 0xf); + int align = 0; + int size = ((given >> 10) & 0x3); + int idx = idx_align >> (size + 1); + int length = ((given >> 8) & 3) + 1; + int stride = 1; + int i; + + if (length > 1 && size > 0) + stride = (idx_align & (1 << size)) ? 2 : 1; + + switch (length) + { + case 1: + { + int amask = (1 << size) - 1; + if ((idx_align & (1 << size)) != 0) + return FALSE; + if (size > 0) + { + if ((idx_align & amask) == amask) + align = 8 << size; + else if ((idx_align & amask) != 0) + return FALSE; + } + } + break; + + case 2: + if (size == 2 && (idx_align & 2) != 0) + return FALSE; + align = (idx_align & 1) ? 16 << size : 0; + break; + + case 3: + if ((size == 2 && (idx_align & 3) != 0) + || (idx_align & 1) != 0) + return FALSE; + break; + + case 4: + if (size == 2) + { + if ((idx_align & 3) == 3) + return FALSE; + align = (idx_align & 3) * 64; + } + else + align = (idx_align & 1) ? 32 << size : 0; + break; + + default: + abort (); + } + + func (stream, "{"); + for (i = 0; i < length; i++) + func (stream, "%sd%d[%d]", (i == 0) ? "" : ",", + rd + i * stride, idx); + func (stream, "}, [%s", arm_regnames[rn]); + if (align) + func (stream, ", :%d", align); + func (stream, "]"); + if (rm == 0xd) + func (stream, "!"); + else if (rm != 0xf) + func (stream, ", %s", arm_regnames[rm]); + } + break; + + case 'C': + { + int rd = ((given >> 12) & 0xf) | (((given >> 22) & 1) << 4); + int rn = ((given >> 16) & 0xf); + int rm = ((given >> 0) & 0xf); + int align = ((given >> 4) & 0x1); + int size = ((given >> 6) & 0x3); + int type = ((given >> 8) & 0x3); + int n = type + 1; + int stride = ((given >> 5) & 0x1); + int ix; + + if (stride && (n == 1)) + n++; + else + stride++; + + func (stream, "{"); + if (stride > 1) + for (ix = 0; ix != n; ix++) + func (stream, "%sd%d[]", ix ? "," : "", rd + ix * stride); + else if (n == 1) + func (stream, "d%d[]", rd); + else + func (stream, "d%d[]-d%d[]", rd, rd + n - 1); + func (stream, "}, [%s", arm_regnames[rn]); + if (align) + { + int align = (8 * (type + 1)) << size; + if (type == 3) + align = (size > 1) ? align >> 1 : align; + if (type == 2 || (type == 0 && !size)) + func (stream, ", :", align); + else + func (stream, ", :%d", align); + } + func (stream, "]"); + if (rm == 0xd) + func (stream, "!"); + else if (rm != 0xf) + func (stream, ", %s", arm_regnames[rm]); + } + break; + + case 'D': + { + int raw_reg = (given & 0xf) | ((given >> 1) & 0x10); + int size = (given >> 20) & 3; + int reg = raw_reg & ((4 << size) - 1); + int ix = raw_reg >> size >> 2; + + func (stream, "d%d[%d]", reg, ix); + } + break; + + case 'E': + /* Neon encoded constant for mov, mvn, vorr, vbic */ + { + int bits = 0; + int cmode = (given >> 8) & 0xf; + int op = (given >> 5) & 0x1; + unsigned long value = 0, hival = 0; + unsigned shift; + int size = 0; + int isfloat = 0; + + bits |= ((given >> 24) & 1) << 7; + bits |= ((given >> 16) & 7) << 4; + bits |= ((given >> 0) & 15) << 0; + + if (cmode < 8) + { + shift = (cmode >> 1) & 3; + value = (unsigned long)bits << (8 * shift); + size = 32; + } + else if (cmode < 12) + { + shift = (cmode >> 1) & 1; + value = (unsigned long)bits << (8 * shift); + size = 16; + } + else if (cmode < 14) + { + shift = (cmode & 1) + 1; + value = (unsigned long)bits << (8 * shift); + value |= (1ul << (8 * shift)) - 1; + size = 32; + } + else if (cmode == 14) + { + if (op) + { + /* bit replication into bytes */ + int ix; + unsigned long mask; + + value = 0; + hival = 0; + for (ix = 7; ix >= 0; ix--) + { + mask = ((bits >> ix) & 1) ? 0xff : 0; + if (ix <= 3) + value = (value << 8) | mask; + else + hival = (hival << 8) | mask; + } + size = 64; + } + else + { + /* byte replication */ + value = (unsigned long)bits; + size = 8; + } + } + else if (!op) + { + /* floating point encoding */ + int tmp; + + value = (unsigned long)(bits & 0x7f) << 19; + value |= (unsigned long)(bits & 0x80) << 24; + tmp = bits & 0x40 ? 0x3c : 0x40; + value |= (unsigned long)tmp << 24; + size = 32; + isfloat = 1; + } + else + { + func (stream, "", + bits, cmode, op); + size = 32; + break; + } + switch (size) + { + case 8: + func (stream, "#%ld\t; 0x%.2lx", value, value); + break; + + case 16: + func (stream, "#%ld\t; 0x%.4lx", value, value); + break; + + case 32: + if (isfloat) + { + unsigned char valbytes[4]; + double fvalue; + + /* Do this a byte at a time so we don't have to + worry about the host's endianness. */ + valbytes[0] = value & 0xff; + valbytes[1] = (value >> 8) & 0xff; + valbytes[2] = (value >> 16) & 0xff; + valbytes[3] = (value >> 24) & 0xff; + +#if 0 + floatformat_to_double + (&floatformat_ieee_single_little, valbytes, + &fvalue); +#endif + fvalue = 0; + + func (stream, "#%.7g\t; 0x%.8lx", fvalue, + value); + } + else + func (stream, "#%ld\t; 0x%.8lx", + (long) ((value & 0x80000000) + ? value | ~0xffffffffl : value), value); + break; + + case 64: + func (stream, "#0x%.8lx%.8lx", hival, value); + break; + + default: + abort (); + } + } + break; + + case 'F': + { + int regno = ((given >> 16) & 0xf) | ((given >> (7 - 4)) & 0x10); + int num = (given >> 8) & 0x3; + + if (!num) + func (stream, "{d%d}", regno); + else if (num + regno >= 32) + func (stream, "{d%d-= '0' && *c <= '9') + limit = *c - '0'; + else if (*c >= 'a' && *c <= 'f') + limit = *c - 'a' + 10; + else + abort (); + low = limit >> 2; + high = limit & 3; + + if (value < low || value > high) + func (stream, "", base << value); + else + func (stream, "%d", base << value); + } + break; + case 'R': + if (given & (1 << 6)) + goto Q; + /* FALLTHROUGH */ + case 'D': + func (stream, "d%ld", value); + break; + case 'Q': + Q: + if (value & 1) + func (stream, "", value >> 1); + else + func (stream, "q%ld", value >> 1); + break; + + case '`': + c++; + if (value == 0) + func (stream, "%c", *c); + break; + case '\'': + c++; + if (value == ((1ul << width) - 1)) + func (stream, "%c", *c); + break; + case '?': + func (stream, "%c", c[(1 << width) - (int)value]); + c += 1 << width; + break; + default: + abort (); + } + break; + + default: + abort (); + } + } + } + else + func (stream, "%c", *c); + } + return TRUE; + } + } + return FALSE; +} + +/* Print one ARM instruction from PC on INFO->STREAM. */ + +static void +print_insn_arm (bfd_vma pc, struct disassemble_info *info, long given) +{ + const struct opcode32 *insn; + void *stream = info->stream; + fprintf_ftype func = info->fprintf_func; + + if (print_insn_coprocessor (pc, info, given, FALSE)) + return; + + if (print_insn_neon (info, given, FALSE)) + return; + + for (insn = arm_opcodes; insn->assembler; insn++) + { + if (insn->value == FIRST_IWMMXT_INSN + && info->mach != bfd_mach_arm_XScale + && info->mach != bfd_mach_arm_iWMMXt) + insn = insn + IWMMXT_INSN_COUNT; + + if ((given & insn->mask) == insn->value + /* Special case: an instruction with all bits set in the condition field + (0xFnnn_nnnn) is only matched if all those bits are set in insn->mask, + or by the catchall at the end of the table. */ + && ((given & 0xF0000000) != 0xF0000000 + || (insn->mask & 0xF0000000) == 0xF0000000 + || (insn->mask == 0 && insn->value == 0))) + { + const char *c; + + for (c = insn->assembler; *c; c++) + { + if (*c == '%') + { + switch (*++c) + { + case '%': + func (stream, "%%"); + break; + + case 'a': + print_arm_address (pc, info, given); + break; + + case 'P': + /* Set P address bit and use normal address + printing routine. */ + print_arm_address (pc, info, given | (1 << 24)); + break; + + case 's': + if ((given & 0x004f0000) == 0x004f0000) + { + /* PC relative with immediate offset. */ + int offset = ((given & 0xf00) >> 4) | (given & 0xf); + + if ((given & 0x00800000) == 0) + offset = -offset; + + func (stream, "[pc, #%d]\t; ", offset); + info->print_address_func (offset + pc + 8, info); + } + else + { + func (stream, "[%s", + arm_regnames[(given >> 16) & 0xf]); + if ((given & 0x01000000) != 0) + { + /* Pre-indexed. */ + if ((given & 0x00400000) == 0x00400000) + { + /* Immediate. */ + int offset = ((given & 0xf00) >> 4) | (given & 0xf); + if (offset) + func (stream, ", #%s%d", + (((given & 0x00800000) == 0) + ? "-" : ""), offset); + } + else + { + /* Register. */ + func (stream, ", %s%s", + (((given & 0x00800000) == 0) + ? "-" : ""), + arm_regnames[given & 0xf]); + } + + func (stream, "]%s", + ((given & 0x00200000) != 0) ? "!" : ""); + } + else + { + /* Post-indexed. */ + if ((given & 0x00400000) == 0x00400000) + { + /* Immediate. */ + int offset = ((given & 0xf00) >> 4) | (given & 0xf); + if (offset) + func (stream, "], #%s%d", + (((given & 0x00800000) == 0) + ? "-" : ""), offset); + else + func (stream, "]"); + } + else + { + /* Register. */ + func (stream, "], %s%s", + (((given & 0x00800000) == 0) + ? "-" : ""), + arm_regnames[given & 0xf]); + } + } + } + break; + + case 'b': + { + int disp = (((given & 0xffffff) ^ 0x800000) - 0x800000); + info->print_address_func (disp*4 + pc + 8, info); + } + break; + + case 'c': + if (((given >> 28) & 0xf) != 0xe) + func (stream, "%s", + arm_conditional [(given >> 28) & 0xf]); + break; + + case 'm': + { + int started = 0; + int reg; + + func (stream, "{"); + for (reg = 0; reg < 16; reg++) + if ((given & (1 << reg)) != 0) + { + if (started) + func (stream, ", "); + started = 1; + func (stream, "%s", arm_regnames[reg]); + } + func (stream, "}"); + } + break; + + case 'q': + arm_decode_shift (given, func, stream, 0); + break; + + case 'o': + if ((given & 0x02000000) != 0) + { + int rotate = (given & 0xf00) >> 7; + int immed = (given & 0xff); + immed = (((immed << (32 - rotate)) + | (immed >> rotate)) & 0xffffffff); + func (stream, "#%d\t; 0x%x", immed, immed); + } + else + arm_decode_shift (given, func, stream, 1); + break; + + case 'p': + if ((given & 0x0000f000) == 0x0000f000) + func (stream, "p"); + break; + + case 't': + if ((given & 0x01200000) == 0x00200000) + func (stream, "t"); + break; + + case 'A': + func (stream, "[%s", arm_regnames [(given >> 16) & 0xf]); + + if ((given & (1 << 24)) != 0) + { + int offset = given & 0xff; + + if (offset) + func (stream, ", #%s%d]%s", + ((given & 0x00800000) == 0 ? "-" : ""), + offset * 4, + ((given & 0x00200000) != 0 ? "!" : "")); + else + func (stream, "]"); + } + else + { + int offset = given & 0xff; + + func (stream, "]"); + + if (given & (1 << 21)) + { + if (offset) + func (stream, ", #%s%d", + ((given & 0x00800000) == 0 ? "-" : ""), + offset * 4); + } + else + func (stream, ", {%d}", offset); + } + break; + + case 'B': + /* Print ARM V5 BLX(1) address: pc+25 bits. */ + { + bfd_vma address; + bfd_vma offset = 0; + + if (given & 0x00800000) + /* Is signed, hi bits should be ones. */ + offset = (-1) ^ 0x00ffffff; + + /* Offset is (SignExtend(offset field)<<2). */ + offset += given & 0x00ffffff; + offset <<= 2; + address = offset + pc + 8; + + if (given & 0x01000000) + /* H bit allows addressing to 2-byte boundaries. */ + address += 2; + + info->print_address_func (address, info); + } + break; + + case 'C': + func (stream, "_"); + if (given & 0x80000) + func (stream, "f"); + if (given & 0x40000) + func (stream, "s"); + if (given & 0x20000) + func (stream, "x"); + if (given & 0x10000) + func (stream, "c"); + break; + + case 'U': + switch (given & 0xf) + { + case 0xf: func(stream, "sy"); break; + case 0x7: func(stream, "un"); break; + case 0xe: func(stream, "st"); break; + case 0x6: func(stream, "unst"); break; + default: + func(stream, "#%d", (int)given & 0xf); + break; + } + break; + + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + { + int width; + unsigned long value; + + c = arm_decode_bitfield (c, given, &value, &width); + + switch (*c) + { + case 'r': + func (stream, "%s", arm_regnames[value]); + break; + case 'd': + func (stream, "%ld", value); + break; + case 'b': + func (stream, "%ld", value * 8); + break; + case 'W': + func (stream, "%ld", value + 1); + break; + case 'x': + func (stream, "0x%08lx", value); + + /* Some SWI instructions have special + meanings. */ + if ((given & 0x0fffffff) == 0x0FF00000) + func (stream, "\t; IMB"); + else if ((given & 0x0fffffff) == 0x0FF00001) + func (stream, "\t; IMBRange"); + break; + case 'X': + func (stream, "%01lx", value & 0xf); + break; + case '`': + c++; + if (value == 0) + func (stream, "%c", *c); + break; + case '\'': + c++; + if (value == ((1ul << width) - 1)) + func (stream, "%c", *c); + break; + case '?': + func (stream, "%c", c[(1 << width) - (int)value]); + c += 1 << width; + break; + default: + abort (); + } + break; + + case 'e': + { + int imm; + + imm = (given & 0xf) | ((given & 0xfff00) >> 4); + func (stream, "%d", imm); + } + break; + + case 'E': + /* LSB and WIDTH fields of BFI or BFC. The machine- + language instruction encodes LSB and MSB. */ + { + long msb = (given & 0x001f0000) >> 16; + long lsb = (given & 0x00000f80) >> 7; + + long width = msb - lsb + 1; + if (width > 0) + func (stream, "#%lu, #%lu", lsb, width); + else + func (stream, "(invalid: %lu:%lu)", lsb, msb); + } + break; + + case 'V': + /* 16-bit unsigned immediate from a MOVT or MOVW + instruction, encoded in bits 0:11 and 15:19. */ + { + long hi = (given & 0x000f0000) >> 4; + long lo = (given & 0x00000fff); + long imm16 = hi | lo; + func (stream, "#%lu\t; 0x%lx", imm16, imm16); + } + break; + + default: + abort (); + } + } + } + else + func (stream, "%c", *c); + } + return; + } + } + abort (); +} + +/* Print one 16-bit Thumb instruction from PC on INFO->STREAM. */ + +static void +print_insn_thumb16 (bfd_vma pc, struct disassemble_info *info, long given) +{ + const struct opcode16 *insn; + void *stream = info->stream; + fprintf_ftype func = info->fprintf_func; + + for (insn = thumb_opcodes; insn->assembler; insn++) + if ((given & insn->mask) == insn->value) + { + const char *c = insn->assembler; + for (; *c; c++) + { + int domaskpc = 0; + int domasklr = 0; + + if (*c != '%') + { + func (stream, "%c", *c); + continue; + } + + switch (*++c) + { + case '%': + func (stream, "%%"); + break; + + case 'c': + if (ifthen_state) + func (stream, "%s", arm_conditional[IFTHEN_COND]); + break; + + case 'C': + if (ifthen_state) + func (stream, "%s", arm_conditional[IFTHEN_COND]); + else + func (stream, "s"); + break; + + case 'I': + { + unsigned int tmp; + + ifthen_next_state = given & 0xff; + for (tmp = given << 1; tmp & 0xf; tmp <<= 1) + func (stream, ((given ^ tmp) & 0x10) ? "e" : "t"); + func (stream, "\t%s", arm_conditional[(given >> 4) & 0xf]); + } + break; + + case 'x': + if (ifthen_next_state) + func (stream, "\t; unpredictable branch in IT block\n"); + break; + + case 'X': + if (ifthen_state) + func (stream, "\t; unpredictable ", + arm_conditional[IFTHEN_COND]); + break; + + case 'S': + { + long reg; + + reg = (given >> 3) & 0x7; + if (given & (1 << 6)) + reg += 8; + + func (stream, "%s", arm_regnames[reg]); + } + break; + + case 'D': + { + long reg; + + reg = given & 0x7; + if (given & (1 << 7)) + reg += 8; + + func (stream, "%s", arm_regnames[reg]); + } + break; + + case 'N': + if (given & (1 << 8)) + domasklr = 1; + /* Fall through. */ + case 'O': + if (*c == 'O' && (given & (1 << 8))) + domaskpc = 1; + /* Fall through. */ + case 'M': + { + int started = 0; + int reg; + + func (stream, "{"); + + /* It would be nice if we could spot + ranges, and generate the rS-rE format: */ + for (reg = 0; (reg < 8); reg++) + if ((given & (1 << reg)) != 0) + { + if (started) + func (stream, ", "); + started = 1; + func (stream, "%s", arm_regnames[reg]); + } + + if (domasklr) + { + if (started) + func (stream, ", "); + started = 1; + func (stream, arm_regnames[14] /* "lr" */); + } + + if (domaskpc) + { + if (started) + func (stream, ", "); + func (stream, arm_regnames[15] /* "pc" */); + } + + func (stream, "}"); + } + break; + + case 'b': + /* Print ARM V6T2 CZB address: pc+4+6 bits. */ + { + bfd_vma address = (pc + 4 + + ((given & 0x00f8) >> 2) + + ((given & 0x0200) >> 3)); + info->print_address_func (address, info); + } + break; + + case 's': + /* Right shift immediate -- bits 6..10; 1-31 print + as themselves, 0 prints as 32. */ + { + long imm = (given & 0x07c0) >> 6; + if (imm == 0) + imm = 32; + func (stream, "#%ld", imm); + } + break; + + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + { + int bitstart = *c++ - '0'; + int bitend = 0; + + while (*c >= '0' && *c <= '9') + bitstart = (bitstart * 10) + *c++ - '0'; + + switch (*c) + { + case '-': + { + long reg; + + c++; + while (*c >= '0' && *c <= '9') + bitend = (bitend * 10) + *c++ - '0'; + if (!bitend) + abort (); + reg = given >> bitstart; + reg &= (2 << (bitend - bitstart)) - 1; + switch (*c) + { + case 'r': + func (stream, "%s", arm_regnames[reg]); + break; + + case 'd': + func (stream, "%ld", reg); + break; + + case 'H': + func (stream, "%ld", reg << 1); + break; + + case 'W': + func (stream, "%ld", reg << 2); + break; + + case 'a': + /* PC-relative address -- the bottom two + bits of the address are dropped + before the calculation. */ + info->print_address_func + (((pc + 4) & ~3) + (reg << 2), info); + break; + + case 'x': + func (stream, "0x%04lx", reg); + break; + + case 'B': + reg = ((reg ^ (1 << bitend)) - (1 << bitend)); + info->print_address_func (reg * 2 + pc + 4, info); + break; + + case 'c': + func (stream, "%s", arm_conditional [reg]); + break; + + default: + abort (); + } + } + break; + + case '\'': + c++; + if ((given & (1 << bitstart)) != 0) + func (stream, "%c", *c); + break; + + case '?': + ++c; + if ((given & (1 << bitstart)) != 0) + func (stream, "%c", *c++); + else + func (stream, "%c", *++c); + break; + + default: + abort (); + } + } + break; + + default: + abort (); + } + } + return; + } + + /* No match. */ + abort (); +} + +/* Return the name of an V7M special register. */ +static const char * +psr_name (int regno) +{ + switch (regno) + { + case 0: return "APSR"; + case 1: return "IAPSR"; + case 2: return "EAPSR"; + case 3: return "PSR"; + case 5: return "IPSR"; + case 6: return "EPSR"; + case 7: return "IEPSR"; + case 8: return "MSP"; + case 9: return "PSP"; + case 16: return "PRIMASK"; + case 17: return "BASEPRI"; + case 18: return "BASEPRI_MASK"; + case 19: return "FAULTMASK"; + case 20: return "CONTROL"; + default: return ""; + } +} + +/* Print one 32-bit Thumb instruction from PC on INFO->STREAM. */ + +static void +print_insn_thumb32 (bfd_vma pc, struct disassemble_info *info, long given) +{ + const struct opcode32 *insn; + void *stream = info->stream; + fprintf_ftype func = info->fprintf_func; + + if (print_insn_coprocessor (pc, info, given, TRUE)) + return; + + if (print_insn_neon (info, given, TRUE)) + return; + + for (insn = thumb32_opcodes; insn->assembler; insn++) + if ((given & insn->mask) == insn->value) + { + const char *c = insn->assembler; + for (; *c; c++) + { + if (*c != '%') + { + func (stream, "%c", *c); + continue; + } + + switch (*++c) + { + case '%': + func (stream, "%%"); + break; + + case 'c': + if (ifthen_state) + func (stream, "%s", arm_conditional[IFTHEN_COND]); + break; + + case 'x': + if (ifthen_next_state) + func (stream, "\t; unpredictable branch in IT block\n"); + break; + + case 'X': + if (ifthen_state) + func (stream, "\t; unpredictable ", + arm_conditional[IFTHEN_COND]); + break; + + case 'I': + { + unsigned int imm12 = 0; + imm12 |= (given & 0x000000ffu); + imm12 |= (given & 0x00007000u) >> 4; + imm12 |= (given & 0x04000000u) >> 15; + func (stream, "#%u\t; 0x%x", imm12, imm12); + } + break; + + case 'M': + { + unsigned int bits = 0, imm, imm8, mod; + bits |= (given & 0x000000ffu); + bits |= (given & 0x00007000u) >> 4; + bits |= (given & 0x04000000u) >> 15; + imm8 = (bits & 0x0ff); + mod = (bits & 0xf00) >> 8; + switch (mod) + { + case 0: imm = imm8; break; + case 1: imm = ((imm8<<16) | imm8); break; + case 2: imm = ((imm8<<24) | (imm8 << 8)); break; + case 3: imm = ((imm8<<24) | (imm8 << 16) | (imm8 << 8) | imm8); break; + default: + mod = (bits & 0xf80) >> 7; + imm8 = (bits & 0x07f) | 0x80; + imm = (((imm8 << (32 - mod)) | (imm8 >> mod)) & 0xffffffff); + } + func (stream, "#%u\t; 0x%x", imm, imm); + } + break; + + case 'J': + { + unsigned int imm = 0; + imm |= (given & 0x000000ffu); + imm |= (given & 0x00007000u) >> 4; + imm |= (given & 0x04000000u) >> 15; + imm |= (given & 0x000f0000u) >> 4; + func (stream, "#%u\t; 0x%x", imm, imm); + } + break; + + case 'K': + { + unsigned int imm = 0; + imm |= (given & 0x000f0000u) >> 16; + imm |= (given & 0x00000ff0u) >> 0; + imm |= (given & 0x0000000fu) << 12; + func (stream, "#%u\t; 0x%x", imm, imm); + } + break; + + case 'S': + { + unsigned int reg = (given & 0x0000000fu); + unsigned int stp = (given & 0x00000030u) >> 4; + unsigned int imm = 0; + imm |= (given & 0x000000c0u) >> 6; + imm |= (given & 0x00007000u) >> 10; + + func (stream, "%s", arm_regnames[reg]); + switch (stp) + { + case 0: + if (imm > 0) + func (stream, ", lsl #%u", imm); + break; + + case 1: + if (imm == 0) + imm = 32; + func (stream, ", lsr #%u", imm); + break; + + case 2: + if (imm == 0) + imm = 32; + func (stream, ", asr #%u", imm); + break; + + case 3: + if (imm == 0) + func (stream, ", rrx"); + else + func (stream, ", ror #%u", imm); + } + } + break; + + case 'a': + { + unsigned int Rn = (given & 0x000f0000) >> 16; + unsigned int U = (given & 0x00800000) >> 23; + unsigned int op = (given & 0x00000f00) >> 8; + unsigned int i12 = (given & 0x00000fff); + unsigned int i8 = (given & 0x000000ff); + bfd_boolean writeback = FALSE, postind = FALSE; + int offset = 0; + + func (stream, "[%s", arm_regnames[Rn]); + if (U) /* 12-bit positive immediate offset */ + offset = i12; + else if (Rn == 15) /* 12-bit negative immediate offset */ + offset = -(int)i12; + else if (op == 0x0) /* shifted register offset */ + { + unsigned int Rm = (i8 & 0x0f); + unsigned int sh = (i8 & 0x30) >> 4; + func (stream, ", %s", arm_regnames[Rm]); + if (sh) + func (stream, ", lsl #%u", sh); + func (stream, "]"); + break; + } + else switch (op) + { + case 0xE: /* 8-bit positive immediate offset */ + offset = i8; + break; + + case 0xC: /* 8-bit negative immediate offset */ + offset = -i8; + break; + + case 0xF: /* 8-bit + preindex with wb */ + offset = i8; + writeback = TRUE; + break; + + case 0xD: /* 8-bit - preindex with wb */ + offset = -i8; + writeback = TRUE; + break; + + case 0xB: /* 8-bit + postindex */ + offset = i8; + postind = TRUE; + break; + + case 0x9: /* 8-bit - postindex */ + offset = -i8; + postind = TRUE; + break; + + default: + func (stream, ", ]"); + goto skip; + } + + if (postind) + func (stream, "], #%d", offset); + else + { + if (offset) + func (stream, ", #%d", offset); + func (stream, writeback ? "]!" : "]"); + } + + if (Rn == 15) + { + func (stream, "\t; "); + info->print_address_func (((pc + 4) & ~3) + offset, info); + } + } + skip: + break; + + case 'A': + { + unsigned int P = (given & 0x01000000) >> 24; + unsigned int U = (given & 0x00800000) >> 23; + unsigned int W = (given & 0x00400000) >> 21; + unsigned int Rn = (given & 0x000f0000) >> 16; + unsigned int off = (given & 0x000000ff); + + func (stream, "[%s", arm_regnames[Rn]); + if (P) + { + if (off || !U) + func (stream, ", #%c%u", U ? '+' : '-', off * 4); + func (stream, "]"); + if (W) + func (stream, "!"); + } + else + { + func (stream, "], "); + if (W) + func (stream, "#%c%u", U ? '+' : '-', off * 4); + else + func (stream, "{%u}", off); + } + } + break; + + case 'w': + { + unsigned int Sbit = (given & 0x01000000) >> 24; + unsigned int type = (given & 0x00600000) >> 21; + switch (type) + { + case 0: func (stream, Sbit ? "sb" : "b"); break; + case 1: func (stream, Sbit ? "sh" : "h"); break; + case 2: + if (Sbit) + func (stream, "??"); + break; + case 3: + func (stream, "??"); + break; + } + } + break; + + case 'm': + { + int started = 0; + int reg; + + func (stream, "{"); + for (reg = 0; reg < 16; reg++) + if ((given & (1 << reg)) != 0) + { + if (started) + func (stream, ", "); + started = 1; + func (stream, "%s", arm_regnames[reg]); + } + func (stream, "}"); + } + break; + + case 'E': + { + unsigned int msb = (given & 0x0000001f); + unsigned int lsb = 0; + lsb |= (given & 0x000000c0u) >> 6; + lsb |= (given & 0x00007000u) >> 10; + func (stream, "#%u, #%u", lsb, msb - lsb + 1); + } + break; + + case 'F': + { + unsigned int width = (given & 0x0000001f) + 1; + unsigned int lsb = 0; + lsb |= (given & 0x000000c0u) >> 6; + lsb |= (given & 0x00007000u) >> 10; + func (stream, "#%u, #%u", lsb, width); + } + break; + + case 'b': + { + unsigned int S = (given & 0x04000000u) >> 26; + unsigned int J1 = (given & 0x00002000u) >> 13; + unsigned int J2 = (given & 0x00000800u) >> 11; + int offset = 0; + + offset |= !S << 20; + offset |= J2 << 19; + offset |= J1 << 18; + offset |= (given & 0x003f0000) >> 4; + offset |= (given & 0x000007ff) << 1; + offset -= (1 << 20); + + info->print_address_func (pc + 4 + offset, info); + } + break; + + case 'B': + { + unsigned int S = (given & 0x04000000u) >> 26; + unsigned int I1 = (given & 0x00002000u) >> 13; + unsigned int I2 = (given & 0x00000800u) >> 11; + int offset = 0; + + offset |= !S << 24; + offset |= !(I1 ^ S) << 23; + offset |= !(I2 ^ S) << 22; + offset |= (given & 0x03ff0000u) >> 4; + offset |= (given & 0x000007ffu) << 1; + offset -= (1 << 24); + offset += pc + 4; + + /* BLX target addresses are always word aligned. */ + if ((given & 0x00001000u) == 0) + offset &= ~2u; + + info->print_address_func (offset, info); + } + break; + + case 's': + { + unsigned int shift = 0; + shift |= (given & 0x000000c0u) >> 6; + shift |= (given & 0x00007000u) >> 10; + if (given & 0x00200000u) + func (stream, ", asr #%u", shift); + else if (shift) + func (stream, ", lsl #%u", shift); + /* else print nothing - lsl #0 */ + } + break; + + case 'R': + { + unsigned int rot = (given & 0x00000030) >> 4; + if (rot) + func (stream, ", ror #%u", rot * 8); + } + break; + + case 'U': + switch (given & 0xf) + { + case 0xf: func(stream, "sy"); break; + case 0x7: func(stream, "un"); break; + case 0xe: func(stream, "st"); break; + case 0x6: func(stream, "unst"); break; + default: + func(stream, "#%d", (int)given & 0xf); + break; + } + break; + + case 'C': + if ((given & 0xff) == 0) + { + func (stream, "%cPSR_", (given & 0x100000) ? 'S' : 'C'); + if (given & 0x800) + func (stream, "f"); + if (given & 0x400) + func (stream, "s"); + if (given & 0x200) + func (stream, "x"); + if (given & 0x100) + func (stream, "c"); + } + else + { + func (stream, psr_name (given & 0xff)); + } + break; + + case 'D': + if ((given & 0xff) == 0) + func (stream, "%cPSR", (given & 0x100000) ? 'S' : 'C'); + else + func (stream, psr_name (given & 0xff)); + break; + + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + { + int width; + unsigned long val; + + c = arm_decode_bitfield (c, given, &val, &width); + + switch (*c) + { + case 'd': func (stream, "%lu", val); break; + case 'W': func (stream, "%lu", val * 4); break; + case 'r': func (stream, "%s", arm_regnames[val]); break; + + case 'c': + func (stream, "%s", arm_conditional[val]); + break; + + case '\'': + c++; + if (val == ((1ul << width) - 1)) + func (stream, "%c", *c); + break; + + case '`': + c++; + if (val == 0) + func (stream, "%c", *c); + break; + + case '?': + func (stream, "%c", c[(1 << width) - (int)val]); + c += 1 << width; + break; + + default: + abort (); + } + } + break; + + default: + abort (); + } + } + return; + } + + /* No match. */ + abort (); +} + +/* Print data bytes on INFO->STREAM. */ + +static void +print_insn_data (bfd_vma pc ATTRIBUTE_UNUSED, struct disassemble_info *info, + long given) +{ + switch (info->bytes_per_chunk) + { + case 1: + info->fprintf_func (info->stream, ".byte\t0x%02lx", given); + break; + case 2: + info->fprintf_func (info->stream, ".short\t0x%04lx", given); + break; + case 4: + info->fprintf_func (info->stream, ".word\t0x%08lx", given); + break; + default: + abort (); + } +} + +/* Disallow mapping symbols ($a, $b, $d, $t etc) from + being displayed in symbol relative addresses. */ + +bfd_boolean +arm_symbol_is_valid (asymbol * sym, + struct disassemble_info * info ATTRIBUTE_UNUSED) +{ + const char * name; + + if (sym == NULL) + return FALSE; + + name = bfd_asymbol_name (sym); + + return (name && *name != '$'); +} + +/* Parse an individual disassembler option. */ + +void +parse_arm_disassembler_option (char *option) +{ + if (option == NULL) + return; + + if (CONST_STRNEQ (option, "reg-names-")) + { + int i; + + option += 10; + + for (i = NUM_ARM_REGNAMES; i--;) + if (strneq (option, regnames[i].name, strlen (regnames[i].name))) + { + regname_selected = i; + break; + } + + if (i < 0) + /* XXX - should break 'option' at following delimiter. */ + printf (_("Unrecognised register name set: %s\n"), option); + } + else if (CONST_STRNEQ (option, "force-thumb")) + force_thumb = 1; + else if (CONST_STRNEQ (option, "no-force-thumb")) + force_thumb = 0; + else + /* XXX - should break 'option' at following delimiter. */ + printf (_("Unrecognised disassembler option: %s\n"), option); + + return; +} + +/* Parse the string of disassembler options, spliting it at whitespaces + or commas. (Whitespace separators supported for backwards compatibility). */ + +static void +parse_disassembler_options (char *options) +{ + if (options == NULL) + return; + + while (*options) + { + parse_arm_disassembler_option (options); + + /* Skip forward to next seperator. */ + while ((*options) && (! ISSPACE (*options)) && (*options != ',')) + ++ options; + /* Skip forward past seperators. */ + while (ISSPACE (*options) || (*options == ',')) + ++ options; + } +} + +/* Search back through the insn stream to determine if this instruction is + conditionally executed. */ +static void +find_ifthen_state (bfd_vma pc, struct disassemble_info *info, + bfd_boolean little) +{ + unsigned char b[2]; + unsigned int insn; + int status; + /* COUNT is twice the number of instructions seen. It will be odd if we + just crossed an instruction boundary. */ + int count; + int it_count; + unsigned int seen_it; + bfd_vma addr; + + ifthen_address = pc; + ifthen_state = 0; + + addr = pc; + count = 1; + it_count = 0; + seen_it = 0; + /* Scan backwards looking for IT instructions, keeping track of where + instruction boundaries are. We don't know if something is actually an + IT instruction until we find a definite instruction boundary. */ + for (;;) + { + if (addr == 0 || info->symbol_at_address_func(addr, info)) + { + /* A symbol must be on an instruction boundary, and will not + be within an IT block. */ + if (seen_it && (count & 1)) + break; + + return; + } + addr -= 2; + status = info->read_memory_func (addr, (bfd_byte *)b, 2, info); + if (status) + return; + + if (little) + insn = (b[0]) | (b[1] << 8); + else + insn = (b[1]) | (b[0] << 8); + if (seen_it) + { + if ((insn & 0xf800) < 0xe800) + { + /* Addr + 2 is an instruction boundary. See if this matches + the expected boundary based on the position of the last + IT candidate. */ + if (count & 1) + break; + seen_it = 0; + } + } + if ((insn & 0xff00) == 0xbf00 && (insn & 0xf) != 0) + { + /* This could be an IT instruction. */ + seen_it = insn; + it_count = count >> 1; + } + if ((insn & 0xf800) >= 0xe800) + count++; + else + count = (count + 2) | 1; + /* IT blocks contain at most 4 instructions. */ + if (count >= 8 && !seen_it) + return; + } + /* We found an IT instruction. */ + ifthen_state = (seen_it & 0xe0) | ((seen_it << it_count) & 0x1f); + if ((ifthen_state & 0xf) == 0) + ifthen_state = 0; +} + +/* Try to infer the code type (Arm or Thumb) from a symbol. + Returns nonzero if *MAP_TYPE was set. */ + +static int +get_sym_code_type (struct disassemble_info *info, int n, + enum map_type *map_type) +{ + elf_symbol_type *es; + unsigned int type; + const char *name; + + es = *(elf_symbol_type **)(info->symtab + n); + type = ELF_ST_TYPE (es->internal_elf_sym.st_info); + + /* If the symbol has function type then use that. */ + if (type == STT_FUNC || type == STT_ARM_TFUNC) + { + *map_type = (type == STT_ARM_TFUNC) ? MAP_THUMB : MAP_ARM; + return TRUE; + } + + /* Check for mapping symbols. */ + name = bfd_asymbol_name(info->symtab[n]); + if (name[0] == '$' && (name[1] == 'a' || name[1] == 't' || name[1] == 'd') + && (name[2] == 0 || name[2] == '.')) + { + *map_type = ((name[1] == 'a') ? MAP_ARM + : (name[1] == 't') ? MAP_THUMB + : MAP_DATA); + return TRUE; + } + + return FALSE; +} + +/* NOTE: There are no checks in these routines that + the relevant number of data bytes exist. */ + +static int +print_insn (bfd_vma pc, struct disassemble_info *info, bfd_boolean little) +{ + unsigned char b[4]; + long given; + int status; + int is_thumb = FALSE; + int is_data = FALSE; + unsigned int size = 4; + void (*printer) (bfd_vma, struct disassemble_info *, long); + bfd_boolean found = FALSE; + + if (info->disassembler_options) + { + parse_disassembler_options (info->disassembler_options); + + /* To avoid repeated parsing of these options, we remove them here. */ + info->disassembler_options = NULL; + } + + /* First check the full symtab for a mapping symbol, even if there + are no usable non-mapping symbols for this address. */ + if (info->symtab != NULL + && bfd_asymbol_flavour (*info->symtab) == bfd_target_elf_flavour) + { + bfd_vma addr; + int n; + int last_sym = -1; + enum map_type type = MAP_ARM; + + if (pc <= last_mapping_addr) + last_mapping_sym = -1; + is_thumb = (last_type == MAP_THUMB); + found = FALSE; + /* Start scanning at the start of the function, or wherever + we finished last time. */ + n = info->symtab_pos + 1; + if (n < last_mapping_sym) + n = last_mapping_sym; + + /* Scan up to the location being disassembled. */ + for (; n < info->symtab_size; n++) + { + addr = bfd_asymbol_value (info->symtab[n]); + if (addr > pc) + break; + if ((info->section == NULL + || info->section == info->symtab[n]->section) + && get_sym_code_type (info, n, &type)) + { + last_sym = n; + found = TRUE; + } + } + + if (!found) + { + n = info->symtab_pos; + if (n < last_mapping_sym - 1) + n = last_mapping_sym - 1; + + /* No mapping symbol found at this address. Look backwards + for a preceeding one. */ + for (; n >= 0; n--) + { + if (get_sym_code_type (info, n, &type)) + { + last_sym = n; + found = TRUE; + break; + } + } + } + + last_mapping_sym = last_sym; + last_type = type; + is_thumb = (last_type == MAP_THUMB); + is_data = (last_type == MAP_DATA); + + /* Look a little bit ahead to see if we should print out + two or four bytes of data. If there's a symbol, + mapping or otherwise, after two bytes then don't + print more. */ + if (is_data) + { + size = 4 - (pc & 3); + for (n = last_sym + 1; n < info->symtab_size; n++) + { + addr = bfd_asymbol_value (info->symtab[n]); + if (addr > pc) + { + if (addr - pc < size) + size = addr - pc; + break; + } + } + /* If the next symbol is after three bytes, we need to + print only part of the data, so that we can use either + .byte or .short. */ + if (size == 3) + size = (pc & 1) ? 1 : 2; + } + } + + if (info->symbols != NULL) + { + if (bfd_asymbol_flavour (*info->symbols) == bfd_target_coff_flavour) + { +#if 0 + coff_symbol_type * cs; + + cs = coffsymbol (*info->symbols); + is_thumb = ( cs->native->u.syment.n_sclass == C_THUMBEXT + || cs->native->u.syment.n_sclass == C_THUMBSTAT + || cs->native->u.syment.n_sclass == C_THUMBLABEL + || cs->native->u.syment.n_sclass == C_THUMBEXTFUNC + || cs->native->u.syment.n_sclass == C_THUMBSTATFUNC); +#endif + } + else if (bfd_asymbol_flavour (*info->symbols) == bfd_target_elf_flavour + && !found) + { + /* If no mapping symbol has been found then fall back to the type + of the function symbol. */ + elf_symbol_type * es; + unsigned int type; + + es = *(elf_symbol_type **)(info->symbols); + type = ELF_ST_TYPE (es->internal_elf_sym.st_info); + + is_thumb = (type == STT_ARM_TFUNC) || (type == STT_ARM_16BIT); + } + } + + if (force_thumb) + is_thumb = TRUE; + + info->display_endian = little ? BFD_ENDIAN_LITTLE : BFD_ENDIAN_BIG; + info->bytes_per_line = 4; + + if (is_data) + { + int i; + + /* size was already set above. */ + info->bytes_per_chunk = size; + printer = print_insn_data; + + status = info->read_memory_func (pc, (bfd_byte *)b, size, info); + given = 0; + if (little) + for (i = size - 1; i >= 0; i--) + given = b[i] | (given << 8); + else + for (i = 0; i < (int) size; i++) + given = b[i] | (given << 8); + } + else if (!is_thumb) + { + /* In ARM mode endianness is a straightforward issue: the instruction + is four bytes long and is either ordered 0123 or 3210. */ + printer = print_insn_arm; + info->bytes_per_chunk = 4; + size = 4; + + status = info->read_memory_func (pc, (bfd_byte *)b, 4, info); + if (little) + given = (b[0]) | (b[1] << 8) | (b[2] << 16) | (b[3] << 24); + else + given = (b[3]) | (b[2] << 8) | (b[1] << 16) | (b[0] << 24); + } + else + { + /* In Thumb mode we have the additional wrinkle of two + instruction lengths. Fortunately, the bits that determine + the length of the current instruction are always to be found + in the first two bytes. */ + printer = print_insn_thumb16; + info->bytes_per_chunk = 2; + size = 2; + + status = info->read_memory_func (pc, (bfd_byte *)b, 2, info); + if (little) + given = (b[0]) | (b[1] << 8); + else + given = (b[1]) | (b[0] << 8); + + if (!status) + { + /* These bit patterns signal a four-byte Thumb + instruction. */ + if ((given & 0xF800) == 0xF800 + || (given & 0xF800) == 0xF000 + || (given & 0xF800) == 0xE800) + { + status = info->read_memory_func (pc + 2, (bfd_byte *)b, 2, info); + if (little) + given = (b[0]) | (b[1] << 8) | (given << 16); + else + given = (b[1]) | (b[0] << 8) | (given << 16); + + printer = print_insn_thumb32; + size = 4; + } + } + + if (ifthen_address != pc) + find_ifthen_state(pc, info, little); + + if (ifthen_state) + { + if ((ifthen_state & 0xf) == 0x8) + ifthen_next_state = 0; + else + ifthen_next_state = (ifthen_state & 0xe0) + | ((ifthen_state & 0xf) << 1); + } + } + + if (status) + { + info->memory_error_func (status, pc, info); + return -1; + } + if (info->flags & INSN_HAS_RELOC) + /* If the instruction has a reloc associated with it, then + the offset field in the instruction will actually be the + addend for the reloc. (We are using REL type relocs). + In such cases, we can ignore the pc when computing + addresses, since the addend is not currently pc-relative. */ + pc = 0; + + printer (pc, info, given); + + if (is_thumb) + { + ifthen_state = ifthen_next_state; + ifthen_address += size; + } + return size; +} + +int +print_insn_big_arm (bfd_vma pc, struct disassemble_info *info) +{ + return print_insn (pc, info, FALSE); +} + +int +print_insn_little_arm (bfd_vma pc, struct disassemble_info *info) +{ + return print_insn (pc, info, TRUE); +} + +void +print_arm_disassembler_options (FILE * stream __attribute__((unused))) +{ + int i; + + printf (_("\n\ +The following ARM specific disassembler options are supported for use with\n\ +the -M switch:\n")); + + for (i = NUM_ARM_REGNAMES; i--;) + printf (" reg-names-%s %*c%s\n", + regnames[i].name, + (int)(14 - strlen (regnames[i].name)), ' ', + regnames[i].description); + + printf (" force-thumb Assume all insns are Thumb insns\n"); + printf (" no-force-thumb Examine preceeding label to determine an insn's type\n\n"); +} diff --git a/kernel/fiasco/src/lib/disasm/opcodes/dis-buf.c b/kernel/fiasco/src/lib/disasm/opcodes/dis-buf.c new file mode 100644 index 00000000..6a317724 --- /dev/null +++ b/kernel/fiasco/src/lib/disasm/opcodes/dis-buf.c @@ -0,0 +1,104 @@ +/* Disassemble from a buffer, for GNU. + Copyright 1993, 1994, 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2005, + 2007 Free Software Foundation, Inc. + + This file is part of the GNU opcodes library. + + This library is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + It is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + MA 02110-1301, USA. */ + +#include "sysdep.h" +#include "dis-asm.h" +#include +#include "opintl.h" + +/* Get LENGTH bytes from info's buffer, at target address memaddr. + Transfer them to myaddr. */ +int +buffer_read_memory (bfd_vma memaddr, + bfd_byte *myaddr, + unsigned int length, + struct disassemble_info *info) +{ + unsigned int opb = info->octets_per_byte; + unsigned int end_addr_offset = length / opb; + unsigned int max_addr_offset = info->buffer_length / opb; + unsigned int octets = (memaddr - info->buffer_vma) * opb; + + if (memaddr < info->buffer_vma + || memaddr - info->buffer_vma + end_addr_offset > max_addr_offset) + /* Out of bounds. Use EIO because GDB uses it. */ + return EIO; + memcpy (myaddr, info->buffer + octets, length); + + return 0; +} + +/* Print an error message. We can assume that this is in response to + an error return from buffer_read_memory. */ + +void +perror_memory (int status, + bfd_vma memaddr, + struct disassemble_info *info) +{ + if (status != EIO) + /* Can't happen. */ + info->fprintf_func (info->stream, _("Unknown error %d\n"), status); + else + { + char buf[30]; + + /* Actually, address between memaddr and memaddr + len was + out of bounds. */ + sprintf_vma (buf, memaddr); + info->fprintf_func (info->stream, + _("Address 0x%s is out of bounds.\n"), buf); + } +} + +/* This could be in a separate file, to save miniscule amounts of space + in statically linked executables. */ + +/* Just print the address is hex. This is included for completeness even + though both GDB and objdump provide their own (to print symbolic + addresses). */ + +void +generic_print_address (bfd_vma addr, struct disassemble_info *info) +{ + char buf[30]; + + sprintf_vma (buf, addr); + (*info->fprintf_func) (info->stream, "0x%s", buf); +} + +/* Just return true. */ + +int +generic_symbol_at_address (bfd_vma addr ATTRIBUTE_UNUSED, + struct disassemble_info *info ATTRIBUTE_UNUSED) +{ + return 1; +} + +/* Just return TRUE. */ + +bfd_boolean +generic_symbol_is_valid (asymbol * sym ATTRIBUTE_UNUSED, + struct disassemble_info *info ATTRIBUTE_UNUSED) +{ + return TRUE; +} diff --git a/kernel/fiasco/src/lib/disasm/opcodes/dis-init.c b/kernel/fiasco/src/lib/disasm/opcodes/dis-init.c new file mode 100644 index 00000000..dff91eb3 --- /dev/null +++ b/kernel/fiasco/src/lib/disasm/opcodes/dis-init.c @@ -0,0 +1,45 @@ +/* Initialize "struct disassemble_info". + + Copyright 2003, 2007 Free Software Foundation, Inc. + + This file is part of the GNU opcodes library. + + This library is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + It is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA + 02110-1301, USA. */ + +#include "sysdep.h" +#include "dis-asm.h" +#include "bfd.h" + +void +init_disassemble_info (struct disassemble_info *info, void *stream, + fprintf_ftype fprintf_func) +{ + memset (info, 0, sizeof (*info)); + + info->flavour = bfd_target_unknown_flavour; + info->arch = bfd_arch_unknown; + info->endian = BFD_ENDIAN_UNKNOWN; + info->octets_per_byte = 1; + info->fprintf_func = fprintf_func; + info->stream = stream; + info->read_memory_func = buffer_read_memory; + info->memory_error_func = perror_memory; + info->print_address_func = generic_print_address; + info->symbol_at_address_func = generic_symbol_at_address; + info->symbol_is_valid = generic_symbol_is_valid; + info->display_endian = BFD_ENDIAN_UNKNOWN; +} + diff --git a/kernel/fiasco/src/lib/disasm/opcodes/i386-dis.c b/kernel/fiasco/src/lib/disasm/opcodes/i386-dis.c new file mode 100644 index 00000000..b01615a6 --- /dev/null +++ b/kernel/fiasco/src/lib/disasm/opcodes/i386-dis.c @@ -0,0 +1,4565 @@ +/* Print i386 instructions for GDB, the GNU debugger. + Copyright 1988, 1989, 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999, + 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* 80386 instruction printer by Pace Willisson (pace@prep.ai.mit.edu) + July 1988 + modified by John Hassey (hassey@dg-rtp.dg.com) + x86-64 support added by Jan Hubicka (jh@suse.cz) + VIA PadLock support by Michal Ludvig (mludvig@suse.cz). */ + +/* The main tables describing the instructions is essentially a copy + of the "Opcode Map" chapter (Appendix A) of the Intel 80386 + Programmers Manual. Usually, there is a capital letter, followed + by a small letter. The capital letter tell the addressing mode, + and the small letter tells about the operand size. Refer to + the Intel manual for details. */ + +#include "dis-asm.h" +#include "sysdep.h" +#include "opintl.h" + +#define MAXLEN 20 + +#include + +#ifndef UNIXWARE_COMPAT +/* Set non-zero for broken, compatible instructions. Set to zero for + non-broken opcodes. */ +#define UNIXWARE_COMPAT 1 +#endif + +static int fetch_data (struct disassemble_info *, bfd_byte *); +static void ckprefix (void); +static const char *prefix_name (int, int); +static int print_insn (bfd_vma, disassemble_info *); +static void dofloat (int); +static void OP_ST (int, int); +static void OP_STi (int, int); +static int putop (const char *, int); +static void oappend (const char *); +static void append_seg (void); +static void OP_indirE (int, int); +static void print_operand_value (char *, int, bfd_vma); +static void OP_E (int, int); +static void OP_G (int, int); +static bfd_vma get64 (void); +static bfd_signed_vma get32 (void); +static bfd_signed_vma get32s (void); +static int get16 (void); +static void set_op (bfd_vma, int); +static void OP_REG (int, int); +static void OP_IMREG (int, int); +static void OP_I (int, int); +static void OP_I64 (int, int); +static void OP_sI (int, int); +static void OP_J (int, int); +static void OP_SEG (int, int); +static void OP_DIR (int, int); +static void OP_OFF (int, int); +static void OP_OFF64 (int, int); +static void ptr_reg (int, int); +static void OP_ESreg (int, int); +static void OP_DSreg (int, int); +static void OP_C (int, int); +static void OP_D (int, int); +static void OP_T (int, int); +static void OP_Rd (int, int); +static void OP_MMX (int, int); +static void OP_XMM (int, int); +static void OP_EM (int, int); +static void OP_EX (int, int); +static void OP_MS (int, int); +static void OP_XS (int, int); +static void OP_M (int, int); +static void OP_0fae (int, int); +static void OP_0f07 (int, int); +static void NOP_Fixup (int, int); +static void OP_3DNowSuffix (int, int); +static void OP_SIMD_Suffix (int, int); +static void SIMD_Fixup (int, int); +static void PNI_Fixup (int, int); +static void INVLPG_Fixup (int, int); +static void BadOp (void); + +struct dis_private { + /* Points to first byte not fetched. */ + bfd_byte *max_fetched; + bfd_byte the_buffer[MAXLEN]; + bfd_vma insn_start; + int orig_sizeflag; + jmp_buf bailout; +}; + +/* The opcode for the fwait instruction, which we treat as a prefix + when we can. */ +#define FWAIT_OPCODE (0x9b) + +/* Set to 1 for 64bit mode disassembly. */ +static int mode_64bit; + +/* Flags for the prefixes for the current instruction. See below. */ +static int prefixes; + +/* REX prefix the current instruction. See below. */ +static int rex; +/* Bits of REX we've already used. */ +static int rex_used; +#define REX_MODE64 8 +#define REX_EXTX 4 +#define REX_EXTY 2 +#define REX_EXTZ 1 +/* Mark parts used in the REX prefix. When we are testing for + empty prefix (for 8bit register REX extension), just mask it + out. Otherwise test for REX bit is excuse for existence of REX + only in case value is nonzero. */ +#define USED_REX(value) \ + { \ + if (value) \ + rex_used |= (rex & value) ? (value) | 0x40 : 0; \ + else \ + rex_used |= 0x40; \ + } + +/* Flags for prefixes which we somehow handled when printing the + current instruction. */ +static int used_prefixes; + +/* Flags stored in PREFIXES. */ +#define PREFIX_REPZ 1 +#define PREFIX_REPNZ 2 +#define PREFIX_LOCK 4 +#define PREFIX_CS 8 +#define PREFIX_SS 0x10 +#define PREFIX_DS 0x20 +#define PREFIX_ES 0x40 +#define PREFIX_FS 0x80 +#define PREFIX_GS 0x100 +#define PREFIX_DATA 0x200 +#define PREFIX_ADDR 0x400 +#define PREFIX_FWAIT 0x800 + +/* Make sure that bytes from INFO->PRIVATE_DATA->BUFFER (inclusive) + to ADDR (exclusive) are valid. Returns 1 for success, longjmps + on error. */ +#define FETCH_DATA(info, addr) \ + ((addr) <= ((struct dis_private *) (info->private_data))->max_fetched \ + ? 1 : fetch_data ((info), (addr))) + +static int +fetch_data (struct disassemble_info *info, bfd_byte *addr) +{ + int status; + struct dis_private *priv = (struct dis_private *) info->private_data; + bfd_vma start = priv->insn_start + (priv->max_fetched - priv->the_buffer); + + status = (*info->read_memory_func) (start, + priv->max_fetched, + addr - priv->max_fetched, + info); + if (status != 0) + { + /* If we did manage to read at least one byte, then + print_insn_i386 will do something sensible. Otherwise, print + an error. We do that here because this is where we know + STATUS. */ + if (priv->max_fetched == priv->the_buffer) + (*info->memory_error_func) (status, start, info); + longjmp (priv->bailout, 1); + } + else + priv->max_fetched = addr; + return 1; +} + +#define XX NULL, 0 + +#define Eb OP_E, b_mode +#define Ev OP_E, v_mode +#define Ed OP_E, d_mode +#define Eq OP_E, q_mode +#define Edq OP_E, dq_mode +#define Edqw OP_E, dqw_mode +#define indirEv OP_indirE, v_mode +#define indirEp OP_indirE, f_mode +#define Ew OP_E, w_mode +#define Ma OP_E, v_mode +#define M OP_M, 0 /* lea, lgdt, etc. */ +#define Mp OP_M, f_mode /* 32 or 48 bit memory operand for LDS, LES etc */ +#define Gb OP_G, b_mode +#define Gv OP_G, v_mode +#define Gd OP_G, d_mode +#define Gdq OP_G, dq_mode +#define Gw OP_G, w_mode +#define Rd OP_Rd, d_mode +#define Rm OP_Rd, m_mode +#define Ib OP_I, b_mode +#define sIb OP_sI, b_mode /* sign extened byte */ +#define Iv OP_I, v_mode +#define Iq OP_I, q_mode +#define Iv64 OP_I64, v_mode +#define Iw OP_I, w_mode +#define I1 OP_I, const_1_mode +#define Jb OP_J, b_mode +#define Jv OP_J, v_mode +#define Cm OP_C, m_mode +#define Dm OP_D, m_mode +#define Td OP_T, d_mode + +#define RMeAX OP_REG, eAX_reg +#define RMeBX OP_REG, eBX_reg +#define RMeCX OP_REG, eCX_reg +#define RMeDX OP_REG, eDX_reg +#define RMeSP OP_REG, eSP_reg +#define RMeBP OP_REG, eBP_reg +#define RMeSI OP_REG, eSI_reg +#define RMeDI OP_REG, eDI_reg +#define RMrAX OP_REG, rAX_reg +#define RMrBX OP_REG, rBX_reg +#define RMrCX OP_REG, rCX_reg +#define RMrDX OP_REG, rDX_reg +#define RMrSP OP_REG, rSP_reg +#define RMrBP OP_REG, rBP_reg +#define RMrSI OP_REG, rSI_reg +#define RMrDI OP_REG, rDI_reg +#define RMAL OP_REG, al_reg +#define RMAL OP_REG, al_reg +#define RMCL OP_REG, cl_reg +#define RMDL OP_REG, dl_reg +#define RMBL OP_REG, bl_reg +#define RMAH OP_REG, ah_reg +#define RMCH OP_REG, ch_reg +#define RMDH OP_REG, dh_reg +#define RMBH OP_REG, bh_reg +#define RMAX OP_REG, ax_reg +#define RMDX OP_REG, dx_reg + +#define eAX OP_IMREG, eAX_reg +#define eBX OP_IMREG, eBX_reg +#define eCX OP_IMREG, eCX_reg +#define eDX OP_IMREG, eDX_reg +#define eSP OP_IMREG, eSP_reg +#define eBP OP_IMREG, eBP_reg +#define eSI OP_IMREG, eSI_reg +#define eDI OP_IMREG, eDI_reg +#define AL OP_IMREG, al_reg +#define AL OP_IMREG, al_reg +#define CL OP_IMREG, cl_reg +#define DL OP_IMREG, dl_reg +#define BL OP_IMREG, bl_reg +#define AH OP_IMREG, ah_reg +#define CH OP_IMREG, ch_reg +#define DH OP_IMREG, dh_reg +#define BH OP_IMREG, bh_reg +#define AX OP_IMREG, ax_reg +#define DX OP_IMREG, dx_reg +#define indirDX OP_IMREG, indir_dx_reg + +#define Sw OP_SEG, w_mode +#define Ap OP_DIR, 0 +#define Ob OP_OFF, b_mode +#define Ob64 OP_OFF64, b_mode +#define Ov OP_OFF, v_mode +#define Ov64 OP_OFF64, v_mode +#define Xb OP_DSreg, eSI_reg +#define Xv OP_DSreg, eSI_reg +#define Yb OP_ESreg, eDI_reg +#define Yv OP_ESreg, eDI_reg +#define DSBX OP_DSreg, eBX_reg + +#define es OP_REG, es_reg +#define ss OP_REG, ss_reg +#define cs OP_REG, cs_reg +#define ds OP_REG, ds_reg +#define fs OP_REG, fs_reg +#define gs OP_REG, gs_reg + +#define MX OP_MMX, 0 +#define XM OP_XMM, 0 +#define EM OP_EM, v_mode +#define EX OP_EX, v_mode +#define MS OP_MS, v_mode +#define XS OP_XS, v_mode +#define OPSUF OP_3DNowSuffix, 0 +#define OPSIMD OP_SIMD_Suffix, 0 + +#define cond_jump_flag NULL, cond_jump_mode +#define loop_jcxz_flag NULL, loop_jcxz_mode + +/* bits in sizeflag */ +#define SUFFIX_ALWAYS 4 +#define AFLAG 2 +#define DFLAG 1 + +#define b_mode 1 /* byte operand */ +#define v_mode 2 /* operand size depends on prefixes */ +#define w_mode 3 /* word operand */ +#define d_mode 4 /* double word operand */ +#define q_mode 5 /* quad word operand */ +#define t_mode 6 /* ten-byte operand */ +#define x_mode 7 /* 16-byte XMM operand */ +#define m_mode 8 /* d_mode in 32bit, q_mode in 64bit mode. */ +#define cond_jump_mode 9 +#define loop_jcxz_mode 10 +#define dq_mode 11 /* operand size depends on REX prefixes. */ +#define dqw_mode 12 /* registers like dq_mode, memory like w_mode. */ +#define f_mode 13 /* 4- or 6-byte pointer operand */ +#define const_1_mode 14 + +#define es_reg 100 +#define cs_reg 101 +#define ss_reg 102 +#define ds_reg 103 +#define fs_reg 104 +#define gs_reg 105 + +#define eAX_reg 108 +#define eCX_reg 109 +#define eDX_reg 110 +#define eBX_reg 111 +#define eSP_reg 112 +#define eBP_reg 113 +#define eSI_reg 114 +#define eDI_reg 115 + +#define al_reg 116 +#define cl_reg 117 +#define dl_reg 118 +#define bl_reg 119 +#define ah_reg 120 +#define ch_reg 121 +#define dh_reg 122 +#define bh_reg 123 + +#define ax_reg 124 +#define cx_reg 125 +#define dx_reg 126 +#define bx_reg 127 +#define sp_reg 128 +#define bp_reg 129 +#define si_reg 130 +#define di_reg 131 + +#define rAX_reg 132 +#define rCX_reg 133 +#define rDX_reg 134 +#define rBX_reg 135 +#define rSP_reg 136 +#define rBP_reg 137 +#define rSI_reg 138 +#define rDI_reg 139 + +#define indir_dx_reg 150 + +#define FLOATCODE 1 +#define USE_GROUPS 2 +#define USE_PREFIX_USER_TABLE 3 +#define X86_64_SPECIAL 4 + +#define FLOAT NULL, NULL, FLOATCODE, NULL, 0, NULL, 0 + +#define GRP1b NULL, NULL, USE_GROUPS, NULL, 0, NULL, 0 +#define GRP1S NULL, NULL, USE_GROUPS, NULL, 1, NULL, 0 +#define GRP1Ss NULL, NULL, USE_GROUPS, NULL, 2, NULL, 0 +#define GRP2b NULL, NULL, USE_GROUPS, NULL, 3, NULL, 0 +#define GRP2S NULL, NULL, USE_GROUPS, NULL, 4, NULL, 0 +#define GRP2b_one NULL, NULL, USE_GROUPS, NULL, 5, NULL, 0 +#define GRP2S_one NULL, NULL, USE_GROUPS, NULL, 6, NULL, 0 +#define GRP2b_cl NULL, NULL, USE_GROUPS, NULL, 7, NULL, 0 +#define GRP2S_cl NULL, NULL, USE_GROUPS, NULL, 8, NULL, 0 +#define GRP3b NULL, NULL, USE_GROUPS, NULL, 9, NULL, 0 +#define GRP3S NULL, NULL, USE_GROUPS, NULL, 10, NULL, 0 +#define GRP4 NULL, NULL, USE_GROUPS, NULL, 11, NULL, 0 +#define GRP5 NULL, NULL, USE_GROUPS, NULL, 12, NULL, 0 +#define GRP6 NULL, NULL, USE_GROUPS, NULL, 13, NULL, 0 +#define GRP7 NULL, NULL, USE_GROUPS, NULL, 14, NULL, 0 +#define GRP8 NULL, NULL, USE_GROUPS, NULL, 15, NULL, 0 +#define GRP9 NULL, NULL, USE_GROUPS, NULL, 16, NULL, 0 +#define GRP10 NULL, NULL, USE_GROUPS, NULL, 17, NULL, 0 +#define GRP11 NULL, NULL, USE_GROUPS, NULL, 18, NULL, 0 +#define GRP12 NULL, NULL, USE_GROUPS, NULL, 19, NULL, 0 +#define GRP13 NULL, NULL, USE_GROUPS, NULL, 20, NULL, 0 +#define GRP14 NULL, NULL, USE_GROUPS, NULL, 21, NULL, 0 +#define GRPAMD NULL, NULL, USE_GROUPS, NULL, 22, NULL, 0 +#define GRPPADLCK1 NULL, NULL, USE_GROUPS, NULL, 23, NULL, 0 +#define GRPPADLCK2 NULL, NULL, USE_GROUPS, NULL, 24, NULL, 0 + +#define PREGRP0 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 0, NULL, 0 +#define PREGRP1 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 1, NULL, 0 +#define PREGRP2 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 2, NULL, 0 +#define PREGRP3 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 3, NULL, 0 +#define PREGRP4 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 4, NULL, 0 +#define PREGRP5 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 5, NULL, 0 +#define PREGRP6 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 6, NULL, 0 +#define PREGRP7 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 7, NULL, 0 +#define PREGRP8 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 8, NULL, 0 +#define PREGRP9 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 9, NULL, 0 +#define PREGRP10 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 10, NULL, 0 +#define PREGRP11 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 11, NULL, 0 +#define PREGRP12 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 12, NULL, 0 +#define PREGRP13 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 13, NULL, 0 +#define PREGRP14 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 14, NULL, 0 +#define PREGRP15 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 15, NULL, 0 +#define PREGRP16 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 16, NULL, 0 +#define PREGRP17 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 17, NULL, 0 +#define PREGRP18 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 18, NULL, 0 +#define PREGRP19 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 19, NULL, 0 +#define PREGRP20 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 20, NULL, 0 +#define PREGRP21 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 21, NULL, 0 +#define PREGRP22 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 22, NULL, 0 +#define PREGRP23 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 23, NULL, 0 +#define PREGRP24 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 24, NULL, 0 +#define PREGRP25 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 25, NULL, 0 +#define PREGRP26 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 26, NULL, 0 +#define PREGRP27 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 27, NULL, 0 +#define PREGRP28 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 28, NULL, 0 +#define PREGRP29 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 29, NULL, 0 +#define PREGRP30 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 30, NULL, 0 +#define PREGRP31 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 31, NULL, 0 +#define PREGRP32 NULL, NULL, USE_PREFIX_USER_TABLE, NULL, 32, NULL, 0 + +#define X86_64_0 NULL, NULL, X86_64_SPECIAL, NULL, 0, NULL, 0 + +typedef void (*op_rtn) (int bytemode, int sizeflag); + +struct dis386 { + const char *name; + op_rtn op1; + int bytemode1; + op_rtn op2; + int bytemode2; + op_rtn op3; + int bytemode3; +}; + +/* Upper case letters in the instruction names here are macros. + 'A' => print 'b' if no register operands or suffix_always is true + 'B' => print 'b' if suffix_always is true + 'C' => print 's' or 'l' ('w' or 'd' in Intel mode) depending on operand + . size prefix + 'E' => print 'e' if 32-bit form of jcxz + 'F' => print 'w' or 'l' depending on address size prefix (loop insns) + 'H' => print ",pt" or ",pn" branch hint + 'I' => honor following macro letter even in Intel mode (implemented only + . for some of the macro letters) + 'J' => print 'l' + 'L' => print 'l' if suffix_always is true + 'N' => print 'n' if instruction has no wait "prefix" + 'O' => print 'd', or 'o' + 'P' => print 'w', 'l' or 'q' if instruction has an operand size prefix, + . or suffix_always is true. print 'q' if rex prefix is present. + 'Q' => print 'w', 'l' or 'q' if no register operands or suffix_always + . is true + 'R' => print 'w', 'l' or 'q' ("wd" or "dq" in intel mode) + 'S' => print 'w', 'l' or 'q' if suffix_always is true + 'T' => print 'q' in 64bit mode and behave as 'P' otherwise + 'U' => print 'q' in 64bit mode and behave as 'Q' otherwise + 'W' => print 'b' or 'w' ("w" or "de" in intel mode) + 'X' => print 's', 'd' depending on data16 prefix (for XMM) + 'Y' => 'q' if instruction has an REX 64bit overwrite prefix + + Many of the above letters print nothing in Intel mode. See "putop" + for the details. + + Braces '{' and '}', and vertical bars '|', indicate alternative + mnemonic strings for AT&T, Intel, X86_64 AT&T, and X86_64 Intel + modes. In cases where there are only two alternatives, the X86_64 + instruction is reserved, and "(bad)" is printed. +*/ + +static const struct dis386 dis386[] = { + /* 00 */ + { "addB", Eb, Gb, XX }, + { "addS", Ev, Gv, XX }, + { "addB", Gb, Eb, XX }, + { "addS", Gv, Ev, XX }, + { "addB", AL, Ib, XX }, + { "addS", eAX, Iv, XX }, + { "push{T|}", es, XX, XX }, + { "pop{T|}", es, XX, XX }, + /* 08 */ + { "orB", Eb, Gb, XX }, + { "orS", Ev, Gv, XX }, + { "orB", Gb, Eb, XX }, + { "orS", Gv, Ev, XX }, + { "orB", AL, Ib, XX }, + { "orS", eAX, Iv, XX }, + { "push{T|}", cs, XX, XX }, + { "(bad)", XX, XX, XX }, /* 0x0f extended opcode escape */ + /* 10 */ + { "adcB", Eb, Gb, XX }, + { "adcS", Ev, Gv, XX }, + { "adcB", Gb, Eb, XX }, + { "adcS", Gv, Ev, XX }, + { "adcB", AL, Ib, XX }, + { "adcS", eAX, Iv, XX }, + { "push{T|}", ss, XX, XX }, + { "popT|}", ss, XX, XX }, + /* 18 */ + { "sbbB", Eb, Gb, XX }, + { "sbbS", Ev, Gv, XX }, + { "sbbB", Gb, Eb, XX }, + { "sbbS", Gv, Ev, XX }, + { "sbbB", AL, Ib, XX }, + { "sbbS", eAX, Iv, XX }, + { "push{T|}", ds, XX, XX }, + { "pop{T|}", ds, XX, XX }, + /* 20 */ + { "andB", Eb, Gb, XX }, + { "andS", Ev, Gv, XX }, + { "andB", Gb, Eb, XX }, + { "andS", Gv, Ev, XX }, + { "andB", AL, Ib, XX }, + { "andS", eAX, Iv, XX }, + { "(bad)", XX, XX, XX }, /* SEG ES prefix */ + { "daa{|}", XX, XX, XX }, + /* 28 */ + { "subB", Eb, Gb, XX }, + { "subS", Ev, Gv, XX }, + { "subB", Gb, Eb, XX }, + { "subS", Gv, Ev, XX }, + { "subB", AL, Ib, XX }, + { "subS", eAX, Iv, XX }, + { "(bad)", XX, XX, XX }, /* SEG CS prefix */ + { "das{|}", XX, XX, XX }, + /* 30 */ + { "xorB", Eb, Gb, XX }, + { "xorS", Ev, Gv, XX }, + { "xorB", Gb, Eb, XX }, + { "xorS", Gv, Ev, XX }, + { "xorB", AL, Ib, XX }, + { "xorS", eAX, Iv, XX }, + { "(bad)", XX, XX, XX }, /* SEG SS prefix */ + { "aaa{|}", XX, XX, XX }, + /* 38 */ + { "cmpB", Eb, Gb, XX }, + { "cmpS", Ev, Gv, XX }, + { "cmpB", Gb, Eb, XX }, + { "cmpS", Gv, Ev, XX }, + { "cmpB", AL, Ib, XX }, + { "cmpS", eAX, Iv, XX }, + { "(bad)", XX, XX, XX }, /* SEG DS prefix */ + { "aas{|}", XX, XX, XX }, + /* 40 */ + { "inc{S|}", RMeAX, XX, XX }, + { "inc{S|}", RMeCX, XX, XX }, + { "inc{S|}", RMeDX, XX, XX }, + { "inc{S|}", RMeBX, XX, XX }, + { "inc{S|}", RMeSP, XX, XX }, + { "inc{S|}", RMeBP, XX, XX }, + { "inc{S|}", RMeSI, XX, XX }, + { "inc{S|}", RMeDI, XX, XX }, + /* 48 */ + { "dec{S|}", RMeAX, XX, XX }, + { "dec{S|}", RMeCX, XX, XX }, + { "dec{S|}", RMeDX, XX, XX }, + { "dec{S|}", RMeBX, XX, XX }, + { "dec{S|}", RMeSP, XX, XX }, + { "dec{S|}", RMeBP, XX, XX }, + { "dec{S|}", RMeSI, XX, XX }, + { "dec{S|}", RMeDI, XX, XX }, + /* 50 */ + { "pushS", RMrAX, XX, XX }, + { "pushS", RMrCX, XX, XX }, + { "pushS", RMrDX, XX, XX }, + { "pushS", RMrBX, XX, XX }, + { "pushS", RMrSP, XX, XX }, + { "pushS", RMrBP, XX, XX }, + { "pushS", RMrSI, XX, XX }, + { "pushS", RMrDI, XX, XX }, + /* 58 */ + { "popS", RMrAX, XX, XX }, + { "popS", RMrCX, XX, XX }, + { "popS", RMrDX, XX, XX }, + { "popS", RMrBX, XX, XX }, + { "popS", RMrSP, XX, XX }, + { "popS", RMrBP, XX, XX }, + { "popS", RMrSI, XX, XX }, + { "popS", RMrDI, XX, XX }, + /* 60 */ + { "pusha{P|}", XX, XX, XX }, + { "popa{P|}", XX, XX, XX }, + { "bound{S|}", Gv, Ma, XX }, + { X86_64_0 }, + { "(bad)", XX, XX, XX }, /* seg fs */ + { "(bad)", XX, XX, XX }, /* seg gs */ + { "(bad)", XX, XX, XX }, /* op size prefix */ + { "(bad)", XX, XX, XX }, /* adr size prefix */ + /* 68 */ + { "pushT", Iq, XX, XX }, + { "imulS", Gv, Ev, Iv }, + { "pushT", sIb, XX, XX }, + { "imulS", Gv, Ev, sIb }, + { "ins{b||b|}", Yb, indirDX, XX }, + { "ins{R||R|}", Yv, indirDX, XX }, + { "outs{b||b|}", indirDX, Xb, XX }, + { "outs{R||R|}", indirDX, Xv, XX }, + /* 70 */ + { "joH", Jb, XX, cond_jump_flag }, + { "jnoH", Jb, XX, cond_jump_flag }, + { "jbH", Jb, XX, cond_jump_flag }, + { "jaeH", Jb, XX, cond_jump_flag }, + { "jeH", Jb, XX, cond_jump_flag }, + { "jneH", Jb, XX, cond_jump_flag }, + { "jbeH", Jb, XX, cond_jump_flag }, + { "jaH", Jb, XX, cond_jump_flag }, + /* 78 */ + { "jsH", Jb, XX, cond_jump_flag }, + { "jnsH", Jb, XX, cond_jump_flag }, + { "jpH", Jb, XX, cond_jump_flag }, + { "jnpH", Jb, XX, cond_jump_flag }, + { "jlH", Jb, XX, cond_jump_flag }, + { "jgeH", Jb, XX, cond_jump_flag }, + { "jleH", Jb, XX, cond_jump_flag }, + { "jgH", Jb, XX, cond_jump_flag }, + /* 80 */ + { GRP1b }, + { GRP1S }, + { "(bad)", XX, XX, XX }, + { GRP1Ss }, + { "testB", Eb, Gb, XX }, + { "testS", Ev, Gv, XX }, + { "xchgB", Eb, Gb, XX }, + { "xchgS", Ev, Gv, XX }, + /* 88 */ + { "movB", Eb, Gb, XX }, + { "movS", Ev, Gv, XX }, + { "movB", Gb, Eb, XX }, + { "movS", Gv, Ev, XX }, + { "movQ", Ev, Sw, XX }, + { "leaS", Gv, M, XX }, + { "movQ", Sw, Ev, XX }, + { "popU", Ev, XX, XX }, + /* 90 */ + { "nop", NOP_Fixup, 0, XX, XX }, + { "xchgS", RMeCX, eAX, XX }, + { "xchgS", RMeDX, eAX, XX }, + { "xchgS", RMeBX, eAX, XX }, + { "xchgS", RMeSP, eAX, XX }, + { "xchgS", RMeBP, eAX, XX }, + { "xchgS", RMeSI, eAX, XX }, + { "xchgS", RMeDI, eAX, XX }, + /* 98 */ + { "cW{tR||tR|}", XX, XX, XX }, + { "cR{tO||tO|}", XX, XX, XX }, + { "Jcall{T|}", Ap, XX, XX }, + { "(bad)", XX, XX, XX }, /* fwait */ + { "pushfT", XX, XX, XX }, + { "popfT", XX, XX, XX }, + { "sahf{|}", XX, XX, XX }, + { "lahf{|}", XX, XX, XX }, + /* a0 */ + { "movB", AL, Ob64, XX }, + { "movS", eAX, Ov64, XX }, + { "movB", Ob64, AL, XX }, + { "movS", Ov64, eAX, XX }, + { "movs{b||b|}", Yb, Xb, XX }, + { "movs{R||R|}", Yv, Xv, XX }, + { "cmps{b||b|}", Xb, Yb, XX }, + { "cmps{R||R|}", Xv, Yv, XX }, + /* a8 */ + { "testB", AL, Ib, XX }, + { "testS", eAX, Iv, XX }, + { "stosB", Yb, AL, XX }, + { "stosS", Yv, eAX, XX }, + { "lodsB", AL, Xb, XX }, + { "lodsS", eAX, Xv, XX }, + { "scasB", AL, Yb, XX }, + { "scasS", eAX, Yv, XX }, + /* b0 */ + { "movB", RMAL, Ib, XX }, + { "movB", RMCL, Ib, XX }, + { "movB", RMDL, Ib, XX }, + { "movB", RMBL, Ib, XX }, + { "movB", RMAH, Ib, XX }, + { "movB", RMCH, Ib, XX }, + { "movB", RMDH, Ib, XX }, + { "movB", RMBH, Ib, XX }, + /* b8 */ + { "movS", RMeAX, Iv64, XX }, + { "movS", RMeCX, Iv64, XX }, + { "movS", RMeDX, Iv64, XX }, + { "movS", RMeBX, Iv64, XX }, + { "movS", RMeSP, Iv64, XX }, + { "movS", RMeBP, Iv64, XX }, + { "movS", RMeSI, Iv64, XX }, + { "movS", RMeDI, Iv64, XX }, + /* c0 */ + { GRP2b }, + { GRP2S }, + { "retT", Iw, XX, XX }, + { "retT", XX, XX, XX }, + { "les{S|}", Gv, Mp, XX }, + { "ldsS", Gv, Mp, XX }, + { "movA", Eb, Ib, XX }, + { "movQ", Ev, Iv, XX }, + /* c8 */ + { "enterT", Iw, Ib, XX }, + { "leaveT", XX, XX, XX }, + { "lretP", Iw, XX, XX }, + { "lretP", XX, XX, XX }, + { "int3", XX, XX, XX }, + { "int", Ib, XX, XX }, + { "into{|}", XX, XX, XX }, + { "iretP", XX, XX, XX }, + /* d0 */ + { GRP2b_one }, + { GRP2S_one }, + { GRP2b_cl }, + { GRP2S_cl }, + { "aam{|}", sIb, XX, XX }, + { "aad{|}", sIb, XX, XX }, + { "(bad)", XX, XX, XX }, + { "xlat", DSBX, XX, XX }, + /* d8 */ + { FLOAT }, + { FLOAT }, + { FLOAT }, + { FLOAT }, + { FLOAT }, + { FLOAT }, + { FLOAT }, + { FLOAT }, + /* e0 */ + { "loopneFH", Jb, XX, loop_jcxz_flag }, + { "loopeFH", Jb, XX, loop_jcxz_flag }, + { "loopFH", Jb, XX, loop_jcxz_flag }, + { "jEcxzH", Jb, XX, loop_jcxz_flag }, + { "inB", AL, Ib, XX }, + { "inS", eAX, Ib, XX }, + { "outB", Ib, AL, XX }, + { "outS", Ib, eAX, XX }, + /* e8 */ + { "callT", Jv, XX, XX }, + { "jmpT", Jv, XX, XX }, + { "Jjmp{T|}", Ap, XX, XX }, + { "jmp", Jb, XX, XX }, + { "inB", AL, indirDX, XX }, + { "inS", eAX, indirDX, XX }, + { "outB", indirDX, AL, XX }, + { "outS", indirDX, eAX, XX }, + /* f0 */ + { "(bad)", XX, XX, XX }, /* lock prefix */ + { "icebp", XX, XX, XX }, + { "(bad)", XX, XX, XX }, /* repne */ + { "(bad)", XX, XX, XX }, /* repz */ + { "hlt", XX, XX, XX }, + { "cmc", XX, XX, XX }, + { GRP3b }, + { GRP3S }, + /* f8 */ + { "clc", XX, XX, XX }, + { "stc", XX, XX, XX }, + { "cli", XX, XX, XX }, + { "sti", XX, XX, XX }, + { "cld", XX, XX, XX }, + { "std", XX, XX, XX }, + { GRP4 }, + { GRP5 }, +}; + +static const struct dis386 dis386_twobyte[] = { + /* 00 */ + { GRP6 }, + { GRP7 }, + { "larS", Gv, Ew, XX }, + { "lslS", Gv, Ew, XX }, + { "(bad)", XX, XX, XX }, + { "syscall", XX, XX, XX }, + { "clts", XX, XX, XX }, + { "sysretP", XX, XX, XX }, + /* 08 */ + { "invd", XX, XX, XX }, + { "wbinvd", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + { "ud2a", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + { GRPAMD }, + { "femms", XX, XX, XX }, + { "", MX, EM, OPSUF }, /* See OP_3DNowSuffix. */ + /* 10 */ + { PREGRP8 }, + { PREGRP9 }, + { PREGRP30 }, + { "movlpX", EX, XM, SIMD_Fixup, 'h' }, + { "unpcklpX", XM, EX, XX }, + { "unpckhpX", XM, EX, XX }, + { PREGRP31 }, + { "movhpX", EX, XM, SIMD_Fixup, 'l' }, + /* 18 */ + { GRP14 }, + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + /* 20 */ + { "movL", Rm, Cm, XX }, + { "movL", Rm, Dm, XX }, + { "movL", Cm, Rm, XX }, + { "movL", Dm, Rm, XX }, + { "movL", Rd, Td, XX }, + { "(bad)", XX, XX, XX }, + { "movL", Td, Rd, XX }, + { "(bad)", XX, XX, XX }, + /* 28 */ + { "movapX", XM, EX, XX }, + { "movapX", EX, XM, XX }, + { PREGRP2 }, + { "movntpX", Ev, XM, XX }, + { PREGRP4 }, + { PREGRP3 }, + { "ucomisX", XM,EX, XX }, + { "comisX", XM,EX, XX }, + /* 30 */ + { "wrmsr", XX, XX, XX }, + { "rdtsc", XX, XX, XX }, + { "rdmsr", XX, XX, XX }, + { "rdpmc", XX, XX, XX }, + { "sysenter", XX, XX, XX }, + { "sysexit", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + /* 38 */ + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + /* 40 */ + { "cmovo", Gv, Ev, XX }, + { "cmovno", Gv, Ev, XX }, + { "cmovb", Gv, Ev, XX }, + { "cmovae", Gv, Ev, XX }, + { "cmove", Gv, Ev, XX }, + { "cmovne", Gv, Ev, XX }, + { "cmovbe", Gv, Ev, XX }, + { "cmova", Gv, Ev, XX }, + /* 48 */ + { "cmovs", Gv, Ev, XX }, + { "cmovns", Gv, Ev, XX }, + { "cmovp", Gv, Ev, XX }, + { "cmovnp", Gv, Ev, XX }, + { "cmovl", Gv, Ev, XX }, + { "cmovge", Gv, Ev, XX }, + { "cmovle", Gv, Ev, XX }, + { "cmovg", Gv, Ev, XX }, + /* 50 */ + { "movmskpX", Gdq, XS, XX }, + { PREGRP13 }, + { PREGRP12 }, + { PREGRP11 }, + { "andpX", XM, EX, XX }, + { "andnpX", XM, EX, XX }, + { "orpX", XM, EX, XX }, + { "xorpX", XM, EX, XX }, + /* 58 */ + { PREGRP0 }, + { PREGRP10 }, + { PREGRP17 }, + { PREGRP16 }, + { PREGRP14 }, + { PREGRP7 }, + { PREGRP5 }, + { PREGRP6 }, + /* 60 */ + { "punpcklbw", MX, EM, XX }, + { "punpcklwd", MX, EM, XX }, + { "punpckldq", MX, EM, XX }, + { "packsswb", MX, EM, XX }, + { "pcmpgtb", MX, EM, XX }, + { "pcmpgtw", MX, EM, XX }, + { "pcmpgtd", MX, EM, XX }, + { "packuswb", MX, EM, XX }, + /* 68 */ + { "punpckhbw", MX, EM, XX }, + { "punpckhwd", MX, EM, XX }, + { "punpckhdq", MX, EM, XX }, + { "packssdw", MX, EM, XX }, + { PREGRP26 }, + { PREGRP24 }, + { "movd", MX, Edq, XX }, + { PREGRP19 }, + /* 70 */ + { PREGRP22 }, + { GRP10 }, + { GRP11 }, + { GRP12 }, + { "pcmpeqb", MX, EM, XX }, + { "pcmpeqw", MX, EM, XX }, + { "pcmpeqd", MX, EM, XX }, + { "emms", XX, XX, XX }, + /* 78 */ + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + { PREGRP28 }, + { PREGRP29 }, + { PREGRP23 }, + { PREGRP20 }, + /* 80 */ + { "joH", Jv, XX, cond_jump_flag }, + { "jnoH", Jv, XX, cond_jump_flag }, + { "jbH", Jv, XX, cond_jump_flag }, + { "jaeH", Jv, XX, cond_jump_flag }, + { "jeH", Jv, XX, cond_jump_flag }, + { "jneH", Jv, XX, cond_jump_flag }, + { "jbeH", Jv, XX, cond_jump_flag }, + { "jaH", Jv, XX, cond_jump_flag }, + /* 88 */ + { "jsH", Jv, XX, cond_jump_flag }, + { "jnsH", Jv, XX, cond_jump_flag }, + { "jpH", Jv, XX, cond_jump_flag }, + { "jnpH", Jv, XX, cond_jump_flag }, + { "jlH", Jv, XX, cond_jump_flag }, + { "jgeH", Jv, XX, cond_jump_flag }, + { "jleH", Jv, XX, cond_jump_flag }, + { "jgH", Jv, XX, cond_jump_flag }, + /* 90 */ + { "seto", Eb, XX, XX }, + { "setno", Eb, XX, XX }, + { "setb", Eb, XX, XX }, + { "setae", Eb, XX, XX }, + { "sete", Eb, XX, XX }, + { "setne", Eb, XX, XX }, + { "setbe", Eb, XX, XX }, + { "seta", Eb, XX, XX }, + /* 98 */ + { "sets", Eb, XX, XX }, + { "setns", Eb, XX, XX }, + { "setp", Eb, XX, XX }, + { "setnp", Eb, XX, XX }, + { "setl", Eb, XX, XX }, + { "setge", Eb, XX, XX }, + { "setle", Eb, XX, XX }, + { "setg", Eb, XX, XX }, + /* a0 */ + { "pushT", fs, XX, XX }, + { "popT", fs, XX, XX }, + { "cpuid", XX, XX, XX }, + { "btS", Ev, Gv, XX }, + { "shldS", Ev, Gv, Ib }, + { "shldS", Ev, Gv, CL }, + { GRPPADLCK2 }, + { GRPPADLCK1 }, + /* a8 */ + { "pushT", gs, XX, XX }, + { "popT", gs, XX, XX }, + { "rsm", XX, XX, XX }, + { "btsS", Ev, Gv, XX }, + { "shrdS", Ev, Gv, Ib }, + { "shrdS", Ev, Gv, CL }, + { GRP13 }, + { "imulS", Gv, Ev, XX }, + /* b0 */ + { "cmpxchgB", Eb, Gb, XX }, + { "cmpxchgS", Ev, Gv, XX }, + { "lssS", Gv, Mp, XX }, + { "btrS", Ev, Gv, XX }, + { "lfsS", Gv, Mp, XX }, + { "lgsS", Gv, Mp, XX }, + { "movz{bR|x|bR|x}", Gv, Eb, XX }, + { "movz{wR|x|wR|x}", Gv, Ew, XX }, /* yes, there really is movzww ! */ + /* b8 */ + { "(bad)", XX, XX, XX }, + { "ud2b", XX, XX, XX }, + { GRP8 }, + { "btcS", Ev, Gv, XX }, + { "bsfS", Gv, Ev, XX }, + { "bsrS", Gv, Ev, XX }, + { "movs{bR|x|bR|x}", Gv, Eb, XX }, + { "movs{wR|x|wR|x}", Gv, Ew, XX }, /* yes, there really is movsww ! */ + /* c0 */ + { "xaddB", Eb, Gb, XX }, + { "xaddS", Ev, Gv, XX }, + { PREGRP1 }, + { "movntiS", Ev, Gv, XX }, + { "pinsrw", MX, Edqw, Ib }, + { "pextrw", Gdq, MS, Ib }, + { "shufpX", XM, EX, Ib }, + { GRP9 }, + /* c8 */ + { "bswap", RMeAX, XX, XX }, + { "bswap", RMeCX, XX, XX }, + { "bswap", RMeDX, XX, XX }, + { "bswap", RMeBX, XX, XX }, + { "bswap", RMeSP, XX, XX }, + { "bswap", RMeBP, XX, XX }, + { "bswap", RMeSI, XX, XX }, + { "bswap", RMeDI, XX, XX }, + /* d0 */ + { PREGRP27 }, + { "psrlw", MX, EM, XX }, + { "psrld", MX, EM, XX }, + { "psrlq", MX, EM, XX }, + { "paddq", MX, EM, XX }, + { "pmullw", MX, EM, XX }, + { PREGRP21 }, + { "pmovmskb", Gdq, MS, XX }, + /* d8 */ + { "psubusb", MX, EM, XX }, + { "psubusw", MX, EM, XX }, + { "pminub", MX, EM, XX }, + { "pand", MX, EM, XX }, + { "paddusb", MX, EM, XX }, + { "paddusw", MX, EM, XX }, + { "pmaxub", MX, EM, XX }, + { "pandn", MX, EM, XX }, + /* e0 */ + { "pavgb", MX, EM, XX }, + { "psraw", MX, EM, XX }, + { "psrad", MX, EM, XX }, + { "pavgw", MX, EM, XX }, + { "pmulhuw", MX, EM, XX }, + { "pmulhw", MX, EM, XX }, + { PREGRP15 }, + { PREGRP25 }, + /* e8 */ + { "psubsb", MX, EM, XX }, + { "psubsw", MX, EM, XX }, + { "pminsw", MX, EM, XX }, + { "por", MX, EM, XX }, + { "paddsb", MX, EM, XX }, + { "paddsw", MX, EM, XX }, + { "pmaxsw", MX, EM, XX }, + { "pxor", MX, EM, XX }, + /* f0 */ + { PREGRP32 }, + { "psllw", MX, EM, XX }, + { "pslld", MX, EM, XX }, + { "psllq", MX, EM, XX }, + { "pmuludq", MX, EM, XX }, + { "pmaddwd", MX, EM, XX }, + { "psadbw", MX, EM, XX }, + { PREGRP18 }, + /* f8 */ + { "psubb", MX, EM, XX }, + { "psubw", MX, EM, XX }, + { "psubd", MX, EM, XX }, + { "psubq", MX, EM, XX }, + { "paddb", MX, EM, XX }, + { "paddw", MX, EM, XX }, + { "paddd", MX, EM, XX }, + { "(bad)", XX, XX, XX } +}; + +static const struct dis386 dis386_l4[] = { + /* 00 */ + { "", XX, XX, XX }, + { "int3", XX, XX, XX } +}; + +static const unsigned char onebyte_has_modrm[256] = { + /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ + /* ------------------------------- */ + /* 00 */ 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0, /* 00 */ + /* 10 */ 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0, /* 10 */ + /* 20 */ 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0, /* 20 */ + /* 30 */ 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0, /* 30 */ + /* 40 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 40 */ + /* 50 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 50 */ + /* 60 */ 0,0,1,1,0,0,0,0,0,1,0,1,0,0,0,0, /* 60 */ + /* 70 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 70 */ + /* 80 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 80 */ + /* 90 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 90 */ + /* a0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* a0 */ + /* b0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* b0 */ + /* c0 */ 1,1,0,0,1,1,1,1,0,0,0,0,0,0,0,0, /* c0 */ + /* d0 */ 1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1, /* d0 */ + /* e0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* e0 */ + /* f0 */ 0,0,0,0,0,0,1,1,0,0,0,0,0,0,1,1 /* f0 */ + /* ------------------------------- */ + /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ +}; + +static const unsigned char twobyte_has_modrm[256] = { + /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ + /* ------------------------------- */ + /* 00 */ 1,1,1,1,0,0,0,0,0,0,0,0,0,1,0,1, /* 0f */ + /* 10 */ 1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0, /* 1f */ + /* 20 */ 1,1,1,1,1,0,1,0,1,1,1,1,1,1,1,1, /* 2f */ + /* 30 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 3f */ + /* 40 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 4f */ + /* 50 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 5f */ + /* 60 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 6f */ + /* 70 */ 1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,1, /* 7f */ + /* 80 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 8f */ + /* 90 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 9f */ + /* a0 */ 0,0,0,1,1,1,1,1,0,0,0,1,1,1,1,1, /* af */ + /* b0 */ 1,1,1,1,1,1,1,1,0,0,1,1,1,1,1,1, /* bf */ + /* c0 */ 1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0, /* cf */ + /* d0 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* df */ + /* e0 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* ef */ + /* f0 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0 /* ff */ + /* ------------------------------- */ + /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ +}; + +static const unsigned char twobyte_uses_SSE_prefix[256] = { + /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ + /* ------------------------------- */ + /* 00 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0f */ + /* 10 */ 1,1,1,0,0,0,1,0,0,0,0,0,0,0,0,0, /* 1f */ + /* 20 */ 0,0,0,0,0,0,0,0,0,0,1,0,1,1,0,0, /* 2f */ + /* 30 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 3f */ + /* 40 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 4f */ + /* 50 */ 0,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1, /* 5f */ + /* 60 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1, /* 6f */ + /* 70 */ 1,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1, /* 7f */ + /* 80 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 8f */ + /* 90 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 9f */ + /* a0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* af */ + /* b0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* bf */ + /* c0 */ 0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0, /* cf */ + /* d0 */ 1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0, /* df */ + /* e0 */ 0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0, /* ef */ + /* f0 */ 1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0 /* ff */ + /* ------------------------------- */ + /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ +}; + +static char obuf[100]; +static char *obufp; +static char scratchbuf[100]; +static unsigned char *start_codep; +static unsigned char *insn_codep; +static unsigned char *codep; +static disassemble_info *the_info; +static int mod; +static int rm; +static int reg; +static unsigned char need_modrm; + +/* If we are accessing mod/rm/reg without need_modrm set, then the + values are stale. Hitting this abort likely indicates that you + need to update onebyte_has_modrm or twobyte_has_modrm. */ +#define MODRM_CHECK if (!need_modrm) abort () + +static const char **names64; +static const char **names32; +static const char **names16; +static const char **names8; +static const char **names8rex; +static const char **names_seg; +static const char **index16; + +static const char *intel_names64[] = { + "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi", + "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15" +}; +static const char *intel_names32[] = { + "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi", + "r8d", "r9d", "r10d", "r11d", "r12d", "r13d", "r14d", "r15d" +}; +static const char *intel_names16[] = { + "ax", "cx", "dx", "bx", "sp", "bp", "si", "di", + "r8w", "r9w", "r10w", "r11w", "r12w", "r13w", "r14w", "r15w" +}; +static const char *intel_names8[] = { + "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh", +}; +static const char *intel_names8rex[] = { + "al", "cl", "dl", "bl", "spl", "bpl", "sil", "dil", + "r8b", "r9b", "r10b", "r11b", "r12b", "r13b", "r14b", "r15b" +}; +static const char *intel_names_seg[] = { + "es", "cs", "ss", "ds", "fs", "gs", "?", "?", +}; +static const char *intel_index16[] = { + "bx+si", "bx+di", "bp+si", "bp+di", "si", "di", "bp", "bx" +}; + +static const char *att_names64[] = { + "%rax", "%rcx", "%rdx", "%rbx", "%rsp", "%rbp", "%rsi", "%rdi", + "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15" +}; +static const char *att_names32[] = { + "%eax", "%ecx", "%edx", "%ebx", "%esp", "%ebp", "%esi", "%edi", + "%r8d", "%r9d", "%r10d", "%r11d", "%r12d", "%r13d", "%r14d", "%r15d" +}; +static const char *att_names16[] = { + "%ax", "%cx", "%dx", "%bx", "%sp", "%bp", "%si", "%di", + "%r8w", "%r9w", "%r10w", "%r11w", "%r12w", "%r13w", "%r14w", "%r15w" +}; +static const char *att_names8[] = { + "%al", "%cl", "%dl", "%bl", "%ah", "%ch", "%dh", "%bh", +}; +static const char *att_names8rex[] = { + "%al", "%cl", "%dl", "%bl", "%spl", "%bpl", "%sil", "%dil", + "%r8b", "%r9b", "%r10b", "%r11b", "%r12b", "%r13b", "%r14b", "%r15b" +}; +static const char *att_names_seg[] = { + "%es", "%cs", "%ss", "%ds", "%fs", "%gs", "%?", "%?", +}; +static const char *att_index16[] = { + "%bx,%si", "%bx,%di", "%bp,%si", "%bp,%di", "%si", "%di", "%bp", "%bx" +}; + +static const struct dis386 grps[][8] = { + /* GRP1b */ + { + { "addA", Eb, Ib, XX }, + { "orA", Eb, Ib, XX }, + { "adcA", Eb, Ib, XX }, + { "sbbA", Eb, Ib, XX }, + { "andA", Eb, Ib, XX }, + { "subA", Eb, Ib, XX }, + { "xorA", Eb, Ib, XX }, + { "cmpA", Eb, Ib, XX } + }, + /* GRP1S */ + { + { "addQ", Ev, Iv, XX }, + { "orQ", Ev, Iv, XX }, + { "adcQ", Ev, Iv, XX }, + { "sbbQ", Ev, Iv, XX }, + { "andQ", Ev, Iv, XX }, + { "subQ", Ev, Iv, XX }, + { "xorQ", Ev, Iv, XX }, + { "cmpQ", Ev, Iv, XX } + }, + /* GRP1Ss */ + { + { "addQ", Ev, sIb, XX }, + { "orQ", Ev, sIb, XX }, + { "adcQ", Ev, sIb, XX }, + { "sbbQ", Ev, sIb, XX }, + { "andQ", Ev, sIb, XX }, + { "subQ", Ev, sIb, XX }, + { "xorQ", Ev, sIb, XX }, + { "cmpQ", Ev, sIb, XX } + }, + /* GRP2b */ + { + { "rolA", Eb, Ib, XX }, + { "rorA", Eb, Ib, XX }, + { "rclA", Eb, Ib, XX }, + { "rcrA", Eb, Ib, XX }, + { "shlA", Eb, Ib, XX }, + { "shrA", Eb, Ib, XX }, + { "(bad)", XX, XX, XX }, + { "sarA", Eb, Ib, XX }, + }, + /* GRP2S */ + { + { "rolQ", Ev, Ib, XX }, + { "rorQ", Ev, Ib, XX }, + { "rclQ", Ev, Ib, XX }, + { "rcrQ", Ev, Ib, XX }, + { "shlQ", Ev, Ib, XX }, + { "shrQ", Ev, Ib, XX }, + { "(bad)", XX, XX, XX }, + { "sarQ", Ev, Ib, XX }, + }, + /* GRP2b_one */ + { + { "rolA", Eb, I1, XX }, + { "rorA", Eb, I1, XX }, + { "rclA", Eb, I1, XX }, + { "rcrA", Eb, I1, XX }, + { "shlA", Eb, I1, XX }, + { "shrA", Eb, I1, XX }, + { "(bad)", XX, XX, XX }, + { "sarA", Eb, I1, XX }, + }, + /* GRP2S_one */ + { + { "rolQ", Ev, I1, XX }, + { "rorQ", Ev, I1, XX }, + { "rclQ", Ev, I1, XX }, + { "rcrQ", Ev, I1, XX }, + { "shlQ", Ev, I1, XX }, + { "shrQ", Ev, I1, XX }, + { "(bad)", XX, XX, XX}, + { "sarQ", Ev, I1, XX }, + }, + /* GRP2b_cl */ + { + { "rolA", Eb, CL, XX }, + { "rorA", Eb, CL, XX }, + { "rclA", Eb, CL, XX }, + { "rcrA", Eb, CL, XX }, + { "shlA", Eb, CL, XX }, + { "shrA", Eb, CL, XX }, + { "(bad)", XX, XX, XX }, + { "sarA", Eb, CL, XX }, + }, + /* GRP2S_cl */ + { + { "rolQ", Ev, CL, XX }, + { "rorQ", Ev, CL, XX }, + { "rclQ", Ev, CL, XX }, + { "rcrQ", Ev, CL, XX }, + { "shlQ", Ev, CL, XX }, + { "shrQ", Ev, CL, XX }, + { "(bad)", XX, XX, XX }, + { "sarQ", Ev, CL, XX } + }, + /* GRP3b */ + { + { "testA", Eb, Ib, XX }, + { "(bad)", Eb, XX, XX }, + { "notA", Eb, XX, XX }, + { "negA", Eb, XX, XX }, + { "mulA", Eb, XX, XX }, /* Don't print the implicit %al register, */ + { "imulA", Eb, XX, XX }, /* to distinguish these opcodes from other */ + { "divA", Eb, XX, XX }, /* mul/imul opcodes. Do the same for div */ + { "idivA", Eb, XX, XX } /* and idiv for consistency. */ + }, + /* GRP3S */ + { + { "testQ", Ev, Iv, XX }, + { "(bad)", XX, XX, XX }, + { "notQ", Ev, XX, XX }, + { "negQ", Ev, XX, XX }, + { "mulQ", Ev, XX, XX }, /* Don't print the implicit register. */ + { "imulQ", Ev, XX, XX }, + { "divQ", Ev, XX, XX }, + { "idivQ", Ev, XX, XX }, + }, + /* GRP4 */ + { + { "incA", Eb, XX, XX }, + { "decA", Eb, XX, XX }, + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + }, + /* GRP5 */ + { + { "incQ", Ev, XX, XX }, + { "decQ", Ev, XX, XX }, + { "callT", indirEv, XX, XX }, + { "JcallT", indirEp, XX, XX }, + { "jmpT", indirEv, XX, XX }, + { "JjmpT", indirEp, XX, XX }, + { "pushU", Ev, XX, XX }, + { "(bad)", XX, XX, XX }, + }, + /* GRP6 */ + { + { "sldtQ", Ev, XX, XX }, + { "strQ", Ev, XX, XX }, + { "lldt", Ew, XX, XX }, + { "ltr", Ew, XX, XX }, + { "verr", Ew, XX, XX }, + { "verw", Ew, XX, XX }, + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX } + }, + /* GRP7 */ + { + { "sgdtIQ", M, XX, XX }, + { "sidtIQ", PNI_Fixup, 0, XX, XX }, + { "lgdt{Q|Q||}", M, XX, XX }, + { "lidt{Q|Q||}", M, XX, XX }, + { "smswQ", Ev, XX, XX }, + { "(bad)", XX, XX, XX }, + { "lmsw", Ew, XX, XX }, + { "invlpg", INVLPG_Fixup, w_mode, XX, XX }, + }, + /* GRP8 */ + { + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + { "btQ", Ev, Ib, XX }, + { "btsQ", Ev, Ib, XX }, + { "btrQ", Ev, Ib, XX }, + { "btcQ", Ev, Ib, XX }, + }, + /* GRP9 */ + { + { "(bad)", XX, XX, XX }, + { "cmpxchg8b", Eq, XX, XX }, + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + }, + /* GRP10 */ + { + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + { "psrlw", MS, Ib, XX }, + { "(bad)", XX, XX, XX }, + { "psraw", MS, Ib, XX }, + { "(bad)", XX, XX, XX }, + { "psllw", MS, Ib, XX }, + { "(bad)", XX, XX, XX }, + }, + /* GRP11 */ + { + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + { "psrld", MS, Ib, XX }, + { "(bad)", XX, XX, XX }, + { "psrad", MS, Ib, XX }, + { "(bad)", XX, XX, XX }, + { "pslld", MS, Ib, XX }, + { "(bad)", XX, XX, XX }, + }, + /* GRP12 */ + { + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + { "psrlq", MS, Ib, XX }, + { "psrldq", MS, Ib, XX }, + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + { "psllq", MS, Ib, XX }, + { "pslldq", MS, Ib, XX }, + }, + /* GRP13 */ + { + { "fxsave", Ev, XX, XX }, + { "fxrstor", Ev, XX, XX }, + { "ldmxcsr", Ev, XX, XX }, + { "stmxcsr", Ev, XX, XX }, + { "(bad)", XX, XX, XX }, + { "lfence", OP_0fae, 0, XX, XX }, + { "mfence", OP_0fae, 0, XX, XX }, + { "clflush", OP_0fae, 0, XX, XX }, + }, + /* GRP14 */ + { + { "prefetchnta", Ev, XX, XX }, + { "prefetcht0", Ev, XX, XX }, + { "prefetcht1", Ev, XX, XX }, + { "prefetcht2", Ev, XX, XX }, + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + }, + /* GRPAMD */ + { + { "prefetch", Eb, XX, XX }, + { "prefetchw", Eb, XX, XX }, + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + }, + /* GRPPADLCK1 */ + { + { "xstorerng", OP_0f07, 0, XX, XX }, + { "xcryptecb", OP_0f07, 0, XX, XX }, + { "xcryptcbc", OP_0f07, 0, XX, XX }, + { "(bad)", OP_0f07, 0, XX, XX }, + { "xcryptcfb", OP_0f07, 0, XX, XX }, + { "xcryptofb", OP_0f07, 0, XX, XX }, + { "(bad)", OP_0f07, 0, XX, XX }, + { "(bad)", OP_0f07, 0, XX, XX }, + }, + /* GRPPADLCK2 */ + { + { "montmul", OP_0f07, 0, XX, XX }, + { "xsha1", OP_0f07, 0, XX, XX }, + { "xsha256", OP_0f07, 0, XX, XX }, + { "(bad)", OP_0f07, 0, XX, XX }, + { "(bad)", OP_0f07, 0, XX, XX }, + { "(bad)", OP_0f07, 0, XX, XX }, + { "(bad)", OP_0f07, 0, XX, XX }, + { "(bad)", OP_0f07, 0, XX, XX }, + } +}; + +static const struct dis386 prefix_user_table[][4] = { + /* PREGRP0 */ + { + { "addps", XM, EX, XX }, + { "addss", XM, EX, XX }, + { "addpd", XM, EX, XX }, + { "addsd", XM, EX, XX }, + }, + /* PREGRP1 */ + { + { "", XM, EX, OPSIMD }, /* See OP_SIMD_SUFFIX. */ + { "", XM, EX, OPSIMD }, + { "", XM, EX, OPSIMD }, + { "", XM, EX, OPSIMD }, + }, + /* PREGRP2 */ + { + { "cvtpi2ps", XM, EM, XX }, + { "cvtsi2ssY", XM, Ev, XX }, + { "cvtpi2pd", XM, EM, XX }, + { "cvtsi2sdY", XM, Ev, XX }, + }, + /* PREGRP3 */ + { + { "cvtps2pi", MX, EX, XX }, + { "cvtss2siY", Gv, EX, XX }, + { "cvtpd2pi", MX, EX, XX }, + { "cvtsd2siY", Gv, EX, XX }, + }, + /* PREGRP4 */ + { + { "cvttps2pi", MX, EX, XX }, + { "cvttss2siY", Gv, EX, XX }, + { "cvttpd2pi", MX, EX, XX }, + { "cvttsd2siY", Gv, EX, XX }, + }, + /* PREGRP5 */ + { + { "divps", XM, EX, XX }, + { "divss", XM, EX, XX }, + { "divpd", XM, EX, XX }, + { "divsd", XM, EX, XX }, + }, + /* PREGRP6 */ + { + { "maxps", XM, EX, XX }, + { "maxss", XM, EX, XX }, + { "maxpd", XM, EX, XX }, + { "maxsd", XM, EX, XX }, + }, + /* PREGRP7 */ + { + { "minps", XM, EX, XX }, + { "minss", XM, EX, XX }, + { "minpd", XM, EX, XX }, + { "minsd", XM, EX, XX }, + }, + /* PREGRP8 */ + { + { "movups", XM, EX, XX }, + { "movss", XM, EX, XX }, + { "movupd", XM, EX, XX }, + { "movsd", XM, EX, XX }, + }, + /* PREGRP9 */ + { + { "movups", EX, XM, XX }, + { "movss", EX, XM, XX }, + { "movupd", EX, XM, XX }, + { "movsd", EX, XM, XX }, + }, + /* PREGRP10 */ + { + { "mulps", XM, EX, XX }, + { "mulss", XM, EX, XX }, + { "mulpd", XM, EX, XX }, + { "mulsd", XM, EX, XX }, + }, + /* PREGRP11 */ + { + { "rcpps", XM, EX, XX }, + { "rcpss", XM, EX, XX }, + { "(bad)", XM, EX, XX }, + { "(bad)", XM, EX, XX }, + }, + /* PREGRP12 */ + { + { "rsqrtps", XM, EX, XX }, + { "rsqrtss", XM, EX, XX }, + { "(bad)", XM, EX, XX }, + { "(bad)", XM, EX, XX }, + }, + /* PREGRP13 */ + { + { "sqrtps", XM, EX, XX }, + { "sqrtss", XM, EX, XX }, + { "sqrtpd", XM, EX, XX }, + { "sqrtsd", XM, EX, XX }, + }, + /* PREGRP14 */ + { + { "subps", XM, EX, XX }, + { "subss", XM, EX, XX }, + { "subpd", XM, EX, XX }, + { "subsd", XM, EX, XX }, + }, + /* PREGRP15 */ + { + { "(bad)", XM, EX, XX }, + { "cvtdq2pd", XM, EX, XX }, + { "cvttpd2dq", XM, EX, XX }, + { "cvtpd2dq", XM, EX, XX }, + }, + /* PREGRP16 */ + { + { "cvtdq2ps", XM, EX, XX }, + { "cvttps2dq",XM, EX, XX }, + { "cvtps2dq",XM, EX, XX }, + { "(bad)", XM, EX, XX }, + }, + /* PREGRP17 */ + { + { "cvtps2pd", XM, EX, XX }, + { "cvtss2sd", XM, EX, XX }, + { "cvtpd2ps", XM, EX, XX }, + { "cvtsd2ss", XM, EX, XX }, + }, + /* PREGRP18 */ + { + { "maskmovq", MX, MS, XX }, + { "(bad)", XM, EX, XX }, + { "maskmovdqu", XM, EX, XX }, + { "(bad)", XM, EX, XX }, + }, + /* PREGRP19 */ + { + { "movq", MX, EM, XX }, + { "movdqu", XM, EX, XX }, + { "movdqa", XM, EX, XX }, + { "(bad)", XM, EX, XX }, + }, + /* PREGRP20 */ + { + { "movq", EM, MX, XX }, + { "movdqu", EX, XM, XX }, + { "movdqa", EX, XM, XX }, + { "(bad)", EX, XM, XX }, + }, + /* PREGRP21 */ + { + { "(bad)", EX, XM, XX }, + { "movq2dq", XM, MS, XX }, + { "movq", EX, XM, XX }, + { "movdq2q", MX, XS, XX }, + }, + /* PREGRP22 */ + { + { "pshufw", MX, EM, Ib }, + { "pshufhw", XM, EX, Ib }, + { "pshufd", XM, EX, Ib }, + { "pshuflw", XM, EX, Ib }, + }, + /* PREGRP23 */ + { + { "movd", Edq, MX, XX }, + { "movq", XM, EX, XX }, + { "movd", Edq, XM, XX }, + { "(bad)", Ed, XM, XX }, + }, + /* PREGRP24 */ + { + { "(bad)", MX, EX, XX }, + { "(bad)", XM, EX, XX }, + { "punpckhqdq", XM, EX, XX }, + { "(bad)", XM, EX, XX }, + }, + /* PREGRP25 */ + { + { "movntq", EM, MX, XX }, + { "(bad)", EM, XM, XX }, + { "movntdq", EM, XM, XX }, + { "(bad)", EM, XM, XX }, + }, + /* PREGRP26 */ + { + { "(bad)", MX, EX, XX }, + { "(bad)", XM, EX, XX }, + { "punpcklqdq", XM, EX, XX }, + { "(bad)", XM, EX, XX }, + }, + /* PREGRP27 */ + { + { "(bad)", MX, EX, XX }, + { "(bad)", XM, EX, XX }, + { "addsubpd", XM, EX, XX }, + { "addsubps", XM, EX, XX }, + }, + /* PREGRP28 */ + { + { "(bad)", MX, EX, XX }, + { "(bad)", XM, EX, XX }, + { "haddpd", XM, EX, XX }, + { "haddps", XM, EX, XX }, + }, + /* PREGRP29 */ + { + { "(bad)", MX, EX, XX }, + { "(bad)", XM, EX, XX }, + { "hsubpd", XM, EX, XX }, + { "hsubps", XM, EX, XX }, + }, + /* PREGRP30 */ + { + { "movlpX", XM, EX, SIMD_Fixup, 'h' }, /* really only 2 operands */ + { "movsldup", XM, EX, XX }, + { "movlpd", XM, EX, XX }, + { "movddup", XM, EX, XX }, + }, + /* PREGRP31 */ + { + { "movhpX", XM, EX, SIMD_Fixup, 'l' }, + { "movshdup", XM, EX, XX }, + { "movhpd", XM, EX, XX }, + { "(bad)", XM, EX, XX }, + }, + /* PREGRP32 */ + { + { "(bad)", XM, EX, XX }, + { "(bad)", XM, EX, XX }, + { "(bad)", XM, EX, XX }, + { "lddqu", XM, M, XX }, + }, +}; + +static const struct dis386 x86_64_table[][2] = { + { + { "arpl", Ew, Gw, XX }, + { "movs{||lq|xd}", Gv, Ed, XX }, + }, +}; + +#define INTERNAL_DISASSEMBLER_ERROR _("") + +static void +ckprefix (void) +{ + int newrex; + rex = 0; + prefixes = 0; + used_prefixes = 0; + rex_used = 0; + while (1) + { + FETCH_DATA (the_info, codep + 1); + newrex = 0; + switch (*codep) + { + /* REX prefixes family. */ + case 0x40: + case 0x41: + case 0x42: + case 0x43: + case 0x44: + case 0x45: + case 0x46: + case 0x47: + case 0x48: + case 0x49: + case 0x4a: + case 0x4b: + case 0x4c: + case 0x4d: + case 0x4e: + case 0x4f: + if (mode_64bit) + newrex = *codep; + else + return; + break; + case 0xf3: + prefixes |= PREFIX_REPZ; + break; + case 0xf2: + prefixes |= PREFIX_REPNZ; + break; + case 0xf0: + prefixes |= PREFIX_LOCK; + break; + case 0x2e: + prefixes |= PREFIX_CS; + break; + case 0x36: + prefixes |= PREFIX_SS; + break; + case 0x3e: + prefixes |= PREFIX_DS; + break; + case 0x26: + prefixes |= PREFIX_ES; + break; + case 0x64: + prefixes |= PREFIX_FS; + break; + case 0x65: + prefixes |= PREFIX_GS; + break; + case 0x66: + prefixes |= PREFIX_DATA; + break; + case 0x67: + prefixes |= PREFIX_ADDR; + break; + case FWAIT_OPCODE: + /* fwait is really an instruction. If there are prefixes + before the fwait, they belong to the fwait, *not* to the + following instruction. */ + if (prefixes) + { + prefixes |= PREFIX_FWAIT; + codep++; + return; + } + prefixes = PREFIX_FWAIT; + break; + default: + return; + } + /* Rex is ignored when followed by another prefix. */ + if (rex) + { + oappend (prefix_name (rex, 0)); + oappend (" "); + } + rex = newrex; + codep++; + } +} + +/* Return the name of the prefix byte PREF, or NULL if PREF is not a + prefix byte. */ + +static const char * +prefix_name (int pref, int sizeflag) +{ + switch (pref) + { + /* REX prefixes family. */ + case 0x40: + return "rex"; + case 0x41: + return "rexZ"; + case 0x42: + return "rexY"; + case 0x43: + return "rexYZ"; + case 0x44: + return "rexX"; + case 0x45: + return "rexXZ"; + case 0x46: + return "rexXY"; + case 0x47: + return "rexXYZ"; + case 0x48: + return "rex64"; + case 0x49: + return "rex64Z"; + case 0x4a: + return "rex64Y"; + case 0x4b: + return "rex64YZ"; + case 0x4c: + return "rex64X"; + case 0x4d: + return "rex64XZ"; + case 0x4e: + return "rex64XY"; + case 0x4f: + return "rex64XYZ"; + case 0xf3: + return "repz"; + case 0xf2: + return "repnz"; + case 0xf0: + return "lock"; + case 0x2e: + return "cs"; + case 0x36: + return "ss"; + case 0x3e: + return "ds"; + case 0x26: + return "es"; + case 0x64: + return "fs"; + case 0x65: + return "gs"; + case 0x66: + return (sizeflag & DFLAG) ? "data16" : "data32"; + case 0x67: + if (mode_64bit) + return (sizeflag & AFLAG) ? "addr32" : "addr64"; + else + return ((sizeflag & AFLAG) && !mode_64bit) ? "addr16" : "addr32"; + case FWAIT_OPCODE: + return "fwait"; + default: + return NULL; + } +} + +static char op1out[100], op2out[100], op3out[100]; +static int op_ad, op_index[3]; +static int two_source_ops; +static bfd_vma op_address[3]; +static bfd_vma op_riprel[3]; +static bfd_vma start_pc; + +/* + * On the 386's of 1988, the maximum length of an instruction is 15 bytes. + * (see topic "Redundant prefixes" in the "Differences from 8086" + * section of the "Virtual 8086 Mode" chapter.) + * 'pc' should be the address of this instruction, it will + * be used to print the target address if this is a relative jump or call + * The function returns the length of this instruction in bytes. + */ + +static char intel_syntax; +static char open_char; +static char close_char; +static char separator_char; +static char scale_char; + +/* Here for backwards compatibility. When gdb stops using + print_insn_i386_att and print_insn_i386_intel these functions can + disappear, and print_insn_i386 be merged into print_insn. */ +int +print_insn_i386_att (bfd_vma pc, disassemble_info *info) +{ + intel_syntax = 0; + + return print_insn (pc, info); +} + +int +print_insn_i386_intel (bfd_vma pc, disassemble_info *info) +{ + intel_syntax = 1; + + return print_insn (pc, info); +} + +int +print_insn_i386 (bfd_vma pc, disassemble_info *info) +{ + intel_syntax = -1; + + return print_insn (pc, info); +} + +static int +print_insn (bfd_vma pc, disassemble_info *info) +{ + const struct dis386 *dp; + int i; +#if 0 + int l; +#endif + char *first, *second, *third; + int needcomma; + unsigned char uses_SSE_prefix, uses_LOCK_prefix; + int sizeflag; + const char *p; + struct dis_private priv; + + mode_64bit = (info->mach == bfd_mach_x86_64_intel_syntax + || info->mach == bfd_mach_x86_64); + + if (intel_syntax == (char) -1) + intel_syntax = (info->mach == bfd_mach_i386_i386_intel_syntax + || info->mach == bfd_mach_x86_64_intel_syntax); + + if (info->mach == bfd_mach_i386_i386 + || info->mach == bfd_mach_x86_64 + || info->mach == bfd_mach_i386_i386_intel_syntax + || info->mach == bfd_mach_x86_64_intel_syntax) + priv.orig_sizeflag = AFLAG | DFLAG; + else if (info->mach == bfd_mach_i386_i8086) + priv.orig_sizeflag = 0; + else + abort (); + + for (p = info->disassembler_options; p != NULL; ) + { + if (strncmp (p, "x86-64", 6) == 0) + { + mode_64bit = 1; + priv.orig_sizeflag = AFLAG | DFLAG; + } + else if (strncmp (p, "i386", 4) == 0) + { + mode_64bit = 0; + priv.orig_sizeflag = AFLAG | DFLAG; + } + else if (strncmp (p, "i8086", 5) == 0) + { + mode_64bit = 0; + priv.orig_sizeflag = 0; + } + else if (strncmp (p, "intel", 5) == 0) + { + intel_syntax = 1; + } + else if (strncmp (p, "att", 3) == 0) + { + intel_syntax = 0; + } + else if (strncmp (p, "addr", 4) == 0) + { + if (p[4] == '1' && p[5] == '6') + priv.orig_sizeflag &= ~AFLAG; + else if (p[4] == '3' && p[5] == '2') + priv.orig_sizeflag |= AFLAG; + } + else if (strncmp (p, "data", 4) == 0) + { + if (p[4] == '1' && p[5] == '6') + priv.orig_sizeflag &= ~DFLAG; + else if (p[4] == '3' && p[5] == '2') + priv.orig_sizeflag |= DFLAG; + } + else if (strncmp (p, "suffix", 6) == 0) + priv.orig_sizeflag |= SUFFIX_ALWAYS; + + p = strchr (p, ','); + if (p != NULL) + p++; + } + + if (intel_syntax) + { + names64 = intel_names64; + names32 = intel_names32; + names16 = intel_names16; + names8 = intel_names8; + names8rex = intel_names8rex; + names_seg = intel_names_seg; + index16 = intel_index16; + open_char = '['; + close_char = ']'; + separator_char = '+'; + scale_char = '*'; + } + else + { + names64 = att_names64; + names32 = att_names32; + names16 = att_names16; + names8 = att_names8; + names8rex = att_names8rex; + names_seg = att_names_seg; + index16 = att_index16; + open_char = '('; + close_char = ')'; + separator_char = ','; + scale_char = ','; + } + + /* The output looks better if we put 7 bytes on a line, since that + puts most long word instructions on a single line. */ + info->bytes_per_line = 7; + + info->private_data = &priv; + priv.max_fetched = priv.the_buffer; + priv.insn_start = pc; + + obuf[0] = 0; + op1out[0] = 0; + op2out[0] = 0; + op3out[0] = 0; + + op_index[0] = op_index[1] = op_index[2] = -1; + + the_info = info; + start_pc = pc; + start_codep = priv.the_buffer; + codep = priv.the_buffer; + + if (setjmp (priv.bailout) != 0) + { + const char *name; + + /* Getting here means we tried for data but didn't get it. That + means we have an incomplete instruction of some sort. Just + print the first byte as a prefix or a .byte pseudo-op. */ + if (codep > priv.the_buffer) + { + name = prefix_name (priv.the_buffer[0], priv.orig_sizeflag); + if (name != NULL) + (*info->fprintf_func) (info->stream, "%s", name); + else + { + /* Just print the first byte as a .byte instruction. */ + (*info->fprintf_func) (info->stream, ".byte 0x%x", + (unsigned int) priv.the_buffer[0]); + } + + return 1; + } + + return -1; + } + + obufp = obuf; + ckprefix (); + + insn_codep = codep; + sizeflag = priv.orig_sizeflag; + + FETCH_DATA (info, codep + 1); + two_source_ops = (*codep == 0x62) || (*codep == 0xc8); + + if ((prefixes & PREFIX_FWAIT) + && ((*codep < 0xd8) || (*codep > 0xdf))) + { + const char *name; + + /* fwait not followed by floating point instruction. Print the + first prefix, which is probably fwait itself. */ + name = prefix_name (priv.the_buffer[0], priv.orig_sizeflag); + if (name == NULL) + name = INTERNAL_DISASSEMBLER_ERROR; + (*info->fprintf_func) (info->stream, "%s", name); + return 1; + } + + if (*codep == 0x0f) + { + FETCH_DATA (info, codep + 2); + dp = &dis386_twobyte[*++codep]; + need_modrm = twobyte_has_modrm[*codep]; + uses_SSE_prefix = twobyte_uses_SSE_prefix[*codep]; + uses_LOCK_prefix = (*codep & ~0x02) == 0x20; + } + else if (*codep == 0xcc) + { + /* L4KD's hacks */ + FETCH_DATA (info, codep + 3); /* get two more bytes */ + dp = &dis386_l4[0]; + need_modrm = 0; + uses_SSE_prefix = 0; + uses_LOCK_prefix = 0; + switch (*++codep) + { + case 0x3c: + switch(*++codep) + { + case 0: oappend ("l4kd outchar(%al)"); break; + case 1: oappend ("l4kd outstring(%eax)"); break; + case 2: oappend ("l4kd outcstring(%eax)"); break; + case 3: oappend ("l4kd clear_page"); break; + case 4: oappend ("l4kd cursor"); break; + case 5: oappend ("l4kd outhex32(%eax)"); break; + case 6: oappend ("l4kd outhex20(%eax)"); break; + case 7: oappend ("l4kd outhex16(%eax)"); break; + case 8: oappend ("l4kd outhex12(%eax)"); break; + case 9: oappend ("l4kd outhex8(%eax)"); break; + case 10: oappend ("l4kd outhex4(%eax)"); break; + case 11: oappend ("l4kd outdec(%eax)"); break; + case 12: oappend ("l4kd incharety"); break; + case 13: oappend ("l4kd inchar"); break; + case 14: oappend ("l4kd inhex32"); break; + case 15: oappend ("l4kd inhex16"); break; + case 16: oappend ("l4kd inhex8"); break; + case 17: oappend ("l4kd inhext"); break; + case 24: oappend ("l4kd start_profile"); break; + case 25: oappend ("l4kd stop+dump profile"); break; + case 26: oappend ("l4kd stop profile"); break; + case 29: oappend ("l4kd trace(%eax)"); break; + case 30: oappend ("l4kd debug info(%ecx)"); break; + case 31: oappend ("l4kd watchdog(%ecx)"); break; + default: + { + if (codep[-1] >= ' ' && codep[-1] <= 0x7f) + { + char msg[2] = {*codep,0}; + oappend ("l4kd ko('"); + oappend (msg); oappend ("')"); + break; + } + oappend ("l4kd ???"); + break; + } + } + break; + + case 0x90: + { + int len; + + if (*++codep == 0xeb) + { + oappend ("l4kd kd_display(\""); + + FETCH_DATA (info, codep + 2); + len = *++codep; + + FETCH_DATA (info, codep + len + 1); + { + char msg[len + 1]; + strncpy(msg, (char*)codep + 1, len); + msg[len] = 0; + oappend (msg); + codep += len; + } + oappend ("\")"); + } + else + { + codep -= 2; + dp = &dis386_l4[1]; + } + } + break; + case 0xeb: + { + int len, len_cut; + oappend ("l4kd enter_kdebug(\""); + + FETCH_DATA (info, codep + 2); + len = len_cut = *++codep; + if (len_cut > 30) + len_cut = 30; + + FETCH_DATA (info, codep + len + 1); + { + char msg[len_cut + 4]; + strncpy(msg, (char*)codep + 1, len_cut); + if (len_cut < len) + { + msg[len_cut++] = '.'; + msg[len_cut++] = '.'; + msg[len_cut++] = '.'; + } + msg[len_cut] = 0; + oappend (msg); + codep += len; + } + oappend ("\")"); + } + break; + default: + codep--; + dp = &dis386_l4[1]; + break; + } + } + else + { + dp = &dis386[*codep]; + need_modrm = onebyte_has_modrm[*codep]; + uses_SSE_prefix = 0; + uses_LOCK_prefix = 0; + } + codep++; + + if (!uses_SSE_prefix && (prefixes & PREFIX_REPZ)) + { + oappend ("repz "); + used_prefixes |= PREFIX_REPZ; + } + if (!uses_SSE_prefix && (prefixes & PREFIX_REPNZ)) + { + oappend ("repnz "); + used_prefixes |= PREFIX_REPNZ; + } + if (!uses_LOCK_prefix && (prefixes & PREFIX_LOCK)) + { + oappend ("lock "); + used_prefixes |= PREFIX_LOCK; + } + + if (prefixes & PREFIX_ADDR) + { + sizeflag ^= AFLAG; + if (dp->bytemode3 != loop_jcxz_mode || intel_syntax) + { + if ((sizeflag & AFLAG) || mode_64bit) + oappend ("addr32 "); + else + oappend ("addr16 "); + used_prefixes |= PREFIX_ADDR; + } + } + + if (!uses_SSE_prefix && (prefixes & PREFIX_DATA)) + { + sizeflag ^= DFLAG; + if (dp->bytemode3 == cond_jump_mode + && dp->bytemode1 == v_mode + && !intel_syntax) + { + if (sizeflag & DFLAG) + oappend ("data32 "); + else + oappend ("data16 "); + used_prefixes |= PREFIX_DATA; + } + } + + if (need_modrm) + { + FETCH_DATA (info, codep + 1); + mod = (*codep >> 6) & 3; + reg = (*codep >> 3) & 7; + rm = *codep & 7; + } + + op_ad = 2; // fm3 + + if (dp->name == NULL && dp->bytemode1 == FLOATCODE) + { + dofloat (sizeflag); + } + else + { + int index; + if (dp->name == NULL) + { + switch (dp->bytemode1) + { + case USE_GROUPS: + dp = &grps[dp->bytemode2][reg]; + break; + + case USE_PREFIX_USER_TABLE: + index = 0; + used_prefixes |= (prefixes & PREFIX_REPZ); + if (prefixes & PREFIX_REPZ) + index = 1; + else + { + used_prefixes |= (prefixes & PREFIX_DATA); + if (prefixes & PREFIX_DATA) + index = 2; + else + { + used_prefixes |= (prefixes & PREFIX_REPNZ); + if (prefixes & PREFIX_REPNZ) + index = 3; + } + } + dp = &prefix_user_table[dp->bytemode2][index]; + break; + + case X86_64_SPECIAL: + dp = &x86_64_table[dp->bytemode2][mode_64bit]; + break; + + default: + oappend (INTERNAL_DISASSEMBLER_ERROR); + break; + } + } + + if (putop (dp->name, sizeflag) == 0) + { + obufp = op1out; + op_ad = 2; + if (dp->op1) + (*dp->op1) (dp->bytemode1, sizeflag); + + obufp = op2out; + op_ad = 1; + if (dp->op2) + (*dp->op2) (dp->bytemode2, sizeflag); + + obufp = op3out; + op_ad = 0; + if (dp->op3) + (*dp->op3) (dp->bytemode3, sizeflag); + } + } + + /* See if any prefixes were not used. If so, print the first one + separately. If we don't do this, we'll wind up printing an + instruction stream which does not precisely correspond to the + bytes we are disassembling. */ + if ((prefixes & ~used_prefixes) != 0) + { + const char *name; + + name = prefix_name (priv.the_buffer[0], priv.orig_sizeflag); + if (name == NULL) + name = INTERNAL_DISASSEMBLER_ERROR; + (*info->fprintf_func) (info->stream, "%s", name); + return 1; + } + if (rex & ~rex_used) + { + const char *name; + name = prefix_name (rex | 0x40, priv.orig_sizeflag); + if (name == NULL) + name = INTERNAL_DISASSEMBLER_ERROR; + (*info->fprintf_func) (info->stream, "%s ", name); + } + +#if 0 + for (l = 0, i = 0;; ++i,++l) + { + if (l == info->bytes_per_line) + { + l = 0; + if (priv.the_buffer + i < codep) + (*info->fprintf_func)(info->stream, "\n"); + else + break; + } + + if (priv.the_buffer + i < codep) + (*info->fprintf_func) (info->stream, "%02x ", priv.the_buffer[i]); + else + (*info->fprintf_func) (info->stream, " "); + } +#endif + + + obufp = obuf + strlen (obuf); + for (i = strlen (obuf); i < 6; i++) + oappend (" "); + oappend (" "); + (*info->fprintf_func) (info->stream, "%s", obuf); + + /* The enter and bound instructions are printed with operands in the same + order as the intel book; everything else is printed in reverse order. */ + if (intel_syntax || two_source_ops) + { + first = op1out; + second = op2out; + third = op3out; + op_ad = op_index[0]; + op_index[0] = op_index[2]; + op_index[2] = op_ad; + } + else + { + first = op3out; + second = op2out; + third = op1out; + } + needcomma = 0; + if (*first) + { +#if 0 // fm3 + if (op_index[0] != -1 && !op_riprel[0]) + (*info->print_address_func) ((bfd_vma) op_address[op_index[0]], info); + else + (*info->fprintf_func) (info->stream, "%s", first); +#else + (*info->fprintf_func) (info->stream, "%s", first); + if (op_index[0] != -1 && !op_riprel[0]) + (*info->print_address_func) ((bfd_vma) op_address[op_index[0]], info); +#endif + needcomma = 1; + } + if (*second) + { + if (needcomma) + (*info->fprintf_func) (info->stream, ","); +#if 0 // fm3 + if (op_index[1] != -1 && !op_riprel[1]) + (*info->print_address_func) ((bfd_vma) op_address[op_index[1]], info); + else + (*info->fprintf_func) (info->stream, "%s", second); +#else + (*info->fprintf_func) (info->stream, "%s", second); + if (op_index[1] != -1 && !op_riprel[1]) + (*info->print_address_func) ((bfd_vma) op_address[op_index[1]], info); +#endif + needcomma = 1; + } + if (*third) + { + if (needcomma) + (*info->fprintf_func) (info->stream, ","); +#if 0 // fm3 + if (op_index[2] != -1 && !op_riprel[2]) + (*info->print_address_func) ((bfd_vma) op_address[op_index[2]], info); + else + (*info->fprintf_func) (info->stream, "%s", third); +#else + (*info->fprintf_func) (info->stream, "%s", third); + if (op_index[2] != -1 && !op_riprel[2]) + (*info->print_address_func) ((bfd_vma) op_address[op_index[2]], info); +#endif + } + for (i = 0; i < 3; i++) + if (op_index[i] != -1 && op_riprel[i]) + { +#if 0 // l4 + (*info->fprintf_func) (info->stream, " # "); +#else + (*info->fprintf_func) (info->stream, " # "); +#endif + (*info->print_address_func) ((bfd_vma) (start_pc + codep - start_codep + + op_address[op_index[i]]), info); + } + return codep - priv.the_buffer; +} + +static const char *float_mem[] = { + /* d8 */ + "fadd{s||s|}", + "fmul{s||s|}", + "fcom{s||s|}", + "fcomp{s||s|}", + "fsub{s||s|}", + "fsubr{s||s|}", + "fdiv{s||s|}", + "fdivr{s||s|}", + /* d9 */ + "fld{s||s|}", + "(bad)", + "fst{s||s|}", + "fstp{s||s|}", + "fldenvIC", + "fldcw", + "fNstenvIC", + "fNstcw", + /* da */ + "fiadd{l||l|}", + "fimul{l||l|}", + "ficom{l||l|}", + "ficomp{l||l|}", + "fisub{l||l|}", + "fisubr{l||l|}", + "fidiv{l||l|}", + "fidivr{l||l|}", + /* db */ + "fild{l||l|}", + "fisttp{l||l|}", + "fist{l||l|}", + "fistp{l||l|}", + "(bad)", + "fld{t||t|}", + "(bad)", + "fstp{t||t|}", + /* dc */ + "fadd{l||l|}", + "fmul{l||l|}", + "fcom{l||l|}", + "fcomp{l||l|}", + "fsub{l||l|}", + "fsubr{l||l|}", + "fdiv{l||l|}", + "fdivr{l||l|}", + /* dd */ + "fld{l||l|}", + "fisttp{ll||ll|}", + "fst{l||l|}", + "fstp{l||l|}", + "frstorIC", + "(bad)", + "fNsaveIC", + "fNstsw", + /* de */ + "fiadd", + "fimul", + "ficom", + "ficomp", + "fisub", + "fisubr", + "fidiv", + "fidivr", + /* df */ + "fild", + "fisttp", + "fist", + "fistp", + "fbld", + "fild{ll||ll|}", + "fbstp", + "fistp{ll||ll|}", +}; + +static const unsigned char float_mem_mode[] = { + /* d8 */ + d_mode, + d_mode, + d_mode, + d_mode, + d_mode, + d_mode, + d_mode, + d_mode, + /* d9 */ + d_mode, + 0, + d_mode, + d_mode, + 0, + w_mode, + 0, + w_mode, + /* da */ + d_mode, + d_mode, + d_mode, + d_mode, + d_mode, + d_mode, + d_mode, + d_mode, + /* db */ + d_mode, + d_mode, + d_mode, + d_mode, + 0, + t_mode, + 0, + t_mode, + /* dc */ + q_mode, + q_mode, + q_mode, + q_mode, + q_mode, + q_mode, + q_mode, + q_mode, + /* dd */ + q_mode, + q_mode, + q_mode, + q_mode, + 0, + 0, + 0, + w_mode, + /* de */ + w_mode, + w_mode, + w_mode, + w_mode, + w_mode, + w_mode, + w_mode, + w_mode, + /* df */ + w_mode, + w_mode, + w_mode, + w_mode, + t_mode, + q_mode, + t_mode, + q_mode +}; + +#define ST OP_ST, 0 +#define STi OP_STi, 0 + +#define FGRPd9_2 NULL, NULL, 0, NULL, 0, NULL, 0 +#define FGRPd9_4 NULL, NULL, 1, NULL, 0, NULL, 0 +#define FGRPd9_5 NULL, NULL, 2, NULL, 0, NULL, 0 +#define FGRPd9_6 NULL, NULL, 3, NULL, 0, NULL, 0 +#define FGRPd9_7 NULL, NULL, 4, NULL, 0, NULL, 0 +#define FGRPda_5 NULL, NULL, 5, NULL, 0, NULL, 0 +#define FGRPdb_4 NULL, NULL, 6, NULL, 0, NULL, 0 +#define FGRPde_3 NULL, NULL, 7, NULL, 0, NULL, 0 +#define FGRPdf_4 NULL, NULL, 8, NULL, 0, NULL, 0 + +static const struct dis386 float_reg[][8] = { + /* d8 */ + { + { "fadd", ST, STi, XX }, + { "fmul", ST, STi, XX }, + { "fcom", STi, XX, XX }, + { "fcomp", STi, XX, XX }, + { "fsub", ST, STi, XX }, + { "fsubr", ST, STi, XX }, + { "fdiv", ST, STi, XX }, + { "fdivr", ST, STi, XX }, + }, + /* d9 */ + { + { "fld", STi, XX, XX }, + { "fxch", STi, XX, XX }, + { FGRPd9_2 }, + { "(bad)", XX, XX, XX }, + { FGRPd9_4 }, + { FGRPd9_5 }, + { FGRPd9_6 }, + { FGRPd9_7 }, + }, + /* da */ + { + { "fcmovb", ST, STi, XX }, + { "fcmove", ST, STi, XX }, + { "fcmovbe",ST, STi, XX }, + { "fcmovu", ST, STi, XX }, + { "(bad)", XX, XX, XX }, + { FGRPda_5 }, + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + }, + /* db */ + { + { "fcmovnb",ST, STi, XX }, + { "fcmovne",ST, STi, XX }, + { "fcmovnbe",ST, STi, XX }, + { "fcmovnu",ST, STi, XX }, + { FGRPdb_4 }, + { "fucomi", ST, STi, XX }, + { "fcomi", ST, STi, XX }, + { "(bad)", XX, XX, XX }, + }, + /* dc */ + { + { "fadd", STi, ST, XX }, + { "fmul", STi, ST, XX }, + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX }, +#if UNIXWARE_COMPAT + { "fsub", STi, ST, XX }, + { "fsubr", STi, ST, XX }, + { "fdiv", STi, ST, XX }, + { "fdivr", STi, ST, XX }, +#else + { "fsubr", STi, ST, XX }, + { "fsub", STi, ST, XX }, + { "fdivr", STi, ST, XX }, + { "fdiv", STi, ST, XX }, +#endif + }, + /* dd */ + { + { "ffree", STi, XX, XX }, + { "(bad)", XX, XX, XX }, + { "fst", STi, XX, XX }, + { "fstp", STi, XX, XX }, + { "fucom", STi, XX, XX }, + { "fucomp", STi, XX, XX }, + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + }, + /* de */ + { + { "faddp", STi, ST, XX }, + { "fmulp", STi, ST, XX }, + { "(bad)", XX, XX, XX }, + { FGRPde_3 }, +#if UNIXWARE_COMPAT + { "fsubp", STi, ST, XX }, + { "fsubrp", STi, ST, XX }, + { "fdivp", STi, ST, XX }, + { "fdivrp", STi, ST, XX }, +#else + { "fsubrp", STi, ST, XX }, + { "fsubp", STi, ST, XX }, + { "fdivrp", STi, ST, XX }, + { "fdivp", STi, ST, XX }, +#endif + }, + /* df */ + { + { "ffreep", STi, XX, XX }, + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + { "(bad)", XX, XX, XX }, + { FGRPdf_4 }, + { "fucomip",ST, STi, XX }, + { "fcomip", ST, STi, XX }, + { "(bad)", XX, XX, XX }, + }, +}; + +static char *fgrps[][8] = { + /* d9_2 0 */ + { + "fnop","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)", + }, + + /* d9_4 1 */ + { + "fchs","fabs","(bad)","(bad)","ftst","fxam","(bad)","(bad)", + }, + + /* d9_5 2 */ + { + "fld1","fldl2t","fldl2e","fldpi","fldlg2","fldln2","fldz","(bad)", + }, + + /* d9_6 3 */ + { + "f2xm1","fyl2x","fptan","fpatan","fxtract","fprem1","fdecstp","fincstp", + }, + + /* d9_7 4 */ + { + "fprem","fyl2xp1","fsqrt","fsincos","frndint","fscale","fsin","fcos", + }, + + /* da_5 5 */ + { + "(bad)","fucompp","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)", + }, + + /* db_4 6 */ + { + "feni(287 only)","fdisi(287 only)","fNclex","fNinit", + "fNsetpm(287 only)","(bad)","(bad)","(bad)", + }, + + /* de_3 7 */ + { + "(bad)","fcompp","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)", + }, + + /* df_4 8 */ + { + "fNstsw","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)","(bad)", + }, +}; + +static void +dofloat (int sizeflag) +{ + const struct dis386 *dp; + unsigned char floatop; + + floatop = codep[-1]; + + if (mod != 3) + { + int fp_indx = (floatop - 0xd8) * 8 + reg; + + putop (float_mem[fp_indx], sizeflag); + obufp = op1out; + OP_E (float_mem_mode[fp_indx], sizeflag); + return; + } + /* Skip mod/rm byte. */ + MODRM_CHECK; + codep++; + + dp = &float_reg[floatop - 0xd8][reg]; + if (dp->name == NULL) + { + putop (fgrps[dp->bytemode1][rm], sizeflag); + + /* Instruction fnstsw is only one with strange arg. */ + if (floatop == 0xdf && codep[-1] == 0xe0) + strcpy (op1out, names16[0]); + } + else + { + putop (dp->name, sizeflag); + + obufp = op1out; + if (dp->op1) + (*dp->op1) (dp->bytemode1, sizeflag); + obufp = op2out; + if (dp->op2) + (*dp->op2) (dp->bytemode2, sizeflag); + } +} + +static void +OP_ST (int bytemode ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED) +{ + oappend ("%st"); +} + +static void +OP_STi (int bytemode ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED) +{ + sprintf (scratchbuf, "%%st(%d)", rm); + oappend (scratchbuf + intel_syntax); +} + +/* Capital letters in template are macros. */ +static int +putop (const char *template, int sizeflag) +{ + const char *p; + int alt = 0; + + for (p = template; *p; p++) + { + switch (*p) + { + default: + *obufp++ = *p; + break; + case '{': + alt = 0; + if (intel_syntax) + alt += 1; + if (mode_64bit) + alt += 2; + while (alt != 0) + { + while (*++p != '|') + { + if (*p == '}') + { + /* Alternative not valid. */ + strcpy (obuf, "(bad)"); + obufp = obuf + 5; + return 1; + } + else if (*p == '\0') + abort (); + } + alt--; + } + /* Fall through. */ + case 'I': + alt = 1; + continue; + case '|': + while (*++p != '}') + { + if (*p == '\0') + abort (); + } + break; + case '}': + break; + case 'A': + if (intel_syntax) + break; + if (mod != 3 || (sizeflag & SUFFIX_ALWAYS)) + *obufp++ = 'b'; + break; + case 'B': + if (intel_syntax) + break; + if (sizeflag & SUFFIX_ALWAYS) + *obufp++ = 'b'; + break; + case 'C': + if (intel_syntax && !alt) + break; + if ((prefixes & PREFIX_DATA) || (sizeflag & SUFFIX_ALWAYS)) + { + if (sizeflag & DFLAG) + *obufp++ = intel_syntax ? 'd' : 'l'; + else + *obufp++ = intel_syntax ? 'w' : 's'; + used_prefixes |= (prefixes & PREFIX_DATA); + } + break; + case 'E': /* For jcxz/jecxz */ + if (mode_64bit) + { + if (sizeflag & AFLAG) + *obufp++ = 'r'; + else + *obufp++ = 'e'; + } + else + if (sizeflag & AFLAG) + *obufp++ = 'e'; + used_prefixes |= (prefixes & PREFIX_ADDR); + break; + case 'F': + if (intel_syntax) + break; + if ((prefixes & PREFIX_ADDR) || (sizeflag & SUFFIX_ALWAYS)) + { + if (sizeflag & AFLAG) + *obufp++ = mode_64bit ? 'q' : 'l'; + else + *obufp++ = mode_64bit ? 'l' : 'w'; + used_prefixes |= (prefixes & PREFIX_ADDR); + } + break; + case 'H': + if (intel_syntax) + break; + if ((prefixes & (PREFIX_CS | PREFIX_DS)) == PREFIX_CS + || (prefixes & (PREFIX_CS | PREFIX_DS)) == PREFIX_DS) + { + used_prefixes |= prefixes & (PREFIX_CS | PREFIX_DS); + *obufp++ = ','; + *obufp++ = 'p'; + if (prefixes & PREFIX_DS) + *obufp++ = 't'; + else + *obufp++ = 'n'; + } + break; + case 'J': + if (intel_syntax) + break; + *obufp++ = 'l'; + break; + case 'L': + if (intel_syntax) + break; + if (sizeflag & SUFFIX_ALWAYS) + *obufp++ = 'l'; + break; + case 'N': + if ((prefixes & PREFIX_FWAIT) == 0) + *obufp++ = 'n'; + else + used_prefixes |= PREFIX_FWAIT; + break; + case 'O': + USED_REX (REX_MODE64); + if (rex & REX_MODE64) + *obufp++ = 'o'; + else + *obufp++ = 'd'; + break; + case 'T': + if (intel_syntax) + break; + if (mode_64bit) + { + *obufp++ = 'q'; + break; + } + /* Fall through. */ + case 'P': + if (intel_syntax) + break; + if ((prefixes & PREFIX_DATA) + || (rex & REX_MODE64) + || (sizeflag & SUFFIX_ALWAYS)) + { + USED_REX (REX_MODE64); + if (rex & REX_MODE64) + *obufp++ = 'q'; + else + { + if (sizeflag & DFLAG) + *obufp++ = 'l'; + else + *obufp++ = 'w'; + used_prefixes |= (prefixes & PREFIX_DATA); + } + } + break; + case 'U': + if (intel_syntax) + break; + if (mode_64bit) + { + *obufp++ = 'q'; + break; + } + /* Fall through. */ + case 'Q': + if (intel_syntax && !alt) + break; + USED_REX (REX_MODE64); + if (mod != 3 || (sizeflag & SUFFIX_ALWAYS)) + { + if (rex & REX_MODE64) + *obufp++ = 'q'; + else + { + if (sizeflag & DFLAG) + *obufp++ = intel_syntax ? 'd' : 'l'; + else + *obufp++ = 'w'; + used_prefixes |= (prefixes & PREFIX_DATA); + } + } + break; + case 'R': + USED_REX (REX_MODE64); + if (intel_syntax) + { + if (rex & REX_MODE64) + { + *obufp++ = 'q'; + *obufp++ = 't'; + } + else if (sizeflag & DFLAG) + { + *obufp++ = 'd'; + *obufp++ = 'q'; + } + else + { + *obufp++ = 'w'; + *obufp++ = 'd'; + } + } + else + { + if (rex & REX_MODE64) + *obufp++ = 'q'; + else if (sizeflag & DFLAG) + *obufp++ = 'l'; + else + *obufp++ = 'w'; + } + if (!(rex & REX_MODE64)) + used_prefixes |= (prefixes & PREFIX_DATA); + break; + case 'S': + if (intel_syntax) + break; + if (sizeflag & SUFFIX_ALWAYS) + { + if (rex & REX_MODE64) + *obufp++ = 'q'; + else + { + if (sizeflag & DFLAG) + *obufp++ = 'l'; + else + *obufp++ = 'w'; + used_prefixes |= (prefixes & PREFIX_DATA); + } + } + break; + case 'X': + if (prefixes & PREFIX_DATA) + *obufp++ = 'd'; + else + *obufp++ = 's'; + used_prefixes |= (prefixes & PREFIX_DATA); + break; + case 'Y': + if (intel_syntax) + break; + if (rex & REX_MODE64) + { + USED_REX (REX_MODE64); + *obufp++ = 'q'; + } + break; + /* implicit operand size 'l' for i386 or 'q' for x86-64 */ + case 'W': + /* operand size flag for cwtl, cbtw */ + USED_REX (0); + if (rex) + *obufp++ = 'l'; + else if (sizeflag & DFLAG) + *obufp++ = 'w'; + else + *obufp++ = 'b'; + if (intel_syntax) + { + if (rex) + { + *obufp++ = 'q'; + *obufp++ = 'e'; + } + if (sizeflag & DFLAG) + { + *obufp++ = 'd'; + *obufp++ = 'e'; + } + else + { + *obufp++ = 'w'; + } + } + if (!rex) + used_prefixes |= (prefixes & PREFIX_DATA); + break; + } + alt = 0; + } + *obufp = 0; + return 0; +} + +static void +oappend (const char *s) +{ + strcpy (obufp, s); + obufp += strlen (s); +} + +static void +append_seg (void) +{ + if (prefixes & PREFIX_CS) + { + used_prefixes |= PREFIX_CS; + oappend ("%cs:" + intel_syntax); + } + if (prefixes & PREFIX_DS) + { + used_prefixes |= PREFIX_DS; + oappend ("%ds:" + intel_syntax); + } + if (prefixes & PREFIX_SS) + { + used_prefixes |= PREFIX_SS; + oappend ("%ss:" + intel_syntax); + } + if (prefixes & PREFIX_ES) + { + used_prefixes |= PREFIX_ES; + oappend ("%es:" + intel_syntax); + } + if (prefixes & PREFIX_FS) + { + used_prefixes |= PREFIX_FS; + oappend ("%fs:" + intel_syntax); + } + if (prefixes & PREFIX_GS) + { + used_prefixes |= PREFIX_GS; + oappend ("%gs:" + intel_syntax); + } +} + +static void +OP_indirE (int bytemode, int sizeflag) +{ + if (!intel_syntax) + oappend ("*"); + OP_E (bytemode, sizeflag); +} + +static void +print_operand_value (char *buf, int hex, bfd_vma disp) +{ +#ifdef CONFIG_AMD64 // fm3 + if (hex) + sprintf (buf, "0x%lx", disp); + else + sprintf (buf, "%ld", disp); +#else + if (hex) + sprintf (buf, "0x%x", (unsigned int) disp); + else + sprintf (buf, "%d", (int) disp); +#endif +} + +static void +OP_E (int bytemode, int sizeflag) +{ + bfd_vma disp; + int add = 0; + int riprel = 0; + USED_REX (REX_EXTZ); + if (rex & REX_EXTZ) + add += 8; + + /* Skip mod/rm byte. */ + MODRM_CHECK; + codep++; + + if (mod == 3) + { + switch (bytemode) + { + case b_mode: + USED_REX (0); + if (rex) + oappend (names8rex[rm + add]); + else + oappend (names8[rm + add]); + break; + case w_mode: + oappend (names16[rm + add]); + break; + case d_mode: + oappend (names32[rm + add]); + break; + case q_mode: + oappend (names64[rm + add]); + break; + case m_mode: + if (mode_64bit) + oappend (names64[rm + add]); + else + oappend (names32[rm + add]); + break; + case v_mode: + case dq_mode: + case dqw_mode: + USED_REX (REX_MODE64); + if (rex & REX_MODE64) + oappend (names64[rm + add]); + else if ((sizeflag & DFLAG) || bytemode != v_mode) + oappend (names32[rm + add]); + else + oappend (names16[rm + add]); + used_prefixes |= (prefixes & PREFIX_DATA); + break; + case 0: + break; + default: + oappend (INTERNAL_DISASSEMBLER_ERROR); + break; + } + return; + } + + disp = 0; + append_seg (); + + if ((sizeflag & AFLAG) || mode_64bit) /* 32 bit address mode */ + { + int havesib; + int havebase; + int base; + int index = 0; + int scale = 0; + int dec = 0; // fm3 + + havesib = 0; + havebase = 1; + base = rm; + + if (base == 4) + { + havesib = 1; + FETCH_DATA (the_info, codep + 1); + index = (*codep >> 3) & 7; + if (mode_64bit || index != 0x4) + /* When INDEX == 0x4 in 32 bit mode, SCALE is ignored. */ + scale = (*codep >> 6) & 3; + base = *codep & 7; + USED_REX (REX_EXTY); + USED_REX (REX_EXTZ); + if (rex & REX_EXTY) + index += 8; + if (rex & REX_EXTZ) + base += 8; + codep++; + } + + switch (mod) + { + case 0: + if ((base & 7) == 5) + { + havebase = 0; + if (mode_64bit && !havesib) + riprel = 1; + disp = get32s (); + } + break; + case 1: + FETCH_DATA (the_info, codep + 1); + disp = *codep++; + if ((disp & 0x80) != 0) + disp -= 0x100; + dec = 1; // fm3 + break; + case 2: + disp = get32s (); + break; + } + + if (!intel_syntax) + if (mod != 0 || (base & 7) == 5) + { + set_op(disp, 0); // fm3 + print_operand_value (scratchbuf, !riprel, disp); + oappend (scratchbuf); + if (riprel) + { + set_op (disp, 1); + oappend ("(%rip)"); + } + } + + if (havebase || (havesib && (index != 4 || scale != 0))) + { + if (intel_syntax) + { + switch (bytemode) + { + case b_mode: + oappend ("BYTE PTR "); + break; + case w_mode: + case dqw_mode: + oappend ("WORD PTR "); + break; + case v_mode: + case dq_mode: + USED_REX (REX_MODE64); + if (rex & REX_MODE64) + oappend ("QWORD PTR "); + else if ((sizeflag & DFLAG) || bytemode == dq_mode) + oappend ("DWORD PTR "); + else + oappend ("WORD PTR "); + used_prefixes |= (prefixes & PREFIX_DATA); + break; + case d_mode: + oappend ("DWORD PTR "); + break; + case q_mode: + oappend ("QWORD PTR "); + break; + case m_mode: + if (mode_64bit) + oappend ("QWORD PTR "); + else + oappend ("DWORD PTR "); + break; + case f_mode: + if (sizeflag & DFLAG) + { + used_prefixes |= (prefixes & PREFIX_DATA); + oappend ("FWORD PTR "); + } + else + oappend ("DWORD PTR "); + break; + case t_mode: + oappend ("TBYTE PTR "); + break; + case x_mode: + oappend ("XMMWORD PTR "); + break; + default: + break; + } + } + *obufp++ = open_char; + if (intel_syntax && riprel) + oappend ("rip + "); + *obufp = '\0'; + USED_REX (REX_EXTZ); + if (!havesib && (rex & REX_EXTZ)) + base += 8; + if (havebase) + oappend (mode_64bit && (sizeflag & AFLAG) + ? names64[base] : names32[base]); + if (havesib) + { + if (index != 4) + { + if (!intel_syntax || havebase) + { + *obufp++ = separator_char; + *obufp = '\0'; + } + oappend (mode_64bit && (sizeflag & AFLAG) + ? names64[index] : names32[index]); + } + if (scale != 0 || (!intel_syntax && index != 4)) + { + *obufp++ = scale_char; + *obufp = '\0'; + sprintf (scratchbuf, "%d", 1 << scale); + oappend (scratchbuf); + } + } + if (intel_syntax) + if (mod != 0 || (base & 7) == 5) + { + /* Don't print zero displacements. */ + if (disp != 0) + { + if ((bfd_signed_vma) disp > 0) + { + *obufp++ = '+'; + *obufp = '\0'; + } + + print_operand_value (scratchbuf, 0, disp); + oappend (scratchbuf); + } + } + + *obufp++ = close_char; + *obufp = '\0'; + } + else if (intel_syntax) + { + if (mod != 0 || (base & 7) == 5) + { + if (prefixes & (PREFIX_CS | PREFIX_SS | PREFIX_DS + | PREFIX_ES | PREFIX_FS | PREFIX_GS)) + ; + else + { + oappend (names_seg[ds_reg - es_reg]); + oappend (":"); + } + print_operand_value (scratchbuf, 1, disp); + oappend (scratchbuf); + } + } + } + else + { /* 16 bit address mode */ + switch (mod) + { + case 0: + if ((rm & 7) == 6) + { + disp = get16 (); + if ((disp & 0x8000) != 0) + disp -= 0x10000; + } + break; + case 1: + FETCH_DATA (the_info, codep + 1); + disp = *codep++; + if ((disp & 0x80) != 0) + disp -= 0x100; + break; + case 2: + disp = get16 (); + if ((disp & 0x8000) != 0) + disp -= 0x10000; + break; + } + + if (!intel_syntax) + if (mod != 0 || (rm & 7) == 6) + { + print_operand_value (scratchbuf, 0, disp); + oappend (scratchbuf); + } + + if (mod != 0 || (rm & 7) != 6) + { + *obufp++ = open_char; + *obufp = '\0'; + oappend (index16[rm + add]); + *obufp++ = close_char; + *obufp = '\0'; + } + } +} + +static void +OP_G (int bytemode, int sizeflag) +{ + int add = 0; + USED_REX (REX_EXTX); + if (rex & REX_EXTX) + add += 8; + switch (bytemode) + { + case b_mode: + USED_REX (0); + if (rex) + oappend (names8rex[reg + add]); + else + oappend (names8[reg + add]); + break; + case w_mode: + oappend (names16[reg + add]); + break; + case d_mode: + oappend (names32[reg + add]); + break; + case q_mode: + oappend (names64[reg + add]); + break; + case v_mode: + case dq_mode: + case dqw_mode: + USED_REX (REX_MODE64); + if (rex & REX_MODE64) + oappend (names64[reg + add]); + else if ((sizeflag & DFLAG) || bytemode != v_mode) + oappend (names32[reg + add]); + else + oappend (names16[reg + add]); + used_prefixes |= (prefixes & PREFIX_DATA); + break; + default: + oappend (INTERNAL_DISASSEMBLER_ERROR); + break; + } +} + +static bfd_vma +get64 (void) +{ + bfd_vma x; +#ifdef BFD64 + unsigned int a; + unsigned int b; + + FETCH_DATA (the_info, codep + 8); + a = *codep++ & 0xff; + a |= (*codep++ & 0xff) << 8; + a |= (*codep++ & 0xff) << 16; + a |= (*codep++ & 0xff) << 24; + b = *codep++ & 0xff; + b |= (*codep++ & 0xff) << 8; + b |= (*codep++ & 0xff) << 16; + b |= (*codep++ & 0xff) << 24; + x = a + ((bfd_vma) b << 32); +#else + abort (); + x = 0; +#endif + return x; +} + +static bfd_signed_vma +get32 (void) +{ + bfd_signed_vma x = 0; + + FETCH_DATA (the_info, codep + 4); + x = *codep++ & (bfd_signed_vma) 0xff; + x |= (*codep++ & (bfd_signed_vma) 0xff) << 8; + x |= (*codep++ & (bfd_signed_vma) 0xff) << 16; + x |= (*codep++ & (bfd_signed_vma) 0xff) << 24; + return x; +} + +static bfd_signed_vma +get32s (void) +{ + bfd_signed_vma x = 0; + + FETCH_DATA (the_info, codep + 4); + x = *codep++ & (bfd_signed_vma) 0xff; + x |= (*codep++ & (bfd_signed_vma) 0xff) << 8; + x |= (*codep++ & (bfd_signed_vma) 0xff) << 16; + x |= (*codep++ & (bfd_signed_vma) 0xff) << 24; + + x = (x ^ ((bfd_signed_vma) 1 << 31)) - ((bfd_signed_vma) 1 << 31); + + return x; +} + +static int +get16 (void) +{ + int x = 0; + + FETCH_DATA (the_info, codep + 2); + x = *codep++ & 0xff; + x |= (*codep++ & 0xff) << 8; + return x; +} + +static void +set_op (bfd_vma op, int riprel) +{ + op_index[op_ad] = op_ad; + if (mode_64bit) + { + op_address[op_ad] = op; + op_riprel[op_ad] = riprel; + } + else + { + /* Mask to get a 32-bit address. */ + op_address[op_ad] = op & 0xffffffff; + op_riprel[op_ad] = riprel & 0xffffffff; + } +} + +static void +OP_REG (int code, int sizeflag) +{ + const char *s; + int add = 0; + USED_REX (REX_EXTZ); + if (rex & REX_EXTZ) + add = 8; + + switch (code) + { + case indir_dx_reg: + if (intel_syntax) + s = "[dx]"; + else + s = "(%dx)"; + break; + case ax_reg: case cx_reg: case dx_reg: case bx_reg: + case sp_reg: case bp_reg: case si_reg: case di_reg: + s = names16[code - ax_reg + add]; + break; + case es_reg: case ss_reg: case cs_reg: + case ds_reg: case fs_reg: case gs_reg: + s = names_seg[code - es_reg + add]; + break; + case al_reg: case ah_reg: case cl_reg: case ch_reg: + case dl_reg: case dh_reg: case bl_reg: case bh_reg: + USED_REX (0); + if (rex) + s = names8rex[code - al_reg + add]; + else + s = names8[code - al_reg]; + break; + case rAX_reg: case rCX_reg: case rDX_reg: case rBX_reg: + case rSP_reg: case rBP_reg: case rSI_reg: case rDI_reg: + if (mode_64bit) + { + s = names64[code - rAX_reg + add]; + break; + } + code += eAX_reg - rAX_reg; + /* Fall through. */ + case eAX_reg: case eCX_reg: case eDX_reg: case eBX_reg: + case eSP_reg: case eBP_reg: case eSI_reg: case eDI_reg: + USED_REX (REX_MODE64); + if (rex & REX_MODE64) + s = names64[code - eAX_reg + add]; + else if (sizeflag & DFLAG) + s = names32[code - eAX_reg + add]; + else + s = names16[code - eAX_reg + add]; + used_prefixes |= (prefixes & PREFIX_DATA); + break; + default: + s = INTERNAL_DISASSEMBLER_ERROR; + break; + } + oappend (s); +} + +static void +OP_IMREG (int code, int sizeflag) +{ + const char *s; + + switch (code) + { + case indir_dx_reg: + if (intel_syntax) + s = "[dx]"; + else + s = "(%dx)"; + break; + case ax_reg: case cx_reg: case dx_reg: case bx_reg: + case sp_reg: case bp_reg: case si_reg: case di_reg: + s = names16[code - ax_reg]; + break; + case es_reg: case ss_reg: case cs_reg: + case ds_reg: case fs_reg: case gs_reg: + s = names_seg[code - es_reg]; + break; + case al_reg: case ah_reg: case cl_reg: case ch_reg: + case dl_reg: case dh_reg: case bl_reg: case bh_reg: + USED_REX (0); + if (rex) + s = names8rex[code - al_reg]; + else + s = names8[code - al_reg]; + break; + case eAX_reg: case eCX_reg: case eDX_reg: case eBX_reg: + case eSP_reg: case eBP_reg: case eSI_reg: case eDI_reg: + USED_REX (REX_MODE64); + if (rex & REX_MODE64) + s = names64[code - eAX_reg]; + else if (sizeflag & DFLAG) + s = names32[code - eAX_reg]; + else + s = names16[code - eAX_reg]; + used_prefixes |= (prefixes & PREFIX_DATA); + break; + default: + s = INTERNAL_DISASSEMBLER_ERROR; + break; + } + oappend (s); +} + +static void +OP_I (int bytemode, int sizeflag) +{ + bfd_signed_vma op; + bfd_signed_vma mask = -1; + + switch (bytemode) + { + case b_mode: + FETCH_DATA (the_info, codep + 1); + op = *codep++; + mask = 0xff; + break; + case q_mode: + if (mode_64bit) + { + op = get32s (); + break; + } + /* Fall through. */ + case v_mode: + USED_REX (REX_MODE64); + if (rex & REX_MODE64) + op = get32s (); + else if (sizeflag & DFLAG) + { + op = get32 (); + mask = 0xffffffff; + } + else + { + op = get16 (); + mask = 0xfffff; + } + used_prefixes |= (prefixes & PREFIX_DATA); + break; + case w_mode: + mask = 0xfffff; + op = get16 (); + break; + case const_1_mode: + if (intel_syntax) + oappend ("1"); + return; + default: + oappend (INTERNAL_DISASSEMBLER_ERROR); + return; + } + + op &= mask; + scratchbuf[0] = '$'; + print_operand_value (scratchbuf + 1, 1, op); + oappend (scratchbuf + intel_syntax); + scratchbuf[0] = '\0'; +} + +static void +OP_I64 (int bytemode, int sizeflag) +{ + bfd_signed_vma op; + bfd_signed_vma mask = -1; + + if (!mode_64bit) + { + OP_I (bytemode, sizeflag); + return; + } + + switch (bytemode) + { + case b_mode: + FETCH_DATA (the_info, codep + 1); + op = *codep++; + mask = 0xff; + break; + case v_mode: + USED_REX (REX_MODE64); + if (rex & REX_MODE64) + op = get64 (); + else if (sizeflag & DFLAG) + { + op = get32 (); + mask = 0xffffffff; + } + else + { + op = get16 (); + mask = 0xfffff; + } + used_prefixes |= (prefixes & PREFIX_DATA); + break; + case w_mode: + mask = 0xfffff; + op = get16 (); + break; + default: + oappend (INTERNAL_DISASSEMBLER_ERROR); + return; + } + + op &= mask; + scratchbuf[0] = '$'; + print_operand_value (scratchbuf + 1, 1, op); + oappend (scratchbuf + intel_syntax); + scratchbuf[0] = '\0'; +} + +static void +OP_sI (int bytemode, int sizeflag) +{ + bfd_signed_vma op; + bfd_signed_vma mask = -1; + + switch (bytemode) + { + case b_mode: + FETCH_DATA (the_info, codep + 1); + op = *codep++; + if ((op & 0x80) != 0) + op -= 0x100; + mask = 0xffffffff; + break; + case v_mode: + USED_REX (REX_MODE64); + if (rex & REX_MODE64) + op = get32s (); + else if (sizeflag & DFLAG) + { + op = get32s (); + mask = 0xffffffff; + } + else + { + mask = 0xffffffff; + op = get16 (); + if ((op & 0x8000) != 0) + op -= 0x10000; + } + used_prefixes |= (prefixes & PREFIX_DATA); + break; + case w_mode: + op = get16 (); + mask = 0xffffffff; + if ((op & 0x8000) != 0) + op -= 0x10000; + break; + default: + oappend (INTERNAL_DISASSEMBLER_ERROR); + return; + } + + scratchbuf[0] = '$'; + print_operand_value (scratchbuf + 1, 1, op); + oappend (scratchbuf + intel_syntax); +} + +static void +OP_J (int bytemode, int sizeflag) +{ + bfd_vma disp; + bfd_vma mask = -1; + + switch (bytemode) + { + case b_mode: + FETCH_DATA (the_info, codep + 1); + disp = *codep++; + if ((disp & 0x80) != 0) + disp -= 0x100; + break; + case v_mode: + if (sizeflag & DFLAG) + disp = get32s (); + else + { + disp = get16 (); + /* For some reason, a data16 prefix on a jump instruction + means that the pc is masked to 16 bits after the + displacement is added! */ + mask = 0xffff; + } + break; + default: + oappend (INTERNAL_DISASSEMBLER_ERROR); + return; + } + disp = (start_pc + codep - start_codep + disp) & mask; + set_op (disp, 0); + print_operand_value (scratchbuf, 1, disp); + oappend (scratchbuf); +} + +static void +OP_SEG (int dummy ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED) +{ + oappend (names_seg[reg]); +} + +static void +OP_DIR (int dummy ATTRIBUTE_UNUSED, int sizeflag) +{ + int seg, offset; + + if (sizeflag & DFLAG) + { + offset = get32 (); + seg = get16 (); + } + else + { + offset = get16 (); + seg = get16 (); + } + used_prefixes |= (prefixes & PREFIX_DATA); + if (intel_syntax) + sprintf (scratchbuf, "0x%x,0x%x", seg, offset); + else + sprintf (scratchbuf, "$0x%x,$0x%x", seg, offset); + oappend (scratchbuf); +} + +static void +OP_OFF (int bytemode ATTRIBUTE_UNUSED, int sizeflag) +{ + bfd_vma off; + + append_seg (); + + if ((sizeflag & AFLAG) || mode_64bit) + off = get32 (); + else + off = get16 (); + + if (intel_syntax) + { + if (!(prefixes & (PREFIX_CS | PREFIX_SS | PREFIX_DS + | PREFIX_ES | PREFIX_FS | PREFIX_GS))) + { + oappend (names_seg[ds_reg - es_reg]); + oappend (":"); + } + } + set_op(off, 0); // fm3 + print_operand_value (scratchbuf, 1, off); + oappend (scratchbuf); +} + +static void +OP_OFF64 (int bytemode ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED) +{ + bfd_vma off; + + if (!mode_64bit) + { + OP_OFF (bytemode, sizeflag); + return; + } + + append_seg (); + + off = get64 (); + + if (intel_syntax) + { + if (!(prefixes & (PREFIX_CS | PREFIX_SS | PREFIX_DS + | PREFIX_ES | PREFIX_FS | PREFIX_GS))) + { + oappend (names_seg[ds_reg - es_reg]); + oappend (":"); + } + } + print_operand_value (scratchbuf, 1, off); + oappend (scratchbuf); +} + +static void +ptr_reg (int code, int sizeflag) +{ + const char *s; + + *obufp++ = open_char; + used_prefixes |= (prefixes & PREFIX_ADDR); + if (mode_64bit) + { + if (!(sizeflag & AFLAG)) + s = names32[code - eAX_reg]; + else + s = names64[code - eAX_reg]; + } + else if (sizeflag & AFLAG) + s = names32[code - eAX_reg]; + else + s = names16[code - eAX_reg]; + oappend (s); + *obufp++ = close_char; + *obufp = 0; +} + +static void +OP_ESreg (int code, int sizeflag) +{ + if (intel_syntax) + { + if (codep[-1] & 1) + { + USED_REX (REX_MODE64); + used_prefixes |= (prefixes & PREFIX_DATA); + if (rex & REX_MODE64) + oappend ("QWORD PTR "); + else if ((sizeflag & DFLAG)) + oappend ("DWORD PTR "); + else + oappend ("WORD PTR "); + } + else + oappend ("BYTE PTR "); + } + + oappend ("%es:" + intel_syntax); + ptr_reg (code, sizeflag); +} + +static void +OP_DSreg (int code, int sizeflag) +{ + if (intel_syntax) + { + if (codep[-1] != 0xd7 && (codep[-1] & 1)) + { + USED_REX (REX_MODE64); + used_prefixes |= (prefixes & PREFIX_DATA); + if (rex & REX_MODE64) + oappend ("QWORD PTR "); + else if ((sizeflag & DFLAG)) + oappend ("DWORD PTR "); + else + oappend ("WORD PTR "); + } + else + oappend ("BYTE PTR "); + } + + if ((prefixes + & (PREFIX_CS + | PREFIX_DS + | PREFIX_SS + | PREFIX_ES + | PREFIX_FS + | PREFIX_GS)) == 0) + prefixes |= PREFIX_DS; + append_seg (); + ptr_reg (code, sizeflag); +} + +static void +OP_C (int dummy ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED) +{ + int add = 0; + if (rex & REX_EXTX) + { + USED_REX (REX_EXTX); + add = 8; + } + else if (!mode_64bit && (prefixes & PREFIX_LOCK)) + { + used_prefixes |= PREFIX_LOCK; + add = 8; + } + sprintf (scratchbuf, "%%cr%d", reg + add); + oappend (scratchbuf + intel_syntax); +} + +static void +OP_D (int dummy ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED) +{ + int add = 0; + USED_REX (REX_EXTX); + if (rex & REX_EXTX) + add = 8; + if (intel_syntax) + sprintf (scratchbuf, "db%d", reg + add); + else + sprintf (scratchbuf, "%%db%d", reg + add); + oappend (scratchbuf); +} + +static void +OP_T (int dummy ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED) +{ + sprintf (scratchbuf, "%%tr%d", reg); + oappend (scratchbuf + intel_syntax); +} + +static void +OP_Rd (int bytemode, int sizeflag) +{ + if (mod == 3) + OP_E (bytemode, sizeflag); + else + BadOp (); +} + +static void +OP_MMX (int bytemode ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED) +{ + used_prefixes |= (prefixes & PREFIX_DATA); + if (prefixes & PREFIX_DATA) + { + int add = 0; + USED_REX (REX_EXTX); + if (rex & REX_EXTX) + add = 8; + sprintf (scratchbuf, "%%xmm%d", reg + add); + } + else + sprintf (scratchbuf, "%%mm%d", reg); + oappend (scratchbuf + intel_syntax); +} + +static void +OP_XMM (int bytemode ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED) +{ + int add = 0; + USED_REX (REX_EXTX); + if (rex & REX_EXTX) + add = 8; + sprintf (scratchbuf, "%%xmm%d", reg + add); + oappend (scratchbuf + intel_syntax); +} + +static void +OP_EM (int bytemode, int sizeflag) +{ + if (mod != 3) + { + if (intel_syntax && bytemode == v_mode) + { + bytemode = (prefixes & PREFIX_DATA) ? x_mode : q_mode; + used_prefixes |= (prefixes & PREFIX_DATA); + } + OP_E (bytemode, sizeflag); + return; + } + + /* Skip mod/rm byte. */ + MODRM_CHECK; + codep++; + used_prefixes |= (prefixes & PREFIX_DATA); + if (prefixes & PREFIX_DATA) + { + int add = 0; + + USED_REX (REX_EXTZ); + if (rex & REX_EXTZ) + add = 8; + sprintf (scratchbuf, "%%xmm%d", rm + add); + } + else + sprintf (scratchbuf, "%%mm%d", rm); + oappend (scratchbuf + intel_syntax); +} + +static void +OP_EX (int bytemode, int sizeflag) +{ + int add = 0; + if (mod != 3) + { + if (intel_syntax && bytemode == v_mode) + { + switch (prefixes & (PREFIX_DATA|PREFIX_REPZ|PREFIX_REPNZ)) + { + case 0: bytemode = x_mode; break; + case PREFIX_REPZ: bytemode = d_mode; used_prefixes |= PREFIX_REPZ; break; + case PREFIX_DATA: bytemode = x_mode; used_prefixes |= PREFIX_DATA; break; + case PREFIX_REPNZ: bytemode = q_mode; used_prefixes |= PREFIX_REPNZ; break; + default: bytemode = 0; break; + } + } + OP_E (bytemode, sizeflag); + return; + } + USED_REX (REX_EXTZ); + if (rex & REX_EXTZ) + add = 8; + + /* Skip mod/rm byte. */ + MODRM_CHECK; + codep++; + sprintf (scratchbuf, "%%xmm%d", rm + add); + oappend (scratchbuf + intel_syntax); +} + +static void +OP_MS (int bytemode, int sizeflag) +{ + if (mod == 3) + OP_EM (bytemode, sizeflag); + else + BadOp (); +} + +static void +OP_XS (int bytemode, int sizeflag) +{ + if (mod == 3) + OP_EX (bytemode, sizeflag); + else + BadOp (); +} + +static void +OP_M (int bytemode, int sizeflag) +{ + if (mod == 3) + BadOp (); /* bad lea,lds,les,lfs,lgs,lss modrm */ + else + OP_E (bytemode, sizeflag); +} + +static void +OP_0f07 (int bytemode, int sizeflag) +{ + if (mod != 3 || rm != 0) + BadOp (); + else + OP_E (bytemode, sizeflag); +} + +static void +OP_0fae (int bytemode, int sizeflag) +{ + if (mod == 3) + { + if (reg == 7) + strcpy (obuf + strlen (obuf) - sizeof ("clflush") + 1, "sfence"); + + if (reg < 5 || rm != 0) + { + BadOp (); /* bad sfence, mfence, or lfence */ + return; + } + } + else if (reg != 7) + { + BadOp (); /* bad clflush */ + return; + } + + OP_E (bytemode, sizeflag); +} + +static void +NOP_Fixup (int bytemode ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED) +{ + /* NOP with REPZ prefix is called PAUSE. */ + if (prefixes == PREFIX_REPZ) + strcpy (obuf, "pause"); +} + +static const char *const Suffix3DNow[] = { +/* 00 */ NULL, NULL, NULL, NULL, +/* 04 */ NULL, NULL, NULL, NULL, +/* 08 */ NULL, NULL, NULL, NULL, +/* 0C */ "pi2fw", "pi2fd", NULL, NULL, +/* 10 */ NULL, NULL, NULL, NULL, +/* 14 */ NULL, NULL, NULL, NULL, +/* 18 */ NULL, NULL, NULL, NULL, +/* 1C */ "pf2iw", "pf2id", NULL, NULL, +/* 20 */ NULL, NULL, NULL, NULL, +/* 24 */ NULL, NULL, NULL, NULL, +/* 28 */ NULL, NULL, NULL, NULL, +/* 2C */ NULL, NULL, NULL, NULL, +/* 30 */ NULL, NULL, NULL, NULL, +/* 34 */ NULL, NULL, NULL, NULL, +/* 38 */ NULL, NULL, NULL, NULL, +/* 3C */ NULL, NULL, NULL, NULL, +/* 40 */ NULL, NULL, NULL, NULL, +/* 44 */ NULL, NULL, NULL, NULL, +/* 48 */ NULL, NULL, NULL, NULL, +/* 4C */ NULL, NULL, NULL, NULL, +/* 50 */ NULL, NULL, NULL, NULL, +/* 54 */ NULL, NULL, NULL, NULL, +/* 58 */ NULL, NULL, NULL, NULL, +/* 5C */ NULL, NULL, NULL, NULL, +/* 60 */ NULL, NULL, NULL, NULL, +/* 64 */ NULL, NULL, NULL, NULL, +/* 68 */ NULL, NULL, NULL, NULL, +/* 6C */ NULL, NULL, NULL, NULL, +/* 70 */ NULL, NULL, NULL, NULL, +/* 74 */ NULL, NULL, NULL, NULL, +/* 78 */ NULL, NULL, NULL, NULL, +/* 7C */ NULL, NULL, NULL, NULL, +/* 80 */ NULL, NULL, NULL, NULL, +/* 84 */ NULL, NULL, NULL, NULL, +/* 88 */ NULL, NULL, "pfnacc", NULL, +/* 8C */ NULL, NULL, "pfpnacc", NULL, +/* 90 */ "pfcmpge", NULL, NULL, NULL, +/* 94 */ "pfmin", NULL, "pfrcp", "pfrsqrt", +/* 98 */ NULL, NULL, "pfsub", NULL, +/* 9C */ NULL, NULL, "pfadd", NULL, +/* A0 */ "pfcmpgt", NULL, NULL, NULL, +/* A4 */ "pfmax", NULL, "pfrcpit1", "pfrsqit1", +/* A8 */ NULL, NULL, "pfsubr", NULL, +/* AC */ NULL, NULL, "pfacc", NULL, +/* B0 */ "pfcmpeq", NULL, NULL, NULL, +/* B4 */ "pfmul", NULL, "pfrcpit2", "pfmulhrw", +/* B8 */ NULL, NULL, NULL, "pswapd", +/* BC */ NULL, NULL, NULL, "pavgusb", +/* C0 */ NULL, NULL, NULL, NULL, +/* C4 */ NULL, NULL, NULL, NULL, +/* C8 */ NULL, NULL, NULL, NULL, +/* CC */ NULL, NULL, NULL, NULL, +/* D0 */ NULL, NULL, NULL, NULL, +/* D4 */ NULL, NULL, NULL, NULL, +/* D8 */ NULL, NULL, NULL, NULL, +/* DC */ NULL, NULL, NULL, NULL, +/* E0 */ NULL, NULL, NULL, NULL, +/* E4 */ NULL, NULL, NULL, NULL, +/* E8 */ NULL, NULL, NULL, NULL, +/* EC */ NULL, NULL, NULL, NULL, +/* F0 */ NULL, NULL, NULL, NULL, +/* F4 */ NULL, NULL, NULL, NULL, +/* F8 */ NULL, NULL, NULL, NULL, +/* FC */ NULL, NULL, NULL, NULL, +}; + +static void +OP_3DNowSuffix (int bytemode ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED) +{ + const char *mnemonic; + + FETCH_DATA (the_info, codep + 1); + /* AMD 3DNow! instructions are specified by an opcode suffix in the + place where an 8-bit immediate would normally go. ie. the last + byte of the instruction. */ + obufp = obuf + strlen (obuf); + mnemonic = Suffix3DNow[*codep++ & 0xff]; + if (mnemonic) + oappend (mnemonic); + else + { + /* Since a variable sized modrm/sib chunk is between the start + of the opcode (0x0f0f) and the opcode suffix, we need to do + all the modrm processing first, and don't know until now that + we have a bad opcode. This necessitates some cleaning up. */ + op1out[0] = '\0'; + op2out[0] = '\0'; + BadOp (); + } +} + +static const char *simd_cmp_op[] = { + "eq", + "lt", + "le", + "unord", + "neq", + "nlt", + "nle", + "ord" +}; + +static void +OP_SIMD_Suffix (int bytemode ATTRIBUTE_UNUSED, int sizeflag ATTRIBUTE_UNUSED) +{ + unsigned int cmp_type; + + FETCH_DATA (the_info, codep + 1); + obufp = obuf + strlen (obuf); + cmp_type = *codep++ & 0xff; + if (cmp_type < 8) + { + char suffix1 = 'p', suffix2 = 's'; + used_prefixes |= (prefixes & PREFIX_REPZ); + if (prefixes & PREFIX_REPZ) + suffix1 = 's'; + else + { + used_prefixes |= (prefixes & PREFIX_DATA); + if (prefixes & PREFIX_DATA) + suffix2 = 'd'; + else + { + used_prefixes |= (prefixes & PREFIX_REPNZ); + if (prefixes & PREFIX_REPNZ) + suffix1 = 's', suffix2 = 'd'; + } + } + sprintf (scratchbuf, "cmp%s%c%c", + simd_cmp_op[cmp_type], suffix1, suffix2); + used_prefixes |= (prefixes & PREFIX_REPZ); + oappend (scratchbuf); + } + else + { + /* We have a bad extension byte. Clean up. */ + op1out[0] = '\0'; + op2out[0] = '\0'; + BadOp (); + } +} + +static void +SIMD_Fixup (int extrachar, int sizeflag ATTRIBUTE_UNUSED) +{ + /* Change movlps/movhps to movhlps/movlhps for 2 register operand + forms of these instructions. */ + if (mod == 3) + { + char *p = obuf + strlen (obuf); + *(p + 1) = '\0'; + *p = *(p - 1); + *(p - 1) = *(p - 2); + *(p - 2) = *(p - 3); + *(p - 3) = extrachar; + } +} + +static void +PNI_Fixup (int extrachar ATTRIBUTE_UNUSED, int sizeflag) +{ + if (mod == 3 && reg == 1 && rm <= 1) + { + /* Override "sidt". */ + char *p = obuf + strlen (obuf) - 4; + + /* We might have a suffix. */ + if (*p == 'i') + --p; + + if (rm) + { + /* mwait %eax,%ecx */ + strcpy (p, "mwait"); + if (!intel_syntax) + strcpy (op1out, names32[0]); + } + else + { + /* monitor %eax,%ecx,%edx" */ + strcpy (p, "monitor"); + if (!intel_syntax) + { + if (!mode_64bit) + strcpy (op1out, names32[0]); + else if (!(prefixes & PREFIX_ADDR)) + strcpy (op1out, names64[0]); + else + { + strcpy (op1out, names32[0]); + used_prefixes |= PREFIX_ADDR; + } + strcpy (op3out, names32[2]); + } + } + if (!intel_syntax) + { + strcpy (op2out, names32[1]); + two_source_ops = 1; + } + + codep++; + } + else + OP_E (0, sizeflag); +} + +static void +INVLPG_Fixup (int bytemode, int sizeflag) +{ + const char *alt; + + switch (*codep) + { + case 0xf8: + alt = "swapgs"; + break; + case 0xf9: + alt = "rdtscp"; + break; + default: + OP_E (bytemode, sizeflag); + return; + } + /* Override "invlpg". */ + strcpy (obuf + strlen (obuf) - 6, alt); + codep++; +} + +static void +BadOp (void) +{ + /* Throw away prefixes and 1st. opcode byte. */ + codep = insn_codep + 1; + oappend ("(bad)"); +} diff --git a/kernel/fiasco/src/lib/disasm/opcodes/opintl.h b/kernel/fiasco/src/lib/disasm/opcodes/opintl.h new file mode 100644 index 00000000..077c790b --- /dev/null +++ b/kernel/fiasco/src/lib/disasm/opcodes/opintl.h @@ -0,0 +1,2 @@ + +# define _(String) (String) diff --git a/kernel/fiasco/src/lib/disasm/opcodes/ppc-dis.c b/kernel/fiasco/src/lib/disasm/opcodes/ppc-dis.c new file mode 100644 index 00000000..b3106f93 --- /dev/null +++ b/kernel/fiasco/src/lib/disasm/opcodes/ppc-dis.c @@ -0,0 +1,376 @@ +/* ppc-dis.c -- Disassemble PowerPC instructions + Copyright 1994, 1995, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 + Free Software Foundation, Inc. + Written by Ian Lance Taylor, Cygnus Support + + This file is part of the GNU opcodes library. + + This library is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + It is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + License for more details. + + You should have received a copy of the GNU General Public License + along with this file; see the file COPYING. If not, write to the + Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston, + MA 02110-1301, USA. */ + +#include +#include "sysdep.h" +#include "dis-asm.h" +#include "opcode/ppc.h" + +/* This file provides several disassembler functions, all of which use + the disassembler interface defined in dis-asm.h. Several functions + are provided because this file handles disassembly for the PowerPC + in both big and little endian mode and also for the POWER (RS/6000) + chip. */ + +static int print_insn_powerpc (bfd_vma, struct disassemble_info *, int, int); + +/* Determine which set of machines to disassemble for. PPC403/601 or + BookE. For convenience, also disassemble instructions supported + by the AltiVec vector unit. */ + +static int +powerpc_dialect (struct disassemble_info *info) +{ + int dialect = PPC_OPCODE_PPC; + + if (BFD_DEFAULT_TARGET_SIZE == 64) + dialect |= PPC_OPCODE_64; + + if (info->disassembler_options + && strstr (info->disassembler_options, "booke") != NULL) + dialect |= PPC_OPCODE_BOOKE | PPC_OPCODE_BOOKE64; + else if ((info->mach == bfd_mach_ppc_e500) + || (info->disassembler_options + && strstr (info->disassembler_options, "e500") != NULL)) + dialect |= (PPC_OPCODE_BOOKE + | PPC_OPCODE_SPE | PPC_OPCODE_ISEL + | PPC_OPCODE_EFS | PPC_OPCODE_BRLOCK + | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK + | PPC_OPCODE_RFMCI); + else if (info->disassembler_options + && strstr (info->disassembler_options, "efs") != NULL) + dialect |= PPC_OPCODE_EFS; + else if (info->disassembler_options + && strstr (info->disassembler_options, "e300") != NULL) + dialect |= PPC_OPCODE_E300 | PPC_OPCODE_CLASSIC | PPC_OPCODE_COMMON; + else if (info->disassembler_options + && strstr (info->disassembler_options, "440") != NULL) + dialect |= PPC_OPCODE_BOOKE | PPC_OPCODE_32 + | PPC_OPCODE_440 | PPC_OPCODE_ISEL | PPC_OPCODE_RFMCI; + else + dialect |= (PPC_OPCODE_403 | PPC_OPCODE_601 | PPC_OPCODE_CLASSIC + | PPC_OPCODE_COMMON | PPC_OPCODE_ALTIVEC); + + if (info->disassembler_options + && strstr (info->disassembler_options, "power4") != NULL) + dialect |= PPC_OPCODE_POWER4; + + if (info->disassembler_options + && strstr (info->disassembler_options, "power5") != NULL) + dialect |= PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5; + + if (info->disassembler_options + && strstr (info->disassembler_options, "cell") != NULL) + dialect |= PPC_OPCODE_POWER4 | PPC_OPCODE_CELL | PPC_OPCODE_ALTIVEC; + + if (info->disassembler_options + && strstr (info->disassembler_options, "power6") != NULL) + dialect |= PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_ALTIVEC; + + if (info->disassembler_options + && strstr (info->disassembler_options, "any") != NULL) + dialect |= PPC_OPCODE_ANY; + + if (info->disassembler_options) + { + if (strstr (info->disassembler_options, "32") != NULL) + dialect &= ~PPC_OPCODE_64; + else if (strstr (info->disassembler_options, "64") != NULL) + dialect |= PPC_OPCODE_64; + } + + info->private_data = (char *) 0 + dialect; + return dialect; +} + +/* Print a big endian PowerPC instruction. */ + +int +print_insn_big_powerpc (bfd_vma memaddr, struct disassemble_info *info) +{ + int dialect = (char *) info->private_data - (char *) 0; + return print_insn_powerpc (memaddr, info, 1, dialect); +} + +/* Print a little endian PowerPC instruction. */ + +int +print_insn_little_powerpc (bfd_vma memaddr, struct disassemble_info *info) +{ + int dialect = (char *) info->private_data - (char *) 0; + return print_insn_powerpc (memaddr, info, 0, dialect); +} + +/* Print a POWER (RS/6000) instruction. */ + +int +print_insn_rs6000 (bfd_vma memaddr, struct disassemble_info *info) +{ + return print_insn_powerpc (memaddr, info, 1, PPC_OPCODE_POWER); +} + +/* Extract the operand value from the PowerPC or POWER instruction. */ + +static long +operand_value_powerpc (const struct powerpc_operand *operand, + unsigned long insn, int dialect) +{ + long value; + int invalid; + /* Extract the value from the instruction. */ + if (operand->extract) + value = (*operand->extract) (insn, dialect, &invalid); + else + { + value = (insn >> operand->shift) & operand->bitm; + if ((operand->flags & PPC_OPERAND_SIGNED) != 0) + { + /* BITM is always some number of zeros followed by some + number of ones, followed by some numer of zeros. */ + unsigned long top = operand->bitm; + /* top & -top gives the rightmost 1 bit, so this + fills in any trailing zeros. */ + top |= (top & -top) - 1; + top &= ~(top >> 1); + value = (value ^ top) - top; + } + } + + return value; +} + +/* Determine whether the optional operand(s) should be printed. */ + +static int +skip_optional_operands (const unsigned char *opindex, + unsigned long insn, int dialect) +{ + const struct powerpc_operand *operand; + + for (; *opindex != 0; opindex++) + { + operand = &powerpc_operands[*opindex]; + if ((operand->flags & PPC_OPERAND_NEXT) != 0 + || ((operand->flags & PPC_OPERAND_OPTIONAL) != 0 + && operand_value_powerpc (operand, insn, dialect) != 0)) + return 0; + } + + return 1; +} + +/* Print a PowerPC or POWER instruction. */ + +static int +print_insn_powerpc (bfd_vma memaddr, + struct disassemble_info *info, + int bigendian, + int dialect) +{ + bfd_byte buffer[4]; + int status; + unsigned long insn; + const struct powerpc_opcode *opcode; + const struct powerpc_opcode *opcode_end; + unsigned long op; + + if (dialect == 0) + dialect = powerpc_dialect (info); + + status = (*info->read_memory_func) (memaddr, buffer, 4, info); + if (status != 0) + { + (*info->memory_error_func) (status, memaddr, info); + return -1; + } + + if (bigendian) + insn = bfd_getb32 (buffer); + else + insn = bfd_getl32 (buffer); + + /* Get the major opcode of the instruction. */ + op = PPC_OP (insn); + + /* Find the first match in the opcode table. We could speed this up + a bit by doing a binary search on the major opcode. */ + opcode_end = powerpc_opcodes + powerpc_num_opcodes; + again: + for (opcode = powerpc_opcodes; opcode < opcode_end; opcode++) + { + unsigned long table_op; + const unsigned char *opindex; + const struct powerpc_operand *operand; + int invalid; + int need_comma; + int need_paren; + int skip_optional; + + table_op = PPC_OP (opcode->opcode); + if (op < table_op) + break; + if (op > table_op) + continue; + + if ((insn & opcode->mask) != opcode->opcode + || (opcode->flags & dialect) == 0) + continue; + + /* Make two passes over the operands. First see if any of them + have extraction functions, and, if they do, make sure the + instruction is valid. */ + invalid = 0; + for (opindex = opcode->operands; *opindex != 0; opindex++) + { + operand = powerpc_operands + *opindex; + if (operand->extract) + (*operand->extract) (insn, dialect, &invalid); + } + if (invalid) + continue; + + /* The instruction is valid. */ + if (opcode->operands[0] != 0) + (*info->fprintf_func) (info->stream, "%-7s ", opcode->name); + else + (*info->fprintf_func) (info->stream, "%s", opcode->name); + + /* Now extract and print the operands. */ + need_comma = 0; + need_paren = 0; + skip_optional = -1; + for (opindex = opcode->operands; *opindex != 0; opindex++) + { + long value; + + operand = powerpc_operands + *opindex; + + /* Operands that are marked FAKE are simply ignored. We + already made sure that the extract function considered + the instruction to be valid. */ + if ((operand->flags & PPC_OPERAND_FAKE) != 0) + continue; + + /* If all of the optional operands have the value zero, + then don't print any of them. */ + if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0) + { + if (skip_optional < 0) + skip_optional = skip_optional_operands (opindex, insn, + dialect); + if (skip_optional) + continue; + } + + value = operand_value_powerpc (operand, insn, dialect); + + if (need_comma) + { + (*info->fprintf_func) (info->stream, ","); + need_comma = 0; + } + + /* Print the operand as directed by the flags. */ + if ((operand->flags & PPC_OPERAND_GPR) != 0 + || ((operand->flags & PPC_OPERAND_GPR_0) != 0 && value != 0)) + (*info->fprintf_func) (info->stream, "r%ld", value); + else if ((operand->flags & PPC_OPERAND_FPR) != 0) + (*info->fprintf_func) (info->stream, "f%ld", value); + else if ((operand->flags & PPC_OPERAND_VR) != 0) + (*info->fprintf_func) (info->stream, "v%ld", value); + else if ((operand->flags & PPC_OPERAND_RELATIVE) != 0) + (*info->print_address_func) (memaddr + value, info); + else if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0) + (*info->print_address_func) ((bfd_vma) value & 0xffffffff, info); + else if ((operand->flags & PPC_OPERAND_CR) == 0 + || (dialect & PPC_OPCODE_PPC) == 0) + (*info->fprintf_func) (info->stream, "%ld", value); + else + { + if (operand->bitm == 7) + (*info->fprintf_func) (info->stream, "cr%ld", value); + else + { + static const char *cbnames[4] = { "lt", "gt", "eq", "so" }; + int cr; + int cc; + + cr = value >> 2; + if (cr != 0) + (*info->fprintf_func) (info->stream, "4*cr%d+", cr); + cc = value & 3; + (*info->fprintf_func) (info->stream, "%s", cbnames[cc]); + } + } + + if (need_paren) + { + (*info->fprintf_func) (info->stream, ")"); + need_paren = 0; + } + + if ((operand->flags & PPC_OPERAND_PARENS) == 0) + need_comma = 1; + else + { + (*info->fprintf_func) (info->stream, "("); + need_paren = 1; + } + } + + /* We have found and printed an instruction; return. */ + return 4; + } + + if ((dialect & PPC_OPCODE_ANY) != 0) + { + dialect = ~PPC_OPCODE_ANY; + goto again; + } + + /* We could not find a match. */ + (*info->fprintf_func) (info->stream, ".long 0x%lx", insn); + + return 4; +} + +void +print_ppc_disassembler_options (FILE *stream) +{ + (void)stream; + /* + fprintf (stream, "\n\ +The following PPC specific disassembler options are supported for use with\n\ +the -M switch:\n"); + + fprintf (stream, " booke|booke32|booke64 Disassemble the BookE instructions\n"); + fprintf (stream, " e300 Disassemble the e300 instructions\n"); + fprintf (stream, " e500|e500x2 Disassemble the e500 instructions\n"); + fprintf (stream, " 440 Disassemble the 440 instructions\n"); + fprintf (stream, " efs Disassemble the EFS instructions\n"); + fprintf (stream, " power4 Disassemble the Power4 instructions\n"); + fprintf (stream, " power5 Disassemble the Power5 instructions\n"); + fprintf (stream, " power6 Disassemble the Power6 instructions\n"); + fprintf (stream, " 32 Do not disassemble 64-bit instructions\n"); + fprintf (stream, " 64 Allow disassembly of 64-bit instructions\n"); + */ +} diff --git a/kernel/fiasco/src/lib/disasm/opcodes/ppc-opc.c b/kernel/fiasco/src/lib/disasm/opcodes/ppc-opc.c new file mode 100644 index 00000000..9b6f388f --- /dev/null +++ b/kernel/fiasco/src/lib/disasm/opcodes/ppc-opc.c @@ -0,0 +1,4740 @@ +/* ppc-opc.c -- PowerPC opcode list + Copyright 1994, 1995, 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2004, + 2005, 2006, 2007 Free Software Foundation, Inc. + Written by Ian Lance Taylor, Cygnus Support + + This file is part of the GNU opcodes library. + + This library is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + It is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + License for more details. + + You should have received a copy of the GNU General Public License + along with this file; see the file COPYING. If not, write to the + Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston, + MA 02110-1301, USA. */ + +#include +#include "sysdep.h" +#include "opcode/ppc.h" +#include "opintl.h" + +#ifndef ATTRIBUTE_UNUSED +#define ATTRIBUTE_UNUSED __attribute__ ((__unused__)) +#endif + +/* This file holds the PowerPC opcode table. The opcode table + includes almost all of the extended instruction mnemonics. This + permits the disassembler to use them, and simplifies the assembler + logic, at the cost of increasing the table size. The table is + strictly constant data, so the compiler should be able to put it in + the .text section. + + This file also holds the operand table. All knowledge about + inserting operands into instructions and vice-versa is kept in this + file. */ + +/* Local insertion and extraction functions. */ + +static unsigned long insert_bat (unsigned long, long, int, const char **); +static long extract_bat (unsigned long, int, int *); +static unsigned long insert_bba (unsigned long, long, int, const char **); +static long extract_bba (unsigned long, int, int *); +static unsigned long insert_bdm (unsigned long, long, int, const char **); +static long extract_bdm (unsigned long, int, int *); +static unsigned long insert_bdp (unsigned long, long, int, const char **); +static long extract_bdp (unsigned long, int, int *); +static unsigned long insert_bo (unsigned long, long, int, const char **); +static long extract_bo (unsigned long, int, int *); +static unsigned long insert_boe (unsigned long, long, int, const char **); +static long extract_boe (unsigned long, int, int *); +static unsigned long insert_fxm (unsigned long, long, int, const char **); +static long extract_fxm (unsigned long, int, int *); +static unsigned long insert_mbe (unsigned long, long, int, const char **); +static long extract_mbe (unsigned long, int, int *); +static unsigned long insert_mb6 (unsigned long, long, int, const char **); +static long extract_mb6 (unsigned long, int, int *); +static long extract_nb (unsigned long, int, int *); +static unsigned long insert_nsi (unsigned long, long, int, const char **); +static long extract_nsi (unsigned long, int, int *); +static unsigned long insert_ral (unsigned long, long, int, const char **); +static unsigned long insert_ram (unsigned long, long, int, const char **); +static unsigned long insert_raq (unsigned long, long, int, const char **); +static unsigned long insert_ras (unsigned long, long, int, const char **); +static unsigned long insert_rbs (unsigned long, long, int, const char **); +static long extract_rbs (unsigned long, int, int *); +static unsigned long insert_sh6 (unsigned long, long, int, const char **); +static long extract_sh6 (unsigned long, int, int *); +static unsigned long insert_spr (unsigned long, long, int, const char **); +static long extract_spr (unsigned long, int, int *); +static unsigned long insert_sprg (unsigned long, long, int, const char **); +static long extract_sprg (unsigned long, int, int *); +static unsigned long insert_tbr (unsigned long, long, int, const char **); +static long extract_tbr (unsigned long, int, int *); + +/* The operands table. + + The fields are bitm, shift, insert, extract, flags. + + We used to put parens around the various additions, like the one + for BA just below. However, that caused trouble with feeble + compilers with a limit on depth of a parenthesized expression, like + (reportedly) the compiler in Microsoft Developer Studio 5. So we + omit the parens, since the macros are never used in a context where + the addition will be ambiguous. */ + +const struct powerpc_operand powerpc_operands[] = +{ + /* The zero index is used to indicate the end of the list of + operands. */ +#define UNUSED 0 + { 0, 0, NULL, NULL, 0 }, + + /* The BA field in an XL form instruction. */ +#define BA UNUSED + 1 + /* The BI field in a B form or XL form instruction. */ +#define BI BA +#define BI_MASK (0x1f << 16) + { 0x1f, 16, NULL, NULL, PPC_OPERAND_CR }, + + /* The BA field in an XL form instruction when it must be the same + as the BT field in the same instruction. */ +#define BAT BA + 1 + { 0x1f, 16, insert_bat, extract_bat, PPC_OPERAND_FAKE }, + + /* The BB field in an XL form instruction. */ +#define BB BAT + 1 +#define BB_MASK (0x1f << 11) + { 0x1f, 11, NULL, NULL, PPC_OPERAND_CR }, + + /* The BB field in an XL form instruction when it must be the same + as the BA field in the same instruction. */ +#define BBA BB + 1 + { 0x1f, 11, insert_bba, extract_bba, PPC_OPERAND_FAKE }, + + /* The BD field in a B form instruction. The lower two bits are + forced to zero. */ +#define BD BBA + 1 + { 0xfffc, 0, NULL, NULL, PPC_OPERAND_RELATIVE | PPC_OPERAND_SIGNED }, + + /* The BD field in a B form instruction when absolute addressing is + used. */ +#define BDA BD + 1 + { 0xfffc, 0, NULL, NULL, PPC_OPERAND_ABSOLUTE | PPC_OPERAND_SIGNED }, + + /* The BD field in a B form instruction when the - modifier is used. + This sets the y bit of the BO field appropriately. */ +#define BDM BDA + 1 + { 0xfffc, 0, insert_bdm, extract_bdm, + PPC_OPERAND_RELATIVE | PPC_OPERAND_SIGNED }, + + /* The BD field in a B form instruction when the - modifier is used + and absolute address is used. */ +#define BDMA BDM + 1 + { 0xfffc, 0, insert_bdm, extract_bdm, + PPC_OPERAND_ABSOLUTE | PPC_OPERAND_SIGNED }, + + /* The BD field in a B form instruction when the + modifier is used. + This sets the y bit of the BO field appropriately. */ +#define BDP BDMA + 1 + { 0xfffc, 0, insert_bdp, extract_bdp, + PPC_OPERAND_RELATIVE | PPC_OPERAND_SIGNED }, + + /* The BD field in a B form instruction when the + modifier is used + and absolute addressing is used. */ +#define BDPA BDP + 1 + { 0xfffc, 0, insert_bdp, extract_bdp, + PPC_OPERAND_ABSOLUTE | PPC_OPERAND_SIGNED }, + + /* The BF field in an X or XL form instruction. */ +#define BF BDPA + 1 + /* The CRFD field in an X form instruction. */ +#define CRFD BF + { 0x7, 23, NULL, NULL, PPC_OPERAND_CR }, + + /* The BF field in an X or XL form instruction. */ +#define BFF BF + 1 + { 0x7, 23, NULL, NULL, 0 }, + + /* An optional BF field. This is used for comparison instructions, + in which an omitted BF field is taken as zero. */ +#define OBF BFF + 1 + { 0x7, 23, NULL, NULL, PPC_OPERAND_CR | PPC_OPERAND_OPTIONAL }, + + /* The BFA field in an X or XL form instruction. */ +#define BFA OBF + 1 + { 0x7, 18, NULL, NULL, PPC_OPERAND_CR }, + + /* The BO field in a B form instruction. Certain values are + illegal. */ +#define BO BFA + 1 +#define BO_MASK (0x1f << 21) + { 0x1f, 21, insert_bo, extract_bo, 0 }, + + /* The BO field in a B form instruction when the + or - modifier is + used. This is like the BO field, but it must be even. */ +#define BOE BO + 1 + { 0x1e, 21, insert_boe, extract_boe, 0 }, + +#define BH BOE + 1 + { 0x3, 11, NULL, NULL, PPC_OPERAND_OPTIONAL }, + + /* The BT field in an X or XL form instruction. */ +#define BT BH + 1 + { 0x1f, 21, NULL, NULL, PPC_OPERAND_CR }, + + /* The condition register number portion of the BI field in a B form + or XL form instruction. This is used for the extended + conditional branch mnemonics, which set the lower two bits of the + BI field. This field is optional. */ +#define CR BT + 1 + { 0x7, 18, NULL, NULL, PPC_OPERAND_CR | PPC_OPERAND_OPTIONAL }, + + /* The CRB field in an X form instruction. */ +#define CRB CR + 1 + /* The MB field in an M form instruction. */ +#define MB CRB +#define MB_MASK (0x1f << 6) + { 0x1f, 6, NULL, NULL, 0 }, + + /* The CRFS field in an X form instruction. */ +#define CRFS CRB + 1 + { 0x7, 0, NULL, NULL, PPC_OPERAND_CR }, + + /* The CT field in an X form instruction. */ +#define CT CRFS + 1 + /* The MO field in an mbar instruction. */ +#define MO CT + { 0x1f, 21, NULL, NULL, PPC_OPERAND_OPTIONAL }, + + /* The D field in a D form instruction. This is a displacement off + a register, and implies that the next operand is a register in + parentheses. */ +#define D CT + 1 + { 0xffff, 0, NULL, NULL, PPC_OPERAND_PARENS | PPC_OPERAND_SIGNED }, + + /* The DE field in a DE form instruction. This is like D, but is 12 + bits only. */ +#define DE D + 1 + { 0xfff, 4, NULL, NULL, PPC_OPERAND_PARENS | PPC_OPERAND_SIGNED }, + + /* The DES field in a DES form instruction. This is like DS, but is 14 + bits only (12 stored.) */ +#define DES DE + 1 + { 0x3ffc, 2, NULL, NULL, PPC_OPERAND_PARENS | PPC_OPERAND_SIGNED }, + + /* The DQ field in a DQ form instruction. This is like D, but the + lower four bits are forced to zero. */ +#define DQ DES + 1 + { 0xfff0, 0, NULL, NULL, + PPC_OPERAND_PARENS | PPC_OPERAND_SIGNED | PPC_OPERAND_DQ }, + + /* The DS field in a DS form instruction. This is like D, but the + lower two bits are forced to zero. */ +#define DS DQ + 1 + { 0xfffc, 0, NULL, NULL, + PPC_OPERAND_PARENS | PPC_OPERAND_SIGNED | PPC_OPERAND_DS }, + + /* The E field in a wrteei instruction. */ +#define E DS + 1 + { 0x1, 15, NULL, NULL, 0 }, + + /* The FL1 field in a POWER SC form instruction. */ +#define FL1 E + 1 + /* The U field in an X form instruction. */ +#define U FL1 + { 0xf, 12, NULL, NULL, 0 }, + + /* The FL2 field in a POWER SC form instruction. */ +#define FL2 FL1 + 1 + { 0x7, 2, NULL, NULL, 0 }, + + /* The FLM field in an XFL form instruction. */ +#define FLM FL2 + 1 + { 0xff, 17, NULL, NULL, 0 }, + + /* The FRA field in an X or A form instruction. */ +#define FRA FLM + 1 +#define FRA_MASK (0x1f << 16) + { 0x1f, 16, NULL, NULL, PPC_OPERAND_FPR }, + + /* The FRB field in an X or A form instruction. */ +#define FRB FRA + 1 +#define FRB_MASK (0x1f << 11) + { 0x1f, 11, NULL, NULL, PPC_OPERAND_FPR }, + + /* The FRC field in an A form instruction. */ +#define FRC FRB + 1 +#define FRC_MASK (0x1f << 6) + { 0x1f, 6, NULL, NULL, PPC_OPERAND_FPR }, + + /* The FRS field in an X form instruction or the FRT field in a D, X + or A form instruction. */ +#define FRS FRC + 1 +#define FRT FRS + { 0x1f, 21, NULL, NULL, PPC_OPERAND_FPR }, + + /* The FXM field in an XFX instruction. */ +#define FXM FRS + 1 + { 0xff, 12, insert_fxm, extract_fxm, 0 }, + + /* Power4 version for mfcr. */ +#define FXM4 FXM + 1 + { 0xff, 12, insert_fxm, extract_fxm, PPC_OPERAND_OPTIONAL }, + + /* The L field in a D or X form instruction. */ +#define L FXM4 + 1 + { 0x1, 21, NULL, NULL, PPC_OPERAND_OPTIONAL }, + + /* The LEV field in a POWER SVC form instruction. */ +#define SVC_LEV L + 1 + { 0x7f, 5, NULL, NULL, 0 }, + + /* The LEV field in an SC form instruction. */ +#define LEV SVC_LEV + 1 + { 0x7f, 5, NULL, NULL, PPC_OPERAND_OPTIONAL }, + + /* The LI field in an I form instruction. The lower two bits are + forced to zero. */ +#define LI LEV + 1 + { 0x3fffffc, 0, NULL, NULL, PPC_OPERAND_RELATIVE | PPC_OPERAND_SIGNED }, + + /* The LI field in an I form instruction when used as an absolute + address. */ +#define LIA LI + 1 + { 0x3fffffc, 0, NULL, NULL, PPC_OPERAND_ABSOLUTE | PPC_OPERAND_SIGNED }, + + /* The LS field in an X (sync) form instruction. */ +#define LS LIA + 1 + { 0x3, 21, NULL, NULL, PPC_OPERAND_OPTIONAL }, + + /* The ME field in an M form instruction. */ +#define ME LS + 1 +#define ME_MASK (0x1f << 1) + { 0x1f, 1, NULL, NULL, 0 }, + + /* The MB and ME fields in an M form instruction expressed a single + operand which is a bitmask indicating which bits to select. This + is a two operand form using PPC_OPERAND_NEXT. See the + description in opcode/ppc.h for what this means. */ +#define MBE ME + 1 + { 0x1f, 6, NULL, NULL, PPC_OPERAND_OPTIONAL | PPC_OPERAND_NEXT }, + { -1, 0, insert_mbe, extract_mbe, 0 }, + + /* The MB or ME field in an MD or MDS form instruction. The high + bit is wrapped to the low end. */ +#define MB6 MBE + 2 +#define ME6 MB6 +#define MB6_MASK (0x3f << 5) + { 0x3f, 5, insert_mb6, extract_mb6, 0 }, + + /* The NB field in an X form instruction. The value 32 is stored as + 0. */ +#define NB MB6 + 1 + { 0x1f, 11, NULL, extract_nb, PPC_OPERAND_PLUS1 }, + + /* The NSI field in a D form instruction. This is the same as the + SI field, only negated. */ +#define NSI NB + 1 + { 0xffff, 0, insert_nsi, extract_nsi, + PPC_OPERAND_NEGATIVE | PPC_OPERAND_SIGNED }, + + /* The RA field in an D, DS, DQ, X, XO, M, or MDS form instruction. */ +#define RA NSI + 1 +#define RA_MASK (0x1f << 16) + { 0x1f, 16, NULL, NULL, PPC_OPERAND_GPR }, + + /* As above, but 0 in the RA field means zero, not r0. */ +#define RA0 RA + 1 + { 0x1f, 16, NULL, NULL, PPC_OPERAND_GPR_0 }, + + /* The RA field in the DQ form lq instruction, which has special + value restrictions. */ +#define RAQ RA0 + 1 + { 0x1f, 16, insert_raq, NULL, PPC_OPERAND_GPR_0 }, + + /* The RA field in a D or X form instruction which is an updating + load, which means that the RA field may not be zero and may not + equal the RT field. */ +#define RAL RAQ + 1 + { 0x1f, 16, insert_ral, NULL, PPC_OPERAND_GPR_0 }, + + /* The RA field in an lmw instruction, which has special value + restrictions. */ +#define RAM RAL + 1 + { 0x1f, 16, insert_ram, NULL, PPC_OPERAND_GPR_0 }, + + /* The RA field in a D or X form instruction which is an updating + store or an updating floating point load, which means that the RA + field may not be zero. */ +#define RAS RAM + 1 + { 0x1f, 16, insert_ras, NULL, PPC_OPERAND_GPR_0 }, + + /* The RA field of the tlbwe instruction, which is optional. */ +#define RAOPT RAS + 1 + { 0x1f, 16, NULL, NULL, PPC_OPERAND_GPR | PPC_OPERAND_OPTIONAL }, + + /* The RB field in an X, XO, M, or MDS form instruction. */ +#define RB RAOPT + 1 +#define RB_MASK (0x1f << 11) + { 0x1f, 11, NULL, NULL, PPC_OPERAND_GPR }, + + /* The RB field in an X form instruction when it must be the same as + the RS field in the instruction. This is used for extended + mnemonics like mr. */ +#define RBS RB + 1 + { 0x1f, 11, insert_rbs, extract_rbs, PPC_OPERAND_FAKE }, + + /* The RS field in a D, DS, X, XFX, XS, M, MD or MDS form + instruction or the RT field in a D, DS, X, XFX or XO form + instruction. */ +#define RS RBS + 1 +#define RT RS +#define RT_MASK (0x1f << 21) + { 0x1f, 21, NULL, NULL, PPC_OPERAND_GPR }, + + /* The RS and RT fields of the DS form stq instruction, which have + special value restrictions. */ +#define RSQ RS + 1 +#define RTQ RSQ + { 0x1e, 21, NULL, NULL, PPC_OPERAND_GPR_0 }, + + /* The RS field of the tlbwe instruction, which is optional. */ +#define RSO RSQ + 1 +#define RTO RSO + { 0x1f, 21, NULL, NULL, PPC_OPERAND_GPR | PPC_OPERAND_OPTIONAL }, + + /* The SH field in an X or M form instruction. */ +#define SH RSO + 1 +#define SH_MASK (0x1f << 11) + /* The other UIMM field in a EVX form instruction. */ +#define EVUIMM SH + { 0x1f, 11, NULL, NULL, 0 }, + + /* The SH field in an MD form instruction. This is split. */ +#define SH6 SH + 1 +#define SH6_MASK ((0x1f << 11) | (1 << 1)) + { 0x3f, -1, insert_sh6, extract_sh6, 0 }, + + /* The SH field of the tlbwe instruction, which is optional. */ +#define SHO SH6 + 1 + { 0x1f, 11, NULL, NULL, PPC_OPERAND_OPTIONAL }, + + /* The SI field in a D form instruction. */ +#define SI SHO + 1 + { 0xffff, 0, NULL, NULL, PPC_OPERAND_SIGNED }, + + /* The SI field in a D form instruction when we accept a wide range + of positive values. */ +#define SISIGNOPT SI + 1 + { 0xffff, 0, NULL, NULL, PPC_OPERAND_SIGNED | PPC_OPERAND_SIGNOPT }, + + /* The SPR field in an XFX form instruction. This is flipped--the + lower 5 bits are stored in the upper 5 and vice- versa. */ +#define SPR SISIGNOPT + 1 +#define PMR SPR +#define SPR_MASK (0x3ff << 11) + { 0x3ff, 11, insert_spr, extract_spr, 0 }, + + /* The BAT index number in an XFX form m[ft]ibat[lu] instruction. */ +#define SPRBAT SPR + 1 +#define SPRBAT_MASK (0x3 << 17) + { 0x3, 17, NULL, NULL, 0 }, + + /* The SPRG register number in an XFX form m[ft]sprg instruction. */ +#define SPRG SPRBAT + 1 + { 0x1f, 16, insert_sprg, extract_sprg, 0 }, + + /* The SR field in an X form instruction. */ +#define SR SPRG + 1 + { 0xf, 16, NULL, NULL, 0 }, + + /* The STRM field in an X AltiVec form instruction. */ +#define STRM SR + 1 + { 0x3, 21, NULL, NULL, 0 }, + + /* The SV field in a POWER SC form instruction. */ +#define SV STRM + 1 + { 0x3fff, 2, NULL, NULL, 0 }, + + /* The TBR field in an XFX form instruction. This is like the SPR + field, but it is optional. */ +#define TBR SV + 1 + { 0x3ff, 11, insert_tbr, extract_tbr, PPC_OPERAND_OPTIONAL }, + + /* The TO field in a D or X form instruction. */ +#define TO TBR + 1 +#define TO_MASK (0x1f << 21) + { 0x1f, 21, NULL, NULL, 0 }, + + /* The UI field in a D form instruction. */ +#define UI TO + 1 + { 0xffff, 0, NULL, NULL, 0 }, + + /* The VA field in a VA, VX or VXR form instruction. */ +#define VA UI + 1 + { 0x1f, 16, NULL, NULL, PPC_OPERAND_VR }, + + /* The VB field in a VA, VX or VXR form instruction. */ +#define VB VA + 1 + { 0x1f, 11, NULL, NULL, PPC_OPERAND_VR }, + + /* The VC field in a VA form instruction. */ +#define VC VB + 1 + { 0x1f, 6, NULL, NULL, PPC_OPERAND_VR }, + + /* The VD or VS field in a VA, VX, VXR or X form instruction. */ +#define VD VC + 1 +#define VS VD + { 0x1f, 21, NULL, NULL, PPC_OPERAND_VR }, + + /* The SIMM field in a VX form instruction. */ +#define SIMM VD + 1 + { 0x1f, 16, NULL, NULL, PPC_OPERAND_SIGNED}, + + /* The UIMM field in a VX form instruction, and TE in Z form. */ +#define UIMM SIMM + 1 +#define TE UIMM + { 0x1f, 16, NULL, NULL, 0 }, + + /* The SHB field in a VA form instruction. */ +#define SHB UIMM + 1 + { 0xf, 6, NULL, NULL, 0 }, + + /* The other UIMM field in a half word EVX form instruction. */ +#define EVUIMM_2 SHB + 1 + { 0x3e, 10, NULL, NULL, PPC_OPERAND_PARENS }, + + /* The other UIMM field in a word EVX form instruction. */ +#define EVUIMM_4 EVUIMM_2 + 1 + { 0x7c, 9, NULL, NULL, PPC_OPERAND_PARENS }, + + /* The other UIMM field in a double EVX form instruction. */ +#define EVUIMM_8 EVUIMM_4 + 1 + { 0xf8, 8, NULL, NULL, PPC_OPERAND_PARENS }, + + /* The WS field. */ +#define WS EVUIMM_8 + 1 + { 0x7, 11, NULL, NULL, 0 }, + + /* The L field in an mtmsrd or A form instruction or W in an X form. */ +#define A_L WS + 1 +#define W A_L + { 0x1, 16, NULL, NULL, PPC_OPERAND_OPTIONAL }, + +#define RMC A_L + 1 + { 0x3, 9, NULL, NULL, 0 }, + +#define R RMC + 1 + { 0x1, 16, NULL, NULL, 0 }, + +#define SP R + 1 + { 0x3, 19, NULL, NULL, 0 }, + +#define S SP + 1 + { 0x1, 20, NULL, NULL, 0 }, + + /* SH field starting at bit position 16. */ +#define SH16 S + 1 + /* The DCM and DGM fields in a Z form instruction. */ +#define DCM SH16 +#define DGM DCM + { 0x3f, 10, NULL, NULL, 0 }, + + /* The EH field in larx instruction. */ +#define EH SH16 + 1 + { 0x1, 0, NULL, NULL, PPC_OPERAND_OPTIONAL }, + + /* The L field in an mtfsf or XFL form instruction. */ +#define XFL_L EH + 1 + { 0x1, 25, NULL, NULL, PPC_OPERAND_OPTIONAL}, +}; + +const unsigned int num_powerpc_operands = (sizeof (powerpc_operands) + / sizeof (powerpc_operands[0])); + +/* The functions used to insert and extract complicated operands. */ + +/* The BA field in an XL form instruction when it must be the same as + the BT field in the same instruction. This operand is marked FAKE. + The insertion function just copies the BT field into the BA field, + and the extraction function just checks that the fields are the + same. */ + +static unsigned long +insert_bat (unsigned long insn, + long value ATTRIBUTE_UNUSED, + int dialect ATTRIBUTE_UNUSED, + const char **errmsg ATTRIBUTE_UNUSED) +{ + return insn | (((insn >> 21) & 0x1f) << 16); +} + +static long +extract_bat (unsigned long insn, + int dialect ATTRIBUTE_UNUSED, + int *invalid) +{ + if (((insn >> 21) & 0x1f) != ((insn >> 16) & 0x1f)) + *invalid = 1; + return 0; +} + +/* The BB field in an XL form instruction when it must be the same as + the BA field in the same instruction. This operand is marked FAKE. + The insertion function just copies the BA field into the BB field, + and the extraction function just checks that the fields are the + same. */ + +static unsigned long +insert_bba (unsigned long insn, + long value ATTRIBUTE_UNUSED, + int dialect ATTRIBUTE_UNUSED, + const char **errmsg ATTRIBUTE_UNUSED) +{ + return insn | (((insn >> 16) & 0x1f) << 11); +} + +static long +extract_bba (unsigned long insn, + int dialect ATTRIBUTE_UNUSED, + int *invalid) +{ + if (((insn >> 16) & 0x1f) != ((insn >> 11) & 0x1f)) + *invalid = 1; + return 0; +} + +/* The BD field in a B form instruction when the - modifier is used. + This modifier means that the branch is not expected to be taken. + For chips built to versions of the architecture prior to version 2 + (ie. not Power4 compatible), we set the y bit of the BO field to 1 + if the offset is negative. When extracting, we require that the y + bit be 1 and that the offset be positive, since if the y bit is 0 + we just want to print the normal form of the instruction. + Power4 compatible targets use two bits, "a", and "t", instead of + the "y" bit. "at" == 00 => no hint, "at" == 01 => unpredictable, + "at" == 10 => not taken, "at" == 11 => taken. The "t" bit is 00001 + in BO field, the "a" bit is 00010 for branch on CR(BI) and 01000 + for branch on CTR. We only handle the taken/not-taken hint here. + Note that we don't relax the conditions tested here when + disassembling with -Many because insns using extract_bdm and + extract_bdp always occur in pairs. One or the other will always + be valid. */ + +static unsigned long +insert_bdm (unsigned long insn, + long value, + int dialect, + const char **errmsg ATTRIBUTE_UNUSED) +{ + if ((dialect & PPC_OPCODE_POWER4) == 0) + { + if ((value & 0x8000) != 0) + insn |= 1 << 21; + } + else + { + if ((insn & (0x14 << 21)) == (0x04 << 21)) + insn |= 0x02 << 21; + else if ((insn & (0x14 << 21)) == (0x10 << 21)) + insn |= 0x08 << 21; + } + return insn | (value & 0xfffc); +} + +static long +extract_bdm (unsigned long insn, + int dialect, + int *invalid) +{ + if ((dialect & PPC_OPCODE_POWER4) == 0) + { + if (((insn & (1 << 21)) == 0) != ((insn & (1 << 15)) == 0)) + *invalid = 1; + } + else + { + if ((insn & (0x17 << 21)) != (0x06 << 21) + && (insn & (0x1d << 21)) != (0x18 << 21)) + *invalid = 1; + } + + return ((insn & 0xfffc) ^ 0x8000) - 0x8000; +} + +/* The BD field in a B form instruction when the + modifier is used. + This is like BDM, above, except that the branch is expected to be + taken. */ + +static unsigned long +insert_bdp (unsigned long insn, + long value, + int dialect, + const char **errmsg ATTRIBUTE_UNUSED) +{ + if ((dialect & PPC_OPCODE_POWER4) == 0) + { + if ((value & 0x8000) == 0) + insn |= 1 << 21; + } + else + { + if ((insn & (0x14 << 21)) == (0x04 << 21)) + insn |= 0x03 << 21; + else if ((insn & (0x14 << 21)) == (0x10 << 21)) + insn |= 0x09 << 21; + } + return insn | (value & 0xfffc); +} + +static long +extract_bdp (unsigned long insn, + int dialect, + int *invalid) +{ + if ((dialect & PPC_OPCODE_POWER4) == 0) + { + if (((insn & (1 << 21)) == 0) == ((insn & (1 << 15)) == 0)) + *invalid = 1; + } + else + { + if ((insn & (0x17 << 21)) != (0x07 << 21) + && (insn & (0x1d << 21)) != (0x19 << 21)) + *invalid = 1; + } + + return ((insn & 0xfffc) ^ 0x8000) - 0x8000; +} + +/* Check for legal values of a BO field. */ + +static int +valid_bo (long value, int dialect, int extract) +{ + if ((dialect & PPC_OPCODE_POWER4) == 0) + { + int valid; + /* Certain encodings have bits that are required to be zero. + These are (z must be zero, y may be anything): + 001zy + 011zy + 1z00y + 1z01y + 1z1zz + */ + switch (value & 0x14) + { + default: + case 0: + valid = 1; + break; + case 0x4: + valid = (value & 0x2) == 0; + break; + case 0x10: + valid = (value & 0x8) == 0; + break; + case 0x14: + valid = value == 0x14; + break; + } + /* When disassembling with -Many, accept power4 encodings too. */ + if (valid + || (dialect & PPC_OPCODE_ANY) == 0 + || !extract) + return valid; + } + + /* Certain encodings have bits that are required to be zero. + These are (z must be zero, a & t may be anything): + 0000z + 0001z + 0100z + 0101z + 001at + 011at + 1a00t + 1a01t + 1z1zz + */ + if ((value & 0x14) == 0) + return (value & 0x1) == 0; + else if ((value & 0x14) == 0x14) + return value == 0x14; + else + return 1; +} + +/* The BO field in a B form instruction. Warn about attempts to set + the field to an illegal value. */ + +static unsigned long +insert_bo (unsigned long insn, + long value, + int dialect, + const char **errmsg) +{ + if (!valid_bo (value, dialect, 0)) + *errmsg = _("invalid conditional option"); + return insn | ((value & 0x1f) << 21); +} + +static long +extract_bo (unsigned long insn, + int dialect, + int *invalid) +{ + long value; + + value = (insn >> 21) & 0x1f; + if (!valid_bo (value, dialect, 1)) + *invalid = 1; + return value; +} + +/* The BO field in a B form instruction when the + or - modifier is + used. This is like the BO field, but it must be even. When + extracting it, we force it to be even. */ + +static unsigned long +insert_boe (unsigned long insn, + long value, + int dialect, + const char **errmsg) +{ + if (!valid_bo (value, dialect, 0)) + *errmsg = _("invalid conditional option"); + else if ((value & 1) != 0) + *errmsg = _("attempt to set y bit when using + or - modifier"); + + return insn | ((value & 0x1f) << 21); +} + +static long +extract_boe (unsigned long insn, + int dialect, + int *invalid) +{ + long value; + + value = (insn >> 21) & 0x1f; + if (!valid_bo (value, dialect, 1)) + *invalid = 1; + return value & 0x1e; +} + +/* FXM mask in mfcr and mtcrf instructions. */ + +static unsigned long +insert_fxm (unsigned long insn, + long value, + int dialect, + const char **errmsg) +{ + /* If we're handling the mfocrf and mtocrf insns ensure that exactly + one bit of the mask field is set. */ + if ((insn & (1 << 20)) != 0) + { + if (value == 0 || (value & -value) != value) + { + *errmsg = _("invalid mask field"); + value = 0; + } + } + + /* If the optional field on mfcr is missing that means we want to use + the old form of the instruction that moves the whole cr. In that + case we'll have VALUE zero. There doesn't seem to be a way to + distinguish this from the case where someone writes mfcr %r3,0. */ + else if (value == 0) + ; + + /* If only one bit of the FXM field is set, we can use the new form + of the instruction, which is faster. Unlike the Power4 branch hint + encoding, this is not backward compatible. Do not generate the + new form unless -mpower4 has been given, or -many and the two + operand form of mfcr was used. */ + else if ((value & -value) == value + && ((dialect & PPC_OPCODE_POWER4) != 0 + || ((dialect & PPC_OPCODE_ANY) != 0 + && (insn & (0x3ff << 1)) == 19 << 1))) + insn |= 1 << 20; + + /* Any other value on mfcr is an error. */ + else if ((insn & (0x3ff << 1)) == 19 << 1) + { + *errmsg = _("ignoring invalid mfcr mask"); + value = 0; + } + + return insn | ((value & 0xff) << 12); +} + +static long +extract_fxm (unsigned long insn, + int dialect ATTRIBUTE_UNUSED, + int *invalid) +{ + long mask = (insn >> 12) & 0xff; + + /* Is this a Power4 insn? */ + if ((insn & (1 << 20)) != 0) + { + /* Exactly one bit of MASK should be set. */ + if (mask == 0 || (mask & -mask) != mask) + *invalid = 1; + } + + /* Check that non-power4 form of mfcr has a zero MASK. */ + else if ((insn & (0x3ff << 1)) == 19 << 1) + { + if (mask != 0) + *invalid = 1; + } + + return mask; +} + +/* The MB and ME fields in an M form instruction expressed as a single + operand which is itself a bitmask. The extraction function always + marks it as invalid, since we never want to recognize an + instruction which uses a field of this type. */ + +static unsigned long +insert_mbe (unsigned long insn, + long value, + int dialect ATTRIBUTE_UNUSED, + const char **errmsg) +{ + unsigned long uval, mask; + int mb, me, mx, count, last; + + uval = value; + + if (uval == 0) + { + *errmsg = _("illegal bitmask"); + return insn; + } + + mb = 0; + me = 32; + if ((uval & 1) != 0) + last = 1; + else + last = 0; + count = 0; + + /* mb: location of last 0->1 transition */ + /* me: location of last 1->0 transition */ + /* count: # transitions */ + + for (mx = 0, mask = 1L << 31; mx < 32; ++mx, mask >>= 1) + { + if ((uval & mask) && !last) + { + ++count; + mb = mx; + last = 1; + } + else if (!(uval & mask) && last) + { + ++count; + me = mx; + last = 0; + } + } + if (me == 0) + me = 32; + + if (count != 2 && (count != 0 || ! last)) + *errmsg = _("illegal bitmask"); + + return insn | (mb << 6) | ((me - 1) << 1); +} + +static long +extract_mbe (unsigned long insn, + int dialect ATTRIBUTE_UNUSED, + int *invalid) +{ + long ret; + int mb, me; + int i; + + *invalid = 1; + + mb = (insn >> 6) & 0x1f; + me = (insn >> 1) & 0x1f; + if (mb < me + 1) + { + ret = 0; + for (i = mb; i <= me; i++) + ret |= 1L << (31 - i); + } + else if (mb == me + 1) + ret = ~0; + else /* (mb > me + 1) */ + { + ret = ~0; + for (i = me + 1; i < mb; i++) + ret &= ~(1L << (31 - i)); + } + return ret; +} + +/* The MB or ME field in an MD or MDS form instruction. The high bit + is wrapped to the low end. */ + +static unsigned long +insert_mb6 (unsigned long insn, + long value, + int dialect ATTRIBUTE_UNUSED, + const char **errmsg ATTRIBUTE_UNUSED) +{ + return insn | ((value & 0x1f) << 6) | (value & 0x20); +} + +static long +extract_mb6 (unsigned long insn, + int dialect ATTRIBUTE_UNUSED, + int *invalid ATTRIBUTE_UNUSED) +{ + return ((insn >> 6) & 0x1f) | (insn & 0x20); +} + +/* The NB field in an X form instruction. The value 32 is stored as + 0. */ + +static long +extract_nb (unsigned long insn, + int dialect ATTRIBUTE_UNUSED, + int *invalid ATTRIBUTE_UNUSED) +{ + long ret; + + ret = (insn >> 11) & 0x1f; + if (ret == 0) + ret = 32; + return ret; +} + +/* The NSI field in a D form instruction. This is the same as the SI + field, only negated. The extraction function always marks it as + invalid, since we never want to recognize an instruction which uses + a field of this type. */ + +static unsigned long +insert_nsi (unsigned long insn, + long value, + int dialect ATTRIBUTE_UNUSED, + const char **errmsg ATTRIBUTE_UNUSED) +{ + return insn | (-value & 0xffff); +} + +static long +extract_nsi (unsigned long insn, + int dialect ATTRIBUTE_UNUSED, + int *invalid) +{ + *invalid = 1; + return -(((insn & 0xffff) ^ 0x8000) - 0x8000); +} + +/* The RA field in a D or X form instruction which is an updating + load, which means that the RA field may not be zero and may not + equal the RT field. */ + +static unsigned long +insert_ral (unsigned long insn, + long value, + int dialect ATTRIBUTE_UNUSED, + const char **errmsg) +{ + if (value == 0 + || (unsigned long) value == ((insn >> 21) & 0x1f)) + *errmsg = "invalid register operand when updating"; + return insn | ((value & 0x1f) << 16); +} + +/* The RA field in an lmw instruction, which has special value + restrictions. */ + +static unsigned long +insert_ram (unsigned long insn, + long value, + int dialect ATTRIBUTE_UNUSED, + const char **errmsg) +{ + if ((unsigned long) value >= ((insn >> 21) & 0x1f)) + *errmsg = _("index register in load range"); + return insn | ((value & 0x1f) << 16); +} + +/* The RA field in the DQ form lq instruction, which has special + value restrictions. */ + +static unsigned long +insert_raq (unsigned long insn, + long value, + int dialect ATTRIBUTE_UNUSED, + const char **errmsg) +{ + long rtvalue = (insn & RT_MASK) >> 21; + + if (value == rtvalue) + *errmsg = _("source and target register operands must be different"); + return insn | ((value & 0x1f) << 16); +} + +/* The RA field in a D or X form instruction which is an updating + store or an updating floating point load, which means that the RA + field may not be zero. */ + +static unsigned long +insert_ras (unsigned long insn, + long value, + int dialect ATTRIBUTE_UNUSED, + const char **errmsg) +{ + if (value == 0) + *errmsg = _("invalid register operand when updating"); + return insn | ((value & 0x1f) << 16); +} + +/* The RB field in an X form instruction when it must be the same as + the RS field in the instruction. This is used for extended + mnemonics like mr. This operand is marked FAKE. The insertion + function just copies the BT field into the BA field, and the + extraction function just checks that the fields are the same. */ + +static unsigned long +insert_rbs (unsigned long insn, + long value ATTRIBUTE_UNUSED, + int dialect ATTRIBUTE_UNUSED, + const char **errmsg ATTRIBUTE_UNUSED) +{ + return insn | (((insn >> 21) & 0x1f) << 11); +} + +static long +extract_rbs (unsigned long insn, + int dialect ATTRIBUTE_UNUSED, + int *invalid) +{ + if (((insn >> 21) & 0x1f) != ((insn >> 11) & 0x1f)) + *invalid = 1; + return 0; +} + +/* The SH field in an MD form instruction. This is split. */ + +static unsigned long +insert_sh6 (unsigned long insn, + long value, + int dialect ATTRIBUTE_UNUSED, + const char **errmsg ATTRIBUTE_UNUSED) +{ + return insn | ((value & 0x1f) << 11) | ((value & 0x20) >> 4); +} + +static long +extract_sh6 (unsigned long insn, + int dialect ATTRIBUTE_UNUSED, + int *invalid ATTRIBUTE_UNUSED) +{ + return ((insn >> 11) & 0x1f) | ((insn << 4) & 0x20); +} + +/* The SPR field in an XFX form instruction. This is flipped--the + lower 5 bits are stored in the upper 5 and vice- versa. */ + +static unsigned long +insert_spr (unsigned long insn, + long value, + int dialect ATTRIBUTE_UNUSED, + const char **errmsg ATTRIBUTE_UNUSED) +{ + return insn | ((value & 0x1f) << 16) | ((value & 0x3e0) << 6); +} + +static long +extract_spr (unsigned long insn, + int dialect ATTRIBUTE_UNUSED, + int *invalid ATTRIBUTE_UNUSED) +{ + return ((insn >> 16) & 0x1f) | ((insn >> 6) & 0x3e0); +} + +/* Some dialects have 8 SPRG registers instead of the standard 4. */ + +static unsigned long +insert_sprg (unsigned long insn, + long value, + int dialect, + const char **errmsg) +{ + /* This check uses PPC_OPCODE_403 because PPC405 is later defined + as a synonym. If ever a 405 specific dialect is added this + check should use that instead. */ + if (value > 7 + || (value > 3 + && (dialect & (PPC_OPCODE_BOOKE | PPC_OPCODE_403)) == 0)) + *errmsg = _("invalid sprg number"); + + /* If this is mfsprg4..7 then use spr 260..263 which can be read in + user mode. Anything else must use spr 272..279. */ + if (value <= 3 || (insn & 0x100) != 0) + value |= 0x10; + + return insn | ((value & 0x17) << 16); +} + +static long +extract_sprg (unsigned long insn, + int dialect, + int *invalid) +{ + unsigned long val = (insn >> 16) & 0x1f; + + /* mfsprg can use 260..263 and 272..279. mtsprg only uses spr 272..279 + If not BOOKE or 405, then both use only 272..275. */ + if (val <= 3 + || (val < 0x10 && (insn & 0x100) != 0) + || (val - 0x10 > 3 + && (dialect & (PPC_OPCODE_BOOKE | PPC_OPCODE_403)) == 0)) + *invalid = 1; + return val & 7; +} + +/* The TBR field in an XFX instruction. This is just like SPR, but it + is optional. When TBR is omitted, it must be inserted as 268 (the + magic number of the TB register). These functions treat 0 + (indicating an omitted optional operand) as 268. This means that + ``mftb 4,0'' is not handled correctly. This does not matter very + much, since the architecture manual does not define mftb as + accepting any values other than 268 or 269. */ + +#define TB (268) + +static unsigned long +insert_tbr (unsigned long insn, + long value, + int dialect ATTRIBUTE_UNUSED, + const char **errmsg ATTRIBUTE_UNUSED) +{ + if (value == 0) + value = TB; + return insn | ((value & 0x1f) << 16) | ((value & 0x3e0) << 6); +} + +static long +extract_tbr (unsigned long insn, + int dialect ATTRIBUTE_UNUSED, + int *invalid ATTRIBUTE_UNUSED) +{ + long ret; + + ret = ((insn >> 16) & 0x1f) | ((insn >> 6) & 0x3e0); + if (ret == TB) + ret = 0; + return ret; +} + +/* Macros used to form opcodes. */ + +/* The main opcode. */ +#define OP(x) ((((unsigned long)(x)) & 0x3f) << 26) +#define OP_MASK OP (0x3f) + +/* The main opcode combined with a trap code in the TO field of a D + form instruction. Used for extended mnemonics for the trap + instructions. */ +#define OPTO(x,to) (OP (x) | ((((unsigned long)(to)) & 0x1f) << 21)) +#define OPTO_MASK (OP_MASK | TO_MASK) + +/* The main opcode combined with a comparison size bit in the L field + of a D form or X form instruction. Used for extended mnemonics for + the comparison instructions. */ +#define OPL(x,l) (OP (x) | ((((unsigned long)(l)) & 1) << 21)) +#define OPL_MASK OPL (0x3f,1) + +/* An A form instruction. */ +#define A(op, xop, rc) (OP (op) | ((((unsigned long)(xop)) & 0x1f) << 1) | (((unsigned long)(rc)) & 1)) +#define A_MASK A (0x3f, 0x1f, 1) + +/* An A_MASK with the FRB field fixed. */ +#define AFRB_MASK (A_MASK | FRB_MASK) + +/* An A_MASK with the FRC field fixed. */ +#define AFRC_MASK (A_MASK | FRC_MASK) + +/* An A_MASK with the FRA and FRC fields fixed. */ +#define AFRAFRC_MASK (A_MASK | FRA_MASK | FRC_MASK) + +/* An AFRAFRC_MASK, but with L bit clear. */ +#define AFRALFRC_MASK (AFRAFRC_MASK & ~((unsigned long) 1 << 16)) + +/* A B form instruction. */ +#define B(op, aa, lk) (OP (op) | ((((unsigned long)(aa)) & 1) << 1) | ((lk) & 1)) +#define B_MASK B (0x3f, 1, 1) + +/* A B form instruction setting the BO field. */ +#define BBO(op, bo, aa, lk) (B ((op), (aa), (lk)) | ((((unsigned long)(bo)) & 0x1f) << 21)) +#define BBO_MASK BBO (0x3f, 0x1f, 1, 1) + +/* A BBO_MASK with the y bit of the BO field removed. This permits + matching a conditional branch regardless of the setting of the y + bit. Similarly for the 'at' bits used for power4 branch hints. */ +#define Y_MASK (((unsigned long) 1) << 21) +#define AT1_MASK (((unsigned long) 3) << 21) +#define AT2_MASK (((unsigned long) 9) << 21) +#define BBOY_MASK (BBO_MASK &~ Y_MASK) +#define BBOAT_MASK (BBO_MASK &~ AT1_MASK) + +/* A B form instruction setting the BO field and the condition bits of + the BI field. */ +#define BBOCB(op, bo, cb, aa, lk) \ + (BBO ((op), (bo), (aa), (lk)) | ((((unsigned long)(cb)) & 0x3) << 16)) +#define BBOCB_MASK BBOCB (0x3f, 0x1f, 0x3, 1, 1) + +/* A BBOCB_MASK with the y bit of the BO field removed. */ +#define BBOYCB_MASK (BBOCB_MASK &~ Y_MASK) +#define BBOATCB_MASK (BBOCB_MASK &~ AT1_MASK) +#define BBOAT2CB_MASK (BBOCB_MASK &~ AT2_MASK) + +/* A BBOYCB_MASK in which the BI field is fixed. */ +#define BBOYBI_MASK (BBOYCB_MASK | BI_MASK) +#define BBOATBI_MASK (BBOAT2CB_MASK | BI_MASK) + +/* An Context form instruction. */ +#define CTX(op, xop) (OP (op) | (((unsigned long)(xop)) & 0x7)) +#define CTX_MASK CTX(0x3f, 0x7) + +/* An User Context form instruction. */ +#define UCTX(op, xop) (OP (op) | (((unsigned long)(xop)) & 0x1f)) +#define UCTX_MASK UCTX(0x3f, 0x1f) + +/* The main opcode mask with the RA field clear. */ +#define DRA_MASK (OP_MASK | RA_MASK) + +/* A DS form instruction. */ +#define DSO(op, xop) (OP (op) | ((xop) & 0x3)) +#define DS_MASK DSO (0x3f, 3) + +/* A DE form instruction. */ +#define DEO(op, xop) (OP (op) | ((xop) & 0xf)) +#define DE_MASK DEO (0x3e, 0xf) + +/* An EVSEL form instruction. */ +#define EVSEL(op, xop) (OP (op) | (((unsigned long)(xop)) & 0xff) << 3) +#define EVSEL_MASK EVSEL(0x3f, 0xff) + +/* An M form instruction. */ +#define M(op, rc) (OP (op) | ((rc) & 1)) +#define M_MASK M (0x3f, 1) + +/* An M form instruction with the ME field specified. */ +#define MME(op, me, rc) (M ((op), (rc)) | ((((unsigned long)(me)) & 0x1f) << 1)) + +/* An M_MASK with the MB and ME fields fixed. */ +#define MMBME_MASK (M_MASK | MB_MASK | ME_MASK) + +/* An M_MASK with the SH and ME fields fixed. */ +#define MSHME_MASK (M_MASK | SH_MASK | ME_MASK) + +/* An MD form instruction. */ +#define MD(op, xop, rc) (OP (op) | ((((unsigned long)(xop)) & 0x7) << 2) | ((rc) & 1)) +#define MD_MASK MD (0x3f, 0x7, 1) + +/* An MD_MASK with the MB field fixed. */ +#define MDMB_MASK (MD_MASK | MB6_MASK) + +/* An MD_MASK with the SH field fixed. */ +#define MDSH_MASK (MD_MASK | SH6_MASK) + +/* An MDS form instruction. */ +#define MDS(op, xop, rc) (OP (op) | ((((unsigned long)(xop)) & 0xf) << 1) | ((rc) & 1)) +#define MDS_MASK MDS (0x3f, 0xf, 1) + +/* An MDS_MASK with the MB field fixed. */ +#define MDSMB_MASK (MDS_MASK | MB6_MASK) + +/* An SC form instruction. */ +#define SC(op, sa, lk) (OP (op) | ((((unsigned long)(sa)) & 1) << 1) | ((lk) & 1)) +#define SC_MASK (OP_MASK | (((unsigned long)0x3ff) << 16) | (((unsigned long)1) << 1) | 1) + +/* An VX form instruction. */ +#define VX(op, xop) (OP (op) | (((unsigned long)(xop)) & 0x7ff)) + +/* The mask for an VX form instruction. */ +#define VX_MASK VX(0x3f, 0x7ff) + +/* An VA form instruction. */ +#define VXA(op, xop) (OP (op) | (((unsigned long)(xop)) & 0x03f)) + +/* The mask for an VA form instruction. */ +#define VXA_MASK VXA(0x3f, 0x3f) + +/* An VXR form instruction. */ +#define VXR(op, xop, rc) (OP (op) | (((rc) & 1) << 10) | (((unsigned long)(xop)) & 0x3ff)) + +/* The mask for a VXR form instruction. */ +#define VXR_MASK VXR(0x3f, 0x3ff, 1) + +/* An X form instruction. */ +#define X(op, xop) (OP (op) | ((((unsigned long)(xop)) & 0x3ff) << 1)) + +/* A Z form instruction. */ +#define Z(op, xop) (OP (op) | ((((unsigned long)(xop)) & 0x1ff) << 1)) + +/* An X form instruction with the RC bit specified. */ +#define XRC(op, xop, rc) (X ((op), (xop)) | ((rc) & 1)) + +/* A Z form instruction with the RC bit specified. */ +#define ZRC(op, xop, rc) (Z ((op), (xop)) | ((rc) & 1)) + +/* The mask for an X form instruction. */ +#define X_MASK XRC (0x3f, 0x3ff, 1) + +/* The mask for a Z form instruction. */ +#define Z_MASK ZRC (0x3f, 0x1ff, 1) +#define Z2_MASK ZRC (0x3f, 0xff, 1) + +/* An X_MASK with the RA field fixed. */ +#define XRA_MASK (X_MASK | RA_MASK) + +/* An XRA_MASK with the W field clear. */ +#define XWRA_MASK (XRA_MASK & ~((unsigned long) 1 << 16)) + +/* An X_MASK with the RB field fixed. */ +#define XRB_MASK (X_MASK | RB_MASK) + +/* An X_MASK with the RT field fixed. */ +#define XRT_MASK (X_MASK | RT_MASK) + +/* An XRT_MASK mask with the L bits clear. */ +#define XLRT_MASK (XRT_MASK & ~((unsigned long) 0x3 << 21)) + +/* An X_MASK with the RA and RB fields fixed. */ +#define XRARB_MASK (X_MASK | RA_MASK | RB_MASK) + +/* An XRARB_MASK, but with the L bit clear. */ +#define XRLARB_MASK (XRARB_MASK & ~((unsigned long) 1 << 16)) + +/* An X_MASK with the RT and RA fields fixed. */ +#define XRTRA_MASK (X_MASK | RT_MASK | RA_MASK) + +/* An XRTRA_MASK, but with L bit clear. */ +#define XRTLRA_MASK (XRTRA_MASK & ~((unsigned long) 1 << 21)) + +/* An X form instruction with the L bit specified. */ +#define XOPL(op, xop, l) (X ((op), (xop)) | ((((unsigned long)(l)) & 1) << 21)) + +/* The mask for an X form comparison instruction. */ +#define XCMP_MASK (X_MASK | (((unsigned long)1) << 22)) + +/* The mask for an X form comparison instruction with the L field + fixed. */ +#define XCMPL_MASK (XCMP_MASK | (((unsigned long)1) << 21)) + +/* An X form trap instruction with the TO field specified. */ +#define XTO(op, xop, to) (X ((op), (xop)) | ((((unsigned long)(to)) & 0x1f) << 21)) +#define XTO_MASK (X_MASK | TO_MASK) + +/* An X form tlb instruction with the SH field specified. */ +#define XTLB(op, xop, sh) (X ((op), (xop)) | ((((unsigned long)(sh)) & 0x1f) << 11)) +#define XTLB_MASK (X_MASK | SH_MASK) + +/* An X form sync instruction. */ +#define XSYNC(op, xop, l) (X ((op), (xop)) | ((((unsigned long)(l)) & 3) << 21)) + +/* An X form sync instruction with everything filled in except the LS field. */ +#define XSYNC_MASK (0xff9fffff) + +/* An X_MASK, but with the EH bit clear. */ +#define XEH_MASK (X_MASK & ~((unsigned long )1)) + +/* An X form AltiVec dss instruction. */ +#define XDSS(op, xop, a) (X ((op), (xop)) | ((((unsigned long)(a)) & 1) << 25)) +#define XDSS_MASK XDSS(0x3f, 0x3ff, 1) + +/* An XFL form instruction. */ +#define XFL(op, xop, rc) (OP (op) | ((((unsigned long)(xop)) & 0x3ff) << 1) | (((unsigned long)(rc)) & 1)) +#define XFL_MASK XFL (0x3f, 0x3ff, 1) + +/* An X form isel instruction. */ +#define XISEL(op, xop) (OP (op) | ((((unsigned long)(xop)) & 0x1f) << 1)) +#define XISEL_MASK XISEL(0x3f, 0x1f) + +/* An XL form instruction with the LK field set to 0. */ +#define XL(op, xop) (OP (op) | ((((unsigned long)(xop)) & 0x3ff) << 1)) + +/* An XL form instruction which uses the LK field. */ +#define XLLK(op, xop, lk) (XL ((op), (xop)) | ((lk) & 1)) + +/* The mask for an XL form instruction. */ +#define XL_MASK XLLK (0x3f, 0x3ff, 1) + +/* An XL form instruction which explicitly sets the BO field. */ +#define XLO(op, bo, xop, lk) \ + (XLLK ((op), (xop), (lk)) | ((((unsigned long)(bo)) & 0x1f) << 21)) +#define XLO_MASK (XL_MASK | BO_MASK) + +/* An XL form instruction which explicitly sets the y bit of the BO + field. */ +#define XLYLK(op, xop, y, lk) (XLLK ((op), (xop), (lk)) | ((((unsigned long)(y)) & 1) << 21)) +#define XLYLK_MASK (XL_MASK | Y_MASK) + +/* An XL form instruction which sets the BO field and the condition + bits of the BI field. */ +#define XLOCB(op, bo, cb, xop, lk) \ + (XLO ((op), (bo), (xop), (lk)) | ((((unsigned long)(cb)) & 3) << 16)) +#define XLOCB_MASK XLOCB (0x3f, 0x1f, 0x3, 0x3ff, 1) + +/* An XL_MASK or XLYLK_MASK or XLOCB_MASK with the BB field fixed. */ +#define XLBB_MASK (XL_MASK | BB_MASK) +#define XLYBB_MASK (XLYLK_MASK | BB_MASK) +#define XLBOCBBB_MASK (XLOCB_MASK | BB_MASK) + +/* A mask for branch instructions using the BH field. */ +#define XLBH_MASK (XL_MASK | (0x1c << 11)) + +/* An XL_MASK with the BO and BB fields fixed. */ +#define XLBOBB_MASK (XL_MASK | BO_MASK | BB_MASK) + +/* An XL_MASK with the BO, BI and BB fields fixed. */ +#define XLBOBIBB_MASK (XL_MASK | BO_MASK | BI_MASK | BB_MASK) + +/* An XO form instruction. */ +#define XO(op, xop, oe, rc) \ + (OP (op) | ((((unsigned long)(xop)) & 0x1ff) << 1) | ((((unsigned long)(oe)) & 1) << 10) | (((unsigned long)(rc)) & 1)) +#define XO_MASK XO (0x3f, 0x1ff, 1, 1) + +/* An XO_MASK with the RB field fixed. */ +#define XORB_MASK (XO_MASK | RB_MASK) + +/* An XS form instruction. */ +#define XS(op, xop, rc) (OP (op) | ((((unsigned long)(xop)) & 0x1ff) << 2) | (((unsigned long)(rc)) & 1)) +#define XS_MASK XS (0x3f, 0x1ff, 1) + +/* A mask for the FXM version of an XFX form instruction. */ +#define XFXFXM_MASK (X_MASK | (1 << 11) | (1 << 20)) + +/* An XFX form instruction with the FXM field filled in. */ +#define XFXM(op, xop, fxm, p4) \ + (X ((op), (xop)) | ((((unsigned long)(fxm)) & 0xff) << 12) \ + | ((unsigned long)(p4) << 20)) + +/* An XFX form instruction with the SPR field filled in. */ +#define XSPR(op, xop, spr) \ + (X ((op), (xop)) | ((((unsigned long)(spr)) & 0x1f) << 16) | ((((unsigned long)(spr)) & 0x3e0) << 6)) +#define XSPR_MASK (X_MASK | SPR_MASK) + +/* An XFX form instruction with the SPR field filled in except for the + SPRBAT field. */ +#define XSPRBAT_MASK (XSPR_MASK &~ SPRBAT_MASK) + +/* An XFX form instruction with the SPR field filled in except for the + SPRG field. */ +#define XSPRG_MASK (XSPR_MASK & ~(0x1f << 16)) + +/* An X form instruction with everything filled in except the E field. */ +#define XE_MASK (0xffff7fff) + +/* An X form user context instruction. */ +#define XUC(op, xop) (OP (op) | (((unsigned long)(xop)) & 0x1f)) +#define XUC_MASK XUC(0x3f, 0x1f) + +/* The BO encodings used in extended conditional branch mnemonics. */ +#define BODNZF (0x0) +#define BODNZFP (0x1) +#define BODZF (0x2) +#define BODZFP (0x3) +#define BODNZT (0x8) +#define BODNZTP (0x9) +#define BODZT (0xa) +#define BODZTP (0xb) + +#define BOF (0x4) +#define BOFP (0x5) +#define BOFM4 (0x6) +#define BOFP4 (0x7) +#define BOT (0xc) +#define BOTP (0xd) +#define BOTM4 (0xe) +#define BOTP4 (0xf) + +#define BODNZ (0x10) +#define BODNZP (0x11) +#define BODZ (0x12) +#define BODZP (0x13) +#define BODNZM4 (0x18) +#define BODNZP4 (0x19) +#define BODZM4 (0x1a) +#define BODZP4 (0x1b) + +#define BOU (0x14) + +/* The BI condition bit encodings used in extended conditional branch + mnemonics. */ +#define CBLT (0) +#define CBGT (1) +#define CBEQ (2) +#define CBSO (3) + +/* The TO encodings used in extended trap mnemonics. */ +#define TOLGT (0x1) +#define TOLLT (0x2) +#define TOEQ (0x4) +#define TOLGE (0x5) +#define TOLNL (0x5) +#define TOLLE (0x6) +#define TOLNG (0x6) +#define TOGT (0x8) +#define TOGE (0xc) +#define TONL (0xc) +#define TOLT (0x10) +#define TOLE (0x14) +#define TONG (0x14) +#define TONE (0x18) +#define TOU (0x1f) + +/* Smaller names for the flags so each entry in the opcodes table will + fit on a single line. */ +#undef PPC +#define PPC PPC_OPCODE_PPC +#define PPCCOM PPC_OPCODE_PPC | PPC_OPCODE_COMMON +#define NOPOWER4 PPC_OPCODE_NOPOWER4 | PPCCOM +#define POWER4 PPC_OPCODE_POWER4 +#define POWER5 PPC_OPCODE_POWER5 +#define POWER6 PPC_OPCODE_POWER6 +#define CELL PPC_OPCODE_CELL +#define PPC32 PPC_OPCODE_32 | PPC_OPCODE_PPC +#define PPC64 PPC_OPCODE_64 | PPC_OPCODE_PPC +#define PPC403 PPC_OPCODE_403 +#define PPC405 PPC403 +#define PPC440 PPC_OPCODE_440 +#define PPC750 PPC +#define PPC7450 PPC +#define PPC860 PPC +#define PPCVEC PPC_OPCODE_ALTIVEC +#define POWER PPC_OPCODE_POWER +#define POWER2 PPC_OPCODE_POWER | PPC_OPCODE_POWER2 +#define PPCPWR2 PPC_OPCODE_PPC | PPC_OPCODE_POWER | PPC_OPCODE_POWER2 +#define POWER32 PPC_OPCODE_POWER | PPC_OPCODE_32 +#define COM PPC_OPCODE_POWER | PPC_OPCODE_PPC | PPC_OPCODE_COMMON +#define COM32 PPC_OPCODE_POWER | PPC_OPCODE_PPC | PPC_OPCODE_COMMON | PPC_OPCODE_32 +#define M601 PPC_OPCODE_POWER | PPC_OPCODE_601 +#define PWRCOM PPC_OPCODE_POWER | PPC_OPCODE_601 | PPC_OPCODE_COMMON +#define MFDEC1 PPC_OPCODE_POWER +#define MFDEC2 PPC_OPCODE_PPC | PPC_OPCODE_601 | PPC_OPCODE_BOOKE +#define BOOKE PPC_OPCODE_BOOKE +#define BOOKE64 PPC_OPCODE_BOOKE64 +#define CLASSIC PPC_OPCODE_CLASSIC +#define PPCE300 PPC_OPCODE_E300 +#define PPCSPE PPC_OPCODE_SPE +#define PPCISEL PPC_OPCODE_ISEL +#define PPCEFS PPC_OPCODE_EFS +#define PPCBRLK PPC_OPCODE_BRLOCK +#define PPCPMR PPC_OPCODE_PMR +#define PPCCHLK PPC_OPCODE_CACHELCK +#define PPCCHLK64 PPC_OPCODE_CACHELCK | PPC_OPCODE_BOOKE64 +#define PPCRFMCI PPC_OPCODE_RFMCI + +/* The opcode table. + + The format of the opcode table is: + + NAME OPCODE MASK FLAGS { OPERANDS } + + NAME is the name of the instruction. + OPCODE is the instruction opcode. + MASK is the opcode mask; this is used to tell the disassembler + which bits in the actual opcode must match OPCODE. + FLAGS are flags indicated what processors support the instruction. + OPERANDS is the list of operands. + + The disassembler reads the table in order and prints the first + instruction which matches, so this table is sorted to put more + specific instructions before more general instructions. It is also + sorted by major opcode. */ + +const struct powerpc_opcode powerpc_opcodes[] = { +{ "attn", X(0,256), X_MASK, POWER4, { 0 } }, +{ "tdlgti", OPTO(2,TOLGT), OPTO_MASK, PPC64, { RA, SI } }, +{ "tdllti", OPTO(2,TOLLT), OPTO_MASK, PPC64, { RA, SI } }, +{ "tdeqi", OPTO(2,TOEQ), OPTO_MASK, PPC64, { RA, SI } }, +{ "tdlgei", OPTO(2,TOLGE), OPTO_MASK, PPC64, { RA, SI } }, +{ "tdlnli", OPTO(2,TOLNL), OPTO_MASK, PPC64, { RA, SI } }, +{ "tdllei", OPTO(2,TOLLE), OPTO_MASK, PPC64, { RA, SI } }, +{ "tdlngi", OPTO(2,TOLNG), OPTO_MASK, PPC64, { RA, SI } }, +{ "tdgti", OPTO(2,TOGT), OPTO_MASK, PPC64, { RA, SI } }, +{ "tdgei", OPTO(2,TOGE), OPTO_MASK, PPC64, { RA, SI } }, +{ "tdnli", OPTO(2,TONL), OPTO_MASK, PPC64, { RA, SI } }, +{ "tdlti", OPTO(2,TOLT), OPTO_MASK, PPC64, { RA, SI } }, +{ "tdlei", OPTO(2,TOLE), OPTO_MASK, PPC64, { RA, SI } }, +{ "tdngi", OPTO(2,TONG), OPTO_MASK, PPC64, { RA, SI } }, +{ "tdnei", OPTO(2,TONE), OPTO_MASK, PPC64, { RA, SI } }, +{ "tdi", OP(2), OP_MASK, PPC64, { TO, RA, SI } }, + +{ "twlgti", OPTO(3,TOLGT), OPTO_MASK, PPCCOM, { RA, SI } }, +{ "tlgti", OPTO(3,TOLGT), OPTO_MASK, PWRCOM, { RA, SI } }, +{ "twllti", OPTO(3,TOLLT), OPTO_MASK, PPCCOM, { RA, SI } }, +{ "tllti", OPTO(3,TOLLT), OPTO_MASK, PWRCOM, { RA, SI } }, +{ "tweqi", OPTO(3,TOEQ), OPTO_MASK, PPCCOM, { RA, SI } }, +{ "teqi", OPTO(3,TOEQ), OPTO_MASK, PWRCOM, { RA, SI } }, +{ "twlgei", OPTO(3,TOLGE), OPTO_MASK, PPCCOM, { RA, SI } }, +{ "tlgei", OPTO(3,TOLGE), OPTO_MASK, PWRCOM, { RA, SI } }, +{ "twlnli", OPTO(3,TOLNL), OPTO_MASK, PPCCOM, { RA, SI } }, +{ "tlnli", OPTO(3,TOLNL), OPTO_MASK, PWRCOM, { RA, SI } }, +{ "twllei", OPTO(3,TOLLE), OPTO_MASK, PPCCOM, { RA, SI } }, +{ "tllei", OPTO(3,TOLLE), OPTO_MASK, PWRCOM, { RA, SI } }, +{ "twlngi", OPTO(3,TOLNG), OPTO_MASK, PPCCOM, { RA, SI } }, +{ "tlngi", OPTO(3,TOLNG), OPTO_MASK, PWRCOM, { RA, SI } }, +{ "twgti", OPTO(3,TOGT), OPTO_MASK, PPCCOM, { RA, SI } }, +{ "tgti", OPTO(3,TOGT), OPTO_MASK, PWRCOM, { RA, SI } }, +{ "twgei", OPTO(3,TOGE), OPTO_MASK, PPCCOM, { RA, SI } }, +{ "tgei", OPTO(3,TOGE), OPTO_MASK, PWRCOM, { RA, SI } }, +{ "twnli", OPTO(3,TONL), OPTO_MASK, PPCCOM, { RA, SI } }, +{ "tnli", OPTO(3,TONL), OPTO_MASK, PWRCOM, { RA, SI } }, +{ "twlti", OPTO(3,TOLT), OPTO_MASK, PPCCOM, { RA, SI } }, +{ "tlti", OPTO(3,TOLT), OPTO_MASK, PWRCOM, { RA, SI } }, +{ "twlei", OPTO(3,TOLE), OPTO_MASK, PPCCOM, { RA, SI } }, +{ "tlei", OPTO(3,TOLE), OPTO_MASK, PWRCOM, { RA, SI } }, +{ "twngi", OPTO(3,TONG), OPTO_MASK, PPCCOM, { RA, SI } }, +{ "tngi", OPTO(3,TONG), OPTO_MASK, PWRCOM, { RA, SI } }, +{ "twnei", OPTO(3,TONE), OPTO_MASK, PPCCOM, { RA, SI } }, +{ "tnei", OPTO(3,TONE), OPTO_MASK, PWRCOM, { RA, SI } }, +{ "twi", OP(3), OP_MASK, PPCCOM, { TO, RA, SI } }, +{ "ti", OP(3), OP_MASK, PWRCOM, { TO, RA, SI } }, + +{ "macchw", XO(4,172,0,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, +{ "macchw.", XO(4,172,0,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, +{ "macchwo", XO(4,172,1,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, +{ "macchwo.", XO(4,172,1,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, +{ "macchws", XO(4,236,0,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, +{ "macchws.", XO(4,236,0,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, +{ "macchwso", XO(4,236,1,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, +{ "macchwso.", XO(4,236,1,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, +{ "macchwsu", XO(4,204,0,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, +{ "macchwsu.", XO(4,204,0,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, +{ "macchwsuo", XO(4,204,1,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, +{ "macchwsuo.", XO(4,204,1,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, +{ "macchwu", XO(4,140,0,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, +{ "macchwu.", XO(4,140,0,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, +{ "macchwuo", XO(4,140,1,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, +{ "macchwuo.", XO(4,140,1,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, +{ "machhw", XO(4,44,0,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, +{ "machhw.", XO(4,44,0,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, +{ "machhwo", XO(4,44,1,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, +{ "machhwo.", XO(4,44,1,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, +{ "machhws", XO(4,108,0,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, +{ "machhws.", XO(4,108,0,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, +{ "machhwso", XO(4,108,1,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, +{ "machhwso.", XO(4,108,1,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, +{ "machhwsu", XO(4,76,0,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, +{ "machhwsu.", XO(4,76,0,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, +{ "machhwsuo", XO(4,76,1,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, +{ "machhwsuo.", XO(4,76,1,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, +{ "machhwu", XO(4,12,0,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, +{ "machhwu.", XO(4,12,0,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, +{ "machhwuo", XO(4,12,1,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, +{ "machhwuo.", XO(4,12,1,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, +{ "maclhw", XO(4,428,0,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, +{ "maclhw.", XO(4,428,0,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, +{ "maclhwo", XO(4,428,1,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, +{ "maclhwo.", XO(4,428,1,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, +{ "maclhws", XO(4,492,0,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, +{ "maclhws.", XO(4,492,0,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, +{ "maclhwso", XO(4,492,1,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, +{ "maclhwso.", XO(4,492,1,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, +{ "maclhwsu", XO(4,460,0,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, +{ "maclhwsu.", XO(4,460,0,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, +{ "maclhwsuo", XO(4,460,1,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, +{ "maclhwsuo.", XO(4,460,1,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, +{ "maclhwu", XO(4,396,0,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, +{ "maclhwu.", XO(4,396,0,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, +{ "maclhwuo", XO(4,396,1,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, +{ "maclhwuo.", XO(4,396,1,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, +{ "mulchw", XRC(4,168,0), X_MASK, PPC405|PPC440, { RT, RA, RB } }, +{ "mulchw.", XRC(4,168,1), X_MASK, PPC405|PPC440, { RT, RA, RB } }, +{ "mulchwu", XRC(4,136,0), X_MASK, PPC405|PPC440, { RT, RA, RB } }, +{ "mulchwu.", XRC(4,136,1), X_MASK, PPC405|PPC440, { RT, RA, RB } }, +{ "mulhhw", XRC(4,40,0), X_MASK, PPC405|PPC440, { RT, RA, RB } }, +{ "mulhhw.", XRC(4,40,1), X_MASK, PPC405|PPC440, { RT, RA, RB } }, +{ "mulhhwu", XRC(4,8,0), X_MASK, PPC405|PPC440, { RT, RA, RB } }, +{ "mulhhwu.", XRC(4,8,1), X_MASK, PPC405|PPC440, { RT, RA, RB } }, +{ "mullhw", XRC(4,424,0), X_MASK, PPC405|PPC440, { RT, RA, RB } }, +{ "mullhw.", XRC(4,424,1), X_MASK, PPC405|PPC440, { RT, RA, RB } }, +{ "mullhwu", XRC(4,392,0), X_MASK, PPC405|PPC440, { RT, RA, RB } }, +{ "mullhwu.", XRC(4,392,1), X_MASK, PPC405|PPC440, { RT, RA, RB } }, +{ "nmacchw", XO(4,174,0,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, +{ "nmacchw.", XO(4,174,0,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, +{ "nmacchwo", XO(4,174,1,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, +{ "nmacchwo.", XO(4,174,1,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, +{ "nmacchws", XO(4,238,0,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, +{ "nmacchws.", XO(4,238,0,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, +{ "nmacchwso", XO(4,238,1,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, +{ "nmacchwso.", XO(4,238,1,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, +{ "nmachhw", XO(4,46,0,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, +{ "nmachhw.", XO(4,46,0,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, +{ "nmachhwo", XO(4,46,1,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, +{ "nmachhwo.", XO(4,46,1,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, +{ "nmachhws", XO(4,110,0,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, +{ "nmachhws.", XO(4,110,0,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, +{ "nmachhwso", XO(4,110,1,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, +{ "nmachhwso.", XO(4,110,1,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, +{ "nmaclhw", XO(4,430,0,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, +{ "nmaclhw.", XO(4,430,0,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, +{ "nmaclhwo", XO(4,430,1,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, +{ "nmaclhwo.", XO(4,430,1,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, +{ "nmaclhws", XO(4,494,0,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, +{ "nmaclhws.", XO(4,494,0,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, +{ "nmaclhwso", XO(4,494,1,0), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, +{ "nmaclhwso.", XO(4,494,1,1), XO_MASK, PPC405|PPC440, { RT, RA, RB } }, +{ "mfvscr", VX(4, 1540), VX_MASK, PPCVEC, { VD } }, +{ "mtvscr", VX(4, 1604), VX_MASK, PPCVEC, { VB } }, + + /* Double-precision opcodes. */ + /* Some of these conflict with AltiVec, so move them before, since + PPCVEC includes the PPC_OPCODE_PPC set. */ +{ "efscfd", VX(4, 719), VX_MASK, PPCEFS, { RS, RB } }, +{ "efdabs", VX(4, 740), VX_MASK, PPCEFS, { RS, RA } }, +{ "efdnabs", VX(4, 741), VX_MASK, PPCEFS, { RS, RA } }, +{ "efdneg", VX(4, 742), VX_MASK, PPCEFS, { RS, RA } }, +{ "efdadd", VX(4, 736), VX_MASK, PPCEFS, { RS, RA, RB } }, +{ "efdsub", VX(4, 737), VX_MASK, PPCEFS, { RS, RA, RB } }, +{ "efdmul", VX(4, 744), VX_MASK, PPCEFS, { RS, RA, RB } }, +{ "efddiv", VX(4, 745), VX_MASK, PPCEFS, { RS, RA, RB } }, +{ "efdcmpgt", VX(4, 748), VX_MASK, PPCEFS, { CRFD, RA, RB } }, +{ "efdcmplt", VX(4, 749), VX_MASK, PPCEFS, { CRFD, RA, RB } }, +{ "efdcmpeq", VX(4, 750), VX_MASK, PPCEFS, { CRFD, RA, RB } }, +{ "efdtstgt", VX(4, 764), VX_MASK, PPCEFS, { CRFD, RA, RB } }, +{ "efdtstlt", VX(4, 765), VX_MASK, PPCEFS, { CRFD, RA, RB } }, +{ "efdtsteq", VX(4, 766), VX_MASK, PPCEFS, { CRFD, RA, RB } }, +{ "efdcfsi", VX(4, 753), VX_MASK, PPCEFS, { RS, RB } }, +{ "efdcfsid", VX(4, 739), VX_MASK, PPCEFS, { RS, RB } }, +{ "efdcfui", VX(4, 752), VX_MASK, PPCEFS, { RS, RB } }, +{ "efdcfuid", VX(4, 738), VX_MASK, PPCEFS, { RS, RB } }, +{ "efdcfsf", VX(4, 755), VX_MASK, PPCEFS, { RS, RB } }, +{ "efdcfuf", VX(4, 754), VX_MASK, PPCEFS, { RS, RB } }, +{ "efdctsi", VX(4, 757), VX_MASK, PPCEFS, { RS, RB } }, +{ "efdctsidz",VX(4, 747), VX_MASK, PPCEFS, { RS, RB } }, +{ "efdctsiz", VX(4, 762), VX_MASK, PPCEFS, { RS, RB } }, +{ "efdctui", VX(4, 756), VX_MASK, PPCEFS, { RS, RB } }, +{ "efdctuidz",VX(4, 746), VX_MASK, PPCEFS, { RS, RB } }, +{ "efdctuiz", VX(4, 760), VX_MASK, PPCEFS, { RS, RB } }, +{ "efdctsf", VX(4, 759), VX_MASK, PPCEFS, { RS, RB } }, +{ "efdctuf", VX(4, 758), VX_MASK, PPCEFS, { RS, RB } }, +{ "efdcfs", VX(4, 751), VX_MASK, PPCEFS, { RS, RB } }, + /* End of double-precision opcodes. */ + +{ "vaddcuw", VX(4, 384), VX_MASK, PPCVEC, { VD, VA, VB } }, +{ "vaddfp", VX(4, 10), VX_MASK, PPCVEC, { VD, VA, VB } }, +{ "vaddsbs", VX(4, 768), VX_MASK, PPCVEC, { VD, VA, VB } }, +{ "vaddshs", VX(4, 832), VX_MASK, PPCVEC, { VD, VA, VB } }, +{ "vaddsws", VX(4, 896), VX_MASK, PPCVEC, { VD, VA, VB } }, +{ "vaddubm", VX(4, 0), VX_MASK, PPCVEC, { VD, VA, VB } }, +{ "vaddubs", VX(4, 512), VX_MASK, PPCVEC, { VD, VA, VB } }, +{ "vadduhm", VX(4, 64), VX_MASK, PPCVEC, { VD, VA, VB } }, +{ "vadduhs", VX(4, 576), VX_MASK, PPCVEC, { VD, VA, VB } }, +{ "vadduwm", VX(4, 128), VX_MASK, PPCVEC, { VD, VA, VB } }, +{ "vadduws", VX(4, 640), VX_MASK, PPCVEC, { VD, VA, VB } }, +{ "vand", VX(4, 1028), VX_MASK, PPCVEC, { VD, VA, VB } }, +{ "vandc", VX(4, 1092), VX_MASK, PPCVEC, { VD, VA, VB } }, +{ "vavgsb", VX(4, 1282), VX_MASK, PPCVEC, { VD, VA, VB } }, +{ "vavgsh", VX(4, 1346), VX_MASK, PPCVEC, { VD, VA, VB } }, +{ "vavgsw", VX(4, 1410), VX_MASK, PPCVEC, { VD, VA, VB } }, +{ "vavgub", VX(4, 1026), VX_MASK, PPCVEC, { VD, VA, VB } }, +{ "vavguh", VX(4, 1090), VX_MASK, PPCVEC, { VD, VA, VB } }, +{ "vavguw", VX(4, 1154), VX_MASK, PPCVEC, { VD, VA, VB } }, +{ "vcfsx", VX(4, 842), VX_MASK, PPCVEC, { VD, VB, UIMM } }, +{ "vcfux", VX(4, 778), VX_MASK, PPCVEC, { VD, VB, UIMM } }, +{ "vcmpbfp", VXR(4, 966, 0), VXR_MASK, PPCVEC, { VD, VA, VB } }, +{ "vcmpbfp.", VXR(4, 966, 1), VXR_MASK, PPCVEC, { VD, VA, VB } }, +{ "vcmpeqfp", VXR(4, 198, 0), VXR_MASK, PPCVEC, { VD, VA, VB } }, +{ "vcmpeqfp.", VXR(4, 198, 1), VXR_MASK, PPCVEC, { VD, VA, VB } }, +{ "vcmpequb", VXR(4, 6, 0), VXR_MASK, PPCVEC, { VD, VA, VB } }, +{ "vcmpequb.", VXR(4, 6, 1), VXR_MASK, PPCVEC, { VD, VA, VB } }, +{ "vcmpequh", VXR(4, 70, 0), VXR_MASK, PPCVEC, { VD, VA, VB } }, +{ "vcmpequh.", VXR(4, 70, 1), VXR_MASK, PPCVEC, { VD, VA, VB } }, +{ "vcmpequw", VXR(4, 134, 0), VXR_MASK, PPCVEC, { VD, VA, VB } }, +{ "vcmpequw.", VXR(4, 134, 1), VXR_MASK, PPCVEC, { VD, VA, VB } }, +{ "vcmpgefp", VXR(4, 454, 0), VXR_MASK, PPCVEC, { VD, VA, VB } }, +{ "vcmpgefp.", VXR(4, 454, 1), VXR_MASK, PPCVEC, { VD, VA, VB } }, +{ "vcmpgtfp", VXR(4, 710, 0), VXR_MASK, PPCVEC, { VD, VA, VB } }, +{ "vcmpgtfp.", VXR(4, 710, 1), VXR_MASK, PPCVEC, { VD, VA, VB } }, +{ "vcmpgtsb", VXR(4, 774, 0), VXR_MASK, PPCVEC, { VD, VA, VB } }, +{ "vcmpgtsb.", VXR(4, 774, 1), VXR_MASK, PPCVEC, { VD, VA, VB } }, +{ "vcmpgtsh", VXR(4, 838, 0), VXR_MASK, PPCVEC, { VD, VA, VB } }, +{ "vcmpgtsh.", VXR(4, 838, 1), VXR_MASK, PPCVEC, { VD, VA, VB } }, +{ "vcmpgtsw", VXR(4, 902, 0), VXR_MASK, PPCVEC, { VD, VA, VB } }, +{ "vcmpgtsw.", VXR(4, 902, 1), VXR_MASK, PPCVEC, { VD, VA, VB } }, +{ "vcmpgtub", VXR(4, 518, 0), VXR_MASK, PPCVEC, { VD, VA, VB } }, +{ "vcmpgtub.", VXR(4, 518, 1), VXR_MASK, PPCVEC, { VD, VA, VB } }, +{ "vcmpgtuh", VXR(4, 582, 0), VXR_MASK, PPCVEC, { VD, VA, VB } }, +{ "vcmpgtuh.", VXR(4, 582, 1), VXR_MASK, PPCVEC, { VD, VA, VB } }, +{ "vcmpgtuw", VXR(4, 646, 0), VXR_MASK, PPCVEC, { VD, VA, VB } }, +{ "vcmpgtuw.", VXR(4, 646, 1), VXR_MASK, PPCVEC, { VD, VA, VB } }, +{ "vctsxs", VX(4, 970), VX_MASK, PPCVEC, { VD, VB, UIMM } }, +{ "vctuxs", VX(4, 906), VX_MASK, PPCVEC, { VD, VB, UIMM } }, +{ "vexptefp", VX(4, 394), VX_MASK, PPCVEC, { VD, VB } }, +{ "vlogefp", VX(4, 458), VX_MASK, PPCVEC, { VD, VB } }, +{ "vmaddfp", VXA(4, 46), VXA_MASK, PPCVEC, { VD, VA, VC, VB } }, +{ "vmaxfp", VX(4, 1034), VX_MASK, PPCVEC, { VD, VA, VB } }, +{ "vmaxsb", VX(4, 258), VX_MASK, PPCVEC, { VD, VA, VB } }, +{ "vmaxsh", VX(4, 322), VX_MASK, PPCVEC, { VD, VA, VB } }, +{ "vmaxsw", VX(4, 386), VX_MASK, PPCVEC, { VD, VA, VB } }, +{ "vmaxub", VX(4, 2), VX_MASK, PPCVEC, { VD, VA, VB } }, +{ "vmaxuh", VX(4, 66), VX_MASK, PPCVEC, { VD, VA, VB } }, +{ "vmaxuw", VX(4, 130), VX_MASK, PPCVEC, { VD, VA, VB } }, +{ "vmhaddshs", VXA(4, 32), VXA_MASK, PPCVEC, { VD, VA, VB, VC } }, +{ "vmhraddshs", VXA(4, 33), VXA_MASK, PPCVEC, { VD, VA, VB, VC } }, +{ "vminfp", VX(4, 1098), VX_MASK, PPCVEC, { VD, VA, VB } }, +{ "vminsb", VX(4, 770), VX_MASK, PPCVEC, { VD, VA, VB } }, +{ "vminsh", VX(4, 834), VX_MASK, PPCVEC, { VD, VA, VB } }, +{ "vminsw", VX(4, 898), VX_MASK, PPCVEC, { VD, VA, VB } }, +{ "vminub", VX(4, 514), VX_MASK, PPCVEC, { VD, VA, VB } }, +{ "vminuh", VX(4, 578), VX_MASK, PPCVEC, { VD, VA, VB } }, +{ "vminuw", VX(4, 642), VX_MASK, PPCVEC, { VD, VA, VB } }, +{ "vmladduhm", VXA(4, 34), VXA_MASK, PPCVEC, { VD, VA, VB, VC } }, +{ "vmrghb", VX(4, 12), VX_MASK, PPCVEC, { VD, VA, VB } }, +{ "vmrghh", VX(4, 76), VX_MASK, PPCVEC, { VD, VA, VB } }, +{ "vmrghw", VX(4, 140), VX_MASK, PPCVEC, { VD, VA, VB } }, +{ "vmrglb", VX(4, 268), VX_MASK, PPCVEC, { VD, VA, VB } }, +{ "vmrglh", VX(4, 332), VX_MASK, PPCVEC, { VD, VA, VB } }, +{ "vmrglw", VX(4, 396), VX_MASK, PPCVEC, { VD, VA, VB } }, +{ "vmsummbm", VXA(4, 37), VXA_MASK, PPCVEC, { VD, VA, VB, VC } }, +{ "vmsumshm", VXA(4, 40), VXA_MASK, PPCVEC, { VD, VA, VB, VC } }, +{ "vmsumshs", VXA(4, 41), VXA_MASK, PPCVEC, { VD, VA, VB, VC } }, +{ "vmsumubm", VXA(4, 36), VXA_MASK, PPCVEC, { VD, VA, VB, VC } }, +{ "vmsumuhm", VXA(4, 38), VXA_MASK, PPCVEC, { VD, VA, VB, VC } }, +{ "vmsumuhs", VXA(4, 39), VXA_MASK, PPCVEC, { VD, VA, VB, VC } }, +{ "vmulesb", VX(4, 776), VX_MASK, PPCVEC, { VD, VA, VB } }, +{ "vmulesh", VX(4, 840), VX_MASK, PPCVEC, { VD, VA, VB } }, +{ "vmuleub", VX(4, 520), VX_MASK, PPCVEC, { VD, VA, VB } }, +{ "vmuleuh", VX(4, 584), VX_MASK, PPCVEC, { VD, VA, VB } }, +{ "vmulosb", VX(4, 264), VX_MASK, PPCVEC, { VD, VA, VB } }, +{ "vmulosh", VX(4, 328), VX_MASK, PPCVEC, { VD, VA, VB } }, +{ "vmuloub", VX(4, 8), VX_MASK, PPCVEC, { VD, VA, VB } }, +{ "vmulouh", VX(4, 72), VX_MASK, PPCVEC, { VD, VA, VB } }, +{ "vnmsubfp", VXA(4, 47), VXA_MASK, PPCVEC, { VD, VA, VC, VB } }, +{ "vnor", VX(4, 1284), VX_MASK, PPCVEC, { VD, VA, VB } }, +{ "vor", VX(4, 1156), VX_MASK, PPCVEC, { VD, VA, VB } }, +{ "vperm", VXA(4, 43), VXA_MASK, PPCVEC, { VD, VA, VB, VC } }, +{ "vpkpx", VX(4, 782), VX_MASK, PPCVEC, { VD, VA, VB } }, +{ "vpkshss", VX(4, 398), VX_MASK, PPCVEC, { VD, VA, VB } }, +{ "vpkshus", VX(4, 270), VX_MASK, PPCVEC, { VD, VA, VB } }, +{ "vpkswss", VX(4, 462), VX_MASK, PPCVEC, { VD, VA, VB } }, +{ "vpkswus", VX(4, 334), VX_MASK, PPCVEC, { VD, VA, VB } }, +{ "vpkuhum", VX(4, 14), VX_MASK, PPCVEC, { VD, VA, VB } }, +{ "vpkuhus", VX(4, 142), VX_MASK, PPCVEC, { VD, VA, VB } }, +{ "vpkuwum", VX(4, 78), VX_MASK, PPCVEC, { VD, VA, VB } }, +{ "vpkuwus", VX(4, 206), VX_MASK, PPCVEC, { VD, VA, VB } }, +{ "vrefp", VX(4, 266), VX_MASK, PPCVEC, { VD, VB } }, +{ "vrfim", VX(4, 714), VX_MASK, PPCVEC, { VD, VB } }, +{ "vrfin", VX(4, 522), VX_MASK, PPCVEC, { VD, VB } }, +{ "vrfip", VX(4, 650), VX_MASK, PPCVEC, { VD, VB } }, +{ "vrfiz", VX(4, 586), VX_MASK, PPCVEC, { VD, VB } }, +{ "vrlb", VX(4, 4), VX_MASK, PPCVEC, { VD, VA, VB } }, +{ "vrlh", VX(4, 68), VX_MASK, PPCVEC, { VD, VA, VB } }, +{ "vrlw", VX(4, 132), VX_MASK, PPCVEC, { VD, VA, VB } }, +{ "vrsqrtefp", VX(4, 330), VX_MASK, PPCVEC, { VD, VB } }, +{ "vsel", VXA(4, 42), VXA_MASK, PPCVEC, { VD, VA, VB, VC } }, +{ "vsl", VX(4, 452), VX_MASK, PPCVEC, { VD, VA, VB } }, +{ "vslb", VX(4, 260), VX_MASK, PPCVEC, { VD, VA, VB } }, +{ "vsldoi", VXA(4, 44), VXA_MASK, PPCVEC, { VD, VA, VB, SHB } }, +{ "vslh", VX(4, 324), VX_MASK, PPCVEC, { VD, VA, VB } }, +{ "vslo", VX(4, 1036), VX_MASK, PPCVEC, { VD, VA, VB } }, +{ "vslw", VX(4, 388), VX_MASK, PPCVEC, { VD, VA, VB } }, +{ "vspltb", VX(4, 524), VX_MASK, PPCVEC, { VD, VB, UIMM } }, +{ "vsplth", VX(4, 588), VX_MASK, PPCVEC, { VD, VB, UIMM } }, +{ "vspltisb", VX(4, 780), VX_MASK, PPCVEC, { VD, SIMM } }, +{ "vspltish", VX(4, 844), VX_MASK, PPCVEC, { VD, SIMM } }, +{ "vspltisw", VX(4, 908), VX_MASK, PPCVEC, { VD, SIMM } }, +{ "vspltw", VX(4, 652), VX_MASK, PPCVEC, { VD, VB, UIMM } }, +{ "vsr", VX(4, 708), VX_MASK, PPCVEC, { VD, VA, VB } }, +{ "vsrab", VX(4, 772), VX_MASK, PPCVEC, { VD, VA, VB } }, +{ "vsrah", VX(4, 836), VX_MASK, PPCVEC, { VD, VA, VB } }, +{ "vsraw", VX(4, 900), VX_MASK, PPCVEC, { VD, VA, VB } }, +{ "vsrb", VX(4, 516), VX_MASK, PPCVEC, { VD, VA, VB } }, +{ "vsrh", VX(4, 580), VX_MASK, PPCVEC, { VD, VA, VB } }, +{ "vsro", VX(4, 1100), VX_MASK, PPCVEC, { VD, VA, VB } }, +{ "vsrw", VX(4, 644), VX_MASK, PPCVEC, { VD, VA, VB } }, +{ "vsubcuw", VX(4, 1408), VX_MASK, PPCVEC, { VD, VA, VB } }, +{ "vsubfp", VX(4, 74), VX_MASK, PPCVEC, { VD, VA, VB } }, +{ "vsubsbs", VX(4, 1792), VX_MASK, PPCVEC, { VD, VA, VB } }, +{ "vsubshs", VX(4, 1856), VX_MASK, PPCVEC, { VD, VA, VB } }, +{ "vsubsws", VX(4, 1920), VX_MASK, PPCVEC, { VD, VA, VB } }, +{ "vsububm", VX(4, 1024), VX_MASK, PPCVEC, { VD, VA, VB } }, +{ "vsububs", VX(4, 1536), VX_MASK, PPCVEC, { VD, VA, VB } }, +{ "vsubuhm", VX(4, 1088), VX_MASK, PPCVEC, { VD, VA, VB } }, +{ "vsubuhs", VX(4, 1600), VX_MASK, PPCVEC, { VD, VA, VB } }, +{ "vsubuwm", VX(4, 1152), VX_MASK, PPCVEC, { VD, VA, VB } }, +{ "vsubuws", VX(4, 1664), VX_MASK, PPCVEC, { VD, VA, VB } }, +{ "vsumsws", VX(4, 1928), VX_MASK, PPCVEC, { VD, VA, VB } }, +{ "vsum2sws", VX(4, 1672), VX_MASK, PPCVEC, { VD, VA, VB } }, +{ "vsum4sbs", VX(4, 1800), VX_MASK, PPCVEC, { VD, VA, VB } }, +{ "vsum4shs", VX(4, 1608), VX_MASK, PPCVEC, { VD, VA, VB } }, +{ "vsum4ubs", VX(4, 1544), VX_MASK, PPCVEC, { VD, VA, VB } }, +{ "vupkhpx", VX(4, 846), VX_MASK, PPCVEC, { VD, VB } }, +{ "vupkhsb", VX(4, 526), VX_MASK, PPCVEC, { VD, VB } }, +{ "vupkhsh", VX(4, 590), VX_MASK, PPCVEC, { VD, VB } }, +{ "vupklpx", VX(4, 974), VX_MASK, PPCVEC, { VD, VB } }, +{ "vupklsb", VX(4, 654), VX_MASK, PPCVEC, { VD, VB } }, +{ "vupklsh", VX(4, 718), VX_MASK, PPCVEC, { VD, VB } }, +{ "vxor", VX(4, 1220), VX_MASK, PPCVEC, { VD, VA, VB } }, + +{ "evaddw", VX(4, 512), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evaddiw", VX(4, 514), VX_MASK, PPCSPE, { RS, RB, UIMM } }, +{ "evsubfw", VX(4, 516), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evsubw", VX(4, 516), VX_MASK, PPCSPE, { RS, RB, RA } }, +{ "evsubifw", VX(4, 518), VX_MASK, PPCSPE, { RS, UIMM, RB } }, +{ "evsubiw", VX(4, 518), VX_MASK, PPCSPE, { RS, RB, UIMM } }, +{ "evabs", VX(4, 520), VX_MASK, PPCSPE, { RS, RA } }, +{ "evneg", VX(4, 521), VX_MASK, PPCSPE, { RS, RA } }, +{ "evextsb", VX(4, 522), VX_MASK, PPCSPE, { RS, RA } }, +{ "evextsh", VX(4, 523), VX_MASK, PPCSPE, { RS, RA } }, +{ "evrndw", VX(4, 524), VX_MASK, PPCSPE, { RS, RA } }, +{ "evcntlzw", VX(4, 525), VX_MASK, PPCSPE, { RS, RA } }, +{ "evcntlsw", VX(4, 526), VX_MASK, PPCSPE, { RS, RA } }, + +{ "brinc", VX(4, 527), VX_MASK, PPCSPE, { RS, RA, RB } }, + +{ "evand", VX(4, 529), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evandc", VX(4, 530), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evmr", VX(4, 535), VX_MASK, PPCSPE, { RS, RA, BBA } }, +{ "evor", VX(4, 535), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evorc", VX(4, 539), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evxor", VX(4, 534), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "eveqv", VX(4, 537), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evnand", VX(4, 542), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evnot", VX(4, 536), VX_MASK, PPCSPE, { RS, RA, BBA } }, +{ "evnor", VX(4, 536), VX_MASK, PPCSPE, { RS, RA, RB } }, + +{ "evrlw", VX(4, 552), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evrlwi", VX(4, 554), VX_MASK, PPCSPE, { RS, RA, EVUIMM } }, +{ "evslw", VX(4, 548), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evslwi", VX(4, 550), VX_MASK, PPCSPE, { RS, RA, EVUIMM } }, +{ "evsrws", VX(4, 545), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evsrwu", VX(4, 544), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evsrwis", VX(4, 547), VX_MASK, PPCSPE, { RS, RA, EVUIMM } }, +{ "evsrwiu", VX(4, 546), VX_MASK, PPCSPE, { RS, RA, EVUIMM } }, +{ "evsplati", VX(4, 553), VX_MASK, PPCSPE, { RS, SIMM } }, +{ "evsplatfi", VX(4, 555), VX_MASK, PPCSPE, { RS, SIMM } }, +{ "evmergehi", VX(4, 556), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evmergelo", VX(4, 557), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evmergehilo",VX(4,558), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evmergelohi",VX(4,559), VX_MASK, PPCSPE, { RS, RA, RB } }, + +{ "evcmpgts", VX(4, 561), VX_MASK, PPCSPE, { CRFD, RA, RB } }, +{ "evcmpgtu", VX(4, 560), VX_MASK, PPCSPE, { CRFD, RA, RB } }, +{ "evcmplts", VX(4, 563), VX_MASK, PPCSPE, { CRFD, RA, RB } }, +{ "evcmpltu", VX(4, 562), VX_MASK, PPCSPE, { CRFD, RA, RB } }, +{ "evcmpeq", VX(4, 564), VX_MASK, PPCSPE, { CRFD, RA, RB } }, +{ "evsel", EVSEL(4,79),EVSEL_MASK, PPCSPE, { RS, RA, RB, CRFS } }, + +{ "evldd", VX(4, 769), VX_MASK, PPCSPE, { RS, EVUIMM_8, RA } }, +{ "evlddx", VX(4, 768), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evldw", VX(4, 771), VX_MASK, PPCSPE, { RS, EVUIMM_8, RA } }, +{ "evldwx", VX(4, 770), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evldh", VX(4, 773), VX_MASK, PPCSPE, { RS, EVUIMM_8, RA } }, +{ "evldhx", VX(4, 772), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evlwhe", VX(4, 785), VX_MASK, PPCSPE, { RS, EVUIMM_4, RA } }, +{ "evlwhex", VX(4, 784), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evlwhou", VX(4, 789), VX_MASK, PPCSPE, { RS, EVUIMM_4, RA } }, +{ "evlwhoux", VX(4, 788), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evlwhos", VX(4, 791), VX_MASK, PPCSPE, { RS, EVUIMM_4, RA } }, +{ "evlwhosx", VX(4, 790), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evlwwsplat",VX(4, 793), VX_MASK, PPCSPE, { RS, EVUIMM_4, RA } }, +{ "evlwwsplatx",VX(4, 792), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evlwhsplat",VX(4, 797), VX_MASK, PPCSPE, { RS, EVUIMM_4, RA } }, +{ "evlwhsplatx",VX(4, 796), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evlhhesplat",VX(4, 777), VX_MASK, PPCSPE, { RS, EVUIMM_2, RA } }, +{ "evlhhesplatx",VX(4, 776), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evlhhousplat",VX(4, 781), VX_MASK, PPCSPE, { RS, EVUIMM_2, RA } }, +{ "evlhhousplatx",VX(4, 780), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evlhhossplat",VX(4, 783), VX_MASK, PPCSPE, { RS, EVUIMM_2, RA } }, +{ "evlhhossplatx",VX(4, 782), VX_MASK, PPCSPE, { RS, RA, RB } }, + +{ "evstdd", VX(4, 801), VX_MASK, PPCSPE, { RS, EVUIMM_8, RA } }, +{ "evstddx", VX(4, 800), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evstdw", VX(4, 803), VX_MASK, PPCSPE, { RS, EVUIMM_8, RA } }, +{ "evstdwx", VX(4, 802), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evstdh", VX(4, 805), VX_MASK, PPCSPE, { RS, EVUIMM_8, RA } }, +{ "evstdhx", VX(4, 804), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evstwwe", VX(4, 825), VX_MASK, PPCSPE, { RS, EVUIMM_4, RA } }, +{ "evstwwex", VX(4, 824), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evstwwo", VX(4, 829), VX_MASK, PPCSPE, { RS, EVUIMM_4, RA } }, +{ "evstwwox", VX(4, 828), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evstwhe", VX(4, 817), VX_MASK, PPCSPE, { RS, EVUIMM_4, RA } }, +{ "evstwhex", VX(4, 816), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evstwho", VX(4, 821), VX_MASK, PPCSPE, { RS, EVUIMM_4, RA } }, +{ "evstwhox", VX(4, 820), VX_MASK, PPCSPE, { RS, RA, RB } }, + +{ "evfsabs", VX(4, 644), VX_MASK, PPCSPE, { RS, RA } }, +{ "evfsnabs", VX(4, 645), VX_MASK, PPCSPE, { RS, RA } }, +{ "evfsneg", VX(4, 646), VX_MASK, PPCSPE, { RS, RA } }, +{ "evfsadd", VX(4, 640), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evfssub", VX(4, 641), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evfsmul", VX(4, 648), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evfsdiv", VX(4, 649), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evfscmpgt", VX(4, 652), VX_MASK, PPCSPE, { CRFD, RA, RB } }, +{ "evfscmplt", VX(4, 653), VX_MASK, PPCSPE, { CRFD, RA, RB } }, +{ "evfscmpeq", VX(4, 654), VX_MASK, PPCSPE, { CRFD, RA, RB } }, +{ "evfststgt", VX(4, 668), VX_MASK, PPCSPE, { CRFD, RA, RB } }, +{ "evfststlt", VX(4, 669), VX_MASK, PPCSPE, { CRFD, RA, RB } }, +{ "evfststeq", VX(4, 670), VX_MASK, PPCSPE, { CRFD, RA, RB } }, +{ "evfscfui", VX(4, 656), VX_MASK, PPCSPE, { RS, RB } }, +{ "evfsctuiz", VX(4, 664), VX_MASK, PPCSPE, { RS, RB } }, +{ "evfscfsi", VX(4, 657), VX_MASK, PPCSPE, { RS, RB } }, +{ "evfscfuf", VX(4, 658), VX_MASK, PPCSPE, { RS, RB } }, +{ "evfscfsf", VX(4, 659), VX_MASK, PPCSPE, { RS, RB } }, +{ "evfsctui", VX(4, 660), VX_MASK, PPCSPE, { RS, RB } }, +{ "evfsctsi", VX(4, 661), VX_MASK, PPCSPE, { RS, RB } }, +{ "evfsctsiz", VX(4, 666), VX_MASK, PPCSPE, { RS, RB } }, +{ "evfsctuf", VX(4, 662), VX_MASK, PPCSPE, { RS, RB } }, +{ "evfsctsf", VX(4, 663), VX_MASK, PPCSPE, { RS, RB } }, + +{ "efsabs", VX(4, 708), VX_MASK, PPCEFS, { RS, RA } }, +{ "efsnabs", VX(4, 709), VX_MASK, PPCEFS, { RS, RA } }, +{ "efsneg", VX(4, 710), VX_MASK, PPCEFS, { RS, RA } }, +{ "efsadd", VX(4, 704), VX_MASK, PPCEFS, { RS, RA, RB } }, +{ "efssub", VX(4, 705), VX_MASK, PPCEFS, { RS, RA, RB } }, +{ "efsmul", VX(4, 712), VX_MASK, PPCEFS, { RS, RA, RB } }, +{ "efsdiv", VX(4, 713), VX_MASK, PPCEFS, { RS, RA, RB } }, +{ "efscmpgt", VX(4, 716), VX_MASK, PPCEFS, { CRFD, RA, RB } }, +{ "efscmplt", VX(4, 717), VX_MASK, PPCEFS, { CRFD, RA, RB } }, +{ "efscmpeq", VX(4, 718), VX_MASK, PPCEFS, { CRFD, RA, RB } }, +{ "efststgt", VX(4, 732), VX_MASK, PPCEFS, { CRFD, RA, RB } }, +{ "efststlt", VX(4, 733), VX_MASK, PPCEFS, { CRFD, RA, RB } }, +{ "efststeq", VX(4, 734), VX_MASK, PPCEFS, { CRFD, RA, RB } }, +{ "efscfui", VX(4, 720), VX_MASK, PPCEFS, { RS, RB } }, +{ "efsctuiz", VX(4, 728), VX_MASK, PPCEFS, { RS, RB } }, +{ "efscfsi", VX(4, 721), VX_MASK, PPCEFS, { RS, RB } }, +{ "efscfuf", VX(4, 722), VX_MASK, PPCEFS, { RS, RB } }, +{ "efscfsf", VX(4, 723), VX_MASK, PPCEFS, { RS, RB } }, +{ "efsctui", VX(4, 724), VX_MASK, PPCEFS, { RS, RB } }, +{ "efsctsi", VX(4, 725), VX_MASK, PPCEFS, { RS, RB } }, +{ "efsctsiz", VX(4, 730), VX_MASK, PPCEFS, { RS, RB } }, +{ "efsctuf", VX(4, 726), VX_MASK, PPCEFS, { RS, RB } }, +{ "efsctsf", VX(4, 727), VX_MASK, PPCEFS, { RS, RB } }, + +{ "evmhossf", VX(4, 1031), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evmhossfa", VX(4, 1063), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evmhosmf", VX(4, 1039), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evmhosmfa", VX(4, 1071), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evmhosmi", VX(4, 1037), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evmhosmia", VX(4, 1069), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evmhoumi", VX(4, 1036), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evmhoumia", VX(4, 1068), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evmhessf", VX(4, 1027), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evmhessfa", VX(4, 1059), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evmhesmf", VX(4, 1035), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evmhesmfa", VX(4, 1067), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evmhesmi", VX(4, 1033), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evmhesmia", VX(4, 1065), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evmheumi", VX(4, 1032), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evmheumia", VX(4, 1064), VX_MASK, PPCSPE, { RS, RA, RB } }, + +{ "evmhossfaaw",VX(4, 1287), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evmhossiaaw",VX(4, 1285), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evmhosmfaaw",VX(4, 1295), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evmhosmiaaw",VX(4, 1293), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evmhousiaaw",VX(4, 1284), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evmhoumiaaw",VX(4, 1292), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evmhessfaaw",VX(4, 1283), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evmhessiaaw",VX(4, 1281), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evmhesmfaaw",VX(4, 1291), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evmhesmiaaw",VX(4, 1289), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evmheusiaaw",VX(4, 1280), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evmheumiaaw",VX(4, 1288), VX_MASK, PPCSPE, { RS, RA, RB } }, + +{ "evmhossfanw",VX(4, 1415), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evmhossianw",VX(4, 1413), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evmhosmfanw",VX(4, 1423), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evmhosmianw",VX(4, 1421), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evmhousianw",VX(4, 1412), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evmhoumianw",VX(4, 1420), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evmhessfanw",VX(4, 1411), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evmhessianw",VX(4, 1409), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evmhesmfanw",VX(4, 1419), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evmhesmianw",VX(4, 1417), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evmheusianw",VX(4, 1408), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evmheumianw",VX(4, 1416), VX_MASK, PPCSPE, { RS, RA, RB } }, + +{ "evmhogsmfaa",VX(4, 1327), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evmhogsmiaa",VX(4, 1325), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evmhogumiaa",VX(4, 1324), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evmhegsmfaa",VX(4, 1323), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evmhegsmiaa",VX(4, 1321), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evmhegumiaa",VX(4, 1320), VX_MASK, PPCSPE, { RS, RA, RB } }, + +{ "evmhogsmfan",VX(4, 1455), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evmhogsmian",VX(4, 1453), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evmhogumian",VX(4, 1452), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evmhegsmfan",VX(4, 1451), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evmhegsmian",VX(4, 1449), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evmhegumian",VX(4, 1448), VX_MASK, PPCSPE, { RS, RA, RB } }, + +{ "evmwhssf", VX(4, 1095), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evmwhssfa", VX(4, 1127), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evmwhsmf", VX(4, 1103), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evmwhsmfa", VX(4, 1135), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evmwhsmi", VX(4, 1101), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evmwhsmia", VX(4, 1133), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evmwhumi", VX(4, 1100), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evmwhumia", VX(4, 1132), VX_MASK, PPCSPE, { RS, RA, RB } }, + +{ "evmwlumi", VX(4, 1096), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evmwlumia", VX(4, 1128), VX_MASK, PPCSPE, { RS, RA, RB } }, + +{ "evmwlssiaaw",VX(4, 1345), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evmwlsmiaaw",VX(4, 1353), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evmwlusiaaw",VX(4, 1344), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evmwlumiaaw",VX(4, 1352), VX_MASK, PPCSPE, { RS, RA, RB } }, + +{ "evmwlssianw",VX(4, 1473), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evmwlsmianw",VX(4, 1481), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evmwlusianw",VX(4, 1472), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evmwlumianw",VX(4, 1480), VX_MASK, PPCSPE, { RS, RA, RB } }, + +{ "evmwssf", VX(4, 1107), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evmwssfa", VX(4, 1139), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evmwsmf", VX(4, 1115), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evmwsmfa", VX(4, 1147), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evmwsmi", VX(4, 1113), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evmwsmia", VX(4, 1145), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evmwumi", VX(4, 1112), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evmwumia", VX(4, 1144), VX_MASK, PPCSPE, { RS, RA, RB } }, + +{ "evmwssfaa", VX(4, 1363), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evmwsmfaa", VX(4, 1371), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evmwsmiaa", VX(4, 1369), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evmwumiaa", VX(4, 1368), VX_MASK, PPCSPE, { RS, RA, RB } }, + +{ "evmwssfan", VX(4, 1491), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evmwsmfan", VX(4, 1499), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evmwsmian", VX(4, 1497), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evmwumian", VX(4, 1496), VX_MASK, PPCSPE, { RS, RA, RB } }, + +{ "evaddssiaaw",VX(4, 1217), VX_MASK, PPCSPE, { RS, RA } }, +{ "evaddsmiaaw",VX(4, 1225), VX_MASK, PPCSPE, { RS, RA } }, +{ "evaddusiaaw",VX(4, 1216), VX_MASK, PPCSPE, { RS, RA } }, +{ "evaddumiaaw",VX(4, 1224), VX_MASK, PPCSPE, { RS, RA } }, + +{ "evsubfssiaaw",VX(4, 1219), VX_MASK, PPCSPE, { RS, RA } }, +{ "evsubfsmiaaw",VX(4, 1227), VX_MASK, PPCSPE, { RS, RA } }, +{ "evsubfusiaaw",VX(4, 1218), VX_MASK, PPCSPE, { RS, RA } }, +{ "evsubfumiaaw",VX(4, 1226), VX_MASK, PPCSPE, { RS, RA } }, + +{ "evmra", VX(4, 1220), VX_MASK, PPCSPE, { RS, RA } }, + +{ "evdivws", VX(4, 1222), VX_MASK, PPCSPE, { RS, RA, RB } }, +{ "evdivwu", VX(4, 1223), VX_MASK, PPCSPE, { RS, RA, RB } }, + +{ "mulli", OP(7), OP_MASK, PPCCOM, { RT, RA, SI } }, +{ "muli", OP(7), OP_MASK, PWRCOM, { RT, RA, SI } }, + +{ "subfic", OP(8), OP_MASK, PPCCOM, { RT, RA, SI } }, +{ "sfi", OP(8), OP_MASK, PWRCOM, { RT, RA, SI } }, + +{ "dozi", OP(9), OP_MASK, M601, { RT, RA, SI } }, + +{ "bce", B(9,0,0), B_MASK, BOOKE64, { BO, BI, BD } }, +{ "bcel", B(9,0,1), B_MASK, BOOKE64, { BO, BI, BD } }, +{ "bcea", B(9,1,0), B_MASK, BOOKE64, { BO, BI, BDA } }, +{ "bcela", B(9,1,1), B_MASK, BOOKE64, { BO, BI, BDA } }, + +{ "cmplwi", OPL(10,0), OPL_MASK, PPCCOM, { OBF, RA, UI } }, +{ "cmpldi", OPL(10,1), OPL_MASK, PPC64, { OBF, RA, UI } }, +{ "cmpli", OP(10), OP_MASK, PPC, { BF, L, RA, UI } }, +{ "cmpli", OP(10), OP_MASK, PWRCOM, { BF, RA, UI } }, + +{ "cmpwi", OPL(11,0), OPL_MASK, PPCCOM, { OBF, RA, SI } }, +{ "cmpdi", OPL(11,1), OPL_MASK, PPC64, { OBF, RA, SI } }, +{ "cmpi", OP(11), OP_MASK, PPC, { BF, L, RA, SI } }, +{ "cmpi", OP(11), OP_MASK, PWRCOM, { BF, RA, SI } }, + +{ "addic", OP(12), OP_MASK, PPCCOM, { RT, RA, SI } }, +{ "ai", OP(12), OP_MASK, PWRCOM, { RT, RA, SI } }, +{ "subic", OP(12), OP_MASK, PPCCOM, { RT, RA, NSI } }, + +{ "addic.", OP(13), OP_MASK, PPCCOM, { RT, RA, SI } }, +{ "ai.", OP(13), OP_MASK, PWRCOM, { RT, RA, SI } }, +{ "subic.", OP(13), OP_MASK, PPCCOM, { RT, RA, NSI } }, + +{ "li", OP(14), DRA_MASK, PPCCOM, { RT, SI } }, +{ "lil", OP(14), DRA_MASK, PWRCOM, { RT, SI } }, +{ "addi", OP(14), OP_MASK, PPCCOM, { RT, RA0, SI } }, +{ "cal", OP(14), OP_MASK, PWRCOM, { RT, D, RA0 } }, +{ "subi", OP(14), OP_MASK, PPCCOM, { RT, RA0, NSI } }, +{ "la", OP(14), OP_MASK, PPCCOM, { RT, D, RA0 } }, + +{ "lis", OP(15), DRA_MASK, PPCCOM, { RT, SISIGNOPT } }, +{ "liu", OP(15), DRA_MASK, PWRCOM, { RT, SISIGNOPT } }, +{ "addis", OP(15), OP_MASK, PPCCOM, { RT,RA0,SISIGNOPT } }, +{ "cau", OP(15), OP_MASK, PWRCOM, { RT,RA0,SISIGNOPT } }, +{ "subis", OP(15), OP_MASK, PPCCOM, { RT, RA0, NSI } }, + +{ "bdnz-", BBO(16,BODNZ,0,0), BBOATBI_MASK, PPCCOM, { BDM } }, +{ "bdnz+", BBO(16,BODNZ,0,0), BBOATBI_MASK, PPCCOM, { BDP } }, +{ "bdnz", BBO(16,BODNZ,0,0), BBOATBI_MASK, PPCCOM, { BD } }, +{ "bdn", BBO(16,BODNZ,0,0), BBOATBI_MASK, PWRCOM, { BD } }, +{ "bdnzl-", BBO(16,BODNZ,0,1), BBOATBI_MASK, PPCCOM, { BDM } }, +{ "bdnzl+", BBO(16,BODNZ,0,1), BBOATBI_MASK, PPCCOM, { BDP } }, +{ "bdnzl", BBO(16,BODNZ,0,1), BBOATBI_MASK, PPCCOM, { BD } }, +{ "bdnl", BBO(16,BODNZ,0,1), BBOATBI_MASK, PWRCOM, { BD } }, +{ "bdnza-", BBO(16,BODNZ,1,0), BBOATBI_MASK, PPCCOM, { BDMA } }, +{ "bdnza+", BBO(16,BODNZ,1,0), BBOATBI_MASK, PPCCOM, { BDPA } }, +{ "bdnza", BBO(16,BODNZ,1,0), BBOATBI_MASK, PPCCOM, { BDA } }, +{ "bdna", BBO(16,BODNZ,1,0), BBOATBI_MASK, PWRCOM, { BDA } }, +{ "bdnzla-", BBO(16,BODNZ,1,1), BBOATBI_MASK, PPCCOM, { BDMA } }, +{ "bdnzla+", BBO(16,BODNZ,1,1), BBOATBI_MASK, PPCCOM, { BDPA } }, +{ "bdnzla", BBO(16,BODNZ,1,1), BBOATBI_MASK, PPCCOM, { BDA } }, +{ "bdnla", BBO(16,BODNZ,1,1), BBOATBI_MASK, PWRCOM, { BDA } }, +{ "bdz-", BBO(16,BODZ,0,0), BBOATBI_MASK, PPCCOM, { BDM } }, +{ "bdz+", BBO(16,BODZ,0,0), BBOATBI_MASK, PPCCOM, { BDP } }, +{ "bdz", BBO(16,BODZ,0,0), BBOATBI_MASK, COM, { BD } }, +{ "bdzl-", BBO(16,BODZ,0,1), BBOATBI_MASK, PPCCOM, { BDM } }, +{ "bdzl+", BBO(16,BODZ,0,1), BBOATBI_MASK, PPCCOM, { BDP } }, +{ "bdzl", BBO(16,BODZ,0,1), BBOATBI_MASK, COM, { BD } }, +{ "bdza-", BBO(16,BODZ,1,0), BBOATBI_MASK, PPCCOM, { BDMA } }, +{ "bdza+", BBO(16,BODZ,1,0), BBOATBI_MASK, PPCCOM, { BDPA } }, +{ "bdza", BBO(16,BODZ,1,0), BBOATBI_MASK, COM, { BDA } }, +{ "bdzla-", BBO(16,BODZ,1,1), BBOATBI_MASK, PPCCOM, { BDMA } }, +{ "bdzla+", BBO(16,BODZ,1,1), BBOATBI_MASK, PPCCOM, { BDPA } }, +{ "bdzla", BBO(16,BODZ,1,1), BBOATBI_MASK, COM, { BDA } }, +{ "blt-", BBOCB(16,BOT,CBLT,0,0), BBOATCB_MASK, PPCCOM, { CR, BDM } }, +{ "blt+", BBOCB(16,BOT,CBLT,0,0), BBOATCB_MASK, PPCCOM, { CR, BDP } }, +{ "blt", BBOCB(16,BOT,CBLT,0,0), BBOATCB_MASK, COM, { CR, BD } }, +{ "bltl-", BBOCB(16,BOT,CBLT,0,1), BBOATCB_MASK, PPCCOM, { CR, BDM } }, +{ "bltl+", BBOCB(16,BOT,CBLT,0,1), BBOATCB_MASK, PPCCOM, { CR, BDP } }, +{ "bltl", BBOCB(16,BOT,CBLT,0,1), BBOATCB_MASK, COM, { CR, BD } }, +{ "blta-", BBOCB(16,BOT,CBLT,1,0), BBOATCB_MASK, PPCCOM, { CR, BDMA } }, +{ "blta+", BBOCB(16,BOT,CBLT,1,0), BBOATCB_MASK, PPCCOM, { CR, BDPA } }, +{ "blta", BBOCB(16,BOT,CBLT,1,0), BBOATCB_MASK, COM, { CR, BDA } }, +{ "bltla-", BBOCB(16,BOT,CBLT,1,1), BBOATCB_MASK, PPCCOM, { CR, BDMA } }, +{ "bltla+", BBOCB(16,BOT,CBLT,1,1), BBOATCB_MASK, PPCCOM, { CR, BDPA } }, +{ "bltla", BBOCB(16,BOT,CBLT,1,1), BBOATCB_MASK, COM, { CR, BDA } }, +{ "bgt-", BBOCB(16,BOT,CBGT,0,0), BBOATCB_MASK, PPCCOM, { CR, BDM } }, +{ "bgt+", BBOCB(16,BOT,CBGT,0,0), BBOATCB_MASK, PPCCOM, { CR, BDP } }, +{ "bgt", BBOCB(16,BOT,CBGT,0,0), BBOATCB_MASK, COM, { CR, BD } }, +{ "bgtl-", BBOCB(16,BOT,CBGT,0,1), BBOATCB_MASK, PPCCOM, { CR, BDM } }, +{ "bgtl+", BBOCB(16,BOT,CBGT,0,1), BBOATCB_MASK, PPCCOM, { CR, BDP } }, +{ "bgtl", BBOCB(16,BOT,CBGT,0,1), BBOATCB_MASK, COM, { CR, BD } }, +{ "bgta-", BBOCB(16,BOT,CBGT,1,0), BBOATCB_MASK, PPCCOM, { CR, BDMA } }, +{ "bgta+", BBOCB(16,BOT,CBGT,1,0), BBOATCB_MASK, PPCCOM, { CR, BDPA } }, +{ "bgta", BBOCB(16,BOT,CBGT,1,0), BBOATCB_MASK, COM, { CR, BDA } }, +{ "bgtla-", BBOCB(16,BOT,CBGT,1,1), BBOATCB_MASK, PPCCOM, { CR, BDMA } }, +{ "bgtla+", BBOCB(16,BOT,CBGT,1,1), BBOATCB_MASK, PPCCOM, { CR, BDPA } }, +{ "bgtla", BBOCB(16,BOT,CBGT,1,1), BBOATCB_MASK, COM, { CR, BDA } }, +{ "beq-", BBOCB(16,BOT,CBEQ,0,0), BBOATCB_MASK, PPCCOM, { CR, BDM } }, +{ "beq+", BBOCB(16,BOT,CBEQ,0,0), BBOATCB_MASK, PPCCOM, { CR, BDP } }, +{ "beq", BBOCB(16,BOT,CBEQ,0,0), BBOATCB_MASK, COM, { CR, BD } }, +{ "beql-", BBOCB(16,BOT,CBEQ,0,1), BBOATCB_MASK, PPCCOM, { CR, BDM } }, +{ "beql+", BBOCB(16,BOT,CBEQ,0,1), BBOATCB_MASK, PPCCOM, { CR, BDP } }, +{ "beql", BBOCB(16,BOT,CBEQ,0,1), BBOATCB_MASK, COM, { CR, BD } }, +{ "beqa-", BBOCB(16,BOT,CBEQ,1,0), BBOATCB_MASK, PPCCOM, { CR, BDMA } }, +{ "beqa+", BBOCB(16,BOT,CBEQ,1,0), BBOATCB_MASK, PPCCOM, { CR, BDPA } }, +{ "beqa", BBOCB(16,BOT,CBEQ,1,0), BBOATCB_MASK, COM, { CR, BDA } }, +{ "beqla-", BBOCB(16,BOT,CBEQ,1,1), BBOATCB_MASK, PPCCOM, { CR, BDMA } }, +{ "beqla+", BBOCB(16,BOT,CBEQ,1,1), BBOATCB_MASK, PPCCOM, { CR, BDPA } }, +{ "beqla", BBOCB(16,BOT,CBEQ,1,1), BBOATCB_MASK, COM, { CR, BDA } }, +{ "bso-", BBOCB(16,BOT,CBSO,0,0), BBOATCB_MASK, PPCCOM, { CR, BDM } }, +{ "bso+", BBOCB(16,BOT,CBSO,0,0), BBOATCB_MASK, PPCCOM, { CR, BDP } }, +{ "bso", BBOCB(16,BOT,CBSO,0,0), BBOATCB_MASK, COM, { CR, BD } }, +{ "bsol-", BBOCB(16,BOT,CBSO,0,1), BBOATCB_MASK, PPCCOM, { CR, BDM } }, +{ "bsol+", BBOCB(16,BOT,CBSO,0,1), BBOATCB_MASK, PPCCOM, { CR, BDP } }, +{ "bsol", BBOCB(16,BOT,CBSO,0,1), BBOATCB_MASK, COM, { CR, BD } }, +{ "bsoa-", BBOCB(16,BOT,CBSO,1,0), BBOATCB_MASK, PPCCOM, { CR, BDMA } }, +{ "bsoa+", BBOCB(16,BOT,CBSO,1,0), BBOATCB_MASK, PPCCOM, { CR, BDPA } }, +{ "bsoa", BBOCB(16,BOT,CBSO,1,0), BBOATCB_MASK, COM, { CR, BDA } }, +{ "bsola-", BBOCB(16,BOT,CBSO,1,1), BBOATCB_MASK, PPCCOM, { CR, BDMA } }, +{ "bsola+", BBOCB(16,BOT,CBSO,1,1), BBOATCB_MASK, PPCCOM, { CR, BDPA } }, +{ "bsola", BBOCB(16,BOT,CBSO,1,1), BBOATCB_MASK, COM, { CR, BDA } }, +{ "bun-", BBOCB(16,BOT,CBSO,0,0), BBOATCB_MASK, PPCCOM, { CR, BDM } }, +{ "bun+", BBOCB(16,BOT,CBSO,0,0), BBOATCB_MASK, PPCCOM, { CR, BDP } }, +{ "bun", BBOCB(16,BOT,CBSO,0,0), BBOATCB_MASK, PPCCOM, { CR, BD } }, +{ "bunl-", BBOCB(16,BOT,CBSO,0,1), BBOATCB_MASK, PPCCOM, { CR, BDM } }, +{ "bunl+", BBOCB(16,BOT,CBSO,0,1), BBOATCB_MASK, PPCCOM, { CR, BDP } }, +{ "bunl", BBOCB(16,BOT,CBSO,0,1), BBOATCB_MASK, PPCCOM, { CR, BD } }, +{ "buna-", BBOCB(16,BOT,CBSO,1,0), BBOATCB_MASK, PPCCOM, { CR, BDMA } }, +{ "buna+", BBOCB(16,BOT,CBSO,1,0), BBOATCB_MASK, PPCCOM, { CR, BDPA } }, +{ "buna", BBOCB(16,BOT,CBSO,1,0), BBOATCB_MASK, PPCCOM, { CR, BDA } }, +{ "bunla-", BBOCB(16,BOT,CBSO,1,1), BBOATCB_MASK, PPCCOM, { CR, BDMA } }, +{ "bunla+", BBOCB(16,BOT,CBSO,1,1), BBOATCB_MASK, PPCCOM, { CR, BDPA } }, +{ "bunla", BBOCB(16,BOT,CBSO,1,1), BBOATCB_MASK, PPCCOM, { CR, BDA } }, +{ "bge-", BBOCB(16,BOF,CBLT,0,0), BBOATCB_MASK, PPCCOM, { CR, BDM } }, +{ "bge+", BBOCB(16,BOF,CBLT,0,0), BBOATCB_MASK, PPCCOM, { CR, BDP } }, +{ "bge", BBOCB(16,BOF,CBLT,0,0), BBOATCB_MASK, COM, { CR, BD } }, +{ "bgel-", BBOCB(16,BOF,CBLT,0,1), BBOATCB_MASK, PPCCOM, { CR, BDM } }, +{ "bgel+", BBOCB(16,BOF,CBLT,0,1), BBOATCB_MASK, PPCCOM, { CR, BDP } }, +{ "bgel", BBOCB(16,BOF,CBLT,0,1), BBOATCB_MASK, COM, { CR, BD } }, +{ "bgea-", BBOCB(16,BOF,CBLT,1,0), BBOATCB_MASK, PPCCOM, { CR, BDMA } }, +{ "bgea+", BBOCB(16,BOF,CBLT,1,0), BBOATCB_MASK, PPCCOM, { CR, BDPA } }, +{ "bgea", BBOCB(16,BOF,CBLT,1,0), BBOATCB_MASK, COM, { CR, BDA } }, +{ "bgela-", BBOCB(16,BOF,CBLT,1,1), BBOATCB_MASK, PPCCOM, { CR, BDMA } }, +{ "bgela+", BBOCB(16,BOF,CBLT,1,1), BBOATCB_MASK, PPCCOM, { CR, BDPA } }, +{ "bgela", BBOCB(16,BOF,CBLT,1,1), BBOATCB_MASK, COM, { CR, BDA } }, +{ "bnl-", BBOCB(16,BOF,CBLT,0,0), BBOATCB_MASK, PPCCOM, { CR, BDM } }, +{ "bnl+", BBOCB(16,BOF,CBLT,0,0), BBOATCB_MASK, PPCCOM, { CR, BDP } }, +{ "bnl", BBOCB(16,BOF,CBLT,0,0), BBOATCB_MASK, COM, { CR, BD } }, +{ "bnll-", BBOCB(16,BOF,CBLT,0,1), BBOATCB_MASK, PPCCOM, { CR, BDM } }, +{ "bnll+", BBOCB(16,BOF,CBLT,0,1), BBOATCB_MASK, PPCCOM, { CR, BDP } }, +{ "bnll", BBOCB(16,BOF,CBLT,0,1), BBOATCB_MASK, COM, { CR, BD } }, +{ "bnla-", BBOCB(16,BOF,CBLT,1,0), BBOATCB_MASK, PPCCOM, { CR, BDMA } }, +{ "bnla+", BBOCB(16,BOF,CBLT,1,0), BBOATCB_MASK, PPCCOM, { CR, BDPA } }, +{ "bnla", BBOCB(16,BOF,CBLT,1,0), BBOATCB_MASK, COM, { CR, BDA } }, +{ "bnlla-", BBOCB(16,BOF,CBLT,1,1), BBOATCB_MASK, PPCCOM, { CR, BDMA } }, +{ "bnlla+", BBOCB(16,BOF,CBLT,1,1), BBOATCB_MASK, PPCCOM, { CR, BDPA } }, +{ "bnlla", BBOCB(16,BOF,CBLT,1,1), BBOATCB_MASK, COM, { CR, BDA } }, +{ "ble-", BBOCB(16,BOF,CBGT,0,0), BBOATCB_MASK, PPCCOM, { CR, BDM } }, +{ "ble+", BBOCB(16,BOF,CBGT,0,0), BBOATCB_MASK, PPCCOM, { CR, BDP } }, +{ "ble", BBOCB(16,BOF,CBGT,0,0), BBOATCB_MASK, COM, { CR, BD } }, +{ "blel-", BBOCB(16,BOF,CBGT,0,1), BBOATCB_MASK, PPCCOM, { CR, BDM } }, +{ "blel+", BBOCB(16,BOF,CBGT,0,1), BBOATCB_MASK, PPCCOM, { CR, BDP } }, +{ "blel", BBOCB(16,BOF,CBGT,0,1), BBOATCB_MASK, COM, { CR, BD } }, +{ "blea-", BBOCB(16,BOF,CBGT,1,0), BBOATCB_MASK, PPCCOM, { CR, BDMA } }, +{ "blea+", BBOCB(16,BOF,CBGT,1,0), BBOATCB_MASK, PPCCOM, { CR, BDPA } }, +{ "blea", BBOCB(16,BOF,CBGT,1,0), BBOATCB_MASK, COM, { CR, BDA } }, +{ "blela-", BBOCB(16,BOF,CBGT,1,1), BBOATCB_MASK, PPCCOM, { CR, BDMA } }, +{ "blela+", BBOCB(16,BOF,CBGT,1,1), BBOATCB_MASK, PPCCOM, { CR, BDPA } }, +{ "blela", BBOCB(16,BOF,CBGT,1,1), BBOATCB_MASK, COM, { CR, BDA } }, +{ "bng-", BBOCB(16,BOF,CBGT,0,0), BBOATCB_MASK, PPCCOM, { CR, BDM } }, +{ "bng+", BBOCB(16,BOF,CBGT,0,0), BBOATCB_MASK, PPCCOM, { CR, BDP } }, +{ "bng", BBOCB(16,BOF,CBGT,0,0), BBOATCB_MASK, COM, { CR, BD } }, +{ "bngl-", BBOCB(16,BOF,CBGT,0,1), BBOATCB_MASK, PPCCOM, { CR, BDM } }, +{ "bngl+", BBOCB(16,BOF,CBGT,0,1), BBOATCB_MASK, PPCCOM, { CR, BDP } }, +{ "bngl", BBOCB(16,BOF,CBGT,0,1), BBOATCB_MASK, COM, { CR, BD } }, +{ "bnga-", BBOCB(16,BOF,CBGT,1,0), BBOATCB_MASK, PPCCOM, { CR, BDMA } }, +{ "bnga+", BBOCB(16,BOF,CBGT,1,0), BBOATCB_MASK, PPCCOM, { CR, BDPA } }, +{ "bnga", BBOCB(16,BOF,CBGT,1,0), BBOATCB_MASK, COM, { CR, BDA } }, +{ "bngla-", BBOCB(16,BOF,CBGT,1,1), BBOATCB_MASK, PPCCOM, { CR, BDMA } }, +{ "bngla+", BBOCB(16,BOF,CBGT,1,1), BBOATCB_MASK, PPCCOM, { CR, BDPA } }, +{ "bngla", BBOCB(16,BOF,CBGT,1,1), BBOATCB_MASK, COM, { CR, BDA } }, +{ "bne-", BBOCB(16,BOF,CBEQ,0,0), BBOATCB_MASK, PPCCOM, { CR, BDM } }, +{ "bne+", BBOCB(16,BOF,CBEQ,0,0), BBOATCB_MASK, PPCCOM, { CR, BDP } }, +{ "bne", BBOCB(16,BOF,CBEQ,0,0), BBOATCB_MASK, COM, { CR, BD } }, +{ "bnel-", BBOCB(16,BOF,CBEQ,0,1), BBOATCB_MASK, PPCCOM, { CR, BDM } }, +{ "bnel+", BBOCB(16,BOF,CBEQ,0,1), BBOATCB_MASK, PPCCOM, { CR, BDP } }, +{ "bnel", BBOCB(16,BOF,CBEQ,0,1), BBOATCB_MASK, COM, { CR, BD } }, +{ "bnea-", BBOCB(16,BOF,CBEQ,1,0), BBOATCB_MASK, PPCCOM, { CR, BDMA } }, +{ "bnea+", BBOCB(16,BOF,CBEQ,1,0), BBOATCB_MASK, PPCCOM, { CR, BDPA } }, +{ "bnea", BBOCB(16,BOF,CBEQ,1,0), BBOATCB_MASK, COM, { CR, BDA } }, +{ "bnela-", BBOCB(16,BOF,CBEQ,1,1), BBOATCB_MASK, PPCCOM, { CR, BDMA } }, +{ "bnela+", BBOCB(16,BOF,CBEQ,1,1), BBOATCB_MASK, PPCCOM, { CR, BDPA } }, +{ "bnela", BBOCB(16,BOF,CBEQ,1,1), BBOATCB_MASK, COM, { CR, BDA } }, +{ "bns-", BBOCB(16,BOF,CBSO,0,0), BBOATCB_MASK, PPCCOM, { CR, BDM } }, +{ "bns+", BBOCB(16,BOF,CBSO,0,0), BBOATCB_MASK, PPCCOM, { CR, BDP } }, +{ "bns", BBOCB(16,BOF,CBSO,0,0), BBOATCB_MASK, COM, { CR, BD } }, +{ "bnsl-", BBOCB(16,BOF,CBSO,0,1), BBOATCB_MASK, PPCCOM, { CR, BDM } }, +{ "bnsl+", BBOCB(16,BOF,CBSO,0,1), BBOATCB_MASK, PPCCOM, { CR, BDP } }, +{ "bnsl", BBOCB(16,BOF,CBSO,0,1), BBOATCB_MASK, COM, { CR, BD } }, +{ "bnsa-", BBOCB(16,BOF,CBSO,1,0), BBOATCB_MASK, PPCCOM, { CR, BDMA } }, +{ "bnsa+", BBOCB(16,BOF,CBSO,1,0), BBOATCB_MASK, PPCCOM, { CR, BDPA } }, +{ "bnsa", BBOCB(16,BOF,CBSO,1,0), BBOATCB_MASK, COM, { CR, BDA } }, +{ "bnsla-", BBOCB(16,BOF,CBSO,1,1), BBOATCB_MASK, PPCCOM, { CR, BDMA } }, +{ "bnsla+", BBOCB(16,BOF,CBSO,1,1), BBOATCB_MASK, PPCCOM, { CR, BDPA } }, +{ "bnsla", BBOCB(16,BOF,CBSO,1,1), BBOATCB_MASK, COM, { CR, BDA } }, +{ "bnu-", BBOCB(16,BOF,CBSO,0,0), BBOATCB_MASK, PPCCOM, { CR, BDM } }, +{ "bnu+", BBOCB(16,BOF,CBSO,0,0), BBOATCB_MASK, PPCCOM, { CR, BDP } }, +{ "bnu", BBOCB(16,BOF,CBSO,0,0), BBOATCB_MASK, PPCCOM, { CR, BD } }, +{ "bnul-", BBOCB(16,BOF,CBSO,0,1), BBOATCB_MASK, PPCCOM, { CR, BDM } }, +{ "bnul+", BBOCB(16,BOF,CBSO,0,1), BBOATCB_MASK, PPCCOM, { CR, BDP } }, +{ "bnul", BBOCB(16,BOF,CBSO,0,1), BBOATCB_MASK, PPCCOM, { CR, BD } }, +{ "bnua-", BBOCB(16,BOF,CBSO,1,0), BBOATCB_MASK, PPCCOM, { CR, BDMA } }, +{ "bnua+", BBOCB(16,BOF,CBSO,1,0), BBOATCB_MASK, PPCCOM, { CR, BDPA } }, +{ "bnua", BBOCB(16,BOF,CBSO,1,0), BBOATCB_MASK, PPCCOM, { CR, BDA } }, +{ "bnula-", BBOCB(16,BOF,CBSO,1,1), BBOATCB_MASK, PPCCOM, { CR, BDMA } }, +{ "bnula+", BBOCB(16,BOF,CBSO,1,1), BBOATCB_MASK, PPCCOM, { CR, BDPA } }, +{ "bnula", BBOCB(16,BOF,CBSO,1,1), BBOATCB_MASK, PPCCOM, { CR, BDA } }, +{ "bdnzt-", BBO(16,BODNZT,0,0), BBOY_MASK, NOPOWER4, { BI, BDM } }, +{ "bdnzt+", BBO(16,BODNZT,0,0), BBOY_MASK, NOPOWER4, { BI, BDP } }, +{ "bdnzt", BBO(16,BODNZT,0,0), BBOY_MASK, PPCCOM, { BI, BD } }, +{ "bdnztl-", BBO(16,BODNZT,0,1), BBOY_MASK, NOPOWER4, { BI, BDM } }, +{ "bdnztl+", BBO(16,BODNZT,0,1), BBOY_MASK, NOPOWER4, { BI, BDP } }, +{ "bdnztl", BBO(16,BODNZT,0,1), BBOY_MASK, PPCCOM, { BI, BD } }, +{ "bdnzta-", BBO(16,BODNZT,1,0), BBOY_MASK, NOPOWER4, { BI, BDMA } }, +{ "bdnzta+", BBO(16,BODNZT,1,0), BBOY_MASK, NOPOWER4, { BI, BDPA } }, +{ "bdnzta", BBO(16,BODNZT,1,0), BBOY_MASK, PPCCOM, { BI, BDA } }, +{ "bdnztla-",BBO(16,BODNZT,1,1), BBOY_MASK, NOPOWER4, { BI, BDMA } }, +{ "bdnztla+",BBO(16,BODNZT,1,1), BBOY_MASK, NOPOWER4, { BI, BDPA } }, +{ "bdnztla", BBO(16,BODNZT,1,1), BBOY_MASK, PPCCOM, { BI, BDA } }, +{ "bdnzf-", BBO(16,BODNZF,0,0), BBOY_MASK, NOPOWER4, { BI, BDM } }, +{ "bdnzf+", BBO(16,BODNZF,0,0), BBOY_MASK, NOPOWER4, { BI, BDP } }, +{ "bdnzf", BBO(16,BODNZF,0,0), BBOY_MASK, PPCCOM, { BI, BD } }, +{ "bdnzfl-", BBO(16,BODNZF,0,1), BBOY_MASK, NOPOWER4, { BI, BDM } }, +{ "bdnzfl+", BBO(16,BODNZF,0,1), BBOY_MASK, NOPOWER4, { BI, BDP } }, +{ "bdnzfl", BBO(16,BODNZF,0,1), BBOY_MASK, PPCCOM, { BI, BD } }, +{ "bdnzfa-", BBO(16,BODNZF,1,0), BBOY_MASK, NOPOWER4, { BI, BDMA } }, +{ "bdnzfa+", BBO(16,BODNZF,1,0), BBOY_MASK, NOPOWER4, { BI, BDPA } }, +{ "bdnzfa", BBO(16,BODNZF,1,0), BBOY_MASK, PPCCOM, { BI, BDA } }, +{ "bdnzfla-",BBO(16,BODNZF,1,1), BBOY_MASK, NOPOWER4, { BI, BDMA } }, +{ "bdnzfla+",BBO(16,BODNZF,1,1), BBOY_MASK, NOPOWER4, { BI, BDPA } }, +{ "bdnzfla", BBO(16,BODNZF,1,1), BBOY_MASK, PPCCOM, { BI, BDA } }, +{ "bt-", BBO(16,BOT,0,0), BBOAT_MASK, PPCCOM, { BI, BDM } }, +{ "bt+", BBO(16,BOT,0,0), BBOAT_MASK, PPCCOM, { BI, BDP } }, +{ "bt", BBO(16,BOT,0,0), BBOAT_MASK, PPCCOM, { BI, BD } }, +{ "bbt", BBO(16,BOT,0,0), BBOAT_MASK, PWRCOM, { BI, BD } }, +{ "btl-", BBO(16,BOT,0,1), BBOAT_MASK, PPCCOM, { BI, BDM } }, +{ "btl+", BBO(16,BOT,0,1), BBOAT_MASK, PPCCOM, { BI, BDP } }, +{ "btl", BBO(16,BOT,0,1), BBOAT_MASK, PPCCOM, { BI, BD } }, +{ "bbtl", BBO(16,BOT,0,1), BBOAT_MASK, PWRCOM, { BI, BD } }, +{ "bta-", BBO(16,BOT,1,0), BBOAT_MASK, PPCCOM, { BI, BDMA } }, +{ "bta+", BBO(16,BOT,1,0), BBOAT_MASK, PPCCOM, { BI, BDPA } }, +{ "bta", BBO(16,BOT,1,0), BBOAT_MASK, PPCCOM, { BI, BDA } }, +{ "bbta", BBO(16,BOT,1,0), BBOAT_MASK, PWRCOM, { BI, BDA } }, +{ "btla-", BBO(16,BOT,1,1), BBOAT_MASK, PPCCOM, { BI, BDMA } }, +{ "btla+", BBO(16,BOT,1,1), BBOAT_MASK, PPCCOM, { BI, BDPA } }, +{ "btla", BBO(16,BOT,1,1), BBOAT_MASK, PPCCOM, { BI, BDA } }, +{ "bbtla", BBO(16,BOT,1,1), BBOAT_MASK, PWRCOM, { BI, BDA } }, +{ "bf-", BBO(16,BOF,0,0), BBOAT_MASK, PPCCOM, { BI, BDM } }, +{ "bf+", BBO(16,BOF,0,0), BBOAT_MASK, PPCCOM, { BI, BDP } }, +{ "bf", BBO(16,BOF,0,0), BBOAT_MASK, PPCCOM, { BI, BD } }, +{ "bbf", BBO(16,BOF,0,0), BBOAT_MASK, PWRCOM, { BI, BD } }, +{ "bfl-", BBO(16,BOF,0,1), BBOAT_MASK, PPCCOM, { BI, BDM } }, +{ "bfl+", BBO(16,BOF,0,1), BBOAT_MASK, PPCCOM, { BI, BDP } }, +{ "bfl", BBO(16,BOF,0,1), BBOAT_MASK, PPCCOM, { BI, BD } }, +{ "bbfl", BBO(16,BOF,0,1), BBOAT_MASK, PWRCOM, { BI, BD } }, +{ "bfa-", BBO(16,BOF,1,0), BBOAT_MASK, PPCCOM, { BI, BDMA } }, +{ "bfa+", BBO(16,BOF,1,0), BBOAT_MASK, PPCCOM, { BI, BDPA } }, +{ "bfa", BBO(16,BOF,1,0), BBOAT_MASK, PPCCOM, { BI, BDA } }, +{ "bbfa", BBO(16,BOF,1,0), BBOAT_MASK, PWRCOM, { BI, BDA } }, +{ "bfla-", BBO(16,BOF,1,1), BBOAT_MASK, PPCCOM, { BI, BDMA } }, +{ "bfla+", BBO(16,BOF,1,1), BBOAT_MASK, PPCCOM, { BI, BDPA } }, +{ "bfla", BBO(16,BOF,1,1), BBOAT_MASK, PPCCOM, { BI, BDA } }, +{ "bbfla", BBO(16,BOF,1,1), BBOAT_MASK, PWRCOM, { BI, BDA } }, +{ "bdzt-", BBO(16,BODZT,0,0), BBOY_MASK, NOPOWER4, { BI, BDM } }, +{ "bdzt+", BBO(16,BODZT,0,0), BBOY_MASK, NOPOWER4, { BI, BDP } }, +{ "bdzt", BBO(16,BODZT,0,0), BBOY_MASK, PPCCOM, { BI, BD } }, +{ "bdztl-", BBO(16,BODZT,0,1), BBOY_MASK, NOPOWER4, { BI, BDM } }, +{ "bdztl+", BBO(16,BODZT,0,1), BBOY_MASK, NOPOWER4, { BI, BDP } }, +{ "bdztl", BBO(16,BODZT,0,1), BBOY_MASK, PPCCOM, { BI, BD } }, +{ "bdzta-", BBO(16,BODZT,1,0), BBOY_MASK, NOPOWER4, { BI, BDMA } }, +{ "bdzta+", BBO(16,BODZT,1,0), BBOY_MASK, NOPOWER4, { BI, BDPA } }, +{ "bdzta", BBO(16,BODZT,1,0), BBOY_MASK, PPCCOM, { BI, BDA } }, +{ "bdztla-", BBO(16,BODZT,1,1), BBOY_MASK, NOPOWER4, { BI, BDMA } }, +{ "bdztla+", BBO(16,BODZT,1,1), BBOY_MASK, NOPOWER4, { BI, BDPA } }, +{ "bdztla", BBO(16,BODZT,1,1), BBOY_MASK, PPCCOM, { BI, BDA } }, +{ "bdzf-", BBO(16,BODZF,0,0), BBOY_MASK, NOPOWER4, { BI, BDM } }, +{ "bdzf+", BBO(16,BODZF,0,0), BBOY_MASK, NOPOWER4, { BI, BDP } }, +{ "bdzf", BBO(16,BODZF,0,0), BBOY_MASK, PPCCOM, { BI, BD } }, +{ "bdzfl-", BBO(16,BODZF,0,1), BBOY_MASK, NOPOWER4, { BI, BDM } }, +{ "bdzfl+", BBO(16,BODZF,0,1), BBOY_MASK, NOPOWER4, { BI, BDP } }, +{ "bdzfl", BBO(16,BODZF,0,1), BBOY_MASK, PPCCOM, { BI, BD } }, +{ "bdzfa-", BBO(16,BODZF,1,0), BBOY_MASK, NOPOWER4, { BI, BDMA } }, +{ "bdzfa+", BBO(16,BODZF,1,0), BBOY_MASK, NOPOWER4, { BI, BDPA } }, +{ "bdzfa", BBO(16,BODZF,1,0), BBOY_MASK, PPCCOM, { BI, BDA } }, +{ "bdzfla-", BBO(16,BODZF,1,1), BBOY_MASK, NOPOWER4, { BI, BDMA } }, +{ "bdzfla+", BBO(16,BODZF,1,1), BBOY_MASK, NOPOWER4, { BI, BDPA } }, +{ "bdzfla", BBO(16,BODZF,1,1), BBOY_MASK, PPCCOM, { BI, BDA } }, +{ "bc-", B(16,0,0), B_MASK, PPCCOM, { BOE, BI, BDM } }, +{ "bc+", B(16,0,0), B_MASK, PPCCOM, { BOE, BI, BDP } }, +{ "bc", B(16,0,0), B_MASK, COM, { BO, BI, BD } }, +{ "bcl-", B(16,0,1), B_MASK, PPCCOM, { BOE, BI, BDM } }, +{ "bcl+", B(16,0,1), B_MASK, PPCCOM, { BOE, BI, BDP } }, +{ "bcl", B(16,0,1), B_MASK, COM, { BO, BI, BD } }, +{ "bca-", B(16,1,0), B_MASK, PPCCOM, { BOE, BI, BDMA } }, +{ "bca+", B(16,1,0), B_MASK, PPCCOM, { BOE, BI, BDPA } }, +{ "bca", B(16,1,0), B_MASK, COM, { BO, BI, BDA } }, +{ "bcla-", B(16,1,1), B_MASK, PPCCOM, { BOE, BI, BDMA } }, +{ "bcla+", B(16,1,1), B_MASK, PPCCOM, { BOE, BI, BDPA } }, +{ "bcla", B(16,1,1), B_MASK, COM, { BO, BI, BDA } }, + +{ "sc", SC(17,1,0), SC_MASK, PPC, { LEV } }, +{ "svc", SC(17,0,0), SC_MASK, POWER, { SVC_LEV, FL1, FL2 } }, +{ "svcl", SC(17,0,1), SC_MASK, POWER, { SVC_LEV, FL1, FL2 } }, +{ "svca", SC(17,1,0), SC_MASK, PWRCOM, { SV } }, +{ "svcla", SC(17,1,1), SC_MASK, POWER, { SV } }, + +{ "b", B(18,0,0), B_MASK, COM, { LI } }, +{ "bl", B(18,0,1), B_MASK, COM, { LI } }, +{ "ba", B(18,1,0), B_MASK, COM, { LIA } }, +{ "bla", B(18,1,1), B_MASK, COM, { LIA } }, + +{ "mcrf", XL(19,0), XLBB_MASK|(3 << 21)|(3 << 16), COM, { BF, BFA } }, + +{ "blr", XLO(19,BOU,16,0), XLBOBIBB_MASK, PPCCOM, { 0 } }, +{ "br", XLO(19,BOU,16,0), XLBOBIBB_MASK, PWRCOM, { 0 } }, +{ "blrl", XLO(19,BOU,16,1), XLBOBIBB_MASK, PPCCOM, { 0 } }, +{ "brl", XLO(19,BOU,16,1), XLBOBIBB_MASK, PWRCOM, { 0 } }, +{ "bdnzlr", XLO(19,BODNZ,16,0), XLBOBIBB_MASK, PPCCOM, { 0 } }, +{ "bdnzlr-", XLO(19,BODNZ,16,0), XLBOBIBB_MASK, NOPOWER4, { 0 } }, +{ "bdnzlr-", XLO(19,BODNZM4,16,0), XLBOBIBB_MASK, POWER4, { 0 } }, +{ "bdnzlr+", XLO(19,BODNZP,16,0), XLBOBIBB_MASK, NOPOWER4, { 0 } }, +{ "bdnzlr+", XLO(19,BODNZP4,16,0), XLBOBIBB_MASK, POWER4, { 0 } }, +{ "bdnzlrl", XLO(19,BODNZ,16,1), XLBOBIBB_MASK, PPCCOM, { 0 } }, +{ "bdnzlrl-",XLO(19,BODNZ,16,1), XLBOBIBB_MASK, NOPOWER4, { 0 } }, +{ "bdnzlrl-",XLO(19,BODNZM4,16,1), XLBOBIBB_MASK, POWER4, { 0 } }, +{ "bdnzlrl+",XLO(19,BODNZP,16,1), XLBOBIBB_MASK, NOPOWER4, { 0 } }, +{ "bdnzlrl+",XLO(19,BODNZP4,16,1), XLBOBIBB_MASK, POWER4, { 0 } }, +{ "bdzlr", XLO(19,BODZ,16,0), XLBOBIBB_MASK, PPCCOM, { 0 } }, +{ "bdzlr-", XLO(19,BODZ,16,0), XLBOBIBB_MASK, NOPOWER4, { 0 } }, +{ "bdzlr-", XLO(19,BODZM4,16,0), XLBOBIBB_MASK, POWER4, { 0 } }, +{ "bdzlr+", XLO(19,BODZP,16,0), XLBOBIBB_MASK, NOPOWER4, { 0 } }, +{ "bdzlr+", XLO(19,BODZP4,16,0), XLBOBIBB_MASK, POWER4, { 0 } }, +{ "bdzlrl", XLO(19,BODZ,16,1), XLBOBIBB_MASK, PPCCOM, { 0 } }, +{ "bdzlrl-", XLO(19,BODZ,16,1), XLBOBIBB_MASK, NOPOWER4, { 0 } }, +{ "bdzlrl-", XLO(19,BODZM4,16,1), XLBOBIBB_MASK, POWER4, { 0 } }, +{ "bdzlrl+", XLO(19,BODZP,16,1), XLBOBIBB_MASK, NOPOWER4, { 0 } }, +{ "bdzlrl+", XLO(19,BODZP4,16,1), XLBOBIBB_MASK, POWER4, { 0 } }, +{ "bltlr", XLOCB(19,BOT,CBLT,16,0), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "bltlr-", XLOCB(19,BOT,CBLT,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "bltlr-", XLOCB(19,BOTM4,CBLT,16,0), XLBOCBBB_MASK, POWER4, { CR } }, +{ "bltlr+", XLOCB(19,BOTP,CBLT,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "bltlr+", XLOCB(19,BOTP4,CBLT,16,0), XLBOCBBB_MASK, POWER4, { CR } }, +{ "bltr", XLOCB(19,BOT,CBLT,16,0), XLBOCBBB_MASK, PWRCOM, { CR } }, +{ "bltlrl", XLOCB(19,BOT,CBLT,16,1), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "bltlrl-", XLOCB(19,BOT,CBLT,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "bltlrl-", XLOCB(19,BOTM4,CBLT,16,1), XLBOCBBB_MASK, POWER4, { CR } }, +{ "bltlrl+", XLOCB(19,BOTP,CBLT,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "bltlrl+", XLOCB(19,BOTP4,CBLT,16,1), XLBOCBBB_MASK, POWER4, { CR } }, +{ "bltrl", XLOCB(19,BOT,CBLT,16,1), XLBOCBBB_MASK, PWRCOM, { CR } }, +{ "bgtlr", XLOCB(19,BOT,CBGT,16,0), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "bgtlr-", XLOCB(19,BOT,CBGT,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "bgtlr-", XLOCB(19,BOTM4,CBGT,16,0), XLBOCBBB_MASK, POWER4, { CR } }, +{ "bgtlr+", XLOCB(19,BOTP,CBGT,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "bgtlr+", XLOCB(19,BOTP4,CBGT,16,0), XLBOCBBB_MASK, POWER4, { CR } }, +{ "bgtr", XLOCB(19,BOT,CBGT,16,0), XLBOCBBB_MASK, PWRCOM, { CR } }, +{ "bgtlrl", XLOCB(19,BOT,CBGT,16,1), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "bgtlrl-", XLOCB(19,BOT,CBGT,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "bgtlrl-", XLOCB(19,BOTM4,CBGT,16,1), XLBOCBBB_MASK, POWER4, { CR } }, +{ "bgtlrl+", XLOCB(19,BOTP,CBGT,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "bgtlrl+", XLOCB(19,BOTP4,CBGT,16,1), XLBOCBBB_MASK, POWER4, { CR } }, +{ "bgtrl", XLOCB(19,BOT,CBGT,16,1), XLBOCBBB_MASK, PWRCOM, { CR } }, +{ "beqlr", XLOCB(19,BOT,CBEQ,16,0), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "beqlr-", XLOCB(19,BOT,CBEQ,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "beqlr-", XLOCB(19,BOTM4,CBEQ,16,0), XLBOCBBB_MASK, POWER4, { CR } }, +{ "beqlr+", XLOCB(19,BOTP,CBEQ,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "beqlr+", XLOCB(19,BOTP4,CBEQ,16,0), XLBOCBBB_MASK, POWER4, { CR } }, +{ "beqr", XLOCB(19,BOT,CBEQ,16,0), XLBOCBBB_MASK, PWRCOM, { CR } }, +{ "beqlrl", XLOCB(19,BOT,CBEQ,16,1), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "beqlrl-", XLOCB(19,BOT,CBEQ,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "beqlrl-", XLOCB(19,BOTM4,CBEQ,16,1), XLBOCBBB_MASK, POWER4, { CR } }, +{ "beqlrl+", XLOCB(19,BOTP,CBEQ,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "beqlrl+", XLOCB(19,BOTP4,CBEQ,16,1), XLBOCBBB_MASK, POWER4, { CR } }, +{ "beqrl", XLOCB(19,BOT,CBEQ,16,1), XLBOCBBB_MASK, PWRCOM, { CR } }, +{ "bsolr", XLOCB(19,BOT,CBSO,16,0), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "bsolr-", XLOCB(19,BOT,CBSO,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "bsolr-", XLOCB(19,BOTM4,CBSO,16,0), XLBOCBBB_MASK, POWER4, { CR } }, +{ "bsolr+", XLOCB(19,BOTP,CBSO,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "bsolr+", XLOCB(19,BOTP4,CBSO,16,0), XLBOCBBB_MASK, POWER4, { CR } }, +{ "bsor", XLOCB(19,BOT,CBSO,16,0), XLBOCBBB_MASK, PWRCOM, { CR } }, +{ "bsolrl", XLOCB(19,BOT,CBSO,16,1), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "bsolrl-", XLOCB(19,BOT,CBSO,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "bsolrl-", XLOCB(19,BOTM4,CBSO,16,1), XLBOCBBB_MASK, POWER4, { CR } }, +{ "bsolrl+", XLOCB(19,BOTP,CBSO,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "bsolrl+", XLOCB(19,BOTP4,CBSO,16,1), XLBOCBBB_MASK, POWER4, { CR } }, +{ "bsorl", XLOCB(19,BOT,CBSO,16,1), XLBOCBBB_MASK, PWRCOM, { CR } }, +{ "bunlr", XLOCB(19,BOT,CBSO,16,0), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "bunlr-", XLOCB(19,BOT,CBSO,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "bunlr-", XLOCB(19,BOTM4,CBSO,16,0), XLBOCBBB_MASK, POWER4, { CR } }, +{ "bunlr+", XLOCB(19,BOTP,CBSO,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "bunlr+", XLOCB(19,BOTP4,CBSO,16,0), XLBOCBBB_MASK, POWER4, { CR } }, +{ "bunlrl", XLOCB(19,BOT,CBSO,16,1), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "bunlrl-", XLOCB(19,BOT,CBSO,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "bunlrl-", XLOCB(19,BOTM4,CBSO,16,1), XLBOCBBB_MASK, POWER4, { CR } }, +{ "bunlrl+", XLOCB(19,BOTP,CBSO,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "bunlrl+", XLOCB(19,BOTP4,CBSO,16,1), XLBOCBBB_MASK, POWER4, { CR } }, +{ "bgelr", XLOCB(19,BOF,CBLT,16,0), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "bgelr-", XLOCB(19,BOF,CBLT,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "bgelr-", XLOCB(19,BOFM4,CBLT,16,0), XLBOCBBB_MASK, POWER4, { CR } }, +{ "bgelr+", XLOCB(19,BOFP,CBLT,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "bgelr+", XLOCB(19,BOFP4,CBLT,16,0), XLBOCBBB_MASK, POWER4, { CR } }, +{ "bger", XLOCB(19,BOF,CBLT,16,0), XLBOCBBB_MASK, PWRCOM, { CR } }, +{ "bgelrl", XLOCB(19,BOF,CBLT,16,1), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "bgelrl-", XLOCB(19,BOF,CBLT,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "bgelrl-", XLOCB(19,BOFM4,CBLT,16,1), XLBOCBBB_MASK, POWER4, { CR } }, +{ "bgelrl+", XLOCB(19,BOFP,CBLT,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "bgelrl+", XLOCB(19,BOFP4,CBLT,16,1), XLBOCBBB_MASK, POWER4, { CR } }, +{ "bgerl", XLOCB(19,BOF,CBLT,16,1), XLBOCBBB_MASK, PWRCOM, { CR } }, +{ "bnllr", XLOCB(19,BOF,CBLT,16,0), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "bnllr-", XLOCB(19,BOF,CBLT,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "bnllr-", XLOCB(19,BOFM4,CBLT,16,0), XLBOCBBB_MASK, POWER4, { CR } }, +{ "bnllr+", XLOCB(19,BOFP,CBLT,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "bnllr+", XLOCB(19,BOFP4,CBLT,16,0), XLBOCBBB_MASK, POWER4, { CR } }, +{ "bnlr", XLOCB(19,BOF,CBLT,16,0), XLBOCBBB_MASK, PWRCOM, { CR } }, +{ "bnllrl", XLOCB(19,BOF,CBLT,16,1), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "bnllrl-", XLOCB(19,BOF,CBLT,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "bnllrl-", XLOCB(19,BOFM4,CBLT,16,1), XLBOCBBB_MASK, POWER4, { CR } }, +{ "bnllrl+", XLOCB(19,BOFP,CBLT,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "bnllrl+", XLOCB(19,BOFP4,CBLT,16,1), XLBOCBBB_MASK, POWER4, { CR } }, +{ "bnlrl", XLOCB(19,BOF,CBLT,16,1), XLBOCBBB_MASK, PWRCOM, { CR } }, +{ "blelr", XLOCB(19,BOF,CBGT,16,0), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "blelr-", XLOCB(19,BOF,CBGT,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "blelr-", XLOCB(19,BOFM4,CBGT,16,0), XLBOCBBB_MASK, POWER4, { CR } }, +{ "blelr+", XLOCB(19,BOFP,CBGT,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "blelr+", XLOCB(19,BOFP4,CBGT,16,0), XLBOCBBB_MASK, POWER4, { CR } }, +{ "bler", XLOCB(19,BOF,CBGT,16,0), XLBOCBBB_MASK, PWRCOM, { CR } }, +{ "blelrl", XLOCB(19,BOF,CBGT,16,1), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "blelrl-", XLOCB(19,BOF,CBGT,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "blelrl-", XLOCB(19,BOFM4,CBGT,16,1), XLBOCBBB_MASK, POWER4, { CR } }, +{ "blelrl+", XLOCB(19,BOFP,CBGT,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "blelrl+", XLOCB(19,BOFP4,CBGT,16,1), XLBOCBBB_MASK, POWER4, { CR } }, +{ "blerl", XLOCB(19,BOF,CBGT,16,1), XLBOCBBB_MASK, PWRCOM, { CR } }, +{ "bnglr", XLOCB(19,BOF,CBGT,16,0), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "bnglr-", XLOCB(19,BOF,CBGT,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "bnglr-", XLOCB(19,BOFM4,CBGT,16,0), XLBOCBBB_MASK, POWER4, { CR } }, +{ "bnglr+", XLOCB(19,BOFP,CBGT,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "bnglr+", XLOCB(19,BOFP4,CBGT,16,0), XLBOCBBB_MASK, POWER4, { CR } }, +{ "bngr", XLOCB(19,BOF,CBGT,16,0), XLBOCBBB_MASK, PWRCOM, { CR } }, +{ "bnglrl", XLOCB(19,BOF,CBGT,16,1), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "bnglrl-", XLOCB(19,BOF,CBGT,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "bnglrl-", XLOCB(19,BOFM4,CBGT,16,1), XLBOCBBB_MASK, POWER4, { CR } }, +{ "bnglrl+", XLOCB(19,BOFP,CBGT,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "bnglrl+", XLOCB(19,BOFP4,CBGT,16,1), XLBOCBBB_MASK, POWER4, { CR } }, +{ "bngrl", XLOCB(19,BOF,CBGT,16,1), XLBOCBBB_MASK, PWRCOM, { CR } }, +{ "bnelr", XLOCB(19,BOF,CBEQ,16,0), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "bnelr-", XLOCB(19,BOF,CBEQ,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "bnelr-", XLOCB(19,BOFM4,CBEQ,16,0), XLBOCBBB_MASK, POWER4, { CR } }, +{ "bnelr+", XLOCB(19,BOFP,CBEQ,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "bnelr+", XLOCB(19,BOFP4,CBEQ,16,0), XLBOCBBB_MASK, POWER4, { CR } }, +{ "bner", XLOCB(19,BOF,CBEQ,16,0), XLBOCBBB_MASK, PWRCOM, { CR } }, +{ "bnelrl", XLOCB(19,BOF,CBEQ,16,1), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "bnelrl-", XLOCB(19,BOF,CBEQ,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "bnelrl-", XLOCB(19,BOFM4,CBEQ,16,1), XLBOCBBB_MASK, POWER4, { CR } }, +{ "bnelrl+", XLOCB(19,BOFP,CBEQ,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "bnelrl+", XLOCB(19,BOFP4,CBEQ,16,1), XLBOCBBB_MASK, POWER4, { CR } }, +{ "bnerl", XLOCB(19,BOF,CBEQ,16,1), XLBOCBBB_MASK, PWRCOM, { CR } }, +{ "bnslr", XLOCB(19,BOF,CBSO,16,0), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "bnslr-", XLOCB(19,BOF,CBSO,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "bnslr-", XLOCB(19,BOFM4,CBSO,16,0), XLBOCBBB_MASK, POWER4, { CR } }, +{ "bnslr+", XLOCB(19,BOFP,CBSO,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "bnslr+", XLOCB(19,BOFP4,CBSO,16,0), XLBOCBBB_MASK, POWER4, { CR } }, +{ "bnsr", XLOCB(19,BOF,CBSO,16,0), XLBOCBBB_MASK, PWRCOM, { CR } }, +{ "bnslrl", XLOCB(19,BOF,CBSO,16,1), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "bnslrl-", XLOCB(19,BOF,CBSO,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "bnslrl-", XLOCB(19,BOFM4,CBSO,16,1), XLBOCBBB_MASK, POWER4, { CR } }, +{ "bnslrl+", XLOCB(19,BOFP,CBSO,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "bnslrl+", XLOCB(19,BOFP4,CBSO,16,1), XLBOCBBB_MASK, POWER4, { CR } }, +{ "bnsrl", XLOCB(19,BOF,CBSO,16,1), XLBOCBBB_MASK, PWRCOM, { CR } }, +{ "bnulr", XLOCB(19,BOF,CBSO,16,0), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "bnulr-", XLOCB(19,BOF,CBSO,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "bnulr-", XLOCB(19,BOFM4,CBSO,16,0), XLBOCBBB_MASK, POWER4, { CR } }, +{ "bnulr+", XLOCB(19,BOFP,CBSO,16,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "bnulr+", XLOCB(19,BOFP4,CBSO,16,0), XLBOCBBB_MASK, POWER4, { CR } }, +{ "bnulrl", XLOCB(19,BOF,CBSO,16,1), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "bnulrl-", XLOCB(19,BOF,CBSO,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "bnulrl-", XLOCB(19,BOFM4,CBSO,16,1), XLBOCBBB_MASK, POWER4, { CR } }, +{ "bnulrl+", XLOCB(19,BOFP,CBSO,16,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "bnulrl+", XLOCB(19,BOFP4,CBSO,16,1), XLBOCBBB_MASK, POWER4, { CR } }, +{ "btlr", XLO(19,BOT,16,0), XLBOBB_MASK, PPCCOM, { BI } }, +{ "btlr-", XLO(19,BOT,16,0), XLBOBB_MASK, NOPOWER4, { BI } }, +{ "btlr-", XLO(19,BOTM4,16,0), XLBOBB_MASK, POWER4, { BI } }, +{ "btlr+", XLO(19,BOTP,16,0), XLBOBB_MASK, NOPOWER4, { BI } }, +{ "btlr+", XLO(19,BOTP4,16,0), XLBOBB_MASK, POWER4, { BI } }, +{ "bbtr", XLO(19,BOT,16,0), XLBOBB_MASK, PWRCOM, { BI } }, +{ "btlrl", XLO(19,BOT,16,1), XLBOBB_MASK, PPCCOM, { BI } }, +{ "btlrl-", XLO(19,BOT,16,1), XLBOBB_MASK, NOPOWER4, { BI } }, +{ "btlrl-", XLO(19,BOTM4,16,1), XLBOBB_MASK, POWER4, { BI } }, +{ "btlrl+", XLO(19,BOTP,16,1), XLBOBB_MASK, NOPOWER4, { BI } }, +{ "btlrl+", XLO(19,BOTP4,16,1), XLBOBB_MASK, POWER4, { BI } }, +{ "bbtrl", XLO(19,BOT,16,1), XLBOBB_MASK, PWRCOM, { BI } }, +{ "bflr", XLO(19,BOF,16,0), XLBOBB_MASK, PPCCOM, { BI } }, +{ "bflr-", XLO(19,BOF,16,0), XLBOBB_MASK, NOPOWER4, { BI } }, +{ "bflr-", XLO(19,BOFM4,16,0), XLBOBB_MASK, POWER4, { BI } }, +{ "bflr+", XLO(19,BOFP,16,0), XLBOBB_MASK, NOPOWER4, { BI } }, +{ "bflr+", XLO(19,BOFP4,16,0), XLBOBB_MASK, POWER4, { BI } }, +{ "bbfr", XLO(19,BOF,16,0), XLBOBB_MASK, PWRCOM, { BI } }, +{ "bflrl", XLO(19,BOF,16,1), XLBOBB_MASK, PPCCOM, { BI } }, +{ "bflrl-", XLO(19,BOF,16,1), XLBOBB_MASK, NOPOWER4, { BI } }, +{ "bflrl-", XLO(19,BOFM4,16,1), XLBOBB_MASK, POWER4, { BI } }, +{ "bflrl+", XLO(19,BOFP,16,1), XLBOBB_MASK, NOPOWER4, { BI } }, +{ "bflrl+", XLO(19,BOFP4,16,1), XLBOBB_MASK, POWER4, { BI } }, +{ "bbfrl", XLO(19,BOF,16,1), XLBOBB_MASK, PWRCOM, { BI } }, +{ "bdnztlr", XLO(19,BODNZT,16,0), XLBOBB_MASK, PPCCOM, { BI } }, +{ "bdnztlr-",XLO(19,BODNZT,16,0), XLBOBB_MASK, NOPOWER4, { BI } }, +{ "bdnztlr+",XLO(19,BODNZTP,16,0), XLBOBB_MASK, NOPOWER4, { BI } }, +{ "bdnztlrl",XLO(19,BODNZT,16,1), XLBOBB_MASK, PPCCOM, { BI } }, +{ "bdnztlrl-",XLO(19,BODNZT,16,1), XLBOBB_MASK, NOPOWER4, { BI } }, +{ "bdnztlrl+",XLO(19,BODNZTP,16,1), XLBOBB_MASK, NOPOWER4, { BI } }, +{ "bdnzflr", XLO(19,BODNZF,16,0), XLBOBB_MASK, PPCCOM, { BI } }, +{ "bdnzflr-",XLO(19,BODNZF,16,0), XLBOBB_MASK, NOPOWER4, { BI } }, +{ "bdnzflr+",XLO(19,BODNZFP,16,0), XLBOBB_MASK, NOPOWER4, { BI } }, +{ "bdnzflrl",XLO(19,BODNZF,16,1), XLBOBB_MASK, PPCCOM, { BI } }, +{ "bdnzflrl-",XLO(19,BODNZF,16,1), XLBOBB_MASK, NOPOWER4, { BI } }, +{ "bdnzflrl+",XLO(19,BODNZFP,16,1), XLBOBB_MASK, NOPOWER4, { BI } }, +{ "bdztlr", XLO(19,BODZT,16,0), XLBOBB_MASK, PPCCOM, { BI } }, +{ "bdztlr-", XLO(19,BODZT,16,0), XLBOBB_MASK, NOPOWER4, { BI } }, +{ "bdztlr+", XLO(19,BODZTP,16,0), XLBOBB_MASK, NOPOWER4, { BI } }, +{ "bdztlrl", XLO(19,BODZT,16,1), XLBOBB_MASK, PPCCOM, { BI } }, +{ "bdztlrl-",XLO(19,BODZT,16,1), XLBOBB_MASK, NOPOWER4, { BI } }, +{ "bdztlrl+",XLO(19,BODZTP,16,1), XLBOBB_MASK, NOPOWER4, { BI } }, +{ "bdzflr", XLO(19,BODZF,16,0), XLBOBB_MASK, PPCCOM, { BI } }, +{ "bdzflr-", XLO(19,BODZF,16,0), XLBOBB_MASK, NOPOWER4, { BI } }, +{ "bdzflr+", XLO(19,BODZFP,16,0), XLBOBB_MASK, NOPOWER4, { BI } }, +{ "bdzflrl", XLO(19,BODZF,16,1), XLBOBB_MASK, PPCCOM, { BI } }, +{ "bdzflrl-",XLO(19,BODZF,16,1), XLBOBB_MASK, NOPOWER4, { BI } }, +{ "bdzflrl+",XLO(19,BODZFP,16,1), XLBOBB_MASK, NOPOWER4, { BI } }, +{ "bclr+", XLYLK(19,16,1,0), XLYBB_MASK, PPCCOM, { BOE, BI } }, +{ "bclrl+", XLYLK(19,16,1,1), XLYBB_MASK, PPCCOM, { BOE, BI } }, +{ "bclr-", XLYLK(19,16,0,0), XLYBB_MASK, PPCCOM, { BOE, BI } }, +{ "bclrl-", XLYLK(19,16,0,1), XLYBB_MASK, PPCCOM, { BOE, BI } }, +{ "bclr", XLLK(19,16,0), XLBH_MASK, PPCCOM, { BO, BI, BH } }, +{ "bclrl", XLLK(19,16,1), XLBH_MASK, PPCCOM, { BO, BI, BH } }, +{ "bcr", XLLK(19,16,0), XLBB_MASK, PWRCOM, { BO, BI } }, +{ "bcrl", XLLK(19,16,1), XLBB_MASK, PWRCOM, { BO, BI } }, +{ "bclre", XLLK(19,17,0), XLBB_MASK, BOOKE64, { BO, BI } }, +{ "bclrel", XLLK(19,17,1), XLBB_MASK, BOOKE64, { BO, BI } }, + +{ "rfid", XL(19,18), 0xffffffff, PPC64, { 0 } }, + +{ "crnot", XL(19,33), XL_MASK, PPCCOM, { BT, BA, BBA } }, +{ "crnor", XL(19,33), XL_MASK, COM, { BT, BA, BB } }, +{ "rfmci", X(19,38), 0xffffffff, PPCRFMCI, { 0 } }, + +{ "rfi", XL(19,50), 0xffffffff, COM, { 0 } }, +{ "rfci", XL(19,51), 0xffffffff, PPC403 | BOOKE, { 0 } }, + +{ "rfsvc", XL(19,82), 0xffffffff, POWER, { 0 } }, + +{ "crandc", XL(19,129), XL_MASK, COM, { BT, BA, BB } }, + +{ "isync", XL(19,150), 0xffffffff, PPCCOM, { 0 } }, +{ "ics", XL(19,150), 0xffffffff, PWRCOM, { 0 } }, + +{ "crclr", XL(19,193), XL_MASK, PPCCOM, { BT, BAT, BBA } }, +{ "crxor", XL(19,193), XL_MASK, COM, { BT, BA, BB } }, + +{ "crnand", XL(19,225), XL_MASK, COM, { BT, BA, BB } }, + +{ "crand", XL(19,257), XL_MASK, COM, { BT, BA, BB } }, + +{ "hrfid", XL(19,274), 0xffffffff, POWER5 | CELL, { 0 } }, + +{ "crset", XL(19,289), XL_MASK, PPCCOM, { BT, BAT, BBA } }, +{ "creqv", XL(19,289), XL_MASK, COM, { BT, BA, BB } }, + +{ "doze", XL(19,402), 0xffffffff, POWER6, { 0 } }, + +{ "crorc", XL(19,417), XL_MASK, COM, { BT, BA, BB } }, + +{ "nap", XL(19,434), 0xffffffff, POWER6, { 0 } }, + +{ "crmove", XL(19,449), XL_MASK, PPCCOM, { BT, BA, BBA } }, +{ "cror", XL(19,449), XL_MASK, COM, { BT, BA, BB } }, + +{ "sleep", XL(19,466), 0xffffffff, POWER6, { 0 } }, +{ "rvwinkle", XL(19,498), 0xffffffff, POWER6, { 0 } }, + +{ "bctr", XLO(19,BOU,528,0), XLBOBIBB_MASK, COM, { 0 } }, +{ "bctrl", XLO(19,BOU,528,1), XLBOBIBB_MASK, COM, { 0 } }, +{ "bltctr", XLOCB(19,BOT,CBLT,528,0), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "bltctr-", XLOCB(19,BOT,CBLT,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "bltctr-", XLOCB(19,BOTM4,CBLT,528,0), XLBOCBBB_MASK, POWER4, { CR } }, +{ "bltctr+", XLOCB(19,BOTP,CBLT,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "bltctr+", XLOCB(19,BOTP4,CBLT,528,0), XLBOCBBB_MASK, POWER4, { CR } }, +{ "bltctrl", XLOCB(19,BOT,CBLT,528,1), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "bltctrl-",XLOCB(19,BOT,CBLT,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "bltctrl-",XLOCB(19,BOTM4,CBLT,528,1), XLBOCBBB_MASK, POWER4, { CR } }, +{ "bltctrl+",XLOCB(19,BOTP,CBLT,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "bltctrl+",XLOCB(19,BOTP4,CBLT,528,1), XLBOCBBB_MASK, POWER4, { CR } }, +{ "bgtctr", XLOCB(19,BOT,CBGT,528,0), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "bgtctr-", XLOCB(19,BOT,CBGT,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "bgtctr-", XLOCB(19,BOTM4,CBGT,528,0), XLBOCBBB_MASK, POWER4, { CR } }, +{ "bgtctr+", XLOCB(19,BOTP,CBGT,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "bgtctr+", XLOCB(19,BOTP4,CBGT,528,0), XLBOCBBB_MASK, POWER4, { CR } }, +{ "bgtctrl", XLOCB(19,BOT,CBGT,528,1), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "bgtctrl-",XLOCB(19,BOT,CBGT,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "bgtctrl-",XLOCB(19,BOTM4,CBGT,528,1), XLBOCBBB_MASK, POWER4, { CR } }, +{ "bgtctrl+",XLOCB(19,BOTP,CBGT,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "bgtctrl+",XLOCB(19,BOTP4,CBGT,528,1), XLBOCBBB_MASK, POWER4, { CR } }, +{ "beqctr", XLOCB(19,BOT,CBEQ,528,0), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "beqctr-", XLOCB(19,BOT,CBEQ,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "beqctr-", XLOCB(19,BOTM4,CBEQ,528,0), XLBOCBBB_MASK, POWER4, { CR } }, +{ "beqctr+", XLOCB(19,BOTP,CBEQ,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "beqctr+", XLOCB(19,BOTP4,CBEQ,528,0), XLBOCBBB_MASK, POWER4, { CR } }, +{ "beqctrl", XLOCB(19,BOT,CBEQ,528,1), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "beqctrl-",XLOCB(19,BOT,CBEQ,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "beqctrl-",XLOCB(19,BOTM4,CBEQ,528,1), XLBOCBBB_MASK, POWER4, { CR } }, +{ "beqctrl+",XLOCB(19,BOTP,CBEQ,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "beqctrl+",XLOCB(19,BOTP4,CBEQ,528,1), XLBOCBBB_MASK, POWER4, { CR } }, +{ "bsoctr", XLOCB(19,BOT,CBSO,528,0), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "bsoctr-", XLOCB(19,BOT,CBSO,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "bsoctr-", XLOCB(19,BOTM4,CBSO,528,0), XLBOCBBB_MASK, POWER4, { CR } }, +{ "bsoctr+", XLOCB(19,BOTP,CBSO,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "bsoctr+", XLOCB(19,BOTP4,CBSO,528,0), XLBOCBBB_MASK, POWER4, { CR } }, +{ "bsoctrl", XLOCB(19,BOT,CBSO,528,1), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "bsoctrl-",XLOCB(19,BOT,CBSO,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "bsoctrl-",XLOCB(19,BOTM4,CBSO,528,1), XLBOCBBB_MASK, POWER4, { CR } }, +{ "bsoctrl+",XLOCB(19,BOTP,CBSO,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "bsoctrl+",XLOCB(19,BOTP4,CBSO,528,1), XLBOCBBB_MASK, POWER4, { CR } }, +{ "bunctr", XLOCB(19,BOT,CBSO,528,0), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "bunctr-", XLOCB(19,BOT,CBSO,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "bunctr-", XLOCB(19,BOTM4,CBSO,528,0), XLBOCBBB_MASK, POWER4, { CR } }, +{ "bunctr+", XLOCB(19,BOTP,CBSO,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "bunctr+", XLOCB(19,BOTP4,CBSO,528,0), XLBOCBBB_MASK, POWER4, { CR } }, +{ "bunctrl", XLOCB(19,BOT,CBSO,528,1), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "bunctrl-",XLOCB(19,BOT,CBSO,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "bunctrl-",XLOCB(19,BOTM4,CBSO,528,1), XLBOCBBB_MASK, POWER4, { CR } }, +{ "bunctrl+",XLOCB(19,BOTP,CBSO,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "bunctrl+",XLOCB(19,BOTP4,CBSO,528,1), XLBOCBBB_MASK, POWER4, { CR } }, +{ "bgectr", XLOCB(19,BOF,CBLT,528,0), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "bgectr-", XLOCB(19,BOF,CBLT,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "bgectr-", XLOCB(19,BOFM4,CBLT,528,0), XLBOCBBB_MASK, POWER4, { CR } }, +{ "bgectr+", XLOCB(19,BOFP,CBLT,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "bgectr+", XLOCB(19,BOFP4,CBLT,528,0), XLBOCBBB_MASK, POWER4, { CR } }, +{ "bgectrl", XLOCB(19,BOF,CBLT,528,1), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "bgectrl-",XLOCB(19,BOF,CBLT,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "bgectrl-",XLOCB(19,BOFM4,CBLT,528,1), XLBOCBBB_MASK, POWER4, { CR } }, +{ "bgectrl+",XLOCB(19,BOFP,CBLT,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "bgectrl+",XLOCB(19,BOFP4,CBLT,528,1), XLBOCBBB_MASK, POWER4, { CR } }, +{ "bnlctr", XLOCB(19,BOF,CBLT,528,0), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "bnlctr-", XLOCB(19,BOF,CBLT,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "bnlctr-", XLOCB(19,BOFM4,CBLT,528,0), XLBOCBBB_MASK, POWER4, { CR } }, +{ "bnlctr+", XLOCB(19,BOFP,CBLT,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "bnlctr+", XLOCB(19,BOFP4,CBLT,528,0), XLBOCBBB_MASK, POWER4, { CR } }, +{ "bnlctrl", XLOCB(19,BOF,CBLT,528,1), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "bnlctrl-",XLOCB(19,BOF,CBLT,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "bnlctrl-",XLOCB(19,BOFM4,CBLT,528,1), XLBOCBBB_MASK, POWER4, { CR } }, +{ "bnlctrl+",XLOCB(19,BOFP,CBLT,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "bnlctrl+",XLOCB(19,BOFP4,CBLT,528,1), XLBOCBBB_MASK, POWER4, { CR } }, +{ "blectr", XLOCB(19,BOF,CBGT,528,0), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "blectr-", XLOCB(19,BOF,CBGT,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "blectr-", XLOCB(19,BOFM4,CBGT,528,0), XLBOCBBB_MASK, POWER4, { CR } }, +{ "blectr+", XLOCB(19,BOFP,CBGT,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "blectr+", XLOCB(19,BOFP4,CBGT,528,0), XLBOCBBB_MASK, POWER4, { CR } }, +{ "blectrl", XLOCB(19,BOF,CBGT,528,1), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "blectrl-",XLOCB(19,BOF,CBGT,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "blectrl-",XLOCB(19,BOFM4,CBGT,528,1), XLBOCBBB_MASK, POWER4, { CR } }, +{ "blectrl+",XLOCB(19,BOFP,CBGT,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "blectrl+",XLOCB(19,BOFP4,CBGT,528,1), XLBOCBBB_MASK, POWER4, { CR } }, +{ "bngctr", XLOCB(19,BOF,CBGT,528,0), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "bngctr-", XLOCB(19,BOF,CBGT,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "bngctr-", XLOCB(19,BOFM4,CBGT,528,0), XLBOCBBB_MASK, POWER4, { CR } }, +{ "bngctr+", XLOCB(19,BOFP,CBGT,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "bngctr+", XLOCB(19,BOFP4,CBGT,528,0), XLBOCBBB_MASK, POWER4, { CR } }, +{ "bngctrl", XLOCB(19,BOF,CBGT,528,1), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "bngctrl-",XLOCB(19,BOF,CBGT,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "bngctrl-",XLOCB(19,BOFM4,CBGT,528,1), XLBOCBBB_MASK, POWER4, { CR } }, +{ "bngctrl+",XLOCB(19,BOFP,CBGT,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "bngctrl+",XLOCB(19,BOFP4,CBGT,528,1), XLBOCBBB_MASK, POWER4, { CR } }, +{ "bnectr", XLOCB(19,BOF,CBEQ,528,0), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "bnectr-", XLOCB(19,BOF,CBEQ,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "bnectr-", XLOCB(19,BOFM4,CBEQ,528,0), XLBOCBBB_MASK, POWER4, { CR } }, +{ "bnectr+", XLOCB(19,BOFP,CBEQ,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "bnectr+", XLOCB(19,BOFP4,CBEQ,528,0), XLBOCBBB_MASK, POWER4, { CR } }, +{ "bnectrl", XLOCB(19,BOF,CBEQ,528,1), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "bnectrl-",XLOCB(19,BOF,CBEQ,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "bnectrl-",XLOCB(19,BOFM4,CBEQ,528,1), XLBOCBBB_MASK, POWER4, { CR } }, +{ "bnectrl+",XLOCB(19,BOFP,CBEQ,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "bnectrl+",XLOCB(19,BOFP4,CBEQ,528,1), XLBOCBBB_MASK, POWER4, { CR } }, +{ "bnsctr", XLOCB(19,BOF,CBSO,528,0), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "bnsctr-", XLOCB(19,BOF,CBSO,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "bnsctr-", XLOCB(19,BOFM4,CBSO,528,0), XLBOCBBB_MASK, POWER4, { CR } }, +{ "bnsctr+", XLOCB(19,BOFP,CBSO,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "bnsctr+", XLOCB(19,BOFP4,CBSO,528,0), XLBOCBBB_MASK, POWER4, { CR } }, +{ "bnsctrl", XLOCB(19,BOF,CBSO,528,1), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "bnsctrl-",XLOCB(19,BOF,CBSO,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "bnsctrl-",XLOCB(19,BOFM4,CBSO,528,1), XLBOCBBB_MASK, POWER4, { CR } }, +{ "bnsctrl+",XLOCB(19,BOFP,CBSO,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "bnsctrl+",XLOCB(19,BOFP4,CBSO,528,1), XLBOCBBB_MASK, POWER4, { CR } }, +{ "bnuctr", XLOCB(19,BOF,CBSO,528,0), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "bnuctr-", XLOCB(19,BOF,CBSO,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "bnuctr-", XLOCB(19,BOFM4,CBSO,528,0), XLBOCBBB_MASK, POWER4, { CR } }, +{ "bnuctr+", XLOCB(19,BOFP,CBSO,528,0), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "bnuctr+", XLOCB(19,BOFP4,CBSO,528,0), XLBOCBBB_MASK, POWER4, { CR } }, +{ "bnuctrl", XLOCB(19,BOF,CBSO,528,1), XLBOCBBB_MASK, PPCCOM, { CR } }, +{ "bnuctrl-",XLOCB(19,BOF,CBSO,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "bnuctrl-",XLOCB(19,BOFM4,CBSO,528,1), XLBOCBBB_MASK, POWER4, { CR } }, +{ "bnuctrl+",XLOCB(19,BOFP,CBSO,528,1), XLBOCBBB_MASK, NOPOWER4, { CR } }, +{ "bnuctrl+",XLOCB(19,BOFP4,CBSO,528,1), XLBOCBBB_MASK, POWER4, { CR } }, +{ "btctr", XLO(19,BOT,528,0), XLBOBB_MASK, PPCCOM, { BI } }, +{ "btctr-", XLO(19,BOT,528,0), XLBOBB_MASK, NOPOWER4, { BI } }, +{ "btctr-", XLO(19,BOTM4,528,0), XLBOBB_MASK, POWER4, { BI } }, +{ "btctr+", XLO(19,BOTP,528,0), XLBOBB_MASK, NOPOWER4, { BI } }, +{ "btctr+", XLO(19,BOTP4,528,0), XLBOBB_MASK, POWER4, { BI } }, +{ "btctrl", XLO(19,BOT,528,1), XLBOBB_MASK, PPCCOM, { BI } }, +{ "btctrl-", XLO(19,BOT,528,1), XLBOBB_MASK, NOPOWER4, { BI } }, +{ "btctrl-", XLO(19,BOTM4,528,1), XLBOBB_MASK, POWER4, { BI } }, +{ "btctrl+", XLO(19,BOTP,528,1), XLBOBB_MASK, NOPOWER4, { BI } }, +{ "btctrl+", XLO(19,BOTP4,528,1), XLBOBB_MASK, POWER4, { BI } }, +{ "bfctr", XLO(19,BOF,528,0), XLBOBB_MASK, PPCCOM, { BI } }, +{ "bfctr-", XLO(19,BOF,528,0), XLBOBB_MASK, NOPOWER4, { BI } }, +{ "bfctr-", XLO(19,BOFM4,528,0), XLBOBB_MASK, POWER4, { BI } }, +{ "bfctr+", XLO(19,BOFP,528,0), XLBOBB_MASK, NOPOWER4, { BI } }, +{ "bfctr+", XLO(19,BOFP4,528,0), XLBOBB_MASK, POWER4, { BI } }, +{ "bfctrl", XLO(19,BOF,528,1), XLBOBB_MASK, PPCCOM, { BI } }, +{ "bfctrl-", XLO(19,BOF,528,1), XLBOBB_MASK, NOPOWER4, { BI } }, +{ "bfctrl-", XLO(19,BOFM4,528,1), XLBOBB_MASK, POWER4, { BI } }, +{ "bfctrl+", XLO(19,BOFP,528,1), XLBOBB_MASK, NOPOWER4, { BI } }, +{ "bfctrl+", XLO(19,BOFP4,528,1), XLBOBB_MASK, POWER4, { BI } }, +{ "bcctr-", XLYLK(19,528,0,0), XLYBB_MASK, PPCCOM, { BOE, BI } }, +{ "bcctr+", XLYLK(19,528,1,0), XLYBB_MASK, PPCCOM, { BOE, BI } }, +{ "bcctrl-", XLYLK(19,528,0,1), XLYBB_MASK, PPCCOM, { BOE, BI } }, +{ "bcctrl+", XLYLK(19,528,1,1), XLYBB_MASK, PPCCOM, { BOE, BI } }, +{ "bcctr", XLLK(19,528,0), XLBH_MASK, PPCCOM, { BO, BI, BH } }, +{ "bcctrl", XLLK(19,528,1), XLBH_MASK, PPCCOM, { BO, BI, BH } }, +{ "bcc", XLLK(19,528,0), XLBB_MASK, PWRCOM, { BO, BI } }, +{ "bccl", XLLK(19,528,1), XLBB_MASK, PWRCOM, { BO, BI } }, +{ "bcctre", XLLK(19,529,0), XLBB_MASK, BOOKE64, { BO, BI } }, +{ "bcctrel", XLLK(19,529,1), XLBB_MASK, BOOKE64, { BO, BI } }, + +{ "rlwimi", M(20,0), M_MASK, PPCCOM, { RA,RS,SH,MBE,ME } }, +{ "rlimi", M(20,0), M_MASK, PWRCOM, { RA,RS,SH,MBE,ME } }, + +{ "rlwimi.", M(20,1), M_MASK, PPCCOM, { RA,RS,SH,MBE,ME } }, +{ "rlimi.", M(20,1), M_MASK, PWRCOM, { RA,RS,SH,MBE,ME } }, + +{ "rotlwi", MME(21,31,0), MMBME_MASK, PPCCOM, { RA, RS, SH } }, +{ "clrlwi", MME(21,31,0), MSHME_MASK, PPCCOM, { RA, RS, MB } }, +{ "rlwinm", M(21,0), M_MASK, PPCCOM, { RA,RS,SH,MBE,ME } }, +{ "rlinm", M(21,0), M_MASK, PWRCOM, { RA,RS,SH,MBE,ME } }, +{ "rotlwi.", MME(21,31,1), MMBME_MASK, PPCCOM, { RA,RS,SH } }, +{ "clrlwi.", MME(21,31,1), MSHME_MASK, PPCCOM, { RA, RS, MB } }, +{ "rlwinm.", M(21,1), M_MASK, PPCCOM, { RA,RS,SH,MBE,ME } }, +{ "rlinm.", M(21,1), M_MASK, PWRCOM, { RA,RS,SH,MBE,ME } }, + +{ "rlmi", M(22,0), M_MASK, M601, { RA,RS,RB,MBE,ME } }, +{ "rlmi.", M(22,1), M_MASK, M601, { RA,RS,RB,MBE,ME } }, + +{ "be", B(22,0,0), B_MASK, BOOKE64, { LI } }, +{ "bel", B(22,0,1), B_MASK, BOOKE64, { LI } }, +{ "bea", B(22,1,0), B_MASK, BOOKE64, { LIA } }, +{ "bela", B(22,1,1), B_MASK, BOOKE64, { LIA } }, + +{ "rotlw", MME(23,31,0), MMBME_MASK, PPCCOM, { RA, RS, RB } }, +{ "rlwnm", M(23,0), M_MASK, PPCCOM, { RA,RS,RB,MBE,ME } }, +{ "rlnm", M(23,0), M_MASK, PWRCOM, { RA,RS,RB,MBE,ME } }, +{ "rotlw.", MME(23,31,1), MMBME_MASK, PPCCOM, { RA, RS, RB } }, +{ "rlwnm.", M(23,1), M_MASK, PPCCOM, { RA,RS,RB,MBE,ME } }, +{ "rlnm.", M(23,1), M_MASK, PWRCOM, { RA,RS,RB,MBE,ME } }, + +{ "nop", OP(24), 0xffffffff, PPCCOM, { 0 } }, +{ "ori", OP(24), OP_MASK, PPCCOM, { RA, RS, UI } }, +{ "oril", OP(24), OP_MASK, PWRCOM, { RA, RS, UI } }, + +{ "oris", OP(25), OP_MASK, PPCCOM, { RA, RS, UI } }, +{ "oriu", OP(25), OP_MASK, PWRCOM, { RA, RS, UI } }, + +{ "xori", OP(26), OP_MASK, PPCCOM, { RA, RS, UI } }, +{ "xoril", OP(26), OP_MASK, PWRCOM, { RA, RS, UI } }, + +{ "xoris", OP(27), OP_MASK, PPCCOM, { RA, RS, UI } }, +{ "xoriu", OP(27), OP_MASK, PWRCOM, { RA, RS, UI } }, + +{ "andi.", OP(28), OP_MASK, PPCCOM, { RA, RS, UI } }, +{ "andil.", OP(28), OP_MASK, PWRCOM, { RA, RS, UI } }, + +{ "andis.", OP(29), OP_MASK, PPCCOM, { RA, RS, UI } }, +{ "andiu.", OP(29), OP_MASK, PWRCOM, { RA, RS, UI } }, + +{ "rotldi", MD(30,0,0), MDMB_MASK, PPC64, { RA, RS, SH6 } }, +{ "clrldi", MD(30,0,0), MDSH_MASK, PPC64, { RA, RS, MB6 } }, +{ "rldicl", MD(30,0,0), MD_MASK, PPC64, { RA, RS, SH6, MB6 } }, +{ "rotldi.", MD(30,0,1), MDMB_MASK, PPC64, { RA, RS, SH6 } }, +{ "clrldi.", MD(30,0,1), MDSH_MASK, PPC64, { RA, RS, MB6 } }, +{ "rldicl.", MD(30,0,1), MD_MASK, PPC64, { RA, RS, SH6, MB6 } }, + +{ "rldicr", MD(30,1,0), MD_MASK, PPC64, { RA, RS, SH6, ME6 } }, +{ "rldicr.", MD(30,1,1), MD_MASK, PPC64, { RA, RS, SH6, ME6 } }, + +{ "rldic", MD(30,2,0), MD_MASK, PPC64, { RA, RS, SH6, MB6 } }, +{ "rldic.", MD(30,2,1), MD_MASK, PPC64, { RA, RS, SH6, MB6 } }, + +{ "rldimi", MD(30,3,0), MD_MASK, PPC64, { RA, RS, SH6, MB6 } }, +{ "rldimi.", MD(30,3,1), MD_MASK, PPC64, { RA, RS, SH6, MB6 } }, + +{ "rotld", MDS(30,8,0), MDSMB_MASK, PPC64, { RA, RS, RB } }, +{ "rldcl", MDS(30,8,0), MDS_MASK, PPC64, { RA, RS, RB, MB6 } }, +{ "rotld.", MDS(30,8,1), MDSMB_MASK, PPC64, { RA, RS, RB } }, +{ "rldcl.", MDS(30,8,1), MDS_MASK, PPC64, { RA, RS, RB, MB6 } }, + +{ "rldcr", MDS(30,9,0), MDS_MASK, PPC64, { RA, RS, RB, ME6 } }, +{ "rldcr.", MDS(30,9,1), MDS_MASK, PPC64, { RA, RS, RB, ME6 } }, + +{ "cmpw", XOPL(31,0,0), XCMPL_MASK, PPCCOM, { OBF, RA, RB } }, +{ "cmpd", XOPL(31,0,1), XCMPL_MASK, PPC64, { OBF, RA, RB } }, +{ "cmp", X(31,0), XCMP_MASK, PPC, { BF, L, RA, RB } }, +{ "cmp", X(31,0), XCMPL_MASK, PWRCOM, { BF, RA, RB } }, + +{ "twlgt", XTO(31,4,TOLGT), XTO_MASK, PPCCOM, { RA, RB } }, +{ "tlgt", XTO(31,4,TOLGT), XTO_MASK, PWRCOM, { RA, RB } }, +{ "twllt", XTO(31,4,TOLLT), XTO_MASK, PPCCOM, { RA, RB } }, +{ "tllt", XTO(31,4,TOLLT), XTO_MASK, PWRCOM, { RA, RB } }, +{ "tweq", XTO(31,4,TOEQ), XTO_MASK, PPCCOM, { RA, RB } }, +{ "teq", XTO(31,4,TOEQ), XTO_MASK, PWRCOM, { RA, RB } }, +{ "twlge", XTO(31,4,TOLGE), XTO_MASK, PPCCOM, { RA, RB } }, +{ "tlge", XTO(31,4,TOLGE), XTO_MASK, PWRCOM, { RA, RB } }, +{ "twlnl", XTO(31,4,TOLNL), XTO_MASK, PPCCOM, { RA, RB } }, +{ "tlnl", XTO(31,4,TOLNL), XTO_MASK, PWRCOM, { RA, RB } }, +{ "twlle", XTO(31,4,TOLLE), XTO_MASK, PPCCOM, { RA, RB } }, +{ "tlle", XTO(31,4,TOLLE), XTO_MASK, PWRCOM, { RA, RB } }, +{ "twlng", XTO(31,4,TOLNG), XTO_MASK, PPCCOM, { RA, RB } }, +{ "tlng", XTO(31,4,TOLNG), XTO_MASK, PWRCOM, { RA, RB } }, +{ "twgt", XTO(31,4,TOGT), XTO_MASK, PPCCOM, { RA, RB } }, +{ "tgt", XTO(31,4,TOGT), XTO_MASK, PWRCOM, { RA, RB } }, +{ "twge", XTO(31,4,TOGE), XTO_MASK, PPCCOM, { RA, RB } }, +{ "tge", XTO(31,4,TOGE), XTO_MASK, PWRCOM, { RA, RB } }, +{ "twnl", XTO(31,4,TONL), XTO_MASK, PPCCOM, { RA, RB } }, +{ "tnl", XTO(31,4,TONL), XTO_MASK, PWRCOM, { RA, RB } }, +{ "twlt", XTO(31,4,TOLT), XTO_MASK, PPCCOM, { RA, RB } }, +{ "tlt", XTO(31,4,TOLT), XTO_MASK, PWRCOM, { RA, RB } }, +{ "twle", XTO(31,4,TOLE), XTO_MASK, PPCCOM, { RA, RB } }, +{ "tle", XTO(31,4,TOLE), XTO_MASK, PWRCOM, { RA, RB } }, +{ "twng", XTO(31,4,TONG), XTO_MASK, PPCCOM, { RA, RB } }, +{ "tng", XTO(31,4,TONG), XTO_MASK, PWRCOM, { RA, RB } }, +{ "twne", XTO(31,4,TONE), XTO_MASK, PPCCOM, { RA, RB } }, +{ "tne", XTO(31,4,TONE), XTO_MASK, PWRCOM, { RA, RB } }, +{ "trap", XTO(31,4,TOU), 0xffffffff, PPCCOM, { 0 } }, +{ "tw", X(31,4), X_MASK, PPCCOM, { TO, RA, RB } }, +{ "t", X(31,4), X_MASK, PWRCOM, { TO, RA, RB } }, + +{ "subfc", XO(31,8,0,0), XO_MASK, PPCCOM, { RT, RA, RB } }, +{ "sf", XO(31,8,0,0), XO_MASK, PWRCOM, { RT, RA, RB } }, +{ "subc", XO(31,8,0,0), XO_MASK, PPC, { RT, RB, RA } }, +{ "subfc.", XO(31,8,0,1), XO_MASK, PPCCOM, { RT, RA, RB } }, +{ "sf.", XO(31,8,0,1), XO_MASK, PWRCOM, { RT, RA, RB } }, +{ "subc.", XO(31,8,0,1), XO_MASK, PPCCOM, { RT, RB, RA } }, +{ "subfco", XO(31,8,1,0), XO_MASK, PPCCOM, { RT, RA, RB } }, +{ "sfo", XO(31,8,1,0), XO_MASK, PWRCOM, { RT, RA, RB } }, +{ "subco", XO(31,8,1,0), XO_MASK, PPC, { RT, RB, RA } }, +{ "subfco.", XO(31,8,1,1), XO_MASK, PPCCOM, { RT, RA, RB } }, +{ "sfo.", XO(31,8,1,1), XO_MASK, PWRCOM, { RT, RA, RB } }, +{ "subco.", XO(31,8,1,1), XO_MASK, PPC, { RT, RB, RA } }, + +{ "mulhdu", XO(31,9,0,0), XO_MASK, PPC64, { RT, RA, RB } }, +{ "mulhdu.", XO(31,9,0,1), XO_MASK, PPC64, { RT, RA, RB } }, + +{ "addc", XO(31,10,0,0), XO_MASK, PPCCOM, { RT, RA, RB } }, +{ "a", XO(31,10,0,0), XO_MASK, PWRCOM, { RT, RA, RB } }, +{ "addc.", XO(31,10,0,1), XO_MASK, PPCCOM, { RT, RA, RB } }, +{ "a.", XO(31,10,0,1), XO_MASK, PWRCOM, { RT, RA, RB } }, +{ "addco", XO(31,10,1,0), XO_MASK, PPCCOM, { RT, RA, RB } }, +{ "ao", XO(31,10,1,0), XO_MASK, PWRCOM, { RT, RA, RB } }, +{ "addco.", XO(31,10,1,1), XO_MASK, PPCCOM, { RT, RA, RB } }, +{ "ao.", XO(31,10,1,1), XO_MASK, PWRCOM, { RT, RA, RB } }, + +{ "mulhwu", XO(31,11,0,0), XO_MASK, PPC, { RT, RA, RB } }, +{ "mulhwu.", XO(31,11,0,1), XO_MASK, PPC, { RT, RA, RB } }, + +{ "isellt", X(31,15), X_MASK, PPCISEL, { RT, RA, RB } }, +{ "iselgt", X(31,47), X_MASK, PPCISEL, { RT, RA, RB } }, +{ "iseleq", X(31,79), X_MASK, PPCISEL, { RT, RA, RB } }, +{ "isel", XISEL(31,15), XISEL_MASK, PPCISEL, { RT, RA, RB, CRB } }, + +{ "mfocrf", XFXM(31,19,0,1), XFXFXM_MASK, COM, { RT, FXM } }, +{ "mfcr", X(31,19), XRARB_MASK, NOPOWER4 | COM, { RT } }, +{ "mfcr", X(31,19), XFXFXM_MASK, POWER4, { RT, FXM4 } }, + +{ "lwarx", X(31,20), XEH_MASK, PPC, { RT, RA0, RB, EH } }, + +{ "ldx", X(31,21), X_MASK, PPC64, { RT, RA0, RB } }, + +{ "icbt", X(31,22), X_MASK, BOOKE|PPCE300, { CT, RA, RB } }, +{ "icbt", X(31,262), XRT_MASK, PPC403, { RA, RB } }, + +{ "lwzx", X(31,23), X_MASK, PPCCOM, { RT, RA0, RB } }, +{ "lx", X(31,23), X_MASK, PWRCOM, { RT, RA, RB } }, + +{ "slw", XRC(31,24,0), X_MASK, PPCCOM, { RA, RS, RB } }, +{ "sl", XRC(31,24,0), X_MASK, PWRCOM, { RA, RS, RB } }, +{ "slw.", XRC(31,24,1), X_MASK, PPCCOM, { RA, RS, RB } }, +{ "sl.", XRC(31,24,1), X_MASK, PWRCOM, { RA, RS, RB } }, + +{ "cntlzw", XRC(31,26,0), XRB_MASK, PPCCOM, { RA, RS } }, +{ "cntlz", XRC(31,26,0), XRB_MASK, PWRCOM, { RA, RS } }, +{ "cntlzw.", XRC(31,26,1), XRB_MASK, PPCCOM, { RA, RS } }, +{ "cntlz.", XRC(31,26,1), XRB_MASK, PWRCOM, { RA, RS } }, + +{ "sld", XRC(31,27,0), X_MASK, PPC64, { RA, RS, RB } }, +{ "sld.", XRC(31,27,1), X_MASK, PPC64, { RA, RS, RB } }, + +{ "and", XRC(31,28,0), X_MASK, COM, { RA, RS, RB } }, +{ "and.", XRC(31,28,1), X_MASK, COM, { RA, RS, RB } }, + +{ "maskg", XRC(31,29,0), X_MASK, M601, { RA, RS, RB } }, +{ "maskg.", XRC(31,29,1), X_MASK, M601, { RA, RS, RB } }, + +{ "icbte", X(31,30), X_MASK, BOOKE64, { CT, RA, RB } }, + +{ "lwzxe", X(31,31), X_MASK, BOOKE64, { RT, RA0, RB } }, + +{ "cmplw", XOPL(31,32,0), XCMPL_MASK, PPCCOM, { OBF, RA, RB } }, +{ "cmpld", XOPL(31,32,1), XCMPL_MASK, PPC64, { OBF, RA, RB } }, +{ "cmpl", X(31,32), XCMP_MASK, PPC, { BF, L, RA, RB } }, +{ "cmpl", X(31,32), XCMPL_MASK, PWRCOM, { BF, RA, RB } }, + +{ "subf", XO(31,40,0,0), XO_MASK, PPC, { RT, RA, RB } }, +{ "sub", XO(31,40,0,0), XO_MASK, PPC, { RT, RB, RA } }, +{ "subf.", XO(31,40,0,1), XO_MASK, PPC, { RT, RA, RB } }, +{ "sub.", XO(31,40,0,1), XO_MASK, PPC, { RT, RB, RA } }, +{ "subfo", XO(31,40,1,0), XO_MASK, PPC, { RT, RA, RB } }, +{ "subo", XO(31,40,1,0), XO_MASK, PPC, { RT, RB, RA } }, +{ "subfo.", XO(31,40,1,1), XO_MASK, PPC, { RT, RA, RB } }, +{ "subo.", XO(31,40,1,1), XO_MASK, PPC, { RT, RB, RA } }, + +{ "ldux", X(31,53), X_MASK, PPC64, { RT, RAL, RB } }, + +{ "dcbst", X(31,54), XRT_MASK, PPC, { RA, RB } }, + +{ "lwzux", X(31,55), X_MASK, PPCCOM, { RT, RAL, RB } }, +{ "lux", X(31,55), X_MASK, PWRCOM, { RT, RA, RB } }, + +{ "dcbste", X(31,62), XRT_MASK, BOOKE64, { RA, RB } }, + +{ "lwzuxe", X(31,63), X_MASK, BOOKE64, { RT, RAL, RB } }, + +{ "cntlzd", XRC(31,58,0), XRB_MASK, PPC64, { RA, RS } }, +{ "cntlzd.", XRC(31,58,1), XRB_MASK, PPC64, { RA, RS } }, + +{ "andc", XRC(31,60,0), X_MASK, COM, { RA, RS, RB } }, +{ "andc.", XRC(31,60,1), X_MASK, COM, { RA, RS, RB } }, + +{ "tdlgt", XTO(31,68,TOLGT), XTO_MASK, PPC64, { RA, RB } }, +{ "tdllt", XTO(31,68,TOLLT), XTO_MASK, PPC64, { RA, RB } }, +{ "tdeq", XTO(31,68,TOEQ), XTO_MASK, PPC64, { RA, RB } }, +{ "tdlge", XTO(31,68,TOLGE), XTO_MASK, PPC64, { RA, RB } }, +{ "tdlnl", XTO(31,68,TOLNL), XTO_MASK, PPC64, { RA, RB } }, +{ "tdlle", XTO(31,68,TOLLE), XTO_MASK, PPC64, { RA, RB } }, +{ "tdlng", XTO(31,68,TOLNG), XTO_MASK, PPC64, { RA, RB } }, +{ "tdgt", XTO(31,68,TOGT), XTO_MASK, PPC64, { RA, RB } }, +{ "tdge", XTO(31,68,TOGE), XTO_MASK, PPC64, { RA, RB } }, +{ "tdnl", XTO(31,68,TONL), XTO_MASK, PPC64, { RA, RB } }, +{ "tdlt", XTO(31,68,TOLT), XTO_MASK, PPC64, { RA, RB } }, +{ "tdle", XTO(31,68,TOLE), XTO_MASK, PPC64, { RA, RB } }, +{ "tdng", XTO(31,68,TONG), XTO_MASK, PPC64, { RA, RB } }, +{ "tdne", XTO(31,68,TONE), XTO_MASK, PPC64, { RA, RB } }, +{ "td", X(31,68), X_MASK, PPC64, { TO, RA, RB } }, + +{ "mulhd", XO(31,73,0,0), XO_MASK, PPC64, { RT, RA, RB } }, +{ "mulhd.", XO(31,73,0,1), XO_MASK, PPC64, { RT, RA, RB } }, + +{ "mulhw", XO(31,75,0,0), XO_MASK, PPC, { RT, RA, RB } }, +{ "mulhw.", XO(31,75,0,1), XO_MASK, PPC, { RT, RA, RB } }, + +{ "dlmzb", XRC(31,78,0), X_MASK, PPC403|PPC440, { RA, RS, RB } }, +{ "dlmzb.", XRC(31,78,1), X_MASK, PPC403|PPC440, { RA, RS, RB } }, + +{ "mtsrd", X(31,82), XRB_MASK|(1<<20), PPC64, { SR, RS } }, + +{ "mfmsr", X(31,83), XRARB_MASK, COM, { RT } }, + +{ "ldarx", X(31,84), XEH_MASK, PPC64, { RT, RA0, RB, EH } }, + +{ "dcbfl", XOPL(31,86,1), XRT_MASK, POWER5, { RA, RB } }, +{ "dcbf", X(31,86), XLRT_MASK, PPC, { RA, RB, L } }, + +{ "lbzx", X(31,87), X_MASK, COM, { RT, RA0, RB } }, + +{ "dcbfe", X(31,94), XRT_MASK, BOOKE64, { RA, RB } }, + +{ "lbzxe", X(31,95), X_MASK, BOOKE64, { RT, RA0, RB } }, + +{ "neg", XO(31,104,0,0), XORB_MASK, COM, { RT, RA } }, +{ "neg.", XO(31,104,0,1), XORB_MASK, COM, { RT, RA } }, +{ "nego", XO(31,104,1,0), XORB_MASK, COM, { RT, RA } }, +{ "nego.", XO(31,104,1,1), XORB_MASK, COM, { RT, RA } }, + +{ "mul", XO(31,107,0,0), XO_MASK, M601, { RT, RA, RB } }, +{ "mul.", XO(31,107,0,1), XO_MASK, M601, { RT, RA, RB } }, +{ "mulo", XO(31,107,1,0), XO_MASK, M601, { RT, RA, RB } }, +{ "mulo.", XO(31,107,1,1), XO_MASK, M601, { RT, RA, RB } }, + +{ "mtsrdin", X(31,114), XRA_MASK, PPC64, { RS, RB } }, + +{ "clf", X(31,118), XTO_MASK, POWER, { RA, RB } }, + +{ "lbzux", X(31,119), X_MASK, COM, { RT, RAL, RB } }, + +{ "popcntb", X(31,122), XRB_MASK, POWER5, { RA, RS } }, + +{ "not", XRC(31,124,0), X_MASK, COM, { RA, RS, RBS } }, +{ "nor", XRC(31,124,0), X_MASK, COM, { RA, RS, RB } }, +{ "not.", XRC(31,124,1), X_MASK, COM, { RA, RS, RBS } }, +{ "nor.", XRC(31,124,1), X_MASK, COM, { RA, RS, RB } }, + +{ "lwarxe", X(31,126), X_MASK, BOOKE64, { RT, RA0, RB } }, + +{ "lbzuxe", X(31,127), X_MASK, BOOKE64, { RT, RAL, RB } }, + +{ "wrtee", X(31,131), XRARB_MASK, PPC403 | BOOKE, { RS } }, + +{ "dcbtstls",X(31,134), X_MASK, PPCCHLK, { CT, RA, RB }}, + +{ "subfe", XO(31,136,0,0), XO_MASK, PPCCOM, { RT, RA, RB } }, +{ "sfe", XO(31,136,0,0), XO_MASK, PWRCOM, { RT, RA, RB } }, +{ "subfe.", XO(31,136,0,1), XO_MASK, PPCCOM, { RT, RA, RB } }, +{ "sfe.", XO(31,136,0,1), XO_MASK, PWRCOM, { RT, RA, RB } }, +{ "subfeo", XO(31,136,1,0), XO_MASK, PPCCOM, { RT, RA, RB } }, +{ "sfeo", XO(31,136,1,0), XO_MASK, PWRCOM, { RT, RA, RB } }, +{ "subfeo.", XO(31,136,1,1), XO_MASK, PPCCOM, { RT, RA, RB } }, +{ "sfeo.", XO(31,136,1,1), XO_MASK, PWRCOM, { RT, RA, RB } }, + +{ "adde", XO(31,138,0,0), XO_MASK, PPCCOM, { RT, RA, RB } }, +{ "ae", XO(31,138,0,0), XO_MASK, PWRCOM, { RT, RA, RB } }, +{ "adde.", XO(31,138,0,1), XO_MASK, PPCCOM, { RT, RA, RB } }, +{ "ae.", XO(31,138,0,1), XO_MASK, PWRCOM, { RT, RA, RB } }, +{ "addeo", XO(31,138,1,0), XO_MASK, PPCCOM, { RT, RA, RB } }, +{ "aeo", XO(31,138,1,0), XO_MASK, PWRCOM, { RT, RA, RB } }, +{ "addeo.", XO(31,138,1,1), XO_MASK, PPCCOM, { RT, RA, RB } }, +{ "aeo.", XO(31,138,1,1), XO_MASK, PWRCOM, { RT, RA, RB } }, + +{ "dcbtstlse",X(31,142),X_MASK, PPCCHLK64, { CT, RA, RB }}, + +{ "mtocrf", XFXM(31,144,0,1), XFXFXM_MASK, COM, { FXM, RS } }, +{ "mtcr", XFXM(31,144,0xff,0), XRARB_MASK, COM, { RS }}, +{ "mtcrf", X(31,144), XFXFXM_MASK, COM, { FXM, RS } }, + +{ "mtmsr", X(31,146), XRARB_MASK, COM, { RS } }, + +{ "stdx", X(31,149), X_MASK, PPC64, { RS, RA0, RB } }, + +{ "stwcx.", XRC(31,150,1), X_MASK, PPC, { RS, RA0, RB } }, + +{ "stwx", X(31,151), X_MASK, PPCCOM, { RS, RA0, RB } }, +{ "stx", X(31,151), X_MASK, PWRCOM, { RS, RA, RB } }, + +{ "stwcxe.", XRC(31,158,1), X_MASK, BOOKE64, { RS, RA0, RB } }, + +{ "stwxe", X(31,159), X_MASK, BOOKE64, { RS, RA0, RB } }, + +{ "slq", XRC(31,152,0), X_MASK, M601, { RA, RS, RB } }, +{ "slq.", XRC(31,152,1), X_MASK, M601, { RA, RS, RB } }, + +{ "sle", XRC(31,153,0), X_MASK, M601, { RA, RS, RB } }, +{ "sle.", XRC(31,153,1), X_MASK, M601, { RA, RS, RB } }, + +{ "prtyw", X(31,154), XRB_MASK, POWER6, { RA, RS } }, + +{ "wrteei", X(31,163), XE_MASK, PPC403 | BOOKE, { E } }, + +{ "dcbtls", X(31,166), X_MASK, PPCCHLK, { CT, RA, RB }}, +{ "dcbtlse", X(31,174), X_MASK, PPCCHLK64, { CT, RA, RB }}, + +{ "mtmsrd", X(31,178), XRLARB_MASK, PPC64, { RS, A_L } }, + +{ "stdux", X(31,181), X_MASK, PPC64, { RS, RAS, RB } }, + +{ "stwux", X(31,183), X_MASK, PPCCOM, { RS, RAS, RB } }, +{ "stux", X(31,183), X_MASK, PWRCOM, { RS, RA0, RB } }, + +{ "sliq", XRC(31,184,0), X_MASK, M601, { RA, RS, SH } }, +{ "sliq.", XRC(31,184,1), X_MASK, M601, { RA, RS, SH } }, + +{ "prtyd", X(31,186), XRB_MASK, POWER6, { RA, RS } }, + +{ "stwuxe", X(31,191), X_MASK, BOOKE64, { RS, RAS, RB } }, + +{ "subfze", XO(31,200,0,0), XORB_MASK, PPCCOM, { RT, RA } }, +{ "sfze", XO(31,200,0,0), XORB_MASK, PWRCOM, { RT, RA } }, +{ "subfze.", XO(31,200,0,1), XORB_MASK, PPCCOM, { RT, RA } }, +{ "sfze.", XO(31,200,0,1), XORB_MASK, PWRCOM, { RT, RA } }, +{ "subfzeo", XO(31,200,1,0), XORB_MASK, PPCCOM, { RT, RA } }, +{ "sfzeo", XO(31,200,1,0), XORB_MASK, PWRCOM, { RT, RA } }, +{ "subfzeo.",XO(31,200,1,1), XORB_MASK, PPCCOM, { RT, RA } }, +{ "sfzeo.", XO(31,200,1,1), XORB_MASK, PWRCOM, { RT, RA } }, + +{ "addze", XO(31,202,0,0), XORB_MASK, PPCCOM, { RT, RA } }, +{ "aze", XO(31,202,0,0), XORB_MASK, PWRCOM, { RT, RA } }, +{ "addze.", XO(31,202,0,1), XORB_MASK, PPCCOM, { RT, RA } }, +{ "aze.", XO(31,202,0,1), XORB_MASK, PWRCOM, { RT, RA } }, +{ "addzeo", XO(31,202,1,0), XORB_MASK, PPCCOM, { RT, RA } }, +{ "azeo", XO(31,202,1,0), XORB_MASK, PWRCOM, { RT, RA } }, +{ "addzeo.", XO(31,202,1,1), XORB_MASK, PPCCOM, { RT, RA } }, +{ "azeo.", XO(31,202,1,1), XORB_MASK, PWRCOM, { RT, RA } }, + +{ "mtsr", X(31,210), XRB_MASK|(1<<20), COM32, { SR, RS } }, + +{ "stdcx.", XRC(31,214,1), X_MASK, PPC64, { RS, RA0, RB } }, + +{ "stbx", X(31,215), X_MASK, COM, { RS, RA0, RB } }, + +{ "sllq", XRC(31,216,0), X_MASK, M601, { RA, RS, RB } }, +{ "sllq.", XRC(31,216,1), X_MASK, M601, { RA, RS, RB } }, + +{ "sleq", XRC(31,217,0), X_MASK, M601, { RA, RS, RB } }, +{ "sleq.", XRC(31,217,1), X_MASK, M601, { RA, RS, RB } }, + +{ "stbxe", X(31,223), X_MASK, BOOKE64, { RS, RA0, RB } }, + +{ "icblc", X(31,230), X_MASK, PPCCHLK, { CT, RA, RB }}, + +{ "subfme", XO(31,232,0,0), XORB_MASK, PPCCOM, { RT, RA } }, +{ "sfme", XO(31,232,0,0), XORB_MASK, PWRCOM, { RT, RA } }, +{ "subfme.", XO(31,232,0,1), XORB_MASK, PPCCOM, { RT, RA } }, +{ "sfme.", XO(31,232,0,1), XORB_MASK, PWRCOM, { RT, RA } }, +{ "subfmeo", XO(31,232,1,0), XORB_MASK, PPCCOM, { RT, RA } }, +{ "sfmeo", XO(31,232,1,0), XORB_MASK, PWRCOM, { RT, RA } }, +{ "subfmeo.",XO(31,232,1,1), XORB_MASK, PPCCOM, { RT, RA } }, +{ "sfmeo.", XO(31,232,1,1), XORB_MASK, PWRCOM, { RT, RA } }, + +{ "mulld", XO(31,233,0,0), XO_MASK, PPC64, { RT, RA, RB } }, +{ "mulld.", XO(31,233,0,1), XO_MASK, PPC64, { RT, RA, RB } }, +{ "mulldo", XO(31,233,1,0), XO_MASK, PPC64, { RT, RA, RB } }, +{ "mulldo.", XO(31,233,1,1), XO_MASK, PPC64, { RT, RA, RB } }, + +{ "addme", XO(31,234,0,0), XORB_MASK, PPCCOM, { RT, RA } }, +{ "ame", XO(31,234,0,0), XORB_MASK, PWRCOM, { RT, RA } }, +{ "addme.", XO(31,234,0,1), XORB_MASK, PPCCOM, { RT, RA } }, +{ "ame.", XO(31,234,0,1), XORB_MASK, PWRCOM, { RT, RA } }, +{ "addmeo", XO(31,234,1,0), XORB_MASK, PPCCOM, { RT, RA } }, +{ "ameo", XO(31,234,1,0), XORB_MASK, PWRCOM, { RT, RA } }, +{ "addmeo.", XO(31,234,1,1), XORB_MASK, PPCCOM, { RT, RA } }, +{ "ameo.", XO(31,234,1,1), XORB_MASK, PWRCOM, { RT, RA } }, + +{ "mullw", XO(31,235,0,0), XO_MASK, PPCCOM, { RT, RA, RB } }, +{ "muls", XO(31,235,0,0), XO_MASK, PWRCOM, { RT, RA, RB } }, +{ "mullw.", XO(31,235,0,1), XO_MASK, PPCCOM, { RT, RA, RB } }, +{ "muls.", XO(31,235,0,1), XO_MASK, PWRCOM, { RT, RA, RB } }, +{ "mullwo", XO(31,235,1,0), XO_MASK, PPCCOM, { RT, RA, RB } }, +{ "mulso", XO(31,235,1,0), XO_MASK, PWRCOM, { RT, RA, RB } }, +{ "mullwo.", XO(31,235,1,1), XO_MASK, PPCCOM, { RT, RA, RB } }, +{ "mulso.", XO(31,235,1,1), XO_MASK, PWRCOM, { RT, RA, RB } }, + +{ "icblce", X(31,238), X_MASK, PPCCHLK64, { CT, RA, RB }}, +{ "mtsrin", X(31,242), XRA_MASK, PPC32, { RS, RB } }, +{ "mtsri", X(31,242), XRA_MASK, POWER32, { RS, RB } }, + +{ "dcbtst", X(31,246), X_MASK, PPC, { CT, RA, RB } }, + +{ "stbux", X(31,247), X_MASK, COM, { RS, RAS, RB } }, + +{ "slliq", XRC(31,248,0), X_MASK, M601, { RA, RS, SH } }, +{ "slliq.", XRC(31,248,1), X_MASK, M601, { RA, RS, SH } }, + +{ "dcbtste", X(31,253), X_MASK, BOOKE64, { CT, RA, RB } }, + +{ "stbuxe", X(31,255), X_MASK, BOOKE64, { RS, RAS, RB } }, + +{ "mfdcrx", X(31,259), X_MASK, BOOKE, { RS, RA } }, + +{ "doz", XO(31,264,0,0), XO_MASK, M601, { RT, RA, RB } }, +{ "doz.", XO(31,264,0,1), XO_MASK, M601, { RT, RA, RB } }, +{ "dozo", XO(31,264,1,0), XO_MASK, M601, { RT, RA, RB } }, +{ "dozo.", XO(31,264,1,1), XO_MASK, M601, { RT, RA, RB } }, + +{ "add", XO(31,266,0,0), XO_MASK, PPCCOM, { RT, RA, RB } }, +{ "cax", XO(31,266,0,0), XO_MASK, PWRCOM, { RT, RA, RB } }, +{ "add.", XO(31,266,0,1), XO_MASK, PPCCOM, { RT, RA, RB } }, +{ "cax.", XO(31,266,0,1), XO_MASK, PWRCOM, { RT, RA, RB } }, +{ "addo", XO(31,266,1,0), XO_MASK, PPCCOM, { RT, RA, RB } }, +{ "caxo", XO(31,266,1,0), XO_MASK, PWRCOM, { RT, RA, RB } }, +{ "addo.", XO(31,266,1,1), XO_MASK, PPCCOM, { RT, RA, RB } }, +{ "caxo.", XO(31,266,1,1), XO_MASK, PWRCOM, { RT, RA, RB } }, + +{ "tlbiel", X(31,274), XRTLRA_MASK, POWER4, { RB, L } }, + +{ "mfapidi", X(31,275), X_MASK, BOOKE, { RT, RA } }, + +{ "lscbx", XRC(31,277,0), X_MASK, M601, { RT, RA, RB } }, +{ "lscbx.", XRC(31,277,1), X_MASK, M601, { RT, RA, RB } }, + +{ "dcbt", X(31,278), X_MASK, PPC, { CT, RA, RB } }, + +{ "lhzx", X(31,279), X_MASK, COM, { RT, RA0, RB } }, + +{ "eqv", XRC(31,284,0), X_MASK, COM, { RA, RS, RB } }, +{ "eqv.", XRC(31,284,1), X_MASK, COM, { RA, RS, RB } }, + +{ "dcbte", X(31,286), X_MASK, BOOKE64, { CT, RA, RB } }, + +{ "lhzxe", X(31,287), X_MASK, BOOKE64, { RT, RA0, RB } }, + +{ "tlbie", X(31,306), XRTLRA_MASK, PPC, { RB, L } }, +{ "tlbi", X(31,306), XRT_MASK, POWER, { RA0, RB } }, + +{ "eciwx", X(31,310), X_MASK, PPC, { RT, RA, RB } }, + +{ "lhzux", X(31,311), X_MASK, COM, { RT, RAL, RB } }, + +{ "xor", XRC(31,316,0), X_MASK, COM, { RA, RS, RB } }, +{ "xor.", XRC(31,316,1), X_MASK, COM, { RA, RS, RB } }, + +{ "lhzuxe", X(31,319), X_MASK, BOOKE64, { RT, RAL, RB } }, + +{ "mfexisr", XSPR(31,323,64), XSPR_MASK, PPC403, { RT } }, +{ "mfexier", XSPR(31,323,66), XSPR_MASK, PPC403, { RT } }, +{ "mfbr0", XSPR(31,323,128), XSPR_MASK, PPC403, { RT } }, +{ "mfbr1", XSPR(31,323,129), XSPR_MASK, PPC403, { RT } }, +{ "mfbr2", XSPR(31,323,130), XSPR_MASK, PPC403, { RT } }, +{ "mfbr3", XSPR(31,323,131), XSPR_MASK, PPC403, { RT } }, +{ "mfbr4", XSPR(31,323,132), XSPR_MASK, PPC403, { RT } }, +{ "mfbr5", XSPR(31,323,133), XSPR_MASK, PPC403, { RT } }, +{ "mfbr6", XSPR(31,323,134), XSPR_MASK, PPC403, { RT } }, +{ "mfbr7", XSPR(31,323,135), XSPR_MASK, PPC403, { RT } }, +{ "mfbear", XSPR(31,323,144), XSPR_MASK, PPC403, { RT } }, +{ "mfbesr", XSPR(31,323,145), XSPR_MASK, PPC403, { RT } }, +{ "mfiocr", XSPR(31,323,160), XSPR_MASK, PPC403, { RT } }, +{ "mfdmacr0", XSPR(31,323,192), XSPR_MASK, PPC403, { RT } }, +{ "mfdmact0", XSPR(31,323,193), XSPR_MASK, PPC403, { RT } }, +{ "mfdmada0", XSPR(31,323,194), XSPR_MASK, PPC403, { RT } }, +{ "mfdmasa0", XSPR(31,323,195), XSPR_MASK, PPC403, { RT } }, +{ "mfdmacc0", XSPR(31,323,196), XSPR_MASK, PPC403, { RT } }, +{ "mfdmacr1", XSPR(31,323,200), XSPR_MASK, PPC403, { RT } }, +{ "mfdmact1", XSPR(31,323,201), XSPR_MASK, PPC403, { RT } }, +{ "mfdmada1", XSPR(31,323,202), XSPR_MASK, PPC403, { RT } }, +{ "mfdmasa1", XSPR(31,323,203), XSPR_MASK, PPC403, { RT } }, +{ "mfdmacc1", XSPR(31,323,204), XSPR_MASK, PPC403, { RT } }, +{ "mfdmacr2", XSPR(31,323,208), XSPR_MASK, PPC403, { RT } }, +{ "mfdmact2", XSPR(31,323,209), XSPR_MASK, PPC403, { RT } }, +{ "mfdmada2", XSPR(31,323,210), XSPR_MASK, PPC403, { RT } }, +{ "mfdmasa2", XSPR(31,323,211), XSPR_MASK, PPC403, { RT } }, +{ "mfdmacc2", XSPR(31,323,212), XSPR_MASK, PPC403, { RT } }, +{ "mfdmacr3", XSPR(31,323,216), XSPR_MASK, PPC403, { RT } }, +{ "mfdmact3", XSPR(31,323,217), XSPR_MASK, PPC403, { RT } }, +{ "mfdmada3", XSPR(31,323,218), XSPR_MASK, PPC403, { RT } }, +{ "mfdmasa3", XSPR(31,323,219), XSPR_MASK, PPC403, { RT } }, +{ "mfdmacc3", XSPR(31,323,220), XSPR_MASK, PPC403, { RT } }, +{ "mfdmasr", XSPR(31,323,224), XSPR_MASK, PPC403, { RT } }, +{ "mfdcr", X(31,323), X_MASK, PPC403 | BOOKE, { RT, SPR } }, + +{ "div", XO(31,331,0,0), XO_MASK, M601, { RT, RA, RB } }, +{ "div.", XO(31,331,0,1), XO_MASK, M601, { RT, RA, RB } }, +{ "divo", XO(31,331,1,0), XO_MASK, M601, { RT, RA, RB } }, +{ "divo.", XO(31,331,1,1), XO_MASK, M601, { RT, RA, RB } }, + +{ "mfpmr", X(31,334), X_MASK, PPCPMR, { RT, PMR }}, + +{ "mfmq", XSPR(31,339,0), XSPR_MASK, M601, { RT } }, +{ "mfxer", XSPR(31,339,1), XSPR_MASK, COM, { RT } }, +{ "mfrtcu", XSPR(31,339,4), XSPR_MASK, COM, { RT } }, +{ "mfrtcl", XSPR(31,339,5), XSPR_MASK, COM, { RT } }, +{ "mfdec", XSPR(31,339,6), XSPR_MASK, MFDEC1, { RT } }, +{ "mfdec", XSPR(31,339,22), XSPR_MASK, MFDEC2, { RT } }, +{ "mflr", XSPR(31,339,8), XSPR_MASK, COM, { RT } }, +{ "mfctr", XSPR(31,339,9), XSPR_MASK, COM, { RT } }, +{ "mftid", XSPR(31,339,17), XSPR_MASK, POWER, { RT } }, +{ "mfdsisr", XSPR(31,339,18), XSPR_MASK, COM, { RT } }, +{ "mfdar", XSPR(31,339,19), XSPR_MASK, COM, { RT } }, +{ "mfsdr0", XSPR(31,339,24), XSPR_MASK, POWER, { RT } }, +{ "mfsdr1", XSPR(31,339,25), XSPR_MASK, COM, { RT } }, +{ "mfsrr0", XSPR(31,339,26), XSPR_MASK, COM, { RT } }, +{ "mfsrr1", XSPR(31,339,27), XSPR_MASK, COM, { RT } }, +{ "mfcfar", XSPR(31,339,28), XSPR_MASK, POWER6, { RT } }, +{ "mfpid", XSPR(31,339,48), XSPR_MASK, BOOKE, { RT } }, +{ "mfpid", XSPR(31,339,945), XSPR_MASK, PPC403, { RT } }, +{ "mfcsrr0", XSPR(31,339,58), XSPR_MASK, BOOKE, { RT } }, +{ "mfcsrr1", XSPR(31,339,59), XSPR_MASK, BOOKE, { RT } }, +{ "mfdear", XSPR(31,339,61), XSPR_MASK, BOOKE, { RT } }, +{ "mfdear", XSPR(31,339,981), XSPR_MASK, PPC403, { RT } }, +{ "mfesr", XSPR(31,339,62), XSPR_MASK, BOOKE, { RT } }, +{ "mfesr", XSPR(31,339,980), XSPR_MASK, PPC403, { RT } }, +{ "mfivpr", XSPR(31,339,63), XSPR_MASK, BOOKE, { RT } }, +{ "mfcmpa", XSPR(31,339,144), XSPR_MASK, PPC860, { RT } }, +{ "mfcmpb", XSPR(31,339,145), XSPR_MASK, PPC860, { RT } }, +{ "mfcmpc", XSPR(31,339,146), XSPR_MASK, PPC860, { RT } }, +{ "mfcmpd", XSPR(31,339,147), XSPR_MASK, PPC860, { RT } }, +{ "mficr", XSPR(31,339,148), XSPR_MASK, PPC860, { RT } }, +{ "mfder", XSPR(31,339,149), XSPR_MASK, PPC860, { RT } }, +{ "mfcounta", XSPR(31,339,150), XSPR_MASK, PPC860, { RT } }, +{ "mfcountb", XSPR(31,339,151), XSPR_MASK, PPC860, { RT } }, +{ "mfcmpe", XSPR(31,339,152), XSPR_MASK, PPC860, { RT } }, +{ "mfcmpf", XSPR(31,339,153), XSPR_MASK, PPC860, { RT } }, +{ "mfcmpg", XSPR(31,339,154), XSPR_MASK, PPC860, { RT } }, +{ "mfcmph", XSPR(31,339,155), XSPR_MASK, PPC860, { RT } }, +{ "mflctrl1", XSPR(31,339,156), XSPR_MASK, PPC860, { RT } }, +{ "mflctrl2", XSPR(31,339,157), XSPR_MASK, PPC860, { RT } }, +{ "mfictrl", XSPR(31,339,158), XSPR_MASK, PPC860, { RT } }, +{ "mfbar", XSPR(31,339,159), XSPR_MASK, PPC860, { RT } }, +{ "mfvrsave", XSPR(31,339,256), XSPR_MASK, PPCVEC, { RT } }, +{ "mfusprg0", XSPR(31,339,256), XSPR_MASK, BOOKE, { RT } }, +{ "mftb", X(31,371), X_MASK, CLASSIC, { RT, TBR } }, +{ "mftb", XSPR(31,339,268), XSPR_MASK, BOOKE, { RT } }, +{ "mftbl", XSPR(31,371,268), XSPR_MASK, CLASSIC, { RT } }, +{ "mftbl", XSPR(31,339,268), XSPR_MASK, BOOKE, { RT } }, +{ "mftbu", XSPR(31,371,269), XSPR_MASK, CLASSIC, { RT } }, +{ "mftbu", XSPR(31,339,269), XSPR_MASK, BOOKE, { RT } }, +{ "mfsprg", XSPR(31,339,256), XSPRG_MASK, PPC, { RT, SPRG } }, +{ "mfsprg0", XSPR(31,339,272), XSPR_MASK, PPC, { RT } }, +{ "mfsprg1", XSPR(31,339,273), XSPR_MASK, PPC, { RT } }, +{ "mfsprg2", XSPR(31,339,274), XSPR_MASK, PPC, { RT } }, +{ "mfsprg3", XSPR(31,339,275), XSPR_MASK, PPC, { RT } }, +{ "mfsprg4", XSPR(31,339,260), XSPR_MASK, PPC405 | BOOKE, { RT } }, +{ "mfsprg5", XSPR(31,339,261), XSPR_MASK, PPC405 | BOOKE, { RT } }, +{ "mfsprg6", XSPR(31,339,262), XSPR_MASK, PPC405 | BOOKE, { RT } }, +{ "mfsprg7", XSPR(31,339,263), XSPR_MASK, PPC405 | BOOKE, { RT } }, +{ "mfasr", XSPR(31,339,280), XSPR_MASK, PPC64, { RT } }, +{ "mfear", XSPR(31,339,282), XSPR_MASK, PPC, { RT } }, +{ "mfpir", XSPR(31,339,286), XSPR_MASK, BOOKE, { RT } }, +{ "mfpvr", XSPR(31,339,287), XSPR_MASK, PPC, { RT } }, +{ "mfdbsr", XSPR(31,339,304), XSPR_MASK, BOOKE, { RT } }, +{ "mfdbsr", XSPR(31,339,1008), XSPR_MASK, PPC403, { RT } }, +{ "mfdbcr0", XSPR(31,339,308), XSPR_MASK, BOOKE, { RT } }, +{ "mfdbcr0", XSPR(31,339,1010), XSPR_MASK, PPC405, { RT } }, +{ "mfdbcr1", XSPR(31,339,309), XSPR_MASK, BOOKE, { RT } }, +{ "mfdbcr1", XSPR(31,339,957), XSPR_MASK, PPC405, { RT } }, +{ "mfdbcr2", XSPR(31,339,310), XSPR_MASK, BOOKE, { RT } }, +{ "mfiac1", XSPR(31,339,312), XSPR_MASK, BOOKE, { RT } }, +{ "mfiac1", XSPR(31,339,1012), XSPR_MASK, PPC403, { RT } }, +{ "mfiac2", XSPR(31,339,313), XSPR_MASK, BOOKE, { RT } }, +{ "mfiac2", XSPR(31,339,1013), XSPR_MASK, PPC403, { RT } }, +{ "mfiac3", XSPR(31,339,314), XSPR_MASK, BOOKE, { RT } }, +{ "mfiac3", XSPR(31,339,948), XSPR_MASK, PPC405, { RT } }, +{ "mfiac4", XSPR(31,339,315), XSPR_MASK, BOOKE, { RT } }, +{ "mfiac4", XSPR(31,339,949), XSPR_MASK, PPC405, { RT } }, +{ "mfdac1", XSPR(31,339,316), XSPR_MASK, BOOKE, { RT } }, +{ "mfdac1", XSPR(31,339,1014), XSPR_MASK, PPC403, { RT } }, +{ "mfdac2", XSPR(31,339,317), XSPR_MASK, BOOKE, { RT } }, +{ "mfdac2", XSPR(31,339,1015), XSPR_MASK, PPC403, { RT } }, +{ "mfdvc1", XSPR(31,339,318), XSPR_MASK, BOOKE, { RT } }, +{ "mfdvc1", XSPR(31,339,950), XSPR_MASK, PPC405, { RT } }, +{ "mfdvc2", XSPR(31,339,319), XSPR_MASK, BOOKE, { RT } }, +{ "mfdvc2", XSPR(31,339,951), XSPR_MASK, PPC405, { RT } }, +{ "mftsr", XSPR(31,339,336), XSPR_MASK, BOOKE, { RT } }, +{ "mftsr", XSPR(31,339,984), XSPR_MASK, PPC403, { RT } }, +{ "mftcr", XSPR(31,339,340), XSPR_MASK, BOOKE, { RT } }, +{ "mftcr", XSPR(31,339,986), XSPR_MASK, PPC403, { RT } }, +{ "mfivor0", XSPR(31,339,400), XSPR_MASK, BOOKE, { RT } }, +{ "mfivor1", XSPR(31,339,401), XSPR_MASK, BOOKE, { RT } }, +{ "mfivor2", XSPR(31,339,402), XSPR_MASK, BOOKE, { RT } }, +{ "mfivor3", XSPR(31,339,403), XSPR_MASK, BOOKE, { RT } }, +{ "mfivor4", XSPR(31,339,404), XSPR_MASK, BOOKE, { RT } }, +{ "mfivor5", XSPR(31,339,405), XSPR_MASK, BOOKE, { RT } }, +{ "mfivor6", XSPR(31,339,406), XSPR_MASK, BOOKE, { RT } }, +{ "mfivor7", XSPR(31,339,407), XSPR_MASK, BOOKE, { RT } }, +{ "mfivor8", XSPR(31,339,408), XSPR_MASK, BOOKE, { RT } }, +{ "mfivor9", XSPR(31,339,409), XSPR_MASK, BOOKE, { RT } }, +{ "mfivor10", XSPR(31,339,410), XSPR_MASK, BOOKE, { RT } }, +{ "mfivor11", XSPR(31,339,411), XSPR_MASK, BOOKE, { RT } }, +{ "mfivor12", XSPR(31,339,412), XSPR_MASK, BOOKE, { RT } }, +{ "mfivor13", XSPR(31,339,413), XSPR_MASK, BOOKE, { RT } }, +{ "mfivor14", XSPR(31,339,414), XSPR_MASK, BOOKE, { RT } }, +{ "mfivor15", XSPR(31,339,415), XSPR_MASK, BOOKE, { RT } }, +{ "mfspefscr", XSPR(31,339,512), XSPR_MASK, PPCSPE, { RT } }, +{ "mfbbear", XSPR(31,339,513), XSPR_MASK, PPCBRLK, { RT } }, +{ "mfbbtar", XSPR(31,339,514), XSPR_MASK, PPCBRLK, { RT } }, +{ "mfivor32", XSPR(31,339,528), XSPR_MASK, PPCSPE, { RT } }, +{ "mfivor33", XSPR(31,339,529), XSPR_MASK, PPCSPE, { RT } }, +{ "mfivor34", XSPR(31,339,530), XSPR_MASK, PPCSPE, { RT } }, +{ "mfivor35", XSPR(31,339,531), XSPR_MASK, PPCPMR, { RT } }, +{ "mfibatu", XSPR(31,339,528), XSPRBAT_MASK, PPC, { RT, SPRBAT } }, +{ "mfibatl", XSPR(31,339,529), XSPRBAT_MASK, PPC, { RT, SPRBAT } }, +{ "mfdbatu", XSPR(31,339,536), XSPRBAT_MASK, PPC, { RT, SPRBAT } }, +{ "mfdbatl", XSPR(31,339,537), XSPRBAT_MASK, PPC, { RT, SPRBAT } }, +{ "mfic_cst", XSPR(31,339,560), XSPR_MASK, PPC860, { RT } }, +{ "mfic_adr", XSPR(31,339,561), XSPR_MASK, PPC860, { RT } }, +{ "mfic_dat", XSPR(31,339,562), XSPR_MASK, PPC860, { RT } }, +{ "mfdc_cst", XSPR(31,339,568), XSPR_MASK, PPC860, { RT } }, +{ "mfdc_adr", XSPR(31,339,569), XSPR_MASK, PPC860, { RT } }, +{ "mfmcsrr0", XSPR(31,339,570), XSPR_MASK, PPCRFMCI, { RT } }, +{ "mfdc_dat", XSPR(31,339,570), XSPR_MASK, PPC860, { RT } }, +{ "mfmcsrr1", XSPR(31,339,571), XSPR_MASK, PPCRFMCI, { RT } }, +{ "mfmcsr", XSPR(31,339,572), XSPR_MASK, PPCRFMCI, { RT } }, +{ "mfmcar", XSPR(31,339,573), XSPR_MASK, PPCRFMCI, { RT } }, +{ "mfdpdr", XSPR(31,339,630), XSPR_MASK, PPC860, { RT } }, +{ "mfdpir", XSPR(31,339,631), XSPR_MASK, PPC860, { RT } }, +{ "mfimmr", XSPR(31,339,638), XSPR_MASK, PPC860, { RT } }, +{ "mfmi_ctr", XSPR(31,339,784), XSPR_MASK, PPC860, { RT } }, +{ "mfmi_ap", XSPR(31,339,786), XSPR_MASK, PPC860, { RT } }, +{ "mfmi_epn", XSPR(31,339,787), XSPR_MASK, PPC860, { RT } }, +{ "mfmi_twc", XSPR(31,339,789), XSPR_MASK, PPC860, { RT } }, +{ "mfmi_rpn", XSPR(31,339,790), XSPR_MASK, PPC860, { RT } }, +{ "mfmd_ctr", XSPR(31,339,792), XSPR_MASK, PPC860, { RT } }, +{ "mfm_casid", XSPR(31,339,793), XSPR_MASK, PPC860, { RT } }, +{ "mfmd_ap", XSPR(31,339,794), XSPR_MASK, PPC860, { RT } }, +{ "mfmd_epn", XSPR(31,339,795), XSPR_MASK, PPC860, { RT } }, +{ "mfmd_twb", XSPR(31,339,796), XSPR_MASK, PPC860, { RT } }, +{ "mfmd_twc", XSPR(31,339,797), XSPR_MASK, PPC860, { RT } }, +{ "mfmd_rpn", XSPR(31,339,798), XSPR_MASK, PPC860, { RT } }, +{ "mfm_tw", XSPR(31,339,799), XSPR_MASK, PPC860, { RT } }, +{ "mfmi_dbcam", XSPR(31,339,816), XSPR_MASK, PPC860, { RT } }, +{ "mfmi_dbram0",XSPR(31,339,817), XSPR_MASK, PPC860, { RT } }, +{ "mfmi_dbram1",XSPR(31,339,818), XSPR_MASK, PPC860, { RT } }, +{ "mfmd_dbcam", XSPR(31,339,824), XSPR_MASK, PPC860, { RT } }, +{ "mfmd_dbram0",XSPR(31,339,825), XSPR_MASK, PPC860, { RT } }, +{ "mfmd_dbram1",XSPR(31,339,826), XSPR_MASK, PPC860, { RT } }, +{ "mfummcr0", XSPR(31,339,936), XSPR_MASK, PPC750, { RT } }, +{ "mfupmc1", XSPR(31,339,937), XSPR_MASK, PPC750, { RT } }, +{ "mfupmc2", XSPR(31,339,938), XSPR_MASK, PPC750, { RT } }, +{ "mfusia", XSPR(31,339,939), XSPR_MASK, PPC750, { RT } }, +{ "mfummcr1", XSPR(31,339,940), XSPR_MASK, PPC750, { RT } }, +{ "mfupmc3", XSPR(31,339,941), XSPR_MASK, PPC750, { RT } }, +{ "mfupmc4", XSPR(31,339,942), XSPR_MASK, PPC750, { RT } }, +{ "mfzpr", XSPR(31,339,944), XSPR_MASK, PPC403, { RT } }, +{ "mfccr0", XSPR(31,339,947), XSPR_MASK, PPC405, { RT } }, +{ "mfmmcr0", XSPR(31,339,952), XSPR_MASK, PPC750, { RT } }, +{ "mfpmc1", XSPR(31,339,953), XSPR_MASK, PPC750, { RT } }, +{ "mfsgr", XSPR(31,339,953), XSPR_MASK, PPC403, { RT } }, +{ "mfpmc2", XSPR(31,339,954), XSPR_MASK, PPC750, { RT } }, +{ "mfdcwr", XSPR(31,339,954), XSPR_MASK, PPC403, { RT } }, +{ "mfsia", XSPR(31,339,955), XSPR_MASK, PPC750, { RT } }, +{ "mfsler", XSPR(31,339,955), XSPR_MASK, PPC405, { RT } }, +{ "mfmmcr1", XSPR(31,339,956), XSPR_MASK, PPC750, { RT } }, +{ "mfsu0r", XSPR(31,339,956), XSPR_MASK, PPC405, { RT } }, +{ "mfpmc3", XSPR(31,339,957), XSPR_MASK, PPC750, { RT } }, +{ "mfpmc4", XSPR(31,339,958), XSPR_MASK, PPC750, { RT } }, +{ "mficdbdr", XSPR(31,339,979), XSPR_MASK, PPC403, { RT } }, +{ "mfevpr", XSPR(31,339,982), XSPR_MASK, PPC403, { RT } }, +{ "mfcdbcr", XSPR(31,339,983), XSPR_MASK, PPC403, { RT } }, +{ "mfpit", XSPR(31,339,987), XSPR_MASK, PPC403, { RT } }, +{ "mftbhi", XSPR(31,339,988), XSPR_MASK, PPC403, { RT } }, +{ "mftblo", XSPR(31,339,989), XSPR_MASK, PPC403, { RT } }, +{ "mfsrr2", XSPR(31,339,990), XSPR_MASK, PPC403, { RT } }, +{ "mfsrr3", XSPR(31,339,991), XSPR_MASK, PPC403, { RT } }, +{ "mfl2cr", XSPR(31,339,1017), XSPR_MASK, PPC750, { RT } }, +{ "mfdccr", XSPR(31,339,1018), XSPR_MASK, PPC403, { RT } }, +{ "mficcr", XSPR(31,339,1019), XSPR_MASK, PPC403, { RT } }, +{ "mfictc", XSPR(31,339,1019), XSPR_MASK, PPC750, { RT } }, +{ "mfpbl1", XSPR(31,339,1020), XSPR_MASK, PPC403, { RT } }, +{ "mfthrm1", XSPR(31,339,1020), XSPR_MASK, PPC750, { RT } }, +{ "mfpbu1", XSPR(31,339,1021), XSPR_MASK, PPC403, { RT } }, +{ "mfthrm2", XSPR(31,339,1021), XSPR_MASK, PPC750, { RT } }, +{ "mfpbl2", XSPR(31,339,1022), XSPR_MASK, PPC403, { RT } }, +{ "mfthrm3", XSPR(31,339,1022), XSPR_MASK, PPC750, { RT } }, +{ "mfpbu2", XSPR(31,339,1023), XSPR_MASK, PPC403, { RT } }, +{ "mfspr", X(31,339), X_MASK, COM, { RT, SPR } }, + +{ "lwax", X(31,341), X_MASK, PPC64, { RT, RA0, RB } }, + +{ "dst", XDSS(31,342,0), XDSS_MASK, PPCVEC, { RA, RB, STRM } }, +{ "dstt", XDSS(31,342,1), XDSS_MASK, PPCVEC, { RA, RB, STRM } }, + +{ "lhax", X(31,343), X_MASK, COM, { RT, RA0, RB } }, + +{ "lhaxe", X(31,351), X_MASK, BOOKE64, { RT, RA0, RB } }, + +{ "dstst", XDSS(31,374,0), XDSS_MASK, PPCVEC, { RA, RB, STRM } }, +{ "dststt", XDSS(31,374,1), XDSS_MASK, PPCVEC, { RA, RB, STRM } }, + +{ "dccci", X(31,454), XRT_MASK, PPC403|PPC440, { RA, RB } }, + +{ "abs", XO(31,360,0,0), XORB_MASK, M601, { RT, RA } }, +{ "abs.", XO(31,360,0,1), XORB_MASK, M601, { RT, RA } }, +{ "abso", XO(31,360,1,0), XORB_MASK, M601, { RT, RA } }, +{ "abso.", XO(31,360,1,1), XORB_MASK, M601, { RT, RA } }, + +{ "divs", XO(31,363,0,0), XO_MASK, M601, { RT, RA, RB } }, +{ "divs.", XO(31,363,0,1), XO_MASK, M601, { RT, RA, RB } }, +{ "divso", XO(31,363,1,0), XO_MASK, M601, { RT, RA, RB } }, +{ "divso.", XO(31,363,1,1), XO_MASK, M601, { RT, RA, RB } }, + +{ "tlbia", X(31,370), 0xffffffff, PPC, { 0 } }, + +{ "lwaux", X(31,373), X_MASK, PPC64, { RT, RAL, RB } }, + +{ "lhaux", X(31,375), X_MASK, COM, { RT, RAL, RB } }, + +{ "lhauxe", X(31,383), X_MASK, BOOKE64, { RT, RAL, RB } }, + +{ "mtdcrx", X(31,387), X_MASK, BOOKE, { RA, RS } }, + +{ "dcblc", X(31,390), X_MASK, PPCCHLK, { CT, RA, RB }}, + +{ "subfe64", XO(31,392,0,0), XO_MASK, BOOKE64, { RT, RA, RB } }, +{ "subfe64o",XO(31,392,1,0), XO_MASK, BOOKE64, { RT, RA, RB } }, + +{ "adde64", XO(31,394,0,0), XO_MASK, BOOKE64, { RT, RA, RB } }, +{ "adde64o", XO(31,394,1,0), XO_MASK, BOOKE64, { RT, RA, RB } }, + +{ "dcblce", X(31,398), X_MASK, PPCCHLK64, { CT, RA, RB }}, + +{ "slbmte", X(31,402), XRA_MASK, PPC64, { RS, RB } }, + +{ "sthx", X(31,407), X_MASK, COM, { RS, RA0, RB } }, + +{ "cmpb", X(31,508), X_MASK, POWER6, { RA, RS, RB } }, + +{ "lfqx", X(31,791), X_MASK, POWER2, { FRT, RA, RB } }, + +{ "lfdpx", X(31,791), X_MASK, POWER6, { FRT, RA, RB } }, + +{ "lfqux", X(31,823), X_MASK, POWER2, { FRT, RA, RB } }, + +{ "stfqx", X(31,919), X_MASK, POWER2, { FRS, RA, RB } }, + +{ "stfdpx", X(31,919), X_MASK, POWER6, { FRS, RA, RB } }, + +{ "stfqux", X(31,951), X_MASK, POWER2, { FRS, RA, RB } }, + +{ "orc", XRC(31,412,0), X_MASK, COM, { RA, RS, RB } }, +{ "orc.", XRC(31,412,1), X_MASK, COM, { RA, RS, RB } }, + +{ "sradi", XS(31,413,0), XS_MASK, PPC64, { RA, RS, SH6 } }, +{ "sradi.", XS(31,413,1), XS_MASK, PPC64, { RA, RS, SH6 } }, + +{ "sthxe", X(31,415), X_MASK, BOOKE64, { RS, RA0, RB } }, + +{ "slbie", X(31,434), XRTRA_MASK, PPC64, { RB } }, + +{ "ecowx", X(31,438), X_MASK, PPC, { RT, RA, RB } }, + +{ "sthux", X(31,439), X_MASK, COM, { RS, RAS, RB } }, + +{ "sthuxe", X(31,447), X_MASK, BOOKE64, { RS, RAS, RB } }, + +{ "cctpl", 0x7c210b78, 0xffffffff, CELL, { 0 }}, +{ "cctpm", 0x7c421378, 0xffffffff, CELL, { 0 }}, +{ "cctph", 0x7c631b78, 0xffffffff, CELL, { 0 }}, +{ "db8cyc", 0x7f9ce378, 0xffffffff, CELL, { 0 }}, +{ "db10cyc", 0x7fbdeb78, 0xffffffff, CELL, { 0 }}, +{ "db12cyc", 0x7fdef378, 0xffffffff, CELL, { 0 }}, +{ "db16cyc", 0x7ffffb78, 0xffffffff, CELL, { 0 }}, +{ "mr", XRC(31,444,0), X_MASK, COM, { RA, RS, RBS } }, +{ "or", XRC(31,444,0), X_MASK, COM, { RA, RS, RB } }, +{ "mr.", XRC(31,444,1), X_MASK, COM, { RA, RS, RBS } }, +{ "or.", XRC(31,444,1), X_MASK, COM, { RA, RS, RB } }, + +{ "mtexisr", XSPR(31,451,64), XSPR_MASK, PPC403, { RS } }, +{ "mtexier", XSPR(31,451,66), XSPR_MASK, PPC403, { RS } }, +{ "mtbr0", XSPR(31,451,128), XSPR_MASK, PPC403, { RS } }, +{ "mtbr1", XSPR(31,451,129), XSPR_MASK, PPC403, { RS } }, +{ "mtbr2", XSPR(31,451,130), XSPR_MASK, PPC403, { RS } }, +{ "mtbr3", XSPR(31,451,131), XSPR_MASK, PPC403, { RS } }, +{ "mtbr4", XSPR(31,451,132), XSPR_MASK, PPC403, { RS } }, +{ "mtbr5", XSPR(31,451,133), XSPR_MASK, PPC403, { RS } }, +{ "mtbr6", XSPR(31,451,134), XSPR_MASK, PPC403, { RS } }, +{ "mtbr7", XSPR(31,451,135), XSPR_MASK, PPC403, { RS } }, +{ "mtbear", XSPR(31,451,144), XSPR_MASK, PPC403, { RS } }, +{ "mtbesr", XSPR(31,451,145), XSPR_MASK, PPC403, { RS } }, +{ "mtiocr", XSPR(31,451,160), XSPR_MASK, PPC403, { RS } }, +{ "mtdmacr0", XSPR(31,451,192), XSPR_MASK, PPC403, { RS } }, +{ "mtdmact0", XSPR(31,451,193), XSPR_MASK, PPC403, { RS } }, +{ "mtdmada0", XSPR(31,451,194), XSPR_MASK, PPC403, { RS } }, +{ "mtdmasa0", XSPR(31,451,195), XSPR_MASK, PPC403, { RS } }, +{ "mtdmacc0", XSPR(31,451,196), XSPR_MASK, PPC403, { RS } }, +{ "mtdmacr1", XSPR(31,451,200), XSPR_MASK, PPC403, { RS } }, +{ "mtdmact1", XSPR(31,451,201), XSPR_MASK, PPC403, { RS } }, +{ "mtdmada1", XSPR(31,451,202), XSPR_MASK, PPC403, { RS } }, +{ "mtdmasa1", XSPR(31,451,203), XSPR_MASK, PPC403, { RS } }, +{ "mtdmacc1", XSPR(31,451,204), XSPR_MASK, PPC403, { RS } }, +{ "mtdmacr2", XSPR(31,451,208), XSPR_MASK, PPC403, { RS } }, +{ "mtdmact2", XSPR(31,451,209), XSPR_MASK, PPC403, { RS } }, +{ "mtdmada2", XSPR(31,451,210), XSPR_MASK, PPC403, { RS } }, +{ "mtdmasa2", XSPR(31,451,211), XSPR_MASK, PPC403, { RS } }, +{ "mtdmacc2", XSPR(31,451,212), XSPR_MASK, PPC403, { RS } }, +{ "mtdmacr3", XSPR(31,451,216), XSPR_MASK, PPC403, { RS } }, +{ "mtdmact3", XSPR(31,451,217), XSPR_MASK, PPC403, { RS } }, +{ "mtdmada3", XSPR(31,451,218), XSPR_MASK, PPC403, { RS } }, +{ "mtdmasa3", XSPR(31,451,219), XSPR_MASK, PPC403, { RS } }, +{ "mtdmacc3", XSPR(31,451,220), XSPR_MASK, PPC403, { RS } }, +{ "mtdmasr", XSPR(31,451,224), XSPR_MASK, PPC403, { RS } }, +{ "mtdcr", X(31,451), X_MASK, PPC403 | BOOKE, { SPR, RS } }, + +{ "subfze64",XO(31,456,0,0), XORB_MASK, BOOKE64, { RT, RA } }, +{ "subfze64o",XO(31,456,1,0), XORB_MASK, BOOKE64, { RT, RA } }, + +{ "divdu", XO(31,457,0,0), XO_MASK, PPC64, { RT, RA, RB } }, +{ "divdu.", XO(31,457,0,1), XO_MASK, PPC64, { RT, RA, RB } }, +{ "divduo", XO(31,457,1,0), XO_MASK, PPC64, { RT, RA, RB } }, +{ "divduo.", XO(31,457,1,1), XO_MASK, PPC64, { RT, RA, RB } }, + +{ "addze64", XO(31,458,0,0), XORB_MASK, BOOKE64, { RT, RA } }, +{ "addze64o",XO(31,458,1,0), XORB_MASK, BOOKE64, { RT, RA } }, + +{ "divwu", XO(31,459,0,0), XO_MASK, PPC, { RT, RA, RB } }, +{ "divwu.", XO(31,459,0,1), XO_MASK, PPC, { RT, RA, RB } }, +{ "divwuo", XO(31,459,1,0), XO_MASK, PPC, { RT, RA, RB } }, +{ "divwuo.", XO(31,459,1,1), XO_MASK, PPC, { RT, RA, RB } }, + +{ "mtmq", XSPR(31,467,0), XSPR_MASK, M601, { RS } }, +{ "mtxer", XSPR(31,467,1), XSPR_MASK, COM, { RS } }, +{ "mtlr", XSPR(31,467,8), XSPR_MASK, COM, { RS } }, +{ "mtctr", XSPR(31,467,9), XSPR_MASK, COM, { RS } }, +{ "mttid", XSPR(31,467,17), XSPR_MASK, POWER, { RS } }, +{ "mtdsisr", XSPR(31,467,18), XSPR_MASK, COM, { RS } }, +{ "mtdar", XSPR(31,467,19), XSPR_MASK, COM, { RS } }, +{ "mtrtcu", XSPR(31,467,20), XSPR_MASK, COM, { RS } }, +{ "mtrtcl", XSPR(31,467,21), XSPR_MASK, COM, { RS } }, +{ "mtdec", XSPR(31,467,22), XSPR_MASK, COM, { RS } }, +{ "mtsdr0", XSPR(31,467,24), XSPR_MASK, POWER, { RS } }, +{ "mtsdr1", XSPR(31,467,25), XSPR_MASK, COM, { RS } }, +{ "mtsrr0", XSPR(31,467,26), XSPR_MASK, COM, { RS } }, +{ "mtsrr1", XSPR(31,467,27), XSPR_MASK, COM, { RS } }, +{ "mtcfar", XSPR(31,467,28), XSPR_MASK, POWER6, { RS } }, +{ "mtpid", XSPR(31,467,48), XSPR_MASK, BOOKE, { RS } }, +{ "mtpid", XSPR(31,467,945), XSPR_MASK, PPC403, { RS } }, +{ "mtdecar", XSPR(31,467,54), XSPR_MASK, BOOKE, { RS } }, +{ "mtcsrr0", XSPR(31,467,58), XSPR_MASK, BOOKE, { RS } }, +{ "mtcsrr1", XSPR(31,467,59), XSPR_MASK, BOOKE, { RS } }, +{ "mtdear", XSPR(31,467,61), XSPR_MASK, BOOKE, { RS } }, +{ "mtdear", XSPR(31,467,981), XSPR_MASK, PPC403, { RS } }, +{ "mtesr", XSPR(31,467,62), XSPR_MASK, BOOKE, { RS } }, +{ "mtesr", XSPR(31,467,980), XSPR_MASK, PPC403, { RS } }, +{ "mtivpr", XSPR(31,467,63), XSPR_MASK, BOOKE, { RS } }, +{ "mtcmpa", XSPR(31,467,144), XSPR_MASK, PPC860, { RS } }, +{ "mtcmpb", XSPR(31,467,145), XSPR_MASK, PPC860, { RS } }, +{ "mtcmpc", XSPR(31,467,146), XSPR_MASK, PPC860, { RS } }, +{ "mtcmpd", XSPR(31,467,147), XSPR_MASK, PPC860, { RS } }, +{ "mticr", XSPR(31,467,148), XSPR_MASK, PPC860, { RS } }, +{ "mtder", XSPR(31,467,149), XSPR_MASK, PPC860, { RS } }, +{ "mtcounta", XSPR(31,467,150), XSPR_MASK, PPC860, { RS } }, +{ "mtcountb", XSPR(31,467,151), XSPR_MASK, PPC860, { RS } }, +{ "mtcmpe", XSPR(31,467,152), XSPR_MASK, PPC860, { RS } }, +{ "mtcmpf", XSPR(31,467,153), XSPR_MASK, PPC860, { RS } }, +{ "mtcmpg", XSPR(31,467,154), XSPR_MASK, PPC860, { RS } }, +{ "mtcmph", XSPR(31,467,155), XSPR_MASK, PPC860, { RS } }, +{ "mtlctrl1", XSPR(31,467,156), XSPR_MASK, PPC860, { RS } }, +{ "mtlctrl2", XSPR(31,467,157), XSPR_MASK, PPC860, { RS } }, +{ "mtictrl", XSPR(31,467,158), XSPR_MASK, PPC860, { RS } }, +{ "mtbar", XSPR(31,467,159), XSPR_MASK, PPC860, { RS } }, +{ "mtvrsave", XSPR(31,467,256), XSPR_MASK, PPCVEC, { RS } }, +{ "mtusprg0", XSPR(31,467,256), XSPR_MASK, BOOKE, { RS } }, +{ "mtsprg", XSPR(31,467,256), XSPRG_MASK,PPC, { SPRG, RS } }, +{ "mtsprg0", XSPR(31,467,272), XSPR_MASK, PPC, { RS } }, +{ "mtsprg1", XSPR(31,467,273), XSPR_MASK, PPC, { RS } }, +{ "mtsprg2", XSPR(31,467,274), XSPR_MASK, PPC, { RS } }, +{ "mtsprg3", XSPR(31,467,275), XSPR_MASK, PPC, { RS } }, +{ "mtsprg4", XSPR(31,467,276), XSPR_MASK, PPC405 | BOOKE, { RS } }, +{ "mtsprg5", XSPR(31,467,277), XSPR_MASK, PPC405 | BOOKE, { RS } }, +{ "mtsprg6", XSPR(31,467,278), XSPR_MASK, PPC405 | BOOKE, { RS } }, +{ "mtsprg7", XSPR(31,467,279), XSPR_MASK, PPC405 | BOOKE, { RS } }, +{ "mtasr", XSPR(31,467,280), XSPR_MASK, PPC64, { RS } }, +{ "mtear", XSPR(31,467,282), XSPR_MASK, PPC, { RS } }, +{ "mttbl", XSPR(31,467,284), XSPR_MASK, PPC, { RS } }, +{ "mttbu", XSPR(31,467,285), XSPR_MASK, PPC, { RS } }, +{ "mtdbsr", XSPR(31,467,304), XSPR_MASK, BOOKE, { RS } }, +{ "mtdbsr", XSPR(31,467,1008), XSPR_MASK, PPC403, { RS } }, +{ "mtdbcr0", XSPR(31,467,308), XSPR_MASK, BOOKE, { RS } }, +{ "mtdbcr0", XSPR(31,467,1010), XSPR_MASK, PPC405, { RS } }, +{ "mtdbcr1", XSPR(31,467,309), XSPR_MASK, BOOKE, { RS } }, +{ "mtdbcr1", XSPR(31,467,957), XSPR_MASK, PPC405, { RS } }, +{ "mtdbcr2", XSPR(31,467,310), XSPR_MASK, BOOKE, { RS } }, +{ "mtiac1", XSPR(31,467,312), XSPR_MASK, BOOKE, { RS } }, +{ "mtiac1", XSPR(31,467,1012), XSPR_MASK, PPC403, { RS } }, +{ "mtiac2", XSPR(31,467,313), XSPR_MASK, BOOKE, { RS } }, +{ "mtiac2", XSPR(31,467,1013), XSPR_MASK, PPC403, { RS } }, +{ "mtiac3", XSPR(31,467,314), XSPR_MASK, BOOKE, { RS } }, +{ "mtiac3", XSPR(31,467,948), XSPR_MASK, PPC405, { RS } }, +{ "mtiac4", XSPR(31,467,315), XSPR_MASK, BOOKE, { RS } }, +{ "mtiac4", XSPR(31,467,949), XSPR_MASK, PPC405, { RS } }, +{ "mtdac1", XSPR(31,467,316), XSPR_MASK, BOOKE, { RS } }, +{ "mtdac1", XSPR(31,467,1014), XSPR_MASK, PPC403, { RS } }, +{ "mtdac2", XSPR(31,467,317), XSPR_MASK, BOOKE, { RS } }, +{ "mtdac2", XSPR(31,467,1015), XSPR_MASK, PPC403, { RS } }, +{ "mtdvc1", XSPR(31,467,318), XSPR_MASK, BOOKE, { RS } }, +{ "mtdvc1", XSPR(31,467,950), XSPR_MASK, PPC405, { RS } }, +{ "mtdvc2", XSPR(31,467,319), XSPR_MASK, BOOKE, { RS } }, +{ "mtdvc2", XSPR(31,467,951), XSPR_MASK, PPC405, { RS } }, +{ "mttsr", XSPR(31,467,336), XSPR_MASK, BOOKE, { RS } }, +{ "mttsr", XSPR(31,467,984), XSPR_MASK, PPC403, { RS } }, +{ "mttcr", XSPR(31,467,340), XSPR_MASK, BOOKE, { RS } }, +{ "mttcr", XSPR(31,467,986), XSPR_MASK, PPC403, { RS } }, +{ "mtivor0", XSPR(31,467,400), XSPR_MASK, BOOKE, { RS } }, +{ "mtivor1", XSPR(31,467,401), XSPR_MASK, BOOKE, { RS } }, +{ "mtivor2", XSPR(31,467,402), XSPR_MASK, BOOKE, { RS } }, +{ "mtivor3", XSPR(31,467,403), XSPR_MASK, BOOKE, { RS } }, +{ "mtivor4", XSPR(31,467,404), XSPR_MASK, BOOKE, { RS } }, +{ "mtivor5", XSPR(31,467,405), XSPR_MASK, BOOKE, { RS } }, +{ "mtivor6", XSPR(31,467,406), XSPR_MASK, BOOKE, { RS } }, +{ "mtivor7", XSPR(31,467,407), XSPR_MASK, BOOKE, { RS } }, +{ "mtivor8", XSPR(31,467,408), XSPR_MASK, BOOKE, { RS } }, +{ "mtivor9", XSPR(31,467,409), XSPR_MASK, BOOKE, { RS } }, +{ "mtivor10", XSPR(31,467,410), XSPR_MASK, BOOKE, { RS } }, +{ "mtivor11", XSPR(31,467,411), XSPR_MASK, BOOKE, { RS } }, +{ "mtivor12", XSPR(31,467,412), XSPR_MASK, BOOKE, { RS } }, +{ "mtivor13", XSPR(31,467,413), XSPR_MASK, BOOKE, { RS } }, +{ "mtivor14", XSPR(31,467,414), XSPR_MASK, BOOKE, { RS } }, +{ "mtivor15", XSPR(31,467,415), XSPR_MASK, BOOKE, { RS } }, +{ "mtspefscr", XSPR(31,467,512), XSPR_MASK, PPCSPE, { RS } }, +{ "mtbbear", XSPR(31,467,513), XSPR_MASK, PPCBRLK, { RS } }, +{ "mtbbtar", XSPR(31,467,514), XSPR_MASK, PPCBRLK, { RS } }, +{ "mtivor32", XSPR(31,467,528), XSPR_MASK, PPCSPE, { RS } }, +{ "mtivor33", XSPR(31,467,529), XSPR_MASK, PPCSPE, { RS } }, +{ "mtivor34", XSPR(31,467,530), XSPR_MASK, PPCSPE, { RS } }, +{ "mtivor35", XSPR(31,467,531), XSPR_MASK, PPCPMR, { RS } }, +{ "mtibatu", XSPR(31,467,528), XSPRBAT_MASK, PPC, { SPRBAT, RS } }, +{ "mtibatl", XSPR(31,467,529), XSPRBAT_MASK, PPC, { SPRBAT, RS } }, +{ "mtdbatu", XSPR(31,467,536), XSPRBAT_MASK, PPC, { SPRBAT, RS } }, +{ "mtdbatl", XSPR(31,467,537), XSPRBAT_MASK, PPC, { SPRBAT, RS } }, +{ "mtmcsrr0", XSPR(31,467,570), XSPR_MASK, PPCRFMCI, { RS } }, +{ "mtmcsrr1", XSPR(31,467,571), XSPR_MASK, PPCRFMCI, { RS } }, +{ "mtmcsr", XSPR(31,467,572), XSPR_MASK, PPCRFMCI, { RS } }, +{ "mtummcr0", XSPR(31,467,936), XSPR_MASK, PPC750, { RS } }, +{ "mtupmc1", XSPR(31,467,937), XSPR_MASK, PPC750, { RS } }, +{ "mtupmc2", XSPR(31,467,938), XSPR_MASK, PPC750, { RS } }, +{ "mtusia", XSPR(31,467,939), XSPR_MASK, PPC750, { RS } }, +{ "mtummcr1", XSPR(31,467,940), XSPR_MASK, PPC750, { RS } }, +{ "mtupmc3", XSPR(31,467,941), XSPR_MASK, PPC750, { RS } }, +{ "mtupmc4", XSPR(31,467,942), XSPR_MASK, PPC750, { RS } }, +{ "mtzpr", XSPR(31,467,944), XSPR_MASK, PPC403, { RS } }, +{ "mtccr0", XSPR(31,467,947), XSPR_MASK, PPC405, { RS } }, +{ "mtmmcr0", XSPR(31,467,952), XSPR_MASK, PPC750, { RS } }, +{ "mtsgr", XSPR(31,467,953), XSPR_MASK, PPC403, { RS } }, +{ "mtpmc1", XSPR(31,467,953), XSPR_MASK, PPC750, { RS } }, +{ "mtdcwr", XSPR(31,467,954), XSPR_MASK, PPC403, { RS } }, +{ "mtpmc2", XSPR(31,467,954), XSPR_MASK, PPC750, { RS } }, +{ "mtsler", XSPR(31,467,955), XSPR_MASK, PPC405, { RS } }, +{ "mtsia", XSPR(31,467,955), XSPR_MASK, PPC750, { RS } }, +{ "mtsu0r", XSPR(31,467,956), XSPR_MASK, PPC405, { RS } }, +{ "mtmmcr1", XSPR(31,467,956), XSPR_MASK, PPC750, { RS } }, +{ "mtpmc3", XSPR(31,467,957), XSPR_MASK, PPC750, { RS } }, +{ "mtpmc4", XSPR(31,467,958), XSPR_MASK, PPC750, { RS } }, +{ "mticdbdr", XSPR(31,467,979), XSPR_MASK, PPC403, { RS } }, +{ "mtevpr", XSPR(31,467,982), XSPR_MASK, PPC403, { RS } }, +{ "mtcdbcr", XSPR(31,467,983), XSPR_MASK, PPC403, { RS } }, +{ "mtpit", XSPR(31,467,987), XSPR_MASK, PPC403, { RS } }, +{ "mttbhi", XSPR(31,467,988), XSPR_MASK, PPC403, { RS } }, +{ "mttblo", XSPR(31,467,989), XSPR_MASK, PPC403, { RS } }, +{ "mtsrr2", XSPR(31,467,990), XSPR_MASK, PPC403, { RS } }, +{ "mtsrr3", XSPR(31,467,991), XSPR_MASK, PPC403, { RS } }, +{ "mtl2cr", XSPR(31,467,1017), XSPR_MASK, PPC750, { RS } }, +{ "mtdccr", XSPR(31,467,1018), XSPR_MASK, PPC403, { RS } }, +{ "mticcr", XSPR(31,467,1019), XSPR_MASK, PPC403, { RS } }, +{ "mtictc", XSPR(31,467,1019), XSPR_MASK, PPC750, { RS } }, +{ "mtpbl1", XSPR(31,467,1020), XSPR_MASK, PPC403, { RS } }, +{ "mtthrm1", XSPR(31,467,1020), XSPR_MASK, PPC750, { RS } }, +{ "mtpbu1", XSPR(31,467,1021), XSPR_MASK, PPC403, { RS } }, +{ "mtthrm2", XSPR(31,467,1021), XSPR_MASK, PPC750, { RS } }, +{ "mtpbl2", XSPR(31,467,1022), XSPR_MASK, PPC403, { RS } }, +{ "mtthrm3", XSPR(31,467,1022), XSPR_MASK, PPC750, { RS } }, +{ "mtpbu2", XSPR(31,467,1023), XSPR_MASK, PPC403, { RS } }, +{ "mtspr", X(31,467), X_MASK, COM, { SPR, RS } }, + +{ "dcbi", X(31,470), XRT_MASK, PPC, { RA, RB } }, + +{ "nand", XRC(31,476,0), X_MASK, COM, { RA, RS, RB } }, +{ "nand.", XRC(31,476,1), X_MASK, COM, { RA, RS, RB } }, + +{ "dcbie", X(31,478), XRT_MASK, BOOKE64, { RA, RB } }, + +{ "dcread", X(31,486), X_MASK, PPC403|PPC440, { RT, RA, RB }}, + +{ "mtpmr", X(31,462), X_MASK, PPCPMR, { PMR, RS }}, + +{ "icbtls", X(31,486), X_MASK, PPCCHLK, { CT, RA, RB }}, + +{ "nabs", XO(31,488,0,0), XORB_MASK, M601, { RT, RA } }, +{ "subfme64",XO(31,488,0,0), XORB_MASK, BOOKE64, { RT, RA } }, +{ "nabs.", XO(31,488,0,1), XORB_MASK, M601, { RT, RA } }, +{ "nabso", XO(31,488,1,0), XORB_MASK, M601, { RT, RA } }, +{ "subfme64o",XO(31,488,1,0), XORB_MASK, BOOKE64, { RT, RA } }, +{ "nabso.", XO(31,488,1,1), XORB_MASK, M601, { RT, RA } }, + +{ "divd", XO(31,489,0,0), XO_MASK, PPC64, { RT, RA, RB } }, +{ "divd.", XO(31,489,0,1), XO_MASK, PPC64, { RT, RA, RB } }, +{ "divdo", XO(31,489,1,0), XO_MASK, PPC64, { RT, RA, RB } }, +{ "divdo.", XO(31,489,1,1), XO_MASK, PPC64, { RT, RA, RB } }, + +{ "addme64", XO(31,490,0,0), XORB_MASK, BOOKE64, { RT, RA } }, +{ "addme64o",XO(31,490,1,0), XORB_MASK, BOOKE64, { RT, RA } }, + +{ "divw", XO(31,491,0,0), XO_MASK, PPC, { RT, RA, RB } }, +{ "divw.", XO(31,491,0,1), XO_MASK, PPC, { RT, RA, RB } }, +{ "divwo", XO(31,491,1,0), XO_MASK, PPC, { RT, RA, RB } }, +{ "divwo.", XO(31,491,1,1), XO_MASK, PPC, { RT, RA, RB } }, + +{ "icbtlse", X(31,494), X_MASK, PPCCHLK64, { CT, RA, RB }}, + +{ "slbia", X(31,498), 0xffffffff, PPC64, { 0 } }, + +{ "cli", X(31,502), XRB_MASK, POWER, { RT, RA } }, + +{ "stdcxe.", XRC(31,511,1), X_MASK, BOOKE64, { RS, RA, RB } }, + +{ "mcrxr", X(31,512), XRARB_MASK|(3<<21), COM, { BF } }, + +{ "bblels", X(31,518), X_MASK, PPCBRLK, { 0 }}, +{ "mcrxr64", X(31,544), XRARB_MASK|(3<<21), BOOKE64, { BF } }, + +{ "clcs", X(31,531), XRB_MASK, M601, { RT, RA } }, + +{ "ldbrx", X(31,532), X_MASK, CELL, { RT, RA0, RB } }, + +{ "lswx", X(31,533), X_MASK, PPCCOM, { RT, RA0, RB } }, +{ "lsx", X(31,533), X_MASK, PWRCOM, { RT, RA, RB } }, + +{ "lwbrx", X(31,534), X_MASK, PPCCOM, { RT, RA0, RB } }, +{ "lbrx", X(31,534), X_MASK, PWRCOM, { RT, RA, RB } }, + +{ "lfsx", X(31,535), X_MASK, COM, { FRT, RA0, RB } }, + +{ "srw", XRC(31,536,0), X_MASK, PPCCOM, { RA, RS, RB } }, +{ "sr", XRC(31,536,0), X_MASK, PWRCOM, { RA, RS, RB } }, +{ "srw.", XRC(31,536,1), X_MASK, PPCCOM, { RA, RS, RB } }, +{ "sr.", XRC(31,536,1), X_MASK, PWRCOM, { RA, RS, RB } }, + +{ "rrib", XRC(31,537,0), X_MASK, M601, { RA, RS, RB } }, +{ "rrib.", XRC(31,537,1), X_MASK, M601, { RA, RS, RB } }, + +{ "srd", XRC(31,539,0), X_MASK, PPC64, { RA, RS, RB } }, +{ "srd.", XRC(31,539,1), X_MASK, PPC64, { RA, RS, RB } }, + +{ "maskir", XRC(31,541,0), X_MASK, M601, { RA, RS, RB } }, +{ "maskir.", XRC(31,541,1), X_MASK, M601, { RA, RS, RB } }, + +{ "lwbrxe", X(31,542), X_MASK, BOOKE64, { RT, RA0, RB } }, + +{ "lfsxe", X(31,543), X_MASK, BOOKE64, { FRT, RA0, RB } }, + +{ "bbelr", X(31,550), X_MASK, PPCBRLK, { 0 }}, + +{ "tlbsync", X(31,566), 0xffffffff, PPC, { 0 } }, + +{ "lfsux", X(31,567), X_MASK, COM, { FRT, RAS, RB } }, + +{ "lfsuxe", X(31,575), X_MASK, BOOKE64, { FRT, RAS, RB } }, + +{ "mfsr", X(31,595), XRB_MASK|(1<<20), COM32, { RT, SR } }, + +{ "lswi", X(31,597), X_MASK, PPCCOM, { RT, RA0, NB } }, +{ "lsi", X(31,597), X_MASK, PWRCOM, { RT, RA0, NB } }, + +{ "lwsync", XSYNC(31,598,1), 0xffffffff, PPC, { 0 } }, +{ "ptesync", XSYNC(31,598,2), 0xffffffff, PPC64, { 0 } }, +{ "msync", X(31,598), 0xffffffff, BOOKE, { 0 } }, +{ "sync", X(31,598), XSYNC_MASK, PPCCOM, { LS } }, +{ "dcs", X(31,598), 0xffffffff, PWRCOM, { 0 } }, + +{ "lfdx", X(31,599), X_MASK, COM, { FRT, RA0, RB } }, + +{ "lfdxe", X(31,607), X_MASK, BOOKE64, { FRT, RA0, RB } }, + +{ "mffgpr", XRC(31,607,0), XRA_MASK, POWER6, { FRT, RB } }, + +{ "mfsri", X(31,627), X_MASK, PWRCOM, { RT, RA, RB } }, + +{ "dclst", X(31,630), XRB_MASK, PWRCOM, { RS, RA } }, + +{ "lfdux", X(31,631), X_MASK, COM, { FRT, RAS, RB } }, + +{ "lfduxe", X(31,639), X_MASK, BOOKE64, { FRT, RAS, RB } }, + +{ "mfsrin", X(31,659), XRA_MASK, PPC32, { RT, RB } }, + +{ "stdbrx", X(31,660), X_MASK, CELL, { RS, RA0, RB } }, + +{ "stswx", X(31,661), X_MASK, PPCCOM, { RS, RA0, RB } }, +{ "stsx", X(31,661), X_MASK, PWRCOM, { RS, RA0, RB } }, + +{ "stwbrx", X(31,662), X_MASK, PPCCOM, { RS, RA0, RB } }, +{ "stbrx", X(31,662), X_MASK, PWRCOM, { RS, RA0, RB } }, + +{ "stfsx", X(31,663), X_MASK, COM, { FRS, RA0, RB } }, + +{ "srq", XRC(31,664,0), X_MASK, M601, { RA, RS, RB } }, +{ "srq.", XRC(31,664,1), X_MASK, M601, { RA, RS, RB } }, + +{ "sre", XRC(31,665,0), X_MASK, M601, { RA, RS, RB } }, +{ "sre.", XRC(31,665,1), X_MASK, M601, { RA, RS, RB } }, + +{ "stwbrxe", X(31,670), X_MASK, BOOKE64, { RS, RA0, RB } }, + +{ "stfsxe", X(31,671), X_MASK, BOOKE64, { FRS, RA0, RB } }, + +{ "stfsux", X(31,695), X_MASK, COM, { FRS, RAS, RB } }, + +{ "sriq", XRC(31,696,0), X_MASK, M601, { RA, RS, SH } }, +{ "sriq.", XRC(31,696,1), X_MASK, M601, { RA, RS, SH } }, + +{ "stfsuxe", X(31,703), X_MASK, BOOKE64, { FRS, RAS, RB } }, + +{ "stswi", X(31,725), X_MASK, PPCCOM, { RS, RA0, NB } }, +{ "stsi", X(31,725), X_MASK, PWRCOM, { RS, RA0, NB } }, + +{ "stfdx", X(31,727), X_MASK, COM, { FRS, RA0, RB } }, + +{ "srlq", XRC(31,728,0), X_MASK, M601, { RA, RS, RB } }, +{ "srlq.", XRC(31,728,1), X_MASK, M601, { RA, RS, RB } }, + +{ "sreq", XRC(31,729,0), X_MASK, M601, { RA, RS, RB } }, +{ "sreq.", XRC(31,729,1), X_MASK, M601, { RA, RS, RB } }, + +{ "stfdxe", X(31,735), X_MASK, BOOKE64, { FRS, RA0, RB } }, + +{ "mftgpr", XRC(31,735,0), XRA_MASK, POWER6, { RT, FRB } }, + +{ "dcba", X(31,758), XRT_MASK, PPC405 | PPC7450 | BOOKE, { RA, RB } }, + +{ "stfdux", X(31,759), X_MASK, COM, { FRS, RAS, RB } }, + +{ "srliq", XRC(31,760,0), X_MASK, M601, { RA, RS, SH } }, +{ "srliq.", XRC(31,760,1), X_MASK, M601, { RA, RS, SH } }, + +{ "dcbae", X(31,766), XRT_MASK, BOOKE64, { RA, RB } }, + +{ "stfduxe", X(31,767), X_MASK, BOOKE64, { FRS, RAS, RB } }, + +{ "tlbivax", X(31,786), XRT_MASK, BOOKE, { RA, RB } }, +{ "tlbivaxe",X(31,787), XRT_MASK, BOOKE64, { RA, RB } }, + +{ "lwzcix", X(31,789), X_MASK, POWER6, { RT, RA0, RB } }, + +{ "lhbrx", X(31,790), X_MASK, COM, { RT, RA0, RB } }, + +{ "sraw", XRC(31,792,0), X_MASK, PPCCOM, { RA, RS, RB } }, +{ "sra", XRC(31,792,0), X_MASK, PWRCOM, { RA, RS, RB } }, +{ "sraw.", XRC(31,792,1), X_MASK, PPCCOM, { RA, RS, RB } }, +{ "sra.", XRC(31,792,1), X_MASK, PWRCOM, { RA, RS, RB } }, + +{ "srad", XRC(31,794,0), X_MASK, PPC64, { RA, RS, RB } }, +{ "srad.", XRC(31,794,1), X_MASK, PPC64, { RA, RS, RB } }, + +{ "lhbrxe", X(31,798), X_MASK, BOOKE64, { RT, RA0, RB } }, + +{ "ldxe", X(31,799), X_MASK, BOOKE64, { RT, RA0, RB } }, +{ "lduxe", X(31,831), X_MASK, BOOKE64, { RT, RA0, RB } }, + +{ "rac", X(31,818), X_MASK, PWRCOM, { RT, RA, RB } }, + +{ "lhzcix", X(31,821), X_MASK, POWER6, { RT, RA0, RB } }, + +{ "dss", XDSS(31,822,0), XDSS_MASK, PPCVEC, { STRM } }, +{ "dssall", XDSS(31,822,1), XDSS_MASK, PPCVEC, { 0 } }, + +{ "srawi", XRC(31,824,0), X_MASK, PPCCOM, { RA, RS, SH } }, +{ "srai", XRC(31,824,0), X_MASK, PWRCOM, { RA, RS, SH } }, +{ "srawi.", XRC(31,824,1), X_MASK, PPCCOM, { RA, RS, SH } }, +{ "srai.", XRC(31,824,1), X_MASK, PWRCOM, { RA, RS, SH } }, + +{ "slbmfev", X(31,851), XRA_MASK, PPC64, { RT, RB } }, + +{ "lbzcix", X(31,853), X_MASK, POWER6, { RT, RA0, RB } }, + +{ "mbar", X(31,854), X_MASK, BOOKE, { MO } }, +{ "eieio", X(31,854), 0xffffffff, PPC, { 0 } }, + +{ "lfiwax", X(31,855), X_MASK, POWER6, { FRT, RA0, RB } }, + +{ "ldcix", X(31,885), X_MASK, POWER6, { RT, RA0, RB } }, + +{ "tlbsx", XRC(31,914,0), X_MASK, PPC403|BOOKE, { RTO, RA, RB } }, +{ "tlbsx.", XRC(31,914,1), X_MASK, PPC403|BOOKE, { RTO, RA, RB } }, +{ "tlbsxe", XRC(31,915,0), X_MASK, BOOKE64, { RTO, RA, RB } }, +{ "tlbsxe.", XRC(31,915,1), X_MASK, BOOKE64, { RTO, RA, RB } }, + +{ "slbmfee", X(31,915), XRA_MASK, PPC64, { RT, RB } }, + +{ "stwcix", X(31,917), X_MASK, POWER6, { RS, RA0, RB } }, + +{ "sthbrx", X(31,918), X_MASK, COM, { RS, RA0, RB } }, + +{ "sraq", XRC(31,920,0), X_MASK, M601, { RA, RS, RB } }, +{ "sraq.", XRC(31,920,1), X_MASK, M601, { RA, RS, RB } }, + +{ "srea", XRC(31,921,0), X_MASK, M601, { RA, RS, RB } }, +{ "srea.", XRC(31,921,1), X_MASK, M601, { RA, RS, RB } }, + +{ "extsh", XRC(31,922,0), XRB_MASK, PPCCOM, { RA, RS } }, +{ "exts", XRC(31,922,0), XRB_MASK, PWRCOM, { RA, RS } }, +{ "extsh.", XRC(31,922,1), XRB_MASK, PPCCOM, { RA, RS } }, +{ "exts.", XRC(31,922,1), XRB_MASK, PWRCOM, { RA, RS } }, + +{ "sthbrxe", X(31,926), X_MASK, BOOKE64, { RS, RA0, RB } }, + +{ "stdxe", X(31,927), X_MASK, BOOKE64, { RS, RA0, RB } }, + +{ "tlbrehi", XTLB(31,946,0), XTLB_MASK, PPC403, { RT, RA } }, +{ "tlbrelo", XTLB(31,946,1), XTLB_MASK, PPC403, { RT, RA } }, +{ "tlbre", X(31,946), X_MASK, PPC403|BOOKE, { RSO, RAOPT, SHO } }, + +{ "sthcix", X(31,949), X_MASK, POWER6, { RS, RA0, RB } }, + +{ "sraiq", XRC(31,952,0), X_MASK, M601, { RA, RS, SH } }, +{ "sraiq.", XRC(31,952,1), X_MASK, M601, { RA, RS, SH } }, + +{ "extsb", XRC(31,954,0), XRB_MASK, PPC, { RA, RS} }, +{ "extsb.", XRC(31,954,1), XRB_MASK, PPC, { RA, RS} }, + +{ "stduxe", X(31,959), X_MASK, BOOKE64, { RS, RAS, RB } }, + +{ "iccci", X(31,966), XRT_MASK, PPC403|PPC440, { RA, RB } }, + +{ "tlbwehi", XTLB(31,978,0), XTLB_MASK, PPC403, { RT, RA } }, +{ "tlbwelo", XTLB(31,978,1), XTLB_MASK, PPC403, { RT, RA } }, +{ "tlbwe", X(31,978), X_MASK, PPC403|BOOKE, { RSO, RAOPT, SHO } }, +{ "tlbld", X(31,978), XRTRA_MASK, PPC, { RB } }, + +{ "stbcix", X(31,981), X_MASK, POWER6, { RS, RA0, RB } }, + +{ "icbi", X(31,982), XRT_MASK, PPC, { RA, RB } }, + +{ "stfiwx", X(31,983), X_MASK, PPC, { FRS, RA0, RB } }, + +{ "extsw", XRC(31,986,0), XRB_MASK, PPC64 | BOOKE64,{ RA, RS } }, +{ "extsw.", XRC(31,986,1), XRB_MASK, PPC64, { RA, RS } }, + +{ "icread", X(31,998), XRT_MASK, PPC403|PPC440, { RA, RB } }, + +{ "icbie", X(31,990), XRT_MASK, BOOKE64, { RA, RB } }, +{ "stfiwxe", X(31,991), X_MASK, BOOKE64, { FRS, RA0, RB } }, + +{ "tlbli", X(31,1010), XRTRA_MASK, PPC, { RB } }, + +{ "stdcix", X(31,1013), X_MASK, POWER6, { RS, RA0, RB } }, + +{ "dcbzl", XOPL(31,1014,1), XRT_MASK,POWER4, { RA, RB } }, +{ "dcbz", X(31,1014), XRT_MASK, PPC, { RA, RB } }, +{ "dclz", X(31,1014), XRT_MASK, PPC, { RA, RB } }, + +{ "dcbze", X(31,1022), XRT_MASK, BOOKE64, { RA, RB } }, + +{ "lvebx", X(31, 7), X_MASK, PPCVEC, { VD, RA, RB } }, +{ "lvehx", X(31, 39), X_MASK, PPCVEC, { VD, RA, RB } }, +{ "lvewx", X(31, 71), X_MASK, PPCVEC, { VD, RA, RB } }, +{ "lvsl", X(31, 6), X_MASK, PPCVEC, { VD, RA, RB } }, +{ "lvsr", X(31, 38), X_MASK, PPCVEC, { VD, RA, RB } }, +{ "lvx", X(31, 103), X_MASK, PPCVEC, { VD, RA, RB } }, +{ "lvxl", X(31, 359), X_MASK, PPCVEC, { VD, RA, RB } }, +{ "stvebx", X(31, 135), X_MASK, PPCVEC, { VS, RA, RB } }, +{ "stvehx", X(31, 167), X_MASK, PPCVEC, { VS, RA, RB } }, +{ "stvewx", X(31, 199), X_MASK, PPCVEC, { VS, RA, RB } }, +{ "stvx", X(31, 231), X_MASK, PPCVEC, { VS, RA, RB } }, +{ "stvxl", X(31, 487), X_MASK, PPCVEC, { VS, RA, RB } }, + +/* New load/store left/right index vector instructions that are in the Cell only. */ +{ "lvlx", X(31, 519), X_MASK, CELL, { VD, RA0, RB } }, +{ "lvlxl", X(31, 775), X_MASK, CELL, { VD, RA0, RB } }, +{ "lvrx", X(31, 551), X_MASK, CELL, { VD, RA0, RB } }, +{ "lvrxl", X(31, 807), X_MASK, CELL, { VD, RA0, RB } }, +{ "stvlx", X(31, 647), X_MASK, CELL, { VS, RA0, RB } }, +{ "stvlxl", X(31, 903), X_MASK, CELL, { VS, RA0, RB } }, +{ "stvrx", X(31, 679), X_MASK, CELL, { VS, RA0, RB } }, +{ "stvrxl", X(31, 935), X_MASK, CELL, { VS, RA0, RB } }, + +{ "lwz", OP(32), OP_MASK, PPCCOM, { RT, D, RA0 } }, +{ "l", OP(32), OP_MASK, PWRCOM, { RT, D, RA0 } }, + +{ "lwzu", OP(33), OP_MASK, PPCCOM, { RT, D, RAL } }, +{ "lu", OP(33), OP_MASK, PWRCOM, { RT, D, RA0 } }, + +{ "lbz", OP(34), OP_MASK, COM, { RT, D, RA0 } }, + +{ "lbzu", OP(35), OP_MASK, COM, { RT, D, RAL } }, + +{ "stw", OP(36), OP_MASK, PPCCOM, { RS, D, RA0 } }, +{ "st", OP(36), OP_MASK, PWRCOM, { RS, D, RA0 } }, + +{ "stwu", OP(37), OP_MASK, PPCCOM, { RS, D, RAS } }, +{ "stu", OP(37), OP_MASK, PWRCOM, { RS, D, RA0 } }, + +{ "stb", OP(38), OP_MASK, COM, { RS, D, RA0 } }, + +{ "stbu", OP(39), OP_MASK, COM, { RS, D, RAS } }, + +{ "lhz", OP(40), OP_MASK, COM, { RT, D, RA0 } }, + +{ "lhzu", OP(41), OP_MASK, COM, { RT, D, RAL } }, + +{ "lha", OP(42), OP_MASK, COM, { RT, D, RA0 } }, + +{ "lhau", OP(43), OP_MASK, COM, { RT, D, RAL } }, + +{ "sth", OP(44), OP_MASK, COM, { RS, D, RA0 } }, + +{ "sthu", OP(45), OP_MASK, COM, { RS, D, RAS } }, + +{ "lmw", OP(46), OP_MASK, PPCCOM, { RT, D, RAM } }, +{ "lm", OP(46), OP_MASK, PWRCOM, { RT, D, RA0 } }, + +{ "stmw", OP(47), OP_MASK, PPCCOM, { RS, D, RA0 } }, +{ "stm", OP(47), OP_MASK, PWRCOM, { RS, D, RA0 } }, + +{ "lfs", OP(48), OP_MASK, COM, { FRT, D, RA0 } }, + +{ "lfsu", OP(49), OP_MASK, COM, { FRT, D, RAS } }, + +{ "lfd", OP(50), OP_MASK, COM, { FRT, D, RA0 } }, + +{ "lfdu", OP(51), OP_MASK, COM, { FRT, D, RAS } }, + +{ "stfs", OP(52), OP_MASK, COM, { FRS, D, RA0 } }, + +{ "stfsu", OP(53), OP_MASK, COM, { FRS, D, RAS } }, + +{ "stfd", OP(54), OP_MASK, COM, { FRS, D, RA0 } }, + +{ "stfdu", OP(55), OP_MASK, COM, { FRS, D, RAS } }, + +{ "lq", OP(56), OP_MASK, POWER4, { RTQ, DQ, RAQ } }, + +{ "lfq", OP(56), OP_MASK, POWER2, { FRT, D, RA0 } }, + +{ "lfqu", OP(57), OP_MASK, POWER2, { FRT, D, RA0 } }, + +{ "lfdp", OP(57), OP_MASK, POWER6, { FRT, D, RA0 } }, + +{ "lbze", DEO(58,0), DE_MASK, BOOKE64, { RT, DE, RA0 } }, +{ "lbzue", DEO(58,1), DE_MASK, BOOKE64, { RT, DE, RAL } }, +{ "lhze", DEO(58,2), DE_MASK, BOOKE64, { RT, DE, RA0 } }, +{ "lhzue", DEO(58,3), DE_MASK, BOOKE64, { RT, DE, RAL } }, +{ "lhae", DEO(58,4), DE_MASK, BOOKE64, { RT, DE, RA0 } }, +{ "lhaue", DEO(58,5), DE_MASK, BOOKE64, { RT, DE, RAL } }, +{ "lwze", DEO(58,6), DE_MASK, BOOKE64, { RT, DE, RA0 } }, +{ "lwzue", DEO(58,7), DE_MASK, BOOKE64, { RT, DE, RAL } }, +{ "stbe", DEO(58,8), DE_MASK, BOOKE64, { RS, DE, RA0 } }, +{ "stbue", DEO(58,9), DE_MASK, BOOKE64, { RS, DE, RAS } }, +{ "sthe", DEO(58,10), DE_MASK, BOOKE64, { RS, DE, RA0 } }, +{ "sthue", DEO(58,11), DE_MASK, BOOKE64, { RS, DE, RAS } }, +{ "stwe", DEO(58,14), DE_MASK, BOOKE64, { RS, DE, RA0 } }, +{ "stwue", DEO(58,15), DE_MASK, BOOKE64, { RS, DE, RAS } }, + +{ "ld", DSO(58,0), DS_MASK, PPC64, { RT, DS, RA0 } }, + +{ "ldu", DSO(58,1), DS_MASK, PPC64, { RT, DS, RAL } }, + +{ "lwa", DSO(58,2), DS_MASK, PPC64, { RT, DS, RA0 } }, + +{ "dadd", XRC(59,2,0), X_MASK, POWER6, { FRT, FRA, FRB } }, +{ "dadd.", XRC(59,2,1), X_MASK, POWER6, { FRT, FRA, FRB } }, + +{ "dqua", ZRC(59,3,0), Z2_MASK, POWER6, { FRT, FRA, FRB, RMC } }, +{ "dqua.", ZRC(59,3,1), Z2_MASK, POWER6, { FRT, FRA, FRB, RMC } }, + +{ "fdivs", A(59,18,0), AFRC_MASK, PPC, { FRT, FRA, FRB } }, +{ "fdivs.", A(59,18,1), AFRC_MASK, PPC, { FRT, FRA, FRB } }, + +{ "fsubs", A(59,20,0), AFRC_MASK, PPC, { FRT, FRA, FRB } }, +{ "fsubs.", A(59,20,1), AFRC_MASK, PPC, { FRT, FRA, FRB } }, + +{ "fadds", A(59,21,0), AFRC_MASK, PPC, { FRT, FRA, FRB } }, +{ "fadds.", A(59,21,1), AFRC_MASK, PPC, { FRT, FRA, FRB } }, + +{ "fsqrts", A(59,22,0), AFRAFRC_MASK, PPC, { FRT, FRB } }, +{ "fsqrts.", A(59,22,1), AFRAFRC_MASK, PPC, { FRT, FRB } }, + +{ "fres", A(59,24,0), AFRALFRC_MASK, PPC, { FRT, FRB, A_L } }, +{ "fres.", A(59,24,1), AFRALFRC_MASK, PPC, { FRT, FRB, A_L } }, + +{ "fmuls", A(59,25,0), AFRB_MASK, PPC, { FRT, FRA, FRC } }, +{ "fmuls.", A(59,25,1), AFRB_MASK, PPC, { FRT, FRA, FRC } }, + +{ "frsqrtes", A(59,26,0), AFRALFRC_MASK,POWER5, { FRT, FRB, A_L } }, +{ "frsqrtes.",A(59,26,1), AFRALFRC_MASK,POWER5, { FRT, FRB, A_L } }, + +{ "fmsubs", A(59,28,0), A_MASK, PPC, { FRT,FRA,FRC,FRB } }, +{ "fmsubs.", A(59,28,1), A_MASK, PPC, { FRT,FRA,FRC,FRB } }, + +{ "fmadds", A(59,29,0), A_MASK, PPC, { FRT,FRA,FRC,FRB } }, +{ "fmadds.", A(59,29,1), A_MASK, PPC, { FRT,FRA,FRC,FRB } }, + +{ "fnmsubs", A(59,30,0), A_MASK, PPC, { FRT,FRA,FRC,FRB } }, +{ "fnmsubs.",A(59,30,1), A_MASK, PPC, { FRT,FRA,FRC,FRB } }, + +{ "fnmadds", A(59,31,0), A_MASK, PPC, { FRT,FRA,FRC,FRB } }, +{ "fnmadds.",A(59,31,1), A_MASK, PPC, { FRT,FRA,FRC,FRB } }, + +{ "dmul", XRC(59,34,0), X_MASK, POWER6, { FRT, FRA, FRB } }, +{ "dmul.", XRC(59,34,1), X_MASK, POWER6, { FRT, FRA, FRB } }, + +{ "drrnd", ZRC(59,35,0), Z2_MASK, POWER6, { FRT, FRA, FRB, RMC } }, +{ "drrnd.", ZRC(59,35,1), Z2_MASK, POWER6, { FRT, FRA, FRB, RMC } }, + +{ "dscli", ZRC(59,66,0), Z_MASK, POWER6, { FRT, FRA, SH16 } }, +{ "dscli.", ZRC(59,66,1), Z_MASK, POWER6, { FRT, FRA, SH16 } }, + +{ "dquai", ZRC(59,67,0), Z2_MASK, POWER6, { TE, FRT, FRB, RMC } }, +{ "dquai.", ZRC(59,67,1), Z2_MASK, POWER6, { TE, FRT, FRB, RMC } }, + +{ "dscri", ZRC(59,98,0), Z_MASK, POWER6, { FRT, FRA, SH16 } }, +{ "dscri.", ZRC(59,98,1), Z_MASK, POWER6, { FRT, FRA, SH16 } }, + +{ "drintx", ZRC(59,99,0), Z2_MASK, POWER6, { R, FRT, FRB, RMC } }, +{ "drintx.", ZRC(59,99,1), Z2_MASK, POWER6, { R, FRT, FRB, RMC } }, + +{ "dcmpo", X(59,130), X_MASK, POWER6, { BF, FRA, FRB } }, + +{ "dtstex", X(59,162), X_MASK, POWER6, { BF, FRA, FRB } }, +{ "dtstdc", Z(59,194), Z_MASK, POWER6, { BF, FRA, DCM } }, +{ "dtstdg", Z(59,226), Z_MASK, POWER6, { BF, FRA, DGM } }, + +{ "drintn", ZRC(59,227,0), Z2_MASK, POWER6, { R, FRT, FRB, RMC } }, +{ "drintn.", ZRC(59,227,1), Z2_MASK, POWER6, { R, FRT, FRB, RMC } }, + +{ "dctdp", XRC(59,258,0), X_MASK, POWER6, { FRT, FRB } }, +{ "dctdp.", XRC(59,258,1), X_MASK, POWER6, { FRT, FRB } }, + +{ "dctfix", XRC(59,290,0), X_MASK, POWER6, { FRT, FRB } }, +{ "dctfix.", XRC(59,290,1), X_MASK, POWER6, { FRT, FRB } }, + +{ "ddedpd", XRC(59,322,0), X_MASK, POWER6, { SP, FRT, FRB } }, +{ "ddedpd.", XRC(59,322,1), X_MASK, POWER6, { SP, FRT, FRB } }, + +{ "dxex", XRC(59,354,0), X_MASK, POWER6, { FRT, FRB } }, +{ "dxex.", XRC(59,354,1), X_MASK, POWER6, { FRT, FRB } }, + +{ "dsub", XRC(59,514,0), X_MASK, POWER6, { FRT, FRA, FRB } }, +{ "dsub.", XRC(59,514,1), X_MASK, POWER6, { FRT, FRA, FRB } }, + +{ "ddiv", XRC(59,546,0), X_MASK, POWER6, { FRT, FRA, FRB } }, +{ "ddiv.", XRC(59,546,1), X_MASK, POWER6, { FRT, FRA, FRB } }, + +{ "dcmpu", X(59,642), X_MASK, POWER6, { BF, FRA, FRB } }, + +{ "dtstsf", X(59,674), X_MASK, POWER6, { BF, FRA, FRB } }, + +{ "drsp", XRC(59,770,0), X_MASK, POWER6, { FRT, FRB } }, +{ "drsp.", XRC(59,770,1), X_MASK, POWER6, { FRT, FRB } }, + +{ "dcffix", XRC(59,802,0), X_MASK, POWER6, { FRT, FRB } }, +{ "dcffix.", XRC(59,802,1), X_MASK, POWER6, { FRT, FRB } }, + +{ "denbcd", XRC(59,834,0), X_MASK, POWER6, { S, FRT, FRB } }, +{ "denbcd.", XRC(59,834,1), X_MASK, POWER6, { S, FRT, FRB } }, + +{ "diex", XRC(59,866,0), X_MASK, POWER6, { FRT, FRA, FRB } }, +{ "diex.", XRC(59,866,1), X_MASK, POWER6, { FRT, FRA, FRB } }, + +{ "stfq", OP(60), OP_MASK, POWER2, { FRS, D, RA } }, + +{ "stfqu", OP(61), OP_MASK, POWER2, { FRS, D, RA } }, + +{ "stfdp", OP(61), OP_MASK, POWER6, { FRT, D, RA0 } }, + +{ "lde", DEO(62,0), DE_MASK, BOOKE64, { RT, DES, RA0 } }, +{ "ldue", DEO(62,1), DE_MASK, BOOKE64, { RT, DES, RA0 } }, +{ "lfse", DEO(62,4), DE_MASK, BOOKE64, { FRT, DES, RA0 } }, +{ "lfsue", DEO(62,5), DE_MASK, BOOKE64, { FRT, DES, RAS } }, +{ "lfde", DEO(62,6), DE_MASK, BOOKE64, { FRT, DES, RA0 } }, +{ "lfdue", DEO(62,7), DE_MASK, BOOKE64, { FRT, DES, RAS } }, +{ "stde", DEO(62,8), DE_MASK, BOOKE64, { RS, DES, RA0 } }, +{ "stdue", DEO(62,9), DE_MASK, BOOKE64, { RS, DES, RAS } }, +{ "stfse", DEO(62,12), DE_MASK, BOOKE64, { FRS, DES, RA0 } }, +{ "stfsue", DEO(62,13), DE_MASK, BOOKE64, { FRS, DES, RAS } }, +{ "stfde", DEO(62,14), DE_MASK, BOOKE64, { FRS, DES, RA0 } }, +{ "stfdue", DEO(62,15), DE_MASK, BOOKE64, { FRS, DES, RAS } }, + +{ "std", DSO(62,0), DS_MASK, PPC64, { RS, DS, RA0 } }, + +{ "stdu", DSO(62,1), DS_MASK, PPC64, { RS, DS, RAS } }, + +{ "stq", DSO(62,2), DS_MASK, POWER4, { RSQ, DS, RA0 } }, + +{ "fcmpu", X(63,0), X_MASK|(3<<21), COM, { BF, FRA, FRB } }, + +{ "daddq", XRC(63,2,0), X_MASK, POWER6, { FRT, FRA, FRB } }, +{ "daddq.", XRC(63,2,1), X_MASK, POWER6, { FRT, FRA, FRB } }, + +{ "dquaq", ZRC(63,3,0), Z2_MASK, POWER6, { FRT, FRA, FRB, RMC } }, +{ "dquaq.", ZRC(63,3,1), Z2_MASK, POWER6, { FRT, FRA, FRB, RMC } }, + +{ "fcpsgn", XRC(63,8,0), X_MASK, POWER6, { FRT, FRA, FRB } }, +{ "fcpsgn.", XRC(63,8,1), X_MASK, POWER6, { FRT, FRA, FRB } }, + +{ "frsp", XRC(63,12,0), XRA_MASK, COM, { FRT, FRB } }, +{ "frsp.", XRC(63,12,1), XRA_MASK, COM, { FRT, FRB } }, + +{ "fctiw", XRC(63,14,0), XRA_MASK, PPCCOM, { FRT, FRB } }, +{ "fcir", XRC(63,14,0), XRA_MASK, POWER2, { FRT, FRB } }, +{ "fctiw.", XRC(63,14,1), XRA_MASK, PPCCOM, { FRT, FRB } }, +{ "fcir.", XRC(63,14,1), XRA_MASK, POWER2, { FRT, FRB } }, + +{ "fctiwz", XRC(63,15,0), XRA_MASK, PPCCOM, { FRT, FRB } }, +{ "fcirz", XRC(63,15,0), XRA_MASK, POWER2, { FRT, FRB } }, +{ "fctiwz.", XRC(63,15,1), XRA_MASK, PPCCOM, { FRT, FRB } }, +{ "fcirz.", XRC(63,15,1), XRA_MASK, POWER2, { FRT, FRB } }, + +{ "fdiv", A(63,18,0), AFRC_MASK, PPCCOM, { FRT, FRA, FRB } }, +{ "fd", A(63,18,0), AFRC_MASK, PWRCOM, { FRT, FRA, FRB } }, +{ "fdiv.", A(63,18,1), AFRC_MASK, PPCCOM, { FRT, FRA, FRB } }, +{ "fd.", A(63,18,1), AFRC_MASK, PWRCOM, { FRT, FRA, FRB } }, + +{ "fsub", A(63,20,0), AFRC_MASK, PPCCOM, { FRT, FRA, FRB } }, +{ "fs", A(63,20,0), AFRC_MASK, PWRCOM, { FRT, FRA, FRB } }, +{ "fsub.", A(63,20,1), AFRC_MASK, PPCCOM, { FRT, FRA, FRB } }, +{ "fs.", A(63,20,1), AFRC_MASK, PWRCOM, { FRT, FRA, FRB } }, + +{ "fadd", A(63,21,0), AFRC_MASK, PPCCOM, { FRT, FRA, FRB } }, +{ "fa", A(63,21,0), AFRC_MASK, PWRCOM, { FRT, FRA, FRB } }, +{ "fadd.", A(63,21,1), AFRC_MASK, PPCCOM, { FRT, FRA, FRB } }, +{ "fa.", A(63,21,1), AFRC_MASK, PWRCOM, { FRT, FRA, FRB } }, + +{ "fsqrt", A(63,22,0), AFRAFRC_MASK, PPCPWR2, { FRT, FRB } }, +{ "fsqrt.", A(63,22,1), AFRAFRC_MASK, PPCPWR2, { FRT, FRB } }, + +{ "fsel", A(63,23,0), A_MASK, PPC, { FRT,FRA,FRC,FRB } }, +{ "fsel.", A(63,23,1), A_MASK, PPC, { FRT,FRA,FRC,FRB } }, + +{ "fre", A(63,24,0), AFRALFRC_MASK, POWER5, { FRT, FRB, A_L } }, +{ "fre.", A(63,24,1), AFRALFRC_MASK, POWER5, { FRT, FRB, A_L } }, + +{ "fmul", A(63,25,0), AFRB_MASK, PPCCOM, { FRT, FRA, FRC } }, +{ "fm", A(63,25,0), AFRB_MASK, PWRCOM, { FRT, FRA, FRC } }, +{ "fmul.", A(63,25,1), AFRB_MASK, PPCCOM, { FRT, FRA, FRC } }, +{ "fm.", A(63,25,1), AFRB_MASK, PWRCOM, { FRT, FRA, FRC } }, + +{ "frsqrte", A(63,26,0), AFRALFRC_MASK, PPC, { FRT, FRB, A_L } }, +{ "frsqrte.",A(63,26,1), AFRALFRC_MASK, PPC, { FRT, FRB, A_L } }, + +{ "fmsub", A(63,28,0), A_MASK, PPCCOM, { FRT,FRA,FRC,FRB } }, +{ "fms", A(63,28,0), A_MASK, PWRCOM, { FRT,FRA,FRC,FRB } }, +{ "fmsub.", A(63,28,1), A_MASK, PPCCOM, { FRT,FRA,FRC,FRB } }, +{ "fms.", A(63,28,1), A_MASK, PWRCOM, { FRT,FRA,FRC,FRB } }, + +{ "fmadd", A(63,29,0), A_MASK, PPCCOM, { FRT,FRA,FRC,FRB } }, +{ "fma", A(63,29,0), A_MASK, PWRCOM, { FRT,FRA,FRC,FRB } }, +{ "fmadd.", A(63,29,1), A_MASK, PPCCOM, { FRT,FRA,FRC,FRB } }, +{ "fma.", A(63,29,1), A_MASK, PWRCOM, { FRT,FRA,FRC,FRB } }, + +{ "fnmsub", A(63,30,0), A_MASK, PPCCOM, { FRT,FRA,FRC,FRB } }, +{ "fnms", A(63,30,0), A_MASK, PWRCOM, { FRT,FRA,FRC,FRB } }, +{ "fnmsub.", A(63,30,1), A_MASK, PPCCOM, { FRT,FRA,FRC,FRB } }, +{ "fnms.", A(63,30,1), A_MASK, PWRCOM, { FRT,FRA,FRC,FRB } }, + +{ "fnmadd", A(63,31,0), A_MASK, PPCCOM, { FRT,FRA,FRC,FRB } }, +{ "fnma", A(63,31,0), A_MASK, PWRCOM, { FRT,FRA,FRC,FRB } }, +{ "fnmadd.", A(63,31,1), A_MASK, PPCCOM, { FRT,FRA,FRC,FRB } }, +{ "fnma.", A(63,31,1), A_MASK, PWRCOM, { FRT,FRA,FRC,FRB } }, + +{ "fcmpo", X(63,32), X_MASK|(3<<21), COM, { BF, FRA, FRB } }, + +{ "dmulq", XRC(63,34,0), X_MASK, POWER6, { FRT, FRA, FRB } }, +{ "dmulq.", XRC(63,34,1), X_MASK, POWER6, { FRT, FRA, FRB } }, + +{ "drrndq", ZRC(63,35,0), Z2_MASK, POWER6, { FRT, FRA, FRB, RMC } }, +{ "drrndq.", ZRC(63,35,1), Z2_MASK, POWER6, { FRT, FRA, FRB, RMC } }, + +{ "mtfsb1", XRC(63,38,0), XRARB_MASK, COM, { BT } }, +{ "mtfsb1.", XRC(63,38,1), XRARB_MASK, COM, { BT } }, + +{ "fneg", XRC(63,40,0), XRA_MASK, COM, { FRT, FRB } }, +{ "fneg.", XRC(63,40,1), XRA_MASK, COM, { FRT, FRB } }, + +{ "mcrfs", X(63,64), XRB_MASK|(3<<21)|(3<<16), COM, { BF, BFA } }, + +{ "dscliq", ZRC(63,66,0), Z_MASK, POWER6, { FRT, FRA, SH16 } }, +{ "dscliq.", ZRC(63,66,1), Z_MASK, POWER6, { FRT, FRA, SH16 } }, + +{ "dquaiq", ZRC(63,67,0), Z2_MASK, POWER6, { TE, FRT, FRB, RMC } }, +{ "dquaiq.", ZRC(63,67,1), Z2_MASK, POWER6, { FRT, FRA, FRB, RMC } }, + +{ "mtfsb0", XRC(63,70,0), XRARB_MASK, COM, { BT } }, +{ "mtfsb0.", XRC(63,70,1), XRARB_MASK, COM, { BT } }, + +{ "fmr", XRC(63,72,0), XRA_MASK, COM, { FRT, FRB } }, +{ "fmr.", XRC(63,72,1), XRA_MASK, COM, { FRT, FRB } }, + +{ "dscriq", ZRC(63,98,0), Z_MASK, POWER6, { FRT, FRA, SH16 } }, +{ "dscriq.", ZRC(63,98,1), Z_MASK, POWER6, { FRT, FRA, SH16 } }, + +{ "drintxq", ZRC(63,99,0), Z2_MASK, POWER6, { R, FRT, FRB, RMC } }, +{ "drintxq.",ZRC(63,99,1), Z2_MASK, POWER6, { R, FRT, FRB, RMC } }, + +{ "dcmpoq", X(63,130), X_MASK, POWER6, { BF, FRA, FRB } }, + +{ "mtfsfi", XRC(63,134,0), XWRA_MASK|(3<<21)|(1<<11), COM, { BFF, U, W } }, +{ "mtfsfi.", XRC(63,134,1), XWRA_MASK|(3<<21)|(1<<11), COM, { BFF, U, W } }, + +{ "fnabs", XRC(63,136,0), XRA_MASK, COM, { FRT, FRB } }, +{ "fnabs.", XRC(63,136,1), XRA_MASK, COM, { FRT, FRB } }, + +{ "dtstexq", X(63,162), X_MASK, POWER6, { BF, FRA, FRB } }, +{ "dtstdcq", Z(63,194), Z_MASK, POWER6, { BF, FRA, DCM } }, +{ "dtstdgq", Z(63,226), Z_MASK, POWER6, { BF, FRA, DGM } }, + +{ "drintnq", ZRC(63,227,0), Z2_MASK, POWER6, { R, FRT, FRB, RMC } }, +{ "drintnq.",ZRC(63,227,1), Z2_MASK, POWER6, { R, FRT, FRB, RMC } }, + +{ "dctqpq", XRC(63,258,0), X_MASK, POWER6, { FRT, FRB } }, +{ "dctqpq.", XRC(63,258,1), X_MASK, POWER6, { FRT, FRB } }, + +{ "fabs", XRC(63,264,0), XRA_MASK, COM, { FRT, FRB } }, +{ "fabs.", XRC(63,264,1), XRA_MASK, COM, { FRT, FRB } }, + +{ "dctfixq", XRC(63,290,0), X_MASK, POWER6, { FRT, FRB } }, +{ "dctfixq.",XRC(63,290,1), X_MASK, POWER6, { FRT, FRB } }, + +{ "ddedpdq", XRC(63,322,0), X_MASK, POWER6, { SP, FRT, FRB } }, +{ "ddedpdq.",XRC(63,322,1), X_MASK, POWER6, { SP, FRT, FRB } }, + +{ "dxexq", XRC(63,354,0), X_MASK, POWER6, { FRT, FRB } }, +{ "dxexq.", XRC(63,354,1), X_MASK, POWER6, { FRT, FRB } }, + +{ "frin", XRC(63,392,0), XRA_MASK, POWER5, { FRT, FRB } }, +{ "frin.", XRC(63,392,1), XRA_MASK, POWER5, { FRT, FRB } }, +{ "friz", XRC(63,424,0), XRA_MASK, POWER5, { FRT, FRB } }, +{ "friz.", XRC(63,424,1), XRA_MASK, POWER5, { FRT, FRB } }, +{ "frip", XRC(63,456,0), XRA_MASK, POWER5, { FRT, FRB } }, +{ "frip.", XRC(63,456,1), XRA_MASK, POWER5, { FRT, FRB } }, +{ "frim", XRC(63,488,0), XRA_MASK, POWER5, { FRT, FRB } }, +{ "frim.", XRC(63,488,1), XRA_MASK, POWER5, { FRT, FRB } }, + +{ "dsubq", XRC(63,514,0), X_MASK, POWER6, { FRT, FRA, FRB } }, +{ "dsubq.", XRC(63,514,1), X_MASK, POWER6, { FRT, FRA, FRB } }, + +{ "ddivq", XRC(63,546,0), X_MASK, POWER6, { FRT, FRA, FRB } }, +{ "ddivq.", XRC(63,546,1), X_MASK, POWER6, { FRT, FRA, FRB } }, + +{ "mffs", XRC(63,583,0), XRARB_MASK, COM, { FRT } }, +{ "mffs.", XRC(63,583,1), XRARB_MASK, COM, { FRT } }, + +{ "dcmpuq", X(63,642), X_MASK, POWER6, { BF, FRA, FRB } }, + +{ "dtstsfq", X(63,674), X_MASK, POWER6, { BF, FRA, FRB } }, + +{ "mtfsf", XFL(63,711,0), XFL_MASK, COM, { FLM, FRB, XFL_L, W } }, +{ "mtfsf.", XFL(63,711,1), XFL_MASK, COM, { FLM, FRB, XFL_L, W } }, + +{ "drdpq", XRC(63,770,0), X_MASK, POWER6, { FRT, FRB } }, +{ "drdpq.", XRC(63,770,1), X_MASK, POWER6, { FRT, FRB } }, + +{ "dcffixq", XRC(63,802,0), X_MASK, POWER6, { FRT, FRB } }, +{ "dcffixq.",XRC(63,802,1), X_MASK, POWER6, { FRT, FRB } }, + +{ "fctid", XRC(63,814,0), XRA_MASK, PPC64, { FRT, FRB } }, +{ "fctid.", XRC(63,814,1), XRA_MASK, PPC64, { FRT, FRB } }, + +{ "fctidz", XRC(63,815,0), XRA_MASK, PPC64, { FRT, FRB } }, +{ "fctidz.", XRC(63,815,1), XRA_MASK, PPC64, { FRT, FRB } }, + +{ "denbcdq", XRC(63,834,0), X_MASK, POWER6, { S, FRT, FRB } }, +{ "denbcdq.",XRC(63,834,1), X_MASK, POWER6, { S, FRT, FRB } }, + +{ "fcfid", XRC(63,846,0), XRA_MASK, PPC64, { FRT, FRB } }, +{ "fcfid.", XRC(63,846,1), XRA_MASK, PPC64, { FRT, FRB } }, + +{ "diexq", XRC(63,866,0), X_MASK, POWER6, { FRT, FRA, FRB } }, +{ "diexq.", XRC(63,866,1), X_MASK, POWER6, { FRT, FRA, FRB } }, + +}; + +const int powerpc_num_opcodes = + sizeof (powerpc_opcodes) / sizeof (powerpc_opcodes[0]); + +/* The macro table. This is only used by the assembler. */ + +/* The expressions of the form (-x ! 31) & (x | 31) have the value 0 + when x=0; 32-x when x is between 1 and 31; are negative if x is + negative; and are 32 or more otherwise. This is what you want + when, for instance, you are emulating a right shift by a + rotate-left-and-mask, because the underlying instructions support + shifts of size 0 but not shifts of size 32. By comparison, when + extracting x bits from some word you want to use just 32-x, because + the underlying instructions don't support extracting 0 bits but do + support extracting the whole word (32 bits in this case). */ + +const struct powerpc_macro powerpc_macros[] = { +{ "extldi", 4, PPC64, "rldicr %0,%1,%3,(%2)-1" }, +{ "extldi.", 4, PPC64, "rldicr. %0,%1,%3,(%2)-1" }, +{ "extrdi", 4, PPC64, "rldicl %0,%1,(%2)+(%3),64-(%2)" }, +{ "extrdi.", 4, PPC64, "rldicl. %0,%1,(%2)+(%3),64-(%2)" }, +{ "insrdi", 4, PPC64, "rldimi %0,%1,64-((%2)+(%3)),%3" }, +{ "insrdi.", 4, PPC64, "rldimi. %0,%1,64-((%2)+(%3)),%3" }, +{ "rotrdi", 3, PPC64, "rldicl %0,%1,(-(%2)!63)&((%2)|63),0" }, +{ "rotrdi.", 3, PPC64, "rldicl. %0,%1,(-(%2)!63)&((%2)|63),0" }, +{ "sldi", 3, PPC64, "rldicr %0,%1,%2,63-(%2)" }, +{ "sldi.", 3, PPC64, "rldicr. %0,%1,%2,63-(%2)" }, +{ "srdi", 3, PPC64, "rldicl %0,%1,(-(%2)!63)&((%2)|63),%2" }, +{ "srdi.", 3, PPC64, "rldicl. %0,%1,(-(%2)!63)&((%2)|63),%2" }, +{ "clrrdi", 3, PPC64, "rldicr %0,%1,0,63-(%2)" }, +{ "clrrdi.", 3, PPC64, "rldicr. %0,%1,0,63-(%2)" }, +{ "clrlsldi",4, PPC64, "rldic %0,%1,%3,(%2)-(%3)" }, +{ "clrlsldi.",4, PPC64, "rldic. %0,%1,%3,(%2)-(%3)" }, + +{ "extlwi", 4, PPCCOM, "rlwinm %0,%1,%3,0,(%2)-1" }, +{ "extlwi.", 4, PPCCOM, "rlwinm. %0,%1,%3,0,(%2)-1" }, +{ "extrwi", 4, PPCCOM, "rlwinm %0,%1,((%2)+(%3))&((%2)+(%3)<>32),32-(%2),31" }, +{ "extrwi.", 4, PPCCOM, "rlwinm. %0,%1,((%2)+(%3))&((%2)+(%3)<>32),32-(%2),31" }, +{ "inslwi", 4, PPCCOM, "rlwimi %0,%1,(-(%3)!31)&((%3)|31),%3,(%2)+(%3)-1" }, +{ "inslwi.", 4, PPCCOM, "rlwimi. %0,%1,(-(%3)!31)&((%3)|31),%3,(%2)+(%3)-1"}, +{ "insrwi", 4, PPCCOM, "rlwimi %0,%1,32-((%2)+(%3)),%3,(%2)+(%3)-1" }, +{ "insrwi.", 4, PPCCOM, "rlwimi. %0,%1,32-((%2)+(%3)),%3,(%2)+(%3)-1"}, +{ "rotrwi", 3, PPCCOM, "rlwinm %0,%1,(-(%2)!31)&((%2)|31),0,31" }, +{ "rotrwi.", 3, PPCCOM, "rlwinm. %0,%1,(-(%2)!31)&((%2)|31),0,31" }, +{ "slwi", 3, PPCCOM, "rlwinm %0,%1,%2,0,31-(%2)" }, +{ "sli", 3, PWRCOM, "rlinm %0,%1,%2,0,31-(%2)" }, +{ "slwi.", 3, PPCCOM, "rlwinm. %0,%1,%2,0,31-(%2)" }, +{ "sli.", 3, PWRCOM, "rlinm. %0,%1,%2,0,31-(%2)" }, +{ "srwi", 3, PPCCOM, "rlwinm %0,%1,(-(%2)!31)&((%2)|31),%2,31" }, +{ "sri", 3, PWRCOM, "rlinm %0,%1,(-(%2)!31)&((%2)|31),%2,31" }, +{ "srwi.", 3, PPCCOM, "rlwinm. %0,%1,(-(%2)!31)&((%2)|31),%2,31" }, +{ "sri.", 3, PWRCOM, "rlinm. %0,%1,(-(%2)!31)&((%2)|31),%2,31" }, +{ "clrrwi", 3, PPCCOM, "rlwinm %0,%1,0,0,31-(%2)" }, +{ "clrrwi.", 3, PPCCOM, "rlwinm. %0,%1,0,0,31-(%2)" }, +{ "clrlslwi",4, PPCCOM, "rlwinm %0,%1,%3,(%2)-(%3),31-(%3)" }, +{ "clrlslwi.",4, PPCCOM, "rlwinm. %0,%1,%3,(%2)-(%3),31-(%3)" }, +}; + +const int powerpc_num_macros = + sizeof (powerpc_macros) / sizeof (powerpc_macros[0]); diff --git a/kernel/fiasco/src/lib/disasm/opcodes/sparc-dis.c b/kernel/fiasco/src/lib/disasm/opcodes/sparc-dis.c new file mode 100644 index 00000000..d7bd6f59 --- /dev/null +++ b/kernel/fiasco/src/lib/disasm/opcodes/sparc-dis.c @@ -0,0 +1,1033 @@ +/* Print SPARC instructions. + Copyright 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, + 2000, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2010 + Free Software Foundation, Inc. + + This file is part of the GNU opcodes library. + + This library is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + It is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + MA 02110-1301, USA. */ + +#include + +#include "sysdep.h" +#include "opcode/sparc.h" +#include "dis-asm.h" +#include "opintl.h" + +/* Bitmask of v9 architectures. */ +#define MASK_V9 ((1 << SPARC_OPCODE_ARCH_V9) \ + | (1 << SPARC_OPCODE_ARCH_V9A) \ + | (1 << SPARC_OPCODE_ARCH_V9B)) +/* 1 if INSN is for v9 only. */ +#define V9_ONLY_P(insn) (! ((insn)->architecture & ~MASK_V9)) +/* 1 if INSN is for v9. */ +#define V9_P(insn) (((insn)->architecture & MASK_V9) != 0) + +/* The sorted opcode table. */ +static const sparc_opcode **sorted_opcodes; + +/* For faster lookup, after insns are sorted they are hashed. */ +/* ??? I think there is room for even more improvement. */ + +#define HASH_SIZE 256 +/* It is important that we only look at insn code bits as that is how the + opcode table is hashed. OPCODE_BITS is a table of valid bits for each + of the main types (0,1,2,3). */ +static int opcode_bits[4] = { 0x01c00000, 0x0, 0x01f80000, 0x01f80000 }; +#define HASH_INSN(INSN) \ + ((((INSN) >> 24) & 0xc0) | (((INSN) & opcode_bits[((INSN) >> 30) & 3]) >> 19)) +typedef struct sparc_opcode_hash +{ + struct sparc_opcode_hash *next; + const sparc_opcode *opcode; +} sparc_opcode_hash; + +static sparc_opcode_hash *opcode_hash_table[HASH_SIZE]; + +/* Sign-extend a value which is N bits long. */ +#define SEX(value, bits) \ + ((((int)(value)) << ((8 * sizeof (int)) - bits)) \ + >> ((8 * sizeof (int)) - bits) ) + +static char *reg_names[] = +{ "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7", + "o0", "o1", "o2", "o3", "o4", "o5", "sp", "o7", + "l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7", + "i0", "i1", "i2", "i3", "i4", "i5", "fp", "i7", + "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", + "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", + "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23", + "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", + "f32", "f33", "f34", "f35", "f36", "f37", "f38", "f39", + "f40", "f41", "f42", "f43", "f44", "f45", "f46", "f47", + "f48", "f49", "f50", "f51", "f52", "f53", "f54", "f55", + "f56", "f57", "f58", "f59", "f60", "f61", "f62", "f63", +/* psr, wim, tbr, fpsr, cpsr are v8 only. */ + "y", "psr", "wim", "tbr", "pc", "npc", "fpsr", "cpsr" +}; + +#define freg_names (®_names[4 * 8]) + +/* These are ordered according to there register number in + rdpr and wrpr insns. */ +static char *v9_priv_reg_names[] = +{ + "tpc", "tnpc", "tstate", "tt", "tick", "tba", "pstate", "tl", + "pil", "cwp", "cansave", "canrestore", "cleanwin", "otherwin", + "wstate", "fq", "gl" + /* "ver" - special cased */ +}; + +/* These are ordered according to there register number in + rdhpr and wrhpr insns. */ +static char *v9_hpriv_reg_names[] = +{ + "hpstate", "htstate", "resv2", "hintp", "resv4", "htba", "hver", + "resv7", "resv8", "resv9", "resv10", "resv11", "resv12", "resv13", + "resv14", "resv15", "resv16", "resv17", "resv18", "resv19", "resv20", + "resv21", "resv22", "resv23", "resv24", "resv25", "resv26", "resv27", + "resv28", "resv29", "resv30", "hstick_cmpr" +}; + +/* These are ordered according to there register number in + rd and wr insns (-16). */ +static char *v9a_asr_reg_names[] = +{ + "pcr", "pic", "dcr", "gsr", "set_softint", "clear_softint", + "softint", "tick_cmpr", "stick", "stick_cmpr", "resv26", + "resv27", "cps" +}; + +/* Macros used to extract instruction fields. Not all fields have + macros defined here, only those which are actually used. */ + +#define X_RD(i) (((i) >> 25) & 0x1f) +#define X_RS1(i) (((i) >> 14) & 0x1f) +#define X_LDST_I(i) (((i) >> 13) & 1) +#define X_ASI(i) (((i) >> 5) & 0xff) +#define X_RS2(i) (((i) >> 0) & 0x1f) +#define X_RS3(i) (((i) >> 9) & 0x1f) +#define X_IMM(i,n) (((i) >> 0) & ((1 << (n)) - 1)) +#define X_SIMM(i,n) SEX (X_IMM ((i), (n)), (n)) +#define X_DISP22(i) (((i) >> 0) & 0x3fffff) +#define X_IMM22(i) X_DISP22 (i) +#define X_DISP30(i) (((i) >> 0) & 0x3fffffff) + +/* These are for v9. */ +#define X_DISP16(i) (((((i) >> 20) & 3) << 14) | (((i) >> 0) & 0x3fff)) +#define X_DISP19(i) (((i) >> 0) & 0x7ffff) +#define X_MEMBAR(i) ((i) & 0x7f) + +/* Here is the union which was used to extract instruction fields + before the shift and mask macros were written. + + union sparc_insn + { + unsigned long int code; + struct + { + unsigned int anop:2; + #define op ldst.anop + unsigned int anrd:5; + #define rd ldst.anrd + unsigned int op3:6; + unsigned int anrs1:5; + #define rs1 ldst.anrs1 + unsigned int i:1; + unsigned int anasi:8; + #define asi ldst.anasi + unsigned int anrs2:5; + #define rs2 ldst.anrs2 + #define shcnt rs2 + } ldst; + struct + { + unsigned int anop:2, anrd:5, op3:6, anrs1:5, i:1; + unsigned int IMM13:13; + #define imm13 IMM13.IMM13 + } IMM13; + struct + { + unsigned int anop:2; + unsigned int a:1; + unsigned int cond:4; + unsigned int op2:3; + unsigned int DISP22:22; + #define disp22 branch.DISP22 + #define imm22 disp22 + } branch; + struct + { + unsigned int anop:2; + unsigned int a:1; + unsigned int z:1; + unsigned int rcond:3; + unsigned int op2:3; + unsigned int DISP16HI:2; + unsigned int p:1; + unsigned int _rs1:5; + unsigned int DISP16LO:14; + } branch16; + struct + { + unsigned int anop:2; + unsigned int adisp30:30; + #define disp30 call.adisp30 + } call; + }; */ + +/* Nonzero if INSN is the opcode for a delayed branch. */ + +static int +is_delayed_branch (unsigned long insn) +{ + sparc_opcode_hash *op; + + for (op = opcode_hash_table[HASH_INSN (insn)]; op; op = op->next) + { + const sparc_opcode *opcode = op->opcode; + + if ((opcode->match & insn) == opcode->match + && (opcode->lose & insn) == 0) + return opcode->flags & F_DELAYED; + } + return 0; +} + +/* extern void qsort (); */ + +/* Records current mask of SPARC_OPCODE_ARCH_FOO values, used to pass value + to compare_opcodes. */ +static unsigned int current_arch_mask; + +/* Given BFD mach number, return a mask of SPARC_OPCODE_ARCH_FOO values. */ + +static int +compute_arch_mask (unsigned long mach) +{ + switch (mach) + { + case 0 : + case bfd_mach_sparc : + return SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_V8); + case bfd_mach_sparc_sparclet : + return SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_SPARCLET); + case bfd_mach_sparc_sparclite : + case bfd_mach_sparc_sparclite_le : + /* sparclites insns are recognized by default (because that's how + they've always been treated, for better or worse). Kludge this by + indicating generic v8 is also selected. */ + return (SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_SPARCLITE) + | SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_V8)); + case bfd_mach_sparc_v8plus : + case bfd_mach_sparc_v9 : + return SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_V9); + case bfd_mach_sparc_v8plusa : + case bfd_mach_sparc_v9a : + return SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_V9A); + case bfd_mach_sparc_v8plusb : + case bfd_mach_sparc_v9b : + return SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_V9B); + } + abort (); +} + +/* Compare opcodes A and B. */ + +static int +compare_opcodes (const void * a, const void * b) +{ + sparc_opcode *op0 = * (sparc_opcode **) a; + sparc_opcode *op1 = * (sparc_opcode **) b; + unsigned long int match0 = op0->match, match1 = op1->match; + unsigned long int lose0 = op0->lose, lose1 = op1->lose; + register unsigned int i; + + /* If one (and only one) insn isn't supported by the current architecture, + prefer the one that is. If neither are supported, but they're both for + the same architecture, continue processing. Otherwise (both unsupported + and for different architectures), prefer lower numbered arch's (fudged + by comparing the bitmasks). */ + if (op0->architecture & current_arch_mask) + { + if (! (op1->architecture & current_arch_mask)) + return -1; + } + else + { + if (op1->architecture & current_arch_mask) + return 1; + else if (op0->architecture != op1->architecture) + return op0->architecture - op1->architecture; + } + + /* If a bit is set in both match and lose, there is something + wrong with the opcode table. */ + if (match0 & lose0) + { + printf + ( /* xgettext:c-format */ + _("Internal error: bad sparc-opcode.h: \"%s\", %#.8lx, %#.8lx\n"), + op0->name, match0, lose0); + op0->lose &= ~op0->match; + lose0 = op0->lose; + } + + if (match1 & lose1) + { + printf + ( /* xgettext:c-format */ + _("Internal error: bad sparc-opcode.h: \"%s\", %#.8lx, %#.8lx\n"), + op1->name, match1, lose1); + op1->lose &= ~op1->match; + lose1 = op1->lose; + } + + /* Because the bits that are variable in one opcode are constant in + another, it is important to order the opcodes in the right order. */ + for (i = 0; i < 32; ++i) + { + unsigned long int x = 1 << i; + int x0 = (match0 & x) != 0; + int x1 = (match1 & x) != 0; + + if (x0 != x1) + return x1 - x0; + } + + for (i = 0; i < 32; ++i) + { + unsigned long int x = 1 << i; + int x0 = (lose0 & x) != 0; + int x1 = (lose1 & x) != 0; + + if (x0 != x1) + return x1 - x0; + } + + /* They are functionally equal. So as long as the opcode table is + valid, we can put whichever one first we want, on aesthetic grounds. */ + + /* Our first aesthetic ground is that aliases defer to real insns. */ + { + int alias_diff = (op0->flags & F_ALIAS) - (op1->flags & F_ALIAS); + + if (alias_diff != 0) + /* Put the one that isn't an alias first. */ + return alias_diff; + } + + /* Except for aliases, two "identical" instructions had + better have the same opcode. This is a sanity check on the table. */ + i = strcmp (op0->name, op1->name); + if (i) + { + if (op0->flags & F_ALIAS) /* If they're both aliases, be arbitrary. */ + return i; + else + printf ( /* xgettext:c-format */ + _("Internal error: bad sparc-opcode.h: \"%s\" == \"%s\"\n"), + op0->name, op1->name); + } + + /* Fewer arguments are preferred. */ + { + int length_diff = strlen (op0->args) - strlen (op1->args); + + if (length_diff != 0) + /* Put the one with fewer arguments first. */ + return length_diff; + } + + /* Put 1+i before i+1. */ + { + char *p0 = (char *) strchr (op0->args, '+'); + char *p1 = (char *) strchr (op1->args, '+'); + + if (p0 && p1) + { + /* There is a plus in both operands. Note that a plus + sign cannot be the first character in args, + so the following [-1]'s are valid. */ + if (p0[-1] == 'i' && p1[1] == 'i') + /* op0 is i+1 and op1 is 1+i, so op1 goes first. */ + return 1; + if (p0[1] == 'i' && p1[-1] == 'i') + /* op0 is 1+i and op1 is i+1, so op0 goes first. */ + return -1; + } + } + + /* Put 1,i before i,1. */ + { + int i0 = strncmp (op0->args, "i,1", 3) == 0; + int i1 = strncmp (op1->args, "i,1", 3) == 0; + + if (i0 ^ i1) + return i0 - i1; + } + + /* They are, as far as we can tell, identical. + Since qsort may have rearranged the table partially, there is + no way to tell which one was first in the opcode table as + written, so just say there are equal. */ + /* ??? This is no longer true now that we sort a vector of pointers, + not the table itself. */ + return 0; +} + +/* Build a hash table from the opcode table. + OPCODE_TABLE is a sorted list of pointers into the opcode table. */ + +static void +build_hash_table (const sparc_opcode **opcode_table, + sparc_opcode_hash **hash_table, + int num_opcodes) +{ + (void)opcode_table; (void)hash_table; (void)num_opcodes; + printf("XXX: %s FIXME\n", __func__); +#if 0 + int i; + int hash_count[HASH_SIZE]; + static sparc_opcode_hash *hash_buf = NULL; + + /* Start at the end of the table and work backwards so that each + chain is sorted. */ + + memset (hash_table, 0, HASH_SIZE * sizeof (hash_table[0])); + memset (hash_count, 0, HASH_SIZE * sizeof (hash_count[0])); + if (hash_buf != NULL) + free (hash_buf); + hash_buf = xmalloc (sizeof (* hash_buf) * num_opcodes); + for (i = num_opcodes - 1; i >= 0; --i) + { + int hash = HASH_INSN (opcode_table[i]->match); + sparc_opcode_hash *h = &hash_buf[i]; + + h->next = hash_table[hash]; + h->opcode = opcode_table[i]; + hash_table[hash] = h; + ++hash_count[hash]; + } +#endif + +#if 0 /* for debugging */ + { + int min_count = num_opcodes, max_count = 0; + int total; + + for (i = 0; i < HASH_SIZE; ++i) + { + if (hash_count[i] < min_count) + min_count = hash_count[i]; + if (hash_count[i] > max_count) + max_count = hash_count[i]; + total += hash_count[i]; + } + + printf ("Opcode hash table stats: min %d, max %d, ave %f\n", + min_count, max_count, (double) total / HASH_SIZE); + } +#endif +} + +/* Print one instruction from MEMADDR on INFO->STREAM. + + We suffix the instruction with a comment that gives the absolute + address involved, as well as its symbolic form, if the instruction + is preceded by a findable `sethi' and it either adds an immediate + displacement to that register, or it is an `add' or `or' instruction + on that register. */ + +int +print_insn_sparc (bfd_vma memaddr, disassemble_info *info) +{ + FILE *stream = info->stream; + bfd_byte buffer[4]; + unsigned long insn; + sparc_opcode_hash *op; + /* Nonzero of opcode table has been initialized. */ + static int opcodes_initialized = 0; + /* bfd mach number of last call. */ + static unsigned long current_mach = 0; + bfd_vma (*getword) (const void *); + + if (!opcodes_initialized + || info->mach != current_mach) + { + int i; + + current_arch_mask = compute_arch_mask (info->mach); + + printf("XXX: %s FIXME\n", __func__); +#if 0 + if (!opcodes_initialized) + sorted_opcodes = + xmalloc (sparc_num_opcodes * sizeof (sparc_opcode *)); + /* Reset the sorted table so we can resort it. */ + for (i = 0; i < sparc_num_opcodes; ++i) + sorted_opcodes[i] = &sparc_opcodes[i]; + qsort ((char *) sorted_opcodes, sparc_num_opcodes, + sizeof (sorted_opcodes[0]), compare_opcodes); +#endif + + build_hash_table (sorted_opcodes, opcode_hash_table, sparc_num_opcodes); + current_mach = info->mach; + opcodes_initialized = 1; + } + + { + int status = + (*info->read_memory_func) (memaddr, buffer, sizeof (buffer), info); + + if (status != 0) + { + (*info->memory_error_func) (status, memaddr, info); + return -1; + } + } + + /* On SPARClite variants such as DANlite (sparc86x), instructions + are always big-endian even when the machine is in little-endian mode. */ + if (info->endian == BFD_ENDIAN_BIG || info->mach == bfd_mach_sparc_sparclite) + getword = bfd_getb32; + else + getword = bfd_getl32; + + insn = getword (buffer); + + info->insn_info_valid = 1; /* We do return this info. */ + info->insn_type = dis_nonbranch; /* Assume non branch insn. */ + info->branch_delay_insns = 0; /* Assume no delay. */ + info->target = 0; /* Assume no target known. */ + + for (op = opcode_hash_table[HASH_INSN (insn)]; op; op = op->next) + { + const sparc_opcode *opcode = op->opcode; + + /* If the insn isn't supported by the current architecture, skip it. */ + if (! (opcode->architecture & current_arch_mask)) + continue; + + if ((opcode->match & insn) == opcode->match + && (opcode->lose & insn) == 0) + { + /* Nonzero means that we have found an instruction which has + the effect of adding or or'ing the imm13 field to rs1. */ + int imm_added_to_rs1 = 0; + int imm_ored_to_rs1 = 0; + + /* Nonzero means that we have found a plus sign in the args + field of the opcode table. */ + int found_plus = 0; + + /* Nonzero means we have an annulled branch. */ + int is_annulled = 0; + + /* Do we have an `add' or `or' instruction combining an + immediate with rs1? */ + if (opcode->match == 0x80102000) /* or */ + imm_ored_to_rs1 = 1; + if (opcode->match == 0x80002000) /* add */ + imm_added_to_rs1 = 1; + + if (X_RS1 (insn) != X_RD (insn) + && strchr (opcode->args, 'r') != 0) + /* Can't do simple format if source and dest are different. */ + continue; + if (X_RS2 (insn) != X_RD (insn) + && strchr (opcode->args, 'O') != 0) + /* Can't do simple format if source and dest are different. */ + continue; + + (*info->fprintf_func) (stream, opcode->name); + + { + const char *s; + + if (opcode->args[0] != ',') + (*info->fprintf_func) (stream, " "); + + for (s = opcode->args; *s != '\0'; ++s) + { + while (*s == ',') + { + (*info->fprintf_func) (stream, ","); + ++s; + switch (*s) + { + case 'a': + (*info->fprintf_func) (stream, "a"); + is_annulled = 1; + ++s; + continue; + case 'N': + (*info->fprintf_func) (stream, "pn"); + ++s; + continue; + + case 'T': + (*info->fprintf_func) (stream, "pt"); + ++s; + continue; + + default: + break; + } + } + + (*info->fprintf_func) (stream, " "); + + switch (*s) + { + case '+': + found_plus = 1; + /* Fall through. */ + + default: + (*info->fprintf_func) (stream, "%c", *s); + break; + + case '#': + (*info->fprintf_func) (stream, "0"); + break; + +#define reg(n) (*info->fprintf_func) (stream, "%%%s", reg_names[n]) + case '1': + case 'r': + reg (X_RS1 (insn)); + break; + + case '2': + case 'O': + reg (X_RS2 (insn)); + break; + + case 'd': + reg (X_RD (insn)); + break; +#undef reg + +#define freg(n) (*info->fprintf_func) (stream, "%%%s", freg_names[n]) +#define fregx(n) (*info->fprintf_func) (stream, "%%%s", freg_names[((n) & ~1) | (((n) & 1) << 5)]) + case 'e': + freg (X_RS1 (insn)); + break; + case 'v': /* Double/even. */ + case 'V': /* Quad/multiple of 4. */ + fregx (X_RS1 (insn)); + break; + + case 'f': + freg (X_RS2 (insn)); + break; + case 'B': /* Double/even. */ + case 'R': /* Quad/multiple of 4. */ + fregx (X_RS2 (insn)); + break; + + case '4': + freg (X_RS3 (insn)); + break; + case '5': /* Double/even. */ + fregx (X_RS3 (insn)); + break; + + case 'g': + freg (X_RD (insn)); + break; + case 'H': /* Double/even. */ + case 'J': /* Quad/multiple of 4. */ + fregx (X_RD (insn)); + break; +#undef freg +#undef fregx + +#define creg(n) (*info->fprintf_func) (stream, "%%c%u", (unsigned int) (n)) + case 'b': + creg (X_RS1 (insn)); + break; + + case 'c': + creg (X_RS2 (insn)); + break; + + case 'D': + creg (X_RD (insn)); + break; +#undef creg + + case 'h': + (*info->fprintf_func) (stream, "%%hi(%#x)", + ((unsigned) 0xFFFFFFFF + & ((int) X_IMM22 (insn) << 10))); + break; + + case 'i': /* 13 bit immediate. */ + case 'I': /* 11 bit immediate. */ + case 'j': /* 10 bit immediate. */ + { + int imm; + + if (*s == 'i') + imm = X_SIMM (insn, 13); + else if (*s == 'I') + imm = X_SIMM (insn, 11); + else + imm = X_SIMM (insn, 10); + + /* Check to see whether we have a 1+i, and take + note of that fact. + + Note: because of the way we sort the table, + we will be matching 1+i rather than i+1, + so it is OK to assume that i is after +, + not before it. */ + if (found_plus) + imm_added_to_rs1 = 1; + + if (imm <= 9) + (*info->fprintf_func) (stream, "%d", imm); + else + (*info->fprintf_func) (stream, "%#x", imm); + } + break; + + case 'X': /* 5 bit unsigned immediate. */ + case 'Y': /* 6 bit unsigned immediate. */ + { + int imm = X_IMM (insn, *s == 'X' ? 5 : 6); + + if (imm <= 9) + (info->fprintf_func) (stream, "%d", imm); + else + (info->fprintf_func) (stream, "%#x", (unsigned) imm); + } + break; + + case '3': + (info->fprintf_func) (stream, "%ld", X_IMM (insn, 3)); + break; + + case 'K': + { + int mask = X_MEMBAR (insn); + int bit = 0x40, printed_one = 0; + const char *name; + + if (mask == 0) + (info->fprintf_func) (stream, "0"); + else + while (bit) + { + if (mask & bit) + { + if (printed_one) + (info->fprintf_func) (stream, "|"); + name = sparc_decode_membar (bit); + (info->fprintf_func) (stream, "%s", name); + printed_one = 1; + } + bit >>= 1; + } + break; + } + + case 'k': + info->target = memaddr + SEX (X_DISP16 (insn), 16) * 4; + (*info->print_address_func) (info->target, info); + break; + + case 'G': + info->target = memaddr + SEX (X_DISP19 (insn), 19) * 4; + (*info->print_address_func) (info->target, info); + break; + + case '6': + case '7': + case '8': + case '9': + (*info->fprintf_func) (stream, "%%fcc%c", *s - '6' + '0'); + break; + + case 'z': + (*info->fprintf_func) (stream, "%%icc"); + break; + + case 'Z': + (*info->fprintf_func) (stream, "%%xcc"); + break; + + case 'E': + (*info->fprintf_func) (stream, "%%ccr"); + break; + + case 's': + (*info->fprintf_func) (stream, "%%fprs"); + break; + + case 'o': + (*info->fprintf_func) (stream, "%%asi"); + break; + + case 'W': + (*info->fprintf_func) (stream, "%%tick"); + break; + + case 'P': + (*info->fprintf_func) (stream, "%%pc"); + break; + + case '?': + if (X_RS1 (insn) == 31) + (*info->fprintf_func) (stream, "%%ver"); + else if ((unsigned) X_RS1 (insn) < 17) + (*info->fprintf_func) (stream, "%%%s", + v9_priv_reg_names[X_RS1 (insn)]); + else + (*info->fprintf_func) (stream, "%%reserved"); + break; + + case '!': + if ((unsigned) X_RD (insn) < 17) + (*info->fprintf_func) (stream, "%%%s", + v9_priv_reg_names[X_RD (insn)]); + else + (*info->fprintf_func) (stream, "%%reserved"); + break; + + case '$': + if ((unsigned) X_RS1 (insn) < 32) + (*info->fprintf_func) (stream, "%%%s", + v9_hpriv_reg_names[X_RS1 (insn)]); + else + (*info->fprintf_func) (stream, "%%reserved"); + break; + + case '%': + if ((unsigned) X_RD (insn) < 32) + (*info->fprintf_func) (stream, "%%%s", + v9_hpriv_reg_names[X_RD (insn)]); + else + (*info->fprintf_func) (stream, "%%reserved"); + break; + + case '/': + if (X_RS1 (insn) < 16 || X_RS1 (insn) > 28) + (*info->fprintf_func) (stream, "%%reserved"); + else + (*info->fprintf_func) (stream, "%%%s", + v9a_asr_reg_names[X_RS1 (insn)-16]); + break; + + case '_': + if (X_RD (insn) < 16 || X_RD (insn) > 28) + (*info->fprintf_func) (stream, "%%reserved"); + else + (*info->fprintf_func) (stream, "%%%s", + v9a_asr_reg_names[X_RD (insn)-16]); + break; + + case '*': + { + const char *name = sparc_decode_prefetch (X_RD (insn)); + + if (name) + (*info->fprintf_func) (stream, "%s", name); + else + (*info->fprintf_func) (stream, "%ld", X_RD (insn)); + break; + } + + case 'M': + (*info->fprintf_func) (stream, "%%asr%ld", X_RS1 (insn)); + break; + + case 'm': + (*info->fprintf_func) (stream, "%%asr%ld", X_RD (insn)); + break; + + case 'L': + info->target = memaddr + SEX (X_DISP30 (insn), 30) * 4; + (*info->print_address_func) (info->target, info); + break; + + case 'n': + (*info->fprintf_func) + (stream, "%#x", SEX (X_DISP22 (insn), 22)); + break; + + case 'l': + info->target = memaddr + SEX (X_DISP22 (insn), 22) * 4; + (*info->print_address_func) (info->target, info); + break; + + case 'A': + { + const char *name = sparc_decode_asi (X_ASI (insn)); + + if (name) + (*info->fprintf_func) (stream, "%s", name); + else + (*info->fprintf_func) (stream, "(%ld)", X_ASI (insn)); + break; + } + + case 'C': + (*info->fprintf_func) (stream, "%%csr"); + break; + + case 'F': + (*info->fprintf_func) (stream, "%%fsr"); + break; + + case '(': + (*info->fprintf_func) (stream, "%%efsr"); + break; + + case 'p': + (*info->fprintf_func) (stream, "%%psr"); + break; + + case 'q': + (*info->fprintf_func) (stream, "%%fq"); + break; + + case 'Q': + (*info->fprintf_func) (stream, "%%cq"); + break; + + case 't': + (*info->fprintf_func) (stream, "%%tbr"); + break; + + case 'w': + (*info->fprintf_func) (stream, "%%wim"); + break; + + case 'x': + (*info->fprintf_func) (stream, "%ld", + ((X_LDST_I (insn) << 8) + + X_ASI (insn))); + break; + + case 'y': + (*info->fprintf_func) (stream, "%%y"); + break; + + case 'u': + case 'U': + { + int val = *s == 'U' ? X_RS1 (insn) : X_RD (insn); + const char *name = sparc_decode_sparclet_cpreg (val); + + if (name) + (*info->fprintf_func) (stream, "%s", name); + else + (*info->fprintf_func) (stream, "%%cpreg(%d)", val); + break; + } + } + } + } + + /* If we are adding or or'ing something to rs1, then + check to see whether the previous instruction was + a sethi to the same register as in the sethi. + If so, attempt to print the result of the add or + or (in this context add and or do the same thing) + and its symbolic value. */ + if (imm_ored_to_rs1 || imm_added_to_rs1) + { + unsigned long prev_insn; + int errcode; + + if (memaddr >= 4) + errcode = + (*info->read_memory_func) + (memaddr - 4, buffer, sizeof (buffer), info); + else + errcode = 1; + + prev_insn = getword (buffer); + + if (errcode == 0) + { + /* If it is a delayed branch, we need to look at the + instruction before the delayed branch. This handles + sequences such as: + + sethi %o1, %hi(_foo), %o1 + call _printf + or %o1, %lo(_foo), %o1 */ + + if (is_delayed_branch (prev_insn)) + { + if (memaddr >= 8) + errcode = (*info->read_memory_func) + (memaddr - 8, buffer, sizeof (buffer), info); + else + errcode = 1; + + prev_insn = getword (buffer); + } + } + + /* If there was a problem reading memory, then assume + the previous instruction was not sethi. */ + if (errcode == 0) + { + /* Is it sethi to the same register? */ + if ((prev_insn & 0xc1c00000) == 0x01000000 + && X_RD (prev_insn) == X_RS1 (insn)) + { + (*info->fprintf_func) (stream, "\t! "); + info->target = + ((unsigned) 0xFFFFFFFF + & ((int) X_IMM22 (prev_insn) << 10)); + if (imm_added_to_rs1) + info->target += X_SIMM (insn, 13); + else + info->target |= X_SIMM (insn, 13); + (*info->print_address_func) (info->target, info); + info->insn_type = dis_dref; + info->data_size = 4; /* FIXME!!! */ + } + } + } + + if (opcode->flags & (F_UNBR|F_CONDBR|F_JSR)) + { + /* FIXME -- check is_annulled flag. */ + (void) is_annulled; + if (opcode->flags & F_UNBR) + info->insn_type = dis_branch; + if (opcode->flags & F_CONDBR) + info->insn_type = dis_condbranch; + if (opcode->flags & F_JSR) + info->insn_type = dis_jsr; + if (opcode->flags & F_DELAYED) + info->branch_delay_insns = 1; + } + + return sizeof (buffer); + } + } + + info->insn_type = dis_noninsn; /* Mark as non-valid instruction. */ + (*info->fprintf_func) (stream, _("unknown")); + return sizeof (buffer); +} diff --git a/kernel/fiasco/src/lib/disasm/opcodes/sparc-opc.c b/kernel/fiasco/src/lib/disasm/opcodes/sparc-opc.c new file mode 100644 index 00000000..a2096c5a --- /dev/null +++ b/kernel/fiasco/src/lib/disasm/opcodes/sparc-opc.c @@ -0,0 +1,2248 @@ +/* Table of opcodes for the sparc. + Copyright 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, + 2000, 2002, 2004, 2005, 2006, 2007, 2008, 2011 + Free Software Foundation, Inc. + + This file is part of the GNU opcodes library. + + This library is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + It is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + License for more details. + + You should have received a copy of the GNU General Public License + along with this file; see the file COPYING. If not, write to the + Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston, + MA 02110-1301, USA. */ + + +/* FIXME-someday: perhaps the ,a's and such should be embedded in the + instruction's name rather than the args. This would make gas faster, pinsn + slower, but would mess up some macros a bit. xoxorich. */ + +#include +#include "sysdep.h" +#include "opcode/sparc.h" + +/* Some defines to make life easy. */ +#define MASK_V6 SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_V6) +#define MASK_V7 SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_V7) +#define MASK_V8 SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_V8) +#define MASK_SPARCLET SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_SPARCLET) +#define MASK_SPARCLITE SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_SPARCLITE) +#define MASK_V9 SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_V9) +#define MASK_V9A SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_V9A) +#define MASK_V9B SPARC_OPCODE_ARCH_MASK (SPARC_OPCODE_ARCH_V9B) + +/* Bit masks of architectures supporting the insn. */ + +#define v6 (MASK_V6 | MASK_V7 | MASK_V8 | MASK_SPARCLET \ + | MASK_SPARCLITE | MASK_V9 | MASK_V9A | MASK_V9B) +/* v6 insns not supported on the sparclet. */ +#define v6notlet (MASK_V6 | MASK_V7 | MASK_V8 \ + | MASK_SPARCLITE | MASK_V9 | MASK_V9A | MASK_V9B) +#define v7 (MASK_V7 | MASK_V8 | MASK_SPARCLET \ + | MASK_SPARCLITE | MASK_V9 | MASK_V9A | MASK_V9B) +/* Although not all insns are implemented in hardware, sparclite is defined + to be a superset of v8. Unimplemented insns trap and are then theoretically + implemented in software. + It's not clear that the same is true for sparclet, although the docs + suggest it is. Rather than complicating things, the sparclet assembler + recognizes all v8 insns. */ +#define v8 (MASK_V8 | MASK_SPARCLET | MASK_SPARCLITE \ + | MASK_V9 | MASK_V9A | MASK_V9B) +#define sparclet (MASK_SPARCLET) +#define sparclite (MASK_SPARCLITE) +#define v9 (MASK_V9 | MASK_V9A | MASK_V9B) +#define v9a (MASK_V9A | MASK_V9B) +#define v9b (MASK_V9B) +/* v6 insns not supported by v9. */ +#define v6notv9 (MASK_V6 | MASK_V7 | MASK_V8 \ + | MASK_SPARCLET | MASK_SPARCLITE) +/* v9a instructions which would appear to be aliases to v9's impdep's + otherwise. */ +#define v9notv9a (MASK_V9) + +/* Table of opcode architectures. + The order is defined in opcode/sparc.h. */ + +const struct sparc_opcode_arch sparc_opcode_archs[] = +{ + { "v6", MASK_V6 }, + { "v7", MASK_V6 | MASK_V7 }, + { "v8", MASK_V6 | MASK_V7 | MASK_V8 }, + { "sparclet", MASK_V6 | MASK_V7 | MASK_V8 | MASK_SPARCLET }, + { "sparclite", MASK_V6 | MASK_V7 | MASK_V8 | MASK_SPARCLITE }, + /* ??? Don't some v8 priviledged insns conflict with v9? */ + { "v9", MASK_V6 | MASK_V7 | MASK_V8 | MASK_V9 }, + /* v9 with ultrasparc additions */ + { "v9a", MASK_V6 | MASK_V7 | MASK_V8 | MASK_V9 | MASK_V9A }, + /* v9 with cheetah additions */ + { "v9b", MASK_V6 | MASK_V7 | MASK_V8 | MASK_V9 | MASK_V9A | MASK_V9B }, + { NULL, 0 } +}; + +/* Given NAME, return it's architecture entry. */ + +enum sparc_opcode_arch_val +sparc_opcode_lookup_arch (const char *name) +{ + const struct sparc_opcode_arch *p; + + for (p = &sparc_opcode_archs[0]; p->name; ++p) + if (strcmp (name, p->name) == 0) + return (enum sparc_opcode_arch_val) (p - &sparc_opcode_archs[0]); + + return SPARC_OPCODE_ARCH_BAD; +} + +/* Branch condition field. */ +#define COND(x) (((x) & 0xf) << 25) + +/* v9: Move (MOVcc and FMOVcc) condition field. */ +#define MCOND(x,i_or_f) ((((i_or_f) & 1) << 18) | (((x) >> 11) & (0xf << 14))) /* v9 */ + +/* v9: Move register (MOVRcc and FMOVRcc) condition field. */ +#define RCOND(x) (((x) & 0x7) << 10) /* v9 */ + +#define CONDA (COND (0x8)) +#define CONDCC (COND (0xd)) +#define CONDCS (COND (0x5)) +#define CONDE (COND (0x1)) +#define CONDG (COND (0xa)) +#define CONDGE (COND (0xb)) +#define CONDGU (COND (0xc)) +#define CONDL (COND (0x3)) +#define CONDLE (COND (0x2)) +#define CONDLEU (COND (0x4)) +#define CONDN (COND (0x0)) +#define CONDNE (COND (0x9)) +#define CONDNEG (COND (0x6)) +#define CONDPOS (COND (0xe)) +#define CONDVC (COND (0xf)) +#define CONDVS (COND (0x7)) + +#define CONDNZ CONDNE +#define CONDZ CONDE +#define CONDGEU CONDCC +#define CONDLU CONDCS + +#define FCONDA (COND (0x8)) +#define FCONDE (COND (0x9)) +#define FCONDG (COND (0x6)) +#define FCONDGE (COND (0xb)) +#define FCONDL (COND (0x4)) +#define FCONDLE (COND (0xd)) +#define FCONDLG (COND (0x2)) +#define FCONDN (COND (0x0)) +#define FCONDNE (COND (0x1)) +#define FCONDO (COND (0xf)) +#define FCONDU (COND (0x7)) +#define FCONDUE (COND (0xa)) +#define FCONDUG (COND (0x5)) +#define FCONDUGE (COND (0xc)) +#define FCONDUL (COND (0x3)) +#define FCONDULE (COND (0xe)) + +#define FCONDNZ FCONDNE +#define FCONDZ FCONDE + +#define ICC (0) /* v9 */ +#define XCC (1 << 12) /* v9 */ +#define FCC(x) (((x) & 0x3) << 11) /* v9 */ +#define FBFCC(x) (((x) & 0x3) << 20) /* v9 */ + +/* The order of the opcodes in the table is significant: + + * The assembler requires that all instances of the same mnemonic must + be consecutive. If they aren't, the assembler will bomb at runtime. + + * The disassembler should not care about the order of the opcodes. */ + +/* Entries for commutative arithmetic operations. */ +/* ??? More entries can make use of this. */ +#define COMMUTEOP(opcode, op3, arch_mask) \ +{ opcode, F3(2, op3, 0), F3(~2, ~op3, ~0)|ASI(~0), "1,2,d", 0, arch_mask }, \ +{ opcode, F3(2, op3, 1), F3(~2, ~op3, ~1), "1,i,d", 0, arch_mask }, \ +{ opcode, F3(2, op3, 1), F3(~2, ~op3, ~1), "i,1,d", 0, arch_mask } + +const struct sparc_opcode sparc_opcodes[] = { + +{ "ld", F3(3, 0x00, 0), F3(~3, ~0x00, ~0), "[1+2],d", 0, v6 }, +{ "ld", F3(3, 0x00, 0), F3(~3, ~0x00, ~0)|RS2_G0, "[1],d", 0, v6 }, /* ld [rs1+%g0],d */ +{ "ld", F3(3, 0x00, 1), F3(~3, ~0x00, ~1), "[1+i],d", 0, v6 }, +{ "ld", F3(3, 0x00, 1), F3(~3, ~0x00, ~1), "[i+1],d", 0, v6 }, +{ "ld", F3(3, 0x00, 1), F3(~3, ~0x00, ~1)|RS1_G0, "[i],d", 0, v6 }, +{ "ld", F3(3, 0x00, 1), F3(~3, ~0x00, ~1)|SIMM13(~0), "[1],d", 0, v6 }, /* ld [rs1+0],d */ +{ "ld", F3(3, 0x20, 0), F3(~3, ~0x20, ~0), "[1+2],g", 0, v6 }, +{ "ld", F3(3, 0x20, 0), F3(~3, ~0x20, ~0)|RS2_G0, "[1],g", 0, v6 }, /* ld [rs1+%g0],d */ +{ "ld", F3(3, 0x20, 1), F3(~3, ~0x20, ~1), "[1+i],g", 0, v6 }, +{ "ld", F3(3, 0x20, 1), F3(~3, ~0x20, ~1), "[i+1],g", 0, v6 }, +{ "ld", F3(3, 0x20, 1), F3(~3, ~0x20, ~1)|RS1_G0, "[i],g", 0, v6 }, +{ "ld", F3(3, 0x20, 1), F3(~3, ~0x20, ~1)|SIMM13(~0), "[1],g", 0, v6 }, /* ld [rs1+0],d */ + +{ "ld", F3(3, 0x21, 0), F3(~3, ~0x21, ~0)|RD(~0), "[1+2],F", 0, v6 }, +{ "ld", F3(3, 0x21, 0), F3(~3, ~0x21, ~0)|RS2_G0|RD(~0),"[1],F", 0, v6 }, /* ld [rs1+%g0],d */ +{ "ld", F3(3, 0x21, 1), F3(~3, ~0x21, ~1)|RD(~0), "[1+i],F", 0, v6 }, +{ "ld", F3(3, 0x21, 1), F3(~3, ~0x21, ~1)|RD(~0), "[i+1],F", 0, v6 }, +{ "ld", F3(3, 0x21, 1), F3(~3, ~0x21, ~1)|RS1_G0|RD(~0),"[i],F", 0, v6 }, +{ "ld", F3(3, 0x21, 1), F3(~3, ~0x21, ~1)|SIMM13(~0)|RD(~0),"[1],F", 0, v6 }, /* ld [rs1+0],d */ + +{ "ld", F3(3, 0x30, 0), F3(~3, ~0x30, ~0), "[1+2],D", 0, v6notv9 }, +{ "ld", F3(3, 0x30, 0), F3(~3, ~0x30, ~0)|RS2_G0, "[1],D", 0, v6notv9 }, /* ld [rs1+%g0],d */ +{ "ld", F3(3, 0x30, 1), F3(~3, ~0x30, ~1), "[1+i],D", 0, v6notv9 }, +{ "ld", F3(3, 0x30, 1), F3(~3, ~0x30, ~1), "[i+1],D", 0, v6notv9 }, +{ "ld", F3(3, 0x30, 1), F3(~3, ~0x30, ~1)|RS1_G0, "[i],D", 0, v6notv9 }, +{ "ld", F3(3, 0x30, 1), F3(~3, ~0x30, ~1)|SIMM13(~0), "[1],D", 0, v6notv9 }, /* ld [rs1+0],d */ +{ "ld", F3(3, 0x31, 0), F3(~3, ~0x31, ~0), "[1+2],C", 0, v6notv9 }, +{ "ld", F3(3, 0x31, 0), F3(~3, ~0x31, ~0)|RS2_G0, "[1],C", 0, v6notv9 }, /* ld [rs1+%g0],d */ +{ "ld", F3(3, 0x31, 1), F3(~3, ~0x31, ~1), "[1+i],C", 0, v6notv9 }, +{ "ld", F3(3, 0x31, 1), F3(~3, ~0x31, ~1), "[i+1],C", 0, v6notv9 }, +{ "ld", F3(3, 0x31, 1), F3(~3, ~0x31, ~1)|RS1_G0, "[i],C", 0, v6notv9 }, +{ "ld", F3(3, 0x31, 1), F3(~3, ~0x31, ~1)|SIMM13(~0), "[1],C", 0, v6notv9 }, /* ld [rs1+0],d */ + +/* The v9 LDUW is the same as the old 'ld' opcode, it is not the same as the + 'ld' pseudo-op in v9. */ +{ "lduw", F3(3, 0x00, 0), F3(~3, ~0x00, ~0), "[1+2],d", F_ALIAS, v9 }, +{ "lduw", F3(3, 0x00, 0), F3(~3, ~0x00, ~0)|RS2_G0, "[1],d", F_ALIAS, v9 }, /* ld [rs1+%g0],d */ +{ "lduw", F3(3, 0x00, 1), F3(~3, ~0x00, ~1), "[1+i],d", F_ALIAS, v9 }, +{ "lduw", F3(3, 0x00, 1), F3(~3, ~0x00, ~1), "[i+1],d", F_ALIAS, v9 }, +{ "lduw", F3(3, 0x00, 1), F3(~3, ~0x00, ~1)|RS1_G0, "[i],d", F_ALIAS, v9 }, +{ "lduw", F3(3, 0x00, 1), F3(~3, ~0x00, ~1)|SIMM13(~0), "[1],d", F_ALIAS, v9 }, /* ld [rs1+0],d */ + +{ "ldd", F3(3, 0x03, 0), F3(~3, ~0x03, ~0)|ASI(~0), "[1+2],d", 0, v6 }, +{ "ldd", F3(3, 0x03, 0), F3(~3, ~0x03, ~0)|ASI_RS2(~0), "[1],d", 0, v6 }, /* ldd [rs1+%g0],d */ +{ "ldd", F3(3, 0x03, 1), F3(~3, ~0x03, ~1), "[1+i],d", 0, v6 }, +{ "ldd", F3(3, 0x03, 1), F3(~3, ~0x03, ~1), "[i+1],d", 0, v6 }, +{ "ldd", F3(3, 0x03, 1), F3(~3, ~0x03, ~1)|RS1_G0, "[i],d", 0, v6 }, +{ "ldd", F3(3, 0x03, 1), F3(~3, ~0x03, ~1)|SIMM13(~0), "[1],d", 0, v6 }, /* ldd [rs1+0],d */ +{ "ldd", F3(3, 0x23, 0), F3(~3, ~0x23, ~0)|ASI(~0), "[1+2],H", 0, v6 }, +{ "ldd", F3(3, 0x23, 0), F3(~3, ~0x23, ~0)|ASI_RS2(~0), "[1],H", 0, v6 }, /* ldd [rs1+%g0],d */ +{ "ldd", F3(3, 0x23, 1), F3(~3, ~0x23, ~1), "[1+i],H", 0, v6 }, +{ "ldd", F3(3, 0x23, 1), F3(~3, ~0x23, ~1), "[i+1],H", 0, v6 }, +{ "ldd", F3(3, 0x23, 1), F3(~3, ~0x23, ~1)|RS1_G0, "[i],H", 0, v6 }, +{ "ldd", F3(3, 0x23, 1), F3(~3, ~0x23, ~1)|SIMM13(~0), "[1],H", 0, v6 }, /* ldd [rs1+0],d */ + +{ "ldd", F3(3, 0x33, 0), F3(~3, ~0x33, ~0)|ASI(~0), "[1+2],D", 0, v6notv9 }, +{ "ldd", F3(3, 0x33, 0), F3(~3, ~0x33, ~0)|ASI_RS2(~0), "[1],D", 0, v6notv9 }, /* ldd [rs1+%g0],d */ +{ "ldd", F3(3, 0x33, 1), F3(~3, ~0x33, ~1), "[1+i],D", 0, v6notv9 }, +{ "ldd", F3(3, 0x33, 1), F3(~3, ~0x33, ~1), "[i+1],D", 0, v6notv9 }, +{ "ldd", F3(3, 0x33, 1), F3(~3, ~0x33, ~1)|RS1_G0, "[i],D", 0, v6notv9 }, +{ "ldd", F3(3, 0x33, 1), F3(~3, ~0x33, ~1)|SIMM13(~0), "[1],D", 0, v6notv9 }, /* ldd [rs1+0],d */ + +{ "ldq", F3(3, 0x22, 0), F3(~3, ~0x22, ~0)|ASI(~0), "[1+2],J", 0, v9 }, +{ "ldq", F3(3, 0x22, 0), F3(~3, ~0x22, ~0)|ASI_RS2(~0), "[1],J", 0, v9 }, /* ldd [rs1+%g0],d */ +{ "ldq", F3(3, 0x22, 1), F3(~3, ~0x22, ~1), "[1+i],J", 0, v9 }, +{ "ldq", F3(3, 0x22, 1), F3(~3, ~0x22, ~1), "[i+1],J", 0, v9 }, +{ "ldq", F3(3, 0x22, 1), F3(~3, ~0x22, ~1)|RS1_G0, "[i],J", 0, v9 }, +{ "ldq", F3(3, 0x22, 1), F3(~3, ~0x22, ~1)|SIMM13(~0), "[1],J", 0, v9 }, /* ldd [rs1+0],d */ + +{ "ldsb", F3(3, 0x09, 0), F3(~3, ~0x09, ~0)|ASI(~0), "[1+2],d", 0, v6 }, +{ "ldsb", F3(3, 0x09, 0), F3(~3, ~0x09, ~0)|ASI_RS2(~0), "[1],d", 0, v6 }, /* ldsb [rs1+%g0],d */ +{ "ldsb", F3(3, 0x09, 1), F3(~3, ~0x09, ~1), "[1+i],d", 0, v6 }, +{ "ldsb", F3(3, 0x09, 1), F3(~3, ~0x09, ~1), "[i+1],d", 0, v6 }, +{ "ldsb", F3(3, 0x09, 1), F3(~3, ~0x09, ~1)|RS1_G0, "[i],d", 0, v6 }, +{ "ldsb", F3(3, 0x09, 1), F3(~3, ~0x09, ~1)|SIMM13(~0), "[1],d", 0, v6 }, /* ldsb [rs1+0],d */ + +{ "ldsh", F3(3, 0x0a, 0), F3(~3, ~0x0a, ~0)|ASI_RS2(~0), "[1],d", 0, v6 }, /* ldsh [rs1+%g0],d */ +{ "ldsh", F3(3, 0x0a, 0), F3(~3, ~0x0a, ~0)|ASI(~0), "[1+2],d", 0, v6 }, +{ "ldsh", F3(3, 0x0a, 1), F3(~3, ~0x0a, ~1), "[1+i],d", 0, v6 }, +{ "ldsh", F3(3, 0x0a, 1), F3(~3, ~0x0a, ~1), "[i+1],d", 0, v6 }, +{ "ldsh", F3(3, 0x0a, 1), F3(~3, ~0x0a, ~1)|RS1_G0, "[i],d", 0, v6 }, +{ "ldsh", F3(3, 0x0a, 1), F3(~3, ~0x0a, ~1)|SIMM13(~0), "[1],d", 0, v6 }, /* ldsh [rs1+0],d */ + +{ "ldstub", F3(3, 0x0d, 0), F3(~3, ~0x0d, ~0)|ASI(~0), "[1+2],d", 0, v6 }, +{ "ldstub", F3(3, 0x0d, 0), F3(~3, ~0x0d, ~0)|ASI_RS2(~0), "[1],d", 0, v6 }, /* ldstub [rs1+%g0],d */ +{ "ldstub", F3(3, 0x0d, 1), F3(~3, ~0x0d, ~1), "[1+i],d", 0, v6 }, +{ "ldstub", F3(3, 0x0d, 1), F3(~3, ~0x0d, ~1), "[i+1],d", 0, v6 }, +{ "ldstub", F3(3, 0x0d, 1), F3(~3, ~0x0d, ~1)|RS1_G0, "[i],d", 0, v6 }, +{ "ldstub", F3(3, 0x0d, 1), F3(~3, ~0x0d, ~1)|SIMM13(~0), "[1],d", 0, v6 }, /* ldstub [rs1+0],d */ + +{ "ldsw", F3(3, 0x08, 0), F3(~3, ~0x08, ~0)|ASI(~0), "[1+2],d", 0, v9 }, +{ "ldsw", F3(3, 0x08, 0), F3(~3, ~0x08, ~0)|ASI_RS2(~0), "[1],d", 0, v9 }, /* ldsw [rs1+%g0],d */ +{ "ldsw", F3(3, 0x08, 1), F3(~3, ~0x08, ~1), "[1+i],d", 0, v9 }, +{ "ldsw", F3(3, 0x08, 1), F3(~3, ~0x08, ~1), "[i+1],d", 0, v9 }, +{ "ldsw", F3(3, 0x08, 1), F3(~3, ~0x08, ~1)|RS1_G0, "[i],d", 0, v9 }, +{ "ldsw", F3(3, 0x08, 1), F3(~3, ~0x08, ~1)|SIMM13(~0), "[1],d", 0, v9 }, /* ldsw [rs1+0],d */ + +{ "ldub", F3(3, 0x01, 0), F3(~3, ~0x01, ~0)|ASI(~0), "[1+2],d", 0, v6 }, +{ "ldub", F3(3, 0x01, 0), F3(~3, ~0x01, ~0)|ASI_RS2(~0), "[1],d", 0, v6 }, /* ldub [rs1+%g0],d */ +{ "ldub", F3(3, 0x01, 1), F3(~3, ~0x01, ~1), "[1+i],d", 0, v6 }, +{ "ldub", F3(3, 0x01, 1), F3(~3, ~0x01, ~1), "[i+1],d", 0, v6 }, +{ "ldub", F3(3, 0x01, 1), F3(~3, ~0x01, ~1)|RS1_G0, "[i],d", 0, v6 }, +{ "ldub", F3(3, 0x01, 1), F3(~3, ~0x01, ~1)|SIMM13(~0), "[1],d", 0, v6 }, /* ldub [rs1+0],d */ + +{ "lduh", F3(3, 0x02, 0), F3(~3, ~0x02, ~0)|ASI(~0), "[1+2],d", 0, v6 }, +{ "lduh", F3(3, 0x02, 0), F3(~3, ~0x02, ~0)|ASI_RS2(~0), "[1],d", 0, v6 }, /* lduh [rs1+%g0],d */ +{ "lduh", F3(3, 0x02, 1), F3(~3, ~0x02, ~1), "[1+i],d", 0, v6 }, +{ "lduh", F3(3, 0x02, 1), F3(~3, ~0x02, ~1), "[i+1],d", 0, v6 }, +{ "lduh", F3(3, 0x02, 1), F3(~3, ~0x02, ~1)|RS1_G0, "[i],d", 0, v6 }, +{ "lduh", F3(3, 0x02, 1), F3(~3, ~0x02, ~1)|SIMM13(~0), "[1],d", 0, v6 }, /* lduh [rs1+0],d */ + +{ "ldx", F3(3, 0x0b, 0), F3(~3, ~0x0b, ~0)|ASI(~0), "[1+2],d", 0, v9 }, +{ "ldx", F3(3, 0x0b, 0), F3(~3, ~0x0b, ~0)|ASI_RS2(~0), "[1],d", 0, v9 }, /* ldx [rs1+%g0],d */ +{ "ldx", F3(3, 0x0b, 1), F3(~3, ~0x0b, ~1), "[1+i],d", 0, v9 }, +{ "ldx", F3(3, 0x0b, 1), F3(~3, ~0x0b, ~1), "[i+1],d", 0, v9 }, +{ "ldx", F3(3, 0x0b, 1), F3(~3, ~0x0b, ~1)|RS1_G0, "[i],d", 0, v9 }, +{ "ldx", F3(3, 0x0b, 1), F3(~3, ~0x0b, ~1)|SIMM13(~0), "[1],d", 0, v9 }, /* ldx [rs1+0],d */ + +{ "ldx", F3(3, 0x21, 0)|RD(1), F3(~3, ~0x21, ~0)|RD(~1), "[1+2],F", 0, v9 }, +{ "ldx", F3(3, 0x21, 0)|RD(1), F3(~3, ~0x21, ~0)|RS2_G0|RD(~1), "[1],F", 0, v9 }, /* ld [rs1+%g0],d */ +{ "ldx", F3(3, 0x21, 1)|RD(1), F3(~3, ~0x21, ~1)|RD(~1), "[1+i],F", 0, v9 }, +{ "ldx", F3(3, 0x21, 1)|RD(1), F3(~3, ~0x21, ~1)|RD(~1), "[i+1],F", 0, v9 }, +{ "ldx", F3(3, 0x21, 1)|RD(1), F3(~3, ~0x21, ~1)|RS1_G0|RD(~1), "[i],F", 0, v9 }, +{ "ldx", F3(3, 0x21, 1)|RD(1), F3(~3, ~0x21, ~1)|SIMM13(~0)|RD(~1),"[1],F", 0, v9 }, /* ld [rs1+0],d */ + +{ "ldx", F3(3, 0x21, 0)|RD(3), F3(~3, ~0x21, ~0)|RD(~3), "[1+2],(", 0, v9b }, +{ "ldx", F3(3, 0x21, 0)|RD(3), F3(~3, ~0x21, ~0)|RS2_G0|RD(~3),"[1],(", 0, v9b }, +{ "ldx", F3(3, 0x21, 1)|RD(3), F3(~3, ~0x21, ~1)|RD(~3), "[1+i],(", 0, v9b }, +{ "ldx", F3(3, 0x21, 1)|RD(3), F3(~3, ~0x21, ~1)|RD(~3), "[i+1],(", 0, v9b }, +{ "ldx", F3(3, 0x21, 1)|RD(3), F3(~3, ~0x21, ~1)|RS1_G0|RD(~3),"[i],(", 0, v9b }, +{ "ldx", F3(3, 0x21, 1)|RD(3), F3(~3, ~0x21, ~1)|SIMM13(~0)|RD(~3),"[1],(", 0, v9b }, + +{ "lda", F3(3, 0x10, 0), F3(~3, ~0x10, ~0), "[1+2]A,d", 0, v6 }, +{ "lda", F3(3, 0x10, 0), F3(~3, ~0x10, ~0)|RS2_G0, "[1]A,d", 0, v6 }, /* lda [rs1+%g0],d */ +{ "lda", F3(3, 0x10, 1), F3(~3, ~0x10, ~1), "[1+i]o,d", 0, v9 }, +{ "lda", F3(3, 0x10, 1), F3(~3, ~0x10, ~1), "[i+1]o,d", 0, v9 }, +{ "lda", F3(3, 0x10, 1), F3(~3, ~0x10, ~1)|RS1_G0, "[i]o,d", 0, v9 }, +{ "lda", F3(3, 0x10, 1), F3(~3, ~0x10, ~1)|SIMM13(~0), "[1]o,d", 0, v9 }, /* ld [rs1+0],d */ +{ "lda", F3(3, 0x30, 0), F3(~3, ~0x30, ~0), "[1+2]A,g", 0, v9 }, +{ "lda", F3(3, 0x30, 0), F3(~3, ~0x30, ~0)|RS2_G0, "[1]A,g", 0, v9 }, /* lda [rs1+%g0],d */ +{ "lda", F3(3, 0x30, 1), F3(~3, ~0x30, ~1), "[1+i]o,g", 0, v9 }, +{ "lda", F3(3, 0x30, 1), F3(~3, ~0x30, ~1), "[i+1]o,g", 0, v9 }, +{ "lda", F3(3, 0x30, 1), F3(~3, ~0x30, ~1)|RS1_G0, "[i]o,g", 0, v9 }, +{ "lda", F3(3, 0x30, 1), F3(~3, ~0x30, ~1)|SIMM13(~0), "[1]o,g", 0, v9 }, /* ld [rs1+0],d */ + +{ "ldda", F3(3, 0x13, 0), F3(~3, ~0x13, ~0), "[1+2]A,d", 0, v6 }, +{ "ldda", F3(3, 0x13, 0), F3(~3, ~0x13, ~0)|RS2_G0, "[1]A,d", 0, v6 }, /* ldda [rs1+%g0],d */ +{ "ldda", F3(3, 0x13, 1), F3(~3, ~0x13, ~1), "[1+i]o,d", 0, v9 }, +{ "ldda", F3(3, 0x13, 1), F3(~3, ~0x13, ~1), "[i+1]o,d", 0, v9 }, +{ "ldda", F3(3, 0x13, 1), F3(~3, ~0x13, ~1)|RS1_G0, "[i]o,d", 0, v9 }, +{ "ldda", F3(3, 0x13, 1), F3(~3, ~0x13, ~1)|SIMM13(~0), "[1]o,d", 0, v9 }, /* ld [rs1+0],d */ + +{ "ldda", F3(3, 0x33, 0), F3(~3, ~0x33, ~0), "[1+2]A,H", 0, v9 }, +{ "ldda", F3(3, 0x33, 0), F3(~3, ~0x33, ~0)|RS2_G0, "[1]A,H", 0, v9 }, /* ldda [rs1+%g0],d */ +{ "ldda", F3(3, 0x33, 1), F3(~3, ~0x33, ~1), "[1+i]o,H", 0, v9 }, +{ "ldda", F3(3, 0x33, 1), F3(~3, ~0x33, ~1), "[i+1]o,H", 0, v9 }, +{ "ldda", F3(3, 0x33, 1), F3(~3, ~0x33, ~1)|RS1_G0, "[i]o,H", 0, v9 }, +{ "ldda", F3(3, 0x33, 1), F3(~3, ~0x33, ~1)|SIMM13(~0), "[1]o,H", 0, v9 }, /* ld [rs1+0],d */ + +{ "ldqa", F3(3, 0x32, 0), F3(~3, ~0x32, ~0), "[1+2]A,J", 0, v9 }, +{ "ldqa", F3(3, 0x32, 0), F3(~3, ~0x32, ~0)|RS2_G0, "[1]A,J", 0, v9 }, /* ldd [rs1+%g0],d */ +{ "ldqa", F3(3, 0x32, 1), F3(~3, ~0x32, ~1), "[1+i]o,J", 0, v9 }, +{ "ldqa", F3(3, 0x32, 1), F3(~3, ~0x32, ~1), "[i+1]o,J", 0, v9 }, +{ "ldqa", F3(3, 0x32, 1), F3(~3, ~0x32, ~1)|RS1_G0, "[i]o,J", 0, v9 }, +{ "ldqa", F3(3, 0x32, 1), F3(~3, ~0x32, ~1)|SIMM13(~0), "[1]o,J", 0, v9 }, /* ldd [rs1+0],d */ + +{ "ldsba", F3(3, 0x19, 0), F3(~3, ~0x19, ~0), "[1+2]A,d", 0, v6 }, +{ "ldsba", F3(3, 0x19, 0), F3(~3, ~0x19, ~0)|RS2_G0, "[1]A,d", 0, v6 }, /* ldsba [rs1+%g0],d */ +{ "ldsba", F3(3, 0x19, 1), F3(~3, ~0x19, ~1), "[1+i]o,d", 0, v9 }, +{ "ldsba", F3(3, 0x19, 1), F3(~3, ~0x19, ~1), "[i+1]o,d", 0, v9 }, +{ "ldsba", F3(3, 0x19, 1), F3(~3, ~0x19, ~1)|RS1_G0, "[i]o,d", 0, v9 }, +{ "ldsba", F3(3, 0x19, 1), F3(~3, ~0x19, ~1)|SIMM13(~0), "[1]o,d", 0, v9 }, /* ld [rs1+0],d */ + +{ "ldsha", F3(3, 0x1a, 0), F3(~3, ~0x1a, ~0), "[1+2]A,d", 0, v6 }, +{ "ldsha", F3(3, 0x1a, 0), F3(~3, ~0x1a, ~0)|RS2_G0, "[1]A,d", 0, v6 }, /* ldsha [rs1+%g0],d */ +{ "ldsha", F3(3, 0x1a, 1), F3(~3, ~0x1a, ~1), "[1+i]o,d", 0, v9 }, +{ "ldsha", F3(3, 0x1a, 1), F3(~3, ~0x1a, ~1), "[i+1]o,d", 0, v9 }, +{ "ldsha", F3(3, 0x1a, 1), F3(~3, ~0x1a, ~1)|RS1_G0, "[i]o,d", 0, v9 }, +{ "ldsha", F3(3, 0x1a, 1), F3(~3, ~0x1a, ~1)|SIMM13(~0), "[1]o,d", 0, v9 }, /* ld [rs1+0],d */ + +{ "ldstuba", F3(3, 0x1d, 0), F3(~3, ~0x1d, ~0), "[1+2]A,d", 0, v6 }, +{ "ldstuba", F3(3, 0x1d, 0), F3(~3, ~0x1d, ~0)|RS2_G0, "[1]A,d", 0, v6 }, /* ldstuba [rs1+%g0],d */ +{ "ldstuba", F3(3, 0x1d, 1), F3(~3, ~0x1d, ~1), "[1+i]o,d", 0, v9 }, +{ "ldstuba", F3(3, 0x1d, 1), F3(~3, ~0x1d, ~1), "[i+1]o,d", 0, v9 }, +{ "ldstuba", F3(3, 0x1d, 1), F3(~3, ~0x1d, ~1)|RS1_G0, "[i]o,d", 0, v9 }, +{ "ldstuba", F3(3, 0x1d, 1), F3(~3, ~0x1d, ~1)|SIMM13(~0), "[1]o,d", 0, v9 }, /* ld [rs1+0],d */ + +{ "ldswa", F3(3, 0x18, 0), F3(~3, ~0x18, ~0), "[1+2]A,d", 0, v9 }, +{ "ldswa", F3(3, 0x18, 0), F3(~3, ~0x18, ~0)|RS2_G0, "[1]A,d", 0, v9 }, /* lda [rs1+%g0],d */ +{ "ldswa", F3(3, 0x18, 1), F3(~3, ~0x18, ~1), "[1+i]o,d", 0, v9 }, +{ "ldswa", F3(3, 0x18, 1), F3(~3, ~0x18, ~1), "[i+1]o,d", 0, v9 }, +{ "ldswa", F3(3, 0x18, 1), F3(~3, ~0x18, ~1)|RS1_G0, "[i]o,d", 0, v9 }, +{ "ldswa", F3(3, 0x18, 1), F3(~3, ~0x18, ~1)|SIMM13(~0), "[1]o,d", 0, v9 }, /* ld [rs1+0],d */ + +{ "lduba", F3(3, 0x11, 0), F3(~3, ~0x11, ~0), "[1+2]A,d", 0, v6 }, +{ "lduba", F3(3, 0x11, 0), F3(~3, ~0x11, ~0)|RS2_G0, "[1]A,d", 0, v6 }, /* lduba [rs1+%g0],d */ +{ "lduba", F3(3, 0x11, 1), F3(~3, ~0x11, ~1), "[1+i]o,d", 0, v9 }, +{ "lduba", F3(3, 0x11, 1), F3(~3, ~0x11, ~1), "[i+1]o,d", 0, v9 }, +{ "lduba", F3(3, 0x11, 1), F3(~3, ~0x11, ~1)|RS1_G0, "[i]o,d", 0, v9 }, +{ "lduba", F3(3, 0x11, 1), F3(~3, ~0x11, ~1)|SIMM13(~0), "[1]o,d", 0, v9 }, /* ld [rs1+0],d */ + +{ "lduha", F3(3, 0x12, 0), F3(~3, ~0x12, ~0), "[1+2]A,d", 0, v6 }, +{ "lduha", F3(3, 0x12, 0), F3(~3, ~0x12, ~0)|RS2_G0, "[1]A,d", 0, v6 }, /* lduha [rs1+%g0],d */ +{ "lduha", F3(3, 0x12, 1), F3(~3, ~0x12, ~1), "[1+i]o,d", 0, v9 }, +{ "lduha", F3(3, 0x12, 1), F3(~3, ~0x12, ~1), "[i+1]o,d", 0, v9 }, +{ "lduha", F3(3, 0x12, 1), F3(~3, ~0x12, ~1)|RS1_G0, "[i]o,d", 0, v9 }, +{ "lduha", F3(3, 0x12, 1), F3(~3, ~0x12, ~1)|SIMM13(~0), "[1]o,d", 0, v9 }, /* ld [rs1+0],d */ + +{ "lduwa", F3(3, 0x10, 0), F3(~3, ~0x10, ~0), "[1+2]A,d", F_ALIAS, v9 }, /* lduwa === lda */ +{ "lduwa", F3(3, 0x10, 0), F3(~3, ~0x10, ~0)|RS2_G0, "[1]A,d", F_ALIAS, v9 }, /* lda [rs1+%g0],d */ +{ "lduwa", F3(3, 0x10, 1), F3(~3, ~0x10, ~1), "[1+i]o,d", F_ALIAS, v9 }, +{ "lduwa", F3(3, 0x10, 1), F3(~3, ~0x10, ~1), "[i+1]o,d", F_ALIAS, v9 }, +{ "lduwa", F3(3, 0x10, 1), F3(~3, ~0x10, ~1)|RS1_G0, "[i]o,d", F_ALIAS, v9 }, +{ "lduwa", F3(3, 0x10, 1), F3(~3, ~0x10, ~1)|SIMM13(~0), "[1]o,d", F_ALIAS, v9 }, /* ld [rs1+0],d */ + +{ "ldxa", F3(3, 0x1b, 0), F3(~3, ~0x1b, ~0), "[1+2]A,d", 0, v9 }, +{ "ldxa", F3(3, 0x1b, 0), F3(~3, ~0x1b, ~0)|RS2_G0, "[1]A,d", 0, v9 }, /* lda [rs1+%g0],d */ +{ "ldxa", F3(3, 0x1b, 1), F3(~3, ~0x1b, ~1), "[1+i]o,d", 0, v9 }, +{ "ldxa", F3(3, 0x1b, 1), F3(~3, ~0x1b, ~1), "[i+1]o,d", 0, v9 }, +{ "ldxa", F3(3, 0x1b, 1), F3(~3, ~0x1b, ~1)|RS1_G0, "[i]o,d", 0, v9 }, +{ "ldxa", F3(3, 0x1b, 1), F3(~3, ~0x1b, ~1)|SIMM13(~0), "[1]o,d", 0, v9 }, /* ld [rs1+0],d */ + +{ "st", F3(3, 0x04, 0), F3(~3, ~0x04, ~0)|ASI(~0), "d,[1+2]", 0, v6 }, +{ "st", F3(3, 0x04, 0), F3(~3, ~0x04, ~0)|ASI_RS2(~0), "d,[1]", 0, v6 }, /* st d,[rs1+%g0] */ +{ "st", F3(3, 0x04, 1), F3(~3, ~0x04, ~1), "d,[1+i]", 0, v6 }, +{ "st", F3(3, 0x04, 1), F3(~3, ~0x04, ~1), "d,[i+1]", 0, v6 }, +{ "st", F3(3, 0x04, 1), F3(~3, ~0x04, ~1)|RS1_G0, "d,[i]", 0, v6 }, +{ "st", F3(3, 0x04, 1), F3(~3, ~0x04, ~1)|SIMM13(~0), "d,[1]", 0, v6 }, /* st d,[rs1+0] */ +{ "st", F3(3, 0x24, 0), F3(~3, ~0x24, ~0)|ASI(~0), "g,[1+2]", 0, v6 }, +{ "st", F3(3, 0x24, 0), F3(~3, ~0x24, ~0)|ASI_RS2(~0), "g,[1]", 0, v6 }, /* st d[rs1+%g0] */ +{ "st", F3(3, 0x24, 1), F3(~3, ~0x24, ~1), "g,[1+i]", 0, v6 }, +{ "st", F3(3, 0x24, 1), F3(~3, ~0x24, ~1), "g,[i+1]", 0, v6 }, +{ "st", F3(3, 0x24, 1), F3(~3, ~0x24, ~1)|RS1_G0, "g,[i]", 0, v6 }, +{ "st", F3(3, 0x24, 1), F3(~3, ~0x24, ~1)|SIMM13(~0), "g,[1]", 0, v6 }, /* st d,[rs1+0] */ + +{ "st", F3(3, 0x34, 0), F3(~3, ~0x34, ~0)|ASI(~0), "D,[1+2]", 0, v6notv9 }, +{ "st", F3(3, 0x34, 0), F3(~3, ~0x34, ~0)|ASI_RS2(~0), "D,[1]", 0, v6notv9 }, /* st d,[rs1+%g0] */ +{ "st", F3(3, 0x34, 1), F3(~3, ~0x34, ~1), "D,[1+i]", 0, v6notv9 }, +{ "st", F3(3, 0x34, 1), F3(~3, ~0x34, ~1), "D,[i+1]", 0, v6notv9 }, +{ "st", F3(3, 0x34, 1), F3(~3, ~0x34, ~1)|RS1_G0, "D,[i]", 0, v6notv9 }, +{ "st", F3(3, 0x34, 1), F3(~3, ~0x34, ~1)|SIMM13(~0), "D,[1]", 0, v6notv9 }, /* st d,[rs1+0] */ +{ "st", F3(3, 0x35, 0), F3(~3, ~0x35, ~0)|ASI(~0), "C,[1+2]", 0, v6notv9 }, +{ "st", F3(3, 0x35, 0), F3(~3, ~0x35, ~0)|ASI_RS2(~0), "C,[1]", 0, v6notv9 }, /* st d,[rs1+%g0] */ +{ "st", F3(3, 0x35, 1), F3(~3, ~0x35, ~1), "C,[1+i]", 0, v6notv9 }, +{ "st", F3(3, 0x35, 1), F3(~3, ~0x35, ~1), "C,[i+1]", 0, v6notv9 }, +{ "st", F3(3, 0x35, 1), F3(~3, ~0x35, ~1)|RS1_G0, "C,[i]", 0, v6notv9 }, +{ "st", F3(3, 0x35, 1), F3(~3, ~0x35, ~1)|SIMM13(~0), "C,[1]", 0, v6notv9 }, /* st d,[rs1+0] */ + +{ "st", F3(3, 0x25, 0), F3(~3, ~0x25, ~0)|RD_G0|ASI(~0), "F,[1+2]", 0, v6 }, +{ "st", F3(3, 0x25, 0), F3(~3, ~0x25, ~0)|RD_G0|ASI_RS2(~0), "F,[1]", 0, v6 }, /* st d,[rs1+%g0] */ +{ "st", F3(3, 0x25, 1), F3(~3, ~0x25, ~1)|RD_G0, "F,[1+i]", 0, v6 }, +{ "st", F3(3, 0x25, 1), F3(~3, ~0x25, ~1)|RD_G0, "F,[i+1]", 0, v6 }, +{ "st", F3(3, 0x25, 1), F3(~3, ~0x25, ~1)|RD_G0|RS1_G0, "F,[i]", 0, v6 }, +{ "st", F3(3, 0x25, 1), F3(~3, ~0x25, ~1)|RD_G0|SIMM13(~0), "F,[1]", 0, v6 }, /* st d,[rs1+0] */ + +{ "stw", F3(3, 0x04, 0), F3(~3, ~0x04, ~0)|ASI(~0), "d,[1+2]", F_ALIAS, v9 }, +{ "stw", F3(3, 0x04, 0), F3(~3, ~0x04, ~0)|ASI_RS2(~0), "d,[1]", F_ALIAS, v9 }, /* st d,[rs1+%g0] */ +{ "stw", F3(3, 0x04, 1), F3(~3, ~0x04, ~1), "d,[1+i]", F_ALIAS, v9 }, +{ "stw", F3(3, 0x04, 1), F3(~3, ~0x04, ~1), "d,[i+1]", F_ALIAS, v9 }, +{ "stw", F3(3, 0x04, 1), F3(~3, ~0x04, ~1)|RS1_G0, "d,[i]", F_ALIAS, v9 }, +{ "stw", F3(3, 0x04, 1), F3(~3, ~0x04, ~1)|SIMM13(~0), "d,[1]", F_ALIAS, v9 }, /* st d,[rs1+0] */ +{ "stsw", F3(3, 0x04, 0), F3(~3, ~0x04, ~0)|ASI(~0), "d,[1+2]", F_ALIAS, v9 }, +{ "stsw", F3(3, 0x04, 0), F3(~3, ~0x04, ~0)|ASI_RS2(~0), "d,[1]", F_ALIAS, v9 }, /* st d,[rs1+%g0] */ +{ "stsw", F3(3, 0x04, 1), F3(~3, ~0x04, ~1), "d,[1+i]", F_ALIAS, v9 }, +{ "stsw", F3(3, 0x04, 1), F3(~3, ~0x04, ~1), "d,[i+1]", F_ALIAS, v9 }, +{ "stsw", F3(3, 0x04, 1), F3(~3, ~0x04, ~1)|RS1_G0, "d,[i]", F_ALIAS, v9 }, +{ "stsw", F3(3, 0x04, 1), F3(~3, ~0x04, ~1)|SIMM13(~0), "d,[1]", F_ALIAS, v9 }, /* st d,[rs1+0] */ +{ "stuw", F3(3, 0x04, 0), F3(~3, ~0x04, ~0)|ASI(~0), "d,[1+2]", F_ALIAS, v9 }, +{ "stuw", F3(3, 0x04, 0), F3(~3, ~0x04, ~0)|ASI_RS2(~0), "d,[1]", F_ALIAS, v9 }, /* st d,[rs1+%g0] */ +{ "stuw", F3(3, 0x04, 1), F3(~3, ~0x04, ~1), "d,[1+i]", F_ALIAS, v9 }, +{ "stuw", F3(3, 0x04, 1), F3(~3, ~0x04, ~1), "d,[i+1]", F_ALIAS, v9 }, +{ "stuw", F3(3, 0x04, 1), F3(~3, ~0x04, ~1)|RS1_G0, "d,[i]", F_ALIAS, v9 }, +{ "stuw", F3(3, 0x04, 1), F3(~3, ~0x04, ~1)|SIMM13(~0), "d,[1]", F_ALIAS, v9 }, /* st d,[rs1+0] */ + +{ "spill", F3(3, 0x04, 0), F3(~3, ~0x04, ~0)|ASI(~0), "d,[1+2]", F_ALIAS, v6 }, +{ "spill", F3(3, 0x04, 0), F3(~3, ~0x04, ~0)|ASI_RS2(~0), "d,[1]", F_ALIAS, v6 }, /* st d,[rs1+%g0] */ +{ "spill", F3(3, 0x04, 1), F3(~3, ~0x04, ~1), "d,[1+i]", F_ALIAS, v6 }, +{ "spill", F3(3, 0x04, 1), F3(~3, ~0x04, ~1), "d,[i+1]", F_ALIAS, v6 }, +{ "spill", F3(3, 0x04, 1), F3(~3, ~0x04, ~1)|RS1_G0, "d,[i]", F_ALIAS, v6 }, +{ "spill", F3(3, 0x04, 1), F3(~3, ~0x04, ~1)|SIMM13(~0), "d,[1]", F_ALIAS, v6 }, /* st d,[rs1+0] */ + +{ "sta", F3(3, 0x14, 0), F3(~3, ~0x14, ~0), "d,[1+2]A", 0, v6 }, +{ "sta", F3(3, 0x14, 0), F3(~3, ~0x14, ~0)|RS2(~0), "d,[1]A", 0, v6 }, /* sta d,[rs1+%g0] */ +{ "sta", F3(3, 0x14, 1), F3(~3, ~0x14, ~1), "d,[1+i]o", 0, v9 }, +{ "sta", F3(3, 0x14, 1), F3(~3, ~0x14, ~1), "d,[i+1]o", 0, v9 }, +{ "sta", F3(3, 0x14, 1), F3(~3, ~0x14, ~1)|RS1_G0, "d,[i]o", 0, v9 }, +{ "sta", F3(3, 0x14, 1), F3(~3, ~0x14, ~1)|SIMM13(~0), "d,[1]o", 0, v9 }, /* st d,[rs1+0] */ + +{ "sta", F3(3, 0x34, 0), F3(~3, ~0x34, ~0), "g,[1+2]A", 0, v9 }, +{ "sta", F3(3, 0x34, 0), F3(~3, ~0x34, ~0)|RS2(~0), "g,[1]A", 0, v9 }, /* sta d,[rs1+%g0] */ +{ "sta", F3(3, 0x34, 1), F3(~3, ~0x34, ~1), "g,[1+i]o", 0, v9 }, +{ "sta", F3(3, 0x34, 1), F3(~3, ~0x34, ~1), "g,[i+1]o", 0, v9 }, +{ "sta", F3(3, 0x34, 1), F3(~3, ~0x34, ~1)|RS1_G0, "g,[i]o", 0, v9 }, +{ "sta", F3(3, 0x34, 1), F3(~3, ~0x34, ~1)|SIMM13(~0), "g,[1]o", 0, v9 }, /* st d,[rs1+0] */ + +{ "stwa", F3(3, 0x14, 0), F3(~3, ~0x14, ~0), "d,[1+2]A", F_ALIAS, v9 }, +{ "stwa", F3(3, 0x14, 0), F3(~3, ~0x14, ~0)|RS2(~0), "d,[1]A", F_ALIAS, v9 }, /* sta d,[rs1+%g0] */ +{ "stwa", F3(3, 0x14, 1), F3(~3, ~0x14, ~1), "d,[1+i]o", F_ALIAS, v9 }, +{ "stwa", F3(3, 0x14, 1), F3(~3, ~0x14, ~1), "d,[i+1]o", F_ALIAS, v9 }, +{ "stwa", F3(3, 0x14, 1), F3(~3, ~0x14, ~1)|RS1_G0, "d,[i]o", F_ALIAS, v9 }, +{ "stwa", F3(3, 0x14, 1), F3(~3, ~0x14, ~1)|SIMM13(~0), "d,[1]o", F_ALIAS, v9 }, /* st d,[rs1+0] */ +{ "stswa", F3(3, 0x14, 0), F3(~3, ~0x14, ~0), "d,[1+2]A", F_ALIAS, v9 }, +{ "stswa", F3(3, 0x14, 0), F3(~3, ~0x14, ~0)|RS2(~0), "d,[1]A", F_ALIAS, v9 }, /* sta d,[rs1+%g0] */ +{ "stswa", F3(3, 0x14, 1), F3(~3, ~0x14, ~1), "d,[1+i]o", F_ALIAS, v9 }, +{ "stswa", F3(3, 0x14, 1), F3(~3, ~0x14, ~1), "d,[i+1]o", F_ALIAS, v9 }, +{ "stswa", F3(3, 0x14, 1), F3(~3, ~0x14, ~1)|RS1_G0, "d,[i]o", F_ALIAS, v9 }, +{ "stswa", F3(3, 0x14, 1), F3(~3, ~0x14, ~1)|SIMM13(~0), "d,[1]o", F_ALIAS, v9 }, /* st d,[rs1+0] */ +{ "stuwa", F3(3, 0x14, 0), F3(~3, ~0x14, ~0), "d,[1+2]A", F_ALIAS, v9 }, +{ "stuwa", F3(3, 0x14, 0), F3(~3, ~0x14, ~0)|RS2(~0), "d,[1]A", F_ALIAS, v9 }, /* sta d,[rs1+%g0] */ +{ "stuwa", F3(3, 0x14, 1), F3(~3, ~0x14, ~1), "d,[1+i]o", F_ALIAS, v9 }, +{ "stuwa", F3(3, 0x14, 1), F3(~3, ~0x14, ~1), "d,[i+1]o", F_ALIAS, v9 }, +{ "stuwa", F3(3, 0x14, 1), F3(~3, ~0x14, ~1)|RS1_G0, "d,[i]o", F_ALIAS, v9 }, +{ "stuwa", F3(3, 0x14, 1), F3(~3, ~0x14, ~1)|SIMM13(~0), "d,[1]o", F_ALIAS, v9 }, /* st d,[rs1+0] */ + +{ "stb", F3(3, 0x05, 0), F3(~3, ~0x05, ~0)|ASI(~0), "d,[1+2]", 0, v6 }, +{ "stb", F3(3, 0x05, 0), F3(~3, ~0x05, ~0)|ASI_RS2(~0), "d,[1]", 0, v6 }, /* stb d,[rs1+%g0] */ +{ "stb", F3(3, 0x05, 1), F3(~3, ~0x05, ~1), "d,[1+i]", 0, v6 }, +{ "stb", F3(3, 0x05, 1), F3(~3, ~0x05, ~1), "d,[i+1]", 0, v6 }, +{ "stb", F3(3, 0x05, 1), F3(~3, ~0x05, ~1)|RS1_G0, "d,[i]", 0, v6 }, +{ "stb", F3(3, 0x05, 1), F3(~3, ~0x05, ~1)|SIMM13(~0), "d,[1]", 0, v6 }, /* stb d,[rs1+0] */ + +{ "stsb", F3(3, 0x05, 0), F3(~3, ~0x05, ~0)|ASI(~0), "d,[1+2]", F_ALIAS, v6 }, +{ "stsb", F3(3, 0x05, 0), F3(~3, ~0x05, ~0)|ASI_RS2(~0), "d,[1]", F_ALIAS, v6 }, /* stb d,[rs1+%g0] */ +{ "stsb", F3(3, 0x05, 1), F3(~3, ~0x05, ~1), "d,[1+i]", F_ALIAS, v6 }, +{ "stsb", F3(3, 0x05, 1), F3(~3, ~0x05, ~1), "d,[i+1]", F_ALIAS, v6 }, +{ "stsb", F3(3, 0x05, 1), F3(~3, ~0x05, ~1)|RS1_G0, "d,[i]", F_ALIAS, v6 }, +{ "stsb", F3(3, 0x05, 1), F3(~3, ~0x05, ~1)|SIMM13(~0), "d,[1]", F_ALIAS, v6 }, /* stb d,[rs1+0] */ +{ "stub", F3(3, 0x05, 0), F3(~3, ~0x05, ~0)|ASI(~0), "d,[1+2]", F_ALIAS, v6 }, +{ "stub", F3(3, 0x05, 0), F3(~3, ~0x05, ~0)|ASI_RS2(~0), "d,[1]", F_ALIAS, v6 }, /* stb d,[rs1+%g0] */ +{ "stub", F3(3, 0x05, 1), F3(~3, ~0x05, ~1), "d,[1+i]", F_ALIAS, v6 }, +{ "stub", F3(3, 0x05, 1), F3(~3, ~0x05, ~1), "d,[i+1]", F_ALIAS, v6 }, +{ "stub", F3(3, 0x05, 1), F3(~3, ~0x05, ~1)|RS1_G0, "d,[i]", F_ALIAS, v6 }, +{ "stub", F3(3, 0x05, 1), F3(~3, ~0x05, ~1)|SIMM13(~0), "d,[1]", F_ALIAS, v6 }, /* stb d,[rs1+0] */ + +{ "stba", F3(3, 0x15, 0), F3(~3, ~0x15, ~0), "d,[1+2]A", 0, v6 }, +{ "stba", F3(3, 0x15, 0), F3(~3, ~0x15, ~0)|RS2(~0), "d,[1]A", 0, v6 }, /* stba d,[rs1+%g0] */ +{ "stba", F3(3, 0x15, 1), F3(~3, ~0x15, ~1), "d,[1+i]o", 0, v9 }, +{ "stba", F3(3, 0x15, 1), F3(~3, ~0x15, ~1), "d,[i+1]o", 0, v9 }, +{ "stba", F3(3, 0x15, 1), F3(~3, ~0x15, ~1)|RS1_G0, "d,[i]o", 0, v9 }, +{ "stba", F3(3, 0x15, 1), F3(~3, ~0x15, ~1)|SIMM13(~0), "d,[1]o", 0, v9 }, /* stb d,[rs1+0] */ + +{ "stsba", F3(3, 0x15, 0), F3(~3, ~0x15, ~0), "d,[1+2]A", F_ALIAS, v6 }, +{ "stsba", F3(3, 0x15, 0), F3(~3, ~0x15, ~0)|RS2(~0), "d,[1]A", F_ALIAS, v6 }, /* stba d,[rs1+%g0] */ +{ "stsba", F3(3, 0x15, 1), F3(~3, ~0x15, ~1), "d,[1+i]o", F_ALIAS, v9 }, +{ "stsba", F3(3, 0x15, 1), F3(~3, ~0x15, ~1), "d,[i+1]o", F_ALIAS, v9 }, +{ "stsba", F3(3, 0x15, 1), F3(~3, ~0x15, ~1)|RS1_G0, "d,[i]o", F_ALIAS, v9 }, +{ "stsba", F3(3, 0x15, 1), F3(~3, ~0x15, ~1)|SIMM13(~0), "d,[1]o", F_ALIAS, v9 }, /* stb d,[rs1+0] */ +{ "stuba", F3(3, 0x15, 0), F3(~3, ~0x15, ~0), "d,[1+2]A", F_ALIAS, v6 }, +{ "stuba", F3(3, 0x15, 0), F3(~3, ~0x15, ~0)|RS2(~0), "d,[1]A", F_ALIAS, v6 }, /* stba d,[rs1+%g0] */ +{ "stuba", F3(3, 0x15, 1), F3(~3, ~0x15, ~1), "d,[1+i]o", F_ALIAS, v9 }, +{ "stuba", F3(3, 0x15, 1), F3(~3, ~0x15, ~1), "d,[i+1]o", F_ALIAS, v9 }, +{ "stuba", F3(3, 0x15, 1), F3(~3, ~0x15, ~1)|RS1_G0, "d,[i]o", F_ALIAS, v9 }, +{ "stuba", F3(3, 0x15, 1), F3(~3, ~0x15, ~1)|SIMM13(~0), "d,[1]o", F_ALIAS, v9 }, /* stb d,[rs1+0] */ + +{ "std", F3(3, 0x07, 0), F3(~3, ~0x07, ~0)|ASI(~0), "d,[1+2]", 0, v6 }, +{ "std", F3(3, 0x07, 0), F3(~3, ~0x07, ~0)|ASI_RS2(~0), "d,[1]", 0, v6 }, /* std d,[rs1+%g0] */ +{ "std", F3(3, 0x07, 1), F3(~3, ~0x07, ~1), "d,[1+i]", 0, v6 }, +{ "std", F3(3, 0x07, 1), F3(~3, ~0x07, ~1), "d,[i+1]", 0, v6 }, +{ "std", F3(3, 0x07, 1), F3(~3, ~0x07, ~1)|RS1_G0, "d,[i]", 0, v6 }, +{ "std", F3(3, 0x07, 1), F3(~3, ~0x07, ~1)|SIMM13(~0), "d,[1]", 0, v6 }, /* std d,[rs1+0] */ + +{ "std", F3(3, 0x26, 0), F3(~3, ~0x26, ~0)|ASI(~0), "q,[1+2]", 0, v6notv9 }, +{ "std", F3(3, 0x26, 0), F3(~3, ~0x26, ~0)|ASI_RS2(~0), "q,[1]", 0, v6notv9 }, /* std d,[rs1+%g0] */ +{ "std", F3(3, 0x26, 1), F3(~3, ~0x26, ~1), "q,[1+i]", 0, v6notv9 }, +{ "std", F3(3, 0x26, 1), F3(~3, ~0x26, ~1), "q,[i+1]", 0, v6notv9 }, +{ "std", F3(3, 0x26, 1), F3(~3, ~0x26, ~1)|RS1_G0, "q,[i]", 0, v6notv9 }, +{ "std", F3(3, 0x26, 1), F3(~3, ~0x26, ~1)|SIMM13(~0), "q,[1]", 0, v6notv9 }, /* std d,[rs1+0] */ +{ "std", F3(3, 0x27, 0), F3(~3, ~0x27, ~0)|ASI(~0), "H,[1+2]", 0, v6 }, +{ "std", F3(3, 0x27, 0), F3(~3, ~0x27, ~0)|ASI_RS2(~0), "H,[1]", 0, v6 }, /* std d,[rs1+%g0] */ +{ "std", F3(3, 0x27, 1), F3(~3, ~0x27, ~1), "H,[1+i]", 0, v6 }, +{ "std", F3(3, 0x27, 1), F3(~3, ~0x27, ~1), "H,[i+1]", 0, v6 }, +{ "std", F3(3, 0x27, 1), F3(~3, ~0x27, ~1)|RS1_G0, "H,[i]", 0, v6 }, +{ "std", F3(3, 0x27, 1), F3(~3, ~0x27, ~1)|SIMM13(~0), "H,[1]", 0, v6 }, /* std d,[rs1+0] */ + +{ "std", F3(3, 0x36, 0), F3(~3, ~0x36, ~0)|ASI(~0), "Q,[1+2]", 0, v6notv9 }, +{ "std", F3(3, 0x36, 0), F3(~3, ~0x36, ~0)|ASI_RS2(~0), "Q,[1]", 0, v6notv9 }, /* std d,[rs1+%g0] */ +{ "std", F3(3, 0x36, 1), F3(~3, ~0x36, ~1), "Q,[1+i]", 0, v6notv9 }, +{ "std", F3(3, 0x36, 1), F3(~3, ~0x36, ~1), "Q,[i+1]", 0, v6notv9 }, +{ "std", F3(3, 0x36, 1), F3(~3, ~0x36, ~1)|RS1_G0, "Q,[i]", 0, v6notv9 }, +{ "std", F3(3, 0x36, 1), F3(~3, ~0x36, ~1)|SIMM13(~0), "Q,[1]", 0, v6notv9 }, /* std d,[rs1+0] */ +{ "std", F3(3, 0x37, 0), F3(~3, ~0x37, ~0)|ASI(~0), "D,[1+2]", 0, v6notv9 }, +{ "std", F3(3, 0x37, 0), F3(~3, ~0x37, ~0)|ASI_RS2(~0), "D,[1]", 0, v6notv9 }, /* std d,[rs1+%g0] */ +{ "std", F3(3, 0x37, 1), F3(~3, ~0x37, ~1), "D,[1+i]", 0, v6notv9 }, +{ "std", F3(3, 0x37, 1), F3(~3, ~0x37, ~1), "D,[i+1]", 0, v6notv9 }, +{ "std", F3(3, 0x37, 1), F3(~3, ~0x37, ~1)|RS1_G0, "D,[i]", 0, v6notv9 }, +{ "std", F3(3, 0x37, 1), F3(~3, ~0x37, ~1)|SIMM13(~0), "D,[1]", 0, v6notv9 }, /* std d,[rs1+0] */ + +{ "spilld", F3(3, 0x07, 0), F3(~3, ~0x07, ~0)|ASI(~0), "d,[1+2]", F_ALIAS, v6 }, +{ "spilld", F3(3, 0x07, 0), F3(~3, ~0x07, ~0)|ASI_RS2(~0), "d,[1]", F_ALIAS, v6 }, /* std d,[rs1+%g0] */ +{ "spilld", F3(3, 0x07, 1), F3(~3, ~0x07, ~1), "d,[1+i]", F_ALIAS, v6 }, +{ "spilld", F3(3, 0x07, 1), F3(~3, ~0x07, ~1), "d,[i+1]", F_ALIAS, v6 }, +{ "spilld", F3(3, 0x07, 1), F3(~3, ~0x07, ~1)|RS1_G0, "d,[i]", F_ALIAS, v6 }, +{ "spilld", F3(3, 0x07, 1), F3(~3, ~0x07, ~1)|SIMM13(~0), "d,[1]", F_ALIAS, v6 }, /* std d,[rs1+0] */ + +{ "stda", F3(3, 0x17, 0), F3(~3, ~0x17, ~0), "d,[1+2]A", 0, v6 }, +{ "stda", F3(3, 0x17, 0), F3(~3, ~0x17, ~0)|RS2(~0), "d,[1]A", 0, v6 }, /* stda d,[rs1+%g0] */ +{ "stda", F3(3, 0x17, 1), F3(~3, ~0x17, ~1), "d,[1+i]o", 0, v9 }, +{ "stda", F3(3, 0x17, 1), F3(~3, ~0x17, ~1), "d,[i+1]o", 0, v9 }, +{ "stda", F3(3, 0x17, 1), F3(~3, ~0x17, ~1)|RS1_G0, "d,[i]o", 0, v9 }, +{ "stda", F3(3, 0x17, 1), F3(~3, ~0x17, ~1)|SIMM13(~0), "d,[1]o", 0, v9 }, /* std d,[rs1+0] */ +{ "stda", F3(3, 0x37, 0), F3(~3, ~0x37, ~0), "H,[1+2]A", 0, v9 }, +{ "stda", F3(3, 0x37, 0), F3(~3, ~0x37, ~0)|RS2(~0), "H,[1]A", 0, v9 }, /* stda d,[rs1+%g0] */ +{ "stda", F3(3, 0x37, 1), F3(~3, ~0x37, ~1), "H,[1+i]o", 0, v9 }, +{ "stda", F3(3, 0x37, 1), F3(~3, ~0x37, ~1), "H,[i+1]o", 0, v9 }, +{ "stda", F3(3, 0x37, 1), F3(~3, ~0x37, ~1)|RS1_G0, "H,[i]o", 0, v9 }, +{ "stda", F3(3, 0x37, 1), F3(~3, ~0x37, ~1)|SIMM13(~0), "H,[1]o", 0, v9 }, /* std d,[rs1+0] */ + +{ "sth", F3(3, 0x06, 0), F3(~3, ~0x06, ~0)|ASI(~0), "d,[1+2]", 0, v6 }, +{ "sth", F3(3, 0x06, 0), F3(~3, ~0x06, ~0)|ASI_RS2(~0), "d,[1]", 0, v6 }, /* sth d,[rs1+%g0] */ +{ "sth", F3(3, 0x06, 1), F3(~3, ~0x06, ~1), "d,[1+i]", 0, v6 }, +{ "sth", F3(3, 0x06, 1), F3(~3, ~0x06, ~1), "d,[i+1]", 0, v6 }, +{ "sth", F3(3, 0x06, 1), F3(~3, ~0x06, ~1)|RS1_G0, "d,[i]", 0, v6 }, +{ "sth", F3(3, 0x06, 1), F3(~3, ~0x06, ~1)|SIMM13(~0), "d,[1]", 0, v6 }, /* sth d,[rs1+0] */ + +{ "stsh", F3(3, 0x06, 0), F3(~3, ~0x06, ~0)|ASI(~0), "d,[1+2]", F_ALIAS, v6 }, +{ "stsh", F3(3, 0x06, 0), F3(~3, ~0x06, ~0)|ASI_RS2(~0), "d,[1]", F_ALIAS, v6 }, /* sth d,[rs1+%g0] */ +{ "stsh", F3(3, 0x06, 1), F3(~3, ~0x06, ~1), "d,[1+i]", F_ALIAS, v6 }, +{ "stsh", F3(3, 0x06, 1), F3(~3, ~0x06, ~1), "d,[i+1]", F_ALIAS, v6 }, +{ "stsh", F3(3, 0x06, 1), F3(~3, ~0x06, ~1)|RS1_G0, "d,[i]", F_ALIAS, v6 }, +{ "stsh", F3(3, 0x06, 1), F3(~3, ~0x06, ~1)|SIMM13(~0), "d,[1]", F_ALIAS, v6 }, /* sth d,[rs1+0] */ +{ "stuh", F3(3, 0x06, 0), F3(~3, ~0x06, ~0)|ASI(~0), "d,[1+2]", F_ALIAS, v6 }, +{ "stuh", F3(3, 0x06, 0), F3(~3, ~0x06, ~0)|ASI_RS2(~0), "d,[1]", F_ALIAS, v6 }, /* sth d,[rs1+%g0] */ +{ "stuh", F3(3, 0x06, 1), F3(~3, ~0x06, ~1), "d,[1+i]", F_ALIAS, v6 }, +{ "stuh", F3(3, 0x06, 1), F3(~3, ~0x06, ~1), "d,[i+1]", F_ALIAS, v6 }, +{ "stuh", F3(3, 0x06, 1), F3(~3, ~0x06, ~1)|RS1_G0, "d,[i]", F_ALIAS, v6 }, +{ "stuh", F3(3, 0x06, 1), F3(~3, ~0x06, ~1)|SIMM13(~0), "d,[1]", F_ALIAS, v6 }, /* sth d,[rs1+0] */ + +{ "stha", F3(3, 0x16, 0), F3(~3, ~0x16, ~0), "d,[1+2]A", 0, v6 }, +{ "stha", F3(3, 0x16, 0), F3(~3, ~0x16, ~0)|RS2(~0), "d,[1]A", 0, v6 }, /* stha ,[rs1+%g0] */ +{ "stha", F3(3, 0x16, 1), F3(~3, ~0x16, ~1), "d,[1+i]o", 0, v9 }, +{ "stha", F3(3, 0x16, 1), F3(~3, ~0x16, ~1), "d,[i+1]o", 0, v9 }, +{ "stha", F3(3, 0x16, 1), F3(~3, ~0x16, ~1)|RS1_G0, "d,[i]o", 0, v9 }, +{ "stha", F3(3, 0x16, 1), F3(~3, ~0x16, ~1)|SIMM13(~0), "d,[1]o", 0, v9 }, /* sth d,[rs1+0] */ + +{ "stsha", F3(3, 0x16, 0), F3(~3, ~0x16, ~0), "d,[1+2]A", F_ALIAS, v6 }, +{ "stsha", F3(3, 0x16, 0), F3(~3, ~0x16, ~0)|RS2(~0), "d,[1]A", F_ALIAS, v6 }, /* stha ,[rs1+%g0] */ +{ "stsha", F3(3, 0x16, 1), F3(~3, ~0x16, ~1), "d,[1+i]o", F_ALIAS, v9 }, +{ "stsha", F3(3, 0x16, 1), F3(~3, ~0x16, ~1), "d,[i+1]o", F_ALIAS, v9 }, +{ "stsha", F3(3, 0x16, 1), F3(~3, ~0x16, ~1)|RS1_G0, "d,[i]o", F_ALIAS, v9 }, +{ "stsha", F3(3, 0x16, 1), F3(~3, ~0x16, ~1)|SIMM13(~0), "d,[1]o", F_ALIAS, v9 }, /* sth d,[rs1+0] */ +{ "stuha", F3(3, 0x16, 0), F3(~3, ~0x16, ~0), "d,[1+2]A", F_ALIAS, v6 }, +{ "stuha", F3(3, 0x16, 0), F3(~3, ~0x16, ~0)|RS2(~0), "d,[1]A", F_ALIAS, v6 }, /* stha ,[rs1+%g0] */ +{ "stuha", F3(3, 0x16, 1), F3(~3, ~0x16, ~1), "d,[1+i]o", F_ALIAS, v9 }, +{ "stuha", F3(3, 0x16, 1), F3(~3, ~0x16, ~1), "d,[i+1]o", F_ALIAS, v9 }, +{ "stuha", F3(3, 0x16, 1), F3(~3, ~0x16, ~1)|RS1_G0, "d,[i]o", F_ALIAS, v9 }, +{ "stuha", F3(3, 0x16, 1), F3(~3, ~0x16, ~1)|SIMM13(~0), "d,[1]o", F_ALIAS, v9 }, /* sth d,[rs1+0] */ + +{ "stx", F3(3, 0x0e, 0), F3(~3, ~0x0e, ~0)|ASI(~0), "d,[1+2]", 0, v9 }, +{ "stx", F3(3, 0x0e, 0), F3(~3, ~0x0e, ~0)|ASI_RS2(~0), "d,[1]", 0, v9 }, /* stx d,[rs1+%g0] */ +{ "stx", F3(3, 0x0e, 1), F3(~3, ~0x0e, ~1), "d,[1+i]", 0, v9 }, +{ "stx", F3(3, 0x0e, 1), F3(~3, ~0x0e, ~1), "d,[i+1]", 0, v9 }, +{ "stx", F3(3, 0x0e, 1), F3(~3, ~0x0e, ~1)|RS1_G0, "d,[i]", 0, v9 }, +{ "stx", F3(3, 0x0e, 1), F3(~3, ~0x0e, ~1)|SIMM13(~0), "d,[1]", 0, v9 }, /* stx d,[rs1+0] */ + +{ "stx", F3(3, 0x25, 0)|RD(1), F3(~3, ~0x25, ~0)|ASI(~0)|RD(~1), "F,[1+2]", 0, v9 }, +{ "stx", F3(3, 0x25, 0)|RD(1), F3(~3, ~0x25, ~0)|ASI_RS2(~0)|RD(~1),"F,[1]", 0, v9 }, /* stx d,[rs1+%g0] */ +{ "stx", F3(3, 0x25, 1)|RD(1), F3(~3, ~0x25, ~1)|RD(~1), "F,[1+i]", 0, v9 }, +{ "stx", F3(3, 0x25, 1)|RD(1), F3(~3, ~0x25, ~1)|RD(~1), "F,[i+1]", 0, v9 }, +{ "stx", F3(3, 0x25, 1)|RD(1), F3(~3, ~0x25, ~1)|RS1_G0|RD(~1), "F,[i]", 0, v9 }, +{ "stx", F3(3, 0x25, 1)|RD(1), F3(~3, ~0x25, ~1)|SIMM13(~0)|RD(~1),"F,[1]", 0, v9 }, /* stx d,[rs1+0] */ + +{ "stxa", F3(3, 0x1e, 0), F3(~3, ~0x1e, ~0), "d,[1+2]A", 0, v9 }, +{ "stxa", F3(3, 0x1e, 0), F3(~3, ~0x1e, ~0)|RS2(~0), "d,[1]A", 0, v9 }, /* stxa d,[rs1+%g0] */ +{ "stxa", F3(3, 0x1e, 1), F3(~3, ~0x1e, ~1), "d,[1+i]o", 0, v9 }, +{ "stxa", F3(3, 0x1e, 1), F3(~3, ~0x1e, ~1), "d,[i+1]o", 0, v9 }, +{ "stxa", F3(3, 0x1e, 1), F3(~3, ~0x1e, ~1)|RS1_G0, "d,[i]o", 0, v9 }, +{ "stxa", F3(3, 0x1e, 1), F3(~3, ~0x1e, ~1)|SIMM13(~0), "d,[1]o", 0, v9 }, /* stx d,[rs1+0] */ + +{ "stq", F3(3, 0x26, 0), F3(~3, ~0x26, ~0)|ASI(~0), "J,[1+2]", 0, v9 }, +{ "stq", F3(3, 0x26, 0), F3(~3, ~0x26, ~0)|ASI_RS2(~0), "J,[1]", 0, v9 }, /* stq [rs1+%g0] */ +{ "stq", F3(3, 0x26, 1), F3(~3, ~0x26, ~1), "J,[1+i]", 0, v9 }, +{ "stq", F3(3, 0x26, 1), F3(~3, ~0x26, ~1), "J,[i+1]", 0, v9 }, +{ "stq", F3(3, 0x26, 1), F3(~3, ~0x26, ~1)|RS1_G0, "J,[i]", 0, v9 }, +{ "stq", F3(3, 0x26, 1), F3(~3, ~0x26, ~1)|SIMM13(~0), "J,[1]", 0, v9 }, /* stq [rs1+0] */ + +{ "stqa", F3(3, 0x36, 0), F3(~3, ~0x36, ~0)|ASI(~0), "J,[1+2]A", 0, v9 }, +{ "stqa", F3(3, 0x36, 0), F3(~3, ~0x36, ~0)|ASI_RS2(~0), "J,[1]A", 0, v9 }, /* stqa [rs1+%g0] */ +{ "stqa", F3(3, 0x36, 1), F3(~3, ~0x36, ~1), "J,[1+i]o", 0, v9 }, +{ "stqa", F3(3, 0x36, 1), F3(~3, ~0x36, ~1), "J,[i+1]o", 0, v9 }, +{ "stqa", F3(3, 0x36, 1), F3(~3, ~0x36, ~1)|RS1_G0, "J,[i]o", 0, v9 }, +{ "stqa", F3(3, 0x36, 1), F3(~3, ~0x36, ~1)|SIMM13(~0), "J,[1]o", 0, v9 }, /* stqa [rs1+0] */ + +{ "swap", F3(3, 0x0f, 0), F3(~3, ~0x0f, ~0)|ASI(~0), "[1+2],d", 0, v7 }, +{ "swap", F3(3, 0x0f, 0), F3(~3, ~0x0f, ~0)|ASI_RS2(~0), "[1],d", 0, v7 }, /* swap [rs1+%g0],d */ +{ "swap", F3(3, 0x0f, 1), F3(~3, ~0x0f, ~1), "[1+i],d", 0, v7 }, +{ "swap", F3(3, 0x0f, 1), F3(~3, ~0x0f, ~1), "[i+1],d", 0, v7 }, +{ "swap", F3(3, 0x0f, 1), F3(~3, ~0x0f, ~1)|RS1_G0, "[i],d", 0, v7 }, +{ "swap", F3(3, 0x0f, 1), F3(~3, ~0x0f, ~1)|SIMM13(~0), "[1],d", 0, v7 }, /* swap [rs1+0],d */ + +{ "swapa", F3(3, 0x1f, 0), F3(~3, ~0x1f, ~0), "[1+2]A,d", 0, v7 }, +{ "swapa", F3(3, 0x1f, 0), F3(~3, ~0x1f, ~0)|RS2(~0), "[1]A,d", 0, v7 }, /* swapa [rs1+%g0],d */ +{ "swapa", F3(3, 0x1f, 1), F3(~3, ~0x1f, ~1), "[1+i]o,d", 0, v9 }, +{ "swapa", F3(3, 0x1f, 1), F3(~3, ~0x1f, ~1), "[i+1]o,d", 0, v9 }, +{ "swapa", F3(3, 0x1f, 1), F3(~3, ~0x1f, ~1)|RS1_G0, "[i]o,d", 0, v9 }, +{ "swapa", F3(3, 0x1f, 1), F3(~3, ~0x1f, ~1)|SIMM13(~0), "[1]o,d", 0, v9 }, /* swap [rs1+0],d */ + +{ "restore", F3(2, 0x3d, 0), F3(~2, ~0x3d, ~0)|ASI(~0), "1,2,d", 0, v6 }, +{ "restore", F3(2, 0x3d, 0), F3(~2, ~0x3d, ~0)|RD_G0|RS1_G0|ASI_RS2(~0), "", 0, v6 }, /* restore %g0,%g0,%g0 */ +{ "restore", F3(2, 0x3d, 1), F3(~2, ~0x3d, ~1), "1,i,d", 0, v6 }, +{ "restore", F3(2, 0x3d, 1), F3(~2, ~0x3d, ~1)|RD_G0|RS1_G0|SIMM13(~0), "", 0, v6 }, /* restore %g0,0,%g0 */ + +{ "rett", F3(2, 0x39, 0), F3(~2, ~0x39, ~0)|RD_G0|ASI(~0), "1+2", F_UNBR|F_DELAYED, v6 }, /* rett rs1+rs2 */ +{ "rett", F3(2, 0x39, 0), F3(~2, ~0x39, ~0)|RD_G0|ASI_RS2(~0), "1", F_UNBR|F_DELAYED, v6 }, /* rett rs1,%g0 */ +{ "rett", F3(2, 0x39, 1), F3(~2, ~0x39, ~1)|RD_G0, "1+i", F_UNBR|F_DELAYED, v6 }, /* rett rs1+X */ +{ "rett", F3(2, 0x39, 1), F3(~2, ~0x39, ~1)|RD_G0, "i+1", F_UNBR|F_DELAYED, v6 }, /* rett X+rs1 */ +{ "rett", F3(2, 0x39, 1), F3(~2, ~0x39, ~1)|RD_G0|RS1_G0, "i", F_UNBR|F_DELAYED, v6 }, /* rett X+rs1 */ +{ "rett", F3(2, 0x39, 1), F3(~2, ~0x39, ~1)|RD_G0|RS1_G0, "i", F_UNBR|F_DELAYED, v6 }, /* rett X */ +{ "rett", F3(2, 0x39, 1), F3(~2, ~0x39, ~1)|RD_G0|SIMM13(~0), "1", F_UNBR|F_DELAYED, v6 }, /* rett rs1+0 */ + +{ "save", F3(2, 0x3c, 0), F3(~2, ~0x3c, ~0)|ASI(~0), "1,2,d", 0, v6 }, +{ "save", F3(2, 0x3c, 1), F3(~2, ~0x3c, ~1), "1,i,d", 0, v6 }, +{ "save", F3(2, 0x3c, 1), F3(~2, ~0x3c, ~1), "i,1,d", 0, v6 }, /* Sun assembler compatibility */ +{ "save", 0x81e00000, ~0x81e00000, "", F_ALIAS, v6 }, + +{ "ret", F3(2, 0x38, 1)|RS1(0x1f)|SIMM13(8), F3(~2, ~0x38, ~1)|SIMM13(~8), "", F_UNBR|F_DELAYED, v6 }, /* jmpl %i7+8,%g0 */ +{ "retl", F3(2, 0x38, 1)|RS1(0x0f)|SIMM13(8), F3(~2, ~0x38, ~1)|RS1(~0x0f)|SIMM13(~8), "", F_UNBR|F_DELAYED, v6 }, /* jmpl %o7+8,%g0 */ + +{ "jmpl", F3(2, 0x38, 0), F3(~2, ~0x38, ~0)|ASI(~0), "1+2,d", F_JSR|F_DELAYED, v6 }, +{ "jmpl", F3(2, 0x38, 0), F3(~2, ~0x38, ~0)|ASI_RS2(~0), "1,d", F_JSR|F_DELAYED, v6 }, /* jmpl rs1+%g0,d */ +{ "jmpl", F3(2, 0x38, 1), F3(~2, ~0x38, ~1)|SIMM13(~0), "1,d", F_JSR|F_DELAYED, v6 }, /* jmpl rs1+0,d */ +{ "jmpl", F3(2, 0x38, 1), F3(~2, ~0x38, ~1)|RS1_G0, "i,d", F_JSR|F_DELAYED, v6 }, /* jmpl %g0+i,d */ +{ "jmpl", F3(2, 0x38, 1), F3(~2, ~0x38, ~1), "1+i,d", F_JSR|F_DELAYED, v6 }, +{ "jmpl", F3(2, 0x38, 1), F3(~2, ~0x38, ~1), "i+1,d", F_JSR|F_DELAYED, v6 }, + +{ "done", F3(2, 0x3e, 0)|RD(0), F3(~2, ~0x3e, ~0)|RD(~0)|RS1_G0|SIMM13(~0), "", 0, v9 }, +{ "retry", F3(2, 0x3e, 0)|RD(1), F3(~2, ~0x3e, ~0)|RD(~1)|RS1_G0|SIMM13(~0), "", 0, v9 }, +{ "saved", F3(2, 0x31, 0)|RD(0), F3(~2, ~0x31, ~0)|RD(~0)|RS1_G0|SIMM13(~0), "", 0, v9 }, +{ "restored", F3(2, 0x31, 0)|RD(1), F3(~2, ~0x31, ~0)|RD(~1)|RS1_G0|SIMM13(~0), "", 0, v9 }, +{ "allclean", F3(2, 0x31, 0)|RD(2), F3(~2, ~0x31, ~0)|RD(~2)|RS1_G0|SIMM13(~0), "", 0, v9 }, +{ "otherw", F3(2, 0x31, 0)|RD(3), F3(~2, ~0x31, ~0)|RD(~3)|RS1_G0|SIMM13(~0), "", 0, v9 }, +{ "normalw", F3(2, 0x31, 0)|RD(4), F3(~2, ~0x31, ~0)|RD(~4)|RS1_G0|SIMM13(~0), "", 0, v9 }, +{ "invalw", F3(2, 0x31, 0)|RD(5), F3(~2, ~0x31, ~0)|RD(~5)|RS1_G0|SIMM13(~0), "", 0, v9 }, +{ "sir", F3(2, 0x30, 1)|RD(0xf), F3(~2, ~0x30, ~1)|RD(~0xf)|RS1_G0, "i", 0, v9 }, + +{ "flush", F3(2, 0x3b, 0), F3(~2, ~0x3b, ~0)|ASI(~0), "1+2", 0, v8 }, +{ "flush", F3(2, 0x3b, 0), F3(~2, ~0x3b, ~0)|ASI_RS2(~0), "1", 0, v8 }, /* flush rs1+%g0 */ +{ "flush", F3(2, 0x3b, 1), F3(~2, ~0x3b, ~1)|SIMM13(~0), "1", 0, v8 }, /* flush rs1+0 */ +{ "flush", F3(2, 0x3b, 1), F3(~2, ~0x3b, ~1)|RS1_G0, "i", 0, v8 }, /* flush %g0+i */ +{ "flush", F3(2, 0x3b, 1), F3(~2, ~0x3b, ~1), "1+i", 0, v8 }, +{ "flush", F3(2, 0x3b, 1), F3(~2, ~0x3b, ~1), "i+1", 0, v8 }, + +/* IFLUSH was renamed to FLUSH in v8. */ +{ "iflush", F3(2, 0x3b, 0), F3(~2, ~0x3b, ~0)|ASI(~0), "1+2", F_ALIAS, v6 }, +{ "iflush", F3(2, 0x3b, 0), F3(~2, ~0x3b, ~0)|ASI_RS2(~0), "1", F_ALIAS, v6 }, /* flush rs1+%g0 */ +{ "iflush", F3(2, 0x3b, 1), F3(~2, ~0x3b, ~1)|SIMM13(~0), "1", F_ALIAS, v6 }, /* flush rs1+0 */ +{ "iflush", F3(2, 0x3b, 1), F3(~2, ~0x3b, ~1)|RS1_G0, "i", F_ALIAS, v6 }, +{ "iflush", F3(2, 0x3b, 1), F3(~2, ~0x3b, ~1), "1+i", F_ALIAS, v6 }, +{ "iflush", F3(2, 0x3b, 1), F3(~2, ~0x3b, ~1), "i+1", F_ALIAS, v6 }, + +{ "return", F3(2, 0x39, 0), F3(~2, ~0x39, ~0)|ASI(~0), "1+2", 0, v9 }, +{ "return", F3(2, 0x39, 0), F3(~2, ~0x39, ~0)|ASI_RS2(~0), "1", 0, v9 }, /* return rs1+%g0 */ +{ "return", F3(2, 0x39, 1), F3(~2, ~0x39, ~1)|SIMM13(~0), "1", 0, v9 }, /* return rs1+0 */ +{ "return", F3(2, 0x39, 1), F3(~2, ~0x39, ~1)|RS1_G0, "i", 0, v9 }, /* return %g0+i */ +{ "return", F3(2, 0x39, 1), F3(~2, ~0x39, ~1), "1+i", 0, v9 }, +{ "return", F3(2, 0x39, 1), F3(~2, ~0x39, ~1), "i+1", 0, v9 }, + +{ "flushw", F3(2, 0x2b, 0), F3(~2, ~0x2b, ~0)|RD_G0|RS1_G0|ASI_RS2(~0), "", 0, v9 }, + +{ "membar", F3(2, 0x28, 1)|RS1(0xf), F3(~2, ~0x28, ~1)|RD_G0|RS1(~0xf)|SIMM13(~127), "K", 0, v9 }, +{ "stbar", F3(2, 0x28, 0)|RS1(0xf), F3(~2, ~0x28, ~0)|RD_G0|RS1(~0xf)|SIMM13(~0), "", 0, v8 }, + +{ "prefetch", F3(3, 0x2d, 0), F3(~3, ~0x2d, ~0), "[1+2],*", 0, v9 }, +{ "prefetch", F3(3, 0x2d, 0), F3(~3, ~0x2d, ~0)|RS2_G0, "[1],*", 0, v9 }, /* prefetch [rs1+%g0],prefetch_fcn */ +{ "prefetch", F3(3, 0x2d, 1), F3(~3, ~0x2d, ~1), "[1+i],*", 0, v9 }, +{ "prefetch", F3(3, 0x2d, 1), F3(~3, ~0x2d, ~1), "[i+1],*", 0, v9 }, +{ "prefetch", F3(3, 0x2d, 1), F3(~3, ~0x2d, ~1)|RS1_G0, "[i],*", 0, v9 }, +{ "prefetch", F3(3, 0x2d, 1), F3(~3, ~0x2d, ~1)|SIMM13(~0), "[1],*", 0, v9 }, /* prefetch [rs1+0],prefetch_fcn */ +{ "prefetcha", F3(3, 0x3d, 0), F3(~3, ~0x3d, ~0), "[1+2]A,*", 0, v9 }, +{ "prefetcha", F3(3, 0x3d, 0), F3(~3, ~0x3d, ~0)|RS2_G0, "[1]A,*", 0, v9 }, /* prefetcha [rs1+%g0],prefetch_fcn */ +{ "prefetcha", F3(3, 0x3d, 1), F3(~3, ~0x3d, ~1), "[1+i]o,*", 0, v9 }, +{ "prefetcha", F3(3, 0x3d, 1), F3(~3, ~0x3d, ~1), "[i+1]o,*", 0, v9 }, +{ "prefetcha", F3(3, 0x3d, 1), F3(~3, ~0x3d, ~1)|RS1_G0, "[i]o,*", 0, v9 }, +{ "prefetcha", F3(3, 0x3d, 1), F3(~3, ~0x3d, ~1)|SIMM13(~0), "[1]o,*", 0, v9 }, /* prefetcha [rs1+0],d */ + +{ "sll", F3(2, 0x25, 0), F3(~2, ~0x25, ~0)|(1<<12)|(0x7f<<5), "1,2,d", 0, v6 }, +{ "sll", F3(2, 0x25, 1), F3(~2, ~0x25, ~1)|(1<<12)|(0x7f<<5), "1,X,d", 0, v6 }, +{ "sra", F3(2, 0x27, 0), F3(~2, ~0x27, ~0)|(1<<12)|(0x7f<<5), "1,2,d", 0, v6 }, +{ "sra", F3(2, 0x27, 1), F3(~2, ~0x27, ~1)|(1<<12)|(0x7f<<5), "1,X,d", 0, v6 }, +{ "srl", F3(2, 0x26, 0), F3(~2, ~0x26, ~0)|(1<<12)|(0x7f<<5), "1,2,d", 0, v6 }, +{ "srl", F3(2, 0x26, 1), F3(~2, ~0x26, ~1)|(1<<12)|(0x7f<<5), "1,X,d", 0, v6 }, + +{ "sllx", F3(2, 0x25, 0)|(1<<12), F3(~2, ~0x25, ~0)|(0x7f<<5), "1,2,d", 0, v9 }, +{ "sllx", F3(2, 0x25, 1)|(1<<12), F3(~2, ~0x25, ~1)|(0x3f<<6), "1,Y,d", 0, v9 }, +{ "srax", F3(2, 0x27, 0)|(1<<12), F3(~2, ~0x27, ~0)|(0x7f<<5), "1,2,d", 0, v9 }, +{ "srax", F3(2, 0x27, 1)|(1<<12), F3(~2, ~0x27, ~1)|(0x3f<<6), "1,Y,d", 0, v9 }, +{ "srlx", F3(2, 0x26, 0)|(1<<12), F3(~2, ~0x26, ~0)|(0x7f<<5), "1,2,d", 0, v9 }, +{ "srlx", F3(2, 0x26, 1)|(1<<12), F3(~2, ~0x26, ~1)|(0x3f<<6), "1,Y,d", 0, v9 }, + +{ "mulscc", F3(2, 0x24, 0), F3(~2, ~0x24, ~0)|ASI(~0), "1,2,d", 0, v6 }, +{ "mulscc", F3(2, 0x24, 1), F3(~2, ~0x24, ~1), "1,i,d", 0, v6 }, + +{ "divscc", F3(2, 0x1d, 0), F3(~2, ~0x1d, ~0)|ASI(~0), "1,2,d", 0, sparclite }, +{ "divscc", F3(2, 0x1d, 1), F3(~2, ~0x1d, ~1), "1,i,d", 0, sparclite }, + +{ "scan", F3(2, 0x2c, 0), F3(~2, ~0x2c, ~0)|ASI(~0), "1,2,d", 0, sparclet|sparclite }, +{ "scan", F3(2, 0x2c, 1), F3(~2, ~0x2c, ~1), "1,i,d", 0, sparclet|sparclite }, + +{ "popc", F3(2, 0x2e, 0), F3(~2, ~0x2e, ~0)|RS1_G0|ASI(~0),"2,d", F_POPC, v9 }, +{ "popc", F3(2, 0x2e, 1), F3(~2, ~0x2e, ~1)|RS1_G0, "i,d", F_POPC, v9 }, + +{ "clr", F3(2, 0x02, 0), F3(~2, ~0x02, ~0)|RD_G0|RS1_G0|ASI_RS2(~0), "d", F_ALIAS, v6 }, /* or %g0,%g0,d */ +{ "clr", F3(2, 0x02, 1), F3(~2, ~0x02, ~1)|RS1_G0|SIMM13(~0), "d", F_ALIAS, v6 }, /* or %g0,0,d */ +{ "clr", F3(3, 0x04, 0), F3(~3, ~0x04, ~0)|RD_G0|ASI(~0), "[1+2]", F_ALIAS, v6 }, +{ "clr", F3(3, 0x04, 0), F3(~3, ~0x04, ~0)|RD_G0|ASI_RS2(~0), "[1]", F_ALIAS, v6 }, /* st %g0,[rs1+%g0] */ +{ "clr", F3(3, 0x04, 1), F3(~3, ~0x04, ~1)|RD_G0, "[1+i]", F_ALIAS, v6 }, +{ "clr", F3(3, 0x04, 1), F3(~3, ~0x04, ~1)|RD_G0, "[i+1]", F_ALIAS, v6 }, +{ "clr", F3(3, 0x04, 1), F3(~3, ~0x04, ~1)|RD_G0|RS1_G0, "[i]", F_ALIAS, v6 }, +{ "clr", F3(3, 0x04, 1), F3(~3, ~0x04, ~1)|RD_G0|SIMM13(~0), "[1]", F_ALIAS, v6 }, /* st %g0,[rs1+0] */ + +{ "clrb", F3(3, 0x05, 0), F3(~3, ~0x05, ~0)|RD_G0|ASI(~0), "[1+2]", F_ALIAS, v6 }, +{ "clrb", F3(3, 0x05, 0), F3(~3, ~0x05, ~0)|RD_G0|ASI_RS2(~0), "[1]", F_ALIAS, v6 }, /* stb %g0,[rs1+%g0] */ +{ "clrb", F3(3, 0x05, 1), F3(~3, ~0x05, ~1)|RD_G0, "[1+i]", F_ALIAS, v6 }, +{ "clrb", F3(3, 0x05, 1), F3(~3, ~0x05, ~1)|RD_G0, "[i+1]", F_ALIAS, v6 }, +{ "clrb", F3(3, 0x05, 1), F3(~3, ~0x05, ~1)|RD_G0|RS1_G0, "[i]", F_ALIAS, v6 }, +{ "clrb", F3(3, 0x05, 1), F3(~3, ~0x05, ~1)|RD_G0|SIMM13(~0), "[1]", F_ALIAS, v6 }, /* stb %g0,[rs1+0] */ + +{ "clrh", F3(3, 0x06, 0), F3(~3, ~0x06, ~0)|RD_G0|ASI(~0), "[1+2]", F_ALIAS, v6 }, +{ "clrh", F3(3, 0x06, 0), F3(~3, ~0x06, ~0)|RD_G0|ASI_RS2(~0), "[1]", F_ALIAS, v6 }, /* sth %g0,[rs1+%g0] */ +{ "clrh", F3(3, 0x06, 1), F3(~3, ~0x06, ~1)|RD_G0, "[1+i]", F_ALIAS, v6 }, +{ "clrh", F3(3, 0x06, 1), F3(~3, ~0x06, ~1)|RD_G0, "[i+1]", F_ALIAS, v6 }, +{ "clrh", F3(3, 0x06, 1), F3(~3, ~0x06, ~1)|RD_G0|RS1_G0, "[i]", F_ALIAS, v6 }, +{ "clrh", F3(3, 0x06, 1), F3(~3, ~0x06, ~1)|RD_G0|SIMM13(~0), "[1]", F_ALIAS, v6 }, /* sth %g0,[rs1+0] */ + +{ "clrx", F3(3, 0x0e, 0), F3(~3, ~0x0e, ~0)|RD_G0|ASI(~0), "[1+2]", F_ALIAS, v9 }, +{ "clrx", F3(3, 0x0e, 0), F3(~3, ~0x0e, ~0)|RD_G0|ASI_RS2(~0), "[1]", F_ALIAS, v9 }, /* stx %g0,[rs1+%g0] */ +{ "clrx", F3(3, 0x0e, 1), F3(~3, ~0x0e, ~1)|RD_G0, "[1+i]", F_ALIAS, v9 }, +{ "clrx", F3(3, 0x0e, 1), F3(~3, ~0x0e, ~1)|RD_G0, "[i+1]", F_ALIAS, v9 }, +{ "clrx", F3(3, 0x0e, 1), F3(~3, ~0x0e, ~1)|RD_G0|RS1_G0, "[i]", F_ALIAS, v9 }, +{ "clrx", F3(3, 0x0e, 1), F3(~3, ~0x0e, ~1)|RD_G0|SIMM13(~0), "[1]", F_ALIAS, v9 }, /* stx %g0,[rs1+0] */ + +{ "orcc", F3(2, 0x12, 0), F3(~2, ~0x12, ~0)|ASI(~0), "1,2,d", 0, v6 }, +{ "orcc", F3(2, 0x12, 1), F3(~2, ~0x12, ~1), "1,i,d", 0, v6 }, +{ "orcc", F3(2, 0x12, 1), F3(~2, ~0x12, ~1), "i,1,d", 0, v6 }, + +/* This is not a commutative instruction. */ +{ "orncc", F3(2, 0x16, 0), F3(~2, ~0x16, ~0)|ASI(~0), "1,2,d", 0, v6 }, +{ "orncc", F3(2, 0x16, 1), F3(~2, ~0x16, ~1), "1,i,d", 0, v6 }, + +/* This is not a commutative instruction. */ +{ "orn", F3(2, 0x06, 0), F3(~2, ~0x06, ~0)|ASI(~0), "1,2,d", 0, v6 }, +{ "orn", F3(2, 0x06, 1), F3(~2, ~0x06, ~1), "1,i,d", 0, v6 }, + +{ "tst", F3(2, 0x12, 0), F3(~2, ~0x12, ~0)|RD_G0|ASI_RS2(~0), "1", 0, v6 }, /* orcc rs1, %g0, %g0 */ +{ "tst", F3(2, 0x12, 0), F3(~2, ~0x12, ~0)|RD_G0|RS1_G0|ASI(~0), "2", 0, v6 }, /* orcc %g0, rs2, %g0 */ +{ "tst", F3(2, 0x12, 1), F3(~2, ~0x12, ~1)|RD_G0|SIMM13(~0), "1", 0, v6 }, /* orcc rs1, 0, %g0 */ + +{ "wr", F3(2, 0x30, 0), F3(~2, ~0x30, ~0)|ASI(~0), "1,2,m", 0, v8 }, /* wr r,r,%asrX */ +{ "wr", F3(2, 0x30, 1), F3(~2, ~0x30, ~1), "1,i,m", 0, v8 }, /* wr r,i,%asrX */ +{ "wr", F3(2, 0x30, 0), F3(~2, ~0x30, ~0)|RS1_G0|ASI(~0), "2,m", F_ALIAS, v8 }, /* wr %g0,rs2,%asrX */ +{ "wr", F3(2, 0x30, 1), F3(~2, ~0x30, ~1)|RS1_G0, "i,m", F_ALIAS, v8 }, /* wr %g0,i,%asrX */ +{ "wr", F3(2, 0x30, 0), F3(~2, ~0x30, ~0)|ASI_RS2(~0), "1,m", F_ALIAS, v8 }, /* wr rs1,%g0,%asrX */ +{ "wr", F3(2, 0x30, 0), F3(~2, ~0x30, ~0)|RD_G0|ASI(~0), "1,2,y", 0, v6 }, /* wr r,r,%y */ +{ "wr", F3(2, 0x30, 1), F3(~2, ~0x30, ~1)|RD_G0, "1,i,y", 0, v6 }, /* wr r,i,%y */ +{ "wr", F3(2, 0x30, 0), F3(~2, ~0x30, ~0)|RD_G0|RS1_G0|ASI(~0), "2,y", F_ALIAS, v6 }, /* wr %g0,rs2,%y */ +{ "wr", F3(2, 0x30, 1), F3(~2, ~0x30, ~1)|RD_G0|RS1_G0, "i,y", F_ALIAS, v6 }, /* wr %g0,i,%y */ +{ "wr", F3(2, 0x30, 0), F3(~2, ~0x30, ~0)|RD_G0|ASI_RS2(~0), "1,y", F_ALIAS, v6 }, /* wr rs1,%g0,%y */ +{ "wr", F3(2, 0x31, 0), F3(~2, ~0x31, ~0)|RD_G0|ASI(~0), "1,2,p", 0, v6notv9 }, /* wr r,r,%psr */ +{ "wr", F3(2, 0x31, 1), F3(~2, ~0x31, ~1)|RD_G0, "1,i,p", 0, v6notv9 }, /* wr r,i,%psr */ +{ "wr", F3(2, 0x31, 0), F3(~2, ~0x31, ~0)|RD_G0|RS1_G0|ASI(~0), "2,p", F_ALIAS, v6notv9 }, /* wr %g0,rs2,%psr */ +{ "wr", F3(2, 0x31, 1), F3(~2, ~0x31, ~1)|RD_G0|RS1_G0, "i,p", F_ALIAS, v6notv9 }, /* wr %g0,i,%psr */ +{ "wr", F3(2, 0x31, 0), F3(~2, ~0x31, ~0)|RD_G0|ASI_RS2(~0), "1,p", F_ALIAS, v6notv9 }, /* wr rs1,%g0,%psr */ +{ "wr", F3(2, 0x32, 0), F3(~2, ~0x32, ~0)|RD_G0|ASI(~0), "1,2,w", 0, v6notv9 }, /* wr r,r,%wim */ +{ "wr", F3(2, 0x32, 1), F3(~2, ~0x32, ~1)|RD_G0, "1,i,w", 0, v6notv9 }, /* wr r,i,%wim */ +{ "wr", F3(2, 0x32, 0), F3(~2, ~0x32, ~0)|RD_G0|RS1_G0|ASI(~0), "2,w", F_ALIAS, v6notv9 }, /* wr %g0,rs2,%wim */ +{ "wr", F3(2, 0x32, 1), F3(~2, ~0x32, ~1)|RD_G0|RS1_G0, "i,w", F_ALIAS, v6notv9 }, /* wr %g0,i,%wim */ +{ "wr", F3(2, 0x32, 0), F3(~2, ~0x32, ~0)|RD_G0|ASI_RS2(~0), "1,w", F_ALIAS, v6notv9 }, /* wr rs1,%g0,%wim */ +{ "wr", F3(2, 0x33, 0), F3(~2, ~0x33, ~0)|RD_G0|ASI(~0), "1,2,t", 0, v6notv9 }, /* wr r,r,%tbr */ +{ "wr", F3(2, 0x33, 1), F3(~2, ~0x33, ~1)|RD_G0, "1,i,t", 0, v6notv9 }, /* wr r,i,%tbr */ +{ "wr", F3(2, 0x33, 0), F3(~2, ~0x33, ~0)|RD_G0|RS1_G0|ASI(~0), "2,t", F_ALIAS, v6notv9 }, /* wr %g0,rs2,%tbr */ +{ "wr", F3(2, 0x33, 1), F3(~2, ~0x33, ~1)|RD_G0|RS1_G0, "i,t", F_ALIAS, v6notv9 }, /* wr %g0,i,%tbr */ +{ "wr", F3(2, 0x33, 0), F3(~2, ~0x33, ~0)|RD_G0|ASI_RS2(~0), "1,t", F_ALIAS, v6notv9 }, /* wr rs1,%g0,%tbr */ + +{ "wr", F3(2, 0x30, 0)|RD(2), F3(~2, ~0x30, ~0)|RD(~2)|ASI(~0), "1,2,E", 0, v9 }, /* wr r,r,%ccr */ +{ "wr", F3(2, 0x30, 1)|RD(2), F3(~2, ~0x30, ~1)|RD(~2), "1,i,E", 0, v9 }, /* wr r,i,%ccr */ +{ "wr", F3(2, 0x30, 0)|RD(3), F3(~2, ~0x30, ~0)|RD(~3)|ASI(~0), "1,2,o", 0, v9 }, /* wr r,r,%asi */ +{ "wr", F3(2, 0x30, 1)|RD(3), F3(~2, ~0x30, ~1)|RD(~3), "1,i,o", 0, v9 }, /* wr r,i,%asi */ +{ "wr", F3(2, 0x30, 0)|RD(6), F3(~2, ~0x30, ~0)|RD(~6)|ASI(~0), "1,2,s", 0, v9 }, /* wr r,r,%fprs */ +{ "wr", F3(2, 0x30, 1)|RD(6), F3(~2, ~0x30, ~1)|RD(~6), "1,i,s", 0, v9 }, /* wr r,i,%fprs */ + +{ "wr", F3(2, 0x30, 0)|RD(16), F3(~2, ~0x30, ~0)|RD(~16)|ASI(~0), "1,2,_", F_VIS, v9a }, /* wr r,r,%pcr */ +{ "wr", F3(2, 0x30, 1)|RD(16), F3(~2, ~0x30, ~1)|RD(~16), "1,i,_", F_VIS, v9a }, /* wr r,i,%pcr */ +{ "wr", F3(2, 0x30, 0)|RD(17), F3(~2, ~0x30, ~0)|RD(~17)|ASI(~0), "1,2,_", F_VIS, v9a }, /* wr r,r,%pic */ +{ "wr", F3(2, 0x30, 1)|RD(17), F3(~2, ~0x30, ~1)|RD(~17), "1,i,_", F_VIS, v9a }, /* wr r,i,%pic */ +{ "wr", F3(2, 0x30, 0)|RD(18), F3(~2, ~0x30, ~0)|RD(~18)|ASI(~0), "1,2,_", F_VIS, v9a }, /* wr r,r,%dcr */ +{ "wr", F3(2, 0x30, 1)|RD(18), F3(~2, ~0x30, ~1)|RD(~18), "1,i,_", F_VIS, v9a }, /* wr r,i,%dcr */ +{ "wr", F3(2, 0x30, 0)|RD(19), F3(~2, ~0x30, ~0)|RD(~19)|ASI(~0), "1,2,_", F_VIS, v9a }, /* wr r,r,%gsr */ +{ "wr", F3(2, 0x30, 1)|RD(19), F3(~2, ~0x30, ~1)|RD(~19), "1,i,_", F_VIS, v9a }, /* wr r,i,%gsr */ +{ "wr", F3(2, 0x30, 0)|RD(20), F3(~2, ~0x30, ~0)|RD(~20)|ASI(~0), "1,2,_", F_VIS, v9a }, /* wr r,r,%set_softint */ +{ "wr", F3(2, 0x30, 1)|RD(20), F3(~2, ~0x30, ~1)|RD(~20), "1,i,_", F_VIS, v9a }, /* wr r,i,%set_softint */ +{ "wr", F3(2, 0x30, 0)|RD(21), F3(~2, ~0x30, ~0)|RD(~21)|ASI(~0), "1,2,_", F_VIS, v9a }, /* wr r,r,%clear_softint */ +{ "wr", F3(2, 0x30, 1)|RD(21), F3(~2, ~0x30, ~1)|RD(~21), "1,i,_", F_VIS, v9a }, /* wr r,i,%clear_softint */ +{ "wr", F3(2, 0x30, 0)|RD(22), F3(~2, ~0x30, ~0)|RD(~22)|ASI(~0), "1,2,_", F_VIS, v9a }, /* wr r,r,%softint */ +{ "wr", F3(2, 0x30, 1)|RD(22), F3(~2, ~0x30, ~1)|RD(~22), "1,i,_", F_VIS, v9a }, /* wr r,i,%softint */ +{ "wr", F3(2, 0x30, 0)|RD(23), F3(~2, ~0x30, ~0)|RD(~23)|ASI(~0), "1,2,_", F_VIS, v9a }, /* wr r,r,%tick_cmpr */ +{ "wr", F3(2, 0x30, 1)|RD(23), F3(~2, ~0x30, ~1)|RD(~23), "1,i,_", F_VIS, v9a }, /* wr r,i,%tick_cmpr */ +{ "wr", F3(2, 0x30, 0)|RD(24), F3(~2, ~0x30, ~0)|RD(~24)|ASI(~0), "1,2,_", F_VIS2, v9b }, /* wr r,r,%sys_tick */ +{ "wr", F3(2, 0x30, 1)|RD(24), F3(~2, ~0x30, ~1)|RD(~24), "1,i,_", F_VIS2, v9b }, /* wr r,i,%sys_tick */ +{ "wr", F3(2, 0x30, 0)|RD(25), F3(~2, ~0x30, ~0)|RD(~25)|ASI(~0), "1,2,_", F_VIS2, v9b }, /* wr r,r,%sys_tick_cmpr */ +{ "wr", F3(2, 0x30, 1)|RD(25), F3(~2, ~0x30, ~1)|RD(~25), "1,i,_", F_VIS2, v9b }, /* wr r,i,%sys_tick_cmpr */ +{ "wr", F3(2, 0x30, 0)|RD(28), F3(~2, ~0x30, ~0)|RD(~28)|ASI(~0), "1,2,_", F_VIS3, v9b }, /* wr r,r,%cps */ +{ "wr", F3(2, 0x30, 1)|RD(28), F3(~2, ~0x30, ~1)|RD(~28), "1,i,_", F_VIS3, v9b }, /* wr r,i,%cps */ + +{ "rd", F3(2, 0x28, 0), F3(~2, ~0x28, ~0)|SIMM13(~0), "M,d", 0, v8 }, /* rd %asrX,r */ +{ "rd", F3(2, 0x28, 0), F3(~2, ~0x28, ~0)|RS1_G0|SIMM13(~0), "y,d", 0, v6 }, /* rd %y,r */ +{ "rd", F3(2, 0x29, 0), F3(~2, ~0x29, ~0)|RS1_G0|SIMM13(~0), "p,d", 0, v6notv9 }, /* rd %psr,r */ +{ "rd", F3(2, 0x2a, 0), F3(~2, ~0x2a, ~0)|RS1_G0|SIMM13(~0), "w,d", 0, v6notv9 }, /* rd %wim,r */ +{ "rd", F3(2, 0x2b, 0), F3(~2, ~0x2b, ~0)|RS1_G0|SIMM13(~0), "t,d", 0, v6notv9 }, /* rd %tbr,r */ + +{ "rd", F3(2, 0x28, 0)|RS1(2), F3(~2, ~0x28, ~0)|RS1(~2)|SIMM13(~0), "E,d", 0, v9 }, /* rd %ccr,r */ +{ "rd", F3(2, 0x28, 0)|RS1(3), F3(~2, ~0x28, ~0)|RS1(~3)|SIMM13(~0), "o,d", 0, v9 }, /* rd %asi,r */ +{ "rd", F3(2, 0x28, 0)|RS1(4), F3(~2, ~0x28, ~0)|RS1(~4)|SIMM13(~0), "W,d", 0, v9 }, /* rd %tick,r */ +{ "rd", F3(2, 0x28, 0)|RS1(5), F3(~2, ~0x28, ~0)|RS1(~5)|SIMM13(~0), "P,d", 0, v9 }, /* rd %pc,r */ +{ "rd", F3(2, 0x28, 0)|RS1(6), F3(~2, ~0x28, ~0)|RS1(~6)|SIMM13(~0), "s,d", 0, v9 }, /* rd %fprs,r */ + +{ "rd", F3(2, 0x28, 0)|RS1(16), F3(~2, ~0x28, ~0)|RS1(~16)|SIMM13(~0), "/,d", F_VIS, v9a }, /* rd %pcr,r */ +{ "rd", F3(2, 0x28, 0)|RS1(17), F3(~2, ~0x28, ~0)|RS1(~17)|SIMM13(~0), "/,d", F_VIS, v9a }, /* rd %pic,r */ +{ "rd", F3(2, 0x28, 0)|RS1(18), F3(~2, ~0x28, ~0)|RS1(~18)|SIMM13(~0), "/,d", F_VIS, v9a }, /* rd %dcr,r */ +{ "rd", F3(2, 0x28, 0)|RS1(19), F3(~2, ~0x28, ~0)|RS1(~19)|SIMM13(~0), "/,d", F_VIS, v9a }, /* rd %gsr,r */ +{ "rd", F3(2, 0x28, 0)|RS1(22), F3(~2, ~0x28, ~0)|RS1(~22)|SIMM13(~0), "/,d", F_VIS, v9a }, /* rd %softint,r */ +{ "rd", F3(2, 0x28, 0)|RS1(23), F3(~2, ~0x28, ~0)|RS1(~23)|SIMM13(~0), "/,d", F_VIS, v9a }, /* rd %tick_cmpr,r */ +{ "rd", F3(2, 0x28, 0)|RS1(24), F3(~2, ~0x28, ~0)|RS1(~24)|SIMM13(~0), "/,d", F_VIS2, v9b }, /* rd %sys_tick,r */ +{ "rd", F3(2, 0x28, 0)|RS1(25), F3(~2, ~0x28, ~0)|RS1(~25)|SIMM13(~0), "/,d", F_VIS2, v9b }, /* rd %sys_tick_cmpr,r */ +{ "rd", F3(2, 0x28, 0)|RS1(28), F3(~2, ~0x28, ~0)|RS1(~28)|SIMM13(~0), "/,d", F_VIS3, v9b }, /* rd %cps,r */ + +{ "rdpr", F3(2, 0x2a, 0), F3(~2, ~0x2a, ~0)|SIMM13(~0), "?,d", 0, v9 }, /* rdpr %priv,r */ +{ "wrpr", F3(2, 0x32, 0), F3(~2, ~0x32, ~0), "1,2,!", 0, v9 }, /* wrpr r1,r2,%priv */ +{ "wrpr", F3(2, 0x32, 0), F3(~2, ~0x32, ~0)|SIMM13(~0), "1,!", 0, v9 }, /* wrpr r1,%priv */ +{ "wrpr", F3(2, 0x32, 1), F3(~2, ~0x32, ~1), "1,i,!", 0, v9 }, /* wrpr r1,i,%priv */ +{ "wrpr", F3(2, 0x32, 1), F3(~2, ~0x32, ~1), "i,1,!", F_ALIAS, v9 }, /* wrpr i,r1,%priv */ +{ "wrpr", F3(2, 0x32, 1), F3(~2, ~0x32, ~1)|RS1(~0), "i,!", 0, v9 }, /* wrpr i,%priv */ + +{ "rdhpr", F3(2, 0x29, 0), F3(~2, ~0x29, ~0)|SIMM13(~0), "$,d", 0, v9 }, /* rdhpr %hpriv,r */ +{ "wrhpr", F3(2, 0x33, 0), F3(~2, ~0x33, ~0), "1,2,%", 0, v9 }, /* wrhpr r1,r2,%hpriv */ +{ "wrhpr", F3(2, 0x33, 0), F3(~2, ~0x33, ~0)|SIMM13(~0), "1,%", 0, v9 }, /* wrhpr r1,%hpriv */ +{ "wrhpr", F3(2, 0x33, 1), F3(~2, ~0x33, ~1), "1,i,%", 0, v9 }, /* wrhpr r1,i,%hpriv */ +{ "wrhpr", F3(2, 0x33, 1), F3(~2, ~0x33, ~1), "i,1,%", F_ALIAS, v9 }, /* wrhpr i,r1,%hpriv */ +{ "wrhpr", F3(2, 0x33, 1), F3(~2, ~0x33, ~1)|RS1(~0), "i,%", 0, v9 }, /* wrhpr i,%hpriv */ + +/* ??? This group seems wrong. A three operand move? */ +{ "mov", F3(2, 0x30, 0), F3(~2, ~0x30, ~0)|ASI(~0), "1,2,m", F_ALIAS, v8 }, /* wr r,r,%asrX */ +{ "mov", F3(2, 0x30, 1), F3(~2, ~0x30, ~1), "1,i,m", F_ALIAS, v8 }, /* wr r,i,%asrX */ +{ "mov", F3(2, 0x30, 0), F3(~2, ~0x30, ~0)|RD_G0|ASI(~0), "1,2,y", F_ALIAS, v6 }, /* wr r,r,%y */ +{ "mov", F3(2, 0x30, 1), F3(~2, ~0x30, ~1)|RD_G0, "1,i,y", F_ALIAS, v6 }, /* wr r,i,%y */ +{ "mov", F3(2, 0x31, 0), F3(~2, ~0x31, ~0)|RD_G0|ASI(~0), "1,2,p", F_ALIAS, v6notv9 }, /* wr r,r,%psr */ +{ "mov", F3(2, 0x31, 1), F3(~2, ~0x31, ~1)|RD_G0, "1,i,p", F_ALIAS, v6notv9 }, /* wr r,i,%psr */ +{ "mov", F3(2, 0x32, 0), F3(~2, ~0x32, ~0)|RD_G0|ASI(~0), "1,2,w", F_ALIAS, v6notv9 }, /* wr r,r,%wim */ +{ "mov", F3(2, 0x32, 1), F3(~2, ~0x32, ~1)|RD_G0, "1,i,w", F_ALIAS, v6notv9 }, /* wr r,i,%wim */ +{ "mov", F3(2, 0x33, 0), F3(~2, ~0x33, ~0)|RD_G0|ASI(~0), "1,2,t", F_ALIAS, v6notv9 }, /* wr r,r,%tbr */ +{ "mov", F3(2, 0x33, 1), F3(~2, ~0x33, ~1)|RD_G0, "1,i,t", F_ALIAS, v6notv9 }, /* wr r,i,%tbr */ + +{ "mov", F3(2, 0x28, 0), F3(~2, ~0x28, ~0)|SIMM13(~0), "M,d", F_ALIAS, v8 }, /* rd %asr1,r */ +{ "mov", F3(2, 0x28, 0), F3(~2, ~0x28, ~0)|RS1_G0|SIMM13(~0), "y,d", F_ALIAS, v6 }, /* rd %y,r */ +{ "mov", F3(2, 0x29, 0), F3(~2, ~0x29, ~0)|RS1_G0|SIMM13(~0), "p,d", F_ALIAS, v6notv9 }, /* rd %psr,r */ +{ "mov", F3(2, 0x2a, 0), F3(~2, ~0x2a, ~0)|RS1_G0|SIMM13(~0), "w,d", F_ALIAS, v6notv9 }, /* rd %wim,r */ +{ "mov", F3(2, 0x2b, 0), F3(~2, ~0x2b, ~0)|RS1_G0|SIMM13(~0), "t,d", F_ALIAS, v6notv9 }, /* rd %tbr,r */ + +{ "mov", F3(2, 0x30, 0), F3(~2, ~0x30, ~0)|RS1_G0|ASI(~0), "2,m", F_ALIAS, v8 }, /* wr %g0,rs2,%asrX */ +{ "mov", F3(2, 0x30, 1), F3(~2, ~0x30, ~1)|RS1_G0, "i,m", F_ALIAS, v8 }, /* wr %g0,i,%asrX */ +{ "mov", F3(2, 0x30, 0), F3(~2, ~0x30, ~0)|ASI_RS2(~0), "1,m", F_ALIAS, v8 }, /* wr rs1,%g0,%asrX */ +{ "mov", F3(2, 0x30, 1), F3(~2, ~0x30, ~1)|SIMM13(~0), "1,m", F_ALIAS, v8 }, /* wr rs1,0,%asrX */ +{ "mov", F3(2, 0x30, 0), F3(~2, ~0x30, ~0)|RD_G0|RS1_G0|ASI(~0), "2,y", F_ALIAS, v6 }, /* wr %g0,rs2,%y */ +{ "mov", F3(2, 0x30, 1), F3(~2, ~0x30, ~1)|RD_G0|RS1_G0, "i,y", F_ALIAS, v6 }, /* wr %g0,i,%y */ +{ "mov", F3(2, 0x30, 0), F3(~2, ~0x30, ~0)|RD_G0|ASI_RS2(~0), "1,y", F_ALIAS, v6 }, /* wr rs1,%g0,%y */ +{ "mov", F3(2, 0x30, 1), F3(~2, ~0x30, ~1)|RD_G0|SIMM13(~0), "1,y", F_ALIAS, v6 }, /* wr rs1,0,%y */ +{ "mov", F3(2, 0x31, 0), F3(~2, ~0x31, ~0)|RD_G0|RS1_G0|ASI(~0), "2,p", F_ALIAS, v6notv9 }, /* wr %g0,rs2,%psr */ +{ "mov", F3(2, 0x31, 1), F3(~2, ~0x31, ~1)|RD_G0|RS1_G0, "i,p", F_ALIAS, v6notv9 }, /* wr %g0,i,%psr */ +{ "mov", F3(2, 0x31, 0), F3(~2, ~0x31, ~0)|RD_G0|ASI_RS2(~0), "1,p", F_ALIAS, v6notv9 }, /* wr rs1,%g0,%psr */ +{ "mov", F3(2, 0x31, 1), F3(~2, ~0x31, ~1)|RD_G0|SIMM13(~0), "1,p", F_ALIAS, v6notv9 }, /* wr rs1,0,%psr */ +{ "mov", F3(2, 0x32, 0), F3(~2, ~0x32, ~0)|RD_G0|RS1_G0|ASI(~0), "2,w", F_ALIAS, v6notv9 }, /* wr %g0,rs2,%wim */ +{ "mov", F3(2, 0x32, 1), F3(~2, ~0x32, ~1)|RD_G0|RS1_G0, "i,w", F_ALIAS, v6notv9 }, /* wr %g0,i,%wim */ +{ "mov", F3(2, 0x32, 0), F3(~2, ~0x32, ~0)|RD_G0|ASI_RS2(~0), "1,w", F_ALIAS, v6notv9 }, /* wr rs1,%g0,%wim */ +{ "mov", F3(2, 0x32, 1), F3(~2, ~0x32, ~1)|RD_G0|SIMM13(~0), "1,w", F_ALIAS, v6notv9 }, /* wr rs1,0,%wim */ +{ "mov", F3(2, 0x33, 0), F3(~2, ~0x33, ~0)|RD_G0|RS1_G0|ASI(~0), "2,t", F_ALIAS, v6notv9 }, /* wr %g0,rs2,%tbr */ +{ "mov", F3(2, 0x33, 1), F3(~2, ~0x33, ~1)|RD_G0|RS1_G0, "i,t", F_ALIAS, v6notv9 }, /* wr %g0,i,%tbr */ +{ "mov", F3(2, 0x33, 0), F3(~2, ~0x33, ~0)|RD_G0|ASI_RS2(~0), "1,t", F_ALIAS, v6notv9 }, /* wr rs1,%g0,%tbr */ +{ "mov", F3(2, 0x33, 1), F3(~2, ~0x33, ~1)|RD_G0|SIMM13(~0), "1,t", F_ALIAS, v6notv9 }, /* wr rs1,0,%tbr */ + +{ "mov", F3(2, 0x02, 0), F3(~2, ~0x02, ~0)|RS1_G0|ASI(~0), "2,d", 0, v6 }, /* or %g0,rs2,d */ +{ "mov", F3(2, 0x02, 1), F3(~2, ~0x02, ~1)|RS1_G0, "i,d", 0, v6 }, /* or %g0,i,d */ +{ "mov", F3(2, 0x02, 0), F3(~2, ~0x02, ~0)|ASI_RS2(~0), "1,d", 0, v6 }, /* or rs1,%g0,d */ +{ "mov", F3(2, 0x02, 1), F3(~2, ~0x02, ~1)|SIMM13(~0), "1,d", 0, v6 }, /* or rs1,0,d */ + +{ "or", F3(2, 0x02, 0), F3(~2, ~0x02, ~0)|ASI(~0), "1,2,d", 0, v6 }, +{ "or", F3(2, 0x02, 1), F3(~2, ~0x02, ~1), "1,i,d", 0, v6 }, +{ "or", F3(2, 0x02, 1), F3(~2, ~0x02, ~1), "i,1,d", 0, v6 }, + +{ "bset", F3(2, 0x02, 0), F3(~2, ~0x02, ~0)|ASI(~0), "2,r", F_ALIAS, v6 }, /* or rd,rs2,rd */ +{ "bset", F3(2, 0x02, 1), F3(~2, ~0x02, ~1), "i,r", F_ALIAS, v6 }, /* or rd,i,rd */ + +/* This is not a commutative instruction. */ +{ "andn", F3(2, 0x05, 0), F3(~2, ~0x05, ~0)|ASI(~0), "1,2,d", 0, v6 }, +{ "andn", F3(2, 0x05, 1), F3(~2, ~0x05, ~1), "1,i,d", 0, v6 }, + +/* This is not a commutative instruction. */ +{ "andncc", F3(2, 0x15, 0), F3(~2, ~0x15, ~0)|ASI(~0), "1,2,d", 0, v6 }, +{ "andncc", F3(2, 0x15, 1), F3(~2, ~0x15, ~1), "1,i,d", 0, v6 }, + +{ "bclr", F3(2, 0x05, 0), F3(~2, ~0x05, ~0)|ASI(~0), "2,r", F_ALIAS, v6 }, /* andn rd,rs2,rd */ +{ "bclr", F3(2, 0x05, 1), F3(~2, ~0x05, ~1), "i,r", F_ALIAS, v6 }, /* andn rd,i,rd */ + +{ "cmp", F3(2, 0x14, 0), F3(~2, ~0x14, ~0)|RD_G0|ASI(~0), "1,2", 0, v6 }, /* subcc rs1,rs2,%g0 */ +{ "cmp", F3(2, 0x14, 1), F3(~2, ~0x14, ~1)|RD_G0, "1,i", 0, v6 }, /* subcc rs1,i,%g0 */ + +{ "sub", F3(2, 0x04, 0), F3(~2, ~0x04, ~0)|ASI(~0), "1,2,d", 0, v6 }, +{ "sub", F3(2, 0x04, 1), F3(~2, ~0x04, ~1), "1,i,d", 0, v6 }, + +{ "subcc", F3(2, 0x14, 0), F3(~2, ~0x14, ~0)|ASI(~0), "1,2,d", 0, v6 }, +{ "subcc", F3(2, 0x14, 1), F3(~2, ~0x14, ~1), "1,i,d", 0, v6 }, + +{ "subx", F3(2, 0x0c, 0), F3(~2, ~0x0c, ~0)|ASI(~0), "1,2,d", 0, v6notv9 }, +{ "subx", F3(2, 0x0c, 1), F3(~2, ~0x0c, ~1), "1,i,d", 0, v6notv9 }, +{ "subc", F3(2, 0x0c, 0), F3(~2, ~0x0c, ~0)|ASI(~0), "1,2,d", 0, v9 }, +{ "subc", F3(2, 0x0c, 1), F3(~2, ~0x0c, ~1), "1,i,d", 0, v9 }, + +{ "subxcc", F3(2, 0x1c, 0), F3(~2, ~0x1c, ~0)|ASI(~0), "1,2,d", 0, v6notv9 }, +{ "subxcc", F3(2, 0x1c, 1), F3(~2, ~0x1c, ~1), "1,i,d", 0, v6notv9 }, +{ "subccc", F3(2, 0x1c, 0), F3(~2, ~0x1c, ~0)|ASI(~0), "1,2,d", 0, v9 }, +{ "subccc", F3(2, 0x1c, 1), F3(~2, ~0x1c, ~1), "1,i,d", 0, v9 }, + +{ "and", F3(2, 0x01, 0), F3(~2, ~0x01, ~0)|ASI(~0), "1,2,d", 0, v6 }, +{ "and", F3(2, 0x01, 1), F3(~2, ~0x01, ~1), "1,i,d", 0, v6 }, +{ "and", F3(2, 0x01, 1), F3(~2, ~0x01, ~1), "i,1,d", 0, v6 }, + +{ "andcc", F3(2, 0x11, 0), F3(~2, ~0x11, ~0)|ASI(~0), "1,2,d", 0, v6 }, +{ "andcc", F3(2, 0x11, 1), F3(~2, ~0x11, ~1), "1,i,d", 0, v6 }, +{ "andcc", F3(2, 0x11, 1), F3(~2, ~0x11, ~1), "i,1,d", 0, v6 }, + +{ "dec", F3(2, 0x04, 1)|SIMM13(0x1), F3(~2, ~0x04, ~1)|SIMM13(~0x0001), "r", F_ALIAS, v6 }, /* sub rd,1,rd */ +{ "dec", F3(2, 0x04, 1), F3(~2, ~0x04, ~1), "i,r", F_ALIAS, v8 }, /* sub rd,imm,rd */ +{ "deccc", F3(2, 0x14, 1)|SIMM13(0x1), F3(~2, ~0x14, ~1)|SIMM13(~0x0001), "r", F_ALIAS, v6 }, /* subcc rd,1,rd */ +{ "deccc", F3(2, 0x14, 1), F3(~2, ~0x14, ~1), "i,r", F_ALIAS, v8 }, /* subcc rd,imm,rd */ +{ "inc", F3(2, 0x00, 1)|SIMM13(0x1), F3(~2, ~0x00, ~1)|SIMM13(~0x0001), "r", F_ALIAS, v6 }, /* add rd,1,rd */ +{ "inc", F3(2, 0x00, 1), F3(~2, ~0x00, ~1), "i,r", F_ALIAS, v8 }, /* add rd,imm,rd */ +{ "inccc", F3(2, 0x10, 1)|SIMM13(0x1), F3(~2, ~0x10, ~1)|SIMM13(~0x0001), "r", F_ALIAS, v6 }, /* addcc rd,1,rd */ +{ "inccc", F3(2, 0x10, 1), F3(~2, ~0x10, ~1), "i,r", F_ALIAS, v8 }, /* addcc rd,imm,rd */ + +{ "btst", F3(2, 0x11, 0), F3(~2, ~0x11, ~0)|RD_G0|ASI(~0), "1,2", F_ALIAS, v6 }, /* andcc rs1,rs2,%g0 */ +{ "btst", F3(2, 0x11, 1), F3(~2, ~0x11, ~1)|RD_G0, "i,1", F_ALIAS, v6 }, /* andcc rs1,i,%g0 */ + +{ "neg", F3(2, 0x04, 0), F3(~2, ~0x04, ~0)|RS1_G0|ASI(~0), "2,d", F_ALIAS, v6 }, /* sub %g0,rs2,rd */ +{ "neg", F3(2, 0x04, 0), F3(~2, ~0x04, ~0)|RS1_G0|ASI(~0), "O", F_ALIAS, v6 }, /* sub %g0,rd,rd */ + +{ "add", F3(2, 0x00, 0), F3(~2, ~0x00, ~0)|ASI(~0), "1,2,d", 0, v6 }, +{ "add", F3(2, 0x00, 1), F3(~2, ~0x00, ~1), "1,i,d", 0, v6 }, +{ "add", F3(2, 0x00, 1), F3(~2, ~0x00, ~1), "i,1,d", 0, v6 }, +{ "addcc", F3(2, 0x10, 0), F3(~2, ~0x10, ~0)|ASI(~0), "1,2,d", 0, v6 }, +{ "addcc", F3(2, 0x10, 1), F3(~2, ~0x10, ~1), "1,i,d", 0, v6 }, +{ "addcc", F3(2, 0x10, 1), F3(~2, ~0x10, ~1), "i,1,d", 0, v6 }, + +{ "addx", F3(2, 0x08, 0), F3(~2, ~0x08, ~0)|ASI(~0), "1,2,d", 0, v6notv9 }, +{ "addx", F3(2, 0x08, 1), F3(~2, ~0x08, ~1), "1,i,d", 0, v6notv9 }, +{ "addx", F3(2, 0x08, 1), F3(~2, ~0x08, ~1), "i,1,d", 0, v6notv9 }, +{ "addc", F3(2, 0x08, 0), F3(~2, ~0x08, ~0)|ASI(~0), "1,2,d", 0, v9 }, +{ "addc", F3(2, 0x08, 1), F3(~2, ~0x08, ~1), "1,i,d", 0, v9 }, +{ "addc", F3(2, 0x08, 1), F3(~2, ~0x08, ~1), "i,1,d", 0, v9 }, + +{ "addxcc", F3(2, 0x18, 0), F3(~2, ~0x18, ~0)|ASI(~0), "1,2,d", 0, v6notv9 }, +{ "addxcc", F3(2, 0x18, 1), F3(~2, ~0x18, ~1), "1,i,d", 0, v6notv9 }, +{ "addxcc", F3(2, 0x18, 1), F3(~2, ~0x18, ~1), "i,1,d", 0, v6notv9 }, +{ "addccc", F3(2, 0x18, 0), F3(~2, ~0x18, ~0)|ASI(~0), "1,2,d", 0, v9 }, +{ "addccc", F3(2, 0x18, 1), F3(~2, ~0x18, ~1), "1,i,d", 0, v9 }, +{ "addccc", F3(2, 0x18, 1), F3(~2, ~0x18, ~1), "i,1,d", 0, v9 }, + +{ "smul", F3(2, 0x0b, 0), F3(~2, ~0x0b, ~0)|ASI(~0), "1,2,d", F_MUL32, v8 }, +{ "smul", F3(2, 0x0b, 1), F3(~2, ~0x0b, ~1), "1,i,d", F_MUL32, v8 }, +{ "smul", F3(2, 0x0b, 1), F3(~2, ~0x0b, ~1), "i,1,d", F_MUL32, v8 }, +{ "smulcc", F3(2, 0x1b, 0), F3(~2, ~0x1b, ~0)|ASI(~0), "1,2,d", F_MUL32, v8 }, +{ "smulcc", F3(2, 0x1b, 1), F3(~2, ~0x1b, ~1), "1,i,d", F_MUL32, v8 }, +{ "smulcc", F3(2, 0x1b, 1), F3(~2, ~0x1b, ~1), "i,1,d", F_MUL32, v8 }, +{ "umul", F3(2, 0x0a, 0), F3(~2, ~0x0a, ~0)|ASI(~0), "1,2,d", F_MUL32, v8 }, +{ "umul", F3(2, 0x0a, 1), F3(~2, ~0x0a, ~1), "1,i,d", F_MUL32, v8 }, +{ "umul", F3(2, 0x0a, 1), F3(~2, ~0x0a, ~1), "i,1,d", F_MUL32, v8 }, +{ "umulcc", F3(2, 0x1a, 0), F3(~2, ~0x1a, ~0)|ASI(~0), "1,2,d", F_MUL32, v8 }, +{ "umulcc", F3(2, 0x1a, 1), F3(~2, ~0x1a, ~1), "1,i,d", F_MUL32, v8 }, +{ "umulcc", F3(2, 0x1a, 1), F3(~2, ~0x1a, ~1), "i,1,d", F_MUL32, v8 }, +{ "sdiv", F3(2, 0x0f, 0), F3(~2, ~0x0f, ~0)|ASI(~0), "1,2,d", F_DIV32, v8 }, +{ "sdiv", F3(2, 0x0f, 1), F3(~2, ~0x0f, ~1), "1,i,d", F_DIV32, v8 }, +{ "sdiv", F3(2, 0x0f, 1), F3(~2, ~0x0f, ~1), "i,1,d", F_DIV32, v8 }, +{ "sdivcc", F3(2, 0x1f, 0), F3(~2, ~0x1f, ~0)|ASI(~0), "1,2,d", F_DIV32, v8 }, +{ "sdivcc", F3(2, 0x1f, 1), F3(~2, ~0x1f, ~1), "1,i,d", F_DIV32, v8 }, +{ "sdivcc", F3(2, 0x1f, 1), F3(~2, ~0x1f, ~1), "i,1,d", F_DIV32, v8 }, +{ "udiv", F3(2, 0x0e, 0), F3(~2, ~0x0e, ~0)|ASI(~0), "1,2,d", F_DIV32, v8 }, +{ "udiv", F3(2, 0x0e, 1), F3(~2, ~0x0e, ~1), "1,i,d", F_DIV32, v8 }, +{ "udiv", F3(2, 0x0e, 1), F3(~2, ~0x0e, ~1), "i,1,d", F_DIV32, v8 }, +{ "udivcc", F3(2, 0x1e, 0), F3(~2, ~0x1e, ~0)|ASI(~0), "1,2,d", F_DIV32, v8 }, +{ "udivcc", F3(2, 0x1e, 1), F3(~2, ~0x1e, ~1), "1,i,d", F_DIV32, v8 }, +{ "udivcc", F3(2, 0x1e, 1), F3(~2, ~0x1e, ~1), "i,1,d", F_DIV32, v8 }, + +{ "mulx", F3(2, 0x09, 0), F3(~2, ~0x09, ~0)|ASI(~0), "1,2,d", 0, v9 }, +{ "mulx", F3(2, 0x09, 1), F3(~2, ~0x09, ~1), "1,i,d", 0, v9 }, +{ "sdivx", F3(2, 0x2d, 0), F3(~2, ~0x2d, ~0)|ASI(~0), "1,2,d", 0, v9 }, +{ "sdivx", F3(2, 0x2d, 1), F3(~2, ~0x2d, ~1), "1,i,d", 0, v9 }, +{ "udivx", F3(2, 0x0d, 0), F3(~2, ~0x0d, ~0)|ASI(~0), "1,2,d", 0, v9 }, +{ "udivx", F3(2, 0x0d, 1), F3(~2, ~0x0d, ~1), "1,i,d", 0, v9 }, + +{ "call", F1(0x1), F1(~0x1), "L", F_JSR|F_DELAYED, v6 }, +{ "call", F1(0x1), F1(~0x1), "L,#", F_JSR|F_DELAYED, v6 }, + +{ "call", F3(2, 0x38, 0)|RD(0xf), F3(~2, ~0x38, ~0)|RD(~0xf)|ASI(~0), "1+2", F_JSR|F_DELAYED, v6 }, /* jmpl rs1+rs2,%o7 */ +{ "call", F3(2, 0x38, 0)|RD(0xf), F3(~2, ~0x38, ~0)|RD(~0xf)|ASI(~0), "1+2,#", F_JSR|F_DELAYED, v6 }, +{ "call", F3(2, 0x38, 0)|RD(0xf), F3(~2, ~0x38, ~0)|RD(~0xf)|ASI_RS2(~0), "1", F_JSR|F_DELAYED, v6 }, /* jmpl rs1+%g0,%o7 */ +{ "call", F3(2, 0x38, 0)|RD(0xf), F3(~2, ~0x38, ~0)|RD(~0xf)|ASI_RS2(~0), "1,#", F_JSR|F_DELAYED, v6 }, +{ "call", F3(2, 0x38, 1)|RD(0xf), F3(~2, ~0x38, ~1)|RD(~0xf), "1+i", F_JSR|F_DELAYED, v6 }, /* jmpl rs1+i,%o7 */ +{ "call", F3(2, 0x38, 1)|RD(0xf), F3(~2, ~0x38, ~1)|RD(~0xf), "1+i,#", F_JSR|F_DELAYED, v6 }, +{ "call", F3(2, 0x38, 1)|RD(0xf), F3(~2, ~0x38, ~1)|RD(~0xf), "i+1", F_JSR|F_DELAYED, v6 }, /* jmpl i+rs1,%o7 */ +{ "call", F3(2, 0x38, 1)|RD(0xf), F3(~2, ~0x38, ~1)|RD(~0xf), "i+1,#", F_JSR|F_DELAYED, v6 }, +{ "call", F3(2, 0x38, 1)|RD(0xf), F3(~2, ~0x38, ~1)|RD(~0xf)|RS1_G0, "i", F_JSR|F_DELAYED, v6 }, /* jmpl %g0+i,%o7 */ +{ "call", F3(2, 0x38, 1)|RD(0xf), F3(~2, ~0x38, ~1)|RD(~0xf)|RS1_G0, "i,#", F_JSR|F_DELAYED, v6 }, +{ "call", F3(2, 0x38, 1)|RD(0xf), F3(~2, ~0x38, ~1)|RD(~0xf)|SIMM13(~0), "1", F_JSR|F_DELAYED, v6 }, /* jmpl rs1+0,%o7 */ +{ "call", F3(2, 0x38, 1)|RD(0xf), F3(~2, ~0x38, ~1)|RD(~0xf)|SIMM13(~0), "1,#", F_JSR|F_DELAYED, v6 }, + +{ "chkpt", F2(0, 1)|CONDA|ANNUL|(1<<20), F2(~0, ~1)|((~CONDA)&COND(~0)), "G", F_TRANS, v9b }, + +/* Conditional instructions. + + Because this part of the table was such a mess earlier, I have + macrofied it so that all the branches and traps are generated from + a single-line description of each condition value. John Gilmore. */ + +/* Define branches -- one annulled, one without, etc. */ +#define br(opcode, mask, lose, flags) \ + { opcode, (mask)|ANNUL, (lose), ",a l", (flags), v6 }, \ + { opcode, (mask) , (lose)|ANNUL, "l", (flags), v6 } + +#define brx(opcode, mask, lose, flags) /* v9 */ \ + { opcode, (mask)|(2<<20)|BPRED, ANNUL|(lose), "Z,G", (flags), v9 }, \ + { opcode, (mask)|(2<<20)|BPRED, ANNUL|(lose), ",T Z,G", (flags), v9 }, \ + { opcode, (mask)|(2<<20)|BPRED|ANNUL, (lose), ",a Z,G", (flags), v9 }, \ + { opcode, (mask)|(2<<20)|BPRED|ANNUL, (lose), ",a,T Z,G", (flags), v9 }, \ + { opcode, (mask)|(2<<20), ANNUL|BPRED|(lose), ",N Z,G", (flags), v9 }, \ + { opcode, (mask)|(2<<20)|ANNUL, BPRED|(lose), ",a,N Z,G", (flags), v9 }, \ + { opcode, (mask)|BPRED, ANNUL|(lose)|(2<<20), "z,G", (flags), v9 }, \ + { opcode, (mask)|BPRED, ANNUL|(lose)|(2<<20), ",T z,G", (flags), v9 }, \ + { opcode, (mask)|BPRED|ANNUL, (lose)|(2<<20), ",a z,G", (flags), v9 }, \ + { opcode, (mask)|BPRED|ANNUL, (lose)|(2<<20), ",a,T z,G", (flags), v9 }, \ + { opcode, (mask), ANNUL|BPRED|(lose)|(2<<20), ",N z,G", (flags), v9 }, \ + { opcode, (mask)|ANNUL, BPRED|(lose)|(2<<20), ",a,N z,G", (flags), v9 } + +/* Define four traps: reg+reg, reg + immediate, immediate alone, reg alone. */ +#define tr(opcode, mask, lose, flags) \ + { opcode, (mask)|(2<<11)|IMMED, (lose)|RS1_G0, "Z,i", (flags), v9 }, /* %g0 + imm */ \ + { opcode, (mask)|(2<<11)|IMMED, (lose), "Z,1+i", (flags), v9 }, /* rs1 + imm */ \ + { opcode, (mask)|(2<<11), IMMED|(lose), "Z,1+2", (flags), v9 }, /* rs1 + rs2 */ \ + { opcode, (mask)|(2<<11), IMMED|(lose)|RS2_G0, "Z,1", (flags), v9 }, /* rs1 + %g0 */ \ + { opcode, (mask)|IMMED, (lose)|RS1_G0, "z,i", (flags)|F_ALIAS, v9 }, /* %g0 + imm */ \ + { opcode, (mask)|IMMED, (lose), "z,1+i", (flags)|F_ALIAS, v9 }, /* rs1 + imm */ \ + { opcode, (mask), IMMED|(lose), "z,1+2", (flags)|F_ALIAS, v9 }, /* rs1 + rs2 */ \ + { opcode, (mask), IMMED|(lose)|RS2_G0, "z,1", (flags)|F_ALIAS, v9 }, /* rs1 + %g0 */ \ + { opcode, (mask)|IMMED, (lose)|RS1_G0, "i", (flags), v6 }, /* %g0 + imm */ \ + { opcode, (mask)|IMMED, (lose), "1+i", (flags), v6 }, /* rs1 + imm */ \ + { opcode, (mask)|IMMED, (lose), "i+1", (flags), v6 }, /* imm + rs1 */ \ + { opcode, (mask), IMMED|(lose), "1+2", (flags), v6 }, /* rs1 + rs2 */ \ + { opcode, (mask), IMMED|(lose)|RS2_G0, "1", (flags), v6 } /* rs1 + %g0 */ + +/* v9: We must put `brx' before `br', to ensure that we never match something + v9: against an expression unless it is an expression. Otherwise, we end + v9: up with undefined symbol tables entries, because they get added, but + v9: are not deleted if the pattern fails to match. */ + +/* Define both branches and traps based on condition mask */ +#define cond(bop, top, mask, flags) \ + brx(bop, F2(0, 1)|(mask), F2(~0, ~1)|((~mask)&COND(~0)), F_DELAYED|(flags)), /* v9 */ \ + br(bop, F2(0, 2)|(mask), F2(~0, ~2)|((~mask)&COND(~0)), F_DELAYED|(flags)), \ + tr(top, F3(2, 0x3a, 0)|(mask), F3(~2, ~0x3a, 0)|((~mask)&COND(~0)), ((flags) & ~(F_UNBR|F_CONDBR))) + +/* Define all the conditions, all the branches, all the traps. */ + +/* Standard branch, trap mnemonics */ +cond ("b", "ta", CONDA, F_UNBR), +/* Alternative form (just for assembly, not for disassembly) */ +cond ("ba", "t", CONDA, F_UNBR|F_ALIAS), + +cond ("bcc", "tcc", CONDCC, F_CONDBR), +cond ("bcs", "tcs", CONDCS, F_CONDBR), +cond ("be", "te", CONDE, F_CONDBR), +cond ("beq", "teq", CONDE, F_CONDBR|F_ALIAS), +cond ("bg", "tg", CONDG, F_CONDBR), +cond ("bgt", "tgt", CONDG, F_CONDBR|F_ALIAS), +cond ("bge", "tge", CONDGE, F_CONDBR), +cond ("bgeu", "tgeu", CONDGEU, F_CONDBR|F_ALIAS), /* for cc */ +cond ("bgu", "tgu", CONDGU, F_CONDBR), +cond ("bl", "tl", CONDL, F_CONDBR), +cond ("blt", "tlt", CONDL, F_CONDBR|F_ALIAS), +cond ("ble", "tle", CONDLE, F_CONDBR), +cond ("bleu", "tleu", CONDLEU, F_CONDBR), +cond ("blu", "tlu", CONDLU, F_CONDBR|F_ALIAS), /* for cs */ +cond ("bn", "tn", CONDN, F_CONDBR), +cond ("bne", "tne", CONDNE, F_CONDBR), +cond ("bneg", "tneg", CONDNEG, F_CONDBR), +cond ("bnz", "tnz", CONDNZ, F_CONDBR|F_ALIAS), /* for ne */ +cond ("bpos", "tpos", CONDPOS, F_CONDBR), +cond ("bvc", "tvc", CONDVC, F_CONDBR), +cond ("bvs", "tvs", CONDVS, F_CONDBR), +cond ("bz", "tz", CONDZ, F_CONDBR|F_ALIAS), /* for e */ + +#undef cond +#undef br +#undef brr /* v9 */ +#undef tr + +#define brr(opcode, mask, lose, flags) /* v9 */ \ + { opcode, (mask)|BPRED, ANNUL|(lose), "1,k", F_DELAYED|(flags), v9 }, \ + { opcode, (mask)|BPRED, ANNUL|(lose), ",T 1,k", F_DELAYED|(flags), v9 }, \ + { opcode, (mask)|BPRED|ANNUL, (lose), ",a 1,k", F_DELAYED|(flags), v9 }, \ + { opcode, (mask)|BPRED|ANNUL, (lose), ",a,T 1,k", F_DELAYED|(flags), v9 }, \ + { opcode, (mask), ANNUL|BPRED|(lose), ",N 1,k", F_DELAYED|(flags), v9 }, \ + { opcode, (mask)|ANNUL, BPRED|(lose), ",a,N 1,k", F_DELAYED|(flags), v9 } + +#define condr(bop, mask, flags) /* v9 */ \ + brr(bop, F2(0, 3)|COND(mask), F2(~0, ~3)|COND(~(mask)), (flags)) /* v9 */ + +/* v9 */ condr("brnz", 0x5, F_CONDBR), +/* v9 */ condr("brz", 0x1, F_CONDBR), +/* v9 */ condr("brgez", 0x7, F_CONDBR), +/* v9 */ condr("brlz", 0x3, F_CONDBR), +/* v9 */ condr("brlez", 0x2, F_CONDBR), +/* v9 */ condr("brgz", 0x6, F_CONDBR), + +#undef condr /* v9 */ +#undef brr /* v9 */ + +#define movr(opcode, mask, flags) /* v9 */ \ + { opcode, F3(2, 0x2f, 0)|RCOND(mask), F3(~2, ~0x2f, ~0)|RCOND(~(mask)), "1,2,d", (flags), v9 }, \ + { opcode, F3(2, 0x2f, 1)|RCOND(mask), F3(~2, ~0x2f, ~1)|RCOND(~(mask)), "1,j,d", (flags), v9 } + +#define fmrrs(opcode, mask, lose, flags) /* v9 */ \ + { opcode, (mask), (lose), "1,f,g", (flags) | F_FLOAT, v9 } +#define fmrrd(opcode, mask, lose, flags) /* v9 */ \ + { opcode, (mask), (lose), "1,B,H", (flags) | F_FLOAT, v9 } +#define fmrrq(opcode, mask, lose, flags) /* v9 */ \ + { opcode, (mask), (lose), "1,R,J", (flags) | F_FLOAT, v9 } + +#define fmovrs(mop, mask, flags) /* v9 */ \ + fmrrs(mop, F3(2, 0x35, 0)|OPF_LOW5(5)|RCOND(mask), F3(~2, ~0x35, 0)|OPF_LOW5(~5)|RCOND(~(mask)), (flags)) /* v9 */ +#define fmovrd(mop, mask, flags) /* v9 */ \ + fmrrd(mop, F3(2, 0x35, 0)|OPF_LOW5(6)|RCOND(mask), F3(~2, ~0x35, 0)|OPF_LOW5(~6)|RCOND(~(mask)), (flags)) /* v9 */ +#define fmovrq(mop, mask, flags) /* v9 */ \ + fmrrq(mop, F3(2, 0x35, 0)|OPF_LOW5(7)|RCOND(mask), F3(~2, ~0x35, 0)|OPF_LOW5(~7)|RCOND(~(mask)), (flags)) /* v9 */ + +/* v9 */ movr("movrne", 0x5, 0), +/* v9 */ movr("movre", 0x1, 0), +/* v9 */ movr("movrgez", 0x7, 0), +/* v9 */ movr("movrlz", 0x3, 0), +/* v9 */ movr("movrlez", 0x2, 0), +/* v9 */ movr("movrgz", 0x6, 0), +/* v9 */ movr("movrnz", 0x5, F_ALIAS), +/* v9 */ movr("movrz", 0x1, F_ALIAS), + +/* v9 */ fmovrs("fmovrsne", 0x5, 0), +/* v9 */ fmovrs("fmovrse", 0x1, 0), +/* v9 */ fmovrs("fmovrsgez", 0x7, 0), +/* v9 */ fmovrs("fmovrslz", 0x3, 0), +/* v9 */ fmovrs("fmovrslez", 0x2, 0), +/* v9 */ fmovrs("fmovrsgz", 0x6, 0), +/* v9 */ fmovrs("fmovrsnz", 0x5, F_ALIAS), +/* v9 */ fmovrs("fmovrsz", 0x1, F_ALIAS), + +/* v9 */ fmovrd("fmovrdne", 0x5, 0), +/* v9 */ fmovrd("fmovrde", 0x1, 0), +/* v9 */ fmovrd("fmovrdgez", 0x7, 0), +/* v9 */ fmovrd("fmovrdlz", 0x3, 0), +/* v9 */ fmovrd("fmovrdlez", 0x2, 0), +/* v9 */ fmovrd("fmovrdgz", 0x6, 0), +/* v9 */ fmovrd("fmovrdnz", 0x5, F_ALIAS), +/* v9 */ fmovrd("fmovrdz", 0x1, F_ALIAS), + +/* v9 */ fmovrq("fmovrqne", 0x5, 0), +/* v9 */ fmovrq("fmovrqe", 0x1, 0), +/* v9 */ fmovrq("fmovrqgez", 0x7, 0), +/* v9 */ fmovrq("fmovrqlz", 0x3, 0), +/* v9 */ fmovrq("fmovrqlez", 0x2, 0), +/* v9 */ fmovrq("fmovrqgz", 0x6, 0), +/* v9 */ fmovrq("fmovrqnz", 0x5, F_ALIAS), +/* v9 */ fmovrq("fmovrqz", 0x1, F_ALIAS), + +#undef movr /* v9 */ +#undef fmovr /* v9 */ +#undef fmrr /* v9 */ + +#define movicc(opcode, cond, flags) /* v9 */ \ + { opcode, F3(2, 0x2c, 0)|MCOND(cond,1)|ICC, F3(~2, ~0x2c, ~0)|MCOND(~cond,~1)|XCC|(1<<11), "z,2,d", flags, v9 }, \ + { opcode, F3(2, 0x2c, 1)|MCOND(cond,1)|ICC, F3(~2, ~0x2c, ~1)|MCOND(~cond,~1)|XCC|(1<<11), "z,I,d", flags, v9 }, \ + { opcode, F3(2, 0x2c, 0)|MCOND(cond,1)|XCC, F3(~2, ~0x2c, ~0)|MCOND(~cond,~1)|(1<<11), "Z,2,d", flags, v9 }, \ + { opcode, F3(2, 0x2c, 1)|MCOND(cond,1)|XCC, F3(~2, ~0x2c, ~1)|MCOND(~cond,~1)|(1<<11), "Z,I,d", flags, v9 } + +#define movfcc(opcode, fcond, flags) /* v9 */ \ + { opcode, F3(2, 0x2c, 0)|FCC(0)|MCOND(fcond,0), MCOND(~fcond,~0)|FCC(~0)|F3(~2, ~0x2c, ~0), "6,2,d", flags, v9 }, \ + { opcode, F3(2, 0x2c, 1)|FCC(0)|MCOND(fcond,0), MCOND(~fcond,~0)|FCC(~0)|F3(~2, ~0x2c, ~1), "6,I,d", flags, v9 }, \ + { opcode, F3(2, 0x2c, 0)|FCC(1)|MCOND(fcond,0), MCOND(~fcond,~0)|FCC(~1)|F3(~2, ~0x2c, ~0), "7,2,d", flags, v9 }, \ + { opcode, F3(2, 0x2c, 1)|FCC(1)|MCOND(fcond,0), MCOND(~fcond,~0)|FCC(~1)|F3(~2, ~0x2c, ~1), "7,I,d", flags, v9 }, \ + { opcode, F3(2, 0x2c, 0)|FCC(2)|MCOND(fcond,0), MCOND(~fcond,~0)|FCC(~2)|F3(~2, ~0x2c, ~0), "8,2,d", flags, v9 }, \ + { opcode, F3(2, 0x2c, 1)|FCC(2)|MCOND(fcond,0), MCOND(~fcond,~0)|FCC(~2)|F3(~2, ~0x2c, ~1), "8,I,d", flags, v9 }, \ + { opcode, F3(2, 0x2c, 0)|FCC(3)|MCOND(fcond,0), MCOND(~fcond,~0)|FCC(~3)|F3(~2, ~0x2c, ~0), "9,2,d", flags, v9 }, \ + { opcode, F3(2, 0x2c, 1)|FCC(3)|MCOND(fcond,0), MCOND(~fcond,~0)|FCC(~3)|F3(~2, ~0x2c, ~1), "9,I,d", flags, v9 } + +#define movcc(opcode, cond, fcond, flags) /* v9 */ \ + movfcc (opcode, fcond, flags), /* v9 */ \ + movicc (opcode, cond, flags) /* v9 */ + +/* v9 */ movcc ("mova", CONDA, FCONDA, 0), +/* v9 */ movicc ("movcc", CONDCC, 0), +/* v9 */ movicc ("movgeu", CONDGEU, F_ALIAS), +/* v9 */ movicc ("movcs", CONDCS, 0), +/* v9 */ movicc ("movlu", CONDLU, F_ALIAS), +/* v9 */ movcc ("move", CONDE, FCONDE, 0), +/* v9 */ movcc ("movg", CONDG, FCONDG, 0), +/* v9 */ movcc ("movge", CONDGE, FCONDGE, 0), +/* v9 */ movicc ("movgu", CONDGU, 0), +/* v9 */ movcc ("movl", CONDL, FCONDL, 0), +/* v9 */ movcc ("movle", CONDLE, FCONDLE, 0), +/* v9 */ movicc ("movleu", CONDLEU, 0), +/* v9 */ movfcc ("movlg", FCONDLG, 0), +/* v9 */ movcc ("movn", CONDN, FCONDN, 0), +/* v9 */ movcc ("movne", CONDNE, FCONDNE, 0), +/* v9 */ movicc ("movneg", CONDNEG, 0), +/* v9 */ movcc ("movnz", CONDNZ, FCONDNZ, F_ALIAS), +/* v9 */ movfcc ("movo", FCONDO, 0), +/* v9 */ movicc ("movpos", CONDPOS, 0), +/* v9 */ movfcc ("movu", FCONDU, 0), +/* v9 */ movfcc ("movue", FCONDUE, 0), +/* v9 */ movfcc ("movug", FCONDUG, 0), +/* v9 */ movfcc ("movuge", FCONDUGE, 0), +/* v9 */ movfcc ("movul", FCONDUL, 0), +/* v9 */ movfcc ("movule", FCONDULE, 0), +/* v9 */ movicc ("movvc", CONDVC, 0), +/* v9 */ movicc ("movvs", CONDVS, 0), +/* v9 */ movcc ("movz", CONDZ, FCONDZ, F_ALIAS), + +#undef movicc /* v9 */ +#undef movfcc /* v9 */ +#undef movcc /* v9 */ + +#define FM_SF 1 /* v9 - values for fpsize */ +#define FM_DF 2 /* v9 */ +#define FM_QF 3 /* v9 */ + +#define fmoviccx(opcode, fpsize, args, cond, flags) /* v9 */ \ +{ opcode, F3F(2, 0x35, 0x100+fpsize)|MCOND(cond,0), F3F(~2, ~0x35, ~(0x100+fpsize))|MCOND(~cond,~0), "z," args, flags, v9 }, \ +{ opcode, F3F(2, 0x35, 0x180+fpsize)|MCOND(cond,0), F3F(~2, ~0x35, ~(0x180+fpsize))|MCOND(~cond,~0), "Z," args, flags, v9 } + +#define fmovfccx(opcode, fpsize, args, fcond, flags) /* v9 */ \ +{ opcode, F3F(2, 0x35, 0x000+fpsize)|MCOND(fcond,0), F3F(~2, ~0x35, ~(0x000+fpsize))|MCOND(~fcond,~0), "6," args, flags, v9 }, \ +{ opcode, F3F(2, 0x35, 0x040+fpsize)|MCOND(fcond,0), F3F(~2, ~0x35, ~(0x040+fpsize))|MCOND(~fcond,~0), "7," args, flags, v9 }, \ +{ opcode, F3F(2, 0x35, 0x080+fpsize)|MCOND(fcond,0), F3F(~2, ~0x35, ~(0x080+fpsize))|MCOND(~fcond,~0), "8," args, flags, v9 }, \ +{ opcode, F3F(2, 0x35, 0x0c0+fpsize)|MCOND(fcond,0), F3F(~2, ~0x35, ~(0x0c0+fpsize))|MCOND(~fcond,~0), "9," args, flags, v9 } + +/* FIXME: use fmovicc/fmovfcc? */ /* v9 */ +#define fmovccx(opcode, fpsize, args, cond, fcond, flags) /* v9 */ \ +{ opcode, F3F(2, 0x35, 0x100+fpsize)|MCOND(cond,0), F3F(~2, ~0x35, ~(0x100+fpsize))|MCOND(~cond,~0), "z," args, flags | F_FLOAT, v9 }, \ +{ opcode, F3F(2, 0x35, 0x000+fpsize)|MCOND(fcond,0), F3F(~2, ~0x35, ~(0x000+fpsize))|MCOND(~fcond,~0), "6," args, flags | F_FLOAT, v9 }, \ +{ opcode, F3F(2, 0x35, 0x180+fpsize)|MCOND(cond,0), F3F(~2, ~0x35, ~(0x180+fpsize))|MCOND(~cond,~0), "Z," args, flags | F_FLOAT, v9 }, \ +{ opcode, F3F(2, 0x35, 0x040+fpsize)|MCOND(fcond,0), F3F(~2, ~0x35, ~(0x040+fpsize))|MCOND(~fcond,~0), "7," args, flags | F_FLOAT, v9 }, \ +{ opcode, F3F(2, 0x35, 0x080+fpsize)|MCOND(fcond,0), F3F(~2, ~0x35, ~(0x080+fpsize))|MCOND(~fcond,~0), "8," args, flags | F_FLOAT, v9 }, \ +{ opcode, F3F(2, 0x35, 0x0c0+fpsize)|MCOND(fcond,0), F3F(~2, ~0x35, ~(0x0c0+fpsize))|MCOND(~fcond,~0), "9," args, flags | F_FLOAT, v9 } + +#define fmovicc(suffix, cond, flags) /* v9 */ \ +fmoviccx("fmovd" suffix, FM_DF, "B,H", cond, flags), \ +fmoviccx("fmovq" suffix, FM_QF, "R,J", cond, flags), \ +fmoviccx("fmovs" suffix, FM_SF, "f,g", cond, flags) + +#define fmovfcc(suffix, fcond, flags) /* v9 */ \ +fmovfccx("fmovd" suffix, FM_DF, "B,H", fcond, flags), \ +fmovfccx("fmovq" suffix, FM_QF, "R,J", fcond, flags), \ +fmovfccx("fmovs" suffix, FM_SF, "f,g", fcond, flags) + +#define fmovcc(suffix, cond, fcond, flags) /* v9 */ \ +fmovccx("fmovd" suffix, FM_DF, "B,H", cond, fcond, flags), \ +fmovccx("fmovq" suffix, FM_QF, "R,J", cond, fcond, flags), \ +fmovccx("fmovs" suffix, FM_SF, "f,g", cond, fcond, flags) + +/* v9 */ fmovcc ("a", CONDA, FCONDA, 0), +/* v9 */ fmovicc ("cc", CONDCC, 0), +/* v9 */ fmovicc ("cs", CONDCS, 0), +/* v9 */ fmovcc ("e", CONDE, FCONDE, 0), +/* v9 */ fmovcc ("g", CONDG, FCONDG, 0), +/* v9 */ fmovcc ("ge", CONDGE, FCONDGE, 0), +/* v9 */ fmovicc ("geu", CONDGEU, F_ALIAS), +/* v9 */ fmovicc ("gu", CONDGU, 0), +/* v9 */ fmovcc ("l", CONDL, FCONDL, 0), +/* v9 */ fmovcc ("le", CONDLE, FCONDLE, 0), +/* v9 */ fmovicc ("leu", CONDLEU, 0), +/* v9 */ fmovfcc ("lg", FCONDLG, 0), +/* v9 */ fmovicc ("lu", CONDLU, F_ALIAS), +/* v9 */ fmovcc ("n", CONDN, FCONDN, 0), +/* v9 */ fmovcc ("ne", CONDNE, FCONDNE, 0), +/* v9 */ fmovicc ("neg", CONDNEG, 0), +/* v9 */ fmovcc ("nz", CONDNZ, FCONDNZ, F_ALIAS), +/* v9 */ fmovfcc ("o", FCONDO, 0), +/* v9 */ fmovicc ("pos", CONDPOS, 0), +/* v9 */ fmovfcc ("u", FCONDU, 0), +/* v9 */ fmovfcc ("ue", FCONDUE, 0), +/* v9 */ fmovfcc ("ug", FCONDUG, 0), +/* v9 */ fmovfcc ("uge", FCONDUGE, 0), +/* v9 */ fmovfcc ("ul", FCONDUL, 0), +/* v9 */ fmovfcc ("ule", FCONDULE, 0), +/* v9 */ fmovicc ("vc", CONDVC, 0), +/* v9 */ fmovicc ("vs", CONDVS, 0), +/* v9 */ fmovcc ("z", CONDZ, FCONDZ, F_ALIAS), + +#undef fmoviccx /* v9 */ +#undef fmovfccx /* v9 */ +#undef fmovccx /* v9 */ +#undef fmovicc /* v9 */ +#undef fmovfcc /* v9 */ +#undef fmovcc /* v9 */ +#undef FM_DF /* v9 */ +#undef FM_QF /* v9 */ +#undef FM_SF /* v9 */ + +/* Coprocessor branches. */ +#define CBR(opcode, mask, lose, flags, arch) \ + { opcode, (mask), ANNUL | (lose), "l", flags | F_DELAYED, arch }, \ + { opcode, (mask) | ANNUL, (lose), ",a l", flags | F_DELAYED, arch } + +/* Floating point branches. */ +#define FBR(opcode, mask, lose, flags) \ + { opcode, (mask), ANNUL | (lose), "l", flags | F_DELAYED | F_FBR, v6 }, \ + { opcode, (mask) | ANNUL, (lose), ",a l", flags | F_DELAYED | F_FBR, v6 } + +/* V9 extended floating point branches. */ +#define FBRX(opcode, mask, lose, flags) /* v9 */ \ + { opcode, FBFCC(0)|(mask)|BPRED, ANNUL|FBFCC(~0)|(lose), "6,G", flags|F_DELAYED|F_FBR, v9 }, \ + { opcode, FBFCC(0)|(mask)|BPRED, ANNUL|FBFCC(~0)|(lose), ",T 6,G", flags|F_DELAYED|F_FBR, v9 }, \ + { opcode, FBFCC(0)|(mask)|BPRED|ANNUL, FBFCC(~0)|(lose), ",a 6,G", flags|F_DELAYED|F_FBR, v9 }, \ + { opcode, FBFCC(0)|(mask)|BPRED|ANNUL, FBFCC(~0)|(lose), ",a,T 6,G", flags|F_DELAYED|F_FBR, v9 }, \ + { opcode, FBFCC(0)|(mask), ANNUL|BPRED|FBFCC(~0)|(lose), ",N 6,G", flags|F_DELAYED|F_FBR, v9 }, \ + { opcode, FBFCC(0)|(mask)|ANNUL, BPRED|FBFCC(~0)|(lose), ",a,N 6,G", flags|F_DELAYED|F_FBR, v9 }, \ + { opcode, FBFCC(1)|(mask)|BPRED, ANNUL|FBFCC(~1)|(lose), "7,G", flags|F_DELAYED|F_FBR, v9 }, \ + { opcode, FBFCC(1)|(mask)|BPRED, ANNUL|FBFCC(~1)|(lose), ",T 7,G", flags|F_DELAYED|F_FBR, v9 }, \ + { opcode, FBFCC(1)|(mask)|BPRED|ANNUL, FBFCC(~1)|(lose), ",a 7,G", flags|F_DELAYED|F_FBR, v9 }, \ + { opcode, FBFCC(1)|(mask)|BPRED|ANNUL, FBFCC(~1)|(lose), ",a,T 7,G", flags|F_DELAYED|F_FBR, v9 }, \ + { opcode, FBFCC(1)|(mask), ANNUL|BPRED|FBFCC(~1)|(lose), ",N 7,G", flags|F_DELAYED|F_FBR, v9 }, \ + { opcode, FBFCC(1)|(mask)|ANNUL, BPRED|FBFCC(~1)|(lose), ",a,N 7,G", flags|F_DELAYED|F_FBR, v9 }, \ + { opcode, FBFCC(2)|(mask)|BPRED, ANNUL|FBFCC(~2)|(lose), "8,G", flags|F_DELAYED|F_FBR, v9 }, \ + { opcode, FBFCC(2)|(mask)|BPRED, ANNUL|FBFCC(~2)|(lose), ",T 8,G", flags|F_DELAYED|F_FBR, v9 }, \ + { opcode, FBFCC(2)|(mask)|BPRED|ANNUL, FBFCC(~2)|(lose), ",a 8,G", flags|F_DELAYED|F_FBR, v9 }, \ + { opcode, FBFCC(2)|(mask)|BPRED|ANNUL, FBFCC(~2)|(lose), ",a,T 8,G", flags|F_DELAYED|F_FBR, v9 }, \ + { opcode, FBFCC(2)|(mask), ANNUL|BPRED|FBFCC(~2)|(lose), ",N 8,G", flags|F_DELAYED|F_FBR, v9 }, \ + { opcode, FBFCC(2)|(mask)|ANNUL, BPRED|FBFCC(~2)|(lose), ",a,N 8,G", flags|F_DELAYED|F_FBR, v9 }, \ + { opcode, FBFCC(3)|(mask)|BPRED, ANNUL|FBFCC(~3)|(lose), "9,G", flags|F_DELAYED|F_FBR, v9 }, \ + { opcode, FBFCC(3)|(mask)|BPRED, ANNUL|FBFCC(~3)|(lose), ",T 9,G", flags|F_DELAYED|F_FBR, v9 }, \ + { opcode, FBFCC(3)|(mask)|BPRED|ANNUL, FBFCC(~3)|(lose), ",a 9,G", flags|F_DELAYED|F_FBR, v9 }, \ + { opcode, FBFCC(3)|(mask)|BPRED|ANNUL, FBFCC(~3)|(lose), ",a,T 9,G", flags|F_DELAYED|F_FBR, v9 }, \ + { opcode, FBFCC(3)|(mask), ANNUL|BPRED|FBFCC(~3)|(lose), ",N 9,G", flags|F_DELAYED|F_FBR, v9 }, \ + { opcode, FBFCC(3)|(mask)|ANNUL, BPRED|FBFCC(~3)|(lose), ",a,N 9,G", flags|F_DELAYED|F_FBR, v9 } + +/* v9: We must put `FBRX' before `FBR', to ensure that we never match + v9: something against an expression unless it is an expression. Otherwise, + v9: we end up with undefined symbol tables entries, because they get added, + v9: but are not deleted if the pattern fails to match. */ + +#define CONDFC(fop, cop, mask, flags) \ + FBRX(fop, F2(0, 5)|COND(mask), F2(~0, ~5)|COND(~(mask)), flags), /* v9 */ \ + FBR(fop, F2(0, 6)|COND(mask), F2(~0, ~6)|COND(~(mask)), flags), \ + CBR(cop, F2(0, 7)|COND(mask), F2(~0, ~7)|COND(~(mask)), flags, v6notlet) + +#define CONDFCL(fop, cop, mask, flags) \ + FBRX(fop, F2(0, 5)|COND(mask), F2(~0, ~5)|COND(~(mask)), flags), /* v9 */ \ + FBR(fop, F2(0, 6)|COND(mask), F2(~0, ~6)|COND(~(mask)), flags), \ + CBR(cop, F2(0, 7)|COND(mask), F2(~0, ~7)|COND(~(mask)), flags, v6) + +#define CONDF(fop, mask, flags) \ + FBRX(fop, F2(0, 5)|COND(mask), F2(~0, ~5)|COND(~(mask)), flags), /* v9 */ \ + FBR(fop, F2(0, 6)|COND(mask), F2(~0, ~6)|COND(~(mask)), flags) + +CONDFC ("fb", "cb", 0x8, F_UNBR), +CONDFCL ("fba", "cba", 0x8, F_UNBR|F_ALIAS), +CONDFC ("fbe", "cb0", 0x9, F_CONDBR), +CONDF ("fbz", 0x9, F_CONDBR|F_ALIAS), +CONDFC ("fbg", "cb2", 0x6, F_CONDBR), +CONDFC ("fbge", "cb02", 0xb, F_CONDBR), +CONDFC ("fbl", "cb1", 0x4, F_CONDBR), +CONDFC ("fble", "cb01", 0xd, F_CONDBR), +CONDFC ("fblg", "cb12", 0x2, F_CONDBR), +CONDFCL ("fbn", "cbn", 0x0, F_UNBR), +CONDFC ("fbne", "cb123", 0x1, F_CONDBR), +CONDF ("fbnz", 0x1, F_CONDBR|F_ALIAS), +CONDFC ("fbo", "cb012", 0xf, F_CONDBR), +CONDFC ("fbu", "cb3", 0x7, F_CONDBR), +CONDFC ("fbue", "cb03", 0xa, F_CONDBR), +CONDFC ("fbug", "cb23", 0x5, F_CONDBR), +CONDFC ("fbuge", "cb023", 0xc, F_CONDBR), +CONDFC ("fbul", "cb13", 0x3, F_CONDBR), +CONDFC ("fbule", "cb013", 0xe, F_CONDBR), + +#undef CONDFC +#undef CONDFCL +#undef CONDF +#undef CBR +#undef FBR +#undef FBRX /* v9 */ + +{ "jmp", F3(2, 0x38, 0), F3(~2, ~0x38, ~0)|RD_G0|ASI(~0), "1+2", F_UNBR|F_DELAYED, v6 }, /* jmpl rs1+rs2,%g0 */ +{ "jmp", F3(2, 0x38, 0), F3(~2, ~0x38, ~0)|RD_G0|ASI_RS2(~0), "1", F_UNBR|F_DELAYED, v6 }, /* jmpl rs1+%g0,%g0 */ +{ "jmp", F3(2, 0x38, 1), F3(~2, ~0x38, ~1)|RD_G0, "1+i", F_UNBR|F_DELAYED, v6 }, /* jmpl rs1+i,%g0 */ +{ "jmp", F3(2, 0x38, 1), F3(~2, ~0x38, ~1)|RD_G0, "i+1", F_UNBR|F_DELAYED, v6 }, /* jmpl i+rs1,%g0 */ +{ "jmp", F3(2, 0x38, 1), F3(~2, ~0x38, ~1)|RD_G0|RS1_G0, "i", F_UNBR|F_DELAYED, v6 }, /* jmpl %g0+i,%g0 */ +{ "jmp", F3(2, 0x38, 1), F3(~2, ~0x38, ~1)|RD_G0|SIMM13(~0), "1", F_UNBR|F_DELAYED, v6 }, /* jmpl rs1+0,%g0 */ + +{ "nop", F2(0, 4), 0xfeffffff, "", 0, v6 }, /* sethi 0, %g0 */ + +{ "set", F2(0x0, 0x4), F2(~0x0, ~0x4), "S0,d", F_ALIAS, v6 }, +{ "setuw", F2(0x0, 0x4), F2(~0x0, ~0x4), "S0,d", F_ALIAS, v9 }, +{ "setsw", F2(0x0, 0x4), F2(~0x0, ~0x4), "S0,d", F_ALIAS, v9 }, +{ "setx", F2(0x0, 0x4), F2(~0x0, ~0x4), "S0,1,d", F_ALIAS, v9 }, + +{ "sethi", F2(0x0, 0x4), F2(~0x0, ~0x4), "h,d", 0, v6 }, + +{ "taddcc", F3(2, 0x20, 0), F3(~2, ~0x20, ~0)|ASI(~0), "1,2,d", 0, v6 }, +{ "taddcc", F3(2, 0x20, 1), F3(~2, ~0x20, ~1), "1,i,d", 0, v6 }, +{ "taddcc", F3(2, 0x20, 1), F3(~2, ~0x20, ~1), "i,1,d", 0, v6 }, +{ "taddcctv", F3(2, 0x22, 0), F3(~2, ~0x22, ~0)|ASI(~0), "1,2,d", 0, v6 }, +{ "taddcctv", F3(2, 0x22, 1), F3(~2, ~0x22, ~1), "1,i,d", 0, v6 }, +{ "taddcctv", F3(2, 0x22, 1), F3(~2, ~0x22, ~1), "i,1,d", 0, v6 }, + +{ "tsubcc", F3(2, 0x21, 0), F3(~2, ~0x21, ~0)|ASI(~0), "1,2,d", 0, v6 }, +{ "tsubcc", F3(2, 0x21, 1), F3(~2, ~0x21, ~1), "1,i,d", 0, v6 }, +{ "tsubcctv", F3(2, 0x23, 0), F3(~2, ~0x23, ~0)|ASI(~0), "1,2,d", 0, v6 }, +{ "tsubcctv", F3(2, 0x23, 1), F3(~2, ~0x23, ~1), "1,i,d", 0, v6 }, + +{ "unimp", F2(0x0, 0x0), 0xffc00000, "n", 0, v6notv9 }, +{ "illtrap", F2(0, 0), F2(~0, ~0)|RD_G0, "n", 0, v9 }, + +/* This *is* a commutative instruction. */ +{ "xnor", F3(2, 0x07, 0), F3(~2, ~0x07, ~0)|ASI(~0), "1,2,d", 0, v6 }, +{ "xnor", F3(2, 0x07, 1), F3(~2, ~0x07, ~1), "1,i,d", 0, v6 }, +{ "xnor", F3(2, 0x07, 1), F3(~2, ~0x07, ~1), "i,1,d", 0, v6 }, +/* This *is* a commutative instruction. */ +{ "xnorcc", F3(2, 0x17, 0), F3(~2, ~0x17, ~0)|ASI(~0), "1,2,d", 0, v6 }, +{ "xnorcc", F3(2, 0x17, 1), F3(~2, ~0x17, ~1), "1,i,d", 0, v6 }, +{ "xnorcc", F3(2, 0x17, 1), F3(~2, ~0x17, ~1), "i,1,d", 0, v6 }, +{ "xor", F3(2, 0x03, 0), F3(~2, ~0x03, ~0)|ASI(~0), "1,2,d", 0, v6 }, +{ "xor", F3(2, 0x03, 1), F3(~2, ~0x03, ~1), "1,i,d", 0, v6 }, +{ "xor", F3(2, 0x03, 1), F3(~2, ~0x03, ~1), "i,1,d", 0, v6 }, +{ "xorcc", F3(2, 0x13, 0), F3(~2, ~0x13, ~0)|ASI(~0), "1,2,d", 0, v6 }, +{ "xorcc", F3(2, 0x13, 1), F3(~2, ~0x13, ~1), "1,i,d", 0, v6 }, +{ "xorcc", F3(2, 0x13, 1), F3(~2, ~0x13, ~1), "i,1,d", 0, v6 }, + +{ "not", F3(2, 0x07, 0), F3(~2, ~0x07, ~0)|ASI(~0), "1,d", F_ALIAS, v6 }, /* xnor rs1,%0,rd */ +{ "not", F3(2, 0x07, 0), F3(~2, ~0x07, ~0)|ASI(~0), "r", F_ALIAS, v6 }, /* xnor rd,%0,rd */ + +{ "btog", F3(2, 0x03, 0), F3(~2, ~0x03, ~0)|ASI(~0), "2,r", F_ALIAS, v6 }, /* xor rd,rs2,rd */ +{ "btog", F3(2, 0x03, 1), F3(~2, ~0x03, ~1), "i,r", F_ALIAS, v6 }, /* xor rd,i,rd */ + +/* FPop1 and FPop2 are not instructions. Don't accept them. */ + +{ "fdtoi", F3F(2, 0x34, 0x0d2), F3F(~2, ~0x34, ~0x0d2)|RS1_G0, "B,g", F_FLOAT, v6 }, +{ "fstoi", F3F(2, 0x34, 0x0d1), F3F(~2, ~0x34, ~0x0d1)|RS1_G0, "f,g", F_FLOAT, v6 }, +{ "fqtoi", F3F(2, 0x34, 0x0d3), F3F(~2, ~0x34, ~0x0d3)|RS1_G0, "R,g", F_FLOAT, v8 }, + +{ "fdtox", F3F(2, 0x34, 0x082), F3F(~2, ~0x34, ~0x082)|RS1_G0, "B,H", F_FLOAT, v9 }, +{ "fstox", F3F(2, 0x34, 0x081), F3F(~2, ~0x34, ~0x081)|RS1_G0, "f,H", F_FLOAT, v9 }, +{ "fqtox", F3F(2, 0x34, 0x083), F3F(~2, ~0x34, ~0x083)|RS1_G0, "R,H", F_FLOAT, v9 }, + +{ "fitod", F3F(2, 0x34, 0x0c8), F3F(~2, ~0x34, ~0x0c8)|RS1_G0, "f,H", F_FLOAT, v6 }, +{ "fitos", F3F(2, 0x34, 0x0c4), F3F(~2, ~0x34, ~0x0c4)|RS1_G0, "f,g", F_FLOAT, v6 }, +{ "fitoq", F3F(2, 0x34, 0x0cc), F3F(~2, ~0x34, ~0x0cc)|RS1_G0, "f,J", F_FLOAT, v8 }, + +{ "fxtod", F3F(2, 0x34, 0x088), F3F(~2, ~0x34, ~0x088)|RS1_G0, "B,H", F_FLOAT, v9 }, +{ "fxtos", F3F(2, 0x34, 0x084), F3F(~2, ~0x34, ~0x084)|RS1_G0, "B,g", F_FLOAT, v9 }, +{ "fxtoq", F3F(2, 0x34, 0x08c), F3F(~2, ~0x34, ~0x08c)|RS1_G0, "B,J", F_FLOAT, v9 }, + +{ "fdtoq", F3F(2, 0x34, 0x0ce), F3F(~2, ~0x34, ~0x0ce)|RS1_G0, "B,J", F_FLOAT, v8 }, +{ "fdtos", F3F(2, 0x34, 0x0c6), F3F(~2, ~0x34, ~0x0c6)|RS1_G0, "B,g", F_FLOAT, v6 }, +{ "fqtod", F3F(2, 0x34, 0x0cb), F3F(~2, ~0x34, ~0x0cb)|RS1_G0, "R,H", F_FLOAT, v8 }, +{ "fqtos", F3F(2, 0x34, 0x0c7), F3F(~2, ~0x34, ~0x0c7)|RS1_G0, "R,g", F_FLOAT, v8 }, +{ "fstod", F3F(2, 0x34, 0x0c9), F3F(~2, ~0x34, ~0x0c9)|RS1_G0, "f,H", F_FLOAT, v6 }, +{ "fstoq", F3F(2, 0x34, 0x0cd), F3F(~2, ~0x34, ~0x0cd)|RS1_G0, "f,J", F_FLOAT, v8 }, + +{ "fdivd", F3F(2, 0x34, 0x04e), F3F(~2, ~0x34, ~0x04e), "v,B,H", F_FLOAT, v6 }, +{ "fdivq", F3F(2, 0x34, 0x04f), F3F(~2, ~0x34, ~0x04f), "V,R,J", F_FLOAT, v8 }, +{ "fdivx", F3F(2, 0x34, 0x04f), F3F(~2, ~0x34, ~0x04f), "V,R,J", F_FLOAT|F_ALIAS, v8 }, +{ "fdivs", F3F(2, 0x34, 0x04d), F3F(~2, ~0x34, ~0x04d), "e,f,g", F_FLOAT, v6 }, +{ "fmuld", F3F(2, 0x34, 0x04a), F3F(~2, ~0x34, ~0x04a), "v,B,H", F_FLOAT, v6 }, +{ "fmulq", F3F(2, 0x34, 0x04b), F3F(~2, ~0x34, ~0x04b), "V,R,J", F_FLOAT, v8 }, +{ "fmulx", F3F(2, 0x34, 0x04b), F3F(~2, ~0x34, ~0x04b), "V,R,J", F_FLOAT|F_ALIAS, v8 }, +{ "fmuls", F3F(2, 0x34, 0x049), F3F(~2, ~0x34, ~0x049), "e,f,g", F_FLOAT, v6 }, + +{ "fdmulq", F3F(2, 0x34, 0x06e), F3F(~2, ~0x34, ~0x06e), "v,B,J", F_FLOAT, v8 }, +{ "fdmulx", F3F(2, 0x34, 0x06e), F3F(~2, ~0x34, ~0x06e), "v,B,J", F_FLOAT|F_ALIAS, v8 }, +{ "fsmuld", F3F(2, 0x34, 0x069), F3F(~2, ~0x34, ~0x069), "e,f,H", F_FLOAT|F_FSMULD, v8 }, + +{ "fsqrtd", F3F(2, 0x34, 0x02a), F3F(~2, ~0x34, ~0x02a)|RS1_G0, "B,H", F_FLOAT, v7 }, +{ "fsqrtq", F3F(2, 0x34, 0x02b), F3F(~2, ~0x34, ~0x02b)|RS1_G0, "R,J", F_FLOAT, v8 }, +{ "fsqrtx", F3F(2, 0x34, 0x02b), F3F(~2, ~0x34, ~0x02b)|RS1_G0, "R,J", F_FLOAT|F_ALIAS, v8 }, +{ "fsqrts", F3F(2, 0x34, 0x029), F3F(~2, ~0x34, ~0x029)|RS1_G0, "f,g", F_FLOAT, v7 }, + +{ "fabsd", F3F(2, 0x34, 0x00a), F3F(~2, ~0x34, ~0x00a)|RS1_G0, "B,H", F_FLOAT, v9 }, +{ "fabsq", F3F(2, 0x34, 0x00b), F3F(~2, ~0x34, ~0x00b)|RS1_G0, "R,J", F_FLOAT, v9 }, +{ "fabsx", F3F(2, 0x34, 0x00b), F3F(~2, ~0x34, ~0x00b)|RS1_G0, "R,J", F_FLOAT|F_ALIAS, v9 }, +{ "fabss", F3F(2, 0x34, 0x009), F3F(~2, ~0x34, ~0x009)|RS1_G0, "f,g", F_FLOAT, v6 }, +{ "fmovd", F3F(2, 0x34, 0x002), F3F(~2, ~0x34, ~0x002)|RS1_G0, "B,H", F_FLOAT, v9 }, +{ "fmovq", F3F(2, 0x34, 0x003), F3F(~2, ~0x34, ~0x003)|RS1_G0, "R,J", F_FLOAT, v9 }, +{ "fmovx", F3F(2, 0x34, 0x003), F3F(~2, ~0x34, ~0x003)|RS1_G0, "R,J", F_FLOAT|F_ALIAS, v9 }, +{ "fmovs", F3F(2, 0x34, 0x001), F3F(~2, ~0x34, ~0x001)|RS1_G0, "f,g", F_FLOAT, v6 }, +{ "fnegd", F3F(2, 0x34, 0x006), F3F(~2, ~0x34, ~0x006)|RS1_G0, "B,H", F_FLOAT, v9 }, +{ "fnegq", F3F(2, 0x34, 0x007), F3F(~2, ~0x34, ~0x007)|RS1_G0, "R,J", F_FLOAT, v9 }, +{ "fnegx", F3F(2, 0x34, 0x007), F3F(~2, ~0x34, ~0x007)|RS1_G0, "R,J", F_FLOAT|F_ALIAS, v9 }, +{ "fnegs", F3F(2, 0x34, 0x005), F3F(~2, ~0x34, ~0x005)|RS1_G0, "f,g", F_FLOAT, v6 }, + +{ "faddd", F3F(2, 0x34, 0x042), F3F(~2, ~0x34, ~0x042), "v,B,H", F_FLOAT, v6 }, +{ "faddq", F3F(2, 0x34, 0x043), F3F(~2, ~0x34, ~0x043), "V,R,J", F_FLOAT, v8 }, +{ "faddx", F3F(2, 0x34, 0x043), F3F(~2, ~0x34, ~0x043), "V,R,J", F_FLOAT|F_ALIAS, v8 }, +{ "fadds", F3F(2, 0x34, 0x041), F3F(~2, ~0x34, ~0x041), "e,f,g", F_FLOAT, v6 }, +{ "fsubd", F3F(2, 0x34, 0x046), F3F(~2, ~0x34, ~0x046), "v,B,H", F_FLOAT, v6 }, +{ "fsubq", F3F(2, 0x34, 0x047), F3F(~2, ~0x34, ~0x047), "V,R,J", F_FLOAT, v8 }, +{ "fsubx", F3F(2, 0x34, 0x047), F3F(~2, ~0x34, ~0x047), "V,R,J", F_FLOAT|F_ALIAS, v8 }, +{ "fsubs", F3F(2, 0x34, 0x045), F3F(~2, ~0x34, ~0x045), "e,f,g", F_FLOAT, v6 }, + +#define CMPFCC(x) (((x)&0x3)<<25) + +{ "fcmpd", F3F(2, 0x35, 0x052), F3F(~2, ~0x35, ~0x052)|RD_G0, "v,B", F_FLOAT, v6 }, +{ "fcmpd", CMPFCC(0)|F3F(2, 0x35, 0x052), CMPFCC(~0)|F3F(~2, ~0x35, ~0x052), "6,v,B", F_FLOAT, v9 }, +{ "fcmpd", CMPFCC(1)|F3F(2, 0x35, 0x052), CMPFCC(~1)|F3F(~2, ~0x35, ~0x052), "7,v,B", F_FLOAT, v9 }, +{ "fcmpd", CMPFCC(2)|F3F(2, 0x35, 0x052), CMPFCC(~2)|F3F(~2, ~0x35, ~0x052), "8,v,B", F_FLOAT, v9 }, +{ "fcmpd", CMPFCC(3)|F3F(2, 0x35, 0x052), CMPFCC(~3)|F3F(~2, ~0x35, ~0x052), "9,v,B", F_FLOAT, v9 }, +{ "fcmped", F3F(2, 0x35, 0x056), F3F(~2, ~0x35, ~0x056)|RD_G0, "v,B", F_FLOAT, v6 }, +{ "fcmped", CMPFCC(0)|F3F(2, 0x35, 0x056), CMPFCC(~0)|F3F(~2, ~0x35, ~0x056), "6,v,B", F_FLOAT, v9 }, +{ "fcmped", CMPFCC(1)|F3F(2, 0x35, 0x056), CMPFCC(~1)|F3F(~2, ~0x35, ~0x056), "7,v,B", F_FLOAT, v9 }, +{ "fcmped", CMPFCC(2)|F3F(2, 0x35, 0x056), CMPFCC(~2)|F3F(~2, ~0x35, ~0x056), "8,v,B", F_FLOAT, v9 }, +{ "fcmped", CMPFCC(3)|F3F(2, 0x35, 0x056), CMPFCC(~3)|F3F(~2, ~0x35, ~0x056), "9,v,B", F_FLOAT, v9 }, +{ "fcmpq", F3F(2, 0x35, 0x053), F3F(~2, ~0x35, ~0x053)|RD_G0, "V,R", F_FLOAT, v8 }, +{ "fcmpq", CMPFCC(0)|F3F(2, 0x35, 0x053), CMPFCC(~0)|F3F(~2, ~0x35, ~0x053), "6,V,R", F_FLOAT, v9 }, +{ "fcmpq", CMPFCC(1)|F3F(2, 0x35, 0x053), CMPFCC(~1)|F3F(~2, ~0x35, ~0x053), "7,V,R", F_FLOAT, v9 }, +{ "fcmpq", CMPFCC(2)|F3F(2, 0x35, 0x053), CMPFCC(~2)|F3F(~2, ~0x35, ~0x053), "8,V,R", F_FLOAT, v9 }, +{ "fcmpq", CMPFCC(3)|F3F(2, 0x35, 0x053), CMPFCC(~3)|F3F(~2, ~0x35, ~0x053), "9,V,R", F_FLOAT, v9 }, +{ "fcmpeq", F3F(2, 0x35, 0x057), F3F(~2, ~0x35, ~0x057)|RD_G0, "V,R", F_FLOAT, v8 }, +{ "fcmpeq", CMPFCC(0)|F3F(2, 0x35, 0x057), CMPFCC(~0)|F3F(~2, ~0x35, ~0x057), "6,V,R", F_FLOAT, v9 }, +{ "fcmpeq", CMPFCC(1)|F3F(2, 0x35, 0x057), CMPFCC(~1)|F3F(~2, ~0x35, ~0x057), "7,V,R", F_FLOAT, v9 }, +{ "fcmpeq", CMPFCC(2)|F3F(2, 0x35, 0x057), CMPFCC(~2)|F3F(~2, ~0x35, ~0x057), "8,V,R", F_FLOAT, v9 }, +{ "fcmpeq", CMPFCC(3)|F3F(2, 0x35, 0x057), CMPFCC(~3)|F3F(~2, ~0x35, ~0x057), "9,V,R", F_FLOAT, v9 }, +{ "fcmpx", F3F(2, 0x35, 0x053), F3F(~2, ~0x35, ~0x053)|RD_G0, "V,R", F_FLOAT|F_ALIAS, v8 }, +{ "fcmpx", CMPFCC(0)|F3F(2, 0x35, 0x053), CMPFCC(~0)|F3F(~2, ~0x35, ~0x053), "6,V,R", F_FLOAT|F_ALIAS, v9 }, +{ "fcmpx", CMPFCC(1)|F3F(2, 0x35, 0x053), CMPFCC(~1)|F3F(~2, ~0x35, ~0x053), "7,V,R", F_FLOAT|F_ALIAS, v9 }, +{ "fcmpx", CMPFCC(2)|F3F(2, 0x35, 0x053), CMPFCC(~2)|F3F(~2, ~0x35, ~0x053), "8,V,R", F_FLOAT|F_ALIAS, v9 }, +{ "fcmpx", CMPFCC(3)|F3F(2, 0x35, 0x053), CMPFCC(~3)|F3F(~2, ~0x35, ~0x053), "9,V,R", F_FLOAT|F_ALIAS, v9 }, +{ "fcmpex", F3F(2, 0x35, 0x057), F3F(~2, ~0x35, ~0x057)|RD_G0, "V,R", F_FLOAT|F_ALIAS, v8 }, +{ "fcmpex", CMPFCC(0)|F3F(2, 0x35, 0x057), CMPFCC(~0)|F3F(~2, ~0x35, ~0x057), "6,V,R", F_FLOAT|F_ALIAS, v9 }, +{ "fcmpex", CMPFCC(1)|F3F(2, 0x35, 0x057), CMPFCC(~1)|F3F(~2, ~0x35, ~0x057), "7,V,R", F_FLOAT|F_ALIAS, v9 }, +{ "fcmpex", CMPFCC(2)|F3F(2, 0x35, 0x057), CMPFCC(~2)|F3F(~2, ~0x35, ~0x057), "8,V,R", F_FLOAT|F_ALIAS, v9 }, +{ "fcmpex", CMPFCC(3)|F3F(2, 0x35, 0x057), CMPFCC(~3)|F3F(~2, ~0x35, ~0x057), "9,V,R", F_FLOAT|F_ALIAS, v9 }, +{ "fcmps", F3F(2, 0x35, 0x051), F3F(~2, ~0x35, ~0x051)|RD_G0, "e,f", F_FLOAT, v6 }, +{ "fcmps", CMPFCC(0)|F3F(2, 0x35, 0x051), CMPFCC(~0)|F3F(~2, ~0x35, ~0x051), "6,e,f", F_FLOAT, v9 }, +{ "fcmps", CMPFCC(1)|F3F(2, 0x35, 0x051), CMPFCC(~1)|F3F(~2, ~0x35, ~0x051), "7,e,f", F_FLOAT, v9 }, +{ "fcmps", CMPFCC(2)|F3F(2, 0x35, 0x051), CMPFCC(~2)|F3F(~2, ~0x35, ~0x051), "8,e,f", F_FLOAT, v9 }, +{ "fcmps", CMPFCC(3)|F3F(2, 0x35, 0x051), CMPFCC(~3)|F3F(~2, ~0x35, ~0x051), "9,e,f", F_FLOAT, v9 }, +{ "fcmpes", F3F(2, 0x35, 0x055), F3F(~2, ~0x35, ~0x055)|RD_G0, "e,f", F_FLOAT, v6 }, +{ "fcmpes", CMPFCC(0)|F3F(2, 0x35, 0x055), CMPFCC(~0)|F3F(~2, ~0x35, ~0x055), "6,e,f", F_FLOAT, v9 }, +{ "fcmpes", CMPFCC(1)|F3F(2, 0x35, 0x055), CMPFCC(~1)|F3F(~2, ~0x35, ~0x055), "7,e,f", F_FLOAT, v9 }, +{ "fcmpes", CMPFCC(2)|F3F(2, 0x35, 0x055), CMPFCC(~2)|F3F(~2, ~0x35, ~0x055), "8,e,f", F_FLOAT, v9 }, +{ "fcmpes", CMPFCC(3)|F3F(2, 0x35, 0x055), CMPFCC(~3)|F3F(~2, ~0x35, ~0x055), "9,e,f", F_FLOAT, v9 }, + +/* These Extended FPop (FIFO) instructions are new in the Fujitsu + MB86934, replacing the CPop instructions from v6 and later + processors. */ + +#define EFPOP1_2(name, op, args) { name, F3F(2, 0x36, op), F3F(~2, ~0x36, ~op)|RS1_G0, args, 0, sparclite } +#define EFPOP1_3(name, op, args) { name, F3F(2, 0x36, op), F3F(~2, ~0x36, ~op), args, 0, sparclite } +#define EFPOP2_2(name, op, args) { name, F3F(2, 0x37, op), F3F(~2, ~0x37, ~op)|RD_G0, args, 0, sparclite } + +EFPOP1_2 ("efitod", 0x0c8, "f,H"), +EFPOP1_2 ("efitos", 0x0c4, "f,g"), +EFPOP1_2 ("efdtoi", 0x0d2, "B,g"), +EFPOP1_2 ("efstoi", 0x0d1, "f,g"), +EFPOP1_2 ("efstod", 0x0c9, "f,H"), +EFPOP1_2 ("efdtos", 0x0c6, "B,g"), +EFPOP1_2 ("efmovs", 0x001, "f,g"), +EFPOP1_2 ("efnegs", 0x005, "f,g"), +EFPOP1_2 ("efabss", 0x009, "f,g"), +EFPOP1_2 ("efsqrtd", 0x02a, "B,H"), +EFPOP1_2 ("efsqrts", 0x029, "f,g"), +EFPOP1_3 ("efaddd", 0x042, "v,B,H"), +EFPOP1_3 ("efadds", 0x041, "e,f,g"), +EFPOP1_3 ("efsubd", 0x046, "v,B,H"), +EFPOP1_3 ("efsubs", 0x045, "e,f,g"), +EFPOP1_3 ("efdivd", 0x04e, "v,B,H"), +EFPOP1_3 ("efdivs", 0x04d, "e,f,g"), +EFPOP1_3 ("efmuld", 0x04a, "v,B,H"), +EFPOP1_3 ("efmuls", 0x049, "e,f,g"), +EFPOP1_3 ("efsmuld", 0x069, "e,f,H"), +EFPOP2_2 ("efcmpd", 0x052, "v,B"), +EFPOP2_2 ("efcmped", 0x056, "v,B"), +EFPOP2_2 ("efcmps", 0x051, "e,f"), +EFPOP2_2 ("efcmpes", 0x055, "e,f"), + +#undef EFPOP1_2 +#undef EFPOP1_3 +#undef EFPOP2_2 + +/* These are marked F_ALIAS, so that they won't conflict with sparclite insns + present. Otherwise, the F_ALIAS flag is ignored. */ +{ "cpop1", F3(2, 0x36, 0), F3(~2, ~0x36, ~1), "[1+2],d", F_ALIAS, v6notv9 }, +{ "cpop2", F3(2, 0x37, 0), F3(~2, ~0x37, ~1), "[1+2],d", F_ALIAS, v6notv9 }, + +/* sparclet specific insns */ + +COMMUTEOP ("umac", 0x3e, sparclet), +COMMUTEOP ("smac", 0x3f, sparclet), +COMMUTEOP ("umacd", 0x2e, sparclet), +COMMUTEOP ("smacd", 0x2f, sparclet), +COMMUTEOP ("umuld", 0x09, sparclet), +COMMUTEOP ("smuld", 0x0d, sparclet), + +{ "shuffle", F3(2, 0x2d, 0), F3(~2, ~0x2d, ~0)|ASI(~0), "1,2,d", 0, sparclet }, +{ "shuffle", F3(2, 0x2d, 1), F3(~2, ~0x2d, ~1), "1,i,d", 0, sparclet }, + +/* The manual isn't completely accurate on these insns. The `rs2' field is + treated as being 6 bits to account for 6 bit immediates to cpush. It is + assumed that it is intended that bit 5 is 0 when rs2 contains a reg. */ +#define BIT5 (1<<5) +{ "crdcxt", F3(2, 0x36, 0)|SLCPOP(4), F3(~2, ~0x36, ~0)|SLCPOP(~4)|BIT5|RS2(~0), "U,d", 0, sparclet }, +{ "cwrcxt", F3(2, 0x36, 0)|SLCPOP(3), F3(~2, ~0x36, ~0)|SLCPOP(~3)|BIT5|RS2(~0), "1,u", 0, sparclet }, +{ "cpush", F3(2, 0x36, 0)|SLCPOP(0), F3(~2, ~0x36, ~0)|SLCPOP(~0)|BIT5|RD(~0), "1,2", 0, sparclet }, +{ "cpush", F3(2, 0x36, 1)|SLCPOP(0), F3(~2, ~0x36, ~1)|SLCPOP(~0)|RD(~0), "1,Y", 0, sparclet }, +{ "cpusha", F3(2, 0x36, 0)|SLCPOP(1), F3(~2, ~0x36, ~0)|SLCPOP(~1)|BIT5|RD(~0), "1,2", 0, sparclet }, +{ "cpusha", F3(2, 0x36, 1)|SLCPOP(1), F3(~2, ~0x36, ~1)|SLCPOP(~1)|RD(~0), "1,Y", 0, sparclet }, +{ "cpull", F3(2, 0x36, 0)|SLCPOP(2), F3(~2, ~0x36, ~0)|SLCPOP(~2)|BIT5|RS1(~0)|RS2(~0), "d", 0, sparclet }, +#undef BIT5 + +/* sparclet coprocessor branch insns */ +#define SLCBCC2(opcode, mask, lose) \ + { opcode, (mask), ANNUL|(lose), "l", F_DELAYED|F_CONDBR, sparclet }, \ + { opcode, (mask)|ANNUL, (lose), ",a l", F_DELAYED|F_CONDBR, sparclet } +#define SLCBCC(opcode, mask) \ + SLCBCC2(opcode, F2(0, 7)|COND(mask), F2(~0, ~7)|COND(~(mask))) + +/* cbn,cba can't be defined here because they're defined elsewhere and GAS + requires all mnemonics of the same name to be consecutive. */ +/*SLCBCC("cbn", 0), - already defined */ +SLCBCC("cbe", 1), +SLCBCC("cbf", 2), +SLCBCC("cbef", 3), +SLCBCC("cbr", 4), +SLCBCC("cber", 5), +SLCBCC("cbfr", 6), +SLCBCC("cbefr", 7), +/*SLCBCC("cba", 8), - already defined */ +SLCBCC("cbne", 9), +SLCBCC("cbnf", 10), +SLCBCC("cbnef", 11), +SLCBCC("cbnr", 12), +SLCBCC("cbner", 13), +SLCBCC("cbnfr", 14), +SLCBCC("cbnefr", 15), + +#undef SLCBCC2 +#undef SLCBCC + +{ "casa", F3(3, 0x3c, 0), F3(~3, ~0x3c, ~0), "[1]A,2,d", 0, v9 }, +{ "casa", F3(3, 0x3c, 1), F3(~3, ~0x3c, ~1), "[1]o,2,d", 0, v9 }, +{ "casxa", F3(3, 0x3e, 0), F3(~3, ~0x3e, ~0), "[1]A,2,d", 0, v9 }, +{ "casxa", F3(3, 0x3e, 1), F3(~3, ~0x3e, ~1), "[1]o,2,d", 0, v9 }, + +/* v9 synthetic insns */ +{ "iprefetch", F2(0, 1)|(2<<20)|BPRED, F2(~0, ~1)|(1<<20)|ANNUL|COND(~0), "G", 0, v9 }, /* bn,a,pt %xcc,label */ +{ "signx", F3(2, 0x27, 0), F3(~2, ~0x27, ~0)|(1<<12)|ASI(~0)|RS2_G0, "1,d", F_ALIAS, v9 }, /* sra rs1,%g0,rd */ +{ "signx", F3(2, 0x27, 0), F3(~2, ~0x27, ~0)|(1<<12)|ASI(~0)|RS2_G0, "r", F_ALIAS, v9 }, /* sra rd,%g0,rd */ +{ "clruw", F3(2, 0x26, 0), F3(~2, ~0x26, ~0)|(1<<12)|ASI(~0)|RS2_G0, "1,d", F_ALIAS, v9 }, /* srl rs1,%g0,rd */ +{ "clruw", F3(2, 0x26, 0), F3(~2, ~0x26, ~0)|(1<<12)|ASI(~0)|RS2_G0, "r", F_ALIAS, v9 }, /* srl rd,%g0,rd */ +{ "cas", F3(3, 0x3c, 0)|ASI(0x80), F3(~3, ~0x3c, ~0)|ASI(~0x80), "[1],2,d", F_ALIAS, v9 }, /* casa [rs1]ASI_P,rs2,rd */ +{ "casl", F3(3, 0x3c, 0)|ASI(0x88), F3(~3, ~0x3c, ~0)|ASI(~0x88), "[1],2,d", F_ALIAS, v9 }, /* casa [rs1]ASI_P_L,rs2,rd */ +{ "casx", F3(3, 0x3e, 0)|ASI(0x80), F3(~3, ~0x3e, ~0)|ASI(~0x80), "[1],2,d", F_ALIAS, v9 }, /* casxa [rs1]ASI_P,rs2,rd */ +{ "casxl", F3(3, 0x3e, 0)|ASI(0x88), F3(~3, ~0x3e, ~0)|ASI(~0x88), "[1],2,d", F_ALIAS, v9 }, /* casxa [rs1]ASI_P_L,rs2,rd */ + +/* Ultrasparc extensions */ +{ "shutdown", F3F(2, 0x36, 0x080), F3F(~2, ~0x36, ~0x080)|RD_G0|RS1_G0|RS2_G0, "", F_VIS, v9a }, + +/* FIXME: Do we want to mark these as F_FLOAT, or something similar? */ +{ "fpadd16", F3F(2, 0x36, 0x050), F3F(~2, ~0x36, ~0x050), "v,B,H", F_VIS, v9a }, +{ "fpadd16s", F3F(2, 0x36, 0x051), F3F(~2, ~0x36, ~0x051), "e,f,g", F_VIS, v9a }, +{ "fpadd32", F3F(2, 0x36, 0x052), F3F(~2, ~0x36, ~0x052), "v,B,H", F_VIS, v9a }, +{ "fpadd32s", F3F(2, 0x36, 0x053), F3F(~2, ~0x36, ~0x053), "e,f,g", F_VIS, v9a }, +{ "fpsub16", F3F(2, 0x36, 0x054), F3F(~2, ~0x36, ~0x054), "v,B,H", F_VIS, v9a }, +{ "fpsub16s", F3F(2, 0x36, 0x055), F3F(~2, ~0x36, ~0x055), "e,f,g", F_VIS, v9a }, +{ "fpsub32", F3F(2, 0x36, 0x056), F3F(~2, ~0x36, ~0x056), "v,B,H", F_VIS, v9a }, +{ "fpsub32s", F3F(2, 0x36, 0x057), F3F(~2, ~0x36, ~0x057), "e,f,g", F_VIS, v9a }, + +{ "fpack32", F3F(2, 0x36, 0x03a), F3F(~2, ~0x36, ~0x03a), "v,B,H", F_VIS, v9a }, +{ "fpack16", F3F(2, 0x36, 0x03b), F3F(~2, ~0x36, ~0x03b)|RS1_G0, "B,g", F_VIS, v9a }, +{ "fpackfix", F3F(2, 0x36, 0x03d), F3F(~2, ~0x36, ~0x03d)|RS1_G0, "B,g", F_VIS, v9a }, +{ "fexpand", F3F(2, 0x36, 0x04d), F3F(~2, ~0x36, ~0x04d)|RS1_G0, "f,H", F_VIS, v9a }, +{ "fpmerge", F3F(2, 0x36, 0x04b), F3F(~2, ~0x36, ~0x04b), "e,f,H", F_VIS, v9a }, + +/* Note that the mixing of 32/64 bit regs is intentional. */ +{ "fmul8x16", F3F(2, 0x36, 0x031), F3F(~2, ~0x36, ~0x031), "e,B,H", F_VIS, v9a }, +{ "fmul8x16au", F3F(2, 0x36, 0x033), F3F(~2, ~0x36, ~0x033), "e,f,H", F_VIS, v9a }, +{ "fmul8x16al", F3F(2, 0x36, 0x035), F3F(~2, ~0x36, ~0x035), "e,f,H", F_VIS, v9a }, +{ "fmul8sux16", F3F(2, 0x36, 0x036), F3F(~2, ~0x36, ~0x036), "v,B,H", F_VIS, v9a }, +{ "fmul8ulx16", F3F(2, 0x36, 0x037), F3F(~2, ~0x36, ~0x037), "v,B,H", F_VIS, v9a }, +{ "fmuld8sux16", F3F(2, 0x36, 0x038), F3F(~2, ~0x36, ~0x038), "e,f,H", F_VIS, v9a }, +{ "fmuld8ulx16", F3F(2, 0x36, 0x039), F3F(~2, ~0x36, ~0x039), "e,f,H", F_VIS, v9a }, + +{ "alignaddr", F3F(2, 0x36, 0x018), F3F(~2, ~0x36, ~0x018), "1,2,d", F_VIS, v9a }, +{ "alignaddrl", F3F(2, 0x36, 0x01a), F3F(~2, ~0x36, ~0x01a), "1,2,d", F_VIS, v9a }, +{ "faligndata", F3F(2, 0x36, 0x048), F3F(~2, ~0x36, ~0x048), "v,B,H", F_VIS, v9a }, + +{ "fzero", F3F(2, 0x36, 0x060), F3F(~2, ~0x36, ~0x060), "H", F_VIS, v9a }, +{ "fzeros", F3F(2, 0x36, 0x061), F3F(~2, ~0x36, ~0x061), "g", F_VIS, v9a }, +{ "fone", F3F(2, 0x36, 0x07e), F3F(~2, ~0x36, ~0x07e), "H", F_VIS, v9a }, +{ "fones", F3F(2, 0x36, 0x07f), F3F(~2, ~0x36, ~0x07f), "g", F_VIS, v9a }, +{ "fsrc1", F3F(2, 0x36, 0x074), F3F(~2, ~0x36, ~0x074), "v,H", F_VIS, v9a }, +{ "fsrc1s", F3F(2, 0x36, 0x075), F3F(~2, ~0x36, ~0x075), "e,g", F_VIS, v9a }, +{ "fsrc2", F3F(2, 0x36, 0x078), F3F(~2, ~0x36, ~0x078), "B,H", F_VIS, v9a }, +{ "fsrc2s", F3F(2, 0x36, 0x079), F3F(~2, ~0x36, ~0x079), "f,g", F_VIS, v9a }, +{ "fnot1", F3F(2, 0x36, 0x06a), F3F(~2, ~0x36, ~0x06a), "v,H", F_VIS, v9a }, +{ "fnot1s", F3F(2, 0x36, 0x06b), F3F(~2, ~0x36, ~0x06b), "e,g", F_VIS, v9a }, +{ "fnot2", F3F(2, 0x36, 0x066), F3F(~2, ~0x36, ~0x066), "B,H", F_VIS, v9a }, +{ "fnot2s", F3F(2, 0x36, 0x067), F3F(~2, ~0x36, ~0x067), "f,g", F_VIS, v9a }, +{ "for", F3F(2, 0x36, 0x07c), F3F(~2, ~0x36, ~0x07c), "v,B,H", F_VIS, v9a }, +{ "fors", F3F(2, 0x36, 0x07d), F3F(~2, ~0x36, ~0x07d), "e,f,g", F_VIS, v9a }, +{ "fnor", F3F(2, 0x36, 0x062), F3F(~2, ~0x36, ~0x062), "v,B,H", F_VIS, v9a }, +{ "fnors", F3F(2, 0x36, 0x063), F3F(~2, ~0x36, ~0x063), "e,f,g", F_VIS, v9a }, +{ "fand", F3F(2, 0x36, 0x070), F3F(~2, ~0x36, ~0x070), "v,B,H", F_VIS, v9a }, +{ "fands", F3F(2, 0x36, 0x071), F3F(~2, ~0x36, ~0x071), "e,f,g", F_VIS, v9a }, +{ "fnand", F3F(2, 0x36, 0x06e), F3F(~2, ~0x36, ~0x06e), "v,B,H", F_VIS, v9a }, +{ "fnands", F3F(2, 0x36, 0x06f), F3F(~2, ~0x36, ~0x06f), "e,f,g", F_VIS, v9a }, +{ "fxor", F3F(2, 0x36, 0x06c), F3F(~2, ~0x36, ~0x06c), "v,B,H", F_VIS, v9a }, +{ "fxors", F3F(2, 0x36, 0x06d), F3F(~2, ~0x36, ~0x06d), "e,f,g", F_VIS, v9a }, +{ "fxnor", F3F(2, 0x36, 0x072), F3F(~2, ~0x36, ~0x072), "v,B,H", F_VIS, v9a }, +{ "fxnors", F3F(2, 0x36, 0x073), F3F(~2, ~0x36, ~0x073), "e,f,g", F_VIS, v9a }, +{ "fornot1", F3F(2, 0x36, 0x07a), F3F(~2, ~0x36, ~0x07a), "v,B,H", F_VIS, v9a }, +{ "fornot1s", F3F(2, 0x36, 0x07b), F3F(~2, ~0x36, ~0x07b), "e,f,g", F_VIS, v9a }, +{ "fornot2", F3F(2, 0x36, 0x076), F3F(~2, ~0x36, ~0x076), "v,B,H", F_VIS, v9a }, +{ "fornot2s", F3F(2, 0x36, 0x077), F3F(~2, ~0x36, ~0x077), "e,f,g", F_VIS, v9a }, +{ "fandnot1", F3F(2, 0x36, 0x068), F3F(~2, ~0x36, ~0x068), "v,B,H", F_VIS, v9a }, +{ "fandnot1s", F3F(2, 0x36, 0x069), F3F(~2, ~0x36, ~0x069), "e,f,g", F_VIS, v9a }, +{ "fandnot2", F3F(2, 0x36, 0x064), F3F(~2, ~0x36, ~0x064), "v,B,H", F_VIS, v9a }, +{ "fandnot2s", F3F(2, 0x36, 0x065), F3F(~2, ~0x36, ~0x065), "e,f,g", F_VIS, v9a }, + +{ "fcmpgt16", F3F(2, 0x36, 0x028), F3F(~2, ~0x36, ~0x028), "v,B,d", F_VIS, v9a }, +{ "fcmpgt32", F3F(2, 0x36, 0x02c), F3F(~2, ~0x36, ~0x02c), "v,B,d", F_VIS, v9a }, +{ "fcmple16", F3F(2, 0x36, 0x020), F3F(~2, ~0x36, ~0x020), "v,B,d", F_VIS, v9a }, +{ "fcmple32", F3F(2, 0x36, 0x024), F3F(~2, ~0x36, ~0x024), "v,B,d", F_VIS, v9a }, +{ "fcmpne16", F3F(2, 0x36, 0x022), F3F(~2, ~0x36, ~0x022), "v,B,d", F_VIS, v9a }, +{ "fcmpne32", F3F(2, 0x36, 0x026), F3F(~2, ~0x36, ~0x026), "v,B,d", F_VIS, v9a }, +{ "fcmpeq16", F3F(2, 0x36, 0x02a), F3F(~2, ~0x36, ~0x02a), "v,B,d", F_VIS, v9a }, +{ "fcmpeq32", F3F(2, 0x36, 0x02e), F3F(~2, ~0x36, ~0x02e), "v,B,d", F_VIS, v9a }, + +{ "edge8", F3F(2, 0x36, 0x000), F3F(~2, ~0x36, ~0x000), "1,2,d", F_VIS, v9a }, +{ "edge8l", F3F(2, 0x36, 0x002), F3F(~2, ~0x36, ~0x002), "1,2,d", F_VIS, v9a }, +{ "edge16", F3F(2, 0x36, 0x004), F3F(~2, ~0x36, ~0x004), "1,2,d", F_VIS, v9a }, +{ "edge16l", F3F(2, 0x36, 0x006), F3F(~2, ~0x36, ~0x006), "1,2,d", F_VIS, v9a }, +{ "edge32", F3F(2, 0x36, 0x008), F3F(~2, ~0x36, ~0x008), "1,2,d", F_VIS, v9a }, +{ "edge32l", F3F(2, 0x36, 0x00a), F3F(~2, ~0x36, ~0x00a), "1,2,d", F_VIS, v9a }, + +{ "pdist", F3F(2, 0x36, 0x03e), F3F(~2, ~0x36, ~0x03e), "v,B,H", F_VIS, v9a }, + +{ "array8", F3F(2, 0x36, 0x010), F3F(~2, ~0x36, ~0x010), "1,2,d", F_VIS, v9a }, +{ "array16", F3F(2, 0x36, 0x012), F3F(~2, ~0x36, ~0x012), "1,2,d", F_VIS, v9a }, +{ "array32", F3F(2, 0x36, 0x014), F3F(~2, ~0x36, ~0x014), "1,2,d", F_VIS, v9a }, + +/* Cheetah instructions */ +{ "edge8n", F3F(2, 0x36, 0x001), F3F(~2, ~0x36, ~0x001), "1,2,d", F_VIS2, v9b }, +{ "edge8ln", F3F(2, 0x36, 0x003), F3F(~2, ~0x36, ~0x003), "1,2,d", F_VIS2, v9b }, +{ "edge16n", F3F(2, 0x36, 0x005), F3F(~2, ~0x36, ~0x005), "1,2,d", F_VIS2, v9b }, +{ "edge16ln", F3F(2, 0x36, 0x007), F3F(~2, ~0x36, ~0x007), "1,2,d", F_VIS2, v9b }, +{ "edge32n", F3F(2, 0x36, 0x009), F3F(~2, ~0x36, ~0x009), "1,2,d", F_VIS2, v9b }, +{ "edge32ln", F3F(2, 0x36, 0x00b), F3F(~2, ~0x36, ~0x00b), "1,2,d", F_VIS2, v9b }, + +{ "bmask", F3F(2, 0x36, 0x019), F3F(~2, ~0x36, ~0x019), "1,2,d", F_VIS2, v9b }, +{ "bshuffle", F3F(2, 0x36, 0x04c), F3F(~2, ~0x36, ~0x04c), "v,B,H", F_VIS2, v9b }, + +{ "siam", F3F(2, 0x36, 0x081), F3F(~2, ~0x36, ~0x081)|RD_G0|RS1_G0|RS2(~7), "3", F_VIS2, v9b }, + +{ "commit", F3(2, 0x3e, 0)|RD(30), F3(~2, ~0x3e, ~0)|RD(~30)|RS1_G0|SIMM13(~0), "", F_TRANS, v9b }, +{ "fnadds", F3F(2, 0x34, 0x051), F3F(~2, ~0x34, ~0x051), "e,f,g", F_FLOAT|F_HPC, v9b }, +{ "fnaddd", F3F(2, 0x34, 0x052), F3F(~2, ~0x34, ~0x052), "v,B,H", F_FLOAT|F_HPC, v9b }, +{ "fnmuls", F3F(2, 0x34, 0x059), F3F(~2, ~0x34, ~0x059), "e,f,g", F_FLOAT|F_HPC, v9b }, +{ "fnmuld", F3F(2, 0x34, 0x05a), F3F(~2, ~0x34, ~0x05a), "v,B,H", F_FLOAT|F_HPC, v9b }, +{ "fhadds", F3F(2, 0x34, 0x061), F3F(~2, ~0x34, ~0x061), "e,f,g", F_FLOAT|F_HPC, v9b }, +{ "fhaddd", F3F(2, 0x34, 0x062), F3F(~2, ~0x34, ~0x062), "v,B,H", F_FLOAT|F_HPC, v9b }, +{ "fhsubs", F3F(2, 0x34, 0x065), F3F(~2, ~0x34, ~0x065), "e,f,g", F_FLOAT|F_HPC, v9b }, +{ "fhsubd", F3F(2, 0x34, 0x066), F3F(~2, ~0x34, ~0x066), "v,B,H", F_FLOAT|F_HPC, v9b }, +{ "fnhadds", F3F(2, 0x34, 0x071), F3F(~2, ~0x34, ~0x071), "e,f,g", F_FLOAT|F_HPC, v9b }, +{ "fnhaddd", F3F(2, 0x34, 0x072), F3F(~2, ~0x34, ~0x072), "v,B,H", F_FLOAT|F_HPC, v9b }, +{ "fnsmuld", F3F(2, 0x34, 0x079), F3F(~2, ~0x34, ~0x079), "e,f,H", F_FLOAT|F_HPC, v9b }, +{ "fpmaddx", F3(2, 0x37, 0)|OPF_LOW4(0), F3(~2, ~0x37, 0)|OPF_LOW4(~0), "v,B,5,H", F_FLOAT|F_IMA, v9b }, +{ "fmadds", F3(2, 0x37, 0)|OPF_LOW4(1), F3(~2, ~0x37, 0)|OPF_LOW4(~1), "e,f,4,g", F_FLOAT|F_FMAF, v9b }, +{ "fmaddd", F3(2, 0x37, 0)|OPF_LOW4(2), F3(~2, ~0x37, 0)|OPF_LOW4(~2), "v,B,5,H", F_FLOAT|F_FMAF, v9b }, +{ "fpmaddxhi", F3(2, 0x37, 0)|OPF_LOW4(4), F3(~2, ~0x37, 0)|OPF_LOW4(~4), "v,B,5,H", F_FLOAT|F_IMA, v9b }, +{ "fmsubs", F3(2, 0x37, 0)|OPF_LOW4(5), F3(~2, ~0x37, 0)|OPF_LOW4(~5), "e,f,4,g", F_FLOAT|F_FMAF, v9b }, +{ "fmsubd", F3(2, 0x37, 0)|OPF_LOW4(6), F3(~2, ~0x37, 0)|OPF_LOW4(~6), "v,B,5,H", F_FLOAT|F_FMAF, v9b }, +{ "fnmsubs", F3(2, 0x37, 0)|OPF_LOW4(9), F3(~2, ~0x37, 0)|OPF_LOW4(~9), "e,f,4,g", F_FLOAT|F_FMAF, v9b }, +{ "fnmsubd", F3(2, 0x37, 0)|OPF_LOW4(10), F3(~2, ~0x37, 0)|OPF_LOW4(~10), "v,B,5,H", F_FLOAT|F_FMAF, v9b }, +{ "fnmadds", F3(2, 0x37, 0)|OPF_LOW4(13), F3(~2, ~0x37, 0)|OPF_LOW4(~13), "e,f,4,g", F_FLOAT|F_FMAF, v9b }, +{ "fnmaddd", F3(2, 0x37, 0)|OPF_LOW4(14), F3(~2, ~0x37, 0)|OPF_LOW4(~14), "v,B,5,H", F_FLOAT|F_FMAF, v9b }, +{ "fumadds", F3(2, 0x3f, 0)|OPF_LOW4(1), F3(~2, ~0x3f, 0)|OPF_LOW4(~1), "e,f,4,g", F_FLOAT|F_FJFMAU, v9b }, +{ "fumaddd", F3(2, 0x3f, 0)|OPF_LOW4(2), F3(~2, ~0x3f, 0)|OPF_LOW4(~2), "v,B,5,H", F_FLOAT|F_FJFMAU, v9b }, +{ "fumsubs", F3(2, 0x3f, 0)|OPF_LOW4(5), F3(~2, ~0x3f, 0)|OPF_LOW4(~5), "e,f,4,g", F_FLOAT|F_FJFMAU, v9b }, +{ "fumsubd", F3(2, 0x3f, 0)|OPF_LOW4(6), F3(~2, ~0x3f, 0)|OPF_LOW4(~6), "v,B,5,H", F_FLOAT|F_FJFMAU, v9b }, +{ "fnumsubs", F3(2, 0x3f, 0)|OPF_LOW4(9), F3(~2, ~0x3f, 0)|OPF_LOW4(~9), "e,f,4,g", F_FLOAT|F_FJFMAU, v9b }, +{ "fnumsubd", F3(2, 0x3f, 0)|OPF_LOW4(10), F3(~2, ~0x3f, 0)|OPF_LOW4(~10), "v,B,5,H", F_FLOAT|F_FJFMAU, v9b }, +{ "fnumadds", F3(2, 0x3f, 0)|OPF_LOW4(13), F3(~2, ~0x3f, 0)|OPF_LOW4(~13), "e,f,4,g", F_FLOAT|F_FJFMAU, v9b }, +{ "fnumaddd", F3(2, 0x3f, 0)|OPF_LOW4(14), F3(~2, ~0x3f, 0)|OPF_LOW4(~14), "v,B,5,H", F_FLOAT|F_FJFMAU, v9b }, +{ "addxc", F3F(2, 0x36, 0x011), F3F(~2, ~0x36, ~0x011), "1,2,d", F_VIS3, v9b }, +{ "addxccc", F3F(2, 0x36, 0x013), F3F(~2, ~0x36, ~0x013), "1,2,d", F_VIS3, v9b }, +{ "random", F3F(2, 0x36, 0x015), F3F(~2, ~0x36, ~0x015), "H", F_FLOAT|F_RANDOM, v9b }, +{ "umulxhi", F3F(2, 0x36, 0x016), F3F(~2, ~0x36, ~0x016), "1,2,d", F_VIS3, v9b }, +{ "lzd", F3F(2, 0x36, 0x017), F3F(~2, ~0x36, ~0x017), "2,d", F_VIS3, v9b }, +{ "cmask8", F3F(2, 0x36, 0x01b), F3F(~2, ~0x36, ~0x01b), "2", F_VIS3, v9b }, +{ "cmask16", F3F(2, 0x36, 0x01d), F3F(~2, ~0x36, ~0x01d), "2", F_VIS3, v9b }, +{ "cmask32", F3F(2, 0x36, 0x01f), F3F(~2, ~0x36, ~0x01f), "2", F_VIS3, v9b }, +{ "fsll16", F3F(2, 0x36, 0x021), F3F(~2, ~0x36, ~0x021), "v,B,H", F_VIS3, v9b }, +{ "fsrl16", F3F(2, 0x36, 0x023), F3F(~2, ~0x36, ~0x023), "v,B,H", F_VIS3, v9b }, +{ "fsll32", F3F(2, 0x36, 0x025), F3F(~2, ~0x36, ~0x025), "v,B,H", F_VIS3, v9b }, +{ "fsrl32", F3F(2, 0x36, 0x027), F3F(~2, ~0x36, ~0x027), "v,B,H", F_VIS3, v9b }, +{ "fslas16", F3F(2, 0x36, 0x029), F3F(~2, ~0x36, ~0x029), "v,B,H", F_VIS3, v9b }, +{ "fsra16", F3F(2, 0x36, 0x02b), F3F(~2, ~0x36, ~0x02b), "v,B,H", F_VIS3, v9b }, +{ "fslas32", F3F(2, 0x36, 0x02d), F3F(~2, ~0x36, ~0x02d), "v,B,H", F_VIS3, v9b }, +{ "fsra32", F3F(2, 0x36, 0x02f), F3F(~2, ~0x36, ~0x02f), "v,B,H", F_VIS3, v9b }, +{ "pdistn", F3F(2, 0x36, 0x03f), F3F(~2, ~0x36, ~0x03f), "v,B,d", F_VIS3, v9b }, +{ "fmean16", F3F(2, 0x36, 0x040), F3F(~2, ~0x36, ~0x040), "v,B,H", F_VIS3, v9b }, +{ "fpadd64", F3F(2, 0x36, 0x042), F3F(~2, ~0x36, ~0x042), "v,B,H", F_VIS3, v9b }, +{ "fchksm16", F3F(2, 0x36, 0x044), F3F(~2, ~0x36, ~0x044), "v,B,H", F_VIS3, v9b }, +{ "fpsub64", F3F(2, 0x36, 0x046), F3F(~2, ~0x36, ~0x046), "v,B,H", F_VIS3, v9b }, +{ "fpadds16", F3F(2, 0x36, 0x058), F3F(~2, ~0x36, ~0x058), "v,B,H", F_VIS3, v9b }, +{ "fpadds16s", F3F(2, 0x36, 0x059), F3F(~2, ~0x36, ~0x059), "e,f,g", F_VIS3, v9b }, +{ "fpadds32", F3F(2, 0x36, 0x05a), F3F(~2, ~0x36, ~0x05a), "v,B,H", F_VIS3, v9b }, +{ "fpadds32s", F3F(2, 0x36, 0x05b), F3F(~2, ~0x36, ~0x05b), "e,f,g", F_VIS3, v9b }, +{ "fpsubs16", F3F(2, 0x36, 0x05c), F3F(~2, ~0x36, ~0x05c), "v,B,H", F_VIS3, v9b }, +{ "fpsubs16s", F3F(2, 0x36, 0x05d), F3F(~2, ~0x36, ~0x05d), "e,f,g", F_VIS3, v9b }, +{ "fpsubs32", F3F(2, 0x36, 0x05e), F3F(~2, ~0x36, ~0x05e), "v,B,H", F_VIS3, v9b }, +{ "fpsubs32s", F3F(2, 0x36, 0x05f), F3F(~2, ~0x36, ~0x05f), "e,f,g", F_VIS3, v9b }, +{ "movdtox", F3F(2, 0x36, 0x110), F3F(~2, ~0x36, ~0x110), "B,d", F_FLOAT|F_VIS3, v9b }, +{ "movstouw", F3F(2, 0x36, 0x111), F3F(~2, ~0x36, ~0x111), "f,d", F_FLOAT|F_VIS3, v9b }, +{ "movstosw", F3F(2, 0x36, 0x113), F3F(~2, ~0x36, ~0x113), "f,d", F_FLOAT|F_VIS3, v9b }, +{ "movxtod", F3F(2, 0x36, 0x118), F3F(~2, ~0x36, ~0x118), "2,H", F_FLOAT|F_VIS3, v9b }, +{ "movwtos", F3F(2, 0x36, 0x119), F3F(~2, ~0x36, ~0x119), "2,g", F_FLOAT|F_VIS3, v9b }, +{ "xmulx", F3F(2, 0x36, 0x115), F3F(~2, ~0x36, ~0x115), "1,2,d", F_VIS3, v9b }, +{ "xmulxhi", F3F(2, 0x36, 0x116), F3F(~2, ~0x36, ~0x116), "1,2,d", F_VIS3, v9b }, +{ "fucmple8", F3F(2, 0x36, 0x120), F3F(~2, ~0x36, ~0x120), "v,B,d", F_VIS3, v9b }, +{ "fucmpne8", F3F(2, 0x36, 0x122), F3F(~2, ~0x36, ~0x122), "v,B,d", F_VIS3, v9b }, +{ "fucmpgt8", F3F(2, 0x36, 0x128), F3F(~2, ~0x36, ~0x128), "v,B,d", F_VIS3, v9b }, +{ "fucmpeq8", F3F(2, 0x36, 0x12a), F3F(~2, ~0x36, ~0x12a), "v,B,d", F_VIS3, v9b }, +{ "flcmps", CMPFCC(0)|F3F(2, 0x36, 0x151), CMPFCC(~0)|F3F(~2, ~0x36, ~0x151), "6,e,f", F_FLOAT|F_HPC, v9b }, +{ "flcmps", CMPFCC(1)|F3F(2, 0x36, 0x151), CMPFCC(~1)|F3F(~2, ~0x36, ~0x151), "7,e,f", F_FLOAT|F_HPC, v9b }, +{ "flcmps", CMPFCC(2)|F3F(2, 0x36, 0x151), CMPFCC(~2)|F3F(~2, ~0x36, ~0x151), "8,e,f", F_FLOAT|F_HPC, v9b }, +{ "flcmps", CMPFCC(3)|F3F(2, 0x36, 0x151), CMPFCC(~3)|F3F(~2, ~0x36, ~0x151), "9,e,f", F_FLOAT|F_HPC, v9b }, +{ "flcmpd", CMPFCC(0)|F3F(2, 0x36, 0x152), CMPFCC(~0)|F3F(~2, ~0x36, ~0x152), "6,v,B", F_FLOAT|F_HPC, v9b }, +{ "flcmpd", CMPFCC(1)|F3F(2, 0x36, 0x152), CMPFCC(~1)|F3F(~2, ~0x36, ~0x152), "7,v,B", F_FLOAT|F_HPC, v9b }, +{ "flcmpd", CMPFCC(2)|F3F(2, 0x36, 0x152), CMPFCC(~2)|F3F(~2, ~0x36, ~0x152), "8,v,B", F_FLOAT|F_HPC, v9b }, +{ "flcmpd", CMPFCC(3)|F3F(2, 0x36, 0x152), CMPFCC(~3)|F3F(~2, ~0x36, ~0x152), "9,v,B", F_FLOAT|F_HPC, v9b }, + +/* More v9 specific insns, these need to come last so they do not clash + with v9a instructions such as "edge8" which looks like impdep1. */ + +#define IMPDEP(name, code) \ +{ name, F3(2, code, 0), F3(~2, ~code, ~0)|ASI(~0), "1,2,d", 0, v9notv9a }, \ +{ name, F3(2, code, 1), F3(~2, ~code, ~1), "1,i,d", 0, v9notv9a }, \ +{ name, F3(2, code, 0), F3(~2, ~code, ~0), "x,1,2,d", 0, v9notv9a }, \ +{ name, F3(2, code, 0), F3(~2, ~code, ~0), "x,e,f,g", 0, v9notv9a } + +IMPDEP ("impdep1", 0x36), +IMPDEP ("impdep2", 0x37), + +#undef IMPDEP + +}; + +const int sparc_num_opcodes = ((sizeof sparc_opcodes)/(sizeof sparc_opcodes[0])); + +/* Utilities for argument parsing. */ + +typedef struct +{ + int value; + const char *name; +} arg; + +/* Look up NAME in TABLE. */ + +static int +lookup_name (const arg *table, const char *name) +{ + const arg *p; + + for (p = table; p->name; ++p) + if (strcmp (name, p->name) == 0) + return p->value; + + return -1; +} + +/* Look up VALUE in TABLE. */ + +static const char * +lookup_value (const arg *table, int value) +{ + const arg *p; + + for (p = table; p->name; ++p) + if (value == p->value) + return p->name; + + return NULL; +} + +/* Handle ASI's. */ + +static arg asi_table[] = +{ + /* These are in the v9 architecture manual. */ + /* The shorter versions appear first, they're here because Sun's as has them. + Sun's as uses #ASI_P_L instead of #ASI_PL (which appears in the + UltraSPARC architecture manual). */ + { 0x04, "#ASI_N" }, + { 0x0c, "#ASI_N_L" }, + { 0x10, "#ASI_AIUP" }, + { 0x11, "#ASI_AIUS" }, + { 0x18, "#ASI_AIUP_L" }, + { 0x19, "#ASI_AIUS_L" }, + { 0x80, "#ASI_P" }, + { 0x81, "#ASI_S" }, + { 0x82, "#ASI_PNF" }, + { 0x83, "#ASI_SNF" }, + { 0x88, "#ASI_P_L" }, + { 0x89, "#ASI_S_L" }, + { 0x8a, "#ASI_PNF_L" }, + { 0x8b, "#ASI_SNF_L" }, + { 0x04, "#ASI_NUCLEUS" }, + { 0x0c, "#ASI_NUCLEUS_LITTLE" }, + { 0x10, "#ASI_AS_IF_USER_PRIMARY" }, + { 0x11, "#ASI_AS_IF_USER_SECONDARY" }, + { 0x18, "#ASI_AS_IF_USER_PRIMARY_LITTLE" }, + { 0x19, "#ASI_AS_IF_USER_SECONDARY_LITTLE" }, + { 0x80, "#ASI_PRIMARY" }, + { 0x81, "#ASI_SECONDARY" }, + { 0x82, "#ASI_PRIMARY_NOFAULT" }, + { 0x83, "#ASI_SECONDARY_NOFAULT" }, + { 0x88, "#ASI_PRIMARY_LITTLE" }, + { 0x89, "#ASI_SECONDARY_LITTLE" }, + { 0x8a, "#ASI_PRIMARY_NOFAULT_LITTLE" }, + { 0x8b, "#ASI_SECONDARY_NOFAULT_LITTLE" }, + /* These are UltraSPARC and Niagara extensions. */ + { 0x14, "#ASI_PHYS_USE_EC" }, + { 0x15, "#ASI_PHYS_BYPASS_EC_E" }, + { 0x16, "#ASI_BLK_AIUP_4V" }, + { 0x17, "#ASI_BLK_AIUS_4V" }, + { 0x1c, "#ASI_PHYS_USE_EC_L" }, + { 0x1d, "#ASI_PHYS_BYPASS_EC_E_L" }, + { 0x1e, "#ASI_BLK_AIUP_L_4V" }, + { 0x1f, "#ASI_BLK_AIUS_L_4V" }, + { 0x20, "#ASI_SCRATCHPAD" }, + { 0x21, "#ASI_MMU" }, + { 0x23, "#ASI_BLK_INIT_QUAD_LDD_AIUS" }, + { 0x24, "#ASI_NUCLEUS_QUAD_LDD" }, + { 0x25, "#ASI_QUEUE" }, + { 0x26, "#ASI_QUAD_LDD_PHYS_4V" }, + { 0x2c, "#ASI_NUCLEUS_QUAD_LDD_L" }, + { 0x30, "#ASI_PCACHE_DATA_STATUS" }, + { 0x31, "#ASI_PCACHE_DATA" }, + { 0x32, "#ASI_PCACHE_TAG" }, + { 0x33, "#ASI_PCACHE_SNOOP_TAG" }, + { 0x34, "#ASI_QUAD_LDD_PHYS" }, + { 0x38, "#ASI_WCACHE_VALID_BITS" }, + { 0x39, "#ASI_WCACHE_DATA" }, + { 0x3a, "#ASI_WCACHE_TAG" }, + { 0x3b, "#ASI_WCACHE_SNOOP_TAG" }, + { 0x3c, "#ASI_QUAD_LDD_PHYS_L" }, + { 0x40, "#ASI_SRAM_FAST_INIT" }, + { 0x41, "#ASI_CORE_AVAILABLE" }, + { 0x41, "#ASI_CORE_ENABLE_STAT" }, + { 0x41, "#ASI_CORE_ENABLE" }, + { 0x41, "#ASI_XIR_STEERING" }, + { 0x41, "#ASI_CORE_RUNNING_RW" }, + { 0x41, "#ASI_CORE_RUNNING_W1S" }, + { 0x41, "#ASI_CORE_RUNNING_W1C" }, + { 0x41, "#ASI_CORE_RUNNING_STAT" }, + { 0x41, "#ASI_CMT_ERROR_STEERING" }, + { 0x41, "#ASI_DCACHE_INVALIDATE" }, + { 0x41, "#ASI_DCACHE_UTAG" }, + { 0x41, "#ASI_DCACHE_SNOOP_TAG" }, + { 0x42, "#ASI_DCACHE_INVALIDATE" }, + { 0x43, "#ASI_DCACHE_UTAG" }, + { 0x44, "#ASI_DCACHE_SNOOP_TAG" }, + { 0x45, "#ASI_LSU_CONTROL_REG" }, + { 0x45, "#ASI_DCU_CONTROL_REG" }, + { 0x46, "#ASI_DCACHE_DATA" }, + { 0x47, "#ASI_DCACHE_TAG" }, + { 0x48, "#ASI_INTR_DISPATCH_STAT" }, + { 0x49, "#ASI_INTR_RECEIVE" }, + { 0x4a, "#ASI_UPA_CONFIG" }, + { 0x4a, "#ASI_JBUS_CONFIG" }, + { 0x4a, "#ASI_SAFARI_CONFIG" }, + { 0x4a, "#ASI_SAFARI_ADDRESS" }, + { 0x4b, "#ASI_ESTATE_ERROR_EN" }, + { 0x4c, "#ASI_AFSR" }, + { 0x4d, "#ASI_AFAR" }, + { 0x4e, "#ASI_EC_TAG_DATA" }, + { 0x50, "#ASI_IMMU" }, + { 0x51, "#ASI_IMMU_TSB_8KB_PTR" }, + { 0x52, "#ASI_IMMU_TSB_16KB_PTR" }, + { 0x54, "#ASI_ITLB_DATA_IN" }, + { 0x55, "#ASI_ITLB_DATA_ACCESS" }, + { 0x56, "#ASI_ITLB_TAG_READ" }, + { 0x57, "#ASI_IMMU_DEMAP" }, + { 0x58, "#ASI_DMMU" }, + { 0x59, "#ASI_DMMU_TSB_8KB_PTR" }, + { 0x5a, "#ASI_DMMU_TSB_64KB_PTR" }, + { 0x5b, "#ASI_DMMU_TSB_DIRECT_PTR" }, + { 0x5c, "#ASI_DTLB_DATA_IN" }, + { 0x5d, "#ASI_DTLB_DATA_ACCESS" }, + { 0x5e, "#ASI_DTLB_TAG_READ" }, + { 0x5f, "#ASI_DMMU_DEMAP" }, + { 0x60, "#ASI_IIU_INST_TRAP" }, + { 0x63, "#ASI_INTR_ID" }, + { 0x63, "#ASI_CORE_ID" }, + { 0x63, "#ASI_CESR_ID" }, + { 0x66, "#ASI_IC_INSTR" }, + { 0x67, "#ASI_IC_TAG" }, + { 0x68, "#ASI_IC_STAG" }, + { 0x6e, "#ASI_IC_PRE_DECODE" }, + { 0x6f, "#ASI_IC_NEXT_FIELD" }, + { 0x6f, "#ASI_BRPRED_ARRAY" }, + { 0x70, "#ASI_BLK_AIUP" }, + { 0x71, "#ASI_BLK_AIUS" }, + { 0x72, "#ASI_MCU_CTRL_REG" }, + { 0x74, "#ASI_EC_DATA" }, + { 0x75, "#ASI_EC_CTRL" }, + { 0x76, "#ASI_EC_W" }, + { 0x77, "#ASI_UDB_ERROR_W" }, + { 0x77, "#ASI_UDB_CONTROL_W" }, + { 0x77, "#ASI_INTR_W" }, + { 0x77, "#ASI_INTR_DATAN_W" }, + { 0x77, "#ASI_INTR_DISPATCH_W" }, + { 0x78, "#ASI_BLK_AIUPL" }, + { 0x79, "#ASI_BLK_AIUSL" }, + { 0x7e, "#ASI_EC_R" }, + { 0x7f, "#ASI_UDBH_ERROR_R" }, + { 0x7f, "#ASI_UDBL_ERROR_R" }, + { 0x7f, "#ASI_UDBH_CONTROL_R" }, + { 0x7f, "#ASI_UDBL_CONTROL_R" }, + { 0x7f, "#ASI_INTR_R" }, + { 0x7f, "#ASI_INTR_DATAN_R" }, + { 0xc0, "#ASI_PST8_P" }, + { 0xc1, "#ASI_PST8_S" }, + { 0xc2, "#ASI_PST16_P" }, + { 0xc3, "#ASI_PST16_S" }, + { 0xc4, "#ASI_PST32_P" }, + { 0xc5, "#ASI_PST32_S" }, + { 0xc8, "#ASI_PST8_PL" }, + { 0xc9, "#ASI_PST8_SL" }, + { 0xca, "#ASI_PST16_PL" }, + { 0xcb, "#ASI_PST16_SL" }, + { 0xcc, "#ASI_PST32_PL" }, + { 0xcd, "#ASI_PST32_SL" }, + { 0xd0, "#ASI_FL8_P" }, + { 0xd1, "#ASI_FL8_S" }, + { 0xd2, "#ASI_FL16_P" }, + { 0xd3, "#ASI_FL16_S" }, + { 0xd8, "#ASI_FL8_PL" }, + { 0xd9, "#ASI_FL8_SL" }, + { 0xda, "#ASI_FL16_PL" }, + { 0xdb, "#ASI_FL16_SL" }, + { 0xe0, "#ASI_BLK_COMMIT_P", }, + { 0xe1, "#ASI_BLK_COMMIT_S", }, + { 0xe2, "#ASI_BLK_INIT_QUAD_LDD_P" }, + { 0xf0, "#ASI_BLK_P", }, + { 0xf1, "#ASI_BLK_S", }, + { 0xf8, "#ASI_BLK_PL", }, + { 0xf9, "#ASI_BLK_SL", }, + { 0, 0 } +}; + +/* Return the value for ASI NAME, or -1 if not found. */ + +int +sparc_encode_asi (const char *name) +{ + return lookup_name (asi_table, name); +} + +/* Return the name for ASI value VALUE or NULL if not found. */ + +const char * +sparc_decode_asi (int value) +{ + return lookup_value (asi_table, value); +} + +/* Handle membar masks. */ + +static arg membar_table[] = +{ + { 0x40, "#Sync" }, + { 0x20, "#MemIssue" }, + { 0x10, "#Lookaside" }, + { 0x08, "#StoreStore" }, + { 0x04, "#LoadStore" }, + { 0x02, "#StoreLoad" }, + { 0x01, "#LoadLoad" }, + { 0, 0 } +}; + +/* Return the value for membar arg NAME, or -1 if not found. */ + +int +sparc_encode_membar (const char *name) +{ + return lookup_name (membar_table, name); +} + +/* Return the name for membar value VALUE or NULL if not found. */ + +const char * +sparc_decode_membar (int value) +{ + return lookup_value (membar_table, value); +} + +/* Handle prefetch args. */ + +static arg prefetch_table[] = +{ + { 0, "#n_reads" }, + { 1, "#one_read" }, + { 2, "#n_writes" }, + { 3, "#one_write" }, + { 4, "#page" }, + { 16, "#invalidate" }, + { 17, "#unified", }, + { 20, "#n_reads_strong", }, + { 21, "#one_read_strong", }, + { 22, "#n_writes_strong", }, + { 23, "#one_write_strong", }, + { 0, 0 } +}; + +/* Return the value for prefetch arg NAME, or -1 if not found. */ + +int +sparc_encode_prefetch (const char *name) +{ + return lookup_name (prefetch_table, name); +} + +/* Return the name for prefetch value VALUE or NULL if not found. */ + +const char * +sparc_decode_prefetch (int value) +{ + return lookup_value (prefetch_table, value); +} + +/* Handle sparclet coprocessor registers. */ + +static arg sparclet_cpreg_table[] = +{ + { 0, "%ccsr" }, + { 1, "%ccfr" }, + { 2, "%cccrcr" }, + { 3, "%ccpr" }, + { 4, "%ccsr2" }, + { 5, "%cccrr" }, + { 6, "%ccrstr" }, + { 0, 0 } +}; + +/* Return the value for sparclet cpreg arg NAME, or -1 if not found. */ + +int +sparc_encode_sparclet_cpreg (const char *name) +{ + return lookup_name (sparclet_cpreg_table, name); +} + +/* Return the name for sparclet cpreg value VALUE or NULL if not found. */ + +const char * +sparc_decode_sparclet_cpreg (int value) +{ + return lookup_value (sparclet_cpreg_table, value); +} diff --git a/kernel/fiasco/src/lib/disasm/opcodes/sysdep.h b/kernel/fiasco/src/lib/disasm/opcodes/sysdep.h new file mode 100644 index 00000000..60eb76ac --- /dev/null +++ b/kernel/fiasco/src/lib/disasm/opcodes/sysdep.h @@ -0,0 +1,5 @@ +#include +#include +#include + +#define abort() panic("Error is i386-dis.c line %d", __LINE__) diff --git a/kernel/fiasco/src/lib/gzip/COPYING b/kernel/fiasco/src/lib/gzip/COPYING new file mode 100644 index 00000000..d60c31a9 --- /dev/null +++ b/kernel/fiasco/src/lib/gzip/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/kernel/fiasco/src/lib/gzip/adler32.c b/kernel/fiasco/src/lib/gzip/adler32.c new file mode 100644 index 00000000..fcb91f9c --- /dev/null +++ b/kernel/fiasco/src/lib/gzip/adler32.c @@ -0,0 +1,48 @@ +/* adler32.c -- compute the Adler-32 checksum of a data stream + * Copyright (C) 1995-2002 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id: adler32.c 5750 2002-11-19 13:56:17Z us15 $ */ + +#include "zlib.h" + +#define BASE 65521L /* largest prime smaller than 65536 */ +#define NMAX 5552 +/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ + +#define DO1(buf,i) {s1 += buf[i]; s2 += s1;} +#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1); +#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2); +#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4); +#define DO16(buf) DO8(buf,0); DO8(buf,8); + +/* ========================================================================= */ +uLong ZEXPORT adler32(adler, buf, len) + uLong adler; + const Bytef *buf; + uInt len; +{ + unsigned long s1 = adler & 0xffff; + unsigned long s2 = (adler >> 16) & 0xffff; + int k; + + if (buf == Z_NULL) return 1L; + + while (len > 0) { + k = len < NMAX ? len : NMAX; + len -= k; + while (k >= 16) { + DO16(buf); + buf += 16; + k -= 16; + } + if (k != 0) do { + s1 += *buf++; + s2 += s1; + } while (--k); + s1 %= BASE; + s2 %= BASE; + } + return (s2 << 16) | s1; +} diff --git a/kernel/fiasco/src/lib/gzip/crc32.c b/kernel/fiasco/src/lib/gzip/crc32.c new file mode 100644 index 00000000..cb531a7c --- /dev/null +++ b/kernel/fiasco/src/lib/gzip/crc32.c @@ -0,0 +1,162 @@ +/* crc32.c -- compute the CRC-32 of a data stream + * Copyright (C) 1995-2002 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id: crc32.c 5750 2002-11-19 13:56:17Z us15 $ */ + +#include "zlib.h" + +#define local static + +#ifdef DYNAMIC_CRC_TABLE + +local int crc_table_empty = 1; +local uLongf crc_table[256]; +local void make_crc_table OF((void)); + +/* + Generate a table for a byte-wise 32-bit CRC calculation on the polynomial: + x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1. + + Polynomials over GF(2) are represented in binary, one bit per coefficient, + with the lowest powers in the most significant bit. Then adding polynomials + is just exclusive-or, and multiplying a polynomial by x is a right shift by + one. If we call the above polynomial p, and represent a byte as the + polynomial q, also with the lowest power in the most significant bit (so the + byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p, + where a mod b means the remainder after dividing a by b. + + This calculation is done using the shift-register method of multiplying and + taking the remainder. The register is initialized to zero, and for each + incoming bit, x^32 is added mod p to the register if the bit is a one (where + x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by + x (which is shifting right by one and adding x^32 mod p if the bit shifted + out is a one). We start with the highest power (least significant bit) of + q and repeat for all eight bits of q. + + The table is simply the CRC of all possible eight bit values. This is all + the information needed to generate CRC's on data a byte at a time for all + combinations of CRC register values and incoming bytes. +*/ +local void make_crc_table() +{ + uLong c; + int n, k; + uLong poly; /* polynomial exclusive-or pattern */ + /* terms of polynomial defining this crc (except x^32): */ + static const Byte p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26}; + + /* make exclusive-or pattern from polynomial (0xedb88320L) */ + poly = 0L; + for (n = 0; n < sizeof(p)/sizeof(Byte); n++) + poly |= 1L << (31 - p[n]); + + for (n = 0; n < 256; n++) + { + c = (uLong)n; + for (k = 0; k < 8; k++) + c = c & 1 ? poly ^ (c >> 1) : c >> 1; + crc_table[n] = c; + } + crc_table_empty = 0; +} +#else +/* ======================================================================== + * Table of CRC-32's of all single-byte values (made by make_crc_table) + */ +local const uLongf crc_table[256] = { + 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, + 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L, + 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, + 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, + 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L, + 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L, + 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, + 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, + 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, + 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL, + 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, + 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, + 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L, + 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, + 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, + 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L, + 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL, + 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L, + 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, + 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, + 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL, + 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, + 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L, + 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL, + 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, + 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L, + 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, + 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, + 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L, + 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, + 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, + 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, + 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, + 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL, + 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, + 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, + 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL, + 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, + 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, + 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L, + 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL, + 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L, + 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, + 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, + 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L, + 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L, + 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, + 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L, + 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, + 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L, + 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, + 0x2d02ef8dL +}; +#endif + +/* ========================================================================= + * This function can be used by asm versions of crc32() + */ +const uLongf * ZEXPORT get_crc_table() +{ +#ifdef DYNAMIC_CRC_TABLE + if (crc_table_empty) make_crc_table(); +#endif + return (const uLongf *)crc_table; +} + +/* ========================================================================= */ +#define DO1(buf) crc = crc_table[((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8); +#define DO2(buf) DO1(buf); DO1(buf); +#define DO4(buf) DO2(buf); DO2(buf); +#define DO8(buf) DO4(buf); DO4(buf); + +/* ========================================================================= */ +uLong ZEXPORT crc32(crc, buf, len) + uLong crc; + const Bytef *buf; + uInt len; +{ + if (buf == Z_NULL) return 0L; +#ifdef DYNAMIC_CRC_TABLE + if (crc_table_empty) + make_crc_table(); +#endif + crc = crc ^ 0xffffffffL; + while (len >= 8) + { + DO8(buf); + len -= 8; + } + if (len) do { + DO1(buf); + } while (--len); + return crc ^ 0xffffffffL; +} diff --git a/kernel/fiasco/src/lib/gzip/deflate.c b/kernel/fiasco/src/lib/gzip/deflate.c new file mode 100644 index 00000000..6da51969 --- /dev/null +++ b/kernel/fiasco/src/lib/gzip/deflate.c @@ -0,0 +1,1350 @@ +/* deflate.c -- compress data using the deflation algorithm + * Copyright (C) 1995-2002 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * ALGORITHM + * + * The "deflation" process depends on being able to identify portions + * of the input text which are identical to earlier input (within a + * sliding window trailing behind the input currently being processed). + * + * The most straightforward technique turns out to be the fastest for + * most input files: try all possible matches and select the longest. + * The key feature of this algorithm is that insertions into the string + * dictionary are very simple and thus fast, and deletions are avoided + * completely. Insertions are performed at each input character, whereas + * string matches are performed only when the previous match ends. So it + * is preferable to spend more time in matches to allow very fast string + * insertions and avoid deletions. The matching algorithm for small + * strings is inspired from that of Rabin & Karp. A brute force approach + * is used to find longer strings when a small match has been found. + * A similar algorithm is used in comic (by Jan-Mark Wams) and freeze + * (by Leonid Broukhis). + * A previous version of this file used a more sophisticated algorithm + * (by Fiala and Greene) which is guaranteed to run in linear amortized + * time, but has a larger average cost, uses more memory and is patented. + * However the F&G algorithm may be faster for some highly redundant + * files if the parameter max_chain_length (described below) is too large. + * + * ACKNOWLEDGEMENTS + * + * The idea of lazy evaluation of matches is due to Jan-Mark Wams, and + * I found it in 'freeze' written by Leonid Broukhis. + * Thanks to many people for bug reports and testing. + * + * REFERENCES + * + * Deutsch, L.P.,"DEFLATE Compressed Data Format Specification". + * Available in ftp://ds.internic.net/rfc/rfc1951.txt + * + * A description of the Rabin and Karp algorithm is given in the book + * "Algorithms" by R. Sedgewick, Addison-Wesley, p252. + * + * Fiala,E.R., and Greene,D.H. + * Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595 + * + */ + +/* @(#) $Id: deflate.c 5750 2002-11-19 13:56:17Z us15 $ */ + +#include "deflate.h" + +const char deflate_copyright[] = + " deflate 1.1.4 Copyright 1995-2002 Jean-loup Gailly "; +/* + If you use the zlib library in a product, an acknowledgment is welcome + in the documentation of your product. If for some reason you cannot + include such an acknowledgment, I would appreciate that you keep this + copyright string in the executable of your product. + */ + +/* =========================================================================== + * Function prototypes. + */ +typedef enum { + need_more, /* block not completed, need more input or more output */ + block_done, /* block flush performed */ + finish_started, /* finish started, need only more output at next deflate */ + finish_done /* finish done, accept no more input or output */ +} block_state; + +typedef block_state (*compress_func) OF((deflate_state *s, int flush)); +/* Compression function. Returns the block state after the call. */ + +local void fill_window OF((deflate_state *s)); +local block_state deflate_stored OF((deflate_state *s, int flush)); +local block_state deflate_fast OF((deflate_state *s, int flush)); +local block_state deflate_slow OF((deflate_state *s, int flush)); +local void lm_init OF((deflate_state *s)); +local void putShortMSB OF((deflate_state *s, uInt b)); +local void flush_pending OF((z_streamp strm)); +local int read_buf OF((z_streamp strm, Bytef *buf, unsigned size)); +#ifdef ASMV + void match_init OF((void)); /* asm code initialization */ + uInt longest_match OF((deflate_state *s, IPos cur_match)); +#else +local uInt longest_match OF((deflate_state *s, IPos cur_match)); +#endif + +#ifdef DEBUG +local void check_match OF((deflate_state *s, IPos start, IPos match, + int length)); +#endif + +/* =========================================================================== + * Local data + */ + +#define NIL 0 +/* Tail of hash chains */ + +#ifndef TOO_FAR +# define TOO_FAR 4096 +#endif +/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */ + +#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) +/* Minimum amount of lookahead, except at the end of the input file. + * See deflate.c for comments about the MIN_MATCH+1. + */ + +/* Values for max_lazy_match, good_match and max_chain_length, depending on + * the desired pack level (0..9). The values given below have been tuned to + * exclude worst case performance for pathological files. Better values may be + * found for specific files. + */ +typedef struct config_s { + ush good_length; /* reduce lazy search above this match length */ + ush max_lazy; /* do not perform lazy search above this match length */ + ush nice_length; /* quit search above this match length */ + ush max_chain; + compress_func func; +} config; + +local const config configuration_table[10] = { +/* good lazy nice chain */ +/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ +/* 1 */ {4, 4, 8, 4, deflate_fast}, /* maximum speed, no lazy matches */ +/* 2 */ {4, 5, 16, 8, deflate_fast}, +/* 3 */ {4, 6, 32, 32, deflate_fast}, + +/* 4 */ {4, 4, 16, 16, deflate_slow}, /* lazy matches */ +/* 5 */ {8, 16, 32, 32, deflate_slow}, +/* 6 */ {8, 16, 128, 128, deflate_slow}, +/* 7 */ {8, 32, 128, 256, deflate_slow}, +/* 8 */ {32, 128, 258, 1024, deflate_slow}, +/* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* maximum compression */ + +/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4 + * For deflate_fast() (levels <= 3) good is ignored and lazy has a different + * meaning. + */ + +#define EQUAL 0 +/* result of memcmp for equal strings */ + +struct static_tree_desc_s {int dummy;}; /* for buggy compilers */ + +/* =========================================================================== + * Update a hash value with the given input byte + * IN assertion: all calls to to UPDATE_HASH are made with consecutive + * input characters, so that a running hash key can be computed from the + * previous key instead of complete recalculation each time. + */ +#define UPDATE_HASH(s,h,c) (h = (((h)<hash_shift) ^ (c)) & s->hash_mask) + + +/* =========================================================================== + * Insert string str in the dictionary and set match_head to the previous head + * of the hash chain (the most recent string with same hash key). Return + * the previous length of the hash chain. + * If this file is compiled with -DFASTEST, the compression level is forced + * to 1, and no hash chains are maintained. + * IN assertion: all calls to to INSERT_STRING are made with consecutive + * input characters and the first MIN_MATCH bytes of str are valid + * (except for the last MIN_MATCH-1 bytes of the input file). + */ +#ifdef FASTEST +#define INSERT_STRING(s, str, match_head) \ + (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ + match_head = s->head[s->ins_h], \ + s->head[s->ins_h] = (Pos)(str)) +#else +#define INSERT_STRING(s, str, match_head) \ + (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ + s->prev[(str) & s->w_mask] = match_head = s->head[s->ins_h], \ + s->head[s->ins_h] = (Pos)(str)) +#endif + +/* =========================================================================== + * Initialize the hash table (avoiding 64K overflow for 16 bit systems). + * prev[] will be initialized on the fly. + */ +#define CLEAR_HASH(s) \ + s->head[s->hash_size-1] = NIL; \ + zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head)); + +/* ========================================================================= */ +int ZEXPORT deflateInit_(strm, level, version, stream_size) + z_streamp strm; + int level; + const char *version; + int stream_size; +{ + return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, + Z_DEFAULT_STRATEGY, version, stream_size); + /* To do: ignore strm->next_in if we use it as window */ +} + +/* ========================================================================= */ +int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, + version, stream_size) + z_streamp strm; + int level; + int method; + int windowBits; + int memLevel; + int strategy; + const char *version; + int stream_size; +{ + deflate_state *s; + int noheader = 0; + static const char* my_version = ZLIB_VERSION; + + ushf *overlay; + /* We overlay pending_buf and d_buf+l_buf. This works since the average + * output size for (length,distance) codes is <= 24 bits. + */ + + if (version == Z_NULL || version[0] != my_version[0] || + stream_size != sizeof(z_stream)) { + return Z_VERSION_ERROR; + } + if (strm == Z_NULL) return Z_STREAM_ERROR; + + strm->msg = Z_NULL; + if (strm->zalloc == Z_NULL) { + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; + } + if (strm->zfree == Z_NULL) strm->zfree = zcfree; + + if (level == Z_DEFAULT_COMPRESSION) level = 6; +#ifdef FASTEST + level = 1; +#endif + + if (windowBits < 0) { /* undocumented feature: suppress zlib header */ + noheader = 1; + windowBits = -windowBits; + } + if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED || + windowBits < 9 || windowBits > 15 || level < 0 || level > 9 || + strategy < 0 || strategy > Z_HUFFMAN_ONLY) { + return Z_STREAM_ERROR; + } + s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state)); + if (s == Z_NULL) return Z_MEM_ERROR; + strm->state = (struct internal_state FAR *)s; + s->strm = strm; + + s->noheader = noheader; + s->w_bits = windowBits; + s->w_size = 1 << s->w_bits; + s->w_mask = s->w_size - 1; + + s->hash_bits = memLevel + 7; + s->hash_size = 1 << s->hash_bits; + s->hash_mask = s->hash_size - 1; + s->hash_shift = ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH); + + s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte)); + s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos)); + s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos)); + + s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ + + overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2); + s->pending_buf = (uchf *) overlay; + s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L); + + if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL || + s->pending_buf == Z_NULL) { + strm->msg = (char*)ERR_MSG(Z_MEM_ERROR); + deflateEnd (strm); + return Z_MEM_ERROR; + } + s->d_buf = overlay + s->lit_bufsize/sizeof(ush); + s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize; + + s->level = level; + s->strategy = strategy; + s->method = (Byte)method; + + return deflateReset(strm); +} + +/* ========================================================================= */ +int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength) + z_streamp strm; + const Bytef *dictionary; + uInt dictLength; +{ + deflate_state *s; + uInt length = dictLength; + uInt n; + IPos hash_head = 0; + + if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL || + strm->state->status != INIT_STATE) return Z_STREAM_ERROR; + + s = strm->state; + strm->adler = adler32(strm->adler, dictionary, dictLength); + + if (length < MIN_MATCH) return Z_OK; + if (length > MAX_DIST(s)) { + length = MAX_DIST(s); +#ifndef USE_DICT_HEAD + dictionary += dictLength - length; /* use the tail of the dictionary */ +#endif + } + zmemcpy(s->window, dictionary, length); + s->strstart = length; + s->block_start = (long)length; + + /* Insert all strings in the hash table (except for the last two bytes). + * s->lookahead stays null, so s->ins_h will be recomputed at the next + * call of fill_window. + */ + s->ins_h = s->window[0]; + UPDATE_HASH(s, s->ins_h, s->window[1]); + for (n = 0; n <= length - MIN_MATCH; n++) { + INSERT_STRING(s, n, hash_head); + } + if (hash_head) hash_head = 0; /* to make compiler happy */ + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateReset (strm) + z_streamp strm; +{ + deflate_state *s; + + if (strm == Z_NULL || strm->state == Z_NULL || + strm->zalloc == Z_NULL || strm->zfree == Z_NULL) return Z_STREAM_ERROR; + + strm->total_in = strm->total_out = 0; + strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */ + strm->data_type = Z_UNKNOWN; + + s = (deflate_state *)strm->state; + s->pending = 0; + s->pending_out = s->pending_buf; + + if (s->noheader < 0) { + s->noheader = 0; /* was set to -1 by deflate(..., Z_FINISH); */ + } + s->status = s->noheader ? BUSY_STATE : INIT_STATE; + strm->adler = 1; + s->last_flush = Z_NO_FLUSH; + + _tr_init(s); + lm_init(s); + + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateParams(strm, level, strategy) + z_streamp strm; + int level; + int strategy; +{ + deflate_state *s; + compress_func func; + int err = Z_OK; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + s = strm->state; + + if (level == Z_DEFAULT_COMPRESSION) { + level = 6; + } + if (level < 0 || level > 9 || strategy < 0 || strategy > Z_HUFFMAN_ONLY) { + return Z_STREAM_ERROR; + } + func = configuration_table[s->level].func; + + if (func != configuration_table[level].func && strm->total_in != 0) { + /* Flush the last buffer: */ + err = deflate(strm, Z_PARTIAL_FLUSH); + } + if (s->level != level) { + s->level = level; + s->max_lazy_match = configuration_table[level].max_lazy; + s->good_match = configuration_table[level].good_length; + s->nice_match = configuration_table[level].nice_length; + s->max_chain_length = configuration_table[level].max_chain; + } + s->strategy = strategy; + return err; +} + +/* ========================================================================= + * Put a short in the pending buffer. The 16-bit value is put in MSB order. + * IN assertion: the stream state is correct and there is enough room in + * pending_buf. + */ +local void putShortMSB (s, b) + deflate_state *s; + uInt b; +{ + put_byte(s, (Byte)(b >> 8)); + put_byte(s, (Byte)(b & 0xff)); +} + +/* ========================================================================= + * Flush as much pending output as possible. All deflate() output goes + * through this function so some applications may wish to modify it + * to avoid allocating a large strm->next_out buffer and copying into it. + * (See also read_buf()). + */ +local void flush_pending(strm) + z_streamp strm; +{ + unsigned len = strm->state->pending; + + if (len > strm->avail_out) len = strm->avail_out; + if (len == 0) return; + + zmemcpy(strm->next_out, strm->state->pending_out, len); + strm->next_out += len; + strm->state->pending_out += len; + strm->total_out += len; + strm->avail_out -= len; + strm->state->pending -= len; + if (strm->state->pending == 0) { + strm->state->pending_out = strm->state->pending_buf; + } +} + +/* ========================================================================= */ +int ZEXPORT deflate (strm, flush) + z_streamp strm; + int flush; +{ + int old_flush; /* value of flush param for previous deflate call */ + deflate_state *s; + + if (strm == Z_NULL || strm->state == Z_NULL || + flush > Z_FINISH || flush < 0) { + return Z_STREAM_ERROR; + } + s = strm->state; + + if (strm->next_out == Z_NULL || + (strm->next_in == Z_NULL && strm->avail_in != 0) || + (s->status == FINISH_STATE && flush != Z_FINISH)) { + ERR_RETURN(strm, Z_STREAM_ERROR); + } + if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR); + + s->strm = strm; /* just in case */ + old_flush = s->last_flush; + s->last_flush = flush; + + /* Write the zlib header */ + if (s->status == INIT_STATE) { + + uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8; + uInt level_flags = (s->level-1) >> 1; + + if (level_flags > 3) level_flags = 3; + header |= (level_flags << 6); + if (s->strstart != 0) header |= PRESET_DICT; + header += 31 - (header % 31); + + s->status = BUSY_STATE; + putShortMSB(s, header); + + /* Save the adler32 of the preset dictionary: */ + if (s->strstart != 0) { + putShortMSB(s, (uInt)(strm->adler >> 16)); + putShortMSB(s, (uInt)(strm->adler & 0xffff)); + } + strm->adler = 1L; + } + + /* Flush as much pending output as possible */ + if (s->pending != 0) { + flush_pending(strm); + if (strm->avail_out == 0) { + /* Since avail_out is 0, deflate will be called again with + * more output space, but possibly with both pending and + * avail_in equal to zero. There won't be anything to do, + * but this is not an error situation so make sure we + * return OK instead of BUF_ERROR at next call of deflate: + */ + s->last_flush = -1; + return Z_OK; + } + + /* Make sure there is something to do and avoid duplicate consecutive + * flushes. For repeated and useless calls with Z_FINISH, we keep + * returning Z_STREAM_END instead of Z_BUFF_ERROR. + */ + } else if (strm->avail_in == 0 && flush <= old_flush && + flush != Z_FINISH) { + ERR_RETURN(strm, Z_BUF_ERROR); + } + + /* User must not provide more input after the first FINISH: */ + if (s->status == FINISH_STATE && strm->avail_in != 0) { + ERR_RETURN(strm, Z_BUF_ERROR); + } + + /* Start a new block or continue the current one. + */ + if (strm->avail_in != 0 || s->lookahead != 0 || + (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) { + block_state bstate; + + bstate = (*(configuration_table[s->level].func))(s, flush); + + if (bstate == finish_started || bstate == finish_done) { + s->status = FINISH_STATE; + } + if (bstate == need_more || bstate == finish_started) { + if (strm->avail_out == 0) { + s->last_flush = -1; /* avoid BUF_ERROR next call, see above */ + } + return Z_OK; + /* If flush != Z_NO_FLUSH && avail_out == 0, the next call + * of deflate should use the same flush parameter to make sure + * that the flush is complete. So we don't have to output an + * empty block here, this will be done at next call. This also + * ensures that for a very small output buffer, we emit at most + * one empty block. + */ + } + if (bstate == block_done) { + if (flush == Z_PARTIAL_FLUSH) { + _tr_align(s); + } else { /* FULL_FLUSH or SYNC_FLUSH */ + _tr_stored_block(s, (char*)0, 0L, 0); + /* For a full flush, this empty block will be recognized + * as a special marker by inflate_sync(). + */ + if (flush == Z_FULL_FLUSH) { + CLEAR_HASH(s); /* forget history */ + } + } + flush_pending(strm); + if (strm->avail_out == 0) { + s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */ + return Z_OK; + } + } + } + Assert(strm->avail_out > 0, "bug2"); + + if (flush != Z_FINISH) return Z_OK; + if (s->noheader) return Z_STREAM_END; + + /* Write the zlib trailer (adler32) */ + putShortMSB(s, (uInt)(strm->adler >> 16)); + putShortMSB(s, (uInt)(strm->adler & 0xffff)); + flush_pending(strm); + /* If avail_out is zero, the application will call deflate again + * to flush the rest. + */ + s->noheader = -1; /* write the trailer only once! */ + return s->pending != 0 ? Z_OK : Z_STREAM_END; +} + +/* ========================================================================= */ +int ZEXPORT deflateEnd (strm) + z_streamp strm; +{ + int status; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + + status = strm->state->status; + if (status != INIT_STATE && status != BUSY_STATE && + status != FINISH_STATE) { + return Z_STREAM_ERROR; + } + + /* Deallocate in reverse order of allocations: */ + TRY_FREE(strm, strm->state->pending_buf); + TRY_FREE(strm, strm->state->head); + TRY_FREE(strm, strm->state->prev); + TRY_FREE(strm, strm->state->window); + + ZFREE(strm, strm->state); + strm->state = Z_NULL; + + return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK; +} + +/* ========================================================================= + * Copy the source state to the destination state. + * To simplify the source, this is not supported for 16-bit MSDOS (which + * doesn't have enough memory anyway to duplicate compression states). + */ +int ZEXPORT deflateCopy (dest, source) + z_streamp dest; + z_streamp source; +{ +#ifdef MAXSEG_64K + return Z_STREAM_ERROR; +#else + deflate_state *ds; + deflate_state *ss; + ushf *overlay; + + + if (source == Z_NULL || dest == Z_NULL || source->state == Z_NULL) { + return Z_STREAM_ERROR; + } + + ss = source->state; + + *dest = *source; + + ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state)); + if (ds == Z_NULL) return Z_MEM_ERROR; + dest->state = (struct internal_state FAR *) ds; + *ds = *ss; + ds->strm = dest; + + ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte)); + ds->prev = (Posf *) ZALLOC(dest, ds->w_size, sizeof(Pos)); + ds->head = (Posf *) ZALLOC(dest, ds->hash_size, sizeof(Pos)); + overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2); + ds->pending_buf = (uchf *) overlay; + + if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL || + ds->pending_buf == Z_NULL) { + deflateEnd (dest); + return Z_MEM_ERROR; + } + /* following zmemcpy do not work for 16-bit MSDOS */ + zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte)); + zmemcpy(ds->prev, ss->prev, ds->w_size * sizeof(Pos)); + zmemcpy(ds->head, ss->head, ds->hash_size * sizeof(Pos)); + zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size); + + ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf); + ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush); + ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize; + + ds->l_desc.dyn_tree = ds->dyn_ltree; + ds->d_desc.dyn_tree = ds->dyn_dtree; + ds->bl_desc.dyn_tree = ds->bl_tree; + + return Z_OK; +#endif +} + +/* =========================================================================== + * Read a new buffer from the current input stream, update the adler32 + * and total number of bytes read. All deflate() input goes through + * this function so some applications may wish to modify it to avoid + * allocating a large strm->next_in buffer and copying from it. + * (See also flush_pending()). + */ +local int read_buf(strm, buf, size) + z_streamp strm; + Bytef *buf; + unsigned size; +{ + unsigned len = strm->avail_in; + + if (len > size) len = size; + if (len == 0) return 0; + + strm->avail_in -= len; + + if (!strm->state->noheader) { + strm->adler = adler32(strm->adler, strm->next_in, len); + } + zmemcpy(buf, strm->next_in, len); + strm->next_in += len; + strm->total_in += len; + + return (int)len; +} + +/* =========================================================================== + * Initialize the "longest match" routines for a new zlib stream + */ +local void lm_init (s) + deflate_state *s; +{ + s->window_size = (ulg)2L*s->w_size; + + CLEAR_HASH(s); + + /* Set the default configuration parameters: + */ + s->max_lazy_match = configuration_table[s->level].max_lazy; + s->good_match = configuration_table[s->level].good_length; + s->nice_match = configuration_table[s->level].nice_length; + s->max_chain_length = configuration_table[s->level].max_chain; + + s->strstart = 0; + s->block_start = 0L; + s->lookahead = 0; + s->match_length = s->prev_length = MIN_MATCH-1; + s->match_available = 0; + s->ins_h = 0; +#ifdef ASMV + match_init(); /* initialize the asm code */ +#endif +} + +/* =========================================================================== + * Set match_start to the longest match starting at the given string and + * return its length. Matches shorter or equal to prev_length are discarded, + * in which case the result is equal to prev_length and match_start is + * garbage. + * IN assertions: cur_match is the head of the hash chain for the current + * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 + * OUT assertion: the match length is not greater than s->lookahead. + */ +#ifndef ASMV +/* For 80x86 and 680x0, an optimized version will be provided in match.asm or + * match.S. The code will be functionally equivalent. + */ +#ifndef FASTEST +local uInt longest_match(s, cur_match) + deflate_state *s; + IPos cur_match; /* current match */ +{ + unsigned chain_length = s->max_chain_length;/* max hash chain length */ + register Bytef *scan = s->window + s->strstart; /* current string */ + register Bytef *match; /* matched string */ + register int len; /* length of current match */ + int best_len = s->prev_length; /* best match length so far */ + int nice_match = s->nice_match; /* stop if match long enough */ + IPos limit = s->strstart > (IPos)MAX_DIST(s) ? + s->strstart - (IPos)MAX_DIST(s) : NIL; + /* Stop when cur_match becomes <= limit. To simplify the code, + * we prevent matches with the string of window index 0. + */ + Posf *prev = s->prev; + uInt wmask = s->w_mask; + +#ifdef UNALIGNED_OK + /* Compare two bytes at a time. Note: this is not always beneficial. + * Try with and without -DUNALIGNED_OK to check. + */ + register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1; + register ush scan_start = *(ushf*)scan; + register ush scan_end = *(ushf*)(scan+best_len-1); +#else + register Bytef *strend = s->window + s->strstart + MAX_MATCH; + register Byte scan_end1 = scan[best_len-1]; + register Byte scan_end = scan[best_len]; +#endif + + /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + * It is easy to get rid of this optimization if necessary. + */ + Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); + + /* Do not waste too much time if we already have a good match: */ + if (s->prev_length >= s->good_match) { + chain_length >>= 2; + } + /* Do not look for matches beyond the end of the input. This is necessary + * to make deflate deterministic. + */ + if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; + + Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + + do { + Assert(cur_match < s->strstart, "no future"); + match = s->window + cur_match; + + /* Skip to next match if the match length cannot increase + * or if the match length is less than 2: + */ +#if (defined(UNALIGNED_OK) && MAX_MATCH == 258) + /* This code assumes sizeof(unsigned short) == 2. Do not use + * UNALIGNED_OK if your compiler uses a different size. + */ + if (*(ushf*)(match+best_len-1) != scan_end || + *(ushf*)match != scan_start) continue; + + /* It is not necessary to compare scan[2] and match[2] since they are + * always equal when the other bytes match, given that the hash keys + * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at + * strstart+3, +5, ... up to strstart+257. We check for insufficient + * lookahead only every 4th comparison; the 128th check will be made + * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is + * necessary to put more guard bytes at the end of the window, or + * to check more often for insufficient lookahead. + */ + Assert(scan[2] == match[2], "scan[2]?"); + scan++, match++; + do { + } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + scan < strend); + /* The funny "do {}" generates better code on most compilers */ + + /* Here, scan <= window+strstart+257 */ + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + if (*scan == *match) scan++; + + len = (MAX_MATCH - 1) - (int)(strend-scan); + scan = strend - (MAX_MATCH-1); + +#else /* UNALIGNED_OK */ + + if (match[best_len] != scan_end || + match[best_len-1] != scan_end1 || + *match != *scan || + *++match != scan[1]) continue; + + /* The check at best_len-1 can be removed because it will be made + * again later. (This heuristic is not always a win.) + * It is not necessary to compare scan[2] and match[2] since they + * are always equal when the other bytes match, given that + * the hash keys are equal and that HASH_BITS >= 8. + */ + scan += 2, match++; + Assert(*scan == *match, "match[2]?"); + + /* We check for insufficient lookahead only every 8th comparison; + * the 256th check will be made at strstart+258. + */ + do { + } while (*++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + scan < strend); + + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + + len = MAX_MATCH - (int)(strend - scan); + scan = strend - MAX_MATCH; + +#endif /* UNALIGNED_OK */ + + if (len > best_len) { + s->match_start = cur_match; + best_len = len; + if (len >= nice_match) break; +#ifdef UNALIGNED_OK + scan_end = *(ushf*)(scan+best_len-1); +#else + scan_end1 = scan[best_len-1]; + scan_end = scan[best_len]; +#endif + } + } while ((cur_match = prev[cur_match & wmask]) > limit + && --chain_length != 0); + + if ((uInt)best_len <= s->lookahead) return (uInt)best_len; + return s->lookahead; +} + +#else /* FASTEST */ +/* --------------------------------------------------------------------------- + * Optimized version for level == 1 only + */ +local uInt longest_match(s, cur_match) + deflate_state *s; + IPos cur_match; /* current match */ +{ + register Bytef *scan = s->window + s->strstart; /* current string */ + register Bytef *match; /* matched string */ + register int len; /* length of current match */ + register Bytef *strend = s->window + s->strstart + MAX_MATCH; + + /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + * It is easy to get rid of this optimization if necessary. + */ + Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); + + Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + + Assert(cur_match < s->strstart, "no future"); + + match = s->window + cur_match; + + /* Return failure if the match length is less than 2: + */ + if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1; + + /* The check at best_len-1 can be removed because it will be made + * again later. (This heuristic is not always a win.) + * It is not necessary to compare scan[2] and match[2] since they + * are always equal when the other bytes match, given that + * the hash keys are equal and that HASH_BITS >= 8. + */ + scan += 2, match += 2; + Assert(*scan == *match, "match[2]?"); + + /* We check for insufficient lookahead only every 8th comparison; + * the 256th check will be made at strstart+258. + */ + do { + } while (*++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + scan < strend); + + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + + len = MAX_MATCH - (int)(strend - scan); + + if (len < MIN_MATCH) return MIN_MATCH - 1; + + s->match_start = cur_match; + return len <= s->lookahead ? len : s->lookahead; +} +#endif /* FASTEST */ +#endif /* ASMV */ + +#ifdef DEBUG +/* =========================================================================== + * Check that the match at match_start is indeed a match. + */ +local void check_match(s, start, match, length) + deflate_state *s; + IPos start, match; + int length; +{ + /* check that the match is indeed a match */ + if (zmemcmp(s->window + match, + s->window + start, length) != EQUAL) { + fprintf(stderr, " start %u, match %u, length %d\n", + start, match, length); + do { + fprintf(stderr, "%c%c", s->window[match++], s->window[start++]); + } while (--length != 0); + z_error("invalid match"); + } + if (z_verbose > 1) { + fprintf(stderr,"\\[%d,%d]", start-match, length); + do { putc(s->window[start++], stderr); } while (--length != 0); + } +} +#else +# define check_match(s, start, match, length) +#endif + +/* =========================================================================== + * Fill the window when the lookahead becomes insufficient. + * Updates strstart and lookahead. + * + * IN assertion: lookahead < MIN_LOOKAHEAD + * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD + * At least one byte has been read, or avail_in == 0; reads are + * performed for at least two bytes (required for the zip translate_eol + * option -- not supported here). + */ +local void fill_window(s) + deflate_state *s; +{ + register unsigned n, m; + register Posf *p; + unsigned more; /* Amount of free space at the end of the window. */ + uInt wsize = s->w_size; + + do { + more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart); + + /* Deal with !@#$% 64K limit: */ + if (more == 0 && s->strstart == 0 && s->lookahead == 0) { + more = wsize; + + } else if (more == (unsigned)(-1)) { + /* Very unlikely, but possible on 16 bit machine if strstart == 0 + * and lookahead == 1 (input done one byte at time) + */ + more--; + + /* If the window is almost full and there is insufficient lookahead, + * move the upper half to the lower one to make room in the upper half. + */ + } else if (s->strstart >= wsize+MAX_DIST(s)) { + + zmemcpy(s->window, s->window+wsize, (unsigned)wsize); + s->match_start -= wsize; + s->strstart -= wsize; /* we now have strstart >= MAX_DIST */ + s->block_start -= (long) wsize; + + /* Slide the hash table (could be avoided with 32 bit values + at the expense of memory usage). We slide even when level == 0 + to keep the hash table consistent if we switch back to level > 0 + later. (Using level 0 permanently is not an optimal usage of + zlib, so we don't care about this pathological case.) + */ + n = s->hash_size; + p = &s->head[n]; + do { + m = *--p; + *p = (Pos)(m >= wsize ? m-wsize : NIL); + } while (--n); + + n = wsize; +#ifndef FASTEST + p = &s->prev[n]; + do { + m = *--p; + *p = (Pos)(m >= wsize ? m-wsize : NIL); + /* If n is not on any hash chain, prev[n] is garbage but + * its value will never be used. + */ + } while (--n); +#endif + more += wsize; + } + if (s->strm->avail_in == 0) return; + + /* If there was no sliding: + * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && + * more == window_size - lookahead - strstart + * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) + * => more >= window_size - 2*WSIZE + 2 + * In the BIG_MEM or MMAP case (not yet supported), + * window_size == input_size + MIN_LOOKAHEAD && + * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. + * Otherwise, window_size == 2*WSIZE so more >= 2. + * If there was sliding, more >= WSIZE. So in all cases, more >= 2. + */ + Assert(more >= 2, "more < 2"); + + n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more); + s->lookahead += n; + + /* Initialize the hash value now that we have some input: */ + if (s->lookahead >= MIN_MATCH) { + s->ins_h = s->window[s->strstart]; + UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); +#if MIN_MATCH != 3 + Call UPDATE_HASH() MIN_MATCH-3 more times +#endif + } + /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, + * but this is not important since only literal bytes will be emitted. + */ + + } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0); +} + +/* =========================================================================== + * Flush the current block, with given end-of-file flag. + * IN assertion: strstart is set to the end of the current match. + */ +#define FLUSH_BLOCK_ONLY(s, eof) { \ + _tr_flush_block(s, (s->block_start >= 0L ? \ + (charf *)&s->window[(unsigned)s->block_start] : \ + (charf *)Z_NULL), \ + (ulg)((long)s->strstart - s->block_start), \ + (eof)); \ + s->block_start = s->strstart; \ + flush_pending(s->strm); \ + Tracev((stderr,"[FLUSH]")); \ +} + +/* Same but force premature exit if necessary. */ +#define FLUSH_BLOCK(s, eof) { \ + FLUSH_BLOCK_ONLY(s, eof); \ + if (s->strm->avail_out == 0) return (eof) ? finish_started : need_more; \ +} + +/* =========================================================================== + * Copy without compression as much as possible from the input stream, return + * the current block state. + * This function does not insert new strings in the dictionary since + * uncompressible data is probably not useful. This function is used + * only for the level=0 compression option. + * NOTE: this function should be optimized to avoid extra copying from + * window to pending_buf. + */ +local block_state deflate_stored(s, flush) + deflate_state *s; + int flush; +{ + /* Stored blocks are limited to 0xffff bytes, pending_buf is limited + * to pending_buf_size, and each stored block has a 5 byte header: + */ + ulg max_block_size = 0xffff; + ulg max_start; + + if (max_block_size > s->pending_buf_size - 5) { + max_block_size = s->pending_buf_size - 5; + } + + /* Copy as much as possible from input to output: */ + for (;;) { + /* Fill the window as much as possible: */ + if (s->lookahead <= 1) { + + Assert(s->strstart < s->w_size+MAX_DIST(s) || + s->block_start >= (long)s->w_size, "slide too late"); + + fill_window(s); + if (s->lookahead == 0 && flush == Z_NO_FLUSH) return need_more; + + if (s->lookahead == 0) break; /* flush the current block */ + } + Assert(s->block_start >= 0L, "block gone"); + + s->strstart += s->lookahead; + s->lookahead = 0; + + /* Emit a stored block if pending_buf will be full: */ + max_start = s->block_start + max_block_size; + if (s->strstart == 0 || (ulg)s->strstart >= max_start) { + /* strstart == 0 is possible when wraparound on 16-bit machine */ + s->lookahead = (uInt)(s->strstart - max_start); + s->strstart = (uInt)max_start; + FLUSH_BLOCK(s, 0); + } + /* Flush if we may have to slide, otherwise block_start may become + * negative and the data will be gone: + */ + if (s->strstart - (uInt)s->block_start >= MAX_DIST(s)) { + FLUSH_BLOCK(s, 0); + } + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} + +/* =========================================================================== + * Compress as much as possible from the input stream, return the current + * block state. + * This function does not perform lazy evaluation of matches and inserts + * new strings in the dictionary only for unmatched strings or for short + * matches. It is used only for the fast compression options. + */ +local block_state deflate_fast(s, flush) + deflate_state *s; + int flush; +{ + IPos hash_head = NIL; /* head of the hash chain */ + int bflush; /* set if current block must be flushed */ + + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + if (s->lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } + + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + if (s->lookahead >= MIN_MATCH) { + INSERT_STRING(s, s->strstart, hash_head); + } + + /* Find the longest match, discarding those <= prev_length. + * At this point we have always match_length < MIN_MATCH + */ + if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ + if (s->strategy != Z_HUFFMAN_ONLY) { + s->match_length = longest_match (s, hash_head); + } + /* longest_match() sets match_start */ + } + if (s->match_length >= MIN_MATCH) { + check_match(s, s->strstart, s->match_start, s->match_length); + + _tr_tally_dist(s, s->strstart - s->match_start, + s->match_length - MIN_MATCH, bflush); + + s->lookahead -= s->match_length; + + /* Insert new strings in the hash table only if the match length + * is not too large. This saves time but degrades compression. + */ +#ifndef FASTEST + if (s->match_length <= s->max_insert_length && + s->lookahead >= MIN_MATCH) { + s->match_length--; /* string at strstart already in hash table */ + do { + s->strstart++; + INSERT_STRING(s, s->strstart, hash_head); + /* strstart never exceeds WSIZE-MAX_MATCH, so there are + * always MIN_MATCH bytes ahead. + */ + } while (--s->match_length != 0); + s->strstart++; + } else +#endif + { + s->strstart += s->match_length; + s->match_length = 0; + s->ins_h = s->window[s->strstart]; + UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); +#if MIN_MATCH != 3 + Call UPDATE_HASH() MIN_MATCH-3 more times +#endif + /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not + * matter since it will be recomputed at next deflate call. + */ + } + } else { + /* No match, output a literal byte */ + Tracevv((stderr,"%c", s->window[s->strstart])); + _tr_tally_lit (s, s->window[s->strstart], bflush); + s->lookahead--; + s->strstart++; + } + if (bflush) FLUSH_BLOCK(s, 0); + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} + +/* =========================================================================== + * Same as above, but achieves better compression. We use a lazy + * evaluation for matches: a match is finally adopted only if there is + * no better match at the next window position. + */ +local block_state deflate_slow(s, flush) + deflate_state *s; + int flush; +{ + IPos hash_head = NIL; /* head of hash chain */ + int bflush; /* set if current block must be flushed */ + + /* Process the input block. */ + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + if (s->lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } + + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + if (s->lookahead >= MIN_MATCH) { + INSERT_STRING(s, s->strstart, hash_head); + } + + /* Find the longest match, discarding those <= prev_length. + */ + s->prev_length = s->match_length, s->prev_match = s->match_start; + s->match_length = MIN_MATCH-1; + + if (hash_head != NIL && s->prev_length < s->max_lazy_match && + s->strstart - hash_head <= MAX_DIST(s)) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ + if (s->strategy != Z_HUFFMAN_ONLY) { + s->match_length = longest_match (s, hash_head); + } + /* longest_match() sets match_start */ + + if (s->match_length <= 5 && (s->strategy == Z_FILTERED || + (s->match_length == MIN_MATCH && + s->strstart - s->match_start > TOO_FAR))) { + + /* If prev_match is also MIN_MATCH, match_start is garbage + * but we will ignore the current match anyway. + */ + s->match_length = MIN_MATCH-1; + } + } + /* If there was a match at the previous step and the current + * match is not better, output the previous match: + */ + if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) { + uInt max_insert = s->strstart + s->lookahead - MIN_MATCH; + /* Do not insert strings in hash table beyond this. */ + + check_match(s, s->strstart-1, s->prev_match, s->prev_length); + + _tr_tally_dist(s, s->strstart -1 - s->prev_match, + s->prev_length - MIN_MATCH, bflush); + + /* Insert in hash table all strings up to the end of the match. + * strstart-1 and strstart are already inserted. If there is not + * enough lookahead, the last two strings are not inserted in + * the hash table. + */ + s->lookahead -= s->prev_length-1; + s->prev_length -= 2; + do { + if (++s->strstart <= max_insert) { + INSERT_STRING(s, s->strstart, hash_head); + } + } while (--s->prev_length != 0); + s->match_available = 0; + s->match_length = MIN_MATCH-1; + s->strstart++; + + if (bflush) FLUSH_BLOCK(s, 0); + + } else if (s->match_available) { + /* If there was no match at the previous position, output a + * single literal. If there was a match but the current match + * is longer, truncate the previous match to a single literal. + */ + Tracevv((stderr,"%c", s->window[s->strstart-1])); + _tr_tally_lit(s, s->window[s->strstart-1], bflush); + if (bflush) { + FLUSH_BLOCK_ONLY(s, 0); + } + s->strstart++; + s->lookahead--; + if (s->strm->avail_out == 0) return need_more; + } else { + /* There is no previous match to compare with, wait for + * the next step to decide. + */ + s->match_available = 1; + s->strstart++; + s->lookahead--; + } + } + Assert (flush != Z_NO_FLUSH, "no flush?"); + if (s->match_available) { + Tracevv((stderr,"%c", s->window[s->strstart-1])); + _tr_tally_lit(s, s->window[s->strstart-1], bflush); + s->match_available = 0; + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} diff --git a/kernel/fiasco/src/lib/gzip/deflate.h b/kernel/fiasco/src/lib/gzip/deflate.h new file mode 100644 index 00000000..cff795e1 --- /dev/null +++ b/kernel/fiasco/src/lib/gzip/deflate.h @@ -0,0 +1,318 @@ +/* deflate.h -- internal compression state + * Copyright (C) 1995-2002 Jean-loup Gailly + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* @(#) $Id: deflate.h 5750 2002-11-19 13:56:17Z us15 $ */ + +#ifndef _DEFLATE_H +#define _DEFLATE_H + +#include "zutil.h" + +/* =========================================================================== + * Internal compression state. + */ + +#define LENGTH_CODES 29 +/* number of length codes, not counting the special END_BLOCK code */ + +#define LITERALS 256 +/* number of literal bytes 0..255 */ + +#define L_CODES (LITERALS+1+LENGTH_CODES) +/* number of Literal or Length codes, including the END_BLOCK code */ + +#define D_CODES 30 +/* number of distance codes */ + +#define BL_CODES 19 +/* number of codes used to transfer the bit lengths */ + +#define HEAP_SIZE (2*L_CODES+1) +/* maximum heap size */ + +#define MAX_BITS 15 +/* All codes must not exceed MAX_BITS bits */ + +#define INIT_STATE 42 +#define BUSY_STATE 113 +#define FINISH_STATE 666 +/* Stream status */ + + +/* Data structure describing a single value and its code string. */ +typedef struct ct_data_s { + union { + ush freq; /* frequency count */ + ush code; /* bit string */ + } fc; + union { + ush dad; /* father node in Huffman tree */ + ush len; /* length of bit string */ + } dl; +} FAR ct_data; + +#define Freq fc.freq +#define Code fc.code +#define Dad dl.dad +#define Len dl.len + +typedef struct static_tree_desc_s static_tree_desc; + +typedef struct tree_desc_s { + ct_data *dyn_tree; /* the dynamic tree */ + int max_code; /* largest code with non zero frequency */ + static_tree_desc *stat_desc; /* the corresponding static tree */ +} FAR tree_desc; + +typedef ush Pos; +typedef Pos FAR Posf; +typedef unsigned IPos; + +/* A Pos is an index in the character window. We use short instead of int to + * save space in the various tables. IPos is used only for parameter passing. + */ + +typedef struct internal_state { + z_streamp strm; /* pointer back to this zlib stream */ + int status; /* as the name implies */ + Bytef *pending_buf; /* output still pending */ + ulg pending_buf_size; /* size of pending_buf */ + Bytef *pending_out; /* next pending byte to output to the stream */ + int pending; /* nb of bytes in the pending buffer */ + int noheader; /* suppress zlib header and adler32 */ + Byte data_type; /* UNKNOWN, BINARY or ASCII */ + Byte method; /* STORED (for zip only) or DEFLATED */ + int last_flush; /* value of flush param for previous deflate call */ + + /* used by deflate.c: */ + + uInt w_size; /* LZ77 window size (32K by default) */ + uInt w_bits; /* log2(w_size) (8..16) */ + uInt w_mask; /* w_size - 1 */ + + Bytef *window; + /* Sliding window. Input bytes are read into the second half of the window, + * and move to the first half later to keep a dictionary of at least wSize + * bytes. With this organization, matches are limited to a distance of + * wSize-MAX_MATCH bytes, but this ensures that IO is always + * performed with a length multiple of the block size. Also, it limits + * the window size to 64K, which is quite useful on MSDOS. + * To do: use the user input buffer as sliding window. + */ + + ulg window_size; + /* Actual size of window: 2*wSize, except when the user input buffer + * is directly used as sliding window. + */ + + Posf *prev; + /* Link to older string with same hash index. To limit the size of this + * array to 64K, this link is maintained only for the last 32K strings. + * An index in this array is thus a window index modulo 32K. + */ + + Posf *head; /* Heads of the hash chains or NIL. */ + + uInt ins_h; /* hash index of string to be inserted */ + uInt hash_size; /* number of elements in hash table */ + uInt hash_bits; /* log2(hash_size) */ + uInt hash_mask; /* hash_size-1 */ + + uInt hash_shift; + /* Number of bits by which ins_h must be shifted at each input + * step. It must be such that after MIN_MATCH steps, the oldest + * byte no longer takes part in the hash key, that is: + * hash_shift * MIN_MATCH >= hash_bits + */ + + long block_start; + /* Window position at the beginning of the current output block. Gets + * negative when the window is moved backwards. + */ + + uInt match_length; /* length of best match */ + IPos prev_match; /* previous match */ + int match_available; /* set if previous match exists */ + uInt strstart; /* start of string to insert */ + uInt match_start; /* start of matching string */ + uInt lookahead; /* number of valid bytes ahead in window */ + + uInt prev_length; + /* Length of the best match at previous step. Matches not greater than this + * are discarded. This is used in the lazy match evaluation. + */ + + uInt max_chain_length; + /* To speed up deflation, hash chains are never searched beyond this + * length. A higher limit improves compression ratio but degrades the + * speed. + */ + + uInt max_lazy_match; + /* Attempt to find a better match only when the current match is strictly + * smaller than this value. This mechanism is used only for compression + * levels >= 4. + */ +# define max_insert_length max_lazy_match + /* Insert new strings in the hash table only if the match length is not + * greater than this length. This saves time but degrades compression. + * max_insert_length is used only for compression levels <= 3. + */ + + int level; /* compression level (1..9) */ + int strategy; /* favor or force Huffman coding*/ + + uInt good_match; + /* Use a faster search when the previous match is longer than this */ + + int nice_match; /* Stop searching when current match exceeds this */ + + /* used by trees.c: */ + /* Didn't use ct_data typedef below to supress compiler warning */ + struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ + struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ + struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ + + struct tree_desc_s l_desc; /* desc. for literal tree */ + struct tree_desc_s d_desc; /* desc. for distance tree */ + struct tree_desc_s bl_desc; /* desc. for bit length tree */ + + ush bl_count[MAX_BITS+1]; + /* number of codes at each bit length for an optimal tree */ + + int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ + int heap_len; /* number of elements in the heap */ + int heap_max; /* element of largest frequency */ + /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. + * The same heap array is used to build all trees. + */ + + uch depth[2*L_CODES+1]; + /* Depth of each subtree used as tie breaker for trees of equal frequency + */ + + uchf *l_buf; /* buffer for literals or lengths */ + + uInt lit_bufsize; + /* Size of match buffer for literals/lengths. There are 4 reasons for + * limiting lit_bufsize to 64K: + * - frequencies can be kept in 16 bit counters + * - if compression is not successful for the first block, all input + * data is still in the window so we can still emit a stored block even + * when input comes from standard input. (This can also be done for + * all blocks if lit_bufsize is not greater than 32K.) + * - if compression is not successful for a file smaller than 64K, we can + * even emit a stored file instead of a stored block (saving 5 bytes). + * This is applicable only for zip (not gzip or zlib). + * - creating new Huffman trees less frequently may not provide fast + * adaptation to changes in the input data statistics. (Take for + * example a binary file with poorly compressible code followed by + * a highly compressible string table.) Smaller buffer sizes give + * fast adaptation but have of course the overhead of transmitting + * trees more frequently. + * - I can't count above 4 + */ + + uInt last_lit; /* running index in l_buf */ + + ushf *d_buf; + /* Buffer for distances. To simplify the code, d_buf and l_buf have + * the same number of elements. To use different lengths, an extra flag + * array would be necessary. + */ + + ulg opt_len; /* bit length of current block with optimal trees */ + ulg static_len; /* bit length of current block with static trees */ + uInt matches; /* number of string matches in current block */ + int last_eob_len; /* bit length of EOB code for last block */ + +#ifdef DEBUG + ulg compressed_len; /* total bit length of compressed file mod 2^32 */ + ulg bits_sent; /* bit length of compressed data sent mod 2^32 */ +#endif + + ush bi_buf; + /* Output buffer. bits are inserted starting at the bottom (least + * significant bits). + */ + int bi_valid; + /* Number of valid bits in bi_buf. All bits above the last valid bit + * are always zero. + */ + +} FAR deflate_state; + +/* Output a byte on the stream. + * IN assertion: there is enough room in pending_buf. + */ +#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);} + + +#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) +/* Minimum amount of lookahead, except at the end of the input file. + * See deflate.c for comments about the MIN_MATCH+1. + */ + +#define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD) +/* In order to simplify the code, particularly on 16 bit machines, match + * distances are limited to MAX_DIST instead of WSIZE. + */ + + /* in trees.c */ +void _tr_init OF((deflate_state *s)); +int _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc)); +void _tr_flush_block OF((deflate_state *s, charf *buf, ulg stored_len, + int eof)); +void _tr_align OF((deflate_state *s)); +void _tr_stored_block OF((deflate_state *s, charf *buf, ulg stored_len, + int eof)); + +#define d_code(dist) \ + ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)]) +/* Mapping from a distance to a distance code. dist is the distance - 1 and + * must not have side effects. _dist_code[256] and _dist_code[257] are never + * used. + */ + +#ifndef DEBUG +/* Inline versions of _tr_tally for speed: */ + +#if defined(GEN_TREES_H) || !defined(STDC) + extern uch _length_code[]; + extern uch _dist_code[]; +#else + extern const uch _length_code[]; + extern const uch _dist_code[]; +#endif + +# define _tr_tally_lit(s, c, flush) \ + { uch cc = (c); \ + s->d_buf[s->last_lit] = 0; \ + s->l_buf[s->last_lit++] = cc; \ + s->dyn_ltree[cc].Freq++; \ + flush = (s->last_lit == s->lit_bufsize-1); \ + } +# define _tr_tally_dist(s, distance, length, flush) \ + { uch len = (length); \ + ush dist = (distance); \ + s->d_buf[s->last_lit] = dist; \ + s->l_buf[s->last_lit++] = len; \ + dist--; \ + s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \ + s->dyn_dtree[d_code(dist)].Freq++; \ + flush = (s->last_lit == s->lit_bufsize-1); \ + } +#else +# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c) +# define _tr_tally_dist(s, distance, length, flush) \ + flush = _tr_tally(s, distance, length) +#endif + +#endif diff --git a/kernel/fiasco/src/lib/gzip/gzip.c b/kernel/fiasco/src/lib/gzip/gzip.c new file mode 100644 index 00000000..531effc6 --- /dev/null +++ b/kernel/fiasco/src/lib/gzip/gzip.c @@ -0,0 +1,285 @@ +#include +#include + +#include "zlib.h" +#include "zutil.h" +#include "gzip.h" +#include "panic.h" + +static z_stream gz_stream; +static char gz_out_buffer[45]; +static unsigned long gz_crc = 0; +static int gz_magic[2] = {0x1f, 0x8b}; +static void (*raw_write)(const char *s, size_t len); + +/* ENC is the basic 1 character encoding function to make a char printing */ +#define ENC(c) ((c) ? ((c) & 077) + ' ': '`') + +static void +raw_putchar(int c) +{ + const char s[] = { c }; + raw_write(s, 1); +} + +static void +uu_open(const char *name) +{ + raw_write("\nbegin 644 ", 11); + raw_write(name, strlen(name)); + raw_write("\n", 1); +} + +static void +uu_close(void) +{ + char ch = ENC('\0'); + + raw_putchar(ch); + raw_write("\nend\n", 5); +} + +static void +uu_write(const char *in, int len) +{ + register int ch, n; + register const char *p; + static char buf[48]; + + while (len > 0) + { + if (len >= 45) + { + n = 45; + } + else + { + n = len; + } + memcpy(buf, in, n); + memset(buf+n, 0, sizeof(buf)-n); + len -= n; + in += n; + + ch = ENC(n); + raw_putchar(ch); + for (p = buf; n > 0; n -= 3, p += 3) + { + ch = *p >> 2; + ch = ENC(ch); + raw_putchar(ch); + ch = ((*p << 4) & 060) | ((p[1] >> 4) & 017); + ch = ENC(ch); + raw_putchar(ch); + ch = ((p[1] << 2) & 074) | ((p[2] >> 6) & 03); + ch = ENC(ch); + raw_putchar(ch); + ch = p[2] & 077; + ch = ENC(ch); + raw_putchar(ch); + } + raw_putchar('\n'); + } +} + +static void *malloc_array[16]; +static void *malloc_ptr, *malloc_init_ptr; +static unsigned malloc_size, malloc_init_size; + +// linear allocator: allocate memory region +void* +gzip_calloc(unsigned elem, unsigned size) +{ + unsigned i; + + size *= elem; + + if (size > malloc_size) + panic("gzip.c: no memory available (need %08x bytes, have %08x bytes\n", + size, malloc_size); + + for (i=0; i 0) + { + uu_write(gz_out_buffer, len); + gz_stream.next_out = (Bytef*)gz_out_buffer; + gz_stream.avail_out = sizeof(gz_out_buffer); + } +} + +int +gz_write(const char *data, unsigned int size) +{ + gz_stream.next_in = (Bytef*)data; + gz_stream.avail_in = size; + + while (gz_stream.avail_in != 0) + { + int error; + + if (gz_stream.avail_out == 0) + gz_flush_outbuffer(); + + if ((error = deflate(&gz_stream, Z_NO_FLUSH)) != Z_OK) + { + printf("Error \"%s\" in deflate()\n", ERR_MSG(error)); + gz_end(); + return -1; + } + } + + gz_crc = crc32(gz_crc, (const Bytef*)data, size); + + return 0; +} + +int +gz_close(void) +{ + char buf[8], *bptr = buf; + int error; + unsigned len; + + do + { + if (gz_stream.avail_out == 0) + gz_flush_outbuffer(); + + error = deflate(&gz_stream, Z_FINISH); + } while (error == Z_OK); + + if (error != Z_STREAM_END) + { + printf("Error \"%s\" deflate() (flush)\n", ERR_MSG(error)); + gz_end(); + return -1; + } + + if (gz_stream.avail_out == 0) + gz_flush_outbuffer(); + + ((unsigned*)bptr)[0] = gz_crc; + ((unsigned*)bptr)[1] = gz_stream.total_in; + len = 8; + + if (gz_stream.avail_out < len) + { + unsigned tmp_len = gz_stream.avail_out; + + memcpy(gz_stream.next_out, bptr, tmp_len); + len -= tmp_len; + bptr += tmp_len; + gz_stream.avail_out = 0; + gz_flush_outbuffer(); + } + + memcpy(gz_stream.next_out, bptr, len); + gz_stream.avail_out -= len; + gz_flush_outbuffer(); + + uu_close(); + gz_end(); + + return 0; +} + diff --git a/kernel/fiasco/src/lib/gzip/gzip.h b/kernel/fiasco/src/lib/gzip/gzip.h new file mode 100644 index 00000000..d2bcaf60 --- /dev/null +++ b/kernel/fiasco/src/lib/gzip/gzip.h @@ -0,0 +1,20 @@ +#ifndef __GZIP_H +#define __GZIP_H + +#ifdef __cplusplus +extern "C" { +#endif + +void gz_init(void *ptr, unsigned size, + void (*_raw_write)(const char *s, size_t len)); +void gz_end(void); +int gz_open(const char *fname); +int gz_write(const char *data, unsigned int size); +int gz_close(void); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/kernel/fiasco/src/lib/gzip/my_conf.h b/kernel/fiasco/src/lib/gzip/my_conf.h new file mode 100644 index 00000000..a1a783ef --- /dev/null +++ b/kernel/fiasco/src/lib/gzip/my_conf.h @@ -0,0 +1,8 @@ +#ifndef GZIP_MY_CONF_H +#define GZIP_MY_CONF_H + +#define MAX_MEM_LEVEL 6 +#define MAX_WBITS 14 + +#endif + diff --git a/kernel/fiasco/src/lib/gzip/trees.c b/kernel/fiasco/src/lib/gzip/trees.c new file mode 100644 index 00000000..3bf12f32 --- /dev/null +++ b/kernel/fiasco/src/lib/gzip/trees.c @@ -0,0 +1,1214 @@ +/* trees.c -- output deflated data using Huffman coding + * Copyright (C) 1995-2002 Jean-loup Gailly + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * ALGORITHM + * + * The "deflation" process uses several Huffman trees. The more + * common source values are represented by shorter bit sequences. + * + * Each code tree is stored in a compressed form which is itself + * a Huffman encoding of the lengths of all the code strings (in + * ascending order by source values). The actual code strings are + * reconstructed from the lengths in the inflate process, as described + * in the deflate specification. + * + * REFERENCES + * + * Deutsch, L.P.,"'Deflate' Compressed Data Format Specification". + * Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc + * + * Storer, James A. + * Data Compression: Methods and Theory, pp. 49-50. + * Computer Science Press, 1988. ISBN 0-7167-8156-5. + * + * Sedgewick, R. + * Algorithms, p290. + * Addison-Wesley, 1983. ISBN 0-201-06672-6. + */ + +/* @(#) $Id: trees.c 5750 2002-11-19 13:56:17Z us15 $ */ + +/* #define GEN_TREES_H */ + +#include "deflate.h" + +#ifdef DEBUG +# include +#endif + +/* =========================================================================== + * Constants + */ + +#define MAX_BL_BITS 7 +/* Bit length codes must not exceed MAX_BL_BITS bits */ + +#define END_BLOCK 256 +/* end of block literal code */ + +#define REP_3_6 16 +/* repeat previous bit length 3-6 times (2 bits of repeat count) */ + +#define REPZ_3_10 17 +/* repeat a zero length 3-10 times (3 bits of repeat count) */ + +#define REPZ_11_138 18 +/* repeat a zero length 11-138 times (7 bits of repeat count) */ + +local const int extra_lbits[LENGTH_CODES] /* extra bits for each length code */ + = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0}; + +local const int extra_dbits[D_CODES] /* extra bits for each distance code */ + = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; + +local const int extra_blbits[BL_CODES]/* extra bits for each bit length code */ + = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7}; + +local const uch bl_order[BL_CODES] + = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15}; +/* The lengths of the bit length codes are sent in order of decreasing + * probability, to avoid transmitting the lengths for unused bit length codes. + */ + +#define Buf_size (8 * 2*sizeof(char)) +/* Number of bits used within bi_buf. (bi_buf might be implemented on + * more than 16 bits on some systems.) + */ + +/* =========================================================================== + * Local data. These are initialized only once. + */ + +#define DIST_CODE_LEN 512 /* see definition of array dist_code below */ + +#if defined(GEN_TREES_H) || !defined(STDC) +/* non ANSI compilers may not accept trees.h */ + +local ct_data static_ltree[L_CODES+2]; +/* The static literal tree. Since the bit lengths are imposed, there is no + * need for the L_CODES extra codes used during heap construction. However + * The codes 286 and 287 are needed to build a canonical tree (see _tr_init + * below). + */ + +local ct_data static_dtree[D_CODES]; +/* The static distance tree. (Actually a trivial tree since all codes use + * 5 bits.) + */ + +uch _dist_code[DIST_CODE_LEN]; +/* Distance codes. The first 256 values correspond to the distances + * 3 .. 258, the last 256 values correspond to the top 8 bits of + * the 15 bit distances. + */ + +uch _length_code[MAX_MATCH-MIN_MATCH+1]; +/* length code for each normalized match length (0 == MIN_MATCH) */ + +local int base_length[LENGTH_CODES]; +/* First normalized length for each code (0 = MIN_MATCH) */ + +local int base_dist[D_CODES]; +/* First normalized distance for each code (0 = distance of 1) */ + +#else +# include "trees.h" +#endif /* GEN_TREES_H */ + +struct static_tree_desc_s { + const ct_data *static_tree; /* static tree or NULL */ + const intf *extra_bits; /* extra bits for each code or NULL */ + int extra_base; /* base index for extra_bits */ + int elems; /* max number of elements in the tree */ + int max_length; /* max bit length for the codes */ +}; + +local static_tree_desc static_l_desc = +{static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS}; + +local static_tree_desc static_d_desc = +{static_dtree, extra_dbits, 0, D_CODES, MAX_BITS}; + +local static_tree_desc static_bl_desc = +{(const ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS}; + +/* =========================================================================== + * Local (static) routines in this file. + */ + +local void tr_static_init OF((void)); +local void init_block OF((deflate_state *s)); +local void pqdownheap OF((deflate_state *s, ct_data *tree, int k)); +local void gen_bitlen OF((deflate_state *s, tree_desc *desc)); +local void gen_codes OF((ct_data *tree, int max_code, ushf *bl_count)); +local void build_tree OF((deflate_state *s, tree_desc *desc)); +local void scan_tree OF((deflate_state *s, ct_data *tree, int max_code)); +local void send_tree OF((deflate_state *s, ct_data *tree, int max_code)); +local int build_bl_tree OF((deflate_state *s)); +local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes, + int blcodes)); +local void compress_block OF((deflate_state *s, ct_data *ltree, + ct_data *dtree)); +local void set_data_type OF((deflate_state *s)); +local unsigned bi_reverse OF((unsigned value, int length)); +local void bi_windup OF((deflate_state *s)); +local void bi_flush OF((deflate_state *s)); +local void copy_block OF((deflate_state *s, charf *buf, unsigned len, + int header)); + +#ifdef GEN_TREES_H +local void gen_trees_header OF((void)); +#endif + +#ifndef DEBUG +# define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len) + /* Send a code of the given tree. c and tree must not have side effects */ + +#else /* DEBUG */ +# define send_code(s, c, tree) \ + { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \ + send_bits(s, tree[c].Code, tree[c].Len); } +#endif + +/* =========================================================================== + * Output a short LSB first on the stream. + * IN assertion: there is enough room in pendingBuf. + */ +#define put_short(s, w) { \ + put_byte(s, (uch)((w) & 0xff)); \ + put_byte(s, (uch)((ush)(w) >> 8)); \ +} + +/* =========================================================================== + * Send a value on a given number of bits. + * IN assertion: length <= 16 and value fits in length bits. + */ +#ifdef DEBUG +local void send_bits OF((deflate_state *s, int value, int length)); + +local void send_bits(s, value, length) + deflate_state *s; + int value; /* value to send */ + int length; /* number of bits */ +{ + Tracevv((stderr," l %2d v %4x ", length, value)); + Assert(length > 0 && length <= 15, "invalid length"); + s->bits_sent += (ulg)length; + + /* If not enough room in bi_buf, use (valid) bits from bi_buf and + * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid)) + * unused bits in value. + */ + if (s->bi_valid > (int)Buf_size - length) { + s->bi_buf |= (value << s->bi_valid); + put_short(s, s->bi_buf); + s->bi_buf = (ush)value >> (Buf_size - s->bi_valid); + s->bi_valid += length - Buf_size; + } else { + s->bi_buf |= value << s->bi_valid; + s->bi_valid += length; + } +} +#else /* !DEBUG */ + +#define send_bits(s, value, length) \ +{ int len = length;\ + if (s->bi_valid > (int)Buf_size - len) {\ + int val = value;\ + s->bi_buf |= (val << s->bi_valid);\ + put_short(s, s->bi_buf);\ + s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\ + s->bi_valid += len - Buf_size;\ + } else {\ + s->bi_buf |= (value) << s->bi_valid;\ + s->bi_valid += len;\ + }\ +} +#endif /* DEBUG */ + + +#define MAX(a,b) (a >= b ? a : b) +/* the arguments must not have side effects */ + +/* =========================================================================== + * Initialize the various 'constant' tables. + */ +local void tr_static_init() +{ +#if defined(GEN_TREES_H) || !defined(STDC) + static int static_init_done = 0; + int n; /* iterates over tree elements */ + int bits; /* bit counter */ + int length; /* length value */ + int code; /* code value */ + int dist; /* distance index */ + ush bl_count[MAX_BITS+1]; + /* number of codes at each bit length for an optimal tree */ + + if (static_init_done) return; + + /* For some embedded targets, global variables are not initialized: */ + static_l_desc.static_tree = static_ltree; + static_l_desc.extra_bits = extra_lbits; + static_d_desc.static_tree = static_dtree; + static_d_desc.extra_bits = extra_dbits; + static_bl_desc.extra_bits = extra_blbits; + + /* Initialize the mapping length (0..255) -> length code (0..28) */ + length = 0; + for (code = 0; code < LENGTH_CODES-1; code++) { + base_length[code] = length; + for (n = 0; n < (1< dist code (0..29) */ + dist = 0; + for (code = 0 ; code < 16; code++) { + base_dist[code] = dist; + for (n = 0; n < (1<>= 7; /* from now on, all distances are divided by 128 */ + for ( ; code < D_CODES; code++) { + base_dist[code] = dist << 7; + for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) { + _dist_code[256 + dist++] = (uch)code; + } + } + Assert (dist == 256, "tr_static_init: 256+dist != 512"); + + /* Construct the codes of the static literal tree */ + for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0; + n = 0; + while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++; + while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++; + while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++; + while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++; + /* Codes 286 and 287 do not exist, but we must include them in the + * tree construction to get a canonical Huffman tree (longest code + * all ones) + */ + gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count); + + /* The static distance tree is trivial: */ + for (n = 0; n < D_CODES; n++) { + static_dtree[n].Len = 5; + static_dtree[n].Code = bi_reverse((unsigned)n, 5); + } + static_init_done = 1; + +# ifdef GEN_TREES_H + gen_trees_header(); +# endif +#endif /* defined(GEN_TREES_H) || !defined(STDC) */ +} + +/* =========================================================================== + * Genererate the file trees.h describing the static trees. + */ +#ifdef GEN_TREES_H +# ifndef DEBUG +# include +# endif + +# define SEPARATOR(i, last, width) \ + ((i) == (last)? "\n};\n\n" : \ + ((i) % (width) == (width)-1 ? ",\n" : ", ")) + +void gen_trees_header() +{ + FILE *header = fopen("trees.h", "w"); + int i; + + Assert (header != NULL, "Can't open trees.h"); + fprintf(header, + "/* header created automatically with -DGEN_TREES_H */\n\n"); + + fprintf(header, "local const ct_data static_ltree[L_CODES+2] = {\n"); + for (i = 0; i < L_CODES+2; i++) { + fprintf(header, "{{%3u},{%3u}}%s", static_ltree[i].Code, + static_ltree[i].Len, SEPARATOR(i, L_CODES+1, 5)); + } + + fprintf(header, "local const ct_data static_dtree[D_CODES] = {\n"); + for (i = 0; i < D_CODES; i++) { + fprintf(header, "{{%2u},{%2u}}%s", static_dtree[i].Code, + static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5)); + } + + fprintf(header, "const uch _dist_code[DIST_CODE_LEN] = {\n"); + for (i = 0; i < DIST_CODE_LEN; i++) { + fprintf(header, "%2u%s", _dist_code[i], + SEPARATOR(i, DIST_CODE_LEN-1, 20)); + } + + fprintf(header, "const uch _length_code[MAX_MATCH-MIN_MATCH+1]= {\n"); + for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) { + fprintf(header, "%2u%s", _length_code[i], + SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20)); + } + + fprintf(header, "local const int base_length[LENGTH_CODES] = {\n"); + for (i = 0; i < LENGTH_CODES; i++) { + fprintf(header, "%1u%s", base_length[i], + SEPARATOR(i, LENGTH_CODES-1, 20)); + } + + fprintf(header, "local const int base_dist[D_CODES] = {\n"); + for (i = 0; i < D_CODES; i++) { + fprintf(header, "%5u%s", base_dist[i], + SEPARATOR(i, D_CODES-1, 10)); + } + + fclose(header); +} +#endif /* GEN_TREES_H */ + +/* =========================================================================== + * Initialize the tree data structures for a new zlib stream. + */ +void _tr_init(s) + deflate_state *s; +{ + tr_static_init(); + + s->l_desc.dyn_tree = s->dyn_ltree; + s->l_desc.stat_desc = &static_l_desc; + + s->d_desc.dyn_tree = s->dyn_dtree; + s->d_desc.stat_desc = &static_d_desc; + + s->bl_desc.dyn_tree = s->bl_tree; + s->bl_desc.stat_desc = &static_bl_desc; + + s->bi_buf = 0; + s->bi_valid = 0; + s->last_eob_len = 8; /* enough lookahead for inflate */ +#ifdef DEBUG + s->compressed_len = 0L; + s->bits_sent = 0L; +#endif + + /* Initialize the first block of the first file: */ + init_block(s); +} + +/* =========================================================================== + * Initialize a new block. + */ +local void init_block(s) + deflate_state *s; +{ + int n; /* iterates over tree elements */ + + /* Initialize the trees. */ + for (n = 0; n < L_CODES; n++) s->dyn_ltree[n].Freq = 0; + for (n = 0; n < D_CODES; n++) s->dyn_dtree[n].Freq = 0; + for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0; + + s->dyn_ltree[END_BLOCK].Freq = 1; + s->opt_len = s->static_len = 0L; + s->last_lit = s->matches = 0; +} + +#define SMALLEST 1 +/* Index within the heap array of least frequent node in the Huffman tree */ + + +/* =========================================================================== + * Remove the smallest element from the heap and recreate the heap with + * one less element. Updates heap and heap_len. + */ +#define pqremove(s, tree, top) \ +{\ + top = s->heap[SMALLEST]; \ + s->heap[SMALLEST] = s->heap[s->heap_len--]; \ + pqdownheap(s, tree, SMALLEST); \ +} + +/* =========================================================================== + * Compares to subtrees, using the tree depth as tie breaker when + * the subtrees have equal frequency. This minimizes the worst case length. + */ +#define smaller(tree, n, m, depth) \ + (tree[n].Freq < tree[m].Freq || \ + (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m])) + +/* =========================================================================== + * Restore the heap property by moving down the tree starting at node k, + * exchanging a node with the smallest of its two sons if necessary, stopping + * when the heap property is re-established (each father smaller than its + * two sons). + */ +local void pqdownheap(s, tree, k) + deflate_state *s; + ct_data *tree; /* the tree to restore */ + int k; /* node to move down */ +{ + int v = s->heap[k]; + int j = k << 1; /* left son of k */ + while (j <= s->heap_len) { + /* Set j to the smallest of the two sons: */ + if (j < s->heap_len && + smaller(tree, s->heap[j+1], s->heap[j], s->depth)) { + j++; + } + /* Exit if v is smaller than both sons */ + if (smaller(tree, v, s->heap[j], s->depth)) break; + + /* Exchange v with the smallest son */ + s->heap[k] = s->heap[j]; k = j; + + /* And continue down the tree, setting j to the left son of k */ + j <<= 1; + } + s->heap[k] = v; +} + +/* =========================================================================== + * Compute the optimal bit lengths for a tree and update the total bit length + * for the current block. + * IN assertion: the fields freq and dad are set, heap[heap_max] and + * above are the tree nodes sorted by increasing frequency. + * OUT assertions: the field len is set to the optimal bit length, the + * array bl_count contains the frequencies for each bit length. + * The length opt_len is updated; static_len is also updated if stree is + * not null. + */ +local void gen_bitlen(s, desc) + deflate_state *s; + tree_desc *desc; /* the tree descriptor */ +{ + ct_data *tree = desc->dyn_tree; + int max_code = desc->max_code; + const ct_data *stree = desc->stat_desc->static_tree; + const intf *extra = desc->stat_desc->extra_bits; + int base = desc->stat_desc->extra_base; + int max_length = desc->stat_desc->max_length; + int h; /* heap index */ + int n, m; /* iterate over the tree elements */ + int bits; /* bit length */ + int xbits; /* extra bits */ + ush f; /* frequency */ + int overflow = 0; /* number of elements with bit length too large */ + + for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0; + + /* In a first pass, compute the optimal bit lengths (which may + * overflow in the case of the bit length tree). + */ + tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */ + + for (h = s->heap_max+1; h < HEAP_SIZE; h++) { + n = s->heap[h]; + bits = tree[tree[n].Dad].Len + 1; + if (bits > max_length) bits = max_length, overflow++; + tree[n].Len = (ush)bits; + /* We overwrite tree[n].Dad which is no longer needed */ + + if (n > max_code) continue; /* not a leaf node */ + + s->bl_count[bits]++; + xbits = 0; + if (n >= base) xbits = extra[n-base]; + f = tree[n].Freq; + s->opt_len += (ulg)f * (bits + xbits); + if (stree) s->static_len += (ulg)f * (stree[n].Len + xbits); + } + if (overflow == 0) return; + + Trace((stderr,"\nbit length overflow\n")); + /* This happens for example on obj2 and pic of the Calgary corpus */ + + /* Find the first bit length which could increase: */ + do { + bits = max_length-1; + while (s->bl_count[bits] == 0) bits--; + s->bl_count[bits]--; /* move one leaf down the tree */ + s->bl_count[bits+1] += 2; /* move one overflow item as its brother */ + s->bl_count[max_length]--; + /* The brother of the overflow item also moves one step up, + * but this does not affect bl_count[max_length] + */ + overflow -= 2; + } while (overflow > 0); + + /* Now recompute all bit lengths, scanning in increasing frequency. + * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all + * lengths instead of fixing only the wrong ones. This idea is taken + * from 'ar' written by Haruhiko Okumura.) + */ + for (bits = max_length; bits != 0; bits--) { + n = s->bl_count[bits]; + while (n != 0) { + m = s->heap[--h]; + if (m > max_code) continue; + if (tree[m].Len != (unsigned) bits) { + Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); + s->opt_len += ((long)bits - (long)tree[m].Len) + *(long)tree[m].Freq; + tree[m].Len = (ush)bits; + } + n--; + } + } +} + +/* =========================================================================== + * Generate the codes for a given tree and bit counts (which need not be + * optimal). + * IN assertion: the array bl_count contains the bit length statistics for + * the given tree and the field len is set for all tree elements. + * OUT assertion: the field code is set for all tree elements of non + * zero code length. + */ +local void gen_codes (tree, max_code, bl_count) + ct_data *tree; /* the tree to decorate */ + int max_code; /* largest code with non zero frequency */ + ushf *bl_count; /* number of codes at each bit length */ +{ + ush next_code[MAX_BITS+1]; /* next code value for each bit length */ + ush code = 0; /* running code value */ + int bits; /* bit index */ + int n; /* code index */ + + /* The distribution counts are first used to generate the code values + * without bit reversal. + */ + for (bits = 1; bits <= MAX_BITS; bits++) { + next_code[bits] = code = (code + bl_count[bits-1]) << 1; + } + /* Check that the bit counts in bl_count are consistent. The last code + * must be all ones. + */ + Assert (code + bl_count[MAX_BITS]-1 == (1<dyn_tree; + const ct_data *stree = desc->stat_desc->static_tree; + int elems = desc->stat_desc->elems; + int n, m; /* iterate over heap elements */ + int max_code = -1; /* largest code with non zero frequency */ + int node; /* new node being created */ + + /* Construct the initial heap, with least frequent element in + * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. + * heap[0] is not used. + */ + s->heap_len = 0, s->heap_max = HEAP_SIZE; + + for (n = 0; n < elems; n++) { + if (tree[n].Freq != 0) { + s->heap[++(s->heap_len)] = max_code = n; + s->depth[n] = 0; + } else { + tree[n].Len = 0; + } + } + + /* The pkzip format requires that at least one distance code exists, + * and that at least one bit should be sent even if there is only one + * possible code. So to avoid special checks later on we force at least + * two codes of non zero frequency. + */ + while (s->heap_len < 2) { + node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0); + tree[node].Freq = 1; + s->depth[node] = 0; + s->opt_len--; if (stree) s->static_len -= stree[node].Len; + /* node is 0 or 1 so it does not have extra bits */ + } + desc->max_code = max_code; + + /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, + * establish sub-heaps of increasing lengths: + */ + for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n); + + /* Construct the Huffman tree by repeatedly combining the least two + * frequent nodes. + */ + node = elems; /* next internal node of the tree */ + do { + pqremove(s, tree, n); /* n = node of least frequency */ + m = s->heap[SMALLEST]; /* m = node of next least frequency */ + + s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */ + s->heap[--(s->heap_max)] = m; + + /* Create a new node father of n and m */ + tree[node].Freq = tree[n].Freq + tree[m].Freq; + s->depth[node] = (uch) (MAX(s->depth[n], s->depth[m]) + 1); + tree[n].Dad = tree[m].Dad = (ush)node; +#ifdef DUMP_BL_TREE + if (tree == s->bl_tree) { + fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)", + node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq); + } +#endif + /* and insert the new node in the heap */ + s->heap[SMALLEST] = node++; + pqdownheap(s, tree, SMALLEST); + + } while (s->heap_len >= 2); + + s->heap[--(s->heap_max)] = s->heap[SMALLEST]; + + /* At this point, the fields freq and dad are set. We can now + * generate the bit lengths. + */ + gen_bitlen(s, (tree_desc *)desc); + + /* The field len is now set, we can generate the bit codes */ + gen_codes ((ct_data *)tree, max_code, s->bl_count); +} + +/* =========================================================================== + * Scan a literal or distance tree to determine the frequencies of the codes + * in the bit length tree. + */ +local void scan_tree (s, tree, max_code) + deflate_state *s; + ct_data *tree; /* the tree to be scanned */ + int max_code; /* and its largest code of non zero frequency */ +{ + int n; /* iterates over all tree elements */ + int prevlen = -1; /* last emitted length */ + int curlen; /* length of current code */ + int nextlen = tree[0].Len; /* length of next code */ + int count = 0; /* repeat count of the current code */ + int max_count = 7; /* max repeat count */ + int min_count = 4; /* min repeat count */ + + if (nextlen == 0) max_count = 138, min_count = 3; + tree[max_code+1].Len = (ush)0xffff; /* guard */ + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; nextlen = tree[n+1].Len; + if (++count < max_count && curlen == nextlen) { + continue; + } else if (count < min_count) { + s->bl_tree[curlen].Freq += count; + } else if (curlen != 0) { + if (curlen != prevlen) s->bl_tree[curlen].Freq++; + s->bl_tree[REP_3_6].Freq++; + } else if (count <= 10) { + s->bl_tree[REPZ_3_10].Freq++; + } else { + s->bl_tree[REPZ_11_138].Freq++; + } + count = 0; prevlen = curlen; + if (nextlen == 0) { + max_count = 138, min_count = 3; + } else if (curlen == nextlen) { + max_count = 6, min_count = 3; + } else { + max_count = 7, min_count = 4; + } + } +} + +/* =========================================================================== + * Send a literal or distance tree in compressed form, using the codes in + * bl_tree. + */ +local void send_tree (s, tree, max_code) + deflate_state *s; + ct_data *tree; /* the tree to be scanned */ + int max_code; /* and its largest code of non zero frequency */ +{ + int n; /* iterates over all tree elements */ + int prevlen = -1; /* last emitted length */ + int curlen; /* length of current code */ + int nextlen = tree[0].Len; /* length of next code */ + int count = 0; /* repeat count of the current code */ + int max_count = 7; /* max repeat count */ + int min_count = 4; /* min repeat count */ + + /* tree[max_code+1].Len = -1; */ /* guard already set */ + if (nextlen == 0) max_count = 138, min_count = 3; + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; nextlen = tree[n+1].Len; + if (++count < max_count && curlen == nextlen) { + continue; + } else if (count < min_count) { + do { send_code(s, curlen, s->bl_tree); } while (--count != 0); + + } else if (curlen != 0) { + if (curlen != prevlen) { + send_code(s, curlen, s->bl_tree); count--; + } + Assert(count >= 3 && count <= 6, " 3_6?"); + send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2); + + } else if (count <= 10) { + send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3); + + } else { + send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7); + } + count = 0; prevlen = curlen; + if (nextlen == 0) { + max_count = 138, min_count = 3; + } else if (curlen == nextlen) { + max_count = 6, min_count = 3; + } else { + max_count = 7, min_count = 4; + } + } +} + +/* =========================================================================== + * Construct the Huffman tree for the bit lengths and return the index in + * bl_order of the last bit length code to send. + */ +local int build_bl_tree(s) + deflate_state *s; +{ + int max_blindex; /* index of last bit length code of non zero freq */ + + /* Determine the bit length frequencies for literal and distance trees */ + scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code); + scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code); + + /* Build the bit length tree: */ + build_tree(s, (tree_desc *)(&(s->bl_desc))); + /* opt_len now includes the length of the tree representations, except + * the lengths of the bit lengths codes and the 5+5+4 bits for the counts. + */ + + /* Determine the number of bit length codes to send. The pkzip format + * requires that at least 4 bit length codes be sent. (appnote.txt says + * 3 but the actual value used is 4.) + */ + for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) { + if (s->bl_tree[bl_order[max_blindex]].Len != 0) break; + } + /* Update opt_len to include the bit length tree and counts */ + s->opt_len += 3*(max_blindex+1) + 5+5+4; + Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", + s->opt_len, s->static_len)); + + return max_blindex; +} + +/* =========================================================================== + * Send the header for a block using dynamic Huffman trees: the counts, the + * lengths of the bit length codes, the literal tree and the distance tree. + * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. + */ +local void send_all_trees(s, lcodes, dcodes, blcodes) + deflate_state *s; + int lcodes, dcodes, blcodes; /* number of codes for each tree */ +{ + int rank; /* index in bl_order */ + + Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); + Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, + "too many codes"); + Tracev((stderr, "\nbl counts: ")); + send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */ + send_bits(s, dcodes-1, 5); + send_bits(s, blcodes-4, 4); /* not -3 as stated in appnote.txt */ + for (rank = 0; rank < blcodes; rank++) { + Tracev((stderr, "\nbl code %2d ", bl_order[rank])); + send_bits(s, s->bl_tree[bl_order[rank]].Len, 3); + } + Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent)); + + send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */ + Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent)); + + send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */ + Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent)); +} + +/* =========================================================================== + * Send a stored block + */ +void _tr_stored_block(s, buf, stored_len, eof) + deflate_state *s; + charf *buf; /* input block */ + ulg stored_len; /* length of input block */ + int eof; /* true if this is the last block for a file */ +{ + send_bits(s, (STORED_BLOCK<<1)+eof, 3); /* send block type */ +#ifdef DEBUG + s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L; + s->compressed_len += (stored_len + 4) << 3; +#endif + copy_block(s, buf, (unsigned)stored_len, 1); /* with header */ +} + +/* =========================================================================== + * Send one empty static block to give enough lookahead for inflate. + * This takes 10 bits, of which 7 may remain in the bit buffer. + * The current inflate code requires 9 bits of lookahead. If the + * last two codes for the previous block (real code plus EOB) were coded + * on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode + * the last real code. In this case we send two empty static blocks instead + * of one. (There are no problems if the previous block is stored or fixed.) + * To simplify the code, we assume the worst case of last real code encoded + * on one bit only. + */ +void _tr_align(s) + deflate_state *s; +{ + send_bits(s, STATIC_TREES<<1, 3); + send_code(s, END_BLOCK, static_ltree); +#ifdef DEBUG + s->compressed_len += 10L; /* 3 for block type, 7 for EOB */ +#endif + bi_flush(s); + /* Of the 10 bits for the empty block, we have already sent + * (10 - bi_valid) bits. The lookahead for the last real code (before + * the EOB of the previous block) was thus at least one plus the length + * of the EOB plus what we have just sent of the empty static block. + */ + if (1 + s->last_eob_len + 10 - s->bi_valid < 9) { + send_bits(s, STATIC_TREES<<1, 3); + send_code(s, END_BLOCK, static_ltree); +#ifdef DEBUG + s->compressed_len += 10L; +#endif + bi_flush(s); + } + s->last_eob_len = 7; +} + +/* =========================================================================== + * Determine the best encoding for the current block: dynamic trees, static + * trees or store, and output the encoded block to the zip file. + */ +void _tr_flush_block(s, buf, stored_len, eof) + deflate_state *s; + charf *buf; /* input block, or NULL if too old */ + ulg stored_len; /* length of input block */ + int eof; /* true if this is the last block for a file */ +{ + ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */ + int max_blindex = 0; /* index of last bit length code of non zero freq */ + + /* Build the Huffman trees unless a stored block is forced */ + if (s->level > 0) { + + /* Check if the file is ascii or binary */ + if (s->data_type == Z_UNKNOWN) set_data_type(s); + + /* Construct the literal and distance trees */ + build_tree(s, (tree_desc *)(&(s->l_desc))); + Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len, + s->static_len)); + + build_tree(s, (tree_desc *)(&(s->d_desc))); + Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len, + s->static_len)); + /* At this point, opt_len and static_len are the total bit lengths of + * the compressed block data, excluding the tree representations. + */ + + /* Build the bit length tree for the above two trees, and get the index + * in bl_order of the last bit length code to send. + */ + max_blindex = build_bl_tree(s); + + /* Determine the best encoding. Compute first the block length in bytes*/ + opt_lenb = (s->opt_len+3+7)>>3; + static_lenb = (s->static_len+3+7)>>3; + + Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ", + opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, + s->last_lit)); + + if (static_lenb <= opt_lenb) opt_lenb = static_lenb; + + } else { + Assert(buf != (char*)0, "lost buf"); + opt_lenb = static_lenb = stored_len + 5; /* force a stored block */ + } + +#ifdef FORCE_STORED + if (buf != (char*)0) { /* force stored block */ +#else + if (stored_len+4 <= opt_lenb && buf != (char*)0) { + /* 4: two words for the lengths */ +#endif + /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. + * Otherwise we can't have processed more than WSIZE input bytes since + * the last block flush, because compression would have been + * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to + * transform a block into a stored block. + */ + _tr_stored_block(s, buf, stored_len, eof); + +#ifdef FORCE_STATIC + } else if (static_lenb >= 0) { /* force static trees */ +#else + } else if (static_lenb == opt_lenb) { +#endif + send_bits(s, (STATIC_TREES<<1)+eof, 3); + compress_block(s, (ct_data *)static_ltree, (ct_data *)static_dtree); +#ifdef DEBUG + s->compressed_len += 3 + s->static_len; +#endif + } else { + send_bits(s, (DYN_TREES<<1)+eof, 3); + send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1, + max_blindex+1); + compress_block(s, (ct_data *)s->dyn_ltree, (ct_data *)s->dyn_dtree); +#ifdef DEBUG + s->compressed_len += 3 + s->opt_len; +#endif + } + Assert (s->compressed_len == s->bits_sent, "bad compressed size"); + /* The above check is made mod 2^32, for files larger than 512 MB + * and uLong implemented on 32 bits. + */ + init_block(s); + + if (eof) { + bi_windup(s); +#ifdef DEBUG + s->compressed_len += 7; /* align on byte boundary */ +#endif + } + Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3, + s->compressed_len-7*eof)); +} + +/* =========================================================================== + * Save the match info and tally the frequency counts. Return true if + * the current block must be flushed. + */ +int _tr_tally (s, dist, lc) + deflate_state *s; + unsigned dist; /* distance of matched string */ + unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */ +{ + s->d_buf[s->last_lit] = (ush)dist; + s->l_buf[s->last_lit++] = (uch)lc; + if (dist == 0) { + /* lc is the unmatched char */ + s->dyn_ltree[lc].Freq++; + } else { + s->matches++; + /* Here, lc is the match length - MIN_MATCH */ + dist--; /* dist = match distance - 1 */ + Assert((ush)dist < (ush)MAX_DIST(s) && + (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && + (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match"); + + s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++; + s->dyn_dtree[d_code(dist)].Freq++; + } + +#ifdef TRUNCATE_BLOCK + /* Try to guess if it is profitable to stop the current block here */ + if ((s->last_lit & 0x1fff) == 0 && s->level > 2) { + /* Compute an upper bound for the compressed length */ + ulg out_length = (ulg)s->last_lit*8L; + ulg in_length = (ulg)((long)s->strstart - s->block_start); + int dcode; + for (dcode = 0; dcode < D_CODES; dcode++) { + out_length += (ulg)s->dyn_dtree[dcode].Freq * + (5L+extra_dbits[dcode]); + } + out_length >>= 3; + Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ", + s->last_lit, in_length, out_length, + 100L - out_length*100L/in_length)); + if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1; + } +#endif + return (s->last_lit == s->lit_bufsize-1); + /* We avoid equality with lit_bufsize because of wraparound at 64K + * on 16 bit machines and because stored blocks are restricted to + * 64K-1 bytes. + */ +} + +/* =========================================================================== + * Send the block data compressed using the given Huffman trees + */ +local void compress_block(s, ltree, dtree) + deflate_state *s; + ct_data *ltree; /* literal tree */ + ct_data *dtree; /* distance tree */ +{ + unsigned dist; /* distance of matched string */ + int lc; /* match length or unmatched char (if dist == 0) */ + unsigned lx = 0; /* running index in l_buf */ + unsigned code; /* the code to send */ + int extra; /* number of extra bits to send */ + + if (s->last_lit != 0) do { + dist = s->d_buf[lx]; + lc = s->l_buf[lx++]; + if (dist == 0) { + send_code(s, lc, ltree); /* send a literal byte */ + Tracecv(isgraph(lc), (stderr," '%c' ", lc)); + } else { + /* Here, lc is the match length - MIN_MATCH */ + code = _length_code[lc]; + send_code(s, code+LITERALS+1, ltree); /* send the length code */ + extra = extra_lbits[code]; + if (extra != 0) { + lc -= base_length[code]; + send_bits(s, lc, extra); /* send the extra length bits */ + } + dist--; /* dist is now the match distance - 1 */ + code = d_code(dist); + Assert (code < D_CODES, "bad d_code"); + + send_code(s, code, dtree); /* send the distance code */ + extra = extra_dbits[code]; + if (extra != 0) { + dist -= base_dist[code]; + send_bits(s, dist, extra); /* send the extra distance bits */ + } + } /* literal or match pair ? */ + + /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */ + Assert(s->pending < s->lit_bufsize + 2*lx, "pendingBuf overflow"); + + } while (lx < s->last_lit); + + send_code(s, END_BLOCK, ltree); + s->last_eob_len = ltree[END_BLOCK].Len; +} + +/* =========================================================================== + * Set the data type to ASCII or BINARY, using a crude approximation: + * binary if more than 20% of the bytes are <= 6 or >= 128, ascii otherwise. + * IN assertion: the fields freq of dyn_ltree are set and the total of all + * frequencies does not exceed 64K (to fit in an int on 16 bit machines). + */ +local void set_data_type(s) + deflate_state *s; +{ + int n = 0; + unsigned ascii_freq = 0; + unsigned bin_freq = 0; + while (n < 7) bin_freq += s->dyn_ltree[n++].Freq; + while (n < 128) ascii_freq += s->dyn_ltree[n++].Freq; + while (n < LITERALS) bin_freq += s->dyn_ltree[n++].Freq; + s->data_type = (Byte)(bin_freq > (ascii_freq >> 2) ? Z_BINARY : Z_ASCII); +} + +/* =========================================================================== + * Reverse the first len bits of a code, using straightforward code (a faster + * method would use a table) + * IN assertion: 1 <= len <= 15 + */ +local unsigned bi_reverse(code, len) + unsigned code; /* the value to invert */ + int len; /* its bit length */ +{ + register unsigned res = 0; + do { + res |= code & 1; + code >>= 1, res <<= 1; + } while (--len > 0); + return res >> 1; +} + +/* =========================================================================== + * Flush the bit buffer, keeping at most 7 bits in it. + */ +local void bi_flush(s) + deflate_state *s; +{ + if (s->bi_valid == 16) { + put_short(s, s->bi_buf); + s->bi_buf = 0; + s->bi_valid = 0; + } else if (s->bi_valid >= 8) { + put_byte(s, (Byte)s->bi_buf); + s->bi_buf >>= 8; + s->bi_valid -= 8; + } +} + +/* =========================================================================== + * Flush the bit buffer and align the output on a byte boundary + */ +local void bi_windup(s) + deflate_state *s; +{ + if (s->bi_valid > 8) { + put_short(s, s->bi_buf); + } else if (s->bi_valid > 0) { + put_byte(s, (Byte)s->bi_buf); + } + s->bi_buf = 0; + s->bi_valid = 0; +#ifdef DEBUG + s->bits_sent = (s->bits_sent+7) & ~7; +#endif +} + +/* =========================================================================== + * Copy a stored block, storing first the length and its + * one's complement if requested. + */ +local void copy_block(s, buf, len, header) + deflate_state *s; + charf *buf; /* the input data */ + unsigned len; /* its length */ + int header; /* true if block header must be written */ +{ + bi_windup(s); /* align on byte boundary */ + s->last_eob_len = 8; /* enough lookahead for inflate */ + + if (header) { + put_short(s, (ush)len); + put_short(s, (ush)~len); +#ifdef DEBUG + s->bits_sent += 2*16; +#endif + } +#ifdef DEBUG + s->bits_sent += (ulg)len<<3; +#endif + while (len--) { + put_byte(s, *buf++); + } +} diff --git a/kernel/fiasco/src/lib/gzip/trees.h b/kernel/fiasco/src/lib/gzip/trees.h new file mode 100644 index 00000000..72facf90 --- /dev/null +++ b/kernel/fiasco/src/lib/gzip/trees.h @@ -0,0 +1,128 @@ +/* header created automatically with -DGEN_TREES_H */ + +local const ct_data static_ltree[L_CODES+2] = { +{{ 12},{ 8}}, {{140},{ 8}}, {{ 76},{ 8}}, {{204},{ 8}}, {{ 44},{ 8}}, +{{172},{ 8}}, {{108},{ 8}}, {{236},{ 8}}, {{ 28},{ 8}}, {{156},{ 8}}, +{{ 92},{ 8}}, {{220},{ 8}}, {{ 60},{ 8}}, {{188},{ 8}}, {{124},{ 8}}, +{{252},{ 8}}, {{ 2},{ 8}}, {{130},{ 8}}, {{ 66},{ 8}}, {{194},{ 8}}, +{{ 34},{ 8}}, {{162},{ 8}}, {{ 98},{ 8}}, {{226},{ 8}}, {{ 18},{ 8}}, +{{146},{ 8}}, {{ 82},{ 8}}, {{210},{ 8}}, {{ 50},{ 8}}, {{178},{ 8}}, +{{114},{ 8}}, {{242},{ 8}}, {{ 10},{ 8}}, {{138},{ 8}}, {{ 74},{ 8}}, +{{202},{ 8}}, {{ 42},{ 8}}, {{170},{ 8}}, {{106},{ 8}}, {{234},{ 8}}, +{{ 26},{ 8}}, {{154},{ 8}}, {{ 90},{ 8}}, {{218},{ 8}}, {{ 58},{ 8}}, +{{186},{ 8}}, {{122},{ 8}}, {{250},{ 8}}, {{ 6},{ 8}}, {{134},{ 8}}, +{{ 70},{ 8}}, {{198},{ 8}}, {{ 38},{ 8}}, {{166},{ 8}}, {{102},{ 8}}, +{{230},{ 8}}, {{ 22},{ 8}}, {{150},{ 8}}, {{ 86},{ 8}}, {{214},{ 8}}, +{{ 54},{ 8}}, {{182},{ 8}}, {{118},{ 8}}, {{246},{ 8}}, {{ 14},{ 8}}, +{{142},{ 8}}, {{ 78},{ 8}}, {{206},{ 8}}, {{ 46},{ 8}}, {{174},{ 8}}, +{{110},{ 8}}, {{238},{ 8}}, {{ 30},{ 8}}, {{158},{ 8}}, {{ 94},{ 8}}, +{{222},{ 8}}, {{ 62},{ 8}}, {{190},{ 8}}, {{126},{ 8}}, {{254},{ 8}}, +{{ 1},{ 8}}, {{129},{ 8}}, {{ 65},{ 8}}, {{193},{ 8}}, {{ 33},{ 8}}, +{{161},{ 8}}, {{ 97},{ 8}}, {{225},{ 8}}, {{ 17},{ 8}}, {{145},{ 8}}, +{{ 81},{ 8}}, {{209},{ 8}}, {{ 49},{ 8}}, {{177},{ 8}}, {{113},{ 8}}, +{{241},{ 8}}, {{ 9},{ 8}}, {{137},{ 8}}, {{ 73},{ 8}}, {{201},{ 8}}, +{{ 41},{ 8}}, {{169},{ 8}}, {{105},{ 8}}, {{233},{ 8}}, {{ 25},{ 8}}, +{{153},{ 8}}, {{ 89},{ 8}}, {{217},{ 8}}, {{ 57},{ 8}}, {{185},{ 8}}, +{{121},{ 8}}, {{249},{ 8}}, {{ 5},{ 8}}, {{133},{ 8}}, {{ 69},{ 8}}, +{{197},{ 8}}, {{ 37},{ 8}}, {{165},{ 8}}, {{101},{ 8}}, {{229},{ 8}}, +{{ 21},{ 8}}, {{149},{ 8}}, {{ 85},{ 8}}, {{213},{ 8}}, {{ 53},{ 8}}, +{{181},{ 8}}, {{117},{ 8}}, {{245},{ 8}}, {{ 13},{ 8}}, {{141},{ 8}}, +{{ 77},{ 8}}, {{205},{ 8}}, {{ 45},{ 8}}, {{173},{ 8}}, {{109},{ 8}}, +{{237},{ 8}}, {{ 29},{ 8}}, {{157},{ 8}}, {{ 93},{ 8}}, {{221},{ 8}}, +{{ 61},{ 8}}, {{189},{ 8}}, {{125},{ 8}}, {{253},{ 8}}, {{ 19},{ 9}}, +{{275},{ 9}}, {{147},{ 9}}, {{403},{ 9}}, {{ 83},{ 9}}, {{339},{ 9}}, +{{211},{ 9}}, {{467},{ 9}}, {{ 51},{ 9}}, {{307},{ 9}}, {{179},{ 9}}, +{{435},{ 9}}, {{115},{ 9}}, {{371},{ 9}}, {{243},{ 9}}, {{499},{ 9}}, +{{ 11},{ 9}}, {{267},{ 9}}, {{139},{ 9}}, {{395},{ 9}}, {{ 75},{ 9}}, +{{331},{ 9}}, {{203},{ 9}}, {{459},{ 9}}, {{ 43},{ 9}}, {{299},{ 9}}, +{{171},{ 9}}, {{427},{ 9}}, {{107},{ 9}}, {{363},{ 9}}, {{235},{ 9}}, +{{491},{ 9}}, {{ 27},{ 9}}, {{283},{ 9}}, {{155},{ 9}}, {{411},{ 9}}, +{{ 91},{ 9}}, {{347},{ 9}}, {{219},{ 9}}, {{475},{ 9}}, {{ 59},{ 9}}, +{{315},{ 9}}, {{187},{ 9}}, {{443},{ 9}}, {{123},{ 9}}, {{379},{ 9}}, +{{251},{ 9}}, {{507},{ 9}}, {{ 7},{ 9}}, {{263},{ 9}}, {{135},{ 9}}, +{{391},{ 9}}, {{ 71},{ 9}}, {{327},{ 9}}, {{199},{ 9}}, {{455},{ 9}}, +{{ 39},{ 9}}, {{295},{ 9}}, {{167},{ 9}}, {{423},{ 9}}, {{103},{ 9}}, +{{359},{ 9}}, {{231},{ 9}}, {{487},{ 9}}, {{ 23},{ 9}}, {{279},{ 9}}, +{{151},{ 9}}, {{407},{ 9}}, {{ 87},{ 9}}, {{343},{ 9}}, {{215},{ 9}}, +{{471},{ 9}}, {{ 55},{ 9}}, {{311},{ 9}}, {{183},{ 9}}, {{439},{ 9}}, +{{119},{ 9}}, {{375},{ 9}}, {{247},{ 9}}, {{503},{ 9}}, {{ 15},{ 9}}, +{{271},{ 9}}, {{143},{ 9}}, {{399},{ 9}}, {{ 79},{ 9}}, {{335},{ 9}}, +{{207},{ 9}}, {{463},{ 9}}, {{ 47},{ 9}}, {{303},{ 9}}, {{175},{ 9}}, +{{431},{ 9}}, {{111},{ 9}}, {{367},{ 9}}, {{239},{ 9}}, {{495},{ 9}}, +{{ 31},{ 9}}, {{287},{ 9}}, {{159},{ 9}}, {{415},{ 9}}, {{ 95},{ 9}}, +{{351},{ 9}}, {{223},{ 9}}, {{479},{ 9}}, {{ 63},{ 9}}, {{319},{ 9}}, +{{191},{ 9}}, {{447},{ 9}}, {{127},{ 9}}, {{383},{ 9}}, {{255},{ 9}}, +{{511},{ 9}}, {{ 0},{ 7}}, {{ 64},{ 7}}, {{ 32},{ 7}}, {{ 96},{ 7}}, +{{ 16},{ 7}}, {{ 80},{ 7}}, {{ 48},{ 7}}, {{112},{ 7}}, {{ 8},{ 7}}, +{{ 72},{ 7}}, {{ 40},{ 7}}, {{104},{ 7}}, {{ 24},{ 7}}, {{ 88},{ 7}}, +{{ 56},{ 7}}, {{120},{ 7}}, {{ 4},{ 7}}, {{ 68},{ 7}}, {{ 36},{ 7}}, +{{100},{ 7}}, {{ 20},{ 7}}, {{ 84},{ 7}}, {{ 52},{ 7}}, {{116},{ 7}}, +{{ 3},{ 8}}, {{131},{ 8}}, {{ 67},{ 8}}, {{195},{ 8}}, {{ 35},{ 8}}, +{{163},{ 8}}, {{ 99},{ 8}}, {{227},{ 8}} +}; + +local const ct_data static_dtree[D_CODES] = { +{{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}}, +{{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}}, +{{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}}, +{{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}}, +{{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}}, +{{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}} +}; + +const uch _dist_code[DIST_CODE_LEN] = { + 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, + 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, +10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, +11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, +12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, +13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, +13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17, +18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, +23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29 +}; + +const uch _length_code[MAX_MATCH-MIN_MATCH+1]= { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, +13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, +17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, +19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, +21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, +22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, +23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, +25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28 +}; + +local const int base_length[LENGTH_CODES] = { +0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, +64, 80, 96, 112, 128, 160, 192, 224, 0 +}; + +local const int base_dist[D_CODES] = { + 0, 1, 2, 3, 4, 6, 8, 12, 16, 24, + 32, 48, 64, 96, 128, 192, 256, 384, 512, 768, + 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576 +}; + diff --git a/kernel/fiasco/src/lib/gzip/zconf.h b/kernel/fiasco/src/lib/gzip/zconf.h new file mode 100644 index 00000000..dd79d093 --- /dev/null +++ b/kernel/fiasco/src/lib/gzip/zconf.h @@ -0,0 +1,281 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-2002 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id: zconf.h 5805 2002-11-21 12:33:10Z fm3 $ */ + +#ifndef _ZCONF_H +#define _ZCONF_H + +#include "my_conf.h" + +/* + * If you *really* need a unique prefix for all types and library functions, + * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. + */ +#ifdef Z_PREFIX +# define deflateInit_ z_deflateInit_ +# define deflate z_deflate +# define deflateEnd z_deflateEnd +# define inflateInit_ z_inflateInit_ +# define inflate z_inflate +# define inflateEnd z_inflateEnd +# define deflateInit2_ z_deflateInit2_ +# define deflateSetDictionary z_deflateSetDictionary +# define deflateCopy z_deflateCopy +# define deflateReset z_deflateReset +# define deflateParams z_deflateParams +# define inflateInit2_ z_inflateInit2_ +# define inflateSetDictionary z_inflateSetDictionary +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateReset z_inflateReset +# define compress z_compress +# define compress2 z_compress2 +# define uncompress z_uncompress +# define adler32 z_adler32 +# define crc32 z_crc32 +# define get_crc_table z_get_crc_table + +# define Byte z_Byte +# define uInt z_uInt +# define uLong z_uLong +# define Bytef z_Bytef +# define charf z_charf +# define intf z_intf +# define uIntf z_uIntf +# define uLongf z_uLongf +# define voidpf z_voidpf +# define voidp z_voidp +#endif + +#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32) +# define WIN32 +#endif +#if defined(__GNUC__) || defined(WIN32) || defined(__386__) || defined(i386) +# ifndef __32BIT__ +# define __32BIT__ +# endif +#endif +#if defined(__MSDOS__) && !defined(MSDOS) +# define MSDOS +#endif + +/* + * Compile with -DMAXSEG_64K if the alloc function cannot allocate more + * than 64k bytes at a time (needed on systems with 16-bit int). + */ +#if defined(MSDOS) && !defined(__32BIT__) +# define MAXSEG_64K +#endif +#ifdef MSDOS +# define UNALIGNED_OK +#endif + +#if (defined(MSDOS) || defined(_WINDOWS) || defined(WIN32)) && !defined(STDC) +# define STDC +#endif +#if defined(__STDC__) || defined(__cplusplus) || defined(__OS2__) +# ifndef STDC +# define STDC +# endif +#endif + +#ifndef STDC +# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ +# define const +# endif +#endif + +/* Some Mac compilers merge all .h files incorrectly: */ +#if defined(__MWERKS__) || defined(applec) ||defined(THINK_C) ||defined(__SC__) +# define NO_DUMMY_DECL +#endif + +/* Old Borland C incorrectly complains about missing returns: */ +#if defined(__BORLANDC__) && (__BORLANDC__ < 0x500) +# define NEED_DUMMY_RETURN +#endif + + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +# ifdef MAXSEG_64K +# define MAX_MEM_LEVEL 8 +# else +# define MAX_MEM_LEVEL 9 +# endif +#endif + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus a few kilobytes + for small objects. +*/ + + /* Type declarations */ + +#ifndef OF /* function prototypes */ +# ifdef STDC +# define OF(args) args +# else +# define OF(args) () +# endif +#endif + +/* The following definitions for FAR are needed only for MSDOS mixed + * model programming (small or medium model with some far allocations). + * This was tested only with MSC; for other MSDOS compilers you may have + * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, + * just define FAR to be empty. + */ +#if (defined(M_I86SM) || defined(M_I86MM)) && !defined(__32BIT__) + /* MSC small or medium model */ +# define SMALL_MEDIUM +# ifdef _MSC_VER +# define FAR _far +# else +# define FAR far +# endif +#endif +#if defined(__BORLANDC__) && (defined(__SMALL__) || defined(__MEDIUM__)) +# ifndef __32BIT__ +# define SMALL_MEDIUM +# define FAR _far +# endif +#endif + +/* Compile with -DZLIB_DLL for Windows DLL support */ +#if defined(ZLIB_DLL) +# if defined(_WINDOWS) || defined(WINDOWS) +# ifdef FAR +# undef FAR +# endif +# include +# define ZEXPORT WINAPI +# ifdef WIN32 +# define ZEXPORTVA WINAPIV +# else +# define ZEXPORTVA FAR _cdecl _export +# endif +# endif +# if defined (__BORLANDC__) +# if (__BORLANDC__ >= 0x0500) && defined (WIN32) +# include +# define ZEXPORT __declspec(dllexport) WINAPI +# define ZEXPORTRVA __declspec(dllexport) WINAPIV +# else +# if defined (_Windows) && defined (__DLL__) +# define ZEXPORT _export +# define ZEXPORTVA _export +# endif +# endif +# endif +#endif + +#if defined (__BEOS__) +# if defined (ZLIB_DLL) +# define ZEXTERN extern __declspec(dllexport) +# else +# define ZEXTERN extern __declspec(dllimport) +# endif +#endif + +#ifndef ZEXPORT +# define ZEXPORT +#endif +#ifndef ZEXPORTVA +# define ZEXPORTVA +#endif +#ifndef ZEXTERN +# define ZEXTERN extern +#endif + +#ifndef FAR +# define FAR +#endif + +#if !defined(MACOS) && !defined(TARGET_OS_MAC) +typedef unsigned char Byte; /* 8 bits */ +#endif +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ + +#ifdef SMALL_MEDIUM + /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ +# define Bytef Byte FAR +#else + typedef Byte FAR Bytef; +#endif +typedef char FAR charf; +typedef int FAR intf; +typedef uInt FAR uIntf; +typedef uLong FAR uLongf; + +#ifdef STDC + typedef void FAR *voidpf; + typedef void *voidp; +#else + typedef Byte FAR *voidpf; + typedef Byte *voidp; +#endif + +#ifdef HAVE_UNISTD_H +# include /* for off_t */ +# include /* for SEEK_* and off_t */ +# define z_off_t off_t +#endif +#ifndef SEEK_SET +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ +#endif +#ifndef z_off_t +# define z_off_t long +#endif + +/* MVS linker does not support external names larger than 8 bytes */ +#if defined(__MVS__) +# pragma map(deflateInit_,"DEIN") +# pragma map(deflateInit2_,"DEIN2") +# pragma map(deflateEnd,"DEEND") +# pragma map(inflateInit_,"ININ") +# pragma map(inflateInit2_,"ININ2") +# pragma map(inflateEnd,"INEND") +# pragma map(inflateSync,"INSY") +# pragma map(inflateSetDictionary,"INSEDI") +# pragma map(inflate_blocks,"INBL") +# pragma map(inflate_blocks_new,"INBLNE") +# pragma map(inflate_blocks_free,"INBLFR") +# pragma map(inflate_blocks_reset,"INBLRE") +# pragma map(inflate_codes_free,"INCOFR") +# pragma map(inflate_codes,"INCO") +# pragma map(inflate_fast,"INFA") +# pragma map(inflate_flush,"INFLU") +# pragma map(inflate_mask,"INMA") +# pragma map(inflate_set_dictionary,"INSEDI2") +# pragma map(inflate_copyright,"INCOPY") +# pragma map(inflate_trees_bits,"INTRBI") +# pragma map(inflate_trees_dynamic,"INTRDY") +# pragma map(inflate_trees_fixed,"INTRFI") +# pragma map(inflate_trees_free,"INTRFR") +#endif + +#endif /* _ZCONF_H */ diff --git a/kernel/fiasco/src/lib/gzip/zlib.h b/kernel/fiasco/src/lib/gzip/zlib.h new file mode 100644 index 00000000..52cb529f --- /dev/null +++ b/kernel/fiasco/src/lib/gzip/zlib.h @@ -0,0 +1,893 @@ +/* zlib.h -- interface of the 'zlib' general purpose compression library + version 1.1.4, March 11th, 2002 + + Copyright (C) 1995-2002 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + + + The data format used by the zlib library is described by RFCs (Request for + Comments) 1950 to 1952 in the files ftp://ds.internic.net/rfc/rfc1950.txt + (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). +*/ + +#ifndef _ZLIB_H +#define _ZLIB_H + +#include "zconf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ZLIB_VERSION "1.1.4" + +/* + The 'zlib' compression library provides in-memory compression and + decompression functions, including integrity checks of the uncompressed + data. This version of the library supports only one compression method + (deflation) but other algorithms will be added later and will have the same + stream interface. + + Compression can be done in a single step if the buffers are large + enough (for example if an input file is mmap'ed), or can be done by + repeated calls of the compression function. In the latter case, the + application must provide more input and/or consume the output + (providing more output space) before each call. + + The library also supports reading and writing files in gzip (.gz) format + with an interface similar to that of stdio. + + The library does not install any signal handler. The decoder checks + the consistency of the compressed data, so the library should never + crash even in case of corrupted input. +*/ + +typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); +typedef void (*free_func) OF((voidpf opaque, voidpf address)); + +struct internal_state; + +typedef struct z_stream_s { + Bytef *next_in; /* next input byte */ + uInt avail_in; /* number of bytes available at next_in */ + uLong total_in; /* total nb of input bytes read so far */ + + Bytef *next_out; /* next output byte should be put there */ + uInt avail_out; /* remaining free space at next_out */ + uLong total_out; /* total nb of bytes output so far */ + + char *msg; /* last error message, NULL if no error */ + struct internal_state FAR *state; /* not visible by applications */ + + alloc_func zalloc; /* used to allocate the internal state */ + free_func zfree; /* used to free the internal state */ + voidpf opaque; /* private data object passed to zalloc and zfree */ + + int data_type; /* best guess about the data type: ascii or binary */ + uLong adler; /* adler32 value of the uncompressed data */ + uLong reserved; /* reserved for future use */ +} z_stream; + +typedef z_stream FAR *z_streamp; + +/* + The application must update next_in and avail_in when avail_in has + dropped to zero. It must update next_out and avail_out when avail_out + has dropped to zero. The application must initialize zalloc, zfree and + opaque before calling the init function. All other fields are set by the + compression library and must not be updated by the application. + + The opaque value provided by the application will be passed as the first + parameter for calls of zalloc and zfree. This can be useful for custom + memory management. The compression library attaches no meaning to the + opaque value. + + zalloc must return Z_NULL if there is not enough memory for the object. + If zlib is used in a multi-threaded application, zalloc and zfree must be + thread safe. + + On 16-bit systems, the functions zalloc and zfree must be able to allocate + exactly 65536 bytes, but will not be required to allocate more than this + if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, + pointers returned by zalloc for objects of exactly 65536 bytes *must* + have their offset normalized to zero. The default allocation function + provided by this library ensures this (see zutil.c). To reduce memory + requirements and avoid any allocation of 64K objects, at the expense of + compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h). + + The fields total_in and total_out can be used for statistics or + progress reports. After compression, total_in holds the total size of + the uncompressed data and may be saved for use in the decompressor + (particularly if the decompressor wants to decompress everything in + a single step). +*/ + + /* constants */ + +#define Z_NO_FLUSH 0 +#define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */ +#define Z_SYNC_FLUSH 2 +#define Z_FULL_FLUSH 3 +#define Z_FINISH 4 +/* Allowed flush values; see deflate() below for details */ + +#define Z_OK 0 +#define Z_STREAM_END 1 +#define Z_NEED_DICT 2 +#define Z_ERRNO (-1) +#define Z_STREAM_ERROR (-2) +#define Z_DATA_ERROR (-3) +#define Z_MEM_ERROR (-4) +#define Z_BUF_ERROR (-5) +#define Z_VERSION_ERROR (-6) +/* Return codes for the compression/decompression functions. Negative + * values are errors, positive values are used for special but normal events. + */ + +#define Z_NO_COMPRESSION 0 +#define Z_BEST_SPEED 1 +#define Z_BEST_COMPRESSION 9 +#define Z_DEFAULT_COMPRESSION (-1) +/* compression levels */ + +#define Z_FILTERED 1 +#define Z_HUFFMAN_ONLY 2 +#define Z_DEFAULT_STRATEGY 0 +/* compression strategy; see deflateInit2() below for details */ + +#define Z_BINARY 0 +#define Z_ASCII 1 +#define Z_UNKNOWN 2 +/* Possible values of the data_type field */ + +#define Z_DEFLATED 8 +/* The deflate compression method (the only one supported in this version) */ + +#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ + +#define zlib_version zlibVersion() +/* for compatibility with versions < 1.0.2 */ + + /* basic functions */ + +ZEXTERN const char * ZEXPORT zlibVersion OF((void)); +/* The application can compare zlibVersion and ZLIB_VERSION for consistency. + If the first character differs, the library code actually used is + not compatible with the zlib.h header file used by the application. + This check is automatically made by deflateInit and inflateInit. + */ + +/* +ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); + + Initializes the internal stream state for compression. The fields + zalloc, zfree and opaque must be initialized before by the caller. + If zalloc and zfree are set to Z_NULL, deflateInit updates them to + use default allocation functions. + + The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: + 1 gives best speed, 9 gives best compression, 0 gives no compression at + all (the input data is simply copied a block at a time). + Z_DEFAULT_COMPRESSION requests a default compromise between speed and + compression (currently equivalent to level 6). + + deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if level is not a valid compression level, + Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible + with the version assumed by the caller (ZLIB_VERSION). + msg is set to null if there is no error message. deflateInit does not + perform any compression: this will be done by deflate(). +*/ + + +ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); +/* + deflate compresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce some + output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. deflate performs one or both of the + following actions: + + - Compress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in and avail_in are updated and + processing will resume at this point for the next call of deflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. This action is forced if the parameter flush is non zero. + Forcing flush frequently degrades the compression ratio, so this parameter + should be set only when necessary (in interactive applications). + Some output may be provided even if flush is not set. + + Before the call of deflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming + more output, and updating avail_in or avail_out accordingly; avail_out + should never be zero before the call. The application can consume the + compressed output when it wants, for example when the output buffer is full + (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK + and with zero avail_out, it must be called again after making room in the + output buffer because there might be more output pending. + + If the parameter flush is set to Z_SYNC_FLUSH, all pending output is + flushed to the output buffer and the output is aligned on a byte boundary, so + that the decompressor can get all input data available so far. (In particular + avail_in is zero after the call if enough output space has been provided + before the call.) Flushing may degrade compression for some compression + algorithms and so it should be used only when necessary. + + If flush is set to Z_FULL_FLUSH, all output is flushed as with + Z_SYNC_FLUSH, and the compression state is reset so that decompression can + restart from this point if previous compressed data has been damaged or if + random access is desired. Using Z_FULL_FLUSH too often can seriously degrade + the compression. + + If deflate returns with avail_out == 0, this function must be called again + with the same value of the flush parameter and more output space (updated + avail_out), until the flush is complete (deflate returns with non-zero + avail_out). + + If the parameter flush is set to Z_FINISH, pending input is processed, + pending output is flushed and deflate returns with Z_STREAM_END if there + was enough output space; if deflate returns with Z_OK, this function must be + called again with Z_FINISH and more output space (updated avail_out) but no + more input data, until it returns with Z_STREAM_END or an error. After + deflate has returned Z_STREAM_END, the only possible operations on the + stream are deflateReset or deflateEnd. + + Z_FINISH can be used immediately after deflateInit if all the compression + is to be done in a single step. In this case, avail_out must be at least + 0.1% larger than avail_in plus 12 bytes. If deflate does not return + Z_STREAM_END, then it must be called again as described above. + + deflate() sets strm->adler to the adler32 checksum of all input read + so far (that is, total_in bytes). + + deflate() may update data_type if it can make a good guess about + the input data type (Z_ASCII or Z_BINARY). In doubt, the data is considered + binary. This field is only for information purposes and does not affect + the compression algorithm in any manner. + + deflate() returns Z_OK if some progress has been made (more input + processed or more output produced), Z_STREAM_END if all input has been + consumed and all output has been produced (only when flush is set to + Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example + if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible + (for example avail_in or avail_out was zero). +*/ + + +ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any + pending output. + + deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the + stream state was inconsistent, Z_DATA_ERROR if the stream was freed + prematurely (some input or output was discarded). In the error case, + msg may be set but then points to a static string (which must not be + deallocated). +*/ + + +/* +ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); + + Initializes the internal stream state for decompression. The fields + next_in, avail_in, zalloc, zfree and opaque must be initialized before by + the caller. If next_in is not Z_NULL and avail_in is large enough (the exact + value depends on the compression method), inflateInit determines the + compression method from the zlib header and allocates all data structures + accordingly; otherwise the allocation will be deferred to the first call of + inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to + use default allocation functions. + + inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller. msg is set to null if there is no error + message. inflateInit does not perform any decompression apart from reading + the zlib header if present: this will be done by inflate(). (So next_in and + avail_in may be modified, but next_out and avail_out are unchanged.) +*/ + + +ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); +/* + inflate decompresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may some + introduce some output latency (reading input without producing any output) + except when forced to flush. + + The detailed semantics are as follows. inflate performs one or both of the + following actions: + + - Decompress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in is updated and processing + will resume at this point for the next call of inflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. inflate() provides as much output as possible, until there + is no more input data or no more space in the output buffer (see below + about the flush parameter). + + Before the call of inflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming + more output, and updating the next_* and avail_* values accordingly. + The application can consume the uncompressed output when it wants, for + example when the output buffer is full (avail_out == 0), or after each + call of inflate(). If inflate returns Z_OK and with zero avail_out, it + must be called again after making room in the output buffer because there + might be more output pending. + + If the parameter flush is set to Z_SYNC_FLUSH, inflate flushes as much + output as possible to the output buffer. The flushing behavior of inflate is + not specified for values of the flush parameter other than Z_SYNC_FLUSH + and Z_FINISH, but the current implementation actually flushes as much output + as possible anyway. + + inflate() should normally be called until it returns Z_STREAM_END or an + error. However if all decompression is to be performed in a single step + (a single call of inflate), the parameter flush should be set to + Z_FINISH. In this case all pending input is processed and all pending + output is flushed; avail_out must be large enough to hold all the + uncompressed data. (The size of the uncompressed data may have been saved + by the compressor for this purpose.) The next operation on this stream must + be inflateEnd to deallocate the decompression state. The use of Z_FINISH + is never required, but can be used to inform inflate that a faster routine + may be used for the single inflate() call. + + If a preset dictionary is needed at this point (see inflateSetDictionary + below), inflate sets strm-adler to the adler32 checksum of the + dictionary chosen by the compressor and returns Z_NEED_DICT; otherwise + it sets strm->adler to the adler32 checksum of all output produced + so far (that is, total_out bytes) and returns Z_OK, Z_STREAM_END or + an error code as described below. At the end of the stream, inflate() + checks that its computed adler32 checksum is equal to that saved by the + compressor and returns Z_STREAM_END only if the checksum is correct. + + inflate() returns Z_OK if some progress has been made (more input processed + or more output produced), Z_STREAM_END if the end of the compressed data has + been reached and all uncompressed output has been produced, Z_NEED_DICT if a + preset dictionary is needed at this point, Z_DATA_ERROR if the input data was + corrupted (input stream not conforming to the zlib format or incorrect + adler32 checksum), Z_STREAM_ERROR if the stream structure was inconsistent + (for example if next_in or next_out was NULL), Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if no progress is possible or if there was not + enough room in the output buffer when Z_FINISH is used. In the Z_DATA_ERROR + case, the application may then call inflateSync to look for a good + compression block. +*/ + + +ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any + pending output. + + inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state + was inconsistent. In the error case, msg may be set but then points to a + static string (which must not be deallocated). +*/ + + /* Advanced functions */ + +/* + The following functions are needed only in some special applications. +*/ + +/* +ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, + int level, + int method, + int windowBits, + int memLevel, + int strategy)); + + This is another version of deflateInit with more compression options. The + fields next_in, zalloc, zfree and opaque must be initialized before by + the caller. + + The method parameter is the compression method. It must be Z_DEFLATED in + this version of the library. + + The windowBits parameter is the base two logarithm of the window size + (the size of the history buffer). It should be in the range 8..15 for this + version of the library. Larger values of this parameter result in better + compression at the expense of memory usage. The default value is 15 if + deflateInit is used instead. + + The memLevel parameter specifies how much memory should be allocated + for the internal compression state. memLevel=1 uses minimum memory but + is slow and reduces compression ratio; memLevel=9 uses maximum memory + for optimal speed. The default value is 8. See zconf.h for total memory + usage as a function of windowBits and memLevel. + + The strategy parameter is used to tune the compression algorithm. Use the + value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a + filter (or predictor), or Z_HUFFMAN_ONLY to force Huffman encoding only (no + string match). Filtered data consists mostly of small values with a + somewhat random distribution. In this case, the compression algorithm is + tuned to compress them better. The effect of Z_FILTERED is to force more + Huffman coding and less string matching; it is somewhat intermediate + between Z_DEFAULT and Z_HUFFMAN_ONLY. The strategy parameter only affects + the compression ratio but not the correctness of the compressed output even + if it is not set appropriately. + + deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid + method). msg is set to null if there is no error message. deflateInit2 does + not perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the compression dictionary from the given byte sequence + without producing any compressed output. This function must be called + immediately after deflateInit, deflateInit2 or deflateReset, before any + call of deflate. The compressor and decompressor must use exactly the same + dictionary (see inflateSetDictionary). + + The dictionary should consist of strings (byte sequences) that are likely + to be encountered later in the data to be compressed, with the most commonly + used strings preferably put towards the end of the dictionary. Using a + dictionary is most useful when the data to be compressed is short and can be + predicted with good accuracy; the data can then be compressed better than + with the default empty dictionary. + + Depending on the size of the compression data structures selected by + deflateInit or deflateInit2, a part of the dictionary may in effect be + discarded, for example if the dictionary is larger than the window size in + deflate or deflate2. Thus the strings most likely to be useful should be + put at the end of the dictionary, not at the front. + + Upon return of this function, strm->adler is set to the Adler32 value + of the dictionary; the decompressor may later use this value to determine + which dictionary has been used by the compressor. (The Adler32 value + applies to the whole dictionary even if only a subset of the dictionary is + actually used by the compressor.) + + deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a + parameter is invalid (such as NULL dictionary) or the stream state is + inconsistent (for example if deflate has already been called for this stream + or if the compression method is bsort). deflateSetDictionary does not + perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when several compression strategies will be + tried, for example when there are several ways of pre-processing the input + data with a filter. The streams that will be discarded should then be freed + by calling deflateEnd. Note that deflateCopy duplicates the internal + compression state which can be quite large, so this strategy is slow and + can consume lots of memory. + + deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); +/* + This function is equivalent to deflateEnd followed by deflateInit, + but does not free and reallocate all the internal compression state. + The stream will keep the same compression level and any other attributes + that may have been set by deflateInit2. + + deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being NULL). +*/ + +ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, + int level, + int strategy)); +/* + Dynamically update the compression level and compression strategy. The + interpretation of level and strategy is as in deflateInit2. This can be + used to switch between compression and straight copy of the input data, or + to switch to a different kind of input data requiring a different + strategy. If the compression level is changed, the input available so far + is compressed with the old level (and may be flushed); the new level will + take effect only at the next call of deflate(). + + Before the call of deflateParams, the stream state must be set as for + a call of deflate(), since the currently available input may have to + be compressed and flushed. In particular, strm->avail_out must be non-zero. + + deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source + stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR + if strm->avail_out was zero. +*/ + +/* +ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, + int windowBits)); + + This is another version of inflateInit with an extra parameter. The + fields next_in, avail_in, zalloc, zfree and opaque must be initialized + before by the caller. + + The windowBits parameter is the base two logarithm of the maximum window + size (the size of the history buffer). It should be in the range 8..15 for + this version of the library. The default value is 15 if inflateInit is used + instead. If a compressed stream with a larger window size is given as + input, inflate() will return with the error code Z_DATA_ERROR instead of + trying to allocate a larger window. + + inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if a parameter is invalid (such as a negative + memLevel). msg is set to null if there is no error message. inflateInit2 + does not perform any decompression apart from reading the zlib header if + present: this will be done by inflate(). (So next_in and avail_in may be + modified, but next_out and avail_out are unchanged.) +*/ + +ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the decompression dictionary from the given uncompressed byte + sequence. This function must be called immediately after a call of inflate + if this call returned Z_NEED_DICT. The dictionary chosen by the compressor + can be determined from the Adler32 value returned by this call of + inflate. The compressor and decompressor must use exactly the same + dictionary (see deflateSetDictionary). + + inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a + parameter is invalid (such as NULL dictionary) or the stream state is + inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the + expected one (incorrect Adler32 value). inflateSetDictionary does not + perform any decompression: this will be done by subsequent calls of + inflate(). +*/ + +ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); +/* + Skips invalid compressed data until a full flush point (see above the + description of deflate with Z_FULL_FLUSH) can be found, or until all + available input is skipped. No output is provided. + + inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR + if no more input was provided, Z_DATA_ERROR if no flush point has been found, + or Z_STREAM_ERROR if the stream structure was inconsistent. In the success + case, the application may save the current current value of total_in which + indicates where valid compressed data was found. In the error case, the + application may repeatedly call inflateSync, providing more input each time, + until success or end of the input data. +*/ + +ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); +/* + This function is equivalent to inflateEnd followed by inflateInit, + but does not free and reallocate all the internal decompression state. + The stream will keep attributes that may have been set by inflateInit2. + + inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being NULL). +*/ + + + /* utility functions */ + +/* + The following utility functions are implemented on top of the + basic stream-oriented functions. To simplify the interface, some + default options are assumed (compression level and memory usage, + standard memory allocation functions). The source code of these + utility functions can easily be modified if you need special options. +*/ + +ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Compresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be at least 0.1% larger than + sourceLen plus 12 bytes. Upon exit, destLen is the actual size of the + compressed buffer. + This function can be used to compress a whole file at once if the + input file is mmap'ed. + compress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer. +*/ + +ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen, + int level)); +/* + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least 0.1% larger than sourceLen plus + 12 bytes. Upon exit, destLen is the actual size of the compressed buffer. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ + +ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be large enough to hold the + entire uncompressed data. (The size of the uncompressed data must have + been saved previously by the compressor and transmitted to the decompressor + by some mechanism outside the scope of this compression library.) + Upon exit, destLen is the actual size of the compressed buffer. + This function can be used to decompress a whole file at once if the + input file is mmap'ed. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted. +*/ + + +typedef voidp gzFile; + +ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); +/* + Opens a gzip (.gz) file for reading or writing. The mode parameter + is as in fopen ("rb" or "wb") but can also include a compression level + ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for + Huffman only compression as in "wb1h". (See the description + of deflateInit2 for more information about the strategy parameter.) + + gzopen can be used to read a file which is not in gzip format; in this + case gzread will directly read from the file without decompression. + + gzopen returns NULL if the file could not be opened or if there was + insufficient memory to allocate the (de)compression state; errno + can be checked to distinguish the two cases (if errno is zero, the + zlib error is Z_MEM_ERROR). */ + +ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); +/* + gzdopen() associates a gzFile with the file descriptor fd. File + descriptors are obtained from calls like open, dup, creat, pipe or + fileno (in the file has been previously opened with fopen). + The mode parameter is as in gzopen. + The next call of gzclose on the returned gzFile will also close the + file descriptor fd, just like fclose(fdopen(fd), mode) closes the file + descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode). + gzdopen returns NULL if there was insufficient memory to allocate + the (de)compression state. +*/ + +ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); +/* + Dynamically update the compression level or strategy. See the description + of deflateInit2 for the meaning of these parameters. + gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not + opened for writing. +*/ + +ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); +/* + Reads the given number of uncompressed bytes from the compressed file. + If the input file was not in gzip format, gzread copies the given number + of bytes into the buffer. + gzread returns the number of uncompressed bytes actually read (0 for + end of file, -1 for error). */ + +ZEXTERN int ZEXPORT gzwrite OF((gzFile file, + const voidp buf, unsigned len)); +/* + Writes the given number of uncompressed bytes into the compressed file. + gzwrite returns the number of uncompressed bytes actually written + (0 in case of error). +*/ + +ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...)); +/* + Converts, formats, and writes the args to the compressed file under + control of the format string, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written (0 in case of error). +*/ + +ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); +/* + Writes the given null-terminated string to the compressed file, excluding + the terminating null character. + gzputs returns the number of characters written, or -1 in case of error. +*/ + +ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); +/* + Reads bytes from the compressed file until len-1 characters are read, or + a newline character is read and transferred to buf, or an end-of-file + condition is encountered. The string is then terminated with a null + character. + gzgets returns buf, or Z_NULL in case of error. +*/ + +ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); +/* + Writes c, converted to an unsigned char, into the compressed file. + gzputc returns the value that was written, or -1 in case of error. +*/ + +ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); +/* + Reads one byte from the compressed file. gzgetc returns this byte + or -1 in case of end of file or error. +*/ + +ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); +/* + Flushes all pending output into the compressed file. The parameter + flush is as in the deflate() function. The return value is the zlib + error number (see function gzerror below). gzflush returns Z_OK if + the flush parameter is Z_FINISH and all output could be flushed. + gzflush should be called only when strictly necessary because it can + degrade compression. +*/ + +ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, + z_off_t offset, int whence)); +/* + Sets the starting position for the next gzread or gzwrite on the + given compressed file. The offset represents a number of bytes in the + uncompressed data stream. The whence parameter is defined as in lseek(2); + the value SEEK_END is not supported. + If the file is opened for reading, this function is emulated but can be + extremely slow. If the file is opened for writing, only forward seeks are + supported; gzseek then compresses a sequence of zeroes up to the new + starting position. + + gzseek returns the resulting offset location as measured in bytes from + the beginning of the uncompressed stream, or -1 in case of error, in + particular if the file is opened for writing and the new starting position + would be before the current position. +*/ + +ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); +/* + Rewinds the given file. This function is supported only for reading. + + gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) +*/ + +ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); +/* + Returns the starting position for the next gzread or gzwrite on the + given compressed file. This position represents a number of bytes in the + uncompressed data stream. + + gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) +*/ + +ZEXTERN int ZEXPORT gzeof OF((gzFile file)); +/* + Returns 1 when EOF has previously been detected reading the given + input stream, otherwise zero. +*/ + +ZEXTERN int ZEXPORT gzclose OF((gzFile file)); +/* + Flushes all pending output if necessary, closes the compressed file + and deallocates all the (de)compression state. The return value is the zlib + error number (see function gzerror below). +*/ + +ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); +/* + Returns the error message for the last error which occurred on the + given compressed file. errnum is set to zlib error number. If an + error occurred in the file system and not in the compression library, + errnum is set to Z_ERRNO and the application may consult errno + to get the exact error code. +*/ + + /* checksum functions */ + +/* + These functions are not related to compression but are exported + anyway because they might be useful in applications using the + compression library. +*/ + +ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); + +/* + Update a running Adler-32 checksum with the bytes buf[0..len-1] and + return the updated checksum. If buf is NULL, this function returns + the required initial value for the checksum. + An Adler-32 checksum is almost as reliable as a CRC32 but can be computed + much faster. Usage example: + + uLong adler = adler32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + adler = adler32(adler, buffer, length); + } + if (adler != original_adler) error(); +*/ + +ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); +/* + Update a running crc with the bytes buf[0..len-1] and return the updated + crc. If buf is NULL, this function returns the required initial value + for the crc. Pre- and post-conditioning (one's complement) is performed + within this function so it shouldn't be done by the application. + Usage example: + + uLong crc = crc32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + crc = crc32(crc, buffer, length); + } + if (crc != original_crc) error(); +*/ + + + /* various hacks, don't look :) */ + +/* deflateInit and inflateInit are macros to allow checking the zlib version + * and the compiler's view of z_stream: + */ +ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, + int windowBits, int memLevel, + int strategy, const char *version, + int stream_size)); +ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, + const char *version, int stream_size)); +#define deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream)) +#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream)) + + +#if !defined(_Z_UTIL_H) && !defined(NO_DUMMY_DECL) + struct internal_state {int dummy;}; /* hack for buggy compilers */ +#endif + +ZEXTERN const char * ZEXPORT zError OF((int err)); +ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp z)); +ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void)); + +#ifdef __cplusplus +} +#endif + +#endif /* _ZLIB_H */ diff --git a/kernel/fiasco/src/lib/gzip/zutil.c b/kernel/fiasco/src/lib/gzip/zutil.c new file mode 100644 index 00000000..6b3d050d --- /dev/null +++ b/kernel/fiasco/src/lib/gzip/zutil.c @@ -0,0 +1,228 @@ +/* zutil.c -- target dependent utility functions for the compression library + * Copyright (C) 1995-2002 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id: zutil.c 5766 2002-11-19 16:33:35Z fm3 $ */ + +#include "zutil.h" + +struct internal_state {int dummy;}; /* for buggy compilers */ + +#ifndef STDC +extern void exit OF((int)); +#endif + +const char *z_errmsg[10] = { +"need dictionary", /* Z_NEED_DICT 2 */ +"stream end", /* Z_STREAM_END 1 */ +"", /* Z_OK 0 */ +"file error", /* Z_ERRNO (-1) */ +"stream error", /* Z_STREAM_ERROR (-2) */ +"data error", /* Z_DATA_ERROR (-3) */ +"insufficient memory", /* Z_MEM_ERROR (-4) */ +"buffer error", /* Z_BUF_ERROR (-5) */ +"incompatible version",/* Z_VERSION_ERROR (-6) */ +""}; + + +const char * ZEXPORT zlibVersion() +{ + return ZLIB_VERSION; +} + +#ifdef DEBUG + +# ifndef verbose +# define verbose 0 +# endif +int z_verbose = verbose; + +void z_error (m) + char *m; +{ + fprintf(stderr, "%s\n", m); + exit(1); +} +#endif + +/* exported to allow conversion of error code to string for compress() and + * uncompress() + */ +const char * ZEXPORT zError(err) + int err; +{ + return ERR_MSG(err); +} + + +#ifndef HAVE_MEMCPY + +void zmemcpy(dest, source, len) + Bytef* dest; + const Bytef* source; + uInt len; +{ + if (len == 0) return; + do { + *dest++ = *source++; /* ??? to be unrolled */ + } while (--len != 0); +} + +int zmemcmp(s1, s2, len) + const Bytef* s1; + const Bytef* s2; + uInt len; +{ + uInt j; + + for (j = 0; j < len; j++) { + if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1; + } + return 0; +} + +void zmemzero(dest, len) + Bytef* dest; + uInt len; +{ + if (len == 0) return; + do { + *dest++ = 0; /* ??? to be unrolled */ + } while (--len != 0); +} +#endif + +#ifdef __TURBOC__ +#if (defined( __BORLANDC__) || !defined(SMALL_MEDIUM)) && !defined(__32BIT__) +/* Small and medium model in Turbo C are for now limited to near allocation + * with reduced MAX_WBITS and MAX_MEM_LEVEL + */ +# define MY_ZCALLOC + +/* Turbo C malloc() does not allow dynamic allocation of 64K bytes + * and farmalloc(64K) returns a pointer with an offset of 8, so we + * must fix the pointer. Warning: the pointer must be put back to its + * original form in order to free it, use zcfree(). + */ + +#define MAX_PTR 10 +/* 10*64K = 640K */ + +local int next_ptr = 0; + +typedef struct ptr_table_s { + voidpf org_ptr; + voidpf new_ptr; +} ptr_table; + +local ptr_table table[MAX_PTR]; +/* This table is used to remember the original form of pointers + * to large buffers (64K). Such pointers are normalized with a zero offset. + * Since MSDOS is not a preemptive multitasking OS, this table is not + * protected from concurrent access. This hack doesn't work anyway on + * a protected system like OS/2. Use Microsoft C instead. + */ + +voidpf zcalloc (voidpf opaque, unsigned items, unsigned size) +{ + voidpf buf = opaque; /* just to make some compilers happy */ + ulg bsize = (ulg)items*size; + + /* If we allocate less than 65520 bytes, we assume that farmalloc + * will return a usable pointer which doesn't have to be normalized. + */ + if (bsize < 65520L) { + buf = farmalloc(bsize); + if (*(ush*)&buf != 0) return buf; + } else { + buf = farmalloc(bsize + 16L); + } + if (buf == NULL || next_ptr >= MAX_PTR) return NULL; + table[next_ptr].org_ptr = buf; + + /* Normalize the pointer to seg:0 */ + *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4; + *(ush*)&buf = 0; + table[next_ptr++].new_ptr = buf; + return buf; +} + +void zcfree (voidpf opaque, voidpf ptr) +{ + int n; + if (*(ush*)&ptr != 0) { /* object < 64K */ + farfree(ptr); + return; + } + /* Find the original pointer */ + for (n = 0; n < next_ptr; n++) { + if (ptr != table[n].new_ptr) continue; + + farfree(table[n].org_ptr); + while (++n < next_ptr) { + table[n-1] = table[n]; + } + next_ptr--; + return; + } + ptr = opaque; /* just to make some compilers happy */ + Assert(0, "zcfree: ptr not found"); +} +#endif +#endif /* __TURBOC__ */ + + +#if defined(M_I86) && !defined(__32BIT__) +/* Microsoft C in 16-bit mode */ + +# define MY_ZCALLOC + +#if (!defined(_MSC_VER) || (_MSC_VER <= 600)) +# define _halloc halloc +# define _hfree hfree +#endif + +voidpf zcalloc (voidpf opaque, unsigned items, unsigned size) +{ + if (opaque) opaque = 0; /* to make compiler happy */ + return _halloc((long)items, size); +} + +void zcfree (voidpf opaque, voidpf ptr) +{ + if (opaque) opaque = 0; /* to make compiler happy */ + _hfree(ptr); +} + +#endif /* MSC */ + + +#ifndef MY_ZCALLOC /* Any system without a special alloc function */ + +#ifndef STDC +extern voidp calloc OF((uInt items, uInt size)); +extern void free OF((voidpf ptr)); +#endif + +void* gzip_calloc(unsigned elem, unsigned size); +void gzip_free(void *ptr); + +voidpf zcalloc (opaque, items, size) + voidpf opaque; + unsigned items; + unsigned size; +{ + if (opaque) items += size - size; /* make compiler happy */ + return (voidpf)gzip_calloc(items, size); +} + +void zcfree (opaque, ptr) + voidpf opaque; + voidpf ptr; +{ + gzip_free(ptr); + if (opaque) return; /* make compiler happy */ +} + +#endif /* MY_ZCALLOC */ diff --git a/kernel/fiasco/src/lib/gzip/zutil.h b/kernel/fiasco/src/lib/gzip/zutil.h new file mode 100644 index 00000000..1b285a67 --- /dev/null +++ b/kernel/fiasco/src/lib/gzip/zutil.h @@ -0,0 +1,221 @@ +/* zutil.h -- internal interface and configuration of the compression library + * Copyright (C) 1995-2002 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* @(#) $Id: zutil.h 5805 2002-11-21 12:33:10Z fm3 $ */ + +#ifndef _Z_UTIL_H +#define _Z_UTIL_H + +#include "my_conf.h" +#include "zlib.h" + +#ifdef STDC +# include +# include +# include +#endif +#ifdef NO_ERRNO_H + extern int errno; +#else +# include +#endif + +#ifndef local +# define local static +#endif +/* compile with -Dlocal if your debugger can't find static symbols */ + +typedef unsigned char uch; +typedef uch FAR uchf; +typedef unsigned short ush; +typedef ush FAR ushf; +typedef unsigned long ulg; + +extern const char *z_errmsg[10]; /* indexed by 2-zlib_error */ +/* (size given to avoid silly warnings with Visual C++) */ + +#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)] + +#define ERR_RETURN(strm,err) \ + return (strm->msg = (char*)ERR_MSG(err), (err)) +/* To be used only when the state is known to be valid */ + + /* common constants */ + +#ifndef DEF_WBITS +# define DEF_WBITS MAX_WBITS +#endif +/* default windowBits for decompression. MAX_WBITS is for compression only */ + +#if MAX_MEM_LEVEL >= 8 +# define DEF_MEM_LEVEL 8 +#else +# define DEF_MEM_LEVEL MAX_MEM_LEVEL +#endif +/* default memLevel */ + +#define STORED_BLOCK 0 +#define STATIC_TREES 1 +#define DYN_TREES 2 +/* The three kinds of block type */ + +#define MIN_MATCH 3 +#define MAX_MATCH 258 +/* The minimum and maximum match lengths */ + +#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */ + + /* target dependencies */ + +#ifdef MSDOS +# define OS_CODE 0x00 +# if defined(__TURBOC__) || defined(__BORLANDC__) +# if(__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__)) + /* Allow compilation with ANSI keywords only enabled */ + void _Cdecl farfree( void *block ); + void *_Cdecl farmalloc( unsigned long nbytes ); +# else +# include +# endif +# else /* MSC or DJGPP */ +# include +# endif +#endif + +#ifdef OS2 +# define OS_CODE 0x06 +#endif + +#ifdef WIN32 /* Window 95 & Windows NT */ +# define OS_CODE 0x0b +#endif + +#if defined(VAXC) || defined(VMS) +# define OS_CODE 0x02 +# define F_OPEN(name, mode) \ + fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512") +#endif + +#ifdef AMIGA +# define OS_CODE 0x01 +#endif + +#if defined(ATARI) || defined(atarist) +# define OS_CODE 0x05 +#endif + +#if defined(MACOS) || defined(TARGET_OS_MAC) +# define OS_CODE 0x07 +# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os +# include /* for fdopen */ +# else +# ifndef fdopen +# define fdopen(fd,mode) NULL /* No fdopen() */ +# endif +# endif +#endif + +#ifdef __50SERIES /* Prime/PRIMOS */ +# define OS_CODE 0x0F +#endif + +#ifdef TOPS20 +# define OS_CODE 0x0a +#endif + +#if defined(_BEOS_) || defined(RISCOS) +# define fdopen(fd,mode) NULL /* No fdopen() */ +#endif + +#if (defined(_MSC_VER) && (_MSC_VER > 600)) +# define fdopen(fd,type) _fdopen(fd,type) +#endif + + + /* Common defaults */ + +#ifndef OS_CODE +# define OS_CODE 0x03 /* assume Unix */ +#endif + +#ifndef F_OPEN +# define F_OPEN(name, mode) fopen((name), (mode)) +#endif + + /* functions */ + +#ifdef HAVE_STRERROR + extern char *strerror OF((int)); +# define zstrerror(errnum) strerror(errnum) +#else +# define zstrerror(errnum) "" +#endif + +#if defined(pyr) +# define NO_MEMCPY +#endif +#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__) + /* Use our own functions for small and medium model with MSC <= 5.0. + * You may have to use the same strategy for Borland C (untested). + * The __SC__ check is for Symantec. + */ +# define NO_MEMCPY +#endif +#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY) +# define HAVE_MEMCPY +#endif +#ifdef HAVE_MEMCPY +# ifdef SMALL_MEDIUM /* MSDOS small or medium model */ +# define zmemcpy _fmemcpy +# define zmemcmp _fmemcmp +# define zmemzero(dest, len) _fmemset(dest, 0, len) +# else +# define zmemcpy memcpy +# define zmemcmp memcmp +# define zmemzero(dest, len) memset(dest, 0, len) +# endif +#else + extern void zmemcpy OF((Bytef* dest, const Bytef* source, uInt len)); + extern int zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len)); + extern void zmemzero OF((Bytef* dest, uInt len)); +#endif + +/* Diagnostic functions */ +#ifdef DEBUG +# include + extern int z_verbose; + extern void z_error OF((char *m)); +# define Assert(cond,msg) {if(!(cond)) z_error(msg);} +# define Trace(x) {if (z_verbose>=0) fprintf x ;} +# define Tracev(x) {if (z_verbose>0) fprintf x ;} +# define Tracevv(x) {if (z_verbose>1) fprintf x ;} +# define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;} +# define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;} +#else +# define Assert(cond,msg) +# define Trace(x) +# define Tracev(x) +# define Tracevv(x) +# define Tracec(c,x) +# define Tracecv(c,x) +#endif + + +typedef uLong (ZEXPORT *check_func) OF((uLong check, const Bytef *buf, + uInt len)); +voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size)); +void zcfree OF((voidpf opaque, voidpf ptr)); + +#define ZALLOC(strm, items, size) \ + (*((strm)->zalloc))((strm)->opaque, (items), (size)) +#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr)) +#define TRY_FREE(s, p) {if (p) ZFREE(s, p);} + +#endif /* _Z_UTIL_H */ diff --git a/kernel/fiasco/src/lib/libk/amd64/atomic-amd64.cpp b/kernel/fiasco/src/lib/libk/amd64/atomic-amd64.cpp new file mode 100644 index 00000000..983ed299 --- /dev/null +++ b/kernel/fiasco/src/lib/libk/amd64/atomic-amd64.cpp @@ -0,0 +1,121 @@ +IMPLEMENTATION [amd64]: + +inline +void +atomic_mp_and(Mword *l, Mword value) +{ + asm volatile ("lock; andq %1, %2" : "=m"(*l) : "ir"(value), "m"(*l)); +} + +inline +void +atomic_mp_or(Mword *l, Mword value) +{ + asm volatile ("lock; orq %1, %2" : "=m"(*l) : "ir"(value), "m"(*l)); +} + +inline +void +atomic_mp_add (Mword *l, Mword value) +{ + asm volatile ("lock; addq %1, %2" : "=m"(*l) : "ir"(value), "m"(*l)); +} + +inline +void +atomic_add (Mword *l, Mword value) +{ + asm volatile ("addq %1, %2" : "=m"(*l) : "ir"(value), "m"(*l)); +} + +inline +void +atomic_and (Mword *l, Mword mask) +{ + asm volatile ("andq %1, %2" : "=m"(*l) : "ir"(mask), "m"(*l)); +} + +inline +void +atomic_or (Mword *l, Mword bits) +{ + asm volatile ("orq %1, %2" : "=m"(*l) : "ir"(bits), "m"(*l)); +} + +// ``unsafe'' stands for no safety according to the size of the given type. +// There are type safe versions of the cas operations in the architecture +// independent part of atomic that use the unsafe versions and make a type +// check. + +inline +bool +cas_unsafe (Mword *ptr, Mword oldval, Mword newval) +{ + Mword tmp; + + asm volatile + ("cmpxchgq %1, %2" + : "=a" (tmp) + : "r" (newval), "m" (*ptr), "a" (oldval) + : "memory"); + + return tmp == oldval; +} + +inline +bool +mp_cas_arch (Mword *ptr, Mword oldval, Mword newval) +{ + Mword tmp; + + asm volatile + ("lock; cmpxchgq %1, %2" + : "=a" (tmp) + : "r" (newval), "m" (*ptr), "a" (oldval) + : "memory"); + + return tmp == oldval; +} + +inline +bool +cas2_unsafe (Mword *ptr, Mword *oldval, Mword *newval) +{ + char ret; + asm volatile + ("cmpxchg16b %3 ; sete %%cl" + : "=c" (ret), + "=a" (* oldval), + "=d" (*(oldval+1)) + : "m" (*ptr) , + "a" (* oldval), "d" (*(oldval+1)), + "b" (* newval), "c" (*(newval+1)) + : "memory"); + + return ret; +} + +inline +bool +mp_cas2_arch (char *p, Mword o1, Mword o2, Mword n1, Mword n2) +{ + char ret; + asm volatile + ("lock; cmpxchg16b %3 ; sete %%cl" + : "=c" (ret), "=a" (o1), "=d" (o2) + : "m" (*p), "a" (o1), "d" (o2), + "b" (n1), "c" (n2) + : "memory"); + + return ret; +} + +inline +bool +tas (Mword *l) +{ + Mword tmp; + asm volatile ("xchg %0, %1" : "=r"(tmp) : "m"(*l), "0"(1) : "memory"); + return tmp; +} + diff --git a/kernel/fiasco/src/lib/libk/amd64/div32.h b/kernel/fiasco/src/lib/libk/amd64/div32.h new file mode 100644 index 00000000..e9f71473 --- /dev/null +++ b/kernel/fiasco/src/lib/libk/amd64/div32.h @@ -0,0 +1,18 @@ +#ifndef MLC_DIV32_H__ +#define MLC_DIV32_H__ + +#include "std_macros.h" + +/** return (divident / divisor) with divisor<2^32 */ +extern inline FIASCO_CONST +unsigned long long +div32(unsigned long long divident, unsigned long divisor) +{ + unsigned long long ret; + asm ("divq %3 \n\t" + : "=a"(ret) + : "a"((unsigned long)(divident)), "d"(0), "rm"(divisor)); + return ret; +} + +#endif diff --git a/kernel/fiasco/src/lib/libk/amd64/mod32.h b/kernel/fiasco/src/lib/libk/amd64/mod32.h new file mode 100644 index 00000000..6a6ab432 --- /dev/null +++ b/kernel/fiasco/src/lib/libk/amd64/mod32.h @@ -0,0 +1,21 @@ +#ifndef MLC_MOD32_H__ +#define MLC_MOD32_H__ + +#include "std_macros.h" + +/** return (divident % divisor) with divisor<2^32 */ +extern inline FIASCO_CONST +unsigned long +mod32(unsigned long long divident, unsigned long divisor) +{ + unsigned long ret, dummy; + asm ("divq %5 \n\t" + "mov %4, %%rax \n\t" + "divq %5 \n\t" + : "=d"(ret), "=a"(dummy) + : "a"((unsigned long)(divident >> 32)), "d"(0), + "irm"((unsigned long)(divident & 0xffffffff)), "rm"(divisor)); + return ret; +} + +#endif diff --git a/kernel/fiasco/src/lib/libk/arm/atomic-arm-up.cpp b/kernel/fiasco/src/lib/libk/arm/atomic-arm-up.cpp new file mode 100644 index 00000000..a0eb709a --- /dev/null +++ b/kernel/fiasco/src/lib/libk/arm/atomic-arm-up.cpp @@ -0,0 +1,83 @@ +IMPLEMENTATION [arm]: + +inline +bool +cas_unsafe( Mword *ptr, Mword oldval, Mword newval ) +{ + Mword ret; + asm volatile ( " mrs r5, cpsr \n" + " mov r6,r5 \n" + " orr r6,r6,#0x80 \n" + " msr cpsr_c, r6 \n" + " \n" + " ldr r6, [%1] \n" + " cmp r6, %2 \n" + " streq %3, [%1] \n" + " moveq %0, #1 \n" + " movne %0, #0 \n" + " msr cpsr_c, r5 \n" + : "=r"(ret) + : "r"(ptr), "r"(oldval), "r"(newval) + : "r5", "r6", "memory" + ); + return ret; +} + +inline +bool +cas2_unsafe( Mword *ptr, Mword *oldval, Mword *newval ) +{ + Mword ret; + asm volatile ( " mrs r5, cpsr \n" + " mov r6,r5 \n" + " orr r6,r6,#128 \n" + " msr cpsr_c, r6 \n" + " \n" + " ldr r6, [%1] \n" + " ldr r7, [%1,#4] \n" + " cmp r6, %2 \n" + " cmpeq r7, %3 \n" + " streq %4, [%1] \n" + " streq %5, [%1,#4] \n" + " moveq %0, #1 \n" + " movne %0, #0 \n" + " msr cpsr_c, r5 \n" + : "=r"(ret) + : "r"(ptr), "r"(*oldval), "r"(*(oldval+1)), "r"(*newval), + "r"(*(newval+1)) + : "r5", "r6", "r7", "memory" + ); + return ret; +} + +inline +bool +tas (Mword *l) +{ + Mword ret; + asm volatile ( " swp %0, %2, [%1] \n " + : "=&r"(ret) + : "r"(l), "r" (1) + : "memory" + ); + return ret; +} + +inline +void +atomic_and (Mword *l, Mword mask) +{ + Mword old; + do { old = *l; } + while ( !cas (l, old, old & mask)); +} + +inline +void +atomic_or (Mword *l, Mword bits) +{ + Mword old; + do { old = *l; } + while ( !cas (l, old, old | bits)); +} + diff --git a/kernel/fiasco/src/lib/libk/arm/div32.h b/kernel/fiasco/src/lib/libk/arm/div32.h new file mode 100644 index 00000000..7c13effe --- /dev/null +++ b/kernel/fiasco/src/lib/libk/arm/div32.h @@ -0,0 +1,14 @@ +#ifndef MLC_DIV32_H__ +#define MLC_DIV32_H__ + +#include "std_macros.h" + +/** return (divident / divisor) with divisor<2^32 */ +extern inline FIASCO_CONST +unsigned long long +div32(unsigned long long divident, unsigned long divisor) +{ + return divident/divisor; +} + +#endif diff --git a/kernel/fiasco/src/lib/libk/assert_opt.h b/kernel/fiasco/src/lib/libk/assert_opt.h new file mode 100644 index 00000000..3c4745c6 --- /dev/null +++ b/kernel/fiasco/src/lib/libk/assert_opt.h @@ -0,0 +1,13 @@ +#pragma once + +#include +#include + +#if defined(NDEBUG) && FIASCO_GCC_VERSION >= 405 +# define assert_opt(expr) do { if (!(expr)) __builtin_unreachable(); } while (0) +#else +# define assert_opt(expr) assert(expr) +#endif + + + diff --git a/kernel/fiasco/src/lib/libk/atomic.cpp b/kernel/fiasco/src/lib/libk/atomic.cpp new file mode 100644 index 00000000..1f4681ce --- /dev/null +++ b/kernel/fiasco/src/lib/libk/atomic.cpp @@ -0,0 +1,369 @@ +INTERFACE: + +#include "types.h" + +extern "C" void cas_error_type_with_bad_size_used(void); + +#define MACRO_CAS_ASSERT(rs,cs) \ + if( (rs) != (cs) ) \ + cas_error_type_with_bad_size_used() + + +template< typename A, typename B > +struct Pair +{ + A first; + B second; + + Pair() {} + Pair(A const &a, B const &b) : first(a), second(b) {} +}; + + +//--------------------------------------------------------------------------- +IMPLEMENTATION: + +template< typename Type > inline +bool +cas(Type *ptr, Type oldval, Type newval) +{ + MACRO_CAS_ASSERT(sizeof(Type),sizeof(Mword)); + return cas_unsafe(reinterpret_cast(ptr), + (Mword)oldval, (Mword)newval); +} + +template< typename Type > inline +bool +cas2(Type *ptr, Type *oldval, Type *newval) +{ + MACRO_CAS_ASSERT(sizeof(Type),(sizeof(Mword)*2)); + return cas2_unsafe(reinterpret_cast(ptr), + reinterpret_cast(oldval), + reinterpret_cast(newval)); +} + +template inline +T +atomic_change(T *ptr, T mask, T bits) +{ + T old; + do + { + old = *ptr; + } + while (!cas(ptr, old, (old & mask) | bits)); + return old; +} + +//--------------------------------------------------------------------------- +IMPLEMENTATION [ia32,ux]: + +inline +void +atomic_mp_and(Mword *l, Mword value) +{ + asm volatile ("lock; andl %1, %2" : "=m"(*l) : "ir"(value), "m"(*l)); +} + +inline +void +atomic_mp_or(Mword *l, Mword value) +{ + asm volatile ("lock; orl %1, %2" : "=m"(*l) : "ir"(value), "m"(*l)); +} + + +inline +void +atomic_mp_add(Mword *l, Mword value) +{ + asm volatile ("lock; addl %1, %2" : "=m"(*l) : "ir"(value), "m"(*l)); +} + +inline +void +atomic_add(Mword *l, Mword value) +{ + asm volatile ("addl %1, %2" : "=m"(*l) : "ir"(value), "m"(*l)); +} + +inline +void +atomic_and(Mword *l, Mword mask) +{ + asm volatile ("andl %1, %2" : "=m"(*l) : "ir"(mask), "m"(*l)); +} + +inline +void +atomic_or(Mword *l, Mword bits) +{ + asm volatile ("orl %1, %2" : "=m"(*l) : "ir"(bits), "m"(*l)); +} + +// ``unsafe'' stands for no safety according to the size of the given type. +// There are type safe versions of the cas operations in the architecture +// independent part of atomic that use the unsafe versions and make a type +// check. + +inline +bool +cas_unsafe(Mword *ptr, Mword oldval, Mword newval) +{ + Mword tmp; + + asm volatile + ("cmpxchgl %1, %2" + : "=a" (tmp) + : "r" (newval), "m" (*ptr), "a" (oldval) + : "memory"); + + return tmp == oldval; +} + + +inline +bool +mp_cas_arch(Mword *m, Mword o, Mword n) +{ + Mword tmp; + + asm volatile + ("lock; cmpxchgl %1, %2" + : "=a" (tmp) + : "r" (n), "m" (*m), "a" (o) + : "memory"); + + return tmp == o; +} + +inline +bool +cas2_unsafe(Mword *ptr, Mword *oldval, Mword *newval) +{ + char ret; + asm volatile + ("cmpxchg8b %3 ; sete %%cl" + : "=c" (ret), + "=a" (* oldval), + "=d" (*(oldval+1)) + : "m" (*ptr) , + "a" (* oldval), "d" (*(oldval+1)), + "b" (* newval), "c" (*(newval+1)) + : "memory"); + + return ret; +} + +inline +bool +mp_cas2_arch(char *m, Mword o1, Mword o2, Mword n1, Mword n2) +{ + char ret; + asm volatile + ("lock; cmpxchg8b %3 ; sete %%cl" + : "=c" (ret), "=a" (o1), "=d" (o2) + : "m" (*m), "a" (o1), "d" (o2), + "b" (n1), "c" (n2) + : "memory"); + + return ret; +} +inline +bool +tas(Mword *l) +{ + Mword tmp; + asm volatile ("xchg %0, %1" : "=r"(tmp) : "m"(*l), "0"(1) : "memory"); + return tmp; +} + +//--------------------------------------------------------------------------- +IMPLEMENTATION[(ppc32 && !mp) || (arm && !armv6plus)]: + +#include "processor.h" + +inline NEEDS["processor.h"] +void +atomic_mp_and(Mword *l, Mword value) +{ + Proc::Status s = Proc::cli_save(); + *l &= value; + Proc::sti_restore(s); +} + +inline NEEDS["processor.h"] +void +atomic_mp_or(Mword *l, Mword value) +{ + Proc::Status s = Proc::cli_save(); + *l |= value; + Proc::sti_restore(s); +} + +inline NEEDS["processor.h"] +void +atomic_mp_add(Mword *l, Mword value) +{ + Proc::Status s = Proc::cli_save(); + *l += value; + Proc::sti_restore(s); +} + +//--------------------------------------------------------------------------- +IMPLEMENTATION[arm && armv6plus]: + +inline +void +atomic_mp_add(Mword *l, Mword value) +{ + Mword tmp, ret; + + asm volatile ( + "1: \n" + "ldrex %[v], [%[mem]] \n" + "add %[v], %[v], %[addval] \n" + "strex %[ret], %[v], [%[mem]] \n" + "teq %[ret], #0 \n" + "bne 1b \n" + : [v] "=&r" (tmp), [ret] "=&r" (ret), "+m" (*l) + : [mem] "r" (l), [addval] "r" (value) + : "cc"); +} + +inline +void +atomic_mp_and(Mword *l, Mword value) +{ + Mword tmp, ret; + + asm volatile ( + "1: \n" + "ldrex %[v], [%[mem]] \n" + "and %[v], %[v], %[andval] \n" + "strex %[ret], %[v], [%[mem]] \n" + "teq %[ret], #0 \n" + "bne 1b \n" + : [v] "=&r" (tmp), [ret] "=&r" (ret), "+m" (*l) + : [mem] "r" (l), [andval] "r" (value) + : "cc"); +} + +inline +void +atomic_mp_or(Mword *l, Mword value) +{ + Mword tmp, ret; + + asm volatile ( + "1: \n" + "ldrex %[v], [%[mem]] \n" + "orr %[v], %[v], %[orval] \n" + "strex %[ret], %[v], [%[mem]] \n" + "teq %[ret], #0 \n" + "bne 1b \n" + : [v] "=&r" (tmp), [ret] "=&r" (ret), "+m" (*l) + : [mem] "r" (l), [orval] "r" (value) + : "cc"); +} + + +inline +bool +mp_cas_arch(Mword *m, Mword o, Mword n) +{ + Mword tmp, res; + + asm volatile + ("mov %[res], #1 \n" + "1: \n" + "ldr %[tmp], [%[m]] \n" + "teq %[tmp], %[o] \n" + "bne 2f \n" + "ldrex %[tmp], [%[m]] \n" + "teq %[tmp], %[o] \n" + "strexeq %[res], %[n], [%[m]] \n" + "teq %[res], #1 \n" + "beq 1b \n" + "2: \n" + : [tmp] "=&r" (tmp), [res] "=&r" (res), "+m" (*m) + : [n] "r" (n), [m] "r" (m), [o] "r" (o) + : "cc"); + + // res == 0 is ok + // res == 1 is failed + + return !res; +} + +inline +bool +mp_cas2_arch(char *m, Mword o1, Mword o2, Mword n1, Mword n2) +{ + register Mword _n1 asm("r6") = n1; + register Mword _n2 asm("r7") = n2; + register Mword tmp1 asm("r8"); + register Mword tmp2 asm("r9"); + Mword res; + + asm volatile + ("mov %[res], #1 \n" + "1: \n" + "ldrd %[tmp1], [%[m]] \n" + "teq %[tmp1], %[o1] \n" + "teqeq %[tmp2], %[o2] \n" + "bne 2f \n" + "ldrexd %[tmp1], [%[m]] \n" + "mov %[res], #1 \n" + "teq %[tmp1], %[o1] \n" + "teqeq %[tmp2], %[o2] \n" + "strexdeq %[res], %[n1], [%[m]] \n" + "teq %[res], #1 \n" + "beq 1b \n" + "2: \n" + : [tmp1] "=r" (tmp1), [tmp2] "=r" (tmp2), + [res] "=&r" (res), "+m" (*m), "+m" (*(m + 1)) + : "0" (tmp1), "1" (tmp2), + [n1] "r" (_n1), "r" (_n2), + [m] "r" (m), + [o1] "r" (o1), [o2] "r" (o2) + : "cc"); + + return !res; +} + +//--------------------------------------------------------------------------- +IMPLEMENTATION [mp]: + +template< typename T > inline +bool +mp_cas(T *m, T o, T n) +{ + MACRO_CAS_ASSERT(sizeof(T),sizeof(Mword)); + return mp_cas_arch(reinterpret_cast(m), + Mword(o), + Mword(n)); +} + +template< typename T, typename T2 > inline +bool +mp_cas2(Pair *m, T o1, T2 o2, T n1, T2 n2) +{ + MACRO_CAS_ASSERT(sizeof(T),sizeof(Mword)); + MACRO_CAS_ASSERT(sizeof(T2),sizeof(Mword)); + return mp_cas2_arch(reinterpret_cast(m), + Mword(o1), + Mword(o2), + Mword(n1), + Mword(n2)); +} + + +//--------------------------------------------------------------------------- +IMPLEMENTATION [!mp]: + +template< typename T > inline +bool +mp_cas(T *m, T o, T n) +{ return cas(m,o,n); } + diff --git a/kernel/fiasco/src/lib/libk/auto_ptr.cpp b/kernel/fiasco/src/lib/libk/auto_ptr.cpp new file mode 100644 index 00000000..d20ab3b2 --- /dev/null +++ b/kernel/fiasco/src/lib/libk/auto_ptr.cpp @@ -0,0 +1,110 @@ +INTERFACE: + +/* + * Copyright (c) 1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + */ + +#ifndef __SGI_STL_MEMORY +#define __SGI_STL_MEMORY + +// #include +// #include +// #include +// #include +// #include +// #include + +#ifndef __STL_NOTHROW +#define __STL_NOTHROW throw() +#endif + +//__STL_BEGIN_NAMESPACE + +template class auto_ptr { +private: + _Tp* _M_ptr; + +public: + typedef _Tp element_type; + explicit auto_ptr(_Tp* __p = 0) __STL_NOTHROW : _M_ptr(__p) {} + auto_ptr(auto_ptr& __a) __STL_NOTHROW : _M_ptr(__a.release()) {} + template auto_ptr(auto_ptr<_Tp1>& __a) __STL_NOTHROW + : _M_ptr(__a.release()) {} + auto_ptr& operator=(auto_ptr& __a) __STL_NOTHROW { + if (&__a != this) { + delete _M_ptr; + _M_ptr = __a.release(); + } + return *this; + } + template + auto_ptr& operator=(auto_ptr<_Tp1>& __a) __STL_NOTHROW { + if (__a.get() != this->get()) { + delete _M_ptr; + _M_ptr = __a.release(); + } + return *this; + } + ~auto_ptr() __STL_NOTHROW { delete _M_ptr; } + + _Tp& operator*() const __STL_NOTHROW { + return *_M_ptr; + } + _Tp* operator->() const __STL_NOTHROW { + return _M_ptr; + } + _Tp* get() const __STL_NOTHROW { + return _M_ptr; + } + _Tp* release() __STL_NOTHROW { + _Tp* __tmp = _M_ptr; + _M_ptr = 0; + return __tmp; + } + void reset(_Tp* __p = 0) __STL_NOTHROW { + delete _M_ptr; + _M_ptr = __p; + } + + // According to the C++ standard, these conversions are required. Most + // present-day compilers, however, do not enforce that requirement---and, + // in fact, most present-day compilers do not support the language + // features that these conversions rely on. + +//#ifdef __SGI_STL_USE_AUTO_PTR_CONVERSIONS + +private: + template struct auto_ptr_ref { + _Tp1* _M_ptr; + auto_ptr_ref(_Tp1* __p) : _M_ptr(__p) {} + }; + +public: + auto_ptr(auto_ptr_ref<_Tp> __ref) __STL_NOTHROW + : _M_ptr(__ref._M_ptr) {} + template operator auto_ptr_ref<_Tp1>() __STL_NOTHROW + { return auto_ptr_ref<_Tp>(this->release()); } + template operator auto_ptr<_Tp1>() __STL_NOTHROW + { return auto_ptr<_Tp1>(this->release()); } + +//#endif /* __SGI_STL_USE_AUTO_PTR_CONVERSIONS */ +}; + +//__STL_END_NAMESPACE + +#endif /* __SGI_STL_MEMORY */ + + +// Local Variables: +// mode:C++ +// End: diff --git a/kernel/fiasco/src/lib/libk/bitmap.cpp b/kernel/fiasco/src/lib/libk/bitmap.cpp new file mode 100644 index 00000000..b10fca77 --- /dev/null +++ b/kernel/fiasco/src/lib/libk/bitmap.cpp @@ -0,0 +1,166 @@ +INTERFACE: + +#include "atomic.h" + +template< bool LARGE > +class Bitmap_base; + +// Implementation for bitmaps bigger than sizeof(unsigned long) * 8 +// Derived classes have to make sure to provide the storage space for +// holding the bitmap. +template<> +class Bitmap_base< true > +{ +public: + void bit(unsigned long bit, bool on) + { + unsigned long idx = bit / Bpl; + unsigned long b = bit % Bpl; + _bits()[idx] = (_bits()[idx] & ~(1UL << b)) | ((unsigned long)on << b); + } + + void clear_bit(unsigned long bit) + { + unsigned long idx = bit / Bpl; + unsigned long b = bit % Bpl; + _bits()[idx] &= ~(1UL << b); + } + + void set_bit(unsigned long bit) + { + unsigned long idx = bit / Bpl; + unsigned long b = bit % Bpl; + _bits()[idx] |= (1UL << b); + } + + unsigned long operator [] (unsigned long bit) const + { + unsigned long idx = bit / Bpl; + unsigned long b = bit % Bpl; + return _bits()[idx] & (1UL << b); + } + + bool atomic_get_and_clear(unsigned long bit) + { + unsigned long idx = bit / Bpl; + unsigned long b = bit % Bpl; + unsigned long v; + do + { + v = _bits()[idx]; + } + while (!mp_cas(&_bits()[idx], v, v & ~(1UL << b))); + + return v & (1UL << b); + } + + void atomic_set_bit(unsigned long bit) + { + unsigned long idx = bit / Bpl; + unsigned long b = bit % Bpl; + atomic_mp_or(&_bits()[idx], 1UL << b); + } + + void atomic_clear_bit(unsigned long bit) + { + unsigned long idx = bit / Bpl; + unsigned long b = bit % Bpl; + atomic_mp_and(&_bits()[idx], ~(1UL << b)); + } + +protected: + enum + { + Bpl = sizeof(unsigned long) * 8, + }; + + Bitmap_base() {} + +private: + unsigned long *_bits() + { return reinterpret_cast(this); } + + unsigned long const *_bits() const + { return reinterpret_cast(this); } +}; + +// Implementation for a bitmap up to sizeof(unsigned long) * 8 bits +template<> +class Bitmap_base +{ +public: + void bit(unsigned long bit, bool on) + { + _bits[0] = (_bits[0] & ~(1UL << bit)) | ((unsigned long)on << bit); + } + + void clear_bit(unsigned long bit) + { + _bits[0] &= ~(1UL << bit); + } + + void set_bit(unsigned long bit) + { + _bits[0] |= 1UL << bit; + } + + unsigned long operator [] (unsigned long bit) const + { + return _bits[0] & (1UL << bit); + } + + bool atomic_get_and_clear(unsigned long bit) + { + unsigned long v; + do + { + v = _bits[0]; + } + while (!mp_cas(&_bits[0], v, v & ~(1UL << bit))); + + return v & (1UL << bit); + } + + void atomic_set_bit(unsigned long bit) + { + atomic_mp_or(&_bits[0], 1UL << bit); + } + + void atomic_clear_bit(unsigned long bit) + { + atomic_mp_and(&_bits[0], ~(1UL << bit)); + } + +protected: + enum + { + Bpl = sizeof(unsigned long) * 8, + }; + unsigned long _bits[1]; +}; + +template +class Bitmap : public Bitmap_base< (BITS > sizeof(unsigned long) * 8) > +{ +public: + void clear_all() + { + for (unsigned i = 0; i < Nr_elems; ++i) + _bits[i] = 0; + } + + bool is_empty() const + { + for (unsigned i = 0; i < Nr_elems; ++i) + if (_bits[i]) + return false; + return true; + } + +private: + enum { + Bpl = sizeof(unsigned long) * 8, + Nr_elems = (BITS + Bpl - 1) / Bpl, + }; + unsigned long _bits[Nr_elems]; +}; diff --git a/kernel/fiasco/src/lib/libk/bits/list_basics.h b/kernel/fiasco/src/lib/libk/bits/list_basics.h new file mode 100644 index 00000000..cfb27280 --- /dev/null +++ b/kernel/fiasco/src/lib/libk/bits/list_basics.h @@ -0,0 +1,158 @@ +/* + * (c) 2011 Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ + +#pragma once + +namespace cxx { namespace Bits { + +template< typename T > +class List_iterator_end_ptr +{ +private: + template< typename U > friend class Basic_list; + static void *_end; +}; + +template< typename T > +void *List_iterator_end_ptr::_end; + +template< typename VALUE_T, typename TYPE > +struct Basic_list_policy +{ + typedef VALUE_T *Value_type; + typedef VALUE_T const *Const_value_type; + typedef TYPE **Type; + typedef TYPE *Const_type; + typedef TYPE *Head_type; + + static Type next(Type c) { return &(*c)->_n; } + static Const_type next(Const_type c) { return c->_n; } +}; + +template< typename POLICY > +class Basic_list +{ + Basic_list(Basic_list const &) = delete; + void operator = (Basic_list const &) = delete; + +public: + typedef typename POLICY::Value_type Value_type; + typedef typename POLICY::Const_value_type Const_value_type; + + class End_iterator {}; + + class Iterator + { + private: + typedef typename POLICY::Type Internal_type; + + public: + typedef typename POLICY::Value_type value_type; + typedef typename POLICY::Value_type Value_type; + + Value_type operator * () const { return static_cast(*_c); } + Value_type operator -> () const { return static_cast(*_c); } + Iterator operator ++ () { _c = POLICY::next(_c); return *this; } + + bool operator == (End_iterator const &) const { return *_c == 0; } + bool operator != (End_iterator const &) const { return *_c != 0; } + bool operator == (Iterator const &o) const { return *_c == *o._c; } + bool operator != (Iterator const &o) const { return !operator == (o); } + + Iterator() {} + Iterator(End_iterator const &) : _c(__end()) {} + + private: + friend class Basic_list; + static Internal_type __end() + { + union X { Internal_type l; void **v; } z; + z.v = &Bits::List_iterator_end_ptr::_end; + return z.l; + } + + explicit Iterator(Internal_type i) : _c(i) {} + + Internal_type _c; + }; + + class Const_iterator + { + private: + typedef typename POLICY::Const_type Internal_type; + + public: + typedef typename POLICY::Value_type value_type; + typedef typename POLICY::Value_type Value_type; + + Value_type operator * () const { return static_cast(_c); } + Value_type operator -> () const { return static_cast(_c); } + Const_iterator operator ++ () { _c = POLICY::next(_c); return *this; } + + bool operator == (End_iterator const &) const { return _c == 0; } + bool operator != (End_iterator const &) const { return _c != 0; } + bool operator == (Const_iterator const &o) const { return _c == o._c; } + bool operator != (Const_iterator const &o) const { return !operator == (o); } + + Const_iterator() {} + Const_iterator(End_iterator const &) : _c(0) {} + Const_iterator(Iterator const &o) : _c(*o) {} + + private: + friend class Basic_list; + + explicit Const_iterator(Internal_type i) : _c(i) {} + + Internal_type _c; + }; + + // BSS allocation + explicit Basic_list(bool) {} + Basic_list() : _f(0) {} + + Basic_list(Basic_list &&o) : _f(o._f) + { + o.clear(); + } + + Basic_list &operator = (Basic_list &&o) + { + _f = o._f; + o.clear(); + return *this; + } + + bool empty() const { return !_f; } + Value_type front() const { return static_cast(_f); } + + void clear() { _f = 0; } + + Iterator begin() { return Iterator(&_f); } + Const_iterator begin() const { return Const_iterator(_f); } + static Const_iterator iter(Const_value_type c) { return Const_iterator(c); } + static End_iterator end() { return End_iterator(); } + +protected: + static typename POLICY::Type __get_internal(Iterator const &i) { return i._c; } + static Iterator __iter(typename POLICY::Type c) { return Iterator(c); } + + typename POLICY::Head_type _f; +}; + +}} + diff --git a/kernel/fiasco/src/lib/libk/cdefs.h b/kernel/fiasco/src/lib/libk/cdefs.h new file mode 100644 index 00000000..b9fc187f --- /dev/null +++ b/kernel/fiasco/src/lib/libk/cdefs.h @@ -0,0 +1,13 @@ +#ifndef __CDEFS_H__ +#define __CDEFS_H__ + +#ifndef __cplusplus +#define __BEGIN_DECLS +#define __END_DECLS +#else +#define __BEGIN_DECLS extern "C" { +#define __END_DECLS } +#endif + + +#endif // __CDEFS_H__ diff --git a/kernel/fiasco/src/lib/libk/construction.cc b/kernel/fiasco/src/lib/libk/construction.cc new file mode 100644 index 00000000..c3086fd7 --- /dev/null +++ b/kernel/fiasco/src/lib/libk/construction.cc @@ -0,0 +1,48 @@ + +#include "construction.h" +#include "types.h" + +typedef void (*ctor_t)(void); + +static int construction_done = 0; + +void run_ctor_functions(ctor_function_t *start, ctor_function_t *end) +{ + if (start < end) + { + for (;start != end; ++start) + (*start)(); + } + else + { + for (;start != end;) + { + --start; + (*start)(); + } + } +} + +void static_construction() +{ + extern ctor_function_t __INIT_ARRAY_START__[]; + extern ctor_function_t __INIT_ARRAY_END__[]; + run_ctor_functions(__INIT_ARRAY_START__, __INIT_ARRAY_END__); + + extern ctor_function_t __CTOR_END__[]; + extern ctor_function_t __CTOR_LIST__[]; + run_ctor_functions(__CTOR_LIST__, __CTOR_END__); + + construction_done = 1; +} + + +void static_destruction() +{ + if(!construction_done) + return; + + extern ctor_function_t __DTOR_END__[]; + extern ctor_function_t __DTOR_LIST__[]; + run_ctor_functions(__DTOR_LIST__, __DTOR_END__); +} diff --git a/kernel/fiasco/src/lib/libk/construction.h b/kernel/fiasco/src/lib/libk/construction.h new file mode 100644 index 00000000..d24b88b5 --- /dev/null +++ b/kernel/fiasco/src/lib/libk/construction.h @@ -0,0 +1,19 @@ +#ifndef INITFINI_H__ +#define INITFINI_H__ + +#include + +__BEGIN_DECLS + +void static_construction(void); +void static_destruction(void); + +typedef void (*ctor_function_t)(void); + +void run_ctor_functions(ctor_function_t *start, ctor_function_t *end); + +__END_DECLS + + + +#endif // INITFINI_H__ diff --git a/kernel/fiasco/src/lib/libk/dlist b/kernel/fiasco/src/lib/libk/dlist new file mode 100644 index 00000000..81a16da3 --- /dev/null +++ b/kernel/fiasco/src/lib/libk/dlist @@ -0,0 +1,270 @@ +// vi:ft=cpp +/* + * (c) 2011 Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ + +#pragma once + +namespace cxx { + +class D_list_item +{ +public: + D_list_item() : _dli_next(0) {} +private: + friend struct D_list_item_policy; + + D_list_item(D_list_item const &); + void operator = (D_list_item const &); + + D_list_item *_dli_next, *_dli_prev; +}; + +struct D_list_item_policy +{ + typedef D_list_item Item; + static D_list_item *&prev(D_list_item *e) { return e->_dli_prev; } + static D_list_item *&next(D_list_item *e) { return e->_dli_next; } +}; + +template< typename T > +struct Sd_list_head_policy +{ + typedef T *Head_type; + static T *head(Head_type h) { return h; } + static void set_head(Head_type &h, T *v) { h = v; } +}; + +template< + typename T, + typename C = D_list_item_policy +> +class D_list_cyclic +{ +protected: + template< typename VALUE, typename ITEM > + class __Iterator + { + public: + typedef VALUE *Value_type; + typedef VALUE *value_type; + + __Iterator() {} + + bool operator == (__Iterator const &o) const + { return _c == o._c; } + + bool operator != (__Iterator const &o) const + { return _c != o._c; } + + __Iterator &operator ++ () + { + _c = C::next(_c); + return *this; + } + + __Iterator &operator -- () + { + _c = C::prev(_c); + return *this; + } + + Value_type operator * () const { return static_cast(_c); } + Value_type operator -> () const { return static_cast(_c); } + + private: + friend class D_list_cyclic; + + explicit __Iterator(ITEM *s) : _c(s) {} + + ITEM *_c; + }; + +public: + typedef T *Value_type; + typedef T *value_type; + typedef __Iterator Iterator; + typedef Iterator Const_iterator; + + static void remove(T *e) + { + C::next(C::prev(e)) = C::next(e); + C::prev(C::next(e)) = C::prev(e); + C::next(e) = 0; + } + + static Iterator erase(Iterator const &e) + { + typename C::Item *n = C::next(*e); + remove(*e); + return __iter(n); + } + + static Iterator iter(T const *e) { return Iterator(const_cast(e)); } + + static bool in_list(T const *e) { return C::next(const_cast(e)); } + static bool has_sibling(T const *e) { return C::next(const_cast(e)) != e; } + + static Iterator insert_after(T *e, Iterator const &pos) + { + C::prev(e) = *pos; + C::next(e) = C::next(*pos); + C::prev(C::next(*pos)) = e; + C::next(*pos) = e; + return pos; + } + + static Iterator insert_before(T *e, Iterator const &pos) + { + C::next(e) = *pos; + C::prev(e) = C::prev(*pos); + C::next(C::prev(*pos)) = e; + C::prev(*pos) = e; + return pos; + } + + static T *self_insert(T *e) + { C::next(e) = C::prev(e) = e; return e; } + + static void remove_last(T *e) + { C::next(e) = 0; } + +protected: + static Iterator __iter(typename C::Item *e) { return Iterator(e); } +}; + +template< + typename T, + typename C = D_list_item_policy, + typename H = Sd_list_head_policy, + bool BSS = false +> +class Sd_list : public D_list_cyclic +{ +private: + typedef D_list_cyclic Base; + +public: + typedef typename Base::Iterator Iterator; + enum Pos + { Back, Front }; + + Sd_list() { if (!BSS) H::set_head(_f, 0); } + + bool empty() const { return !H::head(_f); } + T *front() const { return H::head(_f); } + + void remove(T *e) + { + T *h = H::head(_f); + if (e == C::next(e)) // must be the last + { + Base::remove_last(e); + H::set_head(_f, 0); + return; + } + + if (e == H::head(_f)) + H::set_head(_f, static_cast(C::next(h))); + + Base::remove(e); + } + + Iterator erase(Iterator const &e) + { + typename C::Item *n = C::next(*e); + remove(*e); + return __iter(n); + } + + void push(T *e, Pos pos) + { + T *h = H::head(_f); + if (!h) + H::set_head(_f, Base::self_insert(e)); + else + { + Base::insert_before(e, this->iter(h)); + if (pos == Front) + H::set_head(_f, e); + } + } + + void push_back(T *e) { push(e, Back); } + void push_front(T *e) { push(e, Front); } + void rotate_to(T *h) { H::set_head(_f, h); } + + typename H::Head_type const &head() const { return _f; } + typename H::Head_type &head() { return _f; } + +private: + Sd_list(Sd_list const &); + void operator = (Sd_list const &); + + typename H::Head_type _f; +}; + +template< + typename T, + typename C = D_list_item_policy, + bool BSS = false +> +class D_list : public D_list_cyclic +{ +private: + typedef D_list_cyclic Base; + typedef typename C::Item Internal_type; + +public: + enum Pos + { Back, Front }; + + typedef typename Base::Iterator Iterator; + typedef typename Base::Const_iterator Const_iterator; + typedef T* value_type; + typedef T* Value_type; + + D_list() { this->self_insert(static_cast(&_h)); } + + bool empty() const { return C::next(static_cast(&_h)) == &_h; } + + void remove(T *e) { Base::remove(e); } + void erase(Iterator const &e) { return Base::erase(e); } + + void push(T *e, Pos pos) + { + if (pos == Front) + Base::insert_after(e, end()); + else + Base::insert_before(e, end()); + } + + void push_back(T *e) { push(e, Back); } + void push_front(T *e) { push(e, Front); } + + Iterator begin() const { return this->__iter(C::next(const_cast(&_h))); } + Iterator end() const { return this->__iter(const_cast(&_h)); } + +private: + D_list(D_list const &); + void operator = (D_list const &); + + Internal_type _h; +}; + +} + diff --git a/kernel/fiasco/src/lib/libk/fiasco_defs.h b/kernel/fiasco/src/lib/libk/fiasco_defs.h new file mode 100644 index 00000000..ca5c25ec --- /dev/null +++ b/kernel/fiasco/src/lib/libk/fiasco_defs.h @@ -0,0 +1,12 @@ +#pragma once + +#define FIASCO_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__) + +#if FIASCO_GCC_VERSION >= 403 +# define FIASCO_COLD __attribute__((cold)) +#else +# define FIASCO_COLD +#endif + +#define FIASCO_PURE __attribute__((pure)) + diff --git a/kernel/fiasco/src/lib/libk/gcc_lib.c b/kernel/fiasco/src/lib/libk/gcc_lib.c new file mode 100644 index 00000000..924cc82a --- /dev/null +++ b/kernel/fiasco/src/lib/libk/gcc_lib.c @@ -0,0 +1,54 @@ + +unsigned long long __umoddi3(unsigned long long, unsigned long long); +unsigned long long __udivdi3(unsigned long long, unsigned long long); + +struct llmoddiv_t +{ + unsigned long long div; + unsigned long long mod; +}; + +struct llmoddiv_t llmoddiv(unsigned long long div, unsigned long long s) +{ + unsigned long long i; + unsigned long long tmp; + + if (s == 0) + return (struct llmoddiv_t){.div = 0, .mod = 0}; + + if (s > div) + return (struct llmoddiv_t){.div = 0, .mod = div}; + + tmp = 1; + while (!(s & (1ULL<<63)) && s < div) + { + s <<= 1; + tmp <<= 1; + } + + i = 0; + + while (1) + { + if (div >= s) + { + div -= s; + i |= tmp; + } + if (div == 0) + break; + tmp >>= 1; + if (!tmp) + break; + s >>= 1; + } + + return (struct llmoddiv_t){.div = i, .mod = div}; +} + + +unsigned long long __umoddi3(unsigned long long div, unsigned long long s) +{ return llmoddiv(div,s).mod; } + +unsigned long long __udivdi3(unsigned long long div, unsigned long long s) +{ return llmoddiv(div,s).div; } diff --git a/kernel/fiasco/src/lib/libk/hlist b/kernel/fiasco/src/lib/libk/hlist new file mode 100644 index 00000000..187eb1c6 --- /dev/null +++ b/kernel/fiasco/src/lib/libk/hlist @@ -0,0 +1,137 @@ +// vi:ft=cpp +/* + * (c) 2011 Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ + +#pragma once + +#include "bits/list_basics.h" + +namespace cxx { + +class H_list_item +{ +public: + H_list_item() : _pn(0) {} + ~H_list_item() { l_remove(); } + +private: + H_list_item(H_list_item const &); + void operator = (H_list_item const &); + + template friend class H_list; + template friend struct Bits::Basic_list_policy; + + void l_remove() + { + if (!_pn) + return; + + *_pn = _n; + if (_n) + _n->_pn = _pn; + + _pn = 0; + } + + H_list_item *_n, **_pn; +}; + +template< typename T, typename POLICY = Bits::Basic_list_policy< T, H_list_item > > +class H_list : public Bits::Basic_list +{ +private: + typedef Bits::Basic_list Base; + H_list(H_list const &); + void operator = (H_list const &); + +public: + typedef typename Base::Iterator Iterator; + + // BSS allocation + explicit H_list(bool x) : Base(x) {} + H_list() : Base() {} + + static Iterator iter(T *c) { return Base::__iter(c->_pn); } + + static bool in_list(T const *e) { return e->_pn; } + + void add(T *e) + { + if (this->_f) + this->_f->_pn = &e->_n; + e->_n = this->_f; + e->_pn = &this->_f; + this->_f = e; + } + + void push_front(T *e) { add(e); } + + void insert(T *e, Iterator const &pred) + { + H_list_item **x = &this->_f; + if (pred != Base::end()) + x = &(*pred)->_n; + + e->_n = *x; + + if (*x) + (*x)->_pn = &(e->_n); + + e->_pn = x; + *x = e; + } + + static void insert_before(T *e, Iterator const &succ) + { + H_list_item **x = Base::__get_internal(succ); + + e->_n = *x; + e->_pn = x; + + if (*x) + (*x)->_pn = &e->_n; + + *x = e; + } + + static void replace(T *p, T *e) + { + e->_n = p->_n; + e->_pn = p->_pn; + *(p->_pn) = e; + if (e->_n) + e->_n->_pn = &(e->_n); + + p->_pn = 0; + } + + static void remove(T *e) + { e->H_list_item::l_remove(); } + + static Iterator erase(Iterator const &e) + { e->H_list_item::l_remove(); return e; } +}; + +template< typename T > +class H_list_bss : public H_list +{ +public: + H_list_bss() : H_list(true) {} +}; + +} diff --git a/kernel/fiasco/src/lib/libk/ia32/atomic-ia32-smp.cpp b/kernel/fiasco/src/lib/libk/ia32/atomic-ia32-smp.cpp new file mode 100644 index 00000000..20b5a56b --- /dev/null +++ b/kernel/fiasco/src/lib/libk/ia32/atomic-ia32-smp.cpp @@ -0,0 +1,77 @@ +IMPLEMENTATION [ia32]: + +// ``unsafe'' stands for no safety according to the size of the given type. +// There are type safe versions of the cas operations in the architecture +// independent part of atomic that use the unsafe versions and make a type +// check. + +inline +bool +cas_unsafe (Mword *ptr, Mword oldval, Mword newval) +{ + Mword tmp; + + asm volatile + ("lock; cmpxchgl %1,%2" + : "=a" (tmp) + : "r" (newval), "m" (*ptr), "0" (oldval) + : "memory"); + + return tmp == oldval; +} + +inline +bool +cas2_unsafe (Mword *ptr, Mword *oldval, Mword *newval) +{ + char ret; + asm volatile + ("lock; cmpxchg8b %3 ; sete %%cl" + : "=c" (ret), + "=a" (* oldval), + "=d" (*(oldval+1)) + : "m" (*ptr) , + "1" (* oldval), + "2" (*(oldval+1)), + "b" (* newval), + "0" (*(newval+1)) + : "memory"); + + return ret; +} + +inline +bool +tas (Mword *l) +{ + Mword tmp; + asm volatile + ("xchg %0,%1" : "=r" (tmp) : "m" (*l), "0" (1) : "memory"); + + return tmp; +} + +template inline +atomic_and (Mword *l, Mword bits) +{ + T old; + do { old = *p; } + while (!cas (p, old, old & value)); +} + +template inline +atomic_or (Mword *l, Mword bits) +{ + T old; + do { old = *p; } + while (!cas (p, old, old | value)); +} + +template inline +void atomic_change(T *p, T mask, T bits) +{ + T old; + do { old = *p; } + while (!cas (p, old, (old & mask) | bits)); +} + diff --git a/kernel/fiasco/src/lib/libk/ia32/div32.h b/kernel/fiasco/src/lib/libk/ia32/div32.h new file mode 100644 index 00000000..d4b38088 --- /dev/null +++ b/kernel/fiasco/src/lib/libk/ia32/div32.h @@ -0,0 +1,23 @@ +#ifndef MLC_DIV32_H__ +#define MLC_DIV32_H__ + +#include "std_macros.h" + +/** return (divident / divisor) with divisor<2^32 */ +extern inline FIASCO_CONST +unsigned long long +div32(unsigned long long divident, unsigned long divisor) +{ + unsigned long long ret; + unsigned long dummy; + asm ("divl %5 \n\t" + "xchg %%eax, %4 \n\t" + "divl %5 \n\t" + "movl %4, %%edx \n\t" + : "=A"(ret), "=r"(dummy) + : "a"((unsigned long)(divident >> 32)), "d"(0), + "1"((unsigned long)(divident & 0xffffffff)), "rm"(divisor)); + return ret; +} + +#endif diff --git a/kernel/fiasco/src/lib/libk/ia32/mod32.h b/kernel/fiasco/src/lib/libk/ia32/mod32.h new file mode 100644 index 00000000..12610711 --- /dev/null +++ b/kernel/fiasco/src/lib/libk/ia32/mod32.h @@ -0,0 +1,21 @@ +#ifndef MLC_MOD32_H__ +#define MLC_MOD32_H__ + +#include "std_macros.h" + +/** return (divident % divisor) with divisor<2^32 */ +extern inline FIASCO_CONST +unsigned long +mod32(unsigned long long divident, unsigned long divisor) +{ + unsigned long ret, dummy; + asm ("divl %5 \n\t" + "movl %4, %%eax \n\t" + "divl %5 \n\t" + : "=d"(ret), "=a"(dummy) + : "a"((unsigned long)(divident >> 32)), "d"(0), + "irm"((unsigned long)(divident & 0xffffffff)), "rm"(divisor)); + return ret; +} + +#endif diff --git a/kernel/fiasco/src/lib/libk/ia32/unistd.cpp b/kernel/fiasco/src/lib/libk/ia32/unistd.cpp new file mode 100644 index 00000000..6c7c92dc --- /dev/null +++ b/kernel/fiasco/src/lib/libk/ia32/unistd.cpp @@ -0,0 +1,97 @@ +// Simplistic Unix interface for use by lib/gmon.cpp. We support file +// I/O (translated into uuencoded output), sbrk()-like memory +// allocation, and profile() (setting parameters for profiling). + +INTERFACE: + +#include "types.h" +#include + +extern char *pr_base; +extern Address pr_off; +extern size_t pr_size; +extern size_t pr_scale; + +IMPLEMENTATION: + +#include +#include +#include +#include +#include +#include + +#include "kmem_alloc.h" +#include "config.h" +#include "kernel_console.h" + +int +creat(const char* fname, int) +{ + printf("starting to output: %s.uu -- hit Return\n", fname); +// Kconsole::console()->getchar(); + Kconsole::console()->start_exclusive(Console::GZIP); + + return 6; +} + +void +perror(const char *s) +{ + panic (s); +} + +/*ssize_t*/ size_t +write(int, const char *buf, size_t size) +{ + for (size_t i=0; iend_exclusive(Console::GZIP); + + return 0; +} + +void * +sbrk(size_t size) +{ + void *ret = Kmem_alloc::allocator() + ->unaligned_alloc((size+Config::PAGE_SIZE-1) & ~(Config::PAGE_SIZE-1)); + if (ret == 0) + ret = (void*)-1; + else + memset(ret, 0, size); + + return ret; +} + +void +sbrk_free(void* buf, size_t size) +{ + Kmem_alloc::allocator() + ->unaligned_free((size+Config::PAGE_SIZE-1)/Config::PAGE_SIZE, buf); +} + +char *pr_base; +Address pr_off; +size_t pr_size; +size_t pr_scale; + +int +profil(char *samples, size_t size, Address offset, size_t scale) +{ + pr_base = samples; + pr_size = size; + pr_off = offset; + pr_scale = scale; + + return 0; +} diff --git a/kernel/fiasco/src/lib/libk/lock_guard.cpp b/kernel/fiasco/src/lib/libk/lock_guard.cpp new file mode 100644 index 00000000..4628e5ab --- /dev/null +++ b/kernel/fiasco/src/lib/libk/lock_guard.cpp @@ -0,0 +1,184 @@ +INTERFACE: +#include + +// +// Regular lock-guard policy, lock on ctor, unlock/reset in dtor +// +template< typename LOCK > +struct Lock_guard_regular_policy +{ + typedef typename LOCK::Status Status; + static Status test_and_set(LOCK *l) { return l->test_and_set(); } + static void set(LOCK *l, Status s) { l->set(s); } +}; + +// +// Inverse lock-guard policy, unlock in ctor, lock in dtor +// NOTE: this is applicable only to some locks (e.g., the cpu lock) +// +template +struct Lock_guard_inverse_policy : private LOCK +{ + typedef typename LOCK::Status Status; + static Status test_and_set(LOCK *l) { l->clear(); return LOCK::Locked; } + static void set(LOCK *l, Status s) { l->set(s); } +}; + + +// +// Lock_guard: a guard object using a lock such as helping_lock_t +// +template< + typename LOCK, + template< typename L > class POLICY = Lock_guard_regular_policy > +class Lock_guard +{ + typedef typename cxx::remove_pointer::type>::type Lock; + typedef POLICY Policy; + + Lock *_lock; + typename Policy::Status _state; +}; + +template< typename LOCK> +class Lock_guard_2 +{ + LOCK *_l1, *_l2; + typename LOCK::Status _state1, _state2; +}; + +IMPLEMENTATION: + +PUBLIC template class POLICY> +inline +Lock_guard::Lock_guard() + : _lock(0) +#ifndef NDEBUG + , _state(Lock::Invalid) // silence GCC warning +#endif +{} + +PUBLIC template class POLICY> +inline +Lock_guard::Lock_guard(Lock *l) + : _lock(l) +{ + _state = Policy::test_and_set(_lock); +} + +PUBLIC template class POLICY> +inline +void +Lock_guard::lock(Lock *l) +{ + _lock = l; + _state = Policy::test_and_set(l); +} + +PUBLIC template class POLICY> +inline +bool +Lock_guard::try_lock(Lock *l) +{ + _state = Policy::test_and_set(l); + switch (_state) + { + case Lock::Locked: + return true; + case Lock::Not_locked: + _lock = l; // Was not locked -- unlock. + return true; + default: + return false; // Error case -- lock not existent + } +} + +PUBLIC template class POLICY> +inline +void +Lock_guard::release() +{ + _lock = 0; +} + +PUBLIC template class POLICY> +inline +void +Lock_guard::reset() +{ + if (_lock) + { + Policy::set(_lock, _state); + _lock = 0; + } +} + +PUBLIC template class POLICY> +inline +Lock_guard::~Lock_guard() +{ + if (_lock) + Policy::set(_lock, _state); +} + +PUBLIC template class POLICY> +inline +bool +Lock_guard::was_set(void) +{ + return _state; //!_lock; +} + +PUBLIC template +inline +Lock_guard_2::Lock_guard_2() + : _l1(0), _l2(0) +{} + +PUBLIC template +inline +Lock_guard_2::Lock_guard_2(LOCK *l1, LOCK *l2) + : _l1(l1 < l2 ? l1 : l2), _l2(l1 < l2 ? l2 : l1) +{ + _state1 = _l1->test_and_set(); + if (_l1 == _l2) + _l2 = 0; + else + _state2 = _l2->test_and_set(); +} + + +PUBLIC template +inline +bool +Lock_guard_2::lock(LOCK *l1, LOCK *l2) +{ + _l1 = l1 < l2 ? l1 : l2; + _l2 = l1 < l2 ? l2 : l1; + if ((_state1 = _l1->test_and_set()) == LOCK::Invalid) + { + _l1 = _l2 = 0; + return false; + } + + if (_l1 == _l2) + _l2 = 0; + else if ((_state2 = _l2->test_and_set()) == LOCK::Invalid) + { + _l2 = 0; + return false; + } + + return true; +} + +PUBLIC template +inline +Lock_guard_2::~Lock_guard_2() +{ + if (_l2) + _l2->set(_state2); + + if (_l1) + _l1->set(_state1); +} diff --git a/kernel/fiasco/src/lib/libk/mem_region.cpp b/kernel/fiasco/src/lib/libk/mem_region.cpp new file mode 100644 index 00000000..910051c7 --- /dev/null +++ b/kernel/fiasco/src/lib/libk/mem_region.cpp @@ -0,0 +1,166 @@ +INTERFACE: + +class Mem_region +{ +public: + unsigned long start, end; + + Mem_region() : start(0), end(0) {} + + Mem_region(unsigned long start, unsigned long end) : start(start), end(end) {} + + bool valid() const { return start < end; } + + bool operator < (Mem_region const &o) const + { return end < o.start; } + + bool overlaps(Mem_region const &o) const + { return !(o < *this || *this < o); } + + bool contains(Mem_region const &o) const + { return start <= o.start && end >= o.end; } + + void merge(Mem_region const &r) + { + start = start < r.start ? start : r.start; + end = end > r.end ? end : r.end; + } + + unsigned long size() const + { return end - start + 1; } + +}; + + +class Mem_region_map_base +{ +private: + unsigned _s; + unsigned _l; + Mem_region _r[0]; + +public: + Mem_region_map_base(unsigned size) : _s(size), _l(0) {} +}; + +template< unsigned E > +class Mem_region_map : public Mem_region_map_base +{ +public: + enum { Entries = E }; + Mem_region_map() : Mem_region_map_base(Entries) {} + +private: + Mem_region _r[Entries]; +}; + + +//-------------------------------------------------------------------------- +IMPLEMENTATION: + +PRIVATE inline +void +Mem_region_map_base::del(unsigned start, unsigned end) +{ + register unsigned delta = end - start; + for (unsigned p = start; p < end; ++p) + _r[p] = _r[p + delta]; + + _l -= delta; +} + +PUBLIC inline NEEDS[Mem_region_map_base::del] +bool +Mem_region_map_base::add(Mem_region const &r) +{ + if (!r.valid()) + return true; + + unsigned pos = 0; + for (;pos < _l && _r[pos] < r; ++pos) ; + if (_l > pos && !(r < _r[pos])) + { // overlap -> merge + _r[pos].merge(r); + for (unsigned p = pos + 1; p < _l; ++p) + { + if (!(_r[pos] < _r[p])) + _r[pos].merge(_r[p]); + else + { + del(pos + 1, p); + return true; + } + } + _l = pos + 1; + return true; + } + + if (_l >= _s) + return false; + + for (unsigned p = _l; p > pos; --p) _r[p] = _r[p-1]; + ++_l; + _r[pos] = r; + return true; +} + + +PUBLIC inline NEEDS[Mem_region_map_base::del] +bool +Mem_region_map_base::sub(Mem_region const &r) +{ + if (!r.valid()) + return true; + + unsigned pos; + for (pos = 0; pos < _l; ++pos) + { + if (_r[pos].overlaps(r)) + { + if (r.contains(_r[pos])) + { + del(pos, pos+1); + --pos; // ensure we do not skip the next element + } + else if (r.start <= _r[pos].start) + _r[pos].start = r.end + 1; + else if (r.end >= _r[pos].end) + _r[pos].end = r.start - 1; + else + { + if (_l >= _s) + return false; + + for (unsigned p = _l; p > pos; --p) _r[p] = _r[p-1]; + ++_l; + _r[pos+1].start = r.end + 1; + _r[pos+1].end = _r[pos].end; + _r[pos].end = r.start - 1; + } + } + } + return true; +} + + +PUBLIC inline +unsigned +Mem_region_map_base::length() const +{ return _l; } + + +PUBLIC inline +unsigned +Mem_region_map_base::capacity() const +{ return _s; } + +PUBLIC inline +Mem_region const & +Mem_region_map_base::operator [] (unsigned idx) const +{ return _r[idx]; } + +PUBLIC inline +Mem_region & +Mem_region_map_base::operator [] (unsigned idx) +{ return _r[idx]; } + diff --git a/kernel/fiasco/src/lib/libk/minmax.h b/kernel/fiasco/src/lib/libk/minmax.h new file mode 100644 index 00000000..166a6ec4 --- /dev/null +++ b/kernel/fiasco/src/lib/libk/minmax.h @@ -0,0 +1,14 @@ +#pragma once + +/** @brief Equivalent to std::min. */ +template +const T& +min(const T& a, const T& b) +{ return (a < b) ? a : b; } + +/** @brief Equivalent to std::max. */ +template +const T& +max(const T& a, const T& b) +{ return (a > b) ? a : b; } + diff --git a/kernel/fiasco/src/lib/libk/new b/kernel/fiasco/src/lib/libk/new new file mode 100644 index 00000000..5898d97d --- /dev/null +++ b/kernel/fiasco/src/lib/libk/new @@ -0,0 +1,9 @@ +// vi: ft=cpp + +#pragma once + +#include + +inline void *operator new (size_t, void *p) throw() { return p; } +inline void *operator new [] (size_t, void *p) throw() { return p; } + diff --git a/kernel/fiasco/src/lib/libk/ppc32/atomic-ppc32.cpp b/kernel/fiasco/src/lib/libk/ppc32/atomic-ppc32.cpp new file mode 100644 index 00000000..60643dc6 --- /dev/null +++ b/kernel/fiasco/src/lib/libk/ppc32/atomic-ppc32.cpp @@ -0,0 +1,57 @@ +IMPLEMENTATION [ppc32]: + +#include + +inline +bool +cas_unsafe( Mword *ptr, Mword oldval, Mword newval ) +{ + Mword ret = 0; + + asm volatile ( "1: \n" + " lwarx %%r6, 0, %[ptr] \n" + " cmpw %[oldval], %%r6 \n" + " bne- 2f \n" + " stwcx. %[newval], 0,%[ptr] \n" + " bne- 1b \n" + "2: \n" + " mr %[ret], %%r6 \n" + : [ret] "=r"(ret), + [ptr] "=r"(ptr), + [oldval] "=r"(oldval), + [newval] "=r"(newval) + : "0" (ret), + "1" (ptr), + "2" (oldval), + "3" (newval) + : "memory", "r6" + ); + + return ret == oldval; +} + +/* dummy implement */ +bool +cas2_unsafe( Mword *, Mword *, Mword *) +{ + panic("%s not implemented", __func__); + return false; +} + +inline +void +atomic_and (Mword *l, Mword mask) +{ + Mword old; + do { old = *l; } + while ( !cas (l, old, old & mask)); +} + +inline +void +atomic_or (Mword *l, Mword bits) +{ + Mword old; + do { old = *l; } + while ( !cas (l, old, old | bits)); +} diff --git a/kernel/fiasco/src/lib/libk/ppc32/div32.h b/kernel/fiasco/src/lib/libk/ppc32/div32.h new file mode 100644 index 00000000..7c13effe --- /dev/null +++ b/kernel/fiasco/src/lib/libk/ppc32/div32.h @@ -0,0 +1,14 @@ +#ifndef MLC_DIV32_H__ +#define MLC_DIV32_H__ + +#include "std_macros.h" + +/** return (divident / divisor) with divisor<2^32 */ +extern inline FIASCO_CONST +unsigned long long +div32(unsigned long long divident, unsigned long divisor) +{ + return divident/divisor; +} + +#endif diff --git a/kernel/fiasco/src/lib/libk/slab_cache.cpp b/kernel/fiasco/src/lib/libk/slab_cache.cpp new file mode 100644 index 00000000..065b073d --- /dev/null +++ b/kernel/fiasco/src/lib/libk/slab_cache.cpp @@ -0,0 +1,440 @@ +INTERFACE: + +#include +#include +#include +#include + +// The anonymous slab allocator. You can specialize this allocator by +// providing your own initialization functions and your own low-level +// allocation functions. + +class Slab : public cxx::H_list_item +{ +private: + Slab(const Slab&); // copy constructors remain undefined + + typedef cxx::S_list_item Slab_entry; + typedef cxx::S_list Free_list; + + Free_list _free; + unsigned short _elems; + unsigned short _in_use; +}; + +class Slab_cache +{ +protected: + friend class Slab; + + // Low-level allocator functions: + + // Allocate/free a block. "size" is always a multiple of PAGE_SIZE. + virtual void *block_alloc(unsigned long size, unsigned long alignment) = 0; + virtual void block_free(void *block, unsigned long size) = 0; + +private: + Slab_cache(); + Slab_cache(const Slab_cache&); // default constructor is undefined + + // + // data declaration follows + // + + typedef cxx::H_list Slab_list; + Slab_list _full; ///< List of full slabs + Slab_list _partial; ///< List of partially filled slabs + Slab_list _empty; ///< List of empty slabs + + + unsigned long _slab_size; + unsigned _entry_size, _elem_num; + unsigned _num_empty; + typedef Spin_lock<> Lock; + Lock lock; + char const *_name; +}; + + +IMPLEMENTATION: + +#include +#include +#include +#include + +// default deallocator must not be called -- must use explicit destruction +inline NOEXPORT +void +Slab::operator delete(void* /*block*/) +{ + assert (!"slab::operator delete called"); +} + +PUBLIC +Slab::Slab(unsigned elems, unsigned entry_size, void *mem) +: _elems(elems), _in_use(0) +{ + // Compute pointer to first data element, now taking into account + // the latest colorization offset + char *data = reinterpret_cast(mem); + + // Initialize the cache elements + for (unsigned i = elems; i > 0; --i) + { + Slab_entry *e = reinterpret_cast(data); + _free.push_front(e); + data += entry_size; + } +} + +PUBLIC +void * +Slab::alloc() +{ + Slab_entry *e = _free.pop_front(); + + if (! e) + return 0; + + ++_in_use; + return e; +} + +PUBLIC +void +Slab::free(void *entry) +{ + _free.add(reinterpret_cast(entry)); + + assert(_in_use); + --_in_use; +} + +PUBLIC +inline bool +Slab::is_empty() const +{ + return _in_use == 0; +} + +PUBLIC +inline bool +Slab::is_full() const +{ + return _in_use == _elems; +} + +PUBLIC +inline unsigned +Slab::in_use() const +{ + return _in_use; +} + +PUBLIC +inline void * +Slab::operator new(size_t, void *block) throw() +{ + // slabs must be size-aligned so that we can compute their addresses + // from element addresses + return block; +} + + +PUBLIC static inline +unsigned +Slab_cache::entry_size(unsigned elem_size, unsigned alignment) +{ return (elem_size + alignment - 1) & ~(alignment - 1); } + +// +// Slab_cache +// +PUBLIC inline NEEDS[Slab_cache::entry_size] +Slab_cache::Slab_cache(unsigned elem_size, + unsigned alignment, + char const * name, + unsigned long min_size, + unsigned long max_size) + : _entry_size(entry_size(elem_size, alignment)), _num_empty(0), + _name (name) +{ + lock.init(); + + for ( + _slab_size = min_size; + (_slab_size - sizeof(Slab)) / _entry_size < 8 + && _slab_size < max_size; + _slab_size <<= 1) ; + + _elem_num = (_slab_size - sizeof(Slab)) / _entry_size; +} + +// +// Slab_cache +// +PUBLIC inline +Slab_cache::Slab_cache(unsigned long slab_size, + unsigned elem_size, + unsigned alignment, + char const * name) + : _slab_size(slab_size), _entry_size(entry_size(elem_size, alignment)), + _num_empty(0), _name (name) +{ + lock.init(); + _elem_num = (_slab_size - sizeof(Slab)) / _entry_size; +} + +PUBLIC +virtual +Slab_cache::~Slab_cache() +{ + // the derived class should call destroy() before deleting us. + // assert(_first_slab == 0); +} + +PROTECTED inline +void +Slab_cache::destroy() // descendant should call this in destructor +{ +} + +PRIVATE inline NOEXPORT +Slab * +Slab_cache::get_available_locked() +{ + Slab *s = _partial.front(); + if (s) + return s; + + s = _empty.front(); + if (s) + { + --_num_empty; + _empty.remove(s); + _partial.add(s); + } + + return s; +} + +PUBLIC +void * +Slab_cache::alloc() // request initialized member from cache +{ + void *unused_block = 0; + void *ret; + { + Lock_guard guard(&lock); + + Slab *s = get_available_locked(); + + if (EXPECT_FALSE(!s)) + { + guard.reset(); + + char *m = (char*)block_alloc(_slab_size, _slab_size); + Slab *new_slab = 0; + if (m) + new_slab = new (m + _slab_size - sizeof(Slab)) Slab(_elem_num, _entry_size, m); + + guard.lock(&lock); + + // retry gettin a slab that might be allocated by a different + // CPU meanwhile + s = get_available_locked(); + + if (!s) + { + // real OOM + if (!m) + return 0; + + _partial.add(new_slab); + s = new_slab; + } + else + unused_block = m; + } + + ret = s->alloc(); + assert(ret); + + if (s->is_full()) + { + cxx::H_list::remove(s); + _full.add(s); + } + } + + if (unused_block) + block_free(unused_block, _slab_size); + + return ret; +} + +PUBLIC template< typename Q > +inline +void * +Slab_cache::q_alloc(Q *quota) +{ + Auto_quota q(quota, _entry_size); + if (EXPECT_FALSE(!q)) + return 0; + + void *r; + if (EXPECT_FALSE(!(r=alloc()))) + return 0; + + q.release(); + return r; +} + +PUBLIC +void +Slab_cache::free(void *cache_entry) // return initialized member to cache +{ + Slab *to_free = 0; + { + Lock_guard guard(&lock); + + Slab *s = reinterpret_cast + ((reinterpret_cast(cache_entry) & ~(_slab_size - 1)) + _slab_size - sizeof(Slab)); + + bool was_full = s->is_full(); + + s->free(cache_entry); + + if (was_full) + { + cxx::H_list::remove(s); + _partial.add(s); + } + else if (s->is_empty()) + { + cxx::H_list::remove(s); + if (_num_empty < 2) + { + _empty.add(s); + ++_num_empty; + } + else + to_free = s; + } + else + { + // We weren't either full or empty; we already had free + // elements. This changes nothing in the queue, and there + // already must have been a _first_available_slab. + } + } + + if (to_free) + { + to_free->~Slab(); + block_free(reinterpret_cast(to_free + 1) - _slab_size, _slab_size); + } +} + +PUBLIC template< typename Q > +inline +void +Slab_cache::q_free(Q *quota, void *obj) +{ + free(obj); + quota->free(_entry_size); +} + +PUBLIC +unsigned long +Slab_cache::reap() // request that cache returns memory to system +{ + Slab *s = 0; + unsigned long sz = 0; + + for (;;) + { + { + Lock_guard guard(&lock); + + s = _empty.front(); + // nothing to free + if (!s) + return 0; + + cxx::H_list::remove(s); + } + + // explicitly call destructor to delete s; + s->~Slab(); + block_free(reinterpret_cast(s + 1) - _slab_size, _slab_size); + sz += _slab_size; + } + + return sz; +} + +// Debugging output + +#include + + +PUBLIC +void +Slab_cache::debug_dump() +{ + printf ("%s: %lu-KB slabs (elems per slab=%d ", + _name, _slab_size / 1024, _elem_num); + + unsigned count = 0, total = 0, total_elems = 0; + for (Slab_list::Const_iterator s = _full.begin(); s != _full.end(); ++s) + { + if (!s->is_full()) + printf ("\n*** wrongly-enqueued full slab found\n"); + + ++count; + total_elems += s->in_use(); + } + + total += count; + + printf ("%u full, ", count); + + count = 0; + for (Slab_list::Const_iterator s = _partial.begin(); s != _partial.end(); ++s) + { + if (s->is_full() || s->is_empty()) + printf ("\n*** wrongly-enqueued full slab found\n"); + + count++; + total_elems += s->in_use(); + } + + total += count; + + printf ("%u used, ", count); + + count = 0; + for (Slab_list::Const_iterator s = _empty.begin(); s != _empty.end(); ++s) + { + if (! s->is_empty()) + printf ("\n*** wrongly-enqueued nonempty slab found\n"); + count++; + } + + unsigned total_used = total; + total += count; + + printf ("%u empty = %u total) = %lu KB,\n %u elems (size=%u)", + count, total, total * _slab_size / 1024, + total_elems, _entry_size); + + if (total_elems) + printf (", overhead = %lu B (%lu B) = %lu%% (%lu%%) \n", + total * _slab_size - total_elems * _entry_size, + total_used * _slab_size - total_elems * _entry_size, + 100 - total_elems * _entry_size * 100 / (total * _slab_size), + 100 - total_elems * _entry_size * 100 / (total_used * _slab_size)); + else + printf ("\n"); +} diff --git a/kernel/fiasco/src/lib/libk/slab_cache_anon-old.cpp b/kernel/fiasco/src/lib/libk/slab_cache_anon-old.cpp new file mode 100644 index 00000000..e7d75f95 --- /dev/null +++ b/kernel/fiasco/src/lib/libk/slab_cache_anon-old.cpp @@ -0,0 +1,612 @@ +INTERFACE: + +#include + +// The anonymous slab allocator. You can specialize this allocator by +// providing your own initialization functions and your own low-level +// allocation functions. + +class slab; + +class slab_cache_anon +{ +protected: + friend class slab; + + // Low-level allocator functions: + + // Allocate/free a block. "size" is always a multiple of PAGE_SIZE. + virtual void *block_alloc(unsigned long size, unsigned long alignment) = 0; + virtual void block_free(void *block, unsigned long size) = 0; + +private: + typedef Spin_lock Lock; + + Lock lock; + slab_cache_anon(); + slab_cache_anon(const slab_cache_anon&); // default constructor is undefined + + // + // data declaration follows + // + + // The slabs of this cache are held in a partially-sorted + // doubly-linked list. First come the fully-active slabs (all + // elements in use), then the partially active slabs, then empty + // slabs. + slab *_first_slab, *_first_available_slab, *_last_slab; + unsigned long _slab_size; + unsigned _elem_size, _latest_offset, _alignment; + char const *_name; +}; // end declaration of class slab_cache + +IMPLEMENTATION: + +#include +#include +#include +#include + +#ifndef offsetof // should be defined in stddef.h, but isn't +#define offsetof(TYPE, MEMBER) (((size_t) &((TYPE *)10)->MEMBER) - 10) +#endif + +// +// class slab +// + +class slab // a slab of the cache +{ + slab(); + slab(const slab&); // default constructors remain undefined + + struct slab_entry + { + slab_entry *_next_free; + char _entry[0]; + }; + + struct slab_data + { + slab_cache_anon *_cache; + slab_entry *_first_free; + slab *_next, *_prev; + unsigned short _in_use, _free; + }; + + // slabs for CACHE_ENTRY should contain at least min_cache_items + // cache entries + static const unsigned min_cache_items = 4; + + // + // data declaration follows + // + slab_data _data; +}; // end declaration of class slab + +// +// class slab +//- + +// default deallocator must not be called -- must use explicit destruction +inline NOEXPORT +void +slab::operator delete(void* /*block*/) +{ + assert (!"slab::operator delete called"); +} + + +PUBLIC +slab::slab(slab_cache_anon *cache) +{ + _data._cache = cache; + _data._in_use = 0; + _data._next = _data._prev = 0; + + // Compute offset of first slab_entry in slab, not taking into + // account the colorization offset. "slab_entry._entry[]" needs to + // be "cache->_alignment"-aligned + unsigned long offset_first_elem = + ((sizeof(slab_data) + sizeof (slab_entry) + cache->_alignment - 1) + & ~(cache->_alignment - 1)) + - sizeof (slab_entry); + + // Compute size of a slab entry, including alignment padding at end + // of entry + unsigned entry_size = + (sizeof(slab_entry) + cache->_elem_size + cache->_alignment - 1) + & ~(cache->_alignment - 1); + + // Compute number of elements fitting into a slab + unsigned elem_num = + (cache->_slab_size - offset_first_elem) / entry_size; + + // Compute pointer to first data element, now taking into account + // the latest colorization offset + char* data = + reinterpret_cast(this) + offset_first_elem + cache->_latest_offset; + + // Update the colorization offset + cache->_latest_offset += cache->_alignment; + if (offset_first_elem + cache->_latest_offset + entry_size * elem_num + > cache->_slab_size) + { + cache->_latest_offset = 0; + } + + // Initialize the cache elements + slab_entry *e = 0, *e_prev = 0; + + for (unsigned i = 0; i < elem_num; i++) + { + e = reinterpret_cast(data); + + e->_next_free = e_prev; + cache->elem_ctor(& e->_entry[0]); + + e_prev = e; + + data += + (sizeof(slab_entry) + cache->_elem_size + cache->_alignment - 1) + & ~(cache->_alignment - 1); + } + + _data._first_free = e; + _data._free = elem_num; +} + +PUBLIC +void * +slab::alloc() +{ + slab_entry *e = _data._first_free; + + if (! e) + return 0; + + _data._first_free = e->_next_free; + _data._in_use ++; + _data._free --; + + return & e->_entry; +} + +PUBLIC +void +slab::free(void *entry) +{ + slab_entry *e = reinterpret_cast + (reinterpret_cast(entry) - offsetof(slab_entry, _entry)); + + e->_next_free = _data._first_free; + _data._first_free = e; + + assert(_data._in_use); + _data._in_use --; + _data._free ++; +} + +PUBLIC +inline bool +slab::is_empty() +{ + return _data._in_use == 0; +} + +PUBLIC +inline bool +slab::is_full() +{ + return _data._free == 0; +} + +PUBLIC +inline unsigned +slab::in_use() +{ + return _data._in_use; +} + +PUBLIC +void +slab::enqueue(slab *prev) +{ + assert(prev); + + if ((_data._next = prev->_data._next)) + _data._next->_data._prev = this; + _data._prev = prev; + _data._prev->_data._next = this; +} + +PUBLIC +void +slab::dequeue() +{ + if (_data._prev) + _data._prev->_data._next = _data._next; + if (_data._next) + _data._next->_data._prev = _data._prev; + + _data._prev = _data._next = 0; +} + +PUBLIC +inline slab * +slab::prev() +{ + return _data._prev; +} + +PUBLIC +inline slab * +slab::next() +{ + return _data._next; +} + +PUBLIC +inline void * +slab::operator new(size_t, + slab_cache_anon *cache) throw() +{ + // slabs must be size-aligned so that we can compute their addresses + // from element addresses + return cache->block_alloc(cache->_slab_size, cache->_slab_size); +} + +PUBLIC static +unsigned +slab::num_elems(unsigned long slab_size, + unsigned elem_size, + unsigned alignment) +{ + // Compute offset of first slab_entry in slab, not taking into + // account the colorization offset. "slab_entry._entry[]" needs to + // be "cache->_alignment"-aligned + unsigned long offset_first_elem = + ((sizeof(slab::slab_data) + sizeof (slab::slab_entry) + alignment - 1) + & ~(alignment - 1)) + - sizeof (slab::slab_entry); + + // Compute size of a slab entry, including alignment padding at end + // of entry + unsigned entry_size = + (sizeof(slab::slab_entry) + elem_size + alignment - 1) + & ~(alignment - 1); + + // Compute number of elements fitting into a slab + return (slab_size - offset_first_elem) / entry_size; +} + +PUBLIC static +unsigned +slab_cache_anon::num_elems(unsigned long slab_size, + unsigned elem_size, + unsigned alignment) +{ return slab::num_elems(slab_size, elem_size, alignment); } + +// +// slab_cache_anon +// +PUBLIC inline +slab_cache_anon::slab_cache_anon(unsigned elem_size, + unsigned alignment, + char const * name, + unsigned long min_size, + unsigned long max_size) + : _first_slab(0), _first_available_slab(0), _last_slab(0), + _elem_size(elem_size), + _latest_offset(0), _alignment(alignment), + _name (name) +{ + lock.init(); + + for ( + _slab_size = min_size; + num_elems(_slab_size, elem_size, alignment) < 8 + && _slab_size < max_size; + _slab_size <<= 1) ; +} + +// +// slab_cache_anon +// +PUBLIC inline +slab_cache_anon::slab_cache_anon(unsigned long slab_size, + unsigned elem_size, + unsigned alignment, + char const * name) + : _first_slab(0), _first_available_slab(0), _last_slab(0), + _slab_size(slab_size), _elem_size(elem_size), + _latest_offset(0), _alignment(alignment), + _name (name) +{ + lock.init(); +} + +PUBLIC +virtual +slab_cache_anon::~slab_cache_anon() +{ + // the derived class should call destroy() before deleting us. + // assert(_first_slab == 0); +} + +PROTECTED inline +void +slab_cache_anon::destroy() // descendant should call this in destructor +{ +#if 0 + slab *n, *s = _first_slab; + + while (s) + { + n = s->next(); + + // explicitly call destructor to delete s; + s->~slab(); + block_free(s, _slab_size); + + s = n; + } + + _first_slab = 0; +#endif +} + +PUBLIC +virtual void * +slab_cache_anon::alloc() // request initialized member from cache +{ + Lock_guard guard(&lock); + + if (! _first_available_slab) + { + slab *s = new (this) slab(this); + if (! s) + return 0; + + _first_available_slab = s; + + if (_last_slab) + { + assert(_last_slab->is_full()); + + _first_available_slab->enqueue(_last_slab); + _last_slab = _first_available_slab; + } + else // this was the first slab we allocated + _first_slab = _last_slab = _first_available_slab; + } + + assert(_first_available_slab + && ! _first_available_slab->is_full()); + assert(! _first_available_slab->prev() + || _first_available_slab->prev()->is_full()); + + void *ret = _first_available_slab->alloc(); + assert(ret); + + if (_first_available_slab->is_full()) + _first_available_slab = _first_available_slab->next(); + + return ret; +} + +PUBLIC template< typename Q > +inline +void * +slab_cache_anon::q_alloc(Q *quota) +{ + if (EXPECT_FALSE(!quota->alloc(_elem_size))) + return 0; + + void *r; + if (EXPECT_FALSE(!(r=alloc()))) + { + quota->free(_elem_size); + return 0; + } + + return r; +} + +PUBLIC +virtual void +slab_cache_anon::free(void *cache_entry) // return initialized member to cache +{ + Lock_guard guard(&lock); + + slab *s = reinterpret_cast + (reinterpret_cast(cache_entry) & ~(_slab_size - 1)); + + bool was_full = s->is_full(); + + s->free(cache_entry); + + if (was_full) + { + if (s->next() == 0) // have no right neighbor? + { + assert(! _first_available_slab); + } + else if (s->next()->is_full()) // right neigbor full? + { + // We requeue to become the first non-full slab in the queue + // so that all full slabs are at the beginning of the queue. + + if (s == _first_slab) + _first_slab = s->next(); + // don't care about _first_available_slab, _last_slab -- + // they cannot point to s because we were full and have a + // right neighbor + + s->dequeue(); + + if (_first_available_slab) + { + // _first_available_slab->prev() is defined because we + // had a right neighbor which is full, that is, + // _first_available_slab wasn't our right neighbor and + // now isn't the first slab in the queue + assert(_first_available_slab->prev()->is_full()); + s->enqueue(_first_available_slab->prev()); + } + else + { + // all slabs were full + assert(_last_slab->is_full()); + s->enqueue(_last_slab); + _last_slab = s; + } + } + + _first_available_slab = s; + + } + else if (s->is_empty()) + { + if (s->next() && (! s->next()->is_empty())) // right neighbor not empty? + { + // Move to tail of list + + if (s == _first_slab) + _first_slab = s->next(); + if (s == _first_available_slab) + _first_available_slab = s->next(); + // don't care about _last_slab because we know we have a + // right neighbor + + s->dequeue(); + + s->enqueue(_last_slab); + _last_slab = s; + } + } + else + { + // We weren't either full or empty; we already had free + // elements. This changes nothing in the queue, and there + // already must have been a _first_available_slab. + } + + assert(_first_available_slab); +} + +PUBLIC template< typename Q > +inline +void +slab_cache_anon::q_free(Q *quota, void *obj) +{ + free(obj); + quota->free(_elem_size); +} + +PUBLIC +virtual unsigned long +slab_cache_anon::reap() // request that cache returns memory to system +{ + Lock_guard guard(&lock); + + if (! _first_slab) + return 0; // haven't allocated anything yet + + // never delete first slab, even if it is empty + if (_last_slab == _first_slab + || (! _last_slab->is_empty())) + return 0; + + slab *s = _last_slab; + + if (_first_available_slab == s) + _first_available_slab = 0; + + _last_slab = s->prev(); + s->dequeue(); + + // explicitly call destructor to delete s; + s->~slab(); + block_free(s, _slab_size); + + return _slab_size; +} + +// Element initialization/destruction +PROTECTED +virtual void +slab_cache_anon::elem_ctor(void *) +{} + +PROTECTED +virtual void +slab_cache_anon::elem_dtor(void *) +{} + +// Debugging output + +#include + +PUBLIC +virtual void +slab_cache_anon::debug_dump () +{ + printf ("%s: %lu-KB slabs (", + _name, _slab_size / 1024); + + unsigned count, total = 0, total_elems = 0; + slab* s = _first_slab; + + for (count = 0; + s && s->is_full(); + s = s->next()) + { + count++; + total_elems += s->in_use(); + } + + total += count; + + printf ("%u full, ", count); + + for (count = 0; + s && ! s->is_empty(); + s = s->next()) + { + if (s->is_full()) + printf ("\n*** wrongly-enqueued full slab found\n"); + count++; + total_elems += s->in_use(); + } + + total += count; + + printf ("%u used, ", count); + + for (count = 0; + s; + s = s->next()) + { + if (! s->is_empty()) + printf ("\n*** wrongly-enqueued nonempty slab found\n"); + count++; + total_elems += s->in_use(); + } + + unsigned total_used = total; + total += count; + + printf ("%u empty = %u total) = %lu KB,\n %u elems (size=%u, align=%u)", + count, total, total * _slab_size / 1024, + total_elems, _elem_size, _alignment); + + if (total_elems) + printf (", overhead = %lu B (%lu B) = %lu%% (%lu%%) \n", + total * _slab_size - total_elems * _elem_size, + total_used * _slab_size - total_elems * _elem_size, + 100 - total_elems * _elem_size * 100 / (total * _slab_size), + 100 - total_elems * _elem_size * 100 / (total_used * _slab_size)); + else + printf ("\n"); +} diff --git a/kernel/fiasco/src/lib/libk/slist b/kernel/fiasco/src/lib/libk/slist new file mode 100644 index 00000000..43eaeaad --- /dev/null +++ b/kernel/fiasco/src/lib/libk/slist @@ -0,0 +1,181 @@ +// vi:ft=cpp +/* + * (c) 2011 Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ + +#pragma once + +#include "bits/list_basics.h" + +namespace cxx { + +class S_list_item +{ +public: + S_list_item() : _n(0) {} + explicit S_list_item(bool) {} + +private: + template friend class S_list; + template friend class S_list_tail; + template friend struct Bits::Basic_list_policy; + + S_list_item(S_list_item const &); + void operator = (S_list_item const &); + + S_list_item *_n; +}; + +template< typename T, typename POLICY = Bits::Basic_list_policy< T, S_list_item > > +class S_list : public Bits::Basic_list +{ + S_list(S_list const &) = delete; + void operator = (S_list const &) = delete; + +private: + typedef typename Bits::Basic_list Base; + +public: + typedef typename Base::Iterator Iterator; + + S_list(S_list &&o) : Base(static_cast(o)) {} + + S_list &operator = (S_list &&o) + { + Base::operator = (static_cast(o)); + return *this; + } + + // BSS allocation + explicit S_list(bool x) : Base(x) {} + + S_list() : Base() {} + + void add(T *e) + { + e->_n = this->_f; + this->_f = e; + } + + template< typename CAS > + void add(T *e, CAS const &c) + { + do + { + e->_n = this->_f; + } + while (!c(&this->_f, e->_n, e)); + } + + void push_front(T *e) { add(e); } + T *pop_front() + { + T *r = this->front(); + if (this->_f) + this->_f = this->_f->_n; + return r; + } + + void insert(T *e, Iterator const &pred) + { + S_list_item *p = *pred; + e->_n = p->_n; + p->_n = e; + } + + static void insert_before(T *e, Iterator const &succ) + { + S_list_item **x = Base::__get_internal(succ); + + e->_n = *x; + *x = e; + } + + static void replace(Iterator const &p, T*e) + { + S_list_item **x = Base::__get_internal(p); + e->_n = (*x)->_n; + *x = e; + } + + static Iterator erase(Iterator const &e) + { + S_list_item **x = Base::__get_internal(e); + *x = (*x)->_n; + return e; + } + +}; + + +template< typename T > +class S_list_bss : public S_list +{ +public: + S_list_bss() : S_list(true) {} +}; + +template< typename T, typename POLICY = Bits::Basic_list_policy< T, S_list_item > > +class S_list_tail : public S_list +{ +private: + typedef S_list Base; + +public: + S_list_tail() : Base(), _tail(&this->_f) {} + + S_list_tail(S_list_tail &&t) : Base(static_cast(t)), _tail(t._tail) + { + t._tail = &t._f; + } + + S_list_tail &operator = (S_list_tail &&t) + { + Base::operator = (static_cast(t)); + _tail = t._tail; + t._tail = &t._f; + return *this; + } + + void push_back(T *e) + { + e->_n = 0; + *_tail = e; + _tail = &e->_n; + } + + void clear() + { + Base::clear(); + _tail = &this->_f; + } + + void append(S_list_tail &o) + { + T *x = o.front(); + *_tail = x; + if (x) + _tail = o._tail; + o.clear(); + } + + +private: + S_list_item **_tail; +}; + +} diff --git a/kernel/fiasco/src/lib/libk/sparc/atomic-sparc.cpp b/kernel/fiasco/src/lib/libk/sparc/atomic-sparc.cpp new file mode 100644 index 00000000..1fa70422 --- /dev/null +++ b/kernel/fiasco/src/lib/libk/sparc/atomic-sparc.cpp @@ -0,0 +1,60 @@ +IMPLEMENTATION [sparc]: + +#include + +inline +bool +cas_unsafe( Mword *ptr, Mword oldval, Mword newval ) +{ + (void)ptr; (void)newval; + Mword ret = 0; + +#if 0 + asm volatile ( "1: \n" + " lwarx %%r6, 0, %[ptr] \n" + " cmpw %[oldval], %%r6 \n" + " bne- 2f \n" + " stwcx. %[newval], 0,%[ptr] \n" + " bne- 1b \n" + "2: \n" + " mr %[ret], %%r6 \n" + : [ret] "=r"(ret), + [ptr] "=r"(ptr), + [oldval] "=r"(oldval), + [newval] "=r"(newval) + : "0" (ret), + "1" (ptr), + "2" (oldval), + "3" (newval) + : "memory", "r6" + ); +#endif + + return ret == oldval; +} + +/* dummy implement */ +bool +cas2_unsafe( Mword *, Mword *, Mword *) +{ + panic("%s not implemented", __func__); + return false; +} + +inline +void +atomic_and (Mword *l, Mword mask) +{ + Mword old; + do { old = *l; } + while ( !cas (l, old, old & mask)); +} + +inline +void +atomic_or (Mword *l, Mword bits) +{ + Mword old; + do { old = *l; } + while ( !cas (l, old, old | bits)); +} diff --git a/kernel/fiasco/src/lib/libk/sparc/div32.h b/kernel/fiasco/src/lib/libk/sparc/div32.h new file mode 100644 index 00000000..6234c58e --- /dev/null +++ b/kernel/fiasco/src/lib/libk/sparc/div32.h @@ -0,0 +1,14 @@ +#ifndef SPARC_DIV32_H__ +#define SPARC_DIV32_H__ + +#include "std_macros.h" + +/** return (divident / divisor) with divisor<2^32 */ +extern inline FIASCO_CONST +unsigned long long +div32(unsigned long long divident, unsigned long divisor) +{ + return divident/divisor; +} + +#endif diff --git a/kernel/fiasco/src/lib/libk/std_macros.cpp b/kernel/fiasco/src/lib/libk/std_macros.cpp new file mode 100644 index 00000000..d6d8b87b --- /dev/null +++ b/kernel/fiasco/src/lib/libk/std_macros.cpp @@ -0,0 +1,42 @@ +INTERFACE: + +#if (__GNUC__>=3) +# define BUILTIN_EXPECT(exp,c) __builtin_expect((exp),(c)) +# define EXPECT_TRUE(exp) __builtin_expect((exp),true) +# define EXPECT_FALSE(exp) __builtin_expect((exp),false) +#else +# define BUILTIN_EXPECT(exp,c) (exp) +# define EXPECT_TRUE(exp) (exp) +# define EXPECT_FALSE(exp) (exp) +#endif + +// Use this for functions which do not examine any values except their +// arguments and have no effects except the return value. Note that a +// function that has pointer arguments and examines the data pointed to +// must _not_ be declared `const'. Likewise, a function that calls a +// non-`const' function usually must not be `const'. It does not make +// sense for a `const' function to return `void'. +#define FIASCO_CONST __attribute__ ((__const__)) + +#ifdef __i386__ +#define FIASCO_FASTCALL __attribute__ ((__regparm__(3))) +#else +#define FIASCO_FASTCALL +#endif + +#if (__GNUC__<3) +# define MARK_AS_DEPRECATED /* empty */ +# define ALWAYS_INLINE /* empty */ +# define FIASCO_NOINLINE +# define FIASCO_WARN_RESULT +#else +# define MARK_AS_DEPRECATED __attribute__ ((__deprecated__)) +# define ALWAYS_INLINE __attribute__ ((__always_inline__)) +# define FIASCO_NOINLINE __attribute__ ((__noinline__)) +# define FIASCO_WARN_RESULT __attribute__ ((warn_unused_result)) +#endif + +#define FIASCO_NORETURN __attribute__ ((__noreturn__)) + +IMPLEMENTATION: +//- diff --git a/kernel/fiasco/src/lib/libk/template_math.h b/kernel/fiasco/src/lib/libk/template_math.h new file mode 100644 index 00000000..9403e8a0 --- /dev/null +++ b/kernel/fiasco/src/lib/libk/template_math.h @@ -0,0 +1,17 @@ +#pragma once + +namespace Tl_math { + +/** + * Calculate the ld of \a v. + */ +template< unsigned v > +struct Ld { enum { Res = Ld<(v+1)/2>::Res + 1 }; }; + +// undefined (goes to minus infinity) +template<> +struct Ld<0> { }; + +template<> +struct Ld<1> { enum { Res = 0 }; }; +}; diff --git a/kernel/fiasco/src/lib/libk/type_traits b/kernel/fiasco/src/lib/libk/type_traits new file mode 100644 index 00000000..7306a22e --- /dev/null +++ b/kernel/fiasco/src/lib/libk/type_traits @@ -0,0 +1,138 @@ +// vi:ft=cpp + +/* + * (c) 2008-2009 Alexander Warg , + * Torsten Frenzel + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ + + +#pragma once + +#include "fiasco_defs.h" + +namespace cxx { + +template< typename T, T V > +struct integral_constant +{ + static T const value = V; + typedef T value_type; + typedef integral_constant type; +}; + +typedef integral_constant true_type; +typedef integral_constant false_type; + +template< typename T > struct remove_reference; + +template< typename T > struct idendity { typedef T type; }; + +template< typename T1, typename T2 > struct is_same; + +template< typename T > struct remove_const; + +template< typename T > struct remove_volatile; + +template< typename T > struct remove_cv; + +template< typename T > struct remove_pointer; + + + +template< typename, typename > +struct is_same : public false_type {}; + +template< typename T > +struct is_same : public true_type {}; + +template< typename T > +struct remove_reference { typedef T type; }; + +template< typename T > +struct remove_reference { typedef T type; }; + +template< typename T > +struct remove_reference { typedef T type; }; + + +template< typename T > struct remove_const { typedef T type; }; +template< typename T > struct remove_const { typedef T type; }; + +template< typename T > struct remove_volatile { typedef T type; }; +template< typename T > struct remove_volatile { typedef T type; }; + +template< typename T > +struct remove_cv { typedef typename remove_const::type>::type type; }; + +template< typename T, typename > +struct __remove_pointer_h { typedef T type; }; + +template< typename T, typename I > +struct __remove_pointer_h { typedef I type; }; + +template< typename T > +struct remove_pointer : public __remove_pointer_h::type> {}; + +#if FIASCO_GCC_VERSION >= 405 + +template< typename T > +inline T && +forward(typename cxx::remove_reference::type &t) +{ return static_cast(t); } + +template< typename T > +inline T && +forward(typename cxx::remove_reference::type &&t) +{ return static_cast(t); } + +#else + +template< typename T > +inline T && +forward(typename cxx::idendity::type &&t) +{ return t; } + +#endif + +template< typename T > +inline typename cxx::remove_reference::type && +move(T &t) { return static_cast::type &&>(t); } + +template< bool, typename T = void > +struct enable_if {}; + +template< typename T > +struct enable_if { typedef T type; }; + +template< typename T > +struct is_const : public false_type {}; + +template< typename T > +struct is_const : public true_type {}; + +template< bool, typename, typename > +struct conditional; + +template< bool C, typename T_TRUE, typename T_FALSE > +struct conditional { typedef T_TRUE type; }; + +template< typename T_TRUE, typename T_FALSE > +struct conditional< false, T_TRUE, T_FALSE > { typedef T_FALSE type; }; + + +} + diff --git a/kernel/fiasco/src/lib/libk/unique_ptr.h b/kernel/fiasco/src/lib/libk/unique_ptr.h new file mode 100644 index 00000000..1c64544b --- /dev/null +++ b/kernel/fiasco/src/lib/libk/unique_ptr.h @@ -0,0 +1,92 @@ +#pragma once + +#include + +namespace cxx +{ + +template< typename T > +struct default_delete +{ + default_delete() {} + + template< typename U > + default_delete(default_delete const &) {} + + void operator () (T *p) const + { delete p; } +}; + +template< typename T > +struct default_delete +{ + default_delete() {} + + void operator () (T *p) + { delete [] p; } +}; + +template< typename T, typename T_Del = default_delete > +class unique_ptr +{ +private: + struct _unspec; + typedef _unspec* _unspec_ptr_type; + +public: + typedef T *pointer; + typedef T element_type; + typedef T_Del deleter_type; + + unique_ptr() : _ptr(pointer()) {} + + explicit unique_ptr(pointer p) : _ptr(p) {} + + unique_ptr(unique_ptr &&o) : _ptr(o.release()) {} + + ~unique_ptr() { reset(); } + + unique_ptr &operator = (unique_ptr &&o) + { + reset(o.release()); + return *this; + } + + unique_ptr &operator = (_unspec_ptr_type) + { + reset(); + return *this; + } + + element_type &operator * () const { return *get(); } + pointer operator -> () const { return get(); } + + pointer get() const { return _ptr; } + + operator _unspec_ptr_type () const + { return reinterpret_cast<_unspec_ptr_type>(get()); } + + pointer release() + { + pointer r = _ptr; + _ptr = 0; + return r; + } + + void reset(pointer p = pointer()) + { + if (p != get()) + { + deleter_type()(get()); + _ptr = p; + } + } + + unique_ptr(unique_ptr const &) = delete; + unique_ptr &operator = (unique_ptr const &) = delete; + +private: + pointer _ptr; +}; + +} diff --git a/kernel/fiasco/src/lib/libk/ux/div32.h b/kernel/fiasco/src/lib/libk/ux/div32.h new file mode 100644 index 00000000..d4b38088 --- /dev/null +++ b/kernel/fiasco/src/lib/libk/ux/div32.h @@ -0,0 +1,23 @@ +#ifndef MLC_DIV32_H__ +#define MLC_DIV32_H__ + +#include "std_macros.h" + +/** return (divident / divisor) with divisor<2^32 */ +extern inline FIASCO_CONST +unsigned long long +div32(unsigned long long divident, unsigned long divisor) +{ + unsigned long long ret; + unsigned long dummy; + asm ("divl %5 \n\t" + "xchg %%eax, %4 \n\t" + "divl %5 \n\t" + "movl %4, %%edx \n\t" + : "=A"(ret), "=r"(dummy) + : "a"((unsigned long)(divident >> 32)), "d"(0), + "1"((unsigned long)(divident & 0xffffffff)), "rm"(divisor)); + return ret; +} + +#endif diff --git a/kernel/fiasco/src/lib/libk/ux/mod32.h b/kernel/fiasco/src/lib/libk/ux/mod32.h new file mode 100644 index 00000000..12610711 --- /dev/null +++ b/kernel/fiasco/src/lib/libk/ux/mod32.h @@ -0,0 +1,21 @@ +#ifndef MLC_MOD32_H__ +#define MLC_MOD32_H__ + +#include "std_macros.h" + +/** return (divident % divisor) with divisor<2^32 */ +extern inline FIASCO_CONST +unsigned long +mod32(unsigned long long divident, unsigned long divisor) +{ + unsigned long ret, dummy; + asm ("divl %5 \n\t" + "movl %4, %%eax \n\t" + "divl %5 \n\t" + : "=d"(ret), "=a"(dummy) + : "a"((unsigned long)(divident >> 32)), "d"(0), + "irm"((unsigned long)(divident & 0xffffffff)), "rm"(divisor)); + return ret; +} + +#endif diff --git a/kernel/fiasco/src/lib/minilibc/__assert_fail.c b/kernel/fiasco/src/lib/minilibc/__assert_fail.c new file mode 100644 index 00000000..328982fb --- /dev/null +++ b/kernel/fiasco/src/lib/minilibc/__assert_fail.c @@ -0,0 +1,12 @@ +#include "assert.h" +#include "stdio.h" +#include "stdlib.h" + +void +__assert_fail (const char *__assertion, const char *__file, + unsigned int __line, void *ret) +{ + printf("ASSERTION_FAILED (%s)[ret=%p]\n" + " in file %s:%d\n", __assertion, ret, __file, __line); + exit (EXIT_FAILURE); +} diff --git a/kernel/fiasco/src/lib/minilibc/__lltostr.c b/kernel/fiasco/src/lib/minilibc/__lltostr.c new file mode 100644 index 00000000..c9f593ef --- /dev/null +++ b/kernel/fiasco/src/lib/minilibc/__lltostr.c @@ -0,0 +1,34 @@ +#include + +int __lltostr(char *s, int size, unsigned long long i, int base, char UpCase); + +int __lltostr(char *s, int size, unsigned long long i, int base, char UpCase) +{ + char *tmp; + unsigned int j=0; + + s[--size]=0; + + tmp=s+size; + + if ((base==0)||(base>36)) base=10; + + j=0; + if (!i) + { + *(--tmp)='0'; + j=1; + } + + while((tmp>s)&&(i)) + { + tmp--; + // r = moddiv(i,base); + if ((*tmp=i%base+'0')>'9') *tmp+=(UpCase?'A':'a')-'9'-1; + i=i/base; + j++; + } + memmove(s,tmp,j+1); + + return j; +} diff --git a/kernel/fiasco/src/lib/minilibc/__ltostr.c b/kernel/fiasco/src/lib/minilibc/__ltostr.c new file mode 100644 index 00000000..b13b0e3d --- /dev/null +++ b/kernel/fiasco/src/lib/minilibc/__ltostr.c @@ -0,0 +1,35 @@ +#include +#include +//#include + +int __ltostr(char *s, unsigned int size, unsigned long i, unsigned int base, int UpCase) +{ + char *tmp; + unsigned int j=0; + //_moddiv_t r; + + s[--size]=0; + + tmp=s+size; + + if ((base==0)||(base>36)) base=10; + + j=0; + if (!i) + { + *(--tmp)='0'; + j=1; + } + + while((tmp>s)&&(i)) + { + tmp--; + //r = moddiv(i,base); + if ((*tmp=i%base+'0')>'9') *tmp+=(UpCase?'A':'a')-'9'-1; + i=i/base; + j++; + } + memmove(s,tmp,j+1); + + return j; +} diff --git a/kernel/fiasco/src/lib/minilibc/__v_printf.c b/kernel/fiasco/src/lib/minilibc/__v_printf.c new file mode 100644 index 00000000..4eb4b039 --- /dev/null +++ b/kernel/fiasco/src/lib/minilibc/__v_printf.c @@ -0,0 +1,281 @@ +#include +#include +#include +#include + +#include "vprintf_backend.h" + +static inline unsigned int skip_to(const char *format) { + int unsigned nr; + for (nr=0; format[nr] && (format[nr]!='%'); ++nr); + return nr; +} + +#define A_WRITE(fn,buf,sz) ((fn)->put((buf),(sz),(fn)->data)) + +static int visible_strlen(char const *s, unsigned int *wh_sz) +{ + int l = 0; + int in_esc = 0; + *wh_sz = 0; + for ( ; *s; ++s, ++(*wh_sz)) + { + if (in_esc == 2) + { + if (!(*s >= '0' && *s <= '9') && *s != ';') + in_esc = 0; + + continue; + } + else if (in_esc == 1 && *s == '[') + { + in_esc = 2; + continue; + } + + if (*s == '\033') + { + in_esc = 1; + continue; + } + ++l; + } + + return l + in_esc; +} + +static char* pad_line[16]= { " ", "0000000000000000", }; +static inline int write_pad(struct output_op* fn, int len, int padwith) { + int nr=0; + for (;len>15;len-=16,nr+=16) { + A_WRITE(fn,pad_line[(padwith=='0')?1:0],16); + } + if (len>0) { + A_WRITE(fn,pad_line[(padwith=='0')?1:0],(unsigned int)len); nr+=len; + } + return nr; +} + +int __v_printf(struct output_op* fn, const char *format, va_list arg_ptr) +{ + int len=0; + + while (*format) { + unsigned int sz = skip_to(format); + if (sz) { + A_WRITE(fn,format,sz); len+=sz; + format+=sz; + } + if (*format=='%') { + char buf[32]; + + char ch, padwith=' '; + char *s; + + char flag_in_sign=0; + char flag_upcase=0; + char flag_hash=0; + char flag_left=0; + char flag_space=0; + char flag_sign=0; + char flag_dot=0; + char flag_size_t = 0; + signed char flag_long=0; + + unsigned int base; + unsigned int width=0, preci=0; + + long int number=0; + long long llnumber=0; + + unsigned int wh_sz; + + ++format; +inn_printf: + switch(ch=*format++) { + case 0: + return -1; + break; + + /* FLAGS */ + case '#': + flag_hash=1; + goto inn_printf; + + case 'h': + --flag_long; + goto inn_printf; + case 'l': + ++flag_long; + goto inn_printf; + case 'z': + flag_size_t = 1; + goto inn_printf; + + case '0': + padwith='0'; + goto inn_printf; + + case '-': + flag_left=1; + goto inn_printf; + + case ' ': + flag_space=1; + goto inn_printf; + + case '+': + flag_sign=1; + goto inn_printf; + + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if(flag_dot) return -1; + width=strtoul(format-1,&s,10); + format=s; + goto inn_printf; + + case '*': + width=va_arg(arg_ptr,int); + goto inn_printf; + + case '.': + flag_dot=1; + if (*format=='*') { + preci=va_arg(arg_ptr,int); + ++format; + } else { + long int tmp=strtol(format,&s,10); + preci=tmp<0?0:tmp; + format=s; + } + goto inn_printf; + + /* print a char or % */ + case 'c': + ch=(char)va_arg(arg_ptr,int); + case '%': + A_WRITE(fn,&ch,1); ++len; + break; + + /* print a string */ + case 's': + s=va_arg(arg_ptr,char *); + if (!s) s="(null)"; + sz = visible_strlen(s, &wh_sz); + // FIXME: could not limit output when invisibible charachters are + // in the output + if (sz == wh_sz && flag_dot && sz>preci) + { + sz = preci; + wh_sz = sz; + } + +print_out: + if (width && (!flag_left)) { + len+=write_pad(fn,(signed int)width-(signed int)sz,padwith); + } + A_WRITE(fn,s,wh_sz); len+=wh_sz; + if (width && (flag_left)) { + len+=write_pad(fn,(signed int)width-(signed int)sz,' '); + } + break; + + /* print an integer value */ + case 'b': + base=2; + sz=0; + goto num_printf; + case 'p': + flag_hash=1; + if(sizeof(void*)>sizeof(unsigned)) + ++flag_long; + if(sizeof(void*)>sizeof(long)) + ++flag_long; + ch='x'; + case 'X': + flag_upcase=(ch=='X'); + case 'x': + base=16; + sz=0; + if (flag_hash) { + buf[1]='0'; + buf[2]=ch; + sz=2; + } + goto num_printf; + case 'd': + case 'i': + flag_in_sign=1; + case 'u': + base=10; + sz=0; + goto num_printf; + case 'o': + base=8; + sz=0; + if (flag_hash) { + buf[1]='0'; + ++sz; + } + +num_printf: + if (flag_long>0) { + if (flag_long>1) + llnumber=va_arg(arg_ptr,long long); + else + number=va_arg(arg_ptr,long); + } + else if (flag_size_t) + number=va_arg(arg_ptr,size_t); + else + number=va_arg(arg_ptr,int); + + if (flag_in_sign) { + if ((flag_long>1)&&(llnumber<0)) { + llnumber=-llnumber; + flag_in_sign=2; + } else + if (number<0) { + number=-number; + flag_in_sign=2; + } + } + if (flag_long<1) number&=0xffffffff; + if (flag_long<0) number&=0xffff; + if (flag_long<-1) number&=0xff; + if (flag_long>1) + sz += __lltostr(buf+1+sz,sizeof(buf)-5, + (unsigned long long) llnumber,base,flag_upcase); + else + sz += __ltostr(buf+1+sz,sizeof(buf)-5, + (unsigned long) number,base,flag_upcase); + + s=buf+1; + + if (flag_in_sign==2) { + *(--s)='-'; + ++sz; + } else if ((flag_in_sign)&&(flag_sign || flag_space)) { + *(--s)=(flag_sign)?'+':' '; + ++sz; + } + wh_sz = sz; + + goto print_out; + + default: + break; + } + } + } + return len; +} + diff --git a/kernel/fiasco/src/lib/minilibc/aeabi.c b/kernel/fiasco/src/lib/minilibc/aeabi.c new file mode 100644 index 00000000..07662769 --- /dev/null +++ b/kernel/fiasco/src/lib/minilibc/aeabi.c @@ -0,0 +1,20 @@ +/* + * Adam Lackorzynski + */ + +#include + +int __aeabi_unwind_cpp_pr0(void); +int __aeabi_unwind_cpp_pr1(void); + +int __aeabi_unwind_cpp_pr0(void) +{ + assert(0); + return 0; +} + +int __aeabi_unwind_cpp_pr1(void) +{ + assert(0); + return 0; +} diff --git a/kernel/fiasco/src/lib/minilibc/amd64/include/limits.h b/kernel/fiasco/src/lib/minilibc/amd64/include/limits.h new file mode 100644 index 00000000..05b1ffde --- /dev/null +++ b/kernel/fiasco/src/lib/minilibc/amd64/include/limits.h @@ -0,0 +1,62 @@ +#ifndef _LIMITS_H +#define _LIMITS_H + +//#include + +#define CHAR_BIT 8 + +#define SCHAR_MIN (-128) +#define SCHAR_MAX 0x7f +#define UCHAR_MAX 0xff + +#define SHRT_MIN (-SHRT_MAX-1) +#define SHRT_MAX 0x7fff +#define USHRT_MAX 0xffff + +#define INT_MIN (-INT_MAX-1) +#define INT_MAX 0x7fffffff +#define UINT_MAX 0xffffffff + +#if __WORDSIZE == 64 +#define LONG_MAX 9223372036854775807L +#define ULONG_MAX 18446744073709551615UL +#else +#define LONG_MAX 2147483647L +#define ULONG_MAX 4294967295UL +#endif +#define LONG_MIN (-LONG_MAX - 1L) + +#define LLONG_MAX 9223372036854775807LL +#define LLONG_MIN (-LLONG_MAX - 1LL) + +/* Maximum value an `unsigned long long int' can hold. (Minimum is 0.) */ +#define ULLONG_MAX 18446744073709551615ULL +#define ULONG_LONG_MAX ULLONG_MAX + +#define SSIZE_MIN INT_MIN +#define SSIZE_MAX INT_MAX + +#define PASS_MAX 256 + +#define NR_OPEN 1024 + +#define NGROUPS_MAX 32 /* supplemental group IDs are available */ +#define ARG_MAX 131072 /* # bytes of args + environ for exec() */ +#define CHILD_MAX 999 /* no limit :-) */ +#define OPEN_MAX 256 /* # open files a process may have */ +#define LINK_MAX 127 /* # links a file may have */ +#define MAX_CANON 255 /* size of the canonical input queue */ +#define MAX_INPUT 255 /* size of the type-ahead buffer */ +#define NAME_MAX 255 /* # chars in a file name */ +#define PATH_MAX 4095 /* # chars in a path name */ +#define PIPE_BUF 4096 /* # bytes in atomic write to a pipe */ + +#define RTSIG_MAX 32 + +#define LINE_MAX 2048 + +/* mutt demanded these */ +#define _POSIX_PATH_MAX PATH_MAX +#define MB_LEN_MAX 16 + +#endif diff --git a/kernel/fiasco/src/lib/minilibc/amd64/include/setjmp.h b/kernel/fiasco/src/lib/minilibc/amd64/include/setjmp.h new file mode 100644 index 00000000..f1da3131 --- /dev/null +++ b/kernel/fiasco/src/lib/minilibc/amd64/include/setjmp.h @@ -0,0 +1,42 @@ +#ifndef _SETJMP_H +#define _SETJMP_H + +#include + + +#ifndef __ASSEMBLER__ +typedef long long unsigned __jmp_buf[12]; +#endif +#define JB_BX 0 +#define JB_BP 1 +#define JB_R8 2 +#define JB_R9 3 +#define JB_R10 4 +#define JB_R11 5 +#define JB_R12 6 +#define JB_R13 7 +#define JB_R14 8 +#define JB_R15 9 +#define JB_SP 10 +#define JB_PC 11 +#define JB_SIZE 96 + +#ifndef __ASSEMBLER__ + +typedef struct __jmp_buf_struct +{ + __jmp_buf __jmpbuf; +} jmp_buf[1]; + +__BEGIN_DECLS + +void longjmp (jmp_buf __env, int __val) + __attribute__ ((__noreturn__)); + +int setjmp(jmp_buf env); + +__END_DECLS + +#endif + +#endif diff --git a/kernel/fiasco/src/lib/minilibc/amd64/lltostr.c b/kernel/fiasco/src/lib/minilibc/amd64/lltostr.c new file mode 100644 index 00000000..37f5b176 --- /dev/null +++ b/kernel/fiasco/src/lib/minilibc/amd64/lltostr.c @@ -0,0 +1,34 @@ +#include +#include +#include + +int __lltostr(char *s, int size, unsigned long long i, int base, char UpCase); + +int __lltostr(char *s, int size, unsigned long long i, int base, char UpCase) +{ + char *tmp; + unsigned int j=0; + + s[--size]=0; + tmp=s+size; + if (base==0||base>36) + base=10; + + j=0; + if (!i) + { + *(--tmp)='0'; + j=1; + } + + while (tmp>s && i) + { + tmp--; + if ((*tmp=mod32(i, base)+'0')>'9') + *tmp+=(UpCase?'A':'a')-'9'-1; + i=div32(i, base); + j++; + } + memmove(s,tmp,j+1); + return j; +} diff --git a/kernel/fiasco/src/lib/minilibc/amd64/setjmp.S b/kernel/fiasco/src/lib/minilibc/amd64/setjmp.S new file mode 100644 index 00000000..00456dce --- /dev/null +++ b/kernel/fiasco/src/lib/minilibc/amd64/setjmp.S @@ -0,0 +1,63 @@ +#include + +.text +.weak setjmp +.type setjmp,@function +setjmp: +.globl __setjmp +.type __setjmp,@function +__setjmp: + //mov 8(%rsp), %rax + + /* Save registers. */ + mov %rbx, (JB_BX*8)(%rdi) + mov %rbp, (JB_BP*8)(%rdi) + mov %r8, (JB_R8*8)(%rdi) + mov %r9, (JB_R9*8)(%rdi) + mov %r10, (JB_R10*8)(%rdi) + mov %r11, (JB_R11*8)(%rdi) + mov %r12, (JB_R12*8)(%rdi) + mov %r13, (JB_R13*8)(%rdi) + mov %r14, (JB_R14*8)(%rdi) + mov %r15, (JB_R15*8)(%rdi) + lea 8(%rsp), %rdx /* Save SP as it will be after we return. */ + mov 0(%rsp), %rcx /* Save PC we are returning to now. */ + mov %rdx, (JB_SP*8)(%rdi) + mov %rcx, (JB_PC*8)(%rdi) + xor %rax,%rax + ret + +.size __setjmp,.-__setjmp; + + + +.text +.global longjmp +.type longjmp,@function +longjmp: + mov %rdi, %rcx /* First argument is jump buffer. */ + mov %rsi, %rax /* Second argument is return value. */ + /* Save the return address now. */ + mov (JB_PC*8)(%rcx), %rdx + /* Restore registers. */ + mov (JB_R8*8)(%rcx), %r8 + mov (JB_R9*8)(%rcx), %r9 + mov (JB_R10*8)(%rcx), %r10 + mov (JB_R11*8)(%rcx), %r11 + mov (JB_R12*8)(%rcx), %r12 + mov (JB_R13*8)(%rcx), %r13 + mov (JB_R14*8)(%rcx), %r14 + mov (JB_R15*8)(%rcx), %r15 + mov (JB_BX*8)(%rcx), %rbx + mov (JB_BP*8)(%rcx), %rbp + mov (JB_SP*8)(%rcx), %rsp + or %rax, %rax + jz 1f + /* Jump to saved PC. */ + jmp *%rdx + + /* From the longjmp manpage: ``If longjmp is invoked with a + * second argument of 0, 1 will be returned instead.'' */ +1: mov $1, %rax + jmp *%rdx +.size longjmp,.-longjmp; diff --git a/kernel/fiasco/src/lib/minilibc/arm/include/limits.h b/kernel/fiasco/src/lib/minilibc/arm/include/limits.h new file mode 100644 index 00000000..05b1ffde --- /dev/null +++ b/kernel/fiasco/src/lib/minilibc/arm/include/limits.h @@ -0,0 +1,62 @@ +#ifndef _LIMITS_H +#define _LIMITS_H + +//#include + +#define CHAR_BIT 8 + +#define SCHAR_MIN (-128) +#define SCHAR_MAX 0x7f +#define UCHAR_MAX 0xff + +#define SHRT_MIN (-SHRT_MAX-1) +#define SHRT_MAX 0x7fff +#define USHRT_MAX 0xffff + +#define INT_MIN (-INT_MAX-1) +#define INT_MAX 0x7fffffff +#define UINT_MAX 0xffffffff + +#if __WORDSIZE == 64 +#define LONG_MAX 9223372036854775807L +#define ULONG_MAX 18446744073709551615UL +#else +#define LONG_MAX 2147483647L +#define ULONG_MAX 4294967295UL +#endif +#define LONG_MIN (-LONG_MAX - 1L) + +#define LLONG_MAX 9223372036854775807LL +#define LLONG_MIN (-LLONG_MAX - 1LL) + +/* Maximum value an `unsigned long long int' can hold. (Minimum is 0.) */ +#define ULLONG_MAX 18446744073709551615ULL +#define ULONG_LONG_MAX ULLONG_MAX + +#define SSIZE_MIN INT_MIN +#define SSIZE_MAX INT_MAX + +#define PASS_MAX 256 + +#define NR_OPEN 1024 + +#define NGROUPS_MAX 32 /* supplemental group IDs are available */ +#define ARG_MAX 131072 /* # bytes of args + environ for exec() */ +#define CHILD_MAX 999 /* no limit :-) */ +#define OPEN_MAX 256 /* # open files a process may have */ +#define LINK_MAX 127 /* # links a file may have */ +#define MAX_CANON 255 /* size of the canonical input queue */ +#define MAX_INPUT 255 /* size of the type-ahead buffer */ +#define NAME_MAX 255 /* # chars in a file name */ +#define PATH_MAX 4095 /* # chars in a path name */ +#define PIPE_BUF 4096 /* # bytes in atomic write to a pipe */ + +#define RTSIG_MAX 32 + +#define LINE_MAX 2048 + +/* mutt demanded these */ +#define _POSIX_PATH_MAX PATH_MAX +#define MB_LEN_MAX 16 + +#endif diff --git a/kernel/fiasco/src/lib/minilibc/arm/include/setjmp.h b/kernel/fiasco/src/lib/minilibc/arm/include/setjmp.h new file mode 100644 index 00000000..54c7f815 --- /dev/null +++ b/kernel/fiasco/src/lib/minilibc/arm/include/setjmp.h @@ -0,0 +1,30 @@ +#ifndef _SETJMP_H +#define _SETJMP_H + +#include + +#define __JMP_BUF_SP 8 +#ifndef __ASSEMBLER__ +typedef int __jmp_buf[10]; +#endif + +#ifndef __ASSEMBLER__ + +typedef struct __jmp_buf_struct { + __jmp_buf __jmpbuf; +} jmp_buf[1]; + + +__BEGIN_DECLS + +void longjmp (jmp_buf __env, int __val) + __attribute__ ((__noreturn__)); + +int setjmp(jmp_buf env); + +__END_DECLS + + +#endif /* ASEMBLER */ + +#endif diff --git a/kernel/fiasco/src/lib/minilibc/arm/setjmp.S b/kernel/fiasco/src/lib/minilibc/arm/setjmp.S new file mode 100644 index 00000000..1bce492c --- /dev/null +++ b/kernel/fiasco/src/lib/minilibc/arm/setjmp.S @@ -0,0 +1,22 @@ +#include + +.text +.weak setjmp +.type setjmp,function +setjmp: +.global __setjmp +.type __setjmp,function +__setjmp: + @mov r1, #0 + stmia r0, {r4-r11, sp, lr} + mov r0, #0 /* skipped on longjmp */ + mov pc, lr + +.text +.global longjmp +.type longjmp,function +longjmp: + mov ip, r0 + movs r0, r1 + moveq r0, #1 + ldmia ip, {r4-r11, sp, pc} diff --git a/kernel/fiasco/src/lib/minilibc/atexit.c b/kernel/fiasco/src/lib/minilibc/atexit.c new file mode 100644 index 00000000..a0f3a8c0 --- /dev/null +++ b/kernel/fiasco/src/lib/minilibc/atexit.c @@ -0,0 +1,54 @@ +#include + +typedef struct +{ + void (*func)(void*, int); + void *arg; +} atexit_t; + +#define NUM_ATEXIT 80 + +static atexit_t __atexitlist[NUM_ATEXIT]; +static int atexit_counter; + +int +atexit(void (*func)(void)) +{ + if (atexit_counter >= NUM_ATEXIT) + return -1; + + __atexitlist[atexit_counter].func = (void(*)(void*, int))func; + __atexitlist[atexit_counter].arg = 0; + atexit_counter++; + return 0; +} + +int +__cxa_atexit(void (*func)(void*), void *arg, void *dso_handle) +{ + if (atexit_counter>=NUM_ATEXIT) + return -1; + + __atexitlist[atexit_counter].func = (void(*)(void*, int))func; + __atexitlist[atexit_counter].arg = arg; + (void)dso_handle; + atexit_counter++; + return 0; +} + +int +__aeabi_atexit (void *arg, void (*func)(void*), void *dso_handle) +{ + return __cxa_atexit(func, arg, dso_handle); +} + +void exit(int code) +{ + while (atexit_counter) + { + atexit_t *a = __atexitlist + (--atexit_counter); + if (a->func) + a->func(a->arg, code); + } + _exit(code); +} diff --git a/kernel/fiasco/src/lib/minilibc/fprintf.c b/kernel/fiasco/src/lib/minilibc/fprintf.c new file mode 100644 index 00000000..9f6b3c34 --- /dev/null +++ b/kernel/fiasco/src/lib/minilibc/fprintf.c @@ -0,0 +1,15 @@ +#include +#include + +int fprintf(FILE *stream, const char *format, ...) +{ + int n; + va_list args; + + va_start (args, format); + n = vprintf (format, args); + va_end (args); + + return n; +} + diff --git a/kernel/fiasco/src/lib/minilibc/getchar.c b/kernel/fiasco/src/lib/minilibc/getchar.c new file mode 100644 index 00000000..7b5d06cb --- /dev/null +++ b/kernel/fiasco/src/lib/minilibc/getchar.c @@ -0,0 +1,12 @@ +#include +#include "libc_backend.h" + + +int getchar() +{ + char s; + if(__libc_backend_ins(&s,1)) + return s; + else + return 0; +} diff --git a/kernel/fiasco/src/lib/minilibc/gets.c b/kernel/fiasco/src/lib/minilibc/gets.c new file mode 100644 index 00000000..aad113dc --- /dev/null +++ b/kernel/fiasco/src/lib/minilibc/gets.c @@ -0,0 +1,13 @@ +#include +#include + + +char *gets(char *s) +{ + if(s!=NULL) { + size_t num; + num = __libc_backend_ins(s,(size_t)-1); + s[num-1]=0; + } + return s; +} diff --git a/kernel/fiasco/src/lib/minilibc/ia32/include/limits.h b/kernel/fiasco/src/lib/minilibc/ia32/include/limits.h new file mode 100644 index 00000000..05b1ffde --- /dev/null +++ b/kernel/fiasco/src/lib/minilibc/ia32/include/limits.h @@ -0,0 +1,62 @@ +#ifndef _LIMITS_H +#define _LIMITS_H + +//#include + +#define CHAR_BIT 8 + +#define SCHAR_MIN (-128) +#define SCHAR_MAX 0x7f +#define UCHAR_MAX 0xff + +#define SHRT_MIN (-SHRT_MAX-1) +#define SHRT_MAX 0x7fff +#define USHRT_MAX 0xffff + +#define INT_MIN (-INT_MAX-1) +#define INT_MAX 0x7fffffff +#define UINT_MAX 0xffffffff + +#if __WORDSIZE == 64 +#define LONG_MAX 9223372036854775807L +#define ULONG_MAX 18446744073709551615UL +#else +#define LONG_MAX 2147483647L +#define ULONG_MAX 4294967295UL +#endif +#define LONG_MIN (-LONG_MAX - 1L) + +#define LLONG_MAX 9223372036854775807LL +#define LLONG_MIN (-LLONG_MAX - 1LL) + +/* Maximum value an `unsigned long long int' can hold. (Minimum is 0.) */ +#define ULLONG_MAX 18446744073709551615ULL +#define ULONG_LONG_MAX ULLONG_MAX + +#define SSIZE_MIN INT_MIN +#define SSIZE_MAX INT_MAX + +#define PASS_MAX 256 + +#define NR_OPEN 1024 + +#define NGROUPS_MAX 32 /* supplemental group IDs are available */ +#define ARG_MAX 131072 /* # bytes of args + environ for exec() */ +#define CHILD_MAX 999 /* no limit :-) */ +#define OPEN_MAX 256 /* # open files a process may have */ +#define LINK_MAX 127 /* # links a file may have */ +#define MAX_CANON 255 /* size of the canonical input queue */ +#define MAX_INPUT 255 /* size of the type-ahead buffer */ +#define NAME_MAX 255 /* # chars in a file name */ +#define PATH_MAX 4095 /* # chars in a path name */ +#define PIPE_BUF 4096 /* # bytes in atomic write to a pipe */ + +#define RTSIG_MAX 32 + +#define LINE_MAX 2048 + +/* mutt demanded these */ +#define _POSIX_PATH_MAX PATH_MAX +#define MB_LEN_MAX 16 + +#endif diff --git a/kernel/fiasco/src/lib/minilibc/ia32/include/memcpy.h b/kernel/fiasco/src/lib/minilibc/ia32/include/memcpy.h new file mode 100644 index 00000000..15293725 --- /dev/null +++ b/kernel/fiasco/src/lib/minilibc/ia32/include/memcpy.h @@ -0,0 +1,24 @@ +#ifndef MLC_MEMCPY_H__ +#define MLC_MEMCPY_H__ + +#include +#include + +__BEGIN_DECLS + +extern inline void *memcpy(void *dest, const void *src, size_t n) +{ + unsigned dummy1, dummy2, dummy3; + + asm volatile ("cld \n\t" + "repz movsb %%ds:(%%esi), %%es:(%%edi) \n\t" + : "=c" (dummy1), "=S" (dummy2), "=D" (dummy3) + : "c" (n), "S" (src), "D" (dest) + : "memory"); + return dest; +} + +__END_DECLS + +#endif // MLC_MEMCPY_H__ + diff --git a/kernel/fiasco/src/lib/minilibc/ia32/include/setjmp.h b/kernel/fiasco/src/lib/minilibc/ia32/include/setjmp.h new file mode 100644 index 00000000..b13a8c65 --- /dev/null +++ b/kernel/fiasco/src/lib/minilibc/ia32/include/setjmp.h @@ -0,0 +1,35 @@ +#ifndef _SETJMP_H +#define _SETJMP_H + +#include + + +#ifndef __ASSEMBLER__ +typedef int __jmp_buf[6]; +#endif +# define JB_BX 0 +# define JB_SI 1 +# define JB_DI 2 +# define JB_BP 3 +# define JB_SP 4 +# define JB_PC 5 +# define JB_SIZE 24 + +#ifndef __ASSEMBLER__ + +typedef struct __jmp_buf_struct +{ + __jmp_buf __jmpbuf; +} jmp_buf[1]; + +__BEGIN_DECLS + +void longjmp (jmp_buf __env, int __val) + __attribute__ ((__noreturn__,__regparm__(3))); +int setjmp(jmp_buf env) __attribute__((__regparm__(3))); + +__END_DECLS + +#endif + +#endif diff --git a/kernel/fiasco/src/lib/minilibc/ia32/lltostr.c b/kernel/fiasco/src/lib/minilibc/ia32/lltostr.c new file mode 100644 index 00000000..37f5b176 --- /dev/null +++ b/kernel/fiasco/src/lib/minilibc/ia32/lltostr.c @@ -0,0 +1,34 @@ +#include +#include +#include + +int __lltostr(char *s, int size, unsigned long long i, int base, char UpCase); + +int __lltostr(char *s, int size, unsigned long long i, int base, char UpCase) +{ + char *tmp; + unsigned int j=0; + + s[--size]=0; + tmp=s+size; + if (base==0||base>36) + base=10; + + j=0; + if (!i) + { + *(--tmp)='0'; + j=1; + } + + while (tmp>s && i) + { + tmp--; + if ((*tmp=mod32(i, base)+'0')>'9') + *tmp+=(UpCase?'A':'a')-'9'-1; + i=div32(i, base); + j++; + } + memmove(s,tmp,j+1); + return j; +} diff --git a/kernel/fiasco/src/lib/minilibc/ia32/setjmp.S b/kernel/fiasco/src/lib/minilibc/ia32/setjmp.S new file mode 100644 index 00000000..74a67c22 --- /dev/null +++ b/kernel/fiasco/src/lib/minilibc/ia32/setjmp.S @@ -0,0 +1,43 @@ +#include + +.text +.weak setjmp +.type setjmp,@function +setjmp: +.globl __setjmp +.type __setjmp,@function +__setjmp: + movl %ebx, (JB_BX*4)(%eax) + movl %esi, (JB_SI*4)(%eax) + movl %edi, (JB_DI*4)(%eax) + movl %ebp, (JB_BP*4)(%eax) + leal 4(%esp), %edx /* Save SP as it will be after we return. */ + movl 0(%esp), %ecx /* Save PC we are returning to now. */ + movl %edx, (JB_SP*4)(%eax) + movl %ecx, (JB_PC*4)(%eax) + xor %eax,%eax + ret +.size __setjmp,.-__setjmp; + + + +.text +.global longjmp +.type longjmp,@function +longjmp: + /* eax = User's jmp_buf */ + /* edx = Second argument is return value. */ + movl (JB_PC*4)(%eax), %ecx + movl (JB_BX*4)(%eax), %ebx + movl (JB_SI*4)(%eax), %esi + movl (JB_DI*4)(%eax), %edi + movl (JB_BP*4)(%eax), %ebp + movl (JB_SP*4)(%eax), %esp + movl %edx, %eax + /* From the longjmp manpage: ``If longjmp is invoked with a + * second argument of 0, 1 will be returned instead.'' */ + cmpl $1, %eax + adcl $0, %eax + /* Jump to saved PC. */ + jmp *%ecx +.size longjmp,.-longjmp; diff --git a/kernel/fiasco/src/lib/minilibc/include/alloca.h b/kernel/fiasco/src/lib/minilibc/include/alloca.h new file mode 100644 index 00000000..6c649c9f --- /dev/null +++ b/kernel/fiasco/src/lib/minilibc/include/alloca.h @@ -0,0 +1,13 @@ +#ifndef __MC_ALLOCA__ +#define __MC_ALLOCA__ +#include +#include + +__BEGIN_DECLS + +void *alloca(size_t); + +__END_DECLS + + +#endif //__MC_ALLOCA__ diff --git a/kernel/fiasco/src/lib/minilibc/include/assert.h b/kernel/fiasco/src/lib/minilibc/include/assert.h new file mode 100644 index 00000000..e8e0c840 --- /dev/null +++ b/kernel/fiasco/src/lib/minilibc/include/assert.h @@ -0,0 +1,42 @@ +#ifndef _ASSERT_H +#define _ASSERT_H + +#include +#include + +#if (__GNUC__>=3) +# define ASSERT_EXPECT_FALSE(exp) __builtin_expect((exp), 0) +#else +# define ASSERT_EXPECT_FALSE(exp) (exp) +#endif + +#if defined ASSERT_KDB_KE +# include "kdb_ke.h" +# define assert(expr) \ + do { if (ASSERT_EXPECT_FALSE(!(expr))) \ + kdb_ke(#expr); } while(0) +# define check(expr) assert(expr) +#else +__BEGIN_DECLS +/* This prints an "Assertion failed" message and aborts. */ +void FIASCO_COLD __assert_fail (const char *__assertion, const char *__file, + unsigned int __line, void *ret) + __attribute__ ((__noreturn__)); + +__END_DECLS + + +/* We don't show information about the current function since it needs + * additional space -- especially with gcc-2.95. The function name + * can be found by searching the EIP in the kernel image. */ +# undef assert +# ifdef NDEBUG +# define assert(expr) do {} while (0) +# define check(expr) (void)(expr) +# else +# define assert(expr) \ + do { if (ASSERT_EXPECT_FALSE(!(expr))) __assert_fail (#expr, __FILE__, __LINE__, __builtin_return_address(0)); } while (0) +# endif +#endif + +#endif diff --git a/kernel/fiasco/src/lib/minilibc/include/cassert b/kernel/fiasco/src/lib/minilibc/include/cassert new file mode 100644 index 00000000..d980043f --- /dev/null +++ b/kernel/fiasco/src/lib/minilibc/include/cassert @@ -0,0 +1,8 @@ +/* -*- c++ -*- */ + +#ifndef CASSERT_INCLUDE +#define CASSERT_INCLUDE + +#include + +#endif // CASSERT_INCLUDE diff --git a/kernel/fiasco/src/lib/minilibc/include/cctype b/kernel/fiasco/src/lib/minilibc/include/cctype new file mode 100644 index 00000000..5c771a1c --- /dev/null +++ b/kernel/fiasco/src/lib/minilibc/include/cctype @@ -0,0 +1,27 @@ +/* -*- c++ -*- */ + +#ifndef CCTYPES_INCLUDE +#define CCTYPES_INCLUDE + +#include +namespace std { + +#if(__GNUC__>=3) + using ::isalnum; + using ::isalpha; + using ::isdigit; + using ::isgraph; + using ::islower; + using ::isprint; + using ::ispunct; + using ::isspace; + using ::isupper; + using ::isxdigit; + using ::tolower; + using ::toupper; +#endif + +}; + +#endif // CCTYPES_INCLUDE + diff --git a/kernel/fiasco/src/lib/minilibc/include/cdefs.h b/kernel/fiasco/src/lib/minilibc/include/cdefs.h new file mode 100644 index 00000000..b9fc187f --- /dev/null +++ b/kernel/fiasco/src/lib/minilibc/include/cdefs.h @@ -0,0 +1,13 @@ +#ifndef __CDEFS_H__ +#define __CDEFS_H__ + +#ifndef __cplusplus +#define __BEGIN_DECLS +#define __END_DECLS +#else +#define __BEGIN_DECLS extern "C" { +#define __END_DECLS } +#endif + + +#endif // __CDEFS_H__ diff --git a/kernel/fiasco/src/lib/minilibc/include/climits b/kernel/fiasco/src/lib/minilibc/include/climits new file mode 100644 index 00000000..0e927985 --- /dev/null +++ b/kernel/fiasco/src/lib/minilibc/include/climits @@ -0,0 +1,10 @@ +/* -*- c++ -*- */ + +#ifndef CLIMITS_INCLUDE +#define CLIMITS_INCLUDE + +#include + +#endif //CLIMITS_INCLUDE + + diff --git a/kernel/fiasco/src/lib/minilibc/include/csetjmp b/kernel/fiasco/src/lib/minilibc/include/csetjmp new file mode 100644 index 00000000..edd786d7 --- /dev/null +++ b/kernel/fiasco/src/lib/minilibc/include/csetjmp @@ -0,0 +1,21 @@ +/* -*- c++ -*- */ + +#ifndef CSETJMP_INCLUDE +#define CSETJMP_INCLUDE + +#include + + +namespace std { + +#if(__GNUC__>=3) + using ::jmp_buf; + using ::longjmp; + using ::setjmp; +#endif +}; + + + +#endif // CSETJMP_INCLUDE + diff --git a/kernel/fiasco/src/lib/minilibc/include/cstdarg b/kernel/fiasco/src/lib/minilibc/include/cstdarg new file mode 100644 index 00000000..1729e484 --- /dev/null +++ b/kernel/fiasco/src/lib/minilibc/include/cstdarg @@ -0,0 +1,21 @@ +/* -*- c++ -*- */ + +#ifndef CSTDARG_INCLUDE +#define CSTDARG_INCLUDE + +#include + + +namespace std { + +#if(__GNUC__>=3) + + using ::va_list; + +#endif + +}; + + + +#endif // CSTDARG_INCLUDE diff --git a/kernel/fiasco/src/lib/minilibc/include/cstddef b/kernel/fiasco/src/lib/minilibc/include/cstddef new file mode 100644 index 00000000..bc5e0d2a --- /dev/null +++ b/kernel/fiasco/src/lib/minilibc/include/cstddef @@ -0,0 +1,20 @@ +/* -*- c++ -*- */ + +#ifndef CSTDDEF_INCLUDE +#define CSTDDEF_INCLUDE + +#include + +namespace std { + +#if(__GNUC__>=3) + + using ::ptrdiff_t; + using ::size_t; + +#endif + +}; + + +#endif // CSTDDEF_INCLUDE diff --git a/kernel/fiasco/src/lib/minilibc/include/cstdio b/kernel/fiasco/src/lib/minilibc/include/cstdio new file mode 100644 index 00000000..b5c10955 --- /dev/null +++ b/kernel/fiasco/src/lib/minilibc/include/cstdio @@ -0,0 +1,22 @@ +/* -*- c++ -*-*/ + +#ifndef CSTDIO_INCLUDE +#define CSTDIO_INCLUDE + +#include + +#if(__GNUC__>=3) +namespace std { + using ::putchar; + using ::puts; + using ::printf; + using ::sprintf; + using ::snprintf; + using ::vprintf; + using ::vsprintf; + using ::vsnprintf; +}; +#endif + + +#endif // CSTDIO_INCLUDE diff --git a/kernel/fiasco/src/lib/minilibc/include/cstdlib b/kernel/fiasco/src/lib/minilibc/include/cstdlib new file mode 100644 index 00000000..be0e690d --- /dev/null +++ b/kernel/fiasco/src/lib/minilibc/include/cstdlib @@ -0,0 +1,48 @@ +/* -*- c++ -*- */ + +#ifndef CSTDLIB_INCLUDE +#define CSTDLIB_INCLUDE + +#include + + +namespace std { + +#if(__GNUC__>=3) + + using ::atexit; + using ::abs; + using ::labs; + using ::div_t; + using ::ldiv_t; + using ::lldiv_t; + using ::div; + using ::ldiv; + using ::lldiv; + using ::exit; + using ::abort; + using ::atoi; + using ::atol; + using ::atof; + using ::strtoul; + using ::strtol; + +#endif + + inline long + abs(long i) { return labs(i); } + + inline long long + abs(long long i) { return llabs(i); } + + inline ldiv_t + div( long i, long j ) { return ldiv(i,j); } + + inline lldiv_t + div( long long i, long long j ) { return lldiv(i,j); } + +}; + + + +#endif // CSTDLIB_INCLUDE diff --git a/kernel/fiasco/src/lib/minilibc/include/cstring b/kernel/fiasco/src/lib/minilibc/include/cstring new file mode 100644 index 00000000..5350932e --- /dev/null +++ b/kernel/fiasco/src/lib/minilibc/include/cstring @@ -0,0 +1,73 @@ +/* -*- c++ -*- */ + +#ifndef CSTRING_INCLUDE +#define CSTRING_INCLUDE + +#include + + +namespace std { +#if(__GNUC__>=3) + + // gcc pre 3.0 treats std:: as :: + // so the following usings produce + // already defined errors + + using ::memcpy; + using ::memccpy; + using ::memmove; + using ::memccmp; + using ::memcmp; + using ::memset; + using ::memchr; + + + using ::strcpy; + using ::strncpy; + using ::strcat; + using ::strncat; + using ::strcmp; + using ::strncmp; + using ::strlen; + using ::strspn; + using ::strcspn; + using ::strcoll; + + + using ::strpbrk; + using ::strrchr; + using ::strchr; + using ::strstr; + + + // gcc pre 3.0 also don't know the __builtin_xxx + // functions + + inline char* + strpbrk(char* __s1, const char* __s2) + { return __builtin_strpbrk(const_cast(__s1), __s2); } + + + + inline char* + strrchr(char* __s1, int __n) + { return __builtin_strrchr(const_cast(__s1), __n); } + + + + inline char* + strchr(char* __s1, int __n) + { return __builtin_strchr(const_cast(__s1), __n); } + + + + inline char* + strstr(char* __s1, const char* __s2) + { return __builtin_strstr(const_cast(__s1), __s2); } + +#endif + +}; + + +#endif diff --git a/kernel/fiasco/src/lib/minilibc/include/ctype.h b/kernel/fiasco/src/lib/minilibc/include/ctype.h new file mode 100644 index 00000000..5ec2ba8f --- /dev/null +++ b/kernel/fiasco/src/lib/minilibc/include/ctype.h @@ -0,0 +1,32 @@ +#ifndef _CTYPE_H +#define _CTYPE_H + +#include + +__BEGIN_DECLS + +int isascii (int c) __attribute__ ((__const__)); +int isblank (int c) __attribute__ ((__const__)); +int isalnum (int c) __attribute__ ((__const__)); +int isalpha (int c) __attribute__ ((__const__)); +int isdigit (int c) __attribute__ ((__const__)); +int isspace (int c) __attribute__ ((__const__)); + +int isupper (int c) __attribute__ ((__const__)); +int islower (int c) __attribute__ ((__const__)); + +int tolower(int c) __attribute__ ((__const__)); +int toupper(int c) __attribute__ ((__const__)); + +int isprint(int c) __attribute__ ((__const__)); +int ispunct(int c) __attribute__ ((__const__)); +int iscntrl(int c) __attribute__ ((__const__)); + +/* fscking GNU extensions! */ +int isxdigit(int c) __attribute__ ((__const__)); + +int isgraph(int c) __attribute__ ((__const__)); + +__END_DECLS + +#endif diff --git a/kernel/fiasco/src/lib/minilibc/include/errno.h b/kernel/fiasco/src/lib/minilibc/include/errno.h new file mode 100644 index 00000000..03703581 --- /dev/null +++ b/kernel/fiasco/src/lib/minilibc/include/errno.h @@ -0,0 +1,8 @@ +#ifndef _ERRNO_H +#define _ERRNO_H + +#define EIO 5 /* I/O error */ +#define ENOMEM 12 /* Out of memory */ +#define EINVAL 22 /* Invalid argument */ + +#endif diff --git a/kernel/fiasco/src/lib/minilibc/include/malloc.h b/kernel/fiasco/src/lib/minilibc/include/malloc.h new file mode 100644 index 00000000..b4e3f033 --- /dev/null +++ b/kernel/fiasco/src/lib/minilibc/include/malloc.h @@ -0,0 +1,12 @@ +#pragma once + +/* The intention of this file is to make libdiasm happy */ + +#include +#include + +__BEGIN_DECLS + +void *malloc(size_t size); + +__END_DECLS diff --git a/kernel/fiasco/src/lib/minilibc/include/memcpy.h b/kernel/fiasco/src/lib/minilibc/include/memcpy.h new file mode 100644 index 00000000..18484d0f --- /dev/null +++ b/kernel/fiasco/src/lib/minilibc/include/memcpy.h @@ -0,0 +1,14 @@ +#ifndef MLC_MEMCPY_H__ +#define MLC_MEMCPY_H__ + +#include +#include + +__BEGIN_DECLS + +void *memcpy(void *dest, const void *src, size_t n); + +__END_DECLS + +#endif // MLC_MEMCPY_H__ + diff --git a/kernel/fiasco/src/lib/minilibc/include/mini_defs.h b/kernel/fiasco/src/lib/minilibc/include/mini_defs.h new file mode 100644 index 00000000..e6f19872 --- /dev/null +++ b/kernel/fiasco/src/lib/minilibc/include/mini_defs.h @@ -0,0 +1,12 @@ +#ifndef MINIDEFS_INCLUDE +#define MINIDEFS_INCLUDE + +#if(__GNUC__ >= 3) +# define MARK_DEPRECATED __attribute__((deprecated)) +#else +# define MARK_DEPRECATED /*empty*/ +#endif + + + +#endif // MINIDEFS_INCLUDE diff --git a/kernel/fiasco/src/lib/minilibc/include/panic.h b/kernel/fiasco/src/lib/minilibc/include/panic.h new file mode 100644 index 00000000..13e912b4 --- /dev/null +++ b/kernel/fiasco/src/lib/minilibc/include/panic.h @@ -0,0 +1,15 @@ +#ifndef PANIC_H +#define PANIC_H + +#include +#include + +__BEGIN_DECLS + +void FIASCO_COLD panic (const char *format, ...) + __attribute__ ((__noreturn__)) + __attribute__ ((format(printf, 1, 2))); + +__END_DECLS + +#endif diff --git a/kernel/fiasco/src/lib/minilibc/include/simpleio.h b/kernel/fiasco/src/lib/minilibc/include/simpleio.h new file mode 100644 index 00000000..d40027ca --- /dev/null +++ b/kernel/fiasco/src/lib/minilibc/include/simpleio.h @@ -0,0 +1,14 @@ +#ifndef _SIMPLEIO_H +#define _SIMPLEIO_H + +#include +#include + +__BEGIN_DECLS + +int FIASCO_COLD putstr(const char *const s); +int FIASCO_COLD putnstr(const char *const c, int len); + +__END_DECLS + +#endif diff --git a/kernel/fiasco/src/lib/minilibc/include/stdio.h b/kernel/fiasco/src/lib/minilibc/include/stdio.h new file mode 100644 index 00000000..8a8aec3b --- /dev/null +++ b/kernel/fiasco/src/lib/minilibc/include/stdio.h @@ -0,0 +1,33 @@ +#ifndef _STDIO_H +#define _STDIO_H + +#include +#include +#include +#include + +__BEGIN_DECLS + +int FIASCO_COLD putchar(int c); +int FIASCO_COLD puts(const char *s); +int FIASCO_COLD printf(const char *format, ...) + __attribute__((format(printf,1,2))); +int FIASCO_COLD sprintf(char *str, const char *format, ...) + __attribute__((format(printf,2,3))); +int FIASCO_COLD snprintf(char *str, size_t size, const char *format, ...) + __attribute__((format(printf,3,4))); + +#include + +int FIASCO_COLD vprintf(const char *format, va_list ap) + __attribute__((format(printf,1,0))); +int FIASCO_COLD vsprintf(char *str, const char *format, va_list ap) + __attribute__((format(printf,2,0))); +int FIASCO_COLD vsnprintf(char *str, size_t size, const char *format, va_list ap) + __attribute__((format(printf,3,0))); + +typedef int *FILE; + +__END_DECLS + +#endif diff --git a/kernel/fiasco/src/lib/minilibc/include/stdlib.h b/kernel/fiasco/src/lib/minilibc/include/stdlib.h new file mode 100644 index 00000000..0cfe24cd --- /dev/null +++ b/kernel/fiasco/src/lib/minilibc/include/stdlib.h @@ -0,0 +1,52 @@ +#ifndef _STDLIB_H +#define _STDLIB_H + +#include +#include + +__BEGIN_DECLS + +int atexit(void (*function)(void)); + +long int strtol(const char *nptr, char **endptr, int base); +unsigned long int strtoul(const char *nptr, char **endptr, int base); + +extern int __ltostr(char *s, unsigned int size, unsigned long i, unsigned int base, int UpCase); +extern int __dtostr(double d,char *buf,unsigned int maxlen,unsigned int prec); + +#ifndef __STRICT_ANSI__ +__extension__ long long int strtoll(const char *nptr, char **endptr, int base); +__extension__ unsigned long long int strtoull(const char *nptr, char **endptr, int base); +__extension__ int __lltostr(char *s, unsigned int size, unsigned long long i, unsigned int base, int UpCase); +#endif + +int atoi(const char *nptr); +long int atol(const char *nptr); +double atof(const char *nptr); + +#define EXIT_FAILURE 1 +#define EXIT_SUCCESS 0 + +void _exit(int status) __attribute__((noreturn)); +void exit(int status) __attribute__((noreturn)); +void abort(void); + +/* warning: the rand() implementation of the diet libc really sucks. */ +#define RAND_MAX 32767 + +typedef struct { int quot,rem; } div_t; +div_t div(int numer, int denom) __attribute__((const)); + +typedef struct { long int quot,rem; } ldiv_t; +ldiv_t ldiv(long int numer, long int denom) __attribute__((const)); + +typedef struct { long long int quot,rem; } lldiv_t; +lldiv_t lldiv(long long int numer, long long int denom) __attribute__((const)); + +int abs(int i) __attribute__((const)); +long int labs(long int i) __attribute__((const)); +__extension__ long long int llabs(long long int i) __attribute__((const)); + +__END_DECLS + +#endif diff --git a/kernel/fiasco/src/lib/minilibc/include/string.h b/kernel/fiasco/src/lib/minilibc/include/string.h new file mode 100644 index 00000000..61c9ce2f --- /dev/null +++ b/kernel/fiasco/src/lib/minilibc/include/string.h @@ -0,0 +1,56 @@ +#ifndef _STRING_H +#define _STRING_H + +#include +#include + +#include + +__BEGIN_DECLS + +char *strcpy(char *dest, const char *src); +char *strncpy(char *dest, const char *src, size_t n); + +void *memccpy(void *dest, const void *src, int c, size_t n); +void *memmove(void *dest, const void *src, size_t n); + +int memccmp(const void *s1, const void *s2, int c, size_t n); +int memcmp(const void *s1, const void *s2, size_t n); +int strcmp(const char *s1, const char *s2); +int strncmp(const char *s1, const char *s2, size_t n); + +int strcasecmp(const char *s1, const char *s2); +int strncasecmp(const char *s1, const char *s2, size_t n); + +#if (__GNUC__>=3) +size_t strlen(const char *s) __attribute__((pure)); +#else +size_t strlen(const char *s); +#endif + +char *strstr(const char *haystack, const char *needle); + +char *strdup(const char *s); + +char *strchr(const char *s, int c); +char *strrchr(const char *s, int c); + +char *strcat(char *dest, const char *src); +char *strncat(char *dest, const char *src, size_t n); + +size_t strspn(const char *s, const char *_accept); +size_t strcspn(const char *s, const char *reject); + +char *strpbrk(const char *s, const char *_accept); +char *strsep(char **stringp, const char *delim); + +void* memset(void *s, int c, size_t n); +void* memchr(const void *s, int c, size_t n); + +int strcoll(const char *s1, const char *s2); + + +__END_DECLS + + +#endif diff --git a/kernel/fiasco/src/lib/minilibc/isalnum.c b/kernel/fiasco/src/lib/minilibc/isalnum.c new file mode 100644 index 00000000..3192cc20 --- /dev/null +++ b/kernel/fiasco/src/lib/minilibc/isalnum.c @@ -0,0 +1,9 @@ +#include + +int __isalnum_ascii ( int ch ); +int __isalnum_ascii ( int ch ) { + return (unsigned int)((ch | 0x20) - 'a') < 26u || + (unsigned int)( ch - '0') < 10u; +} + +int isalnum ( int ch ) __attribute__((weak,alias("__isalnum_ascii"))); diff --git a/kernel/fiasco/src/lib/minilibc/isalpha.c b/kernel/fiasco/src/lib/minilibc/isalpha.c new file mode 100644 index 00000000..efd8b194 --- /dev/null +++ b/kernel/fiasco/src/lib/minilibc/isalpha.c @@ -0,0 +1,8 @@ +#include + +int __isalpha_ascii ( int ch ); +int __isalpha_ascii ( int ch ) { + return (unsigned int)((ch | 0x20) - 'a') < 26u; +} + +int isalpha ( int ch ) __attribute__((weak,alias("__isalpha_ascii"))); diff --git a/kernel/fiasco/src/lib/minilibc/isascii.c b/kernel/fiasco/src/lib/minilibc/isascii.c new file mode 100644 index 00000000..57a23ba4 --- /dev/null +++ b/kernel/fiasco/src/lib/minilibc/isascii.c @@ -0,0 +1,6 @@ +#include + +int isascii ( int ch ) +{ + return (unsigned int)ch < 128u; +} diff --git a/kernel/fiasco/src/lib/minilibc/isblank.c b/kernel/fiasco/src/lib/minilibc/isblank.c new file mode 100644 index 00000000..f13ca304 --- /dev/null +++ b/kernel/fiasco/src/lib/minilibc/isblank.c @@ -0,0 +1,6 @@ +#include + +int isblank ( int ch ) +{ + return ch == ' ' || ch == '\t'; +} diff --git a/kernel/fiasco/src/lib/minilibc/iscntrl.c b/kernel/fiasco/src/lib/minilibc/iscntrl.c new file mode 100644 index 00000000..98dbae6f --- /dev/null +++ b/kernel/fiasco/src/lib/minilibc/iscntrl.c @@ -0,0 +1,8 @@ +#include + +int __iscntrl_ascii ( int ch ); +int __iscntrl_ascii ( int ch ) { + return (unsigned int)ch < 32u || ch == 127; +} + +int iscntrl ( int ch ) __attribute__((weak,alias("__iscntrl_ascii"))); diff --git a/kernel/fiasco/src/lib/minilibc/isdigit.c b/kernel/fiasco/src/lib/minilibc/isdigit.c new file mode 100644 index 00000000..d04d281a --- /dev/null +++ b/kernel/fiasco/src/lib/minilibc/isdigit.c @@ -0,0 +1,8 @@ +#include + +int __isdigit_ascii ( int ch ); +int __isdigit_ascii ( int ch ) { + return (unsigned int)(ch - '0') < 10u; +} + +int isdigit ( int ch ) __attribute__((weak,alias("__isdigit_ascii"))); diff --git a/kernel/fiasco/src/lib/minilibc/isgraph.c b/kernel/fiasco/src/lib/minilibc/isgraph.c new file mode 100644 index 00000000..83419e78 --- /dev/null +++ b/kernel/fiasco/src/lib/minilibc/isgraph.c @@ -0,0 +1,6 @@ +int __isgraph_ascii ( int ch ); +int __isgraph_ascii ( int ch ) { + return (unsigned int)(ch - '!') < 127u - '!'; +} + +int isgraph ( int ch ) __attribute__((weak,alias("__isgraph_ascii"))); diff --git a/kernel/fiasco/src/lib/minilibc/islower.c b/kernel/fiasco/src/lib/minilibc/islower.c new file mode 100644 index 00000000..8d219c43 --- /dev/null +++ b/kernel/fiasco/src/lib/minilibc/islower.c @@ -0,0 +1,8 @@ +#include + +int __islower_ascii ( int ch ); +int __islower_ascii ( int ch ) { + return (unsigned int) (ch - 'a') < 26u; +} + +int islower ( int ch ) __attribute__((weak,alias("__islower_ascii"))); diff --git a/kernel/fiasco/src/lib/minilibc/isprint.c b/kernel/fiasco/src/lib/minilibc/isprint.c new file mode 100644 index 00000000..51ff5b6e --- /dev/null +++ b/kernel/fiasco/src/lib/minilibc/isprint.c @@ -0,0 +1,7 @@ + +int __isprint_ascii ( int ch ); +int __isprint_ascii ( int ch ) { + return (unsigned int)(ch - ' ') < 127u - ' '; +} + +int isprint ( int ch ) __attribute__((weak,alias("__isprint_ascii"))); diff --git a/kernel/fiasco/src/lib/minilibc/ispunct.c b/kernel/fiasco/src/lib/minilibc/ispunct.c new file mode 100644 index 00000000..8bbfcdb5 --- /dev/null +++ b/kernel/fiasco/src/lib/minilibc/ispunct.c @@ -0,0 +1,9 @@ +#include + +int __ispunct_ascii ( int ch ); +int __ispunct_ascii ( int ch ) +{ + return isprint (ch) && !isalnum (ch) && !isspace (ch); +} + +int ispunct ( int ch ) __attribute__((weak,alias("__ispunct_ascii"))); diff --git a/kernel/fiasco/src/lib/minilibc/isspace.c b/kernel/fiasco/src/lib/minilibc/isspace.c new file mode 100644 index 00000000..bfa46648 --- /dev/null +++ b/kernel/fiasco/src/lib/minilibc/isspace.c @@ -0,0 +1,9 @@ +#include + +int __isspace_ascii ( int ch ); +int __isspace_ascii ( int ch ) +{ + return (unsigned int)(ch - 9) < 5u || ch == ' '; +} + +int isspace ( int ch ) __attribute__((weak,alias("__isspace_ascii"))); diff --git a/kernel/fiasco/src/lib/minilibc/isupper.c b/kernel/fiasco/src/lib/minilibc/isupper.c new file mode 100644 index 00000000..048d4fd6 --- /dev/null +++ b/kernel/fiasco/src/lib/minilibc/isupper.c @@ -0,0 +1,9 @@ +#include + +int __isupper_ascii ( int ch ); +int __isupper_ascii ( int ch ) +{ + return (unsigned int)(ch - 'A') < 26u; +} + +int isupper ( int ch ) __attribute__((weak,alias("__isupper_ascii"))); diff --git a/kernel/fiasco/src/lib/minilibc/isxdigit.c b/kernel/fiasco/src/lib/minilibc/isxdigit.c new file mode 100644 index 00000000..bca8e74a --- /dev/null +++ b/kernel/fiasco/src/lib/minilibc/isxdigit.c @@ -0,0 +1,8 @@ +int __isxdigit_ascii ( int ch ); +int __isxdigit_ascii ( int ch ) +{ + return (unsigned int)( ch - '0') < 10u || + (unsigned int)((ch | 0x20) - 'a') < 6u; +} + +int isxdigit ( int ch ) __attribute__((weak,alias("__isxdigit_ascii"))); diff --git a/kernel/fiasco/src/lib/minilibc/longjmp.c b/kernel/fiasco/src/lib/minilibc/longjmp.c new file mode 100644 index 00000000..628e7f4a --- /dev/null +++ b/kernel/fiasco/src/lib/minilibc/longjmp.c @@ -0,0 +1 @@ +#include diff --git a/kernel/fiasco/src/lib/minilibc/memccpy.c b/kernel/fiasco/src/lib/minilibc/memccpy.c new file mode 100644 index 00000000..12b5e2ec --- /dev/null +++ b/kernel/fiasco/src/lib/minilibc/memccpy.c @@ -0,0 +1,20 @@ +#define _POSIX_SOURCE +#define _XOPEN_SOURCE +#include +#include + +void *memccpy(void *dst, const void *src, int c, size_t count) +{ + char *a = dst; + const char *b = src; + while (count--) + { + *a++ = *b; + if (*b==c) + { + return (void *)a; + } + b++; + } + return 0; +} diff --git a/kernel/fiasco/src/lib/minilibc/memchr.c b/kernel/fiasco/src/lib/minilibc/memchr.c new file mode 100644 index 00000000..c57d5244 --- /dev/null +++ b/kernel/fiasco/src/lib/minilibc/memchr.c @@ -0,0 +1,12 @@ +#include + +void* memchr(const void *s, int c, size_t n) { + register const char* t=s; + int i; + for (i=n; i; --i) { + if (*t==c) + return (char*)t; + ++t; + } + return 0; +} diff --git a/kernel/fiasco/src/lib/minilibc/memcmp.c b/kernel/fiasco/src/lib/minilibc/memcmp.c new file mode 100644 index 00000000..0b86e243 --- /dev/null +++ b/kernel/fiasco/src/lib/minilibc/memcmp.c @@ -0,0 +1,16 @@ +#include + +int memcmp(const void *dst, const void *src, size_t count) { + register int r; + register const char *d=dst; + register const char *s=src; + while (count--) { + if ((r=(*d - *s))) + return r; + ++d; + ++s; + } + return 0; +} + +int bcmp(const char *a,const char *b,size_t c) __attribute__((weak,alias("memcmp"))); diff --git a/kernel/fiasco/src/lib/minilibc/memcpy.c b/kernel/fiasco/src/lib/minilibc/memcpy.c new file mode 100644 index 00000000..a36f8e3c --- /dev/null +++ b/kernel/fiasco/src/lib/minilibc/memcpy.c @@ -0,0 +1,12 @@ +#include + +void* memcpy(void* dst, const void* src, size_t count) { + register char *d=dst; + register const char *s=src; + ++count; /* this actually produces better code than using count-- */ + while (--count) { + *d = *s; + ++d; ++s; + } + return dst; +} diff --git a/kernel/fiasco/src/lib/minilibc/memmove.c b/kernel/fiasco/src/lib/minilibc/memmove.c new file mode 100644 index 00000000..be21a7cb --- /dev/null +++ b/kernel/fiasco/src/lib/minilibc/memmove.c @@ -0,0 +1,24 @@ +#define _POSIX_SOURCE +#define _XOPEN_SOURCE +#include +#include + +void *memmove(void *dst, const void *src, size_t count) +{ + char *a = dst; + const char *b = src; + if (src!=dst) + { + if (src>dst) + { + while (count--) *a++ = *b++; + } + else + { + a+=count-1; + b+=count-1; + while (count--) *a-- = *b--; + } + } + return dst; +} diff --git a/kernel/fiasco/src/lib/minilibc/memset.c b/kernel/fiasco/src/lib/minilibc/memset.c new file mode 100644 index 00000000..55175ae2 --- /dev/null +++ b/kernel/fiasco/src/lib/minilibc/memset.c @@ -0,0 +1,9 @@ +#include + +void * memset(void * dst, int s, size_t count) { + register char * a = dst; + count++; /* this actually creates smaller code than using count-- */ + while (--count) + *a++ = s; + return dst; +} diff --git a/kernel/fiasco/src/lib/minilibc/panic.c b/kernel/fiasco/src/lib/minilibc/panic.c new file mode 100644 index 00000000..fb51f72a --- /dev/null +++ b/kernel/fiasco/src/lib/minilibc/panic.c @@ -0,0 +1,29 @@ +#include +#include +#include +#include +#include +#include "types.h" + +void __attribute__((weak)) +__assert_fail (const char *__assertion, const char *__file, + unsigned int __line, void *ret) +{ + printf("\nAssertion failed: '%s' [ret=%p]\n" + " %s:%i at " L4_PTR_FMT "\n", + __assertion, ret, __file, __line, (Address)__builtin_return_address(0)); + + exit(1); +} + +void __attribute__((weak)) +panic (const char *format, ...) +{ + va_list args; + + va_start (args, format); + vprintf (format, args); + va_end (args); + + exit (EXIT_FAILURE); +} diff --git a/kernel/fiasco/src/lib/minilibc/ppc32/include/limits.h b/kernel/fiasco/src/lib/minilibc/ppc32/include/limits.h new file mode 100644 index 00000000..05b1ffde --- /dev/null +++ b/kernel/fiasco/src/lib/minilibc/ppc32/include/limits.h @@ -0,0 +1,62 @@ +#ifndef _LIMITS_H +#define _LIMITS_H + +//#include + +#define CHAR_BIT 8 + +#define SCHAR_MIN (-128) +#define SCHAR_MAX 0x7f +#define UCHAR_MAX 0xff + +#define SHRT_MIN (-SHRT_MAX-1) +#define SHRT_MAX 0x7fff +#define USHRT_MAX 0xffff + +#define INT_MIN (-INT_MAX-1) +#define INT_MAX 0x7fffffff +#define UINT_MAX 0xffffffff + +#if __WORDSIZE == 64 +#define LONG_MAX 9223372036854775807L +#define ULONG_MAX 18446744073709551615UL +#else +#define LONG_MAX 2147483647L +#define ULONG_MAX 4294967295UL +#endif +#define LONG_MIN (-LONG_MAX - 1L) + +#define LLONG_MAX 9223372036854775807LL +#define LLONG_MIN (-LLONG_MAX - 1LL) + +/* Maximum value an `unsigned long long int' can hold. (Minimum is 0.) */ +#define ULLONG_MAX 18446744073709551615ULL +#define ULONG_LONG_MAX ULLONG_MAX + +#define SSIZE_MIN INT_MIN +#define SSIZE_MAX INT_MAX + +#define PASS_MAX 256 + +#define NR_OPEN 1024 + +#define NGROUPS_MAX 32 /* supplemental group IDs are available */ +#define ARG_MAX 131072 /* # bytes of args + environ for exec() */ +#define CHILD_MAX 999 /* no limit :-) */ +#define OPEN_MAX 256 /* # open files a process may have */ +#define LINK_MAX 127 /* # links a file may have */ +#define MAX_CANON 255 /* size of the canonical input queue */ +#define MAX_INPUT 255 /* size of the type-ahead buffer */ +#define NAME_MAX 255 /* # chars in a file name */ +#define PATH_MAX 4095 /* # chars in a path name */ +#define PIPE_BUF 4096 /* # bytes in atomic write to a pipe */ + +#define RTSIG_MAX 32 + +#define LINE_MAX 2048 + +/* mutt demanded these */ +#define _POSIX_PATH_MAX PATH_MAX +#define MB_LEN_MAX 16 + +#endif diff --git a/kernel/fiasco/src/lib/minilibc/ppc32/include/setjmp.h b/kernel/fiasco/src/lib/minilibc/ppc32/include/setjmp.h new file mode 100644 index 00000000..8ded73c9 --- /dev/null +++ b/kernel/fiasco/src/lib/minilibc/ppc32/include/setjmp.h @@ -0,0 +1,30 @@ +#ifndef _SETJMP_H +#define _SETJMP_H + +#include + +#define __JMP_BUF_SP 8 +#ifndef __ASSEMBLER__ +typedef int __jmp_buf[22]; +#endif + +#ifndef __ASSEMBLER__ + +typedef struct __jmp_buf_struct { + __jmp_buf __jmpbuf; +} jmp_buf[1]; + + +__BEGIN_DECLS + +void longjmp (jmp_buf __env, int __val) + __attribute__ ((__noreturn__)); + +int setjmp(jmp_buf env); + +__END_DECLS + + +#endif /* ASSEMBLER */ + +#endif diff --git a/kernel/fiasco/src/lib/minilibc/ppc32/setjmp.S b/kernel/fiasco/src/lib/minilibc/ppc32/setjmp.S new file mode 100644 index 00000000..4735e96b --- /dev/null +++ b/kernel/fiasco/src/lib/minilibc/ppc32/setjmp.S @@ -0,0 +1,34 @@ +#include + +.text +.weak setjmp +.type setjmp,function +setjmp: +.global __setjmp +.type __setjmp,function +.align 2 +__setjmp: + stw %r1, 0(%r3) + stw %r2, 4(%r3) + mflr %r0 /* link register */ + stw %r0, 8(%r3) + mfcr %r0, /* condition register */ + stw %r0, 12(%r3) + stmw %r14,16(%r3) /*XXX: r14 - r31 may be slow */ + xor %r3, %r3, %r3 /* return 0 */ + blr + +.text +.global longjmp +.type longjmp,function +.align 2 +longjmp: + lwz %r1, 0(%r3) + lwz %r2, 4(%r3) + lwz %r0, 8(%r3) + mtlr %r0 /* link register */ + lwz %r0, 12(%r3) + mfcr %r0 /* condition register */ + lmw %r14,16(%r3) + mr %r3, %r4 /* return val in r4 */ + blr /* branch to link register */ diff --git a/kernel/fiasco/src/lib/minilibc/printf.c b/kernel/fiasco/src/lib/minilibc/printf.c new file mode 100644 index 00000000..1b8643e9 --- /dev/null +++ b/kernel/fiasco/src/lib/minilibc/printf.c @@ -0,0 +1,14 @@ +#include +#include + +int printf (const char *format, ...) { + + int n; + va_list args; + + va_start (args, format); + n = vprintf (format, args); + va_end (args); + + return n; +} diff --git a/kernel/fiasco/src/lib/minilibc/putchar.c b/kernel/fiasco/src/lib/minilibc/putchar.c new file mode 100644 index 00000000..a5d63572 --- /dev/null +++ b/kernel/fiasco/src/lib/minilibc/putchar.c @@ -0,0 +1,11 @@ +#include +#include "libc_backend.h" + +int putchar (int c) +{ + char _c = c; + unsigned long state = __libc_backend_printf_lock(); + int ret = __libc_backend_outs(&_c,1) ? c : 0; + __libc_backend_printf_unlock(state); + return ret; +} diff --git a/kernel/fiasco/src/lib/minilibc/puts.c b/kernel/fiasco/src/lib/minilibc/puts.c new file mode 100644 index 00000000..671134bd --- /dev/null +++ b/kernel/fiasco/src/lib/minilibc/puts.c @@ -0,0 +1,31 @@ +#include +#include +#include "libc_backend.h" + +int puts( const char *c ) +{ + unsigned long state = __libc_backend_printf_lock(); + __libc_backend_outs(c,strlen(c)); + int ret = __libc_backend_outs("\n",1); + __libc_backend_printf_unlock(state); + + return ret; +} + +int putstr( const char *const c ) +{ + unsigned long state = __libc_backend_printf_lock(); + int ret = __libc_backend_outs(c,strlen(c)); + __libc_backend_printf_unlock(state); + + return ret; +} + +int putnstr( const char *const c, int len ) +{ + unsigned long state = __libc_backend_printf_lock(); + int ret = __libc_backend_outs(c,len); + __libc_backend_printf_unlock(state); + + return ret; +} diff --git a/kernel/fiasco/src/lib/minilibc/raise.c b/kernel/fiasco/src/lib/minilibc/raise.c new file mode 100644 index 00000000..24c60466 --- /dev/null +++ b/kernel/fiasco/src/lib/minilibc/raise.c @@ -0,0 +1,16 @@ +/* + * Simple 'raise' implementation required by some gcc versions. + * + * Adam Lackorzynski + */ + +#include + +int raise(int x); + +int raise(int x) +{ + (void)x; + assert(0); + return 0; +} diff --git a/kernel/fiasco/src/lib/minilibc/snprintf.c b/kernel/fiasco/src/lib/minilibc/snprintf.c new file mode 100644 index 00000000..f4031270 --- /dev/null +++ b/kernel/fiasco/src/lib/minilibc/snprintf.c @@ -0,0 +1,13 @@ +#include +#include +#include + +int snprintf(char *str,size_t size,const char *format,...) +{ + int n; + va_list arg_ptr; + va_start(arg_ptr, format); + n=vsnprintf(str,size,format,arg_ptr); + va_end (arg_ptr); + return n; +} diff --git a/kernel/fiasco/src/lib/minilibc/sparc/include/limits.h b/kernel/fiasco/src/lib/minilibc/sparc/include/limits.h new file mode 100644 index 00000000..05b1ffde --- /dev/null +++ b/kernel/fiasco/src/lib/minilibc/sparc/include/limits.h @@ -0,0 +1,62 @@ +#ifndef _LIMITS_H +#define _LIMITS_H + +//#include + +#define CHAR_BIT 8 + +#define SCHAR_MIN (-128) +#define SCHAR_MAX 0x7f +#define UCHAR_MAX 0xff + +#define SHRT_MIN (-SHRT_MAX-1) +#define SHRT_MAX 0x7fff +#define USHRT_MAX 0xffff + +#define INT_MIN (-INT_MAX-1) +#define INT_MAX 0x7fffffff +#define UINT_MAX 0xffffffff + +#if __WORDSIZE == 64 +#define LONG_MAX 9223372036854775807L +#define ULONG_MAX 18446744073709551615UL +#else +#define LONG_MAX 2147483647L +#define ULONG_MAX 4294967295UL +#endif +#define LONG_MIN (-LONG_MAX - 1L) + +#define LLONG_MAX 9223372036854775807LL +#define LLONG_MIN (-LLONG_MAX - 1LL) + +/* Maximum value an `unsigned long long int' can hold. (Minimum is 0.) */ +#define ULLONG_MAX 18446744073709551615ULL +#define ULONG_LONG_MAX ULLONG_MAX + +#define SSIZE_MIN INT_MIN +#define SSIZE_MAX INT_MAX + +#define PASS_MAX 256 + +#define NR_OPEN 1024 + +#define NGROUPS_MAX 32 /* supplemental group IDs are available */ +#define ARG_MAX 131072 /* # bytes of args + environ for exec() */ +#define CHILD_MAX 999 /* no limit :-) */ +#define OPEN_MAX 256 /* # open files a process may have */ +#define LINK_MAX 127 /* # links a file may have */ +#define MAX_CANON 255 /* size of the canonical input queue */ +#define MAX_INPUT 255 /* size of the type-ahead buffer */ +#define NAME_MAX 255 /* # chars in a file name */ +#define PATH_MAX 4095 /* # chars in a path name */ +#define PIPE_BUF 4096 /* # bytes in atomic write to a pipe */ + +#define RTSIG_MAX 32 + +#define LINE_MAX 2048 + +/* mutt demanded these */ +#define _POSIX_PATH_MAX PATH_MAX +#define MB_LEN_MAX 16 + +#endif diff --git a/kernel/fiasco/src/lib/minilibc/sparc/include/setjmp.h b/kernel/fiasco/src/lib/minilibc/sparc/include/setjmp.h new file mode 100644 index 00000000..8ded73c9 --- /dev/null +++ b/kernel/fiasco/src/lib/minilibc/sparc/include/setjmp.h @@ -0,0 +1,30 @@ +#ifndef _SETJMP_H +#define _SETJMP_H + +#include + +#define __JMP_BUF_SP 8 +#ifndef __ASSEMBLER__ +typedef int __jmp_buf[22]; +#endif + +#ifndef __ASSEMBLER__ + +typedef struct __jmp_buf_struct { + __jmp_buf __jmpbuf; +} jmp_buf[1]; + + +__BEGIN_DECLS + +void longjmp (jmp_buf __env, int __val) + __attribute__ ((__noreturn__)); + +int setjmp(jmp_buf env); + +__END_DECLS + + +#endif /* ASSEMBLER */ + +#endif diff --git a/kernel/fiasco/src/lib/minilibc/sparc/setjmp.S b/kernel/fiasco/src/lib/minilibc/sparc/setjmp.S new file mode 100644 index 00000000..84499098 --- /dev/null +++ b/kernel/fiasco/src/lib/minilibc/sparc/setjmp.S @@ -0,0 +1,18 @@ +#include + +.text +.weak setjmp +.type setjmp,function +setjmp: +.global __setjmp +.type __setjmp,function +.align 2 +__setjmp: + ta 1 + +.text +.global longjmp +.type longjmp,function +.align 2 +longjmp: + ta 1 diff --git a/kernel/fiasco/src/lib/minilibc/sprintf.c b/kernel/fiasco/src/lib/minilibc/sprintf.c new file mode 100644 index 00000000..0f3276df --- /dev/null +++ b/kernel/fiasco/src/lib/minilibc/sprintf.c @@ -0,0 +1,13 @@ +#include +#include +#include + +int sprintf(char *dest,const char *format,...) +{ + int n; + va_list arg_ptr; + va_start(arg_ptr, format); + n=vsprintf(dest,format,arg_ptr); + va_end (arg_ptr); + return n; +} diff --git a/kernel/fiasco/src/lib/minilibc/strchr.c b/kernel/fiasco/src/lib/minilibc/strchr.c new file mode 100644 index 00000000..8a40cce8 --- /dev/null +++ b/kernel/fiasco/src/lib/minilibc/strchr.c @@ -0,0 +1,14 @@ +#include + +char *strchr(register const char *t, int c) { + + register char ch; + + ch = c; + for (;;) { + if (*t == ch) break; if (!*t) return 0; ++t; + } + return (char*)t; +} + +char *index(const char *t,int c) __attribute__((weak,alias("strchr"))); diff --git a/kernel/fiasco/src/lib/minilibc/strcmp.c b/kernel/fiasco/src/lib/minilibc/strcmp.c new file mode 100644 index 00000000..1e6ac17b --- /dev/null +++ b/kernel/fiasco/src/lib/minilibc/strcmp.c @@ -0,0 +1,19 @@ + +int strcmp(register const char *s,register const char *t) { + + register char x; + + for (;;) + { + x = *s; + if (x != *t) + break; + if (!x) + break; + ++s; ++t; + } + return ((int)(unsigned int)(unsigned char) x) + - ((int)(unsigned int)(unsigned char) *t); +} + +int strcoll(const char *s,const char* t) __attribute__((weak,alias("strcmp"))); diff --git a/kernel/fiasco/src/lib/minilibc/strcpy.c b/kernel/fiasco/src/lib/minilibc/strcpy.c new file mode 100644 index 00000000..847af4fe --- /dev/null +++ b/kernel/fiasco/src/lib/minilibc/strcpy.c @@ -0,0 +1,10 @@ + +char* strcpy(register char* s,register const char* t) { + + char *dest=s; + + while ((*dest++=*t++)) + ; + + return s; +} diff --git a/kernel/fiasco/src/lib/minilibc/strcspn.c b/kernel/fiasco/src/lib/minilibc/strcspn.c new file mode 100644 index 00000000..a583b324 --- /dev/null +++ b/kernel/fiasco/src/lib/minilibc/strcspn.c @@ -0,0 +1,19 @@ + +#include + +size_t strcspn(const char *s, const char *reject) +{ + size_t l=0; + int a=1; + int i; + int al=strlen(reject); + + while((a)&&(*s)) { + for(i=0;(a)&&(i + +size_t +strlen(const char *s) +{ + register int i; + if (!s) return 0; + for (i=0; *s; ++s) ++i; + return i; +} diff --git a/kernel/fiasco/src/lib/minilibc/strncmp.c b/kernel/fiasco/src/lib/minilibc/strncmp.c new file mode 100644 index 00000000..ed11b74c --- /dev/null +++ b/kernel/fiasco/src/lib/minilibc/strncmp.c @@ -0,0 +1,15 @@ +#include +#include + +int strncmp(const char *s1, const char *s2, size_t n) { + register const char* a=s1; + register const char* b=s2; + register const char* fini=a+n; + while (a + +char *strncpy(char *dest, const char *src, size_t n) +{ + memccpy(dest,src,0,n); + return dest; +} + +char *strxfrm(char *dest, const char* src, size_t n) __attribute__((weak,alias("strncpy"))); diff --git a/kernel/fiasco/src/lib/minilibc/strspn.c b/kernel/fiasco/src/lib/minilibc/strspn.c new file mode 100644 index 00000000..665ced1f --- /dev/null +++ b/kernel/fiasco/src/lib/minilibc/strspn.c @@ -0,0 +1,19 @@ + +#include + +size_t strspn(const char *s, const char *accept) +{ + size_t l=0; + int a=1; + int i; + int al=strlen(accept); + + while((a)&&(*s)) { + for(a=i=0;(!a)&&(i +#include + +char *strstr(const char *haystack, const char *needle) { + size_t nl=strlen(needle); + size_t hl=strlen(haystack); + int i; + if (nl>hl) return 0; + for (i=hl-nl+1; i; --i) { + if (!memcmp(haystack,needle,nl)) + return (char*)haystack; + ++haystack; + } + return 0; +} diff --git a/kernel/fiasco/src/lib/minilibc/strtol.c b/kernel/fiasco/src/lib/minilibc/strtol.c new file mode 100644 index 00000000..c9a581a4 --- /dev/null +++ b/kernel/fiasco/src/lib/minilibc/strtol.c @@ -0,0 +1,29 @@ +#include +#include + +#define ABS_LONG_MIN 2147483648UL + +long int strtol (const char *nptr, char **endptr, int base) { + + int neg = 0; + unsigned long int v; + + while (isspace (*nptr)) + nptr++; + + if (*nptr == '-') { + neg = -1; + ++nptr; + } + + v = strtoul (nptr, endptr, base); + + if (v >= ABS_LONG_MIN) { + if (v == ABS_LONG_MIN && neg) { + return v; + } + return 0; //(neg ? LONG_MIN : LONG_MAX); + } + + return (neg ? -v : v); +} diff --git a/kernel/fiasco/src/lib/minilibc/strtoul.c b/kernel/fiasco/src/lib/minilibc/strtoul.c new file mode 100644 index 00000000..4612c13a --- /dev/null +++ b/kernel/fiasco/src/lib/minilibc/strtoul.c @@ -0,0 +1,40 @@ +#include +#include + +unsigned long int strtoul (const char *nptr, char **endptr, int base) { + + unsigned long int v=0; + + while(isspace(*nptr)) ++nptr; + if (*nptr == '+') ++nptr; + if (base==16 && nptr[0]=='0') goto skip0x; + if (!base) { + if (*nptr=='0') { + base=8; +skip0x: + if (nptr[1]=='x'||nptr[1]=='X') { + nptr+=2; + base=16; + } + } else + base=10; + } + while(*nptr) { + register unsigned char c=*nptr; + c=(c>='a'?c-'a'+10:c>='A'?c-'A'+10:c<='9'?c-'0':0xff); + if (c>=base) break; + { + register unsigned long int w=v << 4;/*=v*base*/; + if(base==8) w = v << 3; + //if(base==16) w = v << 4; + if(base==10) w = (v << 3) + (v << 1); + if (w + +int tolower(int ch) { + if ( (unsigned int)(ch - 'A') < 26u ) + ch += 'a' - 'A'; + return ch; +} + diff --git a/kernel/fiasco/src/lib/minilibc/vprintf.c b/kernel/fiasco/src/lib/minilibc/vprintf.c new file mode 100644 index 00000000..dc924a7b --- /dev/null +++ b/kernel/fiasco/src/lib/minilibc/vprintf.c @@ -0,0 +1,15 @@ +#include +#include + +#include "vprintf_backend.h" +#include "libc_backend.h" + +int vprintf(const char *format, va_list ap) +{ + struct output_op _ap = { 0, (output_func*) &__libc_backend_outs }; + unsigned long state = __libc_backend_printf_lock(); + int ret = __v_printf(&_ap,format,ap); + __libc_backend_printf_unlock(state); + + return ret; +} diff --git a/kernel/fiasco/src/lib/minilibc/vprintf_backend.h b/kernel/fiasco/src/lib/minilibc/vprintf_backend.h new file mode 100644 index 00000000..12002774 --- /dev/null +++ b/kernel/fiasco/src/lib/minilibc/vprintf_backend.h @@ -0,0 +1,21 @@ +#ifndef __VPRINTF_BACKEND_H__ +#define __VPRINTF_BACKEND_H__ + +#include +#include + +typedef int (output_func)(char const *, size_t, void*); + +struct output_op { + void *data; + output_func *put; +}; + +__BEGIN_DECLS + +int __v_printf(struct output_op* fn, const char *format, va_list arg_ptr); + +__END_DECLS + + +#endif // __VPRINTF_BACKEND_H__ diff --git a/kernel/fiasco/src/lib/minilibc/vsnprintf.c b/kernel/fiasco/src/lib/minilibc/vsnprintf.c new file mode 100644 index 00000000..e49bae42 --- /dev/null +++ b/kernel/fiasco/src/lib/minilibc/vsnprintf.c @@ -0,0 +1,31 @@ +#include +#include +#include +#include + +#include "vprintf_backend.h" + +struct str_data { + char* str; + size_t len; + size_t size; +}; + +static int swrite(void*ptr, size_t nmemb, struct str_data* sd) { + size_t tmp=sd->size-sd->len; + if (tmp>0) { + size_t len=nmemb; + if (len>tmp) len=tmp; + memcpy(&sd->str[sd->len],ptr,len); + sd->len+=len; + sd->str[sd->len]=0; + } + return nmemb; +} + +int vsnprintf(char* str, size_t size, const char *format, va_list arg_ptr) { + struct str_data sd = { str, 0, size }; + struct output_op ap = { &sd, (output_func*)&swrite }; + if (size) --sd.size; + return __v_printf(&ap,format,arg_ptr); +} diff --git a/kernel/fiasco/src/lib/minilibc/vsprintf.c b/kernel/fiasco/src/lib/minilibc/vsprintf.c new file mode 100644 index 00000000..e1b197c8 --- /dev/null +++ b/kernel/fiasco/src/lib/minilibc/vsprintf.c @@ -0,0 +1,9 @@ +#include +#include +#include +#include + +int vsprintf(char *dest,const char *format, va_list arg_ptr) +{ + return vsnprintf(dest,(size_t)-1,format,arg_ptr); +} diff --git a/kernel/fiasco/src/lib/perfctr/COPYING b/kernel/fiasco/src/lib/perfctr/COPYING new file mode 100644 index 00000000..b1e3f5a2 --- /dev/null +++ b/kernel/fiasco/src/lib/perfctr/COPYING @@ -0,0 +1,504 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + diff --git a/kernel/fiasco/src/lib/perfctr/event_set.h b/kernel/fiasco/src/lib/perfctr/event_set.h new file mode 100644 index 00000000..570975c4 --- /dev/null +++ b/kernel/fiasco/src/lib/perfctr/event_set.h @@ -0,0 +1,92 @@ +/* $Id: event_set.h 37048 2009-11-12 21:44:56Z adam $ + * Common definitions used when creating event set descriptions. + * + * Copyright (C) 2003 Mikael Pettersson + */ +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) + +#define UM(um) ((void*)&(um).header) + +struct perfctr_unit_mask_header { + unsigned int default_value; + enum perfctr_unit_mask_type type:16; + unsigned short nvalues; +}; + +struct perfctr_unit_mask_0 { + struct perfctr_unit_mask_header header; +}; + +struct perfctr_unit_mask_1 { + struct perfctr_unit_mask_header header; + struct perfctr_unit_mask_value values[1]; +}; + +struct perfctr_unit_mask_2 { + struct perfctr_unit_mask_header header; + struct perfctr_unit_mask_value values[2]; +}; + +struct perfctr_unit_mask_3 { + struct perfctr_unit_mask_header header; + struct perfctr_unit_mask_value values[3]; +}; + +struct perfctr_unit_mask_4 { + struct perfctr_unit_mask_header header; + struct perfctr_unit_mask_value values[4]; +}; + +struct perfctr_unit_mask_5 { + struct perfctr_unit_mask_header header; + struct perfctr_unit_mask_value values[5]; +}; + +struct perfctr_unit_mask_6 { + struct perfctr_unit_mask_header header; + struct perfctr_unit_mask_value values[6]; +}; + +struct perfctr_unit_mask_7 { + struct perfctr_unit_mask_header header; + struct perfctr_unit_mask_value values[7]; +}; + +struct perfctr_unit_mask_8 { + struct perfctr_unit_mask_header header; + struct perfctr_unit_mask_value values[8]; +}; + +struct perfctr_unit_mask_9 { + struct perfctr_unit_mask_header header; + struct perfctr_unit_mask_value values[9]; +}; + +struct perfctr_unit_mask_13 { + struct perfctr_unit_mask_header header; + struct perfctr_unit_mask_value values[13]; +}; + +struct perfctr_unit_mask_15 { + struct perfctr_unit_mask_header header; + struct perfctr_unit_mask_value values[15]; +}; + +extern const struct perfctr_event_set perfctr_p5_event_set; +extern const struct perfctr_event_set perfctr_p5mmx_event_set; +extern const struct perfctr_event_set perfctr_mii_event_set; +extern const struct perfctr_event_set perfctr_wcc6_event_set; +extern const struct perfctr_event_set perfctr_wc2_event_set; +extern const struct perfctr_event_set perfctr_vc3_event_set; +extern const struct perfctr_event_set perfctr_ppro_event_set; +extern const struct perfctr_event_set perfctr_p2_event_set; +extern const struct perfctr_event_set perfctr_p3_event_set; +extern const struct perfctr_event_set perfctr_p4_event_set; +extern const struct perfctr_event_set perfctr_k7_event_set; +extern const struct perfctr_event_set perfctr_k8_event_set; +extern const struct perfctr_event_set perfctr_pentm_event_set; +extern const struct perfctr_event_set perfctr_k8c_event_set; +extern const struct perfctr_event_set perfctr_p4m3_event_set; + +extern const struct perfctr_event_set *perfctr_cpu_event_set(unsigned); + diff --git a/kernel/fiasco/src/lib/perfctr/event_set_amd.c b/kernel/fiasco/src/lib/perfctr/event_set_amd.c new file mode 100644 index 00000000..05c04efd --- /dev/null +++ b/kernel/fiasco/src/lib/perfctr/event_set_amd.c @@ -0,0 +1,600 @@ +/* $Id: event_set_amd.c 37048 2009-11-12 21:44:56Z adam $ + * Performance counter event descriptions for AMD K7 and K8. + * + * Copyright (C) 2003 Mikael Pettersson + * + * References + * ---------- + * "AMD Athlon Processor x86 Code Optimization Guide", + * Appendix D: "Performance Monitoring Counters". + * AMD Publication #22007 + * Revision E (on AMD Processor Technical Documents CD, Med-12/99-0, 21860F) + * Revision K (at http://www.amd.com/). + * + * "BIOS and Kernel Developer's Guide for AMD Athlon 64 and + * AMD Opteron Processors", Chapter 10: "Performance Monitoring". + * AMD Publication #26094, Revision 3.14 (at http://www.amd.com). + + * "Revision Guide for AMD Opteron Processors", + * AMD Publication #25759, Revision 3.09 + */ +#include /* for NULL */ +#include "libperfctr.h" +#include "event_set.h" + +/* + * AMD K7 events. + * + * Note: Different revisions of AMD #22007 list different sets of events. + * We split the K7 event set into an "official" part based on recent + * revisions of #22007, and an "unofficial" part which includes events + * only documented in older revisions of #22007 (specifically Rev. E). + * + * All official K7 events are also present in K8, as are most of the + * unofficial K7 events. + */ + +static const struct perfctr_unit_mask_5 k7_um_moesi = { + { .type = perfctr_um_type_bitmask, + .default_value = 0x1F, + .nvalues = 5 }, + { { 0x10, "Modified (M)" }, + { 0x08, "Owner (O)" }, + { 0x04, "Exclusive (E)" }, + { 0x02, "Shared (S)" }, + { 0x01, "Invalid (I)" } } +}; + +static const struct perfctr_event k7_official_events[] = { + { 0x40, 0xF, NULL, "DATA_CACHE_ACCESSES", + "Data cache accesses" }, + { 0x41, 0xF, NULL, "DATA_CACHE_MISSES", + "Data cache misses" }, + { 0x42, 0xF, UM(k7_um_moesi), "DATA_CACHE_REFILLS_FROM_L2", + "Data cache refills from L2" }, + { 0x43, 0xF, UM(k7_um_moesi), "DATA_CACHE_REFILLS_FROM_SYSTEM", + "Data cache refills from system" }, + { 0x44, 0xF, UM(k7_um_moesi), "DATA_CACHE_WRITEBACKS", + "Data cache writebacks" }, + { 0x45, 0xF, NULL, "L1_DTLB_MISSES_AND_L2_DTLB_HITS", + "L1 DTLB misses and L2 DTLB hits" }, + { 0x46, 0xF, NULL, "L1_AND_L2_DTLB_MISSES", + "L1 and L2 DTLB misses" }, + { 0x47, 0xF, NULL, "MISALIGNED_DATA_REFERENCES", + "Misaligned data references" }, + { 0x80, 0xF, NULL, "INSTRUCTION_CACHE_FETCHES", + "Instruction cache fetches" }, + { 0x81, 0xF, NULL, "INSTRUCTION_CACHE_MISSES", + "Instruction cache misses" }, + { 0x84, 0xF, NULL, "L1_ITLB_MISSES_AND_L2_ITLB_HITS", /* XXX: was L1_ITLB_MISSES */ + "L1 ITLB misses (and L2 ITLB hits)" }, + { 0x85, 0xF, NULL, "L1_AND_L2_ITLB_MISSES", /* XXX: was L2_ITLB_MISSES */ + "(L1 and) L2 ITLB misses" }, + { 0xC0, 0xF, NULL, "RETIRED_INSTRUCTIONS", + "Retired instructions (includes exceptions, interrupts, resyncs)" }, + { 0xC1, 0xF, NULL, "RETIRED_OPS", + "Retired Ops" }, + { 0xC2, 0xF, NULL, "RETIRED_BRANCHES", + "Retired branches (conditional, unconditional, exceptions, interrupts)" }, + { 0xC3, 0xF, NULL, "RETIRED_BRANCHES_MISPREDICTED", + "Retired branches mispredicted" }, + { 0xC4, 0xF, NULL, "RETIRED_TAKEN_BRANCHES", + "Retired taken branches" }, + { 0xC5, 0xF, NULL, "RETIRED_TAKEN_BRANCHES_MISPREDICTED", + "Retired taken branches mispredicted" }, + { 0xC6, 0xF, NULL, "RETIRED_FAR_CONTROL_TRANSFERS", + "Retired far control transfers" }, + { 0xC7, 0xF, NULL, "RETIRED_RESYNC_BRANCHES", + "Retired resync branches (only non-control transfer branches counted)" }, + { 0xCD, 0xF, NULL, "INTERRUPTS_MASKED_CYCLES", + "Interrupts masked cycles (IF=0)" }, + { 0xCE, 0xF, NULL, "INTERRUPTS_MASKED_WHILE_PENDING_CYCLES", + "Interrupts masked while pending cycles (INTR while IF=0)" }, + { 0xCF, 0xF, NULL, "NUMBER_OF_TAKEN_HARDWARE_INTERRUPTS", + "Number of taken hardware interrupts" }, +}; + +static const struct perfctr_event_set k7_official_event_set = { + .cpu_type = PERFCTR_X86_AMD_K7, + .event_prefix = "K7_", + .include = NULL, + .nevents = ARRAY_SIZE(k7_official_events), + .events = k7_official_events, +}; + +/* also in K8 */ +static const struct perfctr_unit_mask_7 k7_um_seg_reg = { + { .type = perfctr_um_type_bitmask, + .default_value = 0x3F, + .nvalues = 7 }, + { { 0x40, "HS" }, /* what's this? */ + { 0x20, "GS" }, + { 0x10, "FS" }, + { 0x08, "DS" }, + { 0x04, "SS" }, + { 0x02, "CS" }, + { 0x01, "ES" } } +}; + +/* not in K8 */ +static const struct perfctr_unit_mask_5 k7_um_system_request = { + { .type = perfctr_um_type_bitmask, + .default_value = 0x73, + .nvalues = 5 }, + { { 0x40, "WB" }, + { 0x20, "WP" }, + { 0x10, "WT" }, + { 0x02, "WC" }, + { 0x01, "UC" } } +}; + +/* not in K8 */ +static const struct perfctr_unit_mask_3 k7_um_snoop_hits = { + { .type = perfctr_um_type_bitmask, + .default_value = 0x07, + .nvalues = 3 }, + { { 0x04, "L2 (L2 hit and no DC hit)" }, + { 0x02, "Data cache" }, + { 0x01, "Instruction cache" } } +}; + +/* not in K8 */ +static const struct perfctr_unit_mask_2 k7_um_ecc = { + { .type = perfctr_um_type_bitmask, + .default_value = 0x03, + .nvalues = 2 }, + { { 0x02, "L2 single bit error" }, + { 0x01, "System single bit error" } } +}; + +/* not in K8 */ +static const struct perfctr_unit_mask_4 k7_um_invalidates = { + { .type = perfctr_um_type_bitmask, + .default_value = 0x0F, + .nvalues = 4 }, + { { 0x08, "I invalidates D" }, + { 0x04, "I invalidates I" }, + { 0x02, "D invalidates D" }, + { 0x01, "D invalidates I" } } +}; + +/* not in K8 */ +static const struct perfctr_unit_mask_8 k7_um_L2_requests = { + { .type = perfctr_um_type_bitmask, + .default_value = 0xFF, + .nvalues = 8 }, + { { 0x80, "Data block write from the L2 (TBL RMW)" }, + { 0x40, "Data block write from the DC" }, + { 0x20, "Data block write from the system" }, + { 0x10, "Data block read data store" }, + { 0x08, "Data block read data load" }, + { 0x04, "Data block read instruction" }, + { 0x02, "Tag write" }, + { 0x01, "Tag read" } } +}; + +static const struct perfctr_event k7_unofficial_events[] = { + { 0x20, 0xF, UM(k7_um_seg_reg), "SEGMENT_REGISTER_LOADS", /* also in K8 */ + "Segment register loads" }, + { 0x21, 0xF, NULL, "STORES_TO_ACTIVE_INSTRUCTION_STREAM", /* also in K8 as SELF_MODIFY_RESYNC */ + "Stores to active instruction stream" }, + { 0x64, 0xF, NULL, "DRAM_SYSTEM_REQUESTS", /* not in K8 */ + "DRAM system requests" }, + { 0x65, 0xF, UM(k7_um_system_request), "SYSTEM_REQUESTS_WITH_THE_SELECTED_TYPE", /* not in K8 */ + "System requests with the selected type" }, + { 0x73, 0xF, UM(k7_um_snoop_hits), "SNOOP_HITS", /* not in K8 */ + "Snoop hits" }, + { 0x74, 0xF, UM(k7_um_ecc), "SINGLE_BIT_ECC_ERRORS_DETECTED_CORRECTED", /* not in K8 */ /* XXX: was SINGLE_BIT_ECC_ERRORS_DETECTED_OR_CORRECTED */ + "Single-bit ECC errors detected/corrected" }, + { 0x75, 0xF, UM(k7_um_invalidates), "INTERNAL_CACHE_LINE_INVALIDATES", /* not in K8 */ + "Internal cache line invalidates" }, + { 0x76, 0xF, NULL, "CYCLES_PROCESSOR_IS_RUNNING", /* also in K8 */ + "Cycles processor is running (not in HLT or STPCLK)" }, + { 0x79, 0xF, UM(k7_um_L2_requests), "L2_REQUESTS", /* not in K8 */ + "L2 requests" }, + { 0x7A, 0xF, NULL, "CYCLES_THAT_AT_LEAST_ONE_FILL_REQUEST_WAITED_TO_USE_THE_L2", /* not in K8 */ + "Cycles that at least one fill request waited to use the L2" }, + { 0x82, 0xF, NULL, "INSTRUCTION_CACHE_REFILLS_FROM_L2", /* also in K8 */ + "Instruction cache refills from L2" }, + { 0x83, 0xF, NULL, "INSTRUCTION_CACHE_REFILLS_FROM_SYSTEM", /* also in K8 */ + "Instruction cache refills from system" }, + { 0x86, 0xF, NULL, "SNOOP_RESYNCS", /* also in K8 */ + "Snoop resyncs" }, + { 0x87, 0xF, NULL, "INSTRUCTION_FETCH_STALL_CYCLES", /* also in K8 */ + "Instruction fetch stall cycles" }, + { 0x88, 0xF, NULL, "RETURN_STACK_HITS", /* also in K8 */ + "Instruction cache hits" }, + { 0x89, 0xF, NULL, "RETURN_STACK_OVERFLOW", /* also in K8 */ + "Return stack overflow" }, + { 0xC8, 0xF, NULL, "RETIRED_NEAR_RETURNS", /* also in K8 */ + "Retired near returns" }, + { 0xC9, 0xF, NULL, "RETIRED_NEAR_RETURNS_MISPREDICTED", /* also in K8 */ + "Retired near returns mispredicted" }, + { 0xCA, 0xF, NULL, "RETIRED_INDIRECT_BRANCHES_WITH_TARGET_MISPREDICTED", /* also in K8 */ + "Retired indirect branches with target mispredicted" }, + { 0xD0, 0xF, NULL, "INSTRUCTION_DECODER_EMPTY", /* also in K8 */ + "Instruction decoder empty" }, + { 0xD1, 0xF, NULL, "DISPATCH_STALLS", /* also in K8 */ + "Dispatch stalls (event masks D2h through DAh below combined)" }, + { 0xD2, 0xF, NULL, "BRANCH_ABORT_TO_RETIRE", /* also in K8 */ /* XXX: was BRANCH_ABORTS_TO_RETIRE */ + "Branch abort to retire" }, + { 0xD3, 0xF, NULL, "SERIALIZE", /* also in K8 */ + "Serialize" }, + { 0xD4, 0xF, NULL, "SEGMENT_LOAD_STALL", /* also in K8 */ + "Segment load stall" }, + { 0xD5, 0xF, NULL, "ICU_FULL", /* also in K8 */ + "ICU full" }, + { 0xD6, 0xF, NULL, "RESERVATION_STATIONS_FULL", /* also in K8 */ + "Reservation stations full" }, + { 0xD7, 0xF, NULL, "FPU_FULL", /* also in K8 */ + "FPU full" }, + { 0xD8, 0xF, NULL, "LS_FULL", /* also in K8 */ + "LS full" }, + { 0xD9, 0xF, NULL, "ALL_QUIET_STALL", /* also in K8 */ + "All quiet stall" }, + { 0xDA, 0xF, NULL, "FAR_TRANSFER_OR_RESYNC_BRANCH_PENDING", /* also in K8 */ + "Fall transfer or resync branch pending" }, + { 0xDC, 0xF, NULL, "BREAKPOINT_MATCHES_FOR_DR0", /* also in K8 */ + "Breakpoint matches for DR0" }, + { 0xDD, 0xF, NULL, "BREAKPOINT_MATCHES_FOR_DR1", /* also in K8 */ + "Breakpoint matches for DR1" }, + { 0xDE, 0xF, NULL, "BREAKPOINT_MATCHES_FOR_DR2", /* also in K8 */ + "Breakpoint matches for DR2" }, + { 0xDF, 0xF, NULL, "BREAKPOINT_MATCHES_FOR_DR3", /* also in K8 */ + "Breakpoint matches for DR3" }, +}; + +const struct perfctr_event_set perfctr_k7_event_set = { + .cpu_type = PERFCTR_X86_AMD_K7, + .event_prefix = "K7_", + .include = &k7_official_event_set, + .nevents = ARRAY_SIZE(k7_unofficial_events), + .events = k7_unofficial_events, +}; + +/* + * AMD K8 events. + * + * Some events are described as being "Revision B and later", but + * AMD does not document how to distinguish Revision B processors + * from earlier ones. + */ + +static const struct perfctr_unit_mask_6 k8_um_fpu_ops = { + /* Revision B and later */ + { .type = perfctr_um_type_bitmask, + .default_value = 0x3F, + .nvalues = 6 }, + { { 0x01, "Add pipe ops excluding junk ops" }, + { 0x02, "Multiply pipe ops excluding junk ops" }, + { 0x04, "Store pipe ops excluding junk ops" }, + { 0x08, "Add pipe junk ops" }, + { 0x10, "Multiply pipe junk ops" }, + { 0x20, "Store pipe junk ops" } } +}; + +static const struct perfctr_unit_mask_2 k8_um_ecc = { + { .type = perfctr_um_type_bitmask, + .default_value = 0x03, + .nvalues = 2 }, + { { 0x01, "Scrubber error" }, + { 0x02, "Piggyback scrubber errors" } } +}; + +static const struct perfctr_unit_mask_3 k8_um_prefetch = { + { .type = perfctr_um_type_bitmask, + .default_value = 0x07, + .nvalues = 3 }, + { { 0x01, "Load" }, + { 0x02, "Store" }, + { 0x04, "NTA" } } +}; + +static const struct perfctr_unit_mask_5 k8_um_int_L2_req = { + { .type = perfctr_um_type_bitmask, + .default_value = 0x1F, + .nvalues = 5 }, + { { 0x01, "IC fill" }, + { 0x02, "DC fill" }, + { 0x04, "TLB reload" }, + { 0x08, "Tag snoop request" }, + { 0x10, "Cancelled request" } } +}; + +static const struct perfctr_unit_mask_3 k8_um_fill_req = { + { .type = perfctr_um_type_bitmask, + .default_value = 0x07, + .nvalues = 3 }, + { { 0x01, "IC fill" }, + { 0x02, "DC fill" }, + { 0x04, "TLB reload" } } +}; + +static const struct perfctr_unit_mask_2 k8_um_fill_L2 = { + { .type = perfctr_um_type_bitmask, + .default_value = 0x03, + .nvalues = 2 }, + { { 0x01, "Dirty L2 victim" }, + { 0x02, "Victim from L2" } } +}; + +static const struct perfctr_unit_mask_4 k8_um_fpu_instr = { + /* Revision B and later */ + { .type = perfctr_um_type_bitmask, + .default_value = 0x0F, + .nvalues = 4 }, + { { 0x01, "x87 instructions" }, + { 0x02, "Combined MMX & 3DNow! instructions" }, + { 0x04, "Combined packed SSE and SSE2 instructions" }, + { 0x08, "Combined scalar SSE and SSE2 instructions" } } +}; + +static const struct perfctr_unit_mask_3 k8_um_fpu_fastpath = { + /* Revision B and later */ + { .type = perfctr_um_type_bitmask, + .default_value = 0x07, + .nvalues = 3 }, + { { 0x01, "With low op in position 0" }, + { 0x02, "With low op in position 1" }, + { 0x04, "With low op in position 2" } } +}; + +static const struct perfctr_unit_mask_4 k8_um_fpu_exceptions = { + /* Revision B and later */ + { .type = perfctr_um_type_bitmask, + .default_value = 0x0F, + .nvalues = 4 }, + { { 0x01, "x87 reclass microfaults" }, + { 0x02, "SSE retype microfaults" }, + { 0x04, "SSE reclass microfaults" }, + { 0x08, "SSE and x87 microtraps" } } +}; + +static const struct perfctr_unit_mask_3 k8_um_page_access = { + { .type = perfctr_um_type_bitmask, + .default_value = 0x07, + .nvalues = 3 }, + { { 0x01, "Page hit" }, + { 0x02, "Page miss" }, + { 0x04, "Page conflict" } } +}; + +static const struct perfctr_unit_mask_3 k8_um_turnaround = { + { .type = perfctr_um_type_bitmask, + .default_value = 0x07, + .nvalues = 3 }, + { { 0x01, "DIMM turnaround" }, + { 0x02, "Read to write turnaround" }, + { 0x04, "Write to read turnaround" } } +}; + +static const struct perfctr_unit_mask_4 k8_um_saturation = { + { .type = perfctr_um_type_bitmask, + .default_value = 0x0F, + .nvalues = 4 }, + { { 0x01, "Memory controller high priority bypass" }, + { 0x02, "Memory controller low priority bypass" }, + { 0x04, "DRAM controller interface bypass" }, + { 0x08, "DRAM controller queue bypass" } } +}; + +static const struct perfctr_unit_mask_7 k8_um_sized_commands = { + { .type = perfctr_um_type_bitmask, + .default_value = 0x7F, + .nvalues = 7 }, + { { 0x01, "NonPostWrSzByte" }, + { 0x02, "NonPostWrSzDword" }, + { 0x04, "PostWrSzByte" }, + { 0x08, "PostWrSzDword" }, + { 0x10, "RdSzByte" }, + { 0x20, "RdSzDword" }, + { 0x40, "RdModWr" } } +}; + +static const struct perfctr_unit_mask_4 k8_um_probe = { + { .type = perfctr_um_type_bitmask, + .default_value = 0x0F, + .nvalues = 4 }, + { { 0x01, "Probe miss" }, + { 0x02, "Probe hit" }, + { 0x04, "Probe hit dirty without memory cancel" }, + { 0x08, "Probe hit dirty with memory cancel" } } +}; + +static const struct perfctr_unit_mask_4 k8_um_ht = { + { .type = perfctr_um_type_bitmask, + .default_value = 0x0F, + .nvalues = 4 }, + { { 0x01, "Command sent" }, + { 0x02, "Data sent" }, + { 0x04, "Buffer release sent" }, + { 0x08, "Nop sent" } } +}; + +static const struct perfctr_event k8_common_events[] = { + { 0x00, 0xF, UM(k8_um_fpu_ops), "DISPATCHED_FPU_OPS", + /* Revision B and later */ + "Dispatched FPU ops" }, + { 0x01, 0xF, NULL, "NO_FPU_OPS", + /* Revision B and later */ + "Cycles with no FPU ops retired" }, + { 0x02, 0xF, NULL, "FAST_FPU_OPS", + /* Revision B and later */ + "Dispatched FPU ops that use the fast flag interface" }, + { 0x20, 0xF, UM(k7_um_seg_reg), "SEG_REG_LOAD", + "Segment register load" }, + { 0x21, 0xF, NULL, "SELF_MODIFY_RESYNC", + "Microarchitectural resync caused by self modifying code" }, + { 0x22, 0xF, NULL, "LS_RESYNC_BY_SNOOP", + /* similar to 0x86, but LS unit instead of IC unit */ + "Microarchitectural resync caused by snoop" }, + { 0x23, 0xF, NULL, "LS_BUFFER_FULL", + "LS Buffer 2 Full" }, + /* 0x24: changed in Revision C */ + { 0x25, 0xF, NULL, "OP_LATE_CANCEL", + "Microarchitectural late cancel of an operation" }, + { 0x26, 0xF, NULL, "CFLUSH_RETIRED", + "Retired CFLUSH instructions" }, + { 0x27, 0xF, NULL, "CPUID_RETIRED", + "Retired CPUID instructions" }, + /* 0x40-0x47: from K7 official event set */ + { 0x48, 0xF, NULL, "ACCESS_CANCEL_LATE", + "Microarchitectural late cancel of an access" }, + { 0x49, 0xF, NULL, "ACCESS_CANCEL_EARLY", + "Microarchitectural early cancel of an access" }, + { 0x4A, 0xF, UM(k8_um_ecc), "ECC_BIT_ERR", + "One bit ECC error recorded found by scrubber" }, + { 0x4B, 0xF, UM(k8_um_prefetch), "DISPATCHED_PRE_INSTRS", + "Dispatched prefetch instructions" }, + /* 0x4C: added in Revision C */ + { 0x76, 0xF, NULL, "CPU_CLK_UNHALTED", /* XXX: was CYCLES_PROCESSOR_IS_RUNNING */ + "Cycles processor is running (not in HLT or STPCLK)" }, + { 0x7D, 0xF, UM(k8_um_int_L2_req), "BU_INT_L2_REQ", + "Internal L2 request" }, + { 0x7E, 0xF, UM(k8_um_fill_req), "BU_FILL_REQ", + "Fill request that missed in L2" }, + { 0x7F, 0xF, UM(k8_um_fill_L2), "BU_FILL_L2", + "Fill into L2" }, + /* 0x80-0x81: from K7 official event set */ + { 0x82, 0xF, NULL, "IC_REFILL_FROM_L2", + "Refill from L2" }, + { 0x83, 0xF, NULL, "IC_REFILL_FROM_SYS", + "Refill from system" }, + /* 0x84-0x85: from K7 official event set */ + { 0x86, 0xF, NULL, "IC_RESYNC_BY_SNOOP", + /* similar to 0x22, but IC unit instead of LS unit */ + "Microarchitectural resync caused by snoop" }, + { 0x87, 0xF, NULL, "IC_FETCH_STALL", + "Instruction fetch stall" }, + { 0x88, 0xF, NULL, "IC_STACK_HIT", + "Return stack hit" }, + { 0x89, 0xF, NULL, "IC_STACK_OVERFLOW", + "Return stack overflow" }, + /* 0xC0-0xC7: from K7 official event set */ + { 0xC8, 0xF, NULL, "RETIRED_NEAR_RETURNS", + "Retired near returns" }, + { 0xC9, 0xF, NULL, "RETIRED_RETURNS_MISPREDICT", + "Retired near returns mispredicted" }, + { 0xCA, 0xF, NULL, "RETIRED_BRANCH_MISCOMPARE", + "Retired taken branches mispredicted due to address miscompare" }, + { 0xCB, 0xF, UM(k8_um_fpu_instr), "RETIRED_FPU_INSTRS", + /* Revision B and later */ + "Retired FPU instructions" }, + { 0xCC, 0xF, UM(k8_um_fpu_fastpath), "RETIRED_FASTPATH_INSTRS", + /* Revision B and later */ + "Retired fastpath double op instructions" }, + /* 0xCD-0xCF: from K7 official event set */ + { 0xD0, 0xF, NULL, "DECODER_EMPTY", + "Nothing to dispatch (decoder empty)" }, + { 0xD1, 0xF, NULL, "DISPATCH_STALLS", + "Dispatch stalls (events 0xD2-0xDA combined)" }, + { 0xD2, 0xF, NULL, "DISPATCH_STALL_FROM_BRANCH_ABORT", + "Dispatch stall from branch abort to retire" }, + { 0xD3, 0xF, NULL, "DISPATCH_STALL_SERIALIZATION", + "Dispatch stall for serialization" }, + { 0xD4, 0xF, NULL, "DISPATCH_STALL_SEG_LOAD", + "Dispatch stall for segment load" }, + { 0xD5, 0xF, NULL, "DISPATCH_STALL_REORDER_BUFFER", + "Dispatch stall when reorder buffer is full" }, + { 0xD6, 0xF, NULL, "DISPATCH_STALL_RESERVE_STATIONS", + "Dispatch stall when reservation stations are full" }, + { 0xD7, 0xF, NULL, "DISPATCH_STALL_FPU", + "Dispatch stall when FPU is full" }, + { 0xD8, 0xF, NULL, "DISPATCH_STALL_LS", + "Dispatch stall when LS is full" }, + { 0xD9, 0xF, NULL, "DISPATCH_STALL_QUIET_WAIT", + "Dispatch stall when waiting for all to be quiet" }, + { 0xDA, 0xF, NULL, "DISPATCH_STALL_PENDING", + "Dispatch stall when far control transfer or resync branch is pending" }, + { 0xDB, 0xF, UM(k8_um_fpu_exceptions), "FPU_EXCEPTIONS", + /* Revision B and later */ + "FPU exceptions" }, + { 0xDC, 0xF, NULL, "DR0_BREAKPOINTS", + "Number of breakpoints for DR0" }, + { 0xDD, 0xF, NULL, "DR1_BREAKPOINTS", + "Number of breakpoints for DR1" }, + { 0xDE, 0xF, NULL, "DR2_BREAKPOINTS", + "Number of breakpoints for DR2" }, + { 0xDF, 0xF, NULL, "DR3_BREAKPOINTS", + "Number of breakpoints for DR3" }, + { 0xE0, 0xF, UM(k8_um_page_access), "MEM_PAGE_ACCESS", + "Memory controller page access" }, + { 0xE1, 0xF, NULL, "MEM_PAGE_TBL_OVERFLOW", + "Memory controller page table overflow" }, + { 0xE2, 0xF, NULL, "DRAM_SLOTS_MISSED", + "Memory controller DRAM command slots missed (in MemClks)" }, + { 0xE3, 0xF, UM(k8_um_turnaround), "MEM_TURNAROUND", + "Memory controller turnaround" }, + { 0xE4, 0xF, UM(k8_um_saturation), "MEM_BYPASS_SAT", + "Memory controller bypass counter saturation" }, + { 0xEB, 0xF, UM(k8_um_sized_commands), "SIZED_COMMANDS", + "Sized commands" }, + { 0xEC, 0xF, UM(k8_um_probe), "PROBE_RESULT", + "Probe result" }, + { 0xF6, 0xF, UM(k8_um_ht), "HYPERTRANSPORT_BUS0_WIDTH", + "Hypertransport (tm) bus 0 bandwidth" }, + { 0xF7, 0xF, UM(k8_um_ht), "HYPERTRANSPORT_BUS1_WIDTH", + "Hypertransport (tm) bus 1 bandwidth" }, + { 0xF8, 0xF, UM(k8_um_ht), "HYPERTRANSPORT_BUS2_WIDTH", + "Hypertransport (tm) bus 2 bandwidth" }, +}; + +static const struct perfctr_event_set k8_common_event_set = { + .cpu_type = PERFCTR_X86_AMD_K8, + .event_prefix = "K8_", + .include = &k7_official_event_set, + .nevents = ARRAY_SIZE(k8_common_events), + .events = k8_common_events, +}; + +static const struct perfctr_event k8_events[] = { + { 0x24, 0xF, NULL, "LOCKED_OP", /* unit mask changed in Rev. C */ + "Locked operation" }, +}; + +const struct perfctr_event_set perfctr_k8_event_set = { + .cpu_type = PERFCTR_X86_AMD_K8, + .event_prefix = "K8_", + .include = &k8_common_event_set, + .nevents = ARRAY_SIZE(k8_events), + .events = k8_events, +}; + +/* + * K8 Revision C. Starts at CPUID 0xF58 for Opteron/Athlon64FX and + * CPUID 0xF48 for Athlon64. (CPUID 0xF51 is Opteron Revision B3.) + */ + +static const struct perfctr_unit_mask_3 k8c_um_locked_op = { + { .type = perfctr_um_type_bitmask, + .default_value = 0x01, + .nvalues = 3 }, + { { 0x01, "Number of lock instructions executed" }, + { 0x02, "Number of cycles spent in the lock request/grant stage" }, + { 0x04, "Number of cycles a lock takes to complete once it is " + "non-speculative and is the oldest load/store operation " + "(non-speculative cycles in Ls2 entry 0)" } } +}; + +static const struct perfctr_unit_mask_2 k8c_um_lock_accesses = { + { .type = perfctr_um_type_bitmask, + .default_value = 0x03, + .nvalues = 2 }, + { { 0x01, "Number of dcache accesses by lock instructions" }, + { 0x02, "Number of dcache misses by lock instructions" } } +}; + +static const struct perfctr_event k8c_events[] = { + { 0x24, 0xF, UM(k8c_um_locked_op), "LOCKED_OP", /* unit mask changed */ + "Locked operation" }, + { 0x4C, 0xF, UM(k8c_um_lock_accesses), "LOCK_ACCESSES", + "DCACHE accesses by locks" }, +}; + +const struct perfctr_event_set perfctr_k8c_event_set = { + .cpu_type = PERFCTR_X86_AMD_K8C, + .event_prefix = "K8C_", + .include = &k8_common_event_set, + .nevents = ARRAY_SIZE(k8c_events), + .events = k8c_events, +}; diff --git a/kernel/fiasco/src/lib/perfctr/event_set_arm.c b/kernel/fiasco/src/lib/perfctr/event_set_arm.c new file mode 100644 index 00000000..4b709381 --- /dev/null +++ b/kernel/fiasco/src/lib/perfctr/event_set_arm.c @@ -0,0 +1,69 @@ +/* $Id: event_set_arm.c,v 1.1.2.1 2007/02/11 20:15:03 mikpe Exp $ + * Descriptions of the events available for different processor types. + * + * Copyright (C) 2005-2007 Mikael Pettersson + */ +#include /* for NULL */ +#include "libperfctr.h" +#include "event_set.h" + +/* + * XScale 1 and 2 events for PMC1-PMC4. + */ + +static const struct perfctr_event xsc1_events[] = { + { 0x00, 0x0F, NULL, "IC_MISS", + "Instruction cache miss requires fetch from external memory" }, + { 0x01, 0x0F, NULL, "IC_CANNOT_DELIVER", + "Instruction cache cannot deliver an instruction" }, + { 0x02, 0x0F, NULL, "DATA_DEP_STALL", + "Stall due to a data dependency" }, + { 0x03, 0x0F, NULL, "ITLB_MISS", + "Instruction TLB miss" }, + { 0x04, 0x0F, NULL, "DTLB_MISS", + "Data TLB miss" }, + { 0x05, 0x0F, NULL, "BR_INST_EXEC", + "Branch instruction executed" }, + { 0x06, 0x0F, NULL, "BR_MISPRED", + "Branch mispredicted" }, + { 0x07, 0x0F, NULL, "INST_EXEC", + "Instruction executed" }, + { 0x08, 0x0F, NULL, "DC_FULL_CYCLES", + "Stall because the data cache buffers are full (cycles)" }, + { 0x09, 0x0F, NULL, "DC_FULL_OCCURRENCES", + "Stall because the data cache buffers are full (occurrences)" }, + { 0x0A, 0x0F, NULL, "DC_ACCESS", + "Data cache access" }, + { 0x0B, 0x0F, NULL, "DC_MISS", + "Data cache miss" }, + { 0x0C, 0x0F, NULL, "DC_WRITE_BACK", + "Data cache write-back" }, + { 0x0D, 0x0F, NULL, "SW_CHANGED_PC", + "Software changed the PC" }, + { 0xFF, 0x0F, NULL, "IDLE", + "Power saving event" }, +}; + +static const struct perfctr_event_set perfctr_xsc1_event_set = { + .cpu_type = PERFCTR_ARM_XSC1, + .event_prefix = "XSC1_", + .include = NULL, + .nevents = ARRAY_SIZE(xsc1_events), + .events = xsc1_events, +}; + +/* + * Helper function to translate a cpu_type code to an event_set pointer. + */ + +static const struct perfctr_event_set * const cpu_event_set[] = { + [PERFCTR_ARM_XSC1] = &perfctr_xsc1_event_set, + [PERFCTR_ARM_XSC2] = &perfctr_xsc1_event_set, +}; + +const struct perfctr_event_set *perfctr_cpu_event_set(unsigned cpu_type) +{ + if (cpu_type >= ARRAY_SIZE(cpu_event_set)) + return 0; + return cpu_event_set[cpu_type]; +} diff --git a/kernel/fiasco/src/lib/perfctr/event_set_centaur.c b/kernel/fiasco/src/lib/perfctr/event_set_centaur.c new file mode 100644 index 00000000..a5f53c3c --- /dev/null +++ b/kernel/fiasco/src/lib/perfctr/event_set_centaur.c @@ -0,0 +1,108 @@ +/* $Id: event_set_centaur.c,v 1.1 2003/02/16 21:08:54 mikpe Exp $ + * Performance counter event descriptions for Centaur chips: + * IDT WinChip C6/2/3 and VIA C3. + * + * Copyright (C) 2003 Mikael Pettersson + * + * References + * ---------- + * [WinChip C6] "WinChip C6 Processor Data Sheet". + * [WinChip 2A] "WinChip 2 Processor Version A Data Sheet". + * [WinChip 3] "WinChip 3 Processor Data Sheet". + * (at http://www.centtech.com/) + * + * [VIA C3] "VIA C3 Samuel 2 Processor Datasheet", Ver. 1.03, April 2001. + * Note: The C3 was originally called "Cyrix III", but it is a Centaur + * design developed as a replacement for Cyrix' "Joshua". + * (at http://www.viatech.com/) + */ +#include /* for NULL */ +#include "libperfctr.h" +#include "event_set.h" + +/* + * Centaur WinChip C6 events. + * Note: The manual lists the codes in decimal, not hex as done here. + */ + +static const struct perfctr_event wcc6_events[] = { + { 0x00, 0x3, NULL, "INTERNAL_CLOCKS", 0 }, + { 0x01, 0x3, NULL, "VALID_CYCLES_REACHING_WRITEBACKS", 0 }, + { 0x02, 0x3, NULL, "X86_INSTRUCTIONS", 0 }, + { 0x47, 0x3, NULL, "DATA_READ_CACHE_MISSES", 0 }, + { 0x4A, 0x3, NULL, "DATA_WRITE_CACHE_MISSES", 0 }, + { 0x63, 0x3, NULL, "INSTRUCTION_FETCH_CACHE_MISSES", 0 }, +}; + +const struct perfctr_event_set perfctr_wcc6_event_set = { + .cpu_type = PERFCTR_X86_WINCHIP_C6, + .event_prefix = "WCC6_", + .include = NULL, + .nevents = ARRAY_SIZE(wcc6_events), + .events = wcc6_events, +}; + +/* + * Centaur WinChip 2 and 3 events. + * Note: The manual lists the codes in decimal, not hex as done here. + */ + +static const struct perfctr_event wc2_events[] = { + { 0x00, 0x3, NULL, "DATA_READ", 0 }, + { 0x01, 0x3, NULL, "DATA_WRITE", 0 }, + { 0x02, 0x3, NULL, "DATA_TLB_MISS", 0 }, + { 0x03, 0x3, NULL, "DATA_READ_CACHE_MISS", 0 }, + { 0x04, 0x3, NULL, "DATA_WRITE_CACHE_MISS", 0 }, + { 0x06, 0x3, NULL, "DATA_CACHE_WRITEBACKS", 0 }, + { 0x08, 0x3, NULL, "DATA_CACHE_SNOOP_HITS", 0 }, + { 0x09, 0x3, NULL, "PUSH_PUSH_POP_POP_PAIRING", 0 }, + { 0x0B, 0x3, NULL, "MISALIGNED_DATA_MEMORY_NOT_IO", 0 }, + { 0x0C, 0x3, NULL, "CODE_READ", 0 }, + { 0x0D, 0x3, NULL, "CODE_TLB_MISS", 0 }, + { 0x0E, 0x3, NULL, "INSTRUCTION_FETCH_CACHE_MISS", 0 }, + { 0x13, 0x3, NULL, "BHT_HITS", 0 }, + { 0x14, 0x3, NULL, "BHT_CANDIDATE", 0 }, + { 0x16, 0x3, NULL, "INSTRUCTIONS_EXECUTED", 0 }, + { 0x17, 0x3, NULL, "INSTRUCTIONS_IN_PIPE_2", 0 }, + { 0x18, 0x3, NULL, "BUS_UTILIZATION", 0 }, + { 0x1D, 0x3, NULL, "IO_READ_OR_WRITE_CYCLE", 0 }, + { 0x28, 0x3, NULL, "DATA_READ_OR_DATA_WRITE", 0 }, + { 0x2B, 0x1, NULL, "MMX_INSTRUCTIONS_U_PIPE", 0 }, + { 0x2B, 0x2, NULL, "MMX_INSTRUCTIONS_V_PIPE", 0 }, + { 0x37, 0x1, NULL, "RETURNS_PREDICTED_INCORRECTLY", 0 }, + { 0x37, 0x2, NULL, "RETURNS_PREDICTED_CORRECTLY", 0 }, + { 0x3F, 0x3, NULL, "INTERNAL_CLOCKS", 0 }, +}; + +const struct perfctr_event_set perfctr_wc2_event_set = { + .cpu_type = PERFCTR_X86_WINCHIP_2, + .event_prefix = "WC2_", + .include = NULL, + .nevents = ARRAY_SIZE(wc2_events), + .events = wc2_events, +}; + +/* + * VIA C3 events. + * This processor is a Centaur design, tweaked to look like a Celeron. + * Its perfctr MSRs have the same addresses as in the P6, but PERFCTR0 + * is an alias for the TSC and EVNTSEL0 is read-only. It appears that + * rdpmc(0) returns the TSC truncated to 40 bits. Only EVNTSEL1 and + * PERFCTR1 can be used. EVNTSEL1 has a different format than in P6: the + * event selection field is 9 bits, and no other fields are defined. + * The data sheet only lists the three events defined below. + */ + +static const struct perfctr_event vc3_events[] = { + { 0x079, 0x2, NULL, "INTERNAL_CLOCKS", 0 }, + { 0x0C0, 0x2, NULL, "INSTRUCTIONS_EXECUTED", 0 }, + { 0x1C0, 0x2, NULL, "INSTRUCTIONS_EXECUTED_AND_STRING_ITERATIONS", 0 }, +}; + +const struct perfctr_event_set perfctr_vc3_event_set = { + .cpu_type = PERFCTR_X86_VIA_C3, + .event_prefix = "VC3_", + .include = NULL, + .nevents = ARRAY_SIZE(vc3_events), + .events = vc3_events, +}; diff --git a/kernel/fiasco/src/lib/perfctr/event_set_p4.c b/kernel/fiasco/src/lib/perfctr/event_set_p4.c new file mode 100644 index 00000000..4adeb422 --- /dev/null +++ b/kernel/fiasco/src/lib/perfctr/event_set_p4.c @@ -0,0 +1,514 @@ +/* $Id: event_set_p4.c 18810 2004-10-28 14:18:48Z fm3 $ + * Performance counter event descriptions for Intel P4. + * + * Copyright (C) 2003-2004 Mikael Pettersson + * + * This is still preliminary: + * - need mapping from enum escr_set to + * - the current data structures can't describe all P4 side-conditions + * - replace eventsel in struct perfctr_event with a unique cookie? + */ +#include /* for NULL */ +#include "libperfctr.h" +#include "event_set.h" + +enum escr_set { + ALF_ESCR_0_1, /* CCCR 12/13/14/15/16/17 via ESCR select 0x01 */ + BPU_ESCR_0_1, /* CCCR 0/1/2/3 via ESCR select 0x00 */ + BSU_ESCR_0_1, /* CCCR 0/1/2/3 via ESCR select 0x07 */ + BSU_ESCR_0, /* CCCR 0/1 via ESCR select 0x07 */ + BSU_ESCR_1, /* CCCR 2/3 via ESCR select 0x07 */ + CRU_ESCR_0_1, /* CCCR 12/13/14/15/16/17 via ESCR select 0x04 */ + CRU_ESCR_2_3, /* CCCR 12/13/14/15/16/17 via ESCR select 0x05 */ + DAC_ESCR_0_1, /* CCCR 8/9/10/11 via ESCR select 0x05 */ + FIRM_ESCR_0_1, /* CCCR 8/9/10/11 via ESCR select 0x01 */ + FSB_ESCR_0_1, /* CCCR 0/1/2/3 via ESCR select 0x06 */ + FSB_ESCR_0, /* CCCR 0/1 via ESCR select 0x06 */ + FSB_ESCR_1, /* CCCR 2/3 via ESCR select 0x06 */ + ITLB_ESCR_0_1, /* CCCR 0/1/2/3 via ESCR select 0x03 */ + MOB_ESCR_0_1, /* CCCR 0/1/2/3 via ESCR select 0x02 */ + MS_ESCR_0_1, /* CCCR 4/5/6/7 via ESCR select 0x00 */ + PMH_ESCR_0_1, /* CCCR 0/1/2/3 via ESCR select 0x04 */ + RAT_ESCR_0_1, /* CCCR 12/13/14/15/16/17 via ESCR select 0x02 */ + SAAT_ESCR_0_1, /* CCCR 8/9/10/11 via ESCR select 0x02 */ + TBPU_ESCR_0_1, /* CCCR 4/5/6/7 via ESCR select 0x02 */ + TC_ESCR_0_1, /* CCCR 4/5/6/7 via ESCR select 0x01 */ +}; + +static const struct perfctr_unit_mask_8 p4_um_TC_deliver_mode = { + { .type = perfctr_um_type_bitmask, + .default_value = 0x01, /* DD */ + .nvalues = 8 }, + { { 0x01, "DD:both logical processors in deliver mode" }, + { 0x02, "DB:logical processor 0 in deliver mode, 1 in build mode" }, + { 0x04, "DI:logical processor 0 in deliver mode, 1 is inactive" }, + { 0x08, "BD:logical processor 0 in build mode, 1 in deliver mode" }, + { 0x10, "BB:both logical processors in build mode" }, + { 0x20, "BI:logical processor 0 in build mode, 1 is inactive" }, + { 0x40, "ID:logical processor 0 is inactive, 1 in deliver mode" }, + { 0x80, "IB:logical processor 0 is inactive, 1 in build mode" } } +}; + +static const struct perfctr_unit_mask_1 p4_um_BPU_fetch_request = { + { .type = perfctr_um_type_bitmask, + .default_value = 0x00, + .nvalues = 1 }, + { { 0x01, "TCMISS:Trace cache lookup miss" } } +}; + +static const struct perfctr_unit_mask_3 p4_um_ITLB_reference = { + { .type = perfctr_um_type_bitmask, + .default_value = 0x07, + .nvalues = 3 }, + { { 0x01, "HIT:ITLB hit" }, + { 0x02, "MISS:ITLB miss" }, + { 0x04, "HIT_UC:Uncacheable ITLB hit" } } +}; + +static const struct perfctr_unit_mask_2 p4_um_memory_cancel = { + { .type = perfctr_um_type_bitmask, + .default_value = 0x0C, + .nvalues = 2 }, + { { 0x04, "ST_RB_FULL:Replayed because no store request buffer is available" }, + { 0x08, "64K_CONF:Conflicts due to 64K aliasing" } } +}; + +static const struct perfctr_unit_mask_2 p4_um_memory_complete = { + { .type = perfctr_um_type_bitmask, + .default_value = 0x03, + .nvalues = 2 }, + { { 0x01, "LSC:Load split completed, excluding UC/WC loads" }, + { 0x02, "SSC:Any split stores completed" } } +}; + +static const struct perfctr_unit_mask_1 p4_um_load_port_replay = { + { .type = perfctr_um_type_bitmask, + .default_value = 0x02, + .nvalues = 1 }, + { { 0x02, "SPLIT_LD:Split load" } } +}; + +static const struct perfctr_unit_mask_1 p4_um_store_port_replay = { + { .type = perfctr_um_type_bitmask, + .default_value = 0x02, + .nvalues = 1 }, + { { 0x02, "SPLIT_ST:Split store" } } +}; + +static const struct perfctr_unit_mask_4 p4_um_MOB_load_replay = { + { .type = perfctr_um_type_bitmask, + .default_value = 0x3A, + .nvalues = 4 }, + { { 0x02, "NO_STA:Replayed because of unknown store address" }, + { 0x08, "NO_STD:Replayed because of unknown store data" }, + { 0x10, "PARTIAL_DATA:Replayed because of partially overlapped data access between the load and store operations" }, + { 0x20, "UNALGN_ADDR:Replayed because the lower 4 bits of the linear address do not match between the load and store operations" } } +}; + +static const struct perfctr_unit_mask_2 p4_um_page_walk_type = { + { .type = perfctr_um_type_bitmask, + .default_value = 0x03, + .nvalues = 2 }, + { { 0x01, "DTMISS:Page walk for a data TLB miss" }, + { 0x02, "ITMISS:Page walk for an instruction TLB miss" } } +}; + +static const struct perfctr_unit_mask_9 p4_um_BSQ_cache_reference = { + { .type = perfctr_um_type_bitmask, + .default_value = 0x73F, + .nvalues = 9 }, + { { 0x001, "RD_2ndL_HITS:Read 2nd level cache hit Shared" }, + { 0x002, "RD_2ndL_HITE:Read 2nd level cache hit Exclusive" }, + { 0x004, "RD_2ndL_HITM:Read 2nd level cache hit Modified" }, + { 0x008, "RD_3rdL_HITS:Read 3rd level cache hit Shared" }, + { 0x010, "RD_3rdL_HITE:Read 3rd level cache hit Exclusive" }, + { 0x020, "RD_3rdL_HITM:Read 3rd level cache hit Modified" }, + { 0x100, "RD_2ndL_MISS:Read 2nd level cache miss" }, + { 0x200, "RD_3rdL_MISS:Read 3rd level cache miss" }, + { 0x400, "WR_2ndL_MISS:Writeback lookup from DAC misses the 2nd level cache" } } +}; + +/* review P4M0 and P4M2 diffs according to P4 Code Optim manual */ +static const struct perfctr_unit_mask_15 p4_um_IOQ = { + { .type = perfctr_um_type_bitmask, + .default_value = 0xEFE1, + .nvalues = 15 }, + /* XXX: how should we describe that bits 0-4 are a single field? */ + { { 0x0001, "bus request type bit 0" }, + { 0x0002, "bus request type bit 1" }, + { 0x0004, "bus request type bit 2" }, + { 0x0008, "bus request type bit 3" }, + { 0x0010, "bus request type bit 4" }, + { 0x0020, "ALL_READ:Count read entries" }, + { 0x0040, "ALL_WRITE:Count write entries" }, + { 0x0080, "MEM_UC:Count UC memory access entries" }, + { 0x0100, "MEM_WC:Count WC memory access entries" }, + { 0x0200, "MEM_WT:Count WT memory access entries" }, + { 0x0400, "MEM_WP:Count WP memory access entries" }, + { 0x0800, "MEM_WB:Count WB memory access entries" }, + { 0x2000, "OWN:Count own store requests" }, + { 0x4000, "OTHER:Count other and DMA store requests" }, + { 0x8000, "PREFETCH:Include HW and SW prefetch requests" } } +}; + +static const struct perfctr_unit_mask_6 p4_um_FSB_data_activity = { + { .type = perfctr_um_type_bitmask, + .default_value = 0x1B, + .nvalues = 6 }, + /* DRDY_OWN is mutually exclusive with DRDY_OTHER */ + /* DBSY_OWN is mutually exclusive with DBSY_OTHER */ + { { 0x01, "DRDY_DRV:Count when this processor drives data onto the bus" }, + { 0x02, "DRDY_OWN:Count when this processor reads data from the bus" }, + { 0x04, "DRDY_OTHER:Count when data is on the bus but not being sampled by the processor" }, + { 0x08, "DBSY_DRV:Count when this processor reserves the bus for driving data" }, + { 0x10, "DBSY_OWN:Count when this processor reserves the bus for sampling data" }, + { 0x20, "DBSY_OTHER:Count when the bus is reserved for driving data this processor will not sample" } } +}; + +static const struct perfctr_unit_mask_13 p4_um_BSQ = { + { .type = perfctr_um_type_bitmask, + .default_value = 0x0021, + .nvalues = 13 }, + { { 0x0001, "REQ_TYPE0:Request type encoding bit 0" }, + { 0x0002, "REQ_TYPE1:Request type encoding bit 1" }, + { 0x0004, "REQ_LEN0:Request length encoding bit 0" }, + { 0x0008, "REQ_LEN1:Request length encoding bit 1" }, + { 0x0020, "REQ_IO_TYPE:Request type is input or output" }, + { 0x0040, "REQ_LOCK_TYPE:Request type is bus lock" }, + { 0x0080, "REQ_CACHE_TYPE:Request type is cacheable" }, + { 0x0100, "REQ_SPLIT_TYPE:Request type is a bus 8-byte chunk split across 8-byte boundary" }, + { 0x0200, "REQ_DEM_TYPE:Request type is a demand (1) or prefetch (0)" }, + { 0x0400, "REQ_ORD_TYPE:Request is an ordered type" }, + { 0x0800, "MEM_TYPE0:Memory type encoding bit 0" }, + { 0x1000, "MEM_TYPE1:Memory type encoding bit 1" }, + { 0x2000, "MEM_TYPE2:Memory type encoding bit 2" } } +}; + +static const struct perfctr_unit_mask_1 p4_um_firm_uop = { + { .type = perfctr_um_type_bitmask, + .default_value = 0x8000, + .nvalues = 1 }, + { { 0x8000, "ALL:count all uops of this type" } } +}; + +static const struct perfctr_unit_mask_2 p4_um_x87_SIMD_moves_uop = { + { .type = perfctr_um_type_bitmask, + .default_value = 0x18, + .nvalues = 2 }, + { { 0x08, "ALLP0:Count all x87/SIMD store/move uops" }, + { 0x10, "ALLP2:count all x87/SIMD load uops" } } +}; + +static const struct perfctr_unit_mask_1 p4_um_TC_misc = { + { .type = perfctr_um_type_bitmask, + .default_value = 0x10, + .nvalues = 1 }, + { { 0x10, "FLUSH:Number of flushes" } } +}; + +static const struct perfctr_unit_mask_1 p4_um_global_power_events = { + { .type = perfctr_um_type_bitmask, + .default_value = 0x01, + .nvalues = 1 }, + { { 0x01, "Running:The processor is active" } } +}; + +static const struct perfctr_unit_mask_1 p4_um_tc_ms_xfer = { + { .type = perfctr_um_type_bitmask, + .default_value = 0x01, + .nvalues = 1 }, + { { 0x01, "CISC:A TC to MS transfer ocurred" } } +}; + +static const struct perfctr_unit_mask_3 p4_um_uop_queue_writes = { + { .type = perfctr_um_type_bitmask, + .default_value = 0x07, + .nvalues = 3 }, + { { 0x01, "FROM_TC_BUILD:uops written from TC build mode" }, + { 0x02, "FROM_TC_DELIVER:uops written from TC deliver mode" }, + { 0x04, "FROM_ROM:uops written from microcode ROM" } } +}; + +static const struct perfctr_unit_mask_4 p4_um_branch_type = { + { .type = perfctr_um_type_bitmask, + .default_value = 0x1E, + .nvalues = 4 }, + { { 0x02, "CONDITIONAL:Conditional jumps" }, + { 0x04, "CALL:Call branches" }, /* XXX: diff MISPRED/non-MISPRED events? */ + { 0x08, "RETURN:Return branches" }, + { 0x10, "INDIRECT:Returns, indirect calls, or indirect jumps" } } +}; + +static const struct perfctr_unit_mask_1 p4_um_resource_stall = { + { .type = perfctr_um_type_bitmask, + .default_value = 0x20, + .nvalues = 1 }, + { { 0x20, "SBFULL:A Stall due to lack of store buffers" } } +}; + +static const struct perfctr_unit_mask_3 p4_um_WC_Buffer = { + { .type = perfctr_um_type_bitmask, + .default_value = 0x01, + .nvalues = 3 }, + { { 0x01, "WCB_EVICTS:all causes" }, + { 0x02, "WCB_FULL_EVICT:no WC buffer is available" }, + /* XXX: 245472-011 no longer lists bit 2, but that looks like + a table formatting error. Keeping it for now. */ + { 0x04, "WCB_HITM_EVICT:store encountered a Hit Modified condition" } } +}; + +static const struct perfctr_unit_mask_6 p4_um_b2b_cycles = { + /* XXX: bits 1-6; no details documented yet */ + { .type = perfctr_um_type_bitmask, + .default_value = 0x7E, + .nvalues = 6 }, + { { 0x02, "bit 1" }, + { 0x04, "bit 2" }, + { 0x08, "bit 3" }, + { 0x10, "bit 4" }, + { 0x20, "bit 5" }, + { 0x40, "bit 6" } } +}; + +static const struct perfctr_unit_mask_3 p4_um_bnr = { + /* XXX: bits 0-2; no details documented yet */ + { .type = perfctr_um_type_bitmask, + .default_value = 0x07, + .nvalues = 3 }, + { { 0x01, "bit 0" }, + { 0x02, "bit 1" }, + { 0x04, "bit 2" } } +}; + +static const struct perfctr_unit_mask_3 p4_um_snoop = { + /* XXX: bits 2, 6, and 7; no details documented yet */ + { .type = perfctr_um_type_bitmask, + .default_value = 0xC4, + .nvalues = 3 }, + { { 0x04, "bit 2" }, + { 0x40, "bit 6" }, + { 0x80, "bit 7" } } +}; + +static const struct perfctr_unit_mask_4 p4_um_response = { + /* XXX: bits 1, 2, 8, and 9; no details documented yet */ + { .type = perfctr_um_type_bitmask, + .default_value = 0x306, + .nvalues = 4 }, + { { 0x002, "bit 1" }, + { 0x004, "bit 2" }, + { 0x100, "bit 8" }, + { 0x200, "bit 9" } } +}; + +static const struct perfctr_unit_mask_2 p4_um_nbogus_bogus = { + { .type = perfctr_um_type_bitmask, + .default_value = 0x01, + .nvalues = 2 }, + { { 0x01, "NBOGUS:The marked uops are not bogus" }, + { 0x02, "BOGUS:The marked uops are bogus" } } +}; + +static const struct perfctr_unit_mask_8 p4_um_execution_event = { + { .type = perfctr_um_type_bitmask, + .default_value = 0x01, + .nvalues = 8 }, + { { 0x01, "NBOGUS0:non-bogus uops with tag bit 0 set" }, + { 0x02, "NBOGUS1:non-bogus uops with tag bit 1 set" }, + { 0x04, "NBOGUS2:non-bogus uops with tag bit 2 set" }, + { 0x08, "NBOGUS3:non-bogus uops with tag bit 3 set" }, + { 0x10, "BOGUS0:bogus uops with tag bit 0 set" }, + { 0x20, "BOGUS1:bogus uops with tag bit 1 set" }, + { 0x40, "BOGUS2:bogus uops with tag bit 2 set" }, + { 0x80, "BOGUS3:bogus uops with tag bit 3 set" } } +}; + +static const struct perfctr_unit_mask_4 p4_um_instr_retired = { + { .type = perfctr_um_type_bitmask, + .default_value = 0x01, + .nvalues = 4 }, + { { 0x01, "NBOGUSNTAG:Non-bogus instructions that are not tagged" }, + { 0x02, "NBOGUSTAG:Non-bogus instructions that are tagged" }, + { 0x04, "BOGUSNTAG:Bogus instructions that are not tagged" }, + { 0x08, "BOGUSTAG:Bogus instructions that are tagged" } } +}; + +static const struct perfctr_unit_mask_2 p4_um_uop_type = { + { .type = perfctr_um_type_bitmask, + .default_value = 0x06, + .nvalues = 2 }, + { { 0x02, "TAGLOADS:The uop is a load operation" }, + { 0x04, "TAGSTORES:The uop is a store operation" } } +}; + +static const struct perfctr_unit_mask_4 p4_um_branch_retired = { + { .type = perfctr_um_type_bitmask, + .default_value = 0x0C, /* taken branches */ + .nvalues = 4 }, + { { 0x01, "MMNP:Branch Not-taken Predicted" }, + { 0x02, "MMNM:Branch Not-taken Mispredicted" }, + { 0x04, "MMTP:Branch Taken Predicted" }, + { 0x08, "MMTM:Branch Taken Mispredicted" } } +}; + +static const struct perfctr_unit_mask_1 p4_um_mispred_branch_retired = { + { .type = perfctr_um_type_bitmask, + .default_value = 0x01, + .nvalues = 1 }, + { { 0x01, "NBOGUS:The retired branch is not bogus" } } +}; + +static const struct perfctr_unit_mask_5 p4_um_x87_assist = { + { .type = perfctr_um_type_bitmask, + .default_value = 0x1F, + .nvalues = 5 }, + { { 0x01, "FPSU:FP stack underflow" }, + { 0x02, "FPSO:FP stack overflow" }, + { 0x04, "POAO:x87 output overflow" }, + { 0x08, "POAU:x87 output underflow" }, + { 0x10, "PREA:x87 input assist" } } +}; + +static const struct perfctr_unit_mask_3 p4_um_machine_clear = { + { .type = perfctr_um_type_bitmask, + .default_value = 0x01, + .nvalues = 3 }, + { { 0x01, "CLEAR:Count a portion of the cycles when the machine is cleared" }, + { 0x04, "MOCLEAR:Count clears due to memory ordering issues" }, + { 0x08, "SMCLEAR:Count clears due to self-modifying code issues" } } +}; + +static const struct perfctr_event p4_events[] = { + /* Non-Retirement Events: */ + { 0x01, TC_ESCR_0_1, UM(p4_um_TC_deliver_mode), "TC_deliver_mode", + "duration of the operating modes of the trace cache and decode engine" }, + { 0x03, BPU_ESCR_0_1, UM(p4_um_BPU_fetch_request), "BPU_fetch_request", + "instruction fetch requests by the Branch Prediction unit" }, + { 0x18, ITLB_ESCR_0_1, UM(p4_um_ITLB_reference), "ITLB_reference", + "translations using the Instruction Translation Look-aside Buffer" }, + { 0x02, DAC_ESCR_0_1, UM(p4_um_memory_cancel), "memory_cancel", + "cancelled requests in the Data cache Address Control unit" }, + { 0x08, SAAT_ESCR_0_1, UM(p4_um_memory_complete), "memory_complete", + "completed load split, store split, uncacheable split, uncacheable load" }, + { 0x04, SAAT_ESCR_0_1, UM(p4_um_load_port_replay), "load_port_replay", + /* XXX: only ESCR1 supports at-retirement */ + "replayed events at the load port" }, + { 0x05, SAAT_ESCR_0_1, UM(p4_um_store_port_replay), "store_port_replay", + /* XXX: only ESCR1 supports at-retirement */ + "replayed events at the store port" }, + { 0x03, MOB_ESCR_0_1, UM(p4_um_MOB_load_replay), "MOB_load_replay", + "replayed loads at the memory order buffer" }, + { 0x01, PMH_ESCR_0_1, UM(p4_um_page_walk_type), "page_walk_type", + "page walks by the page miss handler" }, + { 0x0C, BSU_ESCR_0_1, UM(p4_um_BSQ_cache_reference), "BSQ_cache_reference", + "cache references seen by the bus unit" }, + { 0x03, FSB_ESCR_0_1, UM(p4_um_IOQ), "IOQ_allocation", + /* XXX: ESCR1 unavailable if CPUID < 0xF27 */ + "bus transactions" }, + { 0x1A, FSB_ESCR_1, UM(p4_um_IOQ), "IOQ_active_entries", + "number of active IOQ entries" }, + { 0x17, FSB_ESCR_0_1, UM(p4_um_FSB_data_activity), "FSB_data_activity", + "DRDY or DBSY events on the front side bus" }, + { 0x05, BSU_ESCR_0, UM(p4_um_BSQ), "BSQ_allocation", + "allocations in the bus sequence unit" }, + { 0x06, BSU_ESCR_1, UM(p4_um_BSQ), "bsq_active_entries", + "number of active BSQ entries" }, + { 0x34, FIRM_ESCR_0_1, UM(p4_um_firm_uop), "SSE_input_assist", + "assists requested for SSE and SSE2 input operands" }, + { 0x08, FIRM_ESCR_0_1, UM(p4_um_firm_uop), "packed_SP_uop", + "packed single-precision uops" }, + { 0x0C, FIRM_ESCR_0_1, UM(p4_um_firm_uop), "packed_DP_uop", + "packed double-precision uops" }, + { 0x0A, FIRM_ESCR_0_1, UM(p4_um_firm_uop), "scalar_SP_uop", + "scalar single-precision uops" }, + { 0x0E, FIRM_ESCR_0_1, UM(p4_um_firm_uop), "scalar_DP_uop", + "scalar double-precision uops" }, + { 0x02, FIRM_ESCR_0_1, UM(p4_um_firm_uop), "64bit_MMX_uop", + "64 bit SIMD MMX instructions" }, + { 0x1A, FIRM_ESCR_0_1, UM(p4_um_firm_uop), "128bit_MMX_uop", + "128 bit integer SIMD SSE2 instructions" }, + { 0x04, FIRM_ESCR_0_1, UM(p4_um_firm_uop), "x87_FP_uop", + "x87 floating-point uops" }, + { 0x2E, FIRM_ESCR_0_1, UM(p4_um_x87_SIMD_moves_uop), "x87_SIMD_moves_uop", + "x87 FPU, MMX, SSE, or SSE2 load, store, and move uops" }, + { 0x06, TC_ESCR_0_1, UM(p4_um_TC_misc), "TC_misc", + "miscellaneous events detected by the TC" }, + { 0x13, FSB_ESCR_0_1, UM(p4_um_global_power_events), "global_power_events", + "time during which the processor is not stopped" }, + { 0x05, MS_ESCR_0_1, UM(p4_um_tc_ms_xfer), "tc_ms_xfer", + "number of times uop delivery changed from TC to MS ROM" }, + { 0x09, MS_ESCR_0_1, UM(p4_um_uop_queue_writes), "uop_queue_writes", + "number of valid uops written to the uop queue" }, + { 0x05, TBPU_ESCR_0_1, UM(p4_um_branch_type), "retired_mispred_branch_type", + "retired mispredicted branches by type" }, + { 0x04, TBPU_ESCR_0_1, UM(p4_um_branch_type), "retired_branch_type", + "retired branches by type" }, + { 0x01, ALF_ESCR_0_1, UM(p4_um_resource_stall), "resource_stall", + /* XXX: may not be supported in all P4 models */ + "stalls in the Allocator" }, + { 0x05, DAC_ESCR_0_1, UM(p4_um_WC_Buffer), "WC_Buffer", + "write combining buffer operations" }, + { 0x16, FSB_ESCR_0_1, UM(p4_um_b2b_cycles), "b2b_cycles", + /* XXX: may not be supported in all P4 models */ + "back-to-back bus cycles" }, + { 0x08, FSB_ESCR_0_1, UM(p4_um_bnr), "bnr", + /* XXX: may not be supported in all P4 models */ + "bus not ready conditions" }, + { 0x06, FSB_ESCR_0_1, UM(p4_um_snoop), "snoop", + /* XXX: may not be supported in all P4 models */ + "snoop hit modified bus traffic" }, + { 0x04, FSB_ESCR_0_1, UM(p4_um_response), "response", + /* XXX: may not be supported in all P4 models */ + "different types of responses" }, + { 0x08, CRU_ESCR_2_3, UM(p4_um_nbogus_bogus), "front_end_event", + /* XXX: another ESCR must count uop_type */ + /* XXX: can support PEBS */ + "retired uops, tagged by the front-end tagging mechanism" }, + { 0x0C, CRU_ESCR_2_3, UM(p4_um_execution_event), "execution_event", + /* XXX: needs upstream ESCR */ + /* XXX: can support PEBS */ + "retired uops, tagged by the execution tagging mechanism" }, + { 0x09, CRU_ESCR_2_3, UM(p4_um_nbogus_bogus), "replay_event", + /* XXX: needs PEBS_ENABLE, PEBS_MATRIX_VERT, and possibly upstream ESCR */ + /* XXX: can support PEBS */ + "retired uops, tagged by the replay tagging mechanism" }, + { 0x02, CRU_ESCR_0_1, UM(p4_um_instr_retired), "instr_retired", + "retired instructions" }, + { 0x01, CRU_ESCR_0_1, UM(p4_um_nbogus_bogus), "uops_retired", + "retired uops" }, + { 0x02, RAT_ESCR_0_1, UM(p4_um_uop_type), "uop_type", + "tag uops for the front-end tagging mechanism" }, + { 0x06, CRU_ESCR_2_3, UM(p4_um_branch_retired), "branch_retired", + "retired branches" }, + { 0x03, CRU_ESCR_0_1, UM(p4_um_mispred_branch_retired), "mispred_branch_retired", + "retired mispredicted branches" }, + { 0x03, CRU_ESCR_2_3, UM(p4_um_x87_assist), "x87_assist", + "retired x87 instructions that required special handling" }, + { 0x02, CRU_ESCR_2_3, UM(p4_um_machine_clear), "machine_clear", + "cycles or occurrences when the entire pipeline is cleared" }, +}; + +const struct perfctr_event_set perfctr_p4_event_set = { + .cpu_type = PERFCTR_X86_INTEL_P4, + .event_prefix = "P4_", + .include = NULL, + .nevents = ARRAY_SIZE(p4_events), + .events = p4_events, +}; + +/* + * Intel Pentium 4 Model 3 events. + */ + +static const struct perfctr_event p4m3_events[] = { + { 0x07, CRU_ESCR_0_1, UM(p4_um_nbogus_bogus), "instr_completed", + "retired and completed instructions" }, +}; + +const struct perfctr_event_set perfctr_p4m3_event_set = { + .cpu_type = PERFCTR_X86_INTEL_P4M3, + .event_prefix = "P4M3_", + .include = &perfctr_p4_event_set, + .nevents = ARRAY_SIZE(p4m3_events), + .events = p4m3_events, +}; diff --git a/kernel/fiasco/src/lib/perfctr/event_set_p5.c b/kernel/fiasco/src/lib/perfctr/event_set_p5.c new file mode 100644 index 00000000..1cae3ade --- /dev/null +++ b/kernel/fiasco/src/lib/perfctr/event_set_p5.c @@ -0,0 +1,283 @@ +/* $Id: event_set_p5.c 8293 2003-04-09 16:47:11Z fm3 $ + * Performance counter event descriptions for Intel P5 and P5 MMX + * processors, and Cyrix 6x86/MII/III processors. + * + * Copyright (C) 2003 Mikael Pettersson + * + * References + * ---------- + * [IA32, Volume 3] "Intel Architecture Software Developer's Manual, + * Volume 3: System Programming Guide". Intel document number 245472-009. + * (at http://developer.intel.com/) + * + * [Cyrix 6x86MX] "Cyrix 6x86MX Processor". + * [Cyrix MII] "Cyrix M II Data Book". + * [Cyrix III] "Cyrix III Processor DataBook" Ver. 1.0, 1/25/00. + * Note: This "Cyrix III" was code-named "Joshua", and it was apparently + * cancelled by VIA due to disappointing performance. + * (MII and III docs at http://www.viatech.com/) + */ +#include /* for NULL */ +#include "libperfctr.h" +#include "event_set.h" + +/* + * Intel Pentium (P5) events. + */ + +static const struct perfctr_event p5_events[] = { + { 0x00, 0x3, NULL, "DATA_READ", + "Number of memory data reads (internal data cache hit and " + "miss combined)." }, + { 0x01, 0x3, NULL, "DATA_WRITE", + "Number of memory data writes (internal data cache hit and " + "miss combined), I/O is not included." }, + { 0x02, 0x3, NULL, "DATA_TLB_MISS", + "Number of misses to the data cache translation look-aside " + "buffer." }, + { 0x03, 0x3, NULL, "DATA_READ_MISS", + "Number of memory read accesses that miss the internal data " + "cache whether or not the access is cacheable or noncacheable." }, + { 0x04, 0x3, NULL, "DATA_WRITE_MISS", + "Number of memory write accesses that miss the internal data " + "cache whether or not the access is cacheable or noncacheable." }, + { 0x05, 0x3, NULL, "WRITE_HIT_TO_M_OR_E_STATE_LINES", + "Number of write hits to exclusive or modified lines in the " + "data cache." }, + { 0x06, 0x3, NULL, "DATA_CACHE_LINES_WRITTEN_BACK", + "Number of dirty lines (all) that are written back, regardless " + "of the cause." }, + { 0x07, 0x3, NULL, "EXTERNAL_SNOOPS", + "Number of accepted external snoops whether they hit in the code " + "cache or data cache or neither." }, + { 0x08, 0x3, NULL, "EXTERNAL_DATA_CACHE_SNOOP_HITS", + "Number of external snoops to the data cache." }, + { 0x09, 0x3, NULL, "MEMORY_ACCESSES_IN_BOTH_PIPES", + "Number of data memory reads or writes that are paired in both " + "pipes of the pipeline." }, + { 0x0A, 0x3, NULL, "BANK_CONFLICTS", + "Number of actual bank conflicts." }, + { 0x0B, 0x3, NULL, "MISALIGNED_DATA_MEMORY_OR_IO_REFERENCES", + "Number of memory or I/O reads or writes that are misaligned." }, + { 0x0C, 0x3, NULL, "CODE_READ", + "Number of instruction reads whether the read is cacheable or " + "noncacheable." }, + { 0x0D, 0x3, NULL, "CODE_TLB_MISS", + "Number of instruction reads that miss the code TLB whether " + "the read is cacheable or noncacheable." }, + { 0x0E, 0x3, NULL, "CODE_CACHE_MISS", + "Number of instruction reads that miss the internal code cache " + "whether the read is cacheable or noncacheable." }, + { 0x0F, 0x3, NULL, "ANY_SEGMENT_REGISTER_LOADED", + "Number of writes into any segment register in real or protected " + "mode including the LDTR, GDTR, IDTR, and TR." }, + /* 0x10: reserved */ + /* 0x11: reserved */ + { 0x12, 0x3, NULL, "BRANCHES", + "Number of taken and not taken branches, including conditional " + "branches, jumps, calls, returns, software interrupts, and " + "interrupt returns." }, + { 0x13, 0x3, NULL, "BTB_HITS", + "Number of BTB hits that occur." }, + { 0x14, 0x3, NULL, "TAKEN_BRANCH_OR_BTB_HIT", + "Number of taken branches or BTB hits that occur." }, + { 0x15, 0x3, NULL, "PIPELINE_FLUSHES", + "Number of pipeline flushes that occur." }, + { 0x16, 0x3, NULL, "INSTRUCTIONS_EXECUTED", + "Number of instructions executed (up to two per clock)." }, + { 0x17, 0x3, NULL, "INSTRUCTIONS_EXECUTED_V_PIPE", /* XXX: was INSTRUCTIONS_EXECUTED_IN_V_PIPE */ + "Number of instructions executed in the V_pipe. It indicates " + "the number of instructions that were paired." }, + { 0x18, 0x3, NULL, "BUS_CYCLE_DURATION", + "Number of clocks while a bus cycle is in progress." }, + { 0x19, 0x3, NULL, "WRITE_BUFFER_FULL_STALL_DURATION", + "Number of clocks while the pipeline is stalled due to full " + "write buffers." }, + { 0x1A, 0x3, NULL, "WAITING_FOR_DATA_MEMORY_READ_STALL_DURATION", + "Number of clocks while the pipeline is stalled while waiting " + "for data memory reads." }, + { 0x1B, 0x3, NULL, "STALL_ON_WRITE_TO_AN_E_OR_M_STATE_LINE", + "Number of stalls on writes to E- or M-state lines." }, + { 0x1C, 0x3, NULL, "LOCKED_BUS_CYCLE", + "Number of locked bus cycles that occur as the result of " + "LOCK prefix or LOCK instruction, page-table updates, and " + "descriptor table updates." }, + { 0x1D, 0x3, NULL, "IO_READ_OR_WRITE_CYCLE", + "Number of bus cycles directed to I/O space." }, + { 0x1E, 0x3, NULL, "NONCACHEABLE_MEMORY_READS", + "Number of noncacheable instruction or data memory read bus cycles." }, + { 0x1F, 0x3, NULL, "PIPELINE_AGI_STALLS", + "Number of adress generation interlock (AGI) stalls." }, + /* 0x20: reserved */ + /* 0x21: reserved */ + { 0x22, 0x3, NULL, "FLOPS", + "Number of floating-point operations that occur." }, + { 0x23, 0x3, NULL, "BREAKPOINT_MATCH_ON_DR0_REGISTER", + "Number of matches on DR0 breakpoint." }, + { 0x24, 0x3, NULL, "BREAKPOINT_MATCH_ON_DR1_REGISTER", + "Number of matches on DR1 breakpoint." }, + { 0x25, 0x3, NULL, "BREAKPOINT_MATCH_ON_DR2_REGISTER", + "Number of matches on DR2 breakpoint." }, + { 0x26, 0x3, NULL, "BREAKPOINT_MATCH_ON_DR3_REGISTER", + "Number of matches on DR3 breakpoint." }, + { 0x27, 0x3, NULL, "HARDWARE_INTERRUPTS", + "Number of taken INTR and NMI interrupts." }, + { 0x28, 0x3, NULL, "DATA_READ_OR_WRITE", + "Number of memory data reads and/or writes (internal data cache " + "hit and miss combined)." }, + { 0x29, 0x3, NULL, "DATA_READ_MISS_OR_WRITE_MISS", + "Number of memory read and/or write accesses that miss the " + "internal data cache whether or not the acceess is cacheable " + "or noncacheable." }, +}; + +const struct perfctr_event_set perfctr_p5_event_set = { + .cpu_type = PERFCTR_X86_INTEL_P5, + .event_prefix = "P5_", + .include = NULL, + .nevents = ARRAY_SIZE(p5_events), + .events = p5_events, +}; + +/* + * Intel Pentium MMX (P5MMX) events. + */ + +static const struct perfctr_event p5mmx_and_mii_events[] = { + { 0x2B, 0x1, NULL, "MMX_INSTRUCTIONS_EXECUTED_U_PIPE", + "Number of MMX instructions executed in the U-pipe." }, + { 0x2B, 0x2, NULL, "MMX_INSTRUCTIONS_EXECUTED_V_PIPE", + "Number of MMX instructions executed in the V-pipe." }, + { 0x2D, 0x1, NULL, "EMMS_INSTRUCTIONS_EXECUTED", + "Number of EMMS instructions executed." }, + { 0x2D, 0x2, NULL, "TRANSITIONS_BETWEEN_MMX_AND_FP_INSTRUCTIONS", + "Number of transitions between MMX and floating-point instructions " + "or vice versa." }, + { 0x2F, 0x1, NULL, "SATURATING_MMX_INSTRUCTIONS_EXECUTED", + "Number of saturating MMX instructions executed, independently of " + "whether they actually saturated." }, + { 0x2F, 0x2, NULL, "SATURATIONS_PERFORMED", + "Number of MMX instructions that used saturating arithmetic and " + "that at least one of its results actually saturated." }, + { 0x31, 0x1, NULL, "MMX_INSTRUCTION_DATA_READS", + "Number of MMX instruction data reads." }, + { 0x32, 0x2, NULL, "TAKEN_BRANCHES", + "Number of taken branches." }, + { 0x37, 0x1, NULL, "MISPREDICTED_OR_UNPREDICTED_RETURNS", + "Number of returns predicted incorrectly or not predicted at all." }, + { 0x37, 0x2, NULL, "PREDICTED_RETURNS", + "Number of predicted returns (whether they are predicted correctly " + "and incorrectly)." }, + { 0x38, 0x1, NULL, "MMX_MULTIPLY_UNIT_INTERLOCK", + "Number of clocks the pipe is stalled since the destination of " + "previous MMX instruction is not ready yet." }, + { 0x38, 0x2, NULL, "MOVD_MOVQ_STORE_STALL_DUE_TO_PREVIOUS_MMX_OPERATION", + "Number of clocks a MOVD/MOVQ instruction store is stalled in D2 " + "stage due to a previous MMX operation with a destination to be " + "used in the store instruction." }, + { 0x39, 0x1, NULL, "RETURNS", + "Number of returns executed." }, + { 0x3A, 0x1, NULL, "BTB_FALSE_ENTRIES", + "Number of false entries in the Branch Target Buffer." }, + { 0x3A, 0x2, NULL, "BTB_MISS_PREDICTION_ON_NOT_TAKEN_BRANCH", + "Number of times the BTB predicted a not-taken branch as taken." }, + { 0x3B, 0x1, NULL, "FULL_WRITE_BUFFER_STALL_DURATION_WHILE_EXECUTING_MMX_INSTRUCTIONS", + "Number of clocks while the pipeline is stalled due to full write " + "buffers while executing MMX instructions." }, + { 0x3B, 0x2, NULL, "STALL_ON_MMX_INSTRUCTION_WRITE_TO_E_OR_M_STATE_LINE", + "Number of clocks during stalls on MMX instructions writing " + "to E- or M-state lines." }, +}; + +static const struct perfctr_event_set p5mmx_and_mii_event_set = { + .cpu_type = PERFCTR_X86_INTEL_P5MMX, + .event_prefix = "P5MMX_", + .include = &perfctr_p5_event_set, + .nevents = ARRAY_SIZE(p5mmx_and_mii_events), + .events = p5mmx_and_mii_events, +}; + +static const struct perfctr_event p5mmx_events[] = { + { 0x2A, 0x1, NULL, "BUS_OWNERSHIP_LATENCY", + "The time from LRM bus ownership request to bus ownership granted." }, + { 0x2A, 0x2, NULL, "BUS_OWNERSHIP_TRANSFERS", + "The number of bus ownership transfers." }, + { 0x2C, 0x1, NULL, "CACHE_M_STATE_LINE_SHARING", + "Number of times a processor identified a hit to a modified line " + "due to a memory access in the other processor." }, + { 0x2C, 0x2, NULL, "CACHE_LINE_SHARING", + "Number of shared data lines in the L1 cache." }, + { 0x2E, 0x1, NULL, "BUS_UTILIZATION_DUE_TO_PROCESSOR_ACTIVITY", + "Number of clocks the bus is busy due to the processor's own activity." }, + { 0x2E, 0x2, NULL, "WRITES_TO_NONCACHEABLE_MEMORY", + "Number of write accesses to noncacheable memory." }, + { 0x30, 0x1, NULL, "NUMBER_OF_CYCLES_NOT_IN_HALT_STATE", + "Number of cycles the processor is not idle due to HLT instruction." }, + { 0x30, 0x2, NULL, "DATA_CACHE_TLB_MISS_STALL_DURATION", + "Number of clocks the pipeline is stalled due to a data cache " + "translation look-aside buffer (TLB) miss." }, + { 0x31, 0x2, NULL, "MMX_INSTRUCTION_DATA_READ_MISSES", + "Number of MMX instruction data read misses." }, + { 0x32, 0x1, NULL, "FLOATING_POINT_STALLS_DURATION", + "Number of clocks while pipe is stalled due to a floating-point freeze." }, + { 0x33, 0x1, NULL, "D1_STARVATION_AND_FIFO_IS_EMPTY", + "Number of times D1 stage cannot issue ANY instructions since the " + "FIFO buffer is empty." }, + { 0x33, 0x2, NULL, "D1_STARVATION_AND_ONLY_ONE_INSTRUCTION_IN_FIFO", + "Number of times the D1 stage issues just a single instruction since " + "the FIFO buffer had just one instruction ready." }, + { 0x34, 0x1, NULL, "MMX_INSTRUCTION_DATA_WRITES", + "Number of data writes caused by MMX instructions." }, + { 0x34, 0x2, NULL, "MMX_INSTRUCTION_DATA_WRITE_MISSES", + "Number of data write misses caused by MMX instructions." }, + { 0x35, 0x1, NULL, "PIPELINE_FLUSHES_DUE_TO_WRONG_BRANCH_PREDICTIONS", + "Number of pipeline flushes due to wrong branch prediction resolved " + "in either the E-stage or the WB-stage." }, + { 0x35, 0x2, NULL, "PIPELINE_FLUSHES_DUE_TO_WRONG_BRANCH_PREDICTIONS_RESOLVED_IN_WB_STAGE", + "Number of pipeline flushes due to wrong branch prediction resolved " + "in the WB-stage." }, + { 0x36, 0x1, NULL, "MISALIGNED_DATA_MEMORY_REFERENCE_ON_MMX_INSTRUCTIONS", + "Number of misaligned data memory references when executing MMX " + "instructions." }, + { 0x36, 0x2, NULL, "PIPELINE_ISTALL_FOR_MMX_INSTRUCTION_DATA_MEMORY_READS", + "Number of clocks during pipeline stalls caused by waits from MMX " + "instructions data memory reads." }, + /* 0x39, counter 1: reserved */ +}; + +const struct perfctr_event_set perfctr_p5mmx_event_set = { + .cpu_type = PERFCTR_X86_INTEL_P5MMX, + .event_prefix = "P5MMX_", + .include = &p5mmx_and_mii_event_set, + .nevents = ARRAY_SIZE(p5mmx_events), + .events = p5mmx_events, +}; + +/* + * Cyrix 6x86MX, MII, and III events. + */ + +static const struct perfctr_event mii_events[] = { + { 0x039, 0x2, NULL, "RSB_OVERFLOWS", 0 }, + /* NOTE: The manuals list the following events as having codes 40-48. + However, the 7-bit event code is actually split in the CESR, using + bits 0-5 and 10, and similarly for the high half of the CESR. + Since the driver also parses the other fields (bits 6-9) in a user's + evntsel, the events are listed here with their actual in-CESR values. */ + { 0x400, 0x3, NULL, "L2_TLB_MISSES", 0 }, + { 0x401, 0x3, NULL, "L1_TLB_DATA_MISS", 0 }, + { 0x402, 0x3, NULL, "L1_TLB_CODE_MISS", 0 }, + { 0x403, 0x3, NULL, "L1_TLB_MISS", 0 }, + { 0x404, 0x3, NULL, "TLB_FLUSHES", 0 }, + { 0x405, 0x3, NULL, "TLB_PAGE_INVALIDATES", 0 }, + { 0x406, 0x3, NULL, "TLB_PAGE_INVALIDATES_THAT_HIT", 0 }, + { 0x408, 0x3, NULL, "INSTRUCTIONS_DECODED", 0 }, +}; + +const struct perfctr_event_set perfctr_mii_event_set = { + .cpu_type = PERFCTR_X86_CYRIX_MII, + .event_prefix = "MII_", + .include = &p5mmx_and_mii_event_set, + .nevents = ARRAY_SIZE(mii_events), + .events = mii_events, +}; diff --git a/kernel/fiasco/src/lib/perfctr/event_set_p6.c b/kernel/fiasco/src/lib/perfctr/event_set_p6.c new file mode 100644 index 00000000..5cab6e3f --- /dev/null +++ b/kernel/fiasco/src/lib/perfctr/event_set_p6.c @@ -0,0 +1,486 @@ +/* $Id: event_set_p6.c 37048 2009-11-12 21:44:56Z adam $ + * Performance counter event descriptions for the Intel P6 family. + * + * Copyright (C) 2003-2004 Mikael Pettersson + * + * References + * ---------- + * [IA32, Volume 3] "Intel Architecture Software Developer's Manual, + * Volume 3: System Programming Guide". Intel document number 25366813. + * (at http://developer.intel.com/) + */ +#include /* for NULL */ +#include "libperfctr.h" +#include "event_set.h" + +/* + * Intel Pentium Pro events. + * Note that four L2 events were redefined in Pentium M. + */ + +static const struct perfctr_unit_mask_4 p6_um_mesi = { + { .type = perfctr_um_type_bitmask, + .default_value = 0x0F, + .nvalues = 4 }, + { { 0x08, "M (modified cache state)" }, + { 0x04, "E (exclusive cache state)" }, + { 0x02, "S (shared cache state)" }, + { 0x01, "I (invalid cache state)" } } +}; + +static const struct perfctr_unit_mask_2 p6_um_ebl = { + { .type = perfctr_um_type_exclusive, + .default_value = 0x20, + .nvalues = 2 }, + { { 0x20, "transactions from any processor" }, + { 0x00, "self-generated transactions" } } +}; + +static const struct perfctr_event p6_events[] = { + /* Data Cache Unit (DCU) */ + { 0x43, 0x3, NULL, "DATA_MEM_REFS", + "All memory references, cachable and non" }, + { 0x45, 0x3, NULL, "DCU_LINES_IN", + "Total lines allocated in the DCU" }, + { 0x46, 0x3, NULL, "DCU_M_LINES_IN", + "Number of M state lines allocated in DCU" }, + { 0x47, 0x3, NULL, "DCU_M_LINES_OUT", + "Number of M lines evicted from the DCU" }, + { 0x48, 0x3, NULL, "DCU_MISS_OUTSTANDING", + "Number of cycles while DCU miss outstanding" }, + /* Instruction Fetch Unit (IFU) */ + { 0x80, 0x3, NULL, "IFU_IFETCH", + "Number of non/cachable instruction fetches" }, /* XXX: was IFU_FETCH */ + { 0x81, 0x3, NULL, "IFU_IFETCH_MISS", + "Number of instruction fetch misses" }, /* XXX: was IFU_FETCH_MISS */ + { 0x85, 0x3, NULL, "ITLB_MISS", + "Number of ITLB misses" }, + { 0x86, 0x3, NULL, "IFU_MEM_STALL", + "Cycles instruction fetch pipe is stalled" }, + { 0x87, 0x3, NULL, "ILD_STALL", + "Cycles instruction length decoder is stalled" }, + /* L2 Cache */ + { 0x28, 0x3, UM(p6_um_mesi), "L2_IFETCH", + "Number of L2 instruction fetches" }, + { 0x2A, 0x3, UM(p6_um_mesi), "L2_ST", + "Number of L2 data stores" }, + { 0x25, 0x3, NULL, "L2_M_LINES_INM", + "Number of modified lines allocated in L2" }, + { 0x2E, 0x3, UM(p6_um_mesi), "L2_RQSTS", + "Number of L2 requests" }, + { 0x21, 0x3, NULL, "L2_ADS", + "Number of L2 address strobes" }, + { 0x22, 0x3, NULL, "L2_DBUS_BUSY", + "Number of cycles data bus was busy" }, + { 0x23, 0x3, NULL, "L2_DBUS_BUSY_RD", + "Cycles data bus was busy in xfer from L2 to CPU" }, + /* External Bus Logic (EBL) */ + { 0x62, 0x3, UM(p6_um_ebl), "BUS_DRDY_CLOCKS", + "Number of clocks DRDY is asserted" }, + { 0x63, 0x3, UM(p6_um_ebl), "BUS_LOCK_CLOCKS", + "Number of clocks LOCK is asserted" }, + { 0x60, 0x3, NULL, "BUS_REQ_OUTSTANDING", + "Number of outstanding bus requests" }, + { 0x65, 0x3, UM(p6_um_ebl), "BUS_TRAN_BRD", + "Number of burst read transactions" }, + { 0x66, 0x3, UM(p6_um_ebl), "BUS_TRAN_RFO", + "Number of read for ownership transactions" }, + { 0x67, 0x3, UM(p6_um_ebl), "BUS_TRANS_WB", + "Number of write back transactions" }, + { 0x68, 0x3, UM(p6_um_ebl), "BUS_TRAN_IFETCH", + "Number of instruction fetch transactions" }, + { 0x69, 0x3, UM(p6_um_ebl), "BUS_TRAN_INVAL", + "Number of invalidate transactions" }, + { 0x6A, 0x3, UM(p6_um_ebl), "BUS_TRAN_PWR", + "Number of partial write transactions" }, + { 0x6B, 0x3, UM(p6_um_ebl), "BUS_TRANS_P", + "Number of partial transactions" }, + { 0x6C, 0x3, UM(p6_um_ebl), "BUS_TRANS_IO", + "Number of I/O transactions" }, + { 0x6D, 0x3, UM(p6_um_ebl), "BUS_TRAN_DEF", 0 }, + { 0x6E, 0x3, UM(p6_um_ebl), "BUS_TRAN_BURST", + "Number of burst transactions" }, + { 0x70, 0x3, UM(p6_um_ebl), "BUS_TRAN_ANY", + "Number of all transactions" }, + { 0x6F, 0x3, UM(p6_um_ebl), "BUS_TRAN_MEM", + "Number of memory transactions" }, + { 0x64, 0x3, NULL, "BUS_DATA_RCV", + "Bus cycles this processor is receiving data" }, + { 0x61, 0x3, NULL, "BUS_BNR_DRV", + "Bus cycles this processor is driving BNR pin" }, + { 0x7A, 0x3, NULL, "BUS_HIT_DRV", + "Bus cycles this processor is driving HIT pin" }, + { 0x7B, 0x3, NULL, "BUS_HITM_DRV", + "Bus cycles this processor is driving HITM pin" }, + { 0x7E, 0x3, NULL, "BUS_SNOOP_STALL", + "Cycles during bus snoop stall" }, + /* Floating-Point Unit */ + { 0xC1, 0x1, NULL, "FLOPS", + "Number of computational FP operations executed" }, + { 0x10, 0x1, NULL, "FP_COMP_OPS_EXE", + "Number of computational FP operations executed" }, + { 0x11, 0x2, NULL, "FP_ASSIST", + "Number of FP exceptions handled by microcode" }, + { 0x12, 0x2, NULL, "MUL", + "Number of multiplies" }, + { 0x13, 0x2, NULL, "DIV", + "Number of divides" }, + { 0x14, 0x1, NULL, "CYCLES_DIV_BUSY", + "Cycles divider is busy" }, + /* Memory Ordering */ + { 0x03, 0x3, NULL, "LD_BLOCKS", + "Number of store buffer blocks" }, + { 0x04, 0x3, NULL, "SB_DRAINS", + "Number of store buffer drain cycles" }, + { 0x05, 0x3, NULL, "MISALIGN_MEM_REF", + "Number of misaligned data memory references" }, + /* Instruction Decoding and Retirement */ + { 0xC0, 0x3, NULL, "INST_RETIRED", + "Number of instructions retired" }, + { 0xC2, 0x3, NULL, "UOPS_RETIRED", + "Number of UOPs retired" }, + { 0xD0, 0x3, NULL, "INST_DECODED", + "Number of instructions decoded" }, + /* Interrupts */ + { 0xC8, 0x3, NULL, "HW_INT_RX", + "Number of hardware interrupts received" }, + { 0xC6, 0x3, NULL, "CYCLES_INT_MASKED", + "Cycles interrupts are disabled" }, + { 0xC7, 0x3, NULL, "CYCLES_INT_PENDING_AND_MASKED", + "Cycles interrupts are disabled with pending interrupts" }, + /* Branches */ + { 0xC4, 0x3, NULL, "BR_INST_RETIRED", + "Number of branch instructions retired" }, + { 0xC5, 0x3, NULL, "BR_MISS_PRED_RETIRED", + "Number of mispredicted branches retired" }, + { 0xC9, 0x3, NULL, "BR_TAKEN_RETIRED", + "Number of taken branches retired" }, + { 0xCA, 0x3, NULL, "BR_MISS_PRED_TAKEN_RET", + "Number of taken mispredictions branches retired" }, + { 0xE0, 0x3, NULL, "BR_INST_DECODED", + "Number of branch instructions decoded" }, + { 0xE2, 0x3, NULL, "BTB_MISSES", + "Number of branches that miss the BTB" }, + { 0xE4, 0x3, NULL, "BR_BOGUS", + "Number of bogus branches" }, + { 0xE6, 0x3, NULL, "BACLEARS", + "Number of times BACLEAR is asserted" }, + /* Stalls */ + { 0xA2, 0x3, NULL, "RESOURCE_STALLS", + "Cycles during resource related stalls" }, + { 0xD2, 0x3, NULL, "PARTIAL_RAT_STALLS", + "Cycles or events for partial stalls" }, + /* Segment Register Loads */ + { 0x06, 0x3, NULL, "SEGMENT_REG_LOADS", + "Number of segment register loads" }, + /* Clocks */ + { 0x79, 0x3, NULL, "CPU_CLK_UNHALTED", + "Clocks processor is not halted" }, +}; + +const struct perfctr_event_set p6_event_set = { + .cpu_type = PERFCTR_X86_INTEL_P6, + .event_prefix = "P6_", + .include = NULL, + .nevents = ARRAY_SIZE(p6_events), + .events = p6_events, +}; + +static const struct perfctr_event ppro_events[] = { + /* L2 cache */ + { 0x29, 0x3, UM(p6_um_mesi), "L2_LD", + "Number of L2 data loads" }, /* redefined in Pentium M */ + { 0x24, 0x3, NULL, "L2_LINES_IN", + "Number of allocated lines in L2" }, /* redefined in Pentium M */ + { 0x26, 0x3, NULL, "L2_LINES_OUT", + "Number of recovered lines from L2" }, /* redefined in Pentium M */ + { 0x27, 0x3, NULL, "L2_M_LINES_OUTM", + "Number of modified lines removed from L2" }, /* redefined in Pentium M */ +}; + +const struct perfctr_event_set perfctr_ppro_event_set = { + .cpu_type = PERFCTR_X86_INTEL_P6, + .event_prefix = "P6_", + .include = &p6_event_set, + .nevents = ARRAY_SIZE(ppro_events), + .events = ppro_events, +}; + +/* + * Intel Pentium II events. + * Note that two PII events (0xB0 and 0xCE) are unavailable in the PIII. + */ + +static const struct perfctr_unit_mask_0 p2_um_mmx_uops_exec = { + { .type = perfctr_um_type_fixed, + .default_value = 0x0F, + .nvalues = 0 } +}; + +static const struct perfctr_unit_mask_6 p2_um_mmx_instr_type_exec = { + { .type = perfctr_um_type_bitmask, + .default_value = 0x3F, + .nvalues = 6 }, + { { 0x01, "MMX packed multiplies" }, + { 0x02, "MMX packed shifts" }, + { 0x04, "MMX pack operations" }, + { 0x08, "MMX unpack operations" }, + { 0x10, "MMX packed logical instructions" }, + { 0x20, "MMX packed arithmetic instructions" } } +}; + +static const struct perfctr_unit_mask_2 p2_um_fp_mmx_trans = { + { .type = perfctr_um_type_exclusive, + .default_value = 0x00, + .nvalues = 2 }, + { { 0x00, "MMX to FP transitions" }, + { 0x01, "FP to MMX transitions" } } +}; + +static const struct perfctr_unit_mask_4 p2_um_seg_reg_rename = { + { .type = perfctr_um_type_bitmask, + .default_value = 0x0F, + .nvalues = 4 }, + { { 0x01, "segment register ES" }, + { 0x02, "segment register DS" }, + { 0x04, "segment register FS" }, + { 0x08, "segment register GS" } } +}; + +static const struct perfctr_event p2andp3_events[] = { + /* MMX Unit */ + { 0xB1, 0x3, NULL, "MMX_SAT_INSTR_EXEC", + "Number of MMX saturating instructions executed" }, + { 0xB2, 0x3, UM(p2_um_mmx_uops_exec), "MMX_UOPS_EXEC", + "Number of MMX UOPS executed" }, + { 0xB3, 0x3, UM(p2_um_mmx_instr_type_exec), "MMX_INSTR_TYPE_EXEC", + "Number of MMX packing instructions" }, + { 0xCC, 0x3, UM(p2_um_fp_mmx_trans), "FP_MMX_TRANS", + "MMX-floating point transitions" }, + { 0xCD, 0x3, NULL, "MMX_ASSIST", + "Number of EMMS instructions executed" }, + /* Segment Register Renaming */ + { 0xD4, 0x3, UM(p2_um_seg_reg_rename), "SEG_RENAME_STALLS", 0 }, + { 0xD5, 0x3, UM(p2_um_seg_reg_rename), "SEG_REG_RENAMES", 0 }, + { 0xD6, 0x3, NULL, "RET_SEG_RENAMES", 0 }, +}; + +static const struct perfctr_event_set p2andp3_event_set = { + .cpu_type = PERFCTR_X86_INTEL_PII, + .event_prefix = "PII_", + .include = &perfctr_ppro_event_set, + .nevents = ARRAY_SIZE(p2andp3_events), + .events = p2andp3_events, +}; + +static const struct perfctr_event p2_events[] = { /* not in PIII :-( */ + /* MMX Unit */ + { 0xB0, 0x3, NULL, "MMX_INSTR_EXEC", 0 }, + { 0xCE, 0x3, NULL, "MMX_INSTR_RET", + "Number of MMX instructions retired" }, +}; + +const struct perfctr_event_set perfctr_p2_event_set = { + .cpu_type = PERFCTR_X86_INTEL_PII, + .event_prefix = "PII_", + .include = &p2andp3_event_set, + .nevents = ARRAY_SIZE(p2_events), + .events = p2_events, +}; + +/* + * Intel Pentium III events. + * Note that the two KNI decoding events were redefined in Pentium M. + */ + +static const struct perfctr_unit_mask_4 p3_um_kni_prefetch = { + { .type = perfctr_um_type_exclusive, + .default_value = 0x00, + .nvalues = 4 }, + { { 0x00, "prefetch NTA" }, + { 0x01, "prefetch T1" }, + { 0x02, "prefetch T2" }, + { 0x03, "weakly ordered stores" } } +}; + +static const struct perfctr_event p3_events_1[] = { + /* Memory Ordering */ + { 0x07, 0x3, UM(p3_um_kni_prefetch), "EMON_KNI_PREF_DISPATCHED", + "Number of KNI pre-fetch/weakly ordered insns dispatched" }, + { 0x4B, 0x3, UM(p3_um_kni_prefetch), "EMON_KNI_PREF_MISS", + "Number of KNI pre-fetch/weakly ordered insns that miss all caches" }, +}; + +static const struct perfctr_event_set p3_event_set_1 = { + .cpu_type = PERFCTR_X86_INTEL_PIII, + .event_prefix = "PIII_", + .include = &p2andp3_event_set, + .nevents = ARRAY_SIZE(p3_events_1), + .events = p3_events_1, +}; + +static const struct perfctr_unit_mask_2 p3_um_kni_inst_retired = { + { .type = perfctr_um_type_exclusive, + .default_value = 0x00, + .nvalues = 2 }, + { { 0x00, "packed and scalar" }, + { 0x01, "scalar" } } +}; + +static const struct perfctr_event p3_events_2[] = { + /* Instruction Decoding and Retirement */ + { 0xD8, 0x3, UM(p3_um_kni_inst_retired), "EMON_KNI_INST_RETIRED", + "Number of KNI instructions retired" }, /* redefined in Pentium M */ + { 0xD9, 0x3, UM(p3_um_kni_inst_retired), "EMON_KNI_COMP_INST_RET", + "Number of KNI computation instructions retired" }, /* redefined in Pentium M */ +}; + +const struct perfctr_event_set perfctr_p3_event_set = { + .cpu_type = PERFCTR_X86_INTEL_PIII, + .event_prefix = "PIII_", + .include = &p3_event_set_1, + .nevents = ARRAY_SIZE(p3_events_2), + .events = p3_events_2, +}; + +/* + * Intel Pentium M events. + * Note that six PPro/PIII events were redefined. To describe that + * we have to break up the PPro and PIII event sets, and assemble + * the Pentium M event set in several steps. + */ + +static const struct perfctr_unit_mask_6 pentm_um_mesi_prefetch = { + { .type = perfctr_um_type_bitmask, + .default_value = 0x0F, + .nvalues = 6 }, + /* XXX: how should we describe that bits 5-4 are a single field? */ + { { 0x01, "I (invalid cache state)" }, + { 0x02, "S (shared cache state)" }, + { 0x04, "E (exclusive cache state)" }, + { 0x08, "M (modified cache state)" }, + /* Bits 5-4: 00: all but HW-prefetched lines, 01: only HW-prefetched + lines, 10/11: all lines */ + { 0x10, "prefetch type bit 0" }, + { 0x20, "prefetch type bit 1" } } +}; + +static const struct perfctr_unit_mask_2 pentm_um_est_trans = { + { .type = perfctr_um_type_exclusive, + .default_value = 0x00, + .nvalues = 2 }, + { { 0x00, "All transitions" }, + { 0x02, "Only Frequency transitions" } } +}; + +static const struct perfctr_unit_mask_4 pentm_um_sse_inst_ret = { + { .type = perfctr_um_type_exclusive, + .default_value = 0x00, + .nvalues = 4 }, + { { 0x00, "SSE Packed Single and Scalar Single" }, + { 0x01, "SSE Packed-Single" }, + { 0x02, "SSE2 Packed-Double" }, + { 0x03, "SSE2 Scalar-Double" } } +}; + +static const struct perfctr_unit_mask_4 pentm_um_sse_comp_inst_ret = { + { .type = perfctr_um_type_exclusive, + .default_value = 0x00, + .nvalues = 4 }, + { { 0x00, "SSE Packed Single" }, + { 0x01, "SSE Scalar-Single" }, + { 0x02, "SSE2 Packed-Double" }, + { 0x03, "SSE2 Scalar-Double" } } +}; + +static const struct perfctr_unit_mask_3 pentm_um_fused_uops = { + { .type = perfctr_um_type_exclusive, + .default_value = 0x00, + .nvalues = 3 }, + { { 0x00, "All fused micro-ops" }, + { 0x01, "Only load+Op micro-ops" }, + { 0x02, "Only std+sta micro-ops" } } +}; + +static const struct perfctr_event pentm_events[] = { + /* L2 cache */ + { 0x24, 0x3, UM(pentm_um_mesi_prefetch), "L2_LINES_IN", + "Number of allocated lines in L2" }, /* redefined */ + { 0x26, 0x3, UM(pentm_um_mesi_prefetch), "L2_LINES_OUT", + "Number of recovered lines from L2" }, /* redefined */ + { 0x27, 0x3, UM(pentm_um_mesi_prefetch), "L2_M_LINES_OUT", + "Number of modified lines in L2, except hardware-prefetched" }, /* redefined */ + { 0x29, 0x3, UM(pentm_um_mesi_prefetch), "L2_LD", + "Number of L2 data loads" }, /* redefined */ + /* Power Management */ + { 0x58, 0x3, UM(pentm_um_est_trans), "EMON_EST_TRANS", + "Number of SpeedStep(R) thermal transitions" }, + { 0x59, 0x3, NULL, "EMON_THERMAL_TRIP", /*XXX: set bit 22(!?) for edge */ + "Number of thermal trips (CPU temp exceeded 100C)" }, + /* BPU */ + { 0x88, 0x3, NULL, "BR_INST_EXEC", + "All executed branches (not necessarily retired)" }, + { 0x89, 0x3, NULL, "BR_MISSP_EXEC", + "Number of branch instruction mispredicted at execution" }, + { 0x8A, 0x3, NULL, "BR_BAC_MISSP_EXEC", + "Number of branch instructions mispredicted at decoding" }, + { 0x8B, 0x3, NULL, "BR_CND_EXEC", + "Number of conditional branch instructions executed" }, + { 0x8C, 0x3, NULL, "BR_CND_MISSP_EXEC", + "Number of mispredicted conditional branch instructions executed" }, + { 0x8D, 0x3, NULL, "BR_IND_EXEC", + "Number of indirect branch instructions executed" }, + { 0x8E, 0x3, NULL, "BR_IND_MISSP_EXEC", + "Number of mispredicted indirect branch instructions executed" }, + { 0x8F, 0x3, NULL, "BR_RET_EXEC", + "Number of return branch instructions executed" }, + { 0x90, 0x3, NULL, "BR_RET_MISSP_EXEC", + "Number of mispredicted return branch instructions executed"}, + { 0x91, 0x3, NULL, "BR_RET_BAC_MISSP_EXEC", + "Number of executed return branch instructions mispredicted at decoding" }, + { 0x92, 0x3, NULL, "BR_CALL_EXEC", + "Number of function calls executed using CALL instruction" }, + { 0x93, 0x3, NULL, "BR_CALL_MISSP_EXEC", + "Number of mispredicted CALL instructions executed" }, + { 0x94, 0x3, NULL, "BR_IND_CALL_EXEC", + "Number of mispredicted indirect CALL instructions executed" }, + /* Decoder */ + { 0xCE, 0x3, NULL, "EMON_SIMD_INSTR_RETIRED", + "Number of SIMD instructions retired" }, + { 0xD3, 0x3, NULL, "EMON_SYNCH_UOPS", 0 }, + { 0xD7, 0x3, NULL, "EMON_ESP_UOPS", 0 }, + { 0xD8, 0x3, UM(pentm_um_sse_inst_ret), "EMON_SSE_SSE2_INST_RETIRED", + "Number of SSE2 instructions retired" }, /* redefined */ + { 0xD9, 0x3, UM(pentm_um_sse_comp_inst_ret), "EMON_SSE_SSE2_COMP_INST_RETIRED", + "Number of scalar-double SSE2 instructions retired" }, /* redefined */ + { 0xDA, 0x3, UM(pentm_um_fused_uops), "EMON_FUSED_UOPS_RET", + "Number of fused UOPS retired" }, + { 0xDB, 0x3, NULL, "EMON_UNFUSION", 0 }, + /* Prefetcher */ + { 0xF0, 0x3, NULL, "EMON_PREF_RQSTS_UP", 0 }, + { 0xF8, 0x3, NULL, "EMON_PREF_RQSTS_DN", 0 }, +}; + +const struct perfctr_event_set pentm_event_set_1 = { + .cpu_type = PERFCTR_X86_INTEL_PII, + .event_prefix = "PII_", + .include = &p6_event_set, + .nevents = ARRAY_SIZE(p2andp3_events), + .events = p2andp3_events, +}; + +const struct perfctr_event_set pentm_event_set_2 = { + .cpu_type = PERFCTR_X86_INTEL_PIII, + .event_prefix = "PIII_", + .include = &pentm_event_set_1, + .nevents = ARRAY_SIZE(p3_events_1), + .events = p3_events_1, +}; + +const struct perfctr_event_set perfctr_pentm_event_set = { + .cpu_type = PERFCTR_X86_INTEL_PENTM, + .event_prefix = "PENTM_", + .include = &pentm_event_set_2, + .nevents = ARRAY_SIZE(pentm_events), + .events = pentm_events, +}; diff --git a/kernel/fiasco/src/lib/perfctr/event_set_ppc.c b/kernel/fiasco/src/lib/perfctr/event_set_ppc.c new file mode 100644 index 00000000..972ab8c9 --- /dev/null +++ b/kernel/fiasco/src/lib/perfctr/event_set_ppc.c @@ -0,0 +1,523 @@ +/* $Id: event_set_ppc.c,v 1.2.2.1 2004/08/02 22:26:42 mikpe Exp $ + * Descriptions of the events available for different processor types. + * + * Copyright (C) 2004 Mikael Pettersson + */ +#include /* for NULL */ +#include "libperfctr.h" +#include "event_set.h" + +/* + * XXX: a few events use the TBSEL and THRESHOLD fields in MMCR0. + * They should have unit mask descriptors. + */ + +/* + * PowerPC common events for PMC1-PMC4, introduced in 604. + */ + +static const struct perfctr_event ppc_common_events[] = { + { 0x00, 0x0F, NULL, "NOTHING", + "Nothing. Register counter holds current value" }, + { 0x01, 0x0F, NULL, "PROCESSOR_CYCLES", + "Processor cycles. Count every cycle" }, + { 0x02, 0x0F, NULL, "INSTRUCTIONS_COMPLETED", + "Number of instructions completed. Does not include folded branches" }, + { 0x03, 0x0F, NULL, "TBL_BIT_TRANSITIONS", /* XXX: depends on MMCR0[TBSEL] */ + "Time-base (lower) bit transition" }, + { 0x04, 0x0F, NULL, "INSTRUCTIONS_DISPATCHED", + "Number of instructions dispatched" }, +}; + +static const struct perfctr_event_set ppc_common_event_set = { + .cpu_type = PERFCTR_PPC_604, + .event_prefix = "PPC604_", + .include = NULL, + .nevents = ARRAY_SIZE(ppc_common_events), + .events = ppc_common_events, +}; + +/* + * PowerPC 604 events. + */ + +static const struct perfctr_event ppc604_events[] = { + /* + * PMC1 events. + */ + { 0x05, 0x01, NULL, "ICACHE_MISSES", + "Instruction cache misses" }, + { 0x06, 0x01, NULL, "DTLB_MISSES", + "Data TLB misses (in order)" }, + { 0x07, 0x01, NULL, "BRANCH_MISPREDICT_CORRECTION", + "Branch misprediction correction from execute stage" }, + { 0x08, 0x01, NULL, "RESERVATIONS_REQUESTED", + "Number of reservations requested. The lwarx instruction is ready " + "for execution in the LSU" }, + { 0x09, 0x01, NULL, "DCACHE_LOAD_MISSES_LATERAL", /* XXX: depends on threshold value */ + "Number of data cache load misses exceeding the threshold value " + "with lateral L2 cache intervention" }, + { 0x0A, 0x01, NULL, "DCACHE_STORE_MISSES_LATERAL", /* XXX: depends on threshold value */ + "Number of data cache store misses exceeding the threshold value " + "with lateral L2 cache intervention" }, + { 0x0B, 0x01, NULL, "MTSPR_DISPATCHED", + "Number of mtspr instructions dispatched" }, + { 0x0C, 0x01, NULL, "SYNC_COMPLETED", + "Number of sync instructions completed" }, + { 0x0D, 0x01, NULL, "EIEIO_COMPLETED", + "Number of eieio instructions completed" }, + { 0x0E, 0x01, NULL, "INTEGER_INSTRUCTIONS_COMPLETED", + "Number of integer instructions completed every cycle " + "(no loads or stores)" }, + { 0x0F, 0x01, NULL, "FP_INSTRUCTIONS_COMPLETED", + "Number of floating-point instructions completed every cycle " + "(no loads or stores)" }, + { 0x10, 0x01, NULL, "LSU_RESULT", + "LSU produced result" }, + { 0x11, 0x01, NULL, "SCIU1_RESULT", + "SCIU1 produced result for an add, subtract, compare, rotate, " + "shift, or logical instruction" }, + { 0x12, 0x01, NULL, "FPU_RESULT", + "FPU produced result" }, + { 0x13, 0x01, NULL, "INSTRUCTIONS_DISPATCHED_LSU", + "Number of instructions dispatched to the LSU" }, + { 0x14, 0x01, NULL, "INSTRUCTIONS_DISPATCHED_SCIU1", + "Number of instructions dispatched to the SCIU1" }, + { 0x15, 0x01, NULL, "INSTRUCTIONS_DISPATCHED_FPU", + "Number of instructions dispatched to the FPU" }, + { 0x16, 0x01, NULL, "SNOOPS_RECEIVED", + "Valid snoop requests received from outside the 604e. " + "Does not distinguish hits or misses" }, + { 0x17, 0x01, NULL, "DCACHE_LOAD_MISSES", /* XXX: depends on threshold value */ + "Number of data cache load misses exceeeding the threshold value " + "without lateral L2 intervention" }, + { 0x18, 0x01, NULL, "DCACHE_STORE_MISSES", /* XXX: depends on threshold value */ + "Number of data cache store misses exceeding the threshold value " + "without lateral L2 intervention" }, + { 0x19, 0x01, NULL, "BRANCH_UNIT_IDLE", + "Number of cycles the branch unit is idle" }, + { 0x1A, 0x01, NULL, "MCIU0_IDLE", + "Number of cycles MCIU0 is idle" }, + { 0x1B, 0x01, NULL, "LSU_IDLE", + "Number of cycles the LSU is idle. No new instructions are executing; " + "however, active loads or stores may be in the queues" }, + { 0x1C, 0x01, NULL, "L2_INT_ASSERTED", + "Number of times the L2_INT is asserted (regardless of TA state)" }, + { 0x1D, 0x01, NULL, "UNALIGNED_LOADS", + "Number of unaligned loads" }, + { 0x1E, 0x01, NULL, "LOAD_QUEUE_ENTRIES", + "Number of entries in the load queue each cycle (maximum of five). " + "Although the load queue has four entries, a load miss latch may " + "hold a load waiting for data from memory" }, + { 0x1F, 0x01, NULL, "INSTRUCTION_BREAKPOINT_HITS", + "Number of instruction breakpoint hits" }, + /* + * PMC2 events. + */ + { 0x05, 0x02, NULL, "LOAD_MISS_CYCLES", + "Number of cycles a load miss takes" }, + { 0x06, 0x02, NULL, "DATA_CACHE_MISSES", + "Data cache misses (in order)" }, + { 0x07, 0x02, NULL, "ITLB_MISSES", + "Number of instruction TLB misses" }, + { 0x08, 0x02, NULL, "BRANCHES_COMPLETED", + "Number of branches completed. Indicates the number of branch " + "instructions being completed every cycle (00 = none, 10 = one, " + "11 = two, 01 is an illegal value)" }, + { 0x09, 0x02, NULL, "RESERVATIONS_OBTAINED", + "Number of reservations successfully obtained (stwcx. operation " + "completed successfully)" }, + { 0x0A, 0x02, NULL, "MFSPR_DISPATCHED", + "Number of mfspr instructions dispatched (in order)" }, + { 0x0B, 0x02, NULL, "ICBI_INSTRUCTIONS", + "Number of icbi instructions. It may not hit in the cache" }, + { 0x0C, 0x02, NULL, "PIPELINE_FLUSH_INSTRUCTIONS", + "Number of pipeline flushing instructions (sc, isync, mtspr(XER), " + "mcrcr, floating-point operation with divide by 0 or invalid operand " + "and MSR[FE0,FE1] = 00, branch with MSR[BE] = 1, load string " + "indexed with XER = 0, and SO bit getting set)" }, + { 0x0D, 0x02, NULL, "BPU_RESULT", + "BPU produced result" }, + { 0x0E, 0x02, NULL, "SCIU0_RESULT", + "SCIU0 produced result (of an add, subtract, compare, rotate, " + "shift, or logical instruction" }, + { 0x0F, 0x02, NULL, "MCIU_RESULT", + "MCIU poduced result (of a multiply/divide or SPR instruction)" }, + { 0x10, 0x02, NULL, "INSTRUCTIONS_DISPATCHED_BRANCH", + "Number of instructions dispatched to the branch unit" }, + { 0x11, 0x02, NULL, "INSTRUCTIONS_DISPATCHED_SCIU0", + "Number of instructions dispatched to the SCIU0" }, + { 0x12, 0x02, NULL, "LOADS_COMPLETED", + "Number of loads completed. These include all cache operations " + "and tlbie, tlbsync, sync, eieio, and icbi instructions" }, + { 0x13, 0x02, NULL, "INSTRUCTIONS_DISPATCHED_MCIU", + "Number of instructions dispatched to the MCIU" }, + { 0x14, 0x02, NULL, "SNOOP_HITS", + "Number of snoop hits occurred" }, + { 0x15, 0x02, NULL, "INTERRUPTS_MASKED", + "Number of cycles during which the MSR[EE] bit is cleared" }, + { 0x16, 0x02, NULL, "MCIU_IDLE", + "Number of cycles the MCIU is idle" }, + { 0x17, 0x02, NULL, "SCIU1_IDLE", + "Number of cycles SCIU1 is idle" }, + { 0x18, 0x02, NULL, "FPU_IDLE", + "Number of cycles the FPU is idle" }, + { 0x19, 0x02, NULL, "L2_INT_ACTIVE", + "Number of cycles the L2_INT signal is active (regardless of TA state)" }, + { 0x1A, 0x02, NULL, "DISPATCHED_4_INSTRUCTIONS", + "Number of times four instructions were dispatched" }, + { 0x1B, 0x02, NULL, "DISPATCHED_3_INSTRUCTIONS", + "Number of times three instructions were dispatched" }, + { 0x1C, 0x02, NULL, "DISPATCHED_2_INSTRUCTIONS", + "Number of times two instructions were dispatched" }, + { 0x1D, 0x02, NULL, "DISPATCHED_1_INSTRUCTION", + "Number of times one instruction was dispatched" }, + { 0x1E, 0x02, NULL, "UNALIGNED_STORES", + "Number of unaligned stores" }, + { 0x1F, 0x02, NULL, "STORE_QUEUE_ENTRIES", + "Number of entries in the store queue each cycle (maximum of six)" }, +}; + +const struct perfctr_event_set perfctr_ppc604_event_set = { + .cpu_type = PERFCTR_PPC_604, + .event_prefix = "PPC604_", + .include = &ppc_common_event_set, + .nevents = ARRAY_SIZE(ppc604_events), + .events = ppc604_events, +}; + +/* + * PowerPC 604e events. + * Extends PPC604 with two new counters and corresponding events. + */ + +static const struct perfctr_event ppc604e_events[] = { + /* + * PMC3 events + */ + { 0x05, 0x04, NULL, "LSU_STALL_BIU", + "Number of cycles the LSU stalls due to BIU or cache busy. " + "Counts cycles between when a load or store request is made and " + "a response was expected. For example, when a store is retried, " + "there are four cycles before the same instruction is presented " + "to the cache again. Cycles in between are not counted" }, + { 0x06, 0x04, NULL, "LSU_STALL_STORE_QUEUE", + "Number of cycles the LSU stalls due to a full store queue" }, + { 0x07, 0x04, NULL, "LSU_STALL_OPERANDS", + "Number of cycles the LSU stalls due to operands not available " + "in the reservation station" }, + { 0x08, 0x04, NULL, "LOAD_QUEUE_INSTRUCTIONS", + "Number of instructions written into the load queue. Misaligned " + "loads are split into two transactions with the first part always " + "written into the load queue. If both parts are cache hits, data " + "is returned to the rename registers and the first part is flushed " + "from the load queue. To count the instructions that enter the " + "load queue to stay, the misaligned load hits must be subtracted. " + "See event 8 for PMC4" }, + { 0x09, 0x04, NULL, "STORE_COMPLETION_STALLS", + "Number of cycles that completion stalls for a store instruction" }, + { 0x0A, 0x04, NULL, "UNFINISHED_COMPLETION_STALLS", + "Number of cycles the completion stalls for an unfinished " + "instruction. This event is a superset of PMC3 event 9 and " + "PMC4 event 10" }, + { 0x0B, 0x04, NULL, "SYSTEM_CALLS", + "Number of system calls" }, + { 0x0C, 0x04, NULL, "BPU_STALL", + "Number of cycles the BPU stalled as branch waits for its operand" }, + { 0x0D, 0x04, NULL, "FETCH_CORRECTIONS_DISPATCH", + "Number of fetch corrections made at the dispatch stage. " + "Prioritized behind the execute stage" }, + { 0x0E, 0x04, NULL, "DISPATCH_STALL_NO_INSTRUCTIONS", + "Number of cycles the dispatch stalls waiting for instructions" }, + { 0x0F, 0x04, NULL, "DISPATCH_STALL_NO_ROB", + "Number of cycles the dispatch unit stalls due to unavailability " + "of reorder buffer (ROB) entry. No ROB entry was available for " + "the first nondispatched instruction" }, + { 0x10, 0x04, NULL, "DISPATCH_STALL_NO_FPR", + "Number of cycles the dispatch unit stalls due to no FPR rename " + "buffer available. First nondispatched instruction required a " + "floating-point reorder buffer and none was available" }, + { 0x11, 0x04, NULL, "INSTRUCTION_TABLE_SEARCH_COUNT", + "Number of instruction table search operations" }, + { 0x12, 0x04, NULL, "DATA_TABLE_SEARCH_COUNT", + "Number of data table search operations. Completion could " + "result from a page fault or a PTE match" }, + { 0x13, 0x04, NULL, "FPU_STALL", + "Number of cycles the FPU stalled" }, + { 0x14, 0x04, NULL, "SCIU1_STALL", + "Number of cycles the SCIU1 stalled" }, + { 0x15, 0x04, NULL, "BIU_FORWARDS", + "Number of times the BIU forwards noncritical data from the " + "line-fill buffer" }, + { 0x16, 0x04, NULL, "DATA_BUS_TRANSACTIONS_NO_QUEUE", + "Number of data bus transactions completed with pipelining one " + "deep with no additional bus transactions queued behind it " }, + { 0x17, 0x04, NULL, "DATA_BUS_TRANSACTIONS_TWO_QUEUED", + "Number of data bus transactions completed with two data bus " + "transactions queued behind" }, + { 0x18, 0x04, NULL, "BURST_READS", + "Counts pairs of back-to-back burst reads streamed without a " + "dead cycle between them in data streaming mode" }, + { 0x19, 0x04, NULL, "WRITE_HIT_ON_SHARED", + "Counts non-ARTRYd processor kill transactions caused by a " + "write-hit-on-shared condition" }, + { 0x1A, 0x04, NULL, "WRITE_WITH_KILL", + "This event counts non-ARTRYd write-with-kill address operations " + "that originate from the three castout buffers. These include " + "high-priority write-with-kill transactions caused by a snoop hit " + "on modified data in one of the BIU's three copy-back buffers. " + "When the cache block on a data cache miss is modified, it is " + "queued in one of the three copy-back buffers. The miss is serviced " + "before the copy-back buffer is written back to memory as a " + "write-with-kill transaction" }, + { 0x1B, 0x04, NULL, "TWO_CASTOUT_BUFFERS_OCCUPIED", + "Number of cycles when exactly two castout buffers are occupied" }, + { 0x1C, 0x04, NULL, "DATA_CACHE_RETRIES", + "Number of data cache accesses retried due to occupied castout buffers" }, + { 0x1D, 0x04, NULL, "SHARED_LOADS", + "Number of read transactions from load misses brought into the " + "cache in a shared state" }, + { 0x1E, 0x04, NULL, "CR_LOGICAL_FINISHED", + "CRU indicates that a CR logical instruction is being finished" }, + /* + * PMC4 events + */ + { 0x05, 0x08, NULL, "LSU_STALL_MMU", + "Number of cycles the LSU stalls due to busy MMU" }, + { 0x06, 0x08, NULL, "LSU_STALL_LOAD_QUEUE", + "Number of cycles the LSU stalls due to the load queue full" }, + { 0x07, 0x08, NULL, "LSU_STALL_ADDRESS", + "Number of cycles the LSU stalls due to address collision" }, + { 0x08, 0x08, NULL, "MISALIGNED_LOAD_HITS", + "Number of misaligned loads that are cache hits for both the " + "first and second accesses. Related to event 8 in PMC3" }, + { 0x09, 0x08, NULL, "STORE_QUEUE_INSTRUCTIONS", + "Number of instructions written into the store queue" }, + { 0x0A, 0x08, NULL, "LOAD_COMPLETION_STALLS", + "Number of cycles that completion stalls for a load instruction" }, + { 0x0B, 0x08, NULL, "BTAC_HITS", + "Number of hits in the BTAC. Warning--if decode buffers cannot " + "accept new instructions, the processor refetches the same " + "address multiple times" }, + { 0x0C, 0x08, NULL, "COMPLETION_USED_FOUR_BLOCKS", + "Number of times the four basic blocks in the completion buffer " + "from which instructions can be retired were used" }, + { 0x0D, 0x08, NULL, "FETCH_CORRECTIONS_DECODE", + "Number of fetch corrections made at decode stage" }, + { 0x0E, 0x08, NULL, "DISPATCH_STALL_NO_UNIT", + "Number of cycles the dispatch unit stalls due to no unit available. " + "First nondispatched instruction requires an execution unit that is " + "either full or a previous instruction is being dispatched to that unit" }, + { 0x0F, 0x08, NULL, "DISPATCH_STALL_GPR", + "Number of cycles the dispatch unit stalls due to unavailability of " + "GPR rename buffer. First nondispatched instruction requires a GPR " + "reorder buffer and none are available" }, + { 0x10, 0x08, NULL, "DISPATCH_STALL_CR", + "Number of cycles the dispatch unit stalls due to no CR rename " + "buffer available. First nondispatched instruction requires a " + "CR rename buffer and none is available" }, + { 0x11, 0x08, NULL, "DISPATCH_STALL_CTR_LR", + "Number of cycles the dispatch unit stalls due to CTR/LR interlock. " + "First nondispatched instruction could not dispatch due to " + "CTR/LR/mtcrf interlock" }, + { 0x12, 0x08, NULL, "INSTRUCTION_TABLE_SEARCH_CYCLES", + "Number of cycles spent doing instruction table search operations" }, + { 0x13, 0x08, NULL, "DATA_TABLE_SEARCH_CYCLES", + "Number of cycles spent doing data table search operations" }, + { 0x14, 0x08, NULL, "SCIU0_STALL", + "Number of cycles SCIU0 was stalled" }, + { 0x15, 0x08, NULL, "MCIU_STALL", + "Number of cycles MCIU was stalled" }, + { 0x16, 0x08, NULL, "BUS_REQUEST_NO_QUALIFIED_GRANT", + "Number of bus cycles after an internal bus request without " + "a qualified bus grant" }, + { 0x17, 0x08, NULL, "DATA_BUS_TRANSACTIONS_ONE_QUEUED", + "Number of data bus transactions completed with one data bus " + "transaction queued behind" }, + { 0x18, 0x08, NULL, "REORDERED_WRITES", + "Number of write data transactions that have been reordered before " + "a previous read data transaction using the DBWO feature" }, + { 0x19, 0x08, NULL, "ARTRYd_ADDRESS_TRANSACTIONS", + "Number of ARTRYd processor address bus transactions" }, + { 0x1A, 0x08, NULL, "HIGH_PRIORITY_SNOOP_PUSHES", + "Number of high-priority snoop pushes. Snoop transactions, except " + "for write-with-kill, that hit modified data in the data cache cause " + "a high-priority write (snoop push) of that modified cache block to " + "memory. This operation has a transaction type of write-with-kill. " + "This events counts the number of non-ARTRYd processor write-with-kill " + "transactions that were caused by a snoop hit on modified data in the " + "data cache. It does not count high-priority write-with-kill " + "transactions caused by snoop hits on modified data in one of the " + "BIU's three copy-back buffers" }, + { 0x1B, 0x08, NULL, "ONE_CASTOUT_BUFFER_OCCUPIED", + "Number of cycles for which exactly one castout buffer is occupied" }, + { 0x1C, 0x08, NULL, "THREE_CASTOUT_BUFFERS_OCCUPIED", + "Number of cycles for which exactly three castout buffers are occupied" }, + { 0x1D, 0x08, NULL, "EXCLUSIVE_LOADS", + "Number of read transactions from load misses brought into the " + "cache in an exclusive (E) state" }, + { 0x1E, 0x08, NULL, "UNDISPATCHED_INSTRUCTIONS", + "Number of undispatched instructions beyond branch" }, +}; + +const struct perfctr_event_set perfctr_ppc604e_event_set = { + .cpu_type = PERFCTR_PPC_604e, + .event_prefix = "PPC604e_", + .include = &perfctr_ppc604_event_set, + .nevents = ARRAY_SIZE(ppc604e_events), + .events = ppc604e_events, +}; + +/* + * PowerPC 750 events. (MPC750, PPC750, PPC750CX, PPC750FX, PPC750GX) + * Unrelated to PPC604/PPC604e, except for the common events 0-4. + */ + +static const struct perfctr_event ppc750_events[] = { + /* + * PMC1 events + */ + { 0x05, 0x01, NULL, "EIEIO_INSTRUCTIONS", + "Number of eieio instructions completed" }, + { 0x06, 0x01, NULL, "ITLB_TABLE_SEARCH_CYCLES", + "Number of cycles spent performing table search operations for the ITLB" }, + { 0x07, 0x01, NULL, "L2_ACCESSES", + "Number of accesses that hit the L2. This event includes cache ops " + "(i.e., dcbz)" }, + { 0x08, 0x01, NULL, "EAS_DELIVERED", + "Number of valid instruction EAs delivered to the memory subsystem" }, + { 0x09, 0x01, NULL, "IABR_MATCHES", + "Number of times the address of an instruction being completed " + "matches the address in the IABR" }, + { 0x0A, 0x01, NULL, "L1_LOAD_MISSES", /* XXX: depends on threshold value */ + "Number of loads that miss the L1 with latencies that exceed " + "the threshold value" }, + { 0x0B, 0x01, NULL, "UNRESOLVED_BRANCHES", + "Number of branches that are unresolved when processed" }, + { 0x0C, 0x01, NULL, "SECOND_UNRESOLVED_BRANCH_STALLS", + "Number of cycles the dispatcher stalls due to a second unresolved " + "branch in the instruction stream" }, + /* XXX: PPC750 defined PMC1 event 0x0D as L1_ICACHE_MISSES, but that + was probably an error. L1_ICACHE_MISSES is PMC2 event 0x05, and + MPC750/PPC750CX/PPC750FX/750GX don't define PMC1 event 0x0D at all. */ + /* + * PMC2 events + */ + { 0x05, 0x02, NULL, "L1_ICACHE_MISSES", + "Counts L1 instruction cache misses" }, + { 0x06, 0x02, NULL, "ITLB_MISSES", + "Counts ITLB misses" }, + { 0x07, 0x02, NULL, "L2_I_MISSES", + /* XXX: The L2 was L1 in IBM 7xx_um. Clearly a typo. */ + "Counts L2 instruction misses" }, + { 0x08, 0x02, NULL, "BRANCHES_NOT_TAKEN", + "Counts branches predicted or resolved not taken" }, + { 0x09, 0x02, NULL, "PRIVILEGED_USER_SWITCHES", + "Counts MSR[PR] bit toggles" }, + { 0x0A, 0x02, NULL, "RESERVED_LOADS", + "Counts times a reserved load operations completes" }, + { 0x0B, 0x02, NULL, "LOADS_AND_STORES", + "Counts completed load and store instructions" }, + { 0x0C, 0x02, NULL, "SNOOPS", + "Counts snoops to the L1 and the L2" }, + { 0x0D, 0x02, NULL, "L1_CASTOUTS_TO_L2", + "Counts L1 cast-outs to the L2" }, + { 0x0E, 0x02, NULL, "SYSTEM_UNIT_INSTRUCTIONS", + "Counts completed system unit instructions" }, + { 0x0F, 0x02, NULL, "INSTRUCTION_FETCH_MISSES", + /* XXX: IBM 7xx_um describes this as counting cycles not occurrences */ + "Counts instruction fetch misses in the L1" }, + { 0x10, 0x02, NULL, "SPECULATIVE_BRANCHES", + "Counts branches allowing out-of-order execution that resolved correctly" }, + /* + * PMC3 events + */ + { 0x05, 0x04, NULL, "L1_DCACHE_MISSES", + "Number of L1 data cache misses. Does not include cache ops" }, + { 0x06, 0x04, NULL, "DTLB_MISSES", + "Number of DTLB misses" }, + { 0x07, 0x04, NULL, "L2_DATA_MISSES", + "Number of L2 data misses" }, + { 0x08, 0x04, NULL, "TAKEN_BRANCHES", + /* XXX: PPC750/PPC750CX/PPC750FX/PPC750GX describe this as predicted & taken branches */ + "Number of taken branches, including predicted branches" }, + { 0x09, 0x04, NULL, "USER_MARKED_UNMARKED_TRANSITIONS", + /* XXX: PPC750 adds a "RESERVED" after the event description. + PPC750CX/PPC750FX/PPC750GX mark event 0x9 as reserved. */ + "Number of transitions between marked and unmarked processes while in " + "user mode. That is, the number of MSR[PM] bit toggles while the " + "processor is in user mode" }, + { 0x0A, 0x04, NULL, "STORE_CONDITIONAL_INSTRUCTIONS", + "Number of store conditional instructions completed" }, + { 0x0B, 0x04, NULL, "FPU_INSTRUCTIONS", + "Number of instructions completed from the FPU" }, + { 0x0C, 0x04, NULL, "L2_CASTOUTS_MODIFIED_SNOOPS", + "Number of L2 castouts caused by snoops to modified lines" }, + { 0x0D, 0x04, NULL, "L2_HITS", + "Number of cache operations that hit in the L2 cache" }, + /* 0x0E: reserved */ + { 0x0F, 0x04, NULL, "L1_LOAD_MISS_CYCLES", + "Number of cycles generated by L1 load misses" }, + { 0x10, 0x04, NULL, "SECOND_STREAM_RESOLVED_BRANCHES", + "Number of branches in the second speculative stream that " + "resolve correctly" }, + { 0x11, 0x04, NULL, "BPU_LR_CR_STALL_CYCLES", + "Number of cycles the BPU stalls due to LR or CR unresolved dependencies" }, + /* + * PMC4 events + */ + { 0x05, 0x08, NULL, "L2_CASTOUTS", + "Number of L2 castouts" }, + { 0x06, 0x08, NULL, "DTLB_TABLE_SEARCH_CYCLES", + "Number of cycles spent performing table searches for DTLB accesses" }, + /* 0x07: reserved */ + { 0x08, 0x08, NULL, "MISPREDICTED_BRANCHES", + /* XXX: PPC750/PPC750CX/PPC750FX/PPC750GX add "RESERVED" after the event description */ + "Number of mispredicted branches" }, + { 0x09, 0x08, NULL, "SUPERVISOR_MARKED_UNMARKED_TRANSITIONS", + /* XXX: In MPC750UM first "supervisor" is "user", presumably a typo. + PPC750/PPC750CX/PPC750FX/PPC750GX mark event 0x09 as reserved. */ + "Number of transitions between marked and unmarked processes while in " + "supervisor mode. That is, the number of MSR[PM] bit toggles while the " + "processor is in supervisor mode" }, + { 0x0A, 0x08, NULL, "STORE_CONDITIONAL_INSTRUCTIONS_RESERVATON_INTACT", + "Number of store conditional instructions completed with reservation " + "intact" }, + { 0x0B, 0x08, NULL, "SYNC_INSTRUCTIONS", + "Number of completed sync instructions" }, + { 0x0C, 0x08, NULL, "SNOOP_RETRIES", + "Number of snoop request retries" }, + { 0x0D, 0x08, NULL, "INTEGER_OPERATIONS", + "Number of completed integer operations" }, + { 0x0E, 0x08, NULL, "BPU_BLOCKED_CYCLES", + "Number of cycles the BPU cannot process new branches due to " + "having two unresolved branches" }, + /* XXX: PPC750 defined PMC4 event 0x1F as L1_DCACHE_MISSES, but that + was probably an error. L1_DCACHE_MISSES is PMC3 event 0x05, and + MPC750/PPC750CX/PPC750FX/PPC750GX don't define PMC4 event 0x1F at all. */ +}; + +const struct perfctr_event_set perfctr_ppc750_event_set = { + .cpu_type = PERFCTR_PPC_750, + .event_prefix = "PPC750_", + .include = &ppc_common_event_set, + .nevents = ARRAY_SIZE(ppc750_events), + .events = ppc750_events, +}; + +/* + * Helper function to translate a cpu_type code to an event_set pointer. + */ + +static const struct perfctr_event_set * const cpu_event_set[] = { + [PERFCTR_PPC_604] = &perfctr_ppc604_event_set, + [PERFCTR_PPC_604e] = &perfctr_ppc604e_event_set, + [PERFCTR_PPC_750] = &perfctr_ppc750_event_set, +}; + +const struct perfctr_event_set *perfctr_cpu_event_set(unsigned cpu_type) +{ + if( cpu_type >= ARRAY_SIZE(cpu_event_set) ) + return 0; + return cpu_event_set[cpu_type]; +} diff --git a/kernel/fiasco/src/lib/perfctr/event_set_x86.c b/kernel/fiasco/src/lib/perfctr/event_set_x86.c new file mode 100644 index 00000000..9e15cfac --- /dev/null +++ b/kernel/fiasco/src/lib/perfctr/event_set_x86.c @@ -0,0 +1,53 @@ +/* $Id: event_set_x86.c 37048 2009-11-12 21:44:56Z adam $ + * Descriptions of the events available for different processor types. + * + * Copyright (C) 1999-2004 Mikael Pettersson + */ +#include /* for NULL */ +#include "libperfctr.h" +#include "event_set.h" + +/* + * Generic events. + */ + +static const struct perfctr_event_set generic_event_set = { + .cpu_type = PERFCTR_X86_GENERIC, + .event_prefix = NULL, + .include = NULL, + .nevents = 0, + .events = NULL, +}; + +/* + * Helper function to translate a cpu_type code to an event_set pointer. + */ + +static const struct perfctr_event_set * const cpu_event_set[] = { + [PERFCTR_X86_GENERIC] = &generic_event_set, +#if !defined(__x86_64__) + [PERFCTR_X86_INTEL_P5] = &perfctr_p5_event_set, + [PERFCTR_X86_INTEL_P5MMX] = &perfctr_p5mmx_event_set, + [PERFCTR_X86_INTEL_P6] = &perfctr_ppro_event_set, + [PERFCTR_X86_INTEL_PII] = &perfctr_p2_event_set, + [PERFCTR_X86_INTEL_PIII] = &perfctr_p3_event_set, + [PERFCTR_X86_CYRIX_MII] = &perfctr_mii_event_set, + [PERFCTR_X86_WINCHIP_C6] = &perfctr_wcc6_event_set, + [PERFCTR_X86_WINCHIP_2] = &perfctr_wc2_event_set, + [PERFCTR_X86_AMD_K7] = &perfctr_k7_event_set, + [PERFCTR_X86_VIA_C3] = &perfctr_vc3_event_set, + [PERFCTR_X86_INTEL_P4] = &perfctr_p4_event_set, + [PERFCTR_X86_INTEL_P4M2] = &perfctr_p4_event_set, + [PERFCTR_X86_INTEL_PENTM] = &perfctr_pentm_event_set, +#endif + [PERFCTR_X86_INTEL_P4M3] = &perfctr_p4m3_event_set, + [PERFCTR_X86_AMD_K8] = &perfctr_k8_event_set, + [PERFCTR_X86_AMD_K8C] = &perfctr_k8c_event_set, +}; + +const struct perfctr_event_set *perfctr_cpu_event_set(unsigned cpu_type) +{ + if( cpu_type >= ARRAY_SIZE(cpu_event_set) ) + return 0; + return cpu_event_set[cpu_type]; +} diff --git a/kernel/fiasco/src/lib/perfctr/libperfctr.h b/kernel/fiasco/src/lib/perfctr/libperfctr.h new file mode 100644 index 00000000..b285c12b --- /dev/null +++ b/kernel/fiasco/src/lib/perfctr/libperfctr.h @@ -0,0 +1,75 @@ +/* $Id: libperfctr.h 37048 2009-11-12 21:44:56Z adam $ + * Library interface to Linux x86 Performance-Monitoring Counters. + * + * Copyright (C) 1999-2009 Mikael Pettersson + */ + +#ifndef __LIB_PERFCTR_H +#define __LIB_PERFCTR_H + +/* from linux/include/asm-x86/perfctr.h */ + +#define PERFCTR_X86_GENERIC 0 /* any x86 with rdtsc */ +#define PERFCTR_X86_INTEL_P5 1 /* no rdpmc */ +#define PERFCTR_X86_INTEL_P5MMX 2 +#define PERFCTR_X86_INTEL_P6 3 +#define PERFCTR_X86_INTEL_PII 4 +#define PERFCTR_X86_INTEL_PIII 5 +#define PERFCTR_X86_CYRIX_MII 6 +#define PERFCTR_X86_WINCHIP_C6 7 /* no rdtsc */ +#define PERFCTR_X86_WINCHIP_2 8 /* no rdtsc */ +#define PERFCTR_X86_AMD_K7 9 +#define PERFCTR_X86_VIA_C3 10 /* no pmc0 */ +#define PERFCTR_X86_INTEL_P4 11 /* model 0 and 1 */ +#define PERFCTR_X86_INTEL_P4M2 12 /* model 2 and above */ +#define PERFCTR_X86_AMD_K8 13 +#define PERFCTR_X86_INTEL_PENTM 14 /* Pentium M */ +#define PERFCTR_X86_AMD_K8C 15 /* Revision C */ +#define PERFCTR_X86_INTEL_P4M3 16 /* model 3 and above */ +#define PERFCTR_X86_INTEL_CORE 17 /* family 6 model 14 */ +#define PERFCTR_X86_INTEL_CORE2 18 /* family 6, models 15, 22, 23, 29 + */ +#define PERFCTR_X86_AMD_FAM10H 19 /* family 10h */ +#define PERFCTR_X86_AMD_FAM10 PERFCTR_X86_AMD_FAM10H /* XXX: compat crap, delete soon */ +#define PERFCTR_X86_INTEL_ATOM 20 /* family 6 model 28 */ +#define PERFCTR_X86_INTEL_COREI7 21 /* family 6 model 26 */ + +/* + * Descriptions of the events available for different processor types. + */ + +enum perfctr_unit_mask_type { + perfctr_um_type_fixed, /* one fixed (required) value */ + perfctr_um_type_exclusive, /* exactly one of N values */ + perfctr_um_type_bitmask, /* bitwise 'or' of N power-of-2 values */ +}; + +struct perfctr_unit_mask_value { + unsigned int value; + const char *description; /* [NAME:]text */ +}; + +struct perfctr_unit_mask { + unsigned int default_value; + enum perfctr_unit_mask_type type:16; + unsigned short nvalues; + struct perfctr_unit_mask_value values[1/*nvalues*/]; +}; + +struct perfctr_event { + unsigned int evntsel; + unsigned int counters_set; /* P4 force this to be CPU-specific */ + const struct perfctr_unit_mask *unit_mask; + const char *name; + const char *description; +}; + +struct perfctr_event_set { + unsigned int cpu_type; + const char *event_prefix; + const struct perfctr_event_set *include; + unsigned int nevents; + const struct perfctr_event *events; +}; + +#endif /* __LIB_PERFCTR_H */ diff --git a/kernel/fiasco/src/lib/perfctr/perfctr.c b/kernel/fiasco/src/lib/perfctr/perfctr.c new file mode 100644 index 00000000..58a120d8 --- /dev/null +++ b/kernel/fiasco/src/lib/perfctr/perfctr.c @@ -0,0 +1,88 @@ +#include +#include "libperfctr.h" +#include "event_set.h" + +/* current event set depending on CPU type */ +static const struct perfctr_event_set *event_set; + +static const struct perfctr_event* +perfctr_lookup_event_set(const struct perfctr_event_set *event_set, + unsigned evntsel, unsigned *nr) +{ + unsigned i; + + if (event_set->include) + { + const struct perfctr_event *event; + + if (0 != (event = perfctr_lookup_event_set(event_set->include, + evntsel, nr))) + return event; + } + for (i=0; inevents; i++) + { + if (event_set->events[i].evntsel == evntsel) + { + *nr += i; + return (event_set->events + i); + } + } + + *nr += event_set->nevents; + return 0; +} + +static const struct perfctr_event* +perfctr_index_event_set(const struct perfctr_event_set *event_set, + unsigned *nr) +{ + if (event_set->include) + { + const struct perfctr_event *event; + + if ((event = perfctr_index_event_set(event_set->include, nr)) != 0) + return event; + } + if (*nr < event_set->nevents) + return event_set->events + *nr; + + *nr -= event_set->nevents; + return 0; +} + +static unsigned +perfctr_get_max_event_set(const struct perfctr_event_set *event_set) +{ + unsigned nr = 0; + + if (event_set->include) + nr += perfctr_get_max_event_set(event_set->include); + + return nr + event_set->nevents; +} + +void +perfctr_set_cputype(unsigned cpu_type) +{ + event_set = perfctr_cpu_event_set(cpu_type); +} + +const struct perfctr_event* +perfctr_lookup_event(unsigned evntsel, unsigned *nr) +{ + *nr = 0; + return perfctr_lookup_event_set(event_set, evntsel, nr); +} + +const struct perfctr_event* +perfctr_index_event(unsigned nr) +{ + return perfctr_index_event_set(event_set, &nr); +} + +unsigned +perfctr_get_max_event(void) +{ + return perfctr_get_max_event_set(event_set); +} + diff --git a/kernel/fiasco/src/lib/regex/COPYING b/kernel/fiasco/src/lib/regex/COPYING new file mode 100644 index 00000000..5b6e7c66 --- /dev/null +++ b/kernel/fiasco/src/lib/regex/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/kernel/fiasco/src/lib/regex/README b/kernel/fiasco/src/lib/regex/README new file mode 100644 index 00000000..1fbd546c --- /dev/null +++ b/kernel/fiasco/src/lib/regex/README @@ -0,0 +1 @@ +The files rx.c alloc.c and regex.h are taken from the dietlibc. diff --git a/kernel/fiasco/src/lib/regex/alloc.c b/kernel/fiasco/src/lib/regex/alloc.c new file mode 100644 index 00000000..dec4e690 --- /dev/null +++ b/kernel/fiasco/src/lib/regex/alloc.c @@ -0,0 +1,315 @@ +/* from Dietlibc */ + +/* + * malloc/free by O.Dreesen + * + * first TRY: + * lists w/magics + * and now the second TRY + * let the kernel map all the stuff (if there is something to do) + */ + +#include +#include +#include +#include +#include + + +#ifndef MAP_FAILED +#define MAP_FAILED ((void*)-1) +#endif + +#ifndef NULL +#define NULL ((void*)0) +#endif + +typedef struct { + void* next; + size_t size; +} __alloc_t; + +#define BLOCK_START(b) (((void*)(b))-sizeof(__alloc_t)) +#define BLOCK_RET(b) (((void*)(b))+sizeof(__alloc_t)) + +#define MEM_BLOCK_SIZE PAGE_SIZE +#define PAGE_SIZE 4096U +#define PAGE_ALIGN(s) (((s)+PAGE_SIZE-1) & (~(PAGE_SIZE-1))) + +static __alloc_t* __small_mem[8]; + +#define __SMALL_NR(i) (MEM_BLOCK_SIZE/(i)) + +#define __MIN_SMALL_SIZE __SMALL_NR(256) /* 16 / 32 */ +#define __MAX_SMALL_SIZE __SMALL_NR(2) /* 2048 / 4096 */ + +#define GET_SIZE(s) (__MIN_SMALL_SIZE< 31*PAGE_SIZE) + size = 31*PAGE_SIZE; + linear_mem_pages = size / PAGE_SIZE; + linear_mem = ptr; + regex_reset(); +} + +static inline int +__ind_shift() +{ + return (MEM_BLOCK_SIZE==4096) ? 4 : 5; +} + +static size_t +get_index(size_t _size) +{ + register size_t idx=0; + if (_size) + { + register size_t size=((_size-1)&(MEM_BLOCK_SIZE-1))>>__ind_shift(); + while(size) + { + size>>=1; + ++idx; + } + } + return idx; +} + +static void +__small_free(void*_ptr,size_t _size) +{ + __alloc_t* ptr=BLOCK_START(_ptr); + size_t size=_size; + size_t idx=get_index(size); + + memset(ptr,0,size); /* allways zero out small mem */ + + ptr->next=__small_mem[idx]; + __small_mem[idx]=ptr; +} + +static void* +__small_malloc(size_t _size) +{ + __alloc_t *ptr; + size_t size=_size; + size_t idx; + + idx=get_index(size); + ptr=__small_mem[idx]; + + if (ptr==0) + { + register int i,nr; + ptr=regex_mmap(MEM_BLOCK_SIZE); + if (ptr==MAP_FAILED) + return MAP_FAILED; + + __small_mem[idx]=ptr; + + nr=__SMALL_NR(size)-1; + for (i=0;inext=(((void*)ptr)+size); + ptr=ptr->next; + } + ptr->next=0; + + ptr=__small_mem[idx]; + } + + /* get a free block */ + __small_mem[idx]=ptr->next; + ptr->next=0; + + return ptr; +} + +void +regex_free(void *ptr) +{ + register size_t size; + if (ptr) + { + size=((__alloc_t*)BLOCK_START(ptr))->size; + if (size) + { + if (size<=__MAX_SMALL_SIZE) + __small_free(ptr,size); + else + regex_munmap(BLOCK_START(ptr),size); + } + } +} + +void* +regex_malloc(size_t size) +{ + __alloc_t* ptr; + size_t need; + if (!size) + return 0; + size+=sizeof(__alloc_t); + if (sizesize=need; + return BLOCK_RET(ptr); +} + +void* +regex_realloc(void* ptr, size_t _size) +{ + register size_t size=_size; + if (ptr) + { + if (size) + { + __alloc_t *tmp=BLOCK_START(ptr); + size+=sizeof(__alloc_t); + if (sizesize!=size) + { + if ((tmp->size<=__MAX_SMALL_SIZE)) + { + void *new=regex_malloc(_size); + if (new) + { + register __alloc_t* foo=BLOCK_START(new); + size=foo->size; + if (size>tmp->size) + size=tmp->size; + if (size) + memcpy(new,ptr,size-sizeof(__alloc_t)); + regex_free(ptr); + } + return new; + } + else + { + register __alloc_t* foo; + size=PAGE_ALIGN(size); + foo=regex_mremap(tmp,tmp->size,size); + if (foo==MAP_FAILED) + return 0; + else + { + foo->size=size; + return BLOCK_RET(foo); + } + } + } + } + else + { /* size==0 */ + regex_free(ptr); + return 0; + } + } + else + { /* ptr==0 */ + if (size) + return regex_malloc(size); + } + return ptr; +} + diff --git a/kernel/fiasco/src/lib/regex/regex.h b/kernel/fiasco/src/lib/regex/regex.h new file mode 100644 index 00000000..7271dcfe --- /dev/null +++ b/kernel/fiasco/src/lib/regex/regex.h @@ -0,0 +1,83 @@ +#ifndef _REGEX_H +#define _REGEX_H + +#ifndef __THROW +#define __THROW +#endif + +#include "cdefs.h" +#include "types.h" + +__BEGIN_DECLS + +typedef ptrdiff_t regoff_t; + +typedef struct { + regoff_t rm_so; + regoff_t rm_eo; +} regmatch_t; + +#define REG_EXTENDED 1 +#define REG_ICASE 2 +#define REG_NOSUB 4 +#define REG_NEWLINE 8 + +#define REG_NOTBOL 1 +#define REG_NOTEOL 2 + +#define REG_NOMATCH -1 + +// overwrite any setting by any libc (e.g. for UX) +#undef RE_DUP_MAX +#define RE_DUP_MAX 255 + +struct __regex_t; + +typedef int (*matcher)(void*,const char*,int ofs,struct __regex_t* t,int plus,int eflags); + +typedef struct __regex_t { + struct regex { + matcher m; + void* next; + int pieces; + int num; + struct branch* b; + } r; + int brackets,cflags; + regmatch_t* l; +} regex_t; +#define re_nsub r.pieces + +int regcomp(regex_t* preg, const char* regex, int cflags) __THROW; +int regexec(const regex_t* preg, const char* string, size_t nmatch, regmatch_t pmatch[], int eflags) __THROW; +size_t regerror(int errcode, const regex_t* preg, char* errbuf, size_t errbuf_size) __THROW; +void regfree(regex_t* preg) __THROW; + +enum __regex_errors { + REG_NOERROR, + REG_BADRPT, /* Invalid use of repetition operators such as using `*' as the first character. */ + REG_BADBR, /* Invalid use of back reference operator. */ + REG_EBRACE, /* Un-matched brace interval operators. */ + REG_EBRACK, /* Un-matched bracket list operators. */ + REG_ERANGE, /* Invalid use of the range operator, eg. the ending point of the + range occurs prior to the starting point. */ + REG_ECTYPE, /* Unknown character class name. */ + REG_ECOLLATE, /* Invalid collating element. */ + REG_EPAREN, /* Un-matched parenthesis group operators. */ + REG_ESUBREG, /* Invalid back reference to a subexpression. */ + REG_EEND, /* Non specific error. This is not defined by POSIX.2. */ + REG_EESCAPE, /* Trailing backslash. */ + REG_BADPAT, /* Invalid use of pattern operators such as group or list. */ + REG_ESIZE, /* Compiled regular expression requires a pattern buffer + larger than 64Kb. This is not defined by POSIX.2. */ + REG_ESPACE /* regcomp ran out of space */ +}; + +char* re_comp(char* regex); +int re_exec(char* string); +void regex_init(void *ptr, unsigned size); +void regex_reset(void); + +__END_DECLS + +#endif diff --git a/kernel/fiasco/src/lib/regex/rx.c b/kernel/fiasco/src/lib/regex/rx.c new file mode 100644 index 00000000..d21710da --- /dev/null +++ b/kernel/fiasco/src/lib/regex/rx.c @@ -0,0 +1,530 @@ +#ifndef NDEBUG +#define NDEBUG +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +extern void* regex_realloc(void *ptr, size_t size); +extern void regex_free(void *ptr); + +#define realloc regex_realloc +#define free regex_free + + +/* this is ugly. + * the idea is to build a parse tree, then do some poor man's OOP with a + * generic matcher function call that is always that the start of each + * record, and a next pointer. When the parse tree is done, we need to + * recursively set the next pointers to point to the part of the parse + * tree that needs to match next. + * This is the prototype of the generic match function call pointer. + * The first argument is the "this" pointer, the second is the text to + * be matched against, ofs is the offset from the start of the matched + * text (so we can match "^") and matches is an array where match + * positions are stored. */ +/* now declared in regex.h: */ +/* typedef int (*matcher)(void*,const char*,int ofs,regmatch_t* matches,int plus,int eflags); */ + +/* one would think that this is approach is an order of magnitude slower + * than the standard NFA approach, but it isn't. The busybox grep took + * 0.26 seconds for a fixed string compared to 0.19 seconds for the + * glibc regex. */ + +/* first part: parse a regex into a parse tree */ +struct bracketed { + unsigned int cc[32]; +}; + +/* now declared in regex.h: +struct regex { + matcher m; + void* next; + int pieces; + int num; + struct branch *b; +}; */ + +struct atom { + matcher m; + void* next; + enum { ILLEGAL, EMPTY, REGEX, BRACKET, ANY, LINESTART, LINEEND, WORDSTART, WORDEND, CHAR, } type; + int bnum; + union { + struct regex r; + struct bracketed b; + char c; + } u; +}; + +struct piece { + matcher m; + void* next; + struct atom a; + unsigned char min,max; +}; + +struct branch { + matcher m; + void* next; + int num; + struct piece *p; +}; + +static void clearcc(unsigned int* x) { + memset(x,0,sizeof(struct bracketed)); +} + +static void setcc(unsigned int* x,unsigned int bit) { + x[bit/32]|=(1<<((bit%32)-1)); +} + +static int issetcc(unsigned int* x,unsigned int bit) { + return x[bit/32] & (1<<((bit%32)-1)); +} + +static const char* parsebracketed(struct bracketed*__restrict__ b,const char*__restrict__ s,regex_t*__restrict__ rx) { + const char* t; + int i,negflag=0; + if (*s!='[') return s; + t=s+1; + clearcc(b->cc); + if (*t=='^') { negflag=1; ++t; } + do { + if (*t==0) return s; + setcc(b->cc,rx->cflags®_ICASE?tolower(*t):*t); + if (t[1]=='-' && t[2]!=']') { + for (i=*t+1; i<=t[2]; ++i) setcc(b->cc,rx->cflags®_ICASE?tolower(i):i); + t+=2; + } + ++t; + } while (*t!=']'); + if (negflag) for (i=0; i<32; ++i) b->cc[i]=~b->cc[i]; + return t+1; +} + +static const char* parseregex(struct regex* r,const char* s,regex_t* rx); + +static int matchatom(void*__restrict__ x,const unsigned char*__restrict__ s,int ofs,struct __regex_t*__restrict__ preg,int plus,int eflags) { + register struct atom* a=(struct atom*)x; + int matchlen=0; + assert(a->type!=ILLEGAL); + switch (a->type) { + case EMPTY: +#ifdef DEBUG + printf("matching atom EMPTY against \"%s\"\n",s); + printf("a->bnum is %d\n",a->bnum); +#endif + if (a->bnum>=0) preg->l[a->bnum].rm_so=preg->l[a->bnum].rm_eo=ofs; + goto match; + case REGEX: +#ifdef DEBUG + printf("matching atom REGEX against \"%s\"\n",s); + printf("a->bnum is %d\n",a->bnum); +#endif + if ((matchlen=a->u.r.m(&a->u.r,(const char*)s,ofs,preg,0,eflags))>=0) { + assert(a->bnum>=0); + preg->l[a->bnum].rm_so=ofs; + preg->l[a->bnum].rm_eo=ofs+matchlen; + goto match; + } + break; + case BRACKET: +#ifdef DEBUG + printf("matching atom BRACKET against \"%s\"\n",s); +#endif + matchlen=1; + if (*s=='\n' && (preg->cflags®_NEWLINE)) break; + if (*s && issetcc(a->u.b.cc,(preg->cflags®_ICASE?tolower(*s):*s))) + goto match; + break; + case ANY: +#ifdef DEBUG + printf("matching atom ANY against \"%s\"\n",s); +#endif + if (*s=='\n' && (preg->cflags®_NEWLINE)) break; + matchlen=1; + if (*s) goto match; + break; + case LINESTART: +#ifdef DEBUG + printf("matching atom LINESTART against \"%s\"\n",s); +#endif + if (ofs==0 && (eflags®_NOTBOL)==0) { + goto match; + } + break; + case LINEEND: +#ifdef DEBUG + printf("matching atom LINEEND against \"%s\"\n",s); +#endif + if ((*s && *s!='\n') || (eflags®_NOTEOL)) break; + goto match; + case WORDSTART: +#ifdef DEBUG + printf("matching atom WORDSTART against \"%s\"\n",s); +#endif + if ((ofs==0 || !isalnum(s[-1])) && isalnum(*s)) + goto match; + break; + case WORDEND: +#ifdef DEBUG + printf("matching atom WORDEND against \"%s\"\n",s); +#endif + if (ofs>0 && isalnum(s[-1]) && !isalnum(*s)) + goto match; + break; + case CHAR: +#ifdef DEBUG + printf("matching atom CHAR %c against \"%s\"\n",a->u.c,s); +#endif + matchlen=1; + if (((preg->cflags®_ICASE)?tolower(*s):*s)==a->u.c) goto match; + break; + default:; + } + return -1; +match: + if (a->next) + return ((struct atom*)(a->next))->m(a->next,(const char*)s+matchlen,ofs+matchlen,preg,plus+matchlen,eflags); + else + return plus+matchlen; +} + +static const char* parseatom(struct atom*__restrict__ a,const char*__restrict__ s,regex_t*__restrict__ rx) { + const char *tmp; + a->m=(matcher)matchatom; + a->bnum=-1; + switch (*s) { + case '(': + a->bnum=++rx->brackets; + if (s[1]==')') { + a->type=EMPTY; + return s+2; + } + a->type=REGEX; + tmp=parseregex(&a->u.r,s+1,rx); + if (*tmp==')') + return tmp+1; + case 0: + case '|': + case ')': + return s; + case '[': + a->type=BRACKET; + if ((tmp=parsebracketed(&a->u.b,s,rx))!=s) + return tmp; + return s; + case '.': + a->type=ANY; + break; + case '^': + a->type=LINESTART; + break; + case '$': + a->type=LINEEND; + break; + case '\\': + if (!*++s) return s; + if (*s=='<') { + a->type=WORDSTART; + break; + } else if (*s=='>') { + a->type=WORDEND; + break; + } + default: + a->type=CHAR; + a->u.c=rx->cflags®_ICASE?tolower(*s):*s; + break; + } + return s+1; +} + +/* needs to do "greedy" matching, i.e. match as often as possible */ +static int matchpiece(void*__restrict__ x,const char*__restrict__ s,int ofs,struct __regex_t*__restrict__ preg,int plus,int eflags) { + register struct piece* a=(struct piece*)x; + int matchlen=0; + int tmp=0,num=0; + unsigned int *offsets; + assert(a->max>0 && a->max<1000); +#ifdef DEBUG + printf("alloca(%d)\n",sizeof(int)*a->max); +#endif + offsets=alloca(sizeof(int)*a->max); + offsets[0]=0; +// printf("allocating %d offsets...\n",a->max); +// printf("matchpiece \"%s\"...\n",s); + /* first, try to match the atom as often as possible, up to a->max times */ + if (a->max == 1 && a->min == 1) + return a->a.m(&a->a,s+matchlen,ofs+matchlen,preg,0,eflags); + while (nummax) { + void* save=a->a.next; + a->a.next=0; + if ((tmp=a->a.m(&a->a,s+matchlen,ofs+matchlen,preg,0,eflags))>=0) { + a->a.next=save; + ++num; + matchlen+=tmp; +// printf("setting offsets[%d] to %d\n",num,tmp); + offsets[num]=tmp; + } else { + a->a.next=save; + break; + } + } + if (nummin) return -1; /* already at minimum matches; signal mismatch */ + /* then, while the rest does not match, back off */ + for (;num>=0;) { + if (a->next) + tmp=((struct atom*)(a->next))->m(a->next,s+matchlen,ofs+matchlen,preg,plus+matchlen,eflags); + else + tmp=plus+matchlen; + if (tmp>=0) break; /* it did match; don't back off any further */ +// printf("using offsets[%d] (%d)\n",num,offsets[num]); + matchlen-=offsets[num]; + --num; + } + return tmp; +} + +static const char* parsepiece(struct piece*__restrict__ p,const char*__restrict__ s,regex_t*__restrict__ rx) { + const char* tmp=parseatom(&p->a,s,rx); + if (tmp==s) return s; + p->m=matchpiece; + p->min=p->max=1; + switch (*tmp) { + case '*': p->min=0; p->max=RE_DUP_MAX; break; + case '+': p->min=1; p->max=RE_DUP_MAX; break; + case '?': p->min=0; p->max=1; break; + case '{': + if (isdigit(*++tmp)) { + p->min=*tmp-'0'; p->max=RE_DUP_MAX; + while (isdigit(*++tmp)) p->min=p->min*10+*tmp-'0'; + if (*tmp==',') { + if (isdigit(*++tmp)) { + p->max=*tmp-'0'; + while (isdigit(*++tmp)) p->max=p->max*10+*tmp-'0'; + } + } else + p->max=p->min; + if (*tmp!='}') return s; + ++tmp; + } + default: + return tmp; + } + return tmp+1; +} + +/* trivial, just pass through */ +static int matchbranch(void*__restrict__ x,const char*__restrict__ s,int ofs,struct __regex_t*__restrict__ preg,int plus,int eflags) { + register struct branch* a=(struct branch*)x; + int tmp; +#ifdef DEBUG + printf("%08x matching branch against \"%s\"\n",(unsigned)a,s); + printf("%p %p\n",&a->p->m,a->p->m); +#endif + assert(a->p->m==matchpiece); + tmp=a->p->m(a->p,s,ofs,preg,plus,eflags); + if (tmp>=0) { + if (a->next) + return ((struct atom*)(a->next))->m(a->next,s+tmp,ofs+tmp,preg,plus+tmp,eflags); + else + return plus+tmp; + } + return -1; +} + +static int matchempty(void*__restrict__ x,const char*__restrict__ s,int ofs,struct __regex_t*__restrict__ preg,int plus,int eflags) { + (void)x; + (void)s; + (void)ofs; + (void)preg; + (void)plus; + (void)eflags; + return 0; +} + +static const char* parsebranch(struct branch*__restrict__ b,const char*__restrict__ s,regex_t*__restrict__ rx,int*__restrict__ pieces) { + struct piece p; + const char *tmp=0; /* the gcc warning here is bogus */ + b->m=matchbranch; + b->num=0; b->p=0; + for (;;) { + if (*s=='|' && b->num==0) { + tmp=s+1; + p.a.type=EMPTY; + p.a.m=matchempty; + p.min=p.max=1; + p.m=matchpiece; + } else { + tmp=parsepiece(&p,s,rx); + if (tmp==s) return s; + } +// printf("b->p from %p to ",b->p); + { + struct piece* tmp; + if (!(tmp=realloc(b->p,++b->num*sizeof(p)))) return s; +// printf("piece realloc: %p -> %p (%d*%d)\n",b->p,tmp,b->num,sizeof(p)); + b->p=tmp; + } +// printf("%p (size %d)\n",b->p,b->num*sizeof(p)); + b->p[b->num-1]=p; +// printf("assigned piece %d in branch %p\n",b->num-1,b->p); + if (*tmp=='|') break; + s=tmp; + } + *pieces+=b->num; + return tmp; +} + +/* try the branches one by one */ +static int matchregex(void*__restrict__ x,const char*__restrict__ s,int ofs,struct __regex_t*__restrict__ preg,int plus,int eflags) { + register struct regex* a=(struct regex*)x; + int i,tmp; +#ifdef DEBUG + printf("%08x matching regex against \"%s\"\n",(unsigned)a,s); +#endif + for (i=0; inum; ++i) { + assert(a->b[i].m==matchbranch); + tmp=a->b[i].m(&a->b[i],s,ofs,preg,plus,eflags); + if (tmp>=0) { + if (a->next) + return ((struct atom*)(a->next))->m(a->next,s+tmp,ofs+tmp,preg,plus+tmp,eflags); + else + return plus+tmp; + } + } + return -1; +} + +static const char* parseregex(struct regex*__restrict__ r,const char*__restrict__ s,regex_t*__restrict__ p) { + struct branch b; + const char *tmp; + r->m=matchregex; + r->num=0; r->b=0; r->pieces=0; + p->brackets=0; + b.next=0; + if (*s==')' || !*s) { + r->m=matchempty; + return s; + } + for (;;) { + tmp=parsebranch(&b,s,p,&r->pieces); + if (tmp==s && *s!=')') return s; +// printf("r->b from %p to ",r->b); + { + struct branch* tmp; + if (!(tmp=realloc(r->b,++r->num*sizeof(b)))) return s; +// printf("branch realloc: %p -> %p (%d*%d)\n",r->b,tmp,r->num,sizeof(b)); + r->b=tmp; + } +// printf("%p (size %d)\n",r->b,r->num*sizeof(b)); + r->b[r->num-1]=b; + if (*s==')') { + r->b[r->num-1].m=matchempty; + return s; + } +// printf("assigned branch %d at %p\n",r->num-1,r->b); + s=tmp; if (*s=='|') ++s; + } + return tmp; +} + + +/* The matcher relies on the presence of next pointers, of which the + * parser does not know the correct destination. So we need an + * additional pass through the data structure that sets the next + * pointers correctly. */ +static void regex_putnext(struct regex* r,void* next); + +static void atom_putnext(struct atom*__restrict__ a,void*__restrict__ next) { + a->next=next; + if (a->type==REGEX) + regex_putnext(&a->u.r,0); +} + +static void piece_putnext(struct piece*__restrict__ p,void*__restrict__ next) { + p->next=next; + atom_putnext(&p->a,next); +} + +static void branch_putnext(struct branch*__restrict__ b,void*__restrict__ next) { + int i; + if (b->m!=matchempty) { + for (i=0; inum-1; ++i) { + if (b->p[i+1].min==1 && b->p[i+1].max==1) + piece_putnext(&b->p[i],&b->p[i+1].a); + else + piece_putnext(&b->p[i],&b->p[i+1]); + } + piece_putnext(&b->p[i],0); + } + b->next=next; +} + +static void regex_putnext(struct regex*__restrict__ r,void*__restrict__ next) { + int i; + for (i=0; inum; ++i) + branch_putnext(&r->b[i],next); + r->next=next; +} + + + +int regcomp(regex_t*__restrict__ preg, const char*__restrict__ regex, int cflags) { + const char* t; + preg->cflags=cflags; + t=parseregex(&preg->r,regex,preg); + if (t==regex && *regex!=0) return -1; + regex_putnext(&preg->r,0); + return 0; +} + +int regexec(const regex_t*__restrict__ preg, const char*__restrict__ string, size_t nmatch, regmatch_t pmatch[], int eflags) { + int matched; + const char *orig=string; + assert(preg->brackets+1>0 && preg->brackets<1000); +#ifdef DEBUG + printf("alloca(%d)\n",sizeof(regmatch_t)*(preg->brackets+3)); +#endif + ((regex_t*)preg)->l=alloca(sizeof(regmatch_t)*(preg->brackets+3)); + while (1) { + matched=preg->r.m((void*)&preg->r,string,string-orig,(regex_t*)preg,0,eflags); +// printf("ebp on stack = %x\n",stack[1]); + if (matched>=0) { + preg->l[0].rm_so=string-orig; + preg->l[0].rm_eo=string-orig+matched; + if ((preg->cflags®_NOSUB)==0) memcpy(pmatch,preg->l,nmatch*sizeof(regmatch_t)); + return 0; + } + if (!*string) break; + ++string; eflags|=REG_NOTBOL; + } + return REG_NOMATCH; +} + +static void __regfree(struct regex* r) { + int i; + for (i=0; inum; ++i) { + int j,k; + k=r->b[i].num; + for (j=0; jb[i].p[j].a.type==REGEX) + __regfree(&r->b[i].p[j].a.u.r); + free(r->b[i].p); + } + free(r->b); +} + +void regfree(regex_t* preg) { + __regfree(&preg->r); + memset(preg,0,sizeof(regex_t)); +} + diff --git a/kernel/fiasco/src/lib/uart/Makefile b/kernel/fiasco/src/lib/uart/Makefile new file mode 100644 index 00000000..616b9580 --- /dev/null +++ b/kernel/fiasco/src/lib/uart/Makefile @@ -0,0 +1,12 @@ +include $(srcdir)/Makeconf +include $(srcdir)/Makerules.global + +vpath %.cc $(VPATH_LIBUART) + +all: $(notdir $(TARGET))($(OBJECTS)) + +$(OBJECTS): $(objbase)/.Compiler-config + +$(notdir $(TARGET)): $(OBJECTS) + +-include $(wildcard .*.d) diff --git a/kernel/fiasco/src/lib/uart/io_regblock.h b/kernel/fiasco/src/lib/uart/io_regblock.h new file mode 100644 index 00000000..db56a0e2 --- /dev/null +++ b/kernel/fiasco/src/lib/uart/io_regblock.h @@ -0,0 +1,96 @@ +#pragma once + +#ifndef __GXX_EXPERIMENTAL_CXX0X__ +#ifndef static_assert +#define static_assert(x, y) \ + do { (void)sizeof(char[-(!(x))]); } while (0) +#endif +#endif + +namespace L4 +{ + class Io_register_block + { + public: + virtual unsigned char read8(unsigned long reg) const = 0; + virtual unsigned short read16(unsigned long reg) const = 0; + virtual unsigned int read32(unsigned long reg) const = 0; + //virtual unsigned long long read64(unsigned long reg) const = 0; + + virtual void write8(unsigned long reg, unsigned char val) const = 0; + virtual void write16(unsigned long reg, unsigned short val) const = 0; + virtual void write32(unsigned long reg, unsigned int val) const = 0; + //virtual void write64(unsigned long reg, unsigned long long val) const = 0; + + virtual void delay() const = 0; + + virtual ~Io_register_block() = 0; + + template< typename R > + R read(unsigned long reg) const + { + switch (sizeof(R)) + { + case 1: return read8(reg); + case 2: return read16(reg); + case 4: return read32(reg); + default: static_assert(sizeof(R) == 1 || sizeof(R) == 2 || sizeof(R) == 4, + "Invalid size"); + }; + } + + template< typename R > + void write(unsigned long reg, R val) const + { + switch (sizeof(R)) + { + case 1: write8(reg, val); return; + case 2: write16(reg, val); return; + case 4: write32(reg, val); return; + default: static_assert(sizeof(R) == 1 || sizeof(R) == 2 || sizeof(R) == 4, + "Invalid size"); + }; + } + }; + + inline Io_register_block::~Io_register_block() {} + + + class Io_register_block_mmio : public Io_register_block + { + private: + template< typename R > + R _read(unsigned long reg) const + { return *reinterpret_cast(_base + (reg << _shift)); } + + template< typename R > + void _write(unsigned long reg, R val) const + { *reinterpret_cast(_base + (reg << _shift)) = val; } + + public: + Io_register_block_mmio(unsigned long base, unsigned char shift = 0) + : _base(base), _shift(shift) + {} + + unsigned char read8(unsigned long reg) const + { return _read(reg); } + unsigned short read16(unsigned long reg) const + { return _read(reg); } + unsigned int read32(unsigned long reg) const + { return _read(reg); } + + void write8(unsigned long reg, unsigned char val) const + { _write(reg, val); } + void write16(unsigned long reg, unsigned short val) const + { _write(reg, val); } + void write32(unsigned long reg, unsigned int val) const + { _write(reg, val); } + + void delay() const + {} + + private: + unsigned long _base; + unsigned char _shift; + }; +} diff --git a/kernel/fiasco/src/lib/uart/io_regblock_asi.h b/kernel/fiasco/src/lib/uart/io_regblock_asi.h new file mode 100644 index 00000000..81e7a2c5 --- /dev/null +++ b/kernel/fiasco/src/lib/uart/io_regblock_asi.h @@ -0,0 +1,53 @@ +#pragma once + +#include "io_regblock.h" +#include "processor.h" + +namespace L4 +{ + class Io_register_block_asi : public Io_register_block + { + public: + + Io_register_block_asi(unsigned long base) + : _base(base) + {} + + unsigned char read8(unsigned long reg) const + { + return Proc::read_alternative<0x1C>(_base + reg) & 0xFF; + } + + unsigned short read16(unsigned long reg) const + { + return Proc::read_alternative<0x1C>(_base + reg) & 0xFFFF; + } + + unsigned int read32(unsigned long reg) const + { + return Proc::read_alternative<0x1C>(_base + reg); + } + + void write8(unsigned long reg, unsigned char val) const + { + Proc::write_alternative<0x1C>(_base + reg, val); + } + + void write16(unsigned long reg, unsigned short val) const + { + Proc::write_alternative<0x1C>(_base + reg, val); + } + + void write32(unsigned long reg, unsigned int val) const + { + Proc::write_alternative<0x1C>(_base + reg, val); + } + + void delay() const + { + } + + private: + unsigned long _base; + }; +} diff --git a/kernel/fiasco/src/lib/uart/io_regblock_port.h b/kernel/fiasco/src/lib/uart/io_regblock_port.h new file mode 100644 index 00000000..12c5cb1f --- /dev/null +++ b/kernel/fiasco/src/lib/uart/io_regblock_port.h @@ -0,0 +1,50 @@ +#pragma once + +#include "io_regblock.h" + +namespace L4 +{ + class Io_register_block_port : public Io_register_block + { + public: + Io_register_block_port(unsigned long base) + : _base(base) + {} + + unsigned char read8(unsigned long reg) const + { + unsigned char val; + asm volatile("inb %w1, %b0" : "=a" (val) : "Nd" (_base + reg)); + return val; + } + + unsigned short read16(unsigned long reg) const + { + unsigned short val; + asm volatile("inw %w1, %w0" : "=a" (val) : "Nd" (_base + reg)); + return val; + } + + unsigned int read32(unsigned long reg) const + { + unsigned int val; + asm volatile("in %w1, %0" : "=a" (val) : "Nd" (_base + reg)); + return val; + } + + void write8(unsigned long reg, unsigned char val) const + { asm volatile("outb %b0, %w1" : : "a" (val), "Nd" (_base + reg)); } + + void write16(unsigned long reg, unsigned short val) const + { asm volatile("outw %w0, %w1" : : "a" (val), "Nd" (_base + reg)); } + + void write32(unsigned long reg, unsigned int val) const + { asm volatile("out %0, %w1" : : "a" (val), "Nd" (_base + reg)); } + + void delay() const + { asm volatile ("outb %al,$0x80"); } + + private: + unsigned long _base; + }; +} diff --git a/kernel/fiasco/src/lib/uart/of1275.h b/kernel/fiasco/src/lib/uart/of1275.h new file mode 100644 index 00000000..1b3ea928 --- /dev/null +++ b/kernel/fiasco/src/lib/uart/of1275.h @@ -0,0 +1,109 @@ +#ifndef L4_CXX_OF1275_H__ +#define L4_CXX_OF1275_H__ + +#include +#include + +namespace L4 { + + class Of + { + + private: + /* declarations */ + struct prom_args + { + const char *service; + int nargs; + int nret; + void *args[10]; + prom_args(const char *s, int na, int nr) : service(s), nargs(na), nret(nr) {} + }; + + typedef int (*prom_entry)(struct prom_args *); + + /* attributes */ + prom_entry _prom; + + //int prom_call(const char *service, int nargs, int nret, ...) const; + protected: + enum { + PROM_ERROR = -1u + }; + + + typedef void *ihandle_t; + typedef void *phandle_t; + + typedef struct + { + unsigned long len; + char data[]; + } of_item_t; + + /* methods */ + unsigned prom_call(const char *service, int nargs, int nret, ...) const + { + struct prom_args args = prom_args(service, nargs, nret); + va_list list; + + va_start(list, nret); + for(int i = 0; i < nargs; i++) + args.args[i] = va_arg(list, void*); + va_end(list); + + for(int i = 0; i < nret; i++) + args.args[nargs + i] = 0; + + if(_prom(&args) < 0) + return PROM_ERROR; + + return (nret > 0) ? (int)args.args[nargs] : 0; + } + + + inline int prom_getprop(phandle_t node, const char *pname, void *value, + size_t size) + { + return prom_call("getprop", 4, 1, node, pname, (unsigned long)value, + (unsigned long)size); + } + + inline int prom_next_node(phandle_t *nodep) + { + phandle_t node; + + if ((node = *nodep) != 0 + && (*nodep = (phandle_t)prom_call("child", 1, 1, node)) != 0) + return 1; + if ((*nodep = (phandle_t)prom_call("peer", 1, 1, node)) != 0) + return 1; + for (;;) { + if ((node = (phandle_t)prom_call("parent", 1, 1, node)) == 0) + return 0; + if ((*nodep = (phandle_t)prom_call("peer", 1, 1, node)) != 0) + return 1; + } + } + + template + static inline bool handle_valid(T p) + { + return ((unsigned)p != 0 && (unsigned)p != PROM_ERROR); + } + + public: + Of() : _prom(0) {} + Of(unsigned long prom) : _prom(reinterpret_cast(prom)) {} + + template + inline void set_prom(T prom) + { + _prom = reinterpret_cast(prom); + } + }; +}; + +#endif + + diff --git a/kernel/fiasco/src/lib/uart/uart_base.h b/kernel/fiasco/src/lib/uart/uart_base.h new file mode 100644 index 00000000..3ac3a9fa --- /dev/null +++ b/kernel/fiasco/src/lib/uart/uart_base.h @@ -0,0 +1,40 @@ +#pragma once + +#include +#include "io_regblock.h" + +namespace L4 +{ + class Uart + { + protected: + unsigned _mode; + unsigned _rate; + Io_register_block const *_regs; + + public: + void *operator new (size_t, void* a) + { return a; } + + public: + typedef unsigned Transfer_mode; + typedef unsigned Baud_rate; + + Uart() + : _mode(~0U), _rate(~0U) + {} + + virtual bool startup(Io_register_block const *regs) = 0; + + virtual ~Uart() {} + virtual void shutdown() = 0; + virtual bool change_mode(Transfer_mode m, Baud_rate r) = 0; + virtual int get_char(bool blocking = true) const = 0; + virtual int char_avail() const = 0; + virtual int write(char const *s, unsigned long count) const = 0; + + virtual bool enable_rx_irq(bool = true) { return false; } + Transfer_mode mode() const { return _mode; } + Baud_rate rate() const { return _rate; } + }; +} diff --git a/kernel/fiasco/src/lib/uart/uart_dcc-v6.cc b/kernel/fiasco/src/lib/uart/uart_dcc-v6.cc new file mode 100644 index 00000000..0a21d0b5 --- /dev/null +++ b/kernel/fiasco/src/lib/uart/uart_dcc-v6.cc @@ -0,0 +1,56 @@ +#include "uart_dcc-v6.h" + +namespace L4 +{ + bool Uart_dcc_v6::startup(Io_register_block const *) + { return true; } + + void Uart_dcc_v6::shutdown() + {} + + bool Uart_dcc_v6::change_mode(Transfer_mode, Baud_rate) + { return true; } + + int Uart_dcc_v6::get_char(bool /*blocking*/) const + { +#ifdef ARCH_arm + int c; + asm volatile("mrc p14, 0, %0, c0, c5, 0": "=r" (c)); + return c & 0xff; +#else + return 0; +#endif + } + + int Uart_dcc_v6::char_avail() const + { +#ifdef ARCH_arm + unsigned long s; + asm volatile("mrc p14, 0, %0, c0, c1, 0" : "=r" (s)); + return s & 0x40000000; +#else + return false; +#endif + } + + void Uart_dcc_v6::out_char(char c) const + { +#ifdef ARCH_arm + unsigned long s; + do + asm volatile("mrc p14, 0, %0, c0, c1, 0" : "=r" (s)); + while (s & 0x20000000); + asm volatile("mcr p14, 0, %0, c0, c5, 0": : "r" (c & 0xff)); +#else + (void)c; +#endif + } + + int Uart_dcc_v6::write(char const *s, unsigned long count) const + { + unsigned long c = count; + while (c--) + out_char(*s++); + return count; + } +}; diff --git a/kernel/fiasco/src/lib/uart/uart_dcc-v6.h b/kernel/fiasco/src/lib/uart/uart_dcc-v6.h new file mode 100644 index 00000000..90529672 --- /dev/null +++ b/kernel/fiasco/src/lib/uart/uart_dcc-v6.h @@ -0,0 +1,21 @@ +#ifndef L4_CXX_UART_DCC_V6_H__ +#define L4_CXX_UART_DCC_V6_H__ + +#include "uart_base.h" + +namespace L4 +{ + class Uart_dcc_v6 : public Uart + { + public: + bool startup(Io_register_block const *); + void shutdown(); + bool change_mode(Transfer_mode m, Baud_rate r); + int get_char(bool blocking = true) const; + int char_avail() const; + inline void out_char(char c) const; + int write(char const *s, unsigned long count) const; + }; +}; + +#endif diff --git a/kernel/fiasco/src/lib/uart/uart_imx.cc b/kernel/fiasco/src/lib/uart/uart_imx.cc new file mode 100644 index 00000000..98568b64 --- /dev/null +++ b/kernel/fiasco/src/lib/uart/uart_imx.cc @@ -0,0 +1,159 @@ +#include "uart_imx.h" + +namespace L4 +{ + enum { + URXD = 0x00, // Receiver + UTXD = 0x40, // Transmitter + UCR1 = 0x80, // Control 1 + UCR2 = 0x84, // Control 2 + UCR3 = 0x88, // Control 3 + UCR4 = 0x8c, // Control 4 + UFCR = 0x90, // FIFO Control + USR1 = 0x94, // Status 1 + USR2 = 0x98, // Status 2 + UESC = 0x9c, // Escape Charater + UTIM = 0xa0, // Escape Timer + UBIR = 0xa4, // BRM Incremental Registers + UBMR = 0xa8, // BRM Modulator Registers + UBRC = 0xac, // Baud Rate Count + ONEMS = 0xb0, // One millisecond + UTS = 0xb4, // Test + + + UCR1_EN = 1 << 0, // Enable UART + + UCR2_SRST = 1 << 0, // Software Reset + UCR2_RXEN = 1 << 1, // Receiver Enable + UCR2_TXEN = 1 << 2, // Transmitter Enable + UCR2_WS = 1 << 5, // 8-bit character length + UCR2_STPB = 1 << 6, // 0 = 1 Stop bit, 1 = 2 stop bits + UCR2_PROE = 1 << 7, // 0 = even parity, 1 = odd parity + UCR2_PREN = 1 << 8, // Parity enable + UCR2_RTEC_MASK = 3 << 9, // Request to Send Edge Control mask + UCR2_RTEC_RISI = 0 << 9, // Trigger IRQ on rising edge + UCR2_RTEC_FALL = 1 << 9, // Trigger IRQ on falling edge + UCR2_RTEC_ANY = 2 << 9, // Trigger IRQ on any edge + UCR2_ESCEN = 1 << 11, // Escape enable + UCR2_CTS = 1 << 12, // Clear to Send: 0 = pin is high (inactive), 1 = pin is low (active) + UCR2_CTSC = 1 << 13, // CTS Pin Control: 0 = pin controlled by CTS bit, 1 = pin controlled by the receiver + UCR2_IRTS = 1 << 14, // Ignore RTS pin + UCR2_ESCI = 1 << 15, // Escape Sequence Interrupt Enable + + UCR3_ACIEN = 1 << 0, // Autobaud Counter Interrupt enable + UCR3_INVT = 1 << 1, // Inverted Infrared Transmission + UCR3_RXDMUXSEL = 1 << 2, // RXD Muxed Input Selected: 0 = serial ist IPP_UART_RXD, IR is IPP_UART_RXD_IR, 1 = IPP_UART_RXD_MUX for both + + + UCR4_DREN = 1 << 0, // Receive Data Ready Interrupt Enable + UCR4_OREN = 1 << 1, // Receiver Overrun Interrupt enable + UCR4_BKEN = 1 << 2, // BREAK Condition Dected Interrupt enable + UCR4_TCEN = 1 << 3, // Transmit Complete Interrupt Enable + UCR4_LPBYP = 1 << 4, // Low Power Bypass + UCR4_IRSC = 1 << 5, // IR Special Case + // Bit 6 is reserve, should be written as 0 + UCR4_WKEN = 1 << 7, // WAKE Interrupt Enable + UCR4_ENIRI = 1 << 8, // Serial Infrared Interrupt Enable + UCR4_INVR = 1 << 9, // Inverted Infrared Reception + UCR4_CTSTL_32 = 32 << 10, // CTS Trigger Level + + UFCR_RXTL_MASK = 63 << 0, // Receiver Trigger Level Mask + UFCR_RXTL_1 = 1 << 0, // Receiver Trigger Level: 1 char + UFCR_RFDIV_2 = 4 << 7, // Reference Frequency Divier: by 2 + UFCR_TXTL_MASK = 63 << 10, // Trasmitter Trigger Level: 8 chars + UFCR_TXTL_8 = 8 << 10, // Trasmitter Trigger Level: 8 chars + UFCR_TXTL_32 = 32 << 10, // Trasmitter Trigger Level: 32 chars + + USR1_TRDY = 1 << 13, // Transmitter Ready + + USR2_RDR = 1 << 0, // Receive Data Ready + USR2_ORE = 1 << 1, // Overrun Error + USR2_BRCD = 1 << 2, // Break Condition Detected + USR2_TXDC = 1 << 3, // Transmitter Complete + USR2_TXFE = 1 << 14, // Transmit Buffer FIFO Empty + + }; + + bool Uart_imx::startup(Io_register_block const *regs) + { + _regs = regs; + + // 115200Baud, 8n1 + switch (_type) + { + case Type_imx21: + _regs->write(UBIR, 0x0344); + _regs->write(UBMR, 0x270f); + break; + case Type_imx35: + _regs->write(UBIR, 0xf); + _regs->write(UBMR, 0x1b2); + break; + case Type_imx51: + _regs->write(UBIR, 0xf); + _regs->write(UBMR, 0x120); + break; + } + + _regs->write(UCR1, UCR1_EN); + _regs->write(UCR2, UCR2_SRST | UCR2_RXEN | UCR2_TXEN | UCR2_WS | UCR2_IRTS); // note: no IRQs enabled + _regs->write(UCR3, UCR3_RXDMUXSEL); + _regs->write(UCR4, UCR4_CTSTL_32); + _regs->write(UFCR, UFCR_TXTL_8 | UFCR_RFDIV_2 | UFCR_RXTL_1); + + return true; + } + + void Uart_imx::shutdown() + { + _regs->write(UCR1, 0); // Disable UART + } + + bool Uart_imx::enable_rx_irq(bool enable) + { + if (enable) + { + _regs->write(UCR2, _regs->read(UCR2) | UCR2_RTEC_ANY); + _regs->write(UCR4, _regs->read(UCR4) | UCR4_DREN); + } + else + _regs->write(UCR4, _regs->read(UCR4) & ~UCR4_DREN); + + return true; + } + + bool Uart_imx::change_mode(Transfer_mode, Baud_rate) + { return true; } + + int Uart_imx::get_char(bool blocking) const + { + while (!char_avail()) + if (!blocking) return -1; + + return _regs->read(URXD) & 0xff; + } + + int Uart_imx::char_avail() const + { + return _regs->read(USR2) & USR2_RDR; + } + + void Uart_imx::out_char(char c) const + { + while (!(_regs->read(USR1) & USR1_TRDY)) + ; + _regs->write(UTXD, c); + } + + int Uart_imx::write(char const *s, unsigned long count) const + { + unsigned long c = count; + while (c--) + out_char(*s++); + + while (!(_regs->read(USR2) & USR2_TXDC)) + ; + + return count; + } +}; diff --git a/kernel/fiasco/src/lib/uart/uart_imx.h b/kernel/fiasco/src/lib/uart/uart_imx.h new file mode 100644 index 00000000..5293d2b8 --- /dev/null +++ b/kernel/fiasco/src/lib/uart/uart_imx.h @@ -0,0 +1,46 @@ +#ifndef L4_CXX_UART_imx_H__ +#define L4_CXX_UART_imx_H__ + +#include "uart_base.h" + +namespace L4 +{ + class Uart_imx : public Uart + { + public: + enum platform_type { Type_imx21, Type_imx35, Type_imx51 }; + explicit Uart_imx(enum platform_type type) + : _type(type) {} + bool startup(Io_register_block const *); + void shutdown(); + bool enable_rx_irq(bool enable = true); + bool change_mode(Transfer_mode m, Baud_rate r); + int get_char(bool blocking = true) const; + int char_avail() const; + inline void out_char(char c) const; + int write(char const *s, unsigned long count) const; + + private: + enum platform_type _type; + }; + + class Uart_imx21 : public Uart_imx + { + public: + Uart_imx21() : Uart_imx(Type_imx21) {} + }; + + class Uart_imx35 : public Uart_imx + { + public: + Uart_imx35() : Uart_imx(Type_imx35) {} + }; + + class Uart_imx51 : public Uart_imx + { + public: + Uart_imx51() : Uart_imx(Type_imx51) {} + }; +}; + +#endif diff --git a/kernel/fiasco/src/lib/uart/uart_leon3.cc b/kernel/fiasco/src/lib/uart/uart_leon3.cc new file mode 100644 index 00000000..9b30ed9a --- /dev/null +++ b/kernel/fiasco/src/lib/uart/uart_leon3.cc @@ -0,0 +1,93 @@ +#include "uart_leon3.h" + +namespace L4 +{ + enum { + DATA_REG = 0x00, + STATUS_REG = 0x04, + CTRL_REG = 0x08, + SCALER_REG = 0x0C, + + DATA_MASK = 0x0F, + + STATUS_DR = 0x001, // data ready + STATUS_TS = 0x002, // transmit shift empty + STATUS_TE = 0x004, // transmit fifo empty + STATUS_BR = 0x008, // BREAK received + STATUS_OV = 0x010, // overrun + STATUS_PE = 0x020, // parity error + STATUS_FE = 0x040, // framing error + STATUS_TH = 0x080, // transmit fifo half-full + STATUS_RH = 0x100, // recv fifo half-full + STATUS_TF = 0x200, // transmit fifo full + STATUS_RF = 0x400, // recv fifo full + + STATUS_TCNT_MASK = 0x3F, + STATUS_TCNT_SHIFT = 20, + STATUS_RCNT_MASK = 0x3F, + STATUS_RCNT_SHIFT = 26, + + CTRL_RE = 0x001, + CTRL_TE = 0x002, + CTRL_RI = 0x004, + CTRL_TI = 0x008, + CTRL_PS = 0x010, + CTRL_PE = 0x020, + CTRL_FL = 0x040, + CTRL_LB = 0x080, + CTRL_EC = 0x100, + CTRL_TF = 0x200, + CTRL_RF = 0x400, + + SCALER_MASK = 0xFFF, + }; + + + bool Uart_leon3::startup(Io_register_block const *regs) + { + _regs = regs; + + return true; + } + + void Uart_leon3::shutdown() + { } + + bool Uart_leon3::change_mode(Transfer_mode, Baud_rate r) + { + if (r != 115200) + return false; + + return true; + } + + int Uart_leon3::get_char(bool blocking) const + { + while (!char_avail()) + if (!blocking) + return -1; + + return _regs->read(DATA_REG) & DATA_MASK; + } + + int Uart_leon3::char_avail() const + { + return 0; + } + + void Uart_leon3::out_char(char c) const + { + while (_regs->read(STATUS_REG) & STATUS_TF) + ; + _regs->write(DATA_REG, c); + } + + int Uart_leon3::write(char const *s, unsigned long count) const + { + unsigned long c = count; + while (c--) + out_char(*s++); + + return count; + } +}; diff --git a/kernel/fiasco/src/lib/uart/uart_leon3.h b/kernel/fiasco/src/lib/uart/uart_leon3.h new file mode 100644 index 00000000..58eb16e2 --- /dev/null +++ b/kernel/fiasco/src/lib/uart/uart_leon3.h @@ -0,0 +1,21 @@ +#ifndef L4_CXX_UART_LEON3_H__ +#define L4_CXX_UART_LEON3_H__ + +#include "uart_base.h" + +namespace L4 +{ + class Uart_leon3 : public Uart + { + public: + bool startup(Io_register_block const *); + void shutdown(); + bool change_mode(Transfer_mode m, Baud_rate r); + int get_char(bool blocking = true) const; + int char_avail() const; + inline void out_char(char c) const; + int write(char const *s, unsigned long count) const; + }; +}; + +#endif diff --git a/kernel/fiasco/src/lib/uart/uart_mpc52xx.cc b/kernel/fiasco/src/lib/uart/uart_mpc52xx.cc new file mode 100644 index 00000000..69a3e892 --- /dev/null +++ b/kernel/fiasco/src/lib/uart/uart_mpc52xx.cc @@ -0,0 +1,147 @@ +#include "uart_mpc52xx.h" +#include "of1275.h" +#include "mmu.h" + +namespace L4 +{ + + enum + { + MR1_RXIRQ = 0x040, + + SR_TXRDY = 0x400, + SR_TXEMPTY = 0x800, + SR_RXRDY = 0x100, + + CMD_TX_ENABLE = 0x004, + CMD_TX_RESET = 0x030, + CMD_RX_ENABLE = 0x001, + CMD_RX_DISABLE = 0x002, + CMD_RX_RESET = 0x020, + CMD_RESET_MODE = 0x010, + CMD_RESET_ERR = 0x040, + CMD_RESET_BREAK= 0x050, + + IMR_RXRDY = 0x200 + }; + + template < typename T > + void Uart_mpc52xx::wr_dirty(unsigned long addr, T val) const + { + asm volatile("sync \n" :::); + *(volatile T*)addr = val; + } + + template < typename T > + void Uart_mpc52xx::wr(unsigned long addr, T val) const + { + Mmu_guard dcache; + wr_dirty(addr, val); + } + + template < typename T > + T Uart_mpc52xx::rd_dirty(unsigned long addr) const + { + volatile T ret; + asm volatile("sync \n" :::); + ret = *(volatile T*)addr; + asm volatile("isync\n" :::); + return ret; + } + + template < typename T > + T Uart_mpc52xx::rd(unsigned long addr) const + { + Mmu_guard dcache; + return rd_dirty(addr); + } + + bool Uart_mpc52xx::startup(const L4::Io_register_block *regs) + { + _regs = regs; + //wait for Of uart driver to finish transmission + Mmu_guard dcache; + while (!(rd_dirty(status()) & SR_TXEMPTY)) + ; + //read MR1 + wr_dirty(command(), CMD_RESET_MODE); + u8 mode_val = rd_dirty(mode()); + //mode points to MR2 + wr_dirty(command(), CMD_RESET_MODE); + //mode points to MR1 + + //clear RxIRQ in MR1 register (RxRDY is now source of interrupt) + mode_val &= ~MR1_RXIRQ; + wr_dirty(mode(), mode_val); + + //disable interrupts + wr_dirty(imr(), 0); + + wr_dirty(status(), 0xdd00); + wr_dirty(sicr(), 0); + + //enable transmit, receive + wr_dirty(command(), CMD_TX_RESET); + wr_dirty(command(), CMD_TX_ENABLE); + wr_dirty(command(), CMD_RX_RESET); + wr_dirty(command(), CMD_RX_ENABLE); + + write("MPC52xx serial port: replaced OF\n", 33); + return true; + } + + void Uart_mpc52xx::out_char(char c) const + { + Mmu_guard dcache; + mpc52xx_out_char(c); + } + + int Uart_mpc52xx::write(char const *s, unsigned long count) const + { + Mmu_guard dcache; + unsigned long c = count; + while (c--) + mpc52xx_out_char(*s++); + return count; + } + + + inline int Uart_mpc52xx::char_avail() const + { + return rd(status()) & SR_RXRDY; + } + + int Uart_mpc52xx::get_char(bool blocking) const + { + while(!char_avail()) + if(!blocking) return -1; + int c = (int)rd(buffer()); + + //reset error conditions + wr(command(), CMD_RESET_ERR); + return c; + } + + bool Uart_mpc52xx::enable_rx_irq(bool enable) + { + u16 mask = 0; + if(enable) + mask |= IMR_RXRDY; + + wr(imr(), mask); + + return true; + } + + //PRIVATE + inline void Uart_mpc52xx::mpc52xx_out_char(char c) const + { + while(!(rd_dirty(status()) & SR_TXRDY)) + ; + wr_dirty(buffer(), c); + } + + //TODO: implement + void Uart_mpc52xx::shutdown() {} + bool Uart_mpc52xx::change_mode(Transfer_mode, Baud_rate) { return true; } +}; diff --git a/kernel/fiasco/src/lib/uart/uart_mpc52xx.h b/kernel/fiasco/src/lib/uart/uart_mpc52xx.h new file mode 100644 index 00000000..af14c478 --- /dev/null +++ b/kernel/fiasco/src/lib/uart/uart_mpc52xx.h @@ -0,0 +1,68 @@ +#ifndef L4_CXX_UART_MPC52XX_H__ +#define L4_CXX_UART_MPC52XX_H__ + +#include "uart_base.h" +#include "of1275.h" + +namespace L4 +{ + class Uart_mpc52xx : public Uart + { + private: + typedef unsigned char u8; + typedef unsigned short u16; + typedef unsigned int u32; + + /** + * PSC registers + */ + //psc + 0x00, size u8 + unsigned long mode() const + { return 0; } + + //psc + 0x04, size u16 + unsigned long status() const + { return 0x04; } + + //psc + 0x08, size u8 + unsigned long command() const + { return 0x08; } + + //psc + 0x0c, size u32 + unsigned long buffer() const + { return 0x0c; } + + //psc + 0x14, size u16 + unsigned long imr() const + { return 0x14; } + + unsigned long sicr() const + { return 0x44; } + + template < typename T > + void wr(unsigned long addr, T val) const; + + template < typename T > + T rd(unsigned long addr) const; + + template < typename T > + void wr_dirty(unsigned long addr, T val) const; + + template < typename T > + T rd_dirty(unsigned long addr) const; + + inline void mpc52xx_out_char(char c) const; + + public: + bool startup(const L4::Io_register_block *); + void shutdown(); + bool enable_rx_irq(bool enable = true); + bool change_mode(Transfer_mode m, Baud_rate r); + int get_char(bool blocking = true) const; + int char_avail() const; + inline void out_char(char c) const; + int write(char const *s, unsigned long count) const; + }; +}; + +#endif diff --git a/kernel/fiasco/src/lib/uart/uart_of.cc b/kernel/fiasco/src/lib/uart/uart_of.cc new file mode 100644 index 00000000..3b06bef0 --- /dev/null +++ b/kernel/fiasco/src/lib/uart/uart_of.cc @@ -0,0 +1,58 @@ +#include "uart_of.h" +#include + +namespace L4 { + + bool Uart_of::startup(Io_register_block const *) + { + char path[64], type[16]; + for (phandle_t node = 0; prom_next_node(&node); ) + { + prom_getprop(node, "device_type", type, sizeof(type)); + + if (strcmp(type, "serial")) + continue; + + if (prom_call("package-to-path", 3, 1, node, + path, sizeof(path)) == Of::PROM_ERROR) + return false; + + /* open port */ + if ((_serial = (ihandle_t)prom_call("open", 1, 1, path)) != 0) + return false; + + break; + } + //prom_call("exit", 0, 0); + return _serial; + } + + void Uart_of::shutdown() + { + prom_call("close", 1, 0, _serial); + } + + int Uart_of::get_char(bool blocking) const + { + int c, len = 0; + + while (len != 1 && blocking) + len = prom_call("read", 3, 1, _serial, &c, 1); + + return len ? c :-1; + } + + int Uart_of::write(char const *s, unsigned long count) const + { + return prom_call("write", 3, 1, _serial, s, count); + } + + void Uart_of::out_char(char c) const + { + prom_call("write", 3, 0, _serial, c, 1); + } + + /* UNIMPLEMENTED */ + bool Uart_of::change_mode(Transfer_mode, Baud_rate){ return true; } + int Uart_of::char_avail() const { return 1; } +}; diff --git a/kernel/fiasco/src/lib/uart/uart_of.h b/kernel/fiasco/src/lib/uart/uart_of.h new file mode 100644 index 00000000..a8638ed4 --- /dev/null +++ b/kernel/fiasco/src/lib/uart/uart_of.h @@ -0,0 +1,30 @@ +#ifndef L4_CXX_UART_OF_H__ +#define L4_CXX_UART_OF_H__ + +#include "uart_base.h" +#include +#include +#include "of1275.h" + +namespace L4 +{ + class Uart_of : public Uart, public Of + { + private: + ihandle_t _serial; + + public: + Uart_of() + : Of(), _serial(0) {} + bool startup(Io_register_block const *); + + void shutdown(); + bool change_mode(Transfer_mode m, Baud_rate r); + int get_char(bool blocking = true) const; + int char_avail() const; + void out_char(char c) const; + int write(char const *s, unsigned long count) const; + }; +}; + +#endif diff --git a/kernel/fiasco/src/lib/uart/uart_omap35x.cc b/kernel/fiasco/src/lib/uart/uart_omap35x.cc new file mode 100644 index 00000000..7762f40a --- /dev/null +++ b/kernel/fiasco/src/lib/uart/uart_omap35x.cc @@ -0,0 +1,100 @@ +#include "uart_omap35x.h" + +namespace L4 +{ + enum { + DLL_REG = 0x00, + RHR_REG = 0x00, + THR_REG = 0x00, + IER_REG = 0x04, + DLH_REG = 0x04, + LCD_REG = 0x08, + LSR_REG = 0x14, + SSR_REG = 0x44, + SYSC_REG = 0x54, + SYSS_REG = 0x58, + + LCD_REG_CHAR_LENGTH_5BIT = 0 << 0, + LCD_REG_CHAR_LENGTH_6BIT = 1 << 0, + LCD_REG_CHAR_LENGTH_7BIT = 2 << 0, + LCD_REG_CHAR_LENGTH_8BIT = 3 << 0, + LCD_REG_CHAR_NB_STOP_2 = 1 << 2, + LCD_REG_CHAR_PARITY_EN = 1 << 3, + LCD_REG_CHAR_PARITY_TYPE1_EVEN = 1 << 4, + + LSR_REG_RX_FIFO_E_AVAIL = 1 << 0, + LSR_REG_TX_FIFO_E_EMPTY = 1 << 5, + + SSR_REG_TX_FIFO_FULL = 1 << 0, + + SYSC_REG_SOFTRESET = 1 << 1, + + SYSC_REG_RESETDONE = 1 << 0, + }; + + + bool Uart_omap35x::startup(Io_register_block const *regs) + { + _regs = regs; + + // Reset UART + //_regs->write(SYSC_REG, _regs->read(SYSC_REG) | SYSC_REG_SOFTRESET); + //while (!(_regs->read(SYSS_REG) & SYSC_REG_RESETDONE)) + // ; + + return true; + } + + void Uart_omap35x::shutdown() + { + } + + bool Uart_omap35x::enable_rx_irq(bool enable) + { + _regs->write(IER_REG, enable ? 1 : 0); + return true; + } + bool Uart_omap35x::change_mode(Transfer_mode, Baud_rate r) + { + if (r != 115200) + return false; + + return true; + } + + int Uart_omap35x::get_char(bool blocking) const + { + while (!char_avail()) + if (!blocking) + return -1; + + return _regs->read(RHR_REG); + } + + int Uart_omap35x::char_avail() const + { + return _regs->read(LSR_REG) & LSR_REG_RX_FIFO_E_AVAIL; + } + + void Uart_omap35x::out_char(char c) const + { + _regs->write(THR_REG, c); + while (!(_regs->read(LSR_REG) & LSR_REG_TX_FIFO_E_EMPTY)) + ; + } + + int Uart_omap35x::write(char const *s, unsigned long count) const + { + unsigned long c = count; + while (c--) + out_char(*s++); +#if 0 + while (_regs->read(UART01x_FR) & UART01x_FR_BUSY) + ; +#endif + + return count; + } + +}; + diff --git a/kernel/fiasco/src/lib/uart/uart_omap35x.h b/kernel/fiasco/src/lib/uart/uart_omap35x.h new file mode 100644 index 00000000..2d66468c --- /dev/null +++ b/kernel/fiasco/src/lib/uart/uart_omap35x.h @@ -0,0 +1,22 @@ +#ifndef L4_CXX_UART_OMAP35X_H__ +#define L4_CXX_UART_OMAP35X_H__ + +#include "uart_base.h" + +namespace L4 +{ + class Uart_omap35x : public Uart + { + public: + bool startup(Io_register_block const *); + void shutdown(); + bool change_mode(Transfer_mode m, Baud_rate r); + bool enable_rx_irq(bool); + int get_char(bool blocking = true) const; + int char_avail() const; + inline void out_char(char c) const; + int write(char const *s, unsigned long count) const; + }; +}; + +#endif diff --git a/kernel/fiasco/src/lib/uart/uart_pl011.cc b/kernel/fiasco/src/lib/uart/uart_pl011.cc new file mode 100644 index 00000000..2b545cb9 --- /dev/null +++ b/kernel/fiasco/src/lib/uart/uart_pl011.cc @@ -0,0 +1,132 @@ +#include "uart_pl011.h" + +namespace L4 +{ + enum { + UART011_RXIM = 1 << 4, + UART011_TXIM = 1 << 5, + UART011_RTIM = 1 << 6, + UART011_FEIM = 1 << 7, + UART011_PEIM = 1 << 8, + UART011_BEIM = 1 << 9, + UART011_OEIM = 1 << 10, + + UART011_RXIS = 1 << 4, + UART011_RTIS = 1 << 6, + + UART011_RXIC = 1 << 4, + UART011_RTIC = 1 << 6, + + UART01x_CR_UARTEN = 1, // UART enable + UART011_CR_LBE = 0x080, // loopback enable + UART011_CR_TXE = 0x100, // transmit enable + UART011_CR_RXE = 0x200, // receive enable + + UART01x_FR_BUSY = 0x008, + UART01x_FR_RXFE = 0x010, + UART01x_FR_TXFF = 0x020, + + UART01x_LCRH_PEN = 0x02, // parity enable + UART01x_LCRH_FEN = 0x10, // FIFO enable + UART01x_LCRH_WLEN_8 = 0x60, + + UART01x_DR = 0x00, + UART011_ECR = 0x04, + UART01x_FR = 0x18, + UART011_IBRD = 0x24, + UART011_FBRD = 0x28, + UART011_LCRH = 0x2c, + UART011_CR = 0x30, + UART011_IMSC = 0x38, + UART011_MIS = 0x40, + UART011_ICR = 0x44, + }; + + + bool Uart_pl011::startup(Io_register_block const *regs) + { + _regs = regs; + _regs->write(UART011_CR, UART01x_CR_UARTEN | UART011_CR_TXE | UART011_CR_RXE); + _regs->write(UART011_FBRD, 2); + _regs->write(UART011_IBRD, 13); + _regs->write(UART011_LCRH, 0x60); + _regs->write(UART011_IMSC, 0); + while (_regs->read(UART01x_FR) & UART01x_FR_BUSY) + ; + return true; + } + + void Uart_pl011::shutdown() + { + _regs->write(UART011_IMSC, 0); + _regs->write(UART011_ICR, 0xffff); + _regs->write(UART011_CR, 0); + } + + bool Uart_pl011::enable_rx_irq(bool enable) + { + unsigned long mask = UART011_RXIM | UART011_RTIM; + + _regs->write(UART011_ICR, 0xffff & ~mask); + _regs->write(UART011_ECR, 0xff); + if (enable) + _regs->write(UART011_IMSC, _regs->read(UART011_IMSC) | mask); + else + _regs->write(UART011_IMSC, _regs->read(UART011_IMSC) & ~mask); + return true; + } + + bool Uart_pl011::change_mode(Transfer_mode, Baud_rate r) + { + if (r != 115200) + return false; + + unsigned long old_cr = _regs->read(UART011_CR); + _regs->write(UART011_CR, 0); + + _regs->write(UART011_FBRD, 2); + _regs->write(UART011_IBRD, 13); + _regs->write(UART011_LCRH, UART01x_LCRH_WLEN_8 | UART01x_LCRH_FEN); + + _regs->write(UART011_CR, old_cr); + + return true; + } + + int Uart_pl011::get_char(bool blocking) const + { + while (!char_avail()) + if (!blocking) + return -1; + + //_regs->write(UART011_ICR, UART011_RXIC | UART011_RTIC); + + int c = _regs->read(UART01x_DR); + _regs->write(UART011_ECR, 0xff); + return c; + } + + int Uart_pl011::char_avail() const + { + return !(_regs->read(UART01x_FR) & UART01x_FR_RXFE); + } + + void Uart_pl011::out_char(char c) const + { + while (_regs->read(UART01x_FR) & UART01x_FR_TXFF) + ; + _regs->write(UART01x_DR,c); + } + + int Uart_pl011::write(char const *s, unsigned long count) const + { + unsigned long c = count; + while (c--) + out_char(*s++); + + while (_regs->read(UART01x_FR) & UART01x_FR_BUSY) + ; + + return count; + } +}; diff --git a/kernel/fiasco/src/lib/uart/uart_pl011.h b/kernel/fiasco/src/lib/uart/uart_pl011.h new file mode 100644 index 00000000..3e9019ea --- /dev/null +++ b/kernel/fiasco/src/lib/uart/uart_pl011.h @@ -0,0 +1,22 @@ +#ifndef L4_CXX_UART_PL011_H__ +#define L4_CXX_UART_PL011_H__ + +#include "uart_base.h" + +namespace L4 +{ + class Uart_pl011 : public Uart + { + public: + bool startup(Io_register_block const *); + void shutdown(); + bool change_mode(Transfer_mode m, Baud_rate r); + bool enable_rx_irq(bool enable); + int get_char(bool blocking = true) const; + int char_avail() const; + inline void out_char(char c) const; + int write(char const *s, unsigned long count) const; + }; +}; + +#endif diff --git a/kernel/fiasco/src/lib/uart/uart_s3c2410.cc b/kernel/fiasco/src/lib/uart/uart_s3c2410.cc new file mode 100644 index 00000000..bf91066f --- /dev/null +++ b/kernel/fiasco/src/lib/uart/uart_s3c2410.cc @@ -0,0 +1,239 @@ +#include "uart_s3c2410.h" + +namespace L4 +{ + enum + { + Type_24xx, Type_64xx, Type_s5pv210, + }; + + enum + { + ULCON = 0x0, // line control register + UCON = 0x4, // control register + UFCON = 0x8, // FIFO control register + UMCON = 0xc, // modem control register + UTRSTAT = 0x10, // Tx/Rx status register + UERSTAT = 0x14, // Rx error status register + UFSTAT = 0x18, // FIFO status register + UMSTAT = 0x1c, // modem status register + UTXH = 0x20, // transmit buffer register (little endian, 0x23 for BE) + URXH = 0x24, // receive buffer register (little endian, 0x27 for BE) + UBRDIV = 0x28, // baud rate divisor register + // 64xx++ + UINTP = 0x30, // interrupt pending register + UINTSP = 0x34, // interrupt source pending register + UINTM = 0x38, // interrupt mask register + + + ULCON_8N1_MODE = 0x3, + + UCON_MODE_RECEIVE_IRQ_POLL = 1 << 0, + UCON_MODE_TRANSMIT_IRQ_POLL = 1 << 2, + UCON_SEND_BREAK_SIGNAL = 1 << 4, + UCON_LOOPBACK_MODE = 1 << 5, + UCON_RX_ERROR_STATUS_IRQ_EN = 1 << 6, + UCON_RX_TIME_OUT_EN = 1 << 7, + UCON_MODE = UCON_MODE_RECEIVE_IRQ_POLL + | UCON_MODE_TRANSMIT_IRQ_POLL + | UCON_RX_TIME_OUT_EN, + + UFCON_ENABLE = 1 << 0, // enable fifo + UFCON_RX_FIFO_RESET = 1 << 1, // Rx Fifo reset + UFCON_TX_FIFO_RESET = 1 << 2, // Tx Fifo reset + + UMCON_AFC = 1 << 4, + + UTRSTAT_Rx_RDY = 1 << 0, + UTRSTAT_Tx_RDY = 1 << 1, + + UINT_RXD = 1 << 0, + UINT_ERROR = 1 << 1, + UINT_TXD = 1 << 2, + UINT_MODEM = 1 << 3, + + // 2410 + UFSTAT_2410_Rx_COUNT_MASK = 0x00f, + UFSTAT_2410_Tx_COUNT_MASK = 0x0f0, + UFSTAT_2410_RxFULL = 0x100, + UFSTAT_2410_TxFULL = 0x200, + + // 64xx + UFSTAT_64XX_Rx_COUNT_MASK = 0x003f, + UFSTAT_64XX_Tx_COUNT_MASK = 0x3f00, + UFSTAT_64XX_RxFULL = 0x0040, + UFSTAT_64XX_TxFULL = 0x4000, + + // s5pv210 + UFSTAT_S5PV210_Rx_COUNT_MASK = 0x000000ff, + UFSTAT_S5PV210_Tx_COUNT_MASK = 0x00ff0000, + UFSTAT_S5PV210_RxFULL = 0x00000100, + UFSTAT_S5PV210_TxFULL = 0x01000000, + }; + + + void Uart_s3c::fifo_reset() + { + _regs->write(UFCON, UFCON_RX_FIFO_RESET | UFCON_TX_FIFO_RESET); + while (_regs->read(UFCON) & (UFCON_RX_FIFO_RESET | UFCON_TX_FIFO_RESET)) + ; + } + + + bool Uart_s3c::startup(Io_register_block const *regs) + { + _regs = regs; + + fifo_reset(); +#if 0 + _regs->write(UMCON, 0); +#endif + + _regs->write(ULCON, ULCON_8N1_MODE); + _regs->write(UCON, UCON_MODE); + _regs->write(UFCON, UFCON_ENABLE); + + switch (type()) + { + case Type_24xx: + break; + case Type_64xx: + case Type_s5pv210: + _regs->write(UINTM, ~UINT_RXD); // mask all but receive irq + _regs->write(UINTP, ~0); // clear all pending irqs + break; + } +#if 0 + _regs->write(UBRDIV, 0x23); +#endif + + return true; + } + + void Uart_s3c::shutdown() + { + // more + } + + bool Uart_s3c::change_mode(Transfer_mode, Baud_rate r) + { + if (r != 115200) + return false; + +#if 0 + _regs->write(ULCON, ULCON_8N1_MODE); + _regs->write(UCON, UCON_MODE); + _regs->write(UFCON, 1); + + _regs->write(UBRDIV, 0x23); +#endif + + return true; + } + + int Uart_s3c::get_char(bool blocking) const + { + while (!char_avail()) + if (!blocking) + return -1; + + _regs->read(UFCON); + int c = _regs->read(URXH) & 0xff; + ack_rx_irq(); + return c; + } + + int Uart_s3c::char_avail() const + { + return is_rx_fifo_non_empty(); + } + + void Uart_s3c::out_char(char c) const + { + wait_for_non_full_tx_fifo(); + _regs->write(UTXH, c); + } + + int Uart_s3c::write(char const *s, unsigned long count) const + { + unsigned long c = count; + while (c--) + out_char(*s++); + wait_for_empty_tx_fifo(); + + return count; + } + + // ----------------------- + + void Uart_s3c2410::wait_for_empty_tx_fifo() const + { + while (_regs->read(UFSTAT) & (UFSTAT_2410_Tx_COUNT_MASK | UFSTAT_2410_TxFULL)) + ; + } + + void Uart_s3c2410::wait_for_non_full_tx_fifo() const + { + while (_regs->read(UFSTAT) & UFSTAT_2410_TxFULL) + ; + } + + unsigned Uart_s3c2410::is_rx_fifo_non_empty() const + { + return _regs->read(UFSTAT) & (UFSTAT_2410_Rx_COUNT_MASK | UFSTAT_2410_RxFULL); + } + + void Uart_s3c2410::auto_flow_control(bool on) + { + _regs->write(UMCON, (_regs->read(UMCON) & ~UMCON_AFC) | (on ? UMCON_AFC : 0)); + } + + // ----------------------- + + void Uart_s3c64xx::wait_for_empty_tx_fifo() const + { + while (_regs->read(UFSTAT) & (UFSTAT_64XX_Tx_COUNT_MASK | UFSTAT_64XX_TxFULL)) + ; + } + + void Uart_s3c64xx::wait_for_non_full_tx_fifo() const + { + while (_regs->read(UFSTAT) & UFSTAT_64XX_TxFULL) + ; + } + + unsigned Uart_s3c64xx::is_rx_fifo_non_empty() const + { + return _regs->read(UFSTAT) & (UFSTAT_64XX_Rx_COUNT_MASK | UFSTAT_64XX_RxFULL); + } + + void Uart_s3c64xx::ack_rx_irq() const + { + _regs->write(UINTP, UINT_RXD); + } + + // ----------------------- + + void Uart_s5pv210::wait_for_empty_tx_fifo() const + { + while (_regs->read(UFSTAT) & (UFSTAT_S5PV210_Tx_COUNT_MASK | UFSTAT_S5PV210_TxFULL)) + ; + } + + void Uart_s5pv210::wait_for_non_full_tx_fifo() const + { + while (_regs->read(UFSTAT) & UFSTAT_S5PV210_TxFULL) + ; + } + + unsigned Uart_s5pv210::is_rx_fifo_non_empty() const + { + return _regs->read(UFSTAT) & (UFSTAT_S5PV210_Rx_COUNT_MASK | UFSTAT_S5PV210_RxFULL); + } + + void Uart_s5pv210::ack_rx_irq() const + { + _regs->write(UINTP, UINT_RXD); + } +}; + diff --git a/kernel/fiasco/src/lib/uart/uart_s3c2410.h b/kernel/fiasco/src/lib/uart/uart_s3c2410.h new file mode 100644 index 00000000..93bca297 --- /dev/null +++ b/kernel/fiasco/src/lib/uart/uart_s3c2410.h @@ -0,0 +1,78 @@ +#ifndef L4_DRIVERS_UART_S3C2410_H__ +#define L4_DRIVERS_UART_S3C2410_H__ + +#include "uart_base.h" + +namespace L4 +{ + class Uart_s3c : public Uart + { + protected: + enum Uart_type + { + Type_24xx, Type_64xx, Type_s5pv210, + }; + + Uart_type type() const { return _type; } + + public: + explicit Uart_s3c(Uart_type type) : _type(type) {} + bool startup(Io_register_block const *); + void shutdown(); + bool change_mode(Transfer_mode m, Baud_rate r); + int get_char(bool blocking = true) const; + int char_avail() const; + inline void out_char(char c) const; + int write(char const *s, unsigned long count) const; + void fifo_reset(); + + protected: + virtual void ack_rx_irq() const = 0; + virtual void wait_for_empty_tx_fifo() const = 0; + virtual void wait_for_non_full_tx_fifo() const = 0; + virtual unsigned is_rx_fifo_non_empty() const = 0; + + private: + Uart_type _type; + }; + + class Uart_s3c2410 : public Uart_s3c + { + public: + Uart_s3c2410() : Uart_s3c(Type_24xx) {} + + protected: + void ack_rx_irq() const {} + void wait_for_empty_tx_fifo() const; + void wait_for_non_full_tx_fifo() const; + unsigned is_rx_fifo_non_empty() const; + + void auto_flow_control(bool on); + }; + + class Uart_s3c64xx : public Uart_s3c + { + public: + Uart_s3c64xx() : Uart_s3c(Type_64xx) {} + + protected: + void ack_rx_irq() const; + void wait_for_empty_tx_fifo() const; + void wait_for_non_full_tx_fifo() const; + unsigned is_rx_fifo_non_empty() const; + }; + + class Uart_s5pv210 : public Uart_s3c + { + public: + Uart_s5pv210() : Uart_s3c(Type_s5pv210) {} + + protected: + void ack_rx_irq() const; + void wait_for_empty_tx_fifo() const; + void wait_for_non_full_tx_fifo() const; + unsigned is_rx_fifo_non_empty() const; + }; +}; + +#endif diff --git a/kernel/fiasco/src/templates/.gdbinit.ux b/kernel/fiasco/src/templates/.gdbinit.ux new file mode 100644 index 00000000..eed1929d --- /dev/null +++ b/kernel/fiasco/src/templates/.gdbinit.ux @@ -0,0 +1,20 @@ +# GDB init file for use with Fiasco-UX (rename to .gdbinit) + +define tcb + p *(class Thread*)((unsigned)&_tcbs_1 + (($arg0 << 17) + ($arg1 << 10) << 1)) +end + +define dtcb + graph display *(class Thread*)((unsigned)&_tcbs_1 + (($arg0 << 17) + ($arg1 << 10) << 1)) +end + +define tcbat + p *(class Thread*)($arg0) +end + +file fiasco + +set output-radix 16 +set history save on + +handle 11 nostop noprint diff --git a/kernel/fiasco/src/templates/Makefile b/kernel/fiasco/src/templates/Makefile new file mode 100644 index 00000000..3f09b05f --- /dev/null +++ b/kernel/fiasco/src/templates/Makefile @@ -0,0 +1,40 @@ +# sample configurations + +SAMPLE_CONFIGS := $(subst globalconfig.out.,,$(wildcard globalconfig.out.*)) + +srcdir = $(shell pwd)/../ + +all: + +runconfig = cp globalconfig.out.$(2) globalconfig.out ; \ + make $(1) && sed -e '3,4d' \ + globalconfig.out > globalconfig.out.$(2) + +cleanup = make mrproper && \ + $(RM) -r globalconfig.out.old globalconfig.h Kconfig include + +testconfigs: + $(foreach cfg,$(SAMPLE_CONFIGS), $(call runconfig,menuconfig,$(cfg))) + $(call cleanup) + +testconfig: + if [ "$$T" != "" ]; then $(call runconfig,menuconfig,$$T); \ + else echo "use: make T=configname testconfig"; fi + $(call cleanup) + +refresh: + for cfg in $(SAMPLE_CONFIGS); do \ + echo "********************************************"; \ + echo "** $$cfg **"; \ + echo "********************************************"; \ + $(call runconfig,oldconfig,$$cfg); \ + done + $(call cleanup) + +%: + $(MAKE) -f $(srcdir)/Makefile \ + srcdir=$(srcdir) objbase=$(shell pwd) "$@" + + +.PHONY: refresh testconfig + diff --git a/kernel/fiasco/src/templates/Makefile.builddir.templ b/kernel/fiasco/src/templates/Makefile.builddir.templ new file mode 100644 index 00000000..fd0a73f9 --- /dev/null +++ b/kernel/fiasco/src/templates/Makefile.builddir.templ @@ -0,0 +1,9 @@ +# This Makefile is a template for the Makefile used in the build +# directories. +# + +srcdir := @SRCDIR@ +objbase := $(shell pwd) + +include $(srcdir)/Makefile + diff --git a/kernel/fiasco/src/templates/globalconfig.out.amd64-1 b/kernel/fiasco/src/templates/globalconfig.out.amd64-1 new file mode 100644 index 00000000..b2366c5f --- /dev/null +++ b/kernel/fiasco/src/templates/globalconfig.out.amd64-1 @@ -0,0 +1,72 @@ +# +# Automatically generated file; DO NOT EDIT. + +# +# Target configuration +# +# CONFIG_IA32 is not set +CONFIG_AMD64=y +# CONFIG_ARM is not set +CONFIG_PF_PC=y +CONFIG_ABI_VF=y +CONFIG_AMD64_K8=y +# CONFIG_AMD64_CORE2 is not set +# CONFIG_AMD64_ATOM is not set +# CONFIG_AMD64_K10 is not set +# CONFIG_CPU_VIRT is not set +# CONFIG_SCHED_PIT is not set +# CONFIG_SCHED_RTC is not set +CONFIG_SCHED_APIC=y +# CONFIG_SCHED_HPET is not set +# CONFIG_WORKAROUND_AMD_FPU_LEAK is not set + +# +# Kernel options +# +# CONFIG_MP is not set +CONFIG_CONTEXT_4K=y +CONFIG_IO_PROT=y +# CONFIG_FINE_GRAINED_CPUTIME is not set +CONFIG_SCHED_FIXED_PRIO=y +# CONFIG_SCHED_WFQ is not set +# CONFIG_SCHED_FP_WFQ is not set +# CONFIG_DISABLE_VIRT_OBJ_SPACE is not set + +# +# Debugging +# +CONFIG_INLINE=y +# CONFIG_NDEBUG is not set +CONFIG_NO_FRAME_PTR=y +# CONFIG_STACK_DEPTH is not set +# CONFIG_LIST_ALLOC_SANITY is not set +# CONFIG_BEFORE_IRET_SANITY is not set +# CONFIG_IRQ_SPINNER is not set +CONFIG_WATCHDOG=y +CONFIG_SERIAL=y +CONFIG_JDB=y +CONFIG_JDB_LOGGING=y +CONFIG_JDB_DISASM=y +CONFIG_JDB_GZIP=y +CONFIG_JDB_MISC=y +CONFIG_POWERSAVE_GETCHAR=y +# CONFIG_WARN_NONE is not set +CONFIG_WARN_WARNING=y +# CONFIG_WARN_ANY is not set + +# +# Compiling +# +CONFIG_CC="gcc" +CONFIG_CXX="g++" +CONFIG_HOST_CC="gcc" +CONFIG_HOST_CXX="g++" +# CONFIG_MAINTAINER_MODE is not set +CONFIG_LABEL="" +CONFIG_EXPERIMENTAL=y +CONFIG_PERF_CNT=y +CONFIG_BIT64=y +CONFIG_WARN_LEVEL=1 +CONFIG_XARCH="amd64" +CONFIG_IA32_TARGET="AMD Opteron" +CONFIG_ABI="vf" diff --git a/kernel/fiasco/src/templates/globalconfig.out.amd64-2 b/kernel/fiasco/src/templates/globalconfig.out.amd64-2 new file mode 100644 index 00000000..77a434e4 --- /dev/null +++ b/kernel/fiasco/src/templates/globalconfig.out.amd64-2 @@ -0,0 +1,72 @@ +# +# Automatically generated file; DO NOT EDIT. + +# +# Target configuration +# +# CONFIG_IA32 is not set +CONFIG_AMD64=y +# CONFIG_ARM is not set +CONFIG_PF_PC=y +CONFIG_ABI_VF=y +CONFIG_AMD64_K8=y +# CONFIG_AMD64_CORE2 is not set +# CONFIG_AMD64_ATOM is not set +# CONFIG_AMD64_K10 is not set +CONFIG_CPU_VIRT=y +CONFIG_SCHED_PIT=y +# CONFIG_SCHED_RTC is not set +# CONFIG_SCHED_APIC is not set +# CONFIG_SCHED_HPET is not set +# CONFIG_WORKAROUND_AMD_FPU_LEAK is not set + +# +# Kernel options +# +# CONFIG_MP is not set +CONFIG_CONTEXT_4K=y +CONFIG_IO_PROT=y +# CONFIG_FINE_GRAINED_CPUTIME is not set +CONFIG_SCHED_FIXED_PRIO=y +# CONFIG_SCHED_WFQ is not set +# CONFIG_SCHED_FP_WFQ is not set +# CONFIG_DISABLE_VIRT_OBJ_SPACE is not set + +# +# Debugging +# +CONFIG_INLINE=y +# CONFIG_NDEBUG is not set +CONFIG_NO_FRAME_PTR=y +CONFIG_STACK_DEPTH=y +# CONFIG_LIST_ALLOC_SANITY is not set +# CONFIG_BEFORE_IRET_SANITY is not set +# CONFIG_IRQ_SPINNER is not set +# CONFIG_WATCHDOG is not set +CONFIG_SERIAL=y +CONFIG_JDB=y +# CONFIG_JDB_LOGGING is not set +CONFIG_JDB_DISASM=y +CONFIG_JDB_GZIP=y +CONFIG_JDB_MISC=y +CONFIG_POWERSAVE_GETCHAR=y +# CONFIG_WARN_NONE is not set +CONFIG_WARN_WARNING=y +# CONFIG_WARN_ANY is not set + +# +# Compiling +# +CONFIG_CC="gcc" +CONFIG_CXX="g++" +CONFIG_HOST_CC="gcc" +CONFIG_HOST_CXX="g++" +CONFIG_MAINTAINER_MODE=y +CONFIG_LABEL="" +CONFIG_EXPERIMENTAL=y +CONFIG_PERF_CNT=y +CONFIG_BIT64=y +CONFIG_WARN_LEVEL=1 +CONFIG_XARCH="amd64" +CONFIG_IA32_TARGET="AMD Opteron" +CONFIG_ABI="vf" diff --git a/kernel/fiasco/src/templates/globalconfig.out.amd64-3-noinl b/kernel/fiasco/src/templates/globalconfig.out.amd64-3-noinl new file mode 100644 index 00000000..66f95d14 --- /dev/null +++ b/kernel/fiasco/src/templates/globalconfig.out.amd64-3-noinl @@ -0,0 +1,72 @@ +# +# Automatically generated file; DO NOT EDIT. + +# +# Target configuration +# +# CONFIG_IA32 is not set +CONFIG_AMD64=y +# CONFIG_ARM is not set +CONFIG_PF_PC=y +CONFIG_ABI_VF=y +CONFIG_AMD64_K8=y +# CONFIG_AMD64_CORE2 is not set +# CONFIG_AMD64_ATOM is not set +# CONFIG_AMD64_K10 is not set +# CONFIG_CPU_VIRT is not set +# CONFIG_SCHED_PIT is not set +# CONFIG_SCHED_RTC is not set +CONFIG_SCHED_APIC=y +# CONFIG_SCHED_HPET is not set +# CONFIG_WORKAROUND_AMD_FPU_LEAK is not set + +# +# Kernel options +# +# CONFIG_MP is not set +CONFIG_CONTEXT_4K=y +CONFIG_IO_PROT=y +# CONFIG_FINE_GRAINED_CPUTIME is not set +CONFIG_SCHED_FIXED_PRIO=y +# CONFIG_SCHED_WFQ is not set +# CONFIG_SCHED_FP_WFQ is not set +# CONFIG_DISABLE_VIRT_OBJ_SPACE is not set + +# +# Debugging +# +# CONFIG_INLINE is not set +# CONFIG_NDEBUG is not set +CONFIG_NO_FRAME_PTR=y +CONFIG_STACK_DEPTH=y +# CONFIG_LIST_ALLOC_SANITY is not set +# CONFIG_BEFORE_IRET_SANITY is not set +# CONFIG_IRQ_SPINNER is not set +CONFIG_WATCHDOG=y +CONFIG_SERIAL=y +CONFIG_JDB=y +CONFIG_JDB_LOGGING=y +CONFIG_JDB_DISASM=y +CONFIG_JDB_GZIP=y +CONFIG_JDB_MISC=y +CONFIG_POWERSAVE_GETCHAR=y +# CONFIG_WARN_NONE is not set +CONFIG_WARN_WARNING=y +# CONFIG_WARN_ANY is not set + +# +# Compiling +# +CONFIG_CC="gcc" +CONFIG_CXX="g++" +CONFIG_HOST_CC="gcc" +CONFIG_HOST_CXX="g++" +CONFIG_MAINTAINER_MODE=y +CONFIG_LABEL="" +CONFIG_EXPERIMENTAL=y +CONFIG_PERF_CNT=y +CONFIG_BIT64=y +CONFIG_WARN_LEVEL=1 +CONFIG_XARCH="amd64" +CONFIG_IA32_TARGET="AMD Opteron" +CONFIG_ABI="vf" diff --git a/kernel/fiasco/src/templates/globalconfig.out.amd64-mp b/kernel/fiasco/src/templates/globalconfig.out.amd64-mp new file mode 100644 index 00000000..3cb7eacf --- /dev/null +++ b/kernel/fiasco/src/templates/globalconfig.out.amd64-mp @@ -0,0 +1,70 @@ +# +# Automatically generated file; DO NOT EDIT. + +# +# Target configuration +# +# CONFIG_IA32 is not set +CONFIG_AMD64=y +# CONFIG_ARM is not set +CONFIG_PF_PC=y +CONFIG_ABI_VF=y +CONFIG_AMD64_K8=y +# CONFIG_AMD64_CORE2 is not set +# CONFIG_AMD64_ATOM is not set +# CONFIG_AMD64_K10 is not set +# CONFIG_CPU_VIRT is not set +CONFIG_SCHED_APIC=y +# CONFIG_WORKAROUND_AMD_FPU_LEAK is not set + +# +# Kernel options +# +CONFIG_MP=y +CONFIG_MP_MAX_CPUS=4 +CONFIG_CONTEXT_4K=y +CONFIG_IO_PROT=y +# CONFIG_FINE_GRAINED_CPUTIME is not set +# CONFIG_SCHED_FIXED_PRIO is not set +CONFIG_SCHED_WFQ=y +# CONFIG_SCHED_FP_WFQ is not set +# CONFIG_DISABLE_VIRT_OBJ_SPACE is not set + +# +# Debugging +# +CONFIG_INLINE=y +# CONFIG_NDEBUG is not set +CONFIG_NO_FRAME_PTR=y +CONFIG_STACK_DEPTH=y +# CONFIG_LIST_ALLOC_SANITY is not set +# CONFIG_BEFORE_IRET_SANITY is not set +# CONFIG_IRQ_SPINNER is not set +# CONFIG_WATCHDOG is not set +CONFIG_SERIAL=y +CONFIG_JDB=y +CONFIG_JDB_LOGGING=y +CONFIG_JDB_DISASM=y +CONFIG_JDB_GZIP=y +CONFIG_JDB_MISC=y +CONFIG_POWERSAVE_GETCHAR=y +# CONFIG_WARN_NONE is not set +CONFIG_WARN_WARNING=y +# CONFIG_WARN_ANY is not set + +# +# Compiling +# +CONFIG_CC="gcc" +CONFIG_CXX="g++" +CONFIG_HOST_CC="gcc" +CONFIG_HOST_CXX="g++" +CONFIG_MAINTAINER_MODE=y +CONFIG_LABEL="" +CONFIG_EXPERIMENTAL=y +CONFIG_PERF_CNT=y +CONFIG_BIT64=y +CONFIG_WARN_LEVEL=1 +CONFIG_XARCH="amd64" +CONFIG_IA32_TARGET="AMD Opteron" +CONFIG_ABI="vf" diff --git a/kernel/fiasco/src/templates/globalconfig.out.arm-a9-mp-1 b/kernel/fiasco/src/templates/globalconfig.out.arm-a9-mp-1 new file mode 100644 index 00000000..2b3e11fe --- /dev/null +++ b/kernel/fiasco/src/templates/globalconfig.out.arm-a9-mp-1 @@ -0,0 +1,89 @@ +# +# Automatically generated file; DO NOT EDIT. + +# +# Target configuration +# +# CONFIG_IA32 is not set +# CONFIG_AMD64 is not set +CONFIG_ARM=y +CONFIG_PF_REALVIEW=y +# CONFIG_PF_IMX is not set +# CONFIG_PF_S3C2410 is not set +# CONFIG_PF_TEGRA2 is not set +# CONFIG_PF_OMAP is not set +# CONFIG_PF_XSCALE is not set +# CONFIG_PF_SA1100 is not set +# CONFIG_PF_KIRKWOOD is not set +# CONFIG_PF_INTEGRATOR is not set +CONFIG_BSP_NAME="realview" +CONFIG_PF_REALVIEW_EB=y +# CONFIG_PF_REALVIEW_PB11MP is not set +# CONFIG_PF_REALVIEW_PBX is not set +# CONFIG_PF_REALVIEW_VEXPRESS is not set +CONFIG_PF_REALVIEW_RAM_PHYS_BASE=0x0 +CONFIG_ABI_VF=y +CONFIG_PF_ARM_MP_CAPABLE=y +CONFIG_CAN_ARM_CPU_926=y +CONFIG_CAN_ARM_CPU_1176=y +CONFIG_CAN_ARM_CPU_MPCORE=y +CONFIG_CAN_ARM_CPU_CORTEX_A8=y +CONFIG_CAN_ARM_CPU_CORTEX_A9=y +# CONFIG_ARM_926 is not set +# CONFIG_ARM_1176 is not set +# CONFIG_ARM_MPCORE is not set +# CONFIG_ARM_CORTEX_A8 is not set +CONFIG_ARM_CORTEX_A9=y +# CONFIG_ARM_ALIGNMENT_CHECK is not set +# CONFIG_ARM_TZ is not set +CONFIG_ARM_CA9_ENABLE_SWP=y +CONFIG_FPU=y + +# +# Kernel options +# +CONFIG_MP=y +CONFIG_MP_MAX_CPUS=4 +CONFIG_CONTEXT_4K=y +# CONFIG_FINE_GRAINED_CPUTIME is not set +CONFIG_SCHED_FIXED_PRIO=y +# CONFIG_SCHED_WFQ is not set +# CONFIG_SCHED_FP_WFQ is not set +# CONFIG_DISABLE_VIRT_OBJ_SPACE is not set + +# +# Debugging +# +CONFIG_INLINE=y +# CONFIG_NDEBUG is not set +CONFIG_NO_FRAME_PTR=y +# CONFIG_STACK_DEPTH is not set +# CONFIG_LIST_ALLOC_SANITY is not set +CONFIG_SERIAL=y +CONFIG_JDB=y +# CONFIG_JDB_LOGGING is not set +# CONFIG_JDB_DISASM is not set +# CONFIG_JDB_GZIP is not set +# CONFIG_VMEM_ALLOC_TEST is not set +# CONFIG_DEBUG_KERNEL_PAGE_FAULTS is not set +# CONFIG_WARN_NONE is not set +CONFIG_WARN_WARNING=y +# CONFIG_WARN_ANY is not set + +# +# Compiling +# +CONFIG_CC="gcc" +CONFIG_CXX="g++" +CONFIG_HOST_CC="gcc" +CONFIG_HOST_CXX="g++" +# CONFIG_MAINTAINER_MODE is not set +CONFIG_LABEL="" +CONFIG_EXPERIMENTAL=y +CONFIG_PERF_CNT=y +CONFIG_BIT32=y +CONFIG_ARM_V7=y +CONFIG_ARM_V6PLUS=y +CONFIG_WARN_LEVEL=1 +CONFIG_XARCH="arm" +CONFIG_ABI="vf" diff --git a/kernel/fiasco/src/templates/globalconfig.out.arm-a9-mp-2 b/kernel/fiasco/src/templates/globalconfig.out.arm-a9-mp-2 new file mode 100644 index 00000000..31194af2 --- /dev/null +++ b/kernel/fiasco/src/templates/globalconfig.out.arm-a9-mp-2 @@ -0,0 +1,89 @@ +# +# Automatically generated file; DO NOT EDIT. + +# +# Target configuration +# +# CONFIG_IA32 is not set +# CONFIG_AMD64 is not set +CONFIG_ARM=y +CONFIG_PF_REALVIEW=y +# CONFIG_PF_IMX is not set +# CONFIG_PF_S3C2410 is not set +# CONFIG_PF_TEGRA2 is not set +# CONFIG_PF_OMAP is not set +# CONFIG_PF_XSCALE is not set +# CONFIG_PF_SA1100 is not set +# CONFIG_PF_KIRKWOOD is not set +# CONFIG_PF_INTEGRATOR is not set +CONFIG_BSP_NAME="realview" +CONFIG_PF_REALVIEW_EB=y +# CONFIG_PF_REALVIEW_PB11MP is not set +# CONFIG_PF_REALVIEW_PBX is not set +# CONFIG_PF_REALVIEW_VEXPRESS is not set +CONFIG_PF_REALVIEW_RAM_PHYS_BASE=0x0 +CONFIG_ABI_VF=y +CONFIG_PF_ARM_MP_CAPABLE=y +CONFIG_CAN_ARM_CPU_926=y +CONFIG_CAN_ARM_CPU_1176=y +CONFIG_CAN_ARM_CPU_MPCORE=y +CONFIG_CAN_ARM_CPU_CORTEX_A8=y +CONFIG_CAN_ARM_CPU_CORTEX_A9=y +# CONFIG_ARM_926 is not set +# CONFIG_ARM_1176 is not set +# CONFIG_ARM_MPCORE is not set +# CONFIG_ARM_CORTEX_A8 is not set +CONFIG_ARM_CORTEX_A9=y +# CONFIG_ARM_ALIGNMENT_CHECK is not set +CONFIG_ARM_TZ=y +# CONFIG_ARM_CA9_ENABLE_SWP is not set +CONFIG_FPU=y + +# +# Kernel options +# +CONFIG_MP=y +CONFIG_MP_MAX_CPUS=4 +CONFIG_CONTEXT_4K=y +# CONFIG_FINE_GRAINED_CPUTIME is not set +CONFIG_SCHED_FIXED_PRIO=y +# CONFIG_SCHED_WFQ is not set +# CONFIG_SCHED_FP_WFQ is not set +# CONFIG_DISABLE_VIRT_OBJ_SPACE is not set + +# +# Debugging +# +CONFIG_INLINE=y +# CONFIG_NDEBUG is not set +CONFIG_NO_FRAME_PTR=y +# CONFIG_STACK_DEPTH is not set +# CONFIG_LIST_ALLOC_SANITY is not set +CONFIG_SERIAL=y +CONFIG_JDB=y +# CONFIG_JDB_LOGGING is not set +# CONFIG_JDB_DISASM is not set +# CONFIG_JDB_GZIP is not set +# CONFIG_VMEM_ALLOC_TEST is not set +# CONFIG_DEBUG_KERNEL_PAGE_FAULTS is not set +# CONFIG_WARN_NONE is not set +CONFIG_WARN_WARNING=y +# CONFIG_WARN_ANY is not set + +# +# Compiling +# +CONFIG_CC="gcc" +CONFIG_CXX="g++" +CONFIG_HOST_CC="gcc" +CONFIG_HOST_CXX="g++" +# CONFIG_MAINTAINER_MODE is not set +CONFIG_LABEL="" +CONFIG_EXPERIMENTAL=y +CONFIG_PERF_CNT=y +CONFIG_BIT32=y +CONFIG_ARM_V7=y +CONFIG_ARM_V6PLUS=y +CONFIG_WARN_LEVEL=1 +CONFIG_XARCH="arm" +CONFIG_ABI="vf" diff --git a/kernel/fiasco/src/templates/globalconfig.out.arm-a9-mp-vexpress b/kernel/fiasco/src/templates/globalconfig.out.arm-a9-mp-vexpress new file mode 100644 index 00000000..438235bb --- /dev/null +++ b/kernel/fiasco/src/templates/globalconfig.out.arm-a9-mp-vexpress @@ -0,0 +1,83 @@ +# +# Automatically generated file; DO NOT EDIT. + +# +# Target configuration +# +# CONFIG_IA32 is not set +# CONFIG_AMD64 is not set +CONFIG_ARM=y +CONFIG_PF_REALVIEW=y +# CONFIG_PF_IMX is not set +# CONFIG_PF_S3C2410 is not set +# CONFIG_PF_TEGRA2 is not set +# CONFIG_PF_OMAP is not set +# CONFIG_PF_XSCALE is not set +# CONFIG_PF_SA1100 is not set +# CONFIG_PF_KIRKWOOD is not set +# CONFIG_PF_INTEGRATOR is not set +CONFIG_BSP_NAME="realview" +# CONFIG_PF_REALVIEW_EB is not set +# CONFIG_PF_REALVIEW_PB11MP is not set +# CONFIG_PF_REALVIEW_PBX is not set +CONFIG_PF_REALVIEW_VEXPRESS=y +# CONFIG_PF_REALVIEW_RAM_PHYS_BASE_0x0 is not set +CONFIG_PF_REALVIEW_RAM_PHYS_BASE_0x6=y +CONFIG_PF_REALVIEW_RAM_PHYS_BASE=0x60000000 +CONFIG_ABI_VF=y +CONFIG_PF_ARM_MP_CAPABLE=y +CONFIG_CAN_ARM_CPU_CORTEX_A9=y +CONFIG_ARM_CORTEX_A9=y +CONFIG_ARM_ALIGNMENT_CHECK=y +# CONFIG_ARM_TZ is not set +CONFIG_ARM_CA9_ENABLE_SWP=y +CONFIG_FPU=y + +# +# Kernel options +# +CONFIG_MP=y +CONFIG_MP_MAX_CPUS=9 +CONFIG_CONTEXT_4K=y +# CONFIG_FINE_GRAINED_CPUTIME is not set +CONFIG_SCHED_FIXED_PRIO=y +# CONFIG_SCHED_WFQ is not set +# CONFIG_SCHED_FP_WFQ is not set +# CONFIG_DISABLE_VIRT_OBJ_SPACE is not set + +# +# Debugging +# +CONFIG_INLINE=y +# CONFIG_NDEBUG is not set +CONFIG_NO_FRAME_PTR=y +# CONFIG_STACK_DEPTH is not set +# CONFIG_LIST_ALLOC_SANITY is not set +CONFIG_SERIAL=y +CONFIG_JDB=y +CONFIG_JDB_LOGGING=y +# CONFIG_JDB_DISASM is not set +# CONFIG_JDB_GZIP is not set +# CONFIG_VMEM_ALLOC_TEST is not set +# CONFIG_DEBUG_KERNEL_PAGE_FAULTS is not set +# CONFIG_WARN_NONE is not set +CONFIG_WARN_WARNING=y +# CONFIG_WARN_ANY is not set + +# +# Compiling +# +CONFIG_CC="gcc" +CONFIG_CXX="g++" +CONFIG_HOST_CC="gcc" +CONFIG_HOST_CXX="g++" +# CONFIG_MAINTAINER_MODE is not set +CONFIG_LABEL="" +CONFIG_EXPERIMENTAL=y +CONFIG_PERF_CNT=y +CONFIG_BIT32=y +CONFIG_ARM_V7=y +CONFIG_ARM_V6PLUS=y +CONFIG_WARN_LEVEL=1 +CONFIG_XARCH="arm" +CONFIG_ABI="vf" diff --git a/kernel/fiasco/src/templates/globalconfig.out.arm-imx21 b/kernel/fiasco/src/templates/globalconfig.out.arm-imx21 new file mode 100644 index 00000000..201d6f81 --- /dev/null +++ b/kernel/fiasco/src/templates/globalconfig.out.arm-imx21 @@ -0,0 +1,70 @@ +# +# Automatically generated file; DO NOT EDIT. + +# +# Target configuration +# +# CONFIG_IA32 is not set +# CONFIG_AMD64 is not set +CONFIG_ARM=y +# CONFIG_PF_REALVIEW is not set +CONFIG_PF_IMX=y +# CONFIG_PF_S3C2410 is not set +# CONFIG_PF_TEGRA2 is not set +# CONFIG_PF_OMAP is not set +# CONFIG_PF_XSCALE is not set +# CONFIG_PF_SA1100 is not set +# CONFIG_PF_KIRKWOOD is not set +# CONFIG_PF_INTEGRATOR is not set +CONFIG_BSP_NAME="imx" +CONFIG_PF_IMX_21=y +# CONFIG_PF_IMX_35 is not set +# CONFIG_PF_IMX_51 is not set +CONFIG_PF_IMX_RAM_PHYS_BASE=0xc0000000 +CONFIG_ABI_VF=y +CONFIG_CAN_ARM_CPU_926=y +CONFIG_ARM_926=y +# CONFIG_ARM_ALIGNMENT_CHECK is not set +# CONFIG_FPU is not set + +# +# Kernel options +# +CONFIG_CONTEXT_4K=y +# CONFIG_FINE_GRAINED_CPUTIME is not set +CONFIG_SCHED_FIXED_PRIO=y + +# +# Debugging +# +CONFIG_INLINE=y +# CONFIG_NDEBUG is not set +# CONFIG_NO_FRAME_PTR is not set +# CONFIG_STACK_DEPTH is not set +# CONFIG_LIST_ALLOC_SANITY is not set +CONFIG_SERIAL=y +CONFIG_JDB=y +# CONFIG_JDB_LOGGING is not set +# CONFIG_JDB_DISASM is not set +# CONFIG_JDB_GZIP is not set +# CONFIG_VMEM_ALLOC_TEST is not set +# CONFIG_DEBUG_KERNEL_PAGE_FAULTS is not set +# CONFIG_WARN_NONE is not set +CONFIG_WARN_WARNING=y +# CONFIG_WARN_ANY is not set + +# +# Compiling +# +CONFIG_CC="gcc" +CONFIG_CXX="g++" +CONFIG_HOST_CC="gcc" +CONFIG_HOST_CXX="g++" +# CONFIG_MAINTAINER_MODE is not set +CONFIG_LABEL="" +# CONFIG_EXPERIMENTAL is not set +CONFIG_PERF_CNT=y +CONFIG_BIT32=y +CONFIG_WARN_LEVEL=1 +CONFIG_XARCH="arm" +CONFIG_ABI="vf" diff --git a/kernel/fiasco/src/templates/globalconfig.out.arm-imx35 b/kernel/fiasco/src/templates/globalconfig.out.arm-imx35 new file mode 100644 index 00000000..ff6a7a7d --- /dev/null +++ b/kernel/fiasco/src/templates/globalconfig.out.arm-imx35 @@ -0,0 +1,72 @@ +# +# Automatically generated file; DO NOT EDIT. + +# +# Target configuration +# +# CONFIG_IA32 is not set +# CONFIG_AMD64 is not set +CONFIG_ARM=y +# CONFIG_PF_REALVIEW is not set +CONFIG_PF_IMX=y +# CONFIG_PF_S3C2410 is not set +# CONFIG_PF_TEGRA2 is not set +# CONFIG_PF_OMAP is not set +# CONFIG_PF_XSCALE is not set +# CONFIG_PF_SA1100 is not set +# CONFIG_PF_KIRKWOOD is not set +# CONFIG_PF_INTEGRATOR is not set +CONFIG_BSP_NAME="imx" +# CONFIG_PF_IMX_21 is not set +CONFIG_PF_IMX_35=y +# CONFIG_PF_IMX_51 is not set +CONFIG_PF_IMX_RAM_PHYS_BASE=0x80000000 +CONFIG_ABI_VF=y +CONFIG_CAN_ARM_CPU_1136=y +CONFIG_ARM_1136=y +# CONFIG_ARM_ALIGNMENT_CHECK is not set +# CONFIG_FPU is not set + +# +# Kernel options +# +CONFIG_CONTEXT_4K=y +# CONFIG_FINE_GRAINED_CPUTIME is not set +CONFIG_SCHED_FIXED_PRIO=y + +# +# Debugging +# +CONFIG_INLINE=y +CONFIG_NDEBUG=y +# CONFIG_NO_FRAME_PTR is not set +# CONFIG_STACK_DEPTH is not set +# CONFIG_LIST_ALLOC_SANITY is not set +CONFIG_SERIAL=y +CONFIG_JDB=y +CONFIG_JDB_LOGGING=y +# CONFIG_JDB_DISASM is not set +# CONFIG_JDB_GZIP is not set +# CONFIG_VMEM_ALLOC_TEST is not set +# CONFIG_DEBUG_KERNEL_PAGE_FAULTS is not set +# CONFIG_WARN_NONE is not set +CONFIG_WARN_WARNING=y +# CONFIG_WARN_ANY is not set + +# +# Compiling +# +CONFIG_CC="gcc" +CONFIG_CXX="g++" +CONFIG_HOST_CC="gcc" +CONFIG_HOST_CXX="g++" +# CONFIG_MAINTAINER_MODE is not set +CONFIG_LABEL="" +# CONFIG_EXPERIMENTAL is not set +CONFIG_PERF_CNT=y +CONFIG_BIT32=y +CONFIG_ARM_V6=y +CONFIG_ARM_V6PLUS=y +CONFIG_WARN_LEVEL=1 +CONFIG_XARCH="arm" +CONFIG_ABI="vf" diff --git a/kernel/fiasco/src/templates/globalconfig.out.arm-imx51 b/kernel/fiasco/src/templates/globalconfig.out.arm-imx51 new file mode 100644 index 00000000..c9224005 --- /dev/null +++ b/kernel/fiasco/src/templates/globalconfig.out.arm-imx51 @@ -0,0 +1,72 @@ +# +# Automatically generated file; DO NOT EDIT. + +# +# Target configuration +# +# CONFIG_IA32 is not set +# CONFIG_AMD64 is not set +CONFIG_ARM=y +# CONFIG_PF_REALVIEW is not set +CONFIG_PF_IMX=y +# CONFIG_PF_S3C2410 is not set +# CONFIG_PF_TEGRA2 is not set +# CONFIG_PF_OMAP is not set +# CONFIG_PF_XSCALE is not set +# CONFIG_PF_SA1100 is not set +# CONFIG_PF_KIRKWOOD is not set +# CONFIG_PF_INTEGRATOR is not set +CONFIG_BSP_NAME="imx" +# CONFIG_PF_IMX_21 is not set +# CONFIG_PF_IMX_35 is not set +CONFIG_PF_IMX_51=y +CONFIG_PF_IMX_RAM_PHYS_BASE=0x90000000 +CONFIG_ABI_VF=y +CONFIG_CAN_ARM_CPU_CORTEX_A8=y +CONFIG_ARM_CORTEX_A8=y +# CONFIG_ARM_ALIGNMENT_CHECK is not set +# CONFIG_FPU is not set + +# +# Kernel options +# +CONFIG_CONTEXT_4K=y +# CONFIG_FINE_GRAINED_CPUTIME is not set +CONFIG_SCHED_FIXED_PRIO=y + +# +# Debugging +# +CONFIG_INLINE=y +# CONFIG_NDEBUG is not set +# CONFIG_NO_FRAME_PTR is not set +# CONFIG_STACK_DEPTH is not set +# CONFIG_LIST_ALLOC_SANITY is not set +CONFIG_SERIAL=y +CONFIG_JDB=y +# CONFIG_JDB_LOGGING is not set +# CONFIG_JDB_DISASM is not set +# CONFIG_JDB_GZIP is not set +# CONFIG_VMEM_ALLOC_TEST is not set +# CONFIG_DEBUG_KERNEL_PAGE_FAULTS is not set +# CONFIG_WARN_NONE is not set +CONFIG_WARN_WARNING=y +# CONFIG_WARN_ANY is not set + +# +# Compiling +# +CONFIG_CC="gcc" +CONFIG_CXX="g++" +CONFIG_HOST_CC="gcc" +CONFIG_HOST_CXX="g++" +# CONFIG_MAINTAINER_MODE is not set +CONFIG_LABEL="" +# CONFIG_EXPERIMENTAL is not set +CONFIG_PERF_CNT=y +CONFIG_BIT32=y +CONFIG_ARM_V7=y +CONFIG_ARM_V6PLUS=y +CONFIG_WARN_LEVEL=1 +CONFIG_XARCH="arm" +CONFIG_ABI="vf" diff --git a/kernel/fiasco/src/templates/globalconfig.out.arm-int-1 b/kernel/fiasco/src/templates/globalconfig.out.arm-int-1 new file mode 100644 index 00000000..ecfd641a --- /dev/null +++ b/kernel/fiasco/src/templates/globalconfig.out.arm-int-1 @@ -0,0 +1,68 @@ +# +# Automatically generated file; DO NOT EDIT. + +# +# Target configuration +# +# CONFIG_IA32 is not set +# CONFIG_AMD64 is not set +CONFIG_ARM=y +# CONFIG_PF_REALVIEW is not set +# CONFIG_PF_IMX is not set +# CONFIG_PF_S3C2410 is not set +# CONFIG_PF_TEGRA2 is not set +# CONFIG_PF_OMAP is not set +# CONFIG_PF_XSCALE is not set +# CONFIG_PF_SA1100 is not set +# CONFIG_PF_KIRKWOOD is not set +CONFIG_PF_INTEGRATOR=y +CONFIG_BSP_NAME="integrator" +CONFIG_ABI_VF=y +CONFIG_CAN_ARM_CPU_926=y +CONFIG_CAN_ARM_CPU_1176=y +CONFIG_ARM_926=y +# CONFIG_ARM_1176 is not set +# CONFIG_ARM_ALIGNMENT_CHECK is not set +# CONFIG_FPU is not set + +# +# Kernel options +# +CONFIG_CONTEXT_4K=y +# CONFIG_FINE_GRAINED_CPUTIME is not set +CONFIG_SCHED_FIXED_PRIO=y + +# +# Debugging +# +CONFIG_INLINE=y +# CONFIG_NDEBUG is not set +CONFIG_NO_FRAME_PTR=y +# CONFIG_STACK_DEPTH is not set +# CONFIG_LIST_ALLOC_SANITY is not set +CONFIG_SERIAL=y +CONFIG_JDB=y +# CONFIG_JDB_LOGGING is not set +# CONFIG_JDB_DISASM is not set +# CONFIG_JDB_GZIP is not set +# CONFIG_VMEM_ALLOC_TEST is not set +# CONFIG_DEBUG_KERNEL_PAGE_FAULTS is not set +# CONFIG_WARN_NONE is not set +CONFIG_WARN_WARNING=y +# CONFIG_WARN_ANY is not set + +# +# Compiling +# +CONFIG_CC="gcc" +CONFIG_CXX="g++" +CONFIG_HOST_CC="gcc" +CONFIG_HOST_CXX="g++" +# CONFIG_MAINTAINER_MODE is not set +CONFIG_LABEL="" +# CONFIG_EXPERIMENTAL is not set +CONFIG_PERF_CNT=y +CONFIG_BIT32=y +CONFIG_WARN_LEVEL=1 +CONFIG_XARCH="arm" +CONFIG_ABI="vf" diff --git a/kernel/fiasco/src/templates/globalconfig.out.arm-int-2 b/kernel/fiasco/src/templates/globalconfig.out.arm-int-2 new file mode 100644 index 00000000..3795bb19 --- /dev/null +++ b/kernel/fiasco/src/templates/globalconfig.out.arm-int-2 @@ -0,0 +1,71 @@ +# +# Automatically generated file; DO NOT EDIT. + +# +# Target configuration +# +# CONFIG_IA32 is not set +# CONFIG_AMD64 is not set +CONFIG_ARM=y +# CONFIG_PF_REALVIEW is not set +# CONFIG_PF_IMX is not set +# CONFIG_PF_S3C2410 is not set +# CONFIG_PF_TEGRA2 is not set +# CONFIG_PF_OMAP is not set +# CONFIG_PF_XSCALE is not set +# CONFIG_PF_SA1100 is not set +# CONFIG_PF_KIRKWOOD is not set +CONFIG_PF_INTEGRATOR=y +CONFIG_BSP_NAME="integrator" +CONFIG_ABI_VF=y +CONFIG_CAN_ARM_CPU_926=y +CONFIG_CAN_ARM_CPU_1176=y +# CONFIG_ARM_926 is not set +CONFIG_ARM_1176=y +# CONFIG_ARM_ALIGNMENT_CHECK is not set +# CONFIG_FPU is not set +# CONFIG_ARM_1176_CACHE_ALIAS_FIX is not set + +# +# Kernel options +# +CONFIG_CONTEXT_4K=y +# CONFIG_FINE_GRAINED_CPUTIME is not set +CONFIG_SCHED_FIXED_PRIO=y + +# +# Debugging +# +CONFIG_INLINE=y +# CONFIG_NDEBUG is not set +CONFIG_NO_FRAME_PTR=y +# CONFIG_STACK_DEPTH is not set +# CONFIG_LIST_ALLOC_SANITY is not set +CONFIG_SERIAL=y +CONFIG_JDB=y +CONFIG_JDB_LOGGING=y +# CONFIG_JDB_DISASM is not set +# CONFIG_JDB_GZIP is not set +# CONFIG_VMEM_ALLOC_TEST is not set +# CONFIG_DEBUG_KERNEL_PAGE_FAULTS is not set +# CONFIG_WARN_NONE is not set +CONFIG_WARN_WARNING=y +# CONFIG_WARN_ANY is not set + +# +# Compiling +# +CONFIG_CC="gcc" +CONFIG_CXX="g++" +CONFIG_HOST_CC="gcc" +CONFIG_HOST_CXX="g++" +# CONFIG_MAINTAINER_MODE is not set +CONFIG_LABEL="" +# CONFIG_EXPERIMENTAL is not set +CONFIG_PERF_CNT=y +CONFIG_BIT32=y +CONFIG_ARM_V6=y +CONFIG_ARM_V6PLUS=y +CONFIG_WARN_LEVEL=1 +CONFIG_XARCH="arm" +CONFIG_ABI="vf" diff --git a/kernel/fiasco/src/templates/globalconfig.out.arm-kirkwood b/kernel/fiasco/src/templates/globalconfig.out.arm-kirkwood new file mode 100644 index 00000000..955bc10f --- /dev/null +++ b/kernel/fiasco/src/templates/globalconfig.out.arm-kirkwood @@ -0,0 +1,66 @@ +# +# Automatically generated file; DO NOT EDIT. + +# +# Target configuration +# +# CONFIG_IA32 is not set +# CONFIG_AMD64 is not set +CONFIG_ARM=y +# CONFIG_PF_REALVIEW is not set +# CONFIG_PF_IMX is not set +# CONFIG_PF_S3C2410 is not set +# CONFIG_PF_TEGRA2 is not set +# CONFIG_PF_OMAP is not set +# CONFIG_PF_XSCALE is not set +# CONFIG_PF_SA1100 is not set +CONFIG_PF_KIRKWOOD=y +# CONFIG_PF_INTEGRATOR is not set +CONFIG_BSP_NAME="kirkwood" +CONFIG_ABI_VF=y +CONFIG_CAN_ARM_CPU_926=y +CONFIG_ARM_926=y +# CONFIG_ARM_ALIGNMENT_CHECK is not set +# CONFIG_FPU is not set + +# +# Kernel options +# +CONFIG_CONTEXT_4K=y +# CONFIG_FINE_GRAINED_CPUTIME is not set +CONFIG_SCHED_FIXED_PRIO=y + +# +# Debugging +# +CONFIG_INLINE=y +# CONFIG_NDEBUG is not set +# CONFIG_NO_FRAME_PTR is not set +# CONFIG_STACK_DEPTH is not set +# CONFIG_LIST_ALLOC_SANITY is not set +CONFIG_SERIAL=y +CONFIG_JDB=y +CONFIG_JDB_LOGGING=y +# CONFIG_JDB_DISASM is not set +# CONFIG_JDB_GZIP is not set +# CONFIG_VMEM_ALLOC_TEST is not set +# CONFIG_DEBUG_KERNEL_PAGE_FAULTS is not set +# CONFIG_WARN_NONE is not set +CONFIG_WARN_WARNING=y +# CONFIG_WARN_ANY is not set + +# +# Compiling +# +CONFIG_CC="gcc" +CONFIG_CXX="g++" +CONFIG_HOST_CC="gcc" +CONFIG_HOST_CXX="g++" +# CONFIG_MAINTAINER_MODE is not set +CONFIG_LABEL="" +# CONFIG_EXPERIMENTAL is not set +CONFIG_PERF_CNT=y +CONFIG_BIT32=y +CONFIG_WARN_LEVEL=1 +CONFIG_XARCH="arm" +CONFIG_ABI="vf" diff --git a/kernel/fiasco/src/templates/globalconfig.out.arm-omap3evm b/kernel/fiasco/src/templates/globalconfig.out.arm-omap3evm new file mode 100644 index 00000000..04838ef3 --- /dev/null +++ b/kernel/fiasco/src/templates/globalconfig.out.arm-omap3evm @@ -0,0 +1,72 @@ +# +# Automatically generated file; DO NOT EDIT. + +# +# Target configuration +# +# CONFIG_IA32 is not set +# CONFIG_AMD64 is not set +CONFIG_ARM=y +# CONFIG_PF_REALVIEW is not set +# CONFIG_PF_IMX is not set +# CONFIG_PF_S3C2410 is not set +# CONFIG_PF_TEGRA2 is not set +CONFIG_PF_OMAP=y +# CONFIG_PF_XSCALE is not set +# CONFIG_PF_SA1100 is not set +# CONFIG_PF_KIRKWOOD is not set +# CONFIG_PF_INTEGRATOR is not set +CONFIG_BSP_NAME="omap3" +CONFIG_PF_OMAP3_OMAP35XEVM=y +# CONFIG_PF_OMAP3_BEAGLEBOARD is not set +# CONFIG_PF_OMAP3_AM33XX is not set +# CONFIG_PF_OMAP4_PANDABOARD is not set +CONFIG_ABI_VF=y +CONFIG_CAN_ARM_CPU_CORTEX_A8=y +CONFIG_ARM_CORTEX_A8=y +# CONFIG_ARM_ALIGNMENT_CHECK is not set +CONFIG_FPU=y + +# +# Kernel options +# +CONFIG_CONTEXT_4K=y +# CONFIG_FINE_GRAINED_CPUTIME is not set +CONFIG_SCHED_FIXED_PRIO=y + +# +# Debugging +# +CONFIG_INLINE=y +# CONFIG_NDEBUG is not set +# CONFIG_NO_FRAME_PTR is not set +# CONFIG_STACK_DEPTH is not set +# CONFIG_LIST_ALLOC_SANITY is not set +CONFIG_SERIAL=y +CONFIG_JDB=y +# CONFIG_JDB_LOGGING is not set +# CONFIG_JDB_DISASM is not set +# CONFIG_JDB_GZIP is not set +# CONFIG_VMEM_ALLOC_TEST is not set +# CONFIG_DEBUG_KERNEL_PAGE_FAULTS is not set +# CONFIG_WARN_NONE is not set +CONFIG_WARN_WARNING=y +# CONFIG_WARN_ANY is not set + +# +# Compiling +# +CONFIG_CC="gcc" +CONFIG_CXX="g++" +CONFIG_HOST_CC="gcc" +CONFIG_HOST_CXX="g++" +# CONFIG_MAINTAINER_MODE is not set +CONFIG_LABEL="" +# CONFIG_EXPERIMENTAL is not set +CONFIG_PERF_CNT=y +CONFIG_BIT32=y +CONFIG_ARM_V7=y +CONFIG_ARM_V6PLUS=y +CONFIG_WARN_LEVEL=1 +CONFIG_XARCH="arm" +CONFIG_ABI="vf" diff --git a/kernel/fiasco/src/templates/globalconfig.out.arm-omap4-panda b/kernel/fiasco/src/templates/globalconfig.out.arm-omap4-panda new file mode 100644 index 00000000..24de3954 --- /dev/null +++ b/kernel/fiasco/src/templates/globalconfig.out.arm-omap4-panda @@ -0,0 +1,80 @@ +# +# Automatically generated file; DO NOT EDIT. + +# +# Target configuration +# +# CONFIG_IA32 is not set +# CONFIG_AMD64 is not set +CONFIG_ARM=y +# CONFIG_PF_REALVIEW is not set +# CONFIG_PF_IMX is not set +# CONFIG_PF_S3C2410 is not set +# CONFIG_PF_TEGRA2 is not set +CONFIG_PF_OMAP=y +# CONFIG_PF_XSCALE is not set +# CONFIG_PF_SA1100 is not set +# CONFIG_PF_KIRKWOOD is not set +# CONFIG_PF_INTEGRATOR is not set +CONFIG_BSP_NAME="omap3" +# CONFIG_PF_OMAP3_OMAP35XEVM is not set +# CONFIG_PF_OMAP3_BEAGLEBOARD is not set +# CONFIG_PF_OMAP3_AM33XX is not set +CONFIG_PF_OMAP4_PANDABOARD=y +CONFIG_ABI_VF=y +CONFIG_PF_ARM_MP_CAPABLE=y +CONFIG_CAN_ARM_CPU_CORTEX_A9=y +CONFIG_ARM_CORTEX_A9=y +CONFIG_ARM_ALIGNMENT_CHECK=y +# CONFIG_ARM_TZ is not set +CONFIG_ARM_CA9_ENABLE_SWP=y +CONFIG_FPU=y + +# +# Kernel options +# +CONFIG_MP=y +CONFIG_MP_MAX_CPUS=4 +CONFIG_CONTEXT_4K=y +# CONFIG_FINE_GRAINED_CPUTIME is not set +CONFIG_SCHED_FIXED_PRIO=y +# CONFIG_SCHED_WFQ is not set +# CONFIG_SCHED_FP_WFQ is not set +# CONFIG_DISABLE_VIRT_OBJ_SPACE is not set + +# +# Debugging +# +CONFIG_INLINE=y +# CONFIG_NDEBUG is not set +# CONFIG_NO_FRAME_PTR is not set +# CONFIG_STACK_DEPTH is not set +# CONFIG_LIST_ALLOC_SANITY is not set +CONFIG_SERIAL=y +CONFIG_JDB=y +CONFIG_JDB_LOGGING=y +# CONFIG_JDB_DISASM is not set +# CONFIG_JDB_GZIP is not set +# CONFIG_VMEM_ALLOC_TEST is not set +# CONFIG_DEBUG_KERNEL_PAGE_FAULTS is not set +# CONFIG_WARN_NONE is not set +CONFIG_WARN_WARNING=y +# CONFIG_WARN_ANY is not set + +# +# Compiling +# +CONFIG_CC="gcc" +CONFIG_CXX="g++" +CONFIG_HOST_CC="gcc" +CONFIG_HOST_CXX="g++" +# CONFIG_MAINTAINER_MODE is not set +CONFIG_LABEL="" +CONFIG_EXPERIMENTAL=y +CONFIG_PERF_CNT=y +CONFIG_BIT32=y +CONFIG_ARM_V7=y +CONFIG_ARM_V6PLUS=y +CONFIG_WARN_LEVEL=1 +CONFIG_XARCH="arm" +CONFIG_ABI="vf" diff --git a/kernel/fiasco/src/templates/globalconfig.out.arm-pxa b/kernel/fiasco/src/templates/globalconfig.out.arm-pxa new file mode 100644 index 00000000..6dfea579 --- /dev/null +++ b/kernel/fiasco/src/templates/globalconfig.out.arm-pxa @@ -0,0 +1,66 @@ +# +# Automatically generated file; DO NOT EDIT. + +# +# Target configuration +# +# CONFIG_IA32 is not set +# CONFIG_AMD64 is not set +CONFIG_ARM=y +# CONFIG_PF_REALVIEW is not set +# CONFIG_PF_IMX is not set +# CONFIG_PF_S3C2410 is not set +# CONFIG_PF_TEGRA2 is not set +# CONFIG_PF_OMAP is not set +CONFIG_PF_XSCALE=y +# CONFIG_PF_SA1100 is not set +# CONFIG_PF_KIRKWOOD is not set +# CONFIG_PF_INTEGRATOR is not set +CONFIG_BSP_NAME="pxa" +CONFIG_ABI_VF=y +CONFIG_CAN_ARM_CPU_XSCALE=y +CONFIG_ARM_PXA=y +# CONFIG_ARM_ALIGNMENT_CHECK is not set +# CONFIG_FPU is not set + +# +# Kernel options +# +CONFIG_CONTEXT_4K=y +# CONFIG_FINE_GRAINED_CPUTIME is not set +CONFIG_SCHED_FIXED_PRIO=y + +# +# Debugging +# +CONFIG_INLINE=y +# CONFIG_NDEBUG is not set +CONFIG_NO_FRAME_PTR=y +# CONFIG_STACK_DEPTH is not set +# CONFIG_LIST_ALLOC_SANITY is not set +CONFIG_SERIAL=y +CONFIG_JDB=y +CONFIG_JDB_LOGGING=y +# CONFIG_JDB_DISASM is not set +# CONFIG_JDB_GZIP is not set +# CONFIG_VMEM_ALLOC_TEST is not set +# CONFIG_DEBUG_KERNEL_PAGE_FAULTS is not set +# CONFIG_WARN_NONE is not set +CONFIG_WARN_WARNING=y +# CONFIG_WARN_ANY is not set + +# +# Compiling +# +CONFIG_CC="gcc" +CONFIG_CXX="g++" +CONFIG_HOST_CC="gcc" +CONFIG_HOST_CXX="g++" +# CONFIG_MAINTAINER_MODE is not set +CONFIG_LABEL="" +# CONFIG_EXPERIMENTAL is not set +CONFIG_PERF_CNT=y +CONFIG_BIT32=y +CONFIG_WARN_LEVEL=1 +CONFIG_XARCH="arm" +CONFIG_ABI="vf" diff --git a/kernel/fiasco/src/templates/globalconfig.out.arm-rv-1 b/kernel/fiasco/src/templates/globalconfig.out.arm-rv-1 new file mode 100644 index 00000000..8dc2824e --- /dev/null +++ b/kernel/fiasco/src/templates/globalconfig.out.arm-rv-1 @@ -0,0 +1,79 @@ +# +# Automatically generated file; DO NOT EDIT. + +# +# Target configuration +# +# CONFIG_IA32 is not set +# CONFIG_AMD64 is not set +CONFIG_ARM=y +CONFIG_PF_REALVIEW=y +# CONFIG_PF_IMX is not set +# CONFIG_PF_S3C2410 is not set +# CONFIG_PF_TEGRA2 is not set +# CONFIG_PF_OMAP is not set +# CONFIG_PF_XSCALE is not set +# CONFIG_PF_SA1100 is not set +# CONFIG_PF_KIRKWOOD is not set +# CONFIG_PF_INTEGRATOR is not set +CONFIG_BSP_NAME="realview" +CONFIG_PF_REALVIEW_EB=y +# CONFIG_PF_REALVIEW_PB11MP is not set +# CONFIG_PF_REALVIEW_PBX is not set +# CONFIG_PF_REALVIEW_VEXPRESS is not set +CONFIG_PF_REALVIEW_RAM_PHYS_BASE=0x0 +CONFIG_ABI_VF=y +CONFIG_CAN_ARM_CPU_926=y +CONFIG_CAN_ARM_CPU_1176=y +CONFIG_CAN_ARM_CPU_MPCORE=y +CONFIG_CAN_ARM_CPU_CORTEX_A8=y +CONFIG_CAN_ARM_CPU_CORTEX_A9=y +CONFIG_ARM_926=y +# CONFIG_ARM_1176 is not set +# CONFIG_ARM_MPCORE is not set +# CONFIG_ARM_CORTEX_A8 is not set +# CONFIG_ARM_CORTEX_A9 is not set +# CONFIG_ARM_ALIGNMENT_CHECK is not set +# CONFIG_FPU is not set + +# +# Kernel options +# +CONFIG_CONTEXT_4K=y +# CONFIG_FINE_GRAINED_CPUTIME is not set +CONFIG_SCHED_FIXED_PRIO=y + +# +# Debugging +# +CONFIG_INLINE=y +# CONFIG_NDEBUG is not set +CONFIG_NO_FRAME_PTR=y +# CONFIG_STACK_DEPTH is not set +# CONFIG_LIST_ALLOC_SANITY is not set +CONFIG_SERIAL=y +CONFIG_JDB=y +CONFIG_JDB_LOGGING=y +# CONFIG_JDB_DISASM is not set +# CONFIG_JDB_GZIP is not set +# CONFIG_VMEM_ALLOC_TEST is not set +# CONFIG_DEBUG_KERNEL_PAGE_FAULTS is not set +# CONFIG_WARN_NONE is not set +CONFIG_WARN_WARNING=y +# CONFIG_WARN_ANY is not set + +# +# Compiling +# +CONFIG_CC="gcc" +CONFIG_CXX="g++" +CONFIG_HOST_CC="gcc" +CONFIG_HOST_CXX="g++" +# CONFIG_MAINTAINER_MODE is not set +CONFIG_LABEL="" +# CONFIG_EXPERIMENTAL is not set +CONFIG_PERF_CNT=y +CONFIG_BIT32=y +CONFIG_WARN_LEVEL=1 +CONFIG_XARCH="arm" +CONFIG_ABI="vf" diff --git a/kernel/fiasco/src/templates/globalconfig.out.arm-rv-2 b/kernel/fiasco/src/templates/globalconfig.out.arm-rv-2 new file mode 100644 index 00000000..7b9bd020 --- /dev/null +++ b/kernel/fiasco/src/templates/globalconfig.out.arm-rv-2 @@ -0,0 +1,82 @@ +# +# Automatically generated file; DO NOT EDIT. + +# +# Target configuration +# +# CONFIG_IA32 is not set +# CONFIG_AMD64 is not set +CONFIG_ARM=y +CONFIG_PF_REALVIEW=y +# CONFIG_PF_IMX is not set +# CONFIG_PF_S3C2410 is not set +# CONFIG_PF_TEGRA2 is not set +# CONFIG_PF_OMAP is not set +# CONFIG_PF_XSCALE is not set +# CONFIG_PF_SA1100 is not set +# CONFIG_PF_KIRKWOOD is not set +# CONFIG_PF_INTEGRATOR is not set +CONFIG_BSP_NAME="realview" +CONFIG_PF_REALVIEW_EB=y +# CONFIG_PF_REALVIEW_PB11MP is not set +# CONFIG_PF_REALVIEW_PBX is not set +# CONFIG_PF_REALVIEW_VEXPRESS is not set +CONFIG_PF_REALVIEW_RAM_PHYS_BASE=0x0 +CONFIG_ABI_VF=y +CONFIG_CAN_ARM_CPU_926=y +CONFIG_CAN_ARM_CPU_1176=y +CONFIG_CAN_ARM_CPU_MPCORE=y +CONFIG_CAN_ARM_CPU_CORTEX_A8=y +CONFIG_CAN_ARM_CPU_CORTEX_A9=y +# CONFIG_ARM_926 is not set +CONFIG_ARM_1176=y +# CONFIG_ARM_MPCORE is not set +# CONFIG_ARM_CORTEX_A8 is not set +# CONFIG_ARM_CORTEX_A9 is not set +# CONFIG_ARM_ALIGNMENT_CHECK is not set +# CONFIG_FPU is not set +CONFIG_ARM_1176_CACHE_ALIAS_FIX=y + +# +# Kernel options +# +CONFIG_CONTEXT_4K=y +# CONFIG_FINE_GRAINED_CPUTIME is not set +CONFIG_SCHED_FIXED_PRIO=y + +# +# Debugging +# +CONFIG_INLINE=y +# CONFIG_NDEBUG is not set +CONFIG_NO_FRAME_PTR=y +# CONFIG_STACK_DEPTH is not set +# CONFIG_LIST_ALLOC_SANITY is not set +CONFIG_SERIAL=y +CONFIG_JDB=y +CONFIG_JDB_LOGGING=y +# CONFIG_JDB_DISASM is not set +# CONFIG_JDB_GZIP is not set +# CONFIG_VMEM_ALLOC_TEST is not set +# CONFIG_DEBUG_KERNEL_PAGE_FAULTS is not set +# CONFIG_WARN_NONE is not set +CONFIG_WARN_WARNING=y +# CONFIG_WARN_ANY is not set + +# +# Compiling +# +CONFIG_CC="gcc" +CONFIG_CXX="g++" +CONFIG_HOST_CC="gcc" +CONFIG_HOST_CXX="g++" +# CONFIG_MAINTAINER_MODE is not set +CONFIG_LABEL="" +# CONFIG_EXPERIMENTAL is not set +CONFIG_PERF_CNT=y +CONFIG_BIT32=y +CONFIG_ARM_V6=y +CONFIG_ARM_V6PLUS=y +CONFIG_WARN_LEVEL=1 +CONFIG_XARCH="arm" +CONFIG_ABI="vf" diff --git a/kernel/fiasco/src/templates/globalconfig.out.arm-rv-3 b/kernel/fiasco/src/templates/globalconfig.out.arm-rv-3 new file mode 100644 index 00000000..16849619 --- /dev/null +++ b/kernel/fiasco/src/templates/globalconfig.out.arm-rv-3 @@ -0,0 +1,85 @@ +# +# Automatically generated file; DO NOT EDIT. + +# +# Target configuration +# +# CONFIG_IA32 is not set +# CONFIG_AMD64 is not set +CONFIG_ARM=y +CONFIG_PF_REALVIEW=y +# CONFIG_PF_IMX is not set +# CONFIG_PF_S3C2410 is not set +# CONFIG_PF_TEGRA2 is not set +# CONFIG_PF_OMAP is not set +# CONFIG_PF_XSCALE is not set +# CONFIG_PF_SA1100 is not set +# CONFIG_PF_KIRKWOOD is not set +# CONFIG_PF_INTEGRATOR is not set +CONFIG_BSP_NAME="realview" +CONFIG_PF_REALVIEW_EB=y +# CONFIG_PF_REALVIEW_PB11MP is not set +# CONFIG_PF_REALVIEW_PBX is not set +# CONFIG_PF_REALVIEW_VEXPRESS is not set +CONFIG_PF_REALVIEW_RAM_PHYS_BASE=0x0 +CONFIG_ABI_VF=y +CONFIG_PF_ARM_MP_CAPABLE=y +CONFIG_CAN_ARM_CPU_926=y +CONFIG_CAN_ARM_CPU_1176=y +CONFIG_CAN_ARM_CPU_MPCORE=y +CONFIG_CAN_ARM_CPU_CORTEX_A8=y +CONFIG_CAN_ARM_CPU_CORTEX_A9=y +CONFIG_CAN_ARM_CACHE_L2CXX0=y +# CONFIG_ARM_926 is not set +# CONFIG_ARM_1176 is not set +CONFIG_ARM_MPCORE=y +# CONFIG_ARM_CORTEX_A8 is not set +# CONFIG_ARM_CORTEX_A9 is not set +# CONFIG_ARM_ALIGNMENT_CHECK is not set +CONFIG_ARM_CACHE_L2CXX0=y +# CONFIG_FPU is not set + +# +# Kernel options +# +# CONFIG_MP is not set +CONFIG_CONTEXT_4K=y +# CONFIG_FINE_GRAINED_CPUTIME is not set +CONFIG_SCHED_FIXED_PRIO=y + +# +# Debugging +# +CONFIG_INLINE=y +# CONFIG_NDEBUG is not set +CONFIG_NO_FRAME_PTR=y +# CONFIG_STACK_DEPTH is not set +# CONFIG_LIST_ALLOC_SANITY is not set +CONFIG_SERIAL=y +CONFIG_JDB=y +CONFIG_JDB_LOGGING=y +# CONFIG_JDB_DISASM is not set +# CONFIG_JDB_GZIP is not set +# CONFIG_VMEM_ALLOC_TEST is not set +# CONFIG_DEBUG_KERNEL_PAGE_FAULTS is not set +# CONFIG_WARN_NONE is not set +CONFIG_WARN_WARNING=y +# CONFIG_WARN_ANY is not set + +# +# Compiling +# +CONFIG_CC="gcc" +CONFIG_CXX="g++" +CONFIG_HOST_CC="gcc" +CONFIG_HOST_CXX="g++" +# CONFIG_MAINTAINER_MODE is not set +CONFIG_LABEL="" +# CONFIG_EXPERIMENTAL is not set +CONFIG_PERF_CNT=y +CONFIG_BIT32=y +CONFIG_ARM_V6=y +CONFIG_ARM_V6PLUS=y +CONFIG_WARN_LEVEL=1 +CONFIG_XARCH="arm" +CONFIG_ABI="vf" diff --git a/kernel/fiasco/src/templates/globalconfig.out.arm-rv-4-noinl b/kernel/fiasco/src/templates/globalconfig.out.arm-rv-4-noinl new file mode 100644 index 00000000..1a819884 --- /dev/null +++ b/kernel/fiasco/src/templates/globalconfig.out.arm-rv-4-noinl @@ -0,0 +1,79 @@ +# +# Automatically generated file; DO NOT EDIT. + +# +# Target configuration +# +# CONFIG_IA32 is not set +# CONFIG_AMD64 is not set +CONFIG_ARM=y +CONFIG_PF_REALVIEW=y +# CONFIG_PF_IMX is not set +# CONFIG_PF_S3C2410 is not set +# CONFIG_PF_TEGRA2 is not set +# CONFIG_PF_OMAP is not set +# CONFIG_PF_XSCALE is not set +# CONFIG_PF_SA1100 is not set +# CONFIG_PF_KIRKWOOD is not set +# CONFIG_PF_INTEGRATOR is not set +CONFIG_BSP_NAME="realview" +CONFIG_PF_REALVIEW_EB=y +# CONFIG_PF_REALVIEW_PB11MP is not set +# CONFIG_PF_REALVIEW_PBX is not set +# CONFIG_PF_REALVIEW_VEXPRESS is not set +CONFIG_PF_REALVIEW_RAM_PHYS_BASE=0x0 +CONFIG_ABI_VF=y +CONFIG_CAN_ARM_CPU_926=y +CONFIG_CAN_ARM_CPU_1176=y +CONFIG_CAN_ARM_CPU_MPCORE=y +CONFIG_CAN_ARM_CPU_CORTEX_A8=y +CONFIG_CAN_ARM_CPU_CORTEX_A9=y +CONFIG_ARM_926=y +# CONFIG_ARM_1176 is not set +# CONFIG_ARM_MPCORE is not set +# CONFIG_ARM_CORTEX_A8 is not set +# CONFIG_ARM_CORTEX_A9 is not set +# CONFIG_ARM_ALIGNMENT_CHECK is not set +# CONFIG_FPU is not set + +# +# Kernel options +# +CONFIG_CONTEXT_4K=y +# CONFIG_FINE_GRAINED_CPUTIME is not set +CONFIG_SCHED_FIXED_PRIO=y + +# +# Debugging +# +# CONFIG_INLINE is not set +# CONFIG_NDEBUG is not set +CONFIG_NO_FRAME_PTR=y +# CONFIG_STACK_DEPTH is not set +# CONFIG_LIST_ALLOC_SANITY is not set +CONFIG_SERIAL=y +CONFIG_JDB=y +CONFIG_JDB_LOGGING=y +# CONFIG_JDB_DISASM is not set +# CONFIG_JDB_GZIP is not set +# CONFIG_VMEM_ALLOC_TEST is not set +# CONFIG_DEBUG_KERNEL_PAGE_FAULTS is not set +# CONFIG_WARN_NONE is not set +CONFIG_WARN_WARNING=y +# CONFIG_WARN_ANY is not set + +# +# Compiling +# +CONFIG_CC="gcc" +CONFIG_CXX="g++" +CONFIG_HOST_CC="gcc" +CONFIG_HOST_CXX="g++" +# CONFIG_MAINTAINER_MODE is not set +CONFIG_LABEL="" +# CONFIG_EXPERIMENTAL is not set +CONFIG_PERF_CNT=y +CONFIG_BIT32=y +CONFIG_WARN_LEVEL=1 +CONFIG_XARCH="arm" +CONFIG_ABI="vf" diff --git a/kernel/fiasco/src/templates/globalconfig.out.arm-s3c b/kernel/fiasco/src/templates/globalconfig.out.arm-s3c new file mode 100644 index 00000000..c73180fa --- /dev/null +++ b/kernel/fiasco/src/templates/globalconfig.out.arm-s3c @@ -0,0 +1,66 @@ +# +# Automatically generated file; DO NOT EDIT. + +# +# Target configuration +# +# CONFIG_IA32 is not set +# CONFIG_AMD64 is not set +CONFIG_ARM=y +# CONFIG_PF_REALVIEW is not set +# CONFIG_PF_IMX is not set +CONFIG_PF_S3C2410=y +# CONFIG_PF_TEGRA2 is not set +# CONFIG_PF_OMAP is not set +# CONFIG_PF_XSCALE is not set +# CONFIG_PF_SA1100 is not set +# CONFIG_PF_KIRKWOOD is not set +# CONFIG_PF_INTEGRATOR is not set +CONFIG_BSP_NAME="s3c" +CONFIG_ABI_VF=y +CONFIG_CAN_ARM_CPU_920T=y +CONFIG_ARM_920T=y +# CONFIG_ARM_ALIGNMENT_CHECK is not set +# CONFIG_FPU is not set + +# +# Kernel options +# +CONFIG_CONTEXT_4K=y +# CONFIG_FINE_GRAINED_CPUTIME is not set +CONFIG_SCHED_FIXED_PRIO=y + +# +# Debugging +# +CONFIG_INLINE=y +# CONFIG_NDEBUG is not set +CONFIG_NO_FRAME_PTR=y +# CONFIG_STACK_DEPTH is not set +# CONFIG_LIST_ALLOC_SANITY is not set +CONFIG_SERIAL=y +CONFIG_JDB=y +# CONFIG_JDB_LOGGING is not set +# CONFIG_JDB_DISASM is not set +# CONFIG_JDB_GZIP is not set +# CONFIG_VMEM_ALLOC_TEST is not set +# CONFIG_DEBUG_KERNEL_PAGE_FAULTS is not set +# CONFIG_WARN_NONE is not set +CONFIG_WARN_WARNING=y +# CONFIG_WARN_ANY is not set + +# +# Compiling +# +CONFIG_CC="gcc" +CONFIG_CXX="g++" +CONFIG_HOST_CC="gcc" +CONFIG_HOST_CXX="g++" +# CONFIG_MAINTAINER_MODE is not set +CONFIG_LABEL="" +# CONFIG_EXPERIMENTAL is not set +CONFIG_PERF_CNT=y +CONFIG_BIT32=y +CONFIG_WARN_LEVEL=1 +CONFIG_XARCH="arm" +CONFIG_ABI="vf" diff --git a/kernel/fiasco/src/templates/globalconfig.out.arm-sa b/kernel/fiasco/src/templates/globalconfig.out.arm-sa new file mode 100644 index 00000000..63807cb9 --- /dev/null +++ b/kernel/fiasco/src/templates/globalconfig.out.arm-sa @@ -0,0 +1,66 @@ +# +# Automatically generated file; DO NOT EDIT. + +# +# Target configuration +# +# CONFIG_IA32 is not set +# CONFIG_AMD64 is not set +CONFIG_ARM=y +# CONFIG_PF_REALVIEW is not set +# CONFIG_PF_IMX is not set +# CONFIG_PF_S3C2410 is not set +# CONFIG_PF_TEGRA2 is not set +# CONFIG_PF_OMAP is not set +# CONFIG_PF_XSCALE is not set +CONFIG_PF_SA1100=y +# CONFIG_PF_KIRKWOOD is not set +# CONFIG_PF_INTEGRATOR is not set +CONFIG_BSP_NAME="sa1100" +CONFIG_ABI_VF=y +CONFIG_CAN_ARM_CPU_SA1100=y +CONFIG_ARM_SA=y +# CONFIG_ARM_ALIGNMENT_CHECK is not set +# CONFIG_FPU is not set + +# +# Kernel options +# +CONFIG_CONTEXT_4K=y +# CONFIG_FINE_GRAINED_CPUTIME is not set +CONFIG_SCHED_FIXED_PRIO=y + +# +# Debugging +# +CONFIG_INLINE=y +# CONFIG_NDEBUG is not set +CONFIG_NO_FRAME_PTR=y +# CONFIG_STACK_DEPTH is not set +# CONFIG_LIST_ALLOC_SANITY is not set +CONFIG_SERIAL=y +CONFIG_JDB=y +CONFIG_JDB_LOGGING=y +# CONFIG_JDB_DISASM is not set +# CONFIG_JDB_GZIP is not set +# CONFIG_VMEM_ALLOC_TEST is not set +# CONFIG_DEBUG_KERNEL_PAGE_FAULTS is not set +# CONFIG_WARN_NONE is not set +CONFIG_WARN_WARNING=y +# CONFIG_WARN_ANY is not set + +# +# Compiling +# +CONFIG_CC="gcc" +CONFIG_CXX="g++" +CONFIG_HOST_CC="gcc" +CONFIG_HOST_CXX="g++" +# CONFIG_MAINTAINER_MODE is not set +CONFIG_LABEL="" +# CONFIG_EXPERIMENTAL is not set +CONFIG_PERF_CNT=y +CONFIG_BIT32=y +CONFIG_WARN_LEVEL=1 +CONFIG_XARCH="arm" +CONFIG_ABI="vf" diff --git a/kernel/fiasco/src/templates/globalconfig.out.arm-t2 b/kernel/fiasco/src/templates/globalconfig.out.arm-t2 new file mode 100644 index 00000000..d98456ff --- /dev/null +++ b/kernel/fiasco/src/templates/globalconfig.out.arm-t2 @@ -0,0 +1,78 @@ +# +# Automatically generated file; DO NOT EDIT. + +# +# Target configuration +# +# CONFIG_IA32 is not set +# CONFIG_AMD64 is not set +CONFIG_ARM=y +# CONFIG_PF_REALVIEW is not set +# CONFIG_PF_IMX is not set +# CONFIG_PF_S3C2410 is not set +CONFIG_PF_TEGRA2=y +# CONFIG_PF_OMAP is not set +# CONFIG_PF_XSCALE is not set +# CONFIG_PF_SA1100 is not set +# CONFIG_PF_KIRKWOOD is not set +# CONFIG_PF_INTEGRATOR is not set +CONFIG_BSP_NAME="tegra2" +CONFIG_ABI_VF=y +CONFIG_PF_ARM_MP_CAPABLE=y +CONFIG_CAN_ARM_CPU_CORTEX_A9=y +CONFIG_CAN_ARM_CACHE_L2CXX0=y +CONFIG_ARM_CORTEX_A9=y +CONFIG_ARM_ALIGNMENT_CHECK=y +CONFIG_ARM_TZ=y +CONFIG_ARM_CA9_ENABLE_SWP=y +CONFIG_ARM_CACHE_L2CXX0=y +CONFIG_FPU=y + +# +# Kernel options +# +CONFIG_MP=y +CONFIG_MP_MAX_CPUS=4 +CONFIG_CONTEXT_4K=y +CONFIG_FINE_GRAINED_CPUTIME=y +# CONFIG_SCHED_FIXED_PRIO is not set +# CONFIG_SCHED_WFQ is not set +CONFIG_SCHED_FP_WFQ=y +# CONFIG_DISABLE_VIRT_OBJ_SPACE is not set + +# +# Debugging +# +CONFIG_INLINE=y +# CONFIG_NDEBUG is not set +CONFIG_NO_FRAME_PTR=y +# CONFIG_STACK_DEPTH is not set +# CONFIG_LIST_ALLOC_SANITY is not set +CONFIG_SERIAL=y +CONFIG_JDB=y +CONFIG_JDB_LOGGING=y +# CONFIG_JDB_DISASM is not set +# CONFIG_JDB_GZIP is not set +# CONFIG_VMEM_ALLOC_TEST is not set +# CONFIG_DEBUG_KERNEL_PAGE_FAULTS is not set +# CONFIG_WARN_NONE is not set +# CONFIG_WARN_WARNING is not set +CONFIG_WARN_ANY=y + +# +# Compiling +# +CONFIG_CC="gcc" +CONFIG_CXX="g++" +CONFIG_HOST_CC="gcc" +CONFIG_HOST_CXX="g++" +# CONFIG_MAINTAINER_MODE is not set +CONFIG_LABEL="T2-mp" +CONFIG_EXPERIMENTAL=y +CONFIG_PERF_CNT=y +CONFIG_BIT32=y +CONFIG_ARM_V7=y +CONFIG_ARM_V6PLUS=y +CONFIG_WARN_LEVEL=2 +CONFIG_XARCH="arm" +CONFIG_ABI="vf" diff --git a/kernel/fiasco/src/templates/globalconfig.out.arm-v6 b/kernel/fiasco/src/templates/globalconfig.out.arm-v6 new file mode 100644 index 00000000..a552ab74 --- /dev/null +++ b/kernel/fiasco/src/templates/globalconfig.out.arm-v6 @@ -0,0 +1,82 @@ +# +# Automatically generated file; DO NOT EDIT. + +# +# Target configuration +# +# CONFIG_IA32 is not set +# CONFIG_AMD64 is not set +CONFIG_ARM=y +CONFIG_PF_REALVIEW=y +# CONFIG_PF_IMX is not set +# CONFIG_PF_S3C2410 is not set +# CONFIG_PF_TEGRA2 is not set +# CONFIG_PF_OMAP is not set +# CONFIG_PF_XSCALE is not set +# CONFIG_PF_SA1100 is not set +# CONFIG_PF_KIRKWOOD is not set +# CONFIG_PF_INTEGRATOR is not set +CONFIG_BSP_NAME="realview" +CONFIG_PF_REALVIEW_EB=y +# CONFIG_PF_REALVIEW_PB11MP is not set +# CONFIG_PF_REALVIEW_PBX is not set +# CONFIG_PF_REALVIEW_VEXPRESS is not set +CONFIG_PF_REALVIEW_RAM_PHYS_BASE=0x0 +CONFIG_ABI_VF=y +CONFIG_CAN_ARM_CPU_926=y +CONFIG_CAN_ARM_CPU_1176=y +CONFIG_CAN_ARM_CPU_MPCORE=y +CONFIG_CAN_ARM_CPU_CORTEX_A8=y +CONFIG_CAN_ARM_CPU_CORTEX_A9=y +# CONFIG_ARM_926 is not set +CONFIG_ARM_1176=y +# CONFIG_ARM_MPCORE is not set +# CONFIG_ARM_CORTEX_A8 is not set +# CONFIG_ARM_CORTEX_A9 is not set +# CONFIG_ARM_ALIGNMENT_CHECK is not set +# CONFIG_FPU is not set +CONFIG_ARM_1176_CACHE_ALIAS_FIX=y + +# +# Kernel options +# +CONFIG_CONTEXT_4K=y +# CONFIG_FINE_GRAINED_CPUTIME is not set +CONFIG_SCHED_FIXED_PRIO=y + +# +# Debugging +# +CONFIG_INLINE=y +# CONFIG_NDEBUG is not set +CONFIG_NO_FRAME_PTR=y +# CONFIG_STACK_DEPTH is not set +# CONFIG_LIST_ALLOC_SANITY is not set +CONFIG_SERIAL=y +CONFIG_JDB=y +# CONFIG_JDB_LOGGING is not set +# CONFIG_JDB_DISASM is not set +# CONFIG_JDB_GZIP is not set +# CONFIG_VMEM_ALLOC_TEST is not set +# CONFIG_DEBUG_KERNEL_PAGE_FAULTS is not set +# CONFIG_WARN_NONE is not set +CONFIG_WARN_WARNING=y +# CONFIG_WARN_ANY is not set + +# +# Compiling +# +CONFIG_CC="gcc" +CONFIG_CXX="g++" +CONFIG_HOST_CC="gcc" +CONFIG_HOST_CXX="g++" +# CONFIG_MAINTAINER_MODE is not set +CONFIG_LABEL="" +# CONFIG_EXPERIMENTAL is not set +CONFIG_PERF_CNT=y +CONFIG_BIT32=y +CONFIG_ARM_V6=y +CONFIG_ARM_V6PLUS=y +CONFIG_WARN_LEVEL=1 +CONFIG_XARCH="arm" +CONFIG_ABI="vf" diff --git a/kernel/fiasco/src/templates/globalconfig.out.arm-v6-mp-eb b/kernel/fiasco/src/templates/globalconfig.out.arm-v6-mp-eb new file mode 100644 index 00000000..775b1401 --- /dev/null +++ b/kernel/fiasco/src/templates/globalconfig.out.arm-v6-mp-eb @@ -0,0 +1,89 @@ +# +# Automatically generated file; DO NOT EDIT. + +# +# Target configuration +# +# CONFIG_IA32 is not set +# CONFIG_AMD64 is not set +CONFIG_ARM=y +CONFIG_PF_REALVIEW=y +# CONFIG_PF_IMX is not set +# CONFIG_PF_S3C2410 is not set +# CONFIG_PF_TEGRA2 is not set +# CONFIG_PF_OMAP is not set +# CONFIG_PF_XSCALE is not set +# CONFIG_PF_SA1100 is not set +# CONFIG_PF_KIRKWOOD is not set +# CONFIG_PF_INTEGRATOR is not set +CONFIG_BSP_NAME="realview" +CONFIG_PF_REALVIEW_EB=y +# CONFIG_PF_REALVIEW_PB11MP is not set +# CONFIG_PF_REALVIEW_PBX is not set +# CONFIG_PF_REALVIEW_VEXPRESS is not set +CONFIG_PF_REALVIEW_RAM_PHYS_BASE=0x0 +CONFIG_ABI_VF=y +CONFIG_PF_ARM_MP_CAPABLE=y +CONFIG_CAN_ARM_CPU_926=y +CONFIG_CAN_ARM_CPU_1176=y +CONFIG_CAN_ARM_CPU_MPCORE=y +CONFIG_CAN_ARM_CPU_CORTEX_A8=y +CONFIG_CAN_ARM_CPU_CORTEX_A9=y +CONFIG_CAN_ARM_CACHE_L2CXX0=y +# CONFIG_ARM_926 is not set +# CONFIG_ARM_1176 is not set +CONFIG_ARM_MPCORE=y +# CONFIG_ARM_CORTEX_A8 is not set +# CONFIG_ARM_CORTEX_A9 is not set +# CONFIG_ARM_ALIGNMENT_CHECK is not set +CONFIG_ARM_CACHE_L2CXX0=y +CONFIG_FPU=y + +# +# Kernel options +# +CONFIG_MP=y +CONFIG_MP_MAX_CPUS=4 +CONFIG_CONTEXT_4K=y +CONFIG_FINE_GRAINED_CPUTIME=y +CONFIG_SCHED_FIXED_PRIO=y +# CONFIG_SCHED_WFQ is not set +# CONFIG_SCHED_FP_WFQ is not set +# CONFIG_DISABLE_VIRT_OBJ_SPACE is not set + +# +# Debugging +# +CONFIG_INLINE=y +# CONFIG_NDEBUG is not set +CONFIG_NO_FRAME_PTR=y +# CONFIG_STACK_DEPTH is not set +# CONFIG_LIST_ALLOC_SANITY is not set +CONFIG_SERIAL=y +CONFIG_JDB=y +CONFIG_JDB_LOGGING=y +# CONFIG_JDB_DISASM is not set +# CONFIG_JDB_GZIP is not set +# CONFIG_VMEM_ALLOC_TEST is not set +# CONFIG_DEBUG_KERNEL_PAGE_FAULTS is not set +# CONFIG_WARN_NONE is not set +# CONFIG_WARN_WARNING is not set +CONFIG_WARN_ANY=y + +# +# Compiling +# +CONFIG_CC="gcc" +CONFIG_CXX="g++" +CONFIG_HOST_CC="gcc" +CONFIG_HOST_CXX="g++" +# CONFIG_MAINTAINER_MODE is not set +CONFIG_LABEL="" +CONFIG_EXPERIMENTAL=y +CONFIG_PERF_CNT=y +CONFIG_BIT32=y +CONFIG_ARM_V6=y +CONFIG_ARM_V6PLUS=y +CONFIG_WARN_LEVEL=2 +CONFIG_XARCH="arm" +CONFIG_ABI="vf" diff --git a/kernel/fiasco/src/templates/globalconfig.out.arm-v6-mp-pb b/kernel/fiasco/src/templates/globalconfig.out.arm-v6-mp-pb new file mode 100644 index 00000000..18efa495 --- /dev/null +++ b/kernel/fiasco/src/templates/globalconfig.out.arm-v6-mp-pb @@ -0,0 +1,83 @@ +# +# Automatically generated file; DO NOT EDIT. + +# +# Target configuration +# +# CONFIG_IA32 is not set +# CONFIG_AMD64 is not set +CONFIG_ARM=y +CONFIG_PF_REALVIEW=y +# CONFIG_PF_IMX is not set +# CONFIG_PF_S3C2410 is not set +# CONFIG_PF_TEGRA2 is not set +# CONFIG_PF_OMAP is not set +# CONFIG_PF_XSCALE is not set +# CONFIG_PF_SA1100 is not set +# CONFIG_PF_KIRKWOOD is not set +# CONFIG_PF_INTEGRATOR is not set +CONFIG_BSP_NAME="realview" +# CONFIG_PF_REALVIEW_EB is not set +CONFIG_PF_REALVIEW_PB11MP=y +# CONFIG_PF_REALVIEW_PBX is not set +# CONFIG_PF_REALVIEW_VEXPRESS is not set +CONFIG_PF_REALVIEW_RAM_PHYS_BASE_0x0=y +# CONFIG_PF_REALVIEW_RAM_PHYS_BASE_0x7 is not set +CONFIG_PF_REALVIEW_RAM_PHYS_BASE=0x0 +CONFIG_ABI_VF=y +CONFIG_PF_ARM_MP_CAPABLE=y +CONFIG_CAN_ARM_CPU_MPCORE=y +CONFIG_CAN_ARM_CACHE_L2CXX0=y +CONFIG_ARM_MPCORE=y +# CONFIG_ARM_ALIGNMENT_CHECK is not set +CONFIG_ARM_CACHE_L2CXX0=y +CONFIG_FPU=y + +# +# Kernel options +# +CONFIG_MP=y +CONFIG_MP_MAX_CPUS=4 +CONFIG_CONTEXT_4K=y +CONFIG_FINE_GRAINED_CPUTIME=y +# CONFIG_SCHED_FIXED_PRIO is not set +# CONFIG_SCHED_WFQ is not set +CONFIG_SCHED_FP_WFQ=y +# CONFIG_DISABLE_VIRT_OBJ_SPACE is not set + +# +# Debugging +# +CONFIG_INLINE=y +# CONFIG_NDEBUG is not set +CONFIG_NO_FRAME_PTR=y +# CONFIG_STACK_DEPTH is not set +# CONFIG_LIST_ALLOC_SANITY is not set +CONFIG_SERIAL=y +CONFIG_JDB=y +CONFIG_JDB_LOGGING=y +# CONFIG_JDB_DISASM is not set +# CONFIG_JDB_GZIP is not set +# CONFIG_VMEM_ALLOC_TEST is not set +# CONFIG_DEBUG_KERNEL_PAGE_FAULTS is not set +# CONFIG_WARN_NONE is not set +# CONFIG_WARN_WARNING is not set +CONFIG_WARN_ANY=y + +# +# Compiling +# +CONFIG_CC="gcc" +CONFIG_CXX="g++" +CONFIG_HOST_CC="gcc" +CONFIG_HOST_CXX="g++" +# CONFIG_MAINTAINER_MODE is not set +CONFIG_LABEL="pb11mp-mp" +CONFIG_EXPERIMENTAL=y +CONFIG_PERF_CNT=y +CONFIG_BIT32=y +CONFIG_ARM_V6=y +CONFIG_ARM_V6PLUS=y +CONFIG_WARN_LEVEL=2 +CONFIG_XARCH="arm" +CONFIG_ABI="vf" diff --git a/kernel/fiasco/src/templates/globalconfig.out.arm-v7 b/kernel/fiasco/src/templates/globalconfig.out.arm-v7 new file mode 100644 index 00000000..e8c27d09 --- /dev/null +++ b/kernel/fiasco/src/templates/globalconfig.out.arm-v7 @@ -0,0 +1,81 @@ +# +# Automatically generated file; DO NOT EDIT. + +# +# Target configuration +# +# CONFIG_IA32 is not set +# CONFIG_AMD64 is not set +CONFIG_ARM=y +CONFIG_PF_REALVIEW=y +# CONFIG_PF_IMX is not set +# CONFIG_PF_S3C2410 is not set +# CONFIG_PF_TEGRA2 is not set +# CONFIG_PF_OMAP is not set +# CONFIG_PF_XSCALE is not set +# CONFIG_PF_SA1100 is not set +# CONFIG_PF_KIRKWOOD is not set +# CONFIG_PF_INTEGRATOR is not set +CONFIG_BSP_NAME="realview" +CONFIG_PF_REALVIEW_EB=y +# CONFIG_PF_REALVIEW_PB11MP is not set +# CONFIG_PF_REALVIEW_PBX is not set +# CONFIG_PF_REALVIEW_VEXPRESS is not set +CONFIG_PF_REALVIEW_RAM_PHYS_BASE=0x0 +CONFIG_ABI_VF=y +CONFIG_CAN_ARM_CPU_926=y +CONFIG_CAN_ARM_CPU_1176=y +CONFIG_CAN_ARM_CPU_MPCORE=y +CONFIG_CAN_ARM_CPU_CORTEX_A8=y +CONFIG_CAN_ARM_CPU_CORTEX_A9=y +# CONFIG_ARM_926 is not set +# CONFIG_ARM_1176 is not set +# CONFIG_ARM_MPCORE is not set +CONFIG_ARM_CORTEX_A8=y +# CONFIG_ARM_CORTEX_A9 is not set +# CONFIG_ARM_ALIGNMENT_CHECK is not set +# CONFIG_FPU is not set + +# +# Kernel options +# +CONFIG_CONTEXT_4K=y +# CONFIG_FINE_GRAINED_CPUTIME is not set +CONFIG_SCHED_FIXED_PRIO=y + +# +# Debugging +# +CONFIG_INLINE=y +# CONFIG_NDEBUG is not set +CONFIG_NO_FRAME_PTR=y +# CONFIG_STACK_DEPTH is not set +# CONFIG_LIST_ALLOC_SANITY is not set +CONFIG_SERIAL=y +CONFIG_JDB=y +CONFIG_JDB_LOGGING=y +# CONFIG_JDB_DISASM is not set +# CONFIG_JDB_GZIP is not set +# CONFIG_VMEM_ALLOC_TEST is not set +# CONFIG_DEBUG_KERNEL_PAGE_FAULTS is not set +# CONFIG_WARN_NONE is not set +CONFIG_WARN_WARNING=y +# CONFIG_WARN_ANY is not set + +# +# Compiling +# +CONFIG_CC="gcc" +CONFIG_CXX="g++" +CONFIG_HOST_CC="gcc" +CONFIG_HOST_CXX="g++" +# CONFIG_MAINTAINER_MODE is not set +CONFIG_LABEL="" +# CONFIG_EXPERIMENTAL is not set +CONFIG_PERF_CNT=y +CONFIG_BIT32=y +CONFIG_ARM_V7=y +CONFIG_ARM_V6PLUS=y +CONFIG_WARN_LEVEL=1 +CONFIG_XARCH="arm" +CONFIG_ABI="vf" diff --git a/kernel/fiasco/src/templates/globalconfig.out.ia32-1 b/kernel/fiasco/src/templates/globalconfig.out.ia32-1 new file mode 100644 index 00000000..6c35c707 --- /dev/null +++ b/kernel/fiasco/src/templates/globalconfig.out.ia32-1 @@ -0,0 +1,81 @@ +# +# Automatically generated file; DO NOT EDIT. + +# +# Target configuration +# +CONFIG_IA32=y +# CONFIG_AMD64 is not set +# CONFIG_ARM is not set +CONFIG_PF_PC=y +# CONFIG_PF_UX is not set +CONFIG_ABI_VF=y +# CONFIG_IA32_486 is not set +CONFIG_IA32_586=y +# CONFIG_IA32_686 is not set +# CONFIG_IA32_P2 is not set +# CONFIG_IA32_P3 is not set +# CONFIG_IA32_P4 is not set +# CONFIG_IA32_PM is not set +# CONFIG_IA32_CORE2 is not set +# CONFIG_IA32_ATOM is not set +# CONFIG_IA32_K6 is not set +# CONFIG_IA32_K7 is not set +# CONFIG_IA32_K8 is not set +# CONFIG_IA32_K10 is not set +# CONFIG_CPU_VIRT is not set +# CONFIG_SCHED_PIT is not set +# CONFIG_SCHED_RTC is not set +CONFIG_SCHED_APIC=y +# CONFIG_WORKAROUND_AMD_FPU_LEAK is not set +CONFIG_REGPARM3=y + +# +# Kernel options +# +# CONFIG_MP is not set +CONFIG_CONTEXT_4K=y +CONFIG_IO_PROT=y +# CONFIG_SYNC_TSC is not set +# CONFIG_FINE_GRAINED_CPUTIME is not set +CONFIG_SCHED_FIXED_PRIO=y + +# +# Debugging +# +CONFIG_INLINE=y +# CONFIG_NDEBUG is not set +# CONFIG_NO_FRAME_PTR is not set +# CONFIG_STACK_DEPTH is not set +# CONFIG_LIST_ALLOC_SANITY is not set +# CONFIG_BEFORE_IRET_SANITY is not set +# CONFIG_IRQ_SPINNER is not set +CONFIG_WATCHDOG=y +CONFIG_SERIAL=y +CONFIG_JDB=y +# CONFIG_JDB_LOGGING is not set +CONFIG_JDB_DISASM=y +CONFIG_JDB_GZIP=y +# CONFIG_JDB_ACCOUNTING is not set +# CONFIG_JDB_MISC is not set +CONFIG_POWERSAVE_GETCHAR=y +# CONFIG_WARN_NONE is not set +CONFIG_WARN_WARNING=y +# CONFIG_WARN_ANY is not set + +# +# Compiling +# +CONFIG_CC="gcc" +CONFIG_CXX="g++" +CONFIG_HOST_CC="gcc" +CONFIG_HOST_CXX="g++" +# CONFIG_MAINTAINER_MODE is not set +CONFIG_LABEL="" +# CONFIG_EXPERIMENTAL is not set +CONFIG_PERF_CNT=y +CONFIG_BIT32=y +CONFIG_WARN_LEVEL=1 +CONFIG_XARCH="ia32" +CONFIG_IA32_TARGET="Intel Pentium" +CONFIG_ABI="vf" diff --git a/kernel/fiasco/src/templates/globalconfig.out.ia32-2 b/kernel/fiasco/src/templates/globalconfig.out.ia32-2 new file mode 100644 index 00000000..6ed1059d --- /dev/null +++ b/kernel/fiasco/src/templates/globalconfig.out.ia32-2 @@ -0,0 +1,85 @@ +# +# Automatically generated file; DO NOT EDIT. + +# +# Target configuration +# +CONFIG_IA32=y +# CONFIG_AMD64 is not set +# CONFIG_ARM is not set +CONFIG_PF_PC=y +# CONFIG_PF_UX is not set +CONFIG_ABI_VF=y +# CONFIG_IA32_486 is not set +CONFIG_IA32_586=y +# CONFIG_IA32_686 is not set +# CONFIG_IA32_P2 is not set +# CONFIG_IA32_P3 is not set +# CONFIG_IA32_P4 is not set +# CONFIG_IA32_PM is not set +# CONFIG_IA32_CORE2 is not set +# CONFIG_IA32_ATOM is not set +# CONFIG_IA32_K6 is not set +# CONFIG_IA32_K7 is not set +# CONFIG_IA32_K8 is not set +# CONFIG_IA32_K10 is not set +# CONFIG_CPU_VIRT is not set +CONFIG_SCHED_PIT=y +# CONFIG_SCHED_RTC is not set +# CONFIG_SCHED_APIC is not set +# CONFIG_SCHED_HPET is not set +# CONFIG_WORKAROUND_AMD_FPU_LEAK is not set +CONFIG_REGPARM3=y + +# +# Kernel options +# +# CONFIG_MP is not set +CONFIG_CONTEXT_4K=y +# CONFIG_IO_PROT is not set +# CONFIG_SYNC_TSC is not set +# CONFIG_FINE_GRAINED_CPUTIME is not set +CONFIG_SCHED_FIXED_PRIO=y +# CONFIG_SCHED_WFQ is not set +# CONFIG_SCHED_FP_WFQ is not set +# CONFIG_DISABLE_VIRT_OBJ_SPACE is not set + +# +# Debugging +# +CONFIG_INLINE=y +# CONFIG_NDEBUG is not set +CONFIG_NO_FRAME_PTR=y +# CONFIG_STACK_DEPTH is not set +# CONFIG_LIST_ALLOC_SANITY is not set +# CONFIG_BEFORE_IRET_SANITY is not set +# CONFIG_IRQ_SPINNER is not set +CONFIG_WATCHDOG=y +CONFIG_SERIAL=y +CONFIG_JDB=y +# CONFIG_JDB_LOGGING is not set +CONFIG_JDB_DISASM=y +CONFIG_JDB_GZIP=y +# CONFIG_JDB_ACCOUNTING is not set +# CONFIG_JDB_MISC is not set +CONFIG_POWERSAVE_GETCHAR=y +# CONFIG_WARN_NONE is not set +CONFIG_WARN_WARNING=y +# CONFIG_WARN_ANY is not set + +# +# Compiling +# +CONFIG_CC="gcc" +CONFIG_CXX="g++" +CONFIG_HOST_CC="gcc" +CONFIG_HOST_CXX="g++" +# CONFIG_MAINTAINER_MODE is not set +CONFIG_LABEL="" +CONFIG_EXPERIMENTAL=y +CONFIG_PERF_CNT=y +CONFIG_BIT32=y +CONFIG_WARN_LEVEL=1 +CONFIG_XARCH="ia32" +CONFIG_IA32_TARGET="Intel Pentium" +CONFIG_ABI="vf" diff --git a/kernel/fiasco/src/templates/globalconfig.out.ia32-3-noinl b/kernel/fiasco/src/templates/globalconfig.out.ia32-3-noinl new file mode 100644 index 00000000..1b36d480 --- /dev/null +++ b/kernel/fiasco/src/templates/globalconfig.out.ia32-3-noinl @@ -0,0 +1,81 @@ +# +# Automatically generated file; DO NOT EDIT. + +# +# Target configuration +# +CONFIG_IA32=y +# CONFIG_AMD64 is not set +# CONFIG_ARM is not set +CONFIG_PF_PC=y +# CONFIG_PF_UX is not set +CONFIG_ABI_VF=y +# CONFIG_IA32_486 is not set +CONFIG_IA32_586=y +# CONFIG_IA32_686 is not set +# CONFIG_IA32_P2 is not set +# CONFIG_IA32_P3 is not set +# CONFIG_IA32_P4 is not set +# CONFIG_IA32_PM is not set +# CONFIG_IA32_CORE2 is not set +# CONFIG_IA32_ATOM is not set +# CONFIG_IA32_K6 is not set +# CONFIG_IA32_K7 is not set +# CONFIG_IA32_K8 is not set +# CONFIG_IA32_K10 is not set +# CONFIG_CPU_VIRT is not set +# CONFIG_SCHED_PIT is not set +# CONFIG_SCHED_RTC is not set +CONFIG_SCHED_APIC=y +# CONFIG_WORKAROUND_AMD_FPU_LEAK is not set +CONFIG_REGPARM3=y + +# +# Kernel options +# +# CONFIG_MP is not set +CONFIG_CONTEXT_4K=y +# CONFIG_IO_PROT is not set +# CONFIG_SYNC_TSC is not set +# CONFIG_FINE_GRAINED_CPUTIME is not set +CONFIG_SCHED_FIXED_PRIO=y + +# +# Debugging +# +# CONFIG_INLINE is not set +# CONFIG_NDEBUG is not set +# CONFIG_NO_FRAME_PTR is not set +# CONFIG_STACK_DEPTH is not set +# CONFIG_LIST_ALLOC_SANITY is not set +# CONFIG_BEFORE_IRET_SANITY is not set +# CONFIG_IRQ_SPINNER is not set +CONFIG_WATCHDOG=y +CONFIG_SERIAL=y +CONFIG_JDB=y +# CONFIG_JDB_LOGGING is not set +CONFIG_JDB_DISASM=y +CONFIG_JDB_GZIP=y +# CONFIG_JDB_ACCOUNTING is not set +# CONFIG_JDB_MISC is not set +CONFIG_POWERSAVE_GETCHAR=y +# CONFIG_WARN_NONE is not set +CONFIG_WARN_WARNING=y +# CONFIG_WARN_ANY is not set + +# +# Compiling +# +CONFIG_CC="gcc" +CONFIG_CXX="g++" +CONFIG_HOST_CC="gcc" +CONFIG_HOST_CXX="g++" +# CONFIG_MAINTAINER_MODE is not set +CONFIG_LABEL="" +# CONFIG_EXPERIMENTAL is not set +CONFIG_PERF_CNT=y +CONFIG_BIT32=y +CONFIG_WARN_LEVEL=1 +CONFIG_XARCH="ia32" +CONFIG_IA32_TARGET="Intel Pentium" +CONFIG_ABI="vf" diff --git a/kernel/fiasco/src/templates/globalconfig.out.ia32-big b/kernel/fiasco/src/templates/globalconfig.out.ia32-big new file mode 100644 index 00000000..c5dc093b --- /dev/null +++ b/kernel/fiasco/src/templates/globalconfig.out.ia32-big @@ -0,0 +1,86 @@ +# +# Automatically generated file; DO NOT EDIT. + +# +# Target configuration +# +CONFIG_IA32=y +# CONFIG_AMD64 is not set +# CONFIG_ARM is not set +CONFIG_PF_PC=y +# CONFIG_PF_UX is not set +CONFIG_ABI_VF=y +# CONFIG_IA32_486 is not set +CONFIG_IA32_586=y +# CONFIG_IA32_686 is not set +# CONFIG_IA32_P2 is not set +# CONFIG_IA32_P3 is not set +# CONFIG_IA32_P4 is not set +# CONFIG_IA32_PM is not set +# CONFIG_IA32_CORE2 is not set +# CONFIG_IA32_ATOM is not set +# CONFIG_IA32_K6 is not set +# CONFIG_IA32_K7 is not set +# CONFIG_IA32_K8 is not set +# CONFIG_IA32_K10 is not set +CONFIG_CPU_VIRT=y +# CONFIG_SCHED_PIT is not set +# CONFIG_SCHED_RTC is not set +CONFIG_SCHED_APIC=y +# CONFIG_SCHED_HPET is not set +CONFIG_WORKAROUND_AMD_FPU_LEAK=y +CONFIG_REGPARM3=y + +# +# Kernel options +# +# CONFIG_MP is not set +CONFIG_CONTEXT_4K=y +CONFIG_IO_PROT=y +# CONFIG_ONE_SHOT is not set +CONFIG_SYNC_TSC=y +# CONFIG_FINE_GRAINED_CPUTIME is not set +# CONFIG_SCHED_FIXED_PRIO is not set +# CONFIG_SCHED_WFQ is not set +CONFIG_SCHED_FP_WFQ=y +# CONFIG_DISABLE_VIRT_OBJ_SPACE is not set + +# +# Debugging +# +CONFIG_INLINE=y +# CONFIG_NDEBUG is not set +CONFIG_NO_FRAME_PTR=y +CONFIG_STACK_DEPTH=y +CONFIG_LIST_ALLOC_SANITY=y +# CONFIG_BEFORE_IRET_SANITY is not set +# CONFIG_IRQ_SPINNER is not set +CONFIG_WATCHDOG=y +CONFIG_SERIAL=y +CONFIG_JDB=y +CONFIG_JDB_LOGGING=y +CONFIG_JDB_DISASM=y +CONFIG_JDB_GZIP=y +CONFIG_JDB_ACCOUNTING=y +CONFIG_JDB_MISC=y +CONFIG_POWERSAVE_GETCHAR=y +# CONFIG_WARN_NONE is not set +CONFIG_WARN_WARNING=y +# CONFIG_WARN_ANY is not set + +# +# Compiling +# +CONFIG_CC="gcc" +CONFIG_CXX="g++" +CONFIG_HOST_CC="gcc" +CONFIG_HOST_CXX="g++" +# CONFIG_MAINTAINER_MODE is not set +CONFIG_LABEL="" +CONFIG_EXPERIMENTAL=y +CONFIG_PERF_CNT=y +CONFIG_BIT32=y +CONFIG_WARN_LEVEL=1 +CONFIG_XARCH="ia32" +CONFIG_IA32_TARGET="Intel Pentium" +CONFIG_ABI="vf" diff --git a/kernel/fiasco/src/templates/globalconfig.out.ia32-mp b/kernel/fiasco/src/templates/globalconfig.out.ia32-mp new file mode 100644 index 00000000..271374e5 --- /dev/null +++ b/kernel/fiasco/src/templates/globalconfig.out.ia32-mp @@ -0,0 +1,83 @@ +# +# Automatically generated file; DO NOT EDIT. + +# +# Target configuration +# +CONFIG_IA32=y +# CONFIG_AMD64 is not set +# CONFIG_ARM is not set +CONFIG_PF_PC=y +# CONFIG_PF_UX is not set +CONFIG_ABI_VF=y +# CONFIG_IA32_486 is not set +CONFIG_IA32_586=y +# CONFIG_IA32_686 is not set +# CONFIG_IA32_P2 is not set +# CONFIG_IA32_P3 is not set +# CONFIG_IA32_P4 is not set +# CONFIG_IA32_PM is not set +# CONFIG_IA32_CORE2 is not set +# CONFIG_IA32_ATOM is not set +# CONFIG_IA32_K6 is not set +# CONFIG_IA32_K7 is not set +# CONFIG_IA32_K8 is not set +# CONFIG_IA32_K10 is not set +# CONFIG_CPU_VIRT is not set +CONFIG_SCHED_APIC=y +# CONFIG_WORKAROUND_AMD_FPU_LEAK is not set +CONFIG_REGPARM3=y + +# +# Kernel options +# +CONFIG_MP=y +CONFIG_MP_MAX_CPUS=4 +CONFIG_CONTEXT_4K=y +# CONFIG_IO_PROT is not set +# CONFIG_SYNC_TSC is not set +# CONFIG_FINE_GRAINED_CPUTIME is not set +CONFIG_SCHED_FIXED_PRIO=y +# CONFIG_SCHED_WFQ is not set +# CONFIG_SCHED_FP_WFQ is not set +# CONFIG_DISABLE_VIRT_OBJ_SPACE is not set + +# +# Debugging +# +CONFIG_INLINE=y +# CONFIG_NDEBUG is not set +CONFIG_NO_FRAME_PTR=y +# CONFIG_STACK_DEPTH is not set +# CONFIG_LIST_ALLOC_SANITY is not set +# CONFIG_BEFORE_IRET_SANITY is not set +# CONFIG_IRQ_SPINNER is not set +CONFIG_WATCHDOG=y +CONFIG_SERIAL=y +CONFIG_JDB=y +# CONFIG_JDB_LOGGING is not set +CONFIG_JDB_DISASM=y +CONFIG_JDB_GZIP=y +# CONFIG_JDB_ACCOUNTING is not set +# CONFIG_JDB_MISC is not set +CONFIG_POWERSAVE_GETCHAR=y +# CONFIG_WARN_NONE is not set +CONFIG_WARN_WARNING=y +# CONFIG_WARN_ANY is not set + +# +# Compiling +# +CONFIG_CC="gcc" +CONFIG_CXX="g++" +CONFIG_HOST_CC="gcc" +CONFIG_HOST_CXX="g++" +# CONFIG_MAINTAINER_MODE is not set +CONFIG_LABEL="" +CONFIG_EXPERIMENTAL=y +CONFIG_PERF_CNT=y +CONFIG_BIT32=y +CONFIG_WARN_LEVEL=1 +CONFIG_XARCH="ia32" +CONFIG_IA32_TARGET="Intel Pentium" +CONFIG_ABI="vf" diff --git a/kernel/fiasco/src/templates/globalconfig.out.ia32-ndebug b/kernel/fiasco/src/templates/globalconfig.out.ia32-ndebug new file mode 100644 index 00000000..0646d1b2 --- /dev/null +++ b/kernel/fiasco/src/templates/globalconfig.out.ia32-ndebug @@ -0,0 +1,79 @@ +# +# Automatically generated file; DO NOT EDIT. + +# +# Target configuration +# +CONFIG_IA32=y +# CONFIG_AMD64 is not set +# CONFIG_ARM is not set +CONFIG_PF_PC=y +# CONFIG_PF_UX is not set +CONFIG_ABI_VF=y +# CONFIG_IA32_486 is not set +CONFIG_IA32_586=y +# CONFIG_IA32_686 is not set +# CONFIG_IA32_P2 is not set +# CONFIG_IA32_P3 is not set +# CONFIG_IA32_P4 is not set +# CONFIG_IA32_PM is not set +# CONFIG_IA32_CORE2 is not set +# CONFIG_IA32_ATOM is not set +# CONFIG_IA32_K6 is not set +# CONFIG_IA32_K7 is not set +# CONFIG_IA32_K8 is not set +# CONFIG_IA32_K10 is not set +# CONFIG_CPU_VIRT is not set +# CONFIG_SCHED_PIT is not set +# CONFIG_SCHED_RTC is not set +CONFIG_SCHED_APIC=y +# CONFIG_SCHED_HPET is not set +# CONFIG_WORKAROUND_AMD_FPU_LEAK is not set +CONFIG_REGPARM3=y + +# +# Kernel options +# +# CONFIG_MP is not set +CONFIG_CONTEXT_4K=y +# CONFIG_IO_PROT is not set +# CONFIG_SYNC_TSC is not set +# CONFIG_FINE_GRAINED_CPUTIME is not set +CONFIG_SCHED_FIXED_PRIO=y +# CONFIG_SCHED_WFQ is not set +# CONFIG_SCHED_FP_WFQ is not set +# CONFIG_DISABLE_VIRT_OBJ_SPACE is not set + +# +# Debugging +# +CONFIG_INLINE=y +CONFIG_NDEBUG=y +CONFIG_NO_FRAME_PTR=y +# CONFIG_STACK_DEPTH is not set +# CONFIG_LIST_ALLOC_SANITY is not set +# CONFIG_BEFORE_IRET_SANITY is not set +# CONFIG_IRQ_SPINNER is not set +CONFIG_WATCHDOG=y +CONFIG_SERIAL=y +# CONFIG_JDB is not set +CONFIG_POWERSAVE_GETCHAR=y +# CONFIG_WARN_NONE is not set +CONFIG_WARN_WARNING=y +# CONFIG_WARN_ANY is not set + +# +# Compiling +# +CONFIG_CC="gcc" +CONFIG_CXX="g++" +CONFIG_HOST_CC="gcc" +CONFIG_HOST_CXX="g++" +# CONFIG_MAINTAINER_MODE is not set +CONFIG_LABEL="" +CONFIG_EXPERIMENTAL=y +CONFIG_BIT32=y +CONFIG_WARN_LEVEL=1 +CONFIG_XARCH="ia32" +CONFIG_IA32_TARGET="Intel Pentium" +CONFIG_ABI="vf" diff --git a/kernel/fiasco/src/templates/globalconfig.out.ux-1 b/kernel/fiasco/src/templates/globalconfig.out.ux-1 new file mode 100644 index 00000000..70c8c920 --- /dev/null +++ b/kernel/fiasco/src/templates/globalconfig.out.ux-1 @@ -0,0 +1,70 @@ +# +# Automatically generated file; DO NOT EDIT. + +# +# Target configuration +# +CONFIG_IA32=y +# CONFIG_AMD64 is not set +# CONFIG_ARM is not set +# CONFIG_PF_PC is not set +CONFIG_PF_UX=y +CONFIG_ABI_VF=y +# CONFIG_IA32_486 is not set +CONFIG_IA32_586=y +# CONFIG_IA32_686 is not set +# CONFIG_IA32_P2 is not set +# CONFIG_IA32_P3 is not set +# CONFIG_IA32_P4 is not set +# CONFIG_IA32_PM is not set +# CONFIG_IA32_CORE2 is not set +# CONFIG_IA32_ATOM is not set +# CONFIG_IA32_K6 is not set +# CONFIG_IA32_K7 is not set +# CONFIG_IA32_K8 is not set +# CONFIG_IA32_K10 is not set +CONFIG_SCHED_PIT=y + +# +# Kernel options +# +CONFIG_CONTEXT_4K=y +# CONFIG_FINE_GRAINED_CPUTIME is not set +# CONFIG_UX_CON is not set +# CONFIG_UX_NET is not set +CONFIG_SCHED_FIXED_PRIO=y + +# +# Debugging +# +CONFIG_INLINE=y +# CONFIG_NDEBUG is not set +# CONFIG_NO_FRAME_PTR is not set +# CONFIG_STACK_DEPTH is not set +# CONFIG_LIST_ALLOC_SANITY is not set +CONFIG_JDB=y +# CONFIG_JDB_LOGGING is not set +CONFIG_JDB_DISASM=y +# CONFIG_JDB_GZIP is not set +# CONFIG_JDB_ACCOUNTING is not set +# CONFIG_JDB_MISC is not set +# CONFIG_WARN_NONE is not set +CONFIG_WARN_WARNING=y +# CONFIG_WARN_ANY is not set + +# +# Compiling +# +CONFIG_CC="gcc" +CONFIG_CXX="g++" +CONFIG_HOST_CC="gcc" +CONFIG_HOST_CXX="g++" +# CONFIG_MAINTAINER_MODE is not set +CONFIG_LABEL="" +# CONFIG_EXPERIMENTAL is not set +CONFIG_PERF_CNT=y +CONFIG_BIT32=y +CONFIG_WARN_LEVEL=1 +CONFIG_XARCH="ux" +CONFIG_IA32_TARGET="Intel Pentium" +CONFIG_ABI="vf" diff --git a/kernel/fiasco/src/templates/globalconfig.out.ux-2 b/kernel/fiasco/src/templates/globalconfig.out.ux-2 new file mode 100644 index 00000000..541989f4 --- /dev/null +++ b/kernel/fiasco/src/templates/globalconfig.out.ux-2 @@ -0,0 +1,73 @@ +# +# Automatically generated file; DO NOT EDIT. + +# +# Target configuration +# +CONFIG_IA32=y +# CONFIG_AMD64 is not set +# CONFIG_ARM is not set +# CONFIG_PF_PC is not set +CONFIG_PF_UX=y +CONFIG_ABI_VF=y +# CONFIG_IA32_486 is not set +CONFIG_IA32_586=y +# CONFIG_IA32_686 is not set +# CONFIG_IA32_P2 is not set +# CONFIG_IA32_P3 is not set +# CONFIG_IA32_P4 is not set +# CONFIG_IA32_PM is not set +# CONFIG_IA32_CORE2 is not set +# CONFIG_IA32_ATOM is not set +# CONFIG_IA32_K6 is not set +# CONFIG_IA32_K7 is not set +# CONFIG_IA32_K8 is not set +# CONFIG_IA32_K10 is not set +CONFIG_SCHED_PIT=y + +# +# Kernel options +# +# CONFIG_MP is not set +CONFIG_CONTEXT_4K=y +# CONFIG_FINE_GRAINED_CPUTIME is not set +# CONFIG_UX_CON is not set +# CONFIG_UX_NET is not set +# CONFIG_SCHED_FIXED_PRIO is not set +CONFIG_SCHED_WFQ=y +# CONFIG_SCHED_FP_WFQ is not set + +# +# Debugging +# +CONFIG_INLINE=y +# CONFIG_NDEBUG is not set +CONFIG_NO_FRAME_PTR=y +# CONFIG_STACK_DEPTH is not set +# CONFIG_LIST_ALLOC_SANITY is not set +CONFIG_JDB=y +# CONFIG_JDB_LOGGING is not set +CONFIG_JDB_DISASM=y +CONFIG_JDB_GZIP=y +# CONFIG_JDB_ACCOUNTING is not set +# CONFIG_JDB_MISC is not set +# CONFIG_WARN_NONE is not set +CONFIG_WARN_WARNING=y +# CONFIG_WARN_ANY is not set + +# +# Compiling +# +CONFIG_CC="gcc" +CONFIG_CXX="g++" +CONFIG_HOST_CC="gcc" +CONFIG_HOST_CXX="g++" +# CONFIG_MAINTAINER_MODE is not set +CONFIG_LABEL="" +CONFIG_EXPERIMENTAL=y +CONFIG_PERF_CNT=y +CONFIG_BIT32=y +CONFIG_WARN_LEVEL=1 +CONFIG_XARCH="ux" +CONFIG_IA32_TARGET="Intel Pentium" +CONFIG_ABI="vf" diff --git a/kernel/fiasco/src/templates/globalconfig.out.ux-3-noinl b/kernel/fiasco/src/templates/globalconfig.out.ux-3-noinl new file mode 100644 index 00000000..81fb109a --- /dev/null +++ b/kernel/fiasco/src/templates/globalconfig.out.ux-3-noinl @@ -0,0 +1,70 @@ +# +# Automatically generated file; DO NOT EDIT. + +# +# Target configuration +# +CONFIG_IA32=y +# CONFIG_AMD64 is not set +# CONFIG_ARM is not set +# CONFIG_PF_PC is not set +CONFIG_PF_UX=y +CONFIG_ABI_VF=y +# CONFIG_IA32_486 is not set +CONFIG_IA32_586=y +# CONFIG_IA32_686 is not set +# CONFIG_IA32_P2 is not set +# CONFIG_IA32_P3 is not set +# CONFIG_IA32_P4 is not set +# CONFIG_IA32_PM is not set +# CONFIG_IA32_CORE2 is not set +# CONFIG_IA32_ATOM is not set +# CONFIG_IA32_K6 is not set +# CONFIG_IA32_K7 is not set +# CONFIG_IA32_K8 is not set +# CONFIG_IA32_K10 is not set +CONFIG_SCHED_PIT=y + +# +# Kernel options +# +CONFIG_CONTEXT_4K=y +# CONFIG_FINE_GRAINED_CPUTIME is not set +# CONFIG_UX_CON is not set +# CONFIG_UX_NET is not set +CONFIG_SCHED_FIXED_PRIO=y + +# +# Debugging +# +# CONFIG_INLINE is not set +# CONFIG_NDEBUG is not set +# CONFIG_NO_FRAME_PTR is not set +# CONFIG_STACK_DEPTH is not set +# CONFIG_LIST_ALLOC_SANITY is not set +CONFIG_JDB=y +# CONFIG_JDB_LOGGING is not set +CONFIG_JDB_DISASM=y +# CONFIG_JDB_GZIP is not set +# CONFIG_JDB_ACCOUNTING is not set +# CONFIG_JDB_MISC is not set +# CONFIG_WARN_NONE is not set +CONFIG_WARN_WARNING=y +# CONFIG_WARN_ANY is not set + +# +# Compiling +# +CONFIG_CC="gcc" +CONFIG_CXX="g++" +CONFIG_HOST_CC="gcc" +CONFIG_HOST_CXX="g++" +# CONFIG_MAINTAINER_MODE is not set +CONFIG_LABEL="" +# CONFIG_EXPERIMENTAL is not set +CONFIG_PERF_CNT=y +CONFIG_BIT32=y +CONFIG_WARN_LEVEL=1 +CONFIG_XARCH="ux" +CONFIG_IA32_TARGET="Intel Pentium" +CONFIG_ABI="vf" diff --git a/kernel/fiasco/src/test/Makefile b/kernel/fiasco/src/test/Makefile new file mode 100644 index 00000000..99ccb9b6 --- /dev/null +++ b/kernel/fiasco/src/test/Makefile @@ -0,0 +1,5 @@ +L4DIR ?= ../../../.. + +TARGET = wrappers mapdb space map_util + +include $(L4DIR)/mk/subdir.mk diff --git a/kernel/fiasco/src/test/Makerules.BOOTTASK b/kernel/fiasco/src/test/Makerules.BOOTTASK new file mode 100644 index 00000000..9ec56151 --- /dev/null +++ b/kernel/fiasco/src/test/Makerules.BOOTTASK @@ -0,0 +1,23 @@ +# -*- makefile -*- + +$(BOOTTASK): $(OBJ_BOOTTASK) kernel.o test.o + $(LD) -Ttext 0x300000 -o $@ $^ $(STD_LIBS) + chmod 755 $@ + +test.o: boottask-r.ld $(TESTTASK) + cp $(TESTTASK) $(TESTTASK).s + $(STRIP) $(TESTTASK).s + $(LD) -r -T $< -o $@ \ + -defsym boottask_entry=$(TESTTASK_ENTRY) \ + $(TESTTASK).s + + +kernel.o: $(srcdir)/kernel-r.ld $(KERNEL) + cp $(KERNEL) $(KERNEL).s + $(STRIP) $(KERNEL).s + $(LD) -r -T $< -o $@ \ + -defsym crt0_start=0x`$(NM) $(KERNEL) | grep crt0_start | cut -f1 -d' '` \ + $(KERNEL).s + +clean-BOOTTASK: + rm -f $(KERNEL).s kernel.o $(TESTTASK).s test.o diff --git a/kernel/fiasco/src/test/Makerules.SYSTEM_UNDER_TEST b/kernel/fiasco/src/test/Makerules.SYSTEM_UNDER_TEST new file mode 100644 index 00000000..162d92c6 --- /dev/null +++ b/kernel/fiasco/src/test/Makerules.SYSTEM_UNDER_TEST @@ -0,0 +1,26 @@ +# -*- makefile -*- + +CXXSRC_SYSTEM_UNDER_TEST += $(SYSTEM_UNDER_TEST).cc + +.PHONY: $(SYSTEM_UNDER_TEST) + +$(SYSTEM_UNDER_TEST): $(SYSTEM_UNDER_TEST).ok + +$(SYSTEM_UNDER_TEST).run: $(OBJ_SYSTEM_UNDER_TEST) $(LIBS) + $(CXX) -g -o $@ $(OBJ_SYSTEM_UNDER_TEST) $(LIBS) + +%.ok: %.run + @echo -n "Running test $* ... " + @./$< > $*.out +ifeq ($(RECREATE_OUTPUT),1) + @cp $*.out $*.out.verify +endif + @diff -u $(DIFF_FLAGS) $*.out.verify $*.out + @touch $@ + +clean-SYSTEM_UNDER_TEST: + rm -f $(SYSTEM_UNDER_TEST).out $(SYSTEM_UNDER_TEST).run $(SYSTEM_UNDER_TEST).ok + +CXXFLAGS := $(filter-out -nostdinc, $(CXXFLAGS)) +CPPFLAGS := $(filter-out -I$(DROPS_STDINCDIR)/flux/c \ + -I$(OSKITDIR)/flux/c -nostdinc, $(CPPFLAGS)) diff --git a/kernel/fiasco/src/test/Makerules.TESTTASK b/kernel/fiasco/src/test/Makerules.TESTTASK new file mode 100644 index 00000000..be083fd3 --- /dev/null +++ b/kernel/fiasco/src/test/Makerules.TESTTASK @@ -0,0 +1,11 @@ +# -*- makefile -*- + +TESTTASK_ENTRY = 0x200000 +TESTTASK_LIBS = $(L4ALL_LIBDIR) \ + -lmc -loskit_support -lmc -lkern + +$(TESTTASK): $(OBJ_TESTTASK) + $(LD) -N -Ttext $(TESTTASK_ENTRY) -o $@ $^ $(TESTTASK_LIBS) + + +clean-TESTTASK: diff --git a/kernel/fiasco/src/test/Makerules.WRAPPERS b/kernel/fiasco/src/test/Makerules.WRAPPERS new file mode 100644 index 00000000..51f5e30f --- /dev/null +++ b/kernel/fiasco/src/test/Makerules.WRAPPERS @@ -0,0 +1,15 @@ +# -*- makefile -*- + +# Kernel library: stuff which is linked in optionally. This includes +# everything in the lib subdirectory, but may also include optional +# kernel subsystems which may be optimized away + +$(WRAPPERS): $(OBJ_WRAPPERS) + $(AR) rv $@ $^ + $(RANLIB) $@ + +clean-WRAPPERS: + +CXXFLAGS := $(filter-out -nostdinc, $(CXXFLAGS)) +CPPFLAGS := $(filter-out -I$(DROPS_STDINCDIR)/flux/c \ + -I$(OSKITDIR)/flux/c -nostdinc, $(CPPFLAGS)) diff --git a/kernel/fiasco/src/test/boottask/bootstrap-boottask.cc b/kernel/fiasco/src/test/boottask/bootstrap-boottask.cc new file mode 100644 index 00000000..471fe212 --- /dev/null +++ b/kernel/fiasco/src/test/boottask/bootstrap-boottask.cc @@ -0,0 +1,71 @@ +/* this code is run directly from boot.S. our task is to setup the + paging just enough so that L4 can run in its native address space + at 0xf0001000, and then start up L4. */ + +#include +#include +#include +#include +#include +#include + +extern "C" void crt0_start(struct multiboot_info *mbi, unsigned int flag) + __attribute__((noreturn)); +extern "C" void boottask_entry() __attribute__((noreturn)); + +extern char kernel_start, kernel_end, boottask_start, boottask_end; + +extern "C" void bootstrap(struct multiboot_info *mbi, unsigned int flag) + __attribute__((noreturn)); + +extern "C" void +bootstrap(struct multiboot_info *mbi, unsigned int flag) +{ + assert(flag == MULTIBOOT_VALID); + + // setup stuff for base_paging_init() + base_cpu_setup(); + phys_mem_max = 1024 * (1024 + mbi->mem_upper); + + // now do base_paging_init(): sets up paging with one-to-one mapping + base_paging_init(); + + // map in physical memory at 0xf0000000 + pdir_map_range(base_pdir_pa, 0xf0000000, 0, phys_mem_max, + INTEL_PTE_VALID | INTEL_PDE_WRITE | INTEL_PDE_USER); + + + // copy l4 kernel binary to its load address + memcpy((void *) crt0_start, &kernel_start, + &kernel_end - &kernel_start); + + memcpy((void *) boottask_entry, &boottask_start, + &boottask_end - &boottask_start); + + crt0_start(mbi, flag); +} + +/* the following simple-minded function definition overrides the (more + complicated) default one the OSKIT*/ +extern "C" int +ptab_alloc(vm_offset_t *out_ptab_pa) +{ + static char pool[0x100000]; + static vm_offset_t pdirs; + static int initialized = 0; + + if (! initialized) + { + initialized = 1; + + pdirs = (reinterpret_cast(&pool[0]) + PAGE_SIZE - 1) + & ~PAGE_MASK; + } + + assert(pdirs < reinterpret_cast(&pool[0]) + sizeof(pool)); + + *out_ptab_pa = pdirs; + pdirs += PAGE_SIZE; + + return 0; +} diff --git a/kernel/fiasco/src/test/boottask/boottask-r.ld b/kernel/fiasco/src/test/boottask/boottask-r.ld new file mode 100644 index 00000000..6d445227 --- /dev/null +++ b/kernel/fiasco/src/test/boottask/boottask-r.ld @@ -0,0 +1,15 @@ +/* -*- c -*- */ + +SECTIONS +{ + /DISCARD/ : /* discard all sections not stripped by `strip' */ + { + *(.comment .note) + } + .data : + { + boottask_start = .; + *(*) + boottask_end = .; + } +} diff --git a/kernel/fiasco/src/test/map_util/Makefile b/kernel/fiasco/src/test/map_util/Makefile new file mode 100644 index 00000000..840d260f --- /dev/null +++ b/kernel/fiasco/src/test/map_util/Makefile @@ -0,0 +1,7 @@ +srcdir = ../.. + +all: + +%: + $(MAKE) -I $(srcdir) -I .. -f $(srcdir)/Makefile \ + srcdir=$(srcdir) MODULES_FILE=Modules.map_util $@ diff --git a/kernel/fiasco/src/test/map_util/Modules.map_util b/kernel/fiasco/src/test/map_util/Modules.map_util new file mode 100644 index 00000000..de8f1a94 --- /dev/null +++ b/kernel/fiasco/src/test/map_util/Modules.map_util @@ -0,0 +1,24 @@ +# -*- makefile -*- + +ARCH := ia32 +SUBSYSTEMS := SYSTEM_UNDER_TEST ABI +SYSTEM_UNDER_TEST := map_util.t + +INTERFACES_SYSTEM_UNDER_TEST := map_util mapdb space space_context \ + space_index config cpu boot_info + +INTERFACES_ABI := l4_types l4_ipc l4_syscalls kip + +boot_info_IMPL := boot_info boot_info-arch +cpu_IMPL := cpu-x86 cpu-arch +config_IMPL := config config-arch +space_IMPL := space space-arch +l4_syscalls_IMPL := l4_syscalls-arch l4_syscalls +l4_types_IMPL := l4_types-arch l4_types +l4_ipc_IMPL := l4_ipc-arch l4_ipc + +PRIVATE_INCDIR += lib/kern/include test/wrappers/auto \ + kern/$(ARCH) kern types/$(ARCH) types + +VPATH += kern kern/$(ARCH) kern/shared abi/$(ARCH) abi types/$(ARCH) types +LIBS := ../wrappers/libwrappers.a diff --git a/kernel/fiasco/src/test/map_util/map_util.t.cc b/kernel/fiasco/src/test/map_util/map_util.t.cc new file mode 100644 index 00000000..549bf592 --- /dev/null +++ b/kernel/fiasco/src/test/map_util/map_util.t.cc @@ -0,0 +1,170 @@ +#include +#include +#include + +using namespace std; + +#include +#include "l4_types.h" +#include "l4_ipc.h" +#include "map_util.h" +#include "space.h" +#include "globals.h" +#include "config.h" + +static void print_node(mapping_t* node, int depth = 0); + +int main() +{ + // + // Create tasks + // + sigma0 = new Space (2); + + Space *server = new Space (5); + assert (server); + Space *client = new Space (6); + assert (client); + + // + // Manipulate mappings. + // + mapdb_t* mapdb = &the_mapdb; + + vm_offset_t phys, size; + unsigned page_attribs; + mapping_t *m; + + // + // s0 [0x10000] -> server [0x1000] + // + assert (fpage_map (sigma0, + l4_fpage (0x10000, L4_LOG2_PAGESIZE, L4_FPAGE_RW, 0), + server, + l4_fpage (0, L4_WHOLE_ADDRESS_SPACE, 0, 0), + 0x1000) + == L4_IPC_FPAGE_MASK); + + assert (server->v_lookup (0x1000, &phys, &size, &page_attribs) == true); + assert (size == PAGE_SIZE); + assert (phys == 0x10000); + assert (page_attribs == (Space::Page_writable + | Space::Page_user_accessible)); + + m = mapdb->lookup (sigma0->space(), 0x10000, 0x10000); + print_node (m); + mapdb->free (m); + + // + // s0 [0/superpage] -> server [0] -> should map many 4K pages and skip + // previos page + // + assert (fpage_map (sigma0, + l4_fpage (0, L4_LOG2_SUPERPAGESIZE, 0, 0), + server, + l4_fpage (0, L4_WHOLE_ADDRESS_SPACE, 0, 0), + 0) == L4_IPC_FPAGE_MASK); + + assert (server->v_lookup (0, &phys, &size, &page_attribs) == true); + assert (size == PAGE_SIZE); // and not SUPERPAGE_SIZE! + assert (phys == 0); + assert (page_attribs == Space::Page_user_accessible); + + m = mapdb->lookup (sigma0->space(), 0, 0); + print_node (m); + mapdb->free (m); + + // previous mapping still there? + assert (server->v_lookup (0x1000, &phys, &size, &page_attribs) == true); + assert (size == PAGE_SIZE); + assert (phys == 0x10000); + assert (page_attribs == (Space::Page_writable + | Space::Page_user_accessible)); + + // mapdb entry -- tree should now contain another mapping + // s0 [0x10000] -> server [0x10000] + m = mapdb->lookup (sigma0->space(), 0x10000, 0x10000); + print_node (m); + mapdb->free (m); + + // + // s0 [4M/superpage] -> server [8M] + // + assert (fpage_map (sigma0, + l4_fpage (0x400000, L4_LOG2_SUPERPAGESIZE, L4_FPAGE_RW,0), + server, + l4_fpage (0x800000, L4_LOG2_SUPERPAGESIZE, 0, 0), + 0) == L4_IPC_FPAGE_MASK); + + assert (server->v_lookup (0x800000, &phys, &size, &page_attribs) == true); + assert (size == SUPERPAGE_SIZE); + assert (phys == 0x400000); + assert (page_attribs == (Space::Page_writable + | Space::Page_user_accessible)); + + m = mapdb->lookup (sigma0->space(), 0x400000, 0x400000); + print_node (m); + mapdb->free (m); + + // + // server [8M+4K] -> client [8K] + // + assert (fpage_map (server, + l4_fpage (0x801000, L4_LOG2_PAGESIZE, L4_FPAGE_RW,0), + client, + l4_fpage (0, L4_WHOLE_ADDRESS_SPACE, 0, 0), + 0x8000) == L4_IPC_FPAGE_MASK); + + assert (client->v_lookup (0x8000, &phys, &size, &page_attribs) == true); + assert (size == PAGE_SIZE); + assert (phys == 0x401000); + assert (page_attribs == (Space::Page_writable + | Space::Page_user_accessible)); + + cout << "XXX: The 4K submapping is attached to the Sigma0 parent." << endl; + m = mapdb->lookup (sigma0->space(), 0x401000, 0x401000); + print_node (m); + mapdb->free (m); + + // + // Delete tasks + // + delete server; + delete client; + delete sigma0; + + cerr << "OK" << endl; + + return 0; +} + +static void print_node(mapping_t* node, int depth = 0) +{ + assert (node); + + for (int i = depth; i != 0; i--) + cout << ' '; + + cout << setbase(16) + << "space=0x" << node->space() + << " vaddr=0x" << node->vaddr() + << " size=0x" << node->size() + << " type=0x" << node->type(); + + unsigned after = 0; + mapping_t* next = node; + while ((next = next->next_iter())) + after++; + + cout << " after=" << after << endl; + + next = node; + while ((next = next->next_child(node))) + { + if(next->parent() == node) + print_node (next, depth + 1); + } + + if (depth == 0) + cout << endl; +} diff --git a/kernel/fiasco/src/test/map_util/map_util.t.out.verify b/kernel/fiasco/src/test/map_util/map_util.t.out.verify new file mode 100644 index 00000000..5b0084a7 --- /dev/null +++ b/kernel/fiasco/src/test/map_util/map_util.t.out.verify @@ -0,0 +1,17 @@ +space=0x2 vaddr=0x10000 size=0x1000 type=0x0 after=1 + space=0x5 vaddr=0x1000 size=0x1000 type=0x0 after=0 + +space=0x2 vaddr=0x0 size=0x1000 type=0x0 after=1 + space=0x5 vaddr=0x0 size=0x1000 type=0x0 after=0 + +space=0x2 vaddr=0x10000 size=0x1000 type=0x0 after=2 + space=0x5 vaddr=0x1000 size=0x1000 type=0x0 after=1 + space=0x5 vaddr=0x10000 size=0x1000 type=0x0 after=0 + +space=0x2 vaddr=0x400000 size=0x1000 type=0x0 after=1 + space=0x5 vaddr=0x800000 size=0x400000 type=0x0 after=0 + +XXX: The 4K submapping is attached to the Sigma0 parent. +space=0x2 vaddr=0x401000 size=0x1000 type=0x0 after=1 + space=0x6 vaddr=0x8000 size=0x1000 type=0x0 after=0 + diff --git a/kernel/fiasco/src/test/mapdb/Makefile b/kernel/fiasco/src/test/mapdb/Makefile new file mode 100644 index 00000000..2a1799b4 --- /dev/null +++ b/kernel/fiasco/src/test/mapdb/Makefile @@ -0,0 +1,7 @@ +srcdir = ../.. + +all: + +%: + $(MAKE) -I $(srcdir) -I .. -f $(srcdir)/Makefile \ + srcdir=$(srcdir) MODULES_FILE=Modules.mapdb $@ diff --git a/kernel/fiasco/src/test/mapdb/Modules.mapdb b/kernel/fiasco/src/test/mapdb/Modules.mapdb new file mode 100644 index 00000000..5295482a --- /dev/null +++ b/kernel/fiasco/src/test/mapdb/Modules.mapdb @@ -0,0 +1,20 @@ +# -*- makefile -*- + +ARCH := ia32 +SUBSYSTEMS := SYSTEM_UNDER_TEST ABI +SYSTEM_UNDER_TEST := mapdb.t + +INTERFACES_SYSTEM_UNDER_TEST := mapdb config boot_info +INTERFACES_ABI := l4_types l4_ipc l4_syscalls kip + +boot_info_IMPL := boot_info boot_info-arch +config_IMPL := config config-arch +l4_syscalls_IMPL := l4_syscalls-arch l4_syscalls +l4_types_IMPL := l4_types-arch l4_types +l4_ipc_IMPL := l4_ipc-arch l4_ipc + +PRIVATE_INCDIR += kern lib/kern/include types/$(ARCH) types \ + test/wrappers/auto +VPATH += kern/$(ARCH) kern abi/$(ARCH) abi \ + types/$(ARCH) types +LIBS := ../wrappers/libwrappers.a diff --git a/kernel/fiasco/src/test/mapdb/mapdb.t.cc b/kernel/fiasco/src/test/mapdb/mapdb.t.cc new file mode 100644 index 00000000..f8a1c946 --- /dev/null +++ b/kernel/fiasco/src/test/mapdb/mapdb.t.cc @@ -0,0 +1,252 @@ +#include +#include +#include + +using namespace std; + +#include +#include "config.h" +#include "mapdb.h" + +static void print_node(mapping_t* node, int depth = 0); +static void print_whole_tree(mapping_t *node); + +static void print_node(mapping_t* node, int depth) +{ + assert (node); + + for (int i = depth; i != 0; i--) + cout << ' '; + + cout << setbase(16) + << "space=0x" << node->space() + << " vaddr=0x" << node->vaddr() + << " size=0x" << node->size() + << " type=0x" << node->type(); + + unsigned after = 0; + mapping_t* next = node; + while ((next = next->next_iter())) + after++; + + cout << " after=" << after << endl; + + next = node; + while ((next = next->next_child(node))) + { + if(next->parent() == node) + print_node (next, depth + 1); + } + + if (depth == 0) + cout << endl; +} + +void basic() +{ + mapdb_t m (64*1024L*1024L); + + unsigned sigma0 = Config::sigma0_taskno; + unsigned other = 10; + unsigned client = 11; + + mapping_t *node, *sub, *subsub; + + assert (m.lookup(other, PAGE_SIZE, PAGE_SIZE) == 0); + + cout << "Looking up 4K node at physaddr=4K" << endl; + node = m.lookup (sigma0, PAGE_SIZE, PAGE_SIZE); + print_node (node); + + cout << "Inserting submapping" << endl; + sub = m.insert (node, other, 2*PAGE_SIZE, PAGE_SIZE, Map_mem); + print_node (node); + + m.free (node); + + ////////////////////////////////////////////////////////////////////// + + cout << "Looking up 4M node at physaddr=8M" << endl; + node = m.lookup (sigma0, 2*SUPERPAGE_SIZE, 2*SUPERPAGE_SIZE); + print_node (node); + + // XXX broken mapdb: assert (node->size() == SUPERPAGE_SIZE); + + cout << "Inserting submapping" << endl; + sub = m.insert (node, other, 4*SUPERPAGE_SIZE, SUPERPAGE_SIZE, Map_mem); + print_node (node); + + assert (sub->size() == SUPERPAGE_SIZE); + + // Before we can insert new mappings, we must free the tree. + m.free (node); + + cout << "Get that mapping again" << endl; + sub = m.lookup (other, 4*SUPERPAGE_SIZE, 2*SUPERPAGE_SIZE); + print_node (sub); + + node = sub->parent(); + + cout << "Inserting 4K submapping" << endl; + subsub = m.insert (sub, client, 15*PAGE_SIZE, PAGE_SIZE, Map_mem); + print_node (node); + + m.free (subsub); // It doesn't matter which mapping is + // passed to free(). + +} + +static void print_whole_tree(mapping_t *node) +{ + while(node->parent()) + node = node->parent(); + print_node(node); +} + + +void maphole() +{ + mapdb_t m(PAGE_SIZE); + + unsigned sigma0 = Config::sigma0_taskno; + + mapping_t *gf_map, *f_map, *son_map, *daughter_map, *a_map; + + unsigned grandfather = sigma0; + unsigned father = 6, son = 7, daughter = 8, aunt = 9; + + cout << "Looking up 4K node at physaddr=0" << endl; + gf_map = m.lookup (grandfather, 0, 0); + print_whole_tree (gf_map); + + cout << "Inserting father mapping" << endl; + f_map = m.insert (gf_map, father, 0, PAGE_SIZE, Map_mem); + print_whole_tree (f_map); + m.free(f_map); + + + cout << "Looking up father at physaddr=0" << endl; + f_map = m.lookup (father, 0, 0); + print_whole_tree (f_map); + + cout << "Inserting son mapping" << endl; + son_map = m.insert (f_map, son, 0, PAGE_SIZE, Map_mem); + print_whole_tree (son_map); + m.free(son_map); + + + cout << "Looking up father at physaddr=0" << endl; + f_map = m.lookup (father, 0, 0); + print_whole_tree (f_map); + + cout << "Inserting daughter mapping" << endl; + daughter_map = m.insert (f_map, daughter, 0, PAGE_SIZE, Map_mem); + print_whole_tree (daughter_map); + m.free(daughter_map); + + + cout << "Looking up son at physaddr=0" << endl; + son_map = m.lookup(son, 0,0); + f_map = son_map->parent(); + print_whole_tree (son_map); + + cout << "Son has accident on return from disco" << endl; + m.flush(son_map, true); + m.free(f_map); + + cout << "Lost aunt returns from holidays" << endl; + gf_map = m.lookup (grandfather, 0, 0); + print_whole_tree (gf_map); + + cout << "Inserting aunt mapping" << endl; + a_map = m.insert (gf_map, aunt, 0, PAGE_SIZE, Map_mem); + print_whole_tree (a_map); + m.free(a_map); + + cout << "Looking up daughter at physaddr=0" << endl; + daughter_map = m.lookup(daughter, 0,0); + print_whole_tree (daughter_map); + f_map = daughter_map->parent(); + cout << "Father of daugther is " << f_map->space() << endl; + + assert(f_map->space() == father); + + m.free(f_map); +} + + +void flushtest() +{ + mapdb_t m(PAGE_SIZE); + + unsigned sigma0 = Config::sigma0_taskno; + + mapping_t *gf_map, *f_map, *son_map, *a_map; + + unsigned grandfather = sigma0; + unsigned father = 6, son = 7, aunt = 9; + + cout << "Looking up 4K node at physaddr=0" << endl; + gf_map = m.lookup (grandfather, 0, 0); + print_whole_tree (gf_map); + + cout << "Inserting father mapping" << endl; + f_map = m.insert (gf_map, father, 0, PAGE_SIZE, Map_mem); + print_whole_tree (f_map); + m.free(f_map); + + + cout << "Looking up father at physaddr=0" << endl; + f_map = m.lookup (father, 0, 0); + print_whole_tree (f_map); + + cout << "Inserting son mapping" << endl; + son_map = m.insert (f_map, son, 0, PAGE_SIZE, Map_mem); + print_whole_tree (son_map); + m.free(son_map); + + cout << "Lost aunt returns from holidays" << endl; + gf_map = m.lookup (grandfather, 0, 0); + print_whole_tree (gf_map); + + cout << "Inserting aunt mapping" << endl; + a_map = m.insert (gf_map, aunt, 0, PAGE_SIZE, Map_mem); + print_whole_tree (a_map); + m.free(a_map); + + cout << "Looking up father at physaddr=0" << endl; + f_map = m.lookup(father, 0,0); + gf_map = f_map->parent(); + print_whole_tree (gf_map); + + cout << "father is killed by his new love" << endl; + m.flush(f_map, true); + print_whole_tree (gf_map); + m.free(f_map); + + cout << "Try resurrecting the killed father again" << endl; + f_map = m.lookup(father, 0,0); + assert (! f_map); + + cout << "Resurrection is impossible, as it ought to be." << endl; +} + + + +int main() +{ + cout << "Basic test" << endl; + basic(); + cout << "########################################" << endl; + + cout << "Hole test" << endl; + maphole(); + cout << "########################################" << endl; + + cout << "Flush test" << endl; + flushtest(); + cout << "########################################" << endl; + + cerr << "OK" << endl; + return(0); +} diff --git a/kernel/fiasco/src/test/mapdb/mapdb.t.out.verify b/kernel/fiasco/src/test/mapdb/mapdb.t.out.verify new file mode 100644 index 00000000..01370cf1 --- /dev/null +++ b/kernel/fiasco/src/test/mapdb/mapdb.t.out.verify @@ -0,0 +1,119 @@ +Basic test +Looking up 4K node at physaddr=4K +space=0x2 vaddr=0x1000 size=0x1000 type=0x0 after=0 + +Inserting submapping +space=0x2 vaddr=0x1000 size=0x1000 type=0x0 after=1 + space=0xa vaddr=0x2000 size=0x1000 type=0x0 after=0 + +Looking up 4M node at physaddr=8M +space=0x2 vaddr=0x800000 size=0x1000 type=0x0 after=0 + +Inserting submapping +space=0x2 vaddr=0x800000 size=0x1000 type=0x0 after=1 + space=0xa vaddr=0x1000000 size=0x400000 type=0x0 after=0 + +Get that mapping again +space=0xa vaddr=0x1000000 size=0x400000 type=0x0 after=0 + +Inserting 4K submapping +space=0x2 vaddr=0x800000 size=0x1000 type=0x0 after=2 + space=0xa vaddr=0x1000000 size=0x400000 type=0x0 after=1 + space=0xb vaddr=0xf000 size=0x1000 type=0x0 after=0 + +######################################## +Hole test +Looking up 4K node at physaddr=0 +space=0x2 vaddr=0x0 size=0x1000 type=0x0 after=0 + +Inserting father mapping +space=0x2 vaddr=0x0 size=0x1000 type=0x0 after=1 + space=0x6 vaddr=0x0 size=0x1000 type=0x0 after=0 + +Looking up father at physaddr=0 +space=0x2 vaddr=0x0 size=0x1000 type=0x0 after=1 + space=0x6 vaddr=0x0 size=0x1000 type=0x0 after=0 + +Inserting son mapping +space=0x2 vaddr=0x0 size=0x1000 type=0x0 after=2 + space=0x6 vaddr=0x0 size=0x1000 type=0x0 after=1 + space=0x7 vaddr=0x0 size=0x1000 type=0x0 after=0 + +Looking up father at physaddr=0 +space=0x2 vaddr=0x0 size=0x1000 type=0x0 after=2 + space=0x6 vaddr=0x0 size=0x1000 type=0x0 after=1 + space=0x7 vaddr=0x0 size=0x1000 type=0x0 after=0 + +Inserting daughter mapping +space=0x2 vaddr=0x0 size=0x1000 type=0x0 after=3 + space=0x6 vaddr=0x0 size=0x1000 type=0x0 after=2 + space=0x7 vaddr=0x0 size=0x1000 type=0x0 after=1 + space=0x8 vaddr=0x0 size=0x1000 type=0x0 after=0 + +Looking up son at physaddr=0 +space=0x2 vaddr=0x0 size=0x1000 type=0x0 after=3 + space=0x6 vaddr=0x0 size=0x1000 type=0x0 after=2 + space=0x7 vaddr=0x0 size=0x1000 type=0x0 after=1 + space=0x8 vaddr=0x0 size=0x1000 type=0x0 after=0 + +Son has accident on return from disco +Lost aunt returns from holidays +space=0x2 vaddr=0x0 size=0x1000 type=0x0 after=2 + space=0x6 vaddr=0x0 size=0x1000 type=0x0 after=1 + space=0x8 vaddr=0x0 size=0x1000 type=0x0 after=0 + +Inserting aunt mapping +space=0x2 vaddr=0x0 size=0x1000 type=0x0 after=3 + space=0x6 vaddr=0x0 size=0x1000 type=0x0 after=2 + space=0x8 vaddr=0x0 size=0x1000 type=0x0 after=1 + space=0x9 vaddr=0x0 size=0x1000 type=0x0 after=0 + +Looking up daughter at physaddr=0 +space=0x2 vaddr=0x0 size=0x1000 type=0x0 after=3 + space=0x6 vaddr=0x0 size=0x1000 type=0x0 after=2 + space=0x8 vaddr=0x0 size=0x1000 type=0x0 after=1 + space=0x9 vaddr=0x0 size=0x1000 type=0x0 after=0 + +Father of daugther is 6 +######################################## +Flush test +Looking up 4K node at physaddr=0 +space=0x2 vaddr=0x0 size=0x1000 type=0x0 after=0 + +Inserting father mapping +space=0x2 vaddr=0x0 size=0x1000 type=0x0 after=1 + space=0x6 vaddr=0x0 size=0x1000 type=0x0 after=0 + +Looking up father at physaddr=0 +space=0x2 vaddr=0x0 size=0x1000 type=0x0 after=1 + space=0x6 vaddr=0x0 size=0x1000 type=0x0 after=0 + +Inserting son mapping +space=0x2 vaddr=0x0 size=0x1000 type=0x0 after=2 + space=0x6 vaddr=0x0 size=0x1000 type=0x0 after=1 + space=0x7 vaddr=0x0 size=0x1000 type=0x0 after=0 + +Lost aunt returns from holidays +space=0x2 vaddr=0x0 size=0x1000 type=0x0 after=2 + space=0x6 vaddr=0x0 size=0x1000 type=0x0 after=1 + space=0x7 vaddr=0x0 size=0x1000 type=0x0 after=0 + +Inserting aunt mapping +space=0x2 vaddr=0x0 size=0x1000 type=0x0 after=3 + space=0x6 vaddr=0x0 size=0x1000 type=0x0 after=2 + space=0x7 vaddr=0x0 size=0x1000 type=0x0 after=1 + space=0x9 vaddr=0x0 size=0x1000 type=0x0 after=0 + +Looking up father at physaddr=0 +space=0x2 vaddr=0x0 size=0x1000 type=0x0 after=3 + space=0x6 vaddr=0x0 size=0x1000 type=0x0 after=2 + space=0x7 vaddr=0x0 size=0x1000 type=0x0 after=1 + space=0x9 vaddr=0x0 size=0x1000 type=0x0 after=0 + +father is killed by his new love +space=0x2 vaddr=0x0 size=0x1000 type=0x0 after=1 + space=0x9 vaddr=0x0 size=0x1000 type=0x0 after=0 + +Try resurrecting the killed father again +Resurrection is impossible, as it ought to be. +######################################## diff --git a/kernel/fiasco/src/test/pingpong/Makefile b/kernel/fiasco/src/test/pingpong/Makefile new file mode 100644 index 00000000..cffd4771 --- /dev/null +++ b/kernel/fiasco/src/test/pingpong/Makefile @@ -0,0 +1,7 @@ +srcdir = ../.. + +all: + +%: + $(MAKE) -I $(srcdir) -I .. -f $(srcdir)/Makefile \ + srcdir=$(srcdir) $@ diff --git a/kernel/fiasco/src/test/pingpong/Modules b/kernel/fiasco/src/test/pingpong/Modules new file mode 100644 index 00000000..2fa8bc2a --- /dev/null +++ b/kernel/fiasco/src/test/pingpong/Modules @@ -0,0 +1,85 @@ +# -*- makefile -*- + +SUBSYSTEMS = BOOTTASK TESTTASK KERNEL CRT0 LIBK LIBAMM + +ifneq ($(wildcard $(srcdir)/disasm),) +SUBSYSTEMS += LIBDISASM +endif + +# +# KERNEL subsystem +# +KERNEL = fiasco.image +KERNEL_EXTRA = Symbols +VPATH += kern +PRIVATE_INCDIR += kern + +INTERFACES_KERNEL = mapdb region \ + space_context space space_index space_index_util \ + stack irq_init kmem kmem_alloc slab_cache kmem_slab_simple kmem_slab \ + switch_lock thread_lock helping_lock kernel_lock timer \ + thread_state sched context threadid thread_regs sender receiver \ + thread kernel_thread \ + map_util irq startup console paranoia globals \ + kdb kdb_ke jdb_symbol jdb_lines jdb_trace jdb_tbuf jdb_bp jdb main config + +thread_IMPL = thread thread-syscall thread-list thread-ipc thread-msg \ + thread-log + +kernel_thread_IMPL = kernel_thread-test + +OBJ_KERNEL = entry.o + +# +# CRT0 subsystem +# +CRT0 = crt0.o + +OBJ_CRT0 = crt0.o + +# +# LIBK subsystem +# +LIBK = libk.a +VPATH += lib +PRIVATE_INCDIR += . lib/oskit + +INTERFACES_LIBK = atomic lock_guard profile uuencode gmon unistd + +CSRC_LIBK = com_cons.c + +NOPROFILE += profile gmon + +# +# LIBAMM subsystem +# + +# This library is not relocatable; it is built in its source +# directory. Reference it with $(srcdir). +LIBAMM = $(srcdir)/lib/oskit/amm/libamm.a + +# +# LIBDISASM subsystem +# +LIBDISASM = $(srcdir)/disasm/libdisasm.a + +# +# BOOTTASK subsystem +# +BOOTTASK = pingpong_test +VPATH += boot test/boottask + +CSRC_BOOTTASK = oskit_support.c +CXXSRC_BOOTTASK = bootstrap-boottask.cc +OBJ_BOOTTASK = boot.o + +NOPROFILE += oskit_support bootstrap + +# +# TESTTASK subsystem +# +TESTTASK = pingpong +VPATH += test/testtask + +CSRC_TESTTASK = pingpong.c +OBJ_TESTTASK = crt0-user.o diff --git a/kernel/fiasco/src/test/pingpong/kernel_thread-test.cpp b/kernel/fiasco/src/test/pingpong/kernel_thread-test.cpp new file mode 100644 index 00000000..8e2e164e --- /dev/null +++ b/kernel/fiasco/src/test/pingpong/kernel_thread-test.cpp @@ -0,0 +1,255 @@ +INTERFACE: + +#include "thread.h" + +class kernel_thread_t : public thread_t +{ +}; + + +IMPLEMENTATION: + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "config.h" +#include "console.h" +#include "space.h" +#include "thread.h" +#include "thread_state.h" +#include "kdb_ke.h" +#include "kmem.h" +#include "kmem_alloc.h" +#include "irq.h" +#include "globals.h" +#include "helping_lock.h" + +// overload allocator -- we cannot allcate by page fault during +// bootstrapping +PUBLIC +void * +kernel_thread_t::operator new(size_t s, threadid_t id) throw() +{ + // call superclass' allocator + void *addr = thread_t::operator new(s, id); + + // explicitly allocate and enter in page table -- we cannot allocate + // by page fault during bootstrapping + if (! kmem_alloc::page_alloc(reinterpret_cast(addr) + & ~PAGE_MASK, + kmem_alloc::zero_fill)) + panic("can't allocate kernel tcb"); + + return addr; +} + +PUBLIC inline NEEDS["kmem.h"] +kernel_thread_t::kernel_thread_t() + : thread_t (// XXX ugly, but OK for now -- perhaps spaces and kmem should be + // inherited from a common super class + const_cast + (reinterpret_cast (kmem::dir())), + &config::kernel_id + ) +{} + +PUBLIC inline +unsigned long * +kernel_thread_t::init_stack() +{ + return kernel_sp; +} + +// the kernel bootstrap routine +PUBLIC +void +kernel_thread_t::bootstrap() +{ + // Initializations done -- helping_lock_t can now use helping lock + helping_lock_t::threading_system_active = true; + + // + // set up my own thread control block + // + state_change (0, Thread_running); + + sched()->set_prio (config::kernel_prio); + sched()->set_mcp (config::kernel_mcp); + sched()->set_timeslice (config::default_time_slice); + sched()->set_ticks_left (config::default_time_slice); + + present_next = present_prev = this; + ready_next = ready_prev = this; + + // + // set up class variables + // + for (int i = 0; i < 256; i++) prio_next[i] = prio_first[i] = 0; + prio_next[config::kernel_prio] = prio_first[config::kernel_prio] = this; + prio_highest = config::kernel_prio; + + timeslice_ticks_left = config::default_time_slice; + timeslice_owner = this; + + // + // install our slow trap handler + // + nested_trap_handler = base_trap_handler; + base_trap_handler = thread_handle_trap; + + // + // initialize FPU + // + set_ts(); // FPU ops -> exception + + // + // initialize interrupts + // + irq_t::lookup(2)->alloc(this, false); // reserve cascade irq + irq_t::lookup(8)->alloc(this, false); // reserve timer irq + + pic_enable_irq(2); // allow cascaded irqs + + // set up serial console + if (! strstr(kmem::cmdline(), " -I-") + && !strstr(kmem::cmdline(), " -irqcom")) + { + int com_port = console::serial_com_port; + int com_irq = com_port & 1 ? 4 : 3; + + irq_t::lookup(com_irq)->alloc(this, false); // the remote-gdb interrupt + pic_enable_irq(com_irq); + + // for some reason, we have to re-enable the com irq here + if (config::serial_esc) + com_cons_enable_receive_interrupt(); + } + + // initialize the profiling timer + bool user_irq0 = strstr(kmem::cmdline(), "irq0"); + + if (config::profiling) + { + if (user_irq0) + { + kdb_ke("options `-profile' and `-irq0' don't mix " + "-- disabling `-irq0'"); + } + irq_t::lookup(0)->alloc(this, false); + + profile::init(); + + if (strstr(kmem::cmdline(), " -profstart")) + profile::start(); + } + else if (! user_irq0) + irq_t::lookup(0)->alloc(this, false); // reserve irq0 even though + // we don't use it + + // + // set up timer interrupt (~ 1ms) + // + while (rtcin(RTC_STATUSA) & RTCSA_TUP) ; // wait till RTC ready + rtcout(RTC_STATUSA, RTCSA_DIVIDER | RTCSA_1024); // 1024 Hz + // set up 1024 Hz interrupt + rtcout(RTC_STATUSB, rtcin(RTC_STATUSB) | RTCSB_PINTR | RTCSB_SQWE); + rtcin(RTC_INTR); // reset + + pic_enable_irq(8); // allow this interrupt + + // + // set PCE-Flag in CR4 to enable read of performace measurement counters + // in usermode. PMC were introduced in Pentium MMX and PPro processors. + // + #ifndef CPUF_MMX + #define CPUF_MMX 0x00800000 + #endif + if(strncmp(cpu.vendor_id, "GenuineIntel", 12) == 0 + && (cpu.family == CPU_FAMILY_PENTIUM_PRO || + cpu.feature_flags & CPUF_MMX)) + { + set_cr4(get_cr4() | CR4_PCE); + } + + // + // allow the boot task to create more tasks + // + for (unsigned i = config::boot_taskno + 1; + i < space_index_t::max_space_number; + i++) + { + check(space_index_t(i).set_chief(space_index(), + space_index_t(config::boot_taskno))); + } + + // + // create sigma0 + // + + // sigma0's chief is the boot task + space_index_t(config::sigma0_id.id.task). + set_chief(space_index(), space_index_t(config::sigma0_id.id.chief)); + + sigma0 = new space_t(config::sigma0_id.id.task); + sigma0_thread = + new (&config::sigma0_id) thread_t (sigma0, &config::sigma0_id, + config::sigma0_prio, + config::sigma0_mcp); + + // push address of kernel info page to sigma0's stack + vm_offset_t esp = kmem::info()->sigma0_esp; + + * reinterpret_cast(kmem::phys_to_virt(--esp)) + = kmem::virt_to_phys(kmem::info()); + + sigma0_thread->initialize(kmem::info()->sigma0_eip, esp, + 0, 0); + + // + // create the boot task + // + + // the boot task's chief is the boot task itself + space_index_t(config::boot_id.id.task). + set_chief(space_index(), space_index_t(config::boot_id.id.chief)); + + space_t *boot = new space_t(config::boot_id.id.task); + thread_t *boot_thread + = new (&config::boot_id) thread_t (boot, &config::boot_id, + config::boot_prio, + config::boot_mcp); + + boot_thread->initialize(0x200000, + 0x200000, + sigma0_thread, 0); + + // + // the idle loop + // + for (;;) + { + // printf("I"); + + sti(); // enable irqs, otherwise idling is fatal + + if (config::hlt_works_ok) + asm("hlt"); // stop the CPU, waiting for an int + + while (ready_next != this) // are there any other threads ready? + schedule(); + } +} + +// A C interface for bootstrap, callable from assembly code +extern "C" +void call_bootstrap(kernel_thread_t *t) +{ + t->bootstrap(); +} diff --git a/kernel/fiasco/src/test/pingpong/pingpong.c b/kernel/fiasco/src/test/pingpong/pingpong.c new file mode 100644 index 00000000..102e77c6 --- /dev/null +++ b/kernel/fiasco/src/test/pingpong/pingpong.c @@ -0,0 +1,14 @@ +#include +#include +#include + +/* #include */ +/* #include */ +#include + +int main(int argc, char **argv) +{ + printf("testing short ipc with small address spaces:\n"); + exit(0); +} + diff --git a/kernel/fiasco/src/test/space/Makefile b/kernel/fiasco/src/test/space/Makefile new file mode 100644 index 00000000..663f0736 --- /dev/null +++ b/kernel/fiasco/src/test/space/Makefile @@ -0,0 +1,7 @@ +srcdir = ../.. + +all: + +%: + $(MAKE) -I $(srcdir) -I .. -f $(srcdir)/Makefile \ + srcdir=$(srcdir) MODULES_FILE=Modules.space $@ diff --git a/kernel/fiasco/src/test/space/Modules.space b/kernel/fiasco/src/test/space/Modules.space new file mode 100644 index 00000000..d9d3911e --- /dev/null +++ b/kernel/fiasco/src/test/space/Modules.space @@ -0,0 +1,23 @@ +# -*- makefile -*- + +XARCH=ia32 + +SUBSYSTEMS = SYSTEM_UNDER_TEST ABI TYPES + +SYSTEM_UNDER_TEST = space.t +INTERFACES_SYSTEM_UNDER_TEST = space space_context space_index config +INTERFACES_ABI = l4_types l4_ipc l4_syscalls kip +INTERFACES_TYPES = types +config_IMPL = config config-arch +space_IMPL = space space-arch +space_context_IMPL = space_context space_context-arch +VPATH += kern kern/$(XARCH) abi/$(XARCH) abi types/$(XARCH) types +PRIVATE_INCDIR += kern lib/kern/include + +PRIVATE_INCDIR += test/wrappers/auto +LIBS = ../wrappers/libwrappers.a + +l4_syscalls_IMPL = l4_syscalls-arch l4_syscalls +l4_types_IMPL = l4_types-arch l4_types +l4_ipc_IMPL = l4_ipc-arch l4_ipc +types_IMPL = types-arch types diff --git a/kernel/fiasco/src/test/space/space.t.cc b/kernel/fiasco/src/test/space/space.t.cc new file mode 100644 index 00000000..a4b10af8 --- /dev/null +++ b/kernel/fiasco/src/test/space/space.t.cc @@ -0,0 +1,136 @@ +#include +#include +#include + +using namespace std; + +#include +#include "space.h" + +int main() +{ + // + // Make task 4 the chief of task 5 + // + assert (space_index_t (5).lookup () == 0); + assert (space_index_t (5).chief () == 0); + + assert (space_index_t (5).set_chief (space_index_t(0), space_index_t(4))); + + assert (space_index_t (5).lookup () == 0); + assert (space_index_t (5).chief () == 4); + + // + // Create task 5. Make sure it is registered correctly. + // + space_t *s = new space_t (5); + + assert (s); + assert (space_index_t (5).lookup () == s); + assert (s->space() == 5); + assert (s->chief() == 4); + + // + // Create a 4K mapping, try flushing attributes + // + vm_offset_t phys, size; + unsigned attribs; + assert (s->v_lookup (0xf000, &phys, &size, &attribs) == false); + + assert (s->v_insert (0x1000, 0xf000, PAGE_SIZE, + space_t::Page_user_accessible|space_t::Page_writable) + == space_t::Insert_ok); + + assert (s->v_lookup (0xf000, &phys, &size, &attribs) == true); + assert (phys == 0x1000); + assert (size == PAGE_SIZE); + assert (attribs == (space_t::Page_user_accessible|space_t::Page_writable)); + + // Flush write permission + assert (s->v_delete (0xf000, PAGE_SIZE, space_t::Page_writable)); + + assert (s->v_lookup (0xf000, &phys, &size, &attribs) == true); + assert (phys == 0x1000); + assert (size == PAGE_SIZE); + assert (attribs == space_t::Page_user_accessible); + + // Remap write permission + assert (s->v_insert (0x1000, 0xf000, PAGE_SIZE, + space_t::Page_user_accessible|space_t::Page_writable) + == space_t::Insert_warn_attrib_upgrade); + + assert (s->v_lookup (0xf000, &phys, &size, &attribs) == true); + assert (phys == 0x1000); + assert (size == PAGE_SIZE); + assert (attribs == (space_t::Page_user_accessible|space_t::Page_writable)); + + // Flush mapping + assert (s->v_delete (0xf000, PAGE_SIZE)); + + assert (s->v_lookup (0xf000, &phys, &size, &attribs) == false); + + // + // Try superpages + // + + // We expect a superpage mapping in this region to fail because a + // 2nd-level page table exists (even though we emptied it again in + // the previous step). This assertion could be wrong if a more + // clever space_t implementation was used. + assert (s->v_lookup (0x0, &phys, &size, &attribs) == false); + assert (size == PAGE_SIZE); + + assert (s->v_insert (0x800000, 0x0, SUPERPAGE_SIZE, + space_t::Page_user_accessible|space_t::Page_writable) + == space_t::Insert_err_exists); + + assert (s->v_lookup (0x0, &phys, &size, &attribs) == false); + assert (size == PAGE_SIZE); + + // Try a clear entry + assert (s->v_lookup (0x400000, &phys, &size, &attribs) == false); + assert (size == SUPERPAGE_SIZE); + + assert (s->v_insert (0x800000, 0x400000, SUPERPAGE_SIZE, + space_t::Page_user_accessible|space_t::Page_writable) + == space_t::Insert_ok); + + assert (s->v_lookup (0x400000, &phys, &size, &attribs) == true); + assert (phys == 0x800000); + assert (size == SUPERPAGE_SIZE); + assert (attribs == (space_t::Page_user_accessible|space_t::Page_writable)); + + // Flush write permission + assert (s->v_delete (0x400000, SUPERPAGE_SIZE, space_t::Page_writable)); + + assert (s->v_lookup (0x400000, &phys, &size, &attribs) == true); + assert (phys == 0x800000); + assert (size == SUPERPAGE_SIZE); + assert (attribs == space_t::Page_user_accessible); + + // Remap write permission + assert (s->v_insert (0x800000, 0x400000, SUPERPAGE_SIZE, + space_t::Page_user_accessible|space_t::Page_writable) + == space_t::Insert_warn_attrib_upgrade); + + assert (s->v_lookup (0x400000, &phys, &size, &attribs) == true); + assert (phys == 0x800000); + assert (size == SUPERPAGE_SIZE); + assert (attribs == (space_t::Page_user_accessible|space_t::Page_writable)); + + // Flush mapping + assert (s->v_delete (0x400000, SUPERPAGE_SIZE)); + + assert (s->v_lookup (0x400000, &phys, &size, &attribs) == false); + + // + // Delete task 5; ensure it is unregistered. + // + delete s; + assert (space_index_t (5).lookup () == 0); + + cerr << "OK" << endl; + + return 0; +} + diff --git a/kernel/fiasco/src/test/space/space.t.out.verify b/kernel/fiasco/src/test/space/space.t.out.verify new file mode 100644 index 00000000..e69de29b diff --git a/kernel/fiasco/src/test/sysenterexit/Makefile b/kernel/fiasco/src/test/sysenterexit/Makefile new file mode 100644 index 00000000..cffd4771 --- /dev/null +++ b/kernel/fiasco/src/test/sysenterexit/Makefile @@ -0,0 +1,7 @@ +srcdir = ../.. + +all: + +%: + $(MAKE) -I $(srcdir) -I .. -f $(srcdir)/Makefile \ + srcdir=$(srcdir) $@ diff --git a/kernel/fiasco/src/test/sysenterexit/Modules b/kernel/fiasco/src/test/sysenterexit/Modules new file mode 100644 index 00000000..a9880eff --- /dev/null +++ b/kernel/fiasco/src/test/sysenterexit/Modules @@ -0,0 +1,138 @@ +# -*- makefile -*- + +SUBSYSTEMS = BOOTTASK TESTTASK KERNEL CRT0 LIBK LIBAMM TCBOFFSET + +ifneq ($(wildcard $(srcdir)/disasm),) +SUBSYSTEMS += LIBDISASM +endif + +# +# KERNEL subsystem +# +KERNEL = fiasco.image +KERNEL_EXTRA = Symbols +VPATH += kern +PRIVATE_INCDIR += kern + +INTERFACES_KERNEL = mapdb region \ + space_context space space_index space_index_util \ + stack irq_init kmem kmem_alloc slab_cache kmem_slab_simple kmem_slab \ + switch_lock thread_lock helping_lock kernel_lock timer \ + thread_state sched context threadid thread_regs sender receiver \ + thread kernel_thread thread_util \ + map_util irq startup console paranoia globals \ + kdb kdb_ke jdb_symbol jdb_lines jdb_trace jdb_tbuf jdb_bp jdb_thread_list \ + jdb_tsc jdb apic watchdog rtc main config logger + +thread_IMPL = thread thread-syscall thread-list thread-ipc thread-msg \ + thread-log + +kernel_thread_IMPL = kernel_thread kernel_thread-boottask + +#ASSRC_KERNEL = entry.S shortcut.S debug.S +ASSRC_KERNEL = entry.S shortcut-classic.S shortcut2.S debug.S + +### When testing with test threads, uncomment the following: +# +VPATH += kern-test +PRIVATE_INCDIR += kern-test +# +INTERFACES_KERNEL += generic_test_thread test_thread \ + node cpu back_trace cpu_guard types +# +node_IMPL = node node-up +cpu_IMPL = cpu cpu-perf cpu-perfp4 +config_IMPL = config config-test +context_IMPL = context context-test +# +#kernel_thread_IMPL := $(filter-out kernel_thread-std,$(kernel_thread_IMPL)) \ +# kernel_thread-test + +# +## Replace this definition with your own test thread. +#test_thread_IMPL = test_thread-test25 # switch to latency +#test_thread_IMPL = test_thread-test26 # trace for thread switch +#test_thread_IMPL = test_thread-test33 # sysenter/exit shortcut ipc +#test_thread_IMPL = test_thread-test37 # PEBS +#test_thread_IMPL = test_thread-test39 # lock overheadd +#test_thread_IMPL = test_thread-test40 # shortcut +#test_thread_IMPL = test_thread-test42 # kernel entry latency +#test_thread_IMPL = test_thread-test43 # scheduling latency +#test_thread_IMPL = test_thread-test44 # semaphore bench helper +test_thread_IMPL = test_thread-test45 # sysenter/exit +# +### End of test-thread section + +# +# CRT0 subsystem +# +CRT0 = crt0.o + +ASSRC_CRT0 = crt0.S + +# +# BOOT subsystem +# +BOOT = main +VPATH += boot + +CSRC_BOOT = oskit_support.c +CXXSRC_BOOT = bootstrap.cc +ASSRC_BOOT = boot.S + +NOPROFILE += oskit_support bootstrap + +# +# LIBK subsystem +# +LIBK = libk.a +VPATH += lib +PRIVATE_INCDIR += . lib/oskit + +INTERFACES_LIBK = atomic lock_guard profile uuencode gmon unistd + +CSRC_LIBK = com_cons.c + +NOPROFILE += profile gmon + +# +# LIBAMM subsystem +# + +# This library is not relocatable; it is built in its source +# directory. Reference it with $(srcdir). +LIBAMM = $(srcdir)/lib/oskit/amm/libamm.a + +# +# LIBDISASM subsystem +# +LIBDISASM = $(srcdir)/disasm/libdisasm.a + +# +# TCBOFFSET subsystem +# +TCBOFFSET = tcboffset.h +CXXSRC_TCBOFFSET = genoffset.cc +#TCBOFFSET_EXTRA_FLAGS = -DFIASCO_SMP + + +# +# BOOTTASK subsystem +# +BOOTTASK = sysenterexit_test +VPATH += boot test/boottask + +CSRC_BOOTTASK = oskit_support.c +CXXSRC_BOOTTASK = bootstrap-boottask.cc +OBJ_BOOTTASK = boot.o + +NOPROFILE += oskit_support bootstrap + +# +# TESTTASK subsystem +# +TESTTASK = sysenterexit +VPATH += test/testtask + +CSRC_TESTTASK = sysenterexit.c +OBJ_TESTTASK = crt0-user.o diff --git a/kernel/fiasco/src/test/sysenterexit/sysenterexit.c b/kernel/fiasco/src/test/sysenterexit/sysenterexit.c new file mode 100644 index 00000000..2fdc736a --- /dev/null +++ b/kernel/fiasco/src/test/sysenterexit/sysenterexit.c @@ -0,0 +1,24 @@ + +// +// user level code for test_thread-test45 +// + +int +main(void) +{ + for(;;) + { + asm volatile("1: \n" + " movl %eax, %edi \n" + " rdtsc \n" + " movl %eax, %esi \n" + " pushl $0 \n" + " pushl $2f \n" + " movl %esp, %ecx \n" + " rdtsc \n" + " sysenter \n" + "2: \n" + " jmp 1b \n"); + } + return 0; +} diff --git a/kernel/fiasco/src/test/testtask/crt0-user.S b/kernel/fiasco/src/test/testtask/crt0-user.S new file mode 100644 index 00000000..cde587fa --- /dev/null +++ b/kernel/fiasco/src/test/testtask/crt0-user.S @@ -0,0 +1,35 @@ +#define __ASSEMBLY__ +#include + + .text + +ENTRY(__crt_dummy__) +ENTRY(_start) +ENTRY(start) + leal stack,%esp + jmp SYMBOL_NAME(main) + +ENTRY(__main) + ret + + /* MultiBoot header - see multiboot.h. */ +#ifdef __ELF__ + .align 4 +#else /* ! __ELF__, that mean a.out assembler */ + .align 2 +#endif + +ENTRY(_mb_header) + .long 0x1BADB002 /* magic */ + .long 0x00010000 /* flags: AOUT_KLUDGE */ + .long - 0x00010000 - 0x1BADB002 + .long SYMBOL_NAME(_mb_header) /* header_addr */ + .long SYMBOL_NAME(__crt_dummy__) /* load_addr */ + .long _edata /* load_end_addr */ + .long _end /* bss_end_addr */ + .long SYMBOL_NAME(_start) /* entry */ + + .bss + + .space 1024 +stack: diff --git a/kernel/fiasco/src/test/trace/Makefile b/kernel/fiasco/src/test/trace/Makefile new file mode 100644 index 00000000..5ccb020d --- /dev/null +++ b/kernel/fiasco/src/test/trace/Makefile @@ -0,0 +1,10 @@ +PKGDIR ?= .. +L4DIR ?= $(PKGDIR)/../../../.. + +TARGET = trace +MODE = sigma0 +DEFAULT_RELOC = 0x00A00000 + +SRC_C = trace.c + +include $(L4DIR)/mk/prog.mk diff --git a/kernel/fiasco/src/test/trace/README b/kernel/fiasco/src/test/trace/README new file mode 100644 index 00000000..fa8d2f62 --- /dev/null +++ b/kernel/fiasco/src/test/trace/README @@ -0,0 +1,3 @@ +Simple program to demonstrate Fiasco's feature to export the trace buffer +into userland. + diff --git a/kernel/fiasco/src/test/trace/trace.c b/kernel/fiasco/src/test/trace/trace.c new file mode 100644 index 00000000..98a0c999 --- /dev/null +++ b/kernel/fiasco/src/test/trace/trace.c @@ -0,0 +1,218 @@ +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +typedef struct __attribute__((packed)) +{ + unsigned number; // event number + unsigned eip; // instruction pointer + l4_threadid_t tid; // thread id + unsigned long long tsc; // time stamp counter + unsigned long long pmc; // performance counter value + union __attribute__((packed)) // data for each type of entry + { + struct __attribute__((packed)) + { + // logged ipc + unsigned eax, edx, ebx, ebp; + l4_threadid_t dest; + } ipc; + struct __attribute__((packed)) + { + // logged ipc result + unsigned eax, edx, ebx; + unsigned orig_eax, orig_ebp; + } ipc_res; + struct __attribute__((packed)) + { + // traced ipc + unsigned long long send_tsc; + l4_threadid_t send_esi_edi; + l4_threadid_t recv_esi_edi; + l4_msgdope_t dope; + unsigned char send_desc, recv_desc; + } ipc_trace; + struct __attribute__((packed)) + { + // logged page fault + unsigned pfa; + unsigned err; + } pf; + struct __attribute__((packed)) + { + // logged kernel event + char msg[31]; + } ke; + struct __attribute__((packed)) + { + // logged kernel event plus register content + unsigned eax, edx, ecx; + char msg[19]; + } ke_reg; + struct __attribute__((packed)) + { + // logged unmap operation + l4_fpage_t fpage; + unsigned mask; + int result; + } unmap; + struct __attribute__((packed)) + { + unsigned lthread; + unsigned old_esp; + unsigned new_esp; + unsigned old_eip; + unsigned new_eip; + } ex_regs; + struct + { + // logged short-cut ipc failed + unsigned eax, ebp, ecx; + l4_threadid_t dest; + char is_irq, snd_lst, dst_ok, dst_lck; + } ipc_sfl; + struct + { + // logged context switch + l4_threadid_t dest; + unsigned kernel_eip; + unsigned long *kernel_sp; + } ctx_sw; + } m; + char type; // type of entry +} tb_entry_t; + +static int ticker_thread_stack[1024]; +static l4_tracebuffer_status_t *tbuf; +static tb_entry_t *tbuffer[2]; + +static void +init_tbuf(void) +{ + // request address of trace buffer from kernel + if (!(tbuf = fiasco_get_tbuf_status())) + enter_kdebug("no kernel trace buffer"); + + printf("buf0: %08x, size0: %08x; buf1: %08x, size1: %08x\n", + tbuf->tracebuffer0, tbuf->size0, + tbuf->tracebuffer1, tbuf->size1); + + tbuffer[0] = (tb_entry_t*)tbuf->tracebuffer0; + tbuffer[1] = (tb_entry_t*)tbuf->tracebuffer1; +} + +// do something we can log +static void +ticker_thread(void) +{ + int i; + enter_kdebug("*#I*"); + enter_kdebug("*#IrT7.1"); + for (;;) + { + for (i=0; i<100; i++) + { + l4_sleep(10); + } + } +} + +static void +create_ticker_thread(void) +{ + create_thread(l4_myself().id.lthread+1, + ticker_thread, + &ticker_thread_stack[1024]); +} + +// wait for virtual irq which is released on trace buffer overflow +static void +wait_for_virq(void) +{ + int error; + l4_msgdope_t result; + l4_threadid_t virq_id; + unsigned msg0, msg1; + + virq_id.lh.high = 0; + virq_id.lh.low = 17; + + if ((error = l4_i386_ipc_receive(virq_id, + L4_IPC_SHORT_MSG, &msg0, &msg1, + L4_IPC_TIMEOUT(0,0,0,1,0,0), + &result)) != L4_IPC_RETIMEOUT) + { + printf("Error %02x allocating interrupt\n", error); + return; + } + + for (;;) + { + int i, j; + int old_version0 = tbuf->version0; + int old_version1 = tbuf->version1; + tb_entry_t *tbe; + + printf("Waiting for interrupts..."); + error = l4_i386_ipc_receive(virq_id, L4_IPC_SHORT_MSG, + &msg0, &msg1, + L4_IPC_NEVER, &result); + + printf("Received interrupt\n"); + + printf("version0: %08x, version1: %08x\n", + tbuf->version0, tbuf->version1); + + if (tbuf->version0 != old_version0) + { + j=tbuf->size0/sizeof(tb_entry_t); + tbe = tbuffer[0]; + } + else + { + j=tbuf->size1/sizeof(tb_entry_t); + tbe = tbuffer[1]; + } + + old_version0 = tbuf->version0; + old_version1 = tbuf->version1; + + for(i=0; iversion0) + || (old_version1 != tbuf->version1)) + printf("version changed! version0: %08x, version1: %08x\n", + tbuf->version0, tbuf->version1); + } +} + +int +main(int argc, char **argv) +{ + init_tbuf(); + + create_ticker_thread(); + + wait_for_virq(); + + return 0; +} + diff --git a/kernel/fiasco/src/test/unit/map_util_t.cpp b/kernel/fiasco/src/test/unit/map_util_t.cpp new file mode 100644 index 00000000..7f03fe23 --- /dev/null +++ b/kernel/fiasco/src/test/unit/map_util_t.cpp @@ -0,0 +1,431 @@ +IMPLEMENTATION: + +#include +#include +#include +#include + +using namespace std; + +#include "map_util.h" +#include "space.h" +#include "globals.h" +#include "config.h" + +#include "boot_info.h" +#include "cpu.h" +#include "config.h" +#include "kip_init.h" +#include "kmem.h" +#include "kmem_alloc.h" +#include "per_cpu_data_alloc.h" +#include "pic.h" +#include "static_init.h" +#include "usermode.h" +#include "vmem_alloc.h" +#include "mem_space_sigma0.h" + +IMPLEMENTATION: + +typedef L4_fpage Test_fpage; + +class Test_space : public Space +{ +public: + Test_space (Ram_quota *rq) + : Space (Space::Default_factory(), rq, L4_fpage::mem(0x1200000, Config::PAGE_SHIFT)) + {} + + void* operator new (size_t s) + { return malloc (s); } + + void operator delete (void *p) + { ::free (p); } +}; + +class Timeout; + +DEFINE_PER_CPU Per_cpu timeslice_timeout; +STATIC_INITIALIZER_P(init, STARTUP_INIT_PRIO); +STATIC_INITIALIZER_P(init2, POST_CPU_LOCAL_INIT_PRIO); + +static void init() +{ + Usermode::init(0); + Boot_info::init(); + Kip_init::setup_ux(); + Kmem_alloc::base_init(); + Kip_init::init(); + Kmem_alloc::init(); + + // Initialize cpu-local data management and run constructors for CPU 0 + Per_cpu_data::init_ctors(); + Per_cpu_data_alloc::alloc(0); + Per_cpu_data::run_ctors(0); + +} + +static void init2() +{ + Cpu::init_global_features(); + Config::init(); + Kmem::init_mmu(*Cpu::boot_cpu()); + Vmem_alloc::init(); + Pic::init(); +} + +static Ram_quota rq; + +struct Sigma0_space_factory +{ + static void create(Mem_space *v, Ram_quota *q) + { new (v) Mem_space_sigma0(q); } + + template< typename S > + static void create(S *v) + { new (v) S(); } + +}; + +int main() +{ + // + // Create tasks + // + Space *sigma0 = new Space (Sigma0_space_factory(), &rq, L4_fpage::mem(0x1200000, Config::PAGE_SHIFT)); + + init_mapdb_mem(sigma0); + + Test_space *server = new Test_space (&rq); + assert (server); + Test_space *client = new Test_space (&rq); + assert (client); + Test_space *client2 = new Test_space (&rq); + assert (client2); + + // + // Manipulate mappings. + // + Mapdb* mapdb = mapdb_instance(); + + Mem_space::Phys_addr phys; + Virt_size size; + unsigned page_attribs; + Mapping *m; + Mapdb::Frame frame; + + // + // s0 [0x10000] -> server [0x1000] + // + assert (server->mem_space()->v_lookup (Virt_addr(0x1000), &phys, &size, &page_attribs) + == false); + Reap_list reap; + fpage_map (sigma0, + Test_fpage::mem(0x10000, Config::PAGE_SHIFT, L4_fpage::RWX), + server, + L4_fpage::all_spaces(), + 0x1000, &reap); + + assert (server->mem_space()->v_lookup (Virt_addr(0x1000), &phys, &size, &page_attribs) + == true); + assert (size == Virt_size(Config::PAGE_SIZE)); + assert (phys == Virt_addr(0x10000)); + assert (page_attribs == (Mem_space::Page_writable + | Mem_space::Page_user_accessible)); + + assert (mapdb->lookup (sigma0, Virt_addr(0x10000), Virt_addr(0x10000), &m, &frame)); + print_node (m, frame); + mapdb->free (frame); + + // + // s0 [0/superpage] -> server [0] -> should map many 4K pages and + // overmap previous mapping + // + assert (server->mem_space()->v_lookup (Virt_addr(0), &phys, &size, &page_attribs) + == false); + + fpage_map (sigma0, + L4_fpage::mem(0, Config::SUPERPAGE_SHIFT, L4_fpage::RX), + server, + L4_fpage::all_spaces(), + 0, &reap); + + assert (server->mem_space()->v_lookup (Virt_addr(0), &phys, &size, &page_attribs) + == true); + assert (size == Virt_size(Config::PAGE_SIZE)); // and not SUPERPAGE_SIZE! + assert (phys == Virt_addr(0)); + assert (page_attribs == Mem_space::Page_user_accessible); + + assert (mapdb->lookup (sigma0, Virt_addr(0), Virt_addr(0), &m, &frame)); + print_node (m, frame); + mapdb->free (frame); + + // previous mapping still there? + + assert (server->mem_space()->v_lookup (Virt_addr(0x1000), &phys, &size, &page_attribs) + == true); + assert (size == Virt_size(Config::PAGE_SIZE)); + // Previously, overmapping did not work and was ignored, so the + // lookup yielded the previously established mapping: + // assert (phys == 0x10000); + // assert (page_attribs == (Mem_space::Page_writable | Mem_space::Page_user_accessible)); + // Now, the previous mapping should have been overwritten: + assert (phys == Virt_addr(0x1000)); + assert (page_attribs == Mem_space::Page_user_accessible); + + // mapdb entry -- tree should now contain another mapping + // s0 [0x10000] -> server [0x10000] + assert (mapdb->lookup (sigma0, Virt_addr(0x10000), Virt_addr(0x10000), &m, &frame)); + print_node (m, frame, 0x10000, 0x11000); + mapdb->free (frame); + + // + // Partially unmap superpage s0 [0/superpage] + // + assert (server->mem_space()->v_lookup (Virt_addr(0x101000), &phys, &size, &page_attribs) + == true); + assert (size == Virt_size(Config::PAGE_SIZE)); + assert (phys == Virt_addr(0x101000)); + assert (page_attribs == Mem_space::Page_user_accessible); + + fpage_unmap (sigma0, + Test_fpage::mem(0x100000, Config::SUPERPAGE_SHIFT - 2, L4_fpage::RWX), + L4_map_mask(0) /*full unmap, not me too)*/, reap.list()); + + assert (mapdb->lookup (sigma0, Virt_addr(0x0), Virt_addr(0x0), &m, &frame)); + print_node (m, frame); + mapdb->free (frame); + + assert (! server->mem_space()->v_lookup (Virt_addr(0x101000), &phys, &size, + &page_attribs) + == true); + + // + // s0 [4M/superpage] -> server [8M] + // + assert (server->mem_space()->v_lookup (Virt_addr(0x800000), &phys, &size, &page_attribs) + == false); + + fpage_map (sigma0, + Test_fpage::mem(0x400000, Config::SUPERPAGE_SHIFT, L4_fpage::RWX), + server, + L4_fpage::mem(0x800000, Config::SUPERPAGE_SHIFT), + 0, &reap); + + assert (server->mem_space()->v_lookup (Virt_addr(0x800000), &phys, &size, &page_attribs) + == true); + assert (size == Virt_size(Config::SUPERPAGE_SIZE)); + assert (phys == Virt_addr(0x400000)); + assert (page_attribs == (Mem_space::Page_writable + | Mem_space::Page_user_accessible)); + + assert (mapdb->lookup (sigma0, Virt_addr(0x400000), Virt_addr(0x400000), &m, &frame)); + print_node (m, frame); + mapdb->free (frame); + + // + // server [8M+4K] -> client [8K] + // + assert (client->mem_space()->v_lookup (Virt_addr(0x8000), &phys, &size, &page_attribs) + == false); + + fpage_map (server, + Test_fpage::mem(0x801000, Config::PAGE_SHIFT, L4_fpage::RWX), + client, + L4_fpage::mem(0, L4_fpage::Whole_space), + 0x8000, &reap); + + assert (client->mem_space()->v_lookup (Virt_addr(0x8000), &phys, &size, &page_attribs) + == true); + assert (size == Virt_size(Config::PAGE_SIZE)); + assert (phys == Virt_addr(0x401000)); + assert (page_attribs == (Mem_space::Page_writable + | Mem_space::Page_user_accessible)); + + // Previously, the 4K submapping is attached to the Sigma0 parent. + // Not any more. + + assert (mapdb->lookup (sigma0, Virt_addr(0x400000), Virt_addr(0x400000), &m, &frame)); + print_node (m, frame); + mapdb->free (frame); + + // + // Overmap a read-only page. The writable attribute should not be + // flushed. + // + fpage_map (server, + Test_fpage::mem(0x801000, Config::PAGE_SHIFT, L4_fpage::RX), + client, + L4_fpage::mem(0, L4_fpage::Whole_space), + 0x8000, &reap); + + assert (client->mem_space()->v_lookup (Virt_addr(0x8000), &phys, &size, &page_attribs) + == true); + assert (size == Virt_size(Config::PAGE_SIZE)); + assert (phys == Virt_addr(0x401000)); + assert (page_attribs == (Mem_space::Page_writable + | Mem_space::Page_user_accessible)); + +#if 0 // no selective unmap anymore + // + // Try selective unmap + // + fpage_map (server, + Test_fpage::mem(0x801000, Config::PAGE_SHIFT, L4_fpage::RWX), + client2, + L4_fpage::all_spaces(), + 0x1000, &reap); + + assert (client2->mem_space()->v_lookup (0x1000, &phys, &size, &page_attribs) + == true); + assert (size == Config::PAGE_SIZE); + assert (phys == 0x401000); + assert (page_attribs == (Mem_space::Page_writable + | Mem_space::Page_user_accessible)); + + assert (mapdb->lookup (sigma0, 0x400000, 0x400000, &m, &frame)); + print_node (m, frame); + mapdb->free (frame); + + fpage_unmap (server, + Test_fpage (false, true, Config::PAGE_SHIFT, 0x801000), + mask(false, client2->id(), true, false, false)); + + // Page should have vanished in client2's space, but should still be + // present in client's space. + assert (client2->mem_space()->v_lookup (0x1000, &phys, &size, &page_attribs) + == false); + assert (client->mem_space()->v_lookup (0x8000, &phys, &size, &page_attribs) + == true); + assert (size == Config::PAGE_SIZE); + assert (phys == 0x401000); + assert (page_attribs == (Mem_space::Page_writable + | Mem_space::Page_user_accessible)); + + assert (mapdb->lookup (sigma0->id(), 0x400000, 0x400000, &m, &frame)); + print_node (m, frame); + mapdb->free (frame); +#endif + cerr << "... "; + + + // + // Try some Accessed / Dirty flag unmaps + // + + // touch page in client + assert (client->mem_space()->v_insert (Virt_addr(0x401000), Virt_addr(0x8000), Virt_size(Config::PAGE_SIZE), + Mem_space::Page_dirty | Mem_space::Page_referenced) + == Mem_space::Insert_warn_attrib_upgrade); + + assert (client->mem_space()->v_lookup (Virt_addr(0x8000), &phys, &size, &page_attribs) + == true); + assert (size == Virt_size(Config::PAGE_SIZE)); + assert (phys == Virt_addr(0x401000)); + assert (page_attribs == (Mem_space::Page_writable + | Mem_space::Page_user_accessible + | Mem_space::Page_dirty | Mem_space::Page_referenced)); + // reset dirty from server + assert (fpage_unmap (server, + Test_fpage::mem(0x801000, Config::PAGE_SHIFT), + L4_map_mask(0), reap.list() + /*no_unmap + reset_refs*/) + == Mem_space::Page_referenced | Mem_space::Page_dirty); + + assert (client->mem_space()->v_lookup (Virt_addr(0x8000), &phys, &size, &page_attribs) + == true); + assert (size == Virt_size(Config::PAGE_SIZE)); + assert (phys == Virt_addr(0x401000)); + assert (page_attribs == (Mem_space::Page_writable + | Mem_space::Page_user_accessible)); // Page_dirty | Page_referecned is gone... + + assert (server->mem_space()->v_lookup (Virt_addr(0x801000), &phys, &size, &page_attribs) + == true); + assert (size == Virt_size(Config::SUPERPAGE_SIZE)); + assert (phys == Virt_addr(0x400000)); + assert (page_attribs == (Mem_space::Page_writable + | Mem_space::Page_user_accessible + | Mem_space::Page_dirty | Mem_space::Page_referenced)); // ...and went here + + // flush dirty and accessed from server + assert (fpage_unmap (server, + Test_fpage::mem(0x800000, Config::SUPERPAGE_SHIFT), + L4_map_mask(0x80000000), reap.list()) + == Mem_space::Page_dirty | Mem_space::Page_referenced); + + assert (client->mem_space()->v_lookup (Virt_addr(0x8000), &phys, &size, &page_attribs) + == true); + assert (size == Virt_size(Config::PAGE_SIZE)); + assert (phys == Virt_addr(0x401000)); + assert (page_attribs == (Mem_space::Page_writable + | Mem_space::Page_user_accessible)); // dirty/ref gone + + assert (server->mem_space()->v_lookup (Virt_addr(0x800000), &phys, &size, &page_attribs) + == true); + assert (size == Virt_size(Config::SUPERPAGE_SIZE)); + assert (phys == Virt_addr(0x400000)); + assert (page_attribs == (Mem_space::Page_writable + | Mem_space::Page_user_accessible)); // dirty/ref gone + + assert (sigma0->mem_space()->v_lookup (Virt_addr(0x400000), &phys, &size, &page_attribs) + == true); + assert (size == Virt_size(Config::SUPERPAGE_SIZE)); + assert (phys == Virt_addr(0x400000)); + // Be a bit more lax in checking Sigma0's address space: It does + // not contain Page_writable / Page_user_accessible flags unless + // they are faulted in. + assert (page_attribs & (Mem_space::Page_dirty | Mem_space::Page_referenced)); + + + // + // Delete tasks + // +#if 0 + // do not do this because the mapping database would crash if + // they has mappings without spaces + delete server; + delete client; + delete client2; + delete sigma0; +#endif + + cerr << "OK" << endl; + + return 0; +} + +static void print_node(Mapping* node, const Mapdb::Frame& frame, + Address va_begin = 0, Address va_end = ~0UL) +{ + assert (node); + + size_t size = Mapdb::shift(frame, node); + + for (Mapdb::Iterator i (frame, node, Virt_addr(va_begin), Virt_addr(va_end)); node;) + { + for (int d = node->depth(); d != 0; d--) + cout << ' '; + + cout << setbase(16) + << "space=0x" << (unsigned long) (node->space()) + << " vaddr=0x" << node->page() << size + << " size=0x" << size; + + if (Mapping* p = node->parent()) + { + cout << " parent=0x" << (unsigned long)p->space() + << " p.vaddr=0x" << p->page().value() << size; + } + + cout << endl; + + node = i; + if (node) + { + size = i.shift(); + ++i; + } + } + cout << endl; +} + diff --git a/kernel/fiasco/src/test/unit/map_util_t.out.verify.v2 b/kernel/fiasco/src/test/unit/map_util_t.out.verify.v2 new file mode 100644 index 00000000..e0d676d8 --- /dev/null +++ b/kernel/fiasco/src/test/unit/map_util_t.out.verify.v2 @@ -0,0 +1,1818 @@ +space=0x2 vaddr=0x0 size=0x400000 + space=0x5 vaddr=0x1000 size=0x1000 parent=0x2 p.vaddr=0x10000 + +space=0x2 vaddr=0x0 size=0x400000 + space=0x5 vaddr=0x0 size=0x1000 parent=0x2 p.vaddr=0x0 + space=0x5 vaddr=0x1000 size=0x1000 parent=0x2 p.vaddr=0x1000 + space=0x5 vaddr=0x2000 size=0x1000 parent=0x2 p.vaddr=0x2000 + space=0x5 vaddr=0x3000 size=0x1000 parent=0x2 p.vaddr=0x3000 + space=0x5 vaddr=0x4000 size=0x1000 parent=0x2 p.vaddr=0x4000 + space=0x5 vaddr=0x5000 size=0x1000 parent=0x2 p.vaddr=0x5000 + space=0x5 vaddr=0x6000 size=0x1000 parent=0x2 p.vaddr=0x6000 + space=0x5 vaddr=0x7000 size=0x1000 parent=0x2 p.vaddr=0x7000 + space=0x5 vaddr=0x8000 size=0x1000 parent=0x2 p.vaddr=0x8000 + space=0x5 vaddr=0x9000 size=0x1000 parent=0x2 p.vaddr=0x9000 + space=0x5 vaddr=0xa000 size=0x1000 parent=0x2 p.vaddr=0xa000 + space=0x5 vaddr=0xb000 size=0x1000 parent=0x2 p.vaddr=0xb000 + space=0x5 vaddr=0xc000 size=0x1000 parent=0x2 p.vaddr=0xc000 + space=0x5 vaddr=0xd000 size=0x1000 parent=0x2 p.vaddr=0xd000 + space=0x5 vaddr=0xe000 size=0x1000 parent=0x2 p.vaddr=0xe000 + space=0x5 vaddr=0xf000 size=0x1000 parent=0x2 p.vaddr=0xf000 + space=0x5 vaddr=0x10000 size=0x1000 parent=0x2 p.vaddr=0x10000 + space=0x5 vaddr=0x11000 size=0x1000 parent=0x2 p.vaddr=0x11000 + space=0x5 vaddr=0x12000 size=0x1000 parent=0x2 p.vaddr=0x12000 + space=0x5 vaddr=0x13000 size=0x1000 parent=0x2 p.vaddr=0x13000 + space=0x5 vaddr=0x14000 size=0x1000 parent=0x2 p.vaddr=0x14000 + space=0x5 vaddr=0x15000 size=0x1000 parent=0x2 p.vaddr=0x15000 + space=0x5 vaddr=0x16000 size=0x1000 parent=0x2 p.vaddr=0x16000 + space=0x5 vaddr=0x17000 size=0x1000 parent=0x2 p.vaddr=0x17000 + space=0x5 vaddr=0x18000 size=0x1000 parent=0x2 p.vaddr=0x18000 + space=0x5 vaddr=0x19000 size=0x1000 parent=0x2 p.vaddr=0x19000 + space=0x5 vaddr=0x1a000 size=0x1000 parent=0x2 p.vaddr=0x1a000 + space=0x5 vaddr=0x1b000 size=0x1000 parent=0x2 p.vaddr=0x1b000 + space=0x5 vaddr=0x1c000 size=0x1000 parent=0x2 p.vaddr=0x1c000 + space=0x5 vaddr=0x1d000 size=0x1000 parent=0x2 p.vaddr=0x1d000 + space=0x5 vaddr=0x1e000 size=0x1000 parent=0x2 p.vaddr=0x1e000 + space=0x5 vaddr=0x1f000 size=0x1000 parent=0x2 p.vaddr=0x1f000 + space=0x5 vaddr=0x20000 size=0x1000 parent=0x2 p.vaddr=0x20000 + space=0x5 vaddr=0x21000 size=0x1000 parent=0x2 p.vaddr=0x21000 + space=0x5 vaddr=0x22000 size=0x1000 parent=0x2 p.vaddr=0x22000 + space=0x5 vaddr=0x23000 size=0x1000 parent=0x2 p.vaddr=0x23000 + space=0x5 vaddr=0x24000 size=0x1000 parent=0x2 p.vaddr=0x24000 + space=0x5 vaddr=0x25000 size=0x1000 parent=0x2 p.vaddr=0x25000 + space=0x5 vaddr=0x26000 size=0x1000 parent=0x2 p.vaddr=0x26000 + space=0x5 vaddr=0x27000 size=0x1000 parent=0x2 p.vaddr=0x27000 + space=0x5 vaddr=0x28000 size=0x1000 parent=0x2 p.vaddr=0x28000 + space=0x5 vaddr=0x29000 size=0x1000 parent=0x2 p.vaddr=0x29000 + space=0x5 vaddr=0x2a000 size=0x1000 parent=0x2 p.vaddr=0x2a000 + space=0x5 vaddr=0x2b000 size=0x1000 parent=0x2 p.vaddr=0x2b000 + space=0x5 vaddr=0x2c000 size=0x1000 parent=0x2 p.vaddr=0x2c000 + space=0x5 vaddr=0x2d000 size=0x1000 parent=0x2 p.vaddr=0x2d000 + space=0x5 vaddr=0x2e000 size=0x1000 parent=0x2 p.vaddr=0x2e000 + space=0x5 vaddr=0x2f000 size=0x1000 parent=0x2 p.vaddr=0x2f000 + space=0x5 vaddr=0x30000 size=0x1000 parent=0x2 p.vaddr=0x30000 + space=0x5 vaddr=0x31000 size=0x1000 parent=0x2 p.vaddr=0x31000 + space=0x5 vaddr=0x32000 size=0x1000 parent=0x2 p.vaddr=0x32000 + space=0x5 vaddr=0x33000 size=0x1000 parent=0x2 p.vaddr=0x33000 + space=0x5 vaddr=0x34000 size=0x1000 parent=0x2 p.vaddr=0x34000 + space=0x5 vaddr=0x35000 size=0x1000 parent=0x2 p.vaddr=0x35000 + space=0x5 vaddr=0x36000 size=0x1000 parent=0x2 p.vaddr=0x36000 + space=0x5 vaddr=0x37000 size=0x1000 parent=0x2 p.vaddr=0x37000 + space=0x5 vaddr=0x38000 size=0x1000 parent=0x2 p.vaddr=0x38000 + space=0x5 vaddr=0x39000 size=0x1000 parent=0x2 p.vaddr=0x39000 + space=0x5 vaddr=0x3a000 size=0x1000 parent=0x2 p.vaddr=0x3a000 + space=0x5 vaddr=0x3b000 size=0x1000 parent=0x2 p.vaddr=0x3b000 + space=0x5 vaddr=0x3c000 size=0x1000 parent=0x2 p.vaddr=0x3c000 + space=0x5 vaddr=0x3d000 size=0x1000 parent=0x2 p.vaddr=0x3d000 + space=0x5 vaddr=0x3e000 size=0x1000 parent=0x2 p.vaddr=0x3e000 + space=0x5 vaddr=0x3f000 size=0x1000 parent=0x2 p.vaddr=0x3f000 + space=0x5 vaddr=0x40000 size=0x1000 parent=0x2 p.vaddr=0x40000 + space=0x5 vaddr=0x41000 size=0x1000 parent=0x2 p.vaddr=0x41000 + space=0x5 vaddr=0x42000 size=0x1000 parent=0x2 p.vaddr=0x42000 + space=0x5 vaddr=0x43000 size=0x1000 parent=0x2 p.vaddr=0x43000 + space=0x5 vaddr=0x44000 size=0x1000 parent=0x2 p.vaddr=0x44000 + space=0x5 vaddr=0x45000 size=0x1000 parent=0x2 p.vaddr=0x45000 + space=0x5 vaddr=0x46000 size=0x1000 parent=0x2 p.vaddr=0x46000 + space=0x5 vaddr=0x47000 size=0x1000 parent=0x2 p.vaddr=0x47000 + space=0x5 vaddr=0x48000 size=0x1000 parent=0x2 p.vaddr=0x48000 + space=0x5 vaddr=0x49000 size=0x1000 parent=0x2 p.vaddr=0x49000 + space=0x5 vaddr=0x4a000 size=0x1000 parent=0x2 p.vaddr=0x4a000 + space=0x5 vaddr=0x4b000 size=0x1000 parent=0x2 p.vaddr=0x4b000 + space=0x5 vaddr=0x4c000 size=0x1000 parent=0x2 p.vaddr=0x4c000 + space=0x5 vaddr=0x4d000 size=0x1000 parent=0x2 p.vaddr=0x4d000 + space=0x5 vaddr=0x4e000 size=0x1000 parent=0x2 p.vaddr=0x4e000 + space=0x5 vaddr=0x4f000 size=0x1000 parent=0x2 p.vaddr=0x4f000 + space=0x5 vaddr=0x50000 size=0x1000 parent=0x2 p.vaddr=0x50000 + space=0x5 vaddr=0x51000 size=0x1000 parent=0x2 p.vaddr=0x51000 + space=0x5 vaddr=0x52000 size=0x1000 parent=0x2 p.vaddr=0x52000 + space=0x5 vaddr=0x53000 size=0x1000 parent=0x2 p.vaddr=0x53000 + space=0x5 vaddr=0x54000 size=0x1000 parent=0x2 p.vaddr=0x54000 + space=0x5 vaddr=0x55000 size=0x1000 parent=0x2 p.vaddr=0x55000 + space=0x5 vaddr=0x56000 size=0x1000 parent=0x2 p.vaddr=0x56000 + space=0x5 vaddr=0x57000 size=0x1000 parent=0x2 p.vaddr=0x57000 + space=0x5 vaddr=0x58000 size=0x1000 parent=0x2 p.vaddr=0x58000 + space=0x5 vaddr=0x59000 size=0x1000 parent=0x2 p.vaddr=0x59000 + space=0x5 vaddr=0x5a000 size=0x1000 parent=0x2 p.vaddr=0x5a000 + space=0x5 vaddr=0x5b000 size=0x1000 parent=0x2 p.vaddr=0x5b000 + space=0x5 vaddr=0x5c000 size=0x1000 parent=0x2 p.vaddr=0x5c000 + space=0x5 vaddr=0x5d000 size=0x1000 parent=0x2 p.vaddr=0x5d000 + space=0x5 vaddr=0x5e000 size=0x1000 parent=0x2 p.vaddr=0x5e000 + space=0x5 vaddr=0x5f000 size=0x1000 parent=0x2 p.vaddr=0x5f000 + space=0x5 vaddr=0x60000 size=0x1000 parent=0x2 p.vaddr=0x60000 + space=0x5 vaddr=0x61000 size=0x1000 parent=0x2 p.vaddr=0x61000 + space=0x5 vaddr=0x62000 size=0x1000 parent=0x2 p.vaddr=0x62000 + space=0x5 vaddr=0x63000 size=0x1000 parent=0x2 p.vaddr=0x63000 + space=0x5 vaddr=0x64000 size=0x1000 parent=0x2 p.vaddr=0x64000 + space=0x5 vaddr=0x65000 size=0x1000 parent=0x2 p.vaddr=0x65000 + space=0x5 vaddr=0x66000 size=0x1000 parent=0x2 p.vaddr=0x66000 + space=0x5 vaddr=0x67000 size=0x1000 parent=0x2 p.vaddr=0x67000 + space=0x5 vaddr=0x68000 size=0x1000 parent=0x2 p.vaddr=0x68000 + space=0x5 vaddr=0x69000 size=0x1000 parent=0x2 p.vaddr=0x69000 + space=0x5 vaddr=0x6a000 size=0x1000 parent=0x2 p.vaddr=0x6a000 + space=0x5 vaddr=0x6b000 size=0x1000 parent=0x2 p.vaddr=0x6b000 + space=0x5 vaddr=0x6c000 size=0x1000 parent=0x2 p.vaddr=0x6c000 + space=0x5 vaddr=0x6d000 size=0x1000 parent=0x2 p.vaddr=0x6d000 + space=0x5 vaddr=0x6e000 size=0x1000 parent=0x2 p.vaddr=0x6e000 + space=0x5 vaddr=0x6f000 size=0x1000 parent=0x2 p.vaddr=0x6f000 + space=0x5 vaddr=0x70000 size=0x1000 parent=0x2 p.vaddr=0x70000 + space=0x5 vaddr=0x71000 size=0x1000 parent=0x2 p.vaddr=0x71000 + space=0x5 vaddr=0x72000 size=0x1000 parent=0x2 p.vaddr=0x72000 + space=0x5 vaddr=0x73000 size=0x1000 parent=0x2 p.vaddr=0x73000 + space=0x5 vaddr=0x74000 size=0x1000 parent=0x2 p.vaddr=0x74000 + space=0x5 vaddr=0x75000 size=0x1000 parent=0x2 p.vaddr=0x75000 + space=0x5 vaddr=0x76000 size=0x1000 parent=0x2 p.vaddr=0x76000 + space=0x5 vaddr=0x77000 size=0x1000 parent=0x2 p.vaddr=0x77000 + space=0x5 vaddr=0x78000 size=0x1000 parent=0x2 p.vaddr=0x78000 + space=0x5 vaddr=0x79000 size=0x1000 parent=0x2 p.vaddr=0x79000 + space=0x5 vaddr=0x7a000 size=0x1000 parent=0x2 p.vaddr=0x7a000 + space=0x5 vaddr=0x7b000 size=0x1000 parent=0x2 p.vaddr=0x7b000 + space=0x5 vaddr=0x7c000 size=0x1000 parent=0x2 p.vaddr=0x7c000 + space=0x5 vaddr=0x7d000 size=0x1000 parent=0x2 p.vaddr=0x7d000 + space=0x5 vaddr=0x7e000 size=0x1000 parent=0x2 p.vaddr=0x7e000 + space=0x5 vaddr=0x7f000 size=0x1000 parent=0x2 p.vaddr=0x7f000 + space=0x5 vaddr=0x80000 size=0x1000 parent=0x2 p.vaddr=0x80000 + space=0x5 vaddr=0x81000 size=0x1000 parent=0x2 p.vaddr=0x81000 + space=0x5 vaddr=0x82000 size=0x1000 parent=0x2 p.vaddr=0x82000 + space=0x5 vaddr=0x83000 size=0x1000 parent=0x2 p.vaddr=0x83000 + space=0x5 vaddr=0x84000 size=0x1000 parent=0x2 p.vaddr=0x84000 + space=0x5 vaddr=0x85000 size=0x1000 parent=0x2 p.vaddr=0x85000 + space=0x5 vaddr=0x86000 size=0x1000 parent=0x2 p.vaddr=0x86000 + space=0x5 vaddr=0x87000 size=0x1000 parent=0x2 p.vaddr=0x87000 + space=0x5 vaddr=0x88000 size=0x1000 parent=0x2 p.vaddr=0x88000 + space=0x5 vaddr=0x89000 size=0x1000 parent=0x2 p.vaddr=0x89000 + space=0x5 vaddr=0x8a000 size=0x1000 parent=0x2 p.vaddr=0x8a000 + space=0x5 vaddr=0x8b000 size=0x1000 parent=0x2 p.vaddr=0x8b000 + space=0x5 vaddr=0x8c000 size=0x1000 parent=0x2 p.vaddr=0x8c000 + space=0x5 vaddr=0x8d000 size=0x1000 parent=0x2 p.vaddr=0x8d000 + space=0x5 vaddr=0x8e000 size=0x1000 parent=0x2 p.vaddr=0x8e000 + space=0x5 vaddr=0x8f000 size=0x1000 parent=0x2 p.vaddr=0x8f000 + space=0x5 vaddr=0x90000 size=0x1000 parent=0x2 p.vaddr=0x90000 + space=0x5 vaddr=0x91000 size=0x1000 parent=0x2 p.vaddr=0x91000 + space=0x5 vaddr=0x92000 size=0x1000 parent=0x2 p.vaddr=0x92000 + space=0x5 vaddr=0x93000 size=0x1000 parent=0x2 p.vaddr=0x93000 + space=0x5 vaddr=0x94000 size=0x1000 parent=0x2 p.vaddr=0x94000 + space=0x5 vaddr=0x95000 size=0x1000 parent=0x2 p.vaddr=0x95000 + space=0x5 vaddr=0x96000 size=0x1000 parent=0x2 p.vaddr=0x96000 + space=0x5 vaddr=0x97000 size=0x1000 parent=0x2 p.vaddr=0x97000 + space=0x5 vaddr=0x98000 size=0x1000 parent=0x2 p.vaddr=0x98000 + space=0x5 vaddr=0x99000 size=0x1000 parent=0x2 p.vaddr=0x99000 + space=0x5 vaddr=0x9a000 size=0x1000 parent=0x2 p.vaddr=0x9a000 + space=0x5 vaddr=0x9b000 size=0x1000 parent=0x2 p.vaddr=0x9b000 + space=0x5 vaddr=0x9c000 size=0x1000 parent=0x2 p.vaddr=0x9c000 + space=0x5 vaddr=0x9d000 size=0x1000 parent=0x2 p.vaddr=0x9d000 + space=0x5 vaddr=0x9e000 size=0x1000 parent=0x2 p.vaddr=0x9e000 + space=0x5 vaddr=0x9f000 size=0x1000 parent=0x2 p.vaddr=0x9f000 + space=0x5 vaddr=0xa0000 size=0x1000 parent=0x2 p.vaddr=0xa0000 + space=0x5 vaddr=0xa1000 size=0x1000 parent=0x2 p.vaddr=0xa1000 + space=0x5 vaddr=0xa2000 size=0x1000 parent=0x2 p.vaddr=0xa2000 + space=0x5 vaddr=0xa3000 size=0x1000 parent=0x2 p.vaddr=0xa3000 + space=0x5 vaddr=0xa4000 size=0x1000 parent=0x2 p.vaddr=0xa4000 + space=0x5 vaddr=0xa5000 size=0x1000 parent=0x2 p.vaddr=0xa5000 + space=0x5 vaddr=0xa6000 size=0x1000 parent=0x2 p.vaddr=0xa6000 + space=0x5 vaddr=0xa7000 size=0x1000 parent=0x2 p.vaddr=0xa7000 + space=0x5 vaddr=0xa8000 size=0x1000 parent=0x2 p.vaddr=0xa8000 + space=0x5 vaddr=0xa9000 size=0x1000 parent=0x2 p.vaddr=0xa9000 + space=0x5 vaddr=0xaa000 size=0x1000 parent=0x2 p.vaddr=0xaa000 + space=0x5 vaddr=0xab000 size=0x1000 parent=0x2 p.vaddr=0xab000 + space=0x5 vaddr=0xac000 size=0x1000 parent=0x2 p.vaddr=0xac000 + space=0x5 vaddr=0xad000 size=0x1000 parent=0x2 p.vaddr=0xad000 + space=0x5 vaddr=0xae000 size=0x1000 parent=0x2 p.vaddr=0xae000 + space=0x5 vaddr=0xaf000 size=0x1000 parent=0x2 p.vaddr=0xaf000 + space=0x5 vaddr=0xb0000 size=0x1000 parent=0x2 p.vaddr=0xb0000 + space=0x5 vaddr=0xb1000 size=0x1000 parent=0x2 p.vaddr=0xb1000 + space=0x5 vaddr=0xb2000 size=0x1000 parent=0x2 p.vaddr=0xb2000 + space=0x5 vaddr=0xb3000 size=0x1000 parent=0x2 p.vaddr=0xb3000 + space=0x5 vaddr=0xb4000 size=0x1000 parent=0x2 p.vaddr=0xb4000 + space=0x5 vaddr=0xb5000 size=0x1000 parent=0x2 p.vaddr=0xb5000 + space=0x5 vaddr=0xb6000 size=0x1000 parent=0x2 p.vaddr=0xb6000 + space=0x5 vaddr=0xb7000 size=0x1000 parent=0x2 p.vaddr=0xb7000 + space=0x5 vaddr=0xb8000 size=0x1000 parent=0x2 p.vaddr=0xb8000 + space=0x5 vaddr=0xb9000 size=0x1000 parent=0x2 p.vaddr=0xb9000 + space=0x5 vaddr=0xba000 size=0x1000 parent=0x2 p.vaddr=0xba000 + space=0x5 vaddr=0xbb000 size=0x1000 parent=0x2 p.vaddr=0xbb000 + space=0x5 vaddr=0xbc000 size=0x1000 parent=0x2 p.vaddr=0xbc000 + space=0x5 vaddr=0xbd000 size=0x1000 parent=0x2 p.vaddr=0xbd000 + space=0x5 vaddr=0xbe000 size=0x1000 parent=0x2 p.vaddr=0xbe000 + space=0x5 vaddr=0xbf000 size=0x1000 parent=0x2 p.vaddr=0xbf000 + space=0x5 vaddr=0xc0000 size=0x1000 parent=0x2 p.vaddr=0xc0000 + space=0x5 vaddr=0xc1000 size=0x1000 parent=0x2 p.vaddr=0xc1000 + space=0x5 vaddr=0xc2000 size=0x1000 parent=0x2 p.vaddr=0xc2000 + space=0x5 vaddr=0xc3000 size=0x1000 parent=0x2 p.vaddr=0xc3000 + space=0x5 vaddr=0xc4000 size=0x1000 parent=0x2 p.vaddr=0xc4000 + space=0x5 vaddr=0xc5000 size=0x1000 parent=0x2 p.vaddr=0xc5000 + space=0x5 vaddr=0xc6000 size=0x1000 parent=0x2 p.vaddr=0xc6000 + space=0x5 vaddr=0xc7000 size=0x1000 parent=0x2 p.vaddr=0xc7000 + space=0x5 vaddr=0xc8000 size=0x1000 parent=0x2 p.vaddr=0xc8000 + space=0x5 vaddr=0xc9000 size=0x1000 parent=0x2 p.vaddr=0xc9000 + space=0x5 vaddr=0xca000 size=0x1000 parent=0x2 p.vaddr=0xca000 + space=0x5 vaddr=0xcb000 size=0x1000 parent=0x2 p.vaddr=0xcb000 + space=0x5 vaddr=0xcc000 size=0x1000 parent=0x2 p.vaddr=0xcc000 + space=0x5 vaddr=0xcd000 size=0x1000 parent=0x2 p.vaddr=0xcd000 + space=0x5 vaddr=0xce000 size=0x1000 parent=0x2 p.vaddr=0xce000 + space=0x5 vaddr=0xcf000 size=0x1000 parent=0x2 p.vaddr=0xcf000 + space=0x5 vaddr=0xd0000 size=0x1000 parent=0x2 p.vaddr=0xd0000 + space=0x5 vaddr=0xd1000 size=0x1000 parent=0x2 p.vaddr=0xd1000 + space=0x5 vaddr=0xd2000 size=0x1000 parent=0x2 p.vaddr=0xd2000 + space=0x5 vaddr=0xd3000 size=0x1000 parent=0x2 p.vaddr=0xd3000 + space=0x5 vaddr=0xd4000 size=0x1000 parent=0x2 p.vaddr=0xd4000 + space=0x5 vaddr=0xd5000 size=0x1000 parent=0x2 p.vaddr=0xd5000 + space=0x5 vaddr=0xd6000 size=0x1000 parent=0x2 p.vaddr=0xd6000 + space=0x5 vaddr=0xd7000 size=0x1000 parent=0x2 p.vaddr=0xd7000 + space=0x5 vaddr=0xd8000 size=0x1000 parent=0x2 p.vaddr=0xd8000 + space=0x5 vaddr=0xd9000 size=0x1000 parent=0x2 p.vaddr=0xd9000 + space=0x5 vaddr=0xda000 size=0x1000 parent=0x2 p.vaddr=0xda000 + space=0x5 vaddr=0xdb000 size=0x1000 parent=0x2 p.vaddr=0xdb000 + space=0x5 vaddr=0xdc000 size=0x1000 parent=0x2 p.vaddr=0xdc000 + space=0x5 vaddr=0xdd000 size=0x1000 parent=0x2 p.vaddr=0xdd000 + space=0x5 vaddr=0xde000 size=0x1000 parent=0x2 p.vaddr=0xde000 + space=0x5 vaddr=0xdf000 size=0x1000 parent=0x2 p.vaddr=0xdf000 + space=0x5 vaddr=0xe0000 size=0x1000 parent=0x2 p.vaddr=0xe0000 + space=0x5 vaddr=0xe1000 size=0x1000 parent=0x2 p.vaddr=0xe1000 + space=0x5 vaddr=0xe2000 size=0x1000 parent=0x2 p.vaddr=0xe2000 + space=0x5 vaddr=0xe3000 size=0x1000 parent=0x2 p.vaddr=0xe3000 + space=0x5 vaddr=0xe4000 size=0x1000 parent=0x2 p.vaddr=0xe4000 + space=0x5 vaddr=0xe5000 size=0x1000 parent=0x2 p.vaddr=0xe5000 + space=0x5 vaddr=0xe6000 size=0x1000 parent=0x2 p.vaddr=0xe6000 + space=0x5 vaddr=0xe7000 size=0x1000 parent=0x2 p.vaddr=0xe7000 + space=0x5 vaddr=0xe8000 size=0x1000 parent=0x2 p.vaddr=0xe8000 + space=0x5 vaddr=0xe9000 size=0x1000 parent=0x2 p.vaddr=0xe9000 + space=0x5 vaddr=0xea000 size=0x1000 parent=0x2 p.vaddr=0xea000 + space=0x5 vaddr=0xeb000 size=0x1000 parent=0x2 p.vaddr=0xeb000 + space=0x5 vaddr=0xec000 size=0x1000 parent=0x2 p.vaddr=0xec000 + space=0x5 vaddr=0xed000 size=0x1000 parent=0x2 p.vaddr=0xed000 + space=0x5 vaddr=0xee000 size=0x1000 parent=0x2 p.vaddr=0xee000 + space=0x5 vaddr=0xef000 size=0x1000 parent=0x2 p.vaddr=0xef000 + space=0x5 vaddr=0xf0000 size=0x1000 parent=0x2 p.vaddr=0xf0000 + space=0x5 vaddr=0xf1000 size=0x1000 parent=0x2 p.vaddr=0xf1000 + space=0x5 vaddr=0xf2000 size=0x1000 parent=0x2 p.vaddr=0xf2000 + space=0x5 vaddr=0xf3000 size=0x1000 parent=0x2 p.vaddr=0xf3000 + space=0x5 vaddr=0xf4000 size=0x1000 parent=0x2 p.vaddr=0xf4000 + space=0x5 vaddr=0xf5000 size=0x1000 parent=0x2 p.vaddr=0xf5000 + space=0x5 vaddr=0xf6000 size=0x1000 parent=0x2 p.vaddr=0xf6000 + space=0x5 vaddr=0xf7000 size=0x1000 parent=0x2 p.vaddr=0xf7000 + space=0x5 vaddr=0xf8000 size=0x1000 parent=0x2 p.vaddr=0xf8000 + space=0x5 vaddr=0xf9000 size=0x1000 parent=0x2 p.vaddr=0xf9000 + space=0x5 vaddr=0xfa000 size=0x1000 parent=0x2 p.vaddr=0xfa000 + space=0x5 vaddr=0xfb000 size=0x1000 parent=0x2 p.vaddr=0xfb000 + space=0x5 vaddr=0xfc000 size=0x1000 parent=0x2 p.vaddr=0xfc000 + space=0x5 vaddr=0xfd000 size=0x1000 parent=0x2 p.vaddr=0xfd000 + space=0x5 vaddr=0xfe000 size=0x1000 parent=0x2 p.vaddr=0xfe000 + space=0x5 vaddr=0xff000 size=0x1000 parent=0x2 p.vaddr=0xff000 + space=0x5 vaddr=0x100000 size=0x1000 parent=0x2 p.vaddr=0x100000 + space=0x5 vaddr=0x101000 size=0x1000 parent=0x2 p.vaddr=0x101000 + space=0x5 vaddr=0x102000 size=0x1000 parent=0x2 p.vaddr=0x102000 + space=0x5 vaddr=0x103000 size=0x1000 parent=0x2 p.vaddr=0x103000 + space=0x5 vaddr=0x104000 size=0x1000 parent=0x2 p.vaddr=0x104000 + space=0x5 vaddr=0x105000 size=0x1000 parent=0x2 p.vaddr=0x105000 + space=0x5 vaddr=0x106000 size=0x1000 parent=0x2 p.vaddr=0x106000 + space=0x5 vaddr=0x107000 size=0x1000 parent=0x2 p.vaddr=0x107000 + space=0x5 vaddr=0x108000 size=0x1000 parent=0x2 p.vaddr=0x108000 + space=0x5 vaddr=0x109000 size=0x1000 parent=0x2 p.vaddr=0x109000 + space=0x5 vaddr=0x10a000 size=0x1000 parent=0x2 p.vaddr=0x10a000 + space=0x5 vaddr=0x10b000 size=0x1000 parent=0x2 p.vaddr=0x10b000 + space=0x5 vaddr=0x10c000 size=0x1000 parent=0x2 p.vaddr=0x10c000 + space=0x5 vaddr=0x10d000 size=0x1000 parent=0x2 p.vaddr=0x10d000 + space=0x5 vaddr=0x10e000 size=0x1000 parent=0x2 p.vaddr=0x10e000 + space=0x5 vaddr=0x10f000 size=0x1000 parent=0x2 p.vaddr=0x10f000 + space=0x5 vaddr=0x110000 size=0x1000 parent=0x2 p.vaddr=0x110000 + space=0x5 vaddr=0x111000 size=0x1000 parent=0x2 p.vaddr=0x111000 + space=0x5 vaddr=0x112000 size=0x1000 parent=0x2 p.vaddr=0x112000 + space=0x5 vaddr=0x113000 size=0x1000 parent=0x2 p.vaddr=0x113000 + space=0x5 vaddr=0x114000 size=0x1000 parent=0x2 p.vaddr=0x114000 + space=0x5 vaddr=0x115000 size=0x1000 parent=0x2 p.vaddr=0x115000 + space=0x5 vaddr=0x116000 size=0x1000 parent=0x2 p.vaddr=0x116000 + space=0x5 vaddr=0x117000 size=0x1000 parent=0x2 p.vaddr=0x117000 + space=0x5 vaddr=0x118000 size=0x1000 parent=0x2 p.vaddr=0x118000 + space=0x5 vaddr=0x119000 size=0x1000 parent=0x2 p.vaddr=0x119000 + space=0x5 vaddr=0x11a000 size=0x1000 parent=0x2 p.vaddr=0x11a000 + space=0x5 vaddr=0x11b000 size=0x1000 parent=0x2 p.vaddr=0x11b000 + space=0x5 vaddr=0x11c000 size=0x1000 parent=0x2 p.vaddr=0x11c000 + space=0x5 vaddr=0x11d000 size=0x1000 parent=0x2 p.vaddr=0x11d000 + space=0x5 vaddr=0x11e000 size=0x1000 parent=0x2 p.vaddr=0x11e000 + space=0x5 vaddr=0x11f000 size=0x1000 parent=0x2 p.vaddr=0x11f000 + space=0x5 vaddr=0x120000 size=0x1000 parent=0x2 p.vaddr=0x120000 + space=0x5 vaddr=0x121000 size=0x1000 parent=0x2 p.vaddr=0x121000 + space=0x5 vaddr=0x122000 size=0x1000 parent=0x2 p.vaddr=0x122000 + space=0x5 vaddr=0x123000 size=0x1000 parent=0x2 p.vaddr=0x123000 + space=0x5 vaddr=0x124000 size=0x1000 parent=0x2 p.vaddr=0x124000 + space=0x5 vaddr=0x125000 size=0x1000 parent=0x2 p.vaddr=0x125000 + space=0x5 vaddr=0x126000 size=0x1000 parent=0x2 p.vaddr=0x126000 + space=0x5 vaddr=0x127000 size=0x1000 parent=0x2 p.vaddr=0x127000 + space=0x5 vaddr=0x128000 size=0x1000 parent=0x2 p.vaddr=0x128000 + space=0x5 vaddr=0x129000 size=0x1000 parent=0x2 p.vaddr=0x129000 + space=0x5 vaddr=0x12a000 size=0x1000 parent=0x2 p.vaddr=0x12a000 + space=0x5 vaddr=0x12b000 size=0x1000 parent=0x2 p.vaddr=0x12b000 + space=0x5 vaddr=0x12c000 size=0x1000 parent=0x2 p.vaddr=0x12c000 + space=0x5 vaddr=0x12d000 size=0x1000 parent=0x2 p.vaddr=0x12d000 + space=0x5 vaddr=0x12e000 size=0x1000 parent=0x2 p.vaddr=0x12e000 + space=0x5 vaddr=0x12f000 size=0x1000 parent=0x2 p.vaddr=0x12f000 + space=0x5 vaddr=0x130000 size=0x1000 parent=0x2 p.vaddr=0x130000 + space=0x5 vaddr=0x131000 size=0x1000 parent=0x2 p.vaddr=0x131000 + space=0x5 vaddr=0x132000 size=0x1000 parent=0x2 p.vaddr=0x132000 + space=0x5 vaddr=0x133000 size=0x1000 parent=0x2 p.vaddr=0x133000 + space=0x5 vaddr=0x134000 size=0x1000 parent=0x2 p.vaddr=0x134000 + space=0x5 vaddr=0x135000 size=0x1000 parent=0x2 p.vaddr=0x135000 + space=0x5 vaddr=0x136000 size=0x1000 parent=0x2 p.vaddr=0x136000 + space=0x5 vaddr=0x137000 size=0x1000 parent=0x2 p.vaddr=0x137000 + space=0x5 vaddr=0x138000 size=0x1000 parent=0x2 p.vaddr=0x138000 + space=0x5 vaddr=0x139000 size=0x1000 parent=0x2 p.vaddr=0x139000 + space=0x5 vaddr=0x13a000 size=0x1000 parent=0x2 p.vaddr=0x13a000 + space=0x5 vaddr=0x13b000 size=0x1000 parent=0x2 p.vaddr=0x13b000 + space=0x5 vaddr=0x13c000 size=0x1000 parent=0x2 p.vaddr=0x13c000 + space=0x5 vaddr=0x13d000 size=0x1000 parent=0x2 p.vaddr=0x13d000 + space=0x5 vaddr=0x13e000 size=0x1000 parent=0x2 p.vaddr=0x13e000 + space=0x5 vaddr=0x13f000 size=0x1000 parent=0x2 p.vaddr=0x13f000 + space=0x5 vaddr=0x140000 size=0x1000 parent=0x2 p.vaddr=0x140000 + space=0x5 vaddr=0x141000 size=0x1000 parent=0x2 p.vaddr=0x141000 + space=0x5 vaddr=0x142000 size=0x1000 parent=0x2 p.vaddr=0x142000 + space=0x5 vaddr=0x143000 size=0x1000 parent=0x2 p.vaddr=0x143000 + space=0x5 vaddr=0x144000 size=0x1000 parent=0x2 p.vaddr=0x144000 + space=0x5 vaddr=0x145000 size=0x1000 parent=0x2 p.vaddr=0x145000 + space=0x5 vaddr=0x146000 size=0x1000 parent=0x2 p.vaddr=0x146000 + space=0x5 vaddr=0x147000 size=0x1000 parent=0x2 p.vaddr=0x147000 + space=0x5 vaddr=0x148000 size=0x1000 parent=0x2 p.vaddr=0x148000 + space=0x5 vaddr=0x149000 size=0x1000 parent=0x2 p.vaddr=0x149000 + space=0x5 vaddr=0x14a000 size=0x1000 parent=0x2 p.vaddr=0x14a000 + space=0x5 vaddr=0x14b000 size=0x1000 parent=0x2 p.vaddr=0x14b000 + space=0x5 vaddr=0x14c000 size=0x1000 parent=0x2 p.vaddr=0x14c000 + space=0x5 vaddr=0x14d000 size=0x1000 parent=0x2 p.vaddr=0x14d000 + space=0x5 vaddr=0x14e000 size=0x1000 parent=0x2 p.vaddr=0x14e000 + space=0x5 vaddr=0x14f000 size=0x1000 parent=0x2 p.vaddr=0x14f000 + space=0x5 vaddr=0x150000 size=0x1000 parent=0x2 p.vaddr=0x150000 + space=0x5 vaddr=0x151000 size=0x1000 parent=0x2 p.vaddr=0x151000 + space=0x5 vaddr=0x152000 size=0x1000 parent=0x2 p.vaddr=0x152000 + space=0x5 vaddr=0x153000 size=0x1000 parent=0x2 p.vaddr=0x153000 + space=0x5 vaddr=0x154000 size=0x1000 parent=0x2 p.vaddr=0x154000 + space=0x5 vaddr=0x155000 size=0x1000 parent=0x2 p.vaddr=0x155000 + space=0x5 vaddr=0x156000 size=0x1000 parent=0x2 p.vaddr=0x156000 + space=0x5 vaddr=0x157000 size=0x1000 parent=0x2 p.vaddr=0x157000 + space=0x5 vaddr=0x158000 size=0x1000 parent=0x2 p.vaddr=0x158000 + space=0x5 vaddr=0x159000 size=0x1000 parent=0x2 p.vaddr=0x159000 + space=0x5 vaddr=0x15a000 size=0x1000 parent=0x2 p.vaddr=0x15a000 + space=0x5 vaddr=0x15b000 size=0x1000 parent=0x2 p.vaddr=0x15b000 + space=0x5 vaddr=0x15c000 size=0x1000 parent=0x2 p.vaddr=0x15c000 + space=0x5 vaddr=0x15d000 size=0x1000 parent=0x2 p.vaddr=0x15d000 + space=0x5 vaddr=0x15e000 size=0x1000 parent=0x2 p.vaddr=0x15e000 + space=0x5 vaddr=0x15f000 size=0x1000 parent=0x2 p.vaddr=0x15f000 + space=0x5 vaddr=0x160000 size=0x1000 parent=0x2 p.vaddr=0x160000 + space=0x5 vaddr=0x161000 size=0x1000 parent=0x2 p.vaddr=0x161000 + space=0x5 vaddr=0x162000 size=0x1000 parent=0x2 p.vaddr=0x162000 + space=0x5 vaddr=0x163000 size=0x1000 parent=0x2 p.vaddr=0x163000 + space=0x5 vaddr=0x164000 size=0x1000 parent=0x2 p.vaddr=0x164000 + space=0x5 vaddr=0x165000 size=0x1000 parent=0x2 p.vaddr=0x165000 + space=0x5 vaddr=0x166000 size=0x1000 parent=0x2 p.vaddr=0x166000 + space=0x5 vaddr=0x167000 size=0x1000 parent=0x2 p.vaddr=0x167000 + space=0x5 vaddr=0x168000 size=0x1000 parent=0x2 p.vaddr=0x168000 + space=0x5 vaddr=0x169000 size=0x1000 parent=0x2 p.vaddr=0x169000 + space=0x5 vaddr=0x16a000 size=0x1000 parent=0x2 p.vaddr=0x16a000 + space=0x5 vaddr=0x16b000 size=0x1000 parent=0x2 p.vaddr=0x16b000 + space=0x5 vaddr=0x16c000 size=0x1000 parent=0x2 p.vaddr=0x16c000 + space=0x5 vaddr=0x16d000 size=0x1000 parent=0x2 p.vaddr=0x16d000 + space=0x5 vaddr=0x16e000 size=0x1000 parent=0x2 p.vaddr=0x16e000 + space=0x5 vaddr=0x16f000 size=0x1000 parent=0x2 p.vaddr=0x16f000 + space=0x5 vaddr=0x170000 size=0x1000 parent=0x2 p.vaddr=0x170000 + space=0x5 vaddr=0x171000 size=0x1000 parent=0x2 p.vaddr=0x171000 + space=0x5 vaddr=0x172000 size=0x1000 parent=0x2 p.vaddr=0x172000 + space=0x5 vaddr=0x173000 size=0x1000 parent=0x2 p.vaddr=0x173000 + space=0x5 vaddr=0x174000 size=0x1000 parent=0x2 p.vaddr=0x174000 + space=0x5 vaddr=0x175000 size=0x1000 parent=0x2 p.vaddr=0x175000 + space=0x5 vaddr=0x176000 size=0x1000 parent=0x2 p.vaddr=0x176000 + space=0x5 vaddr=0x177000 size=0x1000 parent=0x2 p.vaddr=0x177000 + space=0x5 vaddr=0x178000 size=0x1000 parent=0x2 p.vaddr=0x178000 + space=0x5 vaddr=0x179000 size=0x1000 parent=0x2 p.vaddr=0x179000 + space=0x5 vaddr=0x17a000 size=0x1000 parent=0x2 p.vaddr=0x17a000 + space=0x5 vaddr=0x17b000 size=0x1000 parent=0x2 p.vaddr=0x17b000 + space=0x5 vaddr=0x17c000 size=0x1000 parent=0x2 p.vaddr=0x17c000 + space=0x5 vaddr=0x17d000 size=0x1000 parent=0x2 p.vaddr=0x17d000 + space=0x5 vaddr=0x17e000 size=0x1000 parent=0x2 p.vaddr=0x17e000 + space=0x5 vaddr=0x17f000 size=0x1000 parent=0x2 p.vaddr=0x17f000 + space=0x5 vaddr=0x180000 size=0x1000 parent=0x2 p.vaddr=0x180000 + space=0x5 vaddr=0x181000 size=0x1000 parent=0x2 p.vaddr=0x181000 + space=0x5 vaddr=0x182000 size=0x1000 parent=0x2 p.vaddr=0x182000 + space=0x5 vaddr=0x183000 size=0x1000 parent=0x2 p.vaddr=0x183000 + space=0x5 vaddr=0x184000 size=0x1000 parent=0x2 p.vaddr=0x184000 + space=0x5 vaddr=0x185000 size=0x1000 parent=0x2 p.vaddr=0x185000 + space=0x5 vaddr=0x186000 size=0x1000 parent=0x2 p.vaddr=0x186000 + space=0x5 vaddr=0x187000 size=0x1000 parent=0x2 p.vaddr=0x187000 + space=0x5 vaddr=0x188000 size=0x1000 parent=0x2 p.vaddr=0x188000 + space=0x5 vaddr=0x189000 size=0x1000 parent=0x2 p.vaddr=0x189000 + space=0x5 vaddr=0x18a000 size=0x1000 parent=0x2 p.vaddr=0x18a000 + space=0x5 vaddr=0x18b000 size=0x1000 parent=0x2 p.vaddr=0x18b000 + space=0x5 vaddr=0x18c000 size=0x1000 parent=0x2 p.vaddr=0x18c000 + space=0x5 vaddr=0x18d000 size=0x1000 parent=0x2 p.vaddr=0x18d000 + space=0x5 vaddr=0x18e000 size=0x1000 parent=0x2 p.vaddr=0x18e000 + space=0x5 vaddr=0x18f000 size=0x1000 parent=0x2 p.vaddr=0x18f000 + space=0x5 vaddr=0x190000 size=0x1000 parent=0x2 p.vaddr=0x190000 + space=0x5 vaddr=0x191000 size=0x1000 parent=0x2 p.vaddr=0x191000 + space=0x5 vaddr=0x192000 size=0x1000 parent=0x2 p.vaddr=0x192000 + space=0x5 vaddr=0x193000 size=0x1000 parent=0x2 p.vaddr=0x193000 + space=0x5 vaddr=0x194000 size=0x1000 parent=0x2 p.vaddr=0x194000 + space=0x5 vaddr=0x195000 size=0x1000 parent=0x2 p.vaddr=0x195000 + space=0x5 vaddr=0x196000 size=0x1000 parent=0x2 p.vaddr=0x196000 + space=0x5 vaddr=0x197000 size=0x1000 parent=0x2 p.vaddr=0x197000 + space=0x5 vaddr=0x198000 size=0x1000 parent=0x2 p.vaddr=0x198000 + space=0x5 vaddr=0x199000 size=0x1000 parent=0x2 p.vaddr=0x199000 + space=0x5 vaddr=0x19a000 size=0x1000 parent=0x2 p.vaddr=0x19a000 + space=0x5 vaddr=0x19b000 size=0x1000 parent=0x2 p.vaddr=0x19b000 + space=0x5 vaddr=0x19c000 size=0x1000 parent=0x2 p.vaddr=0x19c000 + space=0x5 vaddr=0x19d000 size=0x1000 parent=0x2 p.vaddr=0x19d000 + space=0x5 vaddr=0x19e000 size=0x1000 parent=0x2 p.vaddr=0x19e000 + space=0x5 vaddr=0x19f000 size=0x1000 parent=0x2 p.vaddr=0x19f000 + space=0x5 vaddr=0x1a0000 size=0x1000 parent=0x2 p.vaddr=0x1a0000 + space=0x5 vaddr=0x1a1000 size=0x1000 parent=0x2 p.vaddr=0x1a1000 + space=0x5 vaddr=0x1a2000 size=0x1000 parent=0x2 p.vaddr=0x1a2000 + space=0x5 vaddr=0x1a3000 size=0x1000 parent=0x2 p.vaddr=0x1a3000 + space=0x5 vaddr=0x1a4000 size=0x1000 parent=0x2 p.vaddr=0x1a4000 + space=0x5 vaddr=0x1a5000 size=0x1000 parent=0x2 p.vaddr=0x1a5000 + space=0x5 vaddr=0x1a6000 size=0x1000 parent=0x2 p.vaddr=0x1a6000 + space=0x5 vaddr=0x1a7000 size=0x1000 parent=0x2 p.vaddr=0x1a7000 + space=0x5 vaddr=0x1a8000 size=0x1000 parent=0x2 p.vaddr=0x1a8000 + space=0x5 vaddr=0x1a9000 size=0x1000 parent=0x2 p.vaddr=0x1a9000 + space=0x5 vaddr=0x1aa000 size=0x1000 parent=0x2 p.vaddr=0x1aa000 + space=0x5 vaddr=0x1ab000 size=0x1000 parent=0x2 p.vaddr=0x1ab000 + space=0x5 vaddr=0x1ac000 size=0x1000 parent=0x2 p.vaddr=0x1ac000 + space=0x5 vaddr=0x1ad000 size=0x1000 parent=0x2 p.vaddr=0x1ad000 + space=0x5 vaddr=0x1ae000 size=0x1000 parent=0x2 p.vaddr=0x1ae000 + space=0x5 vaddr=0x1af000 size=0x1000 parent=0x2 p.vaddr=0x1af000 + space=0x5 vaddr=0x1b0000 size=0x1000 parent=0x2 p.vaddr=0x1b0000 + space=0x5 vaddr=0x1b1000 size=0x1000 parent=0x2 p.vaddr=0x1b1000 + space=0x5 vaddr=0x1b2000 size=0x1000 parent=0x2 p.vaddr=0x1b2000 + space=0x5 vaddr=0x1b3000 size=0x1000 parent=0x2 p.vaddr=0x1b3000 + space=0x5 vaddr=0x1b4000 size=0x1000 parent=0x2 p.vaddr=0x1b4000 + space=0x5 vaddr=0x1b5000 size=0x1000 parent=0x2 p.vaddr=0x1b5000 + space=0x5 vaddr=0x1b6000 size=0x1000 parent=0x2 p.vaddr=0x1b6000 + space=0x5 vaddr=0x1b7000 size=0x1000 parent=0x2 p.vaddr=0x1b7000 + space=0x5 vaddr=0x1b8000 size=0x1000 parent=0x2 p.vaddr=0x1b8000 + space=0x5 vaddr=0x1b9000 size=0x1000 parent=0x2 p.vaddr=0x1b9000 + space=0x5 vaddr=0x1ba000 size=0x1000 parent=0x2 p.vaddr=0x1ba000 + space=0x5 vaddr=0x1bb000 size=0x1000 parent=0x2 p.vaddr=0x1bb000 + space=0x5 vaddr=0x1bc000 size=0x1000 parent=0x2 p.vaddr=0x1bc000 + space=0x5 vaddr=0x1bd000 size=0x1000 parent=0x2 p.vaddr=0x1bd000 + space=0x5 vaddr=0x1be000 size=0x1000 parent=0x2 p.vaddr=0x1be000 + space=0x5 vaddr=0x1bf000 size=0x1000 parent=0x2 p.vaddr=0x1bf000 + space=0x5 vaddr=0x1c0000 size=0x1000 parent=0x2 p.vaddr=0x1c0000 + space=0x5 vaddr=0x1c1000 size=0x1000 parent=0x2 p.vaddr=0x1c1000 + space=0x5 vaddr=0x1c2000 size=0x1000 parent=0x2 p.vaddr=0x1c2000 + space=0x5 vaddr=0x1c3000 size=0x1000 parent=0x2 p.vaddr=0x1c3000 + space=0x5 vaddr=0x1c4000 size=0x1000 parent=0x2 p.vaddr=0x1c4000 + space=0x5 vaddr=0x1c5000 size=0x1000 parent=0x2 p.vaddr=0x1c5000 + space=0x5 vaddr=0x1c6000 size=0x1000 parent=0x2 p.vaddr=0x1c6000 + space=0x5 vaddr=0x1c7000 size=0x1000 parent=0x2 p.vaddr=0x1c7000 + space=0x5 vaddr=0x1c8000 size=0x1000 parent=0x2 p.vaddr=0x1c8000 + space=0x5 vaddr=0x1c9000 size=0x1000 parent=0x2 p.vaddr=0x1c9000 + space=0x5 vaddr=0x1ca000 size=0x1000 parent=0x2 p.vaddr=0x1ca000 + space=0x5 vaddr=0x1cb000 size=0x1000 parent=0x2 p.vaddr=0x1cb000 + space=0x5 vaddr=0x1cc000 size=0x1000 parent=0x2 p.vaddr=0x1cc000 + space=0x5 vaddr=0x1cd000 size=0x1000 parent=0x2 p.vaddr=0x1cd000 + space=0x5 vaddr=0x1ce000 size=0x1000 parent=0x2 p.vaddr=0x1ce000 + space=0x5 vaddr=0x1cf000 size=0x1000 parent=0x2 p.vaddr=0x1cf000 + space=0x5 vaddr=0x1d0000 size=0x1000 parent=0x2 p.vaddr=0x1d0000 + space=0x5 vaddr=0x1d1000 size=0x1000 parent=0x2 p.vaddr=0x1d1000 + space=0x5 vaddr=0x1d2000 size=0x1000 parent=0x2 p.vaddr=0x1d2000 + space=0x5 vaddr=0x1d3000 size=0x1000 parent=0x2 p.vaddr=0x1d3000 + space=0x5 vaddr=0x1d4000 size=0x1000 parent=0x2 p.vaddr=0x1d4000 + space=0x5 vaddr=0x1d5000 size=0x1000 parent=0x2 p.vaddr=0x1d5000 + space=0x5 vaddr=0x1d6000 size=0x1000 parent=0x2 p.vaddr=0x1d6000 + space=0x5 vaddr=0x1d7000 size=0x1000 parent=0x2 p.vaddr=0x1d7000 + space=0x5 vaddr=0x1d8000 size=0x1000 parent=0x2 p.vaddr=0x1d8000 + space=0x5 vaddr=0x1d9000 size=0x1000 parent=0x2 p.vaddr=0x1d9000 + space=0x5 vaddr=0x1da000 size=0x1000 parent=0x2 p.vaddr=0x1da000 + space=0x5 vaddr=0x1db000 size=0x1000 parent=0x2 p.vaddr=0x1db000 + space=0x5 vaddr=0x1dc000 size=0x1000 parent=0x2 p.vaddr=0x1dc000 + space=0x5 vaddr=0x1dd000 size=0x1000 parent=0x2 p.vaddr=0x1dd000 + space=0x5 vaddr=0x1de000 size=0x1000 parent=0x2 p.vaddr=0x1de000 + space=0x5 vaddr=0x1df000 size=0x1000 parent=0x2 p.vaddr=0x1df000 + space=0x5 vaddr=0x1e0000 size=0x1000 parent=0x2 p.vaddr=0x1e0000 + space=0x5 vaddr=0x1e1000 size=0x1000 parent=0x2 p.vaddr=0x1e1000 + space=0x5 vaddr=0x1e2000 size=0x1000 parent=0x2 p.vaddr=0x1e2000 + space=0x5 vaddr=0x1e3000 size=0x1000 parent=0x2 p.vaddr=0x1e3000 + space=0x5 vaddr=0x1e4000 size=0x1000 parent=0x2 p.vaddr=0x1e4000 + space=0x5 vaddr=0x1e5000 size=0x1000 parent=0x2 p.vaddr=0x1e5000 + space=0x5 vaddr=0x1e6000 size=0x1000 parent=0x2 p.vaddr=0x1e6000 + space=0x5 vaddr=0x1e7000 size=0x1000 parent=0x2 p.vaddr=0x1e7000 + space=0x5 vaddr=0x1e8000 size=0x1000 parent=0x2 p.vaddr=0x1e8000 + space=0x5 vaddr=0x1e9000 size=0x1000 parent=0x2 p.vaddr=0x1e9000 + space=0x5 vaddr=0x1ea000 size=0x1000 parent=0x2 p.vaddr=0x1ea000 + space=0x5 vaddr=0x1eb000 size=0x1000 parent=0x2 p.vaddr=0x1eb000 + space=0x5 vaddr=0x1ec000 size=0x1000 parent=0x2 p.vaddr=0x1ec000 + space=0x5 vaddr=0x1ed000 size=0x1000 parent=0x2 p.vaddr=0x1ed000 + space=0x5 vaddr=0x1ee000 size=0x1000 parent=0x2 p.vaddr=0x1ee000 + space=0x5 vaddr=0x1ef000 size=0x1000 parent=0x2 p.vaddr=0x1ef000 + space=0x5 vaddr=0x1f0000 size=0x1000 parent=0x2 p.vaddr=0x1f0000 + space=0x5 vaddr=0x1f1000 size=0x1000 parent=0x2 p.vaddr=0x1f1000 + space=0x5 vaddr=0x1f2000 size=0x1000 parent=0x2 p.vaddr=0x1f2000 + space=0x5 vaddr=0x1f3000 size=0x1000 parent=0x2 p.vaddr=0x1f3000 + space=0x5 vaddr=0x1f4000 size=0x1000 parent=0x2 p.vaddr=0x1f4000 + space=0x5 vaddr=0x1f5000 size=0x1000 parent=0x2 p.vaddr=0x1f5000 + space=0x5 vaddr=0x1f6000 size=0x1000 parent=0x2 p.vaddr=0x1f6000 + space=0x5 vaddr=0x1f7000 size=0x1000 parent=0x2 p.vaddr=0x1f7000 + space=0x5 vaddr=0x1f8000 size=0x1000 parent=0x2 p.vaddr=0x1f8000 + space=0x5 vaddr=0x1f9000 size=0x1000 parent=0x2 p.vaddr=0x1f9000 + space=0x5 vaddr=0x1fa000 size=0x1000 parent=0x2 p.vaddr=0x1fa000 + space=0x5 vaddr=0x1fb000 size=0x1000 parent=0x2 p.vaddr=0x1fb000 + space=0x5 vaddr=0x1fc000 size=0x1000 parent=0x2 p.vaddr=0x1fc000 + space=0x5 vaddr=0x1fd000 size=0x1000 parent=0x2 p.vaddr=0x1fd000 + space=0x5 vaddr=0x1fe000 size=0x1000 parent=0x2 p.vaddr=0x1fe000 + space=0x5 vaddr=0x1ff000 size=0x1000 parent=0x2 p.vaddr=0x1ff000 + space=0x5 vaddr=0x200000 size=0x1000 parent=0x2 p.vaddr=0x200000 + space=0x5 vaddr=0x201000 size=0x1000 parent=0x2 p.vaddr=0x201000 + space=0x5 vaddr=0x202000 size=0x1000 parent=0x2 p.vaddr=0x202000 + space=0x5 vaddr=0x203000 size=0x1000 parent=0x2 p.vaddr=0x203000 + space=0x5 vaddr=0x204000 size=0x1000 parent=0x2 p.vaddr=0x204000 + space=0x5 vaddr=0x205000 size=0x1000 parent=0x2 p.vaddr=0x205000 + space=0x5 vaddr=0x206000 size=0x1000 parent=0x2 p.vaddr=0x206000 + space=0x5 vaddr=0x207000 size=0x1000 parent=0x2 p.vaddr=0x207000 + space=0x5 vaddr=0x208000 size=0x1000 parent=0x2 p.vaddr=0x208000 + space=0x5 vaddr=0x209000 size=0x1000 parent=0x2 p.vaddr=0x209000 + space=0x5 vaddr=0x20a000 size=0x1000 parent=0x2 p.vaddr=0x20a000 + space=0x5 vaddr=0x20b000 size=0x1000 parent=0x2 p.vaddr=0x20b000 + space=0x5 vaddr=0x20c000 size=0x1000 parent=0x2 p.vaddr=0x20c000 + space=0x5 vaddr=0x20d000 size=0x1000 parent=0x2 p.vaddr=0x20d000 + space=0x5 vaddr=0x20e000 size=0x1000 parent=0x2 p.vaddr=0x20e000 + space=0x5 vaddr=0x20f000 size=0x1000 parent=0x2 p.vaddr=0x20f000 + space=0x5 vaddr=0x210000 size=0x1000 parent=0x2 p.vaddr=0x210000 + space=0x5 vaddr=0x211000 size=0x1000 parent=0x2 p.vaddr=0x211000 + space=0x5 vaddr=0x212000 size=0x1000 parent=0x2 p.vaddr=0x212000 + space=0x5 vaddr=0x213000 size=0x1000 parent=0x2 p.vaddr=0x213000 + space=0x5 vaddr=0x214000 size=0x1000 parent=0x2 p.vaddr=0x214000 + space=0x5 vaddr=0x215000 size=0x1000 parent=0x2 p.vaddr=0x215000 + space=0x5 vaddr=0x216000 size=0x1000 parent=0x2 p.vaddr=0x216000 + space=0x5 vaddr=0x217000 size=0x1000 parent=0x2 p.vaddr=0x217000 + space=0x5 vaddr=0x218000 size=0x1000 parent=0x2 p.vaddr=0x218000 + space=0x5 vaddr=0x219000 size=0x1000 parent=0x2 p.vaddr=0x219000 + space=0x5 vaddr=0x21a000 size=0x1000 parent=0x2 p.vaddr=0x21a000 + space=0x5 vaddr=0x21b000 size=0x1000 parent=0x2 p.vaddr=0x21b000 + space=0x5 vaddr=0x21c000 size=0x1000 parent=0x2 p.vaddr=0x21c000 + space=0x5 vaddr=0x21d000 size=0x1000 parent=0x2 p.vaddr=0x21d000 + space=0x5 vaddr=0x21e000 size=0x1000 parent=0x2 p.vaddr=0x21e000 + space=0x5 vaddr=0x21f000 size=0x1000 parent=0x2 p.vaddr=0x21f000 + space=0x5 vaddr=0x220000 size=0x1000 parent=0x2 p.vaddr=0x220000 + space=0x5 vaddr=0x221000 size=0x1000 parent=0x2 p.vaddr=0x221000 + space=0x5 vaddr=0x222000 size=0x1000 parent=0x2 p.vaddr=0x222000 + space=0x5 vaddr=0x223000 size=0x1000 parent=0x2 p.vaddr=0x223000 + space=0x5 vaddr=0x224000 size=0x1000 parent=0x2 p.vaddr=0x224000 + space=0x5 vaddr=0x225000 size=0x1000 parent=0x2 p.vaddr=0x225000 + space=0x5 vaddr=0x226000 size=0x1000 parent=0x2 p.vaddr=0x226000 + space=0x5 vaddr=0x227000 size=0x1000 parent=0x2 p.vaddr=0x227000 + space=0x5 vaddr=0x228000 size=0x1000 parent=0x2 p.vaddr=0x228000 + space=0x5 vaddr=0x229000 size=0x1000 parent=0x2 p.vaddr=0x229000 + space=0x5 vaddr=0x22a000 size=0x1000 parent=0x2 p.vaddr=0x22a000 + space=0x5 vaddr=0x22b000 size=0x1000 parent=0x2 p.vaddr=0x22b000 + space=0x5 vaddr=0x22c000 size=0x1000 parent=0x2 p.vaddr=0x22c000 + space=0x5 vaddr=0x22d000 size=0x1000 parent=0x2 p.vaddr=0x22d000 + space=0x5 vaddr=0x22e000 size=0x1000 parent=0x2 p.vaddr=0x22e000 + space=0x5 vaddr=0x22f000 size=0x1000 parent=0x2 p.vaddr=0x22f000 + space=0x5 vaddr=0x230000 size=0x1000 parent=0x2 p.vaddr=0x230000 + space=0x5 vaddr=0x231000 size=0x1000 parent=0x2 p.vaddr=0x231000 + space=0x5 vaddr=0x232000 size=0x1000 parent=0x2 p.vaddr=0x232000 + space=0x5 vaddr=0x233000 size=0x1000 parent=0x2 p.vaddr=0x233000 + space=0x5 vaddr=0x234000 size=0x1000 parent=0x2 p.vaddr=0x234000 + space=0x5 vaddr=0x235000 size=0x1000 parent=0x2 p.vaddr=0x235000 + space=0x5 vaddr=0x236000 size=0x1000 parent=0x2 p.vaddr=0x236000 + space=0x5 vaddr=0x237000 size=0x1000 parent=0x2 p.vaddr=0x237000 + space=0x5 vaddr=0x238000 size=0x1000 parent=0x2 p.vaddr=0x238000 + space=0x5 vaddr=0x239000 size=0x1000 parent=0x2 p.vaddr=0x239000 + space=0x5 vaddr=0x23a000 size=0x1000 parent=0x2 p.vaddr=0x23a000 + space=0x5 vaddr=0x23b000 size=0x1000 parent=0x2 p.vaddr=0x23b000 + space=0x5 vaddr=0x23c000 size=0x1000 parent=0x2 p.vaddr=0x23c000 + space=0x5 vaddr=0x23d000 size=0x1000 parent=0x2 p.vaddr=0x23d000 + space=0x5 vaddr=0x23e000 size=0x1000 parent=0x2 p.vaddr=0x23e000 + space=0x5 vaddr=0x23f000 size=0x1000 parent=0x2 p.vaddr=0x23f000 + space=0x5 vaddr=0x240000 size=0x1000 parent=0x2 p.vaddr=0x240000 + space=0x5 vaddr=0x241000 size=0x1000 parent=0x2 p.vaddr=0x241000 + space=0x5 vaddr=0x242000 size=0x1000 parent=0x2 p.vaddr=0x242000 + space=0x5 vaddr=0x243000 size=0x1000 parent=0x2 p.vaddr=0x243000 + space=0x5 vaddr=0x244000 size=0x1000 parent=0x2 p.vaddr=0x244000 + space=0x5 vaddr=0x245000 size=0x1000 parent=0x2 p.vaddr=0x245000 + space=0x5 vaddr=0x246000 size=0x1000 parent=0x2 p.vaddr=0x246000 + space=0x5 vaddr=0x247000 size=0x1000 parent=0x2 p.vaddr=0x247000 + space=0x5 vaddr=0x248000 size=0x1000 parent=0x2 p.vaddr=0x248000 + space=0x5 vaddr=0x249000 size=0x1000 parent=0x2 p.vaddr=0x249000 + space=0x5 vaddr=0x24a000 size=0x1000 parent=0x2 p.vaddr=0x24a000 + space=0x5 vaddr=0x24b000 size=0x1000 parent=0x2 p.vaddr=0x24b000 + space=0x5 vaddr=0x24c000 size=0x1000 parent=0x2 p.vaddr=0x24c000 + space=0x5 vaddr=0x24d000 size=0x1000 parent=0x2 p.vaddr=0x24d000 + space=0x5 vaddr=0x24e000 size=0x1000 parent=0x2 p.vaddr=0x24e000 + space=0x5 vaddr=0x24f000 size=0x1000 parent=0x2 p.vaddr=0x24f000 + space=0x5 vaddr=0x250000 size=0x1000 parent=0x2 p.vaddr=0x250000 + space=0x5 vaddr=0x251000 size=0x1000 parent=0x2 p.vaddr=0x251000 + space=0x5 vaddr=0x252000 size=0x1000 parent=0x2 p.vaddr=0x252000 + space=0x5 vaddr=0x253000 size=0x1000 parent=0x2 p.vaddr=0x253000 + space=0x5 vaddr=0x254000 size=0x1000 parent=0x2 p.vaddr=0x254000 + space=0x5 vaddr=0x255000 size=0x1000 parent=0x2 p.vaddr=0x255000 + space=0x5 vaddr=0x256000 size=0x1000 parent=0x2 p.vaddr=0x256000 + space=0x5 vaddr=0x257000 size=0x1000 parent=0x2 p.vaddr=0x257000 + space=0x5 vaddr=0x258000 size=0x1000 parent=0x2 p.vaddr=0x258000 + space=0x5 vaddr=0x259000 size=0x1000 parent=0x2 p.vaddr=0x259000 + space=0x5 vaddr=0x25a000 size=0x1000 parent=0x2 p.vaddr=0x25a000 + space=0x5 vaddr=0x25b000 size=0x1000 parent=0x2 p.vaddr=0x25b000 + space=0x5 vaddr=0x25c000 size=0x1000 parent=0x2 p.vaddr=0x25c000 + space=0x5 vaddr=0x25d000 size=0x1000 parent=0x2 p.vaddr=0x25d000 + space=0x5 vaddr=0x25e000 size=0x1000 parent=0x2 p.vaddr=0x25e000 + space=0x5 vaddr=0x25f000 size=0x1000 parent=0x2 p.vaddr=0x25f000 + space=0x5 vaddr=0x260000 size=0x1000 parent=0x2 p.vaddr=0x260000 + space=0x5 vaddr=0x261000 size=0x1000 parent=0x2 p.vaddr=0x261000 + space=0x5 vaddr=0x262000 size=0x1000 parent=0x2 p.vaddr=0x262000 + space=0x5 vaddr=0x263000 size=0x1000 parent=0x2 p.vaddr=0x263000 + space=0x5 vaddr=0x264000 size=0x1000 parent=0x2 p.vaddr=0x264000 + space=0x5 vaddr=0x265000 size=0x1000 parent=0x2 p.vaddr=0x265000 + space=0x5 vaddr=0x266000 size=0x1000 parent=0x2 p.vaddr=0x266000 + space=0x5 vaddr=0x267000 size=0x1000 parent=0x2 p.vaddr=0x267000 + space=0x5 vaddr=0x268000 size=0x1000 parent=0x2 p.vaddr=0x268000 + space=0x5 vaddr=0x269000 size=0x1000 parent=0x2 p.vaddr=0x269000 + space=0x5 vaddr=0x26a000 size=0x1000 parent=0x2 p.vaddr=0x26a000 + space=0x5 vaddr=0x26b000 size=0x1000 parent=0x2 p.vaddr=0x26b000 + space=0x5 vaddr=0x26c000 size=0x1000 parent=0x2 p.vaddr=0x26c000 + space=0x5 vaddr=0x26d000 size=0x1000 parent=0x2 p.vaddr=0x26d000 + space=0x5 vaddr=0x26e000 size=0x1000 parent=0x2 p.vaddr=0x26e000 + space=0x5 vaddr=0x26f000 size=0x1000 parent=0x2 p.vaddr=0x26f000 + space=0x5 vaddr=0x270000 size=0x1000 parent=0x2 p.vaddr=0x270000 + space=0x5 vaddr=0x271000 size=0x1000 parent=0x2 p.vaddr=0x271000 + space=0x5 vaddr=0x272000 size=0x1000 parent=0x2 p.vaddr=0x272000 + space=0x5 vaddr=0x273000 size=0x1000 parent=0x2 p.vaddr=0x273000 + space=0x5 vaddr=0x274000 size=0x1000 parent=0x2 p.vaddr=0x274000 + space=0x5 vaddr=0x275000 size=0x1000 parent=0x2 p.vaddr=0x275000 + space=0x5 vaddr=0x276000 size=0x1000 parent=0x2 p.vaddr=0x276000 + space=0x5 vaddr=0x277000 size=0x1000 parent=0x2 p.vaddr=0x277000 + space=0x5 vaddr=0x278000 size=0x1000 parent=0x2 p.vaddr=0x278000 + space=0x5 vaddr=0x279000 size=0x1000 parent=0x2 p.vaddr=0x279000 + space=0x5 vaddr=0x27a000 size=0x1000 parent=0x2 p.vaddr=0x27a000 + space=0x5 vaddr=0x27b000 size=0x1000 parent=0x2 p.vaddr=0x27b000 + space=0x5 vaddr=0x27c000 size=0x1000 parent=0x2 p.vaddr=0x27c000 + space=0x5 vaddr=0x27d000 size=0x1000 parent=0x2 p.vaddr=0x27d000 + space=0x5 vaddr=0x27e000 size=0x1000 parent=0x2 p.vaddr=0x27e000 + space=0x5 vaddr=0x27f000 size=0x1000 parent=0x2 p.vaddr=0x27f000 + space=0x5 vaddr=0x280000 size=0x1000 parent=0x2 p.vaddr=0x280000 + space=0x5 vaddr=0x281000 size=0x1000 parent=0x2 p.vaddr=0x281000 + space=0x5 vaddr=0x282000 size=0x1000 parent=0x2 p.vaddr=0x282000 + space=0x5 vaddr=0x283000 size=0x1000 parent=0x2 p.vaddr=0x283000 + space=0x5 vaddr=0x284000 size=0x1000 parent=0x2 p.vaddr=0x284000 + space=0x5 vaddr=0x285000 size=0x1000 parent=0x2 p.vaddr=0x285000 + space=0x5 vaddr=0x286000 size=0x1000 parent=0x2 p.vaddr=0x286000 + space=0x5 vaddr=0x287000 size=0x1000 parent=0x2 p.vaddr=0x287000 + space=0x5 vaddr=0x288000 size=0x1000 parent=0x2 p.vaddr=0x288000 + space=0x5 vaddr=0x289000 size=0x1000 parent=0x2 p.vaddr=0x289000 + space=0x5 vaddr=0x28a000 size=0x1000 parent=0x2 p.vaddr=0x28a000 + space=0x5 vaddr=0x28b000 size=0x1000 parent=0x2 p.vaddr=0x28b000 + space=0x5 vaddr=0x28c000 size=0x1000 parent=0x2 p.vaddr=0x28c000 + space=0x5 vaddr=0x28d000 size=0x1000 parent=0x2 p.vaddr=0x28d000 + space=0x5 vaddr=0x28e000 size=0x1000 parent=0x2 p.vaddr=0x28e000 + space=0x5 vaddr=0x28f000 size=0x1000 parent=0x2 p.vaddr=0x28f000 + space=0x5 vaddr=0x290000 size=0x1000 parent=0x2 p.vaddr=0x290000 + space=0x5 vaddr=0x291000 size=0x1000 parent=0x2 p.vaddr=0x291000 + space=0x5 vaddr=0x292000 size=0x1000 parent=0x2 p.vaddr=0x292000 + space=0x5 vaddr=0x293000 size=0x1000 parent=0x2 p.vaddr=0x293000 + space=0x5 vaddr=0x294000 size=0x1000 parent=0x2 p.vaddr=0x294000 + space=0x5 vaddr=0x295000 size=0x1000 parent=0x2 p.vaddr=0x295000 + space=0x5 vaddr=0x296000 size=0x1000 parent=0x2 p.vaddr=0x296000 + space=0x5 vaddr=0x297000 size=0x1000 parent=0x2 p.vaddr=0x297000 + space=0x5 vaddr=0x298000 size=0x1000 parent=0x2 p.vaddr=0x298000 + space=0x5 vaddr=0x299000 size=0x1000 parent=0x2 p.vaddr=0x299000 + space=0x5 vaddr=0x29a000 size=0x1000 parent=0x2 p.vaddr=0x29a000 + space=0x5 vaddr=0x29b000 size=0x1000 parent=0x2 p.vaddr=0x29b000 + space=0x5 vaddr=0x29c000 size=0x1000 parent=0x2 p.vaddr=0x29c000 + space=0x5 vaddr=0x29d000 size=0x1000 parent=0x2 p.vaddr=0x29d000 + space=0x5 vaddr=0x29e000 size=0x1000 parent=0x2 p.vaddr=0x29e000 + space=0x5 vaddr=0x29f000 size=0x1000 parent=0x2 p.vaddr=0x29f000 + space=0x5 vaddr=0x2a0000 size=0x1000 parent=0x2 p.vaddr=0x2a0000 + space=0x5 vaddr=0x2a1000 size=0x1000 parent=0x2 p.vaddr=0x2a1000 + space=0x5 vaddr=0x2a2000 size=0x1000 parent=0x2 p.vaddr=0x2a2000 + space=0x5 vaddr=0x2a3000 size=0x1000 parent=0x2 p.vaddr=0x2a3000 + space=0x5 vaddr=0x2a4000 size=0x1000 parent=0x2 p.vaddr=0x2a4000 + space=0x5 vaddr=0x2a5000 size=0x1000 parent=0x2 p.vaddr=0x2a5000 + space=0x5 vaddr=0x2a6000 size=0x1000 parent=0x2 p.vaddr=0x2a6000 + space=0x5 vaddr=0x2a7000 size=0x1000 parent=0x2 p.vaddr=0x2a7000 + space=0x5 vaddr=0x2a8000 size=0x1000 parent=0x2 p.vaddr=0x2a8000 + space=0x5 vaddr=0x2a9000 size=0x1000 parent=0x2 p.vaddr=0x2a9000 + space=0x5 vaddr=0x2aa000 size=0x1000 parent=0x2 p.vaddr=0x2aa000 + space=0x5 vaddr=0x2ab000 size=0x1000 parent=0x2 p.vaddr=0x2ab000 + space=0x5 vaddr=0x2ac000 size=0x1000 parent=0x2 p.vaddr=0x2ac000 + space=0x5 vaddr=0x2ad000 size=0x1000 parent=0x2 p.vaddr=0x2ad000 + space=0x5 vaddr=0x2ae000 size=0x1000 parent=0x2 p.vaddr=0x2ae000 + space=0x5 vaddr=0x2af000 size=0x1000 parent=0x2 p.vaddr=0x2af000 + space=0x5 vaddr=0x2b0000 size=0x1000 parent=0x2 p.vaddr=0x2b0000 + space=0x5 vaddr=0x2b1000 size=0x1000 parent=0x2 p.vaddr=0x2b1000 + space=0x5 vaddr=0x2b2000 size=0x1000 parent=0x2 p.vaddr=0x2b2000 + space=0x5 vaddr=0x2b3000 size=0x1000 parent=0x2 p.vaddr=0x2b3000 + space=0x5 vaddr=0x2b4000 size=0x1000 parent=0x2 p.vaddr=0x2b4000 + space=0x5 vaddr=0x2b5000 size=0x1000 parent=0x2 p.vaddr=0x2b5000 + space=0x5 vaddr=0x2b6000 size=0x1000 parent=0x2 p.vaddr=0x2b6000 + space=0x5 vaddr=0x2b7000 size=0x1000 parent=0x2 p.vaddr=0x2b7000 + space=0x5 vaddr=0x2b8000 size=0x1000 parent=0x2 p.vaddr=0x2b8000 + space=0x5 vaddr=0x2b9000 size=0x1000 parent=0x2 p.vaddr=0x2b9000 + space=0x5 vaddr=0x2ba000 size=0x1000 parent=0x2 p.vaddr=0x2ba000 + space=0x5 vaddr=0x2bb000 size=0x1000 parent=0x2 p.vaddr=0x2bb000 + space=0x5 vaddr=0x2bc000 size=0x1000 parent=0x2 p.vaddr=0x2bc000 + space=0x5 vaddr=0x2bd000 size=0x1000 parent=0x2 p.vaddr=0x2bd000 + space=0x5 vaddr=0x2be000 size=0x1000 parent=0x2 p.vaddr=0x2be000 + space=0x5 vaddr=0x2bf000 size=0x1000 parent=0x2 p.vaddr=0x2bf000 + space=0x5 vaddr=0x2c0000 size=0x1000 parent=0x2 p.vaddr=0x2c0000 + space=0x5 vaddr=0x2c1000 size=0x1000 parent=0x2 p.vaddr=0x2c1000 + space=0x5 vaddr=0x2c2000 size=0x1000 parent=0x2 p.vaddr=0x2c2000 + space=0x5 vaddr=0x2c3000 size=0x1000 parent=0x2 p.vaddr=0x2c3000 + space=0x5 vaddr=0x2c4000 size=0x1000 parent=0x2 p.vaddr=0x2c4000 + space=0x5 vaddr=0x2c5000 size=0x1000 parent=0x2 p.vaddr=0x2c5000 + space=0x5 vaddr=0x2c6000 size=0x1000 parent=0x2 p.vaddr=0x2c6000 + space=0x5 vaddr=0x2c7000 size=0x1000 parent=0x2 p.vaddr=0x2c7000 + space=0x5 vaddr=0x2c8000 size=0x1000 parent=0x2 p.vaddr=0x2c8000 + space=0x5 vaddr=0x2c9000 size=0x1000 parent=0x2 p.vaddr=0x2c9000 + space=0x5 vaddr=0x2ca000 size=0x1000 parent=0x2 p.vaddr=0x2ca000 + space=0x5 vaddr=0x2cb000 size=0x1000 parent=0x2 p.vaddr=0x2cb000 + space=0x5 vaddr=0x2cc000 size=0x1000 parent=0x2 p.vaddr=0x2cc000 + space=0x5 vaddr=0x2cd000 size=0x1000 parent=0x2 p.vaddr=0x2cd000 + space=0x5 vaddr=0x2ce000 size=0x1000 parent=0x2 p.vaddr=0x2ce000 + space=0x5 vaddr=0x2cf000 size=0x1000 parent=0x2 p.vaddr=0x2cf000 + space=0x5 vaddr=0x2d0000 size=0x1000 parent=0x2 p.vaddr=0x2d0000 + space=0x5 vaddr=0x2d1000 size=0x1000 parent=0x2 p.vaddr=0x2d1000 + space=0x5 vaddr=0x2d2000 size=0x1000 parent=0x2 p.vaddr=0x2d2000 + space=0x5 vaddr=0x2d3000 size=0x1000 parent=0x2 p.vaddr=0x2d3000 + space=0x5 vaddr=0x2d4000 size=0x1000 parent=0x2 p.vaddr=0x2d4000 + space=0x5 vaddr=0x2d5000 size=0x1000 parent=0x2 p.vaddr=0x2d5000 + space=0x5 vaddr=0x2d6000 size=0x1000 parent=0x2 p.vaddr=0x2d6000 + space=0x5 vaddr=0x2d7000 size=0x1000 parent=0x2 p.vaddr=0x2d7000 + space=0x5 vaddr=0x2d8000 size=0x1000 parent=0x2 p.vaddr=0x2d8000 + space=0x5 vaddr=0x2d9000 size=0x1000 parent=0x2 p.vaddr=0x2d9000 + space=0x5 vaddr=0x2da000 size=0x1000 parent=0x2 p.vaddr=0x2da000 + space=0x5 vaddr=0x2db000 size=0x1000 parent=0x2 p.vaddr=0x2db000 + space=0x5 vaddr=0x2dc000 size=0x1000 parent=0x2 p.vaddr=0x2dc000 + space=0x5 vaddr=0x2dd000 size=0x1000 parent=0x2 p.vaddr=0x2dd000 + space=0x5 vaddr=0x2de000 size=0x1000 parent=0x2 p.vaddr=0x2de000 + space=0x5 vaddr=0x2df000 size=0x1000 parent=0x2 p.vaddr=0x2df000 + space=0x5 vaddr=0x2e0000 size=0x1000 parent=0x2 p.vaddr=0x2e0000 + space=0x5 vaddr=0x2e1000 size=0x1000 parent=0x2 p.vaddr=0x2e1000 + space=0x5 vaddr=0x2e2000 size=0x1000 parent=0x2 p.vaddr=0x2e2000 + space=0x5 vaddr=0x2e3000 size=0x1000 parent=0x2 p.vaddr=0x2e3000 + space=0x5 vaddr=0x2e4000 size=0x1000 parent=0x2 p.vaddr=0x2e4000 + space=0x5 vaddr=0x2e5000 size=0x1000 parent=0x2 p.vaddr=0x2e5000 + space=0x5 vaddr=0x2e6000 size=0x1000 parent=0x2 p.vaddr=0x2e6000 + space=0x5 vaddr=0x2e7000 size=0x1000 parent=0x2 p.vaddr=0x2e7000 + space=0x5 vaddr=0x2e8000 size=0x1000 parent=0x2 p.vaddr=0x2e8000 + space=0x5 vaddr=0x2e9000 size=0x1000 parent=0x2 p.vaddr=0x2e9000 + space=0x5 vaddr=0x2ea000 size=0x1000 parent=0x2 p.vaddr=0x2ea000 + space=0x5 vaddr=0x2eb000 size=0x1000 parent=0x2 p.vaddr=0x2eb000 + space=0x5 vaddr=0x2ec000 size=0x1000 parent=0x2 p.vaddr=0x2ec000 + space=0x5 vaddr=0x2ed000 size=0x1000 parent=0x2 p.vaddr=0x2ed000 + space=0x5 vaddr=0x2ee000 size=0x1000 parent=0x2 p.vaddr=0x2ee000 + space=0x5 vaddr=0x2ef000 size=0x1000 parent=0x2 p.vaddr=0x2ef000 + space=0x5 vaddr=0x2f0000 size=0x1000 parent=0x2 p.vaddr=0x2f0000 + space=0x5 vaddr=0x2f1000 size=0x1000 parent=0x2 p.vaddr=0x2f1000 + space=0x5 vaddr=0x2f2000 size=0x1000 parent=0x2 p.vaddr=0x2f2000 + space=0x5 vaddr=0x2f3000 size=0x1000 parent=0x2 p.vaddr=0x2f3000 + space=0x5 vaddr=0x2f4000 size=0x1000 parent=0x2 p.vaddr=0x2f4000 + space=0x5 vaddr=0x2f5000 size=0x1000 parent=0x2 p.vaddr=0x2f5000 + space=0x5 vaddr=0x2f6000 size=0x1000 parent=0x2 p.vaddr=0x2f6000 + space=0x5 vaddr=0x2f7000 size=0x1000 parent=0x2 p.vaddr=0x2f7000 + space=0x5 vaddr=0x2f8000 size=0x1000 parent=0x2 p.vaddr=0x2f8000 + space=0x5 vaddr=0x2f9000 size=0x1000 parent=0x2 p.vaddr=0x2f9000 + space=0x5 vaddr=0x2fa000 size=0x1000 parent=0x2 p.vaddr=0x2fa000 + space=0x5 vaddr=0x2fb000 size=0x1000 parent=0x2 p.vaddr=0x2fb000 + space=0x5 vaddr=0x2fc000 size=0x1000 parent=0x2 p.vaddr=0x2fc000 + space=0x5 vaddr=0x2fd000 size=0x1000 parent=0x2 p.vaddr=0x2fd000 + space=0x5 vaddr=0x2fe000 size=0x1000 parent=0x2 p.vaddr=0x2fe000 + space=0x5 vaddr=0x2ff000 size=0x1000 parent=0x2 p.vaddr=0x2ff000 + space=0x5 vaddr=0x300000 size=0x1000 parent=0x2 p.vaddr=0x300000 + space=0x5 vaddr=0x301000 size=0x1000 parent=0x2 p.vaddr=0x301000 + space=0x5 vaddr=0x302000 size=0x1000 parent=0x2 p.vaddr=0x302000 + space=0x5 vaddr=0x303000 size=0x1000 parent=0x2 p.vaddr=0x303000 + space=0x5 vaddr=0x304000 size=0x1000 parent=0x2 p.vaddr=0x304000 + space=0x5 vaddr=0x305000 size=0x1000 parent=0x2 p.vaddr=0x305000 + space=0x5 vaddr=0x306000 size=0x1000 parent=0x2 p.vaddr=0x306000 + space=0x5 vaddr=0x307000 size=0x1000 parent=0x2 p.vaddr=0x307000 + space=0x5 vaddr=0x308000 size=0x1000 parent=0x2 p.vaddr=0x308000 + space=0x5 vaddr=0x309000 size=0x1000 parent=0x2 p.vaddr=0x309000 + space=0x5 vaddr=0x30a000 size=0x1000 parent=0x2 p.vaddr=0x30a000 + space=0x5 vaddr=0x30b000 size=0x1000 parent=0x2 p.vaddr=0x30b000 + space=0x5 vaddr=0x30c000 size=0x1000 parent=0x2 p.vaddr=0x30c000 + space=0x5 vaddr=0x30d000 size=0x1000 parent=0x2 p.vaddr=0x30d000 + space=0x5 vaddr=0x30e000 size=0x1000 parent=0x2 p.vaddr=0x30e000 + space=0x5 vaddr=0x30f000 size=0x1000 parent=0x2 p.vaddr=0x30f000 + space=0x5 vaddr=0x310000 size=0x1000 parent=0x2 p.vaddr=0x310000 + space=0x5 vaddr=0x311000 size=0x1000 parent=0x2 p.vaddr=0x311000 + space=0x5 vaddr=0x312000 size=0x1000 parent=0x2 p.vaddr=0x312000 + space=0x5 vaddr=0x313000 size=0x1000 parent=0x2 p.vaddr=0x313000 + space=0x5 vaddr=0x314000 size=0x1000 parent=0x2 p.vaddr=0x314000 + space=0x5 vaddr=0x315000 size=0x1000 parent=0x2 p.vaddr=0x315000 + space=0x5 vaddr=0x316000 size=0x1000 parent=0x2 p.vaddr=0x316000 + space=0x5 vaddr=0x317000 size=0x1000 parent=0x2 p.vaddr=0x317000 + space=0x5 vaddr=0x318000 size=0x1000 parent=0x2 p.vaddr=0x318000 + space=0x5 vaddr=0x319000 size=0x1000 parent=0x2 p.vaddr=0x319000 + space=0x5 vaddr=0x31a000 size=0x1000 parent=0x2 p.vaddr=0x31a000 + space=0x5 vaddr=0x31b000 size=0x1000 parent=0x2 p.vaddr=0x31b000 + space=0x5 vaddr=0x31c000 size=0x1000 parent=0x2 p.vaddr=0x31c000 + space=0x5 vaddr=0x31d000 size=0x1000 parent=0x2 p.vaddr=0x31d000 + space=0x5 vaddr=0x31e000 size=0x1000 parent=0x2 p.vaddr=0x31e000 + space=0x5 vaddr=0x31f000 size=0x1000 parent=0x2 p.vaddr=0x31f000 + space=0x5 vaddr=0x320000 size=0x1000 parent=0x2 p.vaddr=0x320000 + space=0x5 vaddr=0x321000 size=0x1000 parent=0x2 p.vaddr=0x321000 + space=0x5 vaddr=0x322000 size=0x1000 parent=0x2 p.vaddr=0x322000 + space=0x5 vaddr=0x323000 size=0x1000 parent=0x2 p.vaddr=0x323000 + space=0x5 vaddr=0x324000 size=0x1000 parent=0x2 p.vaddr=0x324000 + space=0x5 vaddr=0x325000 size=0x1000 parent=0x2 p.vaddr=0x325000 + space=0x5 vaddr=0x326000 size=0x1000 parent=0x2 p.vaddr=0x326000 + space=0x5 vaddr=0x327000 size=0x1000 parent=0x2 p.vaddr=0x327000 + space=0x5 vaddr=0x328000 size=0x1000 parent=0x2 p.vaddr=0x328000 + space=0x5 vaddr=0x329000 size=0x1000 parent=0x2 p.vaddr=0x329000 + space=0x5 vaddr=0x32a000 size=0x1000 parent=0x2 p.vaddr=0x32a000 + space=0x5 vaddr=0x32b000 size=0x1000 parent=0x2 p.vaddr=0x32b000 + space=0x5 vaddr=0x32c000 size=0x1000 parent=0x2 p.vaddr=0x32c000 + space=0x5 vaddr=0x32d000 size=0x1000 parent=0x2 p.vaddr=0x32d000 + space=0x5 vaddr=0x32e000 size=0x1000 parent=0x2 p.vaddr=0x32e000 + space=0x5 vaddr=0x32f000 size=0x1000 parent=0x2 p.vaddr=0x32f000 + space=0x5 vaddr=0x330000 size=0x1000 parent=0x2 p.vaddr=0x330000 + space=0x5 vaddr=0x331000 size=0x1000 parent=0x2 p.vaddr=0x331000 + space=0x5 vaddr=0x332000 size=0x1000 parent=0x2 p.vaddr=0x332000 + space=0x5 vaddr=0x333000 size=0x1000 parent=0x2 p.vaddr=0x333000 + space=0x5 vaddr=0x334000 size=0x1000 parent=0x2 p.vaddr=0x334000 + space=0x5 vaddr=0x335000 size=0x1000 parent=0x2 p.vaddr=0x335000 + space=0x5 vaddr=0x336000 size=0x1000 parent=0x2 p.vaddr=0x336000 + space=0x5 vaddr=0x337000 size=0x1000 parent=0x2 p.vaddr=0x337000 + space=0x5 vaddr=0x338000 size=0x1000 parent=0x2 p.vaddr=0x338000 + space=0x5 vaddr=0x339000 size=0x1000 parent=0x2 p.vaddr=0x339000 + space=0x5 vaddr=0x33a000 size=0x1000 parent=0x2 p.vaddr=0x33a000 + space=0x5 vaddr=0x33b000 size=0x1000 parent=0x2 p.vaddr=0x33b000 + space=0x5 vaddr=0x33c000 size=0x1000 parent=0x2 p.vaddr=0x33c000 + space=0x5 vaddr=0x33d000 size=0x1000 parent=0x2 p.vaddr=0x33d000 + space=0x5 vaddr=0x33e000 size=0x1000 parent=0x2 p.vaddr=0x33e000 + space=0x5 vaddr=0x33f000 size=0x1000 parent=0x2 p.vaddr=0x33f000 + space=0x5 vaddr=0x340000 size=0x1000 parent=0x2 p.vaddr=0x340000 + space=0x5 vaddr=0x341000 size=0x1000 parent=0x2 p.vaddr=0x341000 + space=0x5 vaddr=0x342000 size=0x1000 parent=0x2 p.vaddr=0x342000 + space=0x5 vaddr=0x343000 size=0x1000 parent=0x2 p.vaddr=0x343000 + space=0x5 vaddr=0x344000 size=0x1000 parent=0x2 p.vaddr=0x344000 + space=0x5 vaddr=0x345000 size=0x1000 parent=0x2 p.vaddr=0x345000 + space=0x5 vaddr=0x346000 size=0x1000 parent=0x2 p.vaddr=0x346000 + space=0x5 vaddr=0x347000 size=0x1000 parent=0x2 p.vaddr=0x347000 + space=0x5 vaddr=0x348000 size=0x1000 parent=0x2 p.vaddr=0x348000 + space=0x5 vaddr=0x349000 size=0x1000 parent=0x2 p.vaddr=0x349000 + space=0x5 vaddr=0x34a000 size=0x1000 parent=0x2 p.vaddr=0x34a000 + space=0x5 vaddr=0x34b000 size=0x1000 parent=0x2 p.vaddr=0x34b000 + space=0x5 vaddr=0x34c000 size=0x1000 parent=0x2 p.vaddr=0x34c000 + space=0x5 vaddr=0x34d000 size=0x1000 parent=0x2 p.vaddr=0x34d000 + space=0x5 vaddr=0x34e000 size=0x1000 parent=0x2 p.vaddr=0x34e000 + space=0x5 vaddr=0x34f000 size=0x1000 parent=0x2 p.vaddr=0x34f000 + space=0x5 vaddr=0x350000 size=0x1000 parent=0x2 p.vaddr=0x350000 + space=0x5 vaddr=0x351000 size=0x1000 parent=0x2 p.vaddr=0x351000 + space=0x5 vaddr=0x352000 size=0x1000 parent=0x2 p.vaddr=0x352000 + space=0x5 vaddr=0x353000 size=0x1000 parent=0x2 p.vaddr=0x353000 + space=0x5 vaddr=0x354000 size=0x1000 parent=0x2 p.vaddr=0x354000 + space=0x5 vaddr=0x355000 size=0x1000 parent=0x2 p.vaddr=0x355000 + space=0x5 vaddr=0x356000 size=0x1000 parent=0x2 p.vaddr=0x356000 + space=0x5 vaddr=0x357000 size=0x1000 parent=0x2 p.vaddr=0x357000 + space=0x5 vaddr=0x358000 size=0x1000 parent=0x2 p.vaddr=0x358000 + space=0x5 vaddr=0x359000 size=0x1000 parent=0x2 p.vaddr=0x359000 + space=0x5 vaddr=0x35a000 size=0x1000 parent=0x2 p.vaddr=0x35a000 + space=0x5 vaddr=0x35b000 size=0x1000 parent=0x2 p.vaddr=0x35b000 + space=0x5 vaddr=0x35c000 size=0x1000 parent=0x2 p.vaddr=0x35c000 + space=0x5 vaddr=0x35d000 size=0x1000 parent=0x2 p.vaddr=0x35d000 + space=0x5 vaddr=0x35e000 size=0x1000 parent=0x2 p.vaddr=0x35e000 + space=0x5 vaddr=0x35f000 size=0x1000 parent=0x2 p.vaddr=0x35f000 + space=0x5 vaddr=0x360000 size=0x1000 parent=0x2 p.vaddr=0x360000 + space=0x5 vaddr=0x361000 size=0x1000 parent=0x2 p.vaddr=0x361000 + space=0x5 vaddr=0x362000 size=0x1000 parent=0x2 p.vaddr=0x362000 + space=0x5 vaddr=0x363000 size=0x1000 parent=0x2 p.vaddr=0x363000 + space=0x5 vaddr=0x364000 size=0x1000 parent=0x2 p.vaddr=0x364000 + space=0x5 vaddr=0x365000 size=0x1000 parent=0x2 p.vaddr=0x365000 + space=0x5 vaddr=0x366000 size=0x1000 parent=0x2 p.vaddr=0x366000 + space=0x5 vaddr=0x367000 size=0x1000 parent=0x2 p.vaddr=0x367000 + space=0x5 vaddr=0x368000 size=0x1000 parent=0x2 p.vaddr=0x368000 + space=0x5 vaddr=0x369000 size=0x1000 parent=0x2 p.vaddr=0x369000 + space=0x5 vaddr=0x36a000 size=0x1000 parent=0x2 p.vaddr=0x36a000 + space=0x5 vaddr=0x36b000 size=0x1000 parent=0x2 p.vaddr=0x36b000 + space=0x5 vaddr=0x36c000 size=0x1000 parent=0x2 p.vaddr=0x36c000 + space=0x5 vaddr=0x36d000 size=0x1000 parent=0x2 p.vaddr=0x36d000 + space=0x5 vaddr=0x36e000 size=0x1000 parent=0x2 p.vaddr=0x36e000 + space=0x5 vaddr=0x36f000 size=0x1000 parent=0x2 p.vaddr=0x36f000 + space=0x5 vaddr=0x370000 size=0x1000 parent=0x2 p.vaddr=0x370000 + space=0x5 vaddr=0x371000 size=0x1000 parent=0x2 p.vaddr=0x371000 + space=0x5 vaddr=0x372000 size=0x1000 parent=0x2 p.vaddr=0x372000 + space=0x5 vaddr=0x373000 size=0x1000 parent=0x2 p.vaddr=0x373000 + space=0x5 vaddr=0x374000 size=0x1000 parent=0x2 p.vaddr=0x374000 + space=0x5 vaddr=0x375000 size=0x1000 parent=0x2 p.vaddr=0x375000 + space=0x5 vaddr=0x376000 size=0x1000 parent=0x2 p.vaddr=0x376000 + space=0x5 vaddr=0x377000 size=0x1000 parent=0x2 p.vaddr=0x377000 + space=0x5 vaddr=0x378000 size=0x1000 parent=0x2 p.vaddr=0x378000 + space=0x5 vaddr=0x379000 size=0x1000 parent=0x2 p.vaddr=0x379000 + space=0x5 vaddr=0x37a000 size=0x1000 parent=0x2 p.vaddr=0x37a000 + space=0x5 vaddr=0x37b000 size=0x1000 parent=0x2 p.vaddr=0x37b000 + space=0x5 vaddr=0x37c000 size=0x1000 parent=0x2 p.vaddr=0x37c000 + space=0x5 vaddr=0x37d000 size=0x1000 parent=0x2 p.vaddr=0x37d000 + space=0x5 vaddr=0x37e000 size=0x1000 parent=0x2 p.vaddr=0x37e000 + space=0x5 vaddr=0x37f000 size=0x1000 parent=0x2 p.vaddr=0x37f000 + space=0x5 vaddr=0x380000 size=0x1000 parent=0x2 p.vaddr=0x380000 + space=0x5 vaddr=0x381000 size=0x1000 parent=0x2 p.vaddr=0x381000 + space=0x5 vaddr=0x382000 size=0x1000 parent=0x2 p.vaddr=0x382000 + space=0x5 vaddr=0x383000 size=0x1000 parent=0x2 p.vaddr=0x383000 + space=0x5 vaddr=0x384000 size=0x1000 parent=0x2 p.vaddr=0x384000 + space=0x5 vaddr=0x385000 size=0x1000 parent=0x2 p.vaddr=0x385000 + space=0x5 vaddr=0x386000 size=0x1000 parent=0x2 p.vaddr=0x386000 + space=0x5 vaddr=0x387000 size=0x1000 parent=0x2 p.vaddr=0x387000 + space=0x5 vaddr=0x388000 size=0x1000 parent=0x2 p.vaddr=0x388000 + space=0x5 vaddr=0x389000 size=0x1000 parent=0x2 p.vaddr=0x389000 + space=0x5 vaddr=0x38a000 size=0x1000 parent=0x2 p.vaddr=0x38a000 + space=0x5 vaddr=0x38b000 size=0x1000 parent=0x2 p.vaddr=0x38b000 + space=0x5 vaddr=0x38c000 size=0x1000 parent=0x2 p.vaddr=0x38c000 + space=0x5 vaddr=0x38d000 size=0x1000 parent=0x2 p.vaddr=0x38d000 + space=0x5 vaddr=0x38e000 size=0x1000 parent=0x2 p.vaddr=0x38e000 + space=0x5 vaddr=0x38f000 size=0x1000 parent=0x2 p.vaddr=0x38f000 + space=0x5 vaddr=0x390000 size=0x1000 parent=0x2 p.vaddr=0x390000 + space=0x5 vaddr=0x391000 size=0x1000 parent=0x2 p.vaddr=0x391000 + space=0x5 vaddr=0x392000 size=0x1000 parent=0x2 p.vaddr=0x392000 + space=0x5 vaddr=0x393000 size=0x1000 parent=0x2 p.vaddr=0x393000 + space=0x5 vaddr=0x394000 size=0x1000 parent=0x2 p.vaddr=0x394000 + space=0x5 vaddr=0x395000 size=0x1000 parent=0x2 p.vaddr=0x395000 + space=0x5 vaddr=0x396000 size=0x1000 parent=0x2 p.vaddr=0x396000 + space=0x5 vaddr=0x397000 size=0x1000 parent=0x2 p.vaddr=0x397000 + space=0x5 vaddr=0x398000 size=0x1000 parent=0x2 p.vaddr=0x398000 + space=0x5 vaddr=0x399000 size=0x1000 parent=0x2 p.vaddr=0x399000 + space=0x5 vaddr=0x39a000 size=0x1000 parent=0x2 p.vaddr=0x39a000 + space=0x5 vaddr=0x39b000 size=0x1000 parent=0x2 p.vaddr=0x39b000 + space=0x5 vaddr=0x39c000 size=0x1000 parent=0x2 p.vaddr=0x39c000 + space=0x5 vaddr=0x39d000 size=0x1000 parent=0x2 p.vaddr=0x39d000 + space=0x5 vaddr=0x39e000 size=0x1000 parent=0x2 p.vaddr=0x39e000 + space=0x5 vaddr=0x39f000 size=0x1000 parent=0x2 p.vaddr=0x39f000 + space=0x5 vaddr=0x3a0000 size=0x1000 parent=0x2 p.vaddr=0x3a0000 + space=0x5 vaddr=0x3a1000 size=0x1000 parent=0x2 p.vaddr=0x3a1000 + space=0x5 vaddr=0x3a2000 size=0x1000 parent=0x2 p.vaddr=0x3a2000 + space=0x5 vaddr=0x3a3000 size=0x1000 parent=0x2 p.vaddr=0x3a3000 + space=0x5 vaddr=0x3a4000 size=0x1000 parent=0x2 p.vaddr=0x3a4000 + space=0x5 vaddr=0x3a5000 size=0x1000 parent=0x2 p.vaddr=0x3a5000 + space=0x5 vaddr=0x3a6000 size=0x1000 parent=0x2 p.vaddr=0x3a6000 + space=0x5 vaddr=0x3a7000 size=0x1000 parent=0x2 p.vaddr=0x3a7000 + space=0x5 vaddr=0x3a8000 size=0x1000 parent=0x2 p.vaddr=0x3a8000 + space=0x5 vaddr=0x3a9000 size=0x1000 parent=0x2 p.vaddr=0x3a9000 + space=0x5 vaddr=0x3aa000 size=0x1000 parent=0x2 p.vaddr=0x3aa000 + space=0x5 vaddr=0x3ab000 size=0x1000 parent=0x2 p.vaddr=0x3ab000 + space=0x5 vaddr=0x3ac000 size=0x1000 parent=0x2 p.vaddr=0x3ac000 + space=0x5 vaddr=0x3ad000 size=0x1000 parent=0x2 p.vaddr=0x3ad000 + space=0x5 vaddr=0x3ae000 size=0x1000 parent=0x2 p.vaddr=0x3ae000 + space=0x5 vaddr=0x3af000 size=0x1000 parent=0x2 p.vaddr=0x3af000 + space=0x5 vaddr=0x3b0000 size=0x1000 parent=0x2 p.vaddr=0x3b0000 + space=0x5 vaddr=0x3b1000 size=0x1000 parent=0x2 p.vaddr=0x3b1000 + space=0x5 vaddr=0x3b2000 size=0x1000 parent=0x2 p.vaddr=0x3b2000 + space=0x5 vaddr=0x3b3000 size=0x1000 parent=0x2 p.vaddr=0x3b3000 + space=0x5 vaddr=0x3b4000 size=0x1000 parent=0x2 p.vaddr=0x3b4000 + space=0x5 vaddr=0x3b5000 size=0x1000 parent=0x2 p.vaddr=0x3b5000 + space=0x5 vaddr=0x3b6000 size=0x1000 parent=0x2 p.vaddr=0x3b6000 + space=0x5 vaddr=0x3b7000 size=0x1000 parent=0x2 p.vaddr=0x3b7000 + space=0x5 vaddr=0x3b8000 size=0x1000 parent=0x2 p.vaddr=0x3b8000 + space=0x5 vaddr=0x3b9000 size=0x1000 parent=0x2 p.vaddr=0x3b9000 + space=0x5 vaddr=0x3ba000 size=0x1000 parent=0x2 p.vaddr=0x3ba000 + space=0x5 vaddr=0x3bb000 size=0x1000 parent=0x2 p.vaddr=0x3bb000 + space=0x5 vaddr=0x3bc000 size=0x1000 parent=0x2 p.vaddr=0x3bc000 + space=0x5 vaddr=0x3bd000 size=0x1000 parent=0x2 p.vaddr=0x3bd000 + space=0x5 vaddr=0x3be000 size=0x1000 parent=0x2 p.vaddr=0x3be000 + space=0x5 vaddr=0x3bf000 size=0x1000 parent=0x2 p.vaddr=0x3bf000 + space=0x5 vaddr=0x3c0000 size=0x1000 parent=0x2 p.vaddr=0x3c0000 + space=0x5 vaddr=0x3c1000 size=0x1000 parent=0x2 p.vaddr=0x3c1000 + space=0x5 vaddr=0x3c2000 size=0x1000 parent=0x2 p.vaddr=0x3c2000 + space=0x5 vaddr=0x3c3000 size=0x1000 parent=0x2 p.vaddr=0x3c3000 + space=0x5 vaddr=0x3c4000 size=0x1000 parent=0x2 p.vaddr=0x3c4000 + space=0x5 vaddr=0x3c5000 size=0x1000 parent=0x2 p.vaddr=0x3c5000 + space=0x5 vaddr=0x3c6000 size=0x1000 parent=0x2 p.vaddr=0x3c6000 + space=0x5 vaddr=0x3c7000 size=0x1000 parent=0x2 p.vaddr=0x3c7000 + space=0x5 vaddr=0x3c8000 size=0x1000 parent=0x2 p.vaddr=0x3c8000 + space=0x5 vaddr=0x3c9000 size=0x1000 parent=0x2 p.vaddr=0x3c9000 + space=0x5 vaddr=0x3ca000 size=0x1000 parent=0x2 p.vaddr=0x3ca000 + space=0x5 vaddr=0x3cb000 size=0x1000 parent=0x2 p.vaddr=0x3cb000 + space=0x5 vaddr=0x3cc000 size=0x1000 parent=0x2 p.vaddr=0x3cc000 + space=0x5 vaddr=0x3cd000 size=0x1000 parent=0x2 p.vaddr=0x3cd000 + space=0x5 vaddr=0x3ce000 size=0x1000 parent=0x2 p.vaddr=0x3ce000 + space=0x5 vaddr=0x3cf000 size=0x1000 parent=0x2 p.vaddr=0x3cf000 + space=0x5 vaddr=0x3d0000 size=0x1000 parent=0x2 p.vaddr=0x3d0000 + space=0x5 vaddr=0x3d1000 size=0x1000 parent=0x2 p.vaddr=0x3d1000 + space=0x5 vaddr=0x3d2000 size=0x1000 parent=0x2 p.vaddr=0x3d2000 + space=0x5 vaddr=0x3d3000 size=0x1000 parent=0x2 p.vaddr=0x3d3000 + space=0x5 vaddr=0x3d4000 size=0x1000 parent=0x2 p.vaddr=0x3d4000 + space=0x5 vaddr=0x3d5000 size=0x1000 parent=0x2 p.vaddr=0x3d5000 + space=0x5 vaddr=0x3d6000 size=0x1000 parent=0x2 p.vaddr=0x3d6000 + space=0x5 vaddr=0x3d7000 size=0x1000 parent=0x2 p.vaddr=0x3d7000 + space=0x5 vaddr=0x3d8000 size=0x1000 parent=0x2 p.vaddr=0x3d8000 + space=0x5 vaddr=0x3d9000 size=0x1000 parent=0x2 p.vaddr=0x3d9000 + space=0x5 vaddr=0x3da000 size=0x1000 parent=0x2 p.vaddr=0x3da000 + space=0x5 vaddr=0x3db000 size=0x1000 parent=0x2 p.vaddr=0x3db000 + space=0x5 vaddr=0x3dc000 size=0x1000 parent=0x2 p.vaddr=0x3dc000 + space=0x5 vaddr=0x3dd000 size=0x1000 parent=0x2 p.vaddr=0x3dd000 + space=0x5 vaddr=0x3de000 size=0x1000 parent=0x2 p.vaddr=0x3de000 + space=0x5 vaddr=0x3df000 size=0x1000 parent=0x2 p.vaddr=0x3df000 + space=0x5 vaddr=0x3e0000 size=0x1000 parent=0x2 p.vaddr=0x3e0000 + space=0x5 vaddr=0x3e1000 size=0x1000 parent=0x2 p.vaddr=0x3e1000 + space=0x5 vaddr=0x3e2000 size=0x1000 parent=0x2 p.vaddr=0x3e2000 + space=0x5 vaddr=0x3e3000 size=0x1000 parent=0x2 p.vaddr=0x3e3000 + space=0x5 vaddr=0x3e4000 size=0x1000 parent=0x2 p.vaddr=0x3e4000 + space=0x5 vaddr=0x3e5000 size=0x1000 parent=0x2 p.vaddr=0x3e5000 + space=0x5 vaddr=0x3e6000 size=0x1000 parent=0x2 p.vaddr=0x3e6000 + space=0x5 vaddr=0x3e7000 size=0x1000 parent=0x2 p.vaddr=0x3e7000 + space=0x5 vaddr=0x3e8000 size=0x1000 parent=0x2 p.vaddr=0x3e8000 + space=0x5 vaddr=0x3e9000 size=0x1000 parent=0x2 p.vaddr=0x3e9000 + space=0x5 vaddr=0x3ea000 size=0x1000 parent=0x2 p.vaddr=0x3ea000 + space=0x5 vaddr=0x3eb000 size=0x1000 parent=0x2 p.vaddr=0x3eb000 + space=0x5 vaddr=0x3ec000 size=0x1000 parent=0x2 p.vaddr=0x3ec000 + space=0x5 vaddr=0x3ed000 size=0x1000 parent=0x2 p.vaddr=0x3ed000 + space=0x5 vaddr=0x3ee000 size=0x1000 parent=0x2 p.vaddr=0x3ee000 + space=0x5 vaddr=0x3ef000 size=0x1000 parent=0x2 p.vaddr=0x3ef000 + space=0x5 vaddr=0x3f0000 size=0x1000 parent=0x2 p.vaddr=0x3f0000 + space=0x5 vaddr=0x3f1000 size=0x1000 parent=0x2 p.vaddr=0x3f1000 + space=0x5 vaddr=0x3f2000 size=0x1000 parent=0x2 p.vaddr=0x3f2000 + space=0x5 vaddr=0x3f3000 size=0x1000 parent=0x2 p.vaddr=0x3f3000 + space=0x5 vaddr=0x3f4000 size=0x1000 parent=0x2 p.vaddr=0x3f4000 + space=0x5 vaddr=0x3f5000 size=0x1000 parent=0x2 p.vaddr=0x3f5000 + space=0x5 vaddr=0x3f6000 size=0x1000 parent=0x2 p.vaddr=0x3f6000 + space=0x5 vaddr=0x3f7000 size=0x1000 parent=0x2 p.vaddr=0x3f7000 + space=0x5 vaddr=0x3f8000 size=0x1000 parent=0x2 p.vaddr=0x3f8000 + space=0x5 vaddr=0x3f9000 size=0x1000 parent=0x2 p.vaddr=0x3f9000 + space=0x5 vaddr=0x3fa000 size=0x1000 parent=0x2 p.vaddr=0x3fa000 + space=0x5 vaddr=0x3fb000 size=0x1000 parent=0x2 p.vaddr=0x3fb000 + space=0x5 vaddr=0x3fc000 size=0x1000 parent=0x2 p.vaddr=0x3fc000 + space=0x5 vaddr=0x3fd000 size=0x1000 parent=0x2 p.vaddr=0x3fd000 + space=0x5 vaddr=0x3fe000 size=0x1000 parent=0x2 p.vaddr=0x3fe000 + space=0x5 vaddr=0x3ff000 size=0x1000 parent=0x2 p.vaddr=0x3ff000 + +space=0x2 vaddr=0x0 size=0x400000 + space=0x5 vaddr=0x10000 size=0x1000 parent=0x2 p.vaddr=0x10000 + +space=0x2 vaddr=0x0 size=0x400000 + space=0x5 vaddr=0x0 size=0x1000 parent=0x2 p.vaddr=0x0 + space=0x5 vaddr=0x1000 size=0x1000 parent=0x2 p.vaddr=0x1000 + space=0x5 vaddr=0x2000 size=0x1000 parent=0x2 p.vaddr=0x2000 + space=0x5 vaddr=0x3000 size=0x1000 parent=0x2 p.vaddr=0x3000 + space=0x5 vaddr=0x4000 size=0x1000 parent=0x2 p.vaddr=0x4000 + space=0x5 vaddr=0x5000 size=0x1000 parent=0x2 p.vaddr=0x5000 + space=0x5 vaddr=0x6000 size=0x1000 parent=0x2 p.vaddr=0x6000 + space=0x5 vaddr=0x7000 size=0x1000 parent=0x2 p.vaddr=0x7000 + space=0x5 vaddr=0x8000 size=0x1000 parent=0x2 p.vaddr=0x8000 + space=0x5 vaddr=0x9000 size=0x1000 parent=0x2 p.vaddr=0x9000 + space=0x5 vaddr=0xa000 size=0x1000 parent=0x2 p.vaddr=0xa000 + space=0x5 vaddr=0xb000 size=0x1000 parent=0x2 p.vaddr=0xb000 + space=0x5 vaddr=0xc000 size=0x1000 parent=0x2 p.vaddr=0xc000 + space=0x5 vaddr=0xd000 size=0x1000 parent=0x2 p.vaddr=0xd000 + space=0x5 vaddr=0xe000 size=0x1000 parent=0x2 p.vaddr=0xe000 + space=0x5 vaddr=0xf000 size=0x1000 parent=0x2 p.vaddr=0xf000 + space=0x5 vaddr=0x10000 size=0x1000 parent=0x2 p.vaddr=0x10000 + space=0x5 vaddr=0x11000 size=0x1000 parent=0x2 p.vaddr=0x11000 + space=0x5 vaddr=0x12000 size=0x1000 parent=0x2 p.vaddr=0x12000 + space=0x5 vaddr=0x13000 size=0x1000 parent=0x2 p.vaddr=0x13000 + space=0x5 vaddr=0x14000 size=0x1000 parent=0x2 p.vaddr=0x14000 + space=0x5 vaddr=0x15000 size=0x1000 parent=0x2 p.vaddr=0x15000 + space=0x5 vaddr=0x16000 size=0x1000 parent=0x2 p.vaddr=0x16000 + space=0x5 vaddr=0x17000 size=0x1000 parent=0x2 p.vaddr=0x17000 + space=0x5 vaddr=0x18000 size=0x1000 parent=0x2 p.vaddr=0x18000 + space=0x5 vaddr=0x19000 size=0x1000 parent=0x2 p.vaddr=0x19000 + space=0x5 vaddr=0x1a000 size=0x1000 parent=0x2 p.vaddr=0x1a000 + space=0x5 vaddr=0x1b000 size=0x1000 parent=0x2 p.vaddr=0x1b000 + space=0x5 vaddr=0x1c000 size=0x1000 parent=0x2 p.vaddr=0x1c000 + space=0x5 vaddr=0x1d000 size=0x1000 parent=0x2 p.vaddr=0x1d000 + space=0x5 vaddr=0x1e000 size=0x1000 parent=0x2 p.vaddr=0x1e000 + space=0x5 vaddr=0x1f000 size=0x1000 parent=0x2 p.vaddr=0x1f000 + space=0x5 vaddr=0x20000 size=0x1000 parent=0x2 p.vaddr=0x20000 + space=0x5 vaddr=0x21000 size=0x1000 parent=0x2 p.vaddr=0x21000 + space=0x5 vaddr=0x22000 size=0x1000 parent=0x2 p.vaddr=0x22000 + space=0x5 vaddr=0x23000 size=0x1000 parent=0x2 p.vaddr=0x23000 + space=0x5 vaddr=0x24000 size=0x1000 parent=0x2 p.vaddr=0x24000 + space=0x5 vaddr=0x25000 size=0x1000 parent=0x2 p.vaddr=0x25000 + space=0x5 vaddr=0x26000 size=0x1000 parent=0x2 p.vaddr=0x26000 + space=0x5 vaddr=0x27000 size=0x1000 parent=0x2 p.vaddr=0x27000 + space=0x5 vaddr=0x28000 size=0x1000 parent=0x2 p.vaddr=0x28000 + space=0x5 vaddr=0x29000 size=0x1000 parent=0x2 p.vaddr=0x29000 + space=0x5 vaddr=0x2a000 size=0x1000 parent=0x2 p.vaddr=0x2a000 + space=0x5 vaddr=0x2b000 size=0x1000 parent=0x2 p.vaddr=0x2b000 + space=0x5 vaddr=0x2c000 size=0x1000 parent=0x2 p.vaddr=0x2c000 + space=0x5 vaddr=0x2d000 size=0x1000 parent=0x2 p.vaddr=0x2d000 + space=0x5 vaddr=0x2e000 size=0x1000 parent=0x2 p.vaddr=0x2e000 + space=0x5 vaddr=0x2f000 size=0x1000 parent=0x2 p.vaddr=0x2f000 + space=0x5 vaddr=0x30000 size=0x1000 parent=0x2 p.vaddr=0x30000 + space=0x5 vaddr=0x31000 size=0x1000 parent=0x2 p.vaddr=0x31000 + space=0x5 vaddr=0x32000 size=0x1000 parent=0x2 p.vaddr=0x32000 + space=0x5 vaddr=0x33000 size=0x1000 parent=0x2 p.vaddr=0x33000 + space=0x5 vaddr=0x34000 size=0x1000 parent=0x2 p.vaddr=0x34000 + space=0x5 vaddr=0x35000 size=0x1000 parent=0x2 p.vaddr=0x35000 + space=0x5 vaddr=0x36000 size=0x1000 parent=0x2 p.vaddr=0x36000 + space=0x5 vaddr=0x37000 size=0x1000 parent=0x2 p.vaddr=0x37000 + space=0x5 vaddr=0x38000 size=0x1000 parent=0x2 p.vaddr=0x38000 + space=0x5 vaddr=0x39000 size=0x1000 parent=0x2 p.vaddr=0x39000 + space=0x5 vaddr=0x3a000 size=0x1000 parent=0x2 p.vaddr=0x3a000 + space=0x5 vaddr=0x3b000 size=0x1000 parent=0x2 p.vaddr=0x3b000 + space=0x5 vaddr=0x3c000 size=0x1000 parent=0x2 p.vaddr=0x3c000 + space=0x5 vaddr=0x3d000 size=0x1000 parent=0x2 p.vaddr=0x3d000 + space=0x5 vaddr=0x3e000 size=0x1000 parent=0x2 p.vaddr=0x3e000 + space=0x5 vaddr=0x3f000 size=0x1000 parent=0x2 p.vaddr=0x3f000 + space=0x5 vaddr=0x40000 size=0x1000 parent=0x2 p.vaddr=0x40000 + space=0x5 vaddr=0x41000 size=0x1000 parent=0x2 p.vaddr=0x41000 + space=0x5 vaddr=0x42000 size=0x1000 parent=0x2 p.vaddr=0x42000 + space=0x5 vaddr=0x43000 size=0x1000 parent=0x2 p.vaddr=0x43000 + space=0x5 vaddr=0x44000 size=0x1000 parent=0x2 p.vaddr=0x44000 + space=0x5 vaddr=0x45000 size=0x1000 parent=0x2 p.vaddr=0x45000 + space=0x5 vaddr=0x46000 size=0x1000 parent=0x2 p.vaddr=0x46000 + space=0x5 vaddr=0x47000 size=0x1000 parent=0x2 p.vaddr=0x47000 + space=0x5 vaddr=0x48000 size=0x1000 parent=0x2 p.vaddr=0x48000 + space=0x5 vaddr=0x49000 size=0x1000 parent=0x2 p.vaddr=0x49000 + space=0x5 vaddr=0x4a000 size=0x1000 parent=0x2 p.vaddr=0x4a000 + space=0x5 vaddr=0x4b000 size=0x1000 parent=0x2 p.vaddr=0x4b000 + space=0x5 vaddr=0x4c000 size=0x1000 parent=0x2 p.vaddr=0x4c000 + space=0x5 vaddr=0x4d000 size=0x1000 parent=0x2 p.vaddr=0x4d000 + space=0x5 vaddr=0x4e000 size=0x1000 parent=0x2 p.vaddr=0x4e000 + space=0x5 vaddr=0x4f000 size=0x1000 parent=0x2 p.vaddr=0x4f000 + space=0x5 vaddr=0x50000 size=0x1000 parent=0x2 p.vaddr=0x50000 + space=0x5 vaddr=0x51000 size=0x1000 parent=0x2 p.vaddr=0x51000 + space=0x5 vaddr=0x52000 size=0x1000 parent=0x2 p.vaddr=0x52000 + space=0x5 vaddr=0x53000 size=0x1000 parent=0x2 p.vaddr=0x53000 + space=0x5 vaddr=0x54000 size=0x1000 parent=0x2 p.vaddr=0x54000 + space=0x5 vaddr=0x55000 size=0x1000 parent=0x2 p.vaddr=0x55000 + space=0x5 vaddr=0x56000 size=0x1000 parent=0x2 p.vaddr=0x56000 + space=0x5 vaddr=0x57000 size=0x1000 parent=0x2 p.vaddr=0x57000 + space=0x5 vaddr=0x58000 size=0x1000 parent=0x2 p.vaddr=0x58000 + space=0x5 vaddr=0x59000 size=0x1000 parent=0x2 p.vaddr=0x59000 + space=0x5 vaddr=0x5a000 size=0x1000 parent=0x2 p.vaddr=0x5a000 + space=0x5 vaddr=0x5b000 size=0x1000 parent=0x2 p.vaddr=0x5b000 + space=0x5 vaddr=0x5c000 size=0x1000 parent=0x2 p.vaddr=0x5c000 + space=0x5 vaddr=0x5d000 size=0x1000 parent=0x2 p.vaddr=0x5d000 + space=0x5 vaddr=0x5e000 size=0x1000 parent=0x2 p.vaddr=0x5e000 + space=0x5 vaddr=0x5f000 size=0x1000 parent=0x2 p.vaddr=0x5f000 + space=0x5 vaddr=0x60000 size=0x1000 parent=0x2 p.vaddr=0x60000 + space=0x5 vaddr=0x61000 size=0x1000 parent=0x2 p.vaddr=0x61000 + space=0x5 vaddr=0x62000 size=0x1000 parent=0x2 p.vaddr=0x62000 + space=0x5 vaddr=0x63000 size=0x1000 parent=0x2 p.vaddr=0x63000 + space=0x5 vaddr=0x64000 size=0x1000 parent=0x2 p.vaddr=0x64000 + space=0x5 vaddr=0x65000 size=0x1000 parent=0x2 p.vaddr=0x65000 + space=0x5 vaddr=0x66000 size=0x1000 parent=0x2 p.vaddr=0x66000 + space=0x5 vaddr=0x67000 size=0x1000 parent=0x2 p.vaddr=0x67000 + space=0x5 vaddr=0x68000 size=0x1000 parent=0x2 p.vaddr=0x68000 + space=0x5 vaddr=0x69000 size=0x1000 parent=0x2 p.vaddr=0x69000 + space=0x5 vaddr=0x6a000 size=0x1000 parent=0x2 p.vaddr=0x6a000 + space=0x5 vaddr=0x6b000 size=0x1000 parent=0x2 p.vaddr=0x6b000 + space=0x5 vaddr=0x6c000 size=0x1000 parent=0x2 p.vaddr=0x6c000 + space=0x5 vaddr=0x6d000 size=0x1000 parent=0x2 p.vaddr=0x6d000 + space=0x5 vaddr=0x6e000 size=0x1000 parent=0x2 p.vaddr=0x6e000 + space=0x5 vaddr=0x6f000 size=0x1000 parent=0x2 p.vaddr=0x6f000 + space=0x5 vaddr=0x70000 size=0x1000 parent=0x2 p.vaddr=0x70000 + space=0x5 vaddr=0x71000 size=0x1000 parent=0x2 p.vaddr=0x71000 + space=0x5 vaddr=0x72000 size=0x1000 parent=0x2 p.vaddr=0x72000 + space=0x5 vaddr=0x73000 size=0x1000 parent=0x2 p.vaddr=0x73000 + space=0x5 vaddr=0x74000 size=0x1000 parent=0x2 p.vaddr=0x74000 + space=0x5 vaddr=0x75000 size=0x1000 parent=0x2 p.vaddr=0x75000 + space=0x5 vaddr=0x76000 size=0x1000 parent=0x2 p.vaddr=0x76000 + space=0x5 vaddr=0x77000 size=0x1000 parent=0x2 p.vaddr=0x77000 + space=0x5 vaddr=0x78000 size=0x1000 parent=0x2 p.vaddr=0x78000 + space=0x5 vaddr=0x79000 size=0x1000 parent=0x2 p.vaddr=0x79000 + space=0x5 vaddr=0x7a000 size=0x1000 parent=0x2 p.vaddr=0x7a000 + space=0x5 vaddr=0x7b000 size=0x1000 parent=0x2 p.vaddr=0x7b000 + space=0x5 vaddr=0x7c000 size=0x1000 parent=0x2 p.vaddr=0x7c000 + space=0x5 vaddr=0x7d000 size=0x1000 parent=0x2 p.vaddr=0x7d000 + space=0x5 vaddr=0x7e000 size=0x1000 parent=0x2 p.vaddr=0x7e000 + space=0x5 vaddr=0x7f000 size=0x1000 parent=0x2 p.vaddr=0x7f000 + space=0x5 vaddr=0x80000 size=0x1000 parent=0x2 p.vaddr=0x80000 + space=0x5 vaddr=0x81000 size=0x1000 parent=0x2 p.vaddr=0x81000 + space=0x5 vaddr=0x82000 size=0x1000 parent=0x2 p.vaddr=0x82000 + space=0x5 vaddr=0x83000 size=0x1000 parent=0x2 p.vaddr=0x83000 + space=0x5 vaddr=0x84000 size=0x1000 parent=0x2 p.vaddr=0x84000 + space=0x5 vaddr=0x85000 size=0x1000 parent=0x2 p.vaddr=0x85000 + space=0x5 vaddr=0x86000 size=0x1000 parent=0x2 p.vaddr=0x86000 + space=0x5 vaddr=0x87000 size=0x1000 parent=0x2 p.vaddr=0x87000 + space=0x5 vaddr=0x88000 size=0x1000 parent=0x2 p.vaddr=0x88000 + space=0x5 vaddr=0x89000 size=0x1000 parent=0x2 p.vaddr=0x89000 + space=0x5 vaddr=0x8a000 size=0x1000 parent=0x2 p.vaddr=0x8a000 + space=0x5 vaddr=0x8b000 size=0x1000 parent=0x2 p.vaddr=0x8b000 + space=0x5 vaddr=0x8c000 size=0x1000 parent=0x2 p.vaddr=0x8c000 + space=0x5 vaddr=0x8d000 size=0x1000 parent=0x2 p.vaddr=0x8d000 + space=0x5 vaddr=0x8e000 size=0x1000 parent=0x2 p.vaddr=0x8e000 + space=0x5 vaddr=0x8f000 size=0x1000 parent=0x2 p.vaddr=0x8f000 + space=0x5 vaddr=0x90000 size=0x1000 parent=0x2 p.vaddr=0x90000 + space=0x5 vaddr=0x91000 size=0x1000 parent=0x2 p.vaddr=0x91000 + space=0x5 vaddr=0x92000 size=0x1000 parent=0x2 p.vaddr=0x92000 + space=0x5 vaddr=0x93000 size=0x1000 parent=0x2 p.vaddr=0x93000 + space=0x5 vaddr=0x94000 size=0x1000 parent=0x2 p.vaddr=0x94000 + space=0x5 vaddr=0x95000 size=0x1000 parent=0x2 p.vaddr=0x95000 + space=0x5 vaddr=0x96000 size=0x1000 parent=0x2 p.vaddr=0x96000 + space=0x5 vaddr=0x97000 size=0x1000 parent=0x2 p.vaddr=0x97000 + space=0x5 vaddr=0x98000 size=0x1000 parent=0x2 p.vaddr=0x98000 + space=0x5 vaddr=0x99000 size=0x1000 parent=0x2 p.vaddr=0x99000 + space=0x5 vaddr=0x9a000 size=0x1000 parent=0x2 p.vaddr=0x9a000 + space=0x5 vaddr=0x9b000 size=0x1000 parent=0x2 p.vaddr=0x9b000 + space=0x5 vaddr=0x9c000 size=0x1000 parent=0x2 p.vaddr=0x9c000 + space=0x5 vaddr=0x9d000 size=0x1000 parent=0x2 p.vaddr=0x9d000 + space=0x5 vaddr=0x9e000 size=0x1000 parent=0x2 p.vaddr=0x9e000 + space=0x5 vaddr=0x9f000 size=0x1000 parent=0x2 p.vaddr=0x9f000 + space=0x5 vaddr=0xa0000 size=0x1000 parent=0x2 p.vaddr=0xa0000 + space=0x5 vaddr=0xa1000 size=0x1000 parent=0x2 p.vaddr=0xa1000 + space=0x5 vaddr=0xa2000 size=0x1000 parent=0x2 p.vaddr=0xa2000 + space=0x5 vaddr=0xa3000 size=0x1000 parent=0x2 p.vaddr=0xa3000 + space=0x5 vaddr=0xa4000 size=0x1000 parent=0x2 p.vaddr=0xa4000 + space=0x5 vaddr=0xa5000 size=0x1000 parent=0x2 p.vaddr=0xa5000 + space=0x5 vaddr=0xa6000 size=0x1000 parent=0x2 p.vaddr=0xa6000 + space=0x5 vaddr=0xa7000 size=0x1000 parent=0x2 p.vaddr=0xa7000 + space=0x5 vaddr=0xa8000 size=0x1000 parent=0x2 p.vaddr=0xa8000 + space=0x5 vaddr=0xa9000 size=0x1000 parent=0x2 p.vaddr=0xa9000 + space=0x5 vaddr=0xaa000 size=0x1000 parent=0x2 p.vaddr=0xaa000 + space=0x5 vaddr=0xab000 size=0x1000 parent=0x2 p.vaddr=0xab000 + space=0x5 vaddr=0xac000 size=0x1000 parent=0x2 p.vaddr=0xac000 + space=0x5 vaddr=0xad000 size=0x1000 parent=0x2 p.vaddr=0xad000 + space=0x5 vaddr=0xae000 size=0x1000 parent=0x2 p.vaddr=0xae000 + space=0x5 vaddr=0xaf000 size=0x1000 parent=0x2 p.vaddr=0xaf000 + space=0x5 vaddr=0xb0000 size=0x1000 parent=0x2 p.vaddr=0xb0000 + space=0x5 vaddr=0xb1000 size=0x1000 parent=0x2 p.vaddr=0xb1000 + space=0x5 vaddr=0xb2000 size=0x1000 parent=0x2 p.vaddr=0xb2000 + space=0x5 vaddr=0xb3000 size=0x1000 parent=0x2 p.vaddr=0xb3000 + space=0x5 vaddr=0xb4000 size=0x1000 parent=0x2 p.vaddr=0xb4000 + space=0x5 vaddr=0xb5000 size=0x1000 parent=0x2 p.vaddr=0xb5000 + space=0x5 vaddr=0xb6000 size=0x1000 parent=0x2 p.vaddr=0xb6000 + space=0x5 vaddr=0xb7000 size=0x1000 parent=0x2 p.vaddr=0xb7000 + space=0x5 vaddr=0xb8000 size=0x1000 parent=0x2 p.vaddr=0xb8000 + space=0x5 vaddr=0xb9000 size=0x1000 parent=0x2 p.vaddr=0xb9000 + space=0x5 vaddr=0xba000 size=0x1000 parent=0x2 p.vaddr=0xba000 + space=0x5 vaddr=0xbb000 size=0x1000 parent=0x2 p.vaddr=0xbb000 + space=0x5 vaddr=0xbc000 size=0x1000 parent=0x2 p.vaddr=0xbc000 + space=0x5 vaddr=0xbd000 size=0x1000 parent=0x2 p.vaddr=0xbd000 + space=0x5 vaddr=0xbe000 size=0x1000 parent=0x2 p.vaddr=0xbe000 + space=0x5 vaddr=0xbf000 size=0x1000 parent=0x2 p.vaddr=0xbf000 + space=0x5 vaddr=0xc0000 size=0x1000 parent=0x2 p.vaddr=0xc0000 + space=0x5 vaddr=0xc1000 size=0x1000 parent=0x2 p.vaddr=0xc1000 + space=0x5 vaddr=0xc2000 size=0x1000 parent=0x2 p.vaddr=0xc2000 + space=0x5 vaddr=0xc3000 size=0x1000 parent=0x2 p.vaddr=0xc3000 + space=0x5 vaddr=0xc4000 size=0x1000 parent=0x2 p.vaddr=0xc4000 + space=0x5 vaddr=0xc5000 size=0x1000 parent=0x2 p.vaddr=0xc5000 + space=0x5 vaddr=0xc6000 size=0x1000 parent=0x2 p.vaddr=0xc6000 + space=0x5 vaddr=0xc7000 size=0x1000 parent=0x2 p.vaddr=0xc7000 + space=0x5 vaddr=0xc8000 size=0x1000 parent=0x2 p.vaddr=0xc8000 + space=0x5 vaddr=0xc9000 size=0x1000 parent=0x2 p.vaddr=0xc9000 + space=0x5 vaddr=0xca000 size=0x1000 parent=0x2 p.vaddr=0xca000 + space=0x5 vaddr=0xcb000 size=0x1000 parent=0x2 p.vaddr=0xcb000 + space=0x5 vaddr=0xcc000 size=0x1000 parent=0x2 p.vaddr=0xcc000 + space=0x5 vaddr=0xcd000 size=0x1000 parent=0x2 p.vaddr=0xcd000 + space=0x5 vaddr=0xce000 size=0x1000 parent=0x2 p.vaddr=0xce000 + space=0x5 vaddr=0xcf000 size=0x1000 parent=0x2 p.vaddr=0xcf000 + space=0x5 vaddr=0xd0000 size=0x1000 parent=0x2 p.vaddr=0xd0000 + space=0x5 vaddr=0xd1000 size=0x1000 parent=0x2 p.vaddr=0xd1000 + space=0x5 vaddr=0xd2000 size=0x1000 parent=0x2 p.vaddr=0xd2000 + space=0x5 vaddr=0xd3000 size=0x1000 parent=0x2 p.vaddr=0xd3000 + space=0x5 vaddr=0xd4000 size=0x1000 parent=0x2 p.vaddr=0xd4000 + space=0x5 vaddr=0xd5000 size=0x1000 parent=0x2 p.vaddr=0xd5000 + space=0x5 vaddr=0xd6000 size=0x1000 parent=0x2 p.vaddr=0xd6000 + space=0x5 vaddr=0xd7000 size=0x1000 parent=0x2 p.vaddr=0xd7000 + space=0x5 vaddr=0xd8000 size=0x1000 parent=0x2 p.vaddr=0xd8000 + space=0x5 vaddr=0xd9000 size=0x1000 parent=0x2 p.vaddr=0xd9000 + space=0x5 vaddr=0xda000 size=0x1000 parent=0x2 p.vaddr=0xda000 + space=0x5 vaddr=0xdb000 size=0x1000 parent=0x2 p.vaddr=0xdb000 + space=0x5 vaddr=0xdc000 size=0x1000 parent=0x2 p.vaddr=0xdc000 + space=0x5 vaddr=0xdd000 size=0x1000 parent=0x2 p.vaddr=0xdd000 + space=0x5 vaddr=0xde000 size=0x1000 parent=0x2 p.vaddr=0xde000 + space=0x5 vaddr=0xdf000 size=0x1000 parent=0x2 p.vaddr=0xdf000 + space=0x5 vaddr=0xe0000 size=0x1000 parent=0x2 p.vaddr=0xe0000 + space=0x5 vaddr=0xe1000 size=0x1000 parent=0x2 p.vaddr=0xe1000 + space=0x5 vaddr=0xe2000 size=0x1000 parent=0x2 p.vaddr=0xe2000 + space=0x5 vaddr=0xe3000 size=0x1000 parent=0x2 p.vaddr=0xe3000 + space=0x5 vaddr=0xe4000 size=0x1000 parent=0x2 p.vaddr=0xe4000 + space=0x5 vaddr=0xe5000 size=0x1000 parent=0x2 p.vaddr=0xe5000 + space=0x5 vaddr=0xe6000 size=0x1000 parent=0x2 p.vaddr=0xe6000 + space=0x5 vaddr=0xe7000 size=0x1000 parent=0x2 p.vaddr=0xe7000 + space=0x5 vaddr=0xe8000 size=0x1000 parent=0x2 p.vaddr=0xe8000 + space=0x5 vaddr=0xe9000 size=0x1000 parent=0x2 p.vaddr=0xe9000 + space=0x5 vaddr=0xea000 size=0x1000 parent=0x2 p.vaddr=0xea000 + space=0x5 vaddr=0xeb000 size=0x1000 parent=0x2 p.vaddr=0xeb000 + space=0x5 vaddr=0xec000 size=0x1000 parent=0x2 p.vaddr=0xec000 + space=0x5 vaddr=0xed000 size=0x1000 parent=0x2 p.vaddr=0xed000 + space=0x5 vaddr=0xee000 size=0x1000 parent=0x2 p.vaddr=0xee000 + space=0x5 vaddr=0xef000 size=0x1000 parent=0x2 p.vaddr=0xef000 + space=0x5 vaddr=0xf0000 size=0x1000 parent=0x2 p.vaddr=0xf0000 + space=0x5 vaddr=0xf1000 size=0x1000 parent=0x2 p.vaddr=0xf1000 + space=0x5 vaddr=0xf2000 size=0x1000 parent=0x2 p.vaddr=0xf2000 + space=0x5 vaddr=0xf3000 size=0x1000 parent=0x2 p.vaddr=0xf3000 + space=0x5 vaddr=0xf4000 size=0x1000 parent=0x2 p.vaddr=0xf4000 + space=0x5 vaddr=0xf5000 size=0x1000 parent=0x2 p.vaddr=0xf5000 + space=0x5 vaddr=0xf6000 size=0x1000 parent=0x2 p.vaddr=0xf6000 + space=0x5 vaddr=0xf7000 size=0x1000 parent=0x2 p.vaddr=0xf7000 + space=0x5 vaddr=0xf8000 size=0x1000 parent=0x2 p.vaddr=0xf8000 + space=0x5 vaddr=0xf9000 size=0x1000 parent=0x2 p.vaddr=0xf9000 + space=0x5 vaddr=0xfa000 size=0x1000 parent=0x2 p.vaddr=0xfa000 + space=0x5 vaddr=0xfb000 size=0x1000 parent=0x2 p.vaddr=0xfb000 + space=0x5 vaddr=0xfc000 size=0x1000 parent=0x2 p.vaddr=0xfc000 + space=0x5 vaddr=0xfd000 size=0x1000 parent=0x2 p.vaddr=0xfd000 + space=0x5 vaddr=0xfe000 size=0x1000 parent=0x2 p.vaddr=0xfe000 + space=0x5 vaddr=0xff000 size=0x1000 parent=0x2 p.vaddr=0xff000 + space=0x5 vaddr=0x200000 size=0x1000 parent=0x2 p.vaddr=0x200000 + space=0x5 vaddr=0x201000 size=0x1000 parent=0x2 p.vaddr=0x201000 + space=0x5 vaddr=0x202000 size=0x1000 parent=0x2 p.vaddr=0x202000 + space=0x5 vaddr=0x203000 size=0x1000 parent=0x2 p.vaddr=0x203000 + space=0x5 vaddr=0x204000 size=0x1000 parent=0x2 p.vaddr=0x204000 + space=0x5 vaddr=0x205000 size=0x1000 parent=0x2 p.vaddr=0x205000 + space=0x5 vaddr=0x206000 size=0x1000 parent=0x2 p.vaddr=0x206000 + space=0x5 vaddr=0x207000 size=0x1000 parent=0x2 p.vaddr=0x207000 + space=0x5 vaddr=0x208000 size=0x1000 parent=0x2 p.vaddr=0x208000 + space=0x5 vaddr=0x209000 size=0x1000 parent=0x2 p.vaddr=0x209000 + space=0x5 vaddr=0x20a000 size=0x1000 parent=0x2 p.vaddr=0x20a000 + space=0x5 vaddr=0x20b000 size=0x1000 parent=0x2 p.vaddr=0x20b000 + space=0x5 vaddr=0x20c000 size=0x1000 parent=0x2 p.vaddr=0x20c000 + space=0x5 vaddr=0x20d000 size=0x1000 parent=0x2 p.vaddr=0x20d000 + space=0x5 vaddr=0x20e000 size=0x1000 parent=0x2 p.vaddr=0x20e000 + space=0x5 vaddr=0x20f000 size=0x1000 parent=0x2 p.vaddr=0x20f000 + space=0x5 vaddr=0x210000 size=0x1000 parent=0x2 p.vaddr=0x210000 + space=0x5 vaddr=0x211000 size=0x1000 parent=0x2 p.vaddr=0x211000 + space=0x5 vaddr=0x212000 size=0x1000 parent=0x2 p.vaddr=0x212000 + space=0x5 vaddr=0x213000 size=0x1000 parent=0x2 p.vaddr=0x213000 + space=0x5 vaddr=0x214000 size=0x1000 parent=0x2 p.vaddr=0x214000 + space=0x5 vaddr=0x215000 size=0x1000 parent=0x2 p.vaddr=0x215000 + space=0x5 vaddr=0x216000 size=0x1000 parent=0x2 p.vaddr=0x216000 + space=0x5 vaddr=0x217000 size=0x1000 parent=0x2 p.vaddr=0x217000 + space=0x5 vaddr=0x218000 size=0x1000 parent=0x2 p.vaddr=0x218000 + space=0x5 vaddr=0x219000 size=0x1000 parent=0x2 p.vaddr=0x219000 + space=0x5 vaddr=0x21a000 size=0x1000 parent=0x2 p.vaddr=0x21a000 + space=0x5 vaddr=0x21b000 size=0x1000 parent=0x2 p.vaddr=0x21b000 + space=0x5 vaddr=0x21c000 size=0x1000 parent=0x2 p.vaddr=0x21c000 + space=0x5 vaddr=0x21d000 size=0x1000 parent=0x2 p.vaddr=0x21d000 + space=0x5 vaddr=0x21e000 size=0x1000 parent=0x2 p.vaddr=0x21e000 + space=0x5 vaddr=0x21f000 size=0x1000 parent=0x2 p.vaddr=0x21f000 + space=0x5 vaddr=0x220000 size=0x1000 parent=0x2 p.vaddr=0x220000 + space=0x5 vaddr=0x221000 size=0x1000 parent=0x2 p.vaddr=0x221000 + space=0x5 vaddr=0x222000 size=0x1000 parent=0x2 p.vaddr=0x222000 + space=0x5 vaddr=0x223000 size=0x1000 parent=0x2 p.vaddr=0x223000 + space=0x5 vaddr=0x224000 size=0x1000 parent=0x2 p.vaddr=0x224000 + space=0x5 vaddr=0x225000 size=0x1000 parent=0x2 p.vaddr=0x225000 + space=0x5 vaddr=0x226000 size=0x1000 parent=0x2 p.vaddr=0x226000 + space=0x5 vaddr=0x227000 size=0x1000 parent=0x2 p.vaddr=0x227000 + space=0x5 vaddr=0x228000 size=0x1000 parent=0x2 p.vaddr=0x228000 + space=0x5 vaddr=0x229000 size=0x1000 parent=0x2 p.vaddr=0x229000 + space=0x5 vaddr=0x22a000 size=0x1000 parent=0x2 p.vaddr=0x22a000 + space=0x5 vaddr=0x22b000 size=0x1000 parent=0x2 p.vaddr=0x22b000 + space=0x5 vaddr=0x22c000 size=0x1000 parent=0x2 p.vaddr=0x22c000 + space=0x5 vaddr=0x22d000 size=0x1000 parent=0x2 p.vaddr=0x22d000 + space=0x5 vaddr=0x22e000 size=0x1000 parent=0x2 p.vaddr=0x22e000 + space=0x5 vaddr=0x22f000 size=0x1000 parent=0x2 p.vaddr=0x22f000 + space=0x5 vaddr=0x230000 size=0x1000 parent=0x2 p.vaddr=0x230000 + space=0x5 vaddr=0x231000 size=0x1000 parent=0x2 p.vaddr=0x231000 + space=0x5 vaddr=0x232000 size=0x1000 parent=0x2 p.vaddr=0x232000 + space=0x5 vaddr=0x233000 size=0x1000 parent=0x2 p.vaddr=0x233000 + space=0x5 vaddr=0x234000 size=0x1000 parent=0x2 p.vaddr=0x234000 + space=0x5 vaddr=0x235000 size=0x1000 parent=0x2 p.vaddr=0x235000 + space=0x5 vaddr=0x236000 size=0x1000 parent=0x2 p.vaddr=0x236000 + space=0x5 vaddr=0x237000 size=0x1000 parent=0x2 p.vaddr=0x237000 + space=0x5 vaddr=0x238000 size=0x1000 parent=0x2 p.vaddr=0x238000 + space=0x5 vaddr=0x239000 size=0x1000 parent=0x2 p.vaddr=0x239000 + space=0x5 vaddr=0x23a000 size=0x1000 parent=0x2 p.vaddr=0x23a000 + space=0x5 vaddr=0x23b000 size=0x1000 parent=0x2 p.vaddr=0x23b000 + space=0x5 vaddr=0x23c000 size=0x1000 parent=0x2 p.vaddr=0x23c000 + space=0x5 vaddr=0x23d000 size=0x1000 parent=0x2 p.vaddr=0x23d000 + space=0x5 vaddr=0x23e000 size=0x1000 parent=0x2 p.vaddr=0x23e000 + space=0x5 vaddr=0x23f000 size=0x1000 parent=0x2 p.vaddr=0x23f000 + space=0x5 vaddr=0x240000 size=0x1000 parent=0x2 p.vaddr=0x240000 + space=0x5 vaddr=0x241000 size=0x1000 parent=0x2 p.vaddr=0x241000 + space=0x5 vaddr=0x242000 size=0x1000 parent=0x2 p.vaddr=0x242000 + space=0x5 vaddr=0x243000 size=0x1000 parent=0x2 p.vaddr=0x243000 + space=0x5 vaddr=0x244000 size=0x1000 parent=0x2 p.vaddr=0x244000 + space=0x5 vaddr=0x245000 size=0x1000 parent=0x2 p.vaddr=0x245000 + space=0x5 vaddr=0x246000 size=0x1000 parent=0x2 p.vaddr=0x246000 + space=0x5 vaddr=0x247000 size=0x1000 parent=0x2 p.vaddr=0x247000 + space=0x5 vaddr=0x248000 size=0x1000 parent=0x2 p.vaddr=0x248000 + space=0x5 vaddr=0x249000 size=0x1000 parent=0x2 p.vaddr=0x249000 + space=0x5 vaddr=0x24a000 size=0x1000 parent=0x2 p.vaddr=0x24a000 + space=0x5 vaddr=0x24b000 size=0x1000 parent=0x2 p.vaddr=0x24b000 + space=0x5 vaddr=0x24c000 size=0x1000 parent=0x2 p.vaddr=0x24c000 + space=0x5 vaddr=0x24d000 size=0x1000 parent=0x2 p.vaddr=0x24d000 + space=0x5 vaddr=0x24e000 size=0x1000 parent=0x2 p.vaddr=0x24e000 + space=0x5 vaddr=0x24f000 size=0x1000 parent=0x2 p.vaddr=0x24f000 + space=0x5 vaddr=0x250000 size=0x1000 parent=0x2 p.vaddr=0x250000 + space=0x5 vaddr=0x251000 size=0x1000 parent=0x2 p.vaddr=0x251000 + space=0x5 vaddr=0x252000 size=0x1000 parent=0x2 p.vaddr=0x252000 + space=0x5 vaddr=0x253000 size=0x1000 parent=0x2 p.vaddr=0x253000 + space=0x5 vaddr=0x254000 size=0x1000 parent=0x2 p.vaddr=0x254000 + space=0x5 vaddr=0x255000 size=0x1000 parent=0x2 p.vaddr=0x255000 + space=0x5 vaddr=0x256000 size=0x1000 parent=0x2 p.vaddr=0x256000 + space=0x5 vaddr=0x257000 size=0x1000 parent=0x2 p.vaddr=0x257000 + space=0x5 vaddr=0x258000 size=0x1000 parent=0x2 p.vaddr=0x258000 + space=0x5 vaddr=0x259000 size=0x1000 parent=0x2 p.vaddr=0x259000 + space=0x5 vaddr=0x25a000 size=0x1000 parent=0x2 p.vaddr=0x25a000 + space=0x5 vaddr=0x25b000 size=0x1000 parent=0x2 p.vaddr=0x25b000 + space=0x5 vaddr=0x25c000 size=0x1000 parent=0x2 p.vaddr=0x25c000 + space=0x5 vaddr=0x25d000 size=0x1000 parent=0x2 p.vaddr=0x25d000 + space=0x5 vaddr=0x25e000 size=0x1000 parent=0x2 p.vaddr=0x25e000 + space=0x5 vaddr=0x25f000 size=0x1000 parent=0x2 p.vaddr=0x25f000 + space=0x5 vaddr=0x260000 size=0x1000 parent=0x2 p.vaddr=0x260000 + space=0x5 vaddr=0x261000 size=0x1000 parent=0x2 p.vaddr=0x261000 + space=0x5 vaddr=0x262000 size=0x1000 parent=0x2 p.vaddr=0x262000 + space=0x5 vaddr=0x263000 size=0x1000 parent=0x2 p.vaddr=0x263000 + space=0x5 vaddr=0x264000 size=0x1000 parent=0x2 p.vaddr=0x264000 + space=0x5 vaddr=0x265000 size=0x1000 parent=0x2 p.vaddr=0x265000 + space=0x5 vaddr=0x266000 size=0x1000 parent=0x2 p.vaddr=0x266000 + space=0x5 vaddr=0x267000 size=0x1000 parent=0x2 p.vaddr=0x267000 + space=0x5 vaddr=0x268000 size=0x1000 parent=0x2 p.vaddr=0x268000 + space=0x5 vaddr=0x269000 size=0x1000 parent=0x2 p.vaddr=0x269000 + space=0x5 vaddr=0x26a000 size=0x1000 parent=0x2 p.vaddr=0x26a000 + space=0x5 vaddr=0x26b000 size=0x1000 parent=0x2 p.vaddr=0x26b000 + space=0x5 vaddr=0x26c000 size=0x1000 parent=0x2 p.vaddr=0x26c000 + space=0x5 vaddr=0x26d000 size=0x1000 parent=0x2 p.vaddr=0x26d000 + space=0x5 vaddr=0x26e000 size=0x1000 parent=0x2 p.vaddr=0x26e000 + space=0x5 vaddr=0x26f000 size=0x1000 parent=0x2 p.vaddr=0x26f000 + space=0x5 vaddr=0x270000 size=0x1000 parent=0x2 p.vaddr=0x270000 + space=0x5 vaddr=0x271000 size=0x1000 parent=0x2 p.vaddr=0x271000 + space=0x5 vaddr=0x272000 size=0x1000 parent=0x2 p.vaddr=0x272000 + space=0x5 vaddr=0x273000 size=0x1000 parent=0x2 p.vaddr=0x273000 + space=0x5 vaddr=0x274000 size=0x1000 parent=0x2 p.vaddr=0x274000 + space=0x5 vaddr=0x275000 size=0x1000 parent=0x2 p.vaddr=0x275000 + space=0x5 vaddr=0x276000 size=0x1000 parent=0x2 p.vaddr=0x276000 + space=0x5 vaddr=0x277000 size=0x1000 parent=0x2 p.vaddr=0x277000 + space=0x5 vaddr=0x278000 size=0x1000 parent=0x2 p.vaddr=0x278000 + space=0x5 vaddr=0x279000 size=0x1000 parent=0x2 p.vaddr=0x279000 + space=0x5 vaddr=0x27a000 size=0x1000 parent=0x2 p.vaddr=0x27a000 + space=0x5 vaddr=0x27b000 size=0x1000 parent=0x2 p.vaddr=0x27b000 + space=0x5 vaddr=0x27c000 size=0x1000 parent=0x2 p.vaddr=0x27c000 + space=0x5 vaddr=0x27d000 size=0x1000 parent=0x2 p.vaddr=0x27d000 + space=0x5 vaddr=0x27e000 size=0x1000 parent=0x2 p.vaddr=0x27e000 + space=0x5 vaddr=0x27f000 size=0x1000 parent=0x2 p.vaddr=0x27f000 + space=0x5 vaddr=0x280000 size=0x1000 parent=0x2 p.vaddr=0x280000 + space=0x5 vaddr=0x281000 size=0x1000 parent=0x2 p.vaddr=0x281000 + space=0x5 vaddr=0x282000 size=0x1000 parent=0x2 p.vaddr=0x282000 + space=0x5 vaddr=0x283000 size=0x1000 parent=0x2 p.vaddr=0x283000 + space=0x5 vaddr=0x284000 size=0x1000 parent=0x2 p.vaddr=0x284000 + space=0x5 vaddr=0x285000 size=0x1000 parent=0x2 p.vaddr=0x285000 + space=0x5 vaddr=0x286000 size=0x1000 parent=0x2 p.vaddr=0x286000 + space=0x5 vaddr=0x287000 size=0x1000 parent=0x2 p.vaddr=0x287000 + space=0x5 vaddr=0x288000 size=0x1000 parent=0x2 p.vaddr=0x288000 + space=0x5 vaddr=0x289000 size=0x1000 parent=0x2 p.vaddr=0x289000 + space=0x5 vaddr=0x28a000 size=0x1000 parent=0x2 p.vaddr=0x28a000 + space=0x5 vaddr=0x28b000 size=0x1000 parent=0x2 p.vaddr=0x28b000 + space=0x5 vaddr=0x28c000 size=0x1000 parent=0x2 p.vaddr=0x28c000 + space=0x5 vaddr=0x28d000 size=0x1000 parent=0x2 p.vaddr=0x28d000 + space=0x5 vaddr=0x28e000 size=0x1000 parent=0x2 p.vaddr=0x28e000 + space=0x5 vaddr=0x28f000 size=0x1000 parent=0x2 p.vaddr=0x28f000 + space=0x5 vaddr=0x290000 size=0x1000 parent=0x2 p.vaddr=0x290000 + space=0x5 vaddr=0x291000 size=0x1000 parent=0x2 p.vaddr=0x291000 + space=0x5 vaddr=0x292000 size=0x1000 parent=0x2 p.vaddr=0x292000 + space=0x5 vaddr=0x293000 size=0x1000 parent=0x2 p.vaddr=0x293000 + space=0x5 vaddr=0x294000 size=0x1000 parent=0x2 p.vaddr=0x294000 + space=0x5 vaddr=0x295000 size=0x1000 parent=0x2 p.vaddr=0x295000 + space=0x5 vaddr=0x296000 size=0x1000 parent=0x2 p.vaddr=0x296000 + space=0x5 vaddr=0x297000 size=0x1000 parent=0x2 p.vaddr=0x297000 + space=0x5 vaddr=0x298000 size=0x1000 parent=0x2 p.vaddr=0x298000 + space=0x5 vaddr=0x299000 size=0x1000 parent=0x2 p.vaddr=0x299000 + space=0x5 vaddr=0x29a000 size=0x1000 parent=0x2 p.vaddr=0x29a000 + space=0x5 vaddr=0x29b000 size=0x1000 parent=0x2 p.vaddr=0x29b000 + space=0x5 vaddr=0x29c000 size=0x1000 parent=0x2 p.vaddr=0x29c000 + space=0x5 vaddr=0x29d000 size=0x1000 parent=0x2 p.vaddr=0x29d000 + space=0x5 vaddr=0x29e000 size=0x1000 parent=0x2 p.vaddr=0x29e000 + space=0x5 vaddr=0x29f000 size=0x1000 parent=0x2 p.vaddr=0x29f000 + space=0x5 vaddr=0x2a0000 size=0x1000 parent=0x2 p.vaddr=0x2a0000 + space=0x5 vaddr=0x2a1000 size=0x1000 parent=0x2 p.vaddr=0x2a1000 + space=0x5 vaddr=0x2a2000 size=0x1000 parent=0x2 p.vaddr=0x2a2000 + space=0x5 vaddr=0x2a3000 size=0x1000 parent=0x2 p.vaddr=0x2a3000 + space=0x5 vaddr=0x2a4000 size=0x1000 parent=0x2 p.vaddr=0x2a4000 + space=0x5 vaddr=0x2a5000 size=0x1000 parent=0x2 p.vaddr=0x2a5000 + space=0x5 vaddr=0x2a6000 size=0x1000 parent=0x2 p.vaddr=0x2a6000 + space=0x5 vaddr=0x2a7000 size=0x1000 parent=0x2 p.vaddr=0x2a7000 + space=0x5 vaddr=0x2a8000 size=0x1000 parent=0x2 p.vaddr=0x2a8000 + space=0x5 vaddr=0x2a9000 size=0x1000 parent=0x2 p.vaddr=0x2a9000 + space=0x5 vaddr=0x2aa000 size=0x1000 parent=0x2 p.vaddr=0x2aa000 + space=0x5 vaddr=0x2ab000 size=0x1000 parent=0x2 p.vaddr=0x2ab000 + space=0x5 vaddr=0x2ac000 size=0x1000 parent=0x2 p.vaddr=0x2ac000 + space=0x5 vaddr=0x2ad000 size=0x1000 parent=0x2 p.vaddr=0x2ad000 + space=0x5 vaddr=0x2ae000 size=0x1000 parent=0x2 p.vaddr=0x2ae000 + space=0x5 vaddr=0x2af000 size=0x1000 parent=0x2 p.vaddr=0x2af000 + space=0x5 vaddr=0x2b0000 size=0x1000 parent=0x2 p.vaddr=0x2b0000 + space=0x5 vaddr=0x2b1000 size=0x1000 parent=0x2 p.vaddr=0x2b1000 + space=0x5 vaddr=0x2b2000 size=0x1000 parent=0x2 p.vaddr=0x2b2000 + space=0x5 vaddr=0x2b3000 size=0x1000 parent=0x2 p.vaddr=0x2b3000 + space=0x5 vaddr=0x2b4000 size=0x1000 parent=0x2 p.vaddr=0x2b4000 + space=0x5 vaddr=0x2b5000 size=0x1000 parent=0x2 p.vaddr=0x2b5000 + space=0x5 vaddr=0x2b6000 size=0x1000 parent=0x2 p.vaddr=0x2b6000 + space=0x5 vaddr=0x2b7000 size=0x1000 parent=0x2 p.vaddr=0x2b7000 + space=0x5 vaddr=0x2b8000 size=0x1000 parent=0x2 p.vaddr=0x2b8000 + space=0x5 vaddr=0x2b9000 size=0x1000 parent=0x2 p.vaddr=0x2b9000 + space=0x5 vaddr=0x2ba000 size=0x1000 parent=0x2 p.vaddr=0x2ba000 + space=0x5 vaddr=0x2bb000 size=0x1000 parent=0x2 p.vaddr=0x2bb000 + space=0x5 vaddr=0x2bc000 size=0x1000 parent=0x2 p.vaddr=0x2bc000 + space=0x5 vaddr=0x2bd000 size=0x1000 parent=0x2 p.vaddr=0x2bd000 + space=0x5 vaddr=0x2be000 size=0x1000 parent=0x2 p.vaddr=0x2be000 + space=0x5 vaddr=0x2bf000 size=0x1000 parent=0x2 p.vaddr=0x2bf000 + space=0x5 vaddr=0x2c0000 size=0x1000 parent=0x2 p.vaddr=0x2c0000 + space=0x5 vaddr=0x2c1000 size=0x1000 parent=0x2 p.vaddr=0x2c1000 + space=0x5 vaddr=0x2c2000 size=0x1000 parent=0x2 p.vaddr=0x2c2000 + space=0x5 vaddr=0x2c3000 size=0x1000 parent=0x2 p.vaddr=0x2c3000 + space=0x5 vaddr=0x2c4000 size=0x1000 parent=0x2 p.vaddr=0x2c4000 + space=0x5 vaddr=0x2c5000 size=0x1000 parent=0x2 p.vaddr=0x2c5000 + space=0x5 vaddr=0x2c6000 size=0x1000 parent=0x2 p.vaddr=0x2c6000 + space=0x5 vaddr=0x2c7000 size=0x1000 parent=0x2 p.vaddr=0x2c7000 + space=0x5 vaddr=0x2c8000 size=0x1000 parent=0x2 p.vaddr=0x2c8000 + space=0x5 vaddr=0x2c9000 size=0x1000 parent=0x2 p.vaddr=0x2c9000 + space=0x5 vaddr=0x2ca000 size=0x1000 parent=0x2 p.vaddr=0x2ca000 + space=0x5 vaddr=0x2cb000 size=0x1000 parent=0x2 p.vaddr=0x2cb000 + space=0x5 vaddr=0x2cc000 size=0x1000 parent=0x2 p.vaddr=0x2cc000 + space=0x5 vaddr=0x2cd000 size=0x1000 parent=0x2 p.vaddr=0x2cd000 + space=0x5 vaddr=0x2ce000 size=0x1000 parent=0x2 p.vaddr=0x2ce000 + space=0x5 vaddr=0x2cf000 size=0x1000 parent=0x2 p.vaddr=0x2cf000 + space=0x5 vaddr=0x2d0000 size=0x1000 parent=0x2 p.vaddr=0x2d0000 + space=0x5 vaddr=0x2d1000 size=0x1000 parent=0x2 p.vaddr=0x2d1000 + space=0x5 vaddr=0x2d2000 size=0x1000 parent=0x2 p.vaddr=0x2d2000 + space=0x5 vaddr=0x2d3000 size=0x1000 parent=0x2 p.vaddr=0x2d3000 + space=0x5 vaddr=0x2d4000 size=0x1000 parent=0x2 p.vaddr=0x2d4000 + space=0x5 vaddr=0x2d5000 size=0x1000 parent=0x2 p.vaddr=0x2d5000 + space=0x5 vaddr=0x2d6000 size=0x1000 parent=0x2 p.vaddr=0x2d6000 + space=0x5 vaddr=0x2d7000 size=0x1000 parent=0x2 p.vaddr=0x2d7000 + space=0x5 vaddr=0x2d8000 size=0x1000 parent=0x2 p.vaddr=0x2d8000 + space=0x5 vaddr=0x2d9000 size=0x1000 parent=0x2 p.vaddr=0x2d9000 + space=0x5 vaddr=0x2da000 size=0x1000 parent=0x2 p.vaddr=0x2da000 + space=0x5 vaddr=0x2db000 size=0x1000 parent=0x2 p.vaddr=0x2db000 + space=0x5 vaddr=0x2dc000 size=0x1000 parent=0x2 p.vaddr=0x2dc000 + space=0x5 vaddr=0x2dd000 size=0x1000 parent=0x2 p.vaddr=0x2dd000 + space=0x5 vaddr=0x2de000 size=0x1000 parent=0x2 p.vaddr=0x2de000 + space=0x5 vaddr=0x2df000 size=0x1000 parent=0x2 p.vaddr=0x2df000 + space=0x5 vaddr=0x2e0000 size=0x1000 parent=0x2 p.vaddr=0x2e0000 + space=0x5 vaddr=0x2e1000 size=0x1000 parent=0x2 p.vaddr=0x2e1000 + space=0x5 vaddr=0x2e2000 size=0x1000 parent=0x2 p.vaddr=0x2e2000 + space=0x5 vaddr=0x2e3000 size=0x1000 parent=0x2 p.vaddr=0x2e3000 + space=0x5 vaddr=0x2e4000 size=0x1000 parent=0x2 p.vaddr=0x2e4000 + space=0x5 vaddr=0x2e5000 size=0x1000 parent=0x2 p.vaddr=0x2e5000 + space=0x5 vaddr=0x2e6000 size=0x1000 parent=0x2 p.vaddr=0x2e6000 + space=0x5 vaddr=0x2e7000 size=0x1000 parent=0x2 p.vaddr=0x2e7000 + space=0x5 vaddr=0x2e8000 size=0x1000 parent=0x2 p.vaddr=0x2e8000 + space=0x5 vaddr=0x2e9000 size=0x1000 parent=0x2 p.vaddr=0x2e9000 + space=0x5 vaddr=0x2ea000 size=0x1000 parent=0x2 p.vaddr=0x2ea000 + space=0x5 vaddr=0x2eb000 size=0x1000 parent=0x2 p.vaddr=0x2eb000 + space=0x5 vaddr=0x2ec000 size=0x1000 parent=0x2 p.vaddr=0x2ec000 + space=0x5 vaddr=0x2ed000 size=0x1000 parent=0x2 p.vaddr=0x2ed000 + space=0x5 vaddr=0x2ee000 size=0x1000 parent=0x2 p.vaddr=0x2ee000 + space=0x5 vaddr=0x2ef000 size=0x1000 parent=0x2 p.vaddr=0x2ef000 + space=0x5 vaddr=0x2f0000 size=0x1000 parent=0x2 p.vaddr=0x2f0000 + space=0x5 vaddr=0x2f1000 size=0x1000 parent=0x2 p.vaddr=0x2f1000 + space=0x5 vaddr=0x2f2000 size=0x1000 parent=0x2 p.vaddr=0x2f2000 + space=0x5 vaddr=0x2f3000 size=0x1000 parent=0x2 p.vaddr=0x2f3000 + space=0x5 vaddr=0x2f4000 size=0x1000 parent=0x2 p.vaddr=0x2f4000 + space=0x5 vaddr=0x2f5000 size=0x1000 parent=0x2 p.vaddr=0x2f5000 + space=0x5 vaddr=0x2f6000 size=0x1000 parent=0x2 p.vaddr=0x2f6000 + space=0x5 vaddr=0x2f7000 size=0x1000 parent=0x2 p.vaddr=0x2f7000 + space=0x5 vaddr=0x2f8000 size=0x1000 parent=0x2 p.vaddr=0x2f8000 + space=0x5 vaddr=0x2f9000 size=0x1000 parent=0x2 p.vaddr=0x2f9000 + space=0x5 vaddr=0x2fa000 size=0x1000 parent=0x2 p.vaddr=0x2fa000 + space=0x5 vaddr=0x2fb000 size=0x1000 parent=0x2 p.vaddr=0x2fb000 + space=0x5 vaddr=0x2fc000 size=0x1000 parent=0x2 p.vaddr=0x2fc000 + space=0x5 vaddr=0x2fd000 size=0x1000 parent=0x2 p.vaddr=0x2fd000 + space=0x5 vaddr=0x2fe000 size=0x1000 parent=0x2 p.vaddr=0x2fe000 + space=0x5 vaddr=0x2ff000 size=0x1000 parent=0x2 p.vaddr=0x2ff000 + space=0x5 vaddr=0x300000 size=0x1000 parent=0x2 p.vaddr=0x300000 + space=0x5 vaddr=0x301000 size=0x1000 parent=0x2 p.vaddr=0x301000 + space=0x5 vaddr=0x302000 size=0x1000 parent=0x2 p.vaddr=0x302000 + space=0x5 vaddr=0x303000 size=0x1000 parent=0x2 p.vaddr=0x303000 + space=0x5 vaddr=0x304000 size=0x1000 parent=0x2 p.vaddr=0x304000 + space=0x5 vaddr=0x305000 size=0x1000 parent=0x2 p.vaddr=0x305000 + space=0x5 vaddr=0x306000 size=0x1000 parent=0x2 p.vaddr=0x306000 + space=0x5 vaddr=0x307000 size=0x1000 parent=0x2 p.vaddr=0x307000 + space=0x5 vaddr=0x308000 size=0x1000 parent=0x2 p.vaddr=0x308000 + space=0x5 vaddr=0x309000 size=0x1000 parent=0x2 p.vaddr=0x309000 + space=0x5 vaddr=0x30a000 size=0x1000 parent=0x2 p.vaddr=0x30a000 + space=0x5 vaddr=0x30b000 size=0x1000 parent=0x2 p.vaddr=0x30b000 + space=0x5 vaddr=0x30c000 size=0x1000 parent=0x2 p.vaddr=0x30c000 + space=0x5 vaddr=0x30d000 size=0x1000 parent=0x2 p.vaddr=0x30d000 + space=0x5 vaddr=0x30e000 size=0x1000 parent=0x2 p.vaddr=0x30e000 + space=0x5 vaddr=0x30f000 size=0x1000 parent=0x2 p.vaddr=0x30f000 + space=0x5 vaddr=0x310000 size=0x1000 parent=0x2 p.vaddr=0x310000 + space=0x5 vaddr=0x311000 size=0x1000 parent=0x2 p.vaddr=0x311000 + space=0x5 vaddr=0x312000 size=0x1000 parent=0x2 p.vaddr=0x312000 + space=0x5 vaddr=0x313000 size=0x1000 parent=0x2 p.vaddr=0x313000 + space=0x5 vaddr=0x314000 size=0x1000 parent=0x2 p.vaddr=0x314000 + space=0x5 vaddr=0x315000 size=0x1000 parent=0x2 p.vaddr=0x315000 + space=0x5 vaddr=0x316000 size=0x1000 parent=0x2 p.vaddr=0x316000 + space=0x5 vaddr=0x317000 size=0x1000 parent=0x2 p.vaddr=0x317000 + space=0x5 vaddr=0x318000 size=0x1000 parent=0x2 p.vaddr=0x318000 + space=0x5 vaddr=0x319000 size=0x1000 parent=0x2 p.vaddr=0x319000 + space=0x5 vaddr=0x31a000 size=0x1000 parent=0x2 p.vaddr=0x31a000 + space=0x5 vaddr=0x31b000 size=0x1000 parent=0x2 p.vaddr=0x31b000 + space=0x5 vaddr=0x31c000 size=0x1000 parent=0x2 p.vaddr=0x31c000 + space=0x5 vaddr=0x31d000 size=0x1000 parent=0x2 p.vaddr=0x31d000 + space=0x5 vaddr=0x31e000 size=0x1000 parent=0x2 p.vaddr=0x31e000 + space=0x5 vaddr=0x31f000 size=0x1000 parent=0x2 p.vaddr=0x31f000 + space=0x5 vaddr=0x320000 size=0x1000 parent=0x2 p.vaddr=0x320000 + space=0x5 vaddr=0x321000 size=0x1000 parent=0x2 p.vaddr=0x321000 + space=0x5 vaddr=0x322000 size=0x1000 parent=0x2 p.vaddr=0x322000 + space=0x5 vaddr=0x323000 size=0x1000 parent=0x2 p.vaddr=0x323000 + space=0x5 vaddr=0x324000 size=0x1000 parent=0x2 p.vaddr=0x324000 + space=0x5 vaddr=0x325000 size=0x1000 parent=0x2 p.vaddr=0x325000 + space=0x5 vaddr=0x326000 size=0x1000 parent=0x2 p.vaddr=0x326000 + space=0x5 vaddr=0x327000 size=0x1000 parent=0x2 p.vaddr=0x327000 + space=0x5 vaddr=0x328000 size=0x1000 parent=0x2 p.vaddr=0x328000 + space=0x5 vaddr=0x329000 size=0x1000 parent=0x2 p.vaddr=0x329000 + space=0x5 vaddr=0x32a000 size=0x1000 parent=0x2 p.vaddr=0x32a000 + space=0x5 vaddr=0x32b000 size=0x1000 parent=0x2 p.vaddr=0x32b000 + space=0x5 vaddr=0x32c000 size=0x1000 parent=0x2 p.vaddr=0x32c000 + space=0x5 vaddr=0x32d000 size=0x1000 parent=0x2 p.vaddr=0x32d000 + space=0x5 vaddr=0x32e000 size=0x1000 parent=0x2 p.vaddr=0x32e000 + space=0x5 vaddr=0x32f000 size=0x1000 parent=0x2 p.vaddr=0x32f000 + space=0x5 vaddr=0x330000 size=0x1000 parent=0x2 p.vaddr=0x330000 + space=0x5 vaddr=0x331000 size=0x1000 parent=0x2 p.vaddr=0x331000 + space=0x5 vaddr=0x332000 size=0x1000 parent=0x2 p.vaddr=0x332000 + space=0x5 vaddr=0x333000 size=0x1000 parent=0x2 p.vaddr=0x333000 + space=0x5 vaddr=0x334000 size=0x1000 parent=0x2 p.vaddr=0x334000 + space=0x5 vaddr=0x335000 size=0x1000 parent=0x2 p.vaddr=0x335000 + space=0x5 vaddr=0x336000 size=0x1000 parent=0x2 p.vaddr=0x336000 + space=0x5 vaddr=0x337000 size=0x1000 parent=0x2 p.vaddr=0x337000 + space=0x5 vaddr=0x338000 size=0x1000 parent=0x2 p.vaddr=0x338000 + space=0x5 vaddr=0x339000 size=0x1000 parent=0x2 p.vaddr=0x339000 + space=0x5 vaddr=0x33a000 size=0x1000 parent=0x2 p.vaddr=0x33a000 + space=0x5 vaddr=0x33b000 size=0x1000 parent=0x2 p.vaddr=0x33b000 + space=0x5 vaddr=0x33c000 size=0x1000 parent=0x2 p.vaddr=0x33c000 + space=0x5 vaddr=0x33d000 size=0x1000 parent=0x2 p.vaddr=0x33d000 + space=0x5 vaddr=0x33e000 size=0x1000 parent=0x2 p.vaddr=0x33e000 + space=0x5 vaddr=0x33f000 size=0x1000 parent=0x2 p.vaddr=0x33f000 + space=0x5 vaddr=0x340000 size=0x1000 parent=0x2 p.vaddr=0x340000 + space=0x5 vaddr=0x341000 size=0x1000 parent=0x2 p.vaddr=0x341000 + space=0x5 vaddr=0x342000 size=0x1000 parent=0x2 p.vaddr=0x342000 + space=0x5 vaddr=0x343000 size=0x1000 parent=0x2 p.vaddr=0x343000 + space=0x5 vaddr=0x344000 size=0x1000 parent=0x2 p.vaddr=0x344000 + space=0x5 vaddr=0x345000 size=0x1000 parent=0x2 p.vaddr=0x345000 + space=0x5 vaddr=0x346000 size=0x1000 parent=0x2 p.vaddr=0x346000 + space=0x5 vaddr=0x347000 size=0x1000 parent=0x2 p.vaddr=0x347000 + space=0x5 vaddr=0x348000 size=0x1000 parent=0x2 p.vaddr=0x348000 + space=0x5 vaddr=0x349000 size=0x1000 parent=0x2 p.vaddr=0x349000 + space=0x5 vaddr=0x34a000 size=0x1000 parent=0x2 p.vaddr=0x34a000 + space=0x5 vaddr=0x34b000 size=0x1000 parent=0x2 p.vaddr=0x34b000 + space=0x5 vaddr=0x34c000 size=0x1000 parent=0x2 p.vaddr=0x34c000 + space=0x5 vaddr=0x34d000 size=0x1000 parent=0x2 p.vaddr=0x34d000 + space=0x5 vaddr=0x34e000 size=0x1000 parent=0x2 p.vaddr=0x34e000 + space=0x5 vaddr=0x34f000 size=0x1000 parent=0x2 p.vaddr=0x34f000 + space=0x5 vaddr=0x350000 size=0x1000 parent=0x2 p.vaddr=0x350000 + space=0x5 vaddr=0x351000 size=0x1000 parent=0x2 p.vaddr=0x351000 + space=0x5 vaddr=0x352000 size=0x1000 parent=0x2 p.vaddr=0x352000 + space=0x5 vaddr=0x353000 size=0x1000 parent=0x2 p.vaddr=0x353000 + space=0x5 vaddr=0x354000 size=0x1000 parent=0x2 p.vaddr=0x354000 + space=0x5 vaddr=0x355000 size=0x1000 parent=0x2 p.vaddr=0x355000 + space=0x5 vaddr=0x356000 size=0x1000 parent=0x2 p.vaddr=0x356000 + space=0x5 vaddr=0x357000 size=0x1000 parent=0x2 p.vaddr=0x357000 + space=0x5 vaddr=0x358000 size=0x1000 parent=0x2 p.vaddr=0x358000 + space=0x5 vaddr=0x359000 size=0x1000 parent=0x2 p.vaddr=0x359000 + space=0x5 vaddr=0x35a000 size=0x1000 parent=0x2 p.vaddr=0x35a000 + space=0x5 vaddr=0x35b000 size=0x1000 parent=0x2 p.vaddr=0x35b000 + space=0x5 vaddr=0x35c000 size=0x1000 parent=0x2 p.vaddr=0x35c000 + space=0x5 vaddr=0x35d000 size=0x1000 parent=0x2 p.vaddr=0x35d000 + space=0x5 vaddr=0x35e000 size=0x1000 parent=0x2 p.vaddr=0x35e000 + space=0x5 vaddr=0x35f000 size=0x1000 parent=0x2 p.vaddr=0x35f000 + space=0x5 vaddr=0x360000 size=0x1000 parent=0x2 p.vaddr=0x360000 + space=0x5 vaddr=0x361000 size=0x1000 parent=0x2 p.vaddr=0x361000 + space=0x5 vaddr=0x362000 size=0x1000 parent=0x2 p.vaddr=0x362000 + space=0x5 vaddr=0x363000 size=0x1000 parent=0x2 p.vaddr=0x363000 + space=0x5 vaddr=0x364000 size=0x1000 parent=0x2 p.vaddr=0x364000 + space=0x5 vaddr=0x365000 size=0x1000 parent=0x2 p.vaddr=0x365000 + space=0x5 vaddr=0x366000 size=0x1000 parent=0x2 p.vaddr=0x366000 + space=0x5 vaddr=0x367000 size=0x1000 parent=0x2 p.vaddr=0x367000 + space=0x5 vaddr=0x368000 size=0x1000 parent=0x2 p.vaddr=0x368000 + space=0x5 vaddr=0x369000 size=0x1000 parent=0x2 p.vaddr=0x369000 + space=0x5 vaddr=0x36a000 size=0x1000 parent=0x2 p.vaddr=0x36a000 + space=0x5 vaddr=0x36b000 size=0x1000 parent=0x2 p.vaddr=0x36b000 + space=0x5 vaddr=0x36c000 size=0x1000 parent=0x2 p.vaddr=0x36c000 + space=0x5 vaddr=0x36d000 size=0x1000 parent=0x2 p.vaddr=0x36d000 + space=0x5 vaddr=0x36e000 size=0x1000 parent=0x2 p.vaddr=0x36e000 + space=0x5 vaddr=0x36f000 size=0x1000 parent=0x2 p.vaddr=0x36f000 + space=0x5 vaddr=0x370000 size=0x1000 parent=0x2 p.vaddr=0x370000 + space=0x5 vaddr=0x371000 size=0x1000 parent=0x2 p.vaddr=0x371000 + space=0x5 vaddr=0x372000 size=0x1000 parent=0x2 p.vaddr=0x372000 + space=0x5 vaddr=0x373000 size=0x1000 parent=0x2 p.vaddr=0x373000 + space=0x5 vaddr=0x374000 size=0x1000 parent=0x2 p.vaddr=0x374000 + space=0x5 vaddr=0x375000 size=0x1000 parent=0x2 p.vaddr=0x375000 + space=0x5 vaddr=0x376000 size=0x1000 parent=0x2 p.vaddr=0x376000 + space=0x5 vaddr=0x377000 size=0x1000 parent=0x2 p.vaddr=0x377000 + space=0x5 vaddr=0x378000 size=0x1000 parent=0x2 p.vaddr=0x378000 + space=0x5 vaddr=0x379000 size=0x1000 parent=0x2 p.vaddr=0x379000 + space=0x5 vaddr=0x37a000 size=0x1000 parent=0x2 p.vaddr=0x37a000 + space=0x5 vaddr=0x37b000 size=0x1000 parent=0x2 p.vaddr=0x37b000 + space=0x5 vaddr=0x37c000 size=0x1000 parent=0x2 p.vaddr=0x37c000 + space=0x5 vaddr=0x37d000 size=0x1000 parent=0x2 p.vaddr=0x37d000 + space=0x5 vaddr=0x37e000 size=0x1000 parent=0x2 p.vaddr=0x37e000 + space=0x5 vaddr=0x37f000 size=0x1000 parent=0x2 p.vaddr=0x37f000 + space=0x5 vaddr=0x380000 size=0x1000 parent=0x2 p.vaddr=0x380000 + space=0x5 vaddr=0x381000 size=0x1000 parent=0x2 p.vaddr=0x381000 + space=0x5 vaddr=0x382000 size=0x1000 parent=0x2 p.vaddr=0x382000 + space=0x5 vaddr=0x383000 size=0x1000 parent=0x2 p.vaddr=0x383000 + space=0x5 vaddr=0x384000 size=0x1000 parent=0x2 p.vaddr=0x384000 + space=0x5 vaddr=0x385000 size=0x1000 parent=0x2 p.vaddr=0x385000 + space=0x5 vaddr=0x386000 size=0x1000 parent=0x2 p.vaddr=0x386000 + space=0x5 vaddr=0x387000 size=0x1000 parent=0x2 p.vaddr=0x387000 + space=0x5 vaddr=0x388000 size=0x1000 parent=0x2 p.vaddr=0x388000 + space=0x5 vaddr=0x389000 size=0x1000 parent=0x2 p.vaddr=0x389000 + space=0x5 vaddr=0x38a000 size=0x1000 parent=0x2 p.vaddr=0x38a000 + space=0x5 vaddr=0x38b000 size=0x1000 parent=0x2 p.vaddr=0x38b000 + space=0x5 vaddr=0x38c000 size=0x1000 parent=0x2 p.vaddr=0x38c000 + space=0x5 vaddr=0x38d000 size=0x1000 parent=0x2 p.vaddr=0x38d000 + space=0x5 vaddr=0x38e000 size=0x1000 parent=0x2 p.vaddr=0x38e000 + space=0x5 vaddr=0x38f000 size=0x1000 parent=0x2 p.vaddr=0x38f000 + space=0x5 vaddr=0x390000 size=0x1000 parent=0x2 p.vaddr=0x390000 + space=0x5 vaddr=0x391000 size=0x1000 parent=0x2 p.vaddr=0x391000 + space=0x5 vaddr=0x392000 size=0x1000 parent=0x2 p.vaddr=0x392000 + space=0x5 vaddr=0x393000 size=0x1000 parent=0x2 p.vaddr=0x393000 + space=0x5 vaddr=0x394000 size=0x1000 parent=0x2 p.vaddr=0x394000 + space=0x5 vaddr=0x395000 size=0x1000 parent=0x2 p.vaddr=0x395000 + space=0x5 vaddr=0x396000 size=0x1000 parent=0x2 p.vaddr=0x396000 + space=0x5 vaddr=0x397000 size=0x1000 parent=0x2 p.vaddr=0x397000 + space=0x5 vaddr=0x398000 size=0x1000 parent=0x2 p.vaddr=0x398000 + space=0x5 vaddr=0x399000 size=0x1000 parent=0x2 p.vaddr=0x399000 + space=0x5 vaddr=0x39a000 size=0x1000 parent=0x2 p.vaddr=0x39a000 + space=0x5 vaddr=0x39b000 size=0x1000 parent=0x2 p.vaddr=0x39b000 + space=0x5 vaddr=0x39c000 size=0x1000 parent=0x2 p.vaddr=0x39c000 + space=0x5 vaddr=0x39d000 size=0x1000 parent=0x2 p.vaddr=0x39d000 + space=0x5 vaddr=0x39e000 size=0x1000 parent=0x2 p.vaddr=0x39e000 + space=0x5 vaddr=0x39f000 size=0x1000 parent=0x2 p.vaddr=0x39f000 + space=0x5 vaddr=0x3a0000 size=0x1000 parent=0x2 p.vaddr=0x3a0000 + space=0x5 vaddr=0x3a1000 size=0x1000 parent=0x2 p.vaddr=0x3a1000 + space=0x5 vaddr=0x3a2000 size=0x1000 parent=0x2 p.vaddr=0x3a2000 + space=0x5 vaddr=0x3a3000 size=0x1000 parent=0x2 p.vaddr=0x3a3000 + space=0x5 vaddr=0x3a4000 size=0x1000 parent=0x2 p.vaddr=0x3a4000 + space=0x5 vaddr=0x3a5000 size=0x1000 parent=0x2 p.vaddr=0x3a5000 + space=0x5 vaddr=0x3a6000 size=0x1000 parent=0x2 p.vaddr=0x3a6000 + space=0x5 vaddr=0x3a7000 size=0x1000 parent=0x2 p.vaddr=0x3a7000 + space=0x5 vaddr=0x3a8000 size=0x1000 parent=0x2 p.vaddr=0x3a8000 + space=0x5 vaddr=0x3a9000 size=0x1000 parent=0x2 p.vaddr=0x3a9000 + space=0x5 vaddr=0x3aa000 size=0x1000 parent=0x2 p.vaddr=0x3aa000 + space=0x5 vaddr=0x3ab000 size=0x1000 parent=0x2 p.vaddr=0x3ab000 + space=0x5 vaddr=0x3ac000 size=0x1000 parent=0x2 p.vaddr=0x3ac000 + space=0x5 vaddr=0x3ad000 size=0x1000 parent=0x2 p.vaddr=0x3ad000 + space=0x5 vaddr=0x3ae000 size=0x1000 parent=0x2 p.vaddr=0x3ae000 + space=0x5 vaddr=0x3af000 size=0x1000 parent=0x2 p.vaddr=0x3af000 + space=0x5 vaddr=0x3b0000 size=0x1000 parent=0x2 p.vaddr=0x3b0000 + space=0x5 vaddr=0x3b1000 size=0x1000 parent=0x2 p.vaddr=0x3b1000 + space=0x5 vaddr=0x3b2000 size=0x1000 parent=0x2 p.vaddr=0x3b2000 + space=0x5 vaddr=0x3b3000 size=0x1000 parent=0x2 p.vaddr=0x3b3000 + space=0x5 vaddr=0x3b4000 size=0x1000 parent=0x2 p.vaddr=0x3b4000 + space=0x5 vaddr=0x3b5000 size=0x1000 parent=0x2 p.vaddr=0x3b5000 + space=0x5 vaddr=0x3b6000 size=0x1000 parent=0x2 p.vaddr=0x3b6000 + space=0x5 vaddr=0x3b7000 size=0x1000 parent=0x2 p.vaddr=0x3b7000 + space=0x5 vaddr=0x3b8000 size=0x1000 parent=0x2 p.vaddr=0x3b8000 + space=0x5 vaddr=0x3b9000 size=0x1000 parent=0x2 p.vaddr=0x3b9000 + space=0x5 vaddr=0x3ba000 size=0x1000 parent=0x2 p.vaddr=0x3ba000 + space=0x5 vaddr=0x3bb000 size=0x1000 parent=0x2 p.vaddr=0x3bb000 + space=0x5 vaddr=0x3bc000 size=0x1000 parent=0x2 p.vaddr=0x3bc000 + space=0x5 vaddr=0x3bd000 size=0x1000 parent=0x2 p.vaddr=0x3bd000 + space=0x5 vaddr=0x3be000 size=0x1000 parent=0x2 p.vaddr=0x3be000 + space=0x5 vaddr=0x3bf000 size=0x1000 parent=0x2 p.vaddr=0x3bf000 + space=0x5 vaddr=0x3c0000 size=0x1000 parent=0x2 p.vaddr=0x3c0000 + space=0x5 vaddr=0x3c1000 size=0x1000 parent=0x2 p.vaddr=0x3c1000 + space=0x5 vaddr=0x3c2000 size=0x1000 parent=0x2 p.vaddr=0x3c2000 + space=0x5 vaddr=0x3c3000 size=0x1000 parent=0x2 p.vaddr=0x3c3000 + space=0x5 vaddr=0x3c4000 size=0x1000 parent=0x2 p.vaddr=0x3c4000 + space=0x5 vaddr=0x3c5000 size=0x1000 parent=0x2 p.vaddr=0x3c5000 + space=0x5 vaddr=0x3c6000 size=0x1000 parent=0x2 p.vaddr=0x3c6000 + space=0x5 vaddr=0x3c7000 size=0x1000 parent=0x2 p.vaddr=0x3c7000 + space=0x5 vaddr=0x3c8000 size=0x1000 parent=0x2 p.vaddr=0x3c8000 + space=0x5 vaddr=0x3c9000 size=0x1000 parent=0x2 p.vaddr=0x3c9000 + space=0x5 vaddr=0x3ca000 size=0x1000 parent=0x2 p.vaddr=0x3ca000 + space=0x5 vaddr=0x3cb000 size=0x1000 parent=0x2 p.vaddr=0x3cb000 + space=0x5 vaddr=0x3cc000 size=0x1000 parent=0x2 p.vaddr=0x3cc000 + space=0x5 vaddr=0x3cd000 size=0x1000 parent=0x2 p.vaddr=0x3cd000 + space=0x5 vaddr=0x3ce000 size=0x1000 parent=0x2 p.vaddr=0x3ce000 + space=0x5 vaddr=0x3cf000 size=0x1000 parent=0x2 p.vaddr=0x3cf000 + space=0x5 vaddr=0x3d0000 size=0x1000 parent=0x2 p.vaddr=0x3d0000 + space=0x5 vaddr=0x3d1000 size=0x1000 parent=0x2 p.vaddr=0x3d1000 + space=0x5 vaddr=0x3d2000 size=0x1000 parent=0x2 p.vaddr=0x3d2000 + space=0x5 vaddr=0x3d3000 size=0x1000 parent=0x2 p.vaddr=0x3d3000 + space=0x5 vaddr=0x3d4000 size=0x1000 parent=0x2 p.vaddr=0x3d4000 + space=0x5 vaddr=0x3d5000 size=0x1000 parent=0x2 p.vaddr=0x3d5000 + space=0x5 vaddr=0x3d6000 size=0x1000 parent=0x2 p.vaddr=0x3d6000 + space=0x5 vaddr=0x3d7000 size=0x1000 parent=0x2 p.vaddr=0x3d7000 + space=0x5 vaddr=0x3d8000 size=0x1000 parent=0x2 p.vaddr=0x3d8000 + space=0x5 vaddr=0x3d9000 size=0x1000 parent=0x2 p.vaddr=0x3d9000 + space=0x5 vaddr=0x3da000 size=0x1000 parent=0x2 p.vaddr=0x3da000 + space=0x5 vaddr=0x3db000 size=0x1000 parent=0x2 p.vaddr=0x3db000 + space=0x5 vaddr=0x3dc000 size=0x1000 parent=0x2 p.vaddr=0x3dc000 + space=0x5 vaddr=0x3dd000 size=0x1000 parent=0x2 p.vaddr=0x3dd000 + space=0x5 vaddr=0x3de000 size=0x1000 parent=0x2 p.vaddr=0x3de000 + space=0x5 vaddr=0x3df000 size=0x1000 parent=0x2 p.vaddr=0x3df000 + space=0x5 vaddr=0x3e0000 size=0x1000 parent=0x2 p.vaddr=0x3e0000 + space=0x5 vaddr=0x3e1000 size=0x1000 parent=0x2 p.vaddr=0x3e1000 + space=0x5 vaddr=0x3e2000 size=0x1000 parent=0x2 p.vaddr=0x3e2000 + space=0x5 vaddr=0x3e3000 size=0x1000 parent=0x2 p.vaddr=0x3e3000 + space=0x5 vaddr=0x3e4000 size=0x1000 parent=0x2 p.vaddr=0x3e4000 + space=0x5 vaddr=0x3e5000 size=0x1000 parent=0x2 p.vaddr=0x3e5000 + space=0x5 vaddr=0x3e6000 size=0x1000 parent=0x2 p.vaddr=0x3e6000 + space=0x5 vaddr=0x3e7000 size=0x1000 parent=0x2 p.vaddr=0x3e7000 + space=0x5 vaddr=0x3e8000 size=0x1000 parent=0x2 p.vaddr=0x3e8000 + space=0x5 vaddr=0x3e9000 size=0x1000 parent=0x2 p.vaddr=0x3e9000 + space=0x5 vaddr=0x3ea000 size=0x1000 parent=0x2 p.vaddr=0x3ea000 + space=0x5 vaddr=0x3eb000 size=0x1000 parent=0x2 p.vaddr=0x3eb000 + space=0x5 vaddr=0x3ec000 size=0x1000 parent=0x2 p.vaddr=0x3ec000 + space=0x5 vaddr=0x3ed000 size=0x1000 parent=0x2 p.vaddr=0x3ed000 + space=0x5 vaddr=0x3ee000 size=0x1000 parent=0x2 p.vaddr=0x3ee000 + space=0x5 vaddr=0x3ef000 size=0x1000 parent=0x2 p.vaddr=0x3ef000 + space=0x5 vaddr=0x3f0000 size=0x1000 parent=0x2 p.vaddr=0x3f0000 + space=0x5 vaddr=0x3f1000 size=0x1000 parent=0x2 p.vaddr=0x3f1000 + space=0x5 vaddr=0x3f2000 size=0x1000 parent=0x2 p.vaddr=0x3f2000 + space=0x5 vaddr=0x3f3000 size=0x1000 parent=0x2 p.vaddr=0x3f3000 + space=0x5 vaddr=0x3f4000 size=0x1000 parent=0x2 p.vaddr=0x3f4000 + space=0x5 vaddr=0x3f5000 size=0x1000 parent=0x2 p.vaddr=0x3f5000 + space=0x5 vaddr=0x3f6000 size=0x1000 parent=0x2 p.vaddr=0x3f6000 + space=0x5 vaddr=0x3f7000 size=0x1000 parent=0x2 p.vaddr=0x3f7000 + space=0x5 vaddr=0x3f8000 size=0x1000 parent=0x2 p.vaddr=0x3f8000 + space=0x5 vaddr=0x3f9000 size=0x1000 parent=0x2 p.vaddr=0x3f9000 + space=0x5 vaddr=0x3fa000 size=0x1000 parent=0x2 p.vaddr=0x3fa000 + space=0x5 vaddr=0x3fb000 size=0x1000 parent=0x2 p.vaddr=0x3fb000 + space=0x5 vaddr=0x3fc000 size=0x1000 parent=0x2 p.vaddr=0x3fc000 + space=0x5 vaddr=0x3fd000 size=0x1000 parent=0x2 p.vaddr=0x3fd000 + space=0x5 vaddr=0x3fe000 size=0x1000 parent=0x2 p.vaddr=0x3fe000 + space=0x5 vaddr=0x3ff000 size=0x1000 parent=0x2 p.vaddr=0x3ff000 + +space=0x2 vaddr=0x400000 size=0x400000 + space=0x5 vaddr=0x800000 size=0x400000 parent=0x2 p.vaddr=0x400000 + +space=0x2 vaddr=0x400000 size=0x400000 + space=0x5 vaddr=0x800000 size=0x400000 parent=0x2 p.vaddr=0x400000 + space=0x6 vaddr=0x8000 size=0x1000 parent=0x5 p.vaddr=0x801000 + +space=0x2 vaddr=0x400000 size=0x400000 + space=0x5 vaddr=0x800000 size=0x400000 parent=0x2 p.vaddr=0x400000 + space=0x6 vaddr=0x8000 size=0x1000 parent=0x5 p.vaddr=0x801000 + space=0x7 vaddr=0x1000 size=0x1000 parent=0x5 p.vaddr=0x801000 + +space=0x2 vaddr=0x400000 size=0x400000 + space=0x5 vaddr=0x800000 size=0x400000 parent=0x2 p.vaddr=0x400000 + space=0x6 vaddr=0x8000 size=0x1000 parent=0x5 p.vaddr=0x801000 + diff --git a/kernel/fiasco/src/test/unit/mapdb_t.cpp b/kernel/fiasco/src/test/unit/mapdb_t.cpp new file mode 100644 index 00000000..b97d60ca --- /dev/null +++ b/kernel/fiasco/src/test/unit/mapdb_t.cpp @@ -0,0 +1,373 @@ +IMPLEMENTATION: + +#include +#include +#include +#include + +using namespace std; + +#include "mapdb.h" + +IMPLEMENTATION: + +#include "config.h" +#include "space.h" + +static Space *s0; +static Space *other; +static Space *client; +static Space *father; +static Space *&grandfather = s0; +static Space *son; +static Space *daughter; +static Space *aunt; + +typedef Virt_addr Phys_addr; + +static size_t page_sizes[] = +{ Config::SUPERPAGE_SHIFT - Config::PAGE_SHIFT, 0 }; + +static size_t page_sizes_max = 2; + + +static void init_spaces() +{ + static Ram_quota rq; + L4_fpage utcb_area = L4_fpage::mem(0x1200000, Config::PAGE_SHIFT); + s0 = new Space(Space::Default_factory(), &rq, utcb_area); + other = new Space(Space::Default_factory(), &rq, utcb_area); + client = new Space(Space::Default_factory(), &rq, utcb_area); + father = new Space(Space::Default_factory(), &rq, utcb_area); + son = new Space(Space::Default_factory(), &rq, utcb_area); + daughter = new Space(Space::Default_factory(), &rq, utcb_area); + aunt = new Space(Space::Default_factory(), &rq, utcb_area); +} + +static void print_node(Mapping* node, const Mapdb::Frame& frame) +{ + assert (node); + + size_t shift; + + for (Mapdb::Iterator i(frame, node, Virt_addr(0), Virt_addr(~0)); node;) + { + for (int d = node->depth(); d != 0; d--) + cout << ' '; + + shift = i.shift(); + + cout << setbase(16) + << "space=0x" << (unsigned) (node->space()) + << " vaddr=0x" << (node->page() << shift).value() + << " size=0x" << (1UL << shift); + + if (Mapping* p = node->parent()) + { + cout << " parent=0x" << p->space() + << " p.vaddr=0x" << (p->page() << shift).value(); + } + + cout << endl; + + node = i; + if (node) + { + shift = i.shift(); + ++i; + } + } + cout << endl; +} + +void basic() +{ + Mapdb m (s0, Page_number(1U << (32 - Config::SUPERPAGE_SHIFT)), page_sizes, page_sizes_max); + + Mapping *node, *sub, *subsub; + Mapdb::Frame frame; + + assert (! m.lookup(other, Mem_space::Addr::create(Config::PAGE_SIZE), + Mem_space::Phys_addr::create(Config::PAGE_SIZE), + &node, &frame)); + + cout << "Looking up 4M node at physaddr=0K" << endl; + assert (m.lookup (s0, Mem_space::Addr::create(0), + Mem_space::Phys_addr::create(0), + &node, &frame)); + print_node (node, frame); + + cout << "Inserting submapping" << endl; + sub = m.insert (frame, node, other, + Mem_space::Addr::create(2*Config::PAGE_SIZE), + Mem_space::Phys_addr::create(Config::PAGE_SIZE), + Mem_space::Size::create(Config::PAGE_SIZE)); + print_node (node, frame); + + m.free (frame); + + ////////////////////////////////////////////////////////////////////// + + cout << "Looking up 4M node at physaddr=8M" << endl; + assert (m.lookup (s0, + Mem_space::Addr::create(2*Config::SUPERPAGE_SIZE), + Mem_space::Phys_addr::create(2*Config::SUPERPAGE_SIZE), + &node, &frame)); + print_node (node, frame); + + // XXX broken mapdb: assert (node->size() == Config::SUPERPAGE_SIZE); + + cout << "Inserting submapping" << endl; + sub = m.insert (frame, node, other, + Mem_space::Addr::create(4*Config::SUPERPAGE_SIZE), + Mem_space::Phys_addr::create(2*Config::SUPERPAGE_SIZE), + Mem_space::Size::create(Config::SUPERPAGE_SIZE)); + print_node (node, frame); + + assert (m.shift(frame, sub) == Config::SUPERPAGE_SHIFT- Config::PAGE_SHIFT); + + // Before we can insert new mappings, we must free the tree. + m.free (frame); + + cout << "Get that mapping again" << endl; + assert (m.lookup (other, + Mem_space::Addr::create(4*Config::SUPERPAGE_SIZE), + Mem_space::Phys_addr::create(2*Config::SUPERPAGE_SIZE), + &sub, &frame)); + print_node (sub, frame); + + node = sub->parent(); + + cout << "Inserting 4K submapping" << endl; + subsub = m.insert (frame, sub, client, + Mem_space::Addr::create(15*Config::PAGE_SIZE), + Mem_space::Phys_addr::create(2*Config::SUPERPAGE_SIZE), + Mem_space::Size::create(Config::PAGE_SIZE)); + print_node (node, frame); + + m.free (frame); +} + +static void print_whole_tree(Mapping *node, const Mapdb::Frame& frame) +{ + while(node->parent()) + node = node->parent(); + print_node (node, frame); +} + + +void maphole() +{ + Mapdb m(s0, Page_number(1U << (32 - Config::SUPERPAGE_SHIFT)), + page_sizes, page_sizes_max); + + Mapping *gf_map, *f_map, *son_map, *daughter_map, *a_map; + Mapdb::Frame frame; + + cout << "Looking up 4K node at physaddr=0" << endl; + assert (m.lookup (grandfather, Mem_space::Addr::create(0), + Mem_space::Phys_addr::create(0), &gf_map, &frame)); + print_whole_tree (gf_map, frame); + + cout << "Inserting father mapping" << endl; + f_map = m.insert (frame, gf_map, father, Mem_space::Addr::create(0), + Mem_space::Phys_addr::create(0), + Mem_space::Size::create(Config::PAGE_SIZE)); + print_whole_tree (gf_map, frame); + m.free(frame); + + + cout << "Looking up father at physaddr=0" << endl; + assert (m.lookup (father, Mem_space::Addr::create(0), + Mem_space::Phys_addr::create(0), &f_map, &frame)); + print_whole_tree (f_map, frame); + + cout << "Inserting son mapping" << endl; + son_map = m.insert (frame, f_map, son, Mem_space::Addr::create(0), + Mem_space::Phys_addr::create(0), + Mem_space::Size::create(Config::PAGE_SIZE)); + print_whole_tree (f_map, frame); + m.free(frame); + + + cout << "Looking up father at physaddr=0" << endl; + assert (m.lookup (father, Mem_space::Addr::create(0), + Mem_space::Phys_addr::create(0), &f_map, &frame)); + print_whole_tree (f_map, frame); + + cout << "Inserting daughter mapping" << endl; + daughter_map = m.insert (frame, f_map, daughter, Mem_space::Addr::create(0), + Mem_space::Phys_addr::create(0), + Mem_space::Size::create(Config::PAGE_SIZE)); + print_whole_tree (f_map, frame); + m.free(frame); + + + cout << "Looking up son at physaddr=0" << endl; + assert (m.lookup(son, Mem_space::Addr::create(0), + Mem_space::Phys_addr::create(0), &son_map, &frame)); + f_map = son_map->parent(); + print_whole_tree (son_map, frame); + + cout << "Son has accident on return from disco" << endl; + m.flush(frame, son_map, L4_map_mask::full(), + Mem_space::Addr::create(0), + Mem_space::Addr::create(Config::PAGE_SIZE)); + m.free(frame); + + cout << "Lost aunt returns from holidays" << endl; + assert (m.lookup (grandfather, Mem_space::Addr::create(0), + Mem_space::Phys_addr::create(0), &gf_map, &frame)); + print_whole_tree (gf_map, frame); + + cout << "Inserting aunt mapping" << endl; + a_map = m.insert (frame, gf_map, aunt, Mem_space::Addr::create(0), + Mem_space::Phys_addr::create(0), + Mem_space::Size::create(Config::PAGE_SIZE)); + print_whole_tree (gf_map, frame); + m.free(frame); + + cout << "Looking up daughter at physaddr=0" << endl; + assert (m.lookup(daughter, Mem_space::Addr::create(0), + Mem_space::Phys_addr::create(0), &daughter_map, &frame)); + print_whole_tree (daughter_map, frame); + f_map = daughter_map->parent(); + cout << "Father of daugther is " << (unsigned)(f_map->space()) << endl; + + assert(f_map->space() == father); + + m.free(frame); +} + + +void flushtest() +{ + Mapdb m(s0, Page_number(1U << (32 - Config::SUPERPAGE_SHIFT)), page_sizes, page_sizes_max); + + Mapping *gf_map, *f_map, *son_map, *a_map; + Mapdb::Frame frame; + + cout << "Looking up 4K node at physaddr=0" << endl; + assert (m.lookup (grandfather, Virt_addr(0), Phys_addr(0), &gf_map, &frame)); + print_whole_tree (gf_map, frame); + + cout << "Inserting father mapping" << endl; + f_map = m.insert (frame, gf_map, father, Virt_addr(0), Phys_addr(0), Virt_size(Config::PAGE_SIZE)); + print_whole_tree (gf_map, frame); + m.free(frame); + + + cout << "Looking up father at physaddr=0" << endl; + assert (m.lookup (father, Virt_addr(0), Phys_addr(0), &f_map, &frame)); + print_whole_tree (f_map, frame); + + cout << "Inserting son mapping" << endl; + son_map = m.insert (frame, f_map, son, Virt_addr(0), Phys_addr(0), Virt_size(Config::PAGE_SIZE)); + print_whole_tree (f_map, frame); + m.free(frame); + + cout << "Lost aunt returns from holidays" << endl; + assert (m.lookup (grandfather, Virt_addr(0), Phys_addr(0), &gf_map, &frame)); + print_whole_tree (gf_map, frame); + + cout << "Inserting aunt mapping" << endl; + a_map = m.insert (frame, gf_map, aunt, Virt_addr(0), Phys_addr(0), Virt_size(Config::PAGE_SIZE)); + print_whole_tree (gf_map, frame); + m.free(frame); + + cout << "Looking up father at physaddr=0" << endl; + assert (m.lookup(father, Virt_addr(0), Phys_addr(0), &f_map, &frame)); + gf_map = f_map->parent(); + print_whole_tree (gf_map, frame); + + cout << "father is killed by his new love" << endl; + m.flush(frame, f_map, L4_map_mask::full(), Virt_addr(0), Virt_addr(Config::PAGE_SIZE)); + print_whole_tree (gf_map, frame); + m.free(frame); + + cout << "Try resurrecting the killed father again" << endl; + assert (! m.lookup(father, Virt_addr(0), Phys_addr(0), &f_map, &frame)); + + cout << "Resurrection is impossible, as it ought to be." << endl; +} + +void multilevel () +{ + size_t three_page_sizes[] = { 30 - Config::PAGE_SHIFT, + 22 - Config::PAGE_SHIFT, + 0}; + Mapdb m (s0, Page_number(4), three_page_sizes, 3); + + Mapping *node /* , *sub, *subsub */; + Mapdb::Frame frame; + + cout << "Looking up 0xd2000000" << endl; + assert (m.lookup (s0, Virt_addr(0xd2000000), Phys_addr(0xd2000000), &node, &frame)); + + print_node (node, frame); +} + +#include "boot_info.h" +#include "cpu.h" +#include "config.h" +#include "kip_init.h" +#include "kmem.h" +#include "kmem_alloc.h" +#include "per_cpu_data_alloc.h" +#include "static_init.h" +#include "usermode.h" +#include "vmem_alloc.h" + +class Timeout; + +DEFINE_PER_CPU Per_cpu timeslice_timeout; +STATIC_INITIALIZER_P(init, STARTUP_INIT_PRIO); +STATIC_INITIALIZER_P(init2, POST_CPU_LOCAL_INIT_PRIO); + +static void init() +{ + Usermode::init(0); + Boot_info::init(); + Kip_init::setup_ux(); + Kmem_alloc::base_init(); + Kip_init::init(); + Kmem_alloc::init(); + + // Initialize cpu-local data management and run constructors for CPU 0 + Per_cpu_data::init_ctors(); + Per_cpu_data_alloc::alloc(0); + Per_cpu_data::run_ctors(0); + +} + +static void init2() +{ + Cpu::init_global_features(); + Config::init(); + Kmem::init_mmu(Cpu::cpus.cpu(0)); + printf("ha\n"); + Vmem_alloc::init(); +} + +int main() +{ + init_spaces(); + cout << "Basic test" << endl; + basic(); + cout << "########################################" << endl; + + cout << "Hole test" << endl; + maphole(); + cout << "########################################" << endl; + + cout << "Flush test" << endl; + flushtest(); + cout << "########################################" << endl; + + cout << "Multilevel test" << endl; + multilevel(); + cout << "########################################" << endl; + + cerr << "OK" << endl; + return(0); +} diff --git a/kernel/fiasco/src/test/unit/mapdb_t.out.verify b/kernel/fiasco/src/test/unit/mapdb_t.out.verify new file mode 100644 index 00000000..e33ae0be --- /dev/null +++ b/kernel/fiasco/src/test/unit/mapdb_t.out.verify @@ -0,0 +1,124 @@ +Basic test +Looking up 4M node at physaddr=0K +space=0x2 vaddr=0x0 size=0x400000 + +Inserting submapping +space=0x2 vaddr=0x0 size=0x400000 + space=0xa vaddr=0x2000 size=0x1000 parent=0x2 p.vaddr=0x1000 + +Looking up 4M node at physaddr=8M +space=0x2 vaddr=0x800000 size=0x400000 + +Inserting submapping +space=0x2 vaddr=0x800000 size=0x400000 + space=0xa vaddr=0x1000000 size=0x400000 parent=0x2 p.vaddr=0x800000 + +Get that mapping again + space=0xa vaddr=0x1000000 size=0x400000 parent=0x2 p.vaddr=0x800000 + +Inserting 4K submapping +space=0x2 vaddr=0x800000 size=0x400000 + space=0xa vaddr=0x1000000 size=0x400000 parent=0x2 p.vaddr=0x800000 + space=0xb vaddr=0xf000 size=0x1000 parent=0xa p.vaddr=0x1000000 + +######################################## +Hole test +Looking up 4K node at physaddr=0 +space=0x2 vaddr=0x0 size=0x400000 + +Inserting father mapping +space=0x2 vaddr=0x0 size=0x400000 + space=0x6 vaddr=0x0 size=0x1000 parent=0x2 p.vaddr=0x0 + +Looking up father at physaddr=0 +space=0x2 vaddr=0x0 size=0x1000 + space=0x6 vaddr=0x0 size=0x1000 parent=0x2 p.vaddr=0x0 + +Inserting son mapping +space=0x2 vaddr=0x0 size=0x1000 + space=0x6 vaddr=0x0 size=0x1000 parent=0x2 p.vaddr=0x0 + space=0x7 vaddr=0x0 size=0x1000 parent=0x6 p.vaddr=0x0 + +Looking up father at physaddr=0 +space=0x2 vaddr=0x0 size=0x1000 + space=0x6 vaddr=0x0 size=0x1000 parent=0x2 p.vaddr=0x0 + space=0x7 vaddr=0x0 size=0x1000 parent=0x6 p.vaddr=0x0 + +Inserting daughter mapping +space=0x2 vaddr=0x0 size=0x1000 + space=0x6 vaddr=0x0 size=0x1000 parent=0x2 p.vaddr=0x0 + space=0x7 vaddr=0x0 size=0x1000 parent=0x6 p.vaddr=0x0 + space=0x8 vaddr=0x0 size=0x1000 parent=0x6 p.vaddr=0x0 + +Looking up son at physaddr=0 +space=0x2 vaddr=0x0 size=0x1000 + space=0x6 vaddr=0x0 size=0x1000 parent=0x2 p.vaddr=0x0 + space=0x7 vaddr=0x0 size=0x1000 parent=0x6 p.vaddr=0x0 + space=0x8 vaddr=0x0 size=0x1000 parent=0x6 p.vaddr=0x0 + +Son has accident on return from disco +Lost aunt returns from holidays +space=0x2 vaddr=0x0 size=0x400000 + space=0x6 vaddr=0x0 size=0x1000 parent=0x2 p.vaddr=0x0 + space=0x8 vaddr=0x0 size=0x1000 parent=0x6 p.vaddr=0x0 + +Inserting aunt mapping +space=0x2 vaddr=0x0 size=0x400000 + space=0x6 vaddr=0x0 size=0x1000 parent=0x2 p.vaddr=0x0 + space=0x8 vaddr=0x0 size=0x1000 parent=0x6 p.vaddr=0x0 + space=0x9 vaddr=0x0 size=0x1000 parent=0x2 p.vaddr=0x0 + +Looking up daughter at physaddr=0 +space=0x2 vaddr=0x0 size=0x1000 + space=0x6 vaddr=0x0 size=0x1000 parent=0x2 p.vaddr=0x0 + space=0x8 vaddr=0x0 size=0x1000 parent=0x6 p.vaddr=0x0 + space=0x9 vaddr=0x0 size=0x1000 parent=0x2 p.vaddr=0x0 + +Father of daugther is 6 +######################################## +Flush test +Looking up 4K node at physaddr=0 +space=0x2 vaddr=0x0 size=0x400000 + +Inserting father mapping +space=0x2 vaddr=0x0 size=0x400000 + space=0x6 vaddr=0x0 size=0x1000 parent=0x2 p.vaddr=0x0 + +Looking up father at physaddr=0 +space=0x2 vaddr=0x0 size=0x1000 + space=0x6 vaddr=0x0 size=0x1000 parent=0x2 p.vaddr=0x0 + +Inserting son mapping +space=0x2 vaddr=0x0 size=0x1000 + space=0x6 vaddr=0x0 size=0x1000 parent=0x2 p.vaddr=0x0 + space=0x7 vaddr=0x0 size=0x1000 parent=0x6 p.vaddr=0x0 + +Lost aunt returns from holidays +space=0x2 vaddr=0x0 size=0x400000 + space=0x6 vaddr=0x0 size=0x1000 parent=0x2 p.vaddr=0x0 + space=0x7 vaddr=0x0 size=0x1000 parent=0x6 p.vaddr=0x0 + +Inserting aunt mapping +space=0x2 vaddr=0x0 size=0x400000 + space=0x6 vaddr=0x0 size=0x1000 parent=0x2 p.vaddr=0x0 + space=0x7 vaddr=0x0 size=0x1000 parent=0x6 p.vaddr=0x0 + space=0x9 vaddr=0x0 size=0x1000 parent=0x2 p.vaddr=0x0 + +Looking up father at physaddr=0 +space=0x2 vaddr=0x0 size=0x1000 + space=0x6 vaddr=0x0 size=0x1000 parent=0x2 p.vaddr=0x0 + space=0x7 vaddr=0x0 size=0x1000 parent=0x6 p.vaddr=0x0 + space=0x9 vaddr=0x0 size=0x1000 parent=0x2 p.vaddr=0x0 + +father is killed by his new love +space=0x2 vaddr=0x0 size=0x1000 + space=0x9 vaddr=0x0 size=0x1000 parent=0x2 p.vaddr=0x0 + +Try resurrecting the killed father again +Resurrection is impossible, as it ought to be. +######################################## +Multilevel test +Looking up 0xd2000000 +space=0x2 vaddr=0xc0000000 size=0x40000000 + +######################################## diff --git a/kernel/fiasco/src/test/wrappers/Makefile b/kernel/fiasco/src/test/wrappers/Makefile new file mode 100644 index 00000000..e3fa16b3 --- /dev/null +++ b/kernel/fiasco/src/test/wrappers/Makefile @@ -0,0 +1,7 @@ +srcdir = ../.. + +all: + +%: + $(MAKE) -I $(srcdir) -I .. -f $(srcdir)/Makefile \ + srcdir=$(srcdir) MODULES_FILE=Modules.wrappers $@ diff --git a/kernel/fiasco/src/test/wrappers/Modules.wrappers b/kernel/fiasco/src/test/wrappers/Modules.wrappers new file mode 100644 index 00000000..2c18b505 --- /dev/null +++ b/kernel/fiasco/src/test/wrappers/Modules.wrappers @@ -0,0 +1,39 @@ +# -*- makefile -*- + +ARCH := ia32 +SUBSYSTEMS := WRAPPERS +WRAPPERS := libwrappers.a + +# Original Fiasco modules needed by wrappers that run under Unix +# without modification + +INTERFACES_WRAPPERS := atomic lock_guard simple_lock slab_cache \ + auto_ptr l4_types l4_ipc + +l4_types_IMPL := l4_types-arch l4_types +l4_ipc_IMPL := l4_ipc-arch l4_ipc + +# Faked stuff made to run under Unix + +INTERFACES_WRAPPERS += globals helping_lock kdb_ke kmem kmem_alloc \ + kmem_slab checksum boot_info kip + +atomic_IMPL := atomic atomic-arch +globals_IMPL := fake_globals +helping_lock_IMPL := fake_helping_lock +kdb_ke_IMPL := fake_kdb_ke +kmem_IMPL := fake_kmem +kmem_alloc_IMPL := fake_kmem_alloc +kmem_slab_IMPL := unix_slab +checksum_IMPL := fake_checksum +boot_info_IMPL := fake_boot_info + +# More special stuff needed in support of the fake stuff + +INTERFACES_WRAPPERS += unix_aligned_alloc +CSRC_WRAPPERS := symbols.c + +PRIVATE_INCDIR := lib/kern/include lib/libk/$(ARCH) lib/libk \ + types/$(ARCH) types +VPATH += lib/libk/$(ARCH) lib/libk types types/$(ARCH) \ + abi abi/$(ARCH) diff --git a/kernel/fiasco/src/test/wrappers/fake_boot_info.cpp b/kernel/fiasco/src/test/wrappers/fake_boot_info.cpp new file mode 100644 index 00000000..cc2fe0f3 --- /dev/null +++ b/kernel/fiasco/src/test/wrappers/fake_boot_info.cpp @@ -0,0 +1,14 @@ +INTERFACE: + +class boot_info +{ + +}; + +IMPLEMENTATION: + +PUBLIC static +const char* boot_info::cmdline() +{ + return ""; +} diff --git a/kernel/fiasco/src/test/wrappers/fake_checksum.cpp b/kernel/fiasco/src/test/wrappers/fake_checksum.cpp new file mode 100644 index 00000000..5aa1cbf0 --- /dev/null +++ b/kernel/fiasco/src/test/wrappers/fake_checksum.cpp @@ -0,0 +1,5 @@ +INTERFACE: + +IMPLEMENTATION: + +//- diff --git a/kernel/fiasco/src/test/wrappers/fake_globals.cpp b/kernel/fiasco/src/test/wrappers/fake_globals.cpp new file mode 100644 index 00000000..df6d1dfb --- /dev/null +++ b/kernel/fiasco/src/test/wrappers/fake_globals.cpp @@ -0,0 +1,37 @@ +INTERFACE: + +#include +#include + +#define panic(fmt...) printf(fmt), exit(1) + +#define check(expression) \ + ((void)((expression) ? 0 : \ + (panic(__FILE__":%u: failed check `"#expression"'", \ + __LINE__), 0))) + +class Thread; +class Context; +class Space; + +extern cpu_info cpu; +extern Space* sigma0; + +IMPLEMENTATION: + +Space* sigma0 = 0; + +cpu_info cpu = { 3, 8, CPU_FAMILY_PENTIUM_PRO, CPU_TYPE_ORIGINAL, 0, + CPUF_ON_CHIP_FPU | + CPUF_4MB_PAGES | + CPUF_CMPXCHG8B | + CPUF_PAGE_GLOBAL_EXT, + {'G', 'e', 'n', 'u', 'i', 'n', 'e', 'I', 'n', 't', 'e', 'l'} + }; + +Context* current() +{ + return reinterpret_cast (1); +} + + diff --git a/kernel/fiasco/src/test/wrappers/fake_helping_lock.cpp b/kernel/fiasco/src/test/wrappers/fake_helping_lock.cpp new file mode 100644 index 00000000..ba765341 --- /dev/null +++ b/kernel/fiasco/src/test/wrappers/fake_helping_lock.cpp @@ -0,0 +1,32 @@ +INTERFACE: + +#include "lock_guard.h" +#include "simple_lock.h" + +class Context; + +class Helping_lock : public Simple_lock +{ + Context* _owner; +}; + +typedef Lock_guard Helping_lock_guard; + +IMPLEMENTATION: + +#include "globals.h" + +PUBLIC void +Helping_lock::lock() +{ + test_and_set(); +} + +PUBLIC Context* +Helping_lock::lock_owner() +{ + if (test()) + return current(); + else + return 0; +} diff --git a/kernel/fiasco/src/test/wrappers/fake_kdb_ke.cpp b/kernel/fiasco/src/test/wrappers/fake_kdb_ke.cpp new file mode 100644 index 00000000..fc27f015 --- /dev/null +++ b/kernel/fiasco/src/test/wrappers/fake_kdb_ke.cpp @@ -0,0 +1,9 @@ +INTERFACE: + +#include + +#define kdb_ke(x) assert(! x) + +IMPLEMENTATION: + +//- diff --git a/kernel/fiasco/src/test/wrappers/fake_kmem.cpp b/kernel/fiasco/src/test/wrappers/fake_kmem.cpp new file mode 100644 index 00000000..f7928542 --- /dev/null +++ b/kernel/fiasco/src/test/wrappers/fake_kmem.cpp @@ -0,0 +1,262 @@ +INTERFACE: + +#include // size_t +#include // vm_offset_t & friends +#include // multiboot_info +#include // pd_entry_t + +#include "kip.h" + +//#include "config_gdt.h" + +/* our own implementation of C++ memory management: disallow dynamic + allocation (except where class-specific new/delete functions exist) */ + +void *operator new(size_t); +void operator delete(void *block); + +// more specialized memory allocation/deallocation functions follow +// below in the "kmem" namespace + +// kernel.ld definitions + +extern "C" { + extern char _start, _edata, _end; + // extern char _physmem_1; + // extern char _tcbs_1; + // extern char _iobitmap_1; + extern char _unused1_1, _unused2_1, _unused3_1, _unused4_io_1; + extern char _ipc_window0_1, _ipc_window1_1; +} + +#if 0 +struct x86_gate; +struct x86_tss; +struct x86_desc; +#endif + +// the kernel memory is a singleton object. we access it through a +// static class interface. (we would have preferred to access it like +// a class, but our method saves the overhead of always passing the +// "this" pointer on the (very small) kernel stack). + +// this object is the system's page-level allocator +class kmem +{ +public: + // constants from the above kernel.ld declarations +// static const vm_offset_t mem_phys = reinterpret_cast(&_physmem_1); + static const vm_offset_t mem_phys = 0; +// static const vm_offset_t mem_tcbs = reinterpret_cast(&_tcbs_1); + static const vm_offset_t mem_user_max = 0xc0000000; + + static vm_offset_t io_bitmap; + + static const vm_offset_t ipc_window0 + = reinterpret_cast(&_ipc_window0_1); + static const vm_offset_t ipc_window1 + = reinterpret_cast(&_ipc_window1_1); + +// enum { gdt_tss = GDT_TSS, +// gdt_code_kernel = GDT_CODE_KERNEL, gdt_data_kernel = GDT_DATA_KERNEL, +// gdt_code_user = GDT_CODE_USER, gdt_data_user = GDT_DATA_USER, +// gdt_max = GDT_MAX }; + +// protected: +// static pd_entry_t *kdir; // kernel page directory +// static pd_entry_t cpu_global; + +private: +// friend class kdb; +// friend class jdb; +// friend class profile; + + kmem(); // default constructors are undefined + kmem(const kmem&); + +// static vm_offset_t mem_max, _himem; + + static const pd_entry_t flag_global = 0x200; // l4-specific pg dir entry flag + +// static x86_gate *kidt; +// static x86_tss *tss; +// static x86_desc *gdt; + + static Kip *kinfo; + +// static multiboot_info kmbi; +// static char kcmdline[256]; +}; + +IMPLEMENTATION: + +#include +#include +#include +#include + +// #include +// #include +// #include +// #include +// #include + + +#include "globals.h" +// #include "entry.h" +// #include "irq_init.h" +// #include "config.h" + +#include "unix_aligned_alloc.h" + +// +// class kmem +// + +// static class variables + +// vm_offset_t kmem::mem_max, kmem::_himem; +// pd_entry_t *kmem::kdir; +// pd_entry_t kmem::cpu_global; + +static Kip the_kinfo = + { + /* magic: */ L4_KERNEL_INFO_MAGIC, + /* version: */ 0x01004444, + 0, {0,}, + 0, 0, 0, 0, + 0, 0, {0,}, + 0, 0, {0,}, + 0, 0, {0,}, + 0, 0, 0, 0, +// main_memory.high: mem_max, + /* main_memory: */ { 0, 0x4000000}, +// reserved0.low = trunc_page(virt_to_phys(&__crt_dummy__)), +// reserved0.high = round_page(virt_to_phys(&_end)), + /* reserved0: */ { 0, 0}, + /* reserved1: */ { 0, 0}, + /* semi_reserved: */ { 1024 * 640, 1024 * 1024}, +// Skipped rest -- rely on 0-initialization. + /* clock: 0 */ + }; + +Kip *kmem::kinfo = &the_kinfo; + +vm_offset_t kmem::io_bitmap + = reinterpret_cast + (unix_aligned_alloc(2 * PAGE_SIZE + 4, 2* PAGE_SIZE)); + +// multiboot_info kmem::kmbi; +// char kmem::kcmdline[256]; + +// x86_gate *kmem::kidt; +// x86_tss *kmem::tss; +// x86_desc *kmem::gdt; + +// +// kmem virtual-space related functions (similar to space_t) +// +PUBLIC static +vm_offset_t +kmem::virt_to_phys(const void *addr) +{ + return reinterpret_cast(addr); +} + +PUBLIC static +inline void *kmem::phys_to_virt(vm_offset_t addr) // physical to kernel-virtual +{ + return reinterpret_cast(addr); +} + +// initialize a new task's page directory with the current master copy +// of kernel page tables +PUBLIC static +void kmem::dir_init(pd_entry_t *d) +{ + // Do nothing. +} + +// +// TLB flushing +// +PUBLIC static +inline void kmem::tlb_flush(vm_offset_t addr) // flush tlb at virtual addr +{ + // Do nothing +} + +PUBLIC static +inline void kmem::tlb_flush() +{ + // Do nothing +} + +// +// ACCESSORS +// +PUBLIC static +inline vm_offset_t +kmem::ipc_window(unsigned win) +{ + if (win == 0) + return ipc_window0; + + return ipc_window1; +} + +PUBLIC static +inline Kip *kmem::info() // returns the kernel info page +{ + return kinfo; +} + +PUBLIC static +const pd_entry_t *kmem::dir() // returns the kernel's page directory +{ + assert (! "Cannot request kernel's page directory."); + return 0; + // return kdir; +} + +PUBLIC static +pd_entry_t kmem::pde_global() // returns mask for global pg dir entries +{ + // return cpu_global; + return flag_global + | ((cpu.feature_flags & CPUF_PAGE_GLOBAL_EXT) + ? INTEL_PDE_GLOBAL + : 0); +} + +// PUBLIC static +// inline const multiboot_info *kmem::mbi() +// { +// return &kmbi; +// } + +// PUBLIC static +// inline const char *kmem::cmdline() +// { +// return kcmdline; +// } + +// PUBLIC static +// inline x86_gate *kmem::idt() +// { +// return kidt; +// } + +// PUBLIC static +// inline vm_offset_t kmem::himem() +// { +// return _himem; +// } + +// // Get a pointer to the CPUs kernel stack pointer +// PUBLIC static +// inline NEEDS [] +// vm_offset_t *kmem::kernel_esp() +// { +// return reinterpret_cast(& tss->esp0); +// } diff --git a/kernel/fiasco/src/test/wrappers/fake_kmem_alloc.cpp b/kernel/fiasco/src/test/wrappers/fake_kmem_alloc.cpp new file mode 100644 index 00000000..ff1cd71c --- /dev/null +++ b/kernel/fiasco/src/test/wrappers/fake_kmem_alloc.cpp @@ -0,0 +1,110 @@ +INTERFACE: + +#include // vm_offset_t & friends + +/** The kernel-memory allocator. + This allocator doesn't care about fragmentation or speed, so better + do not use it for fine-grained stuff. Instead, use a kmem_slab_t. + */ +class kmem_alloc +{ +public: + /** Zero-fill mode for page_alloc(). */ + enum zero_fill_t { no_zero_fill = 0, zero_fill, zero_map }; + +private: +// friend class jdb; + +// static vm_offset_t zero_page; + +}; + +IMPLEMENTATION: + +#include +#include +#include +#include +#include +#include "unix_aligned_alloc.h" + +// vm_offset_t kmem_alloc::zero_page; + +/** Allocate one page (with page alignment). + @return address of memory block. 0 if no memory available + */ +PUBLIC static +void * +kmem_alloc::page_alloc() // allocate a page at some kernel virtual addr +{ + return unix_aligned_alloc (PAGE_SIZE, PAGE_SIZE); +} + +/** Allocate one page (with page alignment) at specific virtual address. + This version of page_alloc() is equivalent to the simple + page_alloc(), except that a virtual address can be specified, and + that it can map in a shared zero-page that is unshared on write (in + thread_t::handle_page_fault()). + @param va kernel-virtual address at which to map the page + @param do_zero_fill specifies whether to zero-fill or zero-map the page + @return address of memory block. 0 if no memory available + @pre page_aligned(va) + */ +PUBLIC static +void * +kmem_alloc::page_alloc(vm_offset_t va, zero_fill_t do_zero_fill = no_zero_fill) +{ + void* page = unix_aligned_alloc (PAGE_SIZE, PAGE_SIZE); + if (page + && do_zero_fill != no_zero_fill) + { + memset (page, 0, PAGE_SIZE); + } + + return page; +} + +/** Free a page allocated with page_alloc(). + This function works for both version of page_alloc(). If the page + is at a user-specified virtual address, that virtual address is cleared + in the kernel's master page directory, and the TLB is flushed. + page_free() does not care about task page tables, though. + */ +/* XXX why do we flush the TLB even though we don't care about task + page tables? */ +PUBLIC static +void kmem_alloc::page_free(void *page) // free page at specified kva +{ + unix_aligned_free (page, PAGE_SIZE); +} + +/** Free page at given memory address. */ +// static +// void +// kmem_alloc::page_free_phys(void *page) +// { +// helping_lock_guard_t guard(&lmm_lock); +// lmm_free_page(&lmm, page); +// } + +/** Allocate some bytes from the kernel's free store. + @param size size of requested memory block + @return address memory block. 0 if no memory is available + */ +PUBLIC static +void *kmem_alloc::alloc(vm_size_t size) +{ + return malloc(size); +} + +/** Free a block of memory allocated with alloc() and return it + to the kernel's free store. + @param block address of memory block + @param size size of memory block as requested with alloc() + */ +PUBLIC static +void +kmem_alloc::free(void *block, vm_size_t size) +{ + ::free (block); +} diff --git a/kernel/fiasco/src/test/wrappers/simple_lock.cpp b/kernel/fiasco/src/test/wrappers/simple_lock.cpp new file mode 100644 index 00000000..7b4acda3 --- /dev/null +++ b/kernel/fiasco/src/test/wrappers/simple_lock.cpp @@ -0,0 +1,40 @@ +INTERFACE: + +#include "types.h" + +class Simple_lock +{ + Mword _lock; +}; + +IMPLEMENTATION: + +#include "atomic.h" + +PUBLIC +inline NEEDS ["atomic.h"] +bool Simple_lock::test_and_set() +{ + return smp_tas(&_lock); +} + +PUBLIC +inline +void Simple_lock::clear() +{ + _lock = 0; +} + +PUBLIC +inline +void Simple_lock::set() +{ + _lock = 1; +} + +PUBLIC +inline +bool Simple_lock::test() +{ + return _lock; +} diff --git a/kernel/fiasco/src/test/wrappers/symbols.c b/kernel/fiasco/src/test/wrappers/symbols.c new file mode 100644 index 00000000..a4096dd5 --- /dev/null +++ b/kernel/fiasco/src/test/wrappers/symbols.c @@ -0,0 +1,12 @@ +/* char _start, _edata, _end; */ +/* char _physmem_1; */ +/* char _tcbs_1; */ +/* char _iobitmap_1; */ + +asm (".global _unused1_1; _unused1_1 = 0xea000000"); +asm (".global _unused2_1; _unused2_1 = 0xea400000"); +/* _unused3_1; */ +asm (".global _unused4_io_1; _unused4_io_1 = 0xefc80000"); + +asm (".global _ipc_window0_1; _ipc_window0_1 = 0xee000000"); +asm (".global _ipc_window1_1; _ipc_window1_1 = 0xee800000"); diff --git a/kernel/fiasco/src/test/wrappers/unix_aligned_alloc.cpp b/kernel/fiasco/src/test/wrappers/unix_aligned_alloc.cpp new file mode 100644 index 00000000..9ce12fdc --- /dev/null +++ b/kernel/fiasco/src/test/wrappers/unix_aligned_alloc.cpp @@ -0,0 +1,43 @@ +INTERFACE: + +IMPLEMENTATION: + +#include +#include + +static std::map _free_map; + +void * +unix_aligned_alloc(unsigned long size, unsigned long alignment) +{ + unsigned current_size = size; + void* addr = malloc (current_size); + unsigned aligned_addr = aligned(reinterpret_cast(addr), alignment); + + while (aligned_addr + size + > reinterpret_cast(addr) + current_size) + { + current_size += 4096; + addr = realloc (addr, current_size); + aligned_addr = aligned(reinterpret_cast(addr), alignment); + } + + + _free_map [aligned_addr] = addr; + + return reinterpret_cast(aligned_addr); +} + +void +unix_aligned_free(void *block, unsigned long size) +{ + free (_free_map[reinterpret_cast(block)]); + _free_map.erase (reinterpret_cast(block)); +} + +static inline +unsigned +aligned (unsigned addr, unsigned alignment) +{ + return (addr + alignment - 1) & ~(alignment - 1); +} diff --git a/kernel/fiasco/src/test/wrappers/unix_slab.cpp b/kernel/fiasco/src/test/wrappers/unix_slab.cpp new file mode 100644 index 00000000..5ac2d32b --- /dev/null +++ b/kernel/fiasco/src/test/wrappers/unix_slab.cpp @@ -0,0 +1,53 @@ +INTERFACE: + +#include // size_t + +#include "slab_cache_anon.h" // slab_cache_anon + +class kmem_slab_t : public slab_cache_anon +{ +}; + +IMPLEMENTATION: + +#include + +#include "unix_aligned_alloc.h" + +// We only support slab size == PAGE_SIZE. +PUBLIC +kmem_slab_t::kmem_slab_t(unsigned elem_size, + unsigned alignment) + : slab_cache_anon(PAGE_SIZE, elem_size, alignment) +{ +} + +// We only support slab size == PAGE_SIZE. +PUBLIC +kmem_slab_t::kmem_slab_t(unsigned slab_size, + unsigned elem_size, + unsigned alignment) + : slab_cache_anon(slab_size, elem_size, alignment) +{ +} + +PUBLIC +kmem_slab_t::~kmem_slab_t() +{ + destroy(); +} + +// Callback functions called by our super class, slab_cache_anon, to +// allocate or free blocks + +virtual void * +kmem_slab_t::block_alloc(unsigned long size, unsigned long alignment) +{ + return unix_aligned_alloc (size, alignment); +} + +virtual void +kmem_slab_t::block_free(void *block, unsigned long size) +{ + unix_aligned_free (block, size); +} diff --git a/kernel/fiasco/src/types/amd64/types-arch.h b/kernel/fiasco/src/types/amd64/types-arch.h new file mode 100644 index 00000000..6676bf83 --- /dev/null +++ b/kernel/fiasco/src/types/amd64/types-arch.h @@ -0,0 +1,37 @@ +#ifndef TYPES_ARCH_H__ +#define TYPES_ARCH_H__ + +#define L4_PTR_ARG(a) ((Address)(a)) + +#define L4_PTR_FMT "%016lx" +#define L4_MWORD_FMT "%016lx" +#define L4_X64_FMT "%016llx" +#define L4_ADDR_INPUT_FMT "%16lx" +#define L4_FRAME_INPUT_FMT "%13lx" + +/// standard fixed-width types +typedef unsigned char Unsigned8; +typedef signed char Signed8; +typedef unsigned short Unsigned16; +typedef signed short Signed16; +typedef unsigned int Unsigned32; +typedef signed int Signed32; +typedef unsigned long long int Unsigned64; +typedef signed long long int Signed64; + +/// machine word +typedef signed long int Smword; +typedef unsigned long int Mword; + +enum { + MWORD_BITS = 64, + ARCH_PAGE_SHIFT = 12, +}; + +/// virtual or physical address in 32 bit mode (bootup) +/// (virtual or physical address) should be addr_t or something +typedef Mword Address; + +typedef Unsigned64 Cpu_time; + +#endif diff --git a/kernel/fiasco/src/types/arm/asm.h b/kernel/fiasco/src/types/arm/asm.h new file mode 100644 index 00000000..1cb40da5 --- /dev/null +++ b/kernel/fiasco/src/types/arm/asm.h @@ -0,0 +1,9 @@ + +#define SYMBOL_NAME(x) x +#define SYMBOL_NAME_LABEL(x) x##: +#define ALIGN .align 4,0x90 +#define ENTRY(x) \ + .globl SYMBOL_NAME(x); \ + ALIGN; \ + SYMBOL_NAME_LABEL(x) + diff --git a/kernel/fiasco/src/types/arm/types-arch.h b/kernel/fiasco/src/types/arm/types-arch.h new file mode 100644 index 00000000..3dd5bc1d --- /dev/null +++ b/kernel/fiasco/src/types/arm/types-arch.h @@ -0,0 +1,37 @@ +/* -*- c++ -*- */ +#ifndef TYPES_ARCH_H__ +#define TYPES_ARCH_H__ + +#define L4_PTR_ARG(a) ((Address)(a)) + +#define L4_PTR_FMT "%08lx" +#define L4_MWORD_FMT "%08lx" +#define L4_X64_FMT "%016llx" +#define L4_ADDR_INPUT_FMT "%8x" +#define L4_FRAME_INPUT_FMT "%5x" + +/// standard fixed-width types +typedef unsigned char Unsigned8; +typedef signed char Signed8; +typedef unsigned short Unsigned16; +typedef signed short Signed16; +typedef unsigned int Unsigned32; +typedef signed int Signed32; +typedef unsigned long long int Unsigned64; +typedef signed long long int Signed64; + +/// machine word +typedef signed long Smword; +typedef unsigned long Mword; + +enum { + MWORD_BITS = 32, + ARCH_PAGE_SHIFT = 12, +}; + +/// (virtual or physical address) should be addr_t or something +typedef unsigned long Address; + +typedef Unsigned64 Cpu_time; + +#endif // TYPES_ARCH_H__ diff --git a/kernel/fiasco/src/types/ia32/types-arch.h b/kernel/fiasco/src/types/ia32/types-arch.h new file mode 100644 index 00000000..4a01dfff --- /dev/null +++ b/kernel/fiasco/src/types/ia32/types-arch.h @@ -0,0 +1,37 @@ +#ifndef TYPES_ARCH_H__ +#define TYPES_ARCH_H__ + +#define L4_PTR_ARG(a) ((Address)(a)) + +#define L4_PTR_FMT "%08lx" +#define L4_MWORD_FMT "%08lx" +#define L4_X64_FMT "%016llx" +#define L4_ADDR_INPUT_FMT "%8x" +#define L4_FRAME_INPUT_FMT "%5x" + +/// standard fixed-width types +typedef unsigned char Unsigned8; +typedef signed char Signed8; +typedef unsigned short Unsigned16; +typedef signed short Signed16; +typedef unsigned int Unsigned32; +typedef signed int Signed32; +typedef unsigned long long int Unsigned64; +typedef signed long long int Signed64; + +/// machine word +typedef signed long int Smword; +typedef unsigned long int Mword; + +enum { + MWORD_BITS =32, + ARCH_PAGE_SHIFT = 12, +}; + +/// (virtual or physical address) should be addr_t or something +typedef unsigned long int Address; + +typedef Unsigned64 Cpu_time; + + +#endif diff --git a/kernel/fiasco/src/types/ppc32/types-arch.h b/kernel/fiasco/src/types/ppc32/types-arch.h new file mode 100644 index 00000000..31b42f5f --- /dev/null +++ b/kernel/fiasco/src/types/ppc32/types-arch.h @@ -0,0 +1,37 @@ +#ifndef TYPES_ARCH_H__ +#define TYPES_ARCH_H__ + +#define L4_PTR_ARG(a) ((Address)(a)) + +#define L4_PTR_FMT "%08lx" +#define L4_MWORD_FMT "%08lx" +#define L4_X64_FMT "%016llx" +#define L4_ADDR_INPUT_FMT "%8x" +#define L4_FRAME_INPUT_FMT "%5x" + +/// standard fixed-width types +typedef unsigned char Unsigned8; +typedef signed char Signed8; +typedef unsigned short Unsigned16; +typedef signed short Signed16; +typedef unsigned int Unsigned32; +typedef signed int Signed32; +typedef unsigned long long int Unsigned64; +typedef signed long long int Signed64; + +/// machine word +typedef signed long int Smword; +typedef unsigned long int Mword; + +enum { + MWORD_BITS = 32, + ARCH_PAGE_SHIFT = 12, +}; + +/// (virtual or physical address) should be addr_t or something +typedef unsigned long int Address; + +typedef Unsigned64 Cpu_time; + + +#endif diff --git a/kernel/fiasco/src/types/sparc/types-arch.h b/kernel/fiasco/src/types/sparc/types-arch.h new file mode 100644 index 00000000..f1752df7 --- /dev/null +++ b/kernel/fiasco/src/types/sparc/types-arch.h @@ -0,0 +1,37 @@ +#ifndef TYPES_ARCH_H__ +#define TYPES_ARCH_H__ + +#define L4_PTR_ARG(a) ((Address)(a)) + +#define L4_PTR_FMT "%08lx" +#define L4_MWORD_FMT "%08lx" +#define L4_X64_FMT "%016llx" +#define L4_ADDR_INPUT_FMT "%8x" +#define L4_FRAME_INPUT_FMT "%5x" + +/// standard fixed-width types +typedef unsigned char Unsigned8; +typedef signed char Signed8; +typedef unsigned short Unsigned16; +typedef signed short Signed16; +typedef unsigned int Unsigned32; +typedef signed int Signed32; +typedef unsigned long long int Unsigned64; +typedef signed long long int Signed64; + +/// machine word +typedef signed long int Smword; +typedef unsigned long int Mword; + +enum { + MWORD_BITS = 32, + ARCH_PAGE_SHIFT = 12, // XXX +}; + +/// (virtual or physical address) should be addr_t or something +typedef unsigned long int Address; + +typedef Unsigned64 Cpu_time; + + +#endif diff --git a/kernel/fiasco/src/types/types.h b/kernel/fiasco/src/types/types.h new file mode 100644 index 00000000..12e23447 --- /dev/null +++ b/kernel/fiasco/src/types/types.h @@ -0,0 +1,337 @@ +#ifndef TYPES_H__ +#define TYPES_H__ + +#include +#include "types-arch.h" +#include "std_macros.h" + +#ifdef __cplusplus + +template< typename a, typename b > inline +a nonull_static_cast( b p ) +{ + Address d = reinterpret_cast
+ (static_cast(reinterpret_cast(10))) - 10; + return reinterpret_cast( reinterpret_cast
(p) + d); +} + +template< typename T > +T access_once(T const &a) +{ return static_cast(a); } + +template< typename T > +class Static_object +{ +private: + // prohibit copies + Static_object(Static_object const &); + void operator = (Static_object const &); + + class O : public T + { + public: + void *operator new (size_t, void *p) throw() { return p; } + + O() : T() {} + + template + O(A1 const &a1) : T(a1) {} + + template + O(A1 const &a1, A2 const &a2) : T(a1, a2) {} + + template + O(A1 const &a1, A2 const &a2, A3 const &a3) : T(a1, a2, a3) {} + + template + O(A1 const &a1, A2 const &a2, A3 const &a3, A4 const &a4) : T(a1, a2, a3, a4) {} + + template + O(A1 const &a1, A2 const &a2, A3 const &a3, A4 const &a4, A5 const &a5) + : T(a1, a2, a3, a4, a5) {} + }; + +public: + Static_object() {} + + T *get() const + { + Address i = (Address)_i; + return reinterpret_cast(i); + } + + operator T * () const { return get(); } + T *operator -> () const { return get(); } + + T *construct() + { return new (_i) O(); } + + template + T *construct(A1 const &a1) + { return new (_i) O(a1); } + + template + T *construct(A1 const &a1, A2 const &a2) + { return new (_i) O(a1, a2); } + + template + T *construct(A1 const &a1, A2 const &a2, A3 const &a3) + { return new (_i) O(a1, a2, a3); } + + template + T *construct(A1 const &a1, A2 const &a2, A3 const &a3, A4 const &a4) + { return new (_i) O(a1, a2, a3, a4); } + + template + T *construct(A1 const &a1, A2 const &a2, A3 const &a3, A4 const &a4, A5 const &a5) + { return new (_i) O(a1, a2, a3, a4, a5); } + +private: + mutable char __attribute__((aligned(sizeof(Mword)*2))) _i[sizeof(O)]; +}; + + +template< typename VALUE, typename TARGET > +class Number +{ +public: + typedef VALUE Value; + typedef TARGET Target; + struct Type_conversion_error; + +protected: + Number() {} + explicit Number(Value v) : _v(v) {} + +public: + + static Target create(Value v) + { return Target(v); } + + Target operator = (Target o) + { _v = o._v; return *static_cast(this); } + + Value value() const { return _v; } + Value value() const volatile { return _v; } + void set_value(Value v) { _v = v; } + + bool operator < (Target const &o) const { return _v < o._v; } + bool operator > (Target const &o) const { return _v > o._v; } + bool operator <= (Target const &o) const { return _v <= o._v; } + bool operator >= (Target const &o) const { return _v >= o._v; } + bool operator == (Target const &o) const { return _v == o._v; } + bool operator != (Target const &o) const { return _v != o._v; } + + operator Type_conversion_error const * () const + { return (Type_conversion_error const *)_v; } + + Target operator | (Target const &o) const + { return Target(_v | o._v); } + + Target operator & (Target const &o) const + { return Target(_v & o._v); } + + Target operator + (Target const &o) const + { return Target(_v + o._v); } + + Target operator - (Target const &o) const + { return Target(_v - o._v); } + + Target operator << (unsigned long s) const + { return Target(_v << s); } + + Target operator >> (unsigned long s) const + { return Target(_v >> s); } + + void operator += (Target const &o) { _v += o._v; } + void operator -= (Target const &o) { _v -= o._v; } + void operator <<= (unsigned long s) { _v <<= s; } + void operator >>= (unsigned long s) { _v >>= s; } + + Target operator ++ () { return Target(++_v); } + Target operator ++ (int) { return Target(_v++); } + + Target operator -- () { return Target(--_v); } + Target operator -- (int) { return Target(_v--); } + + Target trunc(Target const &size) const + { return Target(_v & ~(size._v - 1)); } + + Target offset(Target const &size) const + { return Target(_v & (size._v - 1)); } + + static Target from_shift(unsigned char shift) + { + if (shift >= (int)sizeof(Value) * 8) + return Target(Value(1) << Value((sizeof(Value) * 8 - 1))); + return Target(Value(1) << Value(shift)); + } + +protected: + Value _v; +}; + +template< int SHIFT > +class Page_addr : public Number > +{ +private: + typedef Number > B; + + template< int T > + class Itt + {}; + + template< int SH > + Address __shift(Address x, Itt) { return x << SH; } + + template< int SH > + Address __shift(Address x, Itt) { return x >> (-SH); } + +public: + enum { Shift = SHIFT }; + + template< int OSHIFT > + Page_addr(Page_addr o) + : B(__shift(o.value(), Itt<(OSHIFT < Shift)>())) + {} + + explicit Page_addr(Address a) : B(a) {} + + Page_addr(Page_addr const volatile &o) : B(o.value()) {} + Page_addr(Page_addr const &o) : B(o.value()) {} + + Page_addr() {} +}; + +class Virt_addr : public Page_addr +{ +public: + template< int OSHIFT > + Virt_addr(Page_addr o) : Page_addr(o) {} + + explicit Virt_addr(unsigned int a) : Page_addr(a) {} + explicit Virt_addr(int a) : Page_addr(a) {} + explicit Virt_addr(long int a) : Page_addr(a) {} + explicit Virt_addr(unsigned long a) : Page_addr(a) {} + Virt_addr(void *a) : Page_addr(Address(a)) {} + + Virt_addr() {} +}; + +typedef Page_addr Virt_size; + +typedef Page_addr<0> Page_number; +typedef Page_number Page_count; + +template +struct Simple_ptr_policy +{ + typedef T &Deref_type; + typedef T *Ptr_type; + typedef T *Member_type; + typedef T *Storage_type; + + static void init(Storage_type const &) {} + static void init(Storage_type &d, Storage_type const &s) { d = s; } + static void copy(Storage_type &d, Storage_type const &s) { d = s; } + static void destroy(Storage_type const &) {} + static Deref_type deref(Storage_type p) { return *p; } + static Member_type member(Storage_type p) { return p; } + static Ptr_type ptr(Storage_type p) { return p; } +}; + +template<> +struct Simple_ptr_policy +{ + typedef void Deref_type; + typedef void *Ptr_type; + typedef void Member_type; + typedef void *Storage_type; + + static void init(Storage_type const &) {} + static void init(Storage_type &d, Storage_type const &s) { d = s; } + static void copy(Storage_type &d, Storage_type const &s) { d = s; } + static void destroy(Storage_type const &) {} + static Deref_type deref(Storage_type p); + static Member_type member(Storage_type p); + static Ptr_type ptr(Storage_type p) { return p; } +}; + + +template class Policy = Simple_ptr_policy, + typename Discriminator = int> +class Smart_ptr +{ +private: + struct Null_check_type; +public: + typedef typename Policy::Deref_type Deref_type; + typedef typename Policy::Ptr_type Ptr_type; + typedef typename Policy::Member_type Member_type; + typedef typename Policy::Storage_type Storage_type; + + template class B, typename C> + friend class Smart_ptr; + +protected: + Storage_type _p; + +public: + Smart_ptr() + { Policy::init(_p); } + + explicit Smart_ptr(T *p) + { Policy::init(_p, p); } + + Smart_ptr(Smart_ptr const &o) + { Policy::copy(_p, o._p); } + + template< typename RHT > + Smart_ptr(Smart_ptr const &o) + { Policy::copy(_p, o._p); } + + ~Smart_ptr() + { Policy::destroy(_p); } + + Smart_ptr operator = (Smart_ptr const &o) + { + if (this == &o) + return *this; + + Policy::destroy(_p); + Policy::copy(_p, o._p); + return *this; + } + + Deref_type operator * () const + { return Policy::deref(_p); } + + Member_type operator -> () const + { return Policy::member(_p); } + + Ptr_type get() const + { return Policy::ptr(_p); } + + operator Null_check_type const * () const + { return reinterpret_cast(Policy::ptr(_p)); } +}; + +enum User_ptr_discr {}; + +template +struct User +{ + typedef Smart_ptr Ptr; +}; +#endif + +/// standard size type +///typedef mword_t size_t; +///typedef signed int ssize_t; + +/// momentary only used in UX since there the kernel has a different +/// address space than user mode applications +enum Address_type { ADDR_KERNEL = 0, ADDR_USER = 1, ADDR_UNKNOWN = 2 }; + +#endif // TYPES_H__ + diff --git a/kernel/fiasco/src/types/ux/types-arch.h b/kernel/fiasco/src/types/ux/types-arch.h new file mode 100644 index 00000000..d522b4f0 --- /dev/null +++ b/kernel/fiasco/src/types/ux/types-arch.h @@ -0,0 +1,37 @@ +/* -*- c++ -*- */ +#ifndef TYPES_ARCH_H__ +#define TYPES_ARCH_H__ + +#define L4_PTR_ARG(a) ((Address)(a)) + +#define L4_PTR_FMT "%08lx" +#define L4_MWORD_FMT "%08lx" +#define L4_X64_FMT "%016llx" +#define L4_ADDR_INPUT_FMT "%8x" +#define L4_FRAME_INPUT_FMT "%5x" + +/// standard fixed-width types +typedef unsigned char Unsigned8; +typedef signed char Signed8; +typedef unsigned short Unsigned16; +typedef signed short Signed16; +typedef unsigned int Unsigned32; +typedef signed int Signed32; +typedef unsigned long long int Unsigned64; +typedef signed long long int Signed64; + +/// machine word +typedef signed long int Smword; +typedef unsigned long int Mword; + +enum { + MWORD_BITS = 32, + ARCH_PAGE_SHIFT = 12, +}; + +/// (virtual or physical address) should be addr_t or something +typedef unsigned long int Address; + +typedef Unsigned64 Cpu_time; + +#endif diff --git a/kernel/fiasco/tool/backtrace b/kernel/fiasco/tool/backtrace new file mode 100755 index 00000000..6c3bd4d0 --- /dev/null +++ b/kernel/fiasco/tool/backtrace @@ -0,0 +1,136 @@ +#! /usr/bin/perl -W + +use Math::BigInt; +use strict; + +my %sym_tab = (new Math::BigInt(0) => "ERRRRRRROR"); +my $sections = "BdDdTtVvWwuU"; +my %sec_tab; + +my %test; + +sub as_hex($) +{ + my $i = shift; + my $h = substr $i->as_hex(), 2; + $h = ('0' x (16-length($h))) . $h; + return $h; +} + +if (!defined $ARGV[0]) +{ + print "$0 image(s)\n"; + print " input is read from stdin\n"; + exit 1; +} + +my $nm = 'nm'; +$nm = "$ENV{'SYSTEM_TARGET'}$nm" if defined $ENV{"SYSTEM_TARGET"}; +$nm = 'arm-softfloat-elf-nm' if !(system("file -L $ARGV[0] | grep -qw ARM") >> 8); + +while (@ARGV) + { + my $img = shift; + foreach my $l (split('\n', qx{$nm $img | c++filt})) + { + if ($l =~ /^([0-9a-fA-F]*)\s+([$sections])\s+(.*)$/) + { + my ($addr, $sec, $sym) = (new Math::BigInt("0x$1"), $2, $3); + if (defined $addr && ref $addr && !$addr->is_nan()) + { + $sym_tab{as_hex($addr)} = $sym; + $sec_tab{as_hex($addr)} = $sec; + } + } + } + } +my @sorted_sym_tab_keys = sort keys %sym_tab; +my $min_addr = $sorted_sym_tab_keys[0]; +my $max_addr = $sorted_sym_tab_keys[@sorted_sym_tab_keys - 1]; + +print "Scanning image done, proceed.\n"; + +sub find_sym($) +{ + my $addr = as_hex(shift); + my $hit = '0'; + + return new Math::BigInt(0) + if $addr lt $min_addr or $addr gt $max_addr; + + foreach my $s (@sorted_sym_tab_keys) + { + if ($s gt $addr) + { + return new Math::BigInt("0x$hit"); + } + + $hit = $s; + } + + return new Math::BigInt(0); +} + +sub print_func($) +{ + my $addr = new Math::BigInt("0x".shift); + my $hit = find_sym($addr); + my $offset = $addr-$hit; + my $o = $hit->as_hex(); + + return unless $hit; + + printf " %s %30s(%s) + %6s = %s\n", + $addr->as_hex(), $sym_tab{as_hex($hit)}, $sec_tab{as_hex($hit)}, + $offset->as_hex(), $hit->as_hex(); +} + + +my $last_f = 0; +while (<>) +{ + if (/^\s+#(\d+)\s+([0-9a-f]+)\s+([0-9a-f]+)/i) # fiasco bt without debuginfo + { + my $fn = $1; + my $stack = new Math::BigInt("0x$2"); + my $addr = $3; + my $fsize = $stack - $last_f; + + $last_f = $stack; + printf "%2d %s ", $fn, $stack->as_hex(); + if ($fsize >= 0 && $fsize <= 2000) + { + printf "%4d", $fsize; + } else { + printf "...."; + } + print_func($addr); + } + elsif (/^(?:.*?\|)?\s*(0x)?([0-9a-f]+)\s*$/i) # simple figure + { + print_func($2); + } + elsif (/^[\da-f]+:([\d\sa-f]+)$/i) # fiasco memory dump (mostly user stack) + { + my $l = $1; + for my $addr (split(/\s+/, $l)) + { + print_func($addr); + } + } + elsif (/^\s*[\da-f]+\s+([\d\sa-f]+)\s*$/i) # fiasco tcb view stack + { + my $l = $1; + for my $val (split(/\s+/, $l)) + { + next if $val eq '35353535'; # stack poison + if ($val =~ /^f.......(?:........)?$/i) { + print_func($val); + } else { + print " 0x$val ... value ...\n"; + } + } + } +} + + diff --git a/kernel/fiasco/tool/checkinitcalls b/kernel/fiasco/tool/checkinitcalls new file mode 100755 index 00000000..f2d8f06f --- /dev/null +++ b/kernel/fiasco/tool/checkinitcalls @@ -0,0 +1,153 @@ +#!/usr/bin/perl -w + +# we use BigInts for handling 64-bit values on IA32 systems + +use strict; +use Getopt::Long; +use Pod::Usage; +use Math::BigInt; + +my $target = ''; +my $sym_objdump = 'nm -nC'; +my $dis_objdump = 'objdump -drlC'; +my $hdr_objdump = 'objdump -h'; +my $start_symbol = '_initcall_start'; +my $end_symbol = '_initcall_end'; +my $kernel = 'fiasco.image'; +my $error = 0; +my $werror = 0; +my @Wswitch = (); +my @ignore_funcs = (); + +my $opt = { "kernel" => \$kernel, + "start-symbol" => \$start_symbol, + "end-symbol" => \$end_symbol, + "W" => \@Wswitch, + "ignore-function" => \@ignore_funcs, + "target" => \$target }; + +Getopt::Long::Configure ('bundling','no_ignore_case','auto_abbrev'); + +GetOptions( $opt, + "help|?|h", + "man|m", + "W=s@", + "start-symbol=s", + "end-symbol=s", + "ignore-function=s@", + "kernel|k=s", + "target|t=s", + ); + +sub have_warn_opt { + my $opt = shift @_; + my @gr = grep /$opt/, @Wswitch; +# print "W: ".join(" ",@gr)."\n"; + return scalar @gr; +} + +$dis_objdump = $target.$dis_objdump; +$hdr_objdump = $target.$hdr_objdump; +$sym_objdump = $target.$sym_objdump; + +$werror = 1 if have_warn_opt("error"); +if (!have_warn_opt("static-construction")) { + push @ignore_funcs, ("(_Z41)?__static_initialization_and_destruction_0(ii\\.clone\\.\\d+)?"); + push @ignore_funcs, ("_GLOBAL__(sub_)?I\\.\\S*"); + push @ignore_funcs, ("_GLOBAL__sub_I__Z\\S*"); + push @ignore_funcs, ("global constructors keyed to \\S*"); + push @ignore_funcs, ("T\\.\\d+"); +} + +my $ignore_funcs = join("|",@ignore_funcs); + +#print "Ignore: $ignore_funcs\n"; + +my @symbols = split($/,qx{$sym_objdump $kernel}); + +my @start = grep /^[0-9a-fA-F]+\s+[A-Z]\s+$start_symbol\s*$/, @symbols; +my @end = grep /^[0-9a-fA-F]+\s+[A-Z]\s+$end_symbol\s*$/, @symbols; + +if(! defined $start[0] || ! defined $end[0]) { + die 'start ('.$start_symbol.') or end ('.$end_symbol.') symbol not found!'; +} + +my $start = $start[0]; +my $end = $end[0]; + +$start =~ s/^([0-9a-fA-F]+).*$/$1/; +$end =~ s/^([0-9a-fA-F]+).*$/$1/; + +#print "start of init area: $start\n"; +#print "end if init area : $end\n"; + +$start = Math::BigInt->new("0x".$start); +$end = Math::BigInt->new("0x".$end); + +my %init_syms; + +while($_ = shift @symbols) { + if(/^([0-9a-fA-F]+)\s+[A-Z]\s+(\S+)/) { + my $addr = Math::BigInt->new("0x".$1); + my $symbol = $2; + if ( $symbol ne $start_symbol + && $symbol ne $end_symbol + && $addr->bcmp($start) >= 0 + && $addr->bcmp($end) < 0) { + $init_syms{$symbol} = 1; +# print "$symbol\n"; + } + } +} + +while($_ = shift @ARGV) { + my $file = $_; + + # search for sections .text.* in object file + my @sections = split $/, qx{$hdr_objdump $file}; + my $text_sections = ''; + foreach $_ (@sections) { + if (/^\s*[0-9]+\s(\.text[.0-9a-zA-Z_]*)/) { + $text_sections .= " -j ".$1; + } + } + + # disassemble object file + my @dump = split $/, qx{$dis_objdump $text_sections $file}; + + my $source; + my $function; + my $warn; + if ($werror) { + $warn = "error"; + } else { + $warn = "warning"; + } + + foreach $_ (@dump) { + if (/^(\S+:[0-9]+)\s*$/) { + $source = $1; + next; + } + if (/^([0-9a-fA-F]+)\s+<(.*)>:$/) { + $function = $2; + next; + } + if (/^\s*([0-9a-fA-F]+):\s+R_\S+\s+(\S+\(.*\))\S*\s*$/) { + my $sym = $2; + if ( defined $function + && $function !~ /^($ignore_funcs)(\(.*\))?$/ + && defined $init_syms{$sym}) { + $source = $file unless defined $source; + (my $func_pretty = $function) =~ s/_GLOBAL__I\.\d+_//; + $func_pretty = `echo '$func_pretty' | ${target}c++filt`; + chomp $func_pretty; + print STDERR "$source: $warn: $func_pretty uses initcall ($sym) from normal text section\n"; + $error++ if $werror; + } + next; + } + } +} + +exit(1) if $error; diff --git a/kernel/fiasco/tool/circular b/kernel/fiasco/tool/circular new file mode 100755 index 00000000..db6eeaeb --- /dev/null +++ b/kernel/fiasco/tool/circular @@ -0,0 +1,48 @@ +#!/usr/bin/perl +$, = ' '; # set output field separator +$\ = "\n"; # set output record separator + +$doit = 0; # Is there a circular dep. with the current module? +$modnameseen = 0; # Have we seen the module name yet? +$deps = 0; + +print "\n---\n"; + +line: while (<>) { + chomp; # strip record separator + if (/^[a-z]/) { + $modnameseen = 1; + $iam = $_; + + maybeprintmodname() if $doit; + + next; + } + + if (/^---$/) { + print "\n---\n" if $doit; + + $doit = 0; + $iamprinted = 0; + $modnameseen = 0; + } + + s| \*$|| || next; + + $doit = 1; + if ($modnameseen) { + maybeprintmodname(); + $deps++; + } + + print $_; +} + +print "TOTAL CIRCULAR DEPS:\n$deps"; + +###################################################################### + +sub maybeprintmodname { + print "$iam" if ! $iamprinted; + $iamprinted = 1; +} diff --git a/kernel/fiasco/tool/gen_kconfig b/kernel/fiasco/tool/gen_kconfig new file mode 100755 index 00000000..e50cd291 --- /dev/null +++ b/kernel/fiasco/tool/gen_kconfig @@ -0,0 +1,67 @@ +#! /usr/bin/perl -W + +use strict; + +my $kconfig_src_file = shift; +my $kconfig_obj_file = shift; + +my %pfs; +foreach my $f (@ARGV) { + my $bsp_name; + $bsp_name = $1 if $f =~ /\/bsp\/([^\/]+)\//; + open(X, $f) || die "Cannot open $f: $!"; + my $pf; + my $pfdescr; + my $pfcan; + my $pfdep; + while ($_=) { + $pf = $1 if /^\s*\#\s*PF:\s*(\S+)/; + $pfdescr = $1 if /^\s*\#\s*PFDESCR:\s*(.+)/; + $pfcan = $1 if /^\s*\#\s*PFCAN:\s*(.+)/; + $pfdep = $1 if /^\s*\#\s*PFDEPENDS:\s*(.+)/; + } + $pfs{$pf}{file} = $f; + $pfs{$pf}{desc} = $pfdescr; + $pfs{$pf}{can} = $pfcan; + $pfs{$pf}{dep} = $pfdep; + $pfs{$pf}{name} = $bsp_name; + close X; +} +open(IN, "$kconfig_src_file") || die "Cannot open $kconfig_src_file: $!"; +open(OUT, ">$kconfig_obj_file") || die "Cannot open $kconfig_obj_file: $!"; +while ($_=) { + print OUT; + if (/^\s*\#\s*PF_INCLUDE\W/) { + foreach my $i (keys %pfs) { + print OUT "if PF_$i\n"; + if (defined $pfs{$i}{name}) { + print OUT "config BSP_NAME\n string\n"; + print OUT " depends on PF_$i\n"; + print OUT " default \"$pfs{$i}{name}\"\n"; + } + print OUT "source \"$pfs{$i}{file}\"\nendif\n"; + } + } + if (/^\s*\#\s*PF_CHOICE\W/) { + foreach my $i (keys %pfs) { + if (defined $pfs{$i}{desc}) { + print OUT "config PF_$i\n bool \"$pfs{$i}{desc}\"\n"; + } else { + print OUT "config PF_$i\n bool \"$i Platform\"\n"; + } + if (defined $pfs{$i}{dep}) { + foreach my $c (split(/\s+/, $pfs{$i}{dep})) { + print OUT " depends on $c\n"; + } + } + if (defined $pfs{$i}{can}) { + foreach my $c (split(/\s+/, $pfs{$i}{can})) { + print OUT " select $c\n"; + } + } + print OUT "\n"; + } + } +} +close IN; +close OUT; diff --git a/kernel/fiasco/tool/gendotdeps b/kernel/fiasco/tool/gendotdeps new file mode 100755 index 00000000..4d9e679c --- /dev/null +++ b/kernel/fiasco/tool/gendotdeps @@ -0,0 +1,630 @@ +#!/usr/bin/perl -w + +use strict; +use Getopt::Long; +use Pod::Usage; + +my %styles = ( + 'node-normal' => { style=>'solid', fillcolor=>'lightgrey' }, + 'node-included' => { style=>'filled', fillcolor=>'PaleGreen' }, + 'edge-normal' => { color=>'black' }, + 'edge-circle' => { color=>'red' }, +); + + +my $finput = *STDIN{IO}; +my $output = *STDOUT{IO}; +my $trivial = 0; +my $unused = 0; +my $verbose = 0; +my $use_units = 0; + +my $target_bl = ""; +my $source_bl = ""; + +my $opt = { "verbose" => \$verbose, + "trivial" => \$trivial, + "unused" => \$unused, + "units" => \$use_units, + }; + +Getopt::Long::Configure ('bundling','no_ignore_case','auto_abbrev'); + +GetOptions( $opt, + "help|?|h", + "man|m", + "verbose|v+", + "trivial|t:i", + "unused|u:i", + "output|o=s", + "blacklist|b=s", + "sysincludes|s", + "nosysincludes", + "units|U", + "includepath|I=s@", + "vpath=s@", + "descend|d", + "fancy|f", + "pre-parts|E=s", + "verbose-drop|D" + ); + +my %parts = ( '{' => '(', + '}' => ')', + ',' => '||', + '-' => '&&', + '|' => '|', + '&' => '&', + '(' => '(', + ')' => ')', + '!' => '!'); + +if ($$opt{'pre-parts'} ne '') { + foreach my $p (split(' ',$$opt{'pre-parts'})) + { + $parts{$p} = '1'; + } +} + +# the next two lines may be omitted if the trivial|t:1 syntax works +$trivial = 1 unless defined $trivial; +$unused = 1 unless defined $unused; +$$opt{sysincludes} = 1 unless defined $$opt{sysincludes}; +$$opt{sysincludes} = 0 if $$opt{nosysincludes}; + +pod2usage(1) if defined $$opt{help}; +pod2usage(-exitstatus => 0, -verbose => 2, -output=>\*STDOUT) if defined $$opt{man}; + +if( defined $$opt{output} ) { + open( $output, ">$$opt{output}" ) || die "can't open output file: '$$opt{output}' - $!!"; +} + +if( defined $$opt{blacklist} ) { + open( I, "$$opt{blacklist}") || die "can't open black list file: '$$opt{blacklist}' - $!!"; + while() { + chomp; + next if (/^\#/); + if (/^:(.*)$/) { + $target_bl .= $1." "; + } + if (/^->(.*)$/) { + $source_bl .= $1." "; + } + if (/^\*(.*)$/) { + $target_bl .= $1." "; + $source_bl .= $1." "; + } + } + + $target_bl =~ s/\s+/|/g; + $source_bl =~ s/\s+/|/g; +} + +my $args = join(' ',@ARGV); + +if ( $args =~ s/\s*(\S+)// ) { + open( $finput, "$1" ) || die "can't open input file: '$1' - $!!"; +} + +my %all_deps; +my %modules; +my %units; +my %module_struct; + +read_input(); +#print STDERR "READ:-----------------------------------------------\n"; +#list_modules(); +gen_all_deps(); +#print STDERR "GENALL:---------------------------------------------\n"; +#list_modules(); +remove_black_listed(); +#print STDERR "BL:-------------------------------------------------\n"; +#list_modules(); + +while($unused-- && remove_unused()) {} +while($trivial-- && remove_trivial()) {} + +#print STDERR "UT:-------------------------------------------------\n"; +#list_modules(); + +remove_isolated(); + +print_dot(); +close $output; + + +#sub list_modules { +# print STDERR join('; ',sort keys %{$modules{"thread"}})."\n"; +#} + + +sub module_name { + my ($filename) = @_; + $filename = unit_name($filename); + $filename =~ s|^([^-]*).*$|$1|; + return $filename; +} + +sub unit_name { + my ($filename) = @_; + $filename =~ s|.*/(\S+)|$1|; # remove path + $filename =~ s|(\S+)\..*|$1|; # remove extension + $filename =~ s|_i$||; # cpp remove private include ext + return $filename; +} + +#-------------------------------------------------------------------- +sub find_file($) { + my $file = shift; + # absolute path + return $file if $file =~ /^\//; + + # try to find the source cpp file in the vpath + if ($file =~ /^(.*)\.h$/) { + my $cpp = $1.'.cpp'; + foreach my $dir (@{$$opt{"vpath"}}) { + foreach my $sdir (split (':', $dir)) { + return $sdir.'/'.$cpp if -f $sdir.'/'.$cpp; + } + } + } + + # else try to find file in search path + foreach my $sdir (@{$$opt{"includepath"}},'.') { + return $sdir.'/'.$file if -f $sdir.'/'.$file; + } + + print STDERR "file '$file' not found\n"; + return undef; +} + +sub match_e_opt($) +{ + my $tag = shift; + + return 1 if $$opt{'pre-parts'} eq ''; + + my $cp = ''; + my $t = '\(\)&|,\{\}!-'; + + while ($tag =~ /^\s*([$t]|(?:[^\s$t]+))\s*(.*?)$/) + { + my $r = $parts{$1}; + $cp .= defined $r ? $r : 0; + $tag = $2; + } + + my $match = eval $cp; + + if (!defined $match) + { + die "${ARGV}: error: syntax error in tag '$tag'\n"; + } + + if (($verbose>1 || $$opt{'verbose-drop'}) && !$match) + { + print STDERR "Drop SECTION: [$tag]\n"; + } + + return $match; +} + +sub add_unit($$) { + my ($module, $unit) = @_; + if (!defined $modules{$module}) { + $modules{$module} = { + name => $module, + units => {}, + deps => {}, + }; + } + my $c_module = $modules{$module}; + + if (!defined $c_module->{units}->{$unit}) { + $c_module->{units}->{$unit} = { + name => $unit, + parent => $c_module, + deps => {} + }; + $units{$unit} = $c_module->{units}->{$unit}; + } + + my $c_unit = $c_module->{units}->{$unit}; + return ($c_module, $c_unit); +} + +sub read_input { + my $incregexp = "[\\\"<](\\S+)[\\\">]"; + $incregexp = "\\\"(\\S+)\\\"" if $$opt{sysincludes} == 0; + my @input = (); + while(<$finput>) { + push @input ,(split('\s',$_)); + } + + my %files = (); + + foreach my $f (@input) { + $files{$f} = 1; + } + + input_file: foreach my $inp (@input) { + + my $cpp_module = 0; + + open (C, $inp) || die "can't open input file: '$inp' - $!!"; + + print STDERR "read: $inp" if $verbose>1; + my $module = module_name($inp); + my $unit = unit_name($inp); + + + $units{$unit} = {} if !defined $units{$unit}; + my ($c_module, $c_unit) = add_unit($module, $unit); + + my @includes; + my $implname; + my $skip_to_next_section = 0; + my $current_part = ''; + LINE: while() { + chomp; + if (/^(?:INTERFACE|IMPLEMENTATION)\s*(?:\[\s*(.*)\s*\])?\s*:/) + { + $skip_to_next_section = 0; + $cpp_module = 1; + if (defined $1) { + $current_part = $1; + if (!match_e_opt($current_part)) { + $skip_to_next_section = 1; + next LINE; + } + } + } elsif ($skip_to_next_section) { + next LINE; + } + if (/^\#include\s+$incregexp.*$/ && $1 !~ /_i$/ ) { + my $inc = $1; + my $incname = find_file($1); + next input_file if !defined $incname; + my $module_name = module_name($incname); + next LINE if $module_name eq $module; + + $inc =~ s|.h$||; + $inc =~ s|[/.]|_|g; + my ($new_mod, $new_unit) = add_unit($module_name, unit_name($incname)); + $c_unit->{deps}->{$module_name} = $new_mod; + $c_module->{deps}->{$module_name} = $new_mod; + if ($$opt{descend} && !defined $files{$incname}) { + $files{$incname} = 2; + $new_mod->{level} = 2; + push @input, ($incname); + } + } + $cpp_module = 1 if /^(INTERFACE|IMPLEMENTATION).*:/; + if (/^IMPLEMENTATION\s*\[(\S+)\].*$/) { + $implname = $1; + } + } + + $module =~ s|[/.]|_|g; + + if (! defined $implname ) { + $implname = "**generic**"; + push @{$module_struct{$module}{sub}}, ('"'.$module.'"'); + } else { + $module =~ s/-($implname)$//; + push @{$module_struct{$module}{sub}}, ('"'.$module.'-'.$implname.'"'); + } + + print STDERR "[module=$module, implementation=$implname]\n" if $verbose>1; + + @includes = grep {!/^$module$/} @includes; # remove self references + if (! defined $modules{$module}) { + $modules{$module} = {}; + } + #$module_struct{$module}{descend} = $descend; + $module_struct{$module}{cpp} = $cpp_module; + foreach my $inc (@includes) { + ${${%{$modules{$module}}}{$inc}}{$implname} = 1; + } + + close C; + } + + close $finput; +} + +#----------------------------------------------------- +sub gen_all_deps { + %all_deps = (); + my $bunch = \%modules; + $bunch = \%units if $use_units; + foreach my $module (values %$bunch) { + $all_deps{$module->{name}} = finddeps ($module, {}); + } +} + +#----------------------------------------------------- +sub remove_black_listed { + print STDERR "remove blacklisted: " if $verbose>0; + foreach my $mod (keys %modules) { + if( $mod =~ /^($target_bl)$/ && !defined $all_deps{$mod}->{$mod}) { + print STDERR "$mod " if $verbose>0; + delete $modules{$mod}; + delete $all_deps{$mod}; + next; + } + foreach my $calling (keys %{$modules{$mod}}) { + if( $calling =~ /^($source_bl)$/ && !defined $all_deps{$calling}->{$calling}) { + delete $modules{$mod}->{deps}->{$calling}; + print STDERR "->$calling<- " if $verbose>2; + } + } + } + + print STDERR "\n" if $verbose>0; + +} + +sub remove_isolated { + print STDERR "remove isolated: " if $verbose>0; + modu: foreach my $mod (keys %modules) { + next if (scalar (keys %{$modules{$mod}->{deps}})) > 0; + foreach my $calling (keys %modules) { + next modu if defined $modules{$calling}->{deps}->{$mod}; + } + delete $modules{$mod}; + delete $all_deps{$mod}; + print STDERR "$mod " if $verbose >0; + } + print STDERR "\n" if $verbose>0; +} + +#----------------------------------------------------- +sub remove_trivial { + my $count = 0; + print STDERR "remove trivial: " if $verbose>0; + foreach my $mod (keys %modules) { + if (scalar keys %{$modules{$mod}->{deps}} == 0) { + $count++; + delete $modules{$mod}; + delete $all_deps{$mod}; + print STDERR "$mod " if $verbose>0; + foreach my $m (keys %modules) { + if (defined $%{$modules{$m}}{$mod}) { + delete $%{$modules{$m}}{$mod}; + } + } + } + } + print STDERR "\n" if $verbose>0; + return $count; +} + +#------------------------------------------------------------- +sub remove_unused { + my $count = 0; + print STDERR "remove unused: " if $verbose>0; + foreach my $mod (keys %modules) { + foreach my $calling (keys %modules) { + goto used if defined $modules{$calling}->{deps}->{$mod}; + } + print STDERR "$mod " if $verbose>0; + delete $modules{$mod}; + delete $all_deps{$mod}; + $count++; + used: + } + print STDERR "\n" if $verbose>0; + return $count; +} + + + +sub specify_node($) +{ + my $n = shift; + if ($$opt{fancy}) { + my $style = $styles{'node-normal'}; + $style = $styles{'node-included'} if $n->{level}; + print " node [style=$style->{style}, fillcolor=$style->{fillcolor}]; " . + "\"$n->{name}\";\n"; + } + #elsif ( $$m{cpp} ) { +# print " node [style=filled, fillcolor=LightSkyBlue]; \"$mod\";\n"; +# } +} + +sub edge($$) +{ + my ($f, $t) = @_; + my $t_n = $t->{name}; # the unit names + my $f_n = $f->{name}; + my $f_mn = $f_n; + my $t_mn = $t_n; + $f_mn = $f->{parent}->{name} if defined $f->{parent}; + $t_mn = $t->{parent}->{name} if defined $t->{parent}; + + my $style = $styles{'edge-normal'}; + my @label =(); + + if (defined $all_deps{$t_n}->{$f_mn}) { + $style = $styles{'edge-circle'}; + if (!$use_units) { + foreach my $u (values %{$f->{units}}) { + if (defined $u->{deps}->{$t_n}) { + push @label, ($u->{name}); + } + } + } + } + + my $label = join(", ", (@label)); + + print " \"$f_n\" -> \"$t_n\" [color=$style->{color}, label=\"$label\"];\n"; +} + +#------------------------------------------------------------- +sub print_dot { + + # + # Print dependencies per module + # + + print "digraph G {\n"; + print " compound=true;\n"; + + foreach my $val (values %modules) { + specify_node($val); + } + + if ($use_units) { + foreach my $module (values %modules) { + foreach my $unit (values %{$module->{units}}) { + foreach my $calling (values %{$unit->{deps}}) { + # skip removed nodes + next if !defined $modules{$calling->{name}}; + foreach my $tunit (values %{$calling->{units}}) { + edge($unit, $tunit); + } + } + } + } + } else { + foreach my $module (values %modules) { + foreach my $calling (values %{$module->{deps}}) { + # skip removed nodes + next if !defined $modules{$calling->{name}}; + edge($module, $calling); + } + } + } + + print "}\n"; +} + +#------------------------------------------------------------- +sub finddeps { + my ($module, $traversed) = @_; + #print STDERR "finddeps $module\n"; + return {} if defined $traversed->{$module->{name}}; + $traversed->{$module->{name}} = 1; + + my @deps = values %{$module->{deps}}; + + my $alldeps = {}; + + foreach my $dep (@deps) { + $alldeps->{$dep->{name}} = 1; + foreach my $u (keys %{finddeps ($dep, $traversed)}) { + $alldeps->{$u} = 1; + } + } + + return $alldeps; +} + +__END__ + +=head1 NAME + +gendotdeps - generate module (.cpp) dependencies in dot format. + +=head1 SYNOPSIS + +gendotdeps [options] [input_file] + + Options: + --blacklist=file, -b use file as modules black list + --descend, -d descend into included files + --fancy, -f use fancy colors + --help, -h show brief help message + --includepath, -I specify an include path for '--descend' + --man, -m show complete documentation + --nosysincludes do not care about system includes () + --output=file, -o write output to file instead of standard out + --subgraphs (BROKEN) show cpp modules with their submodules + --sysincludes, -s consider even system includes () as + dependencies (default) + --trivial=n, -t remove n levels of trivial modules + --unused=n, -u remove n levels of unused modules + --verbose, -v increase verbosity level + + +=head1 OPTIONS + +=over 8 + +=item B<--blacklist>=file, B<-b> + +Use as module black list. In the black-list file modules can be +specified to be ignored as source of any dependency, as target of any +dependency, or at all. + +=item B<--descend, -d> + +Descend into included files, if this option is enabled gendotdeps +tries to open included files and track down also their +dependecies. The files are looked up in the specified include +directory (see B<--includepath, -I>). + +=item B<--fancy, -f> + +Use fancy colors for the different kinds of modules. If this option is +enabled directly specified 'cpp' modules are filled sky-blue, directly +specified non-'cpp' modules are filled white, not inspected includes +are filled grey, and descended includes are filled beige. + +=item B<--help, -h, -?> + +Prints a brief help message and exits. + +=item B<--includepath> dir, B<-I> + +Adds dir to the search path for includes (see B<--descend>). + +=item B<--man, -m> + +Prints the manual page and exits. + +=item B<--nosysincludes> + +This option disables --sysincludes, this means that no system includes +are taken into account for the dependency generation. + +=item B<--output>=file, B<-o> + +Write the generated dependency graph to instead of standard +output. + +=item B<--subgraphs> + +Generates a subgraph for every cpp module, which shows the submodules. + +=item B<--sysincludes, -s> + +This option is the default (see --nosysincludes). If this option is +enabled also system includes are taken into account () for +the dependency calculations. + +=item B<--trivial>=n, B<-t> + +Remove levels of trivial modules from the dependency +graph. Trivial modules are modules that do not depend on any other +modules. + +=item B<--unused>=n, B<-u> + +Remove levels of unused modules from the dependency graph. Unused +modules are modules that have no other modules depend on them. + +=item B<--verbose, -v> + +Each time this option occurs the verbosity level is increased. + +=back + +=head1 DESCRIPTION + +Should be done, sorry! + +=cut diff --git a/kernel/fiasco/tool/genoffset.py b/kernel/fiasco/tool/genoffset.py new file mode 100755 index 00000000..2ad0bc07 --- /dev/null +++ b/kernel/fiasco/tool/genoffset.py @@ -0,0 +1,230 @@ +#!/usr/bin/env python + +import string,re,sys +import getopt +import pdb + +def gen_esc_sym(*literals): + return gen_escaped_symbols(*literals) + +def gen_escaped_symbols(*literals): + return tuple(map(lambda x: re.escape(x),literals)) + +context_marker = "class context_t %s %s size (\d+) vtable self id \d+ %s" % \ + gen_escaped_symbols("{", "/*", "*/") + +d_members_context = ["_state", + "ready_next", + "ready_prev", + "kernel_sp", + "_space_context", + "_stack_link", + "_donatee", + "_lock_cnt", + "_thread_lock", + "_sched", + "_fpu_regs"] + +sender_marker = "class sender_t %s %s size (\d+) vtable self id \d+ %s" % \ + gen_escaped_symbols("{","/*","*/") + +d_members_sender = ["_id", + "_send_partner", + "sender_next", + "sender_prev"] + + +receiver_marker = "class receiver_t : public context_t %s id \d+ %s %s %s size \d+ vtable class context_t %s id \d+ %s id \d+ %s" % gen_escaped_symbols("/*","*/","{","/*","/*","*/","*/") + + + +d_members_receiver = ["_partner", + "_receive_regs", + "_pagein_request", + "_pagein_applicant", + "_sender_first", + "_timeout"] + + + +thread_marker = "class thread_t : public receiver_t %s id \d+ %s, public sender_t %s id \d+ %s %s bitpos (\d+) %s %s %s size (\d+) vtable class context_t %s id \d+ %s id \d+ %s" % gen_escaped_symbols("/*","*/","/*", "*/", "/*","*/","{", "/*", "/*","*/","*/") + +d_members_thread = ["_space", + "_thread_lock", +# "_timeout", + "_pager", + "_preempter", + "_ext_preempter", + "present_next", + "present_prev", + "_irq", + "_idt", + "_idt_limit", + "_target_desc", + "_pagein_error_code", + "_vm_window0", + "_vm_window1", + "_recover_jmpbuf", + "_pf_timeout", + "_last_pf_address", + "_last_pf_error_code", + "_magic"] + +class_members = {"context" : d_members_context, + "receiver" : d_members_receiver, + "sender" : d_members_sender, + "thread" : d_members_thread} + +f_members = [] + +verbose_output = 0 + +def do_print(*args): + assert len(args) > 0 + if not verbose_output: + return + for i in range(len(args) -1): + print args[i], + print args[-1] + + +def extract_members(sections): + section_members = {} + for k , lines in sections.items(): + do_print( "extract members for %s, %d members to go" % (k, len(class_members[k]))) + line_nr = 0 + section_members[k] = {} + for member in class_members[k]: + assert line_nr < len(lines) + p = re.compile("(?:\s|%s)(?:%s)?%s.*?; %s bitsize (\d+), bitpos (\d+) %s" % (gen_esc_sym("(","*")+ (member,) + gen_esc_sym("/*","*/"))) + while 1: + try: + m = p.search(lines[line_nr]) + except: + print "ERROR: member %s not found for unit %s" % (member,k) + print "use --verbose for more debug output" + sys.exit(1) + assert 0 +# pdb.set_trace() + + if m: + do_print( "found %s for %s %s %s @ %d" % (member, k, m.group(1), m.group(2), line_nr)) + section_members[k][member] = (int(m.group(1)), int(m.group(2))) + break + line_nr = line_nr + 1 + return section_members + +def extract_sections(input_file): + lines = open(input_file).readlines() + + section_keys = {"context" : context_marker, + "receiver" : receiver_marker, + "sender" : sender_marker, + "thread" : thread_marker} + + sections = {} + line_nr = 0 + + while section_keys and line_nr < len(lines) : + marker_pat = [] + curr_section = [] + do_print( "generating new pattern, %d parts, line_nr %d (%d)" % \ + (len(section_keys), line_nr, len(lines))) + for k,p in section_keys.items(): + marker_pat.append("(?P<%s>%s)" % (k,p)) + pat = re.compile("|".join(marker_pat)) + + section_finished = 0 + while line_nr < len(lines) and not section_finished: + m = pat.match(lines[line_nr]) + if m: + d = m.groupdict() + for k,v in d.items(): + if v: + do_print("found section %s @ %d" % (k,line_nr)) + curr_section.append(v) + del section_keys[k] + break + else: + assert 0 + + line_nr = line_nr + 1 + while 1: + curr_section.append(lines[line_nr]) + m = re.match("%s;" % gen_escaped_symbols("}"), lines[line_nr]) + if m: + sections[k] = curr_section + curr_section = [] + do_print( "finished section %s @ %d" % (k,line_nr)) + section_finished = 1 + break + line_nr = line_nr + 1 + else: + line_nr = line_nr + 1 + return sections + +def dump_members(prefix, offset, members): + member_list = members.items() + member_list.sort(lambda x, y: cmp(x[1][1], y[1][1])) + + for m in member_list: + member = m[0].upper() + while member[0] == "_": + member = member[1:] + name = "%s%s" % (prefix,member) + if len(name) < 40: + name = "%s%s" % (name, " " * (30 -len(name))) + print "#define %s %3d" % (name, offset / 8 + m[1][1]/ 8) + +def main(input_file): + sections = extract_sections(input_file) + + assert len(sections) == 4 + section_members = extract_members(sections) + + dump_members("OFS__THREAD__", 0, section_members["context"]) + dump_members("OFS__THREAD__", 0, section_members["receiver"]) + + m = re.match(thread_marker, sections["thread"][0]) + assert m + + sender_offset = int(m.group(1)) + thread_size = int(m.group(2)) + + print "#define CAST_thread_TO_sender " , sender_offset / 8 + + dump_members("OFS__THREAD__",sender_offset, section_members["sender"]) + dump_members("OFS__THREAD__",0, section_members["thread"]) + + print "#define OFS__THREAD__MAX " , thread_size + +def usage(): + print "usage: %s [options]" % sys.argv[0] + print "Options:" + print " --help Display this information" + print " --verbose Verbose output for debugging" + +if __name__ == "__main__": + input_file = "thread.debug" + try: + opts, args = getopt.getopt(sys.argv[1:], "", ["verbose","help","file="]) + except getopt.GetoptError, err: + print err.msg + usage(); + sys.exit(1) + + if args: + usage() + sys.exit(1) + + for o, a in opts: + if o == "--verbose": + verbose_output = 1 + continue + if o == "--file": + input_file = a + continue + if o == "--help": + usage() + sys.exit(0) + main(input_file) diff --git a/kernel/fiasco/tool/kconfig/COPYING b/kernel/fiasco/tool/kconfig/COPYING new file mode 100644 index 00000000..ca442d31 --- /dev/null +++ b/kernel/fiasco/tool/kconfig/COPYING @@ -0,0 +1,356 @@ + + NOTE! This copyright does *not* cover user programs that use kernel + services by normal system calls - this is merely considered normal use + of the kernel, and does *not* fall under the heading of "derived work". + Also note that the GPL below is copyrighted by the Free Software + Foundation, but the instance of code that it refers to (the Linux + kernel) is copyrighted by me and others who actually wrote it. + + Also note that the only valid version of the GPL as far as the kernel + is concerned is _this_ particular version of the license (ie v2, not + v2.2 or v3.x or whatever), unless explicitly otherwise stated. + + Linus Torvalds + +---------------------------------------- + + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/kernel/fiasco/tool/kconfig/Makefile b/kernel/fiasco/tool/kconfig/Makefile new file mode 100644 index 00000000..c565ae05 --- /dev/null +++ b/kernel/fiasco/tool/kconfig/Makefile @@ -0,0 +1,1400 @@ +VERSION = 3 +PATCHLEVEL = 5 +SUBLEVEL = 0 +EXTRAVERSION = +NAME = Saber-toothed Squirrel + +# *DOCUMENTATION* +# To see a list of typical targets execute "make help" +# More info can be located in ./README +# Comments in this file are targeted only to the developer, do not +# expect to learn how to build the kernel reading this file. + +# Do not: +# o use make's built-in rules and variables +# (this increases performance and avoids hard-to-debug behaviour); +# o print "Entering directory ..."; +MAKEFLAGS += -rR --no-print-directory + +# Avoid funny character set dependencies +unexport LC_ALL +LC_COLLATE=C +LC_NUMERIC=C +export LC_COLLATE LC_NUMERIC + +# We are using a recursive build, so we need to do a little thinking +# to get the ordering right. +# +# Most importantly: sub-Makefiles should only ever modify files in +# their own directory. If in some directory we have a dependency on +# a file in another dir (which doesn't happen often, but it's often +# unavoidable when linking the built-in.o targets which finally +# turn into vmlinux), we will call a sub make in that other dir, and +# after that we are sure that everything which is in that other dir +# is now up to date. +# +# The only cases where we need to modify files which have global +# effects are thus separated out and done before the recursive +# descending is started. They are now explicitly listed as the +# prepare rule. + +# To put more focus on warnings, be less verbose as default +# Use 'make V=1' to see the full commands + +ifeq ("$(origin V)", "command line") + KBUILD_VERBOSE = $(V) +endif +ifndef KBUILD_VERBOSE + KBUILD_VERBOSE = 0 +endif + +# Call a source code checker (by default, "sparse") as part of the +# C compilation. +# +# Use 'make C=1' to enable checking of only re-compiled files. +# Use 'make C=2' to enable checking of *all* source files, regardless +# of whether they are re-compiled or not. +# +# See the file "Documentation/sparse.txt" for more details, including +# where to get the "sparse" utility. + +ifeq ("$(origin C)", "command line") + KBUILD_CHECKSRC = $(C) +endif +ifndef KBUILD_CHECKSRC + KBUILD_CHECKSRC = 0 +endif + +# Use make M=dir to specify directory of external module to build +# Old syntax make ... SUBDIRS=$PWD is still supported +# Setting the environment variable KBUILD_EXTMOD take precedence +ifdef SUBDIRS + KBUILD_EXTMOD ?= $(SUBDIRS) +endif + +ifeq ("$(origin M)", "command line") + KBUILD_EXTMOD := $(M) +endif + +# kbuild supports saving output files in a separate directory. +# To locate output files in a separate directory two syntaxes are supported. +# In both cases the working directory must be the root of the kernel src. +# 1) O= +# Use "make O=dir/to/store/output/files/" +# +# 2) Set KBUILD_OUTPUT +# Set the environment variable KBUILD_OUTPUT to point to the directory +# where the output files shall be placed. +# export KBUILD_OUTPUT=dir/to/store/output/files/ +# make +# +# The O= assignment takes precedence over the KBUILD_OUTPUT environment +# variable. + + +# KBUILD_SRC is set on invocation of make in OBJ directory +# KBUILD_SRC is not intended to be used by the regular user (for now) +ifeq ($(KBUILD_SRC),) + +# OK, Make called in directory where kernel src resides +# Do we want to locate output files in a separate directory? +ifeq ("$(origin O)", "command line") + KBUILD_OUTPUT := $(O) +endif + +ifeq ("$(origin W)", "command line") + export KBUILD_ENABLE_EXTRA_GCC_CHECKS := $(W) +endif + +# That's our default target when none is given on the command line +PHONY := _all +_all: + +# Cancel implicit rules on top Makefile +$(CURDIR)/Makefile Makefile: ; + +ifneq ($(KBUILD_OUTPUT),) +# Invoke a second make in the output directory, passing relevant variables +# check that the output directory actually exists +saved-output := $(KBUILD_OUTPUT) +KBUILD_OUTPUT := $(shell cd $(KBUILD_OUTPUT) && /bin/pwd) +$(if $(KBUILD_OUTPUT),, \ + $(error output directory "$(saved-output)" does not exist)) + +PHONY += $(MAKECMDGOALS) sub-make + +$(filter-out _all sub-make $(CURDIR)/Makefile, $(MAKECMDGOALS)) _all: sub-make + $(Q)@: + +sub-make: FORCE + $(if $(KBUILD_VERBOSE:1=),@)$(MAKE) -C $(KBUILD_OUTPUT) \ + KBUILD_SRC=$(CURDIR) \ + KBUILD_EXTMOD="$(KBUILD_EXTMOD)" -f $(CURDIR)/Makefile \ + $(filter-out _all sub-make,$(MAKECMDGOALS)) + +# Leave processing to above invocation of make +skip-makefile := 1 +endif # ifneq ($(KBUILD_OUTPUT),) +endif # ifeq ($(KBUILD_SRC),) + +# We process the rest of the Makefile if this is the final invocation of make +ifeq ($(skip-makefile),) + +# If building an external module we do not care about the all: rule +# but instead _all depend on modules +PHONY += all +ifeq ($(KBUILD_EXTMOD),) +_all: all +else +_all: modules +endif + +srctree := $(if $(KBUILD_SRC),$(KBUILD_SRC),$(CURDIR)) +objtree := $(CURDIR) +src := $(srctree) +obj := $(objtree) + +VPATH := $(srctree)$(if $(KBUILD_EXTMOD),:$(KBUILD_EXTMOD)) + +export srctree objtree VPATH + + +# SUBARCH tells the usermode build what the underlying arch is. That is set +# first, and if a usermode build is happening, the "ARCH=um" on the command +# line overrides the setting of ARCH below. If a native build is happening, +# then ARCH is assigned, getting whatever value it gets normally, and +# SUBARCH is subsequently ignored. + +SUBARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \ + -e s/arm.*/arm/ -e s/sa110/arm/ \ + -e s/s390x/s390/ -e s/parisc64/parisc/ \ + -e s/ppc.*/powerpc/ -e s/mips.*/mips/ \ + -e s/sh[234].*/sh/ ) + +# Cross compiling and selecting different set of gcc/bin-utils +# --------------------------------------------------------------------------- +# +# When performing cross compilation for other architectures ARCH shall be set +# to the target architecture. (See arch/* for the possibilities). +# ARCH can be set during invocation of make: +# make ARCH=ia64 +# Another way is to have ARCH set in the environment. +# The default ARCH is the host where make is executed. + +# CROSS_COMPILE specify the prefix used for all executables used +# during compilation. Only gcc and related bin-utils executables +# are prefixed with $(CROSS_COMPILE). +# CROSS_COMPILE can be set on the command line +# make CROSS_COMPILE=ia64-linux- +# Alternatively CROSS_COMPILE can be set in the environment. +# A third alternative is to store a setting in .config so that plain +# "make" in the configured kernel build directory always uses that. +# Default value for CROSS_COMPILE is not to prefix executables +# Note: Some architectures assign CROSS_COMPILE in their arch/*/Makefile +export KBUILD_BUILDHOST := $(SUBARCH) +ARCH ?= $(SUBARCH) +CROSS_COMPILE ?= $(CONFIG_CROSS_COMPILE:"%"=%) + +# Architecture as present in compile.h +UTS_MACHINE := $(ARCH) +SRCARCH := $(ARCH) + +# Additional ARCH settings for x86 +ifeq ($(ARCH),i386) + SRCARCH := x86 +endif +ifeq ($(ARCH),x86_64) + SRCARCH := x86 +endif + +# Additional ARCH settings for sparc +ifeq ($(ARCH),sparc32) + SRCARCH := sparc +endif +ifeq ($(ARCH),sparc64) + SRCARCH := sparc +endif + +# Additional ARCH settings for sh +ifeq ($(ARCH),sh64) + SRCARCH := sh +endif + +# Additional ARCH settings for tile +ifeq ($(ARCH),tilepro) + SRCARCH := tile +endif +ifeq ($(ARCH),tilegx) + SRCARCH := tile +endif + +# Where to locate arch specific headers +hdr-arch := $(SRCARCH) + +KCONFIG_CONFIG ?= .config +export KCONFIG_CONFIG + +# SHELL used by kbuild +CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \ + else if [ -x /bin/bash ]; then echo /bin/bash; \ + else echo sh; fi ; fi) + +HOSTCC = gcc +HOSTCXX = g++ +HOSTCFLAGS = -Wall -Wmissing-prototypes -Wstrict-prototypes -O2 -fomit-frame-pointer +HOSTCXXFLAGS = -O2 + +# Decide whether to build built-in, modular, or both. +# Normally, just do built-in. + +KBUILD_MODULES := +KBUILD_BUILTIN := 1 + +# If we have only "make modules", don't compile built-in objects. +# When we're building modules with modversions, we need to consider +# the built-in objects during the descend as well, in order to +# make sure the checksums are up to date before we record them. + +ifeq ($(MAKECMDGOALS),modules) + KBUILD_BUILTIN := $(if $(CONFIG_MODVERSIONS),1) +endif + +# If we have "make modules", compile modules +# in addition to whatever we do anyway. +# Just "make" or "make all" shall build modules as well + +ifneq ($(filter all _all modules,$(MAKECMDGOALS)),) + KBUILD_MODULES := 1 +endif + +ifeq ($(MAKECMDGOALS),) + KBUILD_MODULES := 1 +endif + +export KBUILD_MODULES KBUILD_BUILTIN +export KBUILD_CHECKSRC KBUILD_SRC KBUILD_EXTMOD + +# Beautify output +# --------------------------------------------------------------------------- +# +# Normally, we echo the whole command before executing it. By making +# that echo $($(quiet)$(cmd)), we now have the possibility to set +# $(quiet) to choose other forms of output instead, e.g. +# +# quiet_cmd_cc_o_c = Compiling $(RELDIR)/$@ +# cmd_cc_o_c = $(CC) $(c_flags) -c -o $@ $< +# +# If $(quiet) is empty, the whole command will be printed. +# If it is set to "quiet_", only the short version will be printed. +# If it is set to "silent_", nothing will be printed at all, since +# the variable $(silent_cmd_cc_o_c) doesn't exist. +# +# A simple variant is to prefix commands with $(Q) - that's useful +# for commands that shall be hidden in non-verbose mode. +# +# $(Q)ln $@ :< +# +# If KBUILD_VERBOSE equals 0 then the above command will be hidden. +# If KBUILD_VERBOSE equals 1 then the above command is displayed. + +ifeq ($(KBUILD_VERBOSE),1) + quiet = + Q = +else + quiet=quiet_ + Q = @ +endif + +# If the user is running make -s (silent mode), suppress echoing of +# commands + +ifneq ($(filter s% -s%,$(MAKEFLAGS)),) + quiet=silent_ +endif + +export quiet Q KBUILD_VERBOSE + + +# Look for make include files relative to root of kernel src +MAKEFLAGS += --include-dir=$(srctree) + +# We need some generic definitions (do not try to remake the file). +$(srctree)/scripts/Kbuild.include: ; +include $(srctree)/scripts/Kbuild.include + +# Make variables (CC, etc...) + +AS = $(CROSS_COMPILE)as +LD = $(CROSS_COMPILE)ld +CC = $(CROSS_COMPILE)gcc +CPP = $(CC) -E +AR = $(CROSS_COMPILE)ar +NM = $(CROSS_COMPILE)nm +STRIP = $(CROSS_COMPILE)strip +OBJCOPY = $(CROSS_COMPILE)objcopy +OBJDUMP = $(CROSS_COMPILE)objdump +AWK = awk +GENKSYMS = scripts/genksyms/genksyms +INSTALLKERNEL := installkernel +DEPMOD = /sbin/depmod +PERL = perl +CHECK = sparse + +CHECKFLAGS := -D__linux__ -Dlinux -D__STDC__ -Dunix -D__unix__ \ + -Wbitwise -Wno-return-void $(CF) +CFLAGS_MODULE = +AFLAGS_MODULE = +LDFLAGS_MODULE = +CFLAGS_KERNEL = +AFLAGS_KERNEL = +CFLAGS_GCOV = -fprofile-arcs -ftest-coverage + + +# Use LINUXINCLUDE when you must reference the include/ directory. +# Needed to be compatible with the O= option +LINUXINCLUDE := -I$(srctree)/arch/$(hdr-arch)/include \ + -Iarch/$(hdr-arch)/include/generated -Iinclude \ + $(if $(KBUILD_SRC), -I$(srctree)/include) \ + -include $(srctree)/include/linux/kconfig.h + +KBUILD_CPPFLAGS := -D__KERNEL__ + +KBUILD_CFLAGS := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \ + -fno-strict-aliasing -fno-common \ + -Werror-implicit-function-declaration \ + -Wno-format-security \ + -fno-delete-null-pointer-checks +KBUILD_AFLAGS_KERNEL := +KBUILD_CFLAGS_KERNEL := +KBUILD_AFLAGS := -D__ASSEMBLY__ +KBUILD_AFLAGS_MODULE := -DMODULE +KBUILD_CFLAGS_MODULE := -DMODULE +KBUILD_LDFLAGS_MODULE := -T $(srctree)/scripts/module-common.lds + +# Read KERNELRELEASE from include/config/kernel.release (if it exists) +KERNELRELEASE = $(shell cat include/config/kernel.release 2> /dev/null) +KERNELVERSION = $(VERSION)$(if $(PATCHLEVEL),.$(PATCHLEVEL)$(if $(SUBLEVEL),.$(SUBLEVEL)))$(EXTRAVERSION) + +export VERSION PATCHLEVEL SUBLEVEL KERNELRELEASE KERNELVERSION +export ARCH SRCARCH CONFIG_SHELL HOSTCC HOSTCFLAGS CROSS_COMPILE AS LD CC +export CPP AR NM STRIP OBJCOPY OBJDUMP +export MAKE AWK GENKSYMS INSTALLKERNEL PERL UTS_MACHINE +export HOSTCXX HOSTCXXFLAGS LDFLAGS_MODULE CHECK CHECKFLAGS + +export KBUILD_CPPFLAGS NOSTDINC_FLAGS LINUXINCLUDE OBJCOPYFLAGS LDFLAGS +export KBUILD_CFLAGS CFLAGS_KERNEL CFLAGS_MODULE CFLAGS_GCOV +export KBUILD_AFLAGS AFLAGS_KERNEL AFLAGS_MODULE +export KBUILD_AFLAGS_MODULE KBUILD_CFLAGS_MODULE KBUILD_LDFLAGS_MODULE +export KBUILD_AFLAGS_KERNEL KBUILD_CFLAGS_KERNEL +export KBUILD_ARFLAGS + +# When compiling out-of-tree modules, put MODVERDIR in the module +# tree rather than in the kernel tree. The kernel tree might +# even be read-only. +export MODVERDIR := $(if $(KBUILD_EXTMOD),$(firstword $(KBUILD_EXTMOD))/).tmp_versions + +# Files to ignore in find ... statements + +RCS_FIND_IGNORE := \( -name SCCS -o -name BitKeeper -o -name .svn -o -name CVS \ + -o -name .pc -o -name .hg -o -name .git \) -prune -o +export RCS_TAR_IGNORE := --exclude SCCS --exclude BitKeeper --exclude .svn \ + --exclude CVS --exclude .pc --exclude .hg --exclude .git + +# =========================================================================== +# Rules shared between *config targets and build targets + +# Basic helpers built in scripts/ +PHONY += scripts_basic +scripts_basic: + $(Q)$(MAKE) $(build)=scripts/basic + $(Q)rm -f .tmp_quiet_recordmcount + +# To avoid any implicit rule to kick in, define an empty command. +scripts/basic/%: scripts_basic ; + +PHONY += outputmakefile +# outputmakefile generates a Makefile in the output directory, if using a +# separate output directory. This allows convenient use of make in the +# output directory. +outputmakefile: +ifneq ($(KBUILD_SRC_disabled_for_fiasco),) + $(Q)ln -fsn $(srctree) source + $(Q)$(CONFIG_SHELL) $(srctree)/scripts/mkmakefile \ + $(srctree) $(objtree) $(VERSION) $(PATCHLEVEL) +endif + +# Support for using generic headers in asm-generic +PHONY += asm-generic +asm-generic: + $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.asm-generic \ + obj=arch/$(SRCARCH)/include/generated/asm + +# To make sure we do not include .config for any of the *config targets +# catch them early, and hand them over to scripts/kconfig/Makefile +# It is allowed to specify more targets when calling make, including +# mixing *config targets and build targets. +# For example 'make oldconfig all'. +# Detect when mixed targets is specified, and make a second invocation +# of make so .config is not included in this case either (for *config). + +no-dot-config-targets := clean mrproper distclean \ + cscope gtags TAGS tags help %docs check% coccicheck \ + include/linux/version.h headers_% archheaders archscripts \ + kernelversion %src-pkg + +config-targets := 0 +mixed-targets := 0 +dot-config := 1 + +ifneq ($(filter $(no-dot-config-targets), $(MAKECMDGOALS)),) + ifeq ($(filter-out $(no-dot-config-targets), $(MAKECMDGOALS)),) + dot-config := 0 + endif +endif + +ifeq ($(KBUILD_EXTMOD),) + ifneq ($(filter config %config,$(MAKECMDGOALS)),) + config-targets := 1 + ifneq ($(filter-out config %config,$(MAKECMDGOALS)),) + mixed-targets := 1 + endif + endif +endif + +ifeq ($(mixed-targets),1) +# =========================================================================== +# We're called with mixed targets (*config and build targets). +# Handle them one by one. + +%:: FORCE + $(Q)$(MAKE) -C $(srctree) KBUILD_SRC= $@ + +else +ifeq ($(config-targets),1) +# =========================================================================== +# *config targets only - make sure prerequisites are updated, and descend +# in scripts/kconfig to make the *config target + +# Read arch specific Makefile to set KBUILD_DEFCONFIG as needed. +# KBUILD_DEFCONFIG may point out an alternative default configuration +# used for 'make defconfig' +#adam#include $(srctree)/arch/$(SRCARCH)/Makefile +export KBUILD_DEFCONFIG KBUILD_KCONFIG + +config: scripts_basic outputmakefile FORCE + $(Q)mkdir -p config + $(Q)$(MAKE) $(build)=scripts/kconfig $@ + +%config: scripts_basic outputmakefile FORCE + $(Q)mkdir -p config + $(Q)$(MAKE) $(build)=scripts/kconfig $@ + +else +# =========================================================================== +# Build targets only - this includes vmlinux, arch specific targets, clean +# targets and others. In general all targets except *config targets. + +ifeq ($(KBUILD_EXTMOD),) +# Additional helpers built in scripts/ +# Carefully list dependencies so we do not try to build scripts twice +# in parallel +PHONY += scripts +scripts: scripts_basic include/config/auto.conf include/config/tristate.conf + $(Q)$(MAKE) $(build)=$(@) + +# Objects we will link into vmlinux / subdirs we need to visit +init-y := init/ +drivers-y := drivers/ sound/ firmware/ +net-y := net/ +libs-y := lib/ +core-y := usr/ +endif # KBUILD_EXTMOD + +ifeq ($(dot-config),1) +# Read in config +-include include/config/auto.conf + +ifeq ($(KBUILD_EXTMOD),) +# Read in dependencies to all Kconfig* files, make sure to run +# oldconfig if changes are detected. +-include include/config/auto.conf.cmd + +# To avoid any implicit rule to kick in, define an empty command +$(KCONFIG_CONFIG) include/config/auto.conf.cmd: ; + +# If .config is newer than include/config/auto.conf, someone tinkered +# with it and forgot to run make oldconfig. +# if auto.conf.cmd is missing then we are probably in a cleaned tree so +# we execute the config step to be sure to catch updated Kconfig files +include/config/%.conf: $(KCONFIG_CONFIG) include/config/auto.conf.cmd + $(Q)$(MAKE) -f $(srctree)/Makefile silentoldconfig +else +# external modules needs include/generated/autoconf.h and include/config/auto.conf +# but do not care if they are up-to-date. Use auto.conf to trigger the test +PHONY += include/config/auto.conf + +include/config/auto.conf: + $(Q)test -e include/generated/autoconf.h -a -e $@ || ( \ + echo; \ + echo " ERROR: Kernel configuration is invalid."; \ + echo " include/generated/autoconf.h or $@ are missing.";\ + echo " Run 'make oldconfig && make prepare' on kernel src to fix it."; \ + echo; \ + /bin/false) + +endif # KBUILD_EXTMOD + +else +# Dummy target needed, because used as prerequisite +include/config/auto.conf: ; +endif # $(dot-config) + +# The all: target is the default when no target is given on the +# command line. +# This allow a user to issue only 'make' to build a kernel including modules +# Defaults to vmlinux, but the arch makefile usually adds further targets +all: vmlinux + +ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE +KBUILD_CFLAGS += -Os +else +KBUILD_CFLAGS += -O2 +endif + +include $(srctree)/arch/$(SRCARCH)/Makefile + +ifdef CONFIG_READABLE_ASM +# Disable optimizations that make assembler listings hard to read. +# reorder blocks reorders the control in the function +# ipa clone creates specialized cloned functions +# partial inlining inlines only parts of functions +KBUILD_CFLAGS += $(call cc-option,-fno-reorder-blocks,) \ + $(call cc-option,-fno-ipa-cp-clone,) \ + $(call cc-option,-fno-partial-inlining) +endif + +ifneq ($(CONFIG_FRAME_WARN),0) +KBUILD_CFLAGS += $(call cc-option,-Wframe-larger-than=${CONFIG_FRAME_WARN}) +endif + +# Force gcc to behave correct even for buggy distributions +ifndef CONFIG_CC_STACKPROTECTOR +KBUILD_CFLAGS += $(call cc-option, -fno-stack-protector) +endif + +# This warning generated too much noise in a regular build. +# Use make W=1 to enable this warning (see scripts/Makefile.build) +KBUILD_CFLAGS += $(call cc-disable-warning, unused-but-set-variable) + +ifdef CONFIG_FRAME_POINTER +KBUILD_CFLAGS += -fno-omit-frame-pointer -fno-optimize-sibling-calls +else +# Some targets (ARM with Thumb2, for example), can't be built with frame +# pointers. For those, we don't have FUNCTION_TRACER automatically +# select FRAME_POINTER. However, FUNCTION_TRACER adds -pg, and this is +# incompatible with -fomit-frame-pointer with current GCC, so we don't use +# -fomit-frame-pointer with FUNCTION_TRACER. +ifndef CONFIG_FUNCTION_TRACER +KBUILD_CFLAGS += -fomit-frame-pointer +endif +endif + +ifdef CONFIG_DEBUG_INFO +KBUILD_CFLAGS += -g +KBUILD_AFLAGS += -gdwarf-2 +endif + +ifdef CONFIG_DEBUG_INFO_REDUCED +KBUILD_CFLAGS += $(call cc-option, -femit-struct-debug-baseonly) +endif + +ifdef CONFIG_FUNCTION_TRACER +KBUILD_CFLAGS += -pg +ifdef CONFIG_DYNAMIC_FTRACE + ifdef CONFIG_HAVE_C_RECORDMCOUNT + BUILD_C_RECORDMCOUNT := y + export BUILD_C_RECORDMCOUNT + endif +endif +endif + +# We trigger additional mismatches with less inlining +ifdef CONFIG_DEBUG_SECTION_MISMATCH +KBUILD_CFLAGS += $(call cc-option, -fno-inline-functions-called-once) +endif + +# arch Makefile may override CC so keep this after arch Makefile is included +NOSTDINC_FLAGS += -nostdinc -isystem $(shell $(CC) -print-file-name=include) +CHECKFLAGS += $(NOSTDINC_FLAGS) + +# warn about C99 declaration after statement +KBUILD_CFLAGS += $(call cc-option,-Wdeclaration-after-statement,) + +# disable pointer signed / unsigned warnings in gcc 4.0 +KBUILD_CFLAGS += $(call cc-disable-warning, pointer-sign) + +# disable invalid "can't wrap" optimizations for signed / pointers +KBUILD_CFLAGS += $(call cc-option,-fno-strict-overflow) + +# conserve stack if available +KBUILD_CFLAGS += $(call cc-option,-fconserve-stack) + +# use the deterministic mode of AR if available +KBUILD_ARFLAGS := $(call ar-option,D) + +# check for 'asm goto' +ifeq ($(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-goto.sh $(CC)), y) + KBUILD_CFLAGS += -DCC_HAVE_ASM_GOTO +endif + +# Add user supplied CPPFLAGS, AFLAGS and CFLAGS as the last assignments +# But warn user when we do so +warn-assign = \ +$(warning "WARNING: Appending $$K$(1) ($(K$(1))) from $(origin K$(1)) to kernel $$$(1)") + +ifneq ($(KCPPFLAGS),) + $(call warn-assign,CPPFLAGS) + KBUILD_CPPFLAGS += $(KCPPFLAGS) +endif +ifneq ($(KAFLAGS),) + $(call warn-assign,AFLAGS) + KBUILD_AFLAGS += $(KAFLAGS) +endif +ifneq ($(KCFLAGS),) + $(call warn-assign,CFLAGS) + KBUILD_CFLAGS += $(KCFLAGS) +endif + +# Use --build-id when available. +LDFLAGS_BUILD_ID = $(patsubst -Wl$(comma)%,%,\ + $(call cc-ldoption, -Wl$(comma)--build-id,)) +KBUILD_LDFLAGS_MODULE += $(LDFLAGS_BUILD_ID) +LDFLAGS_vmlinux += $(LDFLAGS_BUILD_ID) + +ifeq ($(CONFIG_STRIP_ASM_SYMS),y) +LDFLAGS_vmlinux += $(call ld-option, -X,) +endif + +# Default kernel image to build when no specific target is given. +# KBUILD_IMAGE may be overruled on the command line or +# set in the environment +# Also any assignments in arch/$(ARCH)/Makefile take precedence over +# this default value +export KBUILD_IMAGE ?= vmlinux + +# +# INSTALL_PATH specifies where to place the updated kernel and system map +# images. Default is /boot, but you can set it to other values +export INSTALL_PATH ?= /boot + +# +# INSTALL_MOD_PATH specifies a prefix to MODLIB for module directory +# relocations required by build roots. This is not defined in the +# makefile but the argument can be passed to make if needed. +# + +MODLIB = $(INSTALL_MOD_PATH)/lib/modules/$(KERNELRELEASE) +export MODLIB + +# +# INSTALL_MOD_STRIP, if defined, will cause modules to be +# stripped after they are installed. If INSTALL_MOD_STRIP is '1', then +# the default option --strip-debug will be used. Otherwise, +# INSTALL_MOD_STRIP value will be used as the options to the strip command. + +ifdef INSTALL_MOD_STRIP +ifeq ($(INSTALL_MOD_STRIP),1) +mod_strip_cmd = $(STRIP) --strip-debug +else +mod_strip_cmd = $(STRIP) $(INSTALL_MOD_STRIP) +endif # INSTALL_MOD_STRIP=1 +else +mod_strip_cmd = true +endif # INSTALL_MOD_STRIP +export mod_strip_cmd + + +ifeq ($(KBUILD_EXTMOD),) +core-y += kernel/ mm/ fs/ ipc/ security/ crypto/ block/ + +vmlinux-dirs := $(patsubst %/,%,$(filter %/, $(init-y) $(init-m) \ + $(core-y) $(core-m) $(drivers-y) $(drivers-m) \ + $(net-y) $(net-m) $(libs-y) $(libs-m))) + +vmlinux-alldirs := $(sort $(vmlinux-dirs) $(patsubst %/,%,$(filter %/, \ + $(init-n) $(init-) \ + $(core-n) $(core-) $(drivers-n) $(drivers-) \ + $(net-n) $(net-) $(libs-n) $(libs-)))) + +init-y := $(patsubst %/, %/built-in.o, $(init-y)) +core-y := $(patsubst %/, %/built-in.o, $(core-y)) +drivers-y := $(patsubst %/, %/built-in.o, $(drivers-y)) +net-y := $(patsubst %/, %/built-in.o, $(net-y)) +libs-y1 := $(patsubst %/, %/lib.a, $(libs-y)) +libs-y2 := $(patsubst %/, %/built-in.o, $(libs-y)) +libs-y := $(libs-y1) $(libs-y2) + +# Externally visible symbols (used by link-vmlinux.sh) +export KBUILD_VMLINUX_INIT := $(head-y) $(init-y) +export KBUILD_VMLINUX_MAIN := $(core-y) $(libs-y) $(drivers-y) $(net-y) +export KBUILD_LDS := arch/$(SRCARCH)/kernel/vmlinux.lds +export LDFLAGS_vmlinux + +vmlinux-deps := $(KBUILD_LDS) $(KBUILD_VMLINUX_INIT) $(KBUILD_VMLINUX_MAIN) + +# Final link of vmlinux + cmd_link-vmlinux = $(CONFIG_SHELL) $< $(LD) $(LDFLAGS) $(LDFLAGS_vmlinux) +quiet_cmd_link-vmlinux = LINK $@ + +# Include targets which we want to +# execute if the rest of the kernel build went well. +vmlinux: scripts/link-vmlinux.sh $(vmlinux-deps) FORCE +ifdef CONFIG_HEADERS_CHECK + $(Q)$(MAKE) -f $(srctree)/Makefile headers_check +endif +ifdef CONFIG_SAMPLES + $(Q)$(MAKE) $(build)=samples +endif +ifdef CONFIG_BUILD_DOCSRC + $(Q)$(MAKE) $(build)=Documentation +endif + +$(call if_changed,link-vmlinux) + +# The actual objects are generated when descending, +# make sure no implicit rule kicks in +$(sort $(vmlinux-deps)): $(vmlinux-dirs) ; + +# Handle descending into subdirectories listed in $(vmlinux-dirs) +# Preset locale variables to speed up the build process. Limit locale +# tweaks to this spot to avoid wrong language settings when running +# make menuconfig etc. +# Error messages still appears in the original language + +PHONY += $(vmlinux-dirs) +$(vmlinux-dirs): prepare scripts + $(Q)$(MAKE) $(build)=$@ + +# Store (new) KERNELRELASE string in include/config/kernel.release +include/config/kernel.release: include/config/auto.conf FORCE + $(Q)rm -f $@ + $(Q)echo "$(KERNELVERSION)$$($(CONFIG_SHELL) $(srctree)/scripts/setlocalversion $(srctree))" > $@ + + +# Things we need to do before we recursively start building the kernel +# or the modules are listed in "prepare". +# A multi level approach is used. prepareN is processed before prepareN-1. +# archprepare is used in arch Makefiles and when processed asm symlink, +# version.h and scripts_basic is processed / created. + +# Listed in dependency order +PHONY += prepare archprepare prepare0 prepare1 prepare2 prepare3 + +# prepare3 is used to check if we are building in a separate output directory, +# and if so do: +# 1) Check that make has not been executed in the kernel src $(srctree) +prepare3: include/config/kernel.release +ifneq ($(KBUILD_SRC),) + @$(kecho) ' Using $(srctree) as source for kernel' + $(Q)if [ -f $(srctree)/.config -o -d $(srctree)/include/config ]; then \ + echo " $(srctree) is not clean, please run 'make mrproper'"; \ + echo " in the '$(srctree)' directory.";\ + /bin/false; \ + fi; +endif + +# prepare2 creates a makefile if using a separate output directory +prepare2: prepare3 outputmakefile asm-generic + +prepare1: prepare2 include/linux/version.h include/generated/utsrelease.h \ + include/config/auto.conf + $(cmd_crmodverdir) + +archprepare: archheaders archscripts prepare1 scripts_basic + +prepare0: archprepare FORCE + $(Q)$(MAKE) $(build)=. + +# All the preparing.. +prepare: prepare0 + +# Generate some files +# --------------------------------------------------------------------------- + +# KERNELRELEASE can change from a few different places, meaning version.h +# needs to be updated, so this check is forced on all builds + +uts_len := 64 +define filechk_utsrelease.h + if [ `echo -n "$(KERNELRELEASE)" | wc -c ` -gt $(uts_len) ]; then \ + echo '"$(KERNELRELEASE)" exceeds $(uts_len) characters' >&2; \ + exit 1; \ + fi; \ + (echo \#define UTS_RELEASE \"$(KERNELRELEASE)\";) +endef + +define filechk_version.h + (echo \#define LINUX_VERSION_CODE $(shell \ + expr $(VERSION) \* 65536 + 0$(PATCHLEVEL) \* 256 + 0$(SUBLEVEL)); \ + echo '#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))';) +endef + +include/linux/version.h: $(srctree)/Makefile FORCE + $(call filechk,version.h) + +include/generated/utsrelease.h: include/config/kernel.release FORCE + $(call filechk,utsrelease.h) + +PHONY += headerdep +headerdep: + $(Q)find $(srctree)/include/ -name '*.h' | xargs --max-args 1 \ + $(srctree)/scripts/headerdep.pl -I$(srctree)/include + +# --------------------------------------------------------------------------- + +PHONY += depend dep +depend dep: + @echo '*** Warning: make $@ is unnecessary now.' + +# --------------------------------------------------------------------------- +# Firmware install +INSTALL_FW_PATH=$(INSTALL_MOD_PATH)/lib/firmware +export INSTALL_FW_PATH + +PHONY += firmware_install +firmware_install: FORCE + @mkdir -p $(objtree)/firmware + $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.fwinst obj=firmware __fw_install + +# --------------------------------------------------------------------------- +# Kernel headers + +#Default location for installed headers +export INSTALL_HDR_PATH = $(objtree)/usr + +hdr-inst := -rR -f $(srctree)/scripts/Makefile.headersinst obj + +# If we do an all arch process set dst to asm-$(hdr-arch) +hdr-dst = $(if $(KBUILD_HEADERS), dst=include/asm-$(hdr-arch), dst=include/asm) + +PHONY += archheaders +archheaders: + +PHONY += archscripts +archscripts: + +PHONY += __headers +__headers: include/linux/version.h scripts_basic asm-generic archheaders archscripts FORCE + $(Q)$(MAKE) $(build)=scripts build_unifdef + +PHONY += headers_install_all +headers_install_all: + $(Q)$(CONFIG_SHELL) $(srctree)/scripts/headers.sh install + +PHONY += headers_install +headers_install: __headers + $(if $(wildcard $(srctree)/arch/$(hdr-arch)/include/asm/Kbuild),, \ + $(error Headers not exportable for the $(SRCARCH) architecture)) + $(Q)$(MAKE) $(hdr-inst)=include + $(Q)$(MAKE) $(hdr-inst)=arch/$(hdr-arch)/include/asm $(hdr-dst) + +PHONY += headers_check_all +headers_check_all: headers_install_all + $(Q)$(CONFIG_SHELL) $(srctree)/scripts/headers.sh check + +PHONY += headers_check +headers_check: headers_install + $(Q)$(MAKE) $(hdr-inst)=include HDRCHECK=1 + $(Q)$(MAKE) $(hdr-inst)=arch/$(hdr-arch)/include/asm $(hdr-dst) HDRCHECK=1 + +# --------------------------------------------------------------------------- +# Modules + +ifdef CONFIG_MODULES + +# By default, build modules as well + +all: modules + +# Build modules +# +# A module can be listed more than once in obj-m resulting in +# duplicate lines in modules.order files. Those are removed +# using awk while concatenating to the final file. + +PHONY += modules +modules: $(vmlinux-dirs) $(if $(KBUILD_BUILTIN),vmlinux) modules.builtin + $(Q)$(AWK) '!x[$$0]++' $(vmlinux-dirs:%=$(objtree)/%/modules.order) > $(objtree)/modules.order + @$(kecho) ' Building modules, stage 2.'; + $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost + $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.fwinst obj=firmware __fw_modbuild + +modules.builtin: $(vmlinux-dirs:%=%/modules.builtin) + $(Q)$(AWK) '!x[$$0]++' $^ > $(objtree)/modules.builtin + +%/modules.builtin: include/config/auto.conf + $(Q)$(MAKE) $(modbuiltin)=$* + + +# Target to prepare building external modules +PHONY += modules_prepare +modules_prepare: prepare scripts + +# Target to install modules +PHONY += modules_install +modules_install: _modinst_ _modinst_post + +PHONY += _modinst_ +_modinst_: + @rm -rf $(MODLIB)/kernel + @rm -f $(MODLIB)/source + @mkdir -p $(MODLIB)/kernel + @ln -s $(srctree) $(MODLIB)/source + @if [ ! $(objtree) -ef $(MODLIB)/build ]; then \ + rm -f $(MODLIB)/build ; \ + ln -s $(objtree) $(MODLIB)/build ; \ + fi + @cp -f $(objtree)/modules.order $(MODLIB)/ + @cp -f $(objtree)/modules.builtin $(MODLIB)/ + $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modinst + +# This depmod is only for convenience to give the initial +# boot a modules.dep even before / is mounted read-write. However the +# boot script depmod is the master version. +PHONY += _modinst_post +_modinst_post: _modinst_ + $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.fwinst obj=firmware __fw_modinst + $(call cmd,depmod) + +else # CONFIG_MODULES + +# Modules not configured +# --------------------------------------------------------------------------- + +modules modules_install: FORCE + @echo + @echo "The present kernel configuration has modules disabled." + @echo "Type 'make config' and enable loadable module support." + @echo "Then build a kernel with module support enabled." + @echo + @exit 1 + +endif # CONFIG_MODULES + +### +# Cleaning is done on three levels. +# make clean Delete most generated files +# Leave enough to build external modules +# make mrproper Delete the current configuration, and all generated files +# make distclean Remove editor backup files, patch leftover files and the like + +# Directories & files removed with 'make clean' +CLEAN_DIRS += $(MODVERDIR) + +# Directories & files removed with 'make mrproper' +MRPROPER_DIRS += include/config usr/include include/generated \ + arch/*/include/generated +MRPROPER_FILES += .config .config.old .version .old_version \ + include/linux/version.h \ + Module.symvers tags TAGS cscope* GPATH GTAGS GRTAGS GSYMS + +# clean - Delete most, but leave enough to build external modules +# +clean: rm-dirs := $(CLEAN_DIRS) +clean: rm-files := $(CLEAN_FILES) +clean-dirs := $(addprefix _clean_, . $(vmlinux-alldirs) Documentation samples) + +PHONY += $(clean-dirs) clean archclean +$(clean-dirs): + $(Q)$(MAKE) $(clean)=$(patsubst _clean_%,%,$@) + +clean: archclean + +# mrproper - Delete all generated files, including .config +# +mrproper: rm-dirs := $(wildcard $(MRPROPER_DIRS)) +mrproper: rm-files := $(wildcard $(MRPROPER_FILES)) +mrproper-dirs := $(addprefix _mrproper_,Documentation/DocBook scripts) + +PHONY += $(mrproper-dirs) mrproper archmrproper +$(mrproper-dirs): + $(Q)$(MAKE) $(clean)=$(patsubst _mrproper_%,%,$@) + +mrproper: clean archmrproper $(mrproper-dirs) + $(call cmd,rmdirs) + $(call cmd,rmfiles) + +# distclean +# +PHONY += distclean + +distclean: mrproper + @find $(srctree) $(RCS_FIND_IGNORE) \ + \( -name '*.orig' -o -name '*.rej' -o -name '*~' \ + -o -name '*.bak' -o -name '#*#' -o -name '.*.orig' \ + -o -name '.*.rej' \ + -o -name '*%' -o -name '.*.cmd' -o -name 'core' \) \ + -type f -print | xargs rm -f + + +# Packaging of the kernel to various formats +# --------------------------------------------------------------------------- +# rpm target kept for backward compatibility +package-dir := $(srctree)/scripts/package + +%src-pkg: FORCE + $(Q)$(MAKE) $(build)=$(package-dir) $@ +%pkg: include/config/kernel.release FORCE + $(Q)$(MAKE) $(build)=$(package-dir) $@ +rpm: include/config/kernel.release FORCE + $(Q)$(MAKE) $(build)=$(package-dir) $@ + + +# Brief documentation of the typical targets used +# --------------------------------------------------------------------------- + +boards := $(wildcard $(srctree)/arch/$(SRCARCH)/configs/*_defconfig) +boards := $(notdir $(boards)) +board-dirs := $(dir $(wildcard $(srctree)/arch/$(SRCARCH)/configs/*/*_defconfig)) +board-dirs := $(sort $(notdir $(board-dirs:/=))) + +help: + @echo 'Cleaning targets:' + @echo ' clean - Remove most generated files but keep the config and' + @echo ' enough build support to build external modules' + @echo ' mrproper - Remove all generated files + config + various backup files' + @echo ' distclean - mrproper + remove editor backup and patch files' + @echo '' + @echo 'Configuration targets:' + @$(MAKE) -f $(srctree)/scripts/kconfig/Makefile help + @echo '' + @echo 'Other generic targets:' + @echo ' all - Build all targets marked with [*]' + @echo '* vmlinux - Build the bare kernel' + @echo '* modules - Build all modules' + @echo ' modules_install - Install all modules to INSTALL_MOD_PATH (default: /)' + @echo ' firmware_install- Install all firmware to INSTALL_FW_PATH' + @echo ' (default: $$(INSTALL_MOD_PATH)/lib/firmware)' + @echo ' dir/ - Build all files in dir and below' + @echo ' dir/file.[oisS] - Build specified target only' + @echo ' dir/file.lst - Build specified mixed source/assembly target only' + @echo ' (requires a recent binutils and recent build (System.map))' + @echo ' dir/file.ko - Build module including final link' + @echo ' modules_prepare - Set up for building external modules' + @echo ' tags/TAGS - Generate tags file for editors' + @echo ' cscope - Generate cscope index' + @echo ' gtags - Generate GNU GLOBAL index' + @echo ' kernelrelease - Output the release version string' + @echo ' kernelversion - Output the version stored in Makefile' + @echo ' headers_install - Install sanitised kernel headers to INSTALL_HDR_PATH'; \ + echo ' (default: $(INSTALL_HDR_PATH))'; \ + echo '' + @echo 'Static analysers' + @echo ' checkstack - Generate a list of stack hogs' + @echo ' namespacecheck - Name space analysis on compiled kernel' + @echo ' versioncheck - Sanity check on version.h usage' + @echo ' includecheck - Check for duplicate included header files' + @echo ' export_report - List the usages of all exported symbols' + @echo ' headers_check - Sanity check on exported headers' + @echo ' headerdep - Detect inclusion cycles in headers' + @$(MAKE) -f $(srctree)/scripts/Makefile.help checker-help + @echo '' + @echo 'Kernel packaging:' + @$(MAKE) $(build)=$(package-dir) help + @echo '' + @echo 'Documentation targets:' + @$(MAKE) -f $(srctree)/Documentation/DocBook/Makefile dochelp + @echo '' + @echo 'Architecture specific targets ($(SRCARCH)):' + @$(if $(archhelp),$(archhelp),\ + echo ' No architecture specific help defined for $(SRCARCH)') + @echo '' + @$(if $(boards), \ + $(foreach b, $(boards), \ + printf " %-24s - Build for %s\\n" $(b) $(subst _defconfig,,$(b));) \ + echo '') + @$(if $(board-dirs), \ + $(foreach b, $(board-dirs), \ + printf " %-16s - Show %s-specific targets\\n" help-$(b) $(b);) \ + printf " %-16s - Show all of the above\\n" help-boards; \ + echo '') + + @echo ' make V=0|1 [targets] 0 => quiet build (default), 1 => verbose build' + @echo ' make V=2 [targets] 2 => give reason for rebuild of target' + @echo ' make O=dir [targets] Locate all output files in "dir", including .config' + @echo ' make C=1 [targets] Check all c source with $$CHECK (sparse by default)' + @echo ' make C=2 [targets] Force check of all c source with $$CHECK' + @echo ' make RECORDMCOUNT_WARN=1 [targets] Warn about ignored mcount sections' + @echo ' make W=n [targets] Enable extra gcc checks, n=1,2,3 where' + @echo ' 1: warnings which may be relevant and do not occur too often' + @echo ' 2: warnings which occur quite often but may still be relevant' + @echo ' 3: more obscure warnings, can most likely be ignored' + @echo ' Multiple levels can be combined with W=12 or W=123' + @echo '' + @echo 'Execute "make" or "make all" to build all targets marked with [*] ' + @echo 'For further info see the ./README file' + + +help-board-dirs := $(addprefix help-,$(board-dirs)) + +help-boards: $(help-board-dirs) + +boards-per-dir = $(notdir $(wildcard $(srctree)/arch/$(SRCARCH)/configs/$*/*_defconfig)) + +$(help-board-dirs): help-%: + @echo 'Architecture specific targets ($(SRCARCH) $*):' + @$(if $(boards-per-dir), \ + $(foreach b, $(boards-per-dir), \ + printf " %-24s - Build for %s\\n" $*/$(b) $(subst _defconfig,,$(b));) \ + echo '') + + +# Documentation targets +# --------------------------------------------------------------------------- +%docs: scripts_basic FORCE + $(Q)$(MAKE) $(build)=scripts build_docproc + $(Q)$(MAKE) $(build)=Documentation/DocBook $@ + +else # KBUILD_EXTMOD + +### +# External module support. +# When building external modules the kernel used as basis is considered +# read-only, and no consistency checks are made and the make +# system is not used on the basis kernel. If updates are required +# in the basis kernel ordinary make commands (without M=...) must +# be used. +# +# The following are the only valid targets when building external +# modules. +# make M=dir clean Delete all automatically generated files +# make M=dir modules Make all modules in specified dir +# make M=dir Same as 'make M=dir modules' +# make M=dir modules_install +# Install the modules built in the module directory +# Assumes install directory is already created + +# We are always building modules +KBUILD_MODULES := 1 +PHONY += crmodverdir +crmodverdir: + $(cmd_crmodverdir) + +PHONY += $(objtree)/Module.symvers +$(objtree)/Module.symvers: + @test -e $(objtree)/Module.symvers || ( \ + echo; \ + echo " WARNING: Symbol version dump $(objtree)/Module.symvers"; \ + echo " is missing; modules will have no dependencies and modversions."; \ + echo ) + +module-dirs := $(addprefix _module_,$(KBUILD_EXTMOD)) +PHONY += $(module-dirs) modules +$(module-dirs): crmodverdir $(objtree)/Module.symvers + $(Q)$(MAKE) $(build)=$(patsubst _module_%,%,$@) + +modules: $(module-dirs) + @$(kecho) ' Building modules, stage 2.'; + $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost + +PHONY += modules_install +modules_install: _emodinst_ _emodinst_post + +install-dir := $(if $(INSTALL_MOD_DIR),$(INSTALL_MOD_DIR),extra) +PHONY += _emodinst_ +_emodinst_: + $(Q)mkdir -p $(MODLIB)/$(install-dir) + $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modinst + +PHONY += _emodinst_post +_emodinst_post: _emodinst_ + $(call cmd,depmod) + +clean-dirs := $(addprefix _clean_,$(KBUILD_EXTMOD)) + +PHONY += $(clean-dirs) clean +$(clean-dirs): + $(Q)$(MAKE) $(clean)=$(patsubst _clean_%,%,$@) + +clean: rm-dirs := $(MODVERDIR) +clean: rm-files := $(KBUILD_EXTMOD)/Module.symvers + +help: + @echo ' Building external modules.' + @echo ' Syntax: make -C path/to/kernel/src M=$$PWD target' + @echo '' + @echo ' modules - default target, build the module(s)' + @echo ' modules_install - install the module' + @echo ' clean - remove generated files in module directory only' + @echo '' + +# Dummies... +PHONY += prepare scripts +prepare: ; +scripts: ; +endif # KBUILD_EXTMOD + +clean: $(clean-dirs) + $(Q)$(CONFIG_SHELL) $(srctree)/scripts/link-vmlinux.sh clean + $(call cmd,rmdirs) + $(call cmd,rmfiles) + @find $(if $(KBUILD_EXTMOD), $(KBUILD_EXTMOD), .) $(RCS_FIND_IGNORE) \ + \( -name '*.[oas]' -o -name '*.ko' -o -name '.*.cmd' \ + -o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \ + -o -name '*.symtypes' -o -name 'modules.order' \ + -o -name modules.builtin -o -name '.tmp_*.o.*' \ + -o -name '*.gcno' \) -type f -print | xargs rm -f + +# Generate tags for editors +# --------------------------------------------------------------------------- +quiet_cmd_tags = GEN $@ + cmd_tags = $(CONFIG_SHELL) $(srctree)/scripts/tags.sh $@ + +tags TAGS cscope gtags: FORCE + $(call cmd,tags) + +# Scripts to check various things for consistency +# --------------------------------------------------------------------------- + +PHONY += includecheck versioncheck coccicheck namespacecheck export_report + +includecheck: + find $(srctree)/* $(RCS_FIND_IGNORE) \ + -name '*.[hcS]' -type f -print | sort \ + | xargs $(PERL) -w $(srctree)/scripts/checkincludes.pl + +versioncheck: + find $(srctree)/* $(RCS_FIND_IGNORE) \ + -name '*.[hcS]' -type f -print | sort \ + | xargs $(PERL) -w $(srctree)/scripts/checkversion.pl + +coccicheck: + $(Q)$(CONFIG_SHELL) $(srctree)/scripts/$@ + +namespacecheck: + $(PERL) $(srctree)/scripts/namespace.pl + +export_report: + $(PERL) $(srctree)/scripts/export_report.pl + +endif #ifeq ($(config-targets),1) +endif #ifeq ($(mixed-targets),1) + +PHONY += checkstack kernelrelease kernelversion + +# UML needs a little special treatment here. It wants to use the host +# toolchain, so needs $(SUBARCH) passed to checkstack.pl. Everyone +# else wants $(ARCH), including people doing cross-builds, which means +# that $(SUBARCH) doesn't work here. +ifeq ($(ARCH), um) +CHECKSTACK_ARCH := $(SUBARCH) +else +CHECKSTACK_ARCH := $(ARCH) +endif +checkstack: + $(OBJDUMP) -d vmlinux $$(find . -name '*.ko') | \ + $(PERL) $(src)/scripts/checkstack.pl $(CHECKSTACK_ARCH) + +kernelrelease: + @echo "$(KERNELVERSION)$$($(CONFIG_SHELL) $(srctree)/scripts/setlocalversion $(srctree))" + +kernelversion: + @echo $(KERNELVERSION) + +# Clear a bunch of variables before executing the submake +tools/: FORCE + $(Q)$(MAKE) LDFLAGS= MAKEFLAGS= -C $(src)/tools/ + +tools/%: FORCE + $(Q)$(MAKE) LDFLAGS= MAKEFLAGS= -C $(src)/tools/ $* + +# Single targets +# --------------------------------------------------------------------------- +# Single targets are compatible with: +# - build with mixed source and output +# - build with separate output dir 'make O=...' +# - external modules +# +# target-dir => where to store outputfile +# build-dir => directory in kernel source tree to use + +ifeq ($(KBUILD_EXTMOD),) + build-dir = $(patsubst %/,%,$(dir $@)) + target-dir = $(dir $@) +else + zap-slash=$(filter-out .,$(patsubst %/,%,$(dir $@))) + build-dir = $(KBUILD_EXTMOD)$(if $(zap-slash),/$(zap-slash)) + target-dir = $(if $(KBUILD_EXTMOD),$(dir $<),$(dir $@)) +endif + +%.s: %.c prepare scripts FORCE + $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@) +%.i: %.c prepare scripts FORCE + $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@) +%.o: %.c prepare scripts FORCE + $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@) +%.lst: %.c prepare scripts FORCE + $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@) +%.s: %.S prepare scripts FORCE + $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@) +%.o: %.S prepare scripts FORCE + $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@) +%.symtypes: %.c prepare scripts FORCE + $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@) + +# Modules +/: prepare scripts FORCE + $(cmd_crmodverdir) + $(Q)$(MAKE) KBUILD_MODULES=$(if $(CONFIG_MODULES),1) \ + $(build)=$(build-dir) +%/: prepare scripts FORCE + $(cmd_crmodverdir) + $(Q)$(MAKE) KBUILD_MODULES=$(if $(CONFIG_MODULES),1) \ + $(build)=$(build-dir) +%.ko: prepare scripts FORCE + $(cmd_crmodverdir) + $(Q)$(MAKE) KBUILD_MODULES=$(if $(CONFIG_MODULES),1) \ + $(build)=$(build-dir) $(@:.ko=.o) + $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost + +# FIXME Should go into a make.lib or something +# =========================================================================== + +quiet_cmd_rmdirs = $(if $(wildcard $(rm-dirs)),CLEAN $(wildcard $(rm-dirs))) + cmd_rmdirs = rm -rf $(rm-dirs) + +quiet_cmd_rmfiles = $(if $(wildcard $(rm-files)),CLEAN $(wildcard $(rm-files))) + cmd_rmfiles = rm -f $(rm-files) + +# Run depmod only if we have System.map and depmod is executable +quiet_cmd_depmod = DEPMOD $(KERNELRELEASE) + cmd_depmod = $(CONFIG_SHELL) $(srctree)/scripts/depmod.sh $(DEPMOD) \ + $(KERNELRELEASE) + +# Create temporary dir for module support files +# clean it up only when building all modules +cmd_crmodverdir = $(Q)mkdir -p $(MODVERDIR) \ + $(if $(KBUILD_MODULES),; rm -f $(MODVERDIR)/*) + +# read all saved command lines + +targets := $(wildcard $(sort $(targets))) +cmd_files := $(wildcard .*.cmd $(foreach f,$(targets),$(dir $(f)).$(notdir $(f)).cmd)) + +ifneq ($(cmd_files),) + $(cmd_files): ; # Do not try to update included dependency files + include $(cmd_files) +endif + +# Shorthand for $(Q)$(MAKE) -f scripts/Makefile.clean obj=dir +# Usage: +# $(Q)$(MAKE) $(clean)=dir +clean := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.clean obj + +endif # skip-makefile + +PHONY += FORCE +FORCE: + +# Declare the contents of the .PHONY variable as phony. We keep that +# information in a variable so we can use it in if_changed and friends. +.PHONY: $(PHONY) diff --git a/kernel/fiasco/tool/kconfig/README b/kernel/fiasco/tool/kconfig/README new file mode 100644 index 00000000..cebd46b7 --- /dev/null +++ b/kernel/fiasco/tool/kconfig/README @@ -0,0 +1,3 @@ + +kconfig taken from vanilla Linux 3.5, and slightly patched. + diff --git a/kernel/fiasco/tool/kconfig/scripts/Kbuild.include b/kernel/fiasco/tool/kconfig/scripts/Kbuild.include new file mode 100644 index 00000000..6a3ee981 --- /dev/null +++ b/kernel/fiasco/tool/kconfig/scripts/Kbuild.include @@ -0,0 +1,278 @@ +#### +# kbuild: Generic definitions + +# Convenient variables +comma := , +squote := ' +empty := +space := $(empty) $(empty) + +### +# Name of target with a '.' as filename prefix. foo/bar.o => foo/.bar.o +dot-target = $(dir $@).$(notdir $@) + +### +# The temporary file to save gcc -MD generated dependencies must not +# contain a comma +depfile = $(subst $(comma),_,$(dot-target).d) + +### +# filename of target with directory and extension stripped +basetarget = $(basename $(notdir $@)) + +### +# filename of first prerequisite with directory and extension stripped +baseprereq = $(basename $(notdir $<)) + +### +# Escape single quote for use in echo statements +escsq = $(subst $(squote),'\$(squote)',$1) + +### +# Easy method for doing a status message + kecho := : + quiet_kecho := echo +silent_kecho := : +kecho := $($(quiet)kecho) + +### +# filechk is used to check if the content of a generated file is updated. +# Sample usage: +# define filechk_sample +# echo $KERNELRELEASE +# endef +# version.h : Makefile +# $(call filechk,sample) +# The rule defined shall write to stdout the content of the new file. +# The existing file will be compared with the new one. +# - If no file exist it is created +# - If the content differ the new file is used +# - If they are equal no change, and no timestamp update +# - stdin is piped in from the first prerequisite ($<) so one has +# to specify a valid file as first prerequisite (often the kbuild file) +define filechk + $(Q)set -e; \ + $(kecho) ' CHK $@'; \ + mkdir -p $(dir $@); \ + $(filechk_$(1)) < $< > $@.tmp; \ + if [ -r $@ ] && cmp -s $@ $@.tmp; then \ + rm -f $@.tmp; \ + else \ + $(kecho) ' UPD $@'; \ + mv -f $@.tmp $@; \ + fi +endef + +###### +# gcc support functions +# See documentation in Documentation/kbuild/makefiles.txt + +# cc-cross-prefix +# Usage: CROSS_COMPILE := $(call cc-cross-prefix, m68k-linux-gnu- m68k-linux-) +# Return first prefix where a prefix$(CC) is found in PATH. +# If no $(CC) found in PATH with listed prefixes return nothing +cc-cross-prefix = \ + $(word 1, $(foreach c,$(1), \ + $(shell set -e; \ + if (which $(strip $(c))$(CC)) > /dev/null 2>&1 ; then \ + echo $(c); \ + fi))) + +# output directory for tests below +TMPOUT := $(if $(KBUILD_EXTMOD),$(firstword $(KBUILD_EXTMOD))/) + +# try-run +# Usage: option = $(call try-run, $(CC)...-o "$$TMP",option-ok,otherwise) +# Exit code chooses option. "$$TMP" is can be used as temporary file and +# is automatically cleaned up. +try-run = $(shell set -e; \ + TMP="$(TMPOUT).$$$$.tmp"; \ + TMPO="$(TMPOUT).$$$$.o"; \ + if ($(1)) >/dev/null 2>&1; \ + then echo "$(2)"; \ + else echo "$(3)"; \ + fi; \ + rm -f "$$TMP" "$$TMPO") + +# as-option +# Usage: cflags-y += $(call as-option,-Wa$(comma)-isa=foo,) + +as-option = $(call try-run,\ + $(CC) $(KBUILD_CFLAGS) $(1) -c -xassembler /dev/null -o "$$TMP",$(1),$(2)) + +# as-instr +# Usage: cflags-y += $(call as-instr,instr,option1,option2) + +as-instr = $(call try-run,\ + printf "%b\n" "$(1)" | $(CC) $(KBUILD_AFLAGS) -c -xassembler -o "$$TMP" -,$(2),$(3)) + +# cc-option +# Usage: cflags-y += $(call cc-option,-march=winchip-c6,-march=i586) + +cc-option = $(call try-run,\ + $(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) $(1) -c -xc /dev/null -o "$$TMP",$(1),$(2)) + +# cc-option-yn +# Usage: flag := $(call cc-option-yn,-march=winchip-c6) +cc-option-yn = $(call try-run,\ + $(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) $(1) -c -xc /dev/null -o "$$TMP",y,n) + +# cc-option-align +# Prefix align with either -falign or -malign +cc-option-align = $(subst -functions=0,,\ + $(call cc-option,-falign-functions=0,-malign-functions=0)) + +# cc-disable-warning +# Usage: cflags-y += $(call cc-disable-warning,unused-but-set-variable) +cc-disable-warning = $(call try-run,\ + $(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) -W$(strip $(1)) -c -xc /dev/null -o "$$TMP",-Wno-$(strip $(1))) + +# cc-version +# Usage gcc-ver := $(call cc-version) +cc-version = $(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-version.sh $(CC)) + +# cc-fullversion +# Usage gcc-ver := $(call cc-fullversion) +cc-fullversion = $(shell $(CONFIG_SHELL) \ + $(srctree)/scripts/gcc-version.sh -p $(CC)) + +# cc-ifversion +# Usage: EXTRA_CFLAGS += $(call cc-ifversion, -lt, 0402, -O1) +cc-ifversion = $(shell [ $(call cc-version, $(CC)) $(1) $(2) ] && echo $(3)) + +# cc-ldoption +# Usage: ldflags += $(call cc-ldoption, -Wl$(comma)--hash-style=both) +cc-ldoption = $(call try-run,\ + $(CC) $(1) -nostdlib -xc /dev/null -o "$$TMP",$(1),$(2)) + +# ld-option +# Usage: LDFLAGS += $(call ld-option, -X) +ld-option = $(call try-run,\ + $(CC) /dev/null -c -o "$$TMPO" ; $(LD) $(1) "$$TMPO" -o "$$TMP",$(1),$(2)) + +# ar-option +# Usage: KBUILD_ARFLAGS := $(call ar-option,D) +# Important: no spaces around options +ar-option = $(call try-run, $(AR) rc$(1) "$$TMP",$(1),$(2)) + +###### + +### +# Shorthand for $(Q)$(MAKE) -f scripts/Makefile.build obj= +# Usage: +# $(Q)$(MAKE) $(build)=dir +build := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.build obj + +### +# Shorthand for $(Q)$(MAKE) -f scripts/Makefile.modbuiltin obj= +# Usage: +# $(Q)$(MAKE) $(modbuiltin)=dir +modbuiltin := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.modbuiltin obj + +# Prefix -I with $(srctree) if it is not an absolute path. +# skip if -I has no parameter +addtree = $(if $(patsubst -I%,%,$(1)), \ +$(if $(filter-out -I/%,$(1)),$(patsubst -I%,-I$(srctree)/%,$(1))) $(1)) + +# Find all -I options and call addtree +flags = $(foreach o,$($(1)),$(if $(filter -I%,$(o)),$(call addtree,$(o)),$(o))) + +# echo command. +# Short version is used, if $(quiet) equals `quiet_', otherwise full one. +echo-cmd = $(if $($(quiet)cmd_$(1)),\ + echo ' $(call escsq,$($(quiet)cmd_$(1)))$(echo-why)';) + +# printing commands +cmd = @$(echo-cmd) $(cmd_$(1)) + +# Add $(obj)/ for paths that are not absolute +objectify = $(foreach o,$(1),$(if $(filter /%,$(o)),$(o),$(obj)/$(o))) + +### +# if_changed - execute command if any prerequisite is newer than +# target, or command line has changed +# if_changed_dep - as if_changed, but uses fixdep to reveal dependencies +# including used config symbols +# if_changed_rule - as if_changed but execute rule instead +# See Documentation/kbuild/makefiles.txt for more info + +ifneq ($(KBUILD_NOCMDDEP),1) +# Check if both arguments has same arguments. Result is empty string if equal. +# User may override this check using make KBUILD_NOCMDDEP=1 +arg-check = $(strip $(filter-out $(cmd_$(1)), $(cmd_$@)) \ + $(filter-out $(cmd_$@), $(cmd_$(1))) ) +else +arg-check = $(if $(strip $(cmd_$@)),,1) +endif + +# >'< substitution is for echo to work, +# >$< substitution to preserve $ when reloading .cmd file +# note: when using inline perl scripts [perl -e '...$$t=1;...'] +# in $(cmd_xxx) double $$ your perl vars +make-cmd = $(subst \#,\\\#,$(subst $$,$$$$,$(call escsq,$(cmd_$(1))))) + +# Find any prerequisites that is newer than target or that does not exist. +# PHONY targets skipped in both cases. +any-prereq = $(filter-out $(PHONY),$?) $(filter-out $(PHONY) $(wildcard $^),$^) + +# Execute command if command has changed or prerequisite(s) are updated. +# +if_changed = $(if $(strip $(any-prereq) $(arg-check)), \ + @set -e; \ + $(echo-cmd) $(cmd_$(1)); \ + echo 'cmd_$@ := $(make-cmd)' > $(dot-target).cmd) + +# Execute the command and also postprocess generated .d dependencies file. +if_changed_dep = $(if $(strip $(any-prereq) $(arg-check) ), \ + @set -e; \ + $(echo-cmd) $(cmd_$(1)); \ + scripts/basic/fixdep $(depfile) $@ '$(make-cmd)' > $(dot-target).tmp;\ + rm -f $(depfile); \ + mv -f $(dot-target).tmp $(dot-target).cmd) + +# Usage: $(call if_changed_rule,foo) +# Will check if $(cmd_foo) or any of the prerequisites changed, +# and if so will execute $(rule_foo). +if_changed_rule = $(if $(strip $(any-prereq) $(arg-check) ), \ + @set -e; \ + $(rule_$(1))) + +### +# why - tell why a a target got build +# enabled by make V=2 +# Output (listed in the order they are checked): +# (1) - due to target is PHONY +# (2) - due to target missing +# (3) - due to: file1.h file2.h +# (4) - due to command line change +# (5) - due to missing .cmd file +# (6) - due to target not in $(targets) +# (1) PHONY targets are always build +# (2) No target, so we better build it +# (3) Prerequisite is newer than target +# (4) The command line stored in the file named dir/.target.cmd +# differed from actual command line. This happens when compiler +# options changes +# (5) No dir/.target.cmd file (used to store command line) +# (6) No dir/.target.cmd file and target not listed in $(targets) +# This is a good hint that there is a bug in the kbuild file +ifeq ($(KBUILD_VERBOSE),2) +why = \ + $(if $(filter $@, $(PHONY)),- due to target is PHONY, \ + $(if $(wildcard $@), \ + $(if $(strip $(any-prereq)),- due to: $(any-prereq), \ + $(if $(arg-check), \ + $(if $(cmd_$@),- due to command line change, \ + $(if $(filter $@, $(targets)), \ + - due to missing .cmd file, \ + - due to $(notdir $@) not in $$(targets) \ + ) \ + ) \ + ) \ + ), \ + - due to target missing \ + ) \ + ) + +echo-why = $(call escsq, $(strip $(why))) +endif diff --git a/kernel/fiasco/tool/kconfig/scripts/Makefile b/kernel/fiasco/tool/kconfig/scripts/Makefile new file mode 100644 index 00000000..a55b0067 --- /dev/null +++ b/kernel/fiasco/tool/kconfig/scripts/Makefile @@ -0,0 +1,40 @@ +### +# scripts contains sources for various helper programs used throughout +# the kernel for the build process. +# --------------------------------------------------------------------------- +# kallsyms: Find all symbols in vmlinux +# pnmttologo: Convert pnm files to logo files +# conmakehash: Create chartable +# conmakehash: Create arrays for initializing the kernel console tables +# docproc: Used in Documentation/DocBook + +HOST_EXTRACFLAGS += -I$(srctree)/tools/include + +hostprogs-$(CONFIG_KALLSYMS) += kallsyms +hostprogs-$(CONFIG_LOGO) += pnmtologo +hostprogs-$(CONFIG_VT) += conmakehash +hostprogs-$(CONFIG_IKCONFIG) += bin2c +hostprogs-$(BUILD_C_RECORDMCOUNT) += recordmcount +hostprogs-$(CONFIG_BUILDTIME_EXTABLE_SORT) += sortextable + +HOSTCFLAGS_sortextable.o = -I$(srctree)/tools/include + +always := $(hostprogs-y) $(hostprogs-m) + +# The following hostprogs-y programs are only build on demand +hostprogs-y += unifdef docproc + +# These targets are used internally to avoid "is up to date" messages +PHONY += build_unifdef +build_unifdef: scripts/unifdef FORCE + @: +build_docproc: scripts/docproc FORCE + @: + +subdir-$(CONFIG_MODVERSIONS) += genksyms +subdir-y += mod +subdir-$(CONFIG_SECURITY_SELINUX) += selinux +subdir-$(CONFIG_DTC) += dtc + +# Let clean descend into subdirs +subdir- += basic kconfig package selinux diff --git a/kernel/fiasco/tool/kconfig/scripts/Makefile.build b/kernel/fiasco/tool/kconfig/scripts/Makefile.build new file mode 100644 index 00000000..ff1720d2 --- /dev/null +++ b/kernel/fiasco/tool/kconfig/scripts/Makefile.build @@ -0,0 +1,467 @@ +# ========================================================================== +# Building +# ========================================================================== + +src := $(obj) + +PHONY := __build +__build: + +# Init all relevant variables used in kbuild files so +# 1) they have correct type +# 2) they do not inherit any value from the environment +obj-y := +obj-m := +lib-y := +lib-m := +always := +targets := +subdir-y := +subdir-m := +EXTRA_AFLAGS := +EXTRA_CFLAGS := +EXTRA_CPPFLAGS := +EXTRA_LDFLAGS := +asflags-y := +ccflags-y := +cppflags-y := +ldflags-y := + +subdir-asflags-y := +subdir-ccflags-y := + +# Read auto.conf if it exists, otherwise ignore +-include include/config/auto.conf + +include scripts/Kbuild.include + +# For backward compatibility check that these variables do not change +save-cflags := $(CFLAGS) + +# The filename Kbuild has precedence over Makefile +kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src)) +kbuild-file := $(if $(wildcard $(kbuild-dir)/Kbuild),$(kbuild-dir)/Kbuild,$(kbuild-dir)/Makefile) +include $(kbuild-file) + +# If the save-* variables changed error out +ifeq ($(KBUILD_NOPEDANTIC),) + ifneq ("$(save-cflags)","$(CFLAGS)") + $(error CFLAGS was changed in "$(kbuild-file)". Fix it to use ccflags-y) + endif +endif + +# +# make W=... settings +# +# W=1 - warnings that may be relevant and does not occur too often +# W=2 - warnings that occur quite often but may still be relevant +# W=3 - the more obscure warnings, can most likely be ignored +# +# $(call cc-option, -W...) handles gcc -W.. options which +# are not supported by all versions of the compiler +ifdef KBUILD_ENABLE_EXTRA_GCC_CHECKS +warning- := $(empty) + +warning-1 := -Wextra -Wunused -Wno-unused-parameter +warning-1 += -Wmissing-declarations +warning-1 += -Wmissing-format-attribute +warning-1 += -Wmissing-prototypes +warning-1 += -Wold-style-definition +warning-1 += $(call cc-option, -Wmissing-include-dirs) +warning-1 += $(call cc-option, -Wunused-but-set-variable) +warning-1 += $(call cc-disable-warning, missing-field-initializers) + +warning-2 := -Waggregate-return +warning-2 += -Wcast-align +warning-2 += -Wdisabled-optimization +warning-2 += -Wnested-externs +warning-2 += -Wshadow +warning-2 += $(call cc-option, -Wlogical-op) +warning-2 += $(call cc-option, -Wmissing-field-initializers) + +warning-3 := -Wbad-function-cast +warning-3 += -Wcast-qual +warning-3 += -Wconversion +warning-3 += -Wpacked +warning-3 += -Wpadded +warning-3 += -Wpointer-arith +warning-3 += -Wredundant-decls +warning-3 += -Wswitch-default +warning-3 += $(call cc-option, -Wpacked-bitfield-compat) +warning-3 += $(call cc-option, -Wvla) + +warning := $(warning-$(findstring 1, $(KBUILD_ENABLE_EXTRA_GCC_CHECKS))) +warning += $(warning-$(findstring 2, $(KBUILD_ENABLE_EXTRA_GCC_CHECKS))) +warning += $(warning-$(findstring 3, $(KBUILD_ENABLE_EXTRA_GCC_CHECKS))) + +ifeq ("$(strip $(warning))","") + $(error W=$(KBUILD_ENABLE_EXTRA_GCC_CHECKS) is unknown) +endif + +KBUILD_CFLAGS += $(warning) +endif + +include scripts/Makefile.lib + +ifdef host-progs +ifneq ($(hostprogs-y),$(host-progs)) +$(warning kbuild: $(obj)/Makefile - Usage of host-progs is deprecated. Please replace with hostprogs-y!) +hostprogs-y += $(host-progs) +endif +endif + +# Do not include host rules unless needed +ifneq ($(hostprogs-y)$(hostprogs-m),) +include scripts/Makefile.host +endif + +ifneq ($(KBUILD_SRC),) +# Create output directory if not already present +_dummy := $(shell [ -d $(obj) ] || mkdir -p $(obj)) + +# Create directories for object files if directory does not exist +# Needed when obj-y := dir/file.o syntax is used +_dummy := $(foreach d,$(obj-dirs), $(shell [ -d $(d) ] || mkdir -p $(d))) +endif + +ifndef obj +$(warning kbuild: Makefile.build is included improperly) +endif + +# =========================================================================== + +ifneq ($(strip $(lib-y) $(lib-m) $(lib-n) $(lib-)),) +lib-target := $(obj)/lib.a +endif + +ifneq ($(strip $(obj-y) $(obj-m) $(obj-n) $(obj-) $(subdir-m) $(lib-target)),) +builtin-target := $(obj)/built-in.o +endif + +modorder-target := $(obj)/modules.order + +# We keep a list of all modules in $(MODVERDIR) + +__build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y)) \ + $(if $(KBUILD_MODULES),$(obj-m) $(modorder-target)) \ + $(subdir-ym) $(always) + @: + +# Linus' kernel sanity checking tool +ifneq ($(KBUILD_CHECKSRC),0) + ifeq ($(KBUILD_CHECKSRC),2) + quiet_cmd_force_checksrc = CHECK $< + cmd_force_checksrc = $(CHECK) $(CHECKFLAGS) $(c_flags) $< ; + else + quiet_cmd_checksrc = CHECK $< + cmd_checksrc = $(CHECK) $(CHECKFLAGS) $(c_flags) $< ; + endif +endif + +# Do section mismatch analysis for each module/built-in.o +ifdef CONFIG_DEBUG_SECTION_MISMATCH + cmd_secanalysis = ; scripts/mod/modpost $@ +endif + +# Compile C sources (.c) +# --------------------------------------------------------------------------- + +# Default is built-in, unless we know otherwise +modkern_cflags = \ + $(if $(part-of-module), \ + $(KBUILD_CFLAGS_MODULE) $(CFLAGS_MODULE), \ + $(KBUILD_CFLAGS_KERNEL) $(CFLAGS_KERNEL)) +quiet_modtag := $(empty) $(empty) + +$(real-objs-m) : part-of-module := y +$(real-objs-m:.o=.i) : part-of-module := y +$(real-objs-m:.o=.s) : part-of-module := y +$(real-objs-m:.o=.lst): part-of-module := y + +$(real-objs-m) : quiet_modtag := [M] +$(real-objs-m:.o=.i) : quiet_modtag := [M] +$(real-objs-m:.o=.s) : quiet_modtag := [M] +$(real-objs-m:.o=.lst): quiet_modtag := [M] + +$(obj-m) : quiet_modtag := [M] + +# Default for not multi-part modules +modname = $(basetarget) + +$(multi-objs-m) : modname = $(modname-multi) +$(multi-objs-m:.o=.i) : modname = $(modname-multi) +$(multi-objs-m:.o=.s) : modname = $(modname-multi) +$(multi-objs-m:.o=.lst) : modname = $(modname-multi) +$(multi-objs-y) : modname = $(modname-multi) +$(multi-objs-y:.o=.i) : modname = $(modname-multi) +$(multi-objs-y:.o=.s) : modname = $(modname-multi) +$(multi-objs-y:.o=.lst) : modname = $(modname-multi) + +quiet_cmd_cc_s_c = CC $(quiet_modtag) $@ +cmd_cc_s_c = $(CC) $(c_flags) -fverbose-asm -S -o $@ $< + +$(obj)/%.s: $(src)/%.c FORCE + $(call if_changed_dep,cc_s_c) + +quiet_cmd_cc_i_c = CPP $(quiet_modtag) $@ +cmd_cc_i_c = $(CPP) $(c_flags) -o $@ $< + +$(obj)/%.i: $(src)/%.c FORCE + $(call if_changed_dep,cc_i_c) + +cmd_gensymtypes = \ + $(CPP) -D__GENKSYMS__ $(c_flags) $< | \ + $(GENKSYMS) $(if $(1), -T $(2)) -a $(ARCH) \ + $(if $(KBUILD_PRESERVE),-p) \ + -r $(firstword $(wildcard $(2:.symtypes=.symref) /dev/null)) + +quiet_cmd_cc_symtypes_c = SYM $(quiet_modtag) $@ +cmd_cc_symtypes_c = \ + set -e; \ + $(call cmd_gensymtypes,true,$@) >/dev/null; \ + test -s $@ || rm -f $@ + +$(obj)/%.symtypes : $(src)/%.c FORCE + $(call cmd,cc_symtypes_c) + +# C (.c) files +# The C file is compiled and updated dependency information is generated. +# (See cmd_cc_o_c + relevant part of rule_cc_o_c) + +quiet_cmd_cc_o_c = CC $(quiet_modtag) $@ + +ifndef CONFIG_MODVERSIONS +cmd_cc_o_c = $(CC) $(c_flags) -c -o $@ $< + +else +# When module versioning is enabled the following steps are executed: +# o compile a .tmp_.o from .c +# o if .tmp_.o doesn't contain a __ksymtab version, i.e. does +# not export symbols, we just rename .tmp_.o to .o and +# are done. +# o otherwise, we calculate symbol versions using the good old +# genksyms on the preprocessed source and postprocess them in a way +# that they are usable as a linker script +# o generate .o from .tmp_.o using the linker to +# replace the unresolved symbols __crc_exported_symbol with +# the actual value of the checksum generated by genksyms + +cmd_cc_o_c = $(CC) $(c_flags) -c -o $(@D)/.tmp_$(@F) $< +cmd_modversions = \ + if $(OBJDUMP) -h $(@D)/.tmp_$(@F) | grep -q __ksymtab; then \ + $(call cmd_gensymtypes,$(KBUILD_SYMTYPES),$(@:.o=.symtypes)) \ + > $(@D)/.tmp_$(@F:.o=.ver); \ + \ + $(LD) $(LDFLAGS) -r -o $@ $(@D)/.tmp_$(@F) \ + -T $(@D)/.tmp_$(@F:.o=.ver); \ + rm -f $(@D)/.tmp_$(@F) $(@D)/.tmp_$(@F:.o=.ver); \ + else \ + mv -f $(@D)/.tmp_$(@F) $@; \ + fi; +endif + +ifdef CONFIG_FTRACE_MCOUNT_RECORD +ifdef BUILD_C_RECORDMCOUNT +ifeq ("$(origin RECORDMCOUNT_WARN)", "command line") + RECORDMCOUNT_FLAGS = -w +endif +# Due to recursion, we must skip empty.o. +# The empty.o file is created in the make process in order to determine +# the target endianness and word size. It is made before all other C +# files, including recordmcount. +sub_cmd_record_mcount = \ + if [ $(@) != "scripts/mod/empty.o" ]; then \ + $(objtree)/scripts/recordmcount $(RECORDMCOUNT_FLAGS) "$(@)"; \ + fi; +recordmcount_source := $(srctree)/scripts/recordmcount.c \ + $(srctree)/scripts/recordmcount.h +else +sub_cmd_record_mcount = set -e ; perl $(srctree)/scripts/recordmcount.pl "$(ARCH)" \ + "$(if $(CONFIG_CPU_BIG_ENDIAN),big,little)" \ + "$(if $(CONFIG_64BIT),64,32)" \ + "$(OBJDUMP)" "$(OBJCOPY)" "$(CC) $(KBUILD_CFLAGS)" \ + "$(LD)" "$(NM)" "$(RM)" "$(MV)" \ + "$(if $(part-of-module),1,0)" "$(@)"; +recordmcount_source := $(srctree)/scripts/recordmcount.pl +endif +cmd_record_mcount = \ + if [ "$(findstring -pg,$(_c_flags))" = "-pg" ]; then \ + $(sub_cmd_record_mcount) \ + fi; +endif + +define rule_cc_o_c + $(call echo-cmd,checksrc) $(cmd_checksrc) \ + $(call echo-cmd,cc_o_c) $(cmd_cc_o_c); \ + $(cmd_modversions) \ + $(call echo-cmd,record_mcount) \ + $(cmd_record_mcount) \ + scripts/basic/fixdep $(depfile) $@ '$(call make-cmd,cc_o_c)' > \ + $(dot-target).tmp; \ + rm -f $(depfile); \ + mv -f $(dot-target).tmp $(dot-target).cmd +endef + +# Built-in and composite module parts +$(obj)/%.o: $(src)/%.c $(recordmcount_source) FORCE + $(call cmd,force_checksrc) + $(call if_changed_rule,cc_o_c) + +# Single-part modules are special since we need to mark them in $(MODVERDIR) + +$(single-used-m): $(obj)/%.o: $(src)/%.c $(recordmcount_source) FORCE + $(call cmd,force_checksrc) + $(call if_changed_rule,cc_o_c) + @{ echo $(@:.o=.ko); echo $@; } > $(MODVERDIR)/$(@F:.o=.mod) + +quiet_cmd_cc_lst_c = MKLST $@ + cmd_cc_lst_c = $(CC) $(c_flags) -g -c -o $*.o $< && \ + $(CONFIG_SHELL) $(srctree)/scripts/makelst $*.o \ + System.map $(OBJDUMP) > $@ + +$(obj)/%.lst: $(src)/%.c FORCE + $(call if_changed_dep,cc_lst_c) + +# Compile assembler sources (.S) +# --------------------------------------------------------------------------- + +modkern_aflags := $(KBUILD_AFLAGS_KERNEL) $(AFLAGS_KERNEL) + +$(real-objs-m) : modkern_aflags := $(KBUILD_AFLAGS_MODULE) $(AFLAGS_MODULE) +$(real-objs-m:.o=.s): modkern_aflags := $(KBUILD_AFLAGS_MODULE) $(AFLAGS_MODULE) + +quiet_cmd_as_s_S = CPP $(quiet_modtag) $@ +cmd_as_s_S = $(CPP) $(a_flags) -o $@ $< + +$(obj)/%.s: $(src)/%.S FORCE + $(call if_changed_dep,as_s_S) + +quiet_cmd_as_o_S = AS $(quiet_modtag) $@ +cmd_as_o_S = $(CC) $(a_flags) -c -o $@ $< + +$(obj)/%.o: $(src)/%.S FORCE + $(call if_changed_dep,as_o_S) + +targets += $(real-objs-y) $(real-objs-m) $(lib-y) +targets += $(extra-y) $(MAKECMDGOALS) $(always) + +# Linker scripts preprocessor (.lds.S -> .lds) +# --------------------------------------------------------------------------- +quiet_cmd_cpp_lds_S = LDS $@ + cmd_cpp_lds_S = $(CPP) $(cpp_flags) -P -C -U$(ARCH) \ + -D__ASSEMBLY__ -DLINKER_SCRIPT -o $@ $< + +$(obj)/%.lds: $(src)/%.lds.S FORCE + $(call if_changed_dep,cpp_lds_S) + +# Build the compiled-in targets +# --------------------------------------------------------------------------- + +# To build objects in subdirs, we need to descend into the directories +$(sort $(subdir-obj-y)): $(subdir-ym) ; + +# +# Rule to compile a set of .o files into one .o file +# +ifdef builtin-target +quiet_cmd_link_o_target = LD $@ +# If the list of objects to link is empty, just create an empty built-in.o +cmd_link_o_target = $(if $(strip $(obj-y)),\ + $(LD) $(ld_flags) -r -o $@ $(filter $(obj-y), $^) \ + $(cmd_secanalysis),\ + rm -f $@; $(AR) rcs$(KBUILD_ARFLAGS) $@) + +$(builtin-target): $(obj-y) FORCE + $(call if_changed,link_o_target) + +targets += $(builtin-target) +endif # builtin-target + +# +# Rule to create modules.order file +# +# Create commands to either record .ko file or cat modules.order from +# a subdirectory +modorder-cmds = \ + $(foreach m, $(modorder), \ + $(if $(filter %/modules.order, $m), \ + cat $m;, echo kernel/$m;)) + +$(modorder-target): $(subdir-ym) FORCE + $(Q)(cat /dev/null; $(modorder-cmds)) > $@ + +# +# Rule to compile a set of .o files into one .a file +# +ifdef lib-target +quiet_cmd_link_l_target = AR $@ +cmd_link_l_target = rm -f $@; $(AR) rcs$(KBUILD_ARFLAGS) $@ $(lib-y) + +$(lib-target): $(lib-y) FORCE + $(call if_changed,link_l_target) + +targets += $(lib-target) +endif + +# +# Rule to link composite objects +# +# Composite objects are specified in kbuild makefile as follows: +# -objs := +# or +# -y := +link_multi_deps = \ +$(filter $(addprefix $(obj)/, \ +$($(subst $(obj)/,,$(@:.o=-objs))) \ +$($(subst $(obj)/,,$(@:.o=-y)))), $^) + +quiet_cmd_link_multi-y = LD $@ +cmd_link_multi-y = $(LD) $(ld_flags) -r -o $@ $(link_multi_deps) $(cmd_secanalysis) + +quiet_cmd_link_multi-m = LD [M] $@ +cmd_link_multi-m = $(cmd_link_multi-y) + +# We would rather have a list of rules like +# foo.o: $(foo-objs) +# but that's not so easy, so we rather make all composite objects depend +# on the set of all their parts +$(multi-used-y) : %.o: $(multi-objs-y) FORCE + $(call if_changed,link_multi-y) + +$(multi-used-m) : %.o: $(multi-objs-m) FORCE + $(call if_changed,link_multi-m) + @{ echo $(@:.o=.ko); echo $(link_multi_deps); } > $(MODVERDIR)/$(@F:.o=.mod) + +targets += $(multi-used-y) $(multi-used-m) + + +# Descending +# --------------------------------------------------------------------------- + +PHONY += $(subdir-ym) +$(subdir-ym): + $(Q)$(MAKE) $(build)=$@ + +# Add FORCE to the prequisites of a target to force it to be always rebuilt. +# --------------------------------------------------------------------------- + +PHONY += FORCE + +FORCE: + +# Read all saved command lines and dependencies for the $(targets) we +# may be building above, using $(if_changed{,_dep}). As an +# optimization, we don't need to read them if the target does not +# exist, we will rebuild anyway in that case. + +targets := $(wildcard $(sort $(targets))) +cmd_files := $(wildcard $(foreach f,$(targets),$(dir $(f)).$(notdir $(f)).cmd)) + +ifneq ($(cmd_files),) + include $(cmd_files) +endif + +# Declare the contents of the .PHONY variable as phony. We keep that +# information in a variable se we can use it in if_changed and friends. + +.PHONY: $(PHONY) diff --git a/kernel/fiasco/tool/kconfig/scripts/Makefile.clean b/kernel/fiasco/tool/kconfig/scripts/Makefile.clean new file mode 100644 index 00000000..686cb0d3 --- /dev/null +++ b/kernel/fiasco/tool/kconfig/scripts/Makefile.clean @@ -0,0 +1,104 @@ +# ========================================================================== +# Cleaning up +# ========================================================================== + +src := $(obj) + +PHONY := __clean +__clean: + +# Shorthand for $(Q)$(MAKE) scripts/Makefile.clean obj=dir +# Usage: +# $(Q)$(MAKE) $(clean)=dir +clean := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.clean obj + +# The filename Kbuild has precedence over Makefile +kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src)) +include $(if $(wildcard $(kbuild-dir)/Kbuild), $(kbuild-dir)/Kbuild, $(kbuild-dir)/Makefile) + +# Figure out what we need to build from the various variables +# ========================================================================== + +__subdir-y := $(patsubst %/,%,$(filter %/, $(obj-y))) +subdir-y += $(__subdir-y) +__subdir-m := $(patsubst %/,%,$(filter %/, $(obj-m))) +subdir-m += $(__subdir-m) +__subdir-n := $(patsubst %/,%,$(filter %/, $(obj-n))) +subdir-n += $(__subdir-n) +__subdir- := $(patsubst %/,%,$(filter %/, $(obj-))) +subdir- += $(__subdir-) + +# Subdirectories we need to descend into + +subdir-ym := $(sort $(subdir-y) $(subdir-m)) +subdir-ymn := $(sort $(subdir-ym) $(subdir-n) $(subdir-)) + +# Add subdir path + +subdir-ymn := $(addprefix $(obj)/,$(subdir-ymn)) + +# build a list of files to remove, usually relative to the current +# directory + +__clean-files := $(extra-y) $(always) \ + $(targets) $(clean-files) \ + $(host-progs) \ + $(hostprogs-y) $(hostprogs-m) $(hostprogs-) + +__clean-files := $(filter-out $(no-clean-files), $(__clean-files)) + +# as clean-files is given relative to the current directory, this adds +# a $(obj) prefix, except for absolute paths + +__clean-files := $(wildcard \ + $(addprefix $(obj)/, $(filter-out /%, $(__clean-files))) \ + $(filter /%, $(__clean-files))) + +# as clean-dirs is given relative to the current directory, this adds +# a $(obj) prefix, except for absolute paths + +__clean-dirs := $(wildcard \ + $(addprefix $(obj)/, $(filter-out /%, $(clean-dirs))) \ + $(filter /%, $(clean-dirs))) + +# ========================================================================== + +quiet_cmd_clean = CLEAN $(obj) + cmd_clean = rm -f $(__clean-files) +quiet_cmd_cleandir = CLEAN $(__clean-dirs) + cmd_cleandir = rm -rf $(__clean-dirs) + + +__clean: $(subdir-ymn) +ifneq ($(strip $(__clean-files)),) + +$(call cmd,clean) +endif +ifneq ($(strip $(__clean-dirs)),) + +$(call cmd,cleandir) +endif +ifneq ($(strip $(clean-rule)),) + +$(clean-rule) +endif + @: + + +# =========================================================================== +# Generic stuff +# =========================================================================== + +# Descending +# --------------------------------------------------------------------------- + +PHONY += $(subdir-ymn) +$(subdir-ymn): + $(Q)$(MAKE) $(clean)=$@ + +# If quiet is set, only print short version of command + +cmd = @$(if $($(quiet)cmd_$(1)),echo ' $($(quiet)cmd_$(1))' &&) $(cmd_$(1)) + + +# Declare the contents of the .PHONY variable as phony. We keep that +# information in a variable se we can use it in if_changed and friends. + +.PHONY: $(PHONY) diff --git a/kernel/fiasco/tool/kconfig/scripts/Makefile.headersinst b/kernel/fiasco/tool/kconfig/scripts/Makefile.headersinst new file mode 100644 index 00000000..d3bae5e7 --- /dev/null +++ b/kernel/fiasco/tool/kconfig/scripts/Makefile.headersinst @@ -0,0 +1,117 @@ +# ========================================================================== +# Installing headers +# +# header-y - list files to be installed. They are preprocessed +# to remove __KERNEL__ section of the file +# objhdr-y - Same as header-y but for generated files +# genhdr-y - Same as objhdr-y but in a generated/ directory +# +# ========================================================================== + +# called may set destination dir (when installing to asm/) +_dst := $(if $(dst),$(dst),$(obj)) + +# generated header directory +gen := $(if $(gen),$(gen),$(subst include/,include/generated/,$(obj))) + +kbuild-file := $(srctree)/$(obj)/Kbuild +include $(kbuild-file) + +_dst := $(if $(destination-y),$(destination-y),$(_dst)) + +include scripts/Kbuild.include + +install := $(INSTALL_HDR_PATH)/$(_dst) + +header-y := $(sort $(header-y)) +subdirs := $(patsubst %/,%,$(filter %/, $(header-y))) +header-y := $(filter-out %/, $(header-y)) + +# files used to track state of install/check +install-file := $(install)/.install +check-file := $(install)/.check + +# generic-y list all files an architecture uses from asm-generic +# Use this to build a list of headers which require a wrapper +wrapper-files := $(filter $(header-y), $(generic-y)) + +# all headers files for this dir +header-y := $(filter-out $(generic-y), $(header-y)) +all-files := $(header-y) $(objhdr-y) $(genhdr-y) $(wrapper-files) +input-files := $(addprefix $(srctree)/$(obj)/,$(header-y)) \ + $(addprefix $(objtree)/$(obj)/,$(objhdr-y)) \ + $(addprefix $(objtree)/$(gen)/,$(genhdr-y)) +output-files := $(addprefix $(install)/, $(all-files)) + +# Work out what needs to be removed +oldheaders := $(patsubst $(install)/%,%,$(wildcard $(install)/*.h)) +unwanted := $(filter-out $(all-files),$(oldheaders)) + +# Prefix unwanted with full paths to $(INSTALL_HDR_PATH) +unwanted-file := $(addprefix $(install)/, $(unwanted)) + +printdir = $(patsubst $(INSTALL_HDR_PATH)/%/,%,$(dir $@)) + +quiet_cmd_install = INSTALL $(printdir) ($(words $(all-files))\ + file$(if $(word 2, $(all-files)),s)) + cmd_install = \ + $(PERL) $< $(srctree)/$(obj) $(install) $(SRCARCH) $(header-y); \ + $(PERL) $< $(objtree)/$(obj) $(install) $(SRCARCH) $(objhdr-y); \ + $(PERL) $< $(objtree)/$(gen) $(install) $(SRCARCH) $(genhdr-y); \ + for F in $(wrapper-files); do \ + echo "\#include " > $(install)/$$F; \ + done; \ + touch $@ + +quiet_cmd_remove = REMOVE $(unwanted) + cmd_remove = rm -f $(unwanted-file) + +quiet_cmd_check = CHECK $(printdir) ($(words $(all-files)) files) +# Headers list can be pretty long, xargs helps to avoid +# the "Argument list too long" error. + cmd_check = for f in $(all-files); do \ + echo "$(install)/$${f}"; done \ + | xargs \ + $(PERL) $< $(INSTALL_HDR_PATH)/include $(SRCARCH); \ + touch $@ + +PHONY += __headersinst __headerscheck + +ifndef HDRCHECK +# Rules for installing headers +__headersinst: $(subdirs) $(install-file) + @: + +targets += $(install-file) +$(install-file): scripts/headers_install.pl $(input-files) FORCE + $(if $(unwanted),$(call cmd,remove),) + $(if $(wildcard $(dir $@)),,$(shell mkdir -p $(dir $@))) + $(call if_changed,install) + +else +__headerscheck: $(subdirs) $(check-file) + @: + +targets += $(check-file) +$(check-file): scripts/headers_check.pl $(output-files) FORCE + $(call if_changed,check) + +endif + +# Recursion +hdr-inst := -rR -f $(srctree)/scripts/Makefile.headersinst obj +.PHONY: $(subdirs) +$(subdirs): + $(Q)$(MAKE) $(hdr-inst)=$(obj)/$@ dst=$(_dst)/$@ + +targets := $(wildcard $(sort $(targets))) +cmd_files := $(wildcard \ + $(foreach f,$(targets),$(dir $(f)).$(notdir $(f)).cmd)) + +ifneq ($(cmd_files),) + include $(cmd_files) +endif + +.PHONY: $(PHONY) +PHONY += FORCE +FORCE: ; diff --git a/kernel/fiasco/tool/kconfig/scripts/Makefile.host b/kernel/fiasco/tool/kconfig/scripts/Makefile.host new file mode 100644 index 00000000..1ac414fd --- /dev/null +++ b/kernel/fiasco/tool/kconfig/scripts/Makefile.host @@ -0,0 +1,170 @@ +# ========================================================================== +# Building binaries on the host system +# Binaries are used during the compilation of the kernel, for example +# to preprocess a data file. +# +# Both C and C++ are supported, but preferred language is C for such utilities. +# +# Sample syntax (see Documentation/kbuild/makefiles.txt for reference) +# hostprogs-y := bin2hex +# Will compile bin2hex.c and create an executable named bin2hex +# +# hostprogs-y := lxdialog +# lxdialog-objs := checklist.o lxdialog.o +# Will compile lxdialog.c and checklist.c, and then link the executable +# lxdialog, based on checklist.o and lxdialog.o +# +# hostprogs-y := qconf +# qconf-cxxobjs := qconf.o +# qconf-objs := menu.o +# Will compile qconf as a C++ program, and menu as a C program. +# They are linked as C++ code to the executable qconf + +# hostprogs-y := conf +# conf-objs := conf.o libkconfig.so +# libkconfig-objs := expr.o type.o +# Will create a shared library named libkconfig.so that consists of +# expr.o and type.o (they are both compiled as C code and the object files +# are made as position independent code). +# conf.c is compiled as a C program, and conf.o is linked together with +# libkconfig.so as the executable conf. +# Note: Shared libraries consisting of C++ files are not supported + +__hostprogs := $(sort $(hostprogs-y) $(hostprogs-m)) + +# C code +# Executables compiled from a single .c file +host-csingle := $(foreach m,$(__hostprogs),$(if $($(m)-objs),,$(m))) + +# C executables linked based on several .o files +host-cmulti := $(foreach m,$(__hostprogs),\ + $(if $($(m)-cxxobjs),,$(if $($(m)-objs),$(m)))) + +# Object (.o) files compiled from .c files +host-cobjs := $(sort $(foreach m,$(__hostprogs),$($(m)-objs))) + +# C++ code +# C++ executables compiled from at least on .cc file +# and zero or more .c files +host-cxxmulti := $(foreach m,$(__hostprogs),$(if $($(m)-cxxobjs),$(m))) + +# C++ Object (.o) files compiled from .cc files +host-cxxobjs := $(sort $(foreach m,$(host-cxxmulti),$($(m)-cxxobjs))) + +# Shared libaries (only .c supported) +# Shared libraries (.so) - all .so files referenced in "xxx-objs" +host-cshlib := $(sort $(filter %.so, $(host-cobjs))) +# Remove .so files from "xxx-objs" +host-cobjs := $(filter-out %.so,$(host-cobjs)) + +#Object (.o) files used by the shared libaries +host-cshobjs := $(sort $(foreach m,$(host-cshlib),$($(m:.so=-objs)))) + +# output directory for programs/.o files +# hostprogs-y := tools/build may have been specified. Retrieve directory +host-objdirs := $(foreach f,$(__hostprogs), $(if $(dir $(f)),$(dir $(f)))) +# directory of .o files from prog-objs notation +host-objdirs += $(foreach f,$(host-cmulti), \ + $(foreach m,$($(f)-objs), \ + $(if $(dir $(m)),$(dir $(m))))) +# directory of .o files from prog-cxxobjs notation +host-objdirs += $(foreach f,$(host-cxxmulti), \ + $(foreach m,$($(f)-cxxobjs), \ + $(if $(dir $(m)),$(dir $(m))))) + +host-objdirs := $(strip $(sort $(filter-out ./,$(host-objdirs)))) + + +__hostprogs := $(addprefix $(obj)/,$(__hostprogs)) +host-csingle := $(addprefix $(obj)/,$(host-csingle)) +host-cmulti := $(addprefix $(obj)/,$(host-cmulti)) +host-cobjs := $(addprefix $(obj)/,$(host-cobjs)) +host-cxxmulti := $(addprefix $(obj)/,$(host-cxxmulti)) +host-cxxobjs := $(addprefix $(obj)/,$(host-cxxobjs)) +host-cshlib := $(addprefix $(obj)/,$(host-cshlib)) +host-cshobjs := $(addprefix $(obj)/,$(host-cshobjs)) +host-objdirs := $(addprefix $(obj)/,$(host-objdirs)) + +obj-dirs += $(host-objdirs) + +##### +# Handle options to gcc. Support building with separate output directory + +_hostc_flags = $(HOSTCFLAGS) $(HOST_EXTRACFLAGS) \ + $(HOSTCFLAGS_$(basetarget).o) +_hostcxx_flags = $(HOSTCXXFLAGS) $(HOST_EXTRACXXFLAGS) \ + $(HOSTCXXFLAGS_$(basetarget).o) + +ifeq ($(KBUILD_SRC),) +__hostc_flags = $(_hostc_flags) +__hostcxx_flags = $(_hostcxx_flags) +else +__hostc_flags = -I$(obj) $(call flags,_hostc_flags) +__hostcxx_flags = -I$(obj) $(call flags,_hostcxx_flags) +endif + +hostc_flags = -Wp,-MD,$(depfile) $(__hostc_flags) +hostcxx_flags = -Wp,-MD,$(depfile) $(__hostcxx_flags) + +##### +# Compile programs on the host + +# Create executable from a single .c file +# host-csingle -> Executable +quiet_cmd_host-csingle = HOSTCC $@ + cmd_host-csingle = $(HOSTCC) $(hostc_flags) -o $@ $< \ + $(HOST_LOADLIBES) $(HOSTLOADLIBES_$(@F)) +$(host-csingle): $(obj)/%: $(src)/%.c FORCE + $(call if_changed_dep,host-csingle) + +# Link an executable based on list of .o files, all plain c +# host-cmulti -> executable +quiet_cmd_host-cmulti = HOSTLD $@ + cmd_host-cmulti = $(HOSTCC) $(HOSTLDFLAGS) -o $@ \ + $(addprefix $(obj)/,$($(@F)-objs)) \ + $(HOST_LOADLIBES) $(HOSTLOADLIBES_$(@F)) +$(host-cmulti): $(obj)/%: $(host-cobjs) $(host-cshlib) FORCE + $(call if_changed,host-cmulti) + +# Create .o file from a single .c file +# host-cobjs -> .o +quiet_cmd_host-cobjs = HOSTCC $@ + cmd_host-cobjs = $(HOSTCC) $(hostc_flags) -c -o $@ $< +$(host-cobjs): $(obj)/%.o: $(src)/%.c FORCE + $(call if_changed_dep,host-cobjs) + +# Link an executable based on list of .o files, a mixture of .c and .cc +# host-cxxmulti -> executable +quiet_cmd_host-cxxmulti = HOSTLD $@ + cmd_host-cxxmulti = $(HOSTCXX) $(HOSTLDFLAGS) -o $@ \ + $(foreach o,objs cxxobjs,\ + $(addprefix $(obj)/,$($(@F)-$(o)))) \ + $(HOST_LOADLIBES) $(HOSTLOADLIBES_$(@F)) +$(host-cxxmulti): $(obj)/%: $(host-cobjs) $(host-cxxobjs) $(host-cshlib) FORCE + $(call if_changed,host-cxxmulti) + +# Create .o file from a single .cc (C++) file +quiet_cmd_host-cxxobjs = HOSTCXX $@ + cmd_host-cxxobjs = $(HOSTCXX) $(hostcxx_flags) -c -o $@ $< +$(host-cxxobjs): $(obj)/%.o: $(src)/%.cc FORCE + $(call if_changed_dep,host-cxxobjs) + +# Compile .c file, create position independent .o file +# host-cshobjs -> .o +quiet_cmd_host-cshobjs = HOSTCC -fPIC $@ + cmd_host-cshobjs = $(HOSTCC) $(hostc_flags) -fPIC -c -o $@ $< +$(host-cshobjs): $(obj)/%.o: $(src)/%.c FORCE + $(call if_changed_dep,host-cshobjs) + +# Link a shared library, based on position independent .o files +# *.o -> .so shared library (host-cshlib) +quiet_cmd_host-cshlib = HOSTLLD -shared $@ + cmd_host-cshlib = $(HOSTCC) $(HOSTLDFLAGS) -shared -o $@ \ + $(addprefix $(obj)/,$($(@F:.so=-objs))) \ + $(HOST_LOADLIBES) $(HOSTLOADLIBES_$(@F)) +$(host-cshlib): $(obj)/%: $(host-cshobjs) FORCE + $(call if_changed,host-cshlib) + +targets += $(host-csingle) $(host-cmulti) $(host-cobjs)\ + $(host-cxxmulti) $(host-cxxobjs) $(host-cshlib) $(host-cshobjs) + diff --git a/kernel/fiasco/tool/kconfig/scripts/Makefile.lib b/kernel/fiasco/tool/kconfig/scripts/Makefile.lib new file mode 100644 index 00000000..0be6f110 --- /dev/null +++ b/kernel/fiasco/tool/kconfig/scripts/Makefile.lib @@ -0,0 +1,361 @@ +# Backward compatibility +asflags-y += $(EXTRA_AFLAGS) +ccflags-y += $(EXTRA_CFLAGS) +cppflags-y += $(EXTRA_CPPFLAGS) +ldflags-y += $(EXTRA_LDFLAGS) + +# +# flags that take effect in sub directories +export KBUILD_SUBDIR_ASFLAGS := $(KBUILD_SUBDIR_ASFLAGS) $(subdir-asflags-y) +export KBUILD_SUBDIR_CCFLAGS := $(KBUILD_SUBDIR_CCFLAGS) $(subdir-ccflags-y) + +# Figure out what we need to build from the various variables +# =========================================================================== + +# When an object is listed to be built compiled-in and modular, +# only build the compiled-in version + +obj-m := $(filter-out $(obj-y),$(obj-m)) + +# Libraries are always collected in one lib file. +# Filter out objects already built-in + +lib-y := $(filter-out $(obj-y), $(sort $(lib-y) $(lib-m))) + + +# Handle objects in subdirs +# --------------------------------------------------------------------------- +# o if we encounter foo/ in $(obj-y), replace it by foo/built-in.o +# and add the directory to the list of dirs to descend into: $(subdir-y) +# o if we encounter foo/ in $(obj-m), remove it from $(obj-m) +# and add the directory to the list of dirs to descend into: $(subdir-m) + +# Determine modorder. +# Unfortunately, we don't have information about ordering between -y +# and -m subdirs. Just put -y's first. +modorder := $(patsubst %/,%/modules.order, $(filter %/, $(obj-y)) $(obj-m:.o=.ko)) + +__subdir-y := $(patsubst %/,%,$(filter %/, $(obj-y))) +subdir-y += $(__subdir-y) +__subdir-m := $(patsubst %/,%,$(filter %/, $(obj-m))) +subdir-m += $(__subdir-m) +obj-y := $(patsubst %/, %/built-in.o, $(obj-y)) +obj-m := $(filter-out %/, $(obj-m)) + +# Subdirectories we need to descend into + +subdir-ym := $(sort $(subdir-y) $(subdir-m)) + +# if $(foo-objs) exists, foo.o is a composite object +multi-used-y := $(sort $(foreach m,$(obj-y), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y))), $(m)))) +multi-used-m := $(sort $(foreach m,$(obj-m), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y))), $(m)))) +multi-used := $(multi-used-y) $(multi-used-m) +single-used-m := $(sort $(filter-out $(multi-used-m),$(obj-m))) + +# Build list of the parts of our composite objects, our composite +# objects depend on those (obviously) +multi-objs-y := $(foreach m, $(multi-used-y), $($(m:.o=-objs)) $($(m:.o=-y))) +multi-objs-m := $(foreach m, $(multi-used-m), $($(m:.o=-objs)) $($(m:.o=-y))) +multi-objs := $(multi-objs-y) $(multi-objs-m) + +# $(subdir-obj-y) is the list of objects in $(obj-y) which uses dir/ to +# tell kbuild to descend +subdir-obj-y := $(filter %/built-in.o, $(obj-y)) + +# $(obj-dirs) is a list of directories that contain object files +obj-dirs := $(dir $(multi-objs) $(subdir-obj-y)) + +# Replace multi-part objects by their individual parts, look at local dir only +real-objs-y := $(foreach m, $(filter-out $(subdir-obj-y), $(obj-y)), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y))),$($(m:.o=-objs)) $($(m:.o=-y)),$(m))) $(extra-y) +real-objs-m := $(foreach m, $(obj-m), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y))),$($(m:.o=-objs)) $($(m:.o=-y)),$(m))) + +# Add subdir path + +extra-y := $(addprefix $(obj)/,$(extra-y)) +always := $(addprefix $(obj)/,$(always)) +targets := $(addprefix $(obj)/,$(targets)) +modorder := $(addprefix $(obj)/,$(modorder)) +obj-y := $(addprefix $(obj)/,$(obj-y)) +obj-m := $(addprefix $(obj)/,$(obj-m)) +lib-y := $(addprefix $(obj)/,$(lib-y)) +subdir-obj-y := $(addprefix $(obj)/,$(subdir-obj-y)) +real-objs-y := $(addprefix $(obj)/,$(real-objs-y)) +real-objs-m := $(addprefix $(obj)/,$(real-objs-m)) +single-used-m := $(addprefix $(obj)/,$(single-used-m)) +multi-used-y := $(addprefix $(obj)/,$(multi-used-y)) +multi-used-m := $(addprefix $(obj)/,$(multi-used-m)) +multi-objs-y := $(addprefix $(obj)/,$(multi-objs-y)) +multi-objs-m := $(addprefix $(obj)/,$(multi-objs-m)) +subdir-ym := $(addprefix $(obj)/,$(subdir-ym)) +obj-dirs := $(addprefix $(obj)/,$(obj-dirs)) + +# These flags are needed for modversions and compiling, so we define them here +# already +# $(modname_flags) #defines KBUILD_MODNAME as the name of the module it will +# end up in (or would, if it gets compiled in) +# Note: Files that end up in two or more modules are compiled without the +# KBUILD_MODNAME definition. The reason is that any made-up name would +# differ in different configs. +name-fix = $(subst $(comma),_,$(subst -,_,$1)) +basename_flags = -D"KBUILD_BASENAME=KBUILD_STR($(call name-fix,$(basetarget)))" +modname_flags = $(if $(filter 1,$(words $(modname))),\ + -D"KBUILD_MODNAME=KBUILD_STR($(call name-fix,$(modname)))") + +orig_c_flags = $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) $(KBUILD_SUBDIR_CCFLAGS) \ + $(ccflags-y) $(CFLAGS_$(basetarget).o) +_c_flags = $(filter-out $(CFLAGS_REMOVE_$(basetarget).o), $(orig_c_flags)) +_a_flags = $(KBUILD_CPPFLAGS) $(KBUILD_AFLAGS) $(KBUILD_SUBDIR_ASFLAGS) \ + $(asflags-y) $(AFLAGS_$(basetarget).o) +_cpp_flags = $(KBUILD_CPPFLAGS) $(cppflags-y) $(CPPFLAGS_$(@F)) + +# +# Enable gcov profiling flags for a file, directory or for all files depending +# on variables GCOV_PROFILE_obj.o, GCOV_PROFILE and CONFIG_GCOV_PROFILE_ALL +# (in this order) +# +ifeq ($(CONFIG_GCOV_KERNEL),y) +_c_flags += $(if $(patsubst n%,, \ + $(GCOV_PROFILE_$(basetarget).o)$(GCOV_PROFILE)$(CONFIG_GCOV_PROFILE_ALL)), \ + $(CFLAGS_GCOV)) +endif + +ifdef CONFIG_SYMBOL_PREFIX +_sym_flags = -DSYMBOL_PREFIX=$(patsubst "%",%,$(CONFIG_SYMBOL_PREFIX)) +_cpp_flags += $(_sym_flags) +_a_flags += $(_sym_flags) +endif + + +# If building the kernel in a separate objtree expand all occurrences +# of -Idir to -I$(srctree)/dir except for absolute paths (starting with '/'). + +ifeq ($(KBUILD_SRC),) +__c_flags = $(_c_flags) +__a_flags = $(_a_flags) +__cpp_flags = $(_cpp_flags) +else + +# -I$(obj) locates generated .h files +# $(call addtree,-I$(obj)) locates .h files in srctree, from generated .c files +# and locates generated .h files +# FIXME: Replace both with specific CFLAGS* statements in the makefiles +__c_flags = $(call addtree,-I$(obj)) $(call flags,_c_flags) +__a_flags = $(call flags,_a_flags) +__cpp_flags = $(call flags,_cpp_flags) +endif + +c_flags = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(LINUXINCLUDE) \ + $(__c_flags) $(modkern_cflags) \ + -D"KBUILD_STR(s)=\#s" $(basename_flags) $(modname_flags) + +a_flags = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(LINUXINCLUDE) \ + $(__a_flags) $(modkern_aflags) + +cpp_flags = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(LINUXINCLUDE) \ + $(__cpp_flags) + +ld_flags = $(LDFLAGS) $(ldflags-y) + +# Finds the multi-part object the current object will be linked into +modname-multi = $(sort $(foreach m,$(multi-used),\ + $(if $(filter $(subst $(obj)/,,$*.o), $($(m:.o=-objs)) $($(m:.o=-y))),$(m:.o=)))) + +ifdef REGENERATE_PARSERS + +# GPERF +# --------------------------------------------------------------------------- +quiet_cmd_gperf = GPERF $@ + cmd_gperf = gperf -t --output-file $@ -a -C -E -g -k 1,3,$$ -p -t $< + +.PRECIOUS: $(src)/%.hash.c_shipped +$(src)/%.hash.c_shipped: $(src)/%.gperf + $(call cmd,gperf) + +# LEX +# --------------------------------------------------------------------------- +LEX_PREFIX = $(if $(LEX_PREFIX_${baseprereq}),$(LEX_PREFIX_${baseprereq}),yy) + +quiet_cmd_flex = LEX $@ + cmd_flex = flex -o$@ -L -P $(LEX_PREFIX) $< + +.PRECIOUS: $(src)/%.lex.c_shipped +$(src)/%.lex.c_shipped: $(src)/%.l + $(call cmd,flex) + +# YACC +# --------------------------------------------------------------------------- +YACC_PREFIX = $(if $(YACC_PREFIX_${baseprereq}),$(YACC_PREFIX_${baseprereq}),yy) + +quiet_cmd_bison = YACC $@ + cmd_bison = bison -o$@ -t -l -p $(YACC_PREFIX) $< + +.PRECIOUS: $(src)/%.tab.c_shipped +$(src)/%.tab.c_shipped: $(src)/%.y + $(call cmd,bison) + +quiet_cmd_bison_h = YACC $@ + cmd_bison_h = bison -o/dev/null --defines=$@ -t -l -p $(YACC_PREFIX) $< + +.PRECIOUS: $(src)/%.tab.h_shipped +$(src)/%.tab.h_shipped: $(src)/%.y + $(call cmd,bison_h) + +endif + +# Shipped files +# =========================================================================== + +quiet_cmd_shipped = SHIPPED $@ +cmd_shipped = cat $< > $@ + +$(obj)/%: $(src)/%_shipped + $(call cmd,shipped) + +# Commands useful for building a boot image +# =========================================================================== +# +# Use as following: +# +# target: source(s) FORCE +# $(if_changed,ld/objcopy/gzip) +# +# and add target to extra-y so that we know we have to +# read in the saved command line + +# Linking +# --------------------------------------------------------------------------- + +quiet_cmd_ld = LD $@ +cmd_ld = $(LD) $(LDFLAGS) $(ldflags-y) $(LDFLAGS_$(@F)) \ + $(filter-out FORCE,$^) -o $@ + +# Objcopy +# --------------------------------------------------------------------------- + +quiet_cmd_objcopy = OBJCOPY $@ +cmd_objcopy = $(OBJCOPY) $(OBJCOPYFLAGS) $(OBJCOPYFLAGS_$(@F)) $< $@ + +# Gzip +# --------------------------------------------------------------------------- + +quiet_cmd_gzip = GZIP $@ +cmd_gzip = (cat $(filter-out FORCE,$^) | gzip -n -f -9 > $@) || \ + (rm -f $@ ; false) + +# DTC +# --------------------------------------------------------------------------- + +# Generate an assembly file to wrap the output of the device tree compiler +quiet_cmd_dt_S_dtb= DTB $@ +cmd_dt_S_dtb= \ +( \ + echo '\#include '; \ + echo '.section .dtb.init.rodata,"a"'; \ + echo '.balign STRUCT_ALIGNMENT'; \ + echo '.global __dtb_$(*F)_begin'; \ + echo '__dtb_$(*F)_begin:'; \ + echo '.incbin "$<" '; \ + echo '__dtb_$(*F)_end:'; \ + echo '.global __dtb_$(*F)_end'; \ + echo '.balign STRUCT_ALIGNMENT'; \ +) > $@ + +$(obj)/%.dtb.S: $(obj)/%.dtb + $(call cmd,dt_S_dtb) + +quiet_cmd_dtc = DTC $@ +cmd_dtc = $(objtree)/scripts/dtc/dtc -O dtb -o $@ -b 0 $(DTC_FLAGS) -d $(depfile) $< + +# Bzip2 +# --------------------------------------------------------------------------- + +# Bzip2 and LZMA do not include size in file... so we have to fake that; +# append the size as a 32-bit littleendian number as gzip does. +size_append = printf $(shell \ +dec_size=0; \ +for F in $1; do \ + fsize=$$(stat -c "%s" $$F); \ + dec_size=$$(expr $$dec_size + $$fsize); \ +done; \ +printf "%08x\n" $$dec_size | \ + sed 's/\(..\)/\1 /g' | { \ + read ch0 ch1 ch2 ch3; \ + for ch in $$ch3 $$ch2 $$ch1 $$ch0; do \ + printf '%s%03o' '\\' $$((0x$$ch)); \ + done; \ + } \ +) + +quiet_cmd_bzip2 = BZIP2 $@ +cmd_bzip2 = (cat $(filter-out FORCE,$^) | \ + bzip2 -9 && $(call size_append, $(filter-out FORCE,$^))) > $@ || \ + (rm -f $@ ; false) + +# Lzma +# --------------------------------------------------------------------------- + +quiet_cmd_lzma = LZMA $@ +cmd_lzma = (cat $(filter-out FORCE,$^) | \ + lzma -9 && $(call size_append, $(filter-out FORCE,$^))) > $@ || \ + (rm -f $@ ; false) + +quiet_cmd_lzo = LZO $@ +cmd_lzo = (cat $(filter-out FORCE,$^) | \ + lzop -9 && $(call size_append, $(filter-out FORCE,$^))) > $@ || \ + (rm -f $@ ; false) + +# U-Boot mkimage +# --------------------------------------------------------------------------- + +MKIMAGE := $(srctree)/scripts/mkuboot.sh + +# SRCARCH just happens to match slightly more than ARCH (on sparc), so reduces +# the number of overrides in arch makefiles +UIMAGE_ARCH ?= $(SRCARCH) +UIMAGE_COMPRESSION ?= $(if $(2),$(2),none) +UIMAGE_OPTS-y ?= +UIMAGE_TYPE ?= kernel +UIMAGE_LOADADDR ?= arch_must_set_this +UIMAGE_ENTRYADDR ?= $(UIMAGE_LOADADDR) +UIMAGE_NAME ?= 'Linux-$(KERNELRELEASE)' +UIMAGE_IN ?= $< +UIMAGE_OUT ?= $@ + +quiet_cmd_uimage = UIMAGE $(UIMAGE_OUT) + cmd_uimage = $(CONFIG_SHELL) $(MKIMAGE) -A $(UIMAGE_ARCH) -O linux \ + -C $(UIMAGE_COMPRESSION) $(UIMAGE_OPTS-y) \ + -T $(UIMAGE_TYPE) \ + -a $(UIMAGE_LOADADDR) -e $(UIMAGE_ENTRYADDR) \ + -n $(UIMAGE_NAME) -d $(UIMAGE_IN) $(UIMAGE_OUT) + +# XZ +# --------------------------------------------------------------------------- +# Use xzkern to compress the kernel image and xzmisc to compress other things. +# +# xzkern uses a big LZMA2 dictionary since it doesn't increase memory usage +# of the kernel decompressor. A BCJ filter is used if it is available for +# the target architecture. xzkern also appends uncompressed size of the data +# using size_append. The .xz format has the size information available at +# the end of the file too, but it's in more complex format and it's good to +# avoid changing the part of the boot code that reads the uncompressed size. +# Note that the bytes added by size_append will make the xz tool think that +# the file is corrupt. This is expected. +# +# xzmisc doesn't use size_append, so it can be used to create normal .xz +# files. xzmisc uses smaller LZMA2 dictionary than xzkern, because a very +# big dictionary would increase the memory usage too much in the multi-call +# decompression mode. A BCJ filter isn't used either. +quiet_cmd_xzkern = XZKERN $@ +cmd_xzkern = (cat $(filter-out FORCE,$^) | \ + sh $(srctree)/scripts/xz_wrap.sh && \ + $(call size_append, $(filter-out FORCE,$^))) > $@ || \ + (rm -f $@ ; false) + +quiet_cmd_xzmisc = XZMISC $@ +cmd_xzmisc = (cat $(filter-out FORCE,$^) | \ + xz --check=crc32 --lzma2=dict=1MiB) > $@ || \ + (rm -f $@ ; false) + +# misc stuff +# --------------------------------------------------------------------------- +quote:=" diff --git a/kernel/fiasco/tool/kconfig/scripts/Makefile.modinst b/kernel/fiasco/tool/kconfig/scripts/Makefile.modinst new file mode 100644 index 00000000..efa5d940 --- /dev/null +++ b/kernel/fiasco/tool/kconfig/scripts/Makefile.modinst @@ -0,0 +1,35 @@ +# ========================================================================== +# Installing modules +# ========================================================================== + +PHONY := __modinst +__modinst: + +include scripts/Kbuild.include + +# + +__modules := $(sort $(shell grep -h '\.ko' /dev/null $(wildcard $(MODVERDIR)/*.mod))) +modules := $(patsubst %.o,%.ko,$(wildcard $(__modules:.ko=.o))) + +PHONY += $(modules) +__modinst: $(modules) + @: + +quiet_cmd_modules_install = INSTALL $@ + cmd_modules_install = mkdir -p $(2); cp $@ $(2) ; $(mod_strip_cmd) $(2)/$(notdir $@) + +# Modules built outside the kernel source tree go into extra by default +INSTALL_MOD_DIR ?= extra +ext-mod-dir = $(INSTALL_MOD_DIR)$(subst $(patsubst %/,%,$(KBUILD_EXTMOD)),,$(@D)) + +modinst_dir = $(if $(KBUILD_EXTMOD),$(ext-mod-dir),kernel/$(@D)) + +$(modules): + $(call cmd,modules_install,$(MODLIB)/$(modinst_dir)) + + +# Declare the contents of the .PHONY variable as phony. We keep that +# information in a variable se we can use it in if_changed and friends. + +.PHONY: $(PHONY) diff --git a/kernel/fiasco/tool/kconfig/scripts/Makefile.modpost b/kernel/fiasco/tool/kconfig/scripts/Makefile.modpost new file mode 100644 index 00000000..08dce14f --- /dev/null +++ b/kernel/fiasco/tool/kconfig/scripts/Makefile.modpost @@ -0,0 +1,153 @@ +# =========================================================================== +# Module versions +# =========================================================================== +# +# Stage one of module building created the following: +# a) The individual .o files used for the module +# b) A .o file which is the .o files above linked together +# c) A .mod file in $(MODVERDIR)/, listing the name of the +# the preliminary .o file, plus all .o files + +# Stage 2 is handled by this file and does the following +# 1) Find all modules from the files listed in $(MODVERDIR)/ +# 2) modpost is then used to +# 3) create one .mod.c file pr. module +# 4) create one Module.symvers file with CRC for all exported symbols +# 5) compile all .mod.c files +# 6) final link of the module to a file + +# Step 3 is used to place certain information in the module's ELF +# section, including information such as: +# Version magic (see include/linux/vermagic.h for full details) +# - Kernel release +# - SMP is CONFIG_SMP +# - PREEMPT is CONFIG_PREEMPT +# - GCC Version +# Module info +# - Module version (MODULE_VERSION) +# - Module alias'es (MODULE_ALIAS) +# - Module license (MODULE_LICENSE) +# - See include/linux/module.h for more details + +# Step 4 is solely used to allow module versioning in external modules, +# where the CRC of each module is retrieved from the Module.symvers file. + +# KBUILD_MODPOST_WARN can be set to avoid error out in case of undefined +# symbols in the final module linking stage +# KBUILD_MODPOST_NOFINAL can be set to skip the final link of modules. +# This is solely useful to speed up test compiles +PHONY := _modpost +_modpost: __modpost + +include include/config/auto.conf +include scripts/Kbuild.include + +# When building external modules load the Kbuild file to retrieve EXTRA_SYMBOLS info +ifneq ($(KBUILD_EXTMOD),) + +# set src + obj - they may be used when building the .mod.c file +obj := $(KBUILD_EXTMOD) +src := $(obj) + +# Include the module's Makefile to find KBUILD_EXTRA_SYMBOLS +include $(if $(wildcard $(KBUILD_EXTMOD)/Kbuild), \ + $(KBUILD_EXTMOD)/Kbuild, $(KBUILD_EXTMOD)/Makefile) +endif + +include scripts/Makefile.lib + +kernelsymfile := $(objtree)/Module.symvers +modulesymfile := $(firstword $(KBUILD_EXTMOD))/Module.symvers + +# Step 1), find all modules listed in $(MODVERDIR)/ +__modules := $(sort $(shell grep -h '\.ko' /dev/null $(wildcard $(MODVERDIR)/*.mod))) +modules := $(patsubst %.o,%.ko, $(wildcard $(__modules:.ko=.o))) + +# Stop after building .o files if NOFINAL is set. Makes compile tests quicker +_modpost: $(if $(KBUILD_MODPOST_NOFINAL), $(modules:.ko:.o),$(modules)) + +ifneq ($(KBUILD_BUILDHOST),$(ARCH)) + cross_build := 1 +endif + +# Step 2), invoke modpost +# Includes step 3,4 +modpost = scripts/mod/modpost \ + $(if $(CONFIG_MODVERSIONS),-m) \ + $(if $(CONFIG_MODULE_SRCVERSION_ALL),-a,) \ + $(if $(KBUILD_EXTMOD),-i,-o) $(kernelsymfile) \ + $(if $(KBUILD_EXTMOD),-I $(modulesymfile)) \ + $(if $(KBUILD_EXTRA_SYMBOLS), $(patsubst %, -e %,$(KBUILD_EXTRA_SYMBOLS))) \ + $(if $(KBUILD_EXTMOD),-o $(modulesymfile)) \ + $(if $(CONFIG_DEBUG_SECTION_MISMATCH),,-S) \ + $(if $(KBUILD_EXTMOD)$(KBUILD_MODPOST_WARN),-w) \ + $(if $(cross_build),-c) + +quiet_cmd_modpost = MODPOST $(words $(filter-out vmlinux FORCE, $^)) modules + cmd_modpost = $(modpost) -s + +PHONY += __modpost +__modpost: $(modules:.ko=.o) FORCE + $(call cmd,modpost) $(wildcard vmlinux) $(filter-out FORCE,$^) + +quiet_cmd_kernel-mod = MODPOST $@ + cmd_kernel-mod = $(modpost) $@ + +vmlinux.o: FORCE + $(call cmd,kernel-mod) + +# Declare generated files as targets for modpost +$(symverfile): __modpost ; +$(modules:.ko=.mod.c): __modpost ; + + +# Step 5), compile all *.mod.c files + +# modname is set to make c_flags define KBUILD_MODNAME +modname = $(notdir $(@:.mod.o=)) + +quiet_cmd_cc_o_c = CC $@ + cmd_cc_o_c = $(CC) $(c_flags) $(KBUILD_CFLAGS_MODULE) $(CFLAGS_MODULE) \ + -c -o $@ $< + +$(modules:.ko=.mod.o): %.mod.o: %.mod.c FORCE + $(call if_changed_dep,cc_o_c) + +targets += $(modules:.ko=.mod.o) + +# Step 6), final link of the modules +quiet_cmd_ld_ko_o = LD [M] $@ + cmd_ld_ko_o = $(LD) -r $(LDFLAGS) \ + $(KBUILD_LDFLAGS_MODULE) $(LDFLAGS_MODULE) \ + -o $@ $(filter-out FORCE,$^) + +$(modules): %.ko :%.o %.mod.o FORCE + $(call if_changed,ld_ko_o) + +targets += $(modules) + + +# Add FORCE to the prequisites of a target to force it to be always rebuilt. +# --------------------------------------------------------------------------- + +PHONY += FORCE + +FORCE: + +# Read all saved command lines and dependencies for the $(targets) we +# may be building above, using $(if_changed{,_dep}). As an +# optimization, we don't need to read them if the target does not +# exist, we will rebuild anyway in that case. + +targets := $(wildcard $(sort $(targets))) +cmd_files := $(wildcard $(foreach f,$(targets),$(dir $(f)).$(notdir $(f)).cmd)) + +ifneq ($(cmd_files),) + include $(cmd_files) +endif + + +# Declare the contents of the .PHONY variable as phony. We keep that +# information in a variable se we can use it in if_changed and friends. + +.PHONY: $(PHONY) diff --git a/kernel/fiasco/tool/kconfig/scripts/basic/Makefile b/kernel/fiasco/tool/kconfig/scripts/basic/Makefile new file mode 100644 index 00000000..4fcef87b --- /dev/null +++ b/kernel/fiasco/tool/kconfig/scripts/basic/Makefile @@ -0,0 +1,15 @@ +### +# Makefile.basic lists the most basic programs used during the build process. +# The programs listed herein are what are needed to do the basic stuff, +# such as fix file dependencies. +# This initial step is needed to avoid files to be recompiled +# when kernel configuration changes (which is what happens when +# .config is included by main Makefile. +# --------------------------------------------------------------------------- +# fixdep: Used to generate dependency information during build process + +hostprogs-y := fixdep +always := $(hostprogs-y) + +# fixdep is needed to compile other host programs +$(addprefix $(obj)/,$(filter-out fixdep,$(always))): $(obj)/fixdep diff --git a/kernel/fiasco/tool/kconfig/scripts/basic/docproc.c b/kernel/fiasco/tool/kconfig/scripts/basic/docproc.c new file mode 100644 index 00000000..98dec879 --- /dev/null +++ b/kernel/fiasco/tool/kconfig/scripts/basic/docproc.c @@ -0,0 +1,583 @@ +/* + * docproc is a simple preprocessor for the template files + * used as placeholders for the kernel internal documentation. + * docproc is used for documentation-frontend and + * dependency-generator. + * The two usages have in common that they require + * some knowledge of the .tmpl syntax, therefore they + * are kept together. + * + * documentation-frontend + * Scans the template file and call kernel-doc for + * all occurrences of ![EIF]file + * Beforehand each referenced file is scanned for + * any symbols that are exported via these macros: + * EXPORT_SYMBOL(), EXPORT_SYMBOL_GPL(), & + * EXPORT_SYMBOL_GPL_FUTURE() + * This is used to create proper -function and + * -nofunction arguments in calls to kernel-doc. + * Usage: docproc doc file.tmpl + * + * dependency-generator: + * Scans the template file and list all files + * referenced in a format recognized by make. + * Usage: docproc depend file.tmpl + * Writes dependency information to stdout + * in the following format: + * file.tmpl src.c src2.c + * The filenames are obtained from the following constructs: + * !Efilename + * !Ifilename + * !Dfilename + * !Ffilename + * !Pfilename + * + */ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* exitstatus is used to keep track of any failing calls to kernel-doc, + * but execution continues. */ +int exitstatus = 0; + +typedef void DFL(char *); +DFL *defaultline; + +typedef void FILEONLY(char * file); +FILEONLY *internalfunctions; +FILEONLY *externalfunctions; +FILEONLY *symbolsonly; +FILEONLY *findall; + +typedef void FILELINE(char * file, char * line); +FILELINE * singlefunctions; +FILELINE * entity_system; +FILELINE * docsection; + +#define MAXLINESZ 2048 +#define MAXFILES 250 +#define KERNELDOCPATH "scripts/" +#define KERNELDOC "kernel-doc" +#define DOCBOOK "-docbook" +#define LIST "-list" +#define FUNCTION "-function" +#define NOFUNCTION "-nofunction" +#define NODOCSECTIONS "-no-doc-sections" + +static char *srctree, *kernsrctree; + +static char **all_list = NULL; +static int all_list_len = 0; + +static void consume_symbol(const char *sym) +{ + int i; + + for (i = 0; i < all_list_len; i++) { + if (!all_list[i]) + continue; + if (strcmp(sym, all_list[i])) + continue; + all_list[i] = NULL; + break; + } +} + +static void usage (void) +{ + fprintf(stderr, "Usage: docproc {doc|depend} file\n"); + fprintf(stderr, "Input is read from file.tmpl. Output is sent to stdout\n"); + fprintf(stderr, "doc: frontend when generating kernel documentation\n"); + fprintf(stderr, "depend: generate list of files referenced within file\n"); + fprintf(stderr, "Environment variable SRCTREE: absolute path to sources.\n"); + fprintf(stderr, " KBUILD_SRC: absolute path to kernel source tree.\n"); +} + +/* + * Execute kernel-doc with parameters given in svec + */ +static void exec_kernel_doc(char **svec) +{ + pid_t pid; + int ret; + char real_filename[PATH_MAX + 1]; + /* Make sure output generated so far are flushed */ + fflush(stdout); + switch (pid=fork()) { + case -1: + perror("fork"); + exit(1); + case 0: + memset(real_filename, 0, sizeof(real_filename)); + strncat(real_filename, kernsrctree, PATH_MAX); + strncat(real_filename, "/" KERNELDOCPATH KERNELDOC, + PATH_MAX - strlen(real_filename)); + execvp(real_filename, svec); + fprintf(stderr, "exec "); + perror(real_filename); + exit(1); + default: + waitpid(pid, &ret ,0); + } + if (WIFEXITED(ret)) + exitstatus |= WEXITSTATUS(ret); + else + exitstatus = 0xff; +} + +/* Types used to create list of all exported symbols in a number of files */ +struct symbols +{ + char *name; +}; + +struct symfile +{ + char *filename; + struct symbols *symbollist; + int symbolcnt; +}; + +struct symfile symfilelist[MAXFILES]; +int symfilecnt = 0; + +static void add_new_symbol(struct symfile *sym, char * symname) +{ + sym->symbollist = + realloc(sym->symbollist, (sym->symbolcnt + 1) * sizeof(char *)); + sym->symbollist[sym->symbolcnt++].name = strdup(symname); +} + +/* Add a filename to the list */ +static struct symfile * add_new_file(char * filename) +{ + symfilelist[symfilecnt++].filename = strdup(filename); + return &symfilelist[symfilecnt - 1]; +} + +/* Check if file already are present in the list */ +static struct symfile * filename_exist(char * filename) +{ + int i; + for (i=0; i < symfilecnt; i++) + if (strcmp(symfilelist[i].filename, filename) == 0) + return &symfilelist[i]; + return NULL; +} + +/* + * List all files referenced within the template file. + * Files are separated by tabs. + */ +static void adddep(char * file) { printf("\t%s", file); } +static void adddep2(char * file, char * line) { line = line; adddep(file); } +static void noaction(char * line) { line = line; } +static void noaction2(char * file, char * line) { file = file; line = line; } + +/* Echo the line without further action */ +static void printline(char * line) { printf("%s", line); } + +/* + * Find all symbols in filename that are exported with EXPORT_SYMBOL & + * EXPORT_SYMBOL_GPL (& EXPORT_SYMBOL_GPL_FUTURE implicitly). + * All symbols located are stored in symfilelist. + */ +static void find_export_symbols(char * filename) +{ + FILE * fp; + struct symfile *sym; + char line[MAXLINESZ]; + if (filename_exist(filename) == NULL) { + char real_filename[PATH_MAX + 1]; + memset(real_filename, 0, sizeof(real_filename)); + strncat(real_filename, srctree, PATH_MAX); + strncat(real_filename, "/", PATH_MAX - strlen(real_filename)); + strncat(real_filename, filename, + PATH_MAX - strlen(real_filename)); + sym = add_new_file(filename); + fp = fopen(real_filename, "r"); + if (fp == NULL) + { + fprintf(stderr, "docproc: "); + perror(real_filename); + exit(1); + } + while (fgets(line, MAXLINESZ, fp)) { + char *p; + char *e; + if (((p = strstr(line, "EXPORT_SYMBOL_GPL")) != NULL) || + ((p = strstr(line, "EXPORT_SYMBOL")) != NULL)) { + /* Skip EXPORT_SYMBOL{_GPL} */ + while (isalnum(*p) || *p == '_') + p++; + /* Remove parentheses & additional whitespace */ + while (isspace(*p)) + p++; + if (*p != '(') + continue; /* Syntax error? */ + else + p++; + while (isspace(*p)) + p++; + e = p; + while (isalnum(*e) || *e == '_') + e++; + *e = '\0'; + add_new_symbol(sym, p); + } + } + fclose(fp); + } +} + +/* + * Document all external or internal functions in a file. + * Call kernel-doc with following parameters: + * kernel-doc -docbook -nofunction function_name1 filename + * Function names are obtained from all the src files + * by find_export_symbols. + * intfunc uses -nofunction + * extfunc uses -function + */ +static void docfunctions(char * filename, char * type) +{ + int i,j; + int symcnt = 0; + int idx = 0; + char **vec; + + for (i=0; i <= symfilecnt; i++) + symcnt += symfilelist[i].symbolcnt; + vec = malloc((2 + 2 * symcnt + 3) * sizeof(char *)); + if (vec == NULL) { + perror("docproc: "); + exit(1); + } + vec[idx++] = KERNELDOC; + vec[idx++] = DOCBOOK; + vec[idx++] = NODOCSECTIONS; + for (i=0; i < symfilecnt; i++) { + struct symfile * sym = &symfilelist[i]; + for (j=0; j < sym->symbolcnt; j++) { + vec[idx++] = type; + consume_symbol(sym->symbollist[j].name); + vec[idx++] = sym->symbollist[j].name; + } + } + vec[idx++] = filename; + vec[idx] = NULL; + printf("\n", filename); + exec_kernel_doc(vec); + fflush(stdout); + free(vec); +} +static void intfunc(char * filename) { docfunctions(filename, NOFUNCTION); } +static void extfunc(char * filename) { docfunctions(filename, FUNCTION); } + +/* + * Document specific function(s) in a file. + * Call kernel-doc with the following parameters: + * kernel-doc -docbook -function function1 [-function function2] + */ +static void singfunc(char * filename, char * line) +{ + char *vec[200]; /* Enough for specific functions */ + int i, idx = 0; + int startofsym = 1; + vec[idx++] = KERNELDOC; + vec[idx++] = DOCBOOK; + + /* Split line up in individual parameters preceded by FUNCTION */ + for (i=0; line[i]; i++) { + if (isspace(line[i])) { + line[i] = '\0'; + startofsym = 1; + continue; + } + if (startofsym) { + startofsym = 0; + vec[idx++] = FUNCTION; + vec[idx++] = &line[i]; + } + } + for (i = 0; i < idx; i++) { + if (strcmp(vec[i], FUNCTION)) + continue; + consume_symbol(vec[i + 1]); + } + vec[idx++] = filename; + vec[idx] = NULL; + exec_kernel_doc(vec); +} + +/* + * Insert specific documentation section from a file. + * Call kernel-doc with the following parameters: + * kernel-doc -docbook -function "doc section" filename + */ +static void docsect(char *filename, char *line) +{ + char *vec[6]; /* kerneldoc -docbook -function "section" file NULL */ + char *s; + + for (s = line; *s; s++) + if (*s == '\n') + *s = '\0'; + + if (asprintf(&s, "DOC: %s", line) < 0) { + perror("asprintf"); + exit(1); + } + consume_symbol(s); + free(s); + + vec[0] = KERNELDOC; + vec[1] = DOCBOOK; + vec[2] = FUNCTION; + vec[3] = line; + vec[4] = filename; + vec[5] = NULL; + exec_kernel_doc(vec); +} + +static void find_all_symbols(char *filename) +{ + char *vec[4]; /* kerneldoc -list file NULL */ + pid_t pid; + int ret, i, count, start; + char real_filename[PATH_MAX + 1]; + int pipefd[2]; + char *data, *str; + size_t data_len = 0; + + vec[0] = KERNELDOC; + vec[1] = LIST; + vec[2] = filename; + vec[3] = NULL; + + if (pipe(pipefd)) { + perror("pipe"); + exit(1); + } + + switch (pid=fork()) { + case -1: + perror("fork"); + exit(1); + case 0: + close(pipefd[0]); + dup2(pipefd[1], 1); + memset(real_filename, 0, sizeof(real_filename)); + strncat(real_filename, kernsrctree, PATH_MAX); + strncat(real_filename, "/" KERNELDOCPATH KERNELDOC, + PATH_MAX - strlen(real_filename)); + execvp(real_filename, vec); + fprintf(stderr, "exec "); + perror(real_filename); + exit(1); + default: + close(pipefd[1]); + data = malloc(4096); + do { + while ((ret = read(pipefd[0], + data + data_len, + 4096)) > 0) { + data_len += ret; + data = realloc(data, data_len + 4096); + } + } while (ret == -EAGAIN); + if (ret != 0) { + perror("read"); + exit(1); + } + waitpid(pid, &ret ,0); + } + if (WIFEXITED(ret)) + exitstatus |= WEXITSTATUS(ret); + else + exitstatus = 0xff; + + count = 0; + /* poor man's strtok, but with counting */ + for (i = 0; i < data_len; i++) { + if (data[i] == '\n') { + count++; + data[i] = '\0'; + } + } + start = all_list_len; + all_list_len += count; + all_list = realloc(all_list, sizeof(char *) * all_list_len); + str = data; + for (i = 0; i < data_len && start != all_list_len; i++) { + if (data[i] == '\0') { + all_list[start] = str; + str = data + i + 1; + start++; + } + } +} + +/* + * Parse file, calling action specific functions for: + * 1) Lines containing !E + * 2) Lines containing !I + * 3) Lines containing !D + * 4) Lines containing !F + * 5) Lines containing !P + * 6) Lines containing !C + * 7) Default lines - lines not matching the above + */ +static void parse_file(FILE *infile) +{ + char line[MAXLINESZ]; + char * s; + while (fgets(line, MAXLINESZ, infile)) { + if (line[0] == '!') { + s = line + 2; + switch (line[1]) { + case 'E': + while (*s && !isspace(*s)) s++; + *s = '\0'; + externalfunctions(line+2); + break; + case 'I': + while (*s && !isspace(*s)) s++; + *s = '\0'; + internalfunctions(line+2); + break; + case 'D': + while (*s && !isspace(*s)) s++; + *s = '\0'; + symbolsonly(line+2); + break; + case 'F': + /* filename */ + while (*s && !isspace(*s)) s++; + *s++ = '\0'; + /* function names */ + while (isspace(*s)) + s++; + singlefunctions(line +2, s); + break; + case 'P': + /* filename */ + while (*s && !isspace(*s)) s++; + *s++ = '\0'; + /* DOC: section name */ + while (isspace(*s)) + s++; + docsection(line + 2, s); + break; + case 'C': + while (*s && !isspace(*s)) s++; + *s = '\0'; + if (findall) + findall(line+2); + break; + default: + defaultline(line); + } + } + else { + defaultline(line); + } + } + fflush(stdout); +} + + +int main(int argc, char *argv[]) +{ + FILE * infile; + int i; + + srctree = getenv("SRCTREE"); + if (!srctree) + srctree = getcwd(NULL, 0); + kernsrctree = getenv("KBUILD_SRC"); + if (!kernsrctree || !*kernsrctree) + kernsrctree = srctree; + if (argc != 3) { + usage(); + exit(1); + } + /* Open file, exit on error */ + infile = fopen(argv[2], "r"); + if (infile == NULL) { + fprintf(stderr, "docproc: "); + perror(argv[2]); + exit(2); + } + + if (strcmp("doc", argv[1]) == 0) + { + /* Need to do this in two passes. + * First pass is used to collect all symbols exported + * in the various files; + * Second pass generate the documentation. + * This is required because some functions are declared + * and exported in different files :-(( + */ + /* Collect symbols */ + defaultline = noaction; + internalfunctions = find_export_symbols; + externalfunctions = find_export_symbols; + symbolsonly = find_export_symbols; + singlefunctions = noaction2; + docsection = noaction2; + findall = find_all_symbols; + parse_file(infile); + + /* Rewind to start from beginning of file again */ + fseek(infile, 0, SEEK_SET); + defaultline = printline; + internalfunctions = intfunc; + externalfunctions = extfunc; + symbolsonly = printline; + singlefunctions = singfunc; + docsection = docsect; + findall = NULL; + + parse_file(infile); + + for (i = 0; i < all_list_len; i++) { + if (!all_list[i]) + continue; + fprintf(stderr, "Warning: didn't use docs for %s\n", + all_list[i]); + } + } + else if (strcmp("depend", argv[1]) == 0) + { + /* Create first part of dependency chain + * file.tmpl */ + printf("%s\t", argv[2]); + defaultline = noaction; + internalfunctions = adddep; + externalfunctions = adddep; + symbolsonly = adddep; + singlefunctions = adddep2; + docsection = adddep2; + findall = adddep; + parse_file(infile); + printf("\n"); + } + else + { + fprintf(stderr, "Unknown option: %s\n", argv[1]); + exit(1); + } + fclose(infile); + fflush(stdout); + return exitstatus; +} diff --git a/kernel/fiasco/tool/kconfig/scripts/basic/fixdep.c b/kernel/fiasco/tool/kconfig/scripts/basic/fixdep.c new file mode 100644 index 00000000..cb1f50cf --- /dev/null +++ b/kernel/fiasco/tool/kconfig/scripts/basic/fixdep.c @@ -0,0 +1,433 @@ +/* + * "Optimize" a list of dependencies as spit out by gcc -MD + * for the kernel build + * =========================================================================== + * + * Author Kai Germaschewski + * Copyright 2002 by Kai Germaschewski + * + * This software may be used and distributed according to the terms + * of the GNU General Public License, incorporated herein by reference. + * + * + * Introduction: + * + * gcc produces a very nice and correct list of dependencies which + * tells make when to remake a file. + * + * To use this list as-is however has the drawback that virtually + * every file in the kernel includes autoconf.h. + * + * If the user re-runs make *config, autoconf.h will be + * regenerated. make notices that and will rebuild every file which + * includes autoconf.h, i.e. basically all files. This is extremely + * annoying if the user just changed CONFIG_HIS_DRIVER from n to m. + * + * So we play the same trick that "mkdep" played before. We replace + * the dependency on autoconf.h by a dependency on every config + * option which is mentioned in any of the listed prequisites. + * + * kconfig populates a tree in include/config/ with an empty file + * for each config symbol and when the configuration is updated + * the files representing changed config options are touched + * which then let make pick up the changes and the files that use + * the config symbols are rebuilt. + * + * So if the user changes his CONFIG_HIS_DRIVER option, only the objects + * which depend on "include/linux/config/his/driver.h" will be rebuilt, + * so most likely only his driver ;-) + * + * The idea above dates, by the way, back to Michael E Chastain, AFAIK. + * + * So to get dependencies right, there are two issues: + * o if any of the files the compiler read changed, we need to rebuild + * o if the command line given to the compile the file changed, we + * better rebuild as well. + * + * The former is handled by using the -MD output, the later by saving + * the command line used to compile the old object and comparing it + * to the one we would now use. + * + * Again, also this idea is pretty old and has been discussed on + * kbuild-devel a long time ago. I don't have a sensibly working + * internet connection right now, so I rather don't mention names + * without double checking. + * + * This code here has been based partially based on mkdep.c, which + * says the following about its history: + * + * Copyright abandoned, Michael Chastain, . + * This is a C version of syncdep.pl by Werner Almesberger. + * + * + * It is invoked as + * + * fixdep + * + * and will read the dependency file + * + * The transformed dependency snipped is written to stdout. + * + * It first generates a line + * + * cmd_ = + * + * and then basically copies the ..d file to stdout, in the + * process filtering out the dependency on autoconf.h and adding + * dependencies on include/config/my/option.h for every + * CONFIG_MY_OPTION encountered in any of the prequisites. + * + * It will also filter out all the dependencies on *.ver. We need + * to make sure that the generated version checksum are globally up + * to date before even starting the recursive build, so it's too late + * at this point anyway. + * + * The algorithm to grep for "CONFIG_..." is bit unusual, but should + * be fast ;-) We don't even try to really parse the header files, but + * merely grep, i.e. if CONFIG_FOO is mentioned in a comment, it will + * be picked up as well. It's not a problem with respect to + * correctness, since that can only give too many dependencies, thus + * we cannot miss a rebuild. Since people tend to not mention totally + * unrelated CONFIG_ options all over the place, it's not an + * efficiency problem either. + * + * (Note: it'd be easy to port over the complete mkdep state machine, + * but I don't think the added complexity is worth it) + */ +/* + * Note 2: if somebody writes HELLO_CONFIG_BOOM in a file, it will depend onto + * CONFIG_BOOM. This could seem a bug (not too hard to fix), but please do not + * fix it! Some UserModeLinux files (look at arch/um/) call CONFIG_BOOM as + * UML_CONFIG_BOOM, to avoid conflicts with /usr/include/linux/autoconf.h, + * through arch/um/include/uml-config.h; this fixdep "bug" makes sure that + * those files will have correct dependencies. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define INT_CONF ntohl(0x434f4e46) +#define INT_ONFI ntohl(0x4f4e4649) +#define INT_NFIG ntohl(0x4e464947) +#define INT_FIG_ ntohl(0x4649475f) + +char *target; +char *depfile; +char *cmdline; + +static void usage(void) +{ + fprintf(stderr, "Usage: fixdep \n"); + exit(1); +} + +/* + * Print out the commandline prefixed with cmd_ := + */ +static void print_cmdline(void) +{ + printf("cmd_%s := %s\n\n", target, cmdline); +} + +struct item { + struct item *next; + unsigned int len; + unsigned int hash; + char name[0]; +}; + +#define HASHSZ 256 +static struct item *hashtab[HASHSZ]; + +static unsigned int strhash(const char *str, unsigned int sz) +{ + /* fnv32 hash */ + unsigned int i, hash = 2166136261U; + + for (i = 0; i < sz; i++) + hash = (hash ^ str[i]) * 0x01000193; + return hash; +} + +/* + * Lookup a value in the configuration string. + */ +static int is_defined_config(const char *name, int len, unsigned int hash) +{ + struct item *aux; + + for (aux = hashtab[hash % HASHSZ]; aux; aux = aux->next) { + if (aux->hash == hash && aux->len == len && + memcmp(aux->name, name, len) == 0) + return 1; + } + return 0; +} + +/* + * Add a new value to the configuration string. + */ +static void define_config(const char *name, int len, unsigned int hash) +{ + struct item *aux = malloc(sizeof(*aux) + len); + + if (!aux) { + perror("fixdep:malloc"); + exit(1); + } + memcpy(aux->name, name, len); + aux->len = len; + aux->hash = hash; + aux->next = hashtab[hash % HASHSZ]; + hashtab[hash % HASHSZ] = aux; +} + +/* + * Clear the set of configuration strings. + */ +static void clear_config(void) +{ + struct item *aux, *next; + unsigned int i; + + for (i = 0; i < HASHSZ; i++) { + for (aux = hashtab[i]; aux; aux = next) { + next = aux->next; + free(aux); + } + hashtab[i] = NULL; + } +} + +/* + * Record the use of a CONFIG_* word. + */ +static void use_config(const char *m, int slen) +{ + unsigned int hash = strhash(m, slen); + int c, i; + + if (is_defined_config(m, slen, hash)) + return; + + define_config(m, slen, hash); + + printf(" $(wildcard include/config/"); + for (i = 0; i < slen; i++) { + c = m[i]; + if (c == '_') + c = '/'; + else + c = tolower(c); + putchar(c); + } + printf(".h) \\\n"); +} + +static void parse_config_file(const char *map, size_t len) +{ + const int *end = (const int *) (map + len); + /* start at +1, so that p can never be < map */ + const int *m = (const int *) map + 1; + const char *p, *q; + + for (; m < end; m++) { + if (*m == INT_CONF) { p = (char *) m ; goto conf; } + if (*m == INT_ONFI) { p = (char *) m-1; goto conf; } + if (*m == INT_NFIG) { p = (char *) m-2; goto conf; } + if (*m == INT_FIG_) { p = (char *) m-3; goto conf; } + continue; + conf: + if (p > map + len - 7) + continue; + if (memcmp(p, "CONFIG_", 7)) + continue; + for (q = p + 7; q < map + len; q++) { + if (!(isalnum(*q) || *q == '_')) + goto found; + } + continue; + + found: + if (!memcmp(q - 7, "_MODULE", 7)) + q -= 7; + if( (q-p-7) < 0 ) + continue; + use_config(p+7, q-p-7); + } +} + +/* test is s ends in sub */ +static int strrcmp(char *s, char *sub) +{ + int slen = strlen(s); + int sublen = strlen(sub); + + if (sublen > slen) + return 1; + + return memcmp(s + slen - sublen, sub, sublen); +} + +static void do_config_file(const char *filename) +{ + struct stat st; + int fd; + void *map; + + fd = open(filename, O_RDONLY); + if (fd < 0) { + fprintf(stderr, "fixdep: error opening config file: "); + perror(filename); + exit(2); + } + fstat(fd, &st); + if (st.st_size == 0) { + close(fd); + return; + } + map = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + if ((long) map == -1) { + perror("fixdep: mmap"); + close(fd); + return; + } + + parse_config_file(map, st.st_size); + + munmap(map, st.st_size); + + close(fd); +} + +/* + * Important: The below generated source_foo.o and deps_foo.o variable + * assignments are parsed not only by make, but also by the rather simple + * parser in scripts/mod/sumversion.c. + */ +static void parse_dep_file(void *map, size_t len) +{ + char *m = map; + char *end = m + len; + char *p; + char s[PATH_MAX]; + int first; + + p = strchr(m, ':'); + if (!p) { + fprintf(stderr, "fixdep: parse error\n"); + exit(1); + } + memcpy(s, m, p-m); s[p-m] = 0; + m = p+1; + + clear_config(); + + first = 1; + while (m < end) { + while (m < end && (*m == ' ' || *m == '\\' || *m == '\n')) + m++; + p = m; + while (p < end && *p != ' ') p++; + if (p == end) { + do p--; while (!isalnum(*p)); + p++; + } + memcpy(s, m, p-m); s[p-m] = 0; + if (strrcmp(s, "include/generated/autoconf.h") && + strrcmp(s, "arch/um/include/uml-config.h") && + strrcmp(s, "include/linux/kconfig.h") && + strrcmp(s, ".ver")) { + /* + * Do not list the source file as dependency, so that + * kbuild is not confused if a .c file is rewritten + * into .S or vice versa. Storing it in source_* is + * needed for modpost to compute srcversions. + */ + if (first) { + printf("source_%s := %s\n\n", target, s); + printf("deps_%s := \\\n", target); + } else + printf(" %s \\\n", s); + do_config_file(s); + } + first = 0; + m = p + 1; + } + printf("\n%s: $(deps_%s)\n\n", target, target); + printf("$(deps_%s):\n", target); +} + +static void print_deps(void) +{ + struct stat st; + int fd; + void *map; + + fd = open(depfile, O_RDONLY); + if (fd < 0) { + fprintf(stderr, "fixdep: error opening depfile: "); + perror(depfile); + exit(2); + } + if (fstat(fd, &st) < 0) { + fprintf(stderr, "fixdep: error fstat'ing depfile: "); + perror(depfile); + exit(2); + } + if (st.st_size == 0) { + fprintf(stderr,"fixdep: %s is empty\n",depfile); + close(fd); + return; + } + map = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + if ((long) map == -1) { + perror("fixdep: mmap"); + close(fd); + return; + } + + parse_dep_file(map, st.st_size); + + munmap(map, st.st_size); + + close(fd); +} + +static void traps(void) +{ + static char test[] __attribute__((aligned(sizeof(int)))) = "CONF"; + int *p = (int *)test; + + if (*p != INT_CONF) { + fprintf(stderr, "fixdep: sizeof(int) != 4 or wrong endianess? %#x\n", + *p); + exit(2); + } +} + +int main(int argc, char *argv[]) +{ + traps(); + + if (argc != 4) + usage(); + + depfile = argv[1]; + target = argv[2]; + cmdline = argv[3]; + + print_cmdline(); + print_deps(); + + return 0; +} diff --git a/kernel/fiasco/tool/kconfig/scripts/basic/hash.c b/kernel/fiasco/tool/kconfig/scripts/basic/hash.c new file mode 100644 index 00000000..2ef5d3f6 --- /dev/null +++ b/kernel/fiasco/tool/kconfig/scripts/basic/hash.c @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2008 Red Hat, Inc., Jason Baron + * + */ + +#include +#include +#include + +#define DYNAMIC_DEBUG_HASH_BITS 6 + +static const char *program; + +static void usage(void) +{ + printf("Usage: %s \n", program); + exit(1); +} + +/* djb2 hashing algorithm by Dan Bernstein. From: + * http://www.cse.yorku.ca/~oz/hash.html + */ + +static unsigned int djb2_hash(char *str) +{ + unsigned long hash = 5381; + int c; + + c = *str; + while (c) { + hash = ((hash << 5) + hash) + c; + c = *++str; + } + return (unsigned int)(hash & ((1 << DYNAMIC_DEBUG_HASH_BITS) - 1)); +} + +static unsigned int r5_hash(char *str) +{ + unsigned long hash = 0; + int c; + + c = *str; + while (c) { + hash = (hash + (c << 4) + (c >> 4)) * 11; + c = *++str; + } + return (unsigned int)(hash & ((1 << DYNAMIC_DEBUG_HASH_BITS) - 1)); +} + +int main(int argc, char *argv[]) +{ + program = argv[0]; + + if (argc != 3) + usage(); + if (!strcmp(argv[1], "djb2")) + printf("%d\n", djb2_hash(argv[2])); + else if (!strcmp(argv[1], "r5")) + printf("%d\n", r5_hash(argv[2])); + else + usage(); + exit(0); +} + diff --git a/kernel/fiasco/tool/kconfig/scripts/kconfig/.gitignore b/kernel/fiasco/tool/kconfig/scripts/kconfig/.gitignore new file mode 100644 index 00000000..ee120d44 --- /dev/null +++ b/kernel/fiasco/tool/kconfig/scripts/kconfig/.gitignore @@ -0,0 +1,23 @@ +# +# Generated files +# +config* +*.lex.c +*.tab.c +*.tab.h +zconf.hash.c +*.moc +lkc_defs.h +gconf.glade.h +*.pot +*.mo + +# +# configuration programs +# +conf +mconf +nconf +qconf +gconf +kxgettext diff --git a/kernel/fiasco/tool/kconfig/scripts/kconfig/Makefile b/kernel/fiasco/tool/kconfig/scripts/kconfig/Makefile new file mode 100644 index 00000000..79662658 --- /dev/null +++ b/kernel/fiasco/tool/kconfig/scripts/kconfig/Makefile @@ -0,0 +1,308 @@ +# =========================================================================== +# Kernel configuration targets +# These targets are used from top-level makefile + +PHONY += oldconfig xconfig gconfig menuconfig config silentoldconfig update-po-config \ + localmodconfig localyesconfig + +ifdef KBUILD_KCONFIG +Kconfig := $(KBUILD_KCONFIG) +else +Kconfig := Kconfig +endif + +xconfig: $(obj)/qconf + $< $(Kconfig) + +gconfig: $(obj)/gconf + $< $(Kconfig) + +menuconfig: $(obj)/mconf + $< $(Kconfig) + +config: $(obj)/conf + $< --oldaskconfig $(Kconfig) + +nconfig: $(obj)/nconf + $< $(Kconfig) + +oldconfig: $(obj)/conf + $< --$@ $(Kconfig) + +silentoldconfig: $(obj)/conf + $(Q)mkdir -p include/generated + $< --$@ $(Kconfig) + +localyesconfig localmodconfig: $(obj)/streamline_config.pl $(obj)/conf + $(Q)mkdir -p include/generated + $(Q)perl $< --$@ $(srctree) $(Kconfig) > .tmp.config + $(Q)if [ -f .config ]; then \ + cmp -s .tmp.config .config || \ + (mv -f .config .config.old.1; \ + mv -f .tmp.config .config; \ + $(obj)/conf --silentoldconfig $(Kconfig); \ + mv -f .config.old.1 .config.old) \ + else \ + mv -f .tmp.config .config; \ + $(obj)/conf --silentoldconfig $(Kconfig); \ + fi + $(Q)rm -f .tmp.config + +# Create new linux.pot file +# Adjust charset to UTF-8 in .po file to accept UTF-8 in Kconfig files +update-po-config: $(obj)/kxgettext $(obj)/gconf.glade.h + $(Q)echo " GEN config.pot" + $(Q)xgettext --default-domain=linux \ + --add-comments --keyword=_ --keyword=N_ \ + --from-code=UTF-8 \ + --files-from=$(srctree)/scripts/kconfig/POTFILES.in \ + --directory=$(srctree) --directory=$(objtree) \ + --output $(obj)/config.pot + $(Q)sed -i s/CHARSET/UTF-8/ $(obj)/config.pot + $(Q)(for i in `ls $(srctree)/arch/*/Kconfig \ + $(srctree)/arch/*/um/Kconfig`; \ + do \ + echo " GEN $$i"; \ + $(obj)/kxgettext $$i \ + >> $(obj)/config.pot; \ + done ) + $(Q)echo " GEN linux.pot" + $(Q)msguniq --sort-by-file --to-code=UTF-8 $(obj)/config.pot \ + --output $(obj)/linux.pot + $(Q)rm -f $(obj)/config.pot + +PHONY += allnoconfig allyesconfig allmodconfig alldefconfig randconfig + +allnoconfig allyesconfig allmodconfig alldefconfig randconfig: $(obj)/conf + $< --$@ $(Kconfig) + +PHONY += listnewconfig oldnoconfig savedefconfig defconfig + +listnewconfig oldnoconfig: $(obj)/conf + $< --$@ $(Kconfig) + +savedefconfig: $(obj)/conf + $< --$@=defconfig $(Kconfig) + +defconfig: $(obj)/conf +ifeq ($(KBUILD_DEFCONFIG),) + $< --defconfig $(Kconfig) +else + @echo "*** Default configuration is based on '$(KBUILD_DEFCONFIG)'" + $(Q)$< --defconfig=arch/$(SRCARCH)/configs/$(KBUILD_DEFCONFIG) $(Kconfig) +endif + +%_defconfig: $(obj)/conf + $(Q)$< --defconfig=arch/$(SRCARCH)/configs/$@ $(Kconfig) + +# Help text used by make help +help: + @echo ' config - Update current config utilising a line-oriented program' + @echo ' nconfig - Update current config utilising a ncurses menu based program' + @echo ' menuconfig - Update current config utilising a menu based program' + @echo ' xconfig - Update current config utilising a QT based front-end' + @echo ' gconfig - Update current config utilising a GTK based front-end' + @echo ' oldconfig - Update current config utilising a provided .config as base' + @echo ' localmodconfig - Update current config disabling modules not loaded' + @echo ' localyesconfig - Update current config converting local mods to core' + @echo ' silentoldconfig - Same as oldconfig, but quietly, additionally update deps' + @echo ' defconfig - New config with default from ARCH supplied defconfig' + @echo ' savedefconfig - Save current config as ./defconfig (minimal config)' + @echo ' allnoconfig - New config where all options are answered with no' + @echo ' allyesconfig - New config where all options are accepted with yes' + @echo ' allmodconfig - New config selecting modules when possible' + @echo ' alldefconfig - New config with all symbols set to default' + @echo ' randconfig - New config with random answer to all options' + @echo ' listnewconfig - List new options' + @echo ' oldnoconfig - Same as silentoldconfig but set new symbols to n (unset)' + +# lxdialog stuff +check-lxdialog := $(srctree)/$(src)/lxdialog/check-lxdialog.sh + +# Use recursively expanded variables so we do not call gcc unless +# we really need to do so. (Do not call gcc as part of make mrproper) +HOST_EXTRACFLAGS += $(shell $(CONFIG_SHELL) $(check-lxdialog) -ccflags) \ + -DLOCALE + +# =========================================================================== +# Shared Makefile for the various kconfig executables: +# conf: Used for defconfig, oldconfig and related targets +# nconf: Used for the nconfig target. +# Utilizes ncurses +# mconf: Used for the menuconfig target +# Utilizes the lxdialog package +# qconf: Used for the xconfig target +# Based on QT which needs to be installed to compile it +# gconf: Used for the gconfig target +# Based on GTK which needs to be installed to compile it +# object files used by all kconfig flavours + +lxdialog := lxdialog/checklist.o lxdialog/util.o lxdialog/inputbox.o +lxdialog += lxdialog/textbox.o lxdialog/yesno.o lxdialog/menubox.o + +conf-objs := conf.o zconf.tab.o +mconf-objs := mconf.o zconf.tab.o $(lxdialog) +nconf-objs := nconf.o zconf.tab.o nconf.gui.o +kxgettext-objs := kxgettext.o zconf.tab.o +qconf-cxxobjs := qconf.o +qconf-objs := zconf.tab.o +gconf-objs := gconf.o zconf.tab.o + +hostprogs-y := conf + +ifeq ($(MAKECMDGOALS),nconfig) + hostprogs-y += nconf +endif + +ifeq ($(MAKECMDGOALS),menuconfig) + hostprogs-y += mconf +endif + +ifeq ($(MAKECMDGOALS),update-po-config) + hostprogs-y += kxgettext +endif + +ifeq ($(MAKECMDGOALS),xconfig) + qconf-target := 1 +endif +ifeq ($(MAKECMDGOALS),gconfig) + gconf-target := 1 +endif + + +ifeq ($(qconf-target),1) + hostprogs-y += qconf +endif + +ifeq ($(gconf-target),1) + hostprogs-y += gconf +endif + +clean-files := qconf.moc .tmp_qtcheck .tmp_gtkcheck +clean-files += zconf.tab.c zconf.lex.c zconf.hash.c gconf.glade.h +clean-files += mconf qconf gconf nconf +clean-files += config.pot linux.pot + +# Check that we have the required ncurses stuff installed for lxdialog (menuconfig) +PHONY += $(obj)/dochecklxdialog +$(addprefix $(obj)/,$(lxdialog)): $(obj)/dochecklxdialog +$(obj)/dochecklxdialog: + $(Q)$(CONFIG_SHELL) $(check-lxdialog) -check $(HOSTCC) $(HOST_EXTRACFLAGS) $(HOSTLOADLIBES_mconf) + +always := dochecklxdialog + +# Add environment specific flags +HOST_EXTRACFLAGS += $(shell $(CONFIG_SHELL) $(srctree)/$(src)/check.sh $(HOSTCC) $(HOSTCFLAGS)) + +# generated files seem to need this to find local include files +HOSTCFLAGS_zconf.lex.o := -I$(src) +HOSTCFLAGS_zconf.tab.o := -I$(src) + +LEX_PREFIX_zconf := zconf +YACC_PREFIX_zconf := zconf + +HOSTLOADLIBES_qconf = $(KC_QT_LIBS) +HOSTCXXFLAGS_qconf.o = $(KC_QT_CFLAGS) + +HOSTLOADLIBES_gconf = `pkg-config --libs gtk+-2.0 gmodule-2.0 libglade-2.0` +HOSTCFLAGS_gconf.o = `pkg-config --cflags gtk+-2.0 gmodule-2.0 libglade-2.0` \ + -Wno-missing-prototypes + +HOSTLOADLIBES_mconf = $(shell $(CONFIG_SHELL) $(check-lxdialog) -ldflags $(HOSTCC)) + +HOSTLOADLIBES_nconf = -lmenu -lpanel -lncurses +$(obj)/qconf.o: $(obj)/.tmp_qtcheck + +ifeq ($(qconf-target),1) +$(obj)/.tmp_qtcheck: $(src)/Makefile +-include $(obj)/.tmp_qtcheck + +# QT needs some extra effort... +$(obj)/.tmp_qtcheck: + @set -e; echo " CHECK qt"; dir=""; pkg=""; \ + if ! pkg-config --exists QtCore 2> /dev/null; then \ + echo "* Unable to find the QT4 tool qmake. Trying to use QT3"; \ + pkg-config --exists qt 2> /dev/null && pkg=qt; \ + pkg-config --exists qt-mt 2> /dev/null && pkg=qt-mt; \ + if [ -n "$$pkg" ]; then \ + cflags="\$$(shell pkg-config $$pkg --cflags)"; \ + libs="\$$(shell pkg-config $$pkg --libs)"; \ + moc="\$$(shell pkg-config $$pkg --variable=prefix)/bin/moc"; \ + dir="$$(pkg-config $$pkg --variable=prefix)"; \ + else \ + for d in $$QTDIR /usr/share/qt* /usr/lib/qt*; do \ + if [ -f $$d/include/qconfig.h ]; then dir=$$d; break; fi; \ + done; \ + if [ -z "$$dir" ]; then \ + echo "*"; \ + echo "* Unable to find any QT installation. Please make sure that"; \ + echo "* the QT4 or QT3 development package is correctly installed and"; \ + echo "* either qmake can be found or install pkg-config or set"; \ + echo "* the QTDIR environment variable to the correct location."; \ + echo "*"; \ + false; \ + fi; \ + libpath=$$dir/lib; lib=qt; osdir=""; \ + $(HOSTCXX) -print-multi-os-directory > /dev/null 2>&1 && \ + osdir=x$$($(HOSTCXX) -print-multi-os-directory); \ + test -d $$libpath/$$osdir && libpath=$$libpath/$$osdir; \ + test -f $$libpath/libqt-mt.so && lib=qt-mt; \ + cflags="-I$$dir/include"; \ + libs="-L$$libpath -Wl,-rpath,$$libpath -l$$lib"; \ + moc="$$dir/bin/moc"; \ + fi; \ + if [ ! -x $$dir/bin/moc -a -x /usr/bin/moc ]; then \ + echo "*"; \ + echo "* Unable to find $$dir/bin/moc, using /usr/bin/moc instead."; \ + echo "*"; \ + moc="/usr/bin/moc"; \ + fi; \ + else \ + cflags="\$$(shell pkg-config QtCore QtGui Qt3Support --cflags)"; \ + libs="\$$(shell pkg-config QtCore QtGui Qt3Support --libs)"; \ + binpath="\$$(shell pkg-config QtCore --variable=prefix)"; \ + moc="$$binpath/bin/moc"; \ + fi; \ + echo "KC_QT_CFLAGS=$$cflags" > $@; \ + echo "KC_QT_LIBS=$$libs" >> $@; \ + echo "KC_QT_MOC=$$moc" >> $@ +endif + +$(obj)/gconf.o: $(obj)/.tmp_gtkcheck + +ifeq ($(gconf-target),1) +-include $(obj)/.tmp_gtkcheck + +# GTK needs some extra effort, too... +$(obj)/.tmp_gtkcheck: + @if `pkg-config --exists gtk+-2.0 gmodule-2.0 libglade-2.0`; then \ + if `pkg-config --atleast-version=2.0.0 gtk+-2.0`; then \ + touch $@; \ + else \ + echo "*"; \ + echo "* GTK+ is present but version >= 2.0.0 is required."; \ + echo "*"; \ + false; \ + fi \ + else \ + echo "*"; \ + echo "* Unable to find the GTK+ installation. Please make sure that"; \ + echo "* the GTK+ 2.0 development package is correctly installed..."; \ + echo "* You need gtk+-2.0, glib-2.0 and libglade-2.0."; \ + echo "*"; \ + false; \ + fi +endif + +$(obj)/zconf.tab.o: $(obj)/zconf.lex.c $(obj)/zconf.hash.c + +$(obj)/qconf.o: $(obj)/qconf.moc + +$(obj)/%.moc: $(src)/%.h + $(KC_QT_MOC) -i $< -o $@ + +# Extract gconf menu items for I18N support +$(obj)/gconf.glade.h: $(obj)/gconf.glade + $(Q)intltool-extract --type=gettext/glade --srcdir=$(srctree) \ + $(obj)/gconf.glade + diff --git a/kernel/fiasco/tool/kconfig/scripts/kconfig/POTFILES.in b/kernel/fiasco/tool/kconfig/scripts/kconfig/POTFILES.in new file mode 100644 index 00000000..96745739 --- /dev/null +++ b/kernel/fiasco/tool/kconfig/scripts/kconfig/POTFILES.in @@ -0,0 +1,12 @@ +scripts/kconfig/lxdialog/checklist.c +scripts/kconfig/lxdialog/inputbox.c +scripts/kconfig/lxdialog/menubox.c +scripts/kconfig/lxdialog/textbox.c +scripts/kconfig/lxdialog/util.c +scripts/kconfig/lxdialog/yesno.c +scripts/kconfig/mconf.c +scripts/kconfig/conf.c +scripts/kconfig/confdata.c +scripts/kconfig/gconf.c +scripts/kconfig/gconf.glade.h +scripts/kconfig/qconf.cc diff --git a/kernel/fiasco/tool/kconfig/scripts/kconfig/check.sh b/kernel/fiasco/tool/kconfig/scripts/kconfig/check.sh new file mode 100755 index 00000000..fa59cbf9 --- /dev/null +++ b/kernel/fiasco/tool/kconfig/scripts/kconfig/check.sh @@ -0,0 +1,14 @@ +#!/bin/sh +# Needed for systems without gettext +$* -xc -o /dev/null - > /dev/null 2>&1 << EOF +#include +int main() +{ + gettext(""); + return 0; +} +EOF +if [ ! "$?" -eq "0" ]; then + echo -DKBUILD_NO_NLS; +fi + diff --git a/kernel/fiasco/tool/kconfig/scripts/kconfig/conf.c b/kernel/fiasco/tool/kconfig/scripts/kconfig/conf.c new file mode 100644 index 00000000..0dc4a2c7 --- /dev/null +++ b/kernel/fiasco/tool/kconfig/scripts/kconfig/conf.c @@ -0,0 +1,694 @@ +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "lkc.h" + +static void conf(struct menu *menu); +static void check_conf(struct menu *menu); +static void xfgets(char *str, int size, FILE *in); + +enum input_mode { + oldaskconfig, + silentoldconfig, + oldconfig, + allnoconfig, + allyesconfig, + allmodconfig, + alldefconfig, + randconfig, + defconfig, + savedefconfig, + listnewconfig, + oldnoconfig, +} input_mode = oldaskconfig; + +static int indent = 1; +static int valid_stdin = 1; +static int sync_kconfig; +static int conf_cnt; +static char line[128]; +static struct menu *rootEntry; + +static void print_help(struct menu *menu) +{ + struct gstr help = str_new(); + + menu_get_ext_help(menu, &help); + + printf("\n%s\n", str_get(&help)); + str_free(&help); +} + +static void strip(char *str) +{ + char *p = str; + int l; + + while ((isspace(*p))) + p++; + l = strlen(p); + if (p != str) + memmove(str, p, l + 1); + if (!l) + return; + p = str + l - 1; + while ((isspace(*p))) + *p-- = 0; +} + +static void check_stdin(void) +{ + if (!valid_stdin) { + printf(_("aborted!\n\n")); + printf(_("Console input/output is redirected. ")); + printf(_("Run 'make oldconfig' to update configuration.\n\n")); + exit(1); + } +} + +static int conf_askvalue(struct symbol *sym, const char *def) +{ + enum symbol_type type = sym_get_type(sym); + + if (!sym_has_value(sym)) + printf(_("(NEW) ")); + + line[0] = '\n'; + line[1] = 0; + + if (!sym_is_changable(sym)) { + printf("%s\n", def); + line[0] = '\n'; + line[1] = 0; + return 0; + } + + switch (input_mode) { + case oldconfig: + case silentoldconfig: + if (sym_has_value(sym)) { + printf("%s\n", def); + return 0; + } + check_stdin(); + /* fall through */ + case oldaskconfig: + fflush(stdout); + xfgets(line, 128, stdin); + return 1; + default: + break; + } + + switch (type) { + case S_INT: + case S_HEX: + case S_STRING: + printf("%s\n", def); + return 1; + default: + ; + } + printf("%s", line); + return 1; +} + +static int conf_string(struct menu *menu) +{ + struct symbol *sym = menu->sym; + const char *def; + + while (1) { + printf("%*s%s ", indent - 1, "", _(menu->prompt->text)); + printf("(%s) ", sym->name); + def = sym_get_string_value(sym); + if (sym_get_string_value(sym)) + printf("[%s] ", def); + if (!conf_askvalue(sym, def)) + return 0; + switch (line[0]) { + case '\n': + break; + case '?': + /* print help */ + if (line[1] == '\n') { + print_help(menu); + def = NULL; + break; + } + /* fall through */ + default: + line[strlen(line)-1] = 0; + def = line; + } + if (def && sym_set_string_value(sym, def)) + return 0; + } +} + +static int conf_sym(struct menu *menu) +{ + struct symbol *sym = menu->sym; + tristate oldval, newval; + + while (1) { + printf("%*s%s ", indent - 1, "", _(menu->prompt->text)); + if (sym->name) + printf("(%s) ", sym->name); + putchar('['); + oldval = sym_get_tristate_value(sym); + switch (oldval) { + case no: + putchar('N'); + break; + case mod: + putchar('M'); + break; + case yes: + putchar('Y'); + break; + } + if (oldval != no && sym_tristate_within_range(sym, no)) + printf("/n"); + if (oldval != mod && sym_tristate_within_range(sym, mod)) + printf("/m"); + if (oldval != yes && sym_tristate_within_range(sym, yes)) + printf("/y"); + if (menu_has_help(menu)) + printf("/?"); + printf("] "); + if (!conf_askvalue(sym, sym_get_string_value(sym))) + return 0; + strip(line); + + switch (line[0]) { + case 'n': + case 'N': + newval = no; + if (!line[1] || !strcmp(&line[1], "o")) + break; + continue; + case 'm': + case 'M': + newval = mod; + if (!line[1]) + break; + continue; + case 'y': + case 'Y': + newval = yes; + if (!line[1] || !strcmp(&line[1], "es")) + break; + continue; + case 0: + newval = oldval; + break; + case '?': + goto help; + default: + continue; + } + if (sym_set_tristate_value(sym, newval)) + return 0; +help: + print_help(menu); + } +} + +static int conf_choice(struct menu *menu) +{ + struct symbol *sym, *def_sym; + struct menu *child; + bool is_new; + + sym = menu->sym; + is_new = !sym_has_value(sym); + if (sym_is_changable(sym)) { + conf_sym(menu); + sym_calc_value(sym); + switch (sym_get_tristate_value(sym)) { + case no: + return 1; + case mod: + return 0; + case yes: + break; + } + } else { + switch (sym_get_tristate_value(sym)) { + case no: + return 1; + case mod: + printf("%*s%s\n", indent - 1, "", _(menu_get_prompt(menu))); + return 0; + case yes: + break; + } + } + + while (1) { + int cnt, def; + + printf("%*s%s\n", indent - 1, "", _(menu_get_prompt(menu))); + def_sym = sym_get_choice_value(sym); + cnt = def = 0; + line[0] = 0; + for (child = menu->list; child; child = child->next) { + if (!menu_is_visible(child)) + continue; + if (!child->sym) { + printf("%*c %s\n", indent, '*', _(menu_get_prompt(child))); + continue; + } + cnt++; + if (child->sym == def_sym) { + def = cnt; + printf("%*c", indent, '>'); + } else + printf("%*c", indent, ' '); + printf(" %d. %s", cnt, _(menu_get_prompt(child))); + if (child->sym->name) + printf(" (%s)", child->sym->name); + if (!sym_has_value(child->sym)) + printf(_(" (NEW)")); + printf("\n"); + } + printf(_("%*schoice"), indent - 1, ""); + if (cnt == 1) { + printf("[1]: 1\n"); + goto conf_childs; + } + printf("[1-%d", cnt); + if (menu_has_help(menu)) + printf("?"); + printf("]: "); + switch (input_mode) { + case oldconfig: + case silentoldconfig: + if (!is_new) { + cnt = def; + printf("%d\n", cnt); + break; + } + check_stdin(); + /* fall through */ + case oldaskconfig: + fflush(stdout); + xfgets(line, 128, stdin); + strip(line); + if (line[0] == '?') { + print_help(menu); + continue; + } + if (!line[0]) + cnt = def; + else if (isdigit(line[0])) + cnt = atoi(line); + else + continue; + break; + default: + break; + } + + conf_childs: + for (child = menu->list; child; child = child->next) { + if (!child->sym || !menu_is_visible(child)) + continue; + if (!--cnt) + break; + } + if (!child) + continue; + if (line[0] && line[strlen(line) - 1] == '?') { + print_help(child); + continue; + } + sym_set_choice_value(sym, child->sym); + for (child = child->list; child; child = child->next) { + indent += 2; + conf(child); + indent -= 2; + } + return 1; + } +} + +static void conf(struct menu *menu) +{ + struct symbol *sym; + struct property *prop; + struct menu *child; + + if (!menu_is_visible(menu)) + return; + + sym = menu->sym; + prop = menu->prompt; + if (prop) { + const char *prompt; + + switch (prop->type) { + case P_MENU: + if ((input_mode == silentoldconfig || + input_mode == listnewconfig || + input_mode == oldnoconfig) && + rootEntry != menu) { + check_conf(menu); + return; + } + /* fall through */ + case P_COMMENT: + prompt = menu_get_prompt(menu); + if (prompt) + printf("%*c\n%*c %s\n%*c\n", + indent, '*', + indent, '*', _(prompt), + indent, '*'); + default: + ; + } + } + + if (!sym) + goto conf_childs; + + if (sym_is_choice(sym)) { + conf_choice(menu); + if (sym->curr.tri != mod) + return; + goto conf_childs; + } + + switch (sym->type) { + case S_INT: + case S_HEX: + case S_STRING: + conf_string(menu); + break; + default: + conf_sym(menu); + break; + } + +conf_childs: + if (sym) + indent += 2; + for (child = menu->list; child; child = child->next) + conf(child); + if (sym) + indent -= 2; +} + +static void check_conf(struct menu *menu) +{ + struct symbol *sym; + struct menu *child; + + if (!menu_is_visible(menu)) + return; + + sym = menu->sym; + if (sym && !sym_has_value(sym)) { + if (sym_is_changable(sym) || + (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)) { + if (input_mode == listnewconfig) { + if (sym->name && !sym_is_choice_value(sym)) { + printf("%s%s\n", CONFIG_, sym->name); + } + } else if (input_mode != oldnoconfig) { + if (!conf_cnt++) + printf(_("*\n* Restart config...\n*\n")); + rootEntry = menu_get_parent_menu(menu); + conf(rootEntry); + } + } + } + + for (child = menu->list; child; child = child->next) + check_conf(child); +} + +static struct option long_opts[] = { + {"oldaskconfig", no_argument, NULL, oldaskconfig}, + {"oldconfig", no_argument, NULL, oldconfig}, + {"silentoldconfig", no_argument, NULL, silentoldconfig}, + {"defconfig", optional_argument, NULL, defconfig}, + {"savedefconfig", required_argument, NULL, savedefconfig}, + {"allnoconfig", no_argument, NULL, allnoconfig}, + {"allyesconfig", no_argument, NULL, allyesconfig}, + {"allmodconfig", no_argument, NULL, allmodconfig}, + {"alldefconfig", no_argument, NULL, alldefconfig}, + {"randconfig", no_argument, NULL, randconfig}, + {"listnewconfig", no_argument, NULL, listnewconfig}, + {"oldnoconfig", no_argument, NULL, oldnoconfig}, + {NULL, 0, NULL, 0} +}; + +static void conf_usage(const char *progname) +{ + + printf("Usage: %s [option] \n", progname); + printf("[option] is _one_ of the following:\n"); + printf(" --listnewconfig List new options\n"); + printf(" --oldaskconfig Start a new configuration using a line-oriented program\n"); + printf(" --oldconfig Update a configuration using a provided .config as base\n"); + printf(" --silentoldconfig Same as oldconfig, but quietly, additionally update deps\n"); + printf(" --oldnoconfig Same as silentoldconfig but set new symbols to no\n"); + printf(" --defconfig New config with default defined in \n"); + printf(" --savedefconfig Save the minimal current configuration to \n"); + printf(" --allnoconfig New config where all options are answered with no\n"); + printf(" --allyesconfig New config where all options are answered with yes\n"); + printf(" --allmodconfig New config where all options are answered with mod\n"); + printf(" --alldefconfig New config with all symbols set to default\n"); + printf(" --randconfig New config with random answer to all options\n"); +} + +int main(int ac, char **av) +{ + const char *progname = av[0]; + int opt; + const char *name, *defconfig_file = NULL /* gcc uninit */; + struct stat tmpstat; + + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + + while ((opt = getopt_long(ac, av, "", long_opts, NULL)) != -1) { + input_mode = (enum input_mode)opt; + switch (opt) { + case silentoldconfig: + sync_kconfig = 1; + break; + case defconfig: + case savedefconfig: + defconfig_file = optarg; + break; + case randconfig: + { + struct timeval now; + unsigned int seed; + + /* + * Use microseconds derived seed, + * compensate for systems where it may be zero + */ + gettimeofday(&now, NULL); + + seed = (unsigned int)((now.tv_sec + 1) * (now.tv_usec + 1)); + srand(seed); + break; + } + case oldaskconfig: + case oldconfig: + case allnoconfig: + case allyesconfig: + case allmodconfig: + case alldefconfig: + case listnewconfig: + case oldnoconfig: + break; + case '?': + conf_usage(progname); + exit(1); + break; + } + } + if (ac == optind) { + printf(_("%s: Kconfig file missing\n"), av[0]); + conf_usage(progname); + exit(1); + } + name = av[optind]; + conf_parse(name); + //zconfdump(stdout); + if (sync_kconfig) { + name = conf_get_configname(); + if (stat(name, &tmpstat)) { + fprintf(stderr, _("***\n" + "*** Configuration file \"%s\" not found!\n" + "***\n" + "*** Please run some configurator (e.g. \"make oldconfig\" or\n" + "*** \"make menuconfig\" or \"make xconfig\").\n" + "***\n"), name); + exit(1); + } + } + + switch (input_mode) { + case defconfig: + if (!defconfig_file) + defconfig_file = conf_get_default_confname(); + if (conf_read(defconfig_file)) { + printf(_("***\n" + "*** Can't find default configuration \"%s\"!\n" + "***\n"), defconfig_file); + exit(1); + } + break; + case savedefconfig: + case silentoldconfig: + case oldaskconfig: + case oldconfig: + case listnewconfig: + case oldnoconfig: + conf_read(NULL); + break; + case allnoconfig: + case allyesconfig: + case allmodconfig: + case alldefconfig: + case randconfig: + name = getenv("KCONFIG_ALLCONFIG"); + if (!name) + break; + if ((strcmp(name, "") != 0) && (strcmp(name, "1") != 0)) { + if (conf_read_simple(name, S_DEF_USER)) { + fprintf(stderr, + _("*** Can't read seed configuration \"%s\"!\n"), + name); + exit(1); + } + break; + } + switch (input_mode) { + case allnoconfig: name = "allno.config"; break; + case allyesconfig: name = "allyes.config"; break; + case allmodconfig: name = "allmod.config"; break; + case alldefconfig: name = "alldef.config"; break; + case randconfig: name = "allrandom.config"; break; + default: break; + } + if (conf_read_simple(name, S_DEF_USER) && + conf_read_simple("all.config", S_DEF_USER)) { + fprintf(stderr, + _("*** KCONFIG_ALLCONFIG set, but no \"%s\" or \"all.config\" file found\n"), + name); + exit(1); + } + break; + default: + break; + } + + if (sync_kconfig) { + if (conf_get_changed()) { + name = getenv("KCONFIG_NOSILENTUPDATE"); + if (name && *name) { + fprintf(stderr, + _("\n*** The configuration requires explicit update.\n\n")); + return 1; + } + } + valid_stdin = isatty(0) && isatty(1) && isatty(2); + } + + switch (input_mode) { + case allnoconfig: + conf_set_all_new_symbols(def_no); + break; + case allyesconfig: + conf_set_all_new_symbols(def_yes); + break; + case allmodconfig: + conf_set_all_new_symbols(def_mod); + break; + case alldefconfig: + conf_set_all_new_symbols(def_default); + break; + case randconfig: + conf_set_all_new_symbols(def_random); + break; + case defconfig: + conf_set_all_new_symbols(def_default); + break; + case savedefconfig: + break; + case oldaskconfig: + rootEntry = &rootmenu; + conf(&rootmenu); + input_mode = silentoldconfig; + /* fall through */ + case oldconfig: + case listnewconfig: + case oldnoconfig: + case silentoldconfig: + /* Update until a loop caused no more changes */ + do { + conf_cnt = 0; + check_conf(&rootmenu); + } while (conf_cnt && + (input_mode != listnewconfig && + input_mode != oldnoconfig)); + break; + } + + if (sync_kconfig) { + /* silentoldconfig is used during the build so we shall update autoconf. + * All other commands are only used to generate a config. + */ + if (conf_get_changed() && conf_write(NULL)) { + fprintf(stderr, _("\n*** Error during writing of the configuration.\n\n")); + exit(1); + } + if (conf_write_autoconf()) { + fprintf(stderr, _("\n*** Error during update of the configuration.\n\n")); + return 1; + } + } else if (input_mode == savedefconfig) { + if (conf_write_defconfig(defconfig_file)) { + fprintf(stderr, _("n*** Error while saving defconfig to: %s\n\n"), + defconfig_file); + return 1; + } + } else if (input_mode != listnewconfig) { + if (conf_write(NULL)) { + fprintf(stderr, _("\n*** Error during writing of the configuration.\n\n")); + exit(1); + } + } + return 0; +} + +/* + * Helper function to facilitate fgets() by Jean Sacren. + */ +void xfgets(char *str, int size, FILE *in) +{ + if (fgets(str, size, in) == NULL) + fprintf(stderr, "\nError in reading or end of file.\n"); +} diff --git a/kernel/fiasco/tool/kconfig/scripts/kconfig/confdata.c b/kernel/fiasco/tool/kconfig/scripts/kconfig/confdata.c new file mode 100644 index 00000000..bcc2719d --- /dev/null +++ b/kernel/fiasco/tool/kconfig/scripts/kconfig/confdata.c @@ -0,0 +1,1107 @@ +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "lkc.h" + +static void conf_warning(const char *fmt, ...) + __attribute__ ((format (printf, 1, 2))); + +static void conf_message(const char *fmt, ...) + __attribute__ ((format (printf, 1, 2))); + +static const char *conf_filename; +static int conf_lineno, conf_warnings, conf_unsaved; + +const char conf_defname[] = "arch/$ARCH/defconfig"; + +static void conf_warning(const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + fprintf(stderr, "%s:%d:warning: ", conf_filename, conf_lineno); + vfprintf(stderr, fmt, ap); + fprintf(stderr, "\n"); + va_end(ap); + conf_warnings++; +} + +static void conf_default_message_callback(const char *fmt, va_list ap) +{ + printf("#\n# "); + vprintf(fmt, ap); + printf("\n#\n"); +} + +static void (*conf_message_callback) (const char *fmt, va_list ap) = + conf_default_message_callback; +void conf_set_message_callback(void (*fn) (const char *fmt, va_list ap)) +{ + conf_message_callback = fn; +} + +static void conf_message(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + if (conf_message_callback) + conf_message_callback(fmt, ap); +} + +const char *conf_get_configname(void) +{ + char *name = getenv("KCONFIG_CONFIG"); + + return name ? name : ".config"; +} + +const char *conf_get_autoconfig_name(void) +{ + char *name = getenv("KCONFIG_AUTOCONFIG"); + + return name ? name : "include/config/auto.conf"; +} + +static char *conf_expand_value(const char *in) +{ + struct symbol *sym; + const char *src; + static char res_value[SYMBOL_MAXLENGTH]; + char *dst, name[SYMBOL_MAXLENGTH]; + + res_value[0] = 0; + dst = name; + while ((src = strchr(in, '$'))) { + strncat(res_value, in, src - in); + src++; + dst = name; + while (isalnum(*src) || *src == '_') + *dst++ = *src++; + *dst = 0; + sym = sym_lookup(name, 0); + sym_calc_value(sym); + strcat(res_value, sym_get_string_value(sym)); + in = src; + } + strcat(res_value, in); + + return res_value; +} + +char *conf_get_default_confname(void) +{ + struct stat buf; + static char fullname[PATH_MAX+1]; + char *env, *name; + + name = conf_expand_value(conf_defname); + env = getenv(SRCTREE); + if (env) { + sprintf(fullname, "%s/%s", env, name); + if (!stat(fullname, &buf)) + return fullname; + } + return name; +} + +static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p) +{ + char *p2; + + switch (sym->type) { + case S_TRISTATE: + if (p[0] == 'm') { + sym->def[def].tri = mod; + sym->flags |= def_flags; + break; + } + /* fall through */ + case S_BOOLEAN: + if (p[0] == 'y') { + sym->def[def].tri = yes; + sym->flags |= def_flags; + break; + } + if (p[0] == 'n') { + sym->def[def].tri = no; + sym->flags |= def_flags; + break; + } + conf_warning("symbol value '%s' invalid for %s", p, sym->name); + return 1; + case S_OTHER: + if (*p != '"') { + for (p2 = p; *p2 && !isspace(*p2); p2++) + ; + sym->type = S_STRING; + goto done; + } + /* fall through */ + case S_STRING: + if (*p++ != '"') + break; + for (p2 = p; (p2 = strpbrk(p2, "\"\\")); p2++) { + if (*p2 == '"') { + *p2 = 0; + break; + } + memmove(p2, p2 + 1, strlen(p2)); + } + if (!p2) { + conf_warning("invalid string found"); + return 1; + } + /* fall through */ + case S_INT: + case S_HEX: + done: + if (sym_string_valid(sym, p)) { + sym->def[def].val = strdup(p); + sym->flags |= def_flags; + } else { + conf_warning("symbol value '%s' invalid for %s", p, sym->name); + return 1; + } + break; + default: + ; + } + return 0; +} + +int conf_read_simple(const char *name, int def) +{ + FILE *in = NULL; + char line[1024]; + char *p, *p2; + struct symbol *sym; + int i, def_flags; + + if (name) { + in = zconf_fopen(name); + } else { + struct property *prop; + + name = conf_get_configname(); + in = zconf_fopen(name); + if (in) + goto load; + sym_add_change_count(1); + if (!sym_defconfig_list) { + if (modules_sym) + sym_calc_value(modules_sym); + return 1; + } + + for_all_defaults(sym_defconfig_list, prop) { + if (expr_calc_value(prop->visible.expr) == no || + prop->expr->type != E_SYMBOL) + continue; + name = conf_expand_value(prop->expr->left.sym->name); + in = zconf_fopen(name); + if (in) { + conf_message(_("using defaults found in %s"), + name); + goto load; + } + } + } + if (!in) + return 1; + +load: + conf_filename = name; + conf_lineno = 0; + conf_warnings = 0; + conf_unsaved = 0; + + def_flags = SYMBOL_DEF << def; + for_all_symbols(i, sym) { + sym->flags |= SYMBOL_CHANGED; + sym->flags &= ~(def_flags|SYMBOL_VALID); + if (sym_is_choice(sym)) + sym->flags |= def_flags; + switch (sym->type) { + case S_INT: + case S_HEX: + case S_STRING: + if (sym->def[def].val) + free(sym->def[def].val); + /* fall through */ + default: + sym->def[def].val = NULL; + sym->def[def].tri = no; + } + } + + while (fgets(line, sizeof(line), in)) { + conf_lineno++; + sym = NULL; + if (line[0] == '#') { + if (memcmp(line + 2, CONFIG_, strlen(CONFIG_))) + continue; + p = strchr(line + 2 + strlen(CONFIG_), ' '); + if (!p) + continue; + *p++ = 0; + if (strncmp(p, "is not set", 10)) + continue; + if (def == S_DEF_USER) { + sym = sym_find(line + 2 + strlen(CONFIG_)); + if (!sym) { + sym_add_change_count(1); + goto setsym; + } + } else { + sym = sym_lookup(line + 2 + strlen(CONFIG_), 0); + if (sym->type == S_UNKNOWN) + sym->type = S_BOOLEAN; + } + if (sym->flags & def_flags) { + conf_warning("override: reassigning to symbol %s", sym->name); + } + switch (sym->type) { + case S_BOOLEAN: + case S_TRISTATE: + sym->def[def].tri = no; + sym->flags |= def_flags; + break; + default: + ; + } + } else if (memcmp(line, CONFIG_, strlen(CONFIG_)) == 0) { + p = strchr(line + strlen(CONFIG_), '='); + if (!p) + continue; + *p++ = 0; + p2 = strchr(p, '\n'); + if (p2) { + *p2-- = 0; + if (*p2 == '\r') + *p2 = 0; + } + if (def == S_DEF_USER) { + sym = sym_find(line + strlen(CONFIG_)); + if (!sym) { + sym_add_change_count(1); + goto setsym; + } + } else { + sym = sym_lookup(line + strlen(CONFIG_), 0); + if (sym->type == S_UNKNOWN) + sym->type = S_OTHER; + } + if (sym->flags & def_flags) { + conf_warning("override: reassigning to symbol %s", sym->name); + } + if (conf_set_sym_val(sym, def, def_flags, p)) + continue; + } else { + if (line[0] != '\r' && line[0] != '\n') + conf_warning("unexpected data"); + continue; + } +setsym: + if (sym && sym_is_choice_value(sym)) { + struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym)); + switch (sym->def[def].tri) { + case no: + break; + case mod: + if (cs->def[def].tri == yes) { + conf_warning("%s creates inconsistent choice state", sym->name); + cs->flags &= ~def_flags; + } + break; + case yes: + if (cs->def[def].tri != no) + conf_warning("override: %s changes choice state", sym->name); + cs->def[def].val = sym; + break; + } + cs->def[def].tri = EXPR_OR(cs->def[def].tri, sym->def[def].tri); + } + } + fclose(in); + + if (modules_sym) + sym_calc_value(modules_sym); + return 0; +} + +int conf_read(const char *name) +{ + struct symbol *sym; + int i; + + sym_set_change_count(0); + + if (conf_read_simple(name, S_DEF_USER)) + return 1; + + for_all_symbols(i, sym) { + sym_calc_value(sym); + if (sym_is_choice(sym) || (sym->flags & SYMBOL_AUTO)) + continue; + if (sym_has_value(sym) && (sym->flags & SYMBOL_WRITE)) { + /* check that calculated value agrees with saved value */ + switch (sym->type) { + case S_BOOLEAN: + case S_TRISTATE: + if (sym->def[S_DEF_USER].tri != sym_get_tristate_value(sym)) + break; + if (!sym_is_choice(sym)) + continue; + /* fall through */ + default: + if (!strcmp(sym->curr.val, sym->def[S_DEF_USER].val)) + continue; + break; + } + } else if (!sym_has_value(sym) && !(sym->flags & SYMBOL_WRITE)) + /* no previous value and not saved */ + continue; + conf_unsaved++; + /* maybe print value in verbose mode... */ + } + + for_all_symbols(i, sym) { + if (sym_has_value(sym) && !sym_is_choice_value(sym)) { + /* Reset values of generates values, so they'll appear + * as new, if they should become visible, but that + * doesn't quite work if the Kconfig and the saved + * configuration disagree. + */ + if (sym->visible == no && !conf_unsaved) + sym->flags &= ~SYMBOL_DEF_USER; + switch (sym->type) { + case S_STRING: + case S_INT: + case S_HEX: + /* Reset a string value if it's out of range */ + if (sym_string_within_range(sym, sym->def[S_DEF_USER].val)) + break; + sym->flags &= ~(SYMBOL_VALID|SYMBOL_DEF_USER); + conf_unsaved++; + break; + default: + break; + } + } + } + + sym_add_change_count(conf_warnings || conf_unsaved); + + return 0; +} + +/* + * Kconfig configuration printer + * + * This printer is used when generating the resulting configuration after + * kconfig invocation and `defconfig' files. Unset symbol might be omitted by + * passing a non-NULL argument to the printer. + * + */ +static void +kconfig_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg) +{ + + switch (sym->type) { + case S_BOOLEAN: + case S_TRISTATE: + if (*value == 'n') { + bool skip_unset = (arg != NULL); + + if (!skip_unset) + fprintf(fp, "# %s%s is not set\n", + CONFIG_, sym->name); + return; + } + break; + default: + break; + } + + fprintf(fp, "%s%s=%s\n", CONFIG_, sym->name, value); +} + +static void +kconfig_print_comment(FILE *fp, const char *value, void *arg) +{ + const char *p = value; + size_t l; + + for (;;) { + l = strcspn(p, "\n"); + fprintf(fp, "#"); + if (l) { + fprintf(fp, " "); + xfwrite(p, l, 1, fp); + p += l; + } + fprintf(fp, "\n"); + if (*p++ == '\0') + break; + } +} + +static struct conf_printer kconfig_printer_cb = +{ + .print_symbol = kconfig_print_symbol, + .print_comment = kconfig_print_comment, +}; + +/* + * Header printer + * + * This printer is used when generating the `include/generated/autoconf.h' file. + */ +static void +header_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg) +{ + + switch (sym->type) { + case S_BOOLEAN: + case S_TRISTATE: { + const char *suffix = ""; + + switch (*value) { + case 'n': + break; + case 'm': + suffix = "_MODULE"; + /* fall through */ + default: + fprintf(fp, "#define %s%s%s 1\n", + CONFIG_, sym->name, suffix); + } + break; + } + case S_HEX: { + const char *prefix = ""; + + if (value[0] != '0' || (value[1] != 'x' && value[1] != 'X')) + prefix = "0x"; + fprintf(fp, "#define %s%s %s%s\n", + CONFIG_, sym->name, prefix, value); + break; + } + case S_STRING: + case S_INT: + fprintf(fp, "#define %s%s %s\n", + CONFIG_, sym->name, value); + break; + default: + break; + } + +} + +static void +header_print_comment(FILE *fp, const char *value, void *arg) +{ + const char *p = value; + size_t l; + + fprintf(fp, "/*\n"); + for (;;) { + l = strcspn(p, "\n"); + fprintf(fp, " *"); + if (l) { + fprintf(fp, " "); + xfwrite(p, l, 1, fp); + p += l; + } + fprintf(fp, "\n"); + if (*p++ == '\0') + break; + } + fprintf(fp, " */\n"); +} + +static struct conf_printer header_printer_cb = +{ + .print_symbol = header_print_symbol, + .print_comment = header_print_comment, +}; + +/* + * Tristate printer + * + * This printer is used when generating the `include/config/tristate.conf' file. + */ +static void +tristate_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg) +{ + + if (sym->type == S_TRISTATE && *value != 'n') + fprintf(fp, "%s%s=%c\n", CONFIG_, sym->name, (char)toupper(*value)); +} + +static struct conf_printer tristate_printer_cb = +{ + .print_symbol = tristate_print_symbol, + .print_comment = kconfig_print_comment, +}; + +static void conf_write_symbol(FILE *fp, struct symbol *sym, + struct conf_printer *printer, void *printer_arg) +{ + const char *str; + + switch (sym->type) { + case S_OTHER: + case S_UNKNOWN: + break; + case S_STRING: + str = sym_get_string_value(sym); + str = sym_escape_string_value(str); + printer->print_symbol(fp, sym, str, printer_arg); + free((void *)str); + break; + default: + str = sym_get_string_value(sym); + printer->print_symbol(fp, sym, str, printer_arg); + } +} + +static void +conf_write_heading(FILE *fp, struct conf_printer *printer, void *printer_arg) +{ + char buf[256]; + + snprintf(buf, sizeof(buf), + "\n" + "Automatically generated file; DO NOT EDIT.\n" + "%s\n", + rootmenu.prompt->text); + + printer->print_comment(fp, buf, printer_arg); +} + +/* + * Write out a minimal config. + * All values that has default values are skipped as this is redundant. + */ +int conf_write_defconfig(const char *filename) +{ + struct symbol *sym; + struct menu *menu; + FILE *out; + + out = fopen(filename, "w"); + if (!out) + return 1; + + sym_clear_all_valid(); + + /* Traverse all menus to find all relevant symbols */ + menu = rootmenu.list; + + while (menu != NULL) + { + sym = menu->sym; + if (sym == NULL) { + if (!menu_is_visible(menu)) + goto next_menu; + } else if (!sym_is_choice(sym)) { + sym_calc_value(sym); + if (!(sym->flags & SYMBOL_WRITE)) + goto next_menu; + sym->flags &= ~SYMBOL_WRITE; + /* If we cannot change the symbol - skip */ + if (!sym_is_changable(sym)) + goto next_menu; + /* If symbol equals to default value - skip */ + if (strcmp(sym_get_string_value(sym), sym_get_string_default(sym)) == 0) + goto next_menu; + + /* + * If symbol is a choice value and equals to the + * default for a choice - skip. + * But only if value is bool and equal to "y" and + * choice is not "optional". + * (If choice is "optional" then all values can be "n") + */ + if (sym_is_choice_value(sym)) { + struct symbol *cs; + struct symbol *ds; + + cs = prop_get_symbol(sym_get_choice_prop(sym)); + ds = sym_choice_default(cs); + if (!sym_is_optional(cs) && sym == ds) { + if ((sym->type == S_BOOLEAN) && + sym_get_tristate_value(sym) == yes) + goto next_menu; + } + } + conf_write_symbol(out, sym, &kconfig_printer_cb, NULL); + } +next_menu: + if (menu->list != NULL) { + menu = menu->list; + } + else if (menu->next != NULL) { + menu = menu->next; + } else { + while ((menu = menu->parent)) { + if (menu->next != NULL) { + menu = menu->next; + break; + } + } + } + } + fclose(out); + return 0; +} + +int conf_write(const char *name) +{ + FILE *out; + struct symbol *sym; + struct menu *menu; + const char *basename; + const char *str; + char dirname[PATH_MAX+1], tmpname[PATH_MAX+1], newname[PATH_MAX+1]; + char *env; + + dirname[0] = 0; + if (name && name[0]) { + struct stat st; + char *slash; + + if (!stat(name, &st) && S_ISDIR(st.st_mode)) { + strcpy(dirname, name); + strcat(dirname, "/"); + basename = conf_get_configname(); + } else if ((slash = strrchr(name, '/'))) { + int size = slash - name + 1; + memcpy(dirname, name, size); + dirname[size] = 0; + if (slash[1]) + basename = slash + 1; + else + basename = conf_get_configname(); + } else + basename = name; + } else + basename = conf_get_configname(); + + sprintf(newname, "%s%s", dirname, basename); + env = getenv("KCONFIG_OVERWRITECONFIG"); + if (!env || !*env) { + sprintf(tmpname, "%s.tmpconfig.%d", dirname, (int)getpid()); + out = fopen(tmpname, "w"); + } else { + *tmpname = 0; + out = fopen(newname, "w"); + } + if (!out) + return 1; + + conf_write_heading(out, &kconfig_printer_cb, NULL); + + if (!conf_get_changed()) + sym_clear_all_valid(); + + menu = rootmenu.list; + while (menu) { + sym = menu->sym; + if (!sym) { + if (!menu_is_visible(menu)) + goto next; + str = menu_get_prompt(menu); + fprintf(out, "\n" + "#\n" + "# %s\n" + "#\n", str); + } else if (!(sym->flags & SYMBOL_CHOICE)) { + sym_calc_value(sym); + if (!(sym->flags & SYMBOL_WRITE)) + goto next; + sym->flags &= ~SYMBOL_WRITE; + + conf_write_symbol(out, sym, &kconfig_printer_cb, NULL); + } + +next: + if (menu->list) { + menu = menu->list; + continue; + } + if (menu->next) + menu = menu->next; + else while ((menu = menu->parent)) { + if (menu->next) { + menu = menu->next; + break; + } + } + } + fclose(out); + + if (*tmpname) { + strcat(dirname, basename); + strcat(dirname, ".old"); + rename(newname, dirname); + if (rename(tmpname, newname)) + return 1; + } + + conf_message(_("configuration written to %s"), newname); + + sym_set_change_count(0); + + return 0; +} + +static int conf_split_config(void) +{ + const char *name; + char path[PATH_MAX+1]; + char *s, *d, c; + struct symbol *sym; + struct stat sb; + int res, i, fd; + + name = conf_get_autoconfig_name(); + conf_read_simple(name, S_DEF_AUTO); + + if (chdir("config")) + return 1; + + res = 0; + for_all_symbols(i, sym) { + sym_calc_value(sym); + if ((sym->flags & SYMBOL_AUTO) || !sym->name) + continue; + if (sym->flags & SYMBOL_WRITE) { + if (sym->flags & SYMBOL_DEF_AUTO) { + /* + * symbol has old and new value, + * so compare them... + */ + switch (sym->type) { + case S_BOOLEAN: + case S_TRISTATE: + if (sym_get_tristate_value(sym) == + sym->def[S_DEF_AUTO].tri) + continue; + break; + case S_STRING: + case S_HEX: + case S_INT: + if (!strcmp(sym_get_string_value(sym), + sym->def[S_DEF_AUTO].val)) + continue; + break; + default: + break; + } + } else { + /* + * If there is no old value, only 'no' (unset) + * is allowed as new value. + */ + switch (sym->type) { + case S_BOOLEAN: + case S_TRISTATE: + if (sym_get_tristate_value(sym) == no) + continue; + break; + default: + break; + } + } + } else if (!(sym->flags & SYMBOL_DEF_AUTO)) + /* There is neither an old nor a new value. */ + continue; + /* else + * There is an old value, but no new value ('no' (unset) + * isn't saved in auto.conf, so the old value is always + * different from 'no'). + */ + + /* Replace all '_' and append ".h" */ + s = sym->name; + d = path; + while ((c = *s++)) { + c = tolower(c); + *d++ = (c == '_') ? '/' : c; + } + strcpy(d, ".h"); + + /* Assume directory path already exists. */ + fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644); + if (fd == -1) { + if (errno != ENOENT) { + res = 1; + break; + } + /* + * Create directory components, + * unless they exist already. + */ + d = path; + while ((d = strchr(d, '/'))) { + *d = 0; + if (stat(path, &sb) && mkdir(path, 0755)) { + res = 1; + goto out; + } + *d++ = '/'; + } + /* Try it again. */ + fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644); + if (fd == -1) { + res = 1; + break; + } + } + close(fd); + } +out: + if (chdir("..")) + return 1; + + return res; +} + +int conf_write_autoconf(void) +{ + struct symbol *sym; + const char *name; + FILE *out, *tristate, *out_h; + int i; + + sym_clear_all_valid(); + + file_write_dep("config/auto.conf.cmd"); + + if (conf_split_config()) + return 1; + + out = fopen(".tmpconfig", "w"); + if (!out) + return 1; + + tristate = fopen(".tmpconfig_tristate", "w"); + if (!tristate) { + fclose(out); + return 1; + } + + out_h = fopen(".tmpconfig.h", "w"); + if (!out_h) { + fclose(out); + fclose(tristate); + return 1; + } + + conf_write_heading(out, &kconfig_printer_cb, NULL); + + conf_write_heading(tristate, &tristate_printer_cb, NULL); + + conf_write_heading(out_h, &header_printer_cb, NULL); + + for_all_symbols(i, sym) { + sym_calc_value(sym); + if (!(sym->flags & SYMBOL_WRITE) || !sym->name) + continue; + + /* write symbol to auto.conf, tristate and header files */ + conf_write_symbol(out, sym, &kconfig_printer_cb, (void *)1); + + conf_write_symbol(tristate, sym, &tristate_printer_cb, (void *)1); + + conf_write_symbol(out_h, sym, &header_printer_cb, NULL); + } + fclose(out); + fclose(tristate); + fclose(out_h); + + name = getenv("KCONFIG_AUTOHEADER"); + if (!name) + name = "include/generated/autoconf.h"; + if (rename(".tmpconfig.h", name)) + return 1; + name = getenv("KCONFIG_TRISTATE"); + if (!name) + name = "include/config/tristate.conf"; + if (rename(".tmpconfig_tristate", name)) + return 1; + name = conf_get_autoconfig_name(); + /* + * This must be the last step, kbuild has a dependency on auto.conf + * and this marks the successful completion of the previous steps. + */ + if (rename(".tmpconfig", name)) + return 1; + + return 0; +} + +static int sym_change_count; +static void (*conf_changed_callback)(void); + +void sym_set_change_count(int count) +{ + int _sym_change_count = sym_change_count; + sym_change_count = count; + if (conf_changed_callback && + (bool)_sym_change_count != (bool)count) + conf_changed_callback(); +} + +void sym_add_change_count(int count) +{ + sym_set_change_count(count + sym_change_count); +} + +bool conf_get_changed(void) +{ + return sym_change_count; +} + +void conf_set_changed_callback(void (*fn)(void)) +{ + conf_changed_callback = fn; +} + +static void randomize_choice_values(struct symbol *csym) +{ + struct property *prop; + struct symbol *sym; + struct expr *e; + int cnt, def; + + /* + * If choice is mod then we may have more items selected + * and if no then no-one. + * In both cases stop. + */ + if (csym->curr.tri != yes) + return; + + prop = sym_get_choice_prop(csym); + + /* count entries in choice block */ + cnt = 0; + expr_list_for_each_sym(prop->expr, e, sym) + cnt++; + + /* + * find a random value and set it to yes, + * set the rest to no so we have only one set + */ + def = (rand() % cnt); + + cnt = 0; + expr_list_for_each_sym(prop->expr, e, sym) { + if (def == cnt++) { + sym->def[S_DEF_USER].tri = yes; + csym->def[S_DEF_USER].val = sym; + } + else { + sym->def[S_DEF_USER].tri = no; + } + } + csym->flags |= SYMBOL_DEF_USER; + /* clear VALID to get value calculated */ + csym->flags &= ~(SYMBOL_VALID); +} + +static void set_all_choice_values(struct symbol *csym) +{ + struct property *prop; + struct symbol *sym; + struct expr *e; + + prop = sym_get_choice_prop(csym); + + /* + * Set all non-assinged choice values to no + */ + expr_list_for_each_sym(prop->expr, e, sym) { + if (!sym_has_value(sym)) + sym->def[S_DEF_USER].tri = no; + } + csym->flags |= SYMBOL_DEF_USER; + /* clear VALID to get value calculated */ + csym->flags &= ~(SYMBOL_VALID); +} + +void conf_set_all_new_symbols(enum conf_def_mode mode) +{ + struct symbol *sym, *csym; + int i, cnt; + + for_all_symbols(i, sym) { + if (sym_has_value(sym)) + continue; + switch (sym_get_type(sym)) { + case S_BOOLEAN: + case S_TRISTATE: + switch (mode) { + case def_yes: + sym->def[S_DEF_USER].tri = yes; + break; + case def_mod: + sym->def[S_DEF_USER].tri = mod; + break; + case def_no: + sym->def[S_DEF_USER].tri = no; + break; + case def_random: + cnt = sym_get_type(sym) == S_TRISTATE ? 3 : 2; + sym->def[S_DEF_USER].tri = (tristate)(rand() % cnt); + break; + default: + continue; + } + if (!(sym_is_choice(sym) && mode == def_random)) + sym->flags |= SYMBOL_DEF_USER; + break; + default: + break; + } + + } + + sym_clear_all_valid(); + + /* + * We have different type of choice blocks. + * If curr.tri equals to mod then we can select several + * choice symbols in one block. + * In this case we do nothing. + * If curr.tri equals yes then only one symbol can be + * selected in a choice block and we set it to yes, + * and the rest to no. + */ + for_all_symbols(i, csym) { + if (sym_has_value(csym) || !sym_is_choice(csym)) + continue; + + sym_calc_value(csym); + if (mode == def_random) + randomize_choice_values(csym); + else + set_all_choice_values(csym); + } +} diff --git a/kernel/fiasco/tool/kconfig/scripts/kconfig/expr.c b/kernel/fiasco/tool/kconfig/scripts/kconfig/expr.c new file mode 100644 index 00000000..290ce41f --- /dev/null +++ b/kernel/fiasco/tool/kconfig/scripts/kconfig/expr.c @@ -0,0 +1,1168 @@ +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +#include +#include +#include + +#include "lkc.h" + +#define DEBUG_EXPR 0 + +struct expr *expr_alloc_symbol(struct symbol *sym) +{ + struct expr *e = calloc(1, sizeof(*e)); + e->type = E_SYMBOL; + e->left.sym = sym; + return e; +} + +struct expr *expr_alloc_one(enum expr_type type, struct expr *ce) +{ + struct expr *e = calloc(1, sizeof(*e)); + e->type = type; + e->left.expr = ce; + return e; +} + +struct expr *expr_alloc_two(enum expr_type type, struct expr *e1, struct expr *e2) +{ + struct expr *e = calloc(1, sizeof(*e)); + e->type = type; + e->left.expr = e1; + e->right.expr = e2; + return e; +} + +struct expr *expr_alloc_comp(enum expr_type type, struct symbol *s1, struct symbol *s2) +{ + struct expr *e = calloc(1, sizeof(*e)); + e->type = type; + e->left.sym = s1; + e->right.sym = s2; + return e; +} + +struct expr *expr_alloc_and(struct expr *e1, struct expr *e2) +{ + if (!e1) + return e2; + return e2 ? expr_alloc_two(E_AND, e1, e2) : e1; +} + +struct expr *expr_alloc_or(struct expr *e1, struct expr *e2) +{ + if (!e1) + return e2; + return e2 ? expr_alloc_two(E_OR, e1, e2) : e1; +} + +struct expr *expr_copy(const struct expr *org) +{ + struct expr *e; + + if (!org) + return NULL; + + e = malloc(sizeof(*org)); + memcpy(e, org, sizeof(*org)); + switch (org->type) { + case E_SYMBOL: + e->left = org->left; + break; + case E_NOT: + e->left.expr = expr_copy(org->left.expr); + break; + case E_EQUAL: + case E_UNEQUAL: + e->left.sym = org->left.sym; + e->right.sym = org->right.sym; + break; + case E_AND: + case E_OR: + case E_LIST: + e->left.expr = expr_copy(org->left.expr); + e->right.expr = expr_copy(org->right.expr); + break; + default: + printf("can't copy type %d\n", e->type); + free(e); + e = NULL; + break; + } + + return e; +} + +void expr_free(struct expr *e) +{ + if (!e) + return; + + switch (e->type) { + case E_SYMBOL: + break; + case E_NOT: + expr_free(e->left.expr); + return; + case E_EQUAL: + case E_UNEQUAL: + break; + case E_OR: + case E_AND: + expr_free(e->left.expr); + expr_free(e->right.expr); + break; + default: + printf("how to free type %d?\n", e->type); + break; + } + free(e); +} + +static int trans_count; + +#define e1 (*ep1) +#define e2 (*ep2) + +static void __expr_eliminate_eq(enum expr_type type, struct expr **ep1, struct expr **ep2) +{ + if (e1->type == type) { + __expr_eliminate_eq(type, &e1->left.expr, &e2); + __expr_eliminate_eq(type, &e1->right.expr, &e2); + return; + } + if (e2->type == type) { + __expr_eliminate_eq(type, &e1, &e2->left.expr); + __expr_eliminate_eq(type, &e1, &e2->right.expr); + return; + } + if (e1->type == E_SYMBOL && e2->type == E_SYMBOL && + e1->left.sym == e2->left.sym && + (e1->left.sym == &symbol_yes || e1->left.sym == &symbol_no)) + return; + if (!expr_eq(e1, e2)) + return; + trans_count++; + expr_free(e1); expr_free(e2); + switch (type) { + case E_OR: + e1 = expr_alloc_symbol(&symbol_no); + e2 = expr_alloc_symbol(&symbol_no); + break; + case E_AND: + e1 = expr_alloc_symbol(&symbol_yes); + e2 = expr_alloc_symbol(&symbol_yes); + break; + default: + ; + } +} + +void expr_eliminate_eq(struct expr **ep1, struct expr **ep2) +{ + if (!e1 || !e2) + return; + switch (e1->type) { + case E_OR: + case E_AND: + __expr_eliminate_eq(e1->type, ep1, ep2); + default: + ; + } + if (e1->type != e2->type) switch (e2->type) { + case E_OR: + case E_AND: + __expr_eliminate_eq(e2->type, ep1, ep2); + default: + ; + } + e1 = expr_eliminate_yn(e1); + e2 = expr_eliminate_yn(e2); +} + +#undef e1 +#undef e2 + +int expr_eq(struct expr *e1, struct expr *e2) +{ + int res, old_count; + + if (e1->type != e2->type) + return 0; + switch (e1->type) { + case E_EQUAL: + case E_UNEQUAL: + return e1->left.sym == e2->left.sym && e1->right.sym == e2->right.sym; + case E_SYMBOL: + return e1->left.sym == e2->left.sym; + case E_NOT: + return expr_eq(e1->left.expr, e2->left.expr); + case E_AND: + case E_OR: + e1 = expr_copy(e1); + e2 = expr_copy(e2); + old_count = trans_count; + expr_eliminate_eq(&e1, &e2); + res = (e1->type == E_SYMBOL && e2->type == E_SYMBOL && + e1->left.sym == e2->left.sym); + expr_free(e1); + expr_free(e2); + trans_count = old_count; + return res; + case E_LIST: + case E_RANGE: + case E_NONE: + /* panic */; + } + + if (DEBUG_EXPR) { + expr_fprint(e1, stdout); + printf(" = "); + expr_fprint(e2, stdout); + printf(" ?\n"); + } + + return 0; +} + +struct expr *expr_eliminate_yn(struct expr *e) +{ + struct expr *tmp; + + if (e) switch (e->type) { + case E_AND: + e->left.expr = expr_eliminate_yn(e->left.expr); + e->right.expr = expr_eliminate_yn(e->right.expr); + if (e->left.expr->type == E_SYMBOL) { + if (e->left.expr->left.sym == &symbol_no) { + expr_free(e->left.expr); + expr_free(e->right.expr); + e->type = E_SYMBOL; + e->left.sym = &symbol_no; + e->right.expr = NULL; + return e; + } else if (e->left.expr->left.sym == &symbol_yes) { + free(e->left.expr); + tmp = e->right.expr; + *e = *(e->right.expr); + free(tmp); + return e; + } + } + if (e->right.expr->type == E_SYMBOL) { + if (e->right.expr->left.sym == &symbol_no) { + expr_free(e->left.expr); + expr_free(e->right.expr); + e->type = E_SYMBOL; + e->left.sym = &symbol_no; + e->right.expr = NULL; + return e; + } else if (e->right.expr->left.sym == &symbol_yes) { + free(e->right.expr); + tmp = e->left.expr; + *e = *(e->left.expr); + free(tmp); + return e; + } + } + break; + case E_OR: + e->left.expr = expr_eliminate_yn(e->left.expr); + e->right.expr = expr_eliminate_yn(e->right.expr); + if (e->left.expr->type == E_SYMBOL) { + if (e->left.expr->left.sym == &symbol_no) { + free(e->left.expr); + tmp = e->right.expr; + *e = *(e->right.expr); + free(tmp); + return e; + } else if (e->left.expr->left.sym == &symbol_yes) { + expr_free(e->left.expr); + expr_free(e->right.expr); + e->type = E_SYMBOL; + e->left.sym = &symbol_yes; + e->right.expr = NULL; + return e; + } + } + if (e->right.expr->type == E_SYMBOL) { + if (e->right.expr->left.sym == &symbol_no) { + free(e->right.expr); + tmp = e->left.expr; + *e = *(e->left.expr); + free(tmp); + return e; + } else if (e->right.expr->left.sym == &symbol_yes) { + expr_free(e->left.expr); + expr_free(e->right.expr); + e->type = E_SYMBOL; + e->left.sym = &symbol_yes; + e->right.expr = NULL; + return e; + } + } + break; + default: + ; + } + return e; +} + +/* + * bool FOO!=n => FOO + */ +struct expr *expr_trans_bool(struct expr *e) +{ + if (!e) + return NULL; + switch (e->type) { + case E_AND: + case E_OR: + case E_NOT: + e->left.expr = expr_trans_bool(e->left.expr); + e->right.expr = expr_trans_bool(e->right.expr); + break; + case E_UNEQUAL: + // FOO!=n -> FOO + if (e->left.sym->type == S_TRISTATE) { + if (e->right.sym == &symbol_no) { + e->type = E_SYMBOL; + e->right.sym = NULL; + } + } + break; + default: + ; + } + return e; +} + +/* + * e1 || e2 -> ? + */ +static struct expr *expr_join_or(struct expr *e1, struct expr *e2) +{ + struct expr *tmp; + struct symbol *sym1, *sym2; + + if (expr_eq(e1, e2)) + return expr_copy(e1); + if (e1->type != E_EQUAL && e1->type != E_UNEQUAL && e1->type != E_SYMBOL && e1->type != E_NOT) + return NULL; + if (e2->type != E_EQUAL && e2->type != E_UNEQUAL && e2->type != E_SYMBOL && e2->type != E_NOT) + return NULL; + if (e1->type == E_NOT) { + tmp = e1->left.expr; + if (tmp->type != E_EQUAL && tmp->type != E_UNEQUAL && tmp->type != E_SYMBOL) + return NULL; + sym1 = tmp->left.sym; + } else + sym1 = e1->left.sym; + if (e2->type == E_NOT) { + if (e2->left.expr->type != E_SYMBOL) + return NULL; + sym2 = e2->left.expr->left.sym; + } else + sym2 = e2->left.sym; + if (sym1 != sym2) + return NULL; + if (sym1->type != S_BOOLEAN && sym1->type != S_TRISTATE) + return NULL; + if (sym1->type == S_TRISTATE) { + if (e1->type == E_EQUAL && e2->type == E_EQUAL && + ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_mod) || + (e1->right.sym == &symbol_mod && e2->right.sym == &symbol_yes))) { + // (a='y') || (a='m') -> (a!='n') + return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_no); + } + if (e1->type == E_EQUAL && e2->type == E_EQUAL && + ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_no) || + (e1->right.sym == &symbol_no && e2->right.sym == &symbol_yes))) { + // (a='y') || (a='n') -> (a!='m') + return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_mod); + } + if (e1->type == E_EQUAL && e2->type == E_EQUAL && + ((e1->right.sym == &symbol_mod && e2->right.sym == &symbol_no) || + (e1->right.sym == &symbol_no && e2->right.sym == &symbol_mod))) { + // (a='m') || (a='n') -> (a!='y') + return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_yes); + } + } + if (sym1->type == S_BOOLEAN && sym1 == sym2) { + if ((e1->type == E_NOT && e1->left.expr->type == E_SYMBOL && e2->type == E_SYMBOL) || + (e2->type == E_NOT && e2->left.expr->type == E_SYMBOL && e1->type == E_SYMBOL)) + return expr_alloc_symbol(&symbol_yes); + } + + if (DEBUG_EXPR) { + printf("optimize ("); + expr_fprint(e1, stdout); + printf(") || ("); + expr_fprint(e2, stdout); + printf(")?\n"); + } + return NULL; +} + +static struct expr *expr_join_and(struct expr *e1, struct expr *e2) +{ + struct expr *tmp; + struct symbol *sym1, *sym2; + + if (expr_eq(e1, e2)) + return expr_copy(e1); + if (e1->type != E_EQUAL && e1->type != E_UNEQUAL && e1->type != E_SYMBOL && e1->type != E_NOT) + return NULL; + if (e2->type != E_EQUAL && e2->type != E_UNEQUAL && e2->type != E_SYMBOL && e2->type != E_NOT) + return NULL; + if (e1->type == E_NOT) { + tmp = e1->left.expr; + if (tmp->type != E_EQUAL && tmp->type != E_UNEQUAL && tmp->type != E_SYMBOL) + return NULL; + sym1 = tmp->left.sym; + } else + sym1 = e1->left.sym; + if (e2->type == E_NOT) { + if (e2->left.expr->type != E_SYMBOL) + return NULL; + sym2 = e2->left.expr->left.sym; + } else + sym2 = e2->left.sym; + if (sym1 != sym2) + return NULL; + if (sym1->type != S_BOOLEAN && sym1->type != S_TRISTATE) + return NULL; + + if ((e1->type == E_SYMBOL && e2->type == E_EQUAL && e2->right.sym == &symbol_yes) || + (e2->type == E_SYMBOL && e1->type == E_EQUAL && e1->right.sym == &symbol_yes)) + // (a) && (a='y') -> (a='y') + return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes); + + if ((e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_no) || + (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_no)) + // (a) && (a!='n') -> (a) + return expr_alloc_symbol(sym1); + + if ((e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_mod) || + (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_mod)) + // (a) && (a!='m') -> (a='y') + return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes); + + if (sym1->type == S_TRISTATE) { + if (e1->type == E_EQUAL && e2->type == E_UNEQUAL) { + // (a='b') && (a!='c') -> 'b'='c' ? 'n' : a='b' + sym2 = e1->right.sym; + if ((e2->right.sym->flags & SYMBOL_CONST) && (sym2->flags & SYMBOL_CONST)) + return sym2 != e2->right.sym ? expr_alloc_comp(E_EQUAL, sym1, sym2) + : expr_alloc_symbol(&symbol_no); + } + if (e1->type == E_UNEQUAL && e2->type == E_EQUAL) { + // (a='b') && (a!='c') -> 'b'='c' ? 'n' : a='b' + sym2 = e2->right.sym; + if ((e1->right.sym->flags & SYMBOL_CONST) && (sym2->flags & SYMBOL_CONST)) + return sym2 != e1->right.sym ? expr_alloc_comp(E_EQUAL, sym1, sym2) + : expr_alloc_symbol(&symbol_no); + } + if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL && + ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_no) || + (e1->right.sym == &symbol_no && e2->right.sym == &symbol_yes))) + // (a!='y') && (a!='n') -> (a='m') + return expr_alloc_comp(E_EQUAL, sym1, &symbol_mod); + + if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL && + ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_mod) || + (e1->right.sym == &symbol_mod && e2->right.sym == &symbol_yes))) + // (a!='y') && (a!='m') -> (a='n') + return expr_alloc_comp(E_EQUAL, sym1, &symbol_no); + + if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL && + ((e1->right.sym == &symbol_mod && e2->right.sym == &symbol_no) || + (e1->right.sym == &symbol_no && e2->right.sym == &symbol_mod))) + // (a!='m') && (a!='n') -> (a='m') + return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes); + + if ((e1->type == E_SYMBOL && e2->type == E_EQUAL && e2->right.sym == &symbol_mod) || + (e2->type == E_SYMBOL && e1->type == E_EQUAL && e1->right.sym == &symbol_mod) || + (e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_yes) || + (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_yes)) + return NULL; + } + + if (DEBUG_EXPR) { + printf("optimize ("); + expr_fprint(e1, stdout); + printf(") && ("); + expr_fprint(e2, stdout); + printf(")?\n"); + } + return NULL; +} + +static void expr_eliminate_dups1(enum expr_type type, struct expr **ep1, struct expr **ep2) +{ +#define e1 (*ep1) +#define e2 (*ep2) + struct expr *tmp; + + if (e1->type == type) { + expr_eliminate_dups1(type, &e1->left.expr, &e2); + expr_eliminate_dups1(type, &e1->right.expr, &e2); + return; + } + if (e2->type == type) { + expr_eliminate_dups1(type, &e1, &e2->left.expr); + expr_eliminate_dups1(type, &e1, &e2->right.expr); + return; + } + if (e1 == e2) + return; + + switch (e1->type) { + case E_OR: case E_AND: + expr_eliminate_dups1(e1->type, &e1, &e1); + default: + ; + } + + switch (type) { + case E_OR: + tmp = expr_join_or(e1, e2); + if (tmp) { + expr_free(e1); expr_free(e2); + e1 = expr_alloc_symbol(&symbol_no); + e2 = tmp; + trans_count++; + } + break; + case E_AND: + tmp = expr_join_and(e1, e2); + if (tmp) { + expr_free(e1); expr_free(e2); + e1 = expr_alloc_symbol(&symbol_yes); + e2 = tmp; + trans_count++; + } + break; + default: + ; + } +#undef e1 +#undef e2 +} + +static void expr_eliminate_dups2(enum expr_type type, struct expr **ep1, struct expr **ep2) +{ +#define e1 (*ep1) +#define e2 (*ep2) + struct expr *tmp, *tmp1, *tmp2; + + if (e1->type == type) { + expr_eliminate_dups2(type, &e1->left.expr, &e2); + expr_eliminate_dups2(type, &e1->right.expr, &e2); + return; + } + if (e2->type == type) { + expr_eliminate_dups2(type, &e1, &e2->left.expr); + expr_eliminate_dups2(type, &e1, &e2->right.expr); + } + if (e1 == e2) + return; + + switch (e1->type) { + case E_OR: + expr_eliminate_dups2(e1->type, &e1, &e1); + // (FOO || BAR) && (!FOO && !BAR) -> n + tmp1 = expr_transform(expr_alloc_one(E_NOT, expr_copy(e1))); + tmp2 = expr_copy(e2); + tmp = expr_extract_eq_and(&tmp1, &tmp2); + if (expr_is_yes(tmp1)) { + expr_free(e1); + e1 = expr_alloc_symbol(&symbol_no); + trans_count++; + } + expr_free(tmp2); + expr_free(tmp1); + expr_free(tmp); + break; + case E_AND: + expr_eliminate_dups2(e1->type, &e1, &e1); + // (FOO && BAR) || (!FOO || !BAR) -> y + tmp1 = expr_transform(expr_alloc_one(E_NOT, expr_copy(e1))); + tmp2 = expr_copy(e2); + tmp = expr_extract_eq_or(&tmp1, &tmp2); + if (expr_is_no(tmp1)) { + expr_free(e1); + e1 = expr_alloc_symbol(&symbol_yes); + trans_count++; + } + expr_free(tmp2); + expr_free(tmp1); + expr_free(tmp); + break; + default: + ; + } +#undef e1 +#undef e2 +} + +struct expr *expr_eliminate_dups(struct expr *e) +{ + int oldcount; + if (!e) + return e; + + oldcount = trans_count; + while (1) { + trans_count = 0; + switch (e->type) { + case E_OR: case E_AND: + expr_eliminate_dups1(e->type, &e, &e); + expr_eliminate_dups2(e->type, &e, &e); + default: + ; + } + if (!trans_count) + break; + e = expr_eliminate_yn(e); + } + trans_count = oldcount; + return e; +} + +struct expr *expr_transform(struct expr *e) +{ + struct expr *tmp; + + if (!e) + return NULL; + switch (e->type) { + case E_EQUAL: + case E_UNEQUAL: + case E_SYMBOL: + case E_LIST: + break; + default: + e->left.expr = expr_transform(e->left.expr); + e->right.expr = expr_transform(e->right.expr); + } + + switch (e->type) { + case E_EQUAL: + if (e->left.sym->type != S_BOOLEAN) + break; + if (e->right.sym == &symbol_no) { + e->type = E_NOT; + e->left.expr = expr_alloc_symbol(e->left.sym); + e->right.sym = NULL; + break; + } + if (e->right.sym == &symbol_mod) { + printf("boolean symbol %s tested for 'm'? test forced to 'n'\n", e->left.sym->name); + e->type = E_SYMBOL; + e->left.sym = &symbol_no; + e->right.sym = NULL; + break; + } + if (e->right.sym == &symbol_yes) { + e->type = E_SYMBOL; + e->right.sym = NULL; + break; + } + break; + case E_UNEQUAL: + if (e->left.sym->type != S_BOOLEAN) + break; + if (e->right.sym == &symbol_no) { + e->type = E_SYMBOL; + e->right.sym = NULL; + break; + } + if (e->right.sym == &symbol_mod) { + printf("boolean symbol %s tested for 'm'? test forced to 'y'\n", e->left.sym->name); + e->type = E_SYMBOL; + e->left.sym = &symbol_yes; + e->right.sym = NULL; + break; + } + if (e->right.sym == &symbol_yes) { + e->type = E_NOT; + e->left.expr = expr_alloc_symbol(e->left.sym); + e->right.sym = NULL; + break; + } + break; + case E_NOT: + switch (e->left.expr->type) { + case E_NOT: + // !!a -> a + tmp = e->left.expr->left.expr; + free(e->left.expr); + free(e); + e = tmp; + e = expr_transform(e); + break; + case E_EQUAL: + case E_UNEQUAL: + // !a='x' -> a!='x' + tmp = e->left.expr; + free(e); + e = tmp; + e->type = e->type == E_EQUAL ? E_UNEQUAL : E_EQUAL; + break; + case E_OR: + // !(a || b) -> !a && !b + tmp = e->left.expr; + e->type = E_AND; + e->right.expr = expr_alloc_one(E_NOT, tmp->right.expr); + tmp->type = E_NOT; + tmp->right.expr = NULL; + e = expr_transform(e); + break; + case E_AND: + // !(a && b) -> !a || !b + tmp = e->left.expr; + e->type = E_OR; + e->right.expr = expr_alloc_one(E_NOT, tmp->right.expr); + tmp->type = E_NOT; + tmp->right.expr = NULL; + e = expr_transform(e); + break; + case E_SYMBOL: + if (e->left.expr->left.sym == &symbol_yes) { + // !'y' -> 'n' + tmp = e->left.expr; + free(e); + e = tmp; + e->type = E_SYMBOL; + e->left.sym = &symbol_no; + break; + } + if (e->left.expr->left.sym == &symbol_mod) { + // !'m' -> 'm' + tmp = e->left.expr; + free(e); + e = tmp; + e->type = E_SYMBOL; + e->left.sym = &symbol_mod; + break; + } + if (e->left.expr->left.sym == &symbol_no) { + // !'n' -> 'y' + tmp = e->left.expr; + free(e); + e = tmp; + e->type = E_SYMBOL; + e->left.sym = &symbol_yes; + break; + } + break; + default: + ; + } + break; + default: + ; + } + return e; +} + +int expr_contains_symbol(struct expr *dep, struct symbol *sym) +{ + if (!dep) + return 0; + + switch (dep->type) { + case E_AND: + case E_OR: + return expr_contains_symbol(dep->left.expr, sym) || + expr_contains_symbol(dep->right.expr, sym); + case E_SYMBOL: + return dep->left.sym == sym; + case E_EQUAL: + case E_UNEQUAL: + return dep->left.sym == sym || + dep->right.sym == sym; + case E_NOT: + return expr_contains_symbol(dep->left.expr, sym); + default: + ; + } + return 0; +} + +bool expr_depends_symbol(struct expr *dep, struct symbol *sym) +{ + if (!dep) + return false; + + switch (dep->type) { + case E_AND: + return expr_depends_symbol(dep->left.expr, sym) || + expr_depends_symbol(dep->right.expr, sym); + case E_SYMBOL: + return dep->left.sym == sym; + case E_EQUAL: + if (dep->left.sym == sym) { + if (dep->right.sym == &symbol_yes || dep->right.sym == &symbol_mod) + return true; + } + break; + case E_UNEQUAL: + if (dep->left.sym == sym) { + if (dep->right.sym == &symbol_no) + return true; + } + break; + default: + ; + } + return false; +} + +struct expr *expr_extract_eq_and(struct expr **ep1, struct expr **ep2) +{ + struct expr *tmp = NULL; + expr_extract_eq(E_AND, &tmp, ep1, ep2); + if (tmp) { + *ep1 = expr_eliminate_yn(*ep1); + *ep2 = expr_eliminate_yn(*ep2); + } + return tmp; +} + +struct expr *expr_extract_eq_or(struct expr **ep1, struct expr **ep2) +{ + struct expr *tmp = NULL; + expr_extract_eq(E_OR, &tmp, ep1, ep2); + if (tmp) { + *ep1 = expr_eliminate_yn(*ep1); + *ep2 = expr_eliminate_yn(*ep2); + } + return tmp; +} + +void expr_extract_eq(enum expr_type type, struct expr **ep, struct expr **ep1, struct expr **ep2) +{ +#define e1 (*ep1) +#define e2 (*ep2) + if (e1->type == type) { + expr_extract_eq(type, ep, &e1->left.expr, &e2); + expr_extract_eq(type, ep, &e1->right.expr, &e2); + return; + } + if (e2->type == type) { + expr_extract_eq(type, ep, ep1, &e2->left.expr); + expr_extract_eq(type, ep, ep1, &e2->right.expr); + return; + } + if (expr_eq(e1, e2)) { + *ep = *ep ? expr_alloc_two(type, *ep, e1) : e1; + expr_free(e2); + if (type == E_AND) { + e1 = expr_alloc_symbol(&symbol_yes); + e2 = expr_alloc_symbol(&symbol_yes); + } else if (type == E_OR) { + e1 = expr_alloc_symbol(&symbol_no); + e2 = expr_alloc_symbol(&symbol_no); + } + } +#undef e1 +#undef e2 +} + +struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symbol *sym) +{ + struct expr *e1, *e2; + + if (!e) { + e = expr_alloc_symbol(sym); + if (type == E_UNEQUAL) + e = expr_alloc_one(E_NOT, e); + return e; + } + switch (e->type) { + case E_AND: + e1 = expr_trans_compare(e->left.expr, E_EQUAL, sym); + e2 = expr_trans_compare(e->right.expr, E_EQUAL, sym); + if (sym == &symbol_yes) + e = expr_alloc_two(E_AND, e1, e2); + if (sym == &symbol_no) + e = expr_alloc_two(E_OR, e1, e2); + if (type == E_UNEQUAL) + e = expr_alloc_one(E_NOT, e); + return e; + case E_OR: + e1 = expr_trans_compare(e->left.expr, E_EQUAL, sym); + e2 = expr_trans_compare(e->right.expr, E_EQUAL, sym); + if (sym == &symbol_yes) + e = expr_alloc_two(E_OR, e1, e2); + if (sym == &symbol_no) + e = expr_alloc_two(E_AND, e1, e2); + if (type == E_UNEQUAL) + e = expr_alloc_one(E_NOT, e); + return e; + case E_NOT: + return expr_trans_compare(e->left.expr, type == E_EQUAL ? E_UNEQUAL : E_EQUAL, sym); + case E_UNEQUAL: + case E_EQUAL: + if (type == E_EQUAL) { + if (sym == &symbol_yes) + return expr_copy(e); + if (sym == &symbol_mod) + return expr_alloc_symbol(&symbol_no); + if (sym == &symbol_no) + return expr_alloc_one(E_NOT, expr_copy(e)); + } else { + if (sym == &symbol_yes) + return expr_alloc_one(E_NOT, expr_copy(e)); + if (sym == &symbol_mod) + return expr_alloc_symbol(&symbol_yes); + if (sym == &symbol_no) + return expr_copy(e); + } + break; + case E_SYMBOL: + return expr_alloc_comp(type, e->left.sym, sym); + case E_LIST: + case E_RANGE: + case E_NONE: + /* panic */; + } + return NULL; +} + +tristate expr_calc_value(struct expr *e) +{ + tristate val1, val2; + const char *str1, *str2; + + if (!e) + return yes; + + switch (e->type) { + case E_SYMBOL: + sym_calc_value(e->left.sym); + return e->left.sym->curr.tri; + case E_AND: + val1 = expr_calc_value(e->left.expr); + val2 = expr_calc_value(e->right.expr); + return EXPR_AND(val1, val2); + case E_OR: + val1 = expr_calc_value(e->left.expr); + val2 = expr_calc_value(e->right.expr); + return EXPR_OR(val1, val2); + case E_NOT: + val1 = expr_calc_value(e->left.expr); + return EXPR_NOT(val1); + case E_EQUAL: + sym_calc_value(e->left.sym); + sym_calc_value(e->right.sym); + str1 = sym_get_string_value(e->left.sym); + str2 = sym_get_string_value(e->right.sym); + return !strcmp(str1, str2) ? yes : no; + case E_UNEQUAL: + sym_calc_value(e->left.sym); + sym_calc_value(e->right.sym); + str1 = sym_get_string_value(e->left.sym); + str2 = sym_get_string_value(e->right.sym); + return !strcmp(str1, str2) ? no : yes; + default: + printf("expr_calc_value: %d?\n", e->type); + return no; + } +} + +int expr_compare_type(enum expr_type t1, enum expr_type t2) +{ +#if 0 + return 1; +#else + if (t1 == t2) + return 0; + switch (t1) { + case E_EQUAL: + case E_UNEQUAL: + if (t2 == E_NOT) + return 1; + case E_NOT: + if (t2 == E_AND) + return 1; + case E_AND: + if (t2 == E_OR) + return 1; + case E_OR: + if (t2 == E_LIST) + return 1; + case E_LIST: + if (t2 == 0) + return 1; + default: + return -1; + } + printf("[%dgt%d?]", t1, t2); + return 0; +#endif +} + +static inline struct expr * +expr_get_leftmost_symbol(const struct expr *e) +{ + + if (e == NULL) + return NULL; + + while (e->type != E_SYMBOL) + e = e->left.expr; + + return expr_copy(e); +} + +/* + * Given expression `e1' and `e2', returns the leaf of the longest + * sub-expression of `e1' not containing 'e2. + */ +struct expr *expr_simplify_unmet_dep(struct expr *e1, struct expr *e2) +{ + struct expr *ret; + + switch (e1->type) { + case E_OR: + return expr_alloc_and( + expr_simplify_unmet_dep(e1->left.expr, e2), + expr_simplify_unmet_dep(e1->right.expr, e2)); + case E_AND: { + struct expr *e; + e = expr_alloc_and(expr_copy(e1), expr_copy(e2)); + e = expr_eliminate_dups(e); + ret = (!expr_eq(e, e1)) ? e1 : NULL; + expr_free(e); + break; + } + default: + ret = e1; + break; + } + + return expr_get_leftmost_symbol(ret); +} + +void expr_print(struct expr *e, void (*fn)(void *, struct symbol *, const char *), void *data, int prevtoken) +{ + if (!e) { + fn(data, NULL, "y"); + return; + } + + if (expr_compare_type(prevtoken, e->type) > 0) + fn(data, NULL, "("); + switch (e->type) { + case E_SYMBOL: + if (e->left.sym->name) + fn(data, e->left.sym, e->left.sym->name); + else + fn(data, NULL, ""); + break; + case E_NOT: + fn(data, NULL, "!"); + expr_print(e->left.expr, fn, data, E_NOT); + break; + case E_EQUAL: + if (e->left.sym->name) + fn(data, e->left.sym, e->left.sym->name); + else + fn(data, NULL, ""); + fn(data, NULL, "="); + fn(data, e->right.sym, e->right.sym->name); + break; + case E_UNEQUAL: + if (e->left.sym->name) + fn(data, e->left.sym, e->left.sym->name); + else + fn(data, NULL, ""); + fn(data, NULL, "!="); + fn(data, e->right.sym, e->right.sym->name); + break; + case E_OR: + expr_print(e->left.expr, fn, data, E_OR); + fn(data, NULL, " || "); + expr_print(e->right.expr, fn, data, E_OR); + break; + case E_AND: + expr_print(e->left.expr, fn, data, E_AND); + fn(data, NULL, " && "); + expr_print(e->right.expr, fn, data, E_AND); + break; + case E_LIST: + fn(data, e->right.sym, e->right.sym->name); + if (e->left.expr) { + fn(data, NULL, " ^ "); + expr_print(e->left.expr, fn, data, E_LIST); + } + break; + case E_RANGE: + fn(data, NULL, "["); + fn(data, e->left.sym, e->left.sym->name); + fn(data, NULL, " "); + fn(data, e->right.sym, e->right.sym->name); + fn(data, NULL, "]"); + break; + default: + { + char buf[32]; + sprintf(buf, "", e->type); + fn(data, NULL, buf); + break; + } + } + if (expr_compare_type(prevtoken, e->type) > 0) + fn(data, NULL, ")"); +} + +static void expr_print_file_helper(void *data, struct symbol *sym, const char *str) +{ + xfwrite(str, strlen(str), 1, data); +} + +void expr_fprint(struct expr *e, FILE *out) +{ + expr_print(e, expr_print_file_helper, out, E_NONE); +} + +static void expr_print_gstr_helper(void *data, struct symbol *sym, const char *str) +{ + struct gstr *gs = (struct gstr*)data; + const char *sym_str = NULL; + + if (sym) + sym_str = sym_get_string_value(sym); + + if (gs->max_width) { + unsigned extra_length = strlen(str); + const char *last_cr = strrchr(gs->s, '\n'); + unsigned last_line_length; + + if (sym_str) + extra_length += 4 + strlen(sym_str); + + if (!last_cr) + last_cr = gs->s; + + last_line_length = strlen(gs->s) - (last_cr - gs->s); + + if ((last_line_length + extra_length) > gs->max_width) + str_append(gs, "\\\n"); + } + + str_append(gs, str); + if (sym && sym->type != S_UNKNOWN) + str_printf(gs, " [=%s]", sym_str); +} + +void expr_gstr_print(struct expr *e, struct gstr *gs) +{ + expr_print(e, expr_print_gstr_helper, gs, E_NONE); +} diff --git a/kernel/fiasco/tool/kconfig/scripts/kconfig/expr.h b/kernel/fiasco/tool/kconfig/scripts/kconfig/expr.h new file mode 100644 index 00000000..d4ecce8b --- /dev/null +++ b/kernel/fiasco/tool/kconfig/scripts/kconfig/expr.h @@ -0,0 +1,225 @@ +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +#ifndef EXPR_H +#define EXPR_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#ifndef __cplusplus +#include +#endif + +struct file { + struct file *next; + struct file *parent; + const char *name; + int lineno; +}; + +typedef enum tristate { + no, mod, yes +} tristate; + +enum expr_type { + E_NONE, E_OR, E_AND, E_NOT, E_EQUAL, E_UNEQUAL, E_LIST, E_SYMBOL, E_RANGE +}; + +union expr_data { + struct expr *expr; + struct symbol *sym; +}; + +struct expr { + enum expr_type type; + union expr_data left, right; +}; + +#define EXPR_OR(dep1, dep2) (((dep1)>(dep2))?(dep1):(dep2)) +#define EXPR_AND(dep1, dep2) (((dep1)<(dep2))?(dep1):(dep2)) +#define EXPR_NOT(dep) (2-(dep)) + +#define expr_list_for_each_sym(l, e, s) \ + for (e = (l); e && (s = e->right.sym); e = e->left.expr) + +struct expr_value { + struct expr *expr; + tristate tri; +}; + +struct symbol_value { + void *val; + tristate tri; +}; + +enum symbol_type { + S_UNKNOWN, S_BOOLEAN, S_TRISTATE, S_INT, S_HEX, S_STRING, S_OTHER +}; + +/* enum values are used as index to symbol.def[] */ +enum { + S_DEF_USER, /* main user value */ + S_DEF_AUTO, /* values read from auto.conf */ + S_DEF_DEF3, /* Reserved for UI usage */ + S_DEF_DEF4, /* Reserved for UI usage */ + S_DEF_COUNT +}; + +struct symbol { + struct symbol *next; + char *name; + enum symbol_type type; + struct symbol_value curr; + struct symbol_value def[S_DEF_COUNT]; + tristate visible; + int flags; + struct property *prop; + struct expr_value dir_dep; + struct expr_value rev_dep; +}; + +#define for_all_symbols(i, sym) for (i = 0; i < SYMBOL_HASHSIZE; i++) for (sym = symbol_hash[i]; sym; sym = sym->next) if (sym->type != S_OTHER) + +#define SYMBOL_CONST 0x0001 /* symbol is const */ +#define SYMBOL_CHECK 0x0008 /* used during dependency checking */ +#define SYMBOL_CHOICE 0x0010 /* start of a choice block (null name) */ +#define SYMBOL_CHOICEVAL 0x0020 /* used as a value in a choice block */ +#define SYMBOL_VALID 0x0080 /* set when symbol.curr is calculated */ +#define SYMBOL_OPTIONAL 0x0100 /* choice is optional - values can be 'n' */ +#define SYMBOL_WRITE 0x0200 /* ? */ +#define SYMBOL_CHANGED 0x0400 /* ? */ +#define SYMBOL_AUTO 0x1000 /* value from environment variable */ +#define SYMBOL_CHECKED 0x2000 /* used during dependency checking */ +#define SYMBOL_WARNED 0x8000 /* warning has been issued */ + +/* Set when symbol.def[] is used */ +#define SYMBOL_DEF 0x10000 /* First bit of SYMBOL_DEF */ +#define SYMBOL_DEF_USER 0x10000 /* symbol.def[S_DEF_USER] is valid */ +#define SYMBOL_DEF_AUTO 0x20000 /* symbol.def[S_DEF_AUTO] is valid */ +#define SYMBOL_DEF3 0x40000 /* symbol.def[S_DEF_3] is valid */ +#define SYMBOL_DEF4 0x80000 /* symbol.def[S_DEF_4] is valid */ + +#define SYMBOL_MAXLENGTH 256 +#define SYMBOL_HASHSIZE 9973 + +/* A property represent the config options that can be associated + * with a config "symbol". + * Sample: + * config FOO + * default y + * prompt "foo prompt" + * select BAR + * config BAZ + * int "BAZ Value" + * range 1..255 + */ +enum prop_type { + P_UNKNOWN, + P_PROMPT, /* prompt "foo prompt" or "BAZ Value" */ + P_COMMENT, /* text associated with a comment */ + P_MENU, /* prompt associated with a menuconfig option */ + P_DEFAULT, /* default y */ + P_CHOICE, /* choice value */ + P_SELECT, /* select BAR */ + P_RANGE, /* range 7..100 (for a symbol) */ + P_ENV, /* value from environment variable */ + P_SYMBOL, /* where a symbol is defined */ +}; + +struct property { + struct property *next; /* next property - null if last */ + struct symbol *sym; /* the symbol for which the property is associated */ + enum prop_type type; /* type of property */ + const char *text; /* the prompt value - P_PROMPT, P_MENU, P_COMMENT */ + struct expr_value visible; + struct expr *expr; /* the optional conditional part of the property */ + struct menu *menu; /* the menu the property are associated with + * valid for: P_SELECT, P_RANGE, P_CHOICE, + * P_PROMPT, P_DEFAULT, P_MENU, P_COMMENT */ + struct file *file; /* what file was this property defined */ + int lineno; /* what lineno was this property defined */ +}; + +#define for_all_properties(sym, st, tok) \ + for (st = sym->prop; st; st = st->next) \ + if (st->type == (tok)) +#define for_all_defaults(sym, st) for_all_properties(sym, st, P_DEFAULT) +#define for_all_choices(sym, st) for_all_properties(sym, st, P_CHOICE) +#define for_all_prompts(sym, st) \ + for (st = sym->prop; st; st = st->next) \ + if (st->text) + +struct menu { + struct menu *next; + struct menu *parent; + struct menu *list; + struct symbol *sym; + struct property *prompt; + struct expr *visibility; + struct expr *dep; + unsigned int flags; + char *help; + struct file *file; + int lineno; + void *data; +}; + +#define MENU_CHANGED 0x0001 +#define MENU_ROOT 0x0002 + +extern struct file *file_list; +extern struct file *current_file; +struct file *lookup_file(const char *name); + +extern struct symbol symbol_yes, symbol_no, symbol_mod; +extern struct symbol *modules_sym; +extern struct symbol *sym_defconfig_list; +extern int cdebug; +struct expr *expr_alloc_symbol(struct symbol *sym); +struct expr *expr_alloc_one(enum expr_type type, struct expr *ce); +struct expr *expr_alloc_two(enum expr_type type, struct expr *e1, struct expr *e2); +struct expr *expr_alloc_comp(enum expr_type type, struct symbol *s1, struct symbol *s2); +struct expr *expr_alloc_and(struct expr *e1, struct expr *e2); +struct expr *expr_alloc_or(struct expr *e1, struct expr *e2); +struct expr *expr_copy(const struct expr *org); +void expr_free(struct expr *e); +int expr_eq(struct expr *e1, struct expr *e2); +void expr_eliminate_eq(struct expr **ep1, struct expr **ep2); +tristate expr_calc_value(struct expr *e); +struct expr *expr_eliminate_yn(struct expr *e); +struct expr *expr_trans_bool(struct expr *e); +struct expr *expr_eliminate_dups(struct expr *e); +struct expr *expr_transform(struct expr *e); +int expr_contains_symbol(struct expr *dep, struct symbol *sym); +bool expr_depends_symbol(struct expr *dep, struct symbol *sym); +struct expr *expr_extract_eq_and(struct expr **ep1, struct expr **ep2); +struct expr *expr_extract_eq_or(struct expr **ep1, struct expr **ep2); +void expr_extract_eq(enum expr_type type, struct expr **ep, struct expr **ep1, struct expr **ep2); +struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symbol *sym); +struct expr *expr_simplify_unmet_dep(struct expr *e1, struct expr *e2); + +void expr_fprint(struct expr *e, FILE *out); +struct gstr; /* forward */ +void expr_gstr_print(struct expr *e, struct gstr *gs); + +static inline int expr_is_yes(struct expr *e) +{ + return !e || (e->type == E_SYMBOL && e->left.sym == &symbol_yes); +} + +static inline int expr_is_no(struct expr *e) +{ + return e && (e->type == E_SYMBOL && e->left.sym == &symbol_no); +} + +#ifdef __cplusplus +} +#endif + +#endif /* EXPR_H */ diff --git a/kernel/fiasco/tool/kconfig/scripts/kconfig/gconf.c b/kernel/fiasco/tool/kconfig/scripts/kconfig/gconf.c new file mode 100644 index 00000000..7491559f --- /dev/null +++ b/kernel/fiasco/tool/kconfig/scripts/kconfig/gconf.c @@ -0,0 +1,1542 @@ +/* Hey EMACS -*- linux-c -*- */ +/* + * + * Copyright (C) 2002-2003 Romain Lievin + * Released under the terms of the GNU GPL v2.0. + * + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "lkc.h" +#include "images.c" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +//#define DEBUG + +enum { + SINGLE_VIEW, SPLIT_VIEW, FULL_VIEW +}; + +enum { + OPT_NORMAL, OPT_ALL, OPT_PROMPT +}; + +static gint view_mode = FULL_VIEW; +static gboolean show_name = TRUE; +static gboolean show_range = TRUE; +static gboolean show_value = TRUE; +static gboolean resizeable = FALSE; +static int opt_mode = OPT_NORMAL; + +GtkWidget *main_wnd = NULL; +GtkWidget *tree1_w = NULL; // left frame +GtkWidget *tree2_w = NULL; // right frame +GtkWidget *text_w = NULL; +GtkWidget *hpaned = NULL; +GtkWidget *vpaned = NULL; +GtkWidget *back_btn = NULL; +GtkWidget *save_btn = NULL; +GtkWidget *save_menu_item = NULL; + +GtkTextTag *tag1, *tag2; +GdkColor color; + +GtkTreeStore *tree1, *tree2, *tree; +GtkTreeModel *model1, *model2; +static GtkTreeIter *parents[256]; +static gint indent; + +static struct menu *current; // current node for SINGLE view +static struct menu *browsed; // browsed node for SPLIT view + +enum { + COL_OPTION, COL_NAME, COL_NO, COL_MOD, COL_YES, COL_VALUE, + COL_MENU, COL_COLOR, COL_EDIT, COL_PIXBUF, + COL_PIXVIS, COL_BTNVIS, COL_BTNACT, COL_BTNINC, COL_BTNRAD, + COL_NUMBER +}; + +static void display_list(void); +static void display_tree(struct menu *menu); +static void display_tree_part(void); +static void update_tree(struct menu *src, GtkTreeIter * dst); +static void set_node(GtkTreeIter * node, struct menu *menu, gchar ** row); +static gchar **fill_row(struct menu *menu); +static void conf_changed(void); + +/* Helping/Debugging Functions */ + +const char *dbg_sym_flags(int val) +{ + static char buf[256]; + + bzero(buf, 256); + + if (val & SYMBOL_CONST) + strcat(buf, "const/"); + if (val & SYMBOL_CHECK) + strcat(buf, "check/"); + if (val & SYMBOL_CHOICE) + strcat(buf, "choice/"); + if (val & SYMBOL_CHOICEVAL) + strcat(buf, "choiceval/"); + if (val & SYMBOL_VALID) + strcat(buf, "valid/"); + if (val & SYMBOL_OPTIONAL) + strcat(buf, "optional/"); + if (val & SYMBOL_WRITE) + strcat(buf, "write/"); + if (val & SYMBOL_CHANGED) + strcat(buf, "changed/"); + if (val & SYMBOL_AUTO) + strcat(buf, "auto/"); + + buf[strlen(buf) - 1] = '\0'; + + return buf; +} + +void replace_button_icon(GladeXML * xml, GdkDrawable * window, + GtkStyle * style, gchar * btn_name, gchar ** xpm) +{ + GdkPixmap *pixmap; + GdkBitmap *mask; + GtkToolButton *button; + GtkWidget *image; + + pixmap = gdk_pixmap_create_from_xpm_d(window, &mask, + &style->bg[GTK_STATE_NORMAL], + xpm); + + button = GTK_TOOL_BUTTON(glade_xml_get_widget(xml, btn_name)); + image = gtk_image_new_from_pixmap(pixmap, mask); + gtk_widget_show(image); + gtk_tool_button_set_icon_widget(button, image); +} + +/* Main Window Initialization */ +void init_main_window(const gchar * glade_file) +{ + GladeXML *xml; + GtkWidget *widget; + GtkTextBuffer *txtbuf; + GtkStyle *style; + + xml = glade_xml_new(glade_file, "window1", NULL); + if (!xml) + g_error(_("GUI loading failed !\n")); + glade_xml_signal_autoconnect(xml); + + main_wnd = glade_xml_get_widget(xml, "window1"); + hpaned = glade_xml_get_widget(xml, "hpaned1"); + vpaned = glade_xml_get_widget(xml, "vpaned1"); + tree1_w = glade_xml_get_widget(xml, "treeview1"); + tree2_w = glade_xml_get_widget(xml, "treeview2"); + text_w = glade_xml_get_widget(xml, "textview3"); + + back_btn = glade_xml_get_widget(xml, "button1"); + gtk_widget_set_sensitive(back_btn, FALSE); + + widget = glade_xml_get_widget(xml, "show_name1"); + gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget, + show_name); + + widget = glade_xml_get_widget(xml, "show_range1"); + gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget, + show_range); + + widget = glade_xml_get_widget(xml, "show_data1"); + gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget, + show_value); + + save_btn = glade_xml_get_widget(xml, "button3"); + save_menu_item = glade_xml_get_widget(xml, "save1"); + conf_set_changed_callback(conf_changed); + + style = gtk_widget_get_style(main_wnd); + widget = glade_xml_get_widget(xml, "toolbar1"); + +#if 0 /* Use stock Gtk icons instead */ + replace_button_icon(xml, main_wnd->window, style, + "button1", (gchar **) xpm_back); + replace_button_icon(xml, main_wnd->window, style, + "button2", (gchar **) xpm_load); + replace_button_icon(xml, main_wnd->window, style, + "button3", (gchar **) xpm_save); +#endif + replace_button_icon(xml, main_wnd->window, style, + "button4", (gchar **) xpm_single_view); + replace_button_icon(xml, main_wnd->window, style, + "button5", (gchar **) xpm_split_view); + replace_button_icon(xml, main_wnd->window, style, + "button6", (gchar **) xpm_tree_view); + +#if 0 + switch (view_mode) { + case SINGLE_VIEW: + widget = glade_xml_get_widget(xml, "button4"); + g_signal_emit_by_name(widget, "clicked"); + break; + case SPLIT_VIEW: + widget = glade_xml_get_widget(xml, "button5"); + g_signal_emit_by_name(widget, "clicked"); + break; + case FULL_VIEW: + widget = glade_xml_get_widget(xml, "button6"); + g_signal_emit_by_name(widget, "clicked"); + break; + } +#endif + txtbuf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w)); + tag1 = gtk_text_buffer_create_tag(txtbuf, "mytag1", + "foreground", "red", + "weight", PANGO_WEIGHT_BOLD, + NULL); + tag2 = gtk_text_buffer_create_tag(txtbuf, "mytag2", + /*"style", PANGO_STYLE_OBLIQUE, */ + NULL); + + gtk_window_set_title(GTK_WINDOW(main_wnd), rootmenu.prompt->text); + + gtk_widget_show(main_wnd); +} + +void init_tree_model(void) +{ + gint i; + + tree = tree2 = gtk_tree_store_new(COL_NUMBER, + G_TYPE_STRING, G_TYPE_STRING, + G_TYPE_STRING, G_TYPE_STRING, + G_TYPE_STRING, G_TYPE_STRING, + G_TYPE_POINTER, GDK_TYPE_COLOR, + G_TYPE_BOOLEAN, GDK_TYPE_PIXBUF, + G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, + G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, + G_TYPE_BOOLEAN); + model2 = GTK_TREE_MODEL(tree2); + + for (parents[0] = NULL, i = 1; i < 256; i++) + parents[i] = (GtkTreeIter *) g_malloc(sizeof(GtkTreeIter)); + + tree1 = gtk_tree_store_new(COL_NUMBER, + G_TYPE_STRING, G_TYPE_STRING, + G_TYPE_STRING, G_TYPE_STRING, + G_TYPE_STRING, G_TYPE_STRING, + G_TYPE_POINTER, GDK_TYPE_COLOR, + G_TYPE_BOOLEAN, GDK_TYPE_PIXBUF, + G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, + G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, + G_TYPE_BOOLEAN); + model1 = GTK_TREE_MODEL(tree1); +} + +void init_left_tree(void) +{ + GtkTreeView *view = GTK_TREE_VIEW(tree1_w); + GtkCellRenderer *renderer; + GtkTreeSelection *sel; + GtkTreeViewColumn *column; + + gtk_tree_view_set_model(view, model1); + gtk_tree_view_set_headers_visible(view, TRUE); + gtk_tree_view_set_rules_hint(view, TRUE); + + column = gtk_tree_view_column_new(); + gtk_tree_view_append_column(view, column); + gtk_tree_view_column_set_title(column, _("Options")); + + renderer = gtk_cell_renderer_toggle_new(); + gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column), + renderer, FALSE); + gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column), + renderer, + "active", COL_BTNACT, + "inconsistent", COL_BTNINC, + "visible", COL_BTNVIS, + "radio", COL_BTNRAD, NULL); + renderer = gtk_cell_renderer_text_new(); + gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column), + renderer, FALSE); + gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column), + renderer, + "text", COL_OPTION, + "foreground-gdk", + COL_COLOR, NULL); + + sel = gtk_tree_view_get_selection(view); + gtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE); + gtk_widget_realize(tree1_w); +} + +static void renderer_edited(GtkCellRendererText * cell, + const gchar * path_string, + const gchar * new_text, gpointer user_data); + +void init_right_tree(void) +{ + GtkTreeView *view = GTK_TREE_VIEW(tree2_w); + GtkCellRenderer *renderer; + GtkTreeSelection *sel; + GtkTreeViewColumn *column; + gint i; + + gtk_tree_view_set_model(view, model2); + gtk_tree_view_set_headers_visible(view, TRUE); + gtk_tree_view_set_rules_hint(view, TRUE); + + column = gtk_tree_view_column_new(); + gtk_tree_view_append_column(view, column); + gtk_tree_view_column_set_title(column, _("Options")); + + renderer = gtk_cell_renderer_pixbuf_new(); + gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column), + renderer, FALSE); + gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column), + renderer, + "pixbuf", COL_PIXBUF, + "visible", COL_PIXVIS, NULL); + renderer = gtk_cell_renderer_toggle_new(); + gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column), + renderer, FALSE); + gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column), + renderer, + "active", COL_BTNACT, + "inconsistent", COL_BTNINC, + "visible", COL_BTNVIS, + "radio", COL_BTNRAD, NULL); + renderer = gtk_cell_renderer_text_new(); + gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column), + renderer, FALSE); + gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column), + renderer, + "text", COL_OPTION, + "foreground-gdk", + COL_COLOR, NULL); + + renderer = gtk_cell_renderer_text_new(); + gtk_tree_view_insert_column_with_attributes(view, -1, + _("Name"), renderer, + "text", COL_NAME, + "foreground-gdk", + COL_COLOR, NULL); + renderer = gtk_cell_renderer_text_new(); + gtk_tree_view_insert_column_with_attributes(view, -1, + "N", renderer, + "text", COL_NO, + "foreground-gdk", + COL_COLOR, NULL); + renderer = gtk_cell_renderer_text_new(); + gtk_tree_view_insert_column_with_attributes(view, -1, + "M", renderer, + "text", COL_MOD, + "foreground-gdk", + COL_COLOR, NULL); + renderer = gtk_cell_renderer_text_new(); + gtk_tree_view_insert_column_with_attributes(view, -1, + "Y", renderer, + "text", COL_YES, + "foreground-gdk", + COL_COLOR, NULL); + renderer = gtk_cell_renderer_text_new(); + gtk_tree_view_insert_column_with_attributes(view, -1, + _("Value"), renderer, + "text", COL_VALUE, + "editable", + COL_EDIT, + "foreground-gdk", + COL_COLOR, NULL); + g_signal_connect(G_OBJECT(renderer), "edited", + G_CALLBACK(renderer_edited), NULL); + + column = gtk_tree_view_get_column(view, COL_NAME); + gtk_tree_view_column_set_visible(column, show_name); + column = gtk_tree_view_get_column(view, COL_NO); + gtk_tree_view_column_set_visible(column, show_range); + column = gtk_tree_view_get_column(view, COL_MOD); + gtk_tree_view_column_set_visible(column, show_range); + column = gtk_tree_view_get_column(view, COL_YES); + gtk_tree_view_column_set_visible(column, show_range); + column = gtk_tree_view_get_column(view, COL_VALUE); + gtk_tree_view_column_set_visible(column, show_value); + + if (resizeable) { + for (i = 0; i < COL_VALUE; i++) { + column = gtk_tree_view_get_column(view, i); + gtk_tree_view_column_set_resizable(column, TRUE); + } + } + + sel = gtk_tree_view_get_selection(view); + gtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE); +} + + +/* Utility Functions */ + + +static void text_insert_help(struct menu *menu) +{ + GtkTextBuffer *buffer; + GtkTextIter start, end; + const char *prompt = _(menu_get_prompt(menu)); + struct gstr help = str_new(); + + menu_get_ext_help(menu, &help); + + buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w)); + gtk_text_buffer_get_bounds(buffer, &start, &end); + gtk_text_buffer_delete(buffer, &start, &end); + gtk_text_view_set_left_margin(GTK_TEXT_VIEW(text_w), 15); + + gtk_text_buffer_get_end_iter(buffer, &end); + gtk_text_buffer_insert_with_tags(buffer, &end, prompt, -1, tag1, + NULL); + gtk_text_buffer_insert_at_cursor(buffer, "\n\n", 2); + gtk_text_buffer_get_end_iter(buffer, &end); + gtk_text_buffer_insert_with_tags(buffer, &end, str_get(&help), -1, tag2, + NULL); + str_free(&help); +} + + +static void text_insert_msg(const char *title, const char *message) +{ + GtkTextBuffer *buffer; + GtkTextIter start, end; + const char *msg = message; + + buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w)); + gtk_text_buffer_get_bounds(buffer, &start, &end); + gtk_text_buffer_delete(buffer, &start, &end); + gtk_text_view_set_left_margin(GTK_TEXT_VIEW(text_w), 15); + + gtk_text_buffer_get_end_iter(buffer, &end); + gtk_text_buffer_insert_with_tags(buffer, &end, title, -1, tag1, + NULL); + gtk_text_buffer_insert_at_cursor(buffer, "\n\n", 2); + gtk_text_buffer_get_end_iter(buffer, &end); + gtk_text_buffer_insert_with_tags(buffer, &end, msg, -1, tag2, + NULL); +} + + +/* Main Windows Callbacks */ + +void on_save_activate(GtkMenuItem * menuitem, gpointer user_data); +gboolean on_window1_delete_event(GtkWidget * widget, GdkEvent * event, + gpointer user_data) +{ + GtkWidget *dialog, *label; + gint result; + + if (!conf_get_changed()) + return FALSE; + + dialog = gtk_dialog_new_with_buttons(_("Warning !"), + GTK_WINDOW(main_wnd), + (GtkDialogFlags) + (GTK_DIALOG_MODAL | + GTK_DIALOG_DESTROY_WITH_PARENT), + GTK_STOCK_OK, + GTK_RESPONSE_YES, + GTK_STOCK_NO, + GTK_RESPONSE_NO, + GTK_STOCK_CANCEL, + GTK_RESPONSE_CANCEL, NULL); + gtk_dialog_set_default_response(GTK_DIALOG(dialog), + GTK_RESPONSE_CANCEL); + + label = gtk_label_new(_("\nSave configuration ?\n")); + gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), label); + gtk_widget_show(label); + + result = gtk_dialog_run(GTK_DIALOG(dialog)); + switch (result) { + case GTK_RESPONSE_YES: + on_save_activate(NULL, NULL); + return FALSE; + case GTK_RESPONSE_NO: + return FALSE; + case GTK_RESPONSE_CANCEL: + case GTK_RESPONSE_DELETE_EVENT: + default: + gtk_widget_destroy(dialog); + return TRUE; + } + + return FALSE; +} + + +void on_window1_destroy(GtkObject * object, gpointer user_data) +{ + gtk_main_quit(); +} + + +void +on_window1_size_request(GtkWidget * widget, + GtkRequisition * requisition, gpointer user_data) +{ + static gint old_h; + gint w, h; + + if (widget->window == NULL) + gtk_window_get_default_size(GTK_WINDOW(main_wnd), &w, &h); + else + gdk_window_get_size(widget->window, &w, &h); + + if (h == old_h) + return; + old_h = h; + + gtk_paned_set_position(GTK_PANED(vpaned), 2 * h / 3); +} + + +/* Menu & Toolbar Callbacks */ + + +static void +load_filename(GtkFileSelection * file_selector, gpointer user_data) +{ + const gchar *fn; + + fn = gtk_file_selection_get_filename(GTK_FILE_SELECTION + (user_data)); + + if (conf_read(fn)) + text_insert_msg(_("Error"), _("Unable to load configuration !")); + else + display_tree(&rootmenu); +} + +void on_load1_activate(GtkMenuItem * menuitem, gpointer user_data) +{ + GtkWidget *fs; + + fs = gtk_file_selection_new(_("Load file...")); + g_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(fs)->ok_button), + "clicked", + G_CALLBACK(load_filename), (gpointer) fs); + g_signal_connect_swapped(GTK_OBJECT + (GTK_FILE_SELECTION(fs)->ok_button), + "clicked", G_CALLBACK(gtk_widget_destroy), + (gpointer) fs); + g_signal_connect_swapped(GTK_OBJECT + (GTK_FILE_SELECTION(fs)->cancel_button), + "clicked", G_CALLBACK(gtk_widget_destroy), + (gpointer) fs); + gtk_widget_show(fs); +} + + +void on_save_activate(GtkMenuItem * menuitem, gpointer user_data) +{ + if (conf_write(NULL)) + text_insert_msg(_("Error"), _("Unable to save configuration !")); +} + + +static void +store_filename(GtkFileSelection * file_selector, gpointer user_data) +{ + const gchar *fn; + + fn = gtk_file_selection_get_filename(GTK_FILE_SELECTION + (user_data)); + + if (conf_write(fn)) + text_insert_msg(_("Error"), _("Unable to save configuration !")); + + gtk_widget_destroy(GTK_WIDGET(user_data)); +} + +void on_save_as1_activate(GtkMenuItem * menuitem, gpointer user_data) +{ + GtkWidget *fs; + + fs = gtk_file_selection_new(_("Save file as...")); + g_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(fs)->ok_button), + "clicked", + G_CALLBACK(store_filename), (gpointer) fs); + g_signal_connect_swapped(GTK_OBJECT + (GTK_FILE_SELECTION(fs)->ok_button), + "clicked", G_CALLBACK(gtk_widget_destroy), + (gpointer) fs); + g_signal_connect_swapped(GTK_OBJECT + (GTK_FILE_SELECTION(fs)->cancel_button), + "clicked", G_CALLBACK(gtk_widget_destroy), + (gpointer) fs); + gtk_widget_show(fs); +} + + +void on_quit1_activate(GtkMenuItem * menuitem, gpointer user_data) +{ + if (!on_window1_delete_event(NULL, NULL, NULL)) + gtk_widget_destroy(GTK_WIDGET(main_wnd)); +} + + +void on_show_name1_activate(GtkMenuItem * menuitem, gpointer user_data) +{ + GtkTreeViewColumn *col; + + show_name = GTK_CHECK_MENU_ITEM(menuitem)->active; + col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_NAME); + if (col) + gtk_tree_view_column_set_visible(col, show_name); +} + + +void on_show_range1_activate(GtkMenuItem * menuitem, gpointer user_data) +{ + GtkTreeViewColumn *col; + + show_range = GTK_CHECK_MENU_ITEM(menuitem)->active; + col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_NO); + if (col) + gtk_tree_view_column_set_visible(col, show_range); + col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_MOD); + if (col) + gtk_tree_view_column_set_visible(col, show_range); + col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_YES); + if (col) + gtk_tree_view_column_set_visible(col, show_range); + +} + + +void on_show_data1_activate(GtkMenuItem * menuitem, gpointer user_data) +{ + GtkTreeViewColumn *col; + + show_value = GTK_CHECK_MENU_ITEM(menuitem)->active; + col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_VALUE); + if (col) + gtk_tree_view_column_set_visible(col, show_value); +} + + +void +on_set_option_mode1_activate(GtkMenuItem *menuitem, gpointer user_data) +{ + opt_mode = OPT_NORMAL; + gtk_tree_store_clear(tree2); + display_tree(&rootmenu); /* instead of update_tree to speed-up */ +} + + +void +on_set_option_mode2_activate(GtkMenuItem *menuitem, gpointer user_data) +{ + opt_mode = OPT_ALL; + gtk_tree_store_clear(tree2); + display_tree(&rootmenu); /* instead of update_tree to speed-up */ +} + + +void +on_set_option_mode3_activate(GtkMenuItem *menuitem, gpointer user_data) +{ + opt_mode = OPT_PROMPT; + gtk_tree_store_clear(tree2); + display_tree(&rootmenu); /* instead of update_tree to speed-up */ +} + + +void on_introduction1_activate(GtkMenuItem * menuitem, gpointer user_data) +{ + GtkWidget *dialog; + const gchar *intro_text = _( + "Welcome to gkc, the GTK+ graphical configuration tool\n" + "For each option, a blank box indicates the feature is disabled, a\n" + "check indicates it is enabled, and a dot indicates that it is to\n" + "be compiled as a module. Clicking on the box will cycle through the three states.\n" + "\n" + "If you do not see an option (e.g., a device driver) that you\n" + "believe should be present, try turning on Show All Options\n" + "under the Options menu.\n" + "Although there is no cross reference yet to help you figure out\n" + "what other options must be enabled to support the option you\n" + "are interested in, you can still view the help of a grayed-out\n" + "option.\n" + "\n" + "Toggling Show Debug Info under the Options menu will show \n" + "the dependencies, which you can then match by examining other options."); + + dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_INFO, + GTK_BUTTONS_CLOSE, "%s", intro_text); + g_signal_connect_swapped(GTK_OBJECT(dialog), "response", + G_CALLBACK(gtk_widget_destroy), + GTK_OBJECT(dialog)); + gtk_widget_show_all(dialog); +} + + +void on_about1_activate(GtkMenuItem * menuitem, gpointer user_data) +{ + GtkWidget *dialog; + const gchar *about_text = + _("gkc is copyright (c) 2002 Romain Lievin .\n" + "Based on the source code from Roman Zippel.\n"); + + dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_INFO, + GTK_BUTTONS_CLOSE, "%s", about_text); + g_signal_connect_swapped(GTK_OBJECT(dialog), "response", + G_CALLBACK(gtk_widget_destroy), + GTK_OBJECT(dialog)); + gtk_widget_show_all(dialog); +} + + +void on_license1_activate(GtkMenuItem * menuitem, gpointer user_data) +{ + GtkWidget *dialog; + const gchar *license_text = + _("gkc is released under the terms of the GNU GPL v2.\n" + "For more information, please see the source code or\n" + "visit http://www.fsf.org/licenses/licenses.html\n"); + + dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_INFO, + GTK_BUTTONS_CLOSE, "%s", license_text); + g_signal_connect_swapped(GTK_OBJECT(dialog), "response", + G_CALLBACK(gtk_widget_destroy), + GTK_OBJECT(dialog)); + gtk_widget_show_all(dialog); +} + + +void on_back_clicked(GtkButton * button, gpointer user_data) +{ + enum prop_type ptype; + + current = current->parent; + ptype = current->prompt ? current->prompt->type : P_UNKNOWN; + if (ptype != P_MENU) + current = current->parent; + display_tree_part(); + + if (current == &rootmenu) + gtk_widget_set_sensitive(back_btn, FALSE); +} + + +void on_load_clicked(GtkButton * button, gpointer user_data) +{ + on_load1_activate(NULL, user_data); +} + + +void on_single_clicked(GtkButton * button, gpointer user_data) +{ + view_mode = SINGLE_VIEW; + gtk_widget_hide(tree1_w); + current = &rootmenu; + display_tree_part(); +} + + +void on_split_clicked(GtkButton * button, gpointer user_data) +{ + gint w, h; + view_mode = SPLIT_VIEW; + gtk_widget_show(tree1_w); + gtk_window_get_default_size(GTK_WINDOW(main_wnd), &w, &h); + gtk_paned_set_position(GTK_PANED(hpaned), w / 2); + if (tree2) + gtk_tree_store_clear(tree2); + display_list(); + + /* Disable back btn, like in full mode. */ + gtk_widget_set_sensitive(back_btn, FALSE); +} + + +void on_full_clicked(GtkButton * button, gpointer user_data) +{ + view_mode = FULL_VIEW; + gtk_widget_hide(tree1_w); + if (tree2) + gtk_tree_store_clear(tree2); + display_tree(&rootmenu); + gtk_widget_set_sensitive(back_btn, FALSE); +} + + +void on_collapse_clicked(GtkButton * button, gpointer user_data) +{ + gtk_tree_view_collapse_all(GTK_TREE_VIEW(tree2_w)); +} + + +void on_expand_clicked(GtkButton * button, gpointer user_data) +{ + gtk_tree_view_expand_all(GTK_TREE_VIEW(tree2_w)); +} + + +/* CTree Callbacks */ + +/* Change hex/int/string value in the cell */ +static void renderer_edited(GtkCellRendererText * cell, + const gchar * path_string, + const gchar * new_text, gpointer user_data) +{ + GtkTreePath *path = gtk_tree_path_new_from_string(path_string); + GtkTreeIter iter; + const char *old_def, *new_def; + struct menu *menu; + struct symbol *sym; + + if (!gtk_tree_model_get_iter(model2, &iter, path)) + return; + + gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1); + sym = menu->sym; + + gtk_tree_model_get(model2, &iter, COL_VALUE, &old_def, -1); + new_def = new_text; + + sym_set_string_value(sym, new_def); + + update_tree(&rootmenu, NULL); + + gtk_tree_path_free(path); +} + +/* Change the value of a symbol and update the tree */ +static void change_sym_value(struct menu *menu, gint col) +{ + struct symbol *sym = menu->sym; + tristate newval; + + if (!sym) + return; + + if (col == COL_NO) + newval = no; + else if (col == COL_MOD) + newval = mod; + else if (col == COL_YES) + newval = yes; + else + return; + + switch (sym_get_type(sym)) { + case S_BOOLEAN: + case S_TRISTATE: + if (!sym_tristate_within_range(sym, newval)) + newval = yes; + sym_set_tristate_value(sym, newval); + if (view_mode == FULL_VIEW) + update_tree(&rootmenu, NULL); + else if (view_mode == SPLIT_VIEW) { + update_tree(browsed, NULL); + display_list(); + } + else if (view_mode == SINGLE_VIEW) + display_tree_part(); //fixme: keep exp/coll + break; + case S_INT: + case S_HEX: + case S_STRING: + default: + break; + } +} + +static void toggle_sym_value(struct menu *menu) +{ + if (!menu->sym) + return; + + sym_toggle_tristate_value(menu->sym); + if (view_mode == FULL_VIEW) + update_tree(&rootmenu, NULL); + else if (view_mode == SPLIT_VIEW) { + update_tree(browsed, NULL); + display_list(); + } + else if (view_mode == SINGLE_VIEW) + display_tree_part(); //fixme: keep exp/coll +} + +static gint column2index(GtkTreeViewColumn * column) +{ + gint i; + + for (i = 0; i < COL_NUMBER; i++) { + GtkTreeViewColumn *col; + + col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), i); + if (col == column) + return i; + } + + return -1; +} + + +/* User click: update choice (full) or goes down (single) */ +gboolean +on_treeview2_button_press_event(GtkWidget * widget, + GdkEventButton * event, gpointer user_data) +{ + GtkTreeView *view = GTK_TREE_VIEW(widget); + GtkTreePath *path; + GtkTreeViewColumn *column; + GtkTreeIter iter; + struct menu *menu; + gint col; + +#if GTK_CHECK_VERSION(2,1,4) // bug in ctree with earlier version of GTK + gint tx = (gint) event->x; + gint ty = (gint) event->y; + gint cx, cy; + + gtk_tree_view_get_path_at_pos(view, tx, ty, &path, &column, &cx, + &cy); +#else + gtk_tree_view_get_cursor(view, &path, &column); +#endif + if (path == NULL) + return FALSE; + + if (!gtk_tree_model_get_iter(model2, &iter, path)) + return FALSE; + gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1); + + col = column2index(column); + if (event->type == GDK_2BUTTON_PRESS) { + enum prop_type ptype; + ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN; + + if (ptype == P_MENU && view_mode != FULL_VIEW && col == COL_OPTION) { + // goes down into menu + current = menu; + display_tree_part(); + gtk_widget_set_sensitive(back_btn, TRUE); + } else if ((col == COL_OPTION)) { + toggle_sym_value(menu); + gtk_tree_view_expand_row(view, path, TRUE); + } + } else { + if (col == COL_VALUE) { + toggle_sym_value(menu); + gtk_tree_view_expand_row(view, path, TRUE); + } else if (col == COL_NO || col == COL_MOD + || col == COL_YES) { + change_sym_value(menu, col); + gtk_tree_view_expand_row(view, path, TRUE); + } + } + + return FALSE; +} + +/* Key pressed: update choice */ +gboolean +on_treeview2_key_press_event(GtkWidget * widget, + GdkEventKey * event, gpointer user_data) +{ + GtkTreeView *view = GTK_TREE_VIEW(widget); + GtkTreePath *path; + GtkTreeViewColumn *column; + GtkTreeIter iter; + struct menu *menu; + gint col; + + gtk_tree_view_get_cursor(view, &path, &column); + if (path == NULL) + return FALSE; + + if (event->keyval == GDK_space) { + if (gtk_tree_view_row_expanded(view, path)) + gtk_tree_view_collapse_row(view, path); + else + gtk_tree_view_expand_row(view, path, FALSE); + return TRUE; + } + if (event->keyval == GDK_KP_Enter) { + } + if (widget == tree1_w) + return FALSE; + + gtk_tree_model_get_iter(model2, &iter, path); + gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1); + + if (!strcasecmp(event->string, "n")) + col = COL_NO; + else if (!strcasecmp(event->string, "m")) + col = COL_MOD; + else if (!strcasecmp(event->string, "y")) + col = COL_YES; + else + col = -1; + change_sym_value(menu, col); + + return FALSE; +} + + +/* Row selection changed: update help */ +void +on_treeview2_cursor_changed(GtkTreeView * treeview, gpointer user_data) +{ + GtkTreeSelection *selection; + GtkTreeIter iter; + struct menu *menu; + + selection = gtk_tree_view_get_selection(treeview); + if (gtk_tree_selection_get_selected(selection, &model2, &iter)) { + gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1); + text_insert_help(menu); + } +} + + +/* User click: display sub-tree in the right frame. */ +gboolean +on_treeview1_button_press_event(GtkWidget * widget, + GdkEventButton * event, gpointer user_data) +{ + GtkTreeView *view = GTK_TREE_VIEW(widget); + GtkTreePath *path; + GtkTreeViewColumn *column; + GtkTreeIter iter; + struct menu *menu; + + gint tx = (gint) event->x; + gint ty = (gint) event->y; + gint cx, cy; + + gtk_tree_view_get_path_at_pos(view, tx, ty, &path, &column, &cx, + &cy); + if (path == NULL) + return FALSE; + + gtk_tree_model_get_iter(model1, &iter, path); + gtk_tree_model_get(model1, &iter, COL_MENU, &menu, -1); + + if (event->type == GDK_2BUTTON_PRESS) { + toggle_sym_value(menu); + current = menu; + display_tree_part(); + } else { + browsed = menu; + display_tree_part(); + } + + gtk_widget_realize(tree2_w); + gtk_tree_view_set_cursor(view, path, NULL, FALSE); + gtk_widget_grab_focus(tree2_w); + + return FALSE; +} + + +/* Fill a row of strings */ +static gchar **fill_row(struct menu *menu) +{ + static gchar *row[COL_NUMBER]; + struct symbol *sym = menu->sym; + const char *def; + int stype; + tristate val; + enum prop_type ptype; + int i; + + for (i = COL_OPTION; i <= COL_COLOR; i++) + g_free(row[i]); + bzero(row, sizeof(row)); + + row[COL_OPTION] = + g_strdup_printf("%s %s", _(menu_get_prompt(menu)), + sym && !sym_has_value(sym) ? "(NEW)" : ""); + + if (opt_mode == OPT_ALL && !menu_is_visible(menu)) + row[COL_COLOR] = g_strdup("DarkGray"); + else if (opt_mode == OPT_PROMPT && + menu_has_prompt(menu) && !menu_is_visible(menu)) + row[COL_COLOR] = g_strdup("DarkGray"); + else + row[COL_COLOR] = g_strdup("Black"); + + ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN; + switch (ptype) { + case P_MENU: + row[COL_PIXBUF] = (gchar *) xpm_menu; + if (view_mode == SINGLE_VIEW) + row[COL_PIXVIS] = GINT_TO_POINTER(TRUE); + row[COL_BTNVIS] = GINT_TO_POINTER(FALSE); + break; + case P_COMMENT: + row[COL_PIXBUF] = (gchar *) xpm_void; + row[COL_PIXVIS] = GINT_TO_POINTER(FALSE); + row[COL_BTNVIS] = GINT_TO_POINTER(FALSE); + break; + default: + row[COL_PIXBUF] = (gchar *) xpm_void; + row[COL_PIXVIS] = GINT_TO_POINTER(FALSE); + row[COL_BTNVIS] = GINT_TO_POINTER(TRUE); + break; + } + + if (!sym) + return row; + row[COL_NAME] = g_strdup(sym->name); + + sym_calc_value(sym); + sym->flags &= ~SYMBOL_CHANGED; + + if (sym_is_choice(sym)) { // parse childs for getting final value + struct menu *child; + struct symbol *def_sym = sym_get_choice_value(sym); + struct menu *def_menu = NULL; + + row[COL_BTNVIS] = GINT_TO_POINTER(FALSE); + + for (child = menu->list; child; child = child->next) { + if (menu_is_visible(child) + && child->sym == def_sym) + def_menu = child; + } + + if (def_menu) + row[COL_VALUE] = + g_strdup(_(menu_get_prompt(def_menu))); + } + if (sym->flags & SYMBOL_CHOICEVAL) + row[COL_BTNRAD] = GINT_TO_POINTER(TRUE); + + stype = sym_get_type(sym); + switch (stype) { + case S_BOOLEAN: + if (GPOINTER_TO_INT(row[COL_PIXVIS]) == FALSE) + row[COL_BTNVIS] = GINT_TO_POINTER(TRUE); + if (sym_is_choice(sym)) + break; + /* fall through */ + case S_TRISTATE: + val = sym_get_tristate_value(sym); + switch (val) { + case no: + row[COL_NO] = g_strdup("N"); + row[COL_VALUE] = g_strdup("N"); + row[COL_BTNACT] = GINT_TO_POINTER(FALSE); + row[COL_BTNINC] = GINT_TO_POINTER(FALSE); + break; + case mod: + row[COL_MOD] = g_strdup("M"); + row[COL_VALUE] = g_strdup("M"); + row[COL_BTNINC] = GINT_TO_POINTER(TRUE); + break; + case yes: + row[COL_YES] = g_strdup("Y"); + row[COL_VALUE] = g_strdup("Y"); + row[COL_BTNACT] = GINT_TO_POINTER(TRUE); + row[COL_BTNINC] = GINT_TO_POINTER(FALSE); + break; + } + + if (val != no && sym_tristate_within_range(sym, no)) + row[COL_NO] = g_strdup("_"); + if (val != mod && sym_tristate_within_range(sym, mod)) + row[COL_MOD] = g_strdup("_"); + if (val != yes && sym_tristate_within_range(sym, yes)) + row[COL_YES] = g_strdup("_"); + break; + case S_INT: + case S_HEX: + case S_STRING: + def = sym_get_string_value(sym); + row[COL_VALUE] = g_strdup(def); + row[COL_EDIT] = GINT_TO_POINTER(TRUE); + row[COL_BTNVIS] = GINT_TO_POINTER(FALSE); + break; + } + + return row; +} + + +/* Set the node content with a row of strings */ +static void set_node(GtkTreeIter * node, struct menu *menu, gchar ** row) +{ + GdkColor color; + gboolean success; + GdkPixbuf *pix; + + pix = gdk_pixbuf_new_from_xpm_data((const char **) + row[COL_PIXBUF]); + + gdk_color_parse(row[COL_COLOR], &color); + gdk_colormap_alloc_colors(gdk_colormap_get_system(), &color, 1, + FALSE, FALSE, &success); + + gtk_tree_store_set(tree, node, + COL_OPTION, row[COL_OPTION], + COL_NAME, row[COL_NAME], + COL_NO, row[COL_NO], + COL_MOD, row[COL_MOD], + COL_YES, row[COL_YES], + COL_VALUE, row[COL_VALUE], + COL_MENU, (gpointer) menu, + COL_COLOR, &color, + COL_EDIT, GPOINTER_TO_INT(row[COL_EDIT]), + COL_PIXBUF, pix, + COL_PIXVIS, GPOINTER_TO_INT(row[COL_PIXVIS]), + COL_BTNVIS, GPOINTER_TO_INT(row[COL_BTNVIS]), + COL_BTNACT, GPOINTER_TO_INT(row[COL_BTNACT]), + COL_BTNINC, GPOINTER_TO_INT(row[COL_BTNINC]), + COL_BTNRAD, GPOINTER_TO_INT(row[COL_BTNRAD]), + -1); + + g_object_unref(pix); +} + + +/* Add a node to the tree */ +static void place_node(struct menu *menu, char **row) +{ + GtkTreeIter *parent = parents[indent - 1]; + GtkTreeIter *node = parents[indent]; + + gtk_tree_store_append(tree, node, parent); + set_node(node, menu, row); +} + + +/* Find a node in the GTK+ tree */ +static GtkTreeIter found; + +/* + * Find a menu in the GtkTree starting at parent. + */ +GtkTreeIter *gtktree_iter_find_node(GtkTreeIter * parent, + struct menu *tofind) +{ + GtkTreeIter iter; + GtkTreeIter *child = &iter; + gboolean valid; + GtkTreeIter *ret; + + valid = gtk_tree_model_iter_children(model2, child, parent); + while (valid) { + struct menu *menu; + + gtk_tree_model_get(model2, child, 6, &menu, -1); + + if (menu == tofind) { + memcpy(&found, child, sizeof(GtkTreeIter)); + return &found; + } + + ret = gtktree_iter_find_node(child, tofind); + if (ret) + return ret; + + valid = gtk_tree_model_iter_next(model2, child); + } + + return NULL; +} + + +/* + * Update the tree by adding/removing entries + * Does not change other nodes + */ +static void update_tree(struct menu *src, GtkTreeIter * dst) +{ + struct menu *child1; + GtkTreeIter iter, tmp; + GtkTreeIter *child2 = &iter; + gboolean valid; + GtkTreeIter *sibling; + struct symbol *sym; + struct menu *menu1, *menu2; + + if (src == &rootmenu) + indent = 1; + + valid = gtk_tree_model_iter_children(model2, child2, dst); + for (child1 = src->list; child1; child1 = child1->next) { + + sym = child1->sym; + + reparse: + menu1 = child1; + if (valid) + gtk_tree_model_get(model2, child2, COL_MENU, + &menu2, -1); + else + menu2 = NULL; // force adding of a first child + +#ifdef DEBUG + printf("%*c%s | %s\n", indent, ' ', + menu1 ? menu_get_prompt(menu1) : "nil", + menu2 ? menu_get_prompt(menu2) : "nil"); +#endif + + if ((opt_mode == OPT_NORMAL && !menu_is_visible(child1)) || + (opt_mode == OPT_PROMPT && !menu_has_prompt(child1)) || + (opt_mode == OPT_ALL && !menu_get_prompt(child1))) { + + /* remove node */ + if (gtktree_iter_find_node(dst, menu1) != NULL) { + memcpy(&tmp, child2, sizeof(GtkTreeIter)); + valid = gtk_tree_model_iter_next(model2, + child2); + gtk_tree_store_remove(tree2, &tmp); + if (!valid) + return; /* next parent */ + else + goto reparse; /* next child */ + } else + continue; + } + + if (menu1 != menu2) { + if (gtktree_iter_find_node(dst, menu1) == NULL) { // add node + if (!valid && !menu2) + sibling = NULL; + else + sibling = child2; + gtk_tree_store_insert_before(tree2, + child2, + dst, sibling); + set_node(child2, menu1, fill_row(menu1)); + if (menu2 == NULL) + valid = TRUE; + } else { // remove node + memcpy(&tmp, child2, sizeof(GtkTreeIter)); + valid = gtk_tree_model_iter_next(model2, + child2); + gtk_tree_store_remove(tree2, &tmp); + if (!valid) + return; // next parent + else + goto reparse; // next child + } + } else if (sym && (sym->flags & SYMBOL_CHANGED)) { + set_node(child2, menu1, fill_row(menu1)); + } + + indent++; + update_tree(child1, child2); + indent--; + + valid = gtk_tree_model_iter_next(model2, child2); + } +} + + +/* Display the whole tree (single/split/full view) */ +static void display_tree(struct menu *menu) +{ + struct symbol *sym; + struct property *prop; + struct menu *child; + enum prop_type ptype; + + if (menu == &rootmenu) { + indent = 1; + current = &rootmenu; + } + + for (child = menu->list; child; child = child->next) { + prop = child->prompt; + sym = child->sym; + ptype = prop ? prop->type : P_UNKNOWN; + + if (sym) + sym->flags &= ~SYMBOL_CHANGED; + + if ((view_mode == SPLIT_VIEW) + && !(child->flags & MENU_ROOT) && (tree == tree1)) + continue; + + if ((view_mode == SPLIT_VIEW) && (child->flags & MENU_ROOT) + && (tree == tree2)) + continue; + + if ((opt_mode == OPT_NORMAL && menu_is_visible(child)) || + (opt_mode == OPT_PROMPT && menu_has_prompt(child)) || + (opt_mode == OPT_ALL && menu_get_prompt(child))) + place_node(child, fill_row(child)); +#ifdef DEBUG + printf("%*c%s: ", indent, ' ', menu_get_prompt(child)); + printf("%s", child->flags & MENU_ROOT ? "rootmenu | " : ""); + printf("%s", prop_get_type_name(ptype)); + printf(" | "); + if (sym) { + printf("%s", sym_type_name(sym->type)); + printf(" | "); + printf("%s", dbg_sym_flags(sym->flags)); + printf("\n"); + } else + printf("\n"); +#endif + if ((view_mode != FULL_VIEW) && (ptype == P_MENU) + && (tree == tree2)) + continue; +/* + if (((menu != &rootmenu) && !(menu->flags & MENU_ROOT)) + || (view_mode == FULL_VIEW) + || (view_mode == SPLIT_VIEW))*/ + + /* Change paned position if the view is not in 'split mode' */ + if (view_mode == SINGLE_VIEW || view_mode == FULL_VIEW) { + gtk_paned_set_position(GTK_PANED(hpaned), 0); + } + + if (((view_mode == SINGLE_VIEW) && (menu->flags & MENU_ROOT)) + || (view_mode == FULL_VIEW) + || (view_mode == SPLIT_VIEW)) { + indent++; + display_tree(child); + indent--; + } + } +} + +/* Display a part of the tree starting at current node (single/split view) */ +static void display_tree_part(void) +{ + if (tree2) + gtk_tree_store_clear(tree2); + if (view_mode == SINGLE_VIEW) + display_tree(current); + else if (view_mode == SPLIT_VIEW) + display_tree(browsed); + gtk_tree_view_expand_all(GTK_TREE_VIEW(tree2_w)); +} + +/* Display the list in the left frame (split view) */ +static void display_list(void) +{ + if (tree1) + gtk_tree_store_clear(tree1); + + tree = tree1; + display_tree(&rootmenu); + gtk_tree_view_expand_all(GTK_TREE_VIEW(tree1_w)); + tree = tree2; +} + +void fixup_rootmenu(struct menu *menu) +{ + struct menu *child; + static int menu_cnt = 0; + + menu->flags |= MENU_ROOT; + for (child = menu->list; child; child = child->next) { + if (child->prompt && child->prompt->type == P_MENU) { + menu_cnt++; + fixup_rootmenu(child); + menu_cnt--; + } else if (!menu_cnt) + fixup_rootmenu(child); + } +} + + +/* Main */ +int main(int ac, char *av[]) +{ + const char *name; + char *env; + gchar *glade_file; + + bindtextdomain(PACKAGE, LOCALEDIR); + bind_textdomain_codeset(PACKAGE, "UTF-8"); + textdomain(PACKAGE); + + /* GTK stuffs */ + gtk_set_locale(); + gtk_init(&ac, &av); + glade_init(); + + //add_pixmap_directory (PACKAGE_DATA_DIR "/" PACKAGE "/pixmaps"); + //add_pixmap_directory (PACKAGE_SOURCE_DIR "/pixmaps"); + + /* Determine GUI path */ + env = getenv(SRCTREE); + if (env) + glade_file = g_strconcat(env, "/tool/kconfig/scripts/kconfig/gconf.glade", NULL); + else if (av[0][0] == '/') + glade_file = g_strconcat(av[0], ".glade", NULL); + else + glade_file = g_strconcat(g_get_current_dir(), "/", av[0], ".glade", NULL); + + /* Conf stuffs */ + if (ac > 1 && av[1][0] == '-') { + switch (av[1][1]) { + case 'a': + //showAll = 1; + break; + case 'h': + case '?': + printf("%s \n", av[0]); + exit(0); + } + name = av[2]; + } else + name = av[1]; + + conf_parse(name); + fixup_rootmenu(&rootmenu); + conf_read(NULL); + + /* Load the interface and connect signals */ + init_main_window(glade_file); + init_tree_model(); + init_left_tree(); + init_right_tree(); + + switch (view_mode) { + case SINGLE_VIEW: + display_tree_part(); + break; + case SPLIT_VIEW: + display_list(); + break; + case FULL_VIEW: + display_tree(&rootmenu); + break; + } + + gtk_main(); + + return 0; +} + +static void conf_changed(void) +{ + bool changed = conf_get_changed(); + gtk_widget_set_sensitive(save_btn, changed); + gtk_widget_set_sensitive(save_menu_item, changed); +} diff --git a/kernel/fiasco/tool/kconfig/scripts/kconfig/gconf.glade b/kernel/fiasco/tool/kconfig/scripts/kconfig/gconf.glade new file mode 100644 index 00000000..aa483cb3 --- /dev/null +++ b/kernel/fiasco/tool/kconfig/scripts/kconfig/gconf.glade @@ -0,0 +1,661 @@ + + + + + + True + Gtk Kernel Configurator + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_NONE + False + 640 + 480 + True + False + True + False + False + GDK_WINDOW_TYPE_HINT_NORMAL + GDK_GRAVITY_NORTH_WEST + + + + + + + True + False + 0 + + + + True + + + + True + _File + True + + + + + + + True + Load a config file + _Load + True + + + + + + True + gtk-open + 1 + 0.5 + 0.5 + 0 + 0 + + + + + + + + True + Save the config in .config + _Save + True + + + + + + True + gtk-save + 1 + 0.5 + 0.5 + 0 + 0 + + + + + + + + True + Save the config in a file + Save _as + True + + + + + True + gtk-save-as + 1 + 0.5 + 0.5 + 0 + 0 + + + + + + + + True + + + + + + True + _Quit + True + + + + + + True + gtk-quit + 1 + 0.5 + 0.5 + 0 + 0 + + + + + + + + + + + + True + _Options + True + + + + + + + True + Show name + Show _name + True + False + + + + + + + True + Show range (Y/M/N) + Show _range + True + False + + + + + + + True + Show value of the option + Show _data + True + False + + + + + + + True + + + + + + True + Show normal options + Show normal options + True + True + + + + + + + True + Show all options + Show all _options + True + False + set_option_mode1 + + + + + + + True + Show all options with prompts + Show all prompt options + True + False + set_option_mode1 + + + + + + + + + + + + True + _Help + True + + + + + + + True + _Introduction + True + + + + + + True + gtk-dialog-question + 1 + 0.5 + 0.5 + 0 + 0 + + + + + + + + True + _About + True + + + + + + True + gtk-properties + 1 + 0.5 + 0.5 + 0 + 0 + + + + + + + + True + _License + True + + + + + True + gtk-justify-fill + 1 + 0.5 + 0.5 + 0 + 0 + + + + + + + + + + + 0 + False + False + + + + + + True + GTK_SHADOW_OUT + GTK_POS_LEFT + GTK_POS_TOP + + + + True + GTK_ORIENTATION_HORIZONTAL + GTK_TOOLBAR_BOTH + True + True + + + + True + Goes up of one level (single view) + Back + True + gtk-undo + True + True + False + + + + False + True + + + + + + True + True + True + False + + + + True + + + + + False + False + + + + + + True + Load a config file + Load + True + gtk-open + True + True + False + + + + False + True + + + + + + True + Save a config file + Save + True + gtk-save + True + True + False + + + + False + True + + + + + + True + True + True + False + + + + True + + + + + False + False + + + + + + True + Single view + Single + True + gtk-missing-image + True + True + False + + + + False + True + + + + + + True + Split view + Split + True + gtk-missing-image + True + True + False + + + + False + True + + + + + + True + Full view + Full + True + gtk-missing-image + True + True + False + + + + False + True + + + + + + True + True + True + False + + + + True + + + + + False + False + + + + + + True + Collapse the whole tree in the right frame + Collapse + True + gtk-remove + True + True + False + + + + False + True + + + + + + True + Expand the whole tree in the right frame + Expand + True + gtk-add + True + True + False + + + + False + True + + + + + + + 0 + False + False + + + + + + 1 + True + True + 0 + + + + True + GTK_POLICY_AUTOMATIC + GTK_POLICY_AUTOMATIC + GTK_SHADOW_IN + GTK_CORNER_TOP_LEFT + + + + True + True + True + False + False + False + + + + + + + + True + False + + + + + + True + True + 0 + + + + True + GTK_POLICY_AUTOMATIC + GTK_POLICY_AUTOMATIC + GTK_SHADOW_IN + GTK_CORNER_TOP_LEFT + + + + True + True + True + True + False + False + False + + + + + + + + True + False + + + + + + True + GTK_POLICY_NEVER + GTK_POLICY_AUTOMATIC + GTK_SHADOW_IN + GTK_CORNER_TOP_LEFT + + + + True + True + False + False + True + GTK_JUSTIFY_LEFT + GTK_WRAP_WORD + True + 0 + 0 + 0 + 0 + 0 + 0 + Sorry, no help available for this option yet. + + + + + True + True + + + + + True + True + + + + + 0 + True + True + + + + + + + diff --git a/kernel/fiasco/tool/kconfig/scripts/kconfig/images.c b/kernel/fiasco/tool/kconfig/scripts/kconfig/images.c new file mode 100644 index 00000000..d4f84bd4 --- /dev/null +++ b/kernel/fiasco/tool/kconfig/scripts/kconfig/images.c @@ -0,0 +1,326 @@ +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +static const char *xpm_load[] = { +"22 22 5 1", +". c None", +"# c #000000", +"c c #838100", +"a c #ffff00", +"b c #ffffff", +"......................", +"......................", +"......................", +"............####....#.", +"...........#....##.##.", +"..................###.", +".................####.", +".####...........#####.", +"#abab##########.......", +"#babababababab#.......", +"#ababababababa#.......", +"#babababababab#.......", +"#ababab###############", +"#babab##cccccccccccc##", +"#abab##cccccccccccc##.", +"#bab##cccccccccccc##..", +"#ab##cccccccccccc##...", +"#b##cccccccccccc##....", +"###cccccccccccc##.....", +"##cccccccccccc##......", +"###############.......", +"......................"}; + +static const char *xpm_save[] = { +"22 22 5 1", +". c None", +"# c #000000", +"a c #838100", +"b c #c5c2c5", +"c c #cdb6d5", +"......................", +".####################.", +".#aa#bbbbbbbbbbbb#bb#.", +".#aa#bbbbbbbbbbbb#bb#.", +".#aa#bbbbbbbbbcbb####.", +".#aa#bbbccbbbbbbb#aa#.", +".#aa#bbbccbbbbbbb#aa#.", +".#aa#bbbbbbbbbbbb#aa#.", +".#aa#bbbbbbbbbbbb#aa#.", +".#aa#bbbbbbbbbbbb#aa#.", +".#aa#bbbbbbbbbbbb#aa#.", +".#aaa############aaa#.", +".#aaaaaaaaaaaaaaaaaa#.", +".#aaaaaaaaaaaaaaaaaa#.", +".#aaa#############aa#.", +".#aaa#########bbb#aa#.", +".#aaa#########bbb#aa#.", +".#aaa#########bbb#aa#.", +".#aaa#########bbb#aa#.", +".#aaa#########bbb#aa#.", +"..##################..", +"......................"}; + +static const char *xpm_back[] = { +"22 22 3 1", +". c None", +"# c #000083", +"a c #838183", +"......................", +"......................", +"......................", +"......................", +"......................", +"...........######a....", +"..#......##########...", +"..##...####......##a..", +"..###.###.........##..", +"..######..........##..", +"..#####...........##..", +"..######..........##..", +"..#######.........##..", +"..########.......##a..", +"...............a###...", +"...............###....", +"......................", +"......................", +"......................", +"......................", +"......................", +"......................"}; + +static const char *xpm_tree_view[] = { +"22 22 2 1", +". c None", +"# c #000000", +"......................", +"......................", +"......#...............", +"......#...............", +"......#...............", +"......#...............", +"......#...............", +"......########........", +"......#...............", +"......#...............", +"......#...............", +"......#...............", +"......#...............", +"......########........", +"......#...............", +"......#...............", +"......#...............", +"......#...............", +"......#...............", +"......########........", +"......................", +"......................"}; + +static const char *xpm_single_view[] = { +"22 22 2 1", +". c None", +"# c #000000", +"......................", +"......................", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"......................", +"......................"}; + +static const char *xpm_split_view[] = { +"22 22 2 1", +". c None", +"# c #000000", +"......................", +"......................", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......................", +"......................"}; + +static const char *xpm_symbol_no[] = { +"12 12 2 1", +" c white", +". c black", +" ", +" .......... ", +" . . ", +" . . ", +" . . ", +" . . ", +" . . ", +" . . ", +" . . ", +" . . ", +" .......... ", +" "}; + +static const char *xpm_symbol_mod[] = { +"12 12 2 1", +" c white", +". c black", +" ", +" .......... ", +" . . ", +" . . ", +" . .. . ", +" . .... . ", +" . .... . ", +" . .. . ", +" . . ", +" . . ", +" .......... ", +" "}; + +static const char *xpm_symbol_yes[] = { +"12 12 2 1", +" c white", +". c black", +" ", +" .......... ", +" . . ", +" . . ", +" . . . ", +" . .. . ", +" . . .. . ", +" . .... . ", +" . .. . ", +" . . ", +" .......... ", +" "}; + +static const char *xpm_choice_no[] = { +"12 12 2 1", +" c white", +". c black", +" ", +" .... ", +" .. .. ", +" . . ", +" . . ", +" . . ", +" . . ", +" . . ", +" . . ", +" .. .. ", +" .... ", +" "}; + +static const char *xpm_choice_yes[] = { +"12 12 2 1", +" c white", +". c black", +" ", +" .... ", +" .. .. ", +" . . ", +" . .. . ", +" . .... . ", +" . .... . ", +" . .. . ", +" . . ", +" .. .. ", +" .... ", +" "}; + +static const char *xpm_menu[] = { +"12 12 2 1", +" c white", +". c black", +" ", +" .......... ", +" . . ", +" . .. . ", +" . .... . ", +" . ...... . ", +" . ...... . ", +" . .... . ", +" . .. . ", +" . . ", +" .......... ", +" "}; + +static const char *xpm_menu_inv[] = { +"12 12 2 1", +" c white", +". c black", +" ", +" .......... ", +" .......... ", +" .. ...... ", +" .. .... ", +" .. .. ", +" .. .. ", +" .. .... ", +" .. ...... ", +" .......... ", +" .......... ", +" "}; + +static const char *xpm_menuback[] = { +"12 12 2 1", +" c white", +". c black", +" ", +" .......... ", +" . . ", +" . .. . ", +" . .... . ", +" . ...... . ", +" . ...... . ", +" . .... . ", +" . .. . ", +" . . ", +" .......... ", +" "}; + +static const char *xpm_void[] = { +"12 12 2 1", +" c white", +". c black", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" "}; diff --git a/kernel/fiasco/tool/kconfig/scripts/kconfig/kxgettext.c b/kernel/fiasco/tool/kconfig/scripts/kconfig/kxgettext.c new file mode 100644 index 00000000..2858738b --- /dev/null +++ b/kernel/fiasco/tool/kconfig/scripts/kconfig/kxgettext.c @@ -0,0 +1,235 @@ +/* + * Arnaldo Carvalho de Melo , 2005 + * + * Released under the terms of the GNU GPL v2.0 + */ + +#include +#include + +#include "lkc.h" + +static char *escape(const char* text, char *bf, int len) +{ + char *bfp = bf; + int multiline = strchr(text, '\n') != NULL; + int eol = 0; + int textlen = strlen(text); + + if ((textlen > 0) && (text[textlen-1] == '\n')) + eol = 1; + + *bfp++ = '"'; + --len; + + if (multiline) { + *bfp++ = '"'; + *bfp++ = '\n'; + *bfp++ = '"'; + len -= 3; + } + + while (*text != '\0' && len > 1) { + if (*text == '"') + *bfp++ = '\\'; + else if (*text == '\n') { + *bfp++ = '\\'; + *bfp++ = 'n'; + *bfp++ = '"'; + *bfp++ = '\n'; + *bfp++ = '"'; + len -= 5; + ++text; + goto next; + } + else if (*text == '\\') { + *bfp++ = '\\'; + len--; + } + *bfp++ = *text++; +next: + --len; + } + + if (multiline && eol) + bfp -= 3; + + *bfp++ = '"'; + *bfp = '\0'; + + return bf; +} + +struct file_line { + struct file_line *next; + const char *file; + int lineno; +}; + +static struct file_line *file_line__new(const char *file, int lineno) +{ + struct file_line *self = malloc(sizeof(*self)); + + if (self == NULL) + goto out; + + self->file = file; + self->lineno = lineno; + self->next = NULL; +out: + return self; +} + +struct message { + const char *msg; + const char *option; + struct message *next; + struct file_line *files; +}; + +static struct message *message__list; + +static struct message *message__new(const char *msg, char *option, + const char *file, int lineno) +{ + struct message *self = malloc(sizeof(*self)); + + if (self == NULL) + goto out; + + self->files = file_line__new(file, lineno); + if (self->files == NULL) + goto out_fail; + + self->msg = strdup(msg); + if (self->msg == NULL) + goto out_fail_msg; + + self->option = option; + self->next = NULL; +out: + return self; +out_fail_msg: + free(self->files); +out_fail: + free(self); + self = NULL; + goto out; +} + +static struct message *mesage__find(const char *msg) +{ + struct message *m = message__list; + + while (m != NULL) { + if (strcmp(m->msg, msg) == 0) + break; + m = m->next; + } + + return m; +} + +static int message__add_file_line(struct message *self, const char *file, + int lineno) +{ + int rc = -1; + struct file_line *fl = file_line__new(file, lineno); + + if (fl == NULL) + goto out; + + fl->next = self->files; + self->files = fl; + rc = 0; +out: + return rc; +} + +static int message__add(const char *msg, char *option, const char *file, + int lineno) +{ + int rc = 0; + char bf[16384]; + char *escaped = escape(msg, bf, sizeof(bf)); + struct message *m = mesage__find(escaped); + + if (m != NULL) + rc = message__add_file_line(m, file, lineno); + else { + m = message__new(escaped, option, file, lineno); + + if (m != NULL) { + m->next = message__list; + message__list = m; + } else + rc = -1; + } + return rc; +} + +static void menu_build_message_list(struct menu *menu) +{ + struct menu *child; + + message__add(menu_get_prompt(menu), NULL, + menu->file == NULL ? "Root Menu" : menu->file->name, + menu->lineno); + + if (menu->sym != NULL && menu_has_help(menu)) + message__add(menu_get_help(menu), menu->sym->name, + menu->file == NULL ? "Root Menu" : menu->file->name, + menu->lineno); + + for (child = menu->list; child != NULL; child = child->next) + if (child->prompt != NULL) + menu_build_message_list(child); +} + +static void message__print_file_lineno(struct message *self) +{ + struct file_line *fl = self->files; + + putchar('\n'); + if (self->option != NULL) + printf("# %s:00000\n", self->option); + + printf("#: %s:%d", fl->file, fl->lineno); + fl = fl->next; + + while (fl != NULL) { + printf(", %s:%d", fl->file, fl->lineno); + fl = fl->next; + } + + putchar('\n'); +} + +static void message__print_gettext_msgid_msgstr(struct message *self) +{ + message__print_file_lineno(self); + + printf("msgid %s\n" + "msgstr \"\"\n", self->msg); +} + +static void menu__xgettext(void) +{ + struct message *m = message__list; + + while (m != NULL) { + /* skip empty lines ("") */ + if (strlen(m->msg) > sizeof("\"\"")) + message__print_gettext_msgid_msgstr(m); + m = m->next; + } +} + +int main(int ac, char **av) +{ + conf_parse(av[1]); + + menu_build_message_list(menu_get_root_menu(NULL)); + menu__xgettext(); + return 0; +} diff --git a/kernel/fiasco/tool/kconfig/scripts/kconfig/lkc.h b/kernel/fiasco/tool/kconfig/scripts/kconfig/lkc.h new file mode 100644 index 00000000..97c967e6 --- /dev/null +++ b/kernel/fiasco/tool/kconfig/scripts/kconfig/lkc.h @@ -0,0 +1,190 @@ +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +#ifndef LKC_H +#define LKC_H + +#include "expr.h" + +#ifndef KBUILD_NO_NLS +# include +#else +static inline const char *gettext(const char *txt) { return txt; } +static inline void textdomain(const char *domainname) {} +static inline void bindtextdomain(const char *name, const char *dir) {} +static inline char *bind_textdomain_codeset(const char *dn, char *c) { return c; } +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#define P(name,type,arg) extern type name arg +#include "lkc_proto.h" +#undef P + +#define SRCTREE "fiasco_srcdir" + +#ifndef PACKAGE +#define PACKAGE "linux" +#endif + +#define LOCALEDIR "/usr/share/locale" + +#define _(text) gettext(text) +#define N_(text) (text) + +#ifndef CONFIG_ +#define CONFIG_ "CONFIG_" +#endif + +#define TF_COMMAND 0x0001 +#define TF_PARAM 0x0002 +#define TF_OPTION 0x0004 + +enum conf_def_mode { + def_default, + def_yes, + def_mod, + def_no, + def_random +}; + +#define T_OPT_MODULES 1 +#define T_OPT_DEFCONFIG_LIST 2 +#define T_OPT_ENV 3 + +struct kconf_id { + int name; + int token; + unsigned int flags; + enum symbol_type stype; +}; + +extern int zconfdebug; + +int zconfparse(void); +void zconfdump(FILE *out); +void zconf_starthelp(void); +FILE *zconf_fopen(const char *name); +void zconf_initscan(const char *name); +void zconf_nextfile(const char *name); +int zconf_lineno(void); +const char *zconf_curname(void); + +/* confdata.c */ +const char *conf_get_configname(void); +const char *conf_get_autoconfig_name(void); +char *conf_get_default_confname(void); +void sym_set_change_count(int count); +void sym_add_change_count(int count); +void conf_set_all_new_symbols(enum conf_def_mode mode); + +struct conf_printer { + void (*print_symbol)(FILE *, struct symbol *, const char *, void *); + void (*print_comment)(FILE *, const char *, void *); +}; + +/* confdata.c and expr.c */ +static inline void xfwrite(const void *str, size_t len, size_t count, FILE *out) +{ + assert(len != 0); + + if (fwrite(str, len, count, out) != count) + fprintf(stderr, "Error in writing or end of file.\n"); +} + +/* menu.c */ +void _menu_init(void); +void menu_warn(struct menu *menu, const char *fmt, ...); +struct menu *menu_add_menu(void); +void menu_end_menu(void); +void menu_add_entry(struct symbol *sym); +void menu_end_entry(void); +void menu_add_dep(struct expr *dep); +void menu_add_visibility(struct expr *dep); +struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *expr, struct expr *dep); +struct property *menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep); +void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep); +void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep); +void menu_add_option(int token, char *arg); +void menu_finalize(struct menu *parent); +void menu_set_type(int type); + +/* util.c */ +struct file *file_lookup(const char *name); +int file_write_dep(const char *name); + +struct gstr { + size_t len; + char *s; + /* + * when max_width is not zero long lines in string s (if any) get + * wrapped not to exceed the max_width value + */ + int max_width; +}; +struct gstr str_new(void); +struct gstr str_assign(const char *s); +void str_free(struct gstr *gs); +void str_append(struct gstr *gs, const char *s); +void str_printf(struct gstr *gs, const char *fmt, ...); +const char *str_get(struct gstr *gs); + +/* symbol.c */ +extern struct expr *sym_env_list; + +void sym_init(void); +void sym_clear_all_valid(void); +void sym_set_all_changed(void); +void sym_set_changed(struct symbol *sym); +struct symbol *sym_choice_default(struct symbol *sym); +const char *sym_get_string_default(struct symbol *sym); +struct symbol *sym_check_deps(struct symbol *sym); +struct property *prop_alloc(enum prop_type type, struct symbol *sym); +struct symbol *prop_get_symbol(struct property *prop); +struct property *sym_get_env_prop(struct symbol *sym); + +static inline tristate sym_get_tristate_value(struct symbol *sym) +{ + return sym->curr.tri; +} + + +static inline struct symbol *sym_get_choice_value(struct symbol *sym) +{ + return (struct symbol *)sym->curr.val; +} + +static inline bool sym_set_choice_value(struct symbol *ch, struct symbol *chval) +{ + return sym_set_tristate_value(chval, yes); +} + +static inline bool sym_is_choice(struct symbol *sym) +{ + return sym->flags & SYMBOL_CHOICE ? true : false; +} + +static inline bool sym_is_choice_value(struct symbol *sym) +{ + return sym->flags & SYMBOL_CHOICEVAL ? true : false; +} + +static inline bool sym_is_optional(struct symbol *sym) +{ + return sym->flags & SYMBOL_OPTIONAL ? true : false; +} + +static inline bool sym_has_value(struct symbol *sym) +{ + return sym->flags & SYMBOL_DEF_USER ? true : false; +} + +#ifdef __cplusplus +} +#endif + +#endif /* LKC_H */ diff --git a/kernel/fiasco/tool/kconfig/scripts/kconfig/lkc_proto.h b/kernel/fiasco/tool/kconfig/scripts/kconfig/lkc_proto.h new file mode 100644 index 00000000..47fe9c34 --- /dev/null +++ b/kernel/fiasco/tool/kconfig/scripts/kconfig/lkc_proto.h @@ -0,0 +1,54 @@ +#include + +/* confdata.c */ +P(conf_parse,void,(const char *name)); +P(conf_read,int,(const char *name)); +P(conf_read_simple,int,(const char *name, int)); +P(conf_write_defconfig,int,(const char *name)); +P(conf_write,int,(const char *name)); +P(conf_write_autoconf,int,(void)); +P(conf_get_changed,bool,(void)); +P(conf_set_changed_callback, void,(void (*fn)(void))); +P(conf_set_message_callback, void,(void (*fn)(const char *fmt, va_list ap))); + +/* menu.c */ +P(rootmenu,struct menu,); + +P(menu_is_visible, bool, (struct menu *menu)); +P(menu_has_prompt, bool, (struct menu *menu)); +P(menu_get_prompt,const char *,(struct menu *menu)); +P(menu_get_root_menu,struct menu *,(struct menu *menu)); +P(menu_get_parent_menu,struct menu *,(struct menu *menu)); +P(menu_has_help,bool,(struct menu *menu)); +P(menu_get_help,const char *,(struct menu *menu)); +P(get_symbol_str, void, (struct gstr *r, struct symbol *sym)); +P(get_relations_str, struct gstr, (struct symbol **sym_arr)); +P(menu_get_ext_help,void,(struct menu *menu, struct gstr *help)); + +/* symbol.c */ +P(symbol_hash,struct symbol *,[SYMBOL_HASHSIZE]); + +P(sym_lookup,struct symbol *,(const char *name, int flags)); +P(sym_find,struct symbol *,(const char *name)); +P(sym_expand_string_value,const char *,(const char *in)); +P(sym_escape_string_value, const char *,(const char *in)); +P(sym_re_search,struct symbol **,(const char *pattern)); +P(sym_type_name,const char *,(enum symbol_type type)); +P(sym_calc_value,void,(struct symbol *sym)); +P(sym_get_type,enum symbol_type,(struct symbol *sym)); +P(sym_tristate_within_range,bool,(struct symbol *sym,tristate tri)); +P(sym_set_tristate_value,bool,(struct symbol *sym,tristate tri)); +P(sym_toggle_tristate_value,tristate,(struct symbol *sym)); +P(sym_string_valid,bool,(struct symbol *sym, const char *newval)); +P(sym_string_within_range,bool,(struct symbol *sym, const char *str)); +P(sym_set_string_value,bool,(struct symbol *sym, const char *newval)); +P(sym_is_changable,bool,(struct symbol *sym)); +P(sym_get_choice_prop,struct property *,(struct symbol *sym)); +P(sym_get_default_prop,struct property *,(struct symbol *sym)); +P(sym_get_string_value,const char *,(struct symbol *sym)); + +P(prop_get_type_name,const char *,(enum prop_type type)); + +/* expr.c */ +P(expr_compare_type,int,(enum expr_type t1, enum expr_type t2)); +P(expr_print,void,(struct expr *e, void (*fn)(void *, struct symbol *, const char *), void *data, int prevtoken)); diff --git a/kernel/fiasco/tool/kconfig/scripts/kconfig/lxdialog/.gitignore b/kernel/fiasco/tool/kconfig/scripts/kconfig/lxdialog/.gitignore new file mode 100644 index 00000000..90b08ff0 --- /dev/null +++ b/kernel/fiasco/tool/kconfig/scripts/kconfig/lxdialog/.gitignore @@ -0,0 +1,4 @@ +# +# Generated files +# +lxdialog diff --git a/kernel/fiasco/tool/kconfig/scripts/kconfig/lxdialog/BIG.FAT.WARNING b/kernel/fiasco/tool/kconfig/scripts/kconfig/lxdialog/BIG.FAT.WARNING new file mode 100644 index 00000000..a8999d82 --- /dev/null +++ b/kernel/fiasco/tool/kconfig/scripts/kconfig/lxdialog/BIG.FAT.WARNING @@ -0,0 +1,4 @@ +This is NOT the official version of dialog. This version has been +significantly modified from the original. It is for use by the Linux +kernel configuration script. Please do not bother Savio Lam with +questions about this program. diff --git a/kernel/fiasco/tool/kconfig/scripts/kconfig/lxdialog/check-lxdialog.sh b/kernel/fiasco/tool/kconfig/scripts/kconfig/lxdialog/check-lxdialog.sh new file mode 100644 index 00000000..82cc3a85 --- /dev/null +++ b/kernel/fiasco/tool/kconfig/scripts/kconfig/lxdialog/check-lxdialog.sh @@ -0,0 +1,84 @@ +#!/bin/sh +# Check ncurses compatibility + +# What library to link +ldflags() +{ + for ext in so a dylib ; do + for lib in ncursesw ncurses curses ; do + $cc -print-file-name=lib${lib}.${ext} | grep -q / + if [ $? -eq 0 ]; then + echo "-l${lib}" + exit + fi + done + done + exit 1 +} + +# Where is ncurses.h? +ccflags() +{ + if [ -f /usr/include/ncurses/ncurses.h ]; then + echo '-I/usr/include/ncurses -DCURSES_LOC=""' + elif [ -f /usr/include/ncurses/curses.h ]; then + echo '-I/usr/include/ncurses -DCURSES_LOC=""' + elif [ -f /usr/include/ncursesw/curses.h ]; then + echo '-I/usr/include/ncursesw -DCURSES_LOC=""' + elif [ -f /usr/include/ncurses.h ]; then + echo '-DCURSES_LOC=""' + else + echo '-DCURSES_LOC=""' + fi +} + +# Temp file, try to clean up after us +tmp=.lxdialog.tmp +trap "rm -f $tmp" 0 1 2 3 15 + +# Check if we can link to ncurses +check() { + $cc -xc - -o $tmp 2>/dev/null <<'EOF' +#include CURSES_LOC +main() {} +EOF + if [ $? != 0 ]; then + echo " *** Unable to find the ncurses libraries or the" 1>&2 + echo " *** required header files." 1>&2 + echo " *** 'make menuconfig' requires the ncurses libraries." 1>&2 + echo " *** " 1>&2 + echo " *** Install ncurses (ncurses-devel) and try again." 1>&2 + echo " *** " 1>&2 + exit 1 + fi +} + +usage() { + printf "Usage: $0 [-check compiler options|-ccflags|-ldflags compiler options]\n" +} + +if [ $# -eq 0 ]; then + usage + exit 1 +fi + +cc="" +case "$1" in + "-check") + shift + cc="$@" + check + ;; + "-ccflags") + ccflags + ;; + "-ldflags") + shift + cc="$@" + ldflags + ;; + "*") + usage + exit 1 + ;; +esac diff --git a/kernel/fiasco/tool/kconfig/scripts/kconfig/lxdialog/checklist.c b/kernel/fiasco/tool/kconfig/scripts/kconfig/lxdialog/checklist.c new file mode 100644 index 00000000..a2eb80fb --- /dev/null +++ b/kernel/fiasco/tool/kconfig/scripts/kconfig/lxdialog/checklist.c @@ -0,0 +1,332 @@ +/* + * checklist.c -- implements the checklist box + * + * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) + * Stuart Herbert - S.Herbert@sheffield.ac.uk: radiolist extension + * Alessandro Rubini - rubini@ipvvis.unipv.it: merged the two + * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "dialog.h" + +static int list_width, check_x, item_x; + +/* + * Print list item + */ +static void print_item(WINDOW * win, int choice, int selected) +{ + int i; + char *list_item = malloc(list_width + 1); + + strncpy(list_item, item_str(), list_width - item_x); + list_item[list_width - item_x] = '\0'; + + /* Clear 'residue' of last item */ + wattrset(win, dlg.menubox.atr); + wmove(win, choice, 0); + for (i = 0; i < list_width; i++) + waddch(win, ' '); + + wmove(win, choice, check_x); + wattrset(win, selected ? dlg.check_selected.atr + : dlg.check.atr); + if (!item_is_tag(':')) + wprintw(win, "(%c)", item_is_tag('X') ? 'X' : ' '); + + wattrset(win, selected ? dlg.tag_selected.atr : dlg.tag.atr); + mvwaddch(win, choice, item_x, list_item[0]); + wattrset(win, selected ? dlg.item_selected.atr : dlg.item.atr); + waddstr(win, list_item + 1); + if (selected) { + wmove(win, choice, check_x + 1); + wrefresh(win); + } + free(list_item); +} + +/* + * Print the scroll indicators. + */ +static void print_arrows(WINDOW * win, int choice, int item_no, int scroll, + int y, int x, int height) +{ + wmove(win, y, x); + + if (scroll > 0) { + wattrset(win, dlg.uarrow.atr); + waddch(win, ACS_UARROW); + waddstr(win, "(-)"); + } else { + wattrset(win, dlg.menubox.atr); + waddch(win, ACS_HLINE); + waddch(win, ACS_HLINE); + waddch(win, ACS_HLINE); + waddch(win, ACS_HLINE); + } + + y = y + height + 1; + wmove(win, y, x); + + if ((height < item_no) && (scroll + choice < item_no - 1)) { + wattrset(win, dlg.darrow.atr); + waddch(win, ACS_DARROW); + waddstr(win, "(+)"); + } else { + wattrset(win, dlg.menubox_border.atr); + waddch(win, ACS_HLINE); + waddch(win, ACS_HLINE); + waddch(win, ACS_HLINE); + waddch(win, ACS_HLINE); + } +} + +/* + * Display the termination buttons + */ +static void print_buttons(WINDOW * dialog, int height, int width, int selected) +{ + int x = width / 2 - 11; + int y = height - 2; + + print_button(dialog, gettext("Select"), y, x, selected == 0); + print_button(dialog, gettext(" Help "), y, x + 14, selected == 1); + + wmove(dialog, y, x + 1 + 14 * selected); + wrefresh(dialog); +} + +/* + * Display a dialog box with a list of options that can be turned on or off + * in the style of radiolist (only one option turned on at a time). + */ +int dialog_checklist(const char *title, const char *prompt, int height, + int width, int list_height) +{ + int i, x, y, box_x, box_y; + int key = 0, button = 0, choice = 0, scroll = 0, max_choice; + WINDOW *dialog, *list; + + /* which item to highlight */ + item_foreach() { + if (item_is_tag('X')) + choice = item_n(); + if (item_is_selected()) { + choice = item_n(); + break; + } + } + +do_resize: + if (getmaxy(stdscr) < (height + 6)) + return -ERRDISPLAYTOOSMALL; + if (getmaxx(stdscr) < (width + 6)) + return -ERRDISPLAYTOOSMALL; + + max_choice = MIN(list_height, item_count()); + + /* center dialog box on screen */ + x = (COLS - width) / 2; + y = (LINES - height) / 2; + + draw_shadow(stdscr, y, x, height, width); + + dialog = newwin(height, width, y, x); + keypad(dialog, TRUE); + + draw_box(dialog, 0, 0, height, width, + dlg.dialog.atr, dlg.border.atr); + wattrset(dialog, dlg.border.atr); + mvwaddch(dialog, height - 3, 0, ACS_LTEE); + for (i = 0; i < width - 2; i++) + waddch(dialog, ACS_HLINE); + wattrset(dialog, dlg.dialog.atr); + waddch(dialog, ACS_RTEE); + + print_title(dialog, title, width); + + wattrset(dialog, dlg.dialog.atr); + print_autowrap(dialog, prompt, width - 2, 1, 3); + + list_width = width - 6; + box_y = height - list_height - 5; + box_x = (width - list_width) / 2 - 1; + + /* create new window for the list */ + list = subwin(dialog, list_height, list_width, y + box_y + 1, + x + box_x + 1); + + keypad(list, TRUE); + + /* draw a box around the list items */ + draw_box(dialog, box_y, box_x, list_height + 2, list_width + 2, + dlg.menubox_border.atr, dlg.menubox.atr); + + /* Find length of longest item in order to center checklist */ + check_x = 0; + item_foreach() + check_x = MAX(check_x, strlen(item_str()) + 4); + check_x = MIN(check_x, list_width); + + check_x = (list_width - check_x) / 2; + item_x = check_x + 4; + + if (choice >= list_height) { + scroll = choice - list_height + 1; + choice -= scroll; + } + + /* Print the list */ + for (i = 0; i < max_choice; i++) { + item_set(scroll + i); + print_item(list, i, i == choice); + } + + print_arrows(dialog, choice, item_count(), scroll, + box_y, box_x + check_x + 5, list_height); + + print_buttons(dialog, height, width, 0); + + wnoutrefresh(dialog); + wnoutrefresh(list); + doupdate(); + + while (key != KEY_ESC) { + key = wgetch(dialog); + + for (i = 0; i < max_choice; i++) { + item_set(i + scroll); + if (toupper(key) == toupper(item_str()[0])) + break; + } + + if (i < max_choice || key == KEY_UP || key == KEY_DOWN || + key == '+' || key == '-') { + if (key == KEY_UP || key == '-') { + if (!choice) { + if (!scroll) + continue; + /* Scroll list down */ + if (list_height > 1) { + /* De-highlight current first item */ + item_set(scroll); + print_item(list, 0, FALSE); + scrollok(list, TRUE); + wscrl(list, -1); + scrollok(list, FALSE); + } + scroll--; + item_set(scroll); + print_item(list, 0, TRUE); + print_arrows(dialog, choice, item_count(), + scroll, box_y, box_x + check_x + 5, list_height); + + wnoutrefresh(dialog); + wrefresh(list); + + continue; /* wait for another key press */ + } else + i = choice - 1; + } else if (key == KEY_DOWN || key == '+') { + if (choice == max_choice - 1) { + if (scroll + choice >= item_count() - 1) + continue; + /* Scroll list up */ + if (list_height > 1) { + /* De-highlight current last item before scrolling up */ + item_set(scroll + max_choice - 1); + print_item(list, + max_choice - 1, + FALSE); + scrollok(list, TRUE); + wscrl(list, 1); + scrollok(list, FALSE); + } + scroll++; + item_set(scroll + max_choice - 1); + print_item(list, max_choice - 1, TRUE); + + print_arrows(dialog, choice, item_count(), + scroll, box_y, box_x + check_x + 5, list_height); + + wnoutrefresh(dialog); + wrefresh(list); + + continue; /* wait for another key press */ + } else + i = choice + 1; + } + if (i != choice) { + /* De-highlight current item */ + item_set(scroll + choice); + print_item(list, choice, FALSE); + /* Highlight new item */ + choice = i; + item_set(scroll + choice); + print_item(list, choice, TRUE); + wnoutrefresh(dialog); + wrefresh(list); + } + continue; /* wait for another key press */ + } + switch (key) { + case 'H': + case 'h': + case '?': + button = 1; + /* fall-through */ + case 'S': + case 's': + case ' ': + case '\n': + item_foreach() + item_set_selected(0); + item_set(scroll + choice); + item_set_selected(1); + delwin(list); + delwin(dialog); + return button; + case TAB: + case KEY_LEFT: + case KEY_RIGHT: + button = ((key == KEY_LEFT ? --button : ++button) < 0) + ? 1 : (button > 1 ? 0 : button); + + print_buttons(dialog, height, width, button); + wrefresh(dialog); + break; + case 'X': + case 'x': + key = KEY_ESC; + break; + case KEY_ESC: + key = on_key_esc(dialog); + break; + case KEY_RESIZE: + delwin(list); + delwin(dialog); + on_key_resize(); + goto do_resize; + } + + /* Now, update everything... */ + doupdate(); + } + delwin(list); + delwin(dialog); + return key; /* ESC pressed */ +} diff --git a/kernel/fiasco/tool/kconfig/scripts/kconfig/lxdialog/dialog.h b/kernel/fiasco/tool/kconfig/scripts/kconfig/lxdialog/dialog.h new file mode 100644 index 00000000..b5211fce --- /dev/null +++ b/kernel/fiasco/tool/kconfig/scripts/kconfig/lxdialog/dialog.h @@ -0,0 +1,230 @@ +/* + * dialog.h -- common declarations for all dialog modules + * + * AUTHOR: Savio Lam (lam836@cs.cuhk.hk) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include + +#ifndef KBUILD_NO_NLS +# include +#else +# define gettext(Msgid) ((const char *) (Msgid)) +#endif + +#ifdef __sun__ +#define CURS_MACROS +#endif +#include CURSES_LOC + +/* + * Colors in ncurses 1.9.9e do not work properly since foreground and + * background colors are OR'd rather than separately masked. This version + * of dialog was hacked to work with ncurses 1.9.9e, making it incompatible + * with standard curses. The simplest fix (to make this work with standard + * curses) uses the wbkgdset() function, not used in the original hack. + * Turn it off if we're building with 1.9.9e, since it just confuses things. + */ +#if defined(NCURSES_VERSION) && defined(_NEED_WRAP) && !defined(GCC_PRINTFLIKE) +#define OLD_NCURSES 1 +#undef wbkgdset +#define wbkgdset(w,p) /*nothing */ +#else +#define OLD_NCURSES 0 +#endif + +#define TR(params) _tracef params + +#define KEY_ESC 27 +#define TAB 9 +#define MAX_LEN 2048 +#define BUF_SIZE (10*1024) +#define MIN(x,y) (x < y ? x : y) +#define MAX(x,y) (x > y ? x : y) + +#ifndef ACS_ULCORNER +#define ACS_ULCORNER '+' +#endif +#ifndef ACS_LLCORNER +#define ACS_LLCORNER '+' +#endif +#ifndef ACS_URCORNER +#define ACS_URCORNER '+' +#endif +#ifndef ACS_LRCORNER +#define ACS_LRCORNER '+' +#endif +#ifndef ACS_HLINE +#define ACS_HLINE '-' +#endif +#ifndef ACS_VLINE +#define ACS_VLINE '|' +#endif +#ifndef ACS_LTEE +#define ACS_LTEE '+' +#endif +#ifndef ACS_RTEE +#define ACS_RTEE '+' +#endif +#ifndef ACS_UARROW +#define ACS_UARROW '^' +#endif +#ifndef ACS_DARROW +#define ACS_DARROW 'v' +#endif + +/* error return codes */ +#define ERRDISPLAYTOOSMALL (KEY_MAX + 1) + +/* + * Color definitions + */ +struct dialog_color { + chtype atr; /* Color attribute */ + int fg; /* foreground */ + int bg; /* background */ + int hl; /* highlight this item */ +}; + +struct dialog_info { + const char *backtitle; + struct dialog_color screen; + struct dialog_color shadow; + struct dialog_color dialog; + struct dialog_color title; + struct dialog_color border; + struct dialog_color button_active; + struct dialog_color button_inactive; + struct dialog_color button_key_active; + struct dialog_color button_key_inactive; + struct dialog_color button_label_active; + struct dialog_color button_label_inactive; + struct dialog_color inputbox; + struct dialog_color inputbox_border; + struct dialog_color searchbox; + struct dialog_color searchbox_title; + struct dialog_color searchbox_border; + struct dialog_color position_indicator; + struct dialog_color menubox; + struct dialog_color menubox_border; + struct dialog_color item; + struct dialog_color item_selected; + struct dialog_color tag; + struct dialog_color tag_selected; + struct dialog_color tag_key; + struct dialog_color tag_key_selected; + struct dialog_color check; + struct dialog_color check_selected; + struct dialog_color uarrow; + struct dialog_color darrow; +}; + +/* + * Global variables + */ +extern struct dialog_info dlg; +extern char dialog_input_result[]; + +/* + * Function prototypes + */ + +/* item list as used by checklist and menubox */ +void item_reset(void); +void item_make(const char *fmt, ...); +void item_add_str(const char *fmt, ...); +void item_set_tag(char tag); +void item_set_data(void *p); +void item_set_selected(int val); +int item_activate_selected(void); +void *item_data(void); +char item_tag(void); + +/* item list manipulation for lxdialog use */ +#define MAXITEMSTR 200 +struct dialog_item { + char str[MAXITEMSTR]; /* promtp displayed */ + char tag; + void *data; /* pointer to menu item - used by menubox+checklist */ + int selected; /* Set to 1 by dialog_*() function if selected. */ +}; + +/* list of lialog_items */ +struct dialog_list { + struct dialog_item node; + struct dialog_list *next; +}; + +extern struct dialog_list *item_cur; +extern struct dialog_list item_nil; +extern struct dialog_list *item_head; + +int item_count(void); +void item_set(int n); +int item_n(void); +const char *item_str(void); +int item_is_selected(void); +int item_is_tag(char tag); +#define item_foreach() \ + for (item_cur = item_head ? item_head: item_cur; \ + item_cur && (item_cur != &item_nil); item_cur = item_cur->next) + +/* generic key handlers */ +int on_key_esc(WINDOW *win); +int on_key_resize(void); + +int init_dialog(const char *backtitle); +void set_dialog_backtitle(const char *backtitle); +void end_dialog(int x, int y); +void attr_clear(WINDOW * win, int height, int width, chtype attr); +void dialog_clear(void); +void print_autowrap(WINDOW * win, const char *prompt, int width, int y, int x); +void print_button(WINDOW * win, const char *label, int y, int x, int selected); +void print_title(WINDOW *dialog, const char *title, int width); +void draw_box(WINDOW * win, int y, int x, int height, int width, chtype box, + chtype border); +void draw_shadow(WINDOW * win, int y, int x, int height, int width); + +int first_alpha(const char *string, const char *exempt); +int dialog_yesno(const char *title, const char *prompt, int height, int width); +int dialog_msgbox(const char *title, const char *prompt, int height, + int width, int pause); +int dialog_textbox(const char *title, const char *file, int height, int width); +int dialog_menu(const char *title, const char *prompt, + const void *selected, int *s_scroll); +int dialog_checklist(const char *title, const char *prompt, int height, + int width, int list_height); +extern char dialog_input_result[]; +int dialog_inputbox(const char *title, const char *prompt, int height, + int width, const char *init); + +/* + * This is the base for fictitious keys, which activate + * the buttons. + * + * Mouse-generated keys are the following: + * -- the first 32 are used as numbers, in addition to '0'-'9' + * -- the lowercase are used to signal mouse-enter events (M_EVENT + 'o') + * -- uppercase chars are used to invoke the button (M_EVENT + 'O') + */ +#define M_EVENT (KEY_MAX+1) diff --git a/kernel/fiasco/tool/kconfig/scripts/kconfig/lxdialog/inputbox.c b/kernel/fiasco/tool/kconfig/scripts/kconfig/lxdialog/inputbox.c new file mode 100644 index 00000000..dd8e587c --- /dev/null +++ b/kernel/fiasco/tool/kconfig/scripts/kconfig/lxdialog/inputbox.c @@ -0,0 +1,238 @@ +/* + * inputbox.c -- implements the input box + * + * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) + * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "dialog.h" + +char dialog_input_result[MAX_LEN + 1]; + +/* + * Print the termination buttons + */ +static void print_buttons(WINDOW * dialog, int height, int width, int selected) +{ + int x = width / 2 - 11; + int y = height - 2; + + print_button(dialog, gettext(" Ok "), y, x, selected == 0); + print_button(dialog, gettext(" Help "), y, x + 14, selected == 1); + + wmove(dialog, y, x + 1 + 14 * selected); + wrefresh(dialog); +} + +/* + * Display a dialog box for inputing a string + */ +int dialog_inputbox(const char *title, const char *prompt, int height, int width, + const char *init) +{ + int i, x, y, box_y, box_x, box_width; + int input_x = 0, scroll = 0, key = 0, button = -1; + char *instr = dialog_input_result; + WINDOW *dialog; + + if (!init) + instr[0] = '\0'; + else + strcpy(instr, init); + +do_resize: + if (getmaxy(stdscr) <= (height - 2)) + return -ERRDISPLAYTOOSMALL; + if (getmaxx(stdscr) <= (width - 2)) + return -ERRDISPLAYTOOSMALL; + + /* center dialog box on screen */ + x = (COLS - width) / 2; + y = (LINES - height) / 2; + + draw_shadow(stdscr, y, x, height, width); + + dialog = newwin(height, width, y, x); + keypad(dialog, TRUE); + + draw_box(dialog, 0, 0, height, width, + dlg.dialog.atr, dlg.border.atr); + wattrset(dialog, dlg.border.atr); + mvwaddch(dialog, height - 3, 0, ACS_LTEE); + for (i = 0; i < width - 2; i++) + waddch(dialog, ACS_HLINE); + wattrset(dialog, dlg.dialog.atr); + waddch(dialog, ACS_RTEE); + + print_title(dialog, title, width); + + wattrset(dialog, dlg.dialog.atr); + print_autowrap(dialog, prompt, width - 2, 1, 3); + + /* Draw the input field box */ + box_width = width - 6; + getyx(dialog, y, x); + box_y = y + 2; + box_x = (width - box_width) / 2; + draw_box(dialog, y + 1, box_x - 1, 3, box_width + 2, + dlg.dialog.atr, dlg.border.atr); + + print_buttons(dialog, height, width, 0); + + /* Set up the initial value */ + wmove(dialog, box_y, box_x); + wattrset(dialog, dlg.inputbox.atr); + + input_x = strlen(instr); + + if (input_x >= box_width) { + scroll = input_x - box_width + 1; + input_x = box_width - 1; + for (i = 0; i < box_width - 1; i++) + waddch(dialog, instr[scroll + i]); + } else { + waddstr(dialog, instr); + } + + wmove(dialog, box_y, box_x + input_x); + + wrefresh(dialog); + + while (key != KEY_ESC) { + key = wgetch(dialog); + + if (button == -1) { /* Input box selected */ + switch (key) { + case TAB: + case KEY_UP: + case KEY_DOWN: + break; + case KEY_LEFT: + continue; + case KEY_RIGHT: + continue; + case KEY_BACKSPACE: + case 127: + if (input_x || scroll) { + wattrset(dialog, dlg.inputbox.atr); + if (!input_x) { + scroll = scroll < box_width - 1 ? 0 : scroll - (box_width - 1); + wmove(dialog, box_y, box_x); + for (i = 0; i < box_width; i++) + waddch(dialog, + instr[scroll + input_x + i] ? + instr[scroll + input_x + i] : ' '); + input_x = strlen(instr) - scroll; + } else + input_x--; + instr[scroll + input_x] = '\0'; + mvwaddch(dialog, box_y, input_x + box_x, ' '); + wmove(dialog, box_y, input_x + box_x); + wrefresh(dialog); + } + continue; + default: + if (key < 0x100 && isprint(key)) { + if (scroll + input_x < MAX_LEN) { + wattrset(dialog, dlg.inputbox.atr); + instr[scroll + input_x] = key; + instr[scroll + input_x + 1] = '\0'; + if (input_x == box_width - 1) { + scroll++; + wmove(dialog, box_y, box_x); + for (i = 0; i < box_width - 1; i++) + waddch(dialog, instr [scroll + i]); + } else { + wmove(dialog, box_y, input_x++ + box_x); + waddch(dialog, key); + } + wrefresh(dialog); + } else + flash(); /* Alarm user about overflow */ + continue; + } + } + } + switch (key) { + case 'O': + case 'o': + delwin(dialog); + return 0; + case 'H': + case 'h': + delwin(dialog); + return 1; + case KEY_UP: + case KEY_LEFT: + switch (button) { + case -1: + button = 1; /* Indicates "Help" button is selected */ + print_buttons(dialog, height, width, 1); + break; + case 0: + button = -1; /* Indicates input box is selected */ + print_buttons(dialog, height, width, 0); + wmove(dialog, box_y, box_x + input_x); + wrefresh(dialog); + break; + case 1: + button = 0; /* Indicates "OK" button is selected */ + print_buttons(dialog, height, width, 0); + break; + } + break; + case TAB: + case KEY_DOWN: + case KEY_RIGHT: + switch (button) { + case -1: + button = 0; /* Indicates "OK" button is selected */ + print_buttons(dialog, height, width, 0); + break; + case 0: + button = 1; /* Indicates "Help" button is selected */ + print_buttons(dialog, height, width, 1); + break; + case 1: + button = -1; /* Indicates input box is selected */ + print_buttons(dialog, height, width, 0); + wmove(dialog, box_y, box_x + input_x); + wrefresh(dialog); + break; + } + break; + case ' ': + case '\n': + delwin(dialog); + return (button == -1 ? 0 : button); + case 'X': + case 'x': + key = KEY_ESC; + break; + case KEY_ESC: + key = on_key_esc(dialog); + break; + case KEY_RESIZE: + delwin(dialog); + on_key_resize(); + goto do_resize; + } + } + + delwin(dialog); + return KEY_ESC; /* ESC pressed */ +} diff --git a/kernel/fiasco/tool/kconfig/scripts/kconfig/lxdialog/menubox.c b/kernel/fiasco/tool/kconfig/scripts/kconfig/lxdialog/menubox.c new file mode 100644 index 00000000..1d604738 --- /dev/null +++ b/kernel/fiasco/tool/kconfig/scripts/kconfig/lxdialog/menubox.c @@ -0,0 +1,434 @@ +/* + * menubox.c -- implements the menu box + * + * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) + * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcapw@cfw.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* + * Changes by Clifford Wolf (god@clifford.at) + * + * [ 1998-06-13 ] + * + * *) A bugfix for the Page-Down problem + * + * *) Formerly when I used Page Down and Page Up, the cursor would be set + * to the first position in the menu box. Now lxdialog is a bit + * smarter and works more like other menu systems (just have a look at + * it). + * + * *) Formerly if I selected something my scrolling would be broken because + * lxdialog is re-invoked by the Menuconfig shell script, can't + * remember the last scrolling position, and just sets it so that the + * cursor is at the bottom of the box. Now it writes the temporary file + * lxdialog.scrltmp which contains this information. The file is + * deleted by lxdialog if the user leaves a submenu or enters a new + * one, but it would be nice if Menuconfig could make another "rm -f" + * just to be sure. Just try it out - you will recognise a difference! + * + * [ 1998-06-14 ] + * + * *) Now lxdialog is crash-safe against broken "lxdialog.scrltmp" files + * and menus change their size on the fly. + * + * *) If for some reason the last scrolling position is not saved by + * lxdialog, it sets the scrolling so that the selected item is in the + * middle of the menu box, not at the bottom. + * + * 02 January 1999, Michael Elizabeth Chastain (mec@shout.net) + * Reset 'scroll' to 0 if the value from lxdialog.scrltmp is bogus. + * This fixes a bug in Menuconfig where using ' ' to descend into menus + * would leave mis-synchronized lxdialog.scrltmp files lying around, + * fscanf would read in 'scroll', and eventually that value would get used. + */ + +#include "dialog.h" + +static int menu_width, item_x; + +/* + * Print menu item + */ +static void do_print_item(WINDOW * win, const char *item, int line_y, + int selected, int hotkey) +{ + int j; + char *menu_item = malloc(menu_width + 1); + + strncpy(menu_item, item, menu_width - item_x); + menu_item[menu_width - item_x] = '\0'; + j = first_alpha(menu_item, "YyNnMmHh"); + + /* Clear 'residue' of last item */ + wattrset(win, dlg.menubox.atr); + wmove(win, line_y, 0); +#if OLD_NCURSES + { + int i; + for (i = 0; i < menu_width; i++) + waddch(win, ' '); + } +#else + wclrtoeol(win); +#endif + wattrset(win, selected ? dlg.item_selected.atr : dlg.item.atr); + mvwaddstr(win, line_y, item_x, menu_item); + if (hotkey) { + wattrset(win, selected ? dlg.tag_key_selected.atr + : dlg.tag_key.atr); + mvwaddch(win, line_y, item_x + j, menu_item[j]); + } + if (selected) { + wmove(win, line_y, item_x + 1); + } + free(menu_item); + wrefresh(win); +} + +#define print_item(index, choice, selected) \ +do { \ + item_set(index); \ + do_print_item(menu, item_str(), choice, selected, !item_is_tag(':')); \ +} while (0) + +/* + * Print the scroll indicators. + */ +static void print_arrows(WINDOW * win, int item_no, int scroll, int y, int x, + int height) +{ + int cur_y, cur_x; + + getyx(win, cur_y, cur_x); + + wmove(win, y, x); + + if (scroll > 0) { + wattrset(win, dlg.uarrow.atr); + waddch(win, ACS_UARROW); + waddstr(win, "(-)"); + } else { + wattrset(win, dlg.menubox.atr); + waddch(win, ACS_HLINE); + waddch(win, ACS_HLINE); + waddch(win, ACS_HLINE); + waddch(win, ACS_HLINE); + } + + y = y + height + 1; + wmove(win, y, x); + wrefresh(win); + + if ((height < item_no) && (scroll + height < item_no)) { + wattrset(win, dlg.darrow.atr); + waddch(win, ACS_DARROW); + waddstr(win, "(+)"); + } else { + wattrset(win, dlg.menubox_border.atr); + waddch(win, ACS_HLINE); + waddch(win, ACS_HLINE); + waddch(win, ACS_HLINE); + waddch(win, ACS_HLINE); + } + + wmove(win, cur_y, cur_x); + wrefresh(win); +} + +/* + * Display the termination buttons. + */ +static void print_buttons(WINDOW * win, int height, int width, int selected) +{ + int x = width / 2 - 16; + int y = height - 2; + + print_button(win, gettext("Select"), y, x, selected == 0); + print_button(win, gettext(" Exit "), y, x + 12, selected == 1); + print_button(win, gettext(" Help "), y, x + 24, selected == 2); + + wmove(win, y, x + 1 + 12 * selected); + wrefresh(win); +} + +/* scroll up n lines (n may be negative) */ +static void do_scroll(WINDOW *win, int *scroll, int n) +{ + /* Scroll menu up */ + scrollok(win, TRUE); + wscrl(win, n); + scrollok(win, FALSE); + *scroll = *scroll + n; + wrefresh(win); +} + +/* + * Display a menu for choosing among a number of options + */ +int dialog_menu(const char *title, const char *prompt, + const void *selected, int *s_scroll) +{ + int i, j, x, y, box_x, box_y; + int height, width, menu_height; + int key = 0, button = 0, scroll = 0, choice = 0; + int first_item = 0, max_choice; + WINDOW *dialog, *menu; + +do_resize: + height = getmaxy(stdscr); + width = getmaxx(stdscr); + if (height < 15 || width < 65) + return -ERRDISPLAYTOOSMALL; + + height -= 4; + width -= 5; + menu_height = height - 10; + + max_choice = MIN(menu_height, item_count()); + + /* center dialog box on screen */ + x = (COLS - width) / 2; + y = (LINES - height) / 2; + + draw_shadow(stdscr, y, x, height, width); + + dialog = newwin(height, width, y, x); + keypad(dialog, TRUE); + + draw_box(dialog, 0, 0, height, width, + dlg.dialog.atr, dlg.border.atr); + wattrset(dialog, dlg.border.atr); + mvwaddch(dialog, height - 3, 0, ACS_LTEE); + for (i = 0; i < width - 2; i++) + waddch(dialog, ACS_HLINE); + wattrset(dialog, dlg.dialog.atr); + wbkgdset(dialog, dlg.dialog.atr & A_COLOR); + waddch(dialog, ACS_RTEE); + + print_title(dialog, title, width); + + wattrset(dialog, dlg.dialog.atr); + print_autowrap(dialog, prompt, width - 2, 1, 3); + + menu_width = width - 6; + box_y = height - menu_height - 5; + box_x = (width - menu_width) / 2 - 1; + + /* create new window for the menu */ + menu = subwin(dialog, menu_height, menu_width, + y + box_y + 1, x + box_x + 1); + keypad(menu, TRUE); + + /* draw a box around the menu items */ + draw_box(dialog, box_y, box_x, menu_height + 2, menu_width + 2, + dlg.menubox_border.atr, dlg.menubox.atr); + + if (menu_width >= 80) + item_x = (menu_width - 70) / 2; + else + item_x = 4; + + /* Set choice to default item */ + item_foreach() + if (selected && (selected == item_data())) + choice = item_n(); + /* get the saved scroll info */ + scroll = *s_scroll; + if ((scroll <= choice) && (scroll + max_choice > choice) && + (scroll >= 0) && (scroll + max_choice <= item_count())) { + first_item = scroll; + choice = choice - scroll; + } else { + scroll = 0; + } + if ((choice >= max_choice)) { + if (choice >= item_count() - max_choice / 2) + scroll = first_item = item_count() - max_choice; + else + scroll = first_item = choice - max_choice / 2; + choice = choice - scroll; + } + + /* Print the menu */ + for (i = 0; i < max_choice; i++) { + print_item(first_item + i, i, i == choice); + } + + wnoutrefresh(menu); + + print_arrows(dialog, item_count(), scroll, + box_y, box_x + item_x + 1, menu_height); + + print_buttons(dialog, height, width, 0); + wmove(menu, choice, item_x + 1); + wrefresh(menu); + + while (key != KEY_ESC) { + key = wgetch(menu); + + if (key < 256 && isalpha(key)) + key = tolower(key); + + if (strchr("ynmh", key)) + i = max_choice; + else { + for (i = choice + 1; i < max_choice; i++) { + item_set(scroll + i); + j = first_alpha(item_str(), "YyNnMmHh"); + if (key == tolower(item_str()[j])) + break; + } + if (i == max_choice) + for (i = 0; i < max_choice; i++) { + item_set(scroll + i); + j = first_alpha(item_str(), "YyNnMmHh"); + if (key == tolower(item_str()[j])) + break; + } + } + + if (i < max_choice || + key == KEY_UP || key == KEY_DOWN || + key == '-' || key == '+' || + key == KEY_PPAGE || key == KEY_NPAGE) { + /* Remove highligt of current item */ + print_item(scroll + choice, choice, FALSE); + + if (key == KEY_UP || key == '-') { + if (choice < 2 && scroll) { + /* Scroll menu down */ + do_scroll(menu, &scroll, -1); + + print_item(scroll, 0, FALSE); + } else + choice = MAX(choice - 1, 0); + + } else if (key == KEY_DOWN || key == '+') { + print_item(scroll+choice, choice, FALSE); + + if ((choice > max_choice - 3) && + (scroll + max_choice < item_count())) { + /* Scroll menu up */ + do_scroll(menu, &scroll, 1); + + print_item(scroll+max_choice - 1, + max_choice - 1, FALSE); + } else + choice = MIN(choice + 1, max_choice - 1); + + } else if (key == KEY_PPAGE) { + scrollok(menu, TRUE); + for (i = 0; (i < max_choice); i++) { + if (scroll > 0) { + do_scroll(menu, &scroll, -1); + print_item(scroll, 0, FALSE); + } else { + if (choice > 0) + choice--; + } + } + + } else if (key == KEY_NPAGE) { + for (i = 0; (i < max_choice); i++) { + if (scroll + max_choice < item_count()) { + do_scroll(menu, &scroll, 1); + print_item(scroll+max_choice-1, + max_choice - 1, FALSE); + } else { + if (choice + 1 < max_choice) + choice++; + } + } + } else + choice = i; + + print_item(scroll + choice, choice, TRUE); + + print_arrows(dialog, item_count(), scroll, + box_y, box_x + item_x + 1, menu_height); + + wnoutrefresh(dialog); + wrefresh(menu); + + continue; /* wait for another key press */ + } + + switch (key) { + case KEY_LEFT: + case TAB: + case KEY_RIGHT: + button = ((key == KEY_LEFT ? --button : ++button) < 0) + ? 2 : (button > 2 ? 0 : button); + + print_buttons(dialog, height, width, button); + wrefresh(menu); + break; + case ' ': + case 's': + case 'y': + case 'n': + case 'm': + case '/': + case 'h': + case '?': + case 'z': + case '\n': + /* save scroll info */ + *s_scroll = scroll; + delwin(menu); + delwin(dialog); + item_set(scroll + choice); + item_set_selected(1); + switch (key) { + case 'h': + case '?': + return 2; + case 's': + case 'y': + return 3; + case 'n': + return 4; + case 'm': + return 5; + case ' ': + return 6; + case '/': + return 7; + case 'z': + return 8; + case '\n': + return button; + } + return 0; + case 'e': + case 'x': + key = KEY_ESC; + break; + case KEY_ESC: + key = on_key_esc(menu); + break; + case KEY_RESIZE: + on_key_resize(); + delwin(menu); + delwin(dialog); + goto do_resize; + } + } + delwin(menu); + delwin(dialog); + return key; /* ESC pressed */ +} diff --git a/kernel/fiasco/tool/kconfig/scripts/kconfig/lxdialog/textbox.c b/kernel/fiasco/tool/kconfig/scripts/kconfig/lxdialog/textbox.c new file mode 100644 index 00000000..154c2dd2 --- /dev/null +++ b/kernel/fiasco/tool/kconfig/scripts/kconfig/lxdialog/textbox.c @@ -0,0 +1,390 @@ +/* + * textbox.c -- implements the text box + * + * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) + * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "dialog.h" + +static void back_lines(int n); +static void print_page(WINDOW * win, int height, int width); +static void print_line(WINDOW * win, int row, int width); +static char *get_line(void); +static void print_position(WINDOW * win); + +static int hscroll; +static int begin_reached, end_reached, page_length; +static const char *buf; +static const char *page; + +/* + * refresh window content + */ +static void refresh_text_box(WINDOW *dialog, WINDOW *box, int boxh, int boxw, + int cur_y, int cur_x) +{ + print_page(box, boxh, boxw); + print_position(dialog); + wmove(dialog, cur_y, cur_x); /* Restore cursor position */ + wrefresh(dialog); +} + + +/* + * Display text from a file in a dialog box. + */ +int dialog_textbox(const char *title, const char *tbuf, + int initial_height, int initial_width) +{ + int i, x, y, cur_x, cur_y, key = 0; + int height, width, boxh, boxw; + int passed_end; + WINDOW *dialog, *box; + + begin_reached = 1; + end_reached = 0; + page_length = 0; + hscroll = 0; + buf = tbuf; + page = buf; /* page is pointer to start of page to be displayed */ + +do_resize: + getmaxyx(stdscr, height, width); + if (height < 8 || width < 8) + return -ERRDISPLAYTOOSMALL; + if (initial_height != 0) + height = initial_height; + else + if (height > 4) + height -= 4; + else + height = 0; + if (initial_width != 0) + width = initial_width; + else + if (width > 5) + width -= 5; + else + width = 0; + + /* center dialog box on screen */ + x = (COLS - width) / 2; + y = (LINES - height) / 2; + + draw_shadow(stdscr, y, x, height, width); + + dialog = newwin(height, width, y, x); + keypad(dialog, TRUE); + + /* Create window for box region, used for scrolling text */ + boxh = height - 4; + boxw = width - 2; + box = subwin(dialog, boxh, boxw, y + 1, x + 1); + wattrset(box, dlg.dialog.atr); + wbkgdset(box, dlg.dialog.atr & A_COLOR); + + keypad(box, TRUE); + + /* register the new window, along with its borders */ + draw_box(dialog, 0, 0, height, width, + dlg.dialog.atr, dlg.border.atr); + + wattrset(dialog, dlg.border.atr); + mvwaddch(dialog, height - 3, 0, ACS_LTEE); + for (i = 0; i < width - 2; i++) + waddch(dialog, ACS_HLINE); + wattrset(dialog, dlg.dialog.atr); + wbkgdset(dialog, dlg.dialog.atr & A_COLOR); + waddch(dialog, ACS_RTEE); + + print_title(dialog, title, width); + + print_button(dialog, gettext(" Exit "), height - 2, width / 2 - 4, TRUE); + wnoutrefresh(dialog); + getyx(dialog, cur_y, cur_x); /* Save cursor position */ + + /* Print first page of text */ + attr_clear(box, boxh, boxw, dlg.dialog.atr); + refresh_text_box(dialog, box, boxh, boxw, cur_y, cur_x); + + while ((key != KEY_ESC) && (key != '\n')) { + key = wgetch(dialog); + switch (key) { + case 'E': /* Exit */ + case 'e': + case 'X': + case 'x': + delwin(box); + delwin(dialog); + return 0; + case 'g': /* First page */ + case KEY_HOME: + if (!begin_reached) { + begin_reached = 1; + page = buf; + refresh_text_box(dialog, box, boxh, boxw, + cur_y, cur_x); + } + break; + case 'G': /* Last page */ + case KEY_END: + + end_reached = 1; + /* point to last char in buf */ + page = buf + strlen(buf); + back_lines(boxh); + refresh_text_box(dialog, box, boxh, boxw, + cur_y, cur_x); + break; + case 'K': /* Previous line */ + case 'k': + case KEY_UP: + if (!begin_reached) { + back_lines(page_length + 1); + + /* We don't call print_page() here but use + * scrolling to ensure faster screen update. + * However, 'end_reached' and 'page_length' + * should still be updated, and 'page' should + * point to start of next page. This is done + * by calling get_line() in the following + * 'for' loop. */ + scrollok(box, TRUE); + wscrl(box, -1); /* Scroll box region down one line */ + scrollok(box, FALSE); + page_length = 0; + passed_end = 0; + for (i = 0; i < boxh; i++) { + if (!i) { + /* print first line of page */ + print_line(box, 0, boxw); + wnoutrefresh(box); + } else + /* Called to update 'end_reached' and 'page' */ + get_line(); + if (!passed_end) + page_length++; + if (end_reached && !passed_end) + passed_end = 1; + } + + print_position(dialog); + wmove(dialog, cur_y, cur_x); /* Restore cursor position */ + wrefresh(dialog); + } + break; + case 'B': /* Previous page */ + case 'b': + case KEY_PPAGE: + if (begin_reached) + break; + back_lines(page_length + boxh); + refresh_text_box(dialog, box, boxh, boxw, + cur_y, cur_x); + break; + case 'J': /* Next line */ + case 'j': + case KEY_DOWN: + if (!end_reached) { + begin_reached = 0; + scrollok(box, TRUE); + scroll(box); /* Scroll box region up one line */ + scrollok(box, FALSE); + print_line(box, boxh - 1, boxw); + wnoutrefresh(box); + print_position(dialog); + wmove(dialog, cur_y, cur_x); /* Restore cursor position */ + wrefresh(dialog); + } + break; + case KEY_NPAGE: /* Next page */ + case ' ': + if (end_reached) + break; + + begin_reached = 0; + refresh_text_box(dialog, box, boxh, boxw, + cur_y, cur_x); + break; + case '0': /* Beginning of line */ + case 'H': /* Scroll left */ + case 'h': + case KEY_LEFT: + if (hscroll <= 0) + break; + + if (key == '0') + hscroll = 0; + else + hscroll--; + /* Reprint current page to scroll horizontally */ + back_lines(page_length); + refresh_text_box(dialog, box, boxh, boxw, + cur_y, cur_x); + break; + case 'L': /* Scroll right */ + case 'l': + case KEY_RIGHT: + if (hscroll >= MAX_LEN) + break; + hscroll++; + /* Reprint current page to scroll horizontally */ + back_lines(page_length); + refresh_text_box(dialog, box, boxh, boxw, + cur_y, cur_x); + break; + case KEY_ESC: + key = on_key_esc(dialog); + break; + case KEY_RESIZE: + back_lines(height); + delwin(box); + delwin(dialog); + on_key_resize(); + goto do_resize; + } + } + delwin(box); + delwin(dialog); + return key; /* ESC pressed */ +} + +/* + * Go back 'n' lines in text. Called by dialog_textbox(). + * 'page' will be updated to point to the desired line in 'buf'. + */ +static void back_lines(int n) +{ + int i; + + begin_reached = 0; + /* Go back 'n' lines */ + for (i = 0; i < n; i++) { + if (*page == '\0') { + if (end_reached) { + end_reached = 0; + continue; + } + } + if (page == buf) { + begin_reached = 1; + return; + } + page--; + do { + if (page == buf) { + begin_reached = 1; + return; + } + page--; + } while (*page != '\n'); + page++; + } +} + +/* + * Print a new page of text. Called by dialog_textbox(). + */ +static void print_page(WINDOW * win, int height, int width) +{ + int i, passed_end = 0; + + page_length = 0; + for (i = 0; i < height; i++) { + print_line(win, i, width); + if (!passed_end) + page_length++; + if (end_reached && !passed_end) + passed_end = 1; + } + wnoutrefresh(win); +} + +/* + * Print a new line of text. Called by dialog_textbox() and print_page(). + */ +static void print_line(WINDOW * win, int row, int width) +{ + char *line; + + line = get_line(); + line += MIN(strlen(line), hscroll); /* Scroll horizontally */ + wmove(win, row, 0); /* move cursor to correct line */ + waddch(win, ' '); + waddnstr(win, line, MIN(strlen(line), width - 2)); + + /* Clear 'residue' of previous line */ +#if OLD_NCURSES + { + int x = getcurx(win); + int i; + for (i = 0; i < width - x; i++) + waddch(win, ' '); + } +#else + wclrtoeol(win); +#endif +} + +/* + * Return current line of text. Called by dialog_textbox() and print_line(). + * 'page' should point to start of current line before calling, and will be + * updated to point to start of next line. + */ +static char *get_line(void) +{ + int i = 0; + static char line[MAX_LEN + 1]; + + end_reached = 0; + while (*page != '\n') { + if (*page == '\0') { + if (!end_reached) { + end_reached = 1; + break; + } + } else if (i < MAX_LEN) + line[i++] = *(page++); + else { + /* Truncate lines longer than MAX_LEN characters */ + if (i == MAX_LEN) + line[i++] = '\0'; + page++; + } + } + if (i <= MAX_LEN) + line[i] = '\0'; + if (!end_reached) + page++; /* move pass '\n' */ + + return line; +} + +/* + * Print current position + */ +static void print_position(WINDOW * win) +{ + int percent; + + wattrset(win, dlg.position_indicator.atr); + wbkgdset(win, dlg.position_indicator.atr & A_COLOR); + percent = (page - buf) * 100 / strlen(buf); + wmove(win, getmaxy(win) - 3, getmaxx(win) - 9); + wprintw(win, "(%3d%%)", percent); +} diff --git a/kernel/fiasco/tool/kconfig/scripts/kconfig/lxdialog/util.c b/kernel/fiasco/tool/kconfig/scripts/kconfig/lxdialog/util.c new file mode 100644 index 00000000..f2375ad7 --- /dev/null +++ b/kernel/fiasco/tool/kconfig/scripts/kconfig/lxdialog/util.c @@ -0,0 +1,657 @@ +/* + * util.c + * + * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) + * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include + +#include "dialog.h" + +struct dialog_info dlg; + +static void set_mono_theme(void) +{ + dlg.screen.atr = A_NORMAL; + dlg.shadow.atr = A_NORMAL; + dlg.dialog.atr = A_NORMAL; + dlg.title.atr = A_BOLD; + dlg.border.atr = A_NORMAL; + dlg.button_active.atr = A_REVERSE; + dlg.button_inactive.atr = A_DIM; + dlg.button_key_active.atr = A_REVERSE; + dlg.button_key_inactive.atr = A_BOLD; + dlg.button_label_active.atr = A_REVERSE; + dlg.button_label_inactive.atr = A_NORMAL; + dlg.inputbox.atr = A_NORMAL; + dlg.inputbox_border.atr = A_NORMAL; + dlg.searchbox.atr = A_NORMAL; + dlg.searchbox_title.atr = A_BOLD; + dlg.searchbox_border.atr = A_NORMAL; + dlg.position_indicator.atr = A_BOLD; + dlg.menubox.atr = A_NORMAL; + dlg.menubox_border.atr = A_NORMAL; + dlg.item.atr = A_NORMAL; + dlg.item_selected.atr = A_REVERSE; + dlg.tag.atr = A_BOLD; + dlg.tag_selected.atr = A_REVERSE; + dlg.tag_key.atr = A_BOLD; + dlg.tag_key_selected.atr = A_REVERSE; + dlg.check.atr = A_BOLD; + dlg.check_selected.atr = A_REVERSE; + dlg.uarrow.atr = A_BOLD; + dlg.darrow.atr = A_BOLD; +} + +#define DLG_COLOR(dialog, f, b, h) \ +do { \ + dlg.dialog.fg = (f); \ + dlg.dialog.bg = (b); \ + dlg.dialog.hl = (h); \ +} while (0) + +static void set_classic_theme(void) +{ + DLG_COLOR(screen, COLOR_CYAN, COLOR_BLUE, true); + DLG_COLOR(shadow, COLOR_BLACK, COLOR_BLACK, true); + DLG_COLOR(dialog, COLOR_BLACK, COLOR_WHITE, false); + DLG_COLOR(title, COLOR_YELLOW, COLOR_WHITE, true); + DLG_COLOR(border, COLOR_WHITE, COLOR_WHITE, true); + DLG_COLOR(button_active, COLOR_WHITE, COLOR_BLUE, true); + DLG_COLOR(button_inactive, COLOR_BLACK, COLOR_WHITE, false); + DLG_COLOR(button_key_active, COLOR_WHITE, COLOR_BLUE, true); + DLG_COLOR(button_key_inactive, COLOR_RED, COLOR_WHITE, false); + DLG_COLOR(button_label_active, COLOR_YELLOW, COLOR_BLUE, true); + DLG_COLOR(button_label_inactive, COLOR_BLACK, COLOR_WHITE, true); + DLG_COLOR(inputbox, COLOR_BLACK, COLOR_WHITE, false); + DLG_COLOR(inputbox_border, COLOR_BLACK, COLOR_WHITE, false); + DLG_COLOR(searchbox, COLOR_BLACK, COLOR_WHITE, false); + DLG_COLOR(searchbox_title, COLOR_YELLOW, COLOR_WHITE, true); + DLG_COLOR(searchbox_border, COLOR_WHITE, COLOR_WHITE, true); + DLG_COLOR(position_indicator, COLOR_YELLOW, COLOR_WHITE, true); + DLG_COLOR(menubox, COLOR_BLACK, COLOR_WHITE, false); + DLG_COLOR(menubox_border, COLOR_WHITE, COLOR_WHITE, true); + DLG_COLOR(item, COLOR_BLACK, COLOR_WHITE, false); + DLG_COLOR(item_selected, COLOR_WHITE, COLOR_BLUE, true); + DLG_COLOR(tag, COLOR_YELLOW, COLOR_WHITE, true); + DLG_COLOR(tag_selected, COLOR_YELLOW, COLOR_BLUE, true); + DLG_COLOR(tag_key, COLOR_YELLOW, COLOR_WHITE, true); + DLG_COLOR(tag_key_selected, COLOR_YELLOW, COLOR_BLUE, true); + DLG_COLOR(check, COLOR_BLACK, COLOR_WHITE, false); + DLG_COLOR(check_selected, COLOR_WHITE, COLOR_BLUE, true); + DLG_COLOR(uarrow, COLOR_GREEN, COLOR_WHITE, true); + DLG_COLOR(darrow, COLOR_GREEN, COLOR_WHITE, true); +} + +static void set_blackbg_theme(void) +{ + DLG_COLOR(screen, COLOR_RED, COLOR_BLACK, true); + DLG_COLOR(shadow, COLOR_BLACK, COLOR_BLACK, false); + DLG_COLOR(dialog, COLOR_WHITE, COLOR_BLACK, false); + DLG_COLOR(title, COLOR_RED, COLOR_BLACK, false); + DLG_COLOR(border, COLOR_BLACK, COLOR_BLACK, true); + + DLG_COLOR(button_active, COLOR_YELLOW, COLOR_RED, false); + DLG_COLOR(button_inactive, COLOR_YELLOW, COLOR_BLACK, false); + DLG_COLOR(button_key_active, COLOR_YELLOW, COLOR_RED, true); + DLG_COLOR(button_key_inactive, COLOR_RED, COLOR_BLACK, false); + DLG_COLOR(button_label_active, COLOR_WHITE, COLOR_RED, false); + DLG_COLOR(button_label_inactive, COLOR_BLACK, COLOR_BLACK, true); + + DLG_COLOR(inputbox, COLOR_YELLOW, COLOR_BLACK, false); + DLG_COLOR(inputbox_border, COLOR_YELLOW, COLOR_BLACK, false); + + DLG_COLOR(searchbox, COLOR_YELLOW, COLOR_BLACK, false); + DLG_COLOR(searchbox_title, COLOR_YELLOW, COLOR_BLACK, true); + DLG_COLOR(searchbox_border, COLOR_BLACK, COLOR_BLACK, true); + + DLG_COLOR(position_indicator, COLOR_RED, COLOR_BLACK, false); + + DLG_COLOR(menubox, COLOR_YELLOW, COLOR_BLACK, false); + DLG_COLOR(menubox_border, COLOR_BLACK, COLOR_BLACK, true); + + DLG_COLOR(item, COLOR_WHITE, COLOR_BLACK, false); + DLG_COLOR(item_selected, COLOR_WHITE, COLOR_RED, false); + + DLG_COLOR(tag, COLOR_RED, COLOR_BLACK, false); + DLG_COLOR(tag_selected, COLOR_YELLOW, COLOR_RED, true); + DLG_COLOR(tag_key, COLOR_RED, COLOR_BLACK, false); + DLG_COLOR(tag_key_selected, COLOR_YELLOW, COLOR_RED, true); + + DLG_COLOR(check, COLOR_YELLOW, COLOR_BLACK, false); + DLG_COLOR(check_selected, COLOR_YELLOW, COLOR_RED, true); + + DLG_COLOR(uarrow, COLOR_RED, COLOR_BLACK, false); + DLG_COLOR(darrow, COLOR_RED, COLOR_BLACK, false); +} + +static void set_bluetitle_theme(void) +{ + set_classic_theme(); + DLG_COLOR(title, COLOR_BLUE, COLOR_WHITE, true); + DLG_COLOR(button_key_active, COLOR_YELLOW, COLOR_BLUE, true); + DLG_COLOR(button_label_active, COLOR_WHITE, COLOR_BLUE, true); + DLG_COLOR(searchbox_title, COLOR_BLUE, COLOR_WHITE, true); + DLG_COLOR(position_indicator, COLOR_BLUE, COLOR_WHITE, true); + DLG_COLOR(tag, COLOR_BLUE, COLOR_WHITE, true); + DLG_COLOR(tag_key, COLOR_BLUE, COLOR_WHITE, true); + +} + +/* + * Select color theme + */ +static int set_theme(const char *theme) +{ + int use_color = 1; + if (!theme) + set_bluetitle_theme(); + else if (strcmp(theme, "classic") == 0) + set_classic_theme(); + else if (strcmp(theme, "bluetitle") == 0) + set_bluetitle_theme(); + else if (strcmp(theme, "blackbg") == 0) + set_blackbg_theme(); + else if (strcmp(theme, "mono") == 0) + use_color = 0; + + return use_color; +} + +static void init_one_color(struct dialog_color *color) +{ + static int pair = 0; + + pair++; + init_pair(pair, color->fg, color->bg); + if (color->hl) + color->atr = A_BOLD | COLOR_PAIR(pair); + else + color->atr = COLOR_PAIR(pair); +} + +static void init_dialog_colors(void) +{ + init_one_color(&dlg.screen); + init_one_color(&dlg.shadow); + init_one_color(&dlg.dialog); + init_one_color(&dlg.title); + init_one_color(&dlg.border); + init_one_color(&dlg.button_active); + init_one_color(&dlg.button_inactive); + init_one_color(&dlg.button_key_active); + init_one_color(&dlg.button_key_inactive); + init_one_color(&dlg.button_label_active); + init_one_color(&dlg.button_label_inactive); + init_one_color(&dlg.inputbox); + init_one_color(&dlg.inputbox_border); + init_one_color(&dlg.searchbox); + init_one_color(&dlg.searchbox_title); + init_one_color(&dlg.searchbox_border); + init_one_color(&dlg.position_indicator); + init_one_color(&dlg.menubox); + init_one_color(&dlg.menubox_border); + init_one_color(&dlg.item); + init_one_color(&dlg.item_selected); + init_one_color(&dlg.tag); + init_one_color(&dlg.tag_selected); + init_one_color(&dlg.tag_key); + init_one_color(&dlg.tag_key_selected); + init_one_color(&dlg.check); + init_one_color(&dlg.check_selected); + init_one_color(&dlg.uarrow); + init_one_color(&dlg.darrow); +} + +/* + * Setup for color display + */ +static void color_setup(const char *theme) +{ + int use_color; + + use_color = set_theme(theme); + if (use_color && has_colors()) { + start_color(); + init_dialog_colors(); + } else + set_mono_theme(); +} + +/* + * Set window to attribute 'attr' + */ +void attr_clear(WINDOW * win, int height, int width, chtype attr) +{ + int i, j; + + wattrset(win, attr); + for (i = 0; i < height; i++) { + wmove(win, i, 0); + for (j = 0; j < width; j++) + waddch(win, ' '); + } + touchwin(win); +} + +void dialog_clear(void) +{ + attr_clear(stdscr, LINES, COLS, dlg.screen.atr); + /* Display background title if it exists ... - SLH */ + if (dlg.backtitle != NULL) { + int i; + + wattrset(stdscr, dlg.screen.atr); + mvwaddstr(stdscr, 0, 1, (char *)dlg.backtitle); + wmove(stdscr, 1, 1); + for (i = 1; i < COLS - 1; i++) + waddch(stdscr, ACS_HLINE); + } + wnoutrefresh(stdscr); +} + +/* + * Do some initialization for dialog + */ +int init_dialog(const char *backtitle) +{ + int height, width; + + initscr(); /* Init curses */ + getmaxyx(stdscr, height, width); + if (height < 19 || width < 80) { + endwin(); + return -ERRDISPLAYTOOSMALL; + } + + dlg.backtitle = backtitle; + color_setup(getenv("MENUCONFIG_COLOR")); + + keypad(stdscr, TRUE); + cbreak(); + noecho(); + dialog_clear(); + + return 0; +} + +void set_dialog_backtitle(const char *backtitle) +{ + dlg.backtitle = backtitle; +} + +/* + * End using dialog functions. + */ +void end_dialog(int x, int y) +{ + /* move cursor back to original position */ + move(y, x); + refresh(); + endwin(); +} + +/* Print the title of the dialog. Center the title and truncate + * tile if wider than dialog (- 2 chars). + **/ +void print_title(WINDOW *dialog, const char *title, int width) +{ + if (title) { + int tlen = MIN(width - 2, strlen(title)); + wattrset(dialog, dlg.title.atr); + mvwaddch(dialog, 0, (width - tlen) / 2 - 1, ' '); + mvwaddnstr(dialog, 0, (width - tlen)/2, title, tlen); + waddch(dialog, ' '); + } +} + +/* + * Print a string of text in a window, automatically wrap around to the + * next line if the string is too long to fit on one line. Newline + * characters '\n' are replaced by spaces. We start on a new line + * if there is no room for at least 4 nonblanks following a double-space. + */ +void print_autowrap(WINDOW * win, const char *prompt, int width, int y, int x) +{ + int newl, cur_x, cur_y; + int i, prompt_len, room, wlen; + char tempstr[MAX_LEN + 1], *word, *sp, *sp2; + + strcpy(tempstr, prompt); + + prompt_len = strlen(tempstr); + + /* + * Remove newlines + */ + for (i = 0; i < prompt_len; i++) { + if (tempstr[i] == '\n') + tempstr[i] = ' '; + } + + if (prompt_len <= width - x * 2) { /* If prompt is short */ + wmove(win, y, (width - prompt_len) / 2); + waddstr(win, tempstr); + } else { + cur_x = x; + cur_y = y; + newl = 1; + word = tempstr; + while (word && *word) { + sp = strchr(word, ' '); + if (sp) + *sp++ = 0; + + /* Wrap to next line if either the word does not fit, + or it is the first word of a new sentence, and it is + short, and the next word does not fit. */ + room = width - cur_x; + wlen = strlen(word); + if (wlen > room || + (newl && wlen < 4 && sp + && wlen + 1 + strlen(sp) > room + && (!(sp2 = strchr(sp, ' ')) + || wlen + 1 + (sp2 - sp) > room))) { + cur_y++; + cur_x = x; + } + wmove(win, cur_y, cur_x); + waddstr(win, word); + getyx(win, cur_y, cur_x); + cur_x++; + if (sp && *sp == ' ') { + cur_x++; /* double space */ + while (*++sp == ' ') ; + newl = 1; + } else + newl = 0; + word = sp; + } + } +} + +/* + * Print a button + */ +void print_button(WINDOW * win, const char *label, int y, int x, int selected) +{ + int i, temp; + + wmove(win, y, x); + wattrset(win, selected ? dlg.button_active.atr + : dlg.button_inactive.atr); + waddstr(win, "<"); + temp = strspn(label, " "); + label += temp; + wattrset(win, selected ? dlg.button_label_active.atr + : dlg.button_label_inactive.atr); + for (i = 0; i < temp; i++) + waddch(win, ' '); + wattrset(win, selected ? dlg.button_key_active.atr + : dlg.button_key_inactive.atr); + waddch(win, label[0]); + wattrset(win, selected ? dlg.button_label_active.atr + : dlg.button_label_inactive.atr); + waddstr(win, (char *)label + 1); + wattrset(win, selected ? dlg.button_active.atr + : dlg.button_inactive.atr); + waddstr(win, ">"); + wmove(win, y, x + temp + 1); +} + +/* + * Draw a rectangular box with line drawing characters + */ +void +draw_box(WINDOW * win, int y, int x, int height, int width, + chtype box, chtype border) +{ + int i, j; + + wattrset(win, 0); + for (i = 0; i < height; i++) { + wmove(win, y + i, x); + for (j = 0; j < width; j++) + if (!i && !j) + waddch(win, border | ACS_ULCORNER); + else if (i == height - 1 && !j) + waddch(win, border | ACS_LLCORNER); + else if (!i && j == width - 1) + waddch(win, box | ACS_URCORNER); + else if (i == height - 1 && j == width - 1) + waddch(win, box | ACS_LRCORNER); + else if (!i) + waddch(win, border | ACS_HLINE); + else if (i == height - 1) + waddch(win, box | ACS_HLINE); + else if (!j) + waddch(win, border | ACS_VLINE); + else if (j == width - 1) + waddch(win, box | ACS_VLINE); + else + waddch(win, box | ' '); + } +} + +/* + * Draw shadows along the right and bottom edge to give a more 3D look + * to the boxes + */ +void draw_shadow(WINDOW * win, int y, int x, int height, int width) +{ + int i; + + if (has_colors()) { /* Whether terminal supports color? */ + wattrset(win, dlg.shadow.atr); + wmove(win, y + height, x + 2); + for (i = 0; i < width; i++) + waddch(win, winch(win) & A_CHARTEXT); + for (i = y + 1; i < y + height + 1; i++) { + wmove(win, i, x + width); + waddch(win, winch(win) & A_CHARTEXT); + waddch(win, winch(win) & A_CHARTEXT); + } + wnoutrefresh(win); + } +} + +/* + * Return the position of the first alphabetic character in a string. + */ +int first_alpha(const char *string, const char *exempt) +{ + int i, in_paren = 0, c; + + for (i = 0; i < strlen(string); i++) { + c = tolower(string[i]); + + if (strchr("<[(", c)) + ++in_paren; + if (strchr(">])", c) && in_paren > 0) + --in_paren; + + if ((!in_paren) && isalpha(c) && strchr(exempt, c) == 0) + return i; + } + + return 0; +} + +/* + * ncurses uses ESC to detect escaped char sequences. This resutl in + * a small timeout before ESC is actually delivered to the application. + * lxdialog suggest which is correctly translated to two + * times esc. But then we need to ignore the second esc to avoid stepping + * out one menu too much. Filter away all escaped key sequences since + * keypad(FALSE) turn off ncurses support for escape sequences - and thats + * needed to make notimeout() do as expected. + */ +int on_key_esc(WINDOW *win) +{ + int key; + int key2; + int key3; + + nodelay(win, TRUE); + keypad(win, FALSE); + key = wgetch(win); + key2 = wgetch(win); + do { + key3 = wgetch(win); + } while (key3 != ERR); + nodelay(win, FALSE); + keypad(win, TRUE); + if (key == KEY_ESC && key2 == ERR) + return KEY_ESC; + else if (key != ERR && key != KEY_ESC && key2 == ERR) + ungetch(key); + + return -1; +} + +/* redraw screen in new size */ +int on_key_resize(void) +{ + dialog_clear(); + return KEY_RESIZE; +} + +struct dialog_list *item_cur; +struct dialog_list item_nil; +struct dialog_list *item_head; + +void item_reset(void) +{ + struct dialog_list *p, *next; + + for (p = item_head; p; p = next) { + next = p->next; + free(p); + } + item_head = NULL; + item_cur = &item_nil; +} + +void item_make(const char *fmt, ...) +{ + va_list ap; + struct dialog_list *p = malloc(sizeof(*p)); + + if (item_head) + item_cur->next = p; + else + item_head = p; + item_cur = p; + memset(p, 0, sizeof(*p)); + + va_start(ap, fmt); + vsnprintf(item_cur->node.str, sizeof(item_cur->node.str), fmt, ap); + va_end(ap); +} + +void item_add_str(const char *fmt, ...) +{ + va_list ap; + size_t avail; + + avail = sizeof(item_cur->node.str) - strlen(item_cur->node.str); + + va_start(ap, fmt); + vsnprintf(item_cur->node.str + strlen(item_cur->node.str), + avail, fmt, ap); + item_cur->node.str[sizeof(item_cur->node.str) - 1] = '\0'; + va_end(ap); +} + +void item_set_tag(char tag) +{ + item_cur->node.tag = tag; +} +void item_set_data(void *ptr) +{ + item_cur->node.data = ptr; +} + +void item_set_selected(int val) +{ + item_cur->node.selected = val; +} + +int item_activate_selected(void) +{ + item_foreach() + if (item_is_selected()) + return 1; + return 0; +} + +void *item_data(void) +{ + return item_cur->node.data; +} + +char item_tag(void) +{ + return item_cur->node.tag; +} + +int item_count(void) +{ + int n = 0; + struct dialog_list *p; + + for (p = item_head; p; p = p->next) + n++; + return n; +} + +void item_set(int n) +{ + int i = 0; + item_foreach() + if (i++ == n) + return; +} + +int item_n(void) +{ + int n = 0; + struct dialog_list *p; + + for (p = item_head; p; p = p->next) { + if (p == item_cur) + return n; + n++; + } + return 0; +} + +const char *item_str(void) +{ + return item_cur->node.str; +} + +int item_is_selected(void) +{ + return (item_cur->node.selected != 0); +} + +int item_is_tag(char tag) +{ + return (item_cur->node.tag == tag); +} diff --git a/kernel/fiasco/tool/kconfig/scripts/kconfig/lxdialog/yesno.c b/kernel/fiasco/tool/kconfig/scripts/kconfig/lxdialog/yesno.c new file mode 100644 index 00000000..4e6e8090 --- /dev/null +++ b/kernel/fiasco/tool/kconfig/scripts/kconfig/lxdialog/yesno.c @@ -0,0 +1,114 @@ +/* + * yesno.c -- implements the yes/no box + * + * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) + * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "dialog.h" + +/* + * Display termination buttons + */ +static void print_buttons(WINDOW * dialog, int height, int width, int selected) +{ + int x = width / 2 - 10; + int y = height - 2; + + print_button(dialog, gettext(" Yes "), y, x, selected == 0); + print_button(dialog, gettext(" No "), y, x + 13, selected == 1); + + wmove(dialog, y, x + 1 + 13 * selected); + wrefresh(dialog); +} + +/* + * Display a dialog box with two buttons - Yes and No + */ +int dialog_yesno(const char *title, const char *prompt, int height, int width) +{ + int i, x, y, key = 0, button = 0; + WINDOW *dialog; + +do_resize: + if (getmaxy(stdscr) < (height + 4)) + return -ERRDISPLAYTOOSMALL; + if (getmaxx(stdscr) < (width + 4)) + return -ERRDISPLAYTOOSMALL; + + /* center dialog box on screen */ + x = (COLS - width) / 2; + y = (LINES - height) / 2; + + draw_shadow(stdscr, y, x, height, width); + + dialog = newwin(height, width, y, x); + keypad(dialog, TRUE); + + draw_box(dialog, 0, 0, height, width, + dlg.dialog.atr, dlg.border.atr); + wattrset(dialog, dlg.border.atr); + mvwaddch(dialog, height - 3, 0, ACS_LTEE); + for (i = 0; i < width - 2; i++) + waddch(dialog, ACS_HLINE); + wattrset(dialog, dlg.dialog.atr); + waddch(dialog, ACS_RTEE); + + print_title(dialog, title, width); + + wattrset(dialog, dlg.dialog.atr); + print_autowrap(dialog, prompt, width - 2, 1, 3); + + print_buttons(dialog, height, width, 0); + + while (key != KEY_ESC) { + key = wgetch(dialog); + switch (key) { + case 'Y': + case 'y': + delwin(dialog); + return 0; + case 'N': + case 'n': + delwin(dialog); + return 1; + + case TAB: + case KEY_LEFT: + case KEY_RIGHT: + button = ((key == KEY_LEFT ? --button : ++button) < 0) ? 1 : (button > 1 ? 0 : button); + + print_buttons(dialog, height, width, button); + wrefresh(dialog); + break; + case ' ': + case '\n': + delwin(dialog); + return button; + case KEY_ESC: + key = on_key_esc(dialog); + break; + case KEY_RESIZE: + delwin(dialog); + on_key_resize(); + goto do_resize; + } + } + + delwin(dialog); + return key; /* ESC pressed */ +} diff --git a/kernel/fiasco/tool/kconfig/scripts/kconfig/mconf.c b/kernel/fiasco/tool/kconfig/scripts/kconfig/mconf.c new file mode 100644 index 00000000..f606738d --- /dev/null +++ b/kernel/fiasco/tool/kconfig/scripts/kconfig/mconf.c @@ -0,0 +1,882 @@ +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + * + * Introduced single menu mode (show all sub-menus in one large tree). + * 2002-11-06 Petr Baudis + * + * i18n, 2005, Arnaldo Carvalho de Melo + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "lkc.h" +#include "lxdialog/dialog.h" + +static const char mconf_readme[] = N_( +"Overview\n" +"--------\n" +"This interface let you select features and parameters for the build.\n" +"Features can either be built-in, modularized, or ignored. Parameters\n" +"must be entered in as decimal or hexadecimal numbers or text.\n" +"\n" +"Menu items beginning with following braces represent features that\n" +" [ ] can be built in or removed\n" +" < > can be built in, modularized or removed\n" +" { } can be built in or modularized (selected by other feature)\n" +" - - are selected by other feature,\n" +"while *, M or whitespace inside braces means to build in, build as\n" +"a module or to exclude the feature respectively.\n" +"\n" +"To change any of these features, highlight it with the cursor\n" +"keys and press to build it in, to make it a module or\n" +" to removed it. You may also press the to cycle\n" +"through the available options (ie. Y->N->M->Y).\n" +"\n" +"Some additional keyboard hints:\n" +"\n" +"Menus\n" +"----------\n" +"o Use the Up/Down arrow keys (cursor keys) to highlight the item\n" +" you wish to change or submenu wish to select and press .\n" +" Submenus are designated by \"--->\".\n" +"\n" +" Shortcut: Press the option's highlighted letter (hotkey).\n" +" Pressing a hotkey more than once will sequence\n" +" through all visible items which use that hotkey.\n" +"\n" +" You may also use the and keys to scroll\n" +" unseen options into view.\n" +"\n" +"o To exit a menu use the cursor keys to highlight the button\n" +" and press .\n" +"\n" +" Shortcut: Press or or if there is no hotkey\n" +" using those letters. You may press a single , but\n" +" there is a delayed response which you may find annoying.\n" +"\n" +" Also, the and cursor keys will cycle between and\n" +" \n" +"\n" +"\n" +"Data Entry\n" +"-----------\n" +"o Enter the requested information and press \n" +" If you are entering hexadecimal values, it is not necessary to\n" +" add the '0x' prefix to the entry.\n" +"\n" +"o For help, use the or cursor keys to highlight the help option\n" +" and press . You can try as well.\n" +"\n" +"\n" +"Text Box (Help Window)\n" +"--------\n" +"o Use the cursor keys to scroll up/down/left/right. The VI editor\n" +" keys h,j,k,l function here as do and for those\n" +" who are familiar with less and lynx.\n" +"\n" +"o Press , , or to exit.\n" +"\n" +"\n" +"Alternate Configuration Files\n" +"-----------------------------\n" +"Menuconfig supports the use of alternate configuration files for\n" +"those who, for various reasons, find it necessary to switch\n" +"between different configurations.\n" +"\n" +"At the end of the main menu you will find two options. One is\n" +"for saving the current configuration to a file of your choosing.\n" +"The other option is for loading a previously saved alternate\n" +"configuration.\n" +"\n" +"Even if you don't use alternate configuration files, but you\n" +"find during a Menuconfig session that you have completely messed\n" +"up your settings, you may use the \"Load Alternate...\" option to\n" +"restore your previously saved settings from \".config\" without\n" +"restarting Menuconfig.\n" +"\n" +"Other information\n" +"-----------------\n" +"If you use Menuconfig in an XTERM window make sure you have your\n" +"$TERM variable set to point to a xterm definition which supports color.\n" +"Otherwise, Menuconfig will look rather bad. Menuconfig will not\n" +"display correctly in a RXVT window because rxvt displays only one\n" +"intensity of color, bright.\n" +"\n" +"Menuconfig will display larger menus on screens or xterms which are\n" +"set to display more than the standard 25 row by 80 column geometry.\n" +"In order for this to work, the \"stty size\" command must be able to\n" +"display the screen's current row and column geometry. I STRONGLY\n" +"RECOMMEND that you make sure you do NOT have the shell variables\n" +"LINES and COLUMNS exported into your environment. Some distributions\n" +"export those variables via /etc/profile. Some ncurses programs can\n" +"become confused when those variables (LINES & COLUMNS) don't reflect\n" +"the true screen size.\n" +"\n" +"Optional personality available\n" +"------------------------------\n" +"If you prefer to have all of the options listed in a single menu, rather\n" +"than the default multimenu hierarchy, run the menuconfig with\n" +"MENUCONFIG_MODE environment variable set to single_menu. Example:\n" +"\n" +"make MENUCONFIG_MODE=single_menu menuconfig\n" +"\n" +" will then unroll the appropriate category, or enfold it if it\n" +"is already unrolled.\n" +"\n" +"Note that this mode can eventually be a little more CPU expensive\n" +"(especially with a larger number of unrolled categories) than the\n" +"default mode.\n" +"\n" +"Different color themes available\n" +"--------------------------------\n" +"It is possible to select different color themes using the variable\n" +"MENUCONFIG_COLOR. To select a theme use:\n" +"\n" +"make MENUCONFIG_COLOR= menuconfig\n" +"\n" +"Available themes are\n" +" mono => selects colors suitable for monochrome displays\n" +" blackbg => selects a color scheme with black background\n" +" classic => theme with blue background. The classic look\n" +" bluetitle => a LCD friendly version of classic. (default)\n" +"\n"), +menu_instructions[] = N_( + "Arrow keys navigate the menu. " + " selects submenus --->. " + "Highlighted letters are hotkeys. " + "Pressing includes, excludes, modularizes features. " + "Press to exit, for Help, for Search. " + "Legend: [*] built-in [ ] excluded module < > module capable"), +radiolist_instructions[] = N_( + "Use the arrow keys to navigate this window or " + "press the hotkey of the item you wish to select " + "followed by the . " + "Press for additional information about this option."), +inputbox_instructions_int[] = N_( + "Please enter a decimal value. " + "Fractions will not be accepted. " + "Use the key to move from the input field to the buttons below it."), +inputbox_instructions_hex[] = N_( + "Please enter a hexadecimal value. " + "Use the key to move from the input field to the buttons below it."), +inputbox_instructions_string[] = N_( + "Please enter a string value. " + "Use the key to move from the input field to the buttons below it."), +setmod_text[] = N_( + "This feature depends on another which has been configured as a module.\n" + "As a result, this feature will be built as a module."), +load_config_text[] = N_( + "Enter the name of the configuration file you wish to load. " + "Accept the name shown to restore the configuration you " + "last retrieved. Leave blank to abort."), +load_config_help[] = N_( + "\n" + "For various reasons, one may wish to keep several different\n" + "configurations available on a single machine.\n" + "\n" + "If you have saved a previous configuration in a file other than the\n" + "default one, entering its name here will allow you to modify that\n" + "configuration.\n" + "\n" + "If you are uncertain, then you have probably never used alternate\n" + "configuration files. You should therefore leave this blank to abort.\n"), +save_config_text[] = N_( + "Enter a filename to which this configuration should be saved " + "as an alternate. Leave blank to abort."), +save_config_help[] = N_( + "\n" + "For various reasons, one may wish to keep different configurations\n" + "available on a single machine.\n" + "\n" + "Entering a file name here will allow you to later retrieve, modify\n" + "and use the current configuration as an alternate to whatever\n" + "configuration options you have selected at that time.\n" + "\n" + "If you are uncertain what all this means then you should probably\n" + "leave this blank.\n"), +search_help[] = N_( + "\n" + "Search for symbols and display their relations.\n" + "Regular expressions are allowed.\n" + "Example: search for \"^FOO\"\n" + "Result:\n" + "-----------------------------------------------------------------\n" + "Symbol: FOO [=m]\n" + "Prompt: Foo bus is used to drive the bar HW\n" + "Defined at drivers/pci/Kconfig:47\n" + "Depends on: X86_LOCAL_APIC && X86_IO_APIC || IA64\n" + "Location:\n" + " -> Bus options (PCI, PCMCIA, EISA, ISA)\n" + " -> PCI support (PCI [=y])\n" + " -> PCI access mode ( [=y])\n" + "Selects: LIBCRC32\n" + "Selected by: BAR\n" + "-----------------------------------------------------------------\n" + "o The line 'Prompt:' shows the text used in the menu structure for\n" + " this symbol\n" + "o The 'Defined at' line tell at what file / line number the symbol\n" + " is defined\n" + "o The 'Depends on:' line tell what symbols needs to be defined for\n" + " this symbol to be visible in the menu (selectable)\n" + "o The 'Location:' lines tell where in the menu structure this symbol\n" + " is located\n" + " A location followed by a [=y] indicate that this is a selectable\n" + " menu item - and current value is displayed inside brackets.\n" + "o The 'Selects:' line tell what symbol will be automatically\n" + " selected if this symbol is selected (y or m)\n" + "o The 'Selected by' line tell what symbol has selected this symbol\n" + "\n" + "Only relevant lines are shown.\n" + "\n\n" + "Search examples:\n" + "Examples: USB => find all symbols containing USB\n" + " ^USB => find all symbols starting with USB\n" + " USB$ => find all symbols ending with USB\n" + "\n"); + +static int indent; +static struct menu *current_menu; +static int child_count; +static int single_menu_mode; +static int show_all_options; +static int saved_x, saved_y; + +static void conf(struct menu *menu); +static void conf_choice(struct menu *menu); +static void conf_string(struct menu *menu); +static void conf_load(void); +static void conf_save(void); +static void show_textbox(const char *title, const char *text, int r, int c); +static void show_helptext(const char *title, const char *text); +static void show_help(struct menu *menu); + +static char filename[PATH_MAX+1]; +static void set_config_filename(const char *config_filename) +{ + static char menu_backtitle[PATH_MAX+128]; + int size; + + size = snprintf(menu_backtitle, sizeof(menu_backtitle), + "%s - %s", config_filename, rootmenu.prompt->text); + if (size >= sizeof(menu_backtitle)) + menu_backtitle[sizeof(menu_backtitle)-1] = '\0'; + set_dialog_backtitle(menu_backtitle); + + size = snprintf(filename, sizeof(filename), "%s", config_filename); + if (size >= sizeof(filename)) + filename[sizeof(filename)-1] = '\0'; +} + + +static void search_conf(void) +{ + struct symbol **sym_arr; + struct gstr res; + char *dialog_input; + int dres; +again: + dialog_clear(); + dres = dialog_inputbox(_("Search Configuration Parameter"), + _("Enter " CONFIG_ " (sub)string to search for " + "(with or without \"" CONFIG_ "\")"), + 10, 75, ""); + switch (dres) { + case 0: + break; + case 1: + show_helptext(_("Search Configuration"), search_help); + goto again; + default: + return; + } + + /* strip the prefix if necessary */ + dialog_input = dialog_input_result; + if (strncasecmp(dialog_input_result, CONFIG_, strlen(CONFIG_)) == 0) + dialog_input += strlen(CONFIG_); + + sym_arr = sym_re_search(dialog_input); + res = get_relations_str(sym_arr); + free(sym_arr); + show_textbox(_("Search Results"), str_get(&res), 0, 0); + str_free(&res); +} + +static void build_conf(struct menu *menu) +{ + struct symbol *sym; + struct property *prop; + struct menu *child; + int type, tmp, doint = 2; + tristate val; + char ch; + bool visible; + + /* + * note: menu_is_visible() has side effect that it will + * recalc the value of the symbol. + */ + visible = menu_is_visible(menu); + if (show_all_options && !menu_has_prompt(menu)) + return; + else if (!show_all_options && !visible) + return; + + sym = menu->sym; + prop = menu->prompt; + if (!sym) { + if (prop && menu != current_menu) { + const char *prompt = menu_get_prompt(menu); + switch (prop->type) { + case P_MENU: + child_count++; + prompt = _(prompt); + if (single_menu_mode) { + item_make("%s%*c%s", + menu->data ? "-->" : "++>", + indent + 1, ' ', prompt); + } else + item_make(" %*c%s --->", indent + 1, ' ', prompt); + + item_set_tag('m'); + item_set_data(menu); + if (single_menu_mode && menu->data) + goto conf_childs; + return; + case P_COMMENT: + if (prompt) { + child_count++; + item_make(" %*c*** %s ***", indent + 1, ' ', _(prompt)); + item_set_tag(':'); + item_set_data(menu); + } + break; + default: + if (prompt) { + child_count++; + item_make("---%*c%s", indent + 1, ' ', _(prompt)); + item_set_tag(':'); + item_set_data(menu); + } + } + } else + doint = 0; + goto conf_childs; + } + + type = sym_get_type(sym); + if (sym_is_choice(sym)) { + struct symbol *def_sym = sym_get_choice_value(sym); + struct menu *def_menu = NULL; + + child_count++; + for (child = menu->list; child; child = child->next) { + if (menu_is_visible(child) && child->sym == def_sym) + def_menu = child; + } + + val = sym_get_tristate_value(sym); + if (sym_is_changable(sym)) { + switch (type) { + case S_BOOLEAN: + item_make("[%c]", val == no ? ' ' : '*'); + break; + case S_TRISTATE: + switch (val) { + case yes: ch = '*'; break; + case mod: ch = 'M'; break; + default: ch = ' '; break; + } + item_make("<%c>", ch); + break; + } + item_set_tag('t'); + item_set_data(menu); + } else { + item_make(" "); + item_set_tag(def_menu ? 't' : ':'); + item_set_data(menu); + } + + item_add_str("%*c%s", indent + 1, ' ', _(menu_get_prompt(menu))); + if (val == yes) { + if (def_menu) { + item_add_str(" (%s)", _(menu_get_prompt(def_menu))); + item_add_str(" --->"); + if (def_menu->list) { + indent += 2; + build_conf(def_menu); + indent -= 2; + } + } + return; + } + } else { + if (menu == current_menu) { + item_make("---%*c%s", indent + 1, ' ', _(menu_get_prompt(menu))); + item_set_tag(':'); + item_set_data(menu); + goto conf_childs; + } + child_count++; + val = sym_get_tristate_value(sym); + if (sym_is_choice_value(sym) && val == yes) { + item_make(" "); + item_set_tag(':'); + item_set_data(menu); + } else { + switch (type) { + case S_BOOLEAN: + if (sym_is_changable(sym)) + item_make("[%c]", val == no ? ' ' : '*'); + else + item_make("-%c-", val == no ? ' ' : '*'); + item_set_tag('t'); + item_set_data(menu); + break; + case S_TRISTATE: + switch (val) { + case yes: ch = '*'; break; + case mod: ch = 'M'; break; + default: ch = ' '; break; + } + if (sym_is_changable(sym)) { + if (sym->rev_dep.tri == mod) + item_make("{%c}", ch); + else + item_make("<%c>", ch); + } else + item_make("-%c-", ch); + item_set_tag('t'); + item_set_data(menu); + break; + default: + tmp = 2 + strlen(sym_get_string_value(sym)); /* () = 2 */ + item_make("(%s)", sym_get_string_value(sym)); + tmp = indent - tmp + 4; + if (tmp < 0) + tmp = 0; + item_add_str("%*c%s%s", tmp, ' ', _(menu_get_prompt(menu)), + (sym_has_value(sym) || !sym_is_changable(sym)) ? + "" : _(" (NEW)")); + item_set_tag('s'); + item_set_data(menu); + goto conf_childs; + } + } + item_add_str("%*c%s%s", indent + 1, ' ', _(menu_get_prompt(menu)), + (sym_has_value(sym) || !sym_is_changable(sym)) ? + "" : _(" (NEW)")); + if (menu->prompt->type == P_MENU) { + item_add_str(" --->"); + return; + } + } + +conf_childs: + indent += doint; + for (child = menu->list; child; child = child->next) + build_conf(child); + indent -= doint; +} + +static void conf(struct menu *menu) +{ + struct menu *submenu; + const char *prompt = menu_get_prompt(menu); + struct symbol *sym; + struct menu *active_menu = NULL; + int res; + int s_scroll = 0; + + while (1) { + item_reset(); + current_menu = menu; + build_conf(menu); + if (!child_count) + break; + if (menu == &rootmenu) { + item_make("--- "); + item_set_tag(':'); + item_make(_(" Load an Alternate Configuration File")); + item_set_tag('L'); + item_make(_(" Save an Alternate Configuration File")); + item_set_tag('S'); + } + dialog_clear(); + res = dialog_menu(prompt ? _(prompt) : _("Main Menu"), + _(menu_instructions), + active_menu, &s_scroll); + if (res == 1 || res == KEY_ESC || res == -ERRDISPLAYTOOSMALL) + break; + if (!item_activate_selected()) + continue; + if (!item_tag()) + continue; + + submenu = item_data(); + active_menu = item_data(); + if (submenu) + sym = submenu->sym; + else + sym = NULL; + + switch (res) { + case 0: + switch (item_tag()) { + case 'm': + if (single_menu_mode) + submenu->data = (void *) (long) !submenu->data; + else + conf(submenu); + break; + case 't': + if (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes) + conf_choice(submenu); + else if (submenu->prompt->type == P_MENU) + conf(submenu); + break; + case 's': + conf_string(submenu); + break; + case 'L': + conf_load(); + break; + case 'S': + conf_save(); + break; + } + break; + case 2: + if (sym) + show_help(submenu); + else + show_helptext(_("README"), _(mconf_readme)); + break; + case 3: + if (item_is_tag('t')) { + if (sym_set_tristate_value(sym, yes)) + break; + if (sym_set_tristate_value(sym, mod)) + show_textbox(NULL, setmod_text, 6, 74); + } + break; + case 4: + if (item_is_tag('t')) + sym_set_tristate_value(sym, no); + break; + case 5: + if (item_is_tag('t')) + sym_set_tristate_value(sym, mod); + break; + case 6: + if (item_is_tag('t')) + sym_toggle_tristate_value(sym); + else if (item_is_tag('m')) + conf(submenu); + break; + case 7: + search_conf(); + break; + case 8: + show_all_options = !show_all_options; + break; + } + } +} + +static void show_textbox(const char *title, const char *text, int r, int c) +{ + dialog_clear(); + dialog_textbox(title, text, r, c); +} + +static void show_helptext(const char *title, const char *text) +{ + show_textbox(title, text, 0, 0); +} + +static void show_help(struct menu *menu) +{ + struct gstr help = str_new(); + + help.max_width = getmaxx(stdscr) - 10; + menu_get_ext_help(menu, &help); + + show_helptext(_(menu_get_prompt(menu)), str_get(&help)); + str_free(&help); +} + +static void conf_choice(struct menu *menu) +{ + const char *prompt = _(menu_get_prompt(menu)); + struct menu *child; + struct symbol *active; + + active = sym_get_choice_value(menu->sym); + while (1) { + int res; + int selected; + item_reset(); + + current_menu = menu; + for (child = menu->list; child; child = child->next) { + if (!menu_is_visible(child)) + continue; + if (child->sym) + item_make("%s", _(menu_get_prompt(child))); + else { + item_make("*** %s ***", _(menu_get_prompt(child))); + item_set_tag(':'); + } + item_set_data(child); + if (child->sym == active) + item_set_selected(1); + if (child->sym == sym_get_choice_value(menu->sym)) + item_set_tag('X'); + } + dialog_clear(); + res = dialog_checklist(prompt ? _(prompt) : _("Main Menu"), + _(radiolist_instructions), + 15, 70, 6); + selected = item_activate_selected(); + switch (res) { + case 0: + if (selected) { + child = item_data(); + if (!child->sym) + break; + + sym_set_tristate_value(child->sym, yes); + } + return; + case 1: + if (selected) { + child = item_data(); + show_help(child); + active = child->sym; + } else + show_help(menu); + break; + case KEY_ESC: + return; + case -ERRDISPLAYTOOSMALL: + return; + } + } +} + +static void conf_string(struct menu *menu) +{ + const char *prompt = menu_get_prompt(menu); + + while (1) { + int res; + const char *heading; + + switch (sym_get_type(menu->sym)) { + case S_INT: + heading = _(inputbox_instructions_int); + break; + case S_HEX: + heading = _(inputbox_instructions_hex); + break; + case S_STRING: + heading = _(inputbox_instructions_string); + break; + default: + heading = _("Internal mconf error!"); + } + dialog_clear(); + res = dialog_inputbox(prompt ? _(prompt) : _("Main Menu"), + heading, 10, 75, + sym_get_string_value(menu->sym)); + switch (res) { + case 0: + if (sym_set_string_value(menu->sym, dialog_input_result)) + return; + show_textbox(NULL, _("You have made an invalid entry."), 5, 43); + break; + case 1: + show_help(menu); + break; + case KEY_ESC: + return; + } + } +} + +static void conf_load(void) +{ + + while (1) { + int res; + dialog_clear(); + res = dialog_inputbox(NULL, load_config_text, + 11, 55, filename); + switch(res) { + case 0: + if (!dialog_input_result[0]) + return; + if (!conf_read(dialog_input_result)) { + set_config_filename(dialog_input_result); + sym_set_change_count(1); + return; + } + show_textbox(NULL, _("File does not exist!"), 5, 38); + break; + case 1: + show_helptext(_("Load Alternate Configuration"), load_config_help); + break; + case KEY_ESC: + return; + } + } +} + +static void conf_save(void) +{ + while (1) { + int res; + dialog_clear(); + res = dialog_inputbox(NULL, save_config_text, + 11, 55, filename); + switch(res) { + case 0: + if (!dialog_input_result[0]) + return; + if (!conf_write(dialog_input_result)) { + set_config_filename(dialog_input_result); + return; + } + show_textbox(NULL, _("Can't create file! Probably a nonexistent directory."), 5, 60); + break; + case 1: + show_helptext(_("Save Alternate Configuration"), save_config_help); + break; + case KEY_ESC: + return; + } + } +} + +static int handle_exit(void) +{ + int res; + + dialog_clear(); + if (conf_get_changed()) + res = dialog_yesno(NULL, + _("Do you wish to save your new configuration ?\n" + " to continue."), + 6, 60); + else + res = -1; + + end_dialog(saved_x, saved_y); + + switch (res) { + case 0: + if (conf_write(filename)) { + fprintf(stderr, _("\n\n" + "Error while writing of the configuration.\n" + "Your configuration changes were NOT saved." + "\n\n")); + return 1; + } + /* fall through */ + case -1: + printf(_("\n\n" + "*** End of the configuration.\n" + "*** Execute 'make' to start the build or try 'make help'." + "\n\n")); + res = 0; + break; + default: + fprintf(stderr, _("\n\n" + "Your configuration changes were NOT saved." + "\n\n")); + if (res != KEY_ESC) + res = 0; + } + + return res; +} + +static void sig_handler(int signo) +{ + exit(handle_exit()); +} + +int main(int ac, char **av) +{ + char *mode; + int res; + + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + + signal(SIGINT, sig_handler); + + conf_parse(av[1]); + conf_read(NULL); + + mode = getenv("MENUCONFIG_MODE"); + if (mode) { + if (!strcasecmp(mode, "single_menu")) + single_menu_mode = 1; + } + + initscr(); + + getyx(stdscr, saved_y, saved_x); + if (init_dialog(NULL)) { + fprintf(stderr, N_("Your display is too small to run Menuconfig!\n")); + fprintf(stderr, N_("It must be at least 19 lines by 80 columns.\n")); + return 1; + } + + set_config_filename(conf_get_configname()); + do { + conf(&rootmenu); + res = handle_exit(); + } while (res == KEY_ESC); + + return res; +} + diff --git a/kernel/fiasco/tool/kconfig/scripts/kconfig/menu.c b/kernel/fiasco/tool/kconfig/scripts/kconfig/menu.c new file mode 100644 index 00000000..8c2a97e6 --- /dev/null +++ b/kernel/fiasco/tool/kconfig/scripts/kconfig/menu.c @@ -0,0 +1,607 @@ +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +#include +#include +#include +#include + +#include "lkc.h" + +static const char nohelp_text[] = "There is no help available for this option."; + +struct menu rootmenu; +static struct menu **last_entry_ptr; + +struct file *file_list; +struct file *current_file; + +void menu_warn(struct menu *menu, const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + fprintf(stderr, "%s:%d:warning: ", menu->file->name, menu->lineno); + vfprintf(stderr, fmt, ap); + fprintf(stderr, "\n"); + va_end(ap); +} + +static void prop_warn(struct property *prop, const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + fprintf(stderr, "%s:%d:warning: ", prop->file->name, prop->lineno); + vfprintf(stderr, fmt, ap); + fprintf(stderr, "\n"); + va_end(ap); +} + +void _menu_init(void) +{ + current_entry = current_menu = &rootmenu; + last_entry_ptr = &rootmenu.list; +} + +void menu_add_entry(struct symbol *sym) +{ + struct menu *menu; + + menu = malloc(sizeof(*menu)); + memset(menu, 0, sizeof(*menu)); + menu->sym = sym; + menu->parent = current_menu; + menu->file = current_file; + menu->lineno = zconf_lineno(); + + *last_entry_ptr = menu; + last_entry_ptr = &menu->next; + current_entry = menu; + if (sym) + menu_add_symbol(P_SYMBOL, sym, NULL); +} + +void menu_end_entry(void) +{ +} + +struct menu *menu_add_menu(void) +{ + menu_end_entry(); + last_entry_ptr = ¤t_entry->list; + return current_menu = current_entry; +} + +void menu_end_menu(void) +{ + last_entry_ptr = ¤t_menu->next; + current_menu = current_menu->parent; +} + +static struct expr *menu_check_dep(struct expr *e) +{ + if (!e) + return e; + + switch (e->type) { + case E_NOT: + e->left.expr = menu_check_dep(e->left.expr); + break; + case E_OR: + case E_AND: + e->left.expr = menu_check_dep(e->left.expr); + e->right.expr = menu_check_dep(e->right.expr); + break; + case E_SYMBOL: + /* change 'm' into 'm' && MODULES */ + if (e->left.sym == &symbol_mod) + return expr_alloc_and(e, expr_alloc_symbol(modules_sym)); + break; + default: + break; + } + return e; +} + +void menu_add_dep(struct expr *dep) +{ + current_entry->dep = expr_alloc_and(current_entry->dep, menu_check_dep(dep)); +} + +void menu_set_type(int type) +{ + struct symbol *sym = current_entry->sym; + + if (sym->type == type) + return; + if (sym->type == S_UNKNOWN) { + sym->type = type; + return; + } + menu_warn(current_entry, "type of '%s' redefined from '%s' to '%s'", + sym->name ? sym->name : "", + sym_type_name(sym->type), sym_type_name(type)); +} + +struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *expr, struct expr *dep) +{ + struct property *prop = prop_alloc(type, current_entry->sym); + + prop->menu = current_entry; + prop->expr = expr; + prop->visible.expr = menu_check_dep(dep); + + if (prompt) { + if (isspace(*prompt)) { + prop_warn(prop, "leading whitespace ignored"); + while (isspace(*prompt)) + prompt++; + } + if (current_entry->prompt && current_entry != &rootmenu) + prop_warn(prop, "prompt redefined"); + + /* Apply all upper menus' visibilities to actual prompts. */ + if(type == P_PROMPT) { + struct menu *menu = current_entry; + + while ((menu = menu->parent) != NULL) { + if (!menu->visibility) + continue; + prop->visible.expr + = expr_alloc_and(prop->visible.expr, + menu->visibility); + } + } + + current_entry->prompt = prop; + } + prop->text = prompt; + + return prop; +} + +struct property *menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep) +{ + return menu_add_prop(type, prompt, NULL, dep); +} + +void menu_add_visibility(struct expr *expr) +{ + current_entry->visibility = expr_alloc_and(current_entry->visibility, + expr); +} + +void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep) +{ + menu_add_prop(type, NULL, expr, dep); +} + +void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep) +{ + menu_add_prop(type, NULL, expr_alloc_symbol(sym), dep); +} + +void menu_add_option(int token, char *arg) +{ + struct property *prop; + + switch (token) { + case T_OPT_MODULES: + prop = prop_alloc(P_DEFAULT, modules_sym); + prop->expr = expr_alloc_symbol(current_entry->sym); + break; + case T_OPT_DEFCONFIG_LIST: + if (!sym_defconfig_list) + sym_defconfig_list = current_entry->sym; + else if (sym_defconfig_list != current_entry->sym) + zconf_error("trying to redefine defconfig symbol"); + break; + case T_OPT_ENV: + prop_add_env(arg); + break; + } +} + +static int menu_validate_number(struct symbol *sym, struct symbol *sym2) +{ + return sym2->type == S_INT || sym2->type == S_HEX || + (sym2->type == S_UNKNOWN && sym_string_valid(sym, sym2->name)); +} + +static void sym_check_prop(struct symbol *sym) +{ + struct property *prop; + struct symbol *sym2; + for (prop = sym->prop; prop; prop = prop->next) { + switch (prop->type) { + case P_DEFAULT: + if ((sym->type == S_STRING || sym->type == S_INT || sym->type == S_HEX) && + prop->expr->type != E_SYMBOL) + prop_warn(prop, + "default for config symbol '%s'" + " must be a single symbol", sym->name); + if (prop->expr->type != E_SYMBOL) + break; + sym2 = prop_get_symbol(prop); + if (sym->type == S_HEX || sym->type == S_INT) { + if (!menu_validate_number(sym, sym2)) + prop_warn(prop, + "'%s': number is invalid", + sym->name); + } + break; + case P_SELECT: + sym2 = prop_get_symbol(prop); + if (sym->type != S_BOOLEAN && sym->type != S_TRISTATE) + prop_warn(prop, + "config symbol '%s' uses select, but is " + "not boolean or tristate", sym->name); + else if (sym2->type != S_UNKNOWN && + sym2->type != S_BOOLEAN && + sym2->type != S_TRISTATE) + prop_warn(prop, + "'%s' has wrong type. 'select' only " + "accept arguments of boolean and " + "tristate type", sym2->name); + break; + case P_RANGE: + if (sym->type != S_INT && sym->type != S_HEX) + prop_warn(prop, "range is only allowed " + "for int or hex symbols"); + if (!menu_validate_number(sym, prop->expr->left.sym) || + !menu_validate_number(sym, prop->expr->right.sym)) + prop_warn(prop, "range is invalid"); + break; + default: + ; + } + } +} + +void menu_finalize(struct menu *parent) +{ + struct menu *menu, *last_menu; + struct symbol *sym; + struct property *prop; + struct expr *parentdep, *basedep, *dep, *dep2, **ep; + + sym = parent->sym; + if (parent->list) { + if (sym && sym_is_choice(sym)) { + if (sym->type == S_UNKNOWN) { + /* find the first choice value to find out choice type */ + current_entry = parent; + for (menu = parent->list; menu; menu = menu->next) { + if (menu->sym && menu->sym->type != S_UNKNOWN) { + menu_set_type(menu->sym->type); + break; + } + } + } + /* set the type of the remaining choice values */ + for (menu = parent->list; menu; menu = menu->next) { + current_entry = menu; + if (menu->sym && menu->sym->type == S_UNKNOWN) + menu_set_type(sym->type); + } + parentdep = expr_alloc_symbol(sym); + } else if (parent->prompt) + parentdep = parent->prompt->visible.expr; + else + parentdep = parent->dep; + + for (menu = parent->list; menu; menu = menu->next) { + basedep = expr_transform(menu->dep); + basedep = expr_alloc_and(expr_copy(parentdep), basedep); + basedep = expr_eliminate_dups(basedep); + menu->dep = basedep; + if (menu->sym) + prop = menu->sym->prop; + else + prop = menu->prompt; + for (; prop; prop = prop->next) { + if (prop->menu != menu) + continue; + dep = expr_transform(prop->visible.expr); + dep = expr_alloc_and(expr_copy(basedep), dep); + dep = expr_eliminate_dups(dep); + if (menu->sym && menu->sym->type != S_TRISTATE) + dep = expr_trans_bool(dep); + prop->visible.expr = dep; + if (prop->type == P_SELECT) { + struct symbol *es = prop_get_symbol(prop); + es->rev_dep.expr = expr_alloc_or(es->rev_dep.expr, + expr_alloc_and(expr_alloc_symbol(menu->sym), expr_copy(dep))); + } + } + } + for (menu = parent->list; menu; menu = menu->next) + menu_finalize(menu); + } else if (sym) { + basedep = parent->prompt ? parent->prompt->visible.expr : NULL; + basedep = expr_trans_compare(basedep, E_UNEQUAL, &symbol_no); + basedep = expr_eliminate_dups(expr_transform(basedep)); + last_menu = NULL; + for (menu = parent->next; menu; menu = menu->next) { + dep = menu->prompt ? menu->prompt->visible.expr : menu->dep; + if (!expr_contains_symbol(dep, sym)) + break; + if (expr_depends_symbol(dep, sym)) + goto next; + dep = expr_trans_compare(dep, E_UNEQUAL, &symbol_no); + dep = expr_eliminate_dups(expr_transform(dep)); + dep2 = expr_copy(basedep); + expr_eliminate_eq(&dep, &dep2); + expr_free(dep); + if (!expr_is_yes(dep2)) { + expr_free(dep2); + break; + } + expr_free(dep2); + next: + menu_finalize(menu); + menu->parent = parent; + last_menu = menu; + } + if (last_menu) { + parent->list = parent->next; + parent->next = last_menu->next; + last_menu->next = NULL; + } + + sym->dir_dep.expr = expr_alloc_or(sym->dir_dep.expr, parent->dep); + } + for (menu = parent->list; menu; menu = menu->next) { + if (sym && sym_is_choice(sym) && + menu->sym && !sym_is_choice_value(menu->sym)) { + current_entry = menu; + menu->sym->flags |= SYMBOL_CHOICEVAL; + if (!menu->prompt) + menu_warn(menu, "choice value must have a prompt"); + for (prop = menu->sym->prop; prop; prop = prop->next) { + if (prop->type == P_DEFAULT) + prop_warn(prop, "defaults for choice " + "values not supported"); + if (prop->menu == menu) + continue; + if (prop->type == P_PROMPT && + prop->menu->parent->sym != sym) + prop_warn(prop, "choice value used outside its choice group"); + } + /* Non-tristate choice values of tristate choices must + * depend on the choice being set to Y. The choice + * values' dependencies were propagated to their + * properties above, so the change here must be re- + * propagated. + */ + if (sym->type == S_TRISTATE && menu->sym->type != S_TRISTATE) { + basedep = expr_alloc_comp(E_EQUAL, sym, &symbol_yes); + menu->dep = expr_alloc_and(basedep, menu->dep); + for (prop = menu->sym->prop; prop; prop = prop->next) { + if (prop->menu != menu) + continue; + prop->visible.expr = expr_alloc_and(expr_copy(basedep), + prop->visible.expr); + } + } + menu_add_symbol(P_CHOICE, sym, NULL); + prop = sym_get_choice_prop(sym); + for (ep = &prop->expr; *ep; ep = &(*ep)->left.expr) + ; + *ep = expr_alloc_one(E_LIST, NULL); + (*ep)->right.sym = menu->sym; + } + if (menu->list && (!menu->prompt || !menu->prompt->text)) { + for (last_menu = menu->list; ; last_menu = last_menu->next) { + last_menu->parent = parent; + if (!last_menu->next) + break; + } + last_menu->next = menu->next; + menu->next = menu->list; + menu->list = NULL; + } + } + + if (sym && !(sym->flags & SYMBOL_WARNED)) { + if (sym->type == S_UNKNOWN) + menu_warn(parent, "config symbol defined without type"); + + if (sym_is_choice(sym) && !parent->prompt) + menu_warn(parent, "choice must have a prompt"); + + /* Check properties connected to this symbol */ + sym_check_prop(sym); + sym->flags |= SYMBOL_WARNED; + } + + if (sym && !sym_is_optional(sym) && parent->prompt) { + sym->rev_dep.expr = expr_alloc_or(sym->rev_dep.expr, + expr_alloc_and(parent->prompt->visible.expr, + expr_alloc_symbol(&symbol_mod))); + } +} + +bool menu_has_prompt(struct menu *menu) +{ + if (!menu->prompt) + return false; + return true; +} + +bool menu_is_visible(struct menu *menu) +{ + struct menu *child; + struct symbol *sym; + tristate visible; + + if (!menu->prompt) + return false; + + if (menu->visibility) { + if (expr_calc_value(menu->visibility) == no) + return no; + } + + sym = menu->sym; + if (sym) { + sym_calc_value(sym); + visible = menu->prompt->visible.tri; + } else + visible = menu->prompt->visible.tri = expr_calc_value(menu->prompt->visible.expr); + + if (visible != no) + return true; + + if (!sym || sym_get_tristate_value(menu->sym) == no) + return false; + + for (child = menu->list; child; child = child->next) { + if (menu_is_visible(child)) { + if (sym) + sym->flags |= SYMBOL_DEF_USER; + return true; + } + } + + return false; +} + +const char *menu_get_prompt(struct menu *menu) +{ + if (menu->prompt) + return menu->prompt->text; + else if (menu->sym) + return menu->sym->name; + return NULL; +} + +struct menu *menu_get_root_menu(struct menu *menu) +{ + return &rootmenu; +} + +struct menu *menu_get_parent_menu(struct menu *menu) +{ + enum prop_type type; + + for (; menu != &rootmenu; menu = menu->parent) { + type = menu->prompt ? menu->prompt->type : 0; + if (type == P_MENU) + break; + } + return menu; +} + +bool menu_has_help(struct menu *menu) +{ + return menu->help != NULL; +} + +const char *menu_get_help(struct menu *menu) +{ + if (menu->help) + return menu->help; + else + return ""; +} + +static void get_prompt_str(struct gstr *r, struct property *prop) +{ + int i, j; + struct menu *submenu[8], *menu; + + str_printf(r, _("Prompt: %s\n"), _(prop->text)); + str_printf(r, _(" Defined at %s:%d\n"), prop->menu->file->name, + prop->menu->lineno); + if (!expr_is_yes(prop->visible.expr)) { + str_append(r, _(" Depends on: ")); + expr_gstr_print(prop->visible.expr, r); + str_append(r, "\n"); + } + menu = prop->menu->parent; + for (i = 0; menu != &rootmenu && i < 8; menu = menu->parent) + submenu[i++] = menu; + if (i > 0) { + str_printf(r, _(" Location:\n")); + for (j = 4; --i >= 0; j += 2) { + menu = submenu[i]; + str_printf(r, "%*c-> %s", j, ' ', _(menu_get_prompt(menu))); + if (menu->sym) { + str_printf(r, " (%s [=%s])", menu->sym->name ? + menu->sym->name : _(""), + sym_get_string_value(menu->sym)); + } + str_append(r, "\n"); + } + } +} + +void get_symbol_str(struct gstr *r, struct symbol *sym) +{ + bool hit; + struct property *prop; + + if (sym && sym->name) { + str_printf(r, "Symbol: %s [=%s]\n", sym->name, + sym_get_string_value(sym)); + str_printf(r, "Type : %s\n", sym_type_name(sym->type)); + if (sym->type == S_INT || sym->type == S_HEX) { + prop = sym_get_range_prop(sym); + if (prop) { + str_printf(r, "Range : "); + expr_gstr_print(prop->expr, r); + str_append(r, "\n"); + } + } + } + for_all_prompts(sym, prop) + get_prompt_str(r, prop); + hit = false; + for_all_properties(sym, prop, P_SELECT) { + if (!hit) { + str_append(r, " Selects: "); + hit = true; + } else + str_printf(r, " && "); + expr_gstr_print(prop->expr, r); + } + if (hit) + str_append(r, "\n"); + if (sym->rev_dep.expr) { + str_append(r, _(" Selected by: ")); + expr_gstr_print(sym->rev_dep.expr, r); + str_append(r, "\n"); + } + str_append(r, "\n\n"); +} + +struct gstr get_relations_str(struct symbol **sym_arr) +{ + struct symbol *sym; + struct gstr res = str_new(); + int i; + + for (i = 0; sym_arr && (sym = sym_arr[i]); i++) + get_symbol_str(&res, sym); + if (!i) + str_append(&res, _("No matches found.\n")); + return res; +} + + +void menu_get_ext_help(struct menu *menu, struct gstr *help) +{ + struct symbol *sym = menu->sym; + const char *help_text = nohelp_text; + + if (menu_has_help(menu)) { + if (sym->name) + str_printf(help, "%s%s:\n\n", CONFIG_, sym->name); + help_text = menu_get_help(menu); + } + str_printf(help, "%s\n", _(help_text)); + if (sym) + get_symbol_str(help, sym); +} diff --git a/kernel/fiasco/tool/kconfig/scripts/kconfig/nconf.c b/kernel/fiasco/tool/kconfig/scripts/kconfig/nconf.c new file mode 100644 index 00000000..8c0eb659 --- /dev/null +++ b/kernel/fiasco/tool/kconfig/scripts/kconfig/nconf.c @@ -0,0 +1,1546 @@ +/* + * Copyright (C) 2008 Nir Tzachar + +#include "lkc.h" +#include "nconf.h" +#include + +static const char nconf_readme[] = N_( +"Overview\n" +"--------\n" +"This interface let you select features and parameters for the build.\n" +"Features can either be built-in, modularized, or ignored. Parameters\n" +"must be entered in as decimal or hexadecimal numbers or text.\n" +"\n" +"Menu items beginning with following braces represent features that\n" +" [ ] can be built in or removed\n" +" < > can be built in, modularized or removed\n" +" { } can be built in or modularized (selected by other feature)\n" +" - - are selected by other feature,\n" +" XXX cannot be selected. Use Symbol Info to find out why,\n" +"while *, M or whitespace inside braces means to build in, build as\n" +"a module or to exclude the feature respectively.\n" +"\n" +"To change any of these features, highlight it with the cursor\n" +"keys and press to build it in, to make it a module or\n" +" to removed it. You may also press the to cycle\n" +"through the available options (ie. Y->N->M->Y).\n" +"\n" +"Some additional keyboard hints:\n" +"\n" +"Menus\n" +"----------\n" +"o Use the Up/Down arrow keys (cursor keys) to highlight the item\n" +" you wish to change use or . Goto submenu by \n" +" pressing of . Use or to go back.\n" +" Submenus are designated by \"--->\".\n" +"\n" +" Searching: pressing '/' triggers interactive search mode.\n" +" nconfig performs a case insensitive search for the string\n" +" in the menu prompts (no regex support).\n" +" Pressing the up/down keys highlights the previous/next\n" +" matching item. Backspace removes one character from the\n" +" match string. Pressing either '/' again or ESC exits\n" +" search mode. All other keys behave normally.\n" +"\n" +" You may also use the and keys to scroll\n" +" unseen options into view.\n" +"\n" +"o To exit a menu use the just press or .\n" +"\n" +"o To get help with an item, press \n" +" Shortcut: Press or .\n" +"\n" +"\n" +"Radiolists (Choice lists)\n" +"-----------\n" +"o Use the cursor keys to select the option you wish to set and press\n" +" or the .\n" +"\n" +" Shortcut: Press the first letter of the option you wish to set then\n" +" press or .\n" +"\n" +"o To see available help for the item, press \n" +" Shortcut: Press or .\n" +"\n" +"\n" +"Data Entry\n" +"-----------\n" +"o Enter the requested information and press \n" +" If you are entering hexadecimal values, it is not necessary to\n" +" add the '0x' prefix to the entry.\n" +"\n" +"o For help, press .\n" +"\n" +"\n" +"Text Box (Help Window)\n" +"--------\n" +"o Use the cursor keys to scroll up/down/left/right. The VI editor\n" +" keys h,j,k,l function here as do for those\n" +" who are familiar with less and lynx.\n" +"\n" +"o Press , , , or to exit.\n" +"\n" +"\n" +"Alternate Configuration Files\n" +"-----------------------------\n" +"nconfig supports the use of alternate configuration files for\n" +"those who, for various reasons, find it necessary to switch\n" +"between different configurations.\n" +"\n" +"At the end of the main menu you will find two options. One is\n" +"for saving the current configuration to a file of your choosing.\n" +"The other option is for loading a previously saved alternate\n" +"configuration.\n" +"\n" +"Even if you don't use alternate configuration files, but you\n" +"find during a nconfig session that you have completely messed\n" +"up your settings, you may use the \"Load Alternate...\" option to\n" +"restore your previously saved settings from \".config\" without\n" +"restarting nconfig.\n" +"\n" +"Other information\n" +"-----------------\n" +"If you use nconfig in an XTERM window make sure you have your\n" +"$TERM variable set to point to a xterm definition which supports color.\n" +"Otherwise, nconfig will look rather bad. nconfig will not\n" +"display correctly in a RXVT window because rxvt displays only one\n" +"intensity of color, bright.\n" +"\n" +"nconfig will display larger menus on screens or xterms which are\n" +"set to display more than the standard 25 row by 80 column geometry.\n" +"In order for this to work, the \"stty size\" command must be able to\n" +"display the screen's current row and column geometry. I STRONGLY\n" +"RECOMMEND that you make sure you do NOT have the shell variables\n" +"LINES and COLUMNS exported into your environment. Some distributions\n" +"export those variables via /etc/profile. Some ncurses programs can\n" +"become confused when those variables (LINES & COLUMNS) don't reflect\n" +"the true screen size.\n" +"\n" +"Optional personality available\n" +"------------------------------\n" +"If you prefer to have all of the options listed in a single menu, rather\n" +"than the default multimenu hierarchy, run the nconfig with NCONFIG_MODE\n" +"environment variable set to single_menu. Example:\n" +"\n" +"make NCONFIG_MODE=single_menu nconfig\n" +"\n" +" will then unroll the appropriate category, or enfold it if it\n" +"is already unrolled.\n" +"\n" +"Note that this mode can eventually be a little more CPU expensive\n" +"(especially with a larger number of unrolled categories) than the\n" +"default mode.\n" +"\n"), +menu_no_f_instructions[] = N_( +" You do not have function keys support. Please follow the\n" +" following instructions:\n" +" Arrow keys navigate the menu.\n" +" or selects submenus --->.\n" +" Capital Letters are hotkeys.\n" +" Pressing includes, excludes, modularizes features.\n" +" Pressing SpaceBar toggles between the above options.\n" +" Press or to go back one menu,\n" +" or for Help, for Search.\n" +" <1> is interchangeable with , <2> with , etc.\n" +" Legend: [*] built-in [ ] excluded module < > module capable.\n" +" always leaves the current window.\n"), +menu_instructions[] = N_( +" Arrow keys navigate the menu.\n" +" or selects submenus --->.\n" +" Capital Letters are hotkeys.\n" +" Pressing includes, excludes, modularizes features.\n" +" Pressing SpaceBar toggles between the above options\n" +" Press , or to go back one menu,\n" +" , or for Help, for Search.\n" +" <1> is interchangeable with , <2> with , etc.\n" +" Legend: [*] built-in [ ] excluded module < > module capable.\n" +" always leaves the current window\n"), +radiolist_instructions[] = N_( +" Use the arrow keys to navigate this window or\n" +" press the hotkey of the item you wish to select\n" +" followed by the .\n" +" Press , or for additional information about this option.\n"), +inputbox_instructions_int[] = N_( +"Please enter a decimal value.\n" +"Fractions will not be accepted.\n" +"Press to accept, to cancel."), +inputbox_instructions_hex[] = N_( +"Please enter a hexadecimal value.\n" +"Press to accept, to cancel."), +inputbox_instructions_string[] = N_( +"Please enter a string value.\n" +"Press to accept, to cancel."), +setmod_text[] = N_( +"This feature depends on another which\n" +"has been configured as a module.\n" +"As a result, this feature will be built as a module."), +load_config_text[] = N_( +"Enter the name of the configuration file you wish to load.\n" +"Accept the name shown to restore the configuration you\n" +"last retrieved. Leave blank to abort."), +load_config_help[] = N_( +"\n" +"For various reasons, one may wish to keep several different\n" +"configurations available on a single machine.\n" +"\n" +"If you have saved a previous configuration in a file other than the\n" +"default one, entering its name here will allow you to modify that\n" +"configuration.\n" +"\n" +"If you are uncertain, then you have probably never used alternate\n" +"configuration files. You should therefor leave this blank to abort.\n"), +save_config_text[] = N_( +"Enter a filename to which this configuration should be saved\n" +"as an alternate. Leave blank to abort."), +save_config_help[] = N_( +"\n" +"For various reasons, one may wish to keep different configurations\n" +"available on a single machine.\n" +"\n" +"Entering a file name here will allow you to later retrieve, modify\n" +"and use the current configuration as an alternate to whatever\n" +"configuration options you have selected at that time.\n" +"\n" +"If you are uncertain what all this means then you should probably\n" +"leave this blank.\n"), +search_help[] = N_( +"\n" +"Search for symbols and display their relations. Regular expressions\n" +"are allowed.\n" +"Example: search for \"^FOO\"\n" +"Result:\n" +"-----------------------------------------------------------------\n" +"Symbol: FOO [ = m]\n" +"Prompt: Foo bus is used to drive the bar HW\n" +"Defined at drivers/pci/Kconfig:47\n" +"Depends on: X86_LOCAL_APIC && X86_IO_APIC || IA64\n" +"Location:\n" +" -> Bus options (PCI, PCMCIA, EISA, ISA)\n" +" -> PCI support (PCI [ = y])\n" +" -> PCI access mode ( [ = y])\n" +"Selects: LIBCRC32\n" +"Selected by: BAR\n" +"-----------------------------------------------------------------\n" +"o The line 'Prompt:' shows the text used in the menu structure for\n" +" this symbol\n" +"o The 'Defined at' line tell at what file / line number the symbol\n" +" is defined\n" +"o The 'Depends on:' line tell what symbols needs to be defined for\n" +" this symbol to be visible in the menu (selectable)\n" +"o The 'Location:' lines tell where in the menu structure this symbol\n" +" is located\n" +" A location followed by a [ = y] indicate that this is a selectable\n" +" menu item - and current value is displayed inside brackets.\n" +"o The 'Selects:' line tell what symbol will be automatically\n" +" selected if this symbol is selected (y or m)\n" +"o The 'Selected by' line tell what symbol has selected this symbol\n" +"\n" +"Only relevant lines are shown.\n" +"\n\n" +"Search examples:\n" +"Examples: USB => find all symbols containing USB\n" +" ^USB => find all symbols starting with USB\n" +" USB$ => find all symbols ending with USB\n" +"\n"); + +struct mitem { + char str[256]; + char tag; + void *usrptr; + int is_visible; +}; + +#define MAX_MENU_ITEMS 4096 +static int show_all_items; +static int indent; +static struct menu *current_menu; +static int child_count; +static int single_menu_mode; +/* the window in which all information appears */ +static WINDOW *main_window; +/* the largest size of the menu window */ +static int mwin_max_lines; +static int mwin_max_cols; +/* the window in which we show option buttons */ +static MENU *curses_menu; +static ITEM *curses_menu_items[MAX_MENU_ITEMS]; +static struct mitem k_menu_items[MAX_MENU_ITEMS]; +static int items_num; +static int global_exit; +/* the currently selected button */ +const char *current_instructions = menu_instructions; + +static char *dialog_input_result; +static int dialog_input_result_len; + +static void conf(struct menu *menu); +static void conf_choice(struct menu *menu); +static void conf_string(struct menu *menu); +static void conf_load(void); +static void conf_save(void); +static void show_help(struct menu *menu); +static int do_exit(void); +static void setup_windows(void); +static void search_conf(void); + +typedef void (*function_key_handler_t)(int *key, struct menu *menu); +static void handle_f1(int *key, struct menu *current_item); +static void handle_f2(int *key, struct menu *current_item); +static void handle_f3(int *key, struct menu *current_item); +static void handle_f4(int *key, struct menu *current_item); +static void handle_f5(int *key, struct menu *current_item); +static void handle_f6(int *key, struct menu *current_item); +static void handle_f7(int *key, struct menu *current_item); +static void handle_f8(int *key, struct menu *current_item); +static void handle_f9(int *key, struct menu *current_item); + +struct function_keys { + const char *key_str; + const char *func; + function_key key; + function_key_handler_t handler; +}; + +static const int function_keys_num = 9; +struct function_keys function_keys[] = { + { + .key_str = "F1", + .func = "Help", + .key = F_HELP, + .handler = handle_f1, + }, + { + .key_str = "F2", + .func = "Sym Info", + .key = F_SYMBOL, + .handler = handle_f2, + }, + { + .key_str = "F3", + .func = "Insts", + .key = F_INSTS, + .handler = handle_f3, + }, + { + .key_str = "F4", + .func = "Config", + .key = F_CONF, + .handler = handle_f4, + }, + { + .key_str = "F5", + .func = "Back", + .key = F_BACK, + .handler = handle_f5, + }, + { + .key_str = "F6", + .func = "Save", + .key = F_SAVE, + .handler = handle_f6, + }, + { + .key_str = "F7", + .func = "Load", + .key = F_LOAD, + .handler = handle_f7, + }, + { + .key_str = "F8", + .func = "Sym Search", + .key = F_SEARCH, + .handler = handle_f8, + }, + { + .key_str = "F9", + .func = "Exit", + .key = F_EXIT, + .handler = handle_f9, + }, +}; + +static void print_function_line(void) +{ + int i; + int offset = 1; + const int skip = 1; + + for (i = 0; i < function_keys_num; i++) { + (void) wattrset(main_window, attributes[FUNCTION_HIGHLIGHT]); + mvwprintw(main_window, LINES-3, offset, + "%s", + function_keys[i].key_str); + (void) wattrset(main_window, attributes[FUNCTION_TEXT]); + offset += strlen(function_keys[i].key_str); + mvwprintw(main_window, LINES-3, + offset, "%s", + function_keys[i].func); + offset += strlen(function_keys[i].func) + skip; + } + (void) wattrset(main_window, attributes[NORMAL]); +} + +/* help */ +static void handle_f1(int *key, struct menu *current_item) +{ + show_scroll_win(main_window, + _("README"), _(nconf_readme)); + return; +} + +/* symbole help */ +static void handle_f2(int *key, struct menu *current_item) +{ + show_help(current_item); + return; +} + +/* instructions */ +static void handle_f3(int *key, struct menu *current_item) +{ + show_scroll_win(main_window, + _("Instructions"), + _(current_instructions)); + return; +} + +/* config */ +static void handle_f4(int *key, struct menu *current_item) +{ + int res = btn_dialog(main_window, + _("Show all symbols?"), + 2, + " ", + ""); + if (res == 0) + show_all_items = 1; + else if (res == 1) + show_all_items = 0; + + return; +} + +/* back */ +static void handle_f5(int *key, struct menu *current_item) +{ + *key = KEY_LEFT; + return; +} + +/* save */ +static void handle_f6(int *key, struct menu *current_item) +{ + conf_save(); + return; +} + +/* load */ +static void handle_f7(int *key, struct menu *current_item) +{ + conf_load(); + return; +} + +/* search */ +static void handle_f8(int *key, struct menu *current_item) +{ + search_conf(); + return; +} + +/* exit */ +static void handle_f9(int *key, struct menu *current_item) +{ + do_exit(); + return; +} + +/* return != 0 to indicate the key was handles */ +static int process_special_keys(int *key, struct menu *menu) +{ + int i; + + if (*key == KEY_RESIZE) { + setup_windows(); + return 1; + } + + for (i = 0; i < function_keys_num; i++) { + if (*key == KEY_F(function_keys[i].key) || + *key == '0' + function_keys[i].key){ + function_keys[i].handler(key, menu); + return 1; + } + } + + return 0; +} + +static void clean_items(void) +{ + int i; + for (i = 0; curses_menu_items[i]; i++) + free_item(curses_menu_items[i]); + bzero(curses_menu_items, sizeof(curses_menu_items)); + bzero(k_menu_items, sizeof(k_menu_items)); + items_num = 0; +} + +typedef enum {MATCH_TINKER_PATTERN_UP, MATCH_TINKER_PATTERN_DOWN, + FIND_NEXT_MATCH_DOWN, FIND_NEXT_MATCH_UP} match_f; + +/* return the index of the matched item, or -1 if no such item exists */ +static int get_mext_match(const char *match_str, match_f flag) +{ + int match_start = item_index(current_item(curses_menu)); + int index; + + if (flag == FIND_NEXT_MATCH_DOWN) + ++match_start; + else if (flag == FIND_NEXT_MATCH_UP) + --match_start; + + index = match_start; + index = (index + items_num) % items_num; + while (true) { + char *str = k_menu_items[index].str; + if (strcasestr(str, match_str) != 0) + return index; + if (flag == FIND_NEXT_MATCH_UP || + flag == MATCH_TINKER_PATTERN_UP) + --index; + else + ++index; + index = (index + items_num) % items_num; + if (index == match_start) + return -1; + } +} + +/* Make a new item. */ +static void item_make(struct menu *menu, char tag, const char *fmt, ...) +{ + va_list ap; + + if (items_num > MAX_MENU_ITEMS-1) + return; + + bzero(&k_menu_items[items_num], sizeof(k_menu_items[0])); + k_menu_items[items_num].tag = tag; + k_menu_items[items_num].usrptr = menu; + if (menu != NULL) + k_menu_items[items_num].is_visible = + menu_is_visible(menu); + else + k_menu_items[items_num].is_visible = 1; + + va_start(ap, fmt); + vsnprintf(k_menu_items[items_num].str, + sizeof(k_menu_items[items_num].str), + fmt, ap); + va_end(ap); + + if (!k_menu_items[items_num].is_visible) + memcpy(k_menu_items[items_num].str, "XXX", 3); + + curses_menu_items[items_num] = new_item( + k_menu_items[items_num].str, + k_menu_items[items_num].str); + set_item_userptr(curses_menu_items[items_num], + &k_menu_items[items_num]); + /* + if (!k_menu_items[items_num].is_visible) + item_opts_off(curses_menu_items[items_num], O_SELECTABLE); + */ + + items_num++; + curses_menu_items[items_num] = NULL; +} + +/* very hackish. adds a string to the last item added */ +static void item_add_str(const char *fmt, ...) +{ + va_list ap; + int index = items_num-1; + char new_str[256]; + char tmp_str[256]; + + if (index < 0) + return; + + va_start(ap, fmt); + vsnprintf(new_str, sizeof(new_str), fmt, ap); + va_end(ap); + snprintf(tmp_str, sizeof(tmp_str), "%s%s", + k_menu_items[index].str, new_str); + strncpy(k_menu_items[index].str, + tmp_str, + sizeof(k_menu_items[index].str)); + + free_item(curses_menu_items[index]); + curses_menu_items[index] = new_item( + k_menu_items[index].str, + k_menu_items[index].str); + set_item_userptr(curses_menu_items[index], + &k_menu_items[index]); +} + +/* get the tag of the currently selected item */ +static char item_tag(void) +{ + ITEM *cur; + struct mitem *mcur; + + cur = current_item(curses_menu); + if (cur == NULL) + return 0; + mcur = (struct mitem *) item_userptr(cur); + return mcur->tag; +} + +static int curses_item_index(void) +{ + return item_index(current_item(curses_menu)); +} + +static void *item_data(void) +{ + ITEM *cur; + struct mitem *mcur; + + cur = current_item(curses_menu); + if (!cur) + return NULL; + mcur = (struct mitem *) item_userptr(cur); + return mcur->usrptr; + +} + +static int item_is_tag(char tag) +{ + return item_tag() == tag; +} + +static char filename[PATH_MAX+1]; +static char menu_backtitle[PATH_MAX+128]; +static const char *set_config_filename(const char *config_filename) +{ + int size; + + size = snprintf(menu_backtitle, sizeof(menu_backtitle), + "%s - %s", config_filename, rootmenu.prompt->text); + if (size >= sizeof(menu_backtitle)) + menu_backtitle[sizeof(menu_backtitle)-1] = '\0'; + + size = snprintf(filename, sizeof(filename), "%s", config_filename); + if (size >= sizeof(filename)) + filename[sizeof(filename)-1] = '\0'; + return menu_backtitle; +} + +/* return = 0 means we are successful. + * -1 means go on doing what you were doing + */ +static int do_exit(void) +{ + int res; + if (!conf_get_changed()) { + global_exit = 1; + return 0; + } + res = btn_dialog(main_window, + _("Do you wish to save your new configuration?\n" + " to cancel and resume nconfig."), + 2, + " ", + ""); + if (res == KEY_EXIT) { + global_exit = 0; + return -1; + } + + /* if we got here, the user really wants to exit */ + switch (res) { + case 0: + res = conf_write(filename); + if (res) + btn_dialog( + main_window, + _("Error during writing of configuration.\n" + "Your configuration changes were NOT saved."), + 1, + ""); + break; + default: + btn_dialog( + main_window, + _("Your configuration changes were NOT saved."), + 1, + ""); + break; + } + global_exit = 1; + return 0; +} + + +static void search_conf(void) +{ + struct symbol **sym_arr; + struct gstr res; + char *dialog_input; + int dres; +again: + dres = dialog_inputbox(main_window, + _("Search Configuration Parameter"), + _("Enter " CONFIG_ " (sub)string to search for " + "(with or without \"" CONFIG_ "\")"), + "", &dialog_input_result, &dialog_input_result_len); + switch (dres) { + case 0: + break; + case 1: + show_scroll_win(main_window, + _("Search Configuration"), search_help); + goto again; + default: + return; + } + + /* strip the prefix if necessary */ + dialog_input = dialog_input_result; + if (strncasecmp(dialog_input_result, CONFIG_, strlen(CONFIG_)) == 0) + dialog_input += strlen(CONFIG_); + + sym_arr = sym_re_search(dialog_input); + res = get_relations_str(sym_arr); + free(sym_arr); + show_scroll_win(main_window, + _("Search Results"), str_get(&res)); + str_free(&res); +} + + +static void build_conf(struct menu *menu) +{ + struct symbol *sym; + struct property *prop; + struct menu *child; + int type, tmp, doint = 2; + tristate val; + char ch; + + if (!menu || (!show_all_items && !menu_is_visible(menu))) + return; + + sym = menu->sym; + prop = menu->prompt; + if (!sym) { + if (prop && menu != current_menu) { + const char *prompt = menu_get_prompt(menu); + enum prop_type ptype; + ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN; + switch (ptype) { + case P_MENU: + child_count++; + prompt = _(prompt); + if (single_menu_mode) { + item_make(menu, 'm', + "%s%*c%s", + menu->data ? "-->" : "++>", + indent + 1, ' ', prompt); + } else + item_make(menu, 'm', + " %*c%s --->", + indent + 1, + ' ', prompt); + + if (single_menu_mode && menu->data) + goto conf_childs; + return; + case P_COMMENT: + if (prompt) { + child_count++; + item_make(menu, ':', + " %*c*** %s ***", + indent + 1, ' ', + _(prompt)); + } + break; + default: + if (prompt) { + child_count++; + item_make(menu, ':', "---%*c%s", + indent + 1, ' ', + _(prompt)); + } + } + } else + doint = 0; + goto conf_childs; + } + + type = sym_get_type(sym); + if (sym_is_choice(sym)) { + struct symbol *def_sym = sym_get_choice_value(sym); + struct menu *def_menu = NULL; + + child_count++; + for (child = menu->list; child; child = child->next) { + if (menu_is_visible(child) && child->sym == def_sym) + def_menu = child; + } + + val = sym_get_tristate_value(sym); + if (sym_is_changable(sym)) { + switch (type) { + case S_BOOLEAN: + item_make(menu, 't', "[%c]", + val == no ? ' ' : '*'); + break; + case S_TRISTATE: + switch (val) { + case yes: + ch = '*'; + break; + case mod: + ch = 'M'; + break; + default: + ch = ' '; + break; + } + item_make(menu, 't', "<%c>", ch); + break; + } + } else { + item_make(menu, def_menu ? 't' : ':', " "); + } + + item_add_str("%*c%s", indent + 1, + ' ', _(menu_get_prompt(menu))); + if (val == yes) { + if (def_menu) { + item_add_str(" (%s)", + _(menu_get_prompt(def_menu))); + item_add_str(" --->"); + if (def_menu->list) { + indent += 2; + build_conf(def_menu); + indent -= 2; + } + } + return; + } + } else { + if (menu == current_menu) { + item_make(menu, ':', + "---%*c%s", indent + 1, + ' ', _(menu_get_prompt(menu))); + goto conf_childs; + } + child_count++; + val = sym_get_tristate_value(sym); + if (sym_is_choice_value(sym) && val == yes) { + item_make(menu, ':', " "); + } else { + switch (type) { + case S_BOOLEAN: + if (sym_is_changable(sym)) + item_make(menu, 't', "[%c]", + val == no ? ' ' : '*'); + else + item_make(menu, 't', "-%c-", + val == no ? ' ' : '*'); + break; + case S_TRISTATE: + switch (val) { + case yes: + ch = '*'; + break; + case mod: + ch = 'M'; + break; + default: + ch = ' '; + break; + } + if (sym_is_changable(sym)) { + if (sym->rev_dep.tri == mod) + item_make(menu, + 't', "{%c}", ch); + else + item_make(menu, + 't', "<%c>", ch); + } else + item_make(menu, 't', "-%c-", ch); + break; + default: + tmp = 2 + strlen(sym_get_string_value(sym)); + item_make(menu, 's', " (%s)", + sym_get_string_value(sym)); + tmp = indent - tmp + 4; + if (tmp < 0) + tmp = 0; + item_add_str("%*c%s%s", tmp, ' ', + _(menu_get_prompt(menu)), + (sym_has_value(sym) || + !sym_is_changable(sym)) ? "" : + _(" (NEW)")); + goto conf_childs; + } + } + item_add_str("%*c%s%s", indent + 1, ' ', + _(menu_get_prompt(menu)), + (sym_has_value(sym) || !sym_is_changable(sym)) ? + "" : _(" (NEW)")); + if (menu->prompt && menu->prompt->type == P_MENU) { + item_add_str(" --->"); + return; + } + } + +conf_childs: + indent += doint; + for (child = menu->list; child; child = child->next) + build_conf(child); + indent -= doint; +} + +static void reset_menu(void) +{ + unpost_menu(curses_menu); + clean_items(); +} + +/* adjust the menu to show this item. + * prefer not to scroll the menu if possible*/ +static void center_item(int selected_index, int *last_top_row) +{ + int toprow; + + set_top_row(curses_menu, *last_top_row); + toprow = top_row(curses_menu); + if (selected_index < toprow || + selected_index >= toprow+mwin_max_lines) { + toprow = max(selected_index-mwin_max_lines/2, 0); + if (toprow >= item_count(curses_menu)-mwin_max_lines) + toprow = item_count(curses_menu)-mwin_max_lines; + set_top_row(curses_menu, toprow); + } + set_current_item(curses_menu, + curses_menu_items[selected_index]); + *last_top_row = toprow; + post_menu(curses_menu); + refresh_all_windows(main_window); +} + +/* this function assumes reset_menu has been called before */ +static void show_menu(const char *prompt, const char *instructions, + int selected_index, int *last_top_row) +{ + int maxx, maxy; + WINDOW *menu_window; + + current_instructions = instructions; + + clear(); + (void) wattrset(main_window, attributes[NORMAL]); + print_in_middle(stdscr, 1, 0, COLS, + menu_backtitle, + attributes[MAIN_HEADING]); + + (void) wattrset(main_window, attributes[MAIN_MENU_BOX]); + box(main_window, 0, 0); + (void) wattrset(main_window, attributes[MAIN_MENU_HEADING]); + mvwprintw(main_window, 0, 3, " %s ", prompt); + (void) wattrset(main_window, attributes[NORMAL]); + + set_menu_items(curses_menu, curses_menu_items); + + /* position the menu at the middle of the screen */ + scale_menu(curses_menu, &maxy, &maxx); + maxx = min(maxx, mwin_max_cols-2); + maxy = mwin_max_lines; + menu_window = derwin(main_window, + maxy, + maxx, + 2, + (mwin_max_cols-maxx)/2); + keypad(menu_window, TRUE); + set_menu_win(curses_menu, menu_window); + set_menu_sub(curses_menu, menu_window); + + /* must reassert this after changing items, otherwise returns to a + * default of 16 + */ + set_menu_format(curses_menu, maxy, 1); + center_item(selected_index, last_top_row); + set_menu_format(curses_menu, maxy, 1); + + print_function_line(); + + /* Post the menu */ + post_menu(curses_menu); + refresh_all_windows(main_window); +} + +static void adj_match_dir(match_f *match_direction) +{ + if (*match_direction == FIND_NEXT_MATCH_DOWN) + *match_direction = + MATCH_TINKER_PATTERN_DOWN; + else if (*match_direction == FIND_NEXT_MATCH_UP) + *match_direction = + MATCH_TINKER_PATTERN_UP; + /* else, do no change.. */ +} + +struct match_state +{ + int in_search; + match_f match_direction; + char pattern[256]; +}; + +/* Return 0 means I have handled the key. In such a case, ans should hold the + * item to center, or -1 otherwise. + * Else return -1 . + */ +static int do_match(int key, struct match_state *state, int *ans) +{ + char c = (char) key; + int terminate_search = 0; + *ans = -1; + if (key == '/' || (state->in_search && key == 27)) { + move(0, 0); + refresh(); + clrtoeol(); + state->in_search = 1-state->in_search; + bzero(state->pattern, sizeof(state->pattern)); + state->match_direction = MATCH_TINKER_PATTERN_DOWN; + return 0; + } else if (!state->in_search) + return 1; + + if (isalnum(c) || isgraph(c) || c == ' ') { + state->pattern[strlen(state->pattern)] = c; + state->pattern[strlen(state->pattern)] = '\0'; + adj_match_dir(&state->match_direction); + *ans = get_mext_match(state->pattern, + state->match_direction); + } else if (key == KEY_DOWN) { + state->match_direction = FIND_NEXT_MATCH_DOWN; + *ans = get_mext_match(state->pattern, + state->match_direction); + } else if (key == KEY_UP) { + state->match_direction = FIND_NEXT_MATCH_UP; + *ans = get_mext_match(state->pattern, + state->match_direction); + } else if (key == KEY_BACKSPACE || key == 127) { + state->pattern[strlen(state->pattern)-1] = '\0'; + adj_match_dir(&state->match_direction); + } else + terminate_search = 1; + + if (terminate_search) { + state->in_search = 0; + bzero(state->pattern, sizeof(state->pattern)); + move(0, 0); + refresh(); + clrtoeol(); + return -1; + } + return 0; +} + +static void conf(struct menu *menu) +{ + struct menu *submenu = 0; + const char *prompt = menu_get_prompt(menu); + struct symbol *sym; + int res; + int current_index = 0; + int last_top_row = 0; + struct match_state match_state = { + .in_search = 0, + .match_direction = MATCH_TINKER_PATTERN_DOWN, + .pattern = "", + }; + + while (!global_exit) { + reset_menu(); + current_menu = menu; + build_conf(menu); + if (!child_count) + break; + + show_menu(prompt ? _(prompt) : _("Main Menu"), + _(menu_instructions), + current_index, &last_top_row); + keypad((menu_win(curses_menu)), TRUE); + while (!global_exit) { + if (match_state.in_search) { + mvprintw(0, 0, + "searching: %s", match_state.pattern); + clrtoeol(); + } + refresh_all_windows(main_window); + res = wgetch(menu_win(curses_menu)); + if (!res) + break; + if (do_match(res, &match_state, ¤t_index) == 0) { + if (current_index != -1) + center_item(current_index, + &last_top_row); + continue; + } + if (process_special_keys(&res, + (struct menu *) item_data())) + break; + switch (res) { + case KEY_DOWN: + menu_driver(curses_menu, REQ_DOWN_ITEM); + break; + case KEY_UP: + menu_driver(curses_menu, REQ_UP_ITEM); + break; + case KEY_NPAGE: + menu_driver(curses_menu, REQ_SCR_DPAGE); + break; + case KEY_PPAGE: + menu_driver(curses_menu, REQ_SCR_UPAGE); + break; + case KEY_HOME: + menu_driver(curses_menu, REQ_FIRST_ITEM); + break; + case KEY_END: + menu_driver(curses_menu, REQ_LAST_ITEM); + break; + case 'h': + case '?': + show_help((struct menu *) item_data()); + break; + } + if (res == 10 || res == 27 || + res == 32 || res == 'n' || res == 'y' || + res == KEY_LEFT || res == KEY_RIGHT || + res == 'm') + break; + refresh_all_windows(main_window); + } + + refresh_all_windows(main_window); + /* if ESC or left*/ + if (res == 27 || (menu != &rootmenu && res == KEY_LEFT)) + break; + + /* remember location in the menu */ + last_top_row = top_row(curses_menu); + current_index = curses_item_index(); + + if (!item_tag()) + continue; + + submenu = (struct menu *) item_data(); + if (!submenu || !menu_is_visible(submenu)) + continue; + sym = submenu->sym; + + switch (res) { + case ' ': + if (item_is_tag('t')) + sym_toggle_tristate_value(sym); + else if (item_is_tag('m')) + conf(submenu); + break; + case KEY_RIGHT: + case 10: /* ENTER WAS PRESSED */ + switch (item_tag()) { + case 'm': + if (single_menu_mode) + submenu->data = + (void *) (long) !submenu->data; + else + conf(submenu); + break; + case 't': + if (sym_is_choice(sym) && + sym_get_tristate_value(sym) == yes) + conf_choice(submenu); + else if (submenu->prompt && + submenu->prompt->type == P_MENU) + conf(submenu); + else if (res == 10) + sym_toggle_tristate_value(sym); + break; + case 's': + conf_string(submenu); + break; + } + break; + case 'y': + if (item_is_tag('t')) { + if (sym_set_tristate_value(sym, yes)) + break; + if (sym_set_tristate_value(sym, mod)) + btn_dialog(main_window, setmod_text, 0); + } + break; + case 'n': + if (item_is_tag('t')) + sym_set_tristate_value(sym, no); + break; + case 'm': + if (item_is_tag('t')) + sym_set_tristate_value(sym, mod); + break; + } + } +} + +static void conf_message_callback(const char *fmt, va_list ap) +{ + char buf[1024]; + + vsnprintf(buf, sizeof(buf), fmt, ap); + btn_dialog(main_window, buf, 1, ""); +} + +static void show_help(struct menu *menu) +{ + struct gstr help; + + if (!menu) + return; + + help = str_new(); + menu_get_ext_help(menu, &help); + show_scroll_win(main_window, _(menu_get_prompt(menu)), str_get(&help)); + str_free(&help); +} + +static void conf_choice(struct menu *menu) +{ + const char *prompt = _(menu_get_prompt(menu)); + struct menu *child = 0; + struct symbol *active; + int selected_index = 0; + int last_top_row = 0; + int res, i = 0; + struct match_state match_state = { + .in_search = 0, + .match_direction = MATCH_TINKER_PATTERN_DOWN, + .pattern = "", + }; + + active = sym_get_choice_value(menu->sym); + /* this is mostly duplicated from the conf() function. */ + while (!global_exit) { + reset_menu(); + + for (i = 0, child = menu->list; child; child = child->next) { + if (!show_all_items && !menu_is_visible(child)) + continue; + + if (child->sym == sym_get_choice_value(menu->sym)) + item_make(child, ':', " %s", + _(menu_get_prompt(child))); + else if (child->sym) + item_make(child, ':', " %s", + _(menu_get_prompt(child))); + else + item_make(child, ':', "*** %s ***", + _(menu_get_prompt(child))); + + if (child->sym == active){ + last_top_row = top_row(curses_menu); + selected_index = i; + } + i++; + } + show_menu(prompt ? _(prompt) : _("Choice Menu"), + _(radiolist_instructions), + selected_index, + &last_top_row); + while (!global_exit) { + if (match_state.in_search) { + mvprintw(0, 0, "searching: %s", + match_state.pattern); + clrtoeol(); + } + refresh_all_windows(main_window); + res = wgetch(menu_win(curses_menu)); + if (!res) + break; + if (do_match(res, &match_state, &selected_index) == 0) { + if (selected_index != -1) + center_item(selected_index, + &last_top_row); + continue; + } + if (process_special_keys( + &res, + (struct menu *) item_data())) + break; + switch (res) { + case KEY_DOWN: + menu_driver(curses_menu, REQ_DOWN_ITEM); + break; + case KEY_UP: + menu_driver(curses_menu, REQ_UP_ITEM); + break; + case KEY_NPAGE: + menu_driver(curses_menu, REQ_SCR_DPAGE); + break; + case KEY_PPAGE: + menu_driver(curses_menu, REQ_SCR_UPAGE); + break; + case KEY_HOME: + menu_driver(curses_menu, REQ_FIRST_ITEM); + break; + case KEY_END: + menu_driver(curses_menu, REQ_LAST_ITEM); + break; + case 'h': + case '?': + show_help((struct menu *) item_data()); + break; + } + if (res == 10 || res == 27 || res == ' ' || + res == KEY_LEFT){ + break; + } + refresh_all_windows(main_window); + } + /* if ESC or left */ + if (res == 27 || res == KEY_LEFT) + break; + + child = item_data(); + if (!child || !menu_is_visible(child) || !child->sym) + continue; + switch (res) { + case ' ': + case 10: + case KEY_RIGHT: + sym_set_tristate_value(child->sym, yes); + return; + case 'h': + case '?': + show_help(child); + active = child->sym; + break; + case KEY_EXIT: + return; + } + } +} + +static void conf_string(struct menu *menu) +{ + const char *prompt = menu_get_prompt(menu); + + while (1) { + int res; + const char *heading; + + switch (sym_get_type(menu->sym)) { + case S_INT: + heading = _(inputbox_instructions_int); + break; + case S_HEX: + heading = _(inputbox_instructions_hex); + break; + case S_STRING: + heading = _(inputbox_instructions_string); + break; + default: + heading = _("Internal nconf error!"); + } + res = dialog_inputbox(main_window, + prompt ? _(prompt) : _("Main Menu"), + heading, + sym_get_string_value(menu->sym), + &dialog_input_result, + &dialog_input_result_len); + switch (res) { + case 0: + if (sym_set_string_value(menu->sym, + dialog_input_result)) + return; + btn_dialog(main_window, + _("You have made an invalid entry."), 0); + break; + case 1: + show_help(menu); + break; + case KEY_EXIT: + return; + } + } +} + +static void conf_load(void) +{ + while (1) { + int res; + res = dialog_inputbox(main_window, + NULL, load_config_text, + filename, + &dialog_input_result, + &dialog_input_result_len); + switch (res) { + case 0: + if (!dialog_input_result[0]) + return; + if (!conf_read(dialog_input_result)) { + set_config_filename(dialog_input_result); + sym_set_change_count(1); + return; + } + btn_dialog(main_window, _("File does not exist!"), 0); + break; + case 1: + show_scroll_win(main_window, + _("Load Alternate Configuration"), + load_config_help); + break; + case KEY_EXIT: + return; + } + } +} + +static void conf_save(void) +{ + while (1) { + int res; + res = dialog_inputbox(main_window, + NULL, save_config_text, + filename, + &dialog_input_result, + &dialog_input_result_len); + switch (res) { + case 0: + if (!dialog_input_result[0]) + return; + res = conf_write(dialog_input_result); + if (!res) { + set_config_filename(dialog_input_result); + return; + } + btn_dialog(main_window, _("Can't create file! " + "Probably a nonexistent directory."), + 1, ""); + break; + case 1: + show_scroll_win(main_window, + _("Save Alternate Configuration"), + save_config_help); + break; + case KEY_EXIT: + return; + } + } +} + +void setup_windows(void) +{ + if (main_window != NULL) + delwin(main_window); + + /* set up the menu and menu window */ + main_window = newwin(LINES-2, COLS-2, 2, 1); + keypad(main_window, TRUE); + mwin_max_lines = LINES-7; + mwin_max_cols = COLS-6; + + /* panels order is from bottom to top */ + new_panel(main_window); +} + +int main(int ac, char **av) +{ + char *mode; + + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + + conf_parse(av[1]); + conf_read(NULL); + + mode = getenv("NCONFIG_MODE"); + if (mode) { + if (!strcasecmp(mode, "single_menu")) + single_menu_mode = 1; + } + + /* Initialize curses */ + initscr(); + /* set color theme */ + set_colors(); + + cbreak(); + noecho(); + keypad(stdscr, TRUE); + curs_set(0); + + if (COLS < 75 || LINES < 20) { + endwin(); + printf("Your terminal should have at " + "least 20 lines and 75 columns\n"); + return 1; + } + + notimeout(stdscr, FALSE); + ESCDELAY = 1; + + /* set btns menu */ + curses_menu = new_menu(curses_menu_items); + menu_opts_off(curses_menu, O_SHOWDESC); + menu_opts_on(curses_menu, O_SHOWMATCH); + menu_opts_on(curses_menu, O_ONEVALUE); + menu_opts_on(curses_menu, O_NONCYCLIC); + menu_opts_on(curses_menu, O_IGNORECASE); + set_menu_mark(curses_menu, " "); + set_menu_fore(curses_menu, attributes[MAIN_MENU_FORE]); + set_menu_back(curses_menu, attributes[MAIN_MENU_BACK]); + set_menu_grey(curses_menu, attributes[MAIN_MENU_GREY]); + + set_config_filename(conf_get_configname()); + setup_windows(); + + /* check for KEY_FUNC(1) */ + if (has_key(KEY_F(1)) == FALSE) { + show_scroll_win(main_window, + _("Instructions"), + _(menu_no_f_instructions)); + } + + conf_set_message_callback(conf_message_callback); + /* do the work */ + while (!global_exit) { + conf(&rootmenu); + if (!global_exit && do_exit() == 0) + break; + } + /* ok, we are done */ + unpost_menu(curses_menu); + free_menu(curses_menu); + delwin(main_window); + clear(); + refresh(); + endwin(); + return 0; +} + diff --git a/kernel/fiasco/tool/kconfig/scripts/kconfig/nconf.gui.c b/kernel/fiasco/tool/kconfig/scripts/kconfig/nconf.gui.c new file mode 100644 index 00000000..3b18dd83 --- /dev/null +++ b/kernel/fiasco/tool/kconfig/scripts/kconfig/nconf.gui.c @@ -0,0 +1,652 @@ +/* + * Copyright (C) 2008 Nir Tzachar 0) + win_rows = msg_lines+4; + else + win_rows = msg_lines+2; + + win = newwin(win_rows, total_width+4, y, x); + keypad(win, TRUE); + menu_win = derwin(win, 1, btns_width, win_rows-2, + 1+(total_width+2-btns_width)/2); + menu = new_menu(btns); + msg_win = derwin(win, win_rows-2, msg_width, 1, + 1+(total_width+2-msg_width)/2); + + set_menu_fore(menu, attributes[DIALOG_MENU_FORE]); + set_menu_back(menu, attributes[DIALOG_MENU_BACK]); + + (void) wattrset(win, attributes[DIALOG_BOX]); + box(win, 0, 0); + + /* print message */ + (void) wattrset(msg_win, attributes[DIALOG_TEXT]); + fill_window(msg_win, msg); + + set_menu_win(menu, win); + set_menu_sub(menu, menu_win); + set_menu_format(menu, 1, btn_num); + menu_opts_off(menu, O_SHOWDESC); + menu_opts_off(menu, O_SHOWMATCH); + menu_opts_on(menu, O_ONEVALUE); + menu_opts_on(menu, O_NONCYCLIC); + set_menu_mark(menu, ""); + post_menu(menu); + + + touchwin(win); + refresh_all_windows(main_window); + while ((res = wgetch(win))) { + switch (res) { + case KEY_LEFT: + menu_driver(menu, REQ_LEFT_ITEM); + break; + case KEY_RIGHT: + menu_driver(menu, REQ_RIGHT_ITEM); + break; + case 10: /* ENTER */ + case 27: /* ESCAPE */ + case ' ': + case KEY_F(F_BACK): + case KEY_F(F_EXIT): + break; + } + touchwin(win); + refresh_all_windows(main_window); + + if (res == 10 || res == ' ') { + res = item_index(current_item(menu)); + break; + } else if (res == 27 || res == KEY_F(F_BACK) || + res == KEY_F(F_EXIT)) { + res = KEY_EXIT; + break; + } + } + + unpost_menu(menu); + free_menu(menu); + for (i = 0; i < btn_num; i++) + free_item(btns[i]); + + delwin(win); + return res; +} + +int dialog_inputbox(WINDOW *main_window, + const char *title, const char *prompt, + const char *init, char **resultp, int *result_len) +{ + int prompt_lines = 0; + int prompt_width = 0; + WINDOW *win; + WINDOW *prompt_win; + WINDOW *form_win; + PANEL *panel; + int i, x, y; + int res = -1; + int cursor_position = strlen(init); + int cursor_form_win; + char *result = *resultp; + + if (strlen(init)+1 > *result_len) { + *result_len = strlen(init)+1; + *resultp = result = realloc(result, *result_len); + } + + /* find the widest line of msg: */ + prompt_lines = get_line_no(prompt); + for (i = 0; i < prompt_lines; i++) { + const char *line = get_line(prompt, i); + int len = get_line_length(line); + prompt_width = max(prompt_width, len); + } + + if (title) + prompt_width = max(prompt_width, strlen(title)); + + /* place dialog in middle of screen */ + y = (LINES-(prompt_lines+4))/2; + x = (COLS-(prompt_width+4))/2; + + strncpy(result, init, *result_len); + + /* create the windows */ + win = newwin(prompt_lines+6, prompt_width+7, y, x); + prompt_win = derwin(win, prompt_lines+1, prompt_width, 2, 2); + form_win = derwin(win, 1, prompt_width, prompt_lines+3, 2); + keypad(form_win, TRUE); + + (void) wattrset(form_win, attributes[INPUT_FIELD]); + + (void) wattrset(win, attributes[INPUT_BOX]); + box(win, 0, 0); + (void) wattrset(win, attributes[INPUT_HEADING]); + if (title) + mvwprintw(win, 0, 3, "%s", title); + + /* print message */ + (void) wattrset(prompt_win, attributes[INPUT_TEXT]); + fill_window(prompt_win, prompt); + + mvwprintw(form_win, 0, 0, "%*s", prompt_width, " "); + cursor_form_win = min(cursor_position, prompt_width-1); + mvwprintw(form_win, 0, 0, "%s", + result + cursor_position-cursor_form_win); + + /* create panels */ + panel = new_panel(win); + + /* show the cursor */ + curs_set(1); + + touchwin(win); + refresh_all_windows(main_window); + while ((res = wgetch(form_win))) { + int len = strlen(result); + switch (res) { + case 10: /* ENTER */ + case 27: /* ESCAPE */ + case KEY_F(F_HELP): + case KEY_F(F_EXIT): + case KEY_F(F_BACK): + break; + case 127: + case KEY_BACKSPACE: + if (cursor_position > 0) { + memmove(&result[cursor_position-1], + &result[cursor_position], + len-cursor_position+1); + cursor_position--; + cursor_form_win--; + len--; + } + break; + case KEY_DC: + if (cursor_position >= 0 && cursor_position < len) { + memmove(&result[cursor_position], + &result[cursor_position+1], + len-cursor_position+1); + len--; + } + break; + case KEY_UP: + case KEY_RIGHT: + if (cursor_position < len) { + cursor_position++; + cursor_form_win++; + } + break; + case KEY_DOWN: + case KEY_LEFT: + if (cursor_position > 0) { + cursor_position--; + cursor_form_win--; + } + break; + case KEY_HOME: + cursor_position = 0; + cursor_form_win = 0; + break; + case KEY_END: + cursor_position = len; + cursor_form_win = min(cursor_position, prompt_width-1); + break; + default: + if ((isgraph(res) || isspace(res))) { + /* one for new char, one for '\0' */ + if (len+2 > *result_len) { + *result_len = len+2; + *resultp = result = realloc(result, + *result_len); + } + /* insert the char at the proper position */ + memmove(&result[cursor_position+1], + &result[cursor_position], + len-cursor_position+1); + result[cursor_position] = res; + cursor_position++; + cursor_form_win++; + len++; + } else { + mvprintw(0, 0, "unknown key: %d\n", res); + } + break; + } + if (cursor_form_win < 0) + cursor_form_win = 0; + else if (cursor_form_win > prompt_width-1) + cursor_form_win = prompt_width-1; + + wmove(form_win, 0, 0); + wclrtoeol(form_win); + mvwprintw(form_win, 0, 0, "%*s", prompt_width, " "); + mvwprintw(form_win, 0, 0, "%s", + result + cursor_position-cursor_form_win); + wmove(form_win, 0, cursor_form_win); + touchwin(win); + refresh_all_windows(main_window); + + if (res == 10) { + res = 0; + break; + } else if (res == 27 || res == KEY_F(F_BACK) || + res == KEY_F(F_EXIT)) { + res = KEY_EXIT; + break; + } else if (res == KEY_F(F_HELP)) { + res = 1; + break; + } + } + + /* hide the cursor */ + curs_set(0); + del_panel(panel); + delwin(prompt_win); + delwin(form_win); + delwin(win); + return res; +} + +/* refresh all windows in the correct order */ +void refresh_all_windows(WINDOW *main_window) +{ + update_panels(); + touchwin(main_window); + refresh(); +} + +/* layman's scrollable window... */ +void show_scroll_win(WINDOW *main_window, + const char *title, + const char *text) +{ + int res; + int total_lines = get_line_no(text); + int x, y; + int start_x = 0, start_y = 0; + int text_lines = 0, text_cols = 0; + int total_cols = 0; + int win_cols = 0; + int win_lines = 0; + int i = 0; + WINDOW *win; + WINDOW *pad; + PANEL *panel; + + /* find the widest line of msg: */ + total_lines = get_line_no(text); + for (i = 0; i < total_lines; i++) { + const char *line = get_line(text, i); + int len = get_line_length(line); + total_cols = max(total_cols, len+2); + } + + /* create the pad */ + pad = newpad(total_lines+10, total_cols+10); + (void) wattrset(pad, attributes[SCROLLWIN_TEXT]); + fill_window(pad, text); + + win_lines = min(total_lines+4, LINES-2); + win_cols = min(total_cols+2, COLS-2); + text_lines = max(win_lines-4, 0); + text_cols = max(win_cols-2, 0); + + /* place window in middle of screen */ + y = (LINES-win_lines)/2; + x = (COLS-win_cols)/2; + + win = newwin(win_lines, win_cols, y, x); + keypad(win, TRUE); + /* show the help in the help window, and show the help panel */ + (void) wattrset(win, attributes[SCROLLWIN_BOX]); + box(win, 0, 0); + (void) wattrset(win, attributes[SCROLLWIN_HEADING]); + mvwprintw(win, 0, 3, " %s ", title); + panel = new_panel(win); + + /* handle scrolling */ + do { + + copywin(pad, win, start_y, start_x, 2, 2, text_lines, + text_cols, 0); + print_in_middle(win, + text_lines+2, + 0, + text_cols, + "", + attributes[DIALOG_MENU_FORE]); + wrefresh(win); + + res = wgetch(win); + switch (res) { + case KEY_NPAGE: + case ' ': + start_y += text_lines-2; + break; + case KEY_PPAGE: + start_y -= text_lines+2; + break; + case KEY_HOME: + start_y = 0; + break; + case KEY_END: + start_y = total_lines-text_lines; + break; + case KEY_DOWN: + case 'j': + start_y++; + break; + case KEY_UP: + case 'k': + start_y--; + break; + case KEY_LEFT: + case 'h': + start_x--; + break; + case KEY_RIGHT: + case 'l': + start_x++; + break; + } + if (res == 10 || res == 27 || res == 'q' + || res == KEY_F(F_BACK) || res == KEY_F(F_EXIT)) { + break; + } + if (start_y < 0) + start_y = 0; + if (start_y >= total_lines-text_lines) + start_y = total_lines-text_lines; + if (start_x < 0) + start_x = 0; + if (start_x >= total_cols-text_cols) + start_x = total_cols-text_cols; + } while (res); + + del_panel(panel); + delwin(win); + refresh_all_windows(main_window); +} diff --git a/kernel/fiasco/tool/kconfig/scripts/kconfig/nconf.h b/kernel/fiasco/tool/kconfig/scripts/kconfig/nconf.h new file mode 100644 index 00000000..0d526170 --- /dev/null +++ b/kernel/fiasco/tool/kconfig/scripts/kconfig/nconf.h @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2008 Nir Tzachar +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "ncurses.h" + +#define max(a, b) ({\ + typeof(a) _a = a;\ + typeof(b) _b = b;\ + _a > _b ? _a : _b; }) + +#define min(a, b) ({\ + typeof(a) _a = a;\ + typeof(b) _b = b;\ + _a < _b ? _a : _b; }) + +typedef enum { + NORMAL = 1, + MAIN_HEADING, + MAIN_MENU_BOX, + MAIN_MENU_FORE, + MAIN_MENU_BACK, + MAIN_MENU_GREY, + MAIN_MENU_HEADING, + SCROLLWIN_TEXT, + SCROLLWIN_HEADING, + SCROLLWIN_BOX, + DIALOG_TEXT, + DIALOG_MENU_FORE, + DIALOG_MENU_BACK, + DIALOG_BOX, + INPUT_BOX, + INPUT_HEADING, + INPUT_TEXT, + INPUT_FIELD, + FUNCTION_TEXT, + FUNCTION_HIGHLIGHT, + ATTR_MAX +} attributes_t; +extern attributes_t attributes[]; + +typedef enum { + F_HELP = 1, + F_SYMBOL = 2, + F_INSTS = 3, + F_CONF = 4, + F_BACK = 5, + F_SAVE = 6, + F_LOAD = 7, + F_SEARCH = 8, + F_EXIT = 9, +} function_key; + +void set_colors(void); + +/* this changes the windows attributes !!! */ +void print_in_middle(WINDOW *win, + int starty, + int startx, + int width, + const char *string, + chtype color); +int get_line_length(const char *line); +int get_line_no(const char *text); +const char *get_line(const char *text, int line_no); +void fill_window(WINDOW *win, const char *text); +int btn_dialog(WINDOW *main_window, const char *msg, int btn_num, ...); +int dialog_inputbox(WINDOW *main_window, + const char *title, const char *prompt, + const char *init, char **resultp, int *result_len); +void refresh_all_windows(WINDOW *main_window); +void show_scroll_win(WINDOW *main_window, + const char *title, + const char *text); diff --git a/kernel/fiasco/tool/kconfig/scripts/kconfig/qconf.cc b/kernel/fiasco/tool/kconfig/scripts/kconfig/qconf.cc new file mode 100644 index 00000000..df274feb --- /dev/null +++ b/kernel/fiasco/tool/kconfig/scripts/kconfig/qconf.cc @@ -0,0 +1,1789 @@ +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +#include + +#if QT_VERSION < 0x040000 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#else +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "lkc.h" +#include "qconf.h" + +#include "qconf.moc" +#include "images.c" + +#ifdef _ +# undef _ +# define _ qgettext +#endif + +static QApplication *configApp; +static ConfigSettings *configSettings; + +Q3Action *ConfigMainWindow::saveAction; + +static inline QString qgettext(const char* str) +{ + return QString::fromLocal8Bit(gettext(str)); +} + +static inline QString qgettext(const QString& str) +{ + return QString::fromLocal8Bit(gettext(str.latin1())); +} + +/** + * Reads a list of integer values from the application settings. + */ +Q3ValueList ConfigSettings::readSizes(const QString& key, bool *ok) +{ + Q3ValueList result; + QStringList entryList = readListEntry(key, ok); + QStringList::Iterator it; + + for (it = entryList.begin(); it != entryList.end(); ++it) + result.push_back((*it).toInt()); + + return result; +} + +/** + * Writes a list of integer values to the application settings. + */ +bool ConfigSettings::writeSizes(const QString& key, const Q3ValueList& value) +{ + QStringList stringList; + Q3ValueList::ConstIterator it; + + for (it = value.begin(); it != value.end(); ++it) + stringList.push_back(QString::number(*it)); + return writeEntry(key, stringList); +} + + +/* + * set the new data + * TODO check the value + */ +void ConfigItem::okRename(int col) +{ + Parent::okRename(col); + sym_set_string_value(menu->sym, text(dataColIdx).latin1()); + listView()->updateList(this); +} + +/* + * update the displayed of a menu entry + */ +void ConfigItem::updateMenu(void) +{ + ConfigList* list; + struct symbol* sym; + struct property *prop; + QString prompt; + int type; + tristate expr; + + list = listView(); + if (goParent) { + setPixmap(promptColIdx, list->menuBackPix); + prompt = ".."; + goto set_prompt; + } + + sym = menu->sym; + prop = menu->prompt; + prompt = _(menu_get_prompt(menu)); + + if (prop) switch (prop->type) { + case P_MENU: + if (list->mode == singleMode || list->mode == symbolMode) { + /* a menuconfig entry is displayed differently + * depending whether it's at the view root or a child. + */ + if (sym && list->rootEntry == menu) + break; + setPixmap(promptColIdx, list->menuPix); + } else { + if (sym) + break; + setPixmap(promptColIdx, 0); + } + goto set_prompt; + case P_COMMENT: + setPixmap(promptColIdx, 0); + goto set_prompt; + default: + ; + } + if (!sym) + goto set_prompt; + + setText(nameColIdx, QString::fromLocal8Bit(sym->name)); + + type = sym_get_type(sym); + switch (type) { + case S_BOOLEAN: + case S_TRISTATE: + char ch; + + if (!sym_is_changable(sym) && list->optMode == normalOpt) { + setPixmap(promptColIdx, 0); + setText(noColIdx, QString::null); + setText(modColIdx, QString::null); + setText(yesColIdx, QString::null); + break; + } + expr = sym_get_tristate_value(sym); + switch (expr) { + case yes: + if (sym_is_choice_value(sym) && type == S_BOOLEAN) + setPixmap(promptColIdx, list->choiceYesPix); + else + setPixmap(promptColIdx, list->symbolYesPix); + setText(yesColIdx, "Y"); + ch = 'Y'; + break; + case mod: + setPixmap(promptColIdx, list->symbolModPix); + setText(modColIdx, "M"); + ch = 'M'; + break; + default: + if (sym_is_choice_value(sym) && type == S_BOOLEAN) + setPixmap(promptColIdx, list->choiceNoPix); + else + setPixmap(promptColIdx, list->symbolNoPix); + setText(noColIdx, "N"); + ch = 'N'; + break; + } + if (expr != no) + setText(noColIdx, sym_tristate_within_range(sym, no) ? "_" : 0); + if (expr != mod) + setText(modColIdx, sym_tristate_within_range(sym, mod) ? "_" : 0); + if (expr != yes) + setText(yesColIdx, sym_tristate_within_range(sym, yes) ? "_" : 0); + + setText(dataColIdx, QChar(ch)); + break; + case S_INT: + case S_HEX: + case S_STRING: + const char* data; + + data = sym_get_string_value(sym); + + int i = list->mapIdx(dataColIdx); + if (i >= 0) + setRenameEnabled(i, TRUE); + setText(dataColIdx, data); + if (type == S_STRING) + prompt = QString("%1: %2").arg(prompt).arg(data); + else + prompt = QString("(%2) %1").arg(prompt).arg(data); + break; + } + if (!sym_has_value(sym) && visible) + prompt += _(" (NEW)"); +set_prompt: + setText(promptColIdx, prompt); +} + +void ConfigItem::testUpdateMenu(bool v) +{ + ConfigItem* i; + + visible = v; + if (!menu) + return; + + sym_calc_value(menu->sym); + if (menu->flags & MENU_CHANGED) { + /* the menu entry changed, so update all list items */ + menu->flags &= ~MENU_CHANGED; + for (i = (ConfigItem*)menu->data; i; i = i->nextItem) + i->updateMenu(); + } else if (listView()->updateAll) + updateMenu(); +} + +void ConfigItem::paintCell(QPainter* p, const QColorGroup& cg, int column, int width, int align) +{ + ConfigList* list = listView(); + + if (visible) { + if (isSelected() && !list->hasFocus() && list->mode == menuMode) + Parent::paintCell(p, list->inactivedColorGroup, column, width, align); + else + Parent::paintCell(p, cg, column, width, align); + } else + Parent::paintCell(p, list->disabledColorGroup, column, width, align); +} + +/* + * construct a menu entry + */ +void ConfigItem::init(void) +{ + if (menu) { + ConfigList* list = listView(); + nextItem = (ConfigItem*)menu->data; + menu->data = this; + + if (list->mode != fullMode) + setOpen(TRUE); + sym_calc_value(menu->sym); + } + updateMenu(); +} + +/* + * destruct a menu entry + */ +ConfigItem::~ConfigItem(void) +{ + if (menu) { + ConfigItem** ip = (ConfigItem**)&menu->data; + for (; *ip; ip = &(*ip)->nextItem) { + if (*ip == this) { + *ip = nextItem; + break; + } + } + } +} + +ConfigLineEdit::ConfigLineEdit(ConfigView* parent) + : Parent(parent) +{ + connect(this, SIGNAL(lostFocus()), SLOT(hide())); +} + +void ConfigLineEdit::show(ConfigItem* i) +{ + item = i; + if (sym_get_string_value(item->menu->sym)) + setText(QString::fromLocal8Bit(sym_get_string_value(item->menu->sym))); + else + setText(QString::null); + Parent::show(); + setFocus(); +} + +void ConfigLineEdit::keyPressEvent(QKeyEvent* e) +{ + switch (e->key()) { + case Qt::Key_Escape: + break; + case Qt::Key_Return: + case Qt::Key_Enter: + sym_set_string_value(item->menu->sym, text().latin1()); + parent()->updateList(item); + break; + default: + Parent::keyPressEvent(e); + return; + } + e->accept(); + parent()->list->setFocus(); + hide(); +} + +ConfigList::ConfigList(ConfigView* p, const char *name) + : Parent(p, name), + updateAll(false), + symbolYesPix(xpm_symbol_yes), symbolModPix(xpm_symbol_mod), symbolNoPix(xpm_symbol_no), + choiceYesPix(xpm_choice_yes), choiceNoPix(xpm_choice_no), + menuPix(xpm_menu), menuInvPix(xpm_menu_inv), menuBackPix(xpm_menuback), voidPix(xpm_void), + showName(false), showRange(false), showData(false), optMode(normalOpt), + rootEntry(0), headerPopup(0) +{ + int i; + + setSorting(-1); + setRootIsDecorated(TRUE); + disabledColorGroup = palette().active(); + disabledColorGroup.setColor(QColorGroup::Text, palette().disabled().text()); + inactivedColorGroup = palette().active(); + inactivedColorGroup.setColor(QColorGroup::Highlight, palette().disabled().highlight()); + + connect(this, SIGNAL(selectionChanged(void)), + SLOT(updateSelection(void))); + + if (name) { + configSettings->beginGroup(name); + showName = configSettings->readBoolEntry("/showName", false); + showRange = configSettings->readBoolEntry("/showRange", false); + showData = configSettings->readBoolEntry("/showData", false); + optMode = (enum optionMode)configSettings->readNumEntry("/optionMode", false); + configSettings->endGroup(); + connect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings())); + } + + for (i = 0; i < colNr; i++) + colMap[i] = colRevMap[i] = -1; + addColumn(promptColIdx, _("Option")); + + reinit(); +} + +bool ConfigList::menuSkip(struct menu *menu) +{ + if (optMode == normalOpt && menu_is_visible(menu)) + return false; + if (optMode == promptOpt && menu_has_prompt(menu)) + return false; + if (optMode == allOpt) + return false; + return true; +} + +void ConfigList::reinit(void) +{ + removeColumn(dataColIdx); + removeColumn(yesColIdx); + removeColumn(modColIdx); + removeColumn(noColIdx); + removeColumn(nameColIdx); + + if (showName) + addColumn(nameColIdx, _("Name")); + if (showRange) { + addColumn(noColIdx, "N"); + addColumn(modColIdx, "M"); + addColumn(yesColIdx, "Y"); + } + if (showData) + addColumn(dataColIdx, _("Value")); + + updateListAll(); +} + +void ConfigList::saveSettings(void) +{ + if (name()) { + configSettings->beginGroup(name()); + configSettings->writeEntry("/showName", showName); + configSettings->writeEntry("/showRange", showRange); + configSettings->writeEntry("/showData", showData); + configSettings->writeEntry("/optionMode", (int)optMode); + configSettings->endGroup(); + } +} + +ConfigItem* ConfigList::findConfigItem(struct menu *menu) +{ + ConfigItem* item = (ConfigItem*)menu->data; + + for (; item; item = item->nextItem) { + if (this == item->listView()) + break; + } + + return item; +} + +void ConfigList::updateSelection(void) +{ + struct menu *menu; + enum prop_type type; + + ConfigItem* item = (ConfigItem*)selectedItem(); + if (!item) + return; + + menu = item->menu; + emit menuChanged(menu); + if (!menu) + return; + type = menu->prompt ? menu->prompt->type : P_UNKNOWN; + if (mode == menuMode && type == P_MENU) + emit menuSelected(menu); +} + +void ConfigList::updateList(ConfigItem* item) +{ + ConfigItem* last = 0; + + if (!rootEntry) { + if (mode != listMode) + goto update; + Q3ListViewItemIterator it(this); + ConfigItem* item; + + for (; it.current(); ++it) { + item = (ConfigItem*)it.current(); + if (!item->menu) + continue; + item->testUpdateMenu(menu_is_visible(item->menu)); + } + return; + } + + if (rootEntry != &rootmenu && (mode == singleMode || + (mode == symbolMode && rootEntry->parent != &rootmenu))) { + item = firstChild(); + if (!item) + item = new ConfigItem(this, 0, true); + last = item; + } + if ((mode == singleMode || (mode == symbolMode && !(rootEntry->flags & MENU_ROOT))) && + rootEntry->sym && rootEntry->prompt) { + item = last ? last->nextSibling() : firstChild(); + if (!item) + item = new ConfigItem(this, last, rootEntry, true); + else + item->testUpdateMenu(true); + + updateMenuList(item, rootEntry); + triggerUpdate(); + return; + } +update: + updateMenuList(this, rootEntry); + triggerUpdate(); +} + +void ConfigList::setValue(ConfigItem* item, tristate val) +{ + struct symbol* sym; + int type; + tristate oldval; + + sym = item->menu ? item->menu->sym : 0; + if (!sym) + return; + + type = sym_get_type(sym); + switch (type) { + case S_BOOLEAN: + case S_TRISTATE: + oldval = sym_get_tristate_value(sym); + + if (!sym_set_tristate_value(sym, val)) + return; + if (oldval == no && item->menu->list) + item->setOpen(TRUE); + parent()->updateList(item); + break; + } +} + +void ConfigList::changeValue(ConfigItem* item) +{ + struct symbol* sym; + struct menu* menu; + int type, oldexpr, newexpr; + + menu = item->menu; + if (!menu) + return; + sym = menu->sym; + if (!sym) { + if (item->menu->list) + item->setOpen(!item->isOpen()); + return; + } + + type = sym_get_type(sym); + switch (type) { + case S_BOOLEAN: + case S_TRISTATE: + oldexpr = sym_get_tristate_value(sym); + newexpr = sym_toggle_tristate_value(sym); + if (item->menu->list) { + if (oldexpr == newexpr) + item->setOpen(!item->isOpen()); + else if (oldexpr == no) + item->setOpen(TRUE); + } + if (oldexpr != newexpr) + parent()->updateList(item); + break; + case S_INT: + case S_HEX: + case S_STRING: + if (colMap[dataColIdx] >= 0) + item->startRename(colMap[dataColIdx]); + else + parent()->lineEdit->show(item); + break; + } +} + +void ConfigList::setRootMenu(struct menu *menu) +{ + enum prop_type type; + + if (rootEntry == menu) + return; + type = menu && menu->prompt ? menu->prompt->type : P_UNKNOWN; + if (type != P_MENU) + return; + updateMenuList(this, 0); + rootEntry = menu; + updateListAll(); + setSelected(currentItem(), hasFocus()); + ensureItemVisible(currentItem()); +} + +void ConfigList::setParentMenu(void) +{ + ConfigItem* item; + struct menu *oldroot; + + oldroot = rootEntry; + if (rootEntry == &rootmenu) + return; + setRootMenu(menu_get_parent_menu(rootEntry->parent)); + + Q3ListViewItemIterator it(this); + for (; (item = (ConfigItem*)it.current()); it++) { + if (item->menu == oldroot) { + setCurrentItem(item); + ensureItemVisible(item); + break; + } + } +} + +/* + * update all the children of a menu entry + * removes/adds the entries from the parent widget as necessary + * + * parent: either the menu list widget or a menu entry widget + * menu: entry to be updated + */ +template +void ConfigList::updateMenuList(P* parent, struct menu* menu) +{ + struct menu* child; + ConfigItem* item; + ConfigItem* last; + bool visible; + enum prop_type type; + + if (!menu) { + while ((item = parent->firstChild())) + delete item; + return; + } + + last = parent->firstChild(); + if (last && !last->goParent) + last = 0; + for (child = menu->list; child; child = child->next) { + item = last ? last->nextSibling() : parent->firstChild(); + type = child->prompt ? child->prompt->type : P_UNKNOWN; + + switch (mode) { + case menuMode: + if (!(child->flags & MENU_ROOT)) + goto hide; + break; + case symbolMode: + if (child->flags & MENU_ROOT) + goto hide; + break; + default: + break; + } + + visible = menu_is_visible(child); + if (!menuSkip(child)) { + if (!child->sym && !child->list && !child->prompt) + continue; + if (!item || item->menu != child) + item = new ConfigItem(parent, last, child, visible); + else + item->testUpdateMenu(visible); + + if (mode == fullMode || mode == menuMode || type != P_MENU) + updateMenuList(item, child); + else + updateMenuList(item, 0); + last = item; + continue; + } + hide: + if (item && item->menu == child) { + last = parent->firstChild(); + if (last == item) + last = 0; + else while (last->nextSibling() != item) + last = last->nextSibling(); + delete item; + } + } +} + +void ConfigList::keyPressEvent(QKeyEvent* ev) +{ + Q3ListViewItem* i = currentItem(); + ConfigItem* item; + struct menu *menu; + enum prop_type type; + + if (ev->key() == Qt::Key_Escape && mode != fullMode && mode != listMode) { + emit parentSelected(); + ev->accept(); + return; + } + + if (!i) { + Parent::keyPressEvent(ev); + return; + } + item = (ConfigItem*)i; + + switch (ev->key()) { + case Qt::Key_Return: + case Qt::Key_Enter: + if (item->goParent) { + emit parentSelected(); + break; + } + menu = item->menu; + if (!menu) + break; + type = menu->prompt ? menu->prompt->type : P_UNKNOWN; + if (type == P_MENU && rootEntry != menu && + mode != fullMode && mode != menuMode) { + emit menuSelected(menu); + break; + } + case Qt::Key_Space: + changeValue(item); + break; + case Qt::Key_N: + setValue(item, no); + break; + case Qt::Key_M: + setValue(item, mod); + break; + case Qt::Key_Y: + setValue(item, yes); + break; + default: + Parent::keyPressEvent(ev); + return; + } + ev->accept(); +} + +void ConfigList::contentsMousePressEvent(QMouseEvent* e) +{ + //QPoint p(contentsToViewport(e->pos())); + //printf("contentsMousePressEvent: %d,%d\n", p.x(), p.y()); + Parent::contentsMousePressEvent(e); +} + +void ConfigList::contentsMouseReleaseEvent(QMouseEvent* e) +{ + QPoint p(contentsToViewport(e->pos())); + ConfigItem* item = (ConfigItem*)itemAt(p); + struct menu *menu; + enum prop_type ptype; + const QPixmap* pm; + int idx, x; + + if (!item) + goto skip; + + menu = item->menu; + x = header()->offset() + p.x(); + idx = colRevMap[header()->sectionAt(x)]; + switch (idx) { + case promptColIdx: + pm = item->pixmap(promptColIdx); + if (pm) { + int off = header()->sectionPos(0) + itemMargin() + + treeStepSize() * (item->depth() + (rootIsDecorated() ? 1 : 0)); + if (x >= off && x < off + pm->width()) { + if (item->goParent) { + emit parentSelected(); + break; + } else if (!menu) + break; + ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN; + if (ptype == P_MENU && rootEntry != menu && + mode != fullMode && mode != menuMode) + emit menuSelected(menu); + else + changeValue(item); + } + } + break; + case noColIdx: + setValue(item, no); + break; + case modColIdx: + setValue(item, mod); + break; + case yesColIdx: + setValue(item, yes); + break; + case dataColIdx: + changeValue(item); + break; + } + +skip: + //printf("contentsMouseReleaseEvent: %d,%d\n", p.x(), p.y()); + Parent::contentsMouseReleaseEvent(e); +} + +void ConfigList::contentsMouseMoveEvent(QMouseEvent* e) +{ + //QPoint p(contentsToViewport(e->pos())); + //printf("contentsMouseMoveEvent: %d,%d\n", p.x(), p.y()); + Parent::contentsMouseMoveEvent(e); +} + +void ConfigList::contentsMouseDoubleClickEvent(QMouseEvent* e) +{ + QPoint p(contentsToViewport(e->pos())); + ConfigItem* item = (ConfigItem*)itemAt(p); + struct menu *menu; + enum prop_type ptype; + + if (!item) + goto skip; + if (item->goParent) { + emit parentSelected(); + goto skip; + } + menu = item->menu; + if (!menu) + goto skip; + ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN; + if (ptype == P_MENU && (mode == singleMode || mode == symbolMode)) + emit menuSelected(menu); + else if (menu->sym) + changeValue(item); + +skip: + //printf("contentsMouseDoubleClickEvent: %d,%d\n", p.x(), p.y()); + Parent::contentsMouseDoubleClickEvent(e); +} + +void ConfigList::focusInEvent(QFocusEvent *e) +{ + struct menu *menu = NULL; + + Parent::focusInEvent(e); + + ConfigItem* item = (ConfigItem *)currentItem(); + if (item) { + setSelected(item, TRUE); + menu = item->menu; + } + emit gotFocus(menu); +} + +void ConfigList::contextMenuEvent(QContextMenuEvent *e) +{ + if (e->y() <= header()->geometry().bottom()) { + if (!headerPopup) { + Q3Action *action; + + headerPopup = new Q3PopupMenu(this); + action = new Q3Action(NULL, _("Show Name"), 0, this); + action->setToggleAction(TRUE); + connect(action, SIGNAL(toggled(bool)), + parent(), SLOT(setShowName(bool))); + connect(parent(), SIGNAL(showNameChanged(bool)), + action, SLOT(setOn(bool))); + action->setOn(showName); + action->addTo(headerPopup); + action = new Q3Action(NULL, _("Show Range"), 0, this); + action->setToggleAction(TRUE); + connect(action, SIGNAL(toggled(bool)), + parent(), SLOT(setShowRange(bool))); + connect(parent(), SIGNAL(showRangeChanged(bool)), + action, SLOT(setOn(bool))); + action->setOn(showRange); + action->addTo(headerPopup); + action = new Q3Action(NULL, _("Show Data"), 0, this); + action->setToggleAction(TRUE); + connect(action, SIGNAL(toggled(bool)), + parent(), SLOT(setShowData(bool))); + connect(parent(), SIGNAL(showDataChanged(bool)), + action, SLOT(setOn(bool))); + action->setOn(showData); + action->addTo(headerPopup); + } + headerPopup->exec(e->globalPos()); + e->accept(); + } else + e->ignore(); +} + +ConfigView*ConfigView::viewList; +QAction *ConfigView::showNormalAction; +QAction *ConfigView::showAllAction; +QAction *ConfigView::showPromptAction; + +ConfigView::ConfigView(QWidget* parent, const char *name) + : Parent(parent, name) +{ + list = new ConfigList(this, name); + lineEdit = new ConfigLineEdit(this); + lineEdit->hide(); + + this->nextView = viewList; + viewList = this; +} + +ConfigView::~ConfigView(void) +{ + ConfigView** vp; + + for (vp = &viewList; *vp; vp = &(*vp)->nextView) { + if (*vp == this) { + *vp = nextView; + break; + } + } +} + +void ConfigView::setOptionMode(QAction *act) +{ + if (act == showNormalAction) + list->optMode = normalOpt; + else if (act == showAllAction) + list->optMode = allOpt; + else + list->optMode = promptOpt; + + list->updateListAll(); +} + +void ConfigView::setShowName(bool b) +{ + if (list->showName != b) { + list->showName = b; + list->reinit(); + emit showNameChanged(b); + } +} + +void ConfigView::setShowRange(bool b) +{ + if (list->showRange != b) { + list->showRange = b; + list->reinit(); + emit showRangeChanged(b); + } +} + +void ConfigView::setShowData(bool b) +{ + if (list->showData != b) { + list->showData = b; + list->reinit(); + emit showDataChanged(b); + } +} + +void ConfigList::setAllOpen(bool open) +{ + Q3ListViewItemIterator it(this); + + for (; it.current(); it++) + it.current()->setOpen(open); +} + +void ConfigView::updateList(ConfigItem* item) +{ + ConfigView* v; + + for (v = viewList; v; v = v->nextView) + v->list->updateList(item); +} + +void ConfigView::updateListAll(void) +{ + ConfigView* v; + + for (v = viewList; v; v = v->nextView) + v->list->updateListAll(); +} + +ConfigInfoView::ConfigInfoView(QWidget* parent, const char *name) + : Parent(parent, name), sym(0), _menu(0) +{ + if (name) { + configSettings->beginGroup(name); + _showDebug = configSettings->readBoolEntry("/showDebug", false); + configSettings->endGroup(); + connect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings())); + } +} + +void ConfigInfoView::saveSettings(void) +{ + if (name()) { + configSettings->beginGroup(name()); + configSettings->writeEntry("/showDebug", showDebug()); + configSettings->endGroup(); + } +} + +void ConfigInfoView::setShowDebug(bool b) +{ + if (_showDebug != b) { + _showDebug = b; + if (_menu) + menuInfo(); + else if (sym) + symbolInfo(); + emit showDebugChanged(b); + } +} + +void ConfigInfoView::setInfo(struct menu *m) +{ + if (_menu == m) + return; + _menu = m; + sym = NULL; + if (!_menu) + clear(); + else + menuInfo(); +} + +void ConfigInfoView::symbolInfo(void) +{ + QString str; + + str += "Symbol: "; + str += print_filter(sym->name); + str += "

value: "; + str += print_filter(sym_get_string_value(sym)); + str += "
visibility: "; + str += sym->visible == yes ? "y" : sym->visible == mod ? "m" : "n"; + str += "
"; + str += debug_info(sym); + + setText(str); +} + +void ConfigInfoView::menuInfo(void) +{ + struct symbol* sym; + QString head, debug, help; + + sym = _menu->sym; + if (sym) { + if (_menu->prompt) { + head += ""; + head += print_filter(_(_menu->prompt->text)); + head += ""; + if (sym->name) { + head += " ("; + if (showDebug()) + head += QString().sprintf("
", sym); + head += print_filter(sym->name); + if (showDebug()) + head += ""; + head += ")"; + } + } else if (sym->name) { + head += ""; + if (showDebug()) + head += QString().sprintf("", sym); + head += print_filter(sym->name); + if (showDebug()) + head += ""; + head += ""; + } + head += "

"; + + if (showDebug()) + debug = debug_info(sym); + + struct gstr help_gstr = str_new(); + menu_get_ext_help(_menu, &help_gstr); + help = print_filter(str_get(&help_gstr)); + str_free(&help_gstr); + } else if (_menu->prompt) { + head += ""; + head += print_filter(_(_menu->prompt->text)); + head += "

"; + if (showDebug()) { + if (_menu->prompt->visible.expr) { + debug += "  dep: "; + expr_print(_menu->prompt->visible.expr, expr_print_help, &debug, E_NONE); + debug += "

"; + } + } + } + if (showDebug()) + debug += QString().sprintf("defined at %s:%d

", _menu->file->name, _menu->lineno); + + setText(head + debug + help); +} + +QString ConfigInfoView::debug_info(struct symbol *sym) +{ + QString debug; + + debug += "type: "; + debug += print_filter(sym_type_name(sym->type)); + if (sym_is_choice(sym)) + debug += " (choice)"; + debug += "
"; + if (sym->rev_dep.expr) { + debug += "reverse dep: "; + expr_print(sym->rev_dep.expr, expr_print_help, &debug, E_NONE); + debug += "
"; + } + for (struct property *prop = sym->prop; prop; prop = prop->next) { + switch (prop->type) { + case P_PROMPT: + case P_MENU: + debug += QString().sprintf("prompt: ", prop->menu); + debug += print_filter(_(prop->text)); + debug += "
"; + break; + case P_DEFAULT: + case P_SELECT: + case P_RANGE: + case P_ENV: + debug += prop_get_type_name(prop->type); + debug += ": "; + expr_print(prop->expr, expr_print_help, &debug, E_NONE); + debug += "
"; + break; + case P_CHOICE: + if (sym_is_choice(sym)) { + debug += "choice: "; + expr_print(prop->expr, expr_print_help, &debug, E_NONE); + debug += "
"; + } + break; + default: + debug += "unknown property: "; + debug += prop_get_type_name(prop->type); + debug += "
"; + } + if (prop->visible.expr) { + debug += "    dep: "; + expr_print(prop->visible.expr, expr_print_help, &debug, E_NONE); + debug += "
"; + } + } + debug += "
"; + + return debug; +} + +QString ConfigInfoView::print_filter(const QString &str) +{ + QRegExp re("[<>&\"\\n]"); + QString res = str; + for (int i = 0; (i = res.find(re, i)) >= 0;) { + switch (res[i].latin1()) { + case '<': + res.replace(i, 1, "<"); + i += 4; + break; + case '>': + res.replace(i, 1, ">"); + i += 4; + break; + case '&': + res.replace(i, 1, "&"); + i += 5; + break; + case '"': + res.replace(i, 1, """); + i += 6; + break; + case '\n': + res.replace(i, 1, "
"); + i += 4; + break; + } + } + return res; +} + +void ConfigInfoView::expr_print_help(void *data, struct symbol *sym, const char *str) +{ + QString* text = reinterpret_cast(data); + QString str2 = print_filter(str); + + if (sym && sym->name && !(sym->flags & SYMBOL_CONST)) { + *text += QString().sprintf("", sym); + *text += str2; + *text += ""; + } else + *text += str2; +} + +Q3PopupMenu* ConfigInfoView::createPopupMenu(const QPoint& pos) +{ + Q3PopupMenu* popup = Parent::createPopupMenu(pos); + Q3Action* action = new Q3Action(NULL, _("Show Debug Info"), 0, popup); + action->setToggleAction(TRUE); + connect(action, SIGNAL(toggled(bool)), SLOT(setShowDebug(bool))); + connect(this, SIGNAL(showDebugChanged(bool)), action, SLOT(setOn(bool))); + action->setOn(showDebug()); + popup->insertSeparator(); + action->addTo(popup); + return popup; +} + +void ConfigInfoView::contentsContextMenuEvent(QContextMenuEvent *e) +{ + Parent::contentsContextMenuEvent(e); +} + +ConfigSearchWindow::ConfigSearchWindow(ConfigMainWindow* parent, const char *name) + : Parent(parent, name), result(NULL) +{ + setCaption("Search Config"); + + QVBoxLayout* layout1 = new QVBoxLayout(this, 11, 6); + QHBoxLayout* layout2 = new QHBoxLayout(0, 0, 6); + layout2->addWidget(new QLabel(_("Find:"), this)); + editField = new QLineEdit(this); + connect(editField, SIGNAL(returnPressed()), SLOT(search())); + layout2->addWidget(editField); + searchButton = new QPushButton(_("Search"), this); + searchButton->setAutoDefault(FALSE); + connect(searchButton, SIGNAL(clicked()), SLOT(search())); + layout2->addWidget(searchButton); + layout1->addLayout(layout2); + + split = new QSplitter(this); + split->setOrientation(Qt::Vertical); + list = new ConfigView(split, name); + list->list->mode = listMode; + info = new ConfigInfoView(split, name); + connect(list->list, SIGNAL(menuChanged(struct menu *)), + info, SLOT(setInfo(struct menu *))); + connect(list->list, SIGNAL(menuChanged(struct menu *)), + parent, SLOT(setMenuLink(struct menu *))); + + layout1->addWidget(split); + + if (name) { + int x, y, width, height; + bool ok; + + configSettings->beginGroup(name); + width = configSettings->readNumEntry("/window width", parent->width() / 2); + height = configSettings->readNumEntry("/window height", parent->height() / 2); + resize(width, height); + x = configSettings->readNumEntry("/window x", 0, &ok); + if (ok) + y = configSettings->readNumEntry("/window y", 0, &ok); + if (ok) + move(x, y); + Q3ValueList sizes = configSettings->readSizes("/split", &ok); + if (ok) + split->setSizes(sizes); + configSettings->endGroup(); + connect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings())); + } +} + +void ConfigSearchWindow::saveSettings(void) +{ + if (name()) { + configSettings->beginGroup(name()); + configSettings->writeEntry("/window x", pos().x()); + configSettings->writeEntry("/window y", pos().y()); + configSettings->writeEntry("/window width", size().width()); + configSettings->writeEntry("/window height", size().height()); + configSettings->writeSizes("/split", split->sizes()); + configSettings->endGroup(); + } +} + +void ConfigSearchWindow::search(void) +{ + struct symbol **p; + struct property *prop; + ConfigItem *lastItem = NULL; + + free(result); + list->list->clear(); + info->clear(); + + result = sym_re_search(editField->text().latin1()); + if (!result) + return; + for (p = result; *p; p++) { + for_all_prompts((*p), prop) + lastItem = new ConfigItem(list->list, lastItem, prop->menu, + menu_is_visible(prop->menu)); + } +} + +/* + * Construct the complete config widget + */ +ConfigMainWindow::ConfigMainWindow(void) + : searchWindow(0) +{ + QMenuBar* menu; + bool ok; + int x, y, width, height; + char title[256]; + + QDesktopWidget *d = configApp->desktop(); + snprintf(title, sizeof(title), "%s%s", + rootmenu.prompt->text, +#if QT_VERSION < 0x040000 + " (Qt3)" +#else + "" +#endif + ); + setCaption(title); + + width = configSettings->readNumEntry("/window width", d->width() - 64); + height = configSettings->readNumEntry("/window height", d->height() - 64); + resize(width, height); + x = configSettings->readNumEntry("/window x", 0, &ok); + if (ok) + y = configSettings->readNumEntry("/window y", 0, &ok); + if (ok) + move(x, y); + + split1 = new QSplitter(this); + split1->setOrientation(Qt::Horizontal); + setCentralWidget(split1); + + menuView = new ConfigView(split1, "menu"); + menuList = menuView->list; + + split2 = new QSplitter(split1); + split2->setOrientation(Qt::Vertical); + + // create config tree + configView = new ConfigView(split2, "config"); + configList = configView->list; + + helpText = new ConfigInfoView(split2, "help"); + helpText->setTextFormat(Qt::RichText); + + setTabOrder(configList, helpText); + configList->setFocus(); + + menu = menuBar(); + toolBar = new Q3ToolBar("Tools", this); + + backAction = new Q3Action("Back", QPixmap(xpm_back), _("Back"), 0, this); + connect(backAction, SIGNAL(activated()), SLOT(goBack())); + backAction->setEnabled(FALSE); + Q3Action *quitAction = new Q3Action("Quit", _("&Quit"), Qt::CTRL + Qt::Key_Q, this); + connect(quitAction, SIGNAL(activated()), SLOT(close())); + Q3Action *loadAction = new Q3Action("Load", QPixmap(xpm_load), _("&Load"), Qt::CTRL + Qt::Key_L, this); + connect(loadAction, SIGNAL(activated()), SLOT(loadConfig())); + saveAction = new Q3Action("Save", QPixmap(xpm_save), _("&Save"), Qt::CTRL + Qt::Key_S, this); + connect(saveAction, SIGNAL(activated()), SLOT(saveConfig())); + conf_set_changed_callback(conf_changed); + // Set saveAction's initial state + conf_changed(); + Q3Action *saveAsAction = new Q3Action("Save As...", _("Save &As..."), 0, this); + connect(saveAsAction, SIGNAL(activated()), SLOT(saveConfigAs())); + Q3Action *searchAction = new Q3Action("Find", _("&Find"), Qt::CTRL + Qt::Key_F, this); + connect(searchAction, SIGNAL(activated()), SLOT(searchConfig())); + Q3Action *singleViewAction = new Q3Action("Single View", QPixmap(xpm_single_view), _("Single View"), 0, this); + connect(singleViewAction, SIGNAL(activated()), SLOT(showSingleView())); + Q3Action *splitViewAction = new Q3Action("Split View", QPixmap(xpm_split_view), _("Split View"), 0, this); + connect(splitViewAction, SIGNAL(activated()), SLOT(showSplitView())); + Q3Action *fullViewAction = new Q3Action("Full View", QPixmap(xpm_tree_view), _("Full View"), 0, this); + connect(fullViewAction, SIGNAL(activated()), SLOT(showFullView())); + + Q3Action *showNameAction = new Q3Action(NULL, _("Show Name"), 0, this); + showNameAction->setToggleAction(TRUE); + connect(showNameAction, SIGNAL(toggled(bool)), configView, SLOT(setShowName(bool))); + connect(configView, SIGNAL(showNameChanged(bool)), showNameAction, SLOT(setOn(bool))); + showNameAction->setOn(configView->showName()); + Q3Action *showRangeAction = new Q3Action(NULL, _("Show Range"), 0, this); + showRangeAction->setToggleAction(TRUE); + connect(showRangeAction, SIGNAL(toggled(bool)), configView, SLOT(setShowRange(bool))); + connect(configView, SIGNAL(showRangeChanged(bool)), showRangeAction, SLOT(setOn(bool))); + showRangeAction->setOn(configList->showRange); + Q3Action *showDataAction = new Q3Action(NULL, _("Show Data"), 0, this); + showDataAction->setToggleAction(TRUE); + connect(showDataAction, SIGNAL(toggled(bool)), configView, SLOT(setShowData(bool))); + connect(configView, SIGNAL(showDataChanged(bool)), showDataAction, SLOT(setOn(bool))); + showDataAction->setOn(configList->showData); + + QActionGroup *optGroup = new QActionGroup(this); + optGroup->setExclusive(TRUE); + connect(optGroup, SIGNAL(selected(QAction *)), configView, + SLOT(setOptionMode(QAction *))); + connect(optGroup, SIGNAL(selected(QAction *)), menuView, + SLOT(setOptionMode(QAction *))); + +#if QT_VERSION >= 0x040000 + configView->showNormalAction = new QAction(_("Show Normal Options"), optGroup); + configView->showAllAction = new QAction(_("Show All Options"), optGroup); + configView->showPromptAction = new QAction(_("Show Prompt Options"), optGroup); +#else + configView->showNormalAction = new QAction(_("Show Normal Options"), 0, optGroup); + configView->showAllAction = new QAction(_("Show All Options"), 0, optGroup); + configView->showPromptAction = new QAction(_("Show Prompt Options"), 0, optGroup); +#endif + configView->showNormalAction->setToggleAction(TRUE); + configView->showNormalAction->setOn(configList->optMode == normalOpt); + configView->showAllAction->setToggleAction(TRUE); + configView->showAllAction->setOn(configList->optMode == allOpt); + configView->showPromptAction->setToggleAction(TRUE); + configView->showPromptAction->setOn(configList->optMode == promptOpt); + + Q3Action *showDebugAction = new Q3Action(NULL, _("Show Debug Info"), 0, this); + showDebugAction->setToggleAction(TRUE); + connect(showDebugAction, SIGNAL(toggled(bool)), helpText, SLOT(setShowDebug(bool))); + connect(helpText, SIGNAL(showDebugChanged(bool)), showDebugAction, SLOT(setOn(bool))); + showDebugAction->setOn(helpText->showDebug()); + + Q3Action *showIntroAction = new Q3Action(NULL, _("Introduction"), 0, this); + connect(showIntroAction, SIGNAL(activated()), SLOT(showIntro())); + Q3Action *showAboutAction = new Q3Action(NULL, _("About"), 0, this); + connect(showAboutAction, SIGNAL(activated()), SLOT(showAbout())); + + // init tool bar + backAction->addTo(toolBar); + toolBar->addSeparator(); + loadAction->addTo(toolBar); + saveAction->addTo(toolBar); + toolBar->addSeparator(); + singleViewAction->addTo(toolBar); + splitViewAction->addTo(toolBar); + fullViewAction->addTo(toolBar); + + // create config menu + Q3PopupMenu* config = new Q3PopupMenu(this); + menu->insertItem(_("&File"), config); + loadAction->addTo(config); + saveAction->addTo(config); + saveAsAction->addTo(config); + config->insertSeparator(); + quitAction->addTo(config); + + // create edit menu + Q3PopupMenu* editMenu = new Q3PopupMenu(this); + menu->insertItem(_("&Edit"), editMenu); + searchAction->addTo(editMenu); + + // create options menu + Q3PopupMenu* optionMenu = new Q3PopupMenu(this); + menu->insertItem(_("&Option"), optionMenu); + showNameAction->addTo(optionMenu); + showRangeAction->addTo(optionMenu); + showDataAction->addTo(optionMenu); + optionMenu->insertSeparator(); + optGroup->addTo(optionMenu); + optionMenu->insertSeparator(); + + // create help menu + Q3PopupMenu* helpMenu = new Q3PopupMenu(this); + menu->insertSeparator(); + menu->insertItem(_("&Help"), helpMenu); + showIntroAction->addTo(helpMenu); + showAboutAction->addTo(helpMenu); + + connect(configList, SIGNAL(menuChanged(struct menu *)), + helpText, SLOT(setInfo(struct menu *))); + connect(configList, SIGNAL(menuSelected(struct menu *)), + SLOT(changeMenu(struct menu *))); + connect(configList, SIGNAL(parentSelected()), + SLOT(goBack())); + connect(menuList, SIGNAL(menuChanged(struct menu *)), + helpText, SLOT(setInfo(struct menu *))); + connect(menuList, SIGNAL(menuSelected(struct menu *)), + SLOT(changeMenu(struct menu *))); + + connect(configList, SIGNAL(gotFocus(struct menu *)), + helpText, SLOT(setInfo(struct menu *))); + connect(menuList, SIGNAL(gotFocus(struct menu *)), + helpText, SLOT(setInfo(struct menu *))); + connect(menuList, SIGNAL(gotFocus(struct menu *)), + SLOT(listFocusChanged(void))); + connect(helpText, SIGNAL(menuSelected(struct menu *)), + SLOT(setMenuLink(struct menu *))); + + QString listMode = configSettings->readEntry("/listMode", "symbol"); + if (listMode == "single") + showSingleView(); + else if (listMode == "full") + showFullView(); + else /*if (listMode == "split")*/ + showSplitView(); + + // UI setup done, restore splitter positions + Q3ValueList sizes = configSettings->readSizes("/split1", &ok); + if (ok) + split1->setSizes(sizes); + + sizes = configSettings->readSizes("/split2", &ok); + if (ok) + split2->setSizes(sizes); +} + +void ConfigMainWindow::loadConfig(void) +{ + QString s = Q3FileDialog::getOpenFileName(conf_get_configname(), NULL, this); + if (s.isNull()) + return; + if (conf_read(QFile::encodeName(s))) + QMessageBox::information(this, "qconf", _("Unable to load configuration!")); + ConfigView::updateListAll(); +} + +bool ConfigMainWindow::saveConfig(void) +{ + if (conf_write(NULL)) { + QMessageBox::information(this, "qconf", _("Unable to save configuration!")); + return false; + } + return true; +} + +void ConfigMainWindow::saveConfigAs(void) +{ + QString s = Q3FileDialog::getSaveFileName(conf_get_configname(), NULL, this); + if (s.isNull()) + return; + saveConfig(); +} + +void ConfigMainWindow::searchConfig(void) +{ + if (!searchWindow) + searchWindow = new ConfigSearchWindow(this, "search"); + searchWindow->show(); +} + +void ConfigMainWindow::changeMenu(struct menu *menu) +{ + configList->setRootMenu(menu); + if (configList->rootEntry->parent == &rootmenu) + backAction->setEnabled(FALSE); + else + backAction->setEnabled(TRUE); +} + +void ConfigMainWindow::setMenuLink(struct menu *menu) +{ + struct menu *parent; + ConfigList* list = NULL; + ConfigItem* item; + + if (configList->menuSkip(menu)) + return; + + switch (configList->mode) { + case singleMode: + list = configList; + parent = menu_get_parent_menu(menu); + if (!parent) + return; + list->setRootMenu(parent); + break; + case symbolMode: + if (menu->flags & MENU_ROOT) { + configList->setRootMenu(menu); + configList->clearSelection(); + list = menuList; + } else { + list = configList; + parent = menu_get_parent_menu(menu->parent); + if (!parent) + return; + item = menuList->findConfigItem(parent); + if (item) { + menuList->setSelected(item, TRUE); + menuList->ensureItemVisible(item); + } + list->setRootMenu(parent); + } + break; + case fullMode: + list = configList; + break; + default: + break; + } + + if (list) { + item = list->findConfigItem(menu); + if (item) { + list->setSelected(item, TRUE); + list->ensureItemVisible(item); + list->setFocus(); + } + } +} + +void ConfigMainWindow::listFocusChanged(void) +{ + if (menuList->mode == menuMode) + configList->clearSelection(); +} + +void ConfigMainWindow::goBack(void) +{ + ConfigItem* item; + + configList->setParentMenu(); + if (configList->rootEntry == &rootmenu) + backAction->setEnabled(FALSE); + item = (ConfigItem*)menuList->selectedItem(); + while (item) { + if (item->menu == configList->rootEntry) { + menuList->setSelected(item, TRUE); + break; + } + item = (ConfigItem*)item->parent(); + } +} + +void ConfigMainWindow::showSingleView(void) +{ + menuView->hide(); + menuList->setRootMenu(0); + configList->mode = singleMode; + if (configList->rootEntry == &rootmenu) + configList->updateListAll(); + else + configList->setRootMenu(&rootmenu); + configList->setAllOpen(TRUE); + configList->setFocus(); +} + +void ConfigMainWindow::showSplitView(void) +{ + configList->mode = symbolMode; + if (configList->rootEntry == &rootmenu) + configList->updateListAll(); + else + configList->setRootMenu(&rootmenu); + configList->setAllOpen(TRUE); + configApp->processEvents(); + menuList->mode = menuMode; + menuList->setRootMenu(&rootmenu); + menuList->setAllOpen(TRUE); + menuView->show(); + menuList->setFocus(); +} + +void ConfigMainWindow::showFullView(void) +{ + menuView->hide(); + menuList->setRootMenu(0); + configList->mode = fullMode; + if (configList->rootEntry == &rootmenu) + configList->updateListAll(); + else + configList->setRootMenu(&rootmenu); + configList->setAllOpen(FALSE); + configList->setFocus(); +} + +/* + * ask for saving configuration before quitting + * TODO ask only when something changed + */ +void ConfigMainWindow::closeEvent(QCloseEvent* e) +{ + if (!conf_get_changed()) { + e->accept(); + return; + } + QMessageBox mb("qconf", _("Save configuration?"), QMessageBox::Warning, + QMessageBox::Yes | QMessageBox::Default, QMessageBox::No, QMessageBox::Cancel | QMessageBox::Escape); + mb.setButtonText(QMessageBox::Yes, _("&Save Changes")); + mb.setButtonText(QMessageBox::No, _("&Discard Changes")); + mb.setButtonText(QMessageBox::Cancel, _("Cancel Exit")); + switch (mb.exec()) { + case QMessageBox::Yes: + if (saveConfig()) + e->accept(); + else + e->ignore(); + break; + case QMessageBox::No: + e->accept(); + break; + case QMessageBox::Cancel: + e->ignore(); + break; + } +} + +void ConfigMainWindow::showIntro(void) +{ + static const QString str = _("Welcome to the qconf graphical configuration tool.\n\n" + "For each option, a blank box indicates the feature is disabled, a check\n" + "indicates it is enabled, and a dot indicates that it is to be compiled\n" + "as a module. Clicking on the box will cycle through the three states.\n\n" + "If you do not see an option (e.g., a device driver) that you believe\n" + "should be present, try turning on Show All Options under the Options menu.\n" + "Although there is no cross reference yet to help you figure out what other\n" + "options must be enabled to support the option you are interested in, you can\n" + "still view the help of a grayed-out option.\n\n" + "Toggling Show Debug Info under the Options menu will show the dependencies,\n" + "which you can then match by examining other options.\n\n"); + + QMessageBox::information(this, "qconf", str); +} + +void ConfigMainWindow::showAbout(void) +{ + static const QString str = _("qconf is Copyright (C) 2002 Roman Zippel .\n\n" + "Bug reports and feature request can also be entered at http://bugzilla.kernel.org/\n"); + + QMessageBox::information(this, "qconf", str); +} + +void ConfigMainWindow::saveSettings(void) +{ + configSettings->writeEntry("/window x", pos().x()); + configSettings->writeEntry("/window y", pos().y()); + configSettings->writeEntry("/window width", size().width()); + configSettings->writeEntry("/window height", size().height()); + + QString entry; + switch(configList->mode) { + case singleMode : + entry = "single"; + break; + + case symbolMode : + entry = "split"; + break; + + case fullMode : + entry = "full"; + break; + + default: + break; + } + configSettings->writeEntry("/listMode", entry); + + configSettings->writeSizes("/split1", split1->sizes()); + configSettings->writeSizes("/split2", split2->sizes()); +} + +void ConfigMainWindow::conf_changed(void) +{ + if (saveAction) + saveAction->setEnabled(conf_get_changed()); +} + +void fixup_rootmenu(struct menu *menu) +{ + struct menu *child; + static int menu_cnt = 0; + + menu->flags |= MENU_ROOT; + for (child = menu->list; child; child = child->next) { + if (child->prompt && child->prompt->type == P_MENU) { + menu_cnt++; + fixup_rootmenu(child); + menu_cnt--; + } else if (!menu_cnt) + fixup_rootmenu(child); + } +} + +static const char *progname; + +static void usage(void) +{ + printf(_("%s \n"), progname); + exit(0); +} + +int main(int ac, char** av) +{ + ConfigMainWindow* v; + const char *name; + + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + + progname = av[0]; + configApp = new QApplication(ac, av); + if (ac > 1 && av[1][0] == '-') { + switch (av[1][1]) { + case 'h': + case '?': + usage(); + } + name = av[2]; + } else + name = av[1]; + if (!name) + usage(); + + conf_parse(name); + fixup_rootmenu(&rootmenu); + conf_read(NULL); + //zconfdump(stdout); + + configSettings = new ConfigSettings(); + configSettings->beginGroup("/kconfig/qconf"); + v = new ConfigMainWindow(); + + //zconfdump(stdout); + configApp->setMainWidget(v); + configApp->connect(configApp, SIGNAL(lastWindowClosed()), SLOT(quit())); + configApp->connect(configApp, SIGNAL(aboutToQuit()), v, SLOT(saveSettings())); + v->show(); + configApp->exec(); + + configSettings->endGroup(); + delete configSettings; + + return 0; +} diff --git a/kernel/fiasco/tool/kconfig/scripts/kconfig/qconf.h b/kernel/fiasco/tool/kconfig/scripts/kconfig/qconf.h new file mode 100644 index 00000000..3715b3e7 --- /dev/null +++ b/kernel/fiasco/tool/kconfig/scripts/kconfig/qconf.h @@ -0,0 +1,337 @@ +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +#if QT_VERSION < 0x040000 +#include +#else +#include +#endif +#include + +#if QT_VERSION < 0x040000 +#define Q3ValueList QValueList +#define Q3PopupMenu QPopupMenu +#define Q3ListView QListView +#define Q3ListViewItem QListViewItem +#define Q3VBox QVBox +#define Q3TextBrowser QTextBrowser +#define Q3MainWindow QMainWindow +#define Q3Action QAction +#define Q3ToolBar QToolBar +#define Q3ListViewItemIterator QListViewItemIterator +#define Q3FileDialog QFileDialog +#endif + +class ConfigView; +class ConfigList; +class ConfigItem; +class ConfigLineEdit; +class ConfigMainWindow; + +class ConfigSettings : public QSettings { +public: + Q3ValueList readSizes(const QString& key, bool *ok); + bool writeSizes(const QString& key, const Q3ValueList& value); +}; + +enum colIdx { + promptColIdx, nameColIdx, noColIdx, modColIdx, yesColIdx, dataColIdx, colNr +}; +enum listMode { + singleMode, menuMode, symbolMode, fullMode, listMode +}; +enum optionMode { + normalOpt = 0, allOpt, promptOpt +}; + +class ConfigList : public Q3ListView { + Q_OBJECT + typedef class Q3ListView Parent; +public: + ConfigList(ConfigView* p, const char *name = 0); + void reinit(void); + ConfigView* parent(void) const + { + return (ConfigView*)Parent::parent(); + } + ConfigItem* findConfigItem(struct menu *); + +protected: + void keyPressEvent(QKeyEvent *e); + void contentsMousePressEvent(QMouseEvent *e); + void contentsMouseReleaseEvent(QMouseEvent *e); + void contentsMouseMoveEvent(QMouseEvent *e); + void contentsMouseDoubleClickEvent(QMouseEvent *e); + void focusInEvent(QFocusEvent *e); + void contextMenuEvent(QContextMenuEvent *e); + +public slots: + void setRootMenu(struct menu *menu); + + void updateList(ConfigItem *item); + void setValue(ConfigItem* item, tristate val); + void changeValue(ConfigItem* item); + void updateSelection(void); + void saveSettings(void); +signals: + void menuChanged(struct menu *menu); + void menuSelected(struct menu *menu); + void parentSelected(void); + void gotFocus(struct menu *); + +public: + void updateListAll(void) + { + updateAll = true; + updateList(NULL); + updateAll = false; + } + ConfigList* listView() + { + return this; + } + ConfigItem* firstChild() const + { + return (ConfigItem *)Parent::firstChild(); + } + int mapIdx(colIdx idx) + { + return colMap[idx]; + } + void addColumn(colIdx idx, const QString& label) + { + colMap[idx] = Parent::addColumn(label); + colRevMap[colMap[idx]] = idx; + } + void removeColumn(colIdx idx) + { + int col = colMap[idx]; + if (col >= 0) { + Parent::removeColumn(col); + colRevMap[col] = colMap[idx] = -1; + } + } + void setAllOpen(bool open); + void setParentMenu(void); + + bool menuSkip(struct menu *); + + template + void updateMenuList(P*, struct menu*); + + bool updateAll; + + QPixmap symbolYesPix, symbolModPix, symbolNoPix; + QPixmap choiceYesPix, choiceNoPix; + QPixmap menuPix, menuInvPix, menuBackPix, voidPix; + + bool showName, showRange, showData; + enum listMode mode; + enum optionMode optMode; + struct menu *rootEntry; + QColorGroup disabledColorGroup; + QColorGroup inactivedColorGroup; + Q3PopupMenu* headerPopup; + +private: + int colMap[colNr]; + int colRevMap[colNr]; +}; + +class ConfigItem : public Q3ListViewItem { + typedef class Q3ListViewItem Parent; +public: + ConfigItem(Q3ListView *parent, ConfigItem *after, struct menu *m, bool v) + : Parent(parent, after), menu(m), visible(v), goParent(false) + { + init(); + } + ConfigItem(ConfigItem *parent, ConfigItem *after, struct menu *m, bool v) + : Parent(parent, after), menu(m), visible(v), goParent(false) + { + init(); + } + ConfigItem(Q3ListView *parent, ConfigItem *after, bool v) + : Parent(parent, after), menu(0), visible(v), goParent(true) + { + init(); + } + ~ConfigItem(void); + void init(void); + void okRename(int col); + void updateMenu(void); + void testUpdateMenu(bool v); + ConfigList* listView() const + { + return (ConfigList*)Parent::listView(); + } + ConfigItem* firstChild() const + { + return (ConfigItem *)Parent::firstChild(); + } + ConfigItem* nextSibling() const + { + return (ConfigItem *)Parent::nextSibling(); + } + void setText(colIdx idx, const QString& text) + { + Parent::setText(listView()->mapIdx(idx), text); + } + QString text(colIdx idx) const + { + return Parent::text(listView()->mapIdx(idx)); + } + void setPixmap(colIdx idx, const QPixmap& pm) + { + Parent::setPixmap(listView()->mapIdx(idx), pm); + } + const QPixmap* pixmap(colIdx idx) const + { + return Parent::pixmap(listView()->mapIdx(idx)); + } + void paintCell(QPainter* p, const QColorGroup& cg, int column, int width, int align); + + ConfigItem* nextItem; + struct menu *menu; + bool visible; + bool goParent; +}; + +class ConfigLineEdit : public QLineEdit { + Q_OBJECT + typedef class QLineEdit Parent; +public: + ConfigLineEdit(ConfigView* parent); + ConfigView* parent(void) const + { + return (ConfigView*)Parent::parent(); + } + void show(ConfigItem *i); + void keyPressEvent(QKeyEvent *e); + +public: + ConfigItem *item; +}; + +class ConfigView : public Q3VBox { + Q_OBJECT + typedef class Q3VBox Parent; +public: + ConfigView(QWidget* parent, const char *name = 0); + ~ConfigView(void); + static void updateList(ConfigItem* item); + static void updateListAll(void); + + bool showName(void) const { return list->showName; } + bool showRange(void) const { return list->showRange; } + bool showData(void) const { return list->showData; } +public slots: + void setShowName(bool); + void setShowRange(bool); + void setShowData(bool); + void setOptionMode(QAction *); +signals: + void showNameChanged(bool); + void showRangeChanged(bool); + void showDataChanged(bool); +public: + ConfigList* list; + ConfigLineEdit* lineEdit; + + static ConfigView* viewList; + ConfigView* nextView; + + static QAction *showNormalAction; + static QAction *showAllAction; + static QAction *showPromptAction; +}; + +class ConfigInfoView : public Q3TextBrowser { + Q_OBJECT + typedef class Q3TextBrowser Parent; +public: + ConfigInfoView(QWidget* parent, const char *name = 0); + bool showDebug(void) const { return _showDebug; } + +public slots: + void setInfo(struct menu *menu); + void saveSettings(void); + void setShowDebug(bool); + +signals: + void showDebugChanged(bool); + void menuSelected(struct menu *); + +protected: + void symbolInfo(void); + void menuInfo(void); + QString debug_info(struct symbol *sym); + static QString print_filter(const QString &str); + static void expr_print_help(void *data, struct symbol *sym, const char *str); + Q3PopupMenu* createPopupMenu(const QPoint& pos); + void contentsContextMenuEvent(QContextMenuEvent *e); + + struct symbol *sym; + struct menu *_menu; + bool _showDebug; +}; + +class ConfigSearchWindow : public QDialog { + Q_OBJECT + typedef class QDialog Parent; +public: + ConfigSearchWindow(ConfigMainWindow* parent, const char *name = 0); + +public slots: + void saveSettings(void); + void search(void); + +protected: + QLineEdit* editField; + QPushButton* searchButton; + QSplitter* split; + ConfigView* list; + ConfigInfoView* info; + + struct symbol **result; +}; + +class ConfigMainWindow : public Q3MainWindow { + Q_OBJECT + + static Q3Action *saveAction; + static void conf_changed(void); +public: + ConfigMainWindow(void); +public slots: + void changeMenu(struct menu *); + void setMenuLink(struct menu *); + void listFocusChanged(void); + void goBack(void); + void loadConfig(void); + bool saveConfig(void); + void saveConfigAs(void); + void searchConfig(void); + void showSingleView(void); + void showSplitView(void); + void showFullView(void); + void showIntro(void); + void showAbout(void); + void saveSettings(void); + +protected: + void closeEvent(QCloseEvent *e); + + ConfigSearchWindow *searchWindow; + ConfigView *menuView; + ConfigList *menuList; + ConfigView *configView; + ConfigList *configList; + ConfigInfoView *helpText; + Q3ToolBar *toolBar; + Q3Action *backAction; + QSplitter* split1; + QSplitter* split2; +}; diff --git a/kernel/fiasco/tool/kconfig/scripts/kconfig/symbol.c b/kernel/fiasco/tool/kconfig/scripts/kconfig/symbol.c new file mode 100644 index 00000000..22a3c400 --- /dev/null +++ b/kernel/fiasco/tool/kconfig/scripts/kconfig/symbol.c @@ -0,0 +1,1310 @@ +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +#include +#include +#include +#include +#include + +#include "lkc.h" + +struct symbol symbol_yes = { + .name = "y", + .curr = { "y", yes }, + .flags = SYMBOL_CONST|SYMBOL_VALID, +}, symbol_mod = { + .name = "m", + .curr = { "m", mod }, + .flags = SYMBOL_CONST|SYMBOL_VALID, +}, symbol_no = { + .name = "n", + .curr = { "n", no }, + .flags = SYMBOL_CONST|SYMBOL_VALID, +}, symbol_empty = { + .name = "", + .curr = { "", no }, + .flags = SYMBOL_VALID, +}; + +struct symbol *sym_defconfig_list; +struct symbol *modules_sym; +tristate modules_val; + +struct expr *sym_env_list; + +static void sym_add_default(struct symbol *sym, const char *def) +{ + struct property *prop = prop_alloc(P_DEFAULT, sym); + + prop->expr = expr_alloc_symbol(sym_lookup(def, SYMBOL_CONST)); +} + +void sym_init(void) +{ + struct symbol *sym; + struct utsname uts; + static bool inited = false; + + if (inited) + return; + inited = true; + + uname(&uts); + + sym = sym_lookup("UNAME_RELEASE", 0); + sym->type = S_STRING; + sym->flags |= SYMBOL_AUTO; + sym_add_default(sym, uts.release); +} + +enum symbol_type sym_get_type(struct symbol *sym) +{ + enum symbol_type type = sym->type; + + if (type == S_TRISTATE) { + if (sym_is_choice_value(sym) && sym->visible == yes) + type = S_BOOLEAN; + else if (modules_val == no) + type = S_BOOLEAN; + } + return type; +} + +const char *sym_type_name(enum symbol_type type) +{ + switch (type) { + case S_BOOLEAN: + return "boolean"; + case S_TRISTATE: + return "tristate"; + case S_INT: + return "integer"; + case S_HEX: + return "hex"; + case S_STRING: + return "string"; + case S_UNKNOWN: + return "unknown"; + case S_OTHER: + break; + } + return "???"; +} + +struct property *sym_get_choice_prop(struct symbol *sym) +{ + struct property *prop; + + for_all_choices(sym, prop) + return prop; + return NULL; +} + +struct property *sym_get_env_prop(struct symbol *sym) +{ + struct property *prop; + + for_all_properties(sym, prop, P_ENV) + return prop; + return NULL; +} + +struct property *sym_get_default_prop(struct symbol *sym) +{ + struct property *prop; + + for_all_defaults(sym, prop) { + prop->visible.tri = expr_calc_value(prop->visible.expr); + if (prop->visible.tri != no) + return prop; + } + return NULL; +} + +static struct property *sym_get_range_prop(struct symbol *sym) +{ + struct property *prop; + + for_all_properties(sym, prop, P_RANGE) { + prop->visible.tri = expr_calc_value(prop->visible.expr); + if (prop->visible.tri != no) + return prop; + } + return NULL; +} + +static int sym_get_range_val(struct symbol *sym, int base) +{ + sym_calc_value(sym); + switch (sym->type) { + case S_INT: + base = 10; + break; + case S_HEX: + base = 16; + break; + default: + break; + } + return strtol(sym->curr.val, NULL, base); +} + +static void sym_validate_range(struct symbol *sym) +{ + struct property *prop; + int base, val, val2; + char str[64]; + + switch (sym->type) { + case S_INT: + base = 10; + break; + case S_HEX: + base = 16; + break; + default: + return; + } + prop = sym_get_range_prop(sym); + if (!prop) + return; + val = strtol(sym->curr.val, NULL, base); + val2 = sym_get_range_val(prop->expr->left.sym, base); + if (val >= val2) { + val2 = sym_get_range_val(prop->expr->right.sym, base); + if (val <= val2) + return; + } + if (sym->type == S_INT) + sprintf(str, "%d", val2); + else + sprintf(str, "0x%x", val2); + sym->curr.val = strdup(str); +} + +static void sym_calc_visibility(struct symbol *sym) +{ + struct property *prop; + tristate tri; + + /* any prompt visible? */ + tri = no; + for_all_prompts(sym, prop) { + prop->visible.tri = expr_calc_value(prop->visible.expr); + tri = EXPR_OR(tri, prop->visible.tri); + } + if (tri == mod && (sym->type != S_TRISTATE || modules_val == no)) + tri = yes; + if (sym->visible != tri) { + sym->visible = tri; + sym_set_changed(sym); + } + if (sym_is_choice_value(sym)) + return; + /* defaulting to "yes" if no explicit "depends on" are given */ + tri = yes; + if (sym->dir_dep.expr) + tri = expr_calc_value(sym->dir_dep.expr); + if (tri == mod) + tri = yes; + if (sym->dir_dep.tri != tri) { + sym->dir_dep.tri = tri; + sym_set_changed(sym); + } + tri = no; + if (sym->rev_dep.expr) + tri = expr_calc_value(sym->rev_dep.expr); + if (tri == mod && sym_get_type(sym) == S_BOOLEAN) + tri = yes; + if (sym->rev_dep.tri != tri) { + sym->rev_dep.tri = tri; + sym_set_changed(sym); + } +} + +/* + * Find the default symbol for a choice. + * First try the default values for the choice symbol + * Next locate the first visible choice value + * Return NULL if none was found + */ +struct symbol *sym_choice_default(struct symbol *sym) +{ + struct symbol *def_sym; + struct property *prop; + struct expr *e; + + /* any of the defaults visible? */ + for_all_defaults(sym, prop) { + prop->visible.tri = expr_calc_value(prop->visible.expr); + if (prop->visible.tri == no) + continue; + def_sym = prop_get_symbol(prop); + if (def_sym->visible != no) + return def_sym; + } + + /* just get the first visible value */ + prop = sym_get_choice_prop(sym); + expr_list_for_each_sym(prop->expr, e, def_sym) + if (def_sym->visible != no) + return def_sym; + + /* failed to locate any defaults */ + return NULL; +} + +static struct symbol *sym_calc_choice(struct symbol *sym) +{ + struct symbol *def_sym; + struct property *prop; + struct expr *e; + int flags; + + /* first calculate all choice values' visibilities */ + flags = sym->flags; + prop = sym_get_choice_prop(sym); + expr_list_for_each_sym(prop->expr, e, def_sym) { + sym_calc_visibility(def_sym); + if (def_sym->visible != no) + flags &= def_sym->flags; + } + + sym->flags &= flags | ~SYMBOL_DEF_USER; + + /* is the user choice visible? */ + def_sym = sym->def[S_DEF_USER].val; + if (def_sym && def_sym->visible != no) + return def_sym; + + def_sym = sym_choice_default(sym); + + if (def_sym == NULL) + /* no choice? reset tristate value */ + sym->curr.tri = no; + + return def_sym; +} + +void sym_calc_value(struct symbol *sym) +{ + struct symbol_value newval, oldval; + struct property *prop; + struct expr *e; + + if (!sym) + return; + + if (sym->flags & SYMBOL_VALID) + return; + sym->flags |= SYMBOL_VALID; + + oldval = sym->curr; + + switch (sym->type) { + case S_INT: + case S_HEX: + case S_STRING: + newval = symbol_empty.curr; + break; + case S_BOOLEAN: + case S_TRISTATE: + newval = symbol_no.curr; + break; + default: + sym->curr.val = sym->name; + sym->curr.tri = no; + return; + } + if (!sym_is_choice_value(sym)) + sym->flags &= ~SYMBOL_WRITE; + + sym_calc_visibility(sym); + + /* set default if recursively called */ + sym->curr = newval; + + switch (sym_get_type(sym)) { + case S_BOOLEAN: + case S_TRISTATE: + if (sym_is_choice_value(sym) && sym->visible == yes) { + prop = sym_get_choice_prop(sym); + newval.tri = (prop_get_symbol(prop)->curr.val == sym) ? yes : no; + } else { + if (sym->visible != no) { + /* if the symbol is visible use the user value + * if available, otherwise try the default value + */ + sym->flags |= SYMBOL_WRITE; + if (sym_has_value(sym)) { + newval.tri = EXPR_AND(sym->def[S_DEF_USER].tri, + sym->visible); + goto calc_newval; + } + } + if (sym->rev_dep.tri != no) + sym->flags |= SYMBOL_WRITE; + if (!sym_is_choice(sym)) { + prop = sym_get_default_prop(sym); + if (prop) { + sym->flags |= SYMBOL_WRITE; + newval.tri = EXPR_AND(expr_calc_value(prop->expr), + prop->visible.tri); + } + } + calc_newval: + if (sym->dir_dep.tri == no && sym->rev_dep.tri != no) { + struct expr *e; + e = expr_simplify_unmet_dep(sym->rev_dep.expr, + sym->dir_dep.expr); + fprintf(stderr, "warning: ("); + expr_fprint(e, stderr); + fprintf(stderr, ") selects %s which has unmet direct dependencies (", + sym->name); + expr_fprint(sym->dir_dep.expr, stderr); + fprintf(stderr, ")\n"); + expr_free(e); + } + newval.tri = EXPR_OR(newval.tri, sym->rev_dep.tri); + } + if (newval.tri == mod && sym_get_type(sym) == S_BOOLEAN) + newval.tri = yes; + break; + case S_STRING: + case S_HEX: + case S_INT: + if (sym->visible != no) { + sym->flags |= SYMBOL_WRITE; + if (sym_has_value(sym)) { + newval.val = sym->def[S_DEF_USER].val; + break; + } + } + prop = sym_get_default_prop(sym); + if (prop) { + struct symbol *ds = prop_get_symbol(prop); + if (ds) { + sym->flags |= SYMBOL_WRITE; + sym_calc_value(ds); + newval.val = ds->curr.val; + } + } + break; + default: + ; + } + + sym->curr = newval; + if (sym_is_choice(sym) && newval.tri == yes) + sym->curr.val = sym_calc_choice(sym); + sym_validate_range(sym); + + if (memcmp(&oldval, &sym->curr, sizeof(oldval))) { + sym_set_changed(sym); + if (modules_sym == sym) { + sym_set_all_changed(); + modules_val = modules_sym->curr.tri; + } + } + + if (sym_is_choice(sym)) { + struct symbol *choice_sym; + + prop = sym_get_choice_prop(sym); + expr_list_for_each_sym(prop->expr, e, choice_sym) { + if ((sym->flags & SYMBOL_WRITE) && + choice_sym->visible != no) + choice_sym->flags |= SYMBOL_WRITE; + if (sym->flags & SYMBOL_CHANGED) + sym_set_changed(choice_sym); + } + } + + if (sym->flags & SYMBOL_AUTO) + sym->flags &= ~SYMBOL_WRITE; +} + +void sym_clear_all_valid(void) +{ + struct symbol *sym; + int i; + + for_all_symbols(i, sym) + sym->flags &= ~SYMBOL_VALID; + sym_add_change_count(1); + if (modules_sym) + sym_calc_value(modules_sym); +} + +void sym_set_changed(struct symbol *sym) +{ + struct property *prop; + + sym->flags |= SYMBOL_CHANGED; + for (prop = sym->prop; prop; prop = prop->next) { + if (prop->menu) + prop->menu->flags |= MENU_CHANGED; + } +} + +void sym_set_all_changed(void) +{ + struct symbol *sym; + int i; + + for_all_symbols(i, sym) + sym_set_changed(sym); +} + +bool sym_tristate_within_range(struct symbol *sym, tristate val) +{ + int type = sym_get_type(sym); + + if (sym->visible == no) + return false; + + if (type != S_BOOLEAN && type != S_TRISTATE) + return false; + + if (type == S_BOOLEAN && val == mod) + return false; + if (sym->visible <= sym->rev_dep.tri) + return false; + if (sym_is_choice_value(sym) && sym->visible == yes) + return val == yes; + return val >= sym->rev_dep.tri && val <= sym->visible; +} + +bool sym_set_tristate_value(struct symbol *sym, tristate val) +{ + tristate oldval = sym_get_tristate_value(sym); + + if (oldval != val && !sym_tristate_within_range(sym, val)) + return false; + + if (!(sym->flags & SYMBOL_DEF_USER)) { + sym->flags |= SYMBOL_DEF_USER; + sym_set_changed(sym); + } + /* + * setting a choice value also resets the new flag of the choice + * symbol and all other choice values. + */ + if (sym_is_choice_value(sym) && val == yes) { + struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym)); + struct property *prop; + struct expr *e; + + cs->def[S_DEF_USER].val = sym; + cs->flags |= SYMBOL_DEF_USER; + prop = sym_get_choice_prop(cs); + for (e = prop->expr; e; e = e->left.expr) { + if (e->right.sym->visible != no) + e->right.sym->flags |= SYMBOL_DEF_USER; + } + } + + sym->def[S_DEF_USER].tri = val; + if (oldval != val) + sym_clear_all_valid(); + + return true; +} + +tristate sym_toggle_tristate_value(struct symbol *sym) +{ + tristate oldval, newval; + + oldval = newval = sym_get_tristate_value(sym); + do { + switch (newval) { + case no: + newval = mod; + break; + case mod: + newval = yes; + break; + case yes: + newval = no; + break; + } + if (sym_set_tristate_value(sym, newval)) + break; + } while (oldval != newval); + return newval; +} + +bool sym_string_valid(struct symbol *sym, const char *str) +{ + signed char ch; + + switch (sym->type) { + case S_STRING: + return true; + case S_INT: + ch = *str++; + if (ch == '-') + ch = *str++; + if (!isdigit(ch)) + return false; + if (ch == '0' && *str != 0) + return false; + while ((ch = *str++)) { + if (!isdigit(ch)) + return false; + } + return true; + case S_HEX: + if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) + str += 2; + ch = *str++; + do { + if (!isxdigit(ch)) + return false; + } while ((ch = *str++)); + return true; + case S_BOOLEAN: + case S_TRISTATE: + switch (str[0]) { + case 'y': case 'Y': + case 'm': case 'M': + case 'n': case 'N': + return true; + } + return false; + default: + return false; + } +} + +bool sym_string_within_range(struct symbol *sym, const char *str) +{ + struct property *prop; + int val; + + switch (sym->type) { + case S_STRING: + return sym_string_valid(sym, str); + case S_INT: + if (!sym_string_valid(sym, str)) + return false; + prop = sym_get_range_prop(sym); + if (!prop) + return true; + val = strtol(str, NULL, 10); + return val >= sym_get_range_val(prop->expr->left.sym, 10) && + val <= sym_get_range_val(prop->expr->right.sym, 10); + case S_HEX: + if (!sym_string_valid(sym, str)) + return false; + prop = sym_get_range_prop(sym); + if (!prop) + return true; + val = strtol(str, NULL, 16); + return val >= sym_get_range_val(prop->expr->left.sym, 16) && + val <= sym_get_range_val(prop->expr->right.sym, 16); + case S_BOOLEAN: + case S_TRISTATE: + switch (str[0]) { + case 'y': case 'Y': + return sym_tristate_within_range(sym, yes); + case 'm': case 'M': + return sym_tristate_within_range(sym, mod); + case 'n': case 'N': + return sym_tristate_within_range(sym, no); + } + return false; + default: + return false; + } +} + +bool sym_set_string_value(struct symbol *sym, const char *newval) +{ + const char *oldval; + char *val; + int size; + + switch (sym->type) { + case S_BOOLEAN: + case S_TRISTATE: + switch (newval[0]) { + case 'y': case 'Y': + return sym_set_tristate_value(sym, yes); + case 'm': case 'M': + return sym_set_tristate_value(sym, mod); + case 'n': case 'N': + return sym_set_tristate_value(sym, no); + } + return false; + default: + ; + } + + if (!sym_string_within_range(sym, newval)) + return false; + + if (!(sym->flags & SYMBOL_DEF_USER)) { + sym->flags |= SYMBOL_DEF_USER; + sym_set_changed(sym); + } + + oldval = sym->def[S_DEF_USER].val; + size = strlen(newval) + 1; + if (sym->type == S_HEX && (newval[0] != '0' || (newval[1] != 'x' && newval[1] != 'X'))) { + size += 2; + sym->def[S_DEF_USER].val = val = malloc(size); + *val++ = '0'; + *val++ = 'x'; + } else if (!oldval || strcmp(oldval, newval)) + sym->def[S_DEF_USER].val = val = malloc(size); + else + return true; + + strcpy(val, newval); + free((void *)oldval); + sym_clear_all_valid(); + + return true; +} + +/* + * Find the default value associated to a symbol. + * For tristate symbol handle the modules=n case + * in which case "m" becomes "y". + * If the symbol does not have any default then fallback + * to the fixed default values. + */ +const char *sym_get_string_default(struct symbol *sym) +{ + struct property *prop; + struct symbol *ds; + const char *str; + tristate val; + + sym_calc_visibility(sym); + sym_calc_value(modules_sym); + val = symbol_no.curr.tri; + str = symbol_empty.curr.val; + + /* If symbol has a default value look it up */ + prop = sym_get_default_prop(sym); + if (prop != NULL) { + switch (sym->type) { + case S_BOOLEAN: + case S_TRISTATE: + /* The visibility may limit the value from yes => mod */ + val = EXPR_AND(expr_calc_value(prop->expr), prop->visible.tri); + break; + default: + /* + * The following fails to handle the situation + * where a default value is further limited by + * the valid range. + */ + ds = prop_get_symbol(prop); + if (ds != NULL) { + sym_calc_value(ds); + str = (const char *)ds->curr.val; + } + } + } + + /* Handle select statements */ + val = EXPR_OR(val, sym->rev_dep.tri); + + /* transpose mod to yes if modules are not enabled */ + if (val == mod) + if (!sym_is_choice_value(sym) && modules_sym->curr.tri == no) + val = yes; + + /* transpose mod to yes if type is bool */ + if (sym->type == S_BOOLEAN && val == mod) + val = yes; + + switch (sym->type) { + case S_BOOLEAN: + case S_TRISTATE: + switch (val) { + case no: return "n"; + case mod: return "m"; + case yes: return "y"; + } + case S_INT: + case S_HEX: + return str; + case S_STRING: + return str; + case S_OTHER: + case S_UNKNOWN: + break; + } + return ""; +} + +const char *sym_get_string_value(struct symbol *sym) +{ + tristate val; + + switch (sym->type) { + case S_BOOLEAN: + case S_TRISTATE: + val = sym_get_tristate_value(sym); + switch (val) { + case no: + return "n"; + case mod: + sym_calc_value(modules_sym); + return (modules_sym->curr.tri == no) ? "n" : "m"; + case yes: + return "y"; + } + break; + default: + ; + } + return (const char *)sym->curr.val; +} + +bool sym_is_changable(struct symbol *sym) +{ + return sym->visible > sym->rev_dep.tri; +} + +static unsigned strhash(const char *s) +{ + /* fnv32 hash */ + unsigned hash = 2166136261U; + for (; *s; s++) + hash = (hash ^ *s) * 0x01000193; + return hash; +} + +struct symbol *sym_lookup(const char *name, int flags) +{ + struct symbol *symbol; + char *new_name; + int hash; + + if (name) { + if (name[0] && !name[1]) { + switch (name[0]) { + case 'y': return &symbol_yes; + case 'm': return &symbol_mod; + case 'n': return &symbol_no; + } + } + hash = strhash(name) % SYMBOL_HASHSIZE; + + for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) { + if (symbol->name && + !strcmp(symbol->name, name) && + (flags ? symbol->flags & flags + : !(symbol->flags & (SYMBOL_CONST|SYMBOL_CHOICE)))) + return symbol; + } + new_name = strdup(name); + } else { + new_name = NULL; + hash = 0; + } + + symbol = malloc(sizeof(*symbol)); + memset(symbol, 0, sizeof(*symbol)); + symbol->name = new_name; + symbol->type = S_UNKNOWN; + symbol->flags |= flags; + + symbol->next = symbol_hash[hash]; + symbol_hash[hash] = symbol; + + return symbol; +} + +struct symbol *sym_find(const char *name) +{ + struct symbol *symbol = NULL; + int hash = 0; + + if (!name) + return NULL; + + if (name[0] && !name[1]) { + switch (name[0]) { + case 'y': return &symbol_yes; + case 'm': return &symbol_mod; + case 'n': return &symbol_no; + } + } + hash = strhash(name) % SYMBOL_HASHSIZE; + + for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) { + if (symbol->name && + !strcmp(symbol->name, name) && + !(symbol->flags & SYMBOL_CONST)) + break; + } + + return symbol; +} + +/* + * Expand symbol's names embedded in the string given in argument. Symbols' + * name to be expanded shall be prefixed by a '$'. Unknown symbol expands to + * the empty string. + */ +const char *sym_expand_string_value(const char *in) +{ + const char *src; + char *res; + size_t reslen; + + reslen = strlen(in) + 1; + res = malloc(reslen); + res[0] = '\0'; + + while ((src = strchr(in, '$'))) { + char *p, name[SYMBOL_MAXLENGTH]; + const char *symval = ""; + struct symbol *sym; + size_t newlen; + + strncat(res, in, src - in); + src++; + + p = name; + while (isalnum(*src) || *src == '_') + *p++ = *src++; + *p = '\0'; + + sym = sym_find(name); + if (sym != NULL) { + sym_calc_value(sym); + symval = sym_get_string_value(sym); + } + + newlen = strlen(res) + strlen(symval) + strlen(src) + 1; + if (newlen > reslen) { + reslen = newlen; + res = realloc(res, reslen); + } + + strcat(res, symval); + in = src; + } + strcat(res, in); + + return res; +} + +const char *sym_escape_string_value(const char *in) +{ + const char *p; + size_t reslen; + char *res; + size_t l; + + reslen = strlen(in) + strlen("\"\"") + 1; + + p = in; + for (;;) { + l = strcspn(p, "\"\\"); + p += l; + + if (p[0] == '\0') + break; + + reslen++; + p++; + } + + res = malloc(reslen); + res[0] = '\0'; + + strcat(res, "\""); + + p = in; + for (;;) { + l = strcspn(p, "\"\\"); + strncat(res, p, l); + p += l; + + if (p[0] == '\0') + break; + + strcat(res, "\\"); + strncat(res, p++, 1); + } + + strcat(res, "\""); + return res; +} + +struct symbol **sym_re_search(const char *pattern) +{ + struct symbol *sym, **sym_arr = NULL; + int i, cnt, size; + regex_t re; + + cnt = size = 0; + /* Skip if empty */ + if (strlen(pattern) == 0) + return NULL; + if (regcomp(&re, pattern, REG_EXTENDED|REG_NOSUB|REG_ICASE)) + return NULL; + + for_all_symbols(i, sym) { + if (sym->flags & SYMBOL_CONST || !sym->name) + continue; + if (regexec(&re, sym->name, 0, NULL, 0)) + continue; + if (cnt + 1 >= size) { + void *tmp = sym_arr; + size += 16; + sym_arr = realloc(sym_arr, size * sizeof(struct symbol *)); + if (!sym_arr) { + free(tmp); + return NULL; + } + } + sym_calc_value(sym); + sym_arr[cnt++] = sym; + } + if (sym_arr) + sym_arr[cnt] = NULL; + regfree(&re); + + return sym_arr; +} + +/* + * When we check for recursive dependencies we use a stack to save + * current state so we can print out relevant info to user. + * The entries are located on the call stack so no need to free memory. + * Note inser() remove() must always match to properly clear the stack. + */ +static struct dep_stack { + struct dep_stack *prev, *next; + struct symbol *sym; + struct property *prop; + struct expr *expr; +} *check_top; + +static void dep_stack_insert(struct dep_stack *stack, struct symbol *sym) +{ + memset(stack, 0, sizeof(*stack)); + if (check_top) + check_top->next = stack; + stack->prev = check_top; + stack->sym = sym; + check_top = stack; +} + +static void dep_stack_remove(void) +{ + check_top = check_top->prev; + if (check_top) + check_top->next = NULL; +} + +/* + * Called when we have detected a recursive dependency. + * check_top point to the top of the stact so we use + * the ->prev pointer to locate the bottom of the stack. + */ +static void sym_check_print_recursive(struct symbol *last_sym) +{ + struct dep_stack *stack; + struct symbol *sym, *next_sym; + struct menu *menu = NULL; + struct property *prop; + struct dep_stack cv_stack; + + if (sym_is_choice_value(last_sym)) { + dep_stack_insert(&cv_stack, last_sym); + last_sym = prop_get_symbol(sym_get_choice_prop(last_sym)); + } + + for (stack = check_top; stack != NULL; stack = stack->prev) + if (stack->sym == last_sym) + break; + if (!stack) { + fprintf(stderr, "unexpected recursive dependency error\n"); + return; + } + + for (; stack; stack = stack->next) { + sym = stack->sym; + next_sym = stack->next ? stack->next->sym : last_sym; + prop = stack->prop; + if (prop == NULL) + prop = stack->sym->prop; + + /* for choice values find the menu entry (used below) */ + if (sym_is_choice(sym) || sym_is_choice_value(sym)) { + for (prop = sym->prop; prop; prop = prop->next) { + menu = prop->menu; + if (prop->menu) + break; + } + } + if (stack->sym == last_sym) + fprintf(stderr, "%s:%d:error: recursive dependency detected!\n", + prop->file->name, prop->lineno); + if (stack->expr) { + fprintf(stderr, "%s:%d:\tsymbol %s %s value contains %s\n", + prop->file->name, prop->lineno, + sym->name ? sym->name : "", + prop_get_type_name(prop->type), + next_sym->name ? next_sym->name : ""); + } else if (stack->prop) { + fprintf(stderr, "%s:%d:\tsymbol %s depends on %s\n", + prop->file->name, prop->lineno, + sym->name ? sym->name : "", + next_sym->name ? next_sym->name : ""); + } else if (sym_is_choice(sym)) { + fprintf(stderr, "%s:%d:\tchoice %s contains symbol %s\n", + menu->file->name, menu->lineno, + sym->name ? sym->name : "", + next_sym->name ? next_sym->name : ""); + } else if (sym_is_choice_value(sym)) { + fprintf(stderr, "%s:%d:\tsymbol %s is part of choice %s\n", + menu->file->name, menu->lineno, + sym->name ? sym->name : "", + next_sym->name ? next_sym->name : ""); + } else { + fprintf(stderr, "%s:%d:\tsymbol %s is selected by %s\n", + prop->file->name, prop->lineno, + sym->name ? sym->name : "", + next_sym->name ? next_sym->name : ""); + } + } + + if (check_top == &cv_stack) + dep_stack_remove(); +} + +static struct symbol *sym_check_expr_deps(struct expr *e) +{ + struct symbol *sym; + + if (!e) + return NULL; + switch (e->type) { + case E_OR: + case E_AND: + sym = sym_check_expr_deps(e->left.expr); + if (sym) + return sym; + return sym_check_expr_deps(e->right.expr); + case E_NOT: + return sym_check_expr_deps(e->left.expr); + case E_EQUAL: + case E_UNEQUAL: + sym = sym_check_deps(e->left.sym); + if (sym) + return sym; + return sym_check_deps(e->right.sym); + case E_SYMBOL: + return sym_check_deps(e->left.sym); + default: + break; + } + printf("Oops! How to check %d?\n", e->type); + return NULL; +} + +/* return NULL when dependencies are OK */ +static struct symbol *sym_check_sym_deps(struct symbol *sym) +{ + struct symbol *sym2; + struct property *prop; + struct dep_stack stack; + + dep_stack_insert(&stack, sym); + + sym2 = sym_check_expr_deps(sym->rev_dep.expr); + if (sym2) + goto out; + + for (prop = sym->prop; prop; prop = prop->next) { + if (prop->type == P_CHOICE || prop->type == P_SELECT) + continue; + stack.prop = prop; + sym2 = sym_check_expr_deps(prop->visible.expr); + if (sym2) + break; + if (prop->type != P_DEFAULT || sym_is_choice(sym)) + continue; + stack.expr = prop->expr; + sym2 = sym_check_expr_deps(prop->expr); + if (sym2) + break; + stack.expr = NULL; + } + +out: + dep_stack_remove(); + + return sym2; +} + +static struct symbol *sym_check_choice_deps(struct symbol *choice) +{ + struct symbol *sym, *sym2; + struct property *prop; + struct expr *e; + struct dep_stack stack; + + dep_stack_insert(&stack, choice); + + prop = sym_get_choice_prop(choice); + expr_list_for_each_sym(prop->expr, e, sym) + sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED); + + choice->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED); + sym2 = sym_check_sym_deps(choice); + choice->flags &= ~SYMBOL_CHECK; + if (sym2) + goto out; + + expr_list_for_each_sym(prop->expr, e, sym) { + sym2 = sym_check_sym_deps(sym); + if (sym2) + break; + } +out: + expr_list_for_each_sym(prop->expr, e, sym) + sym->flags &= ~SYMBOL_CHECK; + + if (sym2 && sym_is_choice_value(sym2) && + prop_get_symbol(sym_get_choice_prop(sym2)) == choice) + sym2 = choice; + + dep_stack_remove(); + + return sym2; +} + +struct symbol *sym_check_deps(struct symbol *sym) +{ + struct symbol *sym2; + struct property *prop; + + if (sym->flags & SYMBOL_CHECK) { + sym_check_print_recursive(sym); + return sym; + } + if (sym->flags & SYMBOL_CHECKED) + return NULL; + + if (sym_is_choice_value(sym)) { + struct dep_stack stack; + + /* for choice groups start the check with main choice symbol */ + dep_stack_insert(&stack, sym); + prop = sym_get_choice_prop(sym); + sym2 = sym_check_deps(prop_get_symbol(prop)); + dep_stack_remove(); + } else if (sym_is_choice(sym)) { + sym2 = sym_check_choice_deps(sym); + } else { + sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED); + sym2 = sym_check_sym_deps(sym); + sym->flags &= ~SYMBOL_CHECK; + } + + if (sym2 && sym2 == sym) + sym2 = NULL; + + return sym2; +} + +struct property *prop_alloc(enum prop_type type, struct symbol *sym) +{ + struct property *prop; + struct property **propp; + + prop = malloc(sizeof(*prop)); + memset(prop, 0, sizeof(*prop)); + prop->type = type; + prop->sym = sym; + prop->file = current_file; + prop->lineno = zconf_lineno(); + + /* append property to the prop list of symbol */ + if (sym) { + for (propp = &sym->prop; *propp; propp = &(*propp)->next) + ; + *propp = prop; + } + + return prop; +} + +struct symbol *prop_get_symbol(struct property *prop) +{ + if (prop->expr && (prop->expr->type == E_SYMBOL || + prop->expr->type == E_LIST)) + return prop->expr->left.sym; + return NULL; +} + +const char *prop_get_type_name(enum prop_type type) +{ + switch (type) { + case P_PROMPT: + return "prompt"; + case P_ENV: + return "env"; + case P_COMMENT: + return "comment"; + case P_MENU: + return "menu"; + case P_DEFAULT: + return "default"; + case P_CHOICE: + return "choice"; + case P_SELECT: + return "select"; + case P_RANGE: + return "range"; + case P_SYMBOL: + return "symbol"; + case P_UNKNOWN: + break; + } + return "unknown"; +} + +static void prop_add_env(const char *env) +{ + struct symbol *sym, *sym2; + struct property *prop; + char *p; + + sym = current_entry->sym; + sym->flags |= SYMBOL_AUTO; + for_all_properties(sym, prop, P_ENV) { + sym2 = prop_get_symbol(prop); + if (strcmp(sym2->name, env)) + menu_warn(current_entry, "redefining environment symbol from %s", + sym2->name); + return; + } + + prop = prop_alloc(P_ENV, sym); + prop->expr = expr_alloc_symbol(sym_lookup(env, SYMBOL_CONST)); + + sym_env_list = expr_alloc_one(E_LIST, sym_env_list); + sym_env_list->right.sym = sym; + + p = getenv(env); + if (p) + sym_add_default(sym, p); + else + menu_warn(current_entry, "environment variable %s undefined", env); +} diff --git a/kernel/fiasco/tool/kconfig/scripts/kconfig/util.c b/kernel/fiasco/tool/kconfig/scripts/kconfig/util.c new file mode 100644 index 00000000..d0b8b231 --- /dev/null +++ b/kernel/fiasco/tool/kconfig/scripts/kconfig/util.c @@ -0,0 +1,140 @@ +/* + * Copyright (C) 2002-2005 Roman Zippel + * Copyright (C) 2002-2005 Sam Ravnborg + * + * Released under the terms of the GNU GPL v2.0. + */ + +#include +#include +#include +#include "lkc.h" + +/* file already present in list? If not add it */ +struct file *file_lookup(const char *name) +{ + struct file *file; + const char *file_name = sym_expand_string_value(name); + + for (file = file_list; file; file = file->next) { + if (!strcmp(name, file->name)) { + free((void *)file_name); + return file; + } + } + + file = malloc(sizeof(*file)); + memset(file, 0, sizeof(*file)); + file->name = file_name; + file->next = file_list; + file_list = file; + return file; +} + +/* write a dependency file as used by kbuild to track dependencies */ +int file_write_dep(const char *name) +{ + struct symbol *sym, *env_sym; + struct expr *e; + struct file *file; + FILE *out; + + if (!name) + name = ".kconfig.d"; + out = fopen("..config.tmp", "w"); + if (!out) + return 1; + fprintf(out, "deps_config := \\\n"); + for (file = file_list; file; file = file->next) { + if (file->next) + fprintf(out, "\t%s \\\n", file->name); + else + fprintf(out, "\t%s\n", file->name); + } + fprintf(out, "\n%s: \\\n" + "\t$(deps_config)\n\n", conf_get_autoconfig_name()); + + expr_list_for_each_sym(sym_env_list, e, sym) { + struct property *prop; + const char *value; + + prop = sym_get_env_prop(sym); + env_sym = prop_get_symbol(prop); + if (!env_sym) + continue; + value = getenv(env_sym->name); + if (!value) + value = ""; + fprintf(out, "ifneq \"$(%s)\" \"%s\"\n", env_sym->name, value); + fprintf(out, "%s: FORCE\n", conf_get_autoconfig_name()); + fprintf(out, "endif\n"); + } + + fprintf(out, "\n$(deps_config): ;\n"); + fclose(out); + rename("..config.tmp", name); + return 0; +} + + +/* Allocate initial growable string */ +struct gstr str_new(void) +{ + struct gstr gs; + gs.s = malloc(sizeof(char) * 64); + gs.len = 64; + gs.max_width = 0; + strcpy(gs.s, "\0"); + return gs; +} + +/* Allocate and assign growable string */ +struct gstr str_assign(const char *s) +{ + struct gstr gs; + gs.s = strdup(s); + gs.len = strlen(s) + 1; + gs.max_width = 0; + return gs; +} + +/* Free storage for growable string */ +void str_free(struct gstr *gs) +{ + if (gs->s) + free(gs->s); + gs->s = NULL; + gs->len = 0; +} + +/* Append to growable string */ +void str_append(struct gstr *gs, const char *s) +{ + size_t l; + if (s) { + l = strlen(gs->s) + strlen(s) + 1; + if (l > gs->len) { + gs->s = realloc(gs->s, l); + gs->len = l; + } + strcat(gs->s, s); + } +} + +/* Append printf formatted string to growable string */ +void str_printf(struct gstr *gs, const char *fmt, ...) +{ + va_list ap; + char s[10000]; /* big enough... */ + va_start(ap, fmt); + vsnprintf(s, sizeof(s), fmt, ap); + str_append(gs, s); + va_end(ap); +} + +/* Retrieve value of growable string */ +const char *str_get(struct gstr *gs) +{ + return gs->s; +} + diff --git a/kernel/fiasco/tool/kconfig/scripts/kconfig/zconf.gperf b/kernel/fiasco/tool/kconfig/scripts/kconfig/zconf.gperf new file mode 100644 index 00000000..f14ab411 --- /dev/null +++ b/kernel/fiasco/tool/kconfig/scripts/kconfig/zconf.gperf @@ -0,0 +1,47 @@ +%language=ANSI-C +%define hash-function-name kconf_id_hash +%define lookup-function-name kconf_id_lookup +%define string-pool-name kconf_id_strings +%compare-strncmp +%enum +%pic +%struct-type + +struct kconf_id; + +static const struct kconf_id *kconf_id_lookup(register const char *str, register unsigned int len); + +%% +mainmenu, T_MAINMENU, TF_COMMAND +menu, T_MENU, TF_COMMAND +endmenu, T_ENDMENU, TF_COMMAND +source, T_SOURCE, TF_COMMAND +choice, T_CHOICE, TF_COMMAND +endchoice, T_ENDCHOICE, TF_COMMAND +comment, T_COMMENT, TF_COMMAND +config, T_CONFIG, TF_COMMAND +menuconfig, T_MENUCONFIG, TF_COMMAND +help, T_HELP, TF_COMMAND +if, T_IF, TF_COMMAND|TF_PARAM +endif, T_ENDIF, TF_COMMAND +depends, T_DEPENDS, TF_COMMAND +optional, T_OPTIONAL, TF_COMMAND +default, T_DEFAULT, TF_COMMAND, S_UNKNOWN +prompt, T_PROMPT, TF_COMMAND +tristate, T_TYPE, TF_COMMAND, S_TRISTATE +def_tristate, T_DEFAULT, TF_COMMAND, S_TRISTATE +bool, T_TYPE, TF_COMMAND, S_BOOLEAN +boolean, T_TYPE, TF_COMMAND, S_BOOLEAN +def_bool, T_DEFAULT, TF_COMMAND, S_BOOLEAN +int, T_TYPE, TF_COMMAND, S_INT +hex, T_TYPE, TF_COMMAND, S_HEX +string, T_TYPE, TF_COMMAND, S_STRING +select, T_SELECT, TF_COMMAND +range, T_RANGE, TF_COMMAND +visible, T_VISIBLE, TF_COMMAND +option, T_OPTION, TF_COMMAND +on, T_ON, TF_PARAM +modules, T_OPT_MODULES, TF_OPTION +defconfig_list, T_OPT_DEFCONFIG_LIST,TF_OPTION +env, T_OPT_ENV, TF_OPTION +%% diff --git a/kernel/fiasco/tool/kconfig/scripts/kconfig/zconf.hash.c_shipped b/kernel/fiasco/tool/kconfig/scripts/kconfig/zconf.hash.c_shipped new file mode 100644 index 00000000..40df0005 --- /dev/null +++ b/kernel/fiasco/tool/kconfig/scripts/kconfig/zconf.hash.c_shipped @@ -0,0 +1,286 @@ +/* ANSI-C code produced by gperf version 3.0.4 */ +/* Command-line: gperf -t --output-file scripts/kconfig/zconf.hash.c_shipped -a -C -E -g -k '1,3,$' -p -t scripts/kconfig/zconf.gperf */ + +#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \ + && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \ + && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \ + && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \ + && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \ + && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \ + && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \ + && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \ + && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \ + && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \ + && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \ + && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \ + && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \ + && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \ + && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \ + && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \ + && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \ + && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \ + && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \ + && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \ + && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \ + && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \ + && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126)) +/* The character set is not based on ISO-646. */ +#error "gperf generated tables don't work with this execution character set. Please report a bug to ." +#endif + +#line 10 "scripts/kconfig/zconf.gperf" +struct kconf_id; + +static const struct kconf_id *kconf_id_lookup(register const char *str, register unsigned int len); +/* maximum key range = 71, duplicates = 0 */ + +#ifdef __GNUC__ +__inline +#else +#ifdef __cplusplus +inline +#endif +#endif +static unsigned int +kconf_id_hash (register const char *str, register unsigned int len) +{ + static const unsigned char asso_values[] = + { + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 25, 25, + 0, 0, 0, 5, 0, 0, 73, 73, 5, 0, + 10, 5, 45, 73, 20, 20, 0, 15, 15, 73, + 20, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73 + }; + register int hval = len; + + switch (hval) + { + default: + hval += asso_values[(unsigned char)str[2]]; + /*FALLTHROUGH*/ + case 2: + case 1: + hval += asso_values[(unsigned char)str[0]]; + break; + } + return hval + asso_values[(unsigned char)str[len - 1]]; +} + +struct kconf_id_strings_t + { + char kconf_id_strings_str2[sizeof("if")]; + char kconf_id_strings_str3[sizeof("int")]; + char kconf_id_strings_str5[sizeof("endif")]; + char kconf_id_strings_str7[sizeof("default")]; + char kconf_id_strings_str8[sizeof("tristate")]; + char kconf_id_strings_str9[sizeof("endchoice")]; + char kconf_id_strings_str12[sizeof("def_tristate")]; + char kconf_id_strings_str13[sizeof("def_bool")]; + char kconf_id_strings_str14[sizeof("defconfig_list")]; + char kconf_id_strings_str17[sizeof("on")]; + char kconf_id_strings_str18[sizeof("optional")]; + char kconf_id_strings_str21[sizeof("option")]; + char kconf_id_strings_str22[sizeof("endmenu")]; + char kconf_id_strings_str23[sizeof("mainmenu")]; + char kconf_id_strings_str25[sizeof("menuconfig")]; + char kconf_id_strings_str27[sizeof("modules")]; + char kconf_id_strings_str29[sizeof("menu")]; + char kconf_id_strings_str31[sizeof("select")]; + char kconf_id_strings_str32[sizeof("comment")]; + char kconf_id_strings_str33[sizeof("env")]; + char kconf_id_strings_str35[sizeof("range")]; + char kconf_id_strings_str36[sizeof("choice")]; + char kconf_id_strings_str39[sizeof("bool")]; + char kconf_id_strings_str41[sizeof("source")]; + char kconf_id_strings_str42[sizeof("visible")]; + char kconf_id_strings_str43[sizeof("hex")]; + char kconf_id_strings_str46[sizeof("config")]; + char kconf_id_strings_str47[sizeof("boolean")]; + char kconf_id_strings_str51[sizeof("string")]; + char kconf_id_strings_str54[sizeof("help")]; + char kconf_id_strings_str56[sizeof("prompt")]; + char kconf_id_strings_str72[sizeof("depends")]; + }; +static const struct kconf_id_strings_t kconf_id_strings_contents = + { + "if", + "int", + "endif", + "default", + "tristate", + "endchoice", + "def_tristate", + "def_bool", + "defconfig_list", + "on", + "optional", + "option", + "endmenu", + "mainmenu", + "menuconfig", + "modules", + "menu", + "select", + "comment", + "env", + "range", + "choice", + "bool", + "source", + "visible", + "hex", + "config", + "boolean", + "string", + "help", + "prompt", + "depends" + }; +#define kconf_id_strings ((const char *) &kconf_id_strings_contents) +#ifdef __GNUC__ +__inline +#if defined __GNUC_STDC_INLINE__ || defined __GNUC_GNU_INLINE__ +__attribute__ ((__gnu_inline__)) +#endif +#endif +const struct kconf_id * +kconf_id_lookup (register const char *str, register unsigned int len) +{ + enum + { + TOTAL_KEYWORDS = 32, + MIN_WORD_LENGTH = 2, + MAX_WORD_LENGTH = 14, + MIN_HASH_VALUE = 2, + MAX_HASH_VALUE = 72 + }; + + static const struct kconf_id wordlist[] = + { + {-1}, {-1}, +#line 25 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str2, T_IF, TF_COMMAND|TF_PARAM}, +#line 36 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str3, T_TYPE, TF_COMMAND, S_INT}, + {-1}, +#line 26 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str5, T_ENDIF, TF_COMMAND}, + {-1}, +#line 29 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str7, T_DEFAULT, TF_COMMAND, S_UNKNOWN}, +#line 31 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str8, T_TYPE, TF_COMMAND, S_TRISTATE}, +#line 20 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str9, T_ENDCHOICE, TF_COMMAND}, + {-1}, {-1}, +#line 32 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str12, T_DEFAULT, TF_COMMAND, S_TRISTATE}, +#line 35 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str13, T_DEFAULT, TF_COMMAND, S_BOOLEAN}, +#line 45 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str14, T_OPT_DEFCONFIG_LIST,TF_OPTION}, + {-1}, {-1}, +#line 43 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str17, T_ON, TF_PARAM}, +#line 28 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str18, T_OPTIONAL, TF_COMMAND}, + {-1}, {-1}, +#line 42 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str21, T_OPTION, TF_COMMAND}, +#line 17 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str22, T_ENDMENU, TF_COMMAND}, +#line 15 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str23, T_MAINMENU, TF_COMMAND}, + {-1}, +#line 23 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str25, T_MENUCONFIG, TF_COMMAND}, + {-1}, +#line 44 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str27, T_OPT_MODULES, TF_OPTION}, + {-1}, +#line 16 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str29, T_MENU, TF_COMMAND}, + {-1}, +#line 39 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str31, T_SELECT, TF_COMMAND}, +#line 21 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str32, T_COMMENT, TF_COMMAND}, +#line 46 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str33, T_OPT_ENV, TF_OPTION}, + {-1}, +#line 40 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str35, T_RANGE, TF_COMMAND}, +#line 19 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str36, T_CHOICE, TF_COMMAND}, + {-1}, {-1}, +#line 33 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str39, T_TYPE, TF_COMMAND, S_BOOLEAN}, + {-1}, +#line 18 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str41, T_SOURCE, TF_COMMAND}, +#line 41 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str42, T_VISIBLE, TF_COMMAND}, +#line 37 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str43, T_TYPE, TF_COMMAND, S_HEX}, + {-1}, {-1}, +#line 22 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str46, T_CONFIG, TF_COMMAND}, +#line 34 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str47, T_TYPE, TF_COMMAND, S_BOOLEAN}, + {-1}, {-1}, {-1}, +#line 38 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str51, T_TYPE, TF_COMMAND, S_STRING}, + {-1}, {-1}, +#line 24 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str54, T_HELP, TF_COMMAND}, + {-1}, +#line 30 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str56, T_PROMPT, TF_COMMAND}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, +#line 27 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str72, T_DEPENDS, TF_COMMAND} + }; + + if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) + { + register int key = kconf_id_hash (str, len); + + if (key <= MAX_HASH_VALUE && key >= 0) + { + register int o = wordlist[key].name; + if (o >= 0) + { + register const char *s = o + kconf_id_strings; + + if (*str == *s && !strncmp (str + 1, s + 1, len - 1) && s[len] == '\0') + return &wordlist[key]; + } + } + } + return 0; +} +#line 47 "scripts/kconfig/zconf.gperf" + diff --git a/kernel/fiasco/tool/kconfig/scripts/kconfig/zconf.l b/kernel/fiasco/tool/kconfig/scripts/kconfig/zconf.l new file mode 100644 index 00000000..00f9d3a9 --- /dev/null +++ b/kernel/fiasco/tool/kconfig/scripts/kconfig/zconf.l @@ -0,0 +1,364 @@ +%option nostdinit noyywrap never-interactive full ecs +%option 8bit nodefault perf-report perf-report +%option noinput +%x COMMAND HELP STRING PARAM +%{ +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +#include +#include +#include +#include +#include + +#include "lkc.h" + +#define START_STRSIZE 16 + +static struct { + struct file *file; + int lineno; +} current_pos; + +static char *text; +static int text_size, text_asize; + +struct buffer { + struct buffer *parent; + YY_BUFFER_STATE state; +}; + +struct buffer *current_buf; + +static int last_ts, first_ts; + +static void zconf_endhelp(void); +static void zconf_endfile(void); + +static void new_string(void) +{ + text = malloc(START_STRSIZE); + text_asize = START_STRSIZE; + text_size = 0; + *text = 0; +} + +static void append_string(const char *str, int size) +{ + int new_size = text_size + size + 1; + if (new_size > text_asize) { + new_size += START_STRSIZE - 1; + new_size &= -START_STRSIZE; + text = realloc(text, new_size); + text_asize = new_size; + } + memcpy(text + text_size, str, size); + text_size += size; + text[text_size] = 0; +} + +static void alloc_string(const char *str, int size) +{ + text = malloc(size + 1); + memcpy(text, str, size); + text[size] = 0; +} +%} + +ws [ \n\t] +n [A-Za-z0-9_] + +%% + int str = 0; + int ts, i; + +[ \t]*#.*\n | +[ \t]*\n { + current_file->lineno++; + return T_EOL; +} +[ \t]*#.* + + +[ \t]+ { + BEGIN(COMMAND); +} + +. { + unput(yytext[0]); + BEGIN(COMMAND); +} + + +{ + {n}+ { + const struct kconf_id *id = kconf_id_lookup(yytext, yyleng); + BEGIN(PARAM); + current_pos.file = current_file; + current_pos.lineno = current_file->lineno; + if (id && id->flags & TF_COMMAND) { + zconflval.id = id; + return id->token; + } + alloc_string(yytext, yyleng); + zconflval.string = text; + return T_WORD; + } + . + \n { + BEGIN(INITIAL); + current_file->lineno++; + return T_EOL; + } +} + +{ + "&&" return T_AND; + "||" return T_OR; + "(" return T_OPEN_PAREN; + ")" return T_CLOSE_PAREN; + "!" return T_NOT; + "=" return T_EQUAL; + "!=" return T_UNEQUAL; + \"|\' { + str = yytext[0]; + new_string(); + BEGIN(STRING); + } + \n BEGIN(INITIAL); current_file->lineno++; return T_EOL; + --- /* ignore */ + ({n}|[-/.])+ { + const struct kconf_id *id = kconf_id_lookup(yytext, yyleng); + if (id && id->flags & TF_PARAM) { + zconflval.id = id; + return id->token; + } + alloc_string(yytext, yyleng); + zconflval.string = text; + return T_WORD; + } + #.* /* comment */ + \\\n current_file->lineno++; + . + <> { + BEGIN(INITIAL); + } +} + +{ + [^'"\\\n]+/\n { + append_string(yytext, yyleng); + zconflval.string = text; + return T_WORD_QUOTE; + } + [^'"\\\n]+ { + append_string(yytext, yyleng); + } + \\.?/\n { + append_string(yytext + 1, yyleng - 1); + zconflval.string = text; + return T_WORD_QUOTE; + } + \\.? { + append_string(yytext + 1, yyleng - 1); + } + \'|\" { + if (str == yytext[0]) { + BEGIN(PARAM); + zconflval.string = text; + return T_WORD_QUOTE; + } else + append_string(yytext, 1); + } + \n { + printf("%s:%d:warning: multi-line strings not supported\n", zconf_curname(), zconf_lineno()); + current_file->lineno++; + BEGIN(INITIAL); + return T_EOL; + } + <> { + BEGIN(INITIAL); + } +} + +{ + [ \t]+ { + ts = 0; + for (i = 0; i < yyleng; i++) { + if (yytext[i] == '\t') + ts = (ts & ~7) + 8; + else + ts++; + } + last_ts = ts; + if (first_ts) { + if (ts < first_ts) { + zconf_endhelp(); + return T_HELPTEXT; + } + ts -= first_ts; + while (ts > 8) { + append_string(" ", 8); + ts -= 8; + } + append_string(" ", ts); + } + } + [ \t]*\n/[^ \t\n] { + current_file->lineno++; + zconf_endhelp(); + return T_HELPTEXT; + } + [ \t]*\n { + current_file->lineno++; + append_string("\n", 1); + } + [^ \t\n].* { + while (yyleng) { + if ((yytext[yyleng-1] != ' ') && (yytext[yyleng-1] != '\t')) + break; + yyleng--; + } + append_string(yytext, yyleng); + if (!first_ts) + first_ts = last_ts; + } + <> { + zconf_endhelp(); + return T_HELPTEXT; + } +} + +<> { + if (current_file) { + zconf_endfile(); + return T_EOL; + } + fclose(yyin); + yyterminate(); +} + +%% +void zconf_starthelp(void) +{ + new_string(); + last_ts = first_ts = 0; + BEGIN(HELP); +} + +static void zconf_endhelp(void) +{ + zconflval.string = text; + BEGIN(INITIAL); +} + + +/* + * Try to open specified file with following names: + * ./name + * $(srctree)/name + * The latter is used when srctree is separate from objtree + * when compiling the kernel. + * Return NULL if file is not found. + */ +FILE *zconf_fopen(const char *name) +{ + char *env, fullname[PATH_MAX+1]; + FILE *f; + + f = fopen(name, "r"); + if (!f && name != NULL && name[0] != '/') { + env = getenv(SRCTREE); + if (env) { + sprintf(fullname, "%s/%s", env, name); + f = fopen(fullname, "r"); + } + } + return f; +} + +void zconf_initscan(const char *name) +{ + yyin = zconf_fopen(name); + if (!yyin) { + printf("can't find file %s\n", name); + exit(1); + } + + current_buf = malloc(sizeof(*current_buf)); + memset(current_buf, 0, sizeof(*current_buf)); + + current_file = file_lookup(name); + current_file->lineno = 1; +} + +void zconf_nextfile(const char *name) +{ + struct file *iter; + struct file *file = file_lookup(name); + struct buffer *buf = malloc(sizeof(*buf)); + memset(buf, 0, sizeof(*buf)); + + current_buf->state = YY_CURRENT_BUFFER; + yyin = zconf_fopen(file->name); + if (!yyin) { + printf("%s:%d: can't open file \"%s\"\n", + zconf_curname(), zconf_lineno(), file->name); + exit(1); + } + yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE)); + buf->parent = current_buf; + current_buf = buf; + + for (iter = current_file->parent; iter; iter = iter->parent ) { + if (!strcmp(current_file->name,iter->name) ) { + printf("%s:%d: recursive inclusion detected. " + "Inclusion path:\n current file : '%s'\n", + zconf_curname(), zconf_lineno(), + zconf_curname()); + iter = current_file->parent; + while (iter && \ + strcmp(iter->name,current_file->name)) { + printf(" included from: '%s:%d'\n", + iter->name, iter->lineno-1); + iter = iter->parent; + } + if (iter) + printf(" included from: '%s:%d'\n", + iter->name, iter->lineno+1); + exit(1); + } + } + file->lineno = 1; + file->parent = current_file; + current_file = file; +} + +static void zconf_endfile(void) +{ + struct buffer *parent; + + current_file = current_file->parent; + + parent = current_buf->parent; + if (parent) { + fclose(yyin); + yy_delete_buffer(YY_CURRENT_BUFFER); + yy_switch_to_buffer(parent->state); + } + free(current_buf); + current_buf = parent; +} + +int zconf_lineno(void) +{ + return current_pos.lineno; +} + +const char *zconf_curname(void) +{ + return current_pos.file ? current_pos.file->name : ""; +} diff --git a/kernel/fiasco/tool/kconfig/scripts/kconfig/zconf.lex.c_shipped b/kernel/fiasco/tool/kconfig/scripts/kconfig/zconf.lex.c_shipped new file mode 100644 index 00000000..c32b1a49 --- /dev/null +++ b/kernel/fiasco/tool/kconfig/scripts/kconfig/zconf.lex.c_shipped @@ -0,0 +1,2420 @@ + +#line 3 "scripts/kconfig/zconf.lex.c_shipped" + +#define YY_INT_ALIGNED short int + +/* A lexical scanner generated by flex */ + +#define yy_create_buffer zconf_create_buffer +#define yy_delete_buffer zconf_delete_buffer +#define yy_flex_debug zconf_flex_debug +#define yy_init_buffer zconf_init_buffer +#define yy_flush_buffer zconf_flush_buffer +#define yy_load_buffer_state zconf_load_buffer_state +#define yy_switch_to_buffer zconf_switch_to_buffer +#define yyin zconfin +#define yyleng zconfleng +#define yylex zconflex +#define yylineno zconflineno +#define yyout zconfout +#define yyrestart zconfrestart +#define yytext zconftext +#define yywrap zconfwrap +#define yyalloc zconfalloc +#define yyrealloc zconfrealloc +#define yyfree zconffree + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 5 +#define YY_FLEX_SUBMINOR_VERSION 35 +#if YY_FLEX_SUBMINOR_VERSION > 0 +#define FLEX_BETA +#endif + +/* First, we deal with platform-specific or compiler-specific issues. */ + +/* begin standard C headers. */ +#include +#include +#include +#include + +/* end standard C headers. */ + +/* flex integer type definitions */ + +#ifndef FLEXINT_H +#define FLEXINT_H + +/* C99 systems have . Non-C99 systems may or may not. */ + +#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + +/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, + * if you want the limit (max/min) macros for int types. + */ +#ifndef __STDC_LIMIT_MACROS +#define __STDC_LIMIT_MACROS 1 +#endif + +#include +typedef int8_t flex_int8_t; +typedef uint8_t flex_uint8_t; +typedef int16_t flex_int16_t; +typedef uint16_t flex_uint16_t; +typedef int32_t flex_int32_t; +typedef uint32_t flex_uint32_t; +#else +typedef signed char flex_int8_t; +typedef short int flex_int16_t; +typedef int flex_int32_t; +typedef unsigned char flex_uint8_t; +typedef unsigned short int flex_uint16_t; +typedef unsigned int flex_uint32_t; +#endif /* ! C99 */ + +/* Limits of integral types. */ +#ifndef INT8_MIN +#define INT8_MIN (-128) +#endif +#ifndef INT16_MIN +#define INT16_MIN (-32767-1) +#endif +#ifndef INT32_MIN +#define INT32_MIN (-2147483647-1) +#endif +#ifndef INT8_MAX +#define INT8_MAX (127) +#endif +#ifndef INT16_MAX +#define INT16_MAX (32767) +#endif +#ifndef INT32_MAX +#define INT32_MAX (2147483647) +#endif +#ifndef UINT8_MAX +#define UINT8_MAX (255U) +#endif +#ifndef UINT16_MAX +#define UINT16_MAX (65535U) +#endif +#ifndef UINT32_MAX +#define UINT32_MAX (4294967295U) +#endif + +#endif /* ! FLEXINT_H */ + +#ifdef __cplusplus + +/* The "const" storage-class-modifier is valid. */ +#define YY_USE_CONST + +#else /* ! __cplusplus */ + +/* C99 requires __STDC__ to be defined as 1. */ +#if defined (__STDC__) + +#define YY_USE_CONST + +#endif /* defined (__STDC__) */ +#endif /* ! __cplusplus */ + +#ifdef YY_USE_CONST +#define yyconst const +#else +#define yyconst +#endif + +/* Returned upon end-of-file. */ +#define YY_NULL 0 + +/* Promotes a possibly negative, possibly signed char to an unsigned + * integer for use as an array index. If the signed char is negative, + * we want to instead treat it as an 8-bit unsigned char, hence the + * double cast. + */ +#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) + +/* Enter a start condition. This macro really ought to take a parameter, + * but we do it the disgusting crufty way forced on us by the ()-less + * definition of BEGIN. + */ +#define BEGIN (yy_start) = 1 + 2 * + +/* Translate the current start state into a value that can be later handed + * to BEGIN to return to the state. The YYSTATE alias is for lex + * compatibility. + */ +#define YY_START (((yy_start) - 1) / 2) +#define YYSTATE YY_START + +/* Action number for EOF rule of a given start state. */ +#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) + +/* Special action meaning "start processing a new file". */ +#define YY_NEW_FILE zconfrestart(zconfin ) + +#define YY_END_OF_BUFFER_CHAR 0 + +/* Size of default input buffer. */ +#ifndef YY_BUF_SIZE +#define YY_BUF_SIZE 16384 +#endif + +/* The state buf must be large enough to hold one state per character in the main buffer. + */ +#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type)) + +#ifndef YY_TYPEDEF_YY_BUFFER_STATE +#define YY_TYPEDEF_YY_BUFFER_STATE +typedef struct yy_buffer_state *YY_BUFFER_STATE; +#endif + +extern int zconfleng; + +extern FILE *zconfin, *zconfout; + +#define EOB_ACT_CONTINUE_SCAN 0 +#define EOB_ACT_END_OF_FILE 1 +#define EOB_ACT_LAST_MATCH 2 + + #define YY_LESS_LINENO(n) + +/* Return all but the first "n" matched characters back to the input stream. */ +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up zconftext. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + *yy_cp = (yy_hold_char); \ + YY_RESTORE_YY_MORE_OFFSET \ + (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ + YY_DO_BEFORE_ACTION; /* set up zconftext again */ \ + } \ + while ( 0 ) + +#define unput(c) yyunput( c, (yytext_ptr) ) + +#ifndef YY_TYPEDEF_YY_SIZE_T +#define YY_TYPEDEF_YY_SIZE_T +typedef size_t yy_size_t; +#endif + +#ifndef YY_STRUCT_YY_BUFFER_STATE +#define YY_STRUCT_YY_BUFFER_STATE +struct yy_buffer_state + { + FILE *yy_input_file; + + char *yy_ch_buf; /* input buffer */ + char *yy_buf_pos; /* current position in input buffer */ + + /* Size of input buffer in bytes, not including room for EOB + * characters. + */ + yy_size_t yy_buf_size; + + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ + int yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to + * delete it. + */ + int yy_is_our_buffer; + + /* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ + int yy_is_interactive; + + /* Whether we're considered to be at the beginning of a line. + * If so, '^' rules will be active on the next match, otherwise + * not. + */ + int yy_at_bol; + + int yy_bs_lineno; /**< The line count. */ + int yy_bs_column; /**< The column count. */ + + /* Whether to try to fill the input buffer when we reach the + * end of it. + */ + int yy_fill_buffer; + + int yy_buffer_status; + +#define YY_BUFFER_NEW 0 +#define YY_BUFFER_NORMAL 1 + /* When an EOF's been seen but there's still some text to process + * then we mark the buffer as YY_EOF_PENDING, to indicate that we + * shouldn't try reading from the input source any more. We might + * still have a bunch of tokens to match, though, because of + * possible backing-up. + * + * When we actually see the EOF, we change the status to "new" + * (via zconfrestart()), so that the user can continue scanning by + * just pointing zconfin at a new input file. + */ +#define YY_BUFFER_EOF_PENDING 2 + + }; +#endif /* !YY_STRUCT_YY_BUFFER_STATE */ + +/* Stack of input buffers. */ +static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */ +static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */ +static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */ + +/* We provide macros for accessing buffer states in case in the + * future we want to put the buffer states in a more general + * "scanner state". + * + * Returns the top of the stack, or NULL. + */ +#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \ + ? (yy_buffer_stack)[(yy_buffer_stack_top)] \ + : NULL) + +/* Same as previous macro, but useful when we know that the buffer stack is not + * NULL or when we need an lvalue. For internal use only. + */ +#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)] + +/* yy_hold_char holds the character lost when zconftext is formed. */ +static char yy_hold_char; +static int yy_n_chars; /* number of characters read into yy_ch_buf */ +int zconfleng; + +/* Points to current character in buffer. */ +static char *yy_c_buf_p = (char *) 0; +static int yy_init = 0; /* whether we need to initialize */ +static int yy_start = 0; /* start state number */ + +/* Flag which is used to allow zconfwrap()'s to do buffer switches + * instead of setting up a fresh zconfin. A bit of a hack ... + */ +static int yy_did_buffer_switch_on_eof; + +void zconfrestart (FILE *input_file ); +void zconf_switch_to_buffer (YY_BUFFER_STATE new_buffer ); +YY_BUFFER_STATE zconf_create_buffer (FILE *file,int size ); +void zconf_delete_buffer (YY_BUFFER_STATE b ); +void zconf_flush_buffer (YY_BUFFER_STATE b ); +void zconfpush_buffer_state (YY_BUFFER_STATE new_buffer ); +void zconfpop_buffer_state (void ); + +static void zconfensure_buffer_stack (void ); +static void zconf_load_buffer_state (void ); +static void zconf_init_buffer (YY_BUFFER_STATE b,FILE *file ); + +#define YY_FLUSH_BUFFER zconf_flush_buffer(YY_CURRENT_BUFFER ) + +YY_BUFFER_STATE zconf_scan_buffer (char *base,yy_size_t size ); +YY_BUFFER_STATE zconf_scan_string (yyconst char *yy_str ); +YY_BUFFER_STATE zconf_scan_bytes (yyconst char *bytes,int len ); + +void *zconfalloc (yy_size_t ); +void *zconfrealloc (void *,yy_size_t ); +void zconffree (void * ); + +#define yy_new_buffer zconf_create_buffer + +#define yy_set_interactive(is_interactive) \ + { \ + if ( ! YY_CURRENT_BUFFER ){ \ + zconfensure_buffer_stack (); \ + YY_CURRENT_BUFFER_LVALUE = \ + zconf_create_buffer(zconfin,YY_BUF_SIZE ); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ + } + +#define yy_set_bol(at_bol) \ + { \ + if ( ! YY_CURRENT_BUFFER ){\ + zconfensure_buffer_stack (); \ + YY_CURRENT_BUFFER_LVALUE = \ + zconf_create_buffer(zconfin,YY_BUF_SIZE ); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ + } + +#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) + +/* Begin user sect3 */ + +#define zconfwrap(n) 1 +#define YY_SKIP_YYWRAP + +typedef unsigned char YY_CHAR; + +FILE *zconfin = (FILE *) 0, *zconfout = (FILE *) 0; + +typedef int yy_state_type; + +extern int zconflineno; + +int zconflineno = 1; + +extern char *zconftext; +#define yytext_ptr zconftext +static yyconst flex_int16_t yy_nxt[][17] = + { + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0 + }, + + { + 11, 12, 13, 14, 12, 12, 15, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12 + }, + + { + 11, 12, 13, 14, 12, 12, 15, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12 + }, + + { + 11, 16, 16, 17, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 18, 16, 16, 16 + }, + + { + 11, 16, 16, 17, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 18, 16, 16, 16 + + }, + + { + 11, 19, 20, 21, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19 + }, + + { + 11, 19, 20, 21, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19 + }, + + { + 11, 22, 22, 23, 22, 24, 22, 22, 24, 22, + 22, 22, 22, 22, 22, 25, 22 + }, + + { + 11, 22, 22, 23, 22, 24, 22, 22, 24, 22, + 22, 22, 22, 22, 22, 25, 22 + }, + + { + 11, 26, 26, 27, 28, 29, 30, 31, 29, 32, + 33, 34, 35, 35, 36, 37, 38 + + }, + + { + 11, 26, 26, 27, 28, 29, 30, 31, 29, 32, + 33, 34, 35, 35, 36, 37, 38 + }, + + { + -11, -11, -11, -11, -11, -11, -11, -11, -11, -11, + -11, -11, -11, -11, -11, -11, -11 + }, + + { + 11, -12, -12, -12, -12, -12, -12, -12, -12, -12, + -12, -12, -12, -12, -12, -12, -12 + }, + + { + 11, -13, 39, 40, -13, -13, 41, -13, -13, -13, + -13, -13, -13, -13, -13, -13, -13 + }, + + { + 11, -14, -14, -14, -14, -14, -14, -14, -14, -14, + -14, -14, -14, -14, -14, -14, -14 + + }, + + { + 11, 42, 42, 43, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42 + }, + + { + 11, -16, -16, -16, -16, -16, -16, -16, -16, -16, + -16, -16, -16, -16, -16, -16, -16 + }, + + { + 11, -17, -17, -17, -17, -17, -17, -17, -17, -17, + -17, -17, -17, -17, -17, -17, -17 + }, + + { + 11, -18, -18, -18, -18, -18, -18, -18, -18, -18, + -18, -18, -18, 44, -18, -18, -18 + }, + + { + 11, 45, 45, -19, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45 + + }, + + { + 11, -20, 46, 47, -20, -20, -20, -20, -20, -20, + -20, -20, -20, -20, -20, -20, -20 + }, + + { + 11, 48, -21, -21, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48 + }, + + { + 11, 49, 49, 50, 49, -22, 49, 49, -22, 49, + 49, 49, 49, 49, 49, -22, 49 + }, + + { + 11, -23, -23, -23, -23, -23, -23, -23, -23, -23, + -23, -23, -23, -23, -23, -23, -23 + }, + + { + 11, -24, -24, -24, -24, -24, -24, -24, -24, -24, + -24, -24, -24, -24, -24, -24, -24 + + }, + + { + 11, 51, 51, 52, 51, 51, 51, 51, 51, 51, + 51, 51, 51, 51, 51, 51, 51 + }, + + { + 11, -26, -26, -26, -26, -26, -26, -26, -26, -26, + -26, -26, -26, -26, -26, -26, -26 + }, + + { + 11, -27, -27, -27, -27, -27, -27, -27, -27, -27, + -27, -27, -27, -27, -27, -27, -27 + }, + + { + 11, -28, -28, -28, -28, -28, -28, -28, -28, -28, + -28, -28, -28, -28, 53, -28, -28 + }, + + { + 11, -29, -29, -29, -29, -29, -29, -29, -29, -29, + -29, -29, -29, -29, -29, -29, -29 + + }, + + { + 11, 54, 54, -30, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54 + }, + + { + 11, -31, -31, -31, -31, -31, -31, 55, -31, -31, + -31, -31, -31, -31, -31, -31, -31 + }, + + { + 11, -32, -32, -32, -32, -32, -32, -32, -32, -32, + -32, -32, -32, -32, -32, -32, -32 + }, + + { + 11, -33, -33, -33, -33, -33, -33, -33, -33, -33, + -33, -33, -33, -33, -33, -33, -33 + }, + + { + 11, -34, -34, -34, -34, -34, -34, -34, -34, -34, + -34, 56, 57, 57, -34, -34, -34 + + }, + + { + 11, -35, -35, -35, -35, -35, -35, -35, -35, -35, + -35, 57, 57, 57, -35, -35, -35 + }, + + { + 11, -36, -36, -36, -36, -36, -36, -36, -36, -36, + -36, -36, -36, -36, -36, -36, -36 + }, + + { + 11, -37, -37, 58, -37, -37, -37, -37, -37, -37, + -37, -37, -37, -37, -37, -37, -37 + }, + + { + 11, -38, -38, -38, -38, -38, -38, -38, -38, -38, + -38, -38, -38, -38, -38, -38, 59 + }, + + { + 11, -39, 39, 40, -39, -39, 41, -39, -39, -39, + -39, -39, -39, -39, -39, -39, -39 + + }, + + { + 11, -40, -40, -40, -40, -40, -40, -40, -40, -40, + -40, -40, -40, -40, -40, -40, -40 + }, + + { + 11, 42, 42, 43, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42 + }, + + { + 11, 42, 42, 43, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42 + }, + + { + 11, -43, -43, -43, -43, -43, -43, -43, -43, -43, + -43, -43, -43, -43, -43, -43, -43 + }, + + { + 11, -44, -44, -44, -44, -44, -44, -44, -44, -44, + -44, -44, -44, 44, -44, -44, -44 + + }, + + { + 11, 45, 45, -45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45 + }, + + { + 11, -46, 46, 47, -46, -46, -46, -46, -46, -46, + -46, -46, -46, -46, -46, -46, -46 + }, + + { + 11, 48, -47, -47, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48 + }, + + { + 11, -48, -48, -48, -48, -48, -48, -48, -48, -48, + -48, -48, -48, -48, -48, -48, -48 + }, + + { + 11, 49, 49, 50, 49, -49, 49, 49, -49, 49, + 49, 49, 49, 49, 49, -49, 49 + + }, + + { + 11, -50, -50, -50, -50, -50, -50, -50, -50, -50, + -50, -50, -50, -50, -50, -50, -50 + }, + + { + 11, -51, -51, 52, -51, -51, -51, -51, -51, -51, + -51, -51, -51, -51, -51, -51, -51 + }, + + { + 11, -52, -52, -52, -52, -52, -52, -52, -52, -52, + -52, -52, -52, -52, -52, -52, -52 + }, + + { + 11, -53, -53, -53, -53, -53, -53, -53, -53, -53, + -53, -53, -53, -53, -53, -53, -53 + }, + + { + 11, 54, 54, -54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54 + + }, + + { + 11, -55, -55, -55, -55, -55, -55, -55, -55, -55, + -55, -55, -55, -55, -55, -55, -55 + }, + + { + 11, -56, -56, -56, -56, -56, -56, -56, -56, -56, + -56, 60, 57, 57, -56, -56, -56 + }, + + { + 11, -57, -57, -57, -57, -57, -57, -57, -57, -57, + -57, 57, 57, 57, -57, -57, -57 + }, + + { + 11, -58, -58, -58, -58, -58, -58, -58, -58, -58, + -58, -58, -58, -58, -58, -58, -58 + }, + + { + 11, -59, -59, -59, -59, -59, -59, -59, -59, -59, + -59, -59, -59, -59, -59, -59, -59 + + }, + + { + 11, -60, -60, -60, -60, -60, -60, -60, -60, -60, + -60, 57, 57, 57, -60, -60, -60 + }, + + } ; + +static yy_state_type yy_get_previous_state (void ); +static yy_state_type yy_try_NUL_trans (yy_state_type current_state ); +static int yy_get_next_buffer (void ); +static void yy_fatal_error (yyconst char msg[] ); + +/* Done after the current pattern has been matched and before the + * corresponding action - sets up zconftext. + */ +#define YY_DO_BEFORE_ACTION \ + (yytext_ptr) = yy_bp; \ + zconfleng = (size_t) (yy_cp - yy_bp); \ + (yy_hold_char) = *yy_cp; \ + *yy_cp = '\0'; \ + (yy_c_buf_p) = yy_cp; + +#define YY_NUM_RULES 33 +#define YY_END_OF_BUFFER 34 +/* This struct is not used in this scanner, + but its presence is necessary. */ +struct yy_trans_info + { + flex_int32_t yy_verify; + flex_int32_t yy_nxt; + }; +static yyconst flex_int16_t yy_accept[61] = + { 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 34, 5, 4, 2, 3, 7, 8, 6, 32, 29, + 31, 24, 28, 27, 26, 22, 17, 13, 16, 20, + 22, 11, 12, 19, 19, 14, 22, 22, 4, 2, + 3, 3, 1, 6, 32, 29, 31, 30, 24, 23, + 26, 25, 15, 20, 9, 19, 19, 21, 10, 18 + } ; + +static yyconst flex_int32_t yy_ec[256] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 4, 5, 6, 1, 1, 7, 8, 9, + 10, 1, 1, 1, 11, 12, 12, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 1, 1, 1, + 14, 1, 1, 1, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 1, 15, 1, 1, 13, 1, 13, 13, 13, 13, + + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 1, 16, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1 + } ; + +extern int zconf_flex_debug; +int zconf_flex_debug = 0; + +/* The intent behind this definition is that it'll catch + * any uses of REJECT which flex missed. + */ +#define REJECT reject_used_but_not_detected +#define yymore() yymore_used_but_not_detected +#define YY_MORE_ADJ 0 +#define YY_RESTORE_YY_MORE_OFFSET +char *zconftext; +#define YY_NO_INPUT 1 + +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +#include +#include +#include +#include +#include + +#include "lkc.h" + +#define START_STRSIZE 16 + +static struct { + struct file *file; + int lineno; +} current_pos; + +static char *text; +static int text_size, text_asize; + +struct buffer { + struct buffer *parent; + YY_BUFFER_STATE state; +}; + +struct buffer *current_buf; + +static int last_ts, first_ts; + +static void zconf_endhelp(void); +static void zconf_endfile(void); + +static void new_string(void) +{ + text = malloc(START_STRSIZE); + text_asize = START_STRSIZE; + text_size = 0; + *text = 0; +} + +static void append_string(const char *str, int size) +{ + int new_size = text_size + size + 1; + if (new_size > text_asize) { + new_size += START_STRSIZE - 1; + new_size &= -START_STRSIZE; + text = realloc(text, new_size); + text_asize = new_size; + } + memcpy(text + text_size, str, size); + text_size += size; + text[text_size] = 0; +} + +static void alloc_string(const char *str, int size) +{ + text = malloc(size + 1); + memcpy(text, str, size); + text[size] = 0; +} + +#define INITIAL 0 +#define COMMAND 1 +#define HELP 2 +#define STRING 3 +#define PARAM 4 + +#ifndef YY_NO_UNISTD_H +/* Special case for "unistd.h", since it is non-ANSI. We include it way + * down here because we want the user's section 1 to have been scanned first. + * The user has a chance to override it with an option. + */ +#include +#endif + +#ifndef YY_EXTRA_TYPE +#define YY_EXTRA_TYPE void * +#endif + +static int yy_init_globals (void ); + +/* Accessor methods to globals. + These are made visible to non-reentrant scanners for convenience. */ + +int zconflex_destroy (void ); + +int zconfget_debug (void ); + +void zconfset_debug (int debug_flag ); + +YY_EXTRA_TYPE zconfget_extra (void ); + +void zconfset_extra (YY_EXTRA_TYPE user_defined ); + +FILE *zconfget_in (void ); + +void zconfset_in (FILE * in_str ); + +FILE *zconfget_out (void ); + +void zconfset_out (FILE * out_str ); + +int zconfget_leng (void ); + +char *zconfget_text (void ); + +int zconfget_lineno (void ); + +void zconfset_lineno (int line_number ); + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int zconfwrap (void ); +#else +extern int zconfwrap (void ); +#endif +#endif + + static void yyunput (int c,char *buf_ptr ); + +#ifndef yytext_ptr +static void yy_flex_strncpy (char *,yyconst char *,int ); +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen (yyconst char * ); +#endif + +#ifndef YY_NO_INPUT + +#ifdef __cplusplus +static int yyinput (void ); +#else +static int input (void ); +#endif + +#endif + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#define YY_READ_BUF_SIZE 8192 +#endif + +/* Copy whatever the last rule matched to the standard output. */ +#ifndef ECHO +/* This used to be an fputs(), but since the string might contain NUL's, + * we now use fwrite(). + */ +#define ECHO do { if (fwrite( zconftext, zconfleng, 1, zconfout )) {} } while (0) +#endif + +/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, + * is returned in "result". + */ +#ifndef YY_INPUT +#define YY_INPUT(buf,result,max_size) \ + errno=0; \ + while ( (result = read( fileno(zconfin), (char *) buf, max_size )) < 0 ) \ + { \ + if( errno != EINTR) \ + { \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + break; \ + } \ + errno=0; \ + clearerr(zconfin); \ + }\ +\ + +#endif + +/* No semi-colon after return; correct usage is to write "yyterminate();" - + * we don't want an extra ';' after the "return" because that will cause + * some compilers to complain about unreachable statements. + */ +#ifndef yyterminate +#define yyterminate() return YY_NULL +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Report a fatal error. */ +#ifndef YY_FATAL_ERROR +#define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) +#endif + +/* end tables serialization structures and prototypes */ + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL_IS_OURS 1 + +extern int zconflex (void); + +#define YY_DECL int zconflex (void) +#endif /* !YY_DECL */ + +/* Code executed at the beginning of each rule, after zconftext and zconfleng + * have been set up. + */ +#ifndef YY_USER_ACTION +#define YY_USER_ACTION +#endif + +/* Code executed at the end of each rule. */ +#ifndef YY_BREAK +#define YY_BREAK break; +#endif + +#define YY_RULE_SETUP \ + YY_USER_ACTION + +/** The main scanner function which does all the work. + */ +YY_DECL +{ + register yy_state_type yy_current_state; + register char *yy_cp, *yy_bp; + register int yy_act; + + int str = 0; + int ts, i; + + if ( !(yy_init) ) + { + (yy_init) = 1; + +#ifdef YY_USER_INIT + YY_USER_INIT; +#endif + + if ( ! (yy_start) ) + (yy_start) = 1; /* first start state */ + + if ( ! zconfin ) + zconfin = stdin; + + if ( ! zconfout ) + zconfout = stdout; + + if ( ! YY_CURRENT_BUFFER ) { + zconfensure_buffer_stack (); + YY_CURRENT_BUFFER_LVALUE = + zconf_create_buffer(zconfin,YY_BUF_SIZE ); + } + + zconf_load_buffer_state( ); + } + + while ( 1 ) /* loops until end-of-file is reached */ + { + yy_cp = (yy_c_buf_p); + + /* Support of zconftext. */ + *yy_cp = (yy_hold_char); + + /* yy_bp points to the position in yy_ch_buf of the start of + * the current run. + */ + yy_bp = yy_cp; + + yy_current_state = (yy_start); +yy_match: + while ( (yy_current_state = yy_nxt[yy_current_state][ yy_ec[YY_SC_TO_UI(*yy_cp)] ]) > 0 ) + ++yy_cp; + + yy_current_state = -yy_current_state; + +yy_find_action: + yy_act = yy_accept[yy_current_state]; + + YY_DO_BEFORE_ACTION; + +do_action: /* This label is used only to access EOF actions. */ + + switch ( yy_act ) + { /* beginning of action switch */ +case 1: +/* rule 1 can match eol */ +case 2: +/* rule 2 can match eol */ +YY_RULE_SETUP +{ + current_file->lineno++; + return T_EOL; +} + YY_BREAK +case 3: +YY_RULE_SETUP + + YY_BREAK +case 4: +YY_RULE_SETUP +{ + BEGIN(COMMAND); +} + YY_BREAK +case 5: +YY_RULE_SETUP +{ + unput(zconftext[0]); + BEGIN(COMMAND); +} + YY_BREAK + +case 6: +YY_RULE_SETUP +{ + const struct kconf_id *id = kconf_id_lookup(zconftext, zconfleng); + BEGIN(PARAM); + current_pos.file = current_file; + current_pos.lineno = current_file->lineno; + if (id && id->flags & TF_COMMAND) { + zconflval.id = id; + return id->token; + } + alloc_string(zconftext, zconfleng); + zconflval.string = text; + return T_WORD; + } + YY_BREAK +case 7: +YY_RULE_SETUP + + YY_BREAK +case 8: +/* rule 8 can match eol */ +YY_RULE_SETUP +{ + BEGIN(INITIAL); + current_file->lineno++; + return T_EOL; + } + YY_BREAK + +case 9: +YY_RULE_SETUP +return T_AND; + YY_BREAK +case 10: +YY_RULE_SETUP +return T_OR; + YY_BREAK +case 11: +YY_RULE_SETUP +return T_OPEN_PAREN; + YY_BREAK +case 12: +YY_RULE_SETUP +return T_CLOSE_PAREN; + YY_BREAK +case 13: +YY_RULE_SETUP +return T_NOT; + YY_BREAK +case 14: +YY_RULE_SETUP +return T_EQUAL; + YY_BREAK +case 15: +YY_RULE_SETUP +return T_UNEQUAL; + YY_BREAK +case 16: +YY_RULE_SETUP +{ + str = zconftext[0]; + new_string(); + BEGIN(STRING); + } + YY_BREAK +case 17: +/* rule 17 can match eol */ +YY_RULE_SETUP +BEGIN(INITIAL); current_file->lineno++; return T_EOL; + YY_BREAK +case 18: +YY_RULE_SETUP +/* ignore */ + YY_BREAK +case 19: +YY_RULE_SETUP +{ + const struct kconf_id *id = kconf_id_lookup(zconftext, zconfleng); + if (id && id->flags & TF_PARAM) { + zconflval.id = id; + return id->token; + } + alloc_string(zconftext, zconfleng); + zconflval.string = text; + return T_WORD; + } + YY_BREAK +case 20: +YY_RULE_SETUP +/* comment */ + YY_BREAK +case 21: +/* rule 21 can match eol */ +YY_RULE_SETUP +current_file->lineno++; + YY_BREAK +case 22: +YY_RULE_SETUP + + YY_BREAK +case YY_STATE_EOF(PARAM): +{ + BEGIN(INITIAL); + } + YY_BREAK + +case 23: +/* rule 23 can match eol */ +*yy_cp = (yy_hold_char); /* undo effects of setting up zconftext */ +(yy_c_buf_p) = yy_cp -= 1; +YY_DO_BEFORE_ACTION; /* set up zconftext again */ +YY_RULE_SETUP +{ + append_string(zconftext, zconfleng); + zconflval.string = text; + return T_WORD_QUOTE; + } + YY_BREAK +case 24: +YY_RULE_SETUP +{ + append_string(zconftext, zconfleng); + } + YY_BREAK +case 25: +/* rule 25 can match eol */ +*yy_cp = (yy_hold_char); /* undo effects of setting up zconftext */ +(yy_c_buf_p) = yy_cp -= 1; +YY_DO_BEFORE_ACTION; /* set up zconftext again */ +YY_RULE_SETUP +{ + append_string(zconftext + 1, zconfleng - 1); + zconflval.string = text; + return T_WORD_QUOTE; + } + YY_BREAK +case 26: +YY_RULE_SETUP +{ + append_string(zconftext + 1, zconfleng - 1); + } + YY_BREAK +case 27: +YY_RULE_SETUP +{ + if (str == zconftext[0]) { + BEGIN(PARAM); + zconflval.string = text; + return T_WORD_QUOTE; + } else + append_string(zconftext, 1); + } + YY_BREAK +case 28: +/* rule 28 can match eol */ +YY_RULE_SETUP +{ + printf("%s:%d:warning: multi-line strings not supported\n", zconf_curname(), zconf_lineno()); + current_file->lineno++; + BEGIN(INITIAL); + return T_EOL; + } + YY_BREAK +case YY_STATE_EOF(STRING): +{ + BEGIN(INITIAL); + } + YY_BREAK + +case 29: +YY_RULE_SETUP +{ + ts = 0; + for (i = 0; i < zconfleng; i++) { + if (zconftext[i] == '\t') + ts = (ts & ~7) + 8; + else + ts++; + } + last_ts = ts; + if (first_ts) { + if (ts < first_ts) { + zconf_endhelp(); + return T_HELPTEXT; + } + ts -= first_ts; + while (ts > 8) { + append_string(" ", 8); + ts -= 8; + } + append_string(" ", ts); + } + } + YY_BREAK +case 30: +/* rule 30 can match eol */ +*yy_cp = (yy_hold_char); /* undo effects of setting up zconftext */ +(yy_c_buf_p) = yy_cp -= 1; +YY_DO_BEFORE_ACTION; /* set up zconftext again */ +YY_RULE_SETUP +{ + current_file->lineno++; + zconf_endhelp(); + return T_HELPTEXT; + } + YY_BREAK +case 31: +/* rule 31 can match eol */ +YY_RULE_SETUP +{ + current_file->lineno++; + append_string("\n", 1); + } + YY_BREAK +case 32: +YY_RULE_SETUP +{ + while (zconfleng) { + if ((zconftext[zconfleng-1] != ' ') && (zconftext[zconfleng-1] != '\t')) + break; + zconfleng--; + } + append_string(zconftext, zconfleng); + if (!first_ts) + first_ts = last_ts; + } + YY_BREAK +case YY_STATE_EOF(HELP): +{ + zconf_endhelp(); + return T_HELPTEXT; + } + YY_BREAK + +case YY_STATE_EOF(INITIAL): +case YY_STATE_EOF(COMMAND): +{ + if (current_file) { + zconf_endfile(); + return T_EOL; + } + fclose(zconfin); + yyterminate(); +} + YY_BREAK +case 33: +YY_RULE_SETUP +YY_FATAL_ERROR( "flex scanner jammed" ); + YY_BREAK + + case YY_END_OF_BUFFER: + { + /* Amount of text matched not including the EOB char. */ + int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1; + + /* Undo the effects of YY_DO_BEFORE_ACTION. */ + *yy_cp = (yy_hold_char); + YY_RESTORE_YY_MORE_OFFSET + + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW ) + { + /* We're scanning a new file or input source. It's + * possible that this happened because the user + * just pointed zconfin at a new source and called + * zconflex(). If so, then we have to assure + * consistency between YY_CURRENT_BUFFER and our + * globals. Here is the right place to do so, because + * this is the first action (other than possibly a + * back-up) that will match for the new input source. + */ + (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + YY_CURRENT_BUFFER_LVALUE->yy_input_file = zconfin; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; + } + + /* Note that here we test for yy_c_buf_p "<=" to the position + * of the first EOB in the buffer, since yy_c_buf_p will + * already have been incremented past the NUL character + * (since all states make transitions on EOB to the + * end-of-buffer state). Contrast this with the test + * in input(). + */ + if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) + { /* This was really a NUL. */ + yy_state_type yy_next_state; + + (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state( ); + + /* Okay, we're now positioned to make the NUL + * transition. We couldn't have + * yy_get_previous_state() go ahead and do it + * for us because it doesn't know how to deal + * with the possibility of jamming (and we don't + * want to build jamming into it because then it + * will run more slowly). + */ + + yy_next_state = yy_try_NUL_trans( yy_current_state ); + + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + + if ( yy_next_state ) + { + /* Consume the NUL. */ + yy_cp = ++(yy_c_buf_p); + yy_current_state = yy_next_state; + goto yy_match; + } + + else + { + yy_cp = (yy_c_buf_p); + goto yy_find_action; + } + } + + else switch ( yy_get_next_buffer( ) ) + { + case EOB_ACT_END_OF_FILE: + { + (yy_did_buffer_switch_on_eof) = 0; + + if ( zconfwrap( ) ) + { + /* Note: because we've taken care in + * yy_get_next_buffer() to have set up + * zconftext, we can now set up + * yy_c_buf_p so that if some total + * hoser (like flex itself) wants to + * call the scanner after we return the + * YY_NULL, it'll still work - another + * YY_NULL will get returned. + */ + (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ; + + yy_act = YY_STATE_EOF(YY_START); + goto do_action; + } + + else + { + if ( ! (yy_did_buffer_switch_on_eof) ) + YY_NEW_FILE; + } + break; + } + + case EOB_ACT_CONTINUE_SCAN: + (yy_c_buf_p) = + (yytext_ptr) + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state( ); + + yy_cp = (yy_c_buf_p); + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + goto yy_match; + + case EOB_ACT_LAST_MATCH: + (yy_c_buf_p) = + &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)]; + + yy_current_state = yy_get_previous_state( ); + + yy_cp = (yy_c_buf_p); + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + goto yy_find_action; + } + break; + } + + default: + YY_FATAL_ERROR( + "fatal flex scanner internal error--no action found" ); + } /* end of action switch */ + } /* end of scanning one token */ +} /* end of zconflex */ + +/* yy_get_next_buffer - try to read in a new buffer + * + * Returns a code representing an action: + * EOB_ACT_LAST_MATCH - + * EOB_ACT_CONTINUE_SCAN - continue scanning from current position + * EOB_ACT_END_OF_FILE - end of file + */ +static int yy_get_next_buffer (void) +{ + register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; + register char *source = (yytext_ptr); + register int number_to_move, i; + int ret_val; + + if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] ) + YY_FATAL_ERROR( + "fatal flex scanner internal error--end of buffer missed" ); + + if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 ) + { /* Don't try to fill the buffer, so this is an EOF. */ + if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 ) + { + /* We matched a single character, the EOB, so + * treat this as a final EOF. + */ + return EOB_ACT_END_OF_FILE; + } + + else + { + /* We matched some text prior to the EOB, first + * process it. + */ + return EOB_ACT_LAST_MATCH; + } + } + + /* Try to read more data. */ + + /* First move last chars to start of buffer. */ + number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1; + + for ( i = 0; i < number_to_move; ++i ) + *(dest++) = *(source++); + + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING ) + /* don't do the read, it's not guaranteed to return an EOF, + * just force an EOF + */ + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0; + + else + { + int num_to_read = + YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; + + while ( num_to_read <= 0 ) + { /* Not enough room in the buffer - grow it. */ + + /* just a shorter name for the current buffer */ + YY_BUFFER_STATE b = YY_CURRENT_BUFFER; + + int yy_c_buf_p_offset = + (int) ((yy_c_buf_p) - b->yy_ch_buf); + + if ( b->yy_is_our_buffer ) + { + int new_size = b->yy_buf_size * 2; + + if ( new_size <= 0 ) + b->yy_buf_size += b->yy_buf_size / 8; + else + b->yy_buf_size *= 2; + + b->yy_ch_buf = (char *) + /* Include room in for 2 EOB chars. */ + zconfrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ); + } + else + /* Can't grow it, we don't own it. */ + b->yy_ch_buf = 0; + + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( + "fatal error - scanner input buffer overflow" ); + + (yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset]; + + num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - + number_to_move - 1; + + } + + if ( num_to_read > YY_READ_BUF_SIZE ) + num_to_read = YY_READ_BUF_SIZE; + + /* Read in more data. */ + YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), + (yy_n_chars), (size_t) num_to_read ); + + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + if ( (yy_n_chars) == 0 ) + { + if ( number_to_move == YY_MORE_ADJ ) + { + ret_val = EOB_ACT_END_OF_FILE; + zconfrestart(zconfin ); + } + + else + { + ret_val = EOB_ACT_LAST_MATCH; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = + YY_BUFFER_EOF_PENDING; + } + } + + else + ret_val = EOB_ACT_CONTINUE_SCAN; + + if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { + /* Extend the array by 50%, plus the number we really need. */ + yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1); + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) zconfrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ); + if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" ); + } + + (yy_n_chars) += number_to_move; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR; + + (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; + + return ret_val; +} + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + + static yy_state_type yy_get_previous_state (void) +{ + register yy_state_type yy_current_state; + register char *yy_cp; + + yy_current_state = (yy_start); + + for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp ) + { + yy_current_state = yy_nxt[yy_current_state][(*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1)]; + } + + return yy_current_state; +} + +/* yy_try_NUL_trans - try to make a transition on the NUL character + * + * synopsis + * next_state = yy_try_NUL_trans( current_state ); + */ + static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state ) +{ + register int yy_is_jam; + + yy_current_state = yy_nxt[yy_current_state][1]; + yy_is_jam = (yy_current_state <= 0); + + return yy_is_jam ? 0 : yy_current_state; +} + + static void yyunput (int c, register char * yy_bp ) +{ + register char *yy_cp; + + yy_cp = (yy_c_buf_p); + + /* undo effects of setting up zconftext */ + *yy_cp = (yy_hold_char); + + if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) + { /* need to shift things up to make room */ + /* +2 for EOB chars. */ + register int number_to_move = (yy_n_chars) + 2; + register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[ + YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2]; + register char *source = + &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]; + + while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) + *--dest = *--source; + + yy_cp += (int) (dest - source); + yy_bp += (int) (dest - source); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = + (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_buf_size; + + if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) + YY_FATAL_ERROR( "flex scanner push-back overflow" ); + } + + *--yy_cp = (char) c; + + (yytext_ptr) = yy_bp; + (yy_hold_char) = *yy_cp; + (yy_c_buf_p) = yy_cp; +} + +#ifndef YY_NO_INPUT +#ifdef __cplusplus + static int yyinput (void) +#else + static int input (void) +#endif + +{ + int c; + + *(yy_c_buf_p) = (yy_hold_char); + + if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR ) + { + /* yy_c_buf_p now points to the character we want to return. + * If this occurs *before* the EOB characters, then it's a + * valid NUL; if not, then we've hit the end of the buffer. + */ + if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) + /* This was really a NUL. */ + *(yy_c_buf_p) = '\0'; + + else + { /* need more input */ + int offset = (yy_c_buf_p) - (yytext_ptr); + ++(yy_c_buf_p); + + switch ( yy_get_next_buffer( ) ) + { + case EOB_ACT_LAST_MATCH: + /* This happens because yy_g_n_b() + * sees that we've accumulated a + * token and flags that we need to + * try matching the token before + * proceeding. But for input(), + * there's no matching to consider. + * So convert the EOB_ACT_LAST_MATCH + * to EOB_ACT_END_OF_FILE. + */ + + /* Reset buffer status. */ + zconfrestart(zconfin ); + + /*FALLTHROUGH*/ + + case EOB_ACT_END_OF_FILE: + { + if ( zconfwrap( ) ) + return EOF; + + if ( ! (yy_did_buffer_switch_on_eof) ) + YY_NEW_FILE; +#ifdef __cplusplus + return yyinput(); +#else + return input(); +#endif + } + + case EOB_ACT_CONTINUE_SCAN: + (yy_c_buf_p) = (yytext_ptr) + offset; + break; + } + } + } + + c = *(unsigned char *) (yy_c_buf_p); /* cast for 8-bit char's */ + *(yy_c_buf_p) = '\0'; /* preserve zconftext */ + (yy_hold_char) = *++(yy_c_buf_p); + + return c; +} +#endif /* ifndef YY_NO_INPUT */ + +/** Immediately switch to a different input stream. + * @param input_file A readable stream. + * + * @note This function does not reset the start condition to @c INITIAL . + */ + void zconfrestart (FILE * input_file ) +{ + + if ( ! YY_CURRENT_BUFFER ){ + zconfensure_buffer_stack (); + YY_CURRENT_BUFFER_LVALUE = + zconf_create_buffer(zconfin,YY_BUF_SIZE ); + } + + zconf_init_buffer(YY_CURRENT_BUFFER,input_file ); + zconf_load_buffer_state( ); +} + +/** Switch to a different input buffer. + * @param new_buffer The new input buffer. + * + */ + void zconf_switch_to_buffer (YY_BUFFER_STATE new_buffer ) +{ + + /* TODO. We should be able to replace this entire function body + * with + * zconfpop_buffer_state(); + * zconfpush_buffer_state(new_buffer); + */ + zconfensure_buffer_stack (); + if ( YY_CURRENT_BUFFER == new_buffer ) + return; + + if ( YY_CURRENT_BUFFER ) + { + /* Flush out information for old buffer. */ + *(yy_c_buf_p) = (yy_hold_char); + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + YY_CURRENT_BUFFER_LVALUE = new_buffer; + zconf_load_buffer_state( ); + + /* We don't actually know whether we did this switch during + * EOF (zconfwrap()) processing, but the only time this flag + * is looked at is after zconfwrap() is called, so it's safe + * to go ahead and always set it. + */ + (yy_did_buffer_switch_on_eof) = 1; +} + +static void zconf_load_buffer_state (void) +{ + (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; + zconfin = YY_CURRENT_BUFFER_LVALUE->yy_input_file; + (yy_hold_char) = *(yy_c_buf_p); +} + +/** Allocate and initialize an input buffer state. + * @param file A readable stream. + * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. + * + * @return the allocated buffer state. + */ + YY_BUFFER_STATE zconf_create_buffer (FILE * file, int size ) +{ + YY_BUFFER_STATE b; + + b = (YY_BUFFER_STATE) zconfalloc(sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in zconf_create_buffer()" ); + + b->yy_buf_size = size; + + /* yy_ch_buf has to be 2 characters longer than the size given because + * we need to put in 2 end-of-buffer characters. + */ + b->yy_ch_buf = (char *) zconfalloc(b->yy_buf_size + 2 ); + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in zconf_create_buffer()" ); + + b->yy_is_our_buffer = 1; + + zconf_init_buffer(b,file ); + + return b; +} + +/** Destroy the buffer. + * @param b a buffer created with zconf_create_buffer() + * + */ + void zconf_delete_buffer (YY_BUFFER_STATE b ) +{ + + if ( ! b ) + return; + + if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */ + YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; + + if ( b->yy_is_our_buffer ) + zconffree((void *) b->yy_ch_buf ); + + zconffree((void *) b ); +} + +/* Initializes or reinitializes a buffer. + * This function is sometimes called more than once on the same buffer, + * such as during a zconfrestart() or at EOF. + */ + static void zconf_init_buffer (YY_BUFFER_STATE b, FILE * file ) + +{ + int oerrno = errno; + + zconf_flush_buffer(b ); + + b->yy_input_file = file; + b->yy_fill_buffer = 1; + + /* If b is the current buffer, then zconf_init_buffer was _probably_ + * called from zconfrestart() or through yy_get_next_buffer. + * In that case, we don't want to reset the lineno or column. + */ + if (b != YY_CURRENT_BUFFER){ + b->yy_bs_lineno = 1; + b->yy_bs_column = 0; + } + + b->yy_is_interactive = 0; + + errno = oerrno; +} + +/** Discard all buffered characters. On the next scan, YY_INPUT will be called. + * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. + * + */ + void zconf_flush_buffer (YY_BUFFER_STATE b ) +{ + if ( ! b ) + return; + + b->yy_n_chars = 0; + + /* We always need two end-of-buffer characters. The first causes + * a transition to the end-of-buffer state. The second causes + * a jam in that state. + */ + b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; + b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; + + b->yy_buf_pos = &b->yy_ch_buf[0]; + + b->yy_at_bol = 1; + b->yy_buffer_status = YY_BUFFER_NEW; + + if ( b == YY_CURRENT_BUFFER ) + zconf_load_buffer_state( ); +} + +/** Pushes the new state onto the stack. The new state becomes + * the current state. This function will allocate the stack + * if necessary. + * @param new_buffer The new state. + * + */ +void zconfpush_buffer_state (YY_BUFFER_STATE new_buffer ) +{ + if (new_buffer == NULL) + return; + + zconfensure_buffer_stack(); + + /* This block is copied from zconf_switch_to_buffer. */ + if ( YY_CURRENT_BUFFER ) + { + /* Flush out information for old buffer. */ + *(yy_c_buf_p) = (yy_hold_char); + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + /* Only push if top exists. Otherwise, replace top. */ + if (YY_CURRENT_BUFFER) + (yy_buffer_stack_top)++; + YY_CURRENT_BUFFER_LVALUE = new_buffer; + + /* copied from zconf_switch_to_buffer. */ + zconf_load_buffer_state( ); + (yy_did_buffer_switch_on_eof) = 1; +} + +/** Removes and deletes the top of the stack, if present. + * The next element becomes the new top. + * + */ +void zconfpop_buffer_state (void) +{ + if (!YY_CURRENT_BUFFER) + return; + + zconf_delete_buffer(YY_CURRENT_BUFFER ); + YY_CURRENT_BUFFER_LVALUE = NULL; + if ((yy_buffer_stack_top) > 0) + --(yy_buffer_stack_top); + + if (YY_CURRENT_BUFFER) { + zconf_load_buffer_state( ); + (yy_did_buffer_switch_on_eof) = 1; + } +} + +/* Allocates the stack if it does not exist. + * Guarantees space for at least one push. + */ +static void zconfensure_buffer_stack (void) +{ + int num_to_alloc; + + if (!(yy_buffer_stack)) { + + /* First allocation is just for 2 elements, since we don't know if this + * scanner will even need a stack. We use 2 instead of 1 to avoid an + * immediate realloc on the next call. + */ + num_to_alloc = 1; + (yy_buffer_stack) = (struct yy_buffer_state**)zconfalloc + (num_to_alloc * sizeof(struct yy_buffer_state*) + ); + if ( ! (yy_buffer_stack) ) + YY_FATAL_ERROR( "out of dynamic memory in zconfensure_buffer_stack()" ); + + memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*)); + + (yy_buffer_stack_max) = num_to_alloc; + (yy_buffer_stack_top) = 0; + return; + } + + if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){ + + /* Increase the buffer to prepare for a possible push. */ + int grow_size = 8 /* arbitrary grow size */; + + num_to_alloc = (yy_buffer_stack_max) + grow_size; + (yy_buffer_stack) = (struct yy_buffer_state**)zconfrealloc + ((yy_buffer_stack), + num_to_alloc * sizeof(struct yy_buffer_state*) + ); + if ( ! (yy_buffer_stack) ) + YY_FATAL_ERROR( "out of dynamic memory in zconfensure_buffer_stack()" ); + + /* zero only the new slots.*/ + memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*)); + (yy_buffer_stack_max) = num_to_alloc; + } +} + +/** Setup the input buffer state to scan directly from a user-specified character buffer. + * @param base the character buffer + * @param size the size in bytes of the character buffer + * + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE zconf_scan_buffer (char * base, yy_size_t size ) +{ + YY_BUFFER_STATE b; + + if ( size < 2 || + base[size-2] != YY_END_OF_BUFFER_CHAR || + base[size-1] != YY_END_OF_BUFFER_CHAR ) + /* They forgot to leave room for the EOB's. */ + return 0; + + b = (YY_BUFFER_STATE) zconfalloc(sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in zconf_scan_buffer()" ); + + b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ + b->yy_buf_pos = b->yy_ch_buf = base; + b->yy_is_our_buffer = 0; + b->yy_input_file = 0; + b->yy_n_chars = b->yy_buf_size; + b->yy_is_interactive = 0; + b->yy_at_bol = 1; + b->yy_fill_buffer = 0; + b->yy_buffer_status = YY_BUFFER_NEW; + + zconf_switch_to_buffer(b ); + + return b; +} + +/** Setup the input buffer state to scan a string. The next call to zconflex() will + * scan from a @e copy of @a str. + * @param yystr a NUL-terminated string to scan + * + * @return the newly allocated buffer state object. + * @note If you want to scan bytes that may contain NUL values, then use + * zconf_scan_bytes() instead. + */ +YY_BUFFER_STATE zconf_scan_string (yyconst char * yystr ) +{ + + return zconf_scan_bytes(yystr,strlen(yystr) ); +} + +/** Setup the input buffer state to scan the given bytes. The next call to zconflex() will + * scan from a @e copy of @a bytes. + * @param bytes the byte buffer to scan + * @param len the number of bytes in the buffer pointed to by @a bytes. + * + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE zconf_scan_bytes (yyconst char * yybytes, int _yybytes_len ) +{ + YY_BUFFER_STATE b; + char *buf; + yy_size_t n; + int i; + + /* Get memory for full buffer, including space for trailing EOB's. */ + n = _yybytes_len + 2; + buf = (char *) zconfalloc(n ); + if ( ! buf ) + YY_FATAL_ERROR( "out of dynamic memory in zconf_scan_bytes()" ); + + for ( i = 0; i < _yybytes_len; ++i ) + buf[i] = yybytes[i]; + + buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR; + + b = zconf_scan_buffer(buf,n ); + if ( ! b ) + YY_FATAL_ERROR( "bad buffer in zconf_scan_bytes()" ); + + /* It's okay to grow etc. this buffer, and we should throw it + * away when we're done. + */ + b->yy_is_our_buffer = 1; + + return b; +} + +#ifndef YY_EXIT_FAILURE +#define YY_EXIT_FAILURE 2 +#endif + +static void yy_fatal_error (yyconst char* msg ) +{ + (void) fprintf( stderr, "%s\n", msg ); + exit( YY_EXIT_FAILURE ); +} + +/* Redefine yyless() so it works in section 3 code. */ + +#undef yyless +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up zconftext. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + zconftext[zconfleng] = (yy_hold_char); \ + (yy_c_buf_p) = zconftext + yyless_macro_arg; \ + (yy_hold_char) = *(yy_c_buf_p); \ + *(yy_c_buf_p) = '\0'; \ + zconfleng = yyless_macro_arg; \ + } \ + while ( 0 ) + +/* Accessor methods (get/set functions) to struct members. */ + +/** Get the current line number. + * + */ +int zconfget_lineno (void) +{ + + return zconflineno; +} + +/** Get the input stream. + * + */ +FILE *zconfget_in (void) +{ + return zconfin; +} + +/** Get the output stream. + * + */ +FILE *zconfget_out (void) +{ + return zconfout; +} + +/** Get the length of the current token. + * + */ +int zconfget_leng (void) +{ + return zconfleng; +} + +/** Get the current token. + * + */ + +char *zconfget_text (void) +{ + return zconftext; +} + +/** Set the current line number. + * @param line_number + * + */ +void zconfset_lineno (int line_number ) +{ + + zconflineno = line_number; +} + +/** Set the input stream. This does not discard the current + * input buffer. + * @param in_str A readable stream. + * + * @see zconf_switch_to_buffer + */ +void zconfset_in (FILE * in_str ) +{ + zconfin = in_str ; +} + +void zconfset_out (FILE * out_str ) +{ + zconfout = out_str ; +} + +int zconfget_debug (void) +{ + return zconf_flex_debug; +} + +void zconfset_debug (int bdebug ) +{ + zconf_flex_debug = bdebug ; +} + +static int yy_init_globals (void) +{ + /* Initialization is the same as for the non-reentrant scanner. + * This function is called from zconflex_destroy(), so don't allocate here. + */ + + (yy_buffer_stack) = 0; + (yy_buffer_stack_top) = 0; + (yy_buffer_stack_max) = 0; + (yy_c_buf_p) = (char *) 0; + (yy_init) = 0; + (yy_start) = 0; + +/* Defined in main.c */ +#ifdef YY_STDINIT + zconfin = stdin; + zconfout = stdout; +#else + zconfin = (FILE *) 0; + zconfout = (FILE *) 0; +#endif + + /* For future reference: Set errno on error, since we are called by + * zconflex_init() + */ + return 0; +} + +/* zconflex_destroy is for both reentrant and non-reentrant scanners. */ +int zconflex_destroy (void) +{ + + /* Pop the buffer stack, destroying each element. */ + while(YY_CURRENT_BUFFER){ + zconf_delete_buffer(YY_CURRENT_BUFFER ); + YY_CURRENT_BUFFER_LVALUE = NULL; + zconfpop_buffer_state(); + } + + /* Destroy the stack itself. */ + zconffree((yy_buffer_stack) ); + (yy_buffer_stack) = NULL; + + /* Reset the globals. This is important in a non-reentrant scanner so the next time + * zconflex() is called, initialization will occur. */ + yy_init_globals( ); + + return 0; +} + +/* + * Internal utility routines. + */ + +#ifndef yytext_ptr +static void yy_flex_strncpy (char* s1, yyconst char * s2, int n ) +{ + register int i; + for ( i = 0; i < n; ++i ) + s1[i] = s2[i]; +} +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen (yyconst char * s ) +{ + register int n; + for ( n = 0; s[n]; ++n ) + ; + + return n; +} +#endif + +void *zconfalloc (yy_size_t size ) +{ + return (void *) malloc( size ); +} + +void *zconfrealloc (void * ptr, yy_size_t size ) +{ + /* The cast to (char *) in the following accommodates both + * implementations that use char* generic pointers, and those + * that use void* generic pointers. It works with the latter + * because both ANSI C and C++ allow castless assignment from + * any pointer type to void*, and deal with argument conversions + * as though doing an assignment. + */ + return (void *) realloc( (char *) ptr, size ); +} + +void zconffree (void * ptr ) +{ + free( (char *) ptr ); /* see zconfrealloc() for (char *) cast */ +} + +#define YYTABLES_NAME "yytables" + +void zconf_starthelp(void) +{ + new_string(); + last_ts = first_ts = 0; + BEGIN(HELP); +} + +static void zconf_endhelp(void) +{ + zconflval.string = text; + BEGIN(INITIAL); +} + +/* + * Try to open specified file with following names: + * ./name + * $(srctree)/name + * The latter is used when srctree is separate from objtree + * when compiling the kernel. + * Return NULL if file is not found. + */ +FILE *zconf_fopen(const char *name) +{ + char *env, fullname[PATH_MAX+1]; + FILE *f; + + f = fopen(name, "r"); + if (!f && name != NULL && name[0] != '/') { + env = getenv(SRCTREE); + if (env) { + sprintf(fullname, "%s/%s", env, name); + f = fopen(fullname, "r"); + } + } + return f; +} + +void zconf_initscan(const char *name) +{ + zconfin = zconf_fopen(name); + if (!zconfin) { + printf("can't find file %s\n", name); + exit(1); + } + + current_buf = malloc(sizeof(*current_buf)); + memset(current_buf, 0, sizeof(*current_buf)); + + current_file = file_lookup(name); + current_file->lineno = 1; +} + +void zconf_nextfile(const char *name) +{ + struct file *iter; + struct file *file = file_lookup(name); + struct buffer *buf = malloc(sizeof(*buf)); + memset(buf, 0, sizeof(*buf)); + + current_buf->state = YY_CURRENT_BUFFER; + zconfin = zconf_fopen(file->name); + if (!zconfin) { + printf("%s:%d: can't open file \"%s\"\n", + zconf_curname(), zconf_lineno(), file->name); + exit(1); + } + zconf_switch_to_buffer(zconf_create_buffer(zconfin,YY_BUF_SIZE)); + buf->parent = current_buf; + current_buf = buf; + + for (iter = current_file->parent; iter; iter = iter->parent ) { + if (!strcmp(current_file->name,iter->name) ) { + printf("%s:%d: recursive inclusion detected. " + "Inclusion path:\n current file : '%s'\n", + zconf_curname(), zconf_lineno(), + zconf_curname()); + iter = current_file->parent; + while (iter && \ + strcmp(iter->name,current_file->name)) { + printf(" included from: '%s:%d'\n", + iter->name, iter->lineno-1); + iter = iter->parent; + } + if (iter) + printf(" included from: '%s:%d'\n", + iter->name, iter->lineno+1); + exit(1); + } + } + file->lineno = 1; + file->parent = current_file; + current_file = file; +} + +static void zconf_endfile(void) +{ + struct buffer *parent; + + current_file = current_file->parent; + + parent = current_buf->parent; + if (parent) { + fclose(zconfin); + zconf_delete_buffer(YY_CURRENT_BUFFER); + zconf_switch_to_buffer(parent->state); + } + free(current_buf); + current_buf = parent; +} + +int zconf_lineno(void) +{ + return current_pos.lineno; +} + +const char *zconf_curname(void) +{ + return current_pos.file ? current_pos.file->name : ""; +} + diff --git a/kernel/fiasco/tool/kconfig/scripts/kconfig/zconf.tab.c_shipped b/kernel/fiasco/tool/kconfig/scripts/kconfig/zconf.tab.c_shipped new file mode 100644 index 00000000..d2c56f3c --- /dev/null +++ b/kernel/fiasco/tool/kconfig/scripts/kconfig/zconf.tab.c_shipped @@ -0,0 +1,2504 @@ +/* A Bison parser, made by GNU Bison 2.4.3. */ + +/* Skeleton implementation for Bison's Yacc-like parsers in C + + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006, + 2009, 2010 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* As a special exception, you may create a larger work that contains + part or all of the Bison parser skeleton and distribute that work + under terms of your choice, so long as that work isn't itself a + parser generator using the skeleton or a modified version thereof + as a parser skeleton. Alternatively, if you modify or redistribute + the parser skeleton itself, you may (at your option) remove this + special exception, which will cause the skeleton and the resulting + Bison output files to be licensed under the GNU General Public + License without this special exception. + + This special exception was added by the Free Software Foundation in + version 2.2 of Bison. */ + +/* C LALR(1) parser skeleton written by Richard Stallman, by + simplifying the original so-called "semantic" parser. */ + +/* All symbols defined below should begin with yy or YY, to avoid + infringing on user name space. This should be done even for local + variables, as they might otherwise be expanded by user macros. + There are some unavoidable exceptions within include files to + define necessary library symbols; they are noted "INFRINGES ON + USER NAME SPACE" below. */ + +/* Identify Bison output. */ +#define YYBISON 1 + +/* Bison version. */ +#define YYBISON_VERSION "2.4.3" + +/* Skeleton name. */ +#define YYSKELETON_NAME "yacc.c" + +/* Pure parsers. */ +#define YYPURE 0 + +/* Push parsers. */ +#define YYPUSH 0 + +/* Pull parsers. */ +#define YYPULL 1 + +/* Using locations. */ +#define YYLSP_NEEDED 0 + +/* Substitute the variable and function names. */ +#define yyparse zconfparse +#define yylex zconflex +#define yyerror zconferror +#define yylval zconflval +#define yychar zconfchar +#define yydebug zconfdebug +#define yynerrs zconfnerrs + + +/* Copy the first part of user declarations. */ + + +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +#include +#include +#include +#include +#include +#include + +#include "lkc.h" + +#define printd(mask, fmt...) if (cdebug & (mask)) printf(fmt) + +#define PRINTD 0x0001 +#define DEBUG_PARSE 0x0002 + +int cdebug = PRINTD; + +extern int zconflex(void); +static void zconfprint(const char *err, ...); +static void zconf_error(const char *err, ...); +static void zconferror(const char *err); +static bool zconf_endtoken(const struct kconf_id *id, int starttoken, int endtoken); + +struct symbol *symbol_hash[SYMBOL_HASHSIZE]; + +static struct menu *current_menu, *current_entry; + + + + +/* Enabling traces. */ +#ifndef YYDEBUG +# define YYDEBUG 1 +#endif + +/* Enabling verbose error messages. */ +#ifdef YYERROR_VERBOSE +# undef YYERROR_VERBOSE +# define YYERROR_VERBOSE 1 +#else +# define YYERROR_VERBOSE 0 +#endif + +/* Enabling the token table. */ +#ifndef YYTOKEN_TABLE +# define YYTOKEN_TABLE 0 +#endif + + +/* Tokens. */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE + /* Put the tokens into the symbol table, so that GDB and other debuggers + know about them. */ + enum yytokentype { + T_MAINMENU = 258, + T_MENU = 259, + T_ENDMENU = 260, + T_SOURCE = 261, + T_CHOICE = 262, + T_ENDCHOICE = 263, + T_COMMENT = 264, + T_CONFIG = 265, + T_MENUCONFIG = 266, + T_HELP = 267, + T_HELPTEXT = 268, + T_IF = 269, + T_ENDIF = 270, + T_DEPENDS = 271, + T_OPTIONAL = 272, + T_PROMPT = 273, + T_TYPE = 274, + T_DEFAULT = 275, + T_SELECT = 276, + T_RANGE = 277, + T_VISIBLE = 278, + T_OPTION = 279, + T_ON = 280, + T_WORD = 281, + T_WORD_QUOTE = 282, + T_UNEQUAL = 283, + T_CLOSE_PAREN = 284, + T_OPEN_PAREN = 285, + T_EOL = 286, + T_OR = 287, + T_AND = 288, + T_EQUAL = 289, + T_NOT = 290 + }; +#endif + + + +#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED +typedef union YYSTYPE +{ + + + char *string; + struct file *file; + struct symbol *symbol; + struct expr *expr; + struct menu *menu; + const struct kconf_id *id; + + + +} YYSTYPE; +# define YYSTYPE_IS_TRIVIAL 1 +# define yystype YYSTYPE /* obsolescent; will be withdrawn */ +# define YYSTYPE_IS_DECLARED 1 +#endif + + +/* Copy the second part of user declarations. */ + + +/* Include zconf.hash.c here so it can see the token constants. */ +#include "zconf.hash.c" + + + +#ifdef short +# undef short +#endif + +#ifdef YYTYPE_UINT8 +typedef YYTYPE_UINT8 yytype_uint8; +#else +typedef unsigned char yytype_uint8; +#endif + +#ifdef YYTYPE_INT8 +typedef YYTYPE_INT8 yytype_int8; +#elif (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +typedef signed char yytype_int8; +#else +typedef short int yytype_int8; +#endif + +#ifdef YYTYPE_UINT16 +typedef YYTYPE_UINT16 yytype_uint16; +#else +typedef unsigned short int yytype_uint16; +#endif + +#ifdef YYTYPE_INT16 +typedef YYTYPE_INT16 yytype_int16; +#else +typedef short int yytype_int16; +#endif + +#ifndef YYSIZE_T +# ifdef __SIZE_TYPE__ +# define YYSIZE_T __SIZE_TYPE__ +# elif defined size_t +# define YYSIZE_T size_t +# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +# include /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +# else +# define YYSIZE_T unsigned int +# endif +#endif + +#define YYSIZE_MAXIMUM ((YYSIZE_T) -1) + +#ifndef YY_ +# if defined YYENABLE_NLS && YYENABLE_NLS +# if ENABLE_NLS +# include /* INFRINGES ON USER NAME SPACE */ +# define YY_(msgid) dgettext ("bison-runtime", msgid) +# endif +# endif +# ifndef YY_ +# define YY_(msgid) msgid +# endif +#endif + +/* Suppress unused-variable warnings by "using" E. */ +#if ! defined lint || defined __GNUC__ +# define YYUSE(e) ((void) (e)) +#else +# define YYUSE(e) /* empty */ +#endif + +/* Identity function, used to suppress warnings about constant conditions. */ +#ifndef lint +# define YYID(n) (n) +#else +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static int +YYID (int yyi) +#else +static int +YYID (yyi) + int yyi; +#endif +{ + return yyi; +} +#endif + +#if ! defined yyoverflow || YYERROR_VERBOSE + +/* The parser invokes alloca or malloc; define the necessary symbols. */ + +# ifdef YYSTACK_USE_ALLOCA +# if YYSTACK_USE_ALLOCA +# ifdef __GNUC__ +# define YYSTACK_ALLOC __builtin_alloca +# elif defined __BUILTIN_VA_ARG_INCR +# include /* INFRINGES ON USER NAME SPACE */ +# elif defined _AIX +# define YYSTACK_ALLOC __alloca +# elif defined _MSC_VER +# include /* INFRINGES ON USER NAME SPACE */ +# define alloca _alloca +# else +# define YYSTACK_ALLOC alloca +# if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +# include /* INFRINGES ON USER NAME SPACE */ +# ifndef _STDLIB_H +# define _STDLIB_H 1 +# endif +# endif +# endif +# endif +# endif + +# ifdef YYSTACK_ALLOC + /* Pacify GCC's `empty if-body' warning. */ +# define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0)) +# ifndef YYSTACK_ALLOC_MAXIMUM + /* The OS might guarantee only one guard page at the bottom of the stack, + and a page size can be as small as 4096 bytes. So we cannot safely + invoke alloca (N) if N exceeds 4096. Use a slightly smaller number + to allow for a few compiler-allocated temporary stack slots. */ +# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */ +# endif +# else +# define YYSTACK_ALLOC YYMALLOC +# define YYSTACK_FREE YYFREE +# ifndef YYSTACK_ALLOC_MAXIMUM +# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM +# endif +# if (defined __cplusplus && ! defined _STDLIB_H \ + && ! ((defined YYMALLOC || defined malloc) \ + && (defined YYFREE || defined free))) +# include /* INFRINGES ON USER NAME SPACE */ +# ifndef _STDLIB_H +# define _STDLIB_H 1 +# endif +# endif +# ifndef YYMALLOC +# define YYMALLOC malloc +# if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# ifndef YYFREE +# define YYFREE free +# if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +void free (void *); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# endif +#endif /* ! defined yyoverflow || YYERROR_VERBOSE */ + + +#if (! defined yyoverflow \ + && (! defined __cplusplus \ + || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) + +/* A type that is properly aligned for any stack member. */ +union yyalloc +{ + yytype_int16 yyss_alloc; + YYSTYPE yyvs_alloc; +}; + +/* The size of the maximum gap between one aligned stack and the next. */ +# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) + +/* The size of an array large to enough to hold all stacks, each with + N elements. */ +# define YYSTACK_BYTES(N) \ + ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \ + + YYSTACK_GAP_MAXIMUM) + +/* Copy COUNT objects from FROM to TO. The source and destination do + not overlap. */ +# ifndef YYCOPY +# if defined __GNUC__ && 1 < __GNUC__ +# define YYCOPY(To, From, Count) \ + __builtin_memcpy (To, From, (Count) * sizeof (*(From))) +# else +# define YYCOPY(To, From, Count) \ + do \ + { \ + YYSIZE_T yyi; \ + for (yyi = 0; yyi < (Count); yyi++) \ + (To)[yyi] = (From)[yyi]; \ + } \ + while (YYID (0)) +# endif +# endif + +/* Relocate STACK from its old location to the new one. The + local variables YYSIZE and YYSTACKSIZE give the old and new number of + elements in the stack, and YYPTR gives the new location of the + stack. Advance YYPTR to a properly aligned location for the next + stack. */ +# define YYSTACK_RELOCATE(Stack_alloc, Stack) \ + do \ + { \ + YYSIZE_T yynewbytes; \ + YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \ + Stack = &yyptr->Stack_alloc; \ + yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ + yyptr += yynewbytes / sizeof (*yyptr); \ + } \ + while (YYID (0)) + +#endif + +/* YYFINAL -- State number of the termination state. */ +#define YYFINAL 11 +/* YYLAST -- Last index in YYTABLE. */ +#define YYLAST 290 + +/* YYNTOKENS -- Number of terminals. */ +#define YYNTOKENS 36 +/* YYNNTS -- Number of nonterminals. */ +#define YYNNTS 50 +/* YYNRULES -- Number of rules. */ +#define YYNRULES 118 +/* YYNRULES -- Number of states. */ +#define YYNSTATES 191 + +/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ +#define YYUNDEFTOK 2 +#define YYMAXUTOK 290 + +#define YYTRANSLATE(YYX) \ + ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) + +/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */ +static const yytype_uint8 yytranslate[] = +{ + 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, + 35 +}; + +#if YYDEBUG +/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in + YYRHS. */ +static const yytype_uint16 yyprhs[] = +{ + 0, 0, 3, 6, 8, 11, 13, 14, 17, 20, + 23, 26, 31, 36, 40, 42, 44, 46, 48, 50, + 52, 54, 56, 58, 60, 62, 64, 66, 68, 72, + 75, 79, 82, 86, 89, 90, 93, 96, 99, 102, + 105, 108, 112, 117, 122, 127, 133, 137, 138, 142, + 143, 146, 150, 153, 155, 159, 160, 163, 166, 169, + 172, 175, 180, 184, 187, 192, 193, 196, 200, 202, + 206, 207, 210, 213, 216, 220, 224, 228, 230, 234, + 235, 238, 241, 244, 248, 252, 255, 258, 261, 262, + 265, 268, 271, 276, 277, 280, 283, 286, 287, 290, + 292, 294, 297, 300, 303, 305, 308, 309, 312, 314, + 318, 322, 326, 329, 333, 337, 339, 341, 342 +}; + +/* YYRHS -- A `-1'-separated list of the rules' RHS. */ +static const yytype_int8 yyrhs[] = +{ + 37, 0, -1, 81, 38, -1, 38, -1, 63, 39, + -1, 39, -1, -1, 39, 41, -1, 39, 55, -1, + 39, 67, -1, 39, 80, -1, 39, 26, 1, 31, + -1, 39, 40, 1, 31, -1, 39, 1, 31, -1, + 16, -1, 18, -1, 19, -1, 21, -1, 17, -1, + 22, -1, 20, -1, 23, -1, 31, -1, 61, -1, + 71, -1, 44, -1, 46, -1, 69, -1, 26, 1, + 31, -1, 1, 31, -1, 10, 26, 31, -1, 43, + 47, -1, 11, 26, 31, -1, 45, 47, -1, -1, + 47, 48, -1, 47, 49, -1, 47, 75, -1, 47, + 73, -1, 47, 42, -1, 47, 31, -1, 19, 78, + 31, -1, 18, 79, 82, 31, -1, 20, 83, 82, + 31, -1, 21, 26, 82, 31, -1, 22, 84, 84, + 82, 31, -1, 24, 50, 31, -1, -1, 50, 26, + 51, -1, -1, 34, 79, -1, 7, 85, 31, -1, + 52, 56, -1, 80, -1, 53, 58, 54, -1, -1, + 56, 57, -1, 56, 75, -1, 56, 73, -1, 56, + 31, -1, 56, 42, -1, 18, 79, 82, 31, -1, + 19, 78, 31, -1, 17, 31, -1, 20, 26, 82, + 31, -1, -1, 58, 41, -1, 14, 83, 81, -1, + 80, -1, 59, 62, 60, -1, -1, 62, 41, -1, + 62, 67, -1, 62, 55, -1, 3, 79, 81, -1, + 4, 79, 31, -1, 64, 76, 74, -1, 80, -1, + 65, 68, 66, -1, -1, 68, 41, -1, 68, 67, + -1, 68, 55, -1, 6, 79, 31, -1, 9, 79, + 31, -1, 70, 74, -1, 12, 31, -1, 72, 13, + -1, -1, 74, 75, -1, 74, 31, -1, 74, 42, + -1, 16, 25, 83, 31, -1, -1, 76, 77, -1, + 76, 31, -1, 23, 82, -1, -1, 79, 82, -1, + 26, -1, 27, -1, 5, 31, -1, 8, 31, -1, + 15, 31, -1, 31, -1, 81, 31, -1, -1, 14, + 83, -1, 84, -1, 84, 34, 84, -1, 84, 28, + 84, -1, 30, 83, 29, -1, 35, 83, -1, 83, + 32, 83, -1, 83, 33, 83, -1, 26, -1, 27, + -1, -1, 26, -1 +}; + +/* YYRLINE[YYN] -- source line where rule number YYN was defined. */ +static const yytype_uint16 yyrline[] = +{ + 0, 104, 104, 104, 106, 106, 108, 110, 111, 112, + 113, 114, 115, 119, 123, 123, 123, 123, 123, 123, + 123, 123, 127, 128, 129, 130, 131, 132, 136, 137, + 143, 151, 157, 165, 175, 177, 178, 179, 180, 181, + 182, 185, 193, 199, 209, 215, 221, 224, 226, 237, + 238, 243, 252, 257, 265, 268, 270, 271, 272, 273, + 274, 277, 283, 294, 300, 310, 312, 317, 325, 333, + 336, 338, 339, 340, 345, 352, 359, 364, 372, 375, + 377, 378, 379, 382, 390, 397, 404, 410, 417, 419, + 420, 421, 424, 432, 434, 435, 438, 445, 447, 452, + 453, 456, 457, 458, 462, 463, 466, 467, 470, 471, + 472, 473, 474, 475, 476, 479, 480, 483, 484 +}; +#endif + +#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE +/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. + First, the terminals, then, starting at YYNTOKENS, nonterminals. */ +static const char *const yytname[] = +{ + "$end", "error", "$undefined", "T_MAINMENU", "T_MENU", "T_ENDMENU", + "T_SOURCE", "T_CHOICE", "T_ENDCHOICE", "T_COMMENT", "T_CONFIG", + "T_MENUCONFIG", "T_HELP", "T_HELPTEXT", "T_IF", "T_ENDIF", "T_DEPENDS", + "T_OPTIONAL", "T_PROMPT", "T_TYPE", "T_DEFAULT", "T_SELECT", "T_RANGE", + "T_VISIBLE", "T_OPTION", "T_ON", "T_WORD", "T_WORD_QUOTE", "T_UNEQUAL", + "T_CLOSE_PAREN", "T_OPEN_PAREN", "T_EOL", "T_OR", "T_AND", "T_EQUAL", + "T_NOT", "$accept", "input", "start", "stmt_list", "option_name", + "common_stmt", "option_error", "config_entry_start", "config_stmt", + "menuconfig_entry_start", "menuconfig_stmt", "config_option_list", + "config_option", "symbol_option", "symbol_option_list", + "symbol_option_arg", "choice", "choice_entry", "choice_end", + "choice_stmt", "choice_option_list", "choice_option", "choice_block", + "if_entry", "if_end", "if_stmt", "if_block", "mainmenu_stmt", "menu", + "menu_entry", "menu_end", "menu_stmt", "menu_block", "source_stmt", + "comment", "comment_stmt", "help_start", "help", "depends_list", + "depends", "visibility_list", "visible", "prompt_stmt_opt", "prompt", + "end", "nl", "if_expr", "expr", "symbol", "word_opt", 0 +}; +#endif + +# ifdef YYPRINT +/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to + token YYLEX-NUM. */ +static const yytype_uint16 yytoknum[] = +{ + 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, + 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, + 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, + 285, 286, 287, 288, 289, 290 +}; +# endif + +/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ +static const yytype_uint8 yyr1[] = +{ + 0, 36, 37, 37, 38, 38, 39, 39, 39, 39, + 39, 39, 39, 39, 40, 40, 40, 40, 40, 40, + 40, 40, 41, 41, 41, 41, 41, 41, 42, 42, + 43, 44, 45, 46, 47, 47, 47, 47, 47, 47, + 47, 48, 48, 48, 48, 48, 49, 50, 50, 51, + 51, 52, 53, 54, 55, 56, 56, 56, 56, 56, + 56, 57, 57, 57, 57, 58, 58, 59, 60, 61, + 62, 62, 62, 62, 63, 64, 65, 66, 67, 68, + 68, 68, 68, 69, 70, 71, 72, 73, 74, 74, + 74, 74, 75, 76, 76, 76, 77, 78, 78, 79, + 79, 80, 80, 80, 81, 81, 82, 82, 83, 83, + 83, 83, 83, 83, 83, 84, 84, 85, 85 +}; + +/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ +static const yytype_uint8 yyr2[] = +{ + 0, 2, 2, 1, 2, 1, 0, 2, 2, 2, + 2, 4, 4, 3, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 3, 2, + 3, 2, 3, 2, 0, 2, 2, 2, 2, 2, + 2, 3, 4, 4, 4, 5, 3, 0, 3, 0, + 2, 3, 2, 1, 3, 0, 2, 2, 2, 2, + 2, 4, 3, 2, 4, 0, 2, 3, 1, 3, + 0, 2, 2, 2, 3, 3, 3, 1, 3, 0, + 2, 2, 2, 3, 3, 2, 2, 2, 0, 2, + 2, 2, 4, 0, 2, 2, 2, 0, 2, 1, + 1, 2, 2, 2, 1, 2, 0, 2, 1, 3, + 3, 3, 2, 3, 3, 1, 1, 0, 1 +}; + +/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state + STATE-NUM when YYTABLE doesn't specify something else to do. Zero + means the default is an error. */ +static const yytype_uint8 yydefact[] = +{ + 6, 0, 104, 0, 3, 0, 6, 6, 99, 100, + 0, 1, 0, 0, 0, 0, 117, 0, 0, 0, + 0, 0, 0, 14, 18, 15, 16, 20, 17, 19, + 21, 0, 22, 0, 7, 34, 25, 34, 26, 55, + 65, 8, 70, 23, 93, 79, 9, 27, 88, 24, + 10, 0, 105, 2, 74, 13, 0, 101, 0, 118, + 0, 102, 0, 0, 0, 115, 116, 0, 0, 0, + 108, 103, 0, 0, 0, 0, 0, 0, 0, 88, + 0, 0, 75, 83, 51, 84, 30, 32, 0, 112, + 0, 0, 67, 0, 0, 11, 12, 0, 0, 0, + 0, 97, 0, 0, 0, 47, 0, 40, 39, 35, + 36, 0, 38, 37, 0, 0, 97, 0, 59, 60, + 56, 58, 57, 66, 54, 53, 71, 73, 69, 72, + 68, 106, 95, 0, 94, 80, 82, 78, 81, 77, + 90, 91, 89, 111, 113, 114, 110, 109, 29, 86, + 0, 106, 0, 106, 106, 106, 0, 0, 0, 87, + 63, 106, 0, 106, 0, 96, 0, 0, 41, 98, + 0, 0, 106, 49, 46, 28, 0, 62, 0, 107, + 92, 42, 43, 44, 0, 0, 48, 61, 64, 45, + 50 +}; + +/* YYDEFGOTO[NTERM-NUM]. */ +static const yytype_int16 yydefgoto[] = +{ + -1, 3, 4, 5, 33, 34, 108, 35, 36, 37, + 38, 74, 109, 110, 157, 186, 39, 40, 124, 41, + 76, 120, 77, 42, 128, 43, 78, 6, 44, 45, + 137, 46, 80, 47, 48, 49, 111, 112, 81, 113, + 79, 134, 152, 153, 50, 7, 165, 69, 70, 60 +}; + +/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing + STATE-NUM. */ +#define YYPACT_NINF -90 +static const yytype_int16 yypact[] = +{ + 4, 42, -90, 96, -90, 111, -90, 15, -90, -90, + 75, -90, 82, 42, 104, 42, 110, 107, 42, 115, + 125, -4, 121, -90, -90, -90, -90, -90, -90, -90, + -90, 162, -90, 163, -90, -90, -90, -90, -90, -90, + -90, -90, -90, -90, -90, -90, -90, -90, -90, -90, + -90, 139, -90, -90, 138, -90, 142, -90, 143, -90, + 152, -90, 164, 167, 168, -90, -90, -4, -4, 77, + -18, -90, 177, 185, 33, 71, 195, 247, 236, -2, + 236, 171, -90, -90, -90, -90, -90, -90, 41, -90, + -4, -4, 138, 97, 97, -90, -90, 186, 187, 194, + 42, 42, -4, 196, 97, -90, 219, -90, -90, -90, + -90, 210, -90, -90, 204, 42, 42, 199, -90, -90, + -90, -90, -90, -90, -90, -90, -90, -90, -90, -90, + -90, 222, -90, 223, -90, -90, -90, -90, -90, -90, + -90, -90, -90, -90, 215, -90, -90, -90, -90, -90, + -4, 222, 228, 222, -5, 222, 97, 35, 229, -90, + -90, 222, 232, 222, -4, -90, 135, 233, -90, -90, + 234, 235, 222, 240, -90, -90, 237, -90, 239, -13, + -90, -90, -90, -90, 244, 42, -90, -90, -90, -90, + -90 +}; + +/* YYPGOTO[NTERM-NUM]. */ +static const yytype_int16 yypgoto[] = +{ + -90, -90, 269, 271, -90, 23, -70, -90, -90, -90, + -90, 243, -90, -90, -90, -90, -90, -90, -90, -48, + -90, -90, -90, -90, -90, -90, -90, -90, -90, -90, + -90, -20, -90, -90, -90, -90, -90, 206, 205, -68, + -90, -90, 169, -1, 27, -7, 118, -66, -89, -90 +}; + +/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If + positive, shift that token. If negative, reduce the rule which + number is the opposite. If zero, do what YYDEFACT says. + If YYTABLE_NINF, syntax error. */ +#define YYTABLE_NINF -86 +static const yytype_int16 yytable[] = +{ + 10, 88, 89, 54, 146, 147, 119, 1, 122, 164, + 93, 141, 56, 142, 58, 156, 94, 62, 1, 90, + 91, 131, 65, 66, 144, 145, 67, 90, 91, 132, + 127, 68, 136, -31, 97, 2, 154, -31, -31, -31, + -31, -31, -31, -31, -31, 98, 52, -31, -31, 99, + -31, 100, 101, 102, 103, 104, -31, 105, 129, 106, + 138, 173, 92, 141, 107, 142, 174, 172, 8, 9, + 143, -33, 97, 90, 91, -33, -33, -33, -33, -33, + -33, -33, -33, 98, 166, -33, -33, 99, -33, 100, + 101, 102, 103, 104, -33, 105, 11, 106, 179, 151, + 123, 126, 107, 135, 125, 130, 2, 139, 2, 90, + 91, -5, 12, 55, 161, 13, 14, 15, 16, 17, + 18, 19, 20, 65, 66, 21, 22, 23, 24, 25, + 26, 27, 28, 29, 30, 57, 59, 31, 61, -4, + 12, 63, 32, 13, 14, 15, 16, 17, 18, 19, + 20, 64, 71, 21, 22, 23, 24, 25, 26, 27, + 28, 29, 30, 72, 73, 31, 180, 90, 91, 52, + 32, -85, 97, 82, 83, -85, -85, -85, -85, -85, + -85, -85, -85, 84, 190, -85, -85, 99, -85, -85, + -85, -85, -85, -85, -85, 85, 97, 106, 86, 87, + -52, -52, 140, -52, -52, -52, -52, 98, 95, -52, + -52, 99, 114, 115, 116, 117, 96, 148, 149, 150, + 158, 106, 155, 159, 97, 163, 118, -76, -76, -76, + -76, -76, -76, -76, -76, 160, 164, -76, -76, 99, + 13, 14, 15, 16, 17, 18, 19, 20, 91, 106, + 21, 22, 14, 15, 140, 17, 18, 19, 20, 168, + 175, 21, 22, 177, 181, 182, 183, 32, 187, 167, + 188, 169, 170, 171, 185, 189, 53, 51, 32, 176, + 75, 178, 121, 0, 133, 162, 0, 0, 0, 0, + 184 +}; + +static const yytype_int16 yycheck[] = +{ + 1, 67, 68, 10, 93, 94, 76, 3, 76, 14, + 28, 81, 13, 81, 15, 104, 34, 18, 3, 32, + 33, 23, 26, 27, 90, 91, 30, 32, 33, 31, + 78, 35, 80, 0, 1, 31, 102, 4, 5, 6, + 7, 8, 9, 10, 11, 12, 31, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, 78, 26, + 80, 26, 69, 133, 31, 133, 31, 156, 26, 27, + 29, 0, 1, 32, 33, 4, 5, 6, 7, 8, + 9, 10, 11, 12, 150, 14, 15, 16, 17, 18, + 19, 20, 21, 22, 23, 24, 0, 26, 164, 100, + 77, 78, 31, 80, 77, 78, 31, 80, 31, 32, + 33, 0, 1, 31, 115, 4, 5, 6, 7, 8, + 9, 10, 11, 26, 27, 14, 15, 16, 17, 18, + 19, 20, 21, 22, 23, 31, 26, 26, 31, 0, + 1, 26, 31, 4, 5, 6, 7, 8, 9, 10, + 11, 26, 31, 14, 15, 16, 17, 18, 19, 20, + 21, 22, 23, 1, 1, 26, 31, 32, 33, 31, + 31, 0, 1, 31, 31, 4, 5, 6, 7, 8, + 9, 10, 11, 31, 185, 14, 15, 16, 17, 18, + 19, 20, 21, 22, 23, 31, 1, 26, 31, 31, + 5, 6, 31, 8, 9, 10, 11, 12, 31, 14, + 15, 16, 17, 18, 19, 20, 31, 31, 31, 25, + 1, 26, 26, 13, 1, 26, 31, 4, 5, 6, + 7, 8, 9, 10, 11, 31, 14, 14, 15, 16, + 4, 5, 6, 7, 8, 9, 10, 11, 33, 26, + 14, 15, 5, 6, 31, 8, 9, 10, 11, 31, + 31, 14, 15, 31, 31, 31, 31, 31, 31, 151, + 31, 153, 154, 155, 34, 31, 7, 6, 31, 161, + 37, 163, 76, -1, 79, 116, -1, -1, -1, -1, + 172 +}; + +/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing + symbol of state STATE-NUM. */ +static const yytype_uint8 yystos[] = +{ + 0, 3, 31, 37, 38, 39, 63, 81, 26, 27, + 79, 0, 1, 4, 5, 6, 7, 8, 9, 10, + 11, 14, 15, 16, 17, 18, 19, 20, 21, 22, + 23, 26, 31, 40, 41, 43, 44, 45, 46, 52, + 53, 55, 59, 61, 64, 65, 67, 69, 70, 71, + 80, 39, 31, 38, 81, 31, 79, 31, 79, 26, + 85, 31, 79, 26, 26, 26, 27, 30, 35, 83, + 84, 31, 1, 1, 47, 47, 56, 58, 62, 76, + 68, 74, 31, 31, 31, 31, 31, 31, 83, 83, + 32, 33, 81, 28, 34, 31, 31, 1, 12, 16, + 18, 19, 20, 21, 22, 24, 26, 31, 42, 48, + 49, 72, 73, 75, 17, 18, 19, 20, 31, 42, + 57, 73, 75, 41, 54, 80, 41, 55, 60, 67, + 80, 23, 31, 74, 77, 41, 55, 66, 67, 80, + 31, 42, 75, 29, 83, 83, 84, 84, 31, 31, + 25, 79, 78, 79, 83, 26, 84, 50, 1, 13, + 31, 79, 78, 26, 14, 82, 83, 82, 31, 82, + 82, 82, 84, 26, 31, 31, 82, 31, 82, 83, + 31, 31, 31, 31, 82, 34, 51, 31, 31, 31, + 79 +}; + +#define yyerrok (yyerrstatus = 0) +#define yyclearin (yychar = YYEMPTY) +#define YYEMPTY (-2) +#define YYEOF 0 + +#define YYACCEPT goto yyacceptlab +#define YYABORT goto yyabortlab +#define YYERROR goto yyerrorlab + + +/* Like YYERROR except do call yyerror. This remains here temporarily + to ease the transition to the new meaning of YYERROR, for GCC. + Once GCC version 2 has supplanted version 1, this can go. However, + YYFAIL appears to be in use. Nevertheless, it is formally deprecated + in Bison 2.4.2's NEWS entry, where a plan to phase it out is + discussed. */ + +#define YYFAIL goto yyerrlab +#if defined YYFAIL + /* This is here to suppress warnings from the GCC cpp's + -Wunused-macros. Normally we don't worry about that warning, but + some users do, and we want to make it easy for users to remove + YYFAIL uses, which will produce warnings from Bison 2.5. */ +#endif + +#define YYRECOVERING() (!!yyerrstatus) + +#define YYBACKUP(Token, Value) \ +do \ + if (yychar == YYEMPTY && yylen == 1) \ + { \ + yychar = (Token); \ + yylval = (Value); \ + yytoken = YYTRANSLATE (yychar); \ + YYPOPSTACK (1); \ + goto yybackup; \ + } \ + else \ + { \ + yyerror (YY_("syntax error: cannot back up")); \ + YYERROR; \ + } \ +while (YYID (0)) + + +#define YYTERROR 1 +#define YYERRCODE 256 + + +/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. + If N is 0, then set CURRENT to the empty location which ends + the previous symbol: RHS[0] (always defined). */ + +#define YYRHSLOC(Rhs, K) ((Rhs)[K]) +#ifndef YYLLOC_DEFAULT +# define YYLLOC_DEFAULT(Current, Rhs, N) \ + do \ + if (YYID (N)) \ + { \ + (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ + (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ + (Current).last_line = YYRHSLOC (Rhs, N).last_line; \ + (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ + } \ + else \ + { \ + (Current).first_line = (Current).last_line = \ + YYRHSLOC (Rhs, 0).last_line; \ + (Current).first_column = (Current).last_column = \ + YYRHSLOC (Rhs, 0).last_column; \ + } \ + while (YYID (0)) +#endif + + +/* YY_LOCATION_PRINT -- Print the location on the stream. + This macro was not mandated originally: define only if we know + we won't break user code: when these are the locations we know. */ + +#ifndef YY_LOCATION_PRINT +# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL +# define YY_LOCATION_PRINT(File, Loc) \ + fprintf (File, "%d.%d-%d.%d", \ + (Loc).first_line, (Loc).first_column, \ + (Loc).last_line, (Loc).last_column) +# else +# define YY_LOCATION_PRINT(File, Loc) ((void) 0) +# endif +#endif + + +/* YYLEX -- calling `yylex' with the right arguments. */ + +#ifdef YYLEX_PARAM +# define YYLEX yylex (YYLEX_PARAM) +#else +# define YYLEX yylex () +#endif + +/* Enable debugging if requested. */ +#if YYDEBUG + +# ifndef YYFPRINTF +# include /* INFRINGES ON USER NAME SPACE */ +# define YYFPRINTF fprintf +# endif + +# define YYDPRINTF(Args) \ +do { \ + if (yydebug) \ + YYFPRINTF Args; \ +} while (YYID (0)) + +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ +do { \ + if (yydebug) \ + { \ + YYFPRINTF (stderr, "%s ", Title); \ + yy_symbol_print (stderr, \ + Type, Value); \ + YYFPRINTF (stderr, "\n"); \ + } \ +} while (YYID (0)) + + +/*--------------------------------. +| Print this symbol on YYOUTPUT. | +`--------------------------------*/ + +/*ARGSUSED*/ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) +#else +static void +yy_symbol_value_print (yyoutput, yytype, yyvaluep) + FILE *yyoutput; + int yytype; + YYSTYPE const * const yyvaluep; +#endif +{ + if (!yyvaluep) + return; +# ifdef YYPRINT + if (yytype < YYNTOKENS) + YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); +# else + YYUSE (yyoutput); +# endif + switch (yytype) + { + default: + break; + } +} + + +/*--------------------------------. +| Print this symbol on YYOUTPUT. | +`--------------------------------*/ + +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) +#else +static void +yy_symbol_print (yyoutput, yytype, yyvaluep) + FILE *yyoutput; + int yytype; + YYSTYPE const * const yyvaluep; +#endif +{ + if (yytype < YYNTOKENS) + YYFPRINTF (yyoutput, "token %s (", yytname[yytype]); + else + YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); + + yy_symbol_value_print (yyoutput, yytype, yyvaluep); + YYFPRINTF (yyoutput, ")"); +} + +/*------------------------------------------------------------------. +| yy_stack_print -- Print the state stack from its BOTTOM up to its | +| TOP (included). | +`------------------------------------------------------------------*/ + +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop) +#else +static void +yy_stack_print (yybottom, yytop) + yytype_int16 *yybottom; + yytype_int16 *yytop; +#endif +{ + YYFPRINTF (stderr, "Stack now"); + for (; yybottom <= yytop; yybottom++) + { + int yybot = *yybottom; + YYFPRINTF (stderr, " %d", yybot); + } + YYFPRINTF (stderr, "\n"); +} + +# define YY_STACK_PRINT(Bottom, Top) \ +do { \ + if (yydebug) \ + yy_stack_print ((Bottom), (Top)); \ +} while (YYID (0)) + + +/*------------------------------------------------. +| Report that the YYRULE is going to be reduced. | +`------------------------------------------------*/ + +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_reduce_print (YYSTYPE *yyvsp, int yyrule) +#else +static void +yy_reduce_print (yyvsp, yyrule) + YYSTYPE *yyvsp; + int yyrule; +#endif +{ + int yynrhs = yyr2[yyrule]; + int yyi; + unsigned long int yylno = yyrline[yyrule]; + YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n", + yyrule - 1, yylno); + /* The symbols being reduced. */ + for (yyi = 0; yyi < yynrhs; yyi++) + { + YYFPRINTF (stderr, " $%d = ", yyi + 1); + yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi], + &(yyvsp[(yyi + 1) - (yynrhs)]) + ); + YYFPRINTF (stderr, "\n"); + } +} + +# define YY_REDUCE_PRINT(Rule) \ +do { \ + if (yydebug) \ + yy_reduce_print (yyvsp, Rule); \ +} while (YYID (0)) + +/* Nonzero means print parse trace. It is left uninitialized so that + multiple parsers can coexist. */ +int yydebug; +#else /* !YYDEBUG */ +# define YYDPRINTF(Args) +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) +# define YY_STACK_PRINT(Bottom, Top) +# define YY_REDUCE_PRINT(Rule) +#endif /* !YYDEBUG */ + + +/* YYINITDEPTH -- initial size of the parser's stacks. */ +#ifndef YYINITDEPTH +# define YYINITDEPTH 200 +#endif + +/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only + if the built-in stack extension method is used). + + Do not make this value too large; the results are undefined if + YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) + evaluated with infinite-precision integer arithmetic. */ + +#ifndef YYMAXDEPTH +# define YYMAXDEPTH 10000 +#endif + + + +#if YYERROR_VERBOSE + +# ifndef yystrlen +# if defined __GLIBC__ && defined _STRING_H +# define yystrlen strlen +# else +/* Return the length of YYSTR. */ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static YYSIZE_T +yystrlen (const char *yystr) +#else +static YYSIZE_T +yystrlen (yystr) + const char *yystr; +#endif +{ + YYSIZE_T yylen; + for (yylen = 0; yystr[yylen]; yylen++) + continue; + return yylen; +} +# endif +# endif + +# ifndef yystpcpy +# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE +# define yystpcpy stpcpy +# else +/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in + YYDEST. */ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static char * +yystpcpy (char *yydest, const char *yysrc) +#else +static char * +yystpcpy (yydest, yysrc) + char *yydest; + const char *yysrc; +#endif +{ + char *yyd = yydest; + const char *yys = yysrc; + + while ((*yyd++ = *yys++) != '\0') + continue; + + return yyd - 1; +} +# endif +# endif + +# ifndef yytnamerr +/* Copy to YYRES the contents of YYSTR after stripping away unnecessary + quotes and backslashes, so that it's suitable for yyerror. The + heuristic is that double-quoting is unnecessary unless the string + contains an apostrophe, a comma, or backslash (other than + backslash-backslash). YYSTR is taken from yytname. If YYRES is + null, do not copy; instead, return the length of what the result + would have been. */ +static YYSIZE_T +yytnamerr (char *yyres, const char *yystr) +{ + if (*yystr == '"') + { + YYSIZE_T yyn = 0; + char const *yyp = yystr; + + for (;;) + switch (*++yyp) + { + case '\'': + case ',': + goto do_not_strip_quotes; + + case '\\': + if (*++yyp != '\\') + goto do_not_strip_quotes; + /* Fall through. */ + default: + if (yyres) + yyres[yyn] = *yyp; + yyn++; + break; + + case '"': + if (yyres) + yyres[yyn] = '\0'; + return yyn; + } + do_not_strip_quotes: ; + } + + if (! yyres) + return yystrlen (yystr); + + return yystpcpy (yyres, yystr) - yyres; +} +# endif + +/* Copy into YYRESULT an error message about the unexpected token + YYCHAR while in state YYSTATE. Return the number of bytes copied, + including the terminating null byte. If YYRESULT is null, do not + copy anything; just return the number of bytes that would be + copied. As a special case, return 0 if an ordinary "syntax error" + message will do. Return YYSIZE_MAXIMUM if overflow occurs during + size calculation. */ +static YYSIZE_T +yysyntax_error (char *yyresult, int yystate, int yychar) +{ + int yyn = yypact[yystate]; + + if (! (YYPACT_NINF < yyn && yyn <= YYLAST)) + return 0; + else + { + int yytype = YYTRANSLATE (yychar); + YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]); + YYSIZE_T yysize = yysize0; + YYSIZE_T yysize1; + int yysize_overflow = 0; + enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; + char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; + int yyx; + +# if 0 + /* This is so xgettext sees the translatable formats that are + constructed on the fly. */ + YY_("syntax error, unexpected %s"); + YY_("syntax error, unexpected %s, expecting %s"); + YY_("syntax error, unexpected %s, expecting %s or %s"); + YY_("syntax error, unexpected %s, expecting %s or %s or %s"); + YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"); +# endif + char *yyfmt; + char const *yyf; + static char const yyunexpected[] = "syntax error, unexpected %s"; + static char const yyexpecting[] = ", expecting %s"; + static char const yyor[] = " or %s"; + char yyformat[sizeof yyunexpected + + sizeof yyexpecting - 1 + + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2) + * (sizeof yyor - 1))]; + char const *yyprefix = yyexpecting; + + /* Start YYX at -YYN if negative to avoid negative indexes in + YYCHECK. */ + int yyxbegin = yyn < 0 ? -yyn : 0; + + /* Stay within bounds of both yycheck and yytname. */ + int yychecklim = YYLAST - yyn + 1; + int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; + int yycount = 1; + + yyarg[0] = yytname[yytype]; + yyfmt = yystpcpy (yyformat, yyunexpected); + + for (yyx = yyxbegin; yyx < yyxend; ++yyx) + if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) + { + if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) + { + yycount = 1; + yysize = yysize0; + yyformat[sizeof yyunexpected - 1] = '\0'; + break; + } + yyarg[yycount++] = yytname[yyx]; + yysize1 = yysize + yytnamerr (0, yytname[yyx]); + yysize_overflow |= (yysize1 < yysize); + yysize = yysize1; + yyfmt = yystpcpy (yyfmt, yyprefix); + yyprefix = yyor; + } + + yyf = YY_(yyformat); + yysize1 = yysize + yystrlen (yyf); + yysize_overflow |= (yysize1 < yysize); + yysize = yysize1; + + if (yysize_overflow) + return YYSIZE_MAXIMUM; + + if (yyresult) + { + /* Avoid sprintf, as that infringes on the user's name space. + Don't have undefined behavior even if the translation + produced a string with the wrong number of "%s"s. */ + char *yyp = yyresult; + int yyi = 0; + while ((*yyp = *yyf) != '\0') + { + if (*yyp == '%' && yyf[1] == 's' && yyi < yycount) + { + yyp += yytnamerr (yyp, yyarg[yyi++]); + yyf += 2; + } + else + { + yyp++; + yyf++; + } + } + } + return yysize; + } +} +#endif /* YYERROR_VERBOSE */ + + +/*-----------------------------------------------. +| Release the memory associated to this symbol. | +`-----------------------------------------------*/ + +/*ARGSUSED*/ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep) +#else +static void +yydestruct (yymsg, yytype, yyvaluep) + const char *yymsg; + int yytype; + YYSTYPE *yyvaluep; +#endif +{ + YYUSE (yyvaluep); + + if (!yymsg) + yymsg = "Deleting"; + YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); + + switch (yytype) + { + case 53: /* "choice_entry" */ + + { + fprintf(stderr, "%s:%d: missing end statement for this entry\n", + (yyvaluep->menu)->file->name, (yyvaluep->menu)->lineno); + if (current_menu == (yyvaluep->menu)) + menu_end_menu(); +}; + + break; + case 59: /* "if_entry" */ + + { + fprintf(stderr, "%s:%d: missing end statement for this entry\n", + (yyvaluep->menu)->file->name, (yyvaluep->menu)->lineno); + if (current_menu == (yyvaluep->menu)) + menu_end_menu(); +}; + + break; + case 65: /* "menu_entry" */ + + { + fprintf(stderr, "%s:%d: missing end statement for this entry\n", + (yyvaluep->menu)->file->name, (yyvaluep->menu)->lineno); + if (current_menu == (yyvaluep->menu)) + menu_end_menu(); +}; + + break; + + default: + break; + } +} + +/* Prevent warnings from -Wmissing-prototypes. */ +#ifdef YYPARSE_PARAM +#if defined __STDC__ || defined __cplusplus +int yyparse (void *YYPARSE_PARAM); +#else +int yyparse (); +#endif +#else /* ! YYPARSE_PARAM */ +#if defined __STDC__ || defined __cplusplus +int yyparse (void); +#else +int yyparse (); +#endif +#endif /* ! YYPARSE_PARAM */ + + +/* The lookahead symbol. */ +int yychar; + +/* The semantic value of the lookahead symbol. */ +YYSTYPE yylval; + +/* Number of syntax errors so far. */ +int yynerrs; + + + +/*-------------------------. +| yyparse or yypush_parse. | +`-------------------------*/ + +#ifdef YYPARSE_PARAM +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +int +yyparse (void *YYPARSE_PARAM) +#else +int +yyparse (YYPARSE_PARAM) + void *YYPARSE_PARAM; +#endif +#else /* ! YYPARSE_PARAM */ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +int +yyparse (void) +#else +int +yyparse () + +#endif +#endif +{ + + + int yystate; + /* Number of tokens to shift before error messages enabled. */ + int yyerrstatus; + + /* The stacks and their tools: + `yyss': related to states. + `yyvs': related to semantic values. + + Refer to the stacks thru separate pointers, to allow yyoverflow + to reallocate them elsewhere. */ + + /* The state stack. */ + yytype_int16 yyssa[YYINITDEPTH]; + yytype_int16 *yyss; + yytype_int16 *yyssp; + + /* The semantic value stack. */ + YYSTYPE yyvsa[YYINITDEPTH]; + YYSTYPE *yyvs; + YYSTYPE *yyvsp; + + YYSIZE_T yystacksize; + + int yyn; + int yyresult; + /* Lookahead token as an internal (translated) token number. */ + int yytoken; + /* The variables used to return semantic value and location from the + action routines. */ + YYSTYPE yyval; + +#if YYERROR_VERBOSE + /* Buffer for error messages, and its allocated size. */ + char yymsgbuf[128]; + char *yymsg = yymsgbuf; + YYSIZE_T yymsg_alloc = sizeof yymsgbuf; +#endif + +#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N)) + + /* The number of symbols on the RHS of the reduced rule. + Keep to zero when no symbol should be popped. */ + int yylen = 0; + + yytoken = 0; + yyss = yyssa; + yyvs = yyvsa; + yystacksize = YYINITDEPTH; + + YYDPRINTF ((stderr, "Starting parse\n")); + + yystate = 0; + yyerrstatus = 0; + yynerrs = 0; + yychar = YYEMPTY; /* Cause a token to be read. */ + + /* Initialize stack pointers. + Waste one element of value and location stack + so that they stay on the same level as the state stack. + The wasted elements are never initialized. */ + yyssp = yyss; + yyvsp = yyvs; + + goto yysetstate; + +/*------------------------------------------------------------. +| yynewstate -- Push a new state, which is found in yystate. | +`------------------------------------------------------------*/ + yynewstate: + /* In all cases, when you get here, the value and location stacks + have just been pushed. So pushing a state here evens the stacks. */ + yyssp++; + + yysetstate: + *yyssp = yystate; + + if (yyss + yystacksize - 1 <= yyssp) + { + /* Get the current used size of the three stacks, in elements. */ + YYSIZE_T yysize = yyssp - yyss + 1; + +#ifdef yyoverflow + { + /* Give user a chance to reallocate the stack. Use copies of + these so that the &'s don't force the real ones into + memory. */ + YYSTYPE *yyvs1 = yyvs; + yytype_int16 *yyss1 = yyss; + + /* Each stack pointer address is followed by the size of the + data in use in that stack, in bytes. This used to be a + conditional around just the two extra args, but that might + be undefined if yyoverflow is a macro. */ + yyoverflow (YY_("memory exhausted"), + &yyss1, yysize * sizeof (*yyssp), + &yyvs1, yysize * sizeof (*yyvsp), + &yystacksize); + + yyss = yyss1; + yyvs = yyvs1; + } +#else /* no yyoverflow */ +# ifndef YYSTACK_RELOCATE + goto yyexhaustedlab; +# else + /* Extend the stack our own way. */ + if (YYMAXDEPTH <= yystacksize) + goto yyexhaustedlab; + yystacksize *= 2; + if (YYMAXDEPTH < yystacksize) + yystacksize = YYMAXDEPTH; + + { + yytype_int16 *yyss1 = yyss; + union yyalloc *yyptr = + (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); + if (! yyptr) + goto yyexhaustedlab; + YYSTACK_RELOCATE (yyss_alloc, yyss); + YYSTACK_RELOCATE (yyvs_alloc, yyvs); +# undef YYSTACK_RELOCATE + if (yyss1 != yyssa) + YYSTACK_FREE (yyss1); + } +# endif +#endif /* no yyoverflow */ + + yyssp = yyss + yysize - 1; + yyvsp = yyvs + yysize - 1; + + YYDPRINTF ((stderr, "Stack size increased to %lu\n", + (unsigned long int) yystacksize)); + + if (yyss + yystacksize - 1 <= yyssp) + YYABORT; + } + + YYDPRINTF ((stderr, "Entering state %d\n", yystate)); + + if (yystate == YYFINAL) + YYACCEPT; + + goto yybackup; + +/*-----------. +| yybackup. | +`-----------*/ +yybackup: + + /* Do appropriate processing given the current state. Read a + lookahead token if we need one and don't already have one. */ + + /* First try to decide what to do without reference to lookahead token. */ + yyn = yypact[yystate]; + if (yyn == YYPACT_NINF) + goto yydefault; + + /* Not known => get a lookahead token if don't already have one. */ + + /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */ + if (yychar == YYEMPTY) + { + YYDPRINTF ((stderr, "Reading a token: ")); + yychar = YYLEX; + } + + if (yychar <= YYEOF) + { + yychar = yytoken = YYEOF; + YYDPRINTF ((stderr, "Now at end of input.\n")); + } + else + { + yytoken = YYTRANSLATE (yychar); + YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); + } + + /* If the proper action on seeing token YYTOKEN is to reduce or to + detect an error, take that action. */ + yyn += yytoken; + if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) + goto yydefault; + yyn = yytable[yyn]; + if (yyn <= 0) + { + if (yyn == 0 || yyn == YYTABLE_NINF) + goto yyerrlab; + yyn = -yyn; + goto yyreduce; + } + + /* Count tokens shifted since error; after three, turn off error + status. */ + if (yyerrstatus) + yyerrstatus--; + + /* Shift the lookahead token. */ + YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); + + /* Discard the shifted token. */ + yychar = YYEMPTY; + + yystate = yyn; + *++yyvsp = yylval; + + goto yynewstate; + + +/*-----------------------------------------------------------. +| yydefault -- do the default action for the current state. | +`-----------------------------------------------------------*/ +yydefault: + yyn = yydefact[yystate]; + if (yyn == 0) + goto yyerrlab; + goto yyreduce; + + +/*-----------------------------. +| yyreduce -- Do a reduction. | +`-----------------------------*/ +yyreduce: + /* yyn is the number of a rule to reduce with. */ + yylen = yyr2[yyn]; + + /* If YYLEN is nonzero, implement the default value of the action: + `$$ = $1'. + + Otherwise, the following line sets YYVAL to garbage. + This behavior is undocumented and Bison + users should not rely upon it. Assigning to YYVAL + unconditionally makes the parser a bit smaller, and it avoids a + GCC warning that YYVAL may be used uninitialized. */ + yyval = yyvsp[1-yylen]; + + + YY_REDUCE_PRINT (yyn); + switch (yyn) + { + case 10: + + { zconf_error("unexpected end statement"); ;} + break; + + case 11: + + { zconf_error("unknown statement \"%s\"", (yyvsp[(2) - (4)].string)); ;} + break; + + case 12: + + { + zconf_error("unexpected option \"%s\"", kconf_id_strings + (yyvsp[(2) - (4)].id)->name); +;} + break; + + case 13: + + { zconf_error("invalid statement"); ;} + break; + + case 28: + + { zconf_error("unknown option \"%s\"", (yyvsp[(1) - (3)].string)); ;} + break; + + case 29: + + { zconf_error("invalid option"); ;} + break; + + case 30: + + { + struct symbol *sym = sym_lookup((yyvsp[(2) - (3)].string), 0); + sym->flags |= SYMBOL_OPTIONAL; + menu_add_entry(sym); + printd(DEBUG_PARSE, "%s:%d:config %s\n", zconf_curname(), zconf_lineno(), (yyvsp[(2) - (3)].string)); +;} + break; + + case 31: + + { + menu_end_entry(); + printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno()); +;} + break; + + case 32: + + { + struct symbol *sym = sym_lookup((yyvsp[(2) - (3)].string), 0); + sym->flags |= SYMBOL_OPTIONAL; + menu_add_entry(sym); + printd(DEBUG_PARSE, "%s:%d:menuconfig %s\n", zconf_curname(), zconf_lineno(), (yyvsp[(2) - (3)].string)); +;} + break; + + case 33: + + { + if (current_entry->prompt) + current_entry->prompt->type = P_MENU; + else + zconfprint("warning: menuconfig statement without prompt"); + menu_end_entry(); + printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno()); +;} + break; + + case 41: + + { + menu_set_type((yyvsp[(1) - (3)].id)->stype); + printd(DEBUG_PARSE, "%s:%d:type(%u)\n", + zconf_curname(), zconf_lineno(), + (yyvsp[(1) - (3)].id)->stype); +;} + break; + + case 42: + + { + menu_add_prompt(P_PROMPT, (yyvsp[(2) - (4)].string), (yyvsp[(3) - (4)].expr)); + printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno()); +;} + break; + + case 43: + + { + menu_add_expr(P_DEFAULT, (yyvsp[(2) - (4)].expr), (yyvsp[(3) - (4)].expr)); + if ((yyvsp[(1) - (4)].id)->stype != S_UNKNOWN) + menu_set_type((yyvsp[(1) - (4)].id)->stype); + printd(DEBUG_PARSE, "%s:%d:default(%u)\n", + zconf_curname(), zconf_lineno(), + (yyvsp[(1) - (4)].id)->stype); +;} + break; + + case 44: + + { + menu_add_symbol(P_SELECT, sym_lookup((yyvsp[(2) - (4)].string), 0), (yyvsp[(3) - (4)].expr)); + printd(DEBUG_PARSE, "%s:%d:select\n", zconf_curname(), zconf_lineno()); +;} + break; + + case 45: + + { + menu_add_expr(P_RANGE, expr_alloc_comp(E_RANGE,(yyvsp[(2) - (5)].symbol), (yyvsp[(3) - (5)].symbol)), (yyvsp[(4) - (5)].expr)); + printd(DEBUG_PARSE, "%s:%d:range\n", zconf_curname(), zconf_lineno()); +;} + break; + + case 48: + + { + const struct kconf_id *id = kconf_id_lookup((yyvsp[(2) - (3)].string), strlen((yyvsp[(2) - (3)].string))); + if (id && id->flags & TF_OPTION) + menu_add_option(id->token, (yyvsp[(3) - (3)].string)); + else + zconfprint("warning: ignoring unknown option %s", (yyvsp[(2) - (3)].string)); + free((yyvsp[(2) - (3)].string)); +;} + break; + + case 49: + + { (yyval.string) = NULL; ;} + break; + + case 50: + + { (yyval.string) = (yyvsp[(2) - (2)].string); ;} + break; + + case 51: + + { + struct symbol *sym = sym_lookup((yyvsp[(2) - (3)].string), SYMBOL_CHOICE); + sym->flags |= SYMBOL_AUTO; + menu_add_entry(sym); + menu_add_expr(P_CHOICE, NULL, NULL); + printd(DEBUG_PARSE, "%s:%d:choice\n", zconf_curname(), zconf_lineno()); +;} + break; + + case 52: + + { + (yyval.menu) = menu_add_menu(); +;} + break; + + case 53: + + { + if (zconf_endtoken((yyvsp[(1) - (1)].id), T_CHOICE, T_ENDCHOICE)) { + menu_end_menu(); + printd(DEBUG_PARSE, "%s:%d:endchoice\n", zconf_curname(), zconf_lineno()); + } +;} + break; + + case 61: + + { + menu_add_prompt(P_PROMPT, (yyvsp[(2) - (4)].string), (yyvsp[(3) - (4)].expr)); + printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno()); +;} + break; + + case 62: + + { + if ((yyvsp[(1) - (3)].id)->stype == S_BOOLEAN || (yyvsp[(1) - (3)].id)->stype == S_TRISTATE) { + menu_set_type((yyvsp[(1) - (3)].id)->stype); + printd(DEBUG_PARSE, "%s:%d:type(%u)\n", + zconf_curname(), zconf_lineno(), + (yyvsp[(1) - (3)].id)->stype); + } else + YYERROR; +;} + break; + + case 63: + + { + current_entry->sym->flags |= SYMBOL_OPTIONAL; + printd(DEBUG_PARSE, "%s:%d:optional\n", zconf_curname(), zconf_lineno()); +;} + break; + + case 64: + + { + if ((yyvsp[(1) - (4)].id)->stype == S_UNKNOWN) { + menu_add_symbol(P_DEFAULT, sym_lookup((yyvsp[(2) - (4)].string), 0), (yyvsp[(3) - (4)].expr)); + printd(DEBUG_PARSE, "%s:%d:default\n", + zconf_curname(), zconf_lineno()); + } else + YYERROR; +;} + break; + + case 67: + + { + printd(DEBUG_PARSE, "%s:%d:if\n", zconf_curname(), zconf_lineno()); + menu_add_entry(NULL); + menu_add_dep((yyvsp[(2) - (3)].expr)); + (yyval.menu) = menu_add_menu(); +;} + break; + + case 68: + + { + if (zconf_endtoken((yyvsp[(1) - (1)].id), T_IF, T_ENDIF)) { + menu_end_menu(); + printd(DEBUG_PARSE, "%s:%d:endif\n", zconf_curname(), zconf_lineno()); + } +;} + break; + + case 74: + + { + menu_add_prompt(P_MENU, (yyvsp[(2) - (3)].string), NULL); +;} + break; + + case 75: + + { + menu_add_entry(NULL); + menu_add_prompt(P_MENU, (yyvsp[(2) - (3)].string), NULL); + printd(DEBUG_PARSE, "%s:%d:menu\n", zconf_curname(), zconf_lineno()); +;} + break; + + case 76: + + { + (yyval.menu) = menu_add_menu(); +;} + break; + + case 77: + + { + if (zconf_endtoken((yyvsp[(1) - (1)].id), T_MENU, T_ENDMENU)) { + menu_end_menu(); + printd(DEBUG_PARSE, "%s:%d:endmenu\n", zconf_curname(), zconf_lineno()); + } +;} + break; + + case 83: + + { + printd(DEBUG_PARSE, "%s:%d:source %s\n", zconf_curname(), zconf_lineno(), (yyvsp[(2) - (3)].string)); + zconf_nextfile((yyvsp[(2) - (3)].string)); +;} + break; + + case 84: + + { + menu_add_entry(NULL); + menu_add_prompt(P_COMMENT, (yyvsp[(2) - (3)].string), NULL); + printd(DEBUG_PARSE, "%s:%d:comment\n", zconf_curname(), zconf_lineno()); +;} + break; + + case 85: + + { + menu_end_entry(); +;} + break; + + case 86: + + { + printd(DEBUG_PARSE, "%s:%d:help\n", zconf_curname(), zconf_lineno()); + zconf_starthelp(); +;} + break; + + case 87: + + { + current_entry->help = (yyvsp[(2) - (2)].string); +;} + break; + + case 92: + + { + menu_add_dep((yyvsp[(3) - (4)].expr)); + printd(DEBUG_PARSE, "%s:%d:depends on\n", zconf_curname(), zconf_lineno()); +;} + break; + + case 96: + + { + menu_add_visibility((yyvsp[(2) - (2)].expr)); +;} + break; + + case 98: + + { + menu_add_prompt(P_PROMPT, (yyvsp[(1) - (2)].string), (yyvsp[(2) - (2)].expr)); +;} + break; + + case 101: + + { (yyval.id) = (yyvsp[(1) - (2)].id); ;} + break; + + case 102: + + { (yyval.id) = (yyvsp[(1) - (2)].id); ;} + break; + + case 103: + + { (yyval.id) = (yyvsp[(1) - (2)].id); ;} + break; + + case 106: + + { (yyval.expr) = NULL; ;} + break; + + case 107: + + { (yyval.expr) = (yyvsp[(2) - (2)].expr); ;} + break; + + case 108: + + { (yyval.expr) = expr_alloc_symbol((yyvsp[(1) - (1)].symbol)); ;} + break; + + case 109: + + { (yyval.expr) = expr_alloc_comp(E_EQUAL, (yyvsp[(1) - (3)].symbol), (yyvsp[(3) - (3)].symbol)); ;} + break; + + case 110: + + { (yyval.expr) = expr_alloc_comp(E_UNEQUAL, (yyvsp[(1) - (3)].symbol), (yyvsp[(3) - (3)].symbol)); ;} + break; + + case 111: + + { (yyval.expr) = (yyvsp[(2) - (3)].expr); ;} + break; + + case 112: + + { (yyval.expr) = expr_alloc_one(E_NOT, (yyvsp[(2) - (2)].expr)); ;} + break; + + case 113: + + { (yyval.expr) = expr_alloc_two(E_OR, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;} + break; + + case 114: + + { (yyval.expr) = expr_alloc_two(E_AND, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;} + break; + + case 115: + + { (yyval.symbol) = sym_lookup((yyvsp[(1) - (1)].string), 0); free((yyvsp[(1) - (1)].string)); ;} + break; + + case 116: + + { (yyval.symbol) = sym_lookup((yyvsp[(1) - (1)].string), SYMBOL_CONST); free((yyvsp[(1) - (1)].string)); ;} + break; + + case 117: + + { (yyval.string) = NULL; ;} + break; + + + + default: break; + } + YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); + + YYPOPSTACK (yylen); + yylen = 0; + YY_STACK_PRINT (yyss, yyssp); + + *++yyvsp = yyval; + + /* Now `shift' the result of the reduction. Determine what state + that goes to, based on the state we popped back to and the rule + number reduced by. */ + + yyn = yyr1[yyn]; + + yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; + if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) + yystate = yytable[yystate]; + else + yystate = yydefgoto[yyn - YYNTOKENS]; + + goto yynewstate; + + +/*------------------------------------. +| yyerrlab -- here on detecting error | +`------------------------------------*/ +yyerrlab: + /* If not already recovering from an error, report this error. */ + if (!yyerrstatus) + { + ++yynerrs; +#if ! YYERROR_VERBOSE + yyerror (YY_("syntax error")); +#else + { + YYSIZE_T yysize = yysyntax_error (0, yystate, yychar); + if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM) + { + YYSIZE_T yyalloc = 2 * yysize; + if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM)) + yyalloc = YYSTACK_ALLOC_MAXIMUM; + if (yymsg != yymsgbuf) + YYSTACK_FREE (yymsg); + yymsg = (char *) YYSTACK_ALLOC (yyalloc); + if (yymsg) + yymsg_alloc = yyalloc; + else + { + yymsg = yymsgbuf; + yymsg_alloc = sizeof yymsgbuf; + } + } + + if (0 < yysize && yysize <= yymsg_alloc) + { + (void) yysyntax_error (yymsg, yystate, yychar); + yyerror (yymsg); + } + else + { + yyerror (YY_("syntax error")); + if (yysize != 0) + goto yyexhaustedlab; + } + } +#endif + } + + + + if (yyerrstatus == 3) + { + /* If just tried and failed to reuse lookahead token after an + error, discard it. */ + + if (yychar <= YYEOF) + { + /* Return failure if at end of input. */ + if (yychar == YYEOF) + YYABORT; + } + else + { + yydestruct ("Error: discarding", + yytoken, &yylval); + yychar = YYEMPTY; + } + } + + /* Else will try to reuse lookahead token after shifting the error + token. */ + goto yyerrlab1; + + +/*---------------------------------------------------. +| yyerrorlab -- error raised explicitly by YYERROR. | +`---------------------------------------------------*/ +yyerrorlab: + + /* Pacify compilers like GCC when the user code never invokes + YYERROR and the label yyerrorlab therefore never appears in user + code. */ + if (/*CONSTCOND*/ 0) + goto yyerrorlab; + + /* Do not reclaim the symbols of the rule which action triggered + this YYERROR. */ + YYPOPSTACK (yylen); + yylen = 0; + YY_STACK_PRINT (yyss, yyssp); + yystate = *yyssp; + goto yyerrlab1; + + +/*-------------------------------------------------------------. +| yyerrlab1 -- common code for both syntax error and YYERROR. | +`-------------------------------------------------------------*/ +yyerrlab1: + yyerrstatus = 3; /* Each real token shifted decrements this. */ + + for (;;) + { + yyn = yypact[yystate]; + if (yyn != YYPACT_NINF) + { + yyn += YYTERROR; + if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) + { + yyn = yytable[yyn]; + if (0 < yyn) + break; + } + } + + /* Pop the current state because it cannot handle the error token. */ + if (yyssp == yyss) + YYABORT; + + + yydestruct ("Error: popping", + yystos[yystate], yyvsp); + YYPOPSTACK (1); + yystate = *yyssp; + YY_STACK_PRINT (yyss, yyssp); + } + + *++yyvsp = yylval; + + + /* Shift the error token. */ + YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp); + + yystate = yyn; + goto yynewstate; + + +/*-------------------------------------. +| yyacceptlab -- YYACCEPT comes here. | +`-------------------------------------*/ +yyacceptlab: + yyresult = 0; + goto yyreturn; + +/*-----------------------------------. +| yyabortlab -- YYABORT comes here. | +`-----------------------------------*/ +yyabortlab: + yyresult = 1; + goto yyreturn; + +#if !defined(yyoverflow) || YYERROR_VERBOSE +/*-------------------------------------------------. +| yyexhaustedlab -- memory exhaustion comes here. | +`-------------------------------------------------*/ +yyexhaustedlab: + yyerror (YY_("memory exhausted")); + yyresult = 2; + /* Fall through. */ +#endif + +yyreturn: + if (yychar != YYEMPTY) + yydestruct ("Cleanup: discarding lookahead", + yytoken, &yylval); + /* Do not reclaim the symbols of the rule which action triggered + this YYABORT or YYACCEPT. */ + YYPOPSTACK (yylen); + YY_STACK_PRINT (yyss, yyssp); + while (yyssp != yyss) + { + yydestruct ("Cleanup: popping", + yystos[*yyssp], yyvsp); + YYPOPSTACK (1); + } +#ifndef yyoverflow + if (yyss != yyssa) + YYSTACK_FREE (yyss); +#endif +#if YYERROR_VERBOSE + if (yymsg != yymsgbuf) + YYSTACK_FREE (yymsg); +#endif + /* Make sure YYID is used. */ + return YYID (yyresult); +} + + + + + +void conf_parse(const char *name) +{ + struct symbol *sym; + int i; + + zconf_initscan(name); + + sym_init(); + _menu_init(); + modules_sym = sym_lookup(NULL, 0); + modules_sym->type = S_BOOLEAN; + modules_sym->flags |= SYMBOL_AUTO; + rootmenu.prompt = menu_add_prompt(P_MENU, "Fiasco Kernel Configuration", NULL); + + if (getenv("ZCONF_DEBUG")) + zconfdebug = 1; + zconfparse(); + if (zconfnerrs) + exit(1); + if (!modules_sym->prop) { + struct property *prop; + + prop = prop_alloc(P_DEFAULT, modules_sym); + prop->expr = expr_alloc_symbol(sym_lookup("MODULES", 0)); + } + + rootmenu.prompt->text = _(rootmenu.prompt->text); + rootmenu.prompt->text = sym_expand_string_value(rootmenu.prompt->text); + + menu_finalize(&rootmenu); + for_all_symbols(i, sym) { + if (sym_check_deps(sym)) + zconfnerrs++; + } + if (zconfnerrs) + exit(1); + sym_set_change_count(1); +} + +static const char *zconf_tokenname(int token) +{ + switch (token) { + case T_MENU: return "menu"; + case T_ENDMENU: return "endmenu"; + case T_CHOICE: return "choice"; + case T_ENDCHOICE: return "endchoice"; + case T_IF: return "if"; + case T_ENDIF: return "endif"; + case T_DEPENDS: return "depends"; + case T_VISIBLE: return "visible"; + } + return ""; +} + +static bool zconf_endtoken(const struct kconf_id *id, int starttoken, int endtoken) +{ + if (id->token != endtoken) { + zconf_error("unexpected '%s' within %s block", + kconf_id_strings + id->name, zconf_tokenname(starttoken)); + zconfnerrs++; + return false; + } + if (current_menu->file != current_file) { + zconf_error("'%s' in different file than '%s'", + kconf_id_strings + id->name, zconf_tokenname(starttoken)); + fprintf(stderr, "%s:%d: location of the '%s'\n", + current_menu->file->name, current_menu->lineno, + zconf_tokenname(starttoken)); + zconfnerrs++; + return false; + } + return true; +} + +static void zconfprint(const char *err, ...) +{ + va_list ap; + + fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno()); + va_start(ap, err); + vfprintf(stderr, err, ap); + va_end(ap); + fprintf(stderr, "\n"); +} + +static void zconf_error(const char *err, ...) +{ + va_list ap; + + zconfnerrs++; + fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno()); + va_start(ap, err); + vfprintf(stderr, err, ap); + va_end(ap); + fprintf(stderr, "\n"); +} + +static void zconferror(const char *err) +{ + fprintf(stderr, "%s:%d: %s\n", zconf_curname(), zconf_lineno() + 1, err); +} + +static void print_quoted_string(FILE *out, const char *str) +{ + const char *p; + int len; + + putc('"', out); + while ((p = strchr(str, '"'))) { + len = p - str; + if (len) + fprintf(out, "%.*s", len, str); + fputs("\\\"", out); + str = p + 1; + } + fputs(str, out); + putc('"', out); +} + +static void print_symbol(FILE *out, struct menu *menu) +{ + struct symbol *sym = menu->sym; + struct property *prop; + + if (sym_is_choice(sym)) + fprintf(out, "\nchoice\n"); + else + fprintf(out, "\nconfig %s\n", sym->name); + switch (sym->type) { + case S_BOOLEAN: + fputs(" boolean\n", out); + break; + case S_TRISTATE: + fputs(" tristate\n", out); + break; + case S_STRING: + fputs(" string\n", out); + break; + case S_INT: + fputs(" integer\n", out); + break; + case S_HEX: + fputs(" hex\n", out); + break; + default: + fputs(" ???\n", out); + break; + } + for (prop = sym->prop; prop; prop = prop->next) { + if (prop->menu != menu) + continue; + switch (prop->type) { + case P_PROMPT: + fputs(" prompt ", out); + print_quoted_string(out, prop->text); + if (!expr_is_yes(prop->visible.expr)) { + fputs(" if ", out); + expr_fprint(prop->visible.expr, out); + } + fputc('\n', out); + break; + case P_DEFAULT: + fputs( " default ", out); + expr_fprint(prop->expr, out); + if (!expr_is_yes(prop->visible.expr)) { + fputs(" if ", out); + expr_fprint(prop->visible.expr, out); + } + fputc('\n', out); + break; + case P_CHOICE: + fputs(" #choice value\n", out); + break; + case P_SELECT: + fputs( " select ", out); + expr_fprint(prop->expr, out); + fputc('\n', out); + break; + case P_RANGE: + fputs( " range ", out); + expr_fprint(prop->expr, out); + fputc('\n', out); + break; + case P_MENU: + fputs( " menu ", out); + print_quoted_string(out, prop->text); + fputc('\n', out); + break; + default: + fprintf(out, " unknown prop %d!\n", prop->type); + break; + } + } + if (menu->help) { + int len = strlen(menu->help); + while (menu->help[--len] == '\n') + menu->help[len] = 0; + fprintf(out, " help\n%s\n", menu->help); + } +} + +void zconfdump(FILE *out) +{ + struct property *prop; + struct symbol *sym; + struct menu *menu; + + menu = rootmenu.list; + while (menu) { + if ((sym = menu->sym)) + print_symbol(out, menu); + else if ((prop = menu->prompt)) { + switch (prop->type) { + case P_COMMENT: + fputs("\ncomment ", out); + print_quoted_string(out, prop->text); + fputs("\n", out); + break; + case P_MENU: + fputs("\nmenu ", out); + print_quoted_string(out, prop->text); + fputs("\n", out); + break; + default: + ; + } + if (!expr_is_yes(prop->visible.expr)) { + fputs(" depends ", out); + expr_fprint(prop->visible.expr, out); + fputc('\n', out); + } + } + + if (menu->list) + menu = menu->list; + else if (menu->next) + menu = menu->next; + else while ((menu = menu->parent)) { + if (menu->prompt && menu->prompt->type == P_MENU) + fputs("\nendmenu\n", out); + if (menu->next) { + menu = menu->next; + break; + } + } + } +} + +#include "zconf.lex.c" +#include "util.c" +#include "confdata.c" +#include "expr.c" +#include "symbol.c" +#include "menu.c" + diff --git a/kernel/fiasco/tool/kconfig/scripts/kconfig/zconf.y b/kernel/fiasco/tool/kconfig/scripts/kconfig/zconf.y new file mode 100644 index 00000000..864da07b --- /dev/null +++ b/kernel/fiasco/tool/kconfig/scripts/kconfig/zconf.y @@ -0,0 +1,740 @@ +%{ +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +#include +#include +#include +#include +#include +#include + +#include "lkc.h" + +#define printd(mask, fmt...) if (cdebug & (mask)) printf(fmt) + +#define PRINTD 0x0001 +#define DEBUG_PARSE 0x0002 + +int cdebug = PRINTD; + +extern int zconflex(void); +static void zconfprint(const char *err, ...); +static void zconf_error(const char *err, ...); +static void zconferror(const char *err); +static bool zconf_endtoken(const struct kconf_id *id, int starttoken, int endtoken); + +struct symbol *symbol_hash[SYMBOL_HASHSIZE]; + +static struct menu *current_menu, *current_entry; + +%} +%expect 30 + +%union +{ + char *string; + struct file *file; + struct symbol *symbol; + struct expr *expr; + struct menu *menu; + const struct kconf_id *id; +} + +%token T_MAINMENU +%token T_MENU +%token T_ENDMENU +%token T_SOURCE +%token T_CHOICE +%token T_ENDCHOICE +%token T_COMMENT +%token T_CONFIG +%token T_MENUCONFIG +%token T_HELP +%token T_HELPTEXT +%token T_IF +%token T_ENDIF +%token T_DEPENDS +%token T_OPTIONAL +%token T_PROMPT +%token T_TYPE +%token T_DEFAULT +%token T_SELECT +%token T_RANGE +%token T_VISIBLE +%token T_OPTION +%token T_ON +%token T_WORD +%token T_WORD_QUOTE +%token T_UNEQUAL +%token T_CLOSE_PAREN +%token T_OPEN_PAREN +%token T_EOL + +%left T_OR +%left T_AND +%left T_EQUAL T_UNEQUAL +%nonassoc T_NOT + +%type prompt +%type symbol +%type expr +%type if_expr +%type end +%type option_name +%type if_entry menu_entry choice_entry +%type symbol_option_arg word_opt + +%destructor { + fprintf(stderr, "%s:%d: missing end statement for this entry\n", + $$->file->name, $$->lineno); + if (current_menu == $$) + menu_end_menu(); +} if_entry menu_entry choice_entry + +%{ +/* Include zconf.hash.c here so it can see the token constants. */ +#include "zconf.hash.c" +%} + +%% +input: nl start | start; + +start: mainmenu_stmt stmt_list | stmt_list; + +stmt_list: + /* empty */ + | stmt_list common_stmt + | stmt_list choice_stmt + | stmt_list menu_stmt + | stmt_list end { zconf_error("unexpected end statement"); } + | stmt_list T_WORD error T_EOL { zconf_error("unknown statement \"%s\"", $2); } + | stmt_list option_name error T_EOL +{ + zconf_error("unexpected option \"%s\"", kconf_id_strings + $2->name); +} + | stmt_list error T_EOL { zconf_error("invalid statement"); } +; + +option_name: + T_DEPENDS | T_PROMPT | T_TYPE | T_SELECT | T_OPTIONAL | T_RANGE | T_DEFAULT | T_VISIBLE +; + +common_stmt: + T_EOL + | if_stmt + | comment_stmt + | config_stmt + | menuconfig_stmt + | source_stmt +; + +option_error: + T_WORD error T_EOL { zconf_error("unknown option \"%s\"", $1); } + | error T_EOL { zconf_error("invalid option"); } +; + + +/* config/menuconfig entry */ + +config_entry_start: T_CONFIG T_WORD T_EOL +{ + struct symbol *sym = sym_lookup($2, 0); + sym->flags |= SYMBOL_OPTIONAL; + menu_add_entry(sym); + printd(DEBUG_PARSE, "%s:%d:config %s\n", zconf_curname(), zconf_lineno(), $2); +}; + +config_stmt: config_entry_start config_option_list +{ + menu_end_entry(); + printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno()); +}; + +menuconfig_entry_start: T_MENUCONFIG T_WORD T_EOL +{ + struct symbol *sym = sym_lookup($2, 0); + sym->flags |= SYMBOL_OPTIONAL; + menu_add_entry(sym); + printd(DEBUG_PARSE, "%s:%d:menuconfig %s\n", zconf_curname(), zconf_lineno(), $2); +}; + +menuconfig_stmt: menuconfig_entry_start config_option_list +{ + if (current_entry->prompt) + current_entry->prompt->type = P_MENU; + else + zconfprint("warning: menuconfig statement without prompt"); + menu_end_entry(); + printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno()); +}; + +config_option_list: + /* empty */ + | config_option_list config_option + | config_option_list symbol_option + | config_option_list depends + | config_option_list help + | config_option_list option_error + | config_option_list T_EOL +; + +config_option: T_TYPE prompt_stmt_opt T_EOL +{ + menu_set_type($1->stype); + printd(DEBUG_PARSE, "%s:%d:type(%u)\n", + zconf_curname(), zconf_lineno(), + $1->stype); +}; + +config_option: T_PROMPT prompt if_expr T_EOL +{ + menu_add_prompt(P_PROMPT, $2, $3); + printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno()); +}; + +config_option: T_DEFAULT expr if_expr T_EOL +{ + menu_add_expr(P_DEFAULT, $2, $3); + if ($1->stype != S_UNKNOWN) + menu_set_type($1->stype); + printd(DEBUG_PARSE, "%s:%d:default(%u)\n", + zconf_curname(), zconf_lineno(), + $1->stype); +}; + +config_option: T_SELECT T_WORD if_expr T_EOL +{ + menu_add_symbol(P_SELECT, sym_lookup($2, 0), $3); + printd(DEBUG_PARSE, "%s:%d:select\n", zconf_curname(), zconf_lineno()); +}; + +config_option: T_RANGE symbol symbol if_expr T_EOL +{ + menu_add_expr(P_RANGE, expr_alloc_comp(E_RANGE,$2, $3), $4); + printd(DEBUG_PARSE, "%s:%d:range\n", zconf_curname(), zconf_lineno()); +}; + +symbol_option: T_OPTION symbol_option_list T_EOL +; + +symbol_option_list: + /* empty */ + | symbol_option_list T_WORD symbol_option_arg +{ + const struct kconf_id *id = kconf_id_lookup($2, strlen($2)); + if (id && id->flags & TF_OPTION) + menu_add_option(id->token, $3); + else + zconfprint("warning: ignoring unknown option %s", $2); + free($2); +}; + +symbol_option_arg: + /* empty */ { $$ = NULL; } + | T_EQUAL prompt { $$ = $2; } +; + +/* choice entry */ + +choice: T_CHOICE word_opt T_EOL +{ + struct symbol *sym = sym_lookup($2, SYMBOL_CHOICE); + sym->flags |= SYMBOL_AUTO; + menu_add_entry(sym); + menu_add_expr(P_CHOICE, NULL, NULL); + printd(DEBUG_PARSE, "%s:%d:choice\n", zconf_curname(), zconf_lineno()); +}; + +choice_entry: choice choice_option_list +{ + $$ = menu_add_menu(); +}; + +choice_end: end +{ + if (zconf_endtoken($1, T_CHOICE, T_ENDCHOICE)) { + menu_end_menu(); + printd(DEBUG_PARSE, "%s:%d:endchoice\n", zconf_curname(), zconf_lineno()); + } +}; + +choice_stmt: choice_entry choice_block choice_end +; + +choice_option_list: + /* empty */ + | choice_option_list choice_option + | choice_option_list depends + | choice_option_list help + | choice_option_list T_EOL + | choice_option_list option_error +; + +choice_option: T_PROMPT prompt if_expr T_EOL +{ + menu_add_prompt(P_PROMPT, $2, $3); + printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno()); +}; + +choice_option: T_TYPE prompt_stmt_opt T_EOL +{ + if ($1->stype == S_BOOLEAN || $1->stype == S_TRISTATE) { + menu_set_type($1->stype); + printd(DEBUG_PARSE, "%s:%d:type(%u)\n", + zconf_curname(), zconf_lineno(), + $1->stype); + } else + YYERROR; +}; + +choice_option: T_OPTIONAL T_EOL +{ + current_entry->sym->flags |= SYMBOL_OPTIONAL; + printd(DEBUG_PARSE, "%s:%d:optional\n", zconf_curname(), zconf_lineno()); +}; + +choice_option: T_DEFAULT T_WORD if_expr T_EOL +{ + if ($1->stype == S_UNKNOWN) { + menu_add_symbol(P_DEFAULT, sym_lookup($2, 0), $3); + printd(DEBUG_PARSE, "%s:%d:default\n", + zconf_curname(), zconf_lineno()); + } else + YYERROR; +}; + +choice_block: + /* empty */ + | choice_block common_stmt +; + +/* if entry */ + +if_entry: T_IF expr nl +{ + printd(DEBUG_PARSE, "%s:%d:if\n", zconf_curname(), zconf_lineno()); + menu_add_entry(NULL); + menu_add_dep($2); + $$ = menu_add_menu(); +}; + +if_end: end +{ + if (zconf_endtoken($1, T_IF, T_ENDIF)) { + menu_end_menu(); + printd(DEBUG_PARSE, "%s:%d:endif\n", zconf_curname(), zconf_lineno()); + } +}; + +if_stmt: if_entry if_block if_end +; + +if_block: + /* empty */ + | if_block common_stmt + | if_block menu_stmt + | if_block choice_stmt +; + +/* mainmenu entry */ + +mainmenu_stmt: T_MAINMENU prompt nl +{ + menu_add_prompt(P_MENU, $2, NULL); +}; + +/* menu entry */ + +menu: T_MENU prompt T_EOL +{ + menu_add_entry(NULL); + menu_add_prompt(P_MENU, $2, NULL); + printd(DEBUG_PARSE, "%s:%d:menu\n", zconf_curname(), zconf_lineno()); +}; + +menu_entry: menu visibility_list depends_list +{ + $$ = menu_add_menu(); +}; + +menu_end: end +{ + if (zconf_endtoken($1, T_MENU, T_ENDMENU)) { + menu_end_menu(); + printd(DEBUG_PARSE, "%s:%d:endmenu\n", zconf_curname(), zconf_lineno()); + } +}; + +menu_stmt: menu_entry menu_block menu_end +; + +menu_block: + /* empty */ + | menu_block common_stmt + | menu_block menu_stmt + | menu_block choice_stmt +; + +source_stmt: T_SOURCE prompt T_EOL +{ + printd(DEBUG_PARSE, "%s:%d:source %s\n", zconf_curname(), zconf_lineno(), $2); + zconf_nextfile($2); +}; + +/* comment entry */ + +comment: T_COMMENT prompt T_EOL +{ + menu_add_entry(NULL); + menu_add_prompt(P_COMMENT, $2, NULL); + printd(DEBUG_PARSE, "%s:%d:comment\n", zconf_curname(), zconf_lineno()); +}; + +comment_stmt: comment depends_list +{ + menu_end_entry(); +}; + +/* help option */ + +help_start: T_HELP T_EOL +{ + printd(DEBUG_PARSE, "%s:%d:help\n", zconf_curname(), zconf_lineno()); + zconf_starthelp(); +}; + +help: help_start T_HELPTEXT +{ + current_entry->help = $2; +}; + +/* depends option */ + +depends_list: + /* empty */ + | depends_list depends + | depends_list T_EOL + | depends_list option_error +; + +depends: T_DEPENDS T_ON expr T_EOL +{ + menu_add_dep($3); + printd(DEBUG_PARSE, "%s:%d:depends on\n", zconf_curname(), zconf_lineno()); +}; + +/* visibility option */ + +visibility_list: + /* empty */ + | visibility_list visible + | visibility_list T_EOL +; + +visible: T_VISIBLE if_expr +{ + menu_add_visibility($2); +}; + +/* prompt statement */ + +prompt_stmt_opt: + /* empty */ + | prompt if_expr +{ + menu_add_prompt(P_PROMPT, $1, $2); +}; + +prompt: T_WORD + | T_WORD_QUOTE +; + +end: T_ENDMENU T_EOL { $$ = $1; } + | T_ENDCHOICE T_EOL { $$ = $1; } + | T_ENDIF T_EOL { $$ = $1; } +; + +nl: + T_EOL + | nl T_EOL +; + +if_expr: /* empty */ { $$ = NULL; } + | T_IF expr { $$ = $2; } +; + +expr: symbol { $$ = expr_alloc_symbol($1); } + | symbol T_EQUAL symbol { $$ = expr_alloc_comp(E_EQUAL, $1, $3); } + | symbol T_UNEQUAL symbol { $$ = expr_alloc_comp(E_UNEQUAL, $1, $3); } + | T_OPEN_PAREN expr T_CLOSE_PAREN { $$ = $2; } + | T_NOT expr { $$ = expr_alloc_one(E_NOT, $2); } + | expr T_OR expr { $$ = expr_alloc_two(E_OR, $1, $3); } + | expr T_AND expr { $$ = expr_alloc_two(E_AND, $1, $3); } +; + +symbol: T_WORD { $$ = sym_lookup($1, 0); free($1); } + | T_WORD_QUOTE { $$ = sym_lookup($1, SYMBOL_CONST); free($1); } +; + +word_opt: /* empty */ { $$ = NULL; } + | T_WORD + +%% + +void conf_parse(const char *name) +{ + struct symbol *sym; + int i; + + zconf_initscan(name); + + sym_init(); + _menu_init(); + modules_sym = sym_lookup(NULL, 0); + modules_sym->type = S_BOOLEAN; + modules_sym->flags |= SYMBOL_AUTO; + rootmenu.prompt = menu_add_prompt(P_MENU, "Linux Kernel Configuration", NULL); + + if (getenv("ZCONF_DEBUG")) + zconfdebug = 1; + zconfparse(); + if (zconfnerrs) + exit(1); + if (!modules_sym->prop) { + struct property *prop; + + prop = prop_alloc(P_DEFAULT, modules_sym); + prop->expr = expr_alloc_symbol(sym_lookup("MODULES", 0)); + } + + rootmenu.prompt->text = _(rootmenu.prompt->text); + rootmenu.prompt->text = sym_expand_string_value(rootmenu.prompt->text); + + menu_finalize(&rootmenu); + for_all_symbols(i, sym) { + if (sym_check_deps(sym)) + zconfnerrs++; + } + if (zconfnerrs) + exit(1); + sym_set_change_count(1); +} + +static const char *zconf_tokenname(int token) +{ + switch (token) { + case T_MENU: return "menu"; + case T_ENDMENU: return "endmenu"; + case T_CHOICE: return "choice"; + case T_ENDCHOICE: return "endchoice"; + case T_IF: return "if"; + case T_ENDIF: return "endif"; + case T_DEPENDS: return "depends"; + case T_VISIBLE: return "visible"; + } + return ""; +} + +static bool zconf_endtoken(const struct kconf_id *id, int starttoken, int endtoken) +{ + if (id->token != endtoken) { + zconf_error("unexpected '%s' within %s block", + kconf_id_strings + id->name, zconf_tokenname(starttoken)); + zconfnerrs++; + return false; + } + if (current_menu->file != current_file) { + zconf_error("'%s' in different file than '%s'", + kconf_id_strings + id->name, zconf_tokenname(starttoken)); + fprintf(stderr, "%s:%d: location of the '%s'\n", + current_menu->file->name, current_menu->lineno, + zconf_tokenname(starttoken)); + zconfnerrs++; + return false; + } + return true; +} + +static void zconfprint(const char *err, ...) +{ + va_list ap; + + fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno()); + va_start(ap, err); + vfprintf(stderr, err, ap); + va_end(ap); + fprintf(stderr, "\n"); +} + +static void zconf_error(const char *err, ...) +{ + va_list ap; + + zconfnerrs++; + fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno()); + va_start(ap, err); + vfprintf(stderr, err, ap); + va_end(ap); + fprintf(stderr, "\n"); +} + +static void zconferror(const char *err) +{ + fprintf(stderr, "%s:%d: %s\n", zconf_curname(), zconf_lineno() + 1, err); +} + +static void print_quoted_string(FILE *out, const char *str) +{ + const char *p; + int len; + + putc('"', out); + while ((p = strchr(str, '"'))) { + len = p - str; + if (len) + fprintf(out, "%.*s", len, str); + fputs("\\\"", out); + str = p + 1; + } + fputs(str, out); + putc('"', out); +} + +static void print_symbol(FILE *out, struct menu *menu) +{ + struct symbol *sym = menu->sym; + struct property *prop; + + if (sym_is_choice(sym)) + fprintf(out, "\nchoice\n"); + else + fprintf(out, "\nconfig %s\n", sym->name); + switch (sym->type) { + case S_BOOLEAN: + fputs(" boolean\n", out); + break; + case S_TRISTATE: + fputs(" tristate\n", out); + break; + case S_STRING: + fputs(" string\n", out); + break; + case S_INT: + fputs(" integer\n", out); + break; + case S_HEX: + fputs(" hex\n", out); + break; + default: + fputs(" ???\n", out); + break; + } + for (prop = sym->prop; prop; prop = prop->next) { + if (prop->menu != menu) + continue; + switch (prop->type) { + case P_PROMPT: + fputs(" prompt ", out); + print_quoted_string(out, prop->text); + if (!expr_is_yes(prop->visible.expr)) { + fputs(" if ", out); + expr_fprint(prop->visible.expr, out); + } + fputc('\n', out); + break; + case P_DEFAULT: + fputs( " default ", out); + expr_fprint(prop->expr, out); + if (!expr_is_yes(prop->visible.expr)) { + fputs(" if ", out); + expr_fprint(prop->visible.expr, out); + } + fputc('\n', out); + break; + case P_CHOICE: + fputs(" #choice value\n", out); + break; + case P_SELECT: + fputs( " select ", out); + expr_fprint(prop->expr, out); + fputc('\n', out); + break; + case P_RANGE: + fputs( " range ", out); + expr_fprint(prop->expr, out); + fputc('\n', out); + break; + case P_MENU: + fputs( " menu ", out); + print_quoted_string(out, prop->text); + fputc('\n', out); + break; + default: + fprintf(out, " unknown prop %d!\n", prop->type); + break; + } + } + if (menu->help) { + int len = strlen(menu->help); + while (menu->help[--len] == '\n') + menu->help[len] = 0; + fprintf(out, " help\n%s\n", menu->help); + } +} + +void zconfdump(FILE *out) +{ + struct property *prop; + struct symbol *sym; + struct menu *menu; + + menu = rootmenu.list; + while (menu) { + if ((sym = menu->sym)) + print_symbol(out, menu); + else if ((prop = menu->prompt)) { + switch (prop->type) { + case P_COMMENT: + fputs("\ncomment ", out); + print_quoted_string(out, prop->text); + fputs("\n", out); + break; + case P_MENU: + fputs("\nmenu ", out); + print_quoted_string(out, prop->text); + fputs("\n", out); + break; + default: + ; + } + if (!expr_is_yes(prop->visible.expr)) { + fputs(" depends ", out); + expr_fprint(prop->visible.expr, out); + fputc('\n', out); + } + } + + if (menu->list) + menu = menu->list; + else if (menu->next) + menu = menu->next; + else while ((menu = menu->parent)) { + if (menu->prompt && menu->prompt->type == P_MENU) + fputs("\nendmenu\n", out); + if (menu->next) { + menu = menu->next; + break; + } + } + } +} + +#include "zconf.lex.c" +#include "util.c" +#include "confdata.c" +#include "expr.c" +#include "symbol.c" +#include "menu.c" diff --git a/kernel/fiasco/tool/kobjdeps b/kernel/fiasco/tool/kobjdeps new file mode 100755 index 00000000..0e24d44b --- /dev/null +++ b/kernel/fiasco/tool/kobjdeps @@ -0,0 +1,192 @@ +#! /usr/bin/perl -W +# +# Adam Lackorzynski +# +# Input to this script is the output of dumpmapdbobjs from Fiasco-jdb +# Output of this script is a dot graph +# +# Convert to SVG with e.g.: +# fdp -Gmclimit=200.0 -Gnslimit=500.0 -Gratio=0.7 \ +# -Tsvg -o x.svg x.dot +# +# To be improved... + +use strict; + +my $ignore = 1; +my $line = 0; +#my %spaces; +my %intasks; +my %kobjstype; +my %names; +my %obj_to_connector; +my %obj_to_root_space; + +my %obj_colors = ( + 'Task' => 'red', + 'Thread' => 'green', + 'Sched' => 'blue', + 'Factory' => 'yellow', + 'Gate' => 'magenta', +); + +while (<>) + { + chomp; + ++$line; + s/ $//; + if (/^========= OBJECT DUMP BEGIN ===============/) + { + $ignore = 0; + } + elsif (/^========= OBJECT DUMP END ===============/) + { + last; # done, we only consider the first one + } + elsif (!$ignore) + { + my $dbgid; + my $obj_type; + my $intask; + my $name; + $dbgid = $1 if /^([\da-fA-F]+)\s+/; + $obj_type = $1 if /\s\[([^\s\]]+)/; + $intask = $1 if /intask=(\S+)/; + $name = $1 if /\s{([^\s}]+)/; + + #print "$line: $_\n"; + if (not defined $dbgid or not defined $obj_type) + { + print "ERROR: parse or content error in line $line: $_\n"; + last; + } + + $obj_type =~ s/\[.*?m//g; + + $obj_to_connector{$dbgid} = $1 + if $obj_type eq 'Gate' and (/ D=([\da-fA-Z]+)/); + $obj_to_connector{$dbgid} = $1 + if $obj_type eq 'IRQ' and (/ T=([\da-fA-Z]+)/); + $obj_to_connector{$dbgid} = $1 + if $obj_type eq 'Thread' and (/ S=D:([\da-fA-Z]+)/); + + $kobjstype{$dbgid} = $obj_type; + $names{$dbgid} = $name if defined $name; + + if (defined $intask) + { + $intasks{$dbgid} = [ map { /^\[(.+)\]$/ } split(/,/, $intask) ]; + + $intasks{$dbgid}[0] =~ /^([^:]+)/; + $obj_to_root_space{$dbgid} = $1; + } + } + } + +sub id_to_objtype($) +{ + my $a = shift; + return "$kobjstype{$a}" if defined $kobjstype{$a}; + return $a; +} + +sub id_to_name($) +{ + my $a = shift; + return "$a".":".id_to_objtype($a).":".$names{$a} if defined $names{$a}; + return $a; +} + +print "digraph A {\n"; + +if (0) + { + foreach my $o (keys %kobjstype) + { + print " o$o [label = \"", id_to_objtype($o), "\"];\n"; + } + } + +foreach my $t (keys %kobjstype) + { + next unless + $kobjstype{$t} eq 'Task'; + + print " subgraph cluster_$t { label = \"", id_to_name($t), "\";". + " style=filled; \n"; + + foreach my $o (keys %intasks) + { + foreach my $i (@{$intasks{$o}}) + { + $i =~ /([\da-fA-F]+):(\d+)/; + my $space = $1; + my $lvl = $2; + + if ($t eq $space) + { + print " s$space"."o$o [label = \"".id_to_name($o)."\""; + #print " s$space"."o$o [label = \"$o\""; + print ",color=$obj_colors{$kobjstype{$o}}" + if defined $obj_colors{$kobjstype{$o}}; + print "];\n"; + } + + #print "$o: $space - $lvl\n"; + } + } + + print " }\n"; + } + +# mapping correlations +foreach my $o (keys %intasks) + { + my $lvl = 0; + my @stack; + + foreach my $i (@{$intasks{$o}}) + { + $i =~ /([\da-fA-F]+):(\d+)/; + my $space = $1; + my $l = $2; + + #print STDERR "$i -- l=$l\n"; + + $stack[$l] = $space; + + if ($l > 0) + { + print " s$stack[$l-1]o$o -> s$stack[$l]o$o"; + print "[color=$obj_colors{$kobjstype{$o}}]" + if defined $obj_colors{$kobjstype{$o}}; + print ";\n"; + } + #print "$o: $space - $l\n"; + } + } + +# connect tasks to cluster-boxes +foreach my $t (keys %kobjstype) + { + next unless + $kobjstype{$t} eq 'Task'; + + if ($obj_to_root_space{$t} ne $t) + { + print " s$obj_to_root_space{$t}o$t -> cluster_$t [style=dashed];\n"; + } + } + + +# connect gates/irqs to their threads +foreach my $g (keys %obj_to_connector) + { + my $s1 = $obj_to_root_space{$g}; + my $s2 = $obj_to_root_space{$obj_to_connector{$g}}; + my $o = $obj_to_connector{$g}; + print " s${s1}o$g -> s${s2}o$o [style=dotted];\n" + if defined $s1 and defined $s1; + } + +print "}\n"; diff --git a/kernel/fiasco/tool/mksnap b/kernel/fiasco/tool/mksnap new file mode 100755 index 00000000..faa007d1 --- /dev/null +++ b/kernel/fiasco/tool/mksnap @@ -0,0 +1,69 @@ +#!/bin/sh -ex + +echo "This one needs adaption..." +sleep 10 + +VERSION="fiasco-1.2" +CURRDIR=$(pwd) +SCRATCH="$CURRDIR/release-build" +WORKDIR="$SCRATCH/$VERSION" +EXCLUDE="$SCRATCH/exclude.$$" +KBLDDIR="$WORKDIR/l4/kernel/fiasco/build" + +CVSHOME="/home/cvs" +KERNPKG="l4/kernel/fiasco" +USERPKG="$(echo l4/COPYING l4/LICENSING l4/Makefile \ + l4/tool/preprocess/src/preprocess)" + +umask 022 + +trap "rm -rf $EXCLUDE && exit 1" 1 2 15 +trap "rm -rf $EXCLUDE && exit 0" 0 + +if [ -d "$SCRATCH" ]; +then + echo "$SCRATCH exists, please remove it before calling $0." + exit 1 +fi + +# Create a temporary working directory +mkdir -p $SCRATCH +mkdir -p $WORKDIR + +# Create file blacklist +echo '*CVS*' > $EXCLUDE +echo '.cvsignore' >> $EXCLUDE + +# Check out Userland stuff +(cd $WORKDIR && cvs -d $CVSHOME co $USERPKG) + +# Create Userland archive +(cd $SCRATCH && tar -X $EXCLUDE -cvpf $VERSION.tar $VERSION/l4) + +# Check out Kernel stuff +(cd $WORKDIR && cvs -d $CVSHOME co $KERNPKG) + +# mv README and CHANGES down to root of the archive so that users have +# something to read when they cd into fiasco-* +mv $WORKDIR/l4/kernel/fiasco/README $WORKDIR/l4/kernel/fiasco/CHANGES $WORKDIR +(cd $SCRATCH && tar -rvpf $VERSION.tar $VERSION/README $VERSION/CHANGES ) + +# Add kernel to archive +(cd $SCRATCH && tar -X $EXCLUDE -rvpf $VERSION.tar $VERSION/l4/kernel/fiasco) + +echo "Compressing tar files..." +( cd $SCRATCH + # *zip the dang thing + gzip -c9 $VERSION.tar > $VERSION.tar.gz + bzip2 -9 $VERSION.tar + + # Checksums for everyone + md5sum $VERSION.tar.gz >> $VERSION.tar.gz.md5 + md5sum $VERSION.tar.bz2 >> $VERSION.tar.bz2.md5 +) + +# Clean up +rm -rf $WORKDIR +rm -rf $KBLDDIR + +echo Done! diff --git a/kernel/fiasco/tool/move-if-change b/kernel/fiasco/tool/move-if-change new file mode 100755 index 00000000..3834c5e4 --- /dev/null +++ b/kernel/fiasco/tool/move-if-change @@ -0,0 +1,19 @@ +#!/bin/sh +# Like mv $1 $2, but if the files are the same, just delete $1. +# Status is 0 if $2 is changed, 1 otherwise. +quiet= +if test $1 = "-q"; then + quiet=1 + shift +fi +if test -r $2; then + if cmp -s $1 $2; then + test $quiet || echo $2 is unchanged + rm -f $1 + exit 1 + else + mv -f $1 $2 + fi +else + mv -f $1 $2 +fi diff --git a/kernel/fiasco/tool/parsedeps b/kernel/fiasco/tool/parsedeps new file mode 100755 index 00000000..ab7438bf --- /dev/null +++ b/kernel/fiasco/tool/parsedeps @@ -0,0 +1,45 @@ +#!/usr/bin/perl -w + +use strict; + +$, = ' '; # set output field separator +$\ = "\n"; # set output record separator + +my $doit = 1; + +my @input = <>; +$_ = join '', @input; + +s/\\\n//sg; # delete continuations + +record: +foreach my $record (split /\n/) { + next if $record =~ /^$/; + + my @stuff = split /\s+/, $record; + + line: + while ($_ = shift @stuff) { + chomp; # strip record separator + + if (/^else$/) { + $doit = 1; + next line; + } + + if (/^endif$/) { + print ""; + $doit = 0; + } + + if ($doit) { + /:/ && ! m|^[^/]+\.o:$| && next record; + + /Makefile/ && next line; + /auto\// || /:/ || next line; + print $_." \\"; + } + } + print ""; +} + diff --git a/kernel/fiasco/tool/preprocess/COPYING b/kernel/fiasco/tool/preprocess/COPYING new file mode 100644 index 00000000..ee0775ea --- /dev/null +++ b/kernel/fiasco/tool/preprocess/COPYING @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + Appendix: How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/kernel/fiasco/tool/preprocess/MAINTAINER b/kernel/fiasco/tool/preprocess/MAINTAINER new file mode 100644 index 00000000..1d2b5312 --- /dev/null +++ b/kernel/fiasco/tool/preprocess/MAINTAINER @@ -0,0 +1,2 @@ +mailaddr hohmuth@sax.de + diff --git a/kernel/fiasco/tool/preprocess/Makefile b/kernel/fiasco/tool/preprocess/Makefile new file mode 100644 index 00000000..ee86d56b --- /dev/null +++ b/kernel/fiasco/tool/preprocess/Makefile @@ -0,0 +1,7 @@ +PKGIDR ?= . +L4DIR ?= ../.. +include $(L4DIR)/mk/Makeconf + +TARGET = src test doc + +include $(L4DIR)/mk/subdir.mk diff --git a/kernel/fiasco/tool/preprocess/README b/kernel/fiasco/tool/preprocess/README new file mode 100644 index 00000000..ec8f8312 --- /dev/null +++ b/kernel/fiasco/tool/preprocess/README @@ -0,0 +1,38 @@ +`preprocess' -- A C++ preprocessor. +----------------------------------- + +This program is a preprocessor for C++ modules. With this tool, you +write unit-style single-source-file modules in C++ (e.g., foo.cpp), +from which the tool extracts three C++ source files that can then be +processed using the standard C++ compiler toolchain: + +- A public header file (foo.h) + +- A private header file containing all non-public type definitions + (foo_i.h). This facilitates debugging modules that need access to + implementation-specific data structures. + +- An implementation file (foo.cc) + +Features: + +- Modules contain two sections. The "INTERFACE:" section contains + the public interface to the module; the "IMPLEMENTATION:" section + contains everything else. The preprocessor puts "INTERFACE:" + declarations into the public header file and tries to hide + everything else. + +- The preprocessor automatically expands class declarations using + member-function definitions found in the file. Function labelled + PUBLIC, PROTECTED and PRIVATE are put into the corresponding section + of the class. This feature saves typing effort and reduces + duplication. + +- Functions declared "inline" are exported automatically, along with + all the functions and types they need (these dependencies must be + declared in the module file). This feature can be turned off so that + all functions labeled "inline" are hidded and generated out-of-line. + +For more documentation, please refer to the documentation (manpage, +webpage) in directory "doc" (requires Doxygen), or go to the online +documentation at . diff --git a/kernel/fiasco/tool/preprocess/TODO b/kernel/fiasco/tool/preprocess/TODO new file mode 100644 index 00000000..b37eeb99 --- /dev/null +++ b/kernel/fiasco/tool/preprocess/TODO @@ -0,0 +1,44 @@ +BUGS: + +- Namespace declarations are unsupported. + +- Forward-declared, out-of-line defined nested classes are + unsupported. + +- Preprocess does not automatically export declarations of public + variables and static class data to the generated header file. + +- Conditional compilation (preprocessor) is unsupported on file + top-level (preprocessor expressions inside blocks are OK), with the + exception that code commented out using "#if 0" is detected + correctly and deleted. + +IDEAS: + +- Preprocess' source code should be modularized so that the parser can + be used independently from the output generator. This would enable + us writing other interesting applications based on the parsed source + code: + + . Enforce naming conventions + . Rewrite .cpp files according to user-specified rules; this could + eventually be extented so that Preprocess can support a + refactoring browser. + . Aspect weaving (aspect-oriented programming) + . Automatically generate insulation (wrappers, protocol classes, + procedural interface) for a specified class + . Support class invariants, and pre- and postconditions + +- When should we backdate newly-generated files? Obviously, if the + newly generated file and its previous version are the same. There + are circumstances, however, when clients using a generated header + file do not have to be recompiled: + + . Only line-number changes + . "friend" additions + . Relaxation of protection rules + . (and a number of other circumstances; see [Lakos]) + +- Preprocess should be configurable not only via command-line + arguments, but also using a config file. + diff --git a/kernel/fiasco/tool/preprocess/doc/Doxyfile b/kernel/fiasco/tool/preprocess/doc/Doxyfile new file mode 100644 index 00000000..6f12aa88 --- /dev/null +++ b/kernel/fiasco/tool/preprocess/doc/Doxyfile @@ -0,0 +1,192 @@ +# Doxyfile 1.2.18 + +#--------------------------------------------------------------------------- +# General configuration options +#--------------------------------------------------------------------------- +PROJECT_NAME = Preprocess +PROJECT_NUMBER = +OUTPUT_DIRECTORY = +OUTPUT_LANGUAGE = English +EXTRACT_ALL = NO +EXTRACT_PRIVATE = NO +EXTRACT_STATIC = NO +EXTRACT_LOCAL_CLASSES = YES +HIDE_UNDOC_MEMBERS = NO +HIDE_UNDOC_CLASSES = NO +HIDE_FRIEND_COMPOUNDS = NO +BRIEF_MEMBER_DESC = YES +REPEAT_BRIEF = YES +ALWAYS_DETAILED_SEC = NO +INLINE_INHERITED_MEMB = NO +FULL_PATH_NAMES = NO +STRIP_FROM_PATH = +INTERNAL_DOCS = NO +STRIP_CODE_COMMENTS = YES +CASE_SENSE_NAMES = YES +SHORT_NAMES = NO +HIDE_SCOPE_NAMES = NO +VERBATIM_HEADERS = YES +SHOW_INCLUDE_FILES = YES +JAVADOC_AUTOBRIEF = NO +MULTILINE_CPP_IS_BRIEF = NO +DETAILS_AT_TOP = NO +INHERIT_DOCS = YES +INLINE_INFO = YES +SORT_MEMBER_DOCS = YES +DISTRIBUTE_GROUP_DOC = NO +TAB_SIZE = 8 +GENERATE_TODOLIST = YES +GENERATE_TESTLIST = YES +GENERATE_BUGLIST = YES +GENERATE_DEPRECATEDLIST= YES +ALIASES = +#ENABLED_SECTIONS = +MAX_INITIALIZER_LINES = 30 +OPTIMIZE_OUTPUT_FOR_C = NO +OPTIMIZE_OUTPUT_JAVA = NO +SHOW_USED_FILES = YES +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- +QUIET = NO +WARNINGS = YES +WARN_IF_UNDOCUMENTED = YES +WARN_FORMAT = +WARN_LOGFILE = +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- +INPUT = manpage.dox +FILE_PATTERNS = +RECURSIVE = NO +EXCLUDE = +EXCLUDE_SYMLINKS = NO +EXCLUDE_PATTERNS = +EXAMPLE_PATH = +EXAMPLE_PATTERNS = +EXAMPLE_RECURSIVE = NO +IMAGE_PATH = +INPUT_FILTER = +FILTER_SOURCE_FILES = NO +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- +SOURCE_BROWSER = NO +INLINE_SOURCES = NO +REFERENCED_BY_RELATION = YES +REFERENCES_RELATION = YES +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- +ALPHABETICAL_INDEX = NO +COLS_IN_ALPHA_INDEX = 5 +IGNORE_PREFIX = +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- +#GENERATE_HTML = YES +HTML_OUTPUT = +HTML_FILE_EXTENSION = .html +HTML_HEADER = +HTML_FOOTER = +HTML_STYLESHEET = +HTML_ALIGN_MEMBERS = YES +GENERATE_HTMLHELP = NO +CHM_FILE = +HHC_LOCATION = +GENERATE_CHI = NO +BINARY_TOC = NO +TOC_EXPAND = NO +DISABLE_INDEX = YES +ENUM_VALUES_PER_LINE = 4 +GENERATE_TREEVIEW = NO +TREEVIEW_WIDTH = 250 +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- +#GENERATE_LATEX = NO +LATEX_OUTPUT = +LATEX_CMD_NAME = latex +MAKEINDEX_CMD_NAME = makeindex +COMPACT_LATEX = NO +PAPER_TYPE = a4wide +EXTRA_PACKAGES = +LATEX_HEADER = +PDF_HYPERLINKS = NO +USE_PDFLATEX = NO +LATEX_BATCHMODE = NO +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- +#GENERATE_RTF = NO +RTF_OUTPUT = +COMPACT_RTF = NO +RTF_HYPERLINKS = NO +RTF_STYLESHEET_FILE = +RTF_EXTENSIONS_FILE = +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- +#GENERATE_MAN = YES +MAN_OUTPUT = +MAN_EXTENSION = .1 +MAN_LINKS = YES +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- +#GENERATE_XML = NO +XML_SCHEMA = +XML_DTD = +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- +GENERATE_AUTOGEN_DEF = NO +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- +ENABLE_PREPROCESSING = YES +MACRO_EXPANSION = NO +EXPAND_ONLY_PREDEF = NO +SEARCH_INCLUDES = YES +INCLUDE_PATH = +INCLUDE_FILE_PATTERNS = +PREDEFINED = +EXPAND_AS_DEFINED = +SKIP_FUNCTION_MACROS = YES +#--------------------------------------------------------------------------- +# Configuration::addtions related to external references +#--------------------------------------------------------------------------- +TAGFILES = +GENERATE_TAGFILE = +ALLEXTERNALS = NO +EXTERNAL_GROUPS = YES +PERL_PATH = +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- +CLASS_DIAGRAMS = YES +HIDE_UNDOC_RELATIONS = YES +HAVE_DOT = NO +CLASS_GRAPH = YES +COLLABORATION_GRAPH = YES +TEMPLATE_RELATIONS = YES +INCLUDE_GRAPH = YES +INCLUDED_BY_GRAPH = YES +GRAPHICAL_HIERARCHY = YES +DOT_IMAGE_FORMAT = png +DOT_PATH = +DOTFILE_DIRS = +MAX_DOT_GRAPH_WIDTH = 1024 +MAX_DOT_GRAPH_HEIGHT = 1024 +GENERATE_LEGEND = YES +DOT_CLEANUP = YES +#--------------------------------------------------------------------------- +# Configuration::addtions related to the search engine +#--------------------------------------------------------------------------- +SEARCHENGINE = NO +CGI_NAME = +CGI_URL = +DOC_URL = +DOC_ABSPATH = +BIN_ABSPATH = +EXT_DOC_PATHS = diff --git a/kernel/fiasco/tool/preprocess/doc/Makefile b/kernel/fiasco/tool/preprocess/doc/Makefile new file mode 100644 index 00000000..f7058b25 --- /dev/null +++ b/kernel/fiasco/tool/preprocess/doc/Makefile @@ -0,0 +1,34 @@ +L4DIR ?= ../../.. +include $(L4DIR)/mk/Makeconf + +ALL = html man +all:: $(foreach d, $(ALL), stamp-$(d)) + +DIRS = html man latex +.PHONY: $(DIRS) +$(DIRS) : % : stamp-% + +stamp-%: Doxyfile manpage.dox + ( echo "ENABLED_SECTIONS = $*"; \ + for format in latex html man; do \ + echo "GENERATE_$$(echo $$format | tr a-z A-Z) = \ + $$(if [ $$format = $* ]; then echo YES; else echo NO; fi)"; \ + done; \ + cat $<) | doxygen - + if [ "$*" = html ]; then \ + perl -p -i -e 's/preprocess.html#/#/g' html/preprocess.html; \ + fi + if [ "$*" = man ]; then \ + perl -p -i -e 's/preprocess \\- Preprocess - /preprocess \\- /g' \ + man/man1/preprocess.1; \ + fi + touch $@ + +install: stamp-man + -$(INSTALL) -d $(DROPS_STDDIR)/tool/man/man1 + $(INSTALL) -m 644 man/man1/preprocess.1 \ + $(DROPS_STDDIR)/tool/man/man1/preprocess.1 + + +cleanall clean: + rm -rf $(DIRS) stamp-* diff --git a/kernel/fiasco/tool/preprocess/doc/manpage.dox b/kernel/fiasco/tool/preprocess/doc/manpage.dox new file mode 100644 index 00000000..db820e9c --- /dev/null +++ b/kernel/fiasco/tool/preprocess/doc/manpage.dox @@ -0,0 +1,661 @@ +/*! + +\page preprocess Preprocess - A preprocessor for C and C++ modules + +\ifnot man + +Do you hate writing C or C++ header files? + +Do you always forget where to place those inline, +virtual, static, and explicit +modifiers -- to the member-function definition or declaration? + +Do you often find yourself avoiding to factor out a new method because +you also need to add a method declaration to the class declaration in +the header file? + +Do you hate putting inline function into header files, in a special +order? + +If so, Preprocess may be your answer. With this tool, you write +unit-style single-source-file modules in C++, from which it +automatically generates header and implementation files. + +

+


+ +

Table of contents:

+ +
    +
  • \ref SYNOPSIS +
  • \ref DESCRIPTION +
  • \ref OPTIONS +
  • \ref LANGUAGE +
  • \ref MISC +
  • \ref MAKEFILE +
  • \ref BUGS +
  • \ref DOWNLOAD +
  • \ref LIST +
  • \ref AUTHOR +
  • \ref SEE +
+ +

+ +\endif + +\section SYNOPSIS Synopsis + +preprocess -c filename_base + [ -o outfile_base | -s] +
           [ -p prepend ] +
           [ -C source_ext ] + [ -H header_ext ] +
           [ -e tag_list ] +
           [ -i ] [ -t ] + [ -l | -L ] [ -v ] [ -d ] +
           sources... + +\section DESCRIPTION Description + +Preprocess is a preprocessor for C++ modules. With this tool, you +write unit-style single-source-file modules in C++. + +Preprocess essentially does these things (and frees the programmer +from doing them): +

    +
  • Generate header files that contain declarations for public + classes and functions.
  • +
  • Fill in member-function declarations into class declarations.
  • +
  • Export public inline and template functions in correct order + (you need to declare dependencies for inline functions).
  • +
  • Optionally, function marked "inline" can be put + into the implementation file (out of line). This can ease + development (as it temporarily decreases dependencies on header + files that change frequently) and debugging.
  • +
+ +These automatisms lead to source files that are more logically +cohesive (no need to put inline and template functions into a separate +file, in a special order) and saves typing effort. + +Preprocess works by transforming unit-style single-source-file C++ +modules into three output files: public header, private header, and +implementation file. C and C++ comments are preserved during the +transformation, keeping the resulting files readable and making it +possible to run another preprocessor on Preprocess' output. + +\section OPERATION Basic operation + +\htmlonly + + + + + + +
+\endhtmlonly + +Modules contain two sections. The "INTERFACE:" +section contains the public interface to the module; the +"IMPLEMENTATION:" section contains everything else. The +preprocessor puts interface declarations into a public header file and +tries to hide everything else. + +Class definitions deliberately lack declarations for member +functions: Preprocess will add them automatically. Member-function +definitions (in the implementation section) labelled +PUBLIC, PROTECTED and PRIVATE +are put into the corresponding section of the class. This feature +saves typing effort and reduces duplication. + +From this input file (foo.cpp), Preprocess extracts three C++ source +files that can then be processed using the standard C++ compiler +toolchain: + +\htmlonly + +\endhtmlonly + +
+// C++ module -- Preprocess input file
+INTERFACE:
+
+\#include "bar.h"
+
+struct Baz;
+
+class Foo : public Bar
+{
+  Baz* d_baz;
+};
+
+IMPLEMENTATION:
+
+struct Baz
+{
+  int data;
+};
+
+PUBLIC
+int Foo::get_info() 
+{
+  return d_baz->data;
+}
+ +\htmlonly +
+\endhtmlonly + +First, Preprocess generates a public header file (foo.h). This +header file contains all declarations from the interface section, with +class definitions properly expanded to contain member-function +declarations\htmlonly (shown red in the +example on the right side)\endhtmlonly. + +It also contains declarations of non-"static" free +functions found in the implementation section, as well as definitions +for functions declared "inline". Additionally, it +contains all "\#include" directives and function and class +declarations and definitions the inline functions need; these +dependencies need to be declared in the input file. (These features +are not shown in the example\htmlonly on the right side\endhtmlonly.) + +If desired, preprocess can also be instructed to hide all inline +functions (and to generate them out-of-line instead), resulting in a +public header file that better insulates clients from implementation +details. + +\htmlonly + +\endhtmlonly + +
+// Preprocess-generated public header file
+\#ifndef foo_h
+\#define foo_h
+
+\#include "bar.h"
+
+struct Baz;
+
+class Foo : public Bar
+{
+private:
+  Baz* d_baz;
+\htmlonly  \endhtmlonly
+public:  
+  int get_info();\htmlonly  \endhtmlonly
+};
+
+\#endif // foo_h
+ +\htmlonly +
+\endhtmlonly + +Second, a private header file containing all non-public type +definitions (foo_i.h). This file can be used by debugging modules +that need access to implementation-specific data structures. + + This file also contains all inline member functions belonging to +classes declared here. (This feature is not shown in the example.) + + +\htmlonly + +\endhtmlonly + +
+// Preprocess-generated private header file
+\#ifndef foo_i_h
+\#define foo_i_h
+
+struct Baz
+{
+  int data;
+};
+
+\#endif // foo_i_h
+ +\htmlonly +
+\endhtmlonly + +Third, an implementation file (foo.cc). This file starts with +declarations for all free "static" functions (not shown in +the example). Otherwise, it comprises all non-inline function +definitions (and static inline functions). + +\htmlonly + +\endhtmlonly + +
+// Preprocess-generated implementation file
+\#include "foo.h"
+\#include "foo_i.h"
+
+void Foo::get_info() 
+{
+  return d_baz->info();
+}
+ +\htmlonly +
+\endhtmlonly + +\section OPTIONS Options reference + +Output files have names of the following form: +
    +
  • Implementation file: + [prepend]outfile_base[-suffix].source_ext
  • +
  • Public header file: + [prepend]outfile_base.header_ext
  • +
  • Private header file: + [prepend]outfile_base_i.header_ext
  • +
+ +where [prepend] is an optional filename part that can be +specified using -p, outfile_base needs to be +specified using -c, suffix is an optional +suffix that can be specified using the IMPLEMENTATION +directive, and source_ext and header_ext default +to ".cc" and ".h" but can be overridden using -C and +-H, respectively. +
+
-c filename_base
+
Specifies the basename of generated file names that appear in + the output files. This option is mandantory.
+
-o outfile_base
+
Specifies the basename of output files. It defaults to the + value of the -c option.
+
-s
+
Generate one implementation file per source file, using the base + name of the implementation file as outfile_base, and not one + implementation file per suffix specified as + arguments to IMPLEMENTATION directives in the + source files.
+
-p prepend
+
Specifies a prefix for all output file names. This prefix is + prepended to filename_base and can contain directory + separators ("/").
+
-C source_ext
+
Specify the extension of generated implementation files. + Defaults to ".cc".
+
-H header_ext
+
Specify the extension of generated header files. + Defaults to ".h".
+
-e tag_list
+
Enable conditional compilation using the selectors included in + the comma-separated tag_list. This option is + intended to be used in conjunction with the -s + option. See Section + \ref CONDITIONAL \if man CONDITIONAL COMPILATION \endif + for details on this option.
+
-t
+
Truncate to size 0 output files for which Preprocess generates + no output. This option supresses even \#include + directives in generated source files that are otherwise empty, + resulting in increased compilation speed for these files.
+
-i
+
Generate inline code. If this option is not + given, all code (including code marked "inline") + is generated out-of-line.
+
-l
+
Avoid generating \#line directives in output + files. If this option is not given, \#line will be + generated by default.
+
-L
+
Avoid generating \#line directives in header files only. + Using this option can speed up builds because the contents of + header files change less frequently, as \#line + directives for (member) function declarations do not have to be + updated every time its definition in the source module changes + its absolute position. (Of course, this assumes that the time + stamp of header files are updated only when the contents of the + files change. See Section + \ref MAKEFILE \if man EXAMPLE MAKEFILE FRAGMENT \endif + for a possible way to + do this.)
+
-v
+
Be verbose: Print results of preprocess' parser pass.
+
-d
+
Be verbose: Print a diagnostic when dropping a section in + conditional-compilation mode (Option -e).
+
+ + +\section LANGUAGE Language directives + +Preprocess understands a number of language directive that control its +behavior. +
+
INTERFACE: +
Starts an interface section. Every declaration from such a + section will be copied to the public header file. Class + declarations found here (``public class'') will be completed + with member-function declarations for member functions found in + IMPLEMENTATION sections. + \htmlonly

\endhtmlonly + Function definitions are not allowed in this section. + +

IMPLEMENTATION: +
Starts an implementation section. Preprocess tries to hide + declarations found in these sections in the internal header + file and in the implementation file, as follows: +
+
Class declarations (``private classes'') +
(subject to member-function-declaration completion + as with those in + INTERFACE: sections) end up in the internal + header file -- except if a public inline function of a + public class depends on the private class, in which case + the private class' declaration will be put into the + public header file. +
Include directives +
underlie the same rules as class declarations. +
Function definitions +
are usually held in the implementation file. Public + inline functions, private inline + functions needed by a public inline function, and + functions subject to template instatiation are exported + to the public header file. Other inline functions + (except static non-member inline functions) are put into + the private header file. +
Other code (e.g., variable definitions) +
is put into the implementation file. +
+ +
PUBLIC, PRIVATE, and PROTECTED +
specify member-function visibility. + +
explicit, static, and virtual +
specify member-function attributes. The attributes will be + copied to the automatically-created member-function + declarations in class declarations (and removed for the actual + function definition, as C++ requires). + +
inline +
specifies inline functions. This attribute will be retained + for function definitions (but deleted for + automatically-created member-function declarations, as C++ + requires). (Inline functions will be + exported subject to the rules defined above.) + +
inline NEEDS [dependencies, + ... ] +
like inline, but additionally specifies types, + functions, and \#include statements that this + inline function depends on and that consequently need to be + exported as well, in front of this inline function. Preprocess + reorders definitions such that all dependencies are defined + before the inline function. + \htmlonly

\endhtmlonly + Example: +

inline NEEDS["foo.h", some_func, Some_class,
+             Some_other_class::member_func]
+int
+foo ()
+{ }
+
+
+ +\subsection ADVANCED Language directives for advanced use + +
+
IMPLEMENTATION [suffix]: +
Starts an implementation section with code that will be put + into a nonstandard output file. Instead of landing in + outfile_base.cc, the code ends up in + outfile_base-suffix.cc. + This directive is useful if there are several input files that + together make up one input module (which are fed to Preprocess + at the same time and which share one public and one private + header file). + + (This form of the IMPLEMENTATION directive works only if + neither the -s (no-suffix) nor the -e + (conditional compilation) options are used. See Section + \ref CONDITIONAL \if man CONDITIONAL COMPILATION \endif + for information on conditional compilation.) + +
EXTENSION class classname { + ... }; +
Extends the definition of class classname (which + usually appears in another input file) with more members. This + clause is usually used when a class can be configured with + several alternative extensions, for example to provide + portability across architectures. + +
IMPLEMENT +
is a member-function attribute that specifies that the member + function's declaration should not be copied to the + class declaration. Use this attribute to implement an + interface that is already declared in the class declaration. + +
inline NOEXPORT +
specifies inline functions that will not be exported via the + public header file even if it is a publibly-visible function. + Instead, the function definition will end up in the + implementation file. + +
inline ALWAYS_INLINE +
specifies a functions that is generated as an inline function + even if the -i option is not used. Use this + specifier for functions that absolutely must be inline even in + debugging builds. + +
+ +\subsection CONDITIONAL Conditional compilation + +Conditional compilation is a Preprocess mode that is enabled by using +the "-e tag_list" option. + +
+
INTERFACE [tag_expression]:
+
IMPLEMENTATION [tag_expression]:
+
A tag_expression is a logical expression with negation (!), + conjunction (-), disjunction (,), and one level of parentheses + ({ and }), using selector tags as its atoms. The + INTERFACE or IMPLEMENTATION section + is included in the output only if it is true using the + selectors specified in tag_list. +
+
+ +Examples: + +
INTERFACE [a,b]:
+// This section is used whenever a or b is contained in the tag_list
+
+INTERFACE [a-b]: 
+// This section is used whenever a and b are contained in the tag_list
+
+INTERFACE [a,b-c]:
+// This section is used whenever a, or b and c are 
+// contained in the tag_list
+
+INTERFACE [!a]:
+// This section is used whenever a is not contained in the tag_list
+
+INTERFACE [{a,b}-c]:
+// This section is used whenever a and c, or b and c are 
+// contained in the tag_list
+
+INTERFACE [!a,b-c]:
+// This section is used whenever a is not contained in the tag_list,
+// or b and c are contained in the tag_list
+ +\section MISC Usage hints + +When you use Preprocess, there are a few things you need to keep in +mind. +
    +
  • Preprocess currently does not support namespaces and nested + classes. It is possible to use namespaces and nested classes + defined elsewhere (for example, in a library header file), but + you cannot define new namespaces and nested classes. + \htmlonly

    \endhtmlonly +

  • Preprocess copies function declarations for publicly visible + functions to the public header file. If you use user-defined + types in function signatures, you need to "\#include" + the corresponding header files (or add forward declarations) in + the "INTERFACE:" section of your module. Private + inline functions (which might end up in the public header file) + need to specify their include dependencies in a "NEEDS[]" + clause. + \htmlonly

    \endhtmlonly + Also, if you use names declared in an (externally-defined) + namespace (such as namespace "std"), you must + specify the fully-qualified name (including the namespace) in + the function signature (unless you use a "using + namespace" directive in the "INTERFACE:" + section, which is not recommended). + \htmlonly

    \endhtmlonly +

  • Don't forget to specify inline functions required by other + inline functions in the latter's "NEEDS" clause. + Otherwise, Preprocess cannot guarantee the correct + inline-function order in the output, and you may get compiler + warnings like ``inline function is used but not defined.'' This + problem is reinforced when using private inline functions, + because Preprocess moves them out of the public header file + (into the private header file) unless a public function's + "NEEDS" clause requires them. +
+ +\section MAKEFILE Example Makefile fragment + +\htmlonly + + + + +\htmlonly +
+\endhtmlonly + +This is an example fragment from a Makefile (for GNU Make) that +generates *.cc, *.h, and *_i.h +files on the fly. It only updates the generated files if they +actually change; that is, if you change something in the +implementation section that does not influence the header files, they +will not be updated, avoiding recompilation of files that depend on +them. + +This Makefile fragment needs GNU Make and the move-if-change script that only updates a +target if it is different from the source. + +This example assumes that you do not use the +IMPLEMENTATION[suffix] +directive. If you do plan using this directive, a more elaborate +mechanism is needed, such as the one used in the Makefiles for the +Fiasco microkernel. + +\htmlonly + +\endhtmlonly +
PREPROCESS = preprocess
+
+.PRECIOUS: stamp-%.ready
+stamp-%.ready: %.cpp
+	\$(PREPROCESS) -i -o new_\$* -c \$* \$<
+	./move-if-change new_\$*.h \$*.h 
+	./move-if-change new_\$*_i.h \$*_i.h 
+	./move-if-change new_\$*.cc \$*.cc 
+	touch \$@
+
+%.cc: stamp-%.ready
+        @[ -e \$@ ] || { rm -f \$<; \$(MAKE) \$<; }
+
+%.h: stamp-%.ready
+        @[ -e \$@ ] || { rm -f \$<; \$(MAKE) \$<; }
+
+\%_i.h: stamp-%.ready
+        @[ -e \$@ ] || { rm -f \$<; \$(MAKE) \$<; }
+\endhtmlonly + + + +\section BUGS Limitations and ideas for future extensions + +

Bugs

+ +
    +
  • Namespaces and nested classes currently are unsupported. +
  • The \#line directives Preprocess generates sometimes + are offset plus/minus one or two lines to the real code. +
  • Preprocess doesn't really understand preprocessor constructs + besides \#include and \#if 0; it just + copies all other direcitives into the output as it finds them. + That makes it easy for you to shoot yourself into the foot. +
+ +

Ideas for future extensions

+ +
    +
  • Generate HTML documentation for modules/classes. +
  • Auto-generated getters and setters for attributes +
  • Auto-generate insulation (wrappers, protocol classes, + procedural interface) for any given class. +
  • Transform input .cpp files into new + .cpp files, refactoring or renaming code on the + fly. +
  • Aspect-oriented programming: Weave in extensions (``aspects'') + to member functions. Aspects can be + synchronization or debugging checks, for example. +
  • Support for class invariants (design by contract) +
  • Enforce a set of naming conventions. +
+ +\section DOWNLOAD Download + +Preprocess is free software licensed under the GNU General Public +License. Its implementation language is Perl, so you need a Perl5 +interpreter to run it. + +You can download Preprocess as CVS module "preprocess" +from the DROPS project's remote-CVS server. Please refer to the download +instructions on DROPS' website. + +\section LIST Mailing list + +There is a mailing list to which CVS-commit messages for changes made +to preprocess are posted. Please ask me if you would like to be put +on this list (see Section \ref AUTHOR \if man AUTHOR \endif). + +New releases are periodically announced on the Freshmeat +website. If you are a registered Freshmeat user, you can subscribe to these +release announcements\if man at +http://freshmeat.net/subscribe/36508/\endif. + +\section AUTHOR Author + +Michael Hohmuth + +\section SEE See also + +move-if-change(1) shell script\if man +: http://os.inf.tu-dresden.de/~hohmuth/prj/preprocess/move-if-change +\endif + +\if man +Preprocess +project web page +: http://os.inf.tu-dresden.de/~hohmuth/prj/preprocess/ +\endif + +Preprocess was originally written for the Fiasco microkernel\if man +: http://os.inf.tu-dresden.de/fiasco/ +\endif. + +*/ diff --git a/kernel/fiasco/tool/preprocess/src/Makefile b/kernel/fiasco/tool/preprocess/src/Makefile new file mode 100644 index 00000000..5ed46e5f --- /dev/null +++ b/kernel/fiasco/tool/preprocess/src/Makefile @@ -0,0 +1,25 @@ +# +# Makefile for the preprocess sources +# + +# scan the L4 global configuration file +L4DIR ?= ../../.. +include $(L4DIR)/mk/Makeconf + +-include Makeconf.local + +TARGET = preprocess + +all:: $(TARGET) + +install:: all + -$(INSTALL) -d $(DROPS_STDDIR)/tool/bin + $(INSTALL) -m 755 $(TARGET) $(DROPS_STDDIR)/tool/bin + +clean:: +# $(RM) $(TARGET) $(OBJS) tmp.* + +cleanall:: clean + $(RM) *~ .*.d + +#include $(DEPS) diff --git a/kernel/fiasco/tool/preprocess/src/preprocess b/kernel/fiasco/tool/preprocess/src/preprocess new file mode 100755 index 00000000..345013ac --- /dev/null +++ b/kernel/fiasco/tool/preprocess/src/preprocess @@ -0,0 +1,1799 @@ +#! /usr/bin/perl -w +# -*- perl -*- + +# +# Please find extensive documentation of this program at +# +# + +# Things this script does: +# +# - Expand class declarations as necessary using member-function +# definitions found in the file. Function labelled PUBLIC, +# PROTECTED and PRIVATE are put into the corresponding section of +# the class. +# +# - Put "INTERFACE:" regions in public header file. +# +# - Put "inline" functions and all types they need into public header +# file as well. +# +# - Put all remaining, private types and their inline functions into a +# separate header file. This file can be used by a debugger +# interface to display the data. +# +# - Place include directives to top of public header file and private +# header file. +# + +# +# Declarations +# + +require 5.006; +use Getopt::Std; +use strict; + +sub print_expand($); +sub print_funcdecl($); +sub print_funcdef($); +sub print_classdecl($); +sub print_code($); +sub func_prototype($); + +# +# Get options +# + +our $opt_c = ''; # Base name for generated include directives +our $opt_o = ''; # Base name of output files (defaults to -c, + # overrides -p) +our $opt_p = ''; # Prepend to base name of output files (-c) +our $opt_h = ''; # Name of public header; overrides -c +our $opt_i = 0; # Doing inlines? +our $opt_v = 0; # Verboseness? +our $opt_l = 0; # Avoid generating #line directives? +our $opt_L = 0; # Avoid generatung #line dirs in headers only? +# Support for new style FIASCO config +our $opt_e = ''; # List of part tags +our $opt_s = 0; +our $opt_d = 0; # verbose drop + +our $opt_w = 0; # warn if no inline code for needs is found + +# Added 2003.01.12 by RCB +# Support for changing the names of headers +our $opt_H = "h"; # Default extenstion for header files +our $opt_C = "cc"; # Default extention for source files +our $opt_t = 0; + +getopts('e:o:c:p:h:H:C:ivlLsdwt'); + +sub usage +{ + print < [-C ] + [-e ] [-h ] [-H ] + [-o ] [-p ] +OPTIONS + -c Base name for generated include directives, generated + header files, and generated source files. + -C File extension for generated source files (default 'cc'). + -d Verbose drop sections (only in conjunction with -e). + -e Use explicit section selection, and set the given tag + list. is a qouted and space separated list of + tags that should be enabled. (Useful in conjunction + with -s) + -h Name of generated public header (overrides -c) + -H File extension for generated header files (default 'h'). + -i Do inlines, make inline functions real inline. + -l Avoid generating #line directives. + -L Avoid generating #line directives in headers only. + -o Base name for generated source files (defaults to -c, and + overrides -p) + -p Prefix for names of output files. + -s Generate a single source file per .cpp file (not a file + per section). + -t Truncate empty implementation files to zero length (so + that even the includ directives are ommitted) + -v Be verbose (very). + -w Do warnings. +EOF +} + +if ($opt_c eq '') + { + usage; + die "Need to specify option -c Classfile_basename;"; + } + +my $incfile_base = $opt_c; +my $public_base = (($opt_h eq '') ? $incfile_base : $opt_h); +my $outfile_base; +my $headerfile_base; +my $doing_inlines = $opt_i; +my $verbose = $opt_v; +my $doing_linenumbers = (! $opt_l) && (! $opt_L); +my $wno_inline = $opt_w; +my $status = 0; + +my $parts_re = ''; +my %parts = ( '{' => '(', + '}' => ')', + ',' => '||', + '-' => '&&', + '|' => '|', + '&' => '&', + '(' => '(', + ')' => ')', + '!' => '!'); + +my $ARGV = $ARGV[0]; + +if ($opt_e ne '') + { + foreach my $p (split(' ',$opt_e)) + { + $parts{$p} = '1'; + } + } + +# Added 2003.01.12 by RCB +# Support for changing the names of headers +my $source_ext = $opt_C; +my $header_ext = $opt_H; + +if ($opt_o eq '') + { + $outfile_base = $opt_p . $incfile_base; + $headerfile_base = $opt_p . $public_base; + } +else + { + $outfile_base = $opt_o; + $headerfile_base = $outfile_base; + } + +# +# Variable initializations +# +parse_init(); + +our $print_indent = 0; +clear_head(); + +my %classes = (); +my %sections = (); +my %impl_parts = (); +my %includes = (); +my @comments = (); +my %public_inline = (); +my %private_inline = (); +my %unit_inline = (); +my @inline_order_public = (); +my @inline_order_private = (); +my @inline_order_unit = (); + +# +# Parse input file +# + +parse_file (); + +# +# Print header file +# + +# Fixup incfile_base preproc macro if it contains invalid chars. +my $incfile_base_macro; + +$incfile_base_macro = $incfile_base; +$incfile_base_macro =~ s/[+-]/_/g; + +open(OUT, ">${headerfile_base}.$header_ext") + || die "Cannot open ${headerfile_base}.$header_ext for writing!"; +print OUT "// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*-\n\n"; +print OUT "#ifndef ${incfile_base_macro}_$header_ext\n" . + "#define ${incfile_base_macro}_$header_ext\n"; + +foreach my $i (grep {$_->{type} eq 'include'} @{$sections{"INTERFACE"}}) + { + print_code $i; + } + +print_head ("\n" . + "//\n" . + "// INTERFACE definition follows \n" . + "//\n\n"); + +foreach my $i ( (grep {$_->{type} eq 'classdef' + && $_->{syntax} eq 'forwarddecl'} + @{$sections{"INTERFACE"}}), + (grep {$_->{type} ne 'classdef' || $_->{syntax} ne 'forwarddecl'} + @{$sections{"INTERFACE"}}) ) + { + if ($i->{type} eq 'code') + { + print_code $i; + } + elsif ($i->{type} eq 'classdef') + { + print_classdecl ($i); + } + } + +foreach my $i (grep {$_->{type} eq 'function' && $_->{class} eq '' + && ! $_->{static}} + @{$sections{"IMPLEMENTATION"}}) + { + print_funcdecl $i; + } + +my @public_templates = grep + { + $_->{type} eq 'function' && $_->{template} ne '' # template func + && $_->{fully_specialized_template} eq '' + && ! defined $public_inline{$_} # not public inline -- handled elsewhere + && ($_->{visibility} eq "free" # free func + || ($_->{class} ne '' # or member func of public or published class + && ($classes{$_->{class}}->{section} eq 'INTERFACE' + || defined $public_inline{$classes{$_->{class}}}))) + } + @{$sections{"IMPLEMENTATION"}}; + +my $impl_includes_imported = 0; + +if (scalar keys %public_inline || scalar @public_templates) + { + if (scalar @public_templates) + { + $impl_includes_imported = 1; + } + + clear_head(); + print_head + ("\n" . + "//\n" . + "// IMPLEMENTATION includes follow " . + "(for use by inline functions/templates)\n" . + "//\n\n"); + + foreach my $i (grep { $_->{type} eq 'include' + && ($impl_includes_imported || $_->{inline}) } + @{$sections{"IMPLEMENTATION"}}) + { + print_code $i; + } + + clear_head(); + print_head + ("\n" . + "//\n" . + "// IMPLEMENTATION of inline functions (and needed classes)\n" . + "//\n\n"); + + print_inlines (@inline_order_public); + } + +clear_head(); +print_head ("\n" . + "//\n" . + "// IMPLEMENTATION of function templates\n" . + "//\n\n"); +foreach my $i (@public_templates) + { + print_funcdef $i; + } + +clear_head(); + +print OUT "\n#endif // ${incfile_base_macro}_$header_ext\n"; +close OUT; + +# +# Print "internal data structures" header file +# + +open(OUT, ">${outfile_base}_i.$header_ext") + || die "Cannot open ${outfile_base}_i.$header_ext for writing!"; +print OUT "// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*-\n\n"; +print OUT "#ifndef ${incfile_base_macro}_i_$header_ext\n" . + "#define ${incfile_base_macro}_i_$header_ext\n"; + +foreach my $i (grep { $_->{type} eq 'include' } + @{$sections{"IMPLEMENTATION"}}) + { + print_code $i; + } + +foreach my $i + ( (grep {$_->{type} eq 'classdef' && $_->{syntax} eq 'forwarddecl'} + @{$sections{"IMPLEMENTATION"}}), # first all forward declarations, + (grep {$_->{type} eq 'classdef' && $_->{syntax} ne 'forwarddecl'} + @{$sections{"IMPLEMENTATION"}}) ) # then all other class / type decls + { + print_classdecl ($i); + } + + +# XXX should we print #defines here? + +print_head ("\n" . + "//\n" . + "// IMPLEMENTATION of inline functions follows\n". + "//\n\n"); +print_inlines (@inline_order_private); + +clear_head(); +print_head ("\n" . + "//\n" . + "// IMPLEMENTATION of function templates\n" . + "//\n\n"); +foreach my $i (grep + { + $_->{type} eq 'function' && $_->{template} ne '' + && $_->{fully_specialized_template} eq '' + && ! defined $public_inline{$_} + && ! defined $private_inline{$_} + && ($_->{visibility} eq 'static' + || ($_->{class} ne '' + && ($classes{$_->{class}}->{section} ne 'INTERFACE' && + !defined $public_inline{$classes{$_->{class}}}))) + } @{$sections{"IMPLEMENTATION"}}) + { + print_funcdef $i; + } + +clear_head(); + +print OUT "\n#endif // ${incfile_base_macro}_i_$header_ext\n"; +close OUT; + +$doing_linenumbers = (! $opt_l); + +# +# Print implementation file(s) +# + +foreach my $part (keys %impl_parts) + { + my $filename = $outfile_base.($part eq '' ? '' : ('-' . $part)) . ".$source_ext"; + my $empty = 1; + #print "==> $filename\n"; + open(OUT, ">$filename") || die "Could not open $filename for writing!"; + print OUT "// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*-\n\n"; + print OUT "#include \"${public_base}.$header_ext\"\n" . + "#include \"${incfile_base}_i.$header_ext\"\n\n"; + + foreach my $i (grep {$_->{type} eq 'function' && $_->{class} eq '' + && $_->{static}} + grep {$_->{part_ext} eq $part} @{$sections{"IMPLEMENTATION"}}) + { + print_funcdecl $i; + } + + # Print unparsed code first -- make private inline functions see + # static variables + + foreach my $i (grep {$_->{part_ext} eq $part + && $_->{type} eq 'code'} + @{$sections{"IMPLEMENTATION"}}) + { + print_code $i; + $empty = 0; + } + + print_inlines (grep {$_->{part_ext} eq $part} @inline_order_unit); + + foreach my $i (grep {$_->{part_ext} eq $part + && $_->{type} eq 'function'} + @{$sections{"IMPLEMENTATION"}}) + { + next if $i->{template} ne '' + && $i->{fully_specialized_template} eq ''; + + print_funcdef $i; + $empty = 0; + } + + truncate OUT,0 if $empty && $opt_t; + close OUT; + } + + +exit 0; + +############################################################################# + +# +# Parser code. +# + +my $s_once; # Regexp for whitespace; the \001 stuff is for comments +my $s; # Zero or more whitespace +my $identifier; # Identifier +my $operator_name; # Operator name +my $paren_group; +my $paren_expr; +my $tparen_group; +my $template; # Template declaration tag +my $template_arg; # Template argument list + +my $lineno; # current line to be parsed +my $blockfile; # file that contains the currently pares block +my $blockstart; # first line of the current block +my $current_section; # current section +my $current_part; +my $current_part_ext; +my @ifstack; # stack of #if clauses + + +sub parse_init # Initialize parser variables. +{ + # Regexp for whitespace; the \001 stuff is for comments + $s_once = '(?:[\n\s]|\001[0-9]+\001)'; + + # Zero or more whitespace + $s = $s_once . '*'; + + # Identifier + $identifier = "(?:[A-Za-z_][A-Za-z_0-9]*)"; + + # Operator name + $operator_name = "(?:operator$s(?:" + .'(?:[~,]|[+\-*/%^&|!=<>]=?|[<>]{2}=?|[&|+\-]{2}|->\*?' + .'|\(\)|(?:new|delete)?'.$s.'\[\])'."|$identifier))"; + + + $paren_group = qr{ + \( + (?: + (?> [^()]+ ) # Non-parens without backtracking + | + (??{ $paren_group }) # Group with matching parens + )* + \) + }x; + + $paren_expr = qr{ (?> $paren_group | [^()]+ )* }x; + + # Template argument list -- similar to paren_group above + $tparen_group = qr { < (?: (?> [^<>]+ ) | (??{ $tparen_group }) )* > }x; + + # Template argument list + $template_arg = qr{ (?> $tparen_group) }x; + + # Template declaration tag + $template = qr{template$s$template_arg$s}; + +} + +sub match_e_opt +{ + my $tag = shift; + my $cp = ''; + + my $t = '\(\)&|,\{\}!-'; + my $orig_tag = $tag; + + while ($tag =~ /^\s*([$t]|(?:[^\s$t]+))\s*(.*?)$/) + { + my $r = $parts{$1}; + $cp .= defined $r ? $r : 0; + $tag = $2; + } + + my $match = eval $cp; + #print "TAG: $tag -> $cp = $match\n"; + if (!defined $match) + { + die "${ARGV}:$lineno: error: syntax error in tag '$tag'\n"; + } + + if (($verbose || $opt_d) && (!defined $match || !$match)) + { + print "Drop SECTION: [$orig_tag] from". + " file ${ARGV}\n"; + } + + return $match; +} + +sub parse_file +{ + $lineno = 0; + @ifstack = (); + + $current_section = "IMPLEMENTATION"; + $current_part = ""; + my $skip_to_next_section = 0; + + NEXTLINE: + while (1) + { +#print "PARSED: $_\n"; + $_ = ''; + $blockstart = $lineno + 1; + $blockfile = $ARGV; + + MORE: + while (1) + { + if (! read_more()) + { + last NEXTLINE; + } + + if (/^$s\/\/-[\s\n]*$/s) + { + handle_source_code (); + next NEXTLINE; + } + + if (s/^($s) + (?:(INTERFACE + | IMPLEMENTATION) + (?:$s \[ $s ([A-Za-z0-9_,\{\}!\s&|\(\)-]+) $s \] $s)? : ) + /$1/sx) + { + check_empty_ifstack(); + $skip_to_next_section = 0; + $current_section = $2; + if ($opt_e ne '' || $current_section eq "IMPLEMENTATION") + { + if (defined $3) + { + $current_part = $3; + if ($opt_e ne '') + { + $skip_to_next_section = !match_e_opt($current_part); + next NEXTLINE if $skip_to_next_section; + } + } + else + { + $current_part = ''; + } + } + else + { + if (defined $3 && $opt_h ne $3) + { + die "${ARGV}:${lineno}: all INTERFACE arguments and " + . "option -h must be consistent;" + if ($opt_h ne ''); + + $public_base = $3; + $opt_h = $3; + if ($opt_o eq '') + { + $headerfile_base = $opt_p . $public_base + } + } + } + handle_source_code (); + next NEXTLINE; + } + elsif ($skip_to_next_section) + { + next NEXTLINE; + } + + # Preprocessor directive? + if (/^$s\#/s) + { + while (/\\\n$/s) + { + last NEXTLINE if ! read_more(); + } + + handle_preproc(); + next NEXTLINE; + } + + next NEXTLINE if ignoring(); + + # Read until we can decide what we have: Read till next block end + # or semicolon. + if (/\{/) + { + # Have a block. + my $foo = $_; + do {} while ($foo =~ s/\{[^\{\}]*\}//sg); # kill blocks + if ($foo =~ /\{/) + { +#print "MORE: $foo\n"; + next MORE; # Still unfinished blocks. + } + } + elsif (! /;/) # no unclosed blocks & semicolon? + { + next MORE; + } + + # Type declaration? + if (/^$s(?:$template)?(enum|struct|class|typedef)/s) + { + my $syntax = $1; + + if (/^$s(?:$template)? + (?:enum|struct|class) + $s ($identifier (?:$s $template_arg)?) + $s (?::(?!:)|\{)/sx) + { + # Have a block -> this is a definition. + + my $name = $1; + + if (/^(.*)(\}.*)$/s) + { + my $class = { name => $name, + syntax => $syntax, + pretext => $1, + posttext => $2 }; +#print "CLASS " . $class->{name} . ">" .$class->{pretext} . "###" . $class->{posttext}; + handle_classdef ($class); + } + } + else + { + # No block or no name -- handle as declaration. + if (/^$s(?:$template)?(?:enum|struct|class)$s\{/s) + { + # no name but block -- make this a global variable decl. + handle_source_code (); + } + elsif (/^$s(?:$template)?(?:enum|struct|class)/s) + { + # no block -- this seems to be a forward + # decl. or a variable decl. + + if (/^$s(?:$template)?(?:enum|struct|class)$s + ($identifier) $s ;/sx) + { + my $class = { syntax => 'forwarddecl', + name => $1 }; + handle_classdef ($class); + } + else + { + handle_source_code (); + } + } + elsif (/^${s} typedef \b /sx) # It's a typedef + { + # strip off function args and array spec + my $l = $_; + $l =~ s/; $s $//sx; + $l =~ s/\([^\)]*\) (?:${s}const)? $s $//sx; + $l =~ s/(?: \[ [^\[]* \] $s | \) $s )+ $//sx; + $l =~ m/($identifier) $s $/sx; + + my $class = { syntax => 'typedef', + name => $1 }; + handle_classdef ($class); + } + else + { + die "${ARGV}:$lineno: Parse error"; + } + } + + next NEXTLINE; + } + + # Type declaration extension? + if (/^$s EXTENSION $s (?:struct|class) $s ($identifier) + $s (?::(?!:) $s ([^\{]*))?\{ (.*) \} $s ; $s $/sx) + { + my $super = $2; + my $name = $1; + my $string = $3; + + if (! exists $classes{$name}) + { + die "${ARGV}:$lineno: Class extension for undefined class " . + $name; + } + + # XXX XXX we should not handle line directives here -- + # this is the job of the output functions. However, as + # we don't generate a new codechunk for this extension, + # we just add the extension's line number here. + + if ($doing_linenumbers) + { + $classes{$name}->{pretext} .= + "\n#line " . $blockstart . " \"" . $ARGV . "\"\n"; + } + + my $txt = \($classes{$name}->{pretext}); + + if (defined $super) + { + if ($$txt =~ /^([^\{]*)/sx) + { + my $pre = $1; + if ($pre =~ /^.*:(?!:)(.*)$/sx) + { + $$txt =~ s/^$pre/$pre\n, $super/s; +# print "ADD super classes: , $super\n"; + } + else + { + $$txt =~ s/^$pre/$pre\n: $super/s; + } + } + } + + $classes{$name}->{pretext} .= "private:\n" . $string; + + next NEXTLINE; + } + + # Member function definition? + if (/^([^\{\(]*?) # pretext, maybe w template decl tag + \b ($identifier (?: $s :: $s $identifier)*) # class name + ($s $template_arg)? # optional class-template args + $s :: $s + ((?:$operator_name | (?: ~? $identifier )) # member name + (?:$s $template_arg)?) # optional member-template args + $s ( \( (?: [^\)] | \([^\)]*\) )* \) [^:\{=]* ) # arg list + ((?:\{|:.*\{).* | (?:$s = $s 0 $s ;))$/sx) # initializer ':' and body '{' or pure virtual + { + my ($pretext, $class, $templateargs, $name, $args, $posttext) + = ($1, $2, (defined $3 ? $3 : ''), $4, $5, $6); +#print "P<$pretext> C<$class> T<$templateargs> N<$name> A<$args> P<$posttext>\n"; + # Canonify operator names + $name =~ s/(?<=\w)(?:$s_once)+(?=\W)//gs; + $name =~ s/(?<=\W)(?:$s_once)+(?=\w)//gs; + $name =~ s/(?:$s_once)+/ /gs; + # Canonify class name + $class =~ s/$s//gs; + my $memberfunction = { class => $class, + name => $name, + templateargs => $templateargs, + pretext => $pretext, + args => $args, + posttext => $posttext }; + handle_function ($memberfunction); + next NEXTLINE; + } + + # Free function definition? + if (/^([^\{]*) # pretext, maybe w template decl tag + \b ($operator_name | $identifier) # function name + ($s $template_arg)? # optional template args + $s( \( $paren_expr \) [^:\{\(\)=]*) # arg list + (\{.*)$/sx) # body + { + my $function = { class => '', + name => $2, + templateargs => (defined $3 + ? $3 : ''), + pretext => $1, + args => $4, + posttext => $5 }; + handle_function ($function); + next NEXTLINE; + } + + handle_source_code (); + next NEXTLINE; + } + } + + if (! /^$s$/s) + { + $verbose && print "EOF: " . $_ . "\n"; + die "${blockfile}:$blockstart: Unexpected end of file in block starting here;"; + } + +} + +sub read_more () # Read one more line of code. Stow away + # comments and character constants +{ + # Get a line without comments. + while (1) + { + if (eof(INPUT)) # Reset line numbering. + { + check_empty_ifstack(); + $lineno = 0; + do + { + my $file; + return 0 unless $file = shift @ARGV; + $ARGV = $file; + open(INPUT, $ARGV) || die "Cannot open $ARGV for reading!"; + if ($opt_s) + { +# print "FILE: $ARGV\n"; + my $part_ext = ''; + if ($ARGV =~ /^(?:.*\/)?(.+)$/ && $1 =~ /(?:[^-]*)-(.*)\..*/) + { + $part_ext = $1; + } + $current_part_ext = $part_ext; + $impl_parts{$part_ext} = 1; +# print "PART: '$part_ext'\n"; + } + print "read file: '$ARGV'\n" if $verbose; + } + while(eof(INPUT)); + } + + $lineno++; + + my $line = ; + + if (! defined $line) + { + return 0; + } + + $_ .= $line; + + # Save comments and strings in @comments array. Save strings + # first to catch strings with comment-like contents. + my $number = @comments; + + # We don't touch strings in NEEDS[], neither #includes! Save now -- + # restore later. + my $saved = ''; + if (s/(^$s \# $s include.*$ + | NEEDS $s \[[^\]]* ) + /\003/sx) + { + $saved = $1; + } + + while (s,(\'(?:\\.|[^\']|\\[0-7]+)\'),\002$number\002,s) + { + push @comments, $1; + $number++; + } + +# while (s,(\"(?:[^\"]|(?<=\\)\")*\"),\002$number\002,s) + while (s,(\"(?:[^\\\"]|\\.)*\"),\002$number\002,s) + { + push @comments, $1; + $number++; + } + + if ($saved ne '') + { + s/\003/$saved/s; + } + + while (s|(//(?!-\s*\n).*)$|\001$number\001|m) # Do not match magic "//-" + { # The \001 signifies whitespace. + push @comments, $1; + $number++; + } + + while (s|(/\*.*\*/)|\001$number\001|s) + { + push @comments, $1; + $number++; + } + + if (! /\/\*/) + { + last; + } + } + + return 1; +} + +sub label_chunk +{ + my ($codechunk,$type) = @_; + + $codechunk->{type} = $type; + $codechunk->{section} = $current_section; + $codechunk->{string} = $_; + $codechunk->{part} = $current_part; + $codechunk->{part_ext} = $opt_s ? $current_part_ext : $current_part; + + $impl_parts{$current_part} = 1 unless $opt_s; + + $codechunk->{line} = $blockstart; + $codechunk->{file} = $ARGV; + $codechunk->{printed} = 0; + + push @{$sections{$current_section}}, $codechunk; +} + +sub ignoring +{ + foreach my $i (@ifstack) + { + if ($i->{value} == 1) + { + return 1; + } + } + + return 0; +} + +sub handle_preproc +{ +# if ($codeblock->{string} =~ /^$s\#\s*(if|endif|else|elif)/) +# { +# die "${ARGV}:${lineno}: Conditional compilation not supported;"; +# } + + if (/^$s\#\s*if\s+0${s}$/) + { + push @ifstack, { value => 1, file => ${ARGV}, line => $lineno }; + $verbose && print "IF 0: " . ignoring() . "\n"; + return; + } + elsif (@ifstack && /^$s\#\s*if(def|ndef)?\s/) + { + push @ifstack, { value => 0, file => ${ARGV}, line => $lineno }; + $verbose && print "IF: " . ignoring() . "\n"; + return if ignoring(); + } + elsif (@ifstack && /^$s\#\s*(else|elif)/) + { + my $ignoring = ignoring(); + my $i = pop @ifstack; + $i->{value} = -$i->{value}; + push @ifstack, $i; + $verbose && print "ELSE/ELIF: " . ignoring() . " ($ignoring)\n"; + return if $ignoring; + } + elsif (@ifstack && /^$s\#\s*endif/) + { + my $ignoring = pop @ifstack; + $verbose && print "ENDIF: " . ignoring() . "\n"; + return if ignoring() || $ignoring->{value}; + } + elsif (/^$s\#\s*include${s}([\"<][^\">]+[\">])/) + { + my $codeblock; + $codeblock->{name} = $1; + $codeblock->{inline} = 0; + + $includes{$codeblock->{name}} = $codeblock; + + label_chunk ($codeblock, "include"); + + $verbose && print "INCLUDE: " . $codeblock->{name} . "\n"; + return; + } + + # XXX: For now, treat preprocessor stuff besides #include, #if 0 as code. + handle_source_code (); +} + +sub dump_ifstack +{ + my $indent = ''; + foreach my $i (@ifstack) + { + print "$indent$i->{value}: $i->{file}:$i->{line}\n"; + $indent .= ' '; + } +} + +sub check_empty_ifstack +{ + if ($#ifstack >= 0) + { + my $i = pop @ifstack; + print STDERR "${ARGV}:${lineno}: missing endif for $i->{file}:$i->{line}\n"; + die; + $status = -1; + } +} + +sub handle_source_code +{ + return if /^[\s\n]*$/; + + my $codeblock = {}; + label_chunk ($codeblock, "code"); + + $verbose && print "UNKNOWN: " . $codeblock->{string}; +} + +sub handle_classdef +{ + my $class = $_[0]; + label_chunk ($class, "classdef"); + + $class->{funcs} = []; + + if ($class->{syntax} ne 'forwarddecl') + { + $classes{$class->{name}} = $class; + } + + $verbose && print "CLASSDEF: " . $class->{name} . " [" + . $class->{syntax} . "]\n"; +} + +sub handle_function +{ + my $func = $_[0]; + + $func->{purevirtual} = 0; + + if ($func->{class} ne '') + { + # Nested class hacks + if ($func->{class} =~ /::/ + && ! defined $classes{$func->{class}}) + { + # Define class along the way -- the dirty way. + my $class = { name => $func->{class}, + syntax => "class", + nested_class => 1 }; + my ($topclass, $rest) = split (/::/, $func->{class}); + my $save_sec = $current_section; + $current_section = $classes{$topclass}->{section}; + handle_classdef ($class); + $current_section = $save_sec; + } + + $func->{visibility} = "private"; + if (s/^($s)PRIVATE([\s\n])/$1$2/s) + { + $func->{visibility} = "private"; + $func->{pretext} =~ s|PRIVATE[ \t]*||s; + } + elsif (s/^($s)PUBLIC([\s\n])/$1$2/s) + { + $func->{visibility} = "public"; + $func->{pretext} =~ s|PUBLIC[ \t]*||s; + } + elsif (s/^($s)PROTECTED([\s\n])/$1$2/s) + { + $func->{visibility} = "protected"; + $func->{pretext} =~ s|PROTECTED[ \t]*||s; + } + elsif (s/^($s)IMPLEMENT([\s\n])/$1$2/s) + { + # Use a visibility attribute that is never used in adding + # declarations to classes in print_classdecl. + $func->{visibility} = "implementation_only"; + $func->{pretext} =~ s|IMPLEMENT[ \t]*||s; + } + + if ($func->{posttext} =~ s/$s=${s}0$s;$s$//s) + { + $func->{purevirtual} = 1; + } + + if ($func->{class} =~ /::/ + && $func->{visibility} ne "implementation_only") + { + die "${ARGV}:${lineno}: Limitation: Only predeclared members " . + "supported for nested classes. Use IMPLEMENT;"; + } + + if (! defined $classes{$func->{class}}) + { + die "${ARGV}:${lineno}: Class " . $func->{class} + . " has not been declared;"; + } + } + else + { + $func->{visibility} = "free"; + } + + # Interprete more type attributes. + $func->{inline} = 0; + $func->{always_inline} = 0; + $func->{static} = 0; + $func->{hide} = 0; + $func->{virtual} = 0; + $func->{explicit} = 0; + $func->{classtemplate} = ''; + $func->{funtemplate} = ''; + $func->{template} = ''; + $func->{fully_specialized_template} = ''; + while (1) + { + if (s/^($s)((?:$template)+)([\s\n])/$1$3/s) + { + my $match = $2; + my @specs = split(/(?<= \>)(?= $s template)/sx, $match, 3); + + if ($func->{class} eq '') # Free function? + { + $func->{funtemplate} = shift @specs; + } + else # Have a class + { + my $class = $classes{$func->{class}}; + my $istemplateclass = ($class->{pretext} =~ /^[^\{]*template/s); + + if ($istemplateclass) + { + $func->{classtemplate} = shift @specs; + $func->{funtemplate} = shift @specs if scalar @specs; + } + else # Not a class template + { + $func->{funtemplate} = shift @specs; + } + } + + die "${ARGV}:$lineno: Too many template specs" + if scalar @specs; + + $func->{template} = 'yes'; + $func->{fully_specialized_template} = 'yes' + if ($match =~ /^(?:${s}template$s<${s}>)+${s}$/s); + + $func->{pretext} =~ s/\Q$match//s; +# $func->{pretext} =~ s|$template[ \t]*||s; + next; + } + + if (s/^($s)inline([\s\n])/$1$2/si) # "inline" is case-insensitive. + { + $func->{inline} = 1 if $doing_inlines + || $func->{fully_specialized_template} ne ''; + $func->{pretext} =~ s|inline[ \t]*||si; + @{$func->{needs}} = (); + while (1) + { + if (s/^($s)NEEDS\s*\[([^\]]+)\]([\s\n])/$1$3/s) + { + @{$func->{needs}} = split (/\s*,\s*/, $2); + # Delete NEEDS directive, but keep newlines + while ($func->{pretext} =~ + s|NEEDS \s* \[ ( (?:[^\n\]]*\n)* ) + [^\n\]]+ \n (\n*) + [^\n\]]* \] + |NEEDS[$1\n$2\]|sx) {} + $func->{pretext} =~ s|NEEDS\s*\[ (\n*) [^\n\]]*\]|$1|sx; + next; + } + if (s/^($s)NOEXPORT([\s\n])/$1$2/si) + { + $func->{hide} = 1; + $func->{pretext} =~ s|NOEXPORT[ \t]*||s; + next; + } + if (s/^($s)ALWAYS_INLINE([\s\n])/$1$2/si) + { + $func->{inline} = 1; + $func->{always_inline} = 1; + $func->{pretext} =~ s|ALWAYS_INLINE[ \t]*||s; + next; + } + last; + } + + # Reset inline data if inline handling was not enabled by -i + # or ALWAYS_INLINE. + if (! $func->{inline}) + { + undef $func->{needs}; + } + next; + } + + + if (s/^($s)static([\s\n])/$1$2/s) + { + $func->{static} = 1; + $func->{pretext} =~ s/static[ \t]*//s; + + if ($func->{class} eq '') + { + $func->{visibility} = "static"; + $func->{hide} = 1; + } + + next; + } + + if (s/^($s)IMPLEMENT([\s\n])/$1$2/s) + { + $func->{pretext} =~ s/IMPLEMENT[ \t]*//s; + + if ($func->{class} eq '') + { + $func->{visibility} = "implementation_only"; + } + + next; + } + + if (s/^($s)explicit([\s\n])/$1$2/s) + { + $func->{explicit} = 1; + $func->{pretext} =~ s|explicit[ \t]*||s; + next; + } + + if (s/^($s)virtual([\s\n])/$1$2/s) + { + $func->{virtual} = 1; + $func->{pretext} =~ s|virtual[ \t]*||s; + next; + } + + if (/^($s)(PRIVATE|PUBLIC|PROTECTED)([\s\n])/) + { + die "${blockfile}:$blockstart: only one visibility attribute allowed at start of declaration;"; + } + + last; + } + + label_chunk ($func, "function"); + + if ($current_section eq 'INTERFACE') + { + die "${ARGV}:${lineno}: Function " . $func->{name} + . " in INTERFACE section;"; + } + + push @{$classes{$func->{class}}->{funcs}}, $func; + + $verbose && print "FUNC: " . ($func->{class} ne '' + ? ($func->{class} . "::") + : "") + . $func->{name} + . ($func->{classtemplate} ne '' + ? " T: " . $func->{classtemplate} : "") + . ($func->{funtemplate} ne '' + ? " M: " . $func->{funtemplate} : "") + . ($func->{fully_specialized_template} ne '' + ? " FULLY_SPEC" : "") + . "\n"; +} + +############################################################################# + +# +# Printing code. +# + +my $saved_head; +my $saved_indent; + +sub print_head # Save header. Print it only if a + # print_expand() follows +{ + $saved_head .= $_[0]; + $saved_indent = $print_indent; +} + +sub clear_head +{ + $saved_head = ''; +} + +sub print_expand($) # Expands comments and prints to OUT. +{ + my $str = $_[0]; + + if ($saved_head ne '') + { + local $print_indent = $saved_indent; + my $str = $saved_head; + $saved_head = ''; + + print_expand $str; # Recurse. + } + + $str =~ s/\n(?:[ \t]*\n)+/\n\n/sg if ! $doing_linenumbers; + + while ( $str =~ s/([\001\002])([0-9]+)\1/$comments[$2]/sg ) + {} + + if ($print_indent) + { + my $istr = " " x $print_indent; + $str =~ s/^/$istr/mg; + } + + print OUT $str; +} + +sub print_lineno($) +{ + return if ! $doing_linenumbers; + + my $object = $_[0]; + + print_expand ''; # print headers we accumulated + print OUT "#line " . $object->{line} . " \"" . $object->{file} . "\"\n"; +} + +sub print_lineno_sans_empty_lines($) +{ + return if ! $doing_linenumbers; + + my $object = $_[0]; + + my $start_of_code = $object->{string}; + $start_of_code =~ s/^([\s\n]+).*$/$1/s; + + my @startcomments = split /\n/, " $start_of_code "; + + print OUT "#line " . ($object->{line} + @startcomments - 1) + . " \"" . $object->{file} . "\"\n"; +} + +sub weedout_whitespace # Delete whitespace except on lines w/comments +{ + my $str = $_[0]; + + $str =~ s/^[\s\n]+//s; + + if (! $doing_linenumbers) # more cosmetic changes if we do not + { # have to be correct line-number-wise + my @lines = split /\n/, $str; + my $foundcode = 0; + $str = ''; + + foreach my $line (@lines) + { + $line =~ s/^\s+//; + $line =~ s/\s+$//; + + if ($line =~ /\001/ || $line =~ /^\s*$/) + { + $line .= "\n"; + } + else + { + if (! $foundcode) + { + $foundcode = 1; + + # Found something like code: Remove trailing whitespace + # from $str, + $str =~ s/\s+$//s; + $str .= "\n" if $str ne ''; + } + + $line =~ s/\s+/ /g; + $line .= ' '; + } + $str .= $line; + } + } + + $str =~ s/\s+$//; + + return $str; +} + +sub func_prototype($) # Return a function declaration from + # func head. +{ + my $func = $_[0]; + my $pretext = $func->{pretext}; + + if ($func->{inline}) + { + $pretext =~ s/^($s)/${1}inline /s; + } + + if ($func->{explicit}) + { + $pretext =~ s/^($s)/${1}explicit /s; + } + + if ($func->{static}) + { + $pretext =~ s/^($s)/${1}static /s; + } + + if ($func->{virtual}) + { + $pretext =~ s/^($s)/${1}virtual /s; + } + + if ($func->{funtemplate} ne '') + { + $pretext =~ s/^($s)/${1}$func->{funtemplate} /s; + } + + my $func_header = weedout_whitespace($pretext . + $func->{name} . $func->{args}); + + # Insert ; at the correct place, that is, before any comments. + my $e = $func->{purevirtual} ? ' = 0' : ''; + $func_header =~ s/($s)$/$e;$1/s; + + return $func_header; +} + +sub print_funcdecl($) +{ + my $function = $_[0]; + + if ($function->{visibility} ne "implementation_only") + { + print_expand "\n"; + print_lineno_sans_empty_lines $function; + print_expand func_prototype($function) . "\n"; + } + + # Handle inlines. + if ($function->{inline}) + { + handle_inline ($function); + } +} + +sub print_classdecl($) +{ + my $class = $_[0]; + return if check_if_printed ($class); + + print_lineno $class; + + if (defined $class->{nested_class}) + { + # (This will not actually print anything, but do other processing.) + foreach my $function (@{$class->{funcs}}) + { + die "Assert failed" + if $function->{visibility} ne "implementation_only"; + print_funcdecl $function; + } + } + elsif ($class->{syntax} =~ /^(?:struct|class)$/) + { + if (! $doing_inlines) + { + $class->{pretext} =~ s/\binline\b[ \t]*//g; + } + + print_expand $class->{pretext}; + + print_head "\npublic:"; + $print_indent += 2; + foreach my $function (grep {$_->{visibility} eq "public"} + @{$class->{funcs}}) + { + print_funcdecl $function; + } + $print_indent -= 2; + clear_head(); + print_head "\nprotected:"; + $print_indent += 2; + foreach my $function (grep {$_->{visibility} eq "protected"} + @{$class->{funcs}}) + { + print_funcdecl $function; + } + $print_indent -= 2; + clear_head(); + print_head "\nprivate:"; + $print_indent += 2; + foreach my $function (grep {$_->{visibility} eq "private"} + @{$class->{funcs}}) + { + print_funcdecl $function; + } + $print_indent -= 2; + clear_head(); + + # Also, don't forget to "print" already-declared functions. + # (This will not actually print anything, but do other processing.) + foreach my $function (grep {$_->{visibility} eq "implementation_only"} + @{$class->{funcs}}) + { + print_funcdecl $function; + } + + print_expand $class->{posttext}; + } + else + { + print_expand $class->{string}; + } +} + +my $parengroup; +sub print_funcdef($) +{ + my $function = $_[0]; + return if $function->{purevirtual}; + return if check_if_printed ($function); + + my $pretext = $function->{pretext}; + + if ($function->{inline}) + { + if ($function->{always_inline}) + { + $pretext =~ s/^($s)/${1}ALWAYS_INLINE /s; + } + $pretext =~ s/^($s)/${1}inline /s; + } + + if ($function->{static} && $function->{class} eq '') + { + $pretext =~ s/^($s)/${1}static /s; + } + + if ($function->{funtemplate} ne '') + { + $pretext =~ s/^($s)/${1}$function->{funtemplate} /s; + } + + if ($function->{classtemplate} ne '') + { + $pretext =~ s/^($s)/${1}$function->{classtemplate} /s; + } + + # Remove default arguments from argument list + my $args = $function->{args}; + $parengroup = qr{ # Matches correctly-nested groups of parens + \( + (?: + (?> [^()]* ) # Non-parens without backtracking + | + (??{ $parengroup }) # Backtrack: Group with parens + )* + \) + }x; + my $expr = qr{ [^(),]* (?:$parengroup)? [^(),]* }x; + $args =~ s/$s = $expr//gx; + + print_expand "\n"; + print_lineno $function; + print_expand $pretext + . ($function->{class} ne '' + ? $function->{class} . $function->{templateargs} + . "::" . $function->{name} + : $function->{name} . $function->{templateargs}) + . $args . $function->{posttext}; +} + +sub print_code($) +{ + my $codeblock = $_[0]; + return if check_if_printed ($codeblock); + print_lineno $codeblock; + print_expand $codeblock->{string}; +} + +sub check_if_printed +{ + my $codeblock = $_[0]; + return 1 if $codeblock->{printed}; + $codeblock->{printed} = 1; + return 0; +} + +############################################################################# + +# +# Inline-function bookkeeping. +# + +sub lookup_by_name # Return (list of) item(s) matching name. +{ + my ($item, $context) = @_; + + # Is it a class name? + if (defined $classes{$item}) + { + return $classes{$item}; + } + + # Is it an include file? + if (defined $includes{$item}) + { + $includes{$item}->{inline} = 1; + return $includes{$item}; + } + + # Must be a function name! + my ($classname, $funcname); + + if ($item =~ /::/) + { + ($classname, $funcname) = split /::/, $item; + } + else + { + ($classname, $funcname) = ('' , $item); + } + + my @grepresult = grep {$_->{name} eq $funcname && $_->{inline}} + @{$classes{$classname}->{funcs}}; + + return shift @grepresult + if (scalar @grepresult == 1); + + if (scalar @grepresult == 0) + { + my @xgrepresult = grep {$_->{name} eq $funcname} + @{$classes{$classname}->{funcs}}; + die $context->{file} . ":" . $context->{line} . ": Cannot find $item;" + if (scalar @xgrepresult == 0); + $wno_inline && print STDERR $context->{file} . ":" . $context->{line} . + ": warning: Cannot find inline code ". + "for $item;\n"; + } + + return @grepresult; # Return list of matching function names. +} + +# Check if Function $function can already see Object $item in its context. +sub inline_known +{ + my ($item, $function) = @_; + + if ($item->{type} eq "function" + && $item->{hide} + && ! $function->{hide}) + { + die $function->{file} . ":" . $function->{line} . + ": Nonhidden function " . funcname($function) . + " depends on hidden function " . funcname($item) . " (" . + ($item->{visibility} eq 'static' ? "static" : "NOEXPORT") . ")"; + } + + return exists $public_inline{$item} + || (($function->{visibility} eq 'private' + || ($function->{class} ne '' + && $classes{$function->{class}}->{section} eq "IMPLEMENTATION")) + && exists $private_inline{$item}) + || ($function->{hide} + && exists $unit_inline{$item}); +} + +# Put inline function $1 and all its dependencies (given by NEEDS +# directives) into @inline_order_[public/private/unit], depending on +# visibility of $1. Function handle_inline is called when printing +# inline-function declarations, so the sequence of handle_inline calls +# is determined by declaration-printing order. +sub handle_inline +{ + my $function = $_[0]; + my $class = $function->{class}; + my @needed = (); + + $verbose && + print "INLINE " . funcname($function) . " NEEDS "; + + # Add all needed items, then add my own name as well as my class + # name for good measure. + foreach my $item (@{$function->{needs}}) + { + push @needed, lookup_by_name ($item, $function); + } + + push @needed, $function; + unshift @needed, lookup_by_name ($class, $function) + if ($class ne ''); + + NEEDEDLOOP: + while (@needed) + { + my $object = $needed[0]; + + if (inline_known ($object, $function)) + { + shift @needed; + next; + } + + # Check for further dependencies. + my @moreneeded = (); + + if ($object->{type} eq "function" && $object->{class} ne '') + { + my $class = lookup_by_name ($object->{class}, $object); + push @moreneeded, $class; + } + + if (defined $object->{needs}) + { + foreach my $item (@{$object->{needs}}) + { + my $o = lookup_by_name ($item, $object); + next if ! ref $o; # Skip referenced but noninline objects + push @moreneeded, $o; + } + } + + # Check if we have everything that's needed for $item. + foreach my $i (@moreneeded) + { + if (inline_known ($i, $function)) + { + next; + } + + if ($i == $function) # Function depends on itself! + { + my $callstack = " " . funcname ($function) . "\n";; + my $prev = $function; + push @needed, $function; + foreach my $j (@needed) + { + # $j is not part of call stack if it does not need $prev + next if ! grep {lookup_by_name ($_, $object) == $prev} + @{$j->{needs}}; + $callstack .= " " . funcname ($j) . "\n"; + $prev = $j; + last if $j == $function; + } + + die $object->{file} . ":" . $object->{line} . ": Function " . + funcname ($object) . " NEEDS " . funcname ($i) . + ", which circularly depends on this function:\n" . + $callstack; + } + + unshift @needed, $i; + next NEEDEDLOOP; + } + + $verbose && print &funcname ($object) . " "; + + if ($function->{hide}) + { + $unit_inline{$object} = 1; + push @inline_order_unit, $object; + } + elsif ($function->{visibility} eq 'private' + || ($class ne '' + && $classes{$class}->{section} eq "IMPLEMENTATION")) + { + $private_inline{$object} = 1; + push @inline_order_private, $object; + } + else + { + $public_inline{$object} = 1; + push @inline_order_public, $object; + } + + shift @needed; + } + + $verbose && print "\n"; +} + +sub print_inlines +{ + foreach my $object (grep {$_->{type} eq "classdef"} @_) + { + if ($object->{section} ne 'INTERFACE') + { + print_classdecl $object; + } + } + + foreach my $object (grep {$_->{type} eq "function"} @_) + { + print_funcdef $object; + } +} + +###################################################################### +# +# Utilities +# +sub funcname +{ + my $function = $_[0]; + + return ($function->{class} ? ($function->{class} . "::") : "") + . $function->{name}; +} diff --git a/kernel/fiasco/tool/preprocess/test/Makefile b/kernel/fiasco/tool/preprocess/test/Makefile new file mode 100644 index 00000000..652866c6 --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/Makefile @@ -0,0 +1,134 @@ +# scan the L4 global configuration file +L4DIR ?= ../../.. +#include $(L4DIR)/mk/Makeconf + +TOOL = ../src/preprocess + +all:: test + +ALL_TESTS = $(TOOL_TESTS) +TOOL_TESTS = mapping mapping_inline random random_inline extern_c static \ + noinline explicit operator template template_inline c-preproc \ + inline inline_noinline \ + parser parser_noinline \ + multifile variable line line_not line_nh interface comment_in_string \ + default_args drop_single1 drop_single2 drop_single3 drop_multi1 \ + drop_multi2 + +mapping_inline_src = mapping +mapping_inline_flags = -i + +random_inline_src = random +random_inline_flags = -i + +static_flags = -i + +inline_flags = -i + +inline_noinline_src = inline +inline_noinline_flags = + +noinline_flags = -i + +template_inline_src = template +template_inline_flags = -i + +parser_flags = -i + +parser_noinline_src = parser +parser_noinline_flags = + +multifile_src = multifile1 multifile2 +multifile_flags = -i +multifile_extra = multifile-part1.cc multifile-part2.cc + +line_not_src = line +line_not_flags = -l + +line_nh_src = line +line_nh_flags = -L + +interface_missing = interface.h +interface_extra = interfacepublic.h + +drop_single1_src = dropsection +drop_single1_flags = -s -e "bax" + +drop_single2_src = dropsection +drop_single2_flags = -s -e "bax ixbix" + +drop_single3_src = dropsection +drop_single3_flags = -s -e "bax aba" + +drop_multi1_src = dropsection dropsection-ext +drop_multi1_flags = -s -e "bax aba" +drop_multi1_extra = drop_multi1-ext.cc + +drop_multi2_src = dropsection dropsection-ext +drop_multi2_flags = -s -e "bax aba ext" +drop_multi2_extra = drop_multi2-ext.cc + +ifdef_src = ifdef +ifdef_flags = -s -e "true" + +ifdef1_src = ifdef1 +ifdef1_flags = -s -e "true" +ifdef1_extra = ifdef1-more.cpp + +random.cpp: combine.pl + perl $< > $@.new + mv $@.new $@ + +clean:: + rm -f random.cpp + +test_rules: Makefile + rm -f $@.new + for test in $(TOOL_TESTS); \ + do \ + echo "ifndef $${test}_src" >> $@.new; \ + echo "$${test}_src = $${test}" >> $@.new; \ + echo "endif" >> $@.new; \ + echo "ifndef $${test}_flags" >> $@.new; \ + echo "$${test}_flags = " >> $@.new; \ + echo "endif" >> $@.new; \ + echo "$${test}.cc: \$$(addsuffix .cpp, \$$($${test}_src)) \$$(TOOL); \$$(TOOL) \$$($${test}_flags) -c $${test} \$$(filter-out \$$(TOOL), \$$^)" >> $@.new; \ + done + mv $@.new $@ + +include test_rules + +clean:: + rm -f $(addsuffix .cc, $(TOOL_TESTS)) \ + $(addsuffix .h, $(TOOL_TESTS)) \ + $(addsuffix _i.h, $(TOOL_TESTS)) + +.PHONY: test +test: $(addsuffix .t.ok, $(ALL_TESTS)) + +%.t.ok: %.cc + @echo -n "Running test $* ... " +ifeq ($(RECREATE_OUTPUT),1) + @cp $(filter-out $($*_missing),$*.h $*_i.h $*.cc) $($*_extra) verify/ +endif + @for i in $(filter-out $($*_missing),$*.h $*_i.h $*.cc) $($*_extra); \ + do \ + diff -u verify $$i || exit 1; \ + done + @echo "OK" + @touch $@ + +.PHONY: init +init: + $(MAKE) test RECREATE_OUTPUT=1 + +install: + @echo Not installing tests. + +clean:: + $(RM) $(ALL) $(OBJS) *.t.ok + +cleanall:: clean + $(RM) *~ .*.d test_rules + +#include $(DEPS) diff --git a/kernel/fiasco/tool/preprocess/test/c-preproc.cpp b/kernel/fiasco/tool/preprocess/test/c-preproc.cpp new file mode 100644 index 00000000..9ee72b76 --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/c-preproc.cpp @@ -0,0 +1,19 @@ +INTERFACE: + +IMPLEMENTATION: + +// set CS (missing from OSKIT) +#define set_cs(cs) \ + asm volatile \ + ("ljmp %0,$1f \n1:" \ + : : "i" (cs)); + +void +function (void) +{ +#if 1 + bar (); +#else + foo (); +#endif +} diff --git a/kernel/fiasco/tool/preprocess/test/combine.pl b/kernel/fiasco/tool/preprocess/test/combine.pl new file mode 100644 index 00000000..786ab4d3 --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/combine.pl @@ -0,0 +1,57 @@ +#!/usr/bin/perl -w + +print ' +INTERFACE: + +#include "bar.h" + +class Baz; + +class Foo : public Bar +{ + // DATA + int d_data; + Baz* d_baz; +}; + +IMPLEMENTATION: + +#include "yes.h" +#include + +class Rambo +{ +}; + +// Try combinations of {PUBLIC|PROTECTED|PRIVATE|} {static|} +// {inline|INLINE|inline NEEDS[]|INLINE NEEDS[]} {virtual|} + +'; + +$count = 0; + +foreach my $class ("Foo", "") + { + foreach my $public ("PUBLIC", "PROTECTED", "PRIVATE", "") + { + foreach my $static ("static", "") + { + foreach my $inline ("inline", "INLINE", + "inline NEEDS [Rambo,\"yes.h\"]", + "INLINE NEEDS[Rambo, \"yes.h\"]", "") + { + foreach my $virtual ("virtual", "") + { + next if ($public ne '') && ($class eq ''); + next if ($virtual ne '') && (($static ne '') + || ($class eq '')); + print "$public $virtual $static $inline\n"; + print "void "; + print "${class}::" if ($class ne ''); + print "function" . $count++; + print "() {}\n\n"; + } + } + } + } + } diff --git a/kernel/fiasco/tool/preprocess/test/comment_in_string.cpp b/kernel/fiasco/tool/preprocess/test/comment_in_string.cpp new file mode 100644 index 00000000..adddf931 --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/comment_in_string.cpp @@ -0,0 +1,23 @@ +INTERFACE: + +IMPLEMENTATION: + +int foo(char *s); + +void irq_init(unsigned char master_base, unsigned char slave_base) +{ + if (!(foo(" -vmware")) + { + foo("outb_p(MASTER_OCW, 0xfb); // unmask irq2"); + } + else + { + foo("using normal pic mode \n"); + } +} + +void bar() +{ + foo ("if (0) {"); + foo ("} // if(0)"); +} diff --git a/kernel/fiasco/tool/preprocess/test/default_args.cpp b/kernel/fiasco/tool/preprocess/test/default_args.cpp new file mode 100644 index 00000000..f637dcf0 --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/default_args.cpp @@ -0,0 +1,32 @@ +#include + +IMPLEMENTATION: + +template +std::vector +vec(T f1 = T(), T f2 = T(), T f3 = T(), + T f4 = T(), T f5 = T(), T f6 = T()) +{ + std::vector v; + if (f1 != T()) { + v.push_back (f1); + if (f2 != T()) { + v.push_back (f2); + if (f3 != T()) { + v.push_back (f3); + if (f4 != T()) { + v.push_back (f4); + if (f5 != T()) { + v.push_back (f5); + if (f6 != T()) { + v.push_back (f6); + }}}}}} + return v; +} + +extern "C" +void +disasm_bytes(char *buffer, unsigned len, unsigned va, unsigned task, + int show_symbols, int show_intel_syntax, + int (*peek_task)(unsigned addr, unsigned task), + const char* (*get_symbol)(unsigned addr, unsigned task)) WEAK; diff --git a/kernel/fiasco/tool/preprocess/test/dropsection-ext.cpp b/kernel/fiasco/tool/preprocess/test/dropsection-ext.cpp new file mode 100644 index 00000000..3d103f9e --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/dropsection-ext.cpp @@ -0,0 +1,22 @@ +INTERFACE [ext]: + +EXTENSION class Gen_foo : public Gen_bar +{ +public: + int extra_var; +}; + +EXTENSION class Gen_foo_ext : public Gen_baz +{ +private: + char *extension; +}; + +IMPLEMENTATION [ext]: + +PRIVATE int +Gen_foo::do_something_private() +{ + // just do it +} + diff --git a/kernel/fiasco/tool/preprocess/test/dropsection.cpp b/kernel/fiasco/tool/preprocess/test/dropsection.cpp new file mode 100644 index 00000000..6ab1039b --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/dropsection.cpp @@ -0,0 +1,60 @@ +INTERFACE: + +class Gen_foo +{ +public: + int baz; + +protected: + int foo( int ); + +}; + +class Gen_foo_ext : private Gen_foo, public Ixdebix +{ +protected: + unsigned stuff; +}; + +IMPLEMENTATION: + +PUBLIC inline void +Gen_foo::bar( unsigned x ) +{ + // do soemthing with x; +} + +PUBLIC void +Gen_foo_ext::test() +{ + // the test +} + +IMPLEMENTATION [ixbix-bax]: + +IMPLEMENT int +Gen_foo::foo( int y ) +{ + // do something strange with y + bar(y); + return y; +} + +IMPLEMENTATION [aba-bax]: + +IMPLEMENT int +Gen_foo::foo( int y ) +{ + // just return y + return y; +} + +IMPLEMENTATION [{!bax,!ixbix}]: + +PUBLIC int +Gen_foo::tust( int y ) +{ + // just return y + return y; +} + diff --git a/kernel/fiasco/tool/preprocess/test/explicit.cpp b/kernel/fiasco/tool/preprocess/test/explicit.cpp new file mode 100644 index 00000000..3f5b1d2e --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/explicit.cpp @@ -0,0 +1,11 @@ +INTERFACE: + +class Foo +{ +}; + +IMPLEMENTATION: + +PUBLIC explicit +Foo::Foo (int bar) +{} diff --git a/kernel/fiasco/tool/preprocess/test/extern_c.cpp b/kernel/fiasco/tool/preprocess/test/extern_c.cpp new file mode 100644 index 00000000..7edebff8 --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/extern_c.cpp @@ -0,0 +1,8 @@ +INTERFACE: + +IMPLEMENTATION: + +extern "C" +{ + extern char _mappings_1, _mappings_end_1; +} diff --git a/kernel/fiasco/tool/preprocess/test/inline.cpp b/kernel/fiasco/tool/preprocess/test/inline.cpp new file mode 100644 index 00000000..73da32fd --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/inline.cpp @@ -0,0 +1,74 @@ +INTERFACE: + +class Foo +{ +}; + +class Bar +{ +}; + +IMPLEMENTATION: + +// Test dependency-chain resolver + +class Frob +{ +}; + +inline +bool +Frob::private_func() +{ +} + +inline +bool +Foo::private_func() +{ +} + +inline +bool +Bar::private_func() +{ +} + +inline NEEDS [Foo::private_func, Bar::private_func] +void +Bar::another_private_func() +{ +} + +PUBLIC inline NEEDS [Bar::another_private_func, Frob::private_func] +void +Bar::public_func() +{ +} + +// This inline funtion is public only because it is needed by an +// extern-"C" function. So we do not want to export it. +PUBLIC inline NOEXPORT +void +Foo::bar() +{ + +} + +// Try both NOEXPORT and NEEDED. +PUBLIC inline NOEXPORT NEEDS[Foo::private_func] +void +Foo::baz() +{ +} + +extern "C" +void function (Foo* f) +{ + f->bar(); +} + +template inline void* xcast(T* t) +{ + return (void*) t; +} diff --git a/kernel/fiasco/tool/preprocess/test/interface.cpp b/kernel/fiasco/tool/preprocess/test/interface.cpp new file mode 100644 index 00000000..3e5c037c --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/interface.cpp @@ -0,0 +1,15 @@ +INTERFACE [interfacepublic]: + +// This is class Foo. +class Foo +{ +}; + +IMPLEMENTATION: + +PUBLIC +void +Foo::func1() +{ + +} diff --git a/kernel/fiasco/tool/preprocess/test/line.cpp b/kernel/fiasco/tool/preprocess/test/line.cpp new file mode 100644 index 00000000..60c01257 --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/line.cpp @@ -0,0 +1,20 @@ +INTERFACE: + +// This is class Foo. +class Foo +{ +}; + +IMPLEMENTATION: + +// A long, multiline comment in front of this function definition. +// Also, a lot of specifiers that need to be handled. + +PUBLIC +inline +static +void +Foo::func1() +{ + +} diff --git a/kernel/fiasco/tool/preprocess/test/mapping.cpp b/kernel/fiasco/tool/preprocess/test/mapping.cpp new file mode 100644 index 00000000..c8fc7bff --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/mapping.cpp @@ -0,0 +1,784 @@ +INTERFACE: + +#include // for vm_offset_t, vm_size_t +#include "space.h" // for space_index_t + +enum mapping_type_t { Map_mem = 0, Map_io }; + +class mapping_tree_t; // forward decls +struct mapping_s; + +// +// class mapping_t +// +class mapping_t +{ + friend class mapdb_t; + friend class mapping_tree_t; + friend class jdb; + + // CREATORS + mapping_t(const mapping_t&); // this constructor is undefined. + + // DATA + char _data[5]; +} __attribute__((packed)); + +class kmem_slab_t; +struct physframe_data; + +// +// class mapdb_t: The mapping database +// +class mapdb_t +{ + friend class jdb; + +public: + enum { Size_factor = 4, + Size_id_max = 8 /* can be up to 15 (4 bits) */ }; + +private: + // DATA + physframe_data *physframe; + kmem_slab_t *allocator_for_treesize[Size_id_max + 1]; +}; + +IMPLEMENTATION: + +// The mapping database. + +// This implementation encodes mapping trees in very compact arrays of +// fixed sizes, prefixed by a tree header (mapping_tree_t). Array +// sizes can vary from 4 mappings to 4<<15 mappings. For each size, +// we set up a slab allocator. To grow or shrink the size of an +// array, we have to allocate a larger or smaller tree from the +// corresponding allocator and then copy the array elements. +// +// The array elements (mapping_t) contain a tree depth element. This +// depth and the relative position in the array is all information we +// need to derive tree structure information. Here is an example: +// +// array +// element depth +// number value comment +// -------------------------- +// 0 0 Sigma0 mapping +// 1 1 child of element #0 with depth 0 +// 2 2 child of element #1 with depth 1 +// 3 2 child of element #1 with depth 1 +// 4 3 child of element #3 with depth 2 +// 5 2 child of element #1 with depth 1 +// 6 3 child of element #5 with depth 2 +// 7 1 child of element #0 with depth 0 +// +// This array is a pre-order encoding of the following tree: +// +// 0 +// / \ +// 1 7 +// / | \ +// 2 3 5 +// | | +// 4 6 + +// IDEAS for enhancing this implementation: + +// We often have to find a tree header corresponding to a mapping. +// Currently, we do this by iterating backwards over the array +// containing the mappings until we find the Sigma0 mapping, from +// whose address we can compute the address of the tree header. If +// this becomes a problem, we could add one more byte to the mappings +// with a hint (negative array offset) where to find the sigma0 +// mapping. (If the hint value overflows, just iterate using the hint +// value of the mapping we find with the first hint value.) Another +// idea (from Adam) would be to just look up the tree header by using +// the physical address from the page-table lookup, but we would need +// to change the interface of the mapping database for that (pass in +// the physical address at all times), or we would have to include the +// physical address (or just the address of the tree header) in the +// mapdb_t-user-visible mapping_t (which could be different from the +// internal tree representation). (XXX: Implementing one of these +// ideas is probably worthwile doing!) + +// Instead of copying whole trees around when they grow or shrink a +// lot, or copying parts of trees when inserting an element, we could +// give up the array representation and add a "next" pointer to the +// elements -- that is, keep the tree of mappings in a +// pre-order-encoded singly-linked list (credits to: Christan Szmajda +// and Adam Wiggins). 24 bits would probably be enough to encode that +// pointer. Disadvantages: Mapping entries would be larger, and the +// cache-friendly space-locality of tree entries would be lost. + +// The current handling of superpages sucks rocks both in this module +// and in our user, ipc_map.cc. We could support multiple page sizes +// by not using a physframe[] array only for the largest page size. +// (Entries of that array point to the top-level mappings -- sigma0 +// mappings.) Mapping-tree entries would then either be regular +// mappings or pointers to an array of mappings of the next-smaller +// size. (credits: Christan Szmajda) +// +// physframe[] +// ------------------------------- +// | | | | | | | | | | | | | | | | array of ptr to 4M mapping_tree_t's +// ---|--------------------------- +// | +// v a mapping_tree_t +// --------------- +// | | tree header +// |-------------| +// | | mapping_t *or* ptr to array of ptr to 4K trees +// | | e.g. +// | ----------------| +// | | v array of ptr to 4M mapping_tree_t's +// --------------- ------------------------------- +// | | | | | | | | | | | | | | | | +// ---|--------------------------- +// | +// v a mapping_tree_t +// --------------- +// | | tree header +// |-------------| +// | | mapping_t +// | | +// | | +// | | +// --------------- +//- + +#include +#include + +#ifndef offsetof // should be defined in stddef.h, but isn't +#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) +#endif + +// For implementation of mapping_t functions, we need mapping_tree_t. + +// +// class mapping_tree_t +// +class mapping_tree_t +{ + friend class mapping_t; + friend class mapdb_t; + friend class jdb; + + // DATA + unsigned _count: 16; + unsigned _size_id: 4; + unsigned _empty_count: 11; + unsigned _unused: 1; // make this 32 bits to avoid a compiler bug + + mapping_t _mappings[0] __attribute__((packed)); + +} __attribute__((packed)); + +// public routines with inline implementations +inline +unsigned +mapping_tree_t::number_of_entries() const +{ + return mapdb_t::Size_factor << _size_id; +} + +inline +mapping_t * +mapping_tree_t::mappings() +{ + return & _mappings[0]; +} + +// Define (otherwise private) stuff needed by public inline +// functions. + +enum mapping_depth_t +{ + Depth_sigma0_mapping = 0, Depth_max = 253, + Depth_empty = 254, Depth_end = 255 +}; + +struct mapping_s +{ + unsigned space:11; + unsigned size:1; + unsigned address:20; + mapping_depth_t depth:8; + unsigned do_not_touch: 24; // make this 64 bits, and make sure the + // compiler never touches memory after the + // real data +}; + +inline +mapping_t::mapping_t() +{} + +inline +mapping_s * +mapping_t::data() +{ + return reinterpret_cast(_data); +} + +PUBLIC inline NEEDS[mapping_depth_t, mapping_s, mapping_t::data] +space_index_t +mapping_t::space() +{ + return space_index_t(data()->space); +} + +PUBLIC inline NEEDS[mapping_depth_t, mapping_s, mapping_t::data] +vm_offset_t +mapping_t::vaddr() +{ + return (data()->address << PAGE_SHIFT); +} + +PUBLIC inline NEEDS[mapping_depth_t, mapping_s, mapping_t::data] +vm_size_t +mapping_t::size() +{ + if ( data()->size ) + return SUPERPAGE_SIZE; + else + return PAGE_SIZE; +} + +PUBLIC inline +mapping_type_t +mapping_t::type() +{ + // return data()->type;; + return Map_mem; +} + +inline NEEDS[mapping_depth_t, mapping_s, mapping_t::data] +bool +mapping_t::unused() +{ + return (data()->depth > Depth_max); +} + +mapping_tree_t * +mapping_t::tree() +{ + mapping_t *m = this; + + while (m->data()->depth > Depth_sigma0_mapping) + { + // jump in bigger steps if this is not a free mapping + if (! m->unused()) + { + m -= m->data()->depth; + continue; + } + + m--; + } + + return reinterpret_cast + (reinterpret_cast(m) - offsetof(mapping_tree_t, _mappings)); +} + +// +// more of class mapping_t +// + +PUBLIC mapping_t * +mapping_t::parent() +{ + if (data()->depth <= Depth_sigma0_mapping) + { + // Sigma0 mappings don't have a parent. + return 0; + } + + // Iterate over mapping entries of this tree backwards until we find + // an entry with a depth smaller than ours. (We assume here that + // "special" depths (empty, end) are larger than Depth_max.) + mapping_t *m = this - 1; + + while (m->data()->depth >= data()->depth) + m--; + + return m; +} + +PUBLIC mapping_t * +mapping_t::next_iter() +{ + mapping_tree_t *t = tree(); + mapping_t *last_in_tree = t->mappings() + t->number_of_entries() - 1; + + mapping_t *m = this; + + // Look for a valid element in the tree structure. + while (m != last_in_tree) + { + m++; + if (! m->unused()) + return m; // Found a valid entry! + + // Don't iterate to end of tree if this is the last tree entry. + if (m->data()->depth == Depth_end) + return 0; + } + + // Couldn't find a non-empty element behind ourselves in the tree + // structure. + return 0; +} + +PUBLIC mapping_t * +mapping_t::next_child(mapping_t *parent) +{ + // Find the next valid entry in the tree structure. + mapping_t *m = next_iter(); + + // If we didn't find an entry, or if the entry cannot be a child of + // "parent", return 0 + if (m == 0 + || m->data()->depth <= parent->data()->depth) + return 0; + + return m; // Found! +} + +// helpers + +// +// class mapping_tree_t +// + +// This function copies the elements of mapping tree src to mapping +// tree dst, ignoring empty elements (that is, compressing the +// source tree. In-place compression is supported. +PUBLIC static void +mapping_tree_t::copy_compact_tree(mapping_tree_t *dst, mapping_tree_t *src) +{ + dst->_count = 0; + dst->_empty_count = 0; + + mapping_t *d = dst->mappings(); + + for (mapping_t *s = src->mappings(); + s < src->mappings() + src->number_of_entries(); + s++) + { + if (s->unused()) // entry free + { + if (s->data()->depth == Depth_end) + break; + continue; + } + + *d++ = *s; + dst->_count += 1; + } + + assert (dst->_count == src->_count); + assert (d < dst->mappings() + dst->number_of_entries()); + + d->data()->depth = Depth_end; + dst->mappings()[dst->number_of_entries() - 1].data()->depth = Depth_end; +} // copy_compact_tree() + +// +// class mapdb +// + +#include "lock.h" +#include "kmem_slab.h" + +struct physframe_data { + mapping_tree_t *tree; + helping_lock_t lock; +}; + +PUBLIC +mapdb_t::mapdb_t() +{ + vm_offset_t page_number = kmem::info()->main_memory.high / PAGE_SIZE + 1; + + // allocate physframe array + check ( physframe = reinterpret_cast + (kmem::alloc(page_number * sizeof(physframe_data))) ); + + memset(physframe, 0, page_number * sizeof(physframe_data)); + + // create a slab for each mapping tree size + for (int slab_number = 0; + slab_number <= Size_id_max; + slab_number++ ) + { + unsigned elem_size = + (Size_factor << slab_number) * sizeof(mapping_t) + + sizeof(mapping_tree_t); + + allocator_for_treesize[slab_number] = + new kmem_slab_t(((PAGE_SIZE / elem_size) < 40 + ? 8*PAGE_SIZE : PAGE_SIZE), + elem_size, 1); + } + + // create a sigma0 mapping for all physical pages + for (unsigned page_id = 0; page_id < page_number; page_id++) + { + mapping_tree_t *t; + check( (t = physframe[page_id].tree + = reinterpret_cast + (allocator_for_treesize[0]->alloc())) ); + + t->_count = 1; // 1 valid mapping + t->_size_id = 0; // size is equal to Size_factor << 0 + t->_empty_count = 0; // no gaps in tree representation + + t->mappings()[0].data()->depth = Depth_sigma0_mapping; + t->mappings()[0].data()->address = page_id; + t->mappings()[0].data()->space = config::sigma0_taskno; + t->mappings()[0].data()->size = 0; + + t->mappings()[1].data()->depth = Depth_end; + + // We also always set the end tag on last entry so that we can + // check whether it has been overwritten. + t->mappings()[t->number_of_entries() - 1].data()->depth = Depth_end; + } +} // mapdb_t() + + +// insert a new mapping entry with the given values as child of +// "parent" After locating the right place for the new entry, it will +// be stored there (if this place is empty) or the following entries +// moved by one entry. + +// We assume that there is at least one free entry at the end of the +// array so that at least one insert() operation can succeed between a +// lock()/free() pair of calls. This is guaranteed by the free() +// operation which allocates a larger tree if the current one becomes +// to small. +PUBLIC mapping_t * +mapdb_t::insert(mapping_t *parent, + space_t *space, + vm_offset_t va, + vm_size_t size, + mapping_type_t type) +{ + assert(type == Map_mem); // we don't yet support Map_io + + mapping_tree_t *t = parent->tree(); + + // We cannot continue if the last array entry is not free. This + // only happens if an earlier call to free() with this mapping tree + // couldn't allocate a bigger array. In this case, signal an + // out-of-memory condition. + if (! t->mappings()[t->number_of_entries() - 1].unused()) + return 0; + + // If the parent mapping already has the maximum depth, we cannot + // insert a child. + if (parent->data()->depth == Depth_max) + return 0; + + mapping_t *insert = 0; + + bool + found_free_entry = false, + need_to_move = false; + + mapping_t temp; + + // Find a free entry in the array encoding the tree, and find the + // insertion point for the new entry. These two entries might not + // be equivalent, so we may need to move entries backwards in the + // array. In this implementation, we move entries as we traverse + // the array, instead of doing one big memmove + for (mapping_t *m = parent + 1; + m < t->mappings() + t->number_of_entries(); + m++) + { + if (m->unused()) + { + // We found a free entry in the tree -- allocate it. + found_free_entry = true; + t->_count += 1; + + // Did we find an empty element != the end tag? + if (m->data()->depth == Depth_empty) + { + t->_empty_count -= 1; + } + // Else we have found the end tag. If there is another + // array entry left, apply a new end tag to the array + else if (m + 1 < t->mappings() + t->number_of_entries()) + { + (m + 1)->data()->depth = Depth_end; + } + + // if we haven't identified a place for inserting the new + // element, this is it. + if (! need_to_move) + insert = m; + } + else if (! need_to_move + && m->data()->depth <= parent->data()->depth) + { + // we found a non-descendant of ourselves -- need to make + // space for new child + need_to_move = true; + insert = m; + temp = *insert; + + continue; + } + + if (need_to_move) + { + // replace *m with temp (which used to be *(m - 1); but + // *(m - 1) has since been overwritten), and load temp with + // the old value of *m + mapping_t temp2; + + temp2 = *m; + *m = temp; + temp = temp2; + } + + if (found_free_entry) + break; + } + + assert(insert && found_free_entry); + + // found a place to insert new child. + insert->data()->depth = mapping_depth_t(parent->data()->depth + 1); + insert->data()->address = va >> PAGE_SHIFT; + insert->data()->space = space->space(); + insert->data()->size = (size == SUPERPAGE_SIZE); + + return insert; +} // insert() + +PUBLIC mapping_t * +mapdb_t::lookup(space_t *space, + vm_offset_t va, + mapping_type_t type) +{ + vm_offset_t phys = space->virt_to_phys(va); + + if (phys == 0xffffffff) + return 0; + + mapping_tree_t *t; + + // get and lock the tree. + // XXX For now, use a simple lock with helping. Later + // unify locking with our request scheme. + physframe[phys >> PAGE_SHIFT].lock.lock(); + + t = physframe[phys >> PAGE_SHIFT].tree; + assert(t); + + mapping_t *m; + + for (m = t->mappings(); + m->data()->depth != Depth_end + && m < t->mappings() + t->number_of_entries(); + m++) + { + if (m->data()->space == space->space() + && m->data()->address == va >> PAGE_SHIFT) + { + // found! + return m; + } + } + + // not found -- unlock tree + physframe[phys >> PAGE_SHIFT].lock.clear(); + + return 0; +} // lookup() + +PUBLIC void +mapdb_t::free(mapping_t* mapping_of_tree) +{ + mapping_tree_t *t = mapping_of_tree->tree(); + + // We assume that the zeroth mapping of the tree is a sigma0 + // mapping, that is, its virtual address == the page's physical + // address. + vm_offset_t phys_pno = t->mappings()[0].data()->address; + + // We are the owner of the tree lock. + assert(physframe[phys_pno].lock.lock_owner() == current()); + + // Before we unlock the tree, we need to make sure that there is + // room for at least one new mapping. In particular, this means + // that the last entry of the array encoding the tree must be free. + + // (1) When we use up less than a quarter of all entries of the + // array encoding the tree, copy to a smaller tree. Otherwise, (2) + // if the last entry is free, do nothing. Otherwise, (3) if less + // than 3/4 of the entries are used, compress the tree. Otherwise, + // (4) copy to a larger tree. + + bool maybe_out_of_memory = false; + + do // (this is not actually a loop, just a block we can "break" out of) + { + // (1) Do we need to allocate a smaller tree? + if (t->_size_id > 0 // must not be smallest size + && (t->_count << 2) < t->number_of_entries()) + { + mapping_tree_t *new_t = + reinterpret_cast + (allocator_for_treesize[t->_size_id - 1]->alloc()); + + if (new_t) + { + // XXX should be asserted by allocator: + new_t->_size_id = t->_size_id - 1; + new_t->mappings()[new_t->number_of_entries() - 1].data()->depth + = Depth_end; + + mapping_tree_t::copy_compact_tree(new_t, t); + + // Register new tree. + physframe[phys_pno].tree = new_t; + + allocator_for_treesize[t->_size_id]->free(t); + t = new_t; + + break; + } + } + + // (2) Is last entry is free? + if (t->mappings()[t->number_of_entries() - 1].unused()) + break; // OK, last entry is free. + + // Last entry is not free -- either compress current array + // (i.e., move free entries to end of array), or allocate bigger + // array. + + // (3) Should we compress the tree? + // We also try to compress if we cannot allocate a bigger + // tree because there is no bigger tree size. + if (t->_count < (t->number_of_entries() >> 2) + + (t->number_of_entries() >> 1) + || t->_size_id == Size_id_max) // cannot enlarge? + { + if (t->_size_id == Size_id_max) + maybe_out_of_memory = true; + + mapping_tree_t::copy_compact_tree(t, t); // in-place compression + + break; + } + + // (4) OK, allocate a bigger array. + + mapping_tree_t *new_t = + reinterpret_cast + (allocator_for_treesize[t->_size_id + 1]->alloc()); + + if (new_t) + { + // XXX should be asserted by allocator: + new_t->_size_id = t->_size_id + 1; + new_t->mappings()[new_t->number_of_entries() - 1].data()->depth + = Depth_end; + + mapping_tree_t::copy_compact_tree(new_t, t); + + // Register new tree. + physframe[phys_pno].tree = new_t; + + allocator_for_treesize[t->_size_id]->free(t); + t = new_t; + } + else + { + // out of memory -- just do tree compression and hope that helps. + maybe_out_of_memory = true; + + mapping_tree_t::copy_compact_tree(t, t); // in-place compression + } + } + while (false); + + // The last entry of the tree should now be free -- exept if we're + // out of memory. + assert(t->mappings()[t->number_of_entries() - 1].unused() + || maybe_out_of_memory); + + // Unlock tree. + physframe[phys_pno].lock.clear(); +} // free() + +// Delete mappings from a tree. This is easy to do: We just have to +// iterate over the array encoding the tree. +PUBLIC bool +mapdb_t::flush(mapping_t *m, bool me_too) +{ + mapping_tree_t *t = m->tree(); + mapping_t *start_of_deletions = m; + unsigned m_depth = m->data()->depth; + unsigned deleted = 0, empty_elems_passed = 0; + + if (me_too) + { + m->data()->depth = Depth_empty; + t->_count -= 1; + deleted++; + } + else + start_of_deletions++; + + m++; + + for (; + m < t->mappings() + t->number_of_entries() + && m->data()->depth != Depth_end; + m++) + { + if (unsigned (m->data()->depth) <= m_depth) + { + // Found another data element -- stop deleting. Since we + // created holes in the tree representation, account for it. + t->_empty_count += deleted; + + return true; + } + + if (m->data()->depth == Depth_empty) + { + empty_elems_passed++; + continue; + } + + // Delete the element. + m->data()->depth = Depth_empty; + t->_count -= 1; + deleted++; + } + + // We deleted stuff at the end of the array -- move end tag + if (start_of_deletions < t->mappings() + t->number_of_entries()) + { + start_of_deletions->data()->depth = Depth_end; + + // also, reduce number of free entries + t->_empty_count -= empty_elems_passed; + } + + return true; +} // flush() + +PUBLIC void +mapdb_t::grant(mapping_t *m, space_t *new_space, vm_offset_t va) +{ + m->data()->space = new_space->space(); + m->data()->address = va >> PAGE_SHIFT; +} // grant() diff --git a/kernel/fiasco/tool/preprocess/test/multifile1.cpp b/kernel/fiasco/tool/preprocess/test/multifile1.cpp new file mode 100644 index 00000000..f776d41d --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/multifile1.cpp @@ -0,0 +1,24 @@ +INTERFACE: + +class Foo +{ +}; + +IMPLEMENTATION [part1]: + +PUBLIC +void +Foo::bar () +{} + +PROTECTED inline NEEDS [Foo::rambo] +void +Foo::baz () +{} + +IMPLEMENTATION: + +PRIVATE +void +Foo::gizmatic () +{} diff --git a/kernel/fiasco/tool/preprocess/test/multifile2.cpp b/kernel/fiasco/tool/preprocess/test/multifile2.cpp new file mode 100644 index 00000000..6b92cf07 --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/multifile2.cpp @@ -0,0 +1,23 @@ +INTERFACE: + +EXTENSION class Foo +{ + int more; +}; + +class Bar; + +IMPLEMENTATION [part2]: + +#include "bar.h" + +PUBLIC +void +Foo::bingo (Bar* bar) +{} + +PROTECTED inline +void +Foo::rambo () +{} + diff --git a/kernel/fiasco/tool/preprocess/test/noinline.cpp b/kernel/fiasco/tool/preprocess/test/noinline.cpp new file mode 100644 index 00000000..379e2949 --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/noinline.cpp @@ -0,0 +1,8 @@ +INTERFACE: + +IMPLEMENTATION: + +// There is nothing to inline -- therefore, this #include directive +// should not be put in public header. + +#include "foo.h" diff --git a/kernel/fiasco/tool/preprocess/test/operator.cpp b/kernel/fiasco/tool/preprocess/test/operator.cpp new file mode 100644 index 00000000..1da955af --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/operator.cpp @@ -0,0 +1,88 @@ +INTERFACE: + +class Foo +{ +}; + +IMPLEMENTATION: + +PUBLIC +void * +Foo::operator new (size_t) // funny comment +{ +} + +PUBLIC +Foo& +Foo::operator + (const Foo&) // funny comment +{ +} + +PUBLIC +Foo& +Foo::operator = (const Foo&) // funny comment +{ +} + +PUBLIC +Foo& +Foo::operator * (const Foo&) // funny comment +{ +} + +template +std::vector& +operator << (std::vector& in, const T& new_elem) +{ + in.push_back (new_elem); + return in; +} + +// Some systematic tests (contributed by Matthias Daum) + +struct X { }; + +PUBLIC inline void* X::operator new(unsigned int) { return (void*)0; } +PUBLIC inline void X::operator delete(void*) { } +PUBLIC inline void* X::operator new [] (unsigned int, int) { return (void*)0; } +PUBLIC inline void X::operator delete [] (void*) { } +PUBLIC inline X X::operator + (const X&) { return *this; } +PUBLIC inline X X::operator - (const X&) { return *this; } +PUBLIC inline X X::operator * (const X&) { return *this; } +PUBLIC inline X X::operator / (const X&) { return *this; } +PUBLIC inline X X::operator % (const X&) { return *this; } +PUBLIC inline X X::operator ^ (const X&) { return *this; } +PUBLIC inline X X::operator & (const X&) { return *this; } +PUBLIC inline X X::operator | (const X&) { return *this; } +PUBLIC inline X X::operator ~ () { return *this; } +PUBLIC inline X X::operator ! () { return *this; } +PUBLIC inline X& X::operator = (const X&) {return *this; } +PUBLIC inline bool X::operator < (const X&) { return false; } +PUBLIC inline bool X::operator > (const X&) { return false; } +PUBLIC inline X& X::operator += (const X&) { return *this; } +PUBLIC inline X& X::operator -= (const X&) { return *this; } +PUBLIC inline X& X::operator *= (const X&) { return *this; } +PUBLIC inline X& X::operator /= (const X&) { return *this; } +PUBLIC inline X& X::operator %= (const X&) { return *this; } +PUBLIC inline X& X::operator ^= (const X&) { return *this; } +PUBLIC inline X& X::operator &= (const X&) { return *this; } +PUBLIC inline X& X::operator |= (const X&) { return *this; } +PUBLIC inline X X::operator << (const X&) { return *this; } +PUBLIC inline X X::operator >> (const X&) { return *this; } +PUBLIC inline X& X::operator >>= (const X&) { return *this; } +PUBLIC inline X& X::operator <<= (const X&) { return *this; } +PUBLIC inline bool X::operator == (const X&) { return true; } +PUBLIC inline bool X::operator != (const X&) { return false; } +PUBLIC inline bool X::operator <= (const X&) { return true; } +PUBLIC inline bool X::operator >= (const X&) { return true; } +PUBLIC inline bool X::operator && (const X&) { return false; } +PUBLIC inline bool X::operator || (const X&) { return true; } +PUBLIC inline X& X::operator ++ () { return *this; } +PUBLIC inline X X::operator ++ (int) { return *this; } +PUBLIC inline X& X::operator -- () { return *this; } +PUBLIC inline X X::operator -- (int) { return *this; } +PUBLIC inline X& X::operator , (const X&) { return *this; } +PUBLIC inline X* X::operator ->* (const X&) { return this; } +PUBLIC inline X* X::operator -> () { return this; } +PUBLIC inline int X::operator () (const X&) { return 0; } +PUBLIC inline int X::operator [] (const X&) { return 0; } diff --git a/kernel/fiasco/tool/preprocess/test/parser.cpp b/kernel/fiasco/tool/preprocess/test/parser.cpp new file mode 100644 index 00000000..7ed31293 --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/parser.cpp @@ -0,0 +1,90 @@ +INTERFACE: + +struct Foo +{ + struct Bar + { + int baz; + }; + +public: + int alreadythere(); + inline int alsoalreadythere(); +}; + +IMPLEMENTATION: + +#include "foo.h" + +inline +int bar() +{} + +// Try multiline NEEDS +inline NEEDS["foo.h", + bar] +int baz() +{} + +// Try function arguments +unsigned +somefunc(unsigned (*func1)(), + unsigned (*func2)()) +{ +} + +// Try function-pointer typedef +typedef int (* diag_printf_t) (const char *, ...); +typedef int (**dblfptr) (void); +typedef int (* arrfptr[20]) (void); + +// Try to initialize a nested structure object. +struct Foo::Bar some_bar = { 1 }; + +// And add a Foo function +void Foo::func () +{} + +// Try default arguments +void Foo::bar (int i = 15, int j = somefunc(0, somefunc(0, 0))) +{} + +// Try a constructor with weird syntax +PUBLIC +Foo::Foo () + : something (reinterpret_cast(Baz::bla())) +{} + +// Try implementing an already-declared function +IMPLEMENT int +Foo::alreadythere() +{} + +IMPLEMENT inline int +Foo::alsoalreadythere() +{} + +// +// Try some commented-out code -- only #if 0 supported at the moment. +// +#if 0 + +#ifdef FOO +funny +#else +even funnier +#endif + +#else // ! 0 + +void find_this (); + +#if 0 +but not this +#endif + +#ifdef HEILIGE_WEIHNACHT +static void present_this (); +#endif + +#endif diff --git a/kernel/fiasco/tool/preprocess/test/static.cpp b/kernel/fiasco/tool/preprocess/test/static.cpp new file mode 100644 index 00000000..f0e4b099 --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/static.cpp @@ -0,0 +1,25 @@ +INTERFACE: + +IMPLEMENTATION: + +extern "C" { + extern char _mappings_1, _mappings_end_1; +} + +static const vm_offset_t mem_alloc_region + = reinterpret_cast(&_mappings_1); + +static const vm_offset_t mem_alloc_region_end + = reinterpret_cast(&_mappings_end_1); + +static kmem_slab_t *amm_entry_cache; + +static amm_t region_amm; +static oskit_addr_t end_of_last_region; +static helping_lock_t region_lock; + +static char keymap[128][2] = { + {'[', '{'}, +// {']', '}'}, /* 27 */ + {'+', '*'}, /* 27 */ +}; diff --git a/kernel/fiasco/tool/preprocess/test/template.cpp b/kernel/fiasco/tool/preprocess/test/template.cpp new file mode 100644 index 00000000..6498a0cc --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/template.cpp @@ -0,0 +1,236 @@ +INTERFACE: + +template +class stack_t; + +template +class stack_top_t +{ +private: + friend class stack_t; + + // Dont change the layout !!, comp_and_swap2 expects + // version and _next next to each other, in that order + int _version; + T *_next; +}; + +template +class stack_t +{ +private: + stack_top_t _head; +}; + +IMPLEMENTATION: + +// +// atomic-manipulation functions +// + +// typesafe variants +template +inline bool compare_and_swap(I *ptr, I oldval, I newval) +{ + return compare_and_swap(reinterpret_cast(ptr), + *reinterpret_cast(&oldval), + *reinterpret_cast(&newval)); +} + +template +inline bool test_and_set(I *l) +{ + return test_and_set(reinterpret_cast(l)); +} + +// +// stack_top_t +// + +// template +// stack_top_t & +// stack_top_t::operator=(const stack_top_t& _copy){ +// _version = _copy._version; +// _next = _copy._next; +// return *this; +// } + +PUBLIC inline +template +stack_top_t::stack_top_t (int version, T *next) + : _version (version), + _next (next) +{} + +PUBLIC inline +template +stack_top_t::stack_top_t () + : _version (0), + _next (0) +{} + +// +// stack_t +// + +PUBLIC +template +stack_t::stack_t() + : _head (0, 0) +{} + +PUBLIC +template +int +stack_t::insert(T *e) +{ + stack_top_t old_head, + new_head; + + do { + e->set_next(_head._next); + old_head = _head; + new_head._version = _head._version+1; + new_head._next = e; + } while (! compare_and_swap2((int *) &_head, + (int *) &old_head, + (int *) &new_head)); + return new_head._version; +} + +PUBLIC +template +T* +stack_t::dequeue() +{ + stack_top_t old_head, + new_head; + + T *first; + + do { + old_head = _head; + + first = _head._next; + if(! first){ + break; + } + + new_head._next = first->get_next(); + new_head._version = _head._version + 1; + } while (! compare_and_swap2((int *) &_head, + (int *) &old_head, + (int *) &new_head)); + // XXX Why did the old implementation test on e ? + // while (e && ! compare_and_swap(&_first, e, e->list_property.next)); + // This is necessary to handle the case of a empty stack. + + // return old_head._next; + return first; +} + +// This version of dequeue only returns a value +// if it is equal to the one passed as top +PUBLIC +template +T* +stack_t::dequeue(T *top) +{ + stack_top_t old_head, + new_head; + // stack_elem_t *first; + + old_head._version = _head._version; // version doesnt matter + old_head._next = top; // cas will fail, if top aint at top + if(!_head._next){ // empty stack + return 0; + } + new_head._version = _head._version + 1; + new_head._next = top->get_next(); + + + if(! compare_and_swap2((int *) &_head, + (int *) &old_head, + (int *) &new_head)) + // we didnt succeed + return 0; + else + // top was on top , so we dequeued it + return top; +} + +PUBLIC +template +T* +stack_t::first() +{ + return _head._next; +} + +PUBLIC +template +void +stack_t::reset() +{ + _head._version = 0; + _head._next = 0; +} + +template +stack_t* +create_stack() +{ + return new stack_t(); +} + +template <> +stack_t* +create_stack() +{ + return new stack(); +} + +template <> +inline +stack_t* +create_stack() +{ + return new stack(); +} + +// +// Member templates +// + +class Foo +{ + template T* goo(T* t); +}; + +template +class TFoo +{ +}; + +PUBLIC +template +T* +Foo::bar (T* t) +{ +} + +IMPLEMENT +template +T* +Foo::goo (T* t) +{ +} + +PUBLIC +template +template +T* +TFoo::baz (T* t) +{ +} + diff --git a/kernel/fiasco/tool/preprocess/test/variable.cpp b/kernel/fiasco/tool/preprocess/test/variable.cpp new file mode 100644 index 00000000..6e1a57da --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/variable.cpp @@ -0,0 +1,6 @@ +IMPLEMENTATION: + +int (Foo::*func_vec[100]) (int arg) = +{ + 0, +}; diff --git a/kernel/fiasco/tool/preprocess/test/verify/c-preproc.cc b/kernel/fiasco/tool/preprocess/test/verify/c-preproc.cc new file mode 100644 index 00000000..67b342f3 --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/verify/c-preproc.cc @@ -0,0 +1,24 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#include "c-preproc.h" +#include "c-preproc_i.h" + +#line 4 "c-preproc.cpp" + +// set CS (missing from OSKIT) +#define set_cs(cs) \ + asm volatile \ + ("ljmp %0,$1f \n1:" \ + : : "i" (cs)); + +#line 10 "c-preproc.cpp" + +void +function(void) +{ +#if 1 + bar (); +#else + foo (); +#endif +} diff --git a/kernel/fiasco/tool/preprocess/test/verify/c-preproc.h b/kernel/fiasco/tool/preprocess/test/verify/c-preproc.h new file mode 100644 index 00000000..5e37080c --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/verify/c-preproc.h @@ -0,0 +1,15 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef c_preproc_h +#define c_preproc_h + +// +// INTERFACE definition follows +// + + +#line 11 "c-preproc.cpp" +void +function(void); + +#endif // c_preproc_h diff --git a/kernel/fiasco/tool/preprocess/test/verify/c-preproc_i.h b/kernel/fiasco/tool/preprocess/test/verify/c-preproc_i.h new file mode 100644 index 00000000..24adf030 --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/verify/c-preproc_i.h @@ -0,0 +1,6 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef c_preproc_i_h +#define c_preproc_i_h + +#endif // c_preproc_i_h diff --git a/kernel/fiasco/tool/preprocess/test/verify/comment_in_string.cc b/kernel/fiasco/tool/preprocess/test/verify/comment_in_string.cc new file mode 100644 index 00000000..34b2de48 --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/verify/comment_in_string.cc @@ -0,0 +1,30 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#include "comment_in_string.h" +#include "comment_in_string_i.h" + +#line 4 "comment_in_string.cpp" + +int foo(char *s); + +#line 6 "comment_in_string.cpp" + +void irq_init(unsigned char master_base, unsigned char slave_base) +{ + if (!(foo(" -vmware")) + { + foo("outb_p(MASTER_OCW, 0xfb); // unmask irq2"); + } + else + { + foo("using normal pic mode \n"); + } +} + +#line 18 "comment_in_string.cpp" + +void bar() +{ + foo ("if (0) {"); + foo ("} // if(0)"); +} diff --git a/kernel/fiasco/tool/preprocess/test/verify/comment_in_string.h b/kernel/fiasco/tool/preprocess/test/verify/comment_in_string.h new file mode 100644 index 00000000..cfe129e2 --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/verify/comment_in_string.h @@ -0,0 +1,17 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef comment_in_string_h +#define comment_in_string_h + +// +// INTERFACE definition follows +// + + +#line 7 "comment_in_string.cpp" +void irq_init(unsigned char master_base, unsigned char slave_base); + +#line 19 "comment_in_string.cpp" +void bar(); + +#endif // comment_in_string_h diff --git a/kernel/fiasco/tool/preprocess/test/verify/comment_in_string_i.h b/kernel/fiasco/tool/preprocess/test/verify/comment_in_string_i.h new file mode 100644 index 00000000..cd94db0d --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/verify/comment_in_string_i.h @@ -0,0 +1,6 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef comment_in_string_i_h +#define comment_in_string_i_h + +#endif // comment_in_string_i_h diff --git a/kernel/fiasco/tool/preprocess/test/verify/default_args.cc b/kernel/fiasco/tool/preprocess/test/verify/default_args.cc new file mode 100644 index 00000000..8a42412b --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/verify/default_args.cc @@ -0,0 +1,13 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#include "default_args.h" +#include "default_args_i.h" + +#line 26 "default_args.cpp" + +extern "C" +void +disasm_bytes(char *buffer, unsigned len, unsigned va, unsigned task, + int show_symbols, int show_intel_syntax, + int (*peek_task)(unsigned addr, unsigned task), + const char* (*get_symbol)(unsigned addr, unsigned task)) WEAK; diff --git a/kernel/fiasco/tool/preprocess/test/verify/default_args.h b/kernel/fiasco/tool/preprocess/test/verify/default_args.h new file mode 100644 index 00000000..4aad967f --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/verify/default_args.h @@ -0,0 +1,52 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef default_args_h +#define default_args_h + +// +// INTERFACE definition follows +// + + +#line 6 "default_args.cpp" +template std::vector +vec(T f1 = T(), T f2 = T(), T f3 = T(), + T f4 = T(), T f5 = T(), T f6 = T()); + +// +// IMPLEMENTATION includes follow (for use by inline functions/templates) +// + +#line 1 "default_args.cpp" +#include + +// +// IMPLEMENTATION of function templates +// + + +#line 4 "default_args.cpp" + + +template std::vector +vec(T f1, T f2, T f3, + T f4, T f5, T f6) +{ + std::vector v; + if (f1 != T()) { + v.push_back (f1); + if (f2 != T()) { + v.push_back (f2); + if (f3 != T()) { + v.push_back (f3); + if (f4 != T()) { + v.push_back (f4); + if (f5 != T()) { + v.push_back (f5); + if (f6 != T()) { + v.push_back (f6); + }}}}}} + return v; +} + +#endif // default_args_h diff --git a/kernel/fiasco/tool/preprocess/test/verify/default_args_i.h b/kernel/fiasco/tool/preprocess/test/verify/default_args_i.h new file mode 100644 index 00000000..622b6cba --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/verify/default_args_i.h @@ -0,0 +1,6 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef default_args_i_h +#define default_args_i_h + +#endif // default_args_i_h diff --git a/kernel/fiasco/tool/preprocess/test/verify/drop_multi1-ext.cc b/kernel/fiasco/tool/preprocess/test/verify/drop_multi1-ext.cc new file mode 100644 index 00000000..5fb3d18b --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/verify/drop_multi1-ext.cc @@ -0,0 +1,5 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#include "drop_multi1.h" +#include "drop_multi1_i.h" + diff --git a/kernel/fiasco/tool/preprocess/test/verify/drop_multi1.cc b/kernel/fiasco/tool/preprocess/test/verify/drop_multi1.cc new file mode 100644 index 00000000..58c6248f --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/verify/drop_multi1.cc @@ -0,0 +1,39 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#include "drop_multi1.h" +#include "drop_multi1_i.h" + + +#line 20 "dropsection.cpp" + +void +Gen_foo::bar( unsigned x ) +{ + // do soemthing with x; +} + +#line 26 "dropsection.cpp" + +void +Gen_foo_ext::test() +{ + // the test +} + +#line 44 "dropsection.cpp" + +int +Gen_foo::foo( int y ) +{ + // just return y + return y; +} + +#line 53 "dropsection.cpp" + +int +Gen_foo::tust( int y ) +{ + // just return y + return y; +} diff --git a/kernel/fiasco/tool/preprocess/test/verify/drop_multi1.h b/kernel/fiasco/tool/preprocess/test/verify/drop_multi1.h new file mode 100644 index 00000000..39e8c923 --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/verify/drop_multi1.h @@ -0,0 +1,43 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef drop_multi1_h +#define drop_multi1_h + +// +// INTERFACE definition follows +// + +#line 2 "dropsection.cpp" + +class Gen_foo +{ +public: + int baz; + +protected: + int foo( int ); + + +public: +#line 21 "dropsection.cpp" + void + bar( unsigned x ); + +#line 54 "dropsection.cpp" + int + tust( int y ); +}; +#line 12 "dropsection.cpp" + +class Gen_foo_ext : private Gen_foo, public Ixdebix +{ +protected: + unsigned stuff; + +public: +#line 27 "dropsection.cpp" + void + test(); +}; + +#endif // drop_multi1_h diff --git a/kernel/fiasco/tool/preprocess/test/verify/drop_multi1_i.h b/kernel/fiasco/tool/preprocess/test/verify/drop_multi1_i.h new file mode 100644 index 00000000..873ad9f5 --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/verify/drop_multi1_i.h @@ -0,0 +1,6 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef drop_multi1_i_h +#define drop_multi1_i_h + +#endif // drop_multi1_i_h diff --git a/kernel/fiasco/tool/preprocess/test/verify/drop_multi2-ext.cc b/kernel/fiasco/tool/preprocess/test/verify/drop_multi2-ext.cc new file mode 100644 index 00000000..6be6addd --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/verify/drop_multi2-ext.cc @@ -0,0 +1,13 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#include "drop_multi2.h" +#include "drop_multi2_i.h" + + +#line 16 "dropsection-ext.cpp" + +int +Gen_foo::do_something_private() +{ + // just do it +} diff --git a/kernel/fiasco/tool/preprocess/test/verify/drop_multi2.cc b/kernel/fiasco/tool/preprocess/test/verify/drop_multi2.cc new file mode 100644 index 00000000..aec4a4c8 --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/verify/drop_multi2.cc @@ -0,0 +1,39 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#include "drop_multi2.h" +#include "drop_multi2_i.h" + + +#line 20 "dropsection.cpp" + +void +Gen_foo::bar( unsigned x ) +{ + // do soemthing with x; +} + +#line 26 "dropsection.cpp" + +void +Gen_foo_ext::test() +{ + // the test +} + +#line 44 "dropsection.cpp" + +int +Gen_foo::foo( int y ) +{ + // just return y + return y; +} + +#line 53 "dropsection.cpp" + +int +Gen_foo::tust( int y ) +{ + // just return y + return y; +} diff --git a/kernel/fiasco/tool/preprocess/test/verify/drop_multi2.h b/kernel/fiasco/tool/preprocess/test/verify/drop_multi2.h new file mode 100644 index 00000000..1157167a --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/verify/drop_multi2.h @@ -0,0 +1,64 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef drop_multi2_h +#define drop_multi2_h + +// +// INTERFACE definition follows +// + +#line 2 "dropsection.cpp" + +class Gen_foo + +: public Gen_bar +{ +public: + int baz; + +protected: + int foo( int ); + + +#line 2 "dropsection-ext.cpp" +private: + +public: + int extra_var; + +public: +#line 21 "dropsection.cpp" + void + bar( unsigned x ); + +#line 54 "dropsection.cpp" + int + tust( int y ); + +private: +#line 17 "dropsection-ext.cpp" + int + do_something_private(); +}; +#line 12 "dropsection.cpp" + +class Gen_foo_ext : private Gen_foo, public Ixdebix + +, public Gen_baz +{ +protected: + unsigned stuff; + +#line 8 "dropsection-ext.cpp" +private: + +private: + char *extension; + +public: +#line 27 "dropsection.cpp" + void + test(); +}; + +#endif // drop_multi2_h diff --git a/kernel/fiasco/tool/preprocess/test/verify/drop_multi2_i.h b/kernel/fiasco/tool/preprocess/test/verify/drop_multi2_i.h new file mode 100644 index 00000000..fde38e88 --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/verify/drop_multi2_i.h @@ -0,0 +1,6 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef drop_multi2_i_h +#define drop_multi2_i_h + +#endif // drop_multi2_i_h diff --git a/kernel/fiasco/tool/preprocess/test/verify/drop_single1.cc b/kernel/fiasco/tool/preprocess/test/verify/drop_single1.cc new file mode 100644 index 00000000..6b8d392e --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/verify/drop_single1.cc @@ -0,0 +1,30 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#include "drop_single1.h" +#include "drop_single1_i.h" + + +#line 20 "dropsection.cpp" + +void +Gen_foo::bar( unsigned x ) +{ + // do soemthing with x; +} + +#line 26 "dropsection.cpp" + +void +Gen_foo_ext::test() +{ + // the test +} + +#line 53 "dropsection.cpp" + +int +Gen_foo::tust( int y ) +{ + // just return y + return y; +} diff --git a/kernel/fiasco/tool/preprocess/test/verify/drop_single1.h b/kernel/fiasco/tool/preprocess/test/verify/drop_single1.h new file mode 100644 index 00000000..8bb7a285 --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/verify/drop_single1.h @@ -0,0 +1,43 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef drop_single1_h +#define drop_single1_h + +// +// INTERFACE definition follows +// + +#line 2 "dropsection.cpp" + +class Gen_foo +{ +public: + int baz; + +protected: + int foo( int ); + + +public: +#line 21 "dropsection.cpp" + void + bar( unsigned x ); + +#line 54 "dropsection.cpp" + int + tust( int y ); +}; +#line 12 "dropsection.cpp" + +class Gen_foo_ext : private Gen_foo, public Ixdebix +{ +protected: + unsigned stuff; + +public: +#line 27 "dropsection.cpp" + void + test(); +}; + +#endif // drop_single1_h diff --git a/kernel/fiasco/tool/preprocess/test/verify/drop_single1_i.h b/kernel/fiasco/tool/preprocess/test/verify/drop_single1_i.h new file mode 100644 index 00000000..e63bb12f --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/verify/drop_single1_i.h @@ -0,0 +1,6 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef drop_single1_i_h +#define drop_single1_i_h + +#endif // drop_single1_i_h diff --git a/kernel/fiasco/tool/preprocess/test/verify/drop_single2.cc b/kernel/fiasco/tool/preprocess/test/verify/drop_single2.cc new file mode 100644 index 00000000..81ef0e7d --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/verify/drop_single2.cc @@ -0,0 +1,31 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#include "drop_single2.h" +#include "drop_single2_i.h" + + +#line 20 "dropsection.cpp" + +void +Gen_foo::bar( unsigned x ) +{ + // do soemthing with x; +} + +#line 26 "dropsection.cpp" + +void +Gen_foo_ext::test() +{ + // the test +} + +#line 34 "dropsection.cpp" + +int +Gen_foo::foo( int y ) +{ + // do something strange with y + bar(y); + return y; +} diff --git a/kernel/fiasco/tool/preprocess/test/verify/drop_single2.h b/kernel/fiasco/tool/preprocess/test/verify/drop_single2.h new file mode 100644 index 00000000..6e560b3e --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/verify/drop_single2.h @@ -0,0 +1,39 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef drop_single2_h +#define drop_single2_h + +// +// INTERFACE definition follows +// + +#line 2 "dropsection.cpp" + +class Gen_foo +{ +public: + int baz; + +protected: + int foo( int ); + + +public: +#line 21 "dropsection.cpp" + void + bar( unsigned x ); +}; +#line 12 "dropsection.cpp" + +class Gen_foo_ext : private Gen_foo, public Ixdebix +{ +protected: + unsigned stuff; + +public: +#line 27 "dropsection.cpp" + void + test(); +}; + +#endif // drop_single2_h diff --git a/kernel/fiasco/tool/preprocess/test/verify/drop_single2_i.h b/kernel/fiasco/tool/preprocess/test/verify/drop_single2_i.h new file mode 100644 index 00000000..e1573cef --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/verify/drop_single2_i.h @@ -0,0 +1,6 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef drop_single2_i_h +#define drop_single2_i_h + +#endif // drop_single2_i_h diff --git a/kernel/fiasco/tool/preprocess/test/verify/drop_single3.cc b/kernel/fiasco/tool/preprocess/test/verify/drop_single3.cc new file mode 100644 index 00000000..583c891d --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/verify/drop_single3.cc @@ -0,0 +1,39 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#include "drop_single3.h" +#include "drop_single3_i.h" + + +#line 20 "dropsection.cpp" + +void +Gen_foo::bar( unsigned x ) +{ + // do soemthing with x; +} + +#line 26 "dropsection.cpp" + +void +Gen_foo_ext::test() +{ + // the test +} + +#line 44 "dropsection.cpp" + +int +Gen_foo::foo( int y ) +{ + // just return y + return y; +} + +#line 53 "dropsection.cpp" + +int +Gen_foo::tust( int y ) +{ + // just return y + return y; +} diff --git a/kernel/fiasco/tool/preprocess/test/verify/drop_single3.h b/kernel/fiasco/tool/preprocess/test/verify/drop_single3.h new file mode 100644 index 00000000..a93f16ad --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/verify/drop_single3.h @@ -0,0 +1,43 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef drop_single3_h +#define drop_single3_h + +// +// INTERFACE definition follows +// + +#line 2 "dropsection.cpp" + +class Gen_foo +{ +public: + int baz; + +protected: + int foo( int ); + + +public: +#line 21 "dropsection.cpp" + void + bar( unsigned x ); + +#line 54 "dropsection.cpp" + int + tust( int y ); +}; +#line 12 "dropsection.cpp" + +class Gen_foo_ext : private Gen_foo, public Ixdebix +{ +protected: + unsigned stuff; + +public: +#line 27 "dropsection.cpp" + void + test(); +}; + +#endif // drop_single3_h diff --git a/kernel/fiasco/tool/preprocess/test/verify/drop_single3_i.h b/kernel/fiasco/tool/preprocess/test/verify/drop_single3_i.h new file mode 100644 index 00000000..18af52dc --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/verify/drop_single3_i.h @@ -0,0 +1,6 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef drop_single3_i_h +#define drop_single3_i_h + +#endif // drop_single3_i_h diff --git a/kernel/fiasco/tool/preprocess/test/verify/explicit.cc b/kernel/fiasco/tool/preprocess/test/verify/explicit.cc new file mode 100644 index 00000000..a1686b64 --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/verify/explicit.cc @@ -0,0 +1,11 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#include "explicit.h" +#include "explicit_i.h" + + +#line 8 "explicit.cpp" + + +Foo::Foo(int bar) +{} diff --git a/kernel/fiasco/tool/preprocess/test/verify/explicit.h b/kernel/fiasco/tool/preprocess/test/verify/explicit.h new file mode 100644 index 00000000..b4631a8e --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/verify/explicit.h @@ -0,0 +1,20 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef explicit_h +#define explicit_h + +// +// INTERFACE definition follows +// + +#line 2 "explicit.cpp" + +class Foo +{ + +public: +#line 10 "explicit.cpp" + explicit Foo(int bar); +}; + +#endif // explicit_h diff --git a/kernel/fiasco/tool/preprocess/test/verify/explicit_i.h b/kernel/fiasco/tool/preprocess/test/verify/explicit_i.h new file mode 100644 index 00000000..bfb21fe9 --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/verify/explicit_i.h @@ -0,0 +1,6 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef explicit_i_h +#define explicit_i_h + +#endif // explicit_i_h diff --git a/kernel/fiasco/tool/preprocess/test/verify/extern_c.cc b/kernel/fiasco/tool/preprocess/test/verify/extern_c.cc new file mode 100644 index 00000000..498dd273 --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/verify/extern_c.cc @@ -0,0 +1,11 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#include "extern_c.h" +#include "extern_c_i.h" + +#line 4 "extern_c.cpp" + +extern "C" +{ + extern char _mappings_1, _mappings_end_1; +} diff --git a/kernel/fiasco/tool/preprocess/test/verify/extern_c.h b/kernel/fiasco/tool/preprocess/test/verify/extern_c.h new file mode 100644 index 00000000..3e548a3a --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/verify/extern_c.h @@ -0,0 +1,6 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef extern_c_h +#define extern_c_h + +#endif // extern_c_h diff --git a/kernel/fiasco/tool/preprocess/test/verify/extern_c_i.h b/kernel/fiasco/tool/preprocess/test/verify/extern_c_i.h new file mode 100644 index 00000000..801e8211 --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/verify/extern_c_i.h @@ -0,0 +1,6 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef extern_c_i_h +#define extern_c_i_h + +#endif // extern_c_i_h diff --git a/kernel/fiasco/tool/preprocess/test/verify/inline.cc b/kernel/fiasco/tool/preprocess/test/verify/inline.cc new file mode 100644 index 00000000..f19c5646 --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/verify/inline.cc @@ -0,0 +1,33 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#include "inline.h" +#include "inline_i.h" + + +#line 48 "inline.cpp" + +// This inline funtion is public only because it is needed by an +// extern-"C" function. So we do not want to export it. + +inline void +Foo::bar() +{ + +} + +#line 57 "inline.cpp" + +// Try both NOEXPORT and NEEDED. + +inline void +Foo::baz() +{ +} + +#line 64 "inline.cpp" + +extern "C" +void function(Foo* f) +{ + f->bar(); +} diff --git a/kernel/fiasco/tool/preprocess/test/verify/inline.h b/kernel/fiasco/tool/preprocess/test/verify/inline.h new file mode 100644 index 00000000..986335d3 --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/verify/inline.h @@ -0,0 +1,125 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef inline_h +#define inline_h + +// +// INTERFACE definition follows +// + +#line 2 "inline.cpp" + +class Foo +{ + +public: +#line 49 "inline.cpp" + // This inline funtion is public only because it is needed by an + // extern-"C" function. So we do not want to export it. + + inline void + bar(); + +#line 58 "inline.cpp" + // Try both NOEXPORT and NEEDED. + + inline void + baz(); + +private: +#line 26 "inline.cpp" + inline bool + private_func(); +}; +#line 6 "inline.cpp" + +class Bar +{ + +public: +#line 44 "inline.cpp" + inline void + public_func(); + +private: +#line 32 "inline.cpp" + inline bool + private_func(); + +#line 38 "inline.cpp" + inline void + another_private_func(); +}; + +#line 65 "inline.cpp" +extern "C" +void function(Foo* f); + +#line 71 "inline.cpp" +template inline void* xcast(T* t); + +// +// IMPLEMENTATION of inline functions (and needed classes) +// + +#line 12 "inline.cpp" + +// Test dependency-chain resolver + +class Frob +{ + +private: +#line 20 "inline.cpp" + inline bool + private_func(); +}; + +#line 24 "inline.cpp" + + +inline bool +Foo::private_func() +{ +} + +#line 30 "inline.cpp" + + +inline bool +Bar::private_func() +{ +} + +#line 36 "inline.cpp" + + +inline void +Bar::another_private_func() +{ +} + +#line 18 "inline.cpp" + + +inline bool +Frob::private_func() +{ +} + +#line 42 "inline.cpp" + + +inline void +Bar::public_func() +{ +} + +#line 70 "inline.cpp" + + template inline void* xcast(T* t) +{ + return (void*) t; +} + +#endif // inline_h diff --git a/kernel/fiasco/tool/preprocess/test/verify/inline_i.h b/kernel/fiasco/tool/preprocess/test/verify/inline_i.h new file mode 100644 index 00000000..e733ac3e --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/verify/inline_i.h @@ -0,0 +1,6 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef inline_i_h +#define inline_i_h + +#endif // inline_i_h diff --git a/kernel/fiasco/tool/preprocess/test/verify/inline_noinline.cc b/kernel/fiasco/tool/preprocess/test/verify/inline_noinline.cc new file mode 100644 index 00000000..10e2ac0e --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/verify/inline_noinline.cc @@ -0,0 +1,73 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#include "inline_noinline.h" +#include "inline_noinline_i.h" + + +#line 18 "inline.cpp" + + +bool +Frob::private_func() +{ +} + +#line 24 "inline.cpp" + + +bool +Foo::private_func() +{ +} + +#line 30 "inline.cpp" + + +bool +Bar::private_func() +{ +} + +#line 36 "inline.cpp" + + +void +Bar::another_private_func() +{ +} + +#line 42 "inline.cpp" + + +void +Bar::public_func() +{ +} + +#line 48 "inline.cpp" + +// This inline funtion is public only because it is needed by an +// extern-"C" function. So we do not want to export it. + +void +Foo::bar() +{ + +} + +#line 57 "inline.cpp" + +// Try both NOEXPORT and NEEDED. + +void +Foo::baz() +{ +} + +#line 64 "inline.cpp" + +extern "C" +void function(Foo* f) +{ + f->bar(); +} diff --git a/kernel/fiasco/tool/preprocess/test/verify/inline_noinline.h b/kernel/fiasco/tool/preprocess/test/verify/inline_noinline.h new file mode 100644 index 00000000..fda5df47 --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/verify/inline_noinline.h @@ -0,0 +1,73 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef inline_noinline_h +#define inline_noinline_h + +// +// INTERFACE definition follows +// + +#line 2 "inline.cpp" + +class Foo +{ + +public: +#line 49 "inline.cpp" + // This inline funtion is public only because it is needed by an + // extern-"C" function. So we do not want to export it. + + void + bar(); + +#line 58 "inline.cpp" + // Try both NOEXPORT and NEEDED. + + void + baz(); + +private: +#line 26 "inline.cpp" + bool + private_func(); +}; +#line 6 "inline.cpp" + +class Bar +{ + +public: +#line 44 "inline.cpp" + void + public_func(); + +private: +#line 32 "inline.cpp" + bool + private_func(); + +#line 38 "inline.cpp" + void + another_private_func(); +}; + +#line 65 "inline.cpp" +extern "C" +void function(Foo* f); + +#line 71 "inline.cpp" +template void* xcast(T* t); + +// +// IMPLEMENTATION of function templates +// + + +#line 70 "inline.cpp" + + template void* xcast(T* t) +{ + return (void*) t; +} + +#endif // inline_noinline_h diff --git a/kernel/fiasco/tool/preprocess/test/verify/inline_noinline_i.h b/kernel/fiasco/tool/preprocess/test/verify/inline_noinline_i.h new file mode 100644 index 00000000..12699b47 --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/verify/inline_noinline_i.h @@ -0,0 +1,18 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef inline_noinline_i_h +#define inline_noinline_i_h +#line 12 "inline.cpp" + +// Test dependency-chain resolver + +class Frob +{ + +private: +#line 20 "inline.cpp" + bool + private_func(); +}; + +#endif // inline_noinline_i_h diff --git a/kernel/fiasco/tool/preprocess/test/verify/interface.cc b/kernel/fiasco/tool/preprocess/test/verify/interface.cc new file mode 100644 index 00000000..90a2add2 --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/verify/interface.cc @@ -0,0 +1,14 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#include "interfacepublic.h" +#include "interface_i.h" + + +#line 9 "interface.cpp" + + +void +Foo::func1() +{ + +} diff --git a/kernel/fiasco/tool/preprocess/test/verify/interface_i.h b/kernel/fiasco/tool/preprocess/test/verify/interface_i.h new file mode 100644 index 00000000..2cfa6b8e --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/verify/interface_i.h @@ -0,0 +1,6 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef interface_i_h +#define interface_i_h + +#endif // interface_i_h diff --git a/kernel/fiasco/tool/preprocess/test/verify/interfacepublic.h b/kernel/fiasco/tool/preprocess/test/verify/interfacepublic.h new file mode 100644 index 00000000..b2221b7d --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/verify/interfacepublic.h @@ -0,0 +1,22 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef interface_h +#define interface_h + +// +// INTERFACE definition follows +// + +#line 2 "interface.cpp" + +// This is class Foo. +class Foo +{ + +public: +#line 11 "interface.cpp" + void + func1(); +}; + +#endif // interface_h diff --git a/kernel/fiasco/tool/preprocess/test/verify/line.cc b/kernel/fiasco/tool/preprocess/test/verify/line.cc new file mode 100644 index 00000000..00cdb0f3 --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/verify/line.cc @@ -0,0 +1,19 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#include "line.h" +#include "line_i.h" + + +#line 9 "line.cpp" + +// A long, multiline comment in front of this function definition. +// Also, a lot of specifiers that need to be handled. + + + + +void +Foo::func1() +{ + +} diff --git a/kernel/fiasco/tool/preprocess/test/verify/line.h b/kernel/fiasco/tool/preprocess/test/verify/line.h new file mode 100644 index 00000000..a7d6ce09 --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/verify/line.h @@ -0,0 +1,28 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef line_h +#define line_h + +// +// INTERFACE definition follows +// + +#line 2 "line.cpp" + +// This is class Foo. +class Foo +{ + +public: +#line 10 "line.cpp" + // A long, multiline comment in front of this function definition. + // Also, a lot of specifiers that need to be handled. + + + + + static void + func1(); +}; + +#endif // line_h diff --git a/kernel/fiasco/tool/preprocess/test/verify/line_i.h b/kernel/fiasco/tool/preprocess/test/verify/line_i.h new file mode 100644 index 00000000..7996c91d --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/verify/line_i.h @@ -0,0 +1,6 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef line_i_h +#define line_i_h + +#endif // line_i_h diff --git a/kernel/fiasco/tool/preprocess/test/verify/line_nh.cc b/kernel/fiasco/tool/preprocess/test/verify/line_nh.cc new file mode 100644 index 00000000..2fa3b54a --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/verify/line_nh.cc @@ -0,0 +1,19 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#include "line_nh.h" +#include "line_nh_i.h" + + +#line 9 "line.cpp" + +// A long, multiline comment in front of this function definition. +// Also, a lot of specifiers that need to be handled. + + + + +void +Foo::func1() +{ + +} diff --git a/kernel/fiasco/tool/preprocess/test/verify/line_nh.h b/kernel/fiasco/tool/preprocess/test/verify/line_nh.h new file mode 100644 index 00000000..bbe70c07 --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/verify/line_nh.h @@ -0,0 +1,21 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef line_nh_h +#define line_nh_h + +// +// INTERFACE definition follows +// + + +// This is class Foo. +class Foo +{ + +public: + // A long, multiline comment in front of this function definition. + // Also, a lot of specifiers that need to be handled. + static void func1(); +}; + +#endif // line_nh_h diff --git a/kernel/fiasco/tool/preprocess/test/verify/line_nh_i.h b/kernel/fiasco/tool/preprocess/test/verify/line_nh_i.h new file mode 100644 index 00000000..71df774d --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/verify/line_nh_i.h @@ -0,0 +1,6 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef line_nh_i_h +#define line_nh_i_h + +#endif // line_nh_i_h diff --git a/kernel/fiasco/tool/preprocess/test/verify/line_not.cc b/kernel/fiasco/tool/preprocess/test/verify/line_not.cc new file mode 100644 index 00000000..eb1d7ca6 --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/verify/line_not.cc @@ -0,0 +1,15 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#include "line_not.h" +#include "line_not_i.h" + + + +// A long, multiline comment in front of this function definition. +// Also, a lot of specifiers that need to be handled. + +void +Foo::func1() +{ + +} diff --git a/kernel/fiasco/tool/preprocess/test/verify/line_not.h b/kernel/fiasco/tool/preprocess/test/verify/line_not.h new file mode 100644 index 00000000..11ab555d --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/verify/line_not.h @@ -0,0 +1,21 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef line_not_h +#define line_not_h + +// +// INTERFACE definition follows +// + + +// This is class Foo. +class Foo +{ + +public: + // A long, multiline comment in front of this function definition. + // Also, a lot of specifiers that need to be handled. + static void func1(); +}; + +#endif // line_not_h diff --git a/kernel/fiasco/tool/preprocess/test/verify/line_not_i.h b/kernel/fiasco/tool/preprocess/test/verify/line_not_i.h new file mode 100644 index 00000000..bf9f83e2 --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/verify/line_not_i.h @@ -0,0 +1,6 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef line_not_i_h +#define line_not_i_h + +#endif // line_not_i_h diff --git a/kernel/fiasco/tool/preprocess/test/verify/mapping.cc b/kernel/fiasco/tool/preprocess/test/verify/mapping.cc new file mode 100644 index 00000000..bb16c3b1 --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/verify/mapping.cc @@ -0,0 +1,730 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#include "mapping.h" +#include "mapping_i.h" + +#line 48 "mapping.cpp" + +// The mapping database. + +// This implementation encodes mapping trees in very compact arrays of +// fixed sizes, prefixed by a tree header (mapping_tree_t). Array +// sizes can vary from 4 mappings to 4<<15 mappings. For each size, +// we set up a slab allocator. To grow or shrink the size of an +// array, we have to allocate a larger or smaller tree from the +// corresponding allocator and then copy the array elements. +// +// The array elements (mapping_t) contain a tree depth element. This +// depth and the relative position in the array is all information we +// need to derive tree structure information. Here is an example: +// +// array +// element depth +// number value comment +// -------------------------- +// 0 0 Sigma0 mapping +// 1 1 child of element #0 with depth 0 +// 2 2 child of element #1 with depth 1 +// 3 2 child of element #1 with depth 1 +// 4 3 child of element #3 with depth 2 +// 5 2 child of element #1 with depth 1 +// 6 3 child of element #5 with depth 2 +// 7 1 child of element #0 with depth 0 +// +// This array is a pre-order encoding of the following tree: +// +// 0 +// / \ +// 1 7 +// / | \ +// 2 3 5 +// | | +// 4 6 + +// IDEAS for enhancing this implementation: + +// We often have to find a tree header corresponding to a mapping. +// Currently, we do this by iterating backwards over the array +// containing the mappings until we find the Sigma0 mapping, from +// whose address we can compute the address of the tree header. If +// this becomes a problem, we could add one more byte to the mappings +// with a hint (negative array offset) where to find the sigma0 +// mapping. (If the hint value overflows, just iterate using the hint +// value of the mapping we find with the first hint value.) Another +// idea (from Adam) would be to just look up the tree header by using +// the physical address from the page-table lookup, but we would need +// to change the interface of the mapping database for that (pass in +// the physical address at all times), or we would have to include the +// physical address (or just the address of the tree header) in the +// mapdb_t-user-visible mapping_t (which could be different from the +// internal tree representation). (XXX: Implementing one of these +// ideas is probably worthwile doing!) + +// Instead of copying whole trees around when they grow or shrink a +// lot, or copying parts of trees when inserting an element, we could +// give up the array representation and add a "next" pointer to the +// elements -- that is, keep the tree of mappings in a +// pre-order-encoded singly-linked list (credits to: Christan Szmajda +// and Adam Wiggins). 24 bits would probably be enough to encode that +// pointer. Disadvantages: Mapping entries would be larger, and the +// cache-friendly space-locality of tree entries would be lost. + +// The current handling of superpages sucks rocks both in this module +// and in our user, ipc_map.cc. We could support multiple page sizes +// by not using a physframe[] array only for the largest page size. +// (Entries of that array point to the top-level mappings -- sigma0 +// mappings.) Mapping-tree entries would then either be regular +// mappings or pointers to an array of mappings of the next-smaller +// size. (credits: Christan Szmajda) +// +// physframe[] +// ------------------------------- +// | | | | | | | | | | | | | | | | array of ptr to 4M mapping_tree_t's +// ---|--------------------------- +// | +// v a mapping_tree_t +// --------------- +// | | tree header +// |-------------| +// | | mapping_t *or* ptr to array of ptr to 4K trees +// | | e.g. +// | ----------------| +// | | v array of ptr to 4M mapping_tree_t's +// --------------- ------------------------------- +// | | | | | | | | | | | | | | | | +// ---|--------------------------- +// | +// v a mapping_tree_t +// --------------- +// | | tree header +// |-------------| +// | | mapping_t +// | | +// | | +// | | +// --------------- +//- +#line 151 "mapping.cpp" + +#ifndef offsetof // should be defined in stddef.h, but isn't +#line 153 "mapping.cpp" +#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) +#line 154 "mapping.cpp" +#endif + +#line 176 "mapping.cpp" + +// public routines with inline implementations + +unsigned +mapping_tree_t::number_of_entries() const +{ + return mapdb_t::Size_factor << _size_id; +} + +#line 184 "mapping.cpp" + + +mapping_t * +mapping_tree_t::mappings() +{ + return & _mappings[0]; +} + +#line 211 "mapping.cpp" + + +mapping_t::mapping_t() +{} + +#line 215 "mapping.cpp" + + +mapping_s * +mapping_t::data() +{ + return reinterpret_cast(_data); +} + +#line 222 "mapping.cpp" + + +space_index_t +mapping_t::space() +{ + return space_index_t(data()->space); +} + +#line 229 "mapping.cpp" + + +vm_offset_t +mapping_t::vaddr() +{ + return (data()->address << PAGE_SHIFT); +} + +#line 236 "mapping.cpp" + + +vm_size_t +mapping_t::size() +{ + if ( data()->size ) + return SUPERPAGE_SIZE; + else + return PAGE_SIZE; +} + +#line 246 "mapping.cpp" + + +mapping_type_t +mapping_t::type() +{ + // return data()->type;; + return Map_mem; +} + +#line 254 "mapping.cpp" + + +bool +mapping_t::unused() +{ + return (data()->depth > Depth_max); +} + +#line 261 "mapping.cpp" + +mapping_tree_t * +mapping_t::tree() +{ + mapping_t *m = this; + + while (m->data()->depth > Depth_sigma0_mapping) + { + // jump in bigger steps if this is not a free mapping + if (! m->unused()) + { + m -= m->data()->depth; + continue; + } + + m--; + } + + return reinterpret_cast + (reinterpret_cast(m) - offsetof(mapping_tree_t, _mappings)); +} + +#line 282 "mapping.cpp" + +// +// more of class mapping_t +// + +mapping_t * +mapping_t::parent() +{ + if (data()->depth <= Depth_sigma0_mapping) + { + // Sigma0 mappings don't have a parent. + return 0; + } + + // Iterate over mapping entries of this tree backwards until we find + // an entry with a depth smaller than ours. (We assume here that + // "special" depths (empty, end) are larger than Depth_max.) + mapping_t *m = this - 1; + + while (m->data()->depth >= data()->depth) + m--; + + return m; +} + +#line 306 "mapping.cpp" + +mapping_t * +mapping_t::next_iter() +{ + mapping_tree_t *t = tree(); + mapping_t *last_in_tree = t->mappings() + t->number_of_entries() - 1; + + mapping_t *m = this; + + // Look for a valid element in the tree structure. + while (m != last_in_tree) + { + m++; + if (! m->unused()) + return m; // Found a valid entry! + + // Don't iterate to end of tree if this is the last tree entry. + if (m->data()->depth == Depth_end) + return 0; + } + + // Couldn't find a non-empty element behind ourselves in the tree + // structure. + return 0; +} + +#line 331 "mapping.cpp" + +mapping_t * +mapping_t::next_child(mapping_t *parent) +{ + // Find the next valid entry in the tree structure. + mapping_t *m = next_iter(); + + // If we didn't find an entry, or if the entry cannot be a child of + // "parent", return 0 + if (m == 0 + || m->data()->depth <= parent->data()->depth) + return 0; + + return m; // Found! +} + +#line 346 "mapping.cpp" + +// helpers + +// +// class mapping_tree_t +// + +// This function copies the elements of mapping tree src to mapping +// tree dst, ignoring empty elements (that is, compressing the +// source tree. In-place compression is supported. +void +mapping_tree_t::copy_compact_tree(mapping_tree_t *dst, mapping_tree_t *src) +{ + dst->_count = 0; + dst->_empty_count = 0; + + mapping_t *d = dst->mappings(); + + for (mapping_t *s = src->mappings(); + s < src->mappings() + src->number_of_entries(); + s++) + { + if (s->unused()) // entry free + { + if (s->data()->depth == Depth_end) + break; + continue; + } + + *d++ = *s; + dst->_count += 1; + } + + assert (dst->_count == src->_count); + assert (d < dst->mappings() + dst->number_of_entries()); + + d->data()->depth = Depth_end; + dst->mappings()[dst->number_of_entries() - 1].data()->depth = Depth_end; +} // copy_compact_tree() + +#line 397 "mapping.cpp" + + +mapdb_t::mapdb_t() +{ + vm_offset_t page_number = kmem::info()->main_memory.high / PAGE_SIZE + 1; + + // allocate physframe array + check ( physframe = reinterpret_cast + (kmem::alloc(page_number * sizeof(physframe_data))) ); + + memset(physframe, 0, page_number * sizeof(physframe_data)); + + // create a slab for each mapping tree size + for (int slab_number = 0; + slab_number <= Size_id_max; + slab_number++ ) + { + unsigned elem_size = + (Size_factor << slab_number) * sizeof(mapping_t) + + sizeof(mapping_tree_t); + + allocator_for_treesize[slab_number] = + new kmem_slab_t(((PAGE_SIZE / elem_size) < 40 + ? 8*PAGE_SIZE : PAGE_SIZE), + elem_size, 1); + } + + // create a sigma0 mapping for all physical pages + for (unsigned page_id = 0; page_id < page_number; page_id++) + { + mapping_tree_t *t; + check( (t = physframe[page_id].tree + = reinterpret_cast + (allocator_for_treesize[0]->alloc())) ); + + t->_count = 1; // 1 valid mapping + t->_size_id = 0; // size is equal to Size_factor << 0 + t->_empty_count = 0; // no gaps in tree representation + + t->mappings()[0].data()->depth = Depth_sigma0_mapping; + t->mappings()[0].data()->address = page_id; + t->mappings()[0].data()->space = config::sigma0_taskno; + t->mappings()[0].data()->size = 0; + + t->mappings()[1].data()->depth = Depth_end; + + // We also always set the end tag on last entry so that we can + // check whether it has been overwritten. + t->mappings()[t->number_of_entries() - 1].data()->depth = Depth_end; + } +} // mapdb_t() + +#line 448 "mapping.cpp" + + +// insert a new mapping entry with the given values as child of +// "parent" After locating the right place for the new entry, it will +// be stored there (if this place is empty) or the following entries +// moved by one entry. + +// We assume that there is at least one free entry at the end of the +// array so that at least one insert() operation can succeed between a +// lock()/free() pair of calls. This is guaranteed by the free() +// operation which allocates a larger tree if the current one becomes +// to small. +mapping_t * +mapdb_t::insert(mapping_t *parent, + space_t *space, + vm_offset_t va, + vm_size_t size, + mapping_type_t type) +{ + assert(type == Map_mem); // we don't yet support Map_io + + mapping_tree_t *t = parent->tree(); + + // We cannot continue if the last array entry is not free. This + // only happens if an earlier call to free() with this mapping tree + // couldn't allocate a bigger array. In this case, signal an + // out-of-memory condition. + if (! t->mappings()[t->number_of_entries() - 1].unused()) + return 0; + + // If the parent mapping already has the maximum depth, we cannot + // insert a child. + if (parent->data()->depth == Depth_max) + return 0; + + mapping_t *insert = 0; + + bool + found_free_entry = false, + need_to_move = false; + + mapping_t temp; + + // Find a free entry in the array encoding the tree, and find the + // insertion point for the new entry. These two entries might not + // be equivalent, so we may need to move entries backwards in the + // array. In this implementation, we move entries as we traverse + // the array, instead of doing one big memmove + for (mapping_t *m = parent + 1; + m < t->mappings() + t->number_of_entries(); + m++) + { + if (m->unused()) + { + // We found a free entry in the tree -- allocate it. + found_free_entry = true; + t->_count += 1; + + // Did we find an empty element != the end tag? + if (m->data()->depth == Depth_empty) + { + t->_empty_count -= 1; + } + // Else we have found the end tag. If there is another + // array entry left, apply a new end tag to the array + else if (m + 1 < t->mappings() + t->number_of_entries()) + { + (m + 1)->data()->depth = Depth_end; + } + + // if we haven't identified a place for inserting the new + // element, this is it. + if (! need_to_move) + insert = m; + } + else if (! need_to_move + && m->data()->depth <= parent->data()->depth) + { + // we found a non-descendant of ourselves -- need to make + // space for new child + need_to_move = true; + insert = m; + temp = *insert; + + continue; + } + + if (need_to_move) + { + // replace *m with temp (which used to be *(m - 1); but + // *(m - 1) has since been overwritten), and load temp with + // the old value of *m + mapping_t temp2; + + temp2 = *m; + *m = temp; + temp = temp2; + } + + if (found_free_entry) + break; + } + + assert(insert && found_free_entry); + + // found a place to insert new child. + insert->data()->depth = mapping_depth_t(parent->data()->depth + 1); + insert->data()->address = va >> PAGE_SHIFT; + insert->data()->space = space->space(); + insert->data()->size = (size == SUPERPAGE_SIZE); + + return insert; +} // insert() + +#line 561 "mapping.cpp" + +mapping_t * +mapdb_t::lookup(space_t *space, + vm_offset_t va, + mapping_type_t type) +{ + vm_offset_t phys = space->virt_to_phys(va); + + if (phys == 0xffffffff) + return 0; + + mapping_tree_t *t; + + // get and lock the tree. + // XXX For now, use a simple lock with helping. Later + // unify locking with our request scheme. + physframe[phys >> PAGE_SHIFT].lock.lock(); + + t = physframe[phys >> PAGE_SHIFT].tree; + assert(t); + + mapping_t *m; + + for (m = t->mappings(); + m->data()->depth != Depth_end + && m < t->mappings() + t->number_of_entries(); + m++) + { + if (m->data()->space == space->space() + && m->data()->address == va >> PAGE_SHIFT) + { + // found! + return m; + } + } + + // not found -- unlock tree + physframe[phys >> PAGE_SHIFT].lock.clear(); + + return 0; +} // lookup() + +#line 602 "mapping.cpp" + +void +mapdb_t::free(mapping_t* mapping_of_tree) +{ + mapping_tree_t *t = mapping_of_tree->tree(); + + // We assume that the zeroth mapping of the tree is a sigma0 + // mapping, that is, its virtual address == the page's physical + // address. + vm_offset_t phys_pno = t->mappings()[0].data()->address; + + // We are the owner of the tree lock. + assert(physframe[phys_pno].lock.lock_owner() == current()); + + // Before we unlock the tree, we need to make sure that there is + // room for at least one new mapping. In particular, this means + // that the last entry of the array encoding the tree must be free. + + // (1) When we use up less than a quarter of all entries of the + // array encoding the tree, copy to a smaller tree. Otherwise, (2) + // if the last entry is free, do nothing. Otherwise, (3) if less + // than 3/4 of the entries are used, compress the tree. Otherwise, + // (4) copy to a larger tree. + + bool maybe_out_of_memory = false; + + do // (this is not actually a loop, just a block we can "break" out of) + { + // (1) Do we need to allocate a smaller tree? + if (t->_size_id > 0 // must not be smallest size + && (t->_count << 2) < t->number_of_entries()) + { + mapping_tree_t *new_t = + reinterpret_cast + (allocator_for_treesize[t->_size_id - 1]->alloc()); + + if (new_t) + { + // XXX should be asserted by allocator: + new_t->_size_id = t->_size_id - 1; + new_t->mappings()[new_t->number_of_entries() - 1].data()->depth + = Depth_end; + + mapping_tree_t::copy_compact_tree(new_t, t); + + // Register new tree. + physframe[phys_pno].tree = new_t; + + allocator_for_treesize[t->_size_id]->free(t); + t = new_t; + + break; + } + } + + // (2) Is last entry is free? + if (t->mappings()[t->number_of_entries() - 1].unused()) + break; // OK, last entry is free. + + // Last entry is not free -- either compress current array + // (i.e., move free entries to end of array), or allocate bigger + // array. + + // (3) Should we compress the tree? + // We also try to compress if we cannot allocate a bigger + // tree because there is no bigger tree size. + if (t->_count < (t->number_of_entries() >> 2) + + (t->number_of_entries() >> 1) + || t->_size_id == Size_id_max) // cannot enlarge? + { + if (t->_size_id == Size_id_max) + maybe_out_of_memory = true; + + mapping_tree_t::copy_compact_tree(t, t); // in-place compression + + break; + } + + // (4) OK, allocate a bigger array. + + mapping_tree_t *new_t = + reinterpret_cast + (allocator_for_treesize[t->_size_id + 1]->alloc()); + + if (new_t) + { + // XXX should be asserted by allocator: + new_t->_size_id = t->_size_id + 1; + new_t->mappings()[new_t->number_of_entries() - 1].data()->depth + = Depth_end; + + mapping_tree_t::copy_compact_tree(new_t, t); + + // Register new tree. + physframe[phys_pno].tree = new_t; + + allocator_for_treesize[t->_size_id]->free(t); + t = new_t; + } + else + { + // out of memory -- just do tree compression and hope that helps. + maybe_out_of_memory = true; + + mapping_tree_t::copy_compact_tree(t, t); // in-place compression + } + } + while (false); + + // The last entry of the tree should now be free -- exept if we're + // out of memory. + assert(t->mappings()[t->number_of_entries() - 1].unused() + || maybe_out_of_memory); + + // Unlock tree. + physframe[phys_pno].lock.clear(); +} // free() + +#line 719 "mapping.cpp" + +// Delete mappings from a tree. This is easy to do: We just have to +// iterate over the array encoding the tree. +bool +mapdb_t::flush(mapping_t *m, bool me_too) +{ + mapping_tree_t *t = m->tree(); + mapping_t *start_of_deletions = m; + unsigned m_depth = m->data()->depth; + unsigned deleted = 0, empty_elems_passed = 0; + + if (me_too) + { + m->data()->depth = Depth_empty; + t->_count -= 1; + deleted++; + } + else + start_of_deletions++; + + m++; + + for (; + m < t->mappings() + t->number_of_entries() + && m->data()->depth != Depth_end; + m++) + { + if (unsigned (m->data()->depth) <= m_depth) + { + // Found another data element -- stop deleting. Since we + // created holes in the tree representation, account for it. + t->_empty_count += deleted; + + return true; + } + + if (m->data()->depth == Depth_empty) + { + empty_elems_passed++; + continue; + } + + // Delete the element. + m->data()->depth = Depth_empty; + t->_count -= 1; + deleted++; + } + + // We deleted stuff at the end of the array -- move end tag + if (start_of_deletions < t->mappings() + t->number_of_entries()) + { + start_of_deletions->data()->depth = Depth_end; + + // also, reduce number of free entries + t->_empty_count -= empty_elems_passed; + } + + return true; +} // flush() + +#line 778 "mapping.cpp" + +void +mapdb_t::grant(mapping_t *m, space_t *new_space, vm_offset_t va) +{ + m->data()->space = new_space->space(); + m->data()->address = va >> PAGE_SHIFT; +} // grant() diff --git a/kernel/fiasco/tool/preprocess/test/verify/mapping.h b/kernel/fiasco/tool/preprocess/test/verify/mapping.h new file mode 100644 index 00000000..ce818ff7 --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/verify/mapping.h @@ -0,0 +1,155 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef mapping_h +#define mapping_h +#line 2 "mapping.cpp" + +#include // for vm_offset_t, vm_size_t +#line 4 "mapping.cpp" +#include "space.h" // for space_index_t + +// +// INTERFACE definition follows +// + +#line 7 "mapping.cpp" + +class mapping_tree_t; // forward decls +#line 9 "mapping.cpp" +struct mapping_s; +#line 26 "mapping.cpp" + +class kmem_slab_t; +#line 28 "mapping.cpp" +struct physframe_data; +#line 5 "mapping.cpp" + +enum mapping_type_t { Map_mem = 0, Map_io }; +#line 10 "mapping.cpp" + +// +// class mapping_t +// +class mapping_t +{ + friend class mapdb_t; + friend class mapping_tree_t; + friend class jdb; + + // CREATORS + mapping_t(const mapping_t&); // this constructor is undefined. + + // DATA + char _data[5]; + +public: +#line 224 "mapping.cpp" + space_index_t + space(); + +#line 231 "mapping.cpp" + vm_offset_t + vaddr(); + +#line 238 "mapping.cpp" + vm_size_t + size(); + +#line 248 "mapping.cpp" + mapping_type_t + type(); + +#line 283 "mapping.cpp" + // + // more of class mapping_t + // + + mapping_t * + parent(); + +#line 307 "mapping.cpp" + mapping_t * + next_iter(); + +#line 332 "mapping.cpp" + mapping_t * + next_child(mapping_t *parent); + +private: +#line 213 "mapping.cpp" + mapping_t(); + +#line 217 "mapping.cpp" + mapping_s * + data(); + +#line 256 "mapping.cpp" + bool + unused(); + +#line 262 "mapping.cpp" + mapping_tree_t * + tree(); +} __attribute__((packed)); +#line 29 "mapping.cpp" + +// +// class mapdb_t: The mapping database +// +class mapdb_t +{ + friend class jdb; + +public: + enum { Size_factor = 4, + Size_id_max = 8 /* can be up to 15 (4 bits) */ }; + +private: + // DATA + physframe_data *physframe; + kmem_slab_t *allocator_for_treesize[Size_id_max + 1]; + +public: +#line 399 "mapping.cpp" + mapdb_t(); + +#line 450 "mapping.cpp" + // insert a new mapping entry with the given values as child of + // "parent" After locating the right place for the new entry, it will + // be stored there (if this place is empty) or the following entries + // moved by one entry. + + // We assume that there is at least one free entry at the end of the + // array so that at least one insert() operation can succeed between a + // lock()/free() pair of calls. This is guaranteed by the free() + // operation which allocates a larger tree if the current one becomes + // to small. + mapping_t * + insert(mapping_t *parent, + space_t *space, + vm_offset_t va, + vm_size_t size, + mapping_type_t type); + +#line 562 "mapping.cpp" + mapping_t * + lookup(space_t *space, + vm_offset_t va, + mapping_type_t type); + +#line 603 "mapping.cpp" + void + free(mapping_t* mapping_of_tree); + +#line 720 "mapping.cpp" + // Delete mappings from a tree. This is easy to do: We just have to + // iterate over the array encoding the tree. + bool + flush(mapping_t *m, bool me_too); + +#line 779 "mapping.cpp" + void + grant(mapping_t *m, space_t *new_space, vm_offset_t va); +}; + +#endif // mapping_h diff --git a/kernel/fiasco/tool/preprocess/test/verify/mapping_i.h b/kernel/fiasco/tool/preprocess/test/verify/mapping_i.h new file mode 100644 index 00000000..b18e273c --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/verify/mapping_i.h @@ -0,0 +1,95 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef mapping_i_h +#define mapping_i_h +#line 148 "mapping.cpp" + +#include +#line 150 "mapping.cpp" +#include +#line 385 "mapping.cpp" + +// +// class mapdb +// + +#include "lock.h" +#line 391 "mapping.cpp" +#include "kmem_slab.h" +#line 155 "mapping.cpp" + +// For implementation of mapping_t functions, we need mapping_tree_t. + +// +// class mapping_tree_t +// +class mapping_tree_t +{ + friend class mapping_t; + friend class mapdb_t; + friend class jdb; + + // DATA + unsigned _count: 16; + unsigned _size_id: 4; + unsigned _empty_count: 11; + unsigned _unused: 1; // make this 32 bits to avoid a compiler bug + + mapping_t _mappings[0] __attribute__((packed)); + + +public: +#line 347 "mapping.cpp" + // helpers + + // + // class mapping_tree_t + // + + // This function copies the elements of mapping tree src to mapping + // tree dst, ignoring empty elements (that is, compressing the + // source tree. In-place compression is supported. + static void + copy_compact_tree(mapping_tree_t *dst, mapping_tree_t *src); + +private: +#line 177 "mapping.cpp" + // public routines with inline implementations + + unsigned + number_of_entries() const; + +#line 186 "mapping.cpp" + mapping_t * + mappings(); +} __attribute__((packed)); +#line 191 "mapping.cpp" + +// Define (otherwise private) stuff needed by public inline +// functions. + +enum mapping_depth_t +{ + Depth_sigma0_mapping = 0, Depth_max = 253, + Depth_empty = 254, Depth_end = 255 +}; +#line 200 "mapping.cpp" + +struct mapping_s +{ + unsigned space:11; + unsigned size:1; + unsigned address:20; + mapping_depth_t depth:8; + unsigned do_not_touch: 24; // make this 64 bits, and make sure the + // compiler never touches memory after the + // real data +}; +#line 392 "mapping.cpp" + +struct physframe_data { + mapping_tree_t *tree; + helping_lock_t lock; +}; + +#endif // mapping_i_h diff --git a/kernel/fiasco/tool/preprocess/test/verify/mapping_inline.cc b/kernel/fiasco/tool/preprocess/test/verify/mapping_inline.cc new file mode 100644 index 00000000..5dfb449d --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/verify/mapping_inline.cc @@ -0,0 +1,647 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#include "mapping_inline.h" +#include "mapping_inline_i.h" + +#line 48 "mapping.cpp" + +// The mapping database. + +// This implementation encodes mapping trees in very compact arrays of +// fixed sizes, prefixed by a tree header (mapping_tree_t). Array +// sizes can vary from 4 mappings to 4<<15 mappings. For each size, +// we set up a slab allocator. To grow or shrink the size of an +// array, we have to allocate a larger or smaller tree from the +// corresponding allocator and then copy the array elements. +// +// The array elements (mapping_t) contain a tree depth element. This +// depth and the relative position in the array is all information we +// need to derive tree structure information. Here is an example: +// +// array +// element depth +// number value comment +// -------------------------- +// 0 0 Sigma0 mapping +// 1 1 child of element #0 with depth 0 +// 2 2 child of element #1 with depth 1 +// 3 2 child of element #1 with depth 1 +// 4 3 child of element #3 with depth 2 +// 5 2 child of element #1 with depth 1 +// 6 3 child of element #5 with depth 2 +// 7 1 child of element #0 with depth 0 +// +// This array is a pre-order encoding of the following tree: +// +// 0 +// / \ +// 1 7 +// / | \ +// 2 3 5 +// | | +// 4 6 + +// IDEAS for enhancing this implementation: + +// We often have to find a tree header corresponding to a mapping. +// Currently, we do this by iterating backwards over the array +// containing the mappings until we find the Sigma0 mapping, from +// whose address we can compute the address of the tree header. If +// this becomes a problem, we could add one more byte to the mappings +// with a hint (negative array offset) where to find the sigma0 +// mapping. (If the hint value overflows, just iterate using the hint +// value of the mapping we find with the first hint value.) Another +// idea (from Adam) would be to just look up the tree header by using +// the physical address from the page-table lookup, but we would need +// to change the interface of the mapping database for that (pass in +// the physical address at all times), or we would have to include the +// physical address (or just the address of the tree header) in the +// mapdb_t-user-visible mapping_t (which could be different from the +// internal tree representation). (XXX: Implementing one of these +// ideas is probably worthwile doing!) + +// Instead of copying whole trees around when they grow or shrink a +// lot, or copying parts of trees when inserting an element, we could +// give up the array representation and add a "next" pointer to the +// elements -- that is, keep the tree of mappings in a +// pre-order-encoded singly-linked list (credits to: Christan Szmajda +// and Adam Wiggins). 24 bits would probably be enough to encode that +// pointer. Disadvantages: Mapping entries would be larger, and the +// cache-friendly space-locality of tree entries would be lost. + +// The current handling of superpages sucks rocks both in this module +// and in our user, ipc_map.cc. We could support multiple page sizes +// by not using a physframe[] array only for the largest page size. +// (Entries of that array point to the top-level mappings -- sigma0 +// mappings.) Mapping-tree entries would then either be regular +// mappings or pointers to an array of mappings of the next-smaller +// size. (credits: Christan Szmajda) +// +// physframe[] +// ------------------------------- +// | | | | | | | | | | | | | | | | array of ptr to 4M mapping_tree_t's +// ---|--------------------------- +// | +// v a mapping_tree_t +// --------------- +// | | tree header +// |-------------| +// | | mapping_t *or* ptr to array of ptr to 4K trees +// | | e.g. +// | ----------------| +// | | v array of ptr to 4M mapping_tree_t's +// --------------- ------------------------------- +// | | | | | | | | | | | | | | | | +// ---|--------------------------- +// | +// v a mapping_tree_t +// --------------- +// | | tree header +// |-------------| +// | | mapping_t +// | | +// | | +// | | +// --------------- +//- +#line 151 "mapping.cpp" + +#ifndef offsetof // should be defined in stddef.h, but isn't +#line 153 "mapping.cpp" +#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) +#line 154 "mapping.cpp" +#endif + +#line 261 "mapping.cpp" + +mapping_tree_t * +mapping_t::tree() +{ + mapping_t *m = this; + + while (m->data()->depth > Depth_sigma0_mapping) + { + // jump in bigger steps if this is not a free mapping + if (! m->unused()) + { + m -= m->data()->depth; + continue; + } + + m--; + } + + return reinterpret_cast + (reinterpret_cast(m) - offsetof(mapping_tree_t, _mappings)); +} + +#line 282 "mapping.cpp" + +// +// more of class mapping_t +// + +mapping_t * +mapping_t::parent() +{ + if (data()->depth <= Depth_sigma0_mapping) + { + // Sigma0 mappings don't have a parent. + return 0; + } + + // Iterate over mapping entries of this tree backwards until we find + // an entry with a depth smaller than ours. (We assume here that + // "special" depths (empty, end) are larger than Depth_max.) + mapping_t *m = this - 1; + + while (m->data()->depth >= data()->depth) + m--; + + return m; +} + +#line 306 "mapping.cpp" + +mapping_t * +mapping_t::next_iter() +{ + mapping_tree_t *t = tree(); + mapping_t *last_in_tree = t->mappings() + t->number_of_entries() - 1; + + mapping_t *m = this; + + // Look for a valid element in the tree structure. + while (m != last_in_tree) + { + m++; + if (! m->unused()) + return m; // Found a valid entry! + + // Don't iterate to end of tree if this is the last tree entry. + if (m->data()->depth == Depth_end) + return 0; + } + + // Couldn't find a non-empty element behind ourselves in the tree + // structure. + return 0; +} + +#line 331 "mapping.cpp" + +mapping_t * +mapping_t::next_child(mapping_t *parent) +{ + // Find the next valid entry in the tree structure. + mapping_t *m = next_iter(); + + // If we didn't find an entry, or if the entry cannot be a child of + // "parent", return 0 + if (m == 0 + || m->data()->depth <= parent->data()->depth) + return 0; + + return m; // Found! +} + +#line 346 "mapping.cpp" + +// helpers + +// +// class mapping_tree_t +// + +// This function copies the elements of mapping tree src to mapping +// tree dst, ignoring empty elements (that is, compressing the +// source tree. In-place compression is supported. +void +mapping_tree_t::copy_compact_tree(mapping_tree_t *dst, mapping_tree_t *src) +{ + dst->_count = 0; + dst->_empty_count = 0; + + mapping_t *d = dst->mappings(); + + for (mapping_t *s = src->mappings(); + s < src->mappings() + src->number_of_entries(); + s++) + { + if (s->unused()) // entry free + { + if (s->data()->depth == Depth_end) + break; + continue; + } + + *d++ = *s; + dst->_count += 1; + } + + assert (dst->_count == src->_count); + assert (d < dst->mappings() + dst->number_of_entries()); + + d->data()->depth = Depth_end; + dst->mappings()[dst->number_of_entries() - 1].data()->depth = Depth_end; +} // copy_compact_tree() + +#line 397 "mapping.cpp" + + +mapdb_t::mapdb_t() +{ + vm_offset_t page_number = kmem::info()->main_memory.high / PAGE_SIZE + 1; + + // allocate physframe array + check ( physframe = reinterpret_cast + (kmem::alloc(page_number * sizeof(physframe_data))) ); + + memset(physframe, 0, page_number * sizeof(physframe_data)); + + // create a slab for each mapping tree size + for (int slab_number = 0; + slab_number <= Size_id_max; + slab_number++ ) + { + unsigned elem_size = + (Size_factor << slab_number) * sizeof(mapping_t) + + sizeof(mapping_tree_t); + + allocator_for_treesize[slab_number] = + new kmem_slab_t(((PAGE_SIZE / elem_size) < 40 + ? 8*PAGE_SIZE : PAGE_SIZE), + elem_size, 1); + } + + // create a sigma0 mapping for all physical pages + for (unsigned page_id = 0; page_id < page_number; page_id++) + { + mapping_tree_t *t; + check( (t = physframe[page_id].tree + = reinterpret_cast + (allocator_for_treesize[0]->alloc())) ); + + t->_count = 1; // 1 valid mapping + t->_size_id = 0; // size is equal to Size_factor << 0 + t->_empty_count = 0; // no gaps in tree representation + + t->mappings()[0].data()->depth = Depth_sigma0_mapping; + t->mappings()[0].data()->address = page_id; + t->mappings()[0].data()->space = config::sigma0_taskno; + t->mappings()[0].data()->size = 0; + + t->mappings()[1].data()->depth = Depth_end; + + // We also always set the end tag on last entry so that we can + // check whether it has been overwritten. + t->mappings()[t->number_of_entries() - 1].data()->depth = Depth_end; + } +} // mapdb_t() + +#line 448 "mapping.cpp" + + +// insert a new mapping entry with the given values as child of +// "parent" After locating the right place for the new entry, it will +// be stored there (if this place is empty) or the following entries +// moved by one entry. + +// We assume that there is at least one free entry at the end of the +// array so that at least one insert() operation can succeed between a +// lock()/free() pair of calls. This is guaranteed by the free() +// operation which allocates a larger tree if the current one becomes +// to small. +mapping_t * +mapdb_t::insert(mapping_t *parent, + space_t *space, + vm_offset_t va, + vm_size_t size, + mapping_type_t type) +{ + assert(type == Map_mem); // we don't yet support Map_io + + mapping_tree_t *t = parent->tree(); + + // We cannot continue if the last array entry is not free. This + // only happens if an earlier call to free() with this mapping tree + // couldn't allocate a bigger array. In this case, signal an + // out-of-memory condition. + if (! t->mappings()[t->number_of_entries() - 1].unused()) + return 0; + + // If the parent mapping already has the maximum depth, we cannot + // insert a child. + if (parent->data()->depth == Depth_max) + return 0; + + mapping_t *insert = 0; + + bool + found_free_entry = false, + need_to_move = false; + + mapping_t temp; + + // Find a free entry in the array encoding the tree, and find the + // insertion point for the new entry. These two entries might not + // be equivalent, so we may need to move entries backwards in the + // array. In this implementation, we move entries as we traverse + // the array, instead of doing one big memmove + for (mapping_t *m = parent + 1; + m < t->mappings() + t->number_of_entries(); + m++) + { + if (m->unused()) + { + // We found a free entry in the tree -- allocate it. + found_free_entry = true; + t->_count += 1; + + // Did we find an empty element != the end tag? + if (m->data()->depth == Depth_empty) + { + t->_empty_count -= 1; + } + // Else we have found the end tag. If there is another + // array entry left, apply a new end tag to the array + else if (m + 1 < t->mappings() + t->number_of_entries()) + { + (m + 1)->data()->depth = Depth_end; + } + + // if we haven't identified a place for inserting the new + // element, this is it. + if (! need_to_move) + insert = m; + } + else if (! need_to_move + && m->data()->depth <= parent->data()->depth) + { + // we found a non-descendant of ourselves -- need to make + // space for new child + need_to_move = true; + insert = m; + temp = *insert; + + continue; + } + + if (need_to_move) + { + // replace *m with temp (which used to be *(m - 1); but + // *(m - 1) has since been overwritten), and load temp with + // the old value of *m + mapping_t temp2; + + temp2 = *m; + *m = temp; + temp = temp2; + } + + if (found_free_entry) + break; + } + + assert(insert && found_free_entry); + + // found a place to insert new child. + insert->data()->depth = mapping_depth_t(parent->data()->depth + 1); + insert->data()->address = va >> PAGE_SHIFT; + insert->data()->space = space->space(); + insert->data()->size = (size == SUPERPAGE_SIZE); + + return insert; +} // insert() + +#line 561 "mapping.cpp" + +mapping_t * +mapdb_t::lookup(space_t *space, + vm_offset_t va, + mapping_type_t type) +{ + vm_offset_t phys = space->virt_to_phys(va); + + if (phys == 0xffffffff) + return 0; + + mapping_tree_t *t; + + // get and lock the tree. + // XXX For now, use a simple lock with helping. Later + // unify locking with our request scheme. + physframe[phys >> PAGE_SHIFT].lock.lock(); + + t = physframe[phys >> PAGE_SHIFT].tree; + assert(t); + + mapping_t *m; + + for (m = t->mappings(); + m->data()->depth != Depth_end + && m < t->mappings() + t->number_of_entries(); + m++) + { + if (m->data()->space == space->space() + && m->data()->address == va >> PAGE_SHIFT) + { + // found! + return m; + } + } + + // not found -- unlock tree + physframe[phys >> PAGE_SHIFT].lock.clear(); + + return 0; +} // lookup() + +#line 602 "mapping.cpp" + +void +mapdb_t::free(mapping_t* mapping_of_tree) +{ + mapping_tree_t *t = mapping_of_tree->tree(); + + // We assume that the zeroth mapping of the tree is a sigma0 + // mapping, that is, its virtual address == the page's physical + // address. + vm_offset_t phys_pno = t->mappings()[0].data()->address; + + // We are the owner of the tree lock. + assert(physframe[phys_pno].lock.lock_owner() == current()); + + // Before we unlock the tree, we need to make sure that there is + // room for at least one new mapping. In particular, this means + // that the last entry of the array encoding the tree must be free. + + // (1) When we use up less than a quarter of all entries of the + // array encoding the tree, copy to a smaller tree. Otherwise, (2) + // if the last entry is free, do nothing. Otherwise, (3) if less + // than 3/4 of the entries are used, compress the tree. Otherwise, + // (4) copy to a larger tree. + + bool maybe_out_of_memory = false; + + do // (this is not actually a loop, just a block we can "break" out of) + { + // (1) Do we need to allocate a smaller tree? + if (t->_size_id > 0 // must not be smallest size + && (t->_count << 2) < t->number_of_entries()) + { + mapping_tree_t *new_t = + reinterpret_cast + (allocator_for_treesize[t->_size_id - 1]->alloc()); + + if (new_t) + { + // XXX should be asserted by allocator: + new_t->_size_id = t->_size_id - 1; + new_t->mappings()[new_t->number_of_entries() - 1].data()->depth + = Depth_end; + + mapping_tree_t::copy_compact_tree(new_t, t); + + // Register new tree. + physframe[phys_pno].tree = new_t; + + allocator_for_treesize[t->_size_id]->free(t); + t = new_t; + + break; + } + } + + // (2) Is last entry is free? + if (t->mappings()[t->number_of_entries() - 1].unused()) + break; // OK, last entry is free. + + // Last entry is not free -- either compress current array + // (i.e., move free entries to end of array), or allocate bigger + // array. + + // (3) Should we compress the tree? + // We also try to compress if we cannot allocate a bigger + // tree because there is no bigger tree size. + if (t->_count < (t->number_of_entries() >> 2) + + (t->number_of_entries() >> 1) + || t->_size_id == Size_id_max) // cannot enlarge? + { + if (t->_size_id == Size_id_max) + maybe_out_of_memory = true; + + mapping_tree_t::copy_compact_tree(t, t); // in-place compression + + break; + } + + // (4) OK, allocate a bigger array. + + mapping_tree_t *new_t = + reinterpret_cast + (allocator_for_treesize[t->_size_id + 1]->alloc()); + + if (new_t) + { + // XXX should be asserted by allocator: + new_t->_size_id = t->_size_id + 1; + new_t->mappings()[new_t->number_of_entries() - 1].data()->depth + = Depth_end; + + mapping_tree_t::copy_compact_tree(new_t, t); + + // Register new tree. + physframe[phys_pno].tree = new_t; + + allocator_for_treesize[t->_size_id]->free(t); + t = new_t; + } + else + { + // out of memory -- just do tree compression and hope that helps. + maybe_out_of_memory = true; + + mapping_tree_t::copy_compact_tree(t, t); // in-place compression + } + } + while (false); + + // The last entry of the tree should now be free -- exept if we're + // out of memory. + assert(t->mappings()[t->number_of_entries() - 1].unused() + || maybe_out_of_memory); + + // Unlock tree. + physframe[phys_pno].lock.clear(); +} // free() + +#line 719 "mapping.cpp" + +// Delete mappings from a tree. This is easy to do: We just have to +// iterate over the array encoding the tree. +bool +mapdb_t::flush(mapping_t *m, bool me_too) +{ + mapping_tree_t *t = m->tree(); + mapping_t *start_of_deletions = m; + unsigned m_depth = m->data()->depth; + unsigned deleted = 0, empty_elems_passed = 0; + + if (me_too) + { + m->data()->depth = Depth_empty; + t->_count -= 1; + deleted++; + } + else + start_of_deletions++; + + m++; + + for (; + m < t->mappings() + t->number_of_entries() + && m->data()->depth != Depth_end; + m++) + { + if (unsigned (m->data()->depth) <= m_depth) + { + // Found another data element -- stop deleting. Since we + // created holes in the tree representation, account for it. + t->_empty_count += deleted; + + return true; + } + + if (m->data()->depth == Depth_empty) + { + empty_elems_passed++; + continue; + } + + // Delete the element. + m->data()->depth = Depth_empty; + t->_count -= 1; + deleted++; + } + + // We deleted stuff at the end of the array -- move end tag + if (start_of_deletions < t->mappings() + t->number_of_entries()) + { + start_of_deletions->data()->depth = Depth_end; + + // also, reduce number of free entries + t->_empty_count -= empty_elems_passed; + } + + return true; +} // flush() + +#line 778 "mapping.cpp" + +void +mapdb_t::grant(mapping_t *m, space_t *new_space, vm_offset_t va) +{ + m->data()->space = new_space->space(); + m->data()->address = va >> PAGE_SHIFT; +} // grant() diff --git a/kernel/fiasco/tool/preprocess/test/verify/mapping_inline.h b/kernel/fiasco/tool/preprocess/test/verify/mapping_inline.h new file mode 100644 index 00000000..c4e6b63e --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/verify/mapping_inline.h @@ -0,0 +1,231 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef mapping_inline_h +#define mapping_inline_h +#line 2 "mapping.cpp" + +#include // for vm_offset_t, vm_size_t +#line 4 "mapping.cpp" +#include "space.h" // for space_index_t + +// +// INTERFACE definition follows +// + +#line 7 "mapping.cpp" + +class mapping_tree_t; // forward decls +#line 9 "mapping.cpp" +struct mapping_s; +#line 26 "mapping.cpp" + +class kmem_slab_t; +#line 28 "mapping.cpp" +struct physframe_data; +#line 5 "mapping.cpp" + +enum mapping_type_t { Map_mem = 0, Map_io }; +#line 10 "mapping.cpp" + +// +// class mapping_t +// +class mapping_t +{ + friend class mapdb_t; + friend class mapping_tree_t; + friend class jdb; + + // CREATORS + mapping_t(const mapping_t&); // this constructor is undefined. + + // DATA + char _data[5]; + +public: +#line 224 "mapping.cpp" + inline space_index_t + space(); + +#line 231 "mapping.cpp" + inline vm_offset_t + vaddr(); + +#line 238 "mapping.cpp" + inline vm_size_t + size(); + +#line 248 "mapping.cpp" + inline mapping_type_t + type(); + +#line 283 "mapping.cpp" + // + // more of class mapping_t + // + + mapping_t * + parent(); + +#line 307 "mapping.cpp" + mapping_t * + next_iter(); + +#line 332 "mapping.cpp" + mapping_t * + next_child(mapping_t *parent); + +private: +#line 213 "mapping.cpp" + inline mapping_t(); + +#line 217 "mapping.cpp" + inline mapping_s * + data(); + +#line 256 "mapping.cpp" + inline bool + unused(); + +#line 262 "mapping.cpp" + mapping_tree_t * + tree(); +} __attribute__((packed)); +#line 29 "mapping.cpp" + +// +// class mapdb_t: The mapping database +// +class mapdb_t +{ + friend class jdb; + +public: + enum { Size_factor = 4, + Size_id_max = 8 /* can be up to 15 (4 bits) */ }; + +private: + // DATA + physframe_data *physframe; + kmem_slab_t *allocator_for_treesize[Size_id_max + 1]; + +public: +#line 399 "mapping.cpp" + mapdb_t(); + +#line 450 "mapping.cpp" + // insert a new mapping entry with the given values as child of + // "parent" After locating the right place for the new entry, it will + // be stored there (if this place is empty) or the following entries + // moved by one entry. + + // We assume that there is at least one free entry at the end of the + // array so that at least one insert() operation can succeed between a + // lock()/free() pair of calls. This is guaranteed by the free() + // operation which allocates a larger tree if the current one becomes + // to small. + mapping_t * + insert(mapping_t *parent, + space_t *space, + vm_offset_t va, + vm_size_t size, + mapping_type_t type); + +#line 562 "mapping.cpp" + mapping_t * + lookup(space_t *space, + vm_offset_t va, + mapping_type_t type); + +#line 603 "mapping.cpp" + void + free(mapping_t* mapping_of_tree); + +#line 720 "mapping.cpp" + // Delete mappings from a tree. This is easy to do: We just have to + // iterate over the array encoding the tree. + bool + flush(mapping_t *m, bool me_too); + +#line 779 "mapping.cpp" + void + grant(mapping_t *m, space_t *new_space, vm_offset_t va); +}; + +// +// IMPLEMENTATION of inline functions (and needed classes) +// + +#line 191 "mapping.cpp" + +// Define (otherwise private) stuff needed by public inline +// functions. + +enum mapping_depth_t +{ + Depth_sigma0_mapping = 0, Depth_max = 253, + Depth_empty = 254, Depth_end = 255 +}; +#line 200 "mapping.cpp" + +struct mapping_s +{ + unsigned space:11; + unsigned size:1; + unsigned address:20; + mapping_depth_t depth:8; + unsigned do_not_touch: 24; // make this 64 bits, and make sure the + // compiler never touches memory after the + // real data +}; + +#line 215 "mapping.cpp" + + +inline mapping_s * +mapping_t::data() +{ + return reinterpret_cast(_data); +} + +#line 222 "mapping.cpp" + + +inline space_index_t +mapping_t::space() +{ + return space_index_t(data()->space); +} + +#line 229 "mapping.cpp" + + +inline vm_offset_t +mapping_t::vaddr() +{ + return (data()->address << PAGE_SHIFT); +} + +#line 236 "mapping.cpp" + + +inline vm_size_t +mapping_t::size() +{ + if ( data()->size ) + return SUPERPAGE_SIZE; + else + return PAGE_SIZE; +} + +#line 246 "mapping.cpp" + + +inline mapping_type_t +mapping_t::type() +{ + // return data()->type;; + return Map_mem; +} + +#endif // mapping_inline_h diff --git a/kernel/fiasco/tool/preprocess/test/verify/mapping_inline_i.h b/kernel/fiasco/tool/preprocess/test/verify/mapping_inline_i.h new file mode 100644 index 00000000..48878043 --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/verify/mapping_inline_i.h @@ -0,0 +1,112 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef mapping_inline_i_h +#define mapping_inline_i_h +#line 148 "mapping.cpp" + +#include +#line 150 "mapping.cpp" +#include +#line 385 "mapping.cpp" + +// +// class mapdb +// + +#include "lock.h" +#line 391 "mapping.cpp" +#include "kmem_slab.h" +#line 155 "mapping.cpp" + +// For implementation of mapping_t functions, we need mapping_tree_t. + +// +// class mapping_tree_t +// +class mapping_tree_t +{ + friend class mapping_t; + friend class mapdb_t; + friend class jdb; + + // DATA + unsigned _count: 16; + unsigned _size_id: 4; + unsigned _empty_count: 11; + unsigned _unused: 1; // make this 32 bits to avoid a compiler bug + + mapping_t _mappings[0] __attribute__((packed)); + + +public: +#line 347 "mapping.cpp" + // helpers + + // + // class mapping_tree_t + // + + // This function copies the elements of mapping tree src to mapping + // tree dst, ignoring empty elements (that is, compressing the + // source tree. In-place compression is supported. + static void + copy_compact_tree(mapping_tree_t *dst, mapping_tree_t *src); + +private: +#line 177 "mapping.cpp" + // public routines with inline implementations + + inline unsigned + number_of_entries() const; + +#line 186 "mapping.cpp" + inline mapping_t * + mappings(); +} __attribute__((packed)); +#line 392 "mapping.cpp" + +struct physframe_data { + mapping_tree_t *tree; + helping_lock_t lock; +}; + +// +// IMPLEMENTATION of inline functions follows +// + + +#line 211 "mapping.cpp" + + +inline mapping_t::mapping_t() +{} + +#line 254 "mapping.cpp" + + +inline bool +mapping_t::unused() +{ + return (data()->depth > Depth_max); +} + +#line 176 "mapping.cpp" + +// public routines with inline implementations + +inline unsigned +mapping_tree_t::number_of_entries() const +{ + return mapdb_t::Size_factor << _size_id; +} + +#line 184 "mapping.cpp" + + +inline mapping_t * +mapping_tree_t::mappings() +{ + return & _mappings[0]; +} + +#endif // mapping_inline_i_h diff --git a/kernel/fiasco/tool/preprocess/test/verify/multifile-part1.cc b/kernel/fiasco/tool/preprocess/test/verify/multifile-part1.cc new file mode 100644 index 00000000..e13bd4ba --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/verify/multifile-part1.cc @@ -0,0 +1,12 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#include "multifile.h" +#include "multifile_i.h" + + +#line 8 "multifile1.cpp" + + +void +Foo::bar() +{} diff --git a/kernel/fiasco/tool/preprocess/test/verify/multifile-part2.cc b/kernel/fiasco/tool/preprocess/test/verify/multifile-part2.cc new file mode 100644 index 00000000..788bd9fc --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/verify/multifile-part2.cc @@ -0,0 +1,12 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#include "multifile.h" +#include "multifile_i.h" + + +#line 13 "multifile2.cpp" + + +void +Foo::bingo(Bar* bar) +{} diff --git a/kernel/fiasco/tool/preprocess/test/verify/multifile.cc b/kernel/fiasco/tool/preprocess/test/verify/multifile.cc new file mode 100644 index 00000000..0b5c21e6 --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/verify/multifile.cc @@ -0,0 +1,12 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#include "multifile.h" +#include "multifile_i.h" + + +#line 20 "multifile1.cpp" + + +void +Foo::gizmatic() +{} diff --git a/kernel/fiasco/tool/preprocess/test/verify/multifile.h b/kernel/fiasco/tool/preprocess/test/verify/multifile.h new file mode 100644 index 00000000..970a8730 --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/verify/multifile.h @@ -0,0 +1,66 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef multifile_h +#define multifile_h + +// +// INTERFACE definition follows +// + +#line 7 "multifile2.cpp" + +class Bar; +#line 2 "multifile1.cpp" + +class Foo +{ + +#line 2 "multifile2.cpp" +private: + + int more; + +public: +#line 10 "multifile1.cpp" + void + bar(); + +#line 15 "multifile2.cpp" + void + bingo(Bar* bar); + +protected: +#line 15 "multifile1.cpp" + inline void + baz(); + +#line 20 "multifile2.cpp" + inline void + rambo(); + +private: +#line 22 "multifile1.cpp" + void + gizmatic(); +}; + +// +// IMPLEMENTATION of inline functions (and needed classes) +// + + +#line 18 "multifile2.cpp" + + +inline void +Foo::rambo() +{} + +#line 13 "multifile1.cpp" + + +inline void +Foo::baz() +{} + +#endif // multifile_h diff --git a/kernel/fiasco/tool/preprocess/test/verify/multifile_i.h b/kernel/fiasco/tool/preprocess/test/verify/multifile_i.h new file mode 100644 index 00000000..aee787ab --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/verify/multifile_i.h @@ -0,0 +1,9 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef multifile_i_h +#define multifile_i_h +#line 11 "multifile2.cpp" + +#include "bar.h" + +#endif // multifile_i_h diff --git a/kernel/fiasco/tool/preprocess/test/verify/noinline.cc b/kernel/fiasco/tool/preprocess/test/verify/noinline.cc new file mode 100644 index 00000000..271325ac --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/verify/noinline.cc @@ -0,0 +1,5 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#include "noinline.h" +#include "noinline_i.h" + diff --git a/kernel/fiasco/tool/preprocess/test/verify/noinline.h b/kernel/fiasco/tool/preprocess/test/verify/noinline.h new file mode 100644 index 00000000..b8cdf734 --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/verify/noinline.h @@ -0,0 +1,6 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef noinline_h +#define noinline_h + +#endif // noinline_h diff --git a/kernel/fiasco/tool/preprocess/test/verify/noinline_i.h b/kernel/fiasco/tool/preprocess/test/verify/noinline_i.h new file mode 100644 index 00000000..1bf95d17 --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/verify/noinline_i.h @@ -0,0 +1,12 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef noinline_i_h +#define noinline_i_h +#line 4 "noinline.cpp" + +// There is nothing to inline -- therefore, this #include directive +// should not be put in public header. + +#include "foo.h" + +#endif // noinline_i_h diff --git a/kernel/fiasco/tool/preprocess/test/verify/operator.cc b/kernel/fiasco/tool/preprocess/test/verify/operator.cc new file mode 100644 index 00000000..bce8b306 --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/verify/operator.cc @@ -0,0 +1,170 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#include "operator.h" +#include "operator_i.h" + + +#line 8 "operator.cpp" + + +void * +Foo::operator new(size_t) // funny comment +{ +} + +#line 14 "operator.cpp" + + +Foo& +Foo::operator+(const Foo&) // funny comment +{ +} + +#line 20 "operator.cpp" + + +Foo& +Foo::operator=(const Foo&) // funny comment +{ +} + +#line 26 "operator.cpp" + + +Foo& +Foo::operator*(const Foo&) // funny comment +{ +} + +#line 44 "operator.cpp" + +void* X::operator new(unsigned int) { return (void*)0; } + +#line 46 "operator.cpp" +void X::operator delete(void*) { } + +#line 47 "operator.cpp" +void* X::operator new[](unsigned int, int) { return (void*)0; } + +#line 48 "operator.cpp" +void X::operator delete[](void*) { } + +#line 49 "operator.cpp" +X X::operator+(const X&) { return *this; } + +#line 50 "operator.cpp" +X X::operator-(const X&) { return *this; } + +#line 51 "operator.cpp" +X X::operator*(const X&) { return *this; } + +#line 52 "operator.cpp" +X X::operator/(const X&) { return *this; } + +#line 53 "operator.cpp" +X X::operator%(const X&) { return *this; } + +#line 54 "operator.cpp" +X X::operator^(const X&) { return *this; } + +#line 55 "operator.cpp" +X X::operator&(const X&) { return *this; } + +#line 56 "operator.cpp" +X X::operator|(const X&) { return *this; } + +#line 57 "operator.cpp" +X X::operator~() { return *this; } + +#line 58 "operator.cpp" +X X::operator!() { return *this; } + +#line 59 "operator.cpp" +X& X::operator=(const X&) {return *this; } + +#line 60 "operator.cpp" +bool X::operator<(const X&) { return false; } + +#line 61 "operator.cpp" +bool X::operator>(const X&) { return false; } + +#line 62 "operator.cpp" +X& X::operator+=(const X&) { return *this; } + +#line 63 "operator.cpp" +X& X::operator-=(const X&) { return *this; } + +#line 64 "operator.cpp" +X& X::operator*=(const X&) { return *this; } + +#line 65 "operator.cpp" +X& X::operator/=(const X&) { return *this; } + +#line 66 "operator.cpp" +X& X::operator%=(const X&) { return *this; } + +#line 67 "operator.cpp" +X& X::operator^=(const X&) { return *this; } + +#line 68 "operator.cpp" +X& X::operator&=(const X&) { return *this; } + +#line 69 "operator.cpp" +X& X::operator|=(const X&) { return *this; } + +#line 70 "operator.cpp" +X X::operator<<(const X&) { return *this; } + +#line 71 "operator.cpp" +X X::operator>>(const X&) { return *this; } + +#line 72 "operator.cpp" +X& X::operator>>=(const X&) { return *this; } + +#line 73 "operator.cpp" +X& X::operator<<=(const X&) { return *this; } + +#line 74 "operator.cpp" +bool X::operator==(const X&) { return true; } + +#line 75 "operator.cpp" +bool X::operator!=(const X&) { return false; } + +#line 76 "operator.cpp" +bool X::operator<=(const X&) { return true; } + +#line 77 "operator.cpp" +bool X::operator>=(const X&) { return true; } + +#line 78 "operator.cpp" +bool X::operator&&(const X&) { return false; } + +#line 79 "operator.cpp" +bool X::operator||(const X&) { return true; } + +#line 80 "operator.cpp" +X& X::operator++() { return *this; } + +#line 81 "operator.cpp" +X X::operator++(int) { return *this; } + +#line 82 "operator.cpp" +X& X::operator--() { return *this; } + +#line 83 "operator.cpp" +X X::operator--(int) { return *this; } + +#line 84 "operator.cpp" +X& X::operator,(const X&) { return *this; } + +#line 85 "operator.cpp" +X* X::operator->*(const X&) { return this; } + +#line 86 "operator.cpp" +X* X::operator->() { return this; } + +#line 87 "operator.cpp" +int X::operator()(const X&) { return 0; } + +#line 88 "operator.cpp" +int X::operator[](const X&) { return 0; } diff --git a/kernel/fiasco/tool/preprocess/test/verify/operator.h b/kernel/fiasco/tool/preprocess/test/verify/operator.h new file mode 100644 index 00000000..1ce3cf4f --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/verify/operator.h @@ -0,0 +1,52 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef operator_h +#define operator_h + +// +// INTERFACE definition follows +// + +#line 2 "operator.cpp" + +class Foo +{ + +public: +#line 10 "operator.cpp" + void * + operator new(size_t); // funny comment + +#line 16 "operator.cpp" + Foo& + operator+(const Foo&); // funny comment + +#line 22 "operator.cpp" + Foo& + operator=(const Foo&); // funny comment + +#line 28 "operator.cpp" + Foo& + operator*(const Foo&); // funny comment +}; + +#line 34 "operator.cpp" +template std::vector& +operator <<(std::vector& in, const T& new_elem); + +// +// IMPLEMENTATION of function templates +// + + +#line 32 "operator.cpp" + + +template std::vector& +operator <<(std::vector& in, const T& new_elem) +{ + in.push_back (new_elem); + return in; +} + +#endif // operator_h diff --git a/kernel/fiasco/tool/preprocess/test/verify/operator_i.h b/kernel/fiasco/tool/preprocess/test/verify/operator_i.h new file mode 100644 index 00000000..807c7886 --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/verify/operator_i.h @@ -0,0 +1,144 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef operator_i_h +#define operator_i_h +#line 40 "operator.cpp" + +// Some systematic tests (contributed by Matthias Daum) + +struct X { +public: +#line 45 "operator.cpp" + void* operator new(unsigned int); + +#line 46 "operator.cpp" + void operator delete(void*); + +#line 47 "operator.cpp" + void* operator new[](unsigned int, int); + +#line 48 "operator.cpp" + void operator delete[](void*); + +#line 49 "operator.cpp" + X operator+(const X&); + +#line 50 "operator.cpp" + X operator-(const X&); + +#line 51 "operator.cpp" + X operator*(const X&); + +#line 52 "operator.cpp" + X operator/(const X&); + +#line 53 "operator.cpp" + X operator%(const X&); + +#line 54 "operator.cpp" + X operator^(const X&); + +#line 55 "operator.cpp" + X operator&(const X&); + +#line 56 "operator.cpp" + X operator|(const X&); + +#line 57 "operator.cpp" + X operator~(); + +#line 58 "operator.cpp" + X operator!(); + +#line 59 "operator.cpp" + X& operator=(const X&); + +#line 60 "operator.cpp" + bool operator<(const X&); + +#line 61 "operator.cpp" + bool operator>(const X&); + +#line 62 "operator.cpp" + X& operator+=(const X&); + +#line 63 "operator.cpp" + X& operator-=(const X&); + +#line 64 "operator.cpp" + X& operator*=(const X&); + +#line 65 "operator.cpp" + X& operator/=(const X&); + +#line 66 "operator.cpp" + X& operator%=(const X&); + +#line 67 "operator.cpp" + X& operator^=(const X&); + +#line 68 "operator.cpp" + X& operator&=(const X&); + +#line 69 "operator.cpp" + X& operator|=(const X&); + +#line 70 "operator.cpp" + X operator<<(const X&); + +#line 71 "operator.cpp" + X operator>>(const X&); + +#line 72 "operator.cpp" + X& operator>>=(const X&); + +#line 73 "operator.cpp" + X& operator<<=(const X&); + +#line 74 "operator.cpp" + bool operator==(const X&); + +#line 75 "operator.cpp" + bool operator!=(const X&); + +#line 76 "operator.cpp" + bool operator<=(const X&); + +#line 77 "operator.cpp" + bool operator>=(const X&); + +#line 78 "operator.cpp" + bool operator&&(const X&); + +#line 79 "operator.cpp" + bool operator||(const X&); + +#line 80 "operator.cpp" + X& operator++(); + +#line 81 "operator.cpp" + X operator++(int); + +#line 82 "operator.cpp" + X& operator--(); + +#line 83 "operator.cpp" + X operator--(int); + +#line 84 "operator.cpp" + X& operator,(const X&); + +#line 85 "operator.cpp" + X* operator->*(const X&); + +#line 86 "operator.cpp" + X* operator->(); + +#line 87 "operator.cpp" + int operator()(const X&); + +#line 88 "operator.cpp" + int operator[](const X&); +}; + +#endif // operator_i_h diff --git a/kernel/fiasco/tool/preprocess/test/verify/parser.cc b/kernel/fiasco/tool/preprocess/test/verify/parser.cc new file mode 100644 index 00000000..c1141673 --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/verify/parser.cc @@ -0,0 +1,55 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#include "parser.h" +#include "parser_i.h" + +#line 40 "parser.cpp" + +// Try to initialize a nested structure object. +struct Foo::Bar some_bar = { 1 }; +#line 79 "parser.cpp" + +void find_this (); +#line 85 "parser.cpp" + +#ifdef HEILIGE_WEIHNACHT +#line 87 "parser.cpp" +static void present_this (); +#line 88 "parser.cpp" +#endif + +#line 28 "parser.cpp" + +// Try function arguments +unsigned +somefunc(unsigned (*func1)(), + unsigned (*func2)()) +{ +} + +#line 43 "parser.cpp" + +// And add a Foo function +void Foo::func() +{} + +#line 47 "parser.cpp" + +// Try default arguments +void Foo::bar(int i, int j) +{} + +#line 51 "parser.cpp" + +// Try a constructor with weird syntax + +Foo::Foo() + : something (reinterpret_cast(Baz::bla())) +{} + +#line 57 "parser.cpp" + +// Try implementing an already-declared function +int +Foo::alreadythere() +{} diff --git a/kernel/fiasco/tool/preprocess/test/verify/parser.h b/kernel/fiasco/tool/preprocess/test/verify/parser.h new file mode 100644 index 00000000..36331671 --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/verify/parser.h @@ -0,0 +1,87 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef parser_h +#define parser_h + +// +// INTERFACE definition follows +// + +#line 2 "parser.cpp" + +struct Foo +{ + struct Bar + { + int baz; + }; + +public: + int alreadythere(); + inline int alsoalreadythere(); + +public: +#line 52 "parser.cpp" + // Try a constructor with weird syntax + + Foo(); + +private: +#line 44 "parser.cpp" + // And add a Foo function + void func(); + +#line 48 "parser.cpp" + // Try default arguments + void bar(int i = 15, int j = somefunc(0, somefunc(0, 0))); +}; + +#line 20 "parser.cpp" +inline int bar(); + +#line 23 "parser.cpp" +// Try multiline NEEDS + + +inline int baz(); + +#line 29 "parser.cpp" +// Try function arguments +unsigned +somefunc(unsigned (*func1)(), + unsigned (*func2)()); + +// +// IMPLEMENTATION includes follow (for use by inline functions/templates) +// + +#line 16 "parser.cpp" + +#include "foo.h" + +// +// IMPLEMENTATION of inline functions (and needed classes) +// + + +#line 62 "parser.cpp" + +inline int +Foo::alsoalreadythere() +{} + +#line 18 "parser.cpp" + + +inline int bar() +{} + +#line 22 "parser.cpp" + +// Try multiline NEEDS + + +inline int baz() +{} + +#endif // parser_h diff --git a/kernel/fiasco/tool/preprocess/test/verify/parser_i.h b/kernel/fiasco/tool/preprocess/test/verify/parser_i.h new file mode 100644 index 00000000..f7bec8b2 --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/verify/parser_i.h @@ -0,0 +1,14 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef parser_i_h +#define parser_i_h +#line 35 "parser.cpp" + +// Try function-pointer typedef +typedef int (* diag_printf_t) (const char *, ...); +#line 38 "parser.cpp" +typedef int (**dblfptr) (void); +#line 39 "parser.cpp" +typedef int (* arrfptr[20]) (void); + +#endif // parser_i_h diff --git a/kernel/fiasco/tool/preprocess/test/verify/parser_noinline.cc b/kernel/fiasco/tool/preprocess/test/verify/parser_noinline.cc new file mode 100644 index 00000000..346fb3e9 --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/verify/parser_noinline.cc @@ -0,0 +1,75 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#include "parser_noinline.h" +#include "parser_noinline_i.h" + +#line 40 "parser.cpp" + +// Try to initialize a nested structure object. +struct Foo::Bar some_bar = { 1 }; +#line 79 "parser.cpp" + +void find_this (); +#line 85 "parser.cpp" + +#ifdef HEILIGE_WEIHNACHT +#line 87 "parser.cpp" +static void present_this (); +#line 88 "parser.cpp" +#endif + +#line 18 "parser.cpp" + + +int bar() +{} + +#line 22 "parser.cpp" + +// Try multiline NEEDS + + +int baz() +{} + +#line 28 "parser.cpp" + +// Try function arguments +unsigned +somefunc(unsigned (*func1)(), + unsigned (*func2)()) +{ +} + +#line 43 "parser.cpp" + +// And add a Foo function +void Foo::func() +{} + +#line 47 "parser.cpp" + +// Try default arguments +void Foo::bar(int i, int j) +{} + +#line 51 "parser.cpp" + +// Try a constructor with weird syntax + +Foo::Foo() + : something (reinterpret_cast(Baz::bla())) +{} + +#line 57 "parser.cpp" + +// Try implementing an already-declared function +int +Foo::alreadythere() +{} + +#line 62 "parser.cpp" + +int +Foo::alsoalreadythere() +{} diff --git a/kernel/fiasco/tool/preprocess/test/verify/parser_noinline.h b/kernel/fiasco/tool/preprocess/test/verify/parser_noinline.h new file mode 100644 index 00000000..2b39909f --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/verify/parser_noinline.h @@ -0,0 +1,54 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef parser_noinline_h +#define parser_noinline_h + +// +// INTERFACE definition follows +// + +#line 2 "parser.cpp" + +struct Foo +{ + struct Bar + { + int baz; + }; + +public: + int alreadythere(); + int alsoalreadythere(); + +public: +#line 52 "parser.cpp" + // Try a constructor with weird syntax + + Foo(); + +private: +#line 44 "parser.cpp" + // And add a Foo function + void func(); + +#line 48 "parser.cpp" + // Try default arguments + void bar(int i = 15, int j = somefunc(0, somefunc(0, 0))); +}; + +#line 20 "parser.cpp" +int bar(); + +#line 23 "parser.cpp" +// Try multiline NEEDS + + +int baz(); + +#line 29 "parser.cpp" +// Try function arguments +unsigned +somefunc(unsigned (*func1)(), + unsigned (*func2)()); + +#endif // parser_noinline_h diff --git a/kernel/fiasco/tool/preprocess/test/verify/parser_noinline_i.h b/kernel/fiasco/tool/preprocess/test/verify/parser_noinline_i.h new file mode 100644 index 00000000..a3bdef2f --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/verify/parser_noinline_i.h @@ -0,0 +1,17 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef parser_noinline_i_h +#define parser_noinline_i_h +#line 16 "parser.cpp" + +#include "foo.h" +#line 35 "parser.cpp" + +// Try function-pointer typedef +typedef int (* diag_printf_t) (const char *, ...); +#line 38 "parser.cpp" +typedef int (**dblfptr) (void); +#line 39 "parser.cpp" +typedef int (* arrfptr[20]) (void); + +#endif // parser_noinline_i_h diff --git a/kernel/fiasco/tool/preprocess/test/verify/random.cc b/kernel/fiasco/tool/preprocess/test/verify/random.cc new file mode 100644 index 00000000..33245a47 --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/verify/random.cc @@ -0,0 +1,373 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#include "random.h" +#include "random_i.h" + + +#line 208 "random.cpp" +static void function60(); + +#line 211 "random.cpp" +static void function61(); + +#line 214 "random.cpp" +static void function62(); + +#line 217 "random.cpp" +static void function63(); + +#line 220 "random.cpp" +static void function64(); + +#line 23 "random.cpp" + +// Try combinations of {PUBLIC|PROTECTED|PRIVATE|} {static|} +// {inline|INLINE|inline NEEDS[]|INLINE NEEDS[]} {virtual|} + + +void Foo::function0() {} + +#line 29 "random.cpp" + + +void Foo::function1() {} + +#line 32 "random.cpp" + + +void Foo::function2() {} + +#line 35 "random.cpp" + + +void Foo::function3() {} + +#line 38 "random.cpp" + + +void Foo::function4() {} + +#line 41 "random.cpp" + + +void Foo::function5() {} + +#line 44 "random.cpp" + + +void Foo::function6() {} + +#line 47 "random.cpp" + + +void Foo::function7() {} + +#line 50 "random.cpp" + + +void Foo::function8() {} + +#line 53 "random.cpp" + + +void Foo::function9() {} + +#line 56 "random.cpp" + + +void Foo::function10() {} + +#line 59 "random.cpp" + + +void Foo::function11() {} + +#line 62 "random.cpp" + + +void Foo::function12() {} + +#line 65 "random.cpp" + + +void Foo::function13() {} + +#line 68 "random.cpp" + + +void Foo::function14() {} + +#line 71 "random.cpp" + + +void Foo::function15() {} + +#line 74 "random.cpp" + + +void Foo::function16() {} + +#line 77 "random.cpp" + + +void Foo::function17() {} + +#line 80 "random.cpp" + + +void Foo::function18() {} + +#line 83 "random.cpp" + + +void Foo::function19() {} + +#line 86 "random.cpp" + + +void Foo::function20() {} + +#line 89 "random.cpp" + + +void Foo::function21() {} + +#line 92 "random.cpp" + + +void Foo::function22() {} + +#line 95 "random.cpp" + + +void Foo::function23() {} + +#line 98 "random.cpp" + + +void Foo::function24() {} + +#line 101 "random.cpp" + + +void Foo::function25() {} + +#line 104 "random.cpp" + + +void Foo::function26() {} + +#line 107 "random.cpp" + + +void Foo::function27() {} + +#line 110 "random.cpp" + + +void Foo::function28() {} + +#line 113 "random.cpp" + + +void Foo::function29() {} + +#line 116 "random.cpp" + + +void Foo::function30() {} + +#line 119 "random.cpp" + + +void Foo::function31() {} + +#line 122 "random.cpp" + + +void Foo::function32() {} + +#line 125 "random.cpp" + + +void Foo::function33() {} + +#line 128 "random.cpp" + + +void Foo::function34() {} + +#line 131 "random.cpp" + + +void Foo::function35() {} + +#line 134 "random.cpp" + + +void Foo::function36() {} + +#line 137 "random.cpp" + + +void Foo::function37() {} + +#line 140 "random.cpp" + + +void Foo::function38() {} + +#line 143 "random.cpp" + + +void Foo::function39() {} + +#line 146 "random.cpp" + + +void Foo::function40() {} + +#line 149 "random.cpp" + + +void Foo::function41() {} + +#line 152 "random.cpp" + + +void Foo::function42() {} + +#line 155 "random.cpp" + + +void Foo::function43() {} + +#line 158 "random.cpp" + + +void Foo::function44() {} + +#line 161 "random.cpp" + + +void Foo::function45() {} + +#line 164 "random.cpp" + + +void Foo::function46() {} + +#line 167 "random.cpp" + + +void Foo::function47() {} + +#line 170 "random.cpp" + + +void Foo::function48() {} + +#line 173 "random.cpp" + + +void Foo::function49() {} + +#line 176 "random.cpp" + + +void Foo::function50() {} + +#line 179 "random.cpp" + + +void Foo::function51() {} + +#line 182 "random.cpp" + + +void Foo::function52() {} + +#line 185 "random.cpp" + + +void Foo::function53() {} + +#line 188 "random.cpp" + + +void Foo::function54() {} + +#line 191 "random.cpp" + + +void Foo::function55() {} + +#line 194 "random.cpp" + + +void Foo::function56() {} + +#line 197 "random.cpp" + + +void Foo::function57() {} + +#line 200 "random.cpp" + + +void Foo::function58() {} + +#line 203 "random.cpp" + + +void Foo::function59() {} + +#line 206 "random.cpp" + + +static void function60() {} + +#line 209 "random.cpp" + + +static void function61() {} + +#line 212 "random.cpp" + + +static void function62() {} + +#line 215 "random.cpp" + + +static void function63() {} + +#line 218 "random.cpp" + + +static void function64() {} + +#line 221 "random.cpp" + + +void function65() {} + +#line 224 "random.cpp" + + +void function66() {} + +#line 227 "random.cpp" + + +void function67() {} + +#line 230 "random.cpp" + + +void function68() {} + +#line 233 "random.cpp" + + +void function69() {} diff --git a/kernel/fiasco/tool/preprocess/test/verify/random.h b/kernel/fiasco/tool/preprocess/test/verify/random.h new file mode 100644 index 00000000..db77b0d7 --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/verify/random.h @@ -0,0 +1,227 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef random_h +#define random_h +#line 3 "random.cpp" + +#include "bar.h" + +// +// INTERFACE definition follows +// + +#line 5 "random.cpp" + +class Baz; +#line 7 "random.cpp" + +class Foo : public Bar +{ + // DATA + int d_data; + Baz* d_baz; + +public: +#line 24 "random.cpp" + // Try combinations of {PUBLIC|PROTECTED|PRIVATE|} {static|} + // {inline|INLINE|inline NEEDS[]|INLINE NEEDS[]} {virtual|} + + + static void function0(); + +#line 31 "random.cpp" + static void function1(); + +#line 34 "random.cpp" + static void function2(); + +#line 37 "random.cpp" + static void function3(); + +#line 40 "random.cpp" + static void function4(); + +#line 43 "random.cpp" + virtual void function5(); + +#line 46 "random.cpp" + void function6(); + +#line 49 "random.cpp" + virtual void function7(); + +#line 52 "random.cpp" + void function8(); + +#line 55 "random.cpp" + virtual void function9(); + +#line 58 "random.cpp" + void function10(); + +#line 61 "random.cpp" + virtual void function11(); + +#line 64 "random.cpp" + void function12(); + +#line 67 "random.cpp" + virtual void function13(); + +#line 70 "random.cpp" + void function14(); + +protected: +#line 73 "random.cpp" + static void function15(); + +#line 76 "random.cpp" + static void function16(); + +#line 79 "random.cpp" + static void function17(); + +#line 82 "random.cpp" + static void function18(); + +#line 85 "random.cpp" + static void function19(); + +#line 88 "random.cpp" + virtual void function20(); + +#line 91 "random.cpp" + void function21(); + +#line 94 "random.cpp" + virtual void function22(); + +#line 97 "random.cpp" + void function23(); + +#line 100 "random.cpp" + virtual void function24(); + +#line 103 "random.cpp" + void function25(); + +#line 106 "random.cpp" + virtual void function26(); + +#line 109 "random.cpp" + void function27(); + +#line 112 "random.cpp" + virtual void function28(); + +#line 115 "random.cpp" + void function29(); + +private: +#line 118 "random.cpp" + static void function30(); + +#line 121 "random.cpp" + static void function31(); + +#line 124 "random.cpp" + static void function32(); + +#line 127 "random.cpp" + static void function33(); + +#line 130 "random.cpp" + static void function34(); + +#line 133 "random.cpp" + virtual void function35(); + +#line 136 "random.cpp" + void function36(); + +#line 139 "random.cpp" + virtual void function37(); + +#line 142 "random.cpp" + void function38(); + +#line 145 "random.cpp" + virtual void function39(); + +#line 148 "random.cpp" + void function40(); + +#line 151 "random.cpp" + virtual void function41(); + +#line 154 "random.cpp" + void function42(); + +#line 157 "random.cpp" + virtual void function43(); + +#line 160 "random.cpp" + void function44(); + +#line 163 "random.cpp" + static void function45(); + +#line 166 "random.cpp" + static void function46(); + +#line 169 "random.cpp" + static void function47(); + +#line 172 "random.cpp" + static void function48(); + +#line 175 "random.cpp" + static void function49(); + +#line 178 "random.cpp" + virtual void function50(); + +#line 181 "random.cpp" + void function51(); + +#line 184 "random.cpp" + virtual void function52(); + +#line 187 "random.cpp" + void function53(); + +#line 190 "random.cpp" + virtual void function54(); + +#line 193 "random.cpp" + void function55(); + +#line 196 "random.cpp" + virtual void function56(); + +#line 199 "random.cpp" + void function57(); + +#line 202 "random.cpp" + virtual void function58(); + +#line 205 "random.cpp" + void function59(); +}; + +#line 223 "random.cpp" +void function65(); + +#line 226 "random.cpp" +void function66(); + +#line 229 "random.cpp" +void function67(); + +#line 232 "random.cpp" +void function68(); + +#line 235 "random.cpp" +void function69(); + +#endif // random_h diff --git a/kernel/fiasco/tool/preprocess/test/verify/random_i.h b/kernel/fiasco/tool/preprocess/test/verify/random_i.h new file mode 100644 index 00000000..06622035 --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/verify/random_i.h @@ -0,0 +1,16 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef random_i_h +#define random_i_h +#line 16 "random.cpp" + +#include "yes.h" +#line 18 "random.cpp" +#include +#line 19 "random.cpp" + +class Rambo +{ +}; + +#endif // random_i_h diff --git a/kernel/fiasco/tool/preprocess/test/verify/random_inline.cc b/kernel/fiasco/tool/preprocess/test/verify/random_inline.cc new file mode 100644 index 00000000..1244895e --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/verify/random_inline.cc @@ -0,0 +1,110 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#include "random_inline.h" +#include "random_inline_i.h" + + +#line 208 "random.cpp" +static inline void function60(); + +#line 211 "random.cpp" +static inline void function61(); + +#line 214 "random.cpp" +static inline void function62(); + +#line 217 "random.cpp" +static inline void function63(); + +#line 220 "random.cpp" +static void function64(); + +#line 206 "random.cpp" + + +static inline void function60() {} + +#line 209 "random.cpp" + + +static inline void function61() {} + +#line 212 "random.cpp" + + +static inline void function62() {} + +#line 215 "random.cpp" + + +static inline void function63() {} + +#line 38 "random.cpp" + + +void Foo::function4() {} + +#line 65 "random.cpp" + + +void Foo::function13() {} + +#line 68 "random.cpp" + + +void Foo::function14() {} + +#line 83 "random.cpp" + + +void Foo::function19() {} + +#line 110 "random.cpp" + + +void Foo::function28() {} + +#line 113 "random.cpp" + + +void Foo::function29() {} + +#line 128 "random.cpp" + + +void Foo::function34() {} + +#line 155 "random.cpp" + + +void Foo::function43() {} + +#line 158 "random.cpp" + + +void Foo::function44() {} + +#line 173 "random.cpp" + + +void Foo::function49() {} + +#line 200 "random.cpp" + + +void Foo::function58() {} + +#line 203 "random.cpp" + + +void Foo::function59() {} + +#line 218 "random.cpp" + + +static void function64() {} + +#line 233 "random.cpp" + + +void function69() {} diff --git a/kernel/fiasco/tool/preprocess/test/verify/random_inline.h b/kernel/fiasco/tool/preprocess/test/verify/random_inline.h new file mode 100644 index 00000000..03ff3634 --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/verify/random_inline.h @@ -0,0 +1,388 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef random_inline_h +#define random_inline_h +#line 3 "random.cpp" + +#include "bar.h" + +// +// INTERFACE definition follows +// + +#line 5 "random.cpp" + +class Baz; +#line 7 "random.cpp" + +class Foo : public Bar +{ + // DATA + int d_data; + Baz* d_baz; + +public: +#line 24 "random.cpp" + // Try combinations of {PUBLIC|PROTECTED|PRIVATE|} {static|} + // {inline|INLINE|inline NEEDS[]|INLINE NEEDS[]} {virtual|} + + + static inline void function0(); + +#line 31 "random.cpp" + static inline void function1(); + +#line 34 "random.cpp" + static inline void function2(); + +#line 37 "random.cpp" + static inline void function3(); + +#line 40 "random.cpp" + static void function4(); + +#line 43 "random.cpp" + virtual inline void function5(); + +#line 46 "random.cpp" + inline void function6(); + +#line 49 "random.cpp" + virtual inline void function7(); + +#line 52 "random.cpp" + inline void function8(); + +#line 55 "random.cpp" + virtual inline void function9(); + +#line 58 "random.cpp" + inline void function10(); + +#line 61 "random.cpp" + virtual inline void function11(); + +#line 64 "random.cpp" + inline void function12(); + +#line 67 "random.cpp" + virtual void function13(); + +#line 70 "random.cpp" + void function14(); + +protected: +#line 73 "random.cpp" + static inline void function15(); + +#line 76 "random.cpp" + static inline void function16(); + +#line 79 "random.cpp" + static inline void function17(); + +#line 82 "random.cpp" + static inline void function18(); + +#line 85 "random.cpp" + static void function19(); + +#line 88 "random.cpp" + virtual inline void function20(); + +#line 91 "random.cpp" + inline void function21(); + +#line 94 "random.cpp" + virtual inline void function22(); + +#line 97 "random.cpp" + inline void function23(); + +#line 100 "random.cpp" + virtual inline void function24(); + +#line 103 "random.cpp" + inline void function25(); + +#line 106 "random.cpp" + virtual inline void function26(); + +#line 109 "random.cpp" + inline void function27(); + +#line 112 "random.cpp" + virtual void function28(); + +#line 115 "random.cpp" + void function29(); + +private: +#line 118 "random.cpp" + static inline void function30(); + +#line 121 "random.cpp" + static inline void function31(); + +#line 124 "random.cpp" + static inline void function32(); + +#line 127 "random.cpp" + static inline void function33(); + +#line 130 "random.cpp" + static void function34(); + +#line 133 "random.cpp" + virtual inline void function35(); + +#line 136 "random.cpp" + inline void function36(); + +#line 139 "random.cpp" + virtual inline void function37(); + +#line 142 "random.cpp" + inline void function38(); + +#line 145 "random.cpp" + virtual inline void function39(); + +#line 148 "random.cpp" + inline void function40(); + +#line 151 "random.cpp" + virtual inline void function41(); + +#line 154 "random.cpp" + inline void function42(); + +#line 157 "random.cpp" + virtual void function43(); + +#line 160 "random.cpp" + void function44(); + +#line 163 "random.cpp" + static inline void function45(); + +#line 166 "random.cpp" + static inline void function46(); + +#line 169 "random.cpp" + static inline void function47(); + +#line 172 "random.cpp" + static inline void function48(); + +#line 175 "random.cpp" + static void function49(); + +#line 178 "random.cpp" + virtual inline void function50(); + +#line 181 "random.cpp" + inline void function51(); + +#line 184 "random.cpp" + virtual inline void function52(); + +#line 187 "random.cpp" + inline void function53(); + +#line 190 "random.cpp" + virtual inline void function54(); + +#line 193 "random.cpp" + inline void function55(); + +#line 196 "random.cpp" + virtual inline void function56(); + +#line 199 "random.cpp" + inline void function57(); + +#line 202 "random.cpp" + virtual void function58(); + +#line 205 "random.cpp" + void function59(); +}; + +#line 223 "random.cpp" +inline void function65(); + +#line 226 "random.cpp" +inline void function66(); + +#line 229 "random.cpp" +inline void function67(); + +#line 232 "random.cpp" +inline void function68(); + +#line 235 "random.cpp" +void function69(); + +// +// IMPLEMENTATION includes follow (for use by inline functions/templates) +// + +#line 16 "random.cpp" + +#include "yes.h" + +// +// IMPLEMENTATION of inline functions (and needed classes) +// + +#line 19 "random.cpp" + +class Rambo +{ +}; + +#line 23 "random.cpp" + +// Try combinations of {PUBLIC|PROTECTED|PRIVATE|} {static|} +// {inline|INLINE|inline NEEDS[]|INLINE NEEDS[]} {virtual|} + + +inline void Foo::function0() {} + +#line 29 "random.cpp" + + +inline void Foo::function1() {} + +#line 32 "random.cpp" + + +inline void Foo::function2() {} + +#line 35 "random.cpp" + + +inline void Foo::function3() {} + +#line 41 "random.cpp" + + +inline void Foo::function5() {} + +#line 44 "random.cpp" + + +inline void Foo::function6() {} + +#line 47 "random.cpp" + + +inline void Foo::function7() {} + +#line 50 "random.cpp" + + +inline void Foo::function8() {} + +#line 53 "random.cpp" + + +inline void Foo::function9() {} + +#line 56 "random.cpp" + + +inline void Foo::function10() {} + +#line 59 "random.cpp" + + +inline void Foo::function11() {} + +#line 62 "random.cpp" + + +inline void Foo::function12() {} + +#line 71 "random.cpp" + + +inline void Foo::function15() {} + +#line 74 "random.cpp" + + +inline void Foo::function16() {} + +#line 77 "random.cpp" + + +inline void Foo::function17() {} + +#line 80 "random.cpp" + + +inline void Foo::function18() {} + +#line 86 "random.cpp" + + +inline void Foo::function20() {} + +#line 89 "random.cpp" + + +inline void Foo::function21() {} + +#line 92 "random.cpp" + + +inline void Foo::function22() {} + +#line 95 "random.cpp" + + +inline void Foo::function23() {} + +#line 98 "random.cpp" + + +inline void Foo::function24() {} + +#line 101 "random.cpp" + + +inline void Foo::function25() {} + +#line 104 "random.cpp" + + +inline void Foo::function26() {} + +#line 107 "random.cpp" + + +inline void Foo::function27() {} + +#line 221 "random.cpp" + + +inline void function65() {} + +#line 224 "random.cpp" + + +inline void function66() {} + +#line 227 "random.cpp" + + +inline void function67() {} + +#line 230 "random.cpp" + + +inline void function68() {} + +#endif // random_inline_h diff --git a/kernel/fiasco/tool/preprocess/test/verify/random_inline_i.h b/kernel/fiasco/tool/preprocess/test/verify/random_inline_i.h new file mode 100644 index 00000000..a07def5d --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/verify/random_inline_i.h @@ -0,0 +1,133 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef random_inline_i_h +#define random_inline_i_h +#line 18 "random.cpp" +#include + +// +// IMPLEMENTATION of inline functions follows +// + + +#line 116 "random.cpp" + + +inline void Foo::function30() {} + +#line 119 "random.cpp" + + +inline void Foo::function31() {} + +#line 122 "random.cpp" + + +inline void Foo::function32() {} + +#line 125 "random.cpp" + + +inline void Foo::function33() {} + +#line 131 "random.cpp" + + +inline void Foo::function35() {} + +#line 134 "random.cpp" + + +inline void Foo::function36() {} + +#line 137 "random.cpp" + + +inline void Foo::function37() {} + +#line 140 "random.cpp" + + +inline void Foo::function38() {} + +#line 143 "random.cpp" + + +inline void Foo::function39() {} + +#line 146 "random.cpp" + + +inline void Foo::function40() {} + +#line 149 "random.cpp" + + +inline void Foo::function41() {} + +#line 152 "random.cpp" + + +inline void Foo::function42() {} + +#line 161 "random.cpp" + + +inline void Foo::function45() {} + +#line 164 "random.cpp" + + +inline void Foo::function46() {} + +#line 167 "random.cpp" + + +inline void Foo::function47() {} + +#line 170 "random.cpp" + + +inline void Foo::function48() {} + +#line 176 "random.cpp" + + +inline void Foo::function50() {} + +#line 179 "random.cpp" + + +inline void Foo::function51() {} + +#line 182 "random.cpp" + + +inline void Foo::function52() {} + +#line 185 "random.cpp" + + +inline void Foo::function53() {} + +#line 188 "random.cpp" + + +inline void Foo::function54() {} + +#line 191 "random.cpp" + + +inline void Foo::function55() {} + +#line 194 "random.cpp" + + +inline void Foo::function56() {} + +#line 197 "random.cpp" + + +inline void Foo::function57() {} + +#endif // random_inline_i_h diff --git a/kernel/fiasco/tool/preprocess/test/verify/static.cc b/kernel/fiasco/tool/preprocess/test/verify/static.cc new file mode 100644 index 00000000..6b0c95cc --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/verify/static.cc @@ -0,0 +1,35 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#include "static.h" +#include "static_i.h" + +#line 4 "static.cpp" + +extern "C" { + extern char _mappings_1, _mappings_end_1; +} +#line 8 "static.cpp" + +static const vm_offset_t mem_alloc_region + = reinterpret_cast(&_mappings_1); +#line 11 "static.cpp" + +static const vm_offset_t mem_alloc_region_end + = reinterpret_cast(&_mappings_end_1); +#line 14 "static.cpp" + +static kmem_slab_t *amm_entry_cache; +#line 16 "static.cpp" + +static amm_t region_amm; +#line 18 "static.cpp" +static oskit_addr_t end_of_last_region; +#line 19 "static.cpp" +static helping_lock_t region_lock; +#line 20 "static.cpp" + +static char keymap[128][2] = { + {'[', '{'}, +// {']', '}'}, /* 27 */ + {'+', '*'}, /* 27 */ +}; diff --git a/kernel/fiasco/tool/preprocess/test/verify/static.h b/kernel/fiasco/tool/preprocess/test/verify/static.h new file mode 100644 index 00000000..455ac744 --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/verify/static.h @@ -0,0 +1,6 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef static_h +#define static_h + +#endif // static_h diff --git a/kernel/fiasco/tool/preprocess/test/verify/static_i.h b/kernel/fiasco/tool/preprocess/test/verify/static_i.h new file mode 100644 index 00000000..e24f016b --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/verify/static_i.h @@ -0,0 +1,6 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef static_i_h +#define static_i_h + +#endif // static_i_h diff --git a/kernel/fiasco/tool/preprocess/test/verify/template.cc b/kernel/fiasco/tool/preprocess/test/verify/template.cc new file mode 100644 index 00000000..2e60849f --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/verify/template.cc @@ -0,0 +1,24 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#include "template.h" +#include "template_i.h" + + +#line 185 "template.cpp" + + +template <> stack_t* +create_stack() +{ + return new stack(); +} + +#line 192 "template.cpp" + + + +template <> stack_t* +create_stack() +{ + return new stack(); +} diff --git a/kernel/fiasco/tool/preprocess/test/verify/template.h b/kernel/fiasco/tool/preprocess/test/verify/template.h new file mode 100644 index 00000000..320fceb2 --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/verify/template.h @@ -0,0 +1,301 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef template_h +#define template_h + +// +// INTERFACE definition follows +// + +#line 2 "template.cpp" + +template +class stack_t; +#line 5 "template.cpp" + +template +class stack_top_t +{ +private: + friend class stack_t; + + // Dont change the layout !!, comp_and_swap2 expects + // version and _next next to each other, in that order + int _version; + T *_next; + +public: +#line 46 "template.cpp" + // + // stack_top_t + // + + // template + // stack_top_t & + // stack_top_t::operator=(const stack_top_t& _copy){ + // _version = _copy._version; + // _next = _copy._next; + // return *this; + // } + + + + stack_top_t(int version, T *next); + +#line 67 "template.cpp" + stack_top_t(); +}; +#line 17 "template.cpp" + +template +class stack_t +{ +private: + stack_top_t _head; + +public: +#line 72 "template.cpp" + // + // stack_t + // + + + + stack_t(); + +#line 84 "template.cpp" + int + insert(T *e); + +#line 103 "template.cpp" + T* + dequeue(); + +#line 132 "template.cpp" + // This version of dequeue only returns a value + // if it is equal to the one passed as top + + + T* + dequeue(T *top); + +#line 164 "template.cpp" + T* + first(); + +#line 172 "template.cpp" + void + reset(); +}; + +#line 27 "template.cpp" +// +// atomic-manipulation functions +// + +// typesafe variants + +template bool compare_and_swap(I *ptr, I oldval, I newval); + +#line 41 "template.cpp" +template bool test_and_set(I *l); + +#line 180 "template.cpp" +template stack_t* +create_stack(); + +#line 187 "template.cpp" +template <> stack_t* +create_stack(); + +#line 195 "template.cpp" +template <> stack_t* +create_stack(); + +// +// IMPLEMENTATION of function templates +// + + +#line 26 "template.cpp" + +// +// atomic-manipulation functions +// + +// typesafe variants + +template bool compare_and_swap(I *ptr, I oldval, I newval) +{ + return compare_and_swap(reinterpret_cast(ptr), + *reinterpret_cast(&oldval), + *reinterpret_cast(&newval)); +} + +#line 39 "template.cpp" + + +template bool test_and_set(I *l) +{ + return test_and_set(reinterpret_cast(l)); +} + +#line 45 "template.cpp" + +// +// stack_top_t +// + +// template +// stack_top_t & +// stack_top_t::operator=(const stack_top_t& _copy){ +// _version = _copy._version; +// _next = _copy._next; +// return *this; +// } + + + +template stack_top_t::stack_top_t(int version, T *next) + : _version (version), + _next (next) +{} + +#line 64 "template.cpp" + + + +template stack_top_t::stack_top_t() + : _version (0), + _next (0) +{} + +#line 71 "template.cpp" + +// +// stack_t +// + + + +template stack_t::stack_t() + : _head (0, 0) +{} + +#line 81 "template.cpp" + + + +template int +stack_t::insert(T *e) +{ + stack_top_t old_head, + new_head; + + do { + e->set_next(_head._next); + old_head = _head; + new_head._version = _head._version+1; + new_head._next = e; + } while (! compare_and_swap2((int *) &_head, + (int *) &old_head, + (int *) &new_head)); + return new_head._version; +} + +#line 100 "template.cpp" + + + +template T* +stack_t::dequeue() +{ + stack_top_t old_head, + new_head; + + T *first; + + do { + old_head = _head; + + first = _head._next; + if(! first){ + break; + } + + new_head._next = first->get_next(); + new_head._version = _head._version + 1; + } while (! compare_and_swap2((int *) &_head, + (int *) &old_head, + (int *) &new_head)); + // XXX Why did the old implementation test on e ? + // while (e && ! compare_and_swap(&_first, e, e->list_property.next)); + // This is necessary to handle the case of a empty stack. + + // return old_head._next; + return first; +} + +#line 131 "template.cpp" + +// This version of dequeue only returns a value +// if it is equal to the one passed as top + + +template T* +stack_t::dequeue(T *top) +{ + stack_top_t old_head, + new_head; + // stack_elem_t *first; + + old_head._version = _head._version; // version doesnt matter + old_head._next = top; // cas will fail, if top aint at top + if(!_head._next){ // empty stack + return 0; + } + new_head._version = _head._version + 1; + new_head._next = top->get_next(); + + + if(! compare_and_swap2((int *) &_head, + (int *) &old_head, + (int *) &new_head)) + // we didnt succeed + return 0; + else + // top was on top , so we dequeued it + return top; +} + +#line 161 "template.cpp" + + + +template T* +stack_t::first() +{ + return _head._next; +} + +#line 169 "template.cpp" + + + +template void +stack_t::reset() +{ + _head._version = 0; + _head._next = 0; +} + +#line 178 "template.cpp" + + +template stack_t* +create_stack() +{ + return new stack_t(); +} + +#endif // template_h diff --git a/kernel/fiasco/tool/preprocess/test/verify/template_i.h b/kernel/fiasco/tool/preprocess/test/verify/template_i.h new file mode 100644 index 00000000..350b8566 --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/verify/template_i.h @@ -0,0 +1,65 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef template_i_h +#define template_i_h +#line 200 "template.cpp" + +// +// Member templates +// + +class Foo +{ + template T* goo(T* t); + +public: +#line 217 "template.cpp" + template T* + bar(T* t); +}; +#line 209 "template.cpp" + +template +class TFoo +{ + +public: +#line 231 "template.cpp" + template T* + baz(T* t); +}; + +// +// IMPLEMENTATION of function templates +// + + +#line 214 "template.cpp" + + + +template T* +Foo::bar(T* t) +{ +} + +#line 221 "template.cpp" + + + +template T* +Foo::goo(T* t) +{ +} + +#line 228 "template.cpp" + + + + +template template T* +TFoo::baz(T* t) +{ +} + +#endif // template_i_h diff --git a/kernel/fiasco/tool/preprocess/test/verify/template_inline.cc b/kernel/fiasco/tool/preprocess/test/verify/template_inline.cc new file mode 100644 index 00000000..5bff8e9e --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/verify/template_inline.cc @@ -0,0 +1,14 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#include "template_inline.h" +#include "template_inline_i.h" + + +#line 185 "template.cpp" + + +template <> stack_t* +create_stack() +{ + return new stack(); +} diff --git a/kernel/fiasco/tool/preprocess/test/verify/template_inline.h b/kernel/fiasco/tool/preprocess/test/verify/template_inline.h new file mode 100644 index 00000000..b90c7965 --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/verify/template_inline.h @@ -0,0 +1,316 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef template_inline_h +#define template_inline_h + +// +// INTERFACE definition follows +// + +#line 2 "template.cpp" + +template +class stack_t; +#line 5 "template.cpp" + +template +class stack_top_t +{ +private: + friend class stack_t; + + // Dont change the layout !!, comp_and_swap2 expects + // version and _next next to each other, in that order + int _version; + T *_next; + +public: +#line 46 "template.cpp" + // + // stack_top_t + // + + // template + // stack_top_t & + // stack_top_t::operator=(const stack_top_t& _copy){ + // _version = _copy._version; + // _next = _copy._next; + // return *this; + // } + + + + inline stack_top_t(int version, T *next); + +#line 67 "template.cpp" + inline stack_top_t(); +}; +#line 17 "template.cpp" + +template +class stack_t +{ +private: + stack_top_t _head; + +public: +#line 72 "template.cpp" + // + // stack_t + // + + + + stack_t(); + +#line 84 "template.cpp" + int + insert(T *e); + +#line 103 "template.cpp" + T* + dequeue(); + +#line 132 "template.cpp" + // This version of dequeue only returns a value + // if it is equal to the one passed as top + + + T* + dequeue(T *top); + +#line 164 "template.cpp" + T* + first(); + +#line 172 "template.cpp" + void + reset(); +}; + +#line 27 "template.cpp" +// +// atomic-manipulation functions +// + +// typesafe variants + +template inline bool compare_and_swap(I *ptr, I oldval, I newval); + +#line 41 "template.cpp" +template inline bool test_and_set(I *l); + +#line 180 "template.cpp" +template stack_t* +create_stack(); + +#line 187 "template.cpp" +template <> stack_t* +create_stack(); + +#line 195 "template.cpp" +template <> inline stack_t* +create_stack(); + +// +// IMPLEMENTATION of inline functions (and needed classes) +// + + +#line 45 "template.cpp" + +// +// stack_top_t +// + +// template +// stack_top_t & +// stack_top_t::operator=(const stack_top_t& _copy){ +// _version = _copy._version; +// _next = _copy._next; +// return *this; +// } + + + +template inline stack_top_t::stack_top_t(int version, T *next) + : _version (version), + _next (next) +{} + +#line 64 "template.cpp" + + + +template inline stack_top_t::stack_top_t() + : _version (0), + _next (0) +{} + +#line 26 "template.cpp" + +// +// atomic-manipulation functions +// + +// typesafe variants + +template inline bool compare_and_swap(I *ptr, I oldval, I newval) +{ + return compare_and_swap(reinterpret_cast(ptr), + *reinterpret_cast(&oldval), + *reinterpret_cast(&newval)); +} + +#line 39 "template.cpp" + + +template inline bool test_and_set(I *l) +{ + return test_and_set(reinterpret_cast(l)); +} + +#line 192 "template.cpp" + + + +template <> inline stack_t* +create_stack() +{ + return new stack(); +} + +// +// IMPLEMENTATION of function templates +// + + +#line 71 "template.cpp" + +// +// stack_t +// + + + +template stack_t::stack_t() + : _head (0, 0) +{} + +#line 81 "template.cpp" + + + +template int +stack_t::insert(T *e) +{ + stack_top_t old_head, + new_head; + + do { + e->set_next(_head._next); + old_head = _head; + new_head._version = _head._version+1; + new_head._next = e; + } while (! compare_and_swap2((int *) &_head, + (int *) &old_head, + (int *) &new_head)); + return new_head._version; +} + +#line 100 "template.cpp" + + + +template T* +stack_t::dequeue() +{ + stack_top_t old_head, + new_head; + + T *first; + + do { + old_head = _head; + + first = _head._next; + if(! first){ + break; + } + + new_head._next = first->get_next(); + new_head._version = _head._version + 1; + } while (! compare_and_swap2((int *) &_head, + (int *) &old_head, + (int *) &new_head)); + // XXX Why did the old implementation test on e ? + // while (e && ! compare_and_swap(&_first, e, e->list_property.next)); + // This is necessary to handle the case of a empty stack. + + // return old_head._next; + return first; +} + +#line 131 "template.cpp" + +// This version of dequeue only returns a value +// if it is equal to the one passed as top + + +template T* +stack_t::dequeue(T *top) +{ + stack_top_t old_head, + new_head; + // stack_elem_t *first; + + old_head._version = _head._version; // version doesnt matter + old_head._next = top; // cas will fail, if top aint at top + if(!_head._next){ // empty stack + return 0; + } + new_head._version = _head._version + 1; + new_head._next = top->get_next(); + + + if(! compare_and_swap2((int *) &_head, + (int *) &old_head, + (int *) &new_head)) + // we didnt succeed + return 0; + else + // top was on top , so we dequeued it + return top; +} + +#line 161 "template.cpp" + + + +template T* +stack_t::first() +{ + return _head._next; +} + +#line 169 "template.cpp" + + + +template void +stack_t::reset() +{ + _head._version = 0; + _head._next = 0; +} + +#line 178 "template.cpp" + + +template stack_t* +create_stack() +{ + return new stack_t(); +} + +#endif // template_inline_h diff --git a/kernel/fiasco/tool/preprocess/test/verify/template_inline_i.h b/kernel/fiasco/tool/preprocess/test/verify/template_inline_i.h new file mode 100644 index 00000000..a967c26d --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/verify/template_inline_i.h @@ -0,0 +1,65 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef template_inline_i_h +#define template_inline_i_h +#line 200 "template.cpp" + +// +// Member templates +// + +class Foo +{ + template T* goo(T* t); + +public: +#line 217 "template.cpp" + template T* + bar(T* t); +}; +#line 209 "template.cpp" + +template +class TFoo +{ + +public: +#line 231 "template.cpp" + template T* + baz(T* t); +}; + +// +// IMPLEMENTATION of function templates +// + + +#line 214 "template.cpp" + + + +template T* +Foo::bar(T* t) +{ +} + +#line 221 "template.cpp" + + + +template T* +Foo::goo(T* t) +{ +} + +#line 228 "template.cpp" + + + + +template template T* +TFoo::baz(T* t) +{ +} + +#endif // template_inline_i_h diff --git a/kernel/fiasco/tool/preprocess/test/verify/variable.cc b/kernel/fiasco/tool/preprocess/test/verify/variable.cc new file mode 100644 index 00000000..99f6c2a5 --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/verify/variable.cc @@ -0,0 +1,11 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#include "variable.h" +#include "variable_i.h" + +#line 2 "variable.cpp" + +int (Foo::*func_vec[100]) (int arg) = +{ + 0, +}; diff --git a/kernel/fiasco/tool/preprocess/test/verify/variable.h b/kernel/fiasco/tool/preprocess/test/verify/variable.h new file mode 100644 index 00000000..5db219a5 --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/verify/variable.h @@ -0,0 +1,6 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef variable_h +#define variable_h + +#endif // variable_h diff --git a/kernel/fiasco/tool/preprocess/test/verify/variable_i.h b/kernel/fiasco/tool/preprocess/test/verify/variable_i.h new file mode 100644 index 00000000..a8eda5d3 --- /dev/null +++ b/kernel/fiasco/tool/preprocess/test/verify/variable_i.h @@ -0,0 +1,6 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef variable_i_h +#define variable_i_h + +#endif // variable_i_h diff --git a/kernel/fiasco/tool/showdeps b/kernel/fiasco/tool/showdeps new file mode 100755 index 00000000..9e4cf997 --- /dev/null +++ b/kernel/fiasco/tool/showdeps @@ -0,0 +1,148 @@ +#!/usr/bin/perl -w + +$mode = "ascii"; +$mode = shift @ARGV if ($#ARGV > -1); + +@input = <>; +$_ = join '', @input; + +s/\\\n//sg; # delete continuations +s/^([^.-]+)[^.]*\..*:/${1}:/mg; # keep only first word before ":", w/o "-" +s/\s\.\.\/[^\s]+//sg; # remove all dependencies not in our dir +s|\s/[^\s]+||sg; # remove all dependencies not in our dir +s|\s+[A-Za-z0-9_/]+/([A-Za-z0-9_\.-]+)]*| $1|g; # keep basenames only +s|\s+([A-Za-z0-9_-]+)\.[^\s]*| $1|g; # keep basenames only +s|\s+([A-Za-z0-9_]+)-[^\s]*| $1|g; # drop everything after "-" +s/ +/ /sg; # remove multiple spaces + +# +# Read single-module dependencies +# + +foreach my $line (split /\n/) + { + my ($target, $deps) = split /:\s*/, $line; + + @deps = sort grep {! /^${target}(?:_i)?$/ } split / /, $deps; + + push @{$target_deps{$target}}, @deps; + + foreach my $module (@deps) + { + push @{$depending_on{$module}}, $target; + } + } + +if ($mode eq "ascii") + { + show_deps(); + } +elsif ($mode eq "dot") + { + print_dot(); + } +# elsif ($mode eq "circular") +# { +# print_circular(); +# } + +sub show_deps { + # + # Compute cycles + # + + foreach my $module (keys %target_deps) + { + $all_deps{$module} = finddeps ($module, {}); + } + + # + # Print dependencies per module + # + + foreach my $module (sort keys %target_deps) + { + my %found; + + foreach my $called_by (@{$depending_on{$module}}) + { + next if defined $found{$called_by}; + $found{$called_by} = 1; + + print " $called_by" . (defined $all_deps{$module}->{$called_by} + ? " *" : "") . "\n"; + } + + print "$module\n"; + + %found = (); + + foreach my $calling (@{$target_deps{$module}}) + { + next if defined $found{$calling}; + $found{$calling} = 1; + + print " $calling" . (defined $all_deps{$calling}->{$module} + ? " *" : "") . "\n"; + } + + print "\n---\n\n"; + } +} + +sub print_dot { + print "digraph G {\n"; + + foreach my $module (sort keys %target_deps) + { + next if scalar @{$target_deps{$module}} == 0; + + my $modname = $module; + $modname =~ s,[/-],_,g; + + print " $modname -> { "; + + my %found = (); + my $first = 1; + + foreach my $calling (@{$target_deps{$module}}) + { + next if defined $found{$calling}; + $found{$calling} = 1; + + print "; " if (! $first); + $first = 0; + + $calling =~ s,[/-],_,g; + + print "$calling" + } + print "};\n"; + } + + print "};\n"; +} + +sub finddeps { + my ($module, $traversed) = @_; + + return {} if ! defined $target_deps{$module}; + return {} if defined $traversed->{$module}; + $traversed->{$module} = 1; + + my @alldeps = @{$target_deps{$module}}; + + foreach my $dep (@{$target_deps{$module}}) + { + push @alldeps, keys %{finddeps ($dep, $traversed)}; + } + + my %unique_names; + + foreach my $dep (@alldeps) + { + $unique_names{$dep} = 1; + } + + return \%unique_names; +} diff --git a/kernel/fiasco/tool/split_config b/kernel/fiasco/tool/split_config new file mode 100755 index 00000000..2655d459 --- /dev/null +++ b/kernel/fiasco/tool/split_config @@ -0,0 +1,68 @@ +#! /usr/bin/perl + +use strict; + +my $cfg_prefix = "CONFIG"; +my @arch_opts = ("IA32", "ARM", "UX" ,"XARCH"); +my @abi_opts = ("V2", "X0", "V4", "ABI"); +my @base_opts = ("INLINE", "NDEBUG", "NO_FRAME_PTR", "FINE_GRAINED_CPUTIME", + "FFUN"); +my @debug_opts = ("KDB","JDB","VMEM_ALLOC_TEST","SERIAL", "PERF_CNT"); +my @compile_opts = ("VERBOSE", "MAINTAINER_MODE"); + +my %cfg_files = ("arch_config.cfg" => \@arch_opts, + "abi_config.cfg" => \@abi_opts, + "base_config.cfg" => \@base_opts, + "debug_config.cfg" => \@debug_opts, + "compile_config.cfg" => \@compile_opts); +my $other_opts = "other_config.cfg"; + +my %cfg_files_2; + +my $outfile = shift; +my $outhdl; +my $other = 0; + +open($outhdl,">$outfile") || die "$outfile: $!"; + +foreach my $cfg (keys %cfg_files) +{ + my $cfgs = $cfg_files{$cfg}; + for (my $i = 0; $i <= $#$cfgs; $i++) + { + $cfgs->[$i] = $cfg_prefix."_".$cfgs->[$i]; + } +} + +my $expr; + +if ($outfile eq $other_opts) +{ + $other = 1; + foreach my $cfg (keys %cfg_files) + { + my $cfgs = $cfg_files{$cfg}; + if ($expr ne "") + { + $expr = join("|", ($expr, @$cfgs)); + } else { + $expr = join("|", @$cfgs); + } + } +} else { + my $cfgs = $cfg_files{$outfile}; + exit 0 if (!defined $cfgs) ; + $expr= join("|", @$cfgs); +} + +while(<>) +{ + my $written = 0; + if (/^($expr)/ xor $other) + { + print $outhdl $_; + } +} + +close $outhdl; + diff --git a/l4/BENCHMARKING b/l4/BENCHMARKING new file mode 100644 index 00000000..e41f8895 --- /dev/null +++ b/l4/BENCHMARKING @@ -0,0 +1,13 @@ + +IMPORTANT NOTE ON BENCHMARKING Fiasco.OC/L4RE SOFTWARE +====================================================== + +Owing to the flexibility of configurations possible with this software we +urge you to send any benchmarking results for review prior to publication to + + benchmarking@os.inf.tu-dresden.de + +to get feedback and an 'OK' from our side that the presented figures are +reasonable. + +Thanks. diff --git a/l4/COPYING-GPL-2 b/l4/COPYING-GPL-2 new file mode 100644 index 00000000..0af8bab6 --- /dev/null +++ b/l4/COPYING-GPL-2 @@ -0,0 +1,349 @@ + + NOTE! This License shall not affect user programs that use the micro-kernel +API to invoke kernel-operations or services provided in other address +spaces - this is merely considered normal use of the kernel or +accompanying user-level services, and does not fall under the heading of +"derivative work". + +----------------------------------------------------------------------- + + + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/l4/COPYING-LGPL-2.1 b/l4/COPYING-LGPL-2.1 new file mode 100644 index 00000000..2d2d780e --- /dev/null +++ b/l4/COPYING-LGPL-2.1 @@ -0,0 +1,510 @@ + + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations +below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it +becomes a de-facto standard. To achieve this, non-free programs must +be allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control +compilation and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at least + three years, to give the same user the materials specified in + Subsection 6a, above, for a charge no more than the cost of + performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply, and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License +may add an explicit geographical distribution limitation excluding those +countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms +of the ordinary General Public License). + + To apply these terms, attach the following notices to the library. +It is safest to attach them to the start of each source file to most +effectively convey the exclusion of warranty; and each file should +have at least the "copyright" line and a pointer to where the full +notice is found. + + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or +your school, if any, to sign a "copyright disclaimer" for the library, +if necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James + Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + diff --git a/l4/LICENSING b/l4/LICENSING new file mode 100644 index 00000000..d8a8320d --- /dev/null +++ b/l4/LICENSING @@ -0,0 +1,10 @@ +TUD:OS is released under the terms of the GNU General Public License (GPL), +Version 2 or the GNU Lesser General Public License 2.1, depending on the +software component. See the file COPYING for details. For different +licensing schemes please contact contact@os.inf.tu-dresden.de. + +Note that some parts of TUD:OS are derived from other GPL code and hence +are copyrighted by other parties. Different licensing of those parts either +requires approval of the respective owners or requires to rewrite the +code. To find the best solution for you, mail contact@os.inf.tu-dresden.de. + diff --git a/l4/Makefile b/l4/Makefile new file mode 100644 index 00000000..a556f03d --- /dev/null +++ b/l4/Makefile @@ -0,0 +1,688 @@ +# +# GLOBAL Makefile for the whole L4 tree +# + +L4DIR ?= . + +BUILD_DIRS = tool pkg +install-dirs = tool pkg +clean-dirs = tool pkg doc +cleanall-dirs = tool pkg doc + +BUILD_TOOLS = gawk gcc g++ ld perl pkg-config + +CMDS_WITHOUT_OBJDIR := help checkbuild up update check_build_tools + +# our default target is all:: +all:: + +##################### +# config-tool + +DROPSCONF = y +DROPSCONF_DEFCONFIG ?= $(L4DIR)/mk/defconfig/config.x86 +KCONFIG_FILE = $(OBJ_BASE)/Kconfig.generated +KCONFIG_FILE_SRC = $(L4DIR)/mk/Kconfig +DROPSCONF_CONFIG = $(OBJ_BASE)/.kconfig.auto +DROPSCONF_CONFIG_H = $(OBJ_BASE)/include/l4/bid_config.h +DROPSCONF_CONFIG_MK = $(OBJ_BASE)/.config.all +DROPSCONF_DONTINC_MK = y +DROPSCONF_HELPFILE = $(L4DIR)/mk/config.help + +# separation in "dependent" (ie opts the build output depends on) and +# "independent" (ie opts the build output does not depend on) opts +CONFIG_MK_INDEPOPTS = CONFIG_BID_GENERATE_MAPFILE \ + CONFIG_DEPEND_VERBOSE \ + CONFIG_VERBOSE_SWITCH \ + CONFIG_BID_COLORED_PHASES CONFIG_HAVE_LDSO \ + CONFIG_INT_CPP_NAME_SWITCH BID_LIBGENDEP_PATHS CONFIG_INT_CPP_.*_NAME \ + CONFIG_INT_CXX_.*_NAME CONFIG_VERBOSE CONFIG_BID_STRIP_PROGS \ + CONFIG_INT_LD_NAME_SWITCH CONFIG_INT_LD_.*_NAME +CONFIG_MK_PLATFORM_OPTS = CONFIG_PLATFORM_.* +CONFIG_MK_REAL = $(OBJ_BASE)/.config +CONFIG_MK_INDEP = $(OBJ_BASE)/.config.indep +CONFIG_MK_PLATFORM = $(OBJ_BASE)/.config.platform + +INCLUDE_BOOT_CONFIG := optional + +ifneq ($(filter $(CMDS_WITHOUT_OBJDIR),$(MAKECMDGOALS)),) +IGNORE_MAKECONF_INCLUDE=1 +endif + +ifneq ($(B)$(BUILDDIR_TO_CREATE),) +IGNORE_MAKECONF_INCLUDE=1 +endif + +ifeq ($(IGNORE_MAKECONF_INCLUDE),) +ifneq ($(filter help config oldconfig,$(MAKECMDGOALS)),) +# tweek $(L4DIR)/mk/Makeconf to use the intermediate file +export BID_IGN_ROOT_CONF=y +BID_ROOT_CONF=$(DROPSCONF_CONFIG_MK) +endif + +# $(L4DIR)/mk/Makeconf shouln't include Makeconf.local twice +MAKECONFLOCAL = /dev/null +include $(L4DIR)/mk/Makeconf +export DROPS_STDDIR + +# after having absfilename, we can export BID_ROOT_CONF +ifneq ($(filter config oldconfig gconfig nconfig xconfig, $(MAKECMDGOALS)),) +export BID_ROOT_CONF=$(call absfilename,$(OBJ_BASE))/.config.all +endif +endif + +##################### +# rules follow + +ifneq ($(strip $(B)),) +BUILDDIR_TO_CREATE := $(B) +endif +ifneq ($(strip $(BUILDDIR_TO_CREATE)),) +all:: check_build_tools + @echo "Creating build directory \"$(BUILDDIR_TO_CREATE)\"..." + @if [ -e "$(BUILDDIR_TO_CREATE)" ]; then \ + echo "Already exists, aborting."; \ + exit 1; \ + fi + @mkdir -p "$(BUILDDIR_TO_CREATE)" + @cp $(DROPSCONF_DEFCONFIG) $(BUILDDIR_TO_CREATE)/.kconfig + @$(MAKE) B= BUILDDIR_TO_CREATE= O=$(BUILDDIR_TO_CREATE) oldconfig + @echo "done." +else + +all:: l4defs + +endif + + + +# some more dependencies +tool: $(DROPSCONF_CONFIG_MK) +pkg: $(DROPSCONF_CONFIG_MK) tool + +ifneq ($(CONFIG_BID_BUILD_DOC),) +install-dirs += doc +all:: doc +endif + +up update: + $(VERBOSE)svn up -N + $(VERBOSE)svn up mk tool/gendep tool/kconfig tool/elf-patcher doc/source conf tool/lib tool/vim tool/bin + $(VERBOSE)$(MAKE) -C pkg up + +tool pkg: + $(VERBOSE)if [ -r $@/Makefile ]; then PWD=$(PWD)/$@ $(MAKE) -C $@; fi + +doc: + $(VERBOSE)if [ -r doc/source/Makefile ]; then PWD=$(PWD)/doc/source $(MAKE) -C doc/source; fi + +cont: + $(VERBOSE)$(MAKE) -C pkg cont + +.PHONY: all clean cleanall install up update doc +.PHONY: $(BUILD_DIRS) doc check_build_tools cont cleanfast + +cleanall:: + $(VERBOSE)rm -f *~ + +clean cleanall install:: + $(VERBOSE)set -e; for i in $($@-dirs) ; do \ + if [ -r $$i/Makefile -o -r $$i/GNUmakefile ] ; then \ + PWD=$(PWD)/$$i $(MAKE) -C $$i $@ ; fi ; done + +cleanfast: + $(VERBOSE)$(RM) -r $(OBJ_BASE)/{bin,include,pkg,doc,ext-pkg,pc,lib,l4defs.mk.inc,l4defs.sh.inc,images} + + +L4DEF_FILE_MK ?= $(OBJ_BASE)/l4defs.mk.inc +L4DEF_FILE_SH ?= $(OBJ_BASE)/l4defs.sh.inc + +l4defs: $(L4DEF_FILE_MK) $(L4DEF_FILE_SH) + +generate_l4defs_files = \ + $(VERBOSE)tmpdir=$(OBJ_BASE)/l4defs.gen.dir && \ + mkdir -p $$tmpdir && \ + echo "L4DIR = $(L4DIR_ABS)" > $$tmpdir/Makefile && \ + echo "OBJ_BASE = $(OBJ_BASE)" >> $$tmpdir/Makefile && \ + echo "L4_BUILDDIR = $(OBJ_BASE)" >> $$tmpdir/Makefile && \ + echo "SRC_DIR = $$tmpdir" >> $$tmpdir/Makefile && \ + echo "PKGDIR_ABS = $(L4DIR_ABS)/l4defs.gen.dir" >> $$tmpdir/Makefile && \ + cat $(L4DIR)/mk/export_defs.inc >> $$tmpdir/Makefile && \ + PWD=$$tmpdir $(MAKE) -C $$tmpdir -f $$tmpdir/Makefile \ + CALLED_FOR=$(1) L4DEF_FILE_MK=$(L4DEF_FILE_MK) L4DEF_FILE_SH=$(L4DEF_FILE_SH) && \ + $(RM) -r $$tmpdir + +$(L4DEF_FILE_MK): $(BUILD_DIRS) $(DROPSCONF_CONFIG_MK) $(L4DIR)/mk/export_defs.inc + +$(call generate_l4defs_files,static) + +$(call generate_l4defs_files,shared) + +$(call generate_l4defs_files,sharedlib) + +$(L4DEF_FILE_SH): $(L4DEF_FILE_MK) + +regen_l4defs: + +$(call generate_l4defs_files,static) + +$(call generate_l4defs_files,shared) + +$(call generate_l4defs_files,sharedlib) + +.PHONY: l4defs regen_l4defs + +##################### +# config-rules follow + +HOST_SYSTEM := $(shell uname | tr 'A-Z' 'a-z') +export HOST_SYSTEM + +# it becomes a bit confusing now: 'make config' results in a config file, which +# must be postprocessed. This is done in config.inc. Then, +# we evaluate some variables that depend on the postprocessed config file. +# The variables are defined in mk/Makeconf, which sources Makeconf.bid.local. +# Hence, we have to 1) postprocess, 2) call make again to get the variables. +DROPSCONF_CONFIG_MK_POST_HOOK:: check_build_tools $(OBJ_DIR)/Makefile + # libgendep must be done before calling make with the local helper + $(VERBOSE)$(MAKE) libgendep + $(VERBOSE)$(MAKE) Makeconf.bid.local-helper || \ + (rm -f $(DROPSCONF_CONFIG_MK) $(CONFIG_MK_REAL) $(CONFIG_MK_INDEP); false) + $(VEROBSE)$(LN) -snf $(L4DIR_ABS) $(OBJ_BASE)/source + $(VERBOSE)$(MAKE) checkconf + +define extract_var + $(1)=$$((cat $(2); echo printit:; \ + echo ' @echo $$($(3))') | \ + $(MAKE) --no-print-directory -f - printit) +endef + +define create_kconfig + $(VERBOSE)echo "# vi:set ft=kconfig:" > $(1) + $(VERBOSE)echo "# This Kconfig is auto-generated." >> $(1) + $(VERBOSE)pt=""; \ + while IFS="" read l; do \ + if [ "$$l" = "INSERT_PLATFORMS" ]; then \ + for p in $(wildcard $(L4DIR)/conf/platforms/*.conf \ + $(L4DIR)/mk/platforms/*.conf); do \ + $(call extract_var,n,$$p,PLATFORM_NAME); \ + pn=$${p##*/}; \ + pn=$${pn%.conf}; \ + echo "config PLATFORM_TYPE_$${pn}" >> $(1); \ + echo " bool \"$$n\"" >> $(1); \ + pt="$$pt default \"$$pn\" if PLATFORM_TYPE_$${pn}\n"; \ + $(call extract_var,n,$$p,PLATFORM_ARCH); \ + dep=""; \ + for a in $$n; do \ + if [ -z "$$dep" ]; then \ + dep=" depends on BUILD_ARCH_$$a"; \ + else \ + dep="$$dep || BUILD_ARCH_$$a"; \ + fi; \ + done; \ + echo "$$dep" >> $(1); \ + echo "" >> $(1); \ + done; \ + elif [ "$$l" = "INSERT_PLATFORM_TYPES" ]; then \ + echo "config PLATFORM_TYPE" >> $(1); \ + echo " string" >> $(1); \ + echo -e "$$pt" >> $(1); \ + else \ + echo "$$l" >> $(1); \ + fi; \ + done < $(2) +endef + +$(KCONFIG_FILE): $(KCONFIG_FILE_SRC) Makefile $(wildcard $(L4DIR)/conf/platforms/*.conf $(L4DIR)/conf/platforms/*.conf) + +$(call create_kconfig,$@,$(KCONFIG_FILE_SRC)) + +checkconf: + $(VERBOSE)if [ ! -e $(GCCDIR)/include/stddef.h ]; then \ + $(ECHO); \ + $(ECHO) "$(GCCDIR) seems wrong (stddef.h not found)."; \ + $(ECHO) "Does it exist?"; \ + $(ECHO); \ + exit 1; \ + fi + +# caching of some variables. Others are determined directly. +# The contents of the variables to cache is already defined in mk/Makeconf. +.PHONY: Makeconf.bid.local-helper Makeconf.bid.local-internal-names \ + libgendep checkconf +ARCH = $(BUILD_ARCH) +CC := $(if $(filter sparc,$(ARCH)),$(if $(call GCCIS_sparc_leon_f),sparc-elf-gcc,$(CC)),$(CC)) +LD := $(if $(filter sparc,$(ARCH)),$(if $(call GCCIS_sparc_leon_f),sparc-elf-ld,$(LD)),$(LD)) +Makeconf.bid.local-helper: + $(VERBOSE)echo BUILD_SYSTEMS="$(strip $(ARCH)_$(CPU) \ + $(ARCH)_$(CPU)-$(BUILD_ABI))" >> $(DROPSCONF_CONFIG_MK) + $(VERBOSE)$(foreach v, GCCDIR GCCLIB_HOST GCCLIB_EH GCCLIB_S_SO \ + GCCVERSION GCCMAJORVERSION GCCMINORVERSION \ + GCCSUBVERSION GCC_HAS_ATOMICS \ + GCCNOSTACKPROTOPT LDVERSION GCCSYSLIBDIRS \ + $(if $(GCCNOFPU_$(ARCH)_f),GCCNOFPU_$(ARCH)) \ + $(if $(GCCIS_$(ARCH)_leon_f),GCCIS_$(ARCH)_leon), \ + echo $(v)=$(call $(v)_f,$(ARCH)) \ + >>$(DROPSCONF_CONFIG_MK);) + $(VERBOSE)$(foreach v, crtbegin.o crtbeginS.o crtbeginT.o \ + crtendS.o crtend.o, \ + echo GCCLIB_FILE_$(v)=$(call GCCLIB_file_f,$(v)) \ + >>$(DROPSCONF_CONFIG_MK);) + $(VERBOSE)$(foreach v, LD_GENDEP_PREFIX, echo $v=$($(v)) >>$(DROPSCONF_CONFIG_MK);) + $(VERBOSE)echo "HOST_SYSTEM=$(HOST_SYSTEM)" >>$(DROPSCONF_CONFIG_MK) + $(VERBOSE)echo "COLOR_TERMINAL=$(shell if [ $$(tput colors || echo -1) = '-1' ]; then echo n; else echo y; fi)" >>$(DROPSCONF_CONFIG_MK) + $(VERBOSE)echo "LD_HAS_HASH_STYLE_OPTION=$(shell if $(LD) --help 2>&1 | grep -q ' --hash-style='; then echo y; else echo n; fi)" >>$(DROPSCONF_CONFIG_MK) + $(VERBOSE)# we need to call make again, because HOST_SYSTEM (set above) must be + $(VERBOSE)# evaluated for LD_PRELOAD to be set, which we need in the following + $(VERBOSE)$(MAKE) Makeconf.bid.local-internal-names + $(VERBOSE)sort <$(DROPSCONF_CONFIG_MK) >$(CONFIG_MK_REAL).tmp + $(VERBOSE)echo -e "# Automatically generated. Don't edit\n" >$(CONFIG_MK_INDEP) + $(VERBOSE)echo -e "# Automatically generated. Don't edit\n" >$(CONFIG_MK_PLATFORM) + $(VERBOSE)grep $(addprefix -e ^,$(CONFIG_MK_INDEPOPTS) ) <$(CONFIG_MK_REAL).tmp >>$(CONFIG_MK_INDEP) + $(VERBOSE)grep $(addprefix -e ^,$(CONFIG_MK_PLATFORM_OPTS)) <$(CONFIG_MK_REAL).tmp >>$(CONFIG_MK_PLATFORM) + $(VERBOSE)echo -e "# Automatically generated. Don't edit\n" >$(CONFIG_MK_REAL).tmp2 + $(VERBOSE)grep -v $(addprefix -e ^,$$ # $(CONFIG_MK_INDEPOPTS) $(CONFIG_MK_PLATFORM_OPTS)) \ + <$(CONFIG_MK_REAL).tmp >>$(CONFIG_MK_REAL).tmp2 + $(VERBOSE)echo -e 'include $(call absfilename,$(CONFIG_MK_INDEP))' >>$(CONFIG_MK_REAL).tmp2 + $(VERBOSE)echo -e 'include $(call absfilename,$(CONFIG_MK_PLATFORM))' >>$(CONFIG_MK_REAL).tmp2 + $(VERBOSE)if [ -e "$(CONFIG_MK_REAL)" ]; then \ + diff --brief -I ^COLOR_TERMINAL $(CONFIG_MK_REAL) $(CONFIG_MK_REAL).tmp2 || \ + mv $(CONFIG_MK_REAL).tmp2 $(CONFIG_MK_REAL); \ + else \ + mv $(CONFIG_MK_REAL).tmp2 $(CONFIG_MK_REAL); \ + fi + $(VERBOSE)$(RM) $(CONFIG_MK_REAL).tmp $(CONFIG_MK_REAL).tmp2 + +Makeconf.bid.local-internal-names: +ifneq ($(CONFIG_INT_CPP_NAME_SWITCH),) + $(VERBOSE) set -e; X="tmp.$$$$$$RANDOM.c" ; echo 'int main(void){}'>$$X ; \ + rm -f $$X.out ; $(LD_GENDEP_PREFIX) GENDEP_SOURCE=$$X \ + GENDEP_OUTPUT=$$X.out $(CC) $(CCXX_FLAGS) -c $$X -o $$X.o; \ + test -e $$X.out; echo INT_CPP_NAME=`cat $$X.out` \ + >>$(DROPSCONF_CONFIG_MK); \ + rm -f $$X $$X.{o,out}; + $(VERBOSE)set -e; X="tmp.$$$$$$RANDOM.cc" ; echo 'int main(void){}'>$$X; \ + rm -f $$X.out; $(LD_GENDEP_PREFIX) GENDEP_SOURCE=$$X \ + GENDEP_OUTPUT=$$X.out $(CXX) -c $$X -o $$X.o; \ + test -e $$X.out; echo INT_CXX_NAME=`cat $$X.out` \ + >>$(DROPSCONF_CONFIG_MK); \ + rm -f $$X $$X.{o,out}; +endif +ifneq ($(CONFIG_INT_LD_NAME_SWITCH),) + $(VERBOSE) set -e; echo INT_LD_NAME=$$($(LD) 2>&1 | perl -p -e 's,^(.+/)?(.+):.+,$$2,') >> $(DROPSCONF_CONFIG_MK) +endif + $(VERBOSE)emulations=$$(LANG= $(firstword $(LD)) --help | \ + grep -i "supported emulations:" | \ + sed -e 's/.*supported emulations: //') ; \ + unset found_it; \ + for e in $$emulations; do \ + for c in $(LD_EMULATION_CHOICE_$(ARCH)); do \ + if [ "$$e" = "$$c" ]; then \ + echo LD_EMULATION=$$e >> $(DROPSCONF_CONFIG_MK); \ + found_it=1; \ + break; \ + fi; \ + done; \ + done; \ + if [ "$$found_it" != "1" ]; then \ + echo "No known ld emulation found"; exit 1; \ + fi + +libgendep: + $(VERBOSE)if [ ! -r tool/gendep/Makefile ]; then \ + echo "=== l4/tool/gendep missing! ==="; \ + exit 1; \ + fi + $(VERBOSE)PWD=$(PWD)/tool/gendep $(MAKE) -C tool/gendep + +check_build_tools: + @unset mis; \ + for i in $(BUILD_TOOLS); do \ + if ! command -v $$i >/dev/null 2>&1; then \ + [ -n "$$mis" ] && mis="$$mis "; \ + mis="$$mis$$i"; \ + fi \ + done; \ + if [ -n "$$mis" ]; then \ + echo -e "\033[1;31mProgram(s) \"$$mis\" not found, please install!\033[0m"; \ + exit 1; \ + else \ + echo "All build tools checked ok."; \ + fi + +define common_envvars + ARCH="$(ARCH)" PLATFORM_TYPE="$(PLATFORM_TYPE)" +endef +define tool_envvars + L4DIR=$(L4DIR) \ + SEARCHPATH="$(MODULE_SEARCH_PATH):$(BUILDDIR_SEARCHPATH)" +endef +define set_ml + unset ml; ml=$(L4DIR_ABS)/conf/modules.list; \ + [ -n "$(MODULES_LIST)" ] && ml=$(MODULES_LIST) +endef +define entryselection + unset e; \ + $(set_ml); \ + [ -n "$(ENTRY)" ] && e="$(ENTRY)"; \ + [ -n "$(E)" ] && e="$(E)"; \ + if [ -z "$$e" ]; then \ + BACKTITLE="No entry given. Use 'make $@ E=entryname' to avoid menu." \ + L4DIR=$(L4DIR) $(L4DIR)/tool/bin/entry-selector menu $$ml 2> $(OBJ_BASE)/.entry-selector.tmp; \ + if [ $$? != 0 ]; then \ + cat $(OBJ_BASE)/.entry-selector.tmp; \ + exit 1; \ + fi; \ + e=$$(cat $(OBJ_BASE)/.entry-selector.tmp); \ + $(RM) $(OBJ_BASE)/.entry-selector.tmp; \ + fi +endef +define checkx86amd64build + $(VERBOSE)if [ "$(ARCH)" != "x86" -a "$(ARCH)" != "amd64" ]; then \ + echo "This mode can only be used with architectures x86 and amd64."; \ + exit 1; \ + fi +endef +define genimage + $(VERBOSE)$(entryselection); \ + PWD=$(PWD)/pkg/bootstrap/server/src $(common_envvars) \ + $(MAKE) -C pkg/bootstrap/server/src ENTRY="$$e" \ + BOOTSTRAP_MODULES_LIST=$$ml $(1) \ + BOOTSTRAP_MODULE_PATH_BINLIB="$(BUILDDIR_SEARCHPATH)" \ + BOOTSTRAP_SEARCH_PATH="$(MODULE_SEARCH_PATH)" +endef + +define switch_ram_base_func + echo " ... Regenerating RAM_BASE settings"; \ + echo "# File semi-automatically generated by 'make switch_ram_base'" > $(OBJ_BASE)/Makeconf.ram_base; \ + echo "# Currently being regenerated" >> $(OBJ_BASE)/Makeconf.ram_base; \ + PWD=$(PWD)/pkg/sigma0/server/src $(MAKE) RAM_BASE=$(1) -C pkg/sigma0/server/src; \ + PWD=$(PWD)/pkg/moe/server/src $(MAKE) RAM_BASE=$(1) -C pkg/moe/server/src; \ + echo "# File semi-automatically generated by 'make switch_ram_base'" > $(OBJ_BASE)/Makeconf.ram_base; \ + echo "RAM_BASE := $(1)" >> $(OBJ_BASE)/Makeconf.ram_base +endef + +BUILDDIR_SEARCHPATH = $(OBJ_BASE)/bin/$(ARCH)_$(CPU):$(OBJ_BASE)/bin/$(ARCH)_$(CPU)/$(BUILD_ABI):$(OBJ_BASE)/lib/$(ARCH)_$(CPU):$(OBJ_BASE)/lib/$(ARCH)_$(CPU)/$(BUILD_ABI) + +QEMU_ARCH_MAP_$(ARCH) = qemu-system-$(ARCH) +QEMU_ARCH_MAP_x86 = $(strip $(shell if qemu-system-i386 -version > /dev/null; then echo qemu-system-i386; else echo qemu; fi)) +QEMU_ARCH_MAP_amd64 = qemu-system-x86_64 +QEMU_ARCH_MAP_ppc32 = qemu-system-ppc + +FASTBOOT_BOOT_CMD ?= fastboot boot + +check_and_adjust_ram_base: + $(VERBOSE)if [ -z "$(PLATFORM_RAM_BASE)" ]; then \ + echo "Platform \"$(PLATFORM_TYPE)\" not known."; \ + exit 1; \ + fi + $(VERBOSE)if [ $$(($(RAM_BASE))) != $$(($(PLATFORM_RAM_BASE))) ]; then \ + echo "=========== Updating RAM_BASE for platform $(PLATFORM_TYPE) to $(PLATFORM_RAM_BASE) =========" ; \ + $(call switch_ram_base_func,$(PLATFORM_RAM_BASE)); \ + fi + +listentries: + $(VERBOSE)$(set_ml); \ + L4DIR=$(L4DIR) $(L4DIR)/tool/bin/entry-selector list $$ml + +shellcodeentry: + $(VERBOSE)$(entryselection); \ + SHELLCODE="$(SHELLCODE)" $(common_envvars) $(tool_envvars) \ + $(L4DIR)/tool/bin/shell-entry $$ml "$$e" + +elfimage: check_and_adjust_ram_base + $(call genimage,BOOTSTRAP_DO_UIMAGE= BOOTSTRAP_DO_RAW_IMAGE=) + +uimage: check_and_adjust_ram_base + $(call genimage,BOOTSTRAP_DO_UIMAGE=y BOOTSTRAP_DO_RAW_IMAGE=) + +rawimage: check_and_adjust_ram_base + $(call genimage,BOOTSTRAP_DO_UIMAGE= BOOTSTRAP_DO_RAW_IMAGE=y) + +fastboot: rawimage + $(VERBOSE)$(FASTBOOT_BOOT_CMD) $(OBJ_BASE)/images/bootstrap.raw + +ifneq ($(filter $(ARCH),x86 amd64),) +qemu: + $(VERBOSE)$(entryselection); \ + qemu=$(if $(QEMU_PATH),$(QEMU_PATH),$(QEMU_ARCH_MAP_$(ARCH))); \ + QEMU=$$qemu QEMU_OPTIONS="$(QEMU_OPTIONS)" \ + $(tool_envvars) $(common_envvars) \ + $(L4DIR)/tool/bin/qemu-x86-launch $$ml "$$e" +else +qemu: elfimage + $(VERBOSE)qemu=$(if $(QEMU_PATH),$(QEMU_PATH),$(QEMU_ARCH_MAP_$(ARCH))); \ + if [ -z "$$qemu" ]; then echo "Set QEMU_PATH!"; exit 1; fi; \ + echo QEmu-cmd: $$qemu -kernel $(OBJ_BASE)/images/bootstrap.elf $(QEMU_OPTIONS); \ + $$qemu -kernel $(OBJ_BASE)/images/bootstrap.elf $(QEMU_OPTIONS) +endif + +vbox: $(if $(VBOX_ISOTARGET),$(VBOX_ISOTARGET),grub2iso) + $(checkx86amd64build) + $(VERBOSE)if [ -z "$(VBOX_VM)" ]; then \ + echo "Need to set name of configured VirtualBox VM im 'VBOX_VM'."; \ + exit 1; \ + fi + $(VERBOSE)VBoxSDL \ + --startvm $(VBOX_VM) \ + --cdrom $(OBJ_BASE)/images/.current.iso \ + --boot d \ + $(VBOX_OPTIONS) + +kexec: + $(VERBOSE)$(entryselection); \ + $(tool_envvars) $(common_envvars) \ + $(L4DIR)/tool/bin/kexec-launch $$ml "$$e" + +ux: + $(VERBOSE)if [ "$(ARCH)" != "x86" ]; then \ + echo "This mode can only be used with architecture x86."; \ + exit 1; \ + fi + $(VERBOSE)$(entryselection); \ + $(tool_envvars) $(common_envvars) \ + $(if $(UX_GFX),UX_GFX="$(UX_GFX)") \ + $(if $(UX_GFX_CMD),UX_GFX_CMD="$(UX_GFX_CMD)") \ + $(if $(UX_NET),UX_NET="$(UX_NET)") \ + $(if $(UX_NET_CMD),UX_NET_CMD="$(UX_NET_CMD)") \ + $(if $(UX_GDB_CMD),UX_GDB_CMD="$(UX_GDB_CMD)") \ + $(L4DIR)/tool/bin/ux-launch $$ml "$$e" $(UX_OPTIONS) + +GRUB_TIMEOUT ?= 0 + +define geniso + $(checkx86amd64build) + $(VERBOSE)$(entryselection); \ + $(MKDIR) $(OBJ_BASE)/images; \ + ISONAME=$(OBJ_BASE)/images/$$(echo $$e | tr '[ A-Z]' '[_a-z]').iso; \ + $(tool_envvars) $(common_envvars) \ + $(L4DIR)/tool/bin/gengrub$(1)iso --timeout=$(GRUB_TIMEOUT) $$ml \ + $$ISONAME "$$e" \ + && $(LN) -f $$ISONAME $(OBJ_BASE)/images/.current.iso +endef + +grub1iso: + $(call geniso,1) + +grub2iso: + $(call geniso,2) + +exportpack: + $(if $(EXPORTPACKTARGETDIR),, \ + @echo Need to specific target directory as EXPORTPACKTARGETDIR=dir; exit 1) + $(VERBOSE)$(entryselection); \ + TARGETDIR=$(EXPORTPACKTARGETDIR); \ + qemu=$(if $(QEMU_PATH),$(QEMU_PATH),$(QEMU_ARCH_MAP_$(ARCH))); \ + QEMU=$$qemu L4DIR=$(L4DIR) \ + $(tool_envvars) $(common_envvars) \ + $(L4DIR)/tool/bin/genexportpack --timeout=$(GRUB_TIMEOUT) \ + $$ml $$TARGETDIR $$e; + +help:: + @echo + @echo "Image generation targets:" + @echo " elfimage - Generate an ELF image, containing all modules." + @echo " rawimage - Generate a raw image (memory dump), containing all modules." + @echo " uimage - Generate a uimage for u-boot, containing all modules." + @echo " grub1iso - Generate an ISO using GRUB1 in images/.iso [x86, amd64]" + @echo " grub2iso - Generate an ISO using GRUB2 in images/.iso [x86, amd64]" + @echo " qemu - Use Qemu to run 'name'." + @echo " exportpack - Export binaries with launch support." + @echo " vbox - Use VirtualBox to run 'name'." + @echo " fastboot - Call fastboot with the created rawimage." + @echo " ux - Run 'name' under Fiasco/UX. [x86]" + @echo " kexec - Issue a kexec call to start the entry." + @echo " Add 'E=name' to directly select the entry without using the menu." + @echo " Modules are defined in conf/modules.list." + + +.PHONY: image elfimage rawimage uimage qemu vbox ux switch_ram_base \ + grub1iso grub2iso listentries shellcodeentry exportpack \ + fastboot check_and_adjust_ram_base + +switch_ram_base: + $(VERBOSE)$(call switch_ram_base_func,$(RAM_BASE)) + +checkbuild: + @if [ -z "$(CHECK_BASE_DIR)" ]; then \ + echo "Need to set CHECK_BASE_DIR variable"; \ + exit 1; \ + fi + set -e; for i in $(if $(USE_CONFIGS),$(addprefix mk/defconfig/config.,$(USE_CONFIGS)),mk/defconfig/config.*); do \ + p=$(CHECK_BASE_DIR)/$$(basename $$i); \ + rm -rf $$p; \ + mkdir -p $$p; \ + cp $$i $$p/.kconfig; \ + $(MAKE) O=$$p oldconfig; \ + $(MAKE) O=$$p report; \ + $(MAKE) O=$$p tool; \ + $(MAKE) O=$$p USE_CCACHE=$(USE_CCACHE) $(CHECK_MAKE_ARGS); \ + $(if $(CHCEK_REMOVE_OBJDIR),rm -rf $$p;) \ + done + +report: + @echo -e $(EMPHSTART)"============================================================="$(EMPHSTOP) + @echo -e $(EMPHSTART)" Note, this report might disclose private information"$(EMPHSTOP) + @echo -e $(EMPHSTART)" Please review (and edit) before sending it to public lists"$(EMPHSTOP) + @echo -e $(EMPHSTART)"============================================================="$(EMPHSTOP) + @echo + @echo "make -v:" + @make -v || true + @echo + @echo "CC: $(CC) -v:" + @$(CC) -v || true + @echo + @echo "CXX: $(CXX) -v:" + @$(CXX) -v || true + @echo + @echo "HOST_CC: $(HOST_CC) -v:" + @$(HOST_CC) -v || true + @echo + @echo "HOST_CXX: $(HOST_CXX) -v:" + @$(HOST_CXX) -v || true + @echo + @echo -n "ld: $(LD) -v: " + @$(LD) -v || true + @echo + @echo -n "perl -v:" + @perl -v || true + @echo + @echo -n "python -V: " + @python -V || true + @echo + @echo "svn --version: " + @svn --version || true + @echo + @echo "Shell is:" + @ls -la /bin/sh || true + @echo + @echo "uname -a: "; uname -a + @echo + @echo "Distribution" + @if [ -e "/etc/debian_version" ]; then \ + if grep -qi ubuntu /etc/issue; then \ + echo -n "Ubuntu: "; \ + cat /etc/issue; \ + else \ + echo -n "Debian: "; \ + fi; \ + cat /etc/debian_version; \ + elif [ -e /etc/gentoo-release ]; then \ + echo -n "Gentoo: "; \ + cat /etc/gentoo-release; \ + elif [ -e /etc/SuSE-release ]; then \ + echo -n "SuSE: "; \ + cat /etc/SuSE-release; \ + elif [ -e /etc/fedora-release ]; then \ + echo -n "Fedora: "; \ + cat /etc/fedora-release; \ + elif [ -e /etc/redhat-release ]; then \ + echo -n "Redhat: "; \ + cat /etc/redhat-release; \ + [ -e /etc/redhat_version ] \ + && echo " Version: `cat /etc/redhat_version`"; \ + elif [ -e /etc/slackware-release ]; then \ + echo -n "Slackware: "; \ + cat /etc/slackware-release; \ + [ -e /etc/slackware-version ] \ + && echo " Version: `cat /etc/slackware-version`"; \ + elif [ -e /etc/mandrake-release ]; then \ + echo -n "Mandrake: "; \ + cat /etc/mandrake-release; \ + else \ + echo "Unknown distribution"; \ + fi + @lsb_release -a || true + @echo + @echo "Running as PID" + @id -u || true + @echo + @echo "Archive information:" + @svn info || true + @echo + @echo "CC = $(CC) $(CCXX_FLAGS)" + @echo "CXX = $(CXX) $(CCXX_FLAGS)" + @echo "HOST_CC = $(HOST_CC)" + @echo "HOST_CXX = $(HOST_CXX)" + @echo "LD = $(LD)" + @echo "Paths" + @echo "Current: $$(pwd)" + @echo "L4DIR: $(L4DIR)" + @echo "L4DIR_ABS: $(L4DIR_ABS)" + @echo "OBJ_BASE: $(OBJ_BASE)" + @echo "OBJ_DIR: $(OBJ_DIR)" + @echo + @for i in pkg \ + ../kernel/fiasco/src/kern/ia32 \ + ../tools/preprocess/src/preprocess; do \ + if [ -e $$i ]; then \ + echo Path $$i found ; \ + else \ + echo PATH $$i IS NOT AVAILABLE; \ + fi \ + done + @echo + @echo Configuration: + @for i in $(OBJ_DIR)/.config.all $(OBJ_DIR)/.kconfig \ + $(OBJ_DIR)/Makeconf.local \ + $(L4DIR_ABS)/Makeconf.local \ + $(OBJ_DIR)/conf/Makeconf.boot \ + $(L4DIR_ABS)/conf/Makeconf.boot; do \ + if [ -e "$$i" ]; then \ + echo "______start_______________________________:";\ + echo "$$i:"; \ + cat $$i; \ + echo "____________________________end___________"; \ + else \ + echo "$$i not found"; \ + fi \ + done + @echo -e $(EMPHSTART)"============================================================="$(EMPHSTOP) + @echo -e $(EMPHSTART)" Note, this report might disclose private information"$(EMPHSTOP) + @echo -e $(EMPHSTART)" Please review (and edit) before sending it to public lists"$(EMPHSTOP) + @echo -e $(EMPHSTART)"============================================================="$(EMPHSTOP) + +help:: + @echo + @echo "Miscellaneous targets:" + @echo " switch_ram_base RAM_BASE=0xaddr" + @echo " - Switch physical RAM base of build to 'addr'." + @echo " update - Update working copy by using SVN." + @echo " cont - Continue building after fixing a build error." + @echo " clean - Call 'clean' target recursively." + @echo " cleanfast - Delete all directories created during build." + @echo " report - Print out host configuration information." + @echo " help - Print this help text." diff --git a/l4/conf/Makeconf.boot.example b/l4/conf/Makeconf.boot.example new file mode 100644 index 00000000..17ebde79 --- /dev/null +++ b/l4/conf/Makeconf.boot.example @@ -0,0 +1,91 @@ +# This file is an example for defining configurations for different boot +# methods: +# - QEMU (qemu) +# - Fiasco-UX (ux) +# - Image mode (image) +# - ISO images (grub1iso, grub2iso) +# - VirtualBox +# - Fastboot +# +# This is a make snippet. +# +# Copy this example file to Makeconf.boot in the same directory. +# +# +# +# Generic options: +# +# Search path for modules, such as binaries, libraries, kernel, configuration +# files or any other data file you might want to load. Note that the bin and +# lib directories of the build-tree are automatically added to the search +# path. +# MODULE_SEARCH_PATH = /path/to/cfgs:/path/to/foo:.. +# +# 'image' just builds what's configured: +# - default: just ELF +# - BOOTSTRAP_DO_RAW_IMAGE=y: additionally raw images +# - BOOTSTRAP_DO_UIMAGE=y: additionally uImages +# +# Other bootstrap options (see also pkg/bootstrap/server/src/Make.rules): +# - BOOTSTRAP_CMDLINE: default cmdline +# - BOOTSTRAP_UIMAGE_COMPRESSION: set to none, gzip, or bzip2 +# +# +# QEMU: Specific configuration for 'qemu' target (make qemu E=xxx'): +# +# Add fiasco build directory to MODULE_SEARCH_PATH + +qemu: MODULE_SEARCH_PATH += /path/to/fiasco-build + +# Optional options for QEMU, but setting '-serial stdio' is recommended +QEMU_OPTIONS = -serial stdio +#QEMU_OPTIONS = -nographic +#QEMU_OPTIONS-arm += -M realview-eb -m 256 +QEMU_OPTIONS += $(QEMU_OPTIONS-$(ARCH)) + +# The path to the QEMU binary - optional +#QEMU_PATH-x86 = /path/to/qemu +#QEMU_PATH-amd64 = /path/to/qemu-system-x86_64 +#QEMU_PATH = $(QEMU_PATH-$(ARCH)) + + +# Fiasco-UX: Specific configuration for 'ux' target ('make ux E=xxx'): +# +# Add Fiasco-UX build directory to MODULE_SEARCH_PATH + +ux: MODULE_SEARCH_PATH += /path/to/fiasco-ux-build + +# Additional (optional) variables: +# UX_OPTIONS: Options for Fiasco-UX, such as -m +# UX_GFX: Graphical console resolution and colordepth, e.g.: +# UX_GFX=800x600@16 +# UX_GFX_CMD: Path to ux_con binary, default is to search in the +# UX_SEARCH_PATH +# UX_NET: Enable network if set, e.g.: UX_NET=y +# UX_NET_CMD: Path to ux_net binary, default is to search in the +# UX_SEARCH_PATH + +UX_OPTIONS = -m 128 + +# Search path for other make targets: +# grub1iso grub2iso: MODULE_SEARCH_PATH += /path/to/fiasco-build +# image %image: MODULE_SEARCH_PATH += /path/to/fiasco-build + +# VirtualBox +# +# To use VirtualBox create a VM in VirtualBox and set the name of the VM in +# 'VBOX_VM'. The 'vbox' target uses an ISO image generating target to generate +# an ISO and use that with VirtualBox. +# +# Required variables: +# VBOX_VM: Name of the VM to use. +# +# Additional (optional) variables: +# VBOX_ISOTARGET: grub1iso or grub2iso (grub2iso is the default) +# VBOX_OPTIONS: Additional options (see VBoxSDL --help) +VBOX_VM = L4 +VBOX_ISOTARGET = grub1iso +#VBOX_OPTIONS += --memory 256 + +# Fastboot +# FASTBOOT_BOOT_CMD = path/to/fastboot boot diff --git a/l4/conf/examples/arm-rv-lcd.cfg b/l4/conf/examples/arm-rv-lcd.cfg new file mode 100644 index 00000000..b8391bc9 --- /dev/null +++ b/l4/conf/examples/arm-rv-lcd.cfg @@ -0,0 +1,69 @@ +-- vim:set ft=lua: + +-- This script shall start mag. For that we need a frame-buffer and io to +-- get access to the required hardware resources. Target platform is ARM +-- Real-View as used with QEmu. + +require("L4"); + + +local l = L4.default_loader; + +local io_buses = + { + gui = l:new_channel(); + fbdrv = l:new_channel(); + }; + +l:start({ + caps = { + gui = io_buses.gui:svr(), + fbdrv = io_buses.fbdrv:svr(), + + icu = L4.Env.icu, + sigma0 = L4.cast(L4.Proto.Factory, L4.Env.sigma0):create(L4.Proto.Sigma0), + }, + log = { "IO", "y" }, + l4re_dbg = L4.Dbg.Warn, + }, + "rom/io rom/arm-rv-eb.devs rom/arm-rv-lcd.io"); + +local fbdrv_fb = l:new_channel(); + +l:startv({ + caps = { + vbus = io_buses.fbdrv, + fb = fbdrv_fb:svr(), + }, + log = { "fbdrv", "r" }, + l4re_dbg = L4.Dbg.Warn, + }, + "rom/fb-drv", "-c", "1024 565 bgr"); + +local mag_caps = { + mag = l:new_channel(), + svc = l:new_channel(), + }; + +l:start({ + caps = { + vbus = io_buses.gui, + fb = fbdrv_fb, + mag = mag_caps.mag:svr(), + svc = mag_caps.svc:svr(), + }, + log = { "mag", "g" }, + l4re_dbg = L4.Dbg.Warn, + -- scheduler = L4.Env.user_factory:create(L4.Proto.Scheduler, 0xa0, 0x80), + }, + "rom/mag"); + +e = l:start({ caps = { + fb = mag_caps.svc:create(L4.Proto.Goos, "g=640x480"), + }, + log = { "spectrum", "b" }, + l4re_dbg = L4.Dbg.Warn, + -- scheduler = L4.Env.user_factory:create(L4.Proto.Scheduler, 0x18, 0x8), + }, + "rom/ex_fb_spectrum"); +print("ex_fb_spectrum exited with: " .. e:wait()); diff --git a/l4/conf/examples/arm-rv-lcd.io b/l4/conf/examples/arm-rv-lcd.io new file mode 100644 index 00000000..26c8c6a2 --- /dev/null +++ b/l4/conf/examples/arm-rv-lcd.io @@ -0,0 +1,14 @@ +# vim:set ft=ioconfig: +# configuration file for io + +gui => new System_bus() +{ + KBD => wrap(hw-root.KBD); + MOUSE => wrap(hw-root.MOUSE); +} + +fbdrv => new System_bus() +{ + CTRL => wrap(hw-root.CTRL); + LCD => wrap(hw-root.LCD); +} diff --git a/l4/conf/examples/arm-rv-lcd.list b/l4/conf/examples/arm-rv-lcd.list new file mode 100644 index 00000000..3fe58911 --- /dev/null +++ b/l4/conf/examples/arm-rv-lcd.list @@ -0,0 +1,16 @@ + +modaddr 0x1100000 + +entry arm-lcd-example +bootstrap bootstrap -serial +kernel fiasco -serial_esc +roottask moe rom/arm-rv-lcd.cfg +module arm-rv-lcd.cfg +module arm-rv-lcd.io +module arm-rv-eb.devs +module l4re +module io +module ned +module fb-drv +module mag +module ex_fb_spectrum diff --git a/l4/conf/examples/arm-rv.io b/l4/conf/examples/arm-rv.io new file mode 100644 index 00000000..7e480159 --- /dev/null +++ b/l4/conf/examples/arm-rv.io @@ -0,0 +1,14 @@ +hw-root +{ + NIC => new Device() + { + .hid = "smsc911x"; + new-res Mmio(0x4e000000 .. 0x4e000fff); + new-res Irq(60); + } +} + +l4lx => new System_bus() +{ + NIC => wrap(hw-root.NIC); +} diff --git a/l4/conf/examples/hello.cfg b/l4/conf/examples/hello.cfg new file mode 100644 index 00000000..4f00e3cb --- /dev/null +++ b/l4/conf/examples/hello.cfg @@ -0,0 +1,5 @@ +# this is a configuration to start 'hello' + +require("L4"); + +L4.default_loader:start({}, "rom/hello"); diff --git a/l4/conf/examples/l4lx-gfx.cfg b/l4/conf/examples/l4lx-gfx.cfg new file mode 100644 index 00000000..a7161e16 --- /dev/null +++ b/l4/conf/examples/l4lx-gfx.cfg @@ -0,0 +1,60 @@ +-- vim:set ft=lua: + +loader = L4.default_loader; + +local lxname = "vmlinuz"; +if L4.Info.arch() == "arm" then + lxname = "vmlinuz.arm"; +end + +-- Start io + +vbus_l4linux = loader:new_channel(); +vbus_input = loader:new_channel(); +vbus_fbdrv = loader:new_channel(); + +loader:start( + { + caps = { + sigma0 = L4.cast(L4.Proto.Factory, L4.Env.sigma0):create(L4.Proto.Sigma0); + icu = L4.Env.icu; + input = vbus_input:svr(); + l4linux = vbus_l4linux:svr(); + fbdrv = vbus_fbdrv:svr(); + }, + }, "rom/io rom/x86-legacy.devs rom/l4lx-x86.io"); + +-- Start fb-drv (but only if we need to) +local fb = L4.Env.vesa; +if (not fb) then + fb = loader:new_channel(); + loader:start({ caps = { fb = fb:svr(), vbus = vbus_fbdrv }}, + "rom/fb-drv -m 0x117"); +end + +local mag_mag = loader:new_channel(); +local mag_svc = loader:new_channel(); + +-- Start mag +loader:start( + { + caps = { + vbus = vbus_input; + mag = mag_mag:svr(); + svc = mag_svc:svr(); + fb = fb; + }, + }, "rom/mag"); + + +-- Start Linux +loader:start( + { caps = { + log = L4.Env.log:m("rws"), + fb = mag_svc:create(L4.Proto.Goos, "g=640x480"); + vbus = vbus_l4linux; + }, + l4re_dbg = L4.Dbg.Warn, + log = { "l4linux", "yellow" }, + }, + "rom/" .. lxname .. " mem=64M console=tty0 l4x_rd=rom/ramdisk-" .. L4.Info.arch() .. ".rd root=1:0 ramdisk_size=4000 init=/bin/sh"); diff --git a/l4/conf/examples/l4lx-x86.io b/l4/conf/examples/l4lx-x86.io new file mode 100644 index 00000000..f174079e --- /dev/null +++ b/l4/conf/examples/l4lx-x86.io @@ -0,0 +1,27 @@ +input => new System_bus() +{ + ps2dev => wrap(hw-root.match("PNP0303")); +} + +fbdrv => new System_bus() +{ + PCI0 => new PCI_bus_ident() + { + host_bridge_dummy => new PCI_dummy_device(); + + pci_gfx[] => wrap(hw-root.match("PCI/CC_03")); + } + + x1 => wrap(hw-root.match("BIOS")); + x2 => wrap(hw-root.match("PNP0900")); + x3 => wrap(hw-root.match("PNP0100")); +} + +l4linux => new System_bus() +{ + # Add a new virtual PCI root bridge + PCI0 => new PCI_bus() + { + pci_l4x[] => wrap(hw-root.match("PCI/CC_02,PCI/CC_01,PCI/CC_04")); + } +} diff --git a/l4/conf/examples/l4lx.cfg b/l4/conf/examples/l4lx.cfg new file mode 100644 index 00000000..ca61e77d --- /dev/null +++ b/l4/conf/examples/l4lx.cfg @@ -0,0 +1,15 @@ +-- vim:set ft=lua: + +local lxname = "vmlinuz"; +if L4.Info.arch() == "arm" then + lxname = "vmlinuz.arm"; +end + +L4.default_loader:start( + { caps = { + log = L4.Env.log:m("rws"), + }, + l4re_dbg = L4.Dbg.Warn, + log = { "l4linux", "yellow" }, + }, + "rom/" .. lxname .. " mem=64M console=ttyLv0 l4x_rd=rom/ramdisk-" .. L4.Info.arch() .. ".rd root=1:0 ramdisk_size=4000 init=/bin/sh"); diff --git a/l4/conf/examples/x86-fb.cfg b/l4/conf/examples/x86-fb.cfg new file mode 100644 index 00000000..083545ae --- /dev/null +++ b/l4/conf/examples/x86-fb.cfg @@ -0,0 +1,68 @@ +-- vim:set ft=lua: + +-- This script shall start mag. For that we need a frame-buffer and io to +-- get access to the required hardware resources. Target platform is x86. + +require("L4"); + + +local l = L4.default_loader; + +local io_buses = + { + gui = l:new_channel(); + fbdrv = l:new_channel(); + }; + +l:start({ + caps = { + gui = io_buses.gui:svr(), + fbdrv = io_buses.fbdrv:svr(), + + icu = L4.Env.icu, + sigma0 = L4.cast(L4.Proto.Factory, L4.Env.sigma0):create(L4.Proto.Sigma0), + }, + log = { "IO", "y" }, + l4re_dbg = L4.Dbg.Warn, + }, + "rom/io rom/x86-legacy.devs rom/x86-fb.io"); + +local fbdrv_fb = l:new_channel(); + +l:startv({ + caps = { + vbus = io_buses.fbdrv, + fb = fbdrv_fb:svr(), + }, + log = { "fbdrv", "r" }, + l4re_dbg = L4.Dbg.Warn, + }, + "rom/fb-drv"); + +local mag_caps = { + mag = l:new_channel(), + svc = l:new_channel(), + }; + +l:start({ + caps = { + vbus = io_buses.gui, + fb = fbdrv_fb, + mag = mag_caps.mag:svr(), + svc = mag_caps.svc:svr(), + }, + log = { "mag", "g" }, + l4re_dbg = L4.Dbg.Warn, + -- scheduler = L4.Env.user_factory:create(L4.Proto.Scheduler, 0xa0, 0x80), + }, + "rom/mag"); + +e = l:start({ caps = { + fb = mag_caps.svc:create(L4.Proto.Goos, "g=640x480"), + }, + log = { "spectrum", "b" }, + l4re_dbg = L4.Dbg.Warn, + -- scheduler = L4.Env.user_factory:create(L4.Proto.Scheduler, 0x18, 0x8), + }, + "rom/ex_fb_spectrum"); +print("ex_fb_spectrum exited with: " .. e:wait()); diff --git a/l4/conf/examples/x86-fb.io b/l4/conf/examples/x86-fb.io new file mode 100644 index 00000000..707f5644 --- /dev/null +++ b/l4/conf/examples/x86-fb.io @@ -0,0 +1,19 @@ +# vim:set ft=ioconfig: +# configuration file for io + +gui => new System_bus() +{ + ps2dev => wrap(hw-root.match("PNP0303")); +} + +fbdrv => new System_bus() +{ + PCI0 => new PCI_bus_ident() + { + host_bridge_dummy => new PCI_dummy_device(); + pci_gfx[] => wrap(hw-root.match("PCI/CC_03")); + } + dev1 => wrap(hw-root.match("BIOS")); + dev2 => wrap(hw-root.match("PNP0900")); + dev3 => wrap(hw-root.match("PNP0100")); +} diff --git a/l4/conf/examples/x86-fb.list b/l4/conf/examples/x86-fb.list new file mode 100644 index 00000000..1f649bdd --- /dev/null +++ b/l4/conf/examples/x86-fb.list @@ -0,0 +1,16 @@ + +modaddr 0x1100000 + +entry x86-fb-example +bootstrap bootstrap -serial +kernel fiasco -serial_esc +roottask moe rom/x86-fb.cfg +module x86-fb.cfg +module x86-fb.io +module x86-legacy.devs +module l4re +module io +module ned +module fb-drv +module mag +module ex_fb_spectrum diff --git a/l4/conf/modules.list b/l4/conf/modules.list new file mode 100644 index 00000000..63ab14ef --- /dev/null +++ b/l4/conf/modules.list @@ -0,0 +1,103 @@ +# vim:set ft=l4mods: +# Module configuration file for single image mode +# +# kernel, sigma0 and moe are always loaded automatically +# +# add kernel command line arguments with +# kernel fiasco arguments... +# the seconds argument here is the binary name +# +# add sigma command line arguments with +# sigma0 sigma0 arguments... +# the second sigma0 is the binary name +# +# add roottask command line arguments with +# roottask moe arguments... +# the second roottask is the binary name +# +# modaddr: address where modules start, relative to begin of RAM +# this statement is either global (before first entry statement) +# or per entry +# +# 'module' variants +# - module file: add file +# - module-glob /some/path/*.foo: add all file matching +# - module-perl perl-code: Perl code returns array of files to include +# - moe file.cfg: expands to +# roottask moe rom/file.cfg +# module file.cfg +# +# Define a module group: +# group oftenneedthose +# module one +# module two +# module ... +# +# Use a module group: +# entry someentry +# module-group oftenneedthose +# +# Set defaults: +# - default-kernel: set default kernel including arguments +# - default-sigma0: set default sigma0 including arguments +# - default-roottask: set default roottask including arguments + +modaddr 0x01100000 + +default-kernel fiasco -serial_esc +default-bootstrap bootstrap + +entry hello +roottask moe --init=rom/hello +module l4re +module hello + +entry hello-cfg +kernel fiasco -serial_esc +roottask moe rom/hello.cfg +module l4re +module ned +module hello.cfg +module hello + +entry hello-shared +roottask moe --init=rom/ex_hello_shared +module l4re +module ex_hello_shared +module libld-l4.so +module libl4util.so +module libl4sys.so +module libl4sys-direct.so +module libdl.so +module lib4re.so +module lib4re-util.so +module libc_support_misc.so +module libc_be_socket_noop.so +module libc_be_l4refile.so +module libc_be_l4re.so +module libsupc++.so +module libuc_c.so + +entry L4Linux ARM +roottask moe rom/l4lx.cfg +module l4re +module ned +module l4lx.cfg +module io +module arm-rv.io +module vmlinuz.arm +module ramdisk-arm.rd + +entry L4Linux-mag-x86 +roottask moe rom/l4lx-gfx.cfg +module l4re +module ned +module l4lx-gfx.cfg +module io +module fb-drv +module mag +module x86-legacy.devs +module l4lx-x86.io +module vmlinuz +module ramdisk-x86.rd + diff --git a/l4/conf/platforms/README b/l4/conf/platforms/README new file mode 100644 index 00000000..cb1a8fb3 --- /dev/null +++ b/l4/conf/platforms/README @@ -0,0 +1 @@ +Put your own local platform configuration files in this directory. diff --git a/l4/doc/Makefile b/l4/doc/Makefile new file mode 100644 index 00000000..faea86f0 --- /dev/null +++ b/l4/doc/Makefile @@ -0,0 +1,9 @@ +L4DIR ?= .. + +TARGET = bid-spec bid-tut building-howto dev-overview l4env-concept html +TARGET = source + +doc: $(TARGET) +html: bid-spec bid-tut building-howto dev-overview + +include $(L4DIR)/mk/subdir.mk diff --git a/l4/doc/source/Makefile b/l4/doc/source/Makefile new file mode 100644 index 00000000..31e4c52d --- /dev/null +++ b/l4/doc/source/Makefile @@ -0,0 +1,10 @@ +PKGDIR = . +L4DIR ?= ../.. + +SRC_DOX_REF = l4re.cfg +ADD_FILES_TO_HTML = $(SRC_DIR)/images/header-bg.png + +include $(L4DIR)/mk/doc.mk + +export L4DIR +export OBJ_BASE diff --git a/l4/doc/source/getting_started.dox b/l4/doc/source/getting_started.dox new file mode 100644 index 00000000..82a56494 --- /dev/null +++ b/l4/doc/source/getting_started.dox @@ -0,0 +1,98 @@ +/** + +\page l4re_getting_started Getting Started + +Here you can find the first steps to boot a very simple setup. The setup +consists of the following components: +\li Fiasco.OC --- Microkernel +\li Sigma0 --- Root Pager +\li Moe --- Root Task +\li Ned --- Init Process +\li hello --- Hello World Application + +The guide assumes that you already compiled the base components and describes +how to generate an ISO image, with GRUB 1 or GRUB 2 as a boot loader, that +can for example be booted within QEMU. + +First you need a \c modules.list file that contains an entry for the scenario. + +\code +modaddr 0x002000000 + +entry hello + kernel fiasco -serial_esc + roottask moe rom/hello.cfg + module l4re + module ned + module hello.cfg + module hello +\endcode + +This file describes all the binaries and scripts to put into the ISO image, +and also describes the GRUB \c menu.lst contents. What you need to do is to +set the \c make variable \c MODULE_SEARCH_PATH to contain the path to your +Fiasco.OC build directory and the directory containing your \c hello.cfg +script. + +The \c hello.cfg script should look like the following. A ready to use +version can be found in l4/conf/examples. + +\code +require("L4"); +L4.default_loader:start({}, "rom/hello"); +\endcode + +The first line of this script ensures that the \c L4 package is available +for the script. The second line uses the default loader object defined in that +package and starts the binary \c rom/hello. +\note All modules defined in \c modules.list are available as data spaces +(L4Re::Dataspace) and registered in a name space (L4Re::Namespace). This +name space is in turn available as 'rom' to the init process +(\ref l4re_servers_ned "Ned"). + + +Now you can go to your L4Re build directory and run the following command. +\note The example assumes that you have created the \c modules.list and \c + hello.cfg files in the /tmp directory. Adapt if you created them + somewhere else. + +\code +make grub1iso E=hello MODULES_LIST=/tmp/modules.list MODULE_SEARCH_PATH=/tmp: +\endcode + +Or as an alternative use GRUB 2: + +\code +make grub2iso E=hello MODULES_LIST=/tmp/modules.list MODULE_SEARCH_PATH=/tmp: +\endcode + +Now you should be able to boot the image in QEMU by running: + +\code +qemu-system-i386 -cdrom images/hello.iso -serial stdio +\endcode + +If you press in the terminal that shows you the serial output you +enter the Fiasco.OC kernel debugger... Have fun. + + +\subpage Customizations + +A basic set of bootable entries can be found in \c l4/conf/modules.list. This file +is the default for any image creation as shown above. It is recommeded that +local modification regarding image creation are done in +\c conf/Makeconf.boot. Initially you may copy \c Makeconf.boot.example to +\c Makeconf.boot. You can overwrite \c MODULES_LIST to set your own +modules-list file. Set \c MODULE_SEARCH_PATH to your setup according to the +examples given in the file. +When configured a \c make call is reduced to: + +\code +make grub2iso E=hello +\endcode + + +All other local configuration can be done in a +\c Makeconf.local file located in the \c l4 directory. + +*/ diff --git a/l4/doc/source/header.tex b/l4/doc/source/header.tex new file mode 100644 index 00000000..6c85a346 --- /dev/null +++ b/l4/doc/source/header.tex @@ -0,0 +1,45 @@ +\documentclass[a4paper]{book} +\usepackage{a4wide} +\usepackage{makeidx} +\usepackage{fancyhdr} +\usepackage{graphicx} +\usepackage{multicol} +\usepackage{float} +\usepackage{textcomp} +\usepackage{alltt} +\usepackage{times} +\usepackage{ifpdf} +\ifpdf +\usepackage[pdftex, + pagebackref=true, + colorlinks=true, + linkcolor=blue, + unicode + ]{hyperref} +\else +\usepackage[ps2pdf, + pagebackref=true, + colorlinks=true, + linkcolor=blue, + unicode + ]{hyperref} +\usepackage{pspicture} +\fi +%\usepackage[utf8]{inputenc} +\usepackage{doxygen} +\makeindex +\setcounter{tocdepth}{3} +\renewcommand{\footrulewidth}{0.4pt} +\begin{document} +\begin{titlepage} +\vspace*{7cm} +\begin{center} +{\Large L4Re -- L4 Runtime Environment}\\ +\end{center} +\end{titlepage} +\clearemptydoublepage +\pagenumbering{roman} +\tableofcontents +\clearemptydoublepage +\pagenumbering{arabic} + diff --git a/l4/doc/source/images/Makefile b/l4/doc/source/images/Makefile new file mode 100644 index 00000000..56839416 --- /dev/null +++ b/l4/doc/source/images/Makefile @@ -0,0 +1,23 @@ +INKSCAPE ?= inkscape +PNGWIDTH ?= 640 +PNGOPTS ?= --export-area-drawing +PDFOPTS ?= --export-text-to-path + +IMAGES := l4-caps-basic l4re-basic io-overview + +SVG_PATH ?= ../../../../doc/l4-clipart + +vpath %.svg $(SVG_PATH) + +PDF_IMAGES := $(addsuffix .pdf,$(IMAGES)) +PNG_IMAGES := $(addsuffix .png,$(IMAGES)) + + +all: $(PDF_IMAGES) $(PNG_IMAGES) + + +%.png: %.svg + $(INKSCAPE) $(PNGOPTS) --export-width=$(PNGWIDTH) --export-png=$@ -f $< + +%.pdf: %.svg + $(INKSCAPE) $(PDFOPTS) -A $@ -f $< diff --git a/l4/doc/source/images/header-bg.png b/l4/doc/source/images/header-bg.png new file mode 100644 index 0000000000000000000000000000000000000000..2785e04ef17ba4ecf5824c4a7535792fe6541738 GIT binary patch literal 715 zcmeAS@N?(olHy`uVBq!ia0y~yU|?lnV3@(d#K6F?`0EyZ1_lPk;vjb?hIQv;UNSH+ za29w(7Bet#3xhBt!>l^B)D1O;WdMcC&vFfd4#xJHyX=jZ08=9Mrw z7o{eaq^2m8XO?6rxO@5rgg5euGcYh&c)B=-cpQH__2ASy20YI8Kd#g}YpQ)WX_Vmz z`gE`8{F|yjHj_LB7&QO>`peGH=;%7{&VBdDGoemNcFziSw7d#!1dL zRX&f&hs!v*Qy4r&Q~okf5sH+3{KYr#&zy$Y4DAQAdGt=|M6FDD$d*yM=gFpBae0;j zicYaA=@U!$KA*%a6#IYDvS;a>ON%Bd^|SfCx-4*E_PI4*)#e8(e_XBnwKbNf;lo1q zJ5R2;d|#(s-}=Sl-K936S5=?(HRlVn)Xy>fH|e?h0ri!03{2A`_nAhO9Jy@1k~K6o zLm_7NPLX})GgY)cEmcv!f30NNDf3fnSMED)|HbY3tkZt>IbR+=|K#f_#eVVk-m7cP z_skNxZ1DHiOs}TR6ZVR9W-Wdunz8T6j;6^nUc&O3UxL0oOjM}K=6Tsw@wn^NzxT1P z|4-Ae=uJ6qBN<(4RbIz-|8@9>Z(S9C1RM^>pE|vVgMZ#%dE2LtuAcX@_q-wh|B}^Q z!(yLE^D4s82ch~mu%nys7s{h?3`D$O! z! z;(0M9akj=KPd~5tf6e}EtiREOTlcNgY$^)xXS>f=Y4Y!iKK4K4+~uqFRZH#_E_%29 zVpQ?HOuzQ8$9)9spU?jBV&`++?>4!1wfro8^3@lw%hn(7wP-f^tML2q|K;`n?EioM a9N)~bVB=}uxxNex3=E#GelF{r5}E+Tg-v7t literal 0 HcmV?d00001 diff --git a/l4/doc/source/images/io-overview.pdf b/l4/doc/source/images/io-overview.pdf new file mode 100644 index 0000000000000000000000000000000000000000..994b2e53f42d9df6bbf48a4f0d24932376ca49fe GIT binary patch literal 41742 zcmY!laB{f8PJ?>#y27`)^c8J%0T?T=Qpm?#&P1nZL(}=e3=lS~vCe zFRk<1-&@|r=U!R=*i`Um-9B5cxcM`zW}o{0clG_`I;{uS#jA^0{`@Wd>$URy{j027 zMCxB^>mPn~Z2Lmz+7RK72V`Enex3jR@jv_h|Gu|(m}=NQ>Yr7$``7jVpW{9E3acDX zzJAl;!)L`G`)ytRu^Rms?R+19z;TOTVp-_n-WFVqE>z$-XSl6i-)fzxgD#?rYpL^?nDNCuQqWQkd(v6a7Bqh%lg<2(_75UoF>i}s`hEHJ zmH&3Jc~o3=zsB(Fk4;%DKkF-|)5;3Y{oE7lr%LHBPj`z+uafG#c0T^^nhKkJ|1KEb z-JJhaaLK;^G@F*9}hg$YcZZSJ=oaLG4aX6>9bjiY_cEd3f64t zar8U0JJohQ`@G2ZujvIV8E42j)*Y};?fP!fzKiMZ*8{xX7nrYUeOxcODkP=SMB}SD;}%efB$?le?@xZ%gC$hGklgO zC(X;V<>rc;p7h}Md8cx(V_eqXYo1O!(j?-4-QkMn!t)WAYV(!;^lY8pT5%wT_nzdG zS5pJ_-<-}qv2}+$=Q;j+S)Il2%N{qkRQj@1)j6_1Zk?>u_1RxG_8QiJorcw>X$>n*C%z&hpMimP2Uo=@NPe2 z#>Yyjx_^zPo(~U&NKR5~KL4aaWU86rghc|^j*G-@TD9|wLdJ%TbNlWcR!GP{;O7x| zHEQD5J%TUTmLASeFzR!cxp*&A_=Vs!W_gx!!^)NA7v?`X$|GyFb;F#|5N+opY;3-n?CxScd9#*Q*%V@!OU5=^ru_hu;QJWE?HH_cz06u7XcCG zU1A<}Jm>WP|2wm2)w9GYP8GASnMm?ac(?Aos>b|x4@FP@GB$OaHFvp5l8Jjlg1&vR ze{6-=f+j{g6?^^lvpEx1MoB0N%-FVEVudD`@shB@H#KQrjLYBe?q2F2z98(J(Lr&6 zOY{Hzz37$t<8?oS?FO;Q?z;=G9?Ob9((rMH=LWyE{)u%y0=LhsI^Jk;O^#9b?r%LM zf%A)%i@RKv zqdzXz8+^O=KFUB|;P>rz)|1B!wx?cLyL{=tnLQ68CbikmKWQp?Ylp&~efKQ?yqR_4 z%f(AFpWd&px;2kq>Pq^ugwRcqzZK+mublF>bFrPv&T=1JrPC^0c-zrDYo`)Br1 zB{``&XOD%~+hgWDkye^&6#D1mfu-3e+i%!Es9olJG<=5E^^lMJ74gB1+b{oqxAM_# zl=Y+Hpp@L()O_;=kLJHG ztT!;N>Au@z^5^n@!&@OQ&!)Y-^5M8~OkvOrsn>H&YHFXY-tKhi1HaPEx~8`EZw(E1 zew^H8zQ^Q`i^t)|rP(SO6(;q|d=EEAhF`qX(8iwsZt11@@20=Lx6JLZUg>Y!$>#1W zex$XZxbi_If1Xqw*JP7F?Hl$Qh|g2I(j4&7;fqnIjh*GPw)$Vr!BtrmB@U(heL%E29 z<`Oe%wSKT)k7aebz289}_+?J4e)Quv zGhh8}%w8M3*L;Wcv5@z|JYVyUEW3Am@x=47M_H0q&A54jJt_D-e_Pe5S9`afbXxIU zOm0cQdx@lX-g~#-p1-B%-p0k-IFgl~|9vj_OH#<@kjj>_dI8OzIqtigWACv!@Al7Y zE2~e}-}+nq`2W8RXMg1cKMZ@jxbgnye*W#x7fa8x`}ckSrxLr}*)yv`Re9wv$?AMYw|nND?PvHFR{APVQ^dd%}sS1`%gS? zrS62RJ!k*SdH<(tg38<6zMOKYF*{VIeQk-;dymsO*E^iVpPLI7ED*Cu)N-7m%O8=D z8ulhmXs+h1xlF-U@)=*wXQkOE9GBakWu7e1AHHs$n~m(Q9af8M*L?i?C~otCRQ2>Z zbIJ>Z63+i?*s!JGMWg6-1sjR!G0h(jc=G4&;X5y?!()El*7EQEe>LCkS?y}q{X1i? z_?KDD-SMWMc-j-|X!1<2NX}|K42D{=Hf4$zgu0y_(;9g!PLu8$214wk3D6 z)g+bI7q-^tugXcPZji=sfwX<0;^?_>t{m7l4 zBnlbYCUd-Xw4Y~i6V_RWyHyed1izM`f6 zz)bh~PLt#!+46!}kA5iLj~CY2;uB}RD10Ly*SX13@z(ynpXMdaJMfY1ZM;zR>4KhL z9Q)ONuH4G_AgNWbU1j2f$Rk{mxi_1)_pRLWdqtyM_tKC&tu+hyG<7s~%;CCg8z3ZE z-O*!Qf9BBSj`k|f(;@c+^Viqx7VQy=-@9|xlAQ~f8mC)*|2~6pu7OO0u+4|5-tCPN z9C8&Ru66Afdv6}Fe35i3s^WF?uBCtPy}FjXI(hcqU7{V!cZ*D|DVi_!L9pZMd%@3t zc<1pRQMZ4P{5~wt=6JNp`Tkcj)@KbrzViG0J^YH-)R6TDZ8w*^F=^Mk^Lw78>n4q9 zxl(>o_J0qoi7!Yr4`ZI0_j_&YcDp|tqyHbA=3SSge}rwV=uVqS1=n{)>YYC_`J3sp zjrvRe9x96L*bt+Z7Ny5sY|VDOx9zFXerw(7H@9c*Oo{j;eD3R`N#<{-wQ}rEO+&wvE&bq59o_-2`S{qvr1lss9GAurP;e*5X?&GW% z{u}x3^5NBY*m-!l$@IzWhfdY5`TFeUgW|=q{97VceJxu)zb1Qc@$q--C zc^}Wc@mP8BbQ8hjN9M@)C#+^P{oAlfj7#j$4FT8J;(iM^OuPT4=K8)_(;C=!>$J9; z6!4t8&wbaWYG%vcqI=Qjuke08{pjwSu)bckU4LhFnAaAE_v)Ux(y)B)FNFslT-IOf zrqJbSJb{|&#RuhV(0zn-&M6mF0bVZO&d<{@KDgBJGu~XMCF0 z3BzM1!H&C)eT}~|>Q`~_EVWZ`(md?7*Z*Wv z#7ahgZPD|==Wlws7FSBG{4rk3O;de7>AeAp}JY_@xCQ@L){(&2a-}PyR;C@@5~SIgIcwzt-~HysrXf9NLwpv+EuWdiy7l(T z?;W-bC;tD|7I;whSmf#yt~CFW)C?Pg8?a?>b6pY^G}vD%8&>eHvPs5MpRefav-@W%VvKjKS^d*!>l zy#8diGVK)TRJ3sWu-bQ4j)IBs+)HI~GVbezMHQ7C8I5dY9{S}r^>j-)>e~gF%zpIs zP{!(;Rh@=Muj{iNlige{b>Yol)Aakd8(f)>e$m*NAEAM4(iuGYJT->I# zLm|{x`I@Df8l%{o#D#jBGR0<`e{;OEV%EVTjvX2TJgbURza~uPx%Id#yg-I4c5>IQOI!PTR_&A6v*>wj zw^#eFdWY4C+s|Iu;NJU9dsooYJqu>Z2eEGYrMbqmOz^?v8JoVbypQ>%{P^GB8DaI$ za@+UYvfWvmVQW0F&(4&+r$NE$8yk5odaZ2jmzO|3H&N}{-*Y@3d`^kP$ zC-+`%NPEw^&yL-vP)a=a$?;8XyZ-Kt6LNB{E18k_?Zcz=Spks0Fcq ztY(ynwfbmUZ@Y5C*3L-8uYBujgcTJx*WuW>Mv3v$tCXjQsXroPDfTp@~O=_wEaY>H}T@?7P+mA6{Kv zV4`>-X$Cik7_*P_lSh$_jvE{AcHcK%E;*~c|HT!j&Wj>Pm(E|_VOsEko#WSwg(Xo3 zl9~l2xij~0PGtyIy!B4p_u}ko%VpbM`KH4qIVthV*7v-N@2z*+e0bwM%|+Ut@-9{U zCn~mG;aTc8eY?P!jatro4jjdY8Z8Ot20VeGqRr?LL8SX1!Sort#t0T%Q1Ww;P>2&^- zl>5fls%}+p`a48gXJrYlz9GNqMP!Ah&Wp8m3I-LMmQ-BdVsQS_af6LVmz?<>c=3fJ zr|@z=~u^*43x3{INRs=*rni0gZbm&YrBF&-u~UW$!a#2Fben zd)?zWPRM;{6)yg5_p|SzBW0nE}ksU_*%#HOgG@LzWn#T>gpvQU)YrBByvMM)1@X# zxP4eBkAv)Jmf6`$>({EwJmcNbC%I{H+!L8E z+Hu#uu$iT9T5|7U(XlxXK1v2mpLyhTazlIELdDr#N|yB@w`!NP`338-K%XYJ)iJ8FY8R4{=DO_!0j`# zeg9wW={bM&=&yx88m;b0Y?(JbnhJJE-a3RyO?g@W|hHod?F@ zIV0@y5ueqWhc9H!%5A%9vfpa$vYQ(-O>Jka&JVlH{MqdKmRV*kYnOG-47+^fM%Jv} zTUk}h*+mbkcivmOtj0ey$@0*{tlHV;!k;@%)z&7IRB*JEn)=BYZT_9{dBH@U*#57V z*d&tYtQP6N{5$H#7q2y+KYE;hx|VZJ{J#1peXP^=O6<~k68ElPul|0;GcwwI?auY@ zXGEO3C-7mNa^K>r+Z~fj=IFOAEa;c}yQ%bG^HQ0t>&M#J_s>*U@V})aCUhl^)AXUW z@oo3K*aLlaGd8+^DK@IoJ1M{BdCSp@H@4osz%97=eDK)|Eyog5v}SY0inMHyy|l4xsu^Ux;kf)npe?;bN|*NmL}QRmQ&sAXScN}k!QO@Fpr zV)xgc3k)mMZk)?u%)4qZ&-}u%&ut4o_Ne79(R#*kf6uKv8}U{HpU0ACHZ2MK^z4F@ z#nJhb?#Vqgy|!Uq_qk5<*OKjvY>#YT)w#LKtK{sW#PXK2&pT&+`&{Gx?DNK`t$+8_ zUjJrX_3Yqmm%Eq*B`oS!Sb$|KIVYh+BhF(d2WtY@FuZr9v1 z*f8&^)1_JdpLafa>G~FymZ&M;*VzG#%gEcZlBA(bgAT-?Sg$X&n2AWus>Uoe6GrA zQ`Y61XKwmF_qDxPa_@?`@ALB36>^wVK6{WtjH8HE{~_V-FRD$#RVxwc8D@m+m(W zyuUwiu6^cf)^)OZd!Oi)NW1C8y>I4kYO%lV794ouVV+scyvv6+WS5m5I(TYcjM%*e ze~(H;o|WijTYl}0oo_d*w_Km>)W;JGSSl;jc78o!deeGVs@@((<;b=*syPt>&)z)A ztWvteSn%$%@Y&fPF4$iG!u+!JnYdoe$~zB^9uxc5^1@8N=BE0({Hn@;6V4Y~&undo zd6;p1k@LlKKXV1S)}4(#!!G~-%x&FIteiDo)jlWp^VPqc+sPcY^tqS#*BM*~CD=RG z9Qzl?!Q)rGp|JLz{L$rZE+wv~{$+g7Kb+wAGi}kv&L81Y%~h<)X~~Th`8j#!mnPJU z{%-ZV<>OOsW`5^>LeNBWo|(Bl>nak~I_(jja+0|?zae|A(VMBKxjD|%9N(gIs*?*2ZeO&Y*YoYd?{JO>3 zl80WoE_N$c=Rd#`G52uB#P>OT@iX4@E}kQ1wUEKGZ~h8b{=1P28J`IL{}(l5b|uq( z(S@bm_EY~{I2v||rTj$Wg4ep*&PTiZ=R7ky+ghXf+C9umEN;7I@*$Pms+;TVf~NeK zGDSS*j(+UUXKHfgcV^D(-~Iedw!;*^AJfbuRtAf)MS8to+xcw9kDpUdU3hW*TK}r6 z$=^0lvdh-ES}EFZdaFWZMdR-FpV=2zU)ochtFpGI$WH9+>Q;pvLG_urHw03PR;~^V zUVLh1&wA?%eUX6-+G~UtF=k8rzcjVzV)gu~{*xXj#4V8FRC~&jDePRNS}(FY;zIcR zD_@H~wY>Dd@G;otA)kTyTTS&npEV51??>;bTv=1c>|XG0@~;J_qgVGop3c6sWP4M5 z_KeTvf{8D@j;l;I4(u|on#aDa+q{`m*#7y1J+6IHH@8g8d-Ud(hCy-LIZ$hD;d^_t zf6upmeeZfD#y2uLYw6eT(cuO&>l|j(*EOD9^5(PExf2@>aDCLtz7m|@Eg|oHO14I` zOWB}+=hL&QwZ@ZG{TE)`=w~2kA(_K?VI{wwuGt5Zq(pZw{pC(BR%^K;GlZ{kd)|Eg zNbt6G#^sq31)q+|#Y}v-$j$1G&xM;ye@&f|c(5S!$6+UtG#?F~UqNMSqB)J{aD*P@ z&sk)>RPoHVkg2z`3>F?!-EXytF?Qm?g_eJ3zk6xW$*lL=l}UHfMb51Pr?@OG`Mi!3 zHrQ^=(!I&U`E!oROE-(MBUg9DbMT1SnKg(>-<3b}xN&jsB_FnJ2Zgt=x3&hXwAVY- z(VM2$6{xmm;@muwyXWE-#+k7#m{b;Uzad&+_Pkk_=IAf|;HUra+7$QXIa$HwTf~-xY&sm0%EX*pIJsw0km(P>{5gJny#Lj!pQdE(C}y*mwEATc z1N$T$-#tIQf7+_MZH#cWA7ZXXr=bV@N1KzJ>4H}z4dUy{?>yHTKc>` zp$rz*lPg}TE?XPYp7ymMET|77mE0g=~pgQ%GhEys`lGgrL)0LzPpXPEO_@kF6!pgi$b@`zsDMHhN{SEG{D$`A9 zo4Ur$N9pxI>>Jz>%qJ@2T^7D$rGg8hjjQ2M_JU9OQkDfz;+(wyzMNx; z)ohE`Zs)|z*f!;Ut6mr6FT7kh&TMk9W(nu)2i(Gk%B|Gve;;*uk#S|UrWwbdHRAlL zWlHB;1V2tX7v{;cT_Bm+=?KF?=E+L=Di73toT`le<`F3M{LQrIEx#F$-)OSFY`*87 zL03JGSjoM8kKGr1Kk($Fa#gl>`VQq(@1nyqLi?SQj9g=q-+sAX=e^?m)(=Z(GH$(W z%lhe47SGb)###JYo2GSbTz;nX%w+x>+zo~~DJEM_U3r%3bF+isa1M-sUG^)>AK=p8mkjb2>e^DrWMnqb9~N%V)$D zCQbX4Q@U=yz2T`Vg>Tk#ZZ(*je)7G9PTbpB!Bb`jDCKeQTOIns?6c6{Rg29JT$yDW z#@rewzdGCL?cA$#{@lCIbtJXbWcgd88yCtCgt0`OZJdyMui^s7jO8u!jvjX^xi1$t z!*!w1&gyyvmlw(Pni=^$mfI$lCLOrGaAsNYSB7YJpS^yE*OqEG@J_VJRrt&h4$esBDmD%BjpFZ0dp{8r(h&RZQ9XN%lyzfDh&-t4kp%g{mZ%8ZNI_Qhh<%#=N&#DSN!b5);;SVYKtF~isrk2UaBrC=$w1Zp^QFz-*d-4 zr0U9cGo0+w<=F5*!C}@aeYfgWbr;mrqPIQsu0J&AD96-gL56Z=*Y26b^>Js{6wLgb zvH7~Uu*cWC{w>iJ)>#E;%ExORZgmd-U_VTLt#&fvV z>2KvR`;*qPNK7GdpE-}x#LkZCJwGn?d^tJex1q=l$IFcqSH83EEdO`l$fY}#6}8se zTI%#dZg~}N{G?U&+n{^jCdV81l;5bZToma4o$+j2cavtA)(HMeutoNpx$Crq3xyt#()RiEwAglolzY9rcb z&1>Ayx+AfoIY0Z+Tj|61BlZ?-Tz>OxK}n^|Y1V&+KNL934^98H>Cd%n>1VU&KTCB= zzOi*xnU?JB2Tw0BFZ-K&w8?+v=flF?>t69rvyid&`s2I#jrdl{Pmz%-OWw)3bU(76 zuCn5$x#MjCqbFCdPL{lDa{I--9hcYeltp^HPrUn#_t#qs!&6UPEn$iog64wLI*bR6i~EO)uM!dwIe8o-3(0lGG=s-F?5l zb!OJpm3#iRynLgee^_sdRY=KG{^XXWh4Gi4J}70{*_W5U^~KwrvJs+ox#^3d^70eh zZpl3MFf|nwJ-X(VMgBXD3BOKDyUa0UN{h%2oHR|AFaMLv+J|QE1?!X43ZF+eT9$>( z=ieyBB60gly?%9vBg=`!mIaYVJuM!|@GbP?`jR`DVTa!dm$Rk6W1r6y68RDS-pJN6 zG)F^k<1%n0<`T|ITaOswcbdIjHk;w8+k@h@Vwk# z=j9mN%!&A@^z^`|ibe6)4xU{!{k&(d(eZ7SHjn@P|8~UYSauV;vHP0I`>anrzxkN+ z$G3$sucd8l=N*%I_$kI_!|BgqorlgotvnufUC;lFl2z{EmzM2Dwe#fOKKsnlI!i>o zcHZ_Fu*Vphdn zZ}3R>&qI3~L$9wV8Isty{xiS--sD)Ht;Y<*hRTJTP2ZXK$zD8H@IrW@Wk%8;gT z(bM|#4MDCQQ8S)A{*mGI^5Zr4NvCJz{Pobu-)6Py;o5~9b$=BaxUPn1O1K$!X}q>g zaB2D>l)G^4W;?;Mn+_&6UB{WN_b<+C{?sGTqICZc0GKiT=vc>Nml%G zoM-1mCdzJa77%aGbKT3#%zP#_lw^bdY*hjc-}(EuJu*hZgRhw z_sZe^+DkY0A6&lrIE&jKr8%k(&-nWuu~ogJ$ar+dn+XlGY}H+O^d2?5?wHUpBh$CK zG~kReZ%gt*xs5Wj7grrOPyZ;Bx+Tsi@p|2|S+NFQ2X@anf9T6IFVkI`7IiD9bFGoz z{O|nQ**VRXn@((4$L=+Au@z4@-@;}ppEwk2~>tD%S<&8~yQXceGGW7d=@Ls^-=zrr^ zY`AwwZQ-f1qPN+T*KuF<)tQ&R#PM)Gb8MZRK}XLr^M)hhrzfjExb%MYw#i9e{x=uD z2;Dl#DRyBy%U$`ebIX$cNT1C_= z?}IJxwfwc;J(#+EYlTVdx4YN+9%@fJtm@zR@ZzH*HD-&A&s?6Kpt^8>smr-Fe9Bi2 zw;8^VFfKVRW33fee8DwHL)}?#lN$49Nz>hrimt?_^RSk;PFTG#LTc)H>!*ASHLuJ4 zPoa9=k%#|^gizS01gD%(H7Wz;i-1vcK=8PvdmY7r?b2yl$E;)UH zjPpfXR_|LfUDx}km0YdSGdvOz!kw?z=&*dcjGOU|>eH>dkD`+HKKIi|(qQ;}Wzo^t z2}ha@_6kXe-?|;wG;^c5mjBalv7%S+R3Eb{iN3Dfroy&7QmJam>$ej%zlDC;sJgiG z#*|(4%kMuBdNDJn;_O#hW;-FjHrd5RpN;IVpPC@2#?!DtgmsF+$M9*Br`5=twJ!?q zZN0xoDoY}0>P27I?eo`dyk4?b)ahN~tGIs)x*r~Asrg$Nq-1|IbmGzPKfeby@;`hg zf9LL<{|+XWuP>^FwfdZSK5I4egdWGv35#wf^LVudu*c7>dzh>kBJyLa+{;_H>-Bkz z^uAqvw)Xeyf->8tNt3?_tvH!{=--QM+lPI%`4V4kXMMR)ccFR8 zf5*k5N%k-Ql$%Xhv-Uyt^N6at-Fio_uYKZozh3;`^>172Z!SH3nNP%6x9&lXm52uAaWO;`RD<@7)-$-Q2oj|EVCM%)QQ!o?Lyl zQ8}oqi2snwrt__V@52{M-BouDk$BMT@m|vN!JWdBXCLnQ8GGswXdEQz^m~bzZI(qA z-vt8BUU?bo#btOWR5dUpc7oy!kK?7*6)Xix9^V@rmij)QR{QtdtuMD<^OWAOD=3z= z3zMJIcyjKYhs(I{32$!eI&GEnMEL0SQ|fL<<=D8B7i;g_aP?rYyvyqEg7S})Jy;fQ zG(04`ajjvQ^EnCr$$=b#-=p-)uj$>2E^k_Ov++UZm-WB%Cbxh1b+9az*MHN8Rj;)(M|}@_l;C^406uj9h-*W70p!f83kNt#L`=s|B|{c=uk} z&i-OIL(d;Yk08qu@8vs<4rqQpb(dw$?UOrN3v^o^ecv3<$+Mb`QBI2EbZ5_HIemqo zkJ?A4w?<4#K2Q-XeCD5FPU8nFuP@$DXEv_7q~gWu%d=WvO*8F|iGW6Z=)&s}p^7D` zd#qM6cqPwC(#x45yKjy|U1EeAn{SGF;i}e@N~zDi0v2;#xZmuUaNg4Bu3TtOU${|*Pig(Cb02F#OmjW2oQdQyIB ztgPOidG^GqZ0FGbI~+8Ed4AdcigLQ}{&JYOhP>U21u z=<1q1JB=ecet%J(z}dEK#euuGqqo1ix@WKJ_Eq*@|2}?vYGLJSKjrr!8j_q$LF=px z?@Ondnckn}TWj{^?^g4BnRDLua&I=j_agPSH2<0Ywks8rZ63dCufA9J(~Hw@596mt z(ht@wYU#PpyvD_2d)IV<;Mivduh$61v(540s$|%Bw``TT!j8XvYfRRdyx4tft(#NJ z?dfHOic42l$%jYWaZhyI$oo*LxH00&J_+~l!h%cgMMe5VODxw(IO*QIf0s$Z1^3%6 z(O2i(@aT$a3fXg(Qz78`#uuD=*S7Nu^0ND`|E~UE5?f6tXGpMaQ6j^|EQK?Nollm0 zx_&M-=6PLh?WfpH4>l-?Eb-kKFP0|w!A7}00* zla#Zz-{7C6{A$@vjbmoJe@{|=o&9TF^TX+{Cb}v+yuBM+B(Prh%;%T6*W_J>U0|kSm+kUqXtY}m4 z-&io+i*uS<+O{LP4}K^w`%v;Z+O1-NgUlgc6+N?qg*+V-=O;clzq^r}`%?%DPv_OW zuF)IH+X|#}{0)p)eO)XMuggDGdETnj`IYR)mpYCs;!N`G+SgsPTs=|XxZRaCb294> z_#Es=vlC#qHZxqb_tVNvS_@M>w=&eeV+dRos4(fO=*=AIdluD8J@f=$-oEBHt@-U- zO)>u`uhasbcUMo+YTWyF%V#yV%P+I1vx(}|PVaM;ZdhFT%kAFSYtl2Dgn`JedS>iHYsZ)}LEnyGXC;gZea9H zn`Rt$YCN=YM_deN=vluRs!64V|CxoI+{2DenRF#IcGk?G@bt}!rCqnSp4r%XS<6@H z>Fvq0FT}=8yDl8Ge`d7MtlRTsYg!jY1SsJD! z>nAy*vaITj25;Y-Vll^1)jiYh<-cOz9@Q}SLbgV4fP~27NxwCCraTN$xZI*>dagRj zgZEwJ1r6<6GOic!HwDmuVdBH(XZM;*sR6=WnIYO69zETfB4YuayVaPBdvZsOgDg@w8g;;opnz zx3g~jsyFPwu~r-fLycy6neg4dvQbR>}!8D!Ka}%3FJ-YTs=N`n=BH z!1qV?>lPPvE6>QTQ&SFl$iB_rGwq?hprWy3?_>3>iOy3QC9gmE`0w8>!{;lv<%jZQ zcj>dAnK8Z1`jVD~#P8^rj8n{>Ozm3sCa57b?M0BArEFf_kEOFFCp$APlW!^!pR+hx zc~#7*2kUIsSuFaamYaQN%c{#9|K+uC;_q9(6xkoWT0W_8{X&uB zcVx4-ycP^}zW2s;y@9Zp>(drXv6J1Z3NwVVFCJ2OT3)a+KJLM!TMt+bmmLh0wmI~r zOT+A}uHEU#vZb=0rA|%MXwTBwtdkTuZL53J%|$Oysv30bteWD}mwM1cV$ZhtEz`^k z3^VgCgnkMAx#{4~qTKlzw;r#z)7W|7)#9M}M>YB!_H3KD&i&BOf@QrSzSa?!HtiJN zu>ZT|#oy-^m@U=|SUvfQ=-)RnXVyP!-^<5O-_9d`FH+JkbI!%3TK;oD<-DnA{@G=A(u+K83rkGi z=L&!P+h+0H;gM{j-R!{A+nXNm;#>Z-Y{}kdpDr})6n|;ewg$=6+r!UfX$=jMMGw5*=^qx!2X%kCAsvsX`)o@=o86x&?fiGwUu|?eR{VdVTp=??@Ems z{ENDi)};hz^Dl~f`j#_FA$HcB7{lJxez#*Z)D4cG^N2BvTBFDFp{BOhD4ywIO;&8X z+5Y`vX_KC8%YWQ2A-hrbceY*WY>B%G6~{l6$Qrc1UgBla}I$N~Ah#80q zCOlcVuXa|}57qvPEsR(0-PYu|oy}dGcX{69L=IjPUcc%B#oZozWENjwmt~E8_?qQp z$r9Gt4+Ia_=lbgi-PN1>Mcs$vNzMylQJ>qI(lho?6xg+6^1OqmM5SgNJzYyV!t3^U{uI1e8ZyAqkwHjaCtsxMC4j zUfx`bLZL+WeJ2^;-K#rw^mJZv=sB;#b#>*IKYAObw^zS2YPFj4UhTt9D!lh#aOb+!5e=0uMV$`M*z9Nhm*dE@1^46@ zUcSBPq{GfT$(O8n^fIrt)yMtu*zRa%S%+1UaQgfWzx4Vz zoh{|It*rX)IX(O`$A`>$&kDsZm%QSS@afF6=F3g$YCmRHF;#-=oO@aD_3e)y8|#}+ zKC#!IyGi%M9L+UCr_MFW-g;s7nA7U|MYU|Nhc&0SOsg7J!gglpxA&G91cGH~h$uAVi^X0M5YtN8a*z@Y}!G%w@d<}Ar zeheD)mG~`fDI)Tvx_(*v^|-&c1bTws^0l_||G$zhvNA$6_Exyg;DgL+1W+-h_li29& zlHn@4(q&ih)Xrz@m9H;fUV1yJY2m@-g{dtsJ>JJmzMF1xeYWNQgD!^O!j4?u)UKX3 ztKo5+)kkLIw-0$2GatVF)GwF6|F-urlaAwScQj-Q^b2-tti5Y^NMw_xP22aP*NwNc zRvzA7`b+MWNqeKv)f7JFYegE>742`O#gaC6G)}VpDlFU*`?e;@Z1#+~Co^YiBx^YC z@SU{H@K^56d3!d3yMJ z5$Dna!oB-+SobN2y?p*=rNVjc2hU!vjc`av`gvrfc*5*OH|0*)ct1I3+!Sd%y=hWz zPs%*MPtqrKMV5U^FkfRVkb9xosbU0lzL+vgi_q#rr?mMgwr^6I4if<3;wv*)Z&IqC5%km-<`ZZgA+ zAaj?1?% zYvR^wt;@TEH(pe$xNXw->%M!cy-4KKzo|AszV2%jL>{F6nUQlZ(eXgZrRRT7TGUpQ z-Tt%EHqKCOe&yntAQi*b!;&sy#j|)7LUbP-*;w;{?W9!a)!Q47&8pGtdXgD5amOU@ zPnM=!eU_g0(k9B7N?Fc*)_hi2S4izR!Ou}5sS zx?&LFP-IYi*<`onpUu8JJ55s5t}c?4=yH!UT(!*L%$saY_bn=xOy+v65`aE9lQwSq(h=K^{4{i1cZLw*E;soC$(nf z+2T3rMvrHRENXlms=m(uU;iu{LA$2O%g(4i&J=q3v7r9`jQ-6FAI=fX-Qi|_=B&!; z{0&$Be7N}9=}z6FC-ayhS^Vyo%{+9v zLaF18Si`0j#>x+wx1Bz#f9G7LT#Fvxi9d}uZy4YH>B8FC^6^6iBX_N7YeZoCGPfXU ztu5Rllk*pZ?x~9N+ICSiP=RY2=YE%GDeL#ktt^&xG?7XCzUcBcmE~UZXFOOktHJE% zjI~M|=D(TlVIpt((oWrF(b>bx7jz1<{1u!WQS#tMyl_^coc3E@yU6w_1-$-?qB6`X z)-5zNn=do(RBE|d>aXUDEaeYwJ~!;^W?DawbL-bqVV3>d5@#{JZZ}q#dv>F^miX}m zrrFi+#NX>4oVM5|Y`)(dq3f?$T4a7^|E|5b?AM*2{xcLly>qKmO5($pZ+6T# z8%|!T&a+vx(7NRp^F*I*$w_|qT&m8nr%u@1ELX7VVRm}i686b&IrVr#t>)^rr34B0 zl$ie6Gs$o1j}G-qmi_J%l0Gpg_1&Bmzv7$!{WI3Zzn+}9xy~%Ys6^+AOm@+u3G-*D z3Vyt{Y(={BDb*$IPK#!y7|*@@^IXu|<=ia%*C(e*FBhNYmn&3WJZIlCnJ@b#Oag=F zN^De(4s*<9nOX6?(9oH4Q9#aNm~NkH|^KRR+_RvQAq4RPu1s)rpY> zCk}Y3Z8_b&I^nD7+Ok7-ib?loaL(shQ@1y9$83c|LWig58(3cX>fMEivU~SlH({iD~TLcM5H;Te>yeMZwDbk<_X?-KC<6^7jt*$mV#?pTTkV zpghadEj}B!rHQ38OzgdR<){mLiK2>Bjg^XS)X89y1P^0j7~B|7)_1V79D%?FHLeY$<{m-e2Sk++Hz1*&WW-FNtK&d+MjoPDXJ zlYiD9mHZV&5+0teoS||m+4F^7sb$~v-RH5(_MpP+bv+C!X79b27FzZ!Oxu0Vl7G`* zb=Rwm8|PoNV7sg+q4-_y@9&zY-}Y@1pFVl|Iqg?2o3=|{b-U^tdU(OX1q)p}f>$uC ze4n{(iFRN0uJkZnGe@bMC3II$zqR#ywey^b9*4+CAXASv$3gVUvZLYnE8#hcuJ=2 z;m-nGtTQ5h%$RN0o~~cG@?(XQB&3 z8;A7ab7Ha_7lmhS_L5o5*Eg+4Bk5e1{oI1S&8t|?p44PXpSCM*npBdX#r-AEJ3r=D zowT02^iXlg%7^p3Sh(Y_O|kgQ6J{CJvuA&3Y?pCnNV)A5&7T&Nv)rF>y!M>+PdcY{ zPWXfKXHU#}^ZQ-Q!`I)gPWE2AJJfV)q>gZ3WA5_fA-QWB5{|siF3Ne?%rDoqe!BCX zLtgVbGR2`7hD^{i12_8>Vd|vv` zom=v6i3^`<+S|=JYo0v&^FC4W`7&Ln8A>~UJvw0$=5XG4zwN|Hvln#soO*NZMqGTL zZ=LZ(_2+Zfe2g`z*lIBK^K^BY8$UX{6^x#Kn%(itea5$)D^7X4bTQ~XlnygLWofRo zg+(sHd$w+?&9j-?b2^za`~G}#66W&I!lk3$aow$@WnFr=LGSZww7E8sk{ftXLQ9(BX8TRU2`C2VZxcE z*7?z!(iP6K@;a*=FA?`rX@7s3f9es=rbQ=%^S0LfJ~ul}_<_Nttq<<+TWx+wgtzBy zPrm7;$18q@G<982@ll!S{${z?+?d;CFWzkDU%BDNu@l$wxO`6MCTSdcn4h?^ck=cv zeK$6C)Et%GaOz9N^E(F&Dqpdko|%3`aN^;E3@h}*!oJn!U6buLS88f|dFixf=K`r2 z%>l12CiDx0?#g}fjhBU6Eq~wh!bw7f_xKEE%$`_tzC$|dMZ;Y2`7?K!Ta-Ka ze3tDYpM}5HegC(D>wf;s8^70EE7pH!d0=>Y^7PUh|%f4NHTKmkSYRxqH$Nb_tmjjGHS6xuKw|i^dvQ_UUcJYajdJ@0&iJ1zTJX8_ZceOx#_ZjJwHZMz@07Kz z408V;J7MuQ;>^184Pi69{QLHtKF9W}GwRC^XEvIW}cuvuUBc z*SDKqtd)9&6&I4{&CS0MI%6`w*mNJ889v7gIb4eZm{*nclv~`f;Z}aHxc2C()jytW z-n23FQ>5(FJE2!2Sk6zH_h6MtyP8Es$zI!ox#FuEQUtpz%~cC$@qY1Vo?N?QLC+-7 z)iw^Q8`qkh5?eNr_0x~nQ{ANh-;j1qx%}^DU~sHYxcrFs zzDp|J3s;p~->4Qe+wSNRAwGd+#z*uc|M(P7)DL46_#xJK_-(b-?m~}BgQMQp*}Q-C z$sWBFm|>zdHzLp|r@hqZ({Yx4Papd2;%Mv=QnOsVmgl`sl)pzxwa3p8m+rL-S7ltv zU)7_xmjCPW$&&4MYg<|Po^3O@|5{?{wMv83|9_7B$#`-5xZTmu1y>#lbLM^O{aJUI zg}d80obB0-z>l+(`xGXY*vFr`$G~}}XwBy{jE|VUE_Ra z|5t&(Zvs1)Uo-8C@O~3B<23KzXK~LTa~|7Ja8M}mkkUkZ$s;^H9&=SIz6xa~-}uZ^ zvhY_ed;K3F^R3a7xBuLFQ>{?rSzK?;-mg)g_8${9eiAfOA-QjE*>~L{_3olGhgbD} zS`s^#d*iFEIUSWt3=9t*ezbmB(v7xbk$X!*)Yq2%v_BBJXxTyQZHu<8jX!lyO4Q#{ zgnRYOHI_FjPQFatwt8aGYfiVf8@F8l`!)I7-hUR#|LX+qZ7x0a-G0wQC#Lz<(cdq; z?VQyfEM2(xpvsT$M>a6UUlI&@uNSQ6^6=`i>s2gM%|lmIB^_I@;dD=Q(sGaKKR|QL zFJ=nfkN24$rIz%di78{{rTJ~DKy#gJifB_QPz}0HNwvN?S>Lv zUNNsSp573QU6q}*Ytc0EM|I0WZr^Iz%q5&&7uK=7_oiv$zRpgsuTz)*J-7amTYu|| zU8P$EUfujI?e^U1;xe}H%}QF||9LL`K36Z#?6zL>?by)Shqtgki=Nsrmu1hYzQ;$7 z80+Y-xpU}u_MsPLQw)~B=3sHVC~#`S+ehc0{}#S@aQ=)Rm+ptG{ppi`_`~0gYwa5& zb&p0j{=7Irsyu0S)XZ(qzF$A2aeZR}YtUw$98JG(w#e+)AMt!-np@5%yW3qW^8UaecL|iIZxwm z8mM!hbP@L2S97L+N~E}HRp66`8GChBM`cHT@IIn3t-0dKC*g=|YHLOMf806|`DB~m z*8UZN8-4_C3p(AXx%Z8X*1EX0YEuPgnU?&TU9sm|-bb0Hy<(anpYCm~Wm1f~vqk6e zL^I*Q&CirS|HzWLo-%Qg+oIP~n!jZ~I}~@}-24^&2X7s!nrpM%JgIKsxlQ{owx8mv z-`qX5@Uvl8gL?I=+sf0foPJvM{7lr<65Y2t+?F?kpEm!W;jrG`Z&m&O|LIdD_&#ZS zEIaI7>^ZZl=SQ7D==Itj#+sjJ1Z0GO}W-v1t}d%XH8z% zIghh>s+*{CFN4HuuZ4|wdKz+U;W+3me*jR60gt>NvK zzp4)(d1!2~`3}>%M5EugWoP|8@%)zG$rRON(R)G|6xs?{W++M#(hf#Ws?B~8j8PC4m zGac?!xz2n0=xj!r#Qy17n@${EW^lC6v{O%h&hs5S&o^l+#h*!;xaSP3`=ZdCO|joT zO=8V=lGE8a#WAs2wdQ!A6Vq#%PC3h3)47LtuX9*#TE99=usEwS*7)S?=zyD@Cl~(Q zedKDT&sn9blg<36x1G8caVa5Gbe7!~x%H-s5qG=AM0iaUvsX>l{Nj~*%4=~ivC+9mcenSwQ?&IKKmcZN~^6g`+QISYoW%9gyfSmN^{OI z$_Q2R3))oHpSF?gdUCVPTI9*LHg5YIsp{jB=l}b8%LL7R+RLi<;d`6qW$WVi{mbgV zXt4dcce=l)yU&&Nw||8$R)`1bhn9p}C`A^WG6mp@$d!R*?M_q@i@v+`M=xjVn_eQlGNA2VZb zVcO=qx6K~88)xl$6?1Uqnu{e@3*9EqQ+d;K+vMBCcaMy0N-8!kecATO_sm! zB}FoBJ?B<~Q+K}fC2lZ(aJo3ycg595NkT{NBx%k4ez@`ogYyUX|4&1HJ>C-Gc7D_A ztT!_Rntxt%nzCz|N_A0HU)ZU*-%piPtQK^Z7@ytP>CyDKNz(H*V!AMkM=!YDBZPD`oyG3XB}ns8?&EL zowib@Y)NRQ*SaqmKZ8T(d1^;2e!hl_`G>1d@v3JPPUXip^=W*bIj79V$e8)?)#akn zRa##is}`@i&GtC!ig&Nb^>Y_18UsDP`TKMntIE!LEo=JBIZ(Lss+)hfMeCjd`I=Kt zX6#(yIrUw5#NU@TYYmL^B^l4H`w&pIL#*v(Sj8U3dn)FQe(p_DUz}9;1~%<*@jrfD zPwdpgPm1cB+V!6;&Rw-L{Wyc@ywx8Lp0HawBl24Evj+Xmr-Xbe&$mZUt2X_gp!xR0 zov$oSPyIjCef_iXdBU{a9k$!26{PJ=oW5(t@l~yN;=gms-;#3K_NwB^xnLj3mfczN zA57cSow`Bd-O486H~gm$%n58DO~+=eUe*8 z!rWpnrt-|~R;=%$N+m*)Su}ZKw!2tFC^-TTkCExpzkW)RnzjdSa20VK0T> z{9HHVMABlf`77p~;){P?V!(20(!tl#6LhT`RW65LQMQr|Z|GuPS{Z$=F4oJi=2cbr zf%j`JI(=!|*}SMRQLy*&I=dUnkwObjN1Jw~&7H3P_0BoBvvN~SPW$nRZ1~H#HP>I{ z?uO-oDg0vVe_eRjHFKe7Ta!YE zin;|p$6MBN`mI>;@X5_$*S~8*)GaR=B|hU5jo&-_+lIh%IyWw@shhbeXSR&ikKcCD zOXlqIUA>{J@nKuK)DG^=X#w+DOP2}N=XY!tUTCz(ughlooie{O##8-&PBlJXc;E0W zt8Rm(QT{?MH(up?8CRr@f{gS`t8|a)NfZQhZEr4bS^mE5;KZ}{SSIDH?KfGy;cBm2 zbap9dZ=oP)cW2#%l($pr_U|nf@BgQ#EAVD{uOQ0_#(AOwA^%u3ZthyOkjdiJ{|jq( zAI$!6N}03i?)Pg)mikQj$F=;ksLH)lVs84O%3MnOHyReNy%VW>xIS^2OsCXw{xd4< z8qe0`ZQgPA&b8o)(F(+uu3w=smlczL}eE8dz0byJpl~&9W_J#~C&C8wcF0 zBGdhRQ#s@8N++|KBuP|2Hg;4EIU(+aL0GR^|O5g@2*yF)25Ww>~%&d-sUK%wzubk?S|-bkury zcvqX0a(}L&o7T&flG^1JW8z1n9m|Exxg%K15mUwxgM{whgA zyG8kUf$EAa?!n!RqUH1RXQZF#c)z;+he4wHnvh(Jgh!vmvfY^ub}fi4oy2hb?=h=c z@qwY8YkuGQZmF;T>eERVmD^R^#w&ZBL|*<=R_oYnYI1X1?dsQUtW}R|UL5{=c4F(F zF2Td}c=F;mZ>n?yxF^T78s&bKdcno|ru%@wi<=(h z`)00kPSlo zAN%Z|d~Z8`tUl4;bKE4LFm*=bAC8ZS`Zf3Kn%7q>oc?=m*Y@>~{vFYo*->U^sMTZ` zsCe1Ne#hLVO~$v4oM-5`3Pw&(spfw@DUJU^#{#X&Ic=xrEsgwL{ZH=t%E}4zBCPM2 zw>*{W|MlpF^0aN$p{I5oJk5VIV2W>)dC^&Q)^-bQ*)cA>;>uA^M zjVBFrxb0*Qi_I|h_mE|grF8CrBw`{W&u)mLx-P1d?NVdug#kKH*$SGhVXExXWLtd_C(Lhs7b^GX(K zY-Nh=6_Qf}m+-U;H_zjfjoEPKf2-#gU%8w^yOtH6E!ku?;q-Cu<-Yw(?#MsbC%$E} zposD%;U@vRCRbUCE##fN?o(r675|0n&rayJ#pjvITzVPKr|ii;$B*aSZmAj8M^|og zMl5GfJ9Ef( zm&Rv>KMt2a25ruK(7eqse6O^b^n(+(&o)~gJRWrFxALSz8A_U~ul{lSbS|_uK<stLnwk0xxw^ARN zyqk1#B}=UIp<~zD61N?`>Gbo5+ehqTQHy|h|Bua6x$sYw6OqsWG>- zeV(*(&NkS*m{3ZB(%#^^;9kL z5sF)!$3FG4$FZ$4Ia)@tVb8O3rzN1}s|zguA?-!)4` zaFNyNca|nQ^S*WU*Bvv7sMuw8RbT32sT#ku$Wm?k#$Mm9I-G13ApIfY1CEi-SVLn#r z_v*6WiNM!YQ9?Z?JWnP2W4?tSP&};Rf4;a{<9uj4$8yOWCD%;WDK@tg=4a}*m^jXU z=GiB<=)UK8vZ7?(#R_T8a%;qIqw)Lv$a`xXnR;rz`?C+lPkjE% z@5V5H)t{%gE-Ln@^cvuy<~^=lS{u->W(^b~?p# zw>POHeu5v5*NW!p6N-~Wf?Jy(JMnL{k*=Dj%k#s$ zhw)%^_{Q@8r^Hzo%$0f1Z6J2!nOCX!_D5%zepF*QTDV8eX~~a&RqCRh%TwlANIkoD z?t{wq=pT&y_ogYH5qZGhbg@fZ-EXhx?!ZT>s)Z-GzE&jUbWRKpo8z|4R>j-xQ+Bh8 z0-Kcm{GKDu_7cwzJI{W;*iTz&yCTO4-OWLM(t){&gBgpw+_ylS`oPVs_LH)+6?8DtxH-0J&10EuqIyw; z;bz6{RVq?1*#)NBA7*r0wa7`Vyu2+ywkIw8Pt~lcCIU}HZP(ZYN=|g08Z{+kso=dX z?r5%4g};M7%&BtUxANTe7?CqK%tG5kndg5HJt(og4vz>7EEK2lgwn!o>>9z*@%1NjrfxLwva1+LV){IMd!t0{i!?X}mhTmN6M zdP4Rik!6SPi+^}~dg{}(GY{2mUOs)^@6R$tGW@oZ^5k7QjHfR7Ur2SGJ$2>jzC}*S zVQC(mk!~5Qoh;|BS`%Y)xLcl^f3kc>B%jwpbB0~rljX}7D=Mk4|2W;}@dj15-z-yN zZ=C#aG31V3+}?`+S9qQEH2wdrOH#kPG(qb3?!u78o$;oZ1lq)Wwyx;#nV=l;ds$-e zr1tV@g;8R8n{8X}$1|#j{?Oi2bjit&Mul`6 zl^kE+YqzUnvU|bttR3Fwzc;_zvO6W?(w&0Dh#P|ISEV#dnK8$G41IOmx+*2~?LVoi zDVy7c?X%Z>T%~C!Z8rB$=*15O^Y3}`EQ;5eyn};dT#J1z@5@Jg-1qwX zu@?teU$d0i))#jh)vsTE?d;D#zEfXzmTz!8uXgsx>PwCnL(b2XRWg45zG$Xy><>Go zjP_MF372`+oZ68(qkR5y$q3`K8#CFi`E+ZaIWQ|#?IaJ6#+d`Ghk4elYDzHPkallf zbeh8Z#s0?&xa3cljL6=jbM@rvYnOS}gs+IyIKJwU?r9#D z)zc&+jG52pvV}>eT;^HhsdY0g!B;cvj4jePm61M(TGTyMt>!=a)>yX_B%&R~B zxOwUD-cM(Fc!Js`Gb&~_zGj@!7+PIDyK(ESEtkC-R^OQ|$+1b-cthJs4dV^3+A9C7 zSj1<>yn2(cp0R+@?lT8wy}YqmGD0}kEs>2)A}yg*D`nO7_Q+It{; z*ZjT98eZq8DX{H6bKusY56zMtQ}T98p2*o{#H_m_k!{~;!w~sHrRByGuCG`oc_ZY; z)g_s!QDr8~vtKjay zGPX))RIIdnG3hRkiA`vt$p_AM$s1FuFQ+N|+IGf4Pmq~p zDqG}`Gcj({%Al&r{i0G$?F=2qbwd8UM4@|9%j>QY}r&Wt=l-m|wt+;M4x4&{t`?5_(8g&n{GctUZs@ z8Ok@)Q1{aE?|b7;tGKEZz50B8m9J#T7M;DD^Ol7Kvx$HCu%u=Fq8}?)7I(?cn(eMo zQY*N=tg>I|Y2z2Z$s$c^Ujt9_%%1t+&c$VlnICsm9uWOx>Xh>_zO{ABiRI2*S@)F6 z4hRKRIDJsF4G~x+a&Z&)Ev9#KdM!eam9wR5g>5Qp-xXFgt*lzR#LzkGGHA2=>y;8+rGSS-uc-GGE+t&Ic$0e|J#*U!^Jdj-T6!zF zM<=A@)HLszmr6EjiBI?8E|7C)SGrj6{k7y#^%?%R-Y$0OUZ?i^x5wcF0e)Zk44%-cl+g9IC#?<~ay;pYfipmRZetYIQ z$(${I8Go!YF58rC>t7{n7kl;jX5+W3^KWK;KHL7zc}076b2;1N@27kmKR@+i-7Mw) zET)((-d{^Wrq)``W~qjNRLq`t3*A3YHv9J{@z&0A#~bCFirb?r*#-Nx9a5C0Fg%j( zIHNXY<2nOdLj{*YTLJwio0zA6t1^GO%dh^x> zoSPyj_MCmEb={%|YL*X=S7>_eH%r~J!s4D#QU&MbNrlsNif%WzoK-yR%gDEV`I!e( zb$)%D)bb;8ySl|sfsR9#54W4vyU%{x{PM1!SKa;{l`;L{dQ6Zt4dBD zoO}A|8-eh&s$C8>{zr1u;v(PHnS8pI_oaNB^!<4q&phqoIgg|(-zlFz%l@Rf7IRnz z(_f`oZ={)?>7?J;thy`bd|FuB%91N{W-<57-kEZth|TudXVq>og_cjRimSXb`n}EG z);PGW6+7~+^yHeWHAnvJOSvA@Bj33rWo1^A-JErsQZ7on?({u!cE$Pk70$uyHrVR3 z7F?E{{wDgICENSBO$D6}?J19ssq9X9vd**O_GY?s#%s%|=AY)a>!iMYeP5;5@8HAp>apB=Qhq#YT|H5JLk;7i zJ2PWza^@6zP0x)__;r+BDBU3VV4P7M??hqcv+}8bUY%Xu>HSRq_Oi0wDgT&0YJ6K= z6%%Qs_xt+aWdfh9It1s0nU~KwaN(rPhdGZueC;pE3#cmf_jR5;(|F>^*Cf4Dnpd8= zTISu{i^;J^M?|9^S)?FJL#VIoj?12g51QJQ=~$L6l{&%sw#dYe7>;f>DlR`^CL>@5}ze7 z-mC31elzGsa&2sys<@_5#ho3}pCmUilzDByfid&w>jRq3A|SGZK0Po8KBoUGq9g|p-% zpGL^pj^kTZHdO!EwqNnwu4T@z;{^I|%*mGIZ<;2*E+o{DFXrX z#M1_h%qNo)nHmE`d4tx3HQcUrn7gAr=vl>X@%iuBR5vTHzq7?w_omk-&z-vb8CRGB z9?mleP4#?xs=DnVM`-iI(?=KHIXE*xRGp{YWC`D=K(;vVi*6aVhbvf>IBXm`)}?&z zZ;qV9FRW5J%ZPox*sjBMjOJVU)XN>8+_8~Pn^Kwn>f^?b-w#e;Z;HxdF$i*6P~gR! z%F$Pp^=%b_1T>oAk(~Df96MXQ*nZ28OTsF0Ho?OEqES!GZ>DYqM z?06w|9k;h03I^(tzg~5nh?0x+bh9|Xvo|^XBA-Oz(>bql$^%|q;Z3}}(1)W-p_TFS z?l-|(m$a|S*T{3eblKos=DipHSEYZAH2=oi|hUah~90H#>>9kyZ^x^LRv6 zmGAq4Emp#C((r>@veem^J&4MSxVrKma>V2&e+{Iwhx+BdnCFu z&NwanvHm^xJg=P31s)SyeUGg-{!#tfMp5~OH`~*%Jd2IbSTwU93AbhL*;&JWsQ9bL zzX{j*)A?s^Us~~2VUlQl$c?x&ynL-ImiXPz^V|0Sh{-ImI|bSAs+?nIJn_@n>6LfZ zkI`9mvCoE8m!kwHpHN!-&OgnkNZk39K?c`Jy&})`25<6as-%DPi1JZ=7%gCNilH*} z^UJJhmaat?bbEJtWLDhMk}p3fpuKONdCTdRd4g=WoqmYwC_R2}G1zhHoElly9<_nMH85?SU-AsZ(MlIZB_$SjYFP2p0C8 z{I;xnr*uX7cfPehCOx!U9jxX)V}J0@gX!%|fm5w3dILhveA?sE`1<^96C>;Vn9DxP zjaTk>;rJfdQdKJ#s37t1YP{e3yp8T}RL?&?ey!0p>|Mp{*SR6gdaf5XyY>A_PAuQ^ zJ@W5HzP8@k?>n5#)pko|yUvm7bRBTy2*S{WPJ^*;oFQdOkK{vNwEc z&h|m=jbc|+e!PBVO52pU%MK!`wwG-Zu3ne_QKPYF`pH{%0c$3IYil&|*ibE&rMd2q z=ADz0>o3;&WB{620w`K#mk z_21hr?`)ZOMj&F{;(#@#_opcvoMHX*Z&zK)k>dvS{D18qp8Ve^FCKA8?C-jnis7R3 zxi)%rypMNDKFq1CwPN+*4}vur9}>%-d`<{UFS_)-H9*b1C!J6Fz43{J4_{AB;y%;3 z|5lqIYnp^%>byq`U+reB=>0fl-+ASE#XZmUtD>2nweMMfD*L%u1aqv0&)26`hvb<5 z?R#)!ovuE|m!{kE=aThUN@t|9VGaFg>tZZXeE4p z&hzzqCG&mTYacI(D4rFE_AgKHkYFtT^Y_ET2J3_c`=>6nczEbv|Nj5>Aqn%hKH0Nx zL%9LxV&ikn20V;9eC(S!&d3HV=e6%V>23P&hf8>2M&AM3yPFoI98I(B^qeOqY$x#h z*!%OV4hnNjtI@HF5O4ciVc;TYovYGEsr2NT-4GIp3nFT{pVV z>+LV`7RZ?LxY6l?j4SgR>BDziW)>^&m@KjMQeeAK{>j7KT7F7A2an9(_}|>(=h|aS z-iB+uZ(cdm$0ngB?CHjd3@2hk#H8*f-`IF(U9ovc!oAp1+WVcCg{aAi?#o2(wY0i0Vx8$;4mh756DI!o%uw2BOJ%~l9MP}JT3C~OO ze=#YwJgrPzpp+q|CC$cSRsOl7!hJiRTue?>%G~^^zUoXyEdo^k8rvncXHeO2lnYw$4xW2@!$ey3FX~74dy<}P0 z?&>iq_Sx))1w8%2_r5Tg&yr1F<#yrR@*N`PJa6LDIXn)&-qYlJ?P{!+TH|DfOA?#E zY@hqy;Lo3`|G(Z(7tORezFm}Yr*Zy_EdqB8y{&`i9ORxIWpt8d{o+D*maWH|Lgs6j zRX1&LzISj|HRB{T|JV`TvX)z97<$&;{3`nP&W-E&*Q-`+ zda0^&FdNNRuts-r~L2AbyX z3)#~Ci%Z~|ktC1dWP6i~e+%17dF9w!t2cb%Ym--Tjr}xNOgg$ZGH|Kc_Xigjc{A{^ zXBqWhC~N%e_v>8#ool^$74sgQKPV%Zp*roGh0+DDE};z^Uw)h3o^({OvCi<8 zdbdOI>0&vib1`D7za}O>4~n@`*^+D2&(Y$yx12Gy(|jKc}y30of$Ly zxOa**JbO~Ohtr`VvwPKbmhG%^Tn@%>{M;FeLa*#**b?IUn!_RDY>Yl<#?#qf4jaw0 z@)D@qVV@*FtuAlF()kBkzBDW9q`kPO`}vgjuY+vIEodvVHq%M}T77ulUxb#|u8@A7Bo9oW2>>Os-{0 zzR7N2uI?f)!{=%scQZXNEW&=%`H-o*Ce&7xmhJ1d+hHkmr~i#{=&9H}=dRgy`O&41Za%V}&-_QlP3z;Q+KgYntBdE8Nlxj$he$q}7M%l%3d7 zg_6HZHn=LuB?>%!KfTIqLbi@6>rS5L87_H~47RwQeYj(1rs9O3x|y0s*-oCipR`b= zQR4>3hH7JxY@UcW>nsmg*V$LC3I0+hQfl-3;6t^)HFpgoCWx{uF}<`$=f%hE>-MtQ zyuPc!<1_DRLS6fbFiCD%lZM$3*Uf&cwOVD#kG$ZtX}{79S*2gk|8-fl`|TG#L%%r= zb*vtf4>s=mx^L~{lS~rU^0kewdS%;^)@WGPhuoZ$ zy;}8+ReT38s=R)iHBaqK?(zpS_ix+OCj7CsJo&ifyruld+g5YG&Q+CRc9)zf#I&pY zzWD3%DQ|hL?Pq;rxI3*%qvmB>Wu=dwJxS3! z4D!=*HeWlt)1Y1YPW_Pub;n(1Nq^Y7>}?YJfiIOi7!Rzu=C|nUpG`%{Y!Tf85?>uA zHeNo%u=?iV73ygL7w_i1In1+a_kC7#iw}wHjh25LoSz)#{~&hERc_XS$|;BW7*0tY zynRqMsmn2D{;Rl0ZV5|EW*^~WXlKfQ(!SvLC>S(nO^+3zeg;m{r7Z*^k%J;_&Wtn8K!nXqanzk9_U!ISMbW;pk0{rhVE z?844$nPfee0cQXEgfr?O-d2@?s-i2R(t-DuD&|k3AyFM zs~^m(a6PKoVfdNpS>b)R4_(=do5T0y|Gj^_@!SF%IL4buMX3XJwMYzO}D8UwuN4g5U9~e{Oh#h!|TsBPNkWb%WDkga(VG^ z#kM!)?=crRukWuba6jJrtOWDM5GHLmlOG-BcFe+;f9(^Pwc~jA`>Nbr|uQ$oQ6OH)(c`B ztArJnt*lac&iI6Nt~~$L6@44oe^iNG{@h?{F z-NN*5qQLzcPA0bA2Q2kF%~&3;l+c-6)|)pCf44upZO;9%R^Y#eR4#TNSjpQIP_u!V=Z?^igyin0&;K$+s5(S&O}7#^QsUjd z+OXfV|L~06AtKF_8)Yw8p9olfa{hGT-nL&y-zWvkMzQ^sDOXu}OQpGBT94^WHK}(y zgr;u3HA^orz~ykmCwKTp;38I!IhiZTVS zw^|b|_j@UqwG6L{g5iQ$)_Z?s8uxLYPjG4#@)LD8S$S%;{m}(xY@MubD^$|1IhD@6 zaj@0t#m~#7X6DZiT?>t5vcF}$wT|64muaCx%{t?6jz_H}RBvtV*J7C{`RXY9jaccj zH}PGJ+8j)Ojh=25J(^;4_^XtE@2cYlI_p1Ad{%sV>8e+KhZOdSw!f=X(s!IWvHtYd z_e<{NycJC-U)bL4P|Z=U3WQ_Klb^Hr4^th%@4lqE%GWpZqo{Jrey zI_0(r^{tIk6DuQsf7TAsteK#)>F8tEzrGt9V?Vao#LsR0pzjf?!o+CgaV%D7@!X{9 zz`sEWcdD=;b-^D^h0R^@*5HYM-g zuZo7#TONmq$L}nD(cL7kk=XF$K|tlBjvoFGF{`*ID%))il5qHADy^P&=cCw~wNGx8 z>`0Q>ztWmd+%DN=wnjtMo*ml`1(i=bKC?E})u=|=eC>=V<1W*QR}UOKn{nQ$i09+Y z@E3(A-pXHpwX{CP`R%j+YwI7>|2zL){@?q0p=Xtj8~%oNn(e>7MSR+c^l3tR3#&Z- zeRoewmU^P*V(2$eXLh~p_E1c9&+i9^?y%3-`B^7#V<69*`9U{1 z`6Z9gufTkLiRd+e_Rl0tA6ux$-AZUKFcP2c(d!Nyl%jnwKWHI818q~FH~Q5RPMi6aqdOQ=dwpn zuACvHcDUv9x^w-LTR0!QYuf(mM0fg&>eB0Mx3d}2I#MK;SI_#y!Mb|8_$5QR@9r59 z#{{D9UYZflQsHX7;hE!&kkhwMC|*f4DXaS6V6*?;_kXw7GA_?{eS0t~h`sn4OJvj; z&3{Kqrfn>`zUyVI*sDV#$D;2TMxLp3w<}#HI=}hFrpDa5os(~<^yH*9@RaMUTF5=4 zG=|0QDwB_~@GHCP#R8AQ#g()_9*{WKJWu|^{iR|xj$&?GWS4jfls+lsx*_Z*TzvD> zmrozh-&VfPq#C@|-)GI2+y&VmFQ1-v_qwUUjR^JN1$%;5=B-paV;U4bE^Ho){s=xJCHc!#7yJ)g&dNy}U_LIaPC(kFC zMA}>s5k32vb%*tCtIuk?CU6I6tll zY1^6Ddfd|1D)G9*{2BLu?y|J8X35+yDRqD9qu5E_7fjPnsb8wnZIlQv3bfu~{n^gF zt9H+;wVy39oljq_71jk-Ru-OM~4&As;v-~7*$&R04dWIgbR z(ITli-?d)#z}{aw4D$9}us^&v{e{L7W-G7RP076X%iU(Y7w4Jrt@WY7hR}~J8+amu zYn+M}RRum<)|PsS_eJ^TS^RDNPL~!gk5IeTuyx60`-{S%8&jtA)?C@{CNTH$Q-jr^ zs~0a~Q1My(vg+wN!Am`SB{};Y1yfgkowkZ4*e!9w+?-IAniI^PdV*{bjqILVOI7`N zwoXZIX;&4glTJM#khDYQJNuR29!-MH8pmh8Tyrr*$L0K{TW_^CXdk&9TG`>C8$4a0 z@8!gOiTmM1hbtM25zyz3FK@X50uH#b{4$ImaTzWw@m zo7JN0D@DGa&-9g-&!K)DIyCSdRG=pv>7%X7bW6HeF&2#C~p2R8TeT;X` z^A_H3kTvQ4a6(;BH)@)wZ<1bR)y#Q&Law|O>`)Ip^}W-5j#FP*a-{Bk*^=ptRR3^J znku(w1#gJg$%!gUb26QCLtm$TSG}@n7VEWGYU{yy8+;-+ozJlJ#*LH$u z=F`AFhtg2Zqc_V}S^C_J5xREju*$4;{g?JR`CD~3E&J(vro_r;?Y>55MwK0gd-P8} zRIaWJP4E73_AI~POU)&1F;{necC65}(U=>!p*G#u*?rC2%DlMXdB0yib-8}T;>*oV zpKovN`1bYcNAU+?mjYKi+a|Socj+91e^V|tf809Lt5HWt@S@GaejWA;hd&@{cBM-h^t*vc)`26RY3WsimMHaU+Q~b16bqjOPeD>1qe5={h z-n9YI?yI%#$!;-nn%-rX%1QvN5+2e8b(IeY+ z?sNQ|B$I{mF5bKBZK$$((t-R#Z)6S~QTSx4_%1qy$L4~@d?Duta+|oe#w`j?vNMxC z5j>+>G5Nxt*qLuv*T$~WE&o?}B=?T8Xxr(~uaoE9zNuonkoBxy|FrJkd-lgITwdMy zJj&N~`R;h(;*WD|=W2g#Jh*D=7*Iz0o?- z)u+DyIQm8Nje2(gzlGub>;0#4rZ8|;cQ3M(j56g+3pZh8WpNSl51@`+3dJZM@lX+gc8E{jO}-{`ql($G^Ui2T6qzzi!EXu1!3*X>NS%q36FH z?&~*a>%MP3{wi+9DTPJ1AFzKm4B+_wK{@XD--Nu+bAmeU4X+pOU)=WeLxSxk`{SNU ztKM({T@e&iMPdYI=D~HvgBb zz@Vd+)7FGe2u$jm5p_4tt{HGRDbL0GL0>@Cp4QqdoP|jGI#lA zy;7%@;^y1dExqx!%H`3NsWSx2^W>(!efhWRlKQ=lmrs5@OX6($ZWtml`RX@s=NXkx z*4b-(Fm7M^=*aC|$yR)2vf?{+m$%%sT&&>!w#-fN%chz)Tb&Q5icgDnOg>q=G<((c z$kSc(s_c8M7QTJ3;Me~eS)RJkuW`4^B-ozcnV54oQQOwSJtbSr^{|_4?bBZ-rw;`g zUHe-8l9xaImR4nu{)#JHQ}?Wuw0N!G)%|tF!KGph z-aPa9&WXL6{NzLO+bV%C6OS-|*zk5uYT@F&%S%~m>}IWvIH#28{`263W!(u=b(hUP z7pi3TSES^L?$ln1PhTEd9A>w3@_V{{li&K5s(XSV{0kp*DA{^*=d%A|eypUyVW46W zn#6X|M0`(3<(tB~1EFHDaXJhQl$%emBxRje^>qT(wv=W8qGU0IR5^NGf)W9GWK*H=2v{BfxD z<)zYy@~n@HMXVvKf;R5G`XzJi6?})bgkMfOR21>*s50xcZI8locLm+hPLL{H z#j-sthG$0d1@pU8?s`k;tgSqLb*1ov)t?!eFR}KV;k>dVDy-&H&;`!_a~`vY7|mMJ zDpNV-$I)v`*m{r19eU4Dn0d2prdH_2*0>;1+eL(xsw_X zh$yMqZ_#jEp?Po8wZ^0Wj%!x!Kd_IDKj7{gv1#FjOJAJ5x@2j~(*DIKblDTvK0Q5Y z#icjVSv*b_1<^dGKP)`-YqsK&4b42;Zru#qe(9&{wKZv1ZpHt)v@^ChcA0zB28|_( z4l7zqm%99YrP3`jefy>#D!LIp@s@(8B#L)E_WxwPYt^N9HSD1U58DK`;MX-)dXG z)MIBK$7qP0yUrU@J?q59lM@|!+xEw*^=O3k@-M&Y9J^%G<$sRAatLoT?hd$LLCh`WVnd%nt97s1DK_kn5KgiEjOd{(V@+ge_2o4RF|mr&7XmRALN zvzF?}|LTm5ktx!^>kK}>(c~}FF~~T4@1iXe>%o`j!ZQCqx+i>L zUdE>*Gg_vVNBYgud2gp?nzp0HQ!Q{#?FsKWB^KPR+snGt&M#iI;%~%biBHzWrq=PA z@n+GI{HK3k)X;1_Avt%_B|8J}bLGGPtaC5BvEiWqosT{5AG~w17dq#-CHbfB+3vj> zCoUwOdUQ#9mB|6?eJ<-K?OmreCCI$_%*)QWw-anEuZ85+t-iqaK=06MMXjS^OSA)p zm~wV$Z;zV#gwN{E+h20OcJI=;G}GOu?B>1{e+Ta~l@smva-VzXpMEWTvd;;}Liq#! z5td?{-8W!}HAHtlg$3*;1fC*IN!pto}Q`CCD5Md7n#5;hf|vgoCLM4x{0mq@qB`QkRKq;#v9 z%co0KM{iYJcU>RU;#S(=@pP^2r8P(Hx+|nysGi<9argFm*B$YlToaF3xCc!8Fkf?J zGsA(%+-aiG<2l0KD{)kl40gUKvcF=N%A8Qo%k-@G{cYSFtrFDK|aPJi|9xSrXmmkMvEFD~l% zv$#xh@BBBq3*PN{zx%}9e>ZN{PrSa8T}Vatc*IKi%OQ%^5zHt3mj68W3!XZaT;HP34?#F5j#Qr$T{kv$i*N_P^LZS!DTSm0c?|Z8P#W$2dmT-rme| zFuCJf&`Eb?^=*69pZZJ^UbZB_21p6UbEGw2yvX78`}$B~(~-qfX7I1}kXUKB+NFbUw&L-Z zO22*n&iT0CQqQ>k;N;nr7S3~`tS*!2c-mp3Wb*#$jX$r& zl>e)R{jc%3H-FO4-EaPB-t`vP_~HNbst@ZNJPuaGNFCcP^l9O;J*y4FO61nhI_E3? z%RBg&`K&1-eA!9nu5Wxpt1mxgc=mVEtG(IH@3|iDcKW%p=-<+*`!d#+Z@uRId)4=S zD~|U2pZ%$S_gC!qx~u2p&0FVjrmmj1d&}%Id?tIPwr$@Z=U>p0lvsL8Oz4BI!+{wR zlcTPN1zr}GZ047=)TsP+spDhdvPOru$sW_XkFK@MVcXKGys+Lvszts0qQ>#7cW*lF z+MZk~rg=!as^jC`LS37i+BK=qBXqtcK9keGAD+AO3V&$nMgEfgi}cqWHgvc=+3$eJ z47WLgtn(f`@r_mACFt<2J5lKP!&hoD%2v%yhc=1L?%^w$q<8faOYn`tza@&hFI{}3 z9m4j>YKO0=%a`uOyWYNy*SWiY=ed(%r*H1?KbZMoPMD5g$!)2w4-2;c=+N78d*{M= zRhHi`zdk+D^YGuPOZT6?aA4N%P*blN+Y)Cp_-@}|9yZZ>=K72(fqtDNz3i2rGdKRt zo*5geRllid)`OE5wny4L-NLx!qxmk@sTm zEV_(m-PH|8D{rL<+`Y5GEM&^;M|GKEXA^ZpYizxC_8JinJO{dRT6@60!~=IsA7 z4foBS^54j6|E#6*^UGd`U*7gMT>sd6@!LNh`#-kaJKOyAulApRk2?JSak%Aw*8Td8 z|Np;KNbr1jy79xy#2wa(adSodB7$P?obLbl@Wl>mr+)=gZ_NB;ac_!v{^{BF%WkoJ zf46a`Wr^LDyU&+T`m@e?fA-D(3rF-_|14YiJ|}kH{+FN1bK_UatckCi$$a8Kh9Sr5 zBddKMUVZjqL*%2YS|9VaS8UJT6J>WVS9$%m$zPY3KE3)ciP?9bWX7X;?Yz(P9%ueM z%oYIt=eQlGy_`}yrZ#!JmJQyt(Fm->*=f{0*!N(gk zd8RjAWS`KwtyKJV)7vL}SBvg>?T9{(eBwIYq^4zOCWbx@{legQJhA;CkJ3JcPWA~~e%NJR zy&9--<)f2~$J=EQ*FJ|Pnwh_E=ex1^Y1%~B>YdSVl5G5~J~^jsQkkgCb4X_Liw;)r z-REZT$eJFKpOjp-&_H}?q{(3(mxg;0d-~ZX6;696;XSBEFYic$9GCab*YK=zubyfS8f3M%za?BEpPL6ig^m@GD zr)1G84bIQ$e>#*>MZ#HLx8(e^D_JeqTy}9M@9Fi2ToTOm7b$yXgsZx#Pk+JH-R1G& zR{NWb!`o#$-`cnBi_Ns(rwi_{S$S&H z{~x!1{C_7m;egz`=5qeSk1un6e7S_<$K~FK{*~peH9x%KVl~&#oA%+T&AW3m%=6El zo#`wz_iEysAJvDHzwC%{DsR8I-1+6vr(5pZ1cm;2e>cectu|RT`^)c=ygt{pCOD*2?=SGhgQJ4K(QS>3gej?>4V;LD4o$gSW_f5TJOBpRAS(fkDD6-iYEg>Mde%@CGF7G&b zQ;5rKalu)x1er!IojGbN_v}&0 zXe`;!QP6f#^QPjKH~Z&sy>!@@AFC#6wJ++8Wa@rDd z^^T>}4d4cAm%nY0ck(EEHO(nH<>2N!mQVch zC5}!zR%YY=wPD6C-3wGH2G@IUD`n1Wr(%%Aw@;)vxo_>ldHBGMt6~)91Jvu|HAe&5tzmrJf&T=S}Ni*0a~>D&o2*}-bMYU>)>V|{`+(~ELA-Ur@3WzFq&ciZh5o3AnUADh-F zpuX;v`0D8GwjDC3-X2uRjOLm0xAkS|owWLjmop0YSX_R3d*@z>EOwvN>95Uqutw>< zoOwomQG=7&MXTOEmyEAv{a;gCs#f!z_Q(=z)?M^v!KG;aygfSh5o@0=US#Zl>V{tb z%q!1@(u~CWDqa-4^!~o<@1fGR!bxd&!lG6!ES$b$R?(mBZjBdKtXnUx8$D&)tW|5| zgx#W#UtZg1^yc}AT}ihkd2{1?lCszr%{UUk66GJZv(0GRF54|1vhpQ&iWF_N&OP75 znZc5|_`TV(JoAa~ee06{Cfz!wSX6m%O5(Pw3)gLPuVb&7vbWuJ#pxxCEn0CG_{4U8 z5qYtU$MDS0=Jx%sJALbur{25oe&v&kYuy~17Ty=^CO;2-aa;60>G$>*0!R03F2CEc zqH!IAP*vwd8J2yC5rHgEOt-6_IJVpS#=)GUTjwZ>hOJJdTie^D*)gR0GRmyMo?a2ChPB2C5 z#Um+$=9SAHmMvmuE1h-uOV;ys4}>Lhb}IgzqiwX>PRF(++F$)<3ybdC3ARnqS*DLm zRkoCOioc1}c-fmMr>zvLcrQ0HWP90!g8>x@TA%p0>|9?^x!@-&|L09VPw+DClxJyA zTXS0F^wRy4p9(Rivo3Bq;<-}dL*E0DV`53oB3q}YetxlP5%-K`<~9k9s=rV1vdgBf z`nX*_L_gPM^AEczg5O)FEi90k z%q2AcOMm8hp(7J)*W`BQCv#6PwoNm6j@}Dbug^DkdZ%@za^>0&7fW2(gC8>6 z913!8EP$w4Kw7)(TF0dw$WG{i-p4JoEsmRFT_{|A8IUMEEnz3J9_BYl)m*bAJ*NI^uI55c5KPS&CW%PzKt zR$88THBD~XGDWwz%rA$NmRhLX70!3xpHlKrI`PF z`GbpA*S4QMw|=gxSjF*KO5UkTh3~lz{cG&oed@$aHK87phKKT36c+Nt9kBL&_-J)d zxone~<@PlTRK4X7TAlEA-L=zT+c(!0t4sepEqi>dfF-v2+d-8XU%!`4Iy2+n{qDaz zf7giK{n#BUD?j0^ezC&b&9Ofjt51_uqE{tey~q_CJ7BAPyxqb3ciVqiG zW4wBL<)LpK29v`sE>+$z^}v#UnXC0=-bKr~iY<;`m03P%y;7Gv*Mt>ii(w?URGSIw@5vle&B*di0qLk|H9VJGA}oqw;;4h{o>^bVLdMV=WN7`U#goF zZxc%8_TS^xXJW@*Yjof7BFCl|c|z55%OlT(3Urj8`dI4TF~L0FRpU|E+Zw6IIi1gn z4pvy{xN02pmzv^rBW&lnDJk1U6U{?5edMe1V-%0g{&==Ss)S*;Z1H(-nUpvEu72)^ z+a5|;O7gn~wHC(M^}5AdKFsOfU7zTlDPbtAJngCP*?(_Txc}wc{b0ADKIqeHVI!OH zr$zg!SPum{q%$3{2^aEB3%>j9hRCjkU*@mbYWio&uAo=1l}n6TD|mNA-LW%G+0_#K zlp}#fyUufqT|e`!p83!JzBh@Sr zQ)}M2AJKcKE$S(mq?wieN%>fsZ`3D&$NrkB!dcUHW^eF3si^09KEC?tis|AL6Aw&# zt^d~OHG9sOy(+_ zl}wo{{f|jZRdi?HhGbXAGQ$|r3b{V-`R%jsiF+^4zqLuB*vxM}bKtIBS2Y(LKC~^j zp3!>aleR#aX~hl<=DiCTR=oNqTXUSFG^3_cN@)M=c8R|DqQI?d!`5wQ-xbPmDITXGW0ewLW-3eszIo1n9>#M`&&8ukkqLZ*lZSmE}jH%bZVc9C%i; zS;^HUZ{_bcc1C%%Ugh@H)B6N(EXlb&acSa&Yjcef4CGo?NiHh15LWKYzNJ1z=h&-~ zsOP69TBR38cm3R=G%3Yn_QGtn&%K$s8nVGF_f(w>z4UwK!>yAuUfN{I$l4fWl?rBb z_5b)JR+-q_7voY-u}Uia#-ZUpW1O=B;!SX~tv6OxqT{dls_!-y zGc@OfT#}tux7l>LhfmDmc&l^MTNFK4J&4?(7i@G_p)Ggqxt|GJ=A}KAd$@1U#wR6Q z{9-Z3yUJNB`j0$&)^pXP%0aOvYl+&8>wD*~2s`%Xa>yRm?_ZhT2dDbXs1dz+Y@NcJ zttWQOVUly-nI^D0+w_7_yx*S{VcFFu1ZREvFg<5}i}6`CVeYlZm3Owx>6)#&aE4L) zVdm+N9SoYybGdXjt`*#t)jajG*+-8V@7I6*TYU2W*B|ly|JjeVn|*>Ty~!OSs*o1>r~Qdy9ypdXN!o(fW?ACOp-npdJ=s9>NF z1Qzg3P037j%CAs}RxnU7P%t(z)H5?MFfcGvFtV_OF=N3>o%8cbQu9iR6^!A!-HY-| z3y_=#u?;K=(gJdEu!4R_QDR;7u!6ozYFTD-YLL4VND$%={h-w1{L-T2 z)M5otXapho3gl)`sDbh$ z3C^raRj>g2Dkwj{L;>V+NK*66OUqXPMFKchi%SxVO29reF*LEX^a}0REq@ ALjV8( literal 0 HcmV?d00001 diff --git a/l4/doc/source/images/io-overview.png b/l4/doc/source/images/io-overview.png new file mode 100644 index 0000000000000000000000000000000000000000..8db138a8abad6623f6cd3713db57e745884af6b3 GIT binary patch literal 48195 zcmeAS@N?(olHy`uVBq!ia0y~yU}|7sV3OltV_;y=Ubs(yfq{Xg*vT`5gM)*kh9jke zfq{Xuz$3DlfkET|2s7?DnWN9Zz#v)T8c`CQpH@mmtT}V z`<;yx1A_vCr;B4q#hf>H%PVGI{cHB&cSh8wd(|ps-{j6IOy0nm*dFK=xm34x8pFa5 zn@(pmKD)l`g3+xYjq0|&&Q2URo8P?M`+Z98+0Xwzp74{YJkgip`R(scz4)%B={31M zHNSlnm$vMlrXM|x`R!d!V57Z(?kf|k#Vc@Au6*cY*}D0Ss+_3vT~)Agg( z7-F~{gfW;h>|^@ywQH(&_wQ&!K|w*mxx1d8p0!>{QDfRRshC93uOc?stM(ivqEk9l+$uM_qT|bit zd%^XtsoJaeglK~due|Un^>h;BANd9*2L95kQZIx+P7&jIV9M}1d`-;H?Ts2!IyyQ! zY_flDN-bxY!T#WusCM`)znZnd3^Dt1W^x^FFtdwk=*tN=izfRy;jDEtcbf z6@z#9nwXav^>L+_3jLXW^gZnF=;+Y+U}=1}JisWfy^rCAPsc&+uyr+g4cW>do%)4o zyA#r{F+TwN>oU_0@dLGXt9n7U?|E*=@ZHKd-ktkFKEs}^Nl#C)&7bND3d^{MXDad? zPu9pXe#m0b|FKE~WYVWy;tNvjR?L3=TAfK^U((Z4{Wa0TVBem;`F!5%AJ0~=PpkiY zHT_@*>^Si{jB$q#Yl2jRd~FO5SoQsWhGi=mTGmDE+;s8!RRKXk!HMOT z#_=ysayx>IyQr|7>A@yP1CUzYs7bmFAO|_~Fe?ZO3SJaA%-{iv>mvpXLV|*VyoNkO zPCBC|mO*f$I)`FVOVpCKB`p0xuR{&@t!v+p|1NLoxv*tI#{-w+Xx}%|W%X+?8>+Zk`PMXq=RP(VUBtRTqRa^cE^ zo5FS0zxo8jdAz@r>fTd%!?erU?Z#;povC6sqGSzJUM}! zteltE>dNasId6I| z=k?yk+{DuiVP+qe-8U~x^R9e-nc>}+QeBs3!Rw4FO8dpFO{-GBF;8Cpdlz56V9

1U^>*ATOHGG7EtS2uE_%2+Z2>aA9&yY`eK+k@Ljqlb?V4czL=1 z@#y@$S3mxIC4SB627A7C!j&5wr5RBlME9+0&e$NihuNb;<3T3Rt2a-6ew?{)-Qn3% zVYBbpeLK*|tamM7tJf}Fdu{mg<;xwPPH9h^ zJNNF>*UK&)+^gbK&~#9vrQ=JftV=T|C=7HL3MRfEVf;57*(xo1tzM4%ATJS?k#YSijvCP@sLd?dK-^?{U5_+J~J4n_5aWd8TOz5e!q8KetF@}ojWg^E}3#6 z>_ttWogk~mI%W@-C(cpLVyddDKYpF=|L`q1d7{)O$)u31BkoL`n^o6T)*n;$R+=DF zBlqv)FFTtr7o0altz9Rs70#&19B(hksk{MK#J}LT6U|XJ={%B9; z-t$kk-fDcZ!Y#&Z_o1g-k1h7Sr_tZRrpe}@q$Gby!sNylTk-sw{9DA-?#C> z*7avR`T`FsP8AL8aZ5gK`1;=8iNcN@Cvs)L-g>2Ax@5|ZpDV>eu2>a(jkJnbbKuxs zvz!~*&W<~ojgPM?Je*`3qNSizXq2_pkm26(7Ea-U-*2}k|NQh+Lsz#oYb)Qk&r!91 zRRseX62LCaoX)_|?)>Oy|Ctk-g$^7J%UShiEkC*_Gb-m+`r+8~t1l#YA715e*K);< zhvCMyTWwBm{VS&v;S z|=3D`EMP>5c7#?)kBwi#Zmy?B24)*(S{IX3GayV5My#qOp*Mxn;`+JKsax#vruluUa!ph1RkoI+5 z>~68APoLh{obK;#@W!jE%4(WUU#^(;)*qF@7khN7xQ}g)urtB5@4hJWv-ks~^;w;0gAb61>Fft^f`uMTFy)}y$ zFZTaA>#c4_*=||$yCuSIJrWl`-g*_9z2LS)&8hDSiw?Gf>}fFhcep3Hy}z_ZPE4%q z)b&3{_3JJc&V4?wn(zId&wM;>k2g2$ulr!V;`R<_4#Co63?42f3}0B?YQ7v=zT@Y! z+1B%Rzu9!!@8>Q>Ma3N-k4ZB!gocJzJnl9BaDbV=WKUd3Ku_EAv&(Dbm84?8LEvz7 z_SP9Tl}3HC!BGtEeKI#6>)hYBZimW zbSVM(ZsPQn(Iyd}&wanKvsnGwx>#-p$=%oYZTP&>%h&hl)$n*;h7A!qJKpd6{bBe0 zzv~{C?!Mc1`23TqCvh$&7NBCTa^~0M#%Ir-^__Qiaw_=y^?LOex%wZ6<*k^W9+$80 zsr>v*(c(wN>ig47qZj5q{r28v2{`2_C5lIUpD%B1TmE+I^{N!66P=(Kd3dS6=R%Cstr5+S%DD`~TjKLgh=B zFI(@8`%t$VahrOmNl3z~Gy}d2*;v!duJ<<&7zO!0ZtkCe8ZzucxUbTLS)%D2zp*yd}?Y0+W z^jP3q@!sR_{h@JmxW|lFXy0$H349C(A}`C___Ie!(UDIl zaudt?J)gSV-nw zP_jeL*~OU~l&sia^0Pm_D{h|fFXg)8wRE5BNjF8k#NROU+cbbm%K{6T<#qm3h0J)X z8o$f&I|lW9y0$KGb-_Cw*}5O?a>mCs7rsB7e_CMc^`cYXRTdpM=BeP~viv~75r)_0 zrWsmm9E*LGm#pR0za!fs(EQ@l5BK`a1G{4R-q_?E{CwWNf72$TJwKn#HjwzW-Pt`l zTKY_yF@x#@Uhj~HH+Da~vFCi7;L5BcZYArSmy2rr-^Vp$%7yj61us50z~JFh!sYdU zYI}Lze)&~?maBj3g{@_)_{zwf_BU$L&ZAxZcE312KRbIkeSU3QOUu6YP20Aa&CuQE z_dSI3!4}Tg{d?8jxYtzH@}JwG$9s)q8;cNc=o=>dgGIn)mn0@7Ib4owAERo@2In&8eQS&DGDj7;8SXFn&IM<>6;-yVidW z1@qr~x-_0&%oxD2P}oVQq|Rkm;hzk}Bf3r(akt ztOZ%k{QDVum^NJd`M#L3=I&KTr;eQr|F{%(&wec<=yXSW>7NfFU4l*-40qTb)G-*| zl?l^nsgOEQzhuhV=> z@a*Odk11@u{X8@*Ea~JVRZ#16-L6+!3=J#SzBfJM#t~zmZk<=5C_D4B+n1j;N?b9_ z_gHmWcE}z09&jk0xq+YY4)+5-hJ5A~3+i>A{sQ|B~s->^Q+>8IWU)sICDB-L4 z`h$7fA205=YdV?o>f?{v-`^6yy}1c;T8NhDrOTHY83Yw;-&|{US8g%N<n-cfNcnxpG}Qo58JZmpntamTbkx zV&!iks)~Q#nasFc#W&Z*(rsbz^9p7X@5?X!H8i> z^``1uH%;g99AH===FmIk(%;M$7Z!#KVXr4n6lgJgx%}Jy^LtiKta!1oz2L`(#5;w@ zWp}(@xBHG&{+Stu7BxQ%4jpb1T=LqI!Aj-BO*ZX&5xj474H7QarYj`|YMF76_YWb4ndj>5FNXfee$J!JZ)MNR`eC)*z1MlqlNG1DyDR6Zd3(te`(4F}ibpgQ zUG@n)%HTiVBkokA+p>Z&fN6mbN1$>`g)fKT#j}?8E!J1B6Hs#H_-NPQ#julMR;xgC ztH5J_D|KIviTn?&o(G3ptuK7!{(*M*i-ujz+%gETc@Wlnime#f}6)}ZN znV;Xg*%SRQ%l(Mt^Td18yAvXhJa9Le!kZ%gA?bOtLB#>C~}#$rN`# zE7O~mcMBQjF;8Gfke@QajP=xvlWUziID<~fJh$Xy_{z|A5#P{W9azk2lljyA~I3zWx3G_x=BQ=lZoTTc-9T^hk2Vp4YeU?#|Zv@z;y{ z**tS$@qM$Hc3)&`;Qi;~eAj{Pz|3>U{|0%LPxrmctIFUf?DS&Ely_^k8a!^PfB)9I zak&?Vq2vMkx%2OFJz&*bdiZCQMZ@%kTUzXxQ>T@L&tv+)*)V(Q6w`CXlNoB5Rb}j0 z(!1wR*(7lwMe)eyfHdoRjirB5&9DDep7P(65HovAxhf&KHtxn&G+iVtM>K< zVXGAnHM|asVUFFz7R1dVI;A|bH{@6L5{4xqaS;j+x)14tAE2Cs`tv4eJMPer6je5&4^*!f7vUZOQ(+3pi}R6?{L#>$o7-@tiDu7)X9b|b=sFl zdglt=tG|D|tls~b`AGYcD=JRv*j#`sLle9g2$-vmBTf6dO73_#9mB6tnx1@ITpC&vrgk z|Fe4u|92}@rw$Q~(;FEMbjQjnFU=8gs$qOkr7_uW-}^@!uJ4-pVdKr861pu0-%Q#z zNnZ_^c6g^B$Hv3lv5#F!j6@UU(wh?J95@rLo)GtuXU0C$9y1qJUFITQ;{>WVA9 zF|$3h>)+WUrs*>auKw3MdQhA%`Sh)~H@2MTntG~Fl6#Zk!*dr6`XBPdD;1e4Fa~&O zwhH(LIK|Y+``H$zmz1*~Gnx0{y$esw_GcQ;lcgK7=Pca5y8m0J*xj|eZryz{NjP2b z_~Q4;U*npLj=c|OSSR3A!?4u4qIb%q{fZrI4XR5;Z%H@2kv{f#%dE@-i8mXha|;d> zdR;g5H%a_atSQka!qIND-G7ygLG%A?;lS%`o49v~czL`!?Q{8CaxO#G9h>Jz!VW!@ z*uh|N>8AwCgY$VZ_hSX}UOoFMT<`oP{oA+rg(d#>3<^vKe9!fpDIVF*@NRk#--{WZ zix!@ddOO#xVx`qq15X#{!wzf*)&?*=uuyEdb++`mnw5O{w}q#RUUUAJ>wg@5xib3q ziFZLe%>C9M?B2Sgpzm|F7sp1SQ%={GGw+Z&b;-t?VUBuBgv!zw`w69>LE{6`CrTOY z%k9({ckJ5U+$yknfzJ$vDUloVCI*Qy6zHvLux=69wNIpy>zlQ_Fyj+X&GN6G9!`E5 zwq#10=F{szr>d7uiDXD~d|7slq2i3VDcDG<6AV8X`^t~oDYU#Od$00*lS;ppz3IZ) zo}#u94{K!D9!$H(C+75`MZmb)dYyRt!k%CehIO__v%iM^*3;CiwGH&z$?EmpprB@9 zo|2N1)Dbov2CM7;c5|LObYwBZn(}jV-X7T*cTYXw+EV6*-Akujt=)51+hX6Elku$r z{-xK2G+IuuZD2lLe))xXy7<@HbN>HzT4r3kyV0rRq*KR@;GOq9Z#9=r|1RS6VlKC1 zdHTZ7hRfTNJ32ZtCPi7ok%K~#! zzLZ+JJV|7hVqkRe`ngEpk;Ig|_o#wDU;M1sP<}a_C zvqs?5Ck_3t-{aKpTvlwckUlV%L5{It@#n`WyC3{plUDvNTCZh?*n#_uOPGG#bCP=ui1I}*PPh9{@jXjjh9rd#ZKMWqouJn z&%VT%@yV~ech}FgJ-#13ops&PDe_#3c8#C*`Y>Ji*LPQI=@xFqM+w zbDP%fonH?g4DWw)>L>3p>N#f3LNu6Q6R;V0{tWo~*Gx@*uga6WV^r`bz;fuTnJ{$-oQuE^#%{OB-Xaeeh*gVtQ`ZDP_oy~nN9 zwZDVr!=1=ZTt+`S;X(d4G`eSo5+^)13FM zI~o7NX{(2|x@6^i5vA{onR<3tPC0ETdVBT7kQAo~H;zZkj+fZ{zbcv?SiXZX{QbTi z$~~r{vp!s$8LwEFXS3=3{1#L5e23zVn__QI*?lbe|9<}RmVKq$bKjNB_ug;Muc&$O z#-|T{Pu6H1u*}zU_``GkD9gQhzYGrv?>bv5Hp45*;N7#p4jEBC=NN&gQ_+QA=Gw?qT8lrc;uiap z9JYTwWMqQLFT(9a&x9)pTi3sqC}9z>HO!hJpmf9X+EfOWbA8SQn*@1}O9k#-&SxmB zY#q0G>#cwfsfI043ZEyHY+rwK#`Ts$^Zr9ys?~Pv3EQ}q>*?&(6D-WnB~NxZwArcf z<*v^PA#?v{NYy1u?fZF@U*pFriLLCf1WnBjDSua1`Y&G59ei=Z^8O27D~}5o`QO>{ zLS?F->DB9{KSUS$urW5w;s0d4H{?SqXO6C!%Gus_!+Q_Dsa|!=^7-*LgJ0~X@l>~` zLjM>ToH!d90yeMDJMc3%Y|0;}BAg8$~aUpvi0R$rDfow!%ta!X3wtiHSF#p`JuGt@d9=(6?Qiki169z85yi4z0b%L!0XxH;$pBmP>>`dd=pwSIrif3Qo)i zjm_;;eEo@MO8zRBbL>A)SlGKp{&HnHtmpIkcUb--5j6wL^KY|O*6hA{@2Tc(x%<4{ zi$y<&pL03Jx^iyZ>7NSnN3&1;ia#%))^g%XYnD6b)(7t|Ir`jMdiGL^t;*6fUrTl8 z9g&YxQZipMe{zp5e|F%nWY#FHsQ&eTx0@VZ{5^2xRD+xQpLQtQpbo!V(C?max+Ld%6-oP6)u?s9ix z+pLG)m%Lv0nb<{@@Ay|6fBgw3XihpWfPJOmo2C#@0-XKscH^@o;YG(>6ta5K)6Ypg zp8D?Lu4Y~j+rwM4Emb0KKHZq)EoyY`y^Z{<2mkxZDt#3hiWiIex~jD-V=K4GUuXRI zMRfD3z{9T>xw-4iEqFac+~}Nt=ciI#lY&LZTwT)RCdtkHUwN@xQ2CJS--~VEYho|2 ze58}0q-4Hz`?slUwBLW(seaV2mux4-zI6FzrRnbP9hxfSD!b__R&g^XI zQa^gW{zD0fc;af?~YA=4wdU}wPZO-3g zOfL>s->WZwbywKnpZVfMt=z_?j*;u09;xkUkDt>w>Mr@1cQRk>xz7K)6#=X3&jl7Bm^wAWER&=>wLn>d4Mz4<*U2&$G>Z53rrJia{WK+^4qQE z_jb!pwazwpeDI{lEb;pv|ICWdbx5u=7W-FhrsURA`T4Z6(jvtc#tA2Qk7l3V@UwAl z#>$LVJE!&z!9)&eF{a|ZtY6!u1NUs>IhuV+z}i&m`QGZPvq;g( zc1+F_UZa-1{Q2x|pNuoPugcolm6R6!OJGoW<$Cp;)S91H**K;iXo+@9zV!b1uAIMD zgKl=c^?&1d)!)=^)ufJ&6SX`IF18cOI?wXIXHfyURpRUCGkX2T$0QB@zc&utygjc$ zTSZCfl{K5gBDp8EQ60OQc{zN!4|c4sivPcL^-}wej0}w*t5{N{wI)=B2~B#gUQ*e! z_GsJN`g_a^#b*3GAu|2?>hkN4PDJm_(8_Sj-YU7vK)2^3+Y#Sxw@Z6iTzYKm#BSsj zmgun5DfK!wKS)tdTJEBpmh}JLQKrKrKhg+5>12Qc#=XLA~-@2L2{oX0pf=L^HGu%i!K5=`|!b>Y+m>z6X zFMIsp^r^aYju)#ytun1_$FJ|AMCyW@Hf;Y~@NxU|5*htmKAD%P`p=i_{21}$Pv!-Q zE4Fgwe-<71WxZYD{beNvulH^NTjYFO&#w5jl8rT9OgS-4=UiQKWA%0A{YM!*t~4LJ zqsHLi(RK0o)CuNWuFg=D6>9jz9lm1Myfu$ESSGC7%)k&L#aO$f?m$+KX8zG*|F_Ft z6kcTT^ju-y{O#YaOD{BAVOamvM?cJc-lYGohJ5>KL>wL~qz+-lea# z6@Kktb$!{!mC^iDOkRU)zaArl&+hW13KuU^V1tvq`#&Hdaers>a(#g-c} zut_Wwv-sv%x1G`8d28R-l@0u zTKO5tn}qXq1AL_W`-dG+buPxjh}?uqj&e!j%hvp3P@_~){2 z=IVci0g)d@x$gJMZU0$s{+pgr z{zmNS*LS-VPVS!c?8xGjT+1`1Y16O2>Ni_dV(-& zK~0Pd?)Of;{rdM%?D2c2*%$OMm+bBfS=x6v|Jj$9{PUXsTes;?U+4I=FH7aD|A8aX z#})FTc)0d!9#rq%?|S!Po8R%-r=kPPH!xPt7k&8qeoo8bX9qrTU!GuME_cw=i}z=| zNIB18%bN?$ivr3wFn+w8Y&9=?b>89U;_Hvyd(P*yHaz)@{w9N0&u4C!nRBD$K3~qR zeD~$q7H@<~*`))jH^^nz?PYYmKTRnshh>xA`36I~7f+)3ta2DtUO84Xthssp>nFXe zzaPcKE*_m9eDK`SKJ6{1;z5ptY*8I_6cJFHwA%Vr3mulA3GTZPVK!7kXs<-!&TEYbd@Kb3rhTalw<{MK$H0`)_>v zkvHe>t(xh@{QGA%vz|ZW^s7>H?!5E6OqfBvxjCV%Gd9)KJpU~^GhpXhDM97KR%`cc zc&z_Bpni$q6`yzDV)^F@m7Z3QHYHoduK(wuT=LK==F8Qa zf3tq_gn)_|i89Ako2?g$Z2kRO&{S`c|MS<%UoWs_Cz#$$(8_cyC=yTRoV_+fGnE6Im#ZwHibIQVqWL-D1F@BW`HuvGv5S!vDw;_T(qBp=`BOStG= zEMU6q^Z94H?&r6eMKo(~(|K93F0J17+PzJJi`SiW@#qq?o_Fi^%Q+vO^FKZl{!GbY zLTkx>LHLQirFPpEPe>I$2_$Z-40 z$NjI$R;H`$Y_VsMC`**uX1|l&QeHIS)7-~aU;Ccat>D>va+l8H$2*VxNqe&9l>3(- zC;T4r2TVIUv+lo2P1(aNnL6X+stimA&a^M%S^0t8fI;Z1hKj0$aGqpuZ2j$i-tT#b zo6^%1b0RX{tItzN4OIGMr+et%f0=_l?XkO`@a>((y!&Wl%gl{3Tiz=>Ek5*t`*Oj9 zr;AruU%6n|wmBu%GHUfLgKx_w+Ro9PXkpDabNW){Dkqhmk8Crt&z|_bN5Xpkt!DZ6 zH@dp_TQ3hjJ!|C}*7(?;wr|p`kKMBnQeJn)A;L|=CskMDen{&zsq12oXVsRjxEbDl z`Jat!XYnJ2Tp{*2yRPQ-GDokump{C-U2NCiuVQtZq<^OND zH|ck8e4YQ>@cGL(e#igssFCK{ujlwG(sM@9@ro8+{>GJCSa<)gW7sJ#?v#8X;oJOW zJ8SD-Mg7{T>0xWkDH^>h@Kdeis}Ez^LuN4YPTq=KOnj+7w4fFuQw%R2R4PiJKic$dG$lz_3i&N`E%Bq z`NZ1EJ+3$2_4wz6DG4dMZ>uC6qSs2M|4G-IBrf;<(%F6WLSEOy7ZgRCMrlPQ_L!Gc z=7nF6`t&kVwwsInC`0kQb8bJEc|EBQYq9iCE#I;L)D?bsUDacbbpPe~)@vXCys$;! zOspZZudA9&wY_|DzEtOjGyDD)n!K>sZ*JQ+_jRgMo7ZBeM{{=c9k@K>e$V0c&mVxA zN&h1SgZ%v8h}7IF-TLmqiPi0oCx705^xkuR#Y#t}N6U6^t0{GtUE+3Xk;@VtFBXO? zvRMZj|I0a^Tg4<(@lzv6OjRjyTTpWGL?gFf-KVd8sW|&=lGya;etEfef!9(cK~Xp- z^r!6o{;u563_UZ&)Ig=Cq`v;k*;)ZvCw^{Vu$15BcP=|!>uoe|vm~=Zp#Bvr(Q`Ga za(#QJx4*5w)y%9f`|{I{CqFr7RNR)BZWws5({0Y@XHGd)3G7AoS`P2r=iZ-lsI4{W zT5_;u@r~n3?ybsMF)T&)nn$)&s~@_Q;`(uxk&3=YgQD4r)13~nhS#GL)|oncDO|B! zue=L(KE@BhUzx$a>w^ z!3;K$PhJ$9snn95YMpf<G+539_`UM)PcY?x=XZ)^O`|YGk zZt1f=h8z3Do=r3_p7_0R;pS-HvXb>%!?f>S?fn^h{+f)J)1@izvx_~y*XwNAFJ`tT z|8ec*bDnNbzh!N?y6gXaNej7(HD|Zk&AqP5xMc3!p1=R?cs_HMw(#=1etj3!vP4So zp6iL%`cuPN6TL4Lyx5wo@neyMr1+9W4^Ah&P%iPXRo-}cR z$S#0=rJ$)9Q(*FMGf9?!V=s^Rb-KL~`JV3ktz6#!)%-;7OB??BR~Nhi_0nc8=)Y24 z(pb9uT>$gGeQB~S0w;DTh+cfGypaF8wtie`(?s`uWhz3 zi!Z2m;9m`n)#)Xzxe{h zMA;vFvbzwrc+KqVbAKuKGF({RkhVB1C^hC6bPuT{&QTC()Rn#c81j-BrTd0nQ; zl->CMi(UIat~{~FM7BN7x@}JA&w!U98)oH5{O#76Za-_Wx{Fitl?6X`2bqY^uKLqF zM+7t|<@bw2Ht4*M(?fIB31yvz*LVI~WO?&ny?oo=vwfH2ZFpCvm&}um+_mq}(;weT zuT^EKeo|M|bTfHklJsnG@K1J6eW&1NP;o0$^;P29ojr`pZ7pRdCLdA^VR}}@{q5gp zg|6$<6gAX19_PKY*_iQGS9&4$#iT1+XLigKxM{fW?4^W*jp2O{Z&X(XWQLruxL`m=E0k3OQou${j{Ic2ZgDOHTT5-MH2I4 zw@78p<&s*wOnFbs5|-q1moLXoJ9|;$ipI}{dy?0B=5~l_^}ew1Prj0H%z3hP>#VX% zdLM62x*B^;*xHh7v)t@w*P@yljHa!7uv$o@W@!%Ra_;Mld^b0yF0ylKxAad}Hu+m2 zzU|nGgNwwUB^;LDmUwl=ggmQ^ly4!S>?GMv)vvn-~aCTwc}-p|L&(d zu6=#yRK|9Tn0cS423}8lbRydF#_vOkOXkjQ+MsuBRnFS1X0wRP&-cdPy&98~#dzVX z)}1;x@l{9vq^Bhw37x8OKccg3k6MJUSkeCV;0s=?2`LfK?i>7v;e!mhS`NL}X0-0v@~{&Xb)oVr%8Jy)}1X;K37f&k9#=^0E8$0{{7es5&DJ^x1U zt=iI#`GVcQ7W3Zte<=`T>CHB;>BYzX6^VS>uj6)c`_dneHoZ6av#6wH8SCP$n|M=a zYc0IC(%^mmy4QPuI%Q-TEc=(p1ZvFBkNcqO7H29G_*iLy;fh49OvkJKrW${?iHO%$ zZaXcNKQC$J_8Cj2#PU0Q3GQ5ev~>5e*zguFg|wiM>AE#{U+OW;<60=zalX&7M!Z{f zcX8ger;-Pr?vaYLL1m3o>cG{Q`B_FrzJzr6(HRu05 zr8gB-`h9z*cFX#|ds*QtzUt_a+sAmGOuw-D;`KDetP+-OHlKv~_FdW;8Z5r<@CNRn zh3_9PnYJ%uZ5DUOHTy*lpxKK$Z?8zZN1qbg-Q#TUXfu9THD9mj_l*ft68=1jxb7<* zJiY(;j`%*8HJcvtI+3M=(09i95G&-#Bx=S=;w*Vi9yO5X6~^X3H8n-?Zr zX2~o*ARylIz$JP6Z?Wp8r5C%FC0$Nif43o{1GLC>|FsFXw=7(`sC1s;y$9D4ia<8_&3--Uvmd#dTC{DgMZS0))xjps=AiT`JIE{h?7m(1Wh=F}pSiyE!hu`= zmfJ>amtVQ__O(?9n=+dNmyJ;EZSKxHX~s9#Y%{BFUjN!6GC1+`v}E}w`;)b@3-6}) zvMoKF|76OQH*0_QPPxQfJwx!~NzfGK3~3$Jed`i8thyB$oR+`&{g+bN*p>G}tG_>E zFVEX(7F`?5RT=qp-mYnT{JG-uw6gBKeI4bOlDQ=;YIbhlz5XQ!&)mw{8aaDS=)QH2 zLkt;$4rHFn|Fv@IqN(|Z;sW+AU+3U;^T}(gT}n&0Os$Epdp9dSzh?87_D{d=onPSa zc!TAJ-!qwyZ?oC+nP2qwYWXjvw(8lM`FCSBuDw-SZ!Z;eYJ14kNU61q_IfiJCouUv z?VHtJZnHCe_WIWnIemNPMn`Sl|Bf&I`bA;Q)Zm}bPGxVi-}yW|TK?|V^Vd$@J9u!> zyM(=!Z}ZLScE68r7Y}*A^6&EXuU~de*|aUA^yRg0v6>k#Hg3HYxM^L@@+q6HUEexK zOOM%^(cLSP*Oz-|-rd~UakGB4cW!pN+!XsgRB8Lovt@7o{cco#8olb@m5>{I4qyMe zWAVF!!_`h5`BI-}#dVzTn>(}6(aS9(sv}-s*m>QO*hMwoq1g|wt6G{?zm8jdEB5o2 z_1Uj{Z?<(wU)R6=DfOH4=ezKNEy8RbFlZ{6ikiub zIq78Rxk9leRD7BBo7YiQN{UOjUW~dNba7hr&c(kB zHB%jWGbaX_G3vMmQ*UQ(p?kFx@BkFV}cV$MchRRV3SMi12 zVgk;e`uV*ln|j|`8YsW;_T}Ff8@;_W&wiaY>zUH!bGMkk_IqlwA9YA!bKr^y^0IE& z|6^C*WKKms#v7_j_nf-Em4`LxR2qZ6r9GReVhf`KcSHKpDRuXw%pxqA8}9c8%49fo z*fZ~l^|CyDeQUt|jX!6d`0T{+j=J@vzgU6Ff#RLYG_Zj>RIgBdx6W-UH`H;wa#h<6a zMed2r;-yTx8%|nFFr1t(!Z0C$JHa7|LFLn$fal853@4=}7*6JUXr5&_bwKPu!x09L zCy|Qh+}RvHvH3A6)=%c&#=xe+=Ad*wi@)IwlUn`*6@gFYKVfF*lrc^=-^e}VkFQ)q zi6YBqmxhP+21@6X#0@HinH7G{uF-H77OIV5|0>9=Ffn~2_l!NAj1&IwUT5M7;AwD~ zcT_LolN#6>sDt@YM1wgFFm7XDlL1)|Hgb2v$@LzZYZ<%_Fh~?gFm&2zi!_|w>7X@n zxgo7bayCpnNKrtmv3D_lKZ8X#}LAXF)~yW!;Q8>~M6R@CYq;E5M=tUU}08&DV| zF{so}d0+Fy;s66E=p$ibAv_28wlT1Yz}>6fIN|=ppj!+gjk*nttsvVZ7*5W%;B5I5 zYIlQ4A^_qA8D@`ri&+(xPAQ8QcPg1wvw_uM0mua%0!|DDO}Y(FY@;^(p8h9Tu0chy zW!-hsR#F!8wo!=&w?SPbQyGT(O_0~-g( z2Z`bamD0=#KUFoCGCL^VV3IHZIk#Q6;Ylt}!;|x$4vHOUILP4f#FD4sN$wmLr++&9 zIgC6Kpcp)?m+;996r|Jm6&yJdKa?t7u?8E-txzewyW!;gr`Gb9Ya>~9wu9Uy!Eo|6 zC~X$%Lc-H>A;XyNX3gglo%)xWAZ#rF2glY2=Ouosw%=VSCa_;P zt8n%D?2l}j)3tIZTw8K6dzIpb?Q0jl)n$nH0BwPejyGhu)FAA%qQxs_wehQeGBUY5 zvnxJUoSjkZ_EI@WNnoA`TXIT*pF;K5=lP4Yma~=T{)$!D78k_u-#Ht z>yMq#|NDDV_=TYBT6zEfO>_KdoVESd#gLmamm;o-1npX{lYISmwU}6r?j>pE-t4H? z(bGLO`G4*{}VEoH5TkCuzG^IPj4zOGu?b2FvUF5>xXqYQz~x8DS0 zTa?WH6CP5f(p5h7*Djv*f!S9(JowyQiYzWITb^+3>&=B}lUb$X?$lf>*WPzuR7C7c z-_DbNsx?y=ug`wVd*3tTKt}VHa<-O}(IsHTzpEdXY;d3cw<7z(k?!Nacd4v5FrU4U|LX5uJW@yAgjt91G(0)3ba~27 z`K>=o?bf9{kX+oe(oPg^UtvVXm{OcmpXyKiQvt;nnSeoJ7jYuVrC^yAG? zx_TikW1;uuU%RBNSj$$+YV|Ry*k8NI6k$-ptiX_RR=$t>f6cy+o7wlp=(b3_?@wlu zWH_1KBCt_v@3Z~p>vx@#kP^T2n=^KUNW{etj>2!gmN~Gla1Lz{kXv`f*v(IZkzvD= z-`B17UedalRm8whGSkW>Mv!glLHqsfSB$NXGX(LkS!y<;KO(^{sd4L(SDWppz2Eh> zY=MYI{fblOtQC_Ows=ataDTBter3Da(Z4rLUbp3h{+o7aN9}yM3bq4Z<5q8+FTrp! zyTtA8;>mil>%Hbpxw8Iqu4&noz4sVGH*ig~=Wf^Y=3bas@RHwswae{!W+t_{PIq7P zcI>O%u*!YAwbr*U?7Gf#^V#yVC-46FdOp9&Ypv7K#f|%U7N~{s9=@W$;>+_$ zUPUh9)|IYh`m?7Vn6$|CLyR&@{o()h-`-iTdzoGP;Ky^7#P_x-7J{yY@As}<9d$eF z^@|PF?+dGM|K7cQ_x9Ii@1vr_UuSI1x*N4!qf1(pF)-xYJkN9Q`x%;=nAi?kyuaQ( zUFBz=I>*V$pKYI4=FKp1D2y?*tbaanvnu~_K|Tw+Cxmr1CZ{XbM_WI%ux646EK^u!V9=*4@@Y*RI<%KUw1S3}$ zov@E+INqE$t#3u3@e=71ag&>KXYihzJSW5{mc55{(wnQ6Pjb#2-L{z5YW=IdWfm1y z29JI!?m8=<`&(c}#P+~zKA)@E175Ydt)3}ow^R7sKEJJYZT}WA&TS7BX$4%)XN&|-t7r?i)ByTp6q{Zl}uMs_r|=X&z4^cd$~pU zxFDa_&(+FO(T$He*gx@$1&D;VoLl`%{t%nZ4gc-$-ufh0Fvzyd??FE-K zZdlzu$FtvZ&9%k#3_(m$Uz5_pmdZy-U!Ur~S<@nB^YSB0iryXg=_TKNSJXc(Nvyi=*71i^kH6Ag_BQ_Q zqa(j2Pqmv?XEyf*@A8g&1zj`VZWMWLzQ$F>xATg(N#FIl$tJIQkL2_()p-BPeEA!1 zOBI)S>c4~dPS1-B3{Q+x)wP>Db^V%^pFYlbyYWa)|I;(yB8<+N&zrWyN&Ui&?oBLi zE2Y`%x|4ox)?UBs{tEL?f7gEYuqm1-s=qer{GAT1{)r-U&ulbRKO=TIzhD3PgGtU) z?Y7lFWZWn7-!{JQ|Gf9h{vA2?eS5*nib*%m<#NX6y?m4MI;nd1(#IP9stsPT8SkYY z1g+S-^^EGVD>qE`&9o7(O+4D4dDGLf#`Ixz7k8KD39SVh%U}8Lb`O_*zFhM2S+U?d z^ERu@_gnjAqjSAX>cQImo8ETMT~nQ{yuN+k@k#1+=C^lFopteriB5f)>csBF>#B0T z{$H#5==ooXFKkBVVy!R!x<5hRqs#2P)`>e;Z1{BTgPuN)@BKe-|G&-ieC7Y0oo-%x zyxP`2?@RuSuAeMlc~ZXj3#O=rt#K(z`s*pgAAewbv$^s-X|L-mABM_3e)F&R&ELxU z*mf?5Dkru}2`P8}_ols=+Zg{fn*~H0n zyaVF|StDCtaDPedT(a;+gGrp+N{#*TE8i@U2}%me{^N92>CXJ$)9xNUy!!p)pB?Hq z_rFMp{FGoKvEJ(5)RSvXye9cCpD=w|_~Or6Q(v1dw*LLhJ#5E%gY6y8`{kEjKl5(K z56j}`<=bQHbe0P&KIl&;fty7I5ARbN;|>)Vaar53z&xfHrT z+UxQ2i>KyJ``dJL{|krK-^$P2FV$9sn?&(G=bNXldTh(CKYtc-zxh+fuWmj+?c-tZ zn?LW$@%<4ydUWyhh>w@FuI<|?*dQDKe%%Mh$2B2JyHEEjz5AId-z^t)YELBh%`XqH zNyXmXP`p)nN4P>R`}VX)(dHB92Ra=3SIltaU61mo>!;-}ED7B7XlZEb`r{{;2i^E^ zU-yqmvYq$5AA3(}JAFNQ^Sos3!h@&b(X^9oN7NeCHn-Iae{Wgm68AA_d;LSksyi1& z8=jtDm-6^`G^540aFh9cKf2=I#hq#YYoB_#J^JV8tNT0pJsuoxod5CXi+qM3g}?M& zbnRox_9SQfeKHw-CFx&d+8>}?4`QiV&C*F4*aPW z3%~JfzHXelxvIFqUXJ~DpE`@(`!6le`)AJDr}utLz4g*=ul933wMjLvigr$QKHdL7 z?1@)GKSR*DC7;rc|DR_2?c)OdAD`#fe{^gA9`Wab(6zmLJLgP^nP&T!{r+8}>B6u5 zg*MwxTYs!R{-F)X)FX$*8E<_38)ql=!%{mw?lAjbyQl4$_Q_YISMo}`&*u8QPxM>7 z(Ye@p)%)Jf^<7h4Eu1i`=|kOo{~6}hf~V)lo~*XDTX)rRYTMfHXWqSuF8FC`Xl~m7 zID7F+)5X>d7p46Q-z6w9oLoLB^7}cpZFQUGUbv{pQkLBqKSRIoUf&jZNvGQf*D`ec z`pdDhFf;YIkJZdG7ekMq&RahJ?1JZW@4hfyY@J?qWaE#CsaN~9Tdbe)W%J7ztBFUJ z@&7+|?&`Ellae~!^@R35{PcRYiPyH;o!rg$rZAkFy;orF)@h3VJW44Q(VvWU?T=r% zdA;*dQ&PI3l%L}5XWMxKR`T zS_@fOwbXL+6m8KpdzBV++uu{1%I_tbB4+UWx%GxZlfQQH zU4Cj$eYD=XZ(IG%^7uY0A%ofz5`S(m)b042zGO;>I=feg&G9?d&lc;OO%R%V>Pmm! zGONp7T*X|T-QMaYAsqW;Ygfr;$6k)g6qIT-@seKPxW{8POF-tN8tY#VZXax4@wEMA zd49f~&7bjomjl|9rgvrRipN-9vvj6z^Pk z^txAPoN@JrKQ~2tYD-lzKfXNj-Z$Y{|K-(p_PxGxF7;%5?hT8Z1!>hf%m3RY&tg{f z&EIwPYFa?{ou)e;_Otz-JZhHtq1!c4pJ(^Gy1Kcwk$-PR$=rFvIsX#p_k_^N>oqrR z+PvuXm2+=q%X=2AcldU;f64vYy{qrsv%j-m=jZCRqWWu-s~``K#S&bfJi&x~EabAIn)-pBuq+t#c9ZRp<5y*K^qg5z`V zhRpxwwZi*=*W|08&*i!3S#_9rDb?FnoSi80{#%@B-p0^Gy9HBfF8mKxdM1D1-qk*_ zhjkol7ig@nDvrCu6eIb?qrT0~vSYXSIhWO!H~l_d8#+Ha&hC5d>32?2s`ve7p8nrf zck*WK^QHJ!Z|(mouH%*=#S(pM78U{4xG*VY?l7GGxFoVy~my|dp#;b+MyQ}Nn}+o5YtYp|$p-Kn>^aLc*? zt7U(-u{6ILlu)$?>u$8}BcQ_UJpinb3war^#sd41)X#G0HEpZ{4}%yMtKv$>~7oxjhtp?IsR zx+OcqbnSE1c3K+`ZM2QrY5eqW=N_@YN{WYXZTffDcdOm{qM2^X7ykaT?#*x2NwwU3 z7qZj(rQYU0&+-m@_taeTy?}m@-|{Jc?=L;JEOf?n@sGtSi{s_|`d`Lo-ZY=_xm_q* zw%V~w(Mmh_X1mDyZ}(z!%p?DQxz;s(adS1h;oH+I_f-91P1<&RQpFFawddEG#2nn) zT=1zd>0-0@3!9C}y>4s%TK$|c)X}@4rpUjh_(f;a8+* zB`v#fvC|71&7L_=?nKSqy)t-u!&J4?2QN2XnD{p0=P9YG^X~!|3+{Vx&oRbk*ObY# z{T@Gg+!8;7|83j0#K*s*Gwc`1uH2X@^XoB(o^A|70e_kD+Z?v%{IL#FJ!|UAi+lCd zpQk<%-fS!8ys>dd>_?g3+OyoR-{W^!U3W01%kS9*dH0VQPtW}-H=llX;Yq(!idBC- zZ}oFIE*5-}{v_OTx%hfoge0se4rAL=7 zcfGQxeg8JLj8i|QBKq3itrO=gkx42$5;{YD*TcPMEq+=&ymzVhGrRD{!Yv2Yuk3bv z9wyZvXS{p!tF2q_e7d+q>h1IEC#NrvW88E5Z*tDuHI-@4AGi3wJJMOIUb*;jb;g#c zL;3GKf=(V<`Azxu#@Fq8_sITJyrl8ce7U$&@ZYce$FIA6-t_&yqDfQ3x_>;iMG9}d z?T+kb-FdMz%i?|6e~!6Zx8=OkaqtV`i|_l*r!KGFVo*C{|J%))rd8|Cwt6v4Ra^W2 zZ|%wRT1&pK=~`?)FW0uj{&_ zR%XgvXAsYslN0g%o7$Er-h+FYD_@+i=6rFD$>8kWnI8|EY^&QP>pXGZ#`S%RG`4f} zP8CZuD5}Xdk-m4k>71YYZ^5?`->xKV{>L-h`2DvypPJWdF;P20elR?Ikazw=di#{S zaz6s>?=Zz`y{W#Oz1U*2abL@c&m!V8mND7v`DOP_w?jo$ZK`K}|KlsuW^5|!6u!Tw zv)P-!ILn*o?()*q1I}fs(;H&{%#r-^qCxAi%-2f=3|-t`SW2=Ff(+O7V3PRxC*Y6u z&!Q}Ep2Wx2Gr|r}e=#VN;UaAe z-#(q%yUUMv|Eo_M1e!AA!(t+y$h|q{y!zRM*|XaB?v8CeDl4_Nty=uNlD)Egc6Iia zYf)|X#Xs|xmDI(jy6rP~v+HyC@*0DQh5sd+!&W<{uTDNv?96yM`=h=89*1v7W!A{9 z(W*HSq$PCT?&p(f-|hcZtXRq%IEzp5h&QwRoA1ZYzVF??uzcbd)<_8>o(j7~YD;H# zD;{?E)SkJ+r|{6a=+D)OdwxV2^&NgwD08i)>XliM=KLiKKVN-VwfkvSyIEPK;Lnt` zXAb^mhWiKwb)|)E5+ZNB)h5xZ7jbW7qp4mC2X`OckQ{r;QIP~lMm$m+w$uE zr&Y%{`jnJ6l`1<<{O=e`}e={u!SGJC__=`uNtNnGfzczR2;(H~uKdS+Vuw zfqQrN`OR-miesNHcj(^Pf2-~vJT%8?TiveagZ;b@rtcOvd~{QB>c4voDX}NqGLD$O z&bW3&JbC}qXW!K>DE)bL@s0C-`G=1_sk^|B~J>UI;Mw<=LHG->-An^nmF6 z0R5ozOD0N9KUeFW{#f|cS^aYTv`_Ww0%m$wbT(>zRkq*U!2AF1q2k^1R}}nT_|)Cv z%W*-s{Wfzpe3UKtwz^92{Qddw51a}+KBK>K`jRhvYr6bbIwS8@mlU zmL?+71|rfMwryAYn`0G~EnB&=^2xF%ljcV@T;Rx=o1<|?_s}V~a5Kk!f9evVzD%k! zYhH9m$tJowWcB{6mD6gQcfOu(&3NO>!!WZw+h<<5sF)IaChgvtR!~t}b+7X0q{lm( zJ55*pU1nl)H;*^{sr|KrcL#oMx)j17_*wt^v2S_LBg2Y~G_53??{%DuI{h*?{lnV_ z&ZlOEYzd3%`%@|7uFoFzjq}lwU6Z#+Ug26jsZV*j-wdv)zgw!5m#Tccz$(Nyhn;in z@9jr+*M5!P9Q}Bi+{MG^IT_ch+Nf4B5<3!lqBsiU2x7j5=`Kgp$hv03g_|JLTx zRzB~ujZsdEHM)`*t)yk|=Dj|&kCpw@yU9UeFRVVjUVQrI*S#xGJ6_pzxW@RU`#y=^ zy7%u|_20FBlX_d+8q|g;-+m_b;otp?AKpIMIp%$a)XJF{v?&v?ic@mZlCBR`-X;f|5h1PDyP5B@qXSZ+c`r% zvMm18%#d^Mti!KO|K2YiKE1U6=KdE7`)&8lkzfAb$;(Ge^10E8T@zfdwd$O6Q<)HQ z>3-G0+Wpf?t+npv|3B2spfca<;d*nk36rNB{@L6K8cyo_Q@JPXqji<#gvlvZ=l`{` zzo_6rxNe*fx4G)W&lmX`C-jb7JJ~iPccaKN5uvi+r_((j zD+}$&zZttlKJit@1E~k6I=`yV{QFtapUyPnT8 z-~6aDmp#^!keYsUsjw%@cfM5@4W}Gi{QS(jKSke@)b^V4t=&4U_A|eL)hb!PdsEN9 z^zQb4ymhkv)Ly6g{ksAddmp%`7M=PoC{xymCqV){Sgy z1s{K(qiSv{zJA-hJHJkz-6DB|i$U93_7~IVvw!p6T!~+^NTZAO>#VEIpqBE}Y3F3( z3a7YVw+(o@EiTt~UA2v(M)qg6ge%gg_vxR~e)RZYyuq83jxD|K8{Aea7JYR5;@Xy_ z+AvqGOlLN8gyK3gxzyqvQZ03w0sV9D z?3ZilObIAv5OodIS@HXAtVQ_)o7wm7cco|ddwEBP96fh++M+v)xV~3z|GsKM&)k2% zeQtht50g8*f3m*wJPD5%D+G#yit_((GQ{S;J#^7j-NR~T%)@_={v;KhE#W)5sp{Md zzc0svbADDx-_3s?w7Bk~o^H$u&viel1+ExR*!)|FVS?MqkNX#$mb2b!*=EKZ^-%Uv ztJ~_8VTP|?NqoA&p!Cdr(uV&rt-t;AtbFU19o@b8s$MKowre&ZWlM@sWp5`YyK=pW0D< z`n2u+-S?!PkshzEC$rbZF^$nbr|yK# z^9-L5uPIIn|@{0&8=Dg>Q%z~yz|1*a?h?jo3Tl7nqIKg z;}=g)Jhbn7B>l{J{mi?k-JacHirx9YzuIEUAA_=WWoLe6TJ5gyaR@hhzTx)U*bi?D zN)xjh%$lRaqqgk2@}jJshthIOL)}s}eXSAOjGvFUXq`UP^Y3^^_PQ5u%k%TC z{CSi=eqi0CpL#htDm>~Nx7*^Y3cZus!_FRjDrL$$TWBhSR@b748TIM=y|O*Z=81%T z+Z#XQeQ5q3hIwmkKjg#~<|WK-Tzg7w-*mbCAqDFXaNYHG+i$by&F^>H%U2p5`*eJ@ zSHb%QTH(z6RZISteh-&2+wKs4hiScDQ2ai-1=SmFhxRjb^zO*2YM#7Z`Qc>i&|Q1y zcI!SgkN@{q|9`dU72^e`B-VdbTsmd(bmygaOIzGRUVq=SGJtczA`LIgi_-puOQfc| zotO1dQP*r=>i@U!Ztl{+X`;t-SMVHlYkANXo*#D9^gyfNdET{?leMQt|E+(0>Xk>F zccG)9M}_H!-l~pOcPc-3UA*~9DrRGWcC_sJxm71GC0?-v`CIZu&X&?|$5vihzh{fh zq*WKyqZVI&AoU_@ZLYD9(TUS1@-NIyn&hXp_#%hR?Q3UKZ)xjuYn85l?7MIWYwZ5D zOZJ^$2zW0aFwJ&vlic=_wFXT$1TwaqeY`bBwV|u&R(|^wG z_!;@-kyau{eWJc`E=rx>7QLYQ=4I^+^DVrw%iE%@rlfhQHgqxN{4^Att+##A-bS_u zQVP#^MaSmGyNJkc_7lAD^Oxy85!XPGqcWi6@33(yzn|VT$<|`-_eWcm+c{t4OuVe! zwMgS^z~>zo)@oc2{;TI)T3nU+kU_*Xa7vnMFN2mB@0^$&0@>>7HNU?fKX!HM=jd${ zN}usCD!VHC|r4R=}B< z^>e9)*XIR74z4TJGEF8Geo|SuIbHbcMR%4ysa8Av{%^+VK{IA@Ivi@_-7?Fhv*F=k zPwT2Fo3pQ9Dmui%?Y?e?vtyYcdwBdIg`BKC>o4Bppa1UKn;%=t{uY^T>ga2}Tkvsr znS1Yz4(}x@BC*A@SMAuw>&C$=cv>h+ZvHWkc161zyKi25b;s*-%JZb|x!G@@$7-9q zsWx;4F&}%B)Ky$05T*OAuI|X%C{~9HFD^D{dT#mtkx}921IIOU=IDs6PKsj>Q(ySn zial4??PSfart`e>?6WTG^UMn@Ws;CC?7Xps(V{dfc=hAo;c@-jqj=nu>-GQ4+}Ixz zyCN!c*QUvzZhQ~7s|ws5R{uAycFyKbvpIivKC7*0y&`;NTf>BZt9JY3u4D-a%vzwJ z+uO9oWY_*5N>Ht(J$ut@66m03|Ni!@9h z$jJC~D>`4ed2?db4}+8JdJ6*PIqLk_WUv4V|L2qbW@pV<6IVe8#qef?7LGxd;sb&J>`n_Ow$L^Td;c0b$ zEPkFm`Ga51=h3#@8&y?7Qzkl|TIj5x`gWPWdfG{$B^NsuuIRWBxp~93fY@u#Tw
y z5juHGUuN28i?!SR70EOa`gbGQWAVhr_iLPwot)fa|82(7!`Wh>LhHZ>%YSoj{o_8` z`t|z6!+uWtf|>U1Dq-5)a^-gA)L)nX^;t*MzFu2W|8D1|-!;F!J-zUJesXGhdvJjP zqq5tTXq)BJbsXnUclUE*TDUpA_)WX~i_h=tnK!&YYi=kKyH2s9@VVcw{h#@qR;#|M z|G!wlR5Y6Z>iVdamdh6?=)Jwm?QrjC_m3|xo7c9p-;J-CxHFECD zIk#9G`lrXU`IstuzjnK}ecSeXU3U8XbNAXh+>Ehrn74jU(8GO~ZZpKrtJx&CIAoSo zw7>rw8(Yg?XU%Wy+MWFT>Cuy|+?uCOIZ5%9%rS1CvpF3k<*|6;waMzyR!`C#RU5jJ zK+T*}`+iQ8_~Q2K&ehA89%}f;WPS>dWzEc#;O5@={qyR@9aEO6eEpDUV^z9qRa)BY z==`+>)=&DZweIBEXNS!_zAR*kSfhp)^Mzu!a!^P5Q+jxmmB>;qsaJLH;_kI_FJqOO zdZFm8SbkWTP;%kMo5`oFircm%A78hB;leWA7gN-nygup0J^6FLK6uL1)R!4kvI3MF zyqZ-@6u4jI`^{UrlWm95qn!(LekZB_efPHa+_gXT^NvlLzx+bvy2Y-^qIQ?&HotzB zw8PK6PkP~b?IU6Ho&NoE6@7QTBgu+)Puck^8z$D}#M{U>U%R@-@MKR8*SUD5V*j$K zw>fxNwx47ViNF5r$WiA>ljgLXyV$v>Tf8%R@2n5*@@uCTOMk7}@{7k|tNa?>sSH}Y z(@Hmpvbu9=+Qhc_-hQ^x>)OrpoYTehmKXy}I zmw9cML~fRDRL!qvl>BVG@pWRmZ-;4=dG6lpZ&v5avbSu?z9+}Do9)5vd+c-1_WqrD zDydWPs6$-{W2<_1!He|vYddG2`*)$qaR0+Tt=BmvK6UwrzM8Lbzt(r{h`Wk_*}lVH z&DUuze)-=yWA+dEQrXRUnZF#SZ`Krl{;@AZ=GF7}yA8H??6;3PUwiu9s_CC2C+SRh zl5>*vz^=|IZ-Y1&TuR`KZu}jqm$Lr6YJR+3W%XxW*`U3d?$+nd+WWi2s5Gd|kzm&vF3`aj66;Tyw7L;kXT<|$d>Z()-(+ZOeDRy4H$#V;&-Zt3XY%sjd!CTI7 zd`(Q@ve>-re}7)+=T$y^rY(LobpEw3YzseMGW)%={u}e#llCDVpW0X6XuG-Kb4G>! zlgaO--M?LvDY?e`{AuOS&Dt|Q|GT^OzwDk#Er(_(bv^33`18ev%>(3R=OkuYEzA^A4$|cH>h#i`}&ED*I&bICXJQ?7BBC6|8^!#Z-T~bM1_#!w zOzS?tm#}h*(K()vKbXEVy=@Geajb7rLq&r0hwW30{<@uCtWkP$@l@;Q{ILr5n;8~6 zK6((i*(%S=_1eL(2=?fQMVo~$-S{AMK(2cCgBMRb+_lTS+k?_RE

s`3FZ#^o|*C zXPm7y*|pK~%ke;_UB4d7zgs?OzuKWY$_;%EnVCOh9hPz~5O|dOKt5z&P7c?HZ32(H zA5?0luI=*XRQ$)ehbQD~-cOwbhu$WwUWXrN6J_EuR~;2A3(jbsDSvH6rbC8QoKR5A zlH&;mCM#Gnj}$v^DBF@3V5s@^a6rz3Gkq2&QjJ^pn!Y=jH;vEJaB@|>xS&%F`<_yy3yg)vQTFi>ET;I`qHaS=TfCN=S# zu(i;Qv-4f~^){Ahc*$Oh%=YZ`+*%?bdc<92!ps?&pi%2-bEh~T`{{G;o%e#vNBS(P zuAW_*derEZDWi~+4bK_Poj+|29K3#ZPATf2@@c`8PuV`4xAq&vu9Ick6WkrVH~Q22 z?LntJgHBBiI+YxBDmduW)}T}0mrl8BpgOnfQpOIp9Y$|guhgl0RL)f#`n+}7iM>m$ z?PR5{shZ6X$nWC*GL6r9rTfm6l`iY;JwL4!akDYMa_ON)>4JMg4vH)-+#MWCEhF~=)!yU6vKzPc?R^lzTq*>!wvtH4924oRnumrfmi zP9b|=#B*F+^rWIpb$hG8qGo|dd5TAlWFK8*q7$X9+bs9e|IfY6DRWM5D6#08`E<#X zO`m7qoyNDAY3HkMd;$*w#vc;Kc(rqSp3SvmjB z791Bz_N_WyG41!hYpEYw1N;PIxQW#JNGgK z8)dP}=XCOnn@c3TY&&ks zonFSjz3BQM$%vb#b0?{vy86nPQ6}(H{+204r@xv_3p&P>?VZ=R@?fRkwBP>>6ct02~3%&lIVH-nkgRE1BU`Q_01{n{QeFvswyx)23n-}xd#GL9+ zMxQ{dsG4KWuDarv=qJei?*G|Ki6IZ<-ng}Ie5)(l7IeI>wnS1+_pZd(O9kHTi>@^P z@?r3H-{f~SVg99D=hd@McxrBLtW-63XPDk1@VQmMoLkXm{YGsDrw+XX*)!bak9%q6 zPYc?oyYx?hm!;^AwJDdkuP@w_IYVf>U(hMbpi|*Xr!1WwS+Di;yP2X(sP+`^$%iY0 zPHieLQ#|taK#79r3$>+lbeH~Fpt3JfwJ@4-K1X2c_CvoL&Nr+JI_17}%Kr&L_v(A) zJ1;e`e&<^9|8MP&chlx;d|$oDB4^rHoKDR^3!K08<-2yPl`KrG#{9M zfM0cSPxvp63rzXmn%CogE|^l(DUigvZ0b?|pr21K$2@S{FjwxR6c#Toykt4wl3(D@>H4MYbQOwDLA7ebIE(J<&EM?rnGs<1xqPrS7*PA zG@1PMea^D;v9^UD*O%N{5h*hNday`zi{kBw^ydKy$G`8EEPp?P?eh1i1&ME_TufOT zc$qirRLGHgtJcKlJ8!PP=x7tY+xXATgEuTz^y!@S+^f={$}Q(5?tdlaTGh|o)vL7C5V+vq7aceXxxovCrzGpOZGK3ro*#yR2OP zGhcf~)$J7T_KPo0IB^QSIh0#4?@7ysJc)X1x4jc(@4r(lNwJo(k=;-p9NRW)c9kc? z(kVe46ZJsgayzOIGc%5W+Zr`(P)oHtp`|rg5wD_|9aN-18DfUpO&3dsh zWsK_|zT;i>_5KXU!yn%~Zo9VY;aC5>6Fsbx{_Opkl7Gha2FD!rsC`G{tDM*@Pww2Y zt>D<^-u7KjZu?w)zPcjj)wYEq8 zyivte+i=fe{iNHr4ew^S2^+8c^}PIS#L_9p8#*TaO`lqwAtBK5Qs~pv%?G@N)9;!- zdd0RQNy>7q*3SG0(KOM`SvSokt}}>V+rRf@PBByO&q;IER^Dj4`M~5_plbcs1q!<- zT)AQ5-5z-GX6{_T;VhfeC3hxeY*T1!vE4&&$%AtKPcu z$$H7v=fgkERsCPKa@DrjO4Y@Q%wFG3pQn0jrm{?be!X>i^^2UBY7P^oT>5Gizc*i@ zXQ%4_Y4N-MD-(@b~xO^hvyp=_IWp{&^2Pb-hX-KeWDnU%>lItIIc2Do18b=2d-(wOgkZv!4^bu=eQJ@>MN5u^(2OzF)d%zy1A_^X4mQ zoY8ZMPjN_J`*h=1{s&SIqEam@4J8cQ+oKKt=E)Hnhw0v zeNh%I{_9?FsP4B{-19}+9Pe+qmX#WNW|_wJ4!-0N+XGR83MP*}-4C{%=yvi~x%uU~ z6zjaY@|wT%Vlpqh+P(e!-2;q1-Hu8v0_9$s*QeZf;JC$Fwtk`0`tfgq?6r+D^Nx`!i<_F|Y zS~S_S&-1A6310U8RbKwr)}J||^RKGbwm-i{V86lThO$Qwxo=p6R&V?t%2mwOd9UEp zFX>r<0qY&)qW?3v?VUK|?Z%q=+cvlQbK0X5-cGs^^n8&}XI%Xx!~Z!JUm0%mW-bt(~z)wp49rpPnt0_o&ONF6h)`rw;eV^Nq_JZ?_6q8?K#K zdU(o=ZwI&BNU|zW=6n#ZTKJQx*8AP>m8*J}PO0Zqym!om=?CXBKXt(aJ10FCYsqZv z*4^-s?NQJyf%o6ycChW*@L=El9ohfp#w_P8-P>_ft~@V&X@G5TDah2xth7^^!)svor352Q{T>(p5S)! zM!5UKo41G;&!C*qn``E%(^Mt(4hA(W35!!rqXu@ zDj$^{H~zLYa2lWM$~I-~{)yA)oww~yTlK_$Wys$0@6&?b2|Jar#IdF&cpW=7^|p$5 z@ZVkav4QOCcljmGO16-b=*m*ln1)Oq@PhsJETJ*g?=;Vy5 z-)>iw_I-M8$f5WwIm?)R!`@Y=A3go{vt1xb^n>QIscFFq&^2_Q?MKx8$`(v3BewlCoba%>5n|&9rEDcOw z{rEtBAZQ@v^8S6I>&xb?sV!#imWw&mto{CIK+cnz5T)Z`^3VUJmJ4rw%hN3%flcmB7Ro}NR zo^Bulio#Fn;YLrJJGV&RYHK>fv`H^*dTw~kiswJ#)j8h8?LPgjbm83%W-6@(+g=b9K|8B;lt+Ne#*Hn6F zre8Js>FhOAdFdY?uS(%%g1f&RDDa7OtYWkaI(04R)cN&$wp1T2^z+hmPh2G~5x42T zfDh};+ND#z$4V}q@@d+n=l{xhAJwkAb3W(7*Y6CPPx&-c%MYx4V(EL#9(g!SEOfLwVxpy|Nhb158ord zTnOSS=3;zdzubIxy-Dr9OX9C??*G70``+~I+R1L7mpWB0J-U4H=8IF$%wDb8s^HT( z|J=1NH_NW`3zqEGl~K=U=Q8^IvNF9qY1{Fj384XEr$3~(J$UrqXZ!8l3pQT5RGH)+ z)$;q{{hR&Qn4_lsUGt^2>I>_#^_L>0Tq|8wwEa(<;JErhhG0@Xn9!) z+KFSX%5NQRUE{R(wA{AhjYqF7O}-&GV_rnjwPTiNk| z9F@HDkx}0`cm4A#J#zB)#EJSm$xpZs@2Geqbl>-Hr}OFl3)x}(R=#ge$m_3rR1>1) zsXqB**7MM^ofUsxC*S>u$pPzkh0|II&^d zlXS5KS7(alS8O%j`bEs?!Gpy9{GF#S@yYQ$QJJk}RD0oja8Z!Y>Z$LevsP_-BKPLp zl5#!&HUFPIlfU`#>blo)YNAdCzo%Q@{Bkht9^d~4v*swnZ&xR#PCv-_W{$LC)}TGd>)P zSTs%k;dS@vA8)OgejzH`@RhdS#uDCwg=Zati%OTS;l3Guw_I0Wu431rw?__(ufKK7 z^up9BlbFt(v-1-@H&JSOSmKk5`zPxg*Uxbaj1zo)|K^!h;n$1)zb~I|JFi5mbr+oh8!Jypug@~=+Mo3GUI$F%Fu z8Kz6;mu)V;SGU==|Ii$#N6JDScSX-n>)&3O0a`PXJ8Qed9qW!QJ52i4*c@9b?7618 zSXpZAOV#ZPs~eiV`6tegY%uX^aeE;3BIx0by=f)Kj~%>~vvF4Qx=AY08|VD#sktO< zWU<+H+BsqCFw5}JK&{1Y45CYC3ON*lyk*PMIt#TF2+e(yd;_Ht_{_t|b6O3ZF?ajH86oOj5P(N~X+ zduy}0Cb;xl@v(b%=Ux53ov+tT;D&9(Zt=5A-afd-kg;~_nIDN#xA)!g42&~8JYUkM zE)BFWisRr!`~J=E*7`==jJ#Opk$vpX;zt@!@6G=%Y^JxxvG>J~(oe2ZXD=rO>@@r- z`EyQ0y-+s0wA)^jJC`16^iHVwc2a%&p8p?@JL}4JTq@yEjFbA2u-`ndE`Lu{-8BwS z5nX6E*;{?m3oFw)UG{Ww|f{ttzDYi(b>-NWme z=%*Oev^MzgOzs`e?!SIn=pMeu`HIZuTRXnY7kTsh=0lTH58L_{>tFeN`fm4*$GdM! z-_h6@v=zFv^Z2B%oMK<^1pDU(DmQdpI&*X9t;8$RnrAeX?35ZG#5G>Ozp^j)=Y6wp z=WhGYziB%=^%HwR#!taDvTI%zd8dO$0uM0PO8Xdoe5O_RK9X;}&9S@O>7bc~iNT;O zxy)|;x3D#}#mf6+YqLyO6};$Q{AAgz<;(LE{RHnWD?NDea$~Ih8`IN<(zBc1IB`9` zeDd^)O;J;CmdurkTYJ<&@bmY_vX5M!dnT63O)lEH)c@bX3F>S{@8TEh%6461S-}zz zC~_b~r|Qvc^Nk7T*5CP3zc@Qar|S1~>zxH(CRH|1TA+Vv_Or95VrgBGQmSsv8{@2+ zwn$%E7RC9Xf&Ev|l=8i1ue)|WUG{9_x3j!Gzt7KL+n5!fDJ6Ar^{Pc0Umy0p&r{C2 znfU1YytO5M388X7U)OC0ExTuu=lwHB{F{C1$9Jk%OUv$C+R1*r%6ojy^l8T@+V@|s zF5@?LD^EW6&e}aKDXjIVmDgRXJ)b1{yE@3A$TuTI^1JX<5GU$yf^kLXqfT%|kyPqt3HfiPz&*{-t(?$8iMT&#>M|Ld=@#Hx8n z`bLv(#1>BDTYfY0+ZnGE@RD>oS*m2yxT9WIrFDbDr{TW_4^y$daDBCJ}}T%}ZJ z+uw8h^fDyxXU3$ZhXZE`f>w+K=|*Ymu4B}TxcS1P*Ee{v!`B6$mu%qL+bP{7s=r=M z*KV(0-`wf*{PVKn=F03=G!l{gQFbcE&BnZC!oyr$*}h9>Ru~y{Eee@^&C9#rde_ER zTep7Mzn_1dZj8XJU$6P^+)0T$ap>GpzV8X zXPB#2mh!;)@2PD!w?AO0-@8vPbBc%N#i*AOpHFdA-MiVl_w%>SuYcRx?EE@$SA~^W zaZRqt%XH%%=@)&rUU1&X0rp4oiVgZ}f3YT~UN3l7p>?+V*Nuf5UTeSX*({ygz9sGK{_D|JQ`Al$yvw(p&Eyxm zz#VOYxutJ!UC!Jhb&EIG`Sm|t%Rj#bd)Sn-|81Vfnct)9{f}YK?P}19r)OL{51u%A zQnBc;W7WNjyyErgIdenP`HvQXCWyV(a`Yb9+RAPF{>`z2OWO@z^-kkkdD2iyWnwp9 zgjEk0k1Jaj_m{2r_ABh3@Hwz^%d7j7w)`mhbmRMMZ z$V~B=#eYG=rdHXyCkY7Z+Wv?`} zc$-1%MxVBQ-M!sB@HF3Kfl9f|kk!p+T{#Z=m!I2SA|Yz=)9T`;^0Sj?IQD;e{_MNj zhgY5AJ3jxuEhyC(JwduHi8<1D%ib8rGDS&F$vHO)y86tw9zPm+^?R@sA1I2G#17As z>)CkYz^wl(EE}IKx|liR+tU#5_P~i#z#C}FKXZRpU9h^oRWM1sK7Eh#o*UagygGfS zx7N$CE{*ZxYk#5b=8c8_&7)#Jg-XeQO*C7}zAfoQGV_nWt@fdF9gJ`O*`F)&Ts+#U z$EYl?476N%vuysSdi4!I5AVPE>7yBF?{JM)Ypng7r_-y&X1|sBdUl2Rr`O8foRSy& z^0v1{TgkYtoZ`hG>T0OX?$2Iz_QkoAz00LT9$ktkoqKDi<6oIpfitsrE^zz3MefF` zQ%%?2wrzWOvGjZKy96csvoQzmNPf25Y}+?cpNI9p&Fh^F>vZ!>-c%L;yTJOdqENK_ z?EJ=9;d!@LnABwnb}Z6JyS}K~zPj#~yI&FCH#t62EtxeTQzp-;c3z$L`q0_;z6Szw zR$Ob6Unpp^C+nQ)_K)13Q=i?*oN6a#Wz}-wVsG-)4_(v4FQ=FJ=hc<(S?U}()aR6zxD6arlUJoR^Hfo%WMXpSep{_C5^NH zjHNy}#IxC4_`d7*({!;7udeO~wLL>``)8VfGr-)JWzph&`904cU+jKqu-L3yQbyv- zH~Sm=xE4HHoDk(JsQ9pzrPR>h@aekX)#mfPy&~6o{(s3S`DV8K$qDMa!aO#dI_-Pb zHGS>jV=G^&Y}A`;T`|wt`q2y9)$TWISEdJTEZ=_o+|_eRhOsYy+{*ZL>GP_;|AS-q z$=0sheRiX%`i8O%X)l7CLq07x(E?WxeoIxXFFfCS-s0Qi{*pc4<4VfD&NeynHr^xP zEt|r6qhC)SKC=wyobh(!GL{b;87+QVgzfUpJb&Zg_wRxV78+@7(#vVrT4n`{3G(Zk}m;i<=%X*-r0MH=V(!PGyRz0*L6eWm%q$Hx|)KdWkM^=s8}rMUXJGgQ5A{C;1b{OA9-ch+{VwC?}^ z@%oI96{q5r3(kT96OD~FOtM4v)v1oVp-fvsiRDac4 zkcw8?6`ZC^re{9?e%#0DlnTqFGc3>k*4TWS@g(|O%|4bx*3W<2KCiIRsd-~q zc5c?uZRhQn9~?L}^-b)K30v3iJGJcl{q)Pf-?#7n)A8cMcG=`QJFQEpA%z969mV#1 zab9woWA`6h)-^veL_eM^?ESZAp~ntQhAxkYt&%n~z8!AAenW2dB&YeW*B_rc!67hA z?A|1yOYXf&j~8__+}K`W_}1ULx3T=L>-^X2l*>OqE0``PcrE|u$FoN#>Mibir@XuH z+TP{vyLvW!tgLzR?%dV^7k(ey?#tGL`BGxt3m0K&XlLmHa&YfJ<~Wt;N;z1 zh9B1LzVYp5x=!`4Ool&l{Cv~7Uw_~H>3#k3_odfecRcz~aLnqZ$%e|id1vnjALw!4 z*HI#wn7B6e-2G>pt1HFA_ue=&?Wu4k1FM5zrr4vP;FtBk-(BVK3m{hD`q_K&n} z>vCSd%d9xPXU8MIJ^$VI)g*~6zgwXt%f3u_vOrZ+-o(duJHP9PyF6jp{BibKk$3uw z&RgzPj`eC?V&)mKzqdrPcU3~XVzyoUan0#pmZu({CUJaXc(I^m+)GIZ!OWnK8(pV7 zed6+D@983b!RI<1C#tWz=Q!~klbB;z`d>q?_P58b{#RnlR;}vt?Kt>wRpk9fUG@_< z>ok}|uZql;XkOj8J#+iH^G9OesBI1QzVy31;KyX)c~uOqOFVh!-|0O2*?wWdTI)CO z@2(5w*}FdD)H5gsX=!Gb?2jHwXnpy;%jnO$`9|;m-qE^!*YIw{_r-~iKi!Es$Ff01 zeY!zK(s8T%$-g%>zlq52ue>_#$UNtl*RGzv^S#e*!Y+*k&f)f|KT}nz|9r9izC?Mx zN)b~4gUCd+)SiXkB}>^G9^X7>xx2&qY1Ev~&f_I@LAHG_@4eRX`u1L3bMdnU-EZXg zFIlJA>HW#;=1%kGYlqKUE&Ijb6nk^q_IpYfw=90W;`1w;^8dR+pS+21kGg(q`v2P- zl;(vkR+lfXJ-%z#mi23T7Ol~Fw(o~~Ud?BtufIG)0vSXEGaDv3$)D3ZF81%$>ABP0 z-yQ2+(!$Yj?FhrXsPnpKwGU3cwftiCtLndB6Z&LkJi1+~l7D`Z74w4mANUJCiim8; zKPhC>+WKYx7n4@|POB=m0GA~*yviB$a(zQjPnGhQPW|5c zsR!5BpPhN$w!N@ry?o+VZ+*iDeb%dL_C0$#ozdgfjfv;d=bv3<|EKZEyStuV{_4q> zmPqA3$-R53ZTtOaUzX3~ioUCKb|TY)4v!fT>&4xDcxKM8aVpxLSHZ=tXS6^FSZ#BQR?C7?)^XvV*+}J9kw-ubS{l4L8{r~A< ze}7H9w%;CP(CvfGpbQ(T_8~9pX!W;{pL;UC=j~Bd<@t3~pW%au*rY2fh5y!nGp?(6 zGI0XqhSYvJp6VYDH(b@Z6!TJSgGuY9O-ki&ouynCMZ9KYK5=)CWWJ~8)VHqH-vs7Q zV{1@0Gh1U?YV%s>)Aqd7hwtmpH$FXmFskeOyQSy1Uf=Ziw0^cseZkkPUw4bRZ*q&Z zY(4jCl2xhF&g}5InlFLdYJX`muus!ZKe{DTw0_z`izJhsn_H&ef382@eDgQ0kBa8}d(fl!z?plC<=*+IIfaE0 z`{&C|k2{swZyP4)cAH1;%!BxULi>+5Tie^`Z0)?VG$CJcT}AlBt=Gg~Mx6o&$eKMm ze;2_1wq~^!S`{8WUVJGueB;;0{U4`J6}-MmbZ`By%Nwq4 zt$!Kx?cWdOV=tFHe>%N5<873i%`c60M_j(?MIBklEA5eSoi98|$uj$z!JF;-RX5gF z7n$cidhqIM=(La7UbbrfX_wjM6M7ate{yolo4co%@!K7kI>F(2;bQ|ob=BYBH~(5X z-Q(@$_8U{4Z7kd5QCDWSF5>z>kL!UmnHHF|o^3CCcI?;Qe-pGhI$T!Yn5O&Eu26}A z`Tf4#$Ntrs-G~Vi8$vIwv@ZWYcj?8NtvAAL`}feWbb| zd`8#Gl`7fNnXyqJ^klQM1tFr?3F&-8g()+0SaQ@SHDgUGOy=Id_P2%7BdoA9QAo)A&|ACEbw%!(CvtO*Y zrgn?ALrk|t)z?#x4$LYy>`RW${vHwedbxL$rtam}aa;ulG~{oG@9iyYE&pQdFvouW zKJjwS^RpxWDtEbc-;Yg;EnMe1FX;R|kLy98u;t8t+xFwhkMn81bBjM7Iet9*TO4Up%=krRCDwE8j}2O)rIBS$F-#w=Z2Kf~6ksZ+Cs!H?ivbl?{8k_3!t8 zZ8SFBqZp&Kdd-Qm&-?2lqh`hb>Qes!u-l400X{iVEj!Vf0 z9A3`ae5 z?0?gzEH7L4Yqo~(spx05YWrO8T-d(8{{5wByB&6cmk-IzkD7Cv>Aao%PWdN~=e#^J zb=mC*rLPZ9e|~8D;PBOBo~M@VVn2MMGx_|jy?d%}vmbqzbe<(UH*CpkPFKc&Suv3l ze^1NhE-$G}e6;#-Ufus)M~;MXPSo@4o1}d3!mno`UE)(8ocr=X`-A%~m5Gm=jL&)= zdQc(c?|tA%)|Nt(i2qmJ?(KW|H_5;Ad0F;b{)y|Bn{hQ+V;90?|NJ&A#%(y#8<P13w#$0f&~RL z^ST;x)}N1-c{?4i(kSmC^&K1Vg`-G^q$P8US3sa9~Q;VxU)4o(5I+qiT5Oh ze9z9a=g;_b{i=uOuciaEG3fBvFayspC zT_yCVtz6jtFPC1<{`YnL(ql8?uH8E1aa~18sn`2FgI9!P`{Q?0dV0$?K_#5RxU0}K58;}?O6HxeZ|7KD8Y%s z)0jw#gryHuRz>cgzh-Cg>KtP~^^du?CQO;<7n7B>_W7>QpHI%SpTB60&Z$qII-F?YJ0M$r;rDWT+heN*1O+XvxEhok56f4wJT6K4Ti3N|^UZHJ(^JmR_kY*M z+f)DlZ&%!|*!wkyFD;*UXzB!q|MUO$d@(+!U}rjY5;OaW`@5#f#@Dv)Ua-LHcI9mI z;AxYcuYW$j{O^XuC0|}N-hZ5U-TeNBpZEW#-Mq3=WlOgE^Z9>Ngr@63Qm)F1+ebPr zV%qaQ2EMiN z{0(1!p18e7vZ3s7+tsQ(pQ56v>o5QMx?1qxsnY!~lo*P(=N$a?mv>#Xi^~%a5eC;+ z0=GA*GQ8VkqhR20WahD^EQ)bi0QuiYR4YF zHtFx|{6{_AkEc|>%k1(N6ck+P$QYpV;`HiuOiT~gr@W7=$unoL)!*IImp(7DFvjWj zwmIM5?N0HVf9~DQ%{RBFa4u!%-}L$Q`kOz$URT+Yd%EMe+~U6<9+vKlKe?~A=KqJo z5%c?l-|e5j#Bc7bcaL0LT(kliL{=VqSadP%g2E)L(nYshI2H5HTE*y9`OWh=e{%B2 zY8#nb8ya(s(>DCI|GzNhf1Q}k2L|y!zwdA5`=fFCWa78j^1wam{I&VJJc}8+Iy@pY z8M;_{>;M1Nx_scubY-=+Ys_pHstz!){rU5}#wt_j-lL>#b$<;1=I`Ho?BlyXHP7x8 z^RwRGe);t&ZOf4WlcZ%tEt&H?`bp*>-arAV$bSfzc zJr!Ya?YlI|{%_}=wb9P+wD0VkoIAgs&*60=v-Y;?uC5u?@Ap1g6YIU5TQA{;a=*r( z&JK?wFC-l%F5dEVasQ1^7u`Wg^NL-q$IENH`>%W7o2L8b&nxYkJabvMz9p}Jd=!1Y zrt+yM-?}(nhrlwk&F}XZr`%pVucGOPS?-}CStTW*yhEk$qd_LaWJLS#oc4NDFOZsFx^Y2B0G0$@#F@3=Fn~K%B&8Y+SzY|!krEsj*lxoTmOCU$74UXHM7s2A*QPoJB_8% z+sk4{mgwua`n@-P)zojlRww#$mWzwl=4<;hdUnn~@VWM|#U1A#=1e=Ed1k-8ymd}A z%bn~VPY&;mXJ>$#Cfk=hkxV`_=WG6+!t-p)KbNfW?J4mUO7WTb^>_UTG4cI5Yv&5T zEOK$l+Bn&P;SEzlk0f6Y>nDycAFiH^ioP`Es4Tw-gR0V+t=lM z@+Sm;*joRgbmP`<0Y6q-{mT&9(9zK$Bi?lRu#M+}=lbmj9QYgT4qjh7amDM3C2|ge zf`Xar+9Z={Z8N!|O7)1mHCqBOW>cQ)RWS`v~ zVMTKS7{Efaww6hLkZ0Q7BX4=>En0f^XmU@d`i6P(2aK|F4AD-Xl@g zI-qt#hsWDBTW9we+Ox(fUf`~1HB7T>ynT2r=Nc&^DUXLAz8D6s-pJm#gz-L`y}kU8 zO?}DMAy#ENjjXdl?XAAft>2Q9&wM{%@*w8HwXAj>wtpNoGVgB9lI~>^6BL}7b~Ng@ z`~jKAJF6R4D;Auden92o&I4iDxrH5%?HTMWzGe0Mg9EL|Y16fL?BCpX^*vj0lieY? zhdIML;n{oHXts7gWDvW_=6oX5})N9J|9F!!n2S2%C9y z@)^DdtPdo!*Qy_>{4OlP`Gxa?_XGa}E(_!v-#w{2@aw@wNftRVS>J@tnKsF1_z%>U zUioS}fiEU|ZEQg9{d(r>to!$zh}ymC*1zWso(D{_-)`}`{hmpW?Hto1t=QLk4^khT z3~)RvQEdJ}p>g5+a_0ZCIsczL*viKg#@1iTxSw?$Qx&t{f$W}}41cC?{kHkmy2wL$ zN{#!sD=A(2^Or$`!E8}Fqx}ZX6D(Yf^9~3+IDa4|`OFIe+nALO=1hujZ69zcaLrp*g?H(kFa`9na$F+p=~>w&xl z`UVU?u1I`l&wl%V_0w6dE-p`4E=^%H(5%qjWTxqE@t^ZS{hF<}wen4l&2dZka*l&( zadq6fr+-eeG~KPpej9$UnD+tCzI{Flf6g+iMP?T_AK${3#&X|&O5_340~QOE3?!2; zaemqJREQ((F$c@;Pk;Y%wCoScVmq$hXuf7^^y=8x8y;-sW32OgyYPz>)BakYE!XPe zenvI_p0EDlxhemSi&3*9U)t)i-D8zAJm$0gn%mzC6@r2jg=2&LSpF(DGKAee-nGkb z+cmo&+dr(^|DSlsDf52CVovpf^2#6F^Rm}&jeAhUwB6mi;q>Xl@gHV1AN*^Yr_X+t zYhRziF_rLJc6vX4X%z@qT$T_PPWsQ3og29|`&a$d!|?^blb8JL)V|A-s(XKPo9H6*Xm_k~`qclJ;a>?_>x5n7u63TTadI zkCv!;JIADT4+DdAi>HfYNbGUVn+Nu1-!xbJ@oV1JviPrauier~KEp0kH*fu?eQ%G= z&}GTHIM4HenUM@%MZDk+-D=Cmxb3W0znx#RIBmhT?6;XchS#E`A5Cdy$t!O!3jOeP z@q>&N0r%MD)D1kBx!mJs*{6Pd_jyj6;^=qT5593+Rq|bL+_;-(s;x(YQ>~@pU8X?)8>8H?K<%S)yCUy#^-YkPdGp$>q-3AU z6VmK9ZV6ufAx!7l_14}A_+a)?=RwbdWj+t8nXX6ulYimgyxw!`mC2#*YoG32BF=8# zx5Tzl&Q(xQ(9+TLG=oP%!BG#UgZY!TZu9bwEl7K>?KC&SGxqb(rwp+xs};OrnIrZw z>KGi5xZIbuy}bFg;5!yKspLsoZ|BP{TK>+Q<c_9|=jAHROTdZ@o*-E*1O$-Ir(o?EZ!qdgYxaD-Fhz8rLnJ9ZoN`&GEdFGX{GvyoUJP}wf2W|C!bltwr@J93TB^` z%}`_g!|J4j@m-1H$%fB_lFtMmhkEEFoi{&Llhw2HszmWd!)N*|%O?C>HtqAP zqfxW{6ZjnYKNu&p8a}&zY=(Dp{j%?p$#IGX6P`@xt<(oauARyCbcT4QHsKedyET3U zzKdsB=B=4=LOLRQzQM66f*jT6?DnT@JrYdb`M+J_NH*&Apdb`Ikx9NRg_=P=F5BzD_HtqKAdZi6YTrzcH`XRFAY}F6XDH&Xk z|G9PD=4(;OK0mjx=q^oVooD=kK#IZQqa`{TDPY zXh5(A6~uZuY>I??#jHS ze%^o};H-R67$vvBm+`p0z#WILUnya3Gw2UqUBb$!135-v{e?6-Cg zHhaxJ)etGD<$maK{YojO^yutv<zH*H4Lds*E5}~n_^H}vXWja8&JQ!UZu6|#)?>I)=KlT}_xabb z7&X{4wH}-C$C}~sM8C(rY zXFCj^Ii<(kv0nS@Yw;CnPAv1}mTJC}HFcoi+RQ{p}fno)6E>-Fa+=_u8%9 zQj24geX_%y4&C2SW;5ZMM6Q`|xcjb#wxVOlrdcE>i&u7az1wzeUEZ3qUchqV& zop0THI!Y{qCNq1Snq#P(`7-|Br>Ta^rf>b0;4EcwtfcVRQQh}t2U$C9_4nKCOFchN z;`qlqj1@_mr_TA^`1^Kya@gJvhn$knh+eyOzON?it_ZYR37u~@=i86RoS+)sy{xY{+JeHgK(&q?@PoDB+a@&@~9?wrxr}oMmyF1Syv3Ja;4F@BZpJ1xJoVNd2(QKlepE zkc4sDi$MiSL8}+t-F@@Nzuyc?zP)lic2vCGMz8o7Pmy_^O7bO@pz81IZp<^ym#Y@n zTXHya`9!-kpA*HkOP9WxV>x+`ZuE)Un_4&BiHRzC=To#juVnWFrb)ZYa{q7(Gjwg< zta<9(vAOg8b52iFDSP1%R8_V2+*dL26oZI%Z~>3Mat-U+K4J^H?X{igi;i(J=KytCw68z298&yp`C zRk4+-wd;1TONzeu?rx1;Wzku4!?qvS)@B+PDAcaoKkphdyWH>AlYxN@A``1VR@CNj{qxs7pYOk4I$vdHcDT&OjZ>aJDabg?c5UxRHtY0rDHrtX z7BbxM;9DDg{LSunhu)W6t~Au-@XLYwMP#{I3J0qmSM$PQSl}?z{JI{{IKxs~B&5 zKFmMm&3%8T+uL||L;EXDfYW-u4|cQvL0Fzy6l|^*a9Y>n`n8Z~DEx7av{`SR!FLNmstM zCG1Rw&FOh{Qu}Y8J+S-TqWfpfuitpDtI2tDb#UafFE1Is?06!yt?rNE%*)HeSq|Ko zBH}mSYU?q}`~RPrgYraNc#LDexBlAQe

PVD%RWMu!dC3k+U+y2>ktIj|5l+daD z-v%( z*Z0p_lDE>U*}>&WM+_(Dm;GPE*4#h8>iPWqg6iz}>fT9ze|x^ZzTWM}>O&G$ab=Pp zGc$SX{2BLOk1nj<`#g1etIe^g6C7?UI%nlBPPuOfnyvPH`I2Yf|GJpY&Nn|kdH=~P zUwmc8<~-TT+2)t49yqYwDP%wPa0SO4p~`!Yl0I$EJ8B`55>w=PA~|W&qzvN~|4ysz z782HGs{6Ms_lNDgV;Z4-4vYaVuT&pT^3J%p(>SvDd0S1{n~aq6v)LWyOXp?uTw1d4 z&%dtd)jy-R%LNPHw)-pc`upYFM=mj)oh5d^bME~7`DUK+@<1;g{_4Bxeku!dqi^*~ zI6gc#_f7n^HG#LLw|%VM8?j&h_4nWnwbhHazSh-aTi`lfPfA2c4V2&Y`KEU>mfvAK zaBBbmzcX%ctg~m`UB)=!(qi|;SJb{f?&wwB>Mzd__U~=}o4+63*W8c)&$edm4%^$c zhguH2ZWU)T@zS4r{%zXv>G6*`dY7Kw`JC<6e2a}2Z%uFO_VrxoI$e)J=l|>Yo7*cs zUi>S|wNOL5yEK0fW5DYi#!ElG@GR)K5`F#Sd~0C%(UW^2x!!qJ#1adIot07^QXD(7F5nCf3?9~nwktHQr2SONlLrZ&L+KR z=Fc(+FgAEHeSgY7X8sNN7nQ#0M!7iM-nK>BZcf?ZwuyFCCLh;EU$0uXe8YtN=KUT{ z3V%f3-*nFL;%a`kyFbqUZ>EKwV*vkx4jJBLiHhs73~PQJw?A-eao!=+VmdpgJbSX?akqZNpCiI&W*9WG^4odbT+hT2UM}Zdwf587`$gw|RP5@JZr{G7Wv+3$*^1gsnU~4O3f|q$zx;B| z=7M9#gE!UN-?slh$F<-7+!t=W2krO&u1lIyQCc^@|4y&8w%w_sBBtAW<34T6Tf0M4 z$JgJsL8&O@((#^!XCEAtiP$%1?&h?MPv;c(z4{|I*E(5-Z_R!GkMnFrZ9RqTK#TNV z`PUzMUsjxORf}(3jOVi+Ns)JVPQJUjS@Xuexu5SpexKn)f!h*LI5wUtcBqa_O_?`F>lY}Ec@V?)6-)9 ze7zpJZR)cp8~&X&zxm_cZkd>^U7zpOhEJ|(Z)eX?S1(f7LyYpVWLt~p;G^4uyZ zN$XjoHjf>*#>9smy-V+|Tz={Ov)MC0JZzuy?@BPklk~J}FV5cncs2Zom$#>vfBNz8 z_>E5w^K09E(~I$liIQ^NUA{U0<)!3ROKS=|gO2y*{QdD*>+SRWyIsa+)0nlx0yZSO zH?Oz8C3*efKKXdr#oKFBQ%(EUpOcjK{{8T<<3#l7WA52{*b zUz@Nw&3A2k+PN8lAGteZX5W}1k~C@32NBW0ss{|7bFEr!)>XWZYpBxa&yeBUUYt5W-MBxGii6((<#;Oc`JK%FK7TI z>~H7ok{`@1zqVtmhWm2Y>3T9z`{&*9ot?$ou=8L%Q{Okk-mt&FuKr+MWOr)5^c53> zhYJ}rl#Z)xEzjT8Cx5E894-}rF8-st0Ge-Q@h#`~{Tv(L#`^~y>YG4w58(Xr-%Oz%_e>H`lC%Ez9wZ1+n( ze(hFW`+0ly>~}F`b$?B5vu3JTOzB#gs^+(5^IzTn|I964U)%Wn_j^zKzhA1h>zkHJ zSx<9*eSP!8x#ce^p3O96`r0U}ZLy(9b=?t{TfEX?8}CNPoY{A@+f&|HErp}}`O}Ge z6Bq-&zP~V0+<(8GTAm>`Xa*M`eX+0j>mjuXXiv3?)-4^MfvBmJA{NIe}3P; zx#pHhnB9LH&AYoNUsxymGkSZ_l&P#NRq`fZ-5+nTlfQ5KMWFNT?aO};af4PfJ;}TK zq0;6_?yV!o%I_^KcW$@egbefj-#|m%nng3VEPrR~G`L4R(lGOM2RLb9Wt=}@mS=wyF!}v9l-$i%3lYU-EE zUIYYHf9Kn|-}U*qIW@1>zKPw!(Xivn6{+91`DCSjiA^^AvhS6aRgc`+W99c%^FOD3 z+Li~Rgl=tLe)z=1lKmf?cFn0?m-pRN=yA!V#48%#bR!Sl3XkWl^l1-Vyz0#M>3{E* zPm#0n2wLv9Mb2Wwxo_6~yf1LEzzgl_b*#)wTUU zpR9#LPLNQito5X8>*G(PvkBkYn*63)|JsdrJ-w24Oxd~JXI-u|h-JZ)btSuA%#bn+CJKQ-_O4Bvm1EnkINx08EYYsKy7BCew}xvLC{29$x#Ca5 zZpGY){rk_n|9ZhEzvjKI>VY)9^tVw( z*VmUb-Z$N_@@BQTUdhw+G&8rzOD)&-er&rfC~bW|>UC#{uCJ?hV~2_GwOhT%W~_d8 zull|HZ9Yk-+ltOn7Q#Y4OI}Z6D36<0|GwW|>}l@3m?zrWyN^UwFIbpc)!n^5?(ZS) z?meoiANQ`?q2!i*+f0AorJ%C&b5BpQ|GV>i`~ z;)mMW#g>mBn^$phzu$K4TxO5iU%UICkIh)iEnod6GCni2%~;QmzsXGaTGZq3Rcnpa zo<+~U{nt1<*LnWu+-o8XuCpYw-_|{te~{nuU}Uy&W8pE0$KNZg7S2C?wv}~LEh}rU z9mj#F->esoO9;RJUS(}k_Pgke&9z&1C+aE1d}(%bSt7aNT2w;#lGhVHY`iv&>9$gA zyNfz6lc3GIO?wM+|l>YVJEEKmwUnlN>peoykcMGlPS4z5?I`m#rWP;7Nd9t2EVyx zXPN&<{z!h}B@9|Sr}oMH!TEz{$}3bSth~I;m%U4FhSAe?9-(R=2li^uc-z$!$-iQ! z$Q|bcJJ^@`%oMqH3T)yz&wN7AnoACS0EV3_P zEBJdQ^KzHg`_+OB&FT^l3KvL!SiSP{vbX&13qclKGT`@_c}c87>IUDR{VOjoyUJ0m z$egg0?HpqrdkwpdY3Z#kbJSLaf^3v}(5M-Fse!%m;sN<(ezVOsZ%cm7({S(@Ph;fb z_iTJj@eJ{PbIo$Y7l-PAOm=_Us2Oa<{J8ORINM%8)f_{X5QdVkm30Ne!G^qqE=$2oU3l?#5%CAs}RxnU7 zP%tsE&@(c(v^29&Fg7&RGc+_(hy|;0FUl`1P_VH9aX|J#%ms_Wgn||HLy8jfiVG5p zQuC54VZzSA3i>XoWtqvTLGDfku3eUq3up5`&|#>w{^D%s54c`ZC%G$(gz zmg|!_^U5q_%-awD|J&97!8H2i!nO8p>oTVu|Nle3zy9n0*5ma*=Z9B3xWE7Zb?JXn z{r|Ua_@DOo`~7wQfBaupe(14%?9-3=^8fz|{`?^SBfjse_OUM&|8@oaJGI#^=v}ZLmcHEWg@Y|nV`^nT4d_BGM#dpGn|SDUTl4~jW| zy#BA>y!y&N*2=$ad3Ua}T-9&2KS)RAVYvU@htm(QtzSBaaryd)N6dfUs1*FsQnX#y z>ydo6bXUAVh53wM;nDnchjMkC)|81Q)jgdidr-e8NUl4`(*LW*)UrS81ap2Qd#pcR z|IhBl&#PXp^2N&cd-O{sADljT^}z~;w=emB?3zD6eyhBS%#z=}P6yZ49<}`TSbERB zxc@76FRf<{+HiHpt@t|~E8`0?Sp%YEHZPEQzIe^XcHg(^4|c`v5@YI4Yb<wZA=lHK#9H~yOSv*301 zqiZ|FUawuhZ0C!Z{hz8rZT)yl_;)5aL}XlNDwg%*Zl0$UQYaDfrsgdWFkpM%R}M`X>C;vRyYbu78u_L2c|2H_4P)YwG%I zGc8IRZF7SAznyybdi%wz7ha_L-@R0jddFD%!`F)FjrO`PcZnS9nREN<+Iap0nHGPT z?wDw9Hgj;b@8e@w%^fVu^kSF5oCB=-j1h~g!cIQpHgaS5!ZPQ&0na`$i8tD>&zk0a zsCn2hzv1Nd*4HJD$98A(*6U50>~6w3U2&U$ws*v{AH4UR&P)GjFkErNgW-&x8Q;qocBSf_)_TFiT^jUDK@h2)NI&Mda>`5?5FMZ zUp;P~-KhhN| z{ES!sq|wHGZ&nMm1!TPuc=9Z&_*!)HwZ&4WpV}wS_%|;wVSCn>i|%vFt|>ZRzk5Gb zacbFwTMzbxeSeT{u)4J?$5AuO)*w( z*_qDTQ-923@|GfXMJCo;YDrUd`nSmUw5@h8tPA+@lX+e_p zzg+aryTMEFkXp>+Xde#C*=OALBpNU;@O-tl{MV$M2R*6JF9f`AWRua@ThqfTnt5oW z*ny^~rAFCLcJRGD%&Avv_p3_P)BD*`b#9$YHJXXFx-)WG->*Hd=NYkj^$pgk6&iO| z&t};?fAfzxtujXw+a^i(+O-fjBJC|{VIrOJ$AL}O=Ltk_o9nR zuU}PJC7oV;Z^aV3hq~wYG`>x;I<$7RU##}+tiQI4XNRqx?b*lVtIeaCt9N9=vm4hg za}@2nvrWou{qO5?Yxx%ymE3;yX!GHkN2W(iUGLrZ>JZM@cJ+77Ka0oSG2ctHXJ6FF zGq2={vk`tS-O+Dabh!1a3~QR-wl= zoYHBpq|ZjGr)685Sk$^fE|fQ1>qvHEsk8qdsi#3qauMcRb~xNnx_zdy;9y{z(4HyT zDdpNyyXH%JD@`vv#B#qR>e+{tsl5BlMUrtBEUha=utkJV6 z?p)|%uARGr_bw=sZeQT;yFG^`)%otSM=v;%7c6z{V7Gk4gF9d{%$O(>GalZfoPi zKO1|BdYtv2&$jX>>$Z@5Q~Sx*djdWicfYvwnA_;}g)4tzdThV1cQu>0h zs?XT4ds@7}pZM#aHhZqzF)e<>&tI25vE}RTk9)7Wb6UK>UVqJ>kroYWpDeGqHN~dN zX42|H9*wKcC)Zz`zAd*wQnShD^!cl^Bl2|Zn_Hx}{+SW=^3o^1ozu!AqU7}RqU+cK z4^6dEE8DjAiDC3c%h%`5?7ZD$llVV>X}(Z_Enm{%M|Zj8SnhG%yBWZBPci(%d!JoP z{;qlC75A(n zViR_F&ALY$1M)=Qcb^FTQ~kX@X4+)Mgy|M%a-n5;KWyD{k< zb71U;V^P+92bUd)F*|7AG{66ULxJ@cuXtlF))^nI*YvlDeoc>7^ggZh>X-TNIoXe& z=ymhAop|+m(=-7$qa)dhVkaNFrQDh-s^Fu?zJ6WDv*P5OUvcV84}Y5TBs`Qdx>rz`K-e{EX-v)Ugwn0~rVl;7?!EiyQ)STor) z#qEQ(tlRNDd_HR4%$uL&$*@1WrST^7M)t(UGx7%I&c8pGJImYtD&$YrwCZ>;MKr*5 zy?EiTI}%?ieQX&$86&FQx~FQS=q=dr;NX^GU+sh=a~Kcn**-kdyH?scJz7_1wx~hU zp-PWjhINHEq-}*89~f6jHpO||v2os>eXB!VzVYTG2_Dgp@dr8{F|BK{GS~CywlnG3 zkYbon!P&6d)S;qxPWDq?=BT}L_c^+DM#ayVJ7e35FRzcue118<=uGM2W8s%^YFthW0$E&$)atX$&#=Pg3rHOB4xW0)0`V|gkmxmip#JJy*IOntGn#=JsI+=4= z&+A!D*H_2P=K{KAq@ z!t}V|M%jjaQWn!sfN`Dk~4a@nO)(3Yd2xl+Mt$}6Y~yps6h?|* zA6Yo}ywU!BY{I|85n1=WAKohdurH#ni|bjc(}63GFYNfZOE7zp%EQEmytNiOmYg$; zXJ)+F+1rZyicO%>Q)n;(yw(YMbF!Pb=cVUXe50; zk?*pL>&^2`syCf7URlWe5`M;ICs_G&Th77`SLGOE1)-Osx&K9H1Z|n)(BrdKqp`)o zoNdygy5nr>?2|IIC%^de##3JSlPUk9sdrd*&wH>zT!k}S+O;TuZI(rEgCN(m4?g)D zIM4S+>P+l174)5?^I3oPOuxWjO^yVcX(@*^igav`IY%8-IPp~^BTXb{BKs$kYE~YO zu3a^s7qaLDawgjd?Re{QFiI=2BBO!*vQFNa2g3TMLAeH{E_RP@tqA$5oYrf1|MN1l zOOIM#zuWn8{mL7!7e0Kk?Z|fZUD}>+Iw!15za?+VHA`rX0C$1zmj;Oo2bMB=3mclL z^(Hf^g}-JxED&)#&Ml%#;N2{R6~bQsC$@69<|G8MAJ%!aRAA~&fvd-L(nFSL3;oaZ z^X)KRemTCo_+!asY0oBU#u>~l_X}+Od6>!=yeGJvWZIgdz`Sbx9fgTJvDKMt?;o15 zx@+-`LxpOSUw;=~TsnE(;go=j;cCr%?Nes0oFQWSge+t8vD1+}act?t z6$@J`WoINvpRVNF$Z02&Svy5w23Nu2Pj7nU9&bI=_Q7Y<)%3J8b9&t8rk(j{n(_Vd z@8j9mUcaAl_x1lj_0L!u8NL4AwiB2%ZyHw&TYdTwwP^=rwk-qrDNBy|I0J9sfrYO(gZObfn;WFvkbCmbh zer#sj&QCvGTEX!QJyw ze%JXsPHo{<%Y9ib-?4b2{HFz5q@Tqf6^hKe6g@w$+2Oc*2Ua?oW=7rE+Wr$RT~G z^I4iP`OUma+V~lqb2c&FJbo)7UZGa= zg-8{@lB({7RsX);J6pbDa?gc)VH5sryN|D>{HK_CNUgil{-=YxC&7O9@{5weH~Wq) z3Y)xlzKhMT(jPxOl6X|RnV9bv6uS9r_gb?|aHIP=jZ<=V0_&wWev!=4U%M|)!Y5Hf}m?P(z54+Si&tPTp|M*ad)$P}!w`?2ZJ-a_S zKamky7Q9=|h~w|3FMghlo~vb@7R~-?^TO>^NBhjHBFUQ{Ffh%ScqU-$w^=P570)(Y z-tyYTI&VT`iie+T_=BG(L(U)5J`>}%g>9nAnKiCTQEU5|&+NO<>X4%J>1)&mXE!URA<@a-ffk-eSM^0`~s<|H~F z;4u{3FUa$~(J4D`;wI^yx>FBaJ>(RYoLX9Qe+9czL)tuHCD9Y=Z>59eHqLDSX6(cF zjZJAqM)~C4;?qJi*X+G&jJ*4z2!{Vp;@$7A9*L$uPdlA**mVEcI z_c1k|79+7op0}p7ni?#Zj(%C<+{14BjP*W;PLN8cuD#8ygl{_Mld^1$F9n_Y)~#?| zJhs@U{f<7@pI_&DDNF^~ssGXm(N6)f@981m^BOF7kU?*;|QJU89#_ zU7s8#XgjW1IOnd0He;Oh%u|OlF3!-3;NVF+^UAhTpsK~^@P_RQdUCG2IVKy4>3RG5 zB)ylK+n)L0}=X~_B?)vbu%)rs(Sp1Zd@j}d(x$E-wZr2 zKC(ZX#(GlB#fA4wjyqL0$EK^0Y;o z+s{Pm#C9(Yu-9#QBp1>Bw6Noi-0tS-oge16)T~YWzRSO%xV`a|ZN zf7}KBlhcC5E-Z6=z0LdK+AV3jvM-hzJT}z4vs=)^toFarwv+egtWGOD^meo1`Ni@b z=jVMmd^Jb;%j$yHbL`|g+iY`;)25hp9$(M!qE8yBK?pxlEBRw0u^oOKe*T_K zO^uqdcWg5`^j-YSxNq!#ZPn?xx>w5h>yEV!OU#&`xrv_H!_>c9S@6V}19|xuDqY=o z-SZG@IWWoV#8Q*f0c!tPr`Ytk$+H*iWaee~8-6S%c=m7M8ivZt78@2@xT!3fk*m!w zJ0qd-3xkkCvsKgrS+Cm(o>{jnzbgwEve@pK^QAK*&u?oS@4L9{ugTLUW=e0$mijV_ z&1!r4?q27G#~k<@nRB<@?5OR$l3(wa&3I%@>g?z_eUjxF2cQ4>q&xljS+)zuY~m}D z5?BTO?)sRR2G#5idZs0L)aJt~^Bwhv?k@3)(6XGl`beMY_mAoiuf3CC-g)G0ui+cs zcZ!D<92;b6g4VK1tWs&SPjHT&GUsEV-9Zlf$6}Me+?DR##M&(74}DF^nNl<7No`Zy>ib1ilPy|#vNv=F`|rJ=9C)Vn zy7O*J_0r8NPFhcUdibo*rCV{06aQJ-+e>cZ^t^Cza-6{W9flqIR8&H4^JO)JH>Z4w z;7{FbXTAL-TOjw;_ljIxy@?m+q~(=IxivKD9g1-%xNc?m(<-r9(fjd2fB&Qk9@$@9 z{AIG@C_U#&cpsFb-muf)z!XT_z1LDF*5 z4C;~`6t+EBSoR~mVYTZ$)!>P5mPW9D<6Gz5 zn0oU@Zcm@rwSVE=)Mwrz8(WUPDdcPPz2&y zrM|!wU!N(*_zV+X1S&SFm z{kcDVB{*u?l?-AnrY7C=uCyq9;r>qj*Yu;0G7TE0?qQW&uJH4Vi;i#9_X#|%A9<%g zD8AOt>vHDqnam>-C!XtP+5Bsl?(4k1vI&M=ajlAcy3Xq}x)mcH%-VFYY(vpSu2b_) znz1?`)8TU>I>YO8}Bhu1?v9=^k_j*?M3g;S)x9Kzq!3#>a^Y}9r3%Z3`C zIT{6`1wY;HE}!-zaN+jg^O85u#(_TEtJ7c~-?FvE75e@iy+#lEw9`d_bSb-y+z;!SeVMg9GC$!z8R zjGu4!7?mD6Tcn+OWYff?+pAXxGfX~u{HxmriK5Mm*$#xc3bKO zT$}TGd8B)9@T6x3u8S_lITXykB2eM%-q`oD;LKY^|NFhWZJ$``eD+!KSM^w-m9^5r z1|i{Vn-@vyR^<8JU$FMpLGFF5;n%zGwyn?Ie&~g6!p|bBgS-`2vTpx9Gm*h}s&?cS zd6pZWmTcTu+U&aWrBh6GyuphY`P}?-T2Go+cE1WvQoJK@g?(~Z;JpW5)*d~X+&<)oCp=P^d0Vq# z_D{VK330=~FMQwFjQbp8B)lJ(a$mI2zq#${p_E-3mnSLCm|%EP_1==C?FXLZOcXPC zmSnm!!1eb#2ao3*jp4K2YI1zGGPtNT@yQKKexBb#c|7(xfONYD*G&3LX5r6@|ot5eBqx{ zL_Q>xoUjQiN|=$tWN}_s`(%Nb`9|B!1)EyGEL7R?N5^S?x7u~*f2qHoWW75yeOKnT zrcG|1GMleIxY1cR?~J!~IbZbo#>`1`CQQGW&OayiO!L+?r3i`S#m^J(i3|J|X)9Xes8B4Y;(h3z-H~mQnP((eKZkGT z?$$BhHzj!*+hk??Wr9%_^AukhP18A(|17->d;gtst1n3$AMaC_Q}j@*lTr7hS6#B+aw$V|!=5=$yJ(n)SXZN9;;> zT#Rn`RQBW6eGMJulA0^`Kls%h`gU^ux&1zK{f{Ub@tsb%dZi+=s_vJAkK8Nni+$@# ztSzojG38$^6RP>mP-Ka9QMyZeP{BL1TQ}R!F|VF}@YKrfpWLewUbL)#D#3d~$5iaf zuM3Qssc#ExEIv-(AIz53`R@eD#4<31bZ29iFnJ0WA4pi*anxes*@v1QF zvCxVuuNNv={j$AzSvNYUCgio%iG#&5vwW7ex$3@H6dcd@td_&EBimbYo*H(W|U(vN*RcN`mDNI$qhbL=Q zUhjXuxXel6!7rs4a!-CLXg8SlINxyNwTbU7y0 zF>|x;N&GPVlTN$ew=mg*v$pxImN#sw47hdp`Z1>N72O@jSS@lsoGkgW%=wZ7gU_nc zWt-)vUi1%3e{}gOOUhF*G2yGBZ7%FVW*MI@30CL0KDFKES9~O`|J7Ihdx`1d3cC!s ztECr-hQDaqDUz3#8KxGr=hB{pwupt7YwoUbdK6&$lX+F*O^HdTOeWmi@l@>bod&H< zA7(7~)y`~IPJ93PUvg1wz_$L?_jz}3)BVzNj6Lbg+B(L`c0v1(+ALgK=k38`>iw4~ z$<^lcQ_h)zC!_x|F?$x<7%cgJph{IEH+yxwLRXei;9sU?PbU65TJYdf-rwDVh4U9~ z5MNS%Q?6)*@BdHDZ^QP#@y}aVcQbnGo~AO^6IP~_#A@dY}<@-{l( zU)*Iq(XnV{eEar)cR4f@_Swb!-}F(4|L^Jb?Jv1z7#C;9l-MnC&SN}yD)?XZ!@Q2w z2?xS7+_h$G;k~@|#=)oy2j9>6b|qwE*5cO*N?xV1JQMUi*qM2Z)R#2h+tdEfhGQJsaw{aO!}(zzm_}c*_Go<{w`YlcZukPEq{`V!W<(~o6Db1 z-Yn%-{`Pw9hphh!eYN*9)AtHz?)^Ufp#7_DDXAAigtL78Zic`H-n=dTV96ovdvz01ljrltuUfij z9cR$_`Fx9?39jk+o0XK2V*b|f(%-iplPkab9NoMA?$;MR@12DYx$lcNKXvD9`s(%1 z?%!_-dw=i6zG{9i5h+Q{s8AUb{Zl9I$i2#$Dz)iI&X>5*dGn&ZasHWRV`llAs?ANakMAb{&dic=!Q|@>6t5+qfRe8=;bHA@sBe(SZ?L+r- zT$%r;82QRNbzjfDpT7EX?l;@X3fn8^m;U)__Wtv_O1{rcb0(j?d%|v7<&5uVge0E7 z54$?^Sm33!Q>C-NFPPf;BjH~2Q_+yiopWB^>zcRi;-8tN^V^Rb2ih<{Hg(y`lcw;3 zYqsUA-R*NVHWW4)oVphfE0FM}h#~6!PUEln{Tph77#j21!|PXREeT8e&$MO6yqoej zA8l@JRbbdueCuTChh3)g?H3fg{Qj!)`|RxdZcX)Z%M112&(*Ja{U=V+&f@>wwsl@t z&2zU1{@BwgK6Bm%&)GQ(rCv^!^(wN+Gkm2VFm;t_aNDn4?4554W^Cis5K}sMVb7to_GL1AmLC#0YO&m4&))UD z3BS4e(&t-6Y4)!4c_G`ZuGTZc~ML;VWG-G@+pcX~U@-q*Te6wb&6D$(9j%2Dg1;8c3DnZK zuKqpkl}yGIhKRRt+3#pf>9#)%%jbH{m7C0Jny}~Lmp{_AG7nY0hTA3DPyc1c7NZ=w${ESZapq26r5j$HS-jWqy4%M&4}M-NcS*7gRGj8fc0_b$ok*vKMK;Uo zf|H_$Cd@N@`N2+buTa~nUY}JeCqk?arMy28q~Gd)z>)oola|4ZX;P`%cPEI7_WFE2 zdQdHj@pbZz^7w19DQ+pEbCe$@-3N*)BiNT?76$k*_TT``+BUp za!=u{V>Q_?dM}qf{{OH&IZQ%o(v_sJqbuTNR6YgDe6}+1dMj$*vFX$W^{)xyOpT)c zY?@(P+BzMcbSU%`GVo+JY~i!GU!xqQnC`>tBa@I&TePacW39&tm(6C3=1VuYM0r-I z7~5-pa(JPjW4HHVqI{uG;;g1w5l*ZeIr$&8mkM9Im;B_UvMr;(n8B+r4;a>nwg0#z zcv!kv`D&E;O?V*pf8PnEnhKn-AT@4b`es79y z+&rPV*N^o$<6{pQbw+jhJQuU-*GEho%{I>L$F{tQjy#HW}YLsHb#?r;Ryt9-F z=$#s6iMVcd~V zCZxAnK8ege^UC_kO;Eh}&U<_8|FmaE`Yht6zTQ4_p;*+FC-aYHY|IL_PYeCQd?!<7 zlc2@?iQmOK-8WumkeKwiZF1#u^<|ri#Q6onlqPVWSg)fI#U;0M8+Y>$q2Ii^QBTz- zC_cQ)yl|226VDUvs~+`DNiP&=i&a(h3^485VR6$XftSZCl4HuMC1rZgiw;kU`@nim zJz?!?PT}~w_LEdUl%zH7J+Uc3<3YiUx$;*}@|i7soZiQjTcR*&hTwez-{!!hid_0K z2C92^m8QIE%;FAmH*9DOcoMN8!r`KtcCuPF6Ney2sl~p7 z=5qO@#++vxXG;X=KZy+rNZ4iZT}XAs_U4Ulo>FrR6c>L<(+_y{C};mkxi`_w({`2| z?s|Jy;<0~QlUAa|l|OBDdCMG@g%pLB{)(QR6e#jhXpfK1tbk>En{t@-7Hf5Lt0(Tb z5Hxj<^PkR+XKE6M)D9f@uCjCX0hQehM%Nw0%Qr~ys4fnZ*k7LFeUkaG3#)s~v2P86 zFD~(f9y<5bPWgee@H_4-n+B~HOe<8L{!U*RIDg-<3|{Hxo!u&@A52N&{SvWTapv%Ys|F3)y9VD7-dMO~`R_)850-Rn*^CwOmr%#kgcig;e=l zza2%hKOZ@gV&%MsU)iNrBI)m>T7_2`sisqMKZnhn{XI!zTWQ5yjl27`>#lmeJGOtz zkA;1#d2eO9wi`CxTCuI|*#%{em33K9pTFPcl(4~Z~Ru7yHdY_`T5wI~+ze6})}c{AnNf+WNIGo_2)UEh)Wg?Z7<*h6|gyYi0L-u&_) zSh}=c#_9Z@xUWB?580QLw4MKBWo4u3lykKCewp$6_kYShPj)|h|BV0PJ@+CP?wvVb z`t#a_+dJ>~{$Ja9{G8((s~@VLFB{&T*0Qy2@?wLOO?{j$a{hXHQ2~3lYQLT|sa02_ zyk)iABZlMQr?>Hl_wF`J-tl7M5-t~GO$Y1c;nwF4W*%&MdnR|u5tru-Y@2xstJf)? zF=^qml54bL(fGY4T3qMPqRZEF7}@9FS&%%vE#}68XS-fH95>l@FiCCB^}T)}kJZc! zOlIpwU6p2cdmHFF>&@P0oVr5mHLOCv3cmSqnq^<&X3lh*c@vBRxdXR2T{SqAY+<-N z?&Q_QqO&$QZRcfQezob_r0t(iEMApXd}E4Vcez4?w_0Z2W`m1TE7n*pGkdQ!zv$5I z6M{(vlfBK7l-DSnnPT46eP@qHJ4{Dxw7z6?vXEvX?s=%vMoR4!|v}}rDGDc zU`FLEOX-Cf&J4{ib7YS>*Jy`r4*b<-+Gz0Sy!r;;(`o_s6N2MJl)TLZmhBZ16y-lE zXIWnfLdu zX?y=#+orAKHAk9Wl*sfAy60w@=d_jWHZ*FSthnj+fh?mfJ8~0*7?1m&ly$qN_-@lw z^S3tQp%&9`J>hhcQjYPQd|XKL_#uJ%6XB;;%`J8n^Ob1Vn4T7+sKD>^koyMf z%S%7XUA;depLefj``sV+H**<$UlDPB&4ymdT^f!m(f^MN3U8mSkbP`HQ)xW^tw#3{ zxqWQyr;>_V4ooi?W|X>zQ3l!aiGq>yDDnsmxoUmNM@u7h<#sjQ~ShD=0XAXJr6TnP5sZTxW?2y zSJmyuPeG3@nROePmUExm!_q%jr)l{Urfp(@&v`g)r?(wkabIVR?t!N{p;w)QI2!fd zt=Tr;gYjDEN!fYZ_B>ePzM)p_X1rNWk=W_)6;0m#sqf3*1m>>VAUa(+jbX-$)+0}C zo?e>dJL~JB9BC&Fdo^#LH}VoGvCPVovabriyC&?mwZKntSAFB0@}x6ULt}p(TBUtO z=z)9l{6!qfvA-v->ri=pT5yTXK~{x>PtBQ3C$>lCaCgbw4_SALZ^rqQmByc>tPOiO zFIz~qcyB(yq;9m)^K)CIm%ibIrMxQ5v2TkNUdnK^zN&K(-z2o|>Q$TlhW9(C>QuCK znzn77vA}$R7mvs)Gb8@KaIxpzw@4r+H4xwjW=9#xO0&ykxu!Z_XYO8Y)@&0jXZl?IU4p=7gGR5bKIaz3iEtOGRxjnNZ|$l+rn^!>=|;<;>4$H` zeU0vGurx4pwy`80W$)a!0jGLK?t~`5Rs{GFPg|u_D?aLch3HeQ`*B4!HOti14_78a^x^}To zz@qTTG|e*WrjKozmy>tv{E`gqIGDV*L6qr2rPqPmi(bEZe#0;|th=XqIU6tA3NAtE zg>P8yOS0>j-&(ic=NWsXdE^d_4^MicnHna(+_7BaXKx1A{NCQ3Ip14!uT-b^$-N5$|=(!n#sYG&85&{hLsE>&BWC(O46^z^(cz-A|OVxBmPQ zJA|J;vC>M3-+HCrjaYvZGxYnd-?Ic?z(s4XKRv28=d#d88_7oI-m zOjX?2n7FJap!w{!VCiC?E8L&?BTUl{YHnecTch^7=5U1BG4vQBX^4 zZTBvY!@Am^yuLRmo<4pwuW)l_IOjt7m3eDF0NKd@t>( z+VjILgFRr@yfasN4bue6E7|(C-8N%3;t@T$=;Cp+qnj*udS9!kcgm?25BIIG@Y~9l zeEZ$hITi^jiV=_aCp`V}!N|Vj(1YM3w_-QWe4lXrt;^j{PYwor`*`l-M5C44wD0X; zvH0|b@A$UG5l2L%Y%huQ7Hm7RKQrsWyQ>rCO-OmI^|Iw~j`Ng9PrvpV1a18+xceNJ zZw1E&FJ`lH7wPDOJoc0HpA;~shN|1uYJ!kb(cuf zPL;NuLiq+pE|1d-CbcZk3KY$?`}FLB*M_KD>P%)UHO`bUF1(f5$+<0S(o%zq=hwId zp3qM*G@KpO_hPcd9QQ=&9lx48jxF&Oo36Vn*fuKFeQ#sxqZ!wa#i*a0bLPIG-}C!t zg2UYZJkUJ6=iW}8r<0ePJ&ShEx7jNF-`(cuT_csfmpOcIZVqd$l$9{QZ20@jf(dul zDaBk~R=%P`;zqItw~u7ujI$wAES~W=JU6;rsS^H6dX-(r%ETzIhm}U>rcAo4z}3y= z$gC6G+T6WPnYC-_^=`fYUwF<5Z(~Z7p1kw;I<*DL6K}9j?2ENhdz!j??$o^rYAcJZ zZl3fjxTIk?ucT#j=^cp!cUs)J|G3@AzhP(?u>N)DvE5oW=lORgumo~3EST!ct~RB& zawX?NF7pp5jTfQx})5Ejs4j<+ZS2gJu4W6T;?A zENcVh8|N{td9BucNlr*J_e#Sng{7_+)@T;Ge3Hs#XNwaGU!M9bX?M>0YeKfcOd3!B zD}7qrul8}$_6MDlJ>o8zyCjRAdG5gWTw#Tg?k?e}nlI-}ENNDIW}dO)m&b!Rk=YOC z$#Be_9q8TpHaNK9$k{bl(sRNCnVMuPcgK9ue7NS}GDAMq3z5l1OV?V@`h3?(@;TG| z*y$lPYkuC>JGbhTocyCR2JIHvs}>b^Z0`Me?ZRw}+r9r&-K8I=uIgR)==awfZyLUs zPDx-n-mt=Bnaj?7i;_?KES+=GvSat@(4V^+rdCf2X{|hb@wJ)!j5AVS%PJ)WJdQsN z?^>#RE@geeR)wpAauz?f2>4u$dT=j}_ZibW;^ zb(=%?l*yxG0f*SL7j-3gJ>^P!7a!zX4oS(os|rJ?o1gu0ORpRb24@G?7FVyyAGsc62hkDK?h)6+_Q zW}2TqwujGWwl`Fc{%uN*!LwX4lGt%s$nmp*dV=bT_r!y z)K~M|t}YRBo$Ptw+4?DqQUWB`dUnU`oNr{gOz7RA50MLvR+Uxru`$Jl+&(+;T1&b1 zEQiYz-7h&+R$JZC@vh9dab}89pL)}lj8N6|byayRi^abj&s@gyl%fp}TBe z|1s}O6my-o?M}<3S$x+*Is6i*aNaDr*z;S?BR@CRmUEics@DOT!KtV7-b!^B**#P& z+A!_Us=X7uS*q$=c9&-)X8i25J2mA?X7In%gt^r^%Mv2DPudcELHEqdT7~TCZ>DX1 zpB%Y2#A&g{+3T;qIV(pb8NU9VXB(nv=6}QMfb_GZvQ+cXX`52r_zv0lH*Y!ql6j_8 z#DSuBY0U99H3rA_>KM)a_q;Qp)3$KUwZ;1u?ry%p^3BY1)|&8dr!KwPa+}p*wu)lI z+sXXAwSUW&-{skNSjq5A;=~Cj^2JVq1_aJ3-R%9(+r7j?eo>6W+c)8pxD3y{KH&1~ zEZ5;RyL)%$U8&Q(ZMjX};41f;-~}$KzMtN`eEo0M;&XB{#cRrcNh?Kc{kz!y@Nv~6 z7xV}R%|MOaig~!IrqHOGHrg%0R)0W(vDe`3RDc*C_dLqs^KiJ}`6m|KNTh?(_7N;{?INIe5 zb~}};F&*q~RghYp5Psp-T(g$QmJ5NuCo0JHshyeJa^ywyvy{08iPC$Do2SjO3#t%5 zzCp#q|HVGT{8>toUN4Vn%=9le&+}c_6Ywor%kj#q!?T@Fn*})ceoGKL+8n+AbKCr9 zlb3E+Ul4V(<;;&2HRUEddv_;vuDl^})6HVn)Krx>N3Iy%?OF8s#%k8xAsUl@Zn>zU zrJ`b?x^wr*-`q1;W~I1ma0^B! zxwORJ(3JBp?V>gPl0@DVJd^qoAtd`jqoTs2ZynPl7u_@By2<)M?6YE%Hq2}`wL7OC z;5KE$QFk>_ZGnT#DkWP!-c&o?a@_K!?#ICJXREdq$rK+Iy!&&3efx&n2ch(BAYo_TO zH}2Z*P;&ZhY|6hfX9iQ2`-{J~S#Du$`BnX;E_t8nmu0-5PPxE?%6yd*CYnCSc|NOd zuGz8B*-mBG((qfgJae=w*3?yE<-z;rO-r;yuO((Xy+%k2p^TsQypUYaOPMa6Pva)m0waq^*gpB_`D!J*H zpPj~iiB&T|WZAo}=T*njJ|qM_Ni+Ivwb+T{?j^a!l^2V1ZXEgFxbxeq*{STp%T-OE z&9rrzIrZ`jM$NV-%kM<$>0YXzw)gkL897VWp7ePuym-se9PzdvyWF|5Cv9ARWKRxz z&~|UA#HnMZp%RE6f zx6}z|x3w-a3Q>-=a^1XG=s|_Hl%3I+E-vPPb7o6%KuIQWBvv#V;8`{${7K8F0_3+Fy`v?;kW>Cw9k0pqu67q+IWzU^_m z=fQTZV_INDS%I_8inH!g{+}gg9<^c!H*5cquF9SB`klM`!s>?4GZ;zQq$@- zdvLve;?NP^y+-6*{s6TaW7$UOq72H}SMsTh76^ zY|pnOF0_7r=3vN1|9gMmra7-Du`jYNU-N5^zj(d>w)Om*ej6-Ac|TUE zm(+8g&N-8AtR7l^x;}e$hq+nwx=xk_$(!DCe|)xlM#wD%XipL*bZ-!7FYWdT8K%agXUJB5F}H$y2} zb~69NwmWihlg&%Yb&V|+AJ5W#-xnT|dfp_|)2qw%#1D;Y75frH0Z zb$Zo?w;Nv8{=D}+AS(OgQBirm*{;`LKdy7KG@f@}J9fR;nFYyT9Oj<5{70rxyifO@ zfs?|zQ<43yl^ey%Hf@PG-J>;4bhmNhqVrh>x;(i(Q*I=!G}!Y{a^iuejCL z6m;qW&)R)w3-4J^I=#ckS8Ph(GEG-bcG`CPcb2kk4)>rKBlI2`+ zIC$-fgh_9HdHg=@@HunGxk*3t$GPl{^uSov6*+2d1IkWZlf3oGbWt}}V z(I#o)A4ctIg?m2zdS0Tx>-6ho)t4{so&BzD$IHC+G9~r-EhYbRzO(OI9M!X;OF3%4 z9DCF9t65)fJ+^Uaf9oe25O&I{?8Rg~BcE-_{kI%fILK`Iee%`KgO41}FmkMkIiFP% zI{l?dWySPWVS-_NJmqT2f}Ou-bavfLYcJh0%h_M`5YM%<+fNE7oj04*^2jDZ7jW-rP zp_BMmxqrTqef65vfopGmu6gZnOhEZn-d@iv_l=_^aP*pj+j_i7Ww_@*OhV~`?epFGv@CIR~NHC%Gl*nYJHOcuqe zS7K+aYV1PP_NjRXZ}@po?8@Aycw>BA?Jt zmDIN#`4+eAb_eab)texEBi)E+zxeL(oa;+oENTylnO8dX`MXnFlX4HIrLQ!M2z`I< zZu-L2bM`Jxdw3zbTdj%fF8hgRIXUi1%KnMxirFd>9@n=0YqD&()2KQrZ)*#;bGUup z)|8HD-J9C&QC0aZSuZ!=mA`U{BkFDAvY-0z-YoTVJ)kA*Y$o@$gKLk^%gRa}owTOd zTgw{MyJvd5f3ohcb%<}KoM(!wMAoD!TQ|0)6u%Ihcg9V0@Vo^ZZtU}K-E3XGNj~7=thCm|s$$)lFTN&ypLyt{b$qG)%uV`R*Xqe_J}8zK z)R4XD?Njl)@6)4y@41{1F6B^l;DW7}&h5^erjw>qbWIO9Xg_<@p)|Mm`tDev*PMK& zzgcao?!D`NVz`#|Qv@<)%xPG%sK-mo;aBG7Pi?X6)(gu*OSioK5ck?@ zXWo|FTlaRk{CT+HS=V(x&V#jA9k$x7NtoDm`nIIal^qX{`pwm|v|Rm>QBI^}-T)D9CC*JrKL9R!$1a~UUx^`dhtm#(XITd#k(xqCym1LGhFmAYa zwCnr(izdP1*%uEqo%P~8SQPn3R=Q_Zj_Kb?te4`ZUwd_-etn&{&Z9|lRxNw&Qx!0+ zCGW=8E?*siWvkClihAtZf2!f;0^@6?30>g|m#=a9SAEIMGc%d;YCsr>U*8H{`RD}RW`a2-i}{IE!I zRcGj)ryG>>Zsx9++4Os_;Hh`#%l4nnbKCV)z_-eWy-8YQp=YjYsuyeQTJCmdNsom_ zEoZVd9(-(nm8G}I#qr|Pp-M&cI8(^&jTlxGjtS8x8&8- zNGP@zExz>Bb`RI#9nuHGv#b(!Z*4cQzkarV!@n0z+-#u*n^(t(9Mdbfoq46UMW*U! z(BWweY(XipOFB3IRGHcnH^+|kM(NHA3ims&?3yj=m_EPbQEcUG&8_|~CrWDkELDE9 zW>TKq6UF@jJE{+@?iC4fOfR+OIv>t@S=jgC;{`WV^?zxY6~(?^)Eju`WVEHojNMD3 zuE;LB^_u(CbklB`gei?@BWfGcmq#b5ehXA`j%WXKt6&LR-CJ|M7NGp{rZ$eS>i+5sdZ8x&-$M0-C=&pR{^Us{`?1=|{g?{XNy(A=M z(eJEV9PzgQ+S*ghoQ(U`Lw-NBUNj-H&rGJ!e9~FP+wW_fU6xIj>9u%NZ16vZ%ecYb z|B$n6Z}YpR{7tvH*>B#Tt#H#m`fuYK8%x8vF0T)Vu5>p)E2H>bsN<7r>fN^{GZc;b z*UIPDIKNqWuR~@Pg7Fikm@=A8wj?Ap}GA6b8Ehc|+ zzO&Ej`*HMOS!y4@?2V>djwNL*uKSv{<+b_cI-CrsDZTn&iP*te?~8ZyoY6U-VQ$K1uRkoWeM7&os)XsbOnxHS z#NBDRy+~&24mRny?dwXvEqn3k+L}eT*mFLXy02(3xV3rq{uvslo8<3dS9K}^*Cr>G+VEI6Wv9Hkm8|qO+iK~f zj?-uEO*crqeb7ne=2f3`xr@COudHeu7EBdqX?u8Z+1gbLuUt-xwo(4Ud$G4v;-u}a zIbyp7?{;n9@oq8u!Q-iYYGRL`a0JNfT&ykaS1>Hxa!-zV=J6N>+Y6<$GcG@~Qd?ZG z=}m&1Pj+l$-zUvEwr)iw&GQdi^enjROG&rCsLg(?&j`mdxk6G z+6}Yi&tqk-1T?R)|7$l>wJ)`m`{$N3m)=SauTSqd{n1=q3cJVLE(G-J#yuJe^aN< z3G94vNBHE9_78Wm3y&<@u)k>XpT&X`{zUJ#pCEHJy~J82xKFl^XCw2X3sc!=1s+~n zP*?I+RG=dxdBu&$b72!Xq>{LJxDqv`%|1(QuKFJrYk%Na&wE z?U&HEn_f-QKb~|fUSs(8-i-HUxlCr;?~ArFCuvx5$#NCED)JL4VXb_dbmUCO|EZDr zzh=zW>y@qioUzTz!Qf@|?a$8J#qKL}|K|Bpp(C$!E}QQ=oX2jx+v4^9 z!pr{QhyPui;?r0Agk{(EEb3^{l+VtHga_VC`7O$`QyZ80^tq1n?K3m?iW*a8y|m7ztWeP@cBfB?u*Hnb||I0 zhj?U&9GJmnu6oh(U3!IUq5#VPXC_0hkIK0Esm?7`GGm@mHiu|jJU1|Cu#c@|fR# zCe?B3cFG$rt*|z$c}Bmd^w0I}{35^hf7!QlyS{!D=U;O+FTAJJ`n~v@Gu2x66S|%L z-&DRI|MRprQ}x&SZ7Q!eX-;^Vn|8{Bz?v?J z`i!8d1!;D(F5Rig{=fY!pOHlI7N&bW?J9B(LH7#&O54aCj|#6p_SoBDg9KOPod$lZ zM^O(l(mUE-oRDRkyIE2#&h47!`ISqyOt){fJ+N|C$C16}YF>4}54~UftizhU7MgRbWw&Jje@_pMwSsGLVBIL8G7#u?OU(Vvs%h z-kB-I3egH6Uk5>tXmidl%_~tbL<$o#q%d(VN=+=uFH+D*PRuOIS1{Bw(=$=f$S5f( zu+rBDi=`JO7Gz{57whF0rE6+}Z3!sKPbp1KB|#S=Ld=mYhq&H3u_Q4kKOJInVtQ&Z zG)fS9DvDCmxC|65xD4Px!OYau*i<1+0U~B-X=!Gm0G3tAgNvD2n4*ap7#J9$iy2y) znHi#~Gqf}}HAfROGB7YU#t<_!MY6Y~C^0i9wTKIpE`u|xQWY$~z6#3EFHrz_9FkZ( h^V0GaK#>pxij?A##G(?g4~-0r3=OzcRbBnvxBz{(yEr+qAXP8FD1G)j z8z}|`1qM$S$B>FSZ|;^?gdDwn?Bn~KD&;9GPVa-3c)a&@aBczWaA_Fa8-7sn6B?7zEjCbrZrt@D4yx#io34=ZL& znl$O|8=ph9kvei0qoT{R*G^}cyye!Z&&L8SW0QtcX%nyQTH4<~e{0#><+?XFJu|SLCQxo!|8UE_eYLWhnkTs=7H+LO z{l@2z-ISnK9kKrTYpzWxI@&#b>omR4gOjww>!t*yxeMpLy0p|-#%j;?swXGxx{p38 zypZKv>6cxrv$xd7#^&*>tGUm@H@hWQA7OcL{VMm3&E>C8E?II!sZ83%X3FxLjF(m{ zy|yd$x;Xo#)z1aG*RS7yv$AD}cLA$SA=8^ujxBcp@AhwE|Z)^@#rcPrsxN!NhxA$jtqvo7Q z=e+;v3uaoj+`V#gnyJdt#KU1}&jlXM%et1~6A|%GWI^A}$d=Eiba)qB_V)2f_}e!B z=kFWwY3_nfHzpo^6u8c%^OIcK^Al_M zZKcir9Qwl={H`WvV}*c#fJ;F^*{aa$Nx#0%O5V7mynkKJe)qe-#T{)Xc$+qGa&EV% z|92&JeeCYC*4KuCPtL_M$mid;UeBI-^3{uqmqjlxSw1^An?+;IHIcZQM25=GVn)`} z1P-yr>@51Y?)}uT+^1h&Cja=&KFQeReC+jONAH)E>}lUs@X;iC``Tp*2Op(yp6a@` z?YiH5yJLHP#s}}O<96$x)7#$e{a5t4*_5EE6(8Qdwpjah3VY2z$F274=d#zjr)kXL zE?j9Z`}9<3^2bH?@2hg}JkS69_e^1roaO9GOSNZC(fK=V{fyqLSxb+fes55ED`1-L zeAn}G&S&~mTM8JJ-OucL{rI(E;FbId?NV2z4XdumOb%Kaf8TEYr zt~1YcwJjJj}pQDIQ#GGGW zqb3-q&#MmEfBTgw_f9!k*SovUUMjIYu<5D&B>nuvs&5suS-F>Q$oZL*$&-ZH=u_~+&Zv-e zG4JiK|GRy2v-*#}-?z3rJL9}}*IA<}SMS?TxV3d&+Wmd^ch>#QYRlsIyfiOu?~`xG zy;jaXAhPyrOZ}c_yeaH@*=yhbbXXarC7p0JDt>$M6Q7g0(g$?+uYGd3zv|J`r@j#p zb(1Df-cj+9C*Jo*!$sxv&*$IDK0Et=mY_0w!o~=Vs4XTFCqCa%_LfW8?OXco{J@I; zkFR~&@B8mp@VOEO;gSn%eQV@R<}>vfZ+uD56z`Yjfb|||6d<9x8b6L_}Z^l z?6sVJ2XmzlTw1FA>FblJA!`C&pEKX^`MLkaz3$3weDAB5Gw!MUY_-^pf04(-Nj3J# z!gY0w409|BJ2Ef3+Z6QV@0UJ$J=pH)Prbhq7wRi!ZPty=+HL#!jInIa|GZlhEsNDR zmfX|<$GK_60}ZW^6}8XVZ%mnzqE`P`^YSwO^rNSCZppaE+OYC+n_%H9jl=DA{*%?- zGI)4&JfFUF^Sfy22ak>#e|dA2WvR&JWoy*p_id5q+n9ShYtcHlMHi18KmO@<{%VW5 zKMKM7;#8}T?b`P7K=2Kz15pQz67)ax25B)!Fqd44S|7CSapfzf|CZl;G{35SV7m~L zz4vzD!?~@u%^Hq&+3~r)uhaFP*K}p|?Vg>V)r!BqQZ0IN!Zqbd<)q1zHRAXEn){4@ zfycxkp1*H)|GqZ=>*MJ)AD>q5`A}2;>$~){XE9;fT-xF1mWHhC64Cl0!H{}7Of`O= z(wbkTcFk;khfbfiwvAsU;FNOXZQ46Cet!R3ZQoOFeR(KjwdJ`VbH%?ynmS_qt3omh zo=3^c+aJ1pr(XZj>FN3xK2KeKF--gNvUQ5__YS>0wJqV{mj8R6y?uLlSE;u~&<++x z#-bZ7+LxmAL%dj-jy9?!C~r$=+kbG||17Z_<9e^#=XT%yv0g~dYbED_$qv42OIsFi zvKHQ+%fQ$t_jj^sw)p4c^3oR7?^G^c4EOZ&W6HU`>&c0U-Ab-rf@0I=tJc%_XU~w&n7MFIM_rIg5qCcmBHrS2CSJ zm73I*db7XrYXqE99FiXCPSc%#w$I+I;K2dEMT_)=rKOo~yqj<*Z1u6=oEsmw@5bkO z%r?^x-WOBqHLd2+KKl)Ed!;j$n%9ImZR%RP*IeoBQ-e+OiD>2iPCr=)^v*XyY zUhkPEKZV2AN1izJv--owkKX^qb>~bAI>kJLtAtT6DOw_k!GdeS)_qH+RLMsh&sZ>J z7JJY2sQEwKXHMUkJMr_3Yrobge+CDIxbDBU#KZRw+_#^=_BA?S`#a;5^Ygmz*F_(F zWy<}2SJ|bOr9J;Y#ZFs4btm=`<`x}dS;$6WB1YKs;{$_ zTVKEQ)ShWW;$!_cxAy)#_c}0eB7;u!x5Xw6P8{t!ik>Rf{@(iR!os^Dt3uk_{I{u; zzhh$g!T#~xZ~eQaxu>VadV2Y#yxNl3Bl+8&VN=RUx9R6V@U2qsie;I{d9I52t>(TU zr?G0Q9rJ=IzZg$c{$^VH)nMtBiUo!jL@icKIkkH0zP&~-*cV6`cxzsb$*w&-F}`7Q z!D%)FOUq8fHR9aC%CoU;G(PHu6(|IdFpwR#!kovG1_vpIZkZ}iP?zoo*~ zM;^)EJ9~54*Gwkn=J!?q|FiX{{xVm7@!L&%nSZSB$49A`r)ZnKV|#u5zfVCyS>Bx; z=X#~f^<%iWPMunI_H<|GPPb_~H;sN=)c-U`P~H0Etz-!o_pQd$@xE% z!Pa)~iyIG1Z*6&ZF24S4%KiDbBQ_@K39Hxo6cur;-}mWW?Dh86r_0@XkDZxk+?c3* zFX6=Pc&TZ-BQ_c}tZfw4Qx~!L)Bo(ecm`w6|L3kzuPq*^FTG-vbNkp8mO9VBB|6*I zriwAGo*Lwzy>_wel>3<}@7}&KesSU9-XllvF7bQ2tlYGoUs!C~{N?lW&b!O|r8?|? zsG_E}q4IRs?sb`0H%ZIh+JEW@r#EB8*RRj!*j7J^d-^Z=?5v|IDo2bL{O5Rf?%v1w z^;O?0+LtVGsf*qF;o;F1fk%RG@9kynK6=R5*LulM+k5x+g{+B~ofpe)oc^tBQ`*^s zw@SPJ7vEhm(cY-yLdGo9*GHOIgJ&9ibUs`pZ?l72;jDd4x6f1e1#^P3x`JNiK2Rw5 z^G$tfkiXW_Fs-F*8cXBY_Oa_Rl>bd#yVZ{&it%|vsn<$@J3Y~64Lgf&efxQPPb%y6 z_3n(@A`gmcKi`n?@yqUYcXxdaZ{vG?`s(WG@2YCw?_0Za>!-V4f4vnwdbE3L;-BZ; zJ1ULa!sDvdeC<2+qRqJT^W&xLe%`UQ|6ek>EJ87s zS3%v3sT-B`w_ZDP?3h5|D-B`w+B0)@3Twu#;Stroaw@>~VM!a4HN%!`&l|lQL?*CT zu)bhFlvUtbmxJY#_U(4>>E{CX)qMRQ zQ~l^k;xAqfbqnt@uW40H(&p=mzr2{w!j_ik@c(!I%%=|@o;)GAx#H>8bP4NszD>=W z??*=dF<@rjy8rp>tE+5JvcLD8#;Ty_lx_PZUj9GlpUU~!>luaR1G4|^xAS8=CM95e zx$r032De_fA3s?Iey#tkd%yCxw_Noandoh6T(W&1AA7hZ@2^n$`FRP?&-tdD&YI1; zE_k=5{l5)UduLB8{`JK$?@q_Ey1!yJHy>DLh2)nkpSM4rVQ{XJ+HqWYV|hyef<7R!(^W4=UgXf>&Wv;Z&~6ucbU&zvpGVlr|$0jHajyr zVsja1JOBHKcXo1ciDhsFv5_SCj&;Px;$}TePQ22hEKS_!{m+BLu z&GO?4Z7eNUMpWHfKIM}0y?>KH-L|e{PuAOmiotbis;ay07MGtpqC1~a#EC<(r6Bzh z1D9fpz$3oD_k%C@tewyK&Sn?$^m?{{9qOyEo_fE3{YLM%O|0^#FRWyB;&}MR#&&O? z@0>4%3y*s5+Z;W;?Ae*ZrCUq)?|s$1Wg=U^jwMf?xcu64anh@+Qc_XhQ;rDUYWuz* z`uf4PYobmZ=@aJ65s{Ovefspp3vEaK{Z@z9F-(3N5x=C-q~TC%WmQ$;m*!uK-T141 zxH>U>7WYZKzV0mleuKH2Qn??V{oiZ6XPp2;)azOY`OU=~zbCT=a45b>`2SD#$4~Zv zy{{&>UG3RZ(|EI3&4XE^r6T1L1K0MYTc6$8*&MS^$T6r$sgd!fX2=K5KYyF$|D`Ej zdhju5YR07{a}&QRDfJmtpJO@vic|5<^fgRkdD+j`ss1S~khQa8d~#x5|B4mHYi=9# zzBZgL_b*McML3n+zuoadqAW1^z342SiReK6ko~nE#(Y zn;yJ;nH#3{(5-L&jf3&**Mj%m34U^7-uxLeJosc{{C#{>OtVW&tmg?FI_k-+aVMyt zK*Dm<^W^jUo~o!EnPgudxz25_qTW9%QLa;O=5N@4dHHu?v9KN|R&53W5fP`PB%Atw zTW1|PQn6?6Umrh>mV#7J7=2) z-)-WYIStE~^D~6y9zCw^kjKca_{LAHkz@OmIde{2yZ?NGc6#8v%3boItGB3mPn+}R z#?Be1!2uz z?eok#A3|4!@;?9d)jQ{o4fEQyX~%_~c35OGv__wrXREKN>FF}(R`K(#Po}t>n`iBj zk)imxiF5meIde|j+{}J*{(c>??p)QXh;>OJE3ZtFHeXlp^i<|#VJ^j(xjIaOd79-n zl0`IQW-_y17cR`wcWkum*dyaOO=sa0{qI|Der)OX_VhfI<*R1*?^x{mXq%k-lO|6V zKGUJvQlJcug>62{Tw*%@Ay+Jef+lGM?bvkYA7}fAkDLnC+xE<{+S)#00#i$yh>D$E zo3i`12d||)JUkpXD|0Ev%rR*=v^JHKYie$Mi{`43yrc7KPv6{?YZe!`Pet{vQuMVu zS61AM+tw)PbYm{4<(J45f8QZ1B-`C7Nv5#y;*Xzc2d|r7coX5oVXnx#puqFwNlz73 z)k_-+>zrR7J9_uYN%d%{sNfyu^7-{Od;Xs7Q*0?PzQn*aJ!NA>!p4YZhMli$GbxwwzF_@>k9k75s;@++1WH zZoQ|=vs%5SARZKGTb^#8T4SDk#@7D%e_Gf zulN7kJOA$P?K38L?3jIb_x6On=Reo9a!*%r|2BuuPot`b$R>Fd7CzdpZy zAz!c5HY3G}1?KDb-Rn7Wq$;=yth6#??e*;E=jSiV{e7yX?U|YS6oEsz9?Tjn+iIEj|9Mq===K+d@^?)9d#+_o z&9ykP`17}KKhI|eFXLNW^0F&r{k01%E>0ZfO1ujM4m7o1?${-D^7P&NRS!xFKW_YE z^SF9b`gzaO&vz}FQWW6y@D-ozy~C$Mi)WgpZoL`UB9M0=sfX}tdHH*3K5bH+Y1KS}EEiJ0EZUT&$ew4n6yehH^usos?l8@GXVgEG;#v@;Uj z*JeGRU$5+YU0nN{MYq_y#aUO`N?zZapc!nxx!CF9t8IDFXZvJdzr6i>GJD+ety8B= zNnu|qV7gs0Zxi7+LPD_0&I(lD?+3|k)Ctt(uD_(3}>J_S> zqQbM*RMsjq`M`m)Kcx@&*_Vho?U2f3XuWM!`N^Prdd+d|z4vxM?>e*P)J$Xk`##a$ z4fO(dciC(DF7ViVGK; zS+sclrPaqLl`JbL^zaFx-2;})nIVkcZ zZLBb;x$(WC;@-{JlZVgP9Qs*VS^4>-`(+MJ&eH|GGB=AaZ9lKRCgz{{*VpFHFQ1Q7 z-xKS4Eq}u2HLU{Q)qgW^O<%h8*`J@mZP$8wdlgkwuGiYXfBW{dy1f7L(APx_vQvVR zxB49K_zmjI9L{28W4ru!srk!GJN3K8>JPii?>*GS8vOJAgN-6O5qCBewg{|qlyZ1D zDJUrD!-k3rYJWHnXWRdt5Pi(C@!9<>L~6(w3L(_t!kSS$E#^lWgaW3NIZmc@xw8?QPY?)z1Z( zm^MjF^XHgY>A|dVXV$e@lLdG0D0*sgeSN&s;>;Th*yZHn+^+fudX=($(^`5fYwdIC zpokQ%eRg#$tf{7J;v5`q`LEtN{lI~Qf94fDYokh&kDT~tbA6T0`@Pl^t4e1}P6^1j9XC= zlX+fD;fcuopf1#{DOdMg{BGRF^YT>3#J`?Cds4p_whEkcP6K6=q7v?n8?R>s?6*=De$J(f*yrrVRJljqpi zx9lp7Q^?-1(_Xlus_NqQ^Xeh%?@cJb|N7Xr``17G`#qWC+@!l#Vw^aBPXx8@9_8O< zP%!$$V(Hu+uqMLv&)-d(s?Y1o*ne!dZLi~gv1W=^_Ibya&(>u%);kY(O*XaYnKC7% z-RAdqgV5Di(*NCwT@n$TaepD#?y_7n>q!EK{8HEgb}W7J#05067W((UZ{g>sy1iFt z9r^g!S|e&nSM0H?QS$@5d|8e$_}@$wn5cPYN8!{12i|~Mp3>$y(l+eu&lknqTz+Dn z?)uD~P0gD>|GdF^X7+#6+ItzE)6dnuyjsj5C->=ktH3&!G=|pbPv7~EW%(*e z|K_Hrs{gL>R-Zps!xa+ZWxDmb!lBB{Tvf$~YGSDiV{R_5__fmR%Ie#q{{H#f^5>sl z8~yCP&cNQ0IEc|xXw7<+q3jX@&ENl?(FdK@)BBp{>}5CCxu+%>z;IQ zOx|eQq}c6vXF`zJpFd5V{rx*%m*(f&PYF^{nPJadF?;)VeP{dMeQD=Qo*m8m`m^?T z)MjN)MIHs-1qIPhPuaKz1aQ1I_esCmweii}?M;VTwLV3Blq!>t&YsJ{!)6!ebuuz0 zPa}HUotQ40#@u#=*(a{_H#a%?`jq9b-}}ohpHI&FKVxp>hJsl)3tI&GJ?6a<%{zVj zc7ImrtqD^~x_?BQb9^}e>;n7Ut=H_em+~?EXTDc@-!DSDCfOQn}>D*o;-q8HKl z;zfqi(#Z_oSQb|Lnbvnx%{{SZb0p3Lk!H zYCgOoaP8cihL_d`96Ub5GTHbqd&}j&Pu+U{*9b0LxbtkEYKsSZCPS;Ym(L#8q$H-R zSt+J_%FfQ}eR-{P!$ehehP@Nn0#cMBH$Qvu`lR;H2aD&~{7=d~)*tQCDfASqTN$ML z)3hCM|?5&mf^|IV&)*nOty>})QCW{Ab^{U;R%&B+@)PlLRXK!!qmUBsl zb+_%-maYkU6`ixW;S$5Hj@jnxi+`OlTo+^du6@FjCn`e1!n~`~S(b{d-}{Sk;liCS zukYub-yf~vyFg%OgGqyvMLXw#c(0XrqF!_J?~St9%f#AsaZhCWp~JnmUl}Sr;#mJR zFEPSac`NVxPN$D<`>*xLZ=bL#RCSy~@T6XY*vcTzCrshk%uIzkm zs-JH^`O*hbgILY4k+0k?9%`LyU*9#qerDzQ^ILOoPnNk^Y-KUg@X+l&JwaV{%!ih8 ziX7?$^$chAZ@0HB7BjRymaE+mp&&COw@558{ki^}N3S*K2W>hcTv1th_v_B|S!E}- z@G3aWzIOM$N#o;V=ayG(ZA)_(a{AK^3IxuzTf@A3k8G20k#aCMEIVUU^jt5YjOXyy zystuDn!ornPTw&6ydrS##G4aa1pb4vSoZYwbCRB}k5AZGAtW-Rd6DbtS+zXZ%@3%1 zt?Y_=eK(Cw@KNB_ted z&eITKX4{s0=Ecq{YcAe+I~?V-$*X6jZvt#G|TxlEqM92S+?9iL^n8Vnnq;T zUOl6rl$>|BOIh#TGw1cEr|GtcYCoSiXU>tEo7F#j`<8lS!^|tIt{!33lwF>BdffsM zX7;V=pN>48q91?vjfc|?+f0U5kEK(TGz{3y^WA37a?aixuUX2F!R%vb+T*eL#tjLx z+_-bMwtD}_eZ9V=t;M$Bqw`a*(#Y-4-puV^AK(9IZu#y{*R1t7)V+Pc%O8h@!#bGjLJI;9-91R+md+d$<#La>l!T{(lZ%F@=hMVJ^#`iaLJ~9XzNyGqtK1NKBafL|ec_Z<*;}Ky-`w0ib#=I&Vdf#D zXXkH&W}YwI{i7RU(fjx~|Gl3-vO-iYFXLUFaq*IfM!=aDFZ>QCZ8Z3@`MrmqU)qUk z{e@f2tS1TNd4g-nFJGR0yyRCO_A(}Cd!za+*&}l`mx^rr&)?jz$RX({*H#J3q-)Ao z?{3RAozMH$_uHF=PfiFPn`wOf)_UFC6w14Dx+JLIVz~JErRDkFpjqwh=Zw?bg}}Ymm`T^9)|#^OOIFWt z3%Qc|=utB7+Mfc&jb$FpF9f_+<{bEaK>L8sf*sd>E!w#`NZ2~#9vZCVA)2C-AxgN_~ZkY8&!O5veGU~IU7(?=upr2c>rOQ}u*d6G# zl~Ikkp6Tk=Yro}|-n+Q}`{tsnHphCZFHfjph>DK=^z*>8v)0A${&@b{bFpitvDxk? zH%~ZONM|y%79>TzF7{fv_C_9azo~V)-u&w6*U9~-XYtQtlw0MIC78y*A_q|up&}fOV zocpe&snS7w38TrJpjVm+Rs|9otGC+yp0IsMWJA5c(^Fx}HhbCwRXaN@4(WUIzVx4a z>GylTM@RF%N}5(FIN$qu>Wzid4wIYg0UQs`|6OfaP+&VkY9=o79xg>PE*-pPn74T$gfnJ$J;uq-{3~TM9Bk)k^uFBl0nON_gu3 zuSs*?x%`SN$Lx)|Y=ZqBnp5R(Fom#bWvo@tm|U)W?bfMn_n&{dtbh1y&qI+<&vcKt z%lkdtys*}y^3w*8X^|k)%0522FJt*j+H}>{!?$m*{2sr1uT+E$)6x*%2mCqQwy(0* z{x`D}VyJ)jf2wwPYVY}6-dFbCv#;Hi{FA1hcel&fx=%pQQ_A7twngjXQ@-Cz1&xa> zSm1u|`t^I$7(}NARi5FS6sfs%7vt(i!Kl}HQLkAx8#Bt-Z)`qsT3s`8(YBj`bG+`` z%@-07IFf$&*9=)#j_E4A3ktkHel)+aFPX7_dY(f@hT`VOHX*NaAJjSsZ{D0@=B3HM z^om6S&jqh++jDPxw#V+Mn6lV?d*I?I>zW#-GkuRkY;5;R7}ki*Hea9caZ>)-KIN9v zpqgc=eVLw8{XQcRoq&69G+u5L%4E3gs`->zhix9)s?4?Zrk0mvFJ2VCu{T|Es`hpj z1B3RPg>!-;*45N}JGs3_#&p7B_x~m!AG>aA6wK2!)0-tN7&xcr257+WiAz$Fl4bEX zhSF^N_dVNN!)F1?SF)~VIX(BQmH3mUUN>iJFSsV-d?*B}wpONn{T8vd{CmLe?|RA_8ZD1pR|^U} zn4;aZohi;iG-3D2$T_ouv;=;z-d-QBytcIG4-i5ebXa*F3XyuW!AxW+Jm&XH*j5W5Khnj$MEOx=7;a6x1Km5T>fvTV6kMw zi4($i_7om{(sJ%-(#M1!7iPY>w|AyxvHDC|caG@~YU)pOD$1pZeqj1A@uuUPi9uS{ z+oGQa-Vm!fGF#^5yid=o=luC8xBvCl%jw@Xr@uGK3dzq8(t0i?By{Y;`Lqkqd&59$ zQ5Ly+&zAM<@bOJ!X!Qu)7bDyywlb-#r#+H0B-AU_*t%nLpw~~P(~TYvEYoxUxf}~! zd#k~0?e5PH-S=*Y3O>`P?6ORacY(mlO>FIg0uS!gPQ7NuWWi=)WZ7jrtMBd1{blDi z9gna2@ry-Z(&C1jhI8WP-;)=Xt!8J?P4y&=7R2rj=UH3*>Wkr@KWA(=d1uS6pK`0^ZHU13T!!HDuKzeCR&Je_UN*1Z zy7H63@jm&Khlf_SUA=OnZik@21NkGr-}@##Sn%!2+S@%fmE7P6bCq&XG+I9OfborU z+e@uiF0c8+l5;JpKBsJ6wPxTVo7}_ILUQ*GZ#wd zsK2acFW1s3Hz&57FahO>*FQS#cT{}L&pYOpxOLeLKSs^4xiOZ$`;X2R({4=k()@pB z*9*nPQ{LwPeBU6lVD`?;mYZzfk6OGtVpp|>LdX}tvhmZ5TIih*5Ph7mu!E?s( z<)p8bi|$;msQk5|_Bhizx4EX)x12NA@-t3vs7gyWJlO8QyI|?HU(-%T%6aCzF+Dfe z{>Vq+`hs_N6emqG`Z_(i>%f78d$LB2A0M|De0(Ii`7y`DOi))Vx>xGkq1&h5pF5tI zcrZVB@NUho(pw%p_K!<_)Uq_~xS&$-1W=>7-mIP>@cOyr zt!k6C(*-9BExny~Aom<^uvh4TZ8wY4*M5!L{MlwzLqpD$RTn2tn9#(qWQoe=(%U(F zGBNtR32cAzFGxhS+aJ{Tu3zB#SugFl;Gvf%brT+bJ2%hzz&hLg8_M4ootm2IQ&2GD z=EO@`+ySndPjkxzs)M~M6RY3lFS=IMd9sjaqJI8M>$CC=?d|H0j*1aeYNF3|=tOS% zcY!ufid;fhpkR8wI`(Vh{ND z$0;seHCispazI=mUq|hE^<+WH2<> z+g$nCXUe94B?YOIgKg(ryR~Y{Ew(GizS%7B4)U7Hc8_sZ#@fec&n0i!{G1Ooiqo(t zs8#IA+2~VmJZ9c{(75>JuOQ~A?RB2t*hC&NrmzKcghVzuot$ObbK=D0G?+TY=YU-GBFeJZ=irSp?X?JnEL$M&X{ zi73ti6&QaGuZ=eU`010WwOdsVW7aI$Lw)xcikS0f$sUQTsci;L3MRR(4qTNI%O`)+ zrKo7p&5cG|@2#&t^G){k&*bNBn-_CD+yYAXnx8&-mc9EoQ#;&$@&pO@m>3gK#XNgs z;FI(5$KF)D+{k=l(G;!BGJ(aKOS_onGwt1SE$?H<{{HRuQQ1O5ceC>I52v1&^Xi{| zKk3Q~$B4BvU+s)jlyQ@CcsT7(O>;-@-edXE^(jwR=|}7>GfF=%yTs{d`U%NdmGh*% z?s8O$>y=4ceBIK&@<7enuU?x!-*A5NbaKYp_f>E2v>vXg{`u&=cutVk^@}T$^B+A< zj@8szXPDS{mZ-j0rnS5|*sbkneB6KgcH#o0FsY_AxnFx{FVdnE4L+h|U%O{u4w zw@;T3Uwp3M@v%^?&>Y3|TT%y3pPtS5xBc@+_4SvQct$rhZJH(P$+29?xWOrS#aO9lbqINGfOs+t)aye7Q*0oGENy=Re)} zD0QY$>57|yEd^Fapb_Y6Qme0?`t{XbI_mqIo5Cz?X@*;tF>YgWof@=r%eCoe_>vn= z9?)9*RcUkcjo^fYvM$yzW9zol(k2-uvGdmZ&NkBzUhyCqlv^@Am^EU8ii(6zp7i|l ze(kxoYg?m&KYaOQwB_02OHuKmUb2VEq$?KQtdwgFS|uF7tdUzL_E4%zT>J3m^LFQF z82*2JT0iEIfFyLDEH3U|MfL9uwYN*1U-wDbc1)NM({|0|gjmk@M&n%O6;rqvjxjQC zxi&HFd1c6R{W(d`*ZJ!Fdl`K=OHECs;B#6};@3MzU$3w8=zi|Cx%Bn=D{FpE0af%| zml(JnN^N7PJ;V30;~v8~M&q-5Ni6*Q{xvm!IJivmK05A6*AeTs*)=yVa`UqV>HXyr z#_xPrh3Bj6Z*v0m?vpz^Ip5s;ES-K%1~esd{B+2&ij6*7*&o>Fvh54>V$E2ae3ox= zoY%@V2ND)^|NDMVV`j*@IhC1rHkdwqXv?!&Qn0Y)dewG=HS?@9@4pkRn_)WdYPQ&= zCo8vs0pe=bM>Owx{HBl)J`Kz2xe; zyxyCYMhOB10oi-cyiqu0T3P-3!rIpf%Y0og%nwdnv_ISPO{0uy>RG;tjQPy_v)7u>kUcW7?pGz7q4~Ot3;(X(^K<`35siSJ z^KIYKzRfvf&OA4=qWbrTpjSEzOl}>z8#yIt?v$YAQ-X@81j(hb3mwvF?|;LpprdoY zc712}?vuxQy*)iW%R<(Cx#6ldn=!=eDRbPxvuXbs*mz}*KIuID^2Wo`d6~B+CeA;* zAmk*MPOR1GHyL_sOJ7g#=-heimFdi~gL?$pHZV9hGC5Q)*toN>#i0G_tV3tyk4@GN zk9&1Bx9n|LZOcy9)YMmN%^DN&azW0p#v(}c+kUetoU8zZAMn+zq z>XF$Kj@4FF|30O&K;VYdfwwFF&t-UHY}hTZOww+Vy>)qB(v1rND$4C$rEp@3dXKe-t+aWbeKIM!{`URPYS5T8rJ^b38v+2L(;4{QUMgCkMxqr|tV#*lQBX#FXdSRL&6Jb?x!<__UxE37sbU z-(Oz1_vYs3=AaSLjEp>MHIeOGGw;rQ@j5(JEMSLjB&*Jypqd(;zrWfyXMQeP<{v$I z;qAPm-P50*{^kzw6wB2n!O=FeKIjo;K4T7`(Zolc+ldv^v=Fh{=LDNo~Qdb-0 zpOa5HFZb)h_oYizK0kD~jokiDUClqn@8+gZ*$H6|uQoT_Wjn32pdfma;FbdK=vOeoJ(pkPVf8tk6mB5@~2IF-A0wO_C80B-c9*1d#**<8~tUz zKc_xAdis{-${*W7jq$VF7f0+aGwhYx3Tk%pse&?*E7$ZT;peN@+kW`^)jNFcEK{k^ zAKim1f6o>F@v3{iM#P34f`Y~_*|m|HrBb(@1k!BeQ?|#{u-)0*wn>MUm zUe_|&GB5akcv2G6`aQR%1TX)e1{!KyaZlr}DQJ(y*BKgYf7d^*w==J~;bXb}n&Y9{ zd(N2O?@PM;?CCj!X8o4Kpw&r^QCr`*`J6GmSM|Jd^Wry$D#e?=Fl+E<&tjRh5w=N?>qn{!Xjr5oRuPWg1C?3KIy=FKTnf>vn; zsOad(&#(Km_GV#=lpu|zCnj6(Us(G1ao(fH z#s7O3F~-%sJbRlrL44_z>Xmrq~#wZ->%-};N2uV4Q1_U}pC{+Ggsu7bk+?-^D%jiuAF*ZNylg+KU%Hf+W_^NKfY^$KTkT%GoVhK3_EPWgCoh-Z{#-J-tnH~~^*fdMb>C(sem(ME z`*Ve8m#FU9N%QwT{;4wnYl;J6gA&0 zOg?@cw6NBy{8jf+rTym)Z9VzE;NiBU# z*&&m?ztZ1pWx|8X2iluAFPR#&%H)H!0He*!d(ZUu1_e#>^xSy*z5PVKUg@ohiVwwR zo9P-`cL|h%7NJF7yeMu_{f$90?6>WtWn1_0ePMCaTq?7(;DN%nW0xh%w$%z+tl9eS z?i+>7iNF45nr@KDSif~&>iLgbuI>5s%DCtEpWJFb9JqST>JZWF>86! zBVD&XsT17#*HWLa^Zh2}wj_AAneC0;`O?Sxf*g-Xq#eJsjN?d znC18DGfQ&*OP!u}UQO-Uteb%?8^B|ab50&u%_npI3Y)>#JNK6zxSp2kp}q8qyMywA z%vZ&;5B1vqt4Qq<*FXG7wdhuNK`f{ZW?|g$$!p~&KB@C>Bo7oMY`^xarBhPQOYvKY1ZU(v z`oX_+N*0d~!>z2f-)GHrx9E54jhZ}X&JnkpLT)=WKoQ~P>8YfsIBm(13I-wJ$DSS? zTfh7N5pF!^rRiKgXJ5Z^!~URE4a~=OdA|zNGHs~rle1nsCFp4bt3&?UuUeZwb3A|a z^5xOZx^WMd&);tjiUURUMvm>Je~!q@SpE5bJ3r@E(r>r;rA6MKp6F#xH{5#7dTLO6 zUp_s)}7Gc;`c$-UgD z{$U80h{mzC(S>K?EvEKLPoE{~dB^#4y4A*#mpYr1IT9^qGKw7f_>D2{hFRvn)8~?9 zS)^`M_SC;-ShMl_&z+JBr+i{q#*n=A8vB_ukKW6l*rK`mY>&dF1)h`3dL+NAE%*ED zd$8#!XqXaI1?g!U8a8H`Hu0{VIcJW~`|I{KOQfP+i!8lTwm_{flRF6y`&p_Z316N{Su7lvx5Wlsh zOXeQmwO8PXApe|FhI?fPEM6{}lEoczxN-a8+il;M`Qu%-pY|_fBm= z{;avq7VFPkVwmUSVKfw#R4R?~{!S_BYG$+?Hc`=A6or*mLm~XV>pP zm;Ua~$uNHYes4`pO=z6K2!D6<6<->{-F-B9$<`gu5O>%L`M@BLixdPs~>w7#6O~wdZdn_w)pKt!4RlCF=kA2fH3O)cMZKS{+~c)HZa3 zL!on6ds+2L#mT4Jl`_L|&RW2LW0`gI)=7fZ)4og!{3?x#=wbPhq9O(WTz$wtxOMmjncC2>xr|)nk+I>Cv%WBh~ZDEh`a; zWn2ABtfv>m&0NPQa%if?(r--jGuJ-9T{&m!0i(5FrpZQS6r zW7TB`M)scM?avve28lh;T(H*mReDR%tHPY_Ai2%YEmqFX_BUTOFK89Zw#$jTtg<#| zO|2$zw!FFT0at)WL)M=pyoOZ18xzE59y1{nR$JujVr5~|AAhWi#<)-7Mml^`? z8@t0=8iVTnWf@Z3^CqtJWY%ce>6g6wZF)ZYhIr;1A`y$XmUaF04(hMT?#}%^-N*Iz zypuOsL(HtZD;CUeNI%P`cx3Sewg8Uexd#o68`>KtT)Dc-Et^YcyYt;1qm@(aVQT?i zb-lG*(VWJ9a=}~=<`-}3*k)-go%3str=pyTl!M}#rxT(NM7_>0@gV)xq zG1!#nw$!fwhY*|H^z^2=H}Y0!)>sPPGmD4VE9; zrG_oW636;$R21lXf$bXn&FW>muZgjXR`+Xhbp`ag0$2xF#S08Mu%;} zbB4M1s}uxw#_AhsW-_!I%wHVFB+uR@73!lIDs+PBPhQAb_bZ||R&KRRDHCA!V1Dr= zs6RiZ^$wfZ%qbv)&j)HZ`ZN6u>NhlY%6-6JJui8V-`vLhvwVpHksOmOPm~!bU7o}i z!138K%lO6R2D5@Sw{D!fWjZ%#mBBXAbKPgpB~7qzSmd>GO&Yr({}!3sO>>pf*aemL zE@2coRMU5hOO5mP=eAZ}tw{D8IRR_kuX5dZq~%_`bls|bEFnhL-8=06*1x@5UJ-Kj z+JT4n{oX5bE@9xDaKUMEoXaY%OCc@-tfD&dUEy!uM(K6!?QZCb2>f`?BRF3#I13sPo=>r z;`|yp2ZOf8^Hz)@UPl>v8}Fb07G?URD9itSyrLvq8UN>rl?{h@J()CGzWzHnV|Kcm zWv7%UgJD~}xdoR`^r?-zPyRe$vpRWYV!aZ#;~)B{Y~b zK|f~`155J1_+06Ktjdf%#TWmbU6iKF^ealXMc}F;=K_Ii)|?^_)NC8PRwgWvHG9Dr z;`NhBJc;M`P*ns;Cii@_(I?{e=L-)uhl zZ-1=eyxm{J*dHkw@w}0nmNccgbBmRL;v7}Z1p?nD^jUH~a8#JR`8Dg7%YXLYJ7DB4 z6f1qwNx=NUi?w%qK7Q6{iJrg`z)^kTKnu%-i5hR8z7clVedhmbUY(6r9O9F7AKp1G zlp?pFKpEsS{=o zm|qke<6ID=CB|`-jZ?u*X%_pM%~k^87o(OlSx<;_DBr-6v35$=29R4pK>>1WYQlpz zRSdTocW=F>o@Fr4_^NdB@9j*hnF|dgIUccXx#oEw4CEMLh-1DpnAsivz3r%-ZQj<} zfANYl*;*0({Cv;hIqL$ zK9pE$p0zvFVMfp@wXy=ibz507w0|>kmn(n*F(Hb7!8NO+7vr`HaV?#~e}PF_rNN=@rrWJjSdB812Zo%#d){-q& z98g6GuKWqf>Fpv@gT6LoeIuWjrvGYY!O$qyBic*P#N1GI*$N5*UJD_k1_$BU zf7v^VKgC3!`Cn{tJ&Zv-iob%XGmKqHYx!0`CO+lE2M!$rg}U7*!+Q_T7IAbGev0vA z&|S9m+|df&6p0(QCu|%Nvq8y5K25!Wz42G*+$R!6Ijt%UWeVJmciL4N4qXH5e{+lZ zhRBCQH~Oyy^*!1ZIA=HKf*j80b}5P-8%#ky=&$KJCM**-;&)u!x0Td%pV z;X9&KpZLb;VJ;{atZtm9w(gDiqA0M5pEjiPFF5mmbHA^IyvVI6*^U)+u2qQ_2tEGp z&T)GpO90334M}_pj5!my6E=4z7hc;L#l*(2w$#q;{3IQgLVhFu07z)JixxAy)>!&y zwS_+4;*=g)lVdlIK8aBSx&92Z$hOpHHH(dxP3byx-x}H*M3cL&E=jQ9F@H~dBvn4 zE$$Cnt@uFuVtRY7NA1rq6*x5S&LVaJ4%aFM*SFh6cW_3eCC%1uc;2v6^p0HrMusJP z$CN}@|K;1`aP;FmZjobp!iO8|b^2UG&T(5XePJ?-xUf$)>>c;)qHdOe?76w6JWe}i z1!?i0xE_^0^TspA1$nNyR?FgLu0+i@&|Y>*V`)=^i1B=7>maYcyjw0u>2I|X3$$E% zrE0;{YrphYCkrmJh-6V}shttaF0e|EHF-I!0)wK%uB(nW4#c1EN+{pRnUPs4;50=I zl;{)7WF1ymG3K|;VVlLiQ(UFC7{?f863@8j6DHfmEi@ubK4pWg$@Wuy=Gd? zypa=9v}rm>UAXcpqD8|G?5r-94;voe&tO;@vLQ(8z{gtK9?SBwSBz&iSaC>CY*l#Y z{EU(7c44#f8;k`n2KGG&5nDjG}Gm}WNcPe{)7Sj6=6z*H~I@V6OL`EwYr zWvzXh?qG3LcUu#4fY(<358r?5SgV`w%dE)>%gESJ&7$Wby5*Y2(i?kHr`O-zmALck ztG1`2a>YyUR`dOM_UzfJH*;e8PgFhJ`I}$nTjs?*Cs+R2Q?s@ByWRda-bKZeCI#=Y zwXrG5@JOgT%yx0wo{b_Iz3o9umdJd!np1OScWKh);4~Zivd}*p*T?O)G}z~vGj03y z>2_16J{1&j`de=PpFd4+?%cT(z2%zx z?nSbJyLY%Ut(fxa+0&;x-|Vx_|4{Sh{`RULKTmEuu;^RGr<>+Gt1nr!#ad1@4Ch@M zKYv}#_rpecvkSI*-@d!8mOr+-*R4|H&)=GlpFXAh{`LOk*|Uo)cOR^%teiBjj)|Y2 z-|Wv{)33=&u~Po7avSIHQ@i`wWU^Y{ z(|7Fi7FS>YcBbaL@x2+pB%0a2Y_c*5^f|Thu}jPKhj;n+J=%M-IP%-)9I=02?01!9 zIlENMmCE(bK0D|9zT`u1Cl?zTZ=QGJ{Q3G-Zqfo<``$ih&|13Z&)>h#Y(5>(o#$^~ zxLl=v(Y2FjPcM#sf002&)^p)$*6@p~mcCxjZJK{=#&0 zm^wPw9pCr2-P7CN@pD?QuJ=C%zd0wK{HaT}D0^cuPfo7Hs$L~G%6zkqob`+A%eCiL z_bEMgQIoGRnZ8(a<(1Xi-9B&C?Dsc34EJ4B=VM#;?$+_Xx&I3ex4387{A3RBDm)wN zJmde*68WW9QkI5vOXa&<(c0$E&}hcW%DVCYzW@L4D26Gndb=xI@9}|yDq(By9l7#S zUQkBHWBt6jKAF`w9@M$sKkjl}``5m}J1=itaMpX7?4={R^V_V%H}`hW&&)rU`191( zmiG2bTZ^N;lQ-S^;H|&N_4Bbm+iFCu%ibyjr@WlopYd@fWMp`3__I}fYt-ko-tK+!W;@nrzIAK4zR>Zn zhK;T5&JFipe(&!7_5Hx@+ubLs9!^si^U_R`mfE_?*2YG{ILgY5LGR7=xn;S%f%}-& za`H?$#8Gx-d%5_mW5*Y6b<586dS4nbS76Ux8|T=26AH55O<>>(eBCQ)E5gsu@6^;R zVOz9eWp2FvGow9w_h!tk*yWeIc*n0FzkWs7{fS;tQ0ScDAuyfqW%$vX&-=vZ@8pk{ z&*%EI)NI>a-u+*c820Shv*SU{&At9NntN7rB{DPXz3JRPUtdwt(Z&6$>DITN!pAoy zJe*{7_}t&B^3+et+hx^y|z=lZ$aOp);U$t$1#`F3Jk+4Z;A zKYn^GKVkm#{P(OrtK~i(S@Hj+7i&pPP?qSe29<_I-!8CD$Uk&nRA2qIiTD#I$9=)e z*?u_q_{7dSdfYK?+UJcG6;17v>(^`VSl7?)Q~&Xw(RTaK^E+Eue}?GG`O63R@#utn z-rCi>&bc6f;cs>Mx;PuXinZq=c=v=o{rPFJ_>RO!kFQq8Es$CtYWL)M*!x>omx@$a zMLtxtKmOxqp(?-rd&j* z|2gJSa_ZtK;T!vwok|Yvddu!;7&^b)i1VB7s%uNxzjr)+s4Z>r|4&7QbN9q^bE|*k zd)y9PTd_)a537si&Rx~VZI(}-V|LG=GG_Lxzjqi+eKAXa)6Tp<^!=@?Ph~lL z^^4!#an|mc5u>?C)MeZHUp8~!fBF3H+uyxAUUufM{%^&o!oxa$!mIoK9bTa3nQzbj zFE&zctkJS7M@R^V{Nv3aVXwtn6h4^ zENHdRf%7+hYHH3Gd_;n!)KcE)hQE*VdKS$;}aP;z$hlTIuMuQq6DP>xEOgRy;7% zUwS2DX-KQHz1K=LFU{#!SyzWTAFwWe`*`8;IL3tg{|@`qf1POb{LDP#`Rwwwk`2e@ ze~Q~ymoPlIvC$-Mw%u$;=BkhN<`$NPF*~;E*WWz!OZFtstCAO5~ywyEea zBZG~NNaH^{lOCS5fb%R)Olxm{ull)*S?6E1{_Jvj)f4yI!#<4b2p1h*N;nj8SM@`>0PO~xpES8^o_Sz@=h^UXoCaKr{pU_|aFTP@h{baXt zL(^$atgN$sdT-yDmMwJqzonbU1pTu~hj%Wj_YPie@#p(--#MqwCEwXlmYP@na`DtT z*L5yM6r@gy{CsVL{Yj0h!ZI&T+a~Xxd2O3@ke4pow5+xA+GTGN6O;_Rvfn-m^_*J8 zS;2TC_9Ca(N|pz{4{8p?YnF=q5ZMu*9lL|&j`$4bEv%Qcc7(`3V0^H97DtR`sr81? z?7zxaHnD672uWdiU-v__->$^Fb5>SVc3jQZ+C@sr9$tQ$h4X)?@kZ`_C0!p74B z_s0nsmU`>SWJ!qTcrxv%{2qAB|KBv->b^_6lVv{g9`f+BJ?SmK_Q}2Q`ez$wR~uG3 z7ZT?3sAL-{Gwuq;!te?JH6nDVs-o3aVKYxWqq?G;c+q>rej=4=u zOi}7)svA>lF6RE`S1J6IqNY1bx;~(&`16hJ{|zn%mU41f#J1-gUiNlP>~>Lk`FyKw z`L0eiYcBU|eyyir`XZsJ znW=K*_@lRPT^$`6|G%+ziHP7>sCe+r-{%TDcUGGCc08_#V$=Q?ar)t5_m_88n&w7L zjo)ITuRnk5>+Kur4wp4GF=gCer|K*GXil9?*zdxldO>~ZpML1p&iHdJsBcMHkiO1= zNfAk}*ftj2y6XDhzCxv0?eMbC2e-eTQM7ueb)ipPw&wr8g~Hr%(q|XU<8(c~x%gA% zv%U9EoH}Q0D%Zd-C-0Ud{J1$LEle-}eC*k~`u}+ns)TMV3S`l?lSt2+J#}YoiTJy{ z*M8~7`=>rPd~@!62M>S3+z@YIU-mER%4*$J z%Ro~$%;8Lbw_aP_byuu2aJzxr4emW_xB8Xd5o7ORN@KdtnA`BXVdDX%qGR_yFf2ZH&-b#~bc2t5nscl|OC2xNf0JG0{9W*iY=!Od{&W%9_|19Tvehx3 z+wU#@xxfBzyI}Zz$IaWCD{@Y~R(<#Xj`#ZsHxe~wZ-4h_-S7Fzd;a}2@sv5R|6LVV zLtygzXHDG4KfT(*-&-EW2jsSNBXz zez)jorSp#8jn51IHTP~!(~mgsdUsaA?G=6%Ra(#fY`FMpLYIp>%fq)%6RVtdeGiaY zU-O6kd(7>J}%0o~1jSs!8WRzz*+;DH{r2W?pSUo6GkW_vcxps<{ zj;H{?O|M~z6_4`8&kS-bX$R;RI}q@o z_tM^)sMmK7e3#f;aP%z0I(9$C^Nhvacdv2o*nQ*cZ40^YOOMKZms%P!<8c}P1NNSz zdx8fNdr}O!lH0}kd!AqA|FC+hZ36@Uomye}I-B_`FWWz|=l4&!nP0!T=BZTO-+Mom zp6}dQ8DsNB?b{pM16#u75-&8w%{g-><>Mv$%3nWcE|K%sf7N^X^l9~te*<0}cQN{R z>mds}`-N@3#SH8Azr6qF$Lah%KhD(l?5&cxdDHUD49oWCaaHW{^7(PK4-axBTU2Pw z{MUSJ^4z(H7qz|@|7xQqZ|QcQ@o~n*J%+FU&GCMHWZ9o>HKzLhe;YK<@A15T?yZE? ziYM}S{!Q;u*U)It*4y7P<3*K8X3ehU2AY*$Q@x_4Aigm3O?i zUTgJy^4M!7Z{P918U}JZ1TvOv)mt;|pHHH-*UH@uu2HWw1H9WC7=@yb72mw@&u8vO z!S8nr`<}ha)tf)FK*4fJLltdKK(z5 zTAvPG{$BKWhoEYoZv4(RR_^HrnU5mg?M#lj_%VI?owK{X-mZB3)_>>wbstSu$cHZb zyX1+8o=gq%%$booQ9tZ-qvy=qZ1nTw%Oy+GKU~{#()DEI`gwCRF7DyHU$cG2%lx_^ zHO4swmo?PvYozbpOO5}w!AdbFc6-AHtL5Bpmo1%}aOTJF$bCh*fzs#qS#&>9KK|p+ z0^LyjLmMyr`p$<46=@> zrsheTJ`&pZzff}ZwH&?449jG!&$%||tLVOE=@#1;ZnA&Fg-5CN69nW>&)ds>WApYW z1`#!r+j8#iTkcbB9#ihR^Q3&k{Q3EvPxu#9Za&7KqB=LuU~|RG`A1x?KaR+f`n>Pw z(jz~0XPKtG-o_>FcJtU9*4I0?_!~Dd)i6k0TCKUzao?G^4fnoSrZV_ST}iwwF3hml z{KJEZJaY4Q_H0|6R`g@JH7Bo8`q9<<=bQgzoi*o9P0b!#-^|ZBb8M!1Z+L8K;@vKG zam}wMZo#+LoJltS{^;67)%%~74xfo$8LM&O{_HQpH&y$5s~)=V`?WRWm5@3A`vYg( zW5O;j>am;qD8lCREu-VfYy zI>$F;XSRF&wV!->XTX%lzdw7;{Va8CLP2Pm#lKuG9qs4emL2#OblmIs4)(`})5M;2 z=ypx&uTI{W?GjM5S6>V^Ywh8P=AHPdi6eY!9?%t|(;Qa9)p)Dr{%{+DHRO;({Q;O?MQwtXKuiTp@nkgDTo!7d5ip95c$<8zWJ#b)PyJvR1 zYeUQI%TfQAO_6FbEMLd4!#BIuMRO`&&gH1-YrmG2l_lsL+u@!a`&O1`%Qf{WLER0r z4WB&}4fHZ)U}G+yx+^+AVdG<&_yyX>Y>r&I?ic2jnlPoXa!ZrIHs)}xr6H`^y_*fh z+8DO35h$sY+w)xQzzbd-+mz_36DBD5%{{g5*AXukcInQDw6vQ?)W)Y z>$c^7V*l{*yL1N!?}O#$>k=PsS>3&FnSBLkHUH9$C0Ff3 zzo5Z?rsB~@e)CS5>drfL=l3anmLHYI8{BKIs&h}5zF<4A^!DVRX)j-%>$N&q=i<&H zC@a`9eR=JFwHcbm+ShffuD^B3{%hZJ;D<;Put~}7|wNkNfVc?V?-6=uozdJwZ zE|B{mzcgga<6Q^6R%)**?A_ha=e2S>xA;a}v6*Gh#28{R#v z*WU5%^_1E>y4|+#4*gKqUi!*1FMsJ2Eg7*0o|pwwx&pm^Ui)?bRJXp(eB0={q%S8N zukOqLysX#L`+UOpdB*e8ujnikWO!{p?d{aN8w#rft&f`K2psLdf96s9&-}-a-=0;S z?x$hA<<_Q3;jr~LeZsEYR9$g(>J6jD-r407=G7g#QkH${4eM*k(n6(LYg4U{rVqRN zOgebdzLj5_mT}^=e!-RC-)$2d;@Q4=toY?;s-kpd{_*^mXP4XOJUV#2Ue)^e4~8}C zxgR(&FmRZH?g-dwIRDk8`m>4ml3tgUdfLxC`>B*&;`0Zaw6oD?#n1N})UJzeyq5Cx z$<&{x^b7j0zF${#x}z`Vg59*&|BdHca+?S3d9P?{d)iE1=FGIov*W*1mna#xAFY48 zG6g!m^@wh}&cHq;=y#)X zL-6Vb+3OMA7rU>^SuC1j#khvejG^|_%g8y68;iaR7;s9g-l}Ko6Z@jDXX?eH^52De zCK+U`HD^?A;FRdLo752Bc!;Hd@7Sw{Umeoc$}#C((Rg>JZL?dy%#k(U_di(od;a6i z{c*>RAK(3A+s@DR%Yxgl9XWa|q^j4u{hRWSMu)hHr?G9k@4ENz4;259;iYAqR_9eS zxvk`VRM9TSxfcYOnEqtkT*P_*Z1v=S&BuyAUYPyk?e+f7TnXL-KVG*Lzh0ugvzj5p7(01J`<7i_I-T1 z(!TKX4{hz8O{HPEmS>j5y3hQ1VuI23$_foP{*0q*Dzj&NJ8)o;Vx;jKy9$~8a>oiv z9?o{1-BMNa`IW|_MQ42r)MD>W{lj$j$@XcVZmHK#5|BQ&@9@hd^Uo{`t%;2~dVTFL zCDS#3uWr5&HF&_Ie7HhoG+TQ-?b-3H7_nF<2 zzh7LxW0K0~n|#=!Qfs;`d;et(wJCLTr6XmRy)1j@zx48q@{V4c-{ORLf z%Xj+QmTPlQTW(`n>`=0>eM(S2Q?G&73K=b#Z mqjSPOuDY|**W6ZjO4Gm!R~Vp z3iO2TiaeT^|J3Er>jpiql?)1OH-fD`UXGf7WCml);`Ggi8~n3l|6C5TIQmQ{Yi)4@ z`_!O*3%PQ&f*n5!)?fQ2y)=Z!jZ^yRjv!;IS5I_m6MOy=NE}^L0;K z_heC>?T62wQ?JhQUGpPZ*LK&|a!;m;uPY9oiQmw1bN-q1pQlWDc5F~Tc#v^T-0qoA zwXa{=R4II0ts(GXqt3ia-RIl0Bi_B`@3Ef0aPRDi)58ODrnO}IO5JVM{*Z%qa z;$L603QLP7ojmq&o?KV;`nTtHB)*N~U+mhIRkdsk^qUI=^UU zGUJC&UleSP%&$shoF@9FE~Cc(SbS7f-j0QlITbsP$G)6ye*D4_H|=eQo&QvRzTf=g zJFo4{4aPI){toKo;a?J3bGNA6zi_F#`ZvvA2Lf(|>&JP9v{-Vd&N5kXSX{s7!H0{J zU0hi%Z4Xvv`m6n~T7T8?K!cq*Yv<3}S!U#xfAeOHvatH2VwDV4ue%yc&mCVO8IdNv zW0l-?WyLi`cEM}C7+zoDT;{)C&&B;}@vA+@di}ohR8>}8S{^Pw%Ut^>W8$&w{!9Dw z&F@t`H~#ngsMD5fD%*O}ul1;RwUyuAmg(k~chp&C`+cjnmLC!G>gv?=eQV|A^Yg8? z_&-_gzx>k9PL=)-16t|>3H8;8*5iDns@XO6VsnlHvSC7 zb`_0+)8o&q`MxjVq5o+QUtjfYi6)EJ%N+T7G|cC?Sr5otEbKG)Yi+dQRcbyhvQl?l zTm(a{^~~Ge7fsC0e0h6sPT+PwhQGT_meo%`Htnc@*rW7cuLEaJ>s8j#6b_kqPxkH3 z&weo_9WQOKFWu_5;)m@5ck9ou+)=}_1&*8 z>H4up4|#RH#P6;@a8PtY*sg0iyxjSWfph0rm!Dp~KwC>S%vp+`pBda2*%+1#8PyI*rvS?C@+bcGf)%2zV>C_v+&>1*?so=l2=CT)XS> zWNyuErZZRERbdp_+V0PB+jFzTTOjCN!G~a?L$7!2lxNKv3{~Y{XOIA#{y0q ziaEOG=Kb%*^v<3MDTP)mdZGM{0 zoib+hM-k`4g2p;>gcdKt8QO2JAQfJT25ZhO;$RJEdqy%Zr-%axv`}= zGrwle-aq|Ymv7o!%$B)!DSJT3DP184hNV-cx3?eP+t~OoJUuN<_1W|1)zPw(K|}tg zOQ-Phe7HY*^6cNmetz%vZ@uQerqA=n{r}8H3*~hz-;1>~FfcH9y85}Sb4q9e02rZz AKmY&$ literal 0 HcmV?d00001 diff --git a/l4/doc/source/images/l4re-basic.pdf b/l4/doc/source/images/l4re-basic.pdf new file mode 100644 index 0000000000000000000000000000000000000000..9b70b8bf437ff51507c872e9f97967852506f134 GIT binary patch literal 29667 zcmY!laBINM%8)f_{X5QdVkm30Ne!G^qqE=$2oU3l?#5%CAs}RxnU7 zP%tsE&@(c(v^29&Fg7&RGc+_(hy|;0FUl`1P_VH9aX|J#%ms_Wgn||HLy8jfiVG5p zQuC54VZzSA3i>XoWtqvTLGDf;F49{(t=U-(LRz?f-TAi|hW*cmMfo{=R>w!yg^~-&DUYWPk9f`1SVg`}VDm z-2dt7{`FV({i}&pt?xGyd-nX;l=stq9g106JOAmfhac~*|5&QyV!8jd<-WMz6Q}K~ z*3D5dxL$ttdft|)?<3WuK9=`Z)Vf~p`SJ7A%iT|R3jF+Y?s?wD2ZHx&*0SGOJHNHy z_+s1s*U4Ia*RR+As;>I?d;R~Lm-kJ7xazyq)%8~Ui?!w)dOxrFfIZ{(e{6 ztz9^OuJD|Fr)Tc(Yd!He?)9E{gFRAb{_eiZUw0_?j&R}jV&!MwudZ|Wz`c0N`s!ut zvRAq9+;aTA)WIhEwlAN**8jDA@$;^itNePmU6S`-86B9<@Se?`^~G}g2g&yK`?KqP z9zNLfUQ^`Gt@2sPw)+k|e*5+QuIOLiPfF&P-hF%jO2^Xu4=-^os0lv98=F}-wffET zS#QN3RP8Uh!;v#f+J|}nyzk=qTJMxuzc9_Ij^7`5U%7DZC0j|?EiGlA_C|d_{ImL7 z_uLcA0p8&yAKTU)@jEl?>zm5U1-mtO+;fR@&=Nn;HZ9-DPMzbG%neKP7?*^v_tecx zuKvEhyS4hA`IUDot>d^0zkhvncK+CQ6(=R$8Y+*!Y}oi!zX|K>Vd^|s)h-Uf5J`I#SG znrFW9*n0EJJJU=`omXxOUt8Lze*Z4(oP4=*=B@l^3UV_YqZ+O^z1OYsSBpCme(CJW zJh_&(jgy|+UKW>QThDyLb5C{1Pi6J9e?^b{J6C3W?Z;2Klt+hOKFJdCxy^g`^0ApO z)L(MSu&-`T-Df{p>zTpRBW+$ur@t?`S90w@n7+f(Pgkvsr@u?#zkOx#-c7%M<(8P5 zR7HB1d+#v%c8crI&#K!S_vgN>;_jKbV_W(5e>IHflpn|+@a;CrW)AuC_yxm;-5ahv z@2uP_7;`{+pJamXt4P(E_a|^NUf}*v%76GnVe|6+Mf)rJrA^{39*8GgDt&0TSMhS* zzIOZfn(Dn7oP5e+!rJDW_gsqqkW_W?0DF()(qo(lUQJ5Met7(~g2_9@`xo}ODr}3m zJY&a2>61U(@}z9;e6lrv{!j0@*5j*RUz_T^Pw^=VHdne_Qu!leyRKzNor1pU z?}&5p;x$>37rc%&N$b_i@VO{QVVdL-WY>%b3%Wi!regE#@ z`Ginz)|f+vY{<6>IDxNnKpJ!UB;P7la zul(fV;mHTOB=P?>xJ9$L&q^A@lC$B~5uzQ3(_zvK!Q z#gaqSHRgg%=hI$yNV6F-%$l?J_uRT-vw&l3p9ciKR~NN7^CdU=PQXMJneS{n7KUk_ zk^sUXSisR1W+08$n zdza`7Ry&8-`f0oWz4v*h3Ww<1wiTswlQ_&@=$)JM#bD;v2lE>?E?#-=et~X~%Ey&X za~ZYk@8-PzR}`U~^@i)LP#43mJ4bo)75fyQiV3upoNnD$XY2VpLp-Ind$!9x3-w!j zA8z*iGYQ&o8XqQ4?eyvB8YUG4=L=T`lATv>0{u`z&=>qVDkwerv)n z)hF`Y&v$=zcX6#q@>;dAz0+w%R!zH*M_u^4_YHfh7?#*(ef(F*`R29+Ylw8@!;Fp0 zla{2F5Z99Ey8&|E)w>o3FLHXb_52KhS7GKEUpY@*<(;VBT6ER@hE~A3yc6f0cJETu z(!I20DP|y-S<6(BUeV^Qmqw!zGr} zzM1$*#xIQKUH|&mR`u_Wo98%fxBBsBgKrK0$GAl=@>P$pZpr()Z{GfOKhCbJzIQ0i zWYcX^+qV2!o}YP-9G6=8@Iaj(lfK^MHGv0&ZeQPPp5KwQ{6dU`@2=8~wZ%M=&tAMd zE0?d~@m#ESG3(1Er+MdJ$~d^jJ@oKYrjI)g?ph#T=WC?N$p1zdg7s8=n8#>T!JX zl=llK>=Z!2k-d7??@>GQj@L$*zszkG)D(myk9y`1!kv2_Z6 zM39`mUTodGS)Br(B5vHAHsN^IQn4l0`s?m0J>mRY&skf1;CG>qnaMrX2Zjf|53oym z9bgw>`Zw1jKhJ*k3L_SqgpW&)oV+JgH*Ldem52F1CV4FG*k5hGt%E(&*2U&ULHCc$ z{Tp2V*s906O>?y=JG@5m(Z;}S9sRx{O8@r$-k*2cQ+$K@yZtJ=xYRLg^1FTV(t$5) zE8n_12=gVeEW7WtWS!ab1s%56!g~vTBT5}}j{C{lI-=UU$z@B@ah)|bWLBjhF8{-@-7S`4_gfHZY>;KPs zzvtVNYahRhDLtq-`1fzi_3w3s_tJlrT<3Ure_vr&b~65Wc8ArP_3`SW zbhWIBlJ_#L8vS4Kn%5k%t}Zf9-;u!3pnLa#!fY!pnf0CW`=WK!U3nI?bg;bOWRi+u zVC3{olKu1XUO0ooiFJ(02QPGQsb9M&uIKMBV5o_W&t+TqL^!*`Qc zKFwXQePKH1{U?>$cIH>uJ9@K@-hEfOzexXX=Z)Lk9Wfm{-UZ$fu(sEz%;Px5a?P^* z>-L1j6V@i_bXeY1NHJ>b4UpQ=^~`MUxXWfvdb^;>hZC!;aJgr)b_^N$Qi*r$DY zmLmQ~kKsYXz76v?-D|y6aJWE8(SphQ3tRRht%F+o7f#!A&vvt_htd%?-j(fn5?yZ& zwkOVKC@km7o^#_vM$4-D>`3o`)^e*p0{jqZ1oG(b68sd` zh%c)ycD&kP@tNz$`S1gsTU=)(@A%0%&B1P^^s6ZOg5}H)Bz_s$v~_S~@w~kDIPb-? zkB(c~zP(^={&m`yqhf1T9JeBSnh-P33)V$uowN9VMeMAKwcRHb89h<`sh3Jl%S@BH z3_Fh6Ow+vyme1aKam}9)?YKLG@!kZM`_`*(gj`wRly|Oh@(0ejU0W`7bL=nr9-iCm zb*n**qOkRx%-%USr~>X|lzujeh?$5(vjjHNAibAQdY!0gJ|?;o3QPiyS+$~q?SPa&sq z2~%TFQNwM9edTX?dHrD$HILz*mIuv=EG>Ia zD;SI9Fm*olPF%gLEKyd`BJ$*p2X7OUoY`5aBWD@1*5U(<xpOf6`SpW|8_NaC--OgnG;*l@)0W7RSZ|zjCv*Dlx7Az^noN$oT=n38W9x-ok--!obEqKQ} z>%pZ20k&N_UxeFk=uLdZwK2BD$NAGeqy2~SW1VIw{kd{lY%9mLgKb^&h2JWj_#vrSG+a5zlI9ety_ougM@7kkrdfkhe zmrj(iDv9pAweH0!{TpShhkV|huyr*TVT)m6sN2ZX-B;2q*XG*pw3COMB_r+D8$QKZ z+jiXLt+ajMEPds~wA71isdo}DGhN)h`u3(94Q0^>Ht9%R<&zdO53s7(s>9t{mGJr0 z28R{u-wkx~IDVH%ikbTy)I8m^SkhpF@(OnK;s~)Bi{lP$IuNs5WSOhZY@hDOUmZ?t zxnWQd6aHwS54TR?-D#}XBBE@zedWCw(O_2OJiYYC6ITC6DhYwLA4N~F=oD-<6}Wpo zG0fmZS?kjStoOoL!z^?+GZkODY@{tAa`yHbhYvcjiD6q*rzM7MS?YCj&4Ei-Hl6Ki zIJ_p~+L4s7Ei0d#7YW?u7i@Nh>&Se!2vLrm^G>faII6e$P;$KeIRU%S;;M7GAqoGg z`4&HFTNc4_Wv`z3+TJel=Ax_{jNz-yH)#rRt>K@|q$lAkV^Q>hai+*|Hd+1ZWZ~I0 zIy;znW;2B}*$CejQRpsd^}Q%Ocm3&Q4mO*wY|z|rL-+Qw7hSVuPcM6M?Nn+=!uBn4 zZmePZa%VF|uRe73h@wn{&68`VmT{agJIbbb?4#O^897{Rm6;p|mRbDxuqK>CVZ!50 zN&*r7xwl0WvQKLLo24V45?pb2x^JVbP1X&Oh_cLho-(`Vzs+x&o(s618pJS7V!B-y zN6N~?U`~9!g0Z~T4CbZ8!8*5eoYCLHgj!%Yc$RG;&rj+JueLWw)qw| zd(Lg}y}0{MzlmlZgV%zsJOP^oyC2Q^;~@V*D7WsPu-!Dzi=r1ddNu~U+;M2hi>_n( zlbI5)t*qtWUN@g-*N(S#lDyGstV}zu3q4le!H^uDK11t)1XqMo{Q)&rr@4s%N0{0i zKki$w|Cn~-_kc+U`v0&OZj-vuubA7mP{br7&3vzX!GWZ za^2edb%k1gW^Su$zpyey#bqAbro%T2Z?KuS+_?WR_KZYaukGJt4X5iJf9D3d*l0S$<^y%&6F5&XU5d4Tjr`O88i0HjB(Wm3w@K ziB7ojENQ04?X9K!$_f=;E>>yTo`% zQ+Hvt&4R^0wz9T5-IUVhDQ9=xn0Z2j>+y0GhnuCdWqcX(pPa0)v^^P=`_JH<@ACgC z@0j*gPb^f3Y2UGJN6++4di_roT3a^1Nt5N_jJI`|bgy#Ve92h7M2))wI++`myqwvz z7l)>-lqOV~xJ6w!Imp`y)O7N*Ery z{KDa-$C(Dha+`ZIw;cW2E7q~Q{l{kGpaP>8R}NZtRrjBn%>1|UQcE$L6mME~WAzs9 zMv?Xk*~y;OI=A-gNc_xQ%DXNu)v7#f{pMO*!%K%}%x`Usd(@cure5*dg?h`=hfMx; zbI+*!({j?Q#nQ6ltyo`iUa#fU zRK##DYyRyP{yBb6n(s4dPMe`D`z$h{%*{=q&z9NZmtys6*^5&xKW~=)>5|~ns_FcO zwYsxev0>dA!-BiBCaG90dZK#l1)JqEr)90Y4EK(v%o1C$OrX-C|GuZuR4Zf02-^nl zZ=XMG{QAoBK+(s~8~*Q@qu#DwfBN_@x&4GbDxltKDGL+xc??y7fZ>t&2e+q^SAKS?@;DD zaN%i{&{t*d4MH}qf1KkICAuqxS^}G<1k5nqe#cHw!T67o+q1|&_q2UWW@tT5>R3PD zu9t=7Im;=wUrd4?&$%BpUnqXMz$){<4vUH5I_`PL&)LnKboko4XBTG*Pdg}}efZS0 zhx-hV7GC0GsVFVd`jKWS7P+wKuAD@U-S4^wDbI{&v1_MVW&XY8{Jtw=*I|Z(TVLci zH)cqPSzq1Oy5q&e$FDQ^CF6hHTIuu1>aOgJs+8&rnnl?_D&n+T2?asXY!HYzsCeD$t=-B0VV6R2_(m?JRJu&mPOt@gJ zb0(oo;@7$4WWyPU7ym5H?$f*!x=)fVhvkX7(g&Z-307swSEQB)JC*XJy)WLgR>19_ z|MZ!~2NR@p4~PpEJXm*MIy8NMEyKENl~?v$>b-Wov@NgnY{HULtV~sBBX8B&emwCY z%XaO}FV9OS<(2xW`}bY_ZPB^OP2Gj3ZtuIDH_sNo>ihcB^zy4aw~y@aaOl|d+T_*z z)`ssdl-y@;NqF$DwaH}5=~;IUysrMBvb)^M%jV&d0}%^+rN0Fo_$b3~vMkt9#BrzF zyw!bD+Is~%R&yK9p2l^GVb6^V*Anl)T2pe(&A?{=(K**IPfk(d7CaZcw9+KCo$poJ zFR9M~?K6wjy$=K|`nT;RO{ZX zqA%HoaizZx&M;l`bvJwNQ`2WIHNUp1^PbAT8yvNwalPjL$mU?jJs#23oxGpLovdGc z|NQN(^Trz-uLX_kHN+fjM7dRd*@<+|v=`~F+^Z?}xhhy^#`izVBF=mY(MhY+67y)S z3)Y#i;ZJ~0TCJ9t`ImJOEJ>PT75^4SEZDj{$?$c1QsX@v5$=?yb|Tz8Ph&Saq`h1s*0w!KkV9Ln;_t$U1wYG=COuo8R9OCQWrW4@ip%;% z6Xd&CH`U8`u^I)D(vU9eGcbd(9E& zjWe#dClxBs>tfCLv@)V0|-G`KZC7Sy+6D=v?)~C!b91R8X#6;2^tnzu|||i(S{<<_XhjntQOz z^`iKtDW`w^W$<}dFzboc-+Me)JGH6|l8bznm`;`qt`|J=Ijip4ni<~rl8?TS>zdX) zhGwxq<0$=}ma7=EdpkZF&V_W@$z1NS3p8GN@tnhLF(U5$n?~BrP9#pd~bi42T*fy!;H6w3q{`#4n*ODK7 z`8eb1;knhbzutGMINcv^w`ZG0%%^8tYZYo9ne463jjsB9OR4|K+3fDgZv5+WPrr|g zell}UW$wdQRTU7TaL?1T*{_T9PiMatT>EZ1|N6Cp{O41Dez_&JdG9v21I1qXPrltc zbo0l%t+`LnX5U_CzW#0U7VeK2!I1OD~8{S3M5*B*SkHFkge#~-t=i(UTy zZ0k|aZSB{$Ej3@CYi+-GTQ%F8C4adOI(z%8zm4bUd3iRwJNXa)`nCKo+pmkYTixHY zE#t$(tw*Ez!RFNd@td^s-rj8u_xEgjTlM+Yrr_Jz+#k+nzyA7{J?{3oBYZMer<+YK zlzMq_G%SDRln{Mjve&}SD34!lj|$f8WnFn|%Iof5)&Y&oHmcuw9+|{kKYU`tv(7!5 z$8*DFHLr?ax~_k%s^ROAeX7@5Uoc%PZ`Q90j;zeFJ)rXG>$ij?rl{*VN}^t-YZBPZ zmzHeK_gG=LXIGwq=j+d>&n{=VWA-eybSbZ3kml<2{>a)hzp|BGIE(BzPihxso?``by>h>wPT5gv`fo;f?H{)e`2E`Qx7S~mw*RKp8E{p)cAwE&U90qhwao`pj!(STTe$n}@guKpXWzTB zdF$gVpObS>-nY3imD4uGy=;o`ITaS`Q(Ikcq@~v}iOD7H%kGv>Tdbet@Wr9wrn8`a zWni1|YB}y|&r_U@3e9GZ6BrhCI!Cv@`1Vh2SFgl^6E^Q=?>xn3IPrM)L4_aN?v=W3 z&zQ}g(EV#+Z^>G{wYksi-hcfvLw z)yWS#CwiSa`1E;Fxk}j&u9686&o8p9tIaT&8S%xaQ}Ue3mb|DBpPH_-=`KzVkKfW0 zy5g^5?5?1F{a+mtS@k*kw}de+TE!l_X+u-rm#UzTYq_KU<%<8=<^SM9-ks%wJ0dxD z2k)|(_@3ix?8N$|>rVxVG^~+WSbTL-{fXVHwEi+bY%1AUoM$w9$piNIm#6l1v(L$9 zJ>=cxHiJiY=f#JrTkM`R&hPctF4?TL)1pYZV$FfGCttFM?kWuX$goi5=W9=P+dtZ| zE0?PrcHFSlH)S%rfw-Vt`1QmkUmJ3cB&^(P{Qs%pr(<*OB&@u8b zf+q`SAG1*@601GCD{@EpuD>&;|Iv<^G1E-bPt@=B5{u9`C-xi9517@fWWL->_lf8( z&yqbekL!7P_1)bQIP0*-ySgKJQ+(fN`EkwLz{r~K_j6UzkBD8Hj5OD^d#v;<77CtM za?xhSrvSxmKVtd5=ZJH^2xB^^Cw3+*G5NTexM*?lGM|Gj}@6M`*ydS`1H4oce|C!t5--v>J^9fO{96O|Zo1C(x%BF~Q$2oD z46*|Gm=mV*gxJ{%tjad8RB0@Jm=w+<7M{i`zs_s6t-Dl$6Sc%~_^_^Dh`$2!O2HyyV1-(^^P{W3A4Eo;I=5$_o+JEul4h6=a}PLw~}JMY5JptDm})fPyli>|DkwsWlz z_vxZbirJ1YpSMN6*E_l@CRo~2yJIr%jn>06IUddQN=b>2NH{AbySwCbMov#|VMX$n zxvXNDQ{#h=H+FH!eEstE-2A$$;%PyWXO13X613r28k`nwlQS=A z(X+(KGnx6t+L$!w@on00lI7>oLos^`H*Z+EWaiPsZHpEhJly8>LQihlPTrH36OtxRJ=4^FR#m}^MYX-_{>)Ba&MOH?!K%N+ zglB7A+CEdld*PCVq{-}FP3^iG5io>{g^T_!EPVd7=kJ2}nI z(xe^p#3t+Jm2IdE{cC1^cwWFm=Z%{sc|6|ath#hAEnSe8zpm|L_($iD#&cu1>#l{) z$oaT=ovm8kG99jz-K_S}2_KA=o927|j{n26vhdD>N9kU>Zm@Z|d}@wgIqOLCeBWb+ z)7Vo#<+yIxys~80*>g>MXUy#ko-}o@@v8XqPmHs+ul-`r_4bta0*#o7_Yb~XP^tSj zD$k^)>*a#ZAJ0Y4{eI)IY3h_`%U}N8Dt%U8-&`vCJiqxYvE;fsJUL5fdOiM^Hbf3~F82$6BXevXK>MzmMggcw`9?ufKCReB6 zmzj6|{#)0e-f1c4gag^ub^P_Z{-x?_hf#*@>pr6zoe%2++wPxmTCSh_aPfvSD~oQ= zoGQqW74PiDoW)hs5zl1!*73nrX3fstiXP3(==GK!k>X`X-p}N$o)IKb-4JOg^ZfG9 zAEN)*D^@YQvf{XBuwg;SWcg*w)ioH_UR?XN^MLkGS+|Q^4IyiV`zLQS*IULOxa8ja zZ<>p*d3jw)T=6n%gGeeTUNLFQapsFN8Vy2Otv2t=wVe8Qt9y0cRq4fh9Vfh(I%}zP>EXk9wU*gG zs^hbdYt+Uk-dwfX=$zO+i4+Bwndw8k{VphFR6OO+rm6EYsx|FDzD+(G!+&#GX6@{6*WFq^9cJ6MBdt6_C;X61 z!j7MJ8s6JZ(qgy}zWT#7`R3zNy$P!&KW>^jA>)tXX5}7ZH^IflVTIScTG(2qYMsCT z`tnm=fuADB7ylKy&iL|otJ>FBa}QkoF2rVjxZ~p|shv^vXL|PSOIz2ft5msY-~Y`P zk91|8GM$(xD&8UGSunG*asG!SG7QcQy=UQ@Up8v1))_m$W% zSsQq+b-6Ju^e|X`@aaOXOJdR*bw=~eqzvxx)G?%A{aW>yH6r~@%KfaPhs^oh7CjH> z<7Zc9Je+haUSby0<9bj0)y*Yf{*8ZmNCQqhi6Q$JjUXOghS`wpz@_qETkX z@u~%vZ%dt#EDe73^}*j2;upg_7!$TPcBve12)8Lx6zPBR`fFE(%549~C%H>zo=Qw> zco%stbG`pjeR2IAWob%v>1!uRz7k7Mzg6jMzG&HZE?Er@&xa?zFw&Jw5UC*#C`gatx-MKY5S>ve+LLwvnqRT{We)!;^fYt z_Zz<~sTA!IH-EY7i+0mQLn;1e-&Hoy&qQnl5XV{@Hlz z{|f_)O|F+KKW?_#uIqEBiAz;81grg zrF^M_lPAZIr7}JuS-1N|j_u=IzTV?vih7kws?yrovQLk$@`<^stP%66<*jvHg5UFf zO4=Ng&1RlxepK(f*&>8Xe0ybzQpEy+l?y9{mZi(DoXZp%+)Q!SJB*RKkN6-GtiEDJms%I0>6TY&! zPJgpcz{^Xg>Rw8x@C^TU_rC-X^FUW`%LWqeLs?fU7HRVU`<=*3-PSCD6P zUsdq5>~WR0ZT!dR0~6=-zUD5l4|ggTivP5Cm+$wu4T52D-}X$DHdq?w$)z`+t04KK#di*^u&thO)7qsn;k(7c9+vRKUY0I;m#Y*4 zgJW4b~> z(KPvsA2W5%rwYb$1o_1J8DHsK*)TJuW|P{fDi-%!YuV16ep1tC+IRibnsoIx^8=Z- z4{fHds9*M`@sH7_`jB=O_Z*GqrT5K>)Xwj`!mDOEPfpr+!S3j@fv?^raW1(ad+OAt zE4PGQQcf?}q&3~D$Z)AxzkHAxM|l0hX&$-PtkUQHdbO*xJL^ydbD;9~3SAM^a__S7z^L3V*!Ev|LNjv47?)0i0x5h}8T~&cyjItqX}=u#t)}N-vsBEg zU{1pwF-|*bJbOabYU}B_i}TK?3929b)B3>LS7cMb&6Q?chZ*!% zEogjWcy4-Ls)UhFbGU&l3)}5^2hZh9ZkQT<^W4vhMY>Pth-bJ=lH9*2nN#^mg-Tke z`9o<-xeY331Xmo-;I4cb-(mZw_vDst{-sBr+5Xv}_3cBq`1LhHE1S+AjMu9BE3?<{ z!h82maW_|X8I|7Rn;BTlHnDo`)_W&BPmATV9J4=#B2JpZQQZG1)8YTJ6=X;Tl~(CK+C z>8d|rW)PZTJ1>`;)f2g6&dn$UpOmNxvJEyDXI<$p6^Yssjr`&rlQT1`Ov z&e6KKODn3LZ%>L;vwugO#VaVmXOv@L9scX$VlwGAV z`%PsC|96}H>s^-Y+p^a8Z=iH$veNf1m%yvN38z<2JhWNv&4~a@UYP^|@s;@nJ-Pr{r>fbYP}0PO)Onz{jbUOSt{=sDtkoT&am5g zZJAh_V#J-epC%p+bNxQevC86G+)}b)jqlGR`=(q~Zgf~%t|eaX`}aX%%kfJkT{6mi zV#O1Ro3{I({ib{QpU(M~?FR2AvQ0}(yv9qh-AEbkoM zYaw;Gd1}>!-<*C2H_q7j{Kdg_ww>JztNTuVaF5O|IP%JBrruZA@_M-$!BHwzdcO;$ zQr50|J9X}!bG$y8D>9lY1^yb$__XnkUfhZ7zvpuFi+%Q~<%8gdTD9^5ng-l15=g1*%M`^^r$>-xIq zj%ZHbyU80THNVN-KPNXrbn%4UObR_}o7wo5$MBc49-IAjkKB$K9BSM6IJCYdf0%h| z-)`;?RTbJi`RPZUECS!2*|y(BBga1X*umF7D@?S1um(8|O-`22RnQ zz-^oL#JQX&e7}&U@nr3>M>@<$`{zv8opJien_RVc*5&7mChy~V*RE;pa58s#`LbHk z`N_X8`fmLGZjU|3^J}d~^ro<$oFMl9&9WPoY<`^otG(O8e;Op5^MAETBPO(1;fVpm zObN&T2Ty)-+H>}ZLRVzGl~i)i`s;ryl`6hA-=4k7RqDR+iw2=xDLq-!4_p_>51BWs z`q&j^}W50f{{?N^7ISCbM9=Z?uI%Hg>O4phvy#8zQxRWEDD}UkXQ|Sw| zTfgf{DaJEi(qwW@=gNz6{A0cHQj+SG)pN=%;*3mqL>GrXJTYhO4Avf>4iUMY122}{ z->(+3PRPQ<_&v{}zk)N4R~=ibY$XS=mpl`S4QmUR7uJqF18- zRCheM@n+@ar51NMW^5D}cjb+^%#*5Y5F=TTZ+5X%Yl3*dlYLr2PEOggzFON{jX8Ny ztR_J$*k--DT5XwCx`l7TrkjJ9{8%ccFkq?hVs>Wq735KJv?%1Ma0_zJ=55Gi4h?)kQk3xOq*b-kai1#`D}xWRBb;f05NEXVIy~<_VjwT@*9Q|KV&Onq_Fn<=d5< zxSx0ZqG^o@zI`uGuc=@S59FTtd1=M!vmX|{HR+aNwpegtZ*itVz(wQrCc6(gAF^Jm zKbP(5A64VZnQO$q`V^T~#dT8?RomxOU8Y%gLUSyw2(Ax_PXv4_5iNr7ca^xM$^NftJ<&``GHc7p}O`GGk-k z3MJ)kjEImO9od z58mt-nrjaroOjZZD`=*ULBk)7vFt2_n1vw z@%sPA*2Mh}mvU5S2>O55EMVUYiT$Gg>=t}jK4ryZiI2s~>vrU^c1+<~+@mqcSgghS znbmgJgrLB}&-2-r8P8Re^4SykD=OZG>Eo}WnH=j)qEKt#!pL)&Ik!da(z8EqTkJahdb;g-gMj72Qx$SE@0J{w?nty+eZwemncanD zyaFeM%)0+rcklQdyh3Z&v8ypQ3tyb`h(BE09I{$bJMe(<0l|e&dmWUX@b)G7&VRXc z-i)cgf=komPc)s%F*2%qHv8gRPq&Mz)l$m&Pb@ARPi>w2*7!?*!;vr%{j0SLcoH;g zWF=4UlQ$C+&6*H^P@HVky^Hzw1|#9D&Ldf!75sim8`eGK53S=ka`cj5ds)0W8~3U|{0%bt z{XZB_P1l@!>eSOm`!~g9ddKJ_s5zPcn8E+wu0kzveQ~sJb(qWSi1j*!tDRq;S(14F z!;dLl>=#en)P6oIciuLOqX*XtP6?jAcimB)YYqvTb*%0WB^&k}ob2cLi}!xSx#q(q zUf0?AgF2_m2VVXXx3IoB@5vkKsp}P0>td_wTZ+5hQK=9|Z-w=n6O?lnCV7M8|sT0Uj|%?F~=u^sC~x{sOgb(K$IG%~F?`XD54 z&6ziMEUgt{UNWuHQMWQV(Rj=L;cmBSdgl(bt!(-(UUmIrp05l?V|o6%zESMCP<`%b3;nv$t)&7$MxSjW5Z1Rk`l@DYN;PEAu@QQTrkH$y2Os zo4wD%r2D!8-{rKXGP30f%~_?X!za3lf3D`4`wO3zOlA@L7Sk4@`8qd~@oCq3!wHL5 zCEVFyGkexj7Ke~uKPK;d?D=g6C1AKH!n?=<$phN#?>fx=VF-bJXk&DY|#| zd$-K~kH$@&kx5KR6IGP{TkbV-ZU5=aHdXJcMD5|W7d-)!-=6N=Y+!ZwOS8L*hCD}* zs(zCC#8Z!_m+aazv$bXN@)5HcQ3|K3k$Bi* zYcaKZnxCEDurqy{n5pscl+znGwV7A=t0p=3zr4V+is=-;OF^Ztm{g_wx&68eMVE72 z`Z}Zen(We!u!=+OSq}0)ih}<=bd%Aot&vQBcCTl3n*GB~Hw(@+G4mWr_y6%Q>n_LN zAW5fN6?05v*f$zE@1E8#&;4h8x$K>=i@M_f=I(0_@tYUXu=LJ^OHR83ug_unsNA?& z@J_M1{xz3v$qhSR*BNcpGvM6)rlr0tS;DfP?IGucZAY=`hGmqHh6dSeACs}8E2D!&1ji@@!#_O>d(x@omN@#ZK~y1=_6-z&+P9Z9j3@ zVcO&PS7Hw`KfCW^D{KD8P%XWqXWRFMk__MSChulsc6^k-Lz=H|YtPey2X`XePCY$v zbIW-qJN5&g0!}_JSYsL=*RJlC*WNqve&Yt+LMu5B^-Mb({v}glroV2SV)XfwEkjt1 z+MCcxZkxADUbFCAdgf`J!onp#KiDVixNK;`rsAP}ov*CO?$3eJW7;dX9~YkfboLy9 zIhPEUJZ)om_9lzPjA3Q^l&9?qKO_E5Qf|_g{;U{&$92`v5gbQ;5*&tE@y zGYGF{kmj4CW~osyG4llTj_FboQlE?bbgremKhie6`qAWS+saT24Kpu5>6+8Q3u9+Zf68L9*HWAB?VC+^ zL>toe@K-Rld#meawN5%)&Anw)iz=(k3*)NW-{2CU9D=dE>XSxj+o4^!|M;8 ze0e%waLMLBVk+~ZuCUmM&v_>|ulqdfFW;5Eb~pCLh)XNpXMJGsFY$3#tX^XC;@w+* zzuD!HTP?ofv{1HW{twq4omUl)N;WnB6?f41mi*s!)v9e0d^`uv-pj8rU})Bqzuhjl z;_W7dV@xT@Rq=j2HD))@Gj}rcDR{ij-H5-S zU7LBbcw*{LBa6A;)*hZ&$e=jc>0J+RyZz(Nhff&#W*9jMbUyWbb$IE)_f|r@cc=cH z^{Mf|%7b;)&6bC_L$-Zo@fO_h=**{_gfB|(3UV{*rlmh-kkS3onsFe?!}@x-;ymH^ zwVNH=B}Db@C+^hv&t~vwTS-AdYjnI^A8&iNvVr>#iyKXoogO@4h>?vo-5M79XWMLM zg%g!OEpME@xNR{rhqtkXm51v$kK}_w`q{gut$zHWZO5%or3HHHH>$F&>g@d}ptUkp zeImzUQ@hPeIkrqFi!8YPn2{xRj^e9;4Ts`dPHy(Q@$4E~TRf+ag=NFUgu0|jdvATH z-k|)6>*Qy}N0X0D*tFYj{nMWe5p%bd%v`g~RyC>6H+{i1=1f+D2Y(eLfBv2EcV5;H zd%go#cN%_Zuz9%pcdJ9khV996b^_ZB)_gq4y=lLuIfrI-+-crJdeNOzw{%(0GsqPzl{H$D-Q}EZXZ$&)|q~=_|th*`j_ttMK^I6g? zovuaSHr*u6b>HLB%TFIav@W=QT3*A4yKv(j<@wIPxBqmXWc=)ey7oKe8xpFQ8KyCr zRLoN8-PI(%aQCZk99)cZ=DMw0Tx{{xE%7JMt&S9S=WOqf>~DF)O}401demmb^vyE~ z{<|ZLgDHDbg~paO2i2DFDJPo=eAnLYd;ipB&&>w64USEiDlUryn;*q&(AY78WrTdE(Y}XR?~9{CksMLHanpqL7`@3>9=X`zZ+bJ3K>kZq}kc-+p zsj<7~ra@JHv1ZJ?veh*hw zE3-3L@$6{w^-6A~JFA0!U1pK?o18q$z)>wK;=<2IvXiElZn$xDy4IaHszIeE&%2ti zmZ`6v|G@3Iu&XzJfnIm~qHl_9^#=p`$ ztiZ1yQyUd&llZRUnm1=o(>iOC?tr9k7 zJH)dLmj5f(jsL$k_L`*WeZSPrhSCdHJec%gzVtf&A4M}lmzpyz+CA%Fz48M~zg0q8 z4YUl!&KefJz1R71r?SBM^)CVw>hgSQ52si#8Qjk^d7!-Sca+B0H|dApRG6%A-0ROM ze9unpsd;|sG27*)`pdpP*EXM@V)!gQIm4}3V~@eFMhm9T6)(5w{E!Zw`IXD3#>Sxj z>vQw7YUQ#)-RJMuF1z&Q+F|yzZz(*jOa^D}7aUcrTD`F~V8_XsX}!;a+_oyH>o=Td zeD;%Tg`UZls!fu4cUd`ZcJ`{VJeadh*!FvHqW6KKZwyP1%y4_gz2nUvi-wQd!L7x! zUkleTT;1wtEfElBr$2XF*2>7zck&`ZO@8s zF!Q;IW!D|?Y`m_U(a=!ZYO45(0;vjVYhOQZ`?qO+uh`z3 zEqIcDkym!p&am^PF)tQnZ7pkgXlr}C&SmPxt1eglwn`sj>2Y0swJb!jM@CTg>&})L zd~7TmW3mMmv>3(Z+Z(&sZ+J3RFV#QpUGgt=<1+8iTJsvCbswWYtA|kG!>^ljPcd0(leB@6q^4}06V znZ;}5c2#%lNL*a7aP^;U8+O`Thc9D{(0zR6+#2P}5`IoO+j@-hL+{RD?lAr%t#B-D zyZ7h4$_G-ajSPOADa!TR{`lXkQq^+r=sPpcnf_C3i#u$7X3M3{Qu_~cPe*oL*u{9f zaY@drl1=*4IA7mW{=4~dV^zYAhxK-Q7q@TP({r%q<$*A9^T$t5@HuL<%qo4lVb{f< zM>Z_$7MdX)=KKD-G@I}dF(qf2exYc1p8Y~1^XA;fRqGLPc38;^W6dLwX;+`eso=8= zq5(*PWsUYio#_?M?TcQ>Xef0W7&yjfTzcN$6t=o{&&|JK(`MFOjrg%{ zOO)gU$2AYPG`wzcnR4{;#wdxZpl7#Iom;IJSvAc3(&6{0?S{nbA5|XH9Q|)OZ}Pca zHeI#w#|>q+uC=QtyG|$%g;F~@7zJ;ua zZSxzMlyxUdzS~UeZrq?^Ef}%R?#)BNH8&*_kMh5@Ts|QeS@BO)=|RVuet*r6yH#d}U7KFoT>R;A=A8qXFP=p2_}s8FrpPfgHo;T(N}cZh zo4))!HCIY>*KZelcJaa%ZD!dnk?^W*p99`qVHON>EaJpnq4Skv8$VoEzI)Qq_lU*rer*@Aka??I z>oP=I{Mi{MNKYxezUb)6NsbLC1@qXi&skOM9JS=g+|-}{&K4AAE=$&Xusb+3G*n%A z@4@C!Uo*9frOVhZZA(hq$U41tr*3uPebc2jS!Zs__W5WX_;f(|=&i#u>Kf8i)fSz6 zdQL#~`Kg=J(~9T#T8bXvvAEfF=D^`IUlr5^cuX5b*SvZ>G4t@IO;`9~lH+w6a}t`cz1NrQ=-{ zPrP{*;}GJtFq2ivG`Q=e{!`ZOUnTD}=e@Z1sg*C#Z>67_D7!?%#fw{BYR8seNY>SL^7A=|p_2l(98j%qk}AX!v{miQflK=8ITte$O_Q=iC;XBWtEH zEXoRUD6PvV3{dh&d2b^+$Ks&1_j8?f3*Q8s{TG?I>|=bfoaDZ9D?7|=wnVlr?QNWV z_2|#u#>-Q;hxo|8u{C?NsO)D{|D7{aioQN?%=DSw?N%)HN#RI2^TObh5njp_S~J;} z3;vvP_K6s;+{d%w35%lbr5EQ$psYixnDwX6VL+9}nFdVrL*Ky5qyjk0Bw~pDbc*dHn3t3Ym^y zoQ`R=FaJ$hvgHKpE1^@@g%2Lmnx0pAsIWB5)HP;8`}NpO7Ml+35CV@YuB-xo+>z!hPq|&5m8=?|Le|pxew=1gJv6ZIwKh?>Efb0(Zl z0ecj+xP7FYtrI>l&Ui3=U6#U%%Mh${)8?XAGznT!)_Z_q^&Us$;;XbEOwwS_0s+hyEk`Sf7%6{eiodzcHQ+~RY6JlUvw=6Ev)i?Y-LMtahF?v{LGqX zriJb`cFV5L{XL`1?@5a6;jMgb4}wxt=8FBiy<_6$K4<@nojF^JR((k9dUb#&ezSe0 z?omO5{)cIsdF?J_K3{iz_o?gap6SQiJ~^MfHKOa{UG9SQZVEN>wRd8cJc%$_ul2(A z)Pof)ZjY|+xAL`hky_=E=9T66eb;|8ff;j+zkjt#OOH{SJ0tFDQ@GW~S#KXQ&9Lg< zw)_8Sx0(B_6LkX=_5?1=fArCBV&RV)n$B^ef!2JM+cuUlojcn1@rI^F(#dY!Kh=?s z{cSi`+*S;`Jzd}Q^LG8~?&as1Vz#IqxuyBBYQn17_m{j`&%SbZ{>I=%pR<=Ad62X` zGihWmTyqeatIYuI+tr z(WZ>+eE+h)4p&7pK2}Z5+cI0fgm?X1rq;FFukL2}UcmIwTkY?z@-F^r+cK|}`}__q zxfgSH$I--yz@Rr%gtq4%@eB0a`}J3W=8b*n;Ztwy4Nls$H<;z$<+(wj)k5($kyCfL z+5SKE<$Bb#DGqXqmp|SM_NMufg_B4az#M=O1VI_IBT9*|#rCWX|{ZR_hL( zS3bJunJMF^m!VJlj`xIwCLeA{ys2Ao<8s=Og}>~5(_JdnPu=f$lU084g!&yp}!xSpCt>$$PG}mmjgLk-x#*=px>*A+&=XcJLib`^_A$du1ZQ))ttg`e{-|3l+GUQ z2~z^ref;`k@5DYSZndVqF0omfc?x@Oa0RSeRsL+{W)X(vt}O2j;!CuSB-i=w++X?S z*2~j50kYP$e^09#9^dhB|G)P8aRGn1*CZwWUC+*RH>s$(gHw$+fA^$c$Ja2as70(i z$fcaS(7V3Ht^Ln!mA|pu*K9o(W3cMOj)pDu(OQRBmTh^q>*-~~UDx((6;L?3Gycaa z3$vK4*fnci`HFX+k?Q@)d1f1b1;^uGtQ&iDx1754LOQr~d$Zt9nrN^hGM&VqLz9hn=2zT)q6keyii8#jT67ZbtC0Y8B^B zu?yqwo7aCe<#VL9{B{|+dO40Iyo-v%q#Oey_;nn*t}w=Yd=ZuGapP!Z-n_D=x8?e- zi~qNM6WD7wqi5YYMTzUPLT?=MnXUF;;JBN8LU3Y&Qh|ESRbGv4Wl@#Jb=Q97WoPJC z1U+e5eLdG!DsZcOPe#}5z_R-S=qUM@Yhw%YTS;-)VpLpGz)*7NQrYIkpBJ=5i8F1Uy5vrCwG#i!u3K$SB>%=7JFs_(0?&23 zBPk6At8!jFOZ|M|q#nyA{keq+I!nLLojz&l_sOR+l@_LV&3^gBs;KUW?8Q)lje8vn zcCmFX-?2nN?T~%^p4PtiS<`0b&v~SFU>(y=mplC59yO*f6D+yP#I$3@f=ancZwLJ| z4a)XACzSt=aEv(;ex!0jzVI9tyScNNR2a4GJ|E1Io3nKCblZyaDQmjdEQ|c4wCv7f zuKtrMd=o0fOJ+X#yrGpv$m_Pn@z|GVB)nQ)2By1BOn8#=<;m&iYW#km{`tL+eRclM z1Xn8+wwBPX$;&cAnXi;S;a(_o(BqG_X++wRFU68JUWXqED!nf4Rax~rOPV>&HZoQ8 z#KBXm#rae2|G01>+ebXZHo`#h#C^Hx&L_56*Y_F$#`i~Zx*mF`?pI)C2ouh!o$zg*mLV&a8Xd!yW6 z5!(|TZaTJwUf){K;br-~t^82oGZy(5a(z?(2sq3BY@G3@ZlP84899}w^IKn~%kLB2 zYcTgm#alkD+dJE5yQTZ=y4ikEyiH#;rlYW}DbmC1@fXpPN6Yzoj#wD)ug_1LqvCmS zH)p`K!i9;I#+xVB>`q_W)qm4}Qk6%VT(rllXFDfO%jCSjYkkQAMXs=%8J}jqe8b=3 z^{FpKJs|m${I1)qhxCird|bok7q58lg=Qk(T;1o#uD;`+aQgI#-&F}W{v>Vt7In{H zdsU3#5-mBg6L%KJ?s3_i)vPqpsiHpX(#45+Yc-F4ua#cn%)MgS?KiI)9NCgIAAR$R zf91u!;MUSL^-JO>Jx`No+TdTr6I}hFe#*DGi}ZF+oU!!F2O~w_%x7=gq*h%%vRz%= zd@kF}8*P`p?z-)|rY2!yGHdHK&Ai2utGf4|eShO+z2X_}IysihFHis2tid8wG|S=D zw0|#xUwePyFW$GrOPZbC^3#TmCoC0OnOSV-8)fnqF-1#qADpsEC6x6d`)2M8t?Ad* z*SJcUXYZ^yWWB(6-90NYw(k=@KGl-X%BtCu`g3YX)FOWGxq5qZ+6wPVx-sj|Q1WxV zdVqUfuY$h7@^f=mT%BgVZJm{~+Qp-pr8Ah^zTBFAS8wV5pB8yc7P`#(ESuc!bgCRV z@8G?oUIGisK=NX{yEFJ;^ulczXeXQZ}hhY#dsMd*KDtA!g)KZwf^&TCo4sd$wmr7!LC<7&1B=UBOqL}@z2QkZ zb=gq&T;Bg#_q@a&=qp7@&#rVk(dlJd=o6nA zTAFxOVqR~S@?G(@EKJ`MW^~{4$+`RKwv6J_x3X%sD`YGlW&f|JbGUp`v9ZCm;Cs=E z3G>dLYo7l8#)c_f5b6o&9!;iaa*lx zn@(A1fUemaUq64Xc^i%VH$8Kj(3Pw6S5T=ZZ{3lcM*`Ddxac)JS={72b=%26gFO#d zge*JEpOV4$BxsUC%;r$L3)4T#${t&5aQKZu*U+GAD*HrYGW2=A2IldSy)i)L+T$xp}NPzvhSZ z#wS=o zU%+?N+0}57{0HV|Dy=(Pg||Ghof7htHFmM+qvx`Y!jp}aKJPKQ9T>IpPv_-(ikiwt zzjp@}pZjLjw@Pwa-R!c5z2onecd?&tC?Ax$pnPnh)ti#a z|0_F%vV)dRSd<&eXC10F{j~X=9c%Z$JK#29NmF)x;LG((`GW5(=M(KIPtI}q)?_yO z#^LO^HF`%2%h&8YT*spkVm#F?w{54-wv;8Zm*>CJkn%Bi+otqu(woK8=H9O{Ra?10 zQ$A$|i_DMLlN@jMwZFO}`RT}NU7qq2q0{C$tX6gEbarL)zyC~2Uu&+!wi6Mn+Y5bo z&x9(7xuvJoExEk)m&?YPYdj?Q&&;=SS-4HguI$_J zC?fI4W$~7m`ldl^zFb&4=iFA0n~beb?wY(|@lmOHD{)eHT0`}LSXB*ix9|-4qD1Ru zj}jzL+C1_-wKRBN;-po|)*@GBk3Nr(2-z@w@B91u(Jgu>Ch4(fW=)xSfN9$ju}L>S zmWX(?i0#?`VaMgyjXPI7`Mbi>^`Y6Sh}@kT0xlZMcE$Z!U;NSLlJ=CFi+%-oPOqQ1 zY>jADRtSf>rew|EI<0-m4_B2;xtzT2Z1K#TFXrre%QfE_9pyat?9_4L(B?zuK8pHr z>hRuH zj>WCpL|QzjJ82y`?-nv!;`iJGf3Eh(--=pwEBEQl=v@ZhzP69nw*Jg`7GBuVY%I1+ zi%XQFGJ`RXJ@?erXYo5S8Xq#g|8Q|x%(cHK3l1%-iL7axE+!Fq`=iUhFt+aQQ%~0@ zd@H)bXDCr`Yc&V5DZyn9Xlw7J{nth3vwoMXb@zI-fvUjrJci+?X zyWPe9-DcLfrS|PXQjwA-YmCr`uMMUT7iP^X5qqW*?G<-t@41J^e1AR>T>IfM)3i{f z^miKti_h*bEPBoKCT!uu>!IEL=k=-u=dpb{n{$6_?d}HIU6b>}@BZVuuh%v;!syJs z*uKjzy+6HUQvSc;&+a+1v#Sdjm4m8t$~l*XPfM`b)OzXVTFqjmJ$nT6o~*Tqx$w|# z3A?C{y1qfzIX%AQypIV^?|Gg+ceH%?>@M%^^Q-l})eOG2ZAr;w3fHgB`|H5y)q8f` zv_%`2ZJfK4-8}Bzz4%<$pUXCF_k5OW@bG4%?VPgk&g$mzc1C!?SK*SztLw|5fm5-kiEimmUkoy2`DKKOiJh_U~AT z+{3@B+czZfupfB->yOrp63MI1aBfR z{N&D2UNX~K;ehwyhJZ`wF6k+WN^J@G+BN5w)=9=4J314iAHP~wEWUsDuTvXatLCnI z#&c8Vm6={`R&8Qm$=12{eCMh|-Qy<(y9x0(->78o<=TESbhT~Br}e&l0&JSFORs8F|%>a|eOo-d*Y9!hPA$~^ON zhQF9v-Ks?H%|Bmcy$~*LDUMhn))^`DX=R16F6X!ZT+eqs*I2pjrjSy2oEnoVi~8Hw zicS?Sn{DL+cG_%xaFuWRl@HpjTVl4L#A z-=4A3i8^sRO)EpS=yl(GcBM(L8zgJfuP^l6X(r;XxN};1oowd4c}HG+^V<+Dos@cG zZD%KY&T-3=dTTf9S6<9}T6zD(CU4cCNmJ9NKiafoZU%dZr}bsN4SOn1ZSmey`6jpV zv6kxd+q(0fwCv_}KXh09`mH4uZ|3YiyG`k3-;uIf*GsaRukS>b?^%6f`LQYG>^xI7 z)bCC7d3A0N^BSAz^m~Q28FCii`=U3$dtx2rTbp)2(>z+0-CbwZ-KrK#iH^Aq+YP&} zZ|>X`{J}$GxoFnY2NN3}7qI?ebe+Cg=e_B0##wTxN3#{~^(>8XPIs$V-ownatM&P>IZKGss8s~xm;TKE4g&iscBW3cVAWc#BGh9W4bCkg5fBe==y^b ztF86IPUUU+QM4#0^={whtxiXSrhm^XbS^auf>Ej+_ z)jp1^lVkdv*RnkRp{}a)V%2S~lb;@6=h&kXFIKd!g-e9<<_D$p0AEmZ0|{9IwG$dQS^4v6=1-nnCOc%p%6WQe{%z~|m5Psswi zpkqJF_*A9t-rm2qKP7A3@y~*@5^|K*zwUo@W2T4dqY4jE<(EBa|6R}4=T5r6p3myK zVZ@o^^Vjzlra9g|tgfDYjxS~>C%b-#<$uvM*nBRzEf`^wsq~dwKtm zmAh^)|J}0j@eNbHV(W9Y=GuBP6F)GocyuP?nMH`SzM${=!+AeN^Vb)v?l$VST{pRN zhVA;vFRdk3h3|5jyX#`6Ro$vB4av$%r3r~jI}hkud{x-Dp-A`+r@G7BUvAq3-2$Z_ z-;fk2UGw;|PxNu09}?55EW@sxi4?o)UZ#AY{iWQaFDEYF(0&xtcYM>@lKzOBy&o=F zC#PI)EA|rm`DV>zg$*aXIhjiCor*X4^(#N3oqc-oN4-m-?Z;=h%gQB(-JE-CYVJ0{ z=67df+tqmscg<&aGc5>PyuzQ~Zuh?IBdZPzcZ9a93j~H9*L9Pf_v6{R!;kacTG_m- z*z&xv*5_!n>^xK3|7-a8yH&2lwjckn?r`v(#ov%_q_3lsW3Uyn#-F)Yr z)>zpbbCH#6D8C)pzTD?!USQku4NV_b9SSaC_YZlfIl1&mndrPl)*BXa@t+c0k;4~! z=Tt&@x#&ElwN|U%+)?-~lu&*oRk0wXQvBgV)>q119}Y+@;uUtS=-LrGa~m)V!3xn1|oNMlQ92=e?1Qo6QUF@7LZK+4#4d z`XC{k=PR)wGxXuZ-j9E?Lmw_|UbtS%#=ua3r$@_X=`NPwkcXOGuUtjvE&9|N*vf7` z_jB3A&{pJafPdE>uG$$3F@mhBecD%r`yzu~*a;u}7lGM7Tzmd^=sS`_AM z>G|jSy*c-|^~!|z?-uF1AGfq3?02B|@%#O^tl!;X>fT%ut|@n+{C@s!w$v^6=Dgc! zcRzH8y4Cfm9^0$#>vmjw(bC~%Q&;QjXCgnf;?Gah&2MfWKl0wmrdpLLaHafuC!0O? zd)GVJEZrIBBJwCvwQn2O#|75U@3dC%ymzws*l>RJ@z-|e_RZ?|vikQ&>&WAGx&>=p z6+)V__v-EcqID$LX=ncn;Xi@NYn*Icw_jMh)x+`ExjW`bqK`hl4(w<@TU}*ZJu~d@ zte7u(*B?gi{eQf);@dBlL)J%2E0R|4xOL{9R$%+_BXUQx_J}U3J9SGd@U2>%eztbu zYL|_3?(XY;dE~pSM%O*o9Vc|NKF*MNoO?NI%f5`AYxX)s^`EO;z2@HWu*k)q!wNO$ zRoJSfo60Y(c=X$F`>Q*@ue|rNsn%r@tahCWvPkIsJ*{;|lB4>)Z0>Qc7CL`RE3i{t zZbQCB+;;OK^Y;RdIa60`d3;Z|fLC4Mme%Xi+^M0R>A6!^91-5~&dcT=SGI1_Y8Tac zTSM1eJN|mzk)d%YtkcQnf68i?#>tC5ywW>z*w-Rlah{TWrpP1BLfKIxGJ;*i;L>|I@l7X8*57kA5o~*Mqw?jwDCj zZmsZIrf#YAQAG4xx0lUP@!EAxHm(obG>!y6G3j@*QT5y6q9}JnByV=H=p)9Ov!NZw zALt#~T%WEe*P!>}$$=?)Z)2ubc-&eo;D7P%i@*+c1=+Ify4H$w>ova57k#8zxD+HlJ=HM202>u^dyZV85X||pDT3qj_FB-B?4u4A8LM_ zzkch6t0%upx0QYT+^|uu{JY7E)@+YWw8^~UIk$LwQTYPo-CJyDix;f=> z6MHx2xlB^x)#h}0aBS+D%X33GTmmIKmK_u9Ww~fzzthEZz1XW}ff*~8?K^nt=ut~$ zix;Y!Bz85eGvwzgS-3t?E8zIcEuLae>lamvuU{0~;V1p!Lfn>x54NT_h~@lEQPk_) zTyV%Nc0W_g@70%h8=kuw`A_2d6tM2+hxeJ0rYrJVPKG`1x?Yn0?m|L(q44Yui?j=| zrmMgBviE$SvhMJ;pNXyshvU5sKY7KOHAv^HNAeuK+HAHWXQ_YRW=`GBs~$dcX#FYq z#DcF;DdY9&Su1)MoKRe!b!mM`LdpEMY@6Rjrl#bSWS;ksa+Qp~#$9xYEvRI}aSa8% zs+W$Ep>ECI_Pnjfx)&wuT{>zzZ|kN_fi;aMnaey4*c~G^PaVIe=;>XUzT}(A)GxD6 z-A}cdmr@Y5O>3#hZ-xDT@6D7AFFAffsoUfCt1{meGBWQEPEuk}{ahIe-t`?`PAmq`#2n@uK3W^yY6(^eSsc9aaF~~ujJ3FJZjjH zzdZ7^M@jvoRnt;T*{*v1n%8sew2?FWs=!!f-PXBR1(q~x@J`-pzNpfF-i}V8irC#u zvD%**Jx%S*nu-mlX85h1puoKT=_bAYTbwtiozV6DRd7j%Bc|0vCA7q$@%;SdQ@mBy zec$jCb6YbMKfk{AyXjmG-CgXm;-$XT ze*>&M6ij7*s$F9ab-DdUYt^O1*;kuiDg6BvclGRv7k<}1pE!8L%Th&A{mcK`H>Rq% z@f|v_JAR_NM313O^1TVKpZvd`c~!~dQoH4%yxVUwRtjz0r`@l!q_s+-W_qygGy&cX z+dfV8*xVduox)>2!{YpfJy~5FH0N>}IC$(Z-b^}EIkV3STj$wMtAB8CE5Bgcq@$HeH6=?_=C8ExtL0X@#n-Y<-t%CU zXE0aWMbp9@IrnSb#oMR1fB&^?_N#ic=l?Z+7c*=tKL2o} z{EAIJ3)V$`KD_tWFYDRU_U@UwFz;;pzA3+5W>^MA-RVhfb(EJBSn;1TT~z3;K0QD#!lctJGybtycYZWBs;M z%lBIyUSClEQ+u_0EdO_lRX?+RJVcir-Qspq$m)0_*PGK<9d=dTy!%>VhW4dv?2Z|w ztee6vzuBk$(Y9Vp&T9U;mEV8<^_liUYr>{Szn>fpWlE~go~~N*@Uy6i;;xSR))$vp zHcy@P?atzCo)tWowfD|Sw6}Ad9=qXp-D>4q-?$d~U7mXWUWhHrMwLr*@BNwo_@fx3 z*qh5*6}wj4^g4G%?DVZk-gB)^?&v=+;-ls`Bg$!8_oX+ciqpD6PkE)p*@h?kO^k~_ z)idFkhfkn??!!F+HZPa1^_b83XhHANy6!JktEW4vt=^M(C)J2^{a=35UduPHAK2aM zweeA@5m~Axy-Bmne~x-b>nC2TynVkP*68#%>x;iRkA5B&V8LO(W<1b6JZ}5_c*C5Kl0(i577?-4Rwd*zJNp&k8GwhNT}oHAj~GP_p=+Vz3w7kP-M z-42Lyd)cSB!~Cw%so21<2NNDYbCLAClNOWaFE@Yoi)+8WYp?kCOZZw}VEeIT!!6I7 zOP@$3tYhDP=$HAe$mvaeeFYsFd{X68zgB-q6}|o-&5!$u!Nl4J4=4U@_!uk1E8$k6 zeOuN+SXI46XGZc_$=ep$L8ZLY)#n=L*36$)xazOvKgPuewg+>i=A}UI@=MK20o_>$ zx~LFDD<~)!S(q6bfK-6^M({fgxfB!>^j#}T+=ELJOHz?;8cZ}$0Nr@#?5JRzxxz5_9s?AtooLrxrt_1fi#*C^e1CK*55`01gz)OihhV z719(SVn&vR7DftSS%o~9n1zL;fkA=6)5S5QV$PepI>o0p-paY^Qx z>~2pT!;MFzs(bc+zqk8_sCL(l3@)X)cPsxZrd=?^eD-)tY*8Nl~vH|MNg^UBjgk~&&ilV;aV|7xBW6BH6Ezx4X+_7$tF zPG2cy)aZJ&M&ndgXsG>(dA9B6R{MzN&a+_+6ghfjX(x}E%%6tS(`!qJ z=-0EMp?klrIvyzUl%1RV^hM@h{TDN~ioFcfVi4DxmvVdCQ>_WXp;sT2y!Ke)`Kxw$ z@84CcRz2rGyzJtdm&>KHvv2df3QI{dGz^^eRa(q2@6Upo1O5l5FI(dtIAvDXA|1V; zC0o*-bVPcc6cT-6zN+%_kKggnm(TxwbFS6a`nE+H+e1U|=Dk|f@bkd$zrXq(Z9dn$ zW!ki`W$WB$Oe_05ZRwvs-v5&f4Fg|`xUO8YD(i~2+~JG&?s?wddHF!eUgPcM_u01P zMz3S|*1+N*e0sv|4N|?^;v&~)dA$y^o%lh0(v2H8F0RYXKUEd#9B3jxW0zd7+wKE5 zZ@SL3%Uv9_$%Qp|y0TH@pP$`EPy0=~mZv9%F21M}DB_xZs!GH)lXJ_9zefv}x_^H^ z;e$HEp4lY{UsmkjQnh!VN@xFij*mf-LJXp6}`$fk=k0kyirZhImJwV&wUyH z^M|Sy>|2>F7}?BoL_jH!wc*mz)iZYSP2{Ys4E6oBe5F3`bghUDEZeqyQ`39=^wFcF z9aUdt4j$z9iS4?n@j5hg@x_c&vv=`LG)=i;+>j|G^hrQ|K67SX{9ZTaIdfy~Mg14o zoA>1OKHryDKUdqmwt2Bu=JUtL0)BIDFgq;udjIg*vyWkY+V`xq8@BNIS=H6>CnhRp zX1#tkt=ntrt37q8nm>Nc{x-*E>-@jf@&Bi#*heC2!0*0OEiGONtKzKgXN)0;Kr8FT%ujrOcuBK2<%%_~=bp!U`} z?D6Jv%@QUbrf)Cuk)PizW4&*-w7LGr4~`7)-t9a&f4>B;^tMB*d;Wa<_FkS%t=7je zMRukZL)^})Y46)>r#<^tuW!{-{BpZEL+LJ-d3L<&W@gXU$`*f}wf{%)FAs)YWs--& znUC$;n#_IqXYnr%y%?LB%eI+j*ZsK0oDgy)SV`&7y%!Q2HyY~y`Mv>+&9E z_U#*fytmf~SYVMIKHs=>ACm*@XJ|#7Lpb}d@c9%i~IRJ zQoVO7&%bKpo9mR4(sFSdWBk?w=gu|8*GJ}TxqI{H+rJYh$#seAA73H3nX$vadn>K zzopfFKV=p;Hc#V`H#_^{|H|s`dB&x;`g87Y6bcPZwVJcWmpiBWS+Vv3F^>AQ+fENw zU$?1KRS;KToZutIFn4auikO$Si*xtwOJ~ps+2FFNmch_4(56bnC#FWn@{Y}h?d4U8 z@)IZebMRGm%+B_ck-1b}x7~ZXU*YZlQg?UPdWVFtoSt_6!IblitHM@JU-!4`%k)bc ziEFPhWoOS8xxakXDj_j3uZReaZ{PfO?ArBt(a&vPs%#q@%NYyG&;LENE&tTDV||Z~ zo|epA9lP3adCj-tZ*Ky>RPFt9F^Nsimh0K8t;H=ZHY#RnQsLX@OwkLKEdPFI<+lAL zKSdfFzZVpqbbRQv^u+xA8MA(IaqT+)`1rw;^YfIiK32cEuaQ(1yW4W*EI(h`lv-Z(Rp#5FeN9d8KBw+q z=HljN@bmjs5$$Q)8XIPBQ~9^yQ{JV<6DyYMMB6o=oju)y!NmBpxKF~nJ)ACXc7{2d zw{3g6_*kx_O@>Tg-~Yck-90sjw!Bo1++Ak3absuq;*70gAuD61D>@$wUQ+N<{M*)q zhxupbn$J7dd&?l_#g*&-T32Xr?P8H-*|nPyWPzB$A?u+L%pwR+Vm|A!Ud4yaAj#Zf{?| zAf=N_L@Pw7VNWIZ#_I1@ZFTmN($c%l|0{LqC~Ca0dwMEtanaLVPdy|cy_)Qb=!~^J);NFLizIM3Wdjn7c;ET=wja>$-%Ji^akS-E}L=~&dfCCpKTW7 zxovM!tJRl3dlcFE@(fuHZWounHd`8fJ^#a3+qqft{c^0IE8icp zsS-JJ=H+b7*j+`lUR&3su=mTiU)X!Q-doP>=L+V{&wEnu@9QAoc!blgua{kC;XJHh%;;IX{}@--658nYmZl*I4OJ{R97)7@m3aTI0W8Ib!V+dNsD;q0r_<8m}8~J9sCU1;`dK z*43n$PD$Z6)b0xUbpP$_21dwV@2@Am#@nZC#oeALLOJSMfu+>if@*3lkjD&fb`mwfjoWy+8a?z0>;VaaQ@- zWu1RxnS680Q+dvYG!@N1M~@#be7T9gk)OFjM$9WFM#n0asj;#A-<4w38sv)wy-#7$VB zU~=hev4Rf=#QyzAHcd^bbJ;8)^QR%$?)S&9wuc{Y5I7{)F11ZvGt%he&+Dw*^@k50 z>i}(W`SUH*cGK?c}w|Zo91aJh_>dDEDvgq3hxw*law` z81y+@;y=CEL7*TmaEj^yqtMXW`PM#}4>&$-UbRZtXvqg3EpPS%rLV;d%I{e?-v|~t zYQW)g^}qNFX|s%@lj@flJzqaRa%+{D=&9?AVs^f&`BXSvq<*EFOUuRG{=#{8_nlhQ z${tkn;J@oUJKpsB|9q$Dhs%2G>E(Iw;DO7;LrX2IO2ilTH>FhZ8Vml?=$L=(+tU{p zW82b~ty!}saLSPd%l?1go0XaAdRpvm{gZD$+MyOdR80X>qGtjU!R;6n*NmWcX>ojjm%?p9y1^5 z$;Rn&pPuM71asNTXJ5}c^ZToP;`w`DWvur}v$Ln4stR42d;8v%+Vj?t)&H%p|J+la zeCUwVOyg|#S%>8v_SLWdb9ZO)W7G3Kdy?xIt(X>j)cn&Ih+v6eUa?AQy@pre0^> zO?n%hua^D#W#o+B*R?PI9xaH8E!vd-->vR{vc^5%?#)?O=cK%y{>Ql2n$g_Dqa*$F zw597~Zm)~Y?(FV<_+{o{lOG2AFCOomJ^jM#(wy7d{%k!LouWH2P_X1hMDOAD?U%Qm z71xQXnBdIbY*}Ywb2QU}jsMrwpP#>dx>tRVh2>7l%}BUm7P?tX;LL zN9wM0c6PMid^-;Zhfm-C&Ca;7K=f$$^vB=cuC}R>_z>2wYc&0(vD?P1ukkfkcGy~P zyPI@-+Uzrbv(5Ma-)3}EUbL)??~hrbWw)5jgUfw?HA7ag9PfLd_+UX;&F{O*PxkGt z|F2e5sp6;gZ~w%-9X(!u1KXaf_RToo`G2nTk)ucV-Sq4#cN9*TwQ7}dXy{#j8Oa)yOn<9T7PcGG?TzQq?Zw&dKKQ)9*a@!iLdmL3HknC;%)n18Uj z?&xYC(Kl~p;(yHg^fc?k@g<>e?*DF>s$KIT?^0v&^S+Ilm+zmv)%WAR&oZAl@01jl zz58>V5+3Z`9<~4Oe(%1$r;J;bUR&0ruzxG-`(yFPzv#({smrccRE9o%ttcE}QEwk@ z9)Enbk7(KZNbi6PwTsJ4v+GVAV*M>)@Xbuh7S7GdWqrb>$)rudnI1)MF3r`}W2$By_K15=RYx#1f6J$bSu| zH!)uLf39>>YO$x;`}mM6ms4_`o#doy^U|L;Y%h1exB7C+hY#*|zL{6$2dvKvj)^HU zNW5cTF?Hpk`Ip@{6$^$8N%w{4NGpMzxZl( zDd|G^{)GJZNA~;_wy4l}>Ur|~Tx+-8e4&%CYTdKkKUv}xQ=_y4(}t%r|5i5Wb}h0A z6?w|IVa^do#qjy|6IQMIr^0ri>wuAKpw9gK&+ATaI?pgoGj`_W<=>3oo)@h75@;Q= zcV4g^`wZ*+m`&T1-D>;R_R8kou5tYM=;?+H8y;Lzl`ne})7$OM$F*$JpNVVN+6FIQ zvpoCzuRm6K3VwYzGp?+7%l-P+rc%vSt1dlR{B7m7%sV?|-TU7rU4B+CaiRXq>bW~k z1fBY`+wP_Pf1kr=&o&DkJ^lFk^V7G!a^Kiny*BW6^!D{e1qs?!Uw-suh2B?>-=}nE z|NHZQT7?^rSY8YIe2`sN;@91jWB)GA-}l!(?c15$8#gVNtURVJm?&d8$wEH5#>vKC z`OwayuR79ZdTM57v*PRHzE~~S+cd$dbk>HPn z`kALM$lERcseV@@aFNWmZQp+UnwNI?*ijM97^|C09-aS{bs$2{mMiJ;vi*{_%lMW5 znZI6oe%h|x&!4p?21}Uk;%DBM1!|73h*&75ck}Mfm(NdM&3qngo&WofU4YiyQ|G^I%3=8PZ@2xA zKizI;;td*qatpD4x^d&i$H?c7XXYjExtBNb(9)mPCq>HMN3yHLSq6q)HE8~`d2!SH z=WpH|>ajP!xV750?f-iAzP_6)B0nDvxt)LO4?l<#ySi{y?!EQ@4U_BN9ly5L`~P0m zIjQwD_UP4<#DPxjl(?Ku^)ux@Yv&E5IUiL*CP=AIUIt!MrOi>Ypx zeupf+cwtwmzE#fShSrZ?%c>a9-+TZnaa;jGb zO?`1czho72z>(d_4*LylDhk^F{x&cCb|+Awu=9ZAW%J9=Ppi4*N}FYzoNH}9!@Pb^ z;_O8lH6I+g_emOkY_<0nbxl0-KTSwX?9?yb?t-GC#19Lm+b4YveEhAVGBo*6i=vG6 zw%N76&7{6rT3B3O5g2`I%PUppsb`MtKd8I4w(3D%*6*YBQ+j@^K6&Vn(hk45YI*zr zZ~HVgURt7}zhSqzX2b@UO@W&q`pbcu@J>#06V%Hcv##g$EM9E9{JhMuv!=^09(uO0 zziCIsN0svTzZPE1`0z!?=WCX{#NQ2FJvB}5r*3|7GPWUR=clC+?Q45uSAAxDRl+&P zvYJKxc#i&DgI}Lg$`u+{nX~REe{Vgo;_$a_gu>1MWU{md~4mnW{5~bOGy2ZTXazmI^LWoz8CW zzL3{fUw@rrS9~I4c2iTanRwBz=Y~-WkKDPtuXd`~+Ea{Q0z*ret$Y8`G}Pw(xGe(|;H(-X}J@4U0s0z;=BSWwNve)srE zP3w8{TAxT>t?&K2Q$G9Jx$X-uOV*p@_bt-cZ)Lrk@8iQUE}UuJC<9x9^Cxq?cAWhPya8nnv}6s zER&DlQ+P#JxqIs;)8M<|8vCpF6!iRShb+eAO%82XEJ@YZ{qK zvM99(IB_JVK}>a;A<5a`1hPBLjcI`Zh&6K}gT|VGd^$)B*CpZWbO-FY*c$`MWZh9jwQ1-mU3h z&OcVuVSbQO@PYa4-Q9KI0ck_Sz&Uos5$mtN=AXSwY@%sO07FRr-943&S6@Hn4^Q-2 zf4%tgv(&w-R+;-owy#>{-*{I$>|Bt3{5M0;ST`rfj+1+S3V)I6{kCS+s_i~8=d@e{ zAG!7Xin;o_R87w{MeXr1ekG$%ooo?VucBP8O>krk*l(rqV3|>chcut;y*9t;69n&e z`S>jNesJRAT%MoHWEmOFO;@d2XIARFYE{|A*IyNFt4yz)pKU*H!i4r^dY&@^A|fAqxl9C@=+Wx)R7;952mG^2>OXrbeZpAMz zY5w|_y=-0deu0F(RjaanW2c{x5;0|dcV4S&5#uwhu1lVwq1@Wq*?U`CQ+IvWHd^1( zQt{|fl4;i>l@+UYNxWFOYSl@7LG7*}r@$$at5#iOE+{#(Z1d(~gThdy#Yd0135$uX zVhs>E>K=Oad}yd`?yFssG`cQ%F24A0+4a|V80XB{^m>cbTF_jMhpVd1pNV0ip(awk zTjJKs^ZEpZnx4C|wR4T4Gt+{F#;%2oQOs8-GHN{Ya^n@(-$?gQzx)-}_cC&&CuWzD^kM{YhoHIbpAk9}h&pO7+oBza)n zIlnU2bl+Es5B)h5TPnKOtks$Mx7xou$FGdF!QVHw{{+bNsK}@*x%ZZAnmTuFXjQo? zsFIPjj@Guzi#d7fQc(2iD_c9(DF0<%Fx7SDr?{U}zr1tjP;4;>PxX3s^~SA;sivi} zO0PY>Gpx|aSflgw+Ij&ej)`$Py1D@(u5RI7CX*{6K~Ge$B0~OyY|(E&gLM60i?8qB z`}FU+yEO-HcK>s+Is4~z&;3vSHvcDF;0T@$s-9A^W@a_*XMr#)2KPvD`wID7SMbGv)@)Fx_w0KvOa@zgqnF&+vQ5WEr_T!{Ge7$2G5d@uzR$6&q z?#wq|xu?q}{MvKGVEwABHkJcfQ@b`)9Gkx7)h~ADcHOjVOXObOTMmjN(bQAX2M)8< zI-U8;dgNZb$CtgVYhq0}+}Wk~{YkS^KmTLqu00`dBfi>Zoe)~gf8J&t$j{sUewZe> zOz(T^F`t;@hZh(u`*(}gy?x4hwP)W;l26TfYtw78&vwoA)jo5!&HOVjPcm@T#A&{( zFKo&beWr8o^iS_{qdoPCEdol~Cqlv*f|HVSJwK~W{m9Re_<+CrX6*x|P%RO!Yw!Ln zwVt!Pr2WQ?ialPHK|5;{x7?cY`R(Ba27dEC9=2C#S=4H?B5LD?i@Encs0YUE{KwGn zU;@XvxG&~!w1buO#l-UW-STs4>f_$WcxR8O%ZbGtZ{Dss`TnKb+pMD(GlJr*eja%_ zJ7(`khPi(Jb^hk7LbaOazCE2^{Hml%FK%b{3j3|=y(d|hJI~x&VD2k5W%)|BLGBo5k~mWrh30J^i(&>(6*~ z{hOzYiTe2;g-?Ig#>C33h}gz(lE;`8_!TR2e8oCY zS!8+Y3!{POy*qjgC*?lW3kmwZSNt5Y>siOeZ?~>?Z%#>z|Maxf^p;)qML9OUXrB_F zIf=7ZcQb!pUgx;kO_cFQ@dqQ_-GBHF+}Gy+`2Cb~+qTB=vVv{@}OH zp`leZrn6O7^BL#4u($F4Qt{oId$*Kt`WwCqbDjT}w%zCdGo#%x@l5n4{)WBndd08S z$UC#w&3Tp0#uIzwzBa$%kJD;*?2KnVSZzGhbR~Pb{*TLB9=nuS?OphGCinJ_?+hA^ zR6iHJJ(3T~u@|mNmgGgx{upe&G3o9`k>5YIl==z@mAtuCZ|DmPGwVYqiv$dw{w=8bveScNs;4Rl?h97ljj2Q03$gYes{AgBu?~dM;)uER@Bxe46 zw!NOQs&w7?4~l13MsAhZS(LUo;h#*+#iz`6+2QTc{|?%4@EFhef6}<_%8H;Vd9tr3 z8MhnHtBlEf7(3JUb=`x_Wu-wj`&O;`B4^ak>dkLZ_+@#`ZTq*(etvWIc~0eO?P051 zvdpvj(-hsg{U3wPCr((9d}m5;h)#4v+t)ooIrUF})r#p^Hr z;$5-v+2^{TRM+iO$z5^ji|(1Y9ql`Qu*kK$G8sJh?A9ZH^Pt8Q8M{K>(9q2Li`+IP zm*j=dp7=Pt_`{7*kZ08eFUIVUarmq@b+T`C(547Et*P244lWMA9CClrQ}&s5`Qe-1 z7OQ_>RMNR8)9(C_3R(5@cb*)$sQrVzMc|W0lks!m`R056e=yuxly>;qv93u+i;6#; z@lDgc4|55?(3etvdl`-phR%9_}hoy=UW+XD1U5nT|`vYJtaiv=jUa$49CC6 zn=XF*y#CYK6ZJRtJ-5+*#^D zg9jT|Us)B^(@?#T<60CM4O<+Zh`ua#UamsQdVFzK|3dq=WYL0#x-xe{>|9gyQtMB@3HaxkBYg0yTxB#Udvd!%e11^*huW3 zN>|nVKP{UV%W6Nbbv?Z-l!x)z^8435KGxUny|w+rx-;!x_s-a!BG29z_wYpLYo9;G z#+RSJO?m(8VaVEu8!P_WukH_6RUsFaYjJQ=XnTAnpPlsVBNP7qxuU1P=xWxFW%a?o zYHa)Sf1CT3iWvX-{?&KZ{g07WbLIBNnX>#{a`Dvst*a035PTbKo0j$0wztRgvPPz2 zi@>2fDZkPgw5RJIIb>fg{Og6L@2y_-FBgLk?^9wGp3mvMOX$a%CEE3#xm@BU{(F=v zv@4@M_S||h>Fz-T*&esaKbCrWTv&eNpYI#nl9@Ypu>AU(CySN_zc>U4dleh9>|LIm==U-mHSibAq?4!@-reBJgon6LmBE|Z@ zVM4go@;ur5$?tzXTxmCX#uAT(M;PW``u_0QTZfQP)0RJnSnq7yaG~h#dquf-H-r9q zoLqd|zfwxldEK0w@h@$_aW>&4vw}+B5!tV?+UtJXE;*V$xudt6{Xz40ujJ(1lWSUc zPhMMZUHQ$7;joD2HnXrj@ykW3`Qp63-MMkDR{X=>vhx{MQ*Cw%H8n8ViiQaFl zGi6X$B+ZWc%{F8I9 za@s@t^-D@RZSH*FPDyy*9~3L8y!O>~z1F>RO^e0eD(dMqo_fj+YTkscu|Bre`dFj! zmy5w!)%}NdC$dWIeeZfQsd7iL`4rdF{EM!yF3AeEzFNoiv^@RxsrM^x=kT1h@=Lkj z_Hc^+Wc#b%Jf*Ja9{y9$SMWS9V^gKb{g8EYZc1FbKHE_E`lS_T*ME6`m804^8J~IN!ZYKFnat{9oDP-{f}r{EiELxpTkW*X-#|tFIP3JCtjdXAcT&_3~cNYv+Hh zwQDN|wZdCA>IgG1KJ)!6WB*@a+B!?8g-q}Mn5^MVuFvo`ORxU-{j}C$t36V^PVd*r z8@yD1Y+9o|P4~b*-or1iq+9J}`3m)zhh1_e7jzj;l|CVi<^sUbJple+LumVxVF98Y**=;)2n!o_vSr) zc5>?6os;dCC$FBR|7LZ}%bGR+s||Xi`WF|@E|j@tbm)cUsVOFz0rM)ozkU9G$~kkM z^@q@&U+YBA`IYg=?{2!wF0}qZrU}Fjafe6O);)xJGfr3;F-*xEmxt``?;y=VHmzekS0 z-cj_|Ze!ucDO&TsFXjKweuvvPhHKr1h|v4R zmXNq`Y05?$eVc8oR^8eAzvDN*y!11snwyjI)_X6%9K7n;cAMUwho?4n=F3zB3(K#6 z{HmAT<@k}nT}MvuPv_*c%Dcz+C^LnJ_488?v$_70roQgKyzRKivHmv+TU_P}IPF=T zrg!7)_r=qHwzRs3nU(4)WuFKNXNW&?DX2SK^SsIS?`Iy*TDH>9MC$3(WiFMX-^#A7 z)SLdz#x?L#%;(vcvP^p4<{B#E-Yk*89!&Uu9T&j?e6^$8U|K;7hMV zck$0S`nNst%sqx#C&R()*aC1FA&!Y62|MYu*K?AkVUcF)c z|Kr4p8IPB(b54^7s{oOTJ@?vy0IEG$*yKJ3%itNjMVg?P1H2BP} zO$!z-`E_pUDbb#_VH-EBUAuPbq<6C1iY)@~7rc03@pZ@fUWxgix3AqImFk!ibI2hy zbpEVedJ{`iJQz$$mT63F+!fWkY>V6Ch_r~~;DHU7_2G|8tNyws%wM%?IcTV&%E$yf zw(Z1mnanW-=zveej77n&fp>haZWnOk_{irG5NdklifhLj?ZZwp7HRx^o3nP=t1nrx z2Q(M|5_RHGyyt3W7UsW2>g>H0FK#fdT6NE`)K)3`H(~)+RKFwd$2}@O9-)Z9Nh!mo{f4^8bFn zKWiFeELi2!-Hd0aB(>V+G@e_w&J`TBxodQ@E6vv=tkv*>jpMimW?WjZXKin9DsS+0 zrA>V${0-Bl-C{b*RlTI#9MsjksWm~L{aVL^j)pW`~~ zq{{`6DglxP{5KkuGCsQd$;7B_XZ`!br%pA+&3&DmxX^cFY)FZWRBu!7)>O9e8KA07 zUGQQ`@iyw{^mPAk5A`6`~3aXVV${m^&@}mF4Uf|aq_i|wdX74SlSpLyn5uY z@Xxyn^ED3bVWt{k7UB$b{~SZs{AU(DEtYV8m%Py*n|oJ!qZ_~ctdcukn+Tq6Y>iw_>Y>sj6H>^A?H^zN$1j9cxb zP8QCW-jW~KywQHkQjddkd}i%y^{@UvbIsp1_p1VS)+n;^#GW{NyHRaL1SoD!hJ-Ur zF3E|VeDVHvvl=-G8NcRf_M20#CR%M-)mVO*OKr`&t3DD}Cw|YG!r%}ZDz@IjW&6L) zKbBlpc^5zH*zQeUUNJFDhwGvm)8)eJ{_Jwy^!IJGud15aysO-7mo{aJF0M7)_|a$P z-nqBSn|N=3s@_%j^v02r_13l^cRjekv2FdIzP7J>7$mGdBuAD0ZGM{F|M73QeDFS> zI_K)OVTaG$-xa*|VSkUz_O_$OzhbLRCGcmLFXTYNF&#if0G{z{81t3Fwo z=d%Ybuj1U}Rk`oO9Wfp218=Plo|$!px!O8=aV_I_r=7*-Q;L>;R^_f|FuOLb=Jx)T z7tQv@rJj28Rz&-e<7Bp{z297IdLOPoT5VZ+jel*J^V3hQD?-*OsGt7<%4?sVma;y$ zb(THnW@Vq-`|5{pQjXu(<}d#BN4HD#oa^hfP|av7d4|>I^Bx?ys15Q=&CEYFUtN>m z&!@(Vi&urLQ+PY;dcw> zlws0!v3_#QzN-FbbJYv)zE@=Z{QSVRV_i$L`wS9qsZBfgF8zzQgx=A#&`)M(vwh(=@iO7B}Bxrs(Lt-0pJZzHbuK zrbTf*D^5Ru(7R{$Cc%bvviFRwo@-x!e|gvKly!G&9FA^c-MDpQ%JqNUf6QvRi`Bm` z3Z8wdZJYhyZG3CPnp<1j*0<>@eYqISaO~fOZ%Y{quC@u^h={(luJUWj?@9aOw!dQ$ zmKN{ddi6AW-HWePY`pP4ulrX^u^#XafA`6Ax#yidvL4@ZzU|m)u_@_pVbbGAj2gj4 z>lGR1+11Z>JS={BO`t2E%-%zjJ2G-|bvnEHl0U7<)tP&_|9*N->h*u!H*Q4;N{gTG zDm@;t|7!c<+ip_p&K*1cI^%M!5yQJYza1&%38$Mk`^?+gyK(Zh!kph3GO{^B=P%mN zP#3%yvN}ZNre)~r2nlX(-R0+gEv+~=_tv$fm$Q`D+<$cVf&T10U$RwN1f2G)^ZCm2 zpnJ{jN6ZO3=FVDjeZl@6)&B)&Pp@sBe_lSu%4S~i@A{+Hj&=F%T`v65V}D|G zVvAeqZ0%Kkyz;5})}#93l}}Vfc-o;YzH9E!y5Y|K{#1;ekz9jgt(_BZWYUj<^5Uw+ zpD(=p()RrSscO}GY;P{EluQ5i*Qe!wOijPvgM&})Z|?u-uA^hZBeCnmi?71Va?^g^ zN(PNs9s2X{(W{T0EphXYK1;o?^4dEz)av_8$AAyQ=idEpO}_088Z^wC_iJuatF45= zm;Do_KiPHPd7p&MbiKFtlfO1KuK8ch(QB{q{ZMgNSKs3U6SXVqBN)?{KUo}mH%4}4 z>|P6hrA3$Pi&ay}5PV3Gu34i`; z<-WZCg7I$k_h&88Hm;~jmplFc)%nRC8GCN~D?G~N`EACd{^we}%a8MmJ)1wteBXKS z9rJXa_1CjZ&-~k~&ae01^TAZfA98aYUVOdT^Jkmr^!4|WKdt${PJo@Qoq59HtA>%X zVPRqxmbZ%jKYT3m`p<@W;x{+n++6y7XZWvOpoZjntzfnT6E1M9i`jqvr+4{{U9V-{ zR{5oVJtkapbML~7SJ#3@GoKtWttwlWUov%t&&fSKlDFCxOi({FWB=(5wQrV`J~=sc zu4l59q}z&HH=_)zgZ$sTT_b5)=R51w<(FTM966@`JK(A~`z-dx#FCfRlewoezqquo zPtj-Fhjlq$d?ZxZ?pAH}D*XA%w#3SILWOG9nIl_8G-ph`DZ#|tV%6L));vD@Xwb{|ii_{Of_;tSKfb$u~5CVlta>b*`c3;nU9@Tf@t z-!-$hGj;ZMFMq?mPDt<9X8uqukw>q3*=r0d^i)^X_ZA@%-2$n76J^qs!^`v#TfHPL!SghEL|E z)udgf-btA&kDj~Mb$<6A{sXP28QZRBZFvz37G2HS@!)s-?IjE^ zo@C5U((U6jYZJV1e)EP4paDd^U-xQXUI#VCDuic#68q5eb9YbE?5$H%yPDb0#qVNv zXx^1NNp|tY->JQ~SlHTyMLxCg>1HQoX4=?xuI^@@dP?-kjPtxDR)4*h&zfnFE9`t+ z$A8=38{Yy?=KU>wXDk~nt=;4_?}LSoP{TCe)gO*WJWfBrC%gO9HrwZxC2zF8%iF0v z31mrp7`S4Umrst(x3X(LezFV73cEk%KeaT|YR;1AUjKP+(s`NcANe^Lh1UPD)!x0? zmi5!qikBPbi^}|BY4|g5<^FXE|72ut+s$%5zJ62UYJTw=W{c{B^O@b(7d&_&S~q{^ z)SHv5J|)(!59u%b=#^xU_3PnkUM8=X*-sz7>zQ94u*sdP=&27+rK6&M4`@VYbJ=Ij zZ?d1BUWv4Ca-J_BB-QA*TwTZJ(gnZI?{gntVf+5#t5%fntNXkERNl3ickKH@P>X+; zQ7S{u%`IHHb}QKqT(PvaD0(Et-#jVabf@eDi>xb$?^@p6H^*{Lpvch+YMCu7-OoMA z72ck%tf$w=-kA90?AuR=e(mw9TxOA(-zSpC|NQjpw(K(YtPoAFiA|O(!&Y_#Cir?> zF#K^`)o1SJxo>X1SsA<5B2-)K*x9QSL#6wQKb@&R->o|L@ab3HMUTTCO;M8GKG#pI zgrQ6PWb4=H86B3IH=t(fMv_(NQ;klXf;>+jYa*r6#sb9;(??5}fA-nFh=$u@t< z=kI48|2k$G9kuMwwfZs#_el-a3%9)a#J>F8ufQ!6*g+Mn=iyH&<=dX`zUbY1>)D_0 z*#e@n(;t0Qp69mwmt4z{@5}v`tN-y7(Yv|%o`{7LhvKF-A4vx9=_kB@iS(UQ!2 zmham{FWHEmy&-=~tvc^x_Ve2R-#0Hf{qGEeRm#r$a*|3)-?wkn?z#2s%tVQIP5<_a{#i5QMupP6V*$Hd z?xp;m#KLOtxHvGVW?B%a(GYF)*LIoAI=`HlPo`zt!nVA(?Am-ly-OO)iU4L+6rF4(X{#osg zi7c%)iEp0;n`C{?-jrOP5z0LM4Ihu}W}f@m-zU9|-}g9vla zzi@cp&(cq9ZvGy(8RlJo_#)x-@v4F2DTZGk3G?%?F~|+T5Trezm#WhOEP! zhs*ZHncB49+?%{t z=8%!i`H_2OdCj+{K3doQHI%P(esCIa{rsNzefFN`hjD;8RvI;|Lc+3e=Orl(Py=(I}0oi zyf_ue7p}gn|GnGvea4#MBYaAXjS?-h-IJ0u|_8qnAGp=&8?fYnX<91~5?x;eu zJo~ekPs~VB^jm#ZKuGFf!@}+#Wlw@mP5E+U^%V8OLQYV;pALTyDjT@}{dv^-H>G%6 z^0y^&B`>Xo-+vSC*%q!7-B8plv;-u~;t()T>m*4la`TNV{$~??7K*I=M zCaq*zFuPm1G<(_-2d%}P>|cL&9C%RBH+R>;FO}9m^Bjz=wyg2|w&xKSc{E*oL2i|vc`84=e+d)_a^6@ zE0eLQn)=#YK4?Wl^(Mh1D>Z`*)JwCcsoeIS_Y^d`VI9u@bai4kr~`66&u)R=S0Nwi z>r-pn^*0yacU>IteCF|~kFDJ{XC3C$i{0s+*Z=0q%D_1?>-^T-F6z1?cWm|iE!lx{ zPl<9FRUL{t7qjE+H{0ihC*L`M%BWrIw_j|Sk~Ot!&$qS5pZRKSeEvW+EZ=5kPJ_?k zs<;>ni@wzC{-OsR`sMOANiSb1@7QS-v}FSO{Q7TpwYy9Wq#71#a7}n5V-H&kP?|l> zr_6Ls?&nt(Q$MA=URMn2OQmeQQ&At$xL@pj>ixv{Pfvcmzv)nJuKwzp&df&-rgWup zFR=)p-@KO>6vP3H<%hS$&3!E_Eq(roz4_+K=aQeEl`TxYyoyKqi(%~VvxinMDO}(! z^U`KoRf?05i})-0cNRp1<{FPG2jT|?U z6e1)#l9akyyB2A9X)KLs@#rq$^z!ClzWn=N;klm41{}tR&;0(q#x(oc-Rk*!zgMo$ z{&;6DPvw%|h57pWcYc0g|6@`vdU*b;neUE?2~HHAI+K;zbx!fj^Lsvha&8cK9+MOH zGxOBkH*-$^s#@~psnXoycB3V(md`iYCLKD{W$}EIt@&Gz^S@J_8Wo<$+?n_*;(`W) zPJ)#AiZjRa?;hMFTEFS_`@bUgmb0Wn{U1-_mYy%b&c6TerL|Y=AD4u!zwPDZ6x4U! z=h>Co@{(nNd%M=$-_gu$SQxSEAy-)&ghO@O`klaOZc1{m=IsAKKSfs!Omou=-q761=B)Gm`hpdDAX|PfZqRdiH4c3%=ek^Gx|0< z9}qsEV!Zlw|02<&(ZLdYC5+o9Y%N&8Rlr`rD!^XD;lsqo5dQnA9g7@GP~VmcnHP=X zF@EgtSnbR<+s`R3KC?#S1Mdgj3z91sZDwyvG}h+(!_dQC_4A~2!}>F8CKl^`u1sT{ zz~mq(D0p(ERmH)Jde38wHYoYtD|Ikj&|mycp27Gv{~y*Ztjm5pJ=7RIr?|TBLYRTU z2}|?a>tAy}P+ZVioYy$tj4|W!|J;gf$@>N8_P)MexO`?T%NN#X40jtJ9mxH6im)(v2bH6rt*@m-k^b&0Ebv#(3T<6W&0Jgkwjd@#|Pc@r<#I95PC)_Na2d%SP z#jL_4d{&3U;QvpT1x2&0o;_Fi!JN-x_;%f$s|W5)d7$qbb?V*D%MD5u%JrGPhq><@ zkp37wCGqaVEj&+O|Jc9$*ZYZ|^g1gRPvT;5b#Yk|aHDbiWAnvq2mVc&Xz=__h4JjB z?E)*MH{3Y$uHalRlgtL;3We?}vt>W4%lUp!dC+gPtiYkB%_#HyCU47SYLD|yaO}y< z{&QdQvvFP7f%z$a{(4J8AS7OGKl0uvPI{53(u7vzWt%FdHz<36?}gl&zU{@Vft;uFS_n?img8~UHELA zGM8WHCxLK7#n8xnr-GjyJpqQQU*N+yRVzw zAG7+;pBY(iygEHi_Us#8V{Pwy6;eA6o|$L5x$K|y6sCFKKOcX%_UZ3S@1yID-ZRxP zM?9YXGC8gE?3&3l_vWUlKfhT0WY-=Gj$fD8FW2XrWt(3rXQHa4Boy)NT>Rl+8JjrCxP*PG-`l+vP*4WX}(Q$&)g>gYgM~6p4AXr8yL4={JqoadG zg0%spkkO4eX~PFR3w-O!T|nT|k#t1|(*^Ez-$6W=Pe*u)&pjI9bFYy{`II}X;!$hiOKmSe?h^CPO6HE6H`xLH~6)fb7S@QxADT# z(&e4SdCqa)51%>5EHtP1{__nr$qN=0zvKS@+0tQ0abDEBuSV%--smi7DSr3*&pYq9 z6JHrFoM~FDr2MQrJi`b9cWcXZtFXwO&a{>3HD9MHhSIzLsQMTy$}3qulX;P>v03 z860zXd)VGF#n~Jx{?6Fkzi95n16%(utS_4L^p{OeMux}j)4R)fY*$8Hyp!kU;-d0E zL_4fyo%mM%>hv!^t{rec9uT^wIB)6y?@Gqj!aGEETsfoDT`9bo6 z@Q*u|+l_s9er}xh@A%4dJ1r$|t>i2DZtr*I;P>DaPkwPER8&MXvwh9Z+P<-)!$WUn zvD?-KD^_&49p8D&*5Op!*}emt5A+|H>L6(US8UG%?gcy_HqLZi9+Hsec;I)%K`Dpy z2aRu}Og29|@cuw_8;KZ34SHXTf-Q_{)*9lM&y5! zpXrR;4cQGv2evzOE7!=kdaYwmV>|dTF>&YJo{kQW160G}}MprfNlFtn>3brssC%9q2u9IW6pzzM04mz7?taglf9+PWqKa}2DdGpPTNXrF`8*ZGrH8YZZ z0rLhHi_`koxFVj>9vfMVK*^RdjwCZ(le)p%elheWY z!E}>I-Ai8p`)Wi#{d0e-@kGEJ%#5~pFB}~ekW{?uUh#J>qbU{%>l-%pVZ5+ zyD;z3kJ?<`2&L{Yy;i&&{%k5Gxn0Y>37Jtav%CNC+=FE!c!uuF= zj5ZghnaRIDF(Y9Ao4*dM35#dewr?-{xO(xM?8ar934(%xm7ErL8uunQyo_AJe=ItD z`YFrr(`RlyV*NY6um49}k(Ny3M-TUXd=a z?nrbx$GtBFUNfJcePg^pGeGDDTh07UZ5J)KA3G!UAlHa7|FE~=o{L8t7BCoyzqzq< zwr+HJz}_s^MT?a`@3uaEG(LLU=HlyeCHZZMVtR|SSuB}>5RCb;KZi$mf!n}^O~FX{|D>4_}AZ7Egn4m38uxwpAL*n93I&G!!uMojy&ZPHWiYk`Z7oHSVz-|Z#( z-}Zgs(NkX;uB>~?+HYvs{v-La*s1B-z8jNVgHHeb_B%^VKhiTN#^&p*kmZ?=cd@Xu zKmTzzY)y=ROpQ&bcKCvfi}lxMy}Pq@_D}Bm^tZcwr|1@IrJJtx|5>#3vhD8D+kV^L z|Ck+RswFHa=vP!^lzlx{$;xU{QL6Xm)Yp7vZ|?Z6m72=Q#r0@<{PayFH?u%iw{O$k z6x+X}^tPXvPSm-!-uj@0e=<$-uQgounttY^b!SJ1$H5{ewuYr%V$YYo-u>~{?D-#l z9M~7Ky2^^-Jb(T4VDGtyc(2FJN@e)*;lcDDA0BtUx&KkywaaDcvi|u7&G-Jwo!?UT zw&`=!=dyF}d%^FuwmVk8FP#&( zTZ^IgUDYJRWcA|vvHz1FpL+S`#us7bxVkB<-P4K#x8L^k^RvsbkCXf;_}$K8%IaO^ zNoT6h3kp5zmFknW@BRO^s%4#cdBW*m?>lerp3$qlytr)ju`j#RIk?6C&ReWeN?0>D7e0h1OInkKeNtg zbI{Mb>m5?kuFtx;=1$)878ynsi@i>g>-KHpUVOaf=z{kA=UXQxcX048zkW7cF4Xq# zJ6WfRN`W=@Uv0gnep%Lbdb+mn>uKqi_WPeNNj>{uuX%gH(Nx*XOZDS7_VwG%JaTmI z?N4`tzb{$#eb-N~vUhh5FZSPah&@@Y=e-uv%NPl=jN{FsjJN{e0{{X@?d;a=5lAoQ`0O> zgFmnvWWQ6IG28ZdY@JH))t%EL4 z`?IZU?(VYUy5C`EX8(`gwQccYB~DJxbDMGn1vR%^vwmJ>@m!D5k98ZfeoE+tGhOLF zWYW?S+gIP&zf1Ra{hl*#HvB&@`=)2ww5JEA&UBSu`0lW5(cB=lJ7*RZ1?Z_H+yB{e z;joQxUCSQ@W9vs>md%vi-n`2H1;dA)TcJC56i45awVn5)rNu|N%zcv3fsj=*zOH*X zCu;k>Xz%caHP1@xo}QX^?98RL+r2+NJU)5H((?+dLT%@6cej~nb!ytJ{if0kKVD4s z++y+lRf)as?YP7L{u<`oFRVGYR3}KKYsr#&{_Oazx3a5`M9)vj`hBO*e8P+wC3kL# z2~KP}YAMd`!;r-^N;6omsPM=3kB@42Egn7S9azkDfj=HYH8Fk@fb#A#?@EOY-9X=Hm7~&-H8u>K0lMgyMejGbTj{@C#Bz)dzb$#U2nKK_>Yb8 z=HF*>#6R@Ud~3A%_t`U-Z1!I|Q#I=*&ja}f7uW3LH~xL#jGX!A?|+M|&%ROoKkw1S z19JcW%Afxb6Kgzs_OstJ6VpU5Kbbv~_tX6Q>1n}@lQ(DV-##<<)BeS_Y2Rkdd|Jbv zCFXZS^MMHey>jk&-(P*w)n#Xk%HKb1X{|h1=H&Fq@aw~ZuPSP4kLGyK-RJxI?RWd- zCuf%aC_QK-SMh{(Uj46qB|kM6H#W<^JDh7?ety&2DO;P4Yn`osUw1psz^dj2!@50x z4(ZIl*ekE3#Q0X`-`>B)zMAAB#)ZGk#~7 z|Lf~k#z%kmuVQ zJDbfsomqd@&4}lB-lvIi`h5L;mqmYrG@FmXX18-YQ}&;&Ze*HGTg=k4;##G7K8@@{a zKl3>`JnQP0edl}Yb1qKQS5jgMxORr^@mj~%ELV>1E>(6_xo~@b60h-VrV!?JMd!|b zzx<1NKa=>QUIjZAo$_;EeS^=3*WDD@^WeGQ^E(#y?`w@;Gu+|oVSmL?&pdl>@wxxi zUGdvY;v9BdlHbTOW7@L0)(!b{i#4C0gP}Y*tC6Gg=2j90-XzHPfuAJ@0Op@D88bO{|=u|*}1*XuK!*#Gqy#%V3`EN zp2u^l@BjbPI@6Rb@1X?K0pThx3)j_Ry%tMg%ysuYCiL3KD}CW|NoEd zzE_#|w^>e{DA*(OHFH;HNW=8F-vSNYR`X}S+}ZXuTTn{skhuJQpUcNeD=R*DuQZ>_ z5VA66UR7z9LE0OYXZmOM+&0(Kn>RmQ|ICy+n=9+1n@>$W_4%3g{AGUZ%SDBYJ1qC7 z>^U6m;=;9&V}V!zpT0--t2x!`zW-)Td2l|QH($%*t$hgh$EGc}{yo2SVEWB1;gTIp z>%J}Tt2f(xvtn`Q)W1gZk7K`XJA3BX?3=1-Vk{5l+-BIrdd6t8Wm?(tnWCpJ?0+eF zYYy8LA8Xz@t~1}9Iq{*=_m)Y$OTO&AU!D!G4#-Qsv;KFpe*TpA%h?Q!o%gQ%`|-MI z7^~HipM7Z$d)?$NuN7DS!|`Ba)!(I!Te8Y^)5~9+WG=t&()`Qx=B85h$H)AiUjKRe z#@^I(g0D5gx0!&N2a4zSo@|}|ZPEGMa6wVYgX!@;Pv3sGd*1XpYWeNb*?}b`D)IF{ z+1B3v{^Z*~|A0SFl1ko}F*-Ur?)iBu;oQ3mlg*yTy6?ZeeqrR~Uq_A|+gR|i=veQ3 zx6{vfGw*&n^Z4gf1_43AbFcMzmlR*WXOexn`Csk2rG<;F-rU|k-_<+JsO*k;OqnNp z)SRmyc5K&GQc_>?_1sRm_LKMLJ}g!e;9_CcOkc>#nCQ^--;z=P#Obcj_4}E1PE8Q! zelX`Yr^&bFlk}PI9gsel{r>rPqs{3bmc>^y_0Nv`52i6Z~6K`2%wc0V{+*`xAIlayW)XX@M ztUvkFe#e)=-WQf%ziPSe`ANsW7C)CP;;H!~x~$$>x?#Zrg}mJ>t@Z7`9}t|cAGydP zSbdM@>222w-u{<+uw-)ArH#(ov&^#(9I|};qW=A5p4yLhOP+I@We4e>jy-w&H0$%N zY47;uFTbCsX!G;Ti7W4qoyoZS$w%+q9lh(Int&9(5%+JNe&nCY| z>U4v9T*QX*`~TGbKdm&b7S%tIG0XQKvqSjvn9n>fiyMUwOs-H4V*cpHHQW06oS9b- zO5gp>SRot1U&3HlaPFkY#-$^sxEs%ft$nOIgdw9jKGf%g8uJ-%yedaqa=A6!(W%bln zol$#E@%N>kza{hkJ~&{K`ML4qxt+`Z#P0I`V0O-?QCz~l$9!tty!d}kdtQEj>lZivmrMRLKh{BcLCL9KhyO3S(9f_;R8-V)ua#-v%DxL1CM2&@wiXn8 zc*S<{uZi5xnogYHkh-#ZrhaaBhsVC?!w-|2e3!((p8kmGf#se9Y_@B}hd-A6KgaI&^Jo4~_XBr&#qX#*=$*s+`Sow%eCHDidld4m?yXDs(AT<>JEqrs z)i>LMoyB>ZZ#%i42RuqZKL#o>VcsP_TRUVBwuS zHy0O`gri4~KAv;BLc7&tTahh;O^HU?zb4oH>ax&bdGBfKyle!DGveyLJ9G8L@H0%F zG--L=x1U#*=th@6DGOFoQesShy=`ufw7ssTrDbJW-FH{6zB}`o%JOQ8iawp`)_*U& zKk@PWopw|Z_>YO{W8 z_KgK$5iS)K>$YnvDFsO!J$7_s#>cK7nwRVOxcIncRcM&KQ+s}A-k*2VMPw?47?zo( zU6Zre?lEzNn`2sH<+TkR9Uh94-o*TAWM&s(|u9)0TsWraPY4&t=w7Qc@y! z=$iB7>0@Wsuv}nS!Tdr^Ku~bv|6`1=8(Pop{QC2*q-MpZS9%W=9-Mpd;6eJLMcpdl zs{^eyO-#-d?M(!Y4`*FIR+@MF+I}Tx=flU;RE~TvJNNc1bo4$UBjd(~7fP&y;HImzOAQ^N_cq!l}8OibkffkX(BzI5^IW(Ee%N1!_bK-ZYmM49aH^(VHS*<)${@oP(=it4k!x#s2Hc1>do^`0<6VE*&mZqQhszIq75 zkK2z}?_7S)wygeh=(be1eMVENf8BA&$;pxXc4o4`e21Evn0cTiq*P=xHvk&_`zHK( zci`ie|MP3#+}POrWQmHOZfx6RKfOAiuSbs_-Bk9K%TKS4EA{l;x;a%dZ|>V$ePd&- zw&THrbE0hIzkkCI}0=BZO-)GQrcD7kT{QdtI*Hz}uy1x3r zG<$PK0qN?FgZ$r?d#*K#x%V>1YRihlt6%* z%Sv~p*Z;}W;$1Z@;Z1w~=B%SezwQ;8=1PSxPHpZwa!iitL4prYGuxNPXJ#$kxx?95 zFXM8<=2uf5Kfaj%aE|pi{V33=MyqfUi-DnG=Z+m~uK!To{lq7e{oDKHAuliQ_|lcV zB4nx5#EBQzL~ow-{a)3~xa;M~hkD{Q12=`d`uy=@VU2mM(fghnPU97EoB7)Ljy?F$ zwB+{x>vJvb&o1%3{n>K)U)Gk^){TF*AN7&3H;divJA1pDon2r2^M7ZShQ~~vWmo!X z`jO+u4O1UIH_5xDWLkSrfAh+qwQjFC?%V(V7PPU*wCc;A)~>0m1f;}{eM6OyB4Y z|L52C{Cy!SSN}s#NlE!-)zPj0zt#&03JPkv_?=+*@b#hp=U*R|7su?YTwVO*&+GZd zOQ-9UYW3TesDG}X>3aO!^kt`S|GJ*WX8Tnsc2}HdK|w**uPZ0xjh-)`S@OEj)}OET z?S1xjO>b{+`*ioq$(5d|r{|x0DXMK;e{ao|ExFPEo@`g;)`(vyba~&uu68-;u9+Xd zubZ25Z%gCL{hAA5F}srJpy)#BQ9@mvSwrLU!FU4MLQ_Rc4tRvRz%pZkZE z;qQCt8H@LAv)C=0Y+o}w)_QyJrjX2K{xdx;E;=e<@FMfwj-Og$=jMAqUZxwdDMOAS zeXEsvuT&3eD^-rxKujNUI>t$$90K}}u# z^Rd(CKYe@=_~zD5*@g!X5|osb89luGP8HtH4qw0Iho-7V>8ngjt^0ef?(F&dAy@3o zZ0F*)+#^>!<1g&Um35*Xe zR()yQSM%@W?=6|tcINl4&CfE;3S9JLrOvGX+}C5SJzVkX*6wukz(Cg`aC$N@7CSTB z_42c|kw0F`#O>Rvuc)}NyM#Z_&w54;}!x~J;M(W6Gcm%qQX z)cUza#RrFJ=eJ~(>a7mfN&b^Ae`%Yu`k_O6H1AByy%o6ShUcC?e}rYMBqrzmy)Q3) zed3%sbDoBLu76p+_}JN>)z|r!`AE%A{WtG!y?iMo5=4J6eAr_2RHHU3QtZs^v+nPE zQ!XF-suO9^AKqr`x<7ioWf7}nOnI<;Q&UsLk9qgb%rI)~eSQ7Y*(3Tpw%x8gGxw|W zwDTtUwR)bOo;rU@^LE`mrg`}QD5pn6SoF@CGj&$@Uboyuix$r`OjUYp|9gVHd49^l zJvVKB|7hlsyI{XMjqmk2b~cdHdG@?7bKC#dD*E4@BaO_zXPQ4(Z?pd{Asc<&`jr)E zc}IcP2S$Yh!H3-h1SOA7W`4i$@y)L<3q7svFK$CUn^D1UB&*H$T;Pe%;?-P_u{ zZ+pzy*5@Wq-rZim*kfXniN)r~Y3EIBSBoxOnCRl_e)-p(&zGLYURbKlz$-fA%*5@+(ckgz8j=J{rR^D^t)K3+9yN#Z|{vQO&dF6KVJdU2aT2b}k@0R>R zHs9>&4}ZNAH~KVnVaTeWzbjsgfSR2ri+;CtD7kj&)&A&w{`%oVm zfQg%)Zr)dwd$lX|&F$Uo$IeDAv)-ToI)3&{%g55+-rjbey2>>3@;94FlO{+0yZxx- zt87na;>}B~Q*`4SKZ$Ck-k!d7b+|$PIe!&3m4Nk$!cwM|-KMLjZBGAw-z4{*)m_ON z25<56>M9m3#;;6$rq7!(JO>+@RJDsD-mrj=`$nq^BozCfMuO_xm^R*xqvH>W$%N5EgzEzCL=h*7n(;)_cV3 z>uZ!uOmvP}Zr9)cTZz?q9ecyak00&ptxJP)l9HVA%t32aChVJQrfI37^5puTckLoF zl^fX#uJpZ){$KZRWuxA9{<&hHwxE5T`BZ;9iKl$BRu%E!)_Kf+PL=~_X0^7q`>zaM zANWNy{Jucg>N49y%1Xt1V?mL7VrPokn&`9q_kDfk{=aNLIpgl!852Hu)qVHo>a*cw zU_7(NB_ra-WJSe=&yUMlMVz!;E_*^rN$G!Jh077Y!*!j#wk8)Ww_EK0t;~A*KVy=y WSpnx7-2)5^3=E#GelF{r5}E+_A6v}; literal 0 HcmV?d00001 diff --git a/l4/doc/source/l4re-footer.html b/l4/doc/source/l4re-footer.html new file mode 100644 index 00000000..236b44f1 --- /dev/null +++ b/l4/doc/source/l4re-footer.html @@ -0,0 +1,6 @@ +
+ L4Re - L4 Runtime Environment +
+ + + diff --git a/l4/doc/source/l4re-header.html b/l4/doc/source/l4re-header.html new file mode 100644 index 00000000..d1528956 --- /dev/null +++ b/l4/doc/source/l4re-header.html @@ -0,0 +1,12 @@ + + + L4Re Reference Manual + + + + + +
+
+ L4Re - L4 Runtime Environment +
diff --git a/l4/doc/source/l4re.cfg b/l4/doc/source/l4re.cfg new file mode 100644 index 00000000..425bdc8c --- /dev/null +++ b/l4/doc/source/l4re.cfg @@ -0,0 +1,1643 @@ +# Doxyfile 1.7.1 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project +# +# All text after a hash (#) is considered a comment and will be ignored +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" ") + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all +# text before the first occurrence of this tag. Doxygen uses libiconv (or the +# iconv built into libc) for the transcoding. See +# http://www.gnu.org/software/libiconv for the list of possible encodings. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded +# by quotes) that should identify the project. + +PROJECT_NAME = "L4Re" + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = l4re + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create +# 4096 sub-directories (in 2 levels) under the output directory of each output +# format and will distribute the generated files over these directories. +# Enabling this option can be useful when feeding doxygen a huge amount of +# source files, where putting all generated files in the same directory would +# otherwise cause performance problems for the file system. + +CREATE_SUBDIRS = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, +# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, +# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English +# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, +# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak, +# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is +# used as the annotated text. Otherwise, the brief description is used as-is. +# If left blank, the following values are used ("$name" is automatically +# replaced with the name of the entity): "The $name class" "The $name widget" +# "The $name file" "is" "provides" "specifies" "contains" +# "represents" "a" "an" "the" + +ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = YES + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. + +STRIP_FROM_PATH = $(OBJ_BASE)/include + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of +# the path mentioned in the documentation of a class, which tells +# the reader which header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that +# are normally passed to the compiler using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful is your file systems +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like regular Qt-style comments +# (thus requiring an explicit @brief command for a brief description.) + +JAVADOC_AUTOBRIEF = YES + +# If the QT_AUTOBRIEF tag is set to YES then Doxygen will +# interpret the first line (until the first dot) of a Qt-style +# comment as the brief description. If set to NO, the comments +# will behave just like regular Qt-style comments (thus requiring +# an explicit \brief command for a brief description.) + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce +# a new page for each member. If set to NO, the documentation of a member will +# be part of the file/class/namespace that contains it. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 2 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C +# sources only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = YES + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java +# sources only. Doxygen will then generate output that is more tailored for +# Java. For instance, namespaces will be presented as packages, qualified +# scopes will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources only. Doxygen will then generate output that is more tailored for +# Fortran. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for +# VHDL. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given extension. +# Doxygen has a built-in mapping, but you can override or extend it using this +# tag. The format is ext=language, where ext is a file extension, and language +# is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C, +# C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make +# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C +# (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions +# you also need to set FILE_PATTERNS otherwise the files are not read by doxygen. + +EXTENSION_MAPPING = + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should +# set this tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. +# func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. +# Doxygen will parse them like normal C++ but will assume all classes use public +# instead of private inheritance when no explicit protection keyword is present. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate getter +# and setter methods for a property. Setting this option to YES (the default) +# will make doxygen to replace the get and set methods by a property in the +# documentation. This will only work if the methods are indeed getting or +# setting a simple type. If this is not the case, or you want to show the +# methods anyway, you should set this option to NO. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + +SUBGROUPING = YES + +# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum +# is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically +# be useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. + +TYPEDEF_HIDES_STRUCT = NO + +# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to +# determine which symbols to keep in memory and which to flush to disk. +# When the cache is full, less often used symbols will be written to disk. +# For small to medium size projects (<1000 input files) the default value is +# probably good enough. For larger projects a too small cache size can cause +# doxygen to be busy swapping symbols to and from disk most of the time +# causing a significant performance penality. +# If the system has enough physical memory increasing the cache will improve the +# performance by keeping more symbols in memory. Note that the value works on +# a logarithmic scale so increasing the size by one will rougly double the +# memory usage. The cache size is given by this formula: +# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, +# corresponding to a cache size of 2^16 = 65536 symbols + +SYMBOL_CACHE_SIZE = 2 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = NO + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = NO + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. +# If set to NO (the default) only methods in the interface are included. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base +# name of the file that contains the anonymous namespace. By default +# anonymous namespace are hidden. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = YES + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen +# will list include files with double quotes in the documentation +# rather than with sharp brackets. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = NO + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen +# will sort the (brief and detailed) documentation of class members so that +# constructors and destructors are listed first. If set to NO (the default) +# the constructors will appear in the respective orders defined by +# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. +# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO +# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the +# hierarchy of group names into alphabetical order. If set to NO (the default) +# the group names will appear in their defined order. + +SORT_GROUP_NAMES = YES + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the +# alphabetical list. + +SORT_BY_SCOPE_NAME = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = NO + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or define consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and defines in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = YES + +# If the sources in your project are distributed over multiple directories +# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy +# in the documentation. The default is NO. + +SHOW_DIRECTORIES = YES + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. +# This will remove the Files entry from the Quick Index and from the +# Folder Tree View (if specified). The default is YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the +# Namespaces page. +# This will remove the Namespaces entry from the Quick Index +# and from the Folder Tree View (if specified). The default is YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command , where is the value of +# the FILE_VERSION_FILTER tag, and is the name of an input file +# provided by doxygen. Whatever the program writes to standard output +# is used as the file version. See the manual for examples. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. The create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. +# You can optionally specify a file name after the option, if omitted +# DoxygenLayout.xml will be used as the name of the layout file. + +LAYOUT_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = YES + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = YES + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be abled to get warnings for +# functions that are documented, but have no documentation for their parameters +# or return value. If set to NO (the default) doxygen will only warn about +# wrong or incomplete parameter documentation, but not about the absence of +# documentation. + +WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. Optionally the format may contain +# $version, which will be replaced by the version of the file (if it could +# be obtained via FILE_VERSION_FILTER) + +WARN_FORMAT = "$file:$line: $text " + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = $(L4DIR)/doc/source/l4re.dox \ + $(L4DIR)/doc/source/overview.dox \ + $(L4DIR)/doc/source/getting_started.dox \ + $(L4DIR)/doc/source/server_overview.dox \ + $(L4DIR)/doc/source/pthreads.dox + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is +# also the default input encoding. Doxygen uses libiconv (or the iconv built +# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for +# the list of possible encodings. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx +# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90 + +FILE_PATTERNS = * + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used select whether or not files or +# directories that are symbolic links (a Unix filesystem feature) are excluded +# from the input. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. Note that the wildcards are matched +# against the file with absolute path, so to exclude all test directories +# for example use the pattern */test/* + +EXCLUDE_PATTERNS = uclibc* \ + *.idl + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = $(L4DIR)/pkg + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = YES + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = $(L4DIR)/doc/source/images + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. +# If FILTER_PATTERNS is specified, this tag will be +# ignored. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. +# Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. +# The filters are a list of the form: +# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further +# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER +# is applied to all files. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + +FILTER_SOURCE_FILES = NO + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. + +SOURCE_BROWSER = YES + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = YES + +# If the REFERENCES_RELATION tag is set to YES +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = YES + +# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) +# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from +# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will +# link to the source code. +# Otherwise they will link to the documentation. + +REFERENCES_LINK_SOURCE = YES + +# If the USE_HTAGS tag is set to YES then the references to source code +# will point to the HTML generated by the htags(1) tool instead of doxygen +# built-in source browser. The htags tool is part of GNU's global source +# tagging system (see http://www.gnu.org/software/global/global.html). You +# will need version 4.8.6 or higher. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = YES + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. + +HTML_HEADER = $(L4DIR)/doc/source/l4re-header.html + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = $(L4DIR)/doc/source/l4re-footer.html + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own +# stylesheet in the HTML output directory as well, or it will be erased! + +HTML_STYLESHEET = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. +# Doxygen will adjust the colors in the stylesheet and background images +# according to this color. Hue is specified as an angle on a colorwheel, +# see http://en.wikipedia.org/wiki/Hue for more information. +# For instance the value 0 represents red, 60 is yellow, 120 is green, +# 180 is cyan, 240 is blue, 300 purple, and 360 is red again. +# The allowed range is 0 to 359. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of +# the colors in the HTML output. For a value of 0 the output will use +# grayscales only. A value of 255 will produce the most vivid colors. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to +# the luminance component of the colors in the HTML output. Values below +# 100 gradually make the output lighter, whereas values above 100 make +# the output darker. The value divided by 100 is the actual gamma applied, +# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, +# and 100 does not change the gamma. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting +# this to NO can help when comparing the output of multiple runs. + +HTML_TIMESTAMP = YES + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. + +HTML_ALIGN_MEMBERS = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. For this to work a browser that supports +# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox +# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). + +HTML_DYNAMIC_SECTIONS = YES + +# If the GENERATE_DOCSET tag is set to YES, additional index files +# will be generated that can be used as input for Apple's Xcode 3 +# integrated development environment, introduced with OSX 10.5 (Leopard). +# To create a documentation set, doxygen will generate a Makefile in the +# HTML output directory. Running make will produce the docset in that +# directory and running "make install" will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find +# it at startup. +# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html +# for more information. + +GENERATE_DOCSET = NO + +# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the +# feed. A documentation feed provides an umbrella under which multiple +# documentation sets from a single provider (such as a company or product suite) +# can be grouped. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that +# should uniquely identify the documentation set bundle. This should be a +# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen +# will append .docset to the name. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING +# is used to encode HtmlHelp index (hhk), content (hhc) and project file +# content. + +CHM_INDEX_ENCODING = + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated +# that can be used as input for Qt's qhelpgenerator to generate a +# Qt Compressed Help (.qch) of the generated HTML documentation. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can +# be used to specify the file name of the resulting .qch file. +# The path specified is relative to the HTML output folder. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#namespace + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#virtual-folders + +QHP_VIRTUAL_FOLDER = doc + +# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to +# add. For more information please see +# http://doc.trolltech.com/qthelpproject.html#custom-filters + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see +#
+# Qt Help Project / Custom Filters. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's +# filter section matches. +# +# Qt Help Project / Filter Attributes. + +QHP_SECT_FILTER_ATTRS = + +# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can +# be used to specify the location of Qt's qhelpgenerator. +# If non-empty doxygen will try to run qhelpgenerator on the generated +# .qhp file. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files +# will be generated, which together with the HTML files, form an Eclipse help +# plugin. To install this plugin and make it available under the help contents +# menu in Eclipse, the contents of the directory containing the HTML and XML +# files needs to be copied into the plugins directory of eclipse. The name of +# the directory within the plugins directory should be the same as +# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before +# the help appears. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have +# this name. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. + +DISABLE_INDEX = NO + +# This tag can be used to set the number of enum values (range [1..20]) +# that doxygen will group on one line in the generated HTML documentation. + +ENUM_VALUES_PER_LINE = 4 + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. +# If the tag value is set to YES, a side panel will be generated +# containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). +# Windows users are probably better off using the HTML help feature. + +GENERATE_TREEVIEW = YES + +# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, +# and Class Hierarchy pages using a tree view instead of an ordered list. + +USE_INLINE_TREES = YES + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open +# links to external symbols imported via tag files in a separate window. + +EXT_LINKS_IN_WINDOW = NO + +# Use this tag to change the font size of Latex formulas included +# as images in the HTML documentation. The default is 10. Note that +# when you change the font size after a successful doxygen run you need +# to manually remove any form_*.png images from the HTML output directory +# to force them to be regenerated. + +FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are +# not supported properly for IE 6.0, but are supported on all modern browsers. +# Note that when changing this option you need to delete any form_*.png files +# in the HTML output before the changes have effect. + +FORMULA_TRANSPARENT = YES + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box +# for the HTML output. The underlying search engine uses javascript +# and DHTML and should work on any modern browser. Note that when using +# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets +# (GENERATE_DOCSET) there is already a search function so this one should +# typically be disabled. For large projects the javascript based search engine +# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. + +SEARCHENGINE = YES + +# When the SERVER_BASED_SEARCH tag is enabled the search engine will be +# implemented using a PHP enabled web server instead of at the web client +# using Javascript. Doxygen will generate the search PHP script and index +# file to put on the web server. The advantage of the server +# based approach is that it scales better to large projects and allows +# full text search. The disadvances is that it is more difficult to setup +# and does not have live searching capabilities. + +SERVER_BASED_SEARCH = NO + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = NO + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. +# Note that when enabling USE_PDFLATEX this option is only used for +# generating bitmaps for formulas in the HTML output, but not in the +# Makefile that is written to the output directory. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, a4wide, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = a4wide + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = $(L4DIR)/doc/source/header.tex + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = YES + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = YES + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES = NO + +# If LATEX_SOURCE_CODE is set to YES then doxygen will include +# source code with syntax highlighting in the LaTeX output. +# Note that which sources are shown also depends on other settings +# such as SOURCE_BROWSER. + +LATEX_SOURCE_CODE = YES + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = YES + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3l4re + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. + +GENERATE_XML = NO + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + +XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. + +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. +# This is useful +# if you want to understand what is going on. +# On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = YES + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_DEFINED tags. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# in the INCLUDE_PATH (see below) will be search if a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator +# instead of the = operator. + +PREDEFINED = L4_INLINE=inline \ + __cplusplus=1 \ + __BEGIN_DECLS= \ + __END_DELCS= \ + L4_CV= \ + EXTERN_C_BEGIN= \ + EXTERN_C_END= \ + __attribute__()= \ + __GNUC__=4 + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all function-like macros that are alone +# on a line, have an all uppercase name, and do not end with a semicolon. Such +# function macros are typically used for boiler-plate code, and will confuse +# the parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. +# Optionally an initial location of the external documentation +# can be added for each tagfile. The format of a tag file without +# this location is as follows: +# +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths or +# URLs. If a location is present for each tag, the installdox tool +# does not have to be run to correct the links. +# Note that each tag file must have a unique name +# (where the name does NOT include the path) +# If a tag file is not located in the directory in which doxygen +# is run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base +# or super classes. Setting the tag to NO turns the diagrams off. Note that +# this option is superseded by the HAVE_DOT option below. This is only a +# fallback. It is recommended to install and use dot, since it yields more +# powerful graphs. + +CLASS_DIAGRAMS = YES + +# You can define message sequence charts within doxygen comments using the \msc +# command. Doxygen will then run the mscgen tool (see +# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the +# documentation. The MSCGEN_PATH tag allows you to specify the directory where +# the mscgen tool resides. If left empty the tool is assumed to be found in the +# default search path. + +MSCGEN_PATH = + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = YES + +# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is +# allowed to run in parallel. When set to 0 (the default) doxygen will +# base this on the number of processors available in the system. You can set it +# explicitly to a value larger than 0 to get control over the balance +# between CPU load and processing speed. + +DOT_NUM_THREADS = 0 + +# By default doxygen will write a font called FreeSans.ttf to the output +# directory and reference it in all dot files that doxygen generates. This +# font does not include all possible unicode characters however, so when you need +# these (or just want a differently looking font) you can specify the font name +# using DOT_FONTNAME. You need need to make sure dot is able to find the font, +# which can be done by putting it in a standard location or by setting the +# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory +# containing the font. + +DOT_FONTNAME = FreeSans + +# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. +# The default size is 10pt. + +DOT_FONTSIZE = 10 + +# By default doxygen will tell dot to use the output directory to look for the +# FreeSans.ttf font (which doxygen will put there itself). If you specify a +# different font using DOT_FONTNAME you can set the path where dot +# can find it using this tag. + +DOT_FONTPATH = + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# the CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = YES + +# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for groups, showing the direct groups dependencies + +GROUP_GRAPHS = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. + +UML_LOOK = YES + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH and HAVE_DOT options are set to YES then +# doxygen will generate a call dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable call graphs +# for selected functions only using the \callgraph command. + +CALL_GRAPH = YES + +# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then +# doxygen will generate a caller dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable caller +# graphs for selected functions only using the \callergraph command. + +CALLER_GRAPH = YES + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES +# then doxygen will show the dependencies a directory has on other directories +# in a graphical way. The dependency relations are determined by the #include +# relations between the files in the directories. + +DIRECTORY_GRAPH = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are png, jpg, or gif +# If left blank png will be used. + +DOT_IMAGE_FORMAT = png + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found in the path. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = + +# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of +# nodes that will be shown in the graph. If the number of nodes in a graph +# becomes larger than this value, doxygen will truncate the graph, which is +# visualized by representing a node as a red box. Note that doxygen if the +# number of direct children of the root node in a graph is already larger than +# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note +# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. + +DOT_GRAPH_MAX_NODES = 50 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes +# that lay further from the root node will be omitted. Note that setting this +# option to 1 or 2 may greatly reduce the computation time needed for large +# code bases. Also note that the size of a graph can be further restricted by +# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. + +MAX_DOT_GRAPH_DEPTH = 0 + +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is disabled by default, because dot on Windows does not +# seem to support this out of the box. Warning: Depending on the platform used, +# enabling this option may lead to badly anti-aliased labels on the edges of +# a graph (i.e. they become hard to read). + +DOT_TRANSPARENT = NO + +# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) +# support this, this feature is disabled by default. + +DOT_MULTI_TARGETS = NO + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES diff --git a/l4/doc/source/l4re.dox b/l4/doc/source/l4re.dox new file mode 100644 index 00000000..d962670d --- /dev/null +++ b/l4/doc/source/l4re.dox @@ -0,0 +1,82 @@ +/* vim:set ft=c: */ + + +/** + * \example hello/server/src/main.c + * This is the famous "Hello World!" program. + * + * \example examples/sys/ipc/ipc_example.c + * This example shows how two threads can exchange data using the L4 IPC + * mechanism. One thread is sending an integer to the other thread which + * is returning the square of the integer. Both values are printed. + * + * \example examples/sys/ipc/ipc.cfg + * Sample configuration file for the IPC example. + * + * \example examples/sys/start-with-exc/main.c + * This example shows how to start a newly created thread with a defined set + * of CPU registers. + * + * \example examples/sys/singlestep/main.c + * This example shows how a thread can be single stepped on the x86 + * architecture. + * + * \example examples/sys/aliens/main.c + * This example shows how system call tracing can be done. + * + * \example examples/sys/utcb-ipc/main.c + * This example shows how to send IPC using the UTCB to store payload. + * + * \example examples/sys/ux-vhw/main.c + * This example shows how to iterate the virtual hardware descriptors under + * Fiasco-UX. + * + * \example examples/sys/isr/main.c + * Example of an interrupt service routine. + * + * \example examples/clntsrv/server.cc + * Client/Server example using C++ infrastructure -- Server implementation. + * \example examples/clntsrv/client.cc + * Client/Server example using C++ infrastructure -- Client implementation. + * \example examples/clntsrv/clntsrv.cfg + * Sample configuration file for the client/server example. + * + * \example examples/libs/l4re/c/ma+rm.c + * Coarse grained memory allocation, in C. + * \example examples/libs/l4re/c++/mem_alloc/ma+rm.cc + * Coarse grained memory allocation, in C++. + * + * \example examples/libs/l4re/c++/shared_ds/ds_clnt.cc + * Sharing memory between applications, client side. + * \example examples/libs/l4re/c++/shared_ds/ds_srv.cc + * Sharing memory between applications, server/creator side. + * \example examples/libs/l4re/c++/shared_ds/shared_ds.lua + * Sharing memory between applications, configuration file. + * + * \example examples/libs/l4re/streammap/server.cc + * Client/Server example showing how to map a page to another task -- Server + * implementation. Note that there's also a shared memory library that + * supplies this functionality in more convenient way. + * \example examples/libs/l4re/streammap/client.cc + * Client/Server example showing how to map a page to another task -- Client + * implementation. Note that there's also a shared memory library that + * supplies this functionality in more convenient way. + * \example examples/libs/l4re/streammap/streammap.cfg + * Sample configuration file for the client/server map example. + * + * + * \example examples/libs/libirq/loop.c + * libirq usage example using a self-created thread. + * + * \example examples/libs/libirq/async_isr.c + * libirq usage example using asychronous ISR handler functionality. + * + * \example examples/sys/migrate/thread_migrate.cc + * Thread migration example. + * + * \example examples/sys/migrate/thread_migrate.cfg + * Sample configuration file for the thread migration example. + * + * \example tmpfs/lib/src/fs.cc + * Example file system for L4Re::Vfs. + */ diff --git a/l4/doc/source/overview.dox b/l4/doc/source/overview.dox new file mode 100644 index 00000000..dd326bfb --- /dev/null +++ b/l4/doc/source/overview.dox @@ -0,0 +1,526 @@ +// vi:ft=c +/** +\mainpage Fiasco.OC & L4 Runtime Environment (L4Re) + +\section l4re_concepts_preface Preface + +The intention of this document is to provide a birds eye overview +about L4Re and about the environment in which typical +applications and servers run. We highlight here the principled +functionality of the servers in the environment but do not +discuss their specific interfaces. Detailed documentation about +these interface is available in the modules section. + +The document is meant as a general overview repeating many design +concepts of L4-based systems and capability systems in general. +We do though assume familiarity with C++ and an idea on the +general concepts and terms of L4: threads --- as an abstraction +for execution ---, tasks --- holding the capabilities to kernel +objects that are accessible by the threads executing in this task +---, and \link l4_ipc_api IPC\endlink over +\link l4_kernel_object_gate_api IPC-gates\endlink to send messages +and to transfer capabilities between tasks. + +\todo A more detailed introduction to these concepts is given in the User Manual. +\todo _XXX REF TO APPROPRIATE SPEC / BIG TODO / L4-Ref + +\section l4re_concepts_structure General System Structure + +The system has a multi-tier architecture consisting of the +following layers depicted in the figure below: + +\li Microkernel The microkernel is the component at the lowest level of +the software stack. It is the only piece of software that is running in the +privileged mode of the processor. + +\li Tasks Tasks are the basic containers (address spaces) in which system +services and applications are executed. They run in the processor's deprivileged +user mode. + +\image html l4re-basic.png "Basic Structure of an L4Re based system" +\image latex l4re-basic.pdf "Basic Structure of an L4Re based system" + +In terms of functionality, the system is structured as follows: + +\li Microkernel The kernel provides primitives to execute programs in tasks, +to enforce isolation among them, and to provide means of secure communication in +order to let them cooperate. As the kernel is the most privileged, security-critical +software component in the system, it is a general design goal to make it as small +as possible in order to reduce its attack surface. It provides only a minimal set of +mechanisms that are necessary to support applications. + +\li Runtime Environment The small kernel offers a concise set of interfaces, +but these are not necessarily suited for building applications directly on top of +it. The L4 Runtime Environment aims at providing more convenient abstractions for +application development. It comprises low-level software components that interface +directly with the microkernel. The root pager \em sigma0 and the root task \em Moe +are the most basic components of the runtime environment. Other services (e.g., for +device enumeration) use interfaces provided by them. + +\li \b Applications Applications run on top of the system and use services +provided by the Runtime Environment -- or by other applications. There may be +several types of applications in the system and even virtual machine monitors +and device drivers are considered applications in the terminology used in this +document. They are running alongside other applications on the system. + +Lending terminology from the distributed systems area, applications offering +services to other applications are usually called \em servers, whereas +applications using those services are named \em clients. Being in both +roles is also common, for instance, a file system server may be viewed as a +server with respect to clients using the file system, while the server itself +may also act as a client of a hard disk driver. + +In the following sections, we discuss the basic concepts of our microkernel and +its runtime environment in more depth. + +\section l4re_concepts_fiasco The Fiasco.OC Microkernel + +The Fiasco.OC microkernel is the lowest-level piece of software running in an +L4-based system. The microkernel is the only program that runs in privileged +processor mode. It does not include complex services such as program loading, +device drivers, or file systems; those are implemented in user-level programs on +top of it (a basic set these services and abstractions is provided by the L4 +Runtime Environment). + +Fiasco.OC kernel services are implemented in kernel objects. Tasks hold +references to kernel objects in their respective \em "object space", which is a +kernel-protected table. +These references are called \em capabilities. Fiasco system calls are function +invocations on kernel objects through the corresponding capabilities. These +can be thought of as function invocations on object references in an +object-oriented programming environment. Furthermore, if a task owns a +capability, it may grant other tasks the same (or fewer) rights on this object +by passing the capability from its own to the other task's object space. + +From a design perspective, capabilities are a concept that enables flexibility +in the system structure. A thread that invokes an object through a capability +does not need to care about where this object is implemented. In fact, it is +possible to implement all objects either in the kernel or in a user-level +server and replace one implementation with the other transparently for clients. + +\subsection l4re_concepts_fiasco_ipc Communication + +The basic communication mechanism in L4-based systems is called +\em "Inter Process Communication (IPC)". It is always synchronous, i.e. both +communication partners need to actively rendezvous for IPC. In addition to +transmitting arbitrary data between threads, IPC is also used to resolve +hardware exceptions, faults and for virtual memory management. + +\subsection l4re_concepts_fiasco_kobjects Kernel Objects + +The following list gives a short overview of the kernel objects provided by +the Fiasco.OC microkernel: + +\li Task A task comprises a memory address space (represented by the task's page table), an object space (holding the kernel protected capabilities), and on X86 an IO-port address space. +\li Thread A thread is bound to a task and executes code. Multiple +threads can coexist in one task and are scheduled by the Fiasco scheduler. +\li Factory A factory is used by applications to create new kernel +objects. Access to a factory is required to create any new kernel object. +Factories can control and restrict object creation. +\li IPC Gate An IPC gate is used to create a secure communication +channel between different tasks. It embeds a label (kernel protected payload) that securely identifies +the gate through which a message is received. The gate label is not visible +to and cannot be altered by the sender. +\li IRQ IRQ objects provide access to hardware interrupts. Additionally, +programs can create new virtual interrupt objects and trigger them. This +allows to implement a signaling mechanism. The receiver cannot decide whether +the interrupt is a physical or virtual one. +\li Vcon Provides access to the in-kernel debugging console (input and output). +There is only one such object in the kernel and it is only available, if the +kernel is built with debugging enabled. This object is typically interposed through a user-level service or without debugging in the kernel can be completely based on user-level services. +\li Scheduler Implements scheduling policy and assignment of threads + to CPUs, including CPU statistics. + +\section main_l4re_sec L4 Runtime Environment (L4Re) + +The L4 Runtime Environment (L4Re) provides a basic set of services and +abstractions, which are useful to implement and run user-level applications on +top of the Fiasco.OC microkernel. + +L4Re consists of a set of libraries and servers. Libraries as well as server +interfaces are completely object oriented. They implement prototype +implementations for the classes defined by the L4Re specification. + +A minimal L4Re-based application needs 3 components to be booted beforehand: +the Fiasco microkernel, the root pager (Sigma0), and the root task (Moe). The +Sigma0 root pager initially owns all system resources, but is usually used +only to resolve page faults for the Moe root task. Moe provides the essential +services to normal user applications such as an initial program loader, a +region-map service for virtual memory management, and a memory (data space) +allocator. + + +\section l4re_concepts Introduction to L4Re's concepts + +This section introduces basic concepts used by L4Re. Understanding of these +concepts is a fundamental requirement to understand the inner workings of +L4Re's software components and can dramatically help developers in +efficiently developing L4Re-based software. + +\if WORKING_SUBPAGES +\section l4re_concepts_details Further Details + +- \subpage l4re_concepts_naming +- \subpage l4re_concepts_env_and_start +- \subpage l4re_concepts_ds_rm +- \subpage l4re_concepts_env +- \subpage l4re_concepts_stdio +- \subpage l4re_concepts_memalloc +- \subpage l4re_concepts_apps_svr +\endif + + +\if WORKING_SUBPAGES +\page l4re_concepts_ds_rm Memory management - Data Spaces and the Region Map +\else +\section l4re_concepts_ds_rm Memory management - Data Spaces and the Region Map +\endif + +\subsection l4re_concept_pagers User-level paging + +Memory management in L4-based systems is done by user-level applications, the +role is usually called \em pager. Tasks can give other tasks full or +restricted access rights to parts of their own memory. The kernel offers means +to grant the memory in a secure way, often referred to as \em memory mapping. + +The described mechanism can be used to construct a memory hierarchy among +tasks. The root of the hierarchy is \em sigma0, which initially gets all +system resources and hands them out once on a first-come-first-served basis. +Memory resources can be mapped between tasks at a page-size granularity. This +size is predetermined by the CPU's memory management unit and is commonly set +to 4 kB. + +\subsection l4re_concept_data_spaces Data spaces + +A data space is the L4Re abstraction for objects which may be +accessed in a memory mapped fashion (i.e., using normal memory +read and write instructions). Examples include the sections of a +binary which the loader attaches to the application's address +space, files in the ROM or on disk provided by a file server, the +registers of memory-mapped devices and anonymous memory such as +the heap or the stack. + +Anonymous memory data spaces in particular (but in general all +data spaces except memory mapped IO) can either be constructed +entirely from a portion of the RAM or the current working set may +be multiplexed on some portion of the RAM. In the first case it +is possible to eagerly insert all pages (more precisely +page-frame capabilities) into the application's address space +such that no further page faults occur when this data space is +accessed. In general, however, only the pages for the some +portion are provided and further pages are inserted by the pager +as a result of page faults. + +\subsection l4re_concept_regions Virtual Memory Handling + +The virtual memory of each task is constructed from data spaces, backing virtual memory regions (VMRs). +The management of the VMRs is provided by an object called \em region \em map. A dedicated region-map object is associated with each task, +it allows to attach and detach data spaces to an +address space as well as to reserve areas of virtual memory. Since the region-map +object possesses all knowledge about virtual memory layout of a task, it also serves as +an application's default pager. + +\subsection l4re_concept_mem_alloc Memory Allocation + +Operating systems commonly use anonymous memory for implementing dynamic +memory allocation (e.g., using \em malloc or \em new). In an +L4Re-based system, each task gets assigned a memory allocator providing +anonymous memory using data spaces. + + +\see \ref api_l4re_dataspace and \ref api_l4re_rm. + + +\if WORKING_SUBPAGES +\page l4re_concepts_naming Capabilities and Naming +\else +\section l4re_concepts_naming Capabilities and Naming +\endif + +The L4Re system is a capability based system which uses and offers +capabilities to implement fine-grained access control. + +Generally, owning a capability means to be allowed to communicate with the +object the capability points to. All user-visible kernel objects, such as +tasks, threads, and IRQs, can be accessed only through a capability. +Please refer to the \link l4_kernel_object_api Kernel Objects\endlink +documentation for details. Capabilities are stored in per-task capability +tables (the object space) and are referenced by capability selectors or +object flex pages. In a simplified view, a capability selector is a natural +number indexing into the capability table of the current task. + +As a matter of fact, a system designed solely based on capabilities, uses +so-called 'local names', because each task can only access those objects made +available to this task. Other objects are not visible to and accessible by the +task. + +\image html l4-caps-basic.png "Capabilities and Local Naming in L4" +\image latex l4-caps-basic.pdf "Capabilities and Local Naming in L4 + +So how does an application get access to service? +In general all applications are started with an initial set of objects +available. This set of objects is predetermined by the creator of a new +application process and granted directly to into the new task before starting +the first application thread. The application can then use these initial objects +to request access to further objects or to transfer capabilities to own objects +to other applications. A central L4Re object for exchanging capabilities at +runtime is the name-space object, implementing a store of named capabilities. + +From a security perspective, the set of initial capabilities (access rights to +objects) completely define the execution environment of an application. +Mandatory security policies can be defined by well known properties of the +initial objects and carefully handled access rights to them. + + +\if WORKING_SUBPAGES +\page l4re_concepts_env_and_start Initial Environment and Application Bootstrapping +\else +\section l4re_concepts_env_and_start Initial Environment and Application Bootstrapping +\endif + +New applications that are started by a loader conforming to L4Re get +provided an \link api_l4re_env initial environment\endlink. This environment +comprises a set of capabilities to initial L4Re objects that are +required to bootstrap and run this application. These +capabilities include: + +\li A capability to an initial memory allocator for obtaining memory in the + form of data spaces +\li A capability to a factory which can be used to create additional kernel + objects +\li A capability to a Vcon object for debugging output and maybe input +\li A set of named capabilities to application specific objects + +During the bootstrapping of the application, the loader establishes data +spaces for each individual region in the ELF binary. These include data spaces +for the code and data sections, and a data space backed with RAM for the stack +of the program's first thread. + +One loader implementation is the \em Moe root task. Moe usually starts an \em +init process that is responsible for coordinating the further boot +process. The default \em init process is \em Ned, which implements a +script-based configuration and startup of other processes. Ned uses Lua +(http://www.lua.org) as its scripting language, see \ref l4re_servers_ned +"Ned Script example" for more details. + + +\subsection l4re_ns_config Configuring an application before startup + +The default L4Re init process (Ned) provides a Lua script based configuration +of initial capabilities and application startup. Ned itself also has a set of +initial objects available that can be used to create the environment for an +application. The most important object is a kernel object factory that allows +creation of kernel objects such as IPC gates (communication channels), tasks, +threads, etc. Ned uses Lua tables (associative arrays) to represent sets of +capabilities that shall be granted to application processes. + +\code + local caps = { + name = some_capability + } +\endcode + + +The 'L4' Lua package in Ned also has support functions to create application +tasks, region-map objects, etc. to start an ELF binary in a new task. +The package also contains Lua bindings for basic L4Re objects, for example, to +generic factory objects, which are used to create kernel objects and also +user-level objects provided by user-level servers. + +\code + L4.default_loader:start({ caps = { some_service = service } }, "rom/program --arg"); +\endcode + + +\subsection l4re_config_connection Connecting clients and servers + +In general, a connection between a client and a server is represented by a +communication channel (IPC gate). That is available to the client and the +server. You can see the simplest connection between a client and a server +in the following example. + +\code + local loader = L4.default_loader; -- which is Moe + local svc = loader:new_channel(); -- create an IPC gate + loader:start({ caps = { service = svc:full() }}, "rom/my_server"); + loader:start({ caps = { service = svc:m("rw") }}, "rom/my_client"); +\endcode + +As you can see in the snippet, the first action is to create a new channel +(IPC gate) using \c loader:new_channel(). The capability to the gate is stored +in the variable \c svc. Then the binary \c my_server is started in a new task, +and full (\c :full()) access to the IPC gate is granted to the server as initial +object. The gate is accessible to the server application as "service" in the set of +its initial capabilities. Virtually in parallel a second task, running the client +application, is started and also given access to the IPC gate with less rights +(\c :m("rw"), note, this is essential). The server can now receive messages via the +IPC gate and provide some service and the client can call operations on the IPC gate +to communicate with the server. + +Services that keep client specific state need to implement per-client server +objects. Usually it is the responsibility of some authority (e.g., Ned) to +request such an object from the service via a generic factory object that the +service provides initially. + +\code + local loader = L4.default_loader; -- which is Moe + local svc = loader:new_channel():m("rws"); -- create an IPC gate with rws rights + loader:start({ caps = { service = svc:full() } }, "rom/my-service"); + loader:start({ caps = { foo_service = svc:create(object_to_create, "param") }}, "rom/client"); +\endcode + +This example is quite similar to the first one, however, the difference is that +Ned itself calls the create method on the factory object provided by the server and +passes the returned capability of that request as "foo_service" to the client process. + +\note The \c svc:create(..) call blocks on the server. This means the script execution +blocks until the my-service application handles the create request. + + +\if WORKING_SUBPAGES +\page l4re_concepts_stdio Program Input and Output +\else +\section l4re_concepts_stdio Program Input and Output +\endif + + +The initial environment provides a Vcon capability used as the standard +input/output stream. Output is usually connected to the parent of the +program and displayed as debugging output. The standard output is also used +as a back end to the C-style printf functions and the C++ streams. + +Vcon services are implemented in Moe and the loader as well as by the Fiasco +kernel and connected either to the serial line or to the screen if +available. + +\see \ref l4_vcon_api + + +\if WORKING_SUBPAGES +\page l4re_concepts_memalloc Initial Memory Allocator and Factory +\else +\section l4re_concepts_memalloc Initial Memory Allocator and Factory +\endif + +The purpose of the memory allocator and of the factory is to provide +the application with the means to allocate memory (in the form of data spaces) +and kernel objects respectively. +An initial memory allocator and an initial factory are accessible via the +allocation L4Re environment. + +\see \ref api_l4re_mem_alloc + + +The factory is a kernel object that provides the ability to create new +kernel objects dynamically. A factory imposes a resource limit for +kernel memory, and is thus a means to prevent denial of service attacks on +kernel resources. A factory can also be used to create new factory objects. + +\see \ref l4_factory_api + + + +\if WORKING_SUBPAGES +\page l4re_concepts_apps_svr Application and Server Building Blocks +\else +\section l4re_concepts_apps_svr Application and Server Building Blocks +\endif + +So far we have discussed the environment of applications in which a single +thread runs and which may invoke services provided through their initial objects. +In the following we describe some building blocks to extend the +application in various dimensions and to eventually implement a server which +implements user-level objects that may in turn be accessed by other +applications and servers. + +\if WORKING_SUBPAGES +\section l4re_concepts_app_thread Creating Additional Application Threads +\else +\subsection l4re_concepts_app_thread Creating Additional Application Threads +\endif + +To create application threads, one must allocate a stack on which +this thread may execute, create a thread kernel object and setup +the information required at startup time (instruction pointer, +stack pointer, etc.). In L4Re this functionality is encapsulated in the +pthread library. + +\if WORKING_SUBPAGES +\section l4re_concepts_service Providing a Service +\else +\subsection l4re_concepts_service Providing a Service +\endif + +In capability systems, services are typically provided by +transferring a capability to those applications that are +authorised to access the object to which the capability refers to. + +Let us discuss an example to illustrate how two parties can communicate with +each other: +Assume a simple file server, which implements an interface for accessing +individual files: read(pos, buf, length) and write(pos, data, length). + +L4Re provides support for building servers based on the class +L4::Server_object. L4::Server_object provides an abstract interface to be +used with the L4::Server class. Specific server objects such as, in our +case, files inherit from L4::Server_object. Let us call this class +File_object. When invoked upon receiving a message, the L4::Server will +automatically identify the corresponding server object based on the +capability that has been provided to its clients and invoke this object's +\em dispatch function with the incoming message as a parameter. Based on +this message, the server must then decide which of the protocols it +implements was invoked (if any). Usually, it will evaluate a protocol +specific opcode that clients are required to transmit as one of the first +words in the message. For example, assume our server assigns the following +opcodes: Read = 0 and Write = 1. The \em dispatch function calls the +corresponding server function (i.e., \em File_object::read() or \em +File_object::write()), which will in turn parse additional +parameters given to the function. In our case, this would be the position +and the amount of data to be read or written. In case the write function was +called the server will now update the contents of the file with the data +supplied. In case of a read it will store the requested part of the file in +the message buffer. A reply to the client finishes the client request. + +*/ + + +/* This is some text we currently do not use: + +\link api_l4re_dataspace Data spaces\endlink and the purpose of the \link +api_l4re_rm Region Map\endlink are explained in more detail in the following +section. + + +In Fiasco.OC capabilities are addressed in two different +ways. + +A capability can be addressed with the help of a capability +descriptor \XXX Ref which identifies the position of one single +capability in the application's address space. + +The second means to address a bunch of capabilities at once are +flexpages. A flexpage describes a region of the application's +address space that is of a power 2 size and size aligned. Thus +the name flexpage. When capabilities are to be transferred (see +IPC / MapItem) the flexpage decleared by the sender --- the send +flexpage --- specifies which capabilities are to be transferred. +These are at most those capabilities that are located within the +region described by the flexpage and precisely those in the +region that results from adjusting the flexpage with a possibly +smaller flexpage on the receiver side (see \XXX for more details +on how sender and receiver declared flexpages are adjusted). The +receiver declared flexpage --- the receive flexpage --- defines +where in the address space of the application capabilities are to +be received. + +The key insight here is that applications are able to restrict +an invoked server such that it can only modify a part of the +applications address space --- the receive flexpage. + +When invoking servers and when creating new objects one is faced +with the task to find not yet used parts in the address space of +the application at which the kernel or other servers may insert +capabilities. L4Re assists this task with the help of a capability +allocator. + +*/ diff --git a/l4/doc/source/pthreads.dox b/l4/doc/source/pthreads.dox new file mode 100644 index 00000000..d445e825 --- /dev/null +++ b/l4/doc/source/pthreads.dox @@ -0,0 +1,58 @@ +// vi:ft=c +/** + +\page l4re_pthreads Pthread Support + +L4Re supports the standard pthread library functionality. Therefore L4Re +itself does not contain any documentation for pthreads itself. Please refer +to the standard pthread documentation instead. + +The L4Re specific parts will be described herein. + +
    +
  • + Include pthread-l4.h header file: + \code + #include + \endcode + +
  • +
  • Return the local thread capability of a pthread thread: + + Use \c pthread_getl4cap(pthread_t *t) to get the capability index of + the pthread t. + + For example: + \code + pthread_getl4cap(pthread_self()); + \endcode +
  • + +
  • Setting the L4 priority of an L4 thread works with a special + scheduling policy (other policies do not affect the L4 thread + priority): + + \code + pthread_t t; + pthread_attr_t a; + struct sched_param sp; + + pthread_attr_init(&a); + sp.sched_priority = l4_priority; + pthread_attr_setschedpolicy(&a, SCHED_L4); + pthread_attr_setschedparam(&a, &sp); + pthread_attr_setinheritsched(&a, PTHREAD_EXPLICIT_SCHED); + + if (pthread_create(&t, &a, pthread_func, NULL)) + // failure... + + pthread_attr_destroy(&a); + \endcode + +
  • +
+ + + + +*/ diff --git a/l4/doc/source/server_overview.dox b/l4/doc/source/server_overview.dox new file mode 100644 index 00000000..1381faf5 --- /dev/null +++ b/l4/doc/source/server_overview.dox @@ -0,0 +1,94 @@ +/* vi:ft=c */ +/** + +\page l4re_servers L4Re Servers +\brief Here you shall find a tight overview over the standard services + running on Fiasco.OC and L4Re. + +\section l4re_sigma0_overwview Sigma0, the Root Pager + +Sigma0 is a special server running on L4 because it is responsible +of resolving page faults for the root task, the first useful task on +L4Re. Sigma0 can be seen as part of the kernel, however it runs in +unprivileged mode. To run something useful on Fiasco.OC you usually +need to run Sigma0, nevertheless it is possible to replace Sigma0 +by a different implementation. + + +\section l4re_moe_intro Moe, the Root Task + +Moe is our implementation of the L4 root task that is responsible for +bootstrapping the system, and to provide basic resource management services +to the applications on top. Therefore Moe provides L4Re resource management +an multiplexing services: +\li \b Memory in the form of memory allocators (L4Re::Mem_alloc, L4::Factory) + and data spaces (L4Re::Dataspace) +\li \b Cpu in the form of basic scheduler objects (L4::Scheduler) +\li \b Vcon multiplexing for debug output (output only) +\li \b Virtual \b memory \b management for applications, L4Re::Rm + +Moe further provides an implementation of L4Re name spaces (L4Re::Namespace), +which are for example used to provide a read only directory of all multi-boot +modules. In the case of a boot loader, like grub that enables a VESA frame +buffer, there is also a single instance of an L4Re graphics session +(L4Re::Goos). + +To start the system Moe starts a single ELF program, this init process. The +init process (usually Ned, see the next section) gets access to all resources +managed by Moe and to the Sigma0 root pager interface. + +For more details see \subpage l4re_servers_moe "Moe, the Root-Task". + + +\section l4re_ned_intro Ned, the Default Init Process + +To keep the root task free from complicated scripting engines and to avoid +circular dependencies in application startup (that could lead to dead locks) +the configuration and startup of the real system is managed by an extra task, +the init process. + +Ned is such an init process that allows system configuration via Lua scripts. + +For more information see \subpage l4re_servers_ned "Ned". + + +\section l4re_io_intro Io, the Platform and Device Resource Manager + +Because all peripheral management of Fiasco.OC is done in user-level +applications, there is the need to have a centralized management of +the resources belonging to the platform and to peripheral devices. + +This is the job of Io. Io provides portable abstractions for iterating and +accessing devices and their resources (IRQ's, IO Memory...), as well as +delegating access to those resources to other applications (e.g., device +drivers). + +For more details see \subpage io "Io, the Io Server". + + +\section l4re_mag_intro Mag, the GUI Multiplexer + +Our default multiplexer for the graphics hardware is Mag. Mag is a +Nitpicker (TODO: ref) derivate that allows secure multiplexing of the +graphics and input hardware among multiple applications and multiple complete +windowing environments. + +\todo Add some Nitpicker reference + + +\section l4re_fbdrv_intro fb-drv, the Low-Level Graphics Driver + +The fb-drv server provides low-level access and initialization of various +graphics hardware. It has support for running VESA BIOS calls on Intel x86 +platforms, as well as support for various ARM display controllers. +\em fb-drv, provides a single instance of the L4Re::Goos interface and can +serve as a back end for the Mag server, in particular, if there is no graphics +support in the boot loader. + + +\section l4re_rtc_intro Rtc, the Real-Time Clock Server + +Rtc is a simple multiplexer for real-time clock hardware on your platform. + + +*/ diff --git a/l4/mk/Kconfig b/l4/mk/Kconfig new file mode 100644 index 00000000..453f2143 --- /dev/null +++ b/l4/mk/Kconfig @@ -0,0 +1,454 @@ +mainmenu "L4Re Configuration" + +config KERNELVERSION + string + option env="KERNELVERSION" + +choice + prompt "Target Architecture" + default BUILD_ARCH_x86 + help + Specify for which processor architecture you want to build. + +config BUILD_ARCH_x86 + bool "X86-32 architecture" + +config BUILD_ARCH_amd64 + bool "AMD64 architecture" + +config BUILD_ARCH_arm + bool "ARM architecture" + +config BUILD_ARCH_ppc32 + bool "PowerPC 32 architecture (EXPERIMENTAL!)" + +config BUILD_ARCH_sparc + bool "Sparc architecture (EXPERIMENTAL)" + +endchoice + +config BUILD_ARCH + string + default "x86" if BUILD_ARCH_x86 + default "arm" if BUILD_ARCH_arm + default "amd64" if BUILD_ARCH_amd64 + default "ppc32" if BUILD_ARCH_ppc32 + default "sparc" if BUILD_ARCH_sparc + +# currently we have nothing for abi linux, so just do not offer this option +#choice +# prompt "ABI" +# default BUILD_ABI_l4f +# +#config BUILD_ABI_l4f +# bool "L4/Fiasco" +# +#config BUILD_ABI_linux +# bool "Linux" +# +#endchoice +config BUILD_ABI_l4f + def_bool y + + +config BUILD_ABI + string + default "l4f" if BUILD_ABI_l4f + default "linux" if BUILD_ABI_linux + +if BUILD_ARCH_x86 || BUILD_ARCH_amd64 + +choice + prompt "CPU variant" + +config CPU_X86_586 + bool "586 type CPU" + depends on BUILD_ARCH_x86 + +config CPU_X86_PENTIUM + bool "Pentium type CPU" + depends on BUILD_ARCH_x86 + +config CPU_X86_PENTIUMMMX + bool "Pentium with MMX type CPU" + depends on BUILD_ARCH_x86 + +config CPU_X86_PENTIUMPRO + bool "Pentium Pro type CPU" + depends on BUILD_ARCH_x86 + +config CPU_X86_686 + bool "686 type CPU" + depends on BUILD_ARCH_x86 + +config CPU_X86_PENTIUM2 + bool "Pentium2 type CPU" + depends on BUILD_ARCH_x86 + +config CPU_X86_PENTIUM3 + bool "Pentium3 type CPU" + depends on BUILD_ARCH_x86 + +config CPU_X86_PENTIUMM + bool "Pentium-M type CPU" + depends on BUILD_ARCH_x86 + +config CPU_X86_PENTIUM4 + bool "Pentium4 type CPU" + depends on BUILD_ARCH_x86 + +config CPU_X86_PRESCOTT + bool "Pentium4 Prescott type CPU" + depends on BUILD_ARCH_x86 + +config CPU_X86_NOCONA + bool "Pentium Nocona type CPU" + depends on BUILD_ARCH_x86 + +config CPU_X86_CORE2 + bool "Core2 type CPU" + depends on BUILD_ARCH_x86 + +config CPU_X86_K6 + bool "K6 type CPU" + depends on BUILD_ARCH_x86 + +config CPU_X86_K7 + bool "K7 type CPU" + depends on BUILD_ARCH_x86 + +config CPU_X86_ATHLON4 + bool "Athlon type CPU" + depends on BUILD_ARCH_x86 + +config CPU_X86_K8 + bool "K8 type CPU" + depends on BUILD_ARCH_x86 || BUILD_ARCH_amd64 + +config CPU_X86_K10 + bool "K10/Barcelona type CPU" + depends on BUILD_ARCH_x86 || BUILD_ARCH_amd64 + +config CPU_X86_OPTERON + bool "Opteron type CPU" + depends on BUILD_ARCH_x86 || BUILD_ARCH_amd64 + + + +endchoice + + +config CPU + string + default "586" if CPU_X86_586 + default "pentium" if CPU_X86_PENTIUM + default "pentiummmx" if CPU_X86_PENTIUMMMX + default "pentiumpro" if CPU_X86_PENTIUMPRO + default "686" if CPU_X86_686 + default "pentium2" if CPU_X86_PENTIUM2 + default "pentium3" if CPU_X86_PENTIUM3 + default "pentiumm" if CPU_X86_PENTIUMM + default "pentium4" if CPU_X86_PENTIUM4 + default "prescott" if CPU_X86_PRESCOTT + default "core2" if CPU_X86_CORE2 + default "nocona" if CPU_X86_NOCONA + default "K6" if CPU_X86_K6 + default "K7" if CPU_X86_K7 + default "athlon4" if CPU_X86_ATHLON4 + default "K8" if CPU_X86_K8 + default "amdfam10" if CPU_X86_K10 + default "opteron" if CPU_X86_OPTERON + +endif + + +if BUILD_ARCH_arm + +choice + prompt "CPU variant" + +config CPU_ARM_ARMV4 + bool "ARMv4 type CPU" + depends on BUILD_ARCH_arm + +config CPU_ARM_ARMV4T + bool "ARMv4T type CPU" + depends on BUILD_ARCH_arm + +config CPU_ARM_ARMV5 + bool "ARMv5 type CPU" + depends on BUILD_ARCH_arm + +config CPU_ARM_ARMV5T + bool "ARMv5T type CPU" + depends on BUILD_ARCH_arm + +config CPU_ARM_ARMV5TE + bool "ARMv5TE type CPU" + depends on BUILD_ARCH_arm + +config CPU_ARM_ARMV6 + bool "ARMv6 type CPU" + depends on BUILD_ARCH_arm + +config CPU_ARM_ARMV6T2 + bool "ARMv6t2 type CPU" + depends on BUILD_ARCH_arm + +config CPU_ARM_ARMV6ZK + bool "ARMv6zk type CPU" + depends on BUILD_ARCH_arm + +config CPU_ARM_ARMV7A + bool "ARMv7A type CPU" + depends on BUILD_ARCH_arm + +config CPU_ARM_ARMV7R + bool "ARMv7R type CPU" + depends on BUILD_ARCH_arm + +endchoice + +config CPU + string + default "armv4" if CPU_ARM_ARMV4 + default "armv4t" if CPU_ARM_ARMV4T + default "armv5" if CPU_ARM_ARMV5 + default "armv5t" if CPU_ARM_ARMV5T + default "armv5te" if CPU_ARM_ARMV5TE + default "armv6" if CPU_ARM_ARMV6 + default "armv6t2" if CPU_ARM_ARMV6T2 + default "armv6zk" if CPU_ARM_ARMV6ZK + default "armv7a" if CPU_ARM_ARMV7A + default "armv7r" if CPU_ARM_ARMV7R + +config CPU_ARMV6KPLUS + bool + default y if CPU_ARM_ARMV6ZK || CPU_ARM_ARMV7A || CPU_ARM_ARMV7R + +config CPU_ARMV6PLUS + bool + default y if CPU_ARM_ARMV6 || CPU_ARM_ARMV6T2 || CPU_ARMV6KPLUS + +endif + +if BUILD_ARCH_sparc + +choice + prompt "CPU" + + config CPU_SPARC_V7 + bool "Generic Sparc V7" + depends on BUILD_ARCH_sparc + + config CPU_SPARC_LEON + bool "LEON" + depends on BUILD_ARCH_sparc + + config CPU_SPARC_LEON3 + bool "LEON3" + depends on BUILD_ARCH_sparc + + config CPU_SPARC_V8 + bool "Generic Sparc V8" + depends on BUILD_ARCH_sparc + + config CPU_SPARC_V9 + bool "Generic Sparc V9" + depends on BUILD_ARCH_sparc + + config CPU_SPARC_ULTRASPARC + bool "Ultrasparc" + depends on BUILD_ARCH_sparc + + config CPU_SPARC_ULTRASPARC3 + bool "Ultrasparc3" + depends on BUILD_ARCH_sparc + + config CPU_SPARC_NIAGARA + bool "Niagara" + depends on BUILD_ARCH_sparc + + config CPU_SPARC_NIAGARA2 + bool "Niagara2" + depends on BUILD_ARCH_sparc + + config CPU_SPARC_NIAGARA3 + bool "Niagara3" + depends on BUILD_ARCH_sparc + + config CPU_SPARC_NIAGARA4 + bool "Niagara4" + depends on BUILD_ARCH_sparc +endchoice + +config CPU + string + default "leon" if CPU_SPARC_LEON + default "leon3" if CPU_SPARC_LEON3 + default "v7" if CPU_SPARC_V7 + default "v8" if CPU_SPARC_V8 + default "v9" if CPU_SPARC_V9 + default "ultrasparc" if CPU_SPARC_ULTRASPARC + default "ultrasparc3" if CPU_SPARC_ULTRASPARC3 + default "niagara" if CPU_SPARC_NIAGARA + default "niagara2" if CPU_SPARC_NIAGARA2 + default "niagara3" if CPU_SPARC_NIAGARA3 + default "niagara4" if CPU_SPARC_NIAGARA4 +endif + +choice + prompt "Platform Selection" + +INSERT_PLATFORMS + +config PLATFORM_TYPE_custom + bool "Custom platform" + help + Define your own platform, alternatively define the following + in conf/Platform/yourname.conf: + PLATFORM_RAM_BASE = 0 + PLATFORM_RAM_SIZE_MB = 64 + + +endchoice + +if PLATFORM_TYPE_custom + +menu "Custom Platform Definition" + +config PLATFORM_TYPE + string "Name of your platform" + depends on PLATFORM_TYPE_custom + +config PLATFORM_RAM_BASE + hex "Start of RAM" + default 0x0 + depends on PLATFORM_TYPE_custom + help + Hexadecimal physical address where RAM memory starts on the + platform. + +config PLATFORM_RAM_SIZE_MB + int "RAM-Memory available on the platform in MB" + default 128 + depends on PLATFORM_TYPE_custom + +endmenu # Custom platform +endif + +INSERT_PLATFORM_TYPES + +config USE_DROPS_STDDIR + def_bool n + +config USE_DICE + def_bool n + +config DROPS_STDDIR + string + default "/path/to/l4re" + +config DROPS_INSTDIR + string + default "/path/to/l4re" + +config BID_COLORED_PHASES + bool + default y + +menu "Building" + +config YACC + string + default "yacc" + +config LEX + string + default "flex" + +config CTAGS + string + default "ctags" + +config ETAGS + string + default "etags" + + +config HAVE_LDSO + def_bool y + +config INT_CPP_NAME_SWITCH + bool "Automatically determine internal gcc preprocessor names" + default y + +config INT_LD_NAME_SWITCH + bool "Automatically determine internal ld names" + default y + +config INT_PP_NAME + string "Internal name of the compiler preprocessor" + default "cpp0" + depends on !INT_CPP_NAME_SWITCH + +config INT_LD_NAME + string "Internal name of the compiler linker" + default "ld" + depends on !INT_LD_NAME_SWITCH + + +config BID_STRIP_PROGS + bool "Strip binaries on install" + default n + help + If enabled, binaries will be stripped on installation into + $(L4DIR)/bin or $(DROPS_STDDIR)/bin. If you want to load them with + all their symbols (eg to show the symbols with the Fiasco kernel + debugger), say 'N' here. + + If unsure, say 'Y'. + +config BID_GCC_OMIT_FP + bool "GCC: Omit Frame-pointers" + default n + help + If enabled, gcc will be passed the '-fomit-frame-pointer' cmdline + option, adding an additional register to the register set for the + generated code. Programs will be faster, but backtraces cannot be + done, seriously hindering debugging. + + If unsure, say 'N'. + + +config BID_GENERATE_MAPFILE + bool #"Generate Map-files for binaries" + default n + help + Enabling this option will generate map-files together with the + binaries. This might be handy for debugging purposes. See ld(1) + for details on mapfiles. + + If unsure, say N. + +config BID_BUILD_DOC + bool "Build doc directories" + default n + help + Say Y if you also want to build the doc directories. + +config RELEASE_MODE + bool "Enable RELEASE flag" + help + Enable to leave out debugging and other code normally not needed. + + Say N. + +config MAKECONFS_ADD + string "Additional Makeconf files" + help + List of white space separated suffixes of Makeconf files + which will be included in every source directory as + Makeconf.. + +endmenu diff --git a/l4/mk/Makeconf b/l4/mk/Makeconf new file mode 100644 index 00000000..aa1b2d91 --- /dev/null +++ b/l4/mk/Makeconf @@ -0,0 +1,662 @@ +# -*- Makefile -*- +# vim:set ft=make: +# +# Make configuration file +# +# This file is included by all Makefile-templates. This file defines macros +# for div commands, sets general DROPS-Makefile variables, ensures the +# dependencies from the various Makeconf.locals, defines the messages for +# div actions, and permits the dependency-creation on clean-rules. +# +# The macros BUILD_MULTIPLE_ARCHITECTURES and BUILD_ONE_ARCHITECTURE are +# defined here. +# +# BUILD_MULTIPLE_ARCHITECTURES is set if ARCHS is set to multiple +# architectures in the Makefile. If ARCHS is not set, the default value +# l4_i386 will be assumed, not defining BUILD_MULTIPLE_ARCHITECTURES. +# In the muli-arch case, binary.inc triggers build the files into subdirs, +# dir-name is the architecture. Then, make is called recursively with ARCH +# set to one architecture. +# +# BUILD_ONE_ARCHITECTURE is set if ARCH contains one architecture, and we +# actually build files (in subdirs for multi-arch case, in the same dir in +# the single-arch case). + +ifeq ($(origin _L4DIR_MK_MAKECONF),undefined) +_L4DIR_MK_MAKECONF=y + +MAKEFLAGS += -R + +# the default target is all +all:: + +# make .general.d dependent on the role-file +$(if $(ROLE),$(OBJ_DIR)/.general.d: $(L4DIR)/mk/$(ROLE)) + +SYSTEM_TARGET_arm = arm-linux- +SYSTEM_TARGET_ppc32 = powerpc-linux- +SYSTEM_TARGET_sparc = $(if $(GCCIS_sparc_leon),sparc-elf-,sparc-linux-) +SYSTEM_TARGET = $(SYSTEM_TARGET_$(ARCH)) + +CARCHFLAGS_amd64 = -mno-red-zone +ASFLAGS_amd64 = -m64 +LDFLAGS_amd64 += -m elf_x86_64 -z max-page-size=0x1000 -z common-page-size=0x1000 + +LD_EMULATION_CHOICE_amd64 = elf_x86_64 +LD_EMULATION_CHOICE_arm = armelf armelf_linux_eabi +LD_EMULATION_CHOICE_ppc32 = elf32ppc +LD_EMULATION_CHOICE_x86 = elf_i386 +LD_EMULATION_CHOICE_sparc = $(if $(GCCIS_sparc_leon),sparcleon,elf32_sparc) + +OFORMAT_amd64 = elf64-x86-64 +OFORMAT_arm = elf32-littlearm +OFORMAT_ppc32 = elf32-powerpc +OFORMAT_x86 = elf32-i386 +OFORMAT_sparc = elf32-sparc +OFORMAT = $(OFORMAT_$(ARCH)) + +BFD_ARCH_amd64 = i386 +BFD_ARCH_arm = arm +BFD_ARCH_ppc32 = powerpc +BFD_ARCH_x86 = i386 +BFD_ARCH_sparc = sparc +BFD_ARCH = $(BFD_ARCH_$(ARCH)) + +L4_KIP_ADDR_amd64 ?= 0x6ffff000 +L4_KIP_ADDR_arm ?= 0xaffff000 +L4_KIP_ADDR_ppc32 ?= 0xaffff000 +L4_KIP_ADDR_x86 ?= 0xaffff000 +L4_KIP_ADDR_sparc ?= 0xaffff000 +L4_KIP_ADDR ?= $(L4_KIP_ADDR_$(ARCH)) + +L4_KIP_OFFS_SYS_INVOKE = 0x800 +L4_KIP_OFFS_SYS_DEBUGGER = 0x900 + +L4_STACK_ADDR_amd64 ?= 0x70000000 +L4_STACK_ADDR_arm ?= 0xb0000000 +L4_STACK_ADDR_ppc32 ?= 0xb0000000 +L4_STACK_ADDR_x86 ?= 0xb0000000 +L4_STACK_ADDR_sparc ?= 0xb0000000 +L4_STACK_ADDR ?= $(L4_STACK_ADDR_$(ARCH)) +L4_STACK_SIZE ?= $(if $(L4_STACK_SIZE_MAIN_THREAD),$(L4_STACK_SIZE_MAIN_THREAD),0x8000) + +# This is quite bad: There is no other chance to disable the page-alignedment +# of the linker. The linker aligns the first section at 0x100000 for AMD64! +# We don't want this. Be careful for interactions with objcopy -S! +#LDNMAGIC ?= -n +#LDFLAGS_amd64 += $(LDNMAGIC) + +VERBOSE = $(if $(CONFIG_VERBOSE),,@) +DEPEND_VERBOSE = $(if $(CONFIG_DEPEND_VERBOSE),,@) +DROPS_STDDIR = $(patsubst "%",%,$(CONFIG_DROPS_STDDIR)) +DROPS_INSTDIR = $(patsubst "%",%,$(CONFIG_DROPS_INSTDIR)) +RAM_SIZE_MB = $(CONFIG_RAM_SIZE_MB) +PLATFORM_TYPE = $(patsubst "%",%,$(CONFIG_PLATFORM_TYPE)) +CPU = $(patsubst "%",%,$(CONFIG_CPU)) +BUILD_ABI = $(patsubst "%",%,$(CONFIG_BUILD_ABI)) +BUILD_ARCH = $(patsubst "%",%,$(CONFIG_BUILD_ARCH)) +MAKECONFS_ADD = $(patsubst "%,%,$(patsubst %",%,$(CONFIG_MAKECONFS_ADD))) #" + +CARCHFLAGS_x86_586 = -march=i586 +CARCHFLAGS_x86_pentium = -march=i586 +CARCHFLAGS_x86_pentiummmx = -march=pentium-mmx +CARCHFLAGS_x86_pentiumpro = -march=pentiumpro +CARCHFLAGS_x86_686 = -march=i686 +CARCHFLAGS_x86_pentium2 = -march=pentium2 +CARCHFLAGS_x86_pentium3 = -march=pentium3 +CARCHFLAGS_x86_pentiumm = -march=pentium-m +CARCHFLAGS_x86_pentium4 = -march=pentium4 +CARCHFLAGS_x86_prescott = -march=prescott +CARCHFLAGS_x86_nocona = -march=nocona +CARCHFLAGS_x86_core2 = -march=core2 +CARCHFLAGS_x86_K6 = -march=k6 +CARCHFLAGS_x86_K7 = -march=athlon +CARCHFLAGS_x86_athlon4 = -march=athlon-4 +CARCHFLAGS_x86_K8 = -march=k8 +CARCHFLAGS_x86_opteron = -march=opteron + +CARCHFLAGS_amd64_K8 = -march=k8 +CARCHFLAGS_amd64_K10 = -march=k10 +CARCHFLAGS_amd64_opteron = -march=opteron + +CARCHFLAGS_arm_armv4 = -march=armv4 +CARCHFLAGS_arm_armv4t = -march=armv4t +CARCHFLAGS_arm_armv5 = -march=armv5 +CARCHFLAGS_arm_armv5t = -march=armv5t +CARCHFLAGS_arm_armv5te = -march=armv5te +CARCHFLAGS_arm_armv6 = -march=armv6 +CARCHFLAGS_arm_armv6t2 = -march=armv6t2 +CARCHFLAGS_arm_armv6zk = -march=armv6zk +CARCHFLAGS_arm_armv7a = -march=armv7-a +CARCHFLAGS_arm_armv7r = -march=armv7-r + +CARCHFLAGS_sparc_v7 = -mcpu=v7 +# the -Wa.. is probably a gcc buglet fix only, check again later +CARCHFLAGS_sparc_leon = -mcpu=leon -Wa,-Av8 +CARCHFLAGS_sparc_leon3 = -mcpu=leon3 +CARCHFLAGS_sparc_v8 = -mcpu=v8 +CARCHFLAGS_sparc_v9 = -mcpu=v9 +CARCHFLAGS_sparc_ultrasparc = -mcpu=ultrasparc +CARCHFLAGS_sparc_ultrasparc3 = -mcpu=ultrasparc3 +CARCHFLAGS_sparc_niagara = -mcpu=niagara +CARCHFLAGS_sparc_niagara2 = -mcpu=niagara2 +CARCHFLAGS_sparc_niagara3 = -mcpu=niagara3 +CARCHFLAGS_sparc_niagara4 = -mcpu=niagara4 + +IDL_SYSTEMS = x86-l4f + +CCXX_FLAGS_arm += -marm +CCXX_FLAGS_amd64 += -m64 +CCXX_FLAGS_ppc32 += -m32 +CCXX_FLAGS_sparc += -m32 +CCXX_FLAGS_x86 += -m32 +CCXX_FLAGS = $(CCXX_FLAGS_$(BUILD_ARCH)) + +CC_x86 = $(SYSTEM_TARGET)gcc +CC_amd64 = $(SYSTEM_TARGET)gcc +CC_arm = $(SYSTEM_TARGET)gcc +CC_ppc32 = $(SYSTEM_TARGET)gcc +CC_sparc = $(SYSTEM_TARGET)gcc +CXX_x86 = $(SYSTEM_TARGET)g++ +CXX_amd64 = $(SYSTEM_TARGET)g++ +CXX_arm = $(SYSTEM_TARGET)g++ +CXX_ppc32 = $(SYSTEM_TARGET)g++ +CXX_sparc = $(SYSTEM_TARGET)g++ + +SYSTEMS_ABI := x86-l4f amd64-l4f arm-l4f ppc32-l4f sparc-l4f +SYSTEMS_PLAIN := x86 amd64 arm ppc32 sparc + +AR = $(SYSTEM_TARGET)ar +AS = $(SYSTEM_TARGET)as +AWKP = gawk --posix +CC = $(if $(USE_CCACHE),ccache )$(CC_$(BUILD_ARCH)) +CXX = $(if $(USE_CCACHE),ccache )$(CXX_$(BUILD_ARCH)) +CP = cp +DICE_SRCDIR ?= $(L4DIR)/../dice +DICE_OBJDIR ?= $(DICE_SRCDIR) +DICE = $(firstword $(wildcard $(DICE_OBJDIR)/src/dice \ + $(DROPS_STDDIR)/tool/bin/dice \ + $(shell which dice 2>/dev/null) ) \ + did_not_find_dice___please_install_dice ) +DICE_CPP_NAME = cpp0 + +DICE_INCDIR ?= $(DICE_SRCDIR)/include + +DOXYGEN ?= doxygen +ECHO = echo +ELF_PATCHER = $(OBJ_BASE)/tool/elf-patcher/elf-patcher + +GENOFFSETS = $(L4DIR)/tool/bin/genoffsets.pl +GOSH = $(firstword $(wildcard $(L4DIR)/../tools/gosh/gosh \ + $(DROPS_STDDIR)/tool/bin/gosh \ + $(shell which gosh 2>/dev/null) ) \ + did_not_find_gosh___please_install_gosh ) +HOST_CC = gcc +HOST_CXX = g++ +HOST_LD = ld +INSTALL = install +LD = $(SYSTEM_TARGET)ld -m $(LD_EMULATION) +LATEX = latex +PDFLATEX = pdflatex +GREP = GREP_OPTIONS= grep +LN = ln +MKDIR = mkdir -p +MKFLAGS +=$(MKFLAGS_$@) +NM = $(SYSTEM_TARGET)nm +OBJCOPY = $(SYSTEM_TARGET)objcopy +PKG_CONFIG = pkg-config +PWDCMD = pwd -P +RANLIB = $(SYSTEM_TARGET)ranlib +RM = rm -f +SCRUB = $(RM) $(wildcard *.old) $(wildcard *~) $(wildcard *.bak) \ + $(wildcard \#*\#) +SED = sed +SHELL = bash +SIZE = $(SYSTEM_TARGET)size +STRIP = $(SYSTEM_TARGET)strip +SVN = svn +TR = tr +GEN_DOPECODE = $(L4DIR)/tool/gen_dopecode/gen_dopecode +ABS2REL = $(L4DIR)/tool/bin/abs2rel.sh +# it is optional to be able to set it as environment variable +FIASCOUX ?= $(L4DIR)/../kernel/fiasco/build-ux/fiasco +PAGER ?= less +DISASM_CMD ?= $(SYSTEM_TARGET)objdump -lCSd $(1) | $(PAGER) +IMAGES_DIR ?= $(OBJ_BASE)/images + +# functions that are handy +absfilename_target_dir_needs_to_exist = $(foreach w,$(1),$(addsuffix /$(notdir $(w)),$(shell cd $(dir $(w)) 2>/dev/null&&$(PWDCMD)))) +absfilename = $(shell PWD=$$($(PWDCMD)) $(L4DIR)/mk/rel2abs.sh $(1)) +findfile = $(firstword $(wildcard $(addsuffix /$(1),$(2))) $(1)_NOT_FOUND) +is_dir = $(shell test -d '$(1)' && echo yes) + +ifneq ($(PT),) + PLATFORM_TYPE := $(PT) +endif + +# include this one early to be able to set OBJ_BASE +-include $(L4DIR)/Makeconf.local + +ifeq ($(filter $(IGNORE_OBJDIR_TARGETS),$(MAKECMDGOALS)),) +# output directory + ifeq ($(O)$(OBJ_BASE),) + $(error need to give builddir with O=.../builddir) + else + ifneq ($(O),) + ifeq ($(filter-out undefined environment,$(origin OBJ_BASE)),) + OBJ_BASE := $(call absfilename, $(O)) + export OBJ_BASE + # prevent passing O to sub-makes, because it may be a relative path + # not valid there + override O = + MAKEOVERRIDES := $(filter-out O=%,$(MAKEOVERRIDES)) + endif + endif + endif +endif + +ifeq ($(origin L4DIR_ABS),undefined) +L4DIR_ABS := $(call absfilename,$(L4DIR)) +endif +ifeq ($(origin PKGDIR_ABS),undefined) +PKGDIR_ABS := $(call absfilename,$(PKGDIR)) +endif +ifeq ($(origin SRC_DIR),undefined) +SRC_DIR := $(shell $(PWDCMD)) +endif +ifeq ($(origin SRC_BASE_ABS),undefined) +SRC_BASE ?= $(L4DIR) +SRC_BASE_ABS := $(call absfilename,$(SRC_BASE)) +export SRC_BASE_ABS +endif +ifeq ($(origin OBJ_DIR),undefined) +OBJ_DIR := $(subst $(SRC_BASE_ABS),$(OBJ_BASE),$(SRC_DIR)) +endif +ifeq ($(origin PKGDIR_OBJ),undefined) +PKGDIR_OBJ := $(call absfilename,$(OBJ_DIR)/$(PKGDIR)) +endif + +# if PKGDIR is not in L4DIR, we have an external package, so make up some +# build-dir for it +ifneq ($(patsubst $(L4DIR_ABS)/%,,$(PKGDIR_ABS)),) +ifneq ($(filter-out $(OBJ_BASE)/ext-pkg%,$(PKGDIR_OBJ)),) +PKGDIR_OBJ := $(OBJ_BASE)/ext-pkg$(PKGDIR_OBJ) +OBJ_DIR := $(OBJ_BASE)/ext-pkg$(OBJ_DIR) +endif +endif + +# sanity check the object dir +ifneq ($(SRC_BASE_ABS),$(OBJ_BASE)) +ifeq ($(SRC_DIR),$(OBJ_DIR)) +$(warning Sorry, your object or source path became garbled.) +$(warning OBJ_BASE: $(OBJ_BASE)) +$(warning SRC_BASE_ABS: $(SRC_BASE_ABS)) +$(warning SRC_DIR: $(SRC_DIR)) +$(warning OBJ_DIR: $(OBJ_DIR)) +$(warning PKGDIR: $(PKGDIR)) +$(warning L4DIR_ABS: $(L4DIR_ABS)) +$(warning PKGDIR_ABS: $(PKGDIR_ABS)) +$(warning PKGDIR_OBJ: $(PKGDIR_OBJ)) +$(error Please investigate.) +endif +endif + + +OBJ_DIR_EXPORT = $(OBJ_DIR) +export OBJ_DIR_EXPORT + +VPATH_SRC_BASE ?= $(SRC_DIR) + +# Makeconf.local handling +# dont use -include here, as we have special build conditions in $(L4DIR)/ +ifeq ($(origin BID_ROOT_CONF),undefined) +BID_ROOT_CONF := $(call absfilename, $(OBJ_BASE))/.config.all +endif +ifeq ($(filter $(IGNORE_OBJDIR_TARGETS),$(MAKECMDGOALS)),) +ifeq ($(wildcard $(BID_ROOT_CONF)),) +ifeq ($(BID_IGN_ROOT_CONF),) +$(error No configuration file found in build directory "$(OBJ_BASE)". Please run "make O=/path/to/objdir config" in "$(L4DIR_ABS)" or specify a valid build directory) +endif +else +include $(BID_ROOT_CONF) +endif +endif + +# if we're working on a program that wants the RAM_BASE be considered in its +# linking address, source a possible privately configured one +ifneq ($(RELOC_PHYS),) +INCLUDE_BOOT_CONFIG := required +endif + +ifneq ($(INCLUDE_BOOT_CONFIG),) + PLATFORM_CONF_FILE := $(wildcard $(L4DIR)/conf/platforms/$(PLATFORM_TYPE).conf $(L4DIR)/mk/platforms/$(PLATFORM_TYPE).conf) + ifneq ($(PLATFORM_TYPE),$(patsubst "%",%,$(CONFIG_PLATFORM_TYPE))) + include $(PLATFORM_CONF_FILE) + else + ifneq ($(CONFIG_PLATFORM_TYPE_custom),) + PLATFORM_RAM_BASE=$(CONFIG_PLATFORM_RAM_BASE) + PLATFORM_RAM_SIZE_MB=$(CONFIG_PLATFORM_RAM_SIZE_MB) + else + ifeq ($(INCLUDE_BOOT_CONFIG),optional) + -include $(PLATFORM_CONF_FILE) + else + include $(PLATFORM_CONF_FILE) + endif + endif + endif + -include $(L4DIR)/conf/Makeconf.boot + -include $(OBJ_BASE)/conf/Makeconf.boot + -include $(OBJ_BASE)/Makeconf.ram_base + BID_RAM_BASE_DEP := $(if $(wildcard $(OBJ_BASE)/Makeconf.ram_base),$(OBJ_BASE)/Makeconf.ram_base) + ifeq ($(RAM_BASE),) + RAM_BASE := 0 + endif + RAM_SIZE_MB := $(if $(RAM_SIZE_MB),$(RAM_SIZE_MB),$(PLATFORM_RAM_SIZE_MB)) +endif + +INCLUDE_MAKE_RULES += $(foreach m,$(MAKECONFS_ADD),$(SRC_DIR)/Makeconf.$(m)) + +INCLUDE_MAKE_RULES_EXPANDED := $(foreach m,$(INCLUDE_MAKE_RULES),$(wildcard $(m))) +ifneq ($(strip $(INCLUDE_MAKE_RULES_EXPANDED)),) +-include $(INCLUDE_MAKE_RULES_EXPANDED) +endif + +-include $(OBJ_BASE)/Makeconf.local +ifneq ($(PKGDIR_ABS),) +-include $(PKGDIR_ABS)/Makeconf.local +endif +# if it is not already set, we use this in the local dir +MAKECONFLOCAL ?= Makeconf.local +-include $(MAKECONFLOCAL) + +DROPS_STDDIR ?= /home/drops + +# a nasty workaround for make-3.79/make-3.80. The former needs an additional +# $$ for $-quotation when calling a function. +BID_IDENT = $(1) +ifeq ($(call BID_IDENT,$$),) +BID_DOLLARQUOTE = $$ +endif +BID_COMMA = , + +ifneq ($(PL),) +PL_j := -j $(PL) +export PL +endif + +include $(L4DIR)/mk/config.inc + +ifneq ($(CONFIG_HAVE_LDSO),) +# MAKEDEP-call: +# arg1 - compiler binary name +# arg2 - [opt] compiler target. Will be written as target within the +# dependency file +# arg3 - [opt] name of the dependency file. If unset, ..d will be used. +# arg4 - [opt] alternative binary name +ifeq ($(origin BID_LIBGENDEP_PATHS), undefined) + ifeq ($(HOST_SYSTEM),linux) + BID_LIBGENDEP_PATHS := \ + $(firstword $(wildcard $(call absfilename, $(OBJ_BASE)/tool/gendep/64 \ + $(DROPS_STDDIR)/tool/lib/64))):$(firstword $(wildcard $(call absfilename, \ + $(OBJ_BASE)/tool/gendep/32 $(DROPS_STDDIR)/tool/lib/32 ))) + endif + + ifeq ($(HOST_SYSTEM),darwin) + BID_LIBGENDEP_PATHS := \ + $(firstword $(wildcard $(call absfilename, $(OBJ_BASE)/tool/gendep \ + $(DROPS_STDDIR)/tool/lib))) + endif +endif + +ifeq ($(HOST_SYSTEM),linux) + LD_GENDEP_PREFIX = LD_PRELOAD=libgendep.so LD_LIBRARY_PATH=$(if $(LD_LIBRARY_PATH),$(LD_LIBRARY_PATH):)$(BID_LIBGENDEP_PATHS) +endif +ifeq ($(HOST_SYSTEM),darwin) + LD_GENDEP_PREFIX = DYLD_FORCE_FLAT_NAMESPACE=1 DYLD_INSERT_LIBRARIES=$(BID_LIBGENDEP_PATHS)/libgendep.so +endif +MAKEDEP=$(LD_GENDEP_PREFIX) \ + GENDEP_TARGET=$(if $(2),$(2),$@) \ + GENDEP_BINARY=$(firstword $(1)) $(if $(3),GENDEP_DEPFILE=$(3)) \ + $(if $(4),GENDEP_BINARY_ALT1=$(4)) +endif + +# macros used here and in packages +checkcc = $(shell if $(CC) $(CCXX_FLAGS) $(1) -o /dev/null -c -x c \ + /dev/null > /dev/null 2>&1; then echo "$(1)"; fi) +checkcxx = $(shell if $(CXX) $(CCXX_FLAGS) $(1) -o /dev/null -c -x c++ \ + /dev/null > /dev/null 2>&1; then echo "$(1)"; fi) + +callcc = LC_ALL=C $(CC) $(CCXX_FLAGS) +callcxx = LC_ALL=C $(CXX) $(CCXX_FLAGS) + +# the gcc specific variables: version, base dir, include dir, gcc lib, ... +# note: determining these variables is slow, and the values should +# be set in .config.all. However, this is the place were +# they are determined on a 'make config' in $(L4DIR) +GCCVERSION_f = $(shell $(callcc) -dumpversion | sed -e 's/\(.*\)\..*/\1/') +GCCMAJORVERSION_f=$(shell $(callcc) -dumpversion | sed -e 's/\([^.]*\).*/\1/') +GCCMINORVERSION_f=$(shell $(callcc) -dumpversion | sed -e 's/[^.]*\.\([^.]*\).*/\1/') +GCCSUBVERSION_f = $(shell $(callcc) -dumpversion | sed -e 's/.*\.\(.*\)/\1/') +LDVERSION_f = $(shell $(firstword $(LD)) -v | sed -e 's/.* \([0-9]\)\.\([^. ]*\).*/\1\2/') +GCCSYSLIBDIRS_f = $(shell $(callcc) -print-search-dirs | sed '/^libraries:/{s/^libraries: /-L/;s/:/ -L/g;q;};d') +GCCDIR_f = $(shell $(callcc) -print-search-dirs | sed -ne 's+^install: \(.*[^/][^/]*\)/+\1+p' ) +GCCLIB_file_f = $(shell $(callcc) -print-file-name=$(1)) +GCCLIB_HOST_f = $(shell $(callcc) -print-libgcc-file-name) +GCCLIB_S_SO_f = $(filter /%,$(shell $(callcc) -print-file-name=libgcc_s.so)) +GCCLIB_EH_f = $(filter /%,$(shell $(callcc) -print-file-name=libgcc_eh.a)) +GCCINCDIR_f = $(addprefix $(call GCCDIR_f),/include /include-fixed) +GCCNOSTACKPROTOPT_f= $(call checkcc,-fno-stack-protector) +GCCNOFPU_x86_f = $(call checkcc,-mno-mmx) $(call checkcc,-mno-3dnow) \ + $(call checkcc,-mno-sse) $(call checkcc,-mno-sse2) \ + $(call checkcc,-mno-sse3) $(call checkcc,-mno-sse4) \ + $(call checkcc,-mno-sse4a) +GCC_HAS_ATOMICS_f = $(shell if echo '\#include ' | \ + $(callcxx) -dD -E -x c++ - | \ + grep -q _GLIBCXX_ATOMIC_BUILTINS; then \ + echo y; fi) +GCCIS_sparc_leon_f= $(shell if $(CC) -dD -E -x c /dev/null 2>&1 | grep -qw __leonbare__; then echo y; fi) + +GCCINCDIR = $(GCCDIR)/include $(GCCDIR)/include-fixed +I_GCCINCDIR = $(addprefix -isystem ,$(GCCINCDIR)) + +GCCLIB = $(OBJ_BASE)/lib/$(subst -,/,$(SYSTEM))/libgcc.a +GCCLIB_SO = $(OBJ_BASE)/lib/$(subst -,/,$(SYSTEM))/libgcc.$(if $(filter %l4f,$(SYSTEM)),so,a) + +ifneq ($(PKGDIR),) + ifeq ($(origin PKGNAME),undefined) + PKGNAME := $(notdir $(shell cd $(PKGDIR);pwd)) + endif +endif + +ifeq ($(V),1) + VERBOSE = +endif +ifeq ($(V),0) + VERBOSE = @ +endif + +ifeq ($(D),1) + DEBUG_MODE = y +endif + +ifeq ($(CONFIG_RELEASE_MODE),y) +DEFINES += -DL4BID_RELEASE_MODE +endif + +ifneq ($(filter linux host,$(MODE)),) +HOST_LINK := 1 +HOST_LINK_HOST := 1 +endif + +ifneq ($(filter l4linux,$(MODE)),) +HOST_LINK := 1 +HOST_LINK_TARGET := 1 +endif + +# +# SUBDIR handling, not within the OBJ-*/ dirs +# +ifeq ($(SYSTEM),) +ifneq ($(SUBDIRS),) +.PHONY: $(SUBDIRS) +$(SUBDIRS): + $(VERBOSE)PWD=$(PWD)/$@ $(MAKE) -C $@ all + +# we know that SUBDIRS isn't empty, hence we can avoid the dir-test +scrub clean cleanall:: + $(VERBOSE)set -e; $(foreach i,$(SUBDIRS), \ + PWD=$(PWD)/$(i) $(MAKE) -C $(i) $@ $(MKFLAGS) $(MKFLAGS_$(i));) + +install:: $(SUBDIRS) + $(VERBOSE)set -e; $(foreach i,$(SUBDIRS), \ + PWD=$(PWD)/$(i) $(MAKE) -C $(i) $@ $(MKFLAGS) $(MKFLAGS_$(i));) + +endif + +all:: $(OBJ_DIR)/Makefile + +$(OBJ_DIR)/Makefile: $(L4DIR)/mk/Makeconf + $(VERBOSE)install -d $(dir $@) + $(VERBOSE)echo '# automatically created -- modifications will be lost' > $@ + $(VERBOSE)echo 'SRC := $(SRC_DIR)' >> $@ + $(VERBOSE)echo 'OBJ := $(OBJ_BASE)' >> $@ + $(VERBOSE)echo '.PHONY: x $$(MAKECMDGOALS)' >> $@ + $(VERBOSE)echo 'x:' >> $@ + $(VERBOSE)echo ' @PWD=$$(SRC) $$(MAKE) -C $$(SRC) O=$$(OBJ)' >> $@ + $(VERBOSE)echo '$$(MAKECMDGOALS):' >> $@ + $(VERBOSE)echo ' @PWD=$$(SRC) $$(MAKE) -C $$(SRC) O=$$(OBJ) $$@'>> $@ + +else +# we are within an OBJ-*/ dir, create dummy target +$(SUBDIRS): +endif + +# +# Dependency section +# +# + +# the general dependencies: All generated files depend on ".general.d". +# ".general.d" itself depends on the mk-Makeconf, the optional +# Makeconf.local, the .config.all, the packet-Makeconf.local and the +# Makeconf.local. This ensures a rebuilt if any of the configuration- +# or make-files changes. +# +# We have this nasty if-readable-magic to allow the files to disappear +# or to appear. Depending on if the according makeconf exists now, the +# if-readable magic .general.d is used on existance or non-existence. + +BID_DEPEND_GENERAL_D_COND = \ + if [ -r $(1) ] ; then echo -e '$@: $(1)\n$(1):\n' >>$@ ; \ + else echo '$$(if $$(wildcard $(1)), $@: FORCE)' >>$@; fi + +ifeq ($(SYSTEM),) +GENERAL_D_LOC := $(OBJ_DIR)/.general.d +else +GENERAL_D_LOC := .general.d +endif + +$(GENERAL_D_LOC): $(L4DIR)/mk/Makeconf $(EXTRA_GENERAL_D_DEP) + @$(BUILD_MESSAGE) + @install -d $(dir $@) + $(DEPEND_VERBOSE)echo '$@: $(SRC_DIR)/Makefile ' > $@ + $(DEPEND_VERBOSE)$(call BID_DEPEND_GENERAL_D_COND,\ + $(OBJ_BASE)/.config.all) + $(DEPEND_VERBOSE)$(call BID_DEPEND_GENERAL_D_COND,\ + $(OBJ_BASE)/Makeconf.local) + $(DEPEND_VERBOSE)$(call BID_DEPEND_GENERAL_D_COND,\ + $(L4DIR)/Makeconf.local) + $(DEPEND_VERBOSE)$(foreach m,$(wildcard $(INCLUDE_MAKE_RULES)),\ + $(call BID_DEPEND_GENERAL_D_COND,$(m)); ) + $(if $(PKGDIR_ABS),$(DEPEND_VERBOSE)$(call BID_DEPEND_GENERAL_D_COND,\ + $(PKGDIR_ABS)/Makeconf.local)) + $(DEPEND_VERBOSE)$(call BID_DEPEND_GENERAL_D_COND,\ + $(MAKECONFLOCAL)) + +DEPS += $(GENERAL_D_LOC) + + +# +# Messages +# + +# coloring on color-capable terminals +# enabled by setting CONFIG_BID_COLORED_PHASES to y +ifeq ($(CONFIG_BID_COLORED_PHASES),y) +ifeq ($(COLOR_TERMINAL),y) + EMPHSTART = '\033[34;1m' + EMPHSTOP = '\033[0m' +else + EMPHSTART = + EMPHSTOP = +endif +endif + +AR_MESSAGE ?= echo -e " ==> Archiving into $@" +BUILD_MESSAGE ?= echo -e " ... Building $@" +BUILT_MESSAGE ?= echo -e $(EMPHSTART)' ==> "$@" built'$(EMPHSTOP) +COMP_MESSAGE ?= echo -e " ... Compiling $@" +COMP_P_MESSAGE ?= echo -e " ... Compiling PIC $@" +COMP_PR_MESSAGE ?= echo -e " ... Compiling PROFILE $@" +GEN_MESSAGE ?= echo -e " ... Generating $@" +LINK_MESSAGE ?= echo -e " ==> Linking $@" +LINK_SHARED_MESSAGE ?= echo -e " ==> Linking to shared $@" +LINK_PARTIAL_MESSAGE ?= echo -e " ==> Partial linking to $@" +DEP_MESSAGE ?= echo -e " ... Building dependencies for $<" +CLEAN_MESSAGE ?= echo -e " ... Removing created files" +CLEANALL_MESSAGE ?= echo -e " ... Removing all created files" +INSTALL_LINK_MESSAGE ?= echo -e " ==> Updating symlinks" +INSTALL_DOC_MESSAGE ?= echo -e " ==> Installing $(<) documentation" +INSTALL_DOC_LOCAL_MESSAGE ?= echo -e " ==> Installing $(<) documentation locally" +INSTALL_MESSAGE ?= echo -e " ==> Installing $^" +INSTALL_LOCAL_MESSAGE ?= echo -e " ==> Installing $(<) to local build-tree" +UPDATE_HTML_MESSAGE ?= echo -e " ! You should remake your doc directory in $(1)" + +# allows an include $(DEPSVAR) at the end of the makefile +# but prevents rebuilding them on a scrub, clean, cleanall and help +ifneq ($(filter scrub clean cleanall help,$(MAKECMDGOALS)),) +DEPSVAR = +else +DEPSVAR = $(DEPS) +endif + +# +# Some rules +# + +# addfileheader-rule: allows "make addfileheader main.c server.c"-like +# commands and automatically inserts the path within the package +# options may be passed with $(ADDFILEHEADER_OPTIONS) +ADDFILEHEADER_PREFIX = $(patsubst $(call absfilename,$(PKGDIR)/)%,\ + $(PKGNAME)/%,$(call absfilename,./)) +ADDFILEHEADER_FILES = $(filter-out addfileheader,$(MAKECMDGOALS)) +addfileheader: + addfileheader $(ADDFILEHEADER_OPTIONS) -p $(ADDFILEHEADER_PREFIX) $(ADDFILEHEADER_FILES) + + +.PHONY: FORCE + +# +# Common functions +# + +# 1: name +# 2: output file +# 3: inc path (one only) +# 4: libs +# 5: requires_libs +generate_pcfile = \ + mkdir -p $(dir $(2)) \ + ;echo -n > $(2) \ + $(if $(3),;echo "incdir=/empty_incdir" >> $(2)) \ + ;echo "Name: $(1)" >> $(2) \ + ;echo "Version: 0" >> $(2) \ + ;echo "Description: L4 library" >> $(2) \ + $(if $(3),;echo "Cflags: $(addprefix -I\$${incdir}/,$(3))" >> $(2)) \ + $(if $(4),;echo "Libs: $(sort $(4))" >> $(2)) \ + $(if $(5),;echo "Requires: $(5)" >> $(2)) \ + $(if $(BID_GEN_CONTROL),;echo "Provides: $(1)" >> $(PKGDIR)/Control) \ + $(if $(BID_GEN_CONTROL),;echo "Requires: $(5)" >> $(PKGDIR)/Control) ; + + +endif # _L4DIR_MK_MAKECONF undefined diff --git a/l4/mk/WhatIsThis b/l4/mk/WhatIsThis new file mode 100644 index 00000000..e64452d8 --- /dev/null +++ b/l4/mk/WhatIsThis @@ -0,0 +1,2 @@ +# DROPS Building Makros +filelist="*.mk *.inc config.*" diff --git a/l4/mk/aliases.d/10-stdlibs b/l4/mk/aliases.d/10-stdlibs new file mode 100644 index 00000000..23ec6bcf --- /dev/null +++ b/l4/mk/aliases.d/10-stdlibs @@ -0,0 +1,3 @@ +stdlibs-all := l4sys l4re l4re-util libc_be_l4refile libc_be_l4re +stdlibs := stdlibs-all libl4re-vfs +stdlibs-sh := stdlibs-all ldso libdl libc_support_misc libc_be_socket_noop diff --git a/l4/mk/aliases.d/15-libio b/l4/mk/aliases.d/15-libio new file mode 100644 index 00000000..bbc564b8 --- /dev/null +++ b/l4/mk/aliases.d/15-libio @@ -0,0 +1 @@ +libio := libio-io diff --git a/l4/mk/binary.inc b/l4/mk/binary.inc new file mode 100644 index 00000000..05d3b2fc --- /dev/null +++ b/l4/mk/binary.inc @@ -0,0 +1,773 @@ +# -*- Makefile -*- +# vim:set ft=make: +# +# DROPS (Dresden Realtime OPerating System) Component +# +# Makefile-Include for compiling templates (prog.mk, lib.mk) + +# Makefile-Include for binary and lib directories +# Definitions for building the Makefile.inc, building dependencies, +# compiler configuration. +# +# If SYSTEM is defined and we do not clean, we generate Makefile.inc. This file +# holds the dependencies of the targets. Is also contains the definitions of +# variables holding the objects of the related targets. In a multiple +# architecture makefile, Makefile.inc will be built in arch-specific subdirs, +# like the other components built. +# +# Most compiler- and linker-flag variables are defined in such a way that +# using them in the rule will expand all the target- and +# architecture-specific definitions. +# +# The relink-rule is defined in this file. +# +# The dependencies for compiling files are defined here, the dep-files are +# generated with names .(source-file).d for .c, .cc and .S-files. +# +# Clean-rules are defined here. +# + +$(GENERAL_D_LOC): $(L4DIR)/mk/binary.inc $(L4DIR)/mk/modes.inc + +# our default Makefile-name in the OBJ-Subdirs +BID_OBJ_Makefile ?= Makefile + +ifeq ($(SYSTEM),) # if we have no system yet, build the subdirs +################################################################# +# +# we have NO system defined in $(SYSTEM), we are in the src/ dir +# +################################################################# + +# our default systems +SYSTEMS ?= $(SYSTEMS_ABI) + +BID_MISSING_PCS := \ + $(strip $(if $(DEPENDS_PKGS), \ + $(strip $(foreach i,$(DEPENDS_PKGS), \ + $(if $(strip $(wildcard $(OBJ_BASE)/pc/$(i).pc)),,$(i)))))) + +ifneq ($(BID_MISSING_PCS),) + # clear SYSTEMS to prevent building anything + SYSTEMS = + text := $(shell echo -e "\033[32mPackage dependencies missing: \033[1m$(BID_MISSING_PCS)\033[22m; skipping directory '$(SRC_DIR)'.\033[0m") + $(if $(BID_FAIL_ON_MISSING),$(error $(text)), $(info $(text))) +endif + +# intersection with BUILD_SYSTEMS + +# filter the systems from the local SYSTEMS variable ($2), that match +# the build-architecture. +# args: $(1) - build architecture (one from BUILD_SYSTEMS) +# $(2) - SYSTEMS +# 1. check, if both systems are the same (optionally reduced by the CPU) +# 2. check, if at least the arch matches (and optionally the cpu) +FILTER_SYSTEM = $(shell echo $(2)|$(AWKP) '\ + BEGIN{m=s="$(1)";sub("_[^-]*","",m)}\ + {for(i=1;i<=NF;i++){\ + if(m==$$i||s==$$i){print s}else\ + if(index(m,$$i)==1||index(s,$$i)==1)\ + {t=s;sub("-.*","",t);print t}}}') + +# print that system of the SYSTEMS variable that actually matched with +# $(BUILD_SYSTEMS) to the given system +# args: $(1) - build architecture (SYSTEM) +# $(2) - SYSTEMS +# + do nearly the same as in FILTER_SYSTEM, but additionally check if +# the resulting system matches $(1). If so, print the according pattern from +# SYSTEMS and exit +BID_ORIG_SYSTEM = $(shell echo $(2)|$(AWKP) '\ + BEGIN{m=s="$(1)";sub("_[^-]*","",m)}\ + {for(i=1;i<=NF;i++){\ + if(m==$$i||s==$$i){if(s=="$(1)"){print $$i;exit}};\ + if(index(m,$$i)==1||index(s,$$i)==1)\ + {t=s;sub("-.*","",t);\ + if(t=="$(1)"){print $$i;exit}}}}') + +ifeq ($(ROLE),idl.mk) +TARGET_SYSTEMS := $(sort $(foreach sys,$(sort \ + $(shell echo $(BUILD_SYSTEMS)|$(SED) -e 's/_[^- ]*\(-\{0,1\}\)/\1/g')), \ + $(call FILTER_SYSTEM,$(sys),$(SYSTEMS)))) +else +TARGET_SYSTEMS := $(sort $(foreach sys,$(BUILD_SYSTEMS),\ + $(call FILTER_SYSTEM,$(sys),$(SYSTEMS)))) +endif + +DIR_FROM_SUB = $(firstword $(addprefix ../,$(patsubst /%,,$(1))) $(1)) +SYSTEM_TO_ARCH = $(shell echo $(1)|$(SED) -e 's/[_-].*//') +SYSTEM_TO_CPU = $(shell echo $(1)|$(SED) -ne 's/[^-_]*_\([^-]*\).*/\1/p') +SYSTEM_TO_L4API = $(shell echo $(1)|$(SED) -ne 's/.*-\(.*\)/\1/p') + +$(foreach sys,$(TARGET_SYSTEMS),$(OBJ_DIR)/OBJ-$(sys)/$(BID_OBJ_Makefile)):$(OBJ_DIR)/OBJ-%/$(BID_OBJ_Makefile):$(OBJ_DIR)/.general.d + @install -d $(dir $@) + @echo 'L4DIR=$(L4DIR_ABS)'>$@ + @echo 'OBJ_BASE=$(OBJ_BASE)'>>$@ + @echo 'OBJ_DIR=$(OBJ_DIR)'>>$@ + @echo 'SRC_DIR=$(SRC_DIR)'>>$@ + @echo 'PKGDIR=$(PKGDIR_ABS)'>>$@ + @echo 'PKGDIR_ABS=$(PKGDIR_ABS)'>>$@ + @echo 'PKGDIR_OBJ=$(PKGDIR_OBJ)'>>$@ + @echo 'MAKECONFLOCAL=$(SRC_DIR)/Makeconf.local'>>$@ + @echo 'OSYSTEM=$(call BID_ORIG_SYSTEM,$*,$(SYSTEMS))'>>$@ + @echo 'SYSTEM=$*'>>$@ + @echo 'ARCH=$(call SYSTEM_TO_ARCH,$*)'>>$@ + @echo 'CPU=$(call SYSTEM_TO_CPU,$*)'>>$@ + @echo 'L4API=$(call SYSTEM_TO_L4API,$*)'>>$@ + @echo 'vpath %.c $(VPATH_SRC_BASE)'>>$@ + @echo 'vpath %.cc $(VPATH_SRC_BASE)'>>$@ + @echo 'vpath %.cpp $(VPATH_SRC_BASE)'>>$@ + @echo 'vpath %.S $(VPATH_SRC_BASE)'>>$@ + @echo 'vpath %.y $(VPATH_SRC_BASE)'>>$@ + @echo 'vpath %.l $(VPATH_SRC_BASE)'>>$@ + @echo 'vpath %.ld $(VPATH_SRC_BASE)'>>$@ + @echo 'vpath %.dpe $(VPATH_SRC_BASE)'>>$@ + @echo '.general.d: $(SRC_DIR)/$(if $(wildcard Make.rules),Make.rules,Makefile)'>>$@ + @echo 'include $(SRC_DIR)/$(if $(wildcard Make.rules),Make.rules,Makefile)'>>$@ + @echo 'include $$(L4DIR)/mk/$(ROLE)'>>$@ + +install relink scrub:: $(foreach arch,$(TARGET_SYSTEMS),\ + $(OBJ_DIR)/OBJ-$(arch)/$(BID_OBJ_Makefile)) + $(if $(TARGET_SYSTEMS), $(VERBOSE)set -e ; \ + for d in $(TARGET_SYSTEMS) ; do \ + PWD=$OBJ-$$d $(MAKE) -C $(OBJ_DIR)/OBJ-$$d -f $(BID_OBJ_Makefile) \ + $@ ; done ) + +.PHONY: pre-obj +pre-obj:: + +all:: $(foreach arch,$(TARGET_SYSTEMS), $(OBJ_DIR)/OBJ-$(arch)) +.PHONY: $(foreach arch,$(TARGET_SYSTEMS), $(OBJ_DIR)/OBJ-$(arch)) +$(foreach arch,$(TARGET_SYSTEMS), $(OBJ_DIR)/OBJ-$(arch)):%:%/$(BID_OBJ_Makefile) pre-obj + $(VERBOSE)PWD=$@ $(MAKE) $(PL_j) -C $@ -f $(BID_OBJ_Makefile) + + +foreach_objdir = $(if $(wildcard $(OBJ_DIR)/OBJ-*), $(VERBOSE)set -e ; \ + for d in $(wildcard $(OBJ_DIR)/OBJ-*) ; do \ + PWD=$$d $(MAKE) -C $$d -f $(BID_OBJ_Makefile) $(1); \ + done, @true) + +%.i %.s.i:: export DO_SHOW_RESULT_FILE=y +%.i %.s.i:: + $(call foreach_objdir,$@) + +clean disasm:: + $(call foreach_objdir,$@) + +cleanall:: + $(VERBOSE)$(RM) -r $(wildcard $(OBJ_DIR)) + +.PHONY: $(TARGET_SYSTEMS) + +else +############################################################### +# +# we have a system defined in $(SYSTEM), we are in an OBJ- dir +# +############################################################### + +all:: $(TARGET) + +disasm: $(TARGET) + $(call DISASM_CMD,$(if $(DABIN),$(DABIN),$<)) + +ifneq ($(CONFIG_USE_DROPS_STDDIR),) +L4INCDIR ?= $(addprefix $(OBJ_BASE)/include/$(ARCH)/,$(L4API)) \ + $(addprefix $(OBJ_BASE)/include/,$(L4API)) \ + $(OBJ_BASE)/include/$(ARCH) \ + $(OBJ_BASE)/include \ + $(if $(USE_DICE),$(DICE_INCDIR),) \ + $(addprefix $(DROPS_STDDIR)/include/$(ARCH)/,$(L4API)) \ + $(addprefix $(DROPS_STDDIR)/include/,$(L4API)) \ + $(DROPS_STDDIR)/include/$(ARCH) \ + $(DROPS_STDDIR)/include + +L4LIBDIR ?= $(addprefix $(OBJ_BASE)/lib/$(ARCH)_$(CPU)/,$(L4API)) \ + $(OBJ_BASE)/lib/$(ARCH)_$(CPU) \ + $(OBJ_BASE)/lib \ + $(addprefix $(DROPS_STDDIR)/lib/$(ARCH)_$(CPU)/,$(L4API)) \ + $(DROPS_STDDIR)/lib/$(ARCH)_$(CPU) \ + $(DROPS_STDDIR)/lib + +else + +L4INCDIR ?= $(addprefix $(OBJ_BASE)/include/$(ARCH)/,$(L4API)) \ + $(addprefix $(OBJ_BASE)/include/,$(L4API)) \ + $(OBJ_BASE)/include/$(ARCH) \ + $(OBJ_BASE)/include \ + $(if $(USE_DICE),$(DICE_INCDIR),) + +L4LIBDIR ?= $(addprefix $(OBJ_BASE)/lib/$(ARCH)_$(CPU)/,$(L4API)) \ + $(OBJ_BASE)/lib/$(ARCH)_$(CPU) \ + $(OBJ_BASE)/lib +endif + +# +# Variables Section +# +# There is a hierarchy on defining variables depending on the targets they +# refer to: Most standard-Make Variables are supported. This includes +# LDFLAGS - options for ld, defined in prog.mk and lib.mk +# CPPFLAGS - options for the c preprocessor, included in CFLAGS +# CFLAGS - options for the c compiler +# CXXFLAGS - options for the c++ compiler +# ASFLAGS - options for the assembler +# +# Addtitionally, the following varibales are supported: +# SRC_C, SRC_CC, SRC_S - .c, .cc, .S source files +# CRT0, CRTN - startup and finish code +# LIBS - additional libs to link (with -l), including paths (-L) +# IDL - interface definition files +# TARGET - targets to ge built +# +# These variables will be used for all operations with the corresponding +# file types. More specific description is possible by using variables with +# added specifications. These specifications include a referred element and +# the architecture, both optional but in this order, separated by +# underscores. The referred element for CPPFLAGS, CFLAGS, CXXFLAGS and +# ASFLAGS is the source file. For the other variables, it is one of the +# target files. The TARGET variable can only be postfixed by an +# architecture. +# The specific variables will be used for the target and the referred element +# given in the name, additionally to the more general ones. +# +# Example for a valid specifications: +# SRC_C_libxverbose.a = verbose.c - ar's verbose.o into libxverbose.a, but +# not in other libs in the TARGET var. + +include $(L4DIR)/mk/modes.inc + +# select the variable specified in $(1) from the current architecture and +# mode. Fall back to "all" architecture if no specific version exists. +BID_mode_var= $(if $($(1)_$(ARCH)_$(MODE)),$($(1)_$(ARCH)_$(MODE)),$($(1)_all_$(MODE))) + +BID_SUPPORTED ?= $(call BID_mode_var,BID_SUPPORTED) +ifneq ($(BID_SUPPORTED),y) +$(error Mode "$(MODE)" is not supported for CPU architecture "$(ARCH)") +endif + +LIBCINCDIR ?= $(call BID_mode_var,LIBCINCDIR) +LIBCLIBDIR ?= $(call BID_mode_var,LIBCLIBDIR) +L4_LIBS ?= $(call BID_mode_var,L4_LIBS) +CRT0 ?= $(call BID_mode_var,CRT0) +CRTP ?= $(if $(filter $(CRT0_DEFAULT),$(CRT0)),$(CRTP_DEFAULT),$(CRT0)) +CRTN ?= $(call BID_mode_var,CRTN) +LDSCRIPT ?= $(call BID_mode_var,LDSCRIPT) +LDFLAGS += $(call BID_mode_var,LDFLAGS) +REQUIRES_LIBS += $(REQUIRES_LIBS_$(ARCH)) $(call BID_mode_var,REQUIRES_LIBS) + +# we do not need to put our FLAG-definitions into a special file if we can +# use the target to parameterize it and if it needs not to appear in the deps +#CRT0 = $(word 1, $(CRT0_$@_$(OSYSTEM)) $(CRT0_$@) $(CRT0_$(OSYSTEM))) +#CRTN = $(word 1, $(CRTN_$@_$(OSYSTEM)) $(CRTN_$@) $(CRTN_$(OSYSTEM))) +LIBS += $(strip $(LIBS_$(OSYSTEM)) $(LIBS_$@) $(LIBS_$@_$(OSYSTEM))) + +LDFLAGS += $(strip $(LDFLAGS_$(OSYSTEM)) $(LDFLAGS_$@) $(LDFLAGS_$@_$(OSYSTEM))) +CARCHFLAGS += $(CARCHFLAGS_$(ARCH)) $(CARCHFLAGS_$(ARCH)_$(CPU)) + +# --------------------------------- + +BID_MISSING_LIBS := + +# call pkg-config, returns __PKGCONFIG_FAILED__ if the call failed +# 1: OBJ_BASE +# 2: parameters to pkg-config +# 3: list of packages +# use L4_BID_PKG_CONFIG because of export-defs, the function is copied +L4_BID_PKG_CONFIG = $(PKG_CONFIG) +BID_PKG_CONFIG = $(if $(strip $(3)), \ + $(shell PKG_CONFIG_LIBDIR=$(1)/pc \ + PKG_CONFIG_PATH= $(L4_BID_PKG_CONFIG) \ + --define-variable=incdir=$(1)/include/contrib \ + $(if $(VERBOSE),--silence-errors) \ + $(2) $(3) || echo __PKGCONFIG_FAILED__)) + +BID_PKG_CONFIG_MISSING = \ + $(if $(strip $(3)), \ + $(shell PKG_CONFIG_LIBDIR=$(1)/pc \ + PKG_CONFIG_PATH= LANG=C $(L4_BID_PKG_CONFIG) \ + --errors-to-stdout --print-errors $(2) $(3) \ + | LANG=C grep ", not found")) + +BID_PKG_CONFIG_FAILED = $(findstring __PKGCONFIG_FAILED__,$(1)) + +ifeq ($(BID_MISSING_PCS),) + ifneq ($(SYSTEM),) + ifneq ($(REQUIRES_LIBS),) + REQUIRES_LIBS_LIST := $(strip $(call BID_PKG_CONFIG,$(OBJ_BASE),--libs,$(REQUIRES_LIBS))) + # error handling + ifneq ($(call BID_PKG_CONFIG_FAILED,$(REQUIRES_LIBS_LIST)),) + BID_MISSING_PCS := $(strip $(foreach i,$(REQUIRES_LIBS), \ + $(if $(filter __PKGCONFIG_FAILED__,$(call BID_PKG_CONFIG,$(OBJ_BASE),--libs --print-errors,$(i))),$(i)))) + text := $(shell echo -e "\033[31mLibrary dependencies missing: \033[1m$(BID_MISSING_PCS)\033[22m in directory '$(SRC_DIR)'; aborting.\033[0m") + text2 := $(strip $(foreach i,$(REQUIRES_LIBS), $(call BID_PKG_CONFIG_MISSING,$(OBJ_BASE),--libs,$(i)))) + $(if $(text2),$(info $(shell echo -e "\033[31m$(text2)\033[0m"))) + $(if $(BID_MISSING_PCS),$(info $(text)),$(error $(text))) + endif + + # some sanity check + ifneq ($(filter libl4re-vfs,$(REQUIRES_LIBS)),) + $(error Never include 'libl4re-vfs'!) + endif + endif + + BID_PKG_CONFIG_CFLAGS := $(call BID_PKG_CONFIG,$(OBJ_BASE),--cflags, $(REQUIRES_CFLAGS) $(REQUIRES_LIBS)) + + # error handling + ifneq ($(call BID_PKG_CONFIG_FAILED,$(BID_PKG_CONFIG_CFLAGS)),) + BID_MISSING_PCS := $(strip $(foreach i,$(REQUIRES_CFLAGS) $(REQUIRES_LIBS), \ + $(if $(filter __PKGCONFIG_FAILED__,$(call BID_PKG_CONFIG,$(OBJ_BASE),--cflags --print-errors,$(i))),$(i)))) + text := $(shell echo -e "\033[31mCflags dependencies missing: \033[1m$(BID_MISSING_PCS)\033[22m in directory '$(SRC_DIR)'; aborting.\033[0m") + text2 := $(strip $(foreach i,$(REQUIRES_LIBS), $(call BID_PKG_CONFIG_MISSING,$(OBJ_BASE),--cflags,$(i)))) + $(if $(text2),$(info $(shell echo -e "\033[31m$(text2)\033[0m"))) + $(error $(text)) + endif + endif # SYSTEM +endif + +# ----------------------- + +# May 2007: force somewhat old hash-style as some(!, independant of the +# actual version) ld now use an other format, no uclibc upstream fix +# available yet, until available, we need: +ifeq ($(LD_HAS_HASH_STYLE_OPTION),y) +ifneq ($(HOST_LINK),1) +LDFLAGS += --hash-style=sysv +endif +endif + +OPTS ?= -g -O2 -fno-strict-aliasing +WARNINGS?= -Wextra -Wall -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations $(WARNINGS_$@) + +ifeq ($(MODE),host) +# never cross compile in host mode +SYSTEM_TARGET = +CC = $(HOST_CC) +CXX = $(HOST_CXX) +LIBS += $(REQUIRES_LIBS_LIST) +else +# no architecture specific flags in host mode +LDFLAGS += $(LDFLAGS_$(ARCH)) +L4_LIBS += $(REQUIRES_LIBS_LIST) +endif + +# no link address if build a lib or we're compiling a host program and using +# the host linker scripts +ifeq ($(ROLE),lib.mk) +NO_DEFAULT_RELOC := y +endif +ifneq ($(HOST_LINK),) +NO_DEFAULT_RELOC := y +endif + +default_reloc_base = $(firstword $(DEFAULT_RELOC_$(1)) \ + $(DEFAULT_RELOC_$(ARCH)) \ + $(DEFAULT_RELOC) \ + $(if $(NO_DEFAULT_RELOC),,0x01000000)) +default_reloc = $(if $(call default_reloc_base,$(1)),\ + $(if $(RELOC_PHYS), \ + $(shell printf "0x%x" $$(($(RAM_BASE) + $(call default_reloc_base,$(1))))), \ + $(call default_reloc_base,$(1)))) + +# can be overwritten to get the old mode +CFLAGS_C99 ?= -std=gnu99 + +ifneq ($(MODE),host) +CFLAGS_L4_GENERIC += $(CCXX_FLAGS) $(CARCHFLAGS) $(GCCNOSTACKPROTOPT) +endif + +$(CLIENTIDL:.idl=-client.o): CFLAGS += -ffunction-sections +CFLAGS += $(if $(CONFIG_BID_GCC_OMIT_FP),-fomit-frame-pointer,) +CFLAGS += $(CFLAGS_$(OSYSTEM)) $(CFLAGS_$<) $(CFLAGS_$($@_ + # write helper variables containing the IDL-C-Sources + @$(ECHO) -en '$(strip $(foreach target,$(TARGET), \ + \nIDL_SRC_C_$(target)=$(call IDL_SRC_Cfn,$(target))))'>>$@_ + # and add them to SRC_C + @$(ECHO) -en '$(strip $(foreach target,$(TARGET), \ + \nSRC_C_$(target) += $$(IDL_SRC_C_$(target))))'>>$@_ + # but set the variables empty for the current rule + @$(ECHO) -en '$(strip $(foreach target,$(TARGET), \ + \n$(BID_OBJ_Makefile).inc: IDL_SRC_C_$(target)=))'>>$@_ + # write helper variables containing the IDL-C++-Sources + @$(ECHO) -en '$(strip $(foreach target,$(TARGET), \ + \nIDL_SRC_CC_$(target)=$(call IDL_SRC_CCfn,$(target))))'>>$@_ + # and add them to SRC_CC + @$(ECHO) -en '$(strip $(foreach target,$(TARGET), \ + \nSRC_CC_$(target) += $$(IDL_SRC_CC_$(target))))'>>$@_ + # but set the variables empty for the current rule + @$(ECHO) -en '$(strip $(foreach target,$(TARGET), \ + \n$(BID_OBJ_Makefile).inc: IDL_SRC_CC_$(target)=))'>>$@_ + # write the object declaration variables + # TARGET_{STANDARD, PIC, SHARED, STANDARD_NE, SHARED_NE} + # contain the appropriate targets + # TARGET_PROFILE_{STANDARD, PIC, SHARED} as well + @$(ECHO) -en '$(strip $(foreach target,$(TARGET_STANDARD), \ + \nOBJS_$(target) += $(call targetobjs,$(target),)))' >>$@_ + @$(ECHO) -en '$(strip $(foreach target,$(TARGET_STANDARD_NE), \ + \nOBJS_$(target) += $(call targetobjs_ne,$(target),)))' >>$@_ + @$(ECHO) -en '$(strip $(foreach target,$(TARGET_PIC) $(TARGET_SHARED), \ + \nOBJS_$(target) += $(call targetobjs,$(target),.s)))' >>$@_ + @$(ECHO) -en '$(strip $(foreach target,$(TARGET_PIC_NE) $(TARGET_SHARED_NE), \ + \nOBJS_$(target) += $(call targetobjs_ne,$(target),.s) \ + \nLINK_WITH_NOEXC_LIBS_$(target) = y))' >>$@_ + @$(ECHO) -en '$(strip $(foreach target,$(TARGET_PROFILE), \ + \nOBJS_$(target) += $(call targetobjs,$(target),.pr)))' >>$@_ + @$(ECHO) -e '$(strip $(foreach target,$(TARGET_PROFILE_PIC) $(TARGET_PROFILE_SHARED), \ + \nOBJS_$(target) += $(call targetobjs,$(target),.pr.s)))' >>$@_ + # + # write the dpe-dependencies + @$(ECHO) -e '$(foreach obj,$(sort \ + $(foreach t,$(TARGET_STANDARD),$(call targetobjs,$t)) \ + $(foreach t,$(TARGET_PIC) $(TARGET_SHARED), \ + $(call targetobjs,$t,.s)) \ + $(foreach t,$(TARGET_PROFILE),$(call targetobjs,$t,.pr)) \ + $(foreach t,$(TARGET_PROFILE_PIC) $(TARGET_PROFILE_SHARED),\ + $(call targetobjs,$t,.pr.s))),$(strip \ + $(addprefix \n$(obj): ,$(patsubst %.dpe,%.dpi, \ + $(DPE_$(obj:.o=.c)) $(DPE_$(obj:.o=.cc)) \ + $(DPE_$(obj:.s.o=.c)) $(DPE_$(obj:.s.o=.cc)) \ + $(DPE_$(obj:.pr.o=.c)) $(DPE_$(obj:.pr.o=.cc)) \ + $(DPE_$(obj:.pr.s.o=.c)) $(DPE_$(obj:.pr.s.o=.cc)) \ + ))))' >>$@_ + # + # create the object-dirs + @$(if $(OBJDIRS), $(VERBOSE)set -e; for d in $(OBJDIRS); do \ + [ -d "$$d" ] || $(MKDIR) $$d; done ) + + # + # write the object-dependencies for the targets + @$(ECHO) -e '$(foreach target,$(TARGET),$(strip\ + \n$(target): $$(OBJS_$(target)) ))' >> $@_ + # make the target dependent on '.general.d' + @$(ECHO) -e '$(foreach target,$(TARGET),$(strip \ + \n$$(OBJS_$(target)): .general.d))' \ + >> $@_ + # Using LDSO does not need a RELOC address, so omit the following in + # this case +ifneq ($(MODE),shared) + # in case of a binary, write the link address + # the dependency to the static file: If DEFAULT_RELOC is set, + # all targets are made dependent on the STATIC file + # (defined in Makeconf). + # If DEFAULT_RELOC_xxx is set, xxx is made dependent on the + # STATIC file. +ifneq ($(strip $(foreach target,$(TARGET), $(call default_reloc,$(target)))),) +ifneq ($(filter l4linux host,$(MODE)),) + $(error DEFAULT_RELOC must not be set if MODE is l4linux or host) +endif + # the relocatable binaries depend on Makefile.inc + @$(ECHO) -e '\n$(strip \ + $(foreach target, $(TARGET), \ + $(if $(call default_reloc,$(target)),$(target))) \ + : $@)' >>$@_ + # we find out the relocation address here. + @$(ECHO) -e '$(foreach target, $(TARGET),$(strip \ + \nLDFLAGS_$(target)+= --defsym=__executable_start=$(firstword \ + $(call default_reloc,$(target)))))' \ + >>$@_ +endif +endif # MODE != shared + @mv $@_ $@ + +ifeq ($(filter scrub help,$(MAKECMDGOALS)),) +-include $(BID_OBJ_Makefile).inc +endif + +# +# Rules Section +# + +# the default target "all" ensures building of the targets. When multiple +# architectures are used, the targets are build in subdirs. + +# the relink-rule: make the TARGETs phony. Specification of build-targets +# in MAKECMDGOALS is not allowed. Possibility: TARGET= +# +ifneq ($(filter relink,$(MAKECMDGOALS)),) +.PHONY: $(TARGET) +relink: all +endif + + + +### +# +# Compilation rules with dependency-generation +# +# If we have ld.so, we use it to create our dependencies (see MAKEDEP +# definition). Otherwise, we fall back to whatever we need. For +# compilation with gcc, this is using "-MD" and postprocessing the +# generated files. + +ifeq ($(CONFIG_HAVE_LDSO),) +LIBDEPS = $(foreach file, \ + $(patsubst -l%,lib%.a,$(filter-out -L%,$(LDFLAGS))) \ + $(patsubst -l%,lib%.so,$(filter-out -L%,$(LDFLAGS))),\ + $(word 1, $(foreach dir, \ + $(patsubst -L%,%,\ + $(filter -L%,$(LDFLAGS) $(L4ALL_LIBDIR))),\ + $(wildcard $(dir)/$(file))))) + +DEPEND_EXTEND_CMD = $(AWKP) ' \ +/^[^:]*: ..*/{ \ + while(sub("\\\\$$","")){ \ + getline nextline ; \ + $$0=$$0 " " nextline \ + } \ + split($$0,field,": "); \ + sub("^$(*F).o","$*.s $*.i $@",field[1]); \ + nr=split(field[2],deps) ; \ + for(i=1;i<=nr;){ \ + printf("ifeq ($$(shell test y \\\n"); \ + for(j=0; j<100 && i+j<=nr; j++){ \ + printf("-a -r %s \\\n", deps[i+j]); \ + } \ + printf("&& echo y),)"); \ + printf("\n%s: FORCE\nelse\n%s: $(BID_OBJ_Makefile) \\\n", \ + field[1],field[1]); \ + for(j=0; j<100 && i+j<=nr; j++){ \ + printf("%s \\\n",deps[i+j]); \ + } \ + printf("\nendif\n"); \ + i+=j; \ + } \ +}' +DEPEND_EXTEND_FUNC = ( $(DEPEND_EXTEND_CMD) < $(1) > $(2).new && rm -f $(1) && mv $(2).new $(2) ) || ( rm -f $(1) $(2).new $(2) ; $(DEPEND_IGNORE_ERRORS) ) +DEPEND_FLAG = -MD + +.PHONY: FORCE +endif # CONFIG_HAVE_LDSO empty +DEPFLAGS = -MD -MF $(@D)/.$(@F).d + +include $(L4DIR)/mk/rules.inc + +# generate rules to compile %.cc files to %.o, %.s.o etc +$(eval $(call BID_GENERATE_CXX_MAKE_RULES,cc)) +# generate rules to compile %.cpp files to %.o, %.s.o etc +$(if $(BID_ALLOW_CPP_AS_CPLUSPLUS_FILE),$(eval $(call BID_GENERATE_CXX_MAKE_RULES,cpp))) +# generate rules to compile %.c files to %.o, %.s.o etc +$(eval $(call BID_GENERATE_C_MAKE_RULES,c)) +# generate rules to compile %.S files to %.o, %.s.o etc +$(eval $(call BID_GENERATE_DEFAULT_MAKE_RULES,%,%.S,AS)) + +# Reset implicit rules, mind the TAB. +%: %.c + + +%: %.cc + + +%: %.cpp + + +%: %.S + + +$(eval $(call BID_GENERATE_I_MAKE_RULE,%.i,%.c,$(CC),$(CFLAGS))) +$(eval $(call BID_GENERATE_I_MAKE_RULE,%.s.i,%.c,$(CC),$(CFLAGS) $(PICFLAGS))) +$(eval $(call BID_GENERATE_I_MAKE_RULE,%.i,%.cc,$(CXX),$(CXXFLAGS))) +$(eval $(call BID_GENERATE_I_MAKE_RULE,%.s.i,%.cc,$(CXX),$(CXXFLAGS) $(PICFLAGS))) +$(if $(BID_ALLOW_CPP_AS_CPLUSPLUS_FILE),$(eval $(call BID_GENERATE_I_MAKE_RULE,%.i,%.cpp,$(CXX),$(CXXFLAGS)))) +$(if $(BID_ALLOW_CPP_AS_CPLUSPLUS_FILE),$(eval $(call BID_GENERATE_I_MAKE_RULE,%.s.i,%.cpp,$(CXX),$(CXXFLAGS) $(PICFLAGS)))) +$(eval $(call BID_GENERATE_I_MAKE_RULE,%.i,%.S,$(CC),$(ASFLAGS))) + +$(eval $(call BID_GENERATE_S_MAKE_RULE,%.c,$(CC),$(CFLAGS))) +$(eval $(call BID_GENERATE_S_MAKE_RULE,%.cc,$(CC),$(CXXFLAGS))) +$(if $(BID_ALLOW_CPP_AS_CPLUSPLUS_FILE),$(eval $(call BID_GENERATE_S_MAKE_RULE,%.cpp,$(CC),$(CXXFLAGS)))) + +%.c: %.y + @$(GEN_MESSAGE) + $(VERBOSE)$(CONFIG_YACC) $(YFLAGS) $(call absfilename,$<) + $(VERBOSE)mv -f y.tab.c $@ + $(VERBOSE)if [ -f y.tab.h ]; then mv -f y.tab.h $(@:.c=.h); fi + +%.c: %.l + @$(COMP_MESSAGE) + $(VERBOSE)$(CONFIG_LEX) -o$@ $(call absfilename,$<) + +%.dpi: %.dpe + @$(GEN_MESSAGE) + $(VERBOSE)$(call MAKEDEP,perl) $(GEN_DOPECODE) $< >$@ + +DEPS += $(foreach file,$(ALLOBJS), $(dir $(file)).$(notdir $(file)).d) +DEPS += $(foreach file,$(ALLDPI), $(dir $(file)).$(notdir $(file)).d) + +# Common clean Rules + +clean cleanall:: + $(VERBOSE)$(RM) $(strip $(filter-out $(KEEP_ON_CLEAN),\ + $(wildcard *.dpi) $(wildcard *.o) $(wildcard *.i) \ + $(wildcard *.S) $(ALLOBJS) $(DEL_ON_CLEAN))) + +# clean: delete all temporary editor files, objects, binaries +# and most generated files +cleanall:: + $(VERBOSE)$(RM) $(TARGET) $(wildcard .*.d) $(wildcard $(BID_OBJ_Makefile).inc) + +.PHONY: scrub clean cleanall disasm + +endif # $(SYSTEM) is defined + +# General rules + +# scrub: delete temporary editor files and stuff like this +# can be extended by lokals +scrub cleanall:: + $(VERBOSE)$(SCRUB) + diff --git a/l4/mk/config.inc b/l4/mk/config.inc new file mode 100644 index 00000000..ff52b130 --- /dev/null +++ b/l4/mk/config.inc @@ -0,0 +1,175 @@ +# -*- Makefile -*- +# vim:set ft=make: +# DROPS (Dresden Realtime OPerating System) Component +# +# Makefile-Include for compiling templates (prog.mk, lib.mk) +# + +# Makefile-Include for binary, lib, subdir and other directories. +# Definitions and rules for the DROPS configuration tool. + +# Supported targets: +# +# config:: - run the menu-driven configuration tool +# menuconfig xconfig:: - run the configuration tool +# oldconfig:: - (re)create the configuration header +# based on a prior configuration +# or default values +# +# Required Parameters: +# +# PKGDIR +# +# +# Optional Parameters: +# +# DROPSCONF - if nonempty, the configuration tool is run for +# target config::. If empty, the configuration tool +# is not run. +# DROPSCONF_TITLE - the main title in the configuration tool. +# DROPSCONF_DEFCONFIG - default config file +# DROPSCONF_CONFIG_IN - configuration defintion file +# DROPSCONF_CONFIG - config file +# DROPSCONF_CONFIG_H - generated config header file +# DROPSCONF_MACRO - macro to indicate inclusion of config header file +# DROPSCONF_HELPFILE - options help file +# DROPSCONF_TOOL - the menudriven configuration tool +# DROPSCONF_TOOL_TXT - the configuration tool +# DROPSCONF_TOOL_OLD - helper for recreating the config header file + + +KCONFIG_OBJ_DIR = $(OBJ_BASE)/tool/kconfig + +kconfig_call = [ -d $@ ] || install -d $(OBJ_BASE)/include/l4; \ + $(MAKE) -C $(L4DIR)/tool/kconfig O=$(OBJ_BASE) \ + Kconfig=$(KCONFIG_FILE) \ + KCONFIG_AUTOHEADER=include/l4/bid_config.h \ + KCONFIG_CONFIG=.kconfig \ + KCONFIG_AUTOCONFIG=.kconfig.auto \ + KCONFIG_TRISTATE=.kconfig.tristate \ + KERNELVERSION=SVN \ + l4re_srcdir=$(L4DIR_ABS) + + +DROPSCONF ?= +#DROPSCONF_TITLE ?= DROPS Configuration Tool +#DROPSCONF_DEFCONFIG ?= defconfig +#DROPSCONF_CONFIG_IN ?= config.in +#DROPSCONF_CONFIG ?= $(OBJ_DIR)/.config +#DROPSCONF_CONFIG_H ?= $(OBJ_DIR)/config.h +#DROPSCONF_CONFIG_MK ?= $(OBJ_DIR)/Makeconf.bid.local +DROPSCONF_DONTINC_MK ?= +#DROPSCONF_MACRO ?= CONFIG_H_INCLUDED +#DROPSCONF_HELPFILE ?= config.help +#DROPSCONF_LXDIALOG ?= $(OBJ_BASE)/tool/config/lxdialog/lxdialog +#DROPSCONF_TOOL ?= $(firstword $(wildcard \ +# $(L4DIR)/tool/config/Menuconfig \ +# $(DROPS_STDDIR)/tool/bin/Menuconfig) \ +# did_not_find_BID_Menuconfig) +#DROPSCONF_TOOL_TXT ?= $(firstword $(wildcard \ +# $(L4DIR)/tool/config/Configure \ +# $(DROPS_STDDIR)/tool/bin/Configure) \ +# did_not_find_BID_Configure) +#DROPSCONF_TOOL_OLD ?= $(firstword $(wildcard \ +# $(L4DIR)/tool/config/Configure \ +# $(DROPS_STDDIR)/tool/bin/Configure) \ +# did_not_find_BID_Configure) -d +#DROPSCONF_VARDEFS = $(foreach v,TITLE DEFCONFIG CONFIG_IN CONFIG CONFIG_H \ +# MACRO HELPFILE UNDEF LXDIALOG,DROPSCONF_$v='$(DROPSCONF_$v)') + +ifneq ($(DROPSCONF),) +.o: $(DROPSCONF_CONFIG_H) + +DIRS_FOR_CONFIG = $(KCONFIG_OBJ_DIR) $(OBJ_BASE)/config + +$(DIRS_FOR_CONFIG): $(KCONFIG_FILE) + $(VERBOSE)[ -d $@ ] || install -d $@ + +menuconfig config: $(DIRS_FOR_CONFIG) + $(VERBOSE)+$(kconfig_call) menuconfig silentoldconfig + $(VERBOSE)test ! -r $(DROPSCONF_CONFIG) -o \ + ! $(DROPSCONF_CONFIG) -nt $(DROPSCONF_CONFIG_MK) || \ + $(MAKE) $(DROPSCONF_CONFIG_MK) + +oldconfig xconfig gconfig nconfig randconfig allyesconfig allnoconfig: $(DIRS_FOR_CONFIG) + $(VERBOSE)+$(kconfig_call) $@ silentoldconfig + @$(MAKE) $(DROPSCONF_CONFIG_MK) + +$(DROPSCONF_CONFIG): $(DIRS_FOR_CONFIG) + $(VERBOSE)+$(kconfig_call) silentoldconfig + + +#$(DROPSCONF_CONFIG_H): $(DROPSCONF_CONFIG) + +#$(DROPSCONF_CONFIG_H) $(DROPSCONF_CONFIG): $(DROPSCONF_CONFIG_IN) +# @$(GEN_MESSAGE) +# $(VERBOSE)install -d $(dir $(DROPSCONF_CONFIG)) +# $(VERBOSE)install -d $(dir $(DROPSCONF_CONFIG_H)) +# $(VERBOSE)if tty >/dev/null; then \ +# $(DROPSCONF_VARDEFS) $(DROPSCONF_TOOL_OLD); \ +# else \ +# true | $(DROPSCONF_VARDEFS) $(DROPSCONF_TOOL_OLD) \ +# $(if $(VERBOSE),>/dev/null,) || \ +# ( echo -e "\nError: Unattended mode -- Some defaults for config options are missing." ; \ +# false ) \ +# fi + +$(DROPSCONF_CONFIG_MK): $(DROPSCONF_CONFIG) + $(VERBOSE)sed -e "s/\(^[^= ]*=\)'\([^']*\)'/\1\2/" \ + <$(DROPSCONF_CONFIG) >$@ + $(VERBOSE)$(MAKE) DROPSCONF_CONFIG_MK_POST_HOOK + +DROPSCONF_CONFIG_MK_POST_HOOK:: + +#config:: $(DROPSCONF_LXDIALOG) +# $(VERBOSE)install -d $(dir $(DROPSCONF_CONFIG_H)) +# $(VERBOSE)$(DROPSCONF_VARDEFS) $(DROPSCONF_TOOL) +# $(VERBOSE)test ! -r $(DROPSCONF_CONFIG) -o \ +# ! $(DROPSCONF_CONFIG) -nt $(DROPSCONF_CONFIG_MK) || \ +# $(MAKE) $(DROPSCONF_CONFIG_MK) + +#txtconfig:: +# $(VERBOSE)install -d $(dir $(DROPSCONF_CONFIG_H)) +# $(VERBOSE)$(DROPSCONF_VARDEFS) $(DROPSCONF_TOOL_TXT) +# @$(MAKE) $(DROPSCONF_CONFIG_MK) +# +#oldconfig:: +# $(VERBOSE)install -d $(dir $(DROPSCONF_CONFIG_H)) +# $(VERBOSE)$(DROPSCONF_VARDEFS) $(DROPSCONF_TOOL_OLD) +# @$(MAKE) $(DROPSCONF_CONFIG_MK) +# +#$(DROPSCONF_LXDIALOG): +# $(VERBOSE)install -d $(@D) +# $(VERBOSE)PWD=$(call absfilename,$(L4DIR)/tool/config) $(MAKE) -C $(L4DIR)/tool/config +# +clean:: + +cleanall:: + $(VERBOSE)$(RM) $(DROPSCONF_CONFIG) $(DROPSCONF_CONFIG_H) \ + $(DROPSCONF_CONFIG_MK) .menuconfig.log \ + $(DROPSCONF_CONFIG).old + +help:: + @echo + @echo "Configuration targets:" + @echo " config - run the menu-driven configuration tool" + @echo " gconfig - run a graphical configuration tool" + @echo " xconfig - run a graphical configuration tool" + @echo " oldconfig - (re)create the configuration header based on a prior" + @echo " configuration or default values" + +# special switch not to include DROPSCONF_CONFIG_MK +ifeq ($(DROPSCONF_DONTINC_MK),) +# do not prebuild the config file on "make config" +ifeq ($(filter config oldconfig txtconfig help scrub clean cleanall $(DROPSCONF_CONFIG_MK),$(MAKECMDGOALS)),) +$(info INCLUDING $(DROPSCONF_CONFIG_MK) config.inc) +-include $(DROPSCONF_CONFIG_MK) +endif +endif + +# end of DROPSCONF defined +else +config txtconfig oldconfig:: +endif + +.PHONY: config oldconfig txtconfig diff --git a/l4/mk/defconfig/config.amd64 b/l4/mk/defconfig/config.amd64 new file mode 100644 index 00000000..bd74c2bc --- /dev/null +++ b/l4/mk/defconfig/config.amd64 @@ -0,0 +1,39 @@ +# +# Automatically generated file; DO NOT EDIT. +# L4Re Configuration +# +# CONFIG_BUILD_ARCH_x86 is not set +CONFIG_BUILD_ARCH_amd64=y +# CONFIG_BUILD_ARCH_arm is not set +# CONFIG_BUILD_ARCH_ppc32 is not set +# CONFIG_BUILD_ARCH_sparc is not set +CONFIG_BUILD_ARCH="amd64" +CONFIG_BUILD_ABI_l4f=y +CONFIG_BUILD_ABI="l4f" +CONFIG_CPU_X86_K8=y +# CONFIG_CPU_X86_K10 is not set +# CONFIG_CPU_X86_OPTERON is not set +CONFIG_CPU="K8" +CONFIG_PLATFORM_TYPE_pc=y +# CONFIG_PLATFORM_TYPE_custom is not set +CONFIG_PLATFORM_TYPE="pc" +# CONFIG_USE_DROPS_STDDIR is not set +# CONFIG_USE_DICE is not set +CONFIG_BID_COLORED_PHASES=y + +# +# Building +# +CONFIG_YACC="yacc" +CONFIG_LEX="flex" +CONFIG_CTAGS="ctags" +CONFIG_ETAGS="etags" +CONFIG_HAVE_LDSO=y +CONFIG_INT_CPP_NAME_SWITCH=y +CONFIG_INT_LD_NAME_SWITCH=y +# CONFIG_BID_STRIP_PROGS is not set +# CONFIG_BID_GCC_OMIT_FP is not set +# CONFIG_BID_GENERATE_MAPFILE is not set +# CONFIG_BID_BUILD_DOC is not set +# CONFIG_RELEASE_MODE is not set +CONFIG_MAKECONFS_ADD="" diff --git a/l4/mk/defconfig/config.arm-rv b/l4/mk/defconfig/config.arm-rv new file mode 100644 index 00000000..c737cd67 --- /dev/null +++ b/l4/mk/defconfig/config.arm-rv @@ -0,0 +1,58 @@ +# +# Automatically generated file; DO NOT EDIT. +# L4Re Configuration +# +# CONFIG_BUILD_ARCH_x86 is not set +# CONFIG_BUILD_ARCH_amd64 is not set +CONFIG_BUILD_ARCH_arm=y +# CONFIG_BUILD_ARCH_ppc32 is not set +# CONFIG_BUILD_ARCH_sparc is not set +CONFIG_BUILD_ARCH="arm" +CONFIG_BUILD_ABI_l4f=y +CONFIG_BUILD_ABI="l4f" +CONFIG_CPU="armv5te" +# CONFIG_CPU_ARM_ARMV4 is not set +# CONFIG_CPU_ARM_ARMV4T is not set +# CONFIG_CPU_ARM_ARMV5 is not set +# CONFIG_CPU_ARM_ARMV5T is not set +CONFIG_CPU_ARM_ARMV5TE=y +# CONFIG_CPU_ARM_ARMV6 is not set +# CONFIG_CPU_ARM_ARMV6T2 is not set +# CONFIG_CPU_ARM_ARMV6ZK is not set +# CONFIG_CPU_ARM_ARMV7A is not set +# CONFIG_CPU_ARM_ARMV7R is not set +# CONFIG_PLATFORM_TYPE_beagleboard is not set +# CONFIG_PLATFORM_TYPE_imx21 is not set +# CONFIG_PLATFORM_TYPE_imx35 is not set +# CONFIG_PLATFORM_TYPE_imx51 is not set +# CONFIG_PLATFORM_TYPE_integrator is not set +# CONFIG_PLATFORM_TYPE_kirkwood is not set +# CONFIG_PLATFORM_TYPE_omap3_am33xx is not set +# CONFIG_PLATFORM_TYPE_omap3evm is not set +# CONFIG_PLATFORM_TYPE_pandaboard is not set +CONFIG_PLATFORM_TYPE_rv=y +# CONFIG_PLATFORM_TYPE_rv_pbx is not set +# CONFIG_PLATFORM_TYPE_rv_vexpress is not set +# CONFIG_PLATFORM_TYPE_tegra2 is not set +# CONFIG_PLATFORM_TYPE_custom is not set +CONFIG_PLATFORM_TYPE="rv" +# CONFIG_USE_DROPS_STDDIR is not set +# CONFIG_USE_DICE is not set +CONFIG_BID_COLORED_PHASES=y + +# +# Building +# +CONFIG_YACC="yacc" +CONFIG_LEX="flex" +CONFIG_CTAGS="ctags" +CONFIG_ETAGS="etags" +CONFIG_HAVE_LDSO=y +CONFIG_INT_CPP_NAME_SWITCH=y +CONFIG_INT_LD_NAME_SWITCH=y +# CONFIG_BID_STRIP_PROGS is not set +# CONFIG_BID_GCC_OMIT_FP is not set +# CONFIG_BID_GENERATE_MAPFILE is not set +# CONFIG_BID_BUILD_DOC is not set +# CONFIG_RELEASE_MODE is not set +CONFIG_MAKECONFS_ADD="" diff --git a/l4/mk/defconfig/config.ppc32 b/l4/mk/defconfig/config.ppc32 new file mode 100644 index 00000000..c20c21c4 --- /dev/null +++ b/l4/mk/defconfig/config.ppc32 @@ -0,0 +1,35 @@ +# +# Automatically generated file; DO NOT EDIT. +# L4Re Configuration +# +# CONFIG_BUILD_ARCH_x86 is not set +# CONFIG_BUILD_ARCH_amd64 is not set +# CONFIG_BUILD_ARCH_arm is not set +CONFIG_BUILD_ARCH_ppc32=y +# CONFIG_BUILD_ARCH_sparc is not set +CONFIG_BUILD_ARCH="ppc32" +CONFIG_BUILD_ABI_l4f=y +CONFIG_BUILD_ABI="l4f" +CONFIG_PLATFORM_TYPE_mpc5200=y +# CONFIG_PLATFORM_TYPE_custom is not set +CONFIG_PLATFORM_TYPE="mpc5200" +# CONFIG_USE_DROPS_STDDIR is not set +# CONFIG_USE_DICE is not set +CONFIG_BID_COLORED_PHASES=y + +# +# Building +# +CONFIG_YACC="yacc" +CONFIG_LEX="flex" +CONFIG_CTAGS="ctags" +CONFIG_ETAGS="etags" +CONFIG_HAVE_LDSO=y +CONFIG_INT_CPP_NAME_SWITCH=y +CONFIG_INT_LD_NAME_SWITCH=y +# CONFIG_BID_STRIP_PROGS is not set +# CONFIG_BID_GCC_OMIT_FP is not set +# CONFIG_BID_GENERATE_MAPFILE is not set +# CONFIG_BID_BUILD_DOC is not set +# CONFIG_RELEASE_MODE is not set +CONFIG_MAKECONFS_ADD="" diff --git a/l4/mk/defconfig/config.sparc b/l4/mk/defconfig/config.sparc new file mode 100644 index 00000000..fea304d0 --- /dev/null +++ b/l4/mk/defconfig/config.sparc @@ -0,0 +1,47 @@ +# +# Automatically generated file; DO NOT EDIT. +# L4Re Configuration +# +# CONFIG_BUILD_ARCH_x86 is not set +# CONFIG_BUILD_ARCH_amd64 is not set +# CONFIG_BUILD_ARCH_arm is not set +# CONFIG_BUILD_ARCH_ppc32 is not set +CONFIG_BUILD_ARCH_sparc=y +CONFIG_BUILD_ARCH="sparc" +CONFIG_BUILD_ABI_l4f=y +CONFIG_BUILD_ABI="l4f" +CONFIG_CPU="leon" +# CONFIG_CPU_SPARC_V7 is not set +CONFIG_CPU_SPARC_LEON=y +# CONFIG_CPU_SPARC_LEON3 is not set +# CONFIG_CPU_SPARC_V8 is not set +# CONFIG_CPU_SPARC_V9 is not set +# CONFIG_CPU_SPARC_ULTRASPARC is not set +# CONFIG_CPU_SPARC_ULTRASPARC3 is not set +# CONFIG_CPU_SPARC_NIAGARA is not set +# CONFIG_CPU_SPARC_NIAGARA2 is not set +# CONFIG_CPU_SPARC_NIAGARA3 is not set +# CONFIG_CPU_SPARC_NIAGARA4 is not set +CONFIG_PLATFORM_TYPE_leon3=y +# CONFIG_PLATFORM_TYPE_custom is not set +CONFIG_PLATFORM_TYPE="leon3" +# CONFIG_USE_DROPS_STDDIR is not set +# CONFIG_USE_DICE is not set +CONFIG_BID_COLORED_PHASES=y + +# +# Building +# +CONFIG_YACC="yacc" +CONFIG_LEX="flex" +CONFIG_CTAGS="ctags" +CONFIG_ETAGS="etags" +CONFIG_HAVE_LDSO=y +CONFIG_INT_CPP_NAME_SWITCH=y +CONFIG_INT_LD_NAME_SWITCH=y +# CONFIG_BID_STRIP_PROGS is not set +# CONFIG_BID_GCC_OMIT_FP is not set +# CONFIG_BID_GENERATE_MAPFILE is not set +# CONFIG_BID_BUILD_DOC is not set +# CONFIG_RELEASE_MODE is not set +CONFIG_MAKECONFS_ADD="" diff --git a/l4/mk/defconfig/config.x86 b/l4/mk/defconfig/config.x86 new file mode 100644 index 00000000..691cda6c --- /dev/null +++ b/l4/mk/defconfig/config.x86 @@ -0,0 +1,54 @@ +# +# Automatically generated file; DO NOT EDIT. +# L4Re Configuration +# +CONFIG_BUILD_ARCH_x86=y +# CONFIG_BUILD_ARCH_amd64 is not set +# CONFIG_BUILD_ARCH_arm is not set +# CONFIG_BUILD_ARCH_ppc32 is not set +# CONFIG_BUILD_ARCH_sparc is not set +CONFIG_BUILD_ARCH="x86" +CONFIG_BUILD_ABI_l4f=y +CONFIG_BUILD_ABI="l4f" +CONFIG_CPU_X86_586=y +# CONFIG_CPU_X86_PENTIUM is not set +# CONFIG_CPU_X86_PENTIUMMMX is not set +# CONFIG_CPU_X86_PENTIUMPRO is not set +# CONFIG_CPU_X86_686 is not set +# CONFIG_CPU_X86_PENTIUM2 is not set +# CONFIG_CPU_X86_PENTIUM3 is not set +# CONFIG_CPU_X86_PENTIUMM is not set +# CONFIG_CPU_X86_PENTIUM4 is not set +# CONFIG_CPU_X86_PRESCOTT is not set +# CONFIG_CPU_X86_NOCONA is not set +# CONFIG_CPU_X86_CORE2 is not set +# CONFIG_CPU_X86_K6 is not set +# CONFIG_CPU_X86_K7 is not set +# CONFIG_CPU_X86_ATHLON4 is not set +# CONFIG_CPU_X86_K8 is not set +# CONFIG_CPU_X86_K10 is not set +# CONFIG_CPU_X86_OPTERON is not set +CONFIG_CPU="586" +CONFIG_PLATFORM_TYPE_pc=y +# CONFIG_PLATFORM_TYPE_custom is not set +CONFIG_PLATFORM_TYPE="pc" +# CONFIG_USE_DROPS_STDDIR is not set +# CONFIG_USE_DICE is not set +CONFIG_BID_COLORED_PHASES=y + +# +# Building +# +CONFIG_YACC="yacc" +CONFIG_LEX="flex" +CONFIG_CTAGS="ctags" +CONFIG_ETAGS="etags" +CONFIG_HAVE_LDSO=y +CONFIG_INT_CPP_NAME_SWITCH=y +CONFIG_INT_LD_NAME_SWITCH=y +# CONFIG_BID_STRIP_PROGS is not set +# CONFIG_BID_GCC_OMIT_FP is not set +# CONFIG_BID_GENERATE_MAPFILE is not set +# CONFIG_BID_BUILD_DOC is not set +# CONFIG_RELEASE_MODE is not set +CONFIG_MAKECONFS_ADD="" diff --git a/l4/mk/doc.mk b/l4/mk/doc.mk new file mode 100644 index 00000000..1ffa7ffd --- /dev/null +++ b/l4/mk/doc.mk @@ -0,0 +1,327 @@ +# -*- Makefile -*- +# +# DROPS (Dresden Realtime OPerating System) Component +# +# Makefile-Template for doc directories +# +# install.inc is used, see there for further documentation + +ifeq ($(origin _L4DIR_MK_DOC_MK),undefined) +_L4DIR_MK_DOC_MK=y + +ROLE = doc.mk + +include $(L4DIR)/mk/Makeconf +$(GENERAL_D_LOC): $(L4DIR)/mk/doc.mk + +ifeq ($(IN_OBJ_DIR),) +################################################################## +# +# Empty IN_OBJ_DIR means we are in the source directory and have +# to first generate a Makefile in the build-dir. +# +################################################################## + +all install clean cleanall help:: $(OBJ_DIR)/Makefile.build + $(VERBOSE)PWD=$(OBJ_DIR) $(MAKE) -C $(OBJ_DIR) O=$(OBJ_BASE) -f Makefile.build $@ + + +$(OBJ_DIR)/Makefile.build: $(SRC_DIR)/Makefile + $(VERBOSE)install -d $(dir $@) + $(VERBOSE)echo 'IN_OBJ_DIR=1' > $@ + $(VERBOSE)echo 'L4DIR=$(L4DIR_ABS)' >> $@ + $(VERBOSE)echo 'SRC_DIR=$(SRC_DIR)' >> $@ + $(VERBOSE)echo 'OBJ_BASE=$(OBJ_BASE)' >> $@ + $(VERBOSE)echo 'PKGDIR_ABS=$(PKGDIR_ABS)' >> $@ + $(VERBOSE)echo 'vpath %.fig $(SRC_DIR)' >> $@ + $(VERBOSE)echo 'vpath %.tex $(SRC_DIR)' >> $@ + $(VERBOSE)echo 'include $(SRC_DIR)/Makefile' >> $@ + +else +################################################################### +# +# We are in the build directory and can process the documentation +# +################################################################### + +# default is to install all targets +INSTALL_TARGET_MASK ?= % + +ifneq ($(TARGET),) +# if no SRC_DOX is given, but TARGET, extract it from TARGET +ifeq ($(origin SRC_DOX),undefined) +SRC_DOX := $(filter $(addsuffix .cfg, $(TARGET)),$(wildcard *.cfg)) +ifneq ($(SRC_DOX),) +$(error SRC_DOX is undefined, but TARGET is defined. This is invalid since 04/23/2003) +endif +endif +# the same for SRC_TEX +ifeq ($(origin SRC_TEX),undefined) +SRC_TEX := $(filter $(TARGET:.ps=.tex),$(wildcard *.tex)) \ + $(filter $(TARGET:.pdf=.tex),$(wildcard *.tex)) + $(filter $(TARGET:.dvi=.tex),$(wildcard *.tex)) +ifneq ($(SRC_TEX),) +$(error SRC_TEX is undefined, but TARGET is defined. This is invalid since 04/23/2003) +endif +endif +endif + +TARGET_DOX = $(SRC_DOX:.cfg=) $(SRC_DOX_REF:.cfg=) \ + $(SRC_DOX_GUIDE:.cfg=) $(SRC_DOX_INT:.cfg=) +INSTALL_TARGET_DOX ?= $(filter $(INSTALL_TARGET_MASK), $(TARGET_DOX)) +TARGET_TEX ?= $(SRC_TEX:.tex=.ps) $(SRC_TEX:.tex=.pdf) +DEPS += $(foreach x,$(SRC_TEX:.tex=.dvi),$(dir $x).$(notdir $x).d) + +# if no TARGET is given, generate it from all types of targets +TARGET ?= $(TARGET_DOX) $(TARGET_TEX) +DEPS += $(foreach file,$(TARGET),$(dir $(file)).$(notdir $(file)).d) + +all:: $(TARGET) +$(TARGET): $(OBJ_DIR)/.general.d + +#################################################################### +# +# Doxygen specific +# +#################################################################### +DOXY_FLAGS += $(DOXY_FLAGS_$@) + +OUTPUTDIR = $(shell perl -n -e '/^\s*OUTPUT_DIRECTORY\s*=\s*(\S+)/ && print "$$1\n"' $(1)) + +# we refer to %/html sometimes. However, make fails on a rule of the form +# "% %/html:%.cfg", thus the workaround (others than static-pattern-rules +# won't work) +$(addprefix $(OBJ_DIR)/,$(addsuffix /html,$(TARGET_DOX))):$(OBJ_DIR)/%/html:$(OBJ_DIR)/% + +# We can give an internal rule for doxygen, as the directory specified +# in the config-file should be the name of the config file with the +# .cfg removed. +# Use make DOXY_FAST=y to just build the HTML without graphics +# Use make DOXY_FULL=y to build HTMl with graphics and the PDF +# $(VERBOSE)$(ECHO) ENABLED_SECTIONS=WORKING_SUBPAGES >> $@.flags +$(OBJ_DIR)/% $(OBJ_DIR)/%/html:$(SRC_DIR)/%.cfg + #generate the flags-file + $(VERBOSE)$(MKDIR) $@ + $(VERBOSE)$(ECHO) '@INCLUDE_PATH=/' > $@.flags + $(VERBOSE)$(ECHO) '@INCLUDE=$(SRC_DIR)/$(notdir $<)' >> $@.flags + $(VERBOSE)$(ECHO) $(DOXY_FLAGS) >> $@.flags + $(VERBOSE)$(ECHO) OUTPUT_DIRECTORY=$(OBJ_DIR)/$(call OUTPUTDIR,$<) >> $@.flags + $(VERBOSE)if [ -n "$(DOXY_FAST)" ]; then $(ECHO) HAVE_DOT=NO; $(ECHO) GENERATE_LATEX=NO; fi >> $@.flags + $(VERBOSE)if [ -n "$(DOXY_FULL)" ]; then $(ECHO) HAVE_DOT=YES; $(ECHO) GENERATE_LATEX=YES; fi >> $@.flags + $(VERBOSE)if [ -n "$(DOXY_RELEASE)" ]; then \ + $(ECHO) HAVE_DOT=YES; \ + $(ECHO) GENERATE_LATEX=YES; \ + $(ECHO) SHOW_FILES=NO; \ + $(ECHO) SHOW_DIRECTORIES=NO; \ + $(ECHO) INTERNAL_DOCS=NO; \ + $(ECHO) GENERATE_TODOLIST=NO; \ + $(ECHO) GENERATE_TESTLIST=NO; \ + $(ECHO) GENERATE_BUGLIST=NO; \ + $(ECHO) HIDE_UNDOC_CLASSES=YES; \ + $(ECHO) HIDE_UNDOC_MEMBERS=YES; \ + fi >> $@.flags + $(VERBOSE)cd $(L4DIR)/pkg && \ + for f in $(addsuffix /doc/files.cfg,*); \ + do echo '@INCLUDE = $$(L4DIR)/pkg/'$$f; done >> $@.flags + $(VERBOSE)cd $(OBJ_BASE)/include && $(call MAKEDEP,doxygen) L4DIR=$(L4DIR) $(DOXYGEN) $@.flags + $(VERBOSE)for file in $(ADD_FILES_TO_HTML); do cp $$file $@/html; done + $(VERBOSE)( [ -r $@/latex/Makefile ] && \ + echo | PWD=$@/latex $(MAKE) -C $@/latex ) || true + $(VERBOSE)if [ -d $@ ] ; then touch $@ ; fi + +# Installation rules follow +# +# define LOCAL_INSTALLDIR prior to including install.inc, where the install- +# rules are defined. Same for INSTALLDIR. +INSTALLDIR_HTML ?= $(DROPS_STDDIR)/doc/html +INSTALLFILE_HTML ?= $(CP) -pR $(1) $(2) +INSTALLDIR_HTML_LOCAL ?= $(OBJ_BASE)/doc/html +INSTALLFILE_HTML_LOCAL ?= $(if $(call is_dir,$(2)), \ + find '$(dir $(1))' -name '$(notdir $(1))' | xargs $(LN) -t $(2) -sf, \ + find '$(dir $(1))' -name '$(notdir $(1))' | xargs -I '{}' $(LN) -sf '{}' $(2)) + +INSTALLDIR = $(INSTALLDIR_HTML) +INSTALLFILE = $(INSTALLFILE_HTML) +INSTALLDIR_LOCAL = $(INSTALLDIR_HTML_LOCAL) +INSTALLFILE_LOCAL = $(INSTALLFILE_HTML_LOCAL) + +all:: $(TARGET) \ + $(addprefix $(INSTALLDIR_LOCAL)/, $(addsuffix .title, $(INSTALL_TARGET_DOX))) + +$(OBJ_DIR)/$(SRC_DOX_REF:.cfg=.title): BID_DOC_DOXTYPE=ref +$(OBJ_DIR)/$(SRC_DOX_GUIDE:.cfg=.title): BID_DOC_DOXTYPE=guide +$(OBJ_DIR)/$(SRC_DOX_INT:.cfg=.title): BID_DOC_DOXTYPE=int + +# first line: type +# second line: title that will appear at the generated index page +$(OBJ_DIR)/%.title:$(SRC_DIR)/%.cfg $(OBJ_DIR)/.general.d + $(VERBOSE)$(ECHO) $(BID_DOC_DOXTYPE)>$@ + $(VERBOSE)MAKEFLAGS= $(MAKE) -s -f $(L4DIR)/mk/makehelpers.inc -f $< \ + BID_print VAR=PROJECT_NAME >>$@ + +# Install the title file locally +# The installed title file depends on the installed doku for message reasons +$(foreach f,$(INSTALL_TARGET_DOX),$(INSTALLDIR_LOCAL)/$(f).title):$(INSTALLDIR_LOCAL)/%.title:$(OBJ_DIR)/%.title $(INSTALLDIR_LOCAL)/% + $(VERBOSE)$(call INSTALLFILE_LOCAL,$<,$@) + @$(call UPDATE_HTML_MESSAGE,$(INSTALLDIR_LOCAL)) + +# Install the docu locally, the title file will depend on +$(foreach f,$(INSTALL_TARGET_DOX),$(INSTALLDIR_LOCAL)/$(f)):$(INSTALLDIR_LOCAL)/%:$(OBJ_DIR)/% $(OBJ_DIR)/%/html + @$(INSTALL_DOC_LOCAL_MESSAGE) + $(VERBOSE)$(INSTALL) -d $@ + $(VERBOSE)$(call INSTALLFILE_LOCAL,$> $(L4DEF_FILE_MK); echo '$(1)="$($(1))"' >> $(L4DEF_FILE_SH); +do_output_mk = echo '$(1) = $($(1))' >> $(L4DEF_FILE_MK); + +ifeq ($(CALLED_FOR),static) + +MODE = static + +ifneq ($(SYSTEM),) + +L4_SYSTEM = $(ARCH)_$(CPU) +L4_CC = $(CC) +L4_CXX = $(CXX) +L4_CRT0_STATIC = $(CRT0) +L4_CRTN_STATIC = $(CRTN) +L4_LDFLAGS_LD_STATIC = $(filter-out -l%,$(BID_LDFLAGS_FOR_LINKING_LD)) +L4_LDFLAGS_GCC_STATIC = $(filter-out -l%,$(BID_LDFLAGS_FOR_LINKING_GCC)) +L4_LDFLAGS_DYNAMIC_LINKER_LD = $(LDFLAGS_DYNAMIC_LINKER) +L4_LDFLAGS_DYNAMIC_LINKER_GCC= $(LDFLAGS_DYNAMIC_LINKER_GCC) +L4_LIBDIRS = $(addprefix -L,$(L4LIBDIR)) +L4_CPPFLAGS = $(CPPFLAGS) +L4_CFLAGS = $(CFLAGS) +L4_CXXFLAGS = $(CXXFLAGS) +L4_GCCLIB = $(GCCLIB) +L4_GCCLIB_SO = $(GCCLIB_SO) +L4_GCCLIB_EH = $(GCCLIB_EH) +L4_LDS_stat_bin = $(LDS_stat_bin) +L4_BID_STACK_ADDR = $(L4_STACK_ADDR) +L4_BID_STACK_SIZE = $(L4_STACK_SIZE) +L4_BID_KIP_ADDR = $(L4_KIP_ADDR) +L4_BID_KIP_OFFS_SYS_INVOKE = $(L4_KIP_OFFS_SYS_INVOKE) +L4_BID_KIP_OFFS_SYS_DEBUGGER = $(L4_KIP_OFFS_SYS_DEBUGGER) +L4_BID_PKG_CONFIG = $(PKG_CONFIG) +L4_BID_PKG_CONFIG_CALL = $(value BID_PKG_CONFIG) +L4_BID_PKG_CONFIG_FAILED = $(value BID_PKG_CONFIG_FAILED) + + +all:: + @echo -e $(EMPHSTART)"Creating $(L4DEF_FILE_MK)"$(EMPHSTOP) + @echo "# Definitions for 'make' from L4 BID" > $(L4DEF_FILE_MK) + @echo "# vim:se ft=make:" >> $(L4DEF_FILE_MK) + @echo "# --- Automatically created, do not modify ---" >> $(L4DEF_FILE_MK) + @: + @echo -e $(EMPHSTART)"Creating $(L4DEF_FILE_SH)"$(EMPHSTOP) + @echo "# Definitions for 'sh' from L4 BID" > $(L4DEF_FILE_SH) + @echo "# vim:se ft=sh:" >> $(L4DEF_FILE_SH) + @echo "# --- Automatically created, do not modify ---" >> $(L4DEF_FILE_SH) + @echo "" >> $(L4DEF_FILE_SH) + @echo "l4_bid_call_pkgconfig()" >> $(L4DEF_FILE_SH) + @echo "{" >> $(L4DEF_FILE_SH) + @echo " obj_base=\$$1; shift; " >> $(L4DEF_FILE_SH) + @echo " PKG_CONFIG_LIBDIR=\$$obj_base/pc PKG_CONFIG_PATH= \\" >> $(L4DEF_FILE_SH) + @echo " \$$L4_BID_PKG_CONFIG \\" >> $(L4DEF_FILE_SH) + @echo " --define-variable=incdir=\$$obj_base/include/contrib \\" >> $(L4DEF_FILE_SH) + @echo " \"\$$@\"" >> $(L4DEF_FILE_SH) + @echo "}" >> $(L4DEF_FILE_SH) + @echo "" >> $(L4DEF_FILE_SH) + @: + @$(call do_output_all,L4_SYSTEM) + @$(call do_output_all,L4_CC) + @$(call do_output_all,L4_CXX) + @$(call do_output_all,L4_CRT0_STATIC) + @$(call do_output_all,L4_CRTN_STATIC) + @$(call do_output_all,L4_LDFLAGS_LD_STATIC) + @$(call do_output_all,L4_LDFLAGS_GCC_STATIC) + @$(call do_output_all,L4_LDFLAGS_DYNAMIC_LINKER_LD) + @$(call do_output_all,L4_LDFLAGS_DYNAMIC_LINKER_GCC) + @$(call do_output_all,L4_LIBDIRS_R) + @$(call do_output_all,L4_LIBDIRS) + @$(call do_output_all,L4_CPPFLAGS) + @$(call do_output_all,L4_CFLAGS) + @$(call do_output_all,L4_CXXFLAGS) + @$(call do_output_all,L4_GCCLIB) + @$(call do_output_all,L4_GCCLIB_EH) + @$(call do_output_all,L4_LDS_stat_bin) + @$(call do_output_all,L4_BID_STACK_ADDR) + @$(call do_output_all,L4_BID_KIP_ADDR) + @$(call do_output_all,L4_BID_KIP_OFFS_SYS_INVOKE) + @$(call do_output_all,L4_BID_KIP_OFFS_SYS_DEBUGGER) + @$(call do_output_all,L4_BID_PKG_CONFIG) + @$(call do_output_mk,L4_BID_PKG_CONFIG_CALL) + @$(call do_output_mk,L4_BID_PKG_CONFIG_FAILED) + @$(foreach v,LIBCINCDIR REQUIRES_LIBS L4_LIBS CRT0 CRTN LDSCRIPT LDFLAGS, \ + $(call do_output_all,$(v)_all_static) $(call do_output_all,$(v)_all_shared)) +else +all:: +endif + +include $(L4DIR)/mk/prog.mk + +endif # called for static + +# ---------------------------------------------------- + +ifeq ($(CALLED_FOR),shared) + +MODE = shared + +ifneq ($(SYSTEM),) + +L4_LDFLAGS_LD_SHARED = $(filter-out -l%,$(BID_LDFLAGS_FOR_LINKING_LD)) +L4_LDFLAGS_GCC_SHARED = $(filter-out -l%,$(BID_LDFLAGS_FOR_LINKING_GCC)) +L4_LDS_so = $(LDS_so) +L4_LDS_dyn_bin = $(LDS_dyn_bin) + +all:: + @$(call do_output_all,L4_LDFLAGS_LD_SHARED) + @$(call do_output_all,L4_LDFLAGS_GCC_SHARED) + @$(call do_output_all,L4_LDS_so) + @$(call do_output_all,L4_LDS_dyn_bin) + +else +all:: +endif + +include $(L4DIR)/mk/prog.mk + +endif # called for shared + +# ---------------------------------------------------- + +ifeq ($(CALLED_FOR),sharedlib) + +ifneq ($(SYSTEM),) + +L4_CRT0_SO = $(CRT0) +L4_CRTN_SO = $(CRTN) + +all:: + @$(call do_output_all,L4_CRT0_SO) + @$(call do_output_all,L4_CRTN_SO) +else +all:: +endif + +include $(L4DIR)/mk/lib.mk + +endif # called for sharedlib diff --git a/l4/mk/idl.mk b/l4/mk/idl.mk new file mode 100644 index 00000000..5615a040 --- /dev/null +++ b/l4/mk/idl.mk @@ -0,0 +1,202 @@ +# -*- Makefile -*- +# +# DROPS (Dresden Realtime OPerating System) Component +# +# Makefile-Template for idl directories +# +# install.inc is used, see there for further documentation +# - from install.inc, we use the feature to install files +# to the local install directory on 'all' target. +# Therefore, we set INSTALLDIR_LOCAL and INSTALLFILE_LOCAL. +# Note that we changed INSTALLDIR_IDL_LOCAL AND INSTALLDIR_IDL +# binary.inc is used, see there for further documentation + +ifeq ($(origin _L4DIR_MK_IDL_MK),undefined) +_L4DIR_MK_IDL_MK=y + +ROLE = idl.mk + +DICE_REQ := --require="3.2.0" + +# define LOCAL_INSTALLDIR prior to including install.inc, where the install- +# rules are defined. Same for INSTALLDIR. +INSTALLDIR_IDL ?= $(DROPS_STDDIR)/include/$(ARCH)/$(L4API)/$(INSTALL_INC_PREFIX) +INSTALLDIR_IDL_LOCAL ?= $(OBJ_BASE)/include/$(ARCH)/$(L4API)/$(INSTALL_INC_PREFIX) +INSTALLFILE_IDL ?= $(INSTALL) -m 644 $(1) $(2) +INSTALLFILE_IDL_LOCAL ?= $(LN) -sf $(call absfilename,$(1)) $(2) + +INSTALLFILE = $(INSTALLFILE_IDL) +INSTALLDIR = $(INSTALLDIR_IDL) +INSTALLFILE_LOCAL = $(INSTALLFILE_IDL_LOCAL) +INSTALLDIR_LOCAL = $(INSTALLDIR_IDL_LOCAL) + +INSTALL_INC_PREFIX ?= l4/$(PKGNAME) + +# our default MODE is 'static' +MODE ?= static + +IDL_EXPORT_STUB ?= % +IDL_EXPORT_IDL ?= % + +include $(L4DIR)/mk/Makeconf +include $(L4DIR)/mk/binary.inc +$(GENERAL_D_LOC): $(L4DIR)/mk/idl.mk + +ifneq ($(SYSTEM),) # if we have a system, really build +####################################################### +# +# SYSTEM valid, we are in an OBJ- system subdir +# +####################################################### + +IDL_EXPORT_STUB ?= % +IDL_TYPE ?= dice + +# C++ specific rules +IDL_C = c +IDL_H = h +IDL_CPP = $(CC) +ifneq (,$(findstring BmCPP,$(IDL_FLAGS))) +IDL_C = cc +IDL_H = hh +IDL_CPP = $(CXX) +else +ifneq (,$(findstring Bmcpp,$(IDL_FLAGS))) +IDL_C = cc +IDL_H = hh +IDL_CPP = $(CXX) +endif +endif + +IDL_DEP = $(addprefix .,$(addsuffix .d,$(notdir $(IDL)))) +IDL_SKELETON_C = $(IDL:.idl=-server.$(IDL_C)) +IDL_SKELETON_H = $(IDL_SKELETON_C:.$(IDL_C)=.$(IDL_H)) +IDL_STUB_C = $(IDL:.idl=-client.$(IDL_C)) +IDL_STUB_H = $(IDL_STUB_C:.$(IDL_C)=.$(IDL_H)) +IDL_OPCODE_H = $(IDL:.idl=-sys.$(IDL_H)) + +IDL_FILES = $(IDL_SKELETON_C) $(IDL_SKELETON_H) $(IDL_STUB_C) $(IDL_STUB_H) \ + $(IDL_OPCODE_H) + +# Makro that expands to the list of generated files +# arg1 - name of the idl file. Path and extension will be stripped +IDL_FILES_EXPAND = $(addprefix $(notdir $(basename $(1))),-server.$(IDL_C) -server.$(IDL_H) -client.$(IDL_C) -client.$(IDL_H) -sys.$(IDL_H)) + +INSTALL_TARGET = $(patsubst %.idl,%-sys.$(IDL_H), \ + $(filter $(IDL_EXPORT_SKELETON) $(IDL_EXPORT_STUB),$(IDL)))\ + $(patsubst %.idl,%-server.$(IDL_H), \ + $(filter $(IDL_EXPORT_SKELETON),$(IDL))) \ + $(patsubst %.idl,%-client.$(IDL_H), \ + $(filter $(IDL_EXPORT_STUB), $(IDL))) + +all:: $(IDL_FILES) +.DELETE_ON_ERROR: + +# the dependencies for the generated files +DEPS += $(IDL_DEP) + +ifneq (,$(filter-out corba dice, $(IDL_TYPE))) +$(error IDL_TYPE is neither nor ) +endif + +# the IDL file is found one directory up +vpath %.idl $(SRC_DIR) + +# DICE mode +IDL_FLAGS += $(addprefix -P,$(CPPFLAGS)) +IDL_FLAGS += $(IDL_FLAGS_$(>.$(>.$() { \ + foreach (split) { \ + s|^\./||; $$src=$$_; \ + if(s|^ARCH-([^/]*)/L4API-([^/]*)/([^ ]*)$$|\1/\2/$(INSTALL_INC_PREFIX)/\3| ||\ + s|^ARCH-([^/]*)/([^ ]*)$$|\1/$(INSTALL_INC_PREFIX)/\2| || \ + s|^L4API-([^/]*)/([^ ]*)$$|\1/$(INSTALL_INC_PREFIX)/\2| || \ + s|^(/.*/)?(\S*)$$|$(INSTALL_INC_PREFIX)/\2|) { \ + $$src="$$srcdir/$$src" if $$src !~ /^\//; \ + $$dstdir=$$dst="$(if $(1),$(INSTALLDIR_LOCAL),$(INSTALLDIR))/$$_";\ + $$dstdir=~s|/[^/]*$$||; \ + -d $$dstdir || system("install","-$(if $(VERBOSE),,v)d",$$dstdir) && exit 1; \ + $(if $(1),$(do_link),$(do_inst)) \ + } \ + } \ + }' + +PC_FILENAMES ?= $(PC_FILENAME) +PC_FILES := $(foreach pcfile,$(PC_FILENAMES),$(OBJ_BASE)/pc/$(pcfile).pc) + +$(OBJ_BASE)/pc/%.pc: $(GENERAL_D_LOC) + $(VERBOSE)$(call generate_pcfile,$*,$@,$(PKGNAME),,$(call get_cont,REQUIRES_LIBS,$*)) + +headers:: + +all:: headers $(PC_FILES) + @$(TARGET_CMD) | $(call installscript,1) + +install:: + @$(INSTALL_LINK_MESSAGE) + @$(TARGET_CMD) | $(call installscript); + +cleanall:: + $(VERBOSE)$(RM) .general.d + +help:: + @echo " all - install files to $(INSTALLDIR_LOCAL)" + @echo " install - install files to $(INSTALLDIR)" + @echo " scrub - delete backup and temporary files" + @echo " clean - same as scrub" + @echo " cleanall - same as scrub" + @echo " help - this help" + +scrub clean cleanall:: + $(VERBOSE)$(SCRUB) diff --git a/l4/mk/install.inc b/l4/mk/install.inc new file mode 100644 index 00000000..f311ea97 --- /dev/null +++ b/l4/mk/install.inc @@ -0,0 +1,66 @@ +# -*- Makefile -*- +# vim:set ft=make: +# +# DROPS (Dresden Realtime OPerating System) Component +# +# Makefile-Include for install-rules +# +# This file is useful only when actually building files, thus if +# BUILD_ONE_ARCHITECTURE (see Makeconf) is defined. +# INSTALL_TARGET and INSTALL_TARGET_$(ARCH) contain the targets to be +# installed. If they are both empty, and NOTARGETSTOINSTALL is not set, +# they are set to TARGET and TARGET_$(ARCH). +# +# INSTALLDIR and INSTALLDIR_LOCAL is the dir the files will be installed +# in and must be set prior to including this file. INSTALLDIR is used by the +# target "install" and "INSTALLDIR_LOCAL" by the target "all". +# +# The target "all" is made depending on the installed files in +# INSTALLDIR_LOCAL. "install" on the files in INSTALLDIR. An other +# difference is that "all" results in using the variable +# $(INSTALLFILE_LOCAL) to install the files and "install" in using +# $(INSTALLFILE). This allows the difference between linking and actually +# copying (with stripping for bins). + +ifndef INSTALL_TARGET_$(OSYSTEM) +ifndef NOTARGETSTOINSTALL +INSTALL_TARGET?=$(TARGET) +endif +endif +INSTALL_TARGET += $(INSTALL_TARGET_$(OSYSTEM)) + +all:: $(addprefix $(INSTALLDIR_LOCAL)/,$(INSTALL_TARGET)) +install:: $(addprefix $(INSTALLDIR)/,$(INSTALL_TARGET)) + +# with prog.mk, we copy +ifeq ($(ROLE),prog.mk) +$(foreach f,$(INSTALL_TARGET),$(INSTALLDIR_LOCAL)/$(f)):$(INSTALLDIR_LOCAL)/%:% + @$(INSTALL_LOCAL_MESSAGE) + $(if $(INSTALLFILE_LOCAL),$(VERBOSE)$(INSTALL) -d $(dir $@)) + $(VERBOSE)$(call INSTALLFILE_LOCAL,$<,$@) +else +# with others, we symlink +# we check for each locally installed lib if the symlink is correct or if +# it's a shared lib since we need to always call the local install rule as +# we need to load shared libs to the target +.PHONY: $(addprefix $(INSTALLDIR_LOCAL)/,$(INSTALL_TARGET)) +$(foreach f,$(INSTALL_TARGET),$(INSTALLDIR_LOCAL)/$(f)):$(INSTALLDIR_LOCAL)/%:% + @$(if $(INSTALLFILE_LOCAL), \ + f="$@"; \ + if [ ! $< -ef $@ -o "$${f%%.so}" != "$$f" ] ; then \ + $(if $(INSTALL_LOCAL_MESSAGE),$(INSTALL_LOCAL_MESSAGE);) \ + $(INSTALL) -d $(dir $@); \ + $(call INSTALLFILE_LOCAL,$<,$@); \ + fi) +endif + +$(foreach f,$(INSTALL_TARGET),$(INSTALLDIR)/$(f)):$(INSTALLDIR)/%:% + @$(INSTALL_MESSAGE) + $(if $(INSTALLFILE),$(VERBOSE)$(INSTALL) -d $(dir $@)) + $(VERBOSE)$(call INSTALLFILE,$<,$@) + +# unconditionally install on "make install" +.PHONY: $(addprefix $(INSTALLDIR)/,$(INSTALL_TARGET)) + +.general.d: $(L4DIR)/mk/install.inc + diff --git a/l4/mk/lib.mk b/l4/mk/lib.mk new file mode 100644 index 00000000..043dbc01 --- /dev/null +++ b/l4/mk/lib.mk @@ -0,0 +1,166 @@ +# -*- Makefile -*- +# +# DROPS (Dresden Realtime OPerating System) Component +# +# Makefile-Template for library directories +# +# install.inc is used, see there for further documentation +# binary.inc is used, see there for further documentation + + +ifeq ($(origin _L4DIR_MK_LIB_MK),undefined) +_L4DIR_MK_LIB_MK=y + +ROLE = lib.mk + +# define INSTALLDIRs prior to including install.inc, where the install- +# rules are defined. Same for INSTALLDIR. +ifeq ($(MODE),host) +INSTALLDIR_LIB ?= $(DROPS_STDDIR)/lib/host +INSTALLDIR_LIB_LOCAL ?= $(OBJ_BASE)/lib/host +else +INSTALLDIR_LIB ?= $(DROPS_STDDIR)/lib/$(subst -,/,$(SYSTEM)) +INSTALLDIR_LIB_LOCAL ?= $(OBJ_BASE)/lib/$(subst -,/,$(SYSTEM)) +endif +INSTALLFILE_LIB ?= $(INSTALL) -m 644 $(1) $(2) +INSTALLFILE_LIB_LOCAL ?= $(LN) -sf $(call absfilename,$(1)) $(2) + +INSTALLFILE = $(INSTALLFILE_LIB) +INSTALLDIR = $(INSTALLDIR_LIB) +INSTALLFILE_LOCAL = $(INSTALLFILE_LIB_LOCAL) +INSTALLDIR_LOCAL = $(INSTALLDIR_LIB_LOCAL) + +# our mode +MODE ?= lib + +# sanity check for proper mode +ifneq ($(filter-out lib host,$(MODE)),) +$(error MODE=$(MODE) not possible when building libraries) +endif + +# all libraries are built using the wraped utcb-getter +CPPFLAGS += -DL4SYS_USE_UTCB_WRAP=1 + +# include all Makeconf.locals, define common rules/variables +include $(L4DIR)/mk/Makeconf +include $(L4DIR)/mk/binary.inc +$(GENERAL_D_LOC): $(L4DIR)/mk/lib.mk + +ifneq ($(SYSTEM),) # if we are a system, really build + +TARGET_LIB := $(TARGET) $(TARGET_$(OSYSTEM)) +TARGET_SHARED := $(filter %.so,$(TARGET_LIB)) +TARGET_STANDARD := $(filter-out %.so,$(TARGET_LIB)) + +TARGET_PROFILE := $(patsubst %.a,%.pr.a,\ + $(filter $(BUILD_PROFILE),$(TARGET_STANDARD))) +TARGET_PROFILE_SHARED := $(filter %.so,$(TARGET_PROFILE)) +TARGET_PIC := $(patsubst %.a,%.p.a,\ + $(filter $(BUILD_PIC),$(TARGET_STANDARD))) +TARGET_PROFILE_PIC := $(patsubst %.a,%.p.a,\ + $(filter $(BUILD_PIC),$(TARGET_PROFILE))) +TARGET += $(TARGET_$(OSYSTEM)) $(TARGET_PIC) +TARGET += $(TARGET_PROFILE) $(TARGET_PROFILE_SHARED) $(TARGET_PROFILE_PIC) + +# define some variables different for lib.mk and prog.mk +LDFLAGS += $(addprefix -L, $(PRIVATE_LIBDIR) $(PRIVATE_LIBDIR_$(OSYSTEM)) $(PRIVATE_LIBDIR_$@) $(PRIVATE_LIBDIR_$@_$(OSYSTEM))) +LDFLAGS += $(addprefix -L, $(L4LIBDIR)) +LDFLAGS += $(LIBCLIBDIR) +LDFLAGS_SO ?= -shared -nostdlib + +BID_LDFLAGS_FOR_LINKING_DYN_LD = $(LDFLAGS) +BID_LDFLAGS_FOR_GCC_DYN = $(filter -static -shared -nostdlib -Wl$(BID_COMMA)% -L% -l%,$(LDFLAGS)) +BID_LDFLAGS_FOR_LD_DYN = $(filter-out -static -shared -nostdlib -Wl$(BID_COMMA)% -L% -l%,$(LDFLAGS)) +BID_LDFLAGS_FOR_LINKING_DYN_GCC = $(addprefix -Wl$(BID_COMMA),$(BID_LDFLAGS_FOR_LD_DYN)) $(BID_LDFLAGS_FOR_GCC_DYN) + + +LDSCRIPT = $(LDS_so) +LDSCRIPT_INCR ?= /dev/null +CRT0 = $(CRTI_so) $(CRTBEGIN_so) $(CRT1_so) +CRTN = $(CRTN_so) + +# install.inc eventually defines rules for every target +include $(L4DIR)/mk/install.inc + +ifeq ($(NOTARGETSTOINSTALL),) +PC_LIBS ?= $(patsubst lib%.so,-l%,$(TARGET_SHARED) \ + $(patsubst lib%.a,-l%,$(TARGET_STANDARD))) + +PC_FILENAME ?= $(PKGNAME) +PC_FILENAMES ?= $(PC_FILENAME) + +PC_FILES := $(foreach pcfile,$(PC_FILENAMES),$(OBJ_BASE)/pc/$(pcfile).pc) + +# 1: basename +# 2: pcfilename +get_cont = $(if $($(1)_$(2)),$($(1)_$(2)),$($(1))) + +$(OBJ_BASE)/pc/%.pc: $(GENERAL_D_LOC) + $(if $(filter-out -l%,$(call get_cont,PC_LIBS,$*)),$(error PC_LIBS contains invalid library list: $(call get_cont,PC_LIBS,$*); Only -l statements allowed.),@true) + $(VERBOSE)$(call generate_pcfile,$*,$@,$(call get_cont,CONTRIB_INCDIR,$*),$(call get_cont,PC_LIBS,$*),$(call get_cont,REQUIRES_LIBS,$*)) + +all:: $(PC_FILES) + +endif + +DEPS += $(foreach file,$(TARGET), $(dir $(file)).$(notdir $(file)).d) + +$(filter-out $(LINK_INCR) %.so %.o.a %.o.pr.a, $(TARGET)):%.a: $(OBJS) + @$(AR_MESSAGE) + $(VERBOSE)[ -d "$(dir $@)" ] || $(MKDIR) $(dir $@) + $(VERBOSE)$(RM) $@ + $(VERBOSE)$(AR) crs $@ $(OBJS) + @$(BUILT_MESSAGE) + +# shared lib +$(filter %.so, $(TARGET)):%.so: $(OBJS) $(CRTN) $(CRT0) $(CRTP) $(LIBDEPS) + @$(LINK_SHARED_MESSAGE) + $(VERBOSE)[ -d "$(dir $@)" ] || $(MKDIR) $(dir $@) + $(VERBOSE)$(call MAKEDEP,$(LD)) $(LD) -m $(LD_EMULATION) \ + -o $@ $(LDFLAGS_SO) $(addprefix -T,$(LDSCRIPT)) $(CRTP) \ + $(OBJS) $(REQUIRES_LIBS_LIST) $(LDFLAGS) \ + $(GCCLIB_SO) $(GCCLIB_EH) $(CRTN) + @$(BUILT_MESSAGE) + +# build an object file (which looks like a lib to a later link-call), which +# is either later included as a whole or not at all (important for static +# constructors) +LINK_INCR_TARGETS = $(filter $(LINK_INCR) %.o.a %.o.pr.a, $(TARGET)) +$(LINK_INCR_TARGETS):%.a: $(OBJS) $(LIBDEPS) $(foreach x,$(LINK_INCR_TARGETS),$(LINK_INCR_ONLYGLOBSYMFILE_$(x))) + @$(LINK_PARTIAL_MESSAGE) + $(VERBOSE)[ -d "$(dir $@)" ] || $(MKDIR) $(dir $@) + $(VERBOSE)$(call MAKEDEP,$(LD)) $(LD) -m $(LD_EMULATION) \ + -T$(LDSCRIPT_INCR) \ + -o $@ -r $(OBJS) $(LDFLAGS) + $(if $(LINK_INCR_ONLYGLOBSYM_$@)$(LINK_INCR_ONLYGLOBSYMFILE_$@), \ + $(VERBOSE)$(OBJCOPY) \ + $(foreach f,$(LINK_INCR_ONLYGLOBSYMFILE_$@),--keep-global-symbols=$(f)) \ + $(foreach f,$(LINK_INCR_ONLYGLOBSYM_$@),-G $(f)) \ + $@) + @$(BUILT_MESSAGE) + +endif # architecture is defined, really build + +.PHONY: all clean cleanall config help install oldconfig txtconfig +-include $(DEPSVAR) +help:: + @echo " all - compile and install the libraries locally" +ifneq ($(SYSTEM),) + @echo " to $(INSTALLDIR_LOCAL)" +endif + @echo " install - compile and install the libraries globally" +ifneq ($(SYSTEM),) + @echo " to $(INSTALLDIR)" +endif + @echo " scrub - delete backup and temporary files" + @echo " clean - delete generated object files" + @echo " cleanall - delete all generated, backup and temporary files" + @echo " help - this help" + @echo +ifneq ($(SYSTEM),) + @echo " libraries are: $(TARGET)" +else + @echo " build for architectures: $(TARGET_SYSTEMS)" +endif + +endif # _L4DIR_MK_LIB_MK undefined diff --git a/l4/mk/makehelpers.inc b/l4/mk/makehelpers.inc new file mode 100644 index 00000000..60030cf3 --- /dev/null +++ b/l4/mk/makehelpers.inc @@ -0,0 +1,15 @@ +# -*- Makefile -*- +# vim:set ft=make: +# +# DROPS (Dresden Realtime OPerating System) Component +# +# Makefile-include to extract variables from Makefile-compatible files +# +# We use this file to browse doxygen files in the doc.mk rules. + +BID_print: + @echo $($(VAR)) +BID_printm: + @$(foreach v, $(VARS), echo '$(v)=$($(v))';) + +.PHONY: BID_print BID_printm diff --git a/l4/mk/modes.inc b/l4/mk/modes.inc new file mode 100644 index 00000000..8d2bda91 --- /dev/null +++ b/l4/mk/modes.inc @@ -0,0 +1,140 @@ +# -*- Makefile -*- +# vim:et:ts=8:ft=make: +# +# Makefile-Include for defining modes + +ifneq ($(L4_MULTITHREADED),) + $(error L4_MULTITHREADED is obsolete, just remove, reentrance is default now, you might want to add 'libpthread' to REQUIRES_LIBS) +endif + +ifneq ($(MODE_USE_C),) + $(error MODE_USE_C is obsolete, add l4re_c and/or l4re_c-util to REQUIRES_LIBS as needed) +endif + +CRTBEGIN_so = $(if $(GCCIS_sparc_leon),$(GCCLIB_FILE_crtbegin.o),$(GCCLIB_FILE_crtbeginS.o)) +CRTBEGIN_stat_bin = $(if $(GCCIS_sparc_leon),$(GCCLIB_FILE_crtbegin.o),$(GCCLIB_FILE_crtbeginT.o)) + +CRTBEGIN_dyn_bin = $(GCCLIB_FILE_crtbegin.o) + +CRTEND_so = $(GCCLIB_FILE_crtendS.o) +CRTEND_dyn_bin = $(GCCLIB_FILE_crtend.o) +CRTEND_stat_bin = $(GCCLIB_FILE_crtend.o) + + +CRT1_so = +CRT1_dyn_bin = $(call findfile,crt1.o,$(L4LIBDIR)) +CRT1_stat_bin = $(call findfile,crt1.o,$(L4LIBDIR)) + +CRTI_so = $(call findfile,crti.s.o,$(L4LIBDIR)) +CRTI_dyn_bin = $(call findfile,crti.o,$(L4LIBDIR)) +CRTI_stat_bin = $(call findfile,crti.o,$(L4LIBDIR)) + +CRTN_so = $(if $(GCCIS_sparc_leon),,$(CRTEND_so)) $(call findfile,crtn.s.o,$(L4LIBDIR)) +CRTN_dyn_bin = $(CRTEND_dyn_bin) $(call findfile,crtn.o,$(L4LIBDIR)) +CRTN_stat_bin = $(CRTEND_stat_bin) $(call findfile,crtn.o,$(L4LIBDIR)) + +LDS_so = $(call findfile,main_rel.ld,$(L4LIBDIR)) +LDS_dyn_bin = $(call findfile,main_dyn.ld,$(L4LIBDIR)) +LDS_stat_bin = $(call findfile,main_stat.ld,$(L4LIBDIR)) + + +LIBC_INCLUDE = -nostdinc \ + -I$(OBJ_BASE)/include/$(ARCH)/uclibc \ + -I$(OBJ_BASE)/include/uclibc \ + -I$(OBJ_BASE)/include/contrib/libstdc++-v3 \ + $(if $(CONFIG_USE_DROPS_STDDIR), \ + -I$(DROPS_STDDIR)/include/$(ARCH)/uclibc \ + -I$(DROPS_STDDIR)/include/uclibc \ + -I$(DROPS_STDDIR)/include/contrib/libstdc++-v3,) \ + $(I_GCCINCDIR) + +############################################################################# + +################################ +# sigma0 mode +################################ + +BID_SUPPORTED_all_sigma0 = y +LIBCINCDIR_all_sigma0 = $(LIBC_INCLUDE) +REQUIRES_LIBS_all_sigma0 = +L4_LIBS_all_sigma0 = -static -nostdlib \ + $(GCCLIB) $(GCCLIB_EH) -lcrt0 \ + $(EXTRA_LIBS) +CRT0_all_sigma0 = $(CRTI_stat_bin) $(CRTBEGIN_stat_bin) $(CRT1_stat_bin) +CRTN_all_sigma0 = $(CRTN_stat_bin) +LDSCRIPT_all_sigma0 = $(LDS_stat_bin) +LDFLAGS_all_sigma0 = -Bstatic + + +################################ +# static mode +################################ + +BID_SUPPORTED_all_static = y +LIBCINCDIR_all_static = $(LIBC_INCLUDE) +REQUIRES_LIBS_all_static = stdlibs +L4_LIBS_all_static = -static -nostdlib $(GCCLIB) $(GCCLIB_EH) \ + $(EXTRA_LIBS) +CRT0_all_static = $(CRTI_stat_bin) $(CRTBEGIN_stat_bin) $(CRT1_stat_bin) +CRTN_all_static = $(CRTN_stat_bin) +LDSCRIPT_all_static = $(LDS_stat_bin) +LDFLAGS_all_static = -Bstatic + +##################################### +# shared mode -- programs are linked against shared libs +##################################### +BID_SUPPORTED_all_shared = y +LIBCINCDIR_all_shared = $(LIBC_INCLUDE) +CRT0_all_shared = $(CRTI_dyn_bin) $(CRTBEGIN_dyn_bin) $(CRT1_dyn_bin) +CRTN_all_shared = $(CRTN_dyn_bin) +LDSCRIPT_all_shared = $(LDS_dyn_bin) +REQUIRES_LIBS_all_shared = stdlibs-sh +L4_LIBS_all_shared += -nostdlib -luc_c_nonshared.p \ + $(GCCLIB_SO) $(GCCLIB_EH) \ + $(EXTRA_LIBS) +LDFLAGS_all_shared = --eh-frame-hdr + +################################ +# l4linux mode +################################ + +BID_SUPPORTED_all_l4linux = y +LIBCINCDIR_all_l4linux = +REQUIRES_LIBS_all_l4linux = +L4_LIBS_all_l4linux = -l4re-util \ + -l4lx-re.o \ + -ll4sys-l4x -l4re \ + $(EXTRA_LIBS) \ + -ll4util \ + -lcxx_base -lcxx_io \ + -lcxx_libc_io +CRT0_all_l4linux = +CRTN_all_l4linux = +LDSCRIPT_all_l4linux = +LDFLAGS_all_l4linux = + + +##################################### +# lib mode -- options when building libs +##################################### + +BID_SUPPORTED_all_lib = y +LIBCINCDIR_all_lib = $(LIBC_INCLUDE) +CRT0_all_lib = $(CRTI_dyn_bin) $(CRTBEGIN_dyn_bin) $(CRT1_dyn_bin) +CRTN_all_lib = $(CRTN_dyn_bin) +LDSCRIPT_all_lib = $(LDS_so) +LDFLAGS_all_lib = --eh-frame-hdr + + +##################################### +# host mode -- no L4 specifics +##################################### + +BID_SUPPORTED_all_host = y +LIBCINCDIR_all_host = +REQUIRES_LIBS_all_host = +L4_LIBS_all_host = +CRT0_all_host = +CRTN_all_host = +LDSCRIPT_all_host = +LDFLAGS_all_host = diff --git a/l4/mk/pkgdeps b/l4/mk/pkgdeps new file mode 100755 index 00000000..e712a7c2 --- /dev/null +++ b/l4/mk/pkgdeps @@ -0,0 +1,706 @@ +#! /usr/bin/perl -W + +use strict; + +my $controlfile = 'Control'; +my $controlfile_local = 'Control.local'; +my %pkgs; +my %requires; +my %provided; +my %maintainer; +my %srcpkgs; +my %aliases; +my %disabled; + +my $pcfiledir_for_aliases; + +sub set_pcfiledir_for_aliases($) +{ + $pcfiledir_for_aliases = shift; +} + +sub write_alias_pcfile($@) +{ + my $alias = shift; + + die "Path for pc-files not set, use '-P dir'" + unless defined $pcfiledir_for_aliases; + + open(U, ">$pcfiledir_for_aliases/$alias.pc") + || die "Cannot create '$pcfiledir_for_aliases/$alias.pc': $!"; + + print U "Name: $alias\n". + "Version: 0\n". + "Description: Alias Dependency Package\n". + "Requires: ".join(' ', @_)."\n"; + + close U; +} + +sub add_alias($$@) +{ + my $alias = shift; + my $do_write_pc_file = shift; + + $requires{$alias} = [ @_ ]; + $provided{$alias} = $alias; + $aliases{$alias} = 1; + + write_alias_pcfile($alias, @_) + if $do_write_pc_file; +} + +sub is_alias($) +{ + my $a = shift; + defined $aliases{$a}; +} + +sub read_aliases_dir($$) +{ + my $dir = shift; + my $do_write_pc_file = shift; + + opendir(A, $dir) || die "Cannot open directory '$dir': $!"; + + foreach my $file (sort readdir(A)) + { + next if $file =~ /^\./; + next if -d $file; + + open(F, "$dir/$file") || die "Cannot open file '$dir/$file': $!"; + my $line = 0; + while () + { + $line++; + chomp; + s/\#.*//; + s/^\s+$//; + next if /^$/; + if (/^\s*(\S+)\s*:?=\s*(.+)/) + { + add_alias($1, $do_write_pc_file, split(/\s+/, $2)); + } + else + { + die "Invalid syntax in $dir/$file:$line"; + } + } + + close F; + } + + closedir A; +} + +sub scan_for_provided_pkg_configs($$$) +{ + my $path = shift; + my $pkg = shift; + my $scan_all = shift; + + $disabled{$pkg} = 1 if -e "$path/broken" or -e "$path/obsolete"; + + return if not $scan_all and $disabled{$pkg}; + + foreach my $ctfn ($controlfile, $controlfile_local) + { + if (open(A, "$path/$ctfn")) + { + my $o; + { + undef local $/; + $o = ; + } + + $o =~ s/#.*$//gm; + $o =~ s/\n[ \t]+/ /smg; + + while (1) + { + if ($o =~ /^requires:[ \t]*(.+)$/im) + { + push @{$requires{$pkg}}, split /\s+/, $1; + } + elsif ($o =~ /^provides:[ \t]*(.+)$/im) + { + $provided{$_} = $pkg foreach (split /\s+/, $1); + } + elsif ($o =~ /^source-pkg:[ \t]*(.+)$/im) + { + push @{$srcpkgs{$pkg}}, split /\s+/, $1; + } + elsif ($o =~ /^maintainer:[ \t]*(.+)$/im) + { + push @{$maintainer{$pkg}}, split /[,\s]+/, $1; + } + else + { + last; + } + $o = $`."\n".$'; + } + + close A; + } + } +} + +sub scan_files($$) +{ + my $base_path = shift; + my $scan_all = shift; + my $dh; + opendir($dh, $base_path) || die "Cannot readdir in '$base_path': $!"; + + foreach (readdir($dh)) { + my $path = "$base_path/$_"; + $path = readlink $path if -l $path; + next unless -d $path; + next if /^\./ or /^CVS$/; + $pkgs{$_} = 1; + scan_for_provided_pkg_configs($path, $_, $scan_all); + } + closedir $dh; +} + +sub generate_dep_makefile($) +{ + scan_files(shift, 0); + my $error_count = 0; + + print "# Automatically generated Makefile for dependencies\n"; + print "#\n"; + print "# ", `date`; + print "#\n"; + + my %p = %provided; + + foreach my $a (sort keys %requires) + { + print "$a:"; + delete $p{$a}; + foreach (sort @{$requires{$a}}) + { + if (defined $provided{$_}) + { + print " $provided{$_}"; + } + else + { + if ($disabled{$_}) + { + print STDERR "ERROR: Package providing \"$_\" disabled and required by \"$a\".\n"; + $error_count++; + } + elsif (!is_alias($a)) + { + print STDERR "ERROR: Package providing \"$_\" not found as required by \"$a\".\n"; + $error_count++; + } + } + } + print "\n"; + } + + # delete those packages that do not have dependencies, to avoid circular + # 'make' deps + foreach (keys %p) + { + delete $p{$_} if $_ eq $p{$_}; + } + + print "\n"; + print "$_: $p{$_}\n" foreach sort keys %p; + + print "\n.PHONY: ".join(' ', sort keys %aliases).' ' + .join(' ', sort keys %p)."\n" if %aliases or %p; + + if ($error_count) + { + print STDERR "PANIC: Detected $error_count dependency error(s).\n"; + exit(1); + } +} + +sub figure_out_pkg_dependecies(@) +{ + my %newpkgs; + foreach (@_) + { + if (not defined $requires{$_}) + { + if (not defined $provided{$_} and not is_alias($_)) + { + print STDERR "WARNING: '$_' does not exist (forgot -A?).\n"; + next; + } + $newpkgs{$provided{$_}} = 1; + } + else + { + $newpkgs{$_} = 1; + } + } + + my %pkgh; + my $again; + # get requires of package(s) + do + { + foreach (keys %newpkgs) + { + $newpkgs{$_} = 1 foreach @{$srcpkgs{$_}}; + } + + my %rdeps; + $again = 0; + foreach my $p (keys %newpkgs) + { + if ($requires{$p}) + { + $rdeps{$_} = 1 foreach @{$requires{$p}}; + } + $pkgh{$p} = 1; + } + %newpkgs = (); + if (%rdeps) + { + # translate to packages providing those + foreach (keys %rdeps) + { + my $p = $_; + $p = $provided{$p} if defined $provided{$p}; + $newpkgs{$p} = 1 unless defined $pkgh{$p}; + } + $again = 1; + } + } + while ($again); + + # remove aliases + foreach my $p (keys %pkgh) + { + delete $pkgh{$p} if is_alias($p); + } + + keys %pkgh; +} + +# this sub figures out which packages depend on the given ones +sub figure_out_dependant_pkgs(@) +{ + my %h; + my %r; + $h{$_} = 1 foreach @_; + + while (1) + { + my %tmp = %r; + foreach my $a (keys %requires) + { + foreach (sort @{$requires{$a}}) + { + my $p = $_; + $p = $provided{$_} if defined $provided{$_}; + $tmp{$a} = 1 if defined $h{$p} or $tmp{$p}; + } + } + + last if scalar keys %r == scalar keys %tmp; + %r = %tmp; + } + + # remove aliases + foreach my $p (keys %r) + { + delete $r{$p} if is_alias($p); + } + + %r; +} + +sub generate_dot_file_all($$) +{ + my $base_path = shift; + my $output = shift; + scan_files($base_path, 1) if defined $base_path; + my $error_count = 0; + + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) + = localtime(time); + $year += 1900; + $mon++; + + open O, $output or die "Cannot open '$output': $!"; + + print O "# Automatically generated\n"; + print O "#\n"; + print O "# ", `date`; + print O "#\n"; + print O "digraph dep {\n"; + print O " graph [ label = \"\\nSource based package dependency\\n", + sprintf("%02d. %02d. %04d, %02d:%02d \"];\n", $mday, $mon, $year, $hour, $min); + + my %disabled_because_of_deps = figure_out_dependant_pkgs(%disabled); + + foreach my $a (sort keys %requires) + { + print O " \"$a\" [shape=septagon]\n" if is_alias($a); + foreach (sort @{$requires{$a}}) + { + if (defined $provided{$_}) + { + print O " \"$a\" -> \"$provided{$_}\" [color=black];\n"; + } + elsif (not defined $disabled{$a} and not is_alias($a)) + { + print STDERR "ERROR: Package providing \"$_\" not found as required by \"$a\".\n"; + $error_count++; + } + } + print O "\n"; + } + + foreach my $a (sort keys %requires) + { + if (defined $disabled{$a}) + { + print O " \"$a\" [style=filled, fillcolor=red];\n"; + } + elsif (defined $disabled_because_of_deps{$a}) + { + print O " \"$a\" [style=filled, fillcolor=sandybrown];\n"; + } + } + + print O "}\n"; + + close O; + + if ($error_count) + { + print STDERR "PANIC: Detected $error_count dependency error(s).\n"; + exit(1); + } +} + +sub generate_overview_set($$) +{ + my $base_path = shift; + my $output_dir = shift; + + die "Output directory not given." unless defined $output_dir; + + scan_files($base_path, 1); + my $error_count = 0; + + my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) + = localtime(time); + $year += 1900; + $mon++; + my $datestring = sprintf("%02d. %02d. %04d, %02d:%02d", + $mday, $mon, $year, $hour, $min); + + generate_dot_file_all(undef, "| tred | dot -Tsvg -o $output_dir/all.svg"); + + open INDEX, ">$output_dir/index.html" or die "Cannot create $output_dir/index.html: $!"; + print INDEX < + + TUD:OS package dependency overview + + +

TUD:OS package dependency overview

+

Generated: $datestring

+

+ Legend of overview graphs: +

    +
  • Red: Broken package
  • +
  • Lightred: Package broken because it depends on broken package but is itself not broken
  • +
+ Legend of package graphs: +
    +
  • Blue: The package itself
  • +
  • Green: Reverse dependency of package
  • +
  • Yellow: Dependency of package
  • +
+

+

General overview

+ +EOFOO + + foreach my $pkg (sort keys %pkgs) + { + open F, "| tred | dot -Tsvg -o $output_dir/p_$pkg.svg" || die "Cannot open $output_dir/p_$pkg.svg: $!"; + #open F, ">$output_dir/pkg_$pkg.dot" || die "Cannot open pkg_$pkg.dot: $!"; + + print F "# Automatically generated\n"; + print F "#\n"; + print F "# ", `date`; + print F "#\n"; + print F "digraph dep {\n"; + print F " graph [ label = \"\\nSource based package dependency for package '$pkg'\\n", + "$datestring\"];\n"; + + foreach my $a (sort keys %requires) + { + print F " \"$a\" [shape=septagon]\n" if is_alias($a); + foreach (sort @{$requires{$a}}) + { + if (defined $provided{$_}) + { + print F " \"$a\" -> \"$provided{$_}\" [color=black];\n"; + } + elsif (not defined $disabled{$a} and not is_alias($a)) + { + print STDERR "ERROR: Package providing \"$_\" not found as required by \"$a\".\n"; + $error_count++; + } + } + print F "\n"; + } + + my %rev_deps = figure_out_dependant_pkgs($pkg); + my @deps = figure_out_pkg_dependecies($pkg); + + print F " \"$_\" [style=filled, fillcolor=seagreen1];\n" + foreach keys %rev_deps; + print F " \"$_\" [style=filled, fillcolor=yellow1];\n" + foreach @deps; + + print F " \"$pkg\" [style=filled, fillcolor=dodgerblue];\n"; + + print F "}\n"; + close F; + + # Generate HTML content + + print INDEX "\n"; + } + + print INDEX "
PackageMaintainer(s)DepsReverse Deps
$pkg\n"; + print INDEX defined $maintainer{$pkg} + ? (join " ", map { "$_" } @{$maintainer{$pkg}}) : "none"; + print INDEX "\n"; + foreach my $a (sort @deps) + { + print INDEX " $a "; + } + print INDEX "\n"; + foreach my $a (sort keys %rev_deps) + { + print INDEX " $a "; + } + print INDEX "
\n"; + print INDEX "\n\n"; + close INDEX; + + if ($error_count) + { + print STDERR "PANIC: Detected $error_count dependency error(s).\n"; + exit(1); + } +} + +sub check_control($) +{ + my $base_path = shift; + + scan_files($base_path, 0); + + foreach my $p (keys %pkgs) + { + my %pc_filenames; + my @libs_wo_pcfile; + open(F, "find '$base_path/$p' -name Makefile -o -name Make.rules |") + || die "Cannot start find: $!"; + while (my $file = ) + { + my $is_lib_build; + my $found_pc_filename; + my $not_public; + chomp $file; + open(M, $file) || die "Cannot open \"$_\": $!"; + while () + { + chomp; + $found_pc_filename = $1 + if /^\s*PC_FILENAME\s*:?=\s*(.+)\s*$/; + $is_lib_build = 1 + if /^\s*include\s+.+\/mk\/lib.mk\s*$/; + $not_public = 1 + if /^\s*NOTARGETSTOINSTALL\s*:?=\s/; + } + close M; + + print "ERROR: $p: Not public but PC_FILENAME given\n" + if defined $not_public and defined $found_pc_filename; + + unless (defined $not_public) + { + if (defined $found_pc_filename) + { + $found_pc_filename =~ s/\$\(PKGNAME\)/$p/; + $pc_filenames{$found_pc_filename} = 1; + } + elsif (defined $is_lib_build) + { + $pc_filenames{$p} = 1; + push @libs_wo_pcfile, $file; + } + } + } + + foreach my $a (keys %pc_filenames) + { + print "ERROR: $p: Missing in provides '$a'\n" + if not defined $provided{$a} or $provided{$a} ne $p; + } + + foreach my $a (keys %provided) + { + print "ERROR: $p: Provide not found as PC_FILENAME '$a'\n" + if $provided{$a} eq $p and not defined $pc_filenames{$a}; + } + + print "ERROR: $p: Contains multiple libs without PC_FILENAME:\n", + " ", join("\n ", @libs_wo_pcfile), "\n" + if scalar @libs_wo_pcfile > 1; + + close F; + } + + print "TODO: check if something is provided by multiple packages\n"; +} + + +sub show_pkg_deps($$@) +{ + my $base_path = shift; + my $prefix = shift; + scan_files($base_path, 0); + + my @p = figure_out_pkg_dependecies(@_); + + print join("\n", map { "$prefix$_" } sort @p), "\n" if $prefix; + print join(' ', sort @p), "\n" unless $prefix; +} + +sub show_pkg_deps_and_rdeps($$@) +{ + my $base_path = shift; + my $prefix = shift; + scan_files($base_path, 0); + + my %r = figure_out_dependant_pkgs(@_); + my @p = figure_out_pkg_dependecies(@_, keys %r); + + print join("\n", map { "$prefix$_" } sort @p), "\n" if $prefix; + print join(' ', sort @p), "\n" unless $prefix; +} + +sub show_maintainer($@) +{ + scan_files(shift, 1); + + if (@_) + { + my %m; + + foreach (@_) + { + if ($maintainer{$_}) + { + $m{$_}++ foreach @{$maintainer{$_}}; + } + else + { + $m{'NO MAINTAINER'} = 1; + } + } + + print join(", ", keys %m), "\n"; + } + else + { + my %m; + foreach (keys %pkgs) + { + if ($maintainer{$_}) + { + print "$_: ", join(', ', @{$maintainer{$_}}), "\n"; + $m{$_}++ foreach @{$maintainer{$_}}; + } + else + { + print "$_: NO MAINTAINER\n"; + } + } + print "Stats:\n", join("\n", map { sprintf "%3d: %s", $m{$_}, $_ } sort { $m{$b} <=> $m{$a} } keys %m), "\n"; + } +} + + +sub smooth_control_file($$) +{ + my $path = shift; + my $pkg = shift; + + scan_for_provided_pkg_configs($path, $pkg, 1); + + print "Provides: ".join(' ', keys %provided)."\n"; + print "Requires: ".join(' ', @{$requires{$pkg}})."\n"; +} + +# a bit of hand-crafted option parsing, if it gets more use getopt +my @aliases_dirs; +while (1) + { + last unless defined $ARGV[0]; + if ($ARGV[0] eq '-A') + { + shift; + push @aliases_dirs, shift; + } + elsif ($ARGV[0] eq '-P') + { + shift; + set_pcfiledir_for_aliases(shift), + } + else + { + last; + } + } + +my $cmd = $ARGV[0]; +my $base_path = $ARGV[1]; + +die "Missing arguments" + if not defined $cmd or not defined $base_path; + +read_aliases_dir($_, $cmd eq 'generate') foreach @aliases_dirs; + +if ($cmd eq 'generate') { + generate_dep_makefile($base_path); +} elsif ($cmd eq 'dot') { + generate_dot_file_all($base_path, '>-'); +} elsif ($cmd eq 'overviewset') { + generate_overview_set($base_path, $ARGV[2]); +} elsif ($cmd eq 'pkgdeps') { + show_pkg_deps($base_path, undef, @ARGV[2 .. $#ARGV]); +} elsif ($cmd eq 'pkgdepspath') { + show_pkg_deps($base_path, $ARGV[2], @ARGV[3 .. $#ARGV]); +} elsif ($cmd eq 'pkgdepsandrdeps') { + show_pkg_deps_and_rdeps($base_path, undef, @ARGV[2 .. $#ARGV]); +} elsif ($cmd eq 'collect') { + die "Missing argument" unless defined $ARGV[2]; + smooth_control_file("$base_path/$ARGV[2]", $ARGV[2]); +} elsif ($cmd eq 'maintainer') { + show_maintainer($base_path, @ARGV[2 .. $#ARGV]); +} elsif ($cmd eq 'check') { + check_control($base_path); +} else { + die "Invalid command '$cmd'"; +} diff --git a/l4/mk/platforms/beagleboard.conf b/l4/mk/platforms/beagleboard.conf new file mode 100644 index 00000000..e38257dd --- /dev/null +++ b/l4/mk/platforms/beagleboard.conf @@ -0,0 +1,4 @@ +PLATFORM_NAME = "Beagleboard" +PLATFORM_ARCH = arm +PLATFORM_RAM_BASE = 0x80000000 +PLATFORM_RAM_SIZE_MB = 128 diff --git a/l4/mk/platforms/imx21.conf b/l4/mk/platforms/imx21.conf new file mode 100644 index 00000000..165b09bd --- /dev/null +++ b/l4/mk/platforms/imx21.conf @@ -0,0 +1,4 @@ +PLATFORM_NAME = "Freescale i.MX21" +PLATFORM_ARCH = arm +PLATFORM_RAM_BASE = 0xc0000000 +PLATFORM_RAM_SIZE_MB = 64 diff --git a/l4/mk/platforms/imx35.conf b/l4/mk/platforms/imx35.conf new file mode 100644 index 00000000..860b6d62 --- /dev/null +++ b/l4/mk/platforms/imx35.conf @@ -0,0 +1,4 @@ +PLATFORM_NAME = "Freescale i.MX35" +PLATFORM_ARCH = arm +PLATFORM_RAM_BASE = 0x80000000 +PLATFORM_RAM_SIZE_MB = 128 diff --git a/l4/mk/platforms/imx51.conf b/l4/mk/platforms/imx51.conf new file mode 100644 index 00000000..a5ec04cc --- /dev/null +++ b/l4/mk/platforms/imx51.conf @@ -0,0 +1,4 @@ +PLATFORM_NAME = "Freescale i.MX51" +PLATFORM_ARCH = arm +PLATFORM_RAM_BASE = 0x90000000 +PLATFORM_RAM_SIZE_MB = 512 diff --git a/l4/mk/platforms/integrator.conf b/l4/mk/platforms/integrator.conf new file mode 100644 index 00000000..afd28b74 --- /dev/null +++ b/l4/mk/platforms/integrator.conf @@ -0,0 +1,4 @@ +PLATFORM_NAME = "ARM Integrator" +PLATFORM_ARCH = arm +PLATFORM_RAM_BASE = 0 +PLATFORM_RAM_SIZE_MB = 256 diff --git a/l4/mk/platforms/kirkwood.conf b/l4/mk/platforms/kirkwood.conf new file mode 100644 index 00000000..736b5660 --- /dev/null +++ b/l4/mk/platforms/kirkwood.conf @@ -0,0 +1,4 @@ +PLATFORM_NAME = "Marvell Kirkwood" +PLATFORM_ARCH = arm +PLATFORM_RAM_BASE = 0 +PLATFORM_RAM_SIZE_MB = 128 diff --git a/l4/mk/platforms/leon3.conf b/l4/mk/platforms/leon3.conf new file mode 100644 index 00000000..34fd0d6c --- /dev/null +++ b/l4/mk/platforms/leon3.conf @@ -0,0 +1,3 @@ +PLATFORM_NAME = "Sparc Leon3" +PLATFORM_ARCH = sparc +PLATFORM_RAM_BASE = 0x40000000 diff --git a/l4/mk/platforms/mpc5200.conf b/l4/mk/platforms/mpc5200.conf new file mode 100644 index 00000000..6442295f --- /dev/null +++ b/l4/mk/platforms/mpc5200.conf @@ -0,0 +1,4 @@ +PLATFORM_NAME = "MPC5200" +PLATFORM_ARCH = ppc32 +PLATFORM_RAM_BASE = 0 +PLATFORM_RAM_SIZE_MB = 64 diff --git a/l4/mk/platforms/omap3_am33xx.conf b/l4/mk/platforms/omap3_am33xx.conf new file mode 100644 index 00000000..3a6f6493 --- /dev/null +++ b/l4/mk/platforms/omap3_am33xx.conf @@ -0,0 +1,4 @@ +PLATFORM_NAME = "TI OMAP AM33xx" +PLATFORM_ARCH = arm +PLATFORM_RAM_BASE = 0x80000000 +PLATFORM_RAM_SIZE_MB = 256 diff --git a/l4/mk/platforms/omap3evm.conf b/l4/mk/platforms/omap3evm.conf new file mode 100644 index 00000000..d2af5f14 --- /dev/null +++ b/l4/mk/platforms/omap3evm.conf @@ -0,0 +1,4 @@ +PLATFORM_NAME = "TI OMAP3EVM" +PLATFORM_ARCH = arm +PLATFORM_RAM_BASE = 0x80000000 +PLATFORM_RAM_SIZE_MB = 128 diff --git a/l4/mk/platforms/pandaboard.conf b/l4/mk/platforms/pandaboard.conf new file mode 100644 index 00000000..d61cdd7c --- /dev/null +++ b/l4/mk/platforms/pandaboard.conf @@ -0,0 +1,4 @@ +PLATFORM_NAME = "Pandaboard" +PLATFORM_ARCH = arm +PLATFORM_RAM_BASE = 0x80000000 +PLATFORM_RAM_SIZE_MB = 512 diff --git a/l4/mk/platforms/pc.conf b/l4/mk/platforms/pc.conf new file mode 100644 index 00000000..fcd8800e --- /dev/null +++ b/l4/mk/platforms/pc.conf @@ -0,0 +1,3 @@ +PLATFORM_NAME = "PC" +PLATFORM_ARCH = x86 amd64 +PLATFORM_RAM_BASE = 0 diff --git a/l4/mk/platforms/rv.conf b/l4/mk/platforms/rv.conf new file mode 100644 index 00000000..592de9c3 --- /dev/null +++ b/l4/mk/platforms/rv.conf @@ -0,0 +1,4 @@ +PLATFORM_NAME = "ARM Realview (Generic)" +PLATFORM_ARCH = arm +PLATFORM_RAM_BASE = 0 +PLATFORM_RAM_SIZE_MB = 256 diff --git a/l4/mk/platforms/rv_pbx.conf b/l4/mk/platforms/rv_pbx.conf new file mode 100644 index 00000000..4a31f583 --- /dev/null +++ b/l4/mk/platforms/rv_pbx.conf @@ -0,0 +1,4 @@ +PLATFORM_NAME = "ARM Realview PBX" +PLATFORM_ARCH = arm +PLATFORM_RAM_BASE = 0x70000000 +PLATFORM_RAM_SIZE_MB = 256 diff --git a/l4/mk/platforms/rv_vexpress.conf b/l4/mk/platforms/rv_vexpress.conf new file mode 100644 index 00000000..df23d4f0 --- /dev/null +++ b/l4/mk/platforms/rv_vexpress.conf @@ -0,0 +1,4 @@ +PLATFORM_NAME = "ARM Versatile Express" +PLATFORM_ARCH = arm +PLATFORM_RAM_BASE = 0x60000000 +PLATFORM_RAM_SIZE_MB = 256 diff --git a/l4/mk/platforms/tegra2.conf b/l4/mk/platforms/tegra2.conf new file mode 100644 index 00000000..4b857d34 --- /dev/null +++ b/l4/mk/platforms/tegra2.conf @@ -0,0 +1,3 @@ +PLATFORM_NAME = "Nvidia Tegra 2" +PLATFORM_ARCH = arm +PLATFORM_RAM_BASE = 0 diff --git a/l4/mk/prog.mk b/l4/mk/prog.mk new file mode 100644 index 00000000..4726be76 --- /dev/null +++ b/l4/mk/prog.mk @@ -0,0 +1,204 @@ +# -*- Makefile -*- +# +# DROPS (Dresden Realtime OPerating System) Component +# +# Makefile-Template for binary directories +# +# Makeconf is used, see there for further documentation +# install.inc is used, see there for further documentation +# binary.inc is used, see there for further documentation + +ifeq ($(origin _L4DIR_MK_PROG_MK),undefined) +_L4DIR_MK_PROG_MK=y + +ROLE = prog.mk + +include $(L4DIR)/mk/Makeconf +$(GENERAL_D_LOC): $(L4DIR)/mk/prog.mk + +# define INSTALLDIRs prior to including install.inc, where the install- +# rules are defined. +ifeq ($(MODE),host) +INSTALLDIR_BIN ?= $(DROPS_STDDIR)/bin/host +INSTALLDIR_BIN_LOCAL ?= $(OBJ_BASE)/bin/host +else +INSTALLDIR_BIN ?= $(DROPS_STDDIR)/bin/$(subst -,/,$(SYSTEM)) +INSTALLDIR_BIN_LOCAL ?= $(OBJ_BASE)/bin/$(subst -,/,$(SYSTEM)) +endif +ifeq ($(CONFIG_BID_STRIP_PROGS),y) +INSTALLFILE_BIN ?= $(STRIP) --strip-unneeded $(1) -o $(2) && \ + chmod 755 $(2) +INSTALLFILE_BIN_LOCAL ?= $(STRIP) --strip-unneeded $(1) -o $(2) && \ + chmod 755 $(2) +else +INSTALLFILE_BIN ?= $(INSTALL) -m 755 $(1) $(2) +INSTALLFILE_BIN_LOCAL ?= $(INSTALL) -m 755 $(1) $(2) +endif + +INSTALLFILE = $(INSTALLFILE_BIN) +INSTALLDIR = $(INSTALLDIR_BIN) +INSTALLFILE_LOCAL = $(INSTALLFILE_BIN_LOCAL) +INSTALLDIR_LOCAL = $(INSTALLDIR_BIN_LOCAL) + +# our mode +MODE ?= static + +# include all Makeconf.locals, define common rules/variables +include $(L4DIR)/mk/binary.inc + +ifneq ($(SYSTEM),) # if we have a system, really build + +TARGET_STANDARD := $(TARGET) $(TARGET_$(OSYSTEM)) +TARGET_PROFILE := $(addsuffix .pr,$(filter $(BUILD_PROFILE),$(TARGET))) +TARGET += $(TARGET_$(OSYSTEM)) $(TARGET_PROFILE) + +LDFLAGS_DYNAMIC_LINKER := --dynamic-linker=rom/libld-l4.so +LDFLAGS_DYNAMIC_LINKER_GCC := $(addprefix -Wl$(BID_COMMA),$(LDFLAGS_DYNAMIC_LINKER)) + +# define some variables different for lib.mk and prog.mk +ifeq ($(MODE),shared) +LDFLAGS += $(LDFLAGS_DYNAMIC_LINKER) +endif +ifeq ($(CONFIG_BID_GENERATE_MAPFILE),y) +LDFLAGS += -Map $(strip $@).map +endif +LDFLAGS += $(addprefix -L, $(PRIVATE_LIBDIR) $(PRIVATE_LIBDIR_$(OSYSTEM)) $(PRIVATE_LIBDIR_$@) $(PRIVATE_LIBDIR_$@_$(OSYSTEM))) + +# here because order of --defsym's is important +ifeq ($(MODE),l4linux) + L4LX_USER_KIP_ADDR = 0xbfdfd000 + LDFLAGS += --defsym __L4_KIP_ADDR__=$(L4LX_USER_KIP_ADDR) \ + --defsym __l4sys_invoke_direct=$(L4LX_USER_KIP_ADDR)+$(L4_KIP_OFFS_SYS_INVOKE) \ + --defsym __l4sys_debugger_direct=$(L4LX_USER_KIP_ADDR)+$(L4_KIP_OFFS_SYS_DEBUGGER) + CPPFLAGS += -DL4SYS_USE_UTCB_WRAP=1 +else +ifneq ($(HOST_LINK),1) + LDFLAGS += --defsym __L4_KIP_ADDR__=$(L4_KIP_ADDR) \ + --defsym __L4_STACK_ADDR__=$(L4_STACK_ADDR) +endif +endif + +ifneq ($(HOST_LINK),1) + # linking for our L4 platform + LDFLAGS += $(addprefix -L, $(L4LIBDIR)) + LDFLAGS += $(addprefix -T, $(LDSCRIPT)) + LDFLAGS += --start-group $(LIBS) $(L4_LIBS) --end-group + LDFLAGS += --warn-common +else + # linking for some POSIX platform + ifeq ($(MODE),host) + # linking for the build-platform + LDFLAGS += -L$(OBJ_BASE)/lib/host + LDFLAGS += $(LIBS) + else + # linking for L4Linux, we want to look for Linux-libs before the L4-libs + LDFLAGS += $(GCCSYSLIBDIRS) + LDFLAGS += $(addprefix -L, $(L4LIBDIR)) + LDFLAGS += $(LIBS) -Wl,-Bstatic $(L4_LIBS) + # -Wl,-Bdynamic is only applicable for dynamically linked programs, + # we need a static/dynamic flag for the l4linux mode... + LDFLAGS += -Wl,-Bdynamic + endif +endif + +LDFLAGS += $(LDFLAGS_$@) + +ifeq ($(notdir $(LDSCRIPT)),main_stat.ld) +# ld denies -gc-section when linking against shared libraries +ifeq ($(findstring FOO,$(patsubst -l%.s,FOO,$(LIBS) $(L4_LIBS))),) +LDFLAGS += -gc-sections +endif +endif + + +include $(L4DIR)/mk/install.inc + +#VPATHEX = $(foreach obj, $(OBJS), $(firstword $(foreach dir, \ +# . $(VPATH),$(wildcard $(dir)/$(obj))))) + +# target-rule: + +# Make looks for obj-files using VPATH only when looking for dependencies +# and applying implicit rules. Though make adapts its automatic variables, +# we cannot use them: The dependencies contain files which have not to be +# linked to the binary. Therefore the foreach searches the obj-files like +# make does, using the VPATH variable. +# Use a surrounding strip call to avoid ugly linebreaks in the commands +# output. + +# Dependencies: When we have ld.so, we use MAKEDEP to build our +# library dependencies. If not, we fall back to LIBDEPS, an +# approximation of the correct dependencies for the binary. Note, that +# MAKEDEP will be empty if we dont have ld.so, LIBDEPS will be empty +# if we have ld.so. + +ifeq ($(CONFIG_HAVE_LDSO),) +LIBDEPS = $(foreach file, \ + $(patsubst -l%,lib%.a,$(filter-out -L%,$(LDFLAGS))) \ + $(patsubst -l%,lib%.so,$(filter-out -L%,$(LDFLAGS))),\ + $(word 1, $(foreach dir, \ + $(patsubst -L%,%,\ + $(filter -L%,$(LDFLAGS) $(L4ALL_LIBDIR))),\ + $(wildcard $(dir)/$(file))))) +endif + +DEPS += $(foreach file,$(TARGET), $(dir $(file)).$(notdir $(file)).d) + +LINK_PROGRAM-C-host-1 := $(CC) +LINK_PROGRAM-CXX-host-1 := $(CXX) + +LINK_PROGRAM := $(LINK_PROGRAM-C-host-$(HOST_LINK)) +ifneq ($(SRC_CC),) +LINK_PROGRAM := $(LINK_PROGRAM-CXX-host-$(HOST_LINK)) +endif + +BID_LDFLAGS_FOR_LINKING_LD = $(LDFLAGS) +BID_LDFLAGS_FOR_GCC = $(filter -static -shared -nostdlib -Wl$(BID_COMMA)% -L% -l%,$(LDFLAGS)) +BID_LDFLAGS_FOR_LD = $(filter-out -static -shared -nostdlib -Wl$(BID_COMMA)% -L% -l%,$(LDFLAGS)) +BID_LDFLAGS_FOR_LINKING_GCC = $(addprefix -Wl$(BID_COMMA),$(BID_LDFLAGS_FOR_LD)) $(BID_LDFLAGS_FOR_GCC) + +ifeq ($(LINK_PROGRAM),) +LINK_PROGRAM := $(LD) +BID_LDFLAGS_FOR_LINKING = $(BID_LDFLAGS_FOR_LINKING_LD) +else +BID_LDFLAGS_FOR_LINKING = $(if $(HOST_LINK_TARGET),$(CCXX_FLAGS)) $(BID_LDFLAGS_FOR_LINKING_GCC) +endif + +$(TARGET): $(OBJS) $(LIBDEPS) $(CRT0) $(CRTN) + @$(LINK_MESSAGE) + $(VERBOSE)$(call MAKEDEP,$(INT_LD_NAME),,,ld) $(LINK_PROGRAM) -o $@ $(CRT0) $(OBJS) $(BID_LDFLAGS_FOR_LINKING) $(CRTN) + $(if $(BID_GEN_CONTROL),$(VERBOSE)echo "Requires: $(REQUIRES_LIBS)" >> $(PKGDIR)/Control) + $(if $(BID_POST_PROG_LINK_MSG_$@),@$(BID_POST_PROG_LINK_MSG_$@)) + $(if $(BID_POST_PROG_LINK_$@),$(BID_POST_PROG_LINK_$@)) + @$(BUILT_MESSAGE) + +endif # architecture is defined, really build + +-include $(DEPSVAR) +.PHONY: all clean cleanall config help install oldconfig txtconfig +help:: + @echo " all - compile and install the binaries" +ifneq ($(SYSTEM),) + @echo " to $(INSTALLDIR_LOCAL)" +endif + @echo " install - compile and install the binaries" +ifneq ($(SYSTEM),) + @echo " to $(INSTALLDIR)" +endif + @echo " relink - relink and install the binaries" +ifneq ($(SYSTEM),) + @echo " to $(INSTALLDIR_LOCAL)" +endif + @echo " disasm - disassemble first target" + @echo " scrub - delete backup and temporary files" + @echo " clean - delete generated object files" + @echo " cleanall - delete all generated, backup and temporary files" + @echo " help - this help" + @echo +ifneq ($(SYSTEM),) + @echo " binaries are: $(TARGET)" +else + @echo " build for architectures: $(TARGET_SYSTEMS)" +endif + +endif # _L4DIR_MK_PROG_MK undefined diff --git a/l4/mk/ptest b/l4/mk/ptest new file mode 100755 index 00000000..b56a977b --- /dev/null +++ b/l4/mk/ptest @@ -0,0 +1,444 @@ +#! /usr/bin/perl -W +# +# Run package tests using Fiasco-UX +# +# +# Adam Lackorzynski +# Ronald Aigner +# +# This script is derived from the autocheck script which can be found in +# kernel/fiasco/tools. It has been slightly modified to suit the demands of +# the package tests. +# + +# make it pass for now +#exit 0; + +use strict; +use Getopt::Long; + +my $FIASCOUX; +my $FIASCOUX_PARAM; +my $L4DIR; +my $OBJ_BASE; +my $OBJDIR = 'OBJ-x86_586-l4f'; +my $EXPECTED_OUT = 'expected.txt'; +my $TMP_OUT = 'tmp_out.txt'; +my $PKGNAME; +my $COMPARE_CMD = 'diff -u $EXPECTED_OUT $TMP_OUT'; + +my $ALARM_TIMEOUT = 60; # in seconds + +my %templs = ( + roottask => '%s/pkg/roottask/server/src/%s/roottask', + sigma0 => '%s/pkg/sigma0/server/src/%s/sigma0', +); + +my $Verbose = 0; +my $Quiet = 0; +my $Generate = 0; +my $Memory = 32; +my $Plainrun = 0; +my $No_fb = 0; +my $Use_Symbols = 0; +my $Use_Lines = 0; + +my %progs; +my %results; +my %output; +my @Baseservers; +my $Client; +my $Server; +my $Fiasco_Dir; + +# filehandle for fiasco output +my $Input; +my $Output; + +my $Exit_code = 0; +my $pid = 0; + +my $FILTER_LEVEL_FIASCO = 0; +my $FILTER_LEVEL_ROOTTASK = 1; +my $FILTER_LEVEL_USER = 2; +my $Filter_state = $FILTER_LEVEL_FIASCO; +my $Filter_level = $FILTER_LEVEL_USER; + +sub usage() { + print < -s + + --l4dir, -l path Path to an L4 directory + --fiascoux, -f file Path to the Fiasco-UX binary + --fiascoux_param, -p params Parameters for Fiasco-UX + --memory, -m megabyte Number of Megabytes used by Fiasco. (default: 32) + --objdir, -O objdir Object dir, currently: $OBJDIR + --verbose, -v Be verbose (e.g. show output of L4 apps) + --quiet, -q Tell nothing, just set the exit code + --generate Generate the output file instead of comparing to it + --server, -s file The server to be tested + --client, -c file The file to run as test-application + --base, -b file Additional base servers required by the application + Can be a comma seperated list. (Only specify the + binary names!) (default: log, names, dm_phys) + --timeout, -t timeout Time in seconds to wait before shooting down a + runaway fiasco. (default: 60) + --expectfail Expect failure. Return 0 on failure, 1 on success. + + Environment variables: + L4DIR Path to an L4 directory + OBJ_BASE Path to build directory + FIASCOUX Path to the Fiasco-UX binary + EXPECTED_OUT Filename of the file containing the expected output + TMP_OUT Filename of the tempfile containing Fiasco's output + COMPARE_CMD Command to compare output and expected output + + Notes: + Environment variables override options! +EOU +} + +## +# Check if L4DIR looks like an L4 directory +sub check_for_l4dir() { + unless (-d "$L4DIR/pkg/l4sys/include" || + -d "$L4DIR/../kernel/fiasco/src/kern/ux") { + die "$L4DIR doesn't look like an L4 directory!"; + } +} + +## +# Just check if the supplied binary in $FIASCOUX is really +# a Fiasco UX version. Native versions will just segfault. +sub check_for_fiasco_ux() { + + unless ((-x $FIASCOUX && -f $FIASCOUX) || + (-l $FIASCOUX && -x readlink $FIASCOUX && -f readlink $FIASCOUX)) { + die "$FIASCOUX: Does not exist or isn't an executable file"; + } + + system("$FIASCOUX -h >/dev/null 2>&1"); + die "$FIASCOUX doesn't seem to be a UX version." if $?; + + $FIASCOUX =~ /(.*)\/([^\/]*)$/; + $Fiasco_Dir = $1; +} + +# check for user app in binary path of L4 +sub check_user_app($) +{ + my $app_with_args = shift; + + # extract arch and api from OBJ-dir + $OBJDIR =~ /OBJ-([^-]*)-(.*)/; + my $arch = $1; + my $api = $2; + + my @check = split(/\s+/, $app_with_args); + my $app = shift @check; + + my $p = sprintf "%s/bin/%s/%s/%s", $OBJ_BASE, $arch, $api, $app; + die "There's no $p!" unless -f $p; + + return $p.'\\ '.join('\\ ', @check) if @check; + $p; +} + +## +# Check for userland (roottask, sigma0, ...) +sub check_for_userland() { + foreach my $t (keys %templs) { + my $p = sprintf $templs{$t}, $OBJ_BASE, $OBJDIR; + die "There's no $p!" unless -f $p; + $progs{$t} = $p; + } + + # check for base-servers + my @servers = @Baseservers; + @Baseservers = {}; + if (scalar(@servers) eq 0) { + @servers = ( "log", "names", "dm_phys" ); + } + + # iterate over servers and test if they exist in the bin dir + foreach my $s (@servers) { + push @Baseservers, check_user_app($s); + } + + # test client and server + push @Baseservers, check_user_app($Client) if defined($Client); + push @Baseservers, check_user_app($Server); +} + +## +# Does the comparison of the output +sub run_diff { + print STDERR "Running compare command \"$COMPARE_CMD\".\n" if $Verbose; + open(TMP, "$COMPARE_CMD |") or die "Cannot run diff: $!"; + my @diff = ; + close TMP; + + # reset console in interactive mode + system "if tty -s; then stty echo icrnl icanon; fi"; + + # check if there are differences between expected and generated output + if (@diff == 0) { + print STDERR "Output of test in $PKGNAME ok.\n"; + return $Exit_code; + } + + print STDERR "Test in $PKGNAME generated unexpected output:\n"; + @diff = splice @diff, 1000 if @diff > 1000; + print STDERR @diff, "\n"; + return 1 - $Exit_code; +} + +## +# Called if second alarm signal received +# +# Now all the output of Fiasco-UX should be through and we can savely kill +# Fiasco-UX. We then check the generated output and terminate ourselves. +sub got_sig_alarm_second { + print STDERR "Timeout for flushing Fiasco-UX output\n" if $Verbose; + print STDERR "Sending SIGKILL to $pid and diff output\n" if $Verbose; + + kill KILL => $pid; + alarm 0; + + # some sanity checks + if ( $Filter_state < $FILTER_LEVEL_USER ) { + print $Output "\n"; + print $Output "User tasks did not start. Maybe overlapping modules?\n"; + print $Output "Run \"" . fiascoux_cmdline() . "\" manually to check.\n"; + } + close $Output; + + # in generate mode, simply return + if ($Generate) { + system "stty echo"; + exit 0; + } + + exit run_diff(); +} + +## +# Called if first alarm signal received +# +# To flush Fiasco Output we send it a SIGINT (^C). Then we set up a second +# timeout and return, so the filter can process the output which we forced to +# be flushed. +sub got_sig_alarm_first { + print STDERR "Timeout for Fiasco-UX hit!\n" if $Verbose; + print STDERR "Sending SIGINT to $pid\n" if $Verbose; + + kill INT => $pid; + $SIG{ALRM} = \&got_sig_alarm_second; + alarm 2; # time to flush output + + # return to keep on filtering the output of Fiasco +} + +## +# Runs the timer and kills fiasco if runaway +# +# - sets the signal handler +# - initializes the timeout +sub set_alarm { + $SIG{ALRM} = \&got_sig_alarm_first; + alarm $ALARM_TIMEOUT; + print STDERR "Set alarm to $ALARM_TIMEOUT seconds\n" if $Verbose; +} + +## +# Build the fiasco command line +# +# Adds the binaries with the appropriate parameters. +sub fiascoux_cmdline() { + (my $p = $FIASCOUX) =~ s/\/[^\/]+$//; + my $cmdline = "$FIASCOUX"; + $cmdline .= " $FIASCOUX_PARAM" if defined $FIASCOUX_PARAM; + $cmdline .= " -symbols $Fiasco_Dir/Symbols" if $Use_Symbols; + $cmdline .= " -lines $Fiasco_Dir/Lines" if $Use_Lines; + $cmdline .= " -m $Memory"; + $cmdline .= " -R $progs{roottask}"; # -quiet"; + $cmdline .= "\"" if $Use_Symbols || $Use_Lines; + $cmdline .= " -symbols" if $Use_Symbols; + $cmdline .= " -lines" if $Use_Lines; + $cmdline .= "\"" if $Use_Symbols || $Use_Lines; + $cmdline .= " -S $progs{sigma0}"; # --quiet"; + # when we change this to not cd into Fiasco dir, then + # prepend $p to $irq0 + $cmdline .= " -I ".$p."/irq0"; + if ($No_fb eq 1) { + $cmdline .= " -F /bin/true"; + } else { + $cmdline .= " -F ".$p."/con_ux"; + } + # add -l to base-servers, which already contains client and server + for my $s (@Baseservers) { + if (ref($s) ne "HASH") { # just checking for Hashes that smuggled in + $cmdline .= " -l ".$s; + } + } + $cmdline; +} + +## +# filters the output of fiasco +# +# We want to see everything once roottask are finished loading. +# Therefore, we need some state machine to skip everything before and while +# roottask is running. +sub filter_fiasco_out +{ + $_ = shift; + + # filter escape sequences + s/[[:cntrl:]]\[(\d;)?\d{0,2}m//g; + s/ //g; + s/[[:cntrl:]]\[K//g; + s/[[:cntrl:]]\[\d+;\d+[Hfr]//g; + + # check if we have to change state + if (/^Roottask: Loading \d+ modules\./ && + $Filter_state eq $FILTER_LEVEL_FIASCO) { + $Filter_state = $FILTER_LEVEL_ROOTTASK; + print STDERR "Changed state to Roottask-Output\n" if $Verbose; + } + if ( /^$/ && $Filter_state eq $FILTER_LEVEL_ROOTTASK) { + $Filter_state = $FILTER_LEVEL_USER; + print STDERR "Changed state to Userland-Output\n" if $Verbose; + } + + # skip everything before and from roottask + return undef if $Filter_state < $Filter_level; + + # if we are not supposed to filter anything, then return the line + return $_ if $Filter_level eq $FILTER_LEVEL_FIASCO; + + # filter empty lines + return undef if /^$/; + + # filter JDB warning and prompt + return undef if /^Terminal probably too small, should be at least/; + return undef if /^\([a-f0-9]\.\d\d\) jdb:/; + return undef if /^--.*ESP:.*EIP:.*/; + + # filter memory dump + return undef if /^([a-f0-9]){8}:/; + + $_; +} + +## +# call_test +sub run_fiasco { + my $cmdline = fiascoux_cmdline(); + print "Calling: $cmdline\n" if $Verbose; + + $pid = open($Input, "$cmdline|"); + die "Can't start Fiasco: $!" unless defined $pid; + print "Run Fiasco-UX in $pid\n" if $Verbose; + + # if in generate mode, we redirect output to EXPECTED_OUT + # otherwise we redirect stdout to the TMP_OUT file + my $filename = $Generate ? $EXPECTED_OUT : $TMP_OUT; + open($Output, ">$filename") || die "Cannot open output file $filename"; + my $oldfh = select($Output); $| = 1; select($oldfh); + print STDERR "Opened $filename, now setting timer\n" if $Verbose; + + # the parent sets up the timer (it will eventually call the run_diff sub) + set_alarm(); + + my $o; + while (<$Input>) { + # we have to strip some lines + $o = filter_fiasco_out($_); + next unless defined $o; + print $Output $o; + } + print STDERR "Fiasco terminated.\n" if $Verbose; + close $Input; + close $Output; + # when we drop out of this loop fiasco terminated + alarm 0; + + # in generate mode, simply return + exit 0 if $Generate; + + exit run_diff(); +} + +## +# Plain run of Fiasco UX +# +# Not timer, no filter, simply run UX +sub run_plain_fiasco { + my $cmdline = fiascoux_cmdline(); + print "Running UX: \"$cmdline\"\n"; + exec($cmdline) or die "Can't start Fiasco: $!"; + exit 1; +} + + +# ------------------------------------------------------------- + +unless (GetOptions("help|h", sub { usage(); exit(0); }, + "l4dir|l=s", \$L4DIR, + "builddir=s", \$OBJ_BASE, + "fiascoux|f=s", \$FIASCOUX, + "fiascoux_param|p=s", \$FIASCOUX_PARAM, + "memory|m=s", \$Memory, + "objdir|O=s", \$OBJDIR, + "verbose|v!", \$Verbose, + "quiet|q!", \$Quiet, + "generate!", \$Generate, + "expectfail!", \$Exit_code, + "client|c=s", \$Client, + "server|s=s", \$Server, + "base|b=s", \@Baseservers, + "timeout|t=s", \$ALARM_TIMEOUT, + "plainrun!", \$Plainrun, + "filterlevel=i", \$Filter_level, + "nofb!", \$No_fb, + "symbols!", \$Use_Symbols, + "lines!", \$Use_Lines, + )) { + usage(); + exit(1); +} + +@Baseservers = split(/,/,join(',',@Baseservers)); + +$L4DIR = $ENV{L4DIR} || die "Need an L4DIR set!" unless $L4DIR; +$OBJ_BASE = $ENV{OBJ_BASE} || die "Need an builddir (OBJ_BASE) set!" unless $OBJ_BASE; +$FIASCOUX = $ENV{FIASCOUX} || die "Need a Fiasco-UX path!" unless $FIASCOUX; +if ($ENV{EXPECTED_OUT}) { $EXPECTED_OUT = $ENV{EXPECTED_OUT}; } +die "Need filename of expected output!" unless $EXPECTED_OUT; +if ($ENV{TMP_OUT}) { $TMP_OUT = $ENV{TMP_OUT}; } +die "No valid temporary file set!" unless $TMP_OUT; +$PKGNAME = $ENV{PKGNAME} || $Server + || die "No package-name set!" unless $PKGNAME; +if ($ENV{COMPARE_CMD}) { $COMPARE_CMD = $ENV{COMPARE_CMD}; } +die "No compare command set!" unless $COMPARE_CMD; + +check_for_l4dir(); +check_for_fiasco_ux(); +check_for_userland(); + +## +# The package test script: +# This script forks off Fiasco and sets up a timeout. When the timeout +# strikes, it sends a SIGINT to Fiasco to force a flush of the output buffer. +# Then it sends a SIGKILL to terminate Fiasco. +print "Main called by $$.\n" if $Verbose; + +# if plainrun, start run_plain_fiasco (it never returns) +run_plain_fiasco() if $Plainrun; + +# this function forks off fiasco +run_fiasco(); + +# when we reach this point, something terribly went wrong +die "Oops, error in script!\n"; diff --git a/l4/mk/redo_defconfigs b/l4/mk/redo_defconfigs new file mode 100755 index 00000000..c17db21e --- /dev/null +++ b/l4/mk/redo_defconfigs @@ -0,0 +1,22 @@ +#! /bin/sh + +set -x + +TMPDIR=$(mktemp -d) + +exithandler() +{ + rm -r $TMPDIR +} + +trap exithandler EXIT + +cd .. + +for i in mk/defconfig/config.*; do + cp $i $TMPDIR/.kconfig + make O=$TMPDIR oldconfig + diff -u $i $TMPDIR/.kconfig + grep -v '^CONFIG_DROPS_' $TMPDIR/.kconfig > $i + rm $TMPDIR/.kconfig $TMPDIR/.config.all $TMPDIR/.config +done diff --git a/l4/mk/rel2abs.sh b/l4/mk/rel2abs.sh new file mode 100755 index 00000000..842de0fb --- /dev/null +++ b/l4/mk/rel2abs.sh @@ -0,0 +1,72 @@ +#! /usr/bin/env bash +# +# Convert relative path to absolute one +# +# Adam Lackorzynski +# + +help() +{ + echo PWD=\$PWD $0 relpath1 [relpath2 [..]] + exit $1 +} + +convertpath() +{ + relpath=$1 + basepath=$PWD + # sanity checks + [ -z "$relpath" -o -z "$basepath" ] && help 1 + [ "${basepath#/}" = "${basepath}" ] && help 1 + [ "${basepath/\/..\//}" = "${basepath}" ] || help 1 + [ "${basepath/\/.\//}" = "${basepath}" ] || help 1 + [ "${basepath/%\/../}" = "${basepath}" ] || help 1 + [ "${basepath/%\/./}" = "${basepath}" ] || help 1 + + + # remove slashes at the end + while [ "${relpath%/}" != "${relpath}" ]; + do relpath="${relpath%/}"; done + + # remove double/multi slashes + while [ "${relpath/\/\///}" != "${relpath}" ]; + do relpath=${relpath/\/\///}; done + + # is relpath relative? + if [ "${relpath#/}" != "${relpath}" ]; then + basepath='' + relpath=${relpath#/} + fi + + relpath="$relpath/" + + while [ -n "$relpath" ]; + do + elem=${relpath%%/*} + relpath=${relpath#*/} + + case $elem in + .) # skip + ;; + ..) + basepath=${basepath%/*} + ;; + *) + basepath=$basepath/$elem + ;; + esac + + done + + [ -z "$basepath" ] && basepath=/$basepath + + echo $basepath +} + +while [ -n "$1" ]; +do + convertpath $1 + shift +done + +exit 0 diff --git a/l4/mk/rules.inc b/l4/mk/rules.inc new file mode 100644 index 00000000..46bbd82a --- /dev/null +++ b/l4/mk/rules.inc @@ -0,0 +1,94 @@ +# vi:ft=make +# This makefile contains the generator for our basic pattern rules. +# These generators allow easy instantiation of own rule sets. + +# variables for instantiating make rules. +# for C++ compile (CXX) use $(CXX), $(INT_CXX_NAME), and $(CXXFLAGS) +BID_CXX_COMPILER = CXX +BID_CXX_COMPILER_INT_NAME = INT_CXX_NAME +# for C compile (C) use $(CC), $(INT_CPP_NAME), and $(CFLAGS) +BID_C_COMPILER = CC +BID_C_COMPILER_INT_NAME = INT_CPP_NAME +# for AS compile (AS) use $(CC), $(INT_CPP_NAME), and $(ASFLAGS) +BID_AS_COMPILER = CC +BID_AS_COMPILER_INT_NAME = INT_CPP_NAME + +# Template for our make rules. +# arg1: the target or target pattern (e.g., %.o) +# arg2: the prerequisites (e.g., %.c) +# arg3: the compiler pattern, used for determining the compiler +# variables and default flags (e.g., CXX). The rule uses +# $($(BID__COMPILER)) as compiler, +# $($(BID__COMPILER_INT_NAME)) for gendep, and +# $(FLAGS) as flags +# arg4: extra command line flags for the compile +define BID_MAKE_RULE_template_gendep +$(1): $(2) + @$$(COMP_MESSAGE) + $$(VERBOSE)$$(call MAKEDEP,$$($(BID_$(3)_COMPILER_INT_NAME))) $$($(BID_$(3)_COMPILER)) -c $$(DEPEND_FLAG) $$(CPPFLAGS) $$($(3)FLAGS) $(4) $$(call absfilename,$$<) -o $$@ + $$(DEPEND_VERBOSE)$$(call DEPEND_EXTEND_FUNC, $$(*F).d, $$(dir $$@).$$(notdir $$@).d) +endef + +# Template for our make rules (make rules that do not use gendep) +define BID_MAKE_RULE_template_nongendep +$(1): $(2) + @$$(COMP_MESSAGE) + $$(VERBOSE)$$($(BID_$(3)_COMPILER)) -c $$(DEPFLAGS) $$(CPPFLAGS) $$($(3)FLAGS) $(4) $$(call absfilename,$$<) -o $$@ +endef + +# which template rule do we really use +BID_MAKE_RULE_template = $(BID_MAKE_RULE_template_gendep) + +# +# Generate the default set of make rules. +# targets: .o, .s.o, .pr.o, and .pr.s.o +# +define BID_GENERATE_DEFAULT_MAKE_RULES + $(call BID_MAKE_RULE_template,$(1).o,$(2),$(3),$(4)) + $(call BID_MAKE_RULE_template,$(1).s.o,$(2),$(3),$(4) $$(PICFLAGS)) + $(call BID_MAKE_RULE_template,$(1).pr.o,$(2),$(3),$(4) -DPROFILE -pg) + $(call BID_MAKE_RULE_template,$(1).pr.s.o,$(2),$(3),$(4) $$(PICFLAGS) -DPROFILE -pg) +endef + +# +# Generate the C++ set of make rules. +# prerequisites: %. (usually %.cc) +# targets: %.o, %.s.o, %.ne.o, %.s.ne.o, %.pr.o, and %.pr.s.o +# +define BID_GENERATE_CXX_MAKE_RULES + $(call BID_GENERATE_DEFAULT_MAKE_RULES,%,%.$(1),CXX) + $(call BID_MAKE_RULE_template,%.ne.o,%.$(1),CXX,$$(CXXFLAGS_NOEXC)) + $(call BID_MAKE_RULE_template,%.s.ne.o,%.$(1),CXX,$$(CXXFLAGS_NOEXC) $$(PICFLAGS)) +endef + +# +# +# Generate the C set of make rules. +# prerequisites: %. (usually %.c) +# targets: %.o, %.s.o, %.pr.o, and %.pr.s.o +# +define BID_GENERATE_C_MAKE_RULES + $(call BID_GENERATE_DEFAULT_MAKE_RULES,%,%.$(1),C) +endef + +# +# arg 1: target pattern +# 2: source pattern +# 3: compiler +# 4: compiler options +define BID_GENERATE_I_MAKE_RULE +$(1): $(2) FORCE + @$$(COMP_MESSAGE) + $$(VERBOSE)$(3) -E -H -dD $$(CPPFLAGS) $(4) $$(call absfilename,$$<) -o $$@ + $$(VERBOSE)$$(if $$(DO_SHOW_RESULT_FILE),$$(PAGER) $$@) +endef + +# +# arg 1: source pattern +# 2: compiler +# 3: compiler options +define BID_GENERATE_S_MAKE_RULE +%.S: $(1) FORCE + @$$(COMP_MESSAGE) + $$(VERBOSE)$(2) -S $(3) $(CPPFLAGS) $$(call absfilename,$$<) -fverbose-asm -o $$@ +endef diff --git a/l4/mk/runux.mk b/l4/mk/runux.mk new file mode 100644 index 00000000..c19a30ac --- /dev/null +++ b/l4/mk/runux.mk @@ -0,0 +1,194 @@ +# -*- Makefile -*- +# +# DROPS (Dresden Realtime OPerating System) Component +# +# Makefile-Template to run tests with Fiasco-UX +# +# install.inc is used, see there for further documentation + +ifeq ($(origin _L4DIR_MK_RUNUX_MK),undefined) +_L4DIR_MK_RUNUX_MK=y + +ROLE = runux.mk +.general.d: $(L4DIR)/mk/runux.mk + +# set a mode, so binary.inc is satisfied +MODE ?= l4env + +# include all Makeconf.locals, define common rules/variables +include $(L4DIR)/mk/Makeconf +include $(L4DIR)/mk/binary.inc + +# if we have a system set, build +ifneq ($(SYSTEM),) + +## +# !WARNING! +# +# This is a preliminary test to allow l4check to run Fiasco-UX tests for +# multiple SYSTEMS. This currently only works for x86. +ifneq ($(ARCH),x86) +$(error "$(ROLE) currently does not support $(ARCH).") +endif + +# now check if the current API has a FIASCOUX variable set and if so use it +# XXX could be overloaded by $(OSYSTEM) == $(ARCH)-$(L4API) or $(SYSTEM) +ifneq ($(FIASCOUX_$(L4API)),) +FIASCOUX = $(FIASCOUX_$(L4API)) +else +$(warning "Using generic(?) Fiasco UX "$(FIASCOUX)" to test $(L4API).") +endif + +# the testapplication +# test if variables are set +ifeq ($(TEST_SERVER),) +DO_TARGET := no_ptest +else +DO_TARGET := ptest +endif +# TEST_CLIENT might be empty. Testing server stand-alone +ifneq ($(TEST_CLIENT),) +TEST_CLIENT_PARAM = $(addprefix -c ,$(TEST_CLIENT)) +endif +ifneq ($(BASE_SERVERS),) +$(warning $(BASE_SERVERS)) +BASESERVERS = $(foreach server, $(BASE_SERVERS), -b $(server) $(BASE_SERVERS_PARAM_$(server))) +endif + +# expected output and what to do on mismatch +EXPECTED_OUT ?= expected.txt +TIMEOUT ?= 10 +DEBUG_PERL ?= 0 +TMP_OUT ?= tmp_out.txt + +# specify files to delete when doing 'make clean' +DEL_ON_CLEAN = $(TMP_OUT) core + +ifneq ($(DEBUG_PERL),0) +DEBUG_PERL_ = -v +else +DEBUG_PERL_ = +endif + +ifneq ($(MEMORY),) +MEMORY_ = -m $(MEMORY) +endif + +ifneq ($(FIASCOUX_PARAM),) +FIASCOUX_PARAM_ = -p $(FIASCOUX_PARAM) +endif + +# allow failure of test +# +# If EXPECT_FAIL is set, the test if the output matches must fail, otherwise +# ptest will return an error. +ifeq ($(EXPECT_FAIL),1) +EXPECT_FAIL_ = --expectfail +else +EXPECT_FAIL_ = +endif + +# do keep ALL output +# +# if FILTER_KEEP_ALL is set, the Fiasco UX output is only filtered for escape +# sequences. All other output is printed into temporary file +ifeq ($(FILTER_KEEP_ALL),1) +FILTER_KEEP_ = --filterlevel=0 +else +FILTER_KEEP_ = +endif + +# no framebuffer device +# +# If NO_FBUF_DEV is set, Fiasco UX will not open an X window to display +# graphical output. This is useful for testing graphical applications. +ifeq ($(NO_FBUF_DEV),1) +NO_FBUF_DEV_ = --nofb +else +NO_FBUF_DEV_ = +endif + +# enable symbols and lines per default +USE_SYMBOLS ?= y +USE_LINES ?= y + +ifeq ($(USE_SYMBOLS),y) +USE_SYMBOLS_ = --symbols +else +USE_SYMBOLS_ = +endif +ifeq ($(USE_LINES),y) +USE_LINES_ = --lines +else +USE_LINES_ = +endif + +all:: $(DO_TARGET) + +# install.inc eventually defines rules for every target +include $(L4DIR)/mk/install.inc + +no_ptest: + @echo "No test defined, skipping" + +ptest:: $(EXPECTED_OUT) $(BID_OBJ_Makefile).inc + $(VERBOSE)echo "Running Fiasco UX to test $(TEST_SERVER)" + $(VERBOSE)EXPECTED_OUT=$(EXPECTED_OUT) PKGNAME=$(PKGNAME) \ + L4DIR=$(L4DIR) OBJ_BASE=$(OBJ_BASE) TMP_OUT=$(TMP_OUT) \ + COMPARE_CMD=$(COMPARE_CMD) \ + $(L4DIR)/mk/ptest -s $(TEST_SERVER) $(TEST_CLIENT_PARAM) \ + -f $(FIASCOUX) $(FIASCOUX_PARAM_) -t $(TIMEOUT) \ + -O OBJ-$(SYSTEM) \ + $(BASESERVERS) $(DEBUG_PERL_) $(MEMORY_) $(EXPECT_FAIL_) \ + $(FILTER_KEEP_) $(NO_FBUF_DEV_) $(USE_SYMBOLS_) $(USE_LINES_) + +genexp:: $(EXPECTED_OUT) $(BID_OBJ_Makefile).inc + +$(EXPECTED_OUT): + $(VERBOSE)echo "Running Fiasco UX to generate expected output" + $(VERBOSE)EXPECTED_OUT=$(EXPECTED_OUT) PKGNAME=$(PKGNAME) \ + L4DIR=$(L4DIR) OBJ_BASE=$(OBJ_BASE) TMP_OUT=$(TMP_OUT) \ + COMPARE=$(COMPARE_CMD) \ + $(L4DIR)/mk/ptest -s $(TEST_SERVER) $(TEST_CLIENT_PARAM) \ + -f $(FIASCOUX) $(FIASCOUX_PARAM_) -t $(TIMEOUT) \ + -O OBJ-$(SYSTEM) \ + $(BASESERVERS) $(DEBUG_PERL_) $(MEMORY_) $(EXPECT_FAIL_) \ + $(FILTER_KEEP_) $(NO_FBUF_DEV_) $(USE_SYMBOLS_) $(USE_LINES_) \ + --generate + $(VERBOSE)touch .expect-autogenerated + +plainrun:: $(BID_OBJ_Makefile).inc + $(VERBOSE)echo "Starting Fiasco UX" + $(VERBOSE)EXPECTED_OUT=$(EXPECTED_OUT) PKGNAME=$(PKGNAME) \ + L4DIR=$(L4DIR) OBJ_BASE=$(OBJ_BASE) TMP_OUT=$(TMP_OUT) \ + COMPARE_CMD=$(COMPARE_CMD) \ + $(L4DIR)/mk/ptest -s $(TEST_SERVER) $(TEST_CLIENT_PARAM) \ + -f $(FIASCOUX) $(FIASCOUX_PARAM_) -t $(TIMEOUT) \ + -O OBJ-$(SYSTEM) \ + $(BASESERVERS) $(DEBUG_PERL_) $(MEMORY_) $(FILTER_KEEP_) \ + $(NO_FBUF_DEV_) $(USE_SYMBOLS_) $(USE_LINES_) --plainrun + +endif # system defined + +ptest genexp plainrun:: $(foreach arch,$(TARGET_SYSTEMS),\ + $(OBJ_DIR)/OBJ-$(arch)/$(BID_OBJ_Makefile)) + $(if $(TARGET_SYSTEMS), $(VERBOSE)set -e ; \ + for d in $(TARGET_SYSTEMS) ; do \ + PWD=$(OBJ_DIR)/OBJ-$$d $(MAKE) -C $(OBJ_DIR)/OBJ-$$d -f $(BID_OBJ_Makefile) \ + $@ ; done ) + +.PHONY: all ptest genexp plainrun clean cleanall help no_ptest +-include $(DEPSVAR) + +help:: + @echo "Specify a target:" + @echo "all - run test" + @echo "test - run test" + @echo "genexp - generate file with expected output" + @echo "plainrun - just run binaries (no filter, no comparison)" + @echo "clean - delete generated intermediate files" + @echo "cleanall - delete all generated files (include genexp target)" + @echo "help - this help" + @echo + +endif # _L4DIR_MK_RUNUX_MK undefined diff --git a/l4/mk/subdir.mk b/l4/mk/subdir.mk new file mode 100644 index 00000000..997f0457 --- /dev/null +++ b/l4/mk/subdir.mk @@ -0,0 +1,75 @@ +# -*- Makefile -*- +# +# DROPS (Dresden Realtime OPerating System) Component +# +# Makefile-Template for directories containing only subdirs +# +# 05/2002 Jork Loeser + +include $(L4DIR)/mk/Makeconf + +ifeq ($(PKGDIR),.) +TARGET ?= $(patsubst %/Makefile,%,$(wildcard $(addsuffix /Makefile, \ + idl include src lib server examples doc))) +$(if $(wildcard include/Makefile), idl lib server examples: include) +$(if $(wildcard idl/Makefile), lib server examples: idl) +$(if $(wildcard lib/Makefile), server examples: lib) +else +TARGET ?= $(patsubst %/Makefile,%,$(wildcard $(addsuffix /Makefile, \ + idl src lib server examples doc))) +endif +SUBDIR_TARGET := $(if $(filter doc,$(MAKECMDGOALS)),$(TARGET), \ + $(filter-out doc,$(TARGET))) + +all:: $(SUBDIR_TARGET) $(SUBDIRS) +install:: + +lib: include +server: include + +clean cleanall scrub:: + $(VERBOSE)set -e; $(foreach d,$(TARGET), test -f $d/broken || \ + if [ -f $d/Makefile ] ; then PWD=$(PWD)/$d $(MAKE) -C $d $@ $(MKFLAGS) $(MKFLAGS_$(d)); fi; ) + +install oldconfig txtconfig relink:: + $(VERBOSE)set -e; $(foreach d,$(TARGET), test -f $d/broken -o -f $d/obsolete || \ + if [ -f $d/Makefile ] ; then PWD=$(PWD)/$d $(MAKE) -C $d $@ $(MKFLAGS) $(MKFLAGS_$(d)); fi; ) + +# first the subdir-targets (this is were "all" will be build, e.g. in lib +# or server. +$(filter-out ptest,$(SUBDIR_TARGET)): %: + $(VERBOSE)test -f $@/broken -o -f $@/obsolete || \ + if [ -f $@/Makefile ] ; then PWD=$(PWD)/$@ $(MAKE) -C $@ $(MKFLAGS) ; fi +# Second, the rules for going down into sub-pkgs with "lib" and "server" +# targets. Going down into sub-pkgs. + $(if $(SUBDIRS),$(if $(filter $@,idl include lib server examples doc),\ + $(VERBOSE)set -e; for s in $(SUBDIRS); do \ + PWD=$(PWD)/$$s $(MAKE) -C $$s $@ $(MKFLAGS); done )) + +idl include lib server examples doc: + +# the test target is something special: +TEST_DEPENDS ?= server + +# check if the test directory exists, check if its broken or obsolete +# to be able to specify additional dependencies, we make it a :: target +ptest:: $(TEST_DEPENDS) + $(VERBOSE)test -f $@/broken -o -f $@/obsolete || \ + if [ -f $@/Makefile ] ; then PWD=$(PWD)/$@ $(MAKE) -C $@ $(MKFLAGS) ; fi + +install-symlinks: + $(warning target install-symlinks is obsolete. Use 'include' instead (warning only)) + $(VERBOSE)$(MAKE) include + +help:: + @echo " all - build subdirs: $(SUBDIR_TARGET)" + $(if $(filter doc,$(TARGET)), \ + @echo " doc - build documentation") + @echo " scrub - call scrub recursively" + @echo " clean - call clean recursively" + @echo " cleanall - call cleanall recursively" + @echo " install - build subdirs, install recursively then" + @echo " oldconfig - call oldconfig recursively" + @echo " txtconfig - call txtconfig recursively" + +.PHONY: $(TARGET) all clean cleanall help install oldconfig txtconfig diff --git a/l4/mk/tmpl/Control b/l4/mk/tmpl/Control new file mode 100644 index 00000000..db063eea --- /dev/null +++ b/l4/mk/tmpl/Control @@ -0,0 +1,3 @@ +requires: xyz +provides: abc +maintainer: your@email.example.com diff --git a/l4/mk/tmpl/Makefile b/l4/mk/tmpl/Makefile new file mode 100644 index 00000000..4fe603a0 --- /dev/null +++ b/l4/mk/tmpl/Makefile @@ -0,0 +1,9 @@ +PKGDIR ?= . +L4DIR ?= $(PKGDIR)/../.. + +# the default is to build the listed directories, provided that they +# contain a Makefile. If you need to change this, uncomment the following +# line and adapt it. +# TARGET = include src lib server examples doc + +include $(L4DIR)/mk/subdir.mk diff --git a/l4/mk/tmpl/examples/Makefile b/l4/mk/tmpl/examples/Makefile new file mode 100644 index 00000000..065f6d87 --- /dev/null +++ b/l4/mk/tmpl/examples/Makefile @@ -0,0 +1,10 @@ +PKGDIR ?= .. +L4DIR ?= $(PKGDIR)/../.. + +# create examples demonstrating the use of you package in subdirectories +# and list those subdirs in the TARGET variable. +TARGET = + +include $(L4DIR)/mk/subdir.mk + + diff --git a/l4/mk/tmpl/include/Makefile b/l4/mk/tmpl/include/Makefile new file mode 100644 index 00000000..8d31023f --- /dev/null +++ b/l4/mk/tmpl/include/Makefile @@ -0,0 +1,9 @@ +PKGDIR ?= .. +L4DIR ?= $(PKGDIR)/../.. + +# All haeder files found in this directory tree will be automatically +# installed in a way that they can be included with +# #include later. +# No need to list them in this Makefile. + +include $(L4DIR)/mk/include.mk diff --git a/l4/mk/tmpl/inst b/l4/mk/tmpl/inst new file mode 100755 index 00000000..a4b250c8 --- /dev/null +++ b/l4/mk/tmpl/inst @@ -0,0 +1,8 @@ +#! /bin/sh + +# install default directory hierarchy and default Makefiles +# +# Call this script from a newly created package directory. + +set -e +tar c -C "${0%/*}" -f- --exclude=.svn --exclude=inst . | tar xvf - diff --git a/l4/mk/tmpl/lib/Makefile b/l4/mk/tmpl/lib/Makefile new file mode 100644 index 00000000..528e0ac7 --- /dev/null +++ b/l4/mk/tmpl/lib/Makefile @@ -0,0 +1,9 @@ +PKGDIR ?= .. +L4DIR ?= $(PKGDIR)/../.. + +# the default is to build the listed directories, provided that they +# contain a Makefile. If you need to change this, uncomment the following +# line and adapt it. +# TARGET = src + +include $(L4DIR)/mk/subdir.mk diff --git a/l4/mk/tmpl/lib/src/Makefile b/l4/mk/tmpl/lib/src/Makefile new file mode 100644 index 00000000..218d1ee8 --- /dev/null +++ b/l4/mk/tmpl/lib/src/Makefile @@ -0,0 +1,11 @@ +PKGDIR?= ../.. +L4DIR ?= $(PKGDIR)/../.. + +# the name of your library +TARGET = lib$(PKGNAME).a + +# list your .c or .cc files here +SRC_C = +SRC_CC = + +include $(L4DIR)/mk/lib.mk diff --git a/l4/mk/tmpl/ptest/Makefile b/l4/mk/tmpl/ptest/Makefile new file mode 100644 index 00000000..2fc7ed3b --- /dev/null +++ b/l4/mk/tmpl/ptest/Makefile @@ -0,0 +1,6 @@ +PKGDIR ?= .. +L4DIR ?= $(PKGDIR)/../.. + +TARGET = run + +include $(L4DIR)/mk/subdir.mk diff --git a/l4/mk/tmpl/ptest/run/Makefile b/l4/mk/tmpl/ptest/run/Makefile new file mode 100644 index 00000000..321601f0 --- /dev/null +++ b/l4/mk/tmpl/ptest/run/Makefile @@ -0,0 +1,10 @@ +PKGDIR ?= ../.. +L4DIR ?= $(PKGDIR)/../.. + +# insert the binary name of the server to test +TEST_SERVER = + +# insert the binary name of the application testing the server +TEST_CLIENT = + +include $(L4DIR)/mk/runux.mk diff --git a/l4/mk/tmpl/server/Makefile b/l4/mk/tmpl/server/Makefile new file mode 100644 index 00000000..528e0ac7 --- /dev/null +++ b/l4/mk/tmpl/server/Makefile @@ -0,0 +1,9 @@ +PKGDIR ?= .. +L4DIR ?= $(PKGDIR)/../.. + +# the default is to build the listed directories, provided that they +# contain a Makefile. If you need to change this, uncomment the following +# line and adapt it. +# TARGET = src + +include $(L4DIR)/mk/subdir.mk diff --git a/l4/mk/tmpl/server/src/Makefile b/l4/mk/tmpl/server/src/Makefile new file mode 100644 index 00000000..e61e0ff3 --- /dev/null +++ b/l4/mk/tmpl/server/src/Makefile @@ -0,0 +1,13 @@ +PKGDIR ?= ../.. +L4DIR ?= $(PKGDIR)/../.. + +TARGET = $(PKGNAME) + +# list your .c or .cc files here +SRC_C = main.c +SRC_CC = + +# list requirements of your program here +REQUIRES_LIBS = + +include $(L4DIR)/mk/prog.mk diff --git a/l4/mk/tmpl/server/src/main.c b/l4/mk/tmpl/server/src/main.c new file mode 100644 index 00000000..65eddcf8 --- /dev/null +++ b/l4/mk/tmpl/server/src/main.c @@ -0,0 +1,5 @@ + +int main(int argc, char **argv) +{ + return 0; +} diff --git a/l4/pkg/Makefile b/l4/pkg/Makefile new file mode 100644 index 00000000..f605807b --- /dev/null +++ b/l4/pkg/Makefile @@ -0,0 +1,270 @@ +# GLOBAL Makefile for all packages +# +# DO NOT EDIT -- Automatically generated by Adam's configuration system!!! +# + +IGNORE_OBJDIR_TARGETS := up update diff + +L4DIR ?= .. +include $(L4DIR)/mk/Makeconf + +BID_STATE_FILE = $(OBJ_BASE)/pkg/BUILD.state + +# all our packages +ALL_SUBDIRS = $(shell find -L . -maxdepth 1 -type d ! -name .svn -printf %P' ') + +ifneq ($(S),) + ALL_SUBDIRS := $(shell echo $(S) | tr ':,' ' ') +endif + +# the broken packages +BROKEN_SUBDIRS = $(patsubst %/broken, %, \ + $(wildcard $(addsuffix /broken,$(ALL_SUBDIRS)))) +# the obsolete packages +OBSOLETE_SUBDIRS = $(patsubst %/obsolete, %, \ + $(wildcard $(addsuffix /obsolete,$(ALL_SUBDIRS)))) +# and the packages we are supposed to build +BUILD_SUBDIRS = $(filter-out $(BROKEN_SUBDIRS) $(OBSOLETE_SUBDIRS), \ + $(ALL_SUBDIRS)) + +# force that every package to be built has a Control and Makefile +ifneq ($(addsuffix /Makefile,$(BUILD_SUBDIRS)),$(wildcard $(addsuffix /Makefile,$(BUILD_SUBDIRS)))) +$(error Missing Makefile files: $(filter-out $(wildcard $(addsuffix /Makefile,$(BUILD_SUBDIRS))), $(addsuffix /Makefile,$(BUILD_SUBDIRS)))) +endif +ifeq ($(S),) +ifneq ($(addsuffix /Control,$(BUILD_SUBDIRS)),$(wildcard $(addsuffix /Control,$(BUILD_SUBDIRS)))) +$(error Missing Control files: $(filter-out $(wildcard $(addsuffix /Control,$(BUILD_SUBDIRS))), $(addsuffix /Control,$(BUILD_SUBDIRS)))) +endif +endif + +##################### +# Rules begin. +# We start with cont-checking, as this requires special treatment +ifeq ($(filter cont,$(MAKECMDGOALS)),) + +##################### +# default make action is "all" - build all packages +# +# We build all l4env headers (idl+includes), then all l4env libs, then the +# l4env servers and examples. Then we build the other headers +# (idl+includes), the other libs, the other servers and examples. We use +# dependencies for this, witch might allow parallel build processes. +# + +all:: $(BUILD_SUBDIRS) + +examples: $(filter-out examples,$(BUILD_SUBDIRS)) + +##################### +# cont handling +-include $(BID_STATE_FILE) +BID_cont_reset: + $(VERBOSE)$(RM) $(BID_STATE_FILE) +BID_SAFE_STATE= @echo 'BID_STATE_DONE+=$@'>>$(BID_STATE_FILE) + +.PHONY: all BID_cont_reset cont bin lib headers idl include doc ptest +.PHONY: rm-old-links + +DOC_MESSAGE =echo "=== Creating documentation for package \"$(1)\" ===" +PKG_MESSAGE =echo "=== Building package \"$(basename $@)\" ===" +INST_MESSAGE =echo "=== Installing Package \"$(1)\" ===" +PURGE_INC_MESSAGE =echo "=== Purging pending links in $(L4DIR)/include ===" +PURGE_LIB_MESSAGE =echo "=== Purging pending links in $(L4DIR)/lib ===" +UPDATE_MESSAGE =echo -e $(EMPHSTART)"=== Updating \"$(1)\" ==="$(EMPHSTOP) +DIFF_MESSAGE =echo -e $(EMPHSTART)"=== Diffing \"$(1)\" ==="$(EMPHSTOP) +PTEST_MESSAGE =echo "=== Testing Package \"$(1)\" ===" + +# given order matters +ALIASES_DIRS = $(L4DIR)/mk/aliases.d \ + $(wildcard $(OBJ_BASE)/aliases.d) + +PKGDEPS_CMD = $(L4DIR)/mk/pkgdeps \ + -P $(OBJ_BASE)/pc $(addprefix -A ,$(ALIASES_DIRS)) + +ifneq ($(OBJ_BASE),) +$(OBJ_BASE)/pc: + $(VERBOSE)mkdir -p $(OBJ_BASE)/pc + +# deps on disappearing aliases.d-files are not handled... +$(OBJ_BASE)/pkg/.Package.deps: $(L4DIR)/mk/pkgdeps \ + $(if $(filter update up,$(MAKECMDGOALS)),Makefile) \ + $(wildcard $(foreach d,$(ALIASES_DIRS),$(d)/*)) \ + $(OBJ_BASE)/pc \ + $(wildcard $(foreach d,$(BUILD_SUBDIRS),$(d)/Control)) + $(VERBOSE)mkdir -p $(dir $@) + $(VERBOSE)if $(PKGDEPS_CMD) \ + generate $(L4DIR)/pkg > $@.tmp; then \ + mv $@.tmp $@; else $(RM) $@.tmp; exit 1; fi + +include $(OBJ_BASE)/pkg/.Package.deps +endif + +$(BUILD_SUBDIRS):%:%/Makefile BID_cont_reset + @$(PKG_MESSAGE) + $(VERBOSE)PWD=$(PWD)/$(basename $@) $(MAKE) -C $(basename $@) all + $(VERBOSE)$(BID_SAFE_STATE) + +install:: + $(VERBOSE)set -e; for i in $(BUILD_SUBDIRS); do \ + $(call INST_MESSAGE,$(BID_DOLLARQUOTE)$$i); \ + PWD=$(PWD)/$$i $(MAKE) -C $$i $@; \ + done + +doc: + $(VERBOSE)set -e; for i in $(BUILD_SUBDIRS); do \ + if [ -e $(PWD)/$$i/doc ]; then \ + $(call DOC_MESSAGE,$(BID_DOLLARQUOTE)$$i); \ + PWD=$(PWD)/$$i $(MAKE) -C $$i $@; \ + fi; \ + done + +# Check package dependencies. +# CHECK_PKGS: if undefined, check all packages, +# otherwise gives a list of space separated packages to check +# CHECK_FULL: if set rebuild for every new package check +# (ccache recommended when using this flag) +depcheck: + $(VERBOSE)set -e; \ + $(RM) -r $(filter-out $(OBJ_BASE)/pkg/Makefile, \ + $(wildcard $(OBJ_BASE)/pkg/*)); \ + for checkpkg in $(filter-out $(CHECK_GOOD),$(if $(CHECK_PKGS),$(CHECK_PKGS),$(BUILD_SUBDIRS))); do \ + echo ==========================================================; \ + echo "Deleting all pkgs in build-dir"; \ + $(RM) -r $(OBJ_BASE)/lib $(OBJ_BASE)/bin $(OBJ_BASE)/include \ + $(OBJ_BASE)/pc; \ + $(if $(CHECK_FULL),$(RM) -r $(OBJ_BASE)/pkg;,) \ + echo "Done"; \ + echo ----------------------------------------------------------; \ + echo "Trying standalone build of '$$checkpkg'"; \ + echo $(MAKE) O=$(OBJ_BASE) --no-print-directory $$checkpkg; \ + $(MAKE) O=$(OBJ_BASE) --no-print-directory $$checkpkg \ + || (echo "Failed package: $$checkpkg"; \ + echo "Good package(s): CHECK_GOOD=\"$(CHECK_GOOD) $$PKGDONE\"";\ + exit 1) || exit 1; \ + PKGDONE="$$PKGDONE $$checkpkg"; \ + done; \ + echo "Packages tested: $(CHECK_GOOD) $$PKGDONE" + +depgraph: depsrcgraph depobjgraph +depsrcgraph: $(PKGDIR_OBJ)/depsrc.svg $(PKGDIR_OBJ)/depsrc.ps $(PKGDIR_OBJ)/depsrc.reduced.svg $(PKGDIR_OBJ)/depsrc.reduced.ps +depobjgraph: $(PKGDIR_OBJ)/depobj.svg $(PKGDIR_OBJ)/depobj.ps $(PKGDIR_OBJ)/depobj.reduced.svg $(PKGDIR_OBJ)/depobj.reduced.ps + +%.ps: %.dot + @$(GEN_MESSAGE) + $(VERBOSE)dot -Tps -o $@ $< + +%.svg: %.dot + @$(GEN_MESSAGE) + $(VERBOSE)dot -Tsvg -o $@ $< + +%.reduced.dot: %.dot + @$(GEN_MESSAGE) + $(VERBOSE)tred $< > $@ + +$(PKGDIR_OBJ)/depsrc.dot: FORCE + @$(GEN_MESSAGE) + $(VERBOSE)$(PKGDEPS_CMD) dot $(L4DIR)/pkg > $@ + +$(PKGDIR_OBJ)/depobj.dot: FORCE + @$(GEN_MESSAGE) + $(VERBOSE)$(L4DIR)/tool/bin/pkgdepsobj $(L4DIR_ABS) $(OBJ_BASE) $@ + +ptest: + $(VERBOSE)set -e; \ + for d in $(BUILD_SUBDIRS); do \ + if [ -n "$$(find $$d -type d -name $@)" ]; then \ + $(call PTEST_MESSAGE,$(BID_DOLLARQUOTE)$$d); \ + PWD=$(PWD)/$$d $(MAKE) -C $$d $@; \ + fi; \ + done + +TAGS: + $(ETAGS) + +tags: + $(CTAGS) + +.PHONY: TAGS tags depsrcgraph depobjgraph depgraph depcheck +.PHONY: $(foreach ext, .bin .lib .include .idl .headers,addsuffix $(ext), $(BUILD_SUBDIRS)) + +clean cleanall:: BID_cont_reset +clean cleanall:: + $(VERBOSE)$(RM) $(UPDATE_LOG) + $(VERBOSE)for i in $(BUILD_SUBDIRS) $(OBSOLETE_SUBDIRS); do \ + echo "=== Cleaning in package \"$$i\" ==="; \ + if [ -r $$i/Makefile ] ; then PWD=$(PWD)/$$i $(MAKE) -C $$i $@; fi ; \ + done + $(VERBOSE)$(MAKE) rm-old-links + +del-backup: + $(VERBOSE)rm -i `find . -name "*~"` `find . -name "#*#"` + +rm-old-links: + @$(PURGE_INC_MESSAGE) + $(VERBOSE)test ! -d $(L4DIR)/include || \ + find $(L4DIR)/include -type l -a ! -xtype f -a ! -xtype d \ + -exec rm $(if $(VERBOSE),,-v) '{}' ';' + @$(PURGE_LIB_MESSAGE) + $(VERBOSE)test ! -d $(L4DIR)/lib || \ + find $(L4DIR)/lib -type l -a ! -xtype f -a ! -xtype d \ + -exec rm $(if $(VERBOSE),,-v) '{}' ';' + + +# Update Makefile on update. +ifneq ($(filter update up,$(MAKECMDGOALS)),) +.PHONY: Makefile +Makefile: update.log + $(SVN) up $@ 2>&1 | tee -a $(UPDATE_LOG) +endif + +UPDATE_LOG = $(call absfilename, $(L4DIR)/pkg/update.log) +.PHONY: update.log +update.log: + $(VERBOSE)$(RM) $(UPDATE_LOG) + +update up: update.log + $(VERBOSE)$(call UPDATE_MESSAGE,Packages) + $(VERBOSE)set -e; \ + $(SVN) update $(ALL_SUBDIRS) 2>&1 | tee -a $(UPDATE_LOG) + +# global defines + +.PHONY: install clean cleanall kernels + + +print-subdirs: + @echo $(BUILD_SUBDIRS) + @echo obsolete: $(OBSOLETE_SUBDIRS) + @echo broken: $(BROKEN_SUBDIRS) + +help: + @echo "Specify one of the following targets:" + @echo "all - build the packages neither broken nor obsolete" + @echo " Use make S=dir1:dir2:..: to build those directories" + @echo "cont - after correcting errors, continue where \"make all\" failed" + @echo " - Build package and all its dependencies" +# @echo "doc - build documentation (not build per default)" + @echo "install - install the packages, use only after making all!" + @echo + @echo "clean - clean the packages" + @echo "cleanall - clean the packages pedanticly" + @echo "del-backup - remove temporary file in this tree" + @echo "print-subdirs - print the SUBDIRS which are subject to build" + @echo "BID_cont_reset - reset the state used by the \"cont\" target" + @echo 'rm-old-links - remove invalid symlinks in $$(L4DIR)/lib, $$(L4DIR)/include' + @echo "update - update the packages currently checked out" + @echo "help - this help" + +##################### +# cont handling: "cont" is in the target list +else +-include $(BID_STATE_FILE) +cont: + $(VERBOSE)$(MAKE) $(addprefix -o ,BID_cont_reset $(BID_STATE_DONE)) \ + $(filter-out cont,$(MAKECMDGOALS)) + +# eat up the other targets +.DEFAULT: + @true +endif + diff --git a/l4/pkg/README b/l4/pkg/README new file mode 100644 index 00000000..73f2f679 --- /dev/null +++ b/l4/pkg/README @@ -0,0 +1,66 @@ + +This directory contains software components that are split up in so-called +packages. The following list describes the core packages and those that are +not self descriptive: + +Core packages: + + - bootstrap L4 system boot loader / Boot-image generator + - crtn Program startup support, part of C environment + - cxx* C++ library containing + - Data structures: AVL trees, lists, bitmaps + - L4 IPC framework + - drivers Driver libraries (e.g. UARTs) + - io Io server, maintains the platform and I/O resources + - l4re L4 Runtime Environment interfaces and library, C++ version + - l4re_c C interface for L4 Runtime Environment + - l4re_kernel L4 Runtime Environment system + - l4re_vfs L4Re Virtual Filesystem infrastructure + - l4sys Kernel bindings + - l4util Utility functions + - ldscripts Linker scripts + - ldso Dynamic library support + - libc_backends Glue code between C library and L4 Runtime Environment + such as memory and file handling + - libio Interface and library to access device resources + (e.g. MMIO, IRQs) + - libio-io Specific interface library code for the io server. + - libloader Support library for l4re and moe. + - libsigma0 Sigma0 API library. + - libstdc++-headers Standard C++ library headers + - libstdc++-v3 Standard C++ library + - libstdc++-v3_r Standard C++ library, thread-safe + - libsupc++ Standard C++ Runtime Environment + - libsupc++_r Standard C++ Runtime Environment, thread-safe + - libvbus Virtual bus library for devices + - loader L4Re program loader + - log Library for debug logging support + - lua Lua interpreter and library + - moe L4 Root task (essential L4 program) + - ned Scriptable application launcher + - sigma0 L4 Root pager (essential L4 program) + - ucblic Standard C library, including POSIX thread environment + - uclibc_r Meta package for thread-safe standard C library + + +Other packages: + + - ankh Network server and switch + - boost-lite Subset of the boost library + - dope DOpE windowing system + - examples Examples + - fb-drv Framebuffer driver server + - hello 'Hello World!' example + - input Driver library for input devices (PS2: Keyboard, Mouse) + - l4con Graphical console + - libgomp Open MP library for gcc + - libirq Convenience library for IRQ handling. + - libpng libpng graphics library. + - libsdl* SDL library + - lxfuxlibc Support library for Fiasco-UX specific programs + - mag Windowing system + - mag-gfx Graphic routines + - rtc Real-Time clock service + - scout* Text browser + - shmc Communication infracture based on shared memory + - zlib zlib compression library diff --git a/l4/pkg/bootstrap/Control b/l4/pkg/bootstrap/Control new file mode 100644 index 00000000..e6cd01c4 --- /dev/null +++ b/l4/pkg/bootstrap/Control @@ -0,0 +1,2 @@ +requires: drivers_uart drivers_of libc_minimal l4util cxx_io +Maintainer: frenzel@os.inf.tu-dresden.de, adam@os.inf.tu-dresden.de, warg@os.inf.tu-dresden.de diff --git a/l4/pkg/bootstrap/LEGAL b/l4/pkg/bootstrap/LEGAL new file mode 100644 index 00000000..1ade4a8e --- /dev/null +++ b/l4/pkg/bootstrap/LEGAL @@ -0,0 +1,43 @@ +# Format: (all on one line) +# Source file : Copyright Owner(s) : License +# Please use "TUD" when referring to TU Dresden. +# If sole owner is TUD, the license field defaults to GPL and can be +# left empty. +# Source-file spec can be a directory name or a wildcard like "src/*.c". +Makefile : TUD +server/Makefile : TUD +server/src/ARCH-x86/bootsect.S : GPL +server/src/ARCH-x86/bootstrap.ld.in : TUD +server/src/ARCH-x86/crt0.S : TUD +server/src/ARCH-x86/oskit_support.c : TUD +server/src/ARCH-x86/serial.c : TUD +server/src/ARCH-x86/serial.h : TUD +server/src/ARCH-x86/setup.S : GPL +server/src/ARCH-x86/xen.c +server/src/ARCH-arm/bootstrap.ld.in : TUD +server/src/Makefile : TUD +server/src/base_critical.c : TUD +server/src/base_critical.h : TUD +server/src/build.pl : TUD +server/src/exec.c : TUD +server/src/exec.h : TUD +server/src/gunzip.c : GPL +server/src/gunzip.h : GPL +server/src/init.h : TUD +server/src/init_hazelnut.c : TUD +server/src/init_ibm_nucleus.c : TUD +server/src/init_l4_gmd.c : TUD +server/src/libc_support.c : TUD +server/src/loader_mbi.c : TUD +server/src/loader_mbi.h : TUD +server/src/module.h : TUD +server/src/modules.list : TUD +server/src/region.c : TUD +server/src/region.h : TUD +server/src/startup.c : TUD +server/src/startup.h : TUD +server/src/types.h : TUD : TUD +server/src/uncompress.c : TUD +server/src/uncompress.h : TUD +server/src/version.h : TUD + diff --git a/l4/pkg/bootstrap/Makefile b/l4/pkg/bootstrap/Makefile new file mode 100644 index 00000000..f8ca7cc2 --- /dev/null +++ b/l4/pkg/bootstrap/Makefile @@ -0,0 +1,4 @@ +PKGDIR = . +L4DIR ?= $(PKGDIR)/../.. + +include $(L4DIR)/mk/subdir.mk diff --git a/l4/pkg/bootstrap/README b/l4/pkg/bootstrap/README new file mode 100644 index 00000000..850419cd --- /dev/null +++ b/l4/pkg/bootstrap/README @@ -0,0 +1,40 @@ +L4 Bootstrapper for booting Fiasco and other L4 compatible kernels. + +Command line parameters (in alphabetical order): + + -comport= + If serial logging is enabled, defines which serial port to use, + where 1 is the first port found. + NOTE: Bootstrap does not support the -comspeed= option and uses + the port with 115200 bps. + + -hercules + --- DOCUMENTATION MISSING --- + + -maxmem= + Set the mem_upper field of the multiboot info structure. + + -patch=,=,... + is compared with the path name of each module to decide which + module should be patched. If the module was found, each occurrence of + is replaced by . can also be quoted + text. Otherwise no spaces are allowed. + + -arg=, + is compared with the path name of each module to decide which + module arguments should be replaced. If the module was found, the module + arguments, that is all text of the module command line after the first + ' ' is replaced by . can also be quoted text. + + -roottask + No effect -- Provided for compatibility with RMGR. + + -serial + Enables support for logging to serial line. + + -sigma0 + No effect -- Provided for compatibility with RMGR. + + -modaddr= + Relocate modules to the physical address ADDR. Eliminates the + need for a specialized GRUB that supports the modaddr command. diff --git a/l4/pkg/bootstrap/server/Makefile b/l4/pkg/bootstrap/server/Makefile new file mode 100644 index 00000000..04ac0da0 --- /dev/null +++ b/l4/pkg/bootstrap/server/Makefile @@ -0,0 +1,4 @@ +PKGDIR ?= .. +L4DIR ?= $(PKGDIR)/../.. + +include $(L4DIR)/mk/subdir.mk diff --git a/l4/pkg/bootstrap/server/src/ARCH-amd64/boot32/boot.S b/l4/pkg/bootstrap/server/src/ARCH-amd64/boot32/boot.S new file mode 100644 index 00000000..c67c912f --- /dev/null +++ b/l4/pkg/bootstrap/server/src/ARCH-amd64/boot32/boot.S @@ -0,0 +1,63 @@ +/* + * (c) 2009 Frank Mehnert , + * Torsten Frenzel + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ +/* -*- c -*- */ + + .globl _start + .p2align 4 +_start: +#ifdef REALMODE_LOADING + cld + cli + mov $(3 * 8), %eax + mov %eax, %ds + mov %eax, %es + mov %eax, %fs + mov %eax, %gs + + /* We have the following problem: Our image is loaded at 0x00100000 + * by the boot loader but we don't want to get into conflict with + * the AMD64 executable. Therefore we move ourself out of the way. + * We are linked to 0x01000000 (see ARCH-amd64/boot32/bootstrap.ld) */ + mov %esi, %ebx + mov $0x00100000, %esi + mov $0x01000000, %edi + mov $_image_end, %ecx + sub $_image_start, %ecx + rep movsb + mov $1f, %eax + jmp *%eax +1: mov %ebx, %esi + lss _stack_seg, %esp +#else + leal _stack,%esp +#endif + + pushl %esi /* ptr to real mode */ + pushl %eax + pushl %ebx + pushl $0 /* no return address */ + jmp bootstrap + + .align 4 + + .p2align(2), 0x90 + .long 0x1BADB002 /* magic */ + .long 0x00000000 /* feature flags */ + .long 0 - 0x1BADB002 + +#ifdef REALMODE_LOADING +_stack_seg: + .long _stack + .word (3 * 8) +#endif + + .bss + .space 8192 +_stack: diff --git a/l4/pkg/bootstrap/server/src/ARCH-amd64/boot32/boot_cpu.c b/l4/pkg/bootstrap/server/src/ARCH-amd64/boot32/boot_cpu.c new file mode 100644 index 00000000..c20ee9d9 --- /dev/null +++ b/l4/pkg/bootstrap/server/src/ARCH-amd64/boot32/boot_cpu.c @@ -0,0 +1,639 @@ +/* + * (c) 2009 Adam Lackorzynski , + * Frank Mehnert + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ +#include +#include +#include +#include + +#include "types.h" +#include "boot_cpu.h" +#include "boot_paging.h" + + +unsigned KERNEL_CS_64 = 0x20; // XXX + +enum +{ + PML4ESHIFT = 38, + PML4EMASK = 0x1ff, + PDPESHIFT = 30, + PDPEMASK = 0x1ff, + PDESHIFT = 21, + PDEMASK = 0x1ff, + PTESHIFT = 12, + PTEMASK = 0x1ff, + + INTEL_PTE_VALID = 0x0000000000000001LL, + INTEL_PTE_WRITE = 0x0000000000000002LL, + INTEL_PTE_USER = 0x0000000000000004LL, + INTEL_PTE_WTHRU = 0x00000008, + INTEL_PTE_NCACHE = 0x00000010, + INTEL_PTE_REF = 0x00000020, + INTEL_PTE_MOD = 0x00000040, + INTEL_PTE_GLOBAL = 0x00000100, + INTEL_PTE_AVAIL = 0x00000e00, + INTEL_PTE_PFN = 0x000ffffffffff000LL, + + INTEL_PDE_VALID = 0x0000000000000001LL, + INTEL_PDE_WRITE = 0x0000000000000002LL, + INTEL_PDE_USER = 0x0000000000000004LL, + INTEL_PDE_WTHRU = 0x00000008, + INTEL_PDE_NCACHE = 0x00000010, + INTEL_PDE_REF = 0x00000020, + INTEL_PDE_MOD = 0x00000040, + INTEL_PDE_SUPERPAGE = 0x0000000000000080LL, + INTEL_PDE_GLOBAL = 0x00000100, + INTEL_PDE_AVAIL = 0x00000e00, + INTEL_PDE_PFN = 0x000ffffffffff000LL, + + INTEL_PDPE_VALID = 0x0000000000000001LL, + INTEL_PDPE_WRITE = 0x0000000000000002LL, + INTEL_PDPE_USER = 0x0000000000000004LL, + INTEL_PDPE_PFN = 0x000ffffffffff000LL, + + INTEL_PML4E_VALID = 0x0000000000000001LL, + INTEL_PML4E_WRITE = 0x0000000000000002LL, + INTEL_PML4E_USER = 0x0000000000000004LL, + INTEL_PML4E_PFN = 0x000ffffffffff000LL, + + CPUF_4MB_PAGES = 0x00000008, + + CR0_PG = 0x80000000, + CR4_PSE = 0x00000010, + CR4_PAE = 0x00000020, + EFL_AC = 0x00040000, + EFL_ID = 0x00200000, + EFER_LME = 0x00000100, + + BASE_TSS = 0x08, + KERNEL_CS = 0x10, + KERNEL_DS = 0x18, + + DBF_TSS = 0x28, // XXX check this value + + ACC_TSS = 0x09, + ACC_TSS_BUSY = 0x02, + ACC_CODE_R = 0x1a, + ACC_DATA_W = 0x12, + ACC_PL_K = 0x00, + ACC_P = 0x80, + SZ_32 = 0x4, + SZ_16 = 0x0, + SZ_G = 0x8, + SZ_CODE_64 = 0x2, // XXX 64 Bit Code Segment + + GDTSZ = (0x30/8), // XXX check this value + IDTSZ = 256, +}; + + +struct pseudo_descriptor +{ + l4_uint16_t pad; + l4_uint16_t limit; + l4_uint32_t linear_base; +}; + +struct x86_desc +{ + l4_uint16_t limit_low; /* limit 0..15 */ + l4_uint16_t base_low; /* base 0..15 */ + l4_uint8_t base_med; /* base 16..23 */ + l4_uint8_t access; /* access byte */ + l4_uint8_t limit_high:4; /* limit 16..19 */ + l4_uint8_t granularity:4; /* granularity */ + l4_uint8_t base_high; /* base 24..31 */ +} __attribute__((packed)); + +struct x86_gate +{ + l4_uint16_t offset_low; /* offset 0..15 */ + l4_uint16_t selector; + l4_uint8_t word_count; + l4_uint8_t access; + l4_uint16_t offset_high; /* offset 16..31 */ +} __attribute__((packed)); + +struct x86_tss +{ + l4_uint32_t back_link; + l4_uint32_t esp0, ss0; + l4_uint32_t esp1, ss1; + l4_uint32_t esp2, ss2; + l4_uint32_t cr3; + l4_uint32_t eip, eflags; + l4_uint32_t eax, ecx, edx, ebx, esp, ebp, esi, edi; + l4_uint32_t es, cs, ss, ds, fs, gs; + l4_uint32_t ldt; + l4_uint16_t trace_trap; + l4_uint16_t io_bit_map_offset; +}; + +struct gate_init_entry +{ + l4_uint32_t entrypoint; + l4_uint16_t vector; + l4_uint16_t type; +}; + +struct trap_state +{ + l4_uint32_t gs, fs, es, ds; + l4_uint32_t edi, esi, ebp, cr2, ebx, edx, ecx, eax; + l4_uint32_t trapno, err; + l4_uint32_t eip, cs, eflags, esp, ss; +}; + +static l4_uint32_t cpu_feature_flags; +static l4_uint32_t base_pml4_pa; +static struct x86_tss base_tss; +static struct x86_desc base_gdt[GDTSZ]; +static struct x86_gate base_idt[IDTSZ]; + +static void handle_dbf(void); +static char dbf_stack[2048]; +static struct x86_tss dbf_tss = + { + 0/*back_link*/, + 0/*esp0*/, 0/*ss0*/, 0/*esp1*/, 0/*ss1*/, 0/*esp2*/, 0/*ss2*/, + 0/*cr3*/, + (l4_uint32_t)handle_dbf/*eip*/, 0x00000082/*eflags*/, + 0/*eax*/, 0/*ecx*/, 0/*edx*/, 0/*ebx*/, + (l4_uint32_t)dbf_stack + sizeof(dbf_stack)/*esp*/, + 0/*ebp*/, 0/*esi*/, 0/*edi*/, + KERNEL_DS/*es*/, KERNEL_CS/*cs*/, KERNEL_DS/*ss*/, + KERNEL_DS/*ds*/, KERNEL_DS/*fs*/, KERNEL_DS/*gs*/, + 0/*ldt*/, 0/*trace_trap*/, 0x8000/*io_bit_map_offset*/ + }; + +static inline l4_uint64_t* find_pml4e(l4_uint32_t pml4_pa, l4_uint64_t la) +{ return (&((l4_uint64_t*)pml4_pa)[(la >> PML4ESHIFT) & PML4EMASK]); } + +static inline l4_uint64_t* find_pdpe(l4_uint32_t pdp_pa, l4_uint64_t la) +{ return (&((l4_uint64_t*)pdp_pa)[(la >> PDPESHIFT) & PDPEMASK]); } + +static inline l4_uint64_t* find_pde(l4_uint32_t pdir_pa, l4_uint64_t la) +{ return (&((l4_uint64_t*)pdir_pa)[(la >> PDESHIFT) & PDEMASK]); } + +static inline l4_uint64_t* find_pte(l4_uint32_t ptab_pa, l4_uint64_t la) +{ return (&((l4_uint64_t*)ptab_pa)[(la >> PTESHIFT) & PTEMASK]); } + +static inline l4_uint32_t get_eflags(void) +{ l4_uint32_t efl; asm volatile("pushf ; popl %0" : "=r" (efl)); return efl; } + +static inline void set_eflags(l4_uint32_t efl) +{ asm volatile("pushl %0 ; popf" : : "r" (efl) : "memory"); } + +static inline void set_ds(l4_uint16_t ds) +{ asm volatile("movw %w0,%%ds" : : "r" (ds)); } + +static inline void set_es(l4_uint16_t es) +{ asm volatile("movw %w0,%%es" : : "r" (es)); } + +static inline void set_fs(l4_uint16_t fs) +{ asm volatile("movw %w0,%%fs" : : "r" (fs)); } + +static inline void set_gs(l4_uint16_t gs) +{ asm volatile("movw %w0,%%gs" : : "r" (gs)); } + +static inline void set_ss(l4_uint16_t ss) +{ asm volatile("movw %w0,%%ss" : : "r" (ss)); } + +static inline l4_uint16_t get_ss(void) +{ l4_uint16_t ss; asm volatile("movw %%ss,%w0" : "=r" (ss)); return ss; } + +#define set_idt(pseudo_desc) \ + asm volatile("lidt %0" : : "m" ((pseudo_desc)->limit) : "memory") + +#define set_gdt(pseudo_desc) \ + asm volatile("lgdt %0" : : "m" ((pseudo_desc)->limit) : "memory") + +#define set_tr(seg) \ + asm volatile("ltr %0" : : "rm" ((l4_uint16_t)(seg))) + +#define get_esp() \ + ({ register l4_uint32_t _temp__; \ + asm("movl %%esp, %0" : "=r" (_temp__)); _temp__; }) + +#define get_cr0() \ + ({ register l4_uint32_t _temp__; \ + asm volatile("mov %%cr0, %0" : "=r" (_temp__)); _temp__; }) + +#define set_cr3(value) \ + ({ register l4_uint32_t _temp__ = (value); \ + asm volatile("mov %0, %%cr3" : : "r" (_temp__)); }) + +#define get_cr4() \ + ({ register l4_uint32_t _temp__; \ + asm volatile("mov %%cr4, %0" : "=r" (_temp__)); _temp__; }) + +#define set_cr4(value) \ + ({ register l4_uint32_t _temp__ = (value); \ + asm volatile("mov %0, %%cr4" : : "r" (_temp__)); }) + + +static inline void enable_longmode(void) +{ + l4_uint32_t dummy; + asm volatile("rdmsr; bts $8, %%eax; wrmsr" + :"=a"(dummy), "=d"(dummy) : "c"(0xc0000080)); +} + +static inline void +fill_descriptor(struct x86_desc *desc, l4_uint32_t base, l4_uint32_t limit, + l4_uint8_t access, l4_uint8_t sizebits) +{ + if (limit > 0xfffff) + { + limit >>= 12; + sizebits |= SZ_G; + } + desc->limit_low = limit & 0xffff; + desc->base_low = base & 0xffff; + desc->base_med = (base >> 16) & 0xff; + desc->access = access | ACC_P; + desc->limit_high = limit >> 16; + desc->granularity = sizebits; + desc->base_high = base >> 24; +} + +static inline void +fill_gate(struct x86_gate *gate, l4_uint32_t offset, + l4_uint16_t selector, l4_uint8_t access) +{ + gate->offset_low = offset & 0xffff; + gate->selector = selector; + gate->word_count = 0; + gate->access = access | ACC_P; + gate->offset_high = (offset >> 16) & 0xffff; +} + +static inline void +paging_enable(l4_uint32_t pml4) +{ + /* Enable Physical l4_uint64_t Extension (PAE). */ + set_cr4(get_cr4() | CR4_PAE); + + /* Load the page map level 4. */ + set_cr3(pml4); + + /* Enable long mode. */ + enable_longmode(); + + /* Turn on paging and switch to long mode. */ + asm volatile("movl %0,%%cr0 ; jmp 1f ; 1:" : : "r" (get_cr0() | CR0_PG)); +} + +static void +panic(const char *str) +{ + printf("PANIC: %s\n", str); + while (1) + ; + _exit(-1); +} + +static void +cpuid(void) +{ + int orig_eflags = get_eflags(); + + /* Check for a dumb old 386 by trying to toggle the AC flag. */ + set_eflags(orig_eflags ^ EFL_AC); + if ((get_eflags() ^ orig_eflags) & EFL_AC) + { + /* It's a 486 or better. Now try toggling the ID flag. */ + set_eflags(orig_eflags ^ EFL_ID); + if ((get_eflags() ^ orig_eflags) & EFL_ID) + { + int highest_val, dummy; + asm volatile("cpuid" + : "=a" (highest_val) + : "a" (0) : "ebx", "ecx", "edx"); + + if (highest_val >= 1) + { + asm volatile("cpuid" + : "=a" (dummy), + "=d" (cpu_feature_flags) + : "a" (1) + : "ebx", "ecx"); + } + } + } + + set_eflags(orig_eflags); +} + +extern struct gate_init_entry boot_idt_inittab[]; +static void +base_idt_init(void) +{ + struct x86_gate *dst = base_idt; + const struct gate_init_entry *src = boot_idt_inittab; + + while (src->entrypoint) + { + if ((src->type & 0x1f) == 0x05) + // task gate + fill_gate(&dst[src->vector], 0, src->entrypoint, src->type); + else + // interrupt gate + fill_gate(&dst[src->vector], src->entrypoint, KERNEL_CS, src->type); + src++; + } +} + +static void +base_gdt_init(void) +{ + /* Initialize the base TSS descriptor. */ + fill_descriptor(&base_gdt[BASE_TSS / 8], + (l4_uint32_t)&base_tss, sizeof(base_tss) - 1, + ACC_PL_K | ACC_TSS, 0); + /* Initialize the TSS descriptor for the double fault handler */ + fill_descriptor(&base_gdt[DBF_TSS / 8], + (l4_uint32_t)&dbf_tss, sizeof(dbf_tss) - 1, + ACC_PL_K | ACC_TSS, 0); + /* Initialize the 32-bit kernel code and data segment descriptors + to point to the base of the kernel linear space region. */ + fill_descriptor(&base_gdt[KERNEL_CS / 8], 0, 0xffffffff, + ACC_PL_K | ACC_CODE_R, SZ_32); + fill_descriptor(&base_gdt[KERNEL_DS / 8], 0, 0xffffffff, + ACC_PL_K | ACC_DATA_W, SZ_32); + /* XXX Initialize the 64-bit kernel code segment descriptor */ + fill_descriptor(&base_gdt[KERNEL_CS_64 / 8], 0, 0xffffffff, + ACC_PL_K | ACC_CODE_R, SZ_CODE_64); +} + +static void +base_tss_init(void) +{ + base_tss.ss0 = KERNEL_DS; + base_tss.esp0 = get_esp(); /* only temporary */ + base_tss.io_bit_map_offset = sizeof(base_tss); +} + +static void +base_gdt_load(void) +{ + struct pseudo_descriptor pdesc; + + /* Create a pseudo-descriptor describing the GDT. */ + pdesc.limit = sizeof(base_gdt) - 1; + pdesc.linear_base = (l4_uint32_t)&base_gdt; + + /* Load it into the CPU. */ + set_gdt(&pdesc); + + /* Reload all the segment registers from the new GDT. */ + asm volatile("ljmp %0,$1f ; 1:" : : "i" (KERNEL_CS)); + set_ds(KERNEL_DS); + set_es(KERNEL_DS); + set_ss(KERNEL_DS); + set_fs(0); + set_gs(0); +} + +static void +base_idt_load(void) +{ + struct pseudo_descriptor pdesc; + + /* Create a pseudo-descriptor describing the GDT. */ + pdesc.limit = sizeof(base_idt) - 1; + pdesc.linear_base = (l4_uint32_t)&base_idt; + set_idt(&pdesc); +} + +static void +base_tss_load(void) +{ + /* Make sure the TSS isn't marked busy. */ + base_gdt[BASE_TSS / 8].access &= ~ACC_TSS_BUSY; + set_tr(BASE_TSS); +} + +void +base_cpu_setup(void) +{ + cpuid(); + base_idt_init(); + base_gdt_init(); + base_tss_init(); + // force tables to memory before loading segment registers + asm volatile ("" : : : "memory"); + base_gdt_load(); + base_idt_load(); + base_tss_load(); +} + +struct ptab64_mem_info_t ptab64_mem_info; + +static void +ptab_alloc(l4_uint32_t *out_ptab_pa) +{ + // this pool covers around 128GB physical memory + static char pool[150<<12] __attribute__((aligned(4096))); + static l4_uint32_t pdirs; + static int initialized; + + if (! initialized) + { + initialized = 1; + ptab64_mem_info.addr = (l4_uint32_t)pool; + ptab64_mem_info.size = sizeof(pool); + memset(pool, 0, sizeof(pool)); + pdirs = ((l4_uint32_t)pool + PAGE_SIZE - 1) & ~PAGE_MASK; + } + + if (pdirs > (l4_uint32_t)pool + sizeof(pool)) + panic("Cannot allocate page table -- increase ptab_alloc::pool"); + + *out_ptab_pa = pdirs; + pdirs += PAGE_SIZE; +} + +static void +pdir_map_range(l4_uint32_t pml4_pa, l4_uint64_t la, l4_uint64_t pa, + l4_uint64_t size, l4_uint32_t mapping_bits) +{ + assert(size); + assert(la+size-1 > la); // avoid 4GB wrap around + + while (size > 0) + { + l4_uint64_t *pml4e = find_pml4e(pml4_pa, la); + + /* Create new pml4e with corresponding pdp (page directory pointer) + * if no valid entry exists. */ + if (!(*pml4e & INTEL_PML4E_VALID)) + { + l4_uint32_t pdp_pa; + + /* Allocate new page for pdp. */ + ptab_alloc(&pdp_pa); + + /* Set the pml4 to point to it. */ + *pml4e = (pdp_pa & INTEL_PML4E_PFN) + | INTEL_PML4E_VALID | INTEL_PML4E_USER | INTEL_PML4E_WRITE; + } + + do + { + l4_uint64_t *pdpe = find_pdpe(*pml4e & INTEL_PML4E_PFN, la); + + /* Create new pdpe with corresponding pd (page directory) + * if no valid entry exists. */ + if (!(*pdpe & INTEL_PDPE_VALID)) + { + l4_uint32_t pd_pa; + + /* Allocate new page for pd. */ + ptab_alloc(&pd_pa); + + /* Set the pdpe to point to it. */ + *pdpe = (pd_pa & INTEL_PDPE_PFN) + | INTEL_PDPE_VALID | INTEL_PDPE_USER | INTEL_PDPE_WRITE; + } + + do + { + l4_uint64_t *pde = find_pde(*pdpe & INTEL_PDPE_PFN, la); + + /* Use a 2MB page if we can. */ + if (superpage_aligned(la) && superpage_aligned(pa) + && (size >= SUPERPAGE_SIZE)) + //&& (cpu_feature_flags & CPUF_4MB_PAGES)) XXX + { + /* a failed assertion here may indicate a memory wrap + around problem */ + assert(!(*pde & INTEL_PDE_VALID)); + /* XXX what if an empty page table exists + from previous finer-granularity mappings? */ + *pde = pa | mapping_bits | INTEL_PDE_SUPERPAGE; + la += SUPERPAGE_SIZE; + pa += SUPERPAGE_SIZE; + size -= SUPERPAGE_SIZE; + } + else + { + /* Find the page table, creating one if necessary. */ + if (!(*pde & INTEL_PDE_VALID)) + { + l4_uint32_t ptab_pa; + + /* Allocate a new page table. */ + ptab_alloc(&ptab_pa); + + /* Set the pde to point to it. */ + *pde = (ptab_pa & INTEL_PTE_PFN) + | INTEL_PDE_VALID | INTEL_PDE_USER | INTEL_PDE_WRITE; + } + assert(!(*pde & INTEL_PDE_SUPERPAGE)); + + + /* Use normal 4KB page mappings. */ + do + { + l4_uint64_t *pte = find_pte(*pde & INTEL_PDE_PFN, la); + assert(!(*pte & INTEL_PTE_VALID)); + + /* Insert the mapping. */ + *pte = pa | mapping_bits; + + /* Advance to the next page. */ + //pte++; + la += PAGE_SIZE; + pa += PAGE_SIZE; + size -= PAGE_SIZE; + } + while ((size > 0) && !superpage_aligned(la)); + } + } + while ((size > 0) && !pd_aligned(la)); + } + while ((size > 0) && !pdp_aligned(la)); + } +} + +void +base_paging_init(l4_uint64_t phys_mem_max) +{ + ptab_alloc(&base_pml4_pa); + + // Establish one-to-one mappings for the physical memory + pdir_map_range(base_pml4_pa, 0, 0, phys_mem_max, + INTEL_PDE_VALID | INTEL_PDE_WRITE | INTEL_PDE_USER); + + //dbf_tss.cr3 = base_pml4_pa; + + // XXX Turn on paging and activate long mode + paging_enable(base_pml4_pa); +} + +void trap_dump_panic(const struct trap_state *st); +void trap_dump_panic(const struct trap_state *st) +{ + int from_user = st->cs & 3; + int i; + + printf("EAX %08x EBX %08x ECX %08x EDX %08x\n", + st->eax, st->ebx, st->ecx, st->edx); + printf("ESI %08x EDI %08x EBP %08x ESP %08x\n", + st->esi, st->edi, st->ebp, + from_user ? st->esp : (l4_uint32_t)&st->esp); + printf("EIP %08x EFLAGS %08x\n", st->eip, st->eflags); + printf("CS %04x SS %04x DS %04x ES %04x FS %04x GS %04x\n", + st->cs & 0xffff, from_user ? st->ss & 0xffff : get_ss(), + st->ds & 0xffff, st->es & 0xffff, + st->fs & 0xffff, st->gs & 0xffff); + printf("trapno %d, error %08x, from %s mode\n", + st->trapno, st->err, from_user ? "user" : "kernel"); + + if (st->trapno == 0x0d) + { + if (st->err & 1) + printf("(external event"); + else + printf("(internal event"); + if (st->err & 2) + printf(" regarding IDT gate descriptor no. 0x%02x)\n", st->err >> 3); + else + printf(" regarding %s entry no. 0x%02x)\n", + st->err & 4 ? "LDT" : "GDT", st->err >> 3); + } + else if (st->trapno == 0x0e) + printf("page fault linear address %08x\n", st->cr2); + + if (!from_user) + for (i = 0; i < 32; i++) + printf("%08x%c", (&st->esp)[i], ((i & 7) == 7) ? '\n' : ' '); + + panic("Unexpected trap while booting Fiasco!"); +} + +static void +handle_dbf(void) +{ + /* + printf("\n" + "EAX %08x EBX %08x ECX %08x EDX %08x\n" + "ESI %08x EDI %08x EBP %08x ESP %08x\n" + "EIP %08x EFLAGS %08x\n" + "CS %04x SS %04x DS %04x ES %04x FS %04x GS %04x\n\n", + base_tss.eax, base_tss.ebx, base_tss.ecx, base_tss.edx, + base_tss.esi, base_tss.edi, base_tss.ebp, base_tss.esp, + base_tss.eip, base_tss.eflags, + base_tss.cs & 0xffff, base_tss.ss & 0xffff, base_tss.ds & 0xffff, + base_tss.es & 0xffff, base_tss.fs & 0xffff, base_tss.gs & 0xffff); + */ + panic("Unexpected DOUBLE FAULT while booting Fiasco!"); +} diff --git a/l4/pkg/bootstrap/server/src/ARCH-amd64/boot32/boot_cpu.h b/l4/pkg/bootstrap/server/src/ARCH-amd64/boot32/boot_cpu.h new file mode 100644 index 00000000..54a84771 --- /dev/null +++ b/l4/pkg/bootstrap/server/src/ARCH-amd64/boot32/boot_cpu.h @@ -0,0 +1,20 @@ +/* + * (c) 2009 Adam Lackorzynski , + * Torsten Frenzel + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ +#ifndef BOOT_CPU_H +#define BOOT_CPU_H + +#include "types.h" + +void base_paging_init (l4_uint64_t); +void base_cpu_setup (void); + +extern struct ptab64_mem_info_t ptab64_mem_info; + +#endif diff --git a/l4/pkg/bootstrap/server/src/ARCH-amd64/boot32/boot_idt.S b/l4/pkg/bootstrap/server/src/ARCH-amd64/boot32/boot_idt.S new file mode 100644 index 00000000..7ded85fc --- /dev/null +++ b/l4/pkg/bootstrap/server/src/ARCH-amd64/boot32/boot_idt.S @@ -0,0 +1,99 @@ +/* + * (c) 2009 Torsten Frenzel + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ + +#define GATE_INITTAB_BEGIN(name) \ + .text 1 ;\ + .globl name ;\ +name: ;\ + .text + +#define GATE_ENTRY(n,entry,type) \ + .text 1 ;\ + .long entry ;\ + .word n ;\ + .word type ;\ + .text + +#define GATE_INITTAB_END \ + .text 1 ;\ + .long 0 ;\ + .text + +#define EXCEPTION(n,name) \ + GATE_ENTRY(n,name,0x0e) ;\ +name: ;\ + pushl $(0) ;\ + pushl $(n) ;\ + jmp alltraps + +#define EXCEP_USR(n,name) \ + GATE_ENTRY(n,name,0x6e) ;\ +name: ;\ + pushl $(0) ;\ + pushl $(n) ;\ + jmp alltraps + +#define EXCEP_ERR(n,name) \ + GATE_ENTRY(n,name,0x0e) ;\ +name: ;\ + pushl $(n) ;\ + jmp alltraps + + +GATE_INITTAB_BEGIN(boot_idt_inittab) + +EXCEPTION(0x00,t_zero_div) +EXCEPTION(0x01,t_debug) +EXCEPTION(0x02,t_nmi) +EXCEP_USR(0x03,t_int3) +EXCEP_USR(0x04,t_into) +EXCEP_USR(0x05,t_bounds) +EXCEPTION(0x06,t_invop) +EXCEPTION(0x07,t_nofpu) +GATE_ENTRY(0x08,0x20,0x05) +EXCEPTION(0x09,a_fpu_over) +EXCEP_ERR(0x0a,a_inv_tss) +EXCEP_ERR(0x0b,t_segnp) +EXCEP_ERR(0x0c,t_stack_fault) +EXCEP_ERR(0x0d,t_gen_prot) +EXCEP_ERR(0x0e,t_page_fault) +EXCEPTION(0x0f,t_trap_0f) +EXCEPTION(0x10,t_fpu_err) +EXCEPTION(0x11,t_trap_11) +EXCEPTION(0x12,t_trap_12) +EXCEPTION(0x13,t_trap_13) +EXCEPTION(0x14,t_trap_14) +EXCEPTION(0x15,t_trap_15) +EXCEPTION(0x16,t_trap_16) +EXCEPTION(0x17,t_trap_17) +EXCEPTION(0x18,t_trap_18) +EXCEPTION(0x19,t_trap_19) +EXCEPTION(0x1a,t_trap_1a) +EXCEPTION(0x1b,t_trap_1b) +EXCEPTION(0x1c,t_trap_1c) +EXCEPTION(0x1d,t_trap_1d) +EXCEPTION(0x1e,t_trap_1e) +EXCEPTION(0x1f,t_trap_1f) + +GATE_INITTAB_END + +alltraps: + pusha + pushl %ds + pushl %es + pushl %fs + pushl %gs + + movl %ss,%eax + movl %eax,%ds + movl %eax,%es + movl %esp,%eax + pushl %eax + call trap_dump_panic + diff --git a/l4/pkg/bootstrap/server/src/ARCH-amd64/boot32/boot_kernel.c b/l4/pkg/bootstrap/server/src/ARCH-amd64/boot32/boot_kernel.c new file mode 100644 index 00000000..6af40eac --- /dev/null +++ b/l4/pkg/bootstrap/server/src/ARCH-amd64/boot32/boot_kernel.c @@ -0,0 +1,71 @@ +/* + * (c) 2009 Adam Lackorzynski , + * Alexander Warg , + * Frank Mehnert + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ +#include +#include +#include "boot_cpu.h" +#include "boot_paging.h" +#include "load_elf.h" + +extern unsigned KERNEL_CS_64; +extern char _binary_bootstrap64_bin_start; + +static l4_uint64_t find_upper_mem(l4util_mb_info_t *mbi) +{ + l4_uint64_t max = 0; + l4util_mb_addr_range_t *mmap; + l4util_mb_for_each_mmap_entry(mmap, mbi) + { + if (max < mmap->addr + mmap->size) + max = mmap->addr + mmap->size; + } + return max; +} + +void bootstrap (l4util_mb_info_t *mbi, unsigned int flag, char *rm_pointer); +void +bootstrap (l4util_mb_info_t *mbi, unsigned int flag, char *rm_pointer) +{ + l4_uint32_t vma_start, vma_end; + struct + { + l4_uint32_t start; + l4_uint16_t cs __attribute__((packed)); + } far_ptr; + l4_uint64_t mem_upper; + + // setup stuff for base_paging_init() + base_cpu_setup(); + +#ifdef REALMODE_LOADING + mem_upper = *(unsigned long*)(rm_pointer + 0x1e0); + mem_upper = 1024 * (1024 + mem_upper); +#else + mem_upper = find_upper_mem(mbi); + if (!mem_upper) + mem_upper = 1024 * (1024 + mbi->mem_upper); +#endif + + printf("Highest physical memory address found: %llx\n", mem_upper); + + // now do base_paging_init(): sets up paging with one-to-one mapping + base_paging_init(round_superpage(mem_upper)); + + printf("Loading 64bit part...\n"); + // switch from 32 Bit compatibility mode to 64 Bit mode + far_ptr.cs = KERNEL_CS_64; + far_ptr.start = load_elf(&_binary_bootstrap64_bin_start, + &vma_start, &vma_end); + + asm volatile("ljmp *(%4)" + :: "D"(mbi), "S"(flag), "d"(rm_pointer), + "c"(&ptab64_mem_info), + "r"(&far_ptr), "m"(far_ptr)); +} diff --git a/l4/pkg/bootstrap/server/src/ARCH-amd64/boot32/boot_paging.h b/l4/pkg/bootstrap/server/src/ARCH-amd64/boot32/boot_paging.h new file mode 100644 index 00000000..59320f1f --- /dev/null +++ b/l4/pkg/bootstrap/server/src/ARCH-amd64/boot32/boot_paging.h @@ -0,0 +1,43 @@ +/* + * (c) 2009 Adam Lackorzynski , + * Frank Mehnert , + * Torsten Frenzel + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ +#ifndef BOOT_PAGING_H +#define BOOT_PAGING_H + +#include "types.h" + +enum +{ + PAGE_SIZE = (1 << 12), + PAGE_MASK = (PAGE_SIZE - 1), + SUPERPAGE_SIZE = (1 << 21), + SUPERPAGE_MASK = (SUPERPAGE_SIZE - 1), + PD_SIZE = (1 << 30), + PD_MASK = (PD_SIZE - 1), + PDP_SIZE = (1LL << 39), + PDP_MASK = (PDP_SIZE - 1), +}; + +static inline int +superpage_aligned(l4_uint32_t x) +{ return (x & SUPERPAGE_MASK) == 0; } + +static inline int +pd_aligned(l4_uint32_t x) +{ return (x & PD_MASK) == 0; } + +static inline int +pdp_aligned(l4_uint32_t x) +{ return (x & PDP_MASK) == 0; } + +static inline l4_uint64_t round_superpage(l4_uint64_t x) +{ return (x + SUPERPAGE_MASK) & ~SUPERPAGE_MASK; } + +#endif diff --git a/l4/pkg/bootstrap/server/src/ARCH-amd64/boot32/bootstrap32.ld b/l4/pkg/bootstrap/server/src/ARCH-amd64/boot32/bootstrap32.ld new file mode 100644 index 00000000..18c7ff86 --- /dev/null +++ b/l4/pkg/bootstrap/server/src/ARCH-amd64/boot32/bootstrap32.ld @@ -0,0 +1,26 @@ +ENTRY(_start) +SECTIONS +{ + . = 0x01000000; + _image_start = .; + .text : + { + *(.text .text.*) + *(.rodata .rodata.*) + } =0x9090 + + .data : + { + *(.data .data.*) + *(.bss .bss.*) + *(COMMON) + } + _image_end = .; + + /DISCARD/ : { + *(.interp) + *(.comment) + *(.note) + *(.eh_frame) + } +} diff --git a/l4/pkg/bootstrap/server/src/ARCH-amd64/boot32/load_elf.c b/l4/pkg/bootstrap/server/src/ARCH-amd64/boot32/load_elf.c new file mode 100644 index 00000000..f81fd635 --- /dev/null +++ b/l4/pkg/bootstrap/server/src/ARCH-amd64/boot32/load_elf.c @@ -0,0 +1,72 @@ +/* + * (c) 2009 Alexander Warg , + * Frank Mehnert + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ +#include +#include + +#include "types.h" +#include +#include "load_elf.h" + +extern char _image_start; +extern char _image_end; + +static void check_overlap(unsigned long s, unsigned long e) +{ + if ( (unsigned long)&_image_end >= s + && (unsigned long)&_image_start <= e) + { + printf("Overwrite: ELF-PH: %lx - %lx, bootstrap loader: %lx - %lx\n", + s, e, (unsigned long)&_image_start, (unsigned long)&_image_end); + printf("Change your 'modaddr' setting.\n"); + while (1) + ; + } +} + +l4_uint32_t +load_elf (void *elf, l4_uint32_t *vma_start, l4_uint32_t *vma_end) +{ + char *_elf = (char *) elf; + Elf64_Ehdr *eh = (Elf64_Ehdr *)(_elf); + Elf64_Phdr *ph = (Elf64_Phdr *)(_elf + eh->e_phoff); + l4_uint32_t _vma_start = ~0, _vma_end = 0; + int i; + + for (i = 0; i < eh->e_phnum; i++, ph++) + { + if (ph->p_type != PT_LOAD) + continue; + + if (ph->p_vaddr < _vma_start) + _vma_start = ph->p_vaddr; + + if (ph->p_vaddr + ph->p_memsz > _vma_end) + _vma_end = ph->p_vaddr + ph->p_memsz; + + check_overlap(ph->p_paddr, ph->p_paddr + ph->p_filesz); + + memcpy((void*)((Elf32_Addr)ph->p_paddr), + _elf + ph->p_offset, ph->p_filesz); + + if (ph->p_filesz < ph->p_memsz) + { + check_overlap(ph->p_paddr + ph->p_filesz, ph->p_paddr + ph->p_memsz); + memset((void*)((Elf32_Addr)(ph->p_paddr + ph->p_filesz)), 0, + ph->p_memsz - ph->p_filesz); + } + } + + if (vma_start) + *vma_start = _vma_start; + if (vma_end) + *vma_end = _vma_end; + + return eh->e_entry; +} diff --git a/l4/pkg/bootstrap/server/src/ARCH-amd64/boot32/load_elf.h b/l4/pkg/bootstrap/server/src/ARCH-amd64/boot32/load_elf.h new file mode 100644 index 00000000..0a86c586 --- /dev/null +++ b/l4/pkg/bootstrap/server/src/ARCH-amd64/boot32/load_elf.h @@ -0,0 +1,19 @@ +/* + * (c) 2009 Frank Mehnert , + * Torsten Frenzel + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ +#ifndef LOAD_ELF_H__ +#define LOAD_ELF_H__ 1 + +#include "types.h" + +typedef void (*Startup_func)(void); + +l4_uint32_t load_elf(void *addr, l4_uint32_t *vma_start, l4_uint32_t *vma_end); + +#endif diff --git a/l4/pkg/bootstrap/server/src/ARCH-amd64/boot32/minilibc_support.c b/l4/pkg/bootstrap/server/src/ARCH-amd64/boot32/minilibc_support.c new file mode 100644 index 00000000..88a5d939 --- /dev/null +++ b/l4/pkg/bootstrap/server/src/ARCH-amd64/boot32/minilibc_support.c @@ -0,0 +1,351 @@ +/* + * (c) 2009 Adam Lackorzynski , + * Frank Mehnert + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ +#include +#include +#include + +#include +#include + +//#include "version.h" + +extern int hercules; /* provided by startup.c */ + +static void direct_cons_putchar(unsigned char c, int to_hercules); +static int direct_cons_try_getchar(void); + int have_hercules(void); + void reboot(void); + +int __libc_backend_outs( const char *s, size_t len); +int __getchar(void); + +static int porte9(unsigned char c) +{ + l4util_out8(c, 0xe9); + if (c == 10) + l4util_out8(13, 0xe9); +} + +int +__libc_backend_outs( const char *s, size_t len) +{ + size_t i; + for (i = 0; i < len; i++) + { + direct_cons_putchar(s[i], 0); + if (0) + porte9(s[i]); + } + + return 1; +} + +void __attribute__((noreturn)) +reboot(void) +{ + l4util_out8(0x80, 0x70); + l4util_iodelay(); + l4util_in8(0x71); + l4util_iodelay(); + + while (l4util_in8(0x64) & 0x02) + ; + + l4util_out8(0x8F, 0x70); + l4util_iodelay(); + l4util_out8(0x00, 0x71); + l4util_iodelay(); + + l4util_out8(0xFE, 0x64); + l4util_iodelay(); + + for (;;) + ; +} + +int +__getchar(void) +{ + int c = 0; + do + { + if (c == -1) + c = direct_cons_try_getchar(); + } while (c == -1); + return c; +} + +void +_exit(int fd) +{ + printf("\n\033[1mReturn reboots...\033[m\n"); + __getchar(); + printf("Rebooting.\n"); + reboot(); +} + +static void +direct_cons_putchar(unsigned char c, int to_hercules) +{ + static int ofs = -1; + static int esc; + static int esc_val; + static int attr = 0x07; + unsigned char *vidbase = (unsigned char*)(to_hercules ? 0xb0000 : 0xb8000); + + + if (ofs < 0) + { + /* Called for the first time - initialize. */ + ofs = 80*2*24; + direct_cons_putchar('\n', to_hercules); + } + + switch (esc) + { + case 1: + if (c == '[') + { + esc++; + goto done; + } + esc = 0; + break; + + case 2: + if (c >= '0' && c <= '9') + { + esc_val = 10*esc_val + c - '0'; + goto done; + } + if (c == 'm') + { + attr = esc_val ? 0x0f : 0x07; + goto done; + } + esc = 0; + break; + } + + switch (c) + { + case '\n': + memcpy(vidbase, vidbase+80*2, 80*2*24); + memset(vidbase+80*2*24, 0, 80*2); + /* fall through... */ + case '\r': + ofs = 0; + break; + + case '\t': + ofs = (ofs + 8) & ~7; + break; + + case '\033': + esc = 1; + esc_val = 0; + break; + + default: + /* Wrap if we reach the end of a line. */ + if (ofs >= 80) + direct_cons_putchar('\n', to_hercules); + + /* Stuff the character into the video buffer. */ + { + volatile unsigned char *p = vidbase + 80*2*24 + ofs*2; + p[0] = c; + p[1] = attr; + ofs++; + } + break; + } + +done: + return; +} + +int +have_hercules(void) +{ + unsigned short *p, p_save; + int count = 0; + unsigned long delay; + + /* check for video memory */ + p = (unsigned short*)0xb0000; + p_save = *p; + *p = 0xaa55; if (*p == 0xaa55) count++; + *p = 0x55aa; if (*p == 0x55aa) count++; + *p = p_save; + if (count != 2) + return 0; + + /* check for I/O ports (HW cursor) */ + l4util_out8(0x0f, 0x3b4); + l4util_iodelay(); + l4util_out8(0x66, 0x3b5); + for (delay=0; delay<0x100000UL; delay++) + asm volatile ("nop" : :); + if (l4util_in8(0x3b5) != 0x66) + return 0; + + l4util_iodelay(); + l4util_out8(0x0f, 0x3b4); + l4util_iodelay(); + l4util_out8(0x99, 0x3b5); + + for (delay=0; delay<0x10000; delay++) + l4util_iodelay(); + if (l4util_in8(0x3b5) != 0x99) + return 0; + + /* reset position */ + l4util_out8(0xf, 0x3b4); + l4util_iodelay(); + l4util_out8(0x0, 0x3b5); + l4util_iodelay(); + return 1; +} + +#define SHIFT -1 + +static const char keymap[128][2] = { + {0}, /* 0 */ + {27, 27}, /* 1 - ESC */ + {'1', '!'}, /* 2 */ + {'2', '@'}, + {'3', '#'}, + {'4', '$'}, + {'5', '%'}, + {'6', '^'}, + {'7', '&'}, + {'8', '*'}, + {'9', '('}, + {'0', ')'}, + {'-', '_'}, + {'=', '+'}, + {8, 8}, /* 14 - Backspace */ + {'\t','\t'}, /* 15 */ + {'q', 'Q'}, + {'w', 'W'}, + {'e', 'E'}, + {'r', 'R'}, + {'t', 'T'}, + {'y', 'Y'}, + {'u', 'U'}, + {'i', 'I'}, + {'o', 'O'}, + {'p', 'P'}, + {'[', '{'}, +// {']','}'}, /* 27 */ + {'+', '*'}, /* 27 */ + {'\r','\r'}, /* 28 - Enter */ + {0, 0}, /* 29 - Ctrl */ + {'a', 'A'}, /* 30 */ + {'s', 'S'}, + {'d', 'D'}, + {'f', 'F'}, + {'g', 'G'}, + {'h', 'H'}, + {'j', 'J'}, + {'k', 'K'}, + {'l', 'L'}, + {';', ':'}, + {'\'','"'}, /* 40 */ + {'`', '~'}, /* 41 */ + {SHIFT, SHIFT}, /* 42 - Left Shift */ + {'\\', '|'}, /* 43 */ + {'z', 'Z'}, /* 44 */ + {'x', 'X'}, + {'c', 'C'}, + {'v', 'V'}, + {'b', 'B'}, + {'n', 'N'}, + {'m', 'M'}, + {',', '<'}, + {'.', '>'}, + // {'/','?'}, /* 53 */ + {'-', '_'}, /* 53 */ + {SHIFT, SHIFT}, /* 54 - Right Shift */ + {0, 0}, /* 55 - Print Screen */ + {0, 0}, /* 56 - Alt */ + {' ', ' '}, /* 57 - Space bar */ + {0, 0}, /* 58 - Caps Lock */ + {0, 0}, /* 59 - F1 */ + {0, 0}, /* 60 - F2 */ + {0, 0}, /* 61 - F3 */ + {0, 0}, /* 62 - F4 */ + {0, 0}, /* 63 - F5 */ + {0, 0}, /* 64 - F6 */ + {0, 0}, /* 65 - F7 */ + {0, 0}, /* 66 - F8 */ + {0, 0}, /* 67 - F9 */ + {0, 0}, /* 68 - F10 */ + {0, 0}, /* 69 - Num Lock */ + {0, 0}, /* 70 - Scroll Lock */ + {'7', '7'}, /* 71 - Numeric keypad 7 */ + {'8', '8'}, /* 72 - Numeric keypad 8 */ + {'9', '9'}, /* 73 - Numeric keypad 9 */ + {'-', '-'}, /* 74 - Numeric keypad '-' */ + {'4', '4'}, /* 75 - Numeric keypad 4 */ + {'5', '5'}, /* 76 - Numeric keypad 5 */ + {'6', '6'}, /* 77 - Numeric keypad 6 */ + {'+', '+'}, /* 78 - Numeric keypad '+' */ + {'1', '1'}, /* 79 - Numeric keypad 1 */ + {'2', '2'}, /* 80 - Numeric keypad 2 */ + {'3', '3'}, /* 81 - Numeric keypad 3 */ + {'0', '0'}, /* 82 - Numeric keypad 0 */ + {'.', '.'}, /* 83 - Numeric keypad '.' */ +}; + +int +direct_cons_try_getchar(void) +{ + static unsigned shift_state; + unsigned status, scan_code, ch; + +retry: + __asm__ __volatile__ ("rep; nop"); + + /* Wait until a scan code is ready and read it. */ + status = l4util_in8(0x64); + if ((status & 0x01) == 0) + { + return -1; + } + scan_code = l4util_in8(0x60); + + /* Drop mouse events */ + if ((status & 0x20) != 0) + { + return -1; + } + + /* Handle key releases - only release of SHIFT is important. */ + if (scan_code & 0x80) + { + scan_code &= 0x7f; + if (keymap[scan_code][0] == SHIFT) + shift_state = 0; + goto retry; + } + + /* Translate the character through the keymap. */ + ch = keymap[scan_code][shift_state]; + if (ch == (unsigned)SHIFT) + { + shift_state = 1; + goto retry; + } else if (ch == 0) + goto retry; + + return ch; +} diff --git a/l4/pkg/bootstrap/server/src/ARCH-amd64/crt0.S b/l4/pkg/bootstrap/server/src/ARCH-amd64/crt0.S new file mode 100644 index 00000000..1bd89f93 --- /dev/null +++ b/l4/pkg/bootstrap/server/src/ARCH-amd64/crt0.S @@ -0,0 +1,53 @@ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Frank Mehnert , + * Torsten Frenzel + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ +#include + + .section .init + + .globl _start +_start: +#if defined(REALMODE_LOADING) && !defined(IMAGE_MODE) + cld + cli + mov $(3 * 8), %eax + mov %eax, %ds + mov %eax, %es + mov %eax, %fs + mov %eax, %gs + + lss _stack_seg, %esp +#else + lea _stack,%esp +#endif + + push $_exit + jmp __main + + + /* MultiBoot header - see multiboot.h. */ + .p2align(2) + +_mb_header: + .long 0x1BADB002 /* magic */ + .long 0 /* flags: AOUT_KLUDGE */ + .long 0 - 0x1BADB002 + +#if defined(REALMODE_LOADING) && !defined(IMAGE_MODE) +_stack_seg: + .long _stack + .word (3 * 8) +#endif + + .bss + + .globl _stack + .space 8192 +_stack: diff --git a/l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/Makefile b/l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/Makefile new file mode 100644 index 00000000..4fdee883 --- /dev/null +++ b/l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/Makefile @@ -0,0 +1,17 @@ +PKGDIR ?= ../../../.. +L4DIR ?= $(PKGDIR)/../.. + +TARGET = libc32.a + +SYSTEMS = amd64 + + +SRC_C = __assert_fail.c __lltostr.c __ltostr.c __v_printf.c \ + isspace.c memcpy.c memmove.c memset.c printf.c puts.c \ + strtol.c strtoul.c vprintf.c + +include $(L4DIR)/mk/lib.mk + +CFLAGS := $(filter-out $(CCXX_FLAGS) $(CARCHFLAGS), $(CFLAGS)) +CPPFLAGS := -nostdinc -I$(SRC_DIR)/include -m32 +OPTS := -Os diff --git a/l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/__assert_fail.c b/l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/__assert_fail.c new file mode 100644 index 00000000..36c6b67a --- /dev/null +++ b/l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/__assert_fail.c @@ -0,0 +1,17 @@ +#include "assert.h" +#include "stdio.h" +#include "stdlib.h" + +extern void _exit(int rc); + +void +__assert_fail (const char *__assertion, const char *__file, + unsigned int __line) +{ + printf("ASSERTION_FAILED (%s)\n" + " in file %s:%d\n", __assertion, __file, __line); + _exit (EXIT_FAILURE); +} + +extern __typeof(__assert_fail) __assert + __attribute__((weak, alias("__assert_fail"))); diff --git a/l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/__lltostr.c b/l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/__lltostr.c new file mode 100644 index 00000000..813a408b --- /dev/null +++ b/l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/__lltostr.c @@ -0,0 +1,36 @@ +#include +//#include + +int __lltostr(char *s, int size, unsigned long long i, int base, char UpCase); + +int __lltostr(char *s, int size, unsigned long long i, int base, char UpCase) +{ + char *tmp; + unsigned int j=0; + //_moddiv_t r; + + s[--size]=0; + + tmp=s+size; + + if ((base==0)||(base>36)) base=10; + + j=0; + if (!i) + { + *(--tmp)='0'; + j=1; + } + + while((tmp>s)&&(i)) + { + tmp--; + // r = moddiv(i,base); + if ((*tmp=i%base+'0')>'9') *tmp+=(UpCase?'A':'a')-'9'-1; + i=i/base; + j++; + } + memmove(s,tmp,j+1); + + return j; +} diff --git a/l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/__ltostr.c b/l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/__ltostr.c new file mode 100644 index 00000000..b13b0e3d --- /dev/null +++ b/l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/__ltostr.c @@ -0,0 +1,35 @@ +#include +#include +//#include + +int __ltostr(char *s, unsigned int size, unsigned long i, unsigned int base, int UpCase) +{ + char *tmp; + unsigned int j=0; + //_moddiv_t r; + + s[--size]=0; + + tmp=s+size; + + if ((base==0)||(base>36)) base=10; + + j=0; + if (!i) + { + *(--tmp)='0'; + j=1; + } + + while((tmp>s)&&(i)) + { + tmp--; + //r = moddiv(i,base); + if ((*tmp=i%base+'0')>'9') *tmp+=(UpCase?'A':'a')-'9'-1; + i=i/base; + j++; + } + memmove(s,tmp,j+1); + + return j; +} diff --git a/l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/__v_printf.c b/l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/__v_printf.c new file mode 100644 index 00000000..eed60b19 --- /dev/null +++ b/l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/__v_printf.c @@ -0,0 +1,232 @@ +#include +#include +#include +#include + +#include "vprintf_backend.h" + +static inline unsigned int skip_to(const char *format) { + int unsigned nr; + for (nr=0; format[nr] && (format[nr]!='%'); ++nr); + return nr; +} + +#define A_WRITE(fn,buf,sz) ((fn)->put((buf),(sz),(fn)->data)) + +static char* pad_line[16]= { " ", "0000000000000000", }; +static inline int write_pad(struct output_op* fn, int len, int padwith) { + int nr=0; + for (;len>15;len-=16,nr+=16) { + A_WRITE(fn,pad_line[(padwith=='0')?1:0],16); + } + if (len>0) { + A_WRITE(fn,pad_line[(padwith=='0')?1:0],(unsigned int)len); nr+=len; + } + return nr; +} + +int __v_printf(struct output_op* fn, const char *format, va_list arg_ptr) +{ + int len=0; + + while (*format) { + unsigned int sz = skip_to(format); + if (sz) { + A_WRITE(fn,format,sz); len+=sz; + format+=sz; + } + if (*format=='%') { + char buf[128]; + + char ch, padwith=' '; + char *s; + + char flag_in_sign=0; + char flag_upcase=0; + char flag_hash=0; + char flag_left=0; + char flag_space=0; + char flag_sign=0; + char flag_dot=0; + signed char flag_long=0; + + unsigned int base; + unsigned int width=0, preci=0; + + long int number=0; + long long llnumber=0; + + ++format; +inn_printf: + switch(ch=*format++) { + case 0: + return -1; + break; + + /* FLAGS */ + case '#': + flag_hash=1; + goto inn_printf; + + case 'h': + --flag_long; + goto inn_printf; + case 'l': + ++flag_long; + goto inn_printf; + + case '0': + padwith='0'; + goto inn_printf; + + case '-': + flag_left=1; + goto inn_printf; + + case ' ': + flag_space=1; + goto inn_printf; + + case '+': + flag_sign=1; + goto inn_printf; + + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if(flag_dot) return -1; + width=strtoul(format-1,&s,10); + format=s; + goto inn_printf; + + case '*': + width=va_arg(arg_ptr,int); + goto inn_printf; + + case '.': + flag_dot=1; + if (*format=='*') { + preci=va_arg(arg_ptr,int); + ++format; + } else { + long int tmp=strtol(format,&s,10); + preci=tmp<0?0:tmp; + format=s; + } + goto inn_printf; + + /* print a char or % */ + case 'c': + ch=(char)va_arg(arg_ptr,int); + case '%': + A_WRITE(fn,&ch,1); ++len; + break; + + /* print a string */ + case 's': + s=va_arg(arg_ptr,char *); + if (!s) s="(null)"; + sz = strlen(s); + if (flag_dot && sz>preci) sz=preci; + +print_out: + if (width && (!flag_left)) { + len+=write_pad(fn,(signed int)width-(signed int)sz,padwith); + } + A_WRITE(fn,s,sz); len+=sz; + if (width && (flag_left)) { + len+=write_pad(fn,(signed int)width-(signed int)sz,' '); + } + break; + + /* print an integer value */ + case 'b': + base=2; + sz=0; + goto num_printf; + case 'p': + flag_hash=1; + if(sizeof(void*)>sizeof(unsigned)) + ++flag_long; + if(sizeof(void*)>sizeof(long)) + ++flag_long; + ch='x'; + case 'X': + flag_upcase=(ch=='X'); + case 'x': + base=16; + sz=0; + if (flag_hash) { + buf[1]='0'; + buf[2]=ch; + sz=2; + } + goto num_printf; + case 'd': + case 'i': + flag_in_sign=1; + case 'u': + base=10; + sz=0; + goto num_printf; + case 'o': + base=8; + sz=0; + if (flag_hash) { + buf[1]='0'; + ++sz; + } + +num_printf: + if (flag_long>0) { + if (flag_long>1) + llnumber=va_arg(arg_ptr,long long); + else + number=va_arg(arg_ptr,long); + } + else + number=va_arg(arg_ptr,int); + + if (flag_in_sign) { + if ((flag_long>1)&&(llnumber<0)) { + llnumber=-llnumber; + flag_in_sign=2; + } else + if (number<0) { + number=-number; + flag_in_sign=2; + } + } + if (flag_long<0) number&=0xffff; + if (flag_long<-1) number&=0xff; + if (flag_long>1) + sz += __lltostr(buf+1+sz,sizeof(buf)-5,(unsigned long long) llnumber,base,flag_upcase); + else + sz += __ltostr(buf+1+sz,sizeof(buf)-5,(unsigned long) number,base,flag_upcase); + + s=buf+1; + + if (flag_in_sign==2) { + *(--s)='-'; + ++sz; + } else if ((flag_in_sign)&&(flag_sign || flag_space)) { + *(--s)=(flag_sign)?'+':' '; + ++sz; + } + + goto print_out; + + default: + break; + } + } + } + return len; +} + diff --git a/l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/include/assert.h b/l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/include/assert.h new file mode 100644 index 00000000..68f75f5e --- /dev/null +++ b/l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/include/assert.h @@ -0,0 +1,35 @@ +#ifndef _ASSERT_H +#define _ASSERT_H + +#include + +__BEGIN_DECLS +/* This prints an "Assertion failed" message and aborts. */ +void __assert_fail (const char *__assertion, const char *__file, + unsigned int __line) + __attribute__ ((__noreturn__)); + +__END_DECLS + +#if (__GNUC__>=3) +# define ASSERT_EXPECT_FALSE(exp) __builtin_expect((exp), 0) +#else +# define ASSERT_EXPECT_FALSE(exp) (exp) +#endif + +/* We don't show information about the current function since needs + * additional space -- especially with gcc-2.95. The function name + * can be found by searching the EIP in the kernel image. */ +#undef assert +#ifdef NDEBUG +#define assert(expr) +#define check(expr) (void)(expr) +#else +# define assert(expr) \ + ((void) ((ASSERT_EXPECT_FALSE(!(expr))) \ + ? (__assert_fail (#expr, __FILE__, __LINE__), 0) \ + : 0)) +# define check(expr) assert(expr) +#endif + +#endif diff --git a/l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/include/cdefs.h b/l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/include/cdefs.h new file mode 100644 index 00000000..b9fc187f --- /dev/null +++ b/l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/include/cdefs.h @@ -0,0 +1,13 @@ +#ifndef __CDEFS_H__ +#define __CDEFS_H__ + +#ifndef __cplusplus +#define __BEGIN_DECLS +#define __END_DECLS +#else +#define __BEGIN_DECLS extern "C" { +#define __END_DECLS } +#endif + + +#endif // __CDEFS_H__ diff --git a/l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/include/ctype.h b/l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/include/ctype.h new file mode 100644 index 00000000..5ec2ba8f --- /dev/null +++ b/l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/include/ctype.h @@ -0,0 +1,32 @@ +#ifndef _CTYPE_H +#define _CTYPE_H + +#include + +__BEGIN_DECLS + +int isascii (int c) __attribute__ ((__const__)); +int isblank (int c) __attribute__ ((__const__)); +int isalnum (int c) __attribute__ ((__const__)); +int isalpha (int c) __attribute__ ((__const__)); +int isdigit (int c) __attribute__ ((__const__)); +int isspace (int c) __attribute__ ((__const__)); + +int isupper (int c) __attribute__ ((__const__)); +int islower (int c) __attribute__ ((__const__)); + +int tolower(int c) __attribute__ ((__const__)); +int toupper(int c) __attribute__ ((__const__)); + +int isprint(int c) __attribute__ ((__const__)); +int ispunct(int c) __attribute__ ((__const__)); +int iscntrl(int c) __attribute__ ((__const__)); + +/* fscking GNU extensions! */ +int isxdigit(int c) __attribute__ ((__const__)); + +int isgraph(int c) __attribute__ ((__const__)); + +__END_DECLS + +#endif diff --git a/l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/include/libc_backend.h b/l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/include/libc_backend.h new file mode 100644 index 00000000..fbfb534a --- /dev/null +++ b/l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/include/libc_backend.h @@ -0,0 +1,47 @@ +/* */ + + + +/* This file defines the backend interface */ +/* of the kernel c-library. */ + +#ifndef __LIBC_BACKEND_H__ +#define __LIBC_BACKEND_H__ + +#include +#include + +__BEGIN_DECLS + +/** + * The text output backend. + * + * This function must be provided to the c-library for + * text output. It must simply send len characters of s + * to an output device. + * + * @param s the string to send (not zero terminated). + * @param len the number of characters. + * @return 1 on success, 0 else. + */ +int __libc_backend_outs( const char *s, size_t len ); + + +/** + * The text input backend. + * + * This function must be provided to the c-library for + * text input. It has to block til len characters are + * read or a newline is reached. The retrurn value gives + * the number of characters virtually read. + * + * @param s a poiznter to the buffer for the read text. + * @param len the size of the buffer. + * @return the number of characters virtually read. + */ +int __libc_backend_ins( char *s, size_t len ); + +__END_DECLS + + +#endif //__LIBC_BACKEND_H__ diff --git a/l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/include/memcpy.h b/l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/include/memcpy.h new file mode 100644 index 00000000..18484d0f --- /dev/null +++ b/l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/include/memcpy.h @@ -0,0 +1,14 @@ +#ifndef MLC_MEMCPY_H__ +#define MLC_MEMCPY_H__ + +#include +#include + +__BEGIN_DECLS + +void *memcpy(void *dest, const void *src, size_t n); + +__END_DECLS + +#endif // MLC_MEMCPY_H__ + diff --git a/l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/include/panic.h b/l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/include/panic.h new file mode 100644 index 00000000..19102251 --- /dev/null +++ b/l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/include/panic.h @@ -0,0 +1,12 @@ +#ifndef PANIC_H +#define PANIC_H + +#include + +__BEGIN_DECLS + +void panic (const char *format, ...) __attribute__ ((__noreturn__)); + +__END_DECLS + +#endif diff --git a/l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/include/stdarg-cruft.h b/l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/include/stdarg-cruft.h new file mode 100644 index 00000000..20c94453 --- /dev/null +++ b/l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/include/stdarg-cruft.h @@ -0,0 +1,299 @@ +#if defined(__sparc__) || defined(__alpha__) +enum { + __no_type_class = -1, + __void_type_class, + __integer_type_class, + __char_type_class, + __enumeral_type_class, + __boolean_type_class, + __pointer_type_class, + __reference_type_class, + __offset_type_class, + __real_type_class, + __complex_type_class, + __function_type_class, + __method_type_class, + __record_type_class, + __union_type_class, + __array_type_class, + __string_type_class, + __set_type_class, + __file_type_class, + __lang_type_class +}; +#endif + +#if defined(__sparc__) + +typedef char* va_list; +#define va_end(ap) ap=0 + +#define va_start(AP, LASTARG) \ + (__builtin_next_arg (LASTARG), AP = (char *) __builtin_saveregs ()) + +#define __va_rounded_size(TYPE) \ + (((sizeof (TYPE) + sizeof (int) - 1) / sizeof (int)) * sizeof (int)) + +/* We don't declare the union member `d' to have type TYPE + because that would lose in C++ if TYPE has a constructor. */ +/* We cast to void * and then to TYPE * because this avoids + a warning about increasing the alignment requirement. + The casts to char * avoid warnings about invalid pointer arithmetic. */ +#define va_arg(pvar,TYPE) \ +__extension__ \ +(*({((__builtin_classify_type (*(TYPE*) 0) >= __record_type_class \ + || (__builtin_classify_type (*(TYPE*) 0) == __real_type_class \ + && sizeof (TYPE) == 16)) \ + ? ((pvar) = (char *)(pvar) + __va_rounded_size (TYPE *), \ + *(TYPE **) (void *) ((char *)(pvar) - __va_rounded_size (TYPE *))) \ + : __va_rounded_size (TYPE) == 8 \ + ? ({ union {char __d[sizeof (TYPE)]; int __i[2];} __u; \ + __u.__i[0] = ((int *) (void *) (pvar))[0]; \ + __u.__i[1] = ((int *) (void *) (pvar))[1]; \ + (pvar) = (char *)(pvar) + 8; \ + (TYPE *) (void *) __u.__d; }) \ + : ((pvar) = (char *)(pvar) + __va_rounded_size (TYPE), \ + ((TYPE *) (void *) ((char *)(pvar) - __va_rounded_size (TYPE)))));})) + + +#elif defined(__mips__) + +typedef char * va_list; + +#ifdef __mips64 +#define __va_rounded_size(__TYPE) \ + (((sizeof (__TYPE) + 8 - 1) / 8) * 8) +#else +#define __va_rounded_size(__TYPE) \ + (((sizeof (__TYPE) + sizeof (int) - 1) / sizeof (int)) * sizeof (int)) +#endif +#ifdef __mips64 +#define __va_reg_size 8 +#else +#define __va_reg_size 4 +#endif + +#define va_start(__AP, __LASTARG) \ + (__AP = (va_list) __builtin_next_arg (__LASTARG)) + +#ifdef __mips64 +#ifdef __MIPSEB__ +#define va_arg(__AP, __type) \ + ((__type *) (void *) (__AP = (char *) \ + ((((__PTRDIFF_TYPE__)__AP + 8 - 1) & -8) \ + + __va_rounded_size (__type))))[-1] +#else +#define va_arg(__AP, __type) \ + ((__AP = (char *) ((((__PTRDIFF_TYPE__)__AP + 8 - 1) & -8) \ + + __va_rounded_size (__type))), \ + *(__type *) (void *) (__AP - __va_rounded_size (__type))) +#endif + +#else /* not __mips64 */ + +#ifdef __MIPSEB__ +/* For big-endian machines. */ +#define va_arg(__AP, __type) \ + ((__AP = (char *) ((__alignof__ (__type) > 4 \ + ? ((__PTRDIFF_TYPE__)__AP + 8 - 1) & -8 \ + : ((__PTRDIFF_TYPE__)__AP + 4 - 1) & -4) \ + + __va_rounded_size (__type))), \ + *(__type *) (void *) (__AP - __va_rounded_size (__type))) +#else +/* For little-endian machines. */ +#define va_arg(__AP, __type) \ + ((__type *) (void *) (__AP = (char *) ((__alignof__(__type) > 4 \ + ? ((__PTRDIFF_TYPE__)__AP + 8 - 1) & -8 \ + : ((__PTRDIFF_TYPE__)__AP + 4 - 1) & -4) \ + + __va_rounded_size(__type))))[-1] +#endif +#endif + +#elif defined(__powerpc__) + +typedef struct __va_list_tag { + unsigned char gpr; /* index into the array of 8 GPRs stored in the + register save area gpr=0 corresponds to r3, + gpr=1 to r4, etc. */ + unsigned char fpr; /* index into the array of 8 FPRs stored in the + register save area fpr=0 corresponds to f1, + fpr=1 to f2, etc. */ + char *overflow_arg_area; /* location on stack that holds the next + overflow argument */ + char *reg_save_area; /* where r3:r10 and f1:f8, if saved are stored */ +} va_list[1]; + +#define __va_overflow(AP) (AP)->overflow_arg_area +#ifdef __OPTIMIZE__ +extern void __va_arg_type_violation(void) __attribute__((__noreturn__)); +#else +#define __va_arg_type_violation() +#endif + +typedef struct { + long __gp_save[8]; /* save area for GP registers */ + double __fp_save[8]; /* save area for FP registers */ +} __va_regsave_t; + +/* Macros to access the register save area */ +/* We cast to void * and then to TYPE * because this avoids + a warning about increasing the alignment requirement. */ +#define __VA_FP_REGSAVE(AP,OFS,TYPE) \ + ((TYPE *) (void *) (&(((__va_regsave_t *) \ + (AP)->reg_save_area)->__fp_save[OFS]))) + +#define __VA_GP_REGSAVE(AP,OFS,TYPE) \ + ((TYPE *) (void *) (&(((__va_regsave_t *) \ + (AP)->reg_save_area)->__gp_save[OFS]))) + +#define __va_start_common(AP, FAKE) \ + __builtin_memcpy ((AP), __builtin_saveregs (), sizeof(va_list)) + +#define va_start(AP,LASTARG) \ + (__builtin_next_arg (LASTARG), __va_start_common (AP, 0)) + +#ifdef _SOFT_FLOAT +#define __va_float_p(TYPE) 0 +#else +#define __va_float_p(TYPE) (__builtin_classify_type(*(TYPE *)0) == 8) +#endif + +#define __va_aggregate_p(TYPE) (__builtin_classify_type(*(TYPE *)0) >= 12) +#define __va_size(TYPE) ((sizeof(TYPE) + sizeof (long) - 1) / sizeof (long)) + +#define va_arg(AP,TYPE) \ +__extension__ (*({ \ + register TYPE *__ptr; \ + \ + if (__va_float_p (TYPE) && sizeof (TYPE) < 16) \ + { \ + unsigned char __fpr = (AP)->fpr; \ + if (__fpr < 8) \ + { \ + __ptr = __VA_FP_REGSAVE (AP, __fpr, TYPE); \ + (AP)->fpr = __fpr + 1; \ + } \ + else if (sizeof (TYPE) == 8) \ + { \ + unsigned long __addr = (unsigned long) (__va_overflow (AP)); \ + __ptr = (TYPE *)((__addr + 7) & -8); \ + __va_overflow (AP) = (char *)(__ptr + 1); \ + } \ + else \ + { \ + /* float is promoted to double. */ \ + __va_arg_type_violation (); \ + } \ + } \ + \ + /* Aggregates and long doubles are passed by reference. */ \ + else if (__va_aggregate_p (TYPE) || __va_float_p (TYPE)) \ + { \ + unsigned char __gpr = (AP)->gpr; \ + if (__gpr < 8) \ + { \ + __ptr = * __VA_GP_REGSAVE (AP, __gpr, TYPE *); \ + (AP)->gpr = __gpr + 1; \ + } \ + else \ + { \ + TYPE **__pptr = (TYPE **) (__va_overflow (AP)); \ + __ptr = * __pptr; \ + __va_overflow (AP) = (char *) (__pptr + 1); \ + } \ + } \ + \ + /* Only integrals remaining. */ \ + else \ + { \ + /* longlong is aligned. */ \ + if (sizeof (TYPE) == 8) \ + { \ + unsigned char __gpr = (AP)->gpr; \ + if (__gpr < 7) \ + { \ + __gpr += __gpr & 1; \ + __ptr = __VA_GP_REGSAVE (AP, __gpr, TYPE); \ + (AP)->gpr = __gpr + 2; \ + } \ + else \ + { \ + unsigned long __addr = (unsigned long) (__va_overflow (AP)); \ + __ptr = (TYPE *)((__addr + 7) & -8); \ + (AP)->gpr = 8; \ + __va_overflow (AP) = (char *)(__ptr + 1); \ + } \ + } \ + else if (sizeof (TYPE) == 4) \ + { \ + unsigned char __gpr = (AP)->gpr; \ + if (__gpr < 8) \ + { \ + __ptr = __VA_GP_REGSAVE (AP, __gpr, TYPE); \ + (AP)->gpr = __gpr + 1; \ + } \ + else \ + { \ + __ptr = (TYPE *) __va_overflow (AP); \ + __va_overflow (AP) = (char *)(__ptr + 1); \ + } \ + } \ + else \ + { \ + /* Everything else was promoted to int. */ \ + __va_arg_type_violation (); \ + } \ + } \ + __ptr; \ +})) + +#define va_end(AP) ((void)0) + +/* Copy va_list into another variable of this type. */ +#define __va_copy(dest, src) *(dest) = *(src) + +#elif defined(__alpha__) + +typedef struct { + char *__base; /* Pointer to first integer register. */ + int __offset; /* Byte offset of args so far. */ +} va_list; + +#define va_start(pvar, firstarg) \ + (__builtin_next_arg (firstarg), \ + (pvar) = *(va_list *) __builtin_saveregs ()) +#define va_end(__va) ((void) 0) + +#define __va_tsize(__type) \ + (((sizeof (__type) + __extension__ sizeof (long long) - 1) \ + / __extension__ sizeof (long long)) * __extension__ sizeof (long long)) + +#define va_arg(__va, __type) \ +(*(((__va).__offset += __va_tsize (__type)), \ + (__type *)(void *)((__va).__base + (__va).__offset \ + - (((__builtin_classify_type (* (__type *) 0) \ + == __real_type_class) && (__va).__offset <= (6 * 8)) \ + ? (6 * 8) + 8 : __va_tsize (__type))))) + +#else /* !__sparc__ && !__powerpc__ && !__mips__ && !__alpha__*/ + +typedef char* va_list; + +/* this only works when everything is passed on the stack (i.e. x86) */ +#if __WORDSIZE == 64 +#define va_start(ap,argn) ap=((char*)&argn)+8 +#else +#define va_start(ap,argn) ap=((char*)&argn)+4 +#endif +#define va_arg(ap,type) (ap+=sizeof(type), *(type*)((char*)((void*)ap)-sizeof(type))) + +#endif + +#ifndef __va_copy +#define __va_copy(x,y) x=y +#endif + +#ifndef va_end +#define va_end(ap) ((void)0) +#endif + diff --git a/l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/include/stdarg.h b/l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/include/stdarg.h new file mode 100644 index 00000000..307f51d2 --- /dev/null +++ b/l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/include/stdarg.h @@ -0,0 +1,26 @@ +#ifndef _STDARG_H +#define _STDARG_H + + + +#ifdef __GNUC__ +#if (__GNUC__ > 2) || (__GNUC__ == 2) && (__GNUC_MINOR__ > 96) + +typedef __builtin_va_list va_list; +#define va_start(v,l) __builtin_va_start((v),(l)) +#define va_end __builtin_va_end +#define va_arg __builtin_va_arg +#define __va_copy(d,s) __builtin_va_copy((d),(s)) + +#endif +#endif + +#ifndef va_end +#include +#endif + +#if !defined(__STRICT_ANSI__) || __STDC_VERSION__ + 0 >= 199900L +#define va_copy(d,s) __va_copy(d,s) +#endif + +#endif diff --git a/l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/include/stddef.h b/l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/include/stddef.h new file mode 100644 index 00000000..4136767c --- /dev/null +++ b/l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/include/stddef.h @@ -0,0 +1,7 @@ + +#ifndef _STDDEF_H +#define _STDDEF_H + +typedef unsigned size_t; + +#endif diff --git a/l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/include/stdio.h b/l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/include/stdio.h new file mode 100644 index 00000000..1a6fea52 --- /dev/null +++ b/l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/include/stdio.h @@ -0,0 +1,37 @@ +#ifndef _STDIO_H +#define _STDIO_H + +#include +#include + +__BEGIN_DECLS + +int putchar(int c); +int puts(const char *s); +int printf(const char *format, ...) __attribute__((format(printf,1,2))); +int sprintf(char *str, const char *format, ...) __attribute__((format(printf,2,3))); +int snprintf(char *str, size_t size, const char *format, ...) __attribute__((format(printf,3,4))); +int asprintf(char **ptr, const char* format, ...) __attribute__((format(printf,2,3))); + +#if 0 +int scanf(const char *format, ...) __attribute__((format(scanf,1,2))); +int sscanf(const char *str, const char *format, ...) __attribute__((format(scanf,2,3))); +#endif + +#include + +int vprintf(const char *format, va_list ap) __attribute__((format(printf,1,0))); +int vsprintf(char *str, const char *format, va_list ap) __attribute__((format(printf,2,0))); +int vsnprintf(char *str, size_t size, const char *format, va_list ap) __attribute__((format(printf,3,0))); + + +typedef int FILE; + +int vscanf(const char *format, va_list ap) __attribute__((format(scanf,1,0))); +int vsscanf(const char *str, const char *format, va_list ap) __attribute__((format(scanf,2,0))); + +int sscanf(const char *str, const char *format, ...); + +__END_DECLS + +#endif diff --git a/l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/include/stdlib.h b/l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/include/stdlib.h new file mode 100644 index 00000000..c03396e6 --- /dev/null +++ b/l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/include/stdlib.h @@ -0,0 +1,52 @@ +#ifndef _STDLIB_H +#define _STDLIB_H + +#include +#include + +__BEGIN_DECLS + +int atexit(void (*function)(void)); + +double strtod(const char *nptr, char **endptr); +long int strtol(const char *nptr, char **endptr, int base); +unsigned long int strtoul(const char *nptr, char **endptr, int base); + +extern int __ltostr(char *s, unsigned int size, unsigned long i, unsigned int base, int UpCase); +extern int __dtostr(double d,char *buf,unsigned int maxlen,unsigned int prec); + +#ifndef __STRICT_ANSI__ +__extension__ long long int strtoll(const char *nptr, char **endptr, int base); +__extension__ unsigned long long int strtoull(const char *nptr, char **endptr, int base); +__extension__ int __lltostr(char *s, unsigned int size, unsigned long long i, unsigned int base, int UpCase); +#endif + +int atoi(const char *nptr); +long int atol(const char *nptr); +double atof(const char *nptr); + +#define EXIT_FAILURE 1 +#define EXIT_SUCCESS 0 + +void exit(int status) __attribute__((noreturn)); +void abort(void); + +/* warning: the rand() implementation of the diet libc really sucks. */ +#define RAND_MAX 32767 + +typedef struct { int quot,rem; } div_t; +div_t div(int numer, int denom) __attribute__((const)); + +typedef struct { long int quot,rem; } ldiv_t; +ldiv_t ldiv(long int numer, long int denom) __attribute__((const)); + +typedef struct { long long int quot,rem; } lldiv_t; +lldiv_t lldiv(long long int numer, long long int denom) __attribute__((const)); + +int abs(int i) __attribute__((const)); +long int labs(long int i) __attribute__((const)); +__extension__ long long int llabs(long long int i) __attribute__((const)); + +__END_DECLS + +#endif diff --git a/l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/include/string.h b/l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/include/string.h new file mode 100644 index 00000000..61c9ce2f --- /dev/null +++ b/l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/include/string.h @@ -0,0 +1,56 @@ +#ifndef _STRING_H +#define _STRING_H + +#include +#include + +#include + +__BEGIN_DECLS + +char *strcpy(char *dest, const char *src); +char *strncpy(char *dest, const char *src, size_t n); + +void *memccpy(void *dest, const void *src, int c, size_t n); +void *memmove(void *dest, const void *src, size_t n); + +int memccmp(const void *s1, const void *s2, int c, size_t n); +int memcmp(const void *s1, const void *s2, size_t n); +int strcmp(const char *s1, const char *s2); +int strncmp(const char *s1, const char *s2, size_t n); + +int strcasecmp(const char *s1, const char *s2); +int strncasecmp(const char *s1, const char *s2, size_t n); + +#if (__GNUC__>=3) +size_t strlen(const char *s) __attribute__((pure)); +#else +size_t strlen(const char *s); +#endif + +char *strstr(const char *haystack, const char *needle); + +char *strdup(const char *s); + +char *strchr(const char *s, int c); +char *strrchr(const char *s, int c); + +char *strcat(char *dest, const char *src); +char *strncat(char *dest, const char *src, size_t n); + +size_t strspn(const char *s, const char *_accept); +size_t strcspn(const char *s, const char *reject); + +char *strpbrk(const char *s, const char *_accept); +char *strsep(char **stringp, const char *delim); + +void* memset(void *s, int c, size_t n); +void* memchr(const void *s, int c, size_t n); + +int strcoll(const char *s1, const char *s2); + + +__END_DECLS + + +#endif diff --git a/l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/include/strings.h b/l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/include/strings.h new file mode 100644 index 00000000..ec947a9b --- /dev/null +++ b/l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/include/strings.h @@ -0,0 +1,2 @@ +#warning "your code included obsolescent . Please change that to !" +#include diff --git a/l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/isspace.c b/l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/isspace.c new file mode 100644 index 00000000..bfa46648 --- /dev/null +++ b/l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/isspace.c @@ -0,0 +1,9 @@ +#include + +int __isspace_ascii ( int ch ); +int __isspace_ascii ( int ch ) +{ + return (unsigned int)(ch - 9) < 5u || ch == ' '; +} + +int isspace ( int ch ) __attribute__((weak,alias("__isspace_ascii"))); diff --git a/l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/memcpy.c b/l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/memcpy.c new file mode 100644 index 00000000..13acc63c --- /dev/null +++ b/l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/memcpy.c @@ -0,0 +1,13 @@ +#include +#include + +void* memcpy(void* dst, const void* src, size_t count) { + register char *d=dst; + register const char *s=src; + ++count; /* this actually produces better code than using count-- */ + while (--count) { + *d = *s; + ++d; ++s; + } + return dst; +} diff --git a/l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/memmove.c b/l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/memmove.c new file mode 100644 index 00000000..be21a7cb --- /dev/null +++ b/l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/memmove.c @@ -0,0 +1,24 @@ +#define _POSIX_SOURCE +#define _XOPEN_SOURCE +#include +#include + +void *memmove(void *dst, const void *src, size_t count) +{ + char *a = dst; + const char *b = src; + if (src!=dst) + { + if (src>dst) + { + while (count--) *a++ = *b++; + } + else + { + a+=count-1; + b+=count-1; + while (count--) *a-- = *b--; + } + } + return dst; +} diff --git a/l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/memset.c b/l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/memset.c new file mode 100644 index 00000000..d1a367e1 --- /dev/null +++ b/l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/memset.c @@ -0,0 +1,10 @@ +#include +#include + +void * memset(void * dst, int s, size_t count) { + register char * a = dst; + count++; /* this actually creates smaller code than using count-- */ + while (--count) + *a++ = s; + return dst; +} diff --git a/l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/printf.c b/l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/printf.c new file mode 100644 index 00000000..1b8643e9 --- /dev/null +++ b/l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/printf.c @@ -0,0 +1,14 @@ +#include +#include + +int printf (const char *format, ...) { + + int n; + va_list args; + + va_start (args, format); + n = vprintf (format, args); + va_end (args); + + return n; +} diff --git a/l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/puts.c b/l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/puts.c new file mode 100644 index 00000000..a9e70c9a --- /dev/null +++ b/l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/puts.c @@ -0,0 +1,21 @@ +#include +#include +#include "libc_backend.h" + +size_t strlen(const char *s) +{ + size_t l = 0; + while (*s) + { + l++; + s++; + } + return l; +} + + +int puts(const char *c) +{ + __libc_backend_outs(c, strlen(c)); + return __libc_backend_outs("\n", 1); +} diff --git a/l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/strtol.c b/l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/strtol.c new file mode 100644 index 00000000..c9a581a4 --- /dev/null +++ b/l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/strtol.c @@ -0,0 +1,29 @@ +#include +#include + +#define ABS_LONG_MIN 2147483648UL + +long int strtol (const char *nptr, char **endptr, int base) { + + int neg = 0; + unsigned long int v; + + while (isspace (*nptr)) + nptr++; + + if (*nptr == '-') { + neg = -1; + ++nptr; + } + + v = strtoul (nptr, endptr, base); + + if (v >= ABS_LONG_MIN) { + if (v == ABS_LONG_MIN && neg) { + return v; + } + return 0; //(neg ? LONG_MIN : LONG_MAX); + } + + return (neg ? -v : v); +} diff --git a/l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/strtoul.c b/l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/strtoul.c new file mode 100644 index 00000000..4612c13a --- /dev/null +++ b/l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/strtoul.c @@ -0,0 +1,40 @@ +#include +#include + +unsigned long int strtoul (const char *nptr, char **endptr, int base) { + + unsigned long int v=0; + + while(isspace(*nptr)) ++nptr; + if (*nptr == '+') ++nptr; + if (base==16 && nptr[0]=='0') goto skip0x; + if (!base) { + if (*nptr=='0') { + base=8; +skip0x: + if (nptr[1]=='x'||nptr[1]=='X') { + nptr+=2; + base=16; + } + } else + base=10; + } + while(*nptr) { + register unsigned char c=*nptr; + c=(c>='a'?c-'a'+10:c>='A'?c-'A'+10:c<='9'?c-'0':0xff); + if (c>=base) break; + { + register unsigned long int w=v << 4;/*=v*base*/; + if(base==8) w = v << 3; + //if(base==16) w = v << 4; + if(base==10) w = (v << 3) + (v << 1); + if (w +#include +#include + +#include "vprintf_backend.h" +#include "libc_backend.h" + + + +int vprintf(const char *format, va_list ap) +{ + struct output_op _ap = { 0, (output_func*) &__libc_backend_outs }; + return __v_printf(&_ap,format,ap); +} diff --git a/l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/vprintf_backend.h b/l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/vprintf_backend.h new file mode 100644 index 00000000..12002774 --- /dev/null +++ b/l4/pkg/bootstrap/server/src/ARCH-amd64/libc32/vprintf_backend.h @@ -0,0 +1,21 @@ +#ifndef __VPRINTF_BACKEND_H__ +#define __VPRINTF_BACKEND_H__ + +#include +#include + +typedef int (output_func)(char const *, size_t, void*); + +struct output_op { + void *data; + output_func *put; +}; + +__BEGIN_DECLS + +int __v_printf(struct output_op* fn, const char *format, va_list arg_ptr); + +__END_DECLS + + +#endif // __VPRINTF_BACKEND_H__ diff --git a/l4/pkg/bootstrap/server/src/ARCH-amd64/macros.h b/l4/pkg/bootstrap/server/src/ARCH-amd64/macros.h new file mode 100644 index 00000000..5be8da54 --- /dev/null +++ b/l4/pkg/bootstrap/server/src/ARCH-amd64/macros.h @@ -0,0 +1,21 @@ +/* + * (c) 2008-2009 Frank Mehnert , + * Torsten Frenzel + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ +#ifndef __ARCH_AMD64_MACROS_H__ +#define __ARCH_AMD64_MACROS_H__ + +/* We need this typecasts since addresses of the GRUB multiboot info + * have always a size of 32 Bit. */ + +#define L4_CHAR_PTR(x) (char*)(l4_addr_t)(x) +#define L4_CONST_CHAR_PTR(x) (const char*)(l4_addr_t)(x) +#define L4_VOID_PTR(x) (void*)(l4_addr_t)(x) +#define L4_MB_MOD_PTR(x) (l4util_mb_mod_t*)(l4_addr_t)(x) + +#endif /* ! __ARCH_AMD64_MACROS_H__ */ diff --git a/l4/pkg/bootstrap/server/src/ARCH-arm/bootstrap.ld.in b/l4/pkg/bootstrap/server/src/ARCH-arm/bootstrap.ld.in new file mode 100644 index 00000000..e536d057 --- /dev/null +++ b/l4/pkg/bootstrap/server/src/ARCH-arm/bootstrap.ld.in @@ -0,0 +1,145 @@ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg , + * Frank Mehnert + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ + +#include "ldscript.inc" + +OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", + "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) + +PHDRS { + common PT_LOAD; +#ifndef SINGLE_SECTION + mods PT_LOAD; +#endif +} + +/* Some explanation for SINGLE_SECTION thing: For bootstrap we want to have + * a single program header only because some boot-loaders require that. + * Unfortunately it does not seem to be possible to have the following + * order: + * text - data - bss - modules + * because bss is smaller in the binary than unpacked and things get screwed + * up. So what we do it the following: + * text - data_including_bss - modules + * This way things seem to work and we only have one program header. + */ + +SECTIONS +{ + /* Read-only sections, merged into text segment. The start address of + * the text segment is : */ + . = LINKADDR; + .text : + { + _stext = .; + *(.text.init) + *(.init) + *(.text .text.* .gnu.linkonce.t.*) + *(.glue_7t) *(.glue_7) + KEEP (*(.fini)) + LONG(0xc3) /* terminate .fini */ + . = ALIGN(0x40); + *(.rodata .rodata.* .gnu.linkonce.r.* .rodata1) + } : common + + _etext = .; + PROVIDE (etext = .); + + /* ensure that data starts at a new L4 page */ + . = ALIGN(4096); + .data : + { + *(.data .data.* .gnu.linkonce.d.*) + *(.anno) + + CTORS + PLATFORMS + + . = ALIGN(4); + _module_info_start = .; + *(.module_info) + _module_info_end = .; + +#ifndef SINGLE_SECTION + } : common + + /* exception frames for C++ */ + .eh_frame : + { +#endif + KEEP (*(.eh_frame)) + LONG(0) /* terminate .eh_frame */ +#ifndef SINGLE_SECTION + } : common +#endif + + . = ALIGN(4); + _edata = .; + PROVIDE (edata = .); + + _bss_start = .; +#ifndef SINGLE_SECTION + .bss : + { +#endif + *(.dynbss) + *(.bss .gnu.linkonce.b.*) + *(COMMON) + } : common + _bss_end = .; + _end = . ; + PROVIDE (end = .); + +/* Only move modules to modaddr if bootstrap is being loaded by an elf + * loader, and we do not need to copy images around at runtime (e.g. with + * compression) */ +#if defined(PLACE_MODULES_AT_MODADDR) && !defined(SINGLE_SECTION) + . = RAM_BASE + MODADDR; +#endif + . = ALIGN(4096); + .data.m : + { + _modules_start = .; + *(.module.data) + . = ALIGN(4096); + _modules_end = .; + + . = ALIGN(4096); + _module_data_start = .; + *(.module_data) + _module_data_end = .; +#ifndef SINGLE_SECTION + } : mods +#else + } : common +#endif + + /* Moved here to ensure that these sections are located _after_ the text + * section. In the other case we would get program sections with a virtual + * address of 0 */ + .hash : { *(.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .rel.dyn : { *(.rel.dyn) } + + /* drop the following sections since we do not need them for DROPS */ + /DISCARD/ : { + *(.interp) + *(.comment) + *(.note) + *(.stab) + *(.fini) + *(.ARM.exidx*) + } +} + diff --git a/l4/pkg/bootstrap/server/src/ARCH-arm/crt0.S b/l4/pkg/bootstrap/server/src/ARCH-arm/crt0.S new file mode 100644 index 00000000..b5102520 --- /dev/null +++ b/l4/pkg/bootstrap/server/src/ARCH-arm/crt0.S @@ -0,0 +1,200 @@ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Frank Mehnert + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ +/* -*- c -*- */ + +#define MIMIC_A_VMLINUZ + +.section .text.init,#alloc,#execinstr +.type _start,#function +.globl _start +_start: +/* Some bootloaders like it this way, for others it won't harm */ +#ifdef MIMIC_A_VMLINUZ + nop + nop + nop + nop + nop + nop + nop + nop + b 10f + .word 0x016f2818 + .word _start + .word _edata +10: +#endif + /* + * It might be the case that we're not run at the position where we + * have been linked to. If this is the case we copy ourselves to the + * position we're linked to. + */ + adr r4, run /* Running version */ + ldr r5, .LCrun /* supposed to be version */ + cmp r4, r5 /* If equal ... */ + beq run /* ... go to run */ + + /* Disable caches as we're moving code around */ + mrc p15, 0, r0, c1, c0 + bic r0, #0x0004 + bic r0, #0x1000 + mcr p15, 0, r0, c1, c0 + + /* Figure how to move */ + ldr r7, .LCend_bin + subs r8, r5, r4 /* r8 is the distance between the blocks */ + bpl move_behind + + /* Copy before, copy forwards */ + /* First, copy our copy loop to the very beginning to avoid code + * overwrites */ + mov r9, r5 /* r9: run address */ + ldr r0, .LCstart_bin + ldr r1, 3f + str r1, [r0], #4 + ldr r1, 32f + str r1, [r0], #4 + ldr r1, 33f + str r1, [r0], #4 + ldr r1, 34f + str r1, [r0], #4 + ldr r1, 35f + str r1, [r0], #4 + ldr pc, .LCstart_bin + +3: ldr r6, [r4], #4 +32: str r6, [r5], #4 +33: cmp r5, r7 +34: blt 3b +35: mov pc, r9 + + /* Copy behind, copy backwards */ +move_behind: + sub r8, r7, r8 /* r8 points to the end of source image */ +3: ldr r6, [r8, #-4]! /* Take bytes */ + str r6, [r7, #-4]! /* Put bytes */ + cmp r5, r7 + blt 3b + ldr pc, .LCrun + + +.LCrun: .word run +.LCstart_bin: .word _start +.LCend_bin: .word _module_data_end + +run: + mov r1, #0x1000 + sub r1, r1, #1 /* r1 == 0xfff */ + mrc p15, 0, r0, c0, c0, 0 /* Main ID */ + lsr r0, #4 + and r0, r0, r1 + + /* Check for processors that understand CPU ID */ + mov r9, #0xb00 + orr r9, #0x002 + cmp r0, r9 + beq do_cpuid + + mov r9, #0xc00 + orr r9, #0x009 + cmp r0, r9 + bne do_bootstrap /* None matched, normal startup */ + +do_cpuid: + mrc p15, 0, r0, c0, c0, 5 /* CPU ID */ + and r0, r0, #0xf /* CPU id */ + cmp r0, #0 /* CPU0 continues with bootstrap */ + beq do_bootstrap + +/* CPU1+ wait for bootup */ + + // I-cache on + mrc p15, 0, r0, c1, c0, 0 + orr r0, r0, #(1 << 12) + mcr p15, 0, r0, c1, c0, 0 + + // IRQs off, SVC + mrs r0, cpsr + orr r0, #0xd3 + msr cpsr_c, r0 + +#if defined(PLATFORM_TYPE_rv) || defined(PLATFORM_TYPE_rv_pbx) || defined(PLATFORM_TYPE_rv_vexpress) + // enable GIC CPU interface + prio mask for IRQs + + // get board ID and retrieve MPCore-base from table + mov r5, #0x10000000 + ldr r5, [r5] + bic r5, #0xff + adr r6, .Lmpcore_base_table +2: + ldr r4, [r6] + cmp r4, #0 + cmpne r4, r5 + ldreq r4, [r6, #4] + beq 3f + add r6, #8 + b 2b + +3: + add r4, r4, #0x100 + mov r0, #0x1 + str r0, [r4, #0] + mov r0, #0xf0 + str r0, [r4, #4] + +1: + mov r5, #0x10000000 + ldr r6, [r5, #0x30] + cmp r6, #0 + movne pc, r6 + .word 0xe320f003 /* wfi */ + ldr r0, [r4, #12] + str r0, [r4, #16] + b 1b + +.Lmpcore_base_table: + /* VExpress */ + .word 0x1190f500 /* Board ID */ + .word 0x1e000000 /* MPCore base */ + + /* Default value (with #0) must come last! */ + /* Realview */ + .word 0 + .word 0x1f000000 + +#else +1: .word 0xe320f003 /* wfi */ + b 1b +#endif + +do_bootstrap: + ldr r3, .LCcrt0_tramppage /* Load address of tramppage var */ + str sp, [r3] /* Store SP in variable */ + ldr sp, .LCstack + + mov r0, r2 /* ATAG pointer */ + bl __main +1: b 1b + +.LCcrt0_tramppage: .word crt0_tramppage +.LCstack: .word crt0_stack_high + +.section ".bss" + + .global crt0_tramppage +crt0_tramppage: + .space 4 + + .global crt0_stack_low + .align 3 +crt0_stack_low: + .space 8192 + .global crt0_stack_high +crt0_stack_high: diff --git a/l4/pkg/bootstrap/server/src/ARCH-arm/macros.h b/l4/pkg/bootstrap/server/src/ARCH-arm/macros.h new file mode 100644 index 00000000..682fdcca --- /dev/null +++ b/l4/pkg/bootstrap/server/src/ARCH-arm/macros.h @@ -0,0 +1,9 @@ +/* + * (c) 2008-2009 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ +#include "ARCH-x86/macros.h" diff --git a/l4/pkg/bootstrap/server/src/ARCH-arm/reboot.cc b/l4/pkg/bootstrap/server/src/ARCH-arm/reboot.cc new file mode 100644 index 00000000..e0bd6f25 --- /dev/null +++ b/l4/pkg/bootstrap/server/src/ARCH-arm/reboot.cc @@ -0,0 +1,17 @@ +/* + * (c) 2008-2009 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ + +void +reboot_arch(void) __attribute__((noreturn)); + +void +reboot_arch(void) +{ + for (;;) + ; +} diff --git a/l4/pkg/bootstrap/server/src/ARCH-ppc32/bootstrap.ld.in b/l4/pkg/bootstrap/server/src/ARCH-ppc32/bootstrap.ld.in new file mode 100644 index 00000000..8728e4f6 --- /dev/null +++ b/l4/pkg/bootstrap/server/src/ARCH-ppc32/bootstrap.ld.in @@ -0,0 +1,108 @@ + +#include "ldscript.inc" + +OUTPUT_FORMAT("elf32-powerpc", "elf32-big", + "elf32-little") +ENTRY(_start) + +PHDRS { + text PT_LOAD; + data PT_LOAD; + mods PT_LOAD; +} + +SECTIONS +{ + /* Read-only sections, merged into text segment. The start address of + * the text segment is : */ + . = LINKADDR; + .text : + { + . = ALIGN(4); + _stext = .; + *(.text.init) + *(.init) + *(.text .text.* .gnu.linkonce.t.*) + *(.glue_7t) *(.glue_7) + KEEP (*(.fini)) + LONG(0xc3) /* terminate .fini */ + . = ALIGN(0x40); + *(.rodata .rodata.* .gnu.linkonce.r.* .rodata1) + } : text + + _etext = .; + PROVIDE (etext = .); + + /* ensure that data starts at a new L4 page */ + . = ALIGN(4096); + .data : + { + *(.data .data.* .gnu.linkonce.d.*) + *(.anno) + + CTORS + PLATFORMS + + . = ALIGN(4); + _module_info_start = .; + *(.module_info) + _module_info_end = .; + + . = ALIGN(4096); + _modules_start = .; + *(.module.data) + . = ALIGN(4096); + _modules_end = .; + } : data + /* exception frames for C++ */ + .eh_frame : + { + KEEP (*(.eh_frame)) + LONG(0) /* terminate .eh_frame */ + } : data + + . = ALIGN(4); + _edata = .; + PROVIDE (edata = .); + + _bss_start = .; + .bss : + { + *(.dynbss) + *(.bss .gnu.linkonce.b.*) + *(COMMON) + } : data + _bss_end = .; + _end = . ; + PROVIDE (end = .); + + /* Moved here to ensure that these sections are located _after_ the text + * section. In the other case we would get program sections with a virtual + * address of 0 */ + .hash : { *(.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .rel.dyn : { *(.rel.dyn) } + +/* Only move modules to modaddr if bootstrap is being loaded by an elf + * loader, and we do not need to copy images around at runtime (e.g. with + * compression) */ +#if defined(PLACE_MODULES_AT_MODADDR) && !defined(SINGLE_SECTION) + . = MODADDR; +#else + . = ALIGN(4096); +#endif + _module_data_start = .; + .module_data : { *(.module_data) } : mods + _module_data_end = .; + + /* drop the following sections since we do not need them for DROPS */ + /DISCARD/ : { + *(.interp) + *(.comment) + *(.note) + *(.stab) + *(.stabstr*) + } +} + diff --git a/l4/pkg/bootstrap/server/src/ARCH-ppc32/crt0.S b/l4/pkg/bootstrap/server/src/ARCH-ppc32/crt0.S new file mode 100644 index 00000000..9bc16306 --- /dev/null +++ b/l4/pkg/bootstrap/server/src/ARCH-ppc32/crt0.S @@ -0,0 +1,27 @@ +/* + * (c) 2009 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ +/* -*- c -*- */ + +.section .text.init, "ax" +.type _start, @function +.globl _start +_start: + lis %r1, crt0_stack_high@ha /* load stack pointer */ + addi %r1, %r1, crt0_stack_high@l + b __main +1: + b 1b + +.section ".bss", "aw" + +.global crt0_stack_low +crt0_stack_low: + .space 4096 +.global crt0_stack_high +crt0_stack_high: diff --git a/l4/pkg/bootstrap/server/src/ARCH-ppc32/init_kip_v2-arch.cc b/l4/pkg/bootstrap/server/src/ARCH-ppc32/init_kip_v2-arch.cc new file mode 100644 index 00000000..f40c0040 --- /dev/null +++ b/l4/pkg/bootstrap/server/src/ARCH-ppc32/init_kip_v2-arch.cc @@ -0,0 +1,23 @@ +/* + * (c) 2009 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ +#include "init_kip.h" + +#include + +void +init_kip_v2_arch(l4_kernel_info_t* l4i) +{ + L4_drivers::Of_if of_if; + //l4i->total_ram = of_if.detect_ramsize(); + printf("TBD: set total RAM via mem-descs!\n"); + l4i->frequency_cpu = (l4_uint32_t)of_if.detect_cpu_freq() / 1000; //kHz + l4i->frequency_bus = (l4_uint32_t)of_if.detect_bus_freq(); + + of_if.vesa_set_mode(0x117); +} diff --git a/l4/pkg/bootstrap/server/src/ARCH-ppc32/macros.h b/l4/pkg/bootstrap/server/src/ARCH-ppc32/macros.h new file mode 100644 index 00000000..b2edd95b --- /dev/null +++ b/l4/pkg/bootstrap/server/src/ARCH-ppc32/macros.h @@ -0,0 +1,9 @@ +/* + * (c) 2009 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ +#include "ARCH-x86/macros.h" diff --git a/l4/pkg/bootstrap/server/src/ARCH-ppc32/reboot.cc b/l4/pkg/bootstrap/server/src/ARCH-ppc32/reboot.cc new file mode 100644 index 00000000..e0bd6f25 --- /dev/null +++ b/l4/pkg/bootstrap/server/src/ARCH-ppc32/reboot.cc @@ -0,0 +1,17 @@ +/* + * (c) 2008-2009 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ + +void +reboot_arch(void) __attribute__((noreturn)); + +void +reboot_arch(void) +{ + for (;;) + ; +} diff --git a/l4/pkg/bootstrap/server/src/ARCH-sparc/bootstrap.ld.in b/l4/pkg/bootstrap/server/src/ARCH-sparc/bootstrap.ld.in new file mode 100644 index 00000000..05453c30 --- /dev/null +++ b/l4/pkg/bootstrap/server/src/ARCH-sparc/bootstrap.ld.in @@ -0,0 +1,81 @@ + +#include "ldscript.inc" + +ENTRY(_start) + +PHDRS { + common PT_LOAD; +#ifdef IMAGE_MODE + mods PT_LOAD; +#endif +} + +SECTIONS +{ + . = LINKADDR; + /* Merge .text, .rodata, and .data in one segment to save space */ + .text : + { + _stext = .; + *(.init) + *(.text .text.* .gnu.linkonce.t.*) + } : common + + .data : + { + *(.rodata* .gnu.linkonce.r.*) + . = ALIGN(8); + *(.data) + *(.data.*) + + CTORS + PLATFORMS + + _module_info_start = .; + *(.module_info) + _module_info_end = .; + + . = ALIGN(4096); + _modules_start = .; + *(.module.data) + . = ALIGN(4096); + _modules_end = .; + + } : common + + _edata = .; + PROVIDE (edata = .); + . = ALIGN(4096); + _bss_start = .; + .bss : + { + *(.bss) + *(COMMON) + *(.bss_memmap) + } : common + _bss_end = .; + _end = . ; + PROVIDE (end = .); + +/* Only move modules to modaddr if bootstrap is being loaded by an elf + * loader, and we do not need to copy images around at runtime (e.g. with + * compression) */ +#ifdef IMAGE_MODE +#if defined(PLACE_MODULES_AT_MODADDR) && !defined(SINGLE_SECTION) + . = RAM_BASE + MODADDR; +#endif + _module_data_start = .; + .module_data : { *(.module_data) } : mods + _module_data_end = .; +#endif + + /DISCARD/ : { + *(.interp) + *(.comment) + *(.note) + *(.eh_frame) + *(.stab) + *(.stabstr) + *(.fini) + } +} diff --git a/l4/pkg/bootstrap/server/src/ARCH-sparc/crt0.S b/l4/pkg/bootstrap/server/src/ARCH-sparc/crt0.S new file mode 100644 index 00000000..24732359 --- /dev/null +++ b/l4/pkg/bootstrap/server/src/ARCH-sparc/crt0.S @@ -0,0 +1,168 @@ +#define TRAP(H) mov %psr, %l0; sethi %hi(H), %l4; jmp %l4+%lo(H); nop; +#define TRAP_ENTRY(H) rd %psr, %l0; b H; rd %wim, %l3; nop; +#define TRAP_ENTRY_INTERRUPT(int_level) \ + mov int_level, %l7; rd %psr, %l0; b _prom_leonbare_irq_entry; rd %wim, %l3; +#define BAD_TRAP ta 0; nop; nop; nop; + +.section ".bss" +.align(0x2000) + .global crt0_stack_low +_stack: +crt0_stack_low: +.space 8192 + .global crt0_stack_high +crt0_stack_high: + +.text +/* + * Trap handler table -> must be aligned to page size + * as specified by the SPARC v8 manual (p. 31). + */ +.globl _leon_traphandlers +.align(0x1000) +_leon_traphandlers: + BAD_TRAP + BAD_TRAP + BAD_TRAP + BAD_TRAP + BAD_TRAP + TRAP(sparc_window_overflow); + TRAP(sparc_window_underflow); + BAD_TRAP + BAD_TRAP + BAD_TRAP + BAD_TRAP + BAD_TRAP + BAD_TRAP + BAD_TRAP + BAD_TRAP + BAD_TRAP + BAD_TRAP + +.globl _start +_start: + + rd %asr17, %g1 + + /* + * setup trap handler table + */ + sethi %hi(_leon_traphandlers), %g2 + wr %g2, %tbr + + /* the TBR setup above comes into effect three instructions from now! + * Right now, we assume that no trap occurs in between. + */ + + /* set stack pointer */ + sethi %hi(_stack), %sp + or %sp, %lo(_stack), %sp + + /* + * setup task with enough space for registers %l0-%l7 and %i0-%i7 + */ + sub %sp, 64, %sp + + sethi %hi(_stack), %fp + or %fp, %lo(_stack), %fp + + /* enable traps */ + mov %psr, %l0 + or %l0, (1 << 5), %l0 + mov %l0, %psr + + ba __main + nop + + ta 0 + + +.globl sparc_window_overflow +sparc_window_overflow: + mov %wim, %l3 /* need to determine new WIM */ + mov %g1, %l7 + srl %l3, 1, %g1 + + /* + * Find out if we are on LEON3 (PSR[24:27] == 3) + * or on LEON2. For LEON3, we can read the number of + * register windows from ASR17 + */ + mov %psr, %l4 + srl %l4, 24, %l4 + and %l4, 3, %l4 + subcc %l4, 3, %g0 + bne 1f + nop + + /* + * It's a LEON3 + */ + mov %asr17, %l4 + + /* calculate new WIM */ + and %l4, 0x1f, %l4 + sll %l3, %l4, %l4 + or %l4, %g1, %g1 + + /* + * The trick here is to move to a valid stack frame + * and store the register window contents there. + */ + save + mov %g1, %wim + nop; nop; nop + + std %l0, [%sp + 0]; + std %l2, [%sp + 8]; + std %l4, [%sp + 16]; + std %l6, [%sp + 24]; + std %i0, [%sp + 32]; + std %i2, [%sp + 40]; + std %i4, [%sp + 48]; + std %i6, [%sp + 56]; + + restore + mov %l7, %g1 + jmp %l1 + rett %l2 + +1: ta 0 + +.globl sparc_window_underflow +sparc_window_underflow: + mov %wim, %l3 /* need to determine new WIM */ + sll %l3, 1, %l4 + + /* Determine LEON version */ + mov %psr, %l5 + srl %l5, 24, %l5 + and %l5, 3, %l5 + subcc %l5, 3, %g0 + bne 1f + nop + + mov %asr17, %l5 + and %l5, 0x1f, %l5 + srl %l3, %l5, %l5 + or %l5, %l4, %l5 + mov %l5, %wim + nop; nop; nop + + restore ! Two restores to get into the + restore ! window to restore + ldd [%sp + 0], %l0; ! Restore window from the stack + ldd [%sp + 8], %l2; + ldd [%sp + 16], %l4; + ldd [%sp + 24], %l6; + ldd [%sp + 32], %i0; + ldd [%sp + 40], %i2; + ldd [%sp + 48], %i4; + ldd [%sp + 56], %i6; + save ! Get back to the trap window. + save + + jmp %l1 + rett %l2 + +1: ta 0 diff --git a/l4/pkg/bootstrap/server/src/ARCH-sparc/leon_ahb.h b/l4/pkg/bootstrap/server/src/ARCH-sparc/leon_ahb.h new file mode 100644 index 00000000..3d8f4bc6 --- /dev/null +++ b/l4/pkg/bootstrap/server/src/ARCH-sparc/leon_ahb.h @@ -0,0 +1,69 @@ +#pragma once + +enum Leon_memory_map +{ + LEON_PROM_BASE = 0x00000000, + LEON_IO_BASE = 0x20000000, + LEON_RAM_BASE = 0x40000000, + LEON_AHB_BASE = 0x80000000, + LEON_ETH_BASE = 0xFFFB0000, + LEON_CAN_BASE = 0xFFFC0000, + LEON_PNP_BASE = 0xFFFFF000, +}; + + +enum Leon_register_offsets +{ + LEON_MCTRL = 0, + LEON_APBUART = 0x100, + LEON_IRQMP = 0x200, + LEON_GPTIMER = 0x300, + LEON_PS2 = 0x500, + LEON_VGA = 0x600, + LEON_AHBUART = 0x700, + LEON_GRGPIO = 0x800, + LEON_GRSPW1 = 0xA00, + LEON_GRSPW2 = 0xB00, + LEON_GRSPW3 = 0xD00, + LEON_AHBSTAT = 0xF00, + LEON_AHBPNP = 0xFF000, +}; + + +enum Leon_traps +{ + LEON_TR_RESET = 0x00, + LEON_TR_INSTR_ACCESS_ERR = 0x01, + LEON_TR_ILLEGAL_INSTR = 0x02, + LEON_TR_PRIV_INSTR = 0x03, + LEON_TR_FP_DISABLED = 0x04, + LEON_TR_WRITE_ERR = 0x2B, + LEON_TR_CP_DISABLED = 0x2f, + LEON_TR_WATCHPOINT = 0x0B, + LEON_TR_WINDOW_OVERFL = 0x05, + LEON_TR_WINDOW_UNDERFL = 0x06, + LEON_TR_REG_HW_ERR = 0x20, + LEON_TR_ALIGN = 0x07, + LEON_TR_FP_EXC = 0x08, + LEON_TR_CP_EXC = 0x28, + LEON_TR_DATA_ACCESS_EXC = 0x09, + LEON_TR_TAG_OVERFL = 0x0A, + LEON_TR_DIVIDE_EXC = 0x2A, + LEON_TR_IRQ1 = 0x11, + LEON_TR_IRQ2 = 0x12, + LEON_TR_IRQ3 = 0x13, + LEON_TR_IRQ4 = 0x14, + LEON_TR_IRQ5 = 0x15, + LEON_TR_IRQ6 = 0x16, + LEON_TR_IRQ7 = 0x17, + LEON_TR_IRQ8 = 0x18, + LEON_TR_IRQ9 = 0x19, + LEON_TR_IRQ10 = 0x1A, + LEON_TR_IRQ11 = 0x1B, + LEON_TR_IRQ12 = 0x1C, + LEON_TR_IRQ13 = 0x1D, + LEON_TR_IRQ14 = 0x1E, + LEON_TR_IRQ15 = 0x1F, + LEON_TR_SW_MIN = 0x80, + LEON_TR_SW_MAX = 0xFF, +}; diff --git a/l4/pkg/bootstrap/server/src/ARCH-sparc/macros.h b/l4/pkg/bootstrap/server/src/ARCH-sparc/macros.h new file mode 100644 index 00000000..90176802 --- /dev/null +++ b/l4/pkg/bootstrap/server/src/ARCH-sparc/macros.h @@ -0,0 +1,17 @@ +/* + * (c) 2009 Torsten Frenzel + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ +#ifndef __ARCH_SPARC_MACROS_H__ +#define __ARCH_SPARC_MACROS_H__ + +#define L4_CHAR_PTR (char*) +#define L4_CONST_CHAR_PTR (const char*) +#define L4_VOID_PTR (void*) +#define L4_MB_MOD_PTR (l4util_mb_mod_t*) + +#endif /* ! __ARCH_SPARC_MACROS_H__ */ diff --git a/l4/pkg/bootstrap/server/src/ARCH-sparc/reboot.cc b/l4/pkg/bootstrap/server/src/ARCH-sparc/reboot.cc new file mode 100644 index 00000000..e0bd6f25 --- /dev/null +++ b/l4/pkg/bootstrap/server/src/ARCH-sparc/reboot.cc @@ -0,0 +1,17 @@ +/* + * (c) 2008-2009 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ + +void +reboot_arch(void) __attribute__((noreturn)); + +void +reboot_arch(void) +{ + for (;;) + ; +} diff --git a/l4/pkg/bootstrap/server/src/ARCH-x86/bootsect.S b/l4/pkg/bootstrap/server/src/ARCH-x86/bootsect.S new file mode 100644 index 00000000..c13b7686 --- /dev/null +++ b/l4/pkg/bootstrap/server/src/ARCH-x86/bootsect.S @@ -0,0 +1,108 @@ +/* + * bootsect.S Copyright (C) 1991, 1992 Linus Torvalds + * + * modified by Drew Eckhardt + * modified by Bruce Evans (bde) + * modified by Chris Noe (May 1999) (as86 -> gas) + * gutted by H. Peter Anvin (Jan 2003) + * + * BIG FAT NOTE: We're in real mode using 64k segments. Therefore segment + * addresses must be multiplied by 16 to obtain their respective linear + * addresses. To avoid confusion, linear addresses are written using leading + * hex while segment addresses are written as segment:offset. + * + */ + +/* Don't touch these, unless you really know what you're doing. */ +#define DEF_INITSEG 0x9000 +#define DEF_SYSSEG 0x1000 +#define DEF_SETUPSEG 0x9020 +#define DEF_SYSSIZE 0x7F00 + +/* Internal svga startup constants */ +#define NORMAL_VGA 0xffff /* 80x25 mode */ +#define EXTENDED_VGA 0xfffe /* 80x50 mode */ +#define ASK_VGA 0xfffd /* ask for it at bootup */ + + +SETUPSECTS = 6 /* default nr of setup-sectors */ +BOOTSEG = 0x07C0 /* original address of boot-sector */ +INITSEG = DEF_INITSEG /* we move boot here - out of the way */ +SETUPSEG = DEF_SETUPSEG /* setup starts here */ +SYSSEG = DEF_SYSSEG /* system loaded at 0x10000 (65536) */ +SYSSIZE = DEF_SYSSIZE /* system size: # of 16-byte clicks */ + /* to be loaded */ +ROOT_DEV = 0 /* ROOT_DEV is now written by "build" */ +SWAP_DEV = 0 /* SWAP_DEV is now written by "build" */ + +#ifndef SVGA_MODE +#define SVGA_MODE ASK_VGA +#endif + +#ifndef RAMDISK +#define RAMDISK 0 +#endif + +#ifndef ROOT_RDONLY +#define ROOT_RDONLY 1 +#endif + +.code16 +.text + +.global _start +_start: + + # Normalize the start address + jmpl $BOOTSEG, $start2 + +start2: + movw %cs, %ax + movw %ax, %ds + movw %ax, %es + movw %ax, %ss + movw $0x7c00, %sp + sti + cld + + movw $bugger_off_msg, %si + +msg_loop: + lodsb + andb %al, %al + jz die + movb $0xe, %ah + movw $7, %bx + int $0x10 + jmp msg_loop + +die: + # Allow the user to press a key, then reboot + xorw %ax, %ax + int $0x16 + int $0x19 + + # int 0x19 should never return. In case it does anyway, + # invoke the BIOS reset code... + ljmp $0xf000,$0xfff0 + + +bugger_off_msg: + .ascii "Direct booting from floppy is no longer supported.\r\n" + .ascii "Please use a boot loader program instead.\r\n" + .ascii "\n" + .ascii "Remove disk and press any key to reboot . . .\r\n" + .byte 0 + + + # Kernel attributes; used by setup + + .org 497 +setup_sects: .byte SETUPSECTS +root_flags: .word ROOT_RDONLY +syssize: .word SYSSIZE +swap_dev: .word SWAP_DEV +ram_size: .word RAMDISK +vid_mode: .word SVGA_MODE +root_dev: .word ROOT_DEV +boot_flag: .word 0xAA55 diff --git a/l4/pkg/bootstrap/server/src/ARCH-x86/bootstrap.ld.in b/l4/pkg/bootstrap/server/src/ARCH-x86/bootstrap.ld.in new file mode 100644 index 00000000..2ba7bb2e --- /dev/null +++ b/l4/pkg/bootstrap/server/src/ARCH-x86/bootstrap.ld.in @@ -0,0 +1,79 @@ + +#include "ldscript.inc" + +ENTRY(_start) + +PHDRS { + data PT_LOAD; +#ifdef IMAGE_MODE + mods PT_LOAD; +#endif +} + +SECTIONS +{ +#ifdef ARCH_amd64 + . = LINKADDR + SIZEOF_HEADERS; +#else + . = LINKADDR; +#endif + + /* Merge .text, .rodata, and .data in one segment to save space */ + .data : + { + *(.init) + *(.text .text.* .gnu.linkonce.t*) + *(.rodata*) + . = ALIGN(8); + *(.data) + *(.data.*) + + CTORS + PLATFORMS + + _module_info_start = .; + *(.module_info) + _module_info_end = .; + + . = ALIGN(4096); + _modules_start = .; + *(.module.data) + . = ALIGN(4096); + _modules_end = .; + + } : data + _edata = .; + PROVIDE (edata = .); + . = ALIGN(4096); + __bss_start = .; + .bss : + { + *(.bss) + *(COMMON) + *(.bss_memmap) + } : data + _end = . ; + PROVIDE (end = .); + +/* Only move modules to modaddr if bootstrap is being loaded by an elf + * loader, and we do not need to copy images around at runtime (e.g. with + * compression) */ +#ifdef IMAGE_MODE +#if defined(PLACE_MODULES_AT_MODADDR) && !defined(SINGLE_SECTION) + . = RAM_BASE + MODADDR; +#endif + _module_data_start = .; + .module_data : { *(.module_data) } : mods + _module_data_end = .; +#endif + + /DISCARD/ : { + *(.interp) + *(.comment) + *(.note) + *(.eh_frame) + *(.stab) + *(.stabstr) + *(.fini) + } +} diff --git a/l4/pkg/bootstrap/server/src/ARCH-x86/crt0.S b/l4/pkg/bootstrap/server/src/ARCH-x86/crt0.S new file mode 100644 index 00000000..77cec13a --- /dev/null +++ b/l4/pkg/bootstrap/server/src/ARCH-x86/crt0.S @@ -0,0 +1,200 @@ +/* + * (c) 2009 Adam Lackorzynski , + * Frank Mehnert + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ +#include + + .section .init + + .globl _start +_start: +#ifdef REALMODE_LOADING + cld + cli + mov $(3 * 8), %eax + mov %eax, %ds + mov %eax, %es + mov %eax, %fs + mov %eax, %gs + mov %eax, %ss + lss _stack_seg, %esp +#else + leal _stack, %esp +#endif + pushl $0 + pushl %esi /* Pointer to real mode or Xen start_info pointer */ + pushl %eax + pushl %ebx + +#ifndef XEN + /* initialize vector for exception 6 */ + movl $trap6_entry,%eax + movw %ax, _idt_offset_low + shrl $16, %eax + movw %ax, _idt_offset_high + movw %cs, %ax + movw %ax, _idt_selector + + /* load tiny interrupt descriptor table to catch exception 6 */ + lidtl _idtdesc +#endif + + pushl $_exit + jmp __main + + /* Show an error message and wait for keypress to reboot. */ +trap6_entry: + pusha + cld + + jmp 8f + + /* printhex + * edx: value to print + * eax: location on screen + */ +99: mov %eax, %edi + add $(2*8), %edi +98: mov $numbers,%ebx + mov %edx,%ecx + shr $28,%ecx + shl $4,%edx + movzbl (%ebx,%ecx,1),%ecx + mov $0x4, %ch + mov %cx,(%eax) + add $0x2,%eax + cmp %edi,%eax + jne 98b + ret + +8: + /* print out warning */ + movl $trap6_warning, %esi + movl $(0xb8000 + (24*80*2)), %edi + movb $0x0F, %ah + +1: /* read next character from string */ + lodsb + + /* check for end-of-string */ + cmpb $0, %al + je 3f + + /* Check for hex number */ + cmpb $' ', %al + jne 4f + pusha + mov (32 + 32)(%esp),%edx + mov %edi, %eax + call 99b + popa + add $(8*2), %edi + jmp 1b + +4: /* check for newline */ + cmpb $'\n', %al + jne 2f + + pushl %eax + pushl %esi + + /* move screen upwards 1 line */ + movl $((24*80*2)/4), %ecx + movl $(0xb8000 + 1*80*2), %esi + movl $0xb8000, %edi + rep movsl + + /* clear last line of screen */ + movl $((1*80*2)/4), %ecx + movl $0x07200720, %eax + rep stosl + + popl %esi + popl %eax + + /* jump to new line */ + movl $(0xb8000 + (24*80*2)), %edi + jmp 1b + +2: /* print character */ + stosw + jmp 1b + +3: /* wait for keypress */ + inb $0x64, %al + testb $0x01, %al + je 3b + + movb %al, %ah + + /* empty keyboard buffer */ + inb $0x60, %al + + /* ignore PS/2 mouse events */ + testb $0x20, %ah + jne 3b + + jmp reboot + + + /* the warning text */ +trap6_warning: + .ascii "\n" + .ascii "Bootstrap: Invalid opcode at detected!\n" + .ascii "Be sure that you don't use any CPU optimization flags like\n" + .ascii " -march=i686\n" + .ascii "when compiling Bootstrap and the depending libraries.\n" + .ascii "\n" + .asciz " Press any key to reboot..." + +numbers: + .ascii "0123456789abcdef" + + /* MultiBoot header - see multiboot.h. */ + .p2align(2) + +#define MULTIBOOT_MEMORY_INFO 0x00000002 +_mb_header: + .long 0x1BADB002 /* magic */ + .long MULTIBOOT_MEMORY_INFO /* flags: AOUT_KLUDGE */ + .long 0 - 0x1BADB002 - MULTIBOOT_MEMORY_INFO + +#ifndef XEN + .word 0 +_idtdesc: + .word (7*8)-1 + .long _idt + +_idt: + .word 0,0,0,0 /* trap 0 */ + .word 0,0,0,0 /* trap 1 */ + .word 0,0,0,0 /* trap 2 */ + .word 0,0,0,0 /* trap 3 */ + .word 0,0,0,0 /* trap 4 */ + .word 0,0,0,0 /* trap 5 */ + +_idt_offset_low: + .word 0 +_idt_selector: + .word 0 + .byte 0 + .byte 0xee +_idt_offset_high: + .word 0 +#endif + +#ifdef REALMODE_LOADING +_stack_seg: + .long _stack + .long (3 * 8) +#endif + + .bss + .space 8192 + .globl _stack +_stack: diff --git a/l4/pkg/bootstrap/server/src/ARCH-x86/macros.h b/l4/pkg/bootstrap/server/src/ARCH-x86/macros.h new file mode 100644 index 00000000..1c08fb55 --- /dev/null +++ b/l4/pkg/bootstrap/server/src/ARCH-x86/macros.h @@ -0,0 +1,17 @@ +/* + * (c) 2009 Torsten Frenzel + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ +#ifndef __ARCH_X86_MACROS_H__ +#define __ARCH_X86_MACROS_H__ + +#define L4_CHAR_PTR (char*) +#define L4_CONST_CHAR_PTR (const char*) +#define L4_VOID_PTR (void*) +#define L4_MB_MOD_PTR (l4util_mb_mod_t*) + +#endif /* ! __ARCH_X86_MACROS_H__ */ diff --git a/l4/pkg/bootstrap/server/src/ARCH-x86/reboot.cc b/l4/pkg/bootstrap/server/src/ARCH-x86/reboot.cc new file mode 100644 index 00000000..5ab3ed17 --- /dev/null +++ b/l4/pkg/bootstrap/server/src/ARCH-x86/reboot.cc @@ -0,0 +1,34 @@ +/* + * (c) 2008-2009 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ +#include +#include + +void +reboot_arch(void) __attribute__((noreturn)); + +void +reboot_arch(void) +{ + while (l4util_in8(0x64) & 0x02) + l4util_iodelay(); + l4util_out8(0x60, 0x64); + l4util_iodelay(); + + while (l4util_in8(0x64) & 0x02) + l4util_iodelay(); + l4util_out8(0x04, 0x60); + l4util_iodelay(); + + while (l4util_in8(0x64) & 0x02) + l4util_iodelay(); + l4util_out8(0xFE, 0x64); + l4util_iodelay(); + + for (;;) + l4util_cpu_pause(); +} diff --git a/l4/pkg/bootstrap/server/src/ARCH-x86/setup.S b/l4/pkg/bootstrap/server/src/ARCH-x86/setup.S new file mode 100644 index 00000000..f7405b5e --- /dev/null +++ b/l4/pkg/bootstrap/server/src/ARCH-x86/setup.S @@ -0,0 +1,3039 @@ +/* + * setup.S Copyright (C) 1991, 1992 Linus Torvalds + * + * setup.s is responsible for getting the system data from the BIOS, + * and putting them into the appropriate places in system memory. + * both setup.s and system has been loaded by the bootblock. + * + * This code asks the bios for memory/disk/other parameters, and + * puts them in a "safe" place: 0x90000-0x901FF, ie where the + * boot-block used to be. It is then up to the protected mode + * system to read them from there before the area is overwritten + * for buffer-blocks. + * + * Move PS/2 aux init code to psaux.c + * (troyer@saifr00.cfsat.Honeywell.COM) 03Oct92 + * + * some changes and additional features by Christoph Niemann, + * March 1993/June 1994 (Christoph.Niemann@linux.org) + * + * add APM BIOS checking by Stephen Rothwell, May 1994 + * (sfr@canb.auug.org.au) + * + * High load stuff, initrd support and position independency + * by Hans Lermen & Werner Almesberger, February 1996 + * , + * + * Video handling moved to video.S by Martin Mares, March 1996 + * + * + * Extended memory detection scheme retwiddled by orc@pell.chi.il.us (david + * parsons) to avoid loadlin confusion, July 1997 + * + * Transcribed from Intel (as86) -> AT&T (gas) by Chris Noe, May 1999. + * + * + * Fix to work around buggy BIOSes which dont use carry bit correctly + * and/or report extended memory in CX/DX for e801h memory size detection + * call. As a result the kernel got wrong figures. The int15/e801h docs + * from Ralf Brown interrupt list seem to indicate AX/BX should be used + * anyway. So to avoid breaking many machines (presumably there was a reason + * to orginally use CX/DX instead of AX/BX), we do a kludge to see + * if CX/DX have been changed in the e801 call and if so use AX/BX . + * Michael Miller, April 2001 + * + * New A20 code ported from SYSLINUX by H. Peter Anvin. AMD Elan bugfixes + * by Robert Schwebel, December 2001 + */ + +#define __BIG_KERNEL__ 1 + +//#include +//#include +//#include + +/* Don't touch these, unless you really know what you're doing. */ +#define DEF_INITSEG 0x9000 +#define DEF_SYSSEG 0x1000 +#define DEF_SETUPSEG 0x9020 +#define DEF_SYSSIZE 0x7F00 + +/* Internal svga startup constants */ +#define NORMAL_VGA 0xffff /* 80x25 mode */ +#define EXTENDED_VGA 0xfffe /* 80x50 mode */ +#define ASK_VGA 0xfffd /* ask for it at bootup */ + + +//#include +#define E820MAP 0x2d0 /* our map */ +#define E820MAX 32 /* number of entries in E820MAP */ +#define E820NR 0x1e8 /* # entries in E820MAP */ + +#define E820_RAM 1 +#define E820_RESERVED 2 +#define E820_ACPI 3 /* usable as RAM once ACPI tables have been read +*/ +#define E820_NVS 4 + +#define HIGH_MEMORY (1024*1024) + +//#include + +/* Signature words to ensure LILO loaded us right */ +#define SIG1 0xAA55 +#define SIG2 0x5A5A + +INITSEG = DEF_INITSEG # 0x9000, we move boot here, out of the way +SYSSEG = DEF_SYSSEG # 0x1000, system loaded at 0x10000 (65536). +SETUPSEG = DEF_SETUPSEG # 0x9020, this is the current segment + # ... and the former contents of CS + +DELTA_INITSEG = SETUPSEG - INITSEG # 0x0020 + +.code16 +.globl begtext, begdata, begbss, endtext, enddata, endbss + +.text +begtext: +.data +begdata: +.bss +begbss: +.text + +start: + jmp trampoline + +# This is the setup header, and it must start at %cs:2 (old 0x9020:2) + + .ascii "HdrS" # header signature + .word 0x0203 # header version number (>= 0x0105) + # or else old loadlin-1.5 will fail) +realmode_swtch: .word 0, 0 # default_switch, SETUPSEG +start_sys_seg: .word SYSSEG + .word kernel_version # pointing to kernel version string + # above section of header is compatible + # with loadlin-1.5 (header v1.5). Don't + # change it. + +type_of_loader: .byte 0 # = 0, old one (LILO, Loadlin, + # Bootlin, SYSLX, bootsect...) + # See Documentation/i386/boot.txt for + # assigned ids + +# flags, unused bits must be zero (RFU) bit within loadflags +loadflags: +LOADED_HIGH = 1 # If set, the kernel is loaded high +CAN_USE_HEAP = 0x80 # If set, the loader also has set + # heap_end_ptr to tell how much + # space behind setup.S can be used for + # heap purposes. + # Only the loader knows what is free +#ifndef __BIG_KERNEL__ + .byte 0 +#else + .byte LOADED_HIGH +#endif + +setup_move_size: .word 0x8000 # size to move, when setup is not + # loaded at 0x90000. We will move setup + # to 0x90000 then just before jumping + # into the kernel. However, only the + # loader knows how much data behind + # us also needs to be loaded. + +code32_start: # here loaders can put a different + # start address for 32-bit code. +#ifndef __BIG_KERNEL__ + .long 0x1000 # 0x1000 = default for zImage +#else + .long 0x100000 # 0x100000 = default for big kernel +#endif + +ramdisk_image: .long 0 # address of loaded ramdisk image + # Here the loader puts the 32-bit + # address where it loaded the image. + # This only will be read by the kernel. + +ramdisk_size: .long 0 # its size in bytes + +bootsect_kludge: + .long 0 # obsolete + +heap_end_ptr: .word modelist+1024 # (Header version 0x0201 or later) + # space from here (exclusive) down to + # end of setup code can be used by setup + # for local heap purposes. + +pad1: .word 0 +cmd_line_ptr: .long 0 # (Header version 0x0202 or later) + # If nonzero, a 32-bit pointer + # to the kernel command line. + # The command line should be + # located between the start of + # setup and the end of low + # memory (0xa0000), or it may + # get overwritten before it + # gets read. If this field is + # used, there is no longer + # anything magical about the + # 0x90000 segment; the setup + # can be located anywhere in + # low memory 0x10000 or higher. + +ramdisk_max: .long (-0xC0000000-(512 << 20)-1) & 0x7fffffff + # (Header version 0x0203 or later) + # The highest safe address for + # the contents of an initrd + +trampoline: call start_of_setup + .align 16 + # The offset at this point is 0x240 + .space (0x7ff-0x240+1) # E820 & EDD space (ending at 0x7ff) +# End of setup header ##################################################### + +start_of_setup: +# Bootlin depends on this being done early + movw $0x01500, %ax + movb $0x81, %dl + int $0x13 + +#ifdef SAFE_RESET_DISK_CONTROLLER +# Reset the disk controller. + movw $0x0000, %ax + movb $0x80, %dl + int $0x13 +#endif + +# Set %ds = %cs, we know that SETUPSEG = %cs at this point + movw %cs, %ax # aka SETUPSEG + movw %ax, %ds +# Check signature at end of setup + cmpw $SIG1, setup_sig1 + jne bad_sig + + cmpw $SIG2, setup_sig2 + jne bad_sig + + jmp good_sig1 + +# Routine to print asciiz string at ds:si +prtstr: + lodsb + andb %al, %al + jz fin + + call prtchr + jmp prtstr + +fin: ret + +# Space printing +prtsp2: call prtspc # Print double space +prtspc: movb $0x20, %al # Print single space (note: fall-thru) + +# Part of above routine, this one just prints ascii al +prtchr: pushw %ax + pushw %cx + movw $7,%bx + movw $0x01, %cx + movb $0x0e, %ah + int $0x10 + popw %cx + popw %ax + ret + +beep: movb $0x07, %al + jmp prtchr + +no_sig_mess: .string "No setup signature found ..." + +good_sig1: + jmp good_sig + +# We now have to find the rest of the setup code/data +bad_sig: + movw %cs, %ax # SETUPSEG + subw $DELTA_INITSEG, %ax # INITSEG + movw %ax, %ds + xorb %bh, %bh + movb (497), %bl # get setup sect from bootsect + subw $4, %bx # LILO loads 4 sectors of setup + shlw $8, %bx # convert to words (1sect=2^8 words) + movw %bx, %cx + shrw $3, %bx # convert to segment + addw $SYSSEG, %bx + movw %bx, %cs:start_sys_seg +# Move rest of setup code/data to here + movw $2048, %di # four sectors loaded by LILO + subw %si, %si + pushw %cs + popw %es + movw $SYSSEG, %ax + movw %ax, %ds + rep + movsw + movw %cs, %ax # aka SETUPSEG + movw %ax, %ds + cmpw $SIG1, setup_sig1 + jne no_sig + + cmpw $SIG2, setup_sig2 + jne no_sig + + jmp good_sig + +no_sig: + lea no_sig_mess, %si + call prtstr + +no_sig_loop: + hlt + jmp no_sig_loop + +good_sig: + movw %cs, %ax # aka SETUPSEG + subw $DELTA_INITSEG, %ax # aka INITSEG + movw %ax, %ds +# Check if an old loader tries to load a big-kernel + testb $LOADED_HIGH, %cs:loadflags # Do we have a big kernel? + jz loader_ok # No, no danger for old loaders. + + cmpb $0, %cs:type_of_loader # Do we have a loader that + # can deal with us? + jnz loader_ok # Yes, continue. + + pushw %cs # No, we have an old loader, + popw %ds # die. + lea loader_panic_mess, %si + call prtstr + + jmp no_sig_loop + +loader_panic_mess: .string "Wrong loader, giving up..." + +loader_ok: +# Get memory size (extended mem, kB) + + xorl %eax, %eax + movl %eax, (0x1e0) +#ifndef STANDARD_MEMORY_BIOS_CALL + movb %al, (E820NR) +# Try three different memory detection schemes. First, try +# e820h, which lets us assemble a memory map, then try e801h, +# which returns a 32-bit memory size, and finally 88h, which +# returns 0-64m + +# method E820H: +# the memory map from hell. e820h returns memory classified into +# a whole bunch of different types, and allows memory holes and +# everything. We scan through this memory map and build a list +# of the first 32 memory areas, which we return at [E820MAP]. +# This is documented at http://www.acpi.info/, in the ACPI 2.0 specification. + +#define SMAP 0x534d4150 + +meme820: + xorl %ebx, %ebx # continuation counter + movw $E820MAP, %di # point into the whitelist + # so we can have the bios + # directly write into it. + +jmpe820: + movl $0x0000e820, %eax # e820, upper word zeroed + movl $SMAP, %edx # ascii 'SMAP' + movl $20, %ecx # size of the e820rec + pushw %ds # data record. + popw %es + int $0x15 # make the call + jc bail820 # fall to e801 if it fails + + cmpl $SMAP, %eax # check the return is `SMAP' + jne bail820 # fall to e801 if it fails + +# cmpl $1, 16(%di) # is this usable memory? +# jne again820 + + # If this is usable memory, we save it by simply advancing %di by + # sizeof(e820rec). + # +good820: + movb (E820NR), %al # up to 32 entries + cmpb $E820MAX, %al + jnl bail820 + + incb (E820NR) + movw %di, %ax + addw $20, %ax + movw %ax, %di +again820: + cmpl $0, %ebx # check to see if + jne jmpe820 # %ebx is set to EOF +bail820: + + +# method E801H: +# memory size is in 1k chunksizes, to avoid confusing loadlin. +# we store the 0xe801 memory size in a completely different place, +# because it will most likely be longer than 16 bits. +# (use 1e0 because that's what Larry Augustine uses in his +# alternative new memory detection scheme, and it's sensible +# to write everything into the same place.) + +meme801: + stc # fix to work around buggy + xorw %cx,%cx # BIOSes which dont clear/set + xorw %dx,%dx # carry on pass/error of + # e801h memory size call + # or merely pass cx,dx though + # without changing them. + movw $0xe801, %ax + int $0x15 + jc mem88 + + cmpw $0x0, %cx # Kludge to handle BIOSes + jne e801usecxdx # which report their extended + cmpw $0x0, %dx # memory in AX/BX rather than + jne e801usecxdx # CX/DX. The spec I have read + movw %ax, %cx # seems to indicate AX/BX + movw %bx, %dx # are more reasonable anyway... + +e801usecxdx: + andl $0xffff, %edx # clear sign extend + shll $6, %edx # and go from 64k to 1k chunks + movl %edx, (0x1e0) # store extended memory size + andl $0xffff, %ecx # clear sign extend + addl %ecx, (0x1e0) # and add lower memory into + # total size. + +# Ye Olde Traditional Methode. Returns the memory size (up to 16mb or +# 64mb, depending on the bios) in ax. +mem88: + +#endif + movb $0x88, %ah + int $0x15 + movw %ax, (2) + +# Set the keyboard repeat rate to the max + movw $0x0305, %ax + xorw %bx, %bx + int $0x16 + +# Check for video adapter and its parameters and allow the +# user to browse video modes. + call video # NOTE: we need %ds pointing + # to bootsector + +# Get hd0 data... + xorw %ax, %ax + movw %ax, %ds + ldsw (4 * 0x41), %si + movw %cs, %ax # aka SETUPSEG + subw $DELTA_INITSEG, %ax # aka INITSEG + pushw %ax + movw %ax, %es + movw $0x0080, %di + movw $0x10, %cx + pushw %cx + cld + rep + movsb +# Get hd1 data... + xorw %ax, %ax + movw %ax, %ds + ldsw (4 * 0x46), %si + popw %cx + popw %es + movw $0x0090, %di + rep + movsb +# Check that there IS a hd1 :-) + movw $0x01500, %ax + movb $0x81, %dl + int $0x13 + jc no_disk1 + + cmpb $3, %ah + je is_disk1 + +no_disk1: + movw %cs, %ax # aka SETUPSEG + subw $DELTA_INITSEG, %ax # aka INITSEG + movw %ax, %es + movw $0x0090, %di + movw $0x10, %cx + xorw %ax, %ax + cld + rep + stosb +is_disk1: +# check for Micro Channel (MCA) bus + movw %cs, %ax # aka SETUPSEG + subw $DELTA_INITSEG, %ax # aka INITSEG + movw %ax, %ds + xorw %ax, %ax + movw %ax, (0xa0) # set table length to 0 + movb $0xc0, %ah + stc + int $0x15 # moves feature table to es:bx + jc no_mca + + pushw %ds + movw %es, %ax + movw %ax, %ds + movw %cs, %ax # aka SETUPSEG + subw $DELTA_INITSEG, %ax # aka INITSEG + movw %ax, %es + movw %bx, %si + movw $0xa0, %di + movw (%si), %cx + addw $2, %cx # table length is a short + cmpw $0x10, %cx + jc sysdesc_ok + + movw $0x10, %cx # we keep only first 16 bytes +sysdesc_ok: + rep + movsb + popw %ds +no_mca: +#ifdef CONFIG_X86_VOYAGER + movb $0xff, 0x40 # flag on config found + movb $0xc0, %al + mov $0xff, %ah + int $0x15 # put voyager config info at es:di + jc no_voyager + movw $0x40, %si # place voyager info in apm table + cld + movw $7, %cx +voyager_rep: + movb %es:(%di), %al + movb %al,(%si) + incw %di + incw %si + decw %cx + jnz voyager_rep +no_voyager: +#endif +# Check for PS/2 pointing device + movw %cs, %ax # aka SETUPSEG + subw $DELTA_INITSEG, %ax # aka INITSEG + movw %ax, %ds + movw $0, (0x1ff) # default is no pointing device + int $0x11 # int 0x11: equipment list + testb $0x04, %al # check if mouse installed + jz no_psmouse + + movw $0xAA, (0x1ff) # device present +no_psmouse: + +#if defined(CONFIG_X86_SPEEDSTEP_SMI) || defined(CONFIG_X86_SPEEDSTEP_SMI_MODULE) + movl $0x0000E980, %eax # IST Support + movl $0x47534943, %edx # Request value + int $0x15 + + movl %eax, (96) + movl %ebx, (100) + movl %ecx, (104) + movl %edx, (108) +#endif + +#if defined(CONFIG_APM) || defined(CONFIG_APM_MODULE) +# Then check for an APM BIOS... + # %ds points to the bootsector + movw $0, 0x40 # version = 0 means no APM BIOS + movw $0x05300, %ax # APM BIOS installation check + xorw %bx, %bx + int $0x15 + jc done_apm_bios # Nope, no APM BIOS + + cmpw $0x0504d, %bx # Check for "PM" signature + jne done_apm_bios # No signature, no APM BIOS + + andw $0x02, %cx # Is 32 bit supported? + je done_apm_bios # No 32-bit, no (good) APM BIOS + + movw $0x05304, %ax # Disconnect first just in case + xorw %bx, %bx + int $0x15 # ignore return code + movw $0x05303, %ax # 32 bit connect + xorl %ebx, %ebx + xorw %cx, %cx # paranoia :-) + xorw %dx, %dx # ... + xorl %esi, %esi # ... + xorw %di, %di # ... + int $0x15 + jc no_32_apm_bios # Ack, error. + + movw %ax, (66) # BIOS code segment + movl %ebx, (68) # BIOS entry point offset + movw %cx, (72) # BIOS 16 bit code segment + movw %dx, (74) # BIOS data segment + movl %esi, (78) # BIOS code segment lengths + movw %di, (82) # BIOS data segment length +# Redo the installation check as the 32 bit connect +# modifies the flags returned on some BIOSs + movw $0x05300, %ax # APM BIOS installation check + xorw %bx, %bx + xorw %cx, %cx # paranoia + int $0x15 + jc apm_disconnect # error -> shouldn't happen + + cmpw $0x0504d, %bx # check for "PM" signature + jne apm_disconnect # no sig -> shouldn't happen + + movw %ax, (64) # record the APM BIOS version + movw %cx, (76) # and flags + jmp done_apm_bios + +apm_disconnect: # Tidy up + movw $0x05304, %ax # Disconnect + xorw %bx, %bx + int $0x15 # ignore return code + + jmp done_apm_bios + +no_32_apm_bios: + andw $0xfffd, (76) # remove 32 bit support bit +done_apm_bios: +#endif + +//#include "edd.S" + +# Now we want to move to protected mode ... + cmpw $0, %cs:realmode_swtch + jz rmodeswtch_normal + + lcall *%cs:realmode_swtch + + jmp rmodeswtch_end + +rmodeswtch_normal: + pushw %cs + call default_switch + +rmodeswtch_end: +# we get the code32 start address and modify the below 'jmpi' +# (loader may have changed it) + movl %cs:code32_start, %eax + movl %eax, %cs:code32 + +# Now we move the system to its rightful place ... but we check if we have a +# big-kernel. In that case we *must* not move it ... + testb $LOADED_HIGH, %cs:loadflags + jz do_move0 # .. then we have a normal low + # loaded zImage + # .. or else we have a high + # loaded bzImage + jmp end_move # ... and we skip moving + +do_move0: + movw $0x100, %ax # start of destination segment + movw %cs, %bp # aka SETUPSEG + subw $DELTA_INITSEG, %bp # aka INITSEG + movw %cs:start_sys_seg, %bx # start of source segment + cld +do_move: + movw %ax, %es # destination segment + incb %ah # instead of add ax,#0x100 + movw %bx, %ds # source segment + addw $0x100, %bx + subw %di, %di + subw %si, %si + movw $0x800, %cx + rep + movsw + cmpw %bp, %bx # assume start_sys_seg > 0x200, + # so we will perhaps read one + # page more than needed, but + # never overwrite INITSEG + # because destination is a + # minimum one page below source + jb do_move + +end_move: +# then we load the segment descriptors + movw %cs, %ax # aka SETUPSEG + movw %ax, %ds + +# Check whether we need to be downward compatible with version <=201 + cmpl $0, cmd_line_ptr + jne end_move_self # loader uses version >=202 features + cmpb $0x20, type_of_loader + je end_move_self # bootsect loader, we know of it + +# Boot loader doesnt support boot protocol version 2.02. +# If we have our code not at 0x90000, we need to move it there now. +# We also then need to move the params behind it (commandline) +# Because we would overwrite the code on the current IP, we move +# it in two steps, jumping high after the first one. + movw %cs, %ax + cmpw $SETUPSEG, %ax + je end_move_self + + cli # make sure we really have + # interrupts disabled ! + # because after this the stack + # should not be used + subw $DELTA_INITSEG, %ax # aka INITSEG + movw %ss, %dx + cmpw %ax, %dx + jb move_self_1 + + addw $INITSEG, %dx + subw %ax, %dx # this will go into %ss after + # the move +move_self_1: + movw %ax, %ds + movw $INITSEG, %ax # real INITSEG + movw %ax, %es + movw %cs:setup_move_size, %cx + std # we have to move up, so we use + # direction down because the + # areas may overlap + movw %cx, %di + decw %di + movw %di, %si + subw $move_self_here+0x200, %cx + rep + movsb + ljmp $SETUPSEG, $move_self_here + +move_self_here: + movw $move_self_here+0x200, %cx + rep + movsb + movw $SETUPSEG, %ax + movw %ax, %ds + movw %dx, %ss +end_move_self: # now we are at the right place + +# +# Enable A20. This is at the very best an annoying procedure. +# A20 code ported from SYSLINUX 1.52-1.63 by H. Peter Anvin. +# AMD Elan bug fix by Robert Schwebel. +# + +#if defined(CONFIG_X86_ELAN) + movb $0x02, %al # alternate A20 gate + outb %al, $0x92 # this works on SC410/SC520 +a20_elan_wait: + call a20_test + jz a20_elan_wait + jmp a20_done +#endif + + +A20_TEST_LOOPS = 32 # Iterations per wait +A20_ENABLE_LOOPS = 255 # Total loops to try + + +#ifndef CONFIG_X86_VOYAGER +a20_try_loop: + + # First, see if we are on a system with no A20 gate. +a20_none: + call a20_test + jnz a20_done + + # Next, try the BIOS (INT 0x15, AX=0x2401) +a20_bios: + movw $0x2401, %ax + pushfl # Be paranoid about flags + int $0x15 + popfl + + call a20_test + jnz a20_done + + # Try enabling A20 through the keyboard controller +#endif /* CONFIG_X86_VOYAGER */ +a20_kbc: + call empty_8042 + +#ifndef CONFIG_X86_VOYAGER + call a20_test # Just in case the BIOS worked + jnz a20_done # but had a delayed reaction. +#endif + + movb $0xD1, %al # command write + outb %al, $0x64 + call empty_8042 + + movb $0xDF, %al # A20 on + outb %al, $0x60 + call empty_8042 + +#ifndef CONFIG_X86_VOYAGER + # Wait until a20 really *is* enabled; it can take a fair amount of + # time on certain systems; Toshiba Tecras are known to have this + # problem. +a20_kbc_wait: + xorw %cx, %cx +a20_kbc_wait_loop: + call a20_test + jnz a20_done + loop a20_kbc_wait_loop + + # Final attempt: use "configuration port A" +a20_fast: + inb $0x92, %al # Configuration Port A + orb $0x02, %al # "fast A20" version + andb $0xFE, %al # don't accidentally reset + outb %al, $0x92 + + # Wait for configuration port A to take effect +a20_fast_wait: + xorw %cx, %cx +a20_fast_wait_loop: + call a20_test + jnz a20_done + loop a20_fast_wait_loop + + # A20 is still not responding. Try frobbing it again. + # + decb (a20_tries) + jnz a20_try_loop + + movw $a20_err_msg, %si + call prtstr + +a20_die: + hlt + jmp a20_die + +a20_tries: + .byte A20_ENABLE_LOOPS + +a20_err_msg: + .ascii "linux: fatal error: A20 gate not responding!" + .byte 13, 10, 0 + + # If we get here, all is good +a20_done: + +#endif /* CONFIG_X86_VOYAGER */ +# set up gdt and idt + lidt idt_48 # load idt with 0,0 + xorl %eax, %eax # Compute gdt_base + movw %ds, %ax # (Convert %ds:gdt to a linear ptr) + shll $4, %eax + addl $gdt, %eax + movl %eax, (gdt_48+2) + lgdt gdt_48 # load gdt with whatever is + # appropriate + +# make sure any possible coprocessor is properly reset.. + xorw %ax, %ax + outb %al, $0xf0 + call delay + + outb %al, $0xf1 + call delay + +# well, that went ok, I hope. Now we mask all interrupts - the rest +# is done in init_IRQ(). + movb $0xFF, %al # mask all interrupts for now + outb %al, $0xA1 + call delay + + movb $0xFB, %al # mask all irq's but irq2 which + outb %al, $0x21 # is cascaded + +# Well, that certainly wasn't fun :-(. Hopefully it works, and we don't +# need no steenking BIOS anyway (except for the initial loading :-). +# The BIOS-routine wants lots of unnecessary data, and it's less +# "interesting" anyway. This is how REAL programmers do it. +# +# Well, now's the time to actually move into protected mode. To make +# things as simple as possible, we do no register set-up or anything, +# we let the gnu-compiled 32-bit programs do that. We just jump to +# absolute address 0x1000 (or the loader supplied one), +# in 32-bit protected mode. +# +# Note that the short jump isn't strictly needed, although there are +# reasons why it might be a good idea. It won't hurt in any case. + movw $1, %ax # protected mode (PE) bit + lmsw %ax # This is it! + jmp flush_instr + +flush_instr: + xorw %bx, %bx # Flag to indicate a boot + xorl %esi, %esi # Pointer to real-mode code + movw %cs, %si + subw $DELTA_INITSEG, %si + shll $4, %esi # Convert to 32-bit pointer + +# jump to startup_32 in arch/i386/boot/compressed/head.S +# +# NOTE: For high loaded big kernels we need a +# jmpi 0x100000,__BOOT_CS +# +# but we yet haven't reloaded the CS register, so the default size +# of the target offset still is 16 bit. +# However, using an operand prefix (0x66), the CPU will properly +# take our 48 bit far pointer. (INTeL 80386 Programmer's Reference +# Manual, Mixing 16-bit and 32-bit code, page 16-6) + + .byte 0x66, 0xea # prefix + jmpi-opcode +code32: .long 0x1000 # will be set to 0x100000 + # for big kernels + .word 2 * 8 + +# Here's a bunch of information about your current kernel.. +kernel_version: .ascii "bootstrap" + .byte 0 + +# This is the default real mode switch routine. +# to be called just before protected mode transition +default_switch: + cli # no interrupts allowed ! + movb $0x80, %al # disable NMI for bootup + # sequence + outb %al, $0x70 + lret + + +#ifndef CONFIG_X86_VOYAGER +# This routine tests whether or not A20 is enabled. If so, it +# exits with zf = 0. +# +# The memory address used, 0x200, is the int $0x80 vector, which +# should be safe. + +A20_TEST_ADDR = 4*0x80 + +a20_test: + pushw %cx + pushw %ax + xorw %cx, %cx + movw %cx, %fs # Low memory + decw %cx + movw %cx, %gs # High memory area + movw $A20_TEST_LOOPS, %cx + movw %fs:(A20_TEST_ADDR), %ax + pushw %ax +a20_test_wait: + incw %ax + movw %ax, %fs:(A20_TEST_ADDR) + call delay # Serialize and make delay constant + cmpw %gs:(A20_TEST_ADDR+0x10), %ax + loope a20_test_wait + + popw %fs:(A20_TEST_ADDR) + popw %ax + popw %cx + ret + +#endif /* CONFIG_X86_VOYAGER */ + +# This routine checks that the keyboard command queue is empty +# (after emptying the output buffers) +# +# Some machines have delusions that the keyboard buffer is always full +# with no keyboard attached... +# +# If there is no keyboard controller, we will usually get 0xff +# to all the reads. With each IO taking a microsecond and +# a timeout of 100,000 iterations, this can take about half a +# second ("delay" == outb to port 0x80). That should be ok, +# and should also be plenty of time for a real keyboard controller +# to empty. +# + +empty_8042: + pushl %ecx + movl $100000, %ecx + +empty_8042_loop: + decl %ecx + jz empty_8042_end_loop + + call delay + + inb $0x64, %al # 8042 status port + testb $1, %al # output buffer? + jz no_output + + call delay + inb $0x60, %al # read it + jmp empty_8042_loop + +no_output: + testb $2, %al # is input buffer full? + jnz empty_8042_loop # yes - loop +empty_8042_end_loop: + popl %ecx + ret + +# Read the cmos clock. Return the seconds in al +gettime: + pushw %cx + movb $0x02, %ah + int $0x1a + movb %dh, %al # %dh contains the seconds + andb $0x0f, %al + movb %dh, %ah + movb $0x04, %cl + shrb %cl, %ah + aad + popw %cx + ret + +# Delay is needed after doing I/O +delay: + outb %al,$0x80 + ret + +# Descriptor tables +# +# NOTE: The intel manual says gdt should be sixteen bytes aligned for +# efficiency reasons. However, there are machines which are known not +# to boot with misaligned GDTs, so alter this at your peril! If you alter +# GDT_ENTRY_BOOT_CS (in asm/segment.h) remember to leave at least two +# empty GDT entries (one for NULL and one reserved). +# +# NOTE: On some CPUs, the GDT must be 8 byte aligned. This is +# true for the Voyager Quad CPU card which will not boot without +# This directive. 16 byte aligment is recommended by intel. +# + .align 16 +gdt: + .fill 2,8,0 + + .word 0xFFFF # 4Gb - (0x100000*0x1000 = 4Gb) + .word 0 # base address = 0 + .word 0x9A00 # code read/exec + .word 0x00CF # granularity = 4096, 386 + # (+5th nibble of limit) + + .word 0xFFFF # 4Gb - (0x100000*0x1000 = 4Gb) + .word 0 # base address = 0 + .word 0x9200 # data read/write + .word 0x00CF # granularity = 4096, 386 + # (+5th nibble of limit) +gdt_end: + .align 4 + + .word 0 # alignment byte +idt_48: + .word 0 # idt limit = 0 + .word 0, 0 # idt base = 0L + + .word 0 # alignment byte +gdt_48: + .word gdt_end - gdt - 1 # gdt limit + .word 0, 0 # gdt base (filled in later) + +# Include video setup & detection code + +/* Enable autodetection of SVGA adapters and modes. */ +#undef CONFIG_VIDEO_SVGA + +/* Enable autodetection of VESA modes */ +#define CONFIG_VIDEO_VESA + +/* Enable compacting of mode table */ +#define CONFIG_VIDEO_COMPACT + +/* Retain screen contents when switching modes */ +#define CONFIG_VIDEO_RETAIN + +/* Enable local mode list */ +#undef CONFIG_VIDEO_LOCAL + +/* Force 400 scan lines for standard modes (hack to fix bad BIOS behaviour */ +#undef CONFIG_VIDEO_400_HACK + +/* Hack that lets you force specific BIOS mode ID and specific dimensions */ +#undef CONFIG_VIDEO_GFX_HACK +#define VIDEO_GFX_BIOS_AX 0x4f02 /* 800x600 on ThinkPad */ +#define VIDEO_GFX_BIOS_BX 0x0102 +#define VIDEO_GFX_DUMMY_RESOLUTION 0x6425 /* 100x37 */ + +/* This code uses an extended set of video mode numbers. These include: + * Aliases for standard modes + * NORMAL_VGA (-1) + * EXTENDED_VGA (-2) + * ASK_VGA (-3) + * Video modes numbered by menu position -- NOT RECOMMENDED because of lack + * of compatibility when extending the table. These are between 0x00 and 0xff. + */ +#define VIDEO_FIRST_MENU 0x0000 + +/* Standard BIOS video modes (BIOS number + 0x0100) */ +#define VIDEO_FIRST_BIOS 0x0100 + +/* VESA BIOS video modes (VESA number + 0x0200) */ +#define VIDEO_FIRST_VESA 0x0200 + +/* Video7 special modes (BIOS number + 0x0900) */ +#define VIDEO_FIRST_V7 0x0900 + +/* Special video modes */ +#define VIDEO_FIRST_SPECIAL 0x0f00 +#define VIDEO_80x25 0x0f00 +#define VIDEO_8POINT 0x0f01 +#define VIDEO_80x43 0x0f02 +#define VIDEO_80x28 0x0f03 +#define VIDEO_CURRENT_MODE 0x0f04 +#define VIDEO_80x30 0x0f05 +#define VIDEO_80x34 0x0f06 +#define VIDEO_80x60 0x0f07 +#define VIDEO_GFX_HACK 0x0f08 +#define VIDEO_LAST_SPECIAL 0x0f09 + +/* Video modes given by resolution */ +#define VIDEO_FIRST_RESOLUTION 0x1000 + +/* The "recalculate timings" flag */ +#define VIDEO_RECALC 0x8000 + +/* Positions of various video parameters passed to the kernel */ +/* (see also include/linux/tty.h) */ +#define PARAM_CURSOR_POS 0x00 +#define PARAM_VIDEO_PAGE 0x04 +#define PARAM_VIDEO_MODE 0x06 +#define PARAM_VIDEO_COLS 0x07 +#define PARAM_VIDEO_EGA_BX 0x0a +#define PARAM_VIDEO_LINES 0x0e +#define PARAM_HAVE_VGA 0x0f +#define PARAM_FONT_POINTS 0x10 + +#define PARAM_LFB_WIDTH 0x12 +#define PARAM_LFB_HEIGHT 0x14 +#define PARAM_LFB_DEPTH 0x16 +#define PARAM_LFB_BASE 0x18 +#define PARAM_LFB_SIZE 0x1c +#define PARAM_LFB_LINELENGTH 0x24 +#define PARAM_LFB_COLORS 0x26 +#define PARAM_VESAPM_SEG 0x2e +#define PARAM_VESAPM_OFF 0x30 +#define PARAM_LFB_PAGES 0x32 +#define PARAM_VESA_ATTRIB 0x34 + +/* Define DO_STORE according to CONFIG_VIDEO_RETAIN */ +#ifdef CONFIG_VIDEO_RETAIN +#define DO_STORE call store_screen +#else +#define DO_STORE +#endif /* CONFIG_VIDEO_RETAIN */ + +# This is the main entry point called by setup.S +# %ds *must* be pointing to the bootsector +video: pushw %ds # We use different segments + pushw %ds # FS contains original DS + popw %fs + pushw %cs # DS is equal to CS + popw %ds + pushw %cs # ES is equal to CS + popw %es + xorw %ax, %ax + movw %ax, %gs # GS is zero + cld + call basic_detect # Basic adapter type testing (EGA/VGA/MDA/CGA) +#ifdef CONFIG_VIDEO_SELECT + movw %fs:(0x01fa), %ax # User selected video mode + cmpw $ASK_VGA, %ax # Bring up the menu + jz vid2 + + call mode_set # Set the mode + jc vid1 + + leaw badmdt, %si # Invalid mode ID + call prtstr +vid2: call mode_menu +vid1: +#ifdef CONFIG_VIDEO_RETAIN + call restore_screen # Restore screen contents +#endif /* CONFIG_VIDEO_RETAIN */ + call store_edid +#endif /* CONFIG_VIDEO_SELECT */ + call mode_params # Store mode parameters + popw %ds # Restore original DS + ret + +# Detect if we have CGA, MDA, EGA or VGA and pass it to the kernel. +basic_detect: + movb $0, %fs:(PARAM_HAVE_VGA) + movb $0x12, %ah # Check EGA/VGA + movb $0x10, %bl + int $0x10 + movw %bx, %fs:(PARAM_VIDEO_EGA_BX) # Identifies EGA to the kernel + cmpb $0x10, %bl # No, it's a CGA/MDA/HGA card. + je basret + + incb adapter + movw $0x1a00, %ax # Check EGA or VGA? + int $0x10 + cmpb $0x1a, %al # 1a means VGA... + jne basret # anything else is EGA. + + incb %fs:(PARAM_HAVE_VGA) # We've detected a VGA + incb adapter +basret: ret + +# Store the video mode parameters for later usage by the kernel. +# This is done by asking the BIOS except for the rows/columns +# parameters in the default 80x25 mode -- these are set directly, +# because some very obscure BIOSes supply insane values. +mode_params: +#ifdef CONFIG_VIDEO_SELECT + cmpb $0, graphic_mode + jnz mopar_gr +#endif + movb $0x03, %ah # Read cursor position + xorb %bh, %bh + int $0x10 + movw %dx, %fs:(PARAM_CURSOR_POS) + movb $0x0f, %ah # Read page/mode/width + int $0x10 + movw %bx, %fs:(PARAM_VIDEO_PAGE) + movw %ax, %fs:(PARAM_VIDEO_MODE) # Video mode and screen width + cmpb $0x7, %al # MDA/HGA => segment differs + jnz mopar0 + + movw $0xb000, video_segment +mopar0: movw %gs:(0x485), %ax # Font size + movw %ax, %fs:(PARAM_FONT_POINTS) # (valid only on EGA/VGA) + movw force_size, %ax # Forced size? + orw %ax, %ax + jz mopar1 + + movb %ah, %fs:(PARAM_VIDEO_COLS) + movb %al, %fs:(PARAM_VIDEO_LINES) + ret + +mopar1: movb $25, %al + cmpb $0, adapter # If we are on CGA/MDA/HGA, the + jz mopar2 # screen must have 25 lines. + + movb %gs:(0x484), %al # On EGA/VGA, use the EGA+ BIOS + incb %al # location of max lines. +mopar2: movb %al, %fs:(PARAM_VIDEO_LINES) + ret + +#ifdef CONFIG_VIDEO_SELECT +# Fetching of VESA frame buffer parameters +mopar_gr: + leaw modelist+1024, %di + movb $0x23, %fs:(PARAM_HAVE_VGA) + movw 16(%di), %ax + movw %ax, %fs:(PARAM_LFB_LINELENGTH) + movw 18(%di), %ax + movw %ax, %fs:(PARAM_LFB_WIDTH) + movw 20(%di), %ax + movw %ax, %fs:(PARAM_LFB_HEIGHT) + movb 25(%di), %al + movb $0, %ah + movw %ax, %fs:(PARAM_LFB_DEPTH) + movb 29(%di), %al + movb $0, %ah + movw %ax, %fs:(PARAM_LFB_PAGES) + movl 40(%di), %eax + movl %eax, %fs:(PARAM_LFB_BASE) + movl 31(%di), %eax + movl %eax, %fs:(PARAM_LFB_COLORS) + movl 35(%di), %eax + movl %eax, %fs:(PARAM_LFB_COLORS+4) + movw 0(%di), %ax + movw %ax, %fs:(PARAM_VESA_ATTRIB) + +# get video mem size + leaw modelist+1024, %di + movw $0x4f00, %ax + int $0x10 + xorl %eax, %eax + movw 18(%di), %ax + movl %eax, %fs:(PARAM_LFB_SIZE) + +# switching the DAC to 8-bit is for <= 8 bpp only + movw %fs:(PARAM_LFB_DEPTH), %ax + cmpw $8, %ax + jg dac_done + +# get DAC switching capability + xorl %eax, %eax + movb 10(%di), %al + testb $1, %al + jz dac_set + +# attempt to switch DAC to 8-bit + movw $0x4f08, %ax + movw $0x0800, %bx + int $0x10 + cmpw $0x004f, %ax + jne dac_set + movb %bh, dac_size # store actual DAC size + +dac_set: +# set color size to DAC size + movb dac_size, %al + movb %al, %fs:(PARAM_LFB_COLORS+0) + movb %al, %fs:(PARAM_LFB_COLORS+2) + movb %al, %fs:(PARAM_LFB_COLORS+4) + movb %al, %fs:(PARAM_LFB_COLORS+6) + +# set color offsets to 0 + movb $0, %fs:(PARAM_LFB_COLORS+1) + movb $0, %fs:(PARAM_LFB_COLORS+3) + movb $0, %fs:(PARAM_LFB_COLORS+5) + movb $0, %fs:(PARAM_LFB_COLORS+7) + +dac_done: +# get protected mode interface informations + movw $0x4f0a, %ax + xorw %bx, %bx + xorw %di, %di + int $0x10 + cmp $0x004f, %ax + jnz no_pm + + movw %es, %fs:(PARAM_VESAPM_SEG) + movw %di, %fs:(PARAM_VESAPM_OFF) +no_pm: ret + +# The video mode menu +mode_menu: + leaw keymsg, %si # "Return/Space/Timeout" message + call prtstr + call flush +nokey: call getkt + + cmpb $0x0d, %al # ENTER ? + je listm # yes - manual mode selection + + cmpb $0x20, %al # SPACE ? + je defmd1 # no - repeat + + call beep + jmp nokey + +defmd1: ret # No mode chosen? Default 80x25 + +listm: call mode_table # List mode table +listm0: leaw name_bann, %si # Print adapter name + call prtstr + movw card_name, %si + orw %si, %si + jnz an2 + + movb adapter, %al + leaw old_name, %si + orb %al, %al + jz an1 + + leaw ega_name, %si + decb %al + jz an1 + + leaw vga_name, %si + jmp an1 + +an2: call prtstr + leaw svga_name, %si +an1: call prtstr + leaw listhdr, %si # Table header + call prtstr + movb $0x30, %dl # DL holds mode number + leaw modelist, %si +lm1: cmpw $ASK_VGA, (%si) # End? + jz lm2 + + movb %dl, %al # Menu selection number + call prtchr + call prtsp2 + lodsw + call prthw # Mode ID + call prtsp2 + movb 0x1(%si), %al + call prtdec # Rows + movb $0x78, %al # the letter 'x' + call prtchr + lodsw + call prtdec # Columns + movb $0x0d, %al # New line + call prtchr + movb $0x0a, %al + call prtchr + incb %dl # Next character + cmpb $0x3a, %dl + jnz lm1 + + movb $0x61, %dl + jmp lm1 + +lm2: leaw prompt, %si # Mode prompt + call prtstr + leaw edit_buf, %di # Editor buffer +lm3: call getkey + cmpb $0x0d, %al # Enter? + jz lment + + cmpb $0x08, %al # Backspace? + jz lmbs + + cmpb $0x20, %al # Printable? + jc lm3 + + cmpw $edit_buf+4, %di # Enough space? + jz lm3 + + stosb + call prtchr + jmp lm3 + +lmbs: cmpw $edit_buf, %di # Backspace + jz lm3 + + decw %di + movb $0x08, %al + call prtchr + call prtspc + movb $0x08, %al + call prtchr + jmp lm3 + +lment: movb $0, (%di) + leaw crlft, %si + call prtstr + leaw edit_buf, %si + cmpb $0, (%si) # Empty string = default mode + jz lmdef + + cmpb $0, 1(%si) # One character = menu selection + jz mnusel + + cmpw $0x6373, (%si) # "scan" => mode scanning + jnz lmhx + + cmpw $0x6e61, 2(%si) + jz lmscan + +lmhx: xorw %bx, %bx # Else => mode ID in hex +lmhex: lodsb + orb %al, %al + jz lmuse1 + + subb $0x30, %al + jc lmbad + + cmpb $10, %al + jc lmhx1 + + subb $7, %al + andb $0xdf, %al + cmpb $10, %al + jc lmbad + + cmpb $16, %al + jnc lmbad + +lmhx1: shlw $4, %bx + orb %al, %bl + jmp lmhex + +lmuse1: movw %bx, %ax + jmp lmuse + +mnusel: lodsb # Menu selection + xorb %ah, %ah + subb $0x30, %al + jc lmbad + + cmpb $10, %al + jc lmuse + + cmpb $0x61-0x30, %al + jc lmbad + + subb $0x61-0x30-10, %al + cmpb $36, %al + jnc lmbad + +lmuse: call mode_set + jc lmdef + +lmbad: leaw unknt, %si + call prtstr + jmp lm2 +lmscan: cmpb $0, adapter # Scanning only on EGA/VGA + jz lmbad + + movw $0, mt_end # Scanning of modes is + movb $1, scanning # done as new autodetection. + call mode_table + jmp listm0 +lmdef: ret + +# Additional parts of mode_set... (relative jumps, you know) +setv7: # Video7 extended modes + DO_STORE + subb $VIDEO_FIRST_V7>>8, %bh + movw $0x6f05, %ax + int $0x10 + stc + ret + +_setrec: jmp setrec # Ugly... +_set_80x25: jmp set_80x25 + +# Aliases for backward compatibility. +setalias: + movw $VIDEO_80x25, %ax + incw %bx + jz mode_set + + movb $VIDEO_8POINT-VIDEO_FIRST_SPECIAL, %al + incw %bx + jnz setbad # Fall-through! + +# Setting of user mode (AX=mode ID) => CF=success +mode_set: + movw %ax, %fs:(0x01fa) # Store mode for use in acpi_wakeup.S + movw %ax, %bx + cmpb $0xff, %ah + jz setalias + + testb $VIDEO_RECALC>>8, %ah + jnz _setrec + + cmpb $VIDEO_FIRST_RESOLUTION>>8, %ah + jnc setres + + cmpb $VIDEO_FIRST_SPECIAL>>8, %ah + jz setspc + + cmpb $VIDEO_FIRST_V7>>8, %ah + jz setv7 + + cmpb $VIDEO_FIRST_VESA>>8, %ah + jnc check_vesa + + orb %ah, %ah + jz setmenu + + decb %ah + jz setbios + +setbad: clc + movb $0, do_restore # The screen needn't be restored + ret + +setvesa: + DO_STORE + subb $VIDEO_FIRST_VESA>>8, %bh + movw $0x4f02, %ax # VESA BIOS mode set call + int $0x10 + cmpw $0x004f, %ax # AL=4f if implemented + jnz setbad # AH=0 if OK + + stc + ret + +setbios: + DO_STORE + int $0x10 # Standard BIOS mode set call + pushw %bx + movb $0x0f, %ah # Check if really set + int $0x10 + popw %bx + cmpb %bl, %al + jnz setbad + + stc + ret + +setspc: xorb %bh, %bh # Set special mode + cmpb $VIDEO_LAST_SPECIAL-VIDEO_FIRST_SPECIAL, %bl + jnc setbad + + addw %bx, %bx + jmp *spec_inits(%bx) + +setmenu: + orb %al, %al # 80x25 is an exception + jz _set_80x25 + + pushw %bx # Set mode chosen from menu + call mode_table # Build the mode table + popw %ax + shlw $2, %ax + addw %ax, %si + cmpw %di, %si + jnc setbad + + movw (%si), %ax # Fetch mode ID +_m_s: jmp mode_set + +setres: pushw %bx # Set mode chosen by resolution + call mode_table + popw %bx + xchgb %bl, %bh +setr1: lodsw + cmpw $ASK_VGA, %ax # End of the list? + jz setbad + + lodsw + cmpw %bx, %ax + jnz setr1 + + movw -4(%si), %ax # Fetch mode ID + jmp _m_s + +check_vesa: + leaw modelist+1024, %di + subb $VIDEO_FIRST_VESA>>8, %bh + movw %bx, %cx # Get mode information structure + movw $0x4f01, %ax + int $0x10 + addb $VIDEO_FIRST_VESA>>8, %bh + cmpw $0x004f, %ax + jnz setbad + + movb (%di), %al # Check capabilities. + andb $0x19, %al + cmpb $0x09, %al + jz setvesa # This is a text mode + + movb (%di), %al # Check capabilities. + andb $0x99, %al + cmpb $0x99, %al + jnz _setbad # Doh! No linear frame buffer. + + subb $VIDEO_FIRST_VESA>>8, %bh + orw $0x4000, %bx # Use linear frame buffer + movw $0x4f02, %ax # VESA BIOS mode set call + int $0x10 + cmpw $0x004f, %ax # AL=4f if implemented + jnz _setbad # AH=0 if OK + + movb $1, graphic_mode # flag graphic mode + movb $0, do_restore # no screen restore + stc + ret + +_setbad: jmp setbad # Ugly... + +# Recalculate vertical display end registers -- this fixes various +# inconsistencies of extended modes on many adapters. Called when +# the VIDEO_RECALC flag is set in the mode ID. + +setrec: subb $VIDEO_RECALC>>8, %ah # Set the base mode + call mode_set + jnc rct3 + + movw %gs:(0x485), %ax # Font size in pixels + movb %gs:(0x484), %bl # Number of rows + incb %bl + mulb %bl # Number of visible + decw %ax # scan lines - 1 + movw $0x3d4, %dx + movw %ax, %bx + movb $0x12, %al # Lower 8 bits + movb %bl, %ah + outw %ax, %dx + movb $0x07, %al # Bits 8 and 9 in the overflow register + call inidx + xchgb %al, %ah + andb $0xbd, %ah + shrb %bh + jnc rct1 + orb $0x02, %ah +rct1: shrb %bh + jnc rct2 + orb $0x40, %ah +rct2: movb $0x07, %al + outw %ax, %dx + stc +rct3: ret + +# Table of routines for setting of the special modes. +spec_inits: + .word set_80x25 + .word set_8pixel + .word set_80x43 + .word set_80x28 + .word set_current + .word set_80x30 + .word set_80x34 + .word set_80x60 + .word set_gfx + +# Set the 80x25 mode. If already set, do nothing. +set_80x25: + movw $0x5019, force_size # Override possibly broken BIOS +use_80x25: +#ifdef CONFIG_VIDEO_400_HACK + movw $0x1202, %ax # Force 400 scan lines + movb $0x30, %bl + int $0x10 +#else + movb $0x0f, %ah # Get current mode ID + int $0x10 + cmpw $0x5007, %ax # Mode 7 (80x25 mono) is the only one available + jz st80 # on CGA/MDA/HGA and is also available on EGAM + + cmpw $0x5003, %ax # Unknown mode, force 80x25 color + jnz force3 + +st80: cmpb $0, adapter # CGA/MDA/HGA => mode 3/7 is always 80x25 + jz set80 + + movb %gs:(0x0484), %al # This is EGA+ -- beware of 80x50 etc. + orb %al, %al # Some buggy BIOS'es set 0 rows + jz set80 + + cmpb $24, %al # It's hopefully correct + jz set80 +#endif /* CONFIG_VIDEO_400_HACK */ +force3: DO_STORE + movw $0x0003, %ax # Forced set + int $0x10 +set80: stc + ret + +# Set the 80x50/80x43 8-pixel mode. Simple BIOS calls. +set_8pixel: + DO_STORE + call use_80x25 # The base is 80x25 +set_8pt: + movw $0x1112, %ax # Use 8x8 font + xorb %bl, %bl + int $0x10 + movw $0x1200, %ax # Use alternate print screen + movb $0x20, %bl + int $0x10 + movw $0x1201, %ax # Turn off cursor emulation + movb $0x34, %bl + int $0x10 + movb $0x01, %ah # Define cursor scan lines 6-7 + movw $0x0607, %cx + int $0x10 +set_current: + stc + ret + +# Set the 80x28 mode. This mode works on all VGA's, because it's a standard +# 80x25 mode with 14-point fonts instead of 16-point. +set_80x28: + DO_STORE + call use_80x25 # The base is 80x25 +set14: movw $0x1111, %ax # Use 9x14 font + xorb %bl, %bl + int $0x10 + movb $0x01, %ah # Define cursor scan lines 11-12 + movw $0x0b0c, %cx + int $0x10 + stc + ret + +# Set the 80x43 mode. This mode is works on all VGA's. +# It's a 350-scanline mode with 8-pixel font. +set_80x43: + DO_STORE + movw $0x1201, %ax # Set 350 scans + movb $0x30, %bl + int $0x10 + movw $0x0003, %ax # Reset video mode + int $0x10 + jmp set_8pt # Use 8-pixel font + +# Set the 80x30 mode (all VGA's). 480 scanlines, 16-pixel font. +set_80x30: + call use_80x25 # Start with real 80x25 + DO_STORE + movw $0x3cc, %dx # Get CRTC port + inb %dx, %al + movb $0xd4, %dl + rorb %al # Mono or color? + jc set48a + + movb $0xb4, %dl +set48a: movw $0x0c11, %ax # Vertical sync end (also unlocks CR0-7) + call outidx + movw $0x0b06, %ax # Vertical total + call outidx + movw $0x3e07, %ax # (Vertical) overflow + call outidx + movw $0xea10, %ax # Vertical sync start + call outidx + movw $0xdf12, %ax # Vertical display end + call outidx + movw $0xe715, %ax # Vertical blank start + call outidx + movw $0x0416, %ax # Vertical blank end + call outidx + pushw %dx + movb $0xcc, %dl # Misc output register (read) + inb %dx, %al + movb $0xc2, %dl # (write) + andb $0x0d, %al # Preserve clock select bits and color bit + orb $0xe2, %al # Set correct sync polarity + outb %al, %dx + popw %dx + movw $0x501e, force_size + stc # That's all. + ret + +# Set the 80x34 mode (all VGA's). 480 scans, 14-pixel font. +set_80x34: + call set_80x30 # Set 480 scans + call set14 # And 14-pt font + movw $0xdb12, %ax # VGA vertical display end + movw $0x5022, force_size +setvde: call outidx + stc + ret + +# Set the 80x60 mode (all VGA's). 480 scans, 8-pixel font. +set_80x60: + call set_80x30 # Set 480 scans + call set_8pt # And 8-pt font + movw $0xdf12, %ax # VGA vertical display end + movw $0x503c, force_size + jmp setvde + +# Special hack for ThinkPad graphics +set_gfx: +#ifdef CONFIG_VIDEO_GFX_HACK + movw $VIDEO_GFX_BIOS_AX, %ax + movw $VIDEO_GFX_BIOS_BX, %bx + int $0x10 + movw $VIDEO_GFX_DUMMY_RESOLUTION, force_size + stc +#endif + ret + +#ifdef CONFIG_VIDEO_RETAIN + +# Store screen contents to temporary buffer. +store_screen: + cmpb $0, do_restore # Already stored? + jnz stsr + + testb $CAN_USE_HEAP, loadflags # Have we space for storing? + jz stsr + + pushw %ax + pushw %bx + pushw force_size # Don't force specific size + movw $0, force_size + call mode_params # Obtain params of current mode + popw force_size + movb %fs:(PARAM_VIDEO_LINES), %ah + movb %fs:(PARAM_VIDEO_COLS), %al + movw %ax, %bx # BX=dimensions + mulb %ah + movw %ax, %cx # CX=number of characters + addw %ax, %ax # Calculate image size + addw $modelist+1024+4, %ax + cmpw heap_end_ptr, %ax + jnc sts1 # Unfortunately, out of memory + + movw %fs:(PARAM_CURSOR_POS), %ax # Store mode params + leaw modelist+1024, %di + stosw + movw %bx, %ax + stosw + pushw %ds # Store the screen + movw video_segment, %ds + xorw %si, %si + rep + movsw + popw %ds + incb do_restore # Screen will be restored later +sts1: popw %bx + popw %ax +stsr: ret + +# Restore screen contents from temporary buffer. +restore_screen: + cmpb $0, do_restore # Has the screen been stored? + jz res1 + + call mode_params # Get parameters of current mode + movb %fs:(PARAM_VIDEO_LINES), %cl + movb %fs:(PARAM_VIDEO_COLS), %ch + leaw modelist+1024, %si # Screen buffer + lodsw # Set cursor position + movw %ax, %dx + cmpb %cl, %dh + jc res2 + + movb %cl, %dh + decb %dh +res2: cmpb %ch, %dl + jc res3 + + movb %ch, %dl + decb %dl +res3: movb $0x02, %ah + movb $0x00, %bh + int $0x10 + lodsw # Display size + movb %ah, %dl # DL=number of lines + movb $0, %ah # BX=phys. length of orig. line + movw %ax, %bx + cmpb %cl, %dl # Too many? + jc res4 + + pushw %ax + movb %dl, %al + subb %cl, %al + mulb %bl + addw %ax, %si + addw %ax, %si + popw %ax + movb %cl, %dl +res4: cmpb %ch, %al # Too wide? + jc res5 + + movb %ch, %al # AX=width of src. line +res5: movb $0, %cl + xchgb %ch, %cl + movw %cx, %bp # BP=width of dest. line + pushw %es + movw video_segment, %es + xorw %di, %di # Move the data + addw %bx, %bx # Convert BX and BP to _bytes_ + addw %bp, %bp +res6: pushw %si + pushw %di + movw %ax, %cx + rep + movsw + popw %di + popw %si + addw %bp, %di + addw %bx, %si + decb %dl + jnz res6 + + popw %es # Done +res1: ret +#endif /* CONFIG_VIDEO_RETAIN */ + +# Write to indexed VGA register (AL=index, AH=data, DX=index reg. port) +outidx: outb %al, %dx + pushw %ax + movb %ah, %al + incw %dx + outb %al, %dx + decw %dx + popw %ax + ret + +# Build the table of video modes (stored after the setup.S code at the +# `modelist' label. Each video mode record looks like: +# .word MODE-ID (our special mode ID (see above)) +# .byte rows (number of rows) +# .byte columns (number of columns) +# Returns address of the end of the table in DI, the end is marked +# with a ASK_VGA ID. +mode_table: + movw mt_end, %di # Already filled? + orw %di, %di + jnz mtab1x + + leaw modelist, %di # Store standard modes: + movl $VIDEO_80x25 + 0x50190000, %eax # The 80x25 mode (ALL) + stosl + movb adapter, %al # CGA/MDA/HGA -- no more modes + orb %al, %al + jz mtabe + + decb %al + jnz mtabv + + movl $VIDEO_8POINT + 0x502b0000, %eax # The 80x43 EGA mode + stosl + jmp mtabe + +mtab1x: jmp mtab1 + +mtabv: leaw vga_modes, %si # All modes for std VGA + movw $vga_modes_end-vga_modes, %cx + rep # I'm unable to use movsw as I don't know how to store a half + movsb # of the expression above to cx without using explicit shr. + + cmpb $0, scanning # Mode scan requested? + jz mscan1 + + call mode_scan +mscan1: + +#ifdef CONFIG_VIDEO_LOCAL + call local_modes +#endif /* CONFIG_VIDEO_LOCAL */ + +#ifdef CONFIG_VIDEO_VESA + call vesa_modes # Detect VESA VGA modes +#endif /* CONFIG_VIDEO_VESA */ + +#ifdef CONFIG_VIDEO_SVGA + cmpb $0, scanning # Bypass when scanning + jnz mscan2 + + call svga_modes # Detect SVGA cards & modes +mscan2: +#endif /* CONFIG_VIDEO_SVGA */ + +mtabe: + +#ifdef CONFIG_VIDEO_COMPACT + leaw modelist, %si + movw %di, %dx + movw %si, %di +cmt1: cmpw %dx, %si # Scan all modes + jz cmt2 + + leaw modelist, %bx # Find in previous entries + movw 2(%si), %cx +cmt3: cmpw %bx, %si + jz cmt4 + + cmpw 2(%bx), %cx # Found => don't copy this entry + jz cmt5 + + addw $4, %bx + jmp cmt3 + +cmt4: movsl # Copy entry + jmp cmt1 + +cmt5: addw $4, %si # Skip entry + jmp cmt1 + +cmt2: +#endif /* CONFIG_VIDEO_COMPACT */ + + movw $ASK_VGA, (%di) # End marker + movw %di, mt_end +mtab1: leaw modelist, %si # SI=mode list, DI=list end +ret0: ret + +# Modes usable on all standard VGAs +vga_modes: + .word VIDEO_8POINT + .word 0x5032 # 80x50 + .word VIDEO_80x43 + .word 0x502b # 80x43 + .word VIDEO_80x28 + .word 0x501c # 80x28 + .word VIDEO_80x30 + .word 0x501e # 80x30 + .word VIDEO_80x34 + .word 0x5022 # 80x34 + .word VIDEO_80x60 + .word 0x503c # 80x60 +#ifdef CONFIG_VIDEO_GFX_HACK + .word VIDEO_GFX_HACK + .word VIDEO_GFX_DUMMY_RESOLUTION +#endif + +vga_modes_end: +# Detect VESA modes. + +#ifdef CONFIG_VIDEO_VESA +vesa_modes: + cmpb $2, adapter # VGA only + jnz ret0 + + movw %di, %bp # BP=original mode table end + addw $0x200, %di # Buffer space + movw $0x4f00, %ax # VESA Get card info call + int $0x10 + movw %bp, %di + cmpw $0x004f, %ax # Successful? + jnz ret0 + + cmpw $0x4556, 0x200(%di) + jnz ret0 + + cmpw $0x4153, 0x202(%di) + jnz ret0 + + movw $vesa_name, card_name # Set name to "VESA VGA" + pushw %gs + lgsw 0x20e(%di), %si # GS:SI=mode list + movw $128, %cx # Iteration limit +vesa1: +# gas version 2.9.1, using BFD version 2.9.1.0.23 buggers the next inst. +# XXX: lodsw %gs:(%si), %ax # Get next mode in the list + gs; lodsw + cmpw $0xffff, %ax # End of the table? + jz vesar + + cmpw $0x0080, %ax # Check validity of mode ID + jc vesa2 + + orb %ah, %ah # Valid IDs: 0x0000-0x007f/0x0100-0x07ff + jz vesan # Certain BIOSes report 0x80-0xff! + + cmpw $0x0800, %ax + jnc vesae + +vesa2: pushw %cx + movw %ax, %cx # Get mode information structure + movw $0x4f01, %ax + int $0x10 + movw %cx, %bx # BX=mode number + addb $VIDEO_FIRST_VESA>>8, %bh + popw %cx + cmpw $0x004f, %ax + jnz vesan # Don't report errors (buggy BIOSES) + + movb (%di), %al # Check capabilities. We require + andb $0x19, %al # a color text mode. + cmpb $0x09, %al + jnz vesan + + cmpw $0xb800, 8(%di) # Standard video memory address required + jnz vesan + + testb $2, (%di) # Mode characteristics supplied? + movw %bx, (%di) # Store mode number + jz vesa3 + + xorw %dx, %dx + movw 0x12(%di), %bx # Width + orb %bh, %bh + jnz vesan + + movb %bl, 0x3(%di) + movw 0x14(%di), %ax # Height + orb %ah, %ah + jnz vesan + + movb %al, 2(%di) + mulb %bl + cmpw $8193, %ax # Small enough for Linux console driver? + jnc vesan + + jmp vesaok + +vesa3: subw $0x8108, %bx # This mode has no detailed info specified, + jc vesan # so it must be a standard VESA mode. + + cmpw $5, %bx + jnc vesan + + movw vesa_text_mode_table(%bx), %ax + movw %ax, 2(%di) +vesaok: addw $4, %di # The mode is valid. Store it. +vesan: loop vesa1 # Next mode. Limit exceeded => error +vesae: leaw vesaer, %si + call prtstr + movw %bp, %di # Discard already found modes. +vesar: popw %gs + ret + +# Dimensions of standard VESA text modes +vesa_text_mode_table: + .byte 60, 80 # 0108 + .byte 25, 132 # 0109 + .byte 43, 132 # 010A + .byte 50, 132 # 010B + .byte 60, 132 # 010C +#endif /* CONFIG_VIDEO_VESA */ + +# Scan for video modes. A bit dirty, but should work. +mode_scan: + movw $0x0100, %cx # Start with mode 0 +scm1: movb $0, %ah # Test the mode + movb %cl, %al + int $0x10 + movb $0x0f, %ah + int $0x10 + cmpb %cl, %al + jnz scm2 # Mode not set + + movw $0x3c0, %dx # Test if it's a text mode + movb $0x10, %al # Mode bits + call inidx + andb $0x03, %al + jnz scm2 + + movb $0xce, %dl # Another set of mode bits + movb $0x06, %al + call inidx + shrb %al + jc scm2 + + movb $0xd4, %dl # Cursor location + movb $0x0f, %al + call inidx + orb %al, %al + jnz scm2 + + movw %cx, %ax # Ok, store the mode + stosw + movb %gs:(0x484), %al # Number of rows + incb %al + stosb + movw %gs:(0x44a), %ax # Number of columns + stosb +scm2: incb %cl + jns scm1 + + movw $0x0003, %ax # Return back to mode 3 + int $0x10 + ret + +tstidx: outw %ax, %dx # OUT DX,AX and inidx +inidx: outb %al, %dx # Read from indexed VGA register + incw %dx # AL=index, DX=index reg port -> AL=data + inb %dx, %al + decw %dx + ret + +# Try to detect type of SVGA card and supply (usually approximate) video +# mode table for it. + +#ifdef CONFIG_VIDEO_SVGA +svga_modes: + leaw svga_table, %si # Test all known SVGA adapters +dosvga: lodsw + movw %ax, %bp # Default mode table + orw %ax, %ax + jz didsv1 + + lodsw # Pointer to test routine + pushw %si + pushw %di + pushw %es + movw $0xc000, %bx + movw %bx, %es + call *%ax # Call test routine + popw %es + popw %di + popw %si + orw %bp, %bp + jz dosvga + + movw %bp, %si # Found, copy the modes + movb svga_prefix, %ah +cpsvga: lodsb + orb %al, %al + jz didsv + + stosw + movsw + jmp cpsvga + +didsv: movw %si, card_name # Store pointer to card name +didsv1: ret + +# Table of all known SVGA cards. For each card, we store a pointer to +# a table of video modes supported by the card and a pointer to a routine +# used for testing of presence of the card. The video mode table is always +# followed by the name of the card or the chipset. +svga_table: + .word ati_md, ati_test + .word oak_md, oak_test + .word paradise_md, paradise_test + .word realtek_md, realtek_test + .word s3_md, s3_test + .word chips_md, chips_test + .word video7_md, video7_test + .word cirrus5_md, cirrus5_test + .word cirrus6_md, cirrus6_test + .word cirrus1_md, cirrus1_test + .word ahead_md, ahead_test + .word everex_md, everex_test + .word genoa_md, genoa_test + .word trident_md, trident_test + .word tseng_md, tseng_test + .word 0 + +# Test routines and mode tables: + +# S3 - The test algorithm was taken from the SuperProbe package +# for XFree86 1.2.1. Report bugs to Christoph.Niemann@linux.org +s3_test: + movw $0x0f35, %cx # we store some constants in cl/ch + movw $0x03d4, %dx + movb $0x38, %al + call inidx + movb %al, %bh # store current CRT-register 0x38 + movw $0x0038, %ax + call outidx # disable writing to special regs + movb %cl, %al # check whether we can write special reg 0x35 + call inidx + movb %al, %bl # save the current value of CRT reg 0x35 + andb $0xf0, %al # clear bits 0-3 + movb %al, %ah + movb %cl, %al # and write it to CRT reg 0x35 + call outidx + call inidx # now read it back + andb %ch, %al # clear the upper 4 bits + jz s3_2 # the first test failed. But we have a + + movb %bl, %ah # second chance + movb %cl, %al + call outidx + jmp s3_1 # do the other tests + +s3_2: movw %cx, %ax # load ah with 0xf and al with 0x35 + orb %bl, %ah # set the upper 4 bits of ah with the orig value + call outidx # write ... + call inidx # ... and reread + andb %cl, %al # turn off the upper 4 bits + pushw %ax + movb %bl, %ah # restore old value in register 0x35 + movb %cl, %al + call outidx + popw %ax + cmpb %ch, %al # setting lower 4 bits was successful => bad + je no_s3 # writing is allowed => this is not an S3 + +s3_1: movw $0x4838, %ax # allow writing to special regs by putting + call outidx # magic number into CRT-register 0x38 + movb %cl, %al # check whether we can write special reg 0x35 + call inidx + movb %al, %bl + andb $0xf0, %al + movb %al, %ah + movb %cl, %al + call outidx + call inidx + andb %ch, %al + jnz no_s3 # no, we can't write => no S3 + + movw %cx, %ax + orb %bl, %ah + call outidx + call inidx + andb %ch, %al + pushw %ax + movb %bl, %ah # restore old value in register 0x35 + movb %cl, %al + call outidx + popw %ax + cmpb %ch, %al + jne no_s31 # writing not possible => no S3 + movb $0x30, %al + call inidx # now get the S3 id ... + leaw idS3, %di + movw $0x10, %cx + repne + scasb + je no_s31 + + movb %bh, %ah + movb $0x38, %al + jmp s3rest + +no_s3: movb $0x35, %al # restore CRT register 0x35 + movb %bl, %ah + call outidx +no_s31: xorw %bp, %bp # Detection failed +s3rest: movb %bh, %ah + movb $0x38, %al # restore old value of CRT register 0x38 + jmp outidx + +idS3: .byte 0x81, 0x82, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95 + .byte 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa8, 0xb0 + +s3_md: .byte 0x54, 0x2b, 0x84 + .byte 0x55, 0x19, 0x84 + .byte 0 + .ascii "S3" + .byte 0 + +# ATI cards. +ati_test: + leaw idati, %si + movw $0x31, %di + movw $0x09, %cx + repe + cmpsb + je atiok + + xorw %bp, %bp +atiok: ret + +idati: .ascii "761295520" + +ati_md: .byte 0x23, 0x19, 0x84 + .byte 0x33, 0x2c, 0x84 + .byte 0x22, 0x1e, 0x64 + .byte 0x21, 0x19, 0x64 + .byte 0x58, 0x21, 0x50 + .byte 0x5b, 0x1e, 0x50 + .byte 0 + .ascii "ATI" + .byte 0 + +# AHEAD +ahead_test: + movw $0x200f, %ax + movw $0x3ce, %dx + outw %ax, %dx + incw %dx + inb %dx, %al + cmpb $0x20, %al + je isahed + + cmpb $0x21, %al + je isahed + + xorw %bp, %bp +isahed: ret + +ahead_md: + .byte 0x22, 0x2c, 0x84 + .byte 0x23, 0x19, 0x84 + .byte 0x24, 0x1c, 0x84 + .byte 0x2f, 0x32, 0xa0 + .byte 0x32, 0x22, 0x50 + .byte 0x34, 0x42, 0x50 + .byte 0 + .ascii "Ahead" + .byte 0 + +# Chips & Tech. +chips_test: + movw $0x3c3, %dx + inb %dx, %al + orb $0x10, %al + outb %al, %dx + movw $0x104, %dx + inb %dx, %al + movb %al, %bl + movw $0x3c3, %dx + inb %dx, %al + andb $0xef, %al + outb %al, %dx + cmpb $0xa5, %bl + je cantok + + xorw %bp, %bp +cantok: ret + +chips_md: + .byte 0x60, 0x19, 0x84 + .byte 0x61, 0x32, 0x84 + .byte 0 + .ascii "Chips & Technologies" + .byte 0 + +# Cirrus Logic 5X0 +cirrus1_test: + movw $0x3d4, %dx + movb $0x0c, %al + outb %al, %dx + incw %dx + inb %dx, %al + movb %al, %bl + xorb %al, %al + outb %al, %dx + decw %dx + movb $0x1f, %al + outb %al, %dx + incw %dx + inb %dx, %al + movb %al, %bh + xorb %ah, %ah + shlb $4, %al + movw %ax, %cx + movb %bh, %al + shrb $4, %al + addw %ax, %cx + shlw $8, %cx + addw $6, %cx + movw %cx, %ax + movw $0x3c4, %dx + outw %ax, %dx + incw %dx + inb %dx, %al + andb %al, %al + jnz nocirr + + movb %bh, %al + outb %al, %dx + inb %dx, %al + cmpb $0x01, %al + je iscirr + +nocirr: xorw %bp, %bp +iscirr: movw $0x3d4, %dx + movb %bl, %al + xorb %ah, %ah + shlw $8, %ax + addw $0x0c, %ax + outw %ax, %dx + ret + +cirrus1_md: + .byte 0x1f, 0x19, 0x84 + .byte 0x20, 0x2c, 0x84 + .byte 0x22, 0x1e, 0x84 + .byte 0x31, 0x25, 0x64 + .byte 0 + .ascii "Cirrus Logic 5X0" + .byte 0 + +# Cirrus Logic 54XX +cirrus5_test: + movw $0x3c4, %dx + movb $6, %al + call inidx + movb %al, %bl # BL=backup + movw $6, %ax + call tstidx + cmpb $0x0f, %al + jne c5fail + + movw $0x1206, %ax + call tstidx + cmpb $0x12, %al + jne c5fail + + movb $0x1e, %al + call inidx + movb %al, %bh + movb %bh, %ah + andb $0xc0, %ah + movb $0x1e, %al + call tstidx + andb $0x3f, %al + jne c5xx + + movb $0x1e, %al + movb %bh, %ah + orb $0x3f, %ah + call tstidx + xorb $0x3f, %al + andb $0x3f, %al +c5xx: pushf + movb $0x1e, %al + movb %bh, %ah + outw %ax, %dx + popf + je c5done + +c5fail: xorw %bp, %bp +c5done: movb $6, %al + movb %bl, %ah + outw %ax, %dx + ret + +cirrus5_md: + .byte 0x14, 0x19, 0x84 + .byte 0x54, 0x2b, 0x84 + .byte 0 + .ascii "Cirrus Logic 54XX" + .byte 0 + +# Cirrus Logic 64XX -- no known extra modes, but must be identified, because +# it's misidentified by the Ahead test. +cirrus6_test: + movw $0x3ce, %dx + movb $0x0a, %al + call inidx + movb %al, %bl # BL=backup + movw $0xce0a, %ax + call tstidx + orb %al, %al + jne c2fail + + movw $0xec0a, %ax + call tstidx + cmpb $0x01, %al + jne c2fail + + movb $0xaa, %al + call inidx # 4X, 5X, 7X and 8X are valid 64XX chip ID's. + shrb $4, %al + subb $4, %al + jz c6done + + decb %al + jz c6done + + subb $2, %al + jz c6done + + decb %al + jz c6done + +c2fail: xorw %bp, %bp +c6done: movb $0x0a, %al + movb %bl, %ah + outw %ax, %dx + ret + +cirrus6_md: + .byte 0 + .ascii "Cirrus Logic 64XX" + .byte 0 + +# Everex / Trident +everex_test: + movw $0x7000, %ax + xorw %bx, %bx + int $0x10 + cmpb $0x70, %al + jne noevrx + + shrw $4, %dx + cmpw $0x678, %dx + je evtrid + + cmpw $0x236, %dx + jne evrxok + +evtrid: leaw trident_md, %bp +evrxok: ret + +noevrx: xorw %bp, %bp + ret + +everex_md: + .byte 0x03, 0x22, 0x50 + .byte 0x04, 0x3c, 0x50 + .byte 0x07, 0x2b, 0x64 + .byte 0x08, 0x4b, 0x64 + .byte 0x0a, 0x19, 0x84 + .byte 0x0b, 0x2c, 0x84 + .byte 0x16, 0x1e, 0x50 + .byte 0x18, 0x1b, 0x64 + .byte 0x21, 0x40, 0xa0 + .byte 0x40, 0x1e, 0x84 + .byte 0 + .ascii "Everex/Trident" + .byte 0 + +# Genoa. +genoa_test: + leaw idgenoa, %si # Check Genoa 'clues' + xorw %ax, %ax + movb %es:(0x37), %al + movw %ax, %di + movw $0x04, %cx + decw %si + decw %di +l1: incw %si + incw %di + movb (%si), %al + testb %al, %al + jz l2 + + cmpb %es:(%di), %al +l2: loope l1 + orw %cx, %cx + je isgen + + xorw %bp, %bp +isgen: ret + +idgenoa: .byte 0x77, 0x00, 0x99, 0x66 + +genoa_md: + .byte 0x58, 0x20, 0x50 + .byte 0x5a, 0x2a, 0x64 + .byte 0x60, 0x19, 0x84 + .byte 0x61, 0x1d, 0x84 + .byte 0x62, 0x20, 0x84 + .byte 0x63, 0x2c, 0x84 + .byte 0x64, 0x3c, 0x84 + .byte 0x6b, 0x4f, 0x64 + .byte 0x72, 0x3c, 0x50 + .byte 0x74, 0x42, 0x50 + .byte 0x78, 0x4b, 0x64 + .byte 0 + .ascii "Genoa" + .byte 0 + +# OAK +oak_test: + leaw idoakvga, %si + movw $0x08, %di + movw $0x08, %cx + repe + cmpsb + je isoak + + xorw %bp, %bp +isoak: ret + +idoakvga: .ascii "OAK VGA " + +oak_md: .byte 0x4e, 0x3c, 0x50 + .byte 0x4f, 0x3c, 0x84 + .byte 0x50, 0x19, 0x84 + .byte 0x51, 0x2b, 0x84 + .byte 0 + .ascii "OAK" + .byte 0 + +# WD Paradise. +paradise_test: + leaw idparadise, %si + movw $0x7d, %di + movw $0x04, %cx + repe + cmpsb + je ispara + + xorw %bp, %bp +ispara: ret + +idparadise: .ascii "VGA=" + +paradise_md: + .byte 0x41, 0x22, 0x50 + .byte 0x47, 0x1c, 0x84 + .byte 0x55, 0x19, 0x84 + .byte 0x54, 0x2c, 0x84 + .byte 0 + .ascii "Paradise" + .byte 0 + +# Trident. +trident_test: + movw $0x3c4, %dx + movb $0x0e, %al + outb %al, %dx + incw %dx + inb %dx, %al + xchgb %al, %ah + xorb %al, %al + outb %al, %dx + inb %dx, %al + xchgb %ah, %al + movb %al, %bl # Strange thing ... in the book this wasn't + andb $0x02, %bl # necessary but it worked on my card which + jz setb2 # is a trident. Without it the screen goes + # blurred ... + andb $0xfd, %al + jmp clrb2 + +setb2: orb $0x02, %al +clrb2: outb %al, %dx + andb $0x0f, %ah + cmpb $0x02, %ah + je istrid + + xorw %bp, %bp +istrid: ret + +trident_md: + .byte 0x50, 0x1e, 0x50 + .byte 0x51, 0x2b, 0x50 + .byte 0x52, 0x3c, 0x50 + .byte 0x57, 0x19, 0x84 + .byte 0x58, 0x1e, 0x84 + .byte 0x59, 0x2b, 0x84 + .byte 0x5a, 0x3c, 0x84 + .byte 0 + .ascii "Trident" + .byte 0 + +# Tseng. +tseng_test: + movw $0x3cd, %dx + inb %dx, %al # Could things be this simple ! :-) + movb %al, %bl + movb $0x55, %al + outb %al, %dx + inb %dx, %al + movb %al, %ah + movb %bl, %al + outb %al, %dx + cmpb $0x55, %ah + je istsen + +isnot: xorw %bp, %bp +istsen: ret + +tseng_md: + .byte 0x26, 0x3c, 0x50 + .byte 0x2a, 0x28, 0x64 + .byte 0x23, 0x19, 0x84 + .byte 0x24, 0x1c, 0x84 + .byte 0x22, 0x2c, 0x84 + .byte 0x21, 0x3c, 0x84 + .byte 0 + .ascii "Tseng" + .byte 0 + +# Video7. +video7_test: + movw $0x3cc, %dx + inb %dx, %al + movw $0x3b4, %dx + andb $0x01, %al + jz even7 + + movw $0x3d4, %dx +even7: movb $0x0c, %al + outb %al, %dx + incw %dx + inb %dx, %al + movb %al, %bl + movb $0x55, %al + outb %al, %dx + inb %dx, %al + decw %dx + movb $0x1f, %al + outb %al, %dx + incw %dx + inb %dx, %al + movb %al, %bh + decw %dx + movb $0x0c, %al + outb %al, %dx + incw %dx + movb %bl, %al + outb %al, %dx + movb $0x55, %al + xorb $0xea, %al + cmpb %bh, %al + jne isnot + + movb $VIDEO_FIRST_V7>>8, svga_prefix # Use special mode switching + ret + +video7_md: + .byte 0x40, 0x2b, 0x50 + .byte 0x43, 0x3c, 0x50 + .byte 0x44, 0x3c, 0x64 + .byte 0x41, 0x19, 0x84 + .byte 0x42, 0x2c, 0x84 + .byte 0x45, 0x1c, 0x84 + .byte 0 + .ascii "Video 7" + .byte 0 + +# Realtek VGA +realtek_test: + leaw idrtvga, %si + movw $0x45, %di + movw $0x0b, %cx + repe + cmpsb + je isrt + + xorw %bp, %bp +isrt: ret + +idrtvga: .ascii "REALTEK VGA" + +realtek_md: + .byte 0x1a, 0x3c, 0x50 + .byte 0x1b, 0x19, 0x84 + .byte 0x1c, 0x1e, 0x84 + .byte 0x1d, 0x2b, 0x84 + .byte 0x1e, 0x3c, 0x84 + .byte 0 + .ascii "REALTEK" + .byte 0 + +#endif /* CONFIG_VIDEO_SVGA */ + +# User-defined local mode table (VGA only) +#ifdef CONFIG_VIDEO_LOCAL +local_modes: + leaw local_mode_table, %si +locm1: lodsw + orw %ax, %ax + jz locm2 + + stosw + movsw + jmp locm1 + +locm2: ret + +# This is the table of local video modes which can be supplied manually +# by the user. Each entry consists of mode ID (word) and dimensions +# (byte for column count and another byte for row count). These modes +# are placed before all SVGA and VESA modes and override them if table +# compacting is enabled. The table must end with a zero word followed +# by NUL-terminated video adapter name. +local_mode_table: + .word 0x0100 # Example: 40x25 + .byte 25,40 + .word 0 + .ascii "Local" + .byte 0 +#endif /* CONFIG_VIDEO_LOCAL */ + +# Read a key and return the ASCII code in al, scan code in ah +getkey: xorb %ah, %ah + int $0x16 + ret + +# Read a key with a timeout of 30 seconds. +# The hardware clock is used to get the time. +getkt: call gettime + addb $30, %al # Wait 30 seconds + cmpb $60, %al + jl lminute + + subb $60, %al +lminute: + movb %al, %cl +again: movb $0x01, %ah + int $0x16 + jnz getkey # key pressed, so get it + + call gettime + cmpb %cl, %al + jne again + + movb $0x20, %al # timeout, return `space' + ret + +# Flush the keyboard buffer +flush: movb $0x01, %ah + int $0x16 + jz empty + + xorb %ah, %ah + int $0x16 + jmp flush + +empty: ret + +# Print hexadecimal number. +prthw: pushw %ax + movb %ah, %al + call prthb + popw %ax +prthb: pushw %ax + shrb $4, %al + call prthn + popw %ax + andb $0x0f, %al +prthn: cmpb $0x0a, %al + jc prth1 + + addb $0x07, %al +prth1: addb $0x30, %al + jmp prtchr + +# Print decimal number in al +prtdec: pushw %ax + pushw %cx + xorb %ah, %ah + movb $0x0a, %cl + idivb %cl + cmpb $0x09, %al + jbe lt100 + + call prtdec + jmp skip10 + +lt100: addb $0x30, %al + call prtchr +skip10: movb %ah, %al + addb $0x30, %al + call prtchr + popw %cx + popw %ax + ret + +store_edid: + pushw %es # just save all registers + pushw %ax + pushw %bx + pushw %cx + pushw %dx + pushw %di + + pushw %fs + popw %es + + movl $0x13131313, %eax # memset block with 0x13 + movw $32, %cx + movw $0x140, %di + cld + rep + stosl + + movw $0x4f15, %ax # do VBE/DDC + movw $0x01, %bx + movw $0x00, %cx + movw $0x01, %dx + movw $0x140, %di + int $0x10 + + popw %di # restore all registers + popw %dx + popw %cx + popw %bx + popw %ax + popw %es + ret + +# VIDEO_SELECT-only variables +mt_end: .word 0 # End of video mode table if built +edit_buf: .space 6 # Line editor buffer +card_name: .word 0 # Pointer to adapter name +scanning: .byte 0 # Performing mode scan +do_restore: .byte 0 # Screen contents altered during mode change +svga_prefix: .byte VIDEO_FIRST_BIOS>>8 # Default prefix for BIOS modes +graphic_mode: .byte 0 # Graphic mode with a linear frame buffer +dac_size: .byte 6 # DAC bit depth + +# Status messages +keymsg: .ascii "Press to see video modes available, " + .ascii " to continue or wait 30 secs" + .byte 0x0d, 0x0a, 0 + +listhdr: .byte 0x0d, 0x0a + .ascii "Mode: COLSxROWS:" + +crlft: .byte 0x0d, 0x0a, 0 + +prompt: .byte 0x0d, 0x0a + .asciz "Enter mode number or `scan': " + +unknt: .asciz "Unknown mode ID. Try again." + +badmdt: .ascii "You passed an undefined mode number." + .byte 0x0d, 0x0a, 0 + +vesaer: .ascii "Error: Scanning of VESA modes failed. Please " + .ascii "report to ." + .byte 0x0d, 0x0a, 0 + +old_name: .asciz "CGA/MDA/HGA" + +ega_name: .asciz "EGA" + +svga_name: .ascii " " + +vga_name: .asciz "VGA" + +vesa_name: .asciz "VESA" + +name_bann: .asciz "Video adapter: " +#endif /* CONFIG_VIDEO_SELECT */ + +# Other variables: +adapter: .byte 0 # Video adapter: 0=CGA/MDA/HGA,1=EGA,2=VGA +video_segment: .word 0xb800 # Video memory segment +force_size: .word 0 # Use this size instead of the one in BIOS vars + +# Setup signature -- must be last +setup_sig1: .word SIG1 +setup_sig2: .word SIG2 + +# After this point, there is some free space which is used by the video mode +# handling code to store the temporary mode table (not used by the kernel). + +modelist: + +.text +endtext: +.data +enddata: +.bss +endbss: + diff --git a/l4/pkg/bootstrap/server/src/ARCH-x86/xen.c b/l4/pkg/bootstrap/server/src/ARCH-x86/xen.c new file mode 100644 index 00000000..9aae2a49 --- /dev/null +++ b/l4/pkg/bootstrap/server/src/ARCH-x86/xen.c @@ -0,0 +1,21 @@ + +#include +#include +#include +#include + +asm(".section __xen_guest \n" + ".ascii \"GUEST_OS=DD-L4\" \n" + ".ascii \",GUEST_VER=0.1\" \n" + ".ascii \",XEN_VER=2.0\" \n" + ".ascii \",VIRT_BASE=0xf0000000\" \n" + ".ascii \",LOADER=generic\" \n" + ".ascii \",PT_MODE_WRITABLE\" \n" + ".previous \n"); + +int +putchar(int c) +{ + HYPERVISOR_console_io(CONSOLEIO_write, 1, (char *)&c); + return c; +} diff --git a/l4/pkg/bootstrap/server/src/Make.rules b/l4/pkg/bootstrap/server/src/Make.rules new file mode 100644 index 00000000..c6760f65 --- /dev/null +++ b/l4/pkg/bootstrap/server/src/Make.rules @@ -0,0 +1,437 @@ +# vim:set ft=make: +# +# User definable variables for bootstrap: +# - BOOTSTRAP_SEARCH_PATH +# - BOOTSTRAP_ELF_NAME +# - BOOTSTRAP_MODULES_LIST +# - BOOTSTRAP_DO_RAW_IMAGE +# - BOOTSTRAP_DO_UIMAGE +# - BOOTSTRAP_NO_STRIP if set no stripping of iamge +# - BOOTSTRAP_UIMAGE_COMPRESSION: set to none, gzip, or bzip2 +# - BOOTSTRAP_CMDLINE: compiled-in command line, only used if no cmdline +# given via multi-boot boot loader (e.g. on arm) + +DEFAULT_RELOC_arm := 0x01000000 +DEFAULT_RELOC_x86 := 0x002d0000 +DEFAULT_RELOC_amd64 := 0x002d0000 +DEFAULT_RELOC_ppc32 := 0x002d0000 +DEFAULT_RELOC_sparc := 0x00800000 +RELOC_PHYS := y +LDFLAGS = -Bstatic +EXTRA_GENERAL_D_DEP += .redo-change-tracker $(BID_RAM_BASE_DEP) \ + $(wildcard $(L4DIR)/conf/Makeconf.boot $(OBJ_BASE)/conf/Makeconf.boot) \ + $(SRC_DIR)/build.pl +INCLUDE_MAKE_RULES = $(SRC_DIR)/*/Make.rules +BOOTSTRAP_LD_dep := $(SRC_DIR)/ldscript.inc +#REQUIRES_LIBS = libbsd-lite + +include $(L4DIR)/mk/Makeconf +-include $(OBJ_DIR)/Makeconf.local +-include $(L4DIR)/conf/Makeconf.boot +-include $(OBJ_BASE)/conf/Makeconf.boot + +# Checks added Nov 2010: +ifneq ($(wildcard $(L4DIR)/conf/Makeconf.bootstrap),) +$(error $(L4DIR)/conf/Makeconf.bootstrap not used anymore. Please use $(L4DIR)/conf/Makeconf.boot now) +endif +ifneq ($(wildcard $(OBJ_BASE)/Makeconf.bootstrap),) +$(error $(OBJ_BASE)/Makeconf.bootstrap not used anymore. Please use $(OBJ_BASE)/conf/Makeconf.boot now) +endif + +BOOTSTRAP_SEARCH_PATH ?= . +BOOTSTRAP_MODULES_LIST ?= $(SRC_DIR)/modules.list +BOOTSTRAP_MODULE_PATH_BINLIB ?= $(OBJ_BASE)/bin/$(SYSTEM)/$(BUILD_ABI):$(OBJ_BASE)/lib/$(SYSTEM)/$(BUILD_ABI):$(OBJ_BASE)/lib/$(SYSTEM) +BOOTSTRAP_ELF_NAME ?= bootstrap.elf +MKIMAGE ?= mkimage +BOOTSTRAP_UIMAGE_COMPRESSION ?= none + +ifeq ($(BUILD_ARCH),$(filter $(BUILD_ARCH),arm ppc32 sparc)) + # ARM/PPC/SPARC always uses single image mode + # when no entry is given we build the useless auto-build target + ifeq ($(E)$(ENTRY),) + BOOTSTRAP_ELF_NAME := bootstrap.auto-build-useless.elf + endif + ENTRY := auto-build-entry +endif + + +PRIVATE_INCDIR = $(SRC_DIR) $(SRC_DIR)/ARCH-$(ARCH) + +TARGET := $(BOOTSTRAP_ELF_NAME) +TARGET_BIN = $(BOOTSTRAP_ELF_NAME) +MODE = lib + +SUPPORT_CC_arm-sa1000 := platform/sa1000.cc +SUPPORT_CC_arm-pxa := platform/pxa.cc +SUPPORT_CC_arm-integrator := platform/integrator.cc +SUPPORT_CC_arm-rv := platform/rv.cc +SUPPORT_CC_arm-rv_pbx := platform/rv.cc +SUPPORT_CC_arm-rv_vexpress := platform/rv.cc +SUPPORT_CC_arm-omap3evm := platform/omap.cc +SUPPORT_CC_arm-omap3_am33xx:= platform/omap.cc +SUPPORT_CC_arm-beagleboard := platform/omap.cc +SUPPORT_CC_arm-pandaboard := platform/omap.cc +SUPPORT_CC_arm-tegra2 := platform/tegra2.cc +SUPPORT_CC_arm-imx21 := platform/imx.cc +SUPPORT_CC_arm-imx35 := platform/imx.cc +SUPPORT_CC_arm-imx51 := platform/imx.cc +SUPPORT_CC_arm-om := platform/om.cc +SUPPORT_CC_arm-kirkwood := platform/kirkwood.cc +DEFAULT_RELOC_arm-imx21 := 0x00200000 # because of blob + +ifneq ($(DEFAULT_RELOC_arm-$(PLATFORM_TYPE)),) +DEFAULT_RELOC_arm := $(DEFAULT_RELOC_arm-$(PLATFORM_TYPE)) +endif + +SUPPORT_CC_ppc32-mpc5200 := platform/mpc5200.cc + +SUPPORT_CC_x86-pc := platform/x86_pc.cc + +SUPPORT_CC_amd64-pc := platform/x86_pc.cc + +SUPPORT_CC_sparc-leon3 := platform/leon3.cc + +SRC_C += exec.c module.c +SRC_CC += region.cc startup.cc init_kip_v2.cc init_kip_v4.cc \ + libc_support+.cc patch.cc koptions.cc + +SRC_CC_x86 += ARCH-x86/reboot.cc +SRC_CC_amd64 += ARCH-x86/reboot.cc +SRC_C_x86 += base_critical.c +SRC_C_amd64 += base_critical.c +SRC_CC_arm += ARCH-arm/reboot.cc +SRC_CC_ppc32 += ARCH-ppc32/init_kip_v2-arch.cc \ + ARCH-ppc32/reboot.cc +SRC_CC_sparc += ARCH-sparc/reboot.cc +SRC_CC += $(SUPPORT_CC_$(ARCH)-$(PLATFORM_TYPE)) +SRC_S += ARCH-$(ARCH)/crt0.S + +OPTS = -g -Os $(CARCHFLAGS_$(ARCH)) $(CARCHFLAGS_$(ARCH)_$(CPU)) \ + $(GCCNOFPU_$(ARCH)) +DEFINES += -DRAM_BASE=$(RAM_BASE) -DL4_MINIMAL_LIBC=1 +DEFINES += -DCMDLINE="\"$(BOOTSTRAP_CMDLINE)\"" +DEFINES += -DPLATFORM_TYPE=\"$(PLATFORM_TYPE)\" +DEFINES += -DPLATFORM_TYPE_$(PLATFORM_TYPE) + +MOD_ADDR = 0x02000000 + +CPPFLAGS += $(CPPFLAGS_$(ARCH)-$(PLATFORM_TYPE)) +CPPFLAGS += $(BID_PKG_CONFIG_CFLAGS) + +ifeq ($(filter clean cleanall,$(MAKECMDGOALS)),) +ifeq ($(SUPPORT_CC_$(ARCH)-$(PLATFORM_TYPE)),) + $(info ERROR: PLATFORM_TYPE=$(PLATFORM_TYPE) has no assigned platform support file) + $(info ERROR: A proper PLATFORM_TYPE must be set for a build) + $(error .) +endif +endif + +DRV_LIBS-ppc32 = -ldrivers_of +DRV_LIBS = -ldrivers_uart $(DRV_LIBS-$(ARCH)) +CRT0 = +LDSCRIPT = bootstrap.ld +LDNMAGIC = + +vpath bootstrap.ld.in $(SRC_DIR)/ARCH-$(ARCH) + +# can be overwritten by Makeconf.local +COMPRESS ?= 0 +LOADER_MBI ?= 0 +REALMODE_LOADING ?= 0 +RML ?= 0 + +ifneq ($(REALMODE_LOADING)$(RML),00) +REALMODE_LOADING := 1 +$(error Info: Default reloc needs to be 0x00100000) +# And if you have done so you probably need to relink sigma0 and/or moe +endif + +ifeq ($(ARCH),arm) +LOADER_MBI := 1 +CPPFLAGS += -DSINGLE_SECTION +endif + + +# convenience +ifneq ($(E),) +ENTRY := $(E) +endif + +ENTRY_FN := $(shell echo "$(ENTRY)" | tr '[ ]' '[_]' ) + + +ifneq ($(ENTRY),) + ifeq ($(filter clean cleanall,$(MAKECMDGOALS)),) + BUILD_MOD_CMD = ( SEARCHPATH="$(BOOTSTRAP_SEARCH_PATH):$(BOOTSTRAP_MODULE_PATH_BINLIB)" \ + CROSS_COMPILE=$(SYSTEM_TARGET) \ + OPT_ARCH=$(ARCH) OPT_COMPRESS=$(COMPRESS) L4DIR=$(L4DIR) \ + $(SRC_DIR)/build.pl $(1) $(BOOTSTRAP_MODULES_LIST) "$(ENTRY)" || \ + (echo "processing-of-module-list-failed"; exit 1)) + endif +endif + + +# we need to re-do if some things change +.redo-change-tracker: FORCE + $(VERBOSE)echo "$(ENTRY) '$(COMPRESS)' '$(BOOTSTRAP_CMDLINE)' '$(BOOTSTRAP_SEARCH_PATH):$(BOOTSTRAP_MODULE_PATH_BINLIB)' '$(RAM_SIZE_MB)' '$(PLATFORM_TYPE)' '$(LOADER_MBI)'" > $@.tmp + $(if $(BUILD_MOD_CMD),$(VERBOSE)$(call BUILD_MOD_CMD,dump) >> $@.tmp) + $(VERBOSE)if test ! -r "$@" || ! cmp -s $@ $@.tmp; then \ + mv $@.tmp $@; \ + else \ + rm $@.tmp; \ + fi + +ifneq ($(ENTRY),) + +INSTALL_TARGET = $(BOOTSTRAP_ELF_NAME) bootstrap_$(ENTRY_FN) bootstrap_$(ENTRY_FN).elf +ifeq ($(ARCH),amd64) +INSTALL_TARGET += bootstrap32.elf +BOOTSTRAP_LINK_SOURCE = bootstrap32.elf +else +BOOTSTRAP_LINK_SOURCE = $(BOOTSTRAP_ELF_NAME) +endif + +bootstrap_$(ENTRY_FN): $(BOOTSTRAP_LINK_SOURCE) + $(VERBOSE)$(LN) -f $< $@ + +bootstrap_$(ENTRY_FN).elf: $(BOOTSTRAP_LINK_SOURCE) + $(VERBOSE)$(LN) -f $< $@ + +bootstrap_$(ENTRY_FN).raw: bootstrap.raw + $(VERBOSE)$(LN) -f $< $@ + +bootstrap_$(ENTRY_FN).uimage: bootstrap.uimage + $(VERBOSE)$(LN) -f $< $@ + + ifeq ($(ARCH),$(filter $(ARCH),arm ppc32)) + BID_POST_PROG_LINK_MSG_$(BOOTSTRAP_ELF_NAME) = echo -e " ==> Post-processing $@" + BID_POST_PROG_LINK_$(BOOTSTRAP_ELF_NAME) = \ + $(VERBOSE)LANG=C $(NM) -C $@ | \ + LANG=C $(GREP) -q "V vtable for Platform_base" || \ + { echo -e "\nERROR: Missing at least one platform instantiation.\n"; \ + exit 1; } ; $(if $(BOOTSTRAP_NO_STRIP),,$(STRIP) $@) + + ifneq ($(BOOTSTRAP_DO_RAW_IMAGE)$(BOOTSTRAP_DO_UIMAGE),) + BOOTSTRAP_RAW := bootstrap.raw + INSTALL_TARGET += bootstrap.raw bootstrap_$(ENTRY_FN).raw + ifneq ($(BOOTSTRAP_DO_UIMAGE),) + ifneq ($(shell command -v $(MKIMAGE)),) + BOOTSTRAP_UIMAGE := bootstrap.uimage + INSTALL_TARGET += bootstrap.uimage bootstrap_$(ENTRY_FN).uimage + else + $(error mkimage($(MKIMAGE)) host tool missing, cannot build bootstrap.uimage) + endif + endif + endif + endif + +all:: $(addprefix $(IMAGES_DIR)/,$(INSTALL_TARGET)) + $(VERBOSE)echo " Image size(s) in bytes:" + $(VERBOSE)for f in $(filter bootstrap_$(ENTRY_FN).elf bootstrap.raw bootstrap.uimage, $(INSTALL_TARGET)); do \ + find . -name $$f -printf " %30f: %s\n"; \ + done + $(if $(LDFLAGS_bootstrap.elf),$(VERBOSE)echo " Start address: $(patsubst --defsym=__executable_start=%,%,$(LDFLAGS_bootstrap.elf))") + $(VERBOSE)echo " --> Build-Nr: $$(cat .build_nr)" + +# install images into easy to reach directory in build dir +$(IMAGES_DIR)/%: % $(IMAGES_DIR)/Makefile + $(VERBOSE)if [ "$(ENTRY)" != "auto-build-entry" ]; then \ + echo " ==> Installing $< in image directory"; \ + $(LN) -sf $(PWD)/$< $(dir $@); \ + fi + +$(IMAGES_DIR)/Makefile: $(SRC_DIR)/Make.rules + @echo " ==> Preparing image directory" + $(VERBOSE)install -d $(dir $@) + $(VERBOSE)$(ECHO) "# Automatically generated by bootstrap" > $@ + $(VERBOSE)$(ECHO) "\$$(if \$$(MAKECMDGOALS),%,a):" >> $@ + $(VERBOSE)$(ECHO) " \$$(MAKE) -C .. image \$$(if \$$(MAKECMDGOALS),E=\"\$$@\")" >> $@ +else + INSTALL_TARGET = bootstrap +endif # ENTRY + +ifneq ($(REALMODE_LOADING),0) +LOADER_MBI = 1 +CPPFLAGS += -DREALMODE_LOADING -DSINGLE_SECTION +# don't install bootstrap_$(ENTRY_FN).elf +INSTALL_TARGET = bootstrap.load +endif + +ifneq ($(LOADER_MBI),0) +SRC_CC += loader_mbi.cc +MOD_ADDR = 0x00150000 +CPPFLAGS += -DLOADER_MBI +endif + +ifneq ($(COMPRESS),0) +SRC_C += uncompress.c gunzip.c +CPPFLAGS += -DCOMPRESS +else +CPPFLAGS += -DPLACE_MODULES_AT_MODADDR +endif + +ifneq ($(RAM_SIZE_MB),) +CPPFLAGS += -DRAM_SIZE_MB=$(RAM_SIZE_MB) +endif + +CXXFLAGS += -fno-rtti -fno-exceptions +CXXFLAGS += $(call checkcxx,-fno-threadsafe-statics) + +ifneq ($(ENTRY),) + ifeq ($(filter clean cleanall,$(MAKECMDGOALS)),) + +processing-of-module-list-failed: + @echo + @echo " Processing of $(BOOTSTRAP_MODULES_LIST) failed!" + @echo + @exit 1 + +mod.make.inc: $(GENERAL_D_LOC) $(shell $(call BUILD_MOD_CMD,list)) + @echo Building entry "$(ENTRY)". + $(VERBOSE)$(call BUILD_MOD_CMD,build) + + -include mod.make.inc + BOOTSTRAP_LD_dep += mod.make.inc + STARTUP_C_dep := mod.make.inc + OBJS_$(BOOTSTRAP_ELF_NAME) += $(MODULE_OBJECT_FILES) + endif + + CPPFLAGS += -DIMAGE_MODE +endif + +CPPFLAGS += -DMODADDR=$(MOD_ADDR) + +LIBS = +L4_LIBS = -static -nostdlib $(DRV_LIBS) -lcxx_base -lcxx_io +L4_LIBS += -luc_c_minimal $(GCCLIB) + +all:: $(BOOTSTRAP_RAW) + +# image for use with pxelinux +bootstrap.load: $(TARGET_BIN) bootsect.o.img setup.o.img + @$(GEN_MESSAGE) + $(VERBOSE)objcopy -O binary -R .note -R .comment -S $< $<.load.bin + $(VERBOSE)cat bootsect.o.img setup.o.img $<.load.bin > $@ + +bootsect.o.img: ARCH-x86/bootsect.S Makefile + @$(GEN_MESSAGE) + $(VERBOSE)$(CC) -traditional -nostdinc -nostdlib -c $< + $(VERBOSE)$(LD) -m elf_i386 -Ttext 0x0 -o $@ -s --oformat binary \ + bootsect.o + $(VERBOSE)chmod -x $@ + +setup.o.img: ARCH-x86/setup.S Makefile + @$(GEN_MESSAGE) + $(VERBOSE)$(CC) -traditional -nostdinc -nostdlib -DARCH_$(ARCH) -c $< + $(VERBOSE)$(LD) -m elf_i386 -Ttext 0x0 -o $@ -s --oformat binary \ + -e begtext setup.o + $(VERBOSE)dd if=/dev/zero bs=1 count=$$((3072 - `wc -c < setup.o.img`)) >> setup.o.img 2> /dev/null + $(VERBOSE)chmod -x $@ + +# raw version without ELF, primarily useful for ARM +$(BOOTSTRAP_RAW): $(TARGET_BIN) + @$(GEN_MESSAGE) + $(VERBOSE)cp $< $@.tmp + $(VERBOSE)$(OBJCOPY) -O binary $@.tmp $@ + $(VERBOSE)chmod -x $@ + $(VERBOSE)$(RM) $@.tmp + +%.gzip: % + gzip -c9 $^ > $@ + +%.bzip2: % + bzip2 -c9 $^ > $@ + +%.none: % + ln -sf $^ $@ + +MKIMAGE_ARCH = $(if $(filter ppc32,$(ARCH)),ppc,$(ARCH)) + +# u-boot image, based on raw-version +$(BOOTSTRAP_UIMAGE): $(BOOTSTRAP_RAW).$(BOOTSTRAP_UIMAGE_COMPRESSION) + @$(GEN_MESSAGE) + $(VERBOSE)$(MKIMAGE) -e $(call default_reloc,$(ARCH)) \ + -a $(call default_reloc,$(ARCH)) -A $(MKIMAGE_ARCH) \ + -C $(BOOTSTRAP_UIMAGE_COMPRESSION) \ + -n "L4 Image #$$(cat .build_nr)" \ + -d $^ $@ + +$(TARGET): $(LDSCRIPT) $(OBJS_$(TARGET)) + + +increment_build_nr = \ + $(shell if [ -e .build_nr ]; then \ + nr=$$(($$(cat .build_nr) + 1)); \ + else \ + nr=1; \ + fi; \ + echo $$nr > .build_nr; echo $$nr) + + +startup.o: $(STARTUP_C_dep) +startup.o: CPPFLAGS += -DBUILD_DATE="\"$(shell date)\"" -DBUILD_NR=\"$(call increment_build_nr)\" + +$(LDSCRIPT): $(LDSCRIPT).in $(GENERAL_D_LOC) $(BOOTSTRAP_LD_dep) + @$(GEN_MESSAGE) + $(VERBOSE)$(SYSTEM_TARGET)cpp -P $(CPPFLAGS) -DLINKADDR=$(strip $(call default_reloc,$(ARCH))) $< $@; + +clean:: + $(VERBOSE)$(RM) mod.make.inc mod*.bin mbi_modules.bin $(LDSCRIPT) + $(VERBOSE)$(RM) setup.o.img bootsect.o.img + $(VERBOSE)$(RM) mod*.bin + $(VERBOSE)$(RM) $(SRC32_C:.c=.o32) $(SRC32_S:.S=.o32) + $(VERBOSE)$(RM) .redo-change-tracker + +cleanall:: + $(VERBOSE)$(RM) bootstrap_* bootstrap.* + +ifeq ($(ARCH),amd64) + +vpath %.c $(SRC_DIR)/ARCH-amd64 +vpath %.S $(SRC_DIR)/ARCH-amd64 +vpath %.c $(SRC_DIR)/ARCH-amd64/boot32 +vpath %.S $(SRC_DIR)/ARCH-amd64/boot32 +vpath bootstrap.ld.in $(SRC_DIR)/ARCH-x86 + +SRC32_C = boot_cpu.c boot_kernel.c load_elf.c minilibc_support.c +SRC32_S = boot.S boot_idt.S +OBJ32 = $(SRC32_S:.S=.o32) $(SRC32_C:.c=.o32) +CC32 = $(filter-out -m64, $(CC)) -m32 +CFLAGS32 := $(filter-out -m64, $(CFLAGS)) -m32 + +$(OBJ_DIR)/ARCH-amd64/libc32/OBJ-$(ARCH)_$(CPU)/libc32.a: FORCE + $(VERBOSE)$(MAKE) O=$(OBJ_BASE) -C $(SRC_DIR)/ARCH-amd64/libc32 + +bootstrap32.elf: $(OBJ32) bootstrap32.bin $(OBJ_DIR)/ARCH-amd64/libc32/OBJ-$(ARCH)_$(CPU)/libc32.a + @$(LINK_MESSAGE) + $(VERBOSE)$(CC32) -o $@ -nostdlib -static \ + -Wl,-T,$(SRC_DIR)/ARCH-amd64/boot32/bootstrap32.ld,--gc-sections $^ -lgcc + $(VERBOSE)chmod 755 $@ + +bootstrap: bootstrap32.elf + $(VERBOSE)$(LN) -f $^ $@ + +bootstrap32.bin: $(BOOTSTRAP_ELF_NAME) + @$(GEN_MESSAGE) + $(VERBOSE)$(OBJCOPY) -S $< bootstrap64.bin + $(VERBOSE)chmod -x bootstrap64.bin + $(VERBOSE)$(OBJCOPY) -B i386 -I binary -O elf32-i386 bootstrap64.bin $@ + +%.o32: %.c + @$(COMP_MESSAGE) + $(VERBOSE)$(CC32) -o $@ -c $(DEPEND_FLAG) \ + $(CPPFLAGS) $(CFLAGS32) $(call absfilename,$<) + +%.o32: %.S + @$(COMP_MESSAGE) + $(VERBOSE)$(CC32) -o $@ -c $(DEPEND_FLAG) \ + $(CPPFLAGS) $(CFLAGS32) $(call absfilename,$<) + +clean cleanall:: + $(VERBOSE)PWD=$(call absfilename,$(SRC_DIR)/ARCH-amd64/libc32) \ + $(MAKE) -C $(SRC_DIR)/ARCH-amd64/libc32 $@ + +else +bootstrap: $(BOOTSTRAP_ELF_NAME) + $(VERBOSE)$(LN) -f $^ $@ +endif diff --git a/l4/pkg/bootstrap/server/src/Makefile b/l4/pkg/bootstrap/server/src/Makefile new file mode 100644 index 00000000..00ad289f --- /dev/null +++ b/l4/pkg/bootstrap/server/src/Makefile @@ -0,0 +1,6 @@ +PKGDIR ?= ../.. +L4DIR ?= $(PKGDIR)/../.. + +SYSTEMS = $(SYSTEMS_PLAIN) + +include $(L4DIR)/mk/prog.mk diff --git a/l4/pkg/bootstrap/server/src/README b/l4/pkg/bootstrap/server/src/README new file mode 100644 index 00000000..afef5a58 --- /dev/null +++ b/l4/pkg/bootstrap/server/src/README @@ -0,0 +1,70 @@ + +bootstrap supports different boot modi. + +For x86: + + 1) + boostrap is started by a multiboot compliant bootloader and modules are + attached as multiboot modules. GRUB example: + + kernel bootstrap arg1 args2 ... + module kernel + module sigma0 + module roottask + module task1 + ... + + 2) + bootstrap is started by a multiboot compliant bootloader but includes + all modules by itself. GRUB example: + + kernel bootstrap_hello args... + + For module specifications looks into modules.list + + 3) + bootstrap can boot from real-mode, esp. with pxelinux, i.e. it can be + booted via PXE. For that it also needs include all images. + This should also work with syslinux (e.g. from CDs/DVDs). (Note, grub + can also read is9660 filesystems.) + + 4) + bootstrap starts from protected mode but isn't started by a multiboot + compliant loader. Also needs to include all modules. + +For arm: + + Just the single image mode, i.e. all modules packed into bootstrap. + Anything else doesn't make any sense (currently). + + +Generating bootstrap in single-image-mode: + + Call make with E=entryname, e.g. + + $ make E=hello + + +Local customization: + + You can put a Makeconf.local file right into this directory + (bootstrap/server/src) where you can specify your own search paths etc. + Note that it is encouraged to have your local configuration in src/conf + rather than in this bootstrap directory. + + Makeconf.local could look like this: + + BOOTSTRAP_SEARCH_PATH_x86 := ../stuff:/home/joe/dev/l4/kernel/fiasco/build-ia32 + + KERN_ARM := build-arm + + ifneq ($(PXA),) + KERN_ARM := build-pxa + ARM_DRV_TYPE = pxa + endif + + KERN_PATH := /home/joe/dev/l4/kernel/fiasco/$(KERN_ARM) + BOOTSTRAP_SEARCH_PATH_arm = ../stuff:$(KERN_PATH):../../../../../bin/arm_sa + + BOOTSTRAP_SEARCH_PATH = $(BOOTSTRAP_SEARCH_PATH_$(ARCH)) + diff --git a/l4/pkg/bootstrap/server/src/base_critical.c b/l4/pkg/bootstrap/server/src/base_critical.c new file mode 100644 index 00000000..696b2aa3 --- /dev/null +++ b/l4/pkg/bootstrap/server/src/base_critical.c @@ -0,0 +1,34 @@ +/* + * (c) 2008-2009 Frank Mehnert + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ + +#include +#include "base_critical.h" + +static l4_umword_t flags; +static l4_umword_t entry_count; + +void +base_critical_enter(void) +{ + if (entry_count == 0) + { + l4util_flags_save(&flags); + l4util_cli(); + } + entry_count++; +} + +void +base_critical_leave(void) +{ + entry_count--; + if (entry_count == 0) + l4util_flags_restore(&flags); +} + diff --git a/l4/pkg/bootstrap/server/src/base_critical.h b/l4/pkg/bootstrap/server/src/base_critical.h new file mode 100644 index 00000000..301c1a46 --- /dev/null +++ b/l4/pkg/bootstrap/server/src/base_critical.h @@ -0,0 +1,22 @@ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Frank Mehnert + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ +#ifndef BASE_CRITICAL_H +#define BASE_CRITICAL_H + +#include + +EXTERN_C_BEGIN + +void base_critical_enter(void); +void base_critical_leave(void); + +EXTERN_C_END + +#endif diff --git a/l4/pkg/bootstrap/server/src/build.pl b/l4/pkg/bootstrap/server/src/build.pl new file mode 100755 index 00000000..b488c302 --- /dev/null +++ b/l4/pkg/bootstrap/server/src/build.pl @@ -0,0 +1,229 @@ +#! /usr/bin/perl -W +# +# (c) 2008-2009 Technische Universität Dresden +# This file is part of TUD:OS and distributed under the terms of the +# GNU General Public License 2. +# Please see the COPYING-GPL-2 file for details. +# +# Adam Lackorzynski +# + +use strict; + +BEGIN { unshift @INC, $ENV{L4DIR}.'/tool/lib' + if $ENV{L4DIR} && -d $ENV{L4DIR}.'/tool/lib/L4';} + +use Digest::MD5; +use L4::ModList; + + +my $cross_compile_prefix = $ENV{CROSS_COMPILE} || ''; +my $arch = $ENV{OPT_ARCH} || "x86"; + +my $module_path = $ENV{SEARCHPATH} || "."; +my $prog_objcopy = $ENV{OBJCOPY} || "${cross_compile_prefix}objcopy"; +my $prog_cc = $ENV{CC} || "${cross_compile_prefix}gcc"; +my $prog_ld = $ENV{LD} || "${cross_compile_prefix}ld"; +my $prog_cp = $ENV{PROG_CP} || "cp"; +my $prog_gzip = $ENV{PROG_GZIP} || "gzip"; +my $compress = $ENV{OPT_COMPRESS} || 0; +my $strip = $ENV{OPT_STRIP} || 1; +my $flags_cc = ""; +$flags_cc = "-m32" if $arch eq 'x86'; +$flags_cc = "-m64" if $arch eq 'amd64'; + +my $make_inc_file = $ENV{MAKE_INC_FILE} || "mod.make.inc"; + +my $modulesfile = $ARGV[1]; +my $entryname = $ARGV[2]; + +sub usage() +{ + print STDERR "$0 modulefile entry\n"; +} + +# Write a string to a file, overwriting it. +# 1: filename +# 2..n: Strings to write to the file +sub write_to_file +{ + my $file = shift; + + open(A, ">$file") || die "Cannot open $file!"; + while ($_ = shift) { + print A; + } + close A; +} + +sub first_word($) +{ + (split /\s+/, shift)[0] +} + +# build object files from the modules +sub build_obj($$$) +{ + my ($cmdline, $modname, $no_strip) = @_; + my $_file = first_word($cmdline); + + my $file = L4::ModList::search_file($_file, $module_path) + || die "Cannot find file $_file! Used search path: $module_path"; + + printf STDERR "Merging image %s to %s\n", $file, $modname; + # make sure that the file isn't already compressed + system("$prog_gzip -dc $file > $modname.ugz 2> /dev/null"); + $file = "$modname.ugz" if !$?; + system("$prog_objcopy -S $file $modname.obj 2> /dev/null") + if $strip && !$no_strip; + system("$prog_cp $file $modname.obj") + if $? || !$strip || $no_strip; + my $uncompressed_size = -s "$modname.obj"; + + my $c_unc = Digest::MD5->new; + open(M, "$modname.obj") || die "Failed to open $modname.obj: $!"; + $c_unc->addfile(*M); + close M; + + system("$prog_gzip -9f $modname.obj && mv $modname.obj.gz $modname.obj") + if $compress; + + my $c_compr = Digest::MD5->new; + open(M, "$modname.obj") || die "Failed to open $modname.obj: $!"; + $c_compr->addfile(*M); + close M; + + write_to_file("$modname.extra.s", + ".section .rodata.module_info \n", + ".align 4 \n", + "_bin_${modname}_name: \n", + ".ascii \"$_file\"; .byte 0 \n", + ".align 4 \n", + "_bin_${modname}_md5sum_compr: \n", + ".ascii \"".$c_compr->hexdigest."\"; .byte 0\n", + ".align 4 \n", + "_bin_${modname}_md5sum_uncompr: \n", + ".ascii \"".$c_unc->hexdigest."\"; .byte 0 \n", + ".align 4 \n", + ".section .module_info \n", + ".long _binary_${modname}_start \n", + ".long ", (-s "$modname.obj"), " \n", + ".long $uncompressed_size \n", + ".long _bin_${modname}_name \n", + ".long _bin_${modname}_md5sum_compr \n", + ".long _bin_${modname}_md5sum_uncompr \n", + ($arch eq 'x86' || $arch eq 'amd64' || $arch eq 'ppc32' + ? #".section .module_data, \"a\", \@progbits \n" # Not Xen + ".section .module_data, \"awx\", \@progbits \n" # Xen + : ".section .module_data, #alloc \n"), + ".p2align 12 \n", + ".global _binary_${modname}_start \n", + ".global _binary_${modname}_end \n", + "_binary_${modname}_start: \n", + ".incbin \"$modname.obj\" \n", + "_binary_${modname}_end: \n", + ); + system("$prog_cc $flags_cc -c -o $modname.bin $modname.extra.s"); + unlink("$modname.extra.s", "$modname.obj", "$modname.ugz"); +} + +sub build_mbi_modules_obj(@) +{ + my @mods = @_; + my $asm_string; + + # generate mbi module structures + $asm_string .= ".align 4 \n". + ".section .data.modules_mbi \n". + ".global _modules_mbi_start; \n". + "_modules_mbi_start: \n"; + + for (my $i = 0; $i < @mods; $i++) { + $asm_string .= ".long 0 \n". + ".long 0 \n". + ".long _modules_mbi_cmdline_$i \n". + ".long 0 \n"; + } + + $asm_string .= ".global _modules_mbi_end; \n". + "_modules_mbi_end: \n"; + + $asm_string .= ".section .data.cmdlines \n"; + + # generate cmdlines + for (my $i = 0; $i < @mods; $i++) { + $asm_string .= "_modules_mbi_cmdline_$i: \n". + ".ascii \"$mods[$i]->{cmdline}\"; .byte 0; \n"; + } + + write_to_file("mbi_modules.s", $asm_string); + system("$prog_cc $flags_cc -c -o mbi_modules.bin mbi_modules.s"); + unlink("mbi_modules.s"); + +} + +sub build_objects(@) +{ + my %entry = @_; + my @mods = @{$entry{mods}}; + my $objs = "mbi_modules.bin"; + + unlink($make_inc_file); + + # generate module-names + for (my $i = 0; $i < @mods; $i++) { + $mods[$i]->{modname} = sprintf "mod%02d", $i; + } + + build_mbi_modules_obj(@mods); + + for (my $i = 0; $i < @mods; $i++) { + build_obj($mods[$i]->{cmdline}, $mods[$i]->{modname}, + $mods[$i]->{type} =~ /.+-nostrip$/); + $objs .= " $mods[$i]->{modname}.bin"; + } + + my $make_inc_str = "MODULE_OBJECT_FILES += $objs\n"; + $make_inc_str .= "MOD_ADDR := $entry{modaddr}" + if defined $entry{modaddr}; + + write_to_file($make_inc_file, $make_inc_str); +} + + +sub list_files(@) +{ + my %entry = @_; + print join(' ', map { L4::ModList::search_file_or_die(first_word($_->{cmdline}), + $module_path) } + @{$entry{mods}}), "\n"; +} + +sub dump_entry(@) +{ + my %entry = @_; + print join(' ', map { $_->{cmdline} } @{$entry{mods}}), "\n"; +} + +# ------------------------------------------------------------------------ + +if (!$ARGV[2]) { + print STDERR "Error: Invalid usage!\n"; + usage(); + exit 1; +} + +my %entry = L4::ModList::get_module_entry($modulesfile, $entryname); + +if ($ARGV[0] eq 'build') + { + build_objects(%entry); + } +elsif ($ARGV[0] eq 'list') + { + list_files(%entry); + } +elsif ($ARGV[0] eq 'dump') + { + dump_entry(%entry); + } diff --git a/l4/pkg/bootstrap/server/src/exec.c b/l4/pkg/bootstrap/server/src/exec.c new file mode 100644 index 00000000..2ca7a926 --- /dev/null +++ b/l4/pkg/bootstrap/server/src/exec.c @@ -0,0 +1,66 @@ +/** + * \file bootstrap/server/src/exec.c + * \brief ELF loader + * + * \date 2004 + * \author Frank Mehnert , + * Torsten Frenzel */ + +/* + * (c) 2005-2009 Author(s) + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ + +#include +#include +#include +#include + +#include + +#include "exec.h" + +int +exec_load_elf(exec_handler_func_t *handler, + void *handle, const char **error_msg, l4_addr_t *entry) +{ + exec_task_t *t = handle; + ElfW(Ehdr) *x = t->mod_start; + ElfW(Phdr) *phdr, *ph; + int i; + + /* Read the ELF header. */ + + if (!l4util_elf_check_magic(x)) + return *error_msg="no ELF executable", -1; + + /* Make sure the file is of the right architecture. */ + if (!l4util_elf_check_arch(x)) + return *error_msg="wrong ELF architecture", -1; + + *entry = (l4_addr_t) x->e_entry; + + phdr = l4util_elf_phdr(x); + + for (i = 0; i < x->e_phnum; i++) + { + ph = (ElfW(Phdr)*)((l4_addr_t)phdr + i * x->e_phentsize); + if (ph->p_type == PT_LOAD) + { + exec_sectype_t type = EXEC_SECTYPE_ALLOC | + EXEC_SECTYPE_LOAD; + if (ph->p_flags & PF_R) type |= EXEC_SECTYPE_READ; + if (ph->p_flags & PF_W) type |= EXEC_SECTYPE_WRITE; + if (ph->p_flags & PF_X) type |= EXEC_SECTYPE_EXECUTE; + (*handler)(handle, + ph->p_offset, ph->p_filesz, + ph->p_paddr, ph->p_vaddr, ph->p_memsz, type); + } + } + + return *error_msg="", 0; +} diff --git a/l4/pkg/bootstrap/server/src/exec.h b/l4/pkg/bootstrap/server/src/exec.h new file mode 100644 index 00000000..5d7bdd0e --- /dev/null +++ b/l4/pkg/bootstrap/server/src/exec.h @@ -0,0 +1,50 @@ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg , + * Frank Mehnert + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ +#ifndef EXEC_H +#define EXEC_H + +#include "types.h" +#include +#include + +typedef int exec_sectype_t; + +#define EXEC_SECTYPE_READ ((exec_sectype_t)0x000001) +#define EXEC_SECTYPE_WRITE ((exec_sectype_t)0x000002) +#define EXEC_SECTYPE_EXECUTE ((exec_sectype_t)0x000004) +#define EXEC_SECTYPE_ALLOC ((exec_sectype_t)0x000100) +#define EXEC_SECTYPE_LOAD ((exec_sectype_t)0x000200) + + +typedef struct +{ + void *mod_start; + l4util_mb_mod_t *mod; + unsigned type; + l4_addr_t begin; /* program begin */ + l4_addr_t end; /* program end */ +} exec_task_t; + + +typedef int exec_handler_func_t(void *handle, + l4_addr_t file_ofs, l4_size_t file_size, + l4_addr_t mem_addr, l4_addr_t v_addr, + l4_size_t mem_size, + exec_sectype_t section_type); + +EXTERN_C_BEGIN + +int exec_load_elf(exec_handler_func_t *handler_exec, + void *handle, const char **error_msg, l4_addr_t *entry); + +EXTERN_C_END + +#endif diff --git a/l4/pkg/bootstrap/server/src/gunzip.c b/l4/pkg/bootstrap/server/src/gunzip.c new file mode 100644 index 00000000..9c15df56 --- /dev/null +++ b/l4/pkg/bootstrap/server/src/gunzip.c @@ -0,0 +1,1262 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 1999 Free Software Foundation, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* + * Most of this file was originally the source file "inflate.c", written + * by Mark Adler. It has been very heavily modified. In particular, the + * original would run through the whole file at once, and this version can + * be stopped and restarted on any boundary during the decompression process. + * + * The license and header comments that file are included here. + */ + +/* inflate.c -- Not copyrighted 1992 by Mark Adler + version c10p1, 10 January 1993 */ + +/* You can do whatever you like with this source file, though I would + prefer that if you modify it and redistribute it that you include + comments to that effect with your name and the date. Thank you. + */ + +/* + Inflate deflated (PKZIP's method 8 compressed) data. The compression + method searches for as much of the current string of bytes (up to a + length of 258) in the previous 32K bytes. If it doesn't find any + matches (of at least length 3), it codes the next byte. Otherwise, it + codes the length of the matched string and its distance backwards from + the current position. There is a single Huffman code that codes both + single bytes (called "literals") and match lengths. A second Huffman + code codes the distance information, which follows a length code. Each + length or distance code actually represents a base value and a number + of "extra" (sometimes zero) bits to get to add to the base value. At + the end of each deflated block is a special end-of-block (EOB) literal/ + length code. The decoding process is basically: get a literal/length + code; if EOB then done; if a literal, emit the decoded byte; if a + length then get the distance and emit the referred-to bytes from the + sliding window of previously emitted data. + + There are (currently) three kinds of inflate blocks: stored, fixed, and + dynamic. The compressor deals with some chunk of data at a time, and + decides which method to use on a chunk-by-chunk basis. A chunk might + typically be 32K or 64K. If the chunk is uncompressible, then the + "stored" method is used. In this case, the bytes are simply stored as + is, eight bits per byte, with none of the above coding. The bytes are + preceded by a count, since there is no longer an EOB code. + + If the data is compressible, then either the fixed or dynamic methods + are used. In the dynamic method, the compressed data is preceded by + an encoding of the literal/length and distance Huffman codes that are + to be used to decode this block. The representation is itself Huffman + coded, and so is preceded by a description of that code. These code + descriptions take up a little space, and so for small blocks, there is + a predefined set of codes, called the fixed codes. The fixed method is + used if the block codes up smaller that way (usually for quite small + chunks), otherwise the dynamic method is used. In the latter case, the + codes are customized to the probabilities in the current block, and so + can code it much better than the pre-determined fixed codes. + + The Huffman codes themselves are decoded using a mutli-level table + lookup, in order to maximize the speed of decoding plus the speed of + building the decoding tables. See the comments below that precede the + lbits and dbits tuning parameters. + */ + + +/* + Notes beyond the 1.93a appnote.txt: + + 1. Distance pointers never point before the beginning of the output + stream. + 2. Distance pointers can point back across blocks, up to 32k away. + 3. There is an implied maximum of 7 bits for the bit length table and + 15 bits for the actual data. + 4. If only one code exists, then it is encoded using one bit. (Zero + would be more efficient, but perhaps a little confusing.) If two + codes exist, they are coded using one bit each (0 and 1). + 5. There is no way of sending zero distance codes--a dummy must be + sent if there are none. (History: a pre 2.0 version of PKZIP would + store blocks with no distance codes, but this was discovered to be + too harsh a criterion.) Valid only for 1.93a. 2.04c does allow + zero distance codes, which is sent as one code of zero bits in + length. + 6. There are up to 286 literal/length codes. Code 256 represents the + end-of-block. Note however that the static length tree defines + 288 codes just to fill out the Huffman codes. Codes 286 and 287 + cannot be used though, since there is no length base or extra bits + defined for them. Similarly, there are up to 30 distance codes. + However, static trees define 32 codes (all 5 bits) to fill out the + Huffman codes, but the last two had better not show up in the data. + 7. Unzip can check dynamic Huffman blocks for complete code sets. + The exception is that a single code would not be complete (see #4). + 8. The five bits following the block type is really the number of + literal codes sent minus 257. + 9. Length codes 8,16,16 are interpreted as 13 length codes of 8 bits + (1+6+6). Therefore, to output three times the length, you output + three codes (1+1+1), whereas to output four times the same length, + you only need two codes (1+3). Hmm. + 10. In the tree reconstruction algorithm, Code = Code + Increment + only if BitLength(i) is not zero. (Pretty obvious.) + 11. Correction: 4 Bits: # of Bit Length codes - 4 (4 - 19) + 12. Note: length code 284 can represent 227-258, but length code 285 + really is 258. The last length deserves its own, short code + since it gets used a lot in very redundant files. The length + 258 is special since 258 - 3 (the min match length) is 255. + 13. The literal/length and distance code bit lengths are read as a + single stream of lengths. It is possible (and advantageous) for + a repeat code (16, 17, or 18) to go across the boundary between + the two sets of lengths. + */ + +#ifndef NO_DECOMPRESSION + +#include +#include +#include + +#include "gunzip.h" + +unsigned int filepos; +unsigned int filemax; +unsigned int fsmax; /* max size of fs/readable media */ + +grub_error_t errnum; + +/* whether to show decompression progress or not */ +enum { do_show_progress = 1 }; + +/* so we can disable decompression */ +int no_decompression = 0; + +/* used to tell if "read" should be redirected to "gunzip_read" */ +unsigned int compressed_file; + +/* internal variables only */ +static unsigned int gzip_data_offset; +static int gzip_filepos; +static int gzip_filemax; +static int gzip_fsmax; +static int saved_filepos; +static unsigned long gzip_crc; + +/* internal extra variables for use of inflate code */ +static int block_type; +static unsigned int block_len; +static int last_block; +static int code_state; + + +/* Function prototypes */ +static void initialize_tables (void); + +static void show_progress(int done, int len) +{ + int r = printf("%lld%%", ((unsigned long long)done * 100) / len); + while (r-- > 0) + putchar('\b'); + fflush(NULL); +} + +/* + * Linear allocator. + */ + +static unsigned long linalloc_topaddr; + +static void * +linalloc (int size) +{ + extern void *lin_alloc_buffer; + unsigned long newaddr = (linalloc_topaddr - size) & ~3; + if (newaddr < (unsigned long)lin_alloc_buffer) + panic("Out of memory while uncompressing"); + linalloc_topaddr = newaddr; + return (void *) linalloc_topaddr; +} + +static void +reset_linalloc (void) +{ + linalloc_topaddr = RAW_ADDR (UPPER_MEM_LINALLOC); +} + + +/* internal variable swap function */ +static void +gunzip_swap_values (void) +{ + register int itmp; + + /* swap filepos */ + itmp = filepos; + filepos = gzip_filepos; + gzip_filepos = itmp; + + /* swap filemax */ + itmp = filemax; + filemax = gzip_filemax; + gzip_filemax = itmp; + + /* swap fsmax */ + itmp = fsmax; + fsmax = gzip_fsmax; + gzip_fsmax = itmp; +} + + +/* internal function for eating variable-length header fields */ +static int +bad_field (int len) +{ + unsigned char ch = 1; + int not_retval = 1; + + do + { + if (len >= 0) + { + if (!(len--)) + break; + } + else + { + if (!ch) + break; + } + } + while ((not_retval = grub_read (&ch, 1)) == 1); + + return (!not_retval); +} + + +/* Little-Endian defines for the 2-byte magic number for gzip files */ +#define GZIP_HDR_LE 0x8B1F +#define OLD_GZIP_HDR_LE 0x9E1F + +/* Compression methods (see algorithm.doc) */ +#define STORED 0 +#define COMPRESSED 1 +#define PACKED 2 +#define LZHED 3 +/* methods 4 to 7 reserved */ +#define DEFLATED 8 +#define MAX_METHODS 9 + +/* gzip flag byte */ +#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */ +#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */ +#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ +#define ORIG_NAME 0x08 /* bit 3 set: original file name present */ +#define COMMENT 0x10 /* bit 4 set: file comment present */ +#define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */ +#define RESERVED 0xC0 /* bit 6,7: reserved */ + +#define UNSUPP_FLAGS (CONTINUATION|ENCRYPTED|RESERVED) + +/* inflate block codes */ +#define INFLATE_STORED 0 +#define INFLATE_FIXED 1 +#define INFLATE_DYNAMIC 2 + +typedef unsigned char uch; +typedef unsigned short ush; +typedef unsigned long ulg; + +/* + * Window Size + * + * This must be a power of two, and at least 32K for zip's deflate method + */ + +#define WSIZE 0x8000 + + +int +gunzip_test_header (void) +{ + unsigned char buf[10] __attribute__((aligned(4))); + + /* "compressed_file" is already reset to zero by this point */ + + /* + * This checks if the file is gzipped. If a problem occurs here + * (other than a real error with the disk) then we don't think it + * is a compressed file, and simply mark it as such. + */ + if (no_decompression + || grub_read (buf, 10) != 10 + || ((*((unsigned short *) buf) != GZIP_HDR_LE) + && (*((unsigned short *) buf) != OLD_GZIP_HDR_LE))) + { + filepos = 0; + return ! errnum; + } + + /* + * This does consistency checking on the header data. If a + * problem occurs from here on, then we have corrupt or otherwise + * bad data, and the error should be reported to the user. + */ + if (buf[2] != DEFLATED + || (buf[3] & UNSUPP_FLAGS) + || ((buf[3] & EXTRA_FIELD) + && (grub_read (buf, 2) != 2 + || bad_field (*((unsigned short *) buf)))) + || ((buf[3] & ORIG_NAME) && bad_field (-1)) + || ((buf[3] & COMMENT) && bad_field (-1))) + { + if (! errnum) + errnum = ERR_BAD_GZIP_HEADER; + + return 0; + } + + gzip_data_offset = filepos; + + filepos = filemax - 8; + + if (grub_read (buf, 8) != 8) + { + if (! errnum) + errnum = ERR_BAD_GZIP_HEADER; + + return 0; + } + + gzip_crc = *((unsigned long *) buf); + gzip_fsmax = gzip_filemax = *((unsigned long *) (buf + 4)); + + initialize_tables (); + + compressed_file = 1; + gunzip_swap_values (); + /* + * Now "gzip_*" values refer to the compressed data. + */ + + filepos = 0; + + return 1; +} + + +/* Huffman code lookup table entry--this entry is four bytes for machines + that have 16-bit pointers (e.g. PC's in the small or medium model). + Valid extra bits are 0..13. e == 15 is EOB (end of block), e == 16 + means that v is a literal, 16 < e < 32 means that v is a pointer to + the next table, which codes e - 16 bits, and lastly e == 99 indicates + an unused code. If a code with e == 99 is looked up, this implies an + error in the data. */ +struct huft +{ + uch e; /* number of extra bits or operation */ + uch b; /* number of bits in this code or subcode */ + union + { + ush n; /* literal, length base, or distance base */ + struct huft *t; /* pointer to next level of table */ + } + v; +}; + + +/* The inflate algorithm uses a sliding 32K byte window on the uncompressed + stream to find repeated byte strings. This is implemented here as a + circular buffer. The index is updated simply by incrementing and then + and'ing with 0x7fff (32K-1). */ +/* It is left to other modules to supply the 32K area. It is assumed + to be usable as if it were declared "uch slide[32768];" or as just + "uch *slide;" and then malloc'ed in the latter case. The definition + must be in unzip.h, included above. */ + + +/* sliding window in uncompressed data */ +static uch slide[WSIZE]; + +/* current position in slide */ +static unsigned wp; + + +/* Tables for deflate from PKZIP's appnote.txt. */ +static unsigned bitorder[] = +{ /* Order of the bit length code lengths */ + 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; +static ush cplens[] __attribute__((aligned(4))) = +{ /* Copy lengths for literal codes 257..285 */ + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; + /* note: see note #13 above about the 258 in this list. */ +static ush cplext[] __attribute__((aligned(4))) = +{ /* Extra bits for literal codes 257..285 */ + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, + 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 99, 99}; /* 99==invalid */ +static ush cpdist[] __attribute__((aligned(4))) = +{ /* Copy offsets for distance codes 0..29 */ + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, + 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, + 8193, 12289, 16385, 24577}; +static ush cpdext[] __attribute__((aligned(4))) = +{ /* Extra bits for distance codes */ + 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, + 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, + 12, 12, 13, 13}; + + +/* + Huffman code decoding is performed using a multi-level table lookup. + The fastest way to decode is to simply build a lookup table whose + size is determined by the longest code. However, the time it takes + to build this table can also be a factor if the data being decoded + is not very long. The most common codes are necessarily the + shortest codes, so those codes dominate the decoding time, and hence + the speed. The idea is you can have a shorter table that decodes the + shorter, more probable codes, and then point to subsidiary tables for + the longer codes. The time it costs to decode the longer codes is + then traded against the time it takes to make longer tables. + + This results of this trade are in the variables lbits and dbits + below. lbits is the number of bits the first level table for literal/ + length codes can decode in one step, and dbits is the same thing for + the distance codes. Subsequent tables are also less than or equal to + those sizes. These values may be adjusted either when all of the + codes are shorter than that, in which case the longest code length in + bits is used, or when the shortest code is *longer* than the requested + table size, in which case the length of the shortest code in bits is + used. + + There are two different values for the two tables, since they code a + different number of possibilities each. The literal/length table + codes 286 possible values, or in a flat code, a little over eight + bits. The distance table codes 30 possible values, or a little less + than five bits, flat. The optimum values for speed end up being + about one bit more than those, so lbits is 8+1 and dbits is 5+1. + The optimum values may differ though from machine to machine, and + possibly even between compilers. Your mileage may vary. + */ + + +static int lbits = 9; /* bits in base literal/length lookup table */ +static int dbits = 6; /* bits in base distance lookup table */ + + +/* If BMAX needs to be larger than 16, then h and x[] should be ulg. */ +#define BMAX 16 /* maximum bit length of any code (16 for explode) */ +#define N_MAX 288 /* maximum number of codes in any set */ + + +static unsigned hufts; /* track memory usage */ + + +/* Macros for inflate() bit peeking and grabbing. + The usage is: + + NEEDBITS(j) + x = b & mask_bits[j]; + DUMPBITS(j) + + where NEEDBITS makes sure that b has at least j bits in it, and + DUMPBITS removes the bits from b. The macros use the variable k + for the number of bits in b. Normally, b and k are register + variables for speed, and are initialized at the beginning of a + routine that uses these macros from a global bit buffer and count. + + If we assume that EOB will be the longest code, then we will never + ask for bits with NEEDBITS that are beyond the end of the stream. + So, NEEDBITS should not read any more bytes than are needed to + meet the request. Then no bytes need to be "returned" to the buffer + at the end of the last block. + + However, this assumption is not true for fixed blocks--the EOB code + is 7 bits, but the other literal/length codes can be 8 or 9 bits. + (The EOB code is shorter than other codes because fixed blocks are + generally short. So, while a block always has an EOB, many other + literal/length codes have a significantly lower probability of + showing up at all.) However, by making the first table have a + lookup of seven bits, the EOB code will be found in that first + lookup, and so will not require that too many bits be pulled from + the stream. + */ + +static ulg bb; /* bit buffer */ +static unsigned bk; /* bits in bit buffer */ + +static ush mask_bits[] = +{ + 0x0000, + 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff, + 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff +}; + +#define NEEDBITS(n) do {while(k<(n)){b|=((ulg)get_byte())<>=(n);k-=(n);} while (0) + +#define INBUFSIZ 0x2000 + +static unsigned char inbuf[INBUFSIZ]; +static int bufloc; + +static int +get_byte (void) +{ + if (filepos == gzip_data_offset || bufloc == INBUFSIZ) + { + bufloc = 0; + grub_read (inbuf, INBUFSIZ); + } + + return inbuf[bufloc++]; +} + +/* decompression global pointers */ +static struct huft *tl; /* literal/length code table */ +static struct huft *td; /* distance code table */ +static int bl; /* lookup bits for tl */ +static int bd; /* lookup bits for td */ + + +/* more function prototypes */ +static int huft_build (unsigned *, unsigned, unsigned, ush *, ush *, + struct huft **, int *); +static int inflate_codes_in_window (void); + + +/* Given a list of code lengths and a maximum table size, make a set of + tables to decode that set of codes. Return zero on success, one if + the given code set is incomplete (the tables are still built in this + case), two if the input is invalid (all zero length codes or an + oversubscribed set of lengths), and three if not enough memory. */ + +static int +huft_build (unsigned *b, /* code lengths in bits (all assumed <= BMAX) */ + unsigned n, /* number of codes (assumed <= N_MAX) */ + unsigned s, /* number of simple-valued codes (0..s-1) */ + ush * d, /* list of base values for non-simple codes */ + ush * e, /* list of extra bits for non-simple codes */ + struct huft **t, /* result: starting table */ + int *m) /* maximum lookup bits, returns actual */ +{ + unsigned a; /* counter for codes of length k */ + unsigned c[BMAX + 1]; /* bit length count table */ + unsigned f; /* i repeats in table every f entries */ + int g; /* maximum code length */ + int h; /* table level */ + register unsigned i; /* counter, current code */ + register unsigned j; /* counter */ + register int k; /* number of bits in current code */ + int l; /* bits per table (returned in m) */ + register unsigned *p; /* pointer into c[], b[], or v[] */ + register struct huft *q; /* points to current table */ + struct huft r; /* table entry for structure assignment */ + struct huft *u[BMAX]; /* table stack */ + unsigned v[N_MAX]; /* values in order of bit length */ + register int w; /* bits before this table == (l * h) */ + unsigned x[BMAX + 1]; /* bit offsets, then code stack */ + unsigned *xp; /* pointer into x */ + int y; /* number of dummy codes added */ + unsigned z; /* number of entries in current table */ + + /* Generate counts for each bit length */ + memset ((char *) c, 0, sizeof (c)); + p = b; + i = n; + do + { + c[*p]++; /* assume all entries <= BMAX */ + p++; /* Can't combine with above line (Solaris bug) */ + } + while (--i); + if (c[0] == n) /* null input--all zero length codes */ + { + *t = (struct huft *) NULL; + *m = 0; + return 0; + } + + /* Find minimum and maximum length, bound *m by those */ + l = *m; + for (j = 1; j <= BMAX; j++) + if (c[j]) + break; + k = j; /* minimum code length */ + if ((unsigned) l < j) + l = j; + for (i = BMAX; i; i--) + if (c[i]) + break; + g = i; /* maximum code length */ + if ((unsigned) l > i) + l = i; + *m = l; + + /* Adjust last length count to fill out codes, if needed */ + for (y = 1 << j; j < i; j++, y <<= 1) + if ((y -= c[j]) < 0) + return 2; /* bad input: more codes than bits */ + if ((y -= c[i]) < 0) + return 2; + c[i] += y; + + /* Generate starting offsets into the value table for each length */ + x[1] = j = 0; + p = c + 1; + xp = x + 2; + while (--i) + { /* note that i == g from above */ + *xp++ = (j += *p++); + } + + /* Make a table of values in order of bit lengths */ + p = b; + i = 0; + do + { + if ((j = *p++) != 0) + v[x[j]++] = i; + } + while (++i < n); + + /* Generate the Huffman codes and for each, make the table entries */ + x[0] = i = 0; /* first Huffman code is zero */ + p = v; /* grab values in bit order */ + h = -1; /* no tables yet--level -1 */ + w = -l; /* bits decoded == (l * h) */ + u[0] = (struct huft *) NULL; /* just to keep compilers happy */ + q = (struct huft *) NULL; /* ditto */ + z = 0; /* ditto */ + + /* go through the bit lengths (k already is bits in shortest code) */ + for (; k <= g; k++) + { + a = c[k]; + while (a--) + { + /* here i is the Huffman code of length k bits for value *p */ + /* make tables up to required level */ + while (k > w + l) + { + h++; + w += l; /* previous table always l bits */ + + /* compute minimum size table less than or equal to l bits */ + z = (z = g - w) > (unsigned) l ? l : z; /* upper limit on table size */ + if ((f = 1 << (j = k - w)) > a + 1) /* try a k-w bit table */ + { /* too few codes for k-w bit table */ + f -= a + 1; /* deduct codes from patterns left */ + xp = c + k; + while (++j < z) /* try smaller tables up to z bits */ + { + if ((f <<= 1) <= *++xp) + break; /* enough codes to use up j bits */ + f -= *xp; /* else deduct codes from patterns */ + } + } + z = 1 << j; /* table entries for j-bit table */ + + /* allocate and link in new table */ + q = (struct huft *) linalloc ((z + 1) * sizeof (struct huft)); + + hufts += z + 1; /* track memory usage */ + *t = q + 1; /* link to list for huft_free() */ + *(t = &(q->v.t)) = (struct huft *) NULL; + u[h] = ++q; /* table starts after link */ + + /* connect to last table, if there is one */ + if (h) + { + x[h] = i; /* save pattern for backing up */ + r.b = (uch) l; /* bits to dump before this table */ + r.e = (uch) (16 + j); /* bits in this table */ + r.v.t = q; /* pointer to this table */ + j = i >> (w - l); /* (get around Turbo C bug) */ + u[h - 1][j] = r; /* connect to last table */ + } + } + + /* set up table entry in r */ + r.b = (uch) (k - w); + if (p >= v + n) + r.e = 99; /* out of values--invalid code */ + else if (*p < s) + { + r.e = (uch) (*p < 256 ? 16 : 15); /* 256 is end-of-block code */ + r.v.n = (ush) (*p); /* simple code is just the value */ + p++; /* one compiler does not like *p++ */ + } + else + { + r.e = (uch) e[*p - s]; /* non-simple--look up in lists */ + r.v.n = d[*p++ - s]; + } + + /* fill code-like entries with r */ + f = 1 << (k - w); + for (j = i >> w; j < z; j += f) + q[j] = r; + + /* backwards increment the k-bit code i */ + for (j = 1 << (k - 1); i & j; j >>= 1) + i ^= j; + i ^= j; + + /* backup over finished tables */ + while ((i & ((1 << w) - 1)) != x[h]) + { + h--; /* don't need to update q */ + w -= l; + } + } + } + + /* Return true (1) if we were given an incomplete table */ + return y != 0 && g != 1; +} + + +/* + * inflate (decompress) the codes in a deflated (compressed) block. + * Return an error code or zero if it all goes ok. + */ + +static unsigned inflate_n, inflate_d; + +static int +inflate_codes_in_window (void) +{ + register unsigned e; /* table entry flag/number of extra bits */ + unsigned n, d; /* length and index for copy */ + unsigned w; /* current window position */ + struct huft *t; /* pointer to table entry */ + unsigned ml, md; /* masks for bl and bd bits */ + register ulg b; /* bit buffer */ + register unsigned k; /* number of bits in bit buffer */ + + /* make local copies of globals */ + d = inflate_d; + n = inflate_n; + b = bb; /* initialize bit buffer */ + k = bk; + w = wp; /* initialize window position */ + + /* inflate the coded data */ + ml = mask_bits[bl]; /* precompute masks for speed */ + md = mask_bits[bd]; + for (;;) /* do until end of block */ + { + if (!code_state) + { + NEEDBITS ((unsigned) bl); + if ((e = (t = tl + ((unsigned) b & ml))->e) > 16) + do + { + if (e == 99) + { + errnum = ERR_BAD_GZIP_DATA; + return 0; + } + DUMPBITS (t->b); + e -= 16; + NEEDBITS (e); + } + while ((e = (t = t->v.t + ((unsigned) b & mask_bits[e]))->e) > 16); + DUMPBITS (t->b); + + if (e == 16) /* then it's a literal */ + { + slide[w++] = (uch) t->v.n; + if (w == WSIZE) + break; + } + else + /* it's an EOB or a length */ + { + /* exit if end of block */ + if (e == 15) + { + block_len = 0; + break; + } + + /* get length of block to copy */ + NEEDBITS (e); + n = t->v.n + ((unsigned) b & mask_bits[e]); + DUMPBITS (e); + + /* decode distance of block to copy */ + NEEDBITS ((unsigned) bd); + if ((e = (t = td + ((unsigned) b & md))->e) > 16) + do + { + if (e == 99) + { + errnum = ERR_BAD_GZIP_DATA; + return 0; + } + DUMPBITS (t->b); + e -= 16; + NEEDBITS (e); + } + while ((e = (t = t->v.t + ((unsigned) b & mask_bits[e]))->e) + > 16); + DUMPBITS (t->b); + NEEDBITS (e); + d = w - t->v.n - ((unsigned) b & mask_bits[e]); + DUMPBITS (e); + code_state++; + } + } + + if (code_state) + { + /* do the copy */ + do + { + n -= (e = (e = WSIZE - ((d &= WSIZE - 1) > w ? d : w)) > n ? n + : e); + if (w - d >= e) + { + memmove (slide + w, slide + d, e); + w += e; + d += e; + } + else + /* purposefully use the overlap for extra copies here!! */ + { + while (e--) + slide[w++] = slide[d++]; + } + if (w == WSIZE) + break; + } + while (n); + + if (!n) + code_state--; + + /* did we break from the loop too soon? */ + if (w == WSIZE) + break; + } + } + + /* restore the globals from the locals */ + inflate_d = d; + inflate_n = n; + wp = w; /* restore global window pointer */ + bb = b; /* restore global bit buffer */ + bk = k; + + return !block_len; +} + + +/* get header for an inflated type 0 (stored) block. */ + +static void +init_stored_block (void) +{ + register ulg b; /* bit buffer */ + register unsigned k; /* number of bits in bit buffer */ + + /* make local copies of globals */ + b = bb; /* initialize bit buffer */ + k = bk; + + /* go to byte boundary */ + DUMPBITS (k & 7); + + /* get the length and its complement */ + NEEDBITS (16); + block_len = ((unsigned) b & 0xffff); + DUMPBITS (16); + NEEDBITS (16); + if (block_len != (unsigned) ((~b) & 0xffff)) + errnum = ERR_BAD_GZIP_DATA; + DUMPBITS (16); + + /* restore global variables */ + bb = b; + bk = k; +} + + +/* get header for an inflated type 1 (fixed Huffman codes) block. We should + either replace this with a custom decoder, or at least precompute the + Huffman tables. */ + +static void +init_fixed_block (void) +{ + int i; /* temporary variable */ + unsigned l[288]; /* length list for huft_build */ + + /* set up literal table */ + for (i = 0; i < 144; i++) + l[i] = 8; + for (; i < 256; i++) + l[i] = 9; + for (; i < 280; i++) + l[i] = 7; + for (; i < 288; i++) /* make a complete, but wrong code set */ + l[i] = 8; + bl = 7; + if ((i = huft_build (l, 288, 257, cplens, cplext, &tl, &bl)) != 0) + { + errnum = ERR_BAD_GZIP_DATA; + return; + } + + /* set up distance table */ + for (i = 0; i < 30; i++) /* make an incomplete code set */ + l[i] = 5; + bd = 5; + if ((i = huft_build (l, 30, 0, cpdist, cpdext, &td, &bd)) > 1) + { + errnum = ERR_BAD_GZIP_DATA; + return; + } + + /* indicate we're now working on a block */ + code_state = 0; + block_len++; +} + + +/* get header for an inflated type 2 (dynamic Huffman codes) block. */ + +static void +init_dynamic_block (void) +{ + int i; /* temporary variables */ + unsigned j; + unsigned l; /* last length */ + unsigned m; /* mask for bit lengths table */ + unsigned n; /* number of lengths to get */ + unsigned nb; /* number of bit length codes */ + unsigned nl; /* number of literal/length codes */ + unsigned nd; /* number of distance codes */ + unsigned ll[286 + 30]; /* literal/length and distance code lengths */ + register ulg b; /* bit buffer */ + register unsigned k; /* number of bits in bit buffer */ + + /* make local bit buffer */ + b = bb; + k = bk; + + /* read in table lengths */ + NEEDBITS (5); + nl = 257 + ((unsigned) b & 0x1f); /* number of literal/length codes */ + DUMPBITS (5); + NEEDBITS (5); + nd = 1 + ((unsigned) b & 0x1f); /* number of distance codes */ + DUMPBITS (5); + NEEDBITS (4); + nb = 4 + ((unsigned) b & 0xf); /* number of bit length codes */ + DUMPBITS (4); + if (nl > 286 || nd > 30) + { + errnum = ERR_BAD_GZIP_DATA; + return; + } + + /* read in bit-length-code lengths */ + for (j = 0; j < nb; j++) + { + NEEDBITS (3); + ll[bitorder[j]] = (unsigned) b & 7; + DUMPBITS (3); + } + for (; j < 19; j++) + ll[bitorder[j]] = 0; + + /* build decoding table for trees--single level, 7 bit lookup */ + bl = 7; + if ((i = huft_build (ll, 19, 19, NULL, NULL, &tl, &bl)) != 0) + { + errnum = ERR_BAD_GZIP_DATA; + return; + } + + /* read in literal and distance code lengths */ + n = nl + nd; + m = mask_bits[bl]; + i = l = 0; + while ((unsigned) i < n) + { + NEEDBITS ((unsigned) bl); + j = (td = tl + ((unsigned) b & m))->b; + DUMPBITS (j); + j = td->v.n; + if (j < 16) /* length of code in bits (0..15) */ + ll[i++] = l = j; /* save last length in l */ + else if (j == 16) /* repeat last length 3 to 6 times */ + { + NEEDBITS (2); + j = 3 + ((unsigned) b & 3); + DUMPBITS (2); + if ((unsigned) i + j > n) + { + errnum = ERR_BAD_GZIP_DATA; + return; + } + while (j--) + ll[i++] = l; + } + else if (j == 17) /* 3 to 10 zero length codes */ + { + NEEDBITS (3); + j = 3 + ((unsigned) b & 7); + DUMPBITS (3); + if ((unsigned) i + j > n) + { + errnum = ERR_BAD_GZIP_DATA; + return; + } + while (j--) + ll[i++] = 0; + l = 0; + } + else + /* j == 18: 11 to 138 zero length codes */ + { + NEEDBITS (7); + j = 11 + ((unsigned) b & 0x7f); + DUMPBITS (7); + if ((unsigned) i + j > n) + { + errnum = ERR_BAD_GZIP_DATA; + return; + } + while (j--) + ll[i++] = 0; + l = 0; + } + } + + /* free decoding table for trees */ + reset_linalloc (); + + /* restore the global bit buffer */ + bb = b; + bk = k; + + /* build the decoding tables for literal/length and distance codes */ + bl = lbits; + if ((i = huft_build (ll, nl, 257, cplens, cplext, &tl, &bl)) != 0) + { +#if 0 + if (i == 1) + printf ("gunzip: incomplete literal tree\n"); +#endif + + errnum = ERR_BAD_GZIP_DATA; + return; + } + bd = dbits; + if ((i = huft_build (ll + nl, nd, 0, cpdist, cpdext, &td, &bd)) != 0) + { +#if 0 + if (i == 1) + printf ("gunzip: incomplete distance tree\n"); +#endif + + errnum = ERR_BAD_GZIP_DATA; + return; + } + + /* indicate we're now working on a block */ + code_state = 0; + block_len++; +} + + +static void +get_new_block (void) +{ + register ulg b; /* bit buffer */ + register unsigned k; /* number of bits in bit buffer */ + + hufts = 0; + + /* make local bit buffer */ + b = bb; + k = bk; + + /* read in last block bit */ + NEEDBITS (1); + last_block = (int) b & 1; + DUMPBITS (1); + + /* read in block type */ + NEEDBITS (2); + block_type = (unsigned) b & 3; + DUMPBITS (2); + + /* restore the global bit buffer */ + bb = b; + bk = k; + + if (block_type == INFLATE_STORED) + init_stored_block (); + if (block_type == INFLATE_FIXED) + init_fixed_block (); + if (block_type == INFLATE_DYNAMIC) + init_dynamic_block (); +} + + +static void +inflate_window (void) +{ + /* initialize window */ + wp = 0; + + /* + * Main decompression loop. + */ + + while (wp < WSIZE && !errnum) + { + if (!block_len) + { + if (last_block) + break; + + get_new_block (); + } + + if (block_type > INFLATE_DYNAMIC) + errnum = ERR_BAD_GZIP_DATA; + + if (errnum) + return; + + /* + * Expand stored block here. + */ + if (block_type == INFLATE_STORED) + { + int w = wp; + + /* + * This is basically a glorified pass-through + */ + + while (block_len && w < WSIZE && !errnum) + { + slide[w++] = get_byte (); + block_len--; + } + + wp = w; + + continue; + } + + /* + * Expand other kind of block. + */ + + if (inflate_codes_in_window ()) + reset_linalloc (); + } + + saved_filepos += WSIZE; + + /* XXX do CRC calculation here! */ +} + + +static void +initialize_tables (void) +{ + saved_filepos = 0; + filepos = gzip_data_offset; + + /* initialize window, bit buffer */ + bk = 0; + bb = 0; + + /* reset partial decompression code */ + last_block = 0; + block_len = 0; + + /* reset memory allocation stuff */ + reset_linalloc (); +} + + +int +gunzip_read (unsigned char *buf, int len) +{ + int ret = 0; + int real_len = len; + + compressed_file = 0; + gunzip_swap_values (); + /* + * Now "gzip_*" values refer to the uncompressed data. + */ + + /* do we reset decompression to the beginning of the file? */ + if (saved_filepos > gzip_filepos + WSIZE) + initialize_tables (); + + /* + * This loop operates upon uncompressed data only. The only + * special thing it does is to make sure the decompression + * window is within the range of data it needs. + */ + + while (len > 0 && !errnum) + { + register int size; + register char *srcaddr; + + while (gzip_filepos >= saved_filepos) + inflate_window (); + + srcaddr = (char *) ((gzip_filepos & (WSIZE - 1)) + slide); + size = saved_filepos - gzip_filepos; + if (size > len) + size = len; + + memmove (buf, srcaddr, size); + + buf += size; + len -= size; + gzip_filepos += size; + ret += size; + + if (do_show_progress) + show_progress(ret, real_len); + } + + compressed_file = 1; + gunzip_swap_values (); + /* + * Now "gzip_*" values refer to the compressed data. + */ + + if (errnum) + ret = 0; + + return ret; +} + +#endif /* ! NO_DECOMPRESSION */ diff --git a/l4/pkg/bootstrap/server/src/gunzip.h b/l4/pkg/bootstrap/server/src/gunzip.h new file mode 100644 index 00000000..1c3785d0 --- /dev/null +++ b/l4/pkg/bootstrap/server/src/gunzip.h @@ -0,0 +1,36 @@ +#ifndef __BOOTSTRAP__GUNZIP_H__ +#define __BOOTSTRAP__GUNZIP_H__ + +#include +#include "panic.h" + +typedef enum +{ + ERR_NONE = 0, + ERR_BAD_GZIP_DATA, + ERR_BAD_GZIP_HEADER, + +} grub_error_t; + +l4_addr_t gunzip_upper_mem_linalloc(void); +#define UPPER_MEM_LINALLOC gunzip_upper_mem_linalloc() + +#define RAW_ADDR(x) (x) +#define RAW_SEG(x) (x) + +extern unsigned int filepos; +extern unsigned int filemax; +extern unsigned int fsmax; /* max size of fs/readable media */ +extern unsigned int compressed_file; +extern grub_error_t errnum; + +/* Read LEN bytes into BUF from the file that was opened with + GRUB_OPEN. If LEN is -1, read all the remaining data in the file. */ +int grub_read (unsigned char *buf, int len); + +int gunzip_read (unsigned char *buf, int len); +int gunzip_test_header (void); + +void *memmove(void *dest, const void *src, size_t n); + +#endif /* ! __BOOTSTRAP__GUNZIP_H__ */ diff --git a/l4/pkg/bootstrap/server/src/init_kip-arch.h b/l4/pkg/bootstrap/server/src/init_kip-arch.h new file mode 100644 index 00000000..79bbfcd0 --- /dev/null +++ b/l4/pkg/bootstrap/server/src/init_kip-arch.h @@ -0,0 +1,19 @@ +/* + * (c) 2009 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ +#ifndef INIT_KIP_ARCH_H__ +#define INIT_KIP_ARCH_H__ + +#include + +#if defined(ARCH_ppc32) +void init_kip_v2_arch(l4_kernel_info_t *); +#endif + +#endif + diff --git a/l4/pkg/bootstrap/server/src/init_kip.h b/l4/pkg/bootstrap/server/src/init_kip.h new file mode 100644 index 00000000..cf3e1df4 --- /dev/null +++ b/l4/pkg/bootstrap/server/src/init_kip.h @@ -0,0 +1,27 @@ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg , + * Frank Mehnert + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ +#ifndef INIT_KIP_H__ +#define INIT_KIP_H__ + +#include +#include "startup.h" +#include "init_kip-arch.h" + +#ifdef __cplusplus +class Region_list; + +void init_kip_v2(void *_l4i, boot_info_t *bi, l4util_mb_info_t *mbi, + Region_list *ram, Region_list *regions); +void init_kip_v4(void *_l4i, boot_info_t *bi, l4util_mb_info_t *mbi, + Region_list *ram, Region_list *regions); +#endif + +#endif diff --git a/l4/pkg/bootstrap/server/src/init_kip_v2.cc b/l4/pkg/bootstrap/server/src/init_kip_v2.cc new file mode 100644 index 00000000..414d8b8f --- /dev/null +++ b/l4/pkg/bootstrap/server/src/init_kip_v2.cc @@ -0,0 +1,93 @@ +/** + * \file + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ + +#include +#include +#include +#include +#include "panic.h" + +#include "macros.h" +#include "init_kip.h" +#include "region.h" +#include "startup.h" +#include + +using L4::Kip::Mem_desc; + +extern unsigned char _stack; + +/** + * setup Kernel Info Page + */ +void +init_kip_v2(void *_l4i, boot_info_t *bi, l4util_mb_info_t *mbi, + Region_list *ram, Region_list *regions) +{ + l4_kernel_info_t *l4i = (l4_kernel_info_t *)_l4i; + + unsigned char l4_api = l4i->version >> 24; + + if (l4_api != 0x87 /*VERSION_FIASCO*/) + panic("cannot load kernels other than Fiasco"); + + Mem_desc *md = Mem_desc::first(_l4i); + for (Region const* c = ram->begin(); c != ram->end(); ++c) + (md++)->set(c->begin(), c->end(), Mem_desc::Conventional); + + for (Region const *c = regions->begin(); c != regions->end(); ++c) + { + Mem_desc::Mem_type type = Mem_desc::Reserved; + unsigned char sub_type = 0; + switch (c->type()) + { + case Region::No_mem: + case Region::Ram: + case Region::Boot: + continue; + case Region::Kernel: + type = Mem_desc::Reserved; + break; + case Region::Sigma0: + type = Mem_desc::Dedicated; + break; + case Region::Root: + type = Mem_desc::Bootloader; + break; + case Region::Arch: + type = Mem_desc::Arch; + sub_type = c->sub_type(); + break; + } + (md++)->set(c->begin(), c->end() - 1, type, sub_type); + } + + l4i->user_ptr = (unsigned long)mbi; + + /* set up sigma0 info */ + l4i->sigma0_esp = bi->sigma0_stack; + l4i->sigma0_eip = bi->sigma0_start; + printf(" Sigma0 config ip:"l4_addr_fmt" sp:"l4_addr_fmt"\n", + l4i->sigma0_eip, l4i->sigma0_esp); + + /* set up roottask info */ + //l4i->root_esp = (l4_umword_t) &_stack; + l4i->root_eip = bi->roottask_start; + printf(" Roottask config ip:"l4_addr_fmt" sp:"l4_addr_fmt"\n", + l4i->root_eip, l4i->root_esp); + + /* Platform info */ + strncpy(l4i->platform_info.name, PLATFORM_TYPE, + sizeof(l4i->platform_info.name)); + l4i->platform_info.name[sizeof(l4i->platform_info.name) - 1] = 0; +} diff --git a/l4/pkg/bootstrap/server/src/init_kip_v4.cc b/l4/pkg/bootstrap/server/src/init_kip_v4.cc new file mode 100644 index 00000000..47a8311e --- /dev/null +++ b/l4/pkg/bootstrap/server/src/init_kip_v4.cc @@ -0,0 +1,134 @@ +/** + * \file + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg , + * Frank Mehnert + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ + +#include "init_kip.h" +#include "startup.h" +#include "region.h" +#include +#include + +using L4::Kip::Mem_desc; + +/* XXX not possible to include kip.h from L4Ka::Pistachio here */ + +#if L4_MWORD_BITS == 32 +#define V4KIP_SIGMA0_SP 0x20 +#define V4KIP_SIGMA0_IP 0x24 +#define V4KIP_SIGMA0_LOW 0x28 +#define V4KIP_SIGMA0_HIGH 0x2C +#define V4KIP_ROOT_SP 0x40 +#define V4KIP_ROOT_IP 0x44 +#define V4KIP_ROOT_LOW 0x48 +#define V4KIP_ROOT_HIGH 0x4C +#define V4KIP_MEM_INFO 0x54 +#define V4KIP_BOOT_INFO 0xB8 +#elif L4_MWORD_BITS == 64 +#define V4KIP_SIGMA0_SP 0x40 +#define V4KIP_SIGMA0_IP 0x48 +#define V4KIP_SIGMA0_LOW 0x50 +#define V4KIP_SIGMA0_HIGH 0x58 +#define V4KIP_ROOT_SP 0x80 +#define V4KIP_ROOT_IP 0x88 +#define V4KIP_ROOT_LOW 0x90 +#define V4KIP_ROOT_HIGH 0x98 +#define V4KIP_MEM_INFO 0xA8 +#define V4KIP_BOOT_INFO 0x170 +#else +#error unknown architecture +#endif + +#define V4KIP_WORD(kip,offset) ((l4_umword_t*)(((char*)(kip))+(offset))) + +/** + * @brief Initialize KIP prototype for Fiasco/v4. + */ +void +init_kip_v4 (void *l4i, boot_info_t *bi, l4util_mb_info_t *mbi, + Region_list *ram, Region_list *regions) +{ + Mem_desc *md = Mem_desc::first(l4i); + for (Region const* c = ram->begin(); c != ram->end(); ++c) + (md++)->set(c->begin(), c->end(), Mem_desc::Conventional); + +#if 0 + // 1: all memory is accessible for users + *p++ = 0 | 4; + *p++ = ~0UL; + num_info++; + + // 4: (additional) 20MB kernel memory + if (mem_end > (240 << 20)) + mem_end = 240 << 20; + *p++ = (mem_end - (20 << 20)) | 2; + *p++ = mem_end; + num_info++; +#endif + + // VGA + (md++)->set(0xA0000, 0xBFFFF, Mem_desc::Shared); + // 6: BIOS + (md++)->set(0xC0000, 0xEFFFF, Mem_desc::Shared); + + unsigned long s0_low = ~0UL, s0_high = 0; + unsigned long root_low = ~0UL, root_high = 0; + + for (Region const *c = regions->begin(); c != regions->end(); ++c) + { + Mem_desc::Mem_type type = Mem_desc::Reserved; + unsigned char sub_type = 0; + switch (c->type()) + { + case Region::No_mem: + case Region::Ram: + case Region::Boot: + continue; + case Region::Kernel: + type = Mem_desc::Reserved; + break; + case Region::Sigma0: + type = Mem_desc::Dedicated; + if (s0_low > c->begin()) + s0_low = c->begin(); + if (s0_high < c->end()) + s0_high = c->end(); + break; + case Region::Root: + type = Mem_desc::Bootloader; + if (root_low > c->begin()) + root_low = c->begin(); + if (root_high < c->end()) + root_high = c->end(); + break; + case Region::Arch: + type = Mem_desc::Arch; + sub_type = c->sub_type(); + break; + } + (md++)->set(c->begin(), c->end() - 1, type, sub_type); + } + + *V4KIP_WORD(l4i,V4KIP_SIGMA0_LOW) = s0_low; + *V4KIP_WORD(l4i,V4KIP_SIGMA0_HIGH) = s0_high+1; + *V4KIP_WORD(l4i,V4KIP_SIGMA0_IP) = bi->sigma0_start; + + *V4KIP_WORD(l4i,V4KIP_ROOT_LOW) = root_low; + *V4KIP_WORD(l4i,V4KIP_ROOT_HIGH) = root_high+1; + *V4KIP_WORD(l4i,V4KIP_ROOT_IP) = bi->roottask_start; + *V4KIP_WORD(l4i,V4KIP_ROOT_SP) = bi->roottask_stack; + + *V4KIP_WORD(l4i,V4KIP_BOOT_INFO) = (unsigned long)mbi; + + // set the mem_info variable: count of mem descriptors + Mem_desc::count(l4i, md - Mem_desc::first(l4i)); +} diff --git a/l4/pkg/bootstrap/server/src/koptions-def.h b/l4/pkg/bootstrap/server/src/koptions-def.h new file mode 100644 index 00000000..3a418f60 --- /dev/null +++ b/l4/pkg/bootstrap/server/src/koptions-def.h @@ -0,0 +1,75 @@ +#pragma once + +#include + +// To generate the kernel version: +// perl -p -e 's/l4_uint(\d+)_t/Unsigned$1/;s/^#inc.+/#include "types.h"/' koptions-def.h + +namespace L4_kernel_options +{ + enum Flags + { + F_wait = 1 << 0, + F_serial_esc = 1 << 1, + F_noserial = 1 << 2, + F_noscreen = 1 << 3, + F_esc = 1 << 4, + F_nojdb = 1 << 5, + F_nokdb = 1 << 6, + F_nohlt = 1 << 7, + F_apic = 1 << 8, + F_loadcnt = 1 << 9, + F_watchdog = 1 << 10, + F_irq0 = 1 << 13, + F_nosfn = 1 << 15, + F_jdb_never_stop = 1 << 16, + + F_kmemsize = 1 << 17, + F_tbuf_entries = 1 << 18, + F_out_buf = 1 << 19, + F_uart_baud = 1 << 20, + F_uart_base = 1 << 21, + F_uart_irq = 1 << 22, + + F_jdb_cmd = 1 << 23, + }; + + enum + { + Magic = 0x4C344B43, + }; + + enum Uart_types + { + Uart_type_invalid = 0, + Uart_type_ioport = 1, + Uart_type_mmio = 2, + }; + + struct Uart + { + l4_uint32_t access_type; ///< Accesstype of UART: unset, MMIO or ports + l4_uint32_t baud; ///< Baud rate + l4_uint32_t irqno; ///< (Receive) IRQ + l4_uint64_t base_address; ///< Start address of UART + } __attribute__((packed)); + + struct Options + { + l4_uint32_t magic; ///< Magic value + l4_uint32_t version; ///< Version of this structure + + l4_uint32_t flags; ///< Option flags + + l4_uint32_t kmemsize; ///< Wanted kernel memory size in KiB + + Uart uart; ///< Kernel UART + + char jdb_cmd[128]; + l4_uint32_t tbuf_entries; + l4_uint32_t out_buf; + + l4_uint32_t opt(Flags flag) const { return flags & flag; } + + } __attribute__((packed)); +}; diff --git a/l4/pkg/bootstrap/server/src/koptions.cc b/l4/pkg/bootstrap/server/src/koptions.cc new file mode 100644 index 00000000..ca98caca --- /dev/null +++ b/l4/pkg/bootstrap/server/src/koptions.cc @@ -0,0 +1,136 @@ + +#include +#include +#include +#include +#include + +#include "koptions.h" + +static struct { + const char *s; + unsigned int flag; +} boolean_opts[] = { + { " -wait", L4_kernel_options::F_wait }, + { " -serial_esc", L4_kernel_options::F_serial_esc }, + { " -noserial", L4_kernel_options::F_noserial }, + { " -noscreen", L4_kernel_options::F_noscreen }, + { " -esc", L4_kernel_options::F_esc }, + { " -nojdb", L4_kernel_options::F_nojdb }, + { " -nokdb", L4_kernel_options::F_nokdb }, + { " -nohlt", L4_kernel_options::F_nohlt }, + { " -apic", L4_kernel_options::F_apic }, + { " -loadcnt", L4_kernel_options::F_loadcnt }, + { " -watchdog", L4_kernel_options::F_watchdog }, + { " -irq0", L4_kernel_options::F_irq0 }, + { " -nosfn", L4_kernel_options::F_nosfn }, + { " -jdb_never_stop", L4_kernel_options::F_jdb_never_stop }, +}; + +static struct { + const char *s; + unsigned int flag; + unsigned int offset; +} unsigned_opts[] = { + { " -kmemsize", L4_kernel_options::F_kmemsize, + offsetof(L4_kernel_options::Options, kmemsize) }, + { " -tbuf_entries", L4_kernel_options::F_tbuf_entries, + offsetof(L4_kernel_options::Options, tbuf_entries) }, + { " -out_buf", L4_kernel_options::F_out_buf, + offsetof(L4_kernel_options::Options, out_buf) }, +}; + +#define MEMBERSIZE(type, member) sizeof(((type *)0)->member) + +static struct { + const char *s; + unsigned int flag; + unsigned int size; + unsigned int offset; +} string_opts[] = { + { " -jdb_cmd", L4_kernel_options::F_jdb_cmd, + MEMBERSIZE(L4_kernel_options::Options, jdb_cmd), + offsetof(L4_kernel_options::Options, jdb_cmd) }, +}; + +static void kcmdline_show(L4_kernel_options::Options *lko) +{ + printf("Location: %016lx Size: %zd Bytes\n", + (unsigned long)lko, sizeof(*lko)); + printf("Flags: %08x\n", lko->flags); + for (unsigned i = 0; i < sizeof(boolean_opts) / sizeof(boolean_opts[0]); ++i) + { + if (lko->flags & boolean_opts[i].flag) + printf(" %s\n", boolean_opts[i].s); + } + + if (lko->flags & L4_kernel_options::F_kmemsize) + printf("Kmemsize: %dKiB\n", lko->kmemsize); + if (lko->flags & L4_kernel_options::F_tbuf_entries) + printf("Tbuf entries: %d\n", lko->tbuf_entries); + if (lko->flags & L4_kernel_options::F_out_buf) + printf("Out bufs: %d\n", lko->out_buf); + + if (lko->jdb_cmd[0]) + printf("JDB command: %s\n", lko->jdb_cmd); +} + +#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) + +void kcmdline_parse(char const *cmdline, + L4_kernel_options::Options *lko) +{ + if (0) + printf("Kernel command-line: %s\n", cmdline); + + // boolean options + for (unsigned i = 0; i < ARRAY_SIZE(boolean_opts); ++i) + if (strstr(cmdline, boolean_opts[i].s)) + lko->flags |= boolean_opts[i].flag; + + // integer options + for (unsigned i = 0; i < ARRAY_SIZE(unsigned_opts); ++i) + { + char *c; + unsigned len = strlen(unsigned_opts[i].s); + if ((c = strstr(cmdline, unsigned_opts[i].s)) + && (c[len] == ' ' || c[len] == '=')) + { + lko->flags |= unsigned_opts[i].flag; + *(unsigned *)((char *)lko + unsigned_opts[i].offset) + = strtol(c + len + 1, 0, 0); + } + } + + // string options + for (unsigned i = 0; i < ARRAY_SIZE(string_opts); ++i) + { + char *c; + unsigned len = strlen(string_opts[i].s); + if ((c = strstr(cmdline, string_opts[i].s)) + && (c[len] == ' ' || c[len] == '=')) + { + char *dst = (char *)lko + string_opts[i].offset; + lko->flags |= string_opts[i].flag; + c += len + 1; + while (*c && *c != ' ' + && (dst < (char *)lko + string_opts[i].offset + + string_opts[i].size - 1)) + *dst++ = *c++; + *dst = 0; + } + } + + // warnings + if (strstr(cmdline, "-comport") + || strstr(cmdline, "-comspeed") + || strstr(cmdline, "-comirq")) + printf("WARNING: Command line options -comport, -comspeed and -comirq\n" + " have been moved to bootstrap and are shared beetween\n" + " Fiasco and bootstrap now. Please remove them from\n" + " your Fiasco command line, they do not have an effect\n" + " there.\n"); + + if (0) + kcmdline_show(lko); +} diff --git a/l4/pkg/bootstrap/server/src/koptions.h b/l4/pkg/bootstrap/server/src/koptions.h new file mode 100644 index 00000000..f49365ab --- /dev/null +++ b/l4/pkg/bootstrap/server/src/koptions.h @@ -0,0 +1,6 @@ +#pragma once + +#include "koptions-def.h" + +void +kcmdline_parse(char const *cmdline, L4_kernel_options::Options *lko); diff --git a/l4/pkg/bootstrap/server/src/ldscript.inc b/l4/pkg/bootstrap/server/src/ldscript.inc new file mode 100644 index 00000000..718fd553 --- /dev/null +++ b/l4/pkg/bootstrap/server/src/ldscript.inc @@ -0,0 +1,24 @@ +/* vi:ft=c + Common functionality for linker scripts in bootstrap */ + +#define CTORS \ + . = ALIGN(8); \ + PROVIDE (__CTORS_BEGIN = .); \ + KEEP (*(SORT(.ctors.*))) \ + KEEP (*(.ctors)) \ + PROVIDE (__CTORS_END = .); \ + PROVIDE (__preinit_array_start = .); \ + KEEP (*(SORT(.preinit_array.*))) \ + KEEP (*(.preinit_array)) \ + PROVIDE (__preinit_array_end = .); \ + PROVIDE (__init_array_start = .); \ + KEEP (*(SORT(.init_array.*))) \ + KEEP (*(.init_array)) \ + PROVIDE (__init_array_end = .); + + +#define PLATFORMS \ + PROVIDE (__PLATFORMS_BEGIN = .); \ + KEEP (*(.platformdata)) \ + PROVIDE (__PLATFORMS_END = .); + diff --git a/l4/pkg/bootstrap/server/src/libc_support+.cc b/l4/pkg/bootstrap/server/src/libc_support+.cc new file mode 100644 index 00000000..952a2724 --- /dev/null +++ b/l4/pkg/bootstrap/server/src/libc_support+.cc @@ -0,0 +1,294 @@ +/** + * \file bootstrap/server/src/libc_support.c + * \brief Support for C library + * + * \date 2004-2008 + * \author Adam Lackorzynski , + * Frank Mehnert */ + +/* + * (c) 2005-2009 Author(s) + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "panic.h" + +#include + +#include "support.h" + +Platform_base *Platform_base::platform; + +static L4::Uart *stdio_uart; + +L4::Uart *uart() +{ return stdio_uart; } + +void set_stdio_uart(L4::Uart *uart) +{ stdio_uart = uart; } + + +inline void *operator new (size_t, void *p) { return p; } +// IO Stream backend +namespace { + + class BootstrapIOBackend : public L4::IOBackend + { + protected: + void write(char const *str, unsigned len); + }; + + void BootstrapIOBackend::write(char const *str, unsigned len) + { + ::write(STDOUT_FILENO, str, len); + } + +}; + +namespace L4 { + typedef char Fake_iobackend[sizeof(BootstrapIOBackend)] + __attribute__((aligned(__alignof__(BootstrapIOBackend)))); + typedef char Fake_ostream[sizeof(BasicOStream)] + __attribute__((aligned(__alignof__(BasicOStream)))); + + Fake_ostream cout; + Fake_ostream cerr; + + static Fake_iobackend _iob; + + void iostream_init(); + void iostream_init() + { + static int _initialized; + if (!_initialized) + { + _initialized = 1; + BootstrapIOBackend *iob = new (&_iob) BootstrapIOBackend(); + new (&cerr) BasicOStream(iob); + new (&cout) BasicOStream(iob); + } + } +}; + +typedef void Ctor(); + +static void call_ctors(Ctor **start, Ctor **end) +{ + for (; start < end; ++start) + if (*start) + (*start)(); +} + +static void +ctor_init() +{ + extern Ctor *__CTORS_BEGIN[]; + extern Ctor *__CTORS_END[]; + extern Ctor *__init_array_start[]; + extern Ctor *__init_array_end[]; + extern Ctor *__preinit_array_start[]; + extern Ctor *__preinit_array_end[]; + + call_ctors(__preinit_array_start, __preinit_array_end); + call_ctors(__CTORS_BEGIN, __CTORS_END); + call_ctors(__init_array_start, __init_array_end); +} + + +static inline void clear_bss() +{ + extern char _bss_start[], _bss_end[]; + extern int crt0_stack_low, crt0_stack_high; + memset(_bss_start, 0, (char *)&crt0_stack_low - _bss_start); + memset((char *)&crt0_stack_high, 0, _bss_end - (char *)&crt0_stack_high); +} + +extern "C" +void startup(unsigned long p1, unsigned long p2, + unsigned long p3, unsigned long p4); + +#ifdef ARCH_arm + +extern "C" int __aeabi_unwind_cpp_pr0(void); +extern "C" int __aeabi_unwind_cpp_pr1(void); +enum { _URC_FAILURE = 9 }; +extern "C" int __aeabi_unwind_cpp_pr0(void) { return _URC_FAILURE; } +extern "C" int __aeabi_unwind_cpp_pr1(void) { return _URC_FAILURE; } + +extern "C" void __main(); +void __main() +{ + unsigned long r; + + asm volatile("mrc p15, 0, %0, c1, c0, 0" : "=r" (r) : : "memory"); + r &= ~1UL; + r |= 2; // alignment check on + asm volatile("mcr p15, 0, %0, c1, c0, 0" : : "r" (r) : "memory"); + + clear_bss(); + ctor_init(); + Platform_base::iterate_platforms(); + + startup(0, 0, 0, 0); + while(1) + ; +} +#endif + +#ifdef ARCH_ppc32 +#include +extern "C" void __main(unsigned long p1, unsigned long p2, unsigned long p3); +void __main(unsigned long, unsigned long, unsigned long p3) +{ + clear_bss(); + ctor_init(); + L4_drivers::Of::set_prom(p3); //p3 is OF prom pointer + Platform_base::iterate_platforms(); + + printf("PPC platform initialized\n"); + startup(0, 0, 0, 0); + while(1) + ; +} +#endif + +#if defined(ARCH_x86) || defined(ARCH_amd64) +extern l4util_mb_info_t *x86_bootloader_mbi; +extern "C" void __main(unsigned long p1, unsigned long p2, unsigned long p3, unsigned long p4); +void __main(unsigned long p1, unsigned long p2, unsigned long p3, unsigned long p4) +{ + ctor_init(); + x86_bootloader_mbi = (l4util_mb_info_t *)p1; + Platform_base::iterate_platforms(); + startup(p1, p2, p3, p4); +} +#endif + +#if defined(ARCH_sparc) +extern "C" void __main(); +void __main() +{ + clear_bss(); + ctor_init(); + Platform_base::iterate_platforms(); + startup(0, 0, 0, 0); +} +#endif + +void exit(int c) throw() +{ + _exit(c); +} + +void (*__exit_cleanup) (int) = 0; + +extern "C" void __attribute__((noreturn)) +__assert(const char *, const char *, int, register const char *); + +extern "C" void __attribute__((noreturn)) +__assert(const char *assertion, const char * filename, + int linenumber, register const char * function) +{ + printf("%s:%d: %s: Assertion `%s' failed.\n", + filename, + linenumber, + ((function == NULL) ? "?function?" : function), + assertion + ); + panic("Assertion"); + while(1) + ; +} + +ssize_t +write(int fd, const void *buf, size_t count) +{ + if (!uart()) + return 0; + + if (fd == STDOUT_FILENO || fd == STDERR_FILENO) + { + char *b = (char *)buf; + int i = count; + while (i--) + { + char c = *b++; + if (c == '\n') + uart()->write("\r", 1); + uart()->write(&c, 1); + } + + return count; + } + + errno = EBADF; + return -1; +} + +#undef getchar +int +getchar(void) +{ + int c; + if (!uart()) + return -1; + + do + c = uart()->get_char(0); + while (c == -1) + ; + return c; +} + +off_t lseek(int /*fd*/, off_t /*offset*/, int /*whence*/) +{ + return 0; +} + +void *__dso_handle = &__dso_handle; + +extern "C" void reboot(void) __attribute__((noreturn)); +void reboot(void) +{ + void reboot_arch() __attribute__((noreturn)); + reboot_arch(); +} + +extern "C" void __attribute__((noreturn)) +_exit(int /*rc*/) +{ + printf("\n\033[1mKey press reboots...\033[m\n"); + getchar(); + printf("Rebooting.\n\n"); + reboot(); +} + +/** for assert */ +void +abort(void) throw() +{ + _exit(1); +} + +void +panic(const char *fmt, ...) +{ + va_list v; + va_start (v, fmt); + vprintf(fmt, v); + va_end(v); + putchar('\n'); + exit(1); +} diff --git a/l4/pkg/bootstrap/server/src/loader_mbi.cc b/l4/pkg/bootstrap/server/src/loader_mbi.cc new file mode 100644 index 00000000..a007479f --- /dev/null +++ b/l4/pkg/bootstrap/server/src/loader_mbi.cc @@ -0,0 +1,38 @@ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ +/* + * Used when our boot loader does not supply a mbi structure. + */ + +#include + +#include "loader_mbi.h" + +l4util_mb_info_t loader_mbi; + +l4util_mb_info_t *init_loader_mbi(void *realmode_pointer) +{ + loader_mbi.flags = L4UTIL_MB_MEMORY; + loader_mbi.mem_lower = 0x9f * 4; + + unsigned long *cmd_line_ptr; + + loader_mbi.mem_upper = *(unsigned long *)((char *)realmode_pointer + 0x1e0); + printf("Detected memory size: %dKB\n", loader_mbi.mem_upper); + + cmd_line_ptr = (unsigned long *)((char *)realmode_pointer + 0x228); + if (cmd_line_ptr && *cmd_line_ptr) + { + loader_mbi.flags |= L4UTIL_MB_CMDLINE; + loader_mbi.cmdline = *cmd_line_ptr; + } + + return &loader_mbi; +} diff --git a/l4/pkg/bootstrap/server/src/loader_mbi.h b/l4/pkg/bootstrap/server/src/loader_mbi.h new file mode 100644 index 00000000..c9fe2586 --- /dev/null +++ b/l4/pkg/bootstrap/server/src/loader_mbi.h @@ -0,0 +1,17 @@ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ +#ifndef __BOOTSTRAP__LOADER_MBI_H__ +#define __BOOTSTRAP__LOADER_MBI_H__ + +#include + +l4util_mb_info_t *init_loader_mbi(void *); + +#endif /* ! __BOOTSTRAP__LOADER_MBI_H__ */ diff --git a/l4/pkg/bootstrap/server/src/module.c b/l4/pkg/bootstrap/server/src/module.c new file mode 100644 index 00000000..2273b270 --- /dev/null +++ b/l4/pkg/bootstrap/server/src/module.c @@ -0,0 +1,34 @@ +/* + * (c) 2008-2009 Frank Mehnert , + * Torsten Frenzel + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ +#include +#include "module.h" + +void +print_module_name(const char *name, const char *alt_name) +{ + const char *c1, *c2; + + if (!name) + { + printf("%s", alt_name); + return; + } + + c2 = name; + while (*c2 != '\0' && *c2 != ' ') + c2++; + c1 = c2; + if (c1 > name) + c1--; + while (c1 > name && c2-c1 < 56) + c1--; + + printf("%.*s", (unsigned)(c2-c1), c1); +} diff --git a/l4/pkg/bootstrap/server/src/module.h b/l4/pkg/bootstrap/server/src/module.h new file mode 100644 index 00000000..1252f4a4 --- /dev/null +++ b/l4/pkg/bootstrap/server/src/module.h @@ -0,0 +1,24 @@ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg , + * Frank Mehnert + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ +#ifndef MODULE_H +#define MODULE_H + +#include +#include +#include + +EXTERN_C_BEGIN + +void print_module_name(const char *name, const char *alt_name); + +EXTERN_C_END + +#endif diff --git a/l4/pkg/bootstrap/server/src/panic.h b/l4/pkg/bootstrap/server/src/panic.h new file mode 100644 index 00000000..6c2a5295 --- /dev/null +++ b/l4/pkg/bootstrap/server/src/panic.h @@ -0,0 +1,15 @@ +/* + * (c) 2008-2009 Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ +#pragma once + +#ifdef __cplusplus +extern "C" +#endif +void panic(const char *fmt, ...) __attribute__((format(printf, 1, 2))); + diff --git a/l4/pkg/bootstrap/server/src/patch.cc b/l4/pkg/bootstrap/server/src/patch.cc new file mode 100644 index 00000000..57626827 --- /dev/null +++ b/l4/pkg/bootstrap/server/src/patch.cc @@ -0,0 +1,218 @@ +/** + * \file bootstrap/server/src/patch.c + * \brief Patching of boot modules + * + * \date 09/2005 + * \author Frank Mehnert */ + +/* + * (c) 2005-2009 Author(s) + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ + +#include +#include +#include +#include + +#include +#include +#include "panic.h" + +#ifdef ARCH_x86 +#include "ARCH-x86/macros.h" +#endif + +#ifdef ARCH_arm +#include "ARCH-arm/macros.h" +#endif + +#ifdef ARCH_amd64 +#include "ARCH-amd64/macros.h" +#endif + +#ifdef ARCH_ppc32 +#include "ARCH-ppc32/macros.h" +#endif + +#ifdef ARCH_sparc +#include "ARCH-sparc/macros.h" +#endif + +#include "types.h" +#include "patch.h" +#include "startup.h" + + +/* search module in module list */ +static l4util_mb_mod_t* +search_module(const char *name, size_t name_len, l4util_mb_info_t *mbi, + const char **cmdline) +{ + unsigned i; + const char *c = 0, *ce = 0; + l4util_mb_mod_t *mod; + + for (i=0; imods_count; i++) + { + const char *m, *n; + + mod = (L4_MB_MOD_PTR(mbi->mods_addr)) + i; + m = c = L4_CONST_CHAR_PTR(mod->cmdline); + ce = strchr(c, ' '); + if (!ce) + ce = c+strlen(c); + for (;;) + { + if (!(n = strchr(m, name[0])) || n+name_len>ce) + break; + if (!memcmp(name, n, name_len)) + { + *cmdline = c; + return mod; + } + m = n+1; + } + } + + return NULL; +} + +/** + * Handle -patch=,=blah parameter. Overwrite a specific + * module from command line. This allows to change the boot configuration (e.g. + * changing parameters of a loader script) + */ +void +patch_module(const char **str, l4util_mb_info_t *mbi) +{ + const char *nam_beg, *nam_end; + const char *var_beg, *var_end; + const char *val_beg, *val_end; + char *mod_beg, *mod_end, *mod_ptr, quote = 0; + l4_size_t var_size, val_size, max_patch_size; + const char *cmdline = 0; + l4util_mb_mod_t *mod; + + /* nam_beg ... nam_end */ + nam_beg = *str+8; + nam_end = strchr(nam_beg, ','); + if (!nam_end || strpbrk(nam_beg, "\011 =*")-1 < nam_end) + panic("-patch: bad module name"); + + mod = search_module(nam_beg, nam_end-nam_beg, mbi, &cmdline); + if (!mod) + panic("-patch: cannot find module \"%.*s\"", + (int)(nam_end-nam_beg), nam_beg); + + mod_beg = L4_CHAR_PTR(mod->mod_start); + mod_end = L4_CHAR_PTR(mod->mod_end); + + /* How much bytes the module can be enlarged to. The module cannot + * be extended beyond page boundaries because the next module starts + * there and we don't want to move the following modules. */ + max_patch_size = l4_round_page((l4_addr_t)mod_end) - (l4_addr_t)mod_end - 1; + + printf(" Patching module \"%s\"\n", cmdline); + + for (var_beg=nam_end; *var_beg==','; var_beg=*str) + { + var_beg++; + /* var_beg ... var_end */ + var_end = strchr(var_beg, '='); + if (!var_end || strpbrk(var_beg, "\011 ,*")-1 < nam_end) + panic("-patch: bad variable name"); + var_size = var_end-var_beg; + + /* val_beg ... val_end, consider quotes */ + val_beg = val_end = var_end+1; + if (*val_end == '"' || *val_end == '\'') + { + val_beg++; + quote = *val_end++; + } + while (*val_end && ((!quote && !isspace(*val_end) && *val_end!=',') || + (quote && *val_end!=quote))) + val_end++; + *str = val_end; + if (quote) + (*str)++; + quote = 0; + val_size = val_end-val_beg; + + /* replace all occurences of variable with value */ + for (mod_ptr=mod_beg;;) + { + if (!(mod_ptr = (char *)memmem(mod_ptr, mod_end - mod_ptr, + var_beg, var_end - var_beg))) + break; + if (var_size < val_size && max_patch_size < val_size-var_size) + panic("-patch: not enough space in module"); + max_patch_size += var_size - val_size; + memmove(mod_ptr+val_size, mod_ptr+var_size, mod_end-mod_ptr-var_size); + if (val_size < var_size) + memset(mod_end-var_size+val_size, 0, var_size-val_size); + memcpy(mod_ptr, val_beg, val_size); + mod_ptr += val_size; + mod_end += val_size - var_size; + } + } + + mod->mod_end = (l4_addr_t)mod_end; +} + + +/** + * Handle -arg=,blah parameter. Replace old command line + * parameters of by blah. Useful for changing the boot + * configuration of a bootstrap image. + * + * Get a pointer to new argument and return the size. + */ +char * +get_arg_module(l4util_mb_info_t *mbi, const char *name, unsigned *size) +{ + char *val_beg = NULL, *val_end; + char *s = (char *)get_cmdline(mbi); + + if (!s) + return 0; + + while (!val_beg && (s = strstr(s, " -arg="))) + { + char *a, *name_end; + + s += 6; + name_end = strchr(s, ','); + if (!name_end) + panic("comma missing after modname in -arg="); + *name_end = 0; + + for (a = s; *a; a++) + if (isspace(*a)) + panic("Invalid '-arg=modname,text' parameter"); + + // we do a fuzzy name-match here + if (strstr(name, s)) + val_beg = name_end+1; + *name_end = ','; + } + if (!val_beg) + return 0; + + // consider quotes + unsigned char quote = 0; + if (*val_beg == '"' || *val_beg == '\'') + quote = *val_beg++; + val_end = val_beg; + + while (*val_end && ((!quote && !isspace(*val_end)) || *val_end!=quote)) + val_end++; + + *size = val_end - val_beg; + return val_beg; +} diff --git a/l4/pkg/bootstrap/server/src/patch.h b/l4/pkg/bootstrap/server/src/patch.h new file mode 100644 index 00000000..d7812998 --- /dev/null +++ b/l4/pkg/bootstrap/server/src/patch.h @@ -0,0 +1,23 @@ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg , + * Frank Mehnert + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ +#ifndef PATCH_H +#define PATCH_H + +#include + +EXTERN_C_BEGIN +void +patch_module(const char **str, l4util_mb_info_t *mbi); +char * +get_arg_module(l4util_mb_info_t *mbi, const char *name, unsigned *size); +EXTERN_C_END + +#endif diff --git a/l4/pkg/bootstrap/server/src/platform/imx.cc b/l4/pkg/bootstrap/server/src/platform/imx.cc new file mode 100644 index 00000000..628103e9 --- /dev/null +++ b/l4/pkg/bootstrap/server/src/platform/imx.cc @@ -0,0 +1,48 @@ +/*! + * \file support_imx.cc + * \brief Support for the i.MX platform + * + * \date 2008-02-04 + * \author Adam Lackorznynski + * + */ +/* + * (c) 2008-2009 Author(s) + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ + +#include "support.h" +#include + +namespace { +class Platform_arm_imx : public Platform_single_region_ram +{ + bool probe() { return true; } + + void init() + { +#ifdef PLATFORM_TYPE_imx21 + static L4::Io_register_block_mmio r(0x1000A000); + static L4::Uart_imx21 _uart; +#elif defined(PLATFORM_TYPE_imx35) + static L4::Uart_imx35 _uart; + static L4::Io_register_block_mmio r(0x43f90000); // UART-1 + //static L4::Io_register_block_mmio r(0x43f94000); // UART-2 + //static L4::Io_register_block_mmio r(0x5000c000); // UART-3 +#elif defined(PLATFORM_TYPE_imx51) + static L4::Io_register_block_mmio r(0x73fbc000); + static L4::Uart_imx51 _uart; +#else +#error Which platform type? +#endif + _uart.startup(&r); + set_stdio_uart(&_uart); + } +}; +} + +REGISTER_PLATFORM(Platform_arm_imx); diff --git a/l4/pkg/bootstrap/server/src/platform/integrator.cc b/l4/pkg/bootstrap/server/src/platform/integrator.cc new file mode 100644 index 00000000..4521ed8b --- /dev/null +++ b/l4/pkg/bootstrap/server/src/platform/integrator.cc @@ -0,0 +1,36 @@ +/*! + * \file support_integrator.cc + * \brief Support for the integrator platform + * + * \date 2008-01-02 + * \author Adam Lackorznynski + * + */ +/* + * (c) 2008-2009 Author(s) + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ + +#include "support.h" +#include + +namespace { +class Platform_arm_int : public Platform_single_region_ram +{ + bool probe() { return true; } + + void init() + { + static L4::Io_register_block_mmio r(0x16000000); + static L4::Uart_pl011 _uart; + _uart.startup(&r); + set_stdio_uart(&_uart); + } +}; +} + +REGISTER_PLATFORM(Platform_arm_int); diff --git a/l4/pkg/bootstrap/server/src/platform/kirkwood.cc b/l4/pkg/bootstrap/server/src/platform/kirkwood.cc new file mode 100644 index 00000000..254b1910 --- /dev/null +++ b/l4/pkg/bootstrap/server/src/platform/kirkwood.cc @@ -0,0 +1,45 @@ +/*! + * \file support_kirkwood.cc + * \brief Support for the kirkwood platform + * + * \date 2010-11 + * \author Adam Lackorznynski + * + */ +/* + * (c) 2010 Author(s) + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ + +#include "support.h" +#include + +namespace { +class Platform_arm_kirkwood : public Platform_single_region_ram +{ + bool probe() { return true; } + + void init() + { + static L4::Uart_16550 _uart(L4::Uart_16550::Base_rate_pxa); + static L4::Io_register_block_mmio r(0xf1012000, 2); // uart0 + //static L4::Io_register_block_mmio r(0xf1012100); // uart1 + _uart.startup(&r); // uart1 + _uart.change_mode(0x3, 8500); // TCLK=200000000, Divisor: 108=TCLK/115200/16 + set_stdio_uart(&_uart); + + + // SPI init, as there's an interrupt pending when coming from u-boot on + // the dockstar, so make it go away + *(unsigned *)0xf1010600 = 0; // disable + *(unsigned *)0xf1010614 = 0; // mask interrupt + *(unsigned *)0xf1010610 = 1; // clear interrupt + } +}; +} + +REGISTER_PLATFORM(Platform_arm_kirkwood); diff --git a/l4/pkg/bootstrap/server/src/platform/leon3.cc b/l4/pkg/bootstrap/server/src/platform/leon3.cc new file mode 100644 index 00000000..19c60ce5 --- /dev/null +++ b/l4/pkg/bootstrap/server/src/platform/leon3.cc @@ -0,0 +1,143 @@ +/** + * \file support_sparc_leon3.cc + * \brief Support for the Sparc LEON3 platform + * + * \date 2010 + * \author Björn Döbel + * + */ +/* + * (c) 2010 Author(s) + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ + +#include + +#include "support.h" + +namespace { +class Platform_leon3 : public Platform_base +{ + bool probe() { return true; } + + enum { + LEON3_NUM_DEVICE_INFO = 64, + + LEON3_APBUART = 0x80000100, + + LEON3_VENDOR_GAISLER = 0x1, + LEON3_VENDOR_ESA = 0x4, + LEON3_DEVICEID_MCTRL = 0xF, + + LEON3_AHB_BAR_MASK_SHIFT = 4, + LEON3_AHB_BAR_MASK_MASK = 0xFFF, + LEON3_AHB_BAR_ADDR_SHIFT = 20, + LEON3_AHB_BAR_ADDR_MASK = 0xFFF, + + LEON3_MEMCFG2 = 0x80000004, + LEON3_MEMCFG2_SDRAMSZ_SHIFT = 23, + LEON3_MEMCFG2_SDRAMSZ_MASK = 7, + LEON3_MEMCFG2_RAMSZ_SHIFT = 9, + LEON3_MEMCFG2_SRAM_DISABLEF = 13, + LEON3_MEMCFG2_RAMSZ_MASK = 0xF, + + AHB_MASTER_TABLE = 0xFFFFF000, + AHB_SLAVE_TABLE = 0xFFFFF800, + }; + + long _ram_area_start; + long _ram_area_size; + + void init() + { + static L4::Uart_leon3 _uart; + static L4::Io_register_block_mmio r(LEON3_APBUART); // XXX hard + _uart.startup(&r); + set_stdio_uart(&_uart); + + puts("Scanning AHB masters..."); + unsigned *idx = (unsigned*)AHB_MASTER_TABLE; + while (*idx != 0) + { + check_device(idx); + } + + puts("Scanning AHB slaves..."); + idx = (unsigned*)AHB_SLAVE_TABLE; + while (*idx != 0) + { + check_device(idx); + } + } + + + void check_device(unsigned *&ahb_idx) + { + short vendor = (*ahb_idx >> 24) & 0xF; + short dev = (*ahb_idx >> 12) & 0xFFF; + + /* Special check: default RAM memory controller -> find out where the RAM area lies and + * how large it is configured to be */ + if ((vendor == (short)LEON3_VENDOR_ESA) && (dev == (short)LEON3_DEVICEID_MCTRL)) + { + unsigned bar2_addr = (*(ahb_idx+6) >> LEON3_AHB_BAR_ADDR_SHIFT) & LEON3_AHB_BAR_ADDR_MASK; + unsigned bar2_mask = (*(ahb_idx+6) >> LEON3_AHB_BAR_MASK_SHIFT) & LEON3_AHB_BAR_MASK_MASK; + _ram_area_start = bar2_addr << 20; + _ram_area_size = ~(bar2_mask << 20); + printf("RAM AREA: [%08lx - %08lx]\n", + _ram_area_start, _ram_area_start + _ram_area_size); + } + print_device(ahb_idx); + } + + void print_device(unsigned *&ahb_idx) + { + short dev = (*ahb_idx >> 24) & 0xF; + short vendor = (*ahb_idx >> 12) & 0xFFF; + printf("dev:vendor %04hx:%04hx\n", dev, vendor); + printf("%08x %08x %08x %08x\n", *ahb_idx, *(ahb_idx+1), *(ahb_idx+2), *(ahb_idx+3)); + ahb_idx += 4; + printf("%08x %08x %08x %08x\n", *ahb_idx, *(ahb_idx+1), *(ahb_idx+2), *(ahb_idx+3)); + ahb_idx += 4; + printf("--------------------------------------\n"); + } + + void setup_memory_map(l4util_mb_info_t *, Region_list *ram, Region_list *) + { + /* § 10.8.2 + SDRAM area is mapped into the upper half of the RAM area defined by BAR2 + register. When the SDRAM enable bit is set in MCFG2, the controller is + enabled and mapped into upper half of the RAM area as long as the SRAM + disable bit is not set. If the SRAM disable bit is set, all access to + SRAM is disabled and the SDRAM banks are mapped into the lower half of + the RAM area. + */ + unsigned mcfg2 = *(unsigned*)LEON3_MEMCFG2; + unsigned ram_size = (mcfg2 >> LEON3_MEMCFG2_RAMSZ_SHIFT) & LEON3_MEMCFG2_RAMSZ_MASK; + unsigned sdram_size = (mcfg2 >> LEON3_MEMCFG2_SDRAMSZ_SHIFT) & LEON3_MEMCFG2_SDRAMSZ_MASK; + + sdram_size = 4 << sdram_size; + + long sdram_base = _ram_area_start; + if (!(mcfg2 & LEON3_MEMCFG2_SRAM_DISABLEF)) + sdram_base = _ram_area_start + ((_ram_area_size + 1) >> 1); + +#ifdef RAM_SIZE_MB + sdram_size = RAM_SIZE_MB; + sdram_base = RAM_BASE; +#endif + + printf("RAM: %4d kB\n", (8192 << ram_size) / 1024); + printf("SDRAM: %4d MB\n", sdram_size); + + ram->add(Region::n(sdram_base, sdram_base + (sdram_size << 20), ".sdram", + Region::Ram)); + } +}; +} + +REGISTER_PLATFORM(Platform_leon3); diff --git a/l4/pkg/bootstrap/server/src/platform/mpc5200.cc b/l4/pkg/bootstrap/server/src/platform/mpc5200.cc new file mode 100644 index 00000000..6da07bfa --- /dev/null +++ b/l4/pkg/bootstrap/server/src/platform/mpc5200.cc @@ -0,0 +1,42 @@ +/** + * \file + * \brief Support for the MPC52000 + * + * \date 2009-02-16 + * \author Sebastian Sumpf + * + */ +/* + * (c) 2009 Author(s) + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ + +#include "support.h" +#include + + +namespace { +class Platform_ppc_mpc52000 : public Platform_base +{ + bool probe() { return true; } + + void init() + { + static L4::Uart_of _uart; + static L4::Io_register_block_mmio r(0); + _uart.startup(&r); + set_stdio_uart(&_uart); + } + void setup_memory_map(l4util_mb_info_t *, + Region_list *, Region_list *) + { + // still done in startup.cc + } +}; +} + +REGISTER_PLATFORM(Platform_ppc_mpc52000); diff --git a/l4/pkg/bootstrap/server/src/platform/om.cc b/l4/pkg/bootstrap/server/src/platform/om.cc new file mode 100644 index 00000000..53f1cb1e --- /dev/null +++ b/l4/pkg/bootstrap/server/src/platform/om.cc @@ -0,0 +1,39 @@ +/** + * \file support_om.cc + * \brief Support for the OpenMoko platform + * + * \date 2008 + * \author Adam Lackorznynski + * + */ +/* + * (c) 2008-2009 Author(s) + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ + + +#include "support.h" + +#include +#include + +namespace { +class Platform_arm_om : public Platform_single_region_ram +{ + bool probe() { return true; } + + void init() + { + static L4::Uart_s3c2410 _uart; + static L4::Io_register_block_mmio r(0x50000000); + _uart.startup(&r); + set_stdio_uart(&_uart); + } +}; +} + +REGISTER_PLATFORM(Platform_arm_om); diff --git a/l4/pkg/bootstrap/server/src/platform/omap.cc b/l4/pkg/bootstrap/server/src/platform/omap.cc new file mode 100644 index 00000000..523a5ae4 --- /dev/null +++ b/l4/pkg/bootstrap/server/src/platform/omap.cc @@ -0,0 +1,46 @@ +/*! + * \file support_beagleboard.cc + * \brief Support for the Beagleboard + * + * \date 2009-08 + * \author Adam Lackorznynski + * + */ +/* + * (c) 2009 Author(s) + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ + +#include "support.h" +#include + +namespace { +class Platform_arm_omap : public Platform_single_region_ram +{ + bool probe() { return true; } + + void init() + { + static L4::Uart_omap35x _uart; +#ifdef PLATFORM_TYPE_beagleboard + static L4::Io_register_block_mmio r(0x49020000); +#elif defined(PLATFORM_TYPE_omap3evm) + static L4::Io_register_block_mmio r(0x4806a000); +#elif defined(PLATFORM_TYPE_omap3_am33xx) + static L4::Io_register_block_mmio r(0x44e09000); +#elif defined(PLATFORM_TYPE_pandaboard) + static L4::Io_register_block_mmio r(0x48020000); +#else +#error Unknown platform +#endif + _uart.startup(&r); + set_stdio_uart(&_uart); + } +}; +} + +REGISTER_PLATFORM(Platform_arm_omap); diff --git a/l4/pkg/bootstrap/server/src/platform/pxa.cc b/l4/pkg/bootstrap/server/src/platform/pxa.cc new file mode 100644 index 00000000..3ed17c0b --- /dev/null +++ b/l4/pkg/bootstrap/server/src/platform/pxa.cc @@ -0,0 +1,36 @@ +/*! + * \file support_pxa.cc + * \brief Support for the PXA platform + * + * \date 2008-01-04 + * \author Adam Lackorznynski + * + */ +/* + * (c) 2008-2009 Author(s) + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ + +#include +#include "support.h" + +namespace { +class Platform_arm_pxa : public Platform_single_region_ram +{ + bool probe() { return true; } + + void init() + { + static L4::Uart_16550 _uart(L4::Uart_16550::Base_rate_pxa); + static L4::Io_register_block_mmio regs(0x40100000, 2); + _uart.startup(®s); + set_stdio_uart(&_uart); + } +}; +} + +REGISTER_PLATFORM(Platform_arm_pxa); diff --git a/l4/pkg/bootstrap/server/src/platform/rv.cc b/l4/pkg/bootstrap/server/src/platform/rv.cc new file mode 100644 index 00000000..2d992ba0 --- /dev/null +++ b/l4/pkg/bootstrap/server/src/platform/rv.cc @@ -0,0 +1,36 @@ +/*! + * \file support_rv.cc + * \brief Support for the rv platform + * + * \date 2008-01-02 + * \author Adam Lackorznynski + * + */ +/* + * (c) 2008-2009 Author(s) + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ + +#include "support.h" + +#include + +namespace { +class Platform_arm_rv : public Platform_single_region_ram +{ + bool probe() { return true; } + void init() + { + static L4::Io_register_block_mmio r(0x10009000); + static L4::Uart_pl011 _uart; + _uart.startup(&r); + set_stdio_uart(&_uart); + } +}; +} + +REGISTER_PLATFORM(Platform_arm_rv); diff --git a/l4/pkg/bootstrap/server/src/platform/sa1000.cc b/l4/pkg/bootstrap/server/src/platform/sa1000.cc new file mode 100644 index 00000000..e8b15317 --- /dev/null +++ b/l4/pkg/bootstrap/server/src/platform/sa1000.cc @@ -0,0 +1,37 @@ +/*! + * \file support_sa1000.cc + * \brief Support for SA1000 platform + * + * \date 2008-01-02 + * \author Adam Lackorznynski + * + */ +/* + * (c) 2008-2009 Author(s) + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ + +#include "support.h" +#include + +namespace { +class Platform_arm_sa1000 : public Platform_single_region_ram +{ + bool probe() { return true; } + + void init() + { + static L4::Uart_sa1000 _uart; + static L4::Io_register_block_mmio r(0x80010000); + //static L4::Io_register_block_mmio r(0x80050000); + _uart.startup(&r); + set_stdio_uart(&_uart); + } +}; +} + +REGISTER_PLATFORM(Platform_arm_sa1000); diff --git a/l4/pkg/bootstrap/server/src/platform/tegra2.cc b/l4/pkg/bootstrap/server/src/platform/tegra2.cc new file mode 100644 index 00000000..096fee4e --- /dev/null +++ b/l4/pkg/bootstrap/server/src/platform/tegra2.cc @@ -0,0 +1,88 @@ +/*! + * \file + * \brief Support for Tegra 2 platforms + * + * \date 2010-05 + * \author Adam Lackorznynski + * + */ +/* + * (c) 2010 Author(s) + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ + +/* Init-code from http://android.git.kernel.org/?p=kernel/tegra.git */ + +#include "support.h" +#include + +namespace { +class Platform_arm_tegra2 : public Platform_base +{ +private: + void some_delay(int d) const + { + for (int i = 0; i < d; i++) + asm volatile("":::"memory"); + } + +public: + bool probe() { return true; } + + void init() + { + volatile unsigned long *addr; + + addr = (volatile unsigned long *)0x600060a0; + *addr = 0x5011b00c; + + /* PLLP_OUTA_0 */ + addr = (volatile unsigned long *)0x600060a4; + *addr = 0x10031c03; + + /* PLLP_OUTB_0 */ + addr = (volatile unsigned long *)0x600060a8; + *addr = 0x06030a03; + + /* PLLP_MISC_0 */ + addr = (volatile unsigned long *)0x600060ac; + *addr = 0x00000800; + + some_delay(1000000); + + /* UARTD clock source is PLLP_OUT0 */ + addr = (volatile unsigned long *)0x600061c0; + *addr = 0; + + /* Enable clock to UARTD */ + addr = (volatile unsigned long *)0x60006018; + *addr |= 2; + some_delay(5000); + + /* Deassert reset to UARTD */ + addr = (volatile unsigned long *)0x6000600c; + *addr &= ~2; + + some_delay(5000); + + static L4::Uart_16550 _uart(L4::Uart_16550::Base_rate_pxa); + static L4::Io_register_block_mmio r(0x70006300, 2); + _uart.startup(&r); + _uart.change_mode(3, 7876); + set_stdio_uart(&_uart); + } + + void setup_memory_map(l4util_mb_info_t *, + Region_list *ram, Region_list *) + { + ram->add(Region::n(0x0, 448 << 20, ".ram", Region::Ram)); + ram->add(Region::n(512 << 20, 1024 << 20, ".ram", Region::Ram)); + } +}; +} + +REGISTER_PLATFORM(Platform_arm_tegra2); diff --git a/l4/pkg/bootstrap/server/src/platform/x86_pc.cc b/l4/pkg/bootstrap/server/src/platform/x86_pc.cc new file mode 100644 index 00000000..428898ae --- /dev/null +++ b/l4/pkg/bootstrap/server/src/platform/x86_pc.cc @@ -0,0 +1,676 @@ +/*! + * \file support_x86.cc + * \brief Support for the x86 platform + * + * \date 2008-01-02 + * \author Adam Lackorznynski + * + */ +/* + * (c) 2008-2009 Author(s) + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ + +#include "support.h" +#include +#include + +#include +#include "base_critical.h" +#include "startup.h" +#include +#include +#include +#include +#include + + +/** VGA console output */ + +static void vga_init() +{ + /* Reset any scrolling */ + l4util_out32(0xc, 0x3d4); + l4util_out32(0, 0x3d5); + l4util_out32(0xd, 0x3d4); + l4util_out32(0, 0x3d5); +} + +static void vga_putchar(unsigned char c) +{ + static int ofs = -1, esc, esc_val, attr = 0x07; + unsigned char *vidbase = (unsigned char*)0xb8000; + + base_critical_enter(); + + if (ofs < 0) + { + /* Called for the first time - initialize. */ + ofs = 80*2*24; + vga_putchar('\n'); + } + + switch (esc) + { + case 1: + if (c == '[') + { + esc++; + goto done; + } + esc = 0; + break; + + case 2: + if (c >= '0' && c <= '9') + { + esc_val = 10*esc_val + c - '0'; + goto done; + } + if (c == 'm') + { + attr = esc_val ? 0x0f : 0x07; + goto done; + } + esc = 0; + break; + } + + switch (c) + { + case '\n': + memmove(vidbase, vidbase+80*2, 80*2*24); + memset(vidbase+80*2*24, 0, 80*2); + /* fall through... */ + case '\r': + ofs = 0; + break; + + case '\t': + ofs = (ofs + 8) & ~7; + break; + + case '\033': + esc = 1; + esc_val = 0; + break; + + default: + /* Wrap if we reach the end of a line. */ + if (ofs >= 80) + vga_putchar('\n'); + + /* Stuff the character into the video buffer. */ + { + volatile unsigned char *p = vidbase + 80*2*24 + ofs*2; + p[0] = c; + p[1] = attr; + ofs++; + } + break; + } + +done: + base_critical_leave(); +} + +/** Poor man's getchar, only returns raw scan code. We don't need to know + * _which_ key was pressed, we only want to know _if_ a key was pressed. */ +static int raw_keyboard_getscancode(void) +{ + unsigned status, scan_code; + + base_critical_enter(); + + l4util_cpu_pause(); + + /* Wait until a scan code is ready and read it. */ + status = l4util_in8(0x64); + if ((status & 0x01) == 0) + { + base_critical_leave(); + return -1; + } + scan_code = l4util_in8(0x60); + + /* Drop mouse events */ + if ((status & 0x20) != 0) + { + base_critical_leave(); + return -1; + } + + base_critical_leave(); + return scan_code; +} + + +static inline l4_uint32_t +pci_conf_addr(l4_uint32_t bus, l4_uint32_t dev, l4_uint32_t fn, l4_uint32_t reg) +{ return 0x80000000 | (bus << 16) | (dev << 11) | (fn << 8) | (reg & ~3); } + +static l4_uint32_t pci_read(unsigned char bus, l4_uint32_t dev, + l4_uint32_t fn, l4_uint32_t reg, + unsigned char width) +{ + l4util_out32(pci_conf_addr(bus, dev, fn, reg), 0xcf8); + + switch (width) + { + case 8: return l4util_in8(0xcfc + (reg & 3)); + case 16: return l4util_in16((0xcfc + (reg & 3)) & ~1UL); + case 32: return l4util_in32(0xcfc); + } + return 0; +} + +static void pci_write(unsigned char bus, l4_uint32_t dev, + l4_uint32_t fn, l4_uint32_t reg, + l4_uint32_t val, unsigned char width) +{ + l4util_out32(pci_conf_addr(bus, dev, fn, reg), 0xcf8); + + switch (width) + { + case 8: l4util_out8(val, 0xcfc + (reg & 3)); break; + case 16: l4util_out16(val, (0xcfc + (reg & 3)) & ~1UL); break; + case 32: l4util_out32(val, 0xcfc); break; + } +} + +static void pci_enable_io(unsigned char bus, l4_uint32_t dev, + l4_uint32_t fn) +{ + unsigned cmd = pci_read(bus, dev, fn, 4, 16); + pci_write(bus, dev, fn, 4, cmd | 1, 16); +} + +namespace { + +struct Resource +{ + enum Type { NO_BAR, IO_BAR, MEM_BAR }; + Type type; + unsigned long base; + unsigned long len; + Resource() : type(NO_BAR) {} +}; + +enum { NUM_BARS = 6 }; + +struct Serial_board +{ + int num_ports; + int first_bar; + bool port_per_bar; + Resource bars[NUM_BARS]; + + unsigned long get_port(int idx) + { + if (idx >= num_ports) + return 0; + + if (port_per_bar) + return bars[first_bar + idx].base; + + return bars[first_bar].base + 8 * idx; + } +}; + + +} + +static +int pci_handle_serial_dev(unsigned char bus, l4_uint32_t dev, + l4_uint32_t subdev, bool print, + Serial_board *board) +{ +#if 0 + bool dev_enabled = false; +#endif + + // read bars + int num_iobars = 0; + int num_membars = 0; + int first_port = -1; + for (int bar = 0; bar < NUM_BARS; ++bar) + { + int a = 0x10 + bar * 4; + + unsigned v = pci_read(bus, dev, subdev, a, 32); + pci_write(bus, dev, subdev, a, ~0U, 32); + unsigned x = pci_read(bus, dev, subdev, a, 32); + pci_write(bus, dev, subdev, a, v, 32); + + if (!v) + continue; + + int s; + for (s = 2; s < 32; ++s) + if ((x >> s) & 1) + break; + + board->bars[bar].base = v & ~3UL; + board->bars[bar].len = 1 << s; + board->bars[bar].type = (v & 1) ? Resource::IO_BAR : Resource::MEM_BAR; + + if (print) + printf("BAR%d: %04x (sz=%d)\n", bar, v & ~3, 1 << s); + + switch (board->bars[bar].type) + { + case Resource::IO_BAR: + ++num_iobars; + if (first_port == -1) + first_port = bar; + break; + case Resource::MEM_BAR: + ++num_membars; + break; + default: + break; + } + } + + if (num_membars <= 1 && num_iobars == 1) + { + board->first_bar = first_port; + board->num_ports = board->bars[first_port].len / 8; + board->port_per_bar = false; + pci_enable_io(bus, dev, subdev); + return 1; + } + + + board->num_ports = 0; + board->first_bar = -1; + + for (int bar = 0; bar < NUM_BARS; ++bar) + { + if (board->bars[bar].type == Resource::IO_BAR && board->bars[bar].len == 8 + && (board->first_bar == -1 + || (board->first_bar + board->num_ports) == bar)) + { + ++board->num_ports; + if (board->first_bar == -1) + board->first_bar = bar; + } + } + + board->port_per_bar = true; + return board->num_ports; + +#if 0 + + // for now we only take IO-BARs of size 8 + if (v & 1) + { + + if (!scan_only && !dev_enabled) + { + pci_enable_io(bus, dev, subdev); + dev_enabled = true; + } + + if (scan_only) + printf("BAR%d: %04x (sz=%d)\n", bar, v & ~3, 1 << s); + + if (s == 3) + { + if (scan_only) + printf(" Potential serial port\n"); + else + return v & ~3; + } + } + else + if (scan_only) + printf("BAR%d: %08x (sz=%d)\n", bar, v & ~0xf, 1 << s); + } + return 0; +#endif +} + +static unsigned long +_search_pci_serial_devs(Serial_board *board, unsigned look_for_subclass, + bool print) +{ + l4_umword_t bus, buses, dev; + + for (bus=0, buses=20; busshutdown(); + if (_u2) + _u2->shutdown(); + } + + ~Dual_uart() {} +#if 0 + bool enable_rx_irq(bool e) + { + bool r1 = _u1->enable_rx_irq(e); + bool r2 = _u2 ? _u2->enable_rx_irq(e) : false; + return r1 && r2; + } + + bool enable_tx_irq(bool e) + { + bool r1 = _u1->enable_tx_irq(e); + bool r2 = _u2 ? _u2->enable_tx_irq(e) : false; + return r1 && r2; + } +#endif + + bool change_mode(Transfer_mode m, Baud_rate r) + { + bool r1 = _u1->change_mode(m, r); + bool r2 = _u2 ? _u2->change_mode(m, r) : false; + return r1 && r2; + } + + int char_avail() const + { + return _u1->char_avail() || (_u2 && _u2->char_avail()); + } + + int get_char(bool blocking) const + { + int c; + do + { + c = _u1->get_char(false); + if (c == -1 && _u2) + c = _u2->get_char(false); + } + while (blocking && c == -1); + return c; + } + + int write(char const *s, unsigned long count) const + { + int r = _u1->write(s, count); + if (_u2) + _u2->write(s, count); + return r; + } + +}; + +l4util_mb_info_t *x86_bootloader_mbi; + +namespace { + +class Platform_x86 : public Platform_base +{ +public: + bool probe() { return true; } + + int init_uart(int com_port_or_base, int com_irq, Dual_uart *du) + { + base_critical_enter(); + + switch (com_port_or_base) + { + case 1: com_port_or_base = 0x3f8; + if (com_irq == -1) + com_irq = 4; + break; + case 2: com_port_or_base = 0x2f8; + if (com_irq == -1) + com_irq = 3; + break; + case 3: com_port_or_base = 0x3e8; break; + case 4: com_port_or_base = 0x2e8; break; + } + + unsigned baudrate = 115200; + static L4::Io_register_block_port uart_regs(com_port_or_base); + static L4::Uart_16550 _uart(L4::Uart_16550::Base_rate_x86); + if ( !_uart.startup(&uart_regs) + || !_uart.change_mode(L4::Uart_16550::MODE_8N1, baudrate)) + { + printf("Could not find or enable UART\n"); + base_critical_leave(); + return 1; + } + + du->set_uart2(&_uart); + + kuart.access_type = L4_kernel_options::Uart_type_ioport; + kuart.irqno = com_irq; + kuart.base_address = com_port_or_base; + kuart.baud = baudrate; + kuart_flags |= L4_kernel_options::F_uart_base + | L4_kernel_options::F_uart_baud; + if (com_irq != -1) + kuart_flags |= L4_kernel_options::F_uart_irq; + + base_critical_leave(); + return 0; + } + + void init() + { + const char *s; + int comport = -1; + int comirq = -1; + int pci = 0; + + static Uart_vga _vga; + static Dual_uart du(&_vga); + set_stdio_uart(&du); + + if ((s = check_arg(x86_bootloader_mbi, "-comirq"))) + { + s += 8; + comirq = strtoul(s, 0, 0); + } + + if ((s = check_arg(x86_bootloader_mbi, "-comport"))) + { + s += 9; + if ((pci = !strncmp(s, "pci:", 4))) + s += 4; + + comport = strtoul(s, 0, 0); + } + + if (!check_arg(x86_bootloader_mbi, "-noserial")) + { + if (pci) + { + if (unsigned long port = search_pci_serial_devs(comport)) + comport = port; + else + comport = -1; + + printf("PCI IO port = %x\n", comport); + } + + if (comport == -1) + comport = 1; + + if (init_uart(comport, comirq, &du)) + printf("UART init failed\n"); + } + } + + void setup_memory_map(l4util_mb_info_t *mbi, + Region_list *ram, Region_list *regions) + { + if (!(mbi->flags & L4UTIL_MB_MEM_MAP)) + { + assert(mbi->flags & L4UTIL_MB_MEMORY); + ram->add(Region::n(0, (mbi->mem_upper + 1024) << 10, ".ram", + Region::Ram)); + } + else + { + l4util_mb_addr_range_t *mmap; + l4util_mb_for_each_mmap_entry(mmap, mbi) + { + unsigned long long start = (unsigned long long)mmap->addr; + unsigned long long end = (unsigned long long)mmap->addr + mmap->size; + + switch (mmap->type) + { + case 1: + ram->add(Region::n(start, end, ".ram", Region::Ram)); + break; + case 2: + case 3: + case 4: + regions->add(Region::n(start, end, ".BIOS", Region::Arch, mmap->type)); + break; + case 5: + regions->add(Region::n(start, end, ".BIOS", Region::No_mem)); + break; + default: + break; + } + } + } + + regions->add(Region::n(0, 0x1000, ".BIOS", Region::Arch, 0)); + + + // Quirks + + // Fix EBDA in conventional memory + unsigned long p = *(l4_uint16_t *)0x40e << 4; + + if (p > 0x400) + { + unsigned long e = p + 1024; + Region *r = ram->find(Region(p, e - 1)); + if (r) + { + if (e - 1 < r->end()) + ram->add(Region::n(e, r->end(), ".ram", Region::Ram)); + r->end(p); + } + } + } +}; +} + +REGISTER_PLATFORM(Platform_x86); + diff --git a/l4/pkg/bootstrap/server/src/region.cc b/l4/pkg/bootstrap/server/src/region.cc new file mode 100644 index 00000000..ea1b18ff --- /dev/null +++ b/l4/pkg/bootstrap/server/src/region.cc @@ -0,0 +1,269 @@ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg , + * Frank Mehnert + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ +#include +#include +#include + +#include "panic.h" +#include + +#include "region.h" +#include "module.h" + +bool +Region_list::test_fit(unsigned long long start, unsigned long long _size) +{ + Region r(start, start + _size); + for (Region const *c = _reg; c < _end; ++c) + { + if (0) + printf("test [%p-%p] [%llx-%llx]\n", + (char *)start, (char *)start + _size, c->begin(), c->end()); + + if (c->overlaps(r)) + return false; + } + return true; +} + +unsigned long long +Region_list::next_free(unsigned long long start) +{ + unsigned long long s = ~0ULL, e = ~0ULL; + for (Region const *c = _reg; c < _end; ++c) + { + e = c->end(); + if (e > start && e < s) + s = e; + } + + if (s == ~0ULL) + return e; + + return s; +} + +unsigned long long +Region_list::find_free(Region const &search, unsigned long long _size, + unsigned align) +{ + unsigned long long start = search.begin(); + unsigned long long end = search.end(); + while (1) + { + start = (start + (1ULL << align) -1) & ~((1ULL << align)-1); + + if (start + _size - 1 > end) + return 0; + + if (0) + printf("try start %p\n", (void *)start); + + if (test_fit(start, _size)) + return start; + + start = next_free(start); + } +} + +void +Region_list::add_nolimitcheck(Region const ®ion, bool may_overlap) +{ + Region const *r; + + /* Do not add empty regions */ + if (region.begin() == region.end()) + return; + + if (_end >= _max) + panic("Bootstrap: %s: Region overflow\n", __func__); + + if (!may_overlap && (r = find(region)) + // sometimes there are smaller regions in regions of the same type + && !( r->contains(region) + && region.type() == r->type())) + { + printf(" New region for list %s:\t", _name); + region.vprint(); + printf(" overlaps with: \t"); + r->vprint(); + + dump(); + panic("region overlap"); + } + + *_end = region; + ++_end; +} + +void +Region_list::add(Region const ®ion, bool may_overlap) +{ + Region mem = region; + + if (mem.invalid()) + { + printf(" WARNING: trying to add invalid region to %s list.\n", _name); + return; + } + + if (mem.begin() >= _upper_limit) + { + printf(" Dropping %s region ", _name); + mem.print(); + printf(" due to %lld MB limit\n", _upper_limit >> 20); + return; + } + + if (mem.end() >= _upper_limit - 1) + { + printf(" Limiting %s region ", _name); + mem.print(); + mem.end(_upper_limit - 1); + printf(" to "); + mem.print(); + printf(" due to %lld MB limit\n", _upper_limit >> 20); + } + + add_nolimitcheck(mem, may_overlap); +} + +Region * +Region_list::find(Region const &o) +{ + for (Region *c = _reg; c < _end; ++c) + if (c->overlaps(o)) + return c; + + return 0; +} + +Region * +Region_list::contains(Region const &o) +{ + for (Region *c = _reg; c < _end; ++c) + if (c->contains(o)) + return c; + + return 0; +} + +void +Region::print() const +{ + printf(" [%9llx, %9llx] {%9llx}", begin(), end(), end() - begin() + 1); +} + +void +Region::vprint() const +{ + static char const *types[] = {"Gap ", "Kern ", "Sigma0", + "Boot ", "Root ", "Arch ", "Ram " }; + printf(" "); + print(); + printf(" %s ", types[type()]); + if (name()) + { + if (*name() == '.') + printf("%s", name() + 1); + else + print_module_name(name(), ""); + } + putchar('\n'); +} + +void +Region_list::dump() +{ + Region const *i; + Region const *j; + Region const *min_idx; + unsigned long long min, mark = 0; + + printf("Regions of list '%s'\n", _name); + for (i = _reg; i < _end; ++i) + { + min = ~0; + min_idx = 0; + for (j = _reg; j < _end; ++j) + if (j->begin() < min && j->begin() >= mark) + { + min = j->begin(); + min_idx = j; + } + if (!min_idx) + printf("Check region dump\n"); + min_idx->vprint(); + mark = min_idx->begin() + 1; + } +} + +void +Region_list::swap(Region *a, Region *b) +{ + Region t = *a; *a = *b; *b = t; +} + +void +Region_list::sort() +{ + if (end() - begin() < 2) + return; + bool swapped; + + Region *e = end() - 1; + + do + { + swapped = false; + for (Region *c = begin(); c < e; ++c) + { + Region *n = c; ++n; + if (*n < *c) + { + swap(c,n); + swapped = true; + } + } + } + while (swapped); +} + +void +Region_list::remove(Region *r) +{ + memmove(r, r+1, (end() - r - 1)*sizeof(Region)); + --_end; +} + +void +Region_list::optimize() +{ + sort(); + Region *c = begin(); + while (c < end()) + { + Region *n = c; ++n; + if (n == end()) + return; + + if (n->type() == c->type() && n->sub_type() == c->sub_type() + && n->name() == c->name() && + l4_round_page(c->end()) >= l4_trunc_page(n->begin())) + { + c->end(n->end()); + remove(n); + } + else + ++c; + } +} + diff --git a/l4/pkg/bootstrap/server/src/region.h b/l4/pkg/bootstrap/server/src/region.h new file mode 100644 index 00000000..0890280a --- /dev/null +++ b/l4/pkg/bootstrap/server/src/region.h @@ -0,0 +1,194 @@ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg , + * Frank Mehnert + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ +#ifndef REGION_H +#define REGION_H + +#include +#include + +#include "types.h" + +/** Region in memory. */ +class Region +{ +public: + enum Type { No_mem, Kernel, Sigma0, Boot, Root, Arch, Ram }; + + /** Basic noop constructor, to be able to have array without ini code */ + Region() {} + + /** Create an invalid region. */ + Region(Type) : _begin(0), _end(0) {} + + /** Create a 1byte region at begin, basically for lookups */ + Region(unsigned long long begin) + : _begin(begin), _end(begin), _name(0), _t(No_mem), _s(0) + {} + + /** Create a fully fledged region. + * @param begin The start address. + * @param end The address of the last byte in the region. + * @param name The name for the region (usually the binary name). + * @param t The type of the region. + * @param sub The subtype of the region. + */ + Region(unsigned long long begin, unsigned long long end, + char const *name = 0, Type t = No_mem, char sub = 0) + : _begin(begin), _end(end), _name(name), _t(t), _s(sub) + {} + + /** + * Create a region... + * @param begin The start address. + * @param end The address of the first byte after the region. + * @param name The name for the region (usually the binary name). + * @param t The type of the region. + * @param sub The subtype of the region. + */ + static Region n(unsigned long long begin, + unsigned long long end, char const *name = 0, + Type t = No_mem, char sub = 0) + { return Region(begin, end - 1, name, t, sub); } + + /** Get the start address. */ + unsigned long long begin() const { return _begin; } + /** Get the address of the last byte. */ + unsigned long long end() const { return _end; } + /** Set the start address. */ + void begin(unsigned long long b) { _begin = b; } + /** Set the address of the last byte. */ + void end(unsigned long long e) { _end = e; } + /** Get the name of the region. */ + char const *name() const { return _name; } + /** Set the name of the region. */ + void name(char const *name) { _name = name; } + /** Get the type of the region. */ + Type type() const { return (Type)(_t); } + /** Get the subtype of the region. */ + char sub_type() const { return _s; } + + /** Print the region [begin; end] */ + void print() const; + + /** Print the region verbose (with name and type). */ + void vprint() const; + + /** Compare two regions. */ + bool operator < (Region const &o) const + { return end() < o.begin(); } + + /** Check for an overlap. */ + bool overlaps(Region const &o) const + { return !(*this < o) && !(o < *this); } + + /** Test if o is a sub-region of ourselves. */ + bool contains(Region const &o) const + { return begin() <= o.begin() && end() >= o.end(); } + + /** Calculate the intersection. */ + Region intersect(Region const &o) const + { + if (!overlaps(o)) + return Region(No_mem); + + return Region(begin() > o.begin() ? begin() : o.begin(), + end() < o.end() ? end() : o.end(), + name(), type(), sub_type()); + } + + /** Check if the region is invalid */ + bool invalid() const { return begin()==0 && end()==0; } + +private: + unsigned long long _begin, _end; + char const *_name; + char _t, _s; +}; + + +/** List of memory regions, based on an fixed size array. */ +class Region_list +{ +public: + /** + * Initialize the region list, using the array of given size + * as backing store. + */ + void init(Region *store, unsigned size, + const char *name, + unsigned long long upper_limit = ~0ULL) + { + _reg = _end = store; + _max = _reg + size; + _name = name; + _upper_limit = upper_limit; + } + + /** Search for a region that overlaps o. */ + Region *find(Region const &o); + + /** Search for the region that contains o. */ + Region *contains(Region const &o); + + /** + * Search for a memory region not overlapping any known region, + * within search. + */ + unsigned long long find_free(Region const &search, + unsigned long long size, unsigned align); + + /** + * Add a new memory region to the list. The new region must not overlap + * any known region. + */ + void add_nolimitcheck(Region const &r, bool may_overlap = false); + + /** + * Add a new region, with a upper limit check and verboseness. + */ + void add(Region const &r, bool may_overlap = false); + + /** Dump the whole region list. */ + void dump(); + + /** Get the begin() iterator. */ + Region *begin() const { return _reg; } + /** Get the end() iterator. */ + Region *end() const { return _end; } + + /** Remove the region given by the iterator r. */ + void remove(Region *r); + + /** Sort the region list (does bubble sort). */ + void sort(); + + /** Optimize the region list. + * Basically merges all regions with the same type, subtype, and name + * that have a begin and end address on the same memory page. + */ + void optimize(); + +protected: + Region *_end; + Region *_max; + Region *_reg; + + const char *_name; + unsigned long long _upper_limit; + +private: + void swap(Region *a, Region *b); + unsigned long long next_free(unsigned long long start); + bool test_fit(unsigned long long start, unsigned long long _size); + +}; + +#endif diff --git a/l4/pkg/bootstrap/server/src/startup.cc b/l4/pkg/bootstrap/server/src/startup.cc new file mode 100644 index 00000000..67f5e83b --- /dev/null +++ b/l4/pkg/bootstrap/server/src/startup.cc @@ -0,0 +1,1489 @@ +/** + * \file bootstrap/server/src/startup.c + * \brief Main functions + * + * \date 09/2004 + * \author Torsten Frenzel , + * Frank Mehnert , + * Adam Lackorzynski + * Alexander Warg + * Sebastian Sumpf + */ + +/* + * (c) 2005-2009 Author(s) + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ + +/* LibC stuff */ +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif +#include +#include +#include +#include +#include + +/* L4 stuff */ +#include +#include +#include +#include "panic.h" + +/* local stuff */ +#include "exec.h" +#include "macros.h" +#include "region.h" +#include "module.h" +#include "startup.h" +#include "support.h" +#include "init_kip.h" +#include "patch.h" +#include "loader_mbi.h" +#include "startup.h" +#include "koptions.h" + +#if defined (ARCH_ppc32) +#include +#include +#endif + +#undef getchar + +enum { Verbose_load = 0 }; + +static l4util_mb_info_t *mb_info; +/* management of allocated memory regions */ +static Region_list regions; +static Region __regs[300]; + +/* management of conventional memory regions */ +static Region_list ram; +static Region __ram[8]; + +#if defined(ARCH_x86) || defined(ARCH_amd64) +static l4util_mb_vbe_mode_t __mb_vbe; +static l4util_mb_vbe_ctrl_t __mb_ctrl; +#endif + +L4_kernel_options::Uart kuart; +unsigned int kuart_flags; + +/* + * IMAGE_MODE means that all boot modules are linked together to one + * big binary. + */ +#ifdef IMAGE_MODE +static l4_addr_t _mod_addr = RAM_BASE + MODADDR; +#else +static l4_addr_t _mod_addr; +#endif + +static const char *builtin_cmdline = CMDLINE; + +/* modules to load by bootstrap */ +static int sigma0 = 1; /* we need sigma0 */ +static int roottask = 1; /* we need a roottask */ + +enum { + kernel_module, + sigma0_module, + roottask_module, +}; + +/* we define a small stack for sigma0 and roottask here -- it is used by L4 + * for parameter passing. however, sigma0 and roottask must switch to its + * own private stack as soon as it has initialized itself because this memory + * region is later recycled in init.c */ +static char roottask_init_stack[64]; /* XXX hardcoded */ +static char sigma0_init_stack[64]; /* XXX hardcoded */ + + +static exec_handler_func_t l4_exec_read_exec; +static exec_handler_func_t l4_exec_add_region; + + +#if 0 +static void +dump_mbi(l4util_mb_info_t *mbi) +{ + printf("%p-%p\n", (void*)(mbi->mem_lower << 10), (void*)(mbi->mem_upper << 10)); + printf("MBI: [%p-%p]\n", mbi, mbi + 1); + printf("MODINFO: [%p-%p]\n", (char*)mbi->mods_addr, + (l4util_mb_mod_t*)(mbi->mods_addr) + mbi->mods_count); + + printf("VBEINFO: [%p-%p]\n", (char*)mbi->vbe_ctrl_info, + (l4util_mb_vbe_ctrl_t*)(mbi->vbe_ctrl_info) + 1); + printf("VBEMODE: [%p-%p]\n", (char*)mbi->vbe_mode_info, + (l4util_mb_vbe_mode_t*)(mbi->vbe_mode_info) + 1); + + l4util_mb_mod_t *m = (l4util_mb_mod_t*)(mbi->mods_addr); + l4util_mb_mod_t *me = m + mbi->mods_count; + for (; m < me; ++m) + { + printf(" MOD: [%p-%p]\n", (void*)m->mod_start, (void*)m->mod_end); + printf(" CMD: [%p-%p]\n", (char*)m->cmdline, + (char*)m->cmdline + strlen((char*)m->cmdline)); + } +} +#endif + + +/** + * Scan the memory regions with type == Region::Kernel for a + * kernel interface page (KIP). + * + * After loading the kernel we scan for the magic number at page boundaries. + */ +static +void *find_kip() +{ + unsigned char *p, *end; + void *k = 0; + + printf(" find kernel info page...\n"); + for (Region const *m = regions.begin(); m != regions.end(); ++m) + { + if (m->type() != Region::Kernel) + continue; + + if (sizeof(unsigned long) < 8 + && m->end() >= (1ULL << 32)) + end = (unsigned char *)(~0UL - 0x1000); + else + end = (unsigned char *) (unsigned long)m->end(); + + for (p = (unsigned char *) (unsigned long)(m->begin() & 0xfffff000); + p < end; + p += 0x1000) + { + l4_umword_t magic = L4_KERNEL_INFO_MAGIC; + if (memcmp(p, &magic, 4) == 0) + { + k = p; + printf(" found kernel info page at %p\n", p); + break; + } + } + } + + if (!k) + panic("could not find kernel info page, maybe your kernel is too old"); + + return k; +} + +static +L4_kernel_options::Options *find_kopts(void *kip) +{ + unsigned long a = (unsigned long)kip + sizeof(l4_kernel_info_t); + + // kernel-option directly follow the KIP page + a = (a + 4096 - 1) & ~0xfff; + + L4_kernel_options::Options *ko = (L4_kernel_options::Options *)a; + + if (ko->magic != L4_kernel_options::Magic) + panic("Could not find kernel options page"); + + return ko; +} + +const char *get_cmdline(l4util_mb_info_t *mbi) +{ + if (mbi && mbi->flags & L4UTIL_MB_CMDLINE) + return L4_CHAR_PTR(mbi->cmdline); + + if (*builtin_cmdline) + return builtin_cmdline; + + return 0; +} + +/** + * Get the API version from the KIP. + */ +static inline +unsigned long get_api_version(void *kip) +{ + return ((unsigned long *)kip)[1]; +} + + +static char * +check_arg_str(char *cmdline, const char *arg) +{ + char *s = cmdline; + while ((s = strstr(s, arg))) + { + if (s == cmdline + || isspace(s[-1])) + return s; + } + return NULL; +} + +/** + * Scan the command line for the given argument. + * + * The cmdline string may either be including the calling program + * (.../bootstrap -arg1 -arg2) or without (-arg1 -arg2) in the realmode + * case, there, we do not have a leading space + * + * return pointer after argument, NULL if not found + */ +char * +check_arg(l4util_mb_info_t *mbi, const char *arg) +{ + const char *c = get_cmdline(mbi); + if (c) + return check_arg_str((char *)c, arg); + + return NULL; +} + + +/** + * Calculate the maximum memory limit in MB. + * + * The limit is the highes physical address where conventional RAM is allowed. + * + * If available the '-maxmem=xx' command line option is used. + * If not then the memory is limited to 3 GB IA32 and unlimited on other + * systems. + */ +static +unsigned long +get_memory_limit(l4util_mb_info_t *mbi) +{ + unsigned long arch_limit = ~0UL; +#if defined(ARCH_x86) + /* Limit memory, we cannot really handle more right now. In fact, the + * problem is roottask. It maps as many superpages/pages as it gets. + * After that, the remaining pages are mapped using l4sigma0_map_anypage() + * with a receive window of L4_WHOLE_ADDRESS_SPACE. In response Sigma0 + * could deliver pages beyond the 3GB user space limit. */ + arch_limit = 3024UL << 20; +#endif + + /* maxmem= parameter? */ + if (char *c = check_arg(mbi, "-maxmem=")) + { + unsigned long l = strtoul(c + 8, NULL, 10) << 20; + if (l < arch_limit) + return l; + } + + return arch_limit; +} + +static int +parse_memvalue(const char *s, unsigned long *val, char **ep) +{ + + *val = strtoul(s, ep, 0); + if (*val == ~0UL) + return 1; + + switch (**ep) + { + case 'G': *val <<= 10; + case 'M': *val <<= 10; + case 'k': case 'K': *val <<= 10; (*ep)++; + }; + + return 0; +} + +/* + * Parse a memory layout string: size@offset + * E.g.: 256M@0x40000000, or 128M@128M + */ +static int +parse_mem_layout(const char *s, unsigned long *sz, unsigned long *offset) +{ + char *ep; + + if (parse_memvalue(s, sz, &ep)) + return 1; + + if (*sz == 0) + return 1; + + if (*ep != '@') + return 1; + + if (parse_memvalue(ep + 1, offset, &ep)) + return 1; + + return 0; +} + +static void +dump_ram_map(bool show_total = false) +{ + // print RAM summary + unsigned long long sum = 0; + for (Region *i = ram.begin(); i < ram.end(); ++i) + { + printf(" RAM: %016llx - %016llx: %lldkB\n", + i->begin(), i->end(), (i->end() - i->begin() + 1) >> 10); + sum += i->end() - i->begin() + 1; + } + if (show_total) + printf(" Total RAM: %lldMB\n", sum >> 20); +} + +static void +setup_memory_map(l4util_mb_info_t *mbi) +{ + bool parsed_mem_option = false; + const char *s = get_cmdline(mbi); + + if (s) + { + while ((s = check_arg_str((char *)s, "-mem="))) + { + s += 5; + unsigned long sz, offset = 0; + if (!parse_mem_layout(s, &sz, &offset)) + { + parsed_mem_option = true; + ram.add(Region::n(offset, offset + sz, ".ram", Region::Ram)); + } + } + } + + if (!parsed_mem_option) + // No -mem option given, use the one given by the platform + Platform_base::platform->setup_memory_map(mbi, &ram, ®ions); + + dump_ram_map(true); +} + +static void do_the_memset(unsigned long s, unsigned val, unsigned long len) +{ + printf("Presetting memory %16lx - %16lx to '%x'\n", + s, s + len - 1, val); + memset((void *)s, val, len); +} + +static void fill_mem(unsigned fill_value) +{ + regions.sort(); + for (Region const *r = ram.begin(); r != ram.end(); ++r) + { + unsigned long long b = r->begin(); + // The regions list must be sorted! + for (Region const *reg = regions.begin(); reg != regions.end(); ++reg) + { + // completely before ram? + if (reg->end() < r->begin()) + continue; + // completely after ram? + if (reg->begin() > r->end()) + break; + + if (reg->begin() <= r->begin()) + b = reg->end() + 1; + else if (b > reg->begin()) // some overlapping + { + if (reg->end() + 1 > b) + b = reg->end() + 1; + } + else + { + do_the_memset(b, fill_value, reg->begin() - 1 - b + 1); + b = reg->end() + 1; + } + } + + if (b < r->end()) + do_the_memset(b, fill_value, r->end() - b + 1); + } +} + +static void +move_module(l4util_mb_info_t *mbi, int i, Region *from, Region *to, + bool overlap_check) +{ + unsigned long start = from->begin(); + unsigned long size = from->end() - start + 1; + + if (Verbose_load) + { + unsigned char c[5]; + c[0] = *(unsigned char*)(start + 0); + c[1] = *(unsigned char*)(start + 1); + c[2] = *(unsigned char*)(start + 2); + c[3] = *(unsigned char*)(start + 3); + c[4] = 0; + c[0] = c[0] < 32 ? '.' : c[0]; + c[1] = c[1] < 32 ? '.' : c[1]; + c[2] = c[2] < 32 ? '.' : c[2]; + c[3] = c[3] < 32 ? '.' : c[3]; + printf(" moving module %02d { %lx, %llx } (%s) -> { %llx - %llx } [%ld]\n", + i, start, from->end(), c, to->begin(), to->end(), size); + + for (int a = 0; a < 0x100; a += 4) + printf("%08lx%s", *(unsigned long *)(start + a), (a % 32 == 28) ? "\n" : " "); + printf("\n"); + } + else + printf(" moving module %02d { %lx-%llx } -> { %llx-%llx } [%ld]\n", + i, start, from->end(), to->begin(), to->end(), size); + + if (overlap_check) + { + Region *overlap = regions.find(*to); + if (overlap) + { + printf("ERROR: module target [%llx-%llx) overlaps\n", + to->begin(), to->end()); + overlap->vprint(); + panic("can not move module"); + } + } + if (!ram.contains(*to)) + panic("Panic: Would move outside of RAM"); + memmove((void *)to->begin(), (void *)start, size); + unsigned long x = to->end() + 1; + memset((char *)x, 0, l4_round_page(x) - x); + + (L4_MB_MOD_PTR(mbi->mods_addr))[i].mod_start = to->begin(); + (L4_MB_MOD_PTR(mbi->mods_addr))[i].mod_end = to->end() + 1; + from->begin(to->begin()); + from->end(to->end()); +} + +static inline +unsigned long mbi_mod_start(l4util_mb_info_t *mbi, int i) +{ return (L4_MB_MOD_PTR(mbi->mods_addr))[i].mod_start; } + +static inline +unsigned long mbi_mod_end(l4util_mb_info_t *mbi, int i) +{ return (L4_MB_MOD_PTR(mbi->mods_addr))[i].mod_end; } + +static inline +unsigned long mbi_mod_size(l4util_mb_info_t *mbi, int i) +{ return mbi_mod_end(mbi, i) - mbi_mod_start(mbi, i); } + +/** + * Move modules to another address. + * + * Source and destination regions may overlap. + */ +static void +move_modules(l4util_mb_info_t *mbi, unsigned long modaddr) +{ + printf(" Moving modules behind %lx\n", modaddr); + + Region *ramr = ram.find(Region(modaddr, modaddr)); + Region module_area(modaddr, ramr->end(), "ram for modules"); + + unsigned long firstmodulestart = ~0UL, lastmoduleend = 0; + for (unsigned i = 0; i < mbi->mods_count; ++i) + { + if (lastmoduleend < mbi_mod_end(mbi, i)) + lastmoduleend = mbi_mod_end(mbi, i); + if (firstmodulestart > mbi_mod_start(mbi, i)) + firstmodulestart = mbi_mod_start(mbi, i); + } + lastmoduleend = l4_round_page(lastmoduleend); + if (firstmodulestart < modaddr) + { + Region s(lastmoduleend, ramr->end()); + unsigned long sz = modaddr - firstmodulestart; + lastmoduleend = regions.find_free(s, sz, L4_PAGESHIFT) + sz; + } + + + for (unsigned i = 0; i < mbi->mods_count; ++i) + { + unsigned long start = mbi_mod_start(mbi, i); + unsigned long end = mbi_mod_end(mbi, i); + unsigned long size = mbi_mod_size(mbi, i); + + if (start == end) + continue; + + Region from(start, end - 1); + Region *this_module = regions.find(from); + assert(this_module->begin() == from.begin() + && this_module->end() == from.end()); + + if (i < 3) + { + unsigned long start = mbi_mod_start(mbi, i); + if (start < lastmoduleend) + { + unsigned long end = mbi_mod_end(mbi, i); + + Region to(lastmoduleend, lastmoduleend + (end - start) - 1); + move_module(mbi, i, this_module, &to, true); + lastmoduleend = l4_round_page(this_module->end()); + } + continue; + } + + if (start >= modaddr) + continue; + + unsigned long long to = regions.find_free(module_area, size, L4_PAGESHIFT); + assert(to); + + Region m_to = Region(to, to + size - 1); + move_module(mbi, i, this_module, &m_to, true); + } + + // now everything is behind modaddr -> pull close to modaddr now + // this is optional but avoids holes and gives more consecutive memory + + if (0) + printf(" Compactifying\n"); + + regions.sort(); + unsigned long lastend = modaddr; + for (Region *i = regions.begin(); i < regions.end(); ++i) + { + if (i->begin() < modaddr) + continue; + + // find in mbi + unsigned mi = 0; + for (; mi < mbi->mods_count; ++mi) + if (i->begin() == mbi_mod_start(mbi, mi)) + break; + + if (mi < 3 || mbi->mods_count == mi) + continue; + + unsigned long start = mbi_mod_start(mbi, mi); + unsigned long end = mbi_mod_end(mbi, mi); + + if (start > lastend) + { + Region to(lastend, end - 1 - (start - lastend)); + move_module(mbi, mi, i, &to, false); + end = i->end(); + } + lastend = l4_round_page(end); + } +} + + +/** + * Add the bootstrap binary itself to the allocated memory regions. + */ +static void +init_regions() +{ + extern int _start; /* begin of image -- defined in crt0.S */ + extern int _end; /* end of image -- defined by bootstrap.ld */ + + regions.add(Region::n((unsigned long)&_start, (unsigned long)&_end, + ".bootstrap", Region::Boot)); +} + + +/** + * Add the memory containing the boot modules to the allocated regions. + */ +static void +add_boot_modules_region(l4util_mb_info_t *mbi) +{ + for (unsigned int i = 0; i < mbi->mods_count; ++i) + regions.add(Region(mbi_mod_start(mbi, i), mbi_mod_end(mbi, i) - 1, + ".Module", Region::Root)); +} + + +/** + * Add all sections of the given ELF binary to the allocated regions. + * Actually does not load the ELF binary (see load_elf_module()). + */ +static void +add_elf_regions(l4util_mb_info_t *mbi, l4_umword_t module, + Region::Type type) +{ + exec_task_t exec_task; + l4_addr_t entry; + int r; + const char *error_msg; + l4util_mb_mod_t *mb_mod = (l4util_mb_mod_t*)mbi->mods_addr; + + assert(module < mbi->mods_count); + + exec_task.begin = 0xffffffff; + exec_task.end = 0; + exec_task.type = type; + + exec_task.mod_start = L4_VOID_PTR(mb_mod[module].mod_start); + exec_task.mod = mb_mod + module; + + printf(" Scanning %s\n", L4_CHAR_PTR(mb_mod[module].cmdline)); + + r = exec_load_elf(l4_exec_add_region, &exec_task, + &error_msg, &entry); + + if (r) + { + if (Verbose_load) + { + printf("\n%p: ", exec_task.mod_start); + for (int i = 0; i < 4; ++i) + { + printf("%08lx ", *((unsigned long *)exec_task.mod_start + i)); + } + printf(" "); + for (int i = 0; i < 16; ++i) + { + unsigned char c = *(unsigned char *)((char *)exec_task.mod_start + i); + printf("%c", c < 32 ? '.' : c); + } + } + panic("\n\nThis is an invalid binary, fix it (%s).", error_msg); + } +} + + +/** + * Load the given ELF binary into memory and free the source + * memory region. + */ +static l4_addr_t +load_elf_module(l4util_mb_mod_t *mb_mod) +{ + exec_task_t exec_task; + l4_addr_t entry; + int r; + const char *error_msg; + + exec_task.begin = 0xffffffff; + exec_task.end = 0; + + exec_task.mod_start = L4_VOID_PTR(mb_mod->mod_start); + exec_task.mod = mb_mod; + + r = exec_load_elf(l4_exec_read_exec, &exec_task, + &error_msg, &entry); + +#ifndef RELEASE_MODE + /* clear the image for debugging and security reasons */ + memset(L4_VOID_PTR(mb_mod->mod_start), 0, + mb_mod->mod_end - mb_mod->mod_start); +#endif + + if (r) + printf(" => can't load module (%s)\n", error_msg); + else + { + Region m = Region::n(mb_mod->mod_start, mb_mod->mod_end); + Region *x = regions.find(m); + if (x) + { + if (x->begin() == m.begin()) + { + unsigned long b = l4_round_page(m.end()+1); + if (x->end() <= b) + regions.remove(x); + else + x->begin(b); + } + } + } + + return entry; +} + +/** + * Simple linear memory allocator. + * + * Allocate size bytes startting from *ptr and set *ptr to *ptr + size. + */ +static inline void* +lin_alloc(l4_size_t size, char **ptr) +{ + void *ret = *ptr; + *ptr += (size + 3) & ~3;; + return ret; +} + + +/** + * Duplicate the given command line. + * + * This function is use for relocating the multi-boot info. + * The new location is *ptr and *ptr is incemented by the size of the + * string (basically like lin_alloc() does). + * + * This function also implements the mechanism to replace the command line + * of a module from the bootstrap comand line. + */ +static +char *dup_cmdline(l4util_mb_info_t *mbi, unsigned mod_nr, char **ptr, + char const *orig) +{ + char *res = *ptr; + if (!orig) + return 0; + + char* name_end = strchr(orig, ' '); + if (name_end && *name_end) + *name_end = 0; + else + name_end = 0; + + unsigned size; + char const *new_args = get_arg_module(mbi, orig, &size); + + if (new_args && size) + printf(" new args for %d = \"%.*s\"\n", mod_nr, size, new_args); + else + if (name_end) + *name_end = ' '; + + strcpy(*ptr, orig); + *ptr+= strlen(*ptr)+1; + + if (new_args) + { + *((*ptr)-1) = ' '; + strncpy(*ptr, new_args, size); + *ptr += size; + *((*ptr)++) = 0; + } + return res; +} + + +static +void +print_e820_map(l4util_mb_info_t *mbi) +{ +#ifndef ARCH_arm + printf(" Bootloader MMAP%s\n", mbi->flags & L4UTIL_MB_MEM_MAP + ? ":" : " not available."); +#endif + + if (mbi->flags & L4UTIL_MB_MEM_MAP) + { + l4util_mb_addr_range_t *mmap; + l4util_mb_for_each_mmap_entry(mmap, mbi) + { + const char *types[] = { "unknown", "RAM", "reserved", "ACPI", + "ACPI NVS", "unusable" }; + const char *type_str = (mmap->type < (sizeof(types) / sizeof(types[0]))) + ? types[mmap->type] : types[0]; + + printf(" [%9llx, %9llx) %s (%d)\n", + (unsigned long long) mmap->addr, + (unsigned long long) mmap->addr + (unsigned long long) mmap->size, + type_str, (unsigned) mmap->type); + } + } +} + +/** + * Relocate and compact the multi-boot infomation (MBI). + * + * This function relocates the MBI into the first 4MB of physical memory. + * Substructures such as module information, the VESA information, and + * the command lines of the modules are also relocated. + * During relocation of command lines they may be substituted according + * to '-arg=' options from the bootstrap command line. + * + * The memory map is discared and not relocated, because everything after + * bootstrap has to use the KIP memory desriptors. + */ +static +l4util_mb_info_t * +relocate_mbi(l4util_mb_info_t *src_mbi, unsigned long* start, + unsigned long* end) +{ + l4util_mb_info_t *dst_mbi; + l4_addr_t x; + + print_e820_map(src_mbi); + + static char mbi_store[16 << 10] __attribute__((aligned(L4_PAGESIZE))); + + x = (l4_addr_t)&mbi_store; + + void *mbi_start = (void*)x; + + char *p = (char*)x; + *start = x; + + dst_mbi = (l4util_mb_info_t*)lin_alloc(sizeof(l4util_mb_info_t), &p); + + /* copy (extended) multiboot info structure */ + memcpy(dst_mbi, src_mbi, sizeof(l4util_mb_info_t)); + + dst_mbi->flags &= ~(L4UTIL_MB_CMDLINE | L4UTIL_MB_MEM_MAP | L4UTIL_MB_MEMORY); + + /* copy extended VIDEO information, if available */ + if (dst_mbi->flags & L4UTIL_MB_VIDEO_INFO) + { + if (src_mbi->vbe_mode_info) + { + l4util_mb_vbe_mode_t *m + = (l4util_mb_vbe_mode_t*)lin_alloc(sizeof(l4util_mb_vbe_mode_t), + &p); + + memcpy(m, L4_VOID_PTR(src_mbi->vbe_mode_info), + sizeof(l4util_mb_vbe_mode_t)); + dst_mbi->vbe_mode_info = (l4_addr_t)m; + } + + /* copy VBE controller info structure */ + if (src_mbi->vbe_ctrl_info) + { + l4util_mb_vbe_ctrl_t *m + = (l4util_mb_vbe_ctrl_t*)lin_alloc(sizeof(l4util_mb_vbe_ctrl_t), + &p); + memcpy(m, L4_VOID_PTR(src_mbi->vbe_ctrl_info), + sizeof(l4util_mb_vbe_ctrl_t)); + dst_mbi->vbe_ctrl_info = (l4_addr_t)m; + } + } + + /* copy module descriptions */ + l4util_mb_mod_t *mods = (l4util_mb_mod_t*)lin_alloc(sizeof(l4util_mb_mod_t)* + src_mbi->mods_count, &p); + memcpy(mods, L4_VOID_PTR(dst_mbi->mods_addr), + dst_mbi->mods_count * sizeof (l4util_mb_mod_t)); + dst_mbi->mods_addr = (l4_addr_t)mods; + + /* copy command lines of modules */ + for (unsigned i = 0; i < dst_mbi->mods_count; i++) + { + char *n = dup_cmdline(src_mbi, i, &p, (char const *)(mods[i].cmdline)); + if (n) + mods[i].cmdline = (l4_addr_t) n; + } + *end = (l4_addr_t)p; + + printf(" Relocated mbi to [%p-%p]\n", mbi_start, (void*)(*end)); + regions.add(Region::n((unsigned long)mbi_start, + ((unsigned long)*end) + 0xfe, + ".Multiboot info", Region::Root), + true /* we overlap with the Bootstrap binary, we are in BSS*/); + + return dst_mbi; +} + +#ifdef IMAGE_MODE + +#ifdef COMPRESS +#include "uncompress.h" +#endif + +//#define DO_CHECK_MD5 +#ifdef DO_CHECK_MD5 +#include + +static void check_md5(const char *name, u_int8_t *start, unsigned size, + const char *md5sum) +{ + MD5_CTX md5ctx; + unsigned char digest[MD5_DIGEST_LENGTH]; + char s[MD5_DIGEST_STRING_LENGTH]; + static const char hex[] = "0123456789abcdef"; + int j; + + printf(" Checking checksum of %s\n", name); + + MD5Init(&md5ctx); + MD5Update(&md5ctx, start, size); + MD5Final(digest, &md5ctx); + + for (j = 0; j < MD5_DIGEST_LENGTH; j++) + { + s[j + j] = hex[digest[j] >> 4]; + s[j + j + 1] = hex[digest[j] & 0x0f]; + } + s[j + j] = '\0'; + + if (strcmp(s, md5sum)) + panic("md5sum mismatch"); +} +#else +static inline void check_md5(const char *, u_int8_t *, unsigned, const char *) +{} +#endif + +typedef struct +{ + l4_uint32_t start; + l4_uint32_t size; + l4_uint32_t size_uncompressed; + l4_uint32_t name; + l4_uint32_t md5sum_compr; + l4_uint32_t md5sum_uncompr; +} mod_info; + +extern mod_info _module_info_start[]; +extern mod_info _module_info_end[]; + +extern l4util_mb_mod_t _modules_mbi_start[]; +extern l4util_mb_mod_t _modules_mbi_end[]; + +/** + * Create the basic multi-boot structure in IMAGE_MODE + */ +static void +construct_mbi(l4util_mb_info_t *mbi) +{ + unsigned i; + l4util_mb_mod_t *mods = _modules_mbi_start; +#ifdef COMPRESS + l4_addr_t destbuf; +#endif + + mbi->mods_count = _module_info_end - _module_info_start; + mbi->flags |= L4UTIL_MB_MODS; + mbi->mods_addr = (l4_addr_t)mods; + + assert(mbi->mods_count >= 2); + + for (i = 0; i < mbi->mods_count; ++i) + check_md5(L4_CHAR_PTR(_module_info_start[i].name), + (u_int8_t *)_module_info_start[i].start, + _module_info_start[i].size, + L4_CHAR_PTR(_module_info_start[i].md5sum_compr)); + +#ifdef COMPRESS + printf("Compressed modules:\n"); + for (i = 0; i < mbi->mods_count; i++) + { + printf(" mod%02u: %08x-%08x: %s\n", + i, _module_info_start[i].start, + _module_info_start[i].start + _module_info_start[i].size, + L4_CHAR_PTR(_module_info_start[i].name)); + } + + destbuf = l4_round_page(mods[mbi->mods_count - 1].mod_end); + if (destbuf < _mod_addr) + destbuf = _mod_addr; + + // advance to last module end + for (i = 0; i < mbi->mods_count; i++) + destbuf += l4_round_page(_module_info_start[i].size_uncompressed); + + // check for overlaps and adjust mod_addr accordingly + unsigned long d = destbuf; + for (i = mbi->mods_count; i > 0; --i) + { + d -= l4_round_page(_module_info_start[i - 1].size_uncompressed); + if (d <= _module_info_start[i-1].start + _module_info_start[i-1].size) + { + l4_addr_t x = (_module_info_start[i-1].start + _module_info_start[i-1].size + 0xfff) & ~0xfff; + l4_addr_t delta = x - d; + + _mod_addr += delta; + destbuf += delta; + printf(" Adjusting modaddr to %lx {%d}\n", _mod_addr, i-1); + d = x; + } + } + + printf("Uncompressing modules (modaddr = %lx):\n", _mod_addr); +#endif + + for (i = mbi->mods_count; i > 0; --i) + { +#ifdef COMPRESS + destbuf -= l4_round_page(_module_info_start[i - 1].size_uncompressed); + + l4_addr_t image = + (l4_addr_t)decompress(L4_CONST_CHAR_PTR(_module_info_start[i - 1].name), + L4_VOID_PTR(_module_info_start[i - 1].start), + (void *)destbuf, + _module_info_start[i - 1].size, + _module_info_start[i - 1].size_uncompressed); +#else + l4_addr_t image = _module_info_start[i - 1].start; +#endif + mods[i - 1].mod_start = image; + mods[i - 1].mod_end = image + _module_info_start[i - 1].size_uncompressed; + printf(" mod%02u: %08x-%08x: %s\n", + i - 1, mods[i - 1].mod_start, mods[i - 1].mod_end, + L4_CHAR_PTR(_module_info_start[i - 1].name)); + if (image == 0) + panic("Panic: Failure decompressing image\n"); + if (!ram.contains(Region(mods[i - 1].mod_start, + mods[i - 1].mod_end))) + panic("Panic: Module does not fit into RAM"); + + } + + for (i = 0; i < mbi->mods_count; ++i) + check_md5(L4_CHAR_PTR(_module_info_start[i].name), + (u_int8_t *)mods[i].mod_start, + _module_info_start[i].size_uncompressed, + L4_CHAR_PTR(_module_info_start[i].md5sum_uncompr)); +} +#endif /* IMAGE_MODE */ + + +/* Occupied RAM at the point we are scannig it */ +static int +is_precious_ram(unsigned long addr) +{ + extern int _start, _end; + + if ((unsigned long)&_start <= addr && addr <= (unsigned long)&_end) + return 1; + +#ifdef IMAGE_MODE + unsigned i, c = _module_info_end - _module_info_start; + if ((unsigned long)_module_info_start <= addr + && addr <= (unsigned long)_module_info_end) + return 1; + + if ((unsigned long)_modules_mbi_start <= addr + && addr <= (unsigned long)_modules_mbi_end) + return 1; + + for (i = 0; i < c; ++i) + if (_module_info_start[i].start <= addr + && addr < _module_info_start[i].start + _module_info_start[i].size_uncompressed) + return 1; +#endif + + return 0; +} + +unsigned long +scan_ram_size(unsigned long base_addr, unsigned long max_scan_size_mb) +{ + // scan the RAM to find out the RAM size, note that at this point we have + // two regions in RAM that we cannot touch, &_start - &_end and the + // modules + + unsigned long offset; + const unsigned long increment = 1 << 20; // must be multiple of (1 << 20) + + printf(" Scanning up to %ld MB RAM\n", max_scan_size_mb); + + // initialize memory points + for (offset = increment; offset < (max_scan_size_mb << 20); offset += offset) + if (!is_precious_ram(base_addr + offset)) + *(unsigned long *)(base_addr + offset) = 0; + + // write something at offset 0, does it appear elsewhere? + *(unsigned long *)base_addr = 0x12345678; + asm volatile("" : : : "memory"); + for (offset = increment; offset < (max_scan_size_mb << 20); offset += offset) + if (*(unsigned long *)(base_addr + offset) == 0x12345678) + return offset >> 20; + + return max_scan_size_mb; +} + +/** + * \brief Startup, started from crt0.S + */ +/* entry point */ +extern "C" void +startup(l4util_mb_info_t *mbi, l4_umword_t flag, + void *realmode_si, ptab64_mem_info_t *ptab64_info); +void +startup(l4util_mb_info_t *mbi, l4_umword_t flag, + void *realmode_si, ptab64_mem_info_t *ptab64_info) +{ + void *l4i; + boot_info_t boot_info; + l4util_mb_mod_t *mb_mod; + + if (!Platform_base::platform) + { + // will we ever see this? + printf("No platform found, hangup."); + while (1) + ; + } + + puts("\nL4 Bootstrapper"); + puts(" Build: #" BUILD_NR " " BUILD_DATE +#ifdef ARCH_x86 + ", x86-32" +#endif +#ifdef ARCH_amd64 + ", x86-64" +#endif +#ifdef __VERSION__ + ", " __VERSION__ +#endif + ); + + regions.init(__regs, sizeof(__regs) / sizeof(__regs[0]), "regions"); + ram.init(__ram, sizeof(__ram) / sizeof(__ram[0]), "RAM", + get_memory_limit(mbi)); + +#ifdef ARCH_amd64 + // add the page-table on which we're running in 64bit mode + regions.add(Region::n(ptab64_info->addr, ptab64_info->addr + ptab64_info->size, + ".bootstrap-ptab64", Region::Boot)); +#else + (void)ptab64_info; +#endif + +#if defined(ARCH_x86) || defined(ARCH_amd64) + +#ifdef REALMODE_LOADING + /* create synthetic multi boot info */ + mbi = init_loader_mbi(realmode_si); + (void)flag; +#else + (void)realmode_si; + assert(flag == L4UTIL_MB_VALID); /* we need to be multiboot-booted */ +#endif + +#elif defined(ARCH_arm) + l4util_mb_info_t my_mbi; + memset(&my_mbi, 0, sizeof(my_mbi)); + mbi = &my_mbi; + + (void)realmode_si; + (void)flag; + +#elif defined(ARCH_ppc32) + (void)realmode_si; + (void)flag; + + l4util_mb_info_t my_mbi; + L4_drivers::Of_if of_if; + + printf(" Detecting ram size ...\n"); + unsigned long ram_size = of_if.detect_ramsize(); + printf(" Total memory size is %luMB\n", ram_size / (1024 * 1024)); + + /* setup mbi and detect OF devices */ + memset(&my_mbi, 0, sizeof(my_mbi)); + mbi = &my_mbi; + unsigned long drives_addr, drives_length; + + if (of_if.detect_devices(&drives_addr, &drives_length)) + { + mbi->flags |= L4UTIL_MB_DRIVE_INFO; + mbi->drives_addr = drives_addr; + mbi->drives_length = drives_length; + } + ram.add(Region::n(0x0, ram_size, ".ram", Region::Ram)); + +#elif defined(ARCH_sparc) + l4util_mb_info_t my_mbi; + memset(&my_mbi, 0, sizeof(my_mbi)); + mbi = &my_mbi; + + (void)realmode_si; + (void)flag; +#else +#error Unknown arch! +#endif + + setup_memory_map(mbi); + + /* basically add the bootstrap binary to the allocated regions */ + init_regions(); + + /* check command line */ + if (check_arg(mbi, "-no-sigma0")) + sigma0 = 0; + + if (check_arg(mbi, "-no-roottask")) + roottask = 0; + + if (const char *s = check_arg(mbi, "-modaddr")) + _mod_addr = strtoul(s + 9, 0, 0); + + _mod_addr = l4_round_page(_mod_addr); + +#ifdef IMAGE_MODE + construct_mbi(mbi); +#endif + + /* move vbe and ctrl structures to a known location, it might be in the + * way when moving modules around */ +#if defined(ARCH_x86) || defined(ARCH_amd64) + if (mbi->flags & L4UTIL_MB_VIDEO_INFO) + { + if (mbi->vbe_mode_info) + { + memcpy(&__mb_vbe, L4_VOID_PTR(mbi->vbe_mode_info), + sizeof(l4util_mb_vbe_mode_t)); + mbi->vbe_mode_info = (l4_addr_t)&__mb_vbe; + } + + if (mbi->vbe_ctrl_info) + { + memcpy(&__mb_ctrl, L4_VOID_PTR(mbi->vbe_ctrl_info), + sizeof(l4util_mb_vbe_ctrl_t)); + mbi->vbe_ctrl_info = (l4_addr_t)&__mb_ctrl; + } + } +#endif + + /* We need at least two boot modules */ + assert(mbi->flags & L4UTIL_MB_MODS); + /* We have at least the L4 kernel and the first user task */ + assert(mbi->mods_count >= 2); + assert(mbi->mods_count <= MODS_MAX); + + /* we're just a GRUB-booted kernel! */ + add_boot_modules_region(mbi); + + if (_mod_addr) + move_modules(mbi, _mod_addr); + + if (const char *s = get_cmdline(mbi)) + { + /* patch modules with content given at command line */ + while ((s = check_arg_str((char *)s, "-patch="))) + patch_module(&s, mbi); + } + + + add_elf_regions(mbi, kernel_module, Region::Kernel); + + if (sigma0) + add_elf_regions(mbi, sigma0_module, Region::Sigma0); + + if (roottask) + add_elf_regions(mbi, roottask_module, Region::Root); + + + /* copy Multiboot data structures, we still need to a safe place + * before playing with memory we don't own and starting L4 */ + mb_info = relocate_mbi(mbi, &boot_info.mbi_low, &boot_info.mbi_high); + if (!mb_info) + panic("could not copy multiboot info to memory below 4MB"); + + mb_mod = (l4util_mb_mod_t*)mb_info->mods_addr; + + /* --- Shouldn't touch original Multiboot parameters after here. -- */ + + /* setup kernel PART ONE */ + printf(" Loading "); + print_module_name(L4_CONST_CHAR_PTR(mb_mod[kernel_module].cmdline), + "[KERNEL]"); + putchar('\n'); + + boot_info.kernel_start = load_elf_module(mb_mod + kernel_module); + + /* setup sigma0 */ + if (sigma0) + { + printf(" Loading "); + print_module_name(L4_CONST_CHAR_PTR(mb_mod[sigma0_module].cmdline), + "[SIGMA0]"); + putchar('\n'); + + boot_info.sigma0_start = load_elf_module(mb_mod + sigma0_module); + boot_info.sigma0_stack = (l4_addr_t)sigma0_init_stack + + sizeof(sigma0_init_stack); + } + + /* setup roottask */ + if (roottask) + { + + printf(" Loading "); + print_module_name(L4_CONST_CHAR_PTR(mb_mod[roottask_module].cmdline), + "[ROOTTASK]"); + putchar('\n'); + + boot_info.roottask_start = load_elf_module(mb_mod + roottask_module); + boot_info.roottask_stack = (l4_addr_t)roottask_init_stack + + sizeof(roottask_init_stack); + } + + /* setup kernel PART TWO (special kernel initialization) */ + l4i = find_kip(); + +#if defined(ARCH_x86) || defined(ARCH_amd64) || defined(ARCH_ppc32) + /* setup multi boot info structure for kernel */ + l4util_mb_info_t kernel_mbi; + kernel_mbi = *mb_info; + kernel_mbi.flags = L4UTIL_MB_MEMORY; + if (mb_mod[kernel_module].cmdline) + { + kernel_mbi.cmdline = mb_mod[kernel_module].cmdline; + kernel_mbi.flags |= L4UTIL_MB_CMDLINE; + } +#endif + + regions.optimize(); + regions.dump(); + + if (char *c = check_arg(mbi, "-presetmem=")) + { + unsigned fill_value = strtoul(c + 11, NULL, 0); + fill_mem(fill_value); + } + + L4_kernel_options::Options *lko = find_kopts(l4i); + kcmdline_parse(L4_CONST_CHAR_PTR(mb_mod[kernel_module].cmdline), lko); + lko->uart = kuart; + lko->flags |= kuart_flags; + + + /* setup the L4 kernel info page before booting the L4 microkernel: + * patch ourselves into the booter task addresses */ + unsigned long api_version = get_api_version(l4i); + unsigned major = api_version >> 24; + printf(" API Version: (%x) %s\n", major, (major & 0x80)?"experimental":""); + switch (major) + { + case 0x02: // Version 2 API + case 0x03: // Version X.0 and X.1 + case 0x87: // Fiasco + init_kip_v2(l4i, &boot_info, mb_info, &ram, ®ions); + break; + case 0x84: + case 0x04: + init_kip_v4(l4i, &boot_info, mb_info, &ram, ®ions); + break; + default: + panic("cannot boot a kernel with unknown api version %lx\n", api_version); + break; + } + + printf(" Starting kernel "); + print_module_name(L4_CONST_CHAR_PTR(mb_mod[kernel_module].cmdline), + "[KERNEL]"); + printf(" at "l4_addr_fmt"\n", boot_info.kernel_start); + +#if defined(ARCH_x86) + asm volatile + ("pushl $exit ; jmp *%3" + : + : "a" (L4UTIL_MB_VALID), + "b" (&kernel_mbi), + "S" (realmode_si), + "r" (boot_info.kernel_start)); + +#elif defined(ARCH_amd64) + + asm volatile + ("push $exit; jmp *%2" + : + : "S" (L4UTIL_MB_VALID), "D" (&kernel_mbi), "r" (boot_info.kernel_start)); + +#elif defined(ARCH_arm) + typedef void (*startup_func)(void); + startup_func f = (startup_func)boot_info.kernel_start; + f(); + +#elif defined(ARCH_ppc32) + + init_kip_v2_arch((l4_kernel_info_t*)l4i); + printf("CPU at %lu Khz/Bus at %lu Hz\n", + ((l4_kernel_info_t*)l4i)->frequency_cpu, + ((l4_kernel_info_t*)l4i)->frequency_bus); + typedef void (*startup_func)(l4util_mb_info_t *, unsigned long); + startup_func f = (startup_func)boot_info.kernel_start; + of_if.boot_finish(); + f(&kernel_mbi, of_if.get_prom()); + +#elif defined(ARCH_sparc) + + printf("ENTER THE KERNEL!\n"); + asm volatile("or %%g0,%0,%%g2\n\t" + "jmpl %%g2,%%g0\n\t" + "nop\n\t" : : "r"(boot_info.kernel_start)); + +#else + +#error "How to enter the kernel?" + +#endif + + /*NORETURN*/ +} + +static int +l4_exec_read_exec(void * handle, + l4_addr_t file_ofs, l4_size_t file_size, + l4_addr_t mem_addr, l4_addr_t /*v_addr*/, + l4_size_t mem_size, + exec_sectype_t section_type) +{ + exec_task_t *exec_task = (exec_task_t*)handle; + if (!mem_size) + return 0; + + if (! (section_type & EXEC_SECTYPE_ALLOC)) + return 0; + + if (! (section_type & (EXEC_SECTYPE_ALLOC|EXEC_SECTYPE_LOAD))) + return 0; + + if (mem_addr < exec_task->begin) + exec_task->begin = mem_addr; + if (mem_addr + mem_size > exec_task->end) + exec_task->end = mem_addr + mem_size; + + if (Verbose_load) + printf(" [%p-%p]\n", (void *) mem_addr, (void *) (mem_addr + mem_size)); + + if (!ram.contains(Region::n(mem_addr, mem_addr + mem_size))) + { + printf("To be loaded binary region is out of memory region.\n"); + printf(" Binary region: %lx - %lx\n", mem_addr, mem_addr + mem_size); + dump_ram_map(); + panic("Binary outside memory"); + } + + memcpy((void *) mem_addr, + (char*)(exec_task->mod_start) + file_ofs, file_size); + if (file_size < mem_size) + memset((void *) (mem_addr + file_size), 0, mem_size - file_size); + + + Region *f = regions.find(mem_addr); + if (!f) + { + printf("could not find %lx\n", mem_addr); + regions.dump(); + panic("Oops: region for module not found\n"); + } + + f->name(exec_task->mod->cmdline + ? L4_CONST_CHAR_PTR(exec_task->mod->cmdline) + : ".[Unknown]"); + return 0; +} + +static int +l4_exec_add_region(void * handle, + l4_addr_t /*file_ofs*/, l4_size_t /*file_size*/, + l4_addr_t mem_addr, l4_addr_t v_addr, + l4_size_t mem_size, + exec_sectype_t section_type) +{ + exec_task_t *exec_task = (exec_task_t*)handle; + + if (!mem_size) + return 0; + + if (! (section_type & EXEC_SECTYPE_ALLOC)) + return 0; + + if (! (section_type & (EXEC_SECTYPE_ALLOC|EXEC_SECTYPE_LOAD))) + return 0; + + regions.add(Region::n(mem_addr, mem_addr + mem_size, + exec_task->mod->cmdline + ? L4_CONST_CHAR_PTR(exec_task->mod->cmdline) + : ".[Unknown]", Region::Type(exec_task->type), + mem_addr == v_addr ? 1 : 0)); + return 0; +} diff --git a/l4/pkg/bootstrap/server/src/startup.h b/l4/pkg/bootstrap/server/src/startup.h new file mode 100644 index 00000000..de80be52 --- /dev/null +++ b/l4/pkg/bootstrap/server/src/startup.h @@ -0,0 +1,39 @@ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg , + * Frank Mehnert + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ +#ifndef __STARTUP_H__ +#define __STARTUP_H__ + +#include +#include +#include + +#include "types.h" + +typedef struct +{ + unsigned long kernel_start; + unsigned long sigma0_start, sigma0_stack; + unsigned long roottask_start, roottask_stack; + unsigned long mbi_low, mbi_high; +} boot_info_t; + +extern l4_addr_t _mod_end; + +const char * get_cmdline(l4util_mb_info_t *mbi); + +#ifdef __cplusplus +#include "koptions-def.h" +char *check_arg(l4util_mb_info_t *mbi, const char *arg); +extern L4_kernel_options::Uart kuart; +extern unsigned int kuart_flags; +#endif + +#endif /* ! __STARTUP_H__ */ diff --git a/l4/pkg/bootstrap/server/src/support.h b/l4/pkg/bootstrap/server/src/support.h new file mode 100644 index 00000000..f89afebe --- /dev/null +++ b/l4/pkg/bootstrap/server/src/support.h @@ -0,0 +1,80 @@ +/*! + * \file support.h + * \brief Support header file + * + * \date 2008-01-02 + * \author Adam Lackorznynski + * + */ +/* + * (c) 2008-2009 Author(s) + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ +#ifndef __BOOTSTRAP__SUPPORT_H__ +#define __BOOTSTRAP__SUPPORT_H__ + +#include +#include +#include +#include "region.h" + +L4::Uart *uart(); +void set_stdio_uart(L4::Uart *uart); + +void platform_init(); +unsigned long scan_ram_size(unsigned long base_addr, unsigned long max_scan_size_mb); + + +class Platform_base +{ +public: + virtual void init() = 0; + virtual void setup_memory_map(l4util_mb_info_t *mbi, + Region_list *ram, Region_list *regions) = 0; + virtual bool probe() = 0; + + // remember the chosen platform + static Platform_base *platform; + + // find a platform + static void iterate_platforms() + { + extern Platform_base *__PLATFORMS_BEGIN[]; + extern Platform_base *__PLATFORMS_END[]; + for (Platform_base **p = __PLATFORMS_BEGIN; p < __PLATFORMS_END; ++p) + if (*p && (*p)->probe()) + { + platform = *p; + platform->init(); + break; + } + } +}; + +#define REGISTER_PLATFORM(type) \ + static type type##_inst; \ + static type * const __attribute__((section(".platformdata"),used)) type##_inst_p = &type##_inst + +#ifdef RAM_SIZE_MB +class Platform_single_region_ram : public Platform_base +{ +public: + void setup_memory_map(l4util_mb_info_t *, + Region_list *ram, Region_list *) + { + unsigned long ram_size_mb = scan_ram_size(RAM_BASE, RAM_SIZE_MB); + printf(" Memory size is %ldMB%s (%08lx - %08lx)\n", + ram_size_mb, ram_size_mb != RAM_SIZE_MB ? " (Limited by Scan)" : "", + (unsigned long)RAM_BASE, RAM_BASE + (ram_size_mb << 20)); + ram->add(Region::n(RAM_BASE, + (unsigned long long)RAM_BASE + (ram_size_mb << 20), + ".ram", Region::Ram)); + } +}; +#endif + +#endif /* __BOOTSTRAP__SUPPORT_H__ */ diff --git a/l4/pkg/bootstrap/server/src/types.h b/l4/pkg/bootstrap/server/src/types.h new file mode 100644 index 00000000..9780be0c --- /dev/null +++ b/l4/pkg/bootstrap/server/src/types.h @@ -0,0 +1,28 @@ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Frank Mehnert + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ +#ifndef __TYPES_H__ +#define __TYPES_H__ + +#include + +#define MODS_MAX 128 +#define CMDLINE_MAX 1024 +#define MOD_NAME_MAX 1024 + +typedef char __mb_mod_name_str[MOD_NAME_MAX]; + +// info where the page table is, for 64bit mode only +struct ptab64_mem_info_t +{ + l4_uint32_t addr; + l4_uint32_t size; +}; + +#endif /* ! __TYPES_H__ */ diff --git a/l4/pkg/bootstrap/server/src/uncompress.c b/l4/pkg/bootstrap/server/src/uncompress.c new file mode 100644 index 00000000..7e133887 --- /dev/null +++ b/l4/pkg/bootstrap/server/src/uncompress.c @@ -0,0 +1,119 @@ +/** + * \file bootstrap/server/src/uncompress.c + * \brief Support for on-the-fly uncompressing of boot modules + * + * \date 2004 + * \author Adam Lackorzynski */ + +/* + * (c) 2005-2009 Author(s) + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ + +#include +#include +#include +#include +#include + +#include "startup.h" +#include "gunzip.h" +#include "uncompress.h" + +static void *filestart; + +enum { lin_alloc_buffer_size = 12 << 10 }; +unsigned long lin_alloc_buffer[(lin_alloc_buffer_size + sizeof(unsigned long) - 1)/ sizeof(unsigned long)]; + +/* + * Upper address for the allocator for gunzip + */ +l4_addr_t +gunzip_upper_mem_linalloc(void) +{ + return (l4_addr_t)lin_alloc_buffer + sizeof(lin_alloc_buffer); +} + +/* + * Returns true if file is compressed, false if not + */ +static void +file_open(void *start, int size) +{ + filepos = 0; + filestart = start; + filemax = size; + fsmax = 0xffffffff; /* just big */ + compressed_file = 0; + + gunzip_test_header(); +} + +static int +module_read(void *buf, int size) +{ + memcpy(buf, (const void *)((l4_addr_t)filestart + filepos), size); + filepos += size; + return size; +} + +int +grub_read(unsigned char *buf, int len) +{ + /* Make sure "filepos" is a sane value */ + if (/*(filepos < 0) || */(filepos > filemax)) + filepos = filemax; + + /* Make sure "len" is a sane value */ + if ((len < 0) || (len > (signed)(filemax - filepos))) + len = filemax - filepos; + + /* if target file position is past the end of + the supported/configured filesize, then + there is an error */ + if (filepos + len > fsmax) + { + printf("Filesize error %d + %d > %d\n", filepos, len, fsmax); + return 0; + } + + if (compressed_file) + return gunzip_read (buf, len); + + return module_read(buf, len); +} + +void* +decompress(const char *name, void *start, void *destbuf, + int size, int size_uncompressed) +{ + int read_size; + + if (!size_uncompressed) + return NULL; + + file_open(start, size); + + // don't move data around if the data isn't compressed + if (!compressed_file) + return start; + + printf(" Uncompressing %s from %p to %p (%d to %d bytes, %+lld%%).\n", + name, start, destbuf, size, size_uncompressed, + 100*(unsigned long long)size_uncompressed/size - 100); + + // Add 10 to detect too short given size + if ((read_size = grub_read(destbuf, size_uncompressed + 10)) + != size_uncompressed) + { + printf("Uncorrect decompression: should be %d bytes but got %d bytes. Errnum = %d\n", + size_uncompressed, read_size, errnum); + return NULL; + } + + return destbuf; +} diff --git a/l4/pkg/bootstrap/server/src/uncompress.h b/l4/pkg/bootstrap/server/src/uncompress.h new file mode 100644 index 00000000..bb64e511 --- /dev/null +++ b/l4/pkg/bootstrap/server/src/uncompress.h @@ -0,0 +1,21 @@ +/* + * (c) 2008-2009 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ +#ifndef __BOOTSTRAP__UNCOMPRESS_H__ +#define __BOOTSTRAP__UNCOMPRESS_H__ + +#include + +EXTERN_C_BEGIN + +void *decompress(const char *name, void *start, void *destbuf, + int size, int size_uncompressed); + +EXTERN_C_END + +#endif /* ! __BOOTSTRAP__UNCOMPRESS_H__ */ diff --git a/l4/pkg/bootstrap/server/src/unpack b/l4/pkg/bootstrap/server/src/unpack new file mode 100755 index 00000000..41c989c7 --- /dev/null +++ b/l4/pkg/bootstrap/server/src/unpack @@ -0,0 +1,175 @@ +#! /usr/bin/perl -W +# +# by Adam Lackorzynski +# +# Simple attack at unpacking a bootstrap-image again. A smarter way would +# probably be if we'd add some clear marks in the image when generating +# it... +# +# Todo: prettification + +use strict; + +my @phdrs; +my $filename = shift; +die "Need to give filename!" unless defined $filename; + +system("arm-linux-objcopy -j .data -O binary $filename unpack.data"); +die "objcopy failed" if $?; + +# make it easy, just hold the file parts in memory +my $unpackdata; +my $allfile; +open(A, "unpack.data") || die "Cannot open: $!"; +{ + local undef $/; + $unpackdata = ; +} +close A; + +open(A, $filename) || die "Cannot open: $!"; +{ + local undef $/; + $allfile = ; +} +close A; + +sub find_offset($) +{ + my $vaddr = shift; + die "find_offset: EINVAL" unless defined $vaddr; + + foreach my $p (@phdrs) { + if ($vaddr > @$p{vaddr} && @$p{vaddr} + @$p{memsize} >= $vaddr) { + return $vaddr - @$p{vaddr} + @$p{fileoff}; + } + } + die "find_phdr unsuccessful"; +} + +sub get_string($) +{ + unpack("Z*", substr($allfile, find_offset(shift))); +} + +sub get_blob($$) +{ + my $vaddr = shift; + my $len = shift; + substr($allfile, find_offset($vaddr), $len); +} + +# parse $filename PHDRs +{ + my $o = `objdump -p $filename`; + + foreach (split / LOAD /, $o) { + if (/off\s+0x([a-fA-F0-9]+)\s+vaddr\s+0x([a-fA-F0-9]+)\s+paddr\s+0x[a-fA-F0-9]+\s+align\s+\d\*\*\d+\s*.\s+filesz\s+0x([a-fA-F0-9]+)\s+memsz\s+0x([a-fA-F0-9]+)/m) { + print "PHDR: off=$1 vaddr=$2 fsz=$3 msz=$4\n"; + push @phdrs, { fileoff => hex($1), vaddr => hex($2), filesize => hex($3), memsize => hex($4) }; + } + } +} + +my $filesize = -s "$filename"; + +my $offset = 0; +my %entries; +my $previous; +my $delta = 4; +my $modinfo_size = 24; +while ($offset < length($unpackdata) - 12 * 4) { + my ($start0, $size0, $sizeun0, $name0, $md5comp0, $md5uncomp0, + $start1, $size1, $sizeun1, $name1, $md5comp1, $md5uncomp1, + $start2, $size2, $sizeun2, $name2, $md5comp2, $md5uncomp2) + = unpack("LLLLLLLLLLLLLLLLLL", substr($unpackdata, $offset)); + + if ((!defined $previous || $previous + $modinfo_size == $offset) + && ($start0 > 0x5000) + && ($start1 > 0x5000) + && ($start2 > 0x5000) + && (($start0 & 0xfff) == 0) + && (($start1 & 0xfff) == 0) + && (($start2 & 0xfff) == 0) + && ($size0 < $filesize) + && ($size1 < $filesize) + && ($size2 < $filesize) + && ($sizeun0 < (80 << 20)) + && ($sizeun1 < (80 << 20)) + && ($sizeun2 < (80 << 20))) { + + #printf "%x %x %x\n", $start0, $start1, $start2; + printf "Found module info at offset %d/0x%x\n", $offset, $offset; + + $entries{$offset}{addr} = $start0; + $entries{$offset}{size} = $size0; + $entries{$offset}{usize} = $sizeun0; + $entries{$offset}{name} = $name0; + $entries{$offset}{md5comp} = $md5comp0; + $entries{$offset}{md5uncomp} = $md5uncomp0; + $entries{$offset + 1 * $modinfo_size}{addr} = $start1; + $entries{$offset + 1 * $modinfo_size}{size} = $size1; + $entries{$offset + 1 * $modinfo_size}{usize} = $sizeun1; + $entries{$offset + 1 * $modinfo_size}{name} = $name1; + $entries{$offset + 1 * $modinfo_size}{md5comp} = $md5comp1; + $entries{$offset + 1 * $modinfo_size}{md5uncomp} = $md5uncomp1; + $entries{$offset + 2 * $modinfo_size}{addr} = $start2; + $entries{$offset + 2 * $modinfo_size}{size} = $size2; + $entries{$offset + 2 * $modinfo_size}{usize} = $sizeun2; + $entries{$offset + 2 * $modinfo_size}{name} = $name2; + $entries{$offset + 2 * $modinfo_size}{md5comp} = $md5comp2; + $entries{$offset + 2 * $modinfo_size}{md5uncomp} = $md5uncomp2; + + $previous = $offset; + $delta = $modinfo_size; + } else { + $delta = 4; + } + $offset += $delta; + + print "Scanning at offset $offset\n" if $offset % 1000 == 0; +} + +my $dir = "unpack.dir"; +mkdir $dir; + +open(MODLIST, ">$dir/modules.list") + || die "Cannot open $dir/unpack.modules.list: $!"; +print MODLIST "entry unpacked\n"; +print MODLIST "modaddr 0x01200000\n"; + +my $nr = 1; +open(M, ">md5sums") || die "Cannot create checksum file: $!"; +foreach my $e (sort { $a <=> $b } keys %entries) +{ + my $name = get_string($entries{$e}{name}); + my $fname = "$dir/$name"; + open(A, ">$fname") || die "Cannot create file $fname: $!"; + print A get_blob($entries{$e}{addr}, $entries{$e}{size}); + close A; + + print M get_string($entries{$e}{md5uncomp})." $fname\n"; + + + system("file $fname"); + + # missing: cmdlines + if ($nr == 1) { + print MODLIST "kernel $name\n"; + } elsif ($nr == 2) { + print MODLIST "sigma0 $name\n"; + } elsif ($nr == 3) { + print MODLIST "roottask $name\n"; + } else { + print MODLIST "module $name\n"; + } + + + $nr++; +} +close M; +close MODLIST; + +unlink "unpack.data"; + +system("md5sum -c md5sums"); diff --git a/l4/pkg/cxx/Control b/l4/pkg/cxx/Control new file mode 100644 index 00000000..47f335bc --- /dev/null +++ b/l4/pkg/cxx/Control @@ -0,0 +1,5 @@ +requires: l4sys l4util +provides: cxx_atexit cxx_atexit_e cxx_base cxx_base_e cxx_io + cxx_io_e cxx_io_kdebug cxx_io_kdebug_e cxx_util + cxx_util_e +Maintainer: warg@os.inf.tu-dresden.de diff --git a/l4/pkg/cxx/LEGAL b/l4/pkg/cxx/LEGAL new file mode 100644 index 00000000..c5759305 --- /dev/null +++ b/l4/pkg/cxx/LEGAL @@ -0,0 +1,8 @@ +# Format: (all on one line) +# Source file : Copyright Owner(s) +# Please use "TUD" when referring to TU Dresden. +# If sole owner is TUD, the license field defaults to GPL and can be +# left empty. +# Source-file spec can be a directory name or a wildcard like "src/*.c". +* : TUD + diff --git a/l4/pkg/cxx/Makefile b/l4/pkg/cxx/Makefile new file mode 100644 index 00000000..095c197d --- /dev/null +++ b/l4/pkg/cxx/Makefile @@ -0,0 +1,8 @@ +PKGDIR = . +L4DIR ?= $(PKGDIR)/../.. +TARGET = lib + +include $(L4DIR)/mk/subdir.mk + +include: + $(foreach DIR, $(SUBDIR), $(MAKE) -C $(DIR) include) diff --git a/l4/pkg/cxx/doc/cxx.dox b/l4/pkg/cxx/doc/cxx.dox new file mode 100644 index 00000000..323f63d7 --- /dev/null +++ b/l4/pkg/cxx/doc/cxx.dox @@ -0,0 +1,6 @@ +/** + * \defgroup cxx_api Small C++ Template Library + * \defgroup client_server_ipc Client/Server IPC Framework + * \defgroup ipc_stream IPC Streams + * \defgroup ipc_fw IPC Messaging Framework + */ diff --git a/l4/pkg/cxx/doc/files.cfg b/l4/pkg/cxx/doc/files.cfg new file mode 100644 index 00000000..3ea0a6b9 --- /dev/null +++ b/l4/pkg/cxx/doc/files.cfg @@ -0,0 +1,2 @@ +INPUT += l4/cxx +INPUT += $(L4DIR)/pkg/cxx/doc/cxx.dox diff --git a/l4/pkg/cxx/lib/Makefile b/l4/pkg/cxx/lib/Makefile new file mode 100644 index 00000000..45720469 --- /dev/null +++ b/l4/pkg/cxx/lib/Makefile @@ -0,0 +1,12 @@ +PKGDIR = .. +L4DIR ?= $(PKGDIR)/../.. +TARGET = io base be start util tl ipc + +include $(L4DIR)/mk/subdir.mk + +base: io +be: io +start: base util +util: io +ipc: base tl + diff --git a/l4/pkg/cxx/lib/Makefile.inc b/l4/pkg/cxx/lib/Makefile.inc new file mode 100644 index 00000000..af1bb88b --- /dev/null +++ b/l4/pkg/cxx/lib/Makefile.inc @@ -0,0 +1,45 @@ +# vim:set ft=make: + +TARGET_A := $(TARGET).a +TARGET_E_A := $(TARGET)_e.a + +PC_FILENAMES := $(PC_FILENAME) $(PC_FILENAME)_e +PC_LIBS_$(PC_FILENAME) := -l$(patsubst lib%,%,$(TARGET)) +PC_LIBS_$(PC_FILENAME)_e := -l$(patsubst lib%,%,$(TARGET))_e + +CXXFLAGS_amd64-l4f += -mcmodel=medium +CFLAGS_amd64-l4f += -mcmodel=medium + +CXXFLAGS_F_A := $(patsubst %.cc,%.cxxflags,$(SRC_CC)) +CXXFLAGS_F_E_A := $(patsubst %.cc,%.e.cxxflags,$(SRC_CC)) + +SRC_CC_$(TARGET_A) := $(SRC_CC) +SRC_CC_$(TARGET_E_A) := $(patsubst %.cc,%.e.cc,$(SRC_CC)) +SRC_CC := + +PRIVATE_INCDIR += $(SRC_DIR)/ + +TARGET := $(TARGET_A) $(TARGET_E_A) + +ifneq ($(MAKECMDGOALS),) + MAKEGOALS := $(MAKECMDGOALS) +else + MAKEGOALS := all +endif + +ifeq ($(findstring OBJ,$(shell pwd)),OBJ) +ifneq ($(filter-out clean cleanall scrub,$(MAKEGOALS)),) + -include $(CXXFLAGS_F_A) $(CXXFLAGS_F_E_A) +endif +endif + +all:: + +$(CXXFLAGS_F_A): %.cxxflags: %.cc $(L4DIR)/pkg/cxx/lib/Makefile.inc + $(VERBOSE)echo "CXXFLAGS_$(notdir $<) := -DL4_NO_RTTI -Wall -fno-exceptions -fno-rtti" > $@ + +$(CXXFLAGS_F_E_A): %.cxxflags: %.cc $(L4DIR)/pkg/cxx/lib/Makefile.inc + $(VERBOSE)echo "CXXFLAGS_$(notdir $<) := -Wall" > $@ + +%.e.cc: %.cc + $(VERBOSE)ln -s $< $@ diff --git a/l4/pkg/cxx/lib/base/Makefile b/l4/pkg/cxx/lib/base/Makefile new file mode 100644 index 00000000..b60574b6 --- /dev/null +++ b/l4/pkg/cxx/lib/base/Makefile @@ -0,0 +1,5 @@ +PKGDIR = ../.. +L4DIR ?= $(PKGDIR)/../.. + +TARGET := include src +include $(L4DIR)/mk/subdir.mk diff --git a/l4/pkg/cxx/lib/base/include/Makefile b/l4/pkg/cxx/lib/base/include/Makefile new file mode 100644 index 00000000..d07db7cd --- /dev/null +++ b/l4/pkg/cxx/lib/base/include/Makefile @@ -0,0 +1,5 @@ +PKGDIR = ../../.. +L4DIR ?= $(PKGDIR)/../.. +EXTRA_TARGET := exceptions string std_exc_io + +include $(L4DIR)/mk/include.mk diff --git a/l4/pkg/cxx/lib/base/include/exceptions b/l4/pkg/cxx/lib/base/include/exceptions new file mode 100644 index 00000000..cebb7579 --- /dev/null +++ b/l4/pkg/cxx/lib/base/include/exceptions @@ -0,0 +1,307 @@ +// vi:ft=cpp +/** + * \file + * \brief Base exceptions + * \ingroup l4cxx_exceptions + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ + +#pragma once + +#include +#include +#include +#include + + +/** + * \defgroup l4cxx_exceptions C++ Exceptions + * \ingroup api_l4re + */ +/*@{*/ + +#ifndef L4_CXX_NO_EXCEPTION_BACKTRACE +# define L4_CXX_EXCEPTION_BACKTRACE 20 +#endif + +#if defined(L4_CXX_EXCEPTION_BACKTRACE) +#include +#endif + +/*@}*/ +namespace L4 +{ + + /** + * \addtogroup l4cxx_exceptions + */ + /*@{*/ + /** + * \brief Back-trace support for exceptions. + * \headerfile l4/cxx/exceptions + * + * This class holds an array of at most #L4_CXX_EXCEPTION_BACKTRACE + * instruction pointers containing the call trace at the instant when an + * exception was thrown. + */ + class Exception_tracer + { +#if defined(L4_CXX_EXCEPTION_BACKTRACE) + private: + void *_pc_array[L4_CXX_EXCEPTION_BACKTRACE]; + int _frame_cnt; + + protected: + /** + * \brief Create a back trace. + */ +#if defined(__PIC__) + Exception_tracer() throw() : _frame_cnt(0) {} +#else + Exception_tracer() throw() : _frame_cnt(l4util_backtrace(_pc_array, L4_CXX_EXCEPTION_BACKTRACE)) {} +#endif + + public: + /** + * \brief Get the array containing the call trace. + */ + void const *const *pc_array() const throw() { return _pc_array; } + /** + * \brief Get the number of entries that are valid in the call trace. + */ + int frame_count() const throw() { return _frame_cnt; } +#else + protected: + /** + * \brief Create a back trace. + */ + Exception_tracer() throw() {} + + public: + /** + * \brief Get the array containing the call trace. + */ + void const *const *pc_array() const throw() { return 0; } + /** + * \brief Get the number of entries that are valid in the call trace. + */ + int frame_count() const throw() { return 0; } +#endif + }; + + /** + * \brief Base class for all exceptions, thrown by the L4Re framework. + * \headerfile l4/cxx/exceptions + * + * This is the abstract base of all exceptions thrown within the + * L4Re framework. It is basically also a good idea to use it as base of + * all user defined exceptions. + */ + class Base_exception : public Exception_tracer + { + protected: + /// Create a base exception. + Base_exception() throw() {} + + public: + /** + * \brief Should return a human readable string for the exception. + */ + virtual char const *str() const throw () = 0; + + /// Destruction + virtual ~Base_exception() throw () {} + }; + + /** + * \brief Exception for an abstract runtime error. + * \headerfile l4/cxx/exceptions + * + * This is the base class for a set of exceptions that cover all errors + * that have a C error value (see #l4_error_code_t). + */ + class Runtime_error : public Base_exception + { + private: + long _errno; + char _extra[80]; + + public: + explicit Runtime_error(long err_no, char const *extra = 0) throw () + : _errno(err_no) + { + if (!extra) + _extra[0] = 0; + else + { + for (unsigned i = 0; i < sizeof(_extra) && extra[i]; ++i) + _extra[i] = extra[i]; + _extra[sizeof(_extra) - 1] = 0; + } + } + char const *str() const throw () + { return l4sys_errtostr(_errno); } + char const *extra_str() const { return _extra; } + ~Runtime_error() throw () {} + + long err_no() const throw() { return _errno; } + }; + + /** + * \brief Exception signalling insufficient memory. + * \headerfile l4/cxx/exceptions + */ + class Out_of_memory : public Runtime_error + { + public: + /// Create an out-of-memory exception. + explicit Out_of_memory(char const *extra = "") throw() + : Runtime_error(-L4_ENOMEM, extra) {} + /// Destruction + ~Out_of_memory() throw() {} + }; + + + /** + * \brief Exception for duplicate element insertions. + * \headerfile l4/cxx/exceptions + */ + class Element_already_exists : public Runtime_error + { + public: + explicit Element_already_exists(char const *e = "") throw() + : Runtime_error(-L4_EEXIST, e) {} + ~Element_already_exists() throw() {} + }; + + /** + * \brief Exception for an unknown condition. + * \headerfile l4/cxx/exceptions + * + * This error is usually used when a server returns an unknown return state + * to the client, this may indicate incompatible messages used by the client + * and the server. + */ + class Unknown_error : public Base_exception + { + public: + Unknown_error() throw() {} + char const *str() const throw() { return "unknown error"; } + ~Unknown_error() throw() {} + }; + + + /** + * \brief Exception for a failed lookup (element not found). + * \headerfile l4/cxx/exceptions + */ + class Element_not_found : public Runtime_error + { + public: + explicit Element_not_found(char const *e = "") throw() + : Runtime_error(-L4_ENOENT, e) {} + }; + + /** + * \brief Indicates that an invalid object was invoked. + * \headerfile l4/cxx/exceptions + * + * An Object is invalid if it has L4_INVALID_ID as server L4 UID, + * or if the server does not know the object ID. + */ + class Invalid_capability : public Base_exception + { + private: + Cap const _o; + + public: + /** + * \brief Create an Invalid_obejct exception for the Object o. + * \param o The object that caused the server side error. + */ + explicit Invalid_capability(Cap const &o) throw() : _o(o) {} + template< typename T> + explicit Invalid_capability(Cap const &o) throw() : _o(o.cap()) {} + char const *str() const throw() { return "invalid object"; } + + /** + * \brief Get the object that caused the error. + * \return The object that caused the error on invocation. + */ + Cap const &cap() const throw() { return _o; } + ~Invalid_capability() throw() {} + }; + + /** + * \brief Error conditions during IPC. + * \headerfile l4/cxx/exceptions + * + * This exception encapsulates all IPC error conditions of L4 IPC. + */ + class Com_error : public Runtime_error + { + public: + /** + * \brief Create a Com_error for the givel L4 IPC error code. + * \param err The L4 IPC error code (l4_ipc... return value). + */ + explicit Com_error(long err) throw() : Runtime_error(err) {} + + ~Com_error() throw() {} + }; + + /** + * \brief Access out of bounds. + */ + class Bounds_error : public Runtime_error + { + public: + explicit Bounds_error(char const *e = "") throw() + : Runtime_error(-L4_ERANGE, e) {} + ~Bounds_error() throw() {} + }; + /*@}*/ +}; + +inline +L4::BasicOStream & +operator << (L4::BasicOStream &o, L4::Base_exception const &e) +{ + o << "Exception: " << e.str() << ", backtrace ...\n"; + for (int i = 0; i < e.frame_count(); ++i) + o << L4::n_hex(l4_addr_t(e.pc_array()[i])) << '\n'; + + return o; +} + +inline +L4::BasicOStream & +operator << (L4::BasicOStream &o, L4::Runtime_error const &e) +{ + o << "Exception: " << e.str() << ": "; + if (e.extra_str()) + o << e.extra_str() << ": "; + o << "backtrace ...\n"; + for (int i = 0; i < e.frame_count(); ++i) + o << L4::n_hex(l4_addr_t(e.pc_array()[i])) << '\n'; + + return o; +} + diff --git a/l4/pkg/cxx/lib/base/include/std_exc_io b/l4/pkg/cxx/lib/base/include/std_exc_io new file mode 100644 index 00000000..4e9d2d5c --- /dev/null +++ b/l4/pkg/cxx/lib/base/include/std_exc_io @@ -0,0 +1,54 @@ +// vi:ft=cpp +/** + * \file + * \brief Base exceptions std stream operator + * \ingroup l4cxx_exceptions + */ +/* + * (c) 2011 Adam Lackorzynski , + * Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ + +#pragma once + +#include +#include + +inline +std::ostream & +operator << (std::ostream &o, L4::Base_exception const &e) +{ + o << "Exception: " << e.str() << ", backtrace ...\n"; + for (int i = 0; i < e.frame_count(); ++i) + o << (void *)(e.pc_array()[i]) << '\n'; + + return o; +} + +inline +std::ostream & +operator << (std::ostream &o, L4::Runtime_error const &e) +{ + o << "Exception: " << e.str() << ": "; + if (e.extra_str()) + o << e.extra_str() << ": "; + o << "backtrace ...\n"; + for (int i = 0; i < e.frame_count(); ++i) + o << (void *)(e.pc_array()[i]) << '\n'; + + return o; +} diff --git a/l4/pkg/cxx/lib/base/include/string b/l4/pkg/cxx/lib/base/include/string new file mode 100644 index 00000000..8237daa1 --- /dev/null +++ b/l4/pkg/cxx/lib/base/include/string @@ -0,0 +1,252 @@ +// vi:ft=cpp +/* + * (c) 2008-2009 Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ + +#pragma once + +#include +#include + + +namespace cxx { + +/* + * This class is used to group characters of a string which belong + * to one syntactical token types number, identifier, string, + * whitespace or another single character. + */ +class String +{ +public: + + typedef char const *Index; + + String(char const *s) throw() : _start(s), _len(__builtin_strlen(s)) {} + String(char const *s, unsigned long len) throw() : _start(s), _len(len) {} + String(char const *s, char const *e) throw() : _start(s), _len(e-s) {} + + String() : _start(0), _len(0) {} + + Index start() const { return _start; } + Index end() const { return _start + _len; } + int len() const { return _len; } + + void start(char const *s) { _start = s; } + void len(unsigned long len) { _len = len; } + bool empty() const { return !_len; } + + String head(Index end) const + { + if (end < _start) + return String(); + + if (eof(end)) + return *this; + + return String(_start, end - _start); + } + + String head(unsigned long end) const + { return head(start() + end); } + + String substr(unsigned long idx, unsigned long len = ~0UL) const + { + if (idx >= _len) + return String(end(), 0UL); + + return String(_start + idx, cxx::min(len, _len - idx)); + } + + String substr(char const *start, unsigned long len = 0) const + { + if (start >= _start && !eof(start)) + { + unsigned long nlen =_start + _len - start; + if (len != 0) + nlen = cxx::min(nlen, len); + return String(start, nlen); + } + + return String(end(), 0UL); + } + + template< typename F > + char const *find_match(F const &match) const + { + String::Index s = _start; + while (1) + { + if (eof(s)) + return s; + + if (match(*s)) + return s; + + ++s; + } + } + + char const *find(char const *c) const + { return find(c, start()); } + + char const *find(int c) const + { return find(c, start()); } + + char const *rfind(char const *c) const + { + if (!_len) + return end(); + + char const *p = end(); + --p; + while (p >= _start) + { + if (*p == *c) + return p; + --p; + } + return end(); + + } + + Index starts_with(cxx::String const &c) const + { + unsigned long i; + for (i = 0; i < c._len && i < _len; ++i) + if (_start[i] != c[i]) + return 0; + return i == c._len ? start() + i : 0; + } + + char const *find(int c, char const *s) const + { + if (s<_start) + return end(); + + while (1) + { + if (eof(s)) + return s; + + if (*s == c) + return s; + + ++s; + } + } + + char const *find(char const *c, char const *s) const + { + if (s<_start) + return end(); + + while (1) + { + if (eof(s)) + return s; + + for (char const *x = c; *x; ++x) + if (*s == *x) + return s; + + ++s; + } + } + + char const &operator [] (unsigned long idx) const { return _start[idx]; } + char const &operator [] (int idx) const { return _start[idx]; } + char const &operator [] (Index idx) const { return *idx; } + + bool eof(char const *s) const { return s >= _start + _len || !*s; } + + template + int from_dec(INT *v) const + { + *v = 0; + Index c; + for (c = start(); !eof(c); ++c) + { + unsigned char n; + if (*c >= '0' && *c <= '9') + n = *c - '0'; + else + return c - start(); + + *v *= 10; + *v += n; + } + return c - start(); + } + + template + int from_hex(INT *v) const + { + *v = 0; + unsigned shift = 0; + Index c; + for (c = start(); !eof(c); ++c) + { + shift += 4; + if (shift > sizeof(INT) * 8) + return -1; + unsigned char n; + if (*c >= '0' && *c <= '9') + n = *c - '0'; + else if (*c >= 'A' && *c <= 'F') + n = *c - 'A' + 10; + else if (*c >= 'a' && *c <= 'f') + n = *c - 'a' + 10; + else + return c - start(); + + *v <<= 4; + *v |= n; + } + return c - start(); + } + + bool operator == (String const &o) const + { + if (len() != o.len()) + return false; + + for (unsigned long i = 0; i < _len; ++i) + if (_start[i] != o._start[i]) + return false; + + return true; + } + + bool operator != (String const &o) const + { return ! (operator == (o)); } + +private: + + char const *_start; + unsigned long _len; + +}; + +} + +inline +L4::BasicOStream &operator << (L4::BasicOStream &s, cxx::String const &str) +{ + s.write(str.start(), str.len()); + return s; +} diff --git a/l4/pkg/cxx/lib/base/src/Makefile b/l4/pkg/cxx/lib/base/src/Makefile new file mode 100644 index 00000000..bbfa8685 --- /dev/null +++ b/l4/pkg/cxx/lib/base/src/Makefile @@ -0,0 +1,13 @@ +PKGDIR ?= ../../.. +L4DIR ?= $(PKGDIR)/../.. + +TARGET = libcxx_base +SYSTEMS = $(SYSTEMS_PLAIN) +PC_FILENAME = cxx_base +SRC_CC = cxa_pure_virtual.cc cxa_pure_delete.cc +SRC_CC_arm = dso_handle.cc + +include $(PKGDIR)/lib/Makefile.inc +include $(L4DIR)/mk/lib.mk + +$(GENERAL_D_LOC): $(L4DIR)/pkg/cxx/lib/Makefile.inc diff --git a/l4/pkg/cxx/lib/base/src/cxa_pure_delete.cc b/l4/pkg/cxx/lib/base/src/cxa_pure_delete.cc new file mode 100644 index 00000000..0c74a384 --- /dev/null +++ b/l4/pkg/cxx/lib/base/src/cxa_pure_delete.cc @@ -0,0 +1,25 @@ +/* + * (c) 2004-2009 Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ + +#include + +void operator delete (void *obj) +{ + L4::cerr << "cxa pure delete operator called for object @" + << L4::hex << obj << L4::dec << "\n"; +} diff --git a/l4/pkg/cxx/lib/base/src/cxa_pure_virtual.cc b/l4/pkg/cxx/lib/base/src/cxa_pure_virtual.cc new file mode 100644 index 00000000..a3b3fc51 --- /dev/null +++ b/l4/pkg/cxx/lib/base/src/cxa_pure_virtual.cc @@ -0,0 +1,34 @@ +/* + * (c) 2004-2009 Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ + +#include + +extern "C" void __cxa_pure_virtual(void); + +void __cxa_pure_virtual() +{ + L4::cerr << "cxa pure virtual function called\n"; +} + + +extern "C" void __pure_virtual(void); + +void __pure_virtual() +{ + L4::cerr << "cxa pure virtual function called\n"; +} diff --git a/l4/pkg/cxx/lib/base/src/dso_handle.cc b/l4/pkg/cxx/lib/base/src/dso_handle.cc new file mode 100644 index 00000000..baec9243 --- /dev/null +++ b/l4/pkg/cxx/lib/base/src/dso_handle.cc @@ -0,0 +1,20 @@ +/* + * (c) 2004-2009 Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ + +/* ARM C++ ABI requirement */ +void *__dso_handle __attribute__ ((__visibility__ ("hidden"))) = &__dso_handle; diff --git a/l4/pkg/cxx/lib/be/Makefile b/l4/pkg/cxx/lib/be/Makefile new file mode 100644 index 00000000..2383038a --- /dev/null +++ b/l4/pkg/cxx/lib/be/Makefile @@ -0,0 +1,5 @@ +PKGDIR = ../.. +L4DIR ?= $(PKGDIR)/../.. + +TARGET := kdebug +include $(L4DIR)/mk/subdir.mk diff --git a/l4/pkg/cxx/lib/be/kdebug/Makefile b/l4/pkg/cxx/lib/be/kdebug/Makefile new file mode 100644 index 00000000..c6c66c6e --- /dev/null +++ b/l4/pkg/cxx/lib/be/kdebug/Makefile @@ -0,0 +1,12 @@ +PKGDIR ?= ../../.. +L4DIR ?= $(PKGDIR)/../.. + +TARGET = libcxx_io_kdebug +PC_FILENAME = cxx_io_kdebug +SYSTEMS = $(SYSTEMS_PLAIN) +SRC_CC = iostream.cc + +include $(PKGDIR)/lib/Makefile.inc +include $(L4DIR)/mk/lib.mk + +$(GENERAL_D_LOC): $(L4DIR)/pkg/cxx/lib/Makefile.inc diff --git a/l4/pkg/cxx/lib/be/kdebug/iostream.cc b/l4/pkg/cxx/lib/be/kdebug/iostream.cc new file mode 100644 index 00000000..e02d87a4 --- /dev/null +++ b/l4/pkg/cxx/lib/be/kdebug/iostream.cc @@ -0,0 +1,64 @@ +/* + * (c) 2004-2009 Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ + +#include +#include +#include +#include + +#include + +inline void *operator new (size_t, void *p) { return p; } + +namespace L4 { + + class KdbgIOBackend : public IOBackend + { + protected: + void write(char const *str, unsigned len); + }; + + void KdbgIOBackend::write(char const *str, unsigned len) + { + outnstring(str,len); + } + + typedef char Fake_iobackend[sizeof(KdbgIOBackend)] + __attribute__((aligned(__alignof__(KdbgIOBackend)))); + typedef char Fake_ostream[sizeof(BasicOStream)] + __attribute__((aligned(__alignof__(BasicOStream)))); + + Fake_ostream cout; + Fake_ostream cerr; + + static Fake_iobackend _iob; + + void iostream_init(); + + void iostream_init() + { + static l4_umword_t _initialized; + if (l4util_xchg(&_initialized, 1) == 0) + { + KdbgIOBackend *iob = new (&_iob) KdbgIOBackend(); + new (&cerr) BasicOStream(iob); + new (&cout) BasicOStream(iob); + } + } + +}; diff --git a/l4/pkg/cxx/lib/io/Makefile b/l4/pkg/cxx/lib/io/Makefile new file mode 100644 index 00000000..0cc976f7 --- /dev/null +++ b/l4/pkg/cxx/lib/io/Makefile @@ -0,0 +1,8 @@ +PKGDIR = ../.. +L4DIR ?= $(PKGDIR)/../.. + +TARGET := include src + +include $(L4DIR)/mk/subdir.mk + +src: include diff --git a/l4/pkg/cxx/lib/io/include/Makefile b/l4/pkg/cxx/lib/io/include/Makefile new file mode 100644 index 00000000..d86f52ca --- /dev/null +++ b/l4/pkg/cxx/lib/io/include/Makefile @@ -0,0 +1,6 @@ +PKGDIR = ../../.. +L4DIR ?= $(PKGDIR)/../.. + +EXTRA_TARGET := basic_ostream iostream l4iostream + +include $(L4DIR)/mk/include.mk diff --git a/l4/pkg/cxx/lib/io/include/basic_ostream b/l4/pkg/cxx/lib/io/include/basic_ostream new file mode 100644 index 00000000..48207aab --- /dev/null +++ b/l4/pkg/cxx/lib/io/include/basic_ostream @@ -0,0 +1,275 @@ +// vi:ft=cpp +/** + * \file + * \brief Basic IO stream + */ +/* + * (c) 2009 Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#pragma once + +namespace L4 { + + /** + * \brief Modifier class for the IO stream. + * + * An IO Modifier can be used to change properties of an IO stream + * for example the number format. + */ + class IOModifier + { + public: + IOModifier( int x ) : mod(x) {} + bool operator == (IOModifier o) { return mod == o.mod; } + bool operator != (IOModifier o) { return mod != o.mod; } + int mod; + }; + + /** + * \internal + * \brief Backend to write or read stream data. + */ + class IOBackend + { + public: + typedef int Mode; + + protected: + friend class BasicOStream; + + IOBackend() + : int_mode(10) + {} + + virtual ~IOBackend() {} + + virtual void write(char const *str, unsigned len) = 0; + + private: + void write(IOModifier m); + void write(long long int c, int len); + void write(long long unsigned c, int len); + void write(long long unsigned c, unsigned char base = 10, + unsigned char len = 0, char pad = ' '); + + Mode mode() const + { return int_mode; } + + void mode(Mode m) + { int_mode = m; } + + int int_mode; + }; + + /** + * \internal + * \brief Write-only backend for stream data. + */ + class BasicOStream + { + public: + BasicOStream(IOBackend *b) + : iob(b) + {} + + void write(char const *str, unsigned len) + { if(iob) iob->write(str,len); } + + void write(long long int c, int len) + { if(iob) iob->write(c,len); } + + void write(long long unsigned c, unsigned char base = 10, + unsigned char len = 0, char pad = ' ') + { if(iob) iob->write(c, base, len, pad); } + + void write(long long unsigned c, int len) + { if(iob) iob->write(c,len); } + + void write(IOModifier m) + { if(iob) iob->write(m); } + + IOBackend::Mode be_mode() const + { if(iob) return iob->mode(); return 0; } + + void be_mode(IOBackend::Mode m) + { if(iob) iob->mode(m); } + + private: + IOBackend *iob; + + }; + + /** + * \internal + * \brief Container class describing a the number format. + */ + class IONumFmt + { + public: + IONumFmt(unsigned long long n, unsigned char base = 10, + unsigned char len = 0, char pad = ' ') + : n(n), base(base), len(len), pad(pad) + {} + + BasicOStream &print(BasicOStream &o) const; + + private: + unsigned long long n; + unsigned char base, len; + char pad; + }; + + inline IONumFmt n_hex(unsigned long long n) { return IONumFmt(n, 16); } + + /** + * \brief Modifies the stream to print numbers as hexadecimal values. + */ + extern IOModifier const hex; + + /** + * \brief Modifies the stream to print numbers as decimal values. + */ + extern IOModifier const dec; + + inline + BasicOStream &IONumFmt::print(BasicOStream &o) const + { + o.write(n, base, len, pad); + return o; + } + +} + + +// implementation + +inline +L4::BasicOStream & +operator << (L4::BasicOStream &s, char const * const str) +{ + if (!str) + { + s.write("(NULL)", 6); + return s; + } + + unsigned l=0; + for(; str[l]!=0; l++) + ; + s.write(str,l); + return s; +} + +inline +L4::BasicOStream & +operator << (L4::BasicOStream &s, signed short u) +{ + s.write((long long signed)u,-1); + return s; +} + +inline +L4::BasicOStream & +operator << (L4::BasicOStream &s, signed u) +{ + s.write((long long signed)u,-1); + return s; +} + +inline +L4::BasicOStream & +operator << (L4::BasicOStream &s, signed long u) +{ + s.write((long long signed)u,-1); + return s; +} + +inline +L4::BasicOStream & +operator << (L4::BasicOStream &s, signed long long u) +{ + s.write(u,-1); + return s; +} + +inline +L4::BasicOStream & +operator << (L4::BasicOStream &s, unsigned short u) +{ + s.write((long long unsigned)u,-1); + return s; +} + +inline +L4::BasicOStream & +operator << (L4::BasicOStream &s, unsigned u) +{ + s.write((long long unsigned)u,-1); + return s; +} + +inline +L4::BasicOStream & +operator << (L4::BasicOStream &s, unsigned long u) +{ + s.write((long long unsigned)u,-1); + return s; +} + +inline +L4::BasicOStream & +operator << (L4::BasicOStream &s, unsigned long long u) +{ + s.write(u,-1); + return s; +} + +inline +L4::BasicOStream & +operator << (L4::BasicOStream &s, void const *u) +{ + long unsigned x = (long unsigned)u; + L4::IOBackend::Mode mode = s.be_mode(); + s.write(L4::hex); + s.write((long long unsigned)x,-1); + s.be_mode(mode); + return s; +} + +inline +L4::BasicOStream & +operator << (L4::BasicOStream &s, L4::IOModifier m) +{ + s.write(m); + return s; +} + +inline +L4::BasicOStream & +operator << (L4::BasicOStream &s, char c) +{ + s.write( &c, 1 ); + return s; +} + + + +inline +L4::BasicOStream & +operator << (L4::BasicOStream &o, L4::IONumFmt const &n) +{ return n.print(o); } + diff --git a/l4/pkg/cxx/lib/io/include/iostream b/l4/pkg/cxx/lib/io/include/iostream new file mode 100644 index 00000000..02263a7f --- /dev/null +++ b/l4/pkg/cxx/lib/io/include/iostream @@ -0,0 +1,49 @@ +/** + * \file + * \brief IO Stream + */ +/* + * (c) 2004-2009 Alexander Warg , + * Torsten Frenzel + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ + +#ifndef L4_IOSTREAM_H__ +#define L4_IOSTREAM_H__ + +#include + +namespace L4 { + + /** + * \brief Standard output stream. + */ + extern BasicOStream cout; + + /** + * \brief Standard error stream. + */ + extern BasicOStream cerr; + + + extern void iostream_init(); + + static void __attribute__((used, constructor)) __iostream_init() + { iostream_init(); } + +}; + +#endif /* L4_IOSTREAM_H__ */ diff --git a/l4/pkg/cxx/lib/io/include/iostream.h b/l4/pkg/cxx/lib/io/include/iostream.h new file mode 100644 index 00000000..2c4ae0d7 --- /dev/null +++ b/l4/pkg/cxx/lib/io/include/iostream.h @@ -0,0 +1,4 @@ +#pragma once + +#warning 'iostream.h' is deprecated use 'iostream' instead. +#include diff --git a/l4/pkg/cxx/lib/io/include/l4iostream b/l4/pkg/cxx/lib/io/include/l4iostream new file mode 100644 index 00000000..9b4bb017 --- /dev/null +++ b/l4/pkg/cxx/lib/io/include/l4iostream @@ -0,0 +1,49 @@ +/** + * \file + * \brief L4 IO stream + */ +/* + * (c) 2004-2009 Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ + +#ifndef L4_L4IOSTREAM_H__ +#define L4_L4IOSTREAM_H__ + +#include +#include +#include + +inline +L4::BasicOStream &operator << (L4::BasicOStream &o, l4_msgtag_t const &tag) +{ + L4::IOBackend::Mode m = o.be_mode(); + o << "[l=" << L4::dec << tag.label() << "; w=" << tag.words() << "; i=" + << tag.items() << "]"; + o.be_mode(m); + return o; +} + +template +inline +L4::BasicOStream &operator << (L4::BasicOStream &o, L4::Cap const &cap) +{ + o << "[C:" << L4::n_hex(cap.cap()) << "]"; + return o; +} + + +#endif diff --git a/l4/pkg/cxx/lib/io/include/l4iostream.h b/l4/pkg/cxx/lib/io/include/l4iostream.h new file mode 100644 index 00000000..feaaf852 --- /dev/null +++ b/l4/pkg/cxx/lib/io/include/l4iostream.h @@ -0,0 +1,4 @@ +#pragma once + +#warning 'l4iostream.h' is deprecated, use 'l4iostream' instead. +#include diff --git a/l4/pkg/cxx/lib/io/src/Makefile b/l4/pkg/cxx/lib/io/src/Makefile new file mode 100644 index 00000000..81f23d38 --- /dev/null +++ b/l4/pkg/cxx/lib/io/src/Makefile @@ -0,0 +1,12 @@ +PKGDIR ?= ../../.. +L4DIR ?= $(PKGDIR)/../.. + +TARGET = libcxx_io +SRC_CC = iob_write.cc +PC_FILENAME = cxx_io +SYSTEMS = $(SYSTEMS_PLAIN) + +include $(PKGDIR)/lib/Makefile.inc +include $(L4DIR)/mk/lib.mk + +$(GENERAL_D_LOC): $(L4DIR)/pkg/cxx/lib/Makefile.inc diff --git a/l4/pkg/cxx/lib/io/src/iob_write.cc b/l4/pkg/cxx/lib/io/src/iob_write.cc new file mode 100644 index 00000000..207111be --- /dev/null +++ b/l4/pkg/cxx/lib/io/src/iob_write.cc @@ -0,0 +1,101 @@ +/* + * (c) 2004-2009 Adam Lackorzynski , + * Alexander Warg , + * Frank Mehnert + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ + +#include + +namespace L4 +{ + + IOModifier const hex(16); + IOModifier const dec(10); + + static char const hex_chars[] = "0123456789abcdef"; + + void IOBackend::write(IOModifier m) + { + if(m == dec) + int_mode = 10; + else if(m == hex) + int_mode = 16; + } + + void IOBackend::write(long long int u, int /*len*/) + { + char buffer[20]; + int pos = 20; + bool sign = u < 0; + if(sign) u=-u; + buffer[19] = '0'; + while(u) + { + buffer[--pos] = hex_chars[(u % int_mode)]; + u /= int_mode; + } + if(pos==20) + pos = 19; + if(sign) + buffer[--pos] = '-'; + + write(buffer + pos, 20-pos); + } + + void IOBackend::write(long long unsigned u, int /*len*/) + { + char buffer[20]; + int pos = 20; + buffer[19] = '0'; + while(u) + { + buffer[--pos] = hex_chars[(u % int_mode)]; + u /= int_mode; + } + if(pos==20) + pos = 19; + + write(buffer + pos, 20-pos); + } + + void IOBackend::write(long long unsigned u, unsigned char base, + unsigned char len, char pad) + { + char buffer[30]; + unsigned pos = sizeof(buffer); + buffer[sizeof(buffer)-1] = '0'; + while (pos > 0 && u) + { + buffer[--pos] = hex_chars[(u % base)]; + u /= base; + } + + if (len >sizeof(buffer)) + len = sizeof(buffer); + + if (len && sizeof(buffer)-pos > len) + pos = sizeof(buffer) - len; + + while (sizeof(buffer)-pos < len) + buffer[--pos] = pad; + + if (pos==sizeof(buffer)) + pos--; + + write(buffer + pos, sizeof(buffer)-pos); + } +}; diff --git a/l4/pkg/cxx/lib/ipc/Makefile b/l4/pkg/cxx/lib/ipc/Makefile new file mode 100644 index 00000000..0e4201e8 --- /dev/null +++ b/l4/pkg/cxx/lib/ipc/Makefile @@ -0,0 +1,6 @@ +PKGDIR = ../.. +L4DIR ?= $(PKGDIR)/../.. + +TARGET := include + +include $(L4DIR)/mk/subdir.mk diff --git a/l4/pkg/cxx/lib/ipc/include/Makefile b/l4/pkg/cxx/lib/ipc/include/Makefile new file mode 100644 index 00000000..518974ab --- /dev/null +++ b/l4/pkg/cxx/lib/ipc/include/Makefile @@ -0,0 +1,5 @@ +PKGDIR = ../../.. +L4DIR ?= $(PKGDIR)/../.. +EXTRA_TARGET := ipc_helper ipc_stream ipc_server + +include $(L4DIR)/mk/include.mk diff --git a/l4/pkg/cxx/lib/ipc/include/ipc_helper b/l4/pkg/cxx/lib/ipc/include/ipc_helper new file mode 100644 index 00000000..7afaad89 --- /dev/null +++ b/l4/pkg/cxx/lib/ipc/include/ipc_helper @@ -0,0 +1,64 @@ +// vi:ft=cpp +/** + * \file + * \brief IPC helper + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ + +#pragma once + +#include +#include + +namespace L4 +{ + + +#ifdef __EXCEPTIONS + /** + * \brief Throw an L4 IPC error as exception. + * + * \ingroup helper + * \param o the client side object, for which the IPC was invoked. + * \param err the IPC result code (error code). + */ + inline void + throw_ipc_exception(L4::Cap const &o, l4_msgtag_t const &err, + l4_utcb_t *utcb) + { + (void)o; + if (err.has_error()) + throw (L4::Com_error(l4_error_u(err, utcb))); + } + + /** + * \brief Throw an L4 IPC error as exception. + * + * \ingroup helper + * \param o the client side object, for which the IPC was invoked. + * \param err the IPC result code (error code). + */ + inline void + throw_ipc_exception(void const *o, l4_msgtag_t const &err, + l4_utcb_t *utcb) + { throw_ipc_exception(L4::Cap(o), err, utcb); } +#endif + +}; diff --git a/l4/pkg/cxx/lib/ipc/include/ipc_server b/l4/pkg/cxx/lib/ipc/include/ipc_server new file mode 100644 index 00000000..df81421c --- /dev/null +++ b/l4/pkg/cxx/lib/ipc/include/ipc_server @@ -0,0 +1,348 @@ +// vi:ft=cpp +/** + * \file + * \brief IPC server loop + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg , + * Torsten Frenzel + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ + +#pragma once + +#include +#include +#include +#include +#include + +namespace L4 { + +/** + * \brief Helper classes for L4::Server instantiation. + */ +namespace Ipc_svr { + +/** + * \brief Reply mode for server loop. + * + * The reply mode specifies if the server loop shall do a compound reply + * and wait operation (#Reply_compund), which is the most performant + * method. Note, setup_wait() is called before the reply. The other + * way is to call reply and wait separately and call setup_wait in between. + * + * The actual mode is determined by the return value of the before_reply() + * hook in the LOOP_HOOKS of L4::Server. + */ +enum Reply_mode +{ + Reply_compound, ///< Server shall use a compound reply and wait (fast). + Reply_separate ///< Server shall call reply and wait separately. +}; + +/** + * \brief Mix in for LOOP_HOOKS to ignore IPC errors. + */ +struct Ignore_errors +{ static void error(l4_msgtag_t, L4::Ipc::Iostream const &) {} }; + +/** + * \brief Mix in for LOOP_HOOKS to use a 0 send and a infinite receive timeout. + */ +struct Default_timeout +{ static l4_timeout_t timeout() { return L4_IPC_SEND_TIMEOUT_0; } }; + +/** + * \brief Mix in for LOOP_HOOKS to always use compound reply and wait. + */ +struct Compound_reply +{ + static Reply_mode before_reply(long, L4::Ipc::Ostream const &) + { return Reply_compound; } +}; + +/** + * \brief Mix in for LOOP_HOOKS for setup_wait no op. + */ +struct Default_setup_wait +{ static void setup_wait(L4::Ipc::Istream &, Reply_mode) {} }; + +/** + * \brief Default LOOP_HOOKS. + * + * Combination of Ignore_errors, Default_timeout, Compound_reply, + * and Default_setup_wait. + */ +struct Default_loop_hooks : + public Ignore_errors, public Default_timeout, public Compound_reply, + public Default_setup_wait +{}; + + +template< typename HOOKS > +class Timed_work : public HOOKS +{ +protected: + l4_cpu_time_t _timeout; + +public: + Timed_work() + : _timeout(HOOKS::next_timeout(HOOKS::current_time())) {} + + l4_timeout_t timeout() + { + return l4_timeout(L4_IPC_TIMEOUT_0, + l4_timeout_abs(_timeout, this->timeout_br())); + } + + void setup_wait(L4::Ipc::Istream &s, Reply_mode mode) + { + if (_timeout <= this->current_time() + && mode == Reply_separate) + { + this->work(); + _timeout = this->next_timeout(_timeout); + } + HOOKS::setup_wait(s, mode); + } + + Reply_mode before_reply(long, L4::Ipc::Ostream const &) + { + if (_timeout <= this->current_time()) + return Reply_separate; + return Reply_compound; + } +}; + +template< typename R > +struct Direct_dispatch +{ + R &r; + Direct_dispatch(R &r) : r(r) {} + long operator () (l4_umword_t obj, L4::Ipc::Iostream &ios) + { return r.dispatch(obj, ios); } +}; + +template< typename R > +struct Direct_dispatch +{ + R *r; + Direct_dispatch(R *r) : r(r) {} + long operator () (l4_umword_t obj, L4::Ipc::Iostream &ios) + { return r->dispatch(obj, ios); } +}; + +template< typename R, typename Exc = L4::Runtime_error> +struct Exc_dispatch : private Direct_dispatch +{ + Exc_dispatch(R r) : Direct_dispatch(r) {} + long operator () (l4_umword_t obj, L4::Ipc::Iostream &ios) + { + try + { + return Direct_dispatch::operator () (obj, ios); + } + catch (Exc &e) + { + return e.err_no(); + } + } +}; + +} + +/** + * \brief Basic server loop for handling client requests. + * \ingroup client_server_ipc + * \param LOOP_HOOKS the server inherits from LOOP_HOOKS and calls the + * hooks defined in LOOP_HOOKS in the server loop. + * See Ipc_svr::Default_loop_hooks, Ipc_svr::Ignore_errors, + * Ipc_svr::Default_timeout, Ipc_svr::Compound_reply, and + * Ipc_svr::Default_setup_wait. + * + * This is basically a simple server loop that uses a single message buffer + * for receiving requests and sending replies. The dispatcher determines + * how incoming messages are handled. + */ +template< typename LOOP_HOOKS = Ipc_svr::Default_loop_hooks > +class Server : + public LOOP_HOOKS +{ +public: + /** + * \brief Initializes the server loop and its underlying Ipc::Iostream. + * \param utcb The UTCB of the thread running the server loop. + */ + explicit Server(l4_utcb_t *utcb) : _iostream(utcb) {} + + /** + * \brief The server loop. + * + * This function usually never returns, it waits for + * incoming messages calls the dispatcher, sends a reply and waits again. + */ + template< typename DISPATCH > + inline L4_NORETURN void internal_loop(DISPATCH dispatch); + + template< typename R > + inline L4_NORETURN void loop_noexc(R r) + { internal_loop(Ipc_svr::Direct_dispatch(r)); } + + template< typename R > + inline L4_NORETURN void loop(R r) + { internal_loop(Ipc_svr::Exc_dispatch(r)); } + +protected: + inline l4_msgtag_t reply_n_wait(long reply, l4_umword_t *p); + +public: + Ipc::Iostream _iostream; +}; + +template< typename L > +inline l4_msgtag_t +Server::reply_n_wait(long reply, l4_umword_t *p) +{ + if (reply != -L4_ENOREPLY) + { + Ipc_svr::Reply_mode m = this->before_reply(reply, _iostream); + if (m == Ipc_svr::Reply_compound) + { + this->setup_wait(_iostream, m); + return _iostream.reply_and_wait(p, this->timeout(), reply); + } + else + { + l4_msgtag_t res = _iostream.reply(this->timeout(), reply); + if (res.has_error()) + return res; + } + } + this->setup_wait(_iostream, Ipc_svr::Reply_separate); + return _iostream.wait(p, this->timeout()); +} + +template< typename L > +template< typename DISPATCH > +inline L4_NORETURN void +Server::internal_loop(DISPATCH dispatch) +{ + l4_msgtag_t res; + l4_umword_t p; + long r = -L4_ENOREPLY; + + while (true) + { + res = reply_n_wait(r, &p); + if (res.has_error()) + { + this->error(res, _iostream); + r = -L4_ENOREPLY; + continue; + } + + _iostream.Ipc::Ostream::reset(); + r = dispatch(p, _iostream); + } +} + + + + +/** + * \brief Abstract server object to be used with L4::Server and L4::Basic_registry. + * \ingroup client_server_ipc + * + * This server object provides an abstract interface that is used by the + * L4::Registry_dispatcher model. You can derive subclasses from this + * interface and implement application specific server objects. + */ +class Server_object +{ +public: + /** + * \brief The abstract handler for client requests to the object. + * \param obj The object ID used for looking up the object. + * \param ios The Ipc::Iostream for reading the request and writing the reply. + * \return #Reply, #No_reply, or #Invalid_opcode. + * + * This function must be implemented by application specific server + * objects. The implementation must unmarshall data from the stream (\a ios) + * and create a reply by marshalling to the stream (\a ios). For details + * about the IPC stream see \link ipc_stream IPC stream operators \endlink. + * + * \note You need to extract the complete message from the \a ios stream before + * inserting any reply data or before doing any function call that may use + * the UTCB. Otherwise, the incoming message may get lost. + */ + virtual int dispatch(unsigned long obj, Ipc::Iostream &ios) = 0; + virtual ~Server_object() = 0; + + + Cap obj_cap() const { return _cap; } + template< typename T> + void obj_cap(Cap const &cap) { _cap = cap; } + void obj_cap(Cap const &cap) { _cap = cap; } + +private: + Cap _cap; +}; + +inline Server_object::~Server_object() {} + +/** + * \brief This registry returns the corresponding server object + * based on the label of an Ipc_gate. + * \ingroup client_server_ipc + */ +class Basic_registry +{ +public: + /** + * \brief Get the server object for a Ipc_gate label. + * \param label The label usually stored in an Ipc_gate. + * \return A pointer to the Server_object identified the given label. + */ + typedef Server_object Value; + static Value *find(l4_umword_t label) + { return reinterpret_cast(label & ~3UL); } + + /** + * \brief The dispatch function called by the server loop. + * + * This function forwards the message to the server object identified by the + * given \a label. + * + * \param label The label used to find the object including the rights bits + * of the invoked capability. + * \param ios The Ipc::Iostream for the request and the reply. + * \return The return code from the object's dispatch function or -L4_ENOENT + * if the object does not exist. + */ + static int dispatch(l4_umword_t label, L4::Ipc::Iostream &ios) + { + Value *o = find(label); + + if (!o) + return -L4_ENOENT; + + return o->dispatch(label, ios); + } +}; + +} diff --git a/l4/pkg/cxx/lib/ipc/include/ipc_stream b/l4/pkg/cxx/lib/ipc/include/ipc_stream new file mode 100644 index 00000000..d1db894b --- /dev/null +++ b/l4/pkg/cxx/lib/ipc/include/ipc_stream @@ -0,0 +1,1493 @@ +// vi:ft=cpp +/** + * \file + * \brief IPC stream + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg , + * Torsten Frenzel + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ + +#pragma once + +#include +#include +#include + +#define L4_CXX_IPC_BACKWARD_COMPAT 1 + +namespace L4 { + +typedef int Opcode; + +namespace Ipc { + +class Ostream; +class Istream; + +/** + * \brief Abstraction for inserting an array into an Ipc::Ostream. + * \ingroup ipc_fw + * + * An object of Buf_cp_out can be used to insert an array of arbitrary values, + * that can be inserted into an Ipc::Ostream individually. + * The array is therefore copied to the message buffer, in contrast to + * data handled with Msg_out_buffer or Msg_io_buffer. + * + * On insertion into the Ipc::Ostream exactly the given number of elements + * of type T are copied to the message buffer, this means the source buffer + * is no longer referenced after insertion into the stream. + * + * You should use buf_cp_out() to create instances of Buf_cp_out. + * + * The counterpart is either Buf_cp_in (buf_cp_in()) or Buf_in (buf_in()). + */ +template< typename T > +class Buf_cp_out +{ +public: + /** + * \brief Create a buffer object for the given array. + * \param v The pointer to the array with size elements of type T. + * \param size the number of elements in the array. + */ + Buf_cp_out(T *v, unsigned long size) : _v(v), _s(size) {} + + /** + * \brief Get the number of elements in the array. + * \note This function is usually used by the Ipc::Ostream itself. + */ + unsigned long size() const { return _s; } + + /** + * \brief Get the pointer to the array. + * \note This function is usually used by the Ipc::Ostream itself. + */ + T *buf() const { return _v; } + +private: + friend class Ostream; + T *_v; + unsigned long _s; +}; + +/** + * \brief Create an instance of Buf_cp_out for the given values. + * \ingroup ipc_fw + * + * This function makes it more convenient to insert arrays into an + * Ipc::Ostream (\see Buf_cp_out.) + * + * \param v Pointer to the array that shall be inserted into an Ipc::Ostream. + * \param size Number of elements in the array. + */ +template< typename T > +Buf_cp_out buf_cp_out(T *v, unsigned long size) +{ return Buf_cp_out(v,size); } + + +/** + * \brief Abstraction for extracting array from an Ipc::Istream. + * \ingroup ipc_fw + * + * An instance of Buf_cp_in can be used to extract an array from + * an Ipc::Istream. This is the counterpart to the Buf_cp_out abstraction. + * The data from the received message is thereby copied to the given buffer + * and size is set to the number of elements found in the stream. + * To avoid the copy operation Buf_in may be used instead. + * + * \see buf_cp_in(), Buf_in, buf_in(), Buf_cp_out, and buf_cp_out(). + */ +template< typename T > +class Buf_cp_in +{ +public: + /** + * \brief Create a buffer for extracting an array from an Ipc::Istream. + * \param v The buffer for array (copy in). + * \param size Input: the number of elements the array can take at most
+ * Output: the number of elements found in the stream. + */ + Buf_cp_in(T *v, unsigned long &size) : _v(v), _s(&size) {} + + unsigned long &size() const { return *_s; } + T *buf() const { return _v; } +private: + friend class Istream; + T *_v; + unsigned long *_s; +}; + +/** + * \brief Create an Buf_cp_in for the given values. + * \ingroup ipc_fw + * + * This function makes it more convenient to extract arrays from an + * Ipc::Istream (\see Buf_cp_in.) + * + * \param v Pointer to the array that shall receive the values from the + * Ipc::Istream. + * \param size Input: the number of elements the array can take at most
+ * Output: the number of elements found in the stream. + * + * \see buf_in() and buf_cp_out(). + */ +template< typename T > +Buf_cp_in buf_cp_in(T *v, unsigned long &size) +{ return Buf_cp_in(v,size); } + + +/** + * \brief Pointer to an element of type T in an Ipc::Istream. + * \ingroup ipc_fw + * + * This wrapper can be used to extract an element of type T from an + * Ipc::Istream, whereas the data is not copied out, but a pointer into + * the message buffer itself is returned. With is mechanism it is possible + * to avoid an extra copy of large data structures from a received IPC + * message, instead the returned pointer gives direct access to the data + * in the message. + * + * See msg_ptr(). + */ +template< typename T > +class Msg_ptr +{ +private: + T **_p; +public: + /** + * \brief Create a Msg_ptr object that set pointer p to point into the + * message buffer. + * \param p The pointer that is adjusted to point into the message buffer. + */ + explicit Msg_ptr(T *&p) : _p(&p) {} + void set(T *p) const { *_p = p; } +}; + +/** + * \brief Create an Msg_ptr to adjust the given pointer. + * \ingroup ipc_fw + * + * This function makes it more convenient to extract pointers to data in the + * message buffer itself from an Ipc::Istream. + * This may be used to avoid copy out of large data structures. + * (See Msg_ptr.) + */ +template< typename T > +Msg_ptr msg_ptr(T *&p) +{ return Msg_ptr(p); } + + +/** + * \brief Abstraction to extract an array from an Ipc::Istream. + * \ingroup ipc_fw + * + * This wrapper provides a possibility to extract an array from an + * Ipc::Istream, without extra copy overhead. In contrast to Buf_cp_in + * the data is not copied to a buffer, but a pointer to the array is returned. + * + * The mechanism is comparable to that of Msg_ptr, however it handles arrays + * inserted with Buf_cp_out. + * + * See buf_in(), Buf_cp_out, buf_cp_out(), Buf_cp_in, and buf_cp_in(). + */ +template< typename T > +class Buf_in +{ +public: + /** + * \brief Create an Buf_in to adjust a pointer to the array and the size + * of the array. + * \param v The pointer to adjust to the first element of the array. + * \param size The number of elements found in the stream. + */ + Buf_in(T *&v, unsigned long &size) : _v(&v), _s(&size) {} + + void set_size(unsigned long s) const { *_s = s; } + T *&buf() const { return *_v; } +private: + friend class Istream; + T **_v; + unsigned long *_s; +}; + +/** + * \brief Create an Buf_in for the given values. + * \ingroup ipc_fw + * + * This function makes it more convenient to extract arrays from an + * Ipc::Istream (See Buf_in.) + * + * \param v Output: pointer to the array within the Ipc::Istream. + * \param size Output: the number of elements found in the stream. + * + * See buf_cp_in() and buf_cp_out(). + */ +template< typename T > +Buf_in buf_in(T *&v, unsigned long &size) +{ return Buf_in(v, size); } + + + +/** + * \brief A receive item for receiving a single capability. + * + * This class is the main abstraction for receiving capabilities + * via Ipc::Istream. To receive a capability an instance of Small_buf + * that refers to an empty capability slot must be inserted into the + * Ipc::Istream before the receive operation. + */ +class Small_buf +{ +public: + explicit Small_buf(L4::Cap cap, unsigned long flags = 0) + : _data(cap.cap() | L4_RCV_ITEM_SINGLE_CAP | flags) {} + + explicit Small_buf(l4_cap_idx_t idx, unsigned long flags = 0) + : _data(idx | L4_RCV_ITEM_SINGLE_CAP | flags) {} +private: + l4_umword_t _data; +}; + +class Snd_item +{ +public: + Snd_item(l4_umword_t base, l4_umword_t data) : _base(base), _data(data) {} + +protected: + l4_umword_t _base; + l4_umword_t _data; +}; + +class Buf_item +{ +public: + Buf_item(l4_umword_t base, l4_umword_t data) : _base(base), _data(data) {} + +protected: + l4_umword_t _base; + l4_umword_t _data; +}; + +template< typename T > +class Gen_fpage : public T +{ +public: + enum Type + { + Special = L4_FPAGE_SPECIAL << 4, + Memory = L4_FPAGE_MEMORY << 4, + Io = L4_FPAGE_IO << 4, + Obj = L4_FPAGE_OBJ << 4 + }; + + enum Map_type + { + Map = L4_MAP_ITEM_MAP, + Grant = L4_MAP_ITEM_GRANT, + }; + + enum Cacheopt + { + None = 0, + Cached = L4_FPAGE_CACHEABLE << 4, + Buffered = L4_FPAGE_BUFFERABLE << 4, + Uncached = L4_FPAGE_UNCACHEABLE << 4 + }; + + enum Continue + { + Single = 0, + Last = 0, + More = L4_ITEM_CONT, + Compound = L4_ITEM_CONT, + }; + +private: + Gen_fpage(Type type, l4_addr_t base, int order, + unsigned char rights, + l4_addr_t snd_base, + Map_type map_type, + Cacheopt cache, Continue cont) + : T(L4_ITEM_MAP | (snd_base & (~0UL << 10)) | l4_umword_t(map_type) | l4_umword_t(cache) + | l4_umword_t(cont), + base | l4_umword_t(type) | rights | (l4_umword_t(order) << 6)) + {} + +public: + Gen_fpage() : T(0, 0) {} + Gen_fpage(l4_fpage_t const &fp, l4_addr_t snd_base = 0, + Map_type map_type = Map, + Cacheopt cache = None, Continue cont = Last) + : T(L4_ITEM_MAP | (snd_base & (~0UL << 10)) | l4_umword_t(map_type) | l4_umword_t(cache) + | l4_umword_t(cont), + fp.raw) + {} + + Gen_fpage(L4::Cap cap, unsigned rights) + : T(L4_ITEM_MAP | Map | (rights & 0xf0), cap.fpage(rights).raw) + {} + + static Gen_fpage obj(l4_addr_t base, int order, + unsigned char rights, + l4_addr_t snd_base = 0, + Map_type map_type = Map, + Continue cont = Last) + { return Gen_fpage(Obj, base << 12, order, rights, snd_base, map_type, None, cont); } + static Gen_fpage mem(l4_addr_t base, int order, + unsigned char rights, + l4_addr_t snd_base = 0, + Map_type map_type = Map, + Cacheopt cache = None, Continue cont = Last) + { return Gen_fpage(Memory, base, order, rights, snd_base, + map_type, cache, cont); } + static Gen_fpage io(l4_addr_t base, int order, + unsigned char rights, + l4_addr_t snd_base = 0, + Map_type map_type = Map, + Continue cont = Last) + { return Gen_fpage(Io, base << 12, order, rights, snd_base, map_type, None, cont); } + + unsigned order() const { return (T::_data >> 6) & 0x3f; } + unsigned snd_order() const { return (T::_data >> 6) & 0x3f; } + unsigned rcv_order() const { return (T::_base >> 6) & 0x3f; } + l4_addr_t base() const { return T::_data & (~0UL << 12); } + l4_addr_t snd_base() const { return T::_base & (~0UL << 10); } + void snd_base(l4_addr_t b) { T::_base = (T::_base & ~(~0UL << 10)) | (b & (~0UL << 10)); } + + bool is_valid() const { return T::_base & L4_ITEM_MAP; } + // A cap has been mapped + bool cap_received() const { return (T::_base & 0x3e) == 0x38; } + // the label out of an IPC gate has been received, L4_RCV_ITEM_LOCAL_ID + // must be specified, and the IPC gate must be local to the receiver + // (i.e., the target thread of the IPC gate is in the same task as the + // receiving thread) + bool id_received() const { return (T::_base & 0x3e) == 0x3c; } + // Sender and receiver are in the same task, set only iff + // L4_RCV_ITEM_LOCAL_ID has been specified by the receiver, the value + // delivered is the cap-index (in the task) + bool local_id_received() const { return (T::_base & 0x3e) == 0x3e; } + l4_umword_t data() const { return T::_data; } + l4_umword_t base_x() const { return T::_base; } +}; + + +typedef Gen_fpage Snd_fpage; +typedef Gen_fpage Rcv_fpage; + +#ifdef L4_CXX_IPC_SUPPORT_STRINGS +template +class Gen_string : public T +{ +public: + Gen_string() : T(0,0) {} + Gen_string(B buf, unsigned long size) + : T(size << 10, l4_umword_t(buf)) + {} + + unsigned long len() const { return T::_base >> 10; } +}; + +typedef Gen_string Snd_string; +typedef Gen_string Rcv_string; +#endif + + +template< typename T, template class B > struct Generic_va_type : public B +{ + enum { Id = B::Id }; + typedef B ID; + typedef T const &Ret_value; + typedef T Value; + + static Ret_value value(void const *d) + { return *reinterpret_cast(d); } + + static void const *addr_of(Value const &v) { return &v; } + + static unsigned size(void const *) { return sizeof(T); } + + static L4_varg_type unsigned_id() { return (L4_varg_type)(Id & ~L4_VARG_TYPE_SIGN); } + static L4_varg_type signed_id() { return (L4_varg_type)(Id | L4_VARG_TYPE_SIGN); } + static L4_varg_type id() { return (L4_varg_type)Id; } +}; + +template< typename T > struct Va_type_id; +template<> struct Va_type_id { enum { Id = L4_VARG_TYPE_UMWORD }; }; +template<> struct Va_type_id { enum { Id = L4_VARG_TYPE_MWORD }; }; +template<> struct Va_type_id { enum { Id = L4_VARG_TYPE_FPAGE }; }; +template<> struct Va_type_id { enum { Id = L4_VARG_TYPE_NIL }; }; +template<> struct Va_type_id { enum { Id = L4_VARG_TYPE_STRING }; }; + +template< typename T > struct Va_type; + +template<> struct Va_type : public Generic_va_type {}; +template<> struct Va_type : public Generic_va_type {}; +template<> struct Va_type : public Generic_va_type {}; + +template<> struct Va_type +{ + typedef void Ret_value; + typedef void Value; + + static void const *addr_of(void) { return 0; } + + static void value(void const *) {} + static L4_varg_type id() { return L4_VARG_TYPE_NIL; } + static unsigned size(void const *) { return 0; } +}; + +template<> struct Va_type +{ + typedef char const *Ret_value; + typedef char const *Value; + + static void const *addr_of(Value v) { return v; } + + static L4_varg_type id() { return L4_VARG_TYPE_STRING; } + static unsigned size(void const *s) + { + char const *_s = reinterpret_cast(s); + int l = 1; + while (*_s) + { + ++_s; ++l; + } + return l; + } + + static Ret_value value(void const *d) { return (char const *)d; } +}; + + +class Varg +{ +private: + l4_umword_t _tag; + char const *_d; + +public: + + typedef l4_umword_t Tag; + + L4_varg_type type() const { return (L4_varg_type)(_tag & 0xff); } + int length() const { return _tag >> 16; } + + void tag(Tag tag) { _tag = tag; } + Tag tag() const { return _tag; } + void data(char const *d) { _d = d; } + + char const *data() const { return _d; } + char const *&data() { return _d; } + + Varg() : _tag(0), _d(0) {} + + Varg(L4_varg_type t, void const *v, int len) + : _tag(t | ((l4_mword_t)len << 16)), _d((char const *)v) + {} + + template< typename V > + typename Va_type::Ret_value value() const + { return Va_type::value(_d); } + + + template< typename T > + bool is_of() const { return Va_type::id() == type(); } + + bool is_nil() const { return is_of(); } + + bool is_of_int() const + { return (type() & ~L4_VARG_TYPE_SIGN) == L4_VARG_TYPE_UMWORD; } + + template< typename T > + bool get_value(typename Va_type::Value *v) const + { + if (!is_of()) + return false; + + *v = Va_type::value(_d); + return true; + } + + template< typename T > + void set_value(void const *d) + { + typedef Va_type Vt; + _tag = Vt::id() | (Vt::size(d) << 16); + _d = (char const *)d; + } + +}; + +template +class Varg_t : public Varg +{ +public: + typedef typename Va_type::Value Value; + explicit Varg_t(Value v) : Varg() + { _data = v; set_value(Va_type::addr_of(_data)); } + +private: + Value _data; +}; + +namespace Utcb_stream_check +{ + static bool check_utcb_data_offset(unsigned sz) + { return sz > sizeof(l4_umword_t) * L4_UTCB_GENERIC_DATA_SIZE; } +} + + +/** + * \brief Input stream for IPC unmarshalling. + * \ingroup ipc_fw + * + * Ipc::Istream is part of the dynamic IPC marshalling infrastructure, as well + * as Ipc::Ostream and Ipc::Iostream. + * + * Ipc::Istream is an input stream supporting extraction of values from an + * IPC message buffer. A received IPC message can be unmarshalled using the + * usual extraction operator (>>). + * + * There exist some special wrapper classes to extract arrays (see + * Ipc_buf_cp_in and Ipc_buf_in) and indirect strings (see Msg_in_buffer and + * Msg_io_buffer). + */ +class Istream +{ +public: + /** + * \brief Create an input stream for the given message buffer. + * + * The given message buffer is used for IPC operations wait()/receive() + * and received data can be extracted using the >> operator afterwards. + * In the case of indirect message parts a buffer of type Msg_in_buffer + * must be inserted into the stream before the IPC operation and contains + * received data afterwards. + * + * \param msg The message buffer to receive IPC messages. + */ + Istream(l4_utcb_t *utcb) + : _tag(), _utcb(utcb), + _current_msg(reinterpret_cast(l4_utcb_mr_u(utcb)->mr)), + _pos(0), _current_buf(0) + {} + + /** + * \brief Reset the stream to empty, and ready for receive()/wait(). + * The stream is reset to the same state as on its creation. + */ + void reset() + { + _pos = 0; + _current_buf = 0; + _current_msg = reinterpret_cast(l4_utcb_mr_u(_utcb)->mr); + } + + /** + * \brief Check whether a value of type T can be obtained from the stream. + */ + template< typename T > + bool has_more() + { + unsigned apos = cxx::Type_traits::align(_pos); + return apos + sizeof(T) <= _tag.words() * sizeof(l4_umword_t); + } + + /** + * \name Get/Put Functions. + * These functions are basically used to implement the extraction operators + * (>>) and should not be called directly. + * + * See \link ipc_stream IPC stream operators \endlink. + */ + //@{ + + /** + * \brief Copy out an array of type \a T with \a size elements. + * + * \param buf Pointer to a buffer for size elements of type T. + * \param size number of elements of type T to copy out. + * + * See \link ipc_stream IPC stream operators \endlink. + */ + template< typename T > + unsigned long get(T *buf, unsigned long elems) + { + unsigned long size = elems * sizeof(T); + _pos = cxx::Type_traits::align(_pos); + if (Utcb_stream_check::check_utcb_data_offset(_pos + size)) + return 0; + + __builtin_memcpy(buf, _current_msg + _pos, size); + _pos += size; + return elems; + } + + + /** + * \brief Skip size elements of type T in the stream. + * \param size number of elements to skip. + */ + template< typename T > + void skip(unsigned long size) + { + size *= sizeof(T); + _pos = cxx::Type_traits::align(_pos); + if (Utcb_stream_check::check_utcb_data_offset(_pos + size)) + return; + _pos += size; + } + + /** + * \brief Read one size elements of type T from the stream and return + * a pointer. + * + * In contrast to a normal get, this version does actually not copy the data + * but returns a pointer to the data. + * + * \param buf a Msg_ptr that is actually set to point to the element in the + * stream. + * \param size number of elements to extract (default is 1). + * + * See \link ipc_stream IPC stream operators \endlink. + */ + template< typename T > + unsigned long get(Msg_ptr const &buf, unsigned long size = 1) + { + size *= sizeof(T); + _pos = cxx::Type_traits::align(_pos); + if (Utcb_stream_check::check_utcb_data_offset(_pos + size)) + return 0; + + buf.set(reinterpret_cast(_current_msg + _pos)); + _pos += size; + return size; + } + + + /** + * \brief Extract a single element of type T from the stream. + * \param v Output: the element. + * + * See \link ipc_stream IPC stream operators \endlink. + */ + template< typename T > + void get(T &v) + { + _pos = cxx::Type_traits::align(_pos); + if (Utcb_stream_check::check_utcb_data_offset(_pos + sizeof(T))) + { + v = T(); + return; + } + v = *(reinterpret_cast(_current_msg + _pos)); + _pos += sizeof(T); + } + + + bool get(Ipc::Varg *va) + { + Ipc::Varg::Tag t; + if (!has_more()) + { + va->tag(0); + return 0; + } + get(t); + va->tag(t); + get(msg_ptr(va->data()), va->length()); + + return 1; + } + + /** + * \brief Get the message tag of a received IPC. + * \return The L4 message tag for the received IPC. + * + * This is in particular useful for handling page faults or exceptions. + * + * See \link ipc_stream IPC stream operators \endlink. + */ + l4_msgtag_t tag() const { return _tag; } + + + /** + * \brief Get the message tag of a received IPC. + * \return A reference to the L4 message tag for the received IPC. + * + * This is in particular useful for handling page faults or exceptions. + * + * See \link ipc_stream IPC stream operators \endlink. + */ + l4_msgtag_t &tag() { return _tag; } + + //@} + + /** + * \internal + * \brief Put a receive item into the stream's buffer registers. + */ + inline bool put(Buf_item const &); + + /** + * \internal + * \brief Put a small receive item into the stream's buffer registers. + */ + inline bool put(Small_buf const &); + + + /** + * \name IPC operations. + */ + //@{ + + /** + * \brief Wait for an incoming message from any sender. + * \param src contains the sender after a successful IPC operation. + * \return The IPC result dope (l4_msgtag_t). + * + * This wait is actually known as 'open wait'. + */ + inline l4_msgtag_t wait(l4_umword_t *src) + { return wait(src, L4_IPC_NEVER); } + + /** + * \brief Wait for an incoming message from any sender. + * \param src contains the sender after a successful IPC operation. + * \param timeout Timeout used for IPC. + * \return The IPC result dope (l4_msgtag_t). + * + * This wait is actually known as 'open wait'. + */ + inline l4_msgtag_t wait(l4_umword_t *src, l4_timeout_t timeout); + + /** + * \brief Wait for a message from the specified sender. + * \param src The sender id to receive from. + * \return The IPC result dope (l4_msgtag_t). + * + * This is commonly known as 'closed wait'. + */ + inline l4_msgtag_t receive(l4_cap_idx_t src) + { return receive(src, L4_IPC_NEVER); } + inline l4_msgtag_t receive(l4_cap_idx_t src, l4_timeout_t timeout); + + //@} + + /** + * \brief Return utcb pointer. + */ + inline l4_utcb_t *utcb() const { return _utcb; } + +protected: + l4_msgtag_t _tag; + l4_utcb_t *_utcb; + char *_current_msg; + unsigned _pos; + unsigned char _current_buf; +}; + +class Istream_copy : public Istream +{ +private: + l4_msg_regs_t _mrs; + +public: + Istream_copy(Istream const &o) : Istream(o), _mrs(*l4_utcb_mr_u(o.utcb())) + { + // do some reverse mr to utcb trickery + _utcb = (l4_utcb_t*)((l4_addr_t)&_mrs - (l4_addr_t)l4_utcb_mr_u((l4_utcb_t*)0)); + _current_msg = reinterpret_cast(l4_utcb_mr_u(_utcb)->mr); + } + +}; + +template< typename T > +inline +T read(Istream &s) { T t; s >> t; return t; } + + +/** + * \brief Output stream for IPC marshalling. + * \ingroup ipc_fw + * + * Ipc::Ostream is part of the dynamic IPC marshalling infrastructure, as well + * as Ipc::Istream and Ipc::Iostream. + * + * Ipc::Ostream is an output stream supporting insertion of values into an + * IPC message buffer. A IPC message can be marshalled using the + * usual insertion operator <<, see \link ipc_stream IPC stream operators + * \endlink. + * + * There exist some special wrapper classes to insert arrays (see + * Ipc::Buf_cp_out) and indirect strings (see Msg_out_buffer and + * Msg_io_buffer). */ +class Ostream +{ +public: + /** + * \brief Create an IPC output stream using the given message buffer \a msg. + */ + Ostream(l4_utcb_t *utcb) + : _tag(), _utcb(utcb), + _current_msg(reinterpret_cast(l4_utcb_mr_u(_utcb)->mr)), + _pos(0), _current_item(0) + {} + + /** + * \brief Reset the stream to empty, same state as a newly created stream. + */ + void reset() + { + _pos = 0; + _current_item = 0; + _current_msg = reinterpret_cast(l4_utcb_mr_u(_utcb)->mr); + } + + /** + * \name Get/Put functions. + * + * These functions are basically used to implement the insertion operators + * (<<) and should not be called directly. + * + * See \link ipc_stream IPC stream operators \endlink. + */ + //@{ + + /** + * \brief Put an array with \a size elements of type \a T into the stream. + * \param buf A pointer to the array to insert into the buffer. + * \param size The number of elements in the array. + */ + template< typename T > + void put(T *buf, unsigned long size) + { + size *= sizeof(T); + _pos = cxx::Type_traits::align(_pos); + if (Utcb_stream_check::check_utcb_data_offset(_pos + size)) + return; + + __builtin_memcpy(_current_msg + _pos, buf, size); + _pos += size; + } + + /** + * \brief Insert an element of type \a T into the stream. + * \param v The element to insert. + */ + template< typename T > + bool put(T const &v) + { + _pos = cxx::Type_traits::align(_pos); + if (Utcb_stream_check::check_utcb_data_offset(_pos + sizeof(T))) + return false; + + *(reinterpret_cast(_current_msg + _pos)) = v; + _pos += sizeof(T); + return true; + } + + int put(Varg const &va) + { + put(va.tag()); + put(va.data(), va.length()); + + return 0; + } + + template< typename T > + int put(Varg_t const &va) + { return put(static_cast(va)); } + + /** + * \brief Extract the L4 message tag from the stream. + * \return the extracted L4 message tag. + */ + l4_msgtag_t tag() const { return _tag; } + + /** + * \brief Extract a reference to the L4 message tag from the stream. + * \return A reference to the L4 message tag. + */ + l4_msgtag_t &tag() { return _tag; } + + //@} + + /** + * \internal + * \brief Put a send item into the stream's message buffer. + */ + inline bool put_snd_item(Snd_item const &); + + + /** + * \name IPC operations. + */ + //@{ + + /** + * \brief Send the message via IPC to the given receiver. + * \param dst The destination for the message. + */ + inline l4_msgtag_t send(l4_cap_idx_t dst, long proto = 0, unsigned flags = 0); + + //@} + + /** + * \brief Return utcb pointer. + */ + inline l4_utcb_t *utcb() const { return _utcb; } +#if 0 + /** + * \brief Get the currently used bytes in the stream. + */ + unsigned long tell() const + { + register unsigned w = (_pos + sizeof(l4_umword_t)-1) / sizeof(l4_umword_t); + w -= _current_item * 2; + _tag = l4_msgtag(0, w, _current_item, 0); + } +#endif +public: + l4_msgtag_t prepare_ipc(long proto = 0, unsigned flags = 0) + { + register unsigned w = (_pos + sizeof(l4_umword_t)-1) / sizeof(l4_umword_t); + w -= _current_item * 2; + return l4_msgtag(proto, w, _current_item, flags); + } + +protected: + l4_msgtag_t _tag; + l4_utcb_t *_utcb; + char *_current_msg; + unsigned _pos; + unsigned char _current_item; +}; + + +/** + * \brief Input/Output stream for IPC [un]marshalling. + * \ingroup ipc_fw + * + * The Ipc::Iostream is part of the AW Env IPC framework as well as + * Ipc::Istream and Ipc::Ostream. + * In particular an Ipc::Iostream is a combination of an Ipc::Istream and an + * Ipc::Ostream. It can use either a single message buffer for receiving and + * sending messages or a pair of a receive and a send buffer. The stream also + * supports combined IPC operations such as call() and reply_and_wait(), which + * can be used to implement RPC functionality. + */ +class Iostream : public Istream, public Ostream +{ +public: + + /** + * \brief Create an IPC IO stream with a single message buffer. + * \param msg The message buffer used as backing store. + * + * The created IO stream uses the same message buffer for sending and + * receiving IPC messages. + */ + explicit Iostream(l4_utcb_t *utcb) + : Istream(utcb), Ostream(utcb) + {} + + + /** + * \brief Reset the stream to its initial state. + * + * Input as well as the output stream are reset. + */ + void reset() + { + Istream::reset(); + Ostream::reset(); + } + + + /** + * \name Get/Put functions. + * + * These functions are basically used to implement the insertion operators + * (<<) and should not be called directly. + * + * See \link ipc_stream IPC stream operators \endlink. + */ + //@{ + + using Istream::get; + using Istream::put; + using Ostream::put; + + //@} + + /** + * \name IPC operations. + */ + //@{ + + /** + * \brief Do an IPC call using the message in the output stream and + * receiving to the input stream. + * \param dst The destination L4 UID (thread) to call. + * \return the result dope of the IPC operation. + * + * This is a combined IPC operation consisting of a send and a receive + * to/from the given destination \a dst. + * + * A call is usually used by clients for RPCs to a server. + * + */ + inline l4_msgtag_t call(l4_cap_idx_t dst); + inline l4_msgtag_t call(l4_cap_idx_t dst, long label); + + /** + * \brief Do an IPC reply and wait. + * \param src_dst Input: the destination for the send operation.
+ * Output: the source of the received message. + * \return the result dope of the IPC operation. + * + * This is a combined IPC operation consisting of a send operation and + * an open wait for any message. + * + * A reply and wait is usually used by servers that reply to a client + * and wait for the next request by any other client. + */ + inline l4_msgtag_t reply_and_wait(l4_umword_t *src_dst, long proto = 0) + { return reply_and_wait(src_dst, L4_IPC_SEND_TIMEOUT_0, proto); } + + inline l4_msgtag_t send_and_wait(l4_cap_idx_t dest, l4_umword_t *src, + long proto = 0) + { return send_and_wait(dest, src, L4_IPC_SEND_TIMEOUT_0, proto); } + + /** + * \brief Do an IPC reply and wait. + * \param src_dst Input: the destination for the send operation.
+ * Output: the source of the received message. + * \param timeout Timeout used for IPC. + * \return the result dope of the IPC operation. + * + * This is a combined IPC operation consisting of a send operation and + * an open wait for any message. + * + * A reply and wait is usually used by servers that reply to a client + * and wait for the next request by any other client. + */ + inline l4_msgtag_t reply_and_wait(l4_umword_t *src_dst, + l4_timeout_t timeout, long proto = 0); + inline l4_msgtag_t send_and_wait(l4_cap_idx_t dest, l4_umword_t *src, + l4_timeout_t timeout, long proto = 0); + inline l4_msgtag_t reply(l4_timeout_t timeout, long proto = 0); + inline l4_msgtag_t reply(long proto = 0) + { return reply(L4_IPC_SEND_TIMEOUT_0, proto); } + + //@} +}; + + +inline bool +Ostream::put_snd_item(Snd_item const &v) +{ + typedef Snd_item T; + _pos = cxx::Type_traits::align(_pos); + if (Utcb_stream_check::check_utcb_data_offset(_pos + sizeof(T))) + return false; + + *(reinterpret_cast(_current_msg + _pos)) = v; + _pos += sizeof(T); + ++_current_item; + return true; +} + + +inline bool +Istream::put(Buf_item const &item) +{ + if (_current_buf >= L4_UTCB_GENERIC_BUFFERS_SIZE - 3) + return false; + + l4_utcb_br_u(_utcb)->bdr &= ~L4_BDR_OFFSET_MASK; + + reinterpret_cast(l4_utcb_br_u(_utcb)->br[_current_buf]) = item; + _current_buf += 2; + return true; +} + + +inline bool +Istream::put(Small_buf const &item) +{ + if (_current_buf >= L4_UTCB_GENERIC_BUFFERS_SIZE - 2) + return false; + + l4_utcb_br_u(_utcb)->bdr &= ~L4_BDR_OFFSET_MASK; + + reinterpret_cast(l4_utcb_br_u(_utcb)->br[_current_buf]) = item; + _current_buf += 1; + return true; +} + + +inline l4_msgtag_t +Ostream::send(l4_cap_idx_t dst, long proto, unsigned flags) +{ + l4_msgtag_t tag = prepare_ipc(proto, L4_MSGTAG_FLAGS & flags); + return l4_ipc_send(dst, _utcb, tag, L4_IPC_NEVER); +} + +inline l4_msgtag_t +Iostream::call(l4_cap_idx_t dst) +{ + l4_msgtag_t tag = prepare_ipc(); + tag = l4_ipc_call(dst, Ostream::_utcb, tag, L4_IPC_NEVER); + Istream::tag() = tag; + Istream::_pos = 0; + return tag; +} + +inline l4_msgtag_t +Iostream::call(l4_cap_idx_t dst, long label) +{ + l4_msgtag_t tag = prepare_ipc(label); + tag = l4_ipc_call(dst, Ostream::_utcb, tag, L4_IPC_NEVER); + Istream::tag() = tag; + Istream::_pos = 0; + return tag; +} + + +inline l4_msgtag_t +Iostream::reply_and_wait(l4_umword_t *src_dst, l4_timeout_t timeout, long proto) +{ + l4_msgtag_t tag = prepare_ipc(proto); + tag = l4_ipc_reply_and_wait(Ostream::_utcb, tag, src_dst, timeout); + Istream::tag() = tag; + Istream::_pos = 0; + return tag; +} + + +inline l4_msgtag_t +Iostream::send_and_wait(l4_cap_idx_t dest, l4_umword_t *src, + l4_timeout_t timeout, long proto) +{ + l4_msgtag_t tag = prepare_ipc(proto); + tag = l4_ipc_send_and_wait(dest, Ostream::_utcb, tag, src, timeout); + Istream::tag() = tag; + Istream::_pos = 0; + return tag; +} + +inline l4_msgtag_t +Iostream::reply(l4_timeout_t timeout, long proto) +{ + l4_msgtag_t tag = prepare_ipc(proto); + tag = l4_ipc_send(L4_INVALID_CAP | L4_SYSF_REPLY, Ostream::_utcb, tag, timeout); + Istream::tag() = tag; + Istream::_pos = 0; + return tag; +} + +inline l4_msgtag_t +Istream::wait(l4_umword_t *src, l4_timeout_t timeout) +{ + l4_msgtag_t res; + res = l4_ipc_wait(_utcb, src, timeout); + tag() = res; + _pos = 0; + return res; +} + + +inline l4_msgtag_t +Istream::receive(l4_cap_idx_t src, l4_timeout_t timeout) +{ + l4_msgtag_t res; + res = l4_ipc_receive(src, _utcb, timeout); + tag() = res; + _pos = 0; + return res; +} + +}; + +} // namespace Ipc + +/** + * \brief Extract one element of type \a T from the stream \a s. + * \ingroup ipc_stream + * \param s The stream to extract from. + * \param v Output: extracted value. + * \return the stream \a s. + */ +inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, bool &v) { s.get(v); return s; } +inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, int &v) { s.get(v); return s; } +inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, long int &v) { s.get(v); return s; } +inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, long long int &v) { s.get(v); return s; } +inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, unsigned int &v) { s.get(v); return s; } +inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, unsigned long int &v) { s.get(v); return s; } +inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, unsigned long long int &v) { s.get(v); return s; } +inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, short int &v) { s.get(v); return s; } +inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, unsigned short int &v) { s.get(v); return s; } +inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, char &v) { s.get(v); return s; } +inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, unsigned char &v) { s.get(v); return s; } +inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, signed char &v) { s.get(v); return s; } +inline L4::Ipc::Istream &operator << (L4::Ipc::Istream &s, L4::Ipc::Buf_item const &v) { s.put(v); return s; } +inline L4::Ipc::Istream &operator << (L4::Ipc::Istream &s, L4::Ipc::Small_buf const &v) { s.put(v); return s; } +inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, L4::Ipc::Snd_item &v) +{ + l4_umword_t b, d; + s >> b >> d; + v = L4::Ipc::Snd_item(b,d); + return s; +} +inline L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, L4::Ipc::Varg &v) +{ s.get(&v); return s; } + + +/** + * \brief Extract the L4 message tag from the stream \a s. + * \ingroup ipc_stream + * \param s The stream to extract from. + * \param v Output: the extracted tag. + * \return the stream \a s. + */ +inline +L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, l4_msgtag_t &v) +{ + v = s.tag(); + return s; +} + +/** + * \brief Extract an array of \a T elements from the stream \a s. + * \ingroup ipc_stream + * + * This operator actually does not copy out the data in the array, but + * returns a pointer into the message buffer itself. This means that the + * data is only valid as long as there is no new data inserted into the stream. + * + * See Ipc::Buf_in, Ipc::Buf_cp_in, and Ipc::Buf_cp_out. + * + * \param s The stream to extract from. + * \param v Output: pointer to the extracted array (ipc_buf_in()). + * \return the stream \a s. + */ +template< typename T > +inline +L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, + L4::Ipc::Buf_in const &v) +{ + unsigned long si; + s.get(si); + v.set_size(s.get(L4::Ipc::Msg_ptr(v.buf()), si)); + return s; +} + +/** + * \brief Extract an element of type \a T from the stream \a s. + * \ingroup ipc_stream + * + * This operator actually does not copy out the data, but + * returns a pointer into the message buffer itself. This means that the + * data is only valid as long as there is no new data inserted into the stream. + * + * See Msg_ptr. + * + * \param s The stream to extract from. + * \param v Output: pointer to the extracted element. + * \return the stream \a s. + */ +template< typename T > +inline +L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, + L4::Ipc::Msg_ptr const &v) +{ + s.get(v); + return s; +} + +/** + * \brief Extract an array of \a T elements from the stream \a s. + * \ingroup ipc_stream + * + * This operator does a copy out of the data into the given buffer. + * + * See Ipc::Buf_in, Ipc::Buf_cp_in, and Ipc::Buf_cp_out. + * + * \param s The stream to extract from. + * \param v buffer description to copy the array to (Ipc::Buf_cp_out()). + * \return the stream \a s. + */ +template< typename T > +inline +L4::Ipc::Istream &operator >> (L4::Ipc::Istream &s, + L4::Ipc::Buf_cp_in const &v) +{ + unsigned long sz; + s.get(sz); + v.size() = s.get(v.buf(), sz); + return s; +} + + +/** + * \brief Insert an element to type \a T into the stream \a s. + * \ingroup ipc_stream + * + * \param s The stream to insert the element \a v. + * \param v The element to insert. + * \return the stream \a s. + */ +inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, bool v) { s.put(v); return s; } +inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, int v) { s.put(v); return s; } +inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, long int v) { s.put(v); return s; } +inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, long long int v) { s.put(v); return s; } +inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, unsigned int v) { s.put(v); return s; } +inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, unsigned long int v) { s.put(v); return s; } +inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, unsigned long long int v) { s.put(v); return s; } +inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, short int v) { s.put(v); return s; } +inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, unsigned short int v) { s.put(v); return s; } +inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, char v) { s.put(v); return s; } +inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, unsigned char v) { s.put(v); return s; } +inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, signed char v) { s.put(v); return s; } +inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, L4::Ipc::Snd_item const &v) { s.put_snd_item(v); return s; } +template< typename T > +inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, L4::Cap const &v) +{ s << L4::Ipc::Snd_fpage(v.fpage()); return s; } + +inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, L4::Ipc::Varg const &v) +{ s.put(v); return s; } +template< typename T > +inline L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, L4::Ipc::Varg_t const &v) +{ s.put(v); return s; } + +/** + * \brief Insert the L4 message tag into the stream \a s. + * \ingroup ipc_stream + * + * \note Only one message tag can be inserted into a stream. Multiple + * insertions simply overwrite previous insertions. + * \param s The stream to insert the tag \a v. + * \param v The L4 message tag to insert. + * \return the stream \a s. + */ +inline +L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, l4_msgtag_t const &v) +{ + s.tag() = v; + return s; +} + +/** + * \brief Insert an array with elements of type \a T into the stream \a s. + * \ingroup ipc_stream + * + * \param s The stream to insert the array \a v. + * \param v The array to insert (see Ipc::Buf_cp_out()). + * \return the stream \a s. + */ +template< typename T > +inline +L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, + L4::Ipc::Buf_cp_out const &v) +{ + s.put(v.size()); + s.put(v.buf(), v.size()); + return s; +} + +/** + * \brief Insert a zero terminated character string into the stream \a s. + * \ingroup ipc_stream + * + * \param s The stream to insert the string \a v. + * \param v The string to insert. + * \return the stream \a s. + * + * This operator produces basically the same content as the array insertion, + * however the length of the array is calculated using strlen(\a v) + 1 + * . The string is copied into the message including the trailing zero. + */ +inline +L4::Ipc::Ostream &operator << (L4::Ipc::Ostream &s, char const *v) +{ + unsigned long l = __builtin_strlen(v) + 1; + s.put(l); + s.put(v, l); + return s; +} + + +#ifdef L4_CXX_IPC_BACKWARD_COMPAT +namespace L4 { + +#if 0 +template< typename T > class Ipc_buf_cp_out : public Ipc::Buf_cp_out {}; +template< typename T > class Ipc_buf_cp_in : public Ipc::Buf_cp_in {}; +template< typename T > class Ipc_buf_in : public Ipc::Buf_in {}; +template< typename T > class Msg_ptr : public Ipc::Msg_ptr {}; +#endif + +template< typename T > +Ipc::Buf_cp_out ipc_buf_cp_out(T *v, unsigned long size) + L4_DEPRECATED("Use L4::Ipc::Buf_cp_out() now"); + +template< typename T > +Ipc::Buf_cp_out ipc_buf_cp_out(T *v, unsigned long size) +{ return Ipc::Buf_cp_out(v,size); } + + +template< typename T > +Ipc::Buf_cp_in ipc_buf_cp_in(T *v, unsigned long &size) + L4_DEPRECATED("Use L4::Ipc::Buf_cp_in() now"); + +template< typename T > +Ipc::Buf_cp_in ipc_buf_cp_in(T *v, unsigned long &size) +{ return Ipc::Buf_cp_in(v,size); } + + +template< typename T > +Ipc::Buf_in ipc_buf_in(T *&v, unsigned long &size) + L4_DEPRECATED("Use L4::Ipc::Buf_in() now"); + +template< typename T > +Ipc::Buf_in ipc_buf_in(T *&v, unsigned long &size) +{ return Ipc::Buf_in(v, size); } + + +template< typename T > +Ipc::Msg_ptr msg_ptr(T *&p) + L4_DEPRECATED("Use L4::Ipc::Msg_ptr() now"); + +template< typename T > +Ipc::Msg_ptr msg_ptr(T *&p) +{ return Ipc::Msg_ptr(p); } + +typedef Ipc::Istream Ipc_istream L4_DEPRECATED("Use L4::Ipc::Istream now"); +typedef Ipc::Ostream Ipc_ostream L4_DEPRECATED("Use L4::Ipc::Ostream now");; +typedef Ipc::Iostream Ipc_iostream L4_DEPRECATED("Use L4::Ipc::Iostream now");; +typedef Ipc::Snd_fpage Snd_fpage L4_DEPRECATED("Use L4::Ipc::Snd_fpage now");; +typedef Ipc::Rcv_fpage Rcv_fpage L4_DEPRECATED("Use L4::Ipc::Rcv_fpage now");; +typedef Ipc::Small_buf Small_buf L4_DEPRECATED("Use L4::Ipc::Small_buf now");; + +} +#endif + diff --git a/l4/pkg/cxx/lib/start/Makefile b/l4/pkg/cxx/lib/start/Makefile new file mode 100644 index 00000000..b60574b6 --- /dev/null +++ b/l4/pkg/cxx/lib/start/Makefile @@ -0,0 +1,5 @@ +PKGDIR = ../.. +L4DIR ?= $(PKGDIR)/../.. + +TARGET := include src +include $(L4DIR)/mk/subdir.mk diff --git a/l4/pkg/cxx/lib/start/include/Makefile b/l4/pkg/cxx/lib/start/include/Makefile new file mode 100644 index 00000000..ed2323b5 --- /dev/null +++ b/l4/pkg/cxx/lib/start/include/Makefile @@ -0,0 +1,4 @@ +PKGDIR = ../../.. +L4DIR ?= $(PKGDIR)/../.. + +include $(L4DIR)/mk/include.mk diff --git a/l4/pkg/cxx/lib/start/src/Makefile b/l4/pkg/cxx/lib/start/src/Makefile new file mode 100644 index 00000000..f2d3b3c4 --- /dev/null +++ b/l4/pkg/cxx/lib/start/src/Makefile @@ -0,0 +1,12 @@ +PKGDIR ?= ../../.. +L4DIR ?= $(PKGDIR)/../.. + +TARGET = libcxx_atexit +SYSTEMS = $(SYSTEMS_PLAIN) +SRC_CC = cxx_atexit.cc +PC_FILENAME = cxx_atexit + +include $(PKGDIR)/lib/Makefile.inc +include $(L4DIR)/mk/lib.mk + +$(GENERAL_D_LOC): $(L4DIR)/pkg/cxx/lib/Makefile.inc diff --git a/l4/pkg/cxx/lib/start/src/cxx_atexit.cc b/l4/pkg/cxx/lib/start/src/cxx_atexit.cc new file mode 100644 index 00000000..604300b2 --- /dev/null +++ b/l4/pkg/cxx/lib/start/src/cxx_atexit.cc @@ -0,0 +1,68 @@ +/* + * (c) 2004-2009 Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ + +#include "cxx_atexit.h" + +#define NUM_ATEXIT 64 + +struct __exit_handler +{ + void (*f)(void *); + void *arg; + void *dso_handle; +}; + +static __exit_handler __atexitlist[NUM_ATEXIT]; +static volatile unsigned atexit_counter; +int __cxa_atexit(void (*f)(void*), void *arg, void *dso_handle) +{ + unsigned c = atexit_counter++; + if (c >= NUM_ATEXIT) + return -1; + + __atexitlist[c].f = f; + __atexitlist[c].arg = arg; + __atexitlist[c].dso_handle = dso_handle; + + return 0; +} + +extern void *__dso_handle __attribute__((weak)); + +int atexit(void (*f)(void)) +{ + return __cxa_atexit((void (*)(void*))f, 0, (!&__dso_handle)?0:__dso_handle); +} + +void __cxa_finalize(void *dso_handle) +{ + register unsigned co = atexit_counter; + if (co > NUM_ATEXIT) + co = NUM_ATEXIT; + + while(co) + { + __exit_handler *h = &__atexitlist[--co]; + if (h->f && (dso_handle == 0 || h->dso_handle == dso_handle)) + { + h->f(h->arg); + h->f = 0; + } + } +} + diff --git a/l4/pkg/cxx/lib/start/src/cxx_atexit.h b/l4/pkg/cxx/lib/start/src/cxx_atexit.h new file mode 100644 index 00000000..173eaf97 --- /dev/null +++ b/l4/pkg/cxx/lib/start/src/cxx_atexit.h @@ -0,0 +1,26 @@ +/* + * (c) 2004-2009 Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ + +#ifndef L4_CXX_ATEXIT_H__ +#define L4_CXX_ATEXIT_H__ + +extern "C" void __cxa_finalize(void *dso_handle); +extern "C" int __cxa_atexit(void (*f)(void*), void *arg, void *dso_handle); +extern "C" int atexit(void (*f)(void)); + +#endif diff --git a/l4/pkg/cxx/lib/supc++-support/Makefile b/l4/pkg/cxx/lib/supc++-support/Makefile new file mode 100644 index 00000000..197fd9ee --- /dev/null +++ b/l4/pkg/cxx/lib/supc++-support/Makefile @@ -0,0 +1,5 @@ +PKGDIR = ../.. +L4DIR ?= $(PKGDIR)/../.. + +TARGET := src +include $(L4DIR)/mk/subdir.mk diff --git a/l4/pkg/cxx/lib/supc++-support/src/Makefile b/l4/pkg/cxx/lib/supc++-support/src/Makefile new file mode 100644 index 00000000..efb5cb38 --- /dev/null +++ b/l4/pkg/cxx/lib/supc++-support/src/Makefile @@ -0,0 +1,11 @@ +PKGDIR ?= ../../.. +L4DIR ?= $(PKGDIR)/../.. + +TARGET = libsupc++-support +SRC_C = memset.c +SRC_CC = abort.cc + +include $(PKGDIR)/lib/Makefile.inc +include $(L4DIR)/mk/lib.mk + +$(GENERAL_D_LOC): $(L4DIR)/pkg/cxx/lib/Makefile.inc diff --git a/l4/pkg/cxx/lib/supc++-support/src/abort.cc b/l4/pkg/cxx/lib/supc++-support/src/abort.cc new file mode 100644 index 00000000..bc34818b --- /dev/null +++ b/l4/pkg/cxx/lib/supc++-support/src/abort.cc @@ -0,0 +1,31 @@ +/* + * (c) 2004-2009 Adam Lackorzynski , + * Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ + +#include +#include + +extern "C" +void abort(void) __attribute((noreturn)); + +void abort(void) +{ + L4::cerr << "Aborted\n"; + for (;;) + l4_ipc_sleep(L4_IPC_NEVER, l4sys_utcb()); +} diff --git a/l4/pkg/cxx/lib/supc++-support/src/memset.c b/l4/pkg/cxx/lib/supc++-support/src/memset.c new file mode 100644 index 00000000..dc4c3034 --- /dev/null +++ b/l4/pkg/cxx/lib/supc++-support/src/memset.c @@ -0,0 +1,31 @@ +/* + * (c) 2004-2009 Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ + +#include + +void *memset(void *s, int c, size_t n); + +void *memset(void *s, int c, size_t n) +{ + size_t x; + char *p = s; + for (x=0; x + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ + +#pragma once + +namespace cxx { namespace arith { + +template< unsigned long V > +struct Ld +{ + enum { value = Ld::value + 1 }; +}; + +template<> +struct Ld<0> +{ + enum { value = ~0UL }; +}; + +template<> +struct Ld<1> +{ + enum { value = 0 }; +}; + +}} diff --git a/l4/pkg/cxx/lib/tl/include/auto_ptr b/l4/pkg/cxx/lib/tl/include/auto_ptr new file mode 100644 index 00000000..e932e485 --- /dev/null +++ b/l4/pkg/cxx/lib/tl/include/auto_ptr @@ -0,0 +1,113 @@ +// vim:ft=cpp +/* + * (c) 2008-2009 Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ + +#pragma once + +namespace cxx { + +/** + * \ingroup cxx_api + * \brief Smart pointer with automatic deletion. + * \param T The type of the referenced object. + * + * This smart pointer calls the delete operator when the destructor + * is called. This has the effect that the object the pointer points to + * will be deleted when the pointer goes out of scope, or a new value gets + * assigned. The smart pointer provides a release() method to get a normal + * pointer to the object and set the smart pointer to NULL. + */ +template< typename T> +class Auto_ptr +{ +private: + T *_p; + + struct Priv_type; + +public: + /** \brief The referenced type. */ + typedef T Ref_type; + + /** + * \brief Construction by assignment of a normal pointer. + * \param p The pointer to the object + */ + explicit Auto_ptr(T *p = 0) throw() : _p(p) {} + + /** + * \brief Copy construction, releases the original pointer. + * \param o The smart pointer, which shall be copied and released. + */ + Auto_ptr(Auto_ptr const &o) throw() + : _p(const_cast&>(o).release()) + {} + + /** + * \brief Assignment from another smart pointer. + * \param o The source for the assignment (will be released). + */ + Auto_ptr &operator = (Auto_ptr const &o) throw() + { + if (&o != this) + { + if (_p) delete _p; + _p = const_cast&>(o).release(); + } + return *this; + } + + /** \brief Destruction, shall delete the object. */ + ~Auto_ptr() throw() + { if (_p) delete _p; } + + /** \brief Dereference the pointer. */ + T &operator * () const throw() { return *_p; } + + /** \brief Member access for the object. */ + T *operator -> () const throw() { return _p; } + + /** + * \brief Get the normal pointer. + * \attention This function will not release the object, the + * object will be deleted by the smart pointer. + */ + T *get() const throw() { return _p; } + + /** + * \brief Release the object and get the normal pointer back. + * + * After calling this function the smart pointer will point to NULL + * and the object will not be deleted by the pointer anymore. + */ + T *release() throw() { T *t = _p; _p = 0; return t; } + + /** + * \brief Delete the object and reset the smart pointer to NULL. + */ + void reset(T *p = 0) throw() + { + if (_p) delete _p; + _p = p; + } + + /** \brief Operator for if (!ptr) ...<\c>.*/ + operator Priv_type * () const throw() + { return reinterpret_cast(_p); } +}; +} diff --git a/l4/pkg/cxx/lib/tl/include/avl_map b/l4/pkg/cxx/lib/tl/include/avl_map new file mode 100644 index 00000000..8cae9ab0 --- /dev/null +++ b/l4/pkg/cxx/lib/tl/include/avl_map @@ -0,0 +1,151 @@ +// vi:ft=cpp +/** + * \file + * \brief AVL map + */ +/* + * (c) 2008-2009 Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ + +#pragma once + +#include +#include +#include +#include + +namespace cxx { + +/** + * \ingroup cxx_api + * \brief AVL tree based associative container. + * \param Key Type of the key values. + * \param Data Type of the data values. + * \param Compare Type comparison functor for the key values. + * \param Alloc Type of the allocator used for the nodes. + */ +template< typename Key, typename Data, + template class Compare = Lt_functor, + template class Alloc = New_allocator > +class Avl_map : public Avl_set, + Pair_first_compare< Compare, Pair >, + Alloc> +{ +private: + typedef Pair Local_item_type; + typedef Pair_first_compare< Compare, Local_item_type > Local_compare; + typedef Avl_set Base_type; + +public: + /// Type of the comparison functor. + typedef Compare Key_compare; + /// Type of the key values. + typedef Key Key_type; + /// Type of the data values. + typedef Data Data_type; + /// Return type for find. + typedef typename Base_type::Node Node; + /// Type of the allocator + typedef typename Base_type::Node_allocator Node_allocator; + + typedef typename Base_type::Iterator Iterator; + typedef typename Base_type::Iterator iterator; + typedef typename Base_type::Const_iterator Const_iterator; + typedef typename Base_type::Const_iterator const_iterator; + typedef typename Base_type::Rev_iterator Rev_iterator; + typedef typename Base_type::Rev_iterator reverse_iterator; + typedef typename Base_type::Const_rev_iterator Const_rev_iterator; + typedef typename Base_type::Const_rev_iterator const_reverse_iterator; + + /** + * \brief Create an empty AVL-tree based map. + * \param comp The comparison functor. + * \param alloc The node allocator. + */ + Avl_map(Node_allocator const &alloc = Node_allocator()) + : Base_type(alloc) + {} + + /** + * \brief Insert a pair into the map. + * \param key The key value. + * \param data The data value to insert. + */ + cxx::Pair insert(Key_type const &key, Data_type const &data) + { return Base_type::insert(Pair(key, data)); } + + /** + * \brief Find a pair for a given key. + * \param key The key value to use for the lookup. + */ + Node find_node(Key_type const &key) const + { return Base_type::find_node(Local_item_type(key, Data_type())); } + + /** + * \brief Find the first node greater or equal to \a key. + * \param key the key to look for. + * \return The first node greater or equal to \a key. + */ + Node lower_bound_node(Key_type const &key) const + { return Base_type::lower_bound_node(Local_item_type(key, Data_type())); } + + /** + * \brief Find a pair for a given key. + * \param key The key value to use for the lookup. + */ + Iterator find(Key_type const &key) const + { return Base_type::find(Local_item_type(key, Data_type())); } + + /** + * \brief Remove the pair for the given key. + * \param key The key value of the pair that shall be removed. + */ + int remove(Key_type const &key) + { return Base_type::remove(Local_item_type(key, Data_type())); } + + /** + * \brief Removed the element \a key. + * \see remove() + */ + int erase(Key_type const &key) + { return remove(key); } + + /** + * \brief Get the data for the given key. + * \param key The key value to use for lookup. + * \pre A pair for the given key value must exist. + */ + Data_type const &operator [] (Key_type const &key) const + { return find_node(key)->second; } + + /** + * \brief Get the data for the given key. + * \param key The key value to use for lookup. + * \pre A pair for the given key value must exist. + */ + Data_type &operator [] (Key_type const &key) + { + Node n = find_node(key); + if (n) + return const_cast(n->second); + else + return insert(key, Data_type()).first->second; + } +}; + +} + diff --git a/l4/pkg/cxx/lib/tl/include/avl_set b/l4/pkg/cxx/lib/tl/include/avl_set new file mode 100644 index 00000000..b6ff737b --- /dev/null +++ b/l4/pkg/cxx/lib/tl/include/avl_set @@ -0,0 +1,360 @@ +// vi:ft=cpp +/** + * \file + * \brief AVL set + */ +/* + * (c) 2008-2009 Alexander Warg , + * Carsten Weinhold + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ + +#pragma once + +#include +#include +#include +#include + +namespace cxx { +/** + * \internal + * \ingroup cxx_api + * \brief Generic iterator for the AVL-tree based set. + * \param Cmp the type of the comparison functor. + * \param Node the type of a node. + * \param Key the type of the item stored in a node. + * \param Node_op the type used to determine the direction of the iterator. + */ +template< typename Node, typename Key, typename Node_op > +class __Avl_set_iter : public Bits::__Bst_iter_b +{ +private: + /// Super-class type + typedef Bits::__Bst_iter_b Base; + + using Base::_n; + using Base::_r; + using Base::inc; + +public: + /// Create an invalid iterator (end marker) + __Avl_set_iter() {} + + /** + * \brief Create an iterator for the given tree. + * \param t the root node of the tree to iterate. + * \param cmp the conmparison functor for tree elements. + */ + __Avl_set_iter(Node const *t) : Base(t) {} + + __Avl_set_iter(Base const &o) : Base(o) {} + +// template + __Avl_set_iter(__Avl_set_iter::Non_const_type, Node_op> const &o) + : Base(o) {} + + /** + * \brief Dereference the iterator and get the item out of the tree. + * \return A reference to the data stored in the AVL tree. + */ + Key &operator * () const { return const_cast(_n)->item; } + /** + * \brief Member access to the item the iterator points to. + * \return A pointer to the item in the node. + */ + Key *operator -> () const { return &const_cast(_n)->item; } + /** + * \brief Set the iterator to the next element (pre increment). + */ + __Avl_set_iter &operator ++ () { inc(); return *this; } + /** + * \brief Set the iterator to the next element (post increment). + */ + __Avl_set_iter &operator ++ (int) + { __Avl_set_iter tmp = *this; inc(); return tmp; } + +}; + + +/** + * \ingroup cxx_api + * \brief AVL Tree for simple comapreable items. + * + * The AVL tree can store any kind of items where a partial order is defined. + * The default relation is defined by the '<' operator. + * \param Item The type of the items to be stored in the tree. + * \param Compare The relation to define the partial order, default is + * to use operator '<'. + * \param Alloc The allocator to use for the nodes of the AVL tree. + */ +template< typename Item, class Compare = Lt_functor, + template class Alloc = New_allocator > +class Avl_set +{ +public: + enum + { + E_noent = 2, + E_exist = 17, + E_nomem = 12, + E_inval = 22 + }; + /// Type for the items contained in the tree. + typedef Item Item_type; + typedef typename Type_traits::Const_type Const_item_type; + /// Type for the comparison functor. + typedef Compare Item_compare; + + +private: + + /// Internal representation of a tree node. + class _Node : public Avl_tree_node + { + public: + /// The actual item stored in the node. + Item_type item; + + _Node() : Avl_tree_node(), item() {} + + _Node(Item_type const &item) : Avl_tree_node(), item(item) {} + }; + + struct Get_key + { + typedef Item Key_type; + static Key_type const &key_of(_Node const *n) + { return n->item; } + }; + +public: + /** + * \brief A smart pointer to a tree item. + */ + class Node + { + private: + struct No_type; + friend class Avl_set; + _Node const *_n; + explicit Node(_Node const *n) : _n(n) {} + + public: + /// Default construction for NIL pointer. + Node() : _n(0) {} + + /// Default assignment. + Node &operator = (Node const &o) { _n = o._n; return *this; } + + /// Dereference the pointer. + Item const &operator * () { return _n->item; } + /// Dereferenced member access. + Item const *operator -> () { return &_n->item; } + + /** + * \brief Validity check. + * \return false if the pointer is NIL, true if valid. + */ + bool valid() const { return _n; } + + /// Cast to a real item pointer. + operator Item const * () { if (_n) return &_n->item; else return 0; } + }; + + /// Type for the node allocator. + typedef Alloc<_Node> Node_allocator; + +private: + typedef Avl_tree<_Node, Get_key, Compare> Tree; + Tree _tree; + /// The allocator for new nodes + Node_allocator _alloc; + + void operator = (Avl_set const &); + + typedef typename Tree::Fwd_iter_ops Fwd; + typedef typename Tree::Rev_iter_ops Rev; + +public: + typedef typename Type_traits::Param_type Item_param_type; + + /// Forward iterator for the set. + typedef __Avl_set_iter<_Node, Item_type, Fwd> Iterator; + typedef Iterator iterator; + /// Constant forward iterator for the set. + typedef __Avl_set_iter<_Node, Const_item_type, Fwd> Const_iterator; + typedef Const_iterator const_iterator; + /// Backward iterator for the set. + typedef __Avl_set_iter<_Node, Item_type, Rev> Rev_iterator; + typedef Rev_iterator reverse_iterator; + /// Constant backward iterator for the set. + typedef __Avl_set_iter<_Node, Const_item_type, Rev> Const_rev_iterator; + typedef Const_rev_iterator const_reverse_iterator; + + /** + * \brief Create a AVL-tree based set. + * \param comp Comparison functor. + * \param alloc Node allocator. + * + * Create an empty set (AVL-tree based). + */ + explicit Avl_set(Node_allocator const &alloc = Node_allocator()) + : _tree(), _alloc(alloc) + {} + + /** + * \brief Create a copy of an AVL-tree based set. + * \param o The set to copy. + */ + inline Avl_set(Avl_set const &o); + + /** + * \brief Insert an item into the set. + * \param item The item to insert. + * \return 0 on success, -1 on out of memory, and -2 if the element + * already exists in the set. + * + * Insert a new item into the set, each item can only be once in + * the set. + */ + cxx::Pair insert(Item_type const &item); + + /** + * \brief Remove an item from the set. + * \param item The item to remove. + * \return 0 on success, -3 if the item does not exist, and + * -4 on internal error. + */ + int remove(Item_type const &item) + { + _Node *n = _tree.remove(item); + if ((long)n == -E_inval) + return -E_inval; + + if (n) + { + n->~_Node(); + _alloc.free(n); + return 0; + } + + return -E_noent; + } + + int erase(Item_type const &item) + { return remove(item); } + + /** + * \brief Lookup a node equal to \a item. + * \param item The value to search for. + * \return A smart pointer to the element found, if no element found the + * pointer is NULL. + */ + Node find_node(Item_type const &item) const + { return Node(_tree.find_node(item)); } + + /** + * \brief Find the first node greater or equal to \a key. + * \param key the key to look for. + * \return The first node greater or equal to \a key. + */ + Node lower_bound_node(Item_type const &key) const + { return Node(_tree.lower_bound_node(key)); } + + + /** + * \brief Get the constant forward iterator for the first element in the set. + * \return Constant forward iterator for the first element in the set. + */ + Const_iterator begin() const { return _tree.begin(); } + /** + * \brief Get the end marker for the constant forward iterator. + * \return The end marker for the constant forward iterator. + */ + Const_iterator end() const { return _tree.end(); } + + /** + * \brief Get the mutable forward iterator for the first element of the set. + * \return The mutable forward iterator for the first element of the set. + */ + Iterator begin() { return _tree.begin(); } + /** + * \brief Get the end marker for the mutable forward iterator. + * \return The end marker for mutable forward iterator. + */ + Iterator end() { return _tree.end(); } + + /** + * \brief Get the constant backward iterator for the last element in the set. + * \return The constant backward iterator for the last element in the set. + */ + Const_rev_iterator rbegin() const { return _tree.rbegin(); } + /** + * \brief Get the end marker for the constant backward iterator. + * \return The end marker for the constant backward iterator. + */ + Const_rev_iterator rend() const { return _tree.rend(); } + + /** + * \brief Get the mutable backward iterator for the last element of the set. + * \return The mutable backward iterator for the last element of the set. + */ + Rev_iterator rbegin() { return _tree.rbegin(); } + /** + * \brief Get the end marker for the mutable backward iterator. + * \return The end marker for mutable backward iterator. + */ + Rev_iterator rend() { return _tree.rend(); } + + Const_iterator find(Item_type const &item) const + { return _tree.find(item); } + + +}; + + +//---------------------------------------------------------------------------- +/* Implementation of AVL Tree */ + +/* Create a copy */ +template< typename Item, class Compare, template class Alloc > +Avl_set::Avl_set(Avl_set const &o) + : _tree(), _alloc(o._alloc) +{ + for (Const_iterator i = o.begin(); i != o.end(); ++i) + insert(*i); +} + +/* Insert new _Node. */ +template< typename Item, class Compare, template< typename A > class Alloc > +Pair::Iterator, int> +Avl_set::insert(Item const &item) +{ + _Node *n = _alloc.alloc(); + if (!n) + return cxx::pair(end(), -E_nomem); + + new (n, Nothrow()) _Node(item); + Pair<_Node *, bool> err = _tree.insert(n); + if (!err.second) + _alloc.free(n); + + return cxx::pair(Iterator(typename Tree::Iterator(err.first, err.first)), err.second ? 0 : -E_exist); +} + +} + diff --git a/l4/pkg/cxx/lib/tl/include/avl_tree b/l4/pkg/cxx/lib/tl/include/avl_tree new file mode 100644 index 00000000..212332f7 --- /dev/null +++ b/l4/pkg/cxx/lib/tl/include/avl_tree @@ -0,0 +1,414 @@ +// vi:ft=cpp +/** + * \file + * \brief AVL tree + */ +/* + * (c) 2008-2009 Alexander Warg , + * Carsten Weinhold + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ + +#pragma once + +#include "std_ops" +#include "pair" + +#include "bits/bst.h" +#include "bits/bst_iter.h" + +namespace cxx { + +/** + * \brief Node of an AVL tree. + */ +class Avl_tree_node : public Bits::Bst_node +{ +private: + template< typename Node, typename Get_key, typename Compare > + friend class Avl_tree; + + /// Shortcut for Balance values (we use Direction for that). + typedef Bits::Direction Bal; + /// Alia for Direction. + typedef Bits::Direction Dir; + + /// We are a finaly BST node, hide interior. + /*@{*/ + using Bits::Bst_node::next; + using Bits::Bst_node::next_p; + using Bits::Bst_node::rotate; + /*@}*/ + + /// The balance value (#Direction::N is balanced). + Bal _balance; + +protected: + /// Create an uninitialized node, this is what you shoulkd do. + Avl_tree_node() {} + +private: + /// Hide copy + Avl_tree_node(Avl_tree_node const &o); + + /// private assignment for initialization and relinkage. + void operator = (Avl_tree_node const &o) + { + Bits::Bst_node::operator = (o); + _balance = o._balance; + } + + /// Create an initialized node (for internal stuff). + explicit Avl_tree_node(bool) : Bits::Bst_node(true), _balance(Dir::N) {} + + /// Double rotation of \a t. + static Bits::Bst_node *rotate2(Bst_node **t, Bal idir, Bal pre); + + /// Is this subtree balanced? + bool balanced() const { return _balance == Bal::N; } + + /// What is the balance of this subtree? + Bal balance() const { return _balance; } + + /// Set the balance of this subtree to \a b. + void balance(Bal b) { _balance = b; } +}; + + +/** + * \brief A generic AVL tree. + * \param Node the data type of the nodes (must inherit from Avl_tree_noed). + * \param Get_key the meta fcuntion to get the key value from a node. + * The implementation uses Get_key::key_of(ptr_to_node). + * \param Compare binary relation to establish a total order for the + * nodes of the tree. Compare()(l, r) must return true if + * the key \a l is smaller than the key \a r. + */ +template< typename Node, typename Get_key, + typename Compare = Lt_functor > +class Avl_tree : public Bits::Bst +{ +private: + typedef Bits::Bst Bst; + + /// Hide this from possible descendants. + using Bst::_head; + + /// Provide access to keys of nodes. + using Bst::k; + + /// Alias type for balance values. + typedef typename Avl_tree_node::Bal Bal; + /// Alias type for Direction values. + typedef typename Avl_tree_node::Bal Dir; + + /// Prohibit simple copy. + Avl_tree(Avl_tree const &o); + + /// Prohibit simple copy. + void operator = (Avl_tree const &o); + +public: + //@{ + typedef typename Bst::Key_type Key_type; + typedef typename Bst::Key_param_type Key_param_type; + //@} + + /// Grab iterator types from Bst + //@{ + /// Forward iterator for the set. + typedef typename Bst::Iterator Iterator; + /// Constant forward iterator for the set. + typedef typename Bst::Const_iterator Const_iterator; + /// Backward iterator for the set. + typedef typename Bst::Rev_iterator Rev_iterator; + /// Constant backward iterator for the set. + typedef typename Bst::Const_rev_iterator Const_rev_iterator; + //@} + + /** + * \brief Insert a new node into this AVL tree. + * \param new_node a pointer to the new node. This node must not + * already b in an AVL tree. + * \return A pair, with second set to 'true' and first pointing to + * \a new_node, on success. If there is already a node with the + * same key that first point to this node and second is 'false'. + */ + Pair insert(Node *new_node); + + /** + * \brief Remove the node with \a key from the tree. + * \param key The node to remove. + * \return The pointer to the removed node on success, + * or NULL -3 if no node with the \a key exists. + */ + Node *remove(Key_param_type key); + /** + * \brief An alias for remove(). + */ + Node *erase(Key_param_type key) { return remove(key); } + + /// Create an empty AVL tree. + Avl_tree() : Bst() {} + /// Destroy, and free the set. + ~Avl_tree() + { + Bits::Bst_node const *n; + while ((n = _head)) + remove(k(n)); + } + +#ifdef __DEBUG_L4_AVL + bool rec_dump(Avl_tree_node *n, int depth, int *dp, bool print, char pfx); + bool rec_dump(bool print) + { + int dp=0; + return rec_dump(static_cast(_head), 0, &dp, print, '+'); + } +#endif +}; + + +//---------------------------------------------------------------------------- +/* IMPLEMENTATION: Bits::__Bst_iter_b */ + + +inline +Bits::Bst_node * +Avl_tree_node::rotate2(Bst_node **t, Bal idir, Bal pre) +{ + typedef Bits::Bst_node N; + typedef Avl_tree_node A; + N *tmp[2] = { *t, N::next(*t, idir) }; + *t = N::next(tmp[1], !idir); + A *n = static_cast(*t); + + N::next(tmp[0], idir, N::next(n, !idir)); + N::next(tmp[1], !idir, N::next(n, idir)); + N::next(n, !idir, tmp[0]); + N::next(n, idir, tmp[1]); + + n->balance(Bal::N); + + if (pre == Bal::N) + { + static_cast(tmp[0])->balance(Bal::N); + static_cast(tmp[1])->balance(Bal::N); + return 0; + } + + static_cast(tmp[pre != idir])->balance(!pre); + static_cast(tmp[pre == idir])->balance(Bal::N); + + return N::next(tmp[pre == idir], !pre); +} + +//---------------------------------------------------------------------------- +/* Implementation of AVL Tree */ + +/* Insert new _Node. */ +template< typename Node, typename Get_key, class Compare> +Pair +Avl_tree::insert(Node *new_node) +{ + typedef Avl_tree_node A; + typedef Bits::Bst_node N; + N **t = &_head; /* search variable */ + N **s = &_head; /* node where rebalancing may occur */ + Key_param_type new_key = Get_key::key_of(new_node); + + // search insertion point + for (N *p; (p = *t);) + { + Dir b = this->dir(new_key, p); + if (b == Dir::N) + return pair(static_cast(p), false); + + if (!static_cast
(p)->balanced()) + s = t; + + t = N::next_p(p, b); + } + + *static_cast(new_node) = A(true); + *t = new_node; + + N *n = *s; + A *a = static_cast(n); + if (!a->balanced()) + { + A::Bal b(this->greater(new_key, n)); + if (a->balance() != b) + { + // ok we got in balance the shorter subtree go higher + a->balance(Bal::N); + // propagate the new balance down to the new node + n = N::next(n, b); + } + else if (b == Bal(this->greater(new_key, N::next(n, b)))) + { + // left-left or right-right case -> single rotation + A::rotate(s, b); + a->balance(Bal::N); + static_cast(*s)->balance(Bal::N); + n = N::next(*s, b); + } + else + { + // need a double rotation + n = N::next(N::next(n, b), !b); + n = A::rotate2(s, b, n == new_node ? Bal::N : Bal(this->greater(new_key, n))); + } + } + + for (A::Bal b; n && n != new_node; static_cast(n)->balance(b), n = N::next(n, b)) + b = Bal(this->greater(new_key, n)); + + return pair(new_node, true); +} + + +/* remove an element */ +template< typename Node, typename Get_key, class Compare> +inline +Node *Avl_tree::remove(Key_param_type key) +{ + typedef Avl_tree_node A; + typedef Bits::Bst_node N; + N **q = &_head; /* search variable */ + N **s = &_head; /* last ('deepest') node on the search path to q + * with balance 0, at this place the rebalancing + * stops in any case */ + N **t = 0; + Dir dir; + + // find target node and rebalancing entry + for (N *n; (n = *q); q = N::next_p(n, dir)) + { + dir = Dir(this->greater(key, n)); + if (dir == Dir::L && !this->greater(k(n), key)) + /* found node */ + t = q; + + if (!N::next(n, dir)) + break; + + A const *a = static_cast(n); + if (a->balanced() || (a->balance() == !dir && N::next(n, !dir)->balanced())) + s = q; + } + + // noting found + if (!t) + return 0; + + A *i = static_cast(*t); + + for (N *n; (n = *s); s = N::next_p(n, dir)) + { + dir = Dir(this->greater(key, n)); + + if (!N::next(n, dir)) + break; + + A *a = static_cast(n); + // got one out of balance + if (a->balanced()) + a->balance(!dir); + else if (a->balance() == dir) + a->balance(Bal::N); + else + { + // we need rotations to get in balance + Bal b = N::next(n, !dir)->balance(); + if (b == dir) + A::rotate2(s, !dir, N::next(N::next(n, !dir), dir)->balance()); + else + { + A::rotate(s, !dir); + if (b != Bal::N) + { + a->balance(Bal::N); + static_cast(*s)->balance(Bal::N); + } + else + { + a->balance(!dir); + static_cast(*s)->balance(dir); + } + } + if (n == i) + t = N::next_p(*s, dir); + } + } + + A *n = static_cast(*q); + *t = n; + *q = N::next(n, !dir); + *n = *i; + + return static_cast(i); +} + +#ifdef __DEBUG_L4_AVL +template< typename Node, typename Get_key, class Compare> +bool Avl_tree::rec_dump(Avl_tree_node *n, int depth, int *dp, bool print, char pfx) +{ + typedef Avl_tree_node A; + + if (!n) + return true; + + int dpx[2] = {depth,depth}; + bool res = true; + + res = rec_dump(n->next(Dir::R), depth + 1, dpx + 1, print, '/'); + + if (print) + { + fprintf(stderr, "%2d: [%8p] b=%1d: ", depth, n, (int)n->balance().d); + + for (int i = 0; i < depth; ++i) + std::cerr << " "; + + std::cerr << pfx << (static_cast(n)->item) << std::endl; + } + + res = res & rec_dump(n->next(Dir::L), depth + 1, dpx, print, '\\'); + + int b = dpx[1] - dpx[0]; + + if (b < 0) + *dp = dpx[0]; + else + *dp = dpx[1]; + + Bal x = n->balance(); + if ((b < -1 || b > 1) || + (b == 0 && x != Bal::N) || + (b == -1 && x != Bal::L) || + (b == 1 && x != Bal::R)) + { + if (print) + fprintf(stderr, "%2d: [%8p] b=%1d: balance error %d\n", depth, n, (int)n->balance().d, b); + return false; + } + return res; +} +#endif + +} + diff --git a/l4/pkg/cxx/lib/tl/include/basic_vector.h b/l4/pkg/cxx/lib/tl/include/basic_vector.h new file mode 100644 index 00000000..f3bc84cb --- /dev/null +++ b/l4/pkg/cxx/lib/tl/include/basic_vector.h @@ -0,0 +1,44 @@ +/** + * \file + * \brief Basic vector + */ +/* + * (c) 2008-2009 Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#pragma once + +#include + +namespace cxx { + +template< typename T > +class Basic_vector +{ +public: + Basic_vector(T *array, unsigned long capacity) + : _array(array), _capacity(capacity) + { + for (unsigned long i = 0; i < capacity; ++i) + new (&_array[i]) T(); + } + +private: + T *_array; + unsigned long _capacity; +}; + +}; diff --git a/l4/pkg/cxx/lib/tl/include/bitmap b/l4/pkg/cxx/lib/tl/include/bitmap new file mode 100644 index 00000000..1a8d42d2 --- /dev/null +++ b/l4/pkg/cxx/lib/tl/include/bitmap @@ -0,0 +1,223 @@ +// vi:ft=cpp +/* + * (c) 2008-2009 Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ + +#pragma once + +namespace cxx { + +/** + * \ingroup cxx_api + * \brief Basic bitmap abstraction. + * + * This abstraction keeps a pointer to a memory area that is used as bitmap. + */ +class Bitmap_base +{ +private: + enum + { + W_bits = sizeof(unsigned long) * 8, + C_bits = 8, + }; + unsigned long *_bits; + +public: + explicit Bitmap_base(void *bits) throw() : _bits((unsigned long *)bits) {} + + /** \brief Get the number of \a Words that are used for the bitmap. */ + static long words(long bits) throw() { return (bits + W_bits -1) / W_bits; } + static long bit_buffer_bytes(long bits) throw() + { return words(bits) * W_bits / 8; } + + /** \brief Helper abstraction for a word contained in the bitmap. */ + template< long BITS > + class Word + { + public: + typedef unsigned long Type; + enum + { + Size = (BITS + W_bits - 1) / W_bits + }; + }; + + /** \brief Get the number of chars that are used for the bitmap. */ + static long chars(long bits) throw () + { return (bits + C_bits -1) / C_bits; } + + /** \brief Helper abstraction for a byte contained in the bitmap. */ + template< long BITS > + class Char + { + public: + typedef unsigned char Type; + enum + { + Size = (BITS + C_bits - 1) / C_bits + }; + }; + + /** + * \brief Set the value of bit \a bit to \a on. + * \param bit the number of the bit + * \param on the boolean value that shall be assigned to the bit. + */ + void bit(long bit, bool on) throw(); + + /** + * \brief Clear bit \a bit. + * \param bit the number of the bit to clear. + */ + void clear_bit(long bit) throw(); + /** + * \brief Set bit \a bit. + * \param bit the number of the bit to set, + */ + void set_bit(long bit) throw(); + + /** + * \brief Get the truth value of a bit. + * \param bit the number of the bit to read. + */ + unsigned long operator [] (long bit) const throw(); + + /** + * \brief Scans for the first zero bit. + * \param max_bit the upper bound for the scanning operation. + * \param start_bit the number of the first bit to look at. + */ + long scan_zero(long max_bit, long start_bit = 0) const throw(); + + void *bit_buffer() const throw() { return _bits; } + +protected: + static int _bzl(unsigned long w) throw(); +}; + + +/** + * \ingroup cxx_api + * \brief A static bit map. + * \param BITS the number of bits that shall be in the bitmap. + */ +template +class Bitmap : public Bitmap_base +{ +private: + char _bits[Bitmap_base::Char::Size]; + +public: + /** \brief Create a bitmap with \a BITS bits. */ + Bitmap() throw() : Bitmap_base(_bits) {} + Bitmap(Bitmap const &o) throw() : Bitmap_base(_bits) + { __builtin_memcpy(_bits, o._bits, sizeof(_bits)); } + /** + * \brief Scan for the first zero bit. + * \param start_bit the bit where the scanning shall begin. + * + * Compared to Bitmap_base::scan_zero(), the upper bound is set to BITS. + */ + + void clear_all() + { __builtin_memset(_bits, 0, sizeof(_bits)); } + + long scan_zero(long start_bit = 0) const throw(); +}; + + +inline +void +Bitmap_base::bit(long bit, bool on) throw() +{ + long idx = bit / W_bits; + long b = bit % W_bits; + _bits[idx] = (_bits[idx] & ~(1UL << b)) | ((unsigned long)on << b); +} + +inline +void +Bitmap_base::clear_bit(long bit) throw() +{ + long idx = bit / W_bits; + long b = bit % W_bits; + _bits[idx] &= ~(1UL << b); +} + +inline +void +Bitmap_base::set_bit(long bit) throw() +{ + long idx = bit / W_bits; + long b = bit % W_bits; + _bits[idx] |= (1UL << b); +} + +inline +unsigned long +Bitmap_base::operator [] (long bit) const throw() +{ + long idx = bit / W_bits; + long b = bit % W_bits; + return _bits[idx] & (1UL << b); +} + +inline +int +Bitmap_base::_bzl(unsigned long w) throw() +{ + for (int i = 0; i < W_bits; ++i, w >>= 1) + { + if ((w & 1) == 0) + return i; + } + return -1; +} + +inline +long +Bitmap_base::scan_zero(long max_bit, long start_bit) const throw() +{ + if (!(operator [] (start_bit))) + return start_bit; + + long idx = start_bit / W_bits; + + max_bit -= start_bit & ~(W_bits - 1); + + for (; max_bit > 0; max_bit -= W_bits, ++idx) + { + if (_bits[idx] == 0) + return idx * W_bits; + + if (_bits[idx] != ~0UL) + return idx * W_bits + _bzl(_bits[idx]); + } + + return -1; +} + +template inline +long +Bitmap::scan_zero(long start_bit) const throw() +{ + return Bitmap_base::scan_zero(BITS, start_bit); +} + +}; + diff --git a/l4/pkg/cxx/lib/tl/include/bits/bst.h b/l4/pkg/cxx/lib/tl/include/bits/bst.h new file mode 100644 index 00000000..0e45423e --- /dev/null +++ b/l4/pkg/cxx/lib/tl/include/bits/bst.h @@ -0,0 +1,289 @@ +// vi:ft=cpp +/** + * \file + * \brief AVL tree + */ +/* + * (c) 2008-2009 Alexander Warg , + * Carsten Weinhold + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#pragma once + +#include "type_traits.h" +#include "bst_base.h" +#include "bst_iter.h" + +namespace cxx { namespace Bits { + +/** + * \brief Basic binary search tree (BST). + * + * This class is intended as a base class for concrete binary search trees, + * such as an AVL tree. This class already provides the basic lookup methods + * and iterator definitions for a BST. + */ +template< typename Node, typename Get_key, typename Compare > +class Bst +{ +private: + typedef Direction Dir; + /// Ops for forward iterators + struct Fwd + { + static Node *child(Node const *n, Direction d) + { return Bst_node::next(n, d); } + + static bool cmp(Node const *l, Node const *r) + { return Compare()(Get_key::key_of(l), Get_key::key_of(r)); } + }; + + /// Ops for Reverse iterators + struct Rev + { + static Node *child(Node const *n, Direction d) + { return Bst_node::next(n, !d); } + + static bool cmp(Node const *l, Node const *r) + { return Compare()(Get_key::key_of(r), Get_key::key_of(l)); } + }; + +public: + /// The type of key values used to generate the total order of the elements. + typedef typename Get_key::Key_type Key_type; + /// The type for key parameters. + typedef typename Type_traits::Param_type Key_param_type; + + /// Helper for building forward iterators for different wrapper classes. + typedef Fwd Fwd_iter_ops; + /// Helper for building reverse iterators for different wrapper classes. + typedef Rev Rev_iter_ops; + + /// \name Iterators + //@{ + /// Forward iterator. + typedef __Bst_iter Iterator; + /// Constant forward iterator. + typedef __Bst_iter Const_iterator; + /// Backward iterator. + typedef __Bst_iter Rev_iterator; + /// Constant backward. + typedef __Bst_iter Const_rev_iterator; + //@} + +protected: + /** + * \name Interior access for descendants. + * + * As this class is an intended base class we provide protected access + * to our interior, use 'using' to make this private in concrete + * implementations. + */ + /*@{*/ + + /// The head pointer of the tree. + Bst_node *_head; + + /// Create an empty tree. + Bst() : _head(0) {} + + /// Access the head node as object of type \a Node. + Node *head() const { return static_cast(_head); } + + /// Get the key value of \a n. + static Key_type k(Bst_node const *n) + { return Get_key::key_of(static_cast(n)); } + + /** + * \brief Get the direction to go from \a l to search for \a r. + * \param l is the key to look for. + * \param r is the key at the current position. + * \return #Direction::L for left, #Direction::R for right, + * and #Direction::N if \a l is equal to \a r. + */ + static Dir dir(Key_param_type l, Key_param_type r) + { + Compare cmp; + Dir d(cmp(r, l)); + if (d == Direction::L && !cmp(l, r)) + return Direction::N; + return d; + } + + /** + * \brief Get the direction to go from \a l to search for \a r. + * \param l is the key to look for. + * \param r is the node at the current position. + * \return #Direction::L for left, #Direction::R for right, + * and #Direction::N if \a l is equal to \a r. + */ + static Dir dir(Key_param_type l, Bst_node const *r) + { return dir(l, k(r)); } + + /// Is \a l greater than \a r. + static bool greater(Key_param_type l, Key_param_type r) + { return Compare()(r, l); } + + /// Is \a l greater than \a r. + static bool greater(Key_param_type l, Bst_node const *r) + { return greater(l, k(r)); } + + /// Is \a l greater than \a r. + static bool greater(Bst_node const *l, Bst_node const *r) + { return greater(k(l), k(r)); } + /*@}*/ + +public: + + /** + * \name Get default iterators for the ordered tree. + */ + /*@{*/ + /** + * \brief Get the constant forward iterator for the first element in the set. + * \return Constant forward iterator for the first element in the set. + */ + Const_iterator begin() const { return Const_iterator(head()); } + /** + * \brief Get the end marker for the constant forward iterator. + * \return The end marker for the constant forward iterator. + */ + Const_iterator end() const { return Const_iterator(); } + + /** + * \brief Get the mutable forward iterator for the first element of the set. + * \return The mutable forward iterator for the first element of the set. + */ + Iterator begin() { return Iterator(head()); } + /** + * \brief Get the end marker for the mutable forward iterator. + * \return The end marker for mutable forward iterator. + */ + Iterator end() { return Iterator(); } + + /** + * \brief Get the constant backward iterator for the last element in the set. + * \return The constant backward iterator for the last element in the set. + */ + Const_rev_iterator rbegin() const { return Const_rev_iterator(head()); } + /** + * \brief Get the end marker for the constant backward iterator. + * \return The end marker for the constant backward iterator. + */ + Const_rev_iterator rend() const { return Const_rev_iterator(); } + + /** + * \brief Get the mutable backward iterator for the last element of the set. + * \return The mutable backward iterator for the last element of the set. + */ + Rev_iterator rbegin() { return Rev_iterator(head()); } + /** + * \brief Get the end marker for the mutable backward iterator. + * \return The end marker for mutable backward iterator. + */ + Rev_iterator rend() { return Rev_iterator(); } + /*@}*/ + + + /** + * \name Lookup functions. + */ + //@{ + /** + * \brief find the node with the given \a key. + * \param key The key value of the element to search. + * \return A pointer to the node with the given \a key, or + * NULL if \a key was not found. + */ + Node *find_node(Key_param_type key) const; + + /** + * \brief find the first node with a key not less than the given \a key. + * \param key The key value of the element to search. + * \return A pointer to the node with the given \a key, or + * NULL if \a key was not found. + */ + Node *lower_bound_node(Key_param_type key) const; + + /** + * \brief find the node with the given \a key. + * \param key The key value of the element to search. + * \return A valid iterator for the node with the given \a key, + * or an invalid iterator if \a key was not found. + */ + Const_iterator find(Key_param_type key) const; + + //@} +}; + +/* find an element */ +template< typename Node, typename Get_key, class Compare> +inline +Node * +Bst::find_node(Key_param_type key) const +{ + Dir d; + + for (Bst_node *q = _head; q; q = Bst_node::next(q, d)) + { + d = dir(key, q); + if (d == Dir::N) + return static_cast(q); + } + return 0; +} + +template< typename Node, typename Get_key, class Compare> +inline +Node * +Bst::lower_bound_node(Key_param_type key) const +{ + Dir d; + Bst_node *r = 0; + + for (Bst_node *q = _head; q; q = Bst_node::next(q, d)) + { + d = dir(key, q); + if (d == Dir::L) + r = q; // found a node greater than key + else if (d == Dir::N) + return static_cast(q); + } + return static_cast(r); +} + +/* find an element */ +template< typename Node, typename Get_key, class Compare> +inline +typename Bst::Const_iterator +Bst::find(Key_param_type key) const +{ + Bst_node *q = _head; + Bst_node *r = q; + + for (Dir d; q; q = Bst_node::next(q, d)) + { + d = dir(key, q); + if (d == Dir::N) + return Iterator(static_cast(q), static_cast(r)); + + if (d != Dir::L && q == r) + r = Bst_node::next(q, d); + } + return Iterator(); +} + +}} diff --git a/l4/pkg/cxx/lib/tl/include/bits/bst_base.h b/l4/pkg/cxx/lib/tl/include/bits/bst_base.h new file mode 100644 index 00000000..2bfc43a8 --- /dev/null +++ b/l4/pkg/cxx/lib/tl/include/bits/bst_base.h @@ -0,0 +1,135 @@ +// vi:ft=cpp +/** + * \file + * \brief AVL tree + */ +/* + * (c) 2008-2009 Alexander Warg , + * Carsten Weinhold + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ + +#pragma once + +/* + * This file contains very basic bits for implementing binary serach trees + */ +namespace cxx { +/** + * \brief Internal helpers for the cxx package. + */ +namespace Bits { + +/** + * \brief The direction to go in a binary search tree. + */ +struct Direction +{ + /// The literal direction values. + enum Direction_e + { + L = 0, ///< Go to the left child + R = 1, ///< Go to the right child + N = 2 ///< Stop + }; + unsigned char d; + + /// Uninitialized direction + Direction() {} + + /// Convert a literal direction (#L, #R, #N) to an object + Direction(Direction_e d) : d(d) {} + + /// Convert a boolean to a direction (false == #L, true == #R) + explicit Direction(bool b) : d(Direction_e(b)) /*d(b ? R : L)*/ {} + + /** + * \brief Negate the direction. + * \note This is only defined for a current value of #L or #R + */ + Direction operator ! () const { return Direction(!d); } + + /// \name Comparison operators (equality and inequality) + //@{ + bool operator == (Direction_e o) const { return d == o; } + bool operator != (Direction_e o) const { return d != o; } + bool operator == (Direction o) const { return d == o.d; } + bool operator != (Direction o) const { return d != o.d; } + //@} +}; + +/** + * \brief Basic type of a node in a binary search tree (BST). + */ +class Bst_node +{ + // all BSTs are friends + template< typename Node, typename Get_key, typename Compare > + friend class Bst; + +protected: + /** + * \name Access to BST linkage. + * + * Provide access to the tree linkage to inherited classes + * Inherited nodes, such as AVL nodes should make these methods + * private via 'using' + */ + /*@{*/ + + /// Get next node in direction \a d. + static Bst_node *next(Bst_node const *p, Direction d) + { return p->_c[d.d]; } + + /// Set next node of \a p in direction \a d to \a n. + static void next(Bst_node *p, Direction d, Bst_node *n) + { p->_c[d.d] = n; } + + /// Get pointer to link in direction \a d. + static Bst_node **next_p(Bst_node *p, Direction d) + { return &p->_c[d.d]; } + + /// Get next node in direction \a d as type \a Node. + template< typename Node > static + Node *next(Bst_node const *p, Direction d) + { return static_cast(p->_c[d.d]); } + + /// Rotate subtree \a t in the opposite direction of \a idir. + static void rotate(Bst_node **t, Direction idir); + /*@}*/ + +private: + Bst_node *_c[2]; + +protected: + /// Create uninitialized node + Bst_node() {} + + /// Create initialized node + explicit Bst_node(bool) { _c[0] = _c[1] = 0; } +}; + +inline +void +Bst_node::rotate(Bst_node **t, Direction idir) +{ + Bst_node *tmp = *t; + *t = next(tmp, idir); + next(tmp, idir, next(*t, !idir)); + next(*t, !idir, tmp); +} + +}} diff --git a/l4/pkg/cxx/lib/tl/include/bits/bst_iter.h b/l4/pkg/cxx/lib/tl/include/bits/bst_iter.h new file mode 100644 index 00000000..339b4d74 --- /dev/null +++ b/l4/pkg/cxx/lib/tl/include/bits/bst_iter.h @@ -0,0 +1,188 @@ +// vi:ft=cpp +/** + * \file + * \brief AVL tree + */ +/* + * (c) 2008-2009 Alexander Warg , + * Carsten Weinhold + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ + +#pragma once + +#include "bst_base.h" + +namespace cxx { namespace Bits { + +/** + * \internal + * \ingroup cxx_api + * \brief Generic iterator for the AVL-tree based set. + * \param Cmp the type of the comparison functor. + * \param Node the type of a node. + * \param Node_op the type used to determine the direction of the iterator. + */ +template< typename Node, typename Node_op > +class __Bst_iter_b +{ +protected: + typedef Direction Dir; + Node const *_n; ///< Current node + Node const *_r; ///< Root node of current subtree + + /// Create an invalid iterator, used as end marker. + __Bst_iter_b() : _n(0), _r(0) {} + + /** + * \brief Create an iterator for the given AVL tree. + * \param t the root node of the tree to iterate. + * \param cmp the comparison functor for tree elements. + */ + __Bst_iter_b(Node const *t) + : _n(t), _r(_n) + { _downmost(); } + + __Bst_iter_b(Node const *t, Node const *r) + : _n(t), _r(r) + {} + + /// traverse the subtree down to the leftmost/rightmost leave. + inline void _downmost(); + + /// Increment to the next element. + inline void inc(); + +public: + /// Check two iterators for equality. + bool operator == (__Bst_iter_b const &o) const { return _n == o._n; } + /// Check two iterators for non equality. + bool operator != (__Bst_iter_b const &o) const { return _n != o._n; } +}; + +/** + * \internal + * \ingroup cxx_api + * \brief Generic iterator for the AVL-tree based set. + * \param Node the type of a node. + * \param Node_type the type of the node to return stored in a node. + * \param Node_op the type used to determine the direction of the iterator. + */ +template< typename Node, typename Node_type, typename Node_op > +class __Bst_iter : public __Bst_iter_b +{ +private: + /// Super-class type + typedef __Bst_iter_b Base; + + using Base::_n; + using Base::_r; + using Base::inc; + +public: + /// Create an invalid iterator (end marker) + __Bst_iter() {} + + /** + * \brief Create an iterator for the given tree. + * \param t the root node of the tree to iterate. + * \param cmp the conmparison functor for tree elements. + */ + __Bst_iter(Node const *t) : Base(t) {} + __Bst_iter(Node const *t, Node const *r) : Base(t, r) {} + +// template + __Bst_iter(Base const &o) : Base(o) {} + + /** + * \brief Dereference the iterator and get the item out of the tree. + * \return A reference to the data stored in the AVL tree. + */ + Node_type &operator * () const { return *const_cast(_n); } + /** + * \brief Member access to the item the iterator points to. + * \return A pointer to the item in the node. + */ + Node_type *operator -> () const { return const_cast(_n); } + /** + * \brief Set the iterator to the next element (pre increment). + */ + __Bst_iter &operator ++ () { inc(); return *this; } + /** + * \brief Set the iterator to the next element (post increment). + */ + __Bst_iter &operator ++ (int) + { __Bst_iter tmp = *this; inc(); return tmp; } +}; + + +//---------------------------------------------------------------------------- +/* IMPLEMENTATION: __Bst_iter_b */ + +template< typename Node, typename Node_op> +inline +void __Bst_iter_b::_downmost() +{ + while (_n) + { + Node *n = Node_op::child(_n, Dir::L); + if (n) + _n = n; + else + return; + } +} + +template< typename Node, typename Node_op> +void __Bst_iter_b::inc() +{ + if (!_n) + return; + + if (_n == _r) + { + _r = _n = Node_op::child(_r, Dir::R); + _downmost(); + return; + } + + if (Node_op::child(_n, Dir::R)) + { + _n = Node_op::child(_n, Dir::R); + _downmost(); + return; + } + + Node const *q = _r; + Node const *p = _r; + while (1) + { + if (Node_op::cmp(_n, q)) + { + p = q; + q = Node_op::child(q, Dir::L); + } + else if (_n == q || Node_op::child(q, Dir::R) == _n) + { + _n = p; + return; + } + else + q = Node_op::child(q, Dir::R); + } +} + +}} diff --git a/l4/pkg/cxx/lib/tl/include/bits/list_basics.h b/l4/pkg/cxx/lib/tl/include/bits/list_basics.h new file mode 100644 index 00000000..dc57a74a --- /dev/null +++ b/l4/pkg/cxx/lib/tl/include/bits/list_basics.h @@ -0,0 +1,147 @@ +/* + * (c) 2011 Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ + +#pragma once + +namespace cxx { namespace Bits { + +template< typename T > +class List_iterator_end_ptr +{ +private: + template< typename U > friend class Basic_list; + static void *_end; +}; + +template< typename T > +void *List_iterator_end_ptr::_end; + +template< typename VALUE_T, typename TYPE > +struct Basic_list_policy +{ + typedef VALUE_T *Value_type; + typedef VALUE_T const *Const_value_type; + typedef TYPE **Type; + typedef TYPE *Const_type; + typedef TYPE *Head_type; + + static Type next(Type c) { return &(*c)->_n; } + static Const_type next(Const_type c) { return c->_n; } +}; + +template< typename POLICY > +class Basic_list +{ +private: + Basic_list(Basic_list const &); + void operator = (Basic_list const &); + +public: + typedef typename POLICY::Value_type Value_type; + typedef typename POLICY::Const_value_type Const_value_type; + + class End_iterator {}; + + class Iterator + { + private: + typedef typename POLICY::Type Internal_type; + + public: + typedef typename POLICY::Value_type value_type; + typedef typename POLICY::Value_type Value_type; + + Value_type operator * () const { return static_cast(*_c); } + Value_type operator -> () const { return static_cast(*_c); } + Iterator operator ++ () { _c = POLICY::next(_c); return *this; } + + bool operator == (End_iterator const &) const { return *_c == 0; } + bool operator != (End_iterator const &) const { return *_c != 0; } + bool operator == (Iterator const &o) const { return *_c == *o._c; } + bool operator != (Iterator const &o) const { return !operator == (o); } + + Iterator() {} + Iterator(End_iterator const &) : _c(__end()) {} + + private: + friend class Basic_list; + static Internal_type __end() + { + union X { Internal_type l; void **v; } z; + z.v = &Bits::List_iterator_end_ptr::_end; + return z.l; + } + + explicit Iterator(Internal_type i) : _c(i) {} + + Internal_type _c; + }; + + class Const_iterator + { + private: + typedef typename POLICY::Const_type Internal_type; + + public: + typedef typename POLICY::Value_type value_type; + typedef typename POLICY::Value_type Value_type; + + Value_type operator * () const { return static_cast(_c); } + Value_type operator -> () const { return static_cast(_c); } + Const_iterator operator ++ () { _c = POLICY::next(_c); return *this; } + + bool operator == (End_iterator const &) const { return _c == 0; } + bool operator != (End_iterator const &) const { return _c != 0; } + bool operator == (Const_iterator const &o) const { return _c == o._c; } + bool operator != (Const_iterator const &o) const { return !operator == (o); } + + Const_iterator() {} + Const_iterator(End_iterator const &) : _c(0) {} + Const_iterator(Iterator const &o) : _c(*o) {} + + private: + friend class Basic_list; + + explicit Const_iterator(Internal_type i) : _c(i) {} + + Internal_type _c; + }; + + // BSS allocation + explicit Basic_list(bool) {} + Basic_list() : _f(0) {} + + bool empty() const { return !_f; } + Value_type front() const { return static_cast(_f); } + + void clear() { _f = 0; } + + Iterator begin() { return Iterator(&_f); } + Const_iterator begin() const { return Const_iterator(_f); } + static Const_iterator iter(Const_value_type c) { return Const_iterator(c); } + static End_iterator end() { return End_iterator(); } + +protected: + static typename POLICY::Type __get_internal(Iterator const &i) { return i._c; } + static Iterator __iter(typename POLICY::Type c) { return Iterator(c); } + + typename POLICY::Head_type _f; +}; + +}} + diff --git a/l4/pkg/cxx/lib/tl/include/bits/type_traits.h b/l4/pkg/cxx/lib/tl/include/bits/type_traits.h new file mode 100644 index 00000000..fda5d0dd --- /dev/null +++ b/l4/pkg/cxx/lib/tl/include/bits/type_traits.h @@ -0,0 +1,229 @@ +// vi:ft=cpp +/* + * (c) 2008-2009 Alexander Warg , + * Torsten Frenzel + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ + +#pragma once + +namespace cxx { + +class Null_type; + +template< bool flag, typename T, typename F > +class Select +{ +public: + typedef T Type; +}; + +template< typename T, typename F > +class Select< false, T, F > +{ +public: + typedef F Type; +}; + + + +template< typename T, typename U > +class Conversion +{ + typedef char S; + class B { char dummy[2]; }; + static S test(U); + static B test(...); + static T make_T(); +public: + enum + { + exists = sizeof(test(make_T())) == sizeof(S), + two_way = exists && Conversion::exists, + exists_2_way = two_way, + same_type = false + }; +}; + +template< > +class Conversion +{ +public: + enum { exists = 1, two_way = 1, exists_2_way = two_way, same_type = 1 }; +}; + +template< typename T > +class Conversion +{ +public: + enum { exists = 1, two_way = 1, exists_2_way = two_way, same_type = 1 }; +}; + +template< typename T > +class Conversion +{ +public: + enum { exists = 0, two_way = 0, exists_2_way = two_way, same_type = 0 }; +}; + +template< typename T > +class Conversion +{ +public: + enum { exists = 0, two_way = 0, exists_2_way = two_way, same_type = 0 }; +}; + +template< int I > +class Int_to_type +{ +public: + enum { i = I }; +}; + +namespace TT +{ + template< typename U > class Pointer_traits + { + public: + typedef Null_type Pointee; + enum { value = false }; + }; + + template< typename U > class Pointer_traits< U* > + { + public: + typedef U Pointee; + enum { value = true }; + }; + + template< typename U > struct Ref_traits + { + enum { value = false }; + typedef U Referee; + }; + + template< typename U > struct Ref_traits + { + enum { value = true }; + typedef U Referee; + }; + + + template< typename U > struct Add_ref { typedef U &Type; }; + template< typename U > struct Add_ref { typedef U Type; }; + + template< typename U > struct PMF_traits { enum { value = false }; }; + template< typename U, typename F > struct PMF_traits + { enum { value = true }; }; + + + template< typename U > class Is_unsigned { public: enum { value = false }; }; + template<> class Is_unsigned { public: enum { value = true }; }; + template<> class Is_unsigned { + public: enum { value = true }; + }; + template<> class Is_unsigned { + public: enum { value = true }; + }; + template<> class Is_unsigned { + public: enum { value = true }; + }; + template<> class Is_unsigned { + public: enum { value = true }; + }; + + template< typename U > class Is_signed { public: enum { value = false }; }; + template<> class Is_signed { public: enum { value = true }; }; + template<> class Is_signed { public: enum { value = true }; }; + template<> class Is_signed { public: enum { value = true }; }; + template<> class Is_signed { public: enum { value = true }; }; + template<> class Is_signed { + public: enum { value = true }; + }; + + template< typename U > class Is_int { public: enum { value = false }; }; + template<> class Is_int< char > { public: enum { value = true }; }; + template<> class Is_int< bool > { public: enum { value = true }; }; + template<> class Is_int< wchar_t > { public: enum { value = true }; }; + + template< typename U > class Is_float { public: enum { value = false }; }; + template<> class Is_float< float > { public: enum { value = true }; }; + template<> class Is_float< double > { public: enum { value = true }; }; + template<> class Is_float< long double > { public: enum { value = true }; }; + + template class Const_traits + { + public: + enum { value = false }; + typedef T Type; + typedef const T Const_type; + }; + + template class Const_traits + { + public: + enum { value = true }; + typedef T Type; + typedef const T Const_type; + }; +}; + +template< typename T > +class Type_traits +{ +public: + + enum + { + is_unsigned = TT::Is_unsigned::value, + is_signed = TT::Is_signed::value, + is_int = TT::Is_int::value, + is_float = TT::Is_float::value, + is_pointer = TT::Pointer_traits::value, + is_pointer_to_member = TT::PMF_traits::value, + is_reference = TT::Ref_traits::value, + is_scalar = is_unsigned || is_signed || is_int || is_pointer + || is_pointer_to_member || is_reference, + is_fundamental = is_unsigned || is_signed || is_float + || Conversion::same_type, + is_const = TT::Const_traits::value, + + alignment = + (sizeof(T) >= sizeof(unsigned long) + ? sizeof(unsigned long) + : (sizeof(T) >= sizeof(unsigned) + ? sizeof(unsigned) + : (sizeof(T) >= sizeof(short) + ? sizeof(short) + : 1))) + }; + + typedef typename Select::Const_type>::Type>::Type Param_type; + typedef typename TT::Pointer_traits::Pointee Pointee_type; + typedef typename TT::Ref_traits::Referee Referee_type; + typedef typename TT::Const_traits::Type Non_const_type; + typedef typename TT::Const_traits::Const_type Const_type; + + static unsigned long align(unsigned long a) + { return (a + (unsigned long)alignment - 1UL) + & ~((unsigned long)alignment - 1UL); } +}; + + +}; + + + diff --git a/l4/pkg/cxx/lib/tl/include/dlist b/l4/pkg/cxx/lib/tl/include/dlist new file mode 100644 index 00000000..0737513b --- /dev/null +++ b/l4/pkg/cxx/lib/tl/include/dlist @@ -0,0 +1,270 @@ +// vi:ft=cpp +/* + * (c) 2011 Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ + +#pragma once + +namespace cxx { + +class D_list_item +{ +public: + D_list_item() : _dli_next(0) {} +private: + friend class D_list_item_policy; + + D_list_item(D_list_item const &); + void operator = (D_list_item const &); + + D_list_item *_dli_next, *_dli_prev; +}; + +struct D_list_item_policy +{ + typedef D_list_item Item; + static D_list_item *&prev(D_list_item *e) { return e->_dli_prev; } + static D_list_item *&next(D_list_item *e) { return e->_dli_next; } +}; + +template< typename T > +struct Sd_list_head_policy +{ + typedef T *Head_type; + static T *head(Head_type h) { return h; } + static void set_head(Head_type &h, T *v) { h = v; } +}; + +template< + typename T, + typename C = D_list_item_policy +> +class D_list_cyclic +{ +protected: + template< typename VALUE, typename ITEM > + class __Iterator + { + public: + typedef VALUE *Value_type; + typedef VALUE *value_type; + + __Iterator() {} + + bool operator == (__Iterator const &o) const + { return _c == o._c; } + + bool operator != (__Iterator const &o) const + { return _c != o._c; } + + __Iterator &operator ++ () + { + _c = C::next(_c); + return *this; + } + + __Iterator &operator -- () + { + _c = C::prev(_c); + return *this; + } + + Value_type operator * () const { return static_cast(_c); } + Value_type operator -> () const { return static_cast(_c); } + + private: + friend class D_list_cyclic; + + explicit __Iterator(ITEM *s) : _c(s) {} + + ITEM *_c; + }; + +public: + typedef T *Value_type; + typedef T *value_type; + typedef __Iterator Iterator; + typedef Iterator Const_iterator; + + static void remove(T *e) + { + C::next(C::prev(e)) = C::next(e); + C::prev(C::next(e)) = C::prev(e); + C::next(e) = 0; + } + + static Iterator erase(Iterator const &e) + { + typename C::Item *n = C::next(*e); + remove(*e); + return __iter(n); + } + + static Iterator iter(T const *e) { return Iterator(const_cast(e)); } + + static bool in_list(T const *e) { return C::next(const_cast(e)); } + static bool has_sibling(T const *e) { return C::next(const_cast(e)) != e; } + + static Iterator insert_after(T *e, Iterator const &pos) + { + C::prev(e) = *pos; + C::next(e) = C::next(*pos); + C::prev(C::next(*pos)) = e; + C::next(*pos) = e; + return pos; + } + + static Iterator insert_before(T *e, Iterator const &pos) + { + C::next(e) = *pos; + C::prev(e) = C::prev(*pos); + C::next(C::prev(*pos)) = e; + C::prev(*pos) = e; + return pos; + } + + static T *self_insert(T *e) + { C::next(e) = C::prev(e) = e; return e; } + + static void remove_last(T *e) + { C::next(e) = 0; } + +protected: + static Iterator __iter(typename C::Item *e) { return Iterator(e); } +}; + +template< + typename T, + typename C = D_list_item_policy, + typename H = Sd_list_head_policy, + bool BSS = false +> +class Sd_list : public D_list_cyclic +{ +private: + typedef D_list_cyclic Base; + +public: + typedef typename Base::Iterator Iterator; + enum Pos + { Back, Front }; + + Sd_list() { if (!BSS) H::set_head(_f, 0); } + + bool empty() const { return !H::head(_f); } + T *front() const { return H::head(_f); } + + void remove(T *e) + { + T *h = H::head(_f); + if (e == C::next(e)) // must be the last + { + Base::remove_last(e); + H::set_head(_f, 0); + return; + } + + if (e == H::head(_f)) + H::set_head(_f, static_cast(C::next(h))); + + Base::remove(e); + } + + Iterator erase(Iterator const &e) + { + typename C::Item *n = C::next(*e); + remove(*e); + return __iter(n); + } + + void push(T *e, Pos pos) + { + T *h = H::head(_f); + if (!h) + H::set_head(_f, Base::self_insert(e)); + else + { + Base::insert_before(e, this->iter(h)); + if (pos == Front) + H::set_head(_f, e); + } + } + + void push_back(T *e) { push(e, Back); } + void push_front(T *e) { push(e, Front); } + void rotate_to(T *h) { H::set_head(_f, h); } + + typename H::Head_type const &head() const { return _f; } + typename H::Head_type &head() { return _f; } + +private: + Sd_list(Sd_list const &); + void operator = (Sd_list const &); + + typename H::Head_type _f; +}; + +template< + typename T, + typename C = D_list_item_policy, + bool BSS = false +> +class D_list : public D_list_cyclic +{ +private: + typedef D_list_cyclic Base; + typedef typename C::Item Internal_type; + +public: + enum Pos + { Back, Front }; + + typedef typename Base::Iterator Iterator; + typedef typename Base::Const_iterator Const_iterator; + typedef T* value_type; + typedef T* Value_type; + + D_list() { this->self_insert(static_cast(&_h)); } + + bool empty() const { return C::next(static_cast(&_h)) == &_h; } + + void remove(T *e) { Base::remove(e); } + void erase(Iterator const &e) { return Base::erase(e); } + + void push(T *e, Pos pos) + { + if (pos == Front) + Base::insert_after(e, end()); + else + Base::insert_before(e, end()); + } + + void push_back(T *e) { push(e, Back); } + void push_front(T *e) { push(e, Front); } + + Iterator begin() const { return this->__iter(C::next(const_cast(&_h))); } + Iterator end() const { return this->__iter(const_cast(&_h)); } + +private: + D_list(D_list const &); + void operator = (D_list const &); + + Internal_type _h; +}; + +} + diff --git a/l4/pkg/cxx/lib/tl/include/hlist b/l4/pkg/cxx/lib/tl/include/hlist new file mode 100644 index 00000000..4efa0517 --- /dev/null +++ b/l4/pkg/cxx/lib/tl/include/hlist @@ -0,0 +1,137 @@ +// vi:ft=cpp +/* + * (c) 2011 Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ + +#pragma once + +#include "bits/list_basics.h" + +namespace cxx { + +class H_list_item +{ +public: + H_list_item() : _pn(0) {} + ~H_list_item() { l_remove(); } + +private: + H_list_item(H_list_item const &); + void operator = (H_list_item const &); + + template friend class H_list; + template friend class Bits::Basic_list_policy; + + void l_remove() + { + if (!_pn) + return; + + *_pn = _n; + if (_n) + _n->_pn = _pn; + + _pn = 0; + } + + H_list_item *_n, **_pn; +}; + +template< typename T, typename POLICY = Bits::Basic_list_policy< T, H_list_item > > +class H_list : public Bits::Basic_list +{ +private: + typedef Bits::Basic_list Base; + H_list(H_list const &); + void operator = (H_list const &); + +public: + typedef typename Base::Iterator Iterator; + + // BSS allocation + explicit H_list(bool x) : Base(x) {} + H_list() : Base() {} + + static Iterator iter(T *c) { return Base::__iter(c->_pn); } + + static bool in_list(T const *e) { return e->_pn; } + + void add(T *e) + { + if (this->_f) + this->_f->_pn = &e->_n; + e->_n = this->_f; + e->_pn = &this->_f; + this->_f = e; + } + + void push_front(T *e) { add(e); } + + void insert(T *e, Iterator const &pred) + { + H_list_item **x = &this->_f; + if (pred != Base::end()) + x = &(*pred)->_n; + + e->_n = *x; + + if (*x) + (*x)->_pn = &(e->_n); + + e->_pn = x; + *x = e; + } + + static void insert_before(T *e, Iterator const &succ) + { + H_list_item **x = Base::__get_internal(succ); + + e->_n = *x; + e->_pn = x; + + if (*x) + (*x)->_pn = &e->_n; + + *x = e; + } + + static void replace(T *p, T *e) + { + e->_n = p->_n; + e->_pn = p->_pn; + *(p->_pn) = e; + if (e->_n) + e->_n->_pn = &(e->_n); + + p->_pn = 0; + } + + static void remove(T *e) + { e->H_list_item::l_remove(); } + + static Iterator erase(Iterator const &e) + { e->H_list_item::l_remove(); return e; } +}; + +template< typename T > +class H_list_bss : public H_list +{ +public: + H_list_bss() : H_list(true) {} +}; + +} diff --git a/l4/pkg/cxx/lib/tl/include/list b/l4/pkg/cxx/lib/tl/include/list new file mode 100644 index 00000000..42dacae1 --- /dev/null +++ b/l4/pkg/cxx/lib/tl/include/list @@ -0,0 +1,424 @@ +// vi:ft=cpp +/* + * (c) 2008-2009 Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ + +#pragma once + +#include +#include +#include + +namespace cxx { +/* + * Classes: List_item, List + */ + +/** + * \ingroup cxx_api + * \brief Basic list item. + * + * Basic item that can be member of a doubly linked, cyclic list. + */ +class List_item +{ +public: + /** + * \brief Iterator for a list of ListItem-s. + * + * The Iterator iterates til it finds the first element again. + */ + class Iter + { + public: + Iter(List_item *c, List_item *f) throw() : _c(c), _f(f) {} + Iter(List_item *f = 0) throw() : _c(f), _f(f) {} + + List_item *operator * () const throw() { return _c; } + List_item *operator -> () const throw() { return _c; } + Iter &operator ++ () throw() + { + if (!_f) + _c = 0; + else + _c = _c->get_next_item(); + + if (_c == _f) + _c = 0; + + return *this; + } + + Iter operator ++ (int) throw() + { Iter o = *this; operator ++ (); return o; } + + Iter &operator -- () throw() + { + if (!_f) + _c = 0; + else + _c = _c->get_prev_item(); + + if (_c == _f) + _c = 0; + + return *this; + } + + Iter operator -- (int) throw() + { Iter o = *this; operator -- (); return o; } + + /** Remove item pointed to by iterator, and return pointer to element. */ + List_item *remove_me() throw() + { + if (!_c) + return 0; + + List_item *l = _c; + operator ++ (); + l->remove_me(); + + if (_f == l) + _f = _c; + + return l; + } + + private: + List_item *_c, *_f; + }; + + /** + * \brief Iterator for derived classes from ListItem. + * + * Allows direct access to derived classes by * operator. + * + * Example: + * class Foo : public ListItem + * { + * public: + * typedef T_iter Iter; + * ... + * }; + */ + template< typename T, bool Poly = false> + class T_iter : public Iter + { + private: + static bool const P = !Conversion::exists + || Poly; + + static List_item *cast_to_li(T *i, Int_to_type) throw() + { return dynamic_cast(i); } + + static List_item *cast_to_li(T *i, Int_to_type) throw() + { return i; } + + static T *cast_to_type(List_item *i, Int_to_type) throw() + { return dynamic_cast(i); } + + static T *cast_to_type(List_item *i, Int_to_type) throw() + { return static_cast(i); } + + public: + + template< typename O > + explicit T_iter(T_iter const &o) throw() + : Iter(o) { dynamic_cast(*o); } + + //TIter(CListItem *f) : Iter(f) {} + T_iter(T *f = 0) throw() : Iter(cast_to_li(f, Int_to_type

())) {} + T_iter(T *c, T *f) throw() + : Iter(cast_to_li(c, Int_to_type

()), + cast_to_li(f, Int_to_type

())) + {} + + inline T *operator * () const throw() + { return cast_to_type(Iter::operator * (),Int_to_type

()); } + inline T *operator -> () const throw() + { return operator * (); } + + T_iter operator ++ (int) throw() + { T_iter o = *this; Iter::operator ++ (); return o; } + T_iter operator -- (int) throw() + { T_iter o = *this; Iter::operator -- (); return o; } + T_iter &operator ++ () throw() + { Iter::operator ++ (); return *this; } + T_iter &operator -- () throw() + { Iter::operator -- (); return *this; } + inline T *remove_me() throw(); + }; + + + List_item() throw() : _n(this), _p(this) {} + +protected: + List_item(List_item const &) throw() : _n(this), _p(this) {} + +public: + /** Get previous item. */ + List_item *get_prev_item() const throw() { return _p; } + + /** Get next item. */ + List_item *get_next_item() const throw() { return _n; } + + /** Insert item p before this item. */ + void insert_prev_item(List_item *p) throw() + { + p->_p->_n = this; + List_item *pr = p->_p; + p->_p = _p; + _p->_n = p; + _p = pr; + } + + /** Insert item p after this item. */ + void insert_next_item(List_item *p) throw() + { + p->_p->_n = _n; + p->_p = this; + _n->_p = p; + _n = p; + } + + /** Remove this item from the list. */ + void remove_me() throw() + { + if (_p != this) + { + _p->_n = _n; + _n->_p = _p; + } + _p = _n = this; + } + + /** + * \brief Append item to a list. + * + * Convinience function for empty-head corner case. + * \param h pointer to the current list head. + * \param p pointer to new item. + * \return the pointer to the new head. + */ + template< typename C, typename N > + static inline C *push_back(C *head, N *p) throw(); + + /** + * \brief Prepend item to a list. + * + * Convinience function for empty-head corner case. + * \param head pointer to the current list head. + * \param p pointer to new item. + * \return the pointer to the new head. + */ + template< typename C, typename N > + static inline C *push_front(C *head, N *p) throw(); + + /** + * \brief Remove item from a list. + * + * Convinience function for remove-head corner case. + * \param head pointer to the current list head. + * \param p pointer to the item to remove. + * \return the pointer to the new head. + */ + template< typename C, typename N > + static inline C *remove(C *head, N *p) throw(); + +private: + List_item *_n, *_p; +}; + + +/* IMPLEMENTATION -----------------------------------------------------------*/ +template< typename C, typename N > +C *List_item::push_back(C *h, N *p) throw() +{ + if (!p) + return h; + if (!h) + return p; + h->insert_prev_item(p); + return h; +} + +template< typename C, typename N > +C *List_item::push_front(C *h, N *p) throw() +{ + if (!p) + return h; + if (h) + h->insert_prev_item(p); + return p; +} + +template< typename C, typename N > +C *List_item::remove(C *h, N *p) throw() +{ + if (!p) + return h; + if (!h) + return 0; + if (h == p) + { + if (p == p->_n) + h = 0; + else + h = static_cast(p->_n); + } + p->remove_me(); + + return h; +} + +template< typename T, bool Poly > +inline +T *List_item::T_iter::remove_me() throw() +{ return cast_to_type(Iter::remove_me(), Int_to_type

()); } + + +template< typename T > +class T_list_item : public List_item +{ +public: + T *next() const { return static_cast(List_item::get_next_item()); } + T *prev() const { return static_cast(List_item::get_prev_item()); } +}; + + +template< typename LI > +class L_list +{ +private: + LI *_h; + +public: + + L_list() : _h(0) {} + + void push_front(LI *e) { _h = LI::push_front(_h, e); } + void push_back(LI *e) { _h = LI::push_back(_h, e); } + void insert_before(LI *e, LI *p) + { + p->insert_prev_item(e); + if (_h == p) + _h = e; + } + void insert_after(LI *e, LI *p) { p->insert_next_item(e); } + + void remove(LI *e) + { _h = LI::remove(_h, e); } + + LI *head() const { return _h; } +}; + +/** + * Doubly linked list, with internal allocation. + * Container for items of type D, implemented by a doubly linked list. + * Alloc defines the allocator policy. + */ +template< typename D, template class Alloc = New_allocator > +class List +{ +private: + class E : public List_item + { + public: + E(D const &d) throw() : data(d) {} + D data; + }; + + +public: + class Node : private E + {}; + + typedef Alloc Node_alloc; + + /** + * Iterator. + * Forward and backward iteratable. + */ + class Iter + { + private: + List_item::T_iter _i; + + public: + Iter(E *e) throw() : _i(e) {} + + D &operator * () const throw() { return (*_i)->data; } + D &operator -> () const throw() { return (*_i)->data; } + + Iter operator ++ (int) throw() + { Iter o = *this; operator ++ (); return o; } + Iter operator -- (int) throw() + { Iter o = *this; operator -- (); return o; } + Iter &operator ++ () throw() { ++_i; return *this; } + Iter &operator -- () throw() { --_i; return *this; } + + /** operator for testing validity (syntactiaclly equal to pointers) */ + operator E* () const throw() { return *_i; } + }; + + List(Alloc const &a = Alloc()) throw() : _h(0), _l(0), _a(a) {} + + /** Add element at the end of the list. */ + void push_back(D const &d) throw() + { + void *n = _a.alloc(); + if (!n) return; + _h = E::push_back(_h, new (n) E(d)); + ++_l; + } + + /** Add element at the beginning of the list. */ + void push_front(D const &d) throw() + { + void *n = _a.alloc(); + if (!n) return; + _h = E::push_front(_h, new (n) E(d)); + ++_l; + } + + /** Remove element pointed to by the iterator. */ + void remove(Iter const &i) throw() + { E *e = i; _h = E::remove(_h, e); --_l; _a.free(e); } + + /** Get the length of the list. */ + unsigned long size() const throw() { return _l; } + + /** Random access. Complexity is O(n). */ + D const &operator [] (unsigned long idx) const throw() + { Iter i = _h; for (; idx && *i; ++i, --idx) ; return *i; } + + /** Random access. Complexity is O(n). */ + D &operator [] (unsigned long idx) throw() + { Iter i = _h; for (; idx && *i; ++i, --idx) ; return *i; } + + /** Get iterator for the list elements. */ + Iter items() throw() { return Iter(_h); } + +private: + E *_h; + unsigned _l; + Alloc _a; +}; + + +}; + diff --git a/l4/pkg/cxx/lib/tl/include/list_alloc b/l4/pkg/cxx/lib/tl/include/list_alloc new file mode 100644 index 00000000..e8355514 --- /dev/null +++ b/l4/pkg/cxx/lib/tl/include/list_alloc @@ -0,0 +1,326 @@ +// vim:ft=cpp +/* + * (c) 2008-2009 Alexander Warg , + * Torsten Frenzel + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ + +#pragma once + +#include + +namespace cxx { + +/** + * \brief Standard list-based allocator. + */ +class List_alloc +{ +private: + friend class List_alloc_sanity_guard; + + struct Mem_block + { + Mem_block *next; + unsigned long size; + }; + + Mem_block *_first; + + inline void check_overlap(void *, unsigned long ); + inline void sanity_check_list(char const *, char const *); + inline void merge(); + +public: + + /** + * \brief Initializes an empty list allocator. + * + * \note To initialize the allocator with available memory + * use the #free() function. + */ + List_alloc() : _first(0) {} + + /** + * \brief Return a free memory block to the allocator. + * + * \param block pointer to memory block + * \param size size of memory block + * \param initial_free Set to true for putting fresh memory + * to the allocator. This will enforce alignment on that + * memory. + */ + inline void free(void *block, unsigned long size, bool initial_free = false); + + /** + * \brief Alloc a memory block. + * + * \param size Size of the memory block + * \param align Alignment constraint + * + * \return Pointer to memory block + */ + inline void *alloc(unsigned long size, unsigned align); + + /** + * \brief Get the amount of available memory. + * + * \return Available memory in bytes + */ + inline unsigned long avail(); +}; + +#if !defined (CXX_LIST_ALLOC_SANITY) +class List_alloc_sanity_guard +{ +public: + List_alloc_sanity_guard(List_alloc *, char const *) + {} + +}; + + +void +List_alloc::check_overlap(void *, unsigned long ) +{} + +void +List_alloc::sanity_check_list(char const *, char const *) +{} + +#else + +class List_alloc_sanity_guard +{ +private: + List_alloc *a; + char const *func; + +public: + List_alloc_sanity_guard(List_alloc *a, char const *func) + : a(a), func(func) + { a->sanity_check_list(func, "entry"); } + + ~List_alloc_sanity_guard() + { a->sanity_check_list(func, "exit"); } +}; + +void +List_alloc::check_overlap(void *b, unsigned long s) +{ + unsigned long const mb_align = (1UL << arith::Ld::value) - 1; + if ((unsigned long)b & mb_align) + { + L4::cerr << "List_alloc(FATAL): trying to free unaligned memory: " + << b << " align=" << arith::Ld::value << "\n"; + } + + Mem_block *c = _first; + for (;c ; c = c->next) + { + unsigned long x_s = (unsigned long)b; + unsigned long x_e = x_s + s; + unsigned long b_s = (unsigned long)c; + unsigned long b_e = b_s + c->size; + + if ( (x_s >= b_s && x_s < b_e) + || (x_e > b_s && x_e <= b_e) + || (b_s >= x_s && b_s < x_e) + || (b_e > x_s && b_e <= x_e)) + { + L4::cerr << "List_alloc(FATAL): trying to free memory that " + "is already free: \n [" + << (void*)x_s << '-' << (void*)x_e << ") overlaps [" + << (void*)b_s << '-' << (void*)b_e << ")\n"; + } + } +} + +void +List_alloc::sanity_check_list(char const *func, char const *info) +{ + Mem_block *c = _first; + for (;c ; c = c->next) + { + if (c->next) + { + if (c >= c->next) + { + L4::cerr << "List_alloc(FATAL): " << func << '(' << info + << "): list oerder violation\n"; + } + + if (((unsigned long)c) + c->size > (unsigned long)c->next) + { + L4::cerr << "List_alloc(FATAL): " << func << '(' << info + << "): list oerder violation\n"; + } + } + } +} + +#endif + +void +List_alloc::merge() +{ + List_alloc_sanity_guard __attribute__((unused)) guard(this, __func__); + Mem_block *c = _first; + while (c && c->next) + { + unsigned long f_start = (unsigned long)c; + unsigned long f_end = f_start + c->size; + unsigned long n_start = (unsigned long)c->next; + + if (f_end == n_start) + { + c->size += c->next->size; + c->next = c->next->next; + continue; + } + + c = c->next; + } +} + +void +List_alloc::free(void *block, unsigned long size, bool initial_free) +{ + List_alloc_sanity_guard __attribute__((unused)) guard(this, __func__); + + unsigned long const mb_align = (1UL << arith::Ld::value) - 1; + + if (initial_free) + { + // enforce alignment constraint on initial memory + block = (void*)(((unsigned long)block + mb_align) & ~mb_align); + size &= ~mb_align; + } + else + // blow up size to the minimum aligned size + size = (size + mb_align) & ~mb_align; + + check_overlap(block, size); + + Mem_block **c = &_first; + Mem_block *next = 0; + + if (*c) + { + while (*c && *c < block) + c = &(*c)->next; + + next = *c; + } + + *c = (Mem_block*)block; + + (*c)->next = next; + (*c)->size = size; + + merge(); +} + +void * +List_alloc::alloc(unsigned long size, unsigned align) +{ + List_alloc_sanity_guard __attribute__((unused)) guard(this, __func__); + + unsigned long const mb_align = (1UL << arith::Ld::value) - 1; + + // blow up size to the minimum aligned size + size = (size + mb_align) & ~mb_align; + + unsigned long almask = align ? (align -1) : 0; + + // minimum alignment is given by the size of a Mem_block + if (almask < mb_align) + almask = mb_align; + + Mem_block **c = &_first; + + for (; *c; c=&(*c)->next) + { + // address of free memory block + unsigned long n_start = (unsigned long)(*c); + + // block too small, next + // XXX: maybe we can skip this and just do the test below + if ((*c)->size < size) + continue; + + // aligned start address within the free block + unsigned long a_start = (n_start + almask) & ~almask; + + // hm, block too small after alignment, next + if (a_start - n_start >= (*c)->size) + continue; + + // remaining size after subtracting the padding + // for the alignment + unsigned long r_size = (*c)->size - a_start + n_start; + + // block too small + if (r_size < size) + continue; + + if (a_start < n_start) + { + // have free space before the allocated block + // shrink the block and set c to the next pointer of that + // block + (*c)->size -= r_size; + c = &(*c)->next; + } + else + // drop the block, c remains the next pointer of the + // previous block + *c = (*c)->next; + + // allocated the whole remaining space + if (r_size == size) + return (void*)a_start; + + // add a new free block behind the allocated block + Mem_block *m = (Mem_block*)(a_start + size); + m->next = *c; + m->size = r_size - size; + *c = m; + return (void*)a_start; + } + + return 0; +} + +unsigned long +List_alloc::avail() +{ + List_alloc_sanity_guard __attribute__((unused)) guard(this, __FUNCTION__); + Mem_block *c = _first; + unsigned long a = 0; + while (c) + { + a += c->size; + c = c->next; + } + + return a; +} + + +} + + diff --git a/l4/pkg/cxx/lib/tl/include/minmax b/l4/pkg/cxx/lib/tl/include/minmax new file mode 100644 index 00000000..efa0da39 --- /dev/null +++ b/l4/pkg/cxx/lib/tl/include/minmax @@ -0,0 +1,48 @@ +// vi:ft=cpp +/* + * (c) 2008-2009 Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ + +#pragma once +/** + * \ingroup cxx_api + * \brief Various kinds of C++ utilities. + */ +namespace cxx +{ + /** + * \ingroup cxx_api + * \brief Get the minimum of \a a and \a b. + * \param a the first value. + * \param b the second value. + */ + template< typename T1 > + inline + T1 min(T1 a, T1 b) { return a + inline + T1 max(T1 a, T1 b) { return a>b?a:b;} +}; + + diff --git a/l4/pkg/cxx/lib/tl/include/observer b/l4/pkg/cxx/lib/tl/include/observer new file mode 100644 index 00000000..b52cac74 --- /dev/null +++ b/l4/pkg/cxx/lib/tl/include/observer @@ -0,0 +1,34 @@ +// vi:ft=cpp +/* + * (c) 2010 Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ +#pragma once + +#include + +namespace cxx { + +class Observer : public H_list_item +{ +public: + virtual void notify() = 0; +}; + +class Notifier : public H_list +{ +public: + void notify() + { + for (Iterator i = begin(); i != end(); ++i) + i->notify(); + } +}; + +} + + diff --git a/l4/pkg/cxx/lib/tl/include/pair b/l4/pkg/cxx/lib/tl/include/pair new file mode 100644 index 00000000..0156b3ae --- /dev/null +++ b/l4/pkg/cxx/lib/tl/include/pair @@ -0,0 +1,104 @@ +// vi:ft=cpp +/** + * \file + * \brief Pair implementation + */ +/* + * (c) 2008-2009 Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#pragma once + +namespace cxx { + +/** + * \ingroup cxx_api + * \brief Pair of two values. + * + * Standard container for a pair of values. + * \param First Type of the first value. + * \param Second Type of the second value. + */ +template< typename First, typename Second > +struct Pair +{ + /// Type of first value. + typedef First First_type; + /// Type of second value. + typedef Second Second_type; + + /// First value. + First first; + /// Second value. + Second second; + + /** + * \brief Create a pair from the two values. + * \param first The first value. + * \param second The second value. + */ + Pair(First const &first, Second const &second) + : first(first), second(second) {} + + /// Default construction. + Pair() {} +}; + +template< typename F, typename S > +Pair pair(F const &f, S const &s) +{ return cxx::Pair(f,s); } + + +/** + * \brief Comparison functor for Pair. + * \param Cmp Comparison functor for the first value of the pair. + * \param Typ The pair type. + * + * This functor can be used to compare Pair values with respect to the + * first value. + */ +template< typename Cmp, typename Typ > +class Pair_first_compare +{ +private: + Cmp const &_cmp; + +public: + /** + * \brief Construction. + * \param cmp The comparison functor used for the first value. + */ + Pair_first_compare(Cmp const &cmp = Cmp()) : _cmp(cmp) {} + + /** + * \brief Do the comaprison based on the first value. + * \param l The lefthand value. + * \param r The righthand value. + */ + bool operator () (Typ const &l, Typ const &r) const + { return _cmp(l.first,r.first); } +}; + +} + +template< typename OS, typename A, typename B > +inline +OS &operator << (OS &os, cxx::Pair const &p) +{ + os << p.first << ';' << p.second; + return os; +} + diff --git a/l4/pkg/cxx/lib/tl/include/ref_ptr b/l4/pkg/cxx/lib/tl/include/ref_ptr new file mode 100644 index 00000000..c492a431 --- /dev/null +++ b/l4/pkg/cxx/lib/tl/include/ref_ptr @@ -0,0 +1,201 @@ +// vim:ft=cpp +/* + * (c) 2008-2009 Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ + +#pragma once + +namespace cxx { + +template< typename T > +struct Default_ref_counter +{ + void h_drop_ref(T *p) throw() + { + if (p->remove_ref() == 0) + delete p; + } + + void h_take_ref(T *p) throw() + { + p->add_ref(); + } +}; + +struct Ref_ptr_base +{ + enum Default_value + { Nil = 0 }; +}; + +template class CNT = Default_ref_counter> +class Weak_ptr; + +template < + typename T = void, + template< typename X > class CNT = Default_ref_counter +> +class Ref_ptr : public Ref_ptr_base, private CNT +{ +private: + struct Null_type; + typedef Weak_ptr Wp; + +public: + Ref_ptr() throw() : _p(0) {} + + Ref_ptr(Ref_ptr_base::Default_value v) : _p((T*)v) {} + + Ref_ptr(Wp const &o) throw() : _p(o.ptr()) + { __take_ref(); } + + explicit Ref_ptr(T *o) throw() : _p(o) + { __take_ref(); } + + /** The couterpart to release (dows not create a new reference). + */ + Ref_ptr(T *o, bool) throw() : _p(o) {} + + T *get() const throw() + { + return _p; + } + + T *ptr() const throw() + { + return _p; + } + + T *release() throw() + { + T *p = _p; + _p = 0; + return p; + } + + ~Ref_ptr() throw() + { __drop_ref(); } + + template + Ref_ptr(Ref_ptr const &o) throw() + { + _p = o.ptr(); + __take_ref(); + } + + Ref_ptr(Ref_ptr const &o) throw() + { + _p = o._p; + __take_ref(); + } + + template< typename OT > + void operator = (Ref_ptr const &o) throw() + { + __drop_ref(); + _p = o.ptr(); + __take_ref(); + } + + void operator = (Ref_ptr const &o) throw() + { + if (&o == this) + return; + + __drop_ref(); + _p = o._p; + __take_ref(); + } + + void operator = (T *o) throw() + { + __drop_ref(); + _p = o; + __take_ref(); + } + + T *operator -> () const throw () + { return _p; } + + operator Null_type const * () const throw() + { return reinterpret_cast(_p); } + +private: + void __drop_ref() throw() + { + if (_p) + this->h_drop_ref(_p); + } + + void __take_ref() throw() + { + if (_p) + this->h_take_ref(_p); + } + + T *_p; +}; + + +template class CNT> +class Weak_ptr +{ +private: + struct Null_type; + typedef Ref_ptr Rp; + +public: + Weak_ptr() throw() {} + Weak_ptr(Rp const &o) throw() : _p(o.ptr()) {} + explicit Weak_ptr(T *o) throw() : _p(o) {} + + T *get() const throw() { return _p; } + T *ptr() const throw() { return _p; } + + T *operator -> () const throw () { return _p; } + operator Null_type const * () const throw() + { return reinterpret_cast(_p); } + +private: + T *_p; +}; + +template inline +Ref_ptr ref_ptr_static_cast(Ref_ptr const &o) +{ return ref_ptr(static_cast(o.ptr())); } + +template< typename T > +inline Ref_ptr ref_ptr(T *t) +{ return Ref_ptr(t); } + +template< typename T > +inline Weak_ptr weak_ptr(T *t) +{ return Weak_ptr(t); } + + +class Ref_obj +{ +private: + mutable int _ref_cnt; + +public: + Ref_obj() : _ref_cnt(0) {} + void add_ref() const throw() { ++_ref_cnt; } + int remove_ref() const throw() { return --_ref_cnt; } +}; + +} diff --git a/l4/pkg/cxx/lib/tl/include/slab_alloc b/l4/pkg/cxx/lib/tl/include/slab_alloc new file mode 100644 index 00000000..45c3ba1c --- /dev/null +++ b/l4/pkg/cxx/lib/tl/include/slab_alloc @@ -0,0 +1,432 @@ +// vi:ft=cpp +/* + * (c) 2008-2009 Alexander Warg , + * Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ + +#pragma once + +#include +#include +#include + +namespace cxx { + +/** + * \ingroup cxx_api + * \brief Basic slab allocator. + * \param Obj_size The size of the objects managed by the allocator (in bytes). + * \param Slab_size The size of a slab cache (in bytes). + * \param Max_free The maximum number of free slab caches. When this limit is + * reached slab caches are freed. + * \param Alloc The allocator that is used to allocate the slab caches. + */ +template< int Obj_size, int Slab_size = L4_PAGESIZE, + int Max_free = 2, template class Alloc = New_allocator > +class Base_slab +{ +private: + struct Free_o + { + Free_o *next; + }; + +protected: + struct Slab_i; + +private: + struct Slab_head : public H_list_item + { + unsigned num_free; + Free_o *free; + Base_slab *cache; + + inline Slab_head() throw() : num_free(0), free(0), cache(0) + {} + }; + +public: + enum + { + object_size = Obj_size, ///< size of an object. + slab_size = Slab_size, ///< size of a slab cache. + /// objects per slab cache. + objects_per_slab = (Slab_size - sizeof(Slab_head)) / object_size, + /// maximum number of free slab caches. + max_free_slabs = Max_free, + }; + +protected: + struct Slab_store + { + char _o[slab_size - sizeof(Slab_head)]; + Free_o *object(unsigned obj) throw() + { return reinterpret_cast(_o + object_size * obj); } + }; + + struct Slab_i : public Slab_store, public Slab_head + {}; + +public: + /// Type of the allocator for the slab caches. + typedef Alloc Slab_alloc; + + typedef void Obj_type; + +private: + Slab_alloc _alloc; + unsigned _num_free; + unsigned _num_slabs; + H_list _full_slabs; + H_list _partial_slabs; + H_list _empty_slabs; + + /// Add a new slab cache. + void add_slab(Slab_i *s) throw() + { + s->num_free = objects_per_slab; + s->cache = this; + + //L4::cerr << "Slab: " << this << "->add_slab(" << s << ", size=" + // << slab_size << "):" << " f=" << s->object(0) << '\n'; + + // initialize free list + Free_o *f = s->free = s->object(0); + for (unsigned i = 0; i < objects_per_slab; ++i) + { + f->next = s->object(i); + f = f->next; + } + f->next = 0; + + // insert slab into cache's list + _empty_slabs.push_front(s); + ++_num_slabs; + ++_num_free; + } + + /// Grow the allocator, by adding a new slab cache. + bool grow() throw() + { + Slab_i *s = _alloc.alloc(); + if (!s) + return false; + + new (s, cxx::Nothrow()) Slab_i(); + + add_slab(s); + return true; + } + + /// Shrink the allocator by freeing free slab caches. + void shrink() throw() + { + if (!_alloc.can_free) + return; + + while (!_empty_slabs.empty() && _num_free > max_free_slabs) + { + Slab_i *s = _empty_slabs.front(); + _empty_slabs.remove(s); + --_num_free; + --_num_slabs; + _alloc.free(s); + } + } + +public: + Base_slab(Slab_alloc const &alloc = Slab_alloc()) throw() + : _alloc(alloc), _num_free(0), _num_slabs(0), _full_slabs(0), + _partial_slabs(0), _empty_slabs(0) + {} + + ~Base_slab() throw() + { + while (!_empty_slabs.empty()) + { + Slab_i *o = _empty_slabs.front(); + _empty_slabs.remove(o); + _alloc.free(o); + } + while (!_partial_slabs.empty()) + { + Slab_i *o = _partial_slabs.front(); + _partial_slabs.remove(o); + _alloc.free(o); + } + while (!_full_slabs.empty()) + { + Slab_i *o = _full_slabs.front(); + _full_slabs.remove(o); + _alloc.free(o); + } + } + + void *alloc() throw() + { + H_list *free = &_partial_slabs; + if (free->empty()) + free = &_empty_slabs; + + if (free->empty() && !grow()) + return 0; + + Slab_i *s = free->front(); + Free_o *o = s->free; + s->free = o->next; + + if (free == &_empty_slabs) + { + _empty_slabs.remove(s); + --_num_free; + } + + --(s->num_free); + + if (!s->free) + { + _partial_slabs.remove(s); + _full_slabs.push_front(s); + } + else if (free == &_empty_slabs) + _partial_slabs.push_front(s); + + //L4::cerr << this << "->alloc(): " << o << ", of " << s << '\n'; + + return o; + } + + void free(void *_o) throw() + { + if (!_o) + return; + + unsigned long addr = (unsigned long)_o; + addr = (addr / slab_size) * slab_size; + Slab_i *s = (Slab_i*)addr; + + if (s->cache != this) + return; + + Free_o *o = reinterpret_cast(_o); + + o->next = s->free; + s->free = o; + + bool was_full = false; + + if (!s->num_free) + { + _full_slabs.remove(s); + was_full = true; + } + + ++(s->num_free); + + if (s->num_free == objects_per_slab) + { + if (!was_full) + _partial_slabs.remove(s); + + _empty_slabs.push_front(s); + ++_num_free; + if (_num_free > max_free_slabs) + shrink(); + + was_full = false; + } + else if (was_full) + _partial_slabs.push_front(s); + + //L4::cerr << this << "->free(" << _o << "): of " << s << '\n'; + } + + /** + * \brief Get the total number of objects managed by the slab allocator. + * \return The number of objects managed by the allocator (including the + * free objects). + */ + unsigned total_objects() const throw() + { return _num_slabs * objects_per_slab; } + + /** + * \brief Get the total number of objects managed by the slab allocator. + * \return The number of objects managed by the allocator (including the + * free objects). + */ + unsigned free_objects() const throw() + { + unsigned count = 0; + + /* count partial slabs first */ + for (typename H_list::Const_iterator s = _partial_slabs.begin(); + s != _partial_slabs.end(); ++s) + count += s->num_free; + + /* add empty slabs */ + count += _num_free * objects_per_slab; + + return count; + } +}; + +/** + * \ingroup cxx_api + * \brief Slab allocator for object of type \a Type. + * \param Type the type of the objects to manage. + * \param Slab_size size of a slab cache. + * \param Max_free the maximum number of free slab caches. + * \param Alloc the allocator for the slab caches. + */ +template class Alloc = New_allocator > +class Slab : public Base_slab +{ +private: + typedef Base_slab Base_type; +public: + + typedef Type Obj_type; + + Slab(typename Base_type::Slab_alloc const &alloc + = typename Base_type::Slab_alloc()) throw() + : Base_slab(alloc) {} + + + /** + * \brief Allocate an object of type \a Type. + * \return A pointer to the object just allocated, or 0 on failure. + */ + Type *alloc() throw() + { + return (Type*)Base_slab::alloc(); + } + + /** + * \brief Free the object addressed by \a o. + * \param o The pointer to the object to free. + * \pre The object must have been allocated with this allocator. + */ + void free(Type *o) throw() + { Base_slab::free(o); } +}; + + +/** + * \ingroup cxx_api + * \brief Merged slab allocator (allocators for objects of the same size + * are merged together). + * + * \param Obj_size The size of an object managed by the slab allocator. + * \param Slab_size The size of a slab cache. + * \param Max_free The maximum number of free slab caches. + * \param Alloc The allocator for the slab caches. + * + * This slab allocator class is useful for merging slab allocators with the + * same parameters (equal \a Obj_size, \a Slab_size, \a Max_free, and + * \a Alloc parameters) together and share the overhead for the slab caches + * among all equal-sized objects. + * + */ +template< int Obj_size, int Slab_size = L4_PAGESIZE, + int Max_free = 2, template class Alloc = New_allocator > +class Base_slab_static +{ +private: + typedef Base_slab _A; + static _A _a; +public: + typedef void Obj_type; + enum + { + object_size = Obj_size, ///< size of an object. + slab_size = Slab_size, ///< size of a slab cache. + /// number of objects per slab cache. + objects_per_slab = _A::objects_per_slab, + max_free_slabs = Max_free, ///< maximum number of free slab caches. + }; + + /** \brief Allocate an object. */ + void *alloc() throw() { return _a.alloc(); } + /** + * \brief Free the given object (\a p). + * \param p The pointer to the object to free. + * \pre \a p must be a pointer to an object allocated by this allocator. + */ + void free(void *p) throw() { _a.free(p); } + + /** + * \brief Get the total number of objects managed by the slab allocator. + * \return The number of objects managed by the allocator (including the + * free objects). + * \note The value is the merged value for all equal parameterized + * Base_slab_static instances. + */ + unsigned total_objects() const throw() { return _a.total_objects(); } + + /** + * \brief Get the number of free objects in the slab allocator. + * \return The number of free objects in all free and partially used + * slab caches managed by this allocator. + * \note The value is the merged value for all equal parameterized + * Base_slab_static instances. + */ + unsigned free_objects() const throw() { return _a.free_objects(); } +}; + + +template< int _O, int _S, int _M, template class Alloc > +typename Base_slab_static<_O,_S,_M,Alloc>::_A + Base_slab_static<_O,_S,_M,Alloc>::_a; + +/** + * \ingroup cxx_api + * \brief Merged slab allocator (allocators for objects of the same size + * are merged together). + * + * \param Type The type of the objects to manage. + * \param Slab_size The size of a slab cache. + * \param Max_free The maximum number of free slab caches. + * \param Alloc The allocator for the slab caches. + * + * This slab allocator class is useful for merging slab allocators with the + * same parameters (equal \a sizeof(Type), \a Slab_size, \a Max_free, and + * \a Alloc parameters) together and share the overhead for the slab caches + * among all equal-sized objects. + * + */ +template class Alloc = New_allocator > +class Slab_static +: public Base_slab_static +{ +public: + + typedef Type Obj_type; + /** + * \brief Allocate an object of type \a Type. + * \return A pointer to the just allocated object, or 0 of failure. + */ + Type *alloc() throw() + { + return (Type*)Base_slab_static::alloc(); + } +}; + +} diff --git a/l4/pkg/cxx/lib/tl/include/slist b/l4/pkg/cxx/lib/tl/include/slist new file mode 100644 index 00000000..66e0b6e8 --- /dev/null +++ b/l4/pkg/cxx/lib/tl/include/slist @@ -0,0 +1,162 @@ +// vi:ft=cpp +/* + * (c) 2011 Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ + +#pragma once + +#include "bits/list_basics.h" + +namespace cxx { + +class S_list_item +{ +public: + S_list_item() : _n(0) {} + explicit S_list_item(bool) {} + +private: + template friend class S_list; + template friend class S_list_tail; + template friend class Bits::Basic_list_policy; + + S_list_item(S_list_item const &); + void operator = (S_list_item const &); + + S_list_item *_n; +}; + +template< typename T, typename POLICY = Bits::Basic_list_policy< T, S_list_item > > +class S_list : public Bits::Basic_list +{ +private: + S_list(S_list const &); + void operator = (S_list const &); + + typedef typename Bits::Basic_list Base; + +public: + typedef typename Base::Iterator Iterator; + + // BSS allocation + explicit S_list(bool x) : Base(x) {} + + S_list() : Base() {} + + void add(T *e) + { + e->_n = this->_f; + this->_f = e; + } + + template< typename CAS > + void add(T *e, CAS const &c) + { + do + { + e->_n = this->_f; + } + while (!c(&this->_f, e->_n, e)); + } + + void push_front(T *e) { add(e); } + T *pop_front() + { + T *r = this->front(); + if (this->_f) + this->_f = this->_f->_n; + return r; + } + + void insert(T *e, Iterator const &pred) + { + S_list_item *p = *pred; + e->_n = p->_n; + p->_n = e; + } + + static void insert_before(T *e, Iterator const &succ) + { + S_list_item **x = Base::__get_internal(succ); + + e->_n = *x; + *x = e; + } + + static void replace(Iterator const &p, T*e) + { + S_list_item **x = Base::__get_internal(p); + e->_n = (*x)->_n; + *x = e; + } + + static Iterator erase(Iterator const &e) + { + S_list_item **x = Base::__get_internal(e); + *x = (*x)->_n; + return e; + } + +}; + + +template< typename T > +class S_list_bss : public S_list +{ +public: + S_list_bss() : S_list(true) {} +}; + +template< typename T, typename POLICY = Bits::Basic_list_policy< T, S_list_item > > +class S_list_tail : public S_list +{ +private: + typedef S_list Base; + +public: + S_list_tail() : Base(), _tail(&this->_f) {} + + void push_back(T *e) + { + e->_n = 0; + *_tail = e; + _tail = &e->_n; + } + + void clear() + { + Base::clear(); + _tail = &this->_f; + } + + void append(S_list_tail &o) + { + T *x = o.front(); + *_tail = x; + if (x) + _tail = o._tail; + o.clear(); + } + + void move_to(S_list_tail &t) + { t._f = this->_f; t._tail = _tail; clear(); } + +private: + S_list_item **_tail; +}; + +} diff --git a/l4/pkg/cxx/lib/tl/include/static_container b/l4/pkg/cxx/lib/tl/include/static_container new file mode 100644 index 00000000..daa8d76f --- /dev/null +++ b/l4/pkg/cxx/lib/tl/include/static_container @@ -0,0 +1,35 @@ +// vi:ft=cpp + +#pragma once + +#include +#include + +namespace cxx { + +template< typename T > +class Static_container +{ +public: + void operator = (Static_container const &) = delete; + Static_container(Static_container const &) = delete; + Static_container() = default; + + T *get() { return reinterpret_cast(_s); } + T *operator -> () { return get(); } + T &operator * () { return *get(); } + + void construct() + { new (reinterpret_cast(_s)) T; } + + template< typename ...Args > + void construct(Args... args) + { new (reinterpret_cast(_s)) T(cxx::forward(args)...); } + +private: + char _s[sizeof(T)] __attribute__((aligned(__alignof(T)))); +}; + +} + + diff --git a/l4/pkg/cxx/lib/tl/include/std_alloc b/l4/pkg/cxx/lib/tl/include/std_alloc new file mode 100644 index 00000000..81fe11c4 --- /dev/null +++ b/l4/pkg/cxx/lib/tl/include/std_alloc @@ -0,0 +1,78 @@ +// vi:ft=cpp +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ + +#pragma once + +#include +namespace cxx { +/** + * \ingroup cxx_api + * \brief Helper type to distinguish the oeprator new version + * that does not throw exceptions. + */ +class Nothrow {}; +} + +/** + * \ingroup cxx_api + * \brief Simple placement new operator. + * \param mem the address of the memory block to place the new object. + * \return the address given by \a mem. + */ +inline void *operator new (size_t, void *mem, cxx::Nothrow const &) throw() +{ return mem; } + +/** + * \ingroup cxx_api + * \brief New operator that does not throw exceptions. + */ +void *operator new (size_t, cxx::Nothrow const &) throw(); + +namespace cxx { + + +/** + * \ingroup cxx_api + * \brief Standard allocator based on operator new () . + * + * This allocator is the default allocator used for the \em cxx + * \em Containers, such as cxx::Avl_set and cxx::Avl_map, to allocate + * the internal data structures. + */ +template< typename _Type > +class New_allocator +{ +public: + enum { can_free = true }; + + New_allocator() throw() {} + New_allocator(New_allocator const &) throw() {} + + ~New_allocator() throw() {} + + _Type *alloc() throw() + { return static_cast<_Type*>(::operator new(sizeof (_Type), cxx::Nothrow())); } + + void free(_Type *t) throw() + { ::operator delete(t); } +}; + +} + diff --git a/l4/pkg/cxx/lib/tl/include/std_ops b/l4/pkg/cxx/lib/tl/include/std_ops new file mode 100644 index 00000000..3f8850ff --- /dev/null +++ b/l4/pkg/cxx/lib/tl/include/std_ops @@ -0,0 +1,36 @@ +// vim:ft=cpp +/* + * (c) 2008-2009 Alexander Warg , + * Torsten Frenzel + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ + +#pragma once + +namespace cxx { + +/** + * \brief Generic comparator class that defaults to the less-than operator. + */ +template< typename Obj > +struct Lt_functor +{ + bool operator () (Obj const &l, Obj const &r) const + { return l < r; } +}; + +}; + diff --git a/l4/pkg/cxx/lib/tl/include/type_traits b/l4/pkg/cxx/lib/tl/include/type_traits new file mode 100644 index 00000000..6d8602f7 --- /dev/null +++ b/l4/pkg/cxx/lib/tl/include/type_traits @@ -0,0 +1,129 @@ +// vi:ft=cpp + +/* + * (c) 2008-2009 Alexander Warg , + * Torsten Frenzel + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ + + +#pragma once + +#include "bits/type_traits.h" + + +#define CXX_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__) + + +namespace cxx { + +template< typename T, T V > +struct integral_constant +{ + static T const value = V; + typedef T value_type; + typedef integral_constant type; +}; + +typedef integral_constant true_type; +typedef integral_constant false_type; + +template< typename T > struct remove_reference; + +template< typename T > struct idendity { typedef T type; }; + +template< typename T1, typename T2 > struct is_same; + +template< typename T > struct remove_const; + +template< typename T > struct remove_volatile; + +template< typename T > struct remove_cv; + +template< typename T > struct remove_pointer; + + + +template< typename, typename > +struct is_same : public false_type {}; + +template< typename T > +struct is_same : public true_type {}; + +template< typename T > +struct remove_reference { typedef T type; }; + +template< typename T > +struct remove_reference { typedef T type; }; + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ +template< typename T > +struct remove_reference { typedef T type; }; +#endif + +template< typename T > struct remove_const { typedef T type; }; +template< typename T > struct remove_const { typedef T type; }; + +template< typename T > struct remove_volatile { typedef T type; }; +template< typename T > struct remove_volatile { typedef T type; }; + +template< typename T > +struct remove_cv { typedef typename remove_const::type>::type type; }; + +template< typename T, typename > +struct __remove_pointer_h { typedef T type; }; + +template< typename T, typename I > +struct __remove_pointer_h { typedef I type; }; + +template< typename T > +struct remove_pointer : public __remove_pointer_h::type> {}; + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ +#if CXX_GCC_VERSION >= 405 + +template< typename T > +inline T && +forward(typename cxx::remove_reference::type &t) +{ return static_cast(t); } + +template< typename T > +inline T && +forward(typename cxx::remove_reference::type &&t) +{ return static_cast(t); } + +#else + +template< typename T > +inline T && +forward(typename cxx::idendity::type &&t) +{ return t; } + +#endif + +template< typename T > +inline typename cxx::remove_reference::type && +move(T &t) { return static_cast::type &&>(t); } +#endif + +template< bool, typename T = void > +struct enable_if {}; + +template< typename T > +struct enable_if { typedef T type; }; + +} + diff --git a/l4/pkg/cxx/lib/tl/test/Makefile b/l4/pkg/cxx/lib/tl/test/Makefile new file mode 100644 index 00000000..70aad51b --- /dev/null +++ b/l4/pkg/cxx/lib/tl/test/Makefile @@ -0,0 +1,26 @@ +L4DIR := ../../../../.. +INCLUDEDIR := ../include $(L4DIR)/include +CXXFLAGS += -g $(addprefix -I,$(INCLUDEDIR)) +TESTS := avl_tree_test +all: do_test + +do_test: $(addsuffix .output, $(TESTS)) + $(foreach TEST,$(TESTS),diff -Nu $(TEST).reference $(TEST).output &&) true + +vpath %.h = $(INCLUDEDIR) + +avl_tree_test: avl_tree_test.cc avl_tree.h + +%.output: % + $< >$@ 2>&1 + +%.reference: % + $< >$@ 2>&1 + +references: $(addsuffix .reference,$(TESTS)) + +clean: + rm -rf $(addsuffix .output,$(TESTS)) + rm -rf $(TESTS) + +.PHONY: do_test references clean diff --git a/l4/pkg/cxx/lib/tl/test/avl_tree_test.cc b/l4/pkg/cxx/lib/tl/test/avl_tree_test.cc new file mode 100644 index 00000000..94819dbb --- /dev/null +++ b/l4/pkg/cxx/lib/tl/test/avl_tree_test.cc @@ -0,0 +1,143 @@ +/* + * (c) 2008-2009 Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#define DEBUG_AVL_TREE 1 + +#include "avl_tree.h" + +#include +#include + +class Region +{ +private: + unsigned long _start, _end; + +public: + Region() + : _start(0), _end(0) + {} + + Region(unsigned long start) + : _start(start), _end(start +1) + {} + + Region(unsigned long start, unsigned long end) + : _start(start), _end(end) + {} + + bool operator < (Region const &o) const + { return _end < o._start; } + + bool operator == (Region const &o) const + { return _start <= o._start && _end >= o._end; } + + friend std::ostream &operator << (std::ostream &s, Region const &r); +}; + +std::ostream &operator << (std::ostream &s, Region const &r) +{ + s << '[' << r._start << "; " << (void*)r._end << ']'; + return s; +} + + +typedef cxx::Avl_tree Tree; + +Tree tree; + + +#define check_x(a) \ + std::cerr << " => " #a " =====================\n"; \ + check_z(a) + +void check_z(int err) +{ + if (err) + { + std::cerr << "Error: " << err << "\n"; + abort(); + } + + tree.dump(); +} + +inline int ins(int x) +{ return tree.insert(x,x); } + +inline void find(int x) +{ + Tree::Node_type const *n; + std::cerr << "find(" << x << ") = "; + n = tree.find(x); + if (!n) + std::cerr << "[nil]\n"; + else + std::cerr << "(" << n->key << "; " << n->data << ")\n"; +} + + + +int main() +{ + std::cerr << "Test AVL Tree\n"; + check_x(ins(50)); + check_x(ins(60)); + check_x(ins(70)); + check_x(ins(80)); + check_x(ins(81)); + check_x(ins(45)); + check_x(ins(40)); + check_x(ins(35)); + check_x(ins(33)); + check_x(ins(32)); + check_x(ins(41)); + check_x(ins(42)); + check_x(ins(43)); + check_x(ins(31)); + check_x(ins(30)); + check_x(ins(29)); + check_x(ins(28)); + check_x(ins(27)); + check_x(ins(26)); + + std::cerr << "Find some entries\n"; + find(10); + find(50); + find(26); + find(30); + find(34); + find(22); + find(81); + + std::cerr << "Remove some entries\n"; + check_x(tree.remove(29)); + check_x(tree.remove(70)); + check_x(tree.remove(50)); + check_x(tree.remove(60)); + check_x(tree.remove(26)); + check_x(tree.remove(32)); + check_x(tree.remove(35)); + check_x(tree.remove(30)); + check_x(tree.remove(45)); + check_x(tree.remove(43)); + check_x(tree.remove(80)); + check_x(tree.remove(41)); + check_x(tree.remove(42)); + + return 0; +} diff --git a/l4/pkg/cxx/lib/tl/test/avl_tree_test.reference b/l4/pkg/cxx/lib/tl/test/avl_tree_test.reference new file mode 100644 index 00000000..8c8b21b5 --- /dev/null +++ b/l4/pkg/cxx/lib/tl/test/avl_tree_test.reference @@ -0,0 +1,388 @@ +Test AVL Tree + => ins(50) ===================== +* K:50; D:50; B0 + => ins(60) ===================== +* K:50; D:50; B1 +*R K:60; D:60; B0 + => ins(70) ===================== +* K:60; D:60; B0 +*L K:50; D:50; B0 +*R K:70; D:70; B0 + => ins(80) ===================== +* K:60; D:60; B1 +*L K:50; D:50; B0 +*R K:70; D:70; B1 +*RR K:80; D:80; B0 + => ins(81) ===================== +* K:60; D:60; B1 +*L K:50; D:50; B0 +*R K:80; D:80; B0 +*RL K:70; D:70; B0 +*RR K:81; D:81; B0 + => ins(45) ===================== +* K:60; D:60; B0 +*L K:50; D:50; B-1 +*LL K:45; D:45; B0 +*R K:80; D:80; B0 +*RL K:70; D:70; B0 +*RR K:81; D:81; B0 + => ins(40) ===================== +* K:60; D:60; B0 +*L K:45; D:45; B0 +*LL K:40; D:40; B0 +*LR K:50; D:50; B0 +*R K:80; D:80; B0 +*RL K:70; D:70; B0 +*RR K:81; D:81; B0 + => ins(35) ===================== +* K:60; D:60; B-1 +*L K:45; D:45; B-1 +*LL K:40; D:40; B-1 +*LLL K:35; D:35; B0 +*LR K:50; D:50; B0 +*R K:80; D:80; B0 +*RL K:70; D:70; B0 +*RR K:81; D:81; B0 + => ins(33) ===================== +* K:60; D:60; B-1 +*L K:45; D:45; B-1 +*LL K:35; D:35; B0 +*LLL K:33; D:33; B0 +*LLR K:40; D:40; B0 +*LR K:50; D:50; B0 +*R K:80; D:80; B0 +*RL K:70; D:70; B0 +*RR K:81; D:81; B0 + => ins(32) ===================== +* K:60; D:60; B-1 +*L K:35; D:35; B0 +*LL K:33; D:33; B-1 +*LLL K:32; D:32; B0 +*LR K:45; D:45; B0 +*LRL K:40; D:40; B0 +*LRR K:50; D:50; B0 +*R K:80; D:80; B0 +*RL K:70; D:70; B0 +*RR K:81; D:81; B0 + => ins(41) ===================== +* K:45; D:45; B0 +*L K:35; D:35; B0 +*LL K:33; D:33; B-1 +*LLL K:32; D:32; B0 +*LR K:40; D:40; B1 +*LRR K:41; D:41; B0 +*R K:60; D:60; B1 +*RL K:50; D:50; B0 +*RR K:80; D:80; B0 +*RRL K:70; D:70; B0 +*RRR K:81; D:81; B0 + => ins(42) ===================== +* K:45; D:45; B0 +*L K:35; D:35; B0 +*LL K:33; D:33; B-1 +*LLL K:32; D:32; B0 +*LR K:41; D:41; B0 +*LRL K:40; D:40; B0 +*LRR K:42; D:42; B0 +*R K:60; D:60; B1 +*RL K:50; D:50; B0 +*RR K:80; D:80; B0 +*RRL K:70; D:70; B0 +*RRR K:81; D:81; B0 + => ins(43) ===================== +* K:45; D:45; B-1 +*L K:35; D:35; B1 +*LL K:33; D:33; B-1 +*LLL K:32; D:32; B0 +*LR K:41; D:41; B1 +*LRL K:40; D:40; B0 +*LRR K:42; D:42; B1 +*LRRR K:43; D:43; B0 +*R K:60; D:60; B1 +*RL K:50; D:50; B0 +*RR K:80; D:80; B0 +*RRL K:70; D:70; B0 +*RRR K:81; D:81; B0 + => ins(31) ===================== +* K:45; D:45; B-1 +*L K:35; D:35; B1 +*LL K:32; D:32; B0 +*LLL K:31; D:31; B0 +*LLR K:33; D:33; B0 +*LR K:41; D:41; B1 +*LRL K:40; D:40; B0 +*LRR K:42; D:42; B1 +*LRRR K:43; D:43; B0 +*R K:60; D:60; B1 +*RL K:50; D:50; B0 +*RR K:80; D:80; B0 +*RRL K:70; D:70; B0 +*RRR K:81; D:81; B0 + => ins(30) ===================== +* K:45; D:45; B-1 +*L K:35; D:35; B0 +*LL K:32; D:32; B-1 +*LLL K:31; D:31; B-1 +*LLLL K:30; D:30; B0 +*LLR K:33; D:33; B0 +*LR K:41; D:41; B1 +*LRL K:40; D:40; B0 +*LRR K:42; D:42; B1 +*LRRR K:43; D:43; B0 +*R K:60; D:60; B1 +*RL K:50; D:50; B0 +*RR K:80; D:80; B0 +*RRL K:70; D:70; B0 +*RRR K:81; D:81; B0 + => ins(29) ===================== +* K:45; D:45; B-1 +*L K:35; D:35; B0 +*LL K:32; D:32; B-1 +*LLL K:30; D:30; B0 +*LLLL K:29; D:29; B0 +*LLLR K:31; D:31; B0 +*LLR K:33; D:33; B0 +*LR K:41; D:41; B1 +*LRL K:40; D:40; B0 +*LRR K:42; D:42; B1 +*LRRR K:43; D:43; B0 +*R K:60; D:60; B1 +*RL K:50; D:50; B0 +*RR K:80; D:80; B0 +*RRL K:70; D:70; B0 +*RRR K:81; D:81; B0 + => ins(28) ===================== +* K:45; D:45; B-1 +*L K:35; D:35; B0 +*LL K:30; D:30; B0 +*LLL K:29; D:29; B-1 +*LLLL K:28; D:28; B0 +*LLR K:32; D:32; B0 +*LLRL K:31; D:31; B0 +*LLRR K:33; D:33; B0 +*LR K:41; D:41; B1 +*LRL K:40; D:40; B0 +*LRR K:42; D:42; B1 +*LRRR K:43; D:43; B0 +*R K:60; D:60; B1 +*RL K:50; D:50; B0 +*RR K:80; D:80; B0 +*RRL K:70; D:70; B0 +*RRR K:81; D:81; B0 + => ins(27) ===================== +* K:45; D:45; B-1 +*L K:35; D:35; B0 +*LL K:30; D:30; B0 +*LLL K:28; D:28; B0 +*LLLL K:27; D:27; B0 +*LLLR K:29; D:29; B0 +*LLR K:32; D:32; B0 +*LLRL K:31; D:31; B0 +*LLRR K:33; D:33; B0 +*LR K:41; D:41; B1 +*LRL K:40; D:40; B0 +*LRR K:42; D:42; B1 +*LRRR K:43; D:43; B0 +*R K:60; D:60; B1 +*RL K:50; D:50; B0 +*RR K:80; D:80; B0 +*RRL K:70; D:70; B0 +*RRR K:81; D:81; B0 + => ins(26) ===================== +* K:35; D:35; B0 +*L K:30; D:30; B-1 +*LL K:28; D:28; B-1 +*LLL K:27; D:27; B-1 +*LLLL K:26; D:26; B0 +*LLR K:29; D:29; B0 +*LR K:32; D:32; B0 +*LRL K:31; D:31; B0 +*LRR K:33; D:33; B0 +*R K:45; D:45; B0 +*RL K:41; D:41; B1 +*RLL K:40; D:40; B0 +*RLR K:42; D:42; B1 +*RLRR K:43; D:43; B0 +*RR K:60; D:60; B1 +*RRL K:50; D:50; B0 +*RRR K:80; D:80; B0 +*RRRL K:70; D:70; B0 +*RRRR K:81; D:81; B0 +Find some entries +find(10) = [nil] +find(50) = (50; 50) +find(26) = (26; 26) +find(30) = (30; 30) +find(34) = [nil] +find(22) = [nil] +find(81) = (81; 81) +Remove some entries + => tree.remove(29) ===================== +* K:35; D:35; B1 +*L K:30; D:30; B0 +*LL K:27; D:27; B0 +*LLL K:26; D:26; B0 +*LLR K:28; D:28; B0 +*LR K:32; D:32; B0 +*LRL K:31; D:31; B0 +*LRR K:33; D:33; B0 +*R K:45; D:45; B0 +*RL K:41; D:41; B1 +*RLL K:40; D:40; B0 +*RLR K:42; D:42; B1 +*RLRR K:43; D:43; B0 +*RR K:60; D:60; B1 +*RRL K:50; D:50; B0 +*RRR K:80; D:80; B0 +*RRRL K:70; D:70; B0 +*RRRR K:81; D:81; B0 + => tree.remove(70) ===================== +* K:35; D:35; B1 +*L K:30; D:30; B0 +*LL K:27; D:27; B0 +*LLL K:26; D:26; B0 +*LLR K:28; D:28; B0 +*LR K:32; D:32; B0 +*LRL K:31; D:31; B0 +*LRR K:33; D:33; B0 +*R K:45; D:45; B0 +*RL K:41; D:41; B1 +*RLL K:40; D:40; B0 +*RLR K:42; D:42; B1 +*RLRR K:43; D:43; B0 +*RR K:60; D:60; B1 +*RRL K:50; D:50; B0 +*RRR K:80; D:80; B1 +*RRRR K:81; D:81; B0 + => tree.remove(50) ===================== +* K:35; D:35; B1 +*L K:30; D:30; B0 +*LL K:27; D:27; B0 +*LLL K:26; D:26; B0 +*LLR K:28; D:28; B0 +*LR K:32; D:32; B0 +*LRL K:31; D:31; B0 +*LRR K:33; D:33; B0 +*R K:45; D:45; B-1 +*RL K:41; D:41; B1 +*RLL K:40; D:40; B0 +*RLR K:42; D:42; B1 +*RLRR K:43; D:43; B0 +*RR K:80; D:80; B0 +*RRL K:60; D:60; B0 +*RRR K:81; D:81; B0 + => tree.remove(60) ===================== +* K:35; D:35; B1 +*L K:30; D:30; B0 +*LL K:27; D:27; B0 +*LLL K:26; D:26; B0 +*LLR K:28; D:28; B0 +*LR K:32; D:32; B0 +*LRL K:31; D:31; B0 +*LRR K:33; D:33; B0 +*R K:45; D:45; B-1 +*RL K:41; D:41; B1 +*RLL K:40; D:40; B0 +*RLR K:42; D:42; B1 +*RLRR K:43; D:43; B0 +*RR K:80; D:80; B1 +*RRR K:81; D:81; B0 + => tree.remove(26) ===================== +* K:35; D:35; B1 +*L K:30; D:30; B0 +*LL K:27; D:27; B1 +*LLR K:28; D:28; B0 +*LR K:32; D:32; B0 +*LRL K:31; D:31; B0 +*LRR K:33; D:33; B0 +*R K:45; D:45; B-1 +*RL K:41; D:41; B1 +*RLL K:40; D:40; B0 +*RLR K:42; D:42; B1 +*RLRR K:43; D:43; B0 +*RR K:80; D:80; B1 +*RRR K:81; D:81; B0 + => tree.remove(32) ===================== +* K:35; D:35; B1 +*L K:30; D:30; B0 +*LL K:27; D:27; B1 +*LLR K:28; D:28; B0 +*LR K:31; D:31; B1 +*LRR K:33; D:33; B0 +*R K:45; D:45; B-1 +*RL K:41; D:41; B1 +*RLL K:40; D:40; B0 +*RLR K:42; D:42; B1 +*RLRR K:43; D:43; B0 +*RR K:80; D:80; B1 +*RRR K:81; D:81; B0 + => tree.remove(35) ===================== +* K:33; D:33; B1 +*L K:30; D:30; B-1 +*LL K:27; D:27; B1 +*LLR K:28; D:28; B0 +*LR K:31; D:31; B0 +*R K:45; D:45; B-1 +*RL K:41; D:41; B1 +*RLL K:40; D:40; B0 +*RLR K:42; D:42; B1 +*RLRR K:43; D:43; B0 +*RR K:80; D:80; B1 +*RRR K:81; D:81; B0 + => tree.remove(30) ===================== +* K:41; D:41; B0 +*L K:33; D:33; B-1 +*LL K:28; D:28; B0 +*LLL K:27; D:27; B0 +*LLR K:31; D:31; B0 +*LR K:40; D:40; B0 +*R K:45; D:45; B0 +*RL K:42; D:42; B1 +*RLR K:43; D:43; B0 +*RR K:80; D:80; B1 +*RRR K:81; D:81; B0 + => tree.remove(45) ===================== +* K:41; D:41; B0 +*L K:33; D:33; B-1 +*LL K:28; D:28; B0 +*LLL K:27; D:27; B0 +*LLR K:31; D:31; B0 +*LR K:40; D:40; B0 +*R K:43; D:43; B1 +*RL K:42; D:42; B0 +*RR K:80; D:80; B1 +*RRR K:81; D:81; B0 + => tree.remove(43) ===================== +* K:41; D:41; B-1 +*L K:33; D:33; B-1 +*LL K:28; D:28; B0 +*LLL K:27; D:27; B0 +*LLR K:31; D:31; B0 +*LR K:40; D:40; B0 +*R K:80; D:80; B0 +*RL K:42; D:42; B0 +*RR K:81; D:81; B0 + => tree.remove(80) ===================== +* K:41; D:41; B-1 +*L K:33; D:33; B-1 +*LL K:28; D:28; B0 +*LLL K:27; D:27; B0 +*LLR K:31; D:31; B0 +*LR K:40; D:40; B0 +*R K:42; D:42; B1 +*RR K:81; D:81; B0 + => tree.remove(41) ===================== +* K:40; D:40; B-1 +*L K:28; D:28; B1 +*LL K:27; D:27; B0 +*LR K:33; D:33; B-1 +*LRL K:31; D:31; B0 +*R K:42; D:42; B1 +*RR K:81; D:81; B0 + => tree.remove(42) ===================== +* K:33; D:33; B0 +*L K:28; D:28; B0 +*LL K:27; D:27; B0 +*LR K:31; D:31; B0 +*R K:40; D:40; B1 +*RR K:81; D:81; B0 diff --git a/l4/pkg/cxx/lib/util/Makefile b/l4/pkg/cxx/lib/util/Makefile new file mode 100644 index 00000000..0cc976f7 --- /dev/null +++ b/l4/pkg/cxx/lib/util/Makefile @@ -0,0 +1,8 @@ +PKGDIR = ../.. +L4DIR ?= $(PKGDIR)/../.. + +TARGET := include src + +include $(L4DIR)/mk/subdir.mk + +src: include diff --git a/l4/pkg/cxx/lib/util/include/Makefile b/l4/pkg/cxx/lib/util/include/Makefile new file mode 100644 index 00000000..ed2323b5 --- /dev/null +++ b/l4/pkg/cxx/lib/util/include/Makefile @@ -0,0 +1,4 @@ +PKGDIR = ../../.. +L4DIR ?= $(PKGDIR)/../.. + +include $(L4DIR)/mk/include.mk diff --git a/l4/pkg/cxx/lib/util/include/alloc.h b/l4/pkg/cxx/lib/util/include/alloc.h new file mode 100644 index 00000000..b122fd90 --- /dev/null +++ b/l4/pkg/cxx/lib/util/include/alloc.h @@ -0,0 +1,55 @@ +/** + * \file + * \brief Alloc list + */ +/* + * (c) 2004-2009 Alexander Warg , + * Torsten Frenzel + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ + +#ifndef L4_CXX_ALLOC_H__ +#define L4_CXX_ALLOC_H__ + +namespace L4 { + + /** + * \brief A simple list-based allocator. + * \ingroup cxx_api + */ + class Alloc_list + { + public: + Alloc_list() : _free(0) {} + Alloc_list( void *blk, unsigned long size ) : _free(0) + { free( blk, size ); } + + void free( void *blk, unsigned long size ); + void *alloc( unsigned long size ); + + private: + struct Elem + { + Elem *next; + unsigned long size; + }; + + Elem *_free; + }; +}; + +#endif // L4_CXX_ALLOC_H__ + diff --git a/l4/pkg/cxx/lib/util/include/atomic.h b/l4/pkg/cxx/lib/util/include/atomic.h new file mode 100644 index 00000000..df2c1263 --- /dev/null +++ b/l4/pkg/cxx/lib/util/include/atomic.h @@ -0,0 +1,53 @@ +/** + * \file + * \brief Atomic template + */ +/* + * (c) 2004-2009 Adam Lackorzynski , + * Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ + +#ifndef L4_CXX_ATOMIC_H__ +#define L4_CXX_ATOMIC_H__ + +#include + +extern "C" void ____error_compare_and_swap_does_not_support_3_bytes____(); +extern "C" void ____error_compare_and_swap_does_not_support_more_than_4_bytes____(); + +namespace L4 +{ + template< typename X > + inline int compare_and_swap(X volatile *dst, X old_val, X new_val) + { + switch (sizeof(X)) + { + case 1: + return l4util_cmpxchg8((l4_uint8_t volatile*)dst, old_val, new_val); + case 2: + return l4util_cmpxchg16((l4_uint16_t volatile *)dst, old_val, new_val); + case 3: ____error_compare_and_swap_does_not_support_3_bytes____(); + case 4: + return l4util_cmpxchg32((l4_uint32_t volatile*)dst, old_val, new_val); + default: + ____error_compare_and_swap_does_not_support_more_than_4_bytes____(); + } + return 0; + } +}; + +#endif // L4_CXX_ATOMIC_H__ diff --git a/l4/pkg/cxx/lib/util/include/l4types.h b/l4/pkg/cxx/lib/util/include/l4types.h new file mode 100644 index 00000000..965f15b9 --- /dev/null +++ b/l4/pkg/cxx/lib/util/include/l4types.h @@ -0,0 +1,27 @@ +/** + * \file + * \brief L4 Types + */ +/* + * (c) 2004-2009 Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ + +#pragma once + +#include +#include + diff --git a/l4/pkg/cxx/lib/util/include/string.h b/l4/pkg/cxx/lib/util/include/string.h new file mode 100644 index 00000000..21449d0f --- /dev/null +++ b/l4/pkg/cxx/lib/util/include/string.h @@ -0,0 +1,59 @@ +/** + * \file + * \brief String + */ +/* + * (c) 2004-2009 Alexander Warg , + * Torsten Frenzel + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ + +#ifndef L4_CXX_STRING_H__ +#define L4_CXX_STRING_H__ + +#include + +namespace L4 { + + /** + * \brief A null-terminated string container class. + * \ingroup cxx_api + */ + class String + { + public: + String( char const *str = "" ) : _str(str) + {} + + unsigned length() const + { unsigned l; for( l=0; _str[l] ; l++); return l; } + + char const *p_str() const { return _str; } + + private: + char const *_str; + }; + +}; + +inline +L4::BasicOStream &operator << (L4::BasicOStream &o, L4::String const &s) +{ + o << s.p_str(); + return o; +} + +#endif /* L4_CXX_STRING_H__ */ diff --git a/l4/pkg/cxx/lib/util/src/Makefile b/l4/pkg/cxx/lib/util/src/Makefile new file mode 100644 index 00000000..61718739 --- /dev/null +++ b/l4/pkg/cxx/lib/util/src/Makefile @@ -0,0 +1,12 @@ +PKGDIR ?= ../../.. +L4DIR ?= $(PKGDIR)/../.. + +TARGET = libcxx_util +PC_FILENAME = cxx_util +SRC_CC = ipc_error_str.cc alloc_list.cc +SYSTEMS = $(SYSTEMS_PLAIN) + +include $(PKGDIR)/lib/Makefile.inc +include $(L4DIR)/mk/lib.mk + +$(GENERAL_D_LOC): $(L4DIR)/pkg/cxx/lib/Makefile.inc diff --git a/l4/pkg/cxx/lib/util/src/alloc_list.cc b/l4/pkg/cxx/lib/util/src/alloc_list.cc new file mode 100644 index 00000000..da0c98b0 --- /dev/null +++ b/l4/pkg/cxx/lib/util/src/alloc_list.cc @@ -0,0 +1,93 @@ +/* + * (c) 2004-2009 Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ + +#include + +namespace L4 { + + void Alloc_list::free( void *blk, unsigned long size ) + { + Elem *n = reinterpret_cast(blk); + Elem **c = &_free; + while (*c) + { + if (reinterpret_cast(*c) + (*c)->size == blk) + { + (*c)->size += size; + blk = 0; + break; + } + + if (reinterpret_cast(*c) > blk) + break; + + c = &((*c)->next); + } + + if (blk) + { + n->next = *c; + n->size = size; + *c = n; + } + + while (*c && reinterpret_cast(*c)+(*c)->size == (char*)((*c)->next)) + { + (*c)->size += (*c)->next->size; + (*c)->next = (*c)->next->next; + } + } + + void *Alloc_list::alloc( unsigned long size ) + { + if (!_free) + return 0; + + // best fit; + Elem **min = 0; + Elem **c = &_free; + + while(*c) + { + if ((*c)->size >= size && (!min || (*min)->size > (*c)->size)) + min = c; + + c = &((*c)->next); + } + + if (!min) + return 0; + + + void *r; + if ( (*min)->size > size ) + { + r = reinterpret_cast(*min) + ((*min)->size - size); + (*min)->size -= size; + } + else + { + r = *min; + *min = (*min)->next; + } + + return r; + } + +} + diff --git a/l4/pkg/cxx/lib/util/src/ipc_error_str.cc b/l4/pkg/cxx/lib/util/src/ipc_error_str.cc new file mode 100644 index 00000000..a70802d8 --- /dev/null +++ b/l4/pkg/cxx/lib/util/src/ipc_error_str.cc @@ -0,0 +1,31 @@ +/* + * (c) 2004-2009 Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ + +namespace L4 { + + char const *ipc_error_str[] = + { "ok", + "timeout", + "phase canceled", + "mapping failed", + "send page fault timeout", + "receive page fault timeout", + "aborted", + "message cut" + }; +}; diff --git a/l4/pkg/drivers-frst/Control b/l4/pkg/drivers-frst/Control new file mode 100644 index 00000000..59ade69b --- /dev/null +++ b/l4/pkg/drivers-frst/Control @@ -0,0 +1,3 @@ +requires: libc +provides: drivers_uart drivers_of libdrivers-nand +Maintainer: adam@os.inf.tu-dresden.de diff --git a/l4/pkg/drivers-frst/Makefile b/l4/pkg/drivers-frst/Makefile new file mode 100644 index 00000000..ab3f4bb3 --- /dev/null +++ b/l4/pkg/drivers-frst/Makefile @@ -0,0 +1,8 @@ +PKGDIR = . +L4DIR ?= $(PKGDIR)/../.. + +TARGET = $(wildcard [a-z]*) + +include $(L4DIR)/mk/subdir.mk + +uart: of include diff --git a/l4/pkg/drivers-frst/hpet/Makefile b/l4/pkg/drivers-frst/hpet/Makefile new file mode 100644 index 00000000..8209f639 --- /dev/null +++ b/l4/pkg/drivers-frst/hpet/Makefile @@ -0,0 +1,8 @@ +PKGDIR = .. +L4DIR ?= $(PKGDIR)/../.. + +TARGET := include src + +include $(L4DIR)/mk/subdir.mk + +src: include diff --git a/l4/pkg/drivers-frst/hpet/include/Makefile b/l4/pkg/drivers-frst/hpet/include/Makefile new file mode 100644 index 00000000..554937fa --- /dev/null +++ b/l4/pkg/drivers-frst/hpet/include/Makefile @@ -0,0 +1,7 @@ +PKGDIR = ../.. +L4DIR ?= $(PKGDIR)/../.. + +PKGNAME = drivers +EXTRA_TARGET = hpet + +include $(L4DIR)/mk/include.mk diff --git a/l4/pkg/drivers-frst/hpet/include/hpet b/l4/pkg/drivers-frst/hpet/include/hpet new file mode 100644 index 00000000..5d031e82 --- /dev/null +++ b/l4/pkg/drivers-frst/hpet/include/hpet @@ -0,0 +1,155 @@ +// vim: set ft=cpp: +/* + * (c) 2010 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ +#pragma once + +#include +#include + +namespace L4 { +namespace Driver { + +class Hpet +{ +public: + // General Capabilities and ID Register + unsigned rev_id() const { l4_mb(); return _cap_and_id & 0xff; } + unsigned num_tim_cap() const { l4_mb(); return ((_cap_and_id >> 8) & 0x1f) + 1; } + unsigned count_size_cap() const { l4_mb(); return _cap_and_id & (1 << 13); } + unsigned leg_rt_cap() const { l4_mb(); return _cap_and_id & (1 << 13); } + unsigned vendor_id() const { l4_mb(); return (_cap_and_id >> 16) & 0xffff; }; + l4_uint32_t counter_clk_period() const { l4_mb(); return _cap_and_id >> 32; } + + // General Configuration Register + unsigned enabled() const { return _conf & 1; } + void enable() { _conf |= 1; l4_wmb(); } + void disable() { _conf &= ~1; l4_wmb(); } + unsigned leg_rt_cnf() const { return _conf & 2; } + void legacy_route_enable() { _conf |= 2; l4_wmb(); } + void legacy_route_disable() { _conf &= ~2; l4_wmb(); } + + // General Interrupt Status Register + unsigned irq_active(int irqnum) const { l4_mb(); return (1 << irqnum) & _int_status; } + void irq_clear_active(int irqnum) + { + _int_status = 1 << irqnum; l4_wmb(); + typeof(_int_status) dummy = *(volatile typeof(_int_status) *)&_int_status; + (void)dummy; + } + + // Main Counter Register + l4_uint64_t main_counter_val() const { l4_mb(); return _main_counter; } + void main_counter_val(l4_uint64_t v) { _main_counter = v; l4_wmb(); } + + class Timer + { + public: + // Timer N Configuration and Capability Register + void set_int_type_level() { _conf_and_cap |= 2; l4_wmb(); } + void set_int_type_edge() { _conf_and_cap &= ~2; l4_wmb(); } + unsigned is_int_type_level() const { return _conf_and_cap & 2; } + unsigned is_int_type_edge() const { return !is_int_type_level(); } + + void enable_int() { _conf_and_cap |= 4; l4_wmb(); } + void disable_int() { _conf_and_cap &= ~4; l4_wmb(); } + unsigned is_int_enabled() const { return _conf_and_cap & 4; } + + void set_periodic() { _conf_and_cap |= 8; l4_wmb(); } + void set_nonperiodic() { _conf_and_cap &= ~8; l4_wmb(); } + unsigned is_periodic() const { return _conf_and_cap & 8; } + unsigned is_nonperiodic() const { return !is_periodic(); } + + unsigned periodic_int_capable() const { return _conf_and_cap & (1 << 4); } + unsigned can_64bit() const { return _conf_and_cap & (1 << 5); } + + void val_set_cnf() { _conf_and_cap |= 1 << 6; l4_wmb(); } + + void force_32bit() { _conf_and_cap |= 1 << 8; l4_wmb(); } + unsigned forced_32bit() const { return _conf_and_cap & (1 << 8); } + + unsigned int_route_cnf() const { return (_conf_and_cap >> 9) & 0x1f; } + void set_int_route(unsigned irqnum) + { _conf_and_cap = (_conf_and_cap & ~(31 << 9)) | (irqnum << 9); } + + void enable_fsb() { _conf_and_cap |= 1 << 14; l4_wmb(); } + void disable_fsb() { _conf_and_cap &= ~(1 << 14); l4_wmb(); } + unsigned is_fsb() const { return _conf_and_cap & (1 << 14); } + + unsigned can_fsb() const { return _conf_and_cap & (1 << 15); } + + + l4_uint32_t int_route_cap() const { return _conf_and_cap >> 32; } + unsigned int_avail(int int_nr) const { return int_route_cap() & (1 << int_nr); } + unsigned ints_avail() const { return int_route_cap(); } + + int get_first_int(int i = 0) + { + l4_uint32_t cap = int_route_cap(); + for (; i < 32; ++i) + if (cap & (1 << i)) + return i; + return ~0U; + } + + l4_uint64_t comparator() const { return _comp; } + void set_comparator(l4_uint64_t v) { _comp = v; l4_wmb(); } + + void fsb_int_addr(l4_uint32_t addr) { _int_route_addr = addr; } + void fsb_int_val(l4_uint32_t val) { _int_route_val = val; } + + void print_state() const; + + l4_uint64_t conf_and_cap() const { return _conf_and_cap; } + l4_uint64_t comp() const { return _comp; } + + private: + l4_uint64_t _conf_and_cap; + l4_uint64_t _comp; + l4_uint32_t _int_route_addr; // right order? + l4_uint32_t _int_route_val; + } __attribute__((packed)); + + Timer *timer(int nr) const + { + return reinterpret_cast((char *)this + 0x100 + 0x20 * nr); + } + + unsigned ioapic_irq(int nr) const + { + return timer(nr)->int_route_cnf(); + } + + void print_state() const; + + l4_uint64_t clk2ns(l4_uint64_t v) const + { return v * counter_clk_period() / 1000000ULL; } + + l4_uint64_t clk2us(l4_uint64_t v) const + { return v * counter_clk_period() / 1000000000ULL; } + + l4_uint64_t us2clk(unsigned us) const + { return us * 1000000000ULL / counter_clk_period(); } + + l4_uint64_t ns2clk(unsigned us) const + { return us * 1000000ULL / counter_clk_period(); } + + l4_uint64_t cap_and_id() const { return _cap_and_id; } + l4_uint64_t conf() const { return _conf; } + +private: + l4_uint64_t _cap_and_id; // 0x0 + l4_uint64_t _pad1; + l4_uint64_t _conf; // 0x10 + l4_uint64_t _pad2; + l4_uint64_t _int_status; // 0x20 + l4_uint64_t _pad3[(0xf0 - 0x28) / sizeof(l4_uint64_t)]; + l4_uint64_t _main_counter; +} __attribute__((packed)); + +}} diff --git a/l4/pkg/drivers-frst/hpet/src/Makefile b/l4/pkg/drivers-frst/hpet/src/Makefile new file mode 100644 index 00000000..30618c77 --- /dev/null +++ b/l4/pkg/drivers-frst/hpet/src/Makefile @@ -0,0 +1,10 @@ +PKGDIR ?= ../.. +L4DIR ?= $(PKGDIR)/../.. + +SRC_CC += hpet.cc +TARGET = libdrivers_hpet.a +PC_FILENAME = libdrivers_hpet + +PRIVATE_INCDIR += $(SRC_DIR)/../include + +include $(L4DIR)/mk/lib.mk diff --git a/l4/pkg/drivers-frst/hpet/src/hpet.cc b/l4/pkg/drivers-frst/hpet/src/hpet.cc new file mode 100644 index 00000000..b855b6e8 --- /dev/null +++ b/l4/pkg/drivers-frst/hpet/src/hpet.cc @@ -0,0 +1,58 @@ +/* + * (c) 2010 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ + +#include + +#include + +void +L4::Driver::Hpet::print_state() const +{ + printf("HPET Information:\n"); + printf("Rev-id: 0x%x\n", rev_id()); + printf("Num timers: %d\n", num_tim_cap()); + printf("Count size: %s\n", count_size_cap() ? "64bit" : "32bit"); + printf("Legacy capable: %s\n", leg_rt_cap() ? "Yes" : "No"); + printf("Legacy enabled: %s\n", leg_rt_cnf() ? "Yes" : "No"); + printf("Vedor ID: 0x%x\n", vendor_id()); + printf("Counter clock period: 0x%x / %u\n", counter_clk_period(), + counter_clk_period()); + printf("Frequency (Hz): %lld\n", 1000000000000000ULL / counter_clk_period()); + + printf("Enabled: %s\n", enabled() ? "Yes" : "No"); + + printf("Main counter value: %lld\n", main_counter_val()); + + printf("Raw values: %16llx %16llx\n", cap_and_id(), conf()); + + + for (unsigned i = 0; i < num_tim_cap(); ++i) + { + printf("HPET Timer-%d Information:\n", i); + timer(i)->print_state(); + } +} + +void +L4::Driver::Hpet::Timer::print_state() const +{ + printf(" Int type: %s\n", is_int_type_level() ? "Level" : "Edge"); + printf(" IRQ enabled: %s\n", is_int_enabled() ? "Yes" : "No"); + printf(" Mode: %s\n", is_periodic() ? "Periodic" : "Non-periodic"); + printf(" Periodic int capable: %s\n", periodic_int_capable() ? "Yes" : "No"); + printf(" Can 64bit: %s\n", can_64bit() ? "Yes" : "No"); + printf(" Forced to 32bit: %s\n", forced_32bit() ? "Yes" : "No"); + printf(" Can FSB/MSI: %s\n", can_fsb() ? "Yes" : "No"); + printf(" Does FSB/MSI: %s\n", is_fsb() ? "Yes" : "No"); + printf(" IRQs available: %x\n", ints_avail()); + printf(" IRQ set: %d\n", int_route_cnf()); + printf(" Comparator value: %lld\n", comparator()); + printf(" Raw values: %16llx %16llx\n", conf_and_cap(), comp()); +} + diff --git a/l4/pkg/drivers-frst/include/Makefile b/l4/pkg/drivers-frst/include/Makefile new file mode 100644 index 00000000..7fba07f7 --- /dev/null +++ b/l4/pkg/drivers-frst/include/Makefile @@ -0,0 +1,6 @@ +PKGDIR = .. +L4DIR ?= $(PKGDIR)/../.. + +PKGNAME = drivers + +include $(L4DIR)/mk/include.mk diff --git a/l4/pkg/drivers-frst/include/io_regblock.h b/l4/pkg/drivers-frst/include/io_regblock.h new file mode 100644 index 00000000..9a81bd2a --- /dev/null +++ b/l4/pkg/drivers-frst/include/io_regblock.h @@ -0,0 +1,204 @@ +/* + * (c) 2012 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ +#pragma once + +#ifndef __GXX_EXPERIMENTAL_CXX0X__ +#ifndef static_assert +#define static_assert(x, y) \ + do { (void)sizeof(char[-(!(x))]); } while (0) +#endif +#endif + +namespace L4 +{ + class Io_register_block + { + public: + /** + * \brief Read register with a byte access. + */ + virtual unsigned char read8(unsigned long reg) const = 0; + + /** + * \brief Read register with a 2 byte access. + */ + virtual unsigned short read16(unsigned long reg) const = 0; + + /** + * \brief Read register with a 4 byte access. + */ + virtual unsigned int read32(unsigned long reg) const = 0; + + /* + * \brief Read register with an 8 byte access. + */ + //virtual unsigned long long read64(unsigned long reg) const = 0; + + /** + * \brief Write register with a byte access. + */ + virtual void write8(unsigned long reg, unsigned char value) const = 0; + + /** + * \brief Write register with a 2 byte access. + */ + virtual void write16(unsigned long reg, unsigned short value) const = 0; + + /** + * \brief Write register with a 4 byte access. + */ + virtual void write32(unsigned long reg, unsigned int value) const = 0; + + /* + * \brief Write register with an 8 byte access. + */ + //virtual void write64(unsigned long reg, unsigned long long value) const = 0; + + /** + * \brief Get address of a register. + */ + virtual unsigned long addr(unsigned long reg) const = 0; + + /** + * \brief A delay. + * + * Note, most likely this function does nothing. + */ + virtual void delay() const = 0; + + virtual ~Io_register_block() = 0; + + /** + * \brief Read register. + * \param reg Register to use. + * \return Value in the register + * + * The access width is defined by the return type. + */ + template< typename R > + R read(unsigned long reg) const + { + switch (sizeof(R)) + { + case 1: return read8(reg); + case 2: return read16(reg); + case 4: return read32(reg); + default: static_assert(sizeof(R) == 1 || sizeof(R) == 2 || sizeof(R) == 4, + "Invalid size"); + }; + } + + /** + * \brief Write register. + * \param reg Register to use. + * \param value Date to write to the register. + * + * The access width is defined by the type of the value + */ + template< typename R > + void write(unsigned long reg, R value) const + { + switch (sizeof(R)) + { + case 1: write8(reg, value); return; + case 2: write16(reg, value); return; + case 4: write32(reg, value); return; + default: static_assert(sizeof(R) == 1 || sizeof(R) == 2 || sizeof(R) == 4, + "Invalid size"); + }; + } + + /** + * \brief Modify register. + * \param reg Register to use. + * \param clear_bits Bits to clear in the register. + * \param set_bits Bits to set in the register. + * \return The written value. + * + * This function is a short form of + * write(reg, (read(reg) & ~clear_bits) | add_bits) + */ + template< typename R > + R modify(unsigned long reg, R clear_bits, R set_bits) + { + R r = (read(reg) & ~clear_bits) | set_bits; + write(reg, r); + return r; + } + + /** + * \brief Set bits in register. + * \param reg Register to use. + * \param set_bits Bits to set in the registers. + * \return The written value. + */ + template< typename R > + R set(unsigned long reg, R set_bits) + { + return modify(reg, 0, set_bits); + } + + /** + * \brief Clear bits in register. + * \param reg Register to use. + * \param clear_bits Bits to clear in the register. + * \return The written value. + */ + template< typename R > + R clear(unsigned long reg, R clear_bits) + { + return modify(reg, clear_bits, 0); + } + + }; + + inline Io_register_block::~Io_register_block() {} + + + class Io_register_block_mmio : public Io_register_block + { + private: + template< typename R > + R _read(unsigned long reg) const + { return *reinterpret_cast(_base + (reg << _shift)); } + + template< typename R > + void _write(unsigned long reg, R val) const + { *reinterpret_cast(_base + (reg << _shift)) = val; } + + public: + Io_register_block_mmio(unsigned long base, unsigned char shift = 0) + : _base(base), _shift(shift) + {} + + unsigned long addr(unsigned long reg) const + { return _base + (reg << _shift); } + + unsigned char read8(unsigned long reg) const + { return _read(reg); } + unsigned short read16(unsigned long reg) const + { return _read(reg); } + unsigned int read32(unsigned long reg) const + { return _read(reg); } + + void write8(unsigned long reg, unsigned char val) const + { _write(reg, val); } + void write16(unsigned long reg, unsigned short val) const + { _write(reg, val); } + void write32(unsigned long reg, unsigned int val) const + { _write(reg, val); } + + void delay() const + {} + + private: + unsigned long _base; + unsigned char _shift; + }; +} diff --git a/l4/pkg/drivers-frst/include/io_regblock_port.h b/l4/pkg/drivers-frst/include/io_regblock_port.h new file mode 100644 index 00000000..62cdeb28 --- /dev/null +++ b/l4/pkg/drivers-frst/include/io_regblock_port.h @@ -0,0 +1,60 @@ +/* + * (c) 2012 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ +#pragma once + +#include "io_regblock.h" + +namespace L4 +{ + class Io_register_block_port : public Io_register_block + { + public: + Io_register_block_port(unsigned long base) + : _base(base) + {} + + unsigned long addr(unsigned long reg) const { return _base + reg; } + + unsigned char read8(unsigned long reg) const + { + unsigned char val; + asm volatile("inb %w1, %b0" : "=a" (val) : "Nd" (_base + reg)); + return val; + } + + unsigned short read16(unsigned long reg) const + { + unsigned short val; + asm volatile("inw %w1, %w0" : "=a" (val) : "Nd" (_base + reg)); + return val; + } + + unsigned int read32(unsigned long reg) const + { + unsigned int val; + asm volatile("in %w1, %0" : "=a" (val) : "Nd" (_base + reg)); + return val; + } + + void write8(unsigned long reg, unsigned char val) const + { asm volatile("outb %b0, %w1" : : "a" (val), "Nd" (_base + reg)); } + + void write16(unsigned long reg, unsigned short val) const + { asm volatile("outw %w0, %w1" : : "a" (val), "Nd" (_base + reg)); } + + void write32(unsigned long reg, unsigned int val) const + { asm volatile("out %0, %w1" : : "a" (val), "Nd" (_base + reg)); } + + void delay() const + { asm volatile ("outb %al,$0x80"); } + + private: + unsigned long _base; + }; +} diff --git a/l4/pkg/drivers-frst/nand/Makefile b/l4/pkg/drivers-frst/nand/Makefile new file mode 100644 index 00000000..5f4fd62b --- /dev/null +++ b/l4/pkg/drivers-frst/nand/Makefile @@ -0,0 +1,8 @@ +PKGDIR ?= .. +L4DIR ?= $(PKGDIR)/../.. + +TARGET := include src + +include $(L4DIR)/mk/subdir.mk + +src: include diff --git a/l4/pkg/drivers-frst/nand/include/Makefile b/l4/pkg/drivers-frst/nand/include/Makefile new file mode 100644 index 00000000..6ade365f --- /dev/null +++ b/l4/pkg/drivers-frst/nand/include/Makefile @@ -0,0 +1,4 @@ +PKGDIR = ../.. +L4DIR ?= $(PKGDIR)/../.. + +include $(L4DIR)/mk/include.mk diff --git a/l4/pkg/drivers-frst/nand/include/lib_nand.h b/l4/pkg/drivers-frst/nand/include/lib_nand.h new file mode 100644 index 00000000..b3f54c79 --- /dev/null +++ b/l4/pkg/drivers-frst/nand/include/lib_nand.h @@ -0,0 +1,36 @@ +#pragma once + +#include +#include "transfer.h" + +class Nand_ctrl; +class Nand +{ +public: + Nand(Nand_ctrl *nand_ctrl); + + int read_page(l4_addr_t page, Transfer &transfer); + int write_page(l4_addr_t page, Transfer &transfer); + int erase(l4_addr_t block); + int handle_irq(); + + long unsigned page_size; + long unsigned spare_size; + long unsigned block_size; + long unsigned num_blocks; + +private: + Nand_ctrl *_nand_ctrl; +}; + +class Nand_drv +{ +public: + virtual int probe(const char *configstr) = 0; + virtual Nand_ctrl *create(l4_umword_t base) = 0; +}; + +struct Nand *arm_nand_probe(const char *configstr, l4_addr_t base); + +void arm_nand_register_driver(Nand_drv *nand_drv); + diff --git a/l4/pkg/drivers-frst/nand/include/transfer.h b/l4/pkg/drivers-frst/nand/include/transfer.h new file mode 100644 index 00000000..f5472508 --- /dev/null +++ b/l4/pkg/drivers-frst/nand/include/transfer.h @@ -0,0 +1,67 @@ +#pragma once + +struct Buffer +{ + Buffer() + : addr(0), size(0) + {} + + Buffer(char *a, unsigned s) + : addr(a), size(s) + {} + + char *addr; + unsigned size; +}; + +struct Transfer +{ + enum + { Max = 4, }; + +#if 0 + struct Elem + { + unsigned char *addr; + unsigned size; + }; +#endif + + Transfer() + : num(0), len(0) + {} + + unsigned num; + unsigned len; + + void clear() + { + num = 0; + len = 0; + } + + void add(char *addr, unsigned size) + { + if (num == Max) + return; + + _elems[num].addr = addr; + _elems[num].size = size; + len += size; + num++; + } + + void add(Buffer buffer) + { + add(buffer.addr, buffer.size); + } + + Buffer &operator [] (int index) + { + //assert(index < Max); + return _elems[index]; + } + +private: + Buffer _elems[Max]; +}; diff --git a/l4/pkg/drivers-frst/nand/src/Makefile b/l4/pkg/drivers-frst/nand/src/Makefile new file mode 100644 index 00000000..acc785bd --- /dev/null +++ b/l4/pkg/drivers-frst/nand/src/Makefile @@ -0,0 +1,12 @@ +PKGDIR ?= ../.. +L4DIR ?= $(PKGDIR)/../.. + +TARGET = libarm_nand.o.a +PC_FILENAME := libdrivers-nand + +SRC_CC := lib_nand.cc nand.cc nand_ids.cc gpmc.cc mpc5121.cc + +PRIVATE_INCDIR := $(SRCDIR) +#CFLAGS += -D__KERNEL__ -DHAVE_NET_DEVICE_OPS + +include $(L4DIR)/mk/lib.mk diff --git a/l4/pkg/drivers-frst/nand/src/common.h b/l4/pkg/drivers-frst/nand/src/common.h new file mode 100644 index 00000000..a2334bf3 --- /dev/null +++ b/l4/pkg/drivers-frst/nand/src/common.h @@ -0,0 +1,15 @@ +#pragma once + +#if 0 +#include "l4/util/util.h" + +inline void udelay(unsigned us) +{ + l4_usleep(us); +} +#else + +// environment using this library needs to supply a udelay function +void udelay(unsigned us); + +#endif diff --git a/l4/pkg/drivers-frst/nand/src/gpmc.cc b/l4/pkg/drivers-frst/nand/src/gpmc.cc new file mode 100644 index 00000000..4bbbfe18 --- /dev/null +++ b/l4/pkg/drivers-frst/nand/src/gpmc.cc @@ -0,0 +1,124 @@ +#include + +#include "l4/drivers-frst/lib_nand.h" + +#include "nand.h" +#include "gpmc.h" + +Gpmc::Gpmc(addr base_addr) + : _reg((Reg *)base_addr) +{ + for (int i = 0; i < Num_cs; ++i) + { + /* Check if NAND type is set */ + if (((_reg->cs[i].config1) & 0xc00) == 0x800) + { + //printf("found NAND chip\n"); + /* Found it!! */ + break; + } + } + + // XXX just scan for one chip + scan(1); + + // disable write protection + u32 config = _reg->config; + config |= 0x10; + _reg->config = config; + + // enable interrupts + _reg->irqstatus = 256; + _reg->irqenable = 256; +} + +void Gpmc::add(Nand_chip *chip) +{ + chip->add_options(Opt_no_padding | Opt_cacheprg | Opt_no_autoincr); + if ((_reg->cs[0].config1 & 0x3000) == 0x1000) + chip->add_options(Opt_buswidth_16); + //chip->delay = 100; + + _chips[0] = chip; +} + +Nand_chip *Gpmc::select(loff_t /*addr*/) +{ + // XXX hack:we currently have only one chip + return _chips[0]; +} + +void Gpmc::wr_cmd(u8 c) +{ *((volatile u8 *)&_reg->cs[0].nand_cmd) = c; } + +void Gpmc::wr_adr(u8 a) +{ *((volatile u8 *)&_reg->cs[0].nand_adr) = a; } + +void Gpmc::wr_dat(u8 d) +{ *((volatile u8 *)&_reg->cs[0].nand_dat) = d; } + +u8 Gpmc::rd_dat() +{ return (u8)(*((volatile u16 *)&_reg->cs[0].nand_dat)); } + +void Gpmc::rd_dat(const u8 *buf, unsigned len) +{ + u16 *p = (u16 *)buf; + len >>= 1; + + for (unsigned i = 0; i < len; i++) + p[i] = *((volatile u16 *)&_reg->cs[0].nand_dat); + +#if 0 + for (int i = 0; i < len; i+=4) + { + p[i] = *((volatile u16 *)&_reg->cs[0].nand_dat); + p[i+1] = *((volatile u16 *)&_reg->cs[0].nand_dat); + p[i+2] = *((volatile u16 *)&_reg->cs[0].nand_dat); + p[i+3] = *((volatile u16 *)&_reg->cs[0].nand_dat); + } +#endif +} + +void Gpmc::wr_dat(const u8 *buf, unsigned len) +{ + u16 *p = (u16 *)buf; + len >>= 1; + + for (unsigned i = 0; i < len; i++) + *((volatile u16 *)&_reg->cs[0].nand_dat) = p[i]; +} + +int Gpmc::handle_irq() +{ + int ret = 0; + u32 v = _reg->irqstatus; + u32 v2 = _reg->irqstatus; + if (v & 256) + { + ret = _chips[0]->handle_irq(); + _reg->irqstatus = 256; + } + else + { + printf("spurious interrupt\n"); + printf("irqstatus:%x %x\n", v, v2); + return -1; + } + + return ret; +} + +class Gpmc_drv : public Nand_drv +{ +public: + Gpmc_drv() + { arm_nand_register_driver(this); } + + int probe(const char *configstr) + { return (strcmp(configstr, "GPMC")) ? 0 : 1; } + + Nand_ctrl *create(addr base) + { return new Gpmc(base); } +}; + +static Gpmc_drv gpmc_drv; diff --git a/l4/pkg/drivers-frst/nand/src/gpmc.h b/l4/pkg/drivers-frst/nand/src/gpmc.h new file mode 100644 index 00000000..fb7c43f5 --- /dev/null +++ b/l4/pkg/drivers-frst/nand/src/gpmc.h @@ -0,0 +1,60 @@ +#pragma once + +#include "nand.h" + + +class Gpmc : public Nand_ctrl +{ + enum + { Num_cs = 8, }; + + struct Reg_cs + { + u32 config1; + u32 config2; + u32 config3; + u32 config4; + u32 config5; + u32 config6; + u32 config7; + volatile u32 nand_cmd; + volatile u32 nand_adr; + volatile u32 nand_dat; + }; + + struct Reg + { + u8 res1[0x10]; + u32 sysconfig; + u8 res2[0x04]; + u32 irqstatus; + u32 irqenable; + u8 res3[0x20]; + u8 timeout_control; + u8 res4[0x0c]; + u32 config; + u32 status; + u8 res5[0x08]; + Reg_cs cs[Num_cs]; + }; + +public: + Gpmc(addr base_addr); + +protected: + void add(Nand_chip *chip); + Nand_chip *select(loff_t addr); + + void wr_cmd(u8 c); + void wr_adr(u8 a); + void wr_dat(u8 d); + u8 rd_dat(); + void rd_dat(const u8 *buf, unsigned len); + void wr_dat(const u8 *buf, unsigned len); + + int handle_irq(); + +private: + volatile Reg *_reg; + Nand_chip *_chips[Num_cs]; +}; diff --git a/l4/pkg/drivers-frst/nand/src/lib_nand.cc b/l4/pkg/drivers-frst/nand/src/lib_nand.cc new file mode 100644 index 00000000..108974ac --- /dev/null +++ b/l4/pkg/drivers-frst/nand/src/lib_nand.cc @@ -0,0 +1,75 @@ +#include +#include "nand.h" + +enum { Max_drivers = 10 }; +static Nand_drv *nand_drv[Max_drivers]; +static int nr_drivers; + +Nand *arm_nand_probe(const char *configstr, l4_umword_t base) +{ + for (int i = 0; i < nr_drivers; i++) + if (nand_drv[i] && nand_drv[i]->probe(configstr)) + return new Nand(nand_drv[i]->create(base)); + + return 0; +} + +void arm_nand_register_driver(Nand_drv *drv) +{ + if (nr_drivers < Max_drivers) + nand_drv[nr_drivers++] = drv; +} + +Nand::Nand(Nand_ctrl *nand_ctrl) + : _nand_ctrl(nand_ctrl) +{ + page_size = nand_ctrl->sz_write; + spare_size = nand_ctrl->sz_spare; + block_size = nand_ctrl->sz_erase; + num_blocks = nand_ctrl->size / nand_ctrl->sz_erase; +} + +int Nand::read_page(l4_addr_t page, Transfer &transfer) +{ + if (!_nand_ctrl) + return -1; + + static Read_op op; + op.addr = page * _nand_ctrl->sz_write; + op.transfer = &transfer; + + return _nand_ctrl->read(&op); +} + +int Nand::write_page(l4_addr_t page, Transfer &transfer) +{ + if (!_nand_ctrl) + return -1; + + static Write_op op; + op.addr = page * _nand_ctrl->sz_write; + op.transfer = &transfer; + + return _nand_ctrl->write(&op); +} + +int Nand::erase(l4_addr_t block) +{ + if (!_nand_ctrl) + return -1; + + static Erase_op op; + op.addr = block * _nand_ctrl->sz_erase; + op.len = _nand_ctrl->sz_erase; + + _nand_ctrl->erase(&op); + return 0; +} + +int Nand::handle_irq() +{ + if (!_nand_ctrl) + return -1; + + return _nand_ctrl->handle_irq(); +} diff --git a/l4/pkg/drivers-frst/nand/src/mpc5121.cc b/l4/pkg/drivers-frst/nand/src/mpc5121.cc new file mode 100644 index 00000000..78aba59c --- /dev/null +++ b/l4/pkg/drivers-frst/nand/src/mpc5121.cc @@ -0,0 +1,326 @@ +#include +#include + +#include "l4/drivers-frst/lib_nand.h" + +#include "common.h" +#include "nand.h" +#include "mpc5121.h" + +Mpc5121::Mpc5121(addr base_addr) + : _reg((Reg *)(base_addr + 0x1e00)), + _buffer_main((u32 *)base_addr), _buffer_spare((u32 *)(base_addr + 0x1000)) +{ + // reset controller + _reg->nand_flash_config1 |= 0x40; + unsigned num_us_reset = 0; + while (_reg->nand_flash_config1 & 0x40) + { + if (num_us_reset++ >= Max_us_reset) + { + printf("[Mpc5121] Timeout while resetting controller!\n"); + return; + } + + udelay(1); + } + + // unlock buffer memory + _reg->nfc_configuration = 0x2; + + // disable write protection + _reg->unlock_start_blk_add0 = 0x0000; + _reg->unlock_end_blk_add0 = 0xffff; + _reg->nf_wr_prot = 0x4; + + // mask and configure interrupts only after full page transfer + _reg->nand_flash_config1 = 0x810; + + // detect NAND chips + if (scan(1)) + { + printf(": NAND Flash not found !\n"); + return; + } + + // set spare area size + _reg->spas = sz_spare >> 1; + + // set erase block size + switch (sz_erase / sz_write) + { + case 32: + _reg->nand_flash_config1 |= 0x000; + break; + + case 64: + _reg->nand_flash_config1 |= 0x200; + break; + + case 128: + _reg->nand_flash_config1 |= 0x400; + break; + + case 256: + _reg->nand_flash_config1 |= 0x600; + break; + + default: + printf("[Mpc5121] Unsupported NAND flash chip!\n"); + } + + return; +} + +void Mpc5121::add(Nand_chip *chip) +{ + chip->add_options(Opt_no_autoincr); + _chips[0] = chip; +} + +Nand_chip *Mpc5121::select(loff_t /*addr*/) +{ + return _chips[0]; +} + +void Mpc5121::wr_cmd(u8 c) +{ + switch (c) + { + case Cmd_pageprog: + _start_write(); + _enable_irq(); + break; + + case Cmd_erase2: + _enable_irq(); + break; + + default: + break; + } + + _reg->nand_flash_cmd = c; + _reg->nand_flash_config2 = 0x1; + + // wait for completion + if ((c != Cmd_pageprog) && (c != Cmd_erase2)) + // XXX udelay + while (_reg->nand_flash_config2 & 0x1) ; + + switch (c) + { + case Cmd_status: + _get_status(); + break; + + case Cmd_readstart: + _start_read(); + break; + + case Cmd_seqin: + _buffer_ptr = 0; + break; + + default: + break; + } +} + +void Mpc5121::wr_adr(u8 a) +{ + _reg->nand_flash_addr = a; + _reg->nand_flash_config2 = 0x2; + + // XXX udelay + while (_reg->nand_flash_config2 & 0x2) ; +} + +void Mpc5121::wr_dat(u8 d) +{ _buffer_main[0] = d; } + +u8 Mpc5121::rd_dat() +{ return _buffer_main[0]; } + +void Mpc5121::rd_dat(const u8 *buf, unsigned len) +{ + while (len && (_buffer_ptr < (sz_write + sz_spare))) + { + if (_buffer_ptr < sz_write) + { + int l = len < sz_write ? len : sz_write; + _copy_from_data((u8 *)buf, l); + _buffer_ptr += l; + len -= l; + } + else if (_buffer_ptr < (sz_write + sz_spare)) + { + int l = len < sz_spare ? len : sz_spare; + _copy_from_spare((u8 *)buf, l); + _buffer_ptr += l; + len -= l; + } + } + +} + +void Mpc5121::wr_dat(const u8 *buf, unsigned len) +{ + while (len && (_buffer_ptr < (sz_write + sz_spare))) + { + if (_buffer_ptr < sz_write) + { + int l = len < sz_write ? len : sz_write; + _copy_to_data(buf, l); + _buffer_ptr += l; + len -= l; + } + else if (_buffer_ptr < (sz_write + sz_spare)) + { + int l = len < sz_spare ? len : sz_spare; + _copy_to_spare(buf, l); + _buffer_ptr += l; + len -= l; + } + } + + unsigned sum = 0; + for (int i = 0; i < 4096/4; i++) + sum += _buffer_main[i]; + printf("buffer sum:%d\n", sum); +} + +static void spare_copy(u32 *dst, const u32 *src, int len) +{ + for (int i = 0; i < (len/4); ++i) + dst[i] = src[i]; + + switch (len % 4) + { + case 1: + dst[len/4] = (dst[len/4] & 0xffffff00) | (src[len/4] & 0xff); + break; + + case 2: + dst[len/4] = (dst[len/4] & 0xffff0000) | (src[len/4] & 0xffff); + break; + + case 3: + dst[len/4] = (dst[len/4] & 0xff000000) | (src[len/4] & 0xffffff); + break; + + default: + break; + } +} + +void Mpc5121::_copy_from_data(u8 *buf, int len) +{ + u32 *p = (u32 *)buf; + len >>= 2; + + for (int i = 0; i < len; i++) + p[i] = _buffer_main[i]; +} + +void Mpc5121::_copy_to_data(const u8 *buf, int len) +{ + u32 *p = (u32 *)buf; + len >>= 2; + + for (int i = 0; i < len; i++) + _buffer_main[i] = p[i]; +} + +void Mpc5121::_copy_from_spare(u8 *buf, int len) +{ + int section_len = (sz_spare / (sz_write >> 9) >> 1) << 1; + + unsigned i = 0; + for (i = 0; i < (sz_write >> 9) - 1; ++i) + spare_copy((u32 *)&buf[i * Spare_section_len], &_buffer_spare[(i * Spare_section_len)/4], section_len); + spare_copy((u32 *)&buf[i * Spare_section_len], &_buffer_spare[(i * Spare_section_len)/4], len - i * section_len); +} + +void Mpc5121::_copy_to_spare(const u8 *buf, int len) +{ + int section_len = (sz_spare / (sz_write >> 9) >> 1) << 1; + + unsigned i = 0; + for (i = 0; i < (sz_write >> 9) - 1; ++i) + spare_copy(&_buffer_spare[i * Spare_section_len/4], (u32 *)&buf[i * Spare_section_len], section_len); + spare_copy(&_buffer_spare[i * Spare_section_len/4], (u32 *)&buf[i * Spare_section_len], len - i * section_len); +} + +void Mpc5121::_get_status() +{ + _reg->nand_flash_config2 = 0x20; + while (_reg->nand_flash_config2 & 0x20) ; +} + +int Mpc5121::get_id(char id[4]) +{ + wr_cmd(Cmd_readid); + wr_adr(0x00); + + // transfer data + _reg->nand_flash_config2 = 0x10; + while (_reg->nand_flash_config2 & 0x10) ; + + id[0] = _buffer_main[0]; + id[1] = _buffer_main[0] >> 8; + id[2] = _buffer_main[1]; + id[3] = _buffer_main[1] >> 8; + + return 0; +} + +void Mpc5121::_start_read() +{ + // clear interrupt status + _reg->nand_flash_config2 = 0x0; + // unmask interrupt + _reg->nand_flash_config1 &= ~0x10; + // start data transfer + _reg->nand_flash_config2 = 0x8; + // reset buffer ptr + _buffer_ptr = 0; +} + +void Mpc5121::_start_write() +{ + // transfer data to chip + _reg->nand_flash_config2 = 0x4; + while (_reg->nand_flash_config2 & 0x4) ; +} + +void Mpc5121::_enable_irq() +{ + // clear interrupt status + _reg->nand_flash_config2 = 0x0; + // unmask interrupt + _reg->nand_flash_config1 &= ~0x10; +} + +int Mpc5121::handle_irq() +{ + // mask interrupt + _reg->nand_flash_config1 |= 0x10; + _chips[0]->handle_irq(); + return 0; +} + +class Mpc5121_drv : public Nand_drv +{ +public: + Mpc5121_drv() + { arm_nand_register_driver(this); } + + int probe(const char *configstr) + { return (strcmp(configstr, "MPC5121")) ? 0 : 1; } + + Nand_ctrl *create(addr base) + { return new Mpc5121(base); } +}; + +static Mpc5121_drv mpc5121_drv; diff --git a/l4/pkg/drivers-frst/nand/src/mpc5121.h b/l4/pkg/drivers-frst/nand/src/mpc5121.h new file mode 100644 index 00000000..0715b3c3 --- /dev/null +++ b/l4/pkg/drivers-frst/nand/src/mpc5121.h @@ -0,0 +1,76 @@ +#pragma once + +#include "nand.h" + +class Mpc5121 : public Nand_ctrl +{ + enum + { Max_cs = 4, }; + enum + { Max_us_reset = 100, }; + enum + { Spare_section_len = 64, }; + + struct Reg + { + u16 _res1[2]; + u16 ram_buffer_addr; + u16 nand_flash_addr; + u16 nand_flash_cmd; + u16 nfc_configuration; + u16 ecc_status_result1; + u16 ecc_status_result2; + u16 spas; + u16 nf_wr_prot; + u16 _res2[2]; + u16 nand_flash_wr_pr_st; + u16 nand_flash_config1; + u16 nand_flash_config2; + u16 _res3; + u16 unlock_start_blk_add0; + u16 unlock_end_blk_add0; + u16 unlock_start_blk_add1; + u16 unlock_end_blk_add1; + u16 unlock_start_blk_add2; + u16 unlock_end_blk_add2; + u16 unlock_start_blk_add3; + u16 unlock_end_blk_add3; + }; + +public: + Mpc5121(addr base_addr); + +protected: + void add(Nand_chip *chip); + Nand_chip *select(loff_t addr); + + void wr_cmd(u8 c); + void wr_adr(u8 a); + void wr_dat(u8 d); + u8 rd_dat(); + void rd_dat(const u8 *buf, unsigned len); + void wr_dat(const u8 *buf, unsigned len); + + int handle_irq(); + + int get_id(char id[4]); + +private: + void _get_status(); + void _start_read(); + void _start_write(); + + void _enable_irq(); + + void _copy_from_data(u8 *buf, int len); + void _copy_to_data(const u8 *buf, int len); + void _copy_from_spare(u8 *buf, int len); + void _copy_to_spare(const u8 *buf, int len); + + volatile Reg *_reg; + Nand_chip *_chips[Max_cs]; + + volatile u32 *_buffer_main; + u32 *_buffer_spare; + u32 _buffer_ptr; +}; diff --git a/l4/pkg/drivers-frst/nand/src/nand.cc b/l4/pkg/drivers-frst/nand/src/nand.cc new file mode 100644 index 00000000..3f8f5772 --- /dev/null +++ b/l4/pkg/drivers-frst/nand/src/nand.cc @@ -0,0 +1,316 @@ +#include +#include +#include +#include + +#include "common.h" +#include "nand.h" + +Nand_chip::Nand_chip(Nand_ctrl *ctrl, Dev_desc *dev, Mfr_desc *mfr, int ext_id) + : _state(Ready), _ongoing_op(0), _ctrl(ctrl), _dev(dev), _mfr(mfr) +{ + /* New devices have all the information in additional id bytes */ + if (!dev->sz_page) + { + /* The 3rd id byte holds MLC / multichip data */ + _sz_write = 1024 << (ext_id & 0x3); + ext_id >>= 2; + _sz_spare = (8 << (ext_id & 0x01)) * (_sz_write >> 9); + ext_id >>= 2; + _sz_erase = (64 * 1024) << (ext_id & 0x03); + ext_id >>= 2; + _bus_width = (ext_id & 0x01) ? Opt_buswidth_16 : 0; + } + /* Old devices have chip data hardcoded in the device id table */ + else + { + _sz_write = dev->sz_page; + _sz_spare = dev->sz_spare ? dev->sz_spare : _sz_write / 32; + _sz_erase = dev->sz_erase; + _bus_width = dev->options & Opt_buswidth_16; + } + _sz_chip = (long long unsigned)dev->sz_chip << 20; + + if (_bus_width != (_options & Opt_buswidth_16)) + { + printf("NAND bus width %d instead %d bit\n", + (_options & Opt_buswidth_16) ? 16 : 8, _bus_width ? 16 : 8); + } + + _options |= dev->options; + _options |= Opt_no_autoincr; + + printf("NAND chip: Mfr ID: 0x%02x(%s), Device ID: 0x%02x(%s)\n", + mfr->id, mfr->name, dev->id, dev->name); +} + +int Nand_chip::handle_irq() +{ + switch (_state) + { + case Reading: + return _ctrl->done_read(static_cast(_ongoing_op)); + break; + + case Writing: + return _ctrl->done_write(static_cast(_ongoing_op)); + break; + + case Erasing: + return _ctrl->done_erase(static_cast(_ongoing_op)); + break; + + default: + _state = Ready; + break; + } + return 0; +} + +bool Nand_ctrl::is_wp() +{ + wr_cmd(Cmd_status); + return (rd_dat() & Status_wp) ? false : true; +} + +int Nand_ctrl::get_status() +{ + wr_cmd(Cmd_status); + return rd_dat(); +} + +int Nand_ctrl::read(Read_op *op) +{ + Nand_chip *chip = select(op->addr); + + if (!op->transfer->len) + return -EINVAL; + + u16 col = op->addr & (chip->sz_write() - 1); + u32 row = (op->addr >> chip->page_shift()) & chip->page_mask(); + + assert(!col); + assert(op->transfer->len + col <= (chip->sz_write() + chip->sz_spare())); + + wr_cmd(Cmd_read0); + wr_adr(col); + wr_adr(col >> 8); + wr_adr(row); + wr_adr(row >> 8); + wr_adr(row >> 16); + wr_cmd(Cmd_readstart); + + chip->set_state(Nand_chip::Reading, op); + + return 0; +} + +int Nand_ctrl::done_read(Read_op *op) +{ + Nand_chip *chip = select(op->addr); + assert(chip->state() == Nand_chip::Reading); + + for (unsigned i = 0; i < op->transfer->num; ++i) + rd_dat((u8 *)(*op->transfer)[i].addr, (*op->transfer)[i].size); + + chip->set_state(Nand_chip::Ready); + return 0; +} + +int Nand_ctrl::write(Write_op *op) +{ + Nand_chip *chip = select(op->addr); + + if (!op->transfer->len) + return -EINVAL; + + // check end of device + if ((op->addr + op->transfer->len) > size) + return -EINVAL; + + // check page aligning + if (!aligned(op->addr)) + { + printf("NAND: Attempt to write not page aligned data\n"); + return -EINVAL; + } + + if (is_wp()) + { + printf("NAND: Device is write protected\n"); + return -EIO; + } + + u32 page = (op->addr >> chip->page_shift()) & chip->page_mask(); + + wr_cmd(Cmd_seqin); + wr_adr(0x00); + wr_adr(0x00); + wr_adr(page); + wr_adr(page >> 8); + wr_adr(page >> 16); + + for (unsigned i = 0; i < op->transfer->num; ++i) + wr_dat((u8 *)(*op->transfer)[i].addr, (*op->transfer)[i].size); + + wr_cmd(Cmd_pageprog); + chip->set_state(Nand_chip::Writing, op); + + return 0; +} + +int Nand_ctrl::done_write(Write_op *op) +{ + Nand_chip *chip = select(op->addr); + assert(chip->state() == Nand_chip::Writing); + chip->set_state(Nand_chip::Ready); + return (get_status() & Status_fail) ? -EIO : 0; +} + +int Nand_ctrl::erase(Erase_op *op) +{ + Nand_chip *chip = select(op->addr); + +#if 0 + printf("nand: erase: start = 0x%08x, len = %u\n", + (unsigned int) op->addr, op->len); +#endif + + /* address must align on block boundary */ + if (op->addr & chip->erase_mask()) + { + printf("nand: erase: Unaligned address\n"); + return -EINVAL; + } + + /* length must align on block boundary */ + if (op->len & chip->erase_mask()) + { + printf("nand: erase: Length not block aligned\n"); + return -EINVAL; + } + + /* Do not allow erase past end of device */ + if ((op->len + op->addr) > size) + { + printf("nand: erase: Erase past end of device\n"); + return -EINVAL; + } + + /* Check, if it is write protected */ + if (is_wp()) + { + printf("nand_erase: Device is write protected!!!\n"); + return -EIO; + } + + int page = op->addr >> chip->page_shift(); + + wr_cmd(Cmd_erase1); + wr_adr(page); + wr_adr(page >> 8); + wr_adr(page >> 16); + wr_cmd(Cmd_erase2); + + chip->set_state(Nand_chip::Erasing, op); + + return 0; +} + +int Nand_ctrl::done_erase(Erase_op *op) +{ + Nand_chip *chip = select(op->addr); + assert(chip->state() == Nand_chip::Erasing); + chip->set_state(Nand_chip::Ready); + return (get_status() & Status_fail) ? -EIO : 0; +} + +int Nand_ctrl::get_id(char id[4]) +{ + wr_cmd(Cmd_readid); + wr_adr(0x00); + wr_dat(0xff); + + id[0] = rd_dat(); + id[1] = rd_dat(); + id[2] = rd_dat(); + id[3] = rd_dat(); + + return 0; +} + +int Nand_ctrl::scan(int maxchips) +{ + for (int i = 0; i < maxchips; ++i) + { + wr_cmd(Cmd_reset); + udelay(100); + wr_cmd(Cmd_status); + while (!(rd_dat() & Status_ready)); + + char id1[4], id2[4]; + get_id(id1); + get_id(id2); + + if (id1[0] != id2[0] || id1[1] != id2[1]) + { + printf("manufacturer or device id corrupt:\n"); + printf("mfr-id1:%02x mfr-id2:%02x\n", id1[0], id2[0]); + printf("dev-id1:%02x dev-id2:%02x\n", id1[1], id2[1]); + return -1; + } + + /* identify manufacturer */ + Mfr_desc *mfr = 0; + for (int j = 0; _mfr_ids[j].id != 0; j++) + { + if (id1[0] == _mfr_ids[j].id) + { + mfr = &_mfr_ids[j]; + break; + } + } + + /* identify device */ + Dev_desc *dev = 0; + for (int j = 0; _dev_ids[j].name != 0; j++) + { + if (id1[1] == _dev_ids[j].id) + { + dev = &_dev_ids[j]; + break; + } + } + + if (!dev) + { + printf("no device device found\n"); + continue; + } + if (!mfr) + { + printf("no manufacturer found\n"); + continue; + } + + Nand_chip *chip = new Nand_chip(this, dev, mfr, id1[3]); + add(chip); + + // XXX all chips should have the same features + sz_write = chip->sz_write(); + sz_spare = chip->sz_spare(); + sz_erase = chip->sz_erase(); + + size += chip->sz_chip(); + numchips++; + } + + //printf("%d NAND chips detected\n", numchips); + + return 0; +} + +Nand_ctrl::Nand_ctrl() + : size(0) +{} + diff --git a/l4/pkg/drivers-frst/nand/src/nand.h b/l4/pkg/drivers-frst/nand/src/nand.h new file mode 100644 index 00000000..d1d37b38 --- /dev/null +++ b/l4/pkg/drivers-frst/nand/src/nand.h @@ -0,0 +1,205 @@ +#pragma once + +#include + +#include "types.h" +#include + +struct Op +{}; + +struct Read_op : Op +{ + u32 addr; + Transfer *transfer; +}; + +struct Write_op : Op +{ + u32 addr; + Transfer *transfer; +}; + +struct Erase_op : Op +{ + u32 addr; + u32 len; + u_char state; +}; + + +struct Dev_desc +{ + int id; + const char *name; + unsigned long sz_page; // bytes + unsigned long sz_spare; // bytes + unsigned long sz_chip; // MiB + unsigned long sz_erase; // bytes + unsigned long options; +}; + +struct Mfr_desc +{ + int id; + const char *name; +}; + +extern Dev_desc _dev_ids[]; +extern Mfr_desc _mfr_ids[]; + +enum +{ + Opt_no_autoincr = 0x001, + Opt_buswidth_16 = 0x002, + Opt_no_padding = 0x004, + Opt_cacheprg = 0x008, + Opt_copyback = 0x010, + Opt_is_and = 0x020, + Opt_4page_array = 0x040, + /* Chip does not require ready check on read. True + * for all large page devices, as they do not support autoincrement.*/ + Opt_no_readrdy = 0x100, + Opt_no_subpage_write = 0x200, +}; + + +class Nand_ctrl; +class Nand_chip +{ +public: + enum State + { + Ready, + Reading, + Writing, + Erasing, + Cachedprg, + }; + + Nand_chip(Nand_ctrl *ctrl, Dev_desc *dev, Mfr_desc *mfr, int ext_id = 0); + + State state() {return _state; } + void set_state(State state) { _state = state; } + void set_state(State state, Op *op) + { + _state = state; + _ongoing_op = op; + } + + u32 sz_write() const + { return _sz_write; } + u32 sz_spare() const + { return _sz_spare; } + u32 sz_erase() const + { return _sz_erase; } + u64 sz_chip() const + { return _sz_chip; } + void add_options(int options) + { _options |= options; } + + int page_shift() { return ffs(_sz_write) - 1; } + int page_mask() { return (sz_chip() >> page_shift()) - 1; } + int erase_shift() { return ffs(_sz_erase) - 1; } + int erase_mask() { return (sz_chip() >> erase_shift()) - 1; } + + int handle_irq(); + +protected: + u32 _sz_write; + u32 _sz_spare; + u32 _sz_erase; + u64 _sz_chip; + + int _bus_width; + int _delay; + int _options; + +private: + State _state; + Op *_ongoing_op; + + Nand_ctrl *_ctrl; + Dev_desc *_dev; + Mfr_desc *_mfr; +}; + +class Nand_ctrl +{ +protected: + // commands + enum + { + // standard device commands + Cmd_read0 = 0x00, + Cmd_read1 = 0x01, + Cmd_rndout = 0x05, + Cmd_pageprog = 0x10, + Cmd_readoob = 0x50, + Cmd_erase1 = 0x60, + Cmd_status = 0x70, + Cmd_seqin = 0x80, + Cmd_rndin = 0x85, + Cmd_readid = 0x90, + Cmd_erase2 = 0xd0, + Cmd_reset = 0xff, + + // large page device commands + Cmd_readstart = 0x30, + Cmd_rndoutstart = 0xe0, + Cmd_cachedprog = 0x15, + }; + + /* status bits */ + enum + { + Status_fail = 0x01, + Status_fail_n1 = 0x02, + Status_true_ready = 0x20, + Status_ready = 0x40, + Status_wp = 0x80, + }; + +public: + Nand_ctrl(); + + int read(Read_op *op); + int write(Write_op *op); + int erase(Erase_op *op); + + int done_read(Read_op *op); + int done_write(Write_op *op); + int done_erase(Erase_op *op); + + virtual int handle_irq() = 0; + +protected: + int scan(int maxchips); + + virtual void add(Nand_chip *chip) = 0; + virtual Nand_chip *select(loff_t addr) = 0; + + virtual void wr_cmd(u8 c) = 0; + virtual void wr_adr(u8 a) = 0; + virtual void wr_dat(u8 d) = 0; + + bool aligned(u32 addr) const + { return !(addr & (sz_write - 1)); } + + virtual u8 rd_dat() = 0; + virtual void rd_dat(const u8 *buf, unsigned len) = 0; + virtual void wr_dat(const u8 *buf, unsigned len) = 0; + + bool is_wp(); + int get_status(); + virtual int get_id(char id[4]); + +public: + const char *name; + unsigned numchips; + u64 size; + u32 sz_erase; + u32 sz_write; + u32 sz_spare; +}; + diff --git a/l4/pkg/drivers-frst/nand/src/nand_ids.cc b/l4/pkg/drivers-frst/nand/src/nand_ids.cc new file mode 100644 index 00000000..2b910ffc --- /dev/null +++ b/l4/pkg/drivers-frst/nand/src/nand_ids.cc @@ -0,0 +1,115 @@ +#include "common.h" +#include "nand.h" + +/* +* Chip ID list +* +* Id, name, page size, spare size, chip size in MegaByte, erase block size, options +*/ +struct Dev_desc _dev_ids[] = +{ + {0x6e, "NAND 1MiB 5V 8-bit", 256, 0, 1, 0x1000, 0}, + {0x64, "NAND 2MiB 5V 8-bit", 256, 0, 2, 0x1000, 0}, + {0x6b, "NAND 4MiB 5V 8-bit", 512, 0, 4, 0x2000, 0}, + {0xe8, "NAND 1MiB 3,3V 8-bit", 256, 0, 1, 0x1000, 0}, + {0xec, "NAND 1MiB 3,3V 8-bit", 256, 0, 1, 0x1000, 0}, + {0xea, "NAND 2MiB 3,3V 8-bit", 256, 0, 2, 0x1000, 0}, + {0xd5, "NAND 4MiB 3,3V 8-bit", 512, 0, 4, 0x2000, 0}, + {0xe3, "NAND 4MiB 3,3V 8-bit", 512, 0, 4, 0x2000, 0}, + {0xe5, "NAND 4MiB 3,3V 8-bit", 512, 0, 4, 0x2000, 0}, + {0xd6, "NAND 8MiB 3,3V 8-bit", 512, 0, 8, 0x2000, 0}, + + {0x39, "NAND 8MiB 1,8V 8-bit", 512, 0, 8, 0x2000, 0}, + {0xe6, "NAND 8MiB 3,3V 8-bit", 512, 0, 8, 0x2000, 0}, + {0x49, "NAND 8MiB 1,8V 16-bit", 512, 0, 8, 0x2000, Opt_buswidth_16}, + {0x59, "NAND 8MiB 3,3V 16-bit", 512, 0, 8, 0x2000, Opt_buswidth_16}, + + {0x33, "NAND 16MiB 1,8V 8-bit", 512, 0, 16, 0x4000, 0}, + {0x73, "NAND 16MiB 3,3V 8-bit", 512, 0, 16, 0x4000, 0}, + {0x43, "NAND 16MiB 1,8V 16-bit", 512, 0, 16, 0x4000, Opt_buswidth_16}, + {0x53, "NAND 16MiB 3,3V 16-bit", 512, 0, 16, 0x4000, Opt_buswidth_16}, + + {0x35, "NAND 32MiB 1,8V 8-bit", 512, 0, 32, 0x4000, 0}, + {0x75, "NAND 32MiB 3,3V 8-bit", 512, 0, 32, 0x4000, 0}, + {0x45, "NAND 32MiB 1,8V 16-bit", 512, 0, 32, 0x4000, Opt_buswidth_16}, + {0x55, "NAND 32MiB 3,3V 16-bit", 512, 0, 32, 0x4000, Opt_buswidth_16}, + + {0x36, "NAND 64MiB 1,8V 8-bit", 512, 0, 64, 0x4000, 0}, + {0x76, "NAND 64MiB 3,3V 8-bit", 512, 0, 64, 0x4000, 0}, + {0x46, "NAND 64MiB 1,8V 16-bit", 512, 0, 64, 0x4000, Opt_buswidth_16}, + {0x56, "NAND 64MiB 3,3V 16-bit", 512, 0, 64, 0x4000, Opt_buswidth_16}, + + {0x78, "NAND 128MiB 1,8V 8-bit", 512, 0, 128, 0x4000, 0}, + {0x39, "NAND 128MiB 1,8V 8-bit", 512, 0, 128, 0x4000, 0}, + {0x79, "NAND 128MiB 3,3V 8-bit", 512, 0, 128, 0x4000, 0}, + {0x72, "NAND 128MiB 1,8V 16-bit", 512, 0, 128, 0x4000, Opt_buswidth_16}, + {0x49, "NAND 128MiB 1,8V 16-bit", 512, 0, 128, 0x4000, Opt_buswidth_16}, + {0x74, "NAND 128MiB 3,3V 16-bit", 512, 0, 128, 0x4000, Opt_buswidth_16}, + {0x59, "NAND 128MiB 3,3V 16-bit", 512, 0, 128, 0x4000, Opt_buswidth_16}, + + {0x71, "NAND 256MiB 3,3V 8-bit", 512, 0, 256, 0x4000, 0}, + + /* + * These are the new chips with large page size. The pagesize and the + * erasesize is determined from the extended id bytes + */ +#define LP_OPTIONS (Opt_no_readrdy | Opt_no_autoincr) +#define LP_OPTIONS16 (LP_OPTIONS | Opt_buswidth_16) + + /*512 Megabit */ + {0xA2, "NAND 64MiB 1,8V 8-bit", 0, 0, 64, 0, LP_OPTIONS}, + {0xF2, "NAND 64MiB 3,3V 8-bit", 0, 0, 64, 0, LP_OPTIONS}, + {0xB2, "NAND 64MiB 1,8V 16-bit", 0, 0, 64, 0, LP_OPTIONS16}, + {0xC2, "NAND 64MiB 3,3V 16-bit", 0, 0, 64, 0, LP_OPTIONS16}, + + /* 1 Gigabit */ + {0xA1, "NAND 128MiB 1,8V 8-bit", 0, 0, 128, 0, LP_OPTIONS}, + {0xF1, "NAND 128MiB 3,3V 8-bit", 0, 0, 128, 0, LP_OPTIONS}, + {0xB1, "NAND 128MiB 1,8V 16-bit", 0, 0, 128, 0, LP_OPTIONS16}, + {0xC1, "NAND 128MiB 3,3V 16-bit", 0, 0, 128, 0, LP_OPTIONS16}, + + /* 2 Gigabit */ + {0xAA, "NAND 256MiB 1,8V 8-bit", 0, 0, 256, 0, LP_OPTIONS}, + {0xDA, "NAND 256MiB 3,3V 8-bit", 0, 0, 256, 0, LP_OPTIONS}, + {0xBA, "NAND 256MiB 1,8V 16-bit", 0, 0, 256, 0, LP_OPTIONS16}, + {0xCA, "NAND 256MiB 3,3V 16-bit", 0, 0, 256, 0, LP_OPTIONS16}, + + /* 4 Gigabit */ + {0xAC, "NAND 512MiB 1,8V 8-bit", 0, 0, 512, 0, LP_OPTIONS}, + {0xDC, "NAND 512MiB 3,3V 8-bit", 0, 0, 512, 0, LP_OPTIONS}, + {0xBC, "NAND 512MiB 1,8V 16-bit", 0, 0, 512, 0, LP_OPTIONS16}, + {0xCC, "NAND 512MiB 3,3V 16-bit", 0, 0, 512, 0, LP_OPTIONS16}, + + /* 8 Gigabit */ + {0xA3, "NAND 1GiB 1,8V 8-bit", 0, 0, 1024, 0, LP_OPTIONS}, + {0xD3, "NAND 1GiB 3,3V 8-bit", 0, 0, 1024, 0, LP_OPTIONS}, + {0xB3, "NAND 1GiB 1,8V 16-bit", 0, 0, 1024, 0, LP_OPTIONS16}, + {0xC3, "NAND 1GiB 3,3V 16-bit", 0, 0, 1024, 0, LP_OPTIONS16}, + + /* 16 Gigabit */ + {0xA5, "NAND 2GiB 1,8V 8-bit", 0, 0, 2048, 0, LP_OPTIONS}, + {0xD5, "NAND 2GiB 3,3V 8-bit", 0, 0, 2048, 0, LP_OPTIONS}, + {0xB5, "NAND 2GiB 1,8V 16-bit", 0, 0, 2048, 0, LP_OPTIONS16}, + {0xC5, "NAND 2GiB 3,3V 16-bit", 0, 0, 2048, 0, LP_OPTIONS16}, + + {0xD7, "NAND 4GiB ?V 16-bit", 4096, 218, 4096, 0x80000, LP_OPTIONS16}, + + {0, 0, 0, 0, 0, 0, 0} +}; + +/* +* Manufacturer ID list +*/ +struct Mfr_desc _mfr_ids[] = +{ + {0x01, "AMD"}, + {0x04, "Fujitsu"}, + {0x07, "Renesas"}, + {0x20, "ST Micro"}, + {0x2c, "Micron"}, + {0x84, "National"}, + {0x98, "Toshiba"}, + {0xad, "Hynix"}, + {0xec, "Samsung"}, + {0x00, "Unknown"}, +}; diff --git a/l4/pkg/drivers-frst/nand/src/types.h b/l4/pkg/drivers-frst/nand/src/types.h new file mode 100644 index 00000000..e7c7451e --- /dev/null +++ b/l4/pkg/drivers-frst/nand/src/types.h @@ -0,0 +1,15 @@ +#pragma once + +#include "sys/types.h" + +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned int u32; +typedef unsigned long long u64; + +typedef signed char s8; +typedef signed short s16; +typedef signed int s32; +typedef signed long long s64; + +typedef long unsigned addr; diff --git a/l4/pkg/drivers-frst/of/Makefile b/l4/pkg/drivers-frst/of/Makefile new file mode 100644 index 00000000..b9d0af1b --- /dev/null +++ b/l4/pkg/drivers-frst/of/Makefile @@ -0,0 +1,8 @@ +PKGDIR = .. +L4DIR ?= $(PKGDIR)/../.. + +TARGET = include src + +include $(L4DIR)/mk/subdir.mk + +src: include diff --git a/l4/pkg/drivers-frst/of/include/Makefile b/l4/pkg/drivers-frst/of/include/Makefile new file mode 100644 index 00000000..e77a52bf --- /dev/null +++ b/l4/pkg/drivers-frst/of/include/Makefile @@ -0,0 +1,6 @@ +PKGDIR = ../.. +L4DIR ?= $(PKGDIR)/../.. + +PKGNAME = drivers + +include $(L4DIR)/mk/include.mk diff --git a/l4/pkg/drivers-frst/of/include/of.h b/l4/pkg/drivers-frst/of/include/of.h new file mode 100644 index 00000000..b7233917 --- /dev/null +++ b/l4/pkg/drivers-frst/of/include/of.h @@ -0,0 +1,117 @@ +#ifndef L4_PPC32_OF_H__ +#define L4_PPC32_OF_H__ + +#include +#include + +namespace L4_drivers +{ +class Of +{ +private: + /* declarations */ + struct prom_args + { + const char *service; + int nargs; + int nret; + void *args[10]; + prom_args(const char *s, int na, int nr) : service(s), nargs(na), nret(nr) {} + }; + + typedef int (*prom_entry)(struct prom_args *); + + //int prom_call(const char *service, int nargs, int nret, ...) const; +protected: + enum { + PROM_ERROR = -1u + }; + + + typedef void *ihandle_t; + typedef void *phandle_t; + + typedef struct + { + unsigned long len; + char data[]; + } of_item_t; + + /* methods */ + unsigned prom_call(const char *service, int nargs, int nret, ...) const + { + struct prom_args args = prom_args(service, nargs, nret); + va_list list; + + va_start(list, nret); + for(int i = 0; i < nargs; i++) + args.args[i] = va_arg(list, void*); + va_end(list); + + for(int i = 0; i < nret; i++) + args.args[nargs + i] = 0; + + if(_prom()(&args) < 0) + return PROM_ERROR; + + return (nret > 0) ? (unsigned long)args.args[nargs] : 0; + } + + + int prom_getprop(phandle_t node, const char *pname, void *value, + size_t size) + { + return prom_call("getprop", 4, 1, node, pname, (unsigned long)value, + (unsigned long)size); + } + + int prom_next_node(phandle_t *nodep) + { + phandle_t node; + + if ((node = *nodep) != 0 + && (*nodep = (phandle_t)prom_call("child", 1, 1, node)) != 0) + return 1; + if ((*nodep = (phandle_t)prom_call("peer", 1, 1, node)) != 0) + return 1; + for (;;) { + if ((node = (phandle_t)prom_call("parent", 1, 1, node)) == 0) + return 0; + if ((*nodep = (phandle_t)prom_call("peer", 1, 1, node)) != 0) + return 1; + } + } + + template + static inline bool handle_valid(T p) + { + return ((unsigned long)p != 0 && (unsigned long)p != PROM_ERROR); + } + + static prom_entry _prom(unsigned long prom = 0) + { + static prom_entry local_prom; + + if(prom) + local_prom = reinterpret_cast(prom); + + return local_prom; + } + +public: + Of() {}; + + static void set_prom(unsigned long prom) + { + _prom(prom); + } + + static unsigned long get_prom() + { + return reinterpret_cast(_prom()); + } + +}; +} + +#endif /* L4_PPC32_OF_H__*/ diff --git a/l4/pkg/drivers-frst/of/include/of_dev.h b/l4/pkg/drivers-frst/of/include/of_dev.h new file mode 100644 index 00000000..d794bdb2 --- /dev/null +++ b/l4/pkg/drivers-frst/of/include/of_dev.h @@ -0,0 +1,24 @@ +#ifndef _L4_PPC32_OF_DEV_H__ +#define _L4_PPC32_OF_DEV_H__ + +enum +{ + MAX_OF_DEVICES = 32 +}; + +typedef struct of_device_t +{ + char type[32]; //type name + char name[32]; //device name + unsigned long reg; //address + union { + struct { + unsigned long cpu_freq; + unsigned long bus_freq; + unsigned long time_freq; + } freq; + unsigned long interrupts[3]; //pin, int nr, sense + }; +} of_device_t; + +#endif diff --git a/l4/pkg/drivers-frst/of/include/of_if.h b/l4/pkg/drivers-frst/of/include/of_if.h new file mode 100644 index 00000000..26bfbfb6 --- /dev/null +++ b/l4/pkg/drivers-frst/of/include/of_if.h @@ -0,0 +1,40 @@ +#include +#include + +namespace L4_drivers +{ +class Of_if : public Of +{ +private: + phandle_t _chosen; + ihandle_t _root; + + phandle_t get_device(const char*, const char *prop = "device_type"); + unsigned long cpu_detect(const char *prop); + +public: + Of_if() : Of(), _chosen(0), _root(0) {} + unsigned long detect_ramsize(); + unsigned long detect_cpu_freq(); + unsigned long detect_bus_freq(); + unsigned long detect_time_freq(); + bool detect_devices(unsigned long *start_addr, unsigned long *length); + void boot_finish(); + + phandle_t get_chosen() + { + if(handle_valid(_chosen)) return _chosen; + _chosen = (phandle_t)prom_call("finddevice", 1, 1, "/chosen"); + return _chosen; + } + + ihandle_t get_root() + { + if(handle_valid(_root)) return _root; + _root = (ihandle_t)prom_call("finddevice", 1, 1, "/"); + return _root; + } + + void vesa_set_mode(int mode); +}; +} diff --git a/l4/pkg/drivers-frst/of/src/Makefile b/l4/pkg/drivers-frst/of/src/Makefile new file mode 100644 index 00000000..9945cbe8 --- /dev/null +++ b/l4/pkg/drivers-frst/of/src/Makefile @@ -0,0 +1,13 @@ +PKGDIR ?= ../.. +L4DIR ?= $(PKGDIR)/../.. + +SRC_CC := of.cc +SYSTEMS = $(SYSTEMS_PLAIN) +TARGET = libdrivers_of.a +PC_FILENAME = drivers_of + +PRIVATE_INCDIR += $(SRC_DIR)/../include + +include $(L4DIR)/mk/lib.mk + +CXXFLAGS += -DL4_NO_RTTI -fno-exceptions -fno-rtti diff --git a/l4/pkg/drivers-frst/of/src/of.cc b/l4/pkg/drivers-frst/of/src/of.cc new file mode 100644 index 00000000..afadcc6e --- /dev/null +++ b/l4/pkg/drivers-frst/of/src/of.cc @@ -0,0 +1,152 @@ +#include "of_if.h" +#include + +namespace L4_drivers +{ + unsigned long Of_if::detect_ramsize() + { + unsigned long addr_cells, size_cells, ram_size; + unsigned long reg[100]; + phandle_t mem; + + prom_getprop(get_root(), "#address-cells", &addr_cells, sizeof(&addr_cells)); + prom_getprop(get_root(), "#size-cells", &size_cells, sizeof(&size_cells)); + ram_size = 0; + + mem = get_device("memory"); + unsigned int len = prom_getprop(mem, "reg", ®, sizeof(reg)); + len /= 4; /* always 32 bit values */ + + if(len > sizeof(reg)) + len = sizeof(reg); + + unsigned long base, size; + for(unsigned i = 0; i < len; i += (addr_cells + size_cells)) { + base = reg[i + addr_cells - 1]; + size = reg[i + addr_cells + size_cells - 1]; + if((base + size) > ram_size) + ram_size = base + size; + + printf(" Memory base: [%08lx; %08lx] size: %lu KB\n", + base, base + size, size / 1024); + } + + return ram_size; + } + + unsigned long Of_if::cpu_detect(const char* prop) + { + phandle_t cpu; + unsigned long val; + cpu = get_device("cpu"); + + prom_getprop(cpu, prop, &val, sizeof(&val)); + return val; + } + + unsigned long Of_if::detect_bus_freq() + { + return cpu_detect("bus-frequency"); + } + + unsigned long Of_if::detect_cpu_freq() + { + return cpu_detect("clock-frequency"); + } + + unsigned long Of_if::detect_time_freq() + { + return cpu_detect("timebase-frequency"); + } + + L4_drivers::Of_if::phandle_t Of_if::get_device(const char *device, const char *prop) + { + phandle_t dev; + char type[32]; + for(dev = 0; prom_next_node(&dev); ) + { + prom_getprop(dev, prop, type, sizeof(type)); + + if (strcmp(type, device)) + continue; + + return dev; + } + return 0; + } + + bool Of_if::detect_devices(unsigned long *start_addr, unsigned long *length) + { + static of_device_t dev[MAX_OF_DEVICES]; + char descr[64]; + + printf(" Detecting hardware ...\n"); + int i = -1; + + for(phandle_t node = 0; prom_next_node(&node) && i < MAX_OF_DEVICES;) + { + if (prom_getprop(node, "device_type", &(dev[i+1].type), + sizeof(dev[i].type)) < 0) + continue; + i++; + + prom_getprop(node, "name", &dev[i].name, sizeof(dev[i].name)); + + if (prom_getprop(node, "reg", &(dev[i].reg), sizeof(dev[i].reg)) < 0) + dev[i].reg = 0; + + if (!strcmp(dev[i].type, "cpu")) + { + dev[i].freq.cpu_freq = detect_cpu_freq(); + dev[i].freq.bus_freq = detect_bus_freq(); + dev[i].freq.time_freq = detect_time_freq(); + } + else if (prom_getprop(node, "interrupts", (dev[i].interrupts), + sizeof(dev[i].interrupts)) < 0) + dev[i].interrupts[0] = dev[i].interrupts[1] = dev[i].interrupts[2] = ~0UL; + + + //just for information + prom_getprop(node, ".description", descr, sizeof(descr)); + + printf("\33[1;36m" + " [%s]\33[0;36m (%s)\33[0m\n" + " reg: %08lx interrupts: %08lx, %08lx, %08lx\n", + dev[i].name, descr, dev[i].reg, dev[i].interrupts[0], + dev[i].interrupts[1], dev[i].interrupts[2]); + } + + if (i < 0) + return false; + + *start_addr = (unsigned long)dev; + *length = (i + 1) * sizeof(of_device_t); + + return true; + } + + + void Of_if::boot_finish() + { + ihandle_t _std; + //close stdin + prom_getprop(get_chosen(), "stdin", &_std, sizeof(_std)); + prom_call("close", 1, 0, _std); + //close stdout + prom_getprop(get_chosen(), "stdout", &_std, sizeof(_std)); + prom_call("close", 1, 0, _std); + //finish pending dma requests + prom_call("quiesce", 0, 0); + } + + void Of_if::vesa_set_mode(int mode) + { + (void)mode; + unsigned long test_mode = 0x117; + phandle_t disp = get_device("display", "name"); + int ret = prom_call("vesa-set-mode", 2, 1, disp, test_mode);// &test_mode); + unsigned long adr = prom_call("vesa-frame-buffer-adr", 1, 1); + + printf("VESA: returned %d fb %08lx\n", ret, adr); + } +} diff --git a/l4/pkg/drivers-frst/uart/Makefile b/l4/pkg/drivers-frst/uart/Makefile new file mode 100644 index 00000000..8fe22252 --- /dev/null +++ b/l4/pkg/drivers-frst/uart/Makefile @@ -0,0 +1,5 @@ +PKGDIR = .. +L4DIR ?= $(PKGDIR)/../.. + +TARGET := include src +include $(L4DIR)/mk/subdir.mk diff --git a/l4/pkg/drivers-frst/uart/include/Makefile b/l4/pkg/drivers-frst/uart/include/Makefile new file mode 100644 index 00000000..e77a52bf --- /dev/null +++ b/l4/pkg/drivers-frst/uart/include/Makefile @@ -0,0 +1,6 @@ +PKGDIR = ../.. +L4DIR ?= $(PKGDIR)/../.. + +PKGNAME = drivers + +include $(L4DIR)/mk/include.mk diff --git a/l4/pkg/drivers-frst/uart/include/uart_base.h b/l4/pkg/drivers-frst/uart/include/uart_base.h new file mode 100644 index 00000000..320c2865 --- /dev/null +++ b/l4/pkg/drivers-frst/uart/include/uart_base.h @@ -0,0 +1,48 @@ +/* + * (c) 2009-2012 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ +#pragma once + +#include +#include + +namespace L4 +{ + class Uart + { + protected: + unsigned _mode; + unsigned _rate; + Io_register_block const *_regs; + + public: + void *operator new (size_t, void* a) + { return a; } + + public: + typedef unsigned Transfer_mode; + typedef unsigned Baud_rate; + + Uart() + : _mode(~0U), _rate(~0U) + {} + + virtual bool startup(Io_register_block const *regs) = 0; + + virtual ~Uart() {} + virtual void shutdown() = 0; + virtual bool change_mode(Transfer_mode m, Baud_rate r) = 0; + virtual int get_char(bool blocking = true) const = 0; + virtual int char_avail() const = 0; + virtual int write(char const *s, unsigned long count) const = 0; + + virtual bool enable_rx_irq(bool = true) { return false; } + Transfer_mode mode() const { return _mode; } + Baud_rate rate() const { return _rate; } + }; +} diff --git a/l4/pkg/drivers-frst/uart/include/uart_dcc-v6.h b/l4/pkg/drivers-frst/uart/include/uart_dcc-v6.h new file mode 100644 index 00000000..4c226b1a --- /dev/null +++ b/l4/pkg/drivers-frst/uart/include/uart_dcc-v6.h @@ -0,0 +1,27 @@ +/* + * (c) 2009 Technische Universität Dresden + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ +#ifndef L4_CXX_UART_DCC_V6_H__ +#define L4_CXX_UART_DCC_V6_H__ + +#include "uart_base.h" + +namespace L4 +{ + class Uart_dcc_v6 : public Uart + { + public: + bool startup(Io_register_block const *); + void shutdown(); + bool change_mode(Transfer_mode m, Baud_rate r); + int get_char(bool blocking = true) const; + int char_avail() const; + inline void out_char(char c) const; + int write(char const *s, unsigned long count) const; + }; +}; + +#endif diff --git a/l4/pkg/drivers-frst/uart/include/uart_dummy.h b/l4/pkg/drivers-frst/uart/include/uart_dummy.h new file mode 100644 index 00000000..cba34734 --- /dev/null +++ b/l4/pkg/drivers-frst/uart/include/uart_dummy.h @@ -0,0 +1,29 @@ +/* + * (c) 2009 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ +#ifndef L4_CXX_UART_DUMMY_H__ +#define L4_CXX_UART_DUMMY_H__ + +#include "uart_base.h" + +namespace L4 +{ + class Uart_dummy : public Uart + { + public: + bool startup(Io_register_block const *); + void shutdown(); + bool change_mode(Transfer_mode m, Baud_rate r); + int get_char(bool blocking = true) const; + int char_avail() const; + inline void out_char(char c) const; + int write(char const *s, unsigned long count) const; + }; +}; + +#endif diff --git a/l4/pkg/drivers-frst/uart/include/uart_imx.h b/l4/pkg/drivers-frst/uart/include/uart_imx.h new file mode 100644 index 00000000..99251c1f --- /dev/null +++ b/l4/pkg/drivers-frst/uart/include/uart_imx.h @@ -0,0 +1,54 @@ +/* + * (c) 2008-2009 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ +#ifndef L4_CXX_UART_imx_H__ +#define L4_CXX_UART_imx_H__ + +#include "uart_base.h" + +namespace L4 +{ + class Uart_imx : public Uart + { + public: + enum platform_type { Type_imx21, Type_imx35, Type_imx51 }; + explicit Uart_imx(enum platform_type type) + : _type(type) {} + bool startup(Io_register_block const *); + void shutdown(); + bool enable_rx_irq(bool enable = true); + bool change_mode(Transfer_mode m, Baud_rate r); + int get_char(bool blocking = true) const; + int char_avail() const; + inline void out_char(char c) const; + int write(char const *s, unsigned long count) const; + + private: + enum platform_type _type; + }; + + class Uart_imx21 : public Uart_imx + { + public: + Uart_imx21() : Uart_imx(Type_imx21) {} + }; + + class Uart_imx35 : public Uart_imx + { + public: + Uart_imx35() : Uart_imx(Type_imx35) {} + }; + + class Uart_imx51 : public Uart_imx + { + public: + Uart_imx51() : Uart_imx(Type_imx51) {} + }; +}; + +#endif diff --git a/l4/pkg/drivers-frst/uart/include/uart_leon3.h b/l4/pkg/drivers-frst/uart/include/uart_leon3.h new file mode 100644 index 00000000..78230b57 --- /dev/null +++ b/l4/pkg/drivers-frst/uart/include/uart_leon3.h @@ -0,0 +1,30 @@ +/* + * (c) 2011 Adam Lackorzynski + * Björn Döbel + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ +#ifndef L4_CXX_UART_LEON3_H__ +#define L4_CXX_UART_LEON3_H__ + +#include "uart_base.h" + +namespace L4 +{ + class Uart_leon3 : public Uart + { + public: + bool startup(Io_register_block const *); + void shutdown(); + bool change_mode(Transfer_mode m, Baud_rate r); + int get_char(bool blocking = true) const; + int char_avail() const; + inline void out_char(char c) const; + int write(char const *s, unsigned long count) const; + }; +}; + +#endif diff --git a/l4/pkg/drivers-frst/uart/include/uart_of.h b/l4/pkg/drivers-frst/uart/include/uart_of.h new file mode 100644 index 00000000..9c98f6dc --- /dev/null +++ b/l4/pkg/drivers-frst/uart/include/uart_of.h @@ -0,0 +1,38 @@ +/* + * (c) 2009 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ +#ifndef L4_CXX_UART_OF_H__ +#define L4_CXX_UART_OF_H__ + +#include "uart_base.h" +#include +#include +#include + +namespace L4 +{ + class Uart_of : public Uart, public L4_drivers::Of + { + private: + ihandle_t _serial; + + public: + Uart_of() + : Of(), _serial(0) {} + bool startup(Io_register_block const *); + + void shutdown(); + bool change_mode(Transfer_mode m, Baud_rate r); + int get_char(bool blocking = true) const; + int char_avail() const; + void out_char(char c) const; + int write(char const *s, unsigned long count) const; + }; +}; + +#endif diff --git a/l4/pkg/drivers-frst/uart/include/uart_omap35x.h b/l4/pkg/drivers-frst/uart/include/uart_omap35x.h new file mode 100644 index 00000000..425e7b54 --- /dev/null +++ b/l4/pkg/drivers-frst/uart/include/uart_omap35x.h @@ -0,0 +1,30 @@ +/* + * (c) 2009 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ +#ifndef L4_CXX_UART_OMAP35X_H__ +#define L4_CXX_UART_OMAP35X_H__ + +#include "uart_base.h" + +namespace L4 +{ + class Uart_omap35x : public Uart + { + public: + bool startup(Io_register_block const *); + void shutdown(); + bool change_mode(Transfer_mode m, Baud_rate r); + bool enable_rx_irq(bool); + int get_char(bool blocking = true) const; + int char_avail() const; + inline void out_char(char c) const; + int write(char const *s, unsigned long count) const; + }; +}; + +#endif diff --git a/l4/pkg/drivers-frst/uart/include/uart_pl011.h b/l4/pkg/drivers-frst/uart/include/uart_pl011.h new file mode 100644 index 00000000..0442bcc8 --- /dev/null +++ b/l4/pkg/drivers-frst/uart/include/uart_pl011.h @@ -0,0 +1,30 @@ +/* + * (c) 2009 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ +#ifndef L4_CXX_UART_PL011_H__ +#define L4_CXX_UART_PL011_H__ + +#include "uart_base.h" + +namespace L4 +{ + class Uart_pl011 : public Uart + { + public: + bool startup(Io_register_block const *); + void shutdown(); + bool change_mode(Transfer_mode m, Baud_rate r); + bool enable_rx_irq(bool enable); + int get_char(bool blocking = true) const; + int char_avail() const; + inline void out_char(char c) const; + int write(char const *s, unsigned long count) const; + }; +}; + +#endif diff --git a/l4/pkg/drivers-frst/uart/include/uart_pxa.h b/l4/pkg/drivers-frst/uart/include/uart_pxa.h new file mode 100644 index 00000000..3f142de9 --- /dev/null +++ b/l4/pkg/drivers-frst/uart/include/uart_pxa.h @@ -0,0 +1,58 @@ +/* + * (c) 2008-2012 Adam Lackorznynski + * Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ +#pragma once + +#include "uart_base.h" + +namespace L4 +{ + class Uart_16550 : public Uart + { + public: + enum + { + PAR_NONE = 0x00, + PAR_EVEN = 0x18, + PAR_ODD = 0x08, + DAT_5 = 0x00, + DAT_6 = 0x01, + DAT_7 = 0x02, + DAT_8 = 0x03, + STOP_1 = 0x00, + STOP_2 = 0x04, + + MODE_8N1 = PAR_NONE | DAT_8 | STOP_1, + MODE_7E1 = PAR_EVEN | DAT_7 | STOP_1, + + // these two values are to leave either mode + // or baud rate unchanged on a call to change_mode + MODE_NC = 0x1000000, + BAUD_NC = 0x1000000, + + Base_rate_x86 = 115200, + Base_rate_pxa = 921600, + }; + + explicit Uart_16550(unsigned long base_rate) + : _base_rate(base_rate) + {} + + bool startup(Io_register_block const *regs); + void shutdown(); + bool change_mode(Transfer_mode m, Baud_rate r); + int get_char(bool blocking = true) const; + int char_avail() const; + inline void out_char(char c) const; + int write(char const *s, unsigned long count) const; + + private: + unsigned long _base_rate; + }; +} diff --git a/l4/pkg/drivers-frst/uart/include/uart_s3c2410.h b/l4/pkg/drivers-frst/uart/include/uart_s3c2410.h new file mode 100644 index 00000000..91bbb1a2 --- /dev/null +++ b/l4/pkg/drivers-frst/uart/include/uart_s3c2410.h @@ -0,0 +1,86 @@ +/* + * (c) 2009-2012 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ +#ifndef L4_DRIVERS_UART_S3C2410_H__ +#define L4_DRIVERS_UART_S3C2410_H__ + +#include "uart_base.h" + +namespace L4 +{ + class Uart_s3c : public Uart + { + protected: + enum Uart_type + { + Type_24xx, Type_64xx, Type_s5pv210, + }; + + Uart_type type() const { return _type; } + + public: + explicit Uart_s3c(Uart_type type) : _type(type) {} + bool startup(Io_register_block const *); + void shutdown(); + bool change_mode(Transfer_mode m, Baud_rate r); + int get_char(bool blocking = true) const; + int char_avail() const; + inline void out_char(char c) const; + int write(char const *s, unsigned long count) const; + void fifo_reset(); + + protected: + virtual void ack_rx_irq() const = 0; + virtual void wait_for_empty_tx_fifo() const = 0; + virtual void wait_for_non_full_tx_fifo() const = 0; + virtual unsigned is_rx_fifo_non_empty() const = 0; + + private: + Uart_type _type; + }; + + class Uart_s3c2410 : public Uart_s3c + { + public: + Uart_s3c2410() : Uart_s3c(Type_24xx) {} + + protected: + void ack_rx_irq() const {} + void wait_for_empty_tx_fifo() const; + void wait_for_non_full_tx_fifo() const; + unsigned is_rx_fifo_non_empty() const; + + void auto_flow_control(bool on); + }; + + class Uart_s3c64xx : public Uart_s3c + { + public: + Uart_s3c64xx() : Uart_s3c(Type_64xx) {} + + protected: + void ack_rx_irq() const; + void wait_for_empty_tx_fifo() const; + void wait_for_non_full_tx_fifo() const; + unsigned is_rx_fifo_non_empty() const; + }; + + class Uart_s5pv210 : public Uart_s3c + { + public: + Uart_s5pv210() : Uart_s3c(Type_s5pv210) {} + + protected: + void ack_rx_irq() const; + void wait_for_empty_tx_fifo() const; + void wait_for_non_full_tx_fifo() const; + unsigned is_rx_fifo_non_empty() const; + }; +}; + +#endif diff --git a/l4/pkg/drivers-frst/uart/include/uart_sa1000.h b/l4/pkg/drivers-frst/uart/include/uart_sa1000.h new file mode 100644 index 00000000..ac21d6a5 --- /dev/null +++ b/l4/pkg/drivers-frst/uart/include/uart_sa1000.h @@ -0,0 +1,30 @@ +/* + * (c) 2008-2012 Adam Lackorznynski + * Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ +#ifndef __L4_CXX_UART_SA1000_H__ +#define __L4_CXX_UART_SA1000_H__ + +#include "uart_base.h" + +namespace L4 +{ + class Uart_sa1000 : public Uart + { + public: + bool startup(Io_register_block const *); + void shutdown(); + bool change_mode(Transfer_mode m, Baud_rate r); + int get_char(bool blocking = true) const; + int char_avail() const; + inline void out_char(char c) const; + int write(char const *s, unsigned long count) const; + }; +}; + +#endif diff --git a/l4/pkg/drivers-frst/uart/src/Makefile b/l4/pkg/drivers-frst/uart/src/Makefile new file mode 100644 index 00000000..70a44fa7 --- /dev/null +++ b/l4/pkg/drivers-frst/uart/src/Makefile @@ -0,0 +1,19 @@ +PKGDIR ?= ../.. +L4DIR ?= $(PKGDIR)/../.. + +SRC_CC += uart_dummy.cc uart_pl011.cc uart_sa1000.cc \ + uart_pxa.cc uart_omap35x.cc uart_imx.cc \ + uart_s3c2410.cc uart_of.cc uart_leon3.cc \ + uart_dcc-v6.cc +SYSTEMS = $(SYSTEMS_PLAIN) +TARGET = libdrivers_uart.a +PC_FILENAME = drivers_uart + +PRIVATE_INCDIR += $(SRC_DIR)/../include + +INCLUDE_MAKE_RULES = $(SRC_DIR)/*/Make.rules + +include $(L4DIR)/mk/lib.mk + +CXXFLAGS += -DL4_NO_RTTI -fno-exceptions -fno-rtti + diff --git a/l4/pkg/drivers-frst/uart/src/uart_dcc-v6.cc b/l4/pkg/drivers-frst/uart/src/uart_dcc-v6.cc new file mode 100644 index 00000000..3d620e61 --- /dev/null +++ b/l4/pkg/drivers-frst/uart/src/uart_dcc-v6.cc @@ -0,0 +1,62 @@ +/* + * (c) 2009 Technische Universität Dresden + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ +#include "uart_dcc-v6.h" + +namespace L4 +{ + bool Uart_dcc_v6::startup(Io_register_block const *) + { return true; } + + void Uart_dcc_v6::shutdown() + {} + + bool Uart_dcc_v6::change_mode(Transfer_mode, Baud_rate) + { return true; } + + int Uart_dcc_v6::get_char(bool /*blocking*/) const + { +#ifdef ARCH_arm + int c; + asm volatile("mrc p14, 0, %0, c0, c5, 0": "=r" (c)); + return c & 0xff; +#else + return 0; +#endif + } + + int Uart_dcc_v6::char_avail() const + { +#ifdef ARCH_arm + unsigned long s; + asm volatile("mrc p14, 0, %0, c0, c1, 0" : "=r" (s)); + return s & 0x40000000; +#else + return false; +#endif + } + + void Uart_dcc_v6::out_char(char c) const + { +#ifdef ARCH_arm + unsigned long s; + do + asm volatile("mrc p14, 0, %0, c0, c1, 0" : "=r" (s)); + while (s & 0x20000000); + asm volatile("mcr p14, 0, %0, c0, c5, 0": : "r" (c & 0xff)); +#else + (void)c; +#endif + } + + int Uart_dcc_v6::write(char const *s, unsigned long count) const + { + unsigned long c = count; + while (c--) + out_char(*s++); + return count; + } +}; diff --git a/l4/pkg/drivers-frst/uart/src/uart_dummy.cc b/l4/pkg/drivers-frst/uart/src/uart_dummy.cc new file mode 100644 index 00000000..480a02bf --- /dev/null +++ b/l4/pkg/drivers-frst/uart/src/uart_dummy.cc @@ -0,0 +1,33 @@ +/* + * (c) 2009-2012 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ +#include "uart_dummy.h" + +namespace L4 +{ + bool Uart_dummy::startup(Io_register_block const *) + { return true; } + + void Uart_dummy::shutdown() + {} + + bool Uart_dummy::change_mode(Transfer_mode, Baud_rate) + { return true; } + + int Uart_dummy::get_char(bool /*blocking*/) const + { return 0; } + + int Uart_dummy::char_avail() const + { return false; } + + void Uart_dummy::out_char(char c) const + { (void)c; } + + int Uart_dummy::write(char const *s, unsigned long count) const + { (void)s; (void)count; return 0; } +}; diff --git a/l4/pkg/drivers-frst/uart/src/uart_imx.cc b/l4/pkg/drivers-frst/uart/src/uart_imx.cc new file mode 100644 index 00000000..c22f9bdc --- /dev/null +++ b/l4/pkg/drivers-frst/uart/src/uart_imx.cc @@ -0,0 +1,167 @@ +/* + * (c) 2008-2011 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ +#include "uart_imx.h" + +namespace L4 +{ + enum { + URXD = 0x00, // Receiver + UTXD = 0x40, // Transmitter + UCR1 = 0x80, // Control 1 + UCR2 = 0x84, // Control 2 + UCR3 = 0x88, // Control 3 + UCR4 = 0x8c, // Control 4 + UFCR = 0x90, // FIFO Control + USR1 = 0x94, // Status 1 + USR2 = 0x98, // Status 2 + UESC = 0x9c, // Escape Charater + UTIM = 0xa0, // Escape Timer + UBIR = 0xa4, // BRM Incremental Registers + UBMR = 0xa8, // BRM Modulator Registers + UBRC = 0xac, // Baud Rate Count + ONEMS = 0xb0, // One millisecond + UTS = 0xb4, // Test + + + UCR1_EN = 1 << 0, // Enable UART + + UCR2_SRST = 1 << 0, // Software Reset + UCR2_RXEN = 1 << 1, // Receiver Enable + UCR2_TXEN = 1 << 2, // Transmitter Enable + UCR2_WS = 1 << 5, // 8-bit character length + UCR2_STPB = 1 << 6, // 0 = 1 Stop bit, 1 = 2 stop bits + UCR2_PROE = 1 << 7, // 0 = even parity, 1 = odd parity + UCR2_PREN = 1 << 8, // Parity enable + UCR2_RTEC_MASK = 3 << 9, // Request to Send Edge Control mask + UCR2_RTEC_RISI = 0 << 9, // Trigger IRQ on rising edge + UCR2_RTEC_FALL = 1 << 9, // Trigger IRQ on falling edge + UCR2_RTEC_ANY = 2 << 9, // Trigger IRQ on any edge + UCR2_ESCEN = 1 << 11, // Escape enable + UCR2_CTS = 1 << 12, // Clear to Send: 0 = pin is high (inactive), 1 = pin is low (active) + UCR2_CTSC = 1 << 13, // CTS Pin Control: 0 = pin controlled by CTS bit, 1 = pin controlled by the receiver + UCR2_IRTS = 1 << 14, // Ignore RTS pin + UCR2_ESCI = 1 << 15, // Escape Sequence Interrupt Enable + + UCR3_ACIEN = 1 << 0, // Autobaud Counter Interrupt enable + UCR3_INVT = 1 << 1, // Inverted Infrared Transmission + UCR3_RXDMUXSEL = 1 << 2, // RXD Muxed Input Selected: 0 = serial ist IPP_UART_RXD, IR is IPP_UART_RXD_IR, 1 = IPP_UART_RXD_MUX for both + + + UCR4_DREN = 1 << 0, // Receive Data Ready Interrupt Enable + UCR4_OREN = 1 << 1, // Receiver Overrun Interrupt enable + UCR4_BKEN = 1 << 2, // BREAK Condition Dected Interrupt enable + UCR4_TCEN = 1 << 3, // Transmit Complete Interrupt Enable + UCR4_LPBYP = 1 << 4, // Low Power Bypass + UCR4_IRSC = 1 << 5, // IR Special Case + // Bit 6 is reserve, should be written as 0 + UCR4_WKEN = 1 << 7, // WAKE Interrupt Enable + UCR4_ENIRI = 1 << 8, // Serial Infrared Interrupt Enable + UCR4_INVR = 1 << 9, // Inverted Infrared Reception + UCR4_CTSTL_32 = 32 << 10, // CTS Trigger Level + + UFCR_RXTL_MASK = 63 << 0, // Receiver Trigger Level Mask + UFCR_RXTL_1 = 1 << 0, // Receiver Trigger Level: 1 char + UFCR_RFDIV_2 = 4 << 7, // Reference Frequency Divier: by 2 + UFCR_TXTL_MASK = 63 << 10, // Trasmitter Trigger Level: 8 chars + UFCR_TXTL_8 = 8 << 10, // Trasmitter Trigger Level: 8 chars + UFCR_TXTL_32 = 32 << 10, // Trasmitter Trigger Level: 32 chars + + USR1_TRDY = 1 << 13, // Transmitter Ready + + USR2_RDR = 1 << 0, // Receive Data Ready + USR2_ORE = 1 << 1, // Overrun Error + USR2_BRCD = 1 << 2, // Break Condition Detected + USR2_TXDC = 1 << 3, // Transmitter Complete + USR2_TXFE = 1 << 14, // Transmit Buffer FIFO Empty + + }; + + bool Uart_imx::startup(Io_register_block const *regs) + { + _regs = regs; + + // 115200Baud, 8n1 + switch (_type) + { + case Type_imx21: + _regs->write(UBIR, 0x0344); + _regs->write(UBMR, 0x270f); + break; + case Type_imx35: + _regs->write(UBIR, 0xf); + _regs->write(UBMR, 0x1b2); + break; + case Type_imx51: + _regs->write(UBIR, 0xf); + _regs->write(UBMR, 0x120); + break; + } + + _regs->write(UCR1, UCR1_EN); + _regs->write(UCR2, UCR2_SRST | UCR2_RXEN | UCR2_TXEN | UCR2_WS | UCR2_IRTS); // note: no IRQs enabled + _regs->write(UCR3, UCR3_RXDMUXSEL); + _regs->write(UCR4, UCR4_CTSTL_32); + _regs->write(UFCR, UFCR_TXTL_8 | UFCR_RFDIV_2 | UFCR_RXTL_1); + + return true; + } + + void Uart_imx::shutdown() + { + _regs->write(UCR1, 0); // Disable UART + } + + bool Uart_imx::enable_rx_irq(bool enable) + { + if (enable) + { + _regs->write(UCR2, _regs->read(UCR2) | UCR2_RTEC_ANY); + _regs->write(UCR4, _regs->read(UCR4) | UCR4_DREN); + } + else + _regs->write(UCR4, _regs->read(UCR4) & ~UCR4_DREN); + + return true; + } + + bool Uart_imx::change_mode(Transfer_mode, Baud_rate) + { return true; } + + int Uart_imx::get_char(bool blocking) const + { + while (!char_avail()) + if (!blocking) return -1; + + return _regs->read(URXD) & 0xff; + } + + int Uart_imx::char_avail() const + { + return _regs->read(USR2) & USR2_RDR; + } + + void Uart_imx::out_char(char c) const + { + while (!(_regs->read(USR1) & USR1_TRDY)) + ; + _regs->write(UTXD, c); + } + + int Uart_imx::write(char const *s, unsigned long count) const + { + unsigned long c = count; + while (c--) + out_char(*s++); + + while (!(_regs->read(USR2) & USR2_TXDC)) + ; + + return count; + } +}; diff --git a/l4/pkg/drivers-frst/uart/src/uart_leon3.cc b/l4/pkg/drivers-frst/uart/src/uart_leon3.cc new file mode 100644 index 00000000..2eccde15 --- /dev/null +++ b/l4/pkg/drivers-frst/uart/src/uart_leon3.cc @@ -0,0 +1,102 @@ +/* + * (c) 2011 Adam Lackorzynski + * Björn Döbel + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ +#include "uart_leon3.h" + +namespace L4 +{ + enum { + DATA_REG = 0x00, + STATUS_REG = 0x04, + CTRL_REG = 0x08, + SCALER_REG = 0x0C, + + DATA_MASK = 0x0F, + + STATUS_DR = 0x001, // data ready + STATUS_TS = 0x002, // transmit shift empty + STATUS_TE = 0x004, // transmit fifo empty + STATUS_BR = 0x008, // BREAK received + STATUS_OV = 0x010, // overrun + STATUS_PE = 0x020, // parity error + STATUS_FE = 0x040, // framing error + STATUS_TH = 0x080, // transmit fifo half-full + STATUS_RH = 0x100, // recv fifo half-full + STATUS_TF = 0x200, // transmit fifo full + STATUS_RF = 0x400, // recv fifo full + + STATUS_TCNT_MASK = 0x3F, + STATUS_TCNT_SHIFT = 20, + STATUS_RCNT_MASK = 0x3F, + STATUS_RCNT_SHIFT = 26, + + CTRL_RE = 0x001, + CTRL_TE = 0x002, + CTRL_RI = 0x004, + CTRL_TI = 0x008, + CTRL_PS = 0x010, + CTRL_PE = 0x020, + CTRL_FL = 0x040, + CTRL_LB = 0x080, + CTRL_EC = 0x100, + CTRL_TF = 0x200, + CTRL_RF = 0x400, + + SCALER_MASK = 0xFFF, + }; + + + bool Uart_leon3::startup(Io_register_block const *regs) + { + _regs = regs; + + return true; + } + + void Uart_leon3::shutdown() + { } + + bool Uart_leon3::change_mode(Transfer_mode, Baud_rate r) + { + if (r != 115200) + return false; + + return true; + } + + int Uart_leon3::get_char(bool blocking) const + { + while (!char_avail()) + if (!blocking) + return -1; + + return _regs->read(DATA_REG) & DATA_MASK; + } + + int Uart_leon3::char_avail() const + { + return 0; + } + + void Uart_leon3::out_char(char c) const + { + while (_regs->read(STATUS_REG) & STATUS_TF) + ; + _regs->write(DATA_REG, c); + } + + int Uart_leon3::write(char const *s, unsigned long count) const + { + unsigned long c = count; + while (c--) + out_char(*s++); + + return count; + } +}; diff --git a/l4/pkg/drivers-frst/uart/src/uart_of.cc b/l4/pkg/drivers-frst/uart/src/uart_of.cc new file mode 100644 index 00000000..ab0d7f34 --- /dev/null +++ b/l4/pkg/drivers-frst/uart/src/uart_of.cc @@ -0,0 +1,66 @@ +/* + * (c) 2009-2012 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ +#include "uart_of.h" +#include + +namespace L4 { + + bool Uart_of::startup(Io_register_block const *) + { + char path[64], type[16]; + for (phandle_t node = 0; prom_next_node(&node); ) + { + prom_getprop(node, "device_type", type, sizeof(type)); + + if (strcmp(type, "serial")) + continue; + + if (prom_call("package-to-path", 3, 1, node, + path, sizeof(path)) == Of::PROM_ERROR) + return false; + + /* open port */ + if ((_serial = (ihandle_t)prom_call("open", 1, 1, path)) != 0) + return false; + + break; + } + //prom_call("exit", 0, 0); + return _serial; + } + + void Uart_of::shutdown() + { + prom_call("close", 1, 0, _serial); + } + + int Uart_of::get_char(bool blocking) const + { + int c, len = 0; + + while (len != 1 && blocking) + len = prom_call("read", 3, 1, _serial, &c, 1); + + return len ? c :-1; + } + + int Uart_of::write(char const *s, unsigned long count) const + { + return prom_call("write", 3, 1, _serial, s, count); + } + + void Uart_of::out_char(char c) const + { + prom_call("write", 3, 0, _serial, c, 1); + } + + /* UNIMPLEMENTED */ + bool Uart_of::change_mode(Transfer_mode, Baud_rate){ return true; } + int Uart_of::char_avail() const { return 1; } +}; diff --git a/l4/pkg/drivers-frst/uart/src/uart_omap35x.cc b/l4/pkg/drivers-frst/uart/src/uart_omap35x.cc new file mode 100644 index 00000000..1b719c39 --- /dev/null +++ b/l4/pkg/drivers-frst/uart/src/uart_omap35x.cc @@ -0,0 +1,108 @@ +/* + * (c) 2009-2012 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ +#include "uart_omap35x.h" + +namespace L4 +{ + enum { + DLL_REG = 0x00, + RHR_REG = 0x00, + THR_REG = 0x00, + IER_REG = 0x04, + DLH_REG = 0x04, + LCD_REG = 0x08, + LSR_REG = 0x14, + SSR_REG = 0x44, + SYSC_REG = 0x54, + SYSS_REG = 0x58, + + LCD_REG_CHAR_LENGTH_5BIT = 0 << 0, + LCD_REG_CHAR_LENGTH_6BIT = 1 << 0, + LCD_REG_CHAR_LENGTH_7BIT = 2 << 0, + LCD_REG_CHAR_LENGTH_8BIT = 3 << 0, + LCD_REG_CHAR_NB_STOP_2 = 1 << 2, + LCD_REG_CHAR_PARITY_EN = 1 << 3, + LCD_REG_CHAR_PARITY_TYPE1_EVEN = 1 << 4, + + LSR_REG_RX_FIFO_E_AVAIL = 1 << 0, + LSR_REG_TX_FIFO_E_EMPTY = 1 << 5, + + SSR_REG_TX_FIFO_FULL = 1 << 0, + + SYSC_REG_SOFTRESET = 1 << 1, + + SYSC_REG_RESETDONE = 1 << 0, + }; + + + bool Uart_omap35x::startup(Io_register_block const *regs) + { + _regs = regs; + + // Reset UART + //_regs->write(SYSC_REG, _regs->read(SYSC_REG) | SYSC_REG_SOFTRESET); + //while (!(_regs->read(SYSS_REG) & SYSC_REG_RESETDONE)) + // ; + + return true; + } + + void Uart_omap35x::shutdown() + { + } + + bool Uart_omap35x::enable_rx_irq(bool enable) + { + _regs->write(IER_REG, enable ? 1 : 0); + return true; + } + bool Uart_omap35x::change_mode(Transfer_mode, Baud_rate r) + { + if (r != 115200) + return false; + + return true; + } + + int Uart_omap35x::get_char(bool blocking) const + { + while (!char_avail()) + if (!blocking) + return -1; + + return _regs->read(RHR_REG); + } + + int Uart_omap35x::char_avail() const + { + return _regs->read(LSR_REG) & LSR_REG_RX_FIFO_E_AVAIL; + } + + void Uart_omap35x::out_char(char c) const + { + _regs->write(THR_REG, c); + while (!(_regs->read(LSR_REG) & LSR_REG_TX_FIFO_E_EMPTY)) + ; + } + + int Uart_omap35x::write(char const *s, unsigned long count) const + { + unsigned long c = count; + while (c--) + out_char(*s++); +#if 0 + while (_regs->read(UART01x_FR) & UART01x_FR_BUSY) + ; +#endif + + return count; + } + +}; + diff --git a/l4/pkg/drivers-frst/uart/src/uart_pl011.cc b/l4/pkg/drivers-frst/uart/src/uart_pl011.cc new file mode 100644 index 00000000..cdb58b17 --- /dev/null +++ b/l4/pkg/drivers-frst/uart/src/uart_pl011.cc @@ -0,0 +1,140 @@ +/* + * (c) 2009-2012 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ +#include "uart_pl011.h" + +namespace L4 +{ + enum { + UART011_RXIM = 1 << 4, + UART011_TXIM = 1 << 5, + UART011_RTIM = 1 << 6, + UART011_FEIM = 1 << 7, + UART011_PEIM = 1 << 8, + UART011_BEIM = 1 << 9, + UART011_OEIM = 1 << 10, + + UART011_RXIS = 1 << 4, + UART011_RTIS = 1 << 6, + + UART011_RXIC = 1 << 4, + UART011_RTIC = 1 << 6, + + UART01x_CR_UARTEN = 1, // UART enable + UART011_CR_LBE = 0x080, // loopback enable + UART011_CR_TXE = 0x100, // transmit enable + UART011_CR_RXE = 0x200, // receive enable + + UART01x_FR_BUSY = 0x008, + UART01x_FR_RXFE = 0x010, + UART01x_FR_TXFF = 0x020, + + UART01x_LCRH_PEN = 0x02, // parity enable + UART01x_LCRH_FEN = 0x10, // FIFO enable + UART01x_LCRH_WLEN_8 = 0x60, + + UART01x_DR = 0x00, + UART011_ECR = 0x04, + UART01x_FR = 0x18, + UART011_IBRD = 0x24, + UART011_FBRD = 0x28, + UART011_LCRH = 0x2c, + UART011_CR = 0x30, + UART011_IMSC = 0x38, + UART011_MIS = 0x40, + UART011_ICR = 0x44, + }; + + + bool Uart_pl011::startup(Io_register_block const *regs) + { + _regs = regs; + _regs->write(UART011_CR, UART01x_CR_UARTEN | UART011_CR_TXE | UART011_CR_RXE); + _regs->write(UART011_FBRD, 2); + _regs->write(UART011_IBRD, 13); + _regs->write(UART011_LCRH, 0x60); + _regs->write(UART011_IMSC, 0); + while (_regs->read(UART01x_FR) & UART01x_FR_BUSY) + ; + return true; + } + + void Uart_pl011::shutdown() + { + _regs->write(UART011_IMSC, 0); + _regs->write(UART011_ICR, 0xffff); + _regs->write(UART011_CR, 0); + } + + bool Uart_pl011::enable_rx_irq(bool enable) + { + unsigned long mask = UART011_RXIM | UART011_RTIM; + + _regs->write(UART011_ICR, 0xffff & ~mask); + _regs->write(UART011_ECR, 0xff); + if (enable) + _regs->write(UART011_IMSC, _regs->read(UART011_IMSC) | mask); + else + _regs->write(UART011_IMSC, _regs->read(UART011_IMSC) & ~mask); + return true; + } + + bool Uart_pl011::change_mode(Transfer_mode, Baud_rate r) + { + if (r != 115200) + return false; + + unsigned long old_cr = _regs->read(UART011_CR); + _regs->write(UART011_CR, 0); + + _regs->write(UART011_FBRD, 2); + _regs->write(UART011_IBRD, 13); + _regs->write(UART011_LCRH, UART01x_LCRH_WLEN_8 | UART01x_LCRH_FEN); + + _regs->write(UART011_CR, old_cr); + + return true; + } + + int Uart_pl011::get_char(bool blocking) const + { + while (!char_avail()) + if (!blocking) + return -1; + + //_regs->write(UART011_ICR, UART011_RXIC | UART011_RTIC); + + int c = _regs->read(UART01x_DR); + _regs->write(UART011_ECR, 0xff); + return c; + } + + int Uart_pl011::char_avail() const + { + return !(_regs->read(UART01x_FR) & UART01x_FR_RXFE); + } + + void Uart_pl011::out_char(char c) const + { + while (_regs->read(UART01x_FR) & UART01x_FR_TXFF) + ; + _regs->write(UART01x_DR,c); + } + + int Uart_pl011::write(char const *s, unsigned long count) const + { + unsigned long c = count; + while (c--) + out_char(*s++); + + while (_regs->read(UART01x_FR) & UART01x_FR_BUSY) + ; + + return count; + } +}; diff --git a/l4/pkg/drivers-frst/uart/src/uart_pxa.cc b/l4/pkg/drivers-frst/uart/src/uart_pxa.cc new file mode 100644 index 00000000..f147f1fe --- /dev/null +++ b/l4/pkg/drivers-frst/uart/src/uart_pxa.cc @@ -0,0 +1,157 @@ +/*! + * \file uart_pxa.cc + * \brief PXA UART implementation + * + * \date 2008-01-04 + * \author Adam Lackorznynski + * Alexander Warg + * + */ +/* + * (c) 2008-2009 Author(s) + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ +#include "uart_pxa.h" + +#include + +namespace L4 +{ + enum Registers + { + TRB = 0x00, // Transmit/Receive Buffer (read/write) + BRD_LOW = 0x00, // Baud Rate Divisor LSB if bit 7 of LCR is set (read/write) + IER = 0x01, // Interrupt Enable Register (read/write) + BRD_HIGH = 0x01, // Baud Rate Divisor MSB if bit 7 of LCR is set (read/write) + IIR = 0x02, // Interrupt Identification Register (read only) + FCR = 0x02, // 16550 FIFO Control Register (write only) + LCR = 0x03, // Line Control Register (read/write) + MCR = 0x04, // Modem Control Register (read/write) + LSR = 0x05, // Line Status Register (read only) + MSR = 0x06, // Modem Status Register (read only) + SPR = 0x07, // Scratch Pad Register (read/write) + }; + + enum + { + Base_ier_bits = 1 << 6, // pxa only? + }; + + bool Uart_16550::startup(Io_register_block const *regs) + { + _regs = regs; + + char scratch, scratch2, scratch3; + + scratch = _regs->read(IER); + _regs->write(IER, 0); + + _regs->delay(); + + scratch2 = _regs->read(IER); + _regs->write(IER, 0xf); + + _regs->delay(); + + scratch3 = _regs->read(IER); + _regs->write(IER, scratch); + + if (!(scratch2 == 0x00 && scratch3 == 0x0f)) + return false; // this is not the uart + + _regs->write(IER, Base_ier_bits);/* disable all rs-232 interrupts */ + _regs->write(MCR, 0xb); /* out2, rts, and dtr enabled */ + _regs->write(FCR, 1); /* enable fifo */ + _regs->write(FCR, 7); /* clear rcv xmit fifo */ + _regs->write(FCR, 1); /* enable fifo */ + _regs->write(LCR, 0); /* clear line control register */ + + /* clearall interrupts */ + _regs->read(MSR); /* IRQID 0*/ + _regs->read(IIR); /* IRQID 1*/ + _regs->read(TRB); /* IRQID 2*/ + _regs->read(LSR); /* IRQID 3*/ + + while (_regs->read(LSR) & 1/*DATA READY*/) + _regs->read(TRB); + + return true; + } + + void Uart_16550::shutdown() + { + _regs->write(MCR, 6); + _regs->write(FCR, 0); + _regs->write(LCR, 0); + _regs->write(IER, 0); + } + + bool Uart_16550::change_mode(Transfer_mode m, Baud_rate r) + { + unsigned long old_lcr = _regs->read(LCR); + if(r != BAUD_NC) { + unsigned short divisor = _base_rate / r; + _regs->write(LCR, old_lcr | 0x80/*DLAB*/); + _regs->write(TRB, divisor & 0x0ff); /* BRD_LOW */ + _regs->write(IER, (divisor >> 8) & 0x0ff); /* BRD_HIGH */ + _regs->write(LCR, old_lcr); + } + if (m != MODE_NC) + _regs->write(LCR, m & 0x07f); + + return true; + } + + int Uart_16550::get_char(bool blocking) const + { + char old_ier, ch; + + if (!blocking && !char_avail()) + return -1; + + old_ier = _regs->read(IER); + _regs->write(IER, old_ier & ~0xf); + while (!char_avail()) + ; + ch = _regs->read(TRB); + _regs->write(IER, old_ier); + return ch; + } + + int Uart_16550::char_avail() const + { + return _regs->read(LSR) & 1; // DATA READY + } + + void Uart_16550::out_char(char c) const + { + write(&c, 1); + } + + int Uart_16550::write(char const *s, unsigned long count) const + { + /* disable uart irqs */ + char old_ier; + unsigned i; + old_ier = _regs->read(IER); + _regs->write(IER, old_ier & ~0x0f); + + /* transmission */ + for (i = 0; i < count; i++) { + while (!(_regs->read(LSR) & 0x20 /* THRE */)) + ; + _regs->write(TRB, s[i]); + } + + /* wait till everything is transmitted */ + while (!(_regs->read(LSR) & 0x40 /* TSRE */)) + ; + + _regs->write(IER, old_ier); + return count; + } +}; diff --git a/l4/pkg/drivers-frst/uart/src/uart_s3c2410.cc b/l4/pkg/drivers-frst/uart/src/uart_s3c2410.cc new file mode 100644 index 00000000..4748b002 --- /dev/null +++ b/l4/pkg/drivers-frst/uart/src/uart_s3c2410.cc @@ -0,0 +1,247 @@ +/* + * (c) 2009 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ +#include "uart_s3c2410.h" + +namespace L4 +{ + enum + { + Type_24xx, Type_64xx, Type_s5pv210, + }; + + enum + { + ULCON = 0x0, // line control register + UCON = 0x4, // control register + UFCON = 0x8, // FIFO control register + UMCON = 0xc, // modem control register + UTRSTAT = 0x10, // Tx/Rx status register + UERSTAT = 0x14, // Rx error status register + UFSTAT = 0x18, // FIFO status register + UMSTAT = 0x1c, // modem status register + UTXH = 0x20, // transmit buffer register (little endian, 0x23 for BE) + URXH = 0x24, // receive buffer register (little endian, 0x27 for BE) + UBRDIV = 0x28, // baud rate divisor register + // 64xx++ + UINTP = 0x30, // interrupt pending register + UINTSP = 0x34, // interrupt source pending register + UINTM = 0x38, // interrupt mask register + + + ULCON_8N1_MODE = 0x3, + + UCON_MODE_RECEIVE_IRQ_POLL = 1 << 0, + UCON_MODE_TRANSMIT_IRQ_POLL = 1 << 2, + UCON_SEND_BREAK_SIGNAL = 1 << 4, + UCON_LOOPBACK_MODE = 1 << 5, + UCON_RX_ERROR_STATUS_IRQ_EN = 1 << 6, + UCON_RX_TIME_OUT_EN = 1 << 7, + UCON_MODE = UCON_MODE_RECEIVE_IRQ_POLL + | UCON_MODE_TRANSMIT_IRQ_POLL + | UCON_RX_TIME_OUT_EN, + + UFCON_ENABLE = 1 << 0, // enable fifo + UFCON_RX_FIFO_RESET = 1 << 1, // Rx Fifo reset + UFCON_TX_FIFO_RESET = 1 << 2, // Tx Fifo reset + + UMCON_AFC = 1 << 4, + + UTRSTAT_Rx_RDY = 1 << 0, + UTRSTAT_Tx_RDY = 1 << 1, + + UINT_RXD = 1 << 0, + UINT_ERROR = 1 << 1, + UINT_TXD = 1 << 2, + UINT_MODEM = 1 << 3, + + // 2410 + UFSTAT_2410_Rx_COUNT_MASK = 0x00f, + UFSTAT_2410_Tx_COUNT_MASK = 0x0f0, + UFSTAT_2410_RxFULL = 0x100, + UFSTAT_2410_TxFULL = 0x200, + + // 64xx + UFSTAT_64XX_Rx_COUNT_MASK = 0x003f, + UFSTAT_64XX_Tx_COUNT_MASK = 0x3f00, + UFSTAT_64XX_RxFULL = 0x0040, + UFSTAT_64XX_TxFULL = 0x4000, + + // s5pv210 + UFSTAT_S5PV210_Rx_COUNT_MASK = 0x000000ff, + UFSTAT_S5PV210_Tx_COUNT_MASK = 0x00ff0000, + UFSTAT_S5PV210_RxFULL = 0x00000100, + UFSTAT_S5PV210_TxFULL = 0x01000000, + }; + + + void Uart_s3c::fifo_reset() + { + _regs->write(UFCON, UFCON_RX_FIFO_RESET | UFCON_TX_FIFO_RESET); + while (_regs->read(UFCON) & (UFCON_RX_FIFO_RESET | UFCON_TX_FIFO_RESET)) + ; + } + + + bool Uart_s3c::startup(Io_register_block const *regs) + { + _regs = regs; + + fifo_reset(); +#if 0 + _regs->write(UMCON, 0); +#endif + + _regs->write(ULCON, ULCON_8N1_MODE); + _regs->write(UCON, UCON_MODE); + _regs->write(UFCON, UFCON_ENABLE); + + switch (type()) + { + case Type_24xx: + break; + case Type_64xx: + case Type_s5pv210: + _regs->write(UINTM, ~UINT_RXD); // mask all but receive irq + _regs->write(UINTP, ~0); // clear all pending irqs + break; + } +#if 0 + _regs->write(UBRDIV, 0x23); +#endif + + return true; + } + + void Uart_s3c::shutdown() + { + // more + } + + bool Uart_s3c::change_mode(Transfer_mode, Baud_rate r) + { + if (r != 115200) + return false; + +#if 0 + _regs->write(ULCON, ULCON_8N1_MODE); + _regs->write(UCON, UCON_MODE); + _regs->write(UFCON, 1); + + _regs->write(UBRDIV, 0x23); +#endif + + return true; + } + + int Uart_s3c::get_char(bool blocking) const + { + while (!char_avail()) + if (!blocking) + return -1; + + _regs->read(UFCON); + int c = _regs->read(URXH) & 0xff; + ack_rx_irq(); + return c; + } + + int Uart_s3c::char_avail() const + { + return is_rx_fifo_non_empty(); + } + + void Uart_s3c::out_char(char c) const + { + wait_for_non_full_tx_fifo(); + _regs->write(UTXH, c); + } + + int Uart_s3c::write(char const *s, unsigned long count) const + { + unsigned long c = count; + while (c--) + out_char(*s++); + wait_for_empty_tx_fifo(); + + return count; + } + + // ----------------------- + + void Uart_s3c2410::wait_for_empty_tx_fifo() const + { + while (_regs->read(UFSTAT) & (UFSTAT_2410_Tx_COUNT_MASK | UFSTAT_2410_TxFULL)) + ; + } + + void Uart_s3c2410::wait_for_non_full_tx_fifo() const + { + while (_regs->read(UFSTAT) & UFSTAT_2410_TxFULL) + ; + } + + unsigned Uart_s3c2410::is_rx_fifo_non_empty() const + { + return _regs->read(UFSTAT) & (UFSTAT_2410_Rx_COUNT_MASK | UFSTAT_2410_RxFULL); + } + + void Uart_s3c2410::auto_flow_control(bool on) + { + _regs->write(UMCON, (_regs->read(UMCON) & ~UMCON_AFC) | (on ? UMCON_AFC : 0)); + } + + // ----------------------- + + void Uart_s3c64xx::wait_for_empty_tx_fifo() const + { + while (_regs->read(UFSTAT) & (UFSTAT_64XX_Tx_COUNT_MASK | UFSTAT_64XX_TxFULL)) + ; + } + + void Uart_s3c64xx::wait_for_non_full_tx_fifo() const + { + while (_regs->read(UFSTAT) & UFSTAT_64XX_TxFULL) + ; + } + + unsigned Uart_s3c64xx::is_rx_fifo_non_empty() const + { + return _regs->read(UFSTAT) & (UFSTAT_64XX_Rx_COUNT_MASK | UFSTAT_64XX_RxFULL); + } + + void Uart_s3c64xx::ack_rx_irq() const + { + _regs->write(UINTP, UINT_RXD); + } + + // ----------------------- + + void Uart_s5pv210::wait_for_empty_tx_fifo() const + { + while (_regs->read(UFSTAT) & (UFSTAT_S5PV210_Tx_COUNT_MASK | UFSTAT_S5PV210_TxFULL)) + ; + } + + void Uart_s5pv210::wait_for_non_full_tx_fifo() const + { + while (_regs->read(UFSTAT) & UFSTAT_S5PV210_TxFULL) + ; + } + + unsigned Uart_s5pv210::is_rx_fifo_non_empty() const + { + return _regs->read(UFSTAT) & (UFSTAT_S5PV210_Rx_COUNT_MASK | UFSTAT_S5PV210_RxFULL); + } + + void Uart_s5pv210::ack_rx_irq() const + { + _regs->write(UINTP, UINT_RXD); + } +}; + diff --git a/l4/pkg/drivers-frst/uart/src/uart_sa1000.cc b/l4/pkg/drivers-frst/uart/src/uart_sa1000.cc new file mode 100644 index 00000000..5aed5bad --- /dev/null +++ b/l4/pkg/drivers-frst/uart/src/uart_sa1000.cc @@ -0,0 +1,189 @@ +/*! + * \file uart_sa1000.cc + * \brief SA1000 Uart + * + * \date 2008-01-02 + * \author Adam Lackorznynski + * Alexander Warg + * + */ +/* + * (c) 2008-2009 Author(s) + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ + +#include "uart_sa1000.h" + +namespace L4 +{ + enum { + PAR_NONE = 0x00, + PAR_EVEN = 0x03, + PAR_ODD = 0x01, + DAT_5 = (unsigned)-1, + DAT_6 = (unsigned)-1, + DAT_7 = 0x00, + DAT_8 = 0x08, + STOP_1 = 0x00, + STOP_2 = 0x04, + + MODE_8N1 = PAR_NONE | DAT_8 | STOP_1, + MODE_7E1 = PAR_EVEN | DAT_7 | STOP_1, + + // these two values are to leave either mode + // or baud rate unchanged on a call to change_mode + MODE_NC = 0x1000000, + BAUD_NC = 0x1000000, + }; + + enum { + UTCR0 = 0x00, + UTCR1 = 0x04, + UTCR2 = 0x08, + UTCR3 = 0x0c, + UTCR4 = 0x10, + UTDR = 0x14, + UTSR0 = 0x1c, + UTSR1 = 0x20, + + + UTCR0_PE = 0x01, + UTCR0_OES = 0x02, + UTCR0_SBS = 0x04, + UTCR0_DSS = 0x08, + UTCR0_SCE = 0x10, + UTCR0_RCE = 0x20, + UTCR0_TCE = 0x40, + + UTCR3_RXE = 0x01, + UTCR3_TXE = 0x02, + UTCR3_BRK = 0x04, + UTCR3_RIE = 0x08, + UTCR3_TIE = 0x10, + UTCR3_LBM = 0x20, + + + UTSR0_TFS = 0x01, + UTSR0_RFS = 0x02, + UTSR0_RID = 0x04, + UTSR0_RBB = 0x08, + UTSR0_REB = 0x10, + UTSR0_EIF = 0x20, + + UTSR1_TBY = 0x01, + UTSR1_RNE = 0x02, + UTSR1_TNF = 0x04, + UTSR1_PRE = 0x08, + UTSR1_FRE = 0x10, + UTSR1_ROR = 0x20, + + UARTCLK = 3686400, + }; + + bool Uart_sa1000::startup(Io_register_block const *regs) + { + _regs = regs; + _regs->write(UTSR0, ~0UL); // clear pending status bits + _regs->write(UTCR3, UTCR3_RXE | UTCR3_TXE); //enable transmitter and receiver + return true; + } + + void Uart_sa1000::shutdown() + { + _regs->write(UTCR3, 0); + } + + bool Uart_sa1000::change_mode(Transfer_mode m, Baud_rate baud) + { + unsigned old_utcr3, quot; + //proc_status st; + + if (baud == (Baud_rate)-1) + return false; + if (baud != BAUD_NC && (baud>115200 || baud<96)) + return false; + if (m == (Transfer_mode)-1) + return false; + + //st = proc_cli_save(); + old_utcr3 = _regs->read(UTCR3); + _regs->write(UTCR3, (old_utcr3 & ~(UTCR3_RIE|UTCR3_TIE))); + //proc_sti_restore(st); + + while (_regs->read(UTSR1) & UTSR1_TBY) + ; + + /* disable all */ + _regs->write(UTCR3, 0); + + /* set parity, data size, and stop bits */ + if(m != MODE_NC) + _regs->write(UTCR0, m & 0x0ff); + + /* set baud rate */ + if(baud!=BAUD_NC) + { + quot = (UARTCLK / (16*baud)) -1; + _regs->write(UTCR1, (quot & 0xf00) >> 8); + _regs->write(UTCR2, quot & 0x0ff); + } + + _regs->write(UTSR0, (unsigned)-1); + _regs->write(UTCR3, old_utcr3); + return true; + + } + + int Uart_sa1000::get_char(bool blocking) const + { + int ch; + unsigned long old_utcr3 = _regs->read(UTCR3); + _regs->write(UTCR3, old_utcr3 & ~(UTCR3_RIE|UTCR3_TIE)); + + while (!(_regs->read(UTSR1) & UTSR1_RNE)) + if(!blocking) + return -1; + + ch = _regs->read(UTDR); + _regs->write(UTCR3, old_utcr3); + return ch; + + } + + int Uart_sa1000::char_avail() const + { + return !!(_regs->read(UTSR1) & UTSR1_RNE); + } + + void Uart_sa1000::out_char(char c) const + { + // do UTCR3 thing here as well? + while(!(_regs->read(UTSR1) & UTSR1_TNF)) + ; + _regs->write(UTDR, c); + } + + int Uart_sa1000::write(char const *s, unsigned long count) const + { + unsigned old_utcr3; + unsigned i; + + old_utcr3 = _regs->read(UTCR3); + _regs->write(UTCR3, (old_utcr3 & ~(UTCR3_RIE | UTCR3_TIE)) | UTCR3_TXE ); + + /* transmission */ + for (i = 0; i < count; i++) + out_char(s[i]); + + /* wait till everything is transmitted */ + while (_regs->read(UTSR1) & UTSR1_TBY) + ; + + _regs->write(UTCR3, old_utcr3); + return count; + } +}; diff --git a/l4/pkg/l4sys/Control b/l4/pkg/l4sys/Control new file mode 100644 index 00000000..5a42faf6 --- /dev/null +++ b/l4/pkg/l4sys/Control @@ -0,0 +1,3 @@ +provides: l4sys l4sys-l4x +requires: ldscripts libgcc-pure +Maintainer: adam@os.inf.tu-dresden.de, warg@os.inf.tu-dresden.de diff --git a/l4/pkg/l4sys/LEGAL b/l4/pkg/l4sys/LEGAL new file mode 100644 index 00000000..1861c4cd --- /dev/null +++ b/l4/pkg/l4sys/LEGAL @@ -0,0 +1,11 @@ +# Format: (all on one line) +# Source file : Copyright Owner(s) : License +# Please use "TUD" when referring to TU Dresden. +# If sole owner is TUD, the license field defaults to GPL and can be +# left empty. +# Source-file spec can be a directory name or a wildcard like "src/*.c". +doc : TUD +include : TUD +include-x2 : Universität Karlsruhe +lib/src/L4API-l4x2 : Universität Karlsruhe +lib : TUD diff --git a/l4/pkg/l4sys/Makefile b/l4/pkg/l4sys/Makefile new file mode 100644 index 00000000..842da05b --- /dev/null +++ b/l4/pkg/l4sys/Makefile @@ -0,0 +1,6 @@ +PKGDIR = . +L4DIR ?= $(PKGDIR)/../.. + +TARGET = include lib doc + +include $(L4DIR)/mk/subdir.mk diff --git a/l4/pkg/l4sys/README b/l4/pkg/l4sys/README new file mode 100644 index 00000000..d4e68deb --- /dev/null +++ b/l4/pkg/l4sys/README @@ -0,0 +1,10 @@ +Basic L4 IPC/Syscall Bindings and Type Definitions. + +This package defines the application binary interface (ABI) to the L4 kernel. +Currently there are two versions supported: Version 2 as originally implemented +by Jochen Liedtke and Version X.0 as defined in the appropriate specification +and implemented by the L4Ka Hazelnut kernel. Note that the latter interface +is emulated using a few assembler instructions. This makes it possible to use +the same source code for the two different versions. To support plain X.0 +functionality we have to create additional IPC bindings which take three +DWord arguments to be transferred. diff --git a/l4/pkg/l4sys/doc/files.cfg b/l4/pkg/l4sys/doc/files.cfg new file mode 100644 index 00000000..72c8b55d --- /dev/null +++ b/l4/pkg/l4sys/doc/files.cfg @@ -0,0 +1,3 @@ +INPUT += $(L4DIR)/pkg/l4sys/doc/l4sys-l4f-groups.dox \ + l4/sys l4f/l4/sys arm/l4f/l4/sys arm/l4/sys amd64/l4f/l4/sys \ + amd64/l4/sys x86/l4f/l4/sys x86/l4/sys diff --git a/l4/pkg/l4sys/doc/l4sys-l4f-groups.dox b/l4/pkg/l4sys/doc/l4sys-l4f-groups.dox new file mode 100644 index 00000000..0c563e95 --- /dev/null +++ b/l4/pkg/l4sys/doc/l4sys-l4f-groups.dox @@ -0,0 +1,77 @@ +// vi:ft=c +/* -*- c -*- */ + +/** + * \defgroup l4_api Base API + * \brief Interfaces for all kinds of base functionality. + * + * Some notes on Inter Process Communication (IPC) + * + * IPC in L4 is always synchronous and unbuffered: a message is + * transferred from the sender to the recipient if and only if the + * recipient has invoked a corresponding IPC operation. The sender blocks + * until this happens or a timeout specified by the sender elapsed + * without the destination becoming ready to receive. + */ + +/** + * \defgroup l4_kernel_object_gate_api IPC-Gate API + * \ingroup l4_kernel_object_api + * + * \brief Secure comminication object. + * + * IPC-Gate objects provide a means to establish secure communication channels + * to L4 Threads (\ref l4_thread_api). An IPC-Gate object can be created using + * a \ref l4_factory_api (l4_factory_create_gate()) and get assigned a specific + * L4 thread and a \em label as protected payload. The \em label has the size + * of one machine word and can only be seen by the Task running the thread that + * is assigned of the IPC-gate. The \em label is received as part of the IPC + * message. The \em label can thus be used to securely identify the IPC-gate + * that was used to send a message. + * + * An IPC-gate is usually used to represent an user-level object and may be + * the address of the data structure for the object in the server task. + * + * With client privileges an IPC-gate does not provide any direct API and + * thus an IPC-gate kernel object cannot be modified by invocations. Each + * invocation of an IPC-gate kernel object is translated into an IPC message + * to the assigned thread. + * + * \see \ref l4_ipc_api + */ + + +/* + * IPC can be used to copy data as well as to map or grant flexpages from + * the sender to the recipient. + */ + +/** + * \defgroup l4sys_defines Basic Macros + * \ingroup l4_api + * \brief L4 standard macros for header files, function definitions, + * and public APIs etc. + */ + + +/***************************************************************************** + *** System calls + *****************************************************************************/ + +/** + * \brief L4 low-level kernel interface. + */ +namespace L4 { }; + + +/** + * \defgroup api_calls_fiasco Fiasco extensions + * \ingroup l4_api + * \brief Kernel debugger extensions of the Fiasco L4 implementation + */ + +/** + * \defgroup api_calls_rt_sched Fiasco real time scheduling extensions + * \ingroup api_calls_fiasco + * \brief Real time scheduling extension for the Fiasco L4 implementation + */ diff --git a/l4/pkg/l4sys/include/ARCH-amd64/L4API-l4f/__kernel_object_impl.h b/l4/pkg/l4sys/include/ARCH-amd64/L4API-l4f/__kernel_object_impl.h new file mode 100644 index 00000000..0e04e7c2 --- /dev/null +++ b/l4/pkg/l4sys/include/ARCH-amd64/L4API-l4f/__kernel_object_impl.h @@ -0,0 +1,53 @@ +/** + * \file + * \brief Low-level kernel functions for AMD64 + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#pragma once + +#include +# define L4_SYSCALL_debugger "int $0x32 \n\t" +#ifndef L4_SYSCALL +# define L4_SYSCALL(name) L4_SYSCALL_ ## name ///< syscall entry +#endif + + +L4_INLINE l4_msgtag_t +l4_invoke_debugger(l4_cap_idx_t obj, l4_msgtag_t tag, l4_utcb_t *utcb) L4_NOTHROW +{ + l4_umword_t dummy1, dummy2; + + __asm__ __volatile__( + L4_SYSCALL(debugger) + : + "=d" (dummy1), + "=a" (tag.raw), + "=D" (dummy2) + : + "d" (obj), + "a" (tag.raw), + "D" (utcb) + : + "memory", "cc" + ); + + return tag; +} + diff --git a/l4/pkg/l4sys/include/ARCH-amd64/L4API-l4f/ipc-l42-gcc3.h b/l4/pkg/l4sys/include/ARCH-amd64/L4API-l4f/ipc-l42-gcc3.h new file mode 100644 index 00000000..b7fa64aa --- /dev/null +++ b/l4/pkg/l4sys/include/ARCH-amd64/L4API-l4f/ipc-l42-gcc3.h @@ -0,0 +1,255 @@ +/** + * \file + * \brief IPC system calls for AMD64 + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg , + * Torsten Frenzel + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#pragma once + +#include + +L4_INLINE l4_msgtag_t +l4_ipc_call(l4_cap_idx_t dest, l4_utcb_t *utcb, + l4_msgtag_t snd_tag, + l4_timeout_t timeout) L4_NOTHROW +{ + l4_umword_t dummy1, dummy2, dummy3; + l4_msgtag_t rtag; + (void)utcb; + __asm__ __volatile__ + (L4_ENTER_KERNEL + : + "=d" (dummy3), + "=D" (dummy1), + "=c" (timeout), + "=S" (dummy2), + "=a" (rtag.raw) + : + "S" (0), + "c" (timeout), + "d" (dest | L4_SYSF_CALL), + "a" (snd_tag.raw) + : + "memory", "cc" + ); + return rtag; +} + + +L4_INLINE l4_msgtag_t +l4_ipc_reply_and_wait(l4_utcb_t *utcb, l4_msgtag_t tag, + l4_umword_t *label, + l4_timeout_t timeout) L4_NOTHROW +{ + l4_umword_t dummy, dummy1, dummy2; + l4_msgtag_t rtag; + (void)utcb; + __asm__ __volatile__ + (L4_ENTER_KERNEL + : + "=d" (dummy2), + "=S" (*label), + "=c" (dummy1), + "=D" (dummy), + "=a" (rtag.raw) + : + "S" (0), + "c" (timeout), + "a" (tag.raw), + "d" (L4_INVALID_CAP | L4_SYSF_REPLY_AND_WAIT) + : + "memory", "cc" + ); + return rtag; +} + + +L4_INLINE l4_msgtag_t +l4_ipc_send_and_wait(l4_cap_idx_t dest, l4_utcb_t *utcb, + l4_msgtag_t tag, + l4_umword_t *label, + l4_timeout_t timeout) L4_NOTHROW +{ + l4_umword_t dummy, dummy1, dummy2; + l4_msgtag_t rtag; + (void)utcb; + __asm__ __volatile__ + (L4_ENTER_KERNEL + : + "=d" (dummy2), + "=S" (*label), + "=c" (dummy1), + "=D" (dummy), + "=a" (rtag.raw) + : + "S" (0), + "c" (timeout), + "a" (tag.raw), + "d" (dest | L4_SYSF_SEND_AND_WAIT) + : + "memory", "cc" + ); + return rtag; +} + + +L4_INLINE l4_msgtag_t +l4_ipc_send(l4_cap_idx_t dest, l4_utcb_t *utcb, + l4_msgtag_t tag, + l4_timeout_t timeout) L4_NOTHROW +{ + l4_umword_t dummy1, dummy4, dummy5; + l4_msgtag_t rtag; + (void)utcb; + + __asm__ __volatile__ + (L4_ENTER_KERNEL + : + "=d" (dummy1), + "=a" (rtag.raw), + "=c" (timeout.raw), + "=S" (dummy4), + "=D" (dummy5) + : + "S" (0), + "c" (timeout), + "d" (dest | L4_SYSF_SEND), + "a" (tag.raw) + : "memory" , "cc" + ); + return rtag; +} + + +L4_INLINE l4_msgtag_t +l4_ipc_wait(l4_utcb_t *utcb, l4_umword_t *label, + l4_timeout_t timeout) L4_NOTHROW +{ + l4_umword_t dummy, dummy2, dummy1; + l4_msgtag_t rtag; + (void)utcb; + + __asm__ __volatile__ + (L4_ENTER_KERNEL + : + "=d" (dummy1), + "=S" (*label), + "=c" (dummy), + "=D" (dummy2), + "=a" (rtag.raw) + : + "c" (timeout), + "d" (L4_INVALID_CAP | L4_SYSF_WAIT), + "a" (0), + "S" (0) + : + "memory", "cc" + ); + return rtag; +} + +#if 0 +L4_INLINE int +l4_ipc_wait_next_period(l4_threadid_t *src, + l4_timeout_t timeout, + l4_msgdope_t *result, + l4_utcb_t *utcb) +{ + unsigned dummy, tag; + + __asm__ __volatile__ + ("pushl %%ebp \n\t" /* save ebp, no memory references + ("m") after this point */ + "movl %[msg_desc], %%ebp \n\t" /* rcv_msg */ + IPC_SYSENTER + "popl %%ebp \n\t" /* restore ebp, no memory + references ("m") before this point */ + : + "=a" (*result), + "=d" (*rcv_dword0), + "=b" (*rcv_dword1), + "=c" (dummy), + "=S" (src->raw), + "=D" (tag) + : + "a" (L4_IPC_NIL_DESCRIPTOR), + "c" (timeout), + [msg_desc] "ir"(((int)rcv_msg) | L4_IPC_OPEN_IPC), + "D" (L4_IPC_FLAG_NEXT_PERIOD) /* no absolute timeout */ + ); + return L4_IPC_ERROR(*result); +} +#endif + +L4_INLINE l4_msgtag_t +l4_ipc_receive(l4_cap_idx_t rcv, l4_utcb_t *utcb, + l4_timeout_t timeout) L4_NOTHROW +{ + l4_umword_t dummy, dummy1, dummy2; + l4_msgtag_t rtag; + (void)utcb; + + __asm__ __volatile__ + (L4_ENTER_KERNEL + : + "=d" (dummy2), + "=S" (dummy1), + "=c" (dummy), + "=a" (rtag.raw) + : + "c" (timeout), + "S" (0), + "a" (0), + "d" (rcv | L4_SYSF_RECV) + : + "memory", "cc" + ); + return rtag; +} + +L4_INLINE l4_msgtag_t +l4_ipc(l4_cap_idx_t dest, l4_utcb_t *utcb, + l4_umword_t flags, + l4_umword_t slabel, + l4_msgtag_t tag, + l4_umword_t *rlabel, + l4_timeout_t timeout) L4_NOTHROW +{ + l4_umword_t dummy, dummy1, dummy2; + l4_msgtag_t rtag; + (void)utcb; + __asm__ __volatile__ + (L4_ENTER_KERNEL + : + "=d" (dummy2), + "=S" (*rlabel), + "=c" (dummy1), + "=D" (dummy), + "=a" (rtag.raw) + : + "S" (slabel), + "c" (timeout), + "a" (tag.raw), + "d" (dest | flags) + : + "memory", "cc" + ); + return rtag; +} diff --git a/l4/pkg/l4sys/include/ARCH-amd64/L4API-l4f/ipc.h b/l4/pkg/l4sys/include/ARCH-amd64/L4API-l4f/ipc.h new file mode 100644 index 00000000..e698c1fb --- /dev/null +++ b/l4/pkg/l4sys/include/ARCH-amd64/L4API-l4f/ipc.h @@ -0,0 +1,52 @@ +/** + * \file + * \brief L4 IPC System Calls, amd64 + * \ingroup api_calls + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg , + * Frank Mehnert , + * Torsten Frenzel + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#ifndef __L4SYS__INCLUDE__ARCH_AMD64__L4API_L4F__IPC_H__ +#define __L4SYS__INCLUDE__ARCH_AMD64__L4API_L4F__IPC_H__ + +#include + +#define L4_IPC_IOMAPMSG_BASE 0xfffffffff0000000 ///< I/O mapmsg base +#define L4_IPC_CAPMAPMSG_BASE 0xfffffffff0000100 ///< Capability mapmsg base + +#include_next + +#include + +#define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__) ///< GCC in a single figure (e.g. 402 for gcc-4.2) + +#ifdef PROFILE +# include "ipc-l42-profile.h" +#else +# if GCC_VERSION < 303 +# error gcc >= 3.3 required +# else +# include "ipc-l42-gcc3.h" +# endif +#endif + +#include + +#endif /* ! __L4SYS__INCLUDE__ARCH_AMD64__L4API_L4F__IPC_H__ */ diff --git a/l4/pkg/l4sys/include/ARCH-amd64/L4API-l4f/ktrace.h b/l4/pkg/l4sys/include/ARCH-amd64/L4API-l4f/ktrace.h new file mode 100644 index 00000000..5b8fc31d --- /dev/null +++ b/l4/pkg/l4sys/include/ARCH-amd64/L4API-l4f/ktrace.h @@ -0,0 +1,255 @@ +/** + * \file + * \brief L4 kernel event tracing + * \ingroup api_calls + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Torsten Frenzel + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#ifndef __L4_KTRACE_H__ +#define __L4_KTRACE_H__ + +#include + +#define LOG_EVENT_CONTEXT_SWITCH 0 /**< Event: context switch + ** \ingroup api_calls_fiasco + **/ +#define LOG_EVENT_IPC_SHORTCUT 1 /**< Event: IPC shortcut + ** \ingroup api_calls_fiasco + **/ +#define LOG_EVENT_IRQ_RAISED 2 /**< Event: IRQ occurred + ** \ingroup api_calls_fiasco + **/ +#define LOG_EVENT_TIMER_IRQ 3 /**< Event: Timer IRQ occurred + ** \ingroup api_calls_fiasco + **/ +#define LOG_EVENT_THREAD_EX_REGS 4 /**< Event: thread_ex_regs + ** \ingroup api_calls_fiasco + **/ + +#define LOG_EVENT_MAX_EVENTS 16 /**< Maximum number of events + ** \ingroup api_calls_fiasco + **/ + +/** + * Tracebuffer status. + * \ingroup api_calls_fiasco + */ +typedef struct +{ + /// Address of tracebuffer 0 + l4_umword_t tracebuffer0; + /// Size of tracebuffer 0 + l4_umword_t size0; + /// Version number of tracebuffer 0 (incremented if tb0 overruns) + l4_umword_t version0; + /// Address of tracebuffer 1 (there is no gap between tb0 and tb1) + l4_umword_t tracebuffer1; + /// Size of tracebuffer 1 (same as tb0) + l4_umword_t size1; + /// Version number of tracebuffer 1 (incremented if tb1 overruns) + l4_umword_t version1; + /// Available LOG events + l4_umword_t logevents[LOG_EVENT_MAX_EVENTS]; + + /// Scaler used for translation of CPU cycles to nano seconds + l4_umword_t scaler_tsc_to_ns; + /// Scaler used for translation of CPU cycles to micro seconds + l4_umword_t scaler_tsc_to_us; + /// Scaler used for translation of nano seconds to CPU cycles + l4_umword_t scaler_ns_to_tsc; + + /// Number of context switches (intra AS or inter AS) + l4_umword_t cnt_context_switch; + /// Number of inter AS context switches + l4_umword_t cnt_addr_space_switch; + /// How often was the IPC shortcut not taken + l4_umword_t cnt_shortcut_failed; + /// How often was the IPC shortcut taken + l4_umword_t cnt_shortcut_success; + /// Number of hardware interrupts (without kernel scheduling interrupt) + l4_umword_t cnt_irq; + /// Number of long IPCs + l4_umword_t cnt_ipc_long; + /// Number of page faults + l4_umword_t cnt_page_fault; + /// Number of faults (application runs at IOPL 0 and tries to execute + /// cli, sti, in, or out but does not have a sufficient right in the I/O bitmap) + l4_umword_t cnt_io_fault; + /// Number of tasks created + l4_umword_t cnt_task_create; + /// Number of reschedules + l4_umword_t schedule; + +} l4_tracebuffer_status_t; + +/** + * Return tracebuffer status. + * \ingroup api_calls_fiasco + * + * \return Pointer to tracebuffer status struct. + */ +L4_INLINE l4_tracebuffer_status_t * +fiasco_tbuf_get_status(void); + +/** + * Return the physical address of the tracebuffer status struct. + * \ingroup api_calls_fiasco + * + * \return physical address of status struct. + */ +L4_INLINE l4_addr_t +fiasco_tbuf_get_status_phys(void); + +/** + * Create new tracebuffer entry with describing \. + * \ingroup api_calls_fiasco + * + * \param text Logging text + * \return Pointer to tracebuffer entry + */ +L4_INLINE l4_umword_t +fiasco_tbuf_log(const char *text); + +/** + * Create new tracebuffer entry with describing \ and three additional + * values. + * \ingroup api_calls_fiasco + * + * \param text Logging text + * \param v1 first value + * \param v2 second value + * \param v3 third value + * \return Pointer to tracebuffer entry + */ +L4_INLINE l4_umword_t +fiasco_tbuf_log_3val(const char *text, unsigned v1, unsigned v2, unsigned v3); + +/** + * Create new tracebuffer entry with binary data. + * \ingroup api_calls_fiasco + * + * \param data binary data + * \return Pointer to tracebuffer entry + */ +L4_INLINE l4_umword_t +fiasco_tbuf_log_binary(const unsigned char *data); + +/** + * Clear tracebuffer. + * \ingroup api_calls_fiasco + */ +L4_INLINE void +fiasco_tbuf_clear(void); + +/** + * Dump tracebuffer to kernel console. + * \ingroup api_calls_fiasco + */ +L4_INLINE void +fiasco_tbuf_dump(void); + +/** + * Disable the kernel scheduling timer. + */ +L4_INLINE void +fiasco_timer_disable(void); + +/** + * Enable the kernel scheduling timer (after it was disabled with + * fiasco_timer_disable). + */ +L4_INLINE void +fiasco_timer_enable(void); + +/***************************************************************************** + *** Implementation + *****************************************************************************/ + +L4_INLINE l4_tracebuffer_status_t * +fiasco_tbuf_get_status(void) +{ + l4_tracebuffer_status_t *tbuf; + asm("int $3; cmpb $29, %%al" : "=a" (tbuf) : "0" (0)); + return tbuf; +} + +L4_INLINE l4_addr_t +fiasco_tbuf_get_status_phys(void) +{ + l4_addr_t tbuf_phys; + asm("int $3; cmpb $29, %%al" : "=a" (tbuf_phys) : "0" (5)); + return tbuf_phys; +} + +L4_INLINE l4_umword_t +fiasco_tbuf_log(const char *text) +{ + l4_umword_t offset; + asm volatile("int $3; cmpb $29, %%al" + : "=a" (offset) + : "a" (1), "d" (text)); + return offset; +} + +L4_INLINE l4_umword_t +fiasco_tbuf_log_3val(const char *text, unsigned v1, unsigned v2, unsigned v3) +{ + l4_umword_t offset; + asm volatile("int $3; cmpb $29, %%al" + : "=a" (offset) + : "a" (4), "d" (text), "c" (v1), "S" (v2), "D" (v3)); + return offset; +} + +L4_INLINE void +fiasco_tbuf_clear(void) +{ + asm volatile("int $3; cmpb $29, %%al" : : "a" (2)); +} + +L4_INLINE void +fiasco_tbuf_dump(void) +{ + asm volatile("int $3; cmpb $29, %%al" : : "a" (3)); +} + +L4_INLINE void +fiasco_timer_disable(void) +{ + asm volatile("int $3; cmpb $29, %%al" : : "a" (6)); +} + +L4_INLINE void +fiasco_timer_enable(void) +{ + asm volatile("int $3; cmpb $29, %%al" : : "a" (7)); +} + +L4_INLINE l4_umword_t +fiasco_tbuf_log_binary(const unsigned char *data) +{ + l4_umword_t offset; + asm volatile("int $3; cmpb $29, %%al" + : "=a" (offset) + : "a" (8), "d" (data)); + return offset; +} + +#endif + diff --git a/l4/pkg/l4sys/include/ARCH-amd64/L4API-l4f/segment.h b/l4/pkg/l4sys/include/ARCH-amd64/L4API-l4f/segment.h new file mode 100644 index 00000000..cc78e489 --- /dev/null +++ b/l4/pkg/l4sys/include/ARCH-amd64/L4API-l4f/segment.h @@ -0,0 +1,50 @@ +#include_next + +/** + * \file + * \brief l4f specific fs/gs manipulation + * \ingroup api_calls_fiasco + */ +/* + * (c) 2011 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#ifndef __L4_SYS__ARCH_AMD64__L4API_L4F__SEGMENT_H__ +#define __L4_SYS__ARCH_AMD64__L4API_L4F__SEGMENT_H__ + +#include + +/***************************************************************************** + *** Implementation + *****************************************************************************/ + +L4_INLINE long +fiasco_amd64_set_fs(l4_cap_idx_t thread, l4_umword_t base, l4_utcb_t *utcb) +{ + l4_utcb_mr_u(utcb)->mr[0] = L4_THREAD_SET_FS_AMD64_OP; + l4_utcb_mr_u(utcb)->mr[1] = base; + return l4_error_u(l4_ipc_call(thread, utcb, l4_msgtag(L4_PROTO_THREAD, 2, 0, 0), L4_IPC_NEVER), utcb); +} + +L4_INLINE long +fiasco_gdt_set(l4_cap_idx_t thread, void *desc, unsigned int size, + unsigned int entry_number_start, l4_utcb_t *utcb) +{ + (void)thread; (void)desc; (void)size; (void)entry_number_start; (void)utcb; + return -L4_ENOSYS; +} + +#endif /* ! __L4_SYS__ARCH_X86__L4API_L4F__SEGMENT_H__ */ diff --git a/l4/pkg/l4sys/include/ARCH-amd64/L4API-l4f/types.h b/l4/pkg/l4sys/include/ARCH-amd64/L4API-l4f/types.h new file mode 100644 index 00000000..80d5f33c --- /dev/null +++ b/l4/pkg/l4sys/include/ARCH-amd64/L4API-l4f/types.h @@ -0,0 +1,35 @@ +/** + * \file + * \brief L4 kernel API type definitions + * \ingroup l4_api + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg , + * Torsten Frenzel + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#pragma once + +#include +#include +#include +#include_next + +#include + +#include + diff --git a/l4/pkg/l4sys/include/ARCH-amd64/__vcpu-arch.h b/l4/pkg/l4sys/include/ARCH-amd64/__vcpu-arch.h new file mode 100644 index 00000000..e47f30e7 --- /dev/null +++ b/l4/pkg/l4sys/include/ARCH-amd64/__vcpu-arch.h @@ -0,0 +1,73 @@ +/* + * (c) 2009 Adam Lackorzynski , + * Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#pragma once + +#include + +/** + * \brief vCPU registers. + * \ingroup l4_vcpu_api + */ +typedef struct l4_vcpu_regs_t +{ +#if 0 + l4_umword_t es; /**< es register */ + l4_umword_t ds; /**< ds register */ + l4_umword_t gs; /**< gs register */ + l4_umword_t fs; /**< fs register */ +#endif + l4_umword_t r15; /**< r15 register */ + l4_umword_t r14; /**< r14 register */ + l4_umword_t r13; /**< r13 register */ + l4_umword_t r12; /**< r12 register */ + l4_umword_t r11; /**< r11 register */ + l4_umword_t r10; /**< r10 register */ + l4_umword_t r9; /**< r9 register */ + l4_umword_t r8; /**< r8 reigster */ + + l4_umword_t di; /**< rdi register */ + l4_umword_t si; /**< rsi register */ + l4_umword_t bp; /**< rbp register */ + l4_umword_t pfa; /**< page fault address */ + l4_umword_t bx; /**< rbx register */ + l4_umword_t dx; /**< rdx register */ + l4_umword_t cx; /**< rcx register */ + l4_umword_t ax; /**< rax register */ + + l4_umword_t trapno; /**< trap number */ + l4_umword_t err; /**< error code */ + + l4_umword_t ip; /**< instruction pointer */ + l4_umword_t dummy1; /**< dummy \internal */ + l4_umword_t flags; /**< eflags */ + l4_umword_t sp; /**< stack pointer */ + l4_umword_t ss; +} l4_vcpu_regs_t; + +/** + * \brief vCPU message registers. + * \ingroup l4_vcpu_api + */ +typedef struct l4_vcpu_ipc_regs_t +{ + l4_umword_t _res[10]; + l4_umword_t label; + l4_umword_t _res2[3]; + l4_msgtag_t tag; +} l4_vcpu_ipc_regs_t; diff --git a/l4/pkg/l4sys/include/ARCH-amd64/cache.h b/l4/pkg/l4sys/include/ARCH-amd64/cache.h new file mode 100644 index 00000000..e1429d47 --- /dev/null +++ b/l4/pkg/l4sys/include/ARCH-amd64/cache.h @@ -0,0 +1,67 @@ +/** + * \file + * \brief Cache functions + */ +/* + * (c) 2008-2009 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#ifndef __L4SYS__INCLUDE__ARCH_AMD64__CACHE_H__ +#define __L4SYS__INCLUDE__ARCH_AMD64__CACHE_H__ + +#include_next + +L4_INLINE void +l4_cache_clean_data(unsigned long start, + unsigned long end) L4_NOTHROW +{ + (void)start; (void)end; +} + +L4_INLINE void +l4_cache_flush_data(unsigned long start, + unsigned long end) L4_NOTHROW +{ + (void)start; (void)end; +} + +L4_INLINE void +l4_cache_inv_data(unsigned long start, + unsigned long end) L4_NOTHROW +{ + (void)start; (void)end; +} + +L4_INLINE void +l4_cache_coherent(unsigned long start, + unsigned long end) L4_NOTHROW +{ + (void)start; (void)end; +} + +L4_INLINE void +l4_cache_dma_coherent(unsigned long start, + unsigned long end) L4_NOTHROW +{ + (void)start; (void)end; +} + +L4_INLINE void +l4_cache_dma_coherent_full(void) L4_NOTHROW +{ +} + +#endif /* ! __L4SYS__INCLUDE__ARCH_AMD64__CACHE_H__ */ diff --git a/l4/pkg/l4sys/include/ARCH-amd64/consts.h b/l4/pkg/l4sys/include/ARCH-amd64/consts.h new file mode 100644 index 00000000..aa63367c --- /dev/null +++ b/l4/pkg/l4sys/include/ARCH-amd64/consts.h @@ -0,0 +1,45 @@ +/*****************************************************************************/ +/** + * \file + * \brief Common L4 constants, amd64 version. + * \ingroup l4_api + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg , + * Björn Döbel , + * Torsten Frenzel + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +/*****************************************************************************/ +#ifndef __L4SYS__INCLUDE__ARCH_AMD64__CONSTS_H__ +#define __L4SYS__INCLUDE__ARCH_AMD64__CONSTS_H__ + +/** + * Size of a page, log2-based. + * \ingroup l4_memory_api + */ +#define L4_PAGESHIFT 12 + +/** + * Size of a large page, log2-based. + * \ingroup l4_memory_api + */ +#define L4_SUPERPAGESHIFT 21 + +#include_next + +#endif /* ! __L4SYS__INCLUDE__ARCH_AMD64__CONSTS_H__ */ diff --git a/l4/pkg/l4sys/include/ARCH-amd64/ipc-invoke.h b/l4/pkg/l4sys/include/ARCH-amd64/ipc-invoke.h new file mode 100644 index 00000000..709fb048 --- /dev/null +++ b/l4/pkg/l4sys/include/ARCH-amd64/ipc-invoke.h @@ -0,0 +1,77 @@ +/** + * \file + * \brief L4 IPC System Call Invoking in Assembler. + * \ingroup api_calls + * + * This file can also be used in asm-files, so don't include C statements. + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg , + * Torsten Frenzel + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#pragma once + +/* + * Some words about the sysenter entry frame: Since the sysenter instruction + * automatically reloads the instruction pointer (eip) and the stack pointer + * (esp) after kernel entry, we have to save both registers preliminary to + * that instruction. We use ecx to store the user-level esp and save eip onto + * the stack. The ecx register contains the IPC timeout and has to be saved + * onto the stack, too. The ebp register is saved for compatibility reasons + * with the Hazelnut kernel. Both the esp and the ss register are also pushed + * onto the stack to be able to return using the "lret" instruction from the + * sysexit trampoline page if Small Address Spaces are enabled. + */ + +# ifndef L4F_IPC_SYSENTER + +/** Kernel entry code for inline assembly. \internal */ +# define IPC_SYSENTER "int $0x30 \n\t" +/** Kernel entry code for assembler code. \internal */ +# define IPC_SYSENTER_ASM int $0x30; + +# else +# error No pushs allowed because of red-zone +# ifdef __PIC__ +# error no PIC support for AMD64 +# else +# define IPC_SYSENTER \ + "push %%rcx \n\t" \ + "push %%r11 \n\t" \ + "push %%r15 \n\t" \ + "syscall \n\t" \ + "pop %%r15 \n\t" \ + "pop %%r11 \n\t" \ + "pop %%rcx \n\t" \ + "0: \n\t" +# define IPC_SYSENTER_ASM \ + push %rcx ; \ + push %r11 ; \ + push %r15 ; \ + syscall ; \ + pop %r15 ; \ + pop %r11 ; \ + pop %rcx ; \ + 0: +# endif + +# endif + +/** Kenrel entry code for inline assembly. \internal */ +#define L4_ENTER_KERNEL IPC_SYSENTER + diff --git a/l4/pkg/l4sys/include/ARCH-amd64/kdebug.h b/l4/pkg/l4sys/include/ARCH-amd64/kdebug.h new file mode 100644 index 00000000..86aa3237 --- /dev/null +++ b/l4/pkg/l4sys/include/ARCH-amd64/kdebug.h @@ -0,0 +1,426 @@ +/*****************************************************************************/ +/** + * \file + * \brief Kernel debugger macros + * \ingroup api_calls + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg , + * Björn Döbel , + * Torsten Frenzel + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +/*****************************************************************************/ +#ifndef __L4_KDEBUG_H__ +#define __L4_KDEBUG_H__ + +#include + +/** + * Enter L4 kernel debugger + * \ingroup l4_debugger_api + * \hideinitializer + * + * \param text Text to be shown at kernel debugger prompt + */ +#ifndef __ASSEMBLER__ +#define enter_kdebug(text) \ +asm(\ + "int $3 \n\t"\ + "jmp 1f \n\t"\ + ".ascii \""text "\"\n\t"\ + "1: \n\t"\ + ) +#else +#define enter_kdebug(text) \ + int $3 ;\ + jmp 1f ;\ + .ascii text ;\ + 1: +#endif + +/** + * Enter L4 kernel debugger (plain assembler version) + * \ingroup l4_debugger_api + * \hideinitializer + * + * \param text Text to be shown at kernel debugger prompt + */ +#define asm_enter_kdebug(text) \ + "int $3 \n\t"\ + "jmp 1f \n\t"\ + ".ascii \""text "\"\n\t"\ + "1: \n\t" + +/** + * Show message with L4 kernel debugger, but do not enter debugger + * \ingroup l4_debugger_api + * \hideinitializer + * + * \param text Text to be shown + */ +#define kd_display(text) \ +asm(\ + "int $3 \n\t"\ + "nop \n\t"\ + "jmp 1f \n\t"\ + ".ascii \""text "\"\n\t"\ + "1: \n\t"\ + ) + +/** + * Output character with L4 kernel debugger + * \ingroup l4_debugger_api + * \hideinitializer + * + * \param c Character to be shown + */ +#define ko(c) \ + asm( \ + "int $3 \n\t" \ + "cmpb %0,%%al \n\t" \ + : /* No output */ \ + : "N" (c) \ + ) + +/***************************************************************************** + *** Prototypes + *****************************************************************************/ + +#ifndef __ASSEMBLER__ + +/** + * Print character + * \ingroup l4_debugger_api + * + * \param c Character + */ +L4_INLINE void +outchar(char c) L4_NOTHROW; + +/** + * Print character string + * \ingroup l4_debugger_api + * + * \param text Character string + */ +L4_INLINE void +outstring(const char * text) L4_NOTHROW; + +/** + * Print character string + * \ingroup l4_debugger_api + * + * \param text Character string + * \param len Number of characters + */ +L4_INLINE void +outnstring(char const *text, unsigned len) L4_NOTHROW; + +/** + * Print 32 bit number (hexadecimal) + * \ingroup l4_debugger_api + * + * \param number 32 bit number + */ +L4_INLINE void +outhex32(int number) L4_NOTHROW; + +/** + * Print 20 bit number (hexadecimal) + * \ingroup l4_debugger_api + * + * \param number 20 bit number + */ +L4_INLINE void +outhex20(int number) L4_NOTHROW; + +/** + * Print 16 bit number (hexadecimal) + * \ingroup l4_debugger_api + * + * \param number 16 bit number + */ +L4_INLINE void +outhex16(int number) L4_NOTHROW; + +/** + * Print 12 bit number (hexadecimal) + * \ingroup l4_debugger_api + * + * \param number 12 bit number + */ +L4_INLINE void +outhex12(int number) L4_NOTHROW; + +/** + * Print 8 bit number (hexadecimal) + * \ingroup l4_debugger_api + * + * \param number 8 bit number + */ +L4_INLINE void +outhex8(int number) L4_NOTHROW; + +/** + * Print number (decimal) + * \ingroup l4_debugger_api + * + * \param number Number + */ +L4_INLINE void +outdec(int number) L4_NOTHROW; + +/** + * Read character from console, non blocking + * \ingroup l4_debugger_api + * + * \return Input character, -1 if no character to read + */ +L4_INLINE char +l4kd_inchar(void) L4_NOTHROW; + +/** + * Start profiling + * \ingroup api_calls_fiasco + */ +L4_INLINE void +fiasco_profile_start(void) L4_NOTHROW; + +/** + * Stop profiling and dump result to console + * \ingroup api_calls_fiasco + */ +L4_INLINE void +fiasco_profile_stop_and_dump(void) L4_NOTHROW; + +/** + * Stop profiling + * \ingroup api_calls_fiasco + */ +L4_INLINE void +fiasco_profile_stop(void) L4_NOTHROW; + +/** + * Enable Fiasco watchdog + * \ingroup api_calls_fiasco + */ +L4_INLINE void +fiasco_watchdog_enable(void) L4_NOTHROW; + +/** + * Disable Fiasco watchdog + * \ingroup api_calls_fiasco + */ +L4_INLINE void +fiasco_watchdog_disable(void) L4_NOTHROW; + +/** + * Disable automatic resetting of watchdog. User is responsible to call + * \c fiasco_watchdog_touch from time to time to ensure that the watchdog + * does not trigger. + * \ingroup api_calls_fiasco + */ +L4_INLINE void +fiasco_watchdog_takeover(void) L4_NOTHROW; + +/** + * Reenable automatic resetting of watchdog. + * \ingroup api_calls_fiasco + */ +L4_INLINE void +fiasco_watchdog_giveback(void) L4_NOTHROW; + +/** + * Reset watchdog from user land. This function \b must be called from time + * to time to prevent the watchdog from triggering if the watchdog is + * activated and if \c fiasco_watchdog_takeover was performed. + * \ingroup api_calls_fiasco + */ +L4_INLINE void +fiasco_watchdog_touch(void) L4_NOTHROW; + + +/***************************************************************************** + *** Implementation + *****************************************************************************/ + +L4_INLINE void +outchar(char c) L4_NOTHROW +{ + asm( + "int $3 \n\t" + "cmpb $0,%%al \n\t" + : /* No output */ + : "a" (c) + ); +} + +/* actually outstring is outcstring */ +L4_INLINE void +outstring(const char *text) L4_NOTHROW +{ + asm volatile ( + "int $3 \n\t" + "cmpb $2,%%al \n\t" + : /* No output */ + : "a" (text) + : "memory" + ); +} + +/* actually outstring is outcstring */ +L4_INLINE void +outnstring(char const *text, unsigned len) L4_NOTHROW +{ + asm volatile ( + "push %%rbx \n\t" + "mov %%rcx, %%rbx \n\t" + "int $3 \n\t" + "cmpb $1,%%al \n\t" + "pop %%rbx \n\t" + : /* No output */ + : "a" (text), "c"(len) + : "memory" + ); +} + +L4_INLINE void +outhex32(int number) L4_NOTHROW +{ + asm( + "int $3 \n\t" + "cmpb $5,%%al \n\t" + : /* No output */ + : "a" (number) + ); +} + +L4_INLINE void +outhex20(int number) L4_NOTHROW +{ + asm( + "int $3 \n\t" + "cmpb $6,%%al \n\t" + : /* No output */ + : "a" (number) + ); +} + +L4_INLINE void +outhex16(int number) L4_NOTHROW +{ + asm( + "int $3 \n\t" + "cmpb $7, %%al\n\t" + : /* No output */ + : "a" (number) + ); +} + +L4_INLINE void +outhex12(int number) L4_NOTHROW +{ + asm( + "int $3 \n\t" + "cmpb $8, %%al\n\t" + : /* No output */ + : "a" (number) + ); +} + +L4_INLINE void +outhex8(int number) L4_NOTHROW +{ + asm( + "int $3 \n\t" + "cmpb $9, %%al\n\t" + : /* No output */ + : "a" (number) + ); +} + +L4_INLINE void +outdec(int number) L4_NOTHROW +{ + asm( + "int $3 \n\t" + "cmpb $11, %%al\n\t" + : /* No output */ + : "a" (number) + ); +} + +L4_INLINE char +l4kd_inchar(void) L4_NOTHROW +{ + char c; + asm volatile ("int $3; cmpb $13, %%al" : "=a" (c)); + return c; +} + +L4_INLINE void +fiasco_profile_start(void) L4_NOTHROW +{ + asm("int $3; cmpb $24, %al"); +} + +L4_INLINE void +fiasco_profile_stop_and_dump(void) L4_NOTHROW +{ + asm("int $3; cmpb $25, %al"); +} + +L4_INLINE void +fiasco_profile_stop(void) L4_NOTHROW +{ + asm("int $3; cmpb $26, %al"); +} + +L4_INLINE void +fiasco_watchdog_enable(void) L4_NOTHROW +{ + asm("int $3; cmpb $31, %%al" : : "c" (1)); +} + +L4_INLINE void +fiasco_watchdog_disable(void) L4_NOTHROW +{ + asm("int $3; cmpb $31, %%al" : : "c" (2)); +} + +L4_INLINE void +fiasco_watchdog_takeover(void) L4_NOTHROW +{ + asm("int $3; cmpb $31, %%al" : : "c" (3)); +} + +L4_INLINE void +fiasco_watchdog_giveback(void) L4_NOTHROW +{ + asm("int $3; cmpb $31, %%al" : : "c" (4)); +} + +L4_INLINE void +fiasco_watchdog_touch(void) L4_NOTHROW +{ + asm("int $3; cmpb $31, %%al" : : "c" (5)); +} + +#endif /* __ASSEMBLER__ */ + +#endif /* __L4_KDEBUG_H__ */ diff --git a/l4/pkg/l4sys/include/ARCH-amd64/l4int.h b/l4/pkg/l4sys/include/ARCH-amd64/l4int.h new file mode 100644 index 00000000..b951692d --- /dev/null +++ b/l4/pkg/l4sys/include/ARCH-amd64/l4int.h @@ -0,0 +1,39 @@ +/*****************************************************************************/ +/** + * \file + * \brief Fixed sized integer types, amd64 version + * \ingroup l4_basic_types + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#pragma once + +#include_next + +/** + * \addtogroup l4_basic_types + */ +/*@{*/ + +#define L4_MWORD_BITS 64 /**< Size of machine words in bits */ + +typedef unsigned long l4_size_t; /**< \brief Signed size type */ +typedef signed long l4_ssize_t; /**< \brief Unsigned size type */ +/*@}*/ + diff --git a/l4/pkg/l4sys/include/ARCH-amd64/linkage.h b/l4/pkg/l4sys/include/ARCH-amd64/linkage.h new file mode 100644 index 00000000..99b29d44 --- /dev/null +++ b/l4/pkg/l4sys/include/ARCH-amd64/linkage.h @@ -0,0 +1,49 @@ +/** + * \file + * \brief Linkage + * \ingroup l4sys_api + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg , + * Torsten Frenzel + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#ifndef __L4__SYS__ARCH_AMD64__LINKAGE_H__ +#define __L4__SYS__ARCH_AMD64__LINKAGE_H__ + +#ifdef __ASSEMBLY__ + +#ifndef ENTRY +#define ENTRY(name) \ + .globl name; \ + .p2align(2); \ + name: + +#endif /* __ASSEMBLY__ */ +#endif /* ! ENTRY */ + +#define L4_FASTCALL(x) x +#define l4_fastcall + +/** + * Define calling convention. + * \ingroup l4sys_defines + * \hideinitializer + */ +#define L4_CV + +#endif /* ! __L4__SYS__ARCH_AMD64__LINKAGE_H__ */ diff --git a/l4/pkg/l4sys/include/ARCH-amd64/segment.h b/l4/pkg/l4sys/include/ARCH-amd64/segment.h new file mode 100644 index 00000000..84ee72b0 --- /dev/null +++ b/l4/pkg/l4sys/include/ARCH-amd64/segment.h @@ -0,0 +1,126 @@ +/** + * \file + * \brief Segment handling. + * \ingroup api_calls + */ +/* + * (c) 2008-2009 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +/*****************************************************************************/ +#ifndef __L4_SYS__ARCH_X86__SEGMENT_H__ +#define __L4_SYS__ARCH_X86__SEGMENT_H__ + +#ifndef L4API_l4f +#error This header file can only be used with a L4API version! +#endif + +#include + +/** + * Set LDT segments descriptors. + * \ingroup api_calls_fiasco + * + * \param task Task to set the segment for. + * \param ldt Pointer to LDT hardware descriptors. + * \param num_desc Number of descriptors. + * \param entry_number_start Entry number to start. + * \param utcb UTCB of the caller. + */ +L4_INLINE long +fiasco_ldt_set(l4_cap_idx_t task, void *ldt, unsigned int size, + unsigned int entry_number_start, l4_utcb_t *utcb); + +/** + * Set GDT segment descriptors. Fiasco supports 3 consecutive entries, + * starting at the value returned by fiasco_gdt_get_entry_offset() + * \ingroup api_calls_fiasco + * + * \param thread Thread to set the GDT entry for. + * \param desc Pointer to GDT descriptors. + * \param size Size of the descriptors in bytes + * (multiple of 8). + * \param entry_number_start Entry number to start (valid values: 0-2). + * \param utcb UTCB of the caller. + * \return System call error + */ +L4_INLINE long +fiasco_gdt_set(l4_cap_idx_t thread, void *desc, unsigned int size, + unsigned int entry_number_start, l4_utcb_t *utcb); + +/** + * Return the offset of the entry in the GDT. + * \param thread Thread to get info from. + * \param utcb UTCB of the caller. + * \ingroup api_calls_fiasco + */ +L4_INLINE unsigned +fiasco_gdt_get_entry_offset(l4_cap_idx_t thread, l4_utcb_t *utcb); + +/** + * \brief Contants for LDT handling. + */ +enum L4_task_ldt_x86_consts +{ + /** Size of an LDT entry. */ + L4_TASK_LDT_X86_ENTRY_SIZE = 8, + /** Maximum number of LDT entries that can be written with one call. */ + L4_TASK_LDT_X86_MAX_ENTRIES + = (L4_UTCB_GENERIC_DATA_SIZE - 2) + / (L4_TASK_LDT_X86_ENTRY_SIZE / (L4_MWORD_BITS / 8)), +}; + +/** + * Set the FS register. + * \param thread Thread to get info from. + * \param base Base address. + * \param utcb UTCB of the caller. + * \return System call error + */ +L4_INLINE long +fiasco_amd64_set_fs(l4_cap_idx_t thread, l4_umword_t base, l4_utcb_t *utcb); + + +/***************************************************************************** + *** Implementation + *****************************************************************************/ + +#include +#include + +L4_INLINE long +fiasco_ldt_set(l4_cap_idx_t task, void *ldt, unsigned int num_desc, + unsigned int entry_number_start, l4_utcb_t *utcb) +{ + if (num_desc > L4_TASK_LDT_X86_MAX_ENTRIES) + return -L4_EINVAL; + l4_utcb_mr_u(utcb)->mr[0] = L4_TASK_LDT_SET_X86_OP; + l4_utcb_mr_u(utcb)->mr[1] = entry_number_start; + __builtin_memcpy(&l4_utcb_mr_u(utcb)->mr[2], ldt, + num_desc * L4_TASK_LDT_X86_ENTRY_SIZE); + return l4_error_u(l4_ipc_call(task, utcb, l4_msgtag(L4_PROTO_TASK, 2 + num_desc * 2, 0, 0), L4_IPC_NEVER), utcb); +} + +L4_INLINE unsigned +fiasco_gdt_get_entry_offset(l4_cap_idx_t thread, l4_utcb_t *utcb) +{ + l4_utcb_mr_u(utcb)->mr[0] = L4_THREAD_GDT_X86_OP; + if (l4_error_u(l4_ipc_call(thread, utcb, l4_msgtag(L4_PROTO_THREAD, 1, 0, 0), L4_IPC_NEVER), utcb)) + return -1; + return l4_utcb_mr_u(utcb)->mr[0]; +} + +#endif /* ! __L4_SYS__ARCH_X86__SEGMENT_H__ */ diff --git a/l4/pkg/l4sys/include/ARCH-amd64/utcb.h b/l4/pkg/l4sys/include/ARCH-amd64/utcb.h new file mode 100644 index 00000000..23460e2d --- /dev/null +++ b/l4/pkg/l4sys/include/ARCH-amd64/utcb.h @@ -0,0 +1,125 @@ +/** + * \file + * \brief UTCB definitions for amd64. + * \ingroup l4_utcb_api + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +/*****************************************************************************/ +#ifndef __L4_SYS__INCLUDE__ARCH_AMD64__UTCB_H__ +#define __L4_SYS__INCLUDE__ARCH_AMD64__UTCB_H__ + +#include + +/** + * \defgroup l4_utcb_api_amd64 amd64 Virtual Registers (UTCB) + * \ingroup l4_utcb_api + */ + +/** + * \brief UTCB constants for AMD64 + * \ingroup l4_utcb_api_amd64 + */ +enum L4_utcb_consts_amd64 +{ + L4_UTCB_EXCEPTION_REGS_SIZE = 23, + L4_UTCB_GENERIC_DATA_SIZE = 63, + L4_UTCB_GENERIC_BUFFERS_SIZE = 58, + + L4_UTCB_MSG_REGS_OFFSET = 0, + L4_UTCB_BUF_REGS_OFFSET = 64 * sizeof(l4_umword_t), + L4_UTCB_THREAD_REGS_OFFSET = 123 * sizeof(l4_umword_t), + + L4_UTCB_INHERIT_FPU = 1UL << 24, + L4_UTCB_OFFSET = 1024, +}; + +/** + * \brief UTCB structure for exceptions. + * \ingroup l4_utcb_api_amd64 + */ +typedef struct l4_exc_regs_t +{ + l4_umword_t r15; /**< r15 */ + l4_umword_t r14; /**< r14 */ + l4_umword_t r13; /**< r13 */ + l4_umword_t r12; /**< r12 */ + l4_umword_t r11; /**< r11 */ + l4_umword_t r10; /**< r10 */ + l4_umword_t r9; /**< r9 */ + l4_umword_t r8; /**< r8 */ + l4_umword_t rdi; /**< rdi */ + l4_umword_t rsi; /**< rsi */ + l4_umword_t rbp; /**< rbp */ + l4_umword_t pfa; /**< page fault address */ + l4_umword_t rbx; /**< rbx */ + l4_umword_t rdx; /**< rdx */ + l4_umword_t rcx; /**< rcx */ + l4_umword_t rax; /**< rax */ + + l4_umword_t trapno; /**< trap number */ + l4_umword_t err; /**< error code */ + l4_umword_t ip; /**< instruction pointer */ + l4_umword_t dummy1; + l4_umword_t flags; /**< rflags */ + l4_umword_t sp; /**< stack pointer */ + l4_umword_t ss; /**< stack segment register */ +} l4_exc_regs_t; + + +#include_next + +/* + * ================================================================== + * Implementations. + */ + +L4_INLINE l4_utcb_t *l4_utcb_direct(void) L4_NOTHROW +{ + l4_utcb_t *res; + __asm__ __volatile__ ( "mov %%gs:0, %0 \n" : "=r"(res)); + return res; +} + +L4_INLINE l4_umword_t l4_utcb_exc_pc(l4_exc_regs_t *u) L4_NOTHROW +{ + return u->ip; +} + +L4_INLINE void l4_utcb_exc_pc_set(l4_exc_regs_t *u, l4_addr_t pc) L4_NOTHROW +{ + u->ip = pc; +} + +L4_INLINE l4_umword_t l4_utcb_exc_typeval(l4_exc_regs_t *u) L4_NOTHROW +{ + return u->trapno; +} + +L4_INLINE int l4_utcb_exc_is_pf(l4_exc_regs_t *u) L4_NOTHROW +{ + return u->trapno == 14; +} + +L4_INLINE l4_addr_t l4_utcb_exc_pfa(l4_exc_regs_t *u) L4_NOTHROW +{ + return (u->pfa & ~3) | (u->err & 2); +} + +#endif /* ! __L4_SYS__INCLUDE__ARCH_AMD64__UTCB_H__ */ diff --git a/l4/pkg/l4sys/include/ARCH-amd64/vm b/l4/pkg/l4sys/include/ARCH-amd64/vm new file mode 100644 index 00000000..50324b80 --- /dev/null +++ b/l4/pkg/l4sys/include/ARCH-amd64/vm @@ -0,0 +1,25 @@ +// vi:ft=cpp +/** + * \file + * \brief X86 virtualization interface + */ +/* + * (c) 2008-2009 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ + +#pragma once +#include diff --git a/l4/pkg/l4sys/include/ARCH-amd64/vm.h b/l4/pkg/l4sys/include/ARCH-amd64/vm.h new file mode 100644 index 00000000..05d3c4ff --- /dev/null +++ b/l4/pkg/l4sys/include/ARCH-amd64/vm.h @@ -0,0 +1,28 @@ +/** + * \internal + * \file + * \brief X86 virtualization interface. + */ +/* + * (c) 2008-2009 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#ifndef __INCLUDE__ARCH_X86__VM_H__ +#define __INCLUDE__ARCH_X86__VM_H__ + +#include + +#endif /* ! __INCLUDE__ARCH_X86__VM_H__ */ diff --git a/l4/pkg/l4sys/include/ARCH-arm/L4API-l4f/__kernel_object_impl.h b/l4/pkg/l4sys/include/ARCH-arm/L4API-l4f/__kernel_object_impl.h new file mode 100644 index 00000000..4be3dbc7 --- /dev/null +++ b/l4/pkg/l4sys/include/ARCH-arm/L4API-l4f/__kernel_object_impl.h @@ -0,0 +1,57 @@ +/** + * \file + * \brief Low-level kernel functions for ARM + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#ifndef L4SYS_KERNEL_OBJECT_IMPL_H__ +#define L4SYS_KERNEL_OBJECT_IMPL_H__ + +#include + +L4_INLINE l4_msgtag_t +l4_invoke_debugger(l4_cap_idx_t obj, l4_msgtag_t tag, l4_utcb_t *utcb) L4_NOTHROW +{ + register unsigned long _obj asm ("r2") = obj; + register unsigned long _a1 asm ("r0") = tag.raw; + register void* _a4 asm ("r1") = utcb; + + __asm__ __volatile__ + ("@ l4_syscall_debugger(start) \n\t" + "mov lr, pc \n\t" + "mov pc, %[sc] \n\t" + "@ l4_syscall_debugger(end) \n\t" + : + "=r" (_obj), + "=r" (_a1), + "=r" (_a4) + : + [sc] "i" (L4_SYSCALL_DEBUGGER), + "0" (_obj), + "1" (_a1), + "2" (_a4) + : + "cc", "memory", "lr" + ); + + tag.raw = _a1; // gcc doesn't like the return out of registers variables + return tag; +} + +#endif diff --git a/l4/pkg/l4sys/include/ARCH-arm/L4API-l4f/ipc.h b/l4/pkg/l4sys/include/ARCH-arm/L4API-l4f/ipc.h new file mode 100644 index 00000000..73c46106 --- /dev/null +++ b/l4/pkg/l4sys/include/ARCH-arm/L4API-l4f/ipc.h @@ -0,0 +1,280 @@ +/** + * \file + * \brief L4 IPC System Calls, ARM + * \ingroup api_calls + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#pragma once + +#include_next + +#ifdef __GNUC__ + +#include +#include + +L4_INLINE l4_msgtag_t +l4_ipc_call(l4_cap_idx_t dest, l4_utcb_t *utcb, + l4_msgtag_t tag, + l4_timeout_t timeout) L4_NOTHROW +{ + register l4_umword_t _dest __asm__("r2") = dest | L4_SYSF_CALL; + register l4_umword_t _timeout __asm__("r3") = timeout.raw; + register l4_umword_t _flags __asm__("r4") = 0; + register l4_msgtag_t _tag __asm__("r0") = tag; + (void)utcb; + __asm__ __volatile__ + ("@ l4_ipc_call(start) \n\t" + "mov lr, pc \n\t" + "mov pc, %[sc] \n\t" + "@ l4_ipc_call(end) \n\t" + : + "=r" (_dest), + "=r" (_timeout), + "=r" (_flags), + "=r" (_tag) + : + [sc] "i" (L4_SYSCALL_INVOKE), + "0" (_dest), + "1" (_timeout), + "2" (_flags), + "3" (_tag) + : "cc", "memory", "lr"); + tag.raw = _tag.raw; // because gcc doesn't return out of registers variables + return tag; +} + +L4_INLINE l4_msgtag_t +l4_ipc_reply_and_wait(l4_utcb_t *utcb, l4_msgtag_t tag, + l4_umword_t *label, + l4_timeout_t timeout) L4_NOTHROW +{ + register l4_umword_t _dest __asm__("r2") = L4_INVALID_CAP | L4_SYSF_REPLY_AND_WAIT; + register l4_umword_t _timeout __asm__("r3") = timeout.raw; + register l4_msgtag_t _tag __asm__("r0") = tag; + register l4_umword_t _flags __asm__("r4") = 0; + (void)utcb; + + __asm__ __volatile__ + ("@ l4_ipc_reply_and_wait(start) \n\t" + "mov lr, pc \n\t" + "mov pc, %[sc] \n\t" + "@ l4_ipc_reply_and_wait(end) \n\t" + : + "=r" (_dest), + "=r" (_timeout), + "=r" (_flags), + "=r" (_tag) + : + [sc] "i" (L4_SYSCALL_INVOKE), + "0" (_dest), + "1" (_timeout), + "2" (_flags), + "3" (_tag) + : + "cc", "memory", "lr"); + *label = _flags; + tag.raw = _tag.raw; // because gcc doesn't return out of registers variables + return tag; +} + + +L4_INLINE l4_msgtag_t +l4_ipc_send_and_wait(l4_cap_idx_t dest, l4_utcb_t *utcb, + l4_msgtag_t tag, + l4_umword_t *src, + l4_timeout_t timeout) L4_NOTHROW +{ + register l4_umword_t _dest __asm__("r2") = dest | L4_SYSF_SEND_AND_WAIT; + register l4_umword_t _timeout __asm__("r3") = timeout.raw; + register l4_msgtag_t _tag __asm__("r0") = tag; + register l4_umword_t _flags __asm__("r4") = 0; + (void)utcb; + + __asm__ __volatile__ + ("@ l4_ipc_reply_and_wait(start) \n\t" + "mov lr, pc \n\t" + "mov pc, %[sc] \n\t" + "@ l4_ipc_reply_and_wait(end) \n\t" + : + "=r" (_dest), + "=r" (_timeout), + "=r" (_flags), + "=r" (_tag) + : + [sc] "i" (L4_SYSCALL_INVOKE), + "0" (_dest), + "1" (_timeout), + "2" (_flags), + "3" (_tag) + : + "cc", "memory", "lr"); + *src = _flags; + tag.raw = _tag.raw; // because gcc doesn't return out of registers variables + return tag; +} + +L4_INLINE l4_msgtag_t +l4_ipc_send(l4_cap_idx_t dest, l4_utcb_t *utcb, + l4_msgtag_t tag, + l4_timeout_t timeout) L4_NOTHROW +{ + register l4_umword_t _dest __asm__("r2") = dest | L4_SYSF_SEND; + register l4_umword_t _timeout __asm__("r3") = timeout.raw; + register l4_umword_t _flags __asm__("r4") = 0; + register l4_msgtag_t _tag __asm__("r0") = tag; + (void)utcb; + + __asm__ __volatile__ + ("@ l4_ipc_send(start) \n\t" + "mov lr, pc \n\t" + "mov pc, %[sc] \n\t" + "@ l4_ipc_send(end) \n\t" + : + "=r" (_dest), + "=r" (_timeout), + "=r" (_flags), + "=r" (_tag) + : + [sc] "i" (L4_SYSCALL_INVOKE), + "0" (_dest), + "1" (_timeout), + "2" (_flags), + "3" (_tag) + : + "cc", "memory", "lr"); + tag.raw = _tag.raw; // because gcc doesn't return out of registers variables + return tag; +} + +L4_INLINE l4_msgtag_t +l4_ipc_wait(l4_utcb_t *utcb, l4_umword_t *src, + l4_timeout_t timeout) L4_NOTHROW +{ + l4_msgtag_t rtag; + register l4_umword_t _r __asm__("r2") = L4_INVALID_CAP | L4_SYSF_WAIT; + register l4_umword_t _timeout __asm__("r3") = timeout.raw; + register l4_msgtag_t _tag __asm__("r0"); + register l4_umword_t _flags __asm__("r4") = 0; + (void)utcb; + _tag.raw = 0; + + __asm__ __volatile__ + ("@ l4_ipc_wait(start) \n\t" + "mov lr, pc \n\t" + "mov pc, %[sc] \n\t" + "@ l4_ipc_wait(end) \n\t" + : + "=r"(_r), + "=r"(_timeout), + "=r"(_flags), + "=r"(_tag) + : + [sc] "i"(L4_SYSCALL_INVOKE), + "0"(_r), + "1"(_timeout), + "2"(_flags), + "3"(_tag) + + : + "cc", "memory", "lr"); + *src = _flags; + rtag.raw = _tag.raw; // because gcc doesn't return out of registers variables + return rtag; +} + +L4_INLINE l4_msgtag_t +l4_ipc_receive(l4_cap_idx_t src, l4_utcb_t *utcb, + l4_timeout_t timeout) L4_NOTHROW +{ + l4_msgtag_t rtag; + register l4_umword_t _r __asm__("r2") = src | L4_SYSF_RECV; + register l4_umword_t _timeout __asm__("r3") = timeout.raw; + register l4_msgtag_t _tag __asm__("r0"); + register l4_umword_t _flags __asm__("r4") = 0; + (void)utcb; + + _tag.raw = 0; + + __asm__ __volatile__ + ("@ l4_ipc_receive(start) \n\t" + "mov lr, pc \n\t" + "mov pc, %[sc] \n\t" + "@ l4_ipc_receive(end) \n\t" + : + "=r"(_r), + "=r"(_timeout), + "=r"(_flags), + "=r"(_tag) + : + [sc] "i"(L4_SYSCALL_INVOKE), + "0"(_r), + "1"(_timeout), + "2"(_flags), + "3"(_tag) + : + "cc", "memory", "lr"); + rtag.raw = _tag.raw; // because gcc doesn't return out of registers variables + return rtag; +} + +// todo: let all calls above use this single call +L4_INLINE l4_msgtag_t +l4_ipc(l4_cap_idx_t dest, l4_utcb_t *utcb, + l4_umword_t flags, + l4_umword_t slabel, + l4_msgtag_t tag, + l4_umword_t *rlabel, + l4_timeout_t timeout) L4_NOTHROW +{ + register l4_umword_t _dest __asm__("r2") = dest | flags; + register l4_umword_t _timeout __asm__("r3") = timeout.raw; + register l4_msgtag_t _tag __asm__("r0") = tag; + register l4_umword_t _lab __asm__("r4") = slabel; + (void)utcb; + + __asm__ __volatile__ + ("@ l4_ipc_reply_and_wait(start) \n\t" + "mov lr, pc \n\t" + "mov pc, %[sc] \n\t" + "@ l4_ipc_reply_and_wait(end) \n\t" + : + "=r" (_dest), + "=r" (_timeout), + "=r" (_lab), + "=r" (_tag) + : + [sc] "i" (L4_SYSCALL_INVOKE), + "0" (_dest), + "1" (_timeout), + "2" (_lab), + "3" (_tag) + : + "cc", "memory", "lr"); + *rlabel = _lab; + tag.raw = _tag.raw; // because gcc doesn't return out of registers variables + return tag; +} + + +#include + +#endif //__GNUC__ + diff --git a/l4/pkg/l4sys/include/ARCH-arm/L4API-l4f/syscall_defs.h b/l4/pkg/l4sys/include/ARCH-arm/L4API-l4f/syscall_defs.h new file mode 100644 index 00000000..0a3082f6 --- /dev/null +++ b/l4/pkg/l4sys/include/ARCH-arm/L4API-l4f/syscall_defs.h @@ -0,0 +1,32 @@ +/** + * \file + * \brief Syscall entry definitions. + */ +/* + * (c) 2010 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#ifndef __L4SYS__ARCH_ARM__L4API_L4F__SYSCALL_DEFS_H__ +#define __L4SYS__ARCH_ARM__L4API_L4F__SYSCALL_DEFS_H__ + +#ifndef L4_SYSCALL_MAGIC_OFFSET +# define L4_SYSCALL_MAGIC_OFFSET 8 +#endif +#define L4_SYSCALL_INVOKE (-0x00000004-L4_SYSCALL_MAGIC_OFFSET) +#define L4_SYSCALL_MEM_OP (-0x00000008-L4_SYSCALL_MAGIC_OFFSET) +#define L4_SYSCALL_DEBUGGER (-0x0000000C-L4_SYSCALL_MAGIC_OFFSET) + +#endif /* __L4SYS__ARCH_ARM__L4API_L4F__SYSCALL_DEFS_H__ */ diff --git a/l4/pkg/l4sys/include/ARCH-arm/__vcpu-arch.h b/l4/pkg/l4sys/include/ARCH-arm/__vcpu-arch.h new file mode 100644 index 00000000..01aaa54c --- /dev/null +++ b/l4/pkg/l4sys/include/ARCH-arm/__vcpu-arch.h @@ -0,0 +1,51 @@ +/* + * (c) 2009 Adam Lackorzynski , + * Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#pragma once + +#include + +/** + * \brief vCPU registers. + * \ingroup l4_vcpu_api + */ +typedef struct l4_vcpu_regs_t +{ + l4_umword_t pfa; + l4_umword_t err; + + l4_umword_t r[13]; + + l4_umword_t sp; + l4_umword_t lr; + l4_umword_t _dummy; + l4_umword_t ip; + l4_umword_t flags; +} l4_vcpu_regs_t; + +/** + * \brief vCPU message registers. + * \ingroup l4_vcpu_api + */ +typedef struct l4_vcpu_ipc_regs_t +{ + l4_msgtag_t tag; + l4_umword_t _d1[3]; + l4_umword_t label; + l4_umword_t _d2[8]; +} l4_vcpu_ipc_regs_t; diff --git a/l4/pkg/l4sys/include/ARCH-arm/atomic.h b/l4/pkg/l4sys/include/ARCH-arm/atomic.h new file mode 100644 index 00000000..d440ae7d --- /dev/null +++ b/l4/pkg/l4sys/include/ARCH-arm/atomic.h @@ -0,0 +1,35 @@ +/** + * \file + * \brief Atomic memory modifications. + * \ingroup api_calls + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#pragma once + +#include + +EXTERN_C long int +l4_atomic_add(volatile long int* mem, long int offset) L4_NOTHROW L4_LONG_CALL; + +EXTERN_C long int +l4_atomic_xchg(volatile long int* mem, long int newval) L4_NOTHROW L4_LONG_CALL; + +EXTERN_C long int +l4_atomic_cmpxchg(volatile long int* mem, long int oldval, long int newval) L4_NOTHROW L4_LONG_CALL; diff --git a/l4/pkg/l4sys/include/ARCH-arm/cache.h b/l4/pkg/l4sys/include/ARCH-arm/cache.h new file mode 100644 index 00000000..82f4557d --- /dev/null +++ b/l4/pkg/l4sys/include/ARCH-arm/cache.h @@ -0,0 +1,145 @@ +/** + * \file + * \brief Cache functions + * + * \date 2007-11 + * \author Adam Lackorzynski + * + */ +/* + * (c) 2007-2009 Author(s) + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#ifndef __L4SYS__INCLUDE__ARCH_ARM__CACHE_H__ +#define __L4SYS__INCLUDE__ARCH_ARM__CACHE_H__ + +#include +#include + +#include_next + +/** + * \internal + */ +L4_INLINE void +l4_cache_op_arm_call(unsigned long op, + unsigned long start, + unsigned long end); + +L4_INLINE void +l4_cache_op_arm_call(unsigned long op, + unsigned long start, + unsigned long end) +{ + register unsigned long _op asm ("r0") = op; + register unsigned long _start asm ("r1") = start; + register unsigned long _end asm ("r2") = end; + + __asm__ __volatile__ + ("@ l4_cache_op_arm_call(start) \n\t" + "mov lr, pc \n\t" + "mov pc, %[sc] \n\t" + "@ l4_cache_op_arm_call(end) \n\t" + : + "=r" (_op), + "=r" (_start), + "=r" (_end) + : + [sc] "i" (L4_SYSCALL_MEM_OP), + "0" (_op), + "1" (_start), + "2" (_end) + : + "cc", "memory", "lr" + ); +} + +enum L4_mem_cache_ops +{ + L4_MEM_CACHE_OP_CLEAN_DATA = 0, + L4_MEM_CACHE_OP_FLUSH_DATA = 1, + L4_MEM_CACHE_OP_INV_DATA = 2, + L4_MEM_CACHE_OP_COHERENT = 3, + L4_MEM_CACHE_OP_DMA_COHERENT = 4, + L4_MEM_CACHE_OP_DMA_COHERENT_FULL = 5, + L4_MEM_CACHE_OP_L2_CLEAN = 6, + L4_MEM_CACHE_OP_L2_FLUSH = 7, + L4_MEM_CACHE_OP_L2_INV = 8, +}; + +L4_INLINE void +l4_cache_clean_data(unsigned long start, + unsigned long end) L4_NOTHROW +{ + l4_cache_op_arm_call(L4_MEM_CACHE_OP_CLEAN_DATA, start, end); +} + +L4_INLINE void +l4_cache_flush_data(unsigned long start, + unsigned long end) L4_NOTHROW +{ + l4_cache_op_arm_call(L4_MEM_CACHE_OP_FLUSH_DATA, start, end); +} + +L4_INLINE void +l4_cache_inv_data(unsigned long start, + unsigned long end) L4_NOTHROW +{ + l4_cache_op_arm_call(L4_MEM_CACHE_OP_INV_DATA, start, end); +} + +L4_INLINE void +l4_cache_coherent(unsigned long start, + unsigned long end) L4_NOTHROW +{ + l4_cache_op_arm_call(L4_MEM_CACHE_OP_COHERENT, start, end); +} + +L4_INLINE void +l4_cache_dma_coherent(unsigned long start, + unsigned long end) L4_NOTHROW +{ + l4_cache_op_arm_call(L4_MEM_CACHE_OP_DMA_COHERENT, start, end); +} + +L4_INLINE void +l4_cache_dma_coherent_full(void) L4_NOTHROW +{ + l4_cache_op_arm_call(L4_MEM_CACHE_OP_DMA_COHERENT_FULL, 0, 0); +} + +L4_INLINE void +l4_cache_l2_clean(unsigned long start, + unsigned long end) L4_NOTHROW +{ + l4_cache_op_arm_call(L4_MEM_CACHE_OP_L2_CLEAN, start, end); +} + +L4_INLINE void +l4_cache_l2_flush(unsigned long start, + unsigned long end) L4_NOTHROW +{ + l4_cache_op_arm_call(L4_MEM_CACHE_OP_L2_FLUSH, start, end); +} + +L4_INLINE void +l4_cache_l2_inv(unsigned long start, + unsigned long end) L4_NOTHROW +{ + l4_cache_op_arm_call(L4_MEM_CACHE_OP_L2_INV, start, end); +} + +#endif /* ! __L4SYS__INCLUDE__ARCH_ARM__CACHE_H__ */ diff --git a/l4/pkg/l4sys/include/ARCH-arm/consts.h b/l4/pkg/l4sys/include/ARCH-arm/consts.h new file mode 100644 index 00000000..378272f8 --- /dev/null +++ b/l4/pkg/l4sys/include/ARCH-arm/consts.h @@ -0,0 +1,48 @@ +/** + * \file + * \brief Common L4 constants, arm version + * \ingroup l4_api + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg , + * Björn Döbel + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#ifndef _L4_SYS_CONSTS_H +#define _L4_SYS_CONSTS_H + +/* L4 includes */ +#include +/** + * \addtogroup l4_memory_api + */ +/*@{*/ +/** + * Size of a page, log2-based. + */ +#define L4_PAGESHIFT 12 + +/** + * Size of a large page, log2-based. + */ +#define L4_SUPERPAGESHIFT 20 + +/*@}*/ + +#include_next + +#endif /* !_L4_SYS_CONSTS_H */ diff --git a/l4/pkg/l4sys/include/ARCH-arm/kdebug.h b/l4/pkg/l4sys/include/ARCH-arm/kdebug.h new file mode 100644 index 00000000..eb6e9cb2 --- /dev/null +++ b/l4/pkg/l4sys/include/ARCH-arm/kdebug.h @@ -0,0 +1,288 @@ +/** + * \file + * \brief Kernel debugger macros + * \ingroup api_calls + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#pragma once + +#include + +#ifdef __GNUC__ + +#ifndef L4_SYSCALL_MAGIC_OFFSET +# define L4_SYSCALL_MAGIC_OFFSET 8 +#endif +#define L4_SYSCALL_ENTER_KDEBUG (-0x00000020-L4_SYSCALL_MAGIC_OFFSET) + +#define enter_kdebug(text...) \ +__asm__ __volatile__ ( \ + " mov lr, pc \n" \ + " mov pc, %0 \n" \ + " b 1f \n" \ + " .ascii \"" text "\" \n" \ + " .byte 0 \n" \ + " .align 4 \n" \ + "1: \n" \ + : \ + : "i" (L4_SYSCALL_ENTER_KDEBUG) \ + : "lr") + +L4_INLINE void +outnstring(const char* x, unsigned len) L4_NOTHROW; + +L4_INLINE void +outstring(const char *text) L4_NOTHROW; + +L4_INLINE void +outchar(char c) L4_NOTHROW; + +L4_INLINE void +outdec(int number) L4_NOTHROW; + +L4_INLINE void +outhex32(int number) L4_NOTHROW; + +L4_INLINE void +outhex20(int number) L4_NOTHROW; + +L4_INLINE void +outhex16(int number) L4_NOTHROW; + +L4_INLINE void +outhex12(int number) L4_NOTHROW; + +L4_INLINE void +outhex8(int number) L4_NOTHROW; + +L4_INLINE void +kd_display(char *text) L4_NOTHROW; + +L4_INLINE int +l4kd_inchar(void) L4_NOTHROW; + +L4_INLINE void +l4_sys_cli(void) L4_NOTHROW; + +L4_INLINE void +l4_sys_sti(void) L4_NOTHROW; + +/* + * ------------------------------------------------------------------- + * Implementations + */ + +#define __KDEBUG_ARM_PARAM_0(nr) \ + ({ \ + register unsigned long r0 __asm__("r0"); \ + __asm__ __volatile__ \ + ( \ + "stmdb sp!, {r1-r12,lr} \n\t" \ + "mov lr, pc \n\t" \ + "mov pc, %1 \n\t" \ + "cmp lr, #" #nr " \n\t" \ + "ldmia sp!, {r1-r12,lr} \n\t" \ + : \ + "=r" (r0) \ + : \ + "i" (L4_SYSCALL_ENTER_KDEBUG) \ + ); \ + r0; \ + }) + +#define __KDEBUG_ARM_PARAM_1(nr, p1) \ + ({ \ + register unsigned long r0 __asm__("r0") = (unsigned long)(p1);\ + __asm__ __volatile__ \ + ( \ + "stmdb sp!, {r1-r12,lr} \n\t" \ + "mov lr, pc \n\t" \ + "mov pc, %1 \n\t" \ + "cmp lr, #" #nr " \n\t" \ + "ldmia sp!, {r1-r12,lr} \n\t" \ + : \ + "=r" (r0) \ + : \ + "i" (L4_SYSCALL_ENTER_KDEBUG), \ + "0" (r0) \ + ); \ + r0; \ + }) + +#define __KDEBUG_ARM_PARAM_2(nr, p1, p2) \ + ({ \ + register unsigned long r0 __asm__("r0") = (unsigned long)(p1);\ + register unsigned long r1 __asm__("r1") = (unsigned long)(p2);\ + __asm__ __volatile__ \ + ( \ + "stmdb sp!, {r2-r12,lr} \n\t" \ + "mov lr, pc \n\t" \ + "mov pc, %2 \n\t" \ + "cmp lr, #" #nr " \n\t" \ + "ldmia sp!, {r2-r12,lr} \n\t" \ + : \ + "=r" (r0), \ + "=r" (r1) \ + : \ + "i" (L4_SYSCALL_ENTER_KDEBUG), \ + "0" (r0), \ + "r" (r1) \ + ); \ + r0; \ + }) + +#define __KDEBUG_ARM_PARAM_3(nr, p1, p2, p3) \ + ({ \ + register unsigned long r0 __asm__("r0") = (unsigned long)(p1);\ + register unsigned long r1 __asm__("r1") = (unsigned long)(p2);\ + register unsigned long r2 __asm__("r2") = (unsigned long)(p3);\ + __asm__ __volatile__ \ + ( \ + "stmdb sp!, {r3-r12,lr} \n\t" \ + "mov lr, pc \n\t" \ + "mov pc, %3 \n\t" \ + "cmp lr, #" #nr " \n\t" \ + "ldmia sp!, {r3-r12,lr} \n\t" \ + : \ + "=r" (r0), \ + "=r" (r1), \ + "=r" (r2) \ + : \ + "i" (L4_SYSCALL_ENTER_KDEBUG), \ + "0" (r0), \ + "r" (r1), \ + "r" (r2) \ + ); \ + r0; \ + }) + +#define __KDEBUG_ARM_PARAM_5(nr, p1, p2, p3, p4, p5) \ + ({ \ + register unsigned long r0 __asm__("r0") = (unsigned long)(p1);\ + register unsigned long r1 __asm__("r1") = (unsigned long)(p2);\ + register unsigned long r2 __asm__("r2") = (unsigned long)(p3);\ + register unsigned long r3 __asm__("r3") = (unsigned long)(p4);\ + register unsigned long r4 __asm__("r4") = (unsigned long)(p5);\ + __asm__ __volatile__ \ + ( \ + "stmdb sp!, {r5-r12,lr} \n\t" \ + "mov lr, pc \n\t" \ + "mov pc, %5 \n\t" \ + "cmp lr, #" #nr " \n\t" \ + "ldmia sp!, {r5-r12,lr} \n\t" \ + : \ + "=r" (r0), \ + "=r" (r1), \ + "=r" (r2), \ + "=r" (r3), \ + "=r" (r4) \ + : \ + "i" (L4_SYSCALL_ENTER_KDEBUG), \ + "0" (r0), \ + "r" (r1), \ + "r" (r2), \ + "r" (r3), \ + "r" (r4) \ + ); \ + r0; \ + }) + + +L4_INLINE void +outnstring(const char* x, unsigned len) L4_NOTHROW +{ + __asm__ volatile ("" : : : "memory"); + __KDEBUG_ARM_PARAM_2(3, x, len); +} + +L4_INLINE void +outstring(const char *text) L4_NOTHROW +{ + __asm__ volatile("" : : : "memory"); + __KDEBUG_ARM_PARAM_1(2, text); +} + +L4_INLINE void +outchar(char c) L4_NOTHROW +{ + __KDEBUG_ARM_PARAM_1(1, c); +} + +L4_INLINE void +outdec(int number) L4_NOTHROW +{ + __KDEBUG_ARM_PARAM_1(4, number); +} + +L4_INLINE void +outhex32(int number) L4_NOTHROW +{ + __KDEBUG_ARM_PARAM_1(5, number); +} + +L4_INLINE void +outhex20(int number) L4_NOTHROW +{ + __KDEBUG_ARM_PARAM_1(6, number); +} + +L4_INLINE void +outhex16(int number) L4_NOTHROW +{ + __KDEBUG_ARM_PARAM_1(7, number); +} + +L4_INLINE void +outhex12(int number) L4_NOTHROW +{ + __KDEBUG_ARM_PARAM_1(8, number); +} + +L4_INLINE void +outhex8(int number) L4_NOTHROW +{ + __KDEBUG_ARM_PARAM_1(9, number); +} + +L4_INLINE void +kd_display(char *text) L4_NOTHROW +{ + outstring(text); +} + +L4_INLINE int +l4kd_inchar(void) L4_NOTHROW +{ + return __KDEBUG_ARM_PARAM_0(0xd); +} + +L4_INLINE void +l4_sys_cli(void) L4_NOTHROW +{ + __KDEBUG_ARM_PARAM_0(0x32); +} + +L4_INLINE void +l4_sys_sti(void) L4_NOTHROW +{ + __KDEBUG_ARM_PARAM_0(0x33); +} + +#endif //__GNUC__ diff --git a/l4/pkg/l4sys/include/ARCH-arm/ktrace.h b/l4/pkg/l4sys/include/ARCH-arm/ktrace.h new file mode 100644 index 00000000..724a5eb1 --- /dev/null +++ b/l4/pkg/l4sys/include/ARCH-arm/ktrace.h @@ -0,0 +1,227 @@ +/** + * \file + * \brief L4 kernel event tracing + * \ingroup api_calls + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Björn Döbel , + * Torsten Frenzel + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#ifndef __L4_KTRACE_H__ +#define __L4_KTRACE_H__ + +#include +#include + +#define LOG_EVENT_CONTEXT_SWITCH 0 /**< Event: context switch + ** \ingroup api_calls_fiasco + **/ +#define LOG_EVENT_IPC_SHORTCUT 1 /**< Event: IPC shortcut + ** \ingroup api_calls_fiasco + **/ +#define LOG_EVENT_IRQ_RAISED 2 /**< Event: IRQ occurred + ** \ingroup api_calls_fiasco + **/ +#define LOG_EVENT_TIMER_IRQ 3 /**< Event: Timer IRQ occurred + ** \ingroup api_calls_fiasco + **/ +#define LOG_EVENT_THREAD_EX_REGS 4 /**< Event: thread_ex_regs + ** \ingroup api_calls_fiasco + **/ + +#define LOG_EVENT_MAX_EVENTS 16 /**< Maximum number of events + ** \ingroup api_calls_fiasco + **/ + +/** + * Trace buffer status. + * \ingroup api_calls_fiasco + */ +typedef struct +{ + /// Address of trace buffer 0 + l4_umword_t tracebuffer0; + /// Size of trace buffer 0 + l4_umword_t size0; + /// Version number of trace buffer 0 (incremented if tb0 overruns) + l4_umword_t version0; + /// Address of trace buffer 1 (there is no gap between tb0 and tb1) + l4_umword_t tracebuffer1; + /// Size of trace buffer 1 (same as tb0) + l4_umword_t size1; + /// Version number of trace buffer 1 (incremented if tb1 overruns) + l4_umword_t version1; + /// Available LOG events + l4_umword_t logevents[LOG_EVENT_MAX_EVENTS]; + + /// Scaler used for translation of CPU cycles to nano seconds + l4_umword_t scaler_tsc_to_ns; + /// Scaler used for translation of CPU cycles to micro seconds + l4_umword_t scaler_tsc_to_us; + /// Scaler used for translation of nano seconds to CPU cycles + l4_umword_t scaler_ns_to_tsc; + + /// Number of context switches (intra AS or inter AS) + l4_umword_t cnt_context_switch; + /// Number of inter AS context switches + l4_umword_t cnt_addr_space_switch; + /// How often was the IPC shortcut not taken + l4_umword_t cnt_shortcut_failed; + /// How often was the IPC shortcut taken + l4_umword_t cnt_shortcut_success; + /// Number of hardware interrupts (without kernel scheduling interrupt) + l4_umword_t cnt_irq; + /// Number of long IPCs + l4_umword_t cnt_ipc_long; + +} l4_tracebuffer_status_t; + +/** + * Return trace buffer status. + * \ingroup api_calls_fiasco + * + * \return Pointer to trace buffer status struct. + */ +L4_INLINE l4_tracebuffer_status_t * +fiasco_tbuf_get_status(void); + +/** + * Return the physical address of the trace buffer status struct. + * \ingroup api_calls_fiasco + * + * \return physical address of status struct. + */ +L4_INLINE l4_addr_t +fiasco_tbuf_get_status_phys(void); + +/** + * Create new trace buffer entry with describing \. + * \ingroup api_calls_fiasco + * + * \param text Logging text + * \return Pointer to trace buffer entry + */ +L4_INLINE l4_umword_t +fiasco_tbuf_log(const char *text); + +/** + * Create new trace buffer entry with describing \ and three additional + * values. + * \ingroup api_calls_fiasco + * + * \param text Logging text + * \param v1 first value + * \param v2 second value + * \param v3 third value + * \return Pointer to trace buffer entry + */ +L4_INLINE l4_umword_t +fiasco_tbuf_log_3val(const char *text, unsigned v1, unsigned v2, unsigned v3); + +/** + * Create new trace buffer entry with binary data. + * \ingroup api_calls_fiasco + * + * \param data binary data + * \return Pointer to trace buffer entry + */ +L4_INLINE l4_umword_t +fiasco_tbuf_log_binary(const unsigned char *data); + +/** + * Clear trace buffer. + * \ingroup api_calls_fiasco + */ +L4_INLINE void +fiasco_tbuf_clear(void); + +/** + * Dump trace buffer to kernel console. + * \ingroup api_calls_fiasco + */ +L4_INLINE void +fiasco_tbuf_dump(void); + +L4_INLINE void +fiasco_timer_disable(void); + +L4_INLINE void +fiasco_timer_enable(void); + +/***************************************************************************** + *** Implementation + *****************************************************************************/ + +L4_INLINE l4_tracebuffer_status_t * +fiasco_tbuf_get_status(void) +{ + /* Not implemented */ + return (l4_tracebuffer_status_t *)__KDEBUG_ARM_PARAM_1(29, 0); +} + +L4_INLINE l4_addr_t +fiasco_tbuf_get_status_phys(void) +{ + enter_kdebug("fiasco_tbuf_get_status_phys not there"); + return ~0UL; +} + +L4_INLINE l4_umword_t +fiasco_tbuf_log(const char *text) +{ + return __KDEBUG_ARM_PARAM_2(29, 1, text); +} + +L4_INLINE l4_umword_t +fiasco_tbuf_log_3val(const char *text, unsigned v1, unsigned v2, unsigned v3) +{ + return __KDEBUG_ARM_PARAM_5(29, 4, text, v1, v2, v3); +} + +L4_INLINE void +fiasco_tbuf_clear(void) +{ + __KDEBUG_ARM_PARAM_1(29, 2); +} + +L4_INLINE void +fiasco_tbuf_dump(void) +{ + __KDEBUG_ARM_PARAM_1(29, 3); +} + +L4_INLINE void +fiasco_timer_disable(void) +{ + __KDEBUG_ARM_PARAM_1(29, 6); +} + +L4_INLINE void +fiasco_timer_enable(void) +{ + __KDEBUG_ARM_PARAM_1(29, 6); +} + +L4_INLINE l4_umword_t +fiasco_tbuf_log_binary(const unsigned char *data) +{ + return __KDEBUG_ARM_PARAM_2(29, 8, data); +} + +#endif + diff --git a/l4/pkg/l4sys/include/ARCH-arm/l4int.h b/l4/pkg/l4sys/include/ARCH-arm/l4int.h new file mode 100644 index 00000000..c23748c7 --- /dev/null +++ b/l4/pkg/l4sys/include/ARCH-arm/l4int.h @@ -0,0 +1,38 @@ +/** + * \file + * \brief Fixed sized integer types, arm version + * \ingroup l4_basic_types + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#pragma once + +#include_next + +/** + * \addtogroup l4_basic_types + */ +/*@{*/ + +#define L4_MWORD_BITS 32 /**< Size of machine words in bits */ + +typedef unsigned int l4_size_t; /**< \brief Signed size type */ +typedef signed int l4_ssize_t; /**< \brief Unsigned size type */ +/*@}*/ + diff --git a/l4/pkg/l4sys/include/ARCH-arm/linkage.h b/l4/pkg/l4sys/include/ARCH-arm/linkage.h new file mode 100644 index 00000000..2e98833d --- /dev/null +++ b/l4/pkg/l4sys/include/ARCH-arm/linkage.h @@ -0,0 +1,63 @@ +/** + * \file + * \brief Linkage + * \ingroup l4sys_api + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#ifndef __L4__SYS__ARCH_ARM__LINKAGE_H__ +#define __L4__SYS__ARCH_ARM__LINKAGE_H__ + +#if defined(__PIC__) \ + && ((__GNUC__ < 4) || (__GNUC__ == 4 && __GNUC_MINOR__ < 2)) +# define PIC_SAVE_ASM "str r10, [sp, #-4]! \n\t" +# define PIC_RESTORE_ASM "ldr r10, [sp], #4 \n\t" +# define PIC_CLOBBER +#else +# define PIC_SAVE_ASM +# define PIC_RESTORE_ASM +# define PIC_CLOBBER ,"r10" +#endif + +#ifdef __ASSEMBLY__ +#ifndef ENTRY +#define ENTRY(name) \ + .globl name; \ + .p2align(2); \ + name: +#endif +#endif + +#define L4_FASTCALL(x) x +#define l4_fastcall + +/** + * Define calling convention. + * \ingroup l4sys_defines + * \hideinitializer + */ +#define L4_CV + +#ifdef __PIC__ +# define L4_LONG_CALL +#else +# define L4_LONG_CALL __attribute__((long_call)) +#endif + +#endif /* ! __L4__SYS__ARCH_ARM__LINKAGE_H__ */ diff --git a/l4/pkg/l4sys/include/ARCH-arm/mem_op.h b/l4/pkg/l4sys/include/ARCH-arm/mem_op.h new file mode 100644 index 00000000..235ed2f4 --- /dev/null +++ b/l4/pkg/l4sys/include/ARCH-arm/mem_op.h @@ -0,0 +1,155 @@ +/** + * \file + * \brief Memory access functions (ARM specific) + * + * \date 2010-10 + * \author Adam Lackorzynski + * + */ +/* + * (c) 2010 Author(s) + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#ifndef __L4SYS__INCLUDE__ARCH_ARM__MEM_OP_H__ +#define __L4SYS__INCLUDE__ARCH_ARM__MEM_OP_H__ + +#include +#include + +EXTERN_C_BEGIN + +/** + * \defgroup l4_mem_op_api Memory operations. + * \ingroup l4_api + * \brief Operations for memory access. + * + * This modules provides functionality to access user task memory from the + * kernel. This is needed for some devices that are only accessible from + * privileged processor mode. Only use this when absolutely required. This + * functionality is only available on the ARM architecture. + * + * \#include + */ + +/** + * \brief Memory access width definitions. + * \ingroup l4_mem_op_api + */ +enum L4_mem_op_widths +{ + L4_MEM_WIDTH_1BYTE = 0, ///< Access one byte (8-bit width) + L4_MEM_WIDTH_2BYTE = 1, ///< Access two bytes (16-bit width) + L4_MEM_WIDTH_4BYTE = 2, ///< Access four bytes (32-bit width) +}; + +/** + * \brief Read memory from kernel privilege level. + * \ingroup l4_mem_op_api + * + * \param virtaddress Virtual address in the calling task. + * \param width Width of access in bytes in log2, + * \see L4_mem_op_widths + * \return Read value. + * + * Upon an given invalid address or invalid width value the function does + * nothing. + */ +L4_INLINE unsigned long +l4_mem_read(unsigned long virtaddress, unsigned width); + +/** + * \brief Write memory from kernel privilege level. + * \ingroup l4_mem_op_api + * + * \param virtaddress Virtual address in the calling task. + * \param width Width of access in bytes in log2 + * (i.e. allowed values: 0, 1, 2) + * \param value Value to write. + * + * Upon an given invalid address or invalid width value the function does + * nothing. + */ +L4_INLINE void +l4_mem_write(unsigned long virtaddress, unsigned width, + unsigned long value); + +enum L4_mem_ops +{ + L4_MEM_OP_MEM_READ = 0x10, + L4_MEM_OP_MEM_WRITE = 0x11, +}; + +/** + * \internal + */ +L4_INLINE unsigned long +l4_mem_arm_op_call(unsigned long op, + unsigned long va, + unsigned long width, + unsigned long value); + +/** Implementations */ + +L4_INLINE unsigned long +l4_mem_arm_op_call(unsigned long op, + unsigned long va, + unsigned long width, + unsigned long value) +{ + register unsigned long _op asm ("r0") = op; + register unsigned long _va asm ("r1") = va; + register unsigned long _width asm ("r2") = width; + register unsigned long _value asm ("r3") = value; + + __asm__ __volatile__ + ("@ l4_cache_op_arm_call(start) \n\t" + "mov lr, pc \n\t" + "mov pc, %[sc] \n\t" + "@ l4_cache_op_arm_call(end) \n\t" + : + "=r" (_op), + "=r" (_va), + "=r" (_width), + "=r" (_value) + : + [sc] "i" (L4_SYSCALL_MEM_OP), + "0" (_op), + "1" (_va), + "2" (_width), + "3" (_value) + : + "cc", "memory", "lr" + ); + + return _value; +} + +L4_INLINE unsigned long +l4_mem_read(unsigned long virtaddress, unsigned width) +{ + return l4_mem_arm_op_call(L4_MEM_OP_MEM_READ, virtaddress, width, 0); +} + +L4_INLINE void +l4_mem_write(unsigned long virtaddress, unsigned width, + unsigned long value) +{ + l4_mem_arm_op_call(L4_MEM_OP_MEM_WRITE, virtaddress, width, value); +} + +EXTERN_C_END + +#endif /* ! __L4SYS__INCLUDE__ARCH_ARM__MEM_OP_H__ */ diff --git a/l4/pkg/l4sys/include/ARCH-arm/rt_sched.h b/l4/pkg/l4sys/include/ARCH-arm/rt_sched.h new file mode 100644 index 00000000..1dc0ba1f --- /dev/null +++ b/l4/pkg/l4sys/include/ARCH-arm/rt_sched.h @@ -0,0 +1,27 @@ +/** + * \file + * \brief Real-time scheduling include + */ +/* + * (c) 2008-2009 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#ifndef __L4_SYS__ARCH_ARM__RT_SCHED_H__ +#define __L4_SYS__ARCH_ARM__RT_SCHED_H__ + +/* Empty, just to be here. */ + +#endif /* __L4_SYS__ARCH_ARM__RT_SCHED_H__ */ diff --git a/l4/pkg/l4sys/include/ARCH-arm/types.h b/l4/pkg/l4sys/include/ARCH-arm/types.h new file mode 100644 index 00000000..f3990ced --- /dev/null +++ b/l4/pkg/l4sys/include/ARCH-arm/types.h @@ -0,0 +1,80 @@ +/** + * \file + * \brief Types for ARM + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#ifndef L4_TYPES_H +#define L4_TYPES_H + +#include_next + +#include +#include +#include + +#include + +#include + +/** + * \brief l4_schedule param word + */ +/* +typedef union { + struct { + l4_umword_t prio :8; + l4_umword_t small :8; + l4_umword_t state :4; + l4_umword_t time_exp :4; + l4_umword_t time_man :8; + } sp; + l4_umword_t sched_param; + l4_umword_t raw; +} l4_sched_param_t; + +#define L4_INVALID_SCHED_PARAM ((l4_sched_param_t){raw:(l4_umword_t)-1}) +*/ + +/* Compute l4_sched_param_struct_t->small argument for + l4_thread_schedule(): size_mb is the size of all small address + spaces, and nr is the number of the small address space. See + Liedtke: ``L4 Pentium implementation'' */ +//#define L4_SMALL_SPACE(size_mb, nr) ((size_mb >> 2) + nr * (size_mb >> 1)) + +/* + * Some useful operations and test functions for id's and types + */ + +//L4_INLINE int l4_is_invalid_sched_param (l4_sched_param_t sp); + +/*----------------------------------------------------------------------------- + * IMPLEMENTATION + *---------------------------------------------------------------------------*/ +/* +L4_INLINE int l4_is_invalid_sched_param(l4_sched_param_t sp) +{ + return sp.raw == (l4_umword_t)-1; +} +*/ + + +#endif /* L4_TYPES_H */ + + diff --git a/l4/pkg/l4sys/include/ARCH-arm/utcb.h b/l4/pkg/l4sys/include/ARCH-arm/utcb.h new file mode 100644 index 00000000..52a2738b --- /dev/null +++ b/l4/pkg/l4sys/include/ARCH-arm/utcb.h @@ -0,0 +1,114 @@ +/** + * \file + * \brief UTCB definitions for ARM. + * \ingroup l4_utcb_api + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#ifndef __L4_SYS__INCLUDE__ARCH_ARM__UTCB_H__ +#define __L4_SYS__INCLUDE__ARCH_ARM__UTCB_H__ + +#include + +/** + * \defgroup l4_utcb_api_arm ARM Virtual Registers (UTCB) + * \ingroup l4_utcb_api + */ + +/** + * \brief UTCB constants for ARM + * \ingroup l4_utcb_api_arm + * \hideinitializer + */ +enum L4_utcb_consts_arm +{ + L4_UTCB_EXCEPTION_REGS_SIZE = 20, + L4_UTCB_GENERIC_DATA_SIZE = 63, + L4_UTCB_GENERIC_BUFFERS_SIZE = 58, + + L4_UTCB_MSG_REGS_OFFSET = 0, + L4_UTCB_BUF_REGS_OFFSET = 64 * sizeof(l4_umword_t), + L4_UTCB_THREAD_REGS_OFFSET = 123 * sizeof(l4_umword_t), + + L4_UTCB_INHERIT_FPU = 1UL << 24, + + L4_UTCB_OFFSET = 512, +}; + +/** + * \brief UTCB structure for exceptions. + * \ingroup l4_utcb_api_arm + */ +typedef struct l4_exc_regs_t +{ + l4_umword_t pfa; /**< page fault address */ + l4_umword_t err; /**< error code */ + + l4_umword_t r[13]; /**< registers */ + l4_umword_t sp; /**< stack pointer */ + l4_umword_t ulr; /**< ulr */ + l4_umword_t _dummy1; /**< dummy \internal */ + l4_umword_t pc; /**< pc */ + l4_umword_t cpsr; /**< cpsr */ +} l4_exc_regs_t; + +#include_next + +/* + * ================================================================== + * Implementations. + */ + +#ifdef __GNUC__ +L4_INLINE l4_utcb_t *l4_utcb_direct(void) L4_NOTHROW +{ + register l4_utcb_t *utcb __asm__ ("r0"); + __asm__ volatile ("mov lr, pc \n" + "mov pc, #0xffffff00 \n" + : "=r"(utcb) : : "lr"); + return utcb; +} +#endif + +L4_INLINE l4_umword_t l4_utcb_exc_pc(l4_exc_regs_t *u) L4_NOTHROW +{ + return u->pc; +} + +L4_INLINE void l4_utcb_exc_pc_set(l4_exc_regs_t *u, l4_addr_t pc) L4_NOTHROW +{ + u->pc = pc; +} + +L4_INLINE l4_umword_t l4_utcb_exc_typeval(l4_exc_regs_t *u) L4_NOTHROW +{ + return u->err; +} + +L4_INLINE int l4_utcb_exc_is_pf(l4_exc_regs_t *u) L4_NOTHROW +{ + return u->err & 0x00010000; +} + +L4_INLINE l4_addr_t l4_utcb_exc_pfa(l4_exc_regs_t *u) L4_NOTHROW +{ + return (u->pfa & ~3) | (!(u->err & 0x00020000) << 1); +} + +#endif /* ! __L4_SYS__INCLUDE__ARCH_ARM__UTCB_H__ */ diff --git a/l4/pkg/l4sys/include/ARCH-arm/vm b/l4/pkg/l4sys/include/ARCH-arm/vm new file mode 100644 index 00000000..668e5812 --- /dev/null +++ b/l4/pkg/l4sys/include/ARCH-arm/vm @@ -0,0 +1,56 @@ +// vi:ft=cpp +/** + * \file + * \brief ARM virtualization interface + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg , + * Torsten Frenzel + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ + +#pragma once + +#include +#include + +namespace L4 { + +/** + * \brief TZ Virtual machine. + * \ingroup l4_vm_tz_api + */ +class Vm : public Kobject_t +{ +protected: + Vm(); + +private: + Vm(Vm const &); + void operator = (Vm const &); + +public: + /** + * \copydoc l4_vm_run() + * \note \a dst_task is the implicit \a this pointer. + */ + l4_msgtag_t run(l4_fpage_t const &fpage, l4_umword_t *label, + l4_utcb_t *utcb = l4_utcb()) throw() + { return l4_vm_run_u(cap(), fpage, label, utcb); } +}; + +}; diff --git a/l4/pkg/l4sys/include/ARCH-arm/vm.h b/l4/pkg/l4sys/include/ARCH-arm/vm.h new file mode 100644 index 00000000..23e2ee73 --- /dev/null +++ b/l4/pkg/l4sys/include/ARCH-arm/vm.h @@ -0,0 +1,139 @@ +/** + * \file + * \brief ARM virtualization interface. + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Torsten Frenzel + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#pragma once + +#include +#include + +/** + * \defgroup l4_vm_tz_api VM API for TZ + * \brief Virtual Machine API for ARM TrustZone + * \ingroup l4_vm_api + */ + +/** + * \brief state structure for TrustZone VMs + * \ingroup l4_vm_tz_api + */ +struct l4_vm_state +{ + l4_umword_t r[13]; // r0 - r12 + + l4_umword_t sp_usr; + l4_umword_t lr_usr; + + l4_umword_t sp_irq; + l4_umword_t lr_irq; + l4_umword_t spsr_irq; + + l4_umword_t r_fiq[5]; // r8 - r12 + l4_umword_t sp_fiq; + l4_umword_t lr_fiq; + l4_umword_t spsr_fiq; + + l4_umword_t sp_abt; + l4_umword_t lr_abt; + l4_umword_t spsr_abt; + + l4_umword_t sp_und; + l4_umword_t lr_und; + l4_umword_t spsr_und; + + l4_umword_t sp_svc; + l4_umword_t lr_svc; + l4_umword_t spsr_svc; + + l4_umword_t pc; + l4_umword_t cpsr; + + l4_umword_t pending_events; + + l4_umword_t cp15_ttbr0; + l4_umword_t cp15_ttbr1; + l4_umword_t cp15_ttbc; + l4_umword_t cp15_vector_base; + l4_umword_t cp15_dfsr; + l4_umword_t cp15_dfar; + l4_umword_t cp15_ifsr; + l4_umword_t cp15_ifar; + l4_umword_t cp15_control; + l4_umword_t cp15_prim_region_remap; + l4_umword_t cp15_norm_region_remap; + l4_umword_t cp15_cid; // banked + l4_umword_t cp15_tls[3]; // banked + l4_umword_t cp10_fpexc; + + l4_umword_t pfs; + l4_umword_t pfa; + l4_umword_t exit_reason; +}; + + +/** + * \brief Run a VM + * \ingroup l4_vm_tz_api + * + * \param vm Capability selector for VM + */ +L4_INLINE l4_msgtag_t +l4_vm_run(l4_cap_idx_t vm, l4_fpage_t const vm_state_fpage, + l4_umword_t *label) L4_NOTHROW; + +/** + * \internal + * \ingroup l4_vm_tz_api + */ +L4_INLINE l4_msgtag_t +l4_vm_run_u(l4_cap_idx_t vm, l4_fpage_t const vm_state_fpage, + l4_umword_t *label, l4_utcb_t *u) L4_NOTHROW; + +/** + * \internal + * \brief Operations on task objects. + * \ingroup l4_vm_tz_api + */ +enum +{ + L4_VM_RUN_OP = 0 /* Run a VM */ +}; + + +/****** Implementations ****************/ + +L4_INLINE l4_msgtag_t +l4_vm_run_u(l4_cap_idx_t vm, l4_fpage_t const vm_state_fpage, + l4_umword_t *label, l4_utcb_t *u) L4_NOTHROW +{ + l4_msg_regs_t *r = l4_utcb_mr_u(u); + r->mr[0] = L4_VM_RUN_OP; + r->mr[1] = vm_state_fpage.raw; + + return l4_ipc(vm, u, L4_SYSF_CALL, *label, l4_msgtag(L4_PROTO_TASK, 3, 0, 0), label, L4_IPC_NEVER); +} + +L4_INLINE l4_msgtag_t +l4_vm_run(l4_cap_idx_t vm, l4_fpage_t const vm_state_fpage, + l4_umword_t *label) L4_NOTHROW +{ + return l4_vm_run_u(vm, vm_state_fpage, label, l4_utcb()); +} diff --git a/l4/pkg/l4sys/include/ARCH-ppc32/L4API-l4f/__kernel_object_impl.h b/l4/pkg/l4sys/include/ARCH-ppc32/L4API-l4f/__kernel_object_impl.h new file mode 100644 index 00000000..b271ea28 --- /dev/null +++ b/l4/pkg/l4sys/include/ARCH-ppc32/L4API-l4f/__kernel_object_impl.h @@ -0,0 +1,55 @@ +/** + * \file + * \brief Low-level kernel functions for PPC32 + */ +/* + * (c) 2008-2009 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#pragma once + +#ifndef L4_SYSCALL_MAGIC_OFFSET +# define L4_SYSCALL_MAGIC_OFFSET 8 +#endif +#define L4_SYSCALL_DEBUGGER (-0x0000000C-L4_SYSCALL_MAGIC_OFFSET) + + +L4_INLINE l4_msgtag_t +l4_invoke_debugger(l4_cap_idx_t obj, l4_msgtag_t tag, l4_utcb_t *utcb) L4_NOTHROW +{ + register unsigned long _obj asm ("r4") = obj; + register unsigned long _a1 asm ("r3") = tag.raw; + register void* _a4 asm ("r5") = utcb; + + __asm__ __volatile__ + ("bla %[addr]\n" + : + "=r" (_obj), + "=r" (_a1), + "=r" (_a4) + : + [addr] "i" (L4_SYSCALL_DEBUGGER), + "0" (_obj), + "1" (_a1), + "2" (_a4) + : + "memory", "lr" + ); + + tag.raw = _a1; // gcc doesn't like the return out of registers variables + return tag; +} + diff --git a/l4/pkg/l4sys/include/ARCH-ppc32/L4API-l4f/ipc.h b/l4/pkg/l4sys/include/ARCH-ppc32/L4API-l4f/ipc.h new file mode 100644 index 00000000..e1a3e829 --- /dev/null +++ b/l4/pkg/l4sys/include/ARCH-ppc32/L4API-l4f/ipc.h @@ -0,0 +1,264 @@ +/*! + * \file + * \brief L4 IPC System Calls, PPC + * \ingroup api_calls + */ +/* + * (c) 2009 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#pragma once + +#ifdef __GNUC__ + +#include + +#include_next + +#define L4_IPC_CAPMAPMSG_BASE 0xf0000100 ///< Capability mapmsg base + +#ifndef L4_SYSCALL_MAGIC_OFFSET +# define L4_SYSCALL_MAGIC_OFFSET 8 +#endif +#define L4_SYSCALL_INVOKE (-0x00000004-L4_SYSCALL_MAGIC_OFFSET) + +L4_INLINE l4_msgtag_t +l4_ipc_call(l4_cap_idx_t dest, l4_utcb_t *utcb, + l4_msgtag_t tag, + l4_timeout_t timeout) L4_NOTHROW +{ + register l4_umword_t _dest __asm__("r4") = dest | L4_SYSF_CALL; + register l4_umword_t _timeout __asm__("r5") = timeout.raw; + register l4_umword_t _flags __asm__("r6") = 0; + register l4_msgtag_t _tag __asm__("r3") = tag; + (void)utcb; + + __asm__ __volatile__ + (" bla %[addr] \n" + : + "=r" (_dest), + "=r" (_timeout), + "=r" (_flags), + "=r" (_tag) + : + [addr]"i" (L4_SYSCALL_INVOKE), + "0" (_dest), + "1" (_timeout), + "2" (_flags), + "3" (_tag) + : + "lr", "memory"); + + tag.raw = _tag.raw; // because gcc doesn't return out of registers variables + return tag; +} + +L4_INLINE l4_msgtag_t +l4_ipc_reply_and_wait(l4_utcb_t *utcb, l4_msgtag_t tag, + l4_umword_t *label, + l4_timeout_t timeout) L4_NOTHROW +{ + register l4_umword_t _dest __asm__("r4") = L4_INVALID_CAP | L4_SYSF_REPLY_AND_WAIT; + register l4_umword_t _timeout __asm__("r5") = timeout.raw; + register l4_msgtag_t _tag __asm__("r3") = tag; + register l4_umword_t _flags __asm__("r6") = 0; + (void)utcb; + + __asm__ __volatile__ + (" bla %[addr] \n" + : + "=r" (_dest), + "=r" (_timeout), + "=r" (_flags), + "=r" (_tag) + : + [addr]"i" (L4_SYSCALL_INVOKE), + "0" (_dest), + "1" (_timeout), + "2" (_flags), + "3" (_tag) + : + "lr", "memory"); + *label = _flags; + tag.raw = _tag.raw; // because gcc doesn't return out of registers variables + return tag; +} + +L4_INLINE l4_msgtag_t +l4_ipc_send_and_wait(l4_cap_idx_t dest, l4_utcb_t *utcb, + l4_msgtag_t tag, + l4_umword_t *src, + l4_timeout_t timeout) L4_NOTHROW +{ + register l4_umword_t _dest __asm__("r4") = dest | L4_SYSF_SEND_AND_WAIT; + register l4_umword_t _timeout __asm__("r5") = timeout.raw; + register l4_msgtag_t _tag __asm__("r3") = tag; + register l4_umword_t _flags __asm__("r6") = 0; + (void)utcb; + + __asm__ __volatile__ + (" bla %[addr] \n" + : + "=r" (_dest), + "=r" (_timeout), + "=r" (_flags), + "=r" (_tag) + : + [addr] "i" (L4_SYSCALL_INVOKE), + "0" (_dest), + "1" (_timeout), + "2" (_flags), + "3" (_tag) + : + "memory", "lr"); + *src = _flags; + tag.raw = _tag.raw; // because gcc doesn't return out of registers variables + return tag; +} + +L4_INLINE l4_msgtag_t +l4_ipc_send(l4_cap_idx_t dest, l4_utcb_t *utcb, + l4_msgtag_t tag, + l4_timeout_t timeout) L4_NOTHROW +{ + register l4_umword_t _dest __asm__("r4") = dest | L4_SYSF_SEND; + register l4_umword_t _timeout __asm__("r5") = timeout.raw; + register l4_umword_t _flags __asm__("r6") = 0; + register l4_msgtag_t _tag __asm__("r3") = tag; + (void)utcb; + + __asm__ __volatile__ + ("bla %[addr] \n" + : + "=r" (_dest), + "=r" (_timeout), + "=r" (_flags), + "=r" (_tag) + : + [addr] "i" (L4_SYSCALL_INVOKE), + "0" (_dest), + "1" (_timeout), + "2" (_flags), + "3" (_tag) + : + "memory", "lr"); + tag.raw = _tag.raw; // because gcc doesn't return out of registers variables + return tag; +} + +L4_INLINE l4_msgtag_t +l4_ipc_wait(l4_utcb_t *utcb, l4_umword_t *src, + l4_timeout_t timeout) L4_NOTHROW +{ + l4_msgtag_t rtag; + register l4_umword_t _r __asm__("r4") = L4_INVALID_CAP | L4_SYSF_WAIT; + register l4_umword_t _timeout __asm__("r5") = timeout.raw; + register l4_msgtag_t _tag __asm__("r3"); + register l4_umword_t _flags __asm__("r6") = 0; + (void)utcb; + _tag.raw = 0; + + __asm__ __volatile__ + ("bla %[addr] \n" + : + "=r"(_r), + "=r"(_timeout), + "=r"(_flags), + "=r"(_tag) + : + [addr] "i"(L4_SYSCALL_INVOKE), + "0"(_r), + "1"(_timeout), + "2"(_flags), + "3"(_tag) + + : + "memory", "lr"); + *src = _flags; + rtag.raw = _tag.raw; // because gcc doesn't return out of registers variables + return rtag; +} + +L4_INLINE l4_msgtag_t +l4_ipc_receive(l4_cap_idx_t src, l4_utcb_t *utcb, + l4_timeout_t timeout) L4_NOTHROW +{ + l4_msgtag_t rtag; + register l4_umword_t _r __asm__("r4") = src | L4_SYSF_RECV; + register l4_umword_t _timeout __asm__("r5") = timeout.raw; + register l4_msgtag_t _tag __asm__("r3"); + register l4_umword_t _flags __asm__("r6") = 0; + (void)utcb; + + _tag.raw = 0; + + __asm__ __volatile__ + ("bla %[addr] \n" + : + "=r"(_r), + "=r"(_timeout), + "=r"(_flags), + "=r"(_tag) + : + [addr] "i"(L4_SYSCALL_INVOKE), + "0"(_r), + "1"(_timeout), + "2"(_flags), + "3"(_tag) + : + "memory", "lr"); + rtag.raw = _tag.raw; // because gcc doesn't return out of registers variables + return rtag; +} + +// todo: let all calls above use this single call +L4_INLINE l4_msgtag_t +l4_ipc(l4_cap_idx_t dest, l4_utcb_t *utcb, + l4_umword_t flags, + l4_umword_t slabel, + l4_msgtag_t tag, + l4_umword_t *rlabel, + l4_timeout_t timeout) L4_NOTHROW +{ + register l4_umword_t _dest __asm__("r4") = dest | flags; + register l4_umword_t _timeout __asm__("r5") = timeout.raw; + register l4_msgtag_t _tag __asm__("r3") = tag; + register l4_umword_t _lab __asm__("r6") = slabel; + (void)utcb; + + __asm__ __volatile__ + ("bla %[addr] \n" + : + "=r" (_dest), + "=r" (_timeout), + "=r" (_lab), + "=r" (_tag) + : + [addr] "i" (L4_SYSCALL_INVOKE), + "0" (_dest), + "1" (_timeout), + "2" (_lab), + "3" (_tag) + : + "memory", "lr"); + *rlabel = _lab; + tag.raw = _tag.raw; // because gcc doesn't return out of registers variables + return tag; +} + +#include + +#endif //__GNUC__ diff --git a/l4/pkg/l4sys/include/ARCH-ppc32/__vcpu-arch.h b/l4/pkg/l4sys/include/ARCH-ppc32/__vcpu-arch.h new file mode 100644 index 00000000..aadf5266 --- /dev/null +++ b/l4/pkg/l4sys/include/ARCH-ppc32/__vcpu-arch.h @@ -0,0 +1,51 @@ +/* + * (c) 2010 Adam Lackorzynski , + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#pragma once + +#include + +/** + * \brief vCPU registers. + * \ingroup l4_vcpu_api + */ +typedef struct l4_vcpu_regs_t +{ + l4_umword_t pfa; + l4_umword_t err; + + l4_umword_t r[28]; + l4_umword_t sp; + l4_umword_t lr; + l4_umword_t _dummy; + l4_umword_t ip; + l4_umword_t flags; + + /* And some more */ +} l4_vcpu_regs_t; + +/** + * \brief vCPU message registers. + * \ingroup l4_vcpu_api + */ +typedef struct l4_vcpu_ipc_regs_t +{ + l4_msgtag_t tag; + l4_umword_t _d1[3]; + l4_umword_t label; + l4_umword_t _d2[8]; +} l4_vcpu_ipc_regs_t; diff --git a/l4/pkg/l4sys/include/ARCH-ppc32/atomic.h b/l4/pkg/l4sys/include/ARCH-ppc32/atomic.h new file mode 100644 index 00000000..256e5fdd --- /dev/null +++ b/l4/pkg/l4sys/include/ARCH-ppc32/atomic.h @@ -0,0 +1,27 @@ +/* + * (c) 2009 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#pragma once + +EXTERN_C long int +l4_atomic_add(volatile long int* mem, long int offset) L4_NOTHROW; + +EXTERN_C long int +l4_atomic_cmpxchg(volatile long int* mem, long int oldval, long int newval) L4_NOTHROW; + +EXTERN_C long int +l4_atomic_xchg(volatile long int* mem, long int newval) L4_NOTHROW; diff --git a/l4/pkg/l4sys/include/ARCH-ppc32/cache.h b/l4/pkg/l4sys/include/ARCH-ppc32/cache.h new file mode 100644 index 00000000..5ed856d2 --- /dev/null +++ b/l4/pkg/l4sys/include/ARCH-ppc32/cache.h @@ -0,0 +1,67 @@ +/** + * \file + * \brief Cache functions + */ +/* + * (c) 2008-2009 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#ifndef __L4SYS__INCLUDE__ARCH_PPC32__CACHE_H__ +#define __L4SYS__INCLUDE__ARCH_PPC32__CACHE_H__ + +#include_next + +L4_INLINE void +l4_cache_clean_data(unsigned long start, + unsigned long end) L4_NOTHROW +{ + (void)start; (void)end; +} + +L4_INLINE void +l4_cache_flush_data(unsigned long start, + unsigned long end) L4_NOTHROW +{ + (void)start; (void)end; +} + +L4_INLINE void +l4_cache_inv_data(unsigned long start, + unsigned long end) L4_NOTHROW +{ + (void)start; (void)end; +} + +L4_INLINE void +l4_cache_coherent(unsigned long start, + unsigned long end) L4_NOTHROW +{ + (void)start; (void)end; +} + +L4_INLINE void +l4_cache_dma_coherent(unsigned long start, + unsigned long end) L4_NOTHROW +{ + (void)start; (void)end; +} + +L4_INLINE void +l4_cache_dma_coherent_full(void) L4_NOTHROW +{ +} + +#endif /* ! __L4SYS__INCLUDE__ARCH_PPC32__CACHE_H__ */ diff --git a/l4/pkg/l4sys/include/ARCH-ppc32/consts.h b/l4/pkg/l4sys/include/ARCH-ppc32/consts.h new file mode 100644 index 00000000..25b7a9b9 --- /dev/null +++ b/l4/pkg/l4sys/include/ARCH-ppc32/consts.h @@ -0,0 +1,45 @@ +/*****************************************************************************/ +/*! + * \file l4sys/include/ARCH-ppc32/consts.h + * \brief Common L4 constants, ppc32 version + * \ingroup api_types_ppc32 + */ +/* + * (c) 2009 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +/*****************************************************************************/ +#ifndef _L4_SYS_CONSTS_H +#define _L4_SYS_CONSTS_H + +/* L4 includes */ +#include + +/** + * Sizeof a page in log2 + * \ingroup api_types_common + */ +#define L4_PAGESHIFT 12 + +/** + * Sizeof a large page in log2 + * \ingroup api_types_common + */ +#define L4_SUPERPAGESHIFT 22 + +#include_next + +#endif /* !_L4_SYS_CONSTS_H */ diff --git a/l4/pkg/l4sys/include/ARCH-ppc32/kdebug.h b/l4/pkg/l4sys/include/ARCH-ppc32/kdebug.h new file mode 100644 index 00000000..5b45526b --- /dev/null +++ b/l4/pkg/l4sys/include/ARCH-ppc32/kdebug.h @@ -0,0 +1,241 @@ +/* + * (c) 2009 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#ifndef __L4SYS__INCLUDE__ARCH_PPC32__KDEBUG_H__ +#define __L4SYS__INCLUDE__ARCH_PPC32__KDEBUG_H__ + +#include +#include +#ifdef __GNUC__ + +#ifndef L4_SYSCALL_MAGIC_OFFSET +# define L4_SYSCALL_MAGIC_OFFSET 8 +#endif +#define L4_SYSCALL_ENTER_KDEBUG (-0x00000020-L4_SYSCALL_MAGIC_OFFSET) + + +#define enter_kdebug(text...) \ +__asm__ __volatile__ ( \ + " mr %%r3, %1 \n" \ + " bla %0 \n" \ + " b 1f \n" \ + " .ascii \"" text "\" \n" \ + " .byte 0 \n" \ + " .align 4 \n" \ + "1: \n" \ + : \ + : "i" (L4_SYSCALL_ENTER_KDEBUG), \ + "r" (1 << 30) \ + : "lr", "r3") + +L4_INLINE void +outnstring(const char* x, unsigned len); + +L4_INLINE void +outstring(const char *text); + +L4_INLINE void +outchar(char c); + +L4_INLINE void +outdec(int number); + +L4_INLINE void +outhex32(int number); + +L4_INLINE void +outhex20(int number); + +L4_INLINE void +outhex16(int number); + +L4_INLINE void +outhex12(int number); + +L4_INLINE void +outhex8(int number); + +L4_INLINE void +kd_display(char *text); + +L4_INLINE int +l4kd_inchar(void); + +L4_INLINE void +l4_sys_cli(void); + +L4_INLINE void +l4_sys_sti(void); + +L4_INLINE void +l4_kdebug_imb(void); + +L4_INLINE int +l4_irq_enabled(void); + +L4_INLINE void __touch_ro(const char *x, unsigned len); + +L4_INLINE unsigned long +__kdebug_param(unsigned long nr, unsigned long p1, unsigned long p2); + +L4_INLINE unsigned long +__kdebug_param_5(unsigned long nr, unsigned long p1, unsigned long p2, + unsigned long p3, unsigned long p4, unsigned long p5); + +L4_INLINE +unsigned long +__kdebug_param(unsigned long nr, unsigned long p1, unsigned long p2) +{ + register unsigned long r3 asm("r3") = (nr) | (1 << 31); + register unsigned long r4 asm("r4") = (p1); + register unsigned long r5 asm("r5") = (p2); + asm volatile ( " bla %1 \n" + : "=r" (r4) + : "i" (L4_SYSCALL_ENTER_KDEBUG), + "0" (r4), "r" (r3), "r" (r5) + : "lr" + ); + return r4; +} + +L4_INLINE +unsigned long +__kdebug_param_5(unsigned long nr, unsigned long p1, unsigned long p2, + unsigned long p3, unsigned long p4, unsigned long p5) +{ + register unsigned long r3 asm("r3") = (nr) | (1 << 31); + register unsigned long r4 asm("r4") = (p1); + register unsigned long r5 asm("r5") = (p2); + register unsigned long r6 asm("r6") = (p3); + register unsigned long r7 asm("r7") = (p4); + register unsigned long r8 asm("r8") = (p5); + + asm volatile ( " bla %1 \n" + : "=r" (r4) + : "i" (L4_SYSCALL_ENTER_KDEBUG), + "0" (r4), "r" (r3), "r" (r5), + "r" (r6), "r" (r7), "r" (r8) + : "lr" + ); + return r4; +} + +L4_INLINE void +__touch_ro(const char *x, unsigned len) +{ + volatile const char *sptr, *eptr; + sptr = (const char*)((unsigned)x & L4_PAGEMASK); + eptr = (const char*)(((unsigned)x + len -1) & L4_PAGEMASK); + + for(;sptr <= eptr; sptr += L4_PAGESIZE) + (void)(*sptr); +} + +L4_INLINE void +outnstring(const char* x, unsigned len) +{ + __touch_ro(x, len); + __kdebug_param(3, (unsigned long)x, (unsigned long)len); +} + +L4_INLINE void +outstring(const char *text) +{ + unsigned i = 0; + while(text[i++]) ; + outnstring(text, i); +} + +L4_INLINE void +outchar(char c) +{ + __kdebug_param(1, (unsigned long)c, 0); +} + +L4_INLINE void +outdec(int number) +{ + __kdebug_param(4, (unsigned long)number, 0); +} + +L4_INLINE void +outhex32(int number) +{ + __kdebug_param(5, (unsigned long)number, 0); +} + +L4_INLINE void +outhex20(int number) +{ + __kdebug_param(6, (unsigned long)number, 0); +} + +L4_INLINE void +outhex16(int number) +{ + __kdebug_param(7, (unsigned long)number, 0); +} + +L4_INLINE void +outhex12(int number) +{ + __kdebug_param(8, (unsigned long)number, 0); +} + +L4_INLINE void +outhex8(int number) +{ + __kdebug_param(9, (unsigned long)number, 0); +} + +L4_INLINE void +kd_display(char *text) +{ + outstring(text); +} + +L4_INLINE int +l4kd_inchar(void) +{ + return __kdebug_param(0xd, 0, 0); +} + +L4_INLINE void +l4_sys_cli(void) +{ + __kdebug_param(0x32, 0, 0); +} + +L4_INLINE void +l4_sys_sti(void) +{ + __kdebug_param(0x33, 0, 0); +} + +L4_INLINE void +l4_kdebug_imb(void) +{ + // __KDEBUG_ARM_PARAM_0(0x3f); +} +L4_INLINE int +l4_irq_enabled(void) +{ + return __kdebug_param(0x34, 0, 0); +} +#endif //__GNUC__ + +#endif /* ! __L4SYS__INCLUDE__ARCH_PPC32__KDEBUG_H__ */ diff --git a/l4/pkg/l4sys/include/ARCH-ppc32/l4int.h b/l4/pkg/l4sys/include/ARCH-ppc32/l4int.h new file mode 100644 index 00000000..3065d176 --- /dev/null +++ b/l4/pkg/l4sys/include/ARCH-ppc32/l4int.h @@ -0,0 +1,37 @@ +/** + * \file + * \brief Fixed sized integer types, ppc32 version + * \ingroup l4_basic_types + */ +/* + * (c) 2008-2009 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#pragma once + +#include_next + +/** + * \addtogroup l4_basic_types + */ +/*@{*/ + +#define L4_MWORD_BITS 32 /**< Size of machine words in bits */ + +typedef unsigned int l4_size_t; /**< \brief Signed size type */ +typedef signed int l4_ssize_t; /**< \brief Unsigned size type */ +/*@}*/ + diff --git a/l4/pkg/l4sys/include/ARCH-ppc32/linkage.h b/l4/pkg/l4sys/include/ARCH-ppc32/linkage.h new file mode 100644 index 00000000..0f84b417 --- /dev/null +++ b/l4/pkg/l4sys/include/ARCH-ppc32/linkage.h @@ -0,0 +1,53 @@ +/** + * \file + * \brief Linkage + * \ingroup l4sys_api + */ +/* + * (c) 2008-2009 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#ifndef __L4__SYS__ARCH_PPC32__LINKAGE_H__ +#define __L4__SYS__ARCH_PPC32__LINKAGE_H__ + +#ifdef __ASSEMBLY__ + +#ifndef ENTRY +#define ENTRY(name) \ + .globl name; \ + .p2align(2); \ + name: + +#endif /* ! ENTRY */ +#endif /* __ASSEMBLY__ */ + +#define L4_FASTCALL(x) +#define l4_fastcall + +/** + * Define calling convention. + * \ingroup l4sys_defines + * \hideinitializer + */ +#define L4_CV + +#ifdef __PIC__ +#define L4_LONG_CALL +#else +#define L4_LONG_CALL __attribute__((longcall)) +#endif + +#endif /* ! __L4__SYS__ARCH_PPC32__LINKAGE_H__ */ diff --git a/l4/pkg/l4sys/include/ARCH-ppc32/types.h b/l4/pkg/l4sys/include/ARCH-ppc32/types.h new file mode 100644 index 00000000..f330687c --- /dev/null +++ b/l4/pkg/l4sys/include/ARCH-ppc32/types.h @@ -0,0 +1,35 @@ +/** + * \file + * \brief Types for PPC32 + */ +/* + * (c) 2008-2009 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#ifndef L4_TYPES_H +#define L4_TYPES_H + +#include_next + +#include +#include +#include + +#include + +#include + +#endif /* L4_TYPES_H */ diff --git a/l4/pkg/l4sys/include/ARCH-ppc32/utcb.h b/l4/pkg/l4sys/include/ARCH-ppc32/utcb.h new file mode 100644 index 00000000..8ede8d97 --- /dev/null +++ b/l4/pkg/l4sys/include/ARCH-ppc32/utcb.h @@ -0,0 +1,121 @@ +/** + * \file + * \brief UTCB definitions for PPC32. + * \ingroup l4_utcb_api + */ +/* + * (c) 2008-2009 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#ifndef __L4_SYS__INCLUDE__ARCH_PPC32__UTCB_H__ +#define __L4_SYS__INCLUDE__ARCH_PPC32__UTCB_H__ + +#include + +/** + * \defgroup l4_utcb_api_arm PPC32 Virtual Registers (UTCB) + * \ingroup l4_utcb_api + */ + +/** + * \brief UTCB constants for PPC32 + * \ingroup l4_utcb_api_arm + * \hideinitializer + */ +enum L4_utcb_consts_ppc32 +{ + L4_UTCB_EXCEPTION_REGS_SIZE = 39, + L4_UTCB_GENERIC_DATA_SIZE = 63, + L4_UTCB_GENERIC_BUFFERS_SIZE = 58, + + L4_UTCB_MSG_REGS_OFFSET = 0, + L4_UTCB_BUF_REGS_OFFSET = 64 * sizeof(l4_umword_t), + L4_UTCB_THREAD_REGS_OFFSET = 123 * sizeof(l4_umword_t), + + L4_UTCB_INHERIT_FPU = 1UL << 24, + + L4_UTCB_OFFSET = 512, +}; + +/** + * \brief UTCB structure for exceptions. + * \ingroup l4_utcb_api_arm + */ +typedef struct l4_exc_regs_t +{ + l4_umword_t pfa; /**< page fault address */ + l4_umword_t err; /**< error code */ + + l4_umword_t r[28]; /** GPR 0,3 .. 10, 13 .. 31 */ + l4_umword_t xer; /**< fixed point exception register */ + l4_umword_t ctr; /**< count register */ + l4_umword_t cr; /**< condition register */ + l4_umword_t dummy; /**< dummy */ + l4_umword_t srr0; /**< IP */ + l4_umword_t lr; /**< ulr */ + l4_umword_t sp; /**< stack pointer */ + l4_umword_t r12; /**< GPR 12 */ + l4_umword_t r11; /**< GPR 11 */ +} l4_exc_regs_t; + +#include_next + +/* + * ================================================================== + * Implementations. + */ + +#ifdef __GNUC__ +L4_INLINE l4_utcb_t *l4_utcb_direct(void) L4_NOTHROW +{ + l4_utcb_t *utcb; + + __asm__ __volatile__ + ("mr %[utcb], %%r2\n" + : [utcb] "=r" (utcb) + : ); + + return utcb; +} +#endif + +L4_INLINE l4_umword_t l4_utcb_exc_pc(l4_exc_regs_t *u) L4_NOTHROW +{ + return u->srr0; +} + +L4_INLINE void l4_utcb_exc_pc_set(l4_exc_regs_t *u, l4_addr_t pc) L4_NOTHROW +{ + u->srr0 = pc; +} + +L4_INLINE l4_umword_t l4_utcb_exc_typeval(l4_exc_regs_t *u) L4_NOTHROW +{ + return u->err; +} + +//TODO: cbass check pfa values +L4_INLINE int l4_utcb_exc_is_pf(l4_exc_regs_t *u) L4_NOTHROW +{ + return u->err & 0x00010000; +} + +L4_INLINE l4_addr_t l4_utcb_exc_pfa(l4_exc_regs_t *u) L4_NOTHROW +{ + return (u->pfa & ~3) | (!(u->err & 0x00020000) << 1); +} + +#endif /* ! __L4_SYS__INCLUDE__ARCH_PPC32__UTCB_H__ */ diff --git a/l4/pkg/l4sys/include/ARCH-sparc/L4API-l4f/__kernel_object_impl.h b/l4/pkg/l4sys/include/ARCH-sparc/L4API-l4f/__kernel_object_impl.h new file mode 100644 index 00000000..34dc46fc --- /dev/null +++ b/l4/pkg/l4sys/include/ARCH-sparc/L4API-l4f/__kernel_object_impl.h @@ -0,0 +1,41 @@ +/** + * \file + * \brief Low-level kernel functions for SPARC + */ +/* + * (c) 2010 Adam Lackorzynski + * Björn Döbel + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#pragma once + +#ifndef L4_SYSCALL_MAGIC_OFFSET +# define L4_SYSCALL_MAGIC_OFFSET 8 +#endif +#define L4_SYSCALL_DEBUGGER (-0x0000000C-L4_SYSCALL_MAGIC_OFFSET) + + +L4_INLINE l4_msgtag_t +l4_invoke_debugger(l4_cap_idx_t obj, l4_msgtag_t tag, l4_utcb_t *utcb) L4_NOTHROW +{ + (void)obj; + (void)tag; + (void)utcb; + l4_msgtag_t t; + t.raw = ~0; + return t; +} + diff --git a/l4/pkg/l4sys/include/ARCH-sparc/L4API-l4f/ipc.h b/l4/pkg/l4sys/include/ARCH-sparc/L4API-l4f/ipc.h new file mode 100644 index 00000000..ea4ca87c --- /dev/null +++ b/l4/pkg/l4sys/include/ARCH-sparc/L4API-l4f/ipc.h @@ -0,0 +1,141 @@ +/** + * \file + * \brief L4 IPC System Calls, Sparc + * \ingroup api_calls + */ +/* + * (c) 2010 Adam Lackorzynski + * Björn Döbel + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#pragma once + +#include_next + +#ifdef __GNUC__ + +#include +#include + +L4_INLINE l4_msgtag_t +l4_ipc_call(l4_cap_idx_t dest, l4_utcb_t *utcb, + l4_msgtag_t tag, + l4_timeout_t timeout) L4_NOTHROW +{ + (void)dest; + (void)utcb; + (void)tag; + (void)timeout; + l4_msgtag_t t; + t.raw = ~0; + return t; +} + +L4_INLINE l4_msgtag_t +l4_ipc_reply_and_wait(l4_utcb_t *utcb, l4_msgtag_t tag, + l4_umword_t *label, + l4_timeout_t timeout) L4_NOTHROW +{ + (void)utcb; + (void)tag; + (void)label; + (void)timeout; + l4_msgtag_t t; + t.raw = ~0; + return t; +} + + +L4_INLINE l4_msgtag_t +l4_ipc_send_and_wait(l4_cap_idx_t dest, l4_utcb_t *utcb, + l4_msgtag_t tag, + l4_umword_t *src, + l4_timeout_t timeout) L4_NOTHROW +{ + (void)dest; + (void)utcb; + (void)tag; + (void)src; + (void)timeout; + l4_msgtag_t t; + t.raw = ~0; + return t; +} + +L4_INLINE l4_msgtag_t +l4_ipc_send(l4_cap_idx_t dest, l4_utcb_t *utcb, + l4_msgtag_t tag, + l4_timeout_t timeout) L4_NOTHROW +{ + (void)dest; + (void)utcb; + (void)tag; + (void)timeout; + l4_msgtag_t t; + t.raw = ~0; + return t; +} + +L4_INLINE l4_msgtag_t +l4_ipc_wait(l4_utcb_t *utcb, l4_umword_t *src, + l4_timeout_t timeout) L4_NOTHROW +{ + (void)utcb; + (void)src; + (void)timeout; + l4_msgtag_t t; + t.raw = ~0; + return t; +} + +L4_INLINE l4_msgtag_t +l4_ipc_receive(l4_cap_idx_t src, l4_utcb_t *utcb, + l4_timeout_t timeout) L4_NOTHROW +{ + (void)utcb; + (void)src; + (void)timeout; + l4_msgtag_t t; + t.raw = ~0; + return t; +} + +// todo: let all calls above use this single call +L4_INLINE l4_msgtag_t +l4_ipc(l4_cap_idx_t dest, l4_utcb_t *utcb, + l4_umword_t flags, + l4_umword_t slabel, + l4_msgtag_t tag, + l4_umword_t *rlabel, + l4_timeout_t timeout) L4_NOTHROW +{ + (void)dest; + (void)utcb; + (void)flags; + (void)slabel; + (void)tag; + (void)rlabel; + (void)timeout; + l4_msgtag_t t; + t.raw = ~0; + return t; +} + + +#include + +#endif //__GNUC__ + diff --git a/l4/pkg/l4sys/include/ARCH-sparc/L4API-l4f/syscall_defs.h b/l4/pkg/l4sys/include/ARCH-sparc/L4API-l4f/syscall_defs.h new file mode 100644 index 00000000..0a3082f6 --- /dev/null +++ b/l4/pkg/l4sys/include/ARCH-sparc/L4API-l4f/syscall_defs.h @@ -0,0 +1,32 @@ +/** + * \file + * \brief Syscall entry definitions. + */ +/* + * (c) 2010 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#ifndef __L4SYS__ARCH_ARM__L4API_L4F__SYSCALL_DEFS_H__ +#define __L4SYS__ARCH_ARM__L4API_L4F__SYSCALL_DEFS_H__ + +#ifndef L4_SYSCALL_MAGIC_OFFSET +# define L4_SYSCALL_MAGIC_OFFSET 8 +#endif +#define L4_SYSCALL_INVOKE (-0x00000004-L4_SYSCALL_MAGIC_OFFSET) +#define L4_SYSCALL_MEM_OP (-0x00000008-L4_SYSCALL_MAGIC_OFFSET) +#define L4_SYSCALL_DEBUGGER (-0x0000000C-L4_SYSCALL_MAGIC_OFFSET) + +#endif /* __L4SYS__ARCH_ARM__L4API_L4F__SYSCALL_DEFS_H__ */ diff --git a/l4/pkg/l4sys/include/ARCH-sparc/__vcpu-arch.h b/l4/pkg/l4sys/include/ARCH-sparc/__vcpu-arch.h new file mode 100644 index 00000000..01aaa54c --- /dev/null +++ b/l4/pkg/l4sys/include/ARCH-sparc/__vcpu-arch.h @@ -0,0 +1,51 @@ +/* + * (c) 2009 Adam Lackorzynski , + * Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#pragma once + +#include + +/** + * \brief vCPU registers. + * \ingroup l4_vcpu_api + */ +typedef struct l4_vcpu_regs_t +{ + l4_umword_t pfa; + l4_umword_t err; + + l4_umword_t r[13]; + + l4_umword_t sp; + l4_umword_t lr; + l4_umword_t _dummy; + l4_umword_t ip; + l4_umword_t flags; +} l4_vcpu_regs_t; + +/** + * \brief vCPU message registers. + * \ingroup l4_vcpu_api + */ +typedef struct l4_vcpu_ipc_regs_t +{ + l4_msgtag_t tag; + l4_umword_t _d1[3]; + l4_umword_t label; + l4_umword_t _d2[8]; +} l4_vcpu_ipc_regs_t; diff --git a/l4/pkg/l4sys/include/ARCH-sparc/atomic.h b/l4/pkg/l4sys/include/ARCH-sparc/atomic.h new file mode 100644 index 00000000..33f66ac8 --- /dev/null +++ b/l4/pkg/l4sys/include/ARCH-sparc/atomic.h @@ -0,0 +1,24 @@ +/* + * (c) 2009 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#pragma once + +EXTERN_C long int +l4_atomic_add(volatile long int* mem, long int offset) L4_NOTHROW; + +EXTERN_C long int +l4_atomic_cmpxchg(volatile long int* mem, long int oldval, long int newval) L4_NOTHROW; diff --git a/l4/pkg/l4sys/include/ARCH-sparc/cache.h b/l4/pkg/l4sys/include/ARCH-sparc/cache.h new file mode 100644 index 00000000..5ed856d2 --- /dev/null +++ b/l4/pkg/l4sys/include/ARCH-sparc/cache.h @@ -0,0 +1,67 @@ +/** + * \file + * \brief Cache functions + */ +/* + * (c) 2008-2009 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#ifndef __L4SYS__INCLUDE__ARCH_PPC32__CACHE_H__ +#define __L4SYS__INCLUDE__ARCH_PPC32__CACHE_H__ + +#include_next + +L4_INLINE void +l4_cache_clean_data(unsigned long start, + unsigned long end) L4_NOTHROW +{ + (void)start; (void)end; +} + +L4_INLINE void +l4_cache_flush_data(unsigned long start, + unsigned long end) L4_NOTHROW +{ + (void)start; (void)end; +} + +L4_INLINE void +l4_cache_inv_data(unsigned long start, + unsigned long end) L4_NOTHROW +{ + (void)start; (void)end; +} + +L4_INLINE void +l4_cache_coherent(unsigned long start, + unsigned long end) L4_NOTHROW +{ + (void)start; (void)end; +} + +L4_INLINE void +l4_cache_dma_coherent(unsigned long start, + unsigned long end) L4_NOTHROW +{ + (void)start; (void)end; +} + +L4_INLINE void +l4_cache_dma_coherent_full(void) L4_NOTHROW +{ +} + +#endif /* ! __L4SYS__INCLUDE__ARCH_PPC32__CACHE_H__ */ diff --git a/l4/pkg/l4sys/include/ARCH-sparc/consts.h b/l4/pkg/l4sys/include/ARCH-sparc/consts.h new file mode 100644 index 00000000..4123088f --- /dev/null +++ b/l4/pkg/l4sys/include/ARCH-sparc/consts.h @@ -0,0 +1,45 @@ +/*****************************************************************************/ +/*! + * \file l4sys/include/ARCH-sparc/consts.h + * \brief Common L4 constants, sparc version + * \ingroup api_types_sparc + */ +/* + * (c) 2009 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +/*****************************************************************************/ +#ifndef _L4_SYS_CONSTS_H +#define _L4_SYS_CONSTS_H + +/* L4 includes */ +#include + +/** + * Sizeof a page in log2 + * \ingroup api_types_common + */ +#define L4_PAGESHIFT 12 + +/** + * Sizeof a large page in log2 + * \ingroup api_types_common + */ +#define L4_SUPERPAGESHIFT 22 + +#include_next + +#endif /* !_L4_SYS_CONSTS_H */ diff --git a/l4/pkg/l4sys/include/ARCH-sparc/kdebug.h b/l4/pkg/l4sys/include/ARCH-sparc/kdebug.h new file mode 100644 index 00000000..d4ed6fd9 --- /dev/null +++ b/l4/pkg/l4sys/include/ARCH-sparc/kdebug.h @@ -0,0 +1,215 @@ +/* + * (c) 2009 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#ifndef __L4SYS__INCLUDE__ARCH_SPARC__KDEBUG_H__ +#define __L4SYS__INCLUDE__ARCH_SPARC__KDEBUG_H__ + +#include +#include +#ifdef __GNUC__ + +#ifndef L4_SYSCALL_MAGIC_OFFSET +# define L4_SYSCALL_MAGIC_OFFSET 8 +#endif +#define L4_SYSCALL_ENTER_KDEBUG (-0x00000020-L4_SYSCALL_MAGIC_OFFSET) + + +#define enter_kdebug(text...) do { } while (1) + +L4_INLINE void +outnstring(const char* x, unsigned len); + +L4_INLINE void +outstring(const char *text); + +L4_INLINE void +outchar(char c); + +L4_INLINE void +outdec(int number); + +L4_INLINE void +outhex32(int number); + +L4_INLINE void +outhex20(int number); + +L4_INLINE void +outhex16(int number); + +L4_INLINE void +outhex12(int number); + +L4_INLINE void +outhex8(int number); + +L4_INLINE void +kd_display(char *text); + +L4_INLINE int +l4kd_inchar(void); + +L4_INLINE void +l4_sys_cli(void); + +L4_INLINE void +l4_sys_sti(void); + +L4_INLINE void +l4_kdebug_imb(void); + +L4_INLINE int +l4_irq_enabled(void); + +L4_INLINE void __touch_ro(const char *x, unsigned len); + +L4_INLINE unsigned long +__kdebug_param(unsigned long nr, unsigned long p1, unsigned long p2); + +L4_INLINE unsigned long +__kdebug_param_5(unsigned long nr, unsigned long p1, unsigned long p2, + unsigned long p3, unsigned long p4, unsigned long p5); + +L4_INLINE +unsigned long +__kdebug_param(unsigned long nr, unsigned long p1, unsigned long p2) +{ + (void)nr; + (void)p1; + (void)p2; + return -1; +} + +L4_INLINE +unsigned long +__kdebug_param_5(unsigned long nr, unsigned long p1, unsigned long p2, + unsigned long p3, unsigned long p4, unsigned long p5) +{ + (void)nr; + (void)p1; + (void)p2; + (void)p3; + (void)p4; + (void)p5; + return -1; +} + +L4_INLINE void +__touch_ro(const char *x, unsigned len) +{ + volatile const char *sptr, *eptr; + sptr = (const char*)((unsigned)x & L4_PAGEMASK); + eptr = (const char*)(((unsigned)x + len -1) & L4_PAGEMASK); + + for(;sptr <= eptr; sptr += L4_PAGESIZE) + (void)(*sptr); +} + +L4_INLINE void +outnstring(const char* x, unsigned len) +{ + __touch_ro(x, len); + __kdebug_param(3, (unsigned long)x, (unsigned long)len); +} + +L4_INLINE void +outstring(const char *text) +{ + unsigned i = 0; + while(text[i++]) ; + outnstring(text, i); +} + +L4_INLINE void +outchar(char c) +{ + __kdebug_param(1, (unsigned long)c, 0); +} + +L4_INLINE void +outdec(int number) +{ + __kdebug_param(4, (unsigned long)number, 0); +} + +L4_INLINE void +outhex32(int number) +{ + __kdebug_param(5, (unsigned long)number, 0); +} + +L4_INLINE void +outhex20(int number) +{ + __kdebug_param(6, (unsigned long)number, 0); +} + +L4_INLINE void +outhex16(int number) +{ + __kdebug_param(7, (unsigned long)number, 0); +} + +L4_INLINE void +outhex12(int number) +{ + __kdebug_param(8, (unsigned long)number, 0); +} + +L4_INLINE void +outhex8(int number) +{ + __kdebug_param(9, (unsigned long)number, 0); +} + +L4_INLINE void +kd_display(char *text) +{ + outstring(text); +} + +L4_INLINE int +l4kd_inchar(void) +{ + return __kdebug_param(0xd, 0, 0); +} + +L4_INLINE void +l4_sys_cli(void) +{ + __kdebug_param(0x32, 0, 0); +} + +L4_INLINE void +l4_sys_sti(void) +{ + __kdebug_param(0x33, 0, 0); +} + +L4_INLINE void +l4_kdebug_imb(void) +{ + // __KDEBUG_ARM_PARAM_0(0x3f); +} +L4_INLINE int +l4_irq_enabled(void) +{ + return __kdebug_param(0x34, 0, 0); +} +#endif //__GNUC__ + +#endif /* ! __L4SYS__INCLUDE__ARCH_SPARC__KDEBUG_H__ */ diff --git a/l4/pkg/l4sys/include/ARCH-sparc/l4int.h b/l4/pkg/l4sys/include/ARCH-sparc/l4int.h new file mode 100644 index 00000000..b7be2c1c --- /dev/null +++ b/l4/pkg/l4sys/include/ARCH-sparc/l4int.h @@ -0,0 +1,38 @@ +/** + * \file + * \brief Fixed sized integer types, sparc(32) version + * \ingroup l4_basic_types + */ +/* + * (c) 2008-2010 Adam Lackorzynski + * Björn Döbel + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#pragma once + +#include_next + +/** + * \addtogroup l4_basic_types + */ +/*@{*/ + +#define L4_MWORD_BITS 32 /**< Size of machine words in bits */ + +typedef unsigned int l4_size_t; /**< \brief Signed size type */ +typedef signed int l4_ssize_t; /**< \brief Unsigned size type */ +/*@}*/ + diff --git a/l4/pkg/l4sys/include/ARCH-sparc/linkage.h b/l4/pkg/l4sys/include/ARCH-sparc/linkage.h new file mode 100644 index 00000000..13704e65 --- /dev/null +++ b/l4/pkg/l4sys/include/ARCH-sparc/linkage.h @@ -0,0 +1,49 @@ +/** + * \file + * \brief Linkage + * \ingroup l4sys_api + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg , + * Frank Mehnert + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#ifndef __L4__SYS__ARCH_SPARC__LINKAGE_H__ +#define __L4__SYS__ARCH_SPARC__LINKAGE_H__ + +#ifdef __ASSEMBLY__ + +#ifndef ENTRY +#define ENTRY(name) \ + .globl name; \ + .p2align(2); \ + name: + +#endif /* ! ENTRY */ +#endif /* __ASSEMBLY__ */ + +#define L4_FASTCALL(x) x +#define l4_fastcall + +/** + * Define calling convention. + * \ingroup l4sys_defines + * \hideinitializer + */ +#define L4_CV + +#endif /* ! __L4__SYS__ARCH_SPARC__LINKAGE_H__ */ diff --git a/l4/pkg/l4sys/include/ARCH-sparc/types.h b/l4/pkg/l4sys/include/ARCH-sparc/types.h new file mode 100644 index 00000000..c6b07c60 --- /dev/null +++ b/l4/pkg/l4sys/include/ARCH-sparc/types.h @@ -0,0 +1,36 @@ +/** + * \file + * \brief Types for SPARC + */ +/* + * (c) 2010 Adam Lackorzynski + * Björn Döbel + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#ifndef __ARCH__L4_TYPES_H +#define __ARCH__L4_TYPES_H + +#include_next + +#include +#include +#include + +#include + +#include + +#endif /* __ARCH__L4_TYPES_H */ diff --git a/l4/pkg/l4sys/include/ARCH-sparc/utcb.h b/l4/pkg/l4sys/include/ARCH-sparc/utcb.h new file mode 100644 index 00000000..d570527e --- /dev/null +++ b/l4/pkg/l4sys/include/ARCH-sparc/utcb.h @@ -0,0 +1,112 @@ +/** + * \file + * \brief UTCB definitions for Sparc. + * \ingroup l4_utcb_api + */ +/* + * (c) 2010 Adam Lackorzynski + * Björn Döbel + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#ifndef __L4_SYS__INCLUDE__ARCH_SPARC__UTCB_H__ +#define __L4_SYS__INCLUDE__ARCH_SPARC__UTCB_H__ + +#include + +/** + * \defgroup l4_utcb_api_arm SPARC Virtual Registers (UTCB) + * \ingroup l4_utcb_api + */ + +/** + * \brief UTCB constants for SPARC + * \ingroup l4_utcb_api_arm + * \hideinitializer + */ +enum L4_utcb_consts_sparc +{ + L4_UTCB_EXCEPTION_REGS_SIZE = 39, + L4_UTCB_GENERIC_DATA_SIZE = 63, + L4_UTCB_GENERIC_BUFFERS_SIZE = 58, + + L4_UTCB_MSG_REGS_OFFSET = 0, + L4_UTCB_BUF_REGS_OFFSET = 64 * sizeof(l4_umword_t), + L4_UTCB_THREAD_REGS_OFFSET = 123 * sizeof(l4_umword_t), + + L4_UTCB_INHERIT_FPU = 1UL << 24, + + L4_UTCB_OFFSET = 512, +}; + +/** + * \brief UTCB structure for exceptions. + * \ingroup l4_utcb_api_arm + */ +typedef struct l4_exc_regs_t +{ + l4_umword_t pfa; /**< page fault address */ + l4_umword_t err; /**< error code */ + + l4_umword_t r[30]; /**< G0-7, I0-8, L0-7, O0-7 */ + l4_umword_t sp; /**< O6 */ + l4_umword_t o7; + l4_umword_t trapno; + l4_umword_t ip; +} l4_exc_regs_t; + +#include_next + +/* + * ================================================================== + * Implementations. + */ + +#ifdef __GNUC__ +L4_INLINE l4_utcb_t *l4_utcb_direct(void) L4_NOTHROW +{ + l4_utcb_t *utcb = 0; + + return utcb; +} +#endif + +L4_INLINE l4_umword_t l4_utcb_exc_pc(l4_exc_regs_t *u) L4_NOTHROW +{ + return u->ip; +} + +L4_INLINE void l4_utcb_exc_pc_set(l4_exc_regs_t *u, l4_addr_t pc) L4_NOTHROW +{ + u->ip = pc; +} + +L4_INLINE l4_umword_t l4_utcb_exc_typeval(l4_exc_regs_t *u) L4_NOTHROW +{ + return u->trapno; +} + +L4_INLINE int l4_utcb_exc_is_pf(l4_exc_regs_t *u) L4_NOTHROW +{ + (void)u; + return 0; +} + +L4_INLINE l4_addr_t l4_utcb_exc_pfa(l4_exc_regs_t *u) L4_NOTHROW +{ + return u->pfa; +} + +#endif /* ! __L4_SYS__INCLUDE__ARCH_SPARC__UTCB_H__ */ diff --git a/l4/pkg/l4sys/include/ARCH-x86/L4API-l4f/__kernel_object_impl.h b/l4/pkg/l4sys/include/ARCH-x86/L4API-l4f/__kernel_object_impl.h new file mode 100644 index 00000000..8e049ef1 --- /dev/null +++ b/l4/pkg/l4sys/include/ARCH-x86/L4API-l4f/__kernel_object_impl.h @@ -0,0 +1,50 @@ +/** + * \file + * \brief Low-level kernel functions for X86 + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#pragma once + +#include +#include + + +L4_INLINE l4_msgtag_t +l4_invoke_debugger(l4_cap_idx_t obj, l4_msgtag_t tag, l4_utcb_t *utcb) L4_NOTHROW +{ + l4_umword_t dummy1, dummy2; + + __asm__ __volatile__( + L4_SYSCALL(debugger) + : + "=d" (dummy1), + "=a" (tag.raw), + "=D" (dummy2) + : + "d" (obj), + "a" (tag.raw), + "D" (utcb) + : + "memory", "cc" + ); + + return tag; +} + diff --git a/l4/pkg/l4sys/include/ARCH-x86/L4API-l4f/ipc-l42-gcc3-nopic.h b/l4/pkg/l4sys/include/ARCH-x86/L4API-l4f/ipc-l42-gcc3-nopic.h new file mode 100644 index 00000000..5cf6a374 --- /dev/null +++ b/l4/pkg/l4sys/include/ARCH-x86/L4API-l4f/ipc-l42-gcc3-nopic.h @@ -0,0 +1,268 @@ +/** + * \file + * \brief IPC system calls for X86 + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg , + * Frank Mehnert , + * Jork Löser + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#pragma once + +#include + +L4_INLINE l4_msgtag_t +l4_ipc_call(l4_cap_idx_t dest, l4_utcb_t *u, + l4_msgtag_t snd_tag, + l4_timeout_t timeout) L4_NOTHROW +{ + l4_umword_t dummy1, dummy2, dummy3; + l4_msgtag_t rtag; + + (void)u; + + __asm__ __volatile__ + (L4_ENTER_KERNEL + : + "=d" (dummy3), + "=D" (dummy1), + "=c" (timeout), + "=S" (dummy2), + "=a" (rtag.raw) + : + "S" (0), + "c" (timeout), + "d" (dest | L4_SYSF_CALL), + "a" (snd_tag.raw) + : + "memory", "cc" L4S_PIC_CLOBBER + ); + return rtag; +} + + +L4_INLINE l4_msgtag_t +l4_ipc_reply_and_wait(l4_utcb_t *u, l4_msgtag_t tag, + l4_umword_t *label, + l4_timeout_t timeout) L4_NOTHROW +{ + l4_umword_t dummy, dummy1, dummy2; + l4_msgtag_t rtag; + + (void)u; + + __asm__ __volatile__ + (L4_ENTER_KERNEL + : + "=d" (dummy2), + "=S" (*label), + "=c" (dummy1), + "=D" (dummy), + "=a" (rtag.raw) + : + "S" (0), + "c" (timeout), + "a" (tag.raw), + "d" (L4_INVALID_CAP | L4_SYSF_REPLY_AND_WAIT) + : + "memory", "cc" L4S_PIC_CLOBBER + ); + return rtag; +} + + +L4_INLINE l4_msgtag_t +l4_ipc_send_and_wait(l4_cap_idx_t dest, l4_utcb_t *u, + l4_msgtag_t tag, + l4_umword_t *label, + l4_timeout_t timeout) L4_NOTHROW +{ + l4_umword_t dummy, dummy1, dummy2; + l4_msgtag_t rtag; + + (void)u; + + __asm__ __volatile__ + (L4_ENTER_KERNEL + : + "=d" (dummy2), + "=S" (*label), + "=c" (dummy1), + "=D" (dummy), + "=a" (rtag.raw) + : + "S" (0), + "c" (timeout), + "a" (tag.raw), + "d" (dest | L4_SYSF_SEND_AND_WAIT) + : + "memory", "cc" L4S_PIC_CLOBBER + ); + return rtag; +} + + +L4_INLINE l4_msgtag_t +l4_ipc_send(l4_cap_idx_t dest, l4_utcb_t *u, + l4_msgtag_t tag, + l4_timeout_t timeout) L4_NOTHROW +{ + l4_umword_t dummy1, dummy4, dummy5; + l4_msgtag_t rtag; + + (void)u; + + __asm__ __volatile__ + (L4_ENTER_KERNEL + : + "=d" (dummy1), + "=a" (rtag.raw), + "=c" (timeout.raw), + "=S" (dummy4), + "=D" (dummy5) + : + "S" (0), + "c" (timeout), + "d" (dest | L4_SYSF_SEND), + "a" (tag.raw) + : "memory", "cc" L4S_PIC_CLOBBER + ); + return rtag; +} + + +L4_INLINE l4_msgtag_t +l4_ipc_wait(l4_utcb_t *u, l4_umword_t *label, + l4_timeout_t timeout) L4_NOTHROW +{ + l4_umword_t dummy, dummy2, dummy1; + l4_msgtag_t rtag; + + (void)u; + + __asm__ __volatile__ + (L4_ENTER_KERNEL + : + "=d" (dummy1), + "=S" (*label), + "=c" (dummy), + "=D" (dummy2), + "=a" (rtag.raw) + : + "c" (timeout), + "d" (L4_INVALID_CAP | L4_SYSF_WAIT), + "a" (0), + "S" (0) + : "memory", "cc" L4S_PIC_CLOBBER + ); + return rtag; +} + +#if 0 +L4_INLINE int +l4_ipc_wait_next_period(l4_threadid_t *src, + l4_timeout_t timeout, + l4_msgdope_t *result, + l4_utcb_t *u) +{ + unsigned dummy, tag; + + (void)u; + + __asm__ __volatile__ + ("pushl %%ebp \n\t" /* save ebp, no memory references + ("m") after this point */ + "movl %[msg_desc], %%ebp \n\t" /* rcv_msg */ + IPC_SYSENTER + "popl %%ebp \n\t" /* restore ebp, no memory + references ("m") before this point */ + : + "=a" (*result), + "=d" (*rcv_dword0), + "=b" (*rcv_dword1), + "=c" (dummy), + "=S" (src->raw), + "=D" (tag) + : + "a" (L4_IPC_NIL_DESCRIPTOR), + "c" (timeout), + [msg_desc] "ir"(((int)rcv_msg) | L4_IPC_OPEN_IPC), + "D" (L4_IPC_FLAG_NEXT_PERIOD) /* no absolute timeout */ + ); + return L4_IPC_ERROR(*result); +} +#endif + +L4_INLINE l4_msgtag_t +l4_ipc_receive(l4_cap_idx_t rcv, l4_utcb_t *u, + l4_timeout_t timeout) L4_NOTHROW +{ + l4_umword_t dummy, dummy1, dummy2; + l4_msgtag_t rtag; + + (void)u; + + __asm__ __volatile__ + (L4_ENTER_KERNEL + : + "=d" (dummy2), + "=S" (dummy1), + "=c" (dummy), + "=a" (rtag.raw) + : + "c" (timeout), + "S" (0), + "a" (0), + "d" (rcv | L4_SYSF_RECV) + : "memory", "cc" L4S_PIC_CLOBBER + ); + return rtag; +} + +L4_INLINE l4_msgtag_t +l4_ipc(l4_cap_idx_t dest, l4_utcb_t *u, + l4_umword_t flags, + l4_umword_t slabel, + l4_msgtag_t tag, + l4_umword_t *rlabel, + l4_timeout_t timeout) L4_NOTHROW +{ + l4_umword_t dummy, dummy1, dummy2; + l4_msgtag_t rtag; + + (void)u; + + __asm__ __volatile__ + (L4_ENTER_KERNEL + : + "=d" (dummy2), + "=S" (*rlabel), + "=c" (dummy1), + "=D" (dummy), + "=a" (rtag.raw) + : + "S" (slabel), + "c" (timeout), + "a" (tag.raw), + "d" (dest | flags) + : + "memory", "cc" L4S_PIC_CLOBBER + ); + return rtag; +} + diff --git a/l4/pkg/l4sys/include/ARCH-x86/L4API-l4f/ipc.h b/l4/pkg/l4sys/include/ARCH-x86/L4API-l4f/ipc.h new file mode 100644 index 00000000..626b62ce --- /dev/null +++ b/l4/pkg/l4sys/include/ARCH-x86/L4API-l4f/ipc.h @@ -0,0 +1,40 @@ +/** + * \file + * \brief L4 IPC System Calls, x86 + * \ingroup l4_api + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg , + * Lars Reuther + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#ifndef __L4_IPC_H__ +#define __L4_IPC_H__ + +#include + +#include_next + +/***************************************************************************** + *** Implementation + *****************************************************************************/ + +#include +#include "ipc-l42-gcc3-nopic.h" +#include + +#endif /* !__L4_IPC_H__ */ diff --git a/l4/pkg/l4sys/include/ARCH-x86/L4API-l4f/segment.h b/l4/pkg/l4sys/include/ARCH-x86/L4API-l4f/segment.h new file mode 100644 index 00000000..637c9273 --- /dev/null +++ b/l4/pkg/l4sys/include/ARCH-x86/L4API-l4f/segment.h @@ -0,0 +1,44 @@ +#include_next + +/** + * \file + * \brief l4f specific segment manipulation + * \ingroup api_calls_fiasco + */ +/* + * (c) 2008-2009 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#ifndef __L4_SYS__ARCH_X86__L4API_L4F__SEGMENT_H__ +#define __L4_SYS__ARCH_X86__L4API_L4F__SEGMENT_H__ + +#include + +/***************************************************************************** + *** Implementation + *****************************************************************************/ + +L4_INLINE long +fiasco_gdt_set(l4_cap_idx_t thread, void *desc, unsigned int size, + unsigned int entry_number_start, l4_utcb_t *utcb) +{ + l4_utcb_mr_u(utcb)->mr[0] = L4_THREAD_GDT_X86_OP; + l4_utcb_mr_u(utcb)->mr[1] = entry_number_start; + __builtin_memcpy(&l4_utcb_mr_u(utcb)->mr[2], desc, size); + return l4_error_u(l4_ipc_call(thread, utcb, l4_msgtag(L4_PROTO_THREAD, 2 + (size >> 2), 0, 0), L4_IPC_NEVER), utcb); +} + +#endif /* ! __L4_SYS__ARCH_X86__L4API_L4F__SEGMENT_H__ */ diff --git a/l4/pkg/l4sys/include/ARCH-x86/L4API-l4f/types.h b/l4/pkg/l4sys/include/ARCH-x86/L4API-l4f/types.h new file mode 100644 index 00000000..49194bf5 --- /dev/null +++ b/l4/pkg/l4sys/include/ARCH-x86/L4API-l4f/types.h @@ -0,0 +1,34 @@ +/** + * \file + * \brief L4 kernel API type definitions + * \ingroup l4_api + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg , + * Lars Reuther + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#pragma once + +#include +#include +#include +#include_next + +#include + +#include diff --git a/l4/pkg/l4sys/include/ARCH-x86/__vcpu-arch.h b/l4/pkg/l4sys/include/ARCH-x86/__vcpu-arch.h new file mode 100644 index 00000000..a204f4a8 --- /dev/null +++ b/l4/pkg/l4sys/include/ARCH-x86/__vcpu-arch.h @@ -0,0 +1,63 @@ +/* + * (c) 2009 Adam Lackorzynski , + * Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#pragma once + +#include + +/** + * \brief vCPU registers. + * \ingroup l4_vcpu_api + */ +typedef struct l4_vcpu_regs_t +{ + l4_umword_t es; /**< gs register */ + l4_umword_t ds; /**< fs register */ + l4_umword_t gs; /**< gs register */ + l4_umword_t fs; /**< fs register */ + + l4_umword_t di; /**< edi register */ + l4_umword_t si; /**< esi register */ + l4_umword_t bp; /**< ebp register */ + l4_umword_t pfa; /**< page fault address */ + l4_umword_t bx; /**< ebx register */ + l4_umword_t dx; /**< edx register */ + l4_umword_t cx; /**< ecx register */ + l4_umword_t ax; /**< eax register */ + + l4_umword_t trapno; /**< trap number */ + l4_umword_t err; /**< error code */ + + l4_umword_t ip; /**< instruction pointer */ + l4_umword_t dummy1; /**< dummy \internal */ + l4_umword_t flags; /**< eflags */ + l4_umword_t sp; /**< stack pointer */ + l4_umword_t ss; /**< ss register */ +} l4_vcpu_regs_t; + +/** + * \brief vCPU message registers. + * \ingroup l4_vcpu_api + */ +typedef struct l4_vcpu_ipc_regs_t +{ + l4_umword_t _res[2]; + l4_umword_t label; + l4_umword_t _res2[3]; + l4_msgtag_t tag; +} l4_vcpu_ipc_regs_t; diff --git a/l4/pkg/l4sys/include/ARCH-x86/cache.h b/l4/pkg/l4sys/include/ARCH-x86/cache.h new file mode 100644 index 00000000..1bdc86e5 --- /dev/null +++ b/l4/pkg/l4sys/include/ARCH-x86/cache.h @@ -0,0 +1,67 @@ +/** + * \file + * \brief Cache functions + */ +/* + * (c) 2008-2009 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#ifndef __L4SYS__INCLUDE__ARCH_X86__CACHE_H__ +#define __L4SYS__INCLUDE__ARCH_X86__CACHE_H__ + +#include_next + +L4_INLINE void +l4_cache_clean_data(unsigned long start, + unsigned long end) L4_NOTHROW +{ + (void)start; (void)end; +} + +L4_INLINE void +l4_cache_flush_data(unsigned long start, + unsigned long end) L4_NOTHROW +{ + (void)start; (void)end; +} + +L4_INLINE void +l4_cache_inv_data(unsigned long start, + unsigned long end) L4_NOTHROW +{ + (void)start; (void)end; +} + +L4_INLINE void +l4_cache_coherent(unsigned long start, + unsigned long end) L4_NOTHROW +{ + (void)start; (void)end; +} + +L4_INLINE void +l4_cache_dma_coherent(unsigned long start, + unsigned long end) L4_NOTHROW +{ + (void)start; (void)end; +} + +L4_INLINE void +l4_cache_dma_coherent_full(void) L4_NOTHROW +{ +} + +#endif /* ! __L4SYS__INCLUDE__ARCH_X86__CACHE_H__ */ diff --git a/l4/pkg/l4sys/include/ARCH-x86/consts.h b/l4/pkg/l4sys/include/ARCH-x86/consts.h new file mode 100644 index 00000000..f54a5e28 --- /dev/null +++ b/l4/pkg/l4sys/include/ARCH-x86/consts.h @@ -0,0 +1,45 @@ +/*****************************************************************************/ +/** + * \file + * \brief Common L4 constants, x86 version + * \ingroup l4_api + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg , + * Björn Döbel , + * Lars Reuther + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +/*****************************************************************************/ +#ifndef __L4SYS__INCLUDE__ARCH_X86__CONSTS_H__ +#define __L4SYS__INCLUDE__ARCH_X86__CONSTS_H__ + +/** + * Size of a page log2-based + * \ingroup l4_memory_api + */ +#define L4_PAGESHIFT 12 + +/** + * Size of a large page log2-based + * \ingroup l4_memory_api + */ +#define L4_SUPERPAGESHIFT 22 + +#include_next + +#endif /* ! __L4SYS__INCLUDE__ARCH_X86__CONSTS_H__ */ diff --git a/l4/pkg/l4sys/include/ARCH-x86/ipc-invoke.h b/l4/pkg/l4sys/include/ARCH-x86/ipc-invoke.h new file mode 100644 index 00000000..50c9e432 --- /dev/null +++ b/l4/pkg/l4sys/include/ARCH-x86/ipc-invoke.h @@ -0,0 +1,88 @@ +/** + * \internal + * \file + * \brief L4 IPC System Call Invoking in Assembler. + * \ingroup l4_api + * + * This file can also be used in asm-files, so don't include C statements. + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg , + * Björn Döbel + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ + +#pragma once + +/* + * Some words about the sysenter entry frame: Since the sysenter instruction + * automatically reloads the instruction pointer (eip) and the stack pointer + * (esp) after kernel entry, we have to save both registers preliminary to + * that instruction. We use ecx to store the user-level esp and save eip onto + * the stack. The ecx register contains the IPC timeout and has to be saved + * onto the stack, too. The ebp register is saved for compatibility reasons + * with the Hazelnut kernel. Both the esp and the ss register are also pushed + * onto the stack to be able to return using the "lret" instruction from the + * sysexit trampoline page if Small Address Spaces are enabled. + */ + +#ifdef __PIC__ +# define L4S_PIC_SAVE "push %%ebx; " +# define L4S_PIC_RESTORE "pop %%ebx; " +# define L4S_PIC_CLOBBER +#if 1 +# define IPC_SYSENTER "# indirect sys invoke \n\t" \ + "call *__l4sys_invoke_indirect@GOTOFF(%%ebx) \n\t" +#else +# define IPC_SYSENTER "call __l4sys_invoke_direct@plt \n\t" +#endif +# define IPC_SYSENTER_ASM call __l4sys_invoke_direct@plt +#else +/** + * \internal + * \brief Kernel entry code for inline assembly. + */ +#define IPC_SYSENTER "call __l4sys_invoke_direct \n\t" +/** + * \internal + * \brief Kernel entry code for assembler code. + */ +#define IPC_SYSENTER_ASM call __l4sys_invoke_direct +/** + * \internal + * \brief Save PIC register, if needed. + */ +# define L4S_PIC_SAVE +/** + * \internal + * \brief Restore PIC register, if needed. + */ +# define L4S_PIC_RESTORE +/** + * \internal + * \brief PIC clobber list. + */ +# define L4S_PIC_CLOBBER ,"ebx" +#endif +/** + * \internal + * \brief Kernel entry code for inline assembly. + */ +#define L4_ENTER_KERNEL L4S_PIC_SAVE "push %%ebp; " \ + IPC_SYSENTER \ + " pop %%ebp; " L4S_PIC_RESTORE + diff --git a/l4/pkg/l4sys/include/ARCH-x86/kdebug.h b/l4/pkg/l4sys/include/ARCH-x86/kdebug.h new file mode 100644 index 00000000..6b0ad5b9 --- /dev/null +++ b/l4/pkg/l4sys/include/ARCH-x86/kdebug.h @@ -0,0 +1,426 @@ +/*****************************************************************************/ +/** + * \file + * \brief Kernel debugger macros + * \ingroup api_calls + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg , + * Björn Döbel , + * Frank Mehnert + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +/*****************************************************************************/ +#ifndef __L4_KDEBUG_H__ +#define __L4_KDEBUG_H__ + +#include + +/** + * Enter L4 kernel debugger + * \ingroup l4_debugger_api + * \hideinitializer + * + * \param text Text to be shown at kernel debugger prompt + */ +#ifndef __ASSEMBLER__ +#define enter_kdebug(text) \ +asm(\ + "int $3 \n\t"\ + "jmp 1f \n\t"\ + ".ascii \""text "\"\n\t"\ + "1: \n\t"\ + ) +#else +#define enter_kdebug(text) \ + int $3 ;\ + jmp 1f ;\ + .ascii text ;\ + 1: +#endif + +/** + * Enter L4 kernel debugger (plain assembler version) + * \ingroup l4_debugger_api + * \hideinitializer + * + * \param text Text to be shown at kernel debugger prompt + */ +#define asm_enter_kdebug(text) \ + "int $3 \n\t"\ + "jmp 1f \n\t"\ + ".ascii \""text "\"\n\t"\ + "1: \n\t" + +/** + * Show message with L4 kernel debugger, but do not enter debugger + * \ingroup l4_debugger_api + * \hideinitializer + * + * \param text Text to be shown + */ +#define kd_display(text) \ +asm(\ + "int $3 \n\t"\ + "nop \n\t"\ + "jmp 1f \n\t"\ + ".ascii \""text "\"\n\t"\ + "1: \n\t"\ + ) + +/** + * Output character with L4 kernel debugger + * \ingroup l4_debugger_api + * \hideinitializer + * + * \param c Character to be shown + */ +#define ko(c) \ + asm( \ + "int $3 \n\t" \ + "cmpb %0,%%al \n\t" \ + : /* No output */ \ + : "N" (c) \ + ) + +/***************************************************************************** + *** Prototypes + *****************************************************************************/ + +#ifndef __ASSEMBLER__ + +/** + * Print character + * \ingroup l4_debugger_api + * + * \param c Character + */ +L4_INLINE void +outchar(char c) L4_NOTHROW; + +/** + * Print character string + * \ingroup l4_debugger_api + * + * \param text String + */ +L4_INLINE void +outstring(const char * text) L4_NOTHROW; + +/** + * Print character string + * \ingroup l4_debugger_api + * + * \param text String + * \param len Number of characters + */ +L4_INLINE void +outnstring(char const *text, unsigned len) L4_NOTHROW; + +/** + * Print 32 bit number (hexadecimal) + * \ingroup l4_debugger_api + * + * \param number 32 bit number + */ +L4_INLINE void +outhex32(int number) L4_NOTHROW; + +/** + * Print 20 bit number (hexadecimal) + * \ingroup l4_debugger_api + * + * \param number 20 bit number + */ +L4_INLINE void +outhex20(int number) L4_NOTHROW; + +/** + * Print 16 bit number (hexadecimal) + * \ingroup l4_debugger_api + * + * \param number 16 bit number + */ +L4_INLINE void +outhex16(int number) L4_NOTHROW; + +/** + * Print 12 bit number (hexadecimal) + * \ingroup l4_debugger_api + * + * \param number 12 bit number + */ +L4_INLINE void +outhex12(int number) L4_NOTHROW; + +/** + * Print 8 bit number (hexadecimal) + * \ingroup l4_debugger_api + * + * \param number 8 bit number + */ +L4_INLINE void +outhex8(int number) L4_NOTHROW; + +/** + * Print number (decimal) + * \ingroup l4_debugger_api + * + * \param number Number + */ +L4_INLINE void +outdec(int number) L4_NOTHROW; + +/** + * Read character from console, non blocking + * \ingroup l4_debugger_api + * + * \return Input character, -1 if no character to read + */ +L4_INLINE char +l4kd_inchar(void) L4_NOTHROW; + +/** + * Start profiling + * \ingroup api_calls_fiasco + */ +L4_INLINE void +fiasco_profile_start(void) L4_NOTHROW; + +/** + * Stop profiling and dump result to console + * \ingroup api_calls_fiasco + */ +L4_INLINE void +fiasco_profile_stop_and_dump(void) L4_NOTHROW; + +/** + * Stop profiling + * \ingroup api_calls_fiasco + */ +L4_INLINE void +fiasco_profile_stop(void) L4_NOTHROW; + +/** + * Enable Fiasco watchdog + * \ingroup api_calls_fiasco + */ +L4_INLINE void +fiasco_watchdog_enable(void) L4_NOTHROW; + +/** + * Disable Fiasco watchdog + * \ingroup api_calls_fiasco + */ +L4_INLINE void +fiasco_watchdog_disable(void) L4_NOTHROW; + +/** + * Disable automatic resetting of watchdog. User is responsible to call + * \c fiasco_watchdog_touch from time to time to ensure that the watchdog + * does not trigger. + * \ingroup api_calls_fiasco + */ +L4_INLINE void +fiasco_watchdog_takeover(void) L4_NOTHROW; + +/** + * Reenable automatic resetting of watchdog. + * \ingroup api_calls_fiasco + */ +L4_INLINE void +fiasco_watchdog_giveback(void) L4_NOTHROW; + +/** + * Reset watchdog from user land. This function \b must be called from time + * to time to prevent the watchdog from triggering if the watchdog is + * activated and if \c fiasco_watchdog_takeover was performed. + * \ingroup api_calls_fiasco + */ +L4_INLINE void +fiasco_watchdog_touch(void) L4_NOTHROW; + + +/***************************************************************************** + *** Implementation + *****************************************************************************/ + +L4_INLINE void +outchar(char c) L4_NOTHROW +{ + asm( + "int $3 \n\t" + "cmpb $0,%%al \n\t" + : /* No output */ + : "a" (c) + ); +} + +/* actually outstring is outcstring */ +L4_INLINE void +outstring(const char *text) L4_NOTHROW +{ + asm volatile ( + "int $3 \n\t" + "cmpb $2,%%al \n\t" + : /* No output */ + : "a" (text) + : "memory" + ); +} + +/* actually outstring is outcstring */ +L4_INLINE void +outnstring(char const *text, unsigned len) L4_NOTHROW +{ + asm volatile ( + "pushl %%ebx \n\t" + "movl %%ecx, %%ebx \n\t" + "int $3 \n\t" + "cmpb $1,%%al \n\t" + "popl %%ebx \n\t" + : /* No output */ + : "a" (text), "c"(len) + : "memory" + ); +} + +L4_INLINE void +outhex32(int number) L4_NOTHROW +{ + asm( + "int $3 \n\t" + "cmpb $5,%%al \n\t" + : /* No output */ + : "a" (number) + ); +} + +L4_INLINE void +outhex20(int number) L4_NOTHROW +{ + asm( + "int $3 \n\t" + "cmpb $6,%%al \n\t" + : /* No output */ + : "a" (number) + ); +} + +L4_INLINE void +outhex16(int number) L4_NOTHROW +{ + asm( + "int $3 \n\t" + "cmpb $7, %%al\n\t" + : /* No output */ + : "a" (number) + ); +} + +L4_INLINE void +outhex12(int number) L4_NOTHROW +{ + asm( + "int $3 \n\t" + "cmpb $8, %%al\n\t" + : /* No output */ + : "a" (number) + ); +} + +L4_INLINE void +outhex8(int number) L4_NOTHROW +{ + asm( + "int $3 \n\t" + "cmpb $9, %%al\n\t" + : /* No output */ + : "a" (number) + ); +} + +L4_INLINE void +outdec(int number) L4_NOTHROW +{ + asm( + "int $3 \n\t" + "cmpb $11, %%al\n\t" + : /* No output */ + : "a" (number) + ); +} + +L4_INLINE char +l4kd_inchar(void) L4_NOTHROW +{ + char c; + asm volatile ("int $3; cmpb $13, %%al" : "=a" (c)); + return c; +} + +L4_INLINE void +fiasco_profile_start(void) L4_NOTHROW +{ + asm("int $3; cmpb $24, %al"); +} + +L4_INLINE void +fiasco_profile_stop_and_dump(void) L4_NOTHROW +{ + asm("int $3; cmpb $25, %al"); +} + +L4_INLINE void +fiasco_profile_stop(void) L4_NOTHROW +{ + asm("int $3; cmpb $26, %al"); +} + +L4_INLINE void +fiasco_watchdog_enable(void) L4_NOTHROW +{ + asm("int $3; cmpb $31, %%al" : : "c" (1)); +} + +L4_INLINE void +fiasco_watchdog_disable(void) L4_NOTHROW +{ + asm("int $3; cmpb $31, %%al" : : "c" (2)); +} + +L4_INLINE void +fiasco_watchdog_takeover(void) L4_NOTHROW +{ + asm("int $3; cmpb $31, %%al" : : "c" (3)); +} + +L4_INLINE void +fiasco_watchdog_giveback(void) L4_NOTHROW +{ + asm("int $3; cmpb $31, %%al" : : "c" (4)); +} + +L4_INLINE void +fiasco_watchdog_touch(void) L4_NOTHROW +{ + asm("int $3; cmpb $31, %%al" : : "c" (5)); +} + +#endif /* __ASSEMBLER__ */ + +#endif /* __L4_KDEBUG_H__ */ diff --git a/l4/pkg/l4sys/include/ARCH-x86/ktrace.h b/l4/pkg/l4sys/include/ARCH-x86/ktrace.h new file mode 100644 index 00000000..fca70173 --- /dev/null +++ b/l4/pkg/l4sys/include/ARCH-x86/ktrace.h @@ -0,0 +1,257 @@ +/*****************************************************************************/ +/** + * \file + * \brief L4 kernel event tracing + * \ingroup api_calls + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Björn Döbel + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +/*****************************************************************************/ +#ifndef __L4_KTRACE_H__ +#define __L4_KTRACE_H__ + +#include +#include + +/** + * \brief Log event types + * \ingroup api_calls_fiasco + */ +enum { + LOG_EVENT_MAX_EVENTS = 16, +}; + +/** + * Trace-buffer status window descriptor. + * \ingroup api_calls_fiasco + */ +// keep in sync with fiasco/src/jabi/jdb_ktrace.cpp +typedef struct +{ + /// Address of trace-buffer + l4_tracebuffer_entry_t *tracebuffer; + /// Size of trace-buffer + l4_umword_t size; + /// Version number of trace-buffer (incremented if trace-buffer overruns) + volatile l4_uint64_t version; +} l4_tracebuffer_status_window_t; + +/** + * Trace-buffer status. + * \ingroup api_calls_fiasco + */ +// keep in sync with fiasco/src/jabi/jdb_ktrace.cpp +typedef struct +{ + l4_tracebuffer_status_window_t window[2]; + /// Address of the most current event in trace-buffer. + volatile l4_tracebuffer_entry_t * current_entry; + /// Available LOG events + l4_umword_t logevents[LOG_EVENT_MAX_EVENTS]; + + /// Scaler used for translation of CPU cycles to nano seconds + l4_umword_t scaler_tsc_to_ns; + /// Scaler used for translation of CPU cycles to micro seconds + l4_umword_t scaler_tsc_to_us; + /// Scaler used for translation of nano seconds to CPU cycles + l4_umword_t scaler_ns_to_tsc; + + /// Number of context switches (intra AS or inter AS) + volatile l4_umword_t cnt_context_switch; + /// Number of inter AS context switches + volatile l4_umword_t cnt_addr_space_switch; + /// How often was the IPC shortcut taken + volatile l4_umword_t cnt_shortcut_failed; + /// How often was the IPC shortcut not taken + volatile l4_umword_t cnt_shortcut_success; + /// Number of hardware interrupts (without kernel scheduling interrupt) + volatile l4_umword_t cnt_irq; + /// Number of long IPCs + volatile l4_umword_t cnt_ipc_long; + /// Number of page faults + volatile l4_umword_t cnt_page_fault; + /// Number of faults (application runs at IOPL 0 and tries to execute + /// cli, sti, in, or out but does not have a sufficient in the I/O bitmap) + volatile l4_umword_t cnt_io_fault; + /// Number of tasks created + volatile l4_umword_t cnt_task_create; + /// Number of reschedules + volatile l4_umword_t cnt_schedule; + /// Number of flushes of the I/O bitmap. Increases on context switches + /// between two small address spaces if at least one of the spaces has + /// an I/O bitmap allocated. + volatile l4_umword_t cnt_iobmap_tlb_flush; + +} l4_tracebuffer_status_t; + +/** + * Return trace-buffer status. + * \ingroup api_calls_fiasco + * + * \return Pointer to trace-buffer status struct. + */ +L4_INLINE l4_tracebuffer_status_t * +fiasco_tbuf_get_status(void); + +/** + * Return the physical address of the trace-buffer status struct. + * \ingroup api_calls_fiasco + * + * \return physical address of status struct. + */ +L4_INLINE l4_addr_t +fiasco_tbuf_get_status_phys(void); + +/** + * Create new trace-buffer entry with describing \. + * \ingroup api_calls_fiasco + * + * \param text Logging text + * \return Pointer to trace-buffer entry + */ +L4_INLINE l4_umword_t +fiasco_tbuf_log(const char *text); + +/** + * Create new trace-buffer entry with describing \ and three additional + * values. + * \ingroup api_calls_fiasco + * + * \param text Logging text + * \param v1 first value + * \param v2 second value + * \param v3 third value + * \return Pointer to trace-buffer entry + */ +L4_INLINE l4_umword_t +fiasco_tbuf_log_3val(const char *text, unsigned v1, unsigned v2, unsigned v3); + +/** + * Create new trace-buffer entry with binary data. + * \ingroup api_calls_fiasco + * + * \param data binary data + * \return Pointer to trace-buffer entry + */ +L4_INLINE l4_umword_t +fiasco_tbuf_log_binary(const unsigned char *data); + +/** + * Clear trace-buffer. + * \ingroup api_calls_fiasco + */ +L4_INLINE void +fiasco_tbuf_clear(void); + +/** + * Dump trace-buffer to kernel console. + * \ingroup api_calls_fiasco + */ +L4_INLINE void +fiasco_tbuf_dump(void); + +/** + * Disable the kernel scheduling timer. + */ +L4_INLINE void +fiasco_timer_disable(void); + +/** + * Enable the kernel scheduling timer (after it was disabled with + * fiasco_timer_disable). + */ +L4_INLINE void +fiasco_timer_enable(void); + +/***************************************************************************** + *** Implementation + *****************************************************************************/ + +L4_INLINE l4_tracebuffer_status_t * +fiasco_tbuf_get_status(void) +{ + l4_tracebuffer_status_t *tbuf; + asm("int $3; cmpb $29, %%al" : "=a" (tbuf) : "0" (0)); + return tbuf; +} + +L4_INLINE l4_addr_t +fiasco_tbuf_get_status_phys(void) +{ + l4_addr_t tbuf_phys; + asm("int $3; cmpb $29, %%al" : "=a" (tbuf_phys) : "0" (5)); + return tbuf_phys; +} + +L4_INLINE l4_umword_t +fiasco_tbuf_log(const char *text) +{ + l4_umword_t offset; + asm volatile("int $3; cmpb $29, %%al" + : "=a" (offset) + : "a" (1), "d" (text)); + return offset; +} + +L4_INLINE l4_umword_t +fiasco_tbuf_log_3val(const char *text, unsigned v1, unsigned v2, unsigned v3) +{ + l4_umword_t offset; + asm volatile("int $3; cmpb $29, %%al" + : "=a" (offset) + : "a" (4), "d" (text), "c" (v1), "S" (v2), "D" (v3)); + return offset; +} + +L4_INLINE void +fiasco_tbuf_clear(void) +{ + asm volatile("int $3; cmpb $29, %%al" : : "a" (2)); +} + +L4_INLINE void +fiasco_tbuf_dump(void) +{ + asm volatile("int $3; cmpb $29, %%al" : : "a" (3)); +} + +L4_INLINE void +fiasco_timer_disable(void) +{ + asm volatile("int $3; cmpb $29, %%al" : : "a" (6)); +} + +L4_INLINE void +fiasco_timer_enable(void) +{ + asm volatile("int $3; cmpb $29, %%al" : : "a" (7)); +} + +L4_INLINE l4_umword_t +fiasco_tbuf_log_binary(const unsigned char *data) +{ + l4_umword_t offset; + asm volatile("int $3; cmpb $29, %%al" + : "=a" (offset) + : "a" (8), "d" (data)); + return offset; +} + +#endif + diff --git a/l4/pkg/l4sys/include/ARCH-x86/ktrace_events.h b/l4/pkg/l4sys/include/ARCH-x86/ktrace_events.h new file mode 100644 index 00000000..b5dc394d --- /dev/null +++ b/l4/pkg/l4sys/include/ARCH-x86/ktrace_events.h @@ -0,0 +1,200 @@ +/*****************************************************************************/ +/** + * \file + * \brief L4 kernel event tracing, event memory layout + * \ingroup api_calls + */ +/* + * (c) 2008-2009 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +/*****************************************************************************/ +#ifndef __L4_KTRACE_EVENTS_H__ +#define __L4_KTRACE_EVENTS_H__ + +#include + +enum +{ + l4_ktrace_tbuf_unused = 0, + l4_ktrace_tbuf_pf = 1, + l4_ktrace_tbuf_ipc = 2, + l4_ktrace_tbuf_ipc_res = 3, + l4_ktrace_tbuf_ipc_trace = 4, + l4_ktrace_tbuf_ke = 5, + l4_ktrace_tbuf_ke_reg = 6, + l4_ktrace_tbuf_unmap = 7, + l4_ktrace_tbuf_shortcut_failed = 8, + l4_ktrace_tbuf_shortcut_succeeded = 9, + l4_ktrace_tbuf_context_switch = 10, + l4_ktrace_tbuf_exregs = 11, + l4_ktrace_tbuf_breakpoint = 12, + l4_ktrace_tbuf_trap = 13, + l4_ktrace_tbuf_pf_res = 14, + l4_ktrace_tbuf_sched = 15, + l4_ktrace_tbuf_preemption = 16, + l4_ktrace_tbuf_ke_bin = 17, + l4_ktrace_tbuf_dynentries = 18, + l4_ktrace_tbuf_max = 0x80, + l4_ktrace_tbuf_hidden = 0x80, +}; + +// IA-32 typedefs... +typedef void Context; // We don't have a class Context + // here... But that's fine, we + // can calculate the taskid and + // the threadid from this void + // pointer... +typedef void Space; +typedef void Sched_context; +typedef l4_fpage_t L4_fpage; +typedef unsigned long Address; +typedef unsigned long Mword; +typedef Mword L4_error; +typedef unsigned int L4_snd_desc; +typedef unsigned int L4_rcv_desc; +typedef unsigned long L4_msg_tag; +typedef unsigned long L4_obj_ref; +typedef l4_timeout_t L4_timeout_pair; +typedef unsigned char Unsigned8; +typedef unsigned short Unsigned16; +typedef unsigned int Unsigned32; +typedef unsigned long long Unsigned64; + +typedef struct __attribute__((packed)) +{ + Mword number; // event number + Mword ip; // instruction pointer + Context * context; // current Context + Unsigned64 tsc; // time stamp counter + Unsigned32 pmc1; // performance counter 1 + Unsigned32 pmc2; // performance counter 2 + Unsigned32 kclock; // lower 32 bit of kernel clock + Unsigned8 type; // type of entry + Unsigned8 cpu; // cpu + union __attribute__((__packed__)) // event specific data + { + struct __attribute__((__packed__)) + { + Address _pfa; ///< pagefault address + Mword _error; ///< pagefault error code + Space *_space; + + } pf; // logged page fault + struct __attribute__((__packed__)) + { + L4_msg_tag _tag; ///< message tag + Mword _dword[2]; ///< first two message words + L4_obj_ref _dst; ///< destination id + Mword _dbg_id; + Mword _label; + L4_timeout_pair _timeout; ///< timeout + } ipc; // logged ipc + struct __attribute__((__packed__)) + { + Unsigned64 _snd_tsc; ///< entry tsc + L4_msg_tag _result; ///< result + L4_obj_ref _snd_dst; ///< send destination + Mword _rcv_dst; ///< rcv partner + Unsigned8 _snd_desc; + Unsigned8 _rcv_desc; + + } ipc_res; // logged ipc result + struct __attribute__((__packed__)) + { + } ipc_trace; // traced ipc + struct __attribute__((__packed__)) + { + char msg[30]; + } ke; // logged kernel event + struct __attribute__((__packed__)) + { + char msg[18]; + Mword vals[3]; + } ke_reg; // logged kernel event plus register content + struct __attribute__((__packed__)) + { + char _pad[3]; + L4_fpage fpage; + Mword mask; + int result; // was bool + } unmap; // logged unmap operation + struct __attribute__((__packed__)) + { + // fixme: this seems unused in fiasco + } shortcut_succeeded; // logged short-cut ipc succeeded + struct __attribute__((__packed__)) + { + Context const *_dst; ///< switcher target + Context const *_dst_orig; + Address _kernel_ip; + Mword _lock_cnt; + Space *_from_space; + Sched_context *_from_sched; + Mword _from_prio; + } context_switch; // logged context switch + struct __attribute__((__packed__)) + { + Address _address; ///< breakpoint address + int _len; ///< breakpoint length + Mword _value; ///< value at address + int _mode; ///< breakpoint mode + + } breakpoint; // logged breakpoint + struct __attribute__((__packed__)) + { + char trapno; + Unsigned16 _errno; + Mword ebp; + Mword cr2; + Mword eax; + Mword eflags; + Mword esp; + Unsigned16 cs; + Unsigned16 ds; + } trap; // logged trap + struct __attribute__((__packed__)) + { + Address _pfa; + L4_error _err; + L4_error _ret; + } pf_res; // logged page fault result + struct __attribute__((__packed__)) + { + unsigned short _mode; + Context const *_owner; + unsigned short _id; + unsigned short _prio; + signed long _left; + unsigned long _quantum; + } sched; + struct __attribute__((__packed__)) + { + Mword _preempter; + } preemption; + struct __attribute__((__packed__)) + { + Mword irq_obj; + int irq_number; + } irq; + struct __attribute__((__packed__)) + { + char _pad[30]; + } fit; + } m; +} l4_tracebuffer_entry_t; + +#endif diff --git a/l4/pkg/l4sys/include/ARCH-x86/l4int.h b/l4/pkg/l4sys/include/ARCH-x86/l4int.h new file mode 100644 index 00000000..fc339ccd --- /dev/null +++ b/l4/pkg/l4sys/include/ARCH-x86/l4int.h @@ -0,0 +1,38 @@ +/** + * \file + * \brief Fixed sized integer types, x86 version + * \ingroup l4_basic_types + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#pragma once + +#include_next + +/** + * \addtogroup l4_basic_types + */ +/*@{*/ + +#define L4_MWORD_BITS 32 /**< Size of machine words in bits */ + +typedef unsigned int l4_size_t; /**< \brief Signed size type */ +typedef signed int l4_ssize_t; /**< \brief Unsigned size type */ +/*@}*/ + diff --git a/l4/pkg/l4sys/include/ARCH-x86/linkage.h b/l4/pkg/l4sys/include/ARCH-x86/linkage.h new file mode 100644 index 00000000..4f7585c2 --- /dev/null +++ b/l4/pkg/l4sys/include/ARCH-x86/linkage.h @@ -0,0 +1,49 @@ +/** + * \file + * \brief Linkage + * \ingroup l4sys_api + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg , + * Frank Mehnert + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#ifndef __L4__SYS__ARCH_X86__LINKAGE_H__ +#define __L4__SYS__ARCH_X86__LINKAGE_H__ + +#ifdef __ASSEMBLY__ + +#ifndef ENTRY +#define ENTRY(name) \ + .globl name; \ + .p2align(2); \ + name: + +#endif /* ! ENTRY */ +#endif /* __ASSEMBLY__ */ + +#define L4_FASTCALL(x) x __attribute__((regparm(3))) +#define l4_fastcall __attribute__((regparm(3))) + +/** + * Define calling convention. + * \ingroup l4sys_defines + * \hideinitializer + */ +#define L4_CV __attribute__((regparm(0))) + +#endif /* ! __L4__SYS__ARCH_X86__LINKAGE_H__ */ diff --git a/l4/pkg/l4sys/include/ARCH-x86/rt_sched-impl.h b/l4/pkg/l4sys/include/ARCH-x86/rt_sched-impl.h new file mode 100644 index 00000000..0d640d8c --- /dev/null +++ b/l4/pkg/l4sys/include/ARCH-x86/rt_sched-impl.h @@ -0,0 +1,186 @@ +/** + * \file + * \brief Implementation of real-time scheduling system calls + */ +/* + * (c) 2005-2009 Adam Lackorzynski , + * Alexander Warg , + * Jork Löser + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#ifndef __SYS_INCLUDE_ARCH_X86_RT_SCHED_IMPL_H_ +#define __SYS_INCLUDE_ARCH_X86_RT_SCHED_IMPL_H_ + +#include + +L4_INLINE int +l4_rt_generic(l4_threadid_t dest, l4_sched_param_t param, + l4_kernel_clock_t clock) +{ + unsigned dummy; + int ret; + + __asm__ __volatile__( + "pushl %%ebp \n\t" /* save ebp, no memory references + ("m") after this point */ + L4_SYSCALL(thread_schedule) + "popl %%ebp \n\t" /* restore ebp, no memory references + ("m") before this point */ + : + "=a" (ret), + "=c" (dummy), + "=d" (dummy), + "=S" (dummy) + : + "a" (param), + "c" ((l4_uint32_t)clock), + "d" ((l4_uint32_t)(clock>>32)), + "S" (dest.raw) + : + "ebx", "edi" + ); + return ret; +} + + +/* Erm, the user shall be allowed to pass "normal" time parameters, not + * the mantissa/exponent coding. Thus, make a reference to the external + * l4util function. */ +L4_INLINE int +l4_rt_add_timeslice(l4_threadid_t dest, int prio, int time) +{ + l4_sched_param_t sched = {sp:{prio:prio, small:0, + state:L4_RT_ADD_TIMESLICE}}; + l4_sched_param_set_time(time, &sched); + return l4_rt_generic(dest, sched, 0); +} + +L4_INLINE int +l4_rt_change_timeslice(l4_threadid_t dest, int id, int prio, int time) +{ + l4_sched_param_t sched = {sp:{prio:prio, small:id, + state:L4_RT_CHANGE_TIMESLICE}}; + l4_sched_param_set_time(time, &sched); + return l4_rt_generic(dest, sched, 0); +} + +L4_INLINE int +l4_rt_begin_strictly_periodic (l4_threadid_t dest, l4_kernel_clock_t clock) +{ + return l4_rt_generic(dest, + (l4_sched_param_t){ + sp:{ prio:0, small:0, + state:L4_RT_BEGIN_PERIODIC}}, + clock); +} + +L4_INLINE int +l4_rt_begin_minimal_periodic (l4_threadid_t dest, l4_kernel_clock_t clock) +{ + return l4_rt_generic(dest, + (l4_sched_param_t){ + sp:{prio:0, small: 0, + state:L4_RT_BEGIN_PERIODIC_NS}}, + clock); +} + +L4_INLINE int +l4_rt_end_periodic(l4_threadid_t dest) +{ + return l4_rt_generic(dest, + (l4_sched_param_t){ + sp:{prio:0, small:0, + state:L4_RT_END_PERIODIC}}, 0); +} + +L4_INLINE int +l4_rt_remove(l4_threadid_t dest) +{ + return l4_rt_generic(dest, + (l4_sched_param_t){ + sp:{prio:0, small:0, + state:L4_RT_REM_TIMESLICES}}, 0); +} + +L4_INLINE void +l4_rt_set_period(l4_threadid_t dest, l4_kernel_clock_t clock) +{ + l4_rt_generic(dest, + (l4_sched_param_t){ + sp:{prio:0, small:0, + state:L4_RT_SET_PERIOD}}, + clock); +} + +L4_INLINE int +l4_rt_next_reservation(unsigned id, l4_kernel_clock_t*clock) +{ + long dummy; + int ret; + + __asm__ __volatile__( + "pushl %%ebp \n\t" /* save ebp, no memory references + ("m") after this point */ + L4_SYSCALL(thread_switch) + "popl %%ebp \n\t" /* restore ebp, no memory references + ("m") before this point */ + : + "=a" (ret), + "=c" (((l4_low_high_t*)clock)->low), + "=d" (((l4_low_high_t*)clock)->high), + "=S" (dummy) + : + "S" (0), + "a" (id) + : + "ebx", "edi" + ); + return ret; +} + +L4_INLINE int +l4_rt_next_period(void) +{ + l4_umword_t dummy; + l4_msgdope_t result; + return l4_ipc_receive(l4_next_period_id(L4_NIL_ID), + L4_IPC_SHORT_MSG, + &dummy, &dummy, L4_IPC_BOTH_TIMEOUT_0, + &result); +} + +L4_INLINE int +l4_rt_dp_reserve(int duration) +{ + /* no-op */ + return 0; +} + +L4_INLINE void +l4_rt_dp_remove(void){ + /* no-op */ +} + +L4_INLINE void +l4_rt_dp_begin(void){ + __asm__ __volatile__ ("cli" : : : "memory"); +} + +L4_INLINE void +l4_rt_dp_end(void){ + __asm__ __volatile__ ("sti" : : : "memory"); +} +#endif /* ! __L4_SYS__RT_SCHED_H__ */ diff --git a/l4/pkg/l4sys/include/ARCH-x86/rt_sched-proto.h b/l4/pkg/l4sys/include/ARCH-x86/rt_sched-proto.h new file mode 100644 index 00000000..d46e25ae --- /dev/null +++ b/l4/pkg/l4sys/include/ARCH-x86/rt_sched-proto.h @@ -0,0 +1,316 @@ +/** + * \file + * \brief Identifier and prototype definitions for real-time scheduling + */ +/* + * (c) 2005-2009 Adam Lackorzynski , + * Alexander Warg , + * Björn Döbel , + * Frank Mehnert , + * Jork Löser + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#ifndef __SYS_INCLUDE_ARCH_X86_RT_SCHED_PROTO_H_ +#define __SYS_INCLUDE_ARCH_X86_RT_SCHED_PROTO_H_ + +#include +#include + +#define L4_RT_ADD_TIMESLICE 1 /**< Add time slice */ +#define L4_RT_REM_TIMESLICES 2 /**< Remove time slice */ +#define L4_RT_SET_PERIOD 3 /**< Set period */ +#define L4_RT_BEGIN_PERIODIC 4 /**< Begin periodic */ +#define L4_RT_BEGIN_PERIODIC_NS 5 /**< Begin periodic */ +#define L4_RT_END_PERIODIC 6 /**< End periodic */ +#define L4_RT_CHANGE_TIMESLICE 7 /**< Change time slice */ + +#define L4_RT_NEXT_PERIOD 0x10 /**< Next period */ +#define L4_RT_PREEMPTION_ID 0x20 /**< Preemption ID */ + +/** \brief Struct \internal */ +typedef struct { + l4_uint64_t time:56; /**< time */ + l4_uint64_t id:7; /**< id */ + l4_uint64_t type:1; /**< id */ +} l4_rt_preemption_val_t; +/** \brief Struct \internal */ +typedef struct { + l4_uint32_t time_high:24; /**< time_high */ + l4_uint32_t id:7; /**< id */ + l4_uint32_t type:1; /**< type */ +} l4_rt_preemption_val32_t; +/** \brief Struct \internal */ +typedef union { + l4_low_high_t lh; /**< lh value */ + l4_rt_preemption_val_t p; /**< p value */ +} l4_rt_preemption_t; + + /* preemption ipc types: values of the type field */ +#define L4_RT_PREEMPT_DEADLINE 0 /**< deadline miss */ +#define L4_RT_PREEMPT_TIMESLICE 1 /**< time slice overrun */ + +/*!\brief Add a time slice for periodic execution. + * \ingroup api_calls_rt_sched + * + * \param dest thread to add the time slice to + * \param prio priority of the time slice + * \param time length of the time slice in microseconds + * \retval 0 OK + * \retval -1 Error, one of: + * - dest does not exist + * - insufficient MCP (old or new prio>MCP), + * - dest running in periodic mode or transitioning to + * - time quantum 0 or infinite + */ +L4_INLINE int +l4_rt_add_time slice(l4_threadid_t dest, int prio, int time); + +/*!\brief Change a time slice for periodic execution. + * \ingroup api_calls_rt_sched + * + * \param dest thread whose timing parameters are to change + * \param id number of the time-slice to change (rt start at 1) + * \param prio new priority of the time slice + * \param time new length of the time slice in microseconds, + * 0: don't change. + * \retval 0 OK + * \retval -1 Error, one of: + * - dest does not exist + * - insufficient MCP (old or new prio>MCP), + * - time slice does not exist + * + * This function modifies the priority and optionally the length of an + * existing time slice of a thread. When calling this function while + * the time slice is active, the effect may be delayed till the next + * period. + * + * This function can be called as soon as the denoted time slice was + * added with l4_rt_add_time slice(). Thus, the thread may have started + * periodic execution already, but it needs not. + */ +L4_INLINE int +l4_rt_change_time slice(l4_threadid_t dest, int id, int prio, int time); + +/*!\brief Start strictly periodic execution + * \ingroup api_calls_rt_sched + * + * \param dest thread that starts periodic execution + * \param clock absolute time to start. + * \retval 0 OK + * \retval -1 Error, one of: + * - dest does not exist + * - insufficient MCP (old or new prio>MCP), + * - dest running in periodic mode or transitioning to + * + * Call this function to start the periodic execution after setting up + * the time slices using l4_rt_add_time slice() and l4_rt_set_period(). + * + * By the time specified in clock thread dest must wait for the next period, + * e.g. by using l4_rt_next_period() or some other IPC with the + * L4_RT_NEXT_PERIOD flag enabled. Otherwise the transition to periodic mode + * fails. + */ +L4_INLINE int +l4_rt_begin_strictly_periodic(l4_threadid_t dest, l4_kernel_clock_t clock); + +/*!\brief Start periodic execution with minimal inter-release times + * \ingroup api_calls_rt_sched + * + * \param dest thread that starts periodic execution + * \param clock absolute time to start. + * \retval 0 OK + * \retval -1 Error, one of: + * - dest does not exist + * - insufficient MCP (old or new prio>MCP), + * - dest running in periodic mode or transitioning to + * + * Call this function to start the periodic execution after setting up + * the time slices using l4_rt_add_time slice() and l4_rt_set_period(). + * + * By the time specified in clock thread dest must wait for the next period, + * e.g. by using l4_rt_next_period() or some other IPC with the + * L4_RT_NEXT_PERIOD flag enabled. Otherwise the transition to periodic mode + * fails. + */ +L4_INLINE int +l4_rt_begin_minimal_periodic(l4_threadid_t dest, l4_kernel_clock_t clock); + +/*!\brief Stop periodic execution + * \ingroup api_calls_rt_sched + * + * \param dest thread that stops periodic execution + * \retval 0 OK + * \retval -1 Error, one of: + * - dest does not exist + * - insufficient MCP (old or new prio>MCP), + * - dest not running in periodic mode and + * not transitioning to + * + * This function aborts the periodic execution of thread dest. Thread dest + * returns to conventional scheduling then. + */ +L4_INLINE int +l4_rt_end_periodic(l4_threadid_t dest); + +/*!\brief Remove all reservation scheduling contexts + * \ingroup api_calls_rt_sched + * + * This function removes all the scheduling contexts that were set up + * so far for the given thread. + * + * \param dest thread the scheduling contexts should be removed from + * \retval 0 OK + * \retval -1 Error, one of: + * - dest does not exist + * - insufficient MCP + * - dest running in periodic mode or transitioning to + */ +L4_INLINE int +l4_rt_remove(l4_threadid_t dest); + +/*!\brief Set the length of the period + * \ingroup api_calls_rt_sched + * + * This function sets the length of the period for periodic execution. + * + * \param dest destination thread + * \param clock period length in microseconds. Will be rounded up + * by the kernel according to the timer granularity. + * \return This function always succeeds. + */ +L4_INLINE void +l4_rt_set_period(l4_threadid_t dest, l4_kernel_clock_t clock); + +/*!\brief activate the next time slice (scheduling context) + * \ingroup api_calls_rt_sched + * + * \param id The ID of the time slice we think we are on + * (current time slice) + * \param clock pointer to a l4_kernel_clock_t variable + * \retval 0 OK, *clock contains the remaining time of the time slice + * \retval -1 Error, id did not match current time slice + * + */ +L4_INLINE int +l4_rt_next_reservation(unsigned id, l4_kernel_clock_t*clock); + +/*!\brief Wait for the next period, skipping all unused time slices + * \ingroup api_calls_rt_sched + * + * \retval 0 OK + * \retval !0 IPC Error. + * + */ +L4_INLINE int +l4_rt_next_period(void); + +/*!\brief Return the preemption id of a thread + * \ingroup api_calls_rt_sched + * + * \param id thread + * + * \return thread-id of the (virtual) preemption IPC sender + */ +L4_INLINE l4_threadid_t +l4_preemption_id(l4_threadid_t id); + +/*!\brief Return thread-id that flags waiting for the next period + * \ingroup api_calls_rt_sched + * + * \param id original thread-id + * + * \return modified id, to be used in an IPC, waiting for the next period. + */ +L4_INLINE l4_threadid_t +l4_next_period_id(l4_threadid_t id); + +/*!\brief Generic real-time setup function + * \ingroup api_calls_rt_sched + * + * \param dest destination thread + * \param param scheduling parameter + * \param clock clock parameter + * \retval 0 OK + * \retval -1 Error. + * + * This function is not meant to be used directly, it is merely used + * by others. + */ +L4_INLINE int +l4_rt_generic(l4_threadid_t dest, l4_sched_param_t param, + l4_kernel_clock_t clock); + +/*!\brief Delayed preemption: Reserve a duration + * + * \param duration time (microseconds) + * \retval 0 OK + * \retval !0 Error. + * + * This function reserves a non-preemptible duration at the kernel. + * + * \note Due to the currently missing support in the kernel, this + * call is a no-op. + */ +L4_INLINE int +l4_rt_dp_reserve(int duration); + +/*!\brief Delayed preemption: Cancel a reservation + * + * \retval 0 OK + * \retval !0 Error. + */ +L4_INLINE void +l4_rt_dp_remove(void); + +/*!\brief Delayed preemption: Start a delayed preemption + * + * After making a dp reservation, a thread can start an uninterruptible + * execution for the reserved time. + * + * \note Due to the currently missing support in the kernel, this + * call is implemented as a cli(), requiring cooperation from the + * calling thread. + */ +L4_INLINE void +l4_rt_dp_begin(void); + +/*!\brief Delayed preemption: End a delayed preemption + * + * After calling this function, the thread may be preempted by the kernel + * again. + */ +L4_INLINE void +l4_rt_dp_end(void); + +/*************************************************************************** + *** IMPLEMENTATIONS + ***************************************************************************/ + +L4_INLINE l4_threadid_t +l4_preemption_id(l4_threadid_t id) +{ + //id.id.chief |= L4_RT_PREEMPTION_ID; + return id; +} + +L4_INLINE l4_threadid_t +l4_next_period_id(l4_threadid_t id) +{ + //id.id.chief |= L4_RT_NEXT_PERIOD; + return id; +} + +#endif /* ! __L4_SYS__RT_SCHED_H__ */ diff --git a/l4/pkg/l4sys/include/ARCH-x86/rt_sched.h b/l4/pkg/l4sys/include/ARCH-x86/rt_sched.h new file mode 100644 index 00000000..98432ce3 --- /dev/null +++ b/l4/pkg/l4sys/include/ARCH-x86/rt_sched.h @@ -0,0 +1,32 @@ +/** + * \file + * \brief Real-time scheduling include + * + * \date 01/05/2005 + * \author Jork Loeser + * + */ +/* + * (c) 2005-2009 Author(s) + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#ifndef __SYS_INCLUDE_ARCH_X86_RT_SCHED_H_ +#define __SYS_INCLUDE_ARCH_X86_RT_SCHED_H_ + +#include +#include + +#endif /* ! __L4_SYS__RT_SCHED_H__ */ diff --git a/l4/pkg/l4sys/include/ARCH-x86/segment.h b/l4/pkg/l4sys/include/ARCH-x86/segment.h new file mode 100644 index 00000000..15f4b3fc --- /dev/null +++ b/l4/pkg/l4sys/include/ARCH-x86/segment.h @@ -0,0 +1,115 @@ +/** + * \file + * \brief Segment handling. + * \ingroup api_calls + */ +/* + * (c) 2008-2009 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +/*****************************************************************************/ +#ifndef __L4_SYS__ARCH_X86__SEGMENT_H__ +#define __L4_SYS__ARCH_X86__SEGMENT_H__ + +#ifndef L4API_l4f +#error This header file can only be used with a L4API version! +#endif + +#include + +/** + * Set LDT segments descriptors. + * \ingroup api_calls_fiasco + * + * \param task Task to set the segment for. + * \param ldt Pointer to LDT hardware descriptors. + * \param num_desc Number of descriptors. + * \param entry_number_start Entry number to start. + * \param utcb UTCB of the caller. + */ +L4_INLINE long +fiasco_ldt_set(l4_cap_idx_t task, void *ldt, unsigned int size, + unsigned int entry_number_start, l4_utcb_t *utcb); + +/** + * Set GDT segment descriptors. Fiasco supports 3 consecutive entries, + * starting at the value returned by fiasco_gdt_get_entry_offset() + * \ingroup api_calls_fiasco + * + * \param thread Thread to set the GDT entry for. + * \param desc Pointer to GDT descriptors. + * \param size Size of the descriptors in bytes + * (multiple of 8). + * \param entry_number_start Entry number to start (valid values: 0-2). + * \param utcb UTCB of the caller. + * \return System call error + */ +L4_INLINE long +fiasco_gdt_set(l4_cap_idx_t thread, void *desc, unsigned int size, + unsigned int entry_number_start, l4_utcb_t *utcb); + +/** + * Return the offset of the entry in the GDT. + * \param thread Thread to get info from. + * \param utcb UTCB of the caller. + * \ingroup api_calls_fiasco + */ +L4_INLINE unsigned +fiasco_gdt_get_entry_offset(l4_cap_idx_t thread, l4_utcb_t *utcb); + +/** + * \brief Contants for LDT handling. + */ +enum L4_task_ldt_x86_consts +{ + /** Size of an LDT entry. */ + L4_TASK_LDT_X86_ENTRY_SIZE = 8, + /** Maximum number of LDT entries that can be written with one call. */ + L4_TASK_LDT_X86_MAX_ENTRIES + = (L4_UTCB_GENERIC_DATA_SIZE - 2) + / (L4_TASK_LDT_X86_ENTRY_SIZE / (L4_MWORD_BITS / 8)), +}; + +/***************************************************************************** + *** Implementation + *****************************************************************************/ + +#include +#include + +L4_INLINE long +fiasco_ldt_set(l4_cap_idx_t task, void *ldt, unsigned int num_desc, + unsigned int entry_number_start, l4_utcb_t *utcb) +{ + if (num_desc > L4_TASK_LDT_X86_MAX_ENTRIES) + return -L4_EINVAL; + l4_utcb_mr_u(utcb)->mr[0] = L4_TASK_LDT_SET_X86_OP; + l4_utcb_mr_u(utcb)->mr[1] = entry_number_start; + __builtin_memcpy(&l4_utcb_mr_u(utcb)->mr[2], ldt, + num_desc * L4_TASK_LDT_X86_ENTRY_SIZE); + return l4_error_u(l4_ipc_call(task, utcb, l4_msgtag(L4_PROTO_TASK, 2 + num_desc * 2, 0, 0), L4_IPC_NEVER), utcb); +} + +L4_INLINE unsigned +fiasco_gdt_get_entry_offset(l4_cap_idx_t thread, l4_utcb_t *utcb) +{ + l4_utcb_mr_u(utcb)->mr[0] = L4_THREAD_GDT_X86_OP; + if (l4_error_u(l4_ipc_call(thread, utcb, l4_msgtag(L4_PROTO_THREAD, 1, 0, 0), L4_IPC_NEVER), utcb)) + return -1; + return l4_utcb_mr_u(utcb)->mr[0]; +} + +#endif /* ! __L4_SYS__ARCH_X86__SEGMENT_H__ */ diff --git a/l4/pkg/l4sys/include/ARCH-x86/syscall-invoke.h b/l4/pkg/l4sys/include/ARCH-x86/syscall-invoke.h new file mode 100644 index 00000000..0768de5c --- /dev/null +++ b/l4/pkg/l4sys/include/ARCH-x86/syscall-invoke.h @@ -0,0 +1,65 @@ +/** + * \internal + * \file + * \brief L4 System Call Invoking in Assembler + * \ingroup l4_api + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg , + * Frank Mehnert + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#ifndef __L4_SYSCALL_INVOKE_H__ +#define __L4_SYSCALL_INVOKE_H__ + +/** + * \internal + * \addtogroup l4_internal_api Internal API + */ +/*@{*/ +/** + * \internal + * \brief Address of system call page. + */ +#define L4_ABS_syscall_page 0xeacff000 + +/** + * \internal + * \brief Offset of invoke system call. + */ +#define L4_ABS_invoke (0x000) + +/** + * \internal + * \brief Offset of debugger system call. + */ +#define L4_ABS_debugger (0x200) + +/** + * \internal + * \brief System call. + */ +# define L4_SYSCALL_debugger "int $0x32 \n\t" + +/** + * \internal + * \brief Generic system call. + */ +# define L4_SYSCALL(name) L4_SYSCALL_ ## name + +/*@}*/ +#endif diff --git a/l4/pkg/l4sys/include/ARCH-x86/utcb.h b/l4/pkg/l4sys/include/ARCH-x86/utcb.h new file mode 100644 index 00000000..4973a9a6 --- /dev/null +++ b/l4/pkg/l4sys/include/ARCH-x86/utcb.h @@ -0,0 +1,134 @@ +/*****************************************************************************/ +/** + * \file + * \brief UTCB definitions for X86. + * \ingroup l4_utcb_api + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +/*****************************************************************************/ +#ifndef __L4_SYS__INCLUDE__ARCH_X86__UTCB_H__ +#define __L4_SYS__INCLUDE__ARCH_X86__UTCB_H__ + +#include + +/** + * \defgroup l4_utcb_api_x86 x86 Virtual Registers (UTCB) + * \ingroup l4_utcb_api + */ + +/** + * \brief UTCB constants for x86 + * \ingroup l4_utcb_api_x86 + * \hideinitializer + */ +enum L4_utcb_consts_x86 +{ + /// Number if message registers used for exception IPC + L4_UTCB_EXCEPTION_REGS_SIZE = 16, + + /// Total number of message register (MRs) available + L4_UTCB_GENERIC_DATA_SIZE = 63, + + /// Total number of buffer registers (BRs) available + L4_UTCB_GENERIC_BUFFERS_SIZE = 58, + + /// Offset of MR[0] relative to the UTCB pointer + L4_UTCB_MSG_REGS_OFFSET = 0, + + /// Offset of BR[0] relative to the UTCB pointer + L4_UTCB_BUF_REGS_OFFSET = 64 * sizeof(l4_umword_t), + + /// Offset of TCR[0] relative to the UTCB pointer + L4_UTCB_THREAD_REGS_OFFSET = 123 * sizeof(l4_umword_t), + + /// BDR flag to accept reception of FPU state + L4_UTCB_INHERIT_FPU = 1UL << 24, + + /// Offset of two consecutive UTCBs + L4_UTCB_OFFSET = 512, +}; + +/** + * \brief UTCB structure for exceptions. + * \ingroup l4_utcb_api_x86 + */ +typedef struct l4_exc_regs_t +{ + l4_umword_t gs; /**< gs register */ + l4_umword_t fs; /**< fs register */ + + l4_umword_t edi; /**< edi register */ + l4_umword_t esi; /**< esi register */ + l4_umword_t ebp; /**< ebp register */ + l4_umword_t pfa; /**< page fault address */ + l4_umword_t ebx; /**< ebx register */ + l4_umword_t edx; /**< edx register */ + l4_umword_t ecx; /**< ecx register */ + l4_umword_t eax; /**< eax register */ + + l4_umword_t trapno; /**< trap number */ + l4_umword_t err; /**< error code */ + + l4_umword_t ip; /**< instruction pointer */ + l4_umword_t dummy1; /**< dummy \internal */ + l4_umword_t flags; /**< eflags */ + l4_umword_t sp; /**< stack pointer */ +} l4_exc_regs_t; + +#include_next + +/* + * ================================================================== + * Implementations. + */ + +L4_INLINE l4_utcb_t *l4_utcb_direct(void) L4_NOTHROW +{ + l4_utcb_t *utcb; + __asm__ __volatile__ ("mov %%fs:0, %0" : "=r" (utcb)); + return utcb; +} + +L4_INLINE l4_umword_t l4_utcb_exc_pc(l4_exc_regs_t *u) L4_NOTHROW +{ + return u->ip; +} + +L4_INLINE void l4_utcb_exc_pc_set(l4_exc_regs_t *u, l4_addr_t pc) L4_NOTHROW +{ + u->ip = pc; +} + +L4_INLINE l4_umword_t l4_utcb_exc_typeval(l4_exc_regs_t *u) L4_NOTHROW +{ + return u->trapno; +} + +L4_INLINE int l4_utcb_exc_is_pf(l4_exc_regs_t *u) L4_NOTHROW +{ + return u->trapno == 14; +} + +L4_INLINE l4_addr_t l4_utcb_exc_pfa(l4_exc_regs_t *u) L4_NOTHROW +{ + return (u->pfa & ~3) | (u->err & 2); +} + +#endif /* ! __L4_SYS__INCLUDE__ARCH_X86__UTCB_H__ */ diff --git a/l4/pkg/l4sys/include/ARCH-x86/vm b/l4/pkg/l4sys/include/ARCH-x86/vm new file mode 100644 index 00000000..50324b80 --- /dev/null +++ b/l4/pkg/l4sys/include/ARCH-x86/vm @@ -0,0 +1,25 @@ +// vi:ft=cpp +/** + * \file + * \brief X86 virtualization interface + */ +/* + * (c) 2008-2009 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ + +#pragma once +#include diff --git a/l4/pkg/l4sys/include/ARCH-x86/vm.h b/l4/pkg/l4sys/include/ARCH-x86/vm.h new file mode 100644 index 00000000..0f411052 --- /dev/null +++ b/l4/pkg/l4sys/include/ARCH-x86/vm.h @@ -0,0 +1,29 @@ +/** + * \internal + * \file + * \brief X86 virtualization interface. + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Henning Schild + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#ifndef __INCLUDE__ARCH_X86__VM_H__ +#define __INCLUDE__ARCH_X86__VM_H__ + +#include + +#endif /* ! __INCLUDE__ARCH_X86__VM_H__ */ diff --git a/l4/pkg/l4sys/include/L4API-l4f/ipc-impl.h b/l4/pkg/l4sys/include/L4API-l4f/ipc-impl.h new file mode 100644 index 00000000..44de6a2d --- /dev/null +++ b/l4/pkg/l4sys/include/L4API-l4f/ipc-impl.h @@ -0,0 +1,31 @@ +/** + * \file + * \brief Common IPC inline implementations. + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#ifndef __L4SYS__INCLUDE__L4API_FIASCO__IPC_IMPL_H__ +#define __L4SYS__INCLUDE__L4API_FIASCO__IPC_IMPL_H__ + + +L4_INLINE l4_msgtag_t +l4_ipc_sleep(l4_timeout_t timeout) L4_NOTHROW +{ return l4_ipc_receive(L4_INVALID_CAP, NULL, timeout); } + +#endif /* ! __L4SYS__INCLUDE__L4API_FIASCO__IPC_IMPL_H__ */ diff --git a/l4/pkg/l4sys/include/Makefile b/l4/pkg/l4sys/include/Makefile new file mode 100644 index 00000000..4c4f4f67 --- /dev/null +++ b/l4/pkg/l4sys/include/Makefile @@ -0,0 +1,11 @@ +PKGDIR ?= .. +L4DIR ?= $(PKGDIR)/../.. + +PKGNAME = sys +EXTRA_TARGET += capability kip task factory irq icu thread vcon \ + smart_capability scheduler meta typeinfo_svr ipc_gate \ + __vm ARCH-x86/vm ARCH-amd64/vm ARCH-arm/vm debugger + +include $(L4DIR)/mk/include.mk + + diff --git a/l4/pkg/l4sys/include/__kip-32bit.h b/l4/pkg/l4sys/include/__kip-32bit.h new file mode 100644 index 00000000..03b41461 --- /dev/null +++ b/l4/pkg/l4sys/include/__kip-32bit.h @@ -0,0 +1,105 @@ +/** + * \internal + * \file + * \brief Kernel Interface Page (KIP). + * \ingroup l4_kip_api + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg , + * Björn Döbel , + * Frank Mehnert , + * Torsten Frenzel , + * Martin Pohlack , + * Lars Reuther + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#pragma once + +#include + +/** + * \brief L4 Kernel Interface Page. + * \ingroup l4_kip_api + */ +typedef struct l4_kernel_info_t +{ + /* offset 0x00 */ + l4_uint32_t magic; /**< Kernel Info Page + ** identifier ("L4µK"). + **/ + l4_uint32_t version; ///< Kernel version + l4_uint8_t offset_version_strings; ///< offset to version string + l4_uint8_t fill0[3]; ///< reserved \internal + l4_uint8_t kip_sys_calls; ///< pointer to system calls + l4_uint8_t fill1[3]; ///< reserved \internal + + /* the following stuff is undocumented; we assume that the kernel + info page is located at offset 0x1000 into the L4 kernel boot + image so that these declarations are consistent with section 2.9 + of the L4 Reference Manual */ + + /* offset 0x10 */ + /* Kernel debugger */ + l4_umword_t scheduler_granularity; ///< for rounding time slices + l4_umword_t _res00[3]; ///< default_kdebug_end + + /* offset 0x20 */ + /* Sigma0 */ + l4_umword_t sigma0_esp; ///< Sigma0 start stack pointer + l4_umword_t sigma0_eip; ///< Sigma0 instruction pointer + l4_umword_t _res01[2]; ///< reserved \internal + + /* offset 0x30 */ + /* Sigma1 */ + l4_umword_t sigma1_esp; ///< Sigma1 start stack pointer + l4_umword_t sigma1_eip; ///< Sigma1 instruction pointer + l4_umword_t _res02[2]; ///< reserved \internal + + /* offset 0x40 */ + /* Root task */ + l4_umword_t root_esp; ///< Root task stack pointer + l4_umword_t root_eip; ///< Root task instruction pointer + l4_umword_t _res03[2]; ///< reserved \internal + + /* offset 0x50 */ + /* L4 configuration */ + l4_umword_t _res50[1]; ///< reserved \internal + l4_umword_t mem_info; ///< memory information + l4_umword_t _res58[2]; ///< reserved \internal + + /* offset 0x60 */ + l4_umword_t _res04[16]; ///< reserved \internal + + /* offset 0xA0 */ + volatile l4_cpu_time_t clock; ///< L4 system clock (µs) + l4_umword_t _res05[2]; ///< reserved \internal + + /* offset 0xB0 */ + l4_umword_t frequency_cpu; ///< CPU frequency in kHz + l4_umword_t frequency_bus; ///< Bus frequency + + /* offset 0xB8 */ + l4_umword_t _res06[10]; ///< reserved \internal + + /* offset 0xE0 */ + l4_umword_t user_ptr; ///< user_ptr + l4_umword_t vhw_offset; ///< offset to vhw structure + l4_umword_t _res07[2]; + + /* offset 0xF0 */ + struct l4_kip_platform_info platform_info; +} l4_kernel_info_t; diff --git a/l4/pkg/l4sys/include/__kip-64bit.h b/l4/pkg/l4sys/include/__kip-64bit.h new file mode 100644 index 00000000..ce3f63b7 --- /dev/null +++ b/l4/pkg/l4sys/include/__kip-64bit.h @@ -0,0 +1,101 @@ +/** + * \internal + * \file + * \brief Kernel Interface Page (KIP). + * \ingroup l4_kip_api + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg , + * Björn Döbel , + * Frank Mehnert , + * Torsten Frenzel + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#pragma once + +#include + +/** + * \brief L4 Kernel Interface Page. + * \ingroup l4_kip_api + */ +typedef struct l4_kernel_info_t +{ + /* offset 0x00 */ + l4_uint64_t magic; /**< Kernel Info Page + ** identifier ("L4µK"). + **/ + l4_uint64_t version; ///< Kernel version + l4_uint8_t offset_version_strings; ///< offset to version string + l4_uint8_t fill2[7]; ///< reserved \internal + l4_uint8_t kip_sys_calls; ///< pointer to system calls + l4_uint8_t fill3[7]; ///< reserved \internal + + /* the following stuff is undocumented; we assume that the kernel + info page is located at offset 0x1000 into the L4 kernel boot + image so that these declarations are consistent with section 2.9 + of the L4 Reference Manual */ + + /* offset 0x20 */ + /* Kernel debugger */ + l4_umword_t scheduler_granularity; ///< for rounding time slices + l4_umword_t _res00[3]; ///< default_kdebug_end + + /* offset 0x40 */ + /* Sigma0 */ + l4_umword_t sigma0_esp; ///< Sigma0 start stack pointer + l4_umword_t sigma0_eip; ///< Sigma0 instruction pointer + l4_umword_t _res01[2]; ///< reserved \internal + + /* offset 0x60 */ + /* Sigma1 */ + l4_umword_t sigma1_esp; ///< Sigma1 start stack pointer + l4_umword_t sigma1_eip; ///< Sigma1 instruction pointer + l4_umword_t _res02[2]; ///< reserved \internal + + /* offset 0x80 */ + /* Root task */ + l4_umword_t root_esp; ///< Root task stack pointer + l4_umword_t root_eip; ///< Root task instruction pointer + l4_umword_t _res03[2]; ///< reserved \internal + + /* offset 0xA0 */ + /* L4 configuration */ + l4_umword_t _res_a0[1]; ///< reserved \internal + l4_umword_t mem_info; ///< memory information + l4_umword_t _res_b0[2]; ///< reserver \internal + + /* offset 0xC0 */ + l4_umword_t _res04[16]; ///< reserved \internal + + /* offset 0x140 */ + volatile l4_cpu_time_t clock; ///< L4 system clock (µs) + l4_umword_t _res05[1]; ///< reserved \internal + l4_umword_t frequency_cpu; ///< CPU frequency in kHz + l4_umword_t frequency_bus; ///< Bus frequency + + /* offset 0x160 */ + l4_umword_t _res06[12]; ///< reserved \internal + + /* offset 0x1C0 */ + l4_umword_t user_ptr; ///< user_ptr + l4_umword_t vhw_offset; ///< offset to vhw structure + l4_umword_t _res07[2]; + + /* offset 0x1E0 */ + struct l4_kip_platform_info platform_info; +} l4_kernel_info_t; diff --git a/l4/pkg/l4sys/include/__l4_fpage.h b/l4/pkg/l4sys/include/__l4_fpage.h new file mode 100644 index 00000000..2b71990d --- /dev/null +++ b/l4/pkg/l4sys/include/__l4_fpage.h @@ -0,0 +1,533 @@ +/** + * \internal + * \file + * \brief Common flex-page definitions. + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg , + * Björn Döbel , + * Torsten Frenzel + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#pragma once + +/** + * \defgroup l4_fpage_api Flex pages + * \ingroup l4_api + * \brief Flex-page related API. + * + * A flex page is a page with a variable size, that can describe memory, + * IO-Ports (IA32 only), and sets of kernel objects. + * + * A flex page describes an always size aligned region of an address space. + * The size is given in a log2 scale. This means the size in elements (bytes + * for memory, ports for IO-Ports, and capabilities for kernel objects) is + * always a power of two. + * + * A flex page also carries type and access right information for the + * described region. The type information selects the address space in which + * the flex page is valid. Access rights have a meaning depending on the + * specific address space (type). + * + * There exists a special type for defining \em receive \em windows or for + * the l4_task_unmap() method, that can be used to describe all address + * spaces (all types) with a single flex page. + */ + +/** + * \brief L4 flexpage structure + * \ingroup l4_fpage_api + */ +enum l4_fpage_consts +{ + L4_FPAGE_RIGHTS_SHIFT = 0, ///< Access permissions shift + L4_FPAGE_TYPE_SHIFT = 4, ///< Flexpage type shift (memory, IO port, obj...) + L4_FPAGE_SIZE_SHIFT = 6, ///< Flexpage size shift (log2-based) + L4_FPAGE_ADDR_SHIFT = 12, ///< Page address shift + + L4_FPAGE_RIGHTS_BITS = 4, ///< Access permissions size + L4_FPAGE_TYPE_BITS = 2, ///< Flexpage type size (memory, IO port, obj...) + L4_FPAGE_SIZE_BITS = 6, ///< Flexpage size size (log2-based) + L4_FPAGE_ADDR_BITS = L4_MWORD_BITS - L4_FPAGE_ADDR_SHIFT, ///< Page address size + + + L4_FPAGE_RIGHTS_MASK = ((1UL << L4_FPAGE_RIGHTS_BITS) - 1) << L4_FPAGE_RIGHTS_SHIFT, + L4_FPAGE_TYPE_MASK = ((1UL << L4_FPAGE_TYPE_BITS) - 1) << L4_FPAGE_TYPE_SHIFT, + L4_FPAGE_SIZE_MASK = ((1UL << L4_FPAGE_SIZE_BITS) - 1) << L4_FPAGE_SIZE_SHIFT, + L4_FPAGE_ADDR_MASK = ((1UL << L4_FPAGE_ADDR_BITS) - 1) << L4_FPAGE_ADDR_SHIFT, +}; + +/** + * \brief L4 flexpage type + * \ingroup l4_fpage_api + */ +typedef union { + l4_umword_t fpage; ///< Raw value + l4_umword_t raw; ///< Raw value +} l4_fpage_t; + +/** \brief Constants for flexpages + * \ingroup l4_fpage_api + */ +enum +{ + L4_WHOLE_ADDRESS_SPACE = 63 /**< Whole address space size */ +}; + +/** + * \brief Send-flex-page types + * \ingroup l4_fpage_api + */ +typedef struct { + l4_umword_t snd_base; ///< Offset in receive window (send base) + l4_fpage_t fpage; ///< Source flex-page descriptor +} l4_snd_fpage_t; + + +/** \brief Flex-page rights + * \ingroup l4_fpage_api + */ +enum L4_fpage_rights +{ + L4_FPAGE_RO = 4, /**< Read-only flex page */ + L4_FPAGE_RW = 6, /**< Read-write flex page */ + L4_FPAGE_RX = 5, + L4_FPAGE_RWX = 7, + L4_FPAGE_X = 1, + L4_FPAGE_W = 2, +}; + +/** \brief Cap-flex-page rights + * \ingroup l4_fpage_api + */ +enum L4_cap_fpage_rights +{ + L4_CAP_FPAGE_R = 0x4, /**< Read-only cap */ + L4_CAP_FPAGE_RO = 0x4, /**< Read-only cap */ + L4_CAP_FPAGE_RW = 0x5, /**< Read-write cap */ + L4_CAP_FPAGE_RS = 0x6, + L4_CAP_FPAGE_RWS = 0x7, + L4_CAP_FPAGE_S = 0x2, + L4_CAP_FPAGE_W = 0x1, + L4_CAP_FPAGE_D = 0x8, + L4_CAP_FPAGE_RWSD = 0xf, + L4_CAP_FPAGE_RSD = 0xe, +}; + +/** \brief Flex-page type + * \ingroup l4_fpage_api + */ +enum L4_fpage_type +{ + L4_FPAGE_SPECIAL = 0, + L4_FPAGE_MEMORY = 1, + L4_FPAGE_IO = 2, + L4_FPAGE_OBJ = 3, +}; + +/** \brief Flex-page map control flags + * \ingroup l4_fpage_api + */ +enum L4_fpage_control +{ + L4_FPAGE_CONTROL_OFFSET_SHIFT = 10, + L4_FPAGE_CONTROL_MASK = ~0UL << L4_FPAGE_CONTROL_OFFSET_SHIFT, +}; + +/** \brief Flex-page map control for capabilities (snd_base) + * \ingroup l4_fpage_api + */ +enum L4_obj_fpage_ctl +{ + L4_FPAGE_C_NO_REF_CNT = 0x10, + L4_FPAGE_C_REF_CNT = 0x00, +}; + + +/** \brief Flex-page cacheability option + * \ingroup l4_fpage_api + */ +enum l4_fpage_cacheability_opt_t +{ + /** Enable the cacheability option in a send flex page. */ + L4_FPAGE_CACHE_OPT = 0x1, + + /** Cacheability option to enable caches for the mapping. */ + L4_FPAGE_CACHEABLE = 0x3, + + /** Cacheability option to enable buffered writes for the mapping. */ + L4_FPAGE_BUFFERABLE = 0x5, + + /** Cacheability option to disable caching for the mapping. */ + L4_FPAGE_UNCACHEABLE = 0x1 +}; + + +/** \brief Special constants for IO flex pages + * \ingroup l4_fpage_api + */ +enum +{ + /** Whole I/O address space size */ + L4_WHOLE_IOADDRESS_SPACE = 16, + + /** Maximum I/O port address */ + L4_IOPORT_MAX = (1L << L4_WHOLE_IOADDRESS_SPACE) +}; + + + +/** + * \brief Create a memory flex page. + * \ingroup l4_fpage_api + * + * \param address Flex-page start address + * \param size Flex-page size (log2), #L4_WHOLE_ADDRESS_SPACE to + * specify the whole address space (with \a address 0) + * \param rights Access rights, see #l4_fpage_rights + * \return Memory flex page + */ +L4_INLINE l4_fpage_t +l4_fpage(unsigned long address, unsigned int size, unsigned char rights) L4_NOTHROW; + +/** + * \brief Get a flex page, describing all address spaces at once. + * \ingroup l4_fpage_api + * + * \return Special \em all-spaces flex page. + */ +L4_INLINE l4_fpage_t +l4_fpage_all(void) L4_NOTHROW; + +/** + * \brief Get an invalid flex page. + * \ingroup l4_fpage_api + * + * \return Special \em invalid flex page. + */ +L4_INLINE l4_fpage_t +l4_fpage_invalid(void) L4_NOTHROW; + + +/** + * \brief Create an IO-port flex page. + * \ingroup l4_fpage_api + * + * \param port I/O-flex-page port base + * \param size I/O-flex-page size, #L4_WHOLE_IOADDRESS_SPACE to + * specify the whole I/O address space (with \a port 0) + * \return I/O flex page + */ +L4_INLINE l4_fpage_t +l4_iofpage(unsigned long port, unsigned int size) L4_NOTHROW; + + +/** + * \brief Create a kernel-object flex page. + * \ingroup l4_fpage_api + * + * \param obj Base capability selector. + * \param order Log2 size (number of capabilities). + * \param rights Access rights + * \return Flex page for a set of kernel objects. + * + * \todo What are the possible values for the rights parameter? + */ +L4_INLINE l4_fpage_t +l4_obj_fpage(l4_cap_idx_t obj, unsigned int order, unsigned char rights) L4_NOTHROW; + +/** + * \brief Test if the flex page is writable. + * \ingroup l4_fpage_api + * + * \param fp Flex page. + * \return != 0 if flex page is writable, 0 if not + */ +L4_INLINE int +l4_is_fpage_writable(l4_fpage_t fp) L4_NOTHROW; + + +/** + * \defgroup l4_msgitem_api Message Items + * \ingroup l4_ipc_api + * \brief Message item related functions. + * + * Message items are typed items that can be transferred via IPC + * operations. Message items are also used to specify receive windows for + * typed items to be received. + * Message items are placed in the message registers (MRs) of the UTCB of + * the sending thread. + * Receive items are placed in the buffer registers (BRs) of the UTCB + * of the receiving thread. + * + * Message items are usually two-word data structures. The first + * word denotes the type of the message item (for example a memory flex-page, + * io flex-page or object flex-page) and the second word contains + * information depending on the type. There is actually one exception that is + * a small (one word) receive buffer item for a single capability. + */ + +/** + * \brief Create the first word for a map item for the memory space. + * \ingroup l4_msgitem_api + * + * \param spot Hot spot address, used to determine what is actually mapped + * when send and receive flex page have differing sizes. + * \param cache Cacheability hints for memory flex pages. See + * \link l4_fpage_api::l4_fpage_cacheability_opt_t + * Cacheability options \endlink + * \param grant Indicates if it is a map or a grant item. + * + * \return The value to be used as first word in a map item for memory. + */ +L4_INLINE l4_umword_t +l4_map_control(l4_umword_t spot, unsigned char cache, unsigned grant) L4_NOTHROW; + +/** + * \brief Create the first word for a map item for the object space. + * \ingroup l4_msgitem_api + * + * \param spot Hot spot address, used to determine what is actually mapped + * when send and receive flex pages have different size. + * \param grant Indicates if it is a map item or a grant item. + * + * \return The value to be used as first word in a map item for kernel objects + * or IO-ports. + */ +L4_INLINE l4_umword_t +l4_map_obj_control(l4_umword_t spot, unsigned grant) L4_NOTHROW; + +/** + * \brief Return rights from a flex page. + * \ingroup l4_fpage_api + * + * \param f Flex page + * \return Size part of the given flex page. + */ +L4_INLINE unsigned +l4_fpage_rights(l4_fpage_t f) L4_NOTHROW; + +/** + * \brief Return type from a flex page. + * \ingroup l4_fpage_api + * + * \param f Flex page + * \return Type part of the given flex page. + */ +L4_INLINE unsigned +l4_fpage_type(l4_fpage_t f) L4_NOTHROW; + +/** + * \brief Return size from a flex page. + * \ingroup l4_fpage_api + * + * \param f Flex page + * \return Size part of the given flex page. + */ +L4_INLINE unsigned +l4_fpage_size(l4_fpage_t f) L4_NOTHROW; + +/** + * \brief Return page from a flex page. + * \ingroup l4_fpage_api + * + * \param f Flex page + * \return Page part of the given flex page. + */ +L4_INLINE unsigned long +l4_fpage_page(l4_fpage_t f) L4_NOTHROW; + +/** + * \brief Set new right in a flex page. + * \ingroup l4_fpage_api + * + * \param src Flex page + * \param new_rights New rights + * + * \return Modified flex page with new rights. + */ +L4_INLINE l4_fpage_t +l4_fpage_set_rights(l4_fpage_t src, unsigned char new_rights) L4_NOTHROW; + +/** + * \brief Test whether a given range is completely within an fpage. + * \ingroup l4_fpage_api + * + * \param fpage Flex page + * \param addr Address + * \param size Size of range in log2. + */ +L4_INLINE int +l4_fpage_contains(l4_fpage_t fpage, l4_addr_t addr, unsigned size) L4_NOTHROW; + +/** + * \brief Determine maximum flex page size of a region. + * \ingroup l4_fpage_api + * + * \param order Order value to start with (e.g. for memory + * L4_LOG2_PAGESIZE would be used) + * \param addr Address to be covered by the flex page. + * \param min_addr Start of region / minimal address (including). + * \param max_addr End of region / maximal address (excluding). + * \param hotspot (Optional) hot spot. + * + * \return Maximum order (log2-size) possible. + * + * \note The start address of the flex-page can be determined with + * l4_trunc_size(addr, returnvalue) + */ +L4_INLINE unsigned char +l4_fpage_max_order(unsigned char order, l4_addr_t addr, + l4_addr_t min_addr, l4_addr_t max_addr, + l4_addr_t hotspot L4_DEFAULT_PARAM(0)); + +/************************************************************************* + * Implementations + *************************************************************************/ + +L4_INLINE unsigned +l4_fpage_rights(l4_fpage_t f) L4_NOTHROW +{ + return (f.raw & L4_FPAGE_RIGHTS_MASK) >> L4_FPAGE_RIGHTS_SHIFT; +} + +L4_INLINE unsigned +l4_fpage_type(l4_fpage_t f) L4_NOTHROW +{ + return (f.raw & L4_FPAGE_TYPE_MASK) >> L4_FPAGE_TYPE_SHIFT; +} + +L4_INLINE unsigned +l4_fpage_size(l4_fpage_t f) L4_NOTHROW +{ + return (f.raw & L4_FPAGE_SIZE_MASK) >> L4_FPAGE_SIZE_SHIFT; +} + +L4_INLINE unsigned long +l4_fpage_page(l4_fpage_t f) L4_NOTHROW +{ + return (f.raw & L4_FPAGE_ADDR_MASK) >> L4_FPAGE_ADDR_SHIFT; +} + +/** \internal */ +L4_INLINE l4_fpage_t +__l4_fpage_generic(unsigned long address, unsigned int type, + unsigned int size, unsigned char rights) L4_NOTHROW; + +L4_INLINE l4_fpage_t +__l4_fpage_generic(unsigned long address, unsigned int type, + unsigned int size, unsigned char rights) L4_NOTHROW +{ + l4_fpage_t t; + t.raw = ((rights << L4_FPAGE_RIGHTS_SHIFT) & L4_FPAGE_RIGHTS_MASK) + | ((type << L4_FPAGE_TYPE_SHIFT) & L4_FPAGE_TYPE_MASK) + | ((size << L4_FPAGE_SIZE_SHIFT) & L4_FPAGE_SIZE_MASK) + | ((address ) & L4_FPAGE_ADDR_MASK); + return t; +} + +L4_INLINE l4_fpage_t +l4_fpage_set_rights(l4_fpage_t src, unsigned char new_rights) L4_NOTHROW +{ + l4_fpage_t f; + f.raw = ((L4_FPAGE_TYPE_MASK | L4_FPAGE_SIZE_MASK | L4_FPAGE_ADDR_MASK) & src.raw) + | ((new_rights << L4_FPAGE_RIGHTS_SHIFT) & L4_FPAGE_RIGHTS_MASK); + return f; +} + +L4_INLINE l4_fpage_t +l4_fpage(unsigned long address, unsigned int size, unsigned char rights) L4_NOTHROW +{ + return __l4_fpage_generic(address, L4_FPAGE_MEMORY, size, rights); +} + +L4_INLINE l4_fpage_t +l4_iofpage(unsigned long port, unsigned int size) L4_NOTHROW +{ + return __l4_fpage_generic(port << L4_FPAGE_ADDR_SHIFT, L4_FPAGE_IO, size, L4_FPAGE_RW); +} + +L4_INLINE l4_fpage_t +l4_obj_fpage(l4_cap_idx_t obj, unsigned int order, unsigned char rights) L4_NOTHROW +{ + return __l4_fpage_generic(obj, L4_FPAGE_OBJ, order, rights); +} + +L4_INLINE l4_fpage_t +l4_fpage_all(void) L4_NOTHROW +{ + return __l4_fpage_generic(0, 0, L4_WHOLE_ADDRESS_SPACE, 0); +} + +L4_INLINE l4_fpage_t +l4_fpage_invalid(void) L4_NOTHROW +{ + return __l4_fpage_generic(0, 0, 0, 0); +} + + +L4_INLINE int +l4_is_fpage_writable(l4_fpage_t fp) L4_NOTHROW +{ + return l4_fpage_rights(fp) & L4_FPAGE_W; +} + +L4_INLINE l4_umword_t +l4_map_control(l4_umword_t snd_base, unsigned char cache, unsigned grant) L4_NOTHROW +{ + return (snd_base & L4_FPAGE_CONTROL_MASK) + | ((l4_umword_t)cache << 4) | L4_ITEM_MAP | grant; +} + +L4_INLINE l4_umword_t +l4_map_obj_control(l4_umword_t snd_base, unsigned grant) L4_NOTHROW +{ + return l4_map_control(snd_base, 0, grant); +} + +L4_INLINE int +l4_fpage_contains(l4_fpage_t fpage, l4_addr_t addr, unsigned log2size) L4_NOTHROW +{ + l4_addr_t fa = l4_fpage_page(fpage) << L4_FPAGE_ADDR_SHIFT; + return (fa <= addr) + && (fa + (1UL << l4_fpage_size(fpage)) >= addr + (1UL << log2size)); +} + +L4_INLINE unsigned char +l4_fpage_max_order(unsigned char order, l4_addr_t addr, + l4_addr_t min_addr, l4_addr_t max_addr, + l4_addr_t hotspot) +{ + while (order < 30 /* limit to 1GB flexpages */) + { + l4_addr_t mask; + l4_addr_t base = l4_trunc_size(addr, order + 1); + if (base < min_addr) + return order; + + if (base + (1UL << (order + 1)) - 1 > max_addr - 1) + return order; + + mask = ~(~0UL << (order + 1)); + if (hotspot == ~0UL || ((addr ^ hotspot) & mask)) + break; + + ++order; + } + + return order; +} diff --git a/l4/pkg/l4sys/include/__timeout.h b/l4/pkg/l4sys/include/__timeout.h new file mode 100644 index 00000000..5f2469fa --- /dev/null +++ b/l4/pkg/l4sys/include/__timeout.h @@ -0,0 +1,277 @@ +/** + * \internal + * \file + * \brief Timeout definitions. + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg , + * Torsten Frenzel + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#ifndef L4_SYS_TIMEOUT_H__ +#define L4_SYS_TIMEOUT_H__ + +#include + +/** + * \defgroup l4_timeout_api Timeouts + * \ingroup l4_ipc_api + * \brief All kinds of timeouts and time related functions. + */ + +/** + * \brief Basic timeout specification. + * \ingroup l4_timeout_api + * + * Basically a floating point number with 10 bits mantissa and + * 5 bits exponent (t = m*2^e). + * + * The timeout can also specify an absolute point in time (bit 16 == 1). + */ +typedef struct l4_timeout_s { + l4_uint16_t t; /**< timeout value */ +} __attribute__((packed)) l4_timeout_s; + + +/** + * \brief Timeout pair. + * \ingroup l4_timeout_api + * + * For IPC there are usually a send and a receive timeout. + * So this structure contains a pair of timeouts. + */ +typedef union l4_timeout_t { + l4_uint32_t raw; /**< raw value */ + struct + { +#ifdef __BIG_ENDIAN__ + l4_timeout_s snd; /**< send timeout */ + l4_timeout_s rcv; /**< receive timeout */ +#else + l4_timeout_s rcv; /**< receive timeout */ + l4_timeout_s snd; /**< send timeout */ +#endif + } p; /**< combined timeout */ +} l4_timeout_t; + + +/** + * \brief Timeout constants. + * \ingroup l4_timeout_api + */ +/*@{*/ +#define L4_IPC_TIMEOUT_0 ((l4_timeout_s){0x0400}) /**< 0 timeout */ +#define L4_IPC_TIMEOUT_NEVER ((l4_timeout_s){0}) /**< never timeout */ +#define L4_IPC_NEVER_INITIALIZER {0} /**< never timeout, init */ +#define L4_IPC_NEVER ((l4_timeout_t){0}) /**< never timeout */ +#define L4_IPC_RECV_TIMEOUT_0 ((l4_timeout_t){0x00000400}) /**< 0 receive timeout */ +#define L4_IPC_SEND_TIMEOUT_0 ((l4_timeout_t){0x04000000}) /**< 0 send timeout */ +#define L4_IPC_BOTH_TIMEOUT_0 ((l4_timeout_t){0x04000400}) /**< 0 receive and send timeout */ +/*@}*/ + +/** + * \brief Intervals of validity for absolute timeouts + * \ingroup l4_timeout_api + * + * Times are actually 2^x values (e.g. 2ms -> 2048µs) + */ +enum l4_timeout_abs_validity { + L4_TIMEOUT_ABS_V1_ms = 0, + L4_TIMEOUT_ABS_V2_ms, + L4_TIMEOUT_ABS_V4_ms, + L4_TIMEOUT_ABS_V8_ms, /* 5 */ + L4_TIMEOUT_ABS_V16_ms, + L4_TIMEOUT_ABS_V32_ms, + L4_TIMEOUT_ABS_V64_ms, + L4_TIMEOUT_ABS_V128_ms, + L4_TIMEOUT_ABS_V256_ms, /* 10 */ + L4_TIMEOUT_ABS_V512_ms, + L4_TIMEOUT_ABS_V1_s, + L4_TIMEOUT_ABS_V2_s, + L4_TIMEOUT_ABS_V4_s, + L4_TIMEOUT_ABS_V8_s, + L4_TIMEOUT_ABS_V16_s, + L4_TIMEOUT_ABS_V32_s, +}; + +/** + * \brief Get relative timeout consisting of mantissa and exponent. + * \ingroup l4_timeout_api + * + * \param man Mantissa of timeout + * \param exp Exponent of timeout + * + * \return timeout value + */ +L4_INLINE +l4_timeout_s l4_timeout_rel(unsigned man, unsigned exp) L4_NOTHROW; + + +/** + * \brief Convert explicit timeout values to l4_timeout_t type. + * \ingroup l4_timeout_api + * + * \param snd_man Mantissa of send timeout. + * \param snd_exp Exponent of send timeout. + * \param rcv_man Mantissa of receive timeout. + * \param rcv_exp Exponent of receive timeout. + */ +L4_INLINE +l4_timeout_t l4_ipc_timeout(unsigned snd_man, unsigned snd_exp, + unsigned rcv_man, unsigned rcv_exp) L4_NOTHROW; + +/** + * \brief Combine send and receive timeout in a timeout. + * \ingroup l4_timeout_api + * + * \param snd Send timeout + * \param rcv Receive timeout + * + * \return L4 timeout + */ +L4_INLINE +l4_timeout_t l4_timeout(l4_timeout_s snd, l4_timeout_s rcv) L4_NOTHROW; + +/** + * \brief Set send timeout in given to timeout. + * \ingroup l4_timeout_api + * + * \param snd Send timeout + * \retval to L4 timeout + */ +L4_INLINE +void l4_snd_timeout(l4_timeout_s snd, l4_timeout_t *to) L4_NOTHROW; + +/** + * \brief Set receive timeout in given to timeout. + * \ingroup l4_timeout_api + * + * \param rcv Receive timeout + * \retval to L4 timeout + */ +L4_INLINE +void l4_rcv_timeout(l4_timeout_s rcv, l4_timeout_t *to) L4_NOTHROW; + +/** + * \brief Get clock value of out timeout. + * \ingroup l4_timeout_api + * + * \param to L4 timeout + * + * \return Clock value + */ +L4_INLINE +l4_kernel_clock_t l4_timeout_rel_get(l4_timeout_s to) L4_NOTHROW; + + +/** + * \brief Return whether the given timeout is absolute or not. + * \ingroup l4_timeout_api + * + * \param to L4 timeout + * + * \return != 0 if absolute, 0 if relative + */ +L4_INLINE +unsigned l4_timeout_is_absolute(l4_timeout_s to) L4_NOTHROW; + +/** + * \brief Get clock value for a clock + a timeout. + * \ingroup l4_timeout_api + * + * \param cur Clock value + * \param to L4 timeout + * + * \return Clock sum + */ +L4_INLINE +l4_kernel_clock_t l4_timeout_get(l4_kernel_clock_t cur, l4_timeout_s to) L4_NOTHROW; + + +/* + * Implementation + */ + +L4_INLINE +l4_timeout_t l4_ipc_timeout(unsigned snd_man, unsigned snd_exp, + unsigned rcv_man, unsigned rcv_exp) L4_NOTHROW +{ + l4_timeout_t t; + t.p.snd.t = (snd_man & 0x3ff) | ((snd_exp << 10) & 0x7c00); + t.p.rcv.t = (rcv_man & 0x3ff) | ((rcv_exp << 10) & 0x7c00); + return t; +} + + +L4_INLINE +l4_timeout_t l4_timeout(l4_timeout_s snd, l4_timeout_s rcv) L4_NOTHROW +{ + l4_timeout_t t; + t.p.snd = snd; + t.p.rcv = rcv; + return t; +} + + +L4_INLINE +void l4_snd_timeout(l4_timeout_s snd, l4_timeout_t *to) L4_NOTHROW +{ + to->p.snd = snd; +} + + +L4_INLINE +void l4_rcv_timeout(l4_timeout_s rcv, l4_timeout_t *to) L4_NOTHROW +{ + to->p.rcv = rcv; +} + + +L4_INLINE +l4_timeout_s l4_timeout_rel(unsigned man, unsigned exp) L4_NOTHROW +{ + return (l4_timeout_s){(l4_uint16_t)((man & 0x3ff) | ((exp << 10) & 0x7c00))}; +} + + +L4_INLINE +l4_kernel_clock_t l4_timeout_rel_get(l4_timeout_s to) L4_NOTHROW +{ + if (to.t == 0) + return ~0ULL; + return (l4_kernel_clock_t)(to.t & 0x3ff) << ((to.t >> 10) & 0x1f); +} + + +L4_INLINE +unsigned l4_timeout_is_absolute(l4_timeout_s to) L4_NOTHROW +{ + return to.t & 0x8000; +} + + +L4_INLINE +l4_kernel_clock_t l4_timeout_get(l4_kernel_clock_t cur, l4_timeout_s to) L4_NOTHROW +{ + if (l4_timeout_is_absolute(to)) + return 0; /* We cannot retrieve the value ... */ + else + return cur + l4_timeout_rel_get(to); +} + + +#endif diff --git a/l4/pkg/l4sys/include/__typeinfo.h b/l4/pkg/l4sys/include/__typeinfo.h new file mode 100644 index 00000000..841fe351 --- /dev/null +++ b/l4/pkg/l4sys/include/__typeinfo.h @@ -0,0 +1,195 @@ +/** + * \file + * \brief Type information handling. + */ +/* + * (c) 2010 Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#pragma once + +#if defined(__GXX_RTTI) || !defined(L4_NO_RTTI) +# include + typedef std::type_info const *L4_std_type_info_ptr; +# define L4_KOBJECT_META_RTTI(type) (&typeid(type)) + inline char const *L4_kobject_type_name(L4_std_type_info_ptr n) + { return n ? n->name() : 0; } +#else + typedef void const *L4_std_type_info_ptr; +# define L4_KOBJECT_META_RTTI(type) (0) + inline char const *L4_kobject_type_name(L4_std_type_info_ptr) + { return 0; } +#endif + +namespace L4 { + +/** + * \brief Dynamic Type Information for L4Re Interfaces. + * + * This class represents the runtime-dynamic type information for + * L4Re interfaces, and is not intended to be used directly by applications. + * \note The interface of is subject to changes. + * + * The main use for this info is to be used by the implementation of the + * L4::cap_dynamic_cast() function. + * + */ +struct Type_info +{ + L4_std_type_info_ptr _type; + Type_info const *const *_bases; + unsigned _num_bases; + long _proto; + + L4_std_type_info_ptr type() const { return _type; } + Type_info const *base(unsigned idx) const { return _bases[idx]; } + unsigned num_bases() const { return _num_bases; } + long proto() const { return _proto; } + char const *name() const { return L4_kobject_type_name(type()); } + bool has_proto(long proto) const + { + if (_proto && _proto == proto) + return true; + + if (!proto) + return false; + + for (unsigned i = 0; i < _num_bases; ++i) + if (base(i)->has_proto(proto)) + return true; + + return false; + } +}; + + +/** + * \brief Get the L4::Type_info for the L4Re interface given in \a T. + * \param T The type (L4Re interface) for which the information shall be + * returned. + * \return A pointer to the L4::Type_info structure for \a T. + */ +template +inline +Type_info const *kobject_typeid() +{ return &T::__Kobject_typeid::_m; } + + +/** + * \internal + */ +#define L4____GEN_TI(t...) \ +Type_info const t::__Kobject_typeid::_m = \ +{ \ + L4_KOBJECT_META_RTTI(Derived), \ + &t::__Kobject_typeid::_b[0], sizeof(t::__Kobject_typeid::_b) / sizeof(t::__Kobject_typeid::_b[0]), PROTO \ +} + +/** + * \internal + */ +#define L4____GEN_TI_MEMBERS() \ +private: \ + template< typename T > friend Type_info const *kobject_typeid(); \ +protected: \ + struct __Kobject_typeid { \ + static Type_info const *const _b[]; \ + static Type_info const _m; }; \ +public: \ + static long const Protocol = PROTO; + + +/** + * \brief Helper class to create an L4Re interface class that is derived + * from a single base class. + * + * \param Derived is the name of the new interface. + * \param Base is the name of the interfaces single base class. + * \param PROTO may be set to the statically assigned protocol number + * used to communicate with this interface. + * + * The typical usage pattern is shown in the following code snippet. The + * semantics of this example is an interface My_iface that is derived from + * L4::Kobject. + * + * \code + * class My_iface : public L4::Kobject_t + * { + * ... + * }; + * \endcode + * + */ +template< typename Derived, typename Base, long PROTO = 0 > +class Kobject_t : public Base +{ L4____GEN_TI_MEMBERS() }; + + +template< typename Derived, typename Base, long PROTO > +Type_info const *const Kobject_t::__Kobject_typeid::_b[] = +{ &Base::__Kobject_typeid::_m }; + +/** + * \internal + */ +template< typename Derived, typename Base, long PROTO > +L4____GEN_TI(Kobject_t); + + +/** + * \brief Helper class to create an L4Re interface class that is derived + * from two base classes. + * + * \param Derived is the name of the new interface. + * \param Base1 is the name of the interfaces first base class. + * \param Base2 is the name of the interfaces second base class. + * \param PROTO may be set to the statically assigned protocol number + * used to communicate with this interface. + * + * The typical usage pattern is shown in the following code snippet. The + * semantics of this example is an interface My_iface that is derived from + * L4::Icu and L4Re::Dataspace. + * + * \code + * class My_iface : public L4::Kobject_2t + * { + * ... + * }; + * \endcode + * + */ +template< typename Derived, typename Base1, typename Base2, long PROTO = 0 > +class Kobject_2t : public Base1, public Base2 +{ L4____GEN_TI_MEMBERS() }; + + +template< typename Derived, typename Base1, typename Base2, long PROTO > +Type_info const *const Kobject_2t::__Kobject_typeid::_b[] = +{ + &Base1::__Kobject_typeid::_m, + &Base2::__Kobject_typeid::_m +}; + +/** + * \internal + */ +template< typename Derived, typename Base1, typename Base2, long PROTO > +L4____GEN_TI(Kobject_2t); + +#undef L4____GEN_TI +#undef L4____GEN_TI_MEMBERS + +} diff --git a/l4/pkg/l4sys/include/__vm b/l4/pkg/l4sys/include/__vm new file mode 100644 index 00000000..5498d154 --- /dev/null +++ b/l4/pkg/l4sys/include/__vm @@ -0,0 +1,46 @@ +// vi:ft=cpp +/** + * \file + * \brief X86 virtualization interface + */ +/* + * (c) 2008-2010 Adam Lackorzynski , + * Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ + +#pragma once + +#include +#include + +namespace L4 { + +/** + * \brief Virtual machine. + * \ingroup l4_vm_api + */ +class Vm : public Kobject_t +{ +protected: + Vm(); + +private: + Vm(Vm const &); + void operator = (Vm const &); +}; + +}; diff --git a/l4/pkg/l4sys/include/__vm-svm.h b/l4/pkg/l4sys/include/__vm-svm.h new file mode 100644 index 00000000..5cb81da2 --- /dev/null +++ b/l4/pkg/l4sys/include/__vm-svm.h @@ -0,0 +1,161 @@ +/** + * \internal + * \file + * \brief X86 virtualization interface. + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#pragma once + +#include +#include + +/** + * \defgroup l4_vm_svm_api VM API for SVM + * \brief Virtual machine API for SVM. + * \ingroup l4_vm_api + */ + + +/** + * \brief VMCB structure for SVM VMs + * \ingroup l4_vm_svm_api + */ +typedef struct l4_vm_svm_vmcb_control_area +{ + l4_uint16_t intercept_rd_crX; + l4_uint16_t intercept_wr_crX; + + l4_uint16_t intercept_rd_drX; + l4_uint16_t intercept_wr_drX; + + l4_uint32_t intercept_exceptions; + + l4_uint32_t intercept_instruction0; + l4_uint32_t intercept_instruction1; + + l4_uint8_t _reserved0[44]; + + l4_uint64_t iopm_base_pa; + l4_uint64_t msrpm_base_pa; + l4_uint64_t tsc_offset; + l4_uint64_t guest_asid_tlb_ctl; + l4_uint64_t interrupt_ctl; + l4_uint64_t interrupt_shadow; + l4_uint64_t exitcode; + l4_uint64_t exitinfo1; + l4_uint64_t exitinfo2; + l4_uint64_t exitintinfo; + l4_uint64_t np_enable; + + l4_uint8_t _reserved1[16]; + + l4_uint64_t eventinj; + l4_uint64_t n_cr3; + l4_uint64_t lbr_virtualization_enable; + + l4_uint8_t _reserved2[832]; +} __attribute__((packed)) l4_vm_svm_vmcb_control_area_t; + +/** + * \brief State save area segment selector struct + * \ingroup l4_vm_svm_api + */ +typedef struct l4_vm_svm_vmcb_state_save_area_seg +{ + l4_uint16_t selector; + l4_uint16_t attrib; + l4_uint32_t limit; + l4_uint64_t base; +} __attribute__((packed)) l4_vm_svm_vmcb_state_save_area_seg_t; + +/** + * \brief State save area structure for SVM VMs + * \ingroup l4_vm_svm_api + */ +typedef struct l4_vm_svm_vmcb_state_save_area +{ + struct l4_vm_svm_vmcb_state_save_area_seg es; + struct l4_vm_svm_vmcb_state_save_area_seg cs; + struct l4_vm_svm_vmcb_state_save_area_seg ss; + struct l4_vm_svm_vmcb_state_save_area_seg ds; + struct l4_vm_svm_vmcb_state_save_area_seg fs; + struct l4_vm_svm_vmcb_state_save_area_seg gs; + struct l4_vm_svm_vmcb_state_save_area_seg gdtr; + struct l4_vm_svm_vmcb_state_save_area_seg ldtr; + struct l4_vm_svm_vmcb_state_save_area_seg idtr; + struct l4_vm_svm_vmcb_state_save_area_seg tr; + + l4_uint8_t _reserved0[43]; + + l4_uint8_t cpl; + + l4_uint32_t _reserved1; + + l4_uint64_t efer; + + l4_uint8_t _reserved2[112]; + + l4_uint64_t cr4; + l4_uint64_t cr3; + l4_uint64_t cr0; + l4_uint64_t dr7; + l4_uint64_t dr6; + l4_uint64_t rflags; + l4_uint64_t rip; + + l4_uint8_t _reserved3[88]; + + l4_uint64_t rsp; + + l4_uint8_t _reserved4[24]; + + l4_uint64_t rax; + l4_uint64_t star; + l4_uint64_t lstar; + l4_uint64_t cstar; + l4_uint64_t sfmask; + l4_uint64_t kernelgsbase; + l4_uint64_t sysenter_cs; + l4_uint64_t sysenter_esp; + l4_uint64_t sysenter_eip; + l4_uint64_t cr2; + + l4_uint8_t _reserved5[32]; + + l4_uint64_t g_pat; + l4_uint64_t dbgctl; + l4_uint64_t br_from; + l4_uint64_t br_to; + l4_uint64_t lastexcpfrom; + l4_uint64_t last_excpto; + + l4_uint8_t _reserved6[2408]; +} __attribute__((packed)) l4_vm_svm_vmcb_state_save_area_t; + + +/** + * \brief Control structure for SVM VMs + * \ingroup l4_vm_svm_api + */ +typedef struct l4_vm_svm_vmcb_t +{ + l4_vm_svm_vmcb_control_area_t control_area; + l4_vm_svm_vmcb_state_save_area_t state_save_area; +} l4_vm_svm_vmcb_t; diff --git a/l4/pkg/l4sys/include/__vm-vmx.h b/l4/pkg/l4sys/include/__vm-vmx.h new file mode 100644 index 00000000..4083bc96 --- /dev/null +++ b/l4/pkg/l4sys/include/__vm-vmx.h @@ -0,0 +1,84 @@ +/** + * \internal + * \file + * \brief X86 virtualization interface. + */ +/* + * (c) 2010 Adam Lackorzynski , + * Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#pragma once + +/** + * \defgroup l4_vm_vmx_api VM API for VMX + * \brief Virtual machine API for VMX. + * \ingroup l4_vm_api + */ + + +/** + * \brief Additional VMCS fields. + * \ingroup l4_vm_vmx_api + */ +enum +{ + L4_VM_VMX_VMCS_CR2 = 0x6830, +}; + +/** + * \brief Return length in bytes of a VMCS field. + * \ingroup l4_vm_vmx_api + * + * \param field Field number. + * \return Width of field in bytes. + */ +L4_INLINE +unsigned +l4_vm_vmx_field_len(unsigned field); + +/** + * \brief Get pointer into VMCS. + * \ingroup l4_vm_vmx_api + * + * \param vmcs Pointer to VMCS buffer. + * \param field Field number. + * + * \param Pointer to field in the VMCS. + */ +L4_INLINE +void * +l4_vm_vmx_field_ptr(void *vmcs, unsigned field); + + +/* Implementations */ + +L4_INLINE +unsigned +l4_vm_vmx_field_len(unsigned field) +{ + static const char widths[4] = { 2, 8, 4, sizeof(l4_umword_t) }; + return widths[field >> 13]; +} + +L4_INLINE +void * +l4_vm_vmx_field_ptr(void *vmcs, unsigned field) +{ + return (void *)((char *)vmcs + + ((field >> 13) * 4 + ((field >> 10) & 3) + 1) * 0x80 + + l4_vm_vmx_field_len(field) * ((field >> 1) & 0xff)); +} diff --git a/l4/pkg/l4sys/include/__vm.h b/l4/pkg/l4sys/include/__vm.h new file mode 100644 index 00000000..7510070a --- /dev/null +++ b/l4/pkg/l4sys/include/__vm.h @@ -0,0 +1,27 @@ +/** + * \internal + * \file + * \brief X86 virtualization interface. + */ +/* + * (c) 2008-2010 Adam Lackorzynski , + * Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#pragma once + +#include +#include diff --git a/l4/pkg/l4sys/include/cache.h b/l4/pkg/l4sys/include/cache.h new file mode 100644 index 00000000..ba3eba82 --- /dev/null +++ b/l4/pkg/l4sys/include/cache.h @@ -0,0 +1,103 @@ +/** + * \file + * \brief Cache-consistency functions. + * + * \date 2007-11 + * \author Adam Lackorzynski + * + * \ingroup l4_api + * + */ +/* + * (c) 2007-2009 Author(s) + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ + +#ifndef __L4SYS__INCLUDE__CACHE_H__ +#define __L4SYS__INCLUDE__CACHE_H__ + +#include + +/** + * \defgroup l4_cache_api Cache Consistency + * \ingroup l4_api + * \brief Various functions for cache consistency. + * + * \#include + */ + +EXTERN_C_BEGIN + +/** + * \brief Cache clean a range in D-cache. + * \ingroup l4_cache_api + * \param start Start of range (inclusive) + * \param end End of range (exclusive) + */ +L4_INLINE void +l4_cache_clean_data(unsigned long start, + unsigned long end) L4_NOTHROW; + +/** + * \brief Cache flush a range. + * \ingroup l4_cache_api + * \param start Start of range (inclusive) + * \param end End of range (exclusive) + */ +L4_INLINE void +l4_cache_flush_data(unsigned long start, + unsigned long end) L4_NOTHROW; + +/** + * \brief Cache invalidate a range. + * \ingroup l4_cache_api + * \param start Start of range (inclusive) + * \param end End of range (exclusive) + */ +L4_INLINE void +l4_cache_inv_data(unsigned long start, + unsigned long end) L4_NOTHROW; + +/** + * \brief Make memory coherent between I-cache and D-cache. + * \ingroup l4_cache_api + * \param start Start of range (inclusive) + * \param end End of range (exclusive) + */ +L4_INLINE void +l4_cache_coherent(unsigned long start, + unsigned long end) L4_NOTHROW; + +/** + * \brief Make memory coherent for use with external memory. + * \ingroup l4_cache_api + * \param start Start of range (inclusive) + * \param end End of range (exclusive) + */ +L4_INLINE void +l4_cache_dma_coherent(unsigned long start, + unsigned long end) L4_NOTHROW; + +/** + * \brief Make memory coherent for use with external memory. + * \ingroup l4_cache_api + */ +L4_INLINE void +l4_cache_dma_coherent_full(void) L4_NOTHROW; + +EXTERN_C_END + +#endif /* ! __L4SYS__INCLUDE__CACHE_H__ */ diff --git a/l4/pkg/l4sys/include/capability b/l4/pkg/l4sys/include/capability new file mode 100644 index 00000000..071d1b78 --- /dev/null +++ b/l4/pkg/l4sys/include/capability @@ -0,0 +1,567 @@ +// vim:set ft=cpp: +/** + * \file + * \brief L4::Capability class. + * + * \author Alexander Warg + * + */ +/* + * (c) 2008-2009 Author(s) + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#pragma once + +#include +#include +#include +#include + +#include + +namespace L4 +{ + +/* Forward declarations for our kernel object classes. */ +class Task; +class Thread; +class Factory; +class Irq; +class Log; +class Vm; +class Kobject; + +template< typename T > class Cap; + +/** + * \addtogroup l4_cap_api + * + * C++ interface for capabilities:
+ * \#include + */ +/*@{*/ +/** + * \brief Base class for all kinds of capabilities. + * \attention This class is not for direct use, use L4::Cap instead. + * + * This class contains all the things that are independent of the type + * of the object referred by the capability. + * + * \see L4::Cap for typed capabilities. + */ +class Cap_base +{ +private: + struct Invalid_conversion; + +public: + enum No_init_type + { + /** + * \brief Special value for constructing uninitialized Cap objects. + */ + No_init + }; + + /** + * \brief Invalid capability type. + */ + enum Cap_type + { + Invalid = L4_INVALID_CAP ///< Invalid capability selector + }; + + /** + * \brief Return capability selector. + * \return Capability selector. + */ + l4_cap_idx_t cap() const throw() { return _c; } + + /** + * \brief Test whether capability selector is not the invalid capability + * selector. + * + * \return True if capability is not invalid, false if invalid + */ + bool is_valid() const throw() { return !(_c & L4_INVALID_CAP_BIT); } + + operator Invalid_conversion * () const throw() + { return (Invalid_conversion*)(!(_c & L4_INVALID_CAP_BIT)); } + + /** + * \brief Returns flex-page of the capability selector. + * \param rights Rights, defaults to 'rwx' + * \return flex-page + */ + l4_fpage_t fpage(unsigned rights = L4_FPAGE_RWX) const throw() + { return l4_obj_fpage(_c, 0, rights); } + + /** + * \brief Returns send base. + * \param grant True object should be granted. + * \param base Base capability selector + * \return Map object. + */ + l4_umword_t snd_base(unsigned grant = 0, + l4_cap_idx_t base = L4_INVALID_CAP) const throw() + { + if (base == L4_INVALID_CAP) + base = _c; + return l4_map_obj_control(base, grant); + } + + + /** + * \brief Test if two capability selectors are equal. + */ + bool operator == (Cap_base const &o) const throw() + { return _c == o._c; } + + /** + * \brief Test if two capability selectors are not equal. + */ + bool operator != (Cap_base const &o) const throw() + { return _c != o._c; } + + /** + * \brief Check whether a capability selector points to a valid capability. + * + * \param u UTCB of the caller + * \return label = 0 valid, label > 0 invalid + */ + inline l4_msgtag_t validate(l4_utcb_t *u = l4_utcb()) const throw(); + + /** + * \brief Check whether a capability selector points to a valid capability. + * + * \param u UTCB of the caller + * \param task Task to check the capability in + * + * \return label = 0 valid, label > 0 invalid + */ + inline l4_msgtag_t validate(Cap task, + l4_utcb_t *u = l4_utcb()) const throw(); + + /** + * \brief Set this selector to the invalid capability (L4_INVALID_CAP). + */ + void invalidate() throw() { _c = L4_INVALID_CAP; } +protected: + /** + * \brief Generate a capability from its C representation. + * \param c the C capability selector + */ + explicit Cap_base(l4_cap_idx_t c) throw() : _c(c) {} + /** + * \brief Constructor to create an invalid capability selector. + */ + explicit Cap_base(Cap_type cap) throw() : _c(cap) {} + + /** + * \brief Initialize capability with one of the default capability selectors. + * \param cap Capability selector. + */ + explicit Cap_base(l4_default_caps_t cap) throw() : _c(cap) {} + + /** + * \brief Create an uninitialized instance. + */ + explicit Cap_base() throw() {} + + /** + * \brief The C representation of a capability selector. */ + l4_cap_idx_t _c; +}; + + +/** + * \brief Capability Selector a la C++. + * \tparam T the type of the object the capability points to + * + * The C++ version of a capability looks just as a pointer, in fact + * it is a kind of a smart pointer for our kernel objects and the + * objects derived from the kernel objects (L4::Kobject). + */ +template< typename T > +class Cap : public Cap_base +{ +private: + friend class L4::Kobject; + + /** + * \internal + * \brief Internal Constructor, use to generate a capability from a \a this + * pointer. + * + * \attention This constructor is only useful to generate a capability + * from the \a this pointer of an objected that is an L4::Kobject. + * Do \em never use this constructor for something else! + * \param p The \a this pointer of the Kobject or derived object + */ + explicit Cap(T const *p) throw() + : Cap_base(reinterpret_cast(p)) {} + +public: + + /** + * \brief Create a copy from \a o, supporting implicit type casting. + * \param o is the source selector that shall be copied (and casted). + */ + template< typename O > + Cap(Cap const &o) throw() : Cap_base(o.cap()) + { register T* __t = ((O*)100); (void)__t; } + + /** + * \brief Constructor to create an invalid capability selector. + */ + Cap(Cap_type cap) throw() : Cap_base(cap) {} + + /** + * \brief Initialize capability with one of the default capability selectors. + * \param cap Capability selector. + */ + Cap(l4_default_caps_t cap) throw() : Cap_base(cap) {} + + /** + * \brief Initialize capability, defaults to the invalid capability selector. + * \param idx Capability selector. + */ + explicit Cap(l4_cap_idx_t idx = L4_INVALID_CAP) throw() : Cap_base(idx) {} + + /** + * \brief Create an uninitialized cap selector. + */ + explicit Cap(No_init_type) throw() {} + + /** + * \brief Move a capability to this cap slot. + * \param src the source capability slot. + * + * After this operation the source slot is no longer valid. + */ + Cap move(Cap const &src) const + { + if (!is_valid() || !src.is_valid()) + return *this; + + l4_task_map(L4_BASE_TASK_CAP, L4_BASE_TASK_CAP, src.fpage(L4_FPAGE_RWX), + snd_base(L4_MAP_ITEM_GRANT)); + + return *this; + } + + /** + * \brief Member access of a \a T. + */ + T *operator -> () const throw() { return reinterpret_cast(_c); } +}; + + +/** + * \internal + * \brief Specialization for \a void capabilities. + */ +template<> +class Cap : public Cap_base +{ +public: + + explicit Cap(void const *p) throw() + : Cap_base(reinterpret_cast(p)) {} + + /** + * \brief Constructor to create an invalid capability selector. + */ + Cap(Cap_type cap) throw() : Cap_base(cap) {} + + /** + * \brief Initialize capability with one of the default capability selectors. + * \param cap Capability selector. + */ + Cap(l4_default_caps_t cap) throw() : Cap_base(cap) {} + + /** + * \brief Initialize capability, defaults to the invalid capability selector. + * \param idx Capability selector. + */ + explicit Cap(l4_cap_idx_t idx = L4_INVALID_CAP) throw() : Cap_base(idx) {} + explicit Cap(No_init_type) throw() {} + + /** + * \brief Move a capability to this cap slot. + * \param src the source capability slot. + * + * After this operation the source slot is no longer valid. + */ + Cap move(Cap const &src) const + { + if (!is_valid() || !src.is_valid()) + return *this; + + l4_task_map(L4_BASE_TASK_CAP, L4_BASE_TASK_CAP, src.fpage(L4_FPAGE_RWX), + snd_base(L4_MAP_ITEM_GRANT)); + + return *this; + } + + template< typename T > + Cap(Cap const &o) throw() : Cap_base(o.cap()) {} +}; + +/** + * \brief static_cast for capabilities. + * \param T is the target type of the capability + * \param F is the source type (and is usually implicitly set) + * \param c is the source capability that shall be casted + * \return A capability typed to the interface \a T. + * + * The use of this cast operator is similar to the static_cast<>() for + * C++ pointers. It does the same type checking and adjustment like + * C++ does on pointers. + * + * Example code: + * \code + * L4::Cap obj = ... ; + * L4::Cap icu = L4::cap_cast(obj); + * \endcode + */ +template< typename T, typename F > +inline +Cap cap_cast(Cap const &c) throw() +{ + (void)static_cast(reinterpret_cast(100)); + return Cap(c.cap()); +} + +/** + * \brief reinterpret_cast for capabilities. + * \param T is the target type of the capability + * \param F is the source type (and is usually implicitly set) + * \param c is the source capability that shall be casted + * \return A capability typed to the interface \a T. + * + * The use of this cast operator is similar to the reinterpret_cast<>() for + * C++ pointers. It does not do any type checking or type adjustment. + * + * Example code: + * \code + * L4::Cap obj = ... ; + * L4::Cap icu = L4::cap_reinterpret_cast(obj); + * \endcode + */ +template< typename T, typename F > +inline +Cap cap_reinterpret_cast(Cap const &c) throw() +{ + return Cap(c.cap()); +} + +/*@}*/ + +/** + * \addtogroup l4_kernel_object_api + * + * \#include + */ +/*@{*/ +/** + * \brief Disable copy of a class. + * \param _class is the name of the class that shall not have + * value copy semantics. + * + * + * The typical use of this is: + * \code + * class Non_value + * { + * L4_DISABLE_COPY(Non_value) + * + * ... + * } + * \endcode + */ +#define L4_DISABLE_COPY(_class) \ + private: \ + _class(_class const &); \ + _class operator = (_class const &); + + +/** + * \brief Disable copy and instantiation of a class. + * \param _class is the name of the class to be not copyable and not + * instantiatable. + * + * The typical use looks like: + * \code + * class Type + * { + * L4_KOBJECT_DISABLE_COPY(Type) + * }; + * \endcode + */ +#define L4_KOBJECT_DISABLE_COPY(_class) \ + protected: \ + _class(); \ + L4_DISABLE_COPY(_class) + + +/** + * \brief Declare a kernel object class. + * \param _class is the class name. + * + * The use of this macro disables copy and instantiation + * of the class as needed for kernel object classes derived from + * L4::Kobject. + * + * The typical use looks like: + * \code + * class Type : public L4::Kobject_t + * { + * L4_KOBJECT(Type) + * }; + * \endcode + */ +#define L4_KOBJECT(_class) L4_KOBJECT_DISABLE_COPY(_class) + + +/** + * \ingroup l4_kernel_object_api + * \brief Base class for all kinds of kernel objects, referred to by + * capabilities. + * + * \#include + * + * \attention Objects derived from Kobject \em must never add any data to + * those objects. Kobjects can act only as proxy object + * for encapsulating object invocations. + */ +class Kobject +{ + L4_KOBJECT(Kobject) + +private: + + template + friend Type_info const *kobject_typeid(); + +protected: + /** + * \internal + * \brief Get a pointer to the L4Re dynamic type information + * for this class. + * + * \note This function is used by L4::kobject_typeid(). + */ + struct __Kobject_typeid { static Type_info const _m; }; + + /** + * \brief Return capability selector. + * \return Capability selector. + * + * This method is for derived classes to gain access to the actual + * capability selector. + */ + l4_cap_idx_t cap() const throw() { return _c(); } + +private: + + /** + * \internal + * \brief Used to convert the \c this pointer to a capability selector. + */ + l4_cap_idx_t _c() const throw() + { return reinterpret_cast(this) & L4_CAP_MASK; } + +public: + /** + * \brief Decrement the in kernel reference counter for the object. + * \param diff is the delta that shall be subtracted from the reference + * count. + * \param utcb is the utcb to use for the invocation. + * + * This function is intended for servers to be able to remove the servers + * own capability from the counted references. This leads to the semantics + * that the kernel will delete the object even if the capability of the + * server is valid. The server can detect the deletion by polling its + * capabilities or by using the IPC-gate deletion IRQs. And to cleanup + * if the clients dropped the last reference (capability) to the object. + */ + l4_msgtag_t dec_refcnt(l4_mword_t diff, l4_utcb_t *utcb = l4_utcb()) + { return l4_kobject_dec_refcnt_u(cap(), diff, utcb); } +}; + +/*@}*/ + +inline l4_msgtag_t +Cap_base::validate(Cap task, l4_utcb_t *u) const throw() +{ return l4_task_cap_valid_u(task.cap(), _c, u); } + +inline l4_msgtag_t +Cap_base::validate(l4_utcb_t *u) const throw() +{ return l4_task_cap_valid_u(L4_BASE_TASK_CAP, _c, u); } + +}; // namespace L4 + +#include + +namespace L4 { + +/** + * \addtogroup l4_cap_api + */ +/*@{*/ +/** + * \brief dynamic_cast for capabilities. + * \param T is the target type of the capability + * \param F is the source type (and is usually implicitly set) + * \param c is the source capability that shall be casted + * \return A capability typed to the interface \a T. If the object does not + * support the target interface \a T or does not support the + * L4::Meta interface the result is the invalid capability selector. + * + * The use of this cast operator is similar to the dynamic_cast<>() for + * C++ pointers. It also induces overhead, because it uses the meta interface + * (L4::Meta) to do runtime type checking. + * + * Example code: + * \code + * L4::Cap obj = ... ; + * L4::Cap icu = L4::cap_dynamic_cast(obj); + * \endcode + */ +template< typename T, typename F > +inline +Cap cap_dynamic_cast(Cap const &c) throw() +{ + if (!c.is_valid()) + return Cap::Invalid; + + Cap mc = cap_reinterpret_cast(c); + Type_info const *m = kobject_typeid(); + if (m->proto() && l4_error(mc->supports(m->proto())) > 0) + return Cap(c.cap()); + + // FIXME: use generic checker +#if 0 + if (l4_error(mc->supports(T::kobject_proto())) > 0) + return Cap(c.cap()); +#endif + + return Cap::Invalid; +} + +/*@}*/ +} diff --git a/l4/pkg/l4sys/include/compiler.h b/l4/pkg/l4sys/include/compiler.h new file mode 100644 index 00000000..ab76bc24 --- /dev/null +++ b/l4/pkg/l4sys/include/compiler.h @@ -0,0 +1,312 @@ +/*****************************************************************************/ +/** + * \file + * \brief L4 compiler related defines. + * \ingroup l4_api + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg , + * Frank Mehnert , + * Jork Löser , + * Ronald Aigner + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +/*****************************************************************************/ +#ifndef __L4_COMPILER_H__ +#define __L4_COMPILER_H__ + +#if !defined(__ASSEMBLY__) && !defined(__ASSEMBLER__) + +/** + * \addtogroup l4sys_defines + * + * \#include + */ +/*@{*/ + +/** + * L4 Inline function attribute. + * \hideinitializer + */ +#ifndef L4_INLINE +#ifndef __cplusplus +# ifdef __OPTIMIZE__ +# define L4_INLINE_STATIC static __inline__ +# define L4_INLINE_EXTERN extern __inline__ + /* gcc-4.3 implements c99 inline behaviour, i.e. we use the + * 'extern inline' there, 4.2 and below use 'static inline' */ +# if (__GNUC__ == 4 && __GNUC_MINOR__ <= 2) || __GNUC__ <= 3 +# define L4_INLINE L4_INLINE_STATIC +# else +# ifdef __GNUC_STDC_INLINE__ +# define L4_INLINE L4_INLINE_STATIC +# else +# define L4_INLINE L4_INLINE_EXTERN +# endif +# endif +# else /* ! __OPTIMIZE__ */ +# define L4_INLINE static +# endif /* ! __OPTIMIZE__ */ +#else /* __cplusplus */ +# define L4_INLINE inline +#endif /* __cplusplus */ +#endif /* L4_INLINE */ + +#if ((__GNUC__ * 100 + __GNUC_MINOR__) >= 405) +# define L4_DECLARE_CONSTRUCTOR(func, prio) \ + static inline __attribute__((constructor(prio))) void func ## _ctor_func(void) { func(); } +#else + + +/** + * \brief Handcoded version of __attribute__((constructor(xx))). + * \param func function declaration (prototype) + * \param prio the prio must be 65535 - \a gcc_prio + */ +#if defined (__ARM_EABI__) +# define L4_DECLARE_CONSTRUCTOR(func, prio) \ + static __typeof(&func) func ## _ctor__ __attribute__((used,section(".init_array." L4_stringify(prio)))) = &func; +#else +# define L4_DECLARE_CONSTRUCTOR(func, prio) \ + static __typeof(&func) func ## _ctor__ __attribute__((used,section(".ctors." L4_stringify(prio)))) = &func; +#endif +#endif + + + +/** + * Start section with C types and functions. + * \def __BEGIN_DECLS + * \hideinitializer + */ +/** + * End section with C types and functions. + * \def __END_DECLS + * \hideinitializer + */ +/** + * Start section with C types and functions. + * \def EXTERN_C_BEGIN + * \hideinitializer + */ +/** + * End section with C types and functions. + * \def EXTERN_C_END + * \hideinitializer + */ +/** + * Mark C types and functions. + * \def EXTERN_C + * \hideinitializer + */ + +/** + * \def L4_NOTHROW + * \hideinitializer + * \brief Mark a function declaration and definition as never + * throwing an exception. (Also for C code). + * + * This macro shall be used to mark C and C++ functions that never + * throw any exception. Note that also C functions may throw exceptions + * according to the compilers ABI and shall be marke with L4_NOTHROW + * if they never do. In C++ this is equvalent to \c throw(). + * + * \code + * int foo() L4_NOTHROW; + * ... + * int foo() L4_NOTHROW + * { + * ... + * return result; + * } + * \endcode + * + */ + +/** + * \def L4_EXPORT + * \hideinitializer + * \brief Attribute to mark functions, variables, and data types as being + * exported from a library. + * + * All data types, functions, and global variables that shall be exported + * from a library shall be marked with this attribute. The default may become + * to hide everything that is not marked as L4_EXPORT from the users of a + * library and provide the possibility for aggressive optimization of all + * those internal functionality of a library. + * + * Usage: + * \code + * class L4_EXPORT My_class + * { + * ... + * }; + * + * int L4_EXPORT function(void); + * + * int L4_EXPORT global_data; // global data is not recommended + * \endcode + * + */ + +/** + * \def L4_HIDDEN + * \hideinitializer + * \brief Attribute to mark functions, variables, and data types as being + * explicitly hidden from users of a library. + * + * This attribute is intended for functions, data, and data types that + * shall never be visible outside of a library. In particular, for shared + * libraries this may result in much faster code within the library and short + * linking times. + * + * \code + * class L4_HIDDEN My_class + * { + * ... + * }; + * + * int L4_HIDDEN function(void); + * + * int L4_HIDDEN global_data; // global data is not recommended + * \endcode + */ +#ifndef __cplusplus +# define L4_NOTHROW__A __attribute__((nothrow)) +# define L4_NOTHROW +# define EXTERN_C_BEGIN +# define EXTERN_C_END +# define EXTERN_C +# ifndef __BEGIN_DECLS +# define __BEGIN_DECLS +# endif +# ifndef __END_DECLS +# define __END_DECLS +# endif +# define L4_DEFAULT_PARAM(x) +#else /* __cplusplus */ +# define L4_NOTHROW throw() +# define EXTERN_C_BEGIN extern "C" { +# define EXTERN_C_END } +# define EXTERN_C extern "C" +# ifndef __BEGIN_DECLS +# define __BEGIN_DECLS extern "C" { +# endif +# ifndef __END_DECLS +# define __END_DECLS } +# endif +# define L4_DEFAULT_PARAM(x) = x +#endif /* __cplusplus */ + +/** + * Noreturn function attribute. + * \hideinitializer + */ +#define L4_NORETURN __attribute__((noreturn)) + +/** + * No instrumentation function attribute. + * \hideinitializer + */ +#define L4_NOINSTRUMENT __attribute__((no_instrument_function)) +#ifndef L4_HIDDEN +# define L4_HIDDEN __attribute__((visibility("hidden"))) +#endif +#ifndef L4_EXPORT +# define L4_EXPORT __attribute__((visibility("default"))) +#endif +#define L4_STRONG_ALIAS(name, aliasname) L4__STRONG_ALIAS(name, aliasname) +#define L4__STRONG_ALIAS(name, aliasname) \ + extern __typeof (name) aliasname __attribute__ ((alias (#name))); + + +#endif /* !__ASSEMBLY__ */ + +#include + +#if __GNUC__ == 2 && __GNUC_MINOR__ < 96 +#define __builtin_expect(x, expected_value) (x) +#endif + +#define EXPECT_TRUE(x) __builtin_expect((x),1) ///< Expression is likely to execute. \hideinitializer +#define EXPECT_FALSE(x) __builtin_expect((x),0) ///< Expression is unlikely to execute. \hideinitializer + +#if (__GNUC__ == 3 && __GNUC_MINOR__ >= 3) || __GNUC__ >= 4 +/* Make sure that the function is not removed by optimization. Without the + * "used" attribute, unreferenced static functions are removed. */ +#define L4_STICKY(x) __attribute__((used)) x ///< Mark symbol sticky (even not there) \hideinitializer +/* The deprecated attribute is available with 3.1 and higher (3.3 as here + * is ok for us */ +# if (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) || __GNUC__ >= 5 +# define L4_DEPRECATED(s) __attribute__((deprecated(s))) ///< Mark symbol deprecated. \hideinitializer +# else +# define L4_DEPRECATED(s) __attribute__((deprecated)) ///< Mark symbol deprecated. \hideinitializer +# endif +#else +/* The "used" attribute is not available with older gcc versions so simply + * make sure that gcc doesn't warn about unused functions. */ +#define L4_STICKY(x) __attribute__((unused)) x ///< Mark symbol sticky (even not there). +#define L4_DEPRECATED(s) ///< Mark symbol deprecated +#endif + +#ifndef __GXX_EXPERIMENTAL_CXX0X__ +#ifndef static_assert +#define static_assert(x, y) \ + do { (void)sizeof(char[-(!(x))]); } while (0) +#endif +#endif + +#define L4_stringify_helper(x) #x ///< stringify helper. \hideinitializer +#define L4_stringify(x) L4_stringify_helper(x) ///< stringify. \hideinitializer + +#ifndef __ASSEMBLER__ +/** + * \brief Memory barrier. + */ +L4_INLINE void l4_barrier(void); + +/** + * \brief Memory barrier. + */ +L4_INLINE void l4_mb(void); + +/** + * \brief Write memory barrier. + */ +L4_INLINE void l4_wmb(void); + + +/* Implementations */ +L4_INLINE void l4_barrier(void) +{ + __asm__ __volatile__ ("" : : : "memory"); +} + +L4_INLINE void l4_mb(void) +{ + __asm__ __volatile__ ("" : : : "memory"); +} + +L4_INLINE void l4_wmb(void) +{ + __asm__ __volatile__ ("" : : : "memory"); +} +#endif + +/*@}*/ + +#endif /* !__L4_COMPILER_H__ */ diff --git a/l4/pkg/l4sys/include/consts.h b/l4/pkg/l4sys/include/consts.h new file mode 100644 index 00000000..46bf7a75 --- /dev/null +++ b/l4/pkg/l4sys/include/consts.h @@ -0,0 +1,390 @@ +/** + * \file + * \brief Common constants. + * \ingroup l4_api + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg , + * Björn Döbel , + * Torsten Frenzel + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#ifndef __L4_SYS__INCLUDE__CONSTS_H__ +#define __L4_SYS__INCLUDE__CONSTS_H__ + +#include +#include + +/** + * \addtogroup l4_cap_api + * + * \#include + */ + +/** + * \brief Capability selector flags. + * \ingroup l4_ipc_api + * + * These flags determine the concrete operation when a kernel object + * is invoked. + */ +enum l4_syscall_flags_t +{ + /** + * \brief Default flags (call to a kernel object). + * \hideinitializer + * + * Using this value as flags in the capability selector for an + * invocation indicates a call (send and wait for a reply). + */ + L4_SYSF_NONE = 0x00, + + /** + * \brief Send-phase flag. + * \hideinitializer + * + * Setting this flag in a capability selector induces a send phase, + * this means a message is send to the object denoted by the capability. + * For receive phase see #L4_SYSF_RECV. + */ + L4_SYSF_SEND = 0x01, + + /** + * \brief Receive-phase flag. + * \hideinitializer + * + * Setting this flag in a capability selector induces a receive phase, + * this means the invoking thread waits for a message from the object + * denoted by the capability. + * For a send phase see #L4_SYSF_SEND. + */ + L4_SYSF_RECV = 0x02, + + /** + * \brief Open-wait flag. + * \hideinitializer + * + * This flag indicates that the receive operation (see #L4_SYSF_RECV) + * shall be an \em open \em wait. \em Open \em wait means that the invoking + * thread shall wait for a message from any possible sender and \em not from + * the sender denoted by the capability. + */ + L4_SYSF_OPEN_WAIT = 0x04, + + /** + * \brief Reply flag. + * \hideinitializer + * + * This flag indicates that the send phase shall use the in-kernel reply + * capability instead of the capability denoted by the selector index. + */ + L4_SYSF_REPLY = 0x08, + + /** + * \brief Call flags (combines send and receive). + * \hideinitializer + * + * Combines #L4_SYSF_SEND and L4_SYSF_RECV. + */ + L4_SYSF_CALL = L4_SYSF_SEND | L4_SYSF_RECV, + + /** + * \brief Wait flags (combines receive and open wait). + * \hideinitializer + * + * Combines #L4_SYSF_RECV and #L4_SYSF_OPEN_WAIT. + */ + L4_SYSF_WAIT = L4_SYSF_OPEN_WAIT | L4_SYSF_RECV, + + /** + * \brief Send-and-wait flags. + * \hideinitializer + * + * Combines #L4_SYSF_SEND and #L4_SYSF_WAIT. + */ + L4_SYSF_SEND_AND_WAIT = L4_SYSF_OPEN_WAIT | L4_SYSF_CALL, + + /** + * \brief Reply-and-wait flags. + * \hideinitializer + * + * Combines #L4_SYSF_SEND, #L4_SYSF_REPLY, and #L4_SYSF_WAIT. + */ + L4_SYSF_REPLY_AND_WAIT = L4_SYSF_WAIT | L4_SYSF_SEND | L4_SYSF_REPLY +}; + +/** + * \brief Constants related to capability selectors. + * \ingroup l4_cap_api + */ +enum l4_cap_consts_t +{ + /** \brief Capability index shift. \hideinitializer */ + L4_CAP_SHIFT = 12UL, + /** \brief Offset of two consecutive capability selectors. \hideinitializer */ + L4_CAP_SIZE = 1UL << L4_CAP_SHIFT, + L4_CAP_OFFSET = 1UL << L4_CAP_SHIFT, + /** + * \brief Mask to get only the relevant bits of an l4_cap_idx_t. + * \hideinitializer + */ + L4_CAP_MASK = ~0UL << (L4_CAP_SHIFT -1), + /** \brief Invalid capability selector. \hideinitializer */ + L4_INVALID_CAP = ~0UL << (L4_CAP_SHIFT -1), + + L4_INVALID_CAP_BIT = 1UL << (L4_CAP_SHIFT -1), +}; + +enum l4_sched_consts_t +{ + L4_SCHED_MIN_PRIO = 0, + L4_SCHED_MAX_PRIO = 255, +}; + +/** + * \brief Flags for the unmap operation. + * \ingroup l4_task_api + * \see L4::Task::unmap() and l4_task_unmap() + */ +enum l4_unmap_flags_t +{ + /** + * \brief Flag to tell the unmap operation to unmap all child mappings + * including the mapping in the invoked task. + * \hideinitializer + * \see L4::Task::unmap() l4_task_unmap() + */ + L4_FP_ALL_SPACES = 0x80000000UL, + + /** + * \brief Flag that indicates that the unmap operation on a capability + * shall try to delete the corresponding objects immediately. + * \hideinitializer + * \see L4::Task::unmap() l4_task_unmap() + */ + L4_FP_DELETE_OBJ = 0xc0000000UL, + + /** + * \brief Counterpart to #L4_FP_ALL_SPACES, unmap only child mappings. + * \hideinitializer + * \see L4::Task::unmap() l4_task_unmap() + */ + L4_FP_OTHER_SPACES = 0x0UL +}; + +/** + * \brief Constants for message items. + * \ingroup l4_msgitem_api + */ +enum l4_msg_item_consts_t +{ + L4_ITEM_MAP = 8, ///< Identify a message item as \em map \em item. + + /** + * \brief Donote that the following item shall be put into the same receive + * item as this one. + */ + L4_ITEM_CONT = 1, + + // send + L4_MAP_ITEM_GRANT = 2, ///< Flag as \em grant instead of \em map operation. + L4_MAP_ITEM_MAP = 0, ///< Flag as usual \em map operation. + + // receive + /** + * \brief Mark the receive buffer to be a small receive item that describes + * a buffer for a single capability. + */ + L4_RCV_ITEM_SINGLE_CAP = L4_ITEM_MAP | 2, + + /** + * \brief The receiver requests to receive a local ID instead of a mapping + * whenever possible. + */ + L4_RCV_ITEM_LOCAL_ID = 4, +}; + +/** + * \brief Constants for buffer descriptors. + * \ingroup l4_utcb_br_api + */ +enum l4_buffer_desc_consts_t +{ + L4_BDR_MEM_SHIFT = 0, ///< Bit offset for the memory-buffer index + L4_BDR_IO_SHIFT = 5, ///< Bit offset for the IO-buffer index + L4_BDR_OBJ_SHIFT = 10, ///< Bit offset for the capability-buffer index + L4_BDR_OFFSET_MASK = (1UL << 20) - 1, +}; + +/** + * \brief Default capabilities setup for the initial tasks. + * \ingroup l4_cap_api + * + * \#include + * + * These capability selectors are setup per default by the micro kernel + * for the two initial tasks, the Root-Pager (Sigma0) and the Root-Task + * (Moe). + * + * \attention This constants do not have any particular meaning for + * applications started by Moe, see \ref api_l4re_env for + * this kind of information. + * \see \ref api_l4re_env for information useful for normal user applications. + */ +enum l4_default_caps_t +{ + /// Capability selector for the current task. \hideinitializer + L4_BASE_TASK_CAP = 1UL << L4_CAP_SHIFT, + /// Capability selector for the factory. \hideinitializer + L4_BASE_FACTORY_CAP = 2UL << L4_CAP_SHIFT, + /// Capability selector for the first thread. \hideinitializer + L4_BASE_THREAD_CAP = 3UL << L4_CAP_SHIFT, + /// Capability selector for the pager gate. \hideinitializer + L4_BASE_PAGER_CAP = 4UL << L4_CAP_SHIFT, + /// Capability selector for the log object. \hideinitializer + L4_BASE_LOG_CAP = 5UL << L4_CAP_SHIFT, + /// Capability selector for the base icu object. \hideinitializer + L4_BASE_ICU_CAP = 6UL << L4_CAP_SHIFT, + /// Capability selector for the scheduler cap. \hideinitializer + L4_BASE_SCHEDULER_CAP = 7UL << L4_CAP_SHIFT, +}; + +/** + * \defgroup l4_memory_api Memory related + * \brief Memory related constants, data types and functions. + * \ingroup l4_api + */ +/** + * \brief Minimal page size (in bytes). + * \ingroup l4_memory_api + * \hideinitializer + */ +#define L4_PAGESIZE (1UL << L4_PAGESHIFT) + +/** + * \brief Mask for the page number. + * \ingroup l4_memory_api + * \hideinitializer + * + * \note The most significant bits are set. + */ +#define L4_PAGEMASK (~(L4_PAGESIZE - 1)) + +/** + * \brief Number of bits used for page offset. + * \ingroup l4_memory_api + * \hideinitializer + * + * Size of page in log2. + */ +#define L4_LOG2_PAGESIZE L4_PAGESHIFT + +/** + * \brief Size of a large page. + * \ingroup l4_memory_api + * \hideinitializer + * + * A large page is a \em super \em page on IA32 or a \em section on ARM. + */ +#define L4_SUPERPAGESIZE (1UL << L4_SUPERPAGESHIFT) + +/** + * \brief Mask for the number of a large page. + * \ingroup l4_memory_api + * \hideinitializer + * + * \note The most significant bits are set. + */ +#define L4_SUPERPAGEMASK (~(L4_SUPERPAGESIZE - 1)) + +/** + * \brief Number of bits used as offset for a large page. + * \ingroup l4_memory_api + * \hideinitializer + * Size of large page in log2 + */ +#define L4_LOG2_SUPERPAGESIZE L4_SUPERPAGESHIFT + +/** + * \brief Round an address down to the next lower page boundary. + * \ingroup l4_memory_api + * + * \param address The address to round. + */ +L4_INLINE l4_addr_t l4_trunc_page(l4_addr_t address) L4_NOTHROW; +L4_INLINE l4_addr_t l4_trunc_page(l4_addr_t x) L4_NOTHROW +{ return x & L4_PAGEMASK; } + +/** + * \brief Round an address down to the next lower flex page with size \a bits. + * \ingroup l4_memory_api + * + * \param address The address to round. + * \param bits The size of the flex page (log2). + */ +L4_INLINE l4_addr_t l4_trunc_size(l4_addr_t address, unsigned char bits) L4_NOTHROW; +L4_INLINE l4_addr_t l4_trunc_size(l4_addr_t x, unsigned char bits) L4_NOTHROW +{ return x & (~0UL << bits); } + +/** + * \brief Round address up to the next page. + * \ingroup l4_memory_api + * + * \param address The address to round up. + */ +L4_INLINE l4_addr_t l4_round_page(l4_addr_t address) L4_NOTHROW; +L4_INLINE l4_addr_t l4_round_page(l4_addr_t x) L4_NOTHROW +{ return (x + L4_PAGESIZE-1) & L4_PAGEMASK; } + +/** + * \brief Round address up to the next flex page with \a bits size. + * \ingroup l4_memory_api + * + * \param address The address to round up to the next flex page. + * \param bits The size of the flex page (log2). + */ +L4_INLINE l4_addr_t l4_round_size(l4_addr_t address, unsigned char bits) L4_NOTHROW; +L4_INLINE l4_addr_t l4_round_size(l4_addr_t x, unsigned char bits) L4_NOTHROW +{ return (x + (1UL << bits) - 1) & (~0UL << bits); } + +/** + * \brief Address related constants. + * \ingroup l4_memory_api + */ +enum l4_addr_consts_t { + /// Invalid address. + L4_INVALID_ADDR = ~0UL +}; + +/** + * \brief Invalid address as pointer type. + * \ingroup l4_memory_api + */ +#define L4_INVALID_PTR ((void*)L4_INVALID_ADDR) + +#ifndef NULL +#ifndef __cplusplus +# define NULL ((void *)0) /**< \ingroup l4sys_defines + ** \hideinitializer + ** NULL + **/ +#else +# define NULL 0 +#endif +#endif + +#endif /* ! __L4_SYS__INCLUDE__CONSTS_H__ */ diff --git a/l4/pkg/l4sys/include/debugger b/l4/pkg/l4sys/include/debugger new file mode 100644 index 00000000..b8078350 --- /dev/null +++ b/l4/pkg/l4sys/include/debugger @@ -0,0 +1,111 @@ +// vi:ft=cpp +/** + * \file + * \brief Debugger interface. + */ +/** + * \file + * \brief Common thread related definitions. + */ +/* + * (c) 2010-2011 Adam Lackorzynski , + * Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#pragma once + +#include + +namespace L4 { + +/** + * \ingroup l4_debugger_api + * \brief Debugger interface. + * + * \#include + */ +class Debugger : public Kobject_t +{ + L4_KOBJECT(Debugger) + +public: + enum + { + Switch_log_on = L4_DEBUGGER_SWITCH_LOG_ON, + Switch_log_off = L4_DEBUGGER_SWITCH_LOG_OFF, + }; + + /** + * \copydoc l4_debugger_set_object_name() + * \note the \a cap argument is the implicit \a this pointer. + */ + l4_msgtag_t set_object_name(const char *name, + l4_utcb_t *utcb = l4_utcb()) throw() + { return l4_debugger_set_object_name_u(cap(), name, utcb); } + + /** + * \copydoc l4_debugger_global_id() + * \note the \a cap argument is the implicit \a this pointer. + */ + unsigned long global_id(l4_utcb_t *utcb = l4_utcb()) throw() + { return l4_debugger_global_id_u(cap(), utcb); } + + /** + * \copydoc l4_debugger_kobj_to_id() + * \note the \a cap argument is the implicit \a this pointer. + */ + unsigned long kobj_to_id(l4_addr_t kobjp, + l4_utcb_t *utcb = l4_utcb()) throw() + { return l4_debugger_kobj_to_id_u(cap(), kobjp, utcb); } + + /** + * \copydoc l4_debugger_query_log_typeid() + * \note the \a cap argument is the implicit \a this pointer. + */ + int query_log_typeid(const char *name, unsigned idx, + l4_utcb_t *utcb = l4_utcb()) throw() + { return l4_debugger_query_log_typeid_u(cap(), name, idx, utcb); } + + /** + * \copydoc l4_debugger_query_log_name() + * \note the \a cap argument is the implicit \a this pointer. + */ + int query_log_name(unsigned idx, + char *name, unsigned namelen, + char *shortname, unsigned shortnamelen, + l4_utcb_t *utcb = l4_utcb()) throw() + { + return l4_debugger_query_log_name_u(cap(), idx, name, namelen, + shortname, shortnamelen, utcb); + } + + /** + * \copydoc l4_debugger_switch_log() + * \note the \a cap argument is the implicit \a this pointer. + */ + l4_msgtag_t switch_log(const char *name, unsigned on_off, + l4_utcb_t *utcb = l4_utcb()) throw() + { return l4_debugger_switch_log_u(cap(), name, on_off, utcb); } + + /** + * \copydoc l4_debugger_get_object_name() + * \note the \a cap argument is the implicit \a this pointer. + */ + l4_msgtag_t get_object_name(unsigned id, char *name, unsigned size, + l4_utcb_t *utcb = l4_utcb()) throw() + { return l4_debugger_get_object_name_u(cap(), id, name, size, utcb); } +}; +} diff --git a/l4/pkg/l4sys/include/debugger.h b/l4/pkg/l4sys/include/debugger.h new file mode 100644 index 00000000..c53499e5 --- /dev/null +++ b/l4/pkg/l4sys/include/debugger.h @@ -0,0 +1,336 @@ +#pragma once +/** + * \file + * \brief Debugger related definitions. + * \ingroup l4_api + */ +/* + * (c) 2008-2011 Adam Lackorzynski , + * Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ + +#include +#include +#include + +/** + * \defgroup l4_debugger_api Kernel Debugger + * \ingroup api_calls_fiasco + * \brief Kernel debugger related functionality. + * \attention This API is subject to change! + * + * This is a debugging factility, any call to any function might be invalid. + * Do not rely on it in any real code. + * + * \#include + */ + +/** + * The string name of kernel object. + * \ingroup l4_debugger_api + * + * \param cap Capability + * \param name Name + * + * This is a debugging factility, the call might be invalid. + */ +L4_INLINE l4_msgtag_t +l4_debugger_set_object_name(l4_cap_idx_t cap, const char *name) L4_NOTHROW; + +/** + * \internal + */ +L4_INLINE l4_msgtag_t +l4_debugger_set_object_name_u(l4_cap_idx_t cap, const char *name, l4_utcb_t *utcb) L4_NOTHROW; + +/** + * Get the globally unique ID of the object behind a capability. + * \ingroup l4_debugger_api + * + * \param cap Capability + * + * \return ~0UL on non-valid capability, ID otherwise + * + * This is a debugging factility, the call might be invalid. + */ +L4_INLINE unsigned long +l4_debugger_global_id(l4_cap_idx_t cap) L4_NOTHROW; + +/** + * \internal + */ +L4_INLINE unsigned long +l4_debugger_global_id_u(l4_cap_idx_t cap, l4_utcb_t *utcb) L4_NOTHROW; + +/** + * Get the globally unique ID of the object behind the kobject pointer. + * \ingroup l4_debugger_api + * + * \param cap Capability + * \param kobjp Kobject pointer + * + * \return ~0UL on non-valid capability or invalid kobject pointer, ID otherwise + * + * This is a debugging factility, the call might be invalid. + */ +L4_INLINE unsigned long +l4_debugger_kobj_to_id(l4_cap_idx_t cap, l4_addr_t kobjp) L4_NOTHROW; + +/** + * \internal + */ +L4_INLINE unsigned long +l4_debugger_kobj_to_id_u(l4_cap_idx_t cap, l4_addr_t kobjp, l4_utcb_t *utcb) L4_NOTHROW; + +/** + * \brief Query the log-id for a log type + * + * \param cap Debugger capability + * \param name Name to query for. + * \param idx Idx to start searching, start with 0 + * + * \return positive ID, or negative error code + * + * This is a debugging factility, the call might be invalid. + */ +L4_INLINE int +l4_debugger_query_log_typeid(l4_cap_idx_t cap, const char *name, + unsigned idx) L4_NOTHROW; + +/** + * \internal + */ +L4_INLINE int +l4_debugger_query_log_typeid_u(l4_cap_idx_t cap, const char *name, + unsigned idx, l4_utcb_t *utcb) L4_NOTHROW; + +/** + * \brief Query the name of a log type given the ID + * + * \param cap Debugger capability. + * \param idx ID to query. + * \param name Buffer to copy name to. + * \param namelen Buffer length of name. + * \param shortname Buffer to copy short-name to. + * \param shortnamelen Buffer length of short-name. + * + * \return 0 for success, ~0U in case of error + * + * This is a debugging factility, the call might be invalid. + */ +L4_INLINE int +l4_debugger_query_log_name(l4_cap_idx_t cap, unsigned idx, + char *name, unsigned namelen, + char *shortname, unsigned shortnamelen) L4_NOTHROW; + +/** + * \internal + */ +L4_INLINE int +l4_debugger_query_log_name_u(l4_cap_idx_t cap, unsigned idx, + char *name, unsigned namelen, + char *shortname, unsigned shortnamelen, + l4_utcb_t *utcb) L4_NOTHROW; + +/** + * \brief Set or unset log. + */ +L4_INLINE l4_msgtag_t +l4_debugger_switch_log(l4_cap_idx_t cap, const char *name, + int on_off) L4_NOTHROW; + +/** + * \internal + */ +L4_INLINE l4_msgtag_t +l4_debugger_switch_log_u(l4_cap_idx_t cap, const char *name, int on_off, + l4_utcb_t *utcb) L4_NOTHROW; + +enum +{ + L4_DEBUGGER_NAME_SET_OP = 0UL, + L4_DEBUGGER_GLOBAL_ID_OP = 1UL, + L4_DEBUGGER_KOBJ_TO_ID_OP = 2UL, + L4_DEBUGGER_QUERY_LOG_TYPEID_OP = 3UL, + L4_DEBUGGER_SWITCH_LOG_OP = 4UL, + L4_DEBUGGER_NAME_GET_OP = 5UL, + L4_DEBUGGER_QUERY_LOG_NAME_OP = 6UL, +}; + +enum +{ + L4_DEBUGGER_SWITCH_LOG_ON = 1, + L4_DEBUGGER_SWITCH_LOG_OFF = 0, +}; + +/* IMPLEMENTATION -----------------------------------------------------------*/ + +#include + +L4_INLINE l4_msgtag_t +l4_debugger_set_object_name_u(unsigned long cap, + const char *name, l4_utcb_t *utcb) L4_NOTHROW +{ + unsigned int i; + char *s = (char *)&l4_utcb_mr_u(utcb)->mr[1]; + l4_utcb_mr_u(utcb)->mr[0] = L4_DEBUGGER_NAME_SET_OP; + for (i = 0; + *name && i < (L4_UTCB_GENERIC_DATA_SIZE - 2) * sizeof(l4_umword_t) - 1; + ++i, ++name, ++s) + *s = *name; + *s = 0; + i = (i + sizeof(l4_umword_t) - 1) / sizeof(l4_umword_t); + return l4_invoke_debugger(cap, l4_msgtag(0, i, 0, 0), utcb); +} + +L4_INLINE unsigned long +l4_debugger_global_id_u(l4_cap_idx_t cap, l4_utcb_t *utcb) L4_NOTHROW +{ + l4_utcb_mr_u(utcb)->mr[0] = L4_DEBUGGER_GLOBAL_ID_OP; + if (l4_error_u(l4_invoke_debugger(cap, l4_msgtag(0, 1, 0, 0), utcb), utcb)) + return ~0UL; + return l4_utcb_mr_u(utcb)->mr[0]; +} + +L4_INLINE unsigned long +l4_debugger_kobj_to_id_u(l4_cap_idx_t cap, l4_addr_t kobjp, l4_utcb_t *utcb) L4_NOTHROW +{ + l4_utcb_mr_u(utcb)->mr[0] = L4_DEBUGGER_KOBJ_TO_ID_OP; + l4_utcb_mr_u(utcb)->mr[1] = kobjp; + if (l4_error_u(l4_invoke_debugger(cap, l4_msgtag(0, 2, 0, 0), utcb), utcb)) + return ~0UL; + return l4_utcb_mr_u(utcb)->mr[0]; +} + +L4_INLINE int +l4_debugger_query_log_typeid_u(l4_cap_idx_t cap, const char *name, + unsigned idx, + l4_utcb_t *utcb) L4_NOTHROW +{ + unsigned l; + int e; + l4_utcb_mr_u(utcb)->mr[0] = L4_DEBUGGER_QUERY_LOG_TYPEID_OP; + l4_utcb_mr_u(utcb)->mr[1] = idx; + l = __builtin_strlen(name); + l = l > 31 ? 31 : l; + __builtin_strncpy((char *)&l4_utcb_mr_u(utcb)->mr[2], name, 31); + l = (l + 1 + sizeof(l4_umword_t) - 1) / sizeof(l4_umword_t); + e = l4_error_u(l4_invoke_debugger(cap, l4_msgtag(0, 2 + l, 0, 0), utcb), utcb); + if (e < 0) + return e; + return l4_utcb_mr_u(utcb)->mr[0]; +} + +L4_INLINE int +l4_debugger_query_log_name_u(l4_cap_idx_t cap, unsigned idx, + char *name, unsigned namelen, + char *shortname, unsigned shortnamelen, + l4_utcb_t *utcb) L4_NOTHROW +{ + int e; + char *n; + l4_utcb_mr_u(utcb)->mr[0] = L4_DEBUGGER_QUERY_LOG_NAME_OP; + l4_utcb_mr_u(utcb)->mr[1] = idx; + e = l4_error_u(l4_invoke_debugger(cap, l4_msgtag(0, 2, 0, 0), utcb), utcb); + if (e < 0) + return e; + n = (char *)&l4_utcb_mr_u(utcb)->mr[0]; + __builtin_strncpy(name, n, namelen); + name[namelen - 1] = 0; + __builtin_strncpy(shortname, n + __builtin_strlen(n) + 1, shortnamelen); + shortname[shortnamelen - 1] = 0; + return 0; +} + + +L4_INLINE l4_msgtag_t +l4_debugger_switch_log_u(l4_cap_idx_t cap, const char *name, int on_off, + l4_utcb_t *utcb) L4_NOTHROW +{ + unsigned l; + l4_utcb_mr_u(utcb)->mr[0] = L4_DEBUGGER_SWITCH_LOG_OP; + l4_utcb_mr_u(utcb)->mr[1] = on_off; + l = __builtin_strlen(name); + l = l > 31 ? 31 : l; + __builtin_strncpy((char *)&l4_utcb_mr_u(utcb)->mr[2], name, 31); + l = (l + 1 + sizeof(l4_umword_t) - 1) / sizeof(l4_umword_t); + return l4_invoke_debugger(cap, l4_msgtag(0, 2 + l, 0, 0), utcb); +} + +L4_INLINE l4_msgtag_t +l4_debugger_get_object_name_u(l4_cap_idx_t cap, unsigned id, + char *name, unsigned size, + l4_utcb_t *utcb) L4_NOTHROW +{ + l4_msgtag_t t; + l4_utcb_mr_u(utcb)->mr[0] = L4_DEBUGGER_NAME_GET_OP; + l4_utcb_mr_u(utcb)->mr[1] = id; + t = l4_invoke_debugger(cap, l4_msgtag(0, 2, 0, 0), utcb); + __builtin_strncpy(name, (char *)&l4_utcb_mr_u(utcb)->mr[0], size); + name[size - 1] = 0; + return t; +} + + +L4_INLINE l4_msgtag_t +l4_debugger_set_object_name(unsigned long cap, + const char *name) L4_NOTHROW +{ + return l4_debugger_set_object_name_u(cap, name, l4_utcb()); +} + +L4_INLINE unsigned long +l4_debugger_global_id(l4_cap_idx_t cap) L4_NOTHROW +{ + return l4_debugger_global_id_u(cap, l4_utcb()); +} + +L4_INLINE unsigned long +l4_debugger_kobj_to_id(l4_cap_idx_t cap, l4_addr_t kobjp) L4_NOTHROW +{ + return l4_debugger_kobj_to_id_u(cap, kobjp, l4_utcb()); +} + +L4_INLINE int +l4_debugger_query_log_typeid(l4_cap_idx_t cap, const char *name, + unsigned idx) L4_NOTHROW +{ + return l4_debugger_query_log_typeid_u(cap, name, idx, l4_utcb()); +} + +L4_INLINE int +l4_debugger_query_log_name(l4_cap_idx_t cap, unsigned idx, + char *name, unsigned namelen, + char *shortname, unsigned shortnamelen) L4_NOTHROW +{ + return l4_debugger_query_log_name_u(cap, idx, name, namelen, + shortname, shortnamelen, l4_utcb()); +} + +L4_INLINE l4_msgtag_t +l4_debugger_switch_log(l4_cap_idx_t cap, const char *name, + int on_off) L4_NOTHROW +{ + return l4_debugger_switch_log_u(cap, name, on_off, l4_utcb()); +} + +L4_INLINE l4_msgtag_t +l4_debugger_get_object_name(l4_cap_idx_t cap, unsigned id, + char *name, unsigned size) L4_NOTHROW +{ + return l4_debugger_get_object_name_u(cap, id, name, size, l4_utcb()); +} diff --git a/l4/pkg/l4sys/include/err.h b/l4/pkg/l4sys/include/err.h new file mode 100644 index 00000000..11eac71e --- /dev/null +++ b/l4/pkg/l4sys/include/err.h @@ -0,0 +1,70 @@ +/** + * \file + * \brief Error codes. + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#pragma once + +#include + +/** + * \defgroup l4_error_api Error codes + * \brief Common error codes. + * \ingroup l4_api + * + * \#include + */ + +/** + * \brief L4 error codes. + * \ingroup l4_error_api + * + * Those error codes are used by both the kernel and the user programs. + */ +enum l4_error_code_t +{ + L4_EOK = 0, /**< \brief Ok. */ + L4_EPERM = 1, /**< \brief No permission. */ + L4_ENOENT = 2, /**< \brief No such entity. */ + L4_EIO = 5, /**< \brief I/O error. */ + L4_EAGAIN = 11, /**< \brief Try again. */ + L4_ENOMEM = 12, /**< \brief No memory. */ + L4_EACCESS = 13, /**< \brief Permission denied. */ + L4_EBUSY = 16, /**< \brief Object currently busy, try later. */ + L4_EEXIST = 17, /**< \brief Already exists. */ + L4_ENODEV = 19, /**< \brief No such thing. */ + L4_EINVAL = 22, /**< \brief Invalid argument. */ + L4_ERANGE = 34, /**< \brief Range error. */ + L4_ENAMETOOLONG = 36, /**< \brief Name too long. */ + L4_ENOSYS = 38, /**< \brief No sys. */ + L4_EBADPROTO = 39, /**< \brief Unsupported protocol. */ + L4_EADDRNOTAVAIL = 99, /**< \brief Address not available. */ + L4_ERRNOMAX = 100, /**< \brief Maximum error value. */ + + L4_ENOREPLY = 1000, /**< \brief No reply. */ + L4_EIPC_LO = 2000, /**< \brief Communication error-range low. */ + L4_EIPC_HI = 2000 + 0x1f, /**< \brief Communication error-range high. */ +}; + +__BEGIN_DECLS +L4_CV char const *l4sys_errtostr(long err) L4_NOTHROW; +__END_DECLS + + diff --git a/l4/pkg/l4sys/include/factory b/l4/pkg/l4sys/include/factory new file mode 100644 index 00000000..db28c7ca --- /dev/null +++ b/l4/pkg/l4sys/include/factory @@ -0,0 +1,270 @@ +// vi:ft=cpp +/** + * \file + * \brief Common factory related definitions. + * \ingroup l4_api + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ + +#pragma once + +#include +#include + +namespace L4 { + +/** + * \brief C++ L4 Factory, to create all kinds of kernel objects. + * \ingroup l4_factory_api + * + * \#include + * + * \see \ref l4_factory_api for an overview and C bindings. + */ +class Factory : public Kobject_t +{ + L4_KOBJECT(Factory) + +public: + + typedef l4_mword_t Proto; + + /** + * \brief Special type to add a void argument into the factory create + * stream. + */ + struct Nil {}; + + /** + * \brief Special type to add a pascal string into the factory create + * stream. + * + * This encapsulates a string that has an explicit length. + */ + struct Lstr + { + /** + * \brief The character buffer. + */ + char const *s; + + /** + * \brief The number of characters in the buffer. + */ + int len; + + Lstr(char const *s, int len) : s(s), len(len) {} + }; + + /** + * \brief Stream class for the create() argument stream. + * + * This stream allows a variable number of arguments to be + * added to a create() call. + */ + class S + { + private: + l4_utcb_t *u; + l4_msgtag_t t; + l4_cap_idx_t f; + + public: + /** + * \brief create a copy. + */ + S(S const &o) + : u(o.u), t(o.t), f(o.f) + { const_cast(o).t.raw = 0; } + + /** + * \brief create a stream for a specific create() call. + * \param f is the capability for the factory object (L4::Factory). + * \param obj is the protocol ID to describe the type of the object that + * shall be created. + * \param target is the capabilit selector for the new object. + * \param utcb is the UTCB that shall be used for the operation. + */ + S(l4_cap_idx_t f, long obj, L4::Cap target, + l4_utcb_t *utcb) throw() + : u(utcb), t(l4_factory_create_start_u(obj, target.cap(), u)), f(f) + {} + + /** + * \brief Commit the operation in the destructor to have a cool syntax + * for create(). + */ + ~S() + { + if (t.raw) + l4_factory_create_commit_u(f, t, u); + } + + /** + * \brief Explicitely commits the operation and returns the result. + * \return The result of the create() operation. + */ + operator l4_msgtag_t () + { + l4_msgtag_t r = l4_factory_create_commit_u(f, t, u); + t.raw = 0; + return r; + } + + /** + * \brief Put a single l4_mword_t as next argument. + * \param i is the value to add as next argument. + */ + S &operator << (l4_mword_t i) + { + l4_factory_create_add_int_u(i, &t, u); + return *this; + } + + /** + * \brief Put a single l4_umword_t as next argument. + * \param i is the value to add as next argument. + */ + S &operator << (l4_umword_t i) + { + l4_factory_create_add_uint_u(i, &t, u); + return *this; + } + + /** + * \brief Add a zero-terminated string as next argument. + * \param s is the string to add as next argument. + */ + S &operator << (char const *s) + { + l4_factory_create_add_str_u(s, &t, u); + return *this; + } + + /** + * \brief Add a pascal string as next argument. + * \param s is the string to add as next argument. + */ + S &operator << (Lstr const &s) + { + l4_factory_create_add_lstr_u(s.s, s.len, &t, u); + return *this; + } + + /** + * \brief Add an empty argument. + */ + S &operator << (Nil) + { + l4_factory_create_add_nil_u(&t, u); + return *this; + } + + /** + * \brief Add a flex page as next argument. + * \param d is the flex page to add (there will be no map operation). + */ + S &operator << (l4_fpage_t d) + { + l4_factory_create_add_fpage_u(d, &t, u); + return *this; + } + }; + + +public: + + /** + * \brief Generic create call to the factory. + * \param target is the target capability selector where the new + * object shall be received. + * \param obj is the protocol ID that specifies which kind of object + * shall be created. + * \param utcb is the UTCB to use for the operation. + * \return a create stream that allows adding additional arguments to the + * create() call. + * + * This method does currently not directly invoke the factory. It returns a + * stream that shall invoke the factory after adding all additional arguments. + * + * Usage: + * \code + * L4::Cap ns = L4Re::Util::cap_alloc.alloc(); + * factory->create(ns, L4Re::Namespace::Protocol) << "Argument text"; + * \endcode + */ + S create(Cap target, long obj, l4_utcb_t *utcb = l4_utcb()) throw() + { + return S(cap(), obj, target, utcb); + } + + /** + * \copydoc l4_factory_create_task() + * \note \a factory is the implicit \a this pointer. + */ + l4_msgtag_t create_task(Cap const & target_cap, + l4_fpage_t const &utcb_area, + l4_utcb_t *utcb = l4_utcb()) throw() + { return l4_factory_create_task_u(cap(), target_cap.cap(), utcb_area, utcb); } + + /** + * \copydoc l4_factory_create_thread() + * \note \a factory is the implicit \a this pointer. + */ + l4_msgtag_t create_thread(Cap const &target_cap, + l4_utcb_t *utcb = l4_utcb()) throw() + { return l4_factory_create_thread_u(cap(), target_cap.cap(), utcb); } + + /** + * \copydoc l4_factory_create_factory() + * \note \a factory is the implicit \a this pointer. + */ + l4_msgtag_t create_factory(Cap const &target_cap, + unsigned long limit, + l4_utcb_t *utcb = l4_utcb()) throw() + { return l4_factory_create_factory_u(cap(), target_cap.cap(), limit, utcb); } + + /** + * \copydoc l4_factory_create_gate() + * \note \a factory is the implicit \a this pointer. + */ + l4_msgtag_t create_gate(Cap const &target_cap, + Cap const &thread_cap, l4_umword_t label, + l4_utcb_t *utcb = l4_utcb()) throw() + { return l4_factory_create_gate_u(cap(), target_cap.cap(), thread_cap.cap(), label, utcb); } + + /** + * \copydoc l4_factory_create_irq() + * \note \a factory is the implicit \a this pointer. + */ + l4_msgtag_t create_irq(Capconst &target_cap, + l4_utcb_t *utcb = l4_utcb()) throw() + { return l4_factory_create_irq_u(cap(), target_cap.cap(), utcb); } + + /** + * \copydoc l4_factory_create_vm() + * \note \a factory is the implicit \a this pointer. + */ + l4_msgtag_t create_vm(Capconst &target_cap, + l4_utcb_t *utcb = l4_utcb()) throw() + { return l4_factory_create_vm_u(cap(), target_cap.cap(), utcb); } +}; + +} diff --git a/l4/pkg/l4sys/include/factory.h b/l4/pkg/l4sys/include/factory.h new file mode 100644 index 00000000..b3d23fa9 --- /dev/null +++ b/l4/pkg/l4sys/include/factory.h @@ -0,0 +1,455 @@ +/** + * \file + * \brief Common factory related definitions. + * \ingroup l4_api + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg , + * Björn Döbel , + * Torsten Frenzel , + * Henning Schild + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#pragma once + +#include +#include +#include + +/** + * \defgroup l4_factory_api Factory + * \ingroup l4_kernel_object_api + * \brief A factory is used to create all kinds of kernel objects. + * + * \#include + * + * A factory provides the means to create all kinds of kernel objects. + * The factory is equipped with a limit that limits the amount of kernel + * memory available for that factory. + * \note The limit does not give any guarantee for the amount of available + * kernel memory. + */ + +/** + * \defgroup l4_vm_api Virtual Machines + * \ingroup l4_kernel_object_api + * \brief Virtual Machine API + */ + +/** + * \brief Create a new task. + * \ingroup l4_factory_api + * + * \param factory Capability selector for factory to use for creation. + * \param target_cap Capability selector for the root capability of the new + * task. + * \param utcb_area Flexpage that describes the area for the UTCBs of the new task + * + * \note The size of the UTCB area specifies indirectly the maximum number of UTCBs + * available for this task and cannot be changed afterwards. + * + * \return Syscall return tag + * \see \ref l4_task_api + */ +L4_INLINE l4_msgtag_t +l4_factory_create_task(l4_cap_idx_t factory, + l4_cap_idx_t target_cap, l4_fpage_t const utcb_area) L4_NOTHROW; + +/** + * \internal + */ +L4_INLINE l4_msgtag_t +l4_factory_create_task_u(l4_cap_idx_t factory, l4_cap_idx_t target_cap, + l4_fpage_t const utcb_area, l4_utcb_t *utcb) L4_NOTHROW; + +/** + * \brief Create a new thread. + * \ingroup l4_factory_api + * + * \param factory Capability selector for factory to use for creation. + * \param target_cap Capability selector for the root capability of the + * new thread. + * + * \return Syscall return tag + * \see \ref l4_thread_api + */ +L4_INLINE l4_msgtag_t +l4_factory_create_thread(l4_cap_idx_t factory, + l4_cap_idx_t target_cap) L4_NOTHROW; + +/** + * \internal + */ +L4_INLINE l4_msgtag_t +l4_factory_create_thread_u(l4_cap_idx_t factory, + l4_cap_idx_t target_cap, l4_utcb_t *utcb) L4_NOTHROW; + +/** + * \brief Create a new factory. + * \ingroup l4_factory_api + * + * \param factory Capability selector for factory to use for creation. + * \param target_cap Capability selector for the root capability of the + * new factory. + * \param limit Limit for the new factory in bytes + * + * \note The limit of the new factory is subtracted from the available amount + * of the factory used for creation. + * + * \return Syscall return tag + */ +L4_INLINE l4_msgtag_t +l4_factory_create_factory(l4_cap_idx_t factory, l4_cap_idx_t target_cap, + unsigned long limit) L4_NOTHROW; + +/** + * \internal + */ +L4_INLINE l4_msgtag_t +l4_factory_create_factory_u(l4_cap_idx_t factory, l4_cap_idx_t target_cap, + unsigned long limit, l4_utcb_t *utcb) L4_NOTHROW; + +/** + * \brief Create a new IPC gate. + * \ingroup l4_factory_api + * + * \param factory Capability selector for factory to use for creation. + * \param target_cap Capability selector for the root capability of the + * new IPC gate. + * \param thread_cap Thread to bind the gate to + * \param label Label of the gate + * + * \return Syscall return tag + * \see \ref l4_kernel_object_gate_api + */ +L4_INLINE l4_msgtag_t +l4_factory_create_gate(l4_cap_idx_t factory, + l4_cap_idx_t target_cap, + l4_cap_idx_t thread_cap, l4_umword_t label) L4_NOTHROW; + +/** + * \internal + */ +L4_INLINE l4_msgtag_t +l4_factory_create_gate_u(l4_cap_idx_t factory, + l4_cap_idx_t target_cap, + l4_cap_idx_t thread_cap, l4_umword_t label, + l4_utcb_t *utcb) L4_NOTHROW; + +/** + * \brief Create a new IRQ. + * \ingroup l4_factory_api + * + * \param factory Capability selector for factory to use for creation. + * \param target_cap Capability selector for the root capability of the + * new IRQ. + * + * \return Syscall return tag + * \see \ref l4_irq_api + */ +L4_INLINE l4_msgtag_t +l4_factory_create_irq(l4_cap_idx_t factory, + l4_cap_idx_t target_cap) L4_NOTHROW; + +/** + * \internal + */ +L4_INLINE l4_msgtag_t +l4_factory_create_irq_u(l4_cap_idx_t factory, + l4_cap_idx_t target_cap, l4_utcb_t *utcb) L4_NOTHROW; + +/** + * \brief Create a new virtual machine. + * \ingroup l4_factory_api + * + * \param factory Capability selector for factory to use for creation. + * \param target_cap Capability selector for the root capability of the + * new VM. + * + * \return Syscall return tag + * \see \ref l4_vm_api + */ +L4_INLINE l4_msgtag_t +l4_factory_create_vm(l4_cap_idx_t factory, + l4_cap_idx_t target_cap) L4_NOTHROW; +/** + * \internal + */ +L4_INLINE l4_msgtag_t +l4_factory_create_vm_u(l4_cap_idx_t factory, + l4_cap_idx_t target_cap, l4_utcb_t *utcb) L4_NOTHROW; + +L4_INLINE l4_msgtag_t +l4_factory_create_start_u(long obj, l4_cap_idx_t target, + l4_utcb_t *utcb) L4_NOTHROW; + +L4_INLINE int +l4_factory_create_add_fpage_u(l4_fpage_t d, l4_msgtag_t *tag, + l4_utcb_t *utcb) L4_NOTHROW; + +L4_INLINE int +l4_factory_create_add_int_u(l4_mword_t d, l4_msgtag_t *tag, + l4_utcb_t *utcb) L4_NOTHROW; + +L4_INLINE int +l4_factory_create_add_uint_u(l4_umword_t d, l4_msgtag_t *tag, + l4_utcb_t *utcb) L4_NOTHROW; + +L4_INLINE int +l4_factory_create_add_str_u(char const *s, l4_msgtag_t *tag, + l4_utcb_t *utcb) L4_NOTHROW; + +L4_INLINE int +l4_factory_create_add_lstr_u(char const *s, int len, l4_msgtag_t *tag, + l4_utcb_t *utcb) L4_NOTHROW; + +L4_INLINE int +l4_factory_create_add_nil_u(l4_msgtag_t *tag, l4_utcb_t *utcb) L4_NOTHROW; + +L4_INLINE l4_msgtag_t +l4_factory_create_commit_u(l4_cap_idx_t factory, l4_msgtag_t tag, + l4_utcb_t *utcb) L4_NOTHROW; + + +/* IMPLEMENTATION -----------------------------------------------------------*/ + +#include + +L4_INLINE l4_msgtag_t +l4_factory_create_task_u(l4_cap_idx_t factory, + l4_cap_idx_t target_cap, l4_fpage_t utcb_area, + l4_utcb_t *u) L4_NOTHROW +{ + l4_msgtag_t t; + t = l4_factory_create_start_u(L4_PROTO_TASK, target_cap, u); + l4_factory_create_add_fpage_u(utcb_area, &t, u); + return l4_factory_create_commit_u(factory, t, u); +} + +L4_INLINE l4_msgtag_t +l4_factory_create_thread_u(l4_cap_idx_t factory, + l4_cap_idx_t target_cap, l4_utcb_t *u) L4_NOTHROW +{ + l4_msgtag_t t = l4_factory_create_start_u(L4_PROTO_THREAD, target_cap, u); + return l4_factory_create_commit_u(factory, t, u); +} + +L4_INLINE l4_msgtag_t +l4_factory_create_factory_u(l4_cap_idx_t factory, + l4_cap_idx_t target_cap, unsigned long limit, + l4_utcb_t *u) L4_NOTHROW +{ + l4_msgtag_t t; + t = l4_factory_create_start_u(L4_PROTO_FACTORY, target_cap, u); + l4_factory_create_add_uint_u(limit, &t, u); + return l4_factory_create_commit_u(factory, t, u); +} + +L4_INLINE l4_msgtag_t +l4_factory_create_gate_u(l4_cap_idx_t factory, + l4_cap_idx_t target_cap, + l4_cap_idx_t thread_cap, l4_umword_t label, + l4_utcb_t *u) L4_NOTHROW +{ + l4_msgtag_t t; + l4_msg_regs_t *v; + int items = 0; + t = l4_factory_create_start_u(0, target_cap, u); + l4_factory_create_add_uint_u(label, &t, u); + v = l4_utcb_mr_u(u); + if (!(thread_cap & L4_INVALID_CAP_BIT)) + { + items = 1; + v->mr[3] = l4_map_obj_control(0,0); + v->mr[4] = l4_obj_fpage(thread_cap, 0, L4_FPAGE_RWX).raw; + } + t = l4_msgtag(l4_msgtag_label(t), l4_msgtag_words(t), items, l4_msgtag_flags(t)); + return l4_factory_create_commit_u(factory, t, u); +} + +L4_INLINE l4_msgtag_t +l4_factory_create_irq_u(l4_cap_idx_t factory, + l4_cap_idx_t target_cap, l4_utcb_t *u) L4_NOTHROW +{ + l4_msgtag_t t = l4_factory_create_start_u(L4_PROTO_IRQ, target_cap, u); + return l4_factory_create_commit_u(factory, t, u); +} + +L4_INLINE l4_msgtag_t +l4_factory_create_vm_u(l4_cap_idx_t factory, + l4_cap_idx_t target_cap, + l4_utcb_t *u) L4_NOTHROW +{ + l4_msgtag_t t = l4_factory_create_start_u(L4_PROTO_VM, target_cap, u); + return l4_factory_create_commit_u(factory, t, u); +} + + + + + +L4_INLINE l4_msgtag_t +l4_factory_create_task(l4_cap_idx_t factory, + l4_cap_idx_t target_cap, l4_fpage_t const utcb_area) L4_NOTHROW +{ + return l4_factory_create_task_u(factory, target_cap, utcb_area, l4_utcb()); +} + +L4_INLINE l4_msgtag_t +l4_factory_create_thread(l4_cap_idx_t factory, + l4_cap_idx_t target_cap) L4_NOTHROW +{ + return l4_factory_create_thread_u(factory, target_cap, l4_utcb()); +} + +L4_INLINE l4_msgtag_t +l4_factory_create_factory(l4_cap_idx_t factory, + l4_cap_idx_t target_cap, unsigned long limit) L4_NOTHROW + +{ + return l4_factory_create_factory_u(factory, target_cap, limit, l4_utcb()); +} + +L4_INLINE l4_msgtag_t +l4_factory_create_gate(l4_cap_idx_t factory, + l4_cap_idx_t target_cap, + l4_cap_idx_t thread_cap, l4_umword_t label) L4_NOTHROW +{ + return l4_factory_create_gate_u(factory, target_cap, thread_cap, label, l4_utcb()); +} + +L4_INLINE l4_msgtag_t +l4_factory_create_irq(l4_cap_idx_t factory, + l4_cap_idx_t target_cap) L4_NOTHROW +{ + return l4_factory_create_irq_u(factory, target_cap, l4_utcb()); +} + +L4_INLINE l4_msgtag_t +l4_factory_create_vm(l4_cap_idx_t factory, + l4_cap_idx_t target_cap) L4_NOTHROW +{ + return l4_factory_create_vm_u(factory, target_cap, l4_utcb()); +} + +L4_INLINE l4_msgtag_t +l4_factory_create_start_u(long obj, l4_cap_idx_t target_cap, + l4_utcb_t *u) L4_NOTHROW +{ + l4_msg_regs_t *v = l4_utcb_mr_u(u); + l4_buf_regs_t *b = l4_utcb_br_u(u); + v->mr[0] = obj; + b->bdr = 0; + b->br[0] = target_cap | L4_RCV_ITEM_SINGLE_CAP; + return l4_msgtag(L4_PROTO_FACTORY, 1, 0, 0); +} + +L4_INLINE int +l4_factory_create_add_fpage_u(l4_fpage_t d, l4_msgtag_t *tag, + l4_utcb_t *u) L4_NOTHROW +{ + l4_msg_regs_t *v = l4_utcb_mr_u(u); + int w = l4_msgtag_words(*tag); + if (w + 2 > L4_UTCB_GENERIC_DATA_SIZE) + return 0; + v->mr[w] = L4_VARG_TYPE_FPAGE | (sizeof(l4_fpage_t) << 16); + v->mr[w + 1] = d.raw; + w += 2; + tag->raw = (tag->raw & ~0x3fUL) | (w & 0x3f); + return 1; +} + +L4_INLINE int +l4_factory_create_add_int_u(l4_mword_t d, l4_msgtag_t *tag, + l4_utcb_t *u) L4_NOTHROW +{ + l4_msg_regs_t *v = l4_utcb_mr_u(u); + int w = l4_msgtag_words(*tag); + if (w + 2 > L4_UTCB_GENERIC_DATA_SIZE) + return 0; + v->mr[w] = L4_VARG_TYPE_MWORD | (sizeof(l4_mword_t) << 16); + v->mr[w + 1] = d; + w += 2; + tag->raw = (tag->raw & ~0x3fUL) | (w & 0x3f); + return 1; +} + +L4_INLINE int +l4_factory_create_add_uint_u(l4_umword_t d, l4_msgtag_t *tag, + l4_utcb_t *u) L4_NOTHROW +{ + l4_msg_regs_t *v = l4_utcb_mr_u(u); + int w = l4_msgtag_words(*tag); + if (w + 2 > L4_UTCB_GENERIC_DATA_SIZE) + return 0; + v->mr[w] = L4_VARG_TYPE_UMWORD | (sizeof(l4_umword_t) << 16); + v->mr[w + 1] = d; + w += 2; + tag->raw = (tag->raw & ~0x3fUL) | (w & 0x3f); + return 1; +} + +L4_INLINE int +l4_factory_create_add_str_u(char const *s, l4_msgtag_t *tag, + l4_utcb_t *u) L4_NOTHROW +{ + return l4_factory_create_add_lstr_u(s, __builtin_strlen(s), tag, u); +} + +L4_INLINE int +l4_factory_create_add_lstr_u(char const *s, int len, l4_msgtag_t *tag, + l4_utcb_t *u) L4_NOTHROW +{ + + l4_msg_regs_t *v = l4_utcb_mr_u(u); + int w = l4_msgtag_words(*tag); + char *c; + int i; + + if (w + 1 + (len + sizeof(l4_umword_t) - 1) / sizeof(l4_umword_t) + > L4_UTCB_GENERIC_DATA_SIZE) + return 0; + + v->mr[w] = L4_VARG_TYPE_STRING | (len << 16); + c = (char*)&v->mr[w + 1]; + for (i = 0; i < len; ++i) + *c++ = *s++; + + w = w + 1 + (len + sizeof(l4_umword_t) - 1) / sizeof(l4_umword_t); + + tag->raw = (tag->raw & ~0x3fUL) | (w & 0x3f); + return 1; +} + +L4_INLINE int +l4_factory_create_add_nil_u(l4_msgtag_t *tag, l4_utcb_t *utcb) L4_NOTHROW +{ + l4_msg_regs_t *v = l4_utcb_mr_u(utcb); + int w = l4_msgtag_words(*tag); + v->mr[w] = L4_VARG_TYPE_NIL; + ++w; + tag->raw = (tag->raw & ~0x3fUL) | (w & 0x3f); + return 1; +} + + +L4_INLINE l4_msgtag_t +l4_factory_create_commit_u(l4_cap_idx_t factory, l4_msgtag_t tag, + l4_utcb_t *u) L4_NOTHROW +{ + return l4_ipc_call(factory, u, tag, L4_IPC_NEVER); +} diff --git a/l4/pkg/l4sys/include/icu b/l4/pkg/l4sys/include/icu new file mode 100644 index 00000000..718cfc7c --- /dev/null +++ b/l4/pkg/l4sys/include/icu @@ -0,0 +1,26 @@ +// vi:ft=cpp +/** + * \file + * \brief Interrupt controller. + * \ingroup l4_api + */ +/* + * (c) 2008-2009 Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#pragma once + +#include diff --git a/l4/pkg/l4sys/include/icu.h b/l4/pkg/l4sys/include/icu.h new file mode 100644 index 00000000..221d91b4 --- /dev/null +++ b/l4/pkg/l4sys/include/icu.h @@ -0,0 +1,447 @@ +/** + * \file + * \brief Interrupt controller. + * \ingroup l4_api + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg , + * Torsten Frenzel + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#pragma once + +#include +#include + +/** + * \defgroup l4_icu_api Interrupt controller + * \ingroup l4_kernel_object_api + * + * \brief The ICU class. + * + * \#include + */ + + +/** + * \brief Flags for IRQ numbers used for the ICU. + * \ingroup l4_icu_api + */ +enum L4_icu_flags +{ + /** + * \brief Flag to denote that the IRQ is actually an MSI. + * \hideinitializer + * + * This flag may be used for l4_icu_bind() and l4_icu_unbind() functions to + * denote that the IRQ number is meant to be an MSI. + */ + L4_ICU_FLAG_MSI = 0x80000000, +}; + + +/** + * \brief Interrupt flow types. + * \ingroup l4_irq_api + */ +enum L4_irq_flow_type +{ + L4_IRQ_F_NONE = 0, /**< None */ + L4_IRQ_F_LEVEL = 0x2, /**< Level triggered */ + L4_IRQ_F_EDGE = 0x0, /**< Edge triggered */ + L4_IRQ_F_POS = 0x0, /**< Positive trigger */ + L4_IRQ_F_NEG = 0x4, /**< Negative trigger */ + L4_IRQ_F_BOTH = 0x8, /**< Both edges trigger */ + L4_IRQ_F_LEVEL_HIGH = 0x3, /**< Level high trigger */ + L4_IRQ_F_LEVEL_LOW = 0x7, /**< Level low trigger */ + L4_IRQ_F_POS_EDGE = 0x1, /**< Positive edge trigger */ + L4_IRQ_F_NEG_EDGE = 0x5, /**< Negative edge trigger */ + L4_IRQ_F_BOTH_EDGE = 0x9, /**< Both edges trigger */ + L4_IRQ_F_MASK = 0xf, /**< Mask */ +}; + + +/** + * \brief Opcodes to the ICU interface. + * \ingroup l4_api_icu + */ +enum L4_icu_opcode +{ + /** + * \brief Bind opcode. + * \hideinitializer + * \see l4_icu_bind() + */ + L4_ICU_OP_BIND = 0, + + /** + * \brief Unbind opcode. + * \hideinitializer + * \see l4_icu_unbind() + */ + L4_ICU_OP_UNBIND = 1, + + /** + * \brief Info opcode. + * \hideinitializer + * \see l4_icu_info() + */ + L4_ICU_OP_INFO = 2, + + /** + * \brief Msi-info opcode. + * \hideinitializer + * \see l4_icu_msi_info() + */ + L4_ICU_OP_MSI_INFO = 3, + + /** + * \brief Unmask opcode. + * \hideinitializer + * \see l4_icu_unmask() + */ + L4_ICU_OP_UNMASK = 4, + + /** + * \brief Mask opcode. + * \hideinitializer + * \see l4_icu_mask() + */ + L4_ICU_OP_MASK = 5, + + /** + * \brief Set-mode opcode. + * \hideinitializer + * \see l4_icu_set_mode() + */ + L4_ICU_OP_SET_MODE = 6, +}; + +enum L4_icu_ctl_op +{ + L4_ICU_CTL_UNMASK = 0, + L4_ICU_CTL_MASK = 1 +}; + + +/** + * \brief Info structure for an ICU. + * \ingroup l4_icu_api + * + * This structure contains information about the features of an ICU. + * \see l4_icu_info(). + */ +typedef struct l4_icu_info_t +{ + /** + * \brief Feature flags. + * + * If #L4_ICU_FLAG_MSI is set the ICU supports MSIs. + */ + unsigned features; + + /** + * \brief The number of IRQ lines supported by the ICU, + */ + unsigned nr_irqs; + + /** + * \brief The number of MSI vectors supported by the ICU, + */ + unsigned nr_msis; +} l4_icu_info_t; + +/** + * \brief Bind an interrupt vector of an interrupt controller to an interrupt object. + * \ingroup l4_icu_api + * + * \param icu ICU to use. + * \param irqnum IRQ vector at the ICU. + * \param irq IRQ capability to bind the IRQ to. + * \return Syscall return tag + */ +L4_INLINE l4_msgtag_t +l4_icu_bind(l4_cap_idx_t icu, unsigned irqnum, l4_cap_idx_t irq) L4_NOTHROW; + +/** + * \internal + */ +L4_INLINE l4_msgtag_t +l4_icu_bind_u(l4_cap_idx_t icu, unsigned irqnum, l4_cap_idx_t irq, + l4_utcb_t *utcb) L4_NOTHROW; + +/** + * \brief Remove binding of an interrupt vector from the interrupt controller object. + * \ingroup l4_icu_api + * + * \param icu ICU to use. + * \param irqnum IRQ vector at the ICU. + * \param irq IRQ object to remove from the ICU. + * \return Syscall return tag + */ +L4_INLINE l4_msgtag_t +l4_icu_unbind(l4_cap_idx_t icu, unsigned irqnum, l4_cap_idx_t irq) L4_NOTHROW; + +/** + * \internal + */ +L4_INLINE l4_msgtag_t +l4_icu_unbind_u(l4_cap_idx_t icu, unsigned irqnum, l4_cap_idx_t irq, + l4_utcb_t *utcb) L4_NOTHROW; + +/** + * \brief Set mode of interrupt. + * \ingroup l4_icu_api + * + * \param icu ICU to use. + * \param irqnum IRQ vector at the ICU. + * \param mode Mode, see L4_irq_flow_type. + * \return Syscall return tag + * + * \ingroup l4_icu_api + */ +L4_INLINE l4_msgtag_t +l4_icu_set_mode(l4_cap_idx_t icu, unsigned irqnum, l4_umword_t mode) L4_NOTHROW; + +/** + * \internal + */ +L4_INLINE l4_msgtag_t +l4_icu_set_mode_u(l4_cap_idx_t icu, unsigned irqnum, l4_umword_t mode, + l4_utcb_t *utcb) L4_NOTHROW; + +/** + * \brief Get info about capabilites of ICU. + * \ingroup l4_icu_api + * + * \param icu ICU to use. + * \param info Pointer to an info structure to be filled with information. + * \return Syscall return tag + */ +L4_INLINE l4_msgtag_t +l4_icu_info(l4_cap_idx_t icu, l4_icu_info_t *info) L4_NOTHROW; + +/** + * \internal + */ +L4_INLINE l4_msgtag_t +l4_icu_info_u(l4_cap_idx_t icu, l4_icu_info_t *info, + l4_utcb_t *utcb) L4_NOTHROW; + +/** + * \brief Get MSI info about IRQ. + * \ingroup l4_icu_api + * + * \param icu ICU to use. + * \param irqnum IRQ vector at the ICU. + * \param msg Pointer to a word to receive the message that must be used + * for the PCI devices MSI message. + * \return Syscall return tag + */ +L4_INLINE l4_msgtag_t +l4_icu_msi_info(l4_cap_idx_t icu, unsigned irqnum, l4_umword_t *msg) L4_NOTHROW; + +/** + * \internal + */ +L4_INLINE l4_msgtag_t +l4_icu_msi_info_u(l4_cap_idx_t icu, unsigned irqnum, l4_umword_t *msg, + l4_utcb_t *utcb) L4_NOTHROW; + + +/** + * \brief Unmask an IRQ vector. + * \ingroup l4_icu_api + * + * \param icu ICU to use. + * \param irqnum IRQ vector at the ICU. + * \param label If non-NULL the function also waits for the next message. + * \param to Timeout for message to ICU, if unsure use L4_IPC_NEVER. + * \return Syscall return tag + */ +L4_INLINE l4_msgtag_t +l4_icu_unmask(l4_cap_idx_t icu, unsigned irqnum, l4_umword_t *label, + l4_timeout_t to) L4_NOTHROW; + +/** + * \internal + */ +L4_INLINE l4_msgtag_t +l4_icu_unmask_u(l4_cap_idx_t icu, unsigned irqnum, l4_umword_t *label, + l4_timeout_t to, l4_utcb_t *utcb) L4_NOTHROW; + +/** + * \brief Mask an IRQ vector. + * \ingroup l4_icu_api + * + * \param icu ICU to use. + * \param irqnum IRQ vector at the ICU. + * \param label If non-NULL the function also waits for the next message. + * \param to Timeout for message to ICU, if unsure use L4_IPC_NEVER. + * \return Syscall return tag + */ +L4_INLINE l4_msgtag_t +l4_icu_mask(l4_cap_idx_t icu, unsigned irqnum, l4_umword_t *label, + l4_timeout_t to) L4_NOTHROW; + +/** + * \internal + */ +L4_INLINE l4_msgtag_t +l4_icu_mask_u(l4_cap_idx_t icu, unsigned irqnum, l4_umword_t *label, + l4_timeout_t to, l4_utcb_t *utcb) L4_NOTHROW; + +/** + * \internal + */ +L4_INLINE l4_msgtag_t +l4_icu_control_u(l4_cap_idx_t icu, unsigned irqnum, unsigned op, + l4_umword_t *label,l4_timeout_t to, + l4_utcb_t *utcb) L4_NOTHROW; + + +/************************************************************************** + * Implementations + */ + +L4_INLINE l4_msgtag_t +l4_icu_bind_u(l4_cap_idx_t icu, unsigned irqnum, l4_cap_idx_t irq, + l4_utcb_t *utcb) L4_NOTHROW +{ + l4_msg_regs_t *m = l4_utcb_mr_u(utcb); + m->mr[0] = L4_ICU_OP_BIND; + m->mr[1] = irqnum; + m->mr[2] = l4_map_obj_control(0, 0); + m->mr[3] = l4_obj_fpage(irq, 0, L4_FPAGE_RWX).raw; + return l4_ipc_call(icu, utcb, l4_msgtag(L4_PROTO_IRQ, 2, 1, 0), L4_IPC_NEVER); +} + +L4_INLINE l4_msgtag_t +l4_icu_unbind_u(l4_cap_idx_t icu, unsigned irqnum, l4_cap_idx_t irq, + l4_utcb_t *utcb) L4_NOTHROW +{ + l4_msg_regs_t *m = l4_utcb_mr_u(utcb); + m->mr[0] = L4_ICU_OP_UNBIND; + m->mr[1] = irqnum; + m->mr[2] = l4_map_obj_control(0, 0); + m->mr[3] = l4_obj_fpage(irq, 0, L4_FPAGE_RWX).raw; + return l4_ipc_call(icu, utcb, l4_msgtag(L4_PROTO_IRQ, 2, 1, 0), L4_IPC_NEVER); +} + +L4_INLINE l4_msgtag_t +l4_icu_info_u(l4_cap_idx_t icu, l4_icu_info_t *info, + l4_utcb_t *utcb) L4_NOTHROW +{ + l4_msgtag_t res; + l4_msg_regs_t *m = l4_utcb_mr_u(utcb); + m->mr[0] = L4_ICU_OP_INFO; + res = l4_ipc_call(icu, utcb, l4_msgtag(L4_PROTO_IRQ, 1, 0, 0), L4_IPC_NEVER); + if (!l4_msgtag_has_error(res) && l4_msgtag_label(res) >= 0 + && l4_msgtag_words(res) >= 3) + { + info->features = m->mr[0]; + info->nr_irqs = m->mr[1]; + info->nr_msis = m->mr[2]; + } + return res; +} + +L4_INLINE l4_msgtag_t +l4_icu_msi_info_u(l4_cap_idx_t icu, unsigned irqnum, l4_umword_t *msg, + l4_utcb_t *utcb) L4_NOTHROW +{ + l4_msgtag_t res; + l4_msg_regs_t *m = l4_utcb_mr_u(utcb); + m->mr[0] = L4_ICU_OP_MSI_INFO; + m->mr[1] = irqnum; + res = l4_ipc_call(icu, utcb, l4_msgtag(L4_PROTO_IRQ, 2, 0, 0), L4_IPC_NEVER); + if (!l4_msgtag_has_error(res) && l4_msgtag_label(res) >= 0 + && l4_msgtag_words(res) >= 1) + *msg = m->mr[0]; + return res; +} + +L4_INLINE l4_msgtag_t +l4_icu_set_mode_u(l4_cap_idx_t icu, unsigned irqnum, l4_umword_t mode, + l4_utcb_t *utcb) L4_NOTHROW +{ + l4_msg_regs_t *mr = l4_utcb_mr_u(utcb); + mr->mr[0] = L4_ICU_OP_SET_MODE; + mr->mr[1] = irqnum; + mr->mr[2] = mode; + return l4_ipc_call(icu, utcb, l4_msgtag(L4_PROTO_IRQ, 3, 0, 0), L4_IPC_NEVER); +} + +L4_INLINE l4_msgtag_t +l4_icu_control_u(l4_cap_idx_t icu, unsigned irqnum, unsigned op, + l4_umword_t *label, l4_timeout_t to, + l4_utcb_t *utcb) L4_NOTHROW +{ + l4_msg_regs_t *m = l4_utcb_mr_u(utcb); + m->mr[0] = L4_ICU_OP_UNMASK + op; + m->mr[1] = irqnum; + if (label) + return l4_ipc_send_and_wait(icu, utcb, l4_msgtag(L4_PROTO_IRQ, 2, 0, 0), + label, to); + else + return l4_ipc_send(icu, utcb, l4_msgtag(L4_PROTO_IRQ, 2, 0, 0), to); +} + +L4_INLINE l4_msgtag_t +l4_icu_mask_u(l4_cap_idx_t icu, unsigned irqnum, l4_umword_t *label, + l4_timeout_t to, l4_utcb_t *utcb) L4_NOTHROW +{ return l4_icu_control_u(icu, irqnum, L4_ICU_CTL_MASK, label, to, utcb); } + +L4_INLINE l4_msgtag_t +l4_icu_unmask_u(l4_cap_idx_t icu, unsigned irqnum, l4_umword_t *label, + l4_timeout_t to, l4_utcb_t *utcb) L4_NOTHROW +{ return l4_icu_control_u(icu, irqnum, L4_ICU_CTL_UNMASK, label, to, utcb); } + + + + +L4_INLINE l4_msgtag_t +l4_icu_bind(l4_cap_idx_t icu, unsigned irqnum, l4_cap_idx_t irq) L4_NOTHROW +{ return l4_icu_bind_u(icu, irqnum, irq, l4_utcb()); } + +L4_INLINE l4_msgtag_t +l4_icu_unbind(l4_cap_idx_t icu, unsigned irqnum, l4_cap_idx_t irq) L4_NOTHROW +{ return l4_icu_unbind_u(icu, irqnum, irq, l4_utcb()); } + +L4_INLINE l4_msgtag_t +l4_icu_info(l4_cap_idx_t icu, l4_icu_info_t *info) L4_NOTHROW +{ return l4_icu_info_u(icu, info, l4_utcb()); } + +L4_INLINE l4_msgtag_t +l4_icu_msi_info(l4_cap_idx_t icu, unsigned irqnum, l4_umword_t *msg) L4_NOTHROW +{ return l4_icu_msi_info_u(icu, irqnum, msg, l4_utcb()); } + +L4_INLINE l4_msgtag_t +l4_icu_unmask(l4_cap_idx_t icu, unsigned irqnum, l4_umword_t *label, + l4_timeout_t to) L4_NOTHROW +{ return l4_icu_control_u(icu, irqnum, L4_ICU_CTL_UNMASK, label, to, l4_utcb()); } + +L4_INLINE l4_msgtag_t +l4_icu_mask(l4_cap_idx_t icu, unsigned irqnum, l4_umword_t *label, + l4_timeout_t to) L4_NOTHROW +{ return l4_icu_control_u(icu, irqnum, L4_ICU_CTL_MASK, label, to, l4_utcb()); } + +L4_INLINE l4_msgtag_t +l4_icu_set_mode(l4_cap_idx_t icu, unsigned irqnum, l4_umword_t mode) L4_NOTHROW +{ + return l4_icu_set_mode_u(icu, irqnum, mode, l4_utcb()); +} diff --git a/l4/pkg/l4sys/include/ipc.h b/l4/pkg/l4sys/include/ipc.h new file mode 100644 index 00000000..a8bed1bb --- /dev/null +++ b/l4/pkg/l4sys/include/ipc.h @@ -0,0 +1,493 @@ +/** + * \file + * \brief Common IPC interface. + * \ingroup l4_api + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg , + * Björn Döbel , + * Torsten Frenzel + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#ifndef __L4SYS__INCLUDE__L4API_FIASCO__IPC_H__ +#define __L4SYS__INCLUDE__L4API_FIASCO__IPC_H__ + +#include +#include +#include + +/** + * \defgroup l4_ipc_api Object Invocation + * \ingroup l4_api + * \brief API for L4 object invocation. + * + * \#include + * + * General abstractions for L4 object invocation. The basic principle is that + * all objects are denoted by a capability that is accessed via a capability + * selector (see \link l4_cap_api Capabilities \endlink). + * + * This set of functions is common to all kinds of objects provided by the + * L4 micro kernel. The concrete semantics of an invocation depends on the + * object that shall be invoked. + * + * Objects may be invoked in various ways, the most common way is to use + * a \em call operation (l4_ipc_call()). However, there are a lot more + * flavours available that have a semantics depending on the object. + * + * \see \ref l4_kernel_object_gate_api + * + */ + +/***************************************************************************** + *** IPC result checking + *****************************************************************************/ + +/** + * \defgroup l4_ipc_err_api Error Handling + * \ingroup l4_ipc_api + * \brief Error handling for L4 object invocation. + * + * \#include + */ + +/** + * \brief Error codes in the \em error TCR. + * \ingroup l4_ipc_err_api + * + * The error codes are accessible via the \em error TCR, see + * #l4_thread_regs_t.error. + */ +enum l4_ipc_tcr_error_t +{ + L4_IPC_ERROR_MASK = 0x1F, /**< Mask for error bits. */ + L4_IPC_SND_ERR_MASK = 0x01, /**< Send error mask. */ + + L4_IPC_ENOT_EXISTENT = 0x04, /**< Non-existing destination or source. + ** \ingroup l4_ipc_api + **/ + L4_IPC_RETIMEOUT = 0x03, /**< Timeout during receive operation. + ** \ingroup l4_ipc_api + **/ + L4_IPC_SETIMEOUT = 0x02, /**< Timeout during send operation. + ** \ingroup l4_ipc_api + **/ + L4_IPC_RECANCELED = 0x07, /**< Receive operation canceled. + ** \ingroup l4_ipc_api + **/ + L4_IPC_SECANCELED = 0x06, /**< Send operation canceled. + ** \ingroup l4_ipc_api + **/ + L4_IPC_REMAPFAILED = 0x11, /**< Map flexpage failed in receive + ** operation. + ** \ingroup l4_ipc_api + **/ + L4_IPC_SEMAPFAILED = 0x10, /**< Map flexpage failed in send operation. + ** \ingroup l4_ipc_api + **/ + L4_IPC_RESNDPFTO = 0x0b, /**< Send-pagefault timeout in receive + ** operation. + ** \ingroup l4_ipc_api + **/ + L4_IPC_SESNDPFTO = 0x0a, /**< Send-pagefault timeout in send + ** operation. + ** \ingroup l4_ipc_api + **/ + L4_IPC_RERCVPFTO = 0x0d, /**< Receive-pagefault timeout in receive + ** operation. + ** \ingroup l4_ipc_api + **/ + L4_IPC_SERCVPFTO = 0x0c, /**< Receive-pagefault timeout in send + ** operation. + ** \ingroup l4_ipc_api + **/ + L4_IPC_REABORTED = 0x0f, /**< Receive operation aborted. + ** \ingroup l4_ipc_api + **/ + L4_IPC_SEABORTED = 0x0e, /**< Send operation aborted. + ** \ingroup l4_ipc_api + **/ + L4_IPC_REMSGCUT = 0x09, /**< Cut receive message, due to + ** message buffer is too small. + ** \ingroup l4_ipc_api + **/ + L4_IPC_SEMSGCUT = 0x08, /**< Cut send message. due to + ** message buffer is too small, + ** \ingroup l4_ipc_api + **/ +}; + + +/** + * \brief Get the error code for an object invocation. + * \ingroup l4_ipc_err_api + * + * \param tag Return value of the invocation. + * \param utcb UTCB that was used for the invocation. + * + * \return 0 if no error condition is set, + * error code otherwise (see #l4_ipc_tcr_error_t). + */ +L4_INLINE l4_umword_t +l4_ipc_error(l4_msgtag_t tag, l4_utcb_t *utcb) L4_NOTHROW; + + +/** + * \brief Return error code of a system call return message tag. + * \ingroup l4_ipc_err_api + * \param tag System call return message type + * \return 0 for no error, error number in case of error + */ +L4_INLINE long +l4_error(l4_msgtag_t tag) L4_NOTHROW; + +L4_INLINE long +l4_error_u(l4_msgtag_t tag, l4_utcb_t *utcb) L4_NOTHROW; + +/***************************************************************************** + *** IPC results + *****************************************************************************/ + +/** + * \brief Returns whether an error occurred in send phase of an invocation. + * \ingroup l4_ipc_err_api + * + * \pre l4_msgtag_has_error(tag) == true + * \param utcb UTCB to check. + * + * \return Boolean value. + */ +L4_INLINE int l4_ipc_is_snd_error(l4_utcb_t *utcb) L4_NOTHROW; + +/** + * \brief Returns whether an error occurred in receive phase of an invocation. + * \ingroup l4_ipc_err_api + * + * \pre l4_msgtag_has_error(tag) == true + * \param utcb UTCB to check. + * + * \return Boolean value. + */ +L4_INLINE int l4_ipc_is_rcv_error(l4_utcb_t *utcb) L4_NOTHROW; + +/** + * \brief Get the error condition of the last invocation from the TCR. + * \ingroup l4_ipc_err_api + * + * \pre l4_msgtag_has_error(tag) == true + * \param utcb UTCB to check. + * + * \return Error condition of type l4_ipc_tcr_error_t. + */ +L4_INLINE int l4_ipc_error_code(l4_utcb_t *utcb) L4_NOTHROW; + + +/***************************************************************************** + *** IPC calls + *****************************************************************************/ + +/** + * \brief Send a message to an object (do \b not wait for a reply). + * \ingroup l4_ipc_api + * + * \param dest Capability selector for the destination object. + * \param utcb UTCB of the caller. + * \param tag Descriptor for the message to be sent. + * \param timeout Timeout pair (see #l4_timeout_t) only send part is relevant. + * + * \return result tag + * + * A message is sent to the destination object. There is no receive phase + * included. The invoker continues working after sending the message. + * + * \attention This is a special-purpose message transfer, objects usually + * support only invocation via l4_ipc_call(). + */ +L4_INLINE l4_msgtag_t +l4_ipc_send(l4_cap_idx_t dest, l4_utcb_t *utcb, l4_msgtag_t tag, + l4_timeout_t timeout) L4_NOTHROW; + + +/** + * \brief Wait for an incoming message from any possible sender. + * \ingroup l4_ipc_api + * + * \param utcb UTCB of the caller. + * \retval label Label assigned to the source object (IPC gate or IRQ). + * \param timeout Timeout pair (see #l4_timeout_t, only the receive part is + * used). + * + * \return return tag + * + * This operation does an open wait, and therefore needs no capability to + * denote the possible source of a message. This means the calling thread + * waits for an incoming message from any possible source. + * There is no send phase included in this operation. + * + * The usual usage of this function is to call that function when entering a + * server loop in a user-level server that implements user-level objects, + * see also #l4_ipc_reply_and_wait(). + */ +L4_INLINE l4_msgtag_t +l4_ipc_wait(l4_utcb_t *utcb, l4_umword_t *label, + l4_timeout_t timeout) L4_NOTHROW; + + +/** + * \brief Wait for a message from a specific source. + * \ingroup l4_ipc_api + * + * \param object Object to receive a message from. + * \param timeout Timeout pair (see #l4_timeout_t, only the receive part + * matters). + * \param utcb UTCB of the caller. + * + * \return result tag. + * + * This operation waits for a message from the specified object. Messages from + * other sources are not accepted by this operation. The operation does not + * include a send phase, this means no message is sent to the object. + * + * \note This operation is usually used to receive messages from a specific IRQ + * or thread. However, it is not common to use this operation for normal + * applications. + */ +L4_INLINE l4_msgtag_t +l4_ipc_receive(l4_cap_idx_t object, l4_utcb_t *utcb, + l4_timeout_t timeout) L4_NOTHROW; + +/** + * \brief Object call (usual invocation). + * \ingroup l4_ipc_api + * + * \param object Capability selector for the object to call. + * \param utcb UTCB of the caller. + * \param tag Message tag to describe the message to be sent. + * \param timeout Timeout pair for send an receive phase (see #l4_timeout_t). + * + * \return result tag + * + * A message is sent to the object and the invoker waits for a + * reply from the object. Messages from other sources are not accepted. + * \note The send-to-receive transition needs no time, the object can reply + * with a send timeout of zero. + */ +L4_INLINE l4_msgtag_t +l4_ipc_call(l4_cap_idx_t object, l4_utcb_t *utcb, l4_msgtag_t tag, + l4_timeout_t timeout) L4_NOTHROW; + + +/** + * \brief Reply and wait operation (uses the \em reply capability). + * \ingroup l4_ipc_api + * + * \param tag Describes the message to be sent as reply. + * \param utcb UTCB of the caller. + * \retval label Label assigned to the source object of the received message. + * \param timeout Timeout pair (see #l4_timeout_t). + * \return result tag + * + * A message is sent to the previous caller using the implicit reply + * capability. Afterwards the invoking thread waits for a message from any + * source. + * \note This is the standard server operation: it sends a reply to the actual + * client and waits for the next incoming request, which may come from + * any other client. + */ +L4_INLINE l4_msgtag_t +l4_ipc_reply_and_wait(l4_utcb_t *utcb, l4_msgtag_t tag, + l4_umword_t *label, l4_timeout_t timeout) L4_NOTHROW; + +/** + * \brief Send a message and do an open wait. + * \ingroup l4_ipc_api + * + * \param dest Object to send a message to. + * \param utcb UTCB of the caller. + * \param tag Describes the message that shall be sent. + * \retval label Label assigned to the source object of the receive phase. + * \param timeout Timeout pair (see #l4_timeout_t). + * \return result tag + * + * A message is sent to the destination object and the invoking thread waits + * for a reply from any source. + * + * \note This is a special-purpose operation and shall not be used in general + * applications. + */ +L4_INLINE l4_msgtag_t +l4_ipc_send_and_wait(l4_cap_idx_t dest, l4_utcb_t *utcb, l4_msgtag_t tag, + l4_umword_t *label, l4_timeout_t timeout) L4_NOTHROW; + +/** + * \defgroup l4_ipc_rt_api Realtime API + * \ingroup l4_ipc_api + * \internal + */ + +#if 0 +/** + * Wait for next period. + * \ingroup l4_ipc_rt_api + * + * \param utcb UTCB of the caller. + * \param label Label + * \param timeout IPC timeout (see #l4_ipc_timeout). + * + * \return result tag + */ +L4_INLINE l4_msgtag_t +l4_ipc_wait_next_period(l4_utcb_t *utcb, + l4_umword_t *label, + l4_timeout_t timeout); + +#endif + +/** + * \brief Generic L4 object invocation. + * \ingroup l4_ipc_api + * + * \param dest Destination object. + * \param utcb UTCB of the caller. + * \param flags Invocation flags (see #l4_syscall_flags_t). + * \param slabel Send label if applicable (may be seen by the receiver). + * \param tag Sending message tag. + * \retval rlabel Receiving label. + * \param timeout Timeout pair (see #l4_timeout_t). + * + * \return return tag + */ +L4_INLINE l4_msgtag_t +l4_ipc(l4_cap_idx_t dest, + l4_utcb_t *utcb, + l4_umword_t flags, + l4_umword_t slabel, + l4_msgtag_t tag, + l4_umword_t *rlabel, + l4_timeout_t timeout) L4_NOTHROW; + +/** + * \brief Sleep for an amount of time. + * \ingroup l4_ipc_api + * + * \param timeout Timeout pair (see #l4_timeout_t, the receive part matters). + * + * \return error code: + * - #L4_IPC_RETIMEOUT: success + * - #L4_IPC_RECANCELED woken up by a different thread + * (l4_thread_ex_regs()). + * + * The invoking thread waits until the timeout + * is expired or the wait was aborted by another thread by l4_thread_ex_regs(). + */ +L4_INLINE l4_msgtag_t +l4_ipc_sleep(l4_timeout_t timeout) L4_NOTHROW; + +/** + * \brief Add a flex-page to be sent to the UTCB + * \ingroup l4_ipc_api + * + * \param snd_fpage Flex-page. + * \param snd_base Send base. + * \param tag Tag to be modified. + * \retval tag Modified tag, the number of items will be increased, + * all other values in the tag will be retained. + * + * \return 0 on success, negative error code otherwise + */ +L4_INLINE int +l4_sndfpage_add(l4_fpage_t const snd_fpage, unsigned long snd_base, + l4_msgtag_t *tag) L4_NOTHROW; + +/* + * \internal + * \ingroup l4_ipc_api + */ +L4_INLINE int +l4_sndfpage_add_u(l4_fpage_t const snd_fpage, unsigned long snd_base, + l4_msgtag_t *tag, l4_utcb_t *utcb) L4_NOTHROW; + + +/************************************************************************ + * Implementations + **********************/ + +L4_INLINE l4_umword_t +l4_ipc_error(l4_msgtag_t tag, l4_utcb_t *utcb) L4_NOTHROW +{ + if (!l4_msgtag_has_error(tag)) + return 0; + return l4_utcb_tcr_u(utcb)->error & L4_IPC_ERROR_MASK; +} + +L4_INLINE long +l4_error_u(l4_msgtag_t tag, l4_utcb_t *u) L4_NOTHROW +{ + if (l4_msgtag_has_error(tag)) + return -(L4_EIPC_LO + (l4_utcb_tcr_u(u)->error & L4_IPC_ERROR_MASK)); + + return l4_msgtag_label(tag); +} + +L4_INLINE long +l4_error(l4_msgtag_t tag) L4_NOTHROW +{ + return l4_error_u(tag, l4_utcb()); +} + + +L4_INLINE int l4_ipc_is_snd_error(l4_utcb_t *u) L4_NOTHROW +{ return !(l4_utcb_tcr_u(u)->error & 1) == 0; } + +L4_INLINE int l4_ipc_is_rcv_error(l4_utcb_t *u) L4_NOTHROW +{ return l4_utcb_tcr_u(u)->error & 1; } + +L4_INLINE int l4_ipc_error_code(l4_utcb_t *u) L4_NOTHROW +{ return l4_utcb_tcr_u(u)->error & L4_IPC_ERROR_MASK; } + + +/* + * \internal + * \ingroup l4_ipc_api + */ +L4_INLINE int +l4_sndfpage_add_u(l4_fpage_t const snd_fpage, unsigned long snd_base, + l4_msgtag_t *tag, l4_utcb_t *utcb) L4_NOTHROW +{ + l4_msg_regs_t *v = l4_utcb_mr_u(utcb); + int i = l4_msgtag_words(*tag) + 2 * l4_msgtag_items(*tag); + + if (i >= L4_UTCB_GENERIC_DATA_SIZE - 1) + return -L4_ENOMEM; + + v->mr[i] = snd_base | L4_ITEM_MAP | L4_ITEM_CONT; + v->mr[i + 1] = snd_fpage.raw; + + *tag = l4_msgtag(l4_msgtag_label(*tag), l4_msgtag_words(*tag), + l4_msgtag_items(*tag) + 1, l4_msgtag_flags(*tag)); + return 0; +} + +L4_INLINE int +l4_sndfpage_add(l4_fpage_t const snd_fpage, unsigned long snd_base, + l4_msgtag_t *tag) L4_NOTHROW +{ + return l4_sndfpage_add_u(snd_fpage, snd_base, tag, l4_utcb()); +} + + +#endif /* ! __L4SYS__INCLUDE__L4API_FIASCO__IPC_H__ */ diff --git a/l4/pkg/l4sys/include/ipc_gate b/l4/pkg/l4sys/include/ipc_gate new file mode 100644 index 00000000..f92b096f --- /dev/null +++ b/l4/pkg/l4sys/include/ipc_gate @@ -0,0 +1,63 @@ +// vi:ft=cpp +/** + * \file + * \brief IPC-Gate interface. + */ +/* + * (c) 2009-2010 Adam Lackorzynski , + * Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#pragma once + +#include +#include + +namespace L4 { + +class Thread; + +/** + * \ingroup l4_kernel_object_gate_api + * \brief L4 IPC gate. + * + * \#include + */ +class L4_EXPORT Ipc_gate + : public Kobject_t +{ + L4_KOBJECT_DISABLE_COPY(Ipc_gate) +public: + + /** + * \brief Bind the IPC-gate to the thread. + * + * \see l4_ipc_gate_bind_thread + */ + l4_msgtag_t bind_thread(Cap t, l4_umword_t label, + l4_utcb_t *utcb = l4_utcb()) throw() + { return l4_ipc_gate_bind_thread_u(cap(), t.cap(), label, utcb); } + + /** + * \brief Get information on the IPC-gate. + * + * \see l4_ipc_gate_get_infos + */ + l4_msgtag_t get_infos(l4_umword_t *label, l4_utcb_t *utcb = l4_utcb()) throw() + { return l4_ipc_gate_get_infos_u(cap(), label, utcb); } +}; + +} diff --git a/l4/pkg/l4sys/include/ipc_gate.h b/l4/pkg/l4sys/include/ipc_gate.h new file mode 100644 index 00000000..5a1efe87 --- /dev/null +++ b/l4/pkg/l4sys/include/ipc_gate.h @@ -0,0 +1,127 @@ +/** + * \file + * \brief IPC-Gate interface. + */ +/* + * (c) 2009-2010 Adam Lackorzynski , + * Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#pragma once + +#include +#include + +/** + * \brief Bind the IPC-gate to the thread. + * \ingroup l4_kernel_object_gate_api + * + * \param t Thread to bind the IPC-gate to + * \param label Label to use + * \param utcb UTCB to use. + * + * \return System call return tag. + */ +L4_INLINE l4_msgtag_t +l4_ipc_gate_bind_thread(l4_cap_idx_t gate, l4_cap_idx_t thread, + l4_umword_t label); + +/** + * \internal + * \ingroup l4_kernel_object_gate_api + */ +L4_INLINE l4_msgtag_t +l4_ipc_gate_bind_thread_u(l4_cap_idx_t gate, l4_cap_idx_t thread, + l4_umword_t label, l4_utcb_t *utcb); + +/** + * \brief Get information on the IPC-gate. + * \ingroup l4_kernel_object_gate_api + * + * \retval label Label of the gate. + * \param utcb UTCb to use. + * + * \return System call return tag. + */ +L4_INLINE l4_msgtag_t +l4_ipc_gate_get_infos(l4_cap_idx_t gate, l4_umword_t *label); + +/** + * \internal + * \ingroup l4_kernel_object_gate_api + */ +L4_INLINE l4_msgtag_t +l4_ipc_gate_get_infos_u(l4_cap_idx_t gate, l4_umword_t *label, l4_utcb_t *utcb); + +/** + * \brief Operations on the IPC-gate. + * \ingroup l4_kernel_object_gate_api + * \hideinitializer + * \internal + */ +enum L4_ipc_gate_ops +{ + L4_IPC_GATE_BIND_OP = 0x10, /**< Bind operation */ + L4_IPC_GATE_GET_INFO_OP = 0x11, /**< Info operation */ +}; + + +/* IMPLEMENTATION -----------------------------------------------------------*/ + +#include + +L4_INLINE l4_msgtag_t +l4_ipc_gate_bind_thread_u(l4_cap_idx_t gate, + l4_cap_idx_t thread, l4_umword_t label, + l4_utcb_t *utcb) +{ + l4_msg_regs_t *m = l4_utcb_mr_u(utcb); + m->mr[0] = L4_IPC_GATE_BIND_OP; + m->mr[1] = label; + m->mr[2] = l4_map_obj_control(0, 0); + m->mr[3] = l4_obj_fpage(thread, 0, L4_FPAGE_RWX).raw; + return l4_ipc_call(gate, utcb, l4_msgtag(L4_PROTO_KOBJECT, 2, 1, 0), + L4_IPC_NEVER); +} + +L4_INLINE l4_msgtag_t +l4_ipc_gate_get_infos_u(l4_cap_idx_t gate, l4_umword_t *label, l4_utcb_t *utcb) +{ + l4_msgtag_t tag; + l4_msg_regs_t *m = l4_utcb_mr_u(utcb); + m->mr[0] = L4_IPC_GATE_GET_INFO_OP; + tag = l4_ipc_call(gate, utcb, l4_msgtag(L4_PROTO_KOBJECT, 1, 0, 0), + L4_IPC_NEVER); + if (!l4_msgtag_has_error(tag) && l4_msgtag_label(tag) >= 0) + *label = m->mr[0]; + + return tag; +} + + + +L4_INLINE l4_msgtag_t +l4_ipc_gate_bind_thread(l4_cap_idx_t gate, l4_cap_idx_t thread, + l4_umword_t label) +{ + return l4_ipc_gate_bind_thread_u(gate, thread, label, l4_utcb()); +} + +L4_INLINE l4_msgtag_t +l4_ipc_gate_get_infos(l4_cap_idx_t gate, l4_umword_t *label) +{ + return l4_ipc_gate_get_infos_u(gate, label, l4_utcb()); +} diff --git a/l4/pkg/l4sys/include/irq b/l4/pkg/l4sys/include/irq new file mode 100644 index 00000000..6465bae6 --- /dev/null +++ b/l4/pkg/l4sys/include/irq @@ -0,0 +1,226 @@ +// vi:ft=cpp +/** + * \file + * \brief Interrupt functionality + * \ingroup l4_api + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ + +#pragma once + +#include +#include +#include + +namespace L4 { +namespace Protocol { enum { Icu = L4_PROTO_IRQ }; } +namespace Protocol { enum { Irq = L4_PROTO_IRQ }; } + +class Irq_eio : public Kobject_t +{ + L4_KOBJECT_DISABLE_COPY(Irq_eio) + +public: + l4_msgtag_t unmask(unsigned irqnum, l4_umword_t *label, l4_timeout_t to, + l4_utcb_t *utcb = l4_utcb()) throw() + { return l4_icu_control_u(cap(), irqnum, L4_ICU_CTL_UNMASK, label, to, utcb); } +}; + +/** + * \brief C++ version of an L4 IRQ. + * \ingroup l4_irq_api + * + * \#include + * + * \see \ref l4_irq_api for an overview and C bindings. + */ +class Irq : public Kobject_t +{ + L4_KOBJECT(Irq); + +public: + + /** + * \copydoc l4_irq_attach() + * \note \a irq is the implicit \a this pointer. + */ + l4_msgtag_t attach(l4_umword_t label, Cap const &thread, + l4_utcb_t *utcb = l4_utcb()) throw() + { return l4_irq_attach_u(cap(), label, thread.cap(), utcb); } + + /** + * \copydoc l4_irq_chain() + * \note \a irq is the implicit \a this pointer. + */ + l4_msgtag_t chain(l4_umword_t label, Cap const &slave, + l4_utcb_t *utcb = l4_utcb()) throw() + { return l4_irq_chain_u(cap(), label, slave.cap(), utcb); } + + /** + * \copydoc l4_irq_detach() + * \note \a irq is the implicit \a this pointer. + */ + l4_msgtag_t detach(l4_utcb_t *utcb = l4_utcb()) throw() + { return l4_irq_detach_u(cap(), utcb); } + + + /** + * \copydoc l4_irq_receive() + * \note \a irq is the implicit \a this pointer. + */ + l4_msgtag_t receive(l4_timeout_t to = L4_IPC_NEVER, + l4_utcb_t *utcb = l4_utcb()) throw() + { return l4_irq_receive_u(cap(), to, utcb); } + + /** + * \copydoc l4_irq_wait() + * \note \a irq is the implicit \a this pointer. + */ + l4_msgtag_t wait(l4_umword_t *label, l4_timeout_t to = L4_IPC_NEVER, + l4_utcb_t *utcb = l4_utcb()) throw() + { return l4_irq_wait_u(cap(), label, to, utcb); } + + /** + * \copydoc l4_irq_unmask() + * \note \a irq is the implicit \a this pointer. + */ + l4_msgtag_t unmask(l4_utcb_t *utcb = l4_utcb()) throw() + { return l4_irq_unmask_u(cap(), utcb); } + + /** + * \copydoc l4_irq_trigger() + * \note \a irq is the implicit \a this pointer. + */ + l4_msgtag_t trigger(l4_utcb_t *utcb = l4_utcb()) throw() + { return l4_irq_trigger_u(cap(), utcb); } + +}; + + +/** + * \brief C++ version of an interrupt controller. + * \ingroup l4_icu_api + * + * \#include + * + * \see \ref l4_icu_api for an overview and C bindings. + */ +class Icu : public Kobject_t +{ + L4_KOBJECT(Icu); + +public: + enum Flow_type + { + F_none = L4_IRQ_F_NONE, + F_level_high = L4_IRQ_F_LEVEL_HIGH, + F_level_low = L4_IRQ_F_LEVEL_LOW, + F_pos_edge = L4_IRQ_F_POS_EDGE, + F_neg_edge = L4_IRQ_F_NEG_EDGE, + F_both_edge = L4_IRQ_F_BOTH_EDGE, + F_mask = L4_IRQ_F_MASK, + }; + + enum Flags + { + F_msi = L4_ICU_FLAG_MSI + }; + + /** + * \brief Info for an ICU. + * \ingroup l4_icu_api + * + * This class adds access functions. + * \see l4_icu_info(). + */ + class Info : public l4_icu_info_t + { + public: + bool supports_msi() const { return features & F_msi; } + }; + + /** + * \copydoc l4_icu_bind() + * \note \a the icu argument is the implicit \a this pointer. + */ + l4_msgtag_t bind(unsigned irqnum, L4::Cap irq, + l4_utcb_t *utcb = l4_utcb()) throw() + { return l4_icu_bind_u(cap(), irqnum, irq.cap(), utcb); } + + /** + * \copydoc l4_icu_unbind() + * \note \a the icu argument is the implicit \a this pointer. + */ + l4_msgtag_t unbind(unsigned irqnum, L4::Cap irq, + l4_utcb_t *utcb = l4_utcb()) throw() + { return l4_icu_unbind_u(cap(), irqnum, irq.cap(), utcb); } + + /** + * \copydoc l4_icu_info() + * \note \a the icu argument is the implicit \a this pointer. + */ + l4_msgtag_t info(l4_icu_info_t *info, l4_utcb_t *utcb = l4_utcb()) throw() + { return l4_icu_info_u(cap(), info, utcb); } + + /** + * \copydoc l4_icu_msi_info() + * \note \a the icu argument is the implicit \a this pointer. + */ + l4_msgtag_t msi_info(unsigned irqnum, l4_umword_t *msg, + l4_utcb_t *utcb = l4_utcb()) throw() + { return l4_icu_msi_info_u(cap(), irqnum, msg, utcb); } + + /** + * \internal + */ + l4_msgtag_t control(unsigned irqnum, unsigned op, l4_umword_t *label, + l4_timeout_t to, l4_utcb_t *utcb = l4_utcb()) throw() + { return l4_icu_control_u(cap(), irqnum, op, label, to, utcb); } + + /** + * \copydoc l4_icu_mask() + * \note \a the icu argument is the implicit \a this pointer. + */ + l4_msgtag_t mask(unsigned irqnum, + l4_umword_t *label = 0, + l4_timeout_t to = L4_IPC_NEVER, + l4_utcb_t *utcb = l4_utcb()) throw() + { return l4_icu_mask_u(cap(), irqnum, label, to, utcb); } + + /** + * \copydoc l4_icu_unmask() + * \note \a the icu argument is the implicit \a this pointer. + */ + l4_msgtag_t unmask(unsigned irqnum, + l4_umword_t *label = 0, + l4_timeout_t to = L4_IPC_NEVER, + l4_utcb_t *utcb = l4_utcb()) throw() + { return l4_icu_unmask_u(cap(), irqnum, label, to, utcb); } + + /** + * \copydoc l4_icu_set_mode() + * \note \a the icu argument is the implicit \a this pointer. + */ + l4_msgtag_t set_mode(unsigned irqnum, l4_umword_t mode, + l4_utcb_t *utcb = l4_utcb()) throw() + { return l4_icu_set_mode_u(cap(), irqnum, mode, utcb); } +}; + +} diff --git a/l4/pkg/l4sys/include/irq.h b/l4/pkg/l4sys/include/irq.h new file mode 100644 index 00000000..465580af --- /dev/null +++ b/l4/pkg/l4sys/include/irq.h @@ -0,0 +1,318 @@ +/** + * \file + * \brief Interrupt functionality + * \ingroup l4_api + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg , + * Björn Döbel + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#pragma once + +#include +#include + +/** + * \defgroup l4_irq_api IRQs + * \ingroup l4_kernel_object_api + * + * \brief The IRQ and IRQ class. + * + * \#include + * + * The IRQ class provides access to abstract interrupts + * provided by the micro kernel. Interrupts may be hardware interrupts + * provided by the platform interrupt controller, virtual device interrupts + * provided by the micro kernel virtual devices (virtual serial or trace + * buffer), or IRQs (virtual interrupts that can be triggered by user + * programs). + * + * IRQ objects can be created using a Factory, see \ref l4_factory_api + * (l4_factory_create_irq()). + * + */ + +/** + * \brief Attach to an interrupt source. + * \ingroup l4_irq_api + * + * \param irq IRQ to attach to. + * \param label Identifier of the IRQ. + * \param thread Thread to attach the interrupt to. + * + * \return Syscall return tag + */ +L4_INLINE l4_msgtag_t +l4_irq_attach(l4_cap_idx_t irq, l4_umword_t label, + l4_cap_idx_t thread) L4_NOTHROW; + +/** + * \internal + */ +L4_INLINE l4_msgtag_t +l4_irq_attach_u(l4_cap_idx_t irq, l4_umword_t label, + l4_cap_idx_t thread, l4_utcb_t *utcb) L4_NOTHROW; + +/** + * \brief Chain an IRQ to another master IRQ source. + * \ingroup l4_irq_api + * + * The chaining feature of IRQ objects allows to deal with shared IRQs. + * For chaining IRQs there must be a master IRQ object, bound to the + * real IRQ source. Note, the master IRQ must not have a thread attached to it. + * This function allows to add a limited number of slave IRQs to this master + * IRQ, with the semantics that each of the slave IRQs is triggered whenever + * the master IRQ is triggered. The master IRQ will be masked automatically + * when an IRQ is delivered and shall be unmasked when all attached slave IRQs + * are unmasked. + * + * \param irq The master IRQ object. + * \param label Identifier of the IRQ. + * \param slave The slave that shall be attached to the master. + * + * \return Syscall return tag + */ +L4_INLINE l4_msgtag_t +l4_irq_chain(l4_cap_idx_t irq, l4_umword_t label, + l4_cap_idx_t slave) L4_NOTHROW; + +/** + * \internal + */ +L4_INLINE l4_msgtag_t +l4_irq_chain_u(l4_cap_idx_t irq, l4_umword_t label, + l4_cap_idx_t slave, l4_utcb_t *utcb) L4_NOTHROW; + +/** + * \brief Detach from an interrupt source. + * \ingroup l4_irq_api + * + * \param irq IRQ to detach from. + * + * \return Syscall return tag + */ +L4_INLINE l4_msgtag_t +l4_irq_detach(l4_cap_idx_t irq) L4_NOTHROW; + +/** + * \internal + */ +L4_INLINE l4_msgtag_t +l4_irq_detach_u(l4_cap_idx_t irq, l4_utcb_t *utcb) L4_NOTHROW; + + +/** + * \brief Trigger an IRQ. + * \ingroup l4_irq_api + * + * \param irq IRQ to trigger. + * \pre \a irq must be a reference to an IRQ. + * + * \return Syscall return tag, note this is a send only operation, i.e. there + * is no return value except for failed sending. + */ +L4_INLINE l4_msgtag_t +l4_irq_trigger(l4_cap_idx_t irq) L4_NOTHROW; + +/** + * \internal + */ +L4_INLINE l4_msgtag_t +l4_irq_trigger_u(l4_cap_idx_t irq, l4_utcb_t *utcb) L4_NOTHROW; + +/** + * \brief Unmask and wait for specified IRQ. + * \ingroup l4_irq_api + * + * \param irq IRQ to wait for. + * \param to Timeout. + * + * \return Syscall return tag + */ +L4_INLINE l4_msgtag_t +l4_irq_receive(l4_cap_idx_t irq, l4_timeout_t to) L4_NOTHROW; + +/** + * \internal + */ +L4_INLINE l4_msgtag_t +l4_irq_receive_u(l4_cap_idx_t irq, l4_timeout_t to, l4_utcb_t *utcb) L4_NOTHROW; + +/** + * \brief Unmask IRQ and wait for any message. + * \ingroup l4_irq_api + * + * \param irq IRQ to wait for. + * \param label Receive label. + * \param to Timeout. + * + * \return Syscall return tag + */ +L4_INLINE l4_msgtag_t +l4_irq_wait(l4_cap_idx_t irq, l4_umword_t *label, + l4_timeout_t to) L4_NOTHROW; + +/** + * \internal + */ +L4_INLINE l4_msgtag_t +l4_irq_wait_u(l4_cap_idx_t irq, l4_umword_t *label, + l4_timeout_t to, l4_utcb_t *utcb) L4_NOTHROW; + +/** + * \brief Unmask IRQ. + * \ingroup l4_irq_api + * + * \param irq IRQ to unmask. + * + * \return Syscall return tag + * + * \note l4_irq_wait and l4_irq_receive are doing the unmask themselves. + */ +L4_INLINE l4_msgtag_t +l4_irq_unmask(l4_cap_idx_t irq) L4_NOTHROW; + +/** + * \internal + */ +L4_INLINE l4_msgtag_t +l4_irq_unmask_u(l4_cap_idx_t irq, l4_utcb_t *utcb) L4_NOTHROW; + +/** + * \internal + */ +enum L4_irq_op +{ + L4_IRQ_OP_ATTACH = 1, + L4_IRQ_OP_TRIGGER = 2, + L4_IRQ_OP_CHAIN = 3, + L4_IRQ_OP_EOI = 4, +}; + +/************************************************************************** + * Implementations + */ + +L4_INLINE l4_msgtag_t +l4_irq_attach_u(l4_cap_idx_t irq, l4_umword_t label, + l4_cap_idx_t thread, l4_utcb_t *utcb) L4_NOTHROW +{ + l4_msg_regs_t *m = l4_utcb_mr_u(utcb); + m->mr[0] = L4_IRQ_OP_ATTACH; + m->mr[1] = label; + m->mr[2] = l4_map_obj_control(0, 0); + m->mr[3] = l4_obj_fpage(thread, 0, L4_FPAGE_RWX).raw; + return l4_ipc_call(irq, utcb, l4_msgtag(L4_PROTO_IRQ, 2, 1, 0), L4_IPC_NEVER); +} + +L4_INLINE l4_msgtag_t +l4_irq_chain_u(l4_cap_idx_t irq, l4_umword_t label, + l4_cap_idx_t slave, l4_utcb_t *utcb) L4_NOTHROW +{ + l4_msg_regs_t *m = l4_utcb_mr_u(utcb); + m->mr[0] = L4_IRQ_OP_CHAIN; + m->mr[1] = label; + m->mr[2] = l4_map_obj_control(0, 0); + m->mr[3] = l4_obj_fpage(slave, 0, L4_FPAGE_RWX).raw; + return l4_ipc_call(irq, utcb, l4_msgtag(L4_PROTO_IRQ, 2, 1, 0), L4_IPC_NEVER); +} + +L4_INLINE l4_msgtag_t +l4_irq_detach_u(l4_cap_idx_t irq, l4_utcb_t *utcb) L4_NOTHROW +{ + l4_utcb_mr_u(utcb)->mr[0] = L4_IRQ_OP_ATTACH; + return l4_ipc_call(irq, utcb, l4_msgtag(L4_PROTO_IRQ, 1, 0, 0), L4_IPC_NEVER); +} + +L4_INLINE l4_msgtag_t +l4_irq_trigger_u(l4_cap_idx_t irq, l4_utcb_t *utcb) L4_NOTHROW +{ + l4_utcb_mr_u(utcb)->mr[0] = L4_IRQ_OP_TRIGGER; + return l4_ipc_send(irq, utcb, l4_msgtag(L4_PROTO_IRQ, 1, 0, 0), + L4_IPC_BOTH_TIMEOUT_0); +} + +L4_INLINE l4_msgtag_t +l4_irq_receive_u(l4_cap_idx_t irq, l4_timeout_t to, l4_utcb_t *utcb) L4_NOTHROW +{ + l4_utcb_mr_u(utcb)->mr[0] = L4_IRQ_OP_EOI; + return l4_ipc_call(irq, utcb, l4_msgtag(L4_PROTO_IRQ, 1, 0, 0), to); +} + +L4_INLINE l4_msgtag_t +l4_irq_wait_u(l4_cap_idx_t irq, l4_umword_t *label, + l4_timeout_t to, l4_utcb_t *utcb) L4_NOTHROW +{ + l4_utcb_mr_u(utcb)->mr[0] = L4_IRQ_OP_EOI; + return l4_ipc_send_and_wait(irq, utcb, l4_msgtag(L4_PROTO_IRQ, 1, 0, 0), + label, to); +} + +L4_INLINE l4_msgtag_t +l4_irq_unmask_u(l4_cap_idx_t irq, l4_utcb_t *utcb) L4_NOTHROW +{ + l4_utcb_mr_u(utcb)->mr[0] = L4_IRQ_OP_EOI; + return l4_ipc_send(irq, utcb, l4_msgtag(L4_PROTO_IRQ, 1, 0, 0), L4_IPC_NEVER); +} + + +L4_INLINE l4_msgtag_t +l4_irq_attach(l4_cap_idx_t irq, l4_umword_t label, + l4_cap_idx_t thread) L4_NOTHROW +{ + return l4_irq_attach_u(irq, label, thread, l4_utcb()); +} + +L4_INLINE l4_msgtag_t +l4_irq_chain(l4_cap_idx_t irq, l4_umword_t label, + l4_cap_idx_t slave) L4_NOTHROW +{ + return l4_irq_chain_u(irq, label, slave, l4_utcb()); +} + +L4_INLINE l4_msgtag_t +l4_irq_detach(l4_cap_idx_t irq) L4_NOTHROW +{ + return l4_irq_detach_u(irq, l4_utcb()); +} + +L4_INLINE l4_msgtag_t +l4_irq_trigger(l4_cap_idx_t irq) L4_NOTHROW +{ + return l4_irq_trigger_u(irq, l4_utcb()); +} + +L4_INLINE l4_msgtag_t +l4_irq_receive(l4_cap_idx_t irq, l4_timeout_t to) L4_NOTHROW +{ + return l4_irq_receive_u(irq, to, l4_utcb()); +} + +L4_INLINE l4_msgtag_t +l4_irq_wait(l4_cap_idx_t irq, l4_umword_t *label, + l4_timeout_t to) L4_NOTHROW +{ + return l4_irq_wait_u(irq, label, to, l4_utcb()); +} + +L4_INLINE l4_msgtag_t +l4_irq_unmask(l4_cap_idx_t irq) L4_NOTHROW +{ + return l4_irq_unmask_u(irq, l4_utcb()); +} + diff --git a/l4/pkg/l4sys/include/kernel_object.h b/l4/pkg/l4sys/include/kernel_object.h new file mode 100644 index 00000000..759fcee1 --- /dev/null +++ b/l4/pkg/l4sys/include/kernel_object.h @@ -0,0 +1,88 @@ +/** + * \file + * \brief Kernel object system calls + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg , + * Björn Döbel + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#ifndef __L4SYS__KERNEL_OBJECT_H__ +#define __L4SYS__KERNEL_OBJECT_H__ + +#include +#include +#include + +/** + * \defgroup l4_kernel_object_api Kernel Objects + * \brief API of kernel objects. + * \ingroup l4_api + * + * \#include + */ + + + +/** + * \internal + * \brief Invoke object, the debugger call. + * \ingroup l4_kernel_object_api + * \param obj The capability of the object to invoke. + * \param tag Message tag. + * \param utcb UTCB of the caller. + * + * \return System call return tag + */ +L4_INLINE l4_msgtag_t +l4_invoke_debugger(l4_cap_idx_t obj, l4_msgtag_t tag, l4_utcb_t *utcb) L4_NOTHROW; + + +/************************************************************************** + * Implementation + **************************************************************************/ + +#include +#include + +enum L4_kobject_op { + L4_KOBJECT_OP_DEC_REFCNT = 0, + L4_KOBJECT_OP_REGISTER_IRQ, +}; + +L4_INLINE l4_msgtag_t +l4_kobject_dec_refcnt_u(l4_cap_idx_t obj, l4_mword_t diff, l4_utcb_t *u) L4_NOTHROW; + +L4_INLINE l4_msgtag_t +l4_kobject_dec_refcnt(l4_cap_idx_t obj, l4_mword_t diff) L4_NOTHROW; + +L4_INLINE l4_msgtag_t +l4_kobject_dec_refcnt_u(l4_cap_idx_t obj, l4_mword_t diff, l4_utcb_t *u) L4_NOTHROW +{ + l4_msg_regs_t *m = l4_utcb_mr_u(u); + m->mr[0] = L4_KOBJECT_OP_DEC_REFCNT; + m->mr[1] = diff; + return l4_ipc_call(obj, u, l4_msgtag(L4_PROTO_KOBJECT, 2, 0, 0), L4_IPC_NEVER); +} + +L4_INLINE l4_msgtag_t +l4_kobject_dec_refcnt(l4_cap_idx_t obj, l4_mword_t diff) L4_NOTHROW +{ + return l4_kobject_dec_refcnt_u(obj, diff, l4_utcb()); +} + +#endif /* ! __L4SYS__KERNEL_OBJECT_H__ */ diff --git a/l4/pkg/l4sys/include/kip b/l4/pkg/l4sys/include/kip new file mode 100644 index 00000000..d4127d2e --- /dev/null +++ b/l4/pkg/l4sys/include/kip @@ -0,0 +1,189 @@ +// vim:set ft=cpp: +/*! + * \file + * \brief L4::Kip class, memory descriptors. + * + * \author Alexander Warg + * \ingroup l4_api + * + */ +/* + * (c) 2008-2009 Author(s) + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#ifndef L4_SYS_KIP_H__ +#define L4_SYS_KIP_H__ + +/* C++ version of memory descriptors */ + +/** + * \defgroup l4_kip_api Kernel Interface Page + * \ingroup l4_api + * \brief Kernel Interface Page. + * + * C++ interface for the Kernel Interface Page:
+ * \#include + */ + +namespace L4 +{ + namespace Kip + { + /** + * \brief Memory descriptors stored in the kernel interface page. + * \ingroup l4_kip_api + * + * \#include + */ + class Mem_desc + { + public: + /** + * \brief Memory types. + */ + enum Mem_type + { + Undefined = 0x0, //< Undefined memory + Conventional = 0x1, //< Conventional memory + Reserved = 0x2, //< Reserved region, do not use this memory + Dedicated = 0x3, //< Dedicated + Shared = 0x4, //< Shared + + Bootloader = 0xe, //< Memory belongs to the boot loader + Arch = 0xf //< Architecture specific memory + }; + private: + unsigned long _l, _h; + + static unsigned long &memory_info(void *kip) throw() + { return *((unsigned long *)kip + 21); } + + static unsigned long memory_info(void const *kip) throw() + { return *((unsigned long const *)kip + 21); } + + public: + /** + * \brief Get first memory descriptor. + * \param kip Pointer to the kernel info page + * \return First memory descriptor stored in the kernel info page + */ + static Mem_desc *first(void *kip) throw() + { + return (Mem_desc*)((char *)kip + + (memory_info(kip) >> ((sizeof(unsigned long)/2)*8))); + } + + static Mem_desc const *first(void const *kip) throw() + { + return (Mem_desc const*)((char const *)kip + + (memory_info(kip) >> ((sizeof(unsigned long)/2)*8))); + } + + /** + * \brief Return number of memory descriptors stored in the kernel info page. + * \param kip Pointer to the kernel info page + * \return Number of memory descriptors in the kernel info page. + */ + static unsigned long count(void const *kip) throw() + { + return memory_info(kip) & ((1UL << ((sizeof(unsigned long)/2)*8)) - 1); + } + + /** + * \brief Set number of memory descriptors. + * \param kip Pointer to the kernel info page + * \param count Number of memory descriptors + */ + static void count(void *kip, unsigned count) throw() + { + unsigned long &mi = memory_info(kip); + mi = (mi & ~((1UL << ((sizeof(unsigned long)/2)*8)) - 1)) | count; + } + + /** + * \brief Initialize memory descriptor. + * \param start Start address + * \param end End address + * \param t Memory type + * \param st Memory subtype, defaults to 0 + * \param virt True for virtual memory, false for physical memory, + * defaults to physical + */ + Mem_desc(unsigned long start, unsigned long end, + Mem_type t, unsigned char st = 0, bool virt = false) throw() + : _l((start & ~0x3ffUL) | (t & 0x0f) | ((st << 4) & 0x0f0) + | (virt?0x0200:0x0)), _h(end | 0x3ffUL) + {} + + /** + * \brief Return start address of memory descriptor. + * \return Start address of memory descriptor + */ + unsigned long start() const throw() { return _l & ~0x3ffUL; } + + /** + * \brief Return end address of memory descriptor. + * \return End address of memory descriptor + */ + unsigned long end() const throw() { return _h | 0x3ffUL; } + + /** + * \brief Return size of region described by the memory descriptor. + * \return Size of the region described by the memory descriptor + */ + unsigned long size() const throw() { return end() + 1 - start(); } + + /** + * \brief Return type of the memory descriptor. + * \return Type of the memory descriptor + */ + Mem_type type() const throw() { return (Mem_type)(_l & 0x0f); } + + /** + * \brief Return sub-type of the memory descriptor. + * \return Sub-type of the memory descriptor + */ + unsigned char sub_type() const throw() { return (_l >> 4) & 0x0f; } + + /** + * \brief Return whether the memory descriptor describes a virtual or + * physical region. + * \return True for virtual region, false for physical region. + */ + unsigned is_virtual() const throw() { return _l & 0x200; } + + /** + * \brief Set values of a memory descriptor. + * \param start Start address + * \param end End address + * \param t Memory type + * \param st Sub-type, defaults to 0 + * \param virt Virtual or physical memory region, defaults to physical + */ + void set(unsigned long start, unsigned long end, + Mem_type t, unsigned char st = 0, bool virt = false) throw() + { + _l = (start & ~0x3ffUL) | (t & 0x0f) | ((st << 4) & 0x0f0) + | (virt?0x0200:0x0); + + _h = end | 0x3ffUL; + } + + }; + }; +}; + +#endif diff --git a/l4/pkg/l4sys/include/kip.h b/l4/pkg/l4sys/include/kip.h new file mode 100644 index 00000000..2b3df1a9 --- /dev/null +++ b/l4/pkg/l4sys/include/kip.h @@ -0,0 +1,112 @@ +/** + * \file + * \brief Kernel Info Page access functions. + * \ingroup l4_api + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#pragma once + +#include +#include + +/** + * \internal + */ +struct l4_kip_platform_info +{ + l4_umword_t cpuid; ///< reserved \internal + l4_umword_t mp; ///< reserved \internal + char name[16]; +}; + +#if L4_MWORD_BITS == 32 +# include +#else +# include +#endif + + + + +/** + * \addtogroup l4_kip_api + * + * C interface for the Kernel Interface Page:
+ * \#include + */ +/*@{*/ + +/** + * \internal + */ +enum l4_kernel_info_consts_t +{ + L4_KIP_VERSION_FIASCO = 0x87004444, + L4_KIP_VERSION_FIASCO_MASK = 0xff00ffff, +}; + +/** + * \brief Kernel Info Page identifier ("L4µK"). + */ +#define L4_KERNEL_INFO_MAGIC (0x4BE6344CL) /* "L4µK" */ + + +/** + * \brief Get the kernel version. + * \param kip Kernel Interface Page. + * \return Kernel version string. 0 if KIP could not be mapped. + */ +L4_INLINE l4_umword_t l4_kip_version(l4_kernel_info_t *kip) L4_NOTHROW; + +/** + * \brief Get the kernel version string. + * \param kip Kernel Interface Page. + * \return Kernel version string. + */ +L4_INLINE const char *l4_kip_version_string(l4_kernel_info_t *kip) L4_NOTHROW; + +/** + * \brief Return offset in bytes of version_strings relative to the KIP base. + * + * \param kip Pointer to the kernel into page (KIP). + * + * \return offset of version_strings relative to the KIP base address, in + * bytes. + */ +L4_INLINE int +l4_kernel_info_version_offset(l4_kernel_info_t *kip) L4_NOTHROW; + +/*@}*/ + +/************************************************************************* + * Implementations + *************************************************************************/ + +L4_INLINE l4_umword_t +l4_kip_version(l4_kernel_info_t *kip) L4_NOTHROW +{ return kip->version & L4_KIP_VERSION_FIASCO_MASK; } + +L4_INLINE const char* +l4_kip_version_string(l4_kernel_info_t *k) L4_NOTHROW +{ return (const char *)k + l4_kernel_info_version_offset(k); } + +L4_INLINE int +l4_kernel_info_version_offset(l4_kernel_info_t *kip) L4_NOTHROW +{ return kip->offset_version_strings << 4; } diff --git a/l4/pkg/l4sys/include/l4int.h b/l4/pkg/l4sys/include/l4int.h new file mode 100644 index 00000000..8ee9c3c0 --- /dev/null +++ b/l4/pkg/l4sys/include/l4int.h @@ -0,0 +1,67 @@ +/** + * \addtogroup l4_basic_types Integer Types + * \ingroup l4_api + * + * \#include + */ + +/** + * \file + * \brief Fixed sized integer types, generic version. + * \ingroup l4_basic_types + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#ifndef __L4_SYS_L4INT_H__ +#define __L4_SYS_L4INT_H__ + +/* fixed sized data types */ +typedef signed char l4_int8_t; /**< \brief Signed 8bit value. \ingroup l4_basic_types */ +typedef unsigned char l4_uint8_t; /**< \brief Unsigned 8bit value. \ingroup l4_basic_types */ +typedef signed short int l4_int16_t; /**< \brief Signed 16bit value. \ingroup l4_basic_types */ +typedef unsigned short int l4_uint16_t; /**< \brief Unsigned 16bit value. \ingroup l4_basic_types */ +typedef signed int l4_int32_t; /**< \brief Signed 32bit value. \ingroup l4_basic_types */ +typedef unsigned int l4_uint32_t; /**< \brief Unsigned 32bit value. \ingroup l4_basic_types */ +typedef signed long long l4_int64_t; /**< \brief Signed 64bit value. \ingroup l4_basic_types */ +typedef unsigned long long l4_uint64_t; /**< \brief Unsigned 64bit value. \ingroup l4_basic_types */ + +/* some common data types */ +typedef unsigned long l4_addr_t; /**< \brief Address type \ingroup l4_basic_types */ +//do-we-need-this?//typedef unsigned long l4_offs_t; /**< \brief Address offset type \ingroup l4_basic_types */ + + +typedef signed long l4_mword_t; /**< Signed machine word. + ** \ingroup l4_basic_types + **/ +typedef unsigned long l4_umword_t; /**< Unsigned machine word. + ** \ingroup l4_basic_types + **/ +/** + * CPU clock type. + * \ingroup l4_basic_types + */ +typedef l4_uint64_t l4_cpu_time_t; + +/** + * Kernel clock type. + * \ingroup l4_basic_types + */ +typedef l4_uint64_t l4_kernel_clock_t; + +#endif /* !__L4_SYS_L4INT_H__ */ diff --git a/l4/pkg/l4sys/include/memdesc.h b/l4/pkg/l4sys/include/memdesc.h new file mode 100644 index 00000000..6d5256cb --- /dev/null +++ b/l4/pkg/l4sys/include/memdesc.h @@ -0,0 +1,233 @@ +/** + * \file + * \brief Memory description functions. + * \ingroup l4_api + */ +/* + * (c) 2007-2009 Adam Lackorzynski , + * Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#ifndef __L4SYS__MEMDESC_H__ +#define __L4SYS__MEMDESC_H__ + +#include + +/** + * \defgroup l4_kip_memdesc_api Memory descriptors (C version) + * \ingroup l4_kip_api + * \brief C Interface for KIP memory descriptors. + * + * \#include + * + * This module contains the C functions to access the memory descriptor in the + * kernel interface page (KIP). + */ + +/** + * \brief Type of a memory descriptor. + * \ingroup l4_kip_memdesc_api + */ +enum l4_mem_type_t +{ + l4_mem_type_undefined = 0x0, ///< Undefined, unused descriptor + l4_mem_type_conventional = 0x1, ///< Conventional memory + l4_mem_type_reserved = 0x2, ///< Reserved memory for kernel etc. + l4_mem_type_dedicated = 0x3, ///< Dedicated memory (some device memory) + l4_mem_type_shared = 0x4, ///< Shared memory (not implemented) + + l4_mem_type_bootloader = 0xe, ///< Memory owned by the boot loader + l4_mem_type_archspecific = 0xf, ///< Architecture specific memory (e.g., ACPI memory) +}; + + +/** + * \brief Memory descriptor data structure. + * \ingroup l4_kip_memdesc_api + * + * \note This data type is opaque, and must be accessed by the accessor + * functions defined in this module. + */ +typedef struct l4_kernel_info_mem_desc_t +{ + /// \internal + l4_umword_t l; + /// \internal + l4_umword_t h; +} l4_kernel_info_mem_desc_t; + + +/** + * \brief Get pointer to memory descriptors from KIP. + * \ingroup l4_kip_memdesc_api + */ +L4_INLINE +l4_kernel_info_mem_desc_t * +l4_kernel_info_get_mem_descs(l4_kernel_info_t *kip) L4_NOTHROW; + +/** + * \brief Get number of memory descriptors in KIP. + * \ingroup l4_kip_memdesc_api + * + * \return Number of memory descriptors. + */ +L4_INLINE +unsigned +l4_kernel_info_get_num_mem_descs(l4_kernel_info_t *kip) L4_NOTHROW; + +/** + * \brief Populate a memory descriptor. + * \ingroup l4_kip_memdesc_api + * + * \param md Pointer to memory descriptor + * \param start Start of region + * \param end End of region + * \param type Type of region + * \param virt 1 if virtual region, 0 if physical region + * \param sub_type Sub type. + */ +L4_INLINE +void +l4_kernel_info_set_mem_desc(l4_kernel_info_mem_desc_t *md, + l4_addr_t start, + l4_addr_t end, + unsigned type, + unsigned virt, + unsigned sub_type) L4_NOTHROW; + +/** + * \brief Get start address of the region described by the memory descriptor. + * \ingroup l4_kip_memdesc_api + * + * \return Start address. + */ +L4_INLINE +l4_umword_t +l4_kernel_info_get_mem_desc_start(l4_kernel_info_mem_desc_t *md) L4_NOTHROW; + +/** + * \brief Get end address of the region described by the memory descriptor. + * \ingroup l4_kip_memdesc_api + * + * \return End address. + */ +L4_INLINE +l4_umword_t +l4_kernel_info_get_mem_desc_end(l4_kernel_info_mem_desc_t *md) L4_NOTHROW; + +/** + * \brief Get type of the memory region. + * \ingroup l4_kip_memdesc_api + * + * \return Type of the region (see #l4_mem_type_t). + */ +L4_INLINE +l4_umword_t +l4_kernel_info_get_mem_desc_type(l4_kernel_info_mem_desc_t *md) L4_NOTHROW; + +/** + * \brief Get sub-type of memory region. + * \ingroup l4_kip_memdesc_api + * + * \return Sub-type. + * + * The sub type is defined for architecture specific memory descriptors + * (see #l4_mem_type_archspecific) and has architecture specific meaning. + */ +L4_INLINE +l4_umword_t +l4_kernel_info_get_mem_desc_subtype(l4_kernel_info_mem_desc_t *md) L4_NOTHROW; + +/** + * \brief Get virtual flag of the memory descriptor. + * \ingroup l4_kip_memdesc_api + * + * \return 1 if region is virtual memory, 0 if region is physical memory + */ +L4_INLINE +l4_umword_t +l4_kernel_info_get_mem_desc_is_virtual(l4_kernel_info_mem_desc_t *md) L4_NOTHROW; + +/************************************************************************* + * Implementations + *************************************************************************/ + +L4_INLINE +l4_kernel_info_mem_desc_t * +l4_kernel_info_get_mem_descs(l4_kernel_info_t *kip) L4_NOTHROW +{ + return (l4_kernel_info_mem_desc_t *)(((l4_addr_t)kip) + + (kip->mem_info >> (sizeof(l4_umword_t) * 4))); +} + +L4_INLINE +unsigned +l4_kernel_info_get_num_mem_descs(l4_kernel_info_t *kip) L4_NOTHROW +{ + return kip->mem_info & ((1UL << (sizeof(l4_umword_t)*4)) -1); +} + +L4_INLINE +void +l4_kernel_info_set_mem_desc(l4_kernel_info_mem_desc_t *md, + l4_addr_t start, + l4_addr_t end, + unsigned type, + unsigned virt, + unsigned sub_type) L4_NOTHROW +{ + md->l = (start & ~0x3ffUL) | (type & 0x0f) | ((sub_type << 4) & 0x0f0) + | (virt ? 0x200 : 0x0); + md->h = end; +} + + +L4_INLINE +l4_umword_t +l4_kernel_info_get_mem_desc_start(l4_kernel_info_mem_desc_t *md) L4_NOTHROW +{ + return md->l & ~0x3ffUL; +} + +L4_INLINE +l4_umword_t +l4_kernel_info_get_mem_desc_end(l4_kernel_info_mem_desc_t *md) L4_NOTHROW +{ + return md->h | 0x3ffUL; +} + +L4_INLINE +l4_umword_t +l4_kernel_info_get_mem_desc_type(l4_kernel_info_mem_desc_t *md) L4_NOTHROW +{ + return md->l & 0xf; +} + +L4_INLINE +l4_umword_t +l4_kernel_info_get_mem_desc_subtype(l4_kernel_info_mem_desc_t *md) L4_NOTHROW +{ + return (md->l & 0xf0) >> 4; +} + +L4_INLINE +l4_umword_t +l4_kernel_info_get_mem_desc_is_virtual(l4_kernel_info_mem_desc_t *md) L4_NOTHROW +{ + return md->l & 0x200; +} + +#endif /* ! __L4SYS__MEMDESC_H__ */ diff --git a/l4/pkg/l4sys/include/meta b/l4/pkg/l4sys/include/meta new file mode 100644 index 00000000..b1f21a7c --- /dev/null +++ b/l4/pkg/l4sys/include/meta @@ -0,0 +1,117 @@ +// vi:ft=cpp +/** + * \file + * \brief Meta interface for getting dynamic type information + * about objects behind capabilities. + * \ingroup l4_api + */ +/* + * (c) 2008-2009 Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ + +#pragma once + +#include + +namespace L4 { +/** + * \addtogroup l4_kernel_object_api + */ +/*@{*/ + +/** + * \brief Meta interface that shall be implemented by each L4Re object + * and gives access to the dynamic type information for + * L4Re objects. + */ +class Meta : public Kobject_t +{ + L4_KOBJECT(Meta) + +public: + enum Op + { + O_num_ifaces = 0, + O_iface = 1, + O_supports = 2, + }; + + /** + * \brief Get the number of interfaces implemented by this object. + * \param utcb is the utcb to use for sending the message. + * \return The message tag for the operation, the label (l4_msgtag_t::label()) + * is set to the number of interfaces if successful, or to -error + * when an error occured. + */ + l4_msgtag_t num_interfaces(l4_utcb_t *utcb = l4_utcb()) throw(); + + /** + * \brief Get the protocol number that must be used for the interface with + * the index \a idx. + * \param idx is the index of the interface to get the protocol number for. + * \a idx must be \>= 0 and \< the return value of + * num_interfaces(). + * \param utcb is the utcb to use for sending the message. + * \return The message tag for the operation, the label (l4_msgtag_t::label()) + * is set to the protocol number of interface \a idx. + */ + l4_msgtag_t interface(int idx, l4_utcb_t *u = l4_utcb()) throw(); + /** + * \brief Figure out if the object supports the given \a protocol (number). + * \param protocol is the protocol number to check for. + * \param utcb is the utcb to use for sending the message. + * \return The message tag for the operation, the label (l4_msgtag_t::label()) + * is set to 1 if \a protocol is supported to 0 if not. + * + * This method is intended to be used for statically assigned protocol + * numbers. + */ + l4_msgtag_t supports(long protocol, l4_utcb_t *u = l4_utcb()) throw(); +}; + +/*@}*/ + +inline l4_msgtag_t +Meta::num_interfaces(l4_utcb_t *u) throw() +{ + l4_msg_regs_t *mr = l4_utcb_mr_u(u); + mr->mr[0] = O_num_ifaces; + return l4_ipc_call(cap(), u, l4_msgtag(Protocol, 1, 0, 0), + L4_IPC_NEVER); +} + +inline l4_msgtag_t +Meta::interface(int idx, l4_utcb_t *u) throw() +{ + l4_msg_regs_t *mr = l4_utcb_mr_u(u); + mr->mr[0] = O_iface; + mr->mr[1] = idx; + return l4_ipc_call(cap(), u, l4_msgtag(Protocol, 2, 0, 0), + L4_IPC_NEVER); +} + +inline l4_msgtag_t +Meta::supports(long protocol, l4_utcb_t *u) throw() +{ + l4_msg_regs_t *mr = l4_utcb_mr_u(u); + mr->mr[0] = O_supports; + mr->mr[1] = protocol; + return l4_ipc_call(cap(), u, l4_msgtag(Protocol, 2, 0, 0), + L4_IPC_NEVER); +} + +} diff --git a/l4/pkg/l4sys/include/scheduler b/l4/pkg/l4sys/include/scheduler new file mode 100644 index 00000000..979158c6 --- /dev/null +++ b/l4/pkg/l4sys/include/scheduler @@ -0,0 +1,79 @@ +// vi:ft=cpp +/** + * \file + * \brief Scheduler object functions. + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#pragma once + +#include +#include +#include + +namespace L4 { + +/** + * \brief Scheduler object. + * \ingroup l4_obj_api + * + * \#include + * + * \see \ref l4_scheduler_api for an overview description. + * + */ +class Scheduler : public Kobject_t +{ + L4_KOBJECT(Scheduler) + +public: + /** + * \copydoc l4_scheduler_info() + * \note \a scheduler is the implicit \a this pointer. + */ + l4_msgtag_t info(l4_umword_t *cpu_max, l4_sched_cpu_set_t *cpus, + l4_utcb_t *utcb = l4_utcb()) const throw() + { return l4_scheduler_info_u(cap(), cpu_max, cpus, utcb); } + + /** + * \copydoc l4_scheduler_run_thread() + * \note \a scheduler is the implicit \a this pointer. + */ + l4_msgtag_t run_thread(Cap const &thread, + l4_sched_param_t const &sp, + l4_utcb_t *utcb = l4_utcb()) const throw() + { return l4_scheduler_run_thread_u(cap(), thread.cap(), &sp, utcb); } + + /** + * \copydoc l4_scheduler_idle_time() + * \note \a scheduler is the implicit \a this pointer. + */ + l4_msgtag_t idle_time(l4_sched_cpu_set_t const &cpus, + l4_utcb_t *utcb = l4_utcb()) const throw() + { return l4_scheduler_idle_time_u(cap(), &cpus, utcb); } + + + /** + * \copydoc l4_scheduler_is_online() + * \note \a scheduler is the implicit \a this pointer. + */ + bool is_online(l4_umword_t cpu, l4_utcb_t *utcb = l4_utcb()) const throw() + { return l4_scheduler_is_online_u(cap(), cpu, utcb); } +}; +} diff --git a/l4/pkg/l4sys/include/scheduler.h b/l4/pkg/l4sys/include/scheduler.h new file mode 100644 index 00000000..555937c1 --- /dev/null +++ b/l4/pkg/l4sys/include/scheduler.h @@ -0,0 +1,307 @@ +/** + * \file + * \brief Scheduler object functions. + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#pragma once + +#include +#include + +/** + * \defgroup l4_scheduler_api Scheduler + * \ingroup l4_kernel_object_api + * \brief Scheduler object. + * + * \#include + */ + +/** + * \brief CPU sets. + * \ingroup l4_scheduler_api + */ +typedef struct l4_sched_cpu_set_t +{ + /** + * First CPU of interest (must be aligned to 2^granularity). + */ + l4_umword_t offset; + + /** + * Bitmap of online CPUs. + */ + l4_umword_t map; + + /** + * One bit in map represents 2^granularity CPUs. + */ + unsigned char granularity; + +} l4_sched_cpu_set_t; + +/** + * \brief + * \ingroup l4_scheduler_api + * + * \param offset Offset. + * \param granularity Granularitry in log2 notation. + * \param map Bitmap of CPUs, defaults to 1 in C++. + * + * \return CPU set. + */ +L4_INLINE l4_sched_cpu_set_t +l4_sched_cpu_set(l4_umword_t offset, unsigned char granularity, + l4_umword_t map L4_DEFAULT_PARAM(1)) L4_NOTHROW; + +/** + * \brief Get scheduler information. + * \ingroup l4_scheduler_api + * + * \param scheduler Scheduler object. + * \retval cpu_max maximum number of CPUs ever available. + * \param cpus \a cpus.offset is first CPU of interest. + * \a cpus.granularity (see l4_sched_cpu_set_t). + * \retval cpus \a cpus.map Bitmap of online CPUs. + * + * \return 0 on success, <0 error code otherwise. + */ +L4_INLINE l4_msgtag_t +l4_scheduler_info(l4_cap_idx_t scheduler, l4_umword_t *cpu_max, + l4_sched_cpu_set_t *cpus) L4_NOTHROW; + +/** + * \internal + */ +L4_INLINE l4_msgtag_t +l4_scheduler_info_u(l4_cap_idx_t scheduler, l4_umword_t *cpu_max, + l4_sched_cpu_set_t *cpus, l4_utcb_t *utcb) L4_NOTHROW; + + +/** + * \brief Scheduler parameter set. + * \ingroup l4_scheduler_api + */ +typedef struct l4_sched_param_t +{ + l4_cpu_time_t quantum; ///< Timeslice in micro seconds. + unsigned prio; ///< Priority for scheduling. + l4_sched_cpu_set_t affinity; ///< CPU affinity. +} l4_sched_param_t; + +/** + * \brief Construct scheduler parameter. + * \ingroup l4_scheduler_api + */ +L4_INLINE l4_sched_param_t +l4_sched_param(unsigned prio, + l4_cpu_time_t quantum L4_DEFAULT_PARAM(0)) L4_NOTHROW; + +/** + * \brief Run a thread on a Scheduler. + * \ingroup l4_scheduler_api + * + * \param scheduler Scheduler object. + * \param thread Thread to run. + * \param sp Scheduling parameters. + * + * \return 0 on success, <0 error code otherwise. + */ +L4_INLINE l4_msgtag_t +l4_scheduler_run_thread(l4_cap_idx_t scheduler, + l4_cap_idx_t thread, l4_sched_param_t const *sp) L4_NOTHROW; + +/** + * \internal + */ +L4_INLINE l4_msgtag_t +l4_scheduler_run_thread_u(l4_cap_idx_t scheduler, l4_cap_idx_t thread, + l4_sched_param_t const *sp, l4_utcb_t *utcb) L4_NOTHROW; + +/** + * \brief Query idle time of a CPU, in µs. + * \ingroup l4_scheduler_api + * + * \param scheduler Scheduler object. + * \param cpus Set of CPUs to query. + * + * The consumed time is returned as l4_kernel_clock_t at UTCB message + * register 0. + */ +L4_INLINE l4_msgtag_t +l4_scheduler_idle_time(l4_cap_idx_t scheduler, l4_sched_cpu_set_t const *cpus) L4_NOTHROW; + +/** + * \internal + */ +L4_INLINE l4_msgtag_t +l4_scheduler_idle_time_u(l4_cap_idx_t scheduler, l4_sched_cpu_set_t const *cpus, + l4_utcb_t *utcb) L4_NOTHROW; + + + +/** + * \brief Query if a CPU is online. + * \ingroup l4_scheduler_api + * + * \param scheduler Scheduler object. + * \param cpu CPU number. + * \return true if online, false if not (or any other query error). + */ +L4_INLINE int +l4_scheduler_is_online(l4_cap_idx_t scheduler, l4_umword_t cpu) L4_NOTHROW; + +/** + * \internal + */ +L4_INLINE int +l4_scheduler_is_online_u(l4_cap_idx_t scheduler, l4_umword_t cpu, + l4_utcb_t *utcb) L4_NOTHROW; + + + +/** + * \brief Operations on the Scheduler object. + * \ingroup l4_scheduler_api + * \hideinitializer + * \internal + */ +enum L4_scheduler_ops +{ + L4_SCHEDULER_INFO_OP = 0UL, /**< Query infos about the scheduler */ + L4_SCHEDULER_RUN_THREAD_OP = 1UL, /**< Run a thread on this scheduler */ + L4_SCHEDULER_IDLE_TIME_OP = 2UL, /**< Query idle time for the scheduler */ +}; + +/*************** Implementations *******************/ + +L4_INLINE l4_sched_cpu_set_t +l4_sched_cpu_set(l4_umword_t offset, unsigned char granularity, + l4_umword_t map) L4_NOTHROW +{ + l4_sched_cpu_set_t cs; + cs.offset = offset; + cs.granularity = granularity; + cs.map = map; + return cs; +} + +L4_INLINE l4_sched_param_t +l4_sched_param(unsigned prio, l4_cpu_time_t quantum) L4_NOTHROW +{ + l4_sched_param_t sp; + sp.prio = prio; + sp.quantum = quantum; + sp.affinity = l4_sched_cpu_set(0, ~0, 1); + return sp; +} + + +L4_INLINE l4_msgtag_t +l4_scheduler_info_u(l4_cap_idx_t scheduler, l4_umword_t *cpu_max, + l4_sched_cpu_set_t *cpus, l4_utcb_t *utcb) L4_NOTHROW +{ + l4_msg_regs_t *m = l4_utcb_mr_u(utcb); + l4_msgtag_t res; + + m->mr[0] = L4_SCHEDULER_INFO_OP; + m->mr[1] = (cpus->granularity << 24) | cpus->offset; + + res = l4_ipc_call(scheduler, utcb, l4_msgtag(L4_PROTO_SCHEDULER, 2, 0, 0), L4_IPC_NEVER); + + if (l4_msgtag_has_error(res)) + return res; + + cpus->map = m->mr[0]; + + if (cpu_max) + *cpu_max = m->mr[1]; + + return res; +} + +L4_INLINE l4_msgtag_t +l4_scheduler_run_thread_u(l4_cap_idx_t scheduler, l4_cap_idx_t thread, + l4_sched_param_t const *sp, l4_utcb_t *utcb) L4_NOTHROW +{ + l4_msg_regs_t *m = l4_utcb_mr_u(utcb); + m->mr[0] = L4_SCHEDULER_RUN_THREAD_OP; + m->mr[1] = (sp->affinity.granularity << 24) | sp->affinity.offset; + m->mr[2] = sp->affinity.map; + m->mr[3] = sp->prio; + m->mr[4] = sp->quantum; + m->mr[5] = l4_map_obj_control(0, 0); + m->mr[6] = l4_obj_fpage(thread, 0, L4_FPAGE_RWX).raw; + + return l4_ipc_call(scheduler, utcb, l4_msgtag(L4_PROTO_SCHEDULER, 5, 1, 0), L4_IPC_NEVER); +} + +L4_INLINE l4_msgtag_t +l4_scheduler_idle_time_u(l4_cap_idx_t scheduler, l4_sched_cpu_set_t const *cpus, + l4_utcb_t *utcb) L4_NOTHROW +{ + l4_msg_regs_t *v = l4_utcb_mr_u(utcb); + v->mr[0] = L4_SCHEDULER_IDLE_TIME_OP; + v->mr[1] = (cpus->granularity << 24) | cpus->offset; + v->mr[2] = cpus->map; + return l4_ipc_call(scheduler, utcb, l4_msgtag(L4_PROTO_SCHEDULER, 3, 0, 0), L4_IPC_NEVER); +} + + +L4_INLINE int +l4_scheduler_is_online_u(l4_cap_idx_t scheduler, l4_umword_t cpu, + l4_utcb_t *utcb) L4_NOTHROW +{ + l4_sched_cpu_set_t s; + l4_msgtag_t r; + s.offset = cpu; + s.granularity = 0; + r = l4_scheduler_info_u(scheduler, NULL, &s, utcb); + if (l4_msgtag_has_error(r) || l4_msgtag_label(r) < 0) + return 0; + + return s.map & 1; +} + + +L4_INLINE l4_msgtag_t +l4_scheduler_info(l4_cap_idx_t scheduler, l4_umword_t *cpu_max, + l4_sched_cpu_set_t *cpus) L4_NOTHROW +{ + return l4_scheduler_info_u(scheduler, cpu_max, cpus, l4_utcb()); +} + +L4_INLINE l4_msgtag_t +l4_scheduler_run_thread(l4_cap_idx_t scheduler, + l4_cap_idx_t thread, l4_sched_param_t const *sp) L4_NOTHROW +{ + return l4_scheduler_run_thread_u(scheduler, thread, sp, l4_utcb()); +} + +L4_INLINE l4_msgtag_t +l4_scheduler_idle_time(l4_cap_idx_t scheduler, l4_sched_cpu_set_t const *cpus) L4_NOTHROW +{ + return l4_scheduler_idle_time_u(scheduler, cpus, l4_utcb()); +} + +L4_INLINE int +l4_scheduler_is_online(l4_cap_idx_t scheduler, l4_umword_t cpu) L4_NOTHROW +{ + return l4_scheduler_is_online_u(scheduler, cpu, l4_utcb()); +} diff --git a/l4/pkg/l4sys/include/smart_capability b/l4/pkg/l4sys/include/smart_capability new file mode 100644 index 00000000..16512684 --- /dev/null +++ b/l4/pkg/l4sys/include/smart_capability @@ -0,0 +1,178 @@ +// vim:set ft=cpp: +/** + * \file + * \brief L4::Capability class. + * + * \author Alexander Warg + * + */ +/* + * (c) 2008-2009 Author(s) + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#pragma once + +#include + +namespace L4 { + +/** + * \brief Smart capability class. + */ +template< typename T, typename SMART > +class Smart_cap : public Cap_base, private SMART +{ +public: + + SMART const &smart() const { return *this; } + + void _delete() + { + SMART::free(const_cast&>(*this)); + } + + Cap release() const + { + l4_cap_idx_t r = cap(); + SMART::invalidate(const_cast&>(*this)); + + return Cap(r); + } + + Smart_cap() : Cap_base(Invalid) {} + + /** + * \brief Internal Constructor, use to generate a capability from a \a this + * pointer. + * + * \attention This constructor is only useful to generate a capability + * from the \a this pointer of an objected that is an L4::Kobject. + * Do \em never use this constructor for something else! + * \param p The \a this pointer of the Kobject or derived object + */ + template< typename O > + Smart_cap(Cap const &p) throw() : Cap_base(p.cap()) + { register T* __t = ((O*)100); (void)__t; } + + template< typename O > + Smart_cap(Cap const &p, SMART const &smart) throw() + : Cap_base(p.cap()), SMART(smart) + { register T* __t = ((O*)100); (void)__t; } + + template< typename O > + Smart_cap(Smart_cap const &o) throw() + : Cap_base(SMART::copy(o)), SMART(o.smart()) + { register T* __t = ((O*)100); (void)__t; } + + Smart_cap(Smart_cap const &o) throw() + : Cap_base(SMART::copy(o)), SMART(o.smart()) + { } + + template< typename O > + Smart_cap(typename Cap::Cap_type cap) throw() : Cap_base(cap) + { register T* __t = ((O*)100); (void)__t; } + + void operator = (typename Cap::Cap_type cap) throw() + { + _delete(); + _c = cap; + } + + template< typename O > + void operator = (Smart_cap const &o) throw() + { + _delete(); + _c = this->SMART::copy(o).cap(); + this->SMART::operator = (o.smart()); + // return *this; + } + + Smart_cap const &operator = (Smart_cap const &o) throw() + { + if (&o == this) + return *this; + + _delete(); + _c = this->SMART::copy(o).cap(); + this->SMART::operator = (o.smart()); + return *this; + } + + /** + * \brief Member access of a \a T. + */ + Cap operator -> () const throw() { return Cap(_c); } + + Cap get() const throw() { return Cap(_c); } + + ~Smart_cap() { _delete(); } +}; + +template< typename T > +class Weak_cap : public Cap_base +{ +public: + Weak_cap() : Cap_base(Invalid) {} + + template< typename O > + Weak_cap(typename Cap::Cap_type t) : Cap_base(t) + { register T* __t = ((O*)100); (void)__t; } + + template< typename O, typename S > + Weak_cap(Smart_cap const &c) : Cap_base(c.cap()) + { register T* __t = ((O*)100); (void)__t; } + + Weak_cap(Weak_cap const &o) : Cap_base(o) {} + + template< typename O > + Weak_cap(Weak_cap const &o) : Cap_base(o) + { register T* __t = ((O*)100); (void)__t; } + +}; + +namespace Cap_traits { + template< typename T1, typename T2 > + struct Type { enum { Equal = false }; }; + + template< typename T1 > + struct Type { enum { Equal = true }; }; +}; + +/** + * \brief static_cast for capabilities. + */ +template< typename T, typename F, typename SMART > +inline +Smart_cap cap_cast(Smart_cap const &c) throw() +{ + (void)static_cast(reinterpret_cast(100)); + return Smart_cap(Cap(SMART::copy(c).cap())); +} + + +/** + * \brief reinterpret_cast for capabilities. + */ +template< typename T, typename F, typename SMART > +inline +Smart_cap cap_reinterpret_cast(Smart_cap const &c) throw() +{ + return Smart_cap(Cap(SMART::copy(c).cap())); +} + + +} + diff --git a/l4/pkg/l4sys/include/task b/l4/pkg/l4sys/include/task new file mode 100644 index 00000000..f9017c3d --- /dev/null +++ b/l4/pkg/l4sys/include/task @@ -0,0 +1,110 @@ +// vi:ft=cpp +/** + * \file + * \brief Common task related definitions. + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ + +#pragma once + +#include +#include + +namespace L4 { + +/** + * \brief An L4 Task. + * \ingroup l4_task_api + * + * \#include + * + * \see \ref l4_task_api for an overview description. + * + */ +class Task : public Kobject_t +{ + L4_KOBJECT(Task) + +public: + /** + * \copydoc l4_task_map() + * \note \a dst_task is the implicit \a this pointer. + */ + l4_msgtag_t map(Cap const &src_task, + l4_fpage_t const &snd_fpage, l4_addr_t snd_base, + l4_utcb_t *utcb = l4_utcb()) throw() + { return l4_task_map_u(cap(), src_task.cap(), snd_fpage, snd_base, utcb); } + + /** + * \copydoc l4_task_unmap() + * \note \a task is the implicit \a this pointer. + */ + l4_msgtag_t unmap(l4_fpage_t const &fpage, + l4_umword_t map_mask, + l4_utcb_t *utcb = l4_utcb()) throw() + { return l4_task_unmap_u(cap(), fpage, map_mask, utcb); } + + /** + * \copydoc l4_task_unmap_batch() + * \note \a task is the implicit \a this pointer. + */ + l4_msgtag_t unmap_batch(l4_fpage_t const *fpages, + unsigned num_fpages, + l4_umword_t map_mask, + l4_utcb_t *utcb = l4_utcb()) throw() + { return l4_task_unmap_batch_u(cap(), fpages, num_fpages, map_mask, utcb); } + + /** + * \copydoc l4_task_cap_valid() + * \note \a task is the implicit \a this pointer. + */ + l4_msgtag_t cap_valid(Cap const &cap, + l4_utcb_t *utcb = l4_utcb()) throw() + { return l4_task_cap_valid_u(this->cap(), cap.cap(), utcb); } + + /** + * \copydoc l4_task_cap_has_child() + * \note \a task is the implicit \a this pointer. + */ + l4_msgtag_t cap_has_child(Cap const &cap, + l4_utcb_t *utcb = l4_utcb()) throw() + { return l4_task_cap_has_child_u(this->cap(), cap.cap(), utcb); } + + /** + * \copydoc l4_task_cap_equal() + * \note \a task is the implicit \a this pointer. + */ + l4_msgtag_t cap_equal(Cap const &cap_a, + Cap const &cap_b, + l4_utcb_t *utcb = l4_utcb()) throw() + { return l4_task_cap_equal_u(cap(), cap_a.cap(), cap_b.cap(), utcb); } + + /** + * \copydoc l4_task_add_ku_mem() + * \note \a task is the implicit \a this pointer. + */ + l4_msgtag_t add_ku_mem(l4_fpage_t const &fpage, + l4_utcb_t *utcb = l4_utcb()) throw() + { return l4_task_add_ku_mem_u(cap(), fpage, utcb); } + +}; +} + + diff --git a/l4/pkg/l4sys/include/task.h b/l4/pkg/l4sys/include/task.h new file mode 100644 index 00000000..fc842cd0 --- /dev/null +++ b/l4/pkg/l4sys/include/task.h @@ -0,0 +1,355 @@ +/** + * \file + * \brief Common task related definitions. + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg , + * Björn Döbel , + * Torsten Frenzel + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#pragma once +#include +#include + +/** + * \defgroup l4_task_api Task + * \ingroup l4_kernel_object_api + * \brief Class definition of the Task kernel object. + * + * \#include + * + * The L4 task class represents a combination of the address spaces provided + * by the L4 micro kernel. A task consists of at least a memory address space + * and an object address space. On IA32 there is also an IO-port address space. + * + * A task object can be created using a Factory, see \ref l4_factory_api + * (l4_factory_create_task()). + */ + +/** + * \brief Map resources available in the source task to a destination task. + * \ingroup l4_task_api + * + * \param dst_task Capability selector of destination task + * \param src_task Capability selector of source task + * \param snd_fpage Send flexpage that describes an area in the + * address space or object space of the source task + * \param snd_base Send base that describes an offset in the receive + * window of the destination task. + * + * \return Syscall return tag + * + * This method allows for asynchronous rights delegation from one task to + * another. It can be used to share memory as well as to delegate access to + * objects. + */ +L4_INLINE l4_msgtag_t +l4_task_map(l4_cap_idx_t dst_task, l4_cap_idx_t src_task, + l4_fpage_t const snd_fpage, l4_addr_t snd_base) L4_NOTHROW; + +/** + * \internal + */ +L4_INLINE l4_msgtag_t +l4_task_map_u(l4_cap_idx_t dst_task, l4_cap_idx_t src_task, + l4_fpage_t const snd_fpage, l4_addr_t snd_base, l4_utcb_t *utcb) L4_NOTHROW; + +/** + * \brief Revoke rights from the task. + * \ingroup l4_task_api + * + * \param task Capability selector of destination task + * \param fpage Flexpage that describes an area in the address space or + * object space of the destination task + * \param map_mask Unmap mask, see #l4_unmap_flags_t + * + * \return Syscall return tag + * + * This method allows to revoke rights from the destination task and from all the + * tasks that got the rights delegated from that task (i.e., this operation + * does a recursive rights revocation). + * + * \note Calling this function on the object space can cause a root capability + * of an object to be destructed, which destroys the object itself. + */ +L4_INLINE l4_msgtag_t +l4_task_unmap(l4_cap_idx_t task, l4_fpage_t const fpage, + l4_umword_t map_mask) L4_NOTHROW; + +/** + * \internal + */ +L4_INLINE l4_msgtag_t +l4_task_unmap_u(l4_cap_idx_t task, l4_fpage_t const fpage, + l4_umword_t map_mask, l4_utcb_t *utcb) L4_NOTHROW; + +/** + * \brief Revoke rights from a task. + * \ingroup l4_task_api + * + * \param task Capability selector of destination task + * \param fpages An array of flexpages that describes an area in the + * address space or object space of the destination task each + * \param num_fpages The size of the fpages array in elements (number of + * fpages sent). + * \param map_mask Unmap mask, see #l4_unmap_flags_t + * + * \return Syscall return tag + * + * This method allows to revoke rights from the destination task and from all the + * tasks that got the rights delegated from that task (i.e., this operation + * does a recursive rights revocation). + * + * \pre The caller needs to take care that num_fpages is not bigger + * than L4_UTCB_GENERIC_DATA_SIZE - 2. + * + * \note Calling this function on the object space can cause a root capability + * of an object to be destructed, which destroys the object itself. + */ +L4_INLINE l4_msgtag_t +l4_task_unmap_batch(l4_cap_idx_t task, l4_fpage_t const *fpages, + unsigned num_fpages, unsigned long map_mask) L4_NOTHROW; + +/** + * \internal + */ +L4_INLINE l4_msgtag_t +l4_task_unmap_batch_u(l4_cap_idx_t task, l4_fpage_t const *fpages, + unsigned num_fpages, unsigned long map_mask, + l4_utcb_t *u) L4_NOTHROW; +/** + * \brief Test whether a capability selector points to a valid capability. + * \ingroup l4_task_api + * + * \param task Capability selector of the destination task to do the + * lookup in + * \param cap Capability selector to look up in the destination task + * \return label contains 1 if valid, 0 if invalid + */ +L4_INLINE l4_msgtag_t +l4_task_cap_valid(l4_cap_idx_t task, l4_cap_idx_t cap) L4_NOTHROW; + +/** + * \internal + */ +L4_INLINE l4_msgtag_t +l4_task_cap_valid_u(l4_cap_idx_t task, l4_cap_idx_t cap, l4_utcb_t *utcb) L4_NOTHROW; + +/** + * \brief Test whether a capability has child mappings (in another task). + * \ingroup l4_task_api + * + * \param task Capability selector of the destination task to do the + * lookup in + * \param cap Capability selector to look up in the destination task + * \return label contains 1 if it has at least one child, 0 if not or invalid + */ +L4_INLINE l4_msgtag_t +l4_task_cap_has_child(l4_cap_idx_t task, l4_cap_idx_t cap) L4_NOTHROW; + +/** + * \internal + */ +L4_INLINE l4_msgtag_t +l4_task_cap_has_child_u(l4_cap_idx_t task, l4_cap_idx_t cap, l4_utcb_t *utcb) L4_NOTHROW; + +/** + * \brief Test whether two capabilities point to the same object with the same rights. + * \ingroup l4_task_api + * + * \param task Capability selector of the destination task to do the + * lookup in + * \param cap_a Capability selector to compare + * \param cap_b Capability selector to compare + * + * \return label contains 1 if equal, 0 if not equal + */ +L4_INLINE l4_msgtag_t +l4_task_cap_equal(l4_cap_idx_t task, l4_cap_idx_t cap_a, + l4_cap_idx_t cap_b) L4_NOTHROW; + +/** + * \internal + */ +L4_INLINE l4_msgtag_t +l4_task_add_ku_mem_u(l4_cap_idx_t task, l4_fpage_t const ku_mem, + l4_utcb_t *u) L4_NOTHROW; + +/** + * \brief Add kernel-user memory. + * \ingroup l4_task_api + * + * \param task Capability selector of the task to add the memory to + * \param ku_mem Flexpage describing the virtual area the memory goes to. + * + * \return Syscall return tag + */ +L4_INLINE l4_msgtag_t +l4_task_add_ku_mem(l4_cap_idx_t task, l4_fpage_t const ku_mem) L4_NOTHROW; + + +/** + * \internal + */ +L4_INLINE l4_msgtag_t +l4_task_cap_equal_u(l4_cap_idx_t task, l4_cap_idx_t cap_a, + l4_cap_idx_t cap_b, l4_utcb_t *utcb) L4_NOTHROW; + +/** + * \internal + * \brief Operations on task objects. + * \ingroup l4_task_api + */ +enum L4_task_ops +{ + L4_TASK_MAP_OP = 0UL, /**< Map */ + L4_TASK_UNMAP_OP = 1UL, /**< Unmap */ + L4_TASK_CAP_INFO_OP = 2UL, /**< Cap info */ + L4_TASK_ADD_KU_MEM_OP = 3UL, /**< Add kernel-user memory */ + L4_TASK_LDT_SET_X86_OP = 0x11UL, /**< x86: LDT set */ +}; + + +/* IMPLEMENTATION -----------------------------------------------------------*/ + +#include + + +L4_INLINE l4_msgtag_t +l4_task_map_u(l4_cap_idx_t dst_task, l4_cap_idx_t src_task, + l4_fpage_t const snd_fpage, unsigned long snd_base, l4_utcb_t *u) L4_NOTHROW +{ + l4_msg_regs_t *v = l4_utcb_mr_u(u); + v->mr[0] = L4_TASK_MAP_OP; + v->mr[3] = l4_map_obj_control(0,0); + v->mr[4] = l4_obj_fpage(src_task, 0, L4_FPAGE_RWX).raw; + v->mr[1] = snd_base; + v->mr[2] = snd_fpage.raw; + return l4_ipc_call(dst_task, u, l4_msgtag(L4_PROTO_TASK, 3, 1, 0), L4_IPC_NEVER); +} + +L4_INLINE l4_msgtag_t +l4_task_unmap_u(l4_cap_idx_t task, l4_fpage_t const fpage, + unsigned long map_mask, l4_utcb_t *u) L4_NOTHROW +{ + l4_msg_regs_t *v = l4_utcb_mr_u(u); + v->mr[0] = L4_TASK_UNMAP_OP; + v->mr[1] = map_mask; + v->mr[2] = fpage.raw; + return l4_ipc_call(task, u, l4_msgtag(L4_PROTO_TASK, 3, 0, 0), L4_IPC_NEVER); +} + +L4_INLINE l4_msgtag_t +l4_task_unmap_batch_u(l4_cap_idx_t task, l4_fpage_t const *fpages, + unsigned num_fpages, unsigned long map_mask, + l4_utcb_t *u) L4_NOTHROW +{ + l4_msg_regs_t *v = l4_utcb_mr_u(u); + v->mr[0] = L4_TASK_UNMAP_OP; + v->mr[1] = map_mask; + __builtin_memcpy(&v->mr[2], fpages, num_fpages * sizeof(l4_fpage_t)); + return l4_ipc_call(task, u, l4_msgtag(L4_PROTO_TASK, 2 + num_fpages, 0, 0), L4_IPC_NEVER); +} + +L4_INLINE l4_msgtag_t +l4_task_cap_valid_u(l4_cap_idx_t task, l4_cap_idx_t cap, l4_utcb_t *u) L4_NOTHROW +{ + l4_msg_regs_t *v = l4_utcb_mr_u(u); + v->mr[0] = L4_TASK_CAP_INFO_OP; + v->mr[1] = cap & ~1UL; + return l4_ipc_call(task, u, l4_msgtag(L4_PROTO_TASK, 2, 0, 0), L4_IPC_NEVER); +} + +L4_INLINE l4_msgtag_t +l4_task_cap_has_child_u(l4_cap_idx_t task, l4_cap_idx_t cap, l4_utcb_t *u) L4_NOTHROW +{ + l4_msg_regs_t *v = l4_utcb_mr_u(u); + v->mr[0] = L4_TASK_CAP_INFO_OP; + v->mr[1] = cap | 1UL; + return l4_ipc_call(task, u, l4_msgtag(L4_PROTO_TASK, 2, 0, 0), L4_IPC_NEVER); +} + +L4_INLINE l4_msgtag_t +l4_task_cap_equal_u(l4_cap_idx_t task, l4_cap_idx_t cap_a, + l4_cap_idx_t cap_b, l4_utcb_t *u) L4_NOTHROW +{ + l4_msg_regs_t *v = l4_utcb_mr_u(u); + v->mr[0] = L4_TASK_CAP_INFO_OP; + v->mr[1] = cap_a; + v->mr[2] = cap_b; + return l4_ipc_call(task, u, l4_msgtag(L4_PROTO_TASK, 3, 0, 0), L4_IPC_NEVER); +} + +L4_INLINE l4_msgtag_t +l4_task_add_ku_mem_u(l4_cap_idx_t task, l4_fpage_t const ku_mem, + l4_utcb_t *u) L4_NOTHROW +{ + l4_msg_regs_t *v = l4_utcb_mr_u(u); + v->mr[0] = L4_TASK_ADD_KU_MEM_OP; + v->mr[1] = ku_mem.raw; + return l4_ipc_call(task, u, l4_msgtag(L4_PROTO_TASK, 2, 0, 0), L4_IPC_NEVER); +} + + + +L4_INLINE l4_msgtag_t +l4_task_map(l4_cap_idx_t dst_task, l4_cap_idx_t src_task, + l4_fpage_t const snd_fpage, unsigned long snd_base) L4_NOTHROW +{ + return l4_task_map_u(dst_task, src_task, snd_fpage, snd_base, l4_utcb()); +} + +L4_INLINE l4_msgtag_t +l4_task_unmap(l4_cap_idx_t task, l4_fpage_t const fpage, + unsigned long map_mask) L4_NOTHROW +{ + return l4_task_unmap_u(task, fpage, map_mask, l4_utcb()); +} + +L4_INLINE l4_msgtag_t +l4_task_unmap_batch(l4_cap_idx_t task, l4_fpage_t const *fpages, + unsigned num_fpages, unsigned long map_mask) L4_NOTHROW +{ + return l4_task_unmap_batch_u(task, fpages, num_fpages, map_mask, + l4_utcb()); +} + +L4_INLINE l4_msgtag_t +l4_task_cap_valid(l4_cap_idx_t task, l4_cap_idx_t cap) L4_NOTHROW +{ + return l4_task_cap_valid_u(task, cap, l4_utcb()); +} + +L4_INLINE l4_msgtag_t +l4_task_cap_has_child(l4_cap_idx_t task, l4_cap_idx_t cap) L4_NOTHROW +{ + return l4_task_cap_has_child_u(task, cap, l4_utcb()); +} + +L4_INLINE l4_msgtag_t +l4_task_cap_equal(l4_cap_idx_t task, l4_cap_idx_t cap_a, + l4_cap_idx_t cap_b) L4_NOTHROW +{ + return l4_task_cap_equal_u(task, cap_a, cap_b, l4_utcb()); +} + +L4_INLINE l4_msgtag_t +l4_task_add_ku_mem(l4_cap_idx_t task, l4_fpage_t const ku_mem) L4_NOTHROW +{ + return l4_task_add_ku_mem_u(task, ku_mem, l4_utcb()); +} diff --git a/l4/pkg/l4sys/include/thread b/l4/pkg/l4sys/include/thread new file mode 100644 index 00000000..615e6817 --- /dev/null +++ b/l4/pkg/l4sys/include/thread @@ -0,0 +1,275 @@ +// vi:ft=cpp +/** + * \file + * \brief Common thread related definitions. + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ + +#pragma once + +#include +#include + +namespace L4 { + +/** + * \ingroup l4_thread_api + * \brief L4 kernel thread. + * + * \#include + */ +class Thread : public Kobject_t +{ + L4_KOBJECT(Thread) + +public: + /** + * \copydoc l4_thread_ex_regs() + * \note the \a thread argument is the implicit \a this pointer. + */ + l4_msgtag_t ex_regs(l4_addr_t ip, l4_addr_t sp, + l4_umword_t flags, + l4_utcb_t *utcb = l4_utcb()) throw() + { return l4_thread_ex_regs_u(cap(), ip, sp, flags, utcb); } + + /** + * \copydoc l4_thread_ex_regs_ret() + * \note the \a thread argument is the implicit \a this pointer. + */ + l4_msgtag_t ex_regs(l4_addr_t *ip, l4_addr_t *sp, + l4_umword_t *flags, + l4_utcb_t *utcb = l4_utcb()) throw() + { return l4_thread_ex_regs_ret_u(cap(), ip, sp, flags, utcb); } + + + /** + * \brief Thread attributes used for control_commit(). + * + * This class is responsible for initalizing various attributes of a + * thread in a UTCB for the control_commit() method. + * + * \see \ref l4_thread_control_api for some more details. + */ + class Attr + { + private: + friend class L4::Thread; + l4_utcb_t *_u; + + public: + /** + * \brief Create a thread-attribute object with the given UTCB. + * \param utcb the UTCB to use for the later L4::Thread::control_commit() + * function. Usually this is the UTCB of the calling thread. + */ + explicit Attr(l4_utcb_t *utcb = l4_utcb()) throw() : _u(utcb) + { l4_thread_control_start_u(utcb); } + + /** + * \brief Set the pager capability selector. + * \param pager the capability selector that shall be used for page-fault + * messages. This capability selector must be valid within + * the task the thread is bound to. + */ + void pager(Cap const &pager) throw() + { l4_thread_control_pager_u(pager.cap(), _u); } + + /** + * \brief Get the capability selector used for page-fault messages. + * \return the capability selector used to send page-fault messages. The + * selector is valid in the task the thread is bound to. + */ + Cap pager() throw() + { return Cap(l4_utcb_mr_u(_u)->mr[1]); } + + /** + * \brief Set the exception-handler capability selector. + * \param pager the capability selector that shall be used for exception + * messages. This capability selector must be + * valid within the task the thread is bound to. + */ + void exc_handler(Cap const &exc_handler) throw() + { l4_thread_control_exc_handler_u(exc_handler.cap(), _u); } + + /** + * \brief Get the capability selector used for exception messages. + * \return the capability selector used to send exception messages. The + * selector is valid in the task the thread is bound to. + */ + Cap exc_handler() throw() + { return Cap(l4_utcb_mr_u(_u)->mr[2]); } + + /** + * \brief Bind the thread to a task. + * \param thread_utcb the UTCB address of the thread within the task + * specified by \a task. + * \param task the capability selector for the task the thread + * shall be bound to. + * + * Binding a thread to a task means that the thread shall afterwards + * execute in the given task. To actually start execution you need + * to use L4::Thread::ex_regs(). + */ + void bind(l4_utcb_t *thread_utcb, Cap const &task) throw() + { l4_thread_control_bind_u(thread_utcb, task.cap(), _u); } + + /** + * \brief Set the thread to alien mode. + */ + void alien(int on) throw() + { l4_thread_control_alien_u(_u, on); } + + /** + * \brief Allow host system calls on Fiasco-UX. + * \pre Running on Fiasco-UX. + */ + void ux_host_syscall(int on) throw() + { l4_thread_control_ux_host_syscall_u(_u, on); } + + }; + + /** + * \brief Commit the given thread-attributes object. + * \param attr the attribute object to commit to the thread. + */ + l4_msgtag_t control(Attr const &attr) throw() + { return l4_thread_control_commit_u(cap(), attr._u); } + + /** + * \brief Switch execution to this thread. + * \param utcb the UTCB of the current thread. + * + * \note The current time slice is inherited to this thread. + */ + l4_msgtag_t switch_to(l4_utcb_t *utcb = l4_utcb()) throw() + { return l4_thread_switch_u(cap(), utcb); } + + /** + * \brief Get consumed timed of thread in ns. + * \param utcb the UTCB of the current thread. + * + * The consumed time is return as l4_kernel_clock_t at UTCB message + * register 0. + */ + l4_msgtag_t stats_time(l4_utcb_t *utcb = l4_utcb()) throw() + { return l4_thread_stats_time_u(cap(), utcb); } + + /** + * \brief vCPU resume, start. + * + * \see l4_thread_vcpu_resume_start + */ + l4_msgtag_t vcpu_resume_start(l4_utcb_t *utcb = l4_utcb()) throw() + { return l4_thread_vcpu_resume_start_u(utcb); } + + /** + * \brief vCPU resume, commit. + * + * \see l4_thread_vcpu_resume_commit + */ + l4_msgtag_t vcpu_resume_commit(l4_msgtag_t tag, + l4_utcb_t *utcb = l4_utcb()) throw() + { return l4_thread_vcpu_resume_commit_u(cap(), tag, utcb); } + + /** + * \copydoc l4_thread_vcpu_control() + */ + l4_msgtag_t vcpu_control(l4_addr_t vcpu_state, l4_utcb_t *utcb = l4_utcb()) + throw() + { return l4_thread_vcpu_control_u(cap(), vcpu_state, utcb); } + + /** + * \copydoc l4_thread_vcpu_control_ext() + */ + l4_msgtag_t vcpu_control_ext(l4_addr_t ext_vcpu_state, + l4_utcb_t *utcb = l4_utcb()) throw() + { return l4_thread_vcpu_control_ext_u(cap(), ext_vcpu_state, utcb); } + + /** + * \brief Register an IRQ that will trigger upon deletion events. + * + * \see l4_thread_register_del_irq + */ + l4_msgtag_t register_del_irq(Cap irq, l4_utcb_t *u = l4_utcb()) throw() + { return l4_thread_register_del_irq_u(cap(), irq.cap(), u); } + + /** + * \brief Wrapper class for modifying senders. + * + * Use the add() function to add modification rules, and use + * modify_senders() to commit. Do not use the UTCB inbetween as it is + * used by add() and modify_senders(). + */ + class Modify_senders + { + private: + friend class Thread; + l4_utcb_t *utcb; + unsigned cnt; + + public: + explicit Modify_senders(l4_utcb_t *u = l4_utcb()) throw() + : utcb(u), cnt(1) + { + l4_utcb_mr_u(utcb)->mr[0] = L4_THREAD_MODIFY_SENDER_OP; + } + + /** + * \brief Add a rule. + * + * \param match_mask Bitmask of bits to match the label. + * \param match Bitmask that must be equal to the label after applying + * match_mask. + * \param del_bits Bits to be deleted from the label. + * \param add_bits Bits to be added to the label. + * + * \return 0 on sucess, <0 on error + * + * Only the first match is applied. + * + * \see l4_thread_modify_sender_add() + */ + int add(l4_umword_t match_mask, l4_umword_t match, + l4_umword_t del_bits, l4_umword_t add_bits) throw() + { + l4_msg_regs_t *m = l4_utcb_mr_u(utcb); + if (cnt >= L4_UTCB_GENERIC_DATA_SIZE - 4) + return -L4_ENOMEM; + m->mr[cnt++] = match_mask; + m->mr[cnt++] = match; + m->mr[cnt++] = del_bits; + m->mr[cnt++] = add_bits; + return 0; + } + }; + + /** + * \brief Apply sender modifiction rules. + * + * \param todo Prepared sender modification rules. + * + * \return System call return tag. + */ + l4_msgtag_t modify_senders(Modify_senders const &todo) throw() + { + return l4_ipc_call(cap(), todo.utcb, l4_msgtag(L4_PROTO_THREAD, todo.cnt, 0, 0), L4_IPC_NEVER); + } +}; +} diff --git a/l4/pkg/l4sys/include/thread.h b/l4/pkg/l4sys/include/thread.h new file mode 100644 index 00000000..3fd8d60d --- /dev/null +++ b/l4/pkg/l4sys/include/thread.h @@ -0,0 +1,985 @@ +/** + * \file + * \brief Common thread related definitions. + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg , + * Björn Döbel , + * Torsten Frenzel + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#pragma once + +#include +#include +#include + +/** + * \defgroup l4_thread_api Thread + * \ingroup l4_kernel_object_api + * \brief Thread object. + * + * \#include + * + * The thread class defines a thread of execution in the L4 context. + * Usually user-level and kernel threads are mapped 1:1 to each other. + * Thread kernel object are created using a Factory, see \ref l4_factory_api + * (l4_factory_create_thread()). + * + * An L4 thread encapsulates: + * - CPU state + * - General-purpose registers + * - Program counter + * - Stack pointer + * - FPU state + * - Scheduling parameters + * - CPU-set + * - Priority (0-255) + * - Time slice length + * - Execution state + * - Blocked, Runnable, Running + * + * Thread objects provide an API for + * - Thread configuration and manipulation + * - Thread switching. + * + * The thread control functions are used to control various aspects of a + * thread. See l4_thread_control_start() for more information. + */ + + +/** + * \brief Exchange basic thread registers. + * \ingroup l4_thread_api + * + * \param thread Thread to manipulate + * \param ip New instruction pointer, use ~0UL to leave the + * instruction pointer unchanged + * \param sp New stack pointer, use ~0UL to leave the stack + * pointer unchanged + * \param flags Ex-regs flags, see #L4_thread_ex_regs_flags + * + * \return System call return tag + * + * This method allows to manipulate and start a thread. The basic + * functionality is to set the instruction pointer and the stack pointer of a + * thread. Additionally, this method allows also to cancel ongoing IPC + * operations and to force the thread to raise an artificial exception (see \a + * flags). + * + */ +L4_INLINE l4_msgtag_t +l4_thread_ex_regs(l4_cap_idx_t thread, l4_addr_t ip, l4_addr_t sp, + l4_umword_t flags) L4_NOTHROW; + +/** + * \internal + * \ingroup l4_thread_api + */ +L4_INLINE l4_msgtag_t +l4_thread_ex_regs_u(l4_cap_idx_t thread, l4_addr_t ip, l4_addr_t sp, + l4_umword_t flags, l4_utcb_t *utcb) L4_NOTHROW; + +/** + * \brief Exchange basic thread registers and return previous values. + * \ingroup l4_thread_api + * + * \param[in] thread Thread to manipulate + * \param[in,out] ip New instruction pointer, use ~0UL to leave the + * instruction pointer unchanged, return previous + * instruction pointer + * \param[in,out] sp New stack pointer, use ~0UL to leave the stack + * pointer unchanged, returns previous stack pointer + * \param[in,out] flags Ex-regs flags, see #L4_thread_ex_regs_flags, return + * previous CPU flags of the thread. + * + * \return System call return tag + * + * This method allows to manipulate and start a thread. The basic + * functionality is to set the instruction pointer and the stack pointer of a + * thread. Additionally, this method allows also to cancel ongoing IPC + * operations and to force the thread to raise an artificial exception (see \a + * flags). + * + * Returned values are valid only if function returns successfully. + */ +L4_INLINE l4_msgtag_t +l4_thread_ex_regs_ret(l4_cap_idx_t thread, l4_addr_t *ip, l4_addr_t *sp, + l4_umword_t *flags) L4_NOTHROW; + +/** + * \internal + * \ingroup l4_thread_api + */ +L4_INLINE l4_msgtag_t +l4_thread_ex_regs_ret_u(l4_cap_idx_t thread, l4_addr_t *ip, l4_addr_t *sp, + l4_umword_t *flags, l4_utcb_t *utcb) L4_NOTHROW; + + + +/** + * \defgroup l4_thread_control_api Thread control + * \ingroup l4_thread_api + * + * \brief API for Thread Control method. + * + * + * The thread control API provides access to almost any parameter of a thread + * object. The API is based on a single invocation of the thread object. + * However, because of the huge amount of parameters, the API provides a set + * of functions to set specific parameters of a thread and a commit function + * to commit the thread control call (see l4_thread_control_commit()). + * + * A thread control operation must always start with l4_thread_control_start() + * and be committed with l4_thread_control_commit(). All other thread control + * parameter setter functions must be called between these two functions. + * + * An example for a sequence of thread control API calls can be found below. + * + * l4_utcb_t *u = l4_utcb();
+ * \link l4_thread_control_start() l4_thread_control_start(u)\endlink;
+ * \link l4_thread_control_pager() l4_thread_control_pager(u, pager_cap)\endlink;
+ * \link l4_thread_control_bind() l4_thread_control_bind (u, thread_utcb, task)\endlink;
+ * \link l4_thread_control_commit() l4_thread_control_commit(u, thread_cap)\endlink;
+ * + */ + +/** + * \brief Start a thread control API sequence. + * \ingroup l4_thread_control_api + * + * This function starts a sequence of thread control API functions. + * After this functions any of following functions may be called in any order. + * - l4_thread_control_pager() + * - l4_thread_control_exc_handler() + * - l4_thread_control_bind() + * - l4_thread_control_alien() + * - l4_thread_control_ux_host_syscall() (Fiasco-UX only) + * + * To commit the changes to the thread l4_thread_control_commit() must be + * called in the end. + * + * \note The thread control API calls store the parameters for the thread in + * the UTCB of the caller, this means between l4_thread_control_start() + * and l4_thread_control_commit() no functions that modify the UTCB + * contents must be called. + */ +L4_INLINE void +l4_thread_control_start(void) L4_NOTHROW; + +/** + * \internal + * \ingroup l4_thread_control_api + */ +L4_INLINE void +l4_thread_control_start_u(l4_utcb_t *utcb) L4_NOTHROW; + +/** + * \brief Set the pager. + * \ingroup l4_thread_control_api + * + * \param pager Capability selector invoked to send a page-fault IPC. + * + * \note The pager capability selector is interpreted in the task the thread + * is bound to (executes in). + */ +L4_INLINE void +l4_thread_control_pager(l4_cap_idx_t pager) L4_NOTHROW; + +/** + * \internal + * \ingroup l4_thread_control_api + */ +L4_INLINE void +l4_thread_control_pager_u(l4_cap_idx_t pager, l4_utcb_t *utcb) L4_NOTHROW; + +/** + * \brief Set the exception handler. + * \ingroup l4_thread_control_api + * + * \param exc_handler Capability selector invoked to send an exception IPC. + * + * \note The exception-handler capability selector is interpreted in the task + * the thread is bound to (executes in). + */ +L4_INLINE void +l4_thread_control_exc_handler(l4_cap_idx_t exc_handler) L4_NOTHROW; + +/** + * \internal + * \ingroup l4_thread_control_api + */ +L4_INLINE void +l4_thread_control_exc_handler_u(l4_cap_idx_t exc_handler, + l4_utcb_t *utcb) L4_NOTHROW; + +/** + * \brief Bind the thread to a task. + * \ingroup l4_thread_control_api + * + * \param thread_utcb The address of the UTCB in the target task. + * \param task The target task of the thread. + * + * Binding a thread to a task has the effect that the thread + * afterwards executes code within that task and has access to the + * resources visible within that task. + * + * \note There should not be more than one thread use a UTCB to prevent + * data corruption. + * + */ +L4_INLINE void +l4_thread_control_bind(l4_utcb_t *thread_utcb, + l4_cap_idx_t task) L4_NOTHROW; + +/** + * \internal + * \ingroup l4_thread_control_api + */ +L4_INLINE void +l4_thread_control_bind_u(l4_utcb_t *thread_utcb, + l4_cap_idx_t task, l4_utcb_t *utcb) L4_NOTHROW; + +/** + * \brief Enable alien mode. + * \ingroup l4_thread_control_api + * \param on Boolean value defining the state of the feature. + * + * Alien mode means the thread is not allowed to invoke L4 kernel objects + * directly and it is also not allowed to allocate FPU state. All those + * operations result in an exception IPC that gets sent through the pager + * capability. The responsible pager can then selectively allow an object + * invocation or allocate FPU state for the thread. + * + * This feature can be used to attach a debugger to a thread and trace all + * object invocations. + */ +L4_INLINE void +l4_thread_control_alien(int on) L4_NOTHROW; + +/** + * \internal + * \ingroup l4_thread_control_api + */ +L4_INLINE void +l4_thread_control_alien_u(l4_utcb_t *utcb, int on) L4_NOTHROW; + +/** + * \brief Enable pass through of native host (Linux) system calls. + * \ingroup l4_thread_control_api + * \param on Boolean value defining the state of the feature. + * + * \pre Running on Fiasco-UX + * + * This enables the thread to do host system calls. This feature is only + * available in Fiasco-UX and ignored in other environments. + */ +L4_INLINE void +l4_thread_control_ux_host_syscall(int on) L4_NOTHROW; + +/** + * \internal + * \ingroup l4_thread_control_api + */ +L4_INLINE void +l4_thread_control_ux_host_syscall_u(l4_utcb_t *utcb, int on) L4_NOTHROW; + + + +/** + * \brief Commit the thread control parameters. + * \ingroup l4_thread_control_api + * + * \param thread Capability selector of target thread to commit to. + * \return system call return tag + */ +L4_INLINE l4_msgtag_t +l4_thread_control_commit(l4_cap_idx_t thread) L4_NOTHROW; + +/** + * \internal + * \ingroup l4_thread_control_api + */ +L4_INLINE l4_msgtag_t +l4_thread_control_commit_u(l4_cap_idx_t thread, l4_utcb_t *utcb) L4_NOTHROW; + +/** + * \brief Yield current time slice. + * \ingroup l4_thread_api + * + * \return system call return tag + */ +L4_INLINE l4_msgtag_t +l4_thread_yield(void) L4_NOTHROW; + +/** + * \brief Switch to another thread (and donate the remaining time slice). + * \ingroup l4_thread_api + * + * \param to_thread The thread to switch to. + * + * \return system call return tag + */ +L4_INLINE l4_msgtag_t +l4_thread_switch(l4_cap_idx_t to_thread) L4_NOTHROW; + +/** + * \internal + * \ingroup l4_thread_api + */ +L4_INLINE l4_msgtag_t +l4_thread_switch_u(l4_cap_idx_t to_thread, l4_utcb_t *utcb) L4_NOTHROW; + + + +/** + * \brief Get consumed timed of thread in µs. + * \ingroup l4_thread_api + * \param thread Thread to get the consumed time from. + * + * The consumed time is returned as l4_kernel_clock_t at UTCB message + * register 0. + */ +L4_INLINE l4_msgtag_t +l4_thread_stats_time(l4_cap_idx_t thread) L4_NOTHROW; + +/** + * \internal + * \ingroup l4_thread_api + */ +L4_INLINE l4_msgtag_t +l4_thread_stats_time_u(l4_cap_idx_t thread, l4_utcb_t *utcb) L4_NOTHROW; + + +/** + * \brief vCPU return from event handler. + * \ingroup l4_thread_api + * + * \return Message tag to be used for l4_sndfpage_add() and + * l4_thread_vcpu_commit() + * + * The vCPU resume functionality is split in multiple functions to allow the + * specification of additional send-flex-pages using l4_sndfpage_add(). + */ +L4_INLINE l4_msgtag_t +l4_thread_vcpu_resume_start(void) L4_NOTHROW; + +/** + * \internal + * \ingroup l4_thread_api + */ +L4_INLINE l4_msgtag_t +l4_thread_vcpu_resume_start_u(l4_utcb_t *utcb) L4_NOTHROW; + +/** + * \brief Commit vCPU resume. + * \ingroup l4_thread_api + * + * \param thread Thread to be resumed, using the invalid cap can be used + * for the current thread. + * \param tag Tag to use, returned by l4_thread_vcpu_resume_start() + * + * \return System call result message tag. In extended vCPU mode and when + * the virtual interrupts are cleared, the return code 1 flags an incoming + * IPC message, whereas 0 indicates a VM exit. + * + * To resume into another address space the capability to the target task + * must be set in the vCPU-state. The task needs to be set only once, + * consecutive resumes to the same address space should use an invalid + * capability. The kernel resets the field to #L4_INVALID_CAP. To release a + * task use a different task or use an invalid capability with + * the #L4_SYSF_REPLY flag set. + * + * \see l4_vcpu_state_t + */ +L4_INLINE l4_msgtag_t +l4_thread_vcpu_resume_commit(l4_cap_idx_t thread, + l4_msgtag_t tag) L4_NOTHROW; + +/** + * \internal + * \ingroup l4_thread_api + */ +L4_INLINE l4_msgtag_t +l4_thread_vcpu_resume_commit_u(l4_cap_idx_t thread, + l4_msgtag_t tag, l4_utcb_t *utcb) L4_NOTHROW; + + +/** + * \brief Enable or disable the vCPU feature for the thread. + * \ingroup l4_thread_api + * + * \param thread The thread for which the vCPU feature shall be enabled or + * disabled. + * \param vcpu_state The virtual address where the kernel shall store the vCPU + * state in case of vCPU exits. The address must be a valid + * kernel-user-memory address. + * \return Systemcall result message tag. + * + * This function enables the vCPU feature of the \a thread if \a vcpu_state + * is set to a valid kernel-user-memory address, or disables the vCPU feature + * if \a vcpu_state is 0. + * + */ +L4_INLINE l4_msgtag_t +l4_thread_vcpu_control(l4_cap_idx_t thread, l4_addr_t vcpu_state) L4_NOTHROW; + +/** + * \internal + * \ingroup l4_thread_api + */ +L4_INLINE l4_msgtag_t +l4_thread_vcpu_control_u(l4_cap_idx_t thread, l4_addr_t vcpu_state, + l4_utcb_t *utcb) L4_NOTHROW; + +/** + * \brief Enable or disable the extended vCPU feature for the thread. + * \ingroup l4_thread_api + * + * \param thread The thread for which the extended vCPU feature shall be + * enabled or disabled. + * \param vcpu_state The virtual address where the kernel shall store the vCPU + * state in case of vCPU exits. The address must be a valid + * kernel-user-memory address. + * \return Systemcall result message tag. + * + * The extended vCPU feature allows the use of hardware-virtualization + * features such as Intel's VT or AMD's SVM. + * + * This function enables the extended vCPU feature of the \a thread + * if \a vcpu_state is set to a valid kernel-user-memory address, or disables + * the vCPU feature if \a vcpu_state is 0. + * + */ +L4_INLINE l4_msgtag_t +l4_thread_vcpu_control_ext(l4_cap_idx_t thread, l4_addr_t ext_vcpu_state) L4_NOTHROW; + +/** + * \internal + * \ingroup l4_thread_api + */ +L4_INLINE l4_msgtag_t +l4_thread_vcpu_control_ext_u(l4_cap_idx_t thread, l4_addr_t ext_vcpu_state, + l4_utcb_t *utcb) L4_NOTHROW; + + +/** + * \brief Register an IRQ that will trigger upon deletion events. + * \ingroup l4_thread_api + * + * \param thread Thread to register IRQ for. + * \param irq Irq to register. + * + * \return System call result message tag. + */ +L4_INLINE l4_msgtag_t +l4_thread_register_del_irq(l4_cap_idx_t thread, l4_cap_idx_t irq) L4_NOTHROW; + +/** + * \internal + * \ingroup l4_thread_api + */ +L4_INLINE l4_msgtag_t +l4_thread_register_del_irq_u(l4_cap_idx_t thread, l4_cap_idx_t irq, + l4_utcb_t *utcb) L4_NOTHROW; + +/** + * \brief Start a thread sender modifiction sequence. + * \ingroup l4_thread_api + * + * Add modification rules with l4_thread_modify_sender_add() and commit with + * l4_thread_modify_sender_commit(). Do not touch the UTCB between + * l4_thread_modify_sender_start() and l4_thread_modify_sender_commit(). + * + * \see l4_thread_modify_sender_add + * \see l4_thread_modify_sender_commit + */ +L4_INLINE l4_msgtag_t +l4_thread_modify_sender_start(void) L4_NOTHROW; + +/** + * \internal + * \ingroup l4_thread_api + */ +L4_INLINE l4_msgtag_t +l4_thread_modify_sender_start_u(l4_utcb_t *u) L4_NOTHROW; + +/** + * \brief Add a modification pattern to a sender modification sequence. + * \ingroup l4_thread_api + * + * \param tag Tag received from l4_thread_modify_sender_start() or + * previous l4_thread_modify_sender_add() calls from + * the same sequence. + * \param match_mask Bitmask of bits to match the label. + * \param match Bitmask that must be equal to the label after applying + * match_mask. + * \param del_bits Bits to be deleted from the label. + * \param add_bits Bits to be added to the label. + * + * \return 0 on sucess, <0 on error + * + * In pseudo code: + * if ((sender_label & match_mask) == match) + * { label = (label & ~del_bits) | add_bits; } + * + * Only the first match is applied. + * + * \see l4_thread_modify_sender_start + * \see l4_thread_modify_sender_commit + */ +L4_INLINE int +l4_thread_modify_sender_add(l4_umword_t match_mask, + l4_umword_t match, + l4_umword_t del_bits, + l4_umword_t add_bits, + l4_msgtag_t *tag) L4_NOTHROW; + +/** + * \internal + * \ingroup l4_thread_api + */ +L4_INLINE int +l4_thread_modify_sender_add_u(l4_umword_t match_mask, + l4_umword_t match, + l4_umword_t del_bits, + l4_umword_t add_bits, + l4_msgtag_t *tag, l4_utcb_t *u) L4_NOTHROW; + +/** + * \brief Apply (commit) a sender modification sequence. + * \ingroup l4_thread_api + * + * \see l4_thread_modify_sender_start + * \see l4_thread_modify_sender_add + */ +L4_INLINE l4_msgtag_t +l4_thread_modify_sender_commit(l4_cap_idx_t thread, l4_msgtag_t tag) L4_NOTHROW; + +/** + * \internal + * \ingroup l4_thread_api + */ +L4_INLINE l4_msgtag_t +l4_thread_modify_sender_commit_u(l4_cap_idx_t thread, l4_msgtag_t tag, + l4_utcb_t *u) L4_NOTHROW; + +/** + * \brief Operations on thread objects. + * \ingroup l4_thread_api + * \hideinitializer + * \internal + */ +enum L4_thread_ops +{ + L4_THREAD_CONTROL_OP = 0UL, /**< Control operation */ + L4_THREAD_EX_REGS_OP = 1UL, /**< Exchange registers operation */ + L4_THREAD_SWITCH_OP = 2UL, /**< Do a thread switch */ + L4_THREAD_STATS_OP = 3UL, /**< Thread statistics */ + L4_THREAD_VCPU_RESUME_OP = 4UL, /**< VCPU resume */ + L4_THREAD_REGISTER_DELETE_IRQ_OP = 5UL, /**< Register an IPC-gate deletion IRQ */ + L4_THREAD_MODIFY_SENDER_OP = 6UL, /**< Modify all senders IDs that match the given pattern */ + L4_THREAD_VCPU_CONTROL_OP = 7UL, /**< Enable / disable VCPU feature */ + L4_THREAD_VCPU_CONTROL_EXT_OP = L4_THREAD_VCPU_CONTROL_OP | 0x10000, + L4_THREAD_GDT_X86_OP = 0x10UL, /**< Gdt */ + L4_THREAD_SET_FS_AMD64_OP = 0x12UL, /**< Set FS/TLS */ + L4_THREAD_OPCODE_MASK = 0xffff, /**< Mask for opcodes */ +}; + +/** + * \brief Flags for the thread control operation. + * \ingroup l4_thread_api + * \hideinitializer + * \internal + * + * Values for the enabled flags need to be given in their appropriate field + * in the UTCB, + * \see l4_thread_control + */ +enum L4_thread_control_flags +{ + /** The pager will be given. */ + L4_THREAD_CONTROL_SET_PAGER = 0x0010000, + /** The task to bind the thread to will be given. */ + L4_THREAD_CONTROL_BIND_TASK = 0x0200000, + /** Alien state of the thread is set. */ + L4_THREAD_CONTROL_ALIEN = 0x0400000, + /** Fiasco-UX only: pass-through of host system calls is set. */ + L4_THREAD_CONTROL_UX_NATIVE = 0x0800000, + /** The exception handler of the thread will be given. */ + L4_THREAD_CONTROL_SET_EXC_HANDLER = 0x1000000, +}; + +/** + * \brief Indices for the values in the message register for thread control. + * \ingroup l4_thread_api + * \hideinitializer + * \internal + * + * The values indicate the index in the message registers during + * thread-control operation. + */ +enum L4_thread_control_mr_indices +{ + L4_THREAD_CONTROL_MR_IDX_FLAGS = 0, /**< \see #L4_thread_control_flags. */ + L4_THREAD_CONTROL_MR_IDX_PAGER = 1, /**< Index for pager cap */ + L4_THREAD_CONTROL_MR_IDX_EXC_HANDLER = 2, /**< Index for exception handler */ + L4_THREAD_CONTROL_MR_IDX_FLAG_VALS = 4, /**< Index for feature values */ + L4_THREAD_CONTROL_MR_IDX_BIND_UTCB = 5, /**< Index for UTCB address for bind */ + L4_THREAD_CONTROL_MR_IDX_BIND_TASK = 6, /**< Index for task flex-page for bind */ +}; + +/** + * \brief Flags for the thread ex-regs operation. + * \ingroup l4_thread_api + * \hideinitializer + */ +enum L4_thread_ex_regs_flags +{ + L4_THREAD_EX_REGS_CANCEL = 0x10000UL, /**< Cancel ongoing IPC in the thread. */ + L4_THREAD_EX_REGS_TRIGGER_EXCEPTION = 0x20000UL, /**< Trigger artificial exception in thread. */ +}; + + +/* IMPLEMENTATION -----------------------------------------------------------*/ + +#include +#include + +L4_INLINE l4_msgtag_t +l4_thread_ex_regs_u(l4_cap_idx_t thread, l4_addr_t ip, l4_addr_t sp, + l4_umword_t flags, l4_utcb_t *utcb) L4_NOTHROW +{ + l4_msg_regs_t *v = l4_utcb_mr_u(utcb); + v->mr[0] = L4_THREAD_EX_REGS_OP | flags; + v->mr[1] = ip; + v->mr[2] = sp; + return l4_ipc_call(thread, utcb, l4_msgtag(L4_PROTO_THREAD, 3, 0, 0), L4_IPC_NEVER); +} + +L4_INLINE l4_msgtag_t +l4_thread_ex_regs_ret_u(l4_cap_idx_t thread, l4_addr_t *ip, l4_addr_t *sp, + l4_umword_t *flags, l4_utcb_t *utcb) L4_NOTHROW +{ + l4_msg_regs_t *v = l4_utcb_mr_u(utcb); + l4_msgtag_t ret = l4_thread_ex_regs_u(thread, *ip, *sp, *flags, utcb); + if (l4_error_u(ret, utcb)) + return ret; + + *flags = v->mr[0]; + *ip = v->mr[1]; + *sp = v->mr[2]; + return ret; +} + +L4_INLINE void +l4_thread_control_start_u(l4_utcb_t *utcb) L4_NOTHROW +{ + l4_msg_regs_t *v = l4_utcb_mr_u(utcb); + v->mr[L4_THREAD_CONTROL_MR_IDX_FLAGS] = L4_THREAD_CONTROL_OP; +} + +L4_INLINE void +l4_thread_control_pager_u(l4_cap_idx_t pager, l4_utcb_t *utcb) L4_NOTHROW +{ + l4_msg_regs_t *v = l4_utcb_mr_u(utcb); + v->mr[L4_THREAD_CONTROL_MR_IDX_FLAGS] |= L4_THREAD_CONTROL_SET_PAGER; + v->mr[L4_THREAD_CONTROL_MR_IDX_PAGER] = pager; +} + +L4_INLINE void +l4_thread_control_exc_handler_u(l4_cap_idx_t exc_handler, + l4_utcb_t *utcb) L4_NOTHROW +{ + l4_msg_regs_t *v = l4_utcb_mr_u(utcb); + v->mr[L4_THREAD_CONTROL_MR_IDX_FLAGS] |= L4_THREAD_CONTROL_SET_EXC_HANDLER; + v->mr[L4_THREAD_CONTROL_MR_IDX_EXC_HANDLER] = exc_handler; +} + +L4_INLINE void +l4_thread_control_bind_u(l4_utcb_t *thread_utcb, l4_cap_idx_t task, + l4_utcb_t *utcb) L4_NOTHROW +{ + l4_msg_regs_t *v = l4_utcb_mr_u(utcb); + v->mr[L4_THREAD_CONTROL_MR_IDX_FLAGS] |= L4_THREAD_CONTROL_BIND_TASK; + v->mr[L4_THREAD_CONTROL_MR_IDX_BIND_UTCB] = (l4_addr_t)thread_utcb; + v->mr[L4_THREAD_CONTROL_MR_IDX_BIND_TASK] = L4_ITEM_MAP; + v->mr[L4_THREAD_CONTROL_MR_IDX_BIND_TASK + 1] = l4_obj_fpage(task, 0, L4_FPAGE_RWX).raw; +} + +L4_INLINE void +l4_thread_control_alien_u(l4_utcb_t *utcb, int on) L4_NOTHROW +{ + l4_msg_regs_t *v = l4_utcb_mr_u(utcb); + v->mr[L4_THREAD_CONTROL_MR_IDX_FLAGS] |= L4_THREAD_CONTROL_ALIEN; + v->mr[L4_THREAD_CONTROL_MR_IDX_FLAG_VALS] |= on ? L4_THREAD_CONTROL_ALIEN : 0; +} + +L4_INLINE void +l4_thread_control_ux_host_syscall_u(l4_utcb_t *utcb, int on) L4_NOTHROW +{ + l4_msg_regs_t *v = l4_utcb_mr_u(utcb); + v->mr[L4_THREAD_CONTROL_MR_IDX_FLAGS] |= L4_THREAD_CONTROL_UX_NATIVE; + v->mr[L4_THREAD_CONTROL_MR_IDX_FLAG_VALS] |= on ? L4_THREAD_CONTROL_UX_NATIVE : 0; +} + +L4_INLINE l4_msgtag_t +l4_thread_control_commit_u(l4_cap_idx_t thread, l4_utcb_t *utcb) L4_NOTHROW +{ + int items = 0; + if (l4_utcb_mr_u(utcb)->mr[L4_THREAD_CONTROL_MR_IDX_FLAGS] & L4_THREAD_CONTROL_BIND_TASK) + items = 1; + return l4_ipc_call(thread, utcb, l4_msgtag(L4_PROTO_THREAD, 6, items, 0), L4_IPC_NEVER); +} + + +L4_INLINE l4_msgtag_t +l4_thread_yield(void) L4_NOTHROW +{ + l4_ipc_receive(L4_INVALID_CAP, NULL, L4_IPC_BOTH_TIMEOUT_0); + return l4_msgtag(0, 0, 0, 0); +} + +/* Preliminary, to be changed */ +L4_INLINE l4_msgtag_t +l4_thread_switch_u(l4_cap_idx_t to_thread, l4_utcb_t *utcb) L4_NOTHROW +{ + l4_msg_regs_t *v = l4_utcb_mr_u(utcb); + v->mr[0] = L4_THREAD_SWITCH_OP; + return l4_ipc_call(to_thread, utcb, l4_msgtag(L4_PROTO_THREAD, 1, 0, 0), L4_IPC_NEVER); +} + + +L4_INLINE l4_msgtag_t +l4_thread_stats_time_u(l4_cap_idx_t thread, l4_utcb_t *utcb) L4_NOTHROW +{ + l4_msg_regs_t *v = l4_utcb_mr_u(utcb); + v->mr[0] = L4_THREAD_STATS_OP; + return l4_ipc_call(thread, utcb, l4_msgtag(L4_PROTO_THREAD, 1, 0, 0), L4_IPC_NEVER); +} + +L4_INLINE l4_msgtag_t +l4_thread_vcpu_resume_start_u(l4_utcb_t *utcb) L4_NOTHROW +{ + l4_msg_regs_t *v = l4_utcb_mr_u(utcb); + v->mr[0] = L4_THREAD_VCPU_RESUME_OP; + return l4_msgtag(L4_PROTO_THREAD, 1, 0, 0); +} + +L4_INLINE l4_msgtag_t +l4_thread_vcpu_resume_commit_u(l4_cap_idx_t thread, + l4_msgtag_t tag, l4_utcb_t *utcb) L4_NOTHROW +{ + return l4_ipc_call(thread, utcb, tag, L4_IPC_NEVER); +} + +L4_INLINE l4_msgtag_t +l4_thread_ex_regs(l4_cap_idx_t thread, l4_addr_t ip, l4_addr_t sp, + l4_umword_t flags) L4_NOTHROW +{ + return l4_thread_ex_regs_u(thread, ip, sp, flags, l4_utcb()); +} + +L4_INLINE l4_msgtag_t +l4_thread_ex_regs_ret(l4_cap_idx_t thread, l4_addr_t *ip, l4_addr_t *sp, + l4_umword_t *flags) L4_NOTHROW +{ + return l4_thread_ex_regs_ret_u(thread, ip, sp, flags, l4_utcb()); +} + +L4_INLINE void +l4_thread_control_start(void) L4_NOTHROW +{ + l4_thread_control_start_u(l4_utcb()); +} + +L4_INLINE void +l4_thread_control_pager(l4_cap_idx_t pager) L4_NOTHROW +{ + l4_thread_control_pager_u(pager, l4_utcb()); +} + +L4_INLINE void +l4_thread_control_exc_handler(l4_cap_idx_t exc_handler) L4_NOTHROW +{ + l4_thread_control_exc_handler_u(exc_handler, l4_utcb()); +} + + +L4_INLINE void +l4_thread_control_bind(l4_utcb_t *thread_utcb, l4_cap_idx_t task) L4_NOTHROW +{ + l4_thread_control_bind_u(thread_utcb, task, l4_utcb()); +} + +L4_INLINE void +l4_thread_control_alien(int on) L4_NOTHROW +{ + l4_thread_control_alien_u(l4_utcb(), on); +} + +L4_INLINE void +l4_thread_control_ux_host_syscall(int on) L4_NOTHROW +{ + l4_thread_control_ux_host_syscall_u(l4_utcb(), on); +} + +L4_INLINE l4_msgtag_t +l4_thread_control_commit(l4_cap_idx_t thread) L4_NOTHROW +{ + return l4_thread_control_commit_u(thread, l4_utcb()); +} + + + + +L4_INLINE l4_msgtag_t +l4_thread_switch(l4_cap_idx_t to_thread) L4_NOTHROW +{ + return l4_thread_switch_u(to_thread, l4_utcb()); +} + + + + +L4_INLINE l4_msgtag_t +l4_thread_stats_time(l4_cap_idx_t thread) L4_NOTHROW +{ + return l4_thread_stats_time_u(thread, l4_utcb()); +} + +L4_INLINE l4_msgtag_t +l4_thread_vcpu_resume_start(void) L4_NOTHROW +{ + return l4_thread_vcpu_resume_start_u(l4_utcb()); +} + +L4_INLINE l4_msgtag_t +l4_thread_vcpu_resume_commit(l4_cap_idx_t thread, + l4_msgtag_t tag) L4_NOTHROW +{ + return l4_thread_vcpu_resume_commit_u(thread, tag, l4_utcb()); +} + + +L4_INLINE l4_msgtag_t +l4_thread_register_del_irq_u(l4_cap_idx_t thread, l4_cap_idx_t irq, + l4_utcb_t *u) L4_NOTHROW +{ + l4_msg_regs_t *m = l4_utcb_mr_u(u); + m->mr[0] = L4_THREAD_REGISTER_DELETE_IRQ_OP; + m->mr[1] = l4_map_obj_control(0,0); + m->mr[2] = l4_obj_fpage(irq, 0, L4_CAP_FPAGE_RWS).raw; + return l4_ipc_call(thread, u, l4_msgtag(L4_PROTO_THREAD, 1, 1, 0), L4_IPC_NEVER); + +} + +L4_INLINE l4_msgtag_t +l4_thread_register_del_irq(l4_cap_idx_t thread, l4_cap_idx_t irq) L4_NOTHROW +{ + return l4_thread_register_del_irq_u(thread, irq, l4_utcb()); +} + + +L4_INLINE l4_msgtag_t +l4_thread_vcpu_control_u(l4_cap_idx_t thread, l4_addr_t vcpu_state, + l4_utcb_t *utcb) L4_NOTHROW +{ + l4_msg_regs_t *v = l4_utcb_mr_u(utcb); + v->mr[0] = L4_THREAD_VCPU_CONTROL_OP; + v->mr[1] = vcpu_state; + return l4_ipc_call(thread, utcb, l4_msgtag(L4_PROTO_THREAD, 2, 0, 0), L4_IPC_NEVER); +} + +L4_INLINE l4_msgtag_t +l4_thread_vcpu_control(l4_cap_idx_t thread, l4_addr_t vcpu_state) L4_NOTHROW +{ return l4_thread_vcpu_control_u(thread, vcpu_state, l4_utcb()); } + + +L4_INLINE l4_msgtag_t +l4_thread_vcpu_control_ext_u(l4_cap_idx_t thread, l4_addr_t ext_vcpu_state, + l4_utcb_t *utcb) L4_NOTHROW +{ + l4_msg_regs_t *v = l4_utcb_mr_u(utcb); + v->mr[0] = L4_THREAD_VCPU_CONTROL_EXT_OP; + v->mr[1] = ext_vcpu_state; + return l4_ipc_call(thread, utcb, l4_msgtag(L4_PROTO_THREAD, 2, 0, 0), L4_IPC_NEVER); +} + +L4_INLINE l4_msgtag_t +l4_thread_vcpu_control_ext(l4_cap_idx_t thread, l4_addr_t ext_vcpu_state) L4_NOTHROW +{ return l4_thread_vcpu_control_ext_u(thread, ext_vcpu_state, l4_utcb()); } + +L4_INLINE l4_msgtag_t +l4_thread_modify_sender_start_u(l4_utcb_t *u) L4_NOTHROW +{ + l4_msg_regs_t *m = l4_utcb_mr_u(u); + m->mr[0] = L4_THREAD_MODIFY_SENDER_OP; + return l4_msgtag(L4_PROTO_THREAD, 1, 0, 0); +} + +L4_INLINE int +l4_thread_modify_sender_add_u(l4_umword_t match_mask, + l4_umword_t match, + l4_umword_t del_bits, + l4_umword_t add_bits, + l4_msgtag_t *tag, l4_utcb_t *u) L4_NOTHROW +{ + l4_msg_regs_t *m = l4_utcb_mr_u(u); + unsigned w = l4_msgtag_words(*tag); + if (w >= L4_UTCB_GENERIC_DATA_SIZE - 4) + return -L4_ENOMEM; + + m->mr[w] = match_mask; + m->mr[w+1] = match; + m->mr[w+2] = del_bits; + m->mr[w+3] = add_bits; + + *tag = l4_msgtag(l4_msgtag_label(*tag), w + 4, 0, 0); + + return 0; +} + +L4_INLINE l4_msgtag_t +l4_thread_modify_sender_commit_u(l4_cap_idx_t thread, l4_msgtag_t tag, + l4_utcb_t *u) L4_NOTHROW +{ + return l4_ipc_call(thread, u, tag, L4_IPC_NEVER); +} + +L4_INLINE l4_msgtag_t +l4_thread_modify_sender_start(void) L4_NOTHROW +{ + return l4_thread_modify_sender_start_u(l4_utcb()); +} + +L4_INLINE int +l4_thread_modify_sender_add(l4_umword_t match_mask, + l4_umword_t match, + l4_umword_t del_bits, + l4_umword_t add_bits, + l4_msgtag_t *tag) L4_NOTHROW +{ + return l4_thread_modify_sender_add_u(match_mask, match, + del_bits, add_bits, tag, l4_utcb()); +} + +L4_INLINE l4_msgtag_t +l4_thread_modify_sender_commit(l4_cap_idx_t thread, l4_msgtag_t tag) L4_NOTHROW +{ + return l4_thread_modify_sender_commit_u(thread, tag, l4_utcb()); +} diff --git a/l4/pkg/l4sys/include/typeinfo_svr b/l4/pkg/l4sys/include/typeinfo_svr new file mode 100644 index 00000000..50726253 --- /dev/null +++ b/l4/pkg/l4sys/include/typeinfo_svr @@ -0,0 +1,64 @@ +// vi:ft=cpp +/** + * \file + * \brief Type information server template. + */ +/* + * (c) 2010 Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ + +#pragma once + +#include +#include + +namespace L4 { namespace Util { + +template +long handle_meta_request(L4::Ipc::Iostream &ios) +{ + l4_umword_t op; + ios >> op; + switch (op) + { + case L4::Meta::O_num_ifaces: return 1; + case L4::Meta::O_iface: + { + l4_umword_t ifx; + ios >> ifx; + if (ifx > 0) + return -L4_ERANGE; + + L4::Ipc::Varg_t n(L4::kobject_typeid()->name()); + L4::Ipc::Varg_t p(L4::kobject_typeid()->proto()); + + ios << n << p; + return 0; + } + case L4::Meta::O_supports: + { + l4_mword_t proto; + ios >> proto; + + return L4::kobject_typeid()->has_proto(proto); + } + default: + return -L4_ENOSYS; + } +} + +}} diff --git a/l4/pkg/l4sys/include/types.h b/l4/pkg/l4sys/include/types.h new file mode 100644 index 00000000..cd51bb39 --- /dev/null +++ b/l4/pkg/l4sys/include/types.h @@ -0,0 +1,415 @@ +/*****************************************************************************/ +/** + * \file + * \brief Common L4 ABI Data Types. + * \ingroup l4_api + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg , + * Björn Döbel , + * Torsten Frenzel + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +/*****************************************************************************/ +#pragma once + +#include +#include +#include + + +/** + * \defgroup l4_msgtag_api Message Tag + * \ingroup l4_ipc_api + * \brief API related to the message tag data type. + * + * \#include + */ + +/** + * \brief Message tag for IPC operations. + * \ingroup l4_msgtag_api + * + * All predefined protocols used by the kernel. + */ +enum l4_msgtag_protocol +{ + L4_PROTO_NONE = 0, ///< Default protocol tag to reply to kernel + L4_PROTO_ALLOW_SYSCALL = 1, ///< Allow an alien the system call + L4_PROTO_PF_EXCEPTION = 1, ///< Make an exception out of a page fault + + L4_PROTO_IRQ = -1L, ///< IRQ message + L4_PROTO_PAGE_FAULT = -2L, ///< Page fault message + L4_PROTO_PREEMPTION = -3L, ///< Preemption message + L4_PROTO_SYS_EXCEPTION = -4L, ///< System exception + L4_PROTO_EXCEPTION = -5L, ///< Exception + L4_PROTO_SIGMA0 = -6L, ///< Sigma0 protocol + L4_PROTO_IO_PAGE_FAULT = -8L, ///< I/O page fault message + L4_PROTO_KOBJECT = -10L, ///< Protocol for messages to a a generic kobject + L4_PROTO_TASK = -11L, ///< Protocol for messages to a task object + L4_PROTO_THREAD = -12L, ///< Protocol for messages to a thread object + L4_PROTO_LOG = -13L, ///< Protocol for messages to a log object + L4_PROTO_SCHEDULER = -14L, ///< Protocol for messages to a scheduler object + L4_PROTO_FACTORY = -15L, ///< Protocol for messages to a factory object + L4_PROTO_VM = -16L, ///< Protocol for messages to a virtual machine object + L4_PROTO_DEBUGGER = -17L, + L4_PROTO_META = -21L, ///< Meta information protocol +}; + +enum L4_varg_type +{ + L4_VARG_TYPE_NIL = 0x00, + L4_VARG_TYPE_UMWORD = 0x01, + L4_VARG_TYPE_MWORD = 0x81, + L4_VARG_TYPE_STRING = 0x02, + L4_VARG_TYPE_FPAGE = 0x03, + + L4_VARG_TYPE_SIGN = 0x80, +}; + + +/** + * \brief Flags for message tags. + * \ingroup l4_msgtag_api + */ +enum l4_msgtag_flags +{ + // flags for received IPC + /** + * \brief Error indicator flag. + * \hideinitializer + */ + L4_MSGTAG_ERROR = 0x8000, + /** + * \brief Cross-CPU invocation indicator flag. + * \hideinitializer + */ + L4_MSGTAG_XCPU = 0x4000, + + // flags for sending IPC + /** + * \brief Enable FPU transfer flag for IPC. + * \hideinitializer + * + * By enabling this flag when sending IPC, the sender indicates that the + * contents of the FPU shall be transfered to the receiving thread. + * However, the receiver has to indicate its willingness to receive + * FPU context in its buffer descriptor register (BDR). + */ + L4_MSGTAG_TRANSFER_FPU = 0x1000, + /** + * \brief Enable schedule in IPC flag. + * \hideinitializer + * + * Usually IPC operations donate the remaining time slice of a thread + * to the called thread. Enabling this flag when sending IPC does a real + * scheduling decision. However, this flag decreases IPC performance. + */ + L4_MSGTAG_SCHEDULE = 0x2000, + /** + * \brief Enable IPC propagation. + * \hideinitializer + * + * This flag enables IPC propagation, which means an IPC reply-connection + * from the current caller will be propagated to the new IPC receiver. + * This makes it possible to propagate an IPC call to a third thread, which + * may then directly answer to the caller. + */ + L4_MSGTAG_PROPAGATE = 0x4000, + + /** + * \brief Mask for all flags. + * \hideinitializer + */ + L4_MSGTAG_FLAGS = 0xf000, +}; + + +/** + * \brief Message tag data structure. + * \ingroup l4_msgtag_api + * + * \#include + * + * Describes the details of an IPC operation, in particular + * which parts of the UTCB have to be transmitted, and also flags + * to enable real-time and FPU extensions. + * + * The message tag also contains a user-defined label that could be used + * to specify a protocol ID. Some negative values are reserved for kernel + * protocols such as page faults and exceptions. + * + * The type must be treated completely opaque. + */ +typedef struct l4_msgtag_t +{ + l4_mword_t raw; ///< raw value +#ifdef __cplusplus + /// Get the protocol value. + long label() const throw() { return raw >> 16; } + /// Set the protocol value. + void label(long v) throw() { raw = (raw & 0x0ffff) | (v << 16); } + /// Get the number of untyped words. + unsigned words() const throw() { return raw & 0x3f; } + /// Get the number of typed items. + unsigned items() const throw() { return (raw >> 6) & 0x3f; } + /** + * \brief Get the flags value. + * + * The flags are a combination of the flags defined by + * #l4_msgtag_flags. + */ + unsigned flags() const throw() { return raw & 0xf000; } + /// Test if protocol indicates page-fault protocol. + bool is_page_fault() const throw() { return label() == L4_PROTO_PAGE_FAULT; } + /// Test if protocol indicates preemption protocol. + bool is_preemption() const throw() { return label() == L4_PROTO_PREEMPTION; } + /// Test if protocol indicates system-exception protocol. + bool is_sys_exception() const throw() { return label() == L4_PROTO_SYS_EXCEPTION; } + /// Test if protocol indicates exception protocol. + bool is_exception() const throw() { return label() == L4_PROTO_EXCEPTION; } + /// Test if protocol indicates sigma0 protocol. + bool is_sigma0() const throw() { return label() == L4_PROTO_SIGMA0; } + /// Test if protocol indicates IO-page-fault protocol. + bool is_io_page_fault() const throw() { return label() == L4_PROTO_IO_PAGE_FAULT; } + /// Test if flags indicate an error. + unsigned has_error() const throw() { return raw & L4_MSGTAG_ERROR; } +#endif +} l4_msgtag_t; + + + +/** + * \brief Create a message tag from the specified values. + * \ingroup l4_msgtag_api + * + * \param label the user-defined label + * \param words the number of untyped words within the UTCB + * \param items the number of typed items (e.g., flex pages) within the UTCB + * \param flags the IPC flags for realtime and FPU extensions + * + * \return Message tag + */ +L4_INLINE l4_msgtag_t l4_msgtag(long label, unsigned words, unsigned items, + unsigned flags) L4_NOTHROW; + +/** + * \brief Get the protocol of tag. + * \ingroup l4_msgtag_api + * \param t The tag + * \return Label + */ +L4_INLINE long l4_msgtag_label(l4_msgtag_t t) L4_NOTHROW; + +/** + * \brief Get the number of untyped words. + * \ingroup l4_msgtag_api + * \param t The tag + * \return Number of words + */ +L4_INLINE unsigned l4_msgtag_words(l4_msgtag_t t) L4_NOTHROW; + +/** + * \brief Get the number of typed items. + * \ingroup l4_msgtag_api + * \param t The tag + * \return Number of items. + */ +L4_INLINE unsigned l4_msgtag_items(l4_msgtag_t t) L4_NOTHROW; + +/** + * \brief Get the flags. + * \ingroup l4_msgtag_api + * + * The flag are defined by #l4_msgtag_flags. + * + * \param t the tag + * \return Flags + */ +L4_INLINE unsigned l4_msgtag_flags(l4_msgtag_t t) L4_NOTHROW; + +/** + * \brief Test for error indicator flag. + * \ingroup l4_msgtag_api + * \param t the tag + * \return >0 for yes, 0 for no + * + * Return whether the kernel operation caused a communication error, e.g. + * with IPC. + * if true: utcb->error is valid, otherwise utcb->error is not valid + */ +L4_INLINE unsigned l4_msgtag_has_error(l4_msgtag_t t) L4_NOTHROW; + +/** + * \brief Test for page-fault protocol. + * \ingroup l4_msgtag_api + * \param t the tag + * \return Boolean value + */ +L4_INLINE unsigned l4_msgtag_is_page_fault(l4_msgtag_t t) L4_NOTHROW; + +/** + * \brief Test for preemption protocol. + * \ingroup l4_msgtag_api + * \param t the tag + * \return Boolean value + */ +L4_INLINE unsigned l4_msgtag_is_preemption(l4_msgtag_t t) L4_NOTHROW; + +/** + * \brief Test for system-exception protocol. + * \ingroup l4_msgtag_api + * \param t the tag + * \return Boolean value + */ +L4_INLINE unsigned l4_msgtag_is_sys_exception(l4_msgtag_t t) L4_NOTHROW; + +/** + * \brief Test for exception protocol. + * \ingroup l4_msgtag_api + * \param t the tag + * \return Boolean value + */ +L4_INLINE unsigned l4_msgtag_is_exception(l4_msgtag_t t) L4_NOTHROW; + +/** + * \brief Test for sigma0 protocol. + * \ingroup l4_msgtag_api + * \param t the tag + * \return Boolean value + */ +L4_INLINE unsigned l4_msgtag_is_sigma0(l4_msgtag_t t) L4_NOTHROW; + +/** + * \brief Test for IO-page-fault protocol. + * \ingroup l4_msgtag_api + * \param t the tag + * \return Boolean value + */ +L4_INLINE unsigned l4_msgtag_is_io_page_fault(l4_msgtag_t t) L4_NOTHROW; + +/** + * \defgroup l4_cap_api Capabilities + * \ingroup l4_api + * \brief Functions and definitions related to capabilities. + * + * C interface for capabilities:
+ * \#include + */ +/** + * \brief L4 Capability selector Type. + * \ingroup l4_cap_api + * + * \#include + */ +typedef unsigned long l4_cap_idx_t; + +/** + * \brief Test if a capability selector is the invalid capability. + * \ingroup l4_cap_api + * \param c Capability selector + * \return Boolean value + */ +L4_INLINE unsigned l4_is_invalid_cap(l4_cap_idx_t c) L4_NOTHROW; + +/** + * \brief Test if a capability selector is a valid selector. + * \ingroup l4_cap_api + * \param c Capability selector + * \return Boolean value + */ +L4_INLINE unsigned l4_is_valid_cap(l4_cap_idx_t c) L4_NOTHROW; + +/** + * \brief Test if two capability selectors are equal. + * \ingroup l4_cap_api + * \param c1 Capability + * \param c2 Capability + * \return 1 if equal, 0 if not equal + */ +L4_INLINE unsigned l4_capability_equal(l4_cap_idx_t c1, l4_cap_idx_t c2) L4_NOTHROW; + +/* ************************************************************************* */ +/* Implementation */ + +L4_INLINE unsigned +l4_is_invalid_cap(l4_cap_idx_t c) L4_NOTHROW +{ return c & L4_INVALID_CAP_BIT; } + +L4_INLINE unsigned +l4_is_valid_cap(l4_cap_idx_t c) L4_NOTHROW +{ return !(c & L4_INVALID_CAP_BIT); } + +L4_INLINE unsigned +l4_capability_equal(l4_cap_idx_t c1, l4_cap_idx_t c2) L4_NOTHROW +{ return (c1 >> L4_CAP_SHIFT) == (c2 >> L4_CAP_SHIFT); } + + +/** + * Message tag functions + */ +L4_INLINE +l4_msgtag_t l4_msgtag(long label, unsigned words, unsigned items, + unsigned flags) L4_NOTHROW +{ + return (l4_msgtag_t){(label << 16) | (l4_mword_t)(words & 0x3f) + | (l4_mword_t)((items & 0x3f) << 6) + | (l4_mword_t)(flags & 0xf000)}; +} + + + +L4_INLINE +long l4_msgtag_label(l4_msgtag_t t) L4_NOTHROW +{ return t.raw >> 16; } + +L4_INLINE +unsigned l4_msgtag_words(l4_msgtag_t t) L4_NOTHROW +{ return t.raw & 0x3f; } + +L4_INLINE +unsigned l4_msgtag_items(l4_msgtag_t t) L4_NOTHROW +{ return (t.raw >> 6) & 0x3f; } + +L4_INLINE +unsigned l4_msgtag_flags(l4_msgtag_t t) L4_NOTHROW +{ return t.raw & 0xf000; } + + +L4_INLINE +unsigned l4_msgtag_has_error(l4_msgtag_t t) L4_NOTHROW +{ return t.raw & L4_MSGTAG_ERROR; } + + + +L4_INLINE unsigned l4_msgtag_is_page_fault(l4_msgtag_t t) L4_NOTHROW +{ return l4_msgtag_label(t) == L4_PROTO_PAGE_FAULT; } + +L4_INLINE unsigned l4_msgtag_is_preemption(l4_msgtag_t t) L4_NOTHROW +{ return l4_msgtag_label(t) == L4_PROTO_PREEMPTION; } + +L4_INLINE unsigned l4_msgtag_is_sys_exception(l4_msgtag_t t) L4_NOTHROW +{ return l4_msgtag_label(t) == L4_PROTO_SYS_EXCEPTION; } + +L4_INLINE unsigned l4_msgtag_is_exception(l4_msgtag_t t) L4_NOTHROW +{ return l4_msgtag_label(t) == L4_PROTO_EXCEPTION; } + +L4_INLINE unsigned l4_msgtag_is_sigma0(l4_msgtag_t t) L4_NOTHROW +{ return l4_msgtag_label(t) == L4_PROTO_SIGMA0; } + +L4_INLINE unsigned l4_msgtag_is_io_page_fault(l4_msgtag_t t) L4_NOTHROW +{ return l4_msgtag_label(t) == L4_PROTO_IO_PAGE_FAULT; } diff --git a/l4/pkg/l4sys/include/utcb.h b/l4/pkg/l4sys/include/utcb.h new file mode 100644 index 00000000..18dd3743 --- /dev/null +++ b/l4/pkg/l4sys/include/utcb.h @@ -0,0 +1,367 @@ +/*****************************************************************************/ +/** + * \file + * \brief UTCB definitions. + * \ingroup l4_ipc_api + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg , + * Torsten Frenzel + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +/*****************************************************************************/ +#ifndef _L4_SYS_UTCB_H +#define _L4_SYS_UTCB_H + +#include +#include +#include + +/** + * \defgroup l4_utcb_api Virtual Registers (UTCBs) + * \ingroup l4_ipc_api + * + * \brief L4 Virtual Registers (UTCB). + * Includes:
+ * \#include <\link l4/sys/utcb.h l4/sys/utcb.h\endlink> + * + * The virtual registers are part of the micro-kernel API and are located in + * the user-level thread control block (UTCB). The UTCB is a data structure + * defined by the micro kernel and located on kernel-provided memory. + * Each L4 thread gets a unique UTCB assigned when it is bound to a task (see + * \link l4_thread_control_api Thread Control \endlink, + * l4_thread_control_bind() for more information). + * + * The UTCB is arranged in three blocks of virtual registers. + * - \link l4_utcb_tcr_api Thread Control Registers (TCRs) \endlink + * - \link l4_utcb_mr_api Message Registers (MRs) \endlink + * - \link l4_utcb_br_api Buffer Registers (BRs) \endlink + * + * To access the contents of the virtual registers the l4_utcb_mr(), + * l4_utcb_tcr(), and l4_utcb_br() functions must be used. + * + */ + +/** + * \brief Opaque type for the UTCB. + * \headerfile l4/sys/utcb.h + * \ingroup l4_utcb_api + * + * To access the contents of the virtual registers the l4_utcb_mr(), + * l4_utcb_tcr(), and l4_utcb_br() functions must be used. + * + */ +typedef struct l4_utcb_t l4_utcb_t; + +/** + * \defgroup l4_utcb_mr_api Message Registers (MRs) + * \ingroup l4_utcb_api + */ + +/** + * \brief Encapsulation of the message-register block in the UTCB. + * \headerfile l4/sys/utcb.h + * \ingroup l4_utcb_mr_api + */ +typedef struct l4_msg_regs_t +{ + l4_umword_t mr[L4_UTCB_GENERIC_DATA_SIZE]; /**< Message registers */ +} l4_msg_regs_t; + +/** + * \defgroup l4_utcb_br_api Buffer Registers (BRs) + * \ingroup l4_utcb_api + */ +/** + * \brief Encapsulation of the buffer-registers block in the UTCB. + * \headerfile l4/sys/utcb.h + * + * \ingroup l4_utcb_br_api + */ +typedef struct l4_buf_regs_t +{ + /// Buffer descriptor + l4_umword_t bdr; + + /// Buffer registers + l4_umword_t br[L4_UTCB_GENERIC_BUFFERS_SIZE]; +} l4_buf_regs_t; + +/** + * \defgroup l4_utcb_tcr_api Thread Control Registers (TCRs) + * \ingroup l4_utcb_api + */ +/** + * \brief Encapsulation of the thread-control-register block of the UTCB. + * \headerfile l4/sys/utcb.h + * \ingroup l4_utcb_tcr_api + */ +typedef struct l4_thread_regs_t +{ + /// System call error codes + l4_umword_t error; + /// Message transfer timeout + l4_timeout_t xfer; + /// User values (ignored and preserved by the kernel) + l4_umword_t user[3]; +} l4_thread_regs_t; + +__BEGIN_DECLS + +/** + * \internal + * \headerfile l4/sys/utcb.h + * \brief Get the UTCB address. + * \attention This functions should be used by libraries. + * \ingroup l4_utcb_api + * + * \returns UTCB + * + * This is a weak function which can be overwritten by applications. + */ +L4_CV l4_utcb_t *l4_utcb_wrap(void) L4_NOTHROW; + +/** + * \internal + * \brief Get the UTCB address. + * \ingroup l4_utcb_api + */ +L4_INLINE l4_utcb_t *l4_utcb_direct(void) L4_NOTHROW; + +/** + * \brief Get the UTCB address. + * \ingroup l4_utcb_api + */ +L4_INLINE l4_utcb_t *l4_utcb(void) L4_NOTHROW; + +/** + * \brief Get the message-register block of a UTCB. + * \ingroup l4_utcb_api + * \returns A pointer to the message-register block of \c u. + */ +L4_INLINE l4_msg_regs_t *l4_utcb_mr(void) L4_NOTHROW; + +/** + * \internal + * \param u the UTCB pointer to access. + */ +L4_INLINE l4_msg_regs_t *l4_utcb_mr_u(l4_utcb_t *u) L4_NOTHROW; + +/** + * \brief Get the buffer-register block of a UTCB. + * \ingroup l4_utcb_api + * \returns A pointer to the buffer-register block of \c u. + */ +L4_INLINE l4_buf_regs_t *l4_utcb_br(void) L4_NOTHROW; + +/** + * \internal + * \param u the UTCB pointer to access. + */ +L4_INLINE l4_buf_regs_t *l4_utcb_br_u(l4_utcb_t *u) L4_NOTHROW; + +/** + * \brief Get the thread-control-register block of a UTCB. + * \ingroup l4_utcb_api + * \returns A pointer to the thread-control-register block of \c u. + */ +L4_INLINE l4_thread_regs_t *l4_utcb_tcr(void) L4_NOTHROW; + +/** + * \internal + * \param u the UTCB pointer to access. + */ +L4_INLINE l4_thread_regs_t *l4_utcb_tcr_u(l4_utcb_t *u) L4_NOTHROW; + +/** + * \defgroup l4_utcb_exc_api Exception registers + * \ingroup l4_utcb_mr_api + * \brief Overly definition of the MRs for exception messages. + */ + +/** + * \brief Get the message-register block of a UTCB (for an exception IPC). + * \ingroup l4_utcb_exc_api + * \returns A pointer to the exception message in \c u. + */ +L4_INLINE l4_exc_regs_t *l4_utcb_exc(void) L4_NOTHROW; + +/** + * \internal + * \param u the UTCB pointer to access. + */ +L4_INLINE l4_exc_regs_t *l4_utcb_exc_u(l4_utcb_t *u) L4_NOTHROW; + +/** + * \brief Access function to get the program counter of the exception state. + * \ingroup l4_utcb_exc_api + * + * \param u UTCB + * \return The program counter register out of the exception state. + */ +L4_INLINE l4_umword_t l4_utcb_exc_pc(l4_exc_regs_t *u) L4_NOTHROW; + +/** + * \brief Set the program counter register in the exception state. + * \ingroup l4_utcb_exc_api + * + * \param u UTCB + * \param pc The program counter to set. + * + */ +L4_INLINE void l4_utcb_exc_pc_set(l4_exc_regs_t *u, l4_addr_t pc) L4_NOTHROW; + +/** + * \brief Get the value out of an exception UTCB that describes the type of exception. + * \ingroup l4_utcb_exc_api + */ +L4_INLINE unsigned long l4_utcb_exc_typeval(l4_exc_regs_t *u) L4_NOTHROW; + +/** + * \brief Check whether an exception IPC is a page fault. + * \ingroup l4_utcb_exc_api + * + * \returns 0 if not, != 0 if yes + * + * Function to check whether an exception IPC is a page fault, also applies + * to I/O pagefaults. + */ +L4_INLINE int l4_utcb_exc_is_pf(l4_exc_regs_t *u) L4_NOTHROW; + +/** + * \brief Function to get the L4 style page fault address out of an exception. + * \ingroup l4_utcb_exc_api + */ +L4_INLINE l4_addr_t l4_utcb_exc_pfa(l4_exc_regs_t *u) L4_NOTHROW; + +/** + * \brief Enable or disable inheritance of FPU state to receiver. + * \ingroup l4_utcb_br_api + */ +L4_INLINE void l4_utcb_inherit_fpu(int switch_on) L4_NOTHROW; + +/** + * \internal + */ +L4_INLINE void l4_utcb_inherit_fpu_u(l4_utcb_t *u, int switch_on) L4_NOTHROW; + +/** + * \internal + * + * \brief Set an absolute timeout. + * \ingroup l4_timeout_api + * + * \param pint Point in time in clocks + * \param br The buffer register the timeout shall be placed in. + * (\note On 32bit architectures the timeout needs two + * consecutive buffers.) + * \param utcb Utcb to put the absolute timeout in. + * + * \return timeout value + */ +L4_INLINE +l4_timeout_s l4_timeout_abs_u(l4_kernel_clock_t pint, int br, + l4_utcb_t *utcb) L4_NOTHROW; +/** + * \brief Set an absolute timeout. + * \ingroup l4_timeout_api + * + * \param pint Point in time in clocks + * \param br The buffer register the timeout shall be placed in. + * (\note On 32bit architectures the timeout needs two + * consecutive buffers.) + * + * \note The absolute timeout value will be placed into the buffer register + * \a br of the current thread. + * \return timeout value + */ +L4_INLINE +l4_timeout_s l4_timeout_abs(l4_kernel_clock_t pint, int br) L4_NOTHROW; + +/************************************************************************** + * Implementations + **************************************************************************/ + +L4_INLINE l4_msg_regs_t *l4_utcb_mr_u(l4_utcb_t *u) L4_NOTHROW +{ return (l4_msg_regs_t*)((char*)u + L4_UTCB_MSG_REGS_OFFSET); } + +L4_INLINE l4_buf_regs_t *l4_utcb_br_u(l4_utcb_t *u) L4_NOTHROW +{ return (l4_buf_regs_t*)((char*)u + L4_UTCB_BUF_REGS_OFFSET); } + +L4_INLINE l4_thread_regs_t *l4_utcb_tcr_u(l4_utcb_t *u) L4_NOTHROW +{ return (l4_thread_regs_t*)((char*)u + L4_UTCB_THREAD_REGS_OFFSET); } + +L4_INLINE l4_exc_regs_t *l4_utcb_exc_u(l4_utcb_t *u) L4_NOTHROW +{ return (l4_exc_regs_t*)((char*)u + L4_UTCB_MSG_REGS_OFFSET); } + +L4_INLINE void l4_utcb_inherit_fpu_u(l4_utcb_t *u, int switch_on) L4_NOTHROW +{ + if (switch_on) + l4_utcb_br_u(u)->bdr |= L4_UTCB_INHERIT_FPU; + else + l4_utcb_br_u(u)->bdr &= ~L4_UTCB_INHERIT_FPU; +} + +L4_INLINE l4_utcb_t *l4_utcb(void) L4_NOTHROW +{ +#ifdef L4SYS_USE_UTCB_WRAP + return l4_utcb_wrap(); +#else + return l4_utcb_direct(); +#endif +} + + + + +L4_INLINE l4_msg_regs_t *l4_utcb_mr(void) L4_NOTHROW +{ return l4_utcb_mr_u(l4_utcb()); } + +L4_INLINE l4_buf_regs_t *l4_utcb_br(void) L4_NOTHROW +{ return l4_utcb_br_u(l4_utcb()); } + +L4_INLINE l4_thread_regs_t *l4_utcb_tcr(void) L4_NOTHROW +{ return l4_utcb_tcr_u(l4_utcb()); } + +L4_INLINE l4_exc_regs_t *l4_utcb_exc(void) L4_NOTHROW +{ return l4_utcb_exc_u(l4_utcb()); } + +L4_INLINE void l4_utcb_inherit_fpu(int switch_on) L4_NOTHROW +{ l4_utcb_inherit_fpu_u(l4_utcb(), switch_on); } + +L4_INLINE +l4_timeout_s l4_timeout_abs_u(l4_kernel_clock_t val, int pos, + l4_utcb_t *utcb) L4_NOTHROW +{ + union T + { + l4_kernel_clock_t t; + l4_umword_t m[sizeof(l4_kernel_clock_t)/sizeof(l4_umword_t)]; + }; + l4_timeout_s to; + to.t = 0x8000 | pos; + ((union T*)(l4_utcb_br_u(utcb)->br + pos))->t = val; + return to; +} + +L4_INLINE +l4_timeout_s l4_timeout_abs(l4_kernel_clock_t val, int pos) L4_NOTHROW +{ return l4_timeout_abs_u(val, pos, l4_utcb()); } + +__END_DECLS + +#endif /* ! _L4_SYS_UTCB_H */ diff --git a/l4/pkg/l4sys/include/vcon b/l4/pkg/l4sys/include/vcon new file mode 100644 index 00000000..a4f31ca0 --- /dev/null +++ b/l4/pkg/l4sys/include/vcon @@ -0,0 +1,88 @@ +// vi:ft=cpp +/** + * \file + * \brief Virtual console interface. + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg , + * Torsten Frenzel + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#pragma once + +#include +#include +#include + +namespace L4 { + +/** + * \brief C++ L4 Vcon. + * \ingroup l4_vcon_api + * + * \#include + * + * \see \ref l4_vcon_api for an overview and C bindings. + */ +class Vcon : + public Kobject_t +{ + L4_KOBJECT(Vcon) + +public: + /** + * \copydoc l4_vcon_send() + * \note \a vcon is the implicit \a this pointer. + */ + l4_msgtag_t + send(char const *buf, int size, l4_utcb_t *utcb = l4_utcb()) const throw() + { return l4_vcon_send_u(cap(), buf, size, utcb); } + + /** + * \copydoc l4_vcon_write() + * \note \a vcon is the implicit \a this pointer. + */ + long + write(char const *buf, int size, l4_utcb_t *utcb = l4_utcb()) const throw() + { return l4_vcon_write_u(cap(), buf, size, utcb); } + + /** + * \copydoc l4_vcon_read() + * \note \a vcon is the implicit \a this pointer. + */ + int + read(char *buf, int size, l4_utcb_t *utcb = l4_utcb()) const throw() + { return l4_vcon_read_u(cap(), buf, size, utcb); } + + /** + * \copydoc l4_vcon_set_attr() + * \note \a vcon is the implicit \a this pointer. + */ + l4_msgtag_t + set_attr(l4_vcon_attr_t const *attr, l4_utcb_t *utcb = l4_utcb()) const throw() + { return l4_vcon_set_attr_u(cap(), attr, utcb); } + + /** + * \copydoc l4_vcon_get_attr() + * \note \a vcon is the implicit \a this pointer. + */ + l4_msgtag_t + get_attr(l4_vcon_attr_t *attr, l4_utcb_t *utcb = l4_utcb()) const throw() + { return l4_vcon_get_attr_u(cap(), attr, utcb); } +}; + +} diff --git a/l4/pkg/l4sys/include/vcon.h b/l4/pkg/l4sys/include/vcon.h new file mode 100644 index 00000000..18afec62 --- /dev/null +++ b/l4/pkg/l4sys/include/vcon.h @@ -0,0 +1,327 @@ +/** + * \file + * \brief Virtual console interface. + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg , + * Torsten Frenzel + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#pragma once + +#include + +/** + * \defgroup l4_vcon_api Virtual Console + * \ingroup l4_kernel_object_api + * \brief Virtual console for simple character based input and output. + * + * \#include + * + * Interrupt for read events are provided by the virtual key interrupt. + */ + +/** + * \brief Send data to virtual console. + * \ingroup l4_vcon_api + * + * \param vcon Vcon object. + * \param buf Pointer to data buffer. + * \param size Size of buffer in bytes. + * + * \return Syscall return tag + * + * \note Size must not exceed L4_VCON_WRITE_SIZE. + */ +L4_INLINE l4_msgtag_t +l4_vcon_send(l4_cap_idx_t vcon, char const *buf, int size) L4_NOTHROW; + +/** + * \internal + */ +L4_INLINE l4_msgtag_t +l4_vcon_send_u(l4_cap_idx_t vcon, char const *buf, int size, l4_utcb_t *utcb) L4_NOTHROW; + + +/** + * \brief Write data to virtual console. + * \ingroup l4_vcon_api + * + * \param vcon Vcon object. + * \param buf Pointer to data buffer. + * \param size Size of buffer in bytes. + * + * \return Number of bytes written to the virtual console. + */ +L4_INLINE long +l4_vcon_write(l4_cap_idx_t vcon, char const *buf, int size) L4_NOTHROW; + +/** + * \internal + */ +L4_INLINE long +l4_vcon_write_u(l4_cap_idx_t vcon, char const *buf, int size, l4_utcb_t *utcb) L4_NOTHROW; + +/** + * \brief Constants for l4_vcon_write. + * \ingroup l4_vcon_api + */ +enum L4_vcon_write_consts +{ + /** Maximum size that can be written with one l4_vcon_write call. */ + L4_VCON_WRITE_SIZE = (L4_UTCB_GENERIC_DATA_SIZE - 2) * sizeof(l4_umword_t), +}; + +/** + * \brief Read data from virtual console. + * \ingroup l4_vcon_api + * + * \param vcon Vcon object. + * \param buf Pointer to data buffer. + * \param size Size of buffer in bytes. + * + * \return Negative error code on error, + * > size if more to read, size bytes are in the buffer, + * <= size bytes read + */ +L4_INLINE int +l4_vcon_read(l4_cap_idx_t vcon, char *buf, int size) L4_NOTHROW; + +/** + * \internal + */ +L4_INLINE int +l4_vcon_read_u(l4_cap_idx_t vcon, char *buf, int size, l4_utcb_t *utcb) L4_NOTHROW; + + +/** + * \brief Vcon attribute structure. + * \ingroup l4_vcon_api + */ +typedef struct l4_vcon_attr_t +{ + l4_umword_t i_flags; ///< input flags + l4_umword_t o_flags; ///< output flags + l4_umword_t l_flags; ///< local flags +} l4_vcon_attr_t; + +/** + * \brief Input flags. + * \ingroup l4_vcon_api + */ +enum L4_vcon_i_flags +{ + L4_VCON_INLCR = 000100, ///< Translate NL to CR + L4_VCON_IGNCR = 000200, ///< Ignore CR + L4_VCON_ICRNL = 000400, ///< Translate CR to NL if L4_VCON_IGNCR is not set +}; + +/** + * \brief Output flags. + * \ingroup l4_vcon_api + */ +enum L4_vcon_o_flags +{ + L4_VCON_ONLCR = 000004, ///< Translate NL to CR-NL + L4_VCON_OCRNL = 000010, ///< Translate CR to NL + L4_VCON_ONLRET = 000040, ///< Do not ouput CR +}; + +/** + * \brief Local flags. + * \ingroup l4_vcon_api + */ +enum L4_vcon_l_flags +{ + L4_VCON_ICANON = 000002, ///< Cannonical mode + L4_VCON_ECHO = 000010, ///< Echo input +}; + + +/** + * \brief Set attributes of a Vcon. + * \ingroup l4_vcon_api + * + * \param vcon Vcon object. + * \param attr Attribute structure. + * \return Syscall return tag + */ +L4_INLINE l4_msgtag_t +l4_vcon_set_attr(l4_cap_idx_t vcon, l4_vcon_attr_t const *attr) L4_NOTHROW; + +/** + * \internal + */ +L4_INLINE l4_msgtag_t +l4_vcon_set_attr_u(l4_cap_idx_t vcon, l4_vcon_attr_t const *attr, + l4_utcb_t *utcb) L4_NOTHROW; + +/** + * \brief Get attributes of a Vcon. + * \ingroup l4_vcon_api + * + * \param vcon Vcon object. + * \retval attr Attribute structure. + * \return Syscall return tag + */ +L4_INLINE l4_msgtag_t +l4_vcon_get_attr(l4_cap_idx_t vcon, l4_vcon_attr_t *attr) L4_NOTHROW; + +/** + * \internal + */ +L4_INLINE l4_msgtag_t +l4_vcon_get_attr_u(l4_cap_idx_t vcon, l4_vcon_attr_t *attr, + l4_utcb_t *utcb) L4_NOTHROW; + + +/** + * \brief Operations on the vcon objects. + * \ingroup l4_vcon_api + * \hideinitializer + * \internal + */ +enum L4_vcon_ops +{ + L4_VCON_WRITE_OP = 0UL, /**< Write */ + L4_VCON_SET_ATTR_OP = 2UL, /**< Get console attributes */ + L4_VCON_GET_ATTR_OP = 3UL, /**< Set console attributes */ +}; + +/******* Implementations ********************/ + +L4_INLINE l4_msgtag_t +l4_vcon_send_u(l4_cap_idx_t vcon, char const *buf, int size, l4_utcb_t *utcb) L4_NOTHROW +{ + l4_msg_regs_t *mr = l4_utcb_mr_u(utcb); + mr->mr[0] = L4_VCON_WRITE_OP; + mr->mr[1] = size; + __builtin_memcpy(&mr->mr[2], buf, size); + return l4_ipc_send(vcon, utcb, + l4_msgtag(L4_PROTO_LOG, + 2 + (size + sizeof(l4_umword_t) - 1) / sizeof(l4_umword_t), + 0, L4_MSGTAG_SCHEDULE), + L4_IPC_NEVER); +} + +L4_INLINE l4_msgtag_t +l4_vcon_send(l4_cap_idx_t vcon, char const *buf, int size) L4_NOTHROW +{ + return l4_vcon_send_u(vcon, buf, size, l4_utcb()); +} + +L4_INLINE long +l4_vcon_write_u(l4_cap_idx_t vcon, char const *buf, int size, l4_utcb_t *utcb) L4_NOTHROW +{ + l4_msgtag_t t; + + if (size > L4_VCON_WRITE_SIZE) + size = L4_VCON_WRITE_SIZE; + + t = l4_vcon_send_u(vcon, buf, size, utcb); + if (l4_msgtag_has_error(t)) + return l4_error(t); + + return size; +} + +L4_INLINE long +l4_vcon_write(l4_cap_idx_t vcon, char const *buf, int size) L4_NOTHROW +{ + return l4_vcon_write_u(vcon, buf, size, l4_utcb()); +} + +L4_INLINE int +l4_vcon_read_u(l4_cap_idx_t vcon, char *buf, int size, l4_utcb_t *utcb) L4_NOTHROW +{ + int ret, r; + l4_msg_regs_t *mr; + + if (size <= 0) + return -L4_EINVAL; + + mr = l4_utcb_mr_u(utcb); + mr->mr[0] = size << 16; + + ret = l4_error_u(l4_ipc_call(vcon, utcb, + l4_msgtag(L4_PROTO_LOG, 1, 0, 0), + L4_IPC_NEVER), utcb); + if (ret < 0) + return ret; + + r = mr->mr[0] & ~(1U << 31); + + if (!(mr->mr[0] & (1UL << 31))) // !eof + ret = size + 1; + else if (r < size) + ret = r; + else + ret = size; + + __builtin_memcpy(buf, &mr->mr[1], r); + return ret; +} + +L4_INLINE int +l4_vcon_read(l4_cap_idx_t vcon, char *buf, int size) L4_NOTHROW +{ + return l4_vcon_read_u(vcon, buf, size, l4_utcb()); +} + +L4_INLINE l4_msgtag_t +l4_vcon_set_attr_u(l4_cap_idx_t vcon, l4_vcon_attr_t const *attr, + l4_utcb_t *utcb) L4_NOTHROW +{ + l4_msg_regs_t *mr = l4_utcb_mr_u(utcb); + + mr->mr[0] = L4_VCON_SET_ATTR_OP; + __builtin_memcpy(&mr->mr[1], attr, sizeof(*attr)); + + return l4_ipc_call(vcon, utcb, + l4_msgtag(L4_PROTO_LOG, 4, 0, 0), + L4_IPC_NEVER); +} + +L4_INLINE l4_msgtag_t +l4_vcon_set_attr(l4_cap_idx_t vcon, l4_vcon_attr_t const *attr) L4_NOTHROW +{ + return l4_vcon_set_attr_u(vcon, attr, l4_utcb()); +} + +L4_INLINE l4_msgtag_t +l4_vcon_get_attr_u(l4_cap_idx_t vcon, l4_vcon_attr_t *attr, + l4_utcb_t *utcb) L4_NOTHROW +{ + l4_msgtag_t res; + l4_msg_regs_t *mr = l4_utcb_mr_u(utcb); + + mr->mr[0] = L4_VCON_GET_ATTR_OP; + + res = l4_ipc_call(vcon, utcb, + l4_msgtag(L4_PROTO_LOG, 1, 0, 0), + L4_IPC_NEVER); + if (l4_error_u(res, utcb) >= 0) + __builtin_memcpy(attr, &mr->mr[1], sizeof(*attr)); + + return res; +} + +L4_INLINE l4_msgtag_t +l4_vcon_get_attr(l4_cap_idx_t vcon, l4_vcon_attr_t *attr) L4_NOTHROW +{ + return l4_vcon_get_attr_u(vcon, attr, l4_utcb()); +} diff --git a/l4/pkg/l4sys/include/vcpu.h b/l4/pkg/l4sys/include/vcpu.h new file mode 100644 index 00000000..8d8917bd --- /dev/null +++ b/l4/pkg/l4sys/include/vcpu.h @@ -0,0 +1,81 @@ +/* + * (c) 2009 Adam Lackorzynski , + * Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#pragma once + +#include +#include + +/** + * \defgroup l4_vcpu_api vCPU API + * \ingroup l4_thread_api + * \brief vCPU API + */ + +/** + * \brief State of a vCPU + * \ingroup l4_vcpu_api + */ +typedef struct l4_vcpu_state_t +{ + l4_vcpu_regs_t r; ///< Register state + l4_vcpu_ipc_regs_t i; ///< IPC state + + l4_uint16_t state; ///< Current vCPU state + l4_uint16_t saved_state; ///< Saved vCPU state + l4_uint16_t sticky_flags; ///< Pending flags + l4_uint16_t _reserved; ///< \internal + + l4_cap_idx_t user_task; ///< User task to use + + l4_umword_t entry_sp; ///< Stack pointer for entry (when coming from user task) + l4_umword_t entry_ip; ///< IP for entry + l4_umword_t reserved_sp; ///< \internal +} l4_vcpu_state_t; + +/** + * \brief State flags of a vCPU + * \ingroup l4_vcpu_api + */ +enum L4_vcpu_state_flags +{ + L4_VCPU_F_IRQ = 0x01, ///< IRQs (events) enabled + L4_VCPU_F_PAGE_FAULTS = 0x02, ///< Page faults enabled + L4_VCPU_F_EXCEPTIONS = 0x04, ///< Exception enabled + L4_VCPU_F_DEBUG_EXC = 0x08, ///< Debug exception enabled + L4_VCPU_F_USER_MODE = 0x20, ///< User task will be used + L4_VCPU_F_FPU_ENABLED = 0x80, ///< FPU enabled +}; + +/** + * \brief Sticky flags of a vCPU + * \ingroup l4_vcpu_api + */ +enum L4_vcpu_sticky_flags +{ + L4_VCPU_SF_IRQ_PENDING = 0x01, ///< An event (e.g. IRQ) is pending +}; + +/** + * \brief Offsets for vCPU state layouts + * \ingroup l4_vcpu_api + */ +enum L4_vcpu_state_offset +{ + L4_VCPU_OFFSET_EXT_STATE = 0x400, ///< Offset where extended state begins +}; diff --git a/l4/pkg/l4sys/include/vhw.h b/l4/pkg/l4sys/include/vhw.h new file mode 100644 index 00000000..9d791efb --- /dev/null +++ b/l4/pkg/l4sys/include/vhw.h @@ -0,0 +1,115 @@ +/*****************************************************************************/ +/** + * \file + * \brief Descriptors for virtual hardware (under UX). + * \ingroup l4_api + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +/*****************************************************************************/ +#ifndef _L4_SYS_VHW_H +#define _L4_SYS_VHW_H + +#include +#include + +/** + * \defgroup l4_kip_vhw_api Fiasco-UX Virtual devices + * \ingroup l4_kip_api + * \brief Virtual hardware devices, provided by Fiasco-UX. + * + * \#include + */ + +/** + * \brief Type of device. + * \ingroup l4_kip_vhw_api + */ +enum l4_vhw_entry_type { + L4_TYPE_VHW_NONE, /**< None entry. */ + L4_TYPE_VHW_FRAMEBUFFER, /**< Framebuffer device. */ + L4_TYPE_VHW_INPUT, /**< Input device. */ + L4_TYPE_VHW_NET, /**< Network device. */ +}; + +/** + * \brief Description of a device. + * \ingroup l4_kip_vhw_api + */ +struct l4_vhw_entry { + enum l4_vhw_entry_type type; /**< Type of virtual hardware. */ + l4_uint32_t provider_pid; /**< Host PID of the VHW provider. */ + + l4_addr_t mem_start; /**< Start of memory region. */ + l4_addr_t mem_size; /**< Size of memory region. */ + + l4_uint32_t irq_no; /**< IRQ number. */ + l4_uint32_t fd; /**< File descriptor. */ +}; + +/** + * \brief Virtual hardware devices description. + * \ingroup l4_kip_vhw_api + */ +struct l4_vhw_descriptor { + l4_uint32_t magic; /**< Magic. */ + l4_uint8_t version; /**< Version of the descriptor. */ + l4_uint8_t count; /**< Number of entries. */ + l4_uint8_t pad1; /**< padding \internal. */ + l4_uint8_t pad2; /**< padding \internal. */ + + struct l4_vhw_entry descs[]; /**< Array of device descriptions. */ +}; + +enum { + L4_VHW_MAGIC = 0x56687765, +}; + +static inline struct l4_vhw_descriptor * +l4_vhw_get(l4_kernel_info_t *kip) L4_NOTHROW +{ + struct l4_vhw_descriptor *v + = (struct l4_vhw_descriptor *)(((unsigned long)kip) + kip->vhw_offset); + + if (v->magic == L4_VHW_MAGIC) + return v; + + return NULL; +} + +static inline struct l4_vhw_entry * +l4_vhw_get_entry(struct l4_vhw_descriptor *v, int entry) L4_NOTHROW +{ + return v->descs + entry; +} + +static inline struct l4_vhw_entry * +l4_vhw_get_entry_type(struct l4_vhw_descriptor *v, enum l4_vhw_entry_type t) L4_NOTHROW +{ + int i; + struct l4_vhw_entry *e = v->descs; + + for (i = 0; i < v->count; i++, e++) + if (e->type == t) + return e; + + return NULL; +} + +#endif /* ! _L4_SYS_VHW_H */ diff --git a/l4/pkg/l4sys/lib/Makefile b/l4/pkg/l4sys/lib/Makefile new file mode 100644 index 00000000..16ccaf1e --- /dev/null +++ b/l4/pkg/l4sys/lib/Makefile @@ -0,0 +1,4 @@ +PKGDIR = .. +L4DIR ?= $(PKGDIR)/../.. + +include $(L4DIR)/mk/subdir.mk diff --git a/l4/pkg/l4sys/lib/src/ARCH-amd64/syscalls_direct.S b/l4/pkg/l4sys/lib/src/ARCH-amd64/syscalls_direct.S new file mode 100644 index 00000000..def677c2 --- /dev/null +++ b/l4/pkg/l4sys/lib/src/ARCH-amd64/syscalls_direct.S @@ -0,0 +1,27 @@ +/* + * (c) 2008-2009 Frank Mehnert + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ + +__l4sys_direct_syscalls = 0xffffffffeacff000 +.hidden __l4sys_direct_syscalls + + .macro direct_syscall syscall,offset +\syscall = __l4sys_direct_syscalls + \offset +.global \syscall + .endm + + direct_syscall __l4sys_invoke_direct, 0x000 diff --git a/l4/pkg/l4sys/lib/src/ARCH-arm/atomic_ops_s.S b/l4/pkg/l4sys/lib/src/ARCH-arm/atomic_ops_s.S new file mode 100644 index 00000000..de49fda5 --- /dev/null +++ b/l4/pkg/l4sys/lib/src/ARCH-arm/atomic_ops_s.S @@ -0,0 +1,51 @@ +/* + * (c) 2008-2010 Adam Lackorzynski , + * Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#if 0 +#define ABS_FUNC(s,value) \ +.global s; \ +.type s, #function; \ +.size s, 12; \ +s = value + +ABS_FUNC(l4_atomic_add, 0xffffe000) +ABS_FUNC(l4_atomic_cmpxchg, 0xffffe100) +ABS_FUNC(l4_atomic_xchg, 0xffffe200) + +#else + +/* Using the above gives problems when using it in shared libs + * due to relocation which actually shouldn't happen */ + +#define JUMP_CODE(name) \ + .global name; \ + .type name, #function; \ + .size name, 12; \ + name: \ + ldr pc, .LC##name; \ + /* Will return to our caller */ + +JUMP_CODE(l4_atomic_add) +JUMP_CODE(l4_atomic_cmpxchg) +JUMP_CODE(l4_atomic_xchg) + + +.LCl4_atomic_add: .word 0xffffe000 +.LCl4_atomic_cmpxchg: .word 0xffffe100 +.LCl4_atomic_xchg: .word 0xffffe200 +#endif diff --git a/l4/pkg/l4sys/lib/src/ARCH-ppc32/atomic_ops.c b/l4/pkg/l4sys/lib/src/ARCH-ppc32/atomic_ops.c new file mode 100644 index 00000000..00753fb8 --- /dev/null +++ b/l4/pkg/l4sys/lib/src/ARCH-ppc32/atomic_ops.c @@ -0,0 +1,73 @@ +/* + * (c) 2009 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#include + +long int +l4_atomic_add(volatile long int* mem, long int offset) +{ + long int ret = 0; + asm volatile ( " 1: \n" + " lwarx %%r12, 0, %[ptr] \n" //reserve + " add %[ret], %%r12, %[val] \n" //add + " stwcx. %[ret], 0, %[ptr] \n" //store if still reserved + " bne- 1b \n" //repeat if store failed + : [ret]"=r" (ret), + [ptr]"=r" (mem), + [val]"=r" (offset) + : "0" (ret), + "1" (mem), + "2" (offset) + : "r12", "memory" + ); + return ret; +} + +long int +l4_atomic_cmpxchg(volatile long int* mem, long int oldval, long int newval) +{ + long int ret = 0; + asm volatile ( " 1: \n" + " lwarx %%r12, 0, %[ptr] \n" + " cmpw %[oldval], %%r12 \n" + " bne- 2f \n" + " stwcx. %[newval], 0,%[ptr] \n" + " bne- 1b \n" + " 2: \n" + " mr %[ret], %%r12 \n" + : [ret] "=r"(ret), + [ptr] "=r"(mem), + [oldval] "=r"(oldval), + [newval] "=r"(newval) + : "0" (ret), + "1" (mem), + "2" (oldval), + "3" (newval) + : "memory", "r12" + ); + return (oldval == ret); +} + +long int +l4_atomic_xchg(volatile long int* mem, long int newval) +{ + // someone not speaking ppc has added this... + unsigned long r = *mem; + outstring("l4_atomic_xchg is not atomic!\n"); + *mem = newval; + return r; +} diff --git a/l4/pkg/l4sys/lib/src/ARCH-sparc/atomic_ops.S b/l4/pkg/l4sys/lib/src/ARCH-sparc/atomic_ops.S new file mode 100644 index 00000000..fb85cb52 --- /dev/null +++ b/l4/pkg/l4sys/lib/src/ARCH-sparc/atomic_ops.S @@ -0,0 +1,7 @@ +.globl l4_atomic_add +l4_atomic_add: + ta 0x0815 + +.globl l4_atomic_cmpxchg +l4_atomic_cmpxchg: + ta 0x0815 diff --git a/l4/pkg/l4sys/lib/src/ARCH-x86/syscalls_direct.S b/l4/pkg/l4sys/lib/src/ARCH-x86/syscalls_direct.S new file mode 100644 index 00000000..cd62b34f --- /dev/null +++ b/l4/pkg/l4sys/lib/src/ARCH-x86/syscalls_direct.S @@ -0,0 +1,31 @@ +/* + * (c) 2008-2009 Alexander Warg , + * Frank Mehnert + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ + +__l4sys_direct_syscalls = 0xeacff000 +.hidden __l4sys_direct_syscalls + + .macro direct_syscall syscall,offset + \syscall = __l4sys_direct_syscalls + \offset + .global \syscall + .hidden \syscall + .endm + + + direct_syscall __l4sys_invoke_direct, 0x000 + direct_syscall __l4sys_debugger_direct, 0x200 diff --git a/l4/pkg/l4sys/lib/src/ARCH-x86/utcb-l4x.c b/l4/pkg/l4sys/lib/src/ARCH-x86/utcb-l4x.c new file mode 100644 index 00000000..2930e033 --- /dev/null +++ b/l4/pkg/l4sys/lib/src/ARCH-x86/utcb-l4x.c @@ -0,0 +1,34 @@ +/*! + * \file l4sys/lib/src/utcb.c + * \brief utcb for L4Linux programs + * + * \date 2008-02-25 + * \author Adam Lackorzynski + * + */ +/* + * (c) 2008-2009 Author(s) + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ + +#include + +L4_CV l4_utcb_t *l4_utcb_wrap(void) +{ + l4_utcb_t *utcb; + __asm__ __volatile__ ("mov %%fs:0, %0" : "=r" (utcb)); + return utcb; +} diff --git a/l4/pkg/l4sys/lib/src/Makefile b/l4/pkg/l4sys/lib/src/Makefile new file mode 100644 index 00000000..43033838 --- /dev/null +++ b/l4/pkg/l4sys/lib/src/Makefile @@ -0,0 +1,45 @@ +PKGDIR ?= ../.. +L4DIR ?= $(PKGDIR)/../.. + +TARGET = libl4sys.a libl4sys.so \ + libl4sys-direct.a libl4sys-direct.so \ + libl4sys-l4x.a libl4sys-l4x.so +PC_FILENAMES = l4sys l4sys-direct l4sys-l4x +PC_LIBS_l4sys = -ll4sys +PC_LIBS_l4sys-direct = -ll4sys-direct +PC_LIBS_l4sys-l4x = -ll4sys-l4x + +CXXFLAGS += -DL4_NO_RTTI -fno-rtti -fno-exceptions + +SRC_CC = kobject.cc +SRC_S_libl4sys-arm += ARCH-arm/atomic_ops_s.S +SRC_C_libl4sys-ppc32 += ARCH-ppc32/atomic_ops.c +SRC_S_libl4sys-sparc += ARCH-sparc/atomic_ops.S + +SRC_S_libl4sys-direct.so = +SRC_S_libl4sys-direct.a-x86 = syscalls_direct.S +SRC_S_libl4sys-direct.a = $(SRC_S_libl4sys-direct.a-$(ARCH)) +vpath syscalls_direct.S $(SRC_DIR)/ARCH-$(ARCH) + +SRC_C_libl4sys.a = utcb.c errtostr.c $(SRC_C_libl4sys-$(ARCH)) +SRC_C_libl4sys.so = utcb.c errtostr.c $(SRC_C_libl4sys-$(ARCH)) +SRC_S_libl4sys.a = $(SRC_S_libl4sys-$(ARCH)) +SRC_S_libl4sys.so = $(SRC_S_libl4sys-$(ARCH)) + +SRC_C_libl4sys-l4x.a = utcb.c errtostr.c $(SRC_C_libl4sys-$(ARCH)) +SRC_C_libl4sys-l4x.so = utcb.c errtostr.c $(SRC_C_libl4sys-$(ARCH)) +SRC_S_libl4sys-l4x.a = $(SRC_S_libl4sys-$(ARCH)) +SRC_S_libl4sys-l4x.so = $(SRC_S_libl4sys-$(ARCH)) + +SRC_C_l4lx-arm = utcb.c +SRC_C_l4lx-amd64 = utcb.c +SRC_S_l4lx-arm = ARCH-arm/atomic_ops_s.S +SRC_C_l4lx-ppc32 = utcb.c ARCH-ppc32/atomic_ops.c +SRC_C_l4lx-x86 = ARCH-x86/utcb-l4x.c +SRC_C_libl4sys-l4x.a = errtostr.c $(SRC_C_l4lx-$(ARCH)) +SRC_S_libl4sys-l4x.a = $(SRC_S_l4lx-$(ARCH)) + +include $(L4DIR)/mk/lib.mk + +GCCLIB = $(OBJ_BASE)/lib/$(ARCH)_$(CPU)/libgcc.a +GCCLIB_SO = $(OBJ_BASE)/lib/$(ARCH)_$(CPU)/libgcc.a diff --git a/l4/pkg/l4sys/lib/src/errtostr.c b/l4/pkg/l4sys/lib/src/errtostr.c new file mode 100644 index 00000000..ae56987f --- /dev/null +++ b/l4/pkg/l4sys/lib/src/errtostr.c @@ -0,0 +1,70 @@ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ + +#include +#include + +static char const *const _l4sys_errortab[L4_ERRNOMAX] = { + [L4_EOK] = "OK", + [L4_EPERM] = "Operation not permitted", + [L4_ENOENT] = "No such object found", + [L4_EIO] = "I/O error", + [L4_EAGAIN] = "Try again", + [L4_ENOMEM] = "Insufficient memory", + [L4_EACCESS] = "Access not permitted", + [L4_EBUSY] = "Function busy", + [L4_EEXIST] = "Object exists", + [L4_ENODEV] = "No such device", + [L4_EINVAL] = "Invalid argument", + [L4_ERANGE] = "Argument out of range", + [L4_ENAMETOOLONG] = "Name too long", + [L4_ENOSYS] = "Invalid request", + [L4_EBADPROTO] = "Invalid protocol", + [L4_EADDRNOTAVAIL] = "Address not available" +}; + +static char const *const _l4sys_ipc_errortab[L4_EIPC_HI - L4_EIPC_LO] = { + [0] = "OK", + [L4_IPC_SETIMEOUT] = "Send timeout", + [L4_IPC_RETIMEOUT] = "Receive timeout", + [L4_IPC_ENOT_EXISTENT] = "Void capability invoked", + [L4_IPC_SECANCELED] = "Send operation canceled", + [L4_IPC_RECANCELED] = "Receive operation canceled", + [L4_IPC_SEMSGCUT] = "Overflow during send operation", + [L4_IPC_REMSGCUT] = "Overflow during receive operation", + [L4_IPC_SESNDPFTO] = "Send page-fault timeout (send phase)", + [L4_IPC_RESNDPFTO] = "Send page-fault timeout (receive phase)", + [L4_IPC_SERCVPFTO] = "Receive page-fault timeout (send phase)", + [L4_IPC_RERCVPFTO] = "Receive page-fault timeout (receive phase)", + [L4_IPC_SEABORTED] = "Send operation aborted", + [L4_IPC_REABORTED] = "Receive operation aborted", + [L4_IPC_SEMAPFAILED] = "Map operation failed (send phase)", + [L4_IPC_REMAPFAILED] = "Map operation failed (receive phase)" +}; + +L4_CV char const *l4sys_errtostr(long err) +{ + err = -err; + if (err >= 0 && err < L4_ERRNOMAX) + return _l4sys_errortab[err]; + else if (err >= L4_EIPC_LO && err < L4_EIPC_HI) + return _l4sys_ipc_errortab[err-L4_EIPC_LO]; + else + return "bad, unknown runtime error"; +} diff --git a/l4/pkg/l4sys/lib/src/kobject.cc b/l4/pkg/l4sys/lib/src/kobject.cc new file mode 100644 index 00000000..2d2437f0 --- /dev/null +++ b/l4/pkg/l4sys/lib/src/kobject.cc @@ -0,0 +1,3 @@ +#include + +L4::Type_info const L4::Kobject::__Kobject_typeid::_m = { 0, 0, 0, 0 }; diff --git a/l4/pkg/l4sys/lib/src/utcb.c b/l4/pkg/l4sys/lib/src/utcb.c new file mode 100644 index 00000000..74435db7 --- /dev/null +++ b/l4/pkg/l4sys/lib/src/utcb.c @@ -0,0 +1,32 @@ +/*! + * \file l4sys/lib/src/utcb.c + * \brief utcb + * + * \date 2007-11-20 + * \author Adam Lackorzynski + * + */ +/* + * (c) 2007-2009 Author(s) + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ + +#include + +L4_CV __attribute__((weak)) l4_utcb_t *l4_utcb_wrap(void) +{ + return l4_utcb_direct(); +} diff --git a/l4/pkg/l4util/Control b/l4/pkg/l4util/Control new file mode 100644 index 00000000..a145c918 --- /dev/null +++ b/l4/pkg/l4util/Control @@ -0,0 +1,3 @@ +provides: l4util +requires: crtn libc-headers +Maintainer: adam@os.inf.tu-dresden.de diff --git a/l4/pkg/l4util/LEGAL b/l4/pkg/l4util/LEGAL new file mode 100644 index 00000000..67a90c53 --- /dev/null +++ b/l4/pkg/l4util/LEGAL @@ -0,0 +1,78 @@ +# Format: (all on one line) +# Source file : Copyright Owner(s) : License +# Please use "TUD" when referring to TU Dresden. +# If sole owner is TUD, the license field defaults to GPL and can be +# left empty. +# Source-file spec can be a directory name or a wildcard like "src/*.c". +doc : TUD +examples : TUD +include/ARCH-x86/L4API-l4f : TUD +include/ARCH-x86/apic.h : GPL +include/ARCH-x86/atomic_arch.h : TUD +include/ARCH-x86/bitops.h : TUD +include/ARCH-x86/cpu.h : TUD +include/ARCH-x86/idt.h : TUD +include/ARCH-x86/irq.h : TUD +include/ARCH-x86/lock_wq.h : TUD +include/ARCH-x86/mb_info.h : GPL +include/ARCH-x86/mbi_argv.h : GPL +include/ARCH-x86/perform.h : GPL +include/ARCH-x86/port_io.h : TUD +include/ARCH-x86/rdtsc.h : TUD +include/ARCH-x86/spin.h : TUD +include/ARCH-x86/stack_impl.h : TUD +include/ARCH-x86/util.h : TUD +include/ARCH-arm/__libc_panic.h : TUD +include/ARCH-arm/atomic_arch.h : TUD +include/ARCH-arm/bitops.h : TUD +include/ARCH-arm/cpu.h : TUD +include/ARCH-arm/irq.h : TUD +include/ARCH-arm/lock_wq.h : TUD +include/ARCH-arm/mb_info.h : TUD +include/ARCH-arm/mbi_argv.h : TUD +include/Makefile : TUD +include/alloc.h : TUD +include/atomic.h : TUD +include/getopt.h : GPL +include/kip.h : TUD +include/lock.h : TUD +include/macros.h : TUD +include/memdesc.h : TUD +include/parse_cmd.h : TUD +include/queue.h : TUD +include/rand.h : TUD +include/reboot.h : TUD +include/sll.h : TUD +include/slmap.h : TUD +include/stack.h : TUD +include/thread.h : TUD +include/util.h : TUD +include/wait_queue.h : TUD +lib/Makefile : TUD +lib/src/ARCH-arm : TUD +lib/src/ARCH-x86/apic.c : GPL +lib/src/ARCH-x86/kip_area.S : TUD +lib/src/ARCH-x86/perform.c : TUD +lib/src/ARCH-x86/pmc_events.in : TUD +lib/src/ARCH-x86/rdtsc.c : GPL +lib/src/ARCH-x86/reboot.c : TUD +lib/src/ARCH-x86/spin.c : TUD +lib/src/Makefile : TUD +lib/src/__main.c : TUD +lib/src/alloc.c : TUD +lib/src/base64.c : Trantor Standard Systems Inc. : MIT +lib/src/getopt2.c : TUD +lib/src/kip.c : TUD +lib/src/memdesc.c : TUD +lib/src/micros2l4to.c : TUD +lib/src/parse_cmdline.c : TUD +lib/src/queue.c : TUD +lib/src/rand.c : TUD +lib/src/reboot.c : TUD +lib/src/reboot_arch.h : TUD +lib/src/setjmp.c : TUD +lib/src/sleep.c : TUD +lib/src/slmap.c : TUD +lib/src/thread.c : TUD +lib/src/wait_queue.c : TUD + diff --git a/l4/pkg/l4util/Makefile b/l4/pkg/l4util/Makefile new file mode 100644 index 00000000..f8ca7cc2 --- /dev/null +++ b/l4/pkg/l4util/Makefile @@ -0,0 +1,4 @@ +PKGDIR = . +L4DIR ?= $(PKGDIR)/../.. + +include $(L4DIR)/mk/subdir.mk diff --git a/l4/pkg/l4util/README b/l4/pkg/l4util/README new file mode 100644 index 00000000..1efa266a --- /dev/null +++ b/l4/pkg/l4util/README @@ -0,0 +1,19 @@ +Miscellaneous functionality not belonging to other packages. + +This package implements some functionality which doesn't fit into other +packages, mainly to support some features of a C library and to support some +features of the L4 microkernel: + +- programming of the Local APIC of x86 processors (PPro+) +- using the time stamp counter of x86 processors (Pentium+) +- using the performance counters of x86 processors (Pentium+) +- atomic operations (compare and exchange) +- bit and bit field manipulation operations +- x86 port I/O (in/out) +- x86 cli/sti, irq_acknowledge for the fully special nested mode +- comfortable parsing of command line arguments +- a simple random number generator +- touching memory to preclude later pagefaults +- a very simple lock implementation (better use the L4env lock package) +- a simple function for creating threads (better use the L4env thread package) +- etc. diff --git a/l4/pkg/l4util/doc/Makefile b/l4/pkg/l4util/doc/Makefile new file mode 100644 index 00000000..aea908be --- /dev/null +++ b/l4/pkg/l4util/doc/Makefile @@ -0,0 +1,6 @@ +PKGDIR = .. +L4DIR ?= $(PKGDIR)/../.. + +SRC_DOX_REF = l4util.cfg + +include $(L4DIR)/mk/doc.mk diff --git a/l4/pkg/l4util/doc/files.cfg b/l4/pkg/l4util/doc/files.cfg new file mode 100644 index 00000000..6c77fde8 --- /dev/null +++ b/l4/pkg/l4util/doc/files.cfg @@ -0,0 +1,3 @@ +INPUT += arm/l4f/l4/util arm/l4/util amd64/l4f/l4/util amd64/l4/util \ + l4/util x86/l4f/l4/util x86/l4/util + diff --git a/l4/pkg/l4util/doc/footer.html b/l4/pkg/l4util/doc/footer.html new file mode 100644 index 00000000..88be12eb --- /dev/null +++ b/l4/pkg/l4util/doc/footer.html @@ -0,0 +1,10 @@ + + +


+
+ + diff --git a/l4/pkg/l4util/doc/header.html b/l4/pkg/l4util/doc/header.html new file mode 100644 index 00000000..1954645c --- /dev/null +++ b/l4/pkg/l4util/doc/header.html @@ -0,0 +1,12 @@ + + + L4 Utilities + + + + +
+ Main Page   + File List   +
+
diff --git a/l4/pkg/l4util/doc/l4util.cfg b/l4/pkg/l4util/doc/l4util.cfg new file mode 100644 index 00000000..00621922 --- /dev/null +++ b/l4/pkg/l4util/doc/l4util.cfg @@ -0,0 +1,911 @@ +# Doxyfile 1.2.15 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project +# +# All text after a hash (#) is considered a comment and will be ignored +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" ") + +#--------------------------------------------------------------------------- +# General configuration options +#--------------------------------------------------------------------------- + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded +# by quotes) that should identify the project. + +PROJECT_NAME = "L4 Miscellaneous Functions Library" + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = l4util + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Brazilian, Chinese, Croatian, Czech, Danish, Dutch, Finnish, French, +# German, Greek, Hungarian, Italian, Japanese, Korean, Norwegian, Polish, +# Portuguese, Romanian, Russian, Slovak, Slovene, Spanish and Swedish. + +OUTPUT_LANGUAGE = English + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = NO + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = YES + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = YES + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = YES + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these class will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all inherited +# members of a class in the documentation of that class as if those members were +# ordinary class members. Constructors, destructors and assignment operators of +# the base classes will not be shown. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = NO + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. It is allowed to use relative paths in the argument list. + +STRIP_FROM_PATH = + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = YES + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower case letters. If set to YES upper case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# users are adviced to set this option to NO. + +CASE_SENSE_NAMES = YES + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful is your file systems +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = NO + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = YES + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like the Qt-style comments (thus requiring an +# explict @brief command for a brief description. + +JAVADOC_AUTOBRIEF = YES + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# reimplements. + +INHERIT_DOCS = YES + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = NO + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = YES + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 8 + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = YES + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = "reviewer=\par Reviewer:\n" \ + "witness=\par Witnesses:\n" \ + "risks=\par Risks:\n" + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or define consist of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and defines in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources +# only. Doxygen will then generate output that is more tailored for C. +# For instance some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = YES + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources +# only. Doxygen will then generate output that is more tailored for Java. +# For instance namespaces will be presented as packages, qualified scopes +# will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = NO + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = YES + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = YES + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +@INCLUDE = $(L4DIR)/pkg/l4util/doc/files.cfg + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx *.hpp +# *.h++ *.idl *.odl + +FILE_PATTERNS = *.h \ + *.idl + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used select whether or not files or directories +# that are symbolic links (a Unix filesystem feature) are excluded from the input. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. + +EXCLUDE_PATTERNS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = . + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. + +INPUT_FILTER = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse. + +FILTER_SOURCE_FILES = NO + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. + +SOURCE_BROWSER = YES + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# If the REFERENCED_BY_RELATION tag is set to YES (the default) +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = YES + +# If the REFERENCES_RELATION tag is set to YES (the default) +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = YES + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = NO + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. + +HTML_HEADER = $(L4DIR)/pkg/l4util/doc/header.html + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = $(L4DIR)/pkg/l4util/doc/footer.html + +# The HTML_STYLESHEET tag can be used to specify a user defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet + +HTML_STYLESHEET = + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. + +HTML_ALIGN_MEMBERS = YES + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the Html help documentation and to the tree view. + +TOC_EXPAND = NO + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. + +DISABLE_INDEX = YES + +# This tag can be used to set the number of enum values (range [1..20]) +# that doxygen will group on one line in the generated HTML documentation. + +ENUM_VALUES_PER_LINE = 4 + +# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be +# generated containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript and frames is required (for instance Mozilla, Netscape 4.0+, +# or Internet explorer 4.0+). Note that for large projects the tree generation +# can take a very long time. In such cases it is better to disable this feature. +# Windows users are probably better off using the HTML help feature. + +GENERATE_TREEVIEW = NO + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = NO + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be invoked. If left blank `latex' will be used as the default command name. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, a4wide, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = a4wide + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = NO + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = NO + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimised for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assigments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_XML = NO + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = YES + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_PREDEFINED tags. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# in the INCLUDE_PATH (see below) will be search if a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. + +PREDEFINED = DOXYGEN \ + L4_INLINE=inline \ + EXTERN_C_BEGIN= \ + EXTERN_C_END= \ + __attribute__(x)= + +# If the MACRO_EXPANSION and EXPAND_PREDEF_ONLY tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all function-like macros that are alone +# on a line and do not end with a semicolon. Such function macros are typically +# used for boiler-plate code, and will confuse the parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::addtions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES tag can be used to specify one or more tagfiles. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in Html, RTF and LaTeX) for classes with base or +# super classes. Setting the tag to NO turns the diagrams off. Note that this +# option is superceded by the HAVE_DOT option below. This is only a fallback. It is +# recommended to install and use dot, since it yield more powerful graphs. + +CLASS_DIAGRAMS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = NO + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# the CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = YES + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = YES + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = YES + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are png, jpg, or gif +# If left blank png will be used. + +DOT_IMAGE_FORMAT = png + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found on the path. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = + +# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width +# (in pixels) of the graphs generated by dot. If a graph becomes larger than +# this value, doxygen will try to truncate the graph, so that it fits within +# the specified constraint. Beware that most browsers cannot cope with very +# large images. + +MAX_DOT_GRAPH_WIDTH = 1024 + +# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height +# (in pixels) of the graphs generated by dot. If a graph becomes larger than +# this value, doxygen will try to truncate the graph, so that it fits within +# the specified constraint. Beware that most browsers cannot cope with very +# large images. + +MAX_DOT_GRAPH_HEIGHT = 1024 + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermedate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES + +#--------------------------------------------------------------------------- +# Configuration::addtions related to the search engine +#--------------------------------------------------------------------------- + +# The SEARCHENGINE tag specifies whether or not a search engine should be +# used. If set to NO the values of all tags below this one will be ignored. + +SEARCHENGINE = NO + diff --git a/l4/pkg/l4util/doc/l4util.dox b/l4/pkg/l4util/doc/l4util.dox new file mode 100644 index 00000000..3997248e --- /dev/null +++ b/l4/pkg/l4util/doc/l4util.dox @@ -0,0 +1,20 @@ +/*!\mainpage L4 Utilities -- Miscellaneous Helper Functions + + +\section Function Overview +- \ref atomic +- \ref bitops +- \ref port_io +- \ref rdtsc +- \ref idt +- \ref parse_cmd +- \ref thread +- \ref kip +- \ref reboot + + +\section sec_about About this documentation + +\author several people of the Dresden OS group +*/ + diff --git a/l4/pkg/l4util/include/ARCH-amd64/L4API-l4f/l4_macros.h b/l4/pkg/l4util/include/ARCH-amd64/L4API-l4f/l4_macros.h new file mode 100644 index 00000000..d61161a1 --- /dev/null +++ b/l4/pkg/l4util/include/ARCH-amd64/L4API-l4f/l4_macros.h @@ -0,0 +1,34 @@ +/*****************************************************************************/ +/** + * \file + * \brief Some useful generic macros, L4f version + * + * \date 11/12/2002 + * \author Lars Reuther */ +/* + * (c) 2000-2009 Author(s) + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ + +/*****************************************************************************/ + +#include_next + +#ifndef _L4UTIL__ARCH_AMD64__L4F__L4_MACROS_H +#define _L4UTIL__ARCH_AMD64__L4F__L4_MACROS_H + +/***************************************************************************** + *** generic macros + *****************************************************************************/ + +/* generate L4 thread id printf string */ +#ifndef l4util_idstr +# define l4util_idfmt "%lx" +# define l4util_idfmt_adjust "%04lx" +# define l4util_idstr(tid) (tid >> L4_CAP_SHIFT) +#endif + +#endif /* !_L4UTIL__ARCH_AMD64__L4F__L4_MACROS_H */ diff --git a/l4/pkg/l4util/include/ARCH-amd64/L4API-l4f/port_io.h b/l4/pkg/l4util/include/ARCH-amd64/L4API-l4f/port_io.h new file mode 100644 index 00000000..a36e6129 --- /dev/null +++ b/l4/pkg/l4util/include/ARCH-amd64/L4API-l4f/port_io.h @@ -0,0 +1,12 @@ +/** + * \file + * \brief Port I/O functions. + */ +/* + * (c) 2008-2009 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ +#include diff --git a/l4/pkg/l4util/include/ARCH-amd64/L4API-l4f/setjmp.h b/l4/pkg/l4util/include/ARCH-amd64/L4API-l4f/setjmp.h new file mode 100644 index 00000000..b036b969 --- /dev/null +++ b/l4/pkg/l4util/include/ARCH-amd64/L4API-l4f/setjmp.h @@ -0,0 +1,77 @@ +/*! + * \file + * \brief Inter-thread setjmp/longjmp + * + * \date 12/21/2005 + * \author Jork Loeser + * + */ +/* + * (c) 2004-2009 Author(s) + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ +#ifndef __UTIL_INCLUDE_ARCH_AMD64_L4API_L4F_SETJMP_H_ +#define __UTIL_INCLUDE_ARCH_AMd64_L4API_L4F_SETJMP_H_ +#include +#include + +EXTERN_C_BEGIN + +typedef struct{ + l4_umword_t r8; /* 0x00 */ + l4_umword_t r9; /* 0x08 */ + l4_umword_t r10; /* 0x10 */ + l4_umword_t r11; /* 0x18 */ + l4_umword_t r12; /* 0x20 */ + l4_umword_t r13; /* 0x28 */ + l4_umword_t r14; /* 0x30 */ + l4_umword_t r15; /* 0x38 */ + l4_umword_t rbx; /* 0x40 */ + l4_umword_t rsi; /* 0x48 */ + l4_umword_t rbp; /* 0x50 */ + l4_umword_t rsp; /* 0x58 */ + l4_umword_t rip; /* 0x60 */ + l4_umword_t rip_caller; /* 0x68 */ + l4_umword_t rflags; /* 0x70 */ + l4_umword_t stack[40]; +} l4_thread_jmp_buf_s; +typedef int l4_thread_jmp_buf[sizeof(l4_thread_jmp_buf_s)/sizeof(l4_umword_t)]; + +typedef union{ + l4_thread_jmp_buf_s s; + l4_thread_jmp_buf raw; +} l4_thread_jmp_buf_u; + +/*\brief inter-thread setjmp + * + * \param env jump buffer + * \retval 0 returned directly + * \retval !0 returned from longjmp + * + * Use this function to prepare a longjmp from another thread for this thread. + * + * \see setjmp(3) + */ +L4_CV int l4_thread_setjmp(l4_thread_jmp_buf env); + +/*!\brief inter-thread longjmp + * + * \param thread thread to apply the longjmp to + * \param env jump buffer + * \param val 0: setjmp returns with 1 + * \param val !0: return value of setjmp + * + * This function sets #thread to the location obtained by its former + * l4_thread_setjump on #env. + * + * \see longjmp(3) + * \note In contrast to longjmp(3), this function returns. + */ +L4_CV void l4_thread_longjmp(l4_threadid_t thread, l4_thread_jmp_buf env, int val); + +EXTERN_C_END + +#endif diff --git a/l4/pkg/l4util/include/ARCH-amd64/apic.h b/l4/pkg/l4util/include/ARCH-amd64/apic.h new file mode 100644 index 00000000..0e8766c1 --- /dev/null +++ b/l4/pkg/l4util/include/ARCH-amd64/apic.h @@ -0,0 +1,415 @@ +/** + * \file + * \brief APIC for AMD64 + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Torsten Frenzel + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ +#ifndef __L4_UTIL_APIC_H +#define __L4_UTIL_APIC_H + +/* + * Local APIC programming library + * + * For documentation, see + * + * "Intel Architecture Software Developer's Manual", Volume 3, chapter 7.5: + * "Advanced Programmable Interrupt Controller (APIC)" + * + * Local APIC is present since + * - INTEL P6 (PPro) + * - AMD K7 (Athlon), Model 2 + * + * In non-SMP-boards, local APIC is disabled, but + * can be activated by writing to a MSR register. + * For using APIC see packets cpufreq and l4rtl. + * + * See linux/include/asm-i386/i82489.h for further details. + */ + +#define APIC_PHYS_BASE 0xFEE00000 +#define APIC_MAP_BASE 0xA0200000 +#define APIC_BASE_MSR 0x1b + +#define APIC_ID 0x20 +#define GET_APIC_ID(x) (((x)>>24)&0x0F) +#define APIC_LVR 0x30 +#define GET_APIC_VERSION(x) ((x)&0xFF) +#define APIC_TASKPRI 0x80 +#define APIC_TPRI_MASK 0xFF +#define APIC_EOI 0xB0 +#define APIC_LDR 0xD0 +#define APIC_LDR_MASK (0xFF<<24) +#define APIC_DFR 0xE0 +#define SET_APIC_DFR(x) ((x)<<28) +#define APIC_SPIV 0xF0 +#define APIC_LVTT 0x320 +#define APIC_LVTPC 0x340 +#define APIC_LVT0 0x350 +#define SET_APIC_TIMER_BASE(x) (((x)<<18)) +#define APIC_TIMER_BASE_DIV 0x2 +#define APIC_LVT1 0x360 +#define APIC_LVTERR 0x370 +#define APIC_TMICT 0x380 +#define APIC_TMCCT 0x390 +#define APIC_TDCR 0x3E0 + +#define APIC_LVT_MASKED (1<<16) +#define APIC_LVT_TIMER_PERIODIC (1<<17) +#define APIC_TDR_DIV_1 0xB +#define APIC_TDR_DIV_2 0x0 +#define APIC_TDR_DIV_4 0x1 +#define APIC_TDR_DIV_8 0x2 +#define APIC_TDR_DIV_16 0x3 +#define APIC_TDR_DIV_32 0x8 +#define APIC_TDR_DIV_64 0x9 +#define APIC_TDR_DIV_128 0xA + +#include +#include + +EXTERN_C_BEGIN + +/* prototypes */ +extern unsigned long apic_map_base; +extern unsigned long apic_timer_divisor; + +extern unsigned long l4_scaler_apic_to_ms; + +L4_CV void apic_show_registers(void); +L4_CV int apic_check_working(void); +L4_CV void apic_activate_by_io(void); +L4_CV void apic_timer_set_divisor(int divisor); + +L4_CV unsigned long l4_calibrate_apic(void); + +EXTERN_C_END + +L4_INLINE void apic_write(unsigned long reg, unsigned long v); +L4_INLINE unsigned long apic_read(unsigned long reg); +L4_INLINE void apic_activate_by_msr(void); +L4_INLINE void apic_deactivate_by_msr(void); +L4_INLINE unsigned long apic_read_phys_address(void); +L4_INLINE int apic_test_present(void); +L4_INLINE void apic_soft_enable(void); +L4_INLINE void apic_init(unsigned long map_addr); +L4_INLINE void apic_done(void); +L4_INLINE void apic_irq_ack(void); + +L4_INLINE void apic_lvt0_disable_irq(void); +L4_INLINE void apic_lvt0_enable_irq(void); +L4_INLINE void apic_lvt1_disable_irq(void); +L4_INLINE void apic_lvt1_enable_irq(void); + +L4_INLINE void apic_timer_write(unsigned long value); +L4_INLINE unsigned long apic_timer_read(void); +L4_INLINE void apic_timer_disable_irq(void); +L4_INLINE void apic_timer_enable_irq(void); +L4_INLINE void apic_timer_assign_irq(unsigned long vector); +L4_INLINE void apic_timer_set_periodic(void); +L4_INLINE void apic_timer_set_one_shot(void); + +L4_INLINE void apic_perf_disable_irq(void); +L4_INLINE void apic_perf_enable_irq(void); +L4_INLINE void apic_perf_assign_irq(unsigned long vector); + + +/* write APIC register */ +L4_INLINE void +apic_write(unsigned long reg, unsigned long v) +{ + *((volatile unsigned long *)(apic_map_base+reg))=v; +} + + +/* read APIC register */ +L4_INLINE unsigned long +apic_read(unsigned long reg) +{ + return *((volatile unsigned long *)(apic_map_base+reg)); +} + + +/* disable LINT0 */ +L4_INLINE void +apic_lvt0_disable_irq(void) +{ + unsigned long tmp_val; + tmp_val = apic_read(APIC_LVT0); + tmp_val |= APIC_LVT_MASKED; + apic_write(APIC_LVT0, tmp_val); +} + + +/* enable LINT0 */ +L4_INLINE void +apic_lvt0_enable_irq(void) +{ + unsigned long tmp_val; + tmp_val = apic_read(APIC_LVT0); + tmp_val &= ~(APIC_LVT_MASKED); + apic_write(APIC_LVT0, tmp_val); +} + + +/* disable LINT1 */ +L4_INLINE void +apic_lvt1_disable_irq(void) +{ + unsigned long tmp_val; + tmp_val = apic_read(APIC_LVT1); + tmp_val |= APIC_LVT_MASKED; + apic_write(APIC_LVT1, tmp_val); +} + + +/* enable LINT1 */ +L4_INLINE void +apic_lvt1_enable_irq(void) +{ + unsigned long tmp_val; + tmp_val = apic_read(APIC_LVT1); + tmp_val &= ~(APIC_LVT_MASKED); + apic_write(APIC_LVT1, tmp_val); +} + + +/* write APIC timer register */ +L4_INLINE void +apic_timer_write(unsigned long value) +{ + apic_read(APIC_TMICT); + apic_write(APIC_TMICT,value); +} + + +/* read APIC timer register */ +L4_INLINE unsigned long +apic_timer_read(void) +{ + return apic_read(APIC_TMCCT); +} + + +/* disable IRQ when APIC timer passes 0 */ +L4_INLINE void +apic_timer_disable_irq(void) +{ + unsigned long tmp_val; + tmp_val = apic_read(APIC_LVTT); + tmp_val |= APIC_LVT_MASKED; + apic_write(APIC_LVTT, tmp_val); +} + + +/* enable IRQ when APIC timer passes 0 */ +L4_INLINE void +apic_timer_enable_irq(void) +{ + unsigned long tmp_val; + tmp_val = apic_read(APIC_LVTT); + tmp_val &= ~(APIC_LVT_MASKED); + apic_write(APIC_LVTT, tmp_val); +} + + +L4_INLINE void +apic_timer_set_periodic(void) +{ + unsigned long tmp_val; + tmp_val = apic_read(APIC_LVTT); + tmp_val |= APIC_LVT_TIMER_PERIODIC; + tmp_val |= APIC_LVT_MASKED; + apic_write(APIC_LVTT, tmp_val); +} + + +L4_INLINE void +apic_timer_set_one_shot(void) +{ + unsigned long tmp_val; + tmp_val = apic_read(APIC_LVTT); + tmp_val &= ~APIC_LVT_TIMER_PERIODIC; + tmp_val |= APIC_LVT_MASKED; + apic_write(APIC_LVTT, tmp_val); +} + + +/* set vector of APIC timer irq */ +L4_INLINE void +apic_timer_assign_irq(unsigned long vector) +{ + unsigned long tmp_val; + tmp_val = apic_read(APIC_LVTT); + tmp_val &= 0xffffff00; + tmp_val |= vector; + tmp_val |= APIC_LVT_MASKED; + apic_write(APIC_LVTT, tmp_val); +} + + +/* disable IRQ when performance counter passes 0 */ +L4_INLINE void +apic_perf_disable_irq(void) +{ + unsigned long tmp_val; + tmp_val = apic_read(APIC_LVTPC); + tmp_val |= APIC_LVT_MASKED; + apic_write(APIC_LVTPC, tmp_val); +} + + +/* enable IRQ when performance counter passes 0 */ +L4_INLINE void +apic_perf_enable_irq(void) +{ + unsigned long tmp_val; + tmp_val = apic_read(APIC_LVTPC); + tmp_val &= ~(APIC_LVT_MASKED); + apic_write(APIC_LVTPC, tmp_val); +} + + +/* set vector of performance counter irq */ +L4_INLINE void +apic_perf_assign_irq(unsigned long vector) +{ + unsigned long tmp_val; + tmp_val = apic_read(APIC_LVTPC); + tmp_val &= 0xffffff00; + tmp_val |= vector; + tmp_val |= APIC_LVT_MASKED; + apic_write(APIC_LVTPC, tmp_val); +} + + +/* activate APIC by writing to appropriate MSR */ +L4_INLINE void +apic_activate_by_msr(void) +{ + unsigned long low; + unsigned long high; + + /* rdmsr */ + asm volatile(".byte 0xf; .byte 0x32\n" + :"=a" (low), + "=d" (high) + :"c" (APIC_BASE_MSR) + ); + + low |= 0x800; /* activate APIC */ + low &= 0x00000fff; + low |= (APIC_PHYS_BASE & 0xfffff000); /* set address */ + + /* wrmsr */ + asm volatile(".byte 0xf; .byte 0x30\n" + : + :"c" (APIC_BASE_MSR), + "a" (low), + "d" (high) + ); +} + + +/* deactivate APIC by writing to appropriate MSR */ +L4_INLINE void +apic_deactivate_by_msr(void) +{ + unsigned long low; + unsigned long high; + + /* rdmsr */ + asm volatile(".byte 0xf; .byte 0x32\n" + :"=a" (low), + "=d" (high) + :"c" (APIC_BASE_MSR) + ); + + low &= 0xfffff7ff; /* deactivate APIC */ + + /* wrmsr */ + asm volatile(".byte 0xf; .byte 0x30\n" + : + :"c" (APIC_BASE_MSR), + "a" (low), + "d" (high) + ); +} + + +/* read memory mapped address of apic */ +L4_INLINE unsigned long +apic_read_phys_address(void) +{ + unsigned long low; + unsigned long high; + + /* rdmsr */ + asm volatile(".byte 0xf; .byte 0x32\n" + :"=a" (low), + "=d" (high) + :"c" (APIC_BASE_MSR) + ); + + return (low &= 0xfffff000); +} + + +/* test if APIC present */ +L4_INLINE int +apic_test_present(void) +{ + unsigned int dummy; + unsigned int capability; + + asm volatile("pushl %%ebx ; cpuid ; popl %%ebx" + : "=a" (dummy), + "=c" (dummy), + "=d" (capability) + : "a" (0x00000001) + : "cc"); + + return ((capability & 1<<9) !=0); +} + + +L4_INLINE void +apic_soft_enable(void) +{ + unsigned long tmp_val; + tmp_val = apic_read(APIC_SPIV); + tmp_val |= (1<<8); /* enable APIC */ + tmp_val &= ~(1<<9); /* enable Focus Processor Checking */ + tmp_val |= 0xff; /* Set spurious IRQ vector to 0xff */ + apic_write(APIC_SPIV, tmp_val); +} + + +L4_INLINE void +apic_init(unsigned long base_addr) +{ + apic_map_base = base_addr; +} + + +L4_INLINE void +apic_done(void) +{ + apic_map_base = 0; +} + + +L4_INLINE void +apic_irq_ack(void) +{ + apic_read(APIC_SPIV); + apic_write(APIC_EOI, 0); +} + + +#endif /* __L4_UTIL_APIC_H */ diff --git a/l4/pkg/l4util/include/ARCH-amd64/atomic_arch.h b/l4/pkg/l4util/include/ARCH-amd64/atomic_arch.h new file mode 100644 index 00000000..577de68d --- /dev/null +++ b/l4/pkg/l4util/include/ARCH-amd64/atomic_arch.h @@ -0,0 +1,451 @@ +/*****************************************************************************/ +/** + * \file + * \brief i386 atomic operations + * \ingroup atomic + * + * \date 10/20/2000 + * \author Lars Reuther , + * Jork Loeser */ +/* + * (c) 2000-2009 Author(s) + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ + +/*****************************************************************************/ +#ifndef __L4UTIL__INCLUDE__ARCH_AMD64__ATOMIC_ARCH_H__ +#define __L4UTIL__INCLUDE__ARCH_AMD64__ATOMIC_ARCH_H__ + +/***************************************************************************** + *** Prototypes + *****************************************************************************/ + +#define LOCK "lock;" + +EXTERN_C_BEGIN + +L4_INLINE l4_uint64_t +l4util_xchg64(volatile l4_uint64_t * dest, l4_uint64_t val); + +L4_INLINE l4_uint64_t +l4util_cmpxchg64_res(volatile l4_uint64_t *dest, + l4_uint64_t cmp_val, l4_uint64_t new_val); +L4_INLINE void +l4util_add64(volatile l4_uint64_t *dest, l4_uint64_t val); +L4_INLINE void +l4util_sub64(volatile l4_uint64_t *dest, l4_uint64_t val); +L4_INLINE void +l4util_and64(volatile l4_uint64_t *dest, l4_uint64_t val); +L4_INLINE void +l4util_or64(volatile l4_uint64_t *dest, l4_uint64_t val); +L4_INLINE l4_uint64_t +l4util_add64_res(volatile l4_uint64_t *dest, l4_uint64_t val); +L4_INLINE l4_uint64_t +l4util_sub64_res(volatile l4_uint64_t *dest, l4_uint64_t val); +L4_INLINE l4_uint64_t +l4util_and64_res(volatile l4_uint64_t *dest, l4_uint64_t val); +L4_INLINE l4_uint64_t +l4util_or64_res(volatile l4_uint64_t *dest, l4_uint64_t val); +L4_INLINE void +l4util_inc64(volatile l4_uint64_t *dest); +L4_INLINE void +l4util_dec64(volatile l4_uint64_t *dest); +L4_INLINE l4_uint64_t +l4util_inc64_res(volatile l4_uint64_t *dest); +L4_INLINE l4_uint64_t +l4util_dec64_res(volatile l4_uint64_t *dest); + +EXTERN_C_END + +/***************************************************************************** + *** Implementation + *****************************************************************************/ + +/* atomic compare and exchange 64 bit value */ +#define __L4UTIL_ATOMIC_HAVE_ARCH_CMPXCHG64 +L4_INLINE int +l4util_cmpxchg64(volatile l4_uint64_t * dest, + l4_uint64_t cmp_val, l4_uint64_t new_val) +{ + l4_uint64_t tmp; + + __asm__ __volatile__ + ( + LOCK "cmpxchgq %1, %3 \n\t" + : + "=a" (tmp) /* 0 RAX, return val */ + : + "r" (new_val), /* 1 reg, new value */ + "0" (cmp_val), /* 2 RAX, compare value */ + "m" (*dest) /* 3 mem, destination operand */ + : + "memory", "cc" + ); + + return tmp == cmp_val; +} + +/* atomic compare and exchange 32 bit value */ +#define __L4UTIL_ATOMIC_HAVE_ARCH_CMPXCHG32 +L4_INLINE int +l4util_cmpxchg32(volatile l4_uint32_t * dest, + l4_uint32_t cmp_val, l4_uint32_t new_val) +{ + l4_uint32_t tmp; + + __asm__ __volatile__ + ( + LOCK "cmpxchgl %1, %3 \n\t" + : + "=a" (tmp) /* 0 EAX, return val */ + : + "r" (new_val), /* 1 reg, new value */ + "0" (cmp_val), /* 2 EAX, compare value */ + "m" (*dest) /* 3 mem, destination operand */ + : + "memory", "cc" + ); + + return tmp == cmp_val; +} + +/* atomic compare and exchange 16 bit value */ +#define __L4UTIL_ATOMIC_HAVE_ARCH_CMPXCHG16 +L4_INLINE int +l4util_cmpxchg16(volatile l4_uint16_t * dest, + l4_uint16_t cmp_val, l4_uint16_t new_val) +{ + l4_uint16_t tmp; + + __asm__ __volatile__ + ( + LOCK "cmpxchgw %1, %3 \n\t" + : + "=a" (tmp) /* 0 AX, return value */ + : + "c" (new_val), /* 1 CX, new value */ + "0" (cmp_val), /* 2 AX, compare value */ + "m" (*dest) /* 3 mem, destination operand */ + : + "memory", "cc" + ); + + return tmp == cmp_val; +} + +/* atomic compare and exchange 8 bit value */ +#define __L4UTIL_ATOMIC_HAVE_ARCH_CMPXCHG8 +L4_INLINE int +l4util_cmpxchg8(volatile l4_uint8_t * dest, + l4_uint8_t cmp_val, l4_uint8_t new_val) +{ + l4_uint8_t tmp; + + __asm__ __volatile__ + ( + LOCK "cmpxchgb %1, %3 \n\t" + : + "=a" (tmp) /* 0 AL, return value */ + : + "c" (new_val), /* 1 CL, new value */ + "0" (cmp_val), /* 2 AL, compare value */ + "m" (*dest) /* 3 mem, destination operand */ + : + "memory", "cc" + ); + + return tmp == cmp_val; +} + +#define __L4UTIL_ATOMIC_HAVE_ARCH_CMPXCHG +L4_INLINE int +l4util_cmpxchg(volatile l4_umword_t * dest, + l4_umword_t cmp_val, l4_umword_t new_val) +{ + return l4util_cmpxchg64((volatile l4_uint64_t *)dest, + (l4_uint64_t)cmp_val, (l4_uint64_t)new_val); +} + +/* atomic exchange 64 bit value */ +#define __L4UTIL_ATOMIC_HAVE_ARCH_XCHG64 +L4_INLINE l4_uint64_t +l4util_xchg64(volatile l4_uint64_t * dest, l4_uint64_t val) +{ + __asm__ __volatile__ + ( + LOCK "xchg %0, %1 \n\t" + : + "=r" (val) + : + "m" (*dest), "0" (val) + : + "memory" + ); + + return val; +} + +/* atomic exchange 32 bit value */ +#define __L4UTIL_ATOMIC_HAVE_ARCH_XCHG32 +L4_INLINE l4_uint32_t +l4util_xchg32(volatile l4_uint32_t * dest, l4_uint32_t val) +{ + __asm__ __volatile__ + ( + LOCK "xchg %0, %1 \n\t" + : + "=r" (val) + : + "m" (*dest), "0" (val) + : + "memory" + ); + + return val; +} + +/* atomic exchange 16 bit value */ +#define __L4UTIL_ATOMIC_HAVE_ARCH_XCHG16 +L4_INLINE l4_uint16_t +l4util_xchg16(volatile l4_uint16_t * dest, l4_uint16_t val) +{ + __asm__ __volatile__ + ( + LOCK "xchg %w0, %1 \n\t" + : + "=r" (val) + : + "m" (*dest), "0" (val) + : + "memory" + ); + + return val; +} + +/* atomic exchange 8 bit value */ +#define __L4UTIL_ATOMIC_HAVE_ARCH_XCHG8 +L4_INLINE l4_uint8_t +l4util_xchg8(volatile l4_uint8_t * dest, l4_uint8_t val) +{ + __asm__ __volatile__ + ( + LOCK "xchg %b0, %1 \n\t" + : + "=r" (val) + : + "m" (*dest), "0" (val) + : + "memory" + ); + + return val; +} + +/* atomic exchange machine width */ +#define __L4UTIL_ATOMIC_HAVE_ARCH_XCHG +L4_INLINE l4_umword_t +l4util_xchg(volatile l4_umword_t * dest, l4_umword_t val) +{ + return l4util_xchg64((volatile l4_uint64_t *)dest, (l4_uint64_t)val); +} + +#define l4util_gen_allop(args...) \ +l4util_genop( 8,"b", "", args) \ +l4util_genop(16,"w", "", args) \ +l4util_genop(32,"l", "", args) \ +l4util_genop(64,"q", "", args) + +#define __L4UTIL_ATOMIC_HAVE_ARCH_CMPXCHG8_RES +#define __L4UTIL_ATOMIC_HAVE_ARCH_CMPXCHG16_RES +#define __L4UTIL_ATOMIC_HAVE_ARCH_CMPXCHG32_RES +#define __L4UTIL_ATOMIC_HAVE_ARCH_CMPXCHG64_RES +/* Generate l4_uint{8,16,32,64} l4util_cmpxchg{8,16,32,64}_res(...) */ +#undef l4util_genop +#define l4util_genop(bit, mod, op1, opname, opchar) \ +L4_INLINE l4_uint##bit##_t \ +l4util_##opname##bit##_res(volatile l4_uint##bit##_t* dest, \ + l4_uint##bit##_t cmp_val, \ + l4_uint##bit##_t new_val) \ +{ \ + l4_uint##bit##_t old_val; \ + __asm__ __volatile__ \ + ( \ + LOCK #opname mod " %"op1"1,%3 \n\t" \ + : \ + "=a"(old_val) \ + : \ + "r"(new_val), "a"(cmp_val), "m" (*dest) \ + : \ + "memory" \ + ); \ + return old_val; \ +} +l4util_gen_allop(cmpxchg,cmpxchg) + +#define __L4UTIL_ATOMIC_HAVE_ARCH_CMPXCHG_RES +L4_INLINE l4_umword_t +l4util_cmpxchg_res(volatile l4_umword_t *dest, + l4_umword_t cmp_val, l4_umword_t new_val) +{ + return l4util_cmpxchg64_res((volatile l4_uint64_t *)dest, + (l4_uint64_t)cmp_val, (l4_uint64_t)new_val); +} + +#define __L4UTIL_ATOMIC_HAVE_ARCH_ADD8 +#define __L4UTIL_ATOMIC_HAVE_ARCH_ADD16 +#define __L4UTIL_ATOMIC_HAVE_ARCH_ADD32 +#define __L4UTIL_ATOMIC_HAVE_ARCH_ADD64 +#define __L4UTIL_ATOMIC_HAVE_ARCH_SUB8 +#define __L4UTIL_ATOMIC_HAVE_ARCH_SUB16 +#define __L4UTIL_ATOMIC_HAVE_ARCH_SUB32 +#define __L4UTIL_ATOMIC_HAVE_ARCH_SUB64 +#define __L4UTIL_ATOMIC_HAVE_ARCH_AND8 +#define __L4UTIL_ATOMIC_HAVE_ARCH_AND16 +#define __L4UTIL_ATOMIC_HAVE_ARCH_AND32 +#define __L4UTIL_ATOMIC_HAVE_ARCH_AND64 +#define __L4UTIL_ATOMIC_HAVE_ARCH_OR8 +#define __L4UTIL_ATOMIC_HAVE_ARCH_OR16 +#define __L4UTIL_ATOMIC_HAVE_ARCH_OR32 +#define __L4UTIL_ATOMIC_HAVE_ARCH_OR64 +/* Generate void l4util_{add,sub,and,or}{8,16,32,64}(*dest) */ +#undef l4util_genop +#define l4util_genop(bit, mod, op1, opname) \ +L4_INLINE void \ +l4util_##opname##bit(volatile l4_uint##bit##_t* dest, l4_uint##bit##_t val) \ +{ \ + __asm__ __volatile__ \ + ( \ + LOCK #opname mod " %1,%0 \n\t" \ + : \ + : \ + "m" (*dest), "ir" (val) \ + : \ + "memory" \ + ); \ +} +l4util_gen_allop(add) +l4util_gen_allop(sub) +l4util_gen_allop(and) +l4util_gen_allop(or) + +#define __L4UTIL_ATOMIC_HAVE_ARCH_ADD8_RES +#define __L4UTIL_ATOMIC_HAVE_ARCH_ADD16_RES +#define __L4UTIL_ATOMIC_HAVE_ARCH_ADD32_RES +#define __L4UTIL_ATOMIC_HAVE_ARCH_ADD64_RES +#define __L4UTIL_ATOMIC_HAVE_ARCH_SUB8_RES +#define __L4UTIL_ATOMIC_HAVE_ARCH_SUB16_RES +#define __L4UTIL_ATOMIC_HAVE_ARCH_SUB32_RES +#define __L4UTIL_ATOMIC_HAVE_ARCH_SUB64_RES +#define __L4UTIL_ATOMIC_HAVE_ARCH_AND8_RES +#define __L4UTIL_ATOMIC_HAVE_ARCH_AND16_RES +#define __L4UTIL_ATOMIC_HAVE_ARCH_AND32_RES +#define __L4UTIL_ATOMIC_HAVE_ARCH_AND64_RES +#define __L4UTIL_ATOMIC_HAVE_ARCH_OR8_RES +#define __L4UTIL_ATOMIC_HAVE_ARCH_OR16_RES +#define __L4UTIL_ATOMIC_HAVE_ARCH_OR32_RES +#define __L4UTIL_ATOMIC_HAVE_ARCH_OR64_RES +/* Generate l4_uint{8,16,32,64} l4util_{add,sub,and,or}{8,16,32,64}_res(*dest) */ +#undef l4util_genop +#define l4util_genop(bit, mod, op1, opname, opchar) \ +L4_INLINE l4_uint##bit##_t \ +l4util_##opname##bit##_res(volatile l4_uint##bit##_t* dest, \ + l4_uint##bit##_t val) \ +{ \ + l4_uint##bit##_t res, old; \ + \ + do \ + { \ + old = *dest; \ + res = old opchar val; \ + } \ + while (!l4util_cmpxchg##bit(dest, old, res)); \ + \ + return res; \ +} +l4util_gen_allop(add, +) +l4util_gen_allop(sub, -) +l4util_gen_allop(and, &) +l4util_gen_allop(or, &&) + +#define __L4UTIL_ATOMIC_HAVE_ARCH_INC8 +#define __L4UTIL_ATOMIC_HAVE_ARCH_INC16 +#define __L4UTIL_ATOMIC_HAVE_ARCH_INC32 +#define __L4UTIL_ATOMIC_HAVE_ARCH_INC64 +#define __L4UTIL_ATOMIC_HAVE_ARCH_DEC8 +#define __L4UTIL_ATOMIC_HAVE_ARCH_DEC16 +#define __L4UTIL_ATOMIC_HAVE_ARCH_DEC32 +#define __L4UTIL_ATOMIC_HAVE_ARCH_DEC64 +/* Generate void l4util_{inc,dec}{8,16,32,64}(*dest) */ +#undef l4util_genop +#define l4util_genop(bit, mod, op1, opname) \ +L4_INLINE void \ +l4util_##opname##bit(volatile l4_uint##bit##_t* dest) \ +{ \ + __asm__ __volatile__ \ + ( \ + LOCK #opname mod " %0 \n\t" \ + : \ + : \ + "m" (*dest) \ + : \ + "memory" \ + ); \ +} +l4util_gen_allop(inc) +l4util_gen_allop(dec) + +#define __L4UTIL_ATOMIC_HAVE_ARCH_INC8_RES +#define __L4UTIL_ATOMIC_HAVE_ARCH_INC16_RES +#define __L4UTIL_ATOMIC_HAVE_ARCH_INC32_RES +#define __L4UTIL_ATOMIC_HAVE_ARCH_INC64_RES +#define __L4UTIL_ATOMIC_HAVE_ARCH_DEC8_RES +#define __L4UTIL_ATOMIC_HAVE_ARCH_DEC16_RES +#define __L4UTIL_ATOMIC_HAVE_ARCH_DEC32_RES +#define __L4UTIL_ATOMIC_HAVE_ARCH_DEC64_RES +/* Generate l4_uint{8,16,32,64} l4util_{inc,dec}{8,16,32,64}_res(*dest) */ +#undef l4util_genop +#define l4util_genop(bit, mod, op1, opname, opchar) \ +L4_INLINE l4_uint##bit##_t \ +l4util_##opname##bit##_res(volatile l4_uint##bit##_t* dest) \ +{ \ + l4_uint##bit##_t res, old; \ + \ + do \ + { \ + res = *dest; \ + old = res opchar; \ + } \ + while (!l4util_cmpxchg##bit(dest, old, res)); \ + \ + return res; \ +} +l4util_gen_allop(inc, ++) +l4util_gen_allop(dec, --) + +#undef l4util_genop +#undef l4util_gen_allop + + +#define __L4UTIL_ATOMIC_HAVE_ARCH_ADD +L4_INLINE void +l4util_atomic_add(volatile long *dest, long val) +{ + __asm__ __volatile__(LOCK "addq %1, %0 \n" + : "=m" (*dest) + : "ri" (val), "m" (*dest)); +} + +#define __L4UTIL_ATOMIC_HAVE_ARCH_INC +L4_INLINE void +l4util_atomic_inc(volatile long *dest) +{ + __asm__ __volatile__(LOCK "incq %0" + : "=m" (*dest) + : "m" (*dest)); +} + +#endif /* ! __L4UTIL__INCLUDE__ARCH_AMD64__ATOMIC_ARCH_H__ */ diff --git a/l4/pkg/l4util/include/ARCH-amd64/bitops_arch.h b/l4/pkg/l4util/include/ARCH-amd64/bitops_arch.h new file mode 100644 index 00000000..d57c8239 --- /dev/null +++ b/l4/pkg/l4util/include/ARCH-amd64/bitops_arch.h @@ -0,0 +1,353 @@ +/*****************************************************************************/ +/** + * \file + * \brief amd64 bit manipulation functions + * \ingroup bitops + * + * \date 07/03/2001 + * \author Lars Reuther + * Torsten Frenzel + * Frank Mehnert */ +/* + * (c) 2000-2009 Author(s) + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ + +/*****************************************************************************/ +#ifndef __L4UTIL__INCLUDE__ARCH_AMD64__BITOPS_ARCH_H__ +#define __L4UTIL__INCLUDE__ARCH_AMD64__BITOPS_ARCH_H__ + +EXTERN_C_BEGIN + +/***************************************************************************** + *** Implementation + *****************************************************************************/ + +/* set bit */ +#define __L4UTIL_BITOPS_HAVE_ARCH_SET_BIT32 +L4_INLINE void +l4util_set_bit32(int b, volatile l4_uint32_t * dest) +{ + __asm__ __volatile__ + ( + "btsl %1,%0 \n\t" + : + : + "m" (*dest), /* 0 mem, destination operand */ + "Ir" (b) /* 1, bit number */ + : + "memory", "cc" + ); +} + +#define __L4UTIL_BITOPS_HAVE_ARCH_SET_BIT64 +L4_INLINE void +l4util_set_bit64(int b, volatile l4_uint64_t * dest) +{ + __asm__ __volatile__ + ( + "btsl %1,%0 \n\t" + : + : + "m" (*dest), /* 0 mem, destination operand */ + "Ir" (b) /* 1, bit number */ + : + "memory", "cc" + ); +} + +#define __L4UTIL_BITOPS_HAVE_ARCH_SET_BIT +L4_INLINE void +l4util_set_bit(int b, volatile l4_umword_t * dest) +{ + return l4util_set_bit64(b, (volatile l4_uint64_t*)dest); +} + +/* clear bit */ +#define __L4UTIL_BITOPS_HAVE_ARCH_CLEAR_BIT32 +L4_INLINE void +l4util_clear_bit32(int b, volatile l4_uint32_t * dest) +{ + __asm__ __volatile__ + ( + "btrl %1,%0 \n\t" + : + : + "m" (*dest), /* 0 mem, destination operand */ + "Ir" (b) /* 1, bit number */ + : + "memory", "cc" + ); +} + +#define __L4UTIL_BITOPS_HAVE_ARCH_CLEAR_BIT64 +L4_INLINE void +l4util_clear_bit64(int b, volatile l4_uint64_t * dest) +{ + __asm__ __volatile__ + ( + "btrl %1,%0 \n\t" + : + : + "m" (*dest), /* 0 mem, destination operand */ + "Ir" (b) /* 1, bit number */ + : + "memory", "cc" + ); +} + +#define __L4UTIL_BITOPS_HAVE_ARCH_CLEAR_BIT +L4_INLINE void +l4util_clear_bit(int b, volatile l4_umword_t * dest) +{ + return l4util_clear_bit64(b, (volatile l4_uint64_t*)dest); +} + +/* change bit */ +#define __L4UTIL_BITOPS_HAVE_ARCH_COMPLEMENT_BIT +L4_INLINE void +l4util_complement_bit(int b, volatile l4_umword_t * dest) +{ + __asm__ __volatile__ + ( + "btcq %1,%0 \n\t" + : + : + "m" (*dest), /* 0 mem, destination operand */ + "Ir" ((l4_umword_t)b) /* 1, bit number */ + : + "memory", "cc" + ); +} + +/* test bit */ +#define __L4UTIL_BITOPS_HAVE_ARCH_TEST_BIT32 +L4_INLINE int +l4util_test_bit32(int b, const volatile l4_uint32_t * dest) +{ + l4_int8_t bit; + + __asm__ __volatile__ + ( + "btl %2,%1 \n\t" + "setc %0 \n\t" + : + "=r" (bit) /* 0, old bit value */ + : + "m" (*dest), /* 1 mem, destination operand */ + "Ir" (b) /* 2, bit number */ + : + "memory", "cc" + ); + + return (int)bit; +} + +#define __L4UTIL_BITOPS_HAVE_ARCH_TEST_BIT64 +L4_INLINE int +l4util_test_bit64(int b, const volatile l4_uint64_t * dest) +{ + l4_int8_t bit; + + __asm__ __volatile__ + ( + "btl %2,%1 \n\t" + "setc %0 \n\t" + : + "=r" (bit) /* 0, old bit value */ + : + "m" (*dest), /* 1 mem, destination operand */ + "Ir" (b) /* 2, bit number */ + : + "memory", "cc" + ); + + return (int)bit; +} + +#define __L4UTIL_BITOPS_HAVE_ARCH_TEST_BIT +L4_INLINE int +l4util_test_bit(int b, const volatile l4_umword_t * dest) +{ + return l4util_test_bit64(b, (const volatile l4_uint64_t *)dest); +} + + +/* bit test and set */ +#define __L4UTIL_BITOPS_HAVE_ARCH_BIT_TEST_AND_SET +L4_INLINE int +l4util_bts(int b, volatile l4_umword_t * dest) +{ + l4_int8_t bit; + + __asm__ __volatile__ + ( + "btsl %2,%1 \n\t" + "setc %0 \n\t" + : + "=r" (bit) /* 0, old bit value */ + : + "m" (*dest), /* 1 mem, destination operand */ + "Ir" (b) /* 2, bit number */ + : + "memory", "cc" + ); + + return (int)bit; +} + +/* bit test and reset */ +#define __L4UTIL_BITOPS_HAVE_ARCH_BIT_TEST_AND_RESET +L4_INLINE int +l4util_btr(int b, volatile l4_umword_t * dest) +{ + l4_int8_t bit; + + __asm__ __volatile__ + ( + "btrl %2,%1 \n\t" + "setc %0 \n\t" + : + "=r" (bit) /* 0, old bit value */ + : + "m" (*dest), /* 1 mem, destination operand */ + "Ir" (b) /* 2, bit number */ + : + "memory", "cc" + ); + + return (int)bit; +} + +/* bit test and complement */ +#define __L4UTIL_BITOPS_HAVE_ARCH_BIT_TEST_AND_COMPLEMENT +L4_INLINE int +l4util_btc(int b, volatile l4_umword_t * dest) +{ + l4_int8_t bit; + + __asm__ __volatile__ + ( + "btc %2,%1 \n\t" + "setc %0 \n\t" + : + "=r" (bit) /* 0, old bit value */ + : + "m" (*dest), /* 1 mem, destination operand */ + "Ir" ((l4_umword_t)b) /* 2, bit number */ + : + "memory", "cc" + ); + + return (int)bit; +} + +/* bit scan reverse */ +#define __L4UTIL_BITOPS_HAVE_ARCH_BIT_SCAN_REVERSE +L4_INLINE int +l4util_bsr(l4_umword_t word) +{ + l4_umword_t tmp; + + if (EXPECT_FALSE(word == 0)) + return -1; + + __asm__ __volatile__ + ( + "bsr %1,%0 \n\t" + : + "=r" (tmp) /* 0, index of most significant set bit */ + : + "r" (word) /* 1, argument */ + ); + + return tmp; +} + +/* bit scan forwad */ +#define __L4UTIL_BITOPS_HAVE_ARCH_BIT_SCAN_FORWARD +L4_INLINE int +l4util_bsf(l4_umword_t word) +{ + l4_umword_t tmp; + + if (EXPECT_FALSE(word == 0)) + return -1; + + __asm__ __volatile__ + ( + "bsf %1,%0 \n\t" + : + "=r" (tmp) /* 0, index of least significant set bit */ + : + "r" (word) /* 1, argument */ + ); + + return tmp; +} + +#define __L4UTIL_BITOPS_HAVE_ARCH_FIND_FIRST_SET_BIT +L4_INLINE int +l4util_find_first_set_bit(const void * dest, l4_size_t size) +{ + l4_mword_t dummy0, dummy1, res; + + __asm__ __volatile__ + ( + "xor %%rax,%%rax \n\t" + "repe; scasl \n\t" + "jz 1f \n\t" + "lea -4(%%rdi),%%rdi \n\t" + "bsfq (%%rdi),%%rax \n" + "1: \n\t" + "sub %%rbx,%%rdi \n\t" + "shl $3,%%rdi \n\t" + "add %%rdi,%%rax \n\t" + : + "=a" (res), "=&c" (dummy0), "=&D" (dummy1) + : + "1" ((size + 31) >> 5), "2" (dest), "b" (dest) + : + "cc", "memory"); + + return res; +} + +#define __L4UTIL_BITOPS_HAVE_ARCH_FIND_FIRST_ZERO_BIT +L4_INLINE int +l4util_find_first_zero_bit(const void * dest, l4_size_t size) +{ + l4_mword_t dummy0, dummy1, dummy2, res; + + if (!size) + return 0; + + __asm__ __volatile__ + ( + "mov $-1,%%rax \n\t" + "xor %%rdx,%%rdx \n\t" + "repe; scasl \n\t" + "je 1f \n\t" + "xor -4(%%rdi),%%rax \n\t" + "sub $4,%%rdi \n\t" + "bsf %%rax,%%rdx \n" + "1: \n\t" + "sub %[dest],%%rdi \n\t" + "shl $3,%%rdi \n\t" + "add %%rdi,%%rdx \n\t" + : + "=d" (res), "=&c" (dummy0), "=&D" (dummy1), "=&a" (dummy2) + : + "1" ((size + 31) >> 5), "2" (dest), [dest] "S" (dest) + : + "cc", "memory"); + + return res; +} + +EXTERN_C_END + +#endif /* ! __L4UTIL__INCLUDE__ARCH_AMD64__BITOPS_ARCH_H__ */ diff --git a/l4/pkg/l4util/include/ARCH-amd64/cpu.h b/l4/pkg/l4util/include/ARCH-amd64/cpu.h new file mode 100644 index 00000000..1aa4e52d --- /dev/null +++ b/l4/pkg/l4util/include/ARCH-amd64/cpu.h @@ -0,0 +1,125 @@ +/** + * \file + * \brief CPU related functions + * + * \author Frank Mehnert */ + +/* + * (c) 2004-2009 Author(s) + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ + +#ifndef __L4_UTIL_CPU_H +#define __L4_UTIL_CPU_H + +#include + +EXTERN_C_BEGIN + +/** + * \defgroup l4util_cpu CPU related functions + * \ingroup l4util_api + */ +/*@{*/ + +/** + * Check whether the CPU supports the "cpuid" instruction. + * + * \return 1 if it has, 0 if it has not + */ +L4_INLINE int l4util_cpu_has_cpuid(void); + +/** + * Returns the CPU capabilities if the "cpuid" instruction is available. + * + * \return CPU capabilities if the "cpuid" instruction is available, + * 0 if the "cpuid" instruction is not supported. + */ +L4_INLINE unsigned int l4util_cpu_capabilities(void); + +/** + * Returns the CPU capabilities. + * + * \return CPU capabilities. + */ +L4_INLINE unsigned int l4util_cpu_capabilities_nocheck(void); + +/** + * Generic CPUID access function. + */ +L4_INLINE void +l4util_cpu_cpuid(unsigned long mode, + unsigned long *eax, unsigned long *ebx, + unsigned long *ecx, unsigned long *edx); +/*@}*/ + +static inline void +l4util_cpu_pause(void) +{ + __asm__ __volatile__ ("rep; nop"); +} + +L4_INLINE int +l4util_cpu_has_cpuid(void) +{ + unsigned long eax; + + asm volatile("pushf \t\n" + "pop %%rax \t\n" /* get eflags */ + "mov %%rax, %%rbx \t\n" /* save it */ + "xorq $0x200000, %%rax \t\n" /* toggle ID bit */ + "push %%rax \t\n" + "popf \t\n" /* set again */ + "pushf \t\n" + "pop %%rax \t\n" /* get it again */ + "xor %%rax, %%rbx \t\n" + "push %%rbx \t\n" + "popf \t\n" /* restore saved flags */ + : "=a" (eax) + : /* no input */ + : "rbx"); + + return eax & 0x200000; +} + +L4_INLINE void +l4util_cpu_cpuid(unsigned long mode, + unsigned long *eax, unsigned long *ebx, + unsigned long *ecx, unsigned long *edx) +{ + asm volatile("cpuid" + : "=a" (*eax), + "=b" (*ebx), + "=c" (*ecx), + "=d" (*edx) + : "a" (mode) + : "cc"); +} + +L4_INLINE unsigned int +l4util_cpu_capabilities_nocheck(void) +{ + unsigned long dummy, capability; + + /* get CPU capabilities */ + l4util_cpu_cpuid(1, &dummy, &dummy, &dummy, &capability); + + return capability; +} + +L4_INLINE unsigned int +l4util_cpu_capabilities(void) +{ + if (!l4util_cpu_has_cpuid()) + return 0; /* CPU has not cpuid instruction */ + + return l4util_cpu_capabilities_nocheck(); +} + +EXTERN_C_END + +#endif + diff --git a/l4/pkg/l4util/include/ARCH-amd64/idt.h b/l4/pkg/l4util/include/ARCH-amd64/idt.h new file mode 100644 index 00000000..26f7ccb1 --- /dev/null +++ b/l4/pkg/l4util/include/ARCH-amd64/idt.h @@ -0,0 +1,86 @@ +/** + * \file + * \brief IDT related functions + * \ingroup irq + * + * \date 2003 + * \author Frank Mehnert */ + +/* + * (c) 2003-2009 Author(s) + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ + +#ifndef __L4UTIL_IDT_H +#define __L4UTIL_IDT_H + +#include +#include + +EXTERN_C_BEGIN + +/** + * \defgroup l4util_idt Functions to manipulate the local IDT + * \ingroup l4util_api + */ +/*@{*/ + +/** IDT entry. + */ +typedef struct +{ + l4_uint64_t a, b; /**< see Intel doc */ +} __attribute__ ((packed)) l4util_idt_desc_t; + +/** Header of an IDT table. + */ +typedef struct +{ + l4_uint16_t limit; /**< limit field (see Intel doc) */ + void *base; /**< idt base (see Intel doc) */ + l4util_idt_desc_t desc[0]; +} __attribute__ ((packed)) l4util_idt_header_t; + +/** Create an IDT entry. + * \param idt pointer to idt table header + * \param nr # of exception vector + * \param handler exception handler + */ +static inline void +l4util_idt_entry(l4util_idt_header_t *idt, int nr, void(*handler)(void)) +{ + idt->desc[nr].a = (l4_uint64_t)handler & 0x0000ffff; + idt->desc[nr].b = 0x0000ef00 | ((l4_uint64_t)handler & 0xffff0000); +} + +/** Initializes an IDT. + * \param idt pointer to idt table header + * \param entries # of of exception entries to hold by the idt table + */ +static inline void +l4util_idt_init(l4util_idt_header_t *idt, int entries) +{ + int i; + idt->limit = entries*8 - 1; + idt->base = &idt->desc; + + for (i=0; i + * Frank Mehnert */ + +/* + * (c) 2003-2009 Author(s) + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ + +#ifndef __L4_IRQ_H__ +#define __L4_IRQ_H__ + +#include +#include + +EXTERN_C_BEGIN + +/** Acknowledge IRQ at PIC in fully special nested mode. + * \param irq number of interrupt to acknowledge + */ +L4_INLINE void +l4util_irq_acknowledge(unsigned int irq); + +/** Disable all interrupts + */ +static inline void +l4util_cli (void) +{ + __asm__ __volatile__ ("cli" : : : "memory"); +} + +/** Enable all interrupts + */ +static inline void +l4util_sti (void) +{ + __asm__ __volatile__ ("sti" : : : "memory"); +} + +/** Save the processor flags. Can be used to save and later restore the + * interrupt flag + */ +static inline void +l4util_flags_save (l4_umword_t *flags) +{ + __asm__ __volatile__ ("pushf ; popq %0 " :"=g" (*flags) : :"memory"); +} + +/** Restore processor flags. Can be used to restore the interrupt flag + */ +static inline void +l4util_flags_restore (l4_umword_t *flags) +{ + __asm__ __volatile__ ("pushq %0 ; popf" : :"g" (*flags) : "memory"); +} + +L4_INLINE void +l4util_irq_acknowledge(unsigned int irq) +{ + if (irq > 7) + { + l4util_out8(0x60+(irq & 7), 0xA0); + l4util_out8(0x0B,0xA0); + if (l4util_in8(0xA0) == 0) + l4util_out8(0x60 + 2, 0x20); + } + else + l4util_out8(0x60+irq, 0x20); /* acknowledge the irq */ +}; + +EXTERN_C_END + +#endif diff --git a/l4/pkg/l4util/include/ARCH-amd64/l4_macros.h b/l4/pkg/l4util/include/ARCH-amd64/l4_macros.h new file mode 100644 index 00000000..9c23ee45 --- /dev/null +++ b/l4/pkg/l4util/include/ARCH-amd64/l4_macros.h @@ -0,0 +1,23 @@ +/** + * \file + * \brief Main function + * + * \date 08/29/2000 + * \author Frank Mehnert */ + +/* + * (c) 2006-2009 Author(s) + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ + +#ifndef _L4UTIL__ARCH_AMD64__L4_MACROS_H +#define _L4UTIL__ARCH_AMD64__L4_MACROS_H + +#ifndef l4_addr_fmt +# define l4_addr_fmt "%016lx" +#endif + +#endif /* !_L4UTIL__ARCH_AMD64__L4_MACROS_H */ diff --git a/l4/pkg/l4util/include/ARCH-amd64/mbi_argv.h b/l4/pkg/l4util/include/ARCH-amd64/mbi_argv.h new file mode 100644 index 00000000..2c3eeeda --- /dev/null +++ b/l4/pkg/l4util/include/ARCH-amd64/mbi_argv.h @@ -0,0 +1,33 @@ +/** + * \file + * \brief command line handling + * + * \date 2003 + * \author Frank Mehnert */ + +/* + * (c) 2003-2009 Author(s) + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ + +#ifndef L4UTIL_MBI_ARGV +#define L4UTIL_MBI_ARGV + +#include +#include +#include + +EXTERN_C_BEGIN + +L4_CV void l4util_mbi_to_argv(l4_mword_t flag, l4util_mb_info_t *mbi); + +extern int l4util_argc; +extern char *l4util_argv[]; + +EXTERN_C_END + +#endif + diff --git a/l4/pkg/l4util/include/ARCH-amd64/perform.h b/l4/pkg/l4util/include/ARCH-amd64/perform.h new file mode 100644 index 00000000..4ec7595c --- /dev/null +++ b/l4/pkg/l4util/include/ARCH-amd64/perform.h @@ -0,0 +1,450 @@ +/** + * \file + * \brief Perfomance Monitoring using P5/P6 Measurement Counters. + * + * Define either CPU_PENTIUM or CPU_P6 + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Torsten Frenzel + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ +#ifndef __L4UTIL_PERFORM_H +#define __L4UTIL_PERFORM_H + +#include +#include + +EXTERN_C_BEGIN + +extern const char*strp6pmc_event(l4_uint32_t event); + +#ifndef CONFIG_PERFORM_ONLY_PROTOTYPES + +#if ! (defined CPU_PENTIUM ^ defined CPU_P6 ^ defined CPU_K7) + +#error You must define your target architecture. +#error Define EITHER CPU_PENTIUM for Intel Pentium or CPU_P6 for Intel PPro/PII/PIII. + +#else + +/* P5/P6/K7 section */ + +/* Makros for access to model specific registers (MSR) */ + +/* Write the 64-Bit Model Specific Register. First argument is the register, + second the 64-Bit value. This can only be called at priviledge level 0. + With L4, the kernel emulates the WRMSR when calling in PL 3. + */ +static inline void l4_i586_wrmsr(unsigned reg,unsigned long long*val){ + unsigned long dummyeax, dummyecx, dummyedx; + + asm volatile( + ".byte 0xf; .byte 0x30\n" /* wrmsr */ + : "=a" (dummyeax), "=d" (dummyedx), "=c" (dummyecx) + : "2" (reg), "0" (*(unsigned *)val), "1" (*((unsigned *)val+1)) + ); +} + +/* Read the 64-Bit Model Specific Register. First argument is the register, + second the address to a 64-Bit value. This can only be called at + priviledge level 0. With L4, the kernel emulates the RDMSR when calling + in PL 3. + */ +static inline void l4_i586_rdmsr(unsigned reg,unsigned long long*val){ + unsigned dummy; + + asm volatile( + ".byte 0xf; .byte 0x32\n" /* rdmsr */ + : "=a" (*(unsigned *)val), "=d" (*((unsigned *)val+1)), "=c" (dummy) + : "2" (reg) + ); +} + + +#ifdef CPU_PENTIUM +/* Pentium section */ + +/* functions and events defined here are only usable at Pentium + Processors. P6 architecture does NOT support this kind of measuring and + these events. P6 architecture has its own counters and its own events. + See P6-section for details. */ + +/* from l4linux/arch/l4-i386/include/perform.h */ + +static inline void +l4_i586_reset_event_counter(void){ + asm volatile("xor %%rax, %%rax\n" + "xor %%rdx, %%rdx\n" + "mov $0x12, %%rcx\n" + ".byte 0x0f, 0x30\n" + "movl $0x13, %%rcx\n" + ".byte 0x0f, 0x30\n" + : : : "cx", "ax", "dx" + ); +}; + +static inline void +l4_i586_read_event_counter_long(long long *counter0, long long *counter1) +{ + asm volatile( + /* "movl $0, %%eax\n" + "movl $0x11, %%ecx\n" + ".byte 0x0f, 0x30\n" *//* stop event counting */ + "mov $0x12, %%rcx\n" + ".byte 0x0f, 0x32\n" + "mov %%rax, (%%rbx)\n" + "mov %%rdx, 4(%%rbx)\n" + "mov $0x13, %%ecx\n" + ".byte 0x0f, 0x32\n" + "mov %%rax, (%%rsi)\n" + "mov %%rdx, 4(%%rsi)\n" + : /* no output */ + : "b" (counter0), "S" (counter1) + : "ax", "cx", "dx" + ); +} + +static inline void +l4_i586_read_event_counter(int *counter0, int *counter1) +{ + asm volatile("push %%rdx \n" + ".byte 0x0f, 0x30 \n" + "mov $0x12, %%rcx \n" + ".byte 0x0f, 0x32 \n" + "mov %%rax, %%rbx \n" + "movl $0x13, %%rcx \n" + ".byte 0x0f, 0x32\n" + "popl %%edx\n" + : "=b" (*counter0), "=a" (*counter1) + : "1" (0), "c" (0x11) + ); +} + +static inline void +l4_i586_select_event(int event0, int event1) +{ + asm volatile(".byte 0x0f, 0x30\n" + : + : + "a" (event0 + (event1 << 16)), + "d" (0), + "c" (0x11) + ); +}; + +#define P5_RD_MISS 0x003 /* 000011B */ +#define P5_WR_MISS 0x008 /* 000100B */ +#define P5_RW_MISS 0x029 /* 101001B */ +#define P5_EX_MISS 0x00e /* 001110B */ + +#define P5_D_WBACK 0x006 /* 000110B */ + +#define P5_RW_TLB 0x002 /* 00010B */ +#define P5_EX_TLB 0x00d /* 01101B */ + +#define P5_A_STALL 0x01f /* 11111B */ +#define P5_W_STALL 0x019 /* 11001B */ +#define P5_R_STALL 0x01a /* 11010B */ +#define P5_X_STALL 0x01b /* 11011B */ + +#define P5_AGI_STALL 0x01f /* 11111B */ + +#define P5_PIPLINE_FLUSH 0x015 /* 10101B */ + +#define P5_NON_CACHE_RD 0x01e /* 11110B */ +#define P5_NCACHE_REFS 0x01e /* 11110B */ +#define P5_LOCKED_BUS 0x01c /* 11100B */ + +#define P5_MEM2PIPE 0x009 /* 01001B */ +#define P5_BANK_CONF 0x00a /* 01010B */ + + +#define P5_INSTRS_EX 0x016 /* 10110B */ +#define P5_INSTRS_EX_V 0x017 /* 10111B */ + + +#define P5_CNT_NOTHING (0x00 << 6) /* 00B << 6 */ +#define P5_CNT_EVENT_PL0 (0x01 << 6) /* 01B << 6 */ +#define P5_CNT_EVENT_PL3 (0x02 << 6) /* 10B << 6 */ +#define P5_CNT_EVENT (0x03 << 6) /* 11B << 6 */ +#define P5_CNT_CLOCKS_PL0 (0x05 << 6) /* 101B << 6 */ +#define P5_CNT_CLOCKS_PL3 (0x06 << 6) /* 110B << 6 */ +#define P5_CNT_CLOCKS (0x07 << 6) /* 111B << 6 */ + + +#else +#if defined CPU_P6 +/* PPro/PII/PIII section */ + +/*- + * Copyright (c) 1997 The President and Fellows of Harvard College. + * All rights reserved. + * Copyright (c) 1997 Aaron B. Brown. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Harvard University + * and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY HARVARD AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL HARVARD UNIVERSITY OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/********************************************************************* + ** Symbolic names for counter numbers (used in select_p6counter()) ** + ********************************************************************* + * + * These correspond in order to the Pentium Pro counters. Add new counters at + * the end. These agree with the mneumonics in the Pentium Pro Family + * Developer's Manual, vol 3. + * + * Those events marked with a $ require a MESI unit field; those marked with + * a @ require a self/any unit field. Those marked with a 0 are only supported + * in counter 0; those marked with 1 are only supported in counter 1. + */ + +/* Data cache unit */ +#define P6_DATA_MEM_REFS 0x43 /* total memory refs */ +#define P6_DCU_LINES_IN 0x45 /* all lines allocated in cache unit */ +#define P6_DCU_M_LINES_IN 0x46 /* M lines allocated in cache unit */ +#define P6_DCU_M_LINES_OUT 0x47 /* M lines evicted from cache */ +#define P6_DCU_MISS_OUTSTANDING 0x48 /* #cycles a miss is outstanding */ + +/* Instruction fetch unit */ +#define P6_IFU_IFETCH 0x80 /* instruction fetches */ +#define P6_IFU_IFETCH_MISS 0x81 /* instruction fetch misses */ +#define P6_ITLB_MISS 0x85 /* ITLB misses */ +#define P6_IFU_MEM_STALL 0x86 /* number of cycles IFU is stalled */ +#define P6_ILD_STALL 0x87 /* #stalls in instr length decode */ + +/* L2 Cache */ +#define P6_L2_IFETCH 0x28 /* ($) l2 ifetches */ +#define P6_L2_LD 0x29 /* ($) l2 data loads */ +#define P6_L2_ST 0x2a /* ($) l2 data stores */ +#define P6_L2_LINES_IN 0x24 /* lines allocated in l2 */ +#define P6_L2_LINES_OUT 0x26 /* lines removed from l2 */ +#define P6_L2_M_LINES_INM 0x25 /* modified lines allocated in L2 */ +#define P6_L2_M_LINES_OUTM 0x27 /* modified lines removed from L2 */ +#define P6_L2_RQSTS 0x2e /* ($) number of l2 requests */ +#define P6_L2_ADS 0x21 /* number of l2 addr strobes */ +#define P6_L2_DBUS_BUSY 0x22 /* number of data bus busy cycles */ +#define P6_L2_DBUS_BUSY_RD 0x23 /* #bus cycles xferring l2->cpu */ + +/* External bus logic */ +#define P6_BUS_DRDY_CLOCKS 0x62 /* (@) #clocks DRDY is asserted */ +#define P6_BUS_LOCK_CLOCKS 0x63 /* (@) #clocks LOCK is asserted */ +#define P6_BUS_REQ_OUTSTANDING 0x60 /* #bus requests outstanding */ +#define P6_BUS_TRAN_BRD 0x65 /* (@) bus burst read txns */ +#define P6_BUS_TRAN_RFO 0x66 /* (@) bus read for ownership txns */ +#define P6_BUS_TRAN_WB 0x67 /* (@) bus writeback txns */ +#define P6_BUS_TRAN_IFETCH 0x68 /* (@) bus instr fetch txns */ +#define P6_BUS_TRAN_INVAL 0x69 /* (@) bus invalidate txns */ +#define P6_BUS_TRAN_PWR 0x6a /* (@) bus partial write txns */ +#define P6_BUS_TRANS_P 0x6b /* (@) bus partial txns */ +#define P6_BUS_TRANS_IO 0x6c /* (@) bus I/O txns */ +#define P6_BUS_TRAN_DEF 0x6d /* (@) bus deferred txns */ +#define P6_BUS_TRAN_BURST 0x6e /* (@) bus burst txns */ +#define P6_BUS_TRAN_ANY 0x70 /* (@) total bus txns */ +#define P6_BUS_TRAN_MEM 0x6f /* (@) total memory txns */ +#define P6_BUS_DATA_RCV 0x64 /* #busclocks CPU is receiving data */ +#define P6_BUS_BNR_DRV 0x61 /* #busclocks CPU is driving BNR pin */ +#define P6_BUS_HIT_DRV 0x7a /* #busclocks CPU is driving HIT pin */ +#define P6_BUS_HITM_DRV 0x7b /* #busclocks CPU is driving HITM pin*/ +#define P6_BUS_SNOOP_STALL 0x7e /* #clkcycles bus is snoop-stalled */ + +/* FPU */ +#define P6_FLOPS 0xc1 /* (0) number of FP ops retired */ +#define P6_FP_COMP_OPS 0x10 /* (0) computational FPOPS exec'd */ +#define P6_FP_ASSIST 0x11 /* (1) FP excep's handled in ucode */ +#define P6_MUL 0x12 /* (1) number of FP multiplies */ +#define P6_DIV 0x13 /* (1) number of FP divides */ +#define P6_CYCLES_DIV_BUSY 0x14 /* (0) number of cycles divider busy */ + +/* Memory ordering */ +#define P6_LD_BLOCKS 0x03 /* number of store buffer blocks */ +#define P6_SB_DRAINS 0x04 /* # of store buffer drain cycles */ +#define P6_MISALING_MEM_REF 0x05 /* # misaligned data memory refs */ + +/* Instruction decoding and retirement */ +#define P6_INST_RETIRED 0xc0 /* number of instrs retired */ +#define P6_UOPS_RETIRED 0xc2 /* number of micro-ops retired */ +#define P6_INST_DECODER 0xd0 /* number of instructions decoded */ + +/* Interrupts */ +#define P6_HW_INT_RX 0xc8 /* number of hardware interrupts */ +#define P6_CYCLES_INT_MASKED 0xc6 /* number of cycles hardints masked */ +#define P6_CYCLES_INT_PENDING_AND_MASKED 0xc7 /* #cycles masked but pending */ + +/* Branches */ +#define P6_BR_INST_RETIRED 0xc4 /* number of branch instrs retired */ +#define P6_BR_MISS_PRED_RETIRED 0xc5 /* number of mispred'd brs retired */ +#define P6_BR_TAKEN_RETIRED 0xc9 /* number of taken branches retired */ +#define P6_BR_MISS_PRED_TAKEN_RET 0xca /* #taken mispredictions br's retired*/ +#define P6_BR_INST_DECODED 0xe0 /* number of branch instrs decoded */ +#define P6_BTB_MISSES 0xe2 /* # of branches that missed in BTB */ +#define P6_BR_BOGUS 0xe4 /* number of bogus branches */ +#define P6_BACLEARS 0xe6 /* # times BACLEAR is asserted */ + +/* Stalls */ +#define P6_RESOURCE_STALLS 0xa2 /* # resource-related stall cycles */ +#define P6_PARTIAL_RAT_STALLS 0xd2 /* # cycles/events for partial stalls*/ + +/* Segment register loads */ +#define P6_SEGMENT_REG_LOADS 0x06 /* number of segment register loads */ + +/* Clocks */ +#define P6_CPU_CLK_UNHALTED 0x79 /* #clocks CPU is not halted */ + +/* Unit field tags */ +#define P6_UNIT_M 0x0800 +#define P6_UNIT_E 0x0400 +#define P6_UNIT_S 0x0200 +#define P6_UNIT_I 0x0100 +#define P6_UNIT_MESI 0x0f00 + +#define P6_UNIT_SELF 0x0000 +#define P6_UNIT_ANY 0x2000 + +/**************************************************************************** + ** Flag bit definitions (used for the 'flag' field in select_p6counter()) ** + **************************************************************************** + * + * The driver accepts fully-formed counter specifications from user-level. + * The following flags are mneumonics for the bits that get set in the + * PerfEvtSel0 and PerfEvtSel1 MSR's + * + */ +#define P6CNT_U 0x010000 /* Monitor user-level events */ +#define P6CNT_K 0x020000 /* Monitor kernel-level events */ +#define P6CNT_E 0x040000 /* Edge detect: count state transitions */ +#define P6CNT_PC 0x080000 /* Pin control: ?? */ +#define P6CNT_IE 0x100000 /* Int enable: enable interrupt on overflow */ +#define P6CNT_F 0x200000 /* Freeze counter (handled in software) */ +#define P6CNT_EN 0x400000 /* enable counters (in PerfEvtSel0) */ +#define P6CNT_IV 0x800000 /* Invert counter mask comparison result */ + +/***************************** + ** Miscellaneous constants ** + ***************************** + * + * Number of Pentium Pro programable hardware counters. + */ +#define NUM_P6HWC 2 + +/***************************************************************************** +* +* End of Copyright by Harvard College +* +*****************************************************************************/ + + +#define MSR_P6_EVNTSEL0 0x186 +#define MSR_P6_EVNTSEL1 0x187 +#define MSR_P6_PERFCTR0 0xc1 +#define MSR_P6_PERFCTR1 0xc2 + +/* P6-specific Makros to manipulate and read counters */ + +/* Read the 40 bit performance monitoring counter. This requires + the PCE-flag in CR4 to be set. Otherwise GP0 is raised. Works only + at P6. + */ +#define l4_i686_rdpmc(cntr, res_p) \ + __asm __volatile( \ + "mov %2, %%rcx # put counter number in \n\ + .byte 0xf; .byte 0x33 # RDPMC instruction \n\ + mov %%rdx, %1 # High order 32 bits \n\ + mov %%rax, %0 # Low order 32 bits" \ + : "=g" (*(int *)(res_p)), "=g" (*(((int *)res_p)+1)) \ + : "g" (cntr) \ + : "ecx", "eax", "edx") + +static inline l4_uint32_t l4_i686_rdpmc_32(int cntr){ + l4_uint32_t x; + + __asm__ __volatile__( + ".byte 0xf; .byte 0x33 # RDPMC instruction" + : "=a" (x) + : "c" (cntr) + : "rcx", "rax", "rdx"); + return x; +} + +static inline void l4_i686_select_perfctr_event(int counter, + unsigned long long val){ + l4_i586_wrmsr(MSR_P6_EVNTSEL0+counter, &val); +} + +static inline void l4_i686_select_perfctr0_event(long long *val){ + asm volatile( + "mov $MSR_P6_EVNTSEL0, %%rcx\n" + "mov (%%rbx), %%rax\n" + "mov 4(%%rbx), %%rdx\n" + //".byte 0xcc, 0xeb, 0x01, 0x21\n" + ".byte 0x0f, 0x30\n" // wrmsr + //".byte 0xcc, 0xeb, 0x01, 0x21\n" + : /* no output */ + : "b" (val) + : "ax", "cx", "dx", "bx" + ); + +} + +/* end of P6 section */ +#else + +#define K7CNT_U 0x010000 /* Monitor user-level events */ +#define K7CNT_K 0x020000 /* Monitor kernel-level events */ +#define K7CNT_E 0x040000 /* Edge detect: count state transitions */ +#define K7CNT_PC 0x080000 /* Pin control: ?? */ +#define K7CNT_IE 0x100000 /* Int enable: enable interrupt on overflow */ +#define K7CNT_F 0x200000 /* Freeze counter (handled in software) */ +#define K7CNT_EN 0x400000 /* enable counters (in PerfEvtSel0) */ +#define K7CNT_IV 0x800000 /* Invert counter mask comparison result */ + +#define MSR_K7_EVNTSEL0 0xC0010000 +#define MSR_K7_EVNTSEL1 0xC0010001 +#define MSR_K7_EVNTSEL2 0xC0010002 +#define MSR_K7_EVNTSEL3 0xC0010003 +#define MSR_K7_PERFCTR0 0xC0010004 +#define MSR_K7_PERFCTR1 0xC0010005 +#define MSR_K7_PERFCTR2 0xC0010006 +#define MSR_K7_PERFCTR3 0xC0010007 + +#endif + +#endif + +/* end of P5/P6/K7 section*/ +#endif + +/* end of not only lib-prototypes section */ +#endif + +EXTERN_C_END + +#endif diff --git a/l4/pkg/l4util/include/ARCH-amd64/port_io.h b/l4/pkg/l4util/include/ARCH-amd64/port_io.h new file mode 100644 index 00000000..32d46e47 --- /dev/null +++ b/l4/pkg/l4util/include/ARCH-amd64/port_io.h @@ -0,0 +1,12 @@ +/** + * \file + * \brief Port I/O functions. + */ +/* + * (c) 2008-2009 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ +#include diff --git a/l4/pkg/l4util/include/ARCH-amd64/rdtsc.h b/l4/pkg/l4util/include/ARCH-amd64/rdtsc.h new file mode 100644 index 00000000..f3b67b7f --- /dev/null +++ b/l4/pkg/l4util/include/ARCH-amd64/rdtsc.h @@ -0,0 +1,339 @@ +/** + * \file + * \brief time stamp counter related functions + * + * \date Frank Mehnert + * \ingroup l4util_tsc + */ + +/* + * (c) 2003-2009 Adam Lackorzynski , + * Alexander Warg , + * Torsten Frenzel + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ + +#ifndef __l4_rdtsc_h +#define __l4_rdtsc_h + +/** + * \defgroup l4util_tsc Timestamp Counter + * \ingroup l4util_api + */ + +#include +#include +#include + +EXTERN_C_BEGIN + +/* interface */ +/** + * \addtogroup l4util_tsc + */ +/*@{*/ + +#define L4_TSC_INIT_AUTO 0 ///< Automatic init +#define L4_TSC_INIT_KERNEL 1 ///< Initialized by kernel +#define L4_TSC_INIT_CALIBRATE 2 ///< Initialized by user-level + +extern l4_uint32_t l4_scaler_tsc_to_ns; +extern l4_uint32_t l4_scaler_tsc_to_us; +extern l4_uint32_t l4_scaler_ns_to_tsc; +extern l4_uint32_t l4_scaler_tsc_linux; + +/** + * \brief Read current value of CPU-internal time stamp counter. + * \return 64-bit time stamp + */ +L4_INLINE l4_cpu_time_t +l4_rdtsc (void); + +/** + * \brief Read the lest significant 32 bit of the TSC. + * + * Useful for smaller differences, needs less cycles. + */ +L4_INLINE +l4_uint32_t l4_rdtsc_32(void); + +/** + * \brief Return current value of CPU-internal performance measurement counter. + * \param nr Number of counter (0 or 1) + * \return 64-bit PMC */ +L4_INLINE l4_cpu_time_t +l4_rdpmc (int nr); + +/** + * \brief Return the least significant 32 bit of a performance counter. + * + * Useful for smaller differences, needs less cycles. + */ +L4_INLINE +l4_uint32_t l4_rdpmc_32(int nr); + +/** Convert time stamp to ns value. + * \param tsc time value in CPU ticks + * \return time value in ns + */ +L4_INLINE l4_uint64_t +l4_tsc_to_ns (l4_cpu_time_t tsc); + +/** Convert time stamp into micro seconds value. + * \param tsc time value in CPU ticks + * \return time value in micro seconds + */ +L4_INLINE l4_uint64_t +l4_tsc_to_us (l4_cpu_time_t tsc); + +/** Convert time stamp to s.ns value. + * \param tsc time value in CPU ticks + * \retval s seconds + * \retval ns nano seconds + */ +L4_INLINE void +l4_tsc_to_s_and_ns (l4_cpu_time_t tsc, l4_uint32_t *s, l4_uint32_t *ns); + +/** + * \brief Convert nano seconds into CPU ticks. + * \param ns nano seconds + * \return CPU ticks + */ +L4_INLINE l4_cpu_time_t +l4_ns_to_tsc (l4_uint64_t ns); + +/** + * \brief Wait busy for a small amount of time. + * \param ns nano seconds to wait + * \attention Not intendet for any use! + */ +L4_INLINE void +l4_busy_wait_ns (l4_uint64_t ns); + +/** + * \brief Wait busy for a small amount of time. + * \param us micro seconds to wait + * \attention Not intendet for any use! + */ +L4_INLINE void +l4_busy_wait_us (l4_uint64_t us); + +EXTERN_C_BEGIN + +/** + * \brief Calibrate scalers for time stamp calculations. + * + * Determine some scalers to be able to convert between real time and CPU + * ticks. This test uses channel 0 of the PIT (i8254) or the kernel KIP, + * depending on availability. + * Just calls l4_tsc_init(L4_TSC_INIT_AUTO). + */ +L4_INLINE l4_uint32_t +l4_calibrate_tsc (l4_kernel_info_t *kip); + +/** + * \brief Initialitze scaler for TSC calicaltions. + * + * Initialize the scalers needed by l4_tsc_to_ns()/l4_ns_to_tsc() and so on. + * Current versions of Fiasco export these scalers from kernel into userland. + * The programmer may decide whether he allows to use these scalers or if an + * calibration should be performed. + * \param constraint programmers constraint: + * - #L4_TSC_INIT_AUTO if the kernel exports the scalers + * then use them. If not, perform calibration using + * channel 0 of the PIT (i8254). The latter case may + * lead into short (unpredictable) periods where + * interrupts are disabled. + * - #L4_TSC_INIT_KERNEL depend on retrieving the scalers + * from kernel. If the scalers are not available, + * return 0. + * - #L4_TSC_INIT_CALIBRATE Ignore possible scalers + * exported by the scaler, instead insist on + * calibration using the PIT. + * \param kip KIP pointer + * \return 0 on error (no scalers exported by kernel, calibrating failed ...) + * otherwise returns (2^32 / (tsc per µsec)). This value has the + * same semantics as the value returned by the calibrate_delay_loop() + * function of the Linux kernel. + */ +L4_CV l4_uint32_t +l4_tsc_init (int constraint, l4_kernel_info_t *kip); + +/** + * \brief Get CPU frequency in Hz + * \return frequency in Hz + */ +L4_CV l4_uint32_t +l4_get_hz (void); + +/*@}*/ + +EXTERN_C_END + +/* implementaion */ + +L4_INLINE l4_uint32_t +l4_calibrate_tsc (l4_kernel_info_t *kip) +{ + return l4_tsc_init(L4_TSC_INIT_AUTO, kip); +} + +L4_INLINE l4_cpu_time_t +l4_rdtsc (void) +{ + l4_cpu_time_t v; + + __asm__ __volatile__ + (".byte 0x0f, 0x31 \n\t" + "mov $0xffffffff, %%rcx \n\t" /* clears the upper 32 bits! */ + "and %%rcx,%%rax \n\t" + "shlq $32,%%rdx \n\t" + "orq %%rdx,%%rax \n\t" + : + "=a" (v) + : /* no inputs */ + :"rdx", "rcx" + ); + + return v; +} + +L4_INLINE l4_cpu_time_t +l4_rdpmc (int nr) +{ + l4_cpu_time_t v; + l4_uint64_t dummy; + + __asm__ __volatile__ ( + "rdpmc \n\t" + "mov $0xffffffff, %%rcx \n\t" /* clears the upper 32 bits! */ + "and %%rcx,%%rax \n\t" + "shlq $32,%%rdx \n\t" + "orq %%rdx,%%rax \n\t" + : + "=a" (v), "=c"(dummy) + : "c" (nr) + : "rdx" + ); + + return v; +} + +/* the same, but only 32 bit. Useful for smaller differences */ +L4_INLINE +l4_uint32_t l4_rdpmc_32(int nr) +{ + l4_uint32_t x; + l4_uint64_t dummy; + + __asm__ __volatile__ ( + "rdpmc \n\t" + "mov $0xffffffff, %%rcx \n\t" /* clears the upper 32 bits! */ + "and %%rcx,%%rax \n\t" + : "=a" (x), "=c"(dummy) + : "c" (nr) + : "rdx"); + + return x; +} + +/* the same, but only 32 bit. Useful for smaller differences, + needs less cycles. */ +L4_INLINE +l4_uint32_t l4_rdtsc_32(void) +{ + l4_uint32_t x; + + __asm__ __volatile__ ( + ".byte 0x0f, 0x31\n\t" // rdtsc + : "=a" (x) + : + : "rdx"); + + return x; +} + +L4_INLINE l4_uint64_t +l4_tsc_to_ns (l4_cpu_time_t tsc) +{ + l4_uint64_t ns, dummy; + __asm__ + (" \n\t" + "mulq %3 \n\t" + "shrd $27, %%rdx, %%rax \n\t" + :"=a" (ns), "=d"(dummy) + :"a" (tsc), "r" ((l4_uint64_t)l4_scaler_tsc_to_ns) + ); + return ns; +} + +L4_INLINE l4_uint64_t +l4_tsc_to_us (l4_cpu_time_t tsc) +{ + l4_uint64_t ns, dummy; + __asm__ + (" \n\t" + "mulq %3 \n\t" + "shrd $32, %%rdx, %%rax \n\t" + :"=a" (ns), "=d" (dummy) + :"a" (tsc), "r" ((l4_uint64_t)l4_scaler_tsc_to_us) + ); + return ns; +} + +L4_INLINE void +l4_tsc_to_s_and_ns (l4_cpu_time_t tsc, l4_uint32_t *s, l4_uint32_t *ns) +{ + __asm__ + (" \n\t" + "mulq %3 \n\t" + "shrd $27, %%rdx, %%rax \n\t" + "xorq %%rdx, %%rdx \n\t" + "divq %4 \n\t" + :"=a" (*s), "=&d" (*ns) + : "a" (tsc), "r" ((l4_uint64_t)l4_scaler_tsc_to_ns), + "rm"(1000000000ULL) + ); +} + +L4_INLINE l4_cpu_time_t +l4_ns_to_tsc (l4_uint64_t ns) +{ + l4_uint64_t tsc, dummy; + __asm__ + (" \n\t" + "mulq %3 \n\t" + "shrd $27, %%rdx, %%rax \n\t" + :"=a" (tsc), "=d" (dummy) + :"a" (ns), "r" ((l4_uint64_t)l4_scaler_ns_to_tsc) + ); + return tsc; +} + +L4_INLINE void +l4_busy_wait_ns (l4_uint64_t ns) +{ + l4_cpu_time_t stop = l4_rdtsc(); + stop += l4_ns_to_tsc(ns); + + while (l4_rdtsc() < stop) + ; +} + +L4_INLINE void +l4_busy_wait_us (l4_uint64_t us) +{ + l4_cpu_time_t stop = l4_rdtsc (); + stop += l4_ns_to_tsc(us*1000ULL); + + while (l4_rdtsc() < stop) + ; +} + +EXTERN_C_END + +#endif /* __l4_rdtsc_h */ + diff --git a/l4/pkg/l4util/include/ARCH-amd64/spin.h b/l4/pkg/l4util/include/ARCH-amd64/spin.h new file mode 100644 index 00000000..3f066181 --- /dev/null +++ b/l4/pkg/l4util/include/ARCH-amd64/spin.h @@ -0,0 +1,41 @@ +/** + * \file + * \brief Spinning for amd64 + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Torsten Frenzel + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ +#ifndef __l4util_spin_h +#define __l4util_spin_h + +#include + +EXTERN_C_BEGIN + +L4_CV void l4_spin(int x,int y); +L4_CV void l4_spin_vga(int x,int y); +L4_CV void l4_spin_n_text(int x, int y, int len, const char*s); +L4_CV void l4_spin_n_text_vga(int x, int y, int len, const char*s); + +/**************************************************************************** +* * +* spin_text() - spinning wheel at the hercules screen. The given text * +* must be a text constant, no variables or arrays. Its * +* size is determined with the sizeof operator, it's much * +* faster than the strlen function. * +* spin_text_vga() - same for vga. * +* * +****************************************************************************/ +#define l4_spin_text(x, y, text) \ + l4_spin_n_text((x), (y), sizeof(text)-1, "" text) +#define l4_spin_text_vga(x, y, text) \ + l4_spin_n_text_vga((x), (y), sizeof(text)-1, "" text) + +EXTERN_C_END + +#endif diff --git a/l4/pkg/l4util/include/ARCH-amd64/stack_impl.h b/l4/pkg/l4util/include/ARCH-amd64/stack_impl.h new file mode 100644 index 00000000..0b4ca849 --- /dev/null +++ b/l4/pkg/l4util/include/ARCH-amd64/stack_impl.h @@ -0,0 +1,32 @@ +/** + * \file + * \brief Stack utilities for amd64 + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Torsten Frenzel + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ +#ifndef __L4UTIL__INCLUDE__ARCH_AMD64__STACK_IMPL_H__ +#define __L4UTIL__INCLUDE__ARCH_AMD64__STACK_IMPL_H__ + +EXTERN_C_BEGIN + +#ifndef _L4UTIL_STACK_H +#error Do not include stack_impl.h directly, use stack.h instead +#endif + +L4_INLINE l4_addr_t l4util_stack_get_sp(void) +{ + l4_addr_t rsp; + + asm("movq %%rsp, %0\n\t" : "=r" (rsp) : ); + return rsp; +} + +EXTERN_C_END + +#endif /* ! __L4UTIL__INCLUDE__ARCH_AMD64__STACK_IMPL_H__ */ diff --git a/l4/pkg/l4util/include/ARCH-amd64/util.h b/l4/pkg/l4util/include/ARCH-amd64/util.h new file mode 100644 index 00000000..5f1107b2 --- /dev/null +++ b/l4/pkg/l4util/include/ARCH-amd64/util.h @@ -0,0 +1,89 @@ +/** + * \file + * \brief Utilities, amd64 version + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg , + * Torsten Frenzel + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ +#ifndef __UTIL_H +#define __UTIL_H + +#include +#include +#include + +EXTERN_C_BEGIN + +/** Calculate l4 timeouts + * \param mus time in microseconds. Special cases: + * - 0 - > timeout 0 + * - ~0U -> timeout NEVER + * \return the corresponding l4_timeout value + */ +L4_CV l4_timeout_s l4util_micros2l4to(unsigned int mus) L4_NOTHROW; + +/** Suspend thread for a period of milliseconds */ +L4_CV void l4_sleep(int ms) L4_NOTHROW; + +/* Suspend thread for a period of micro seconds. + * WARNING: This function is mostly bogus since the timer resolution of + * current L4 implementations is about 1ms! */ +L4_CV void l4_usleep(int us) L4_NOTHROW; + +/** + * \brief Go sleep and never wake up. + * \ingroup l4util_api + * + */ +L4_INLINE void l4_sleep_forever(void) L4_NOTHROW __attribute__((noreturn)); + +L4_INLINE void +l4_sleep_forever(void) L4_NOTHROW +{ + for (;;) + l4_ipc_sleep(L4_IPC_NEVER); +} + +/** Touch data areas to force mapping read-only */ +static inline void +l4_touch_ro(const void*addr, unsigned size) L4_NOTHROW +{ + const char *bptr, *eptr; + + bptr = (const char*)(((l4_addr_t)addr) & L4_PAGEMASK); + eptr = (const char*)(((l4_addr_t)addr+size-1) & L4_PAGEMASK); + for(;bptr<=eptr;bptr+=L4_PAGESIZE){ + asm volatile("or %0,%%rax \n" + : + : "m" (*(const unsigned*)bptr) + : "rax" ); + } +} + + +/** Touch data areas to force mapping read-write */ +static inline void +l4_touch_rw(const void*addr, unsigned size) L4_NOTHROW +{ + const char *bptr, *eptr; + + bptr = (const char*)(((l4_addr_t)addr) & L4_PAGEMASK); + eptr = (const char*)(((l4_addr_t)addr+size-1) & L4_PAGEMASK); + for(;bptr<=eptr;bptr+=L4_PAGESIZE){ + asm volatile("or $0,%0 \n" + : + : "m" (*(const unsigned*)bptr) + ); + } +} + +EXTERN_C_END + +#endif + diff --git a/l4/pkg/l4util/include/ARCH-arm/L4API-l4f/l4_macros.h b/l4/pkg/l4util/include/ARCH-arm/L4API-l4f/l4_macros.h new file mode 100644 index 00000000..a431c9ac --- /dev/null +++ b/l4/pkg/l4util/include/ARCH-arm/L4API-l4f/l4_macros.h @@ -0,0 +1,34 @@ +/*****************************************************************************/ +/** + * \file + * \brief Some useful generic macros, L4f version + * + * \date 11/12/2002 + * \author Lars Reuther */ +/* + * (c) 2000-2009 Author(s) + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ + +/*****************************************************************************/ + +#include_next + +#ifndef _L4UTIL__ARCH_ARM__L4F__L4_MACROS_H +#define _L4UTIL__ARCH_ARM__L4F__L4_MACROS_H + +/***************************************************************************** + *** generic macros + *****************************************************************************/ + +/* generate L4 thread id printf string */ +#ifndef l4util_idstr +# define l4util_idfmt "%lx" +# define l4util_idfmt_adjust "%04lx" +# define l4util_idstr(tid) (tid >> L4_CAP_SHIFT) +#endif + +#endif /* !_L4UTIL__ARCH_ARM__L4F__L4_MACROS_H */ diff --git a/l4/pkg/l4util/include/ARCH-arm/atomic_arch.h b/l4/pkg/l4util/include/ARCH-arm/atomic_arch.h new file mode 100644 index 00000000..9b007196 --- /dev/null +++ b/l4/pkg/l4util/include/ARCH-arm/atomic_arch.h @@ -0,0 +1,95 @@ +/** + * \file + * \brief ARM specific implementation of atomic functions + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ +#ifndef __L4UTIL__INCLUDE__ARCH_ARM__ATOMIC_ARCH_H__ +#define __L4UTIL__INCLUDE__ARCH_ARM__ATOMIC_ARCH_H__ + +#ifdef __GNUC__ + +#include + +EXTERN_C_BEGIN + +#define __L4UTIL_ATOMIC_HAVE_ARCH_CMPXCHG32 +L4_INLINE int +l4util_cmpxchg32(volatile l4_uint32_t * dest, + l4_uint32_t cmp_val, l4_uint32_t new_val) +{ + return l4_atomic_cmpxchg((volatile long int *)dest, cmp_val, new_val); +} + +#define __L4UTIL_ATOMIC_HAVE_ARCH_CMPXCHG +L4_INLINE int +l4util_cmpxchg(volatile l4_umword_t * dest, + l4_umword_t cmp_val, l4_umword_t new_val) +{ + return l4_atomic_cmpxchg((volatile long int *)dest, cmp_val, new_val); +} + +#define __L4UTIL_ATOMIC_HAVE_ARCH_XCHG32 +L4_INLINE l4_uint32_t +l4util_xchg32(volatile l4_uint32_t *dest, l4_uint32_t new_val) +{ + return l4_atomic_xchg((volatile long int *)dest, new_val); +} + +#define __L4UTIL_ATOMIC_HAVE_ARCH_XCHG +L4_INLINE l4_umword_t +l4util_xchg(volatile l4_umword_t *dest, l4_umword_t new_val) +{ + return l4_atomic_xchg((volatile long int *)dest, new_val); +} + +#define __L4UTIL_ATOMIC_HAVE_ARCH_ADD +L4_INLINE void +l4util_atomic_add(volatile long *dest, long val) +{ + l4_atomic_add(dest, val); +} + +#define __L4UTIL_ATOMIC_HAVE_ARCH_INC +L4_INLINE void +l4util_atomic_inc(volatile long *dest) +{ + l4_atomic_add(dest, 1); +} + +L4_INLINE void +l4util_inc32(volatile l4_uint32_t *dest) +{ + l4_atomic_add((volatile long int *)dest, 1); +} + +L4_INLINE void +l4util_dec32(volatile l4_uint32_t *dest) +{ + l4_atomic_add((volatile long int *)dest, -1); +} + + +L4_INLINE l4_uint32_t +l4util_inc32_res(volatile l4_uint32_t *dest) +{ + return l4_atomic_add((volatile long int *)dest, 1); +} + +L4_INLINE l4_uint32_t +l4util_dec32_res(volatile l4_uint32_t *dest) +{ + return l4_atomic_add((volatile long int *)dest, -1); +} + +EXTERN_C_END + +#endif //__GNUC__ + +#endif /* ! __L4UTIL__INCLUDE__ARCH_ARM__ATOMIC_ARCH_H__ */ diff --git a/l4/pkg/l4util/include/ARCH-arm/bitops_arch.h b/l4/pkg/l4util/include/ARCH-arm/bitops_arch.h new file mode 100644 index 00000000..71ea7591 --- /dev/null +++ b/l4/pkg/l4util/include/ARCH-arm/bitops_arch.h @@ -0,0 +1,24 @@ +/** + * \file + * \brief ARM specific implementation of bitops functions + */ +/* + * (c) 2008-2009 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ +#ifndef __L4UTIL__ARCH_ARM__BITOPS_ARCH_H__ +#define __L4UTIL__ARCH_ARM__BITOPS_ARCH_H__ + +/* No optimized variants available. */ + +L4_INLINE void +l4util_set_bit32(int b, volatile l4_uint32_t * dest) +{ + // for ARM sizeof(l4_umword_t) == sizeof(l4_uint32_t) + l4util_set_bit(b, (volatile l4_umword_t *)dest); +} + +#endif /* ! __L4UTIL__ARCH_ARM__BITOPS_ARCH_H__ */ diff --git a/l4/pkg/l4util/include/ARCH-arm/cpu.h b/l4/pkg/l4util/include/ARCH-arm/cpu.h new file mode 100644 index 00000000..c1f8d50c --- /dev/null +++ b/l4/pkg/l4util/include/ARCH-arm/cpu.h @@ -0,0 +1,21 @@ +/** + * \file + * \brief CPU related functions + * + * \author Adam Lackorzynski + */ + +/* + * (c) 2004-2009 Author(s) + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ + +#ifndef __L4_UTIL__ARCH_ARM__CPU_H__ +#define __L4_UTIL__ARCH_ARM__CPU_H__ + +/* Nothing yet */ + +#endif /* __L4_UTIL__ARCH_ARM__CPU_H__ */ diff --git a/l4/pkg/l4util/include/ARCH-arm/irq.h b/l4/pkg/l4util/include/ARCH-arm/irq.h new file mode 100644 index 00000000..2fe6f5c2 --- /dev/null +++ b/l4/pkg/l4util/include/ARCH-arm/irq.h @@ -0,0 +1,84 @@ +/** + * \file + * \brief ARM specific implementation of irq functions + * + * Do not use. + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg , + * Frank Mehnert + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ +#ifndef __L4UTIL__ARCH_ARCH__IRQ_H__ +#define __L4UTIL__ARCH_ARCH__IRQ_H__ + +#ifdef __GNUC__ + +#include +#include + +EXTERN_C_BEGIN + +L4_INLINE void l4util_cli (void); +L4_INLINE void l4util_sti (void); +L4_INLINE void l4util_flags_save(l4_umword_t *flags); +L4_INLINE void l4util_flags_restore(l4_umword_t *flags); + +/** \brief Disable all interrupts + * \internal + */ +L4_INLINE +void +l4util_cli (void) +{ + l4_sys_cli(); +} + +/** \brief Enable all interrupts + * \internal + */ +L4_INLINE +void +l4util_sti (void) +{ + l4_sys_sti(); +} + +/** + * \brief Do not use + * \internal + * + * !!!!!!! + * We probably need some primitive like in linux here which + * enable/disable interrupts on l4util_flags_restore + * + */ + +L4_INLINE +void +l4util_flags_save(l4_umword_t *flags) +{ + (void)flags; + enter_kdebug("l4util_flags_save"); +} + +/** \brief Restore processor flags. Can be used to restore the interrupt flag + * \internal + */ +L4_INLINE +void +l4util_flags_restore(l4_umword_t *flags) +{ + (void)flags; + enter_kdebug("l4util_flags_restore"); +} + +EXTERN_C_END + +#endif //__GNUC__ + +#endif /* ! __L4UTIL__ARCH_ARCH__IRQ_H__ */ diff --git a/l4/pkg/l4util/include/ARCH-arm/l4_macros.h b/l4/pkg/l4util/include/ARCH-arm/l4_macros.h new file mode 100644 index 00000000..b5c54d81 --- /dev/null +++ b/l4/pkg/l4util/include/ARCH-arm/l4_macros.h @@ -0,0 +1,23 @@ +/** + * \file + * \brief Main function + * + * \date 08/29/2000 + * \author Frank Mehnert */ + +/* + * (c) 2006-2009 Author(s) + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ + +#ifndef _L4UTIL__ARCH_ARM__L4_MACROS_H +#define _L4UTIL__ARCH_ARM__L4_MACROS_H + +#ifndef l4_addr_fmt +# define l4_addr_fmt "%08lx" +#endif + +#endif /* !_L4UTIL__ARCH_ARM__L4_MACROS_H */ diff --git a/l4/pkg/l4util/include/ARCH-arm/mbi_argv.h b/l4/pkg/l4util/include/ARCH-arm/mbi_argv.h new file mode 100644 index 00000000..c0f6b035 --- /dev/null +++ b/l4/pkg/l4util/include/ARCH-arm/mbi_argv.h @@ -0,0 +1,13 @@ +/** + * \file + * \brief Multiboot + */ +/* + * (c) 2008-2009 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ +/* If this persists, move it to a generic place */ +#include diff --git a/l4/pkg/l4util/include/ARCH-arm/stack_impl.h b/l4/pkg/l4util/include/ARCH-arm/stack_impl.h new file mode 100644 index 00000000..12d614d6 --- /dev/null +++ b/l4/pkg/l4util/include/ARCH-arm/stack_impl.h @@ -0,0 +1,31 @@ +/** + * \file + * \brief Stack utilities, arm version + */ +/* + * (c) 2008-2009 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ +#ifndef __L4UTIL__INCLUDE__ARCH_ARM__STACK_IMPL_H__ +#define __L4UTIL__INCLUDE__ARCH_ARM__STACK_IMPL_H__ + +#include + +EXTERN_C_BEGIN + +#ifndef _L4UTIL_STACK_H +#error Do not include stack_impl.h directly, use stack.h instead +#endif + +L4_INLINE l4_addr_t l4util_stack_get_sp(void) +{ + register l4_addr_t sp asm ("sp"); + return sp; +} + +EXTERN_C_END + +#endif /* ! __L4UTIL__INCLUDE__ARCH_ARM__STACK_IMPL_H__ */ diff --git a/l4/pkg/l4util/include/ARCH-ppc32/L4API-l4f/l4_macros.h b/l4/pkg/l4util/include/ARCH-ppc32/L4API-l4f/l4_macros.h new file mode 100644 index 00000000..a2658a37 --- /dev/null +++ b/l4/pkg/l4util/include/ARCH-ppc32/L4API-l4f/l4_macros.h @@ -0,0 +1,30 @@ +/*****************************************************************************/ +/** + * \file + * \brief Some useful generic macros, L4f version + * + * \date 11/12/2002 + * \author Lars Reuther */ +/* + * (c) 2000-2009 Author(s) + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ + +/*****************************************************************************/ +#pragma once +#include_next + + +/***************************************************************************** + *** generic macros + *****************************************************************************/ + +/* generate L4 thread id printf string */ +#ifndef l4util_idstr +# define l4util_idfmt "%lx" +# define l4util_idfmt_adjust "%04lx" +# define l4util_idstr(tid) (tid >> L4_CAP_SHIFT) +#endif diff --git a/l4/pkg/l4util/include/ARCH-ppc32/atomic_arch.h b/l4/pkg/l4util/include/ARCH-ppc32/atomic_arch.h new file mode 100644 index 00000000..32709547 --- /dev/null +++ b/l4/pkg/l4util/include/ARCH-ppc32/atomic_arch.h @@ -0,0 +1,8 @@ +/* + * (c) 2009 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ +#include diff --git a/l4/pkg/l4util/include/ARCH-ppc32/bitops_arch.h b/l4/pkg/l4util/include/ARCH-ppc32/bitops_arch.h new file mode 100644 index 00000000..bbcae85b --- /dev/null +++ b/l4/pkg/l4util/include/ARCH-ppc32/bitops_arch.h @@ -0,0 +1,8 @@ +/* + * (c) 2009 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ +#include diff --git a/l4/pkg/l4util/include/ARCH-ppc32/irq.h b/l4/pkg/l4util/include/ARCH-ppc32/irq.h new file mode 100644 index 00000000..539d2a24 --- /dev/null +++ b/l4/pkg/l4util/include/ARCH-ppc32/irq.h @@ -0,0 +1,8 @@ +/* + * (c) 2009 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ +#include diff --git a/l4/pkg/l4util/include/ARCH-ppc32/l4_macros.h b/l4/pkg/l4util/include/ARCH-ppc32/l4_macros.h new file mode 100644 index 00000000..448a6c1b --- /dev/null +++ b/l4/pkg/l4util/include/ARCH-ppc32/l4_macros.h @@ -0,0 +1,20 @@ +/** + * \file + * \brief Main function + * + * \date 08/29/2000 + * \author Frank Mehnert */ + +/* + * (c) 2006-2009 Author(s) + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ +#pragma once + +#ifndef l4_addr_fmt +# define l4_addr_fmt "%08lx" +#endif + diff --git a/l4/pkg/l4util/include/ARCH-ppc32/rdtsc.h b/l4/pkg/l4util/include/ARCH-ppc32/rdtsc.h new file mode 100644 index 00000000..3e901655 --- /dev/null +++ b/l4/pkg/l4util/include/ARCH-ppc32/rdtsc.h @@ -0,0 +1,163 @@ +/** + * \file + * \brief time stamp counter related functions + * + * \date Frank Mehnert + * \ingroup l4util_tsc + */ + +/* + * (c) 2003-2009 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ + +#ifndef __l4_rdtsc_h +#define __l4_rdtsc_h + +/** + * \defgroup l4util_tsc Timestamp Counter + * \ingroup l4util_api + */ + +#include +#include +#include + + +EXTERN_C_BEGIN + +extern l4_uint32_t l4_scaler_tsc_to_us; +extern l4_uint32_t l4_scaler_timer_to_tsc; + +/* interface */ +/** + * \addtogroup l4util_tsc + */ +/*@{*/ + +#define L4_TSC_INIT_AUTO 0 ///< Automatic init +#define L4_TSC_INIT_KERNEL 1 ///< Initialized by kernel +#define L4_TSC_INIT_CALIBRATE 2 ///< Initialized by user-level + +/** + * \brief Read current value of CPU-internal time stamp counter. + * \return 64-bit time stamp + */ +L4_INLINE l4_cpu_time_t +l4_rdtsc (void); + +/** + * \brief Read the lest significant 32 bit of the TSC. + * + * Useful for smaller differences, needs less cycles. + */ +L4_INLINE +l4_uint32_t l4_rdtsc_32(void); + +/** Convert time stamp into micro seconds value. + * \param tsc time value in CPU ticks + * \return time value in micro seconds + */ +L4_INLINE l4_uint64_t +l4_tsc_to_us (l4_cpu_time_t tsc); + +EXTERN_C_BEGIN + +/** + * \brief Calibrate scalers for time stamp calculations. + * + * Determine some scalers to be able to convert between real time and CPU + * ticks. This test uses channel 0 of the PIT (i8254) or the kernel KIP, + * depending on availability. + * Just calls l4_tsc_init(L4_TSC_INIT_AUTO). + */ +L4_INLINE l4_uint32_t +l4_calibrate_tsc (l4_kernel_info_t *kip); + +/** + * \brief Initialitze scaler for TSC calicaltions. + * + * Initialize the scalers needed by l4_tsc_to_ns()/l4_ns_to_tsc() and so on. + * Current versions of Fiasco export these scalers from kernel into userland. + * The programmer may decide whether he allows to use these scalers or if an + * calibration should be performed. + * \param constraint programmers constraint: + * - #L4_TSC_INIT_AUTO if the kernel exports the scalers + * then use them. If not, perform calibration using + * channel 0 of the PIT (i8254). The latter case may + * lead into short (unpredictable) periods where + * interrupts are disabled. + * - #L4_TSC_INIT_KERNEL depend on retrieving the scalers + * from kernel. If the scalers are not available, + * return 0. + * - #L4_TSC_INIT_CALIBRATE Ignore possible scalers + * exported by the scaler, instead insist on + * calibration using the PIT. + * \param kip KIP pointer + * \return 0 on error (no scalers exported by kernel, calibrating failed ...) + * otherwise returns (2^32 / (tsc per µsec)). This value has the + * same semantics as the value returned by the calibrate_delay_loop() + * function of the Linux kernel. + */ +L4_CV l4_uint32_t +l4_tsc_init (int constraint, l4_kernel_info_t *kip); +/*@}*/ + +EXTERN_C_END + +EXTERN_C_BEGIN + +L4_INLINE l4_uint32_t +l4_calibrate_tsc (l4_kernel_info_t *kip) +{ + return l4_tsc_init(0, kip); +} + +L4_INLINE l4_cpu_time_t +l4_rdtsc (void) +{ + l4_uint32_t upper = 0, lower = 0; + l4_cpu_time_t tb; + + __asm__ __volatile__ + (" 1: \n" + " mftbu %[upper] \n" + " mftb %[lower] \n" + " mftbu %%r12 \n" + " cmpw %[upper], %%r12 \n" + " bne- 1b \n" + : [upper] "=r" (upper), + [lower] "=r" (lower) + : "0"(upper), + "1"(lower) + : "r12"); + + tb = upper; + tb = (tb << 32 | lower); + return tb * l4_scaler_timer_to_tsc; +} + +L4_INLINE +l4_uint32_t l4_rdtsc_32(void) +{ + l4_uint32_t lower; + + __asm__ __volatile__ + (" mftb %[lower]\n" + : [lower] "=r" (lower)); + + return lower * l4_scaler_timer_to_tsc; +} + +L4_INLINE l4_uint64_t +l4_tsc_to_us (l4_cpu_time_t tsc) +{ + return tsc / l4_scaler_tsc_to_us; +} + +EXTERN_C_END +#endif /* __l4_rdtsc_h */ + diff --git a/l4/pkg/l4util/include/ARCH-ppc32/stack_impl.h b/l4/pkg/l4util/include/ARCH-ppc32/stack_impl.h new file mode 100644 index 00000000..559a6a78 --- /dev/null +++ b/l4/pkg/l4util/include/ARCH-ppc32/stack_impl.h @@ -0,0 +1,31 @@ +/** + * \file + * \brief Stack utilities, ppc32 version + */ +/* + * (c) 2008-2009 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ +#ifndef __L4UTIL__INCLUDE__ARCH_PPC32__STACK_IMPL_H__ +#define __L4UTIL__INCLUDE__ARCH_PPC32__STACK_IMPL_H__ + +#include + +EXTERN_C_BEGIN + +#ifndef _L4UTIL_STACK_H +#error Do not include stack_impl.h directly, use stack.h instead +#endif + +L4_INLINE l4_addr_t l4util_stack_get_sp(void) +{ + register l4_addr_t sp asm ("sp"); + return sp; +} + +EXTERN_C_END + +#endif /* ! __L4UTIL__INCLUDE__ARCH_PPC32__STACK_IMPL_H__ */ diff --git a/l4/pkg/l4util/include/ARCH-sparc/L4API-l4f/l4_macros.h b/l4/pkg/l4util/include/ARCH-sparc/L4API-l4f/l4_macros.h new file mode 100644 index 00000000..a2658a37 --- /dev/null +++ b/l4/pkg/l4util/include/ARCH-sparc/L4API-l4f/l4_macros.h @@ -0,0 +1,30 @@ +/*****************************************************************************/ +/** + * \file + * \brief Some useful generic macros, L4f version + * + * \date 11/12/2002 + * \author Lars Reuther */ +/* + * (c) 2000-2009 Author(s) + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ + +/*****************************************************************************/ +#pragma once +#include_next + + +/***************************************************************************** + *** generic macros + *****************************************************************************/ + +/* generate L4 thread id printf string */ +#ifndef l4util_idstr +# define l4util_idfmt "%lx" +# define l4util_idfmt_adjust "%04lx" +# define l4util_idstr(tid) (tid >> L4_CAP_SHIFT) +#endif diff --git a/l4/pkg/l4util/include/ARCH-sparc/atomic_arch.h b/l4/pkg/l4util/include/ARCH-sparc/atomic_arch.h new file mode 100644 index 00000000..a1a71ebe --- /dev/null +++ b/l4/pkg/l4util/include/ARCH-sparc/atomic_arch.h @@ -0,0 +1,103 @@ +/** + * \file + * \brief SPARC specific implementation of atomic functions + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ +#ifndef __L4UTIL__INCLUDE__ARCH_SPARC__ATOMIC_ARCH_H__ +#define __L4UTIL__INCLUDE__ARCH_SPARC__ATOMIC_ARCH_H__ + +#ifdef __GNUC__ + +#include + +EXTERN_C_BEGIN + +#define __L4UTIL_ATOMIC_HAVE_ARCH_CMPXCHG32 +L4_INLINE int +l4util_cmpxchg32(volatile l4_uint32_t * dest, + l4_uint32_t cmp_val, l4_uint32_t new_val) +{ + return l4_atomic_cmpxchg((volatile long int *)dest, cmp_val, new_val); +} + +#define __L4UTIL_ATOMIC_HAVE_ARCH_CMPXCHG +L4_INLINE int +l4util_cmpxchg(volatile l4_umword_t * dest, + l4_umword_t cmp_val, l4_umword_t new_val) +{ + return l4_atomic_cmpxchg((volatile long int *)dest, cmp_val, new_val); +} + +#define __L4UTIL_ATOMIC_HAVE_ARCH_XCHG32 +L4_INLINE l4_uint32_t +l4util_xchg32(volatile l4_uint32_t *dest, l4_uint32_t new_val) +{ +// return l4_atomic_xchg((volatile long int *)dest, new_val); + asm volatile ("ta 0"); + return ~0; +} + +#define __L4UTIL_ATOMIC_HAVE_ARCH_XCHG +L4_INLINE l4_umword_t +l4util_xchg(volatile l4_umword_t *dest, l4_umword_t new_val) +{ +// return l4_atomic_xchg((volatile long int *)dest, new_val); + asm volatile ("ta 0"); + return ~0; +} + +#define __L4UTIL_ATOMIC_HAVE_ARCH_ADD +L4_INLINE void +l4util_atomic_add(volatile long *dest, long val) +{ + l4_atomic_add(dest, val); +} + +#define __L4UTIL_ATOMIC_HAVE_ARCH_INC +L4_INLINE void +l4util_atomic_inc(volatile long *dest) +{ + l4_atomic_add(dest, 1); +} + +#define __L4UTIL_ATOMIC_HAVE_ARCH_INC32 +L4_INLINE void +l4util_inc32(volatile l4_uint32_t *dest) +{ + l4_atomic_add((volatile long int *)dest, 1); +} + +#define __L4UTIL_ATOMIC_HAVE_ARCH_DEC32 +L4_INLINE void +l4util_dec32(volatile l4_uint32_t *dest) +{ + l4_atomic_add((volatile long int *)dest, -1); +} + + +#define __L4UTIL_ATOMIC_HAVE_ARCH_INC32_RES +L4_INLINE l4_uint32_t +l4util_inc32_res(volatile l4_uint32_t *dest) +{ + return l4_atomic_add((volatile long int *)dest, 1); +} + +#define __L4UTIL_ATOMIC_HAVE_ARCH_DEC32_RES +L4_INLINE l4_uint32_t +l4util_dec32_res(volatile l4_uint32_t *dest) +{ + return l4_atomic_add((volatile long int *)dest, -1); +} + +EXTERN_C_END + +#endif //__GNUC__ + +#endif /* ! __L4UTIL__INCLUDE__ARCH_SPARC__ATOMIC_ARCH_H__ */ diff --git a/l4/pkg/l4util/include/ARCH-sparc/bitops_arch.h b/l4/pkg/l4util/include/ARCH-sparc/bitops_arch.h new file mode 100644 index 00000000..710719d0 --- /dev/null +++ b/l4/pkg/l4util/include/ARCH-sparc/bitops_arch.h @@ -0,0 +1,4 @@ +#ifndef __L4UTIL_BITOPS_ARCH_SPARC_H +#define __L4UTIL_BITOPS_ARCH_SPARC_H + +#endif diff --git a/l4/pkg/l4util/include/ARCH-sparc/irq.h b/l4/pkg/l4util/include/ARCH-sparc/irq.h new file mode 100644 index 00000000..6d5e1c80 --- /dev/null +++ b/l4/pkg/l4util/include/ARCH-sparc/irq.h @@ -0,0 +1,47 @@ +#ifndef __L4UTIL_SPARC_IRQ_H +#define __L4UTIL_SPARC_IRQ_H + +#include + +EXTERN_C_BEGIN + +L4_INLINE void l4util_cli (void); +L4_INLINE void l4util_sti (void); +L4_INLINE void l4util_flags_save(l4_umword_t *flags); +L4_INLINE void l4util_flags_restore(l4_umword_t *flags); + +L4_INLINE +void +l4util_cli(void) +{ + enter_kdebug("l4util_cli"); +} + + +L4_INLINE +void +l4util_sti(void) +{ + enter_kdebug("l4util_sti"); +} + + +L4_INLINE +void +l4util_flags_save(l4_umword_t *flags) +{ + (void)flags; + enter_kdebug("l4util_flags_save"); +} + +L4_INLINE +void +l4util_flags_restore(l4_umword_t *flags) +{ + (void)flags; + enter_kdebug("l4util_flags_restore"); +} + +EXTERN_C_END + +#endif diff --git a/l4/pkg/l4util/include/ARCH-sparc/l4_macros.h b/l4/pkg/l4util/include/ARCH-sparc/l4_macros.h new file mode 100644 index 00000000..448a6c1b --- /dev/null +++ b/l4/pkg/l4util/include/ARCH-sparc/l4_macros.h @@ -0,0 +1,20 @@ +/** + * \file + * \brief Main function + * + * \date 08/29/2000 + * \author Frank Mehnert */ + +/* + * (c) 2006-2009 Author(s) + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ +#pragma once + +#ifndef l4_addr_fmt +# define l4_addr_fmt "%08lx" +#endif + diff --git a/l4/pkg/l4util/include/ARCH-sparc/stack_impl.h b/l4/pkg/l4util/include/ARCH-sparc/stack_impl.h new file mode 100644 index 00000000..7a874a58 --- /dev/null +++ b/l4/pkg/l4util/include/ARCH-sparc/stack_impl.h @@ -0,0 +1,31 @@ +/** + * \file + * \brief Stack utilities, SPARC version + */ +/* + * (c) 2008-2009 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ +#ifndef __L4UTIL__INCLUDE__ARCH_ARM__STACK_IMPL_H__ +#define __L4UTIL__INCLUDE__ARCH_ARM__STACK_IMPL_H__ + +#include + +EXTERN_C_BEGIN + +#ifndef _L4UTIL_STACK_H +#error Do not include stack_impl.h directly, use stack.h instead +#endif + +L4_INLINE l4_addr_t l4util_stack_get_sp(void) +{ + register l4_addr_t sp = 0; + return sp; +} + +EXTERN_C_END + +#endif /* ! __L4UTIL__INCLUDE__ARCH_ARM__STACK_IMPL_H__ */ diff --git a/l4/pkg/l4util/include/ARCH-x86/L4API-l4f/l4_macros.h b/l4/pkg/l4util/include/ARCH-x86/L4API-l4f/l4_macros.h new file mode 100644 index 00000000..6ae172b3 --- /dev/null +++ b/l4/pkg/l4util/include/ARCH-x86/L4API-l4f/l4_macros.h @@ -0,0 +1,34 @@ +/*****************************************************************************/ +/** + * \file + * \brief Some useful generic macros, L4f version + * + * \date 11/12/2002 + * \author Lars Reuther */ +/* + * (c) 2000-2009 Author(s) + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ + +/*****************************************************************************/ + +#include_next + +#ifndef _L4UTIL__ARCH_X86__L4F__L4_MACROS_H +#define _L4UTIL__ARCH_X86__L4F__L4_MACROS_H + +/***************************************************************************** + *** generic macros + *****************************************************************************/ + +/* generate L4 thread id printf string */ +#ifndef l4util_idstr +# define l4util_idfmt "%lx" +# define l4util_idfmt_adjust "%04lx" +# define l4util_idstr(tid) (tid >> L4_CAP_SHIFT) +#endif + +#endif /* !_L4UTIL__ARCH_X86__L4F__L4_MACROS_H */ diff --git a/l4/pkg/l4util/include/ARCH-x86/L4API-l4f/port_io.h b/l4/pkg/l4util/include/ARCH-x86/L4API-l4f/port_io.h new file mode 100644 index 00000000..c6d930b3 --- /dev/null +++ b/l4/pkg/l4util/include/ARCH-x86/L4API-l4f/port_io.h @@ -0,0 +1,79 @@ +/*****************************************************************************/ +/** + * \file + * \brief port I/O functions + * + * \date 06/2003 + * \author Frank Mehnert + */ +/*****************************************************************************/ + +/* + * (c) 2003-2009 Author(s) + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ + +#ifndef _L4UTIL_PORT_IO_API_H +#define _L4UTIL_PORT_IO_API_H + +#include +#include + +#include + +EXTERN_C_BEGIN + +/** + * \brief Map a range of I/O ports. + * \ingroup l4util_port_io + * + * \param sigma0id I/O port service (sigma0). + * \param port_start (Start) Port to request. + * \param log2size Log2size of range to request. + * + * \return IPC result: 0 if the range could be successfully mapped + * on error: IPC failure, or -L4_ENOENT if nothing mapped + */ +L4_INLINE int +l4util_ioport_map(l4_cap_idx_t sigma0id, + unsigned port_start, unsigned log2size); + +EXTERN_C_END + + +/***************************************************************************** + *** Implementation + *****************************************************************************/ + +#include +#include + + +L4_INLINE int +l4util_ioport_map(l4_cap_idx_t sigma0id, + unsigned port_start, unsigned log2size) +{ + l4_fpage_t iofp; + l4_msgtag_t tag; + long err; + + iofp = l4_iofpage(port_start, log2size); + l4_utcb_mr()->mr[0] = iofp.raw; + l4_utcb_br()->bdr = 0; + l4_utcb_br()->br[0] = L4_ITEM_MAP; + l4_utcb_br()->br[1] = iofp.raw; + tag = l4_ipc_call(sigma0id, l4_utcb(), + l4_msgtag(L4_PROTO_IO_PAGE_FAULT, 1, 0, 0), + L4_IPC_NEVER); + + if ((err = l4_ipc_error(tag, l4_utcb()))) + return err; + + return l4_msgtag_items(tag) > 0 ? 0 : -L4_ENOENT; +} + +#endif + diff --git a/l4/pkg/l4util/include/ARCH-x86/L4API-l4f/setjmp.h b/l4/pkg/l4util/include/ARCH-x86/L4API-l4f/setjmp.h new file mode 100644 index 00000000..b4223ea5 --- /dev/null +++ b/l4/pkg/l4util/include/ARCH-x86/L4API-l4f/setjmp.h @@ -0,0 +1,70 @@ +/*! + * \file + * \brief Inter-thread setjmp/longjmp + * + * \date 11/26/2004 + * \author Jork Loeser + * + */ +/* + * (c) 2004-2009 Author(s) + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ +#ifndef __UTIL_INCLUDE_ARCH_X86_L4API_L4F_SETJMP_H_ +#define __UTIL_INCLUDE_ARCH_X86_L4API_L4F_SETJMP_H_ +#include +#include + +EXTERN_C_BEGIN + +typedef struct{ + l4_umword_t ebx; /* 0 */ + l4_umword_t esi; /* 4 */ + l4_umword_t edi; /* 8 */ + l4_umword_t ebp; /* 12 */ + l4_umword_t esp; /* 16 */ + l4_umword_t eip; /* 20 */ + l4_umword_t eip_caller; /* 24 */ + l4_umword_t eflags; /* 28 */ + l4_umword_t stack[40]; +} l4_thread_jmp_buf_s; +typedef int l4_thread_jmp_buf[sizeof(l4_thread_jmp_buf_s)/sizeof(l4_umword_t)]; + +typedef union{ + l4_thread_jmp_buf_s s; + l4_thread_jmp_buf raw; +} l4_thread_jmp_buf_u; + +/*\brief inter-thread setjmp + * + * \param env jump buffer + * \retval 0 returned directly + * \retval !0 returned from longjmp + * + * Use this function to prepare a longjmp from another thread for this thread. + * + * \see setjmp(3) + */ +extern int l4_thread_setjmp(l4_thread_jmp_buf env); + +/*!\brief inter-thread longjmp + * + * \param thread thread to apply the longjmp to + * \param env jump buffer + * \param val 0: setjmp returns with 1 + * \param val !0: return value of setjmp + * + * This function sets #thread to the location obtained by its former + * l4_thread_setjump on #env. + * + * \see longjmp(3) + * \note In contrast to longjmp(3), this function returns. + */ +void l4_thread_longjmp(l4_threadid_t thread, l4_thread_jmp_buf env, int val); + +EXTERN_C_END + +#endif diff --git a/l4/pkg/l4util/include/ARCH-x86/apic.h b/l4/pkg/l4util/include/ARCH-x86/apic.h new file mode 100644 index 00000000..a98a4c1b --- /dev/null +++ b/l4/pkg/l4util/include/ARCH-x86/apic.h @@ -0,0 +1,415 @@ +/** + * \file + * \brief APIC for X86 + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Frank Mehnert + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ +#ifndef __L4_UTIL_APIC_H +#define __L4_UTIL_APIC_H + +/* + * Local APIC programming library + * + * For documentation, see + * + * "Intel Architecture Software Developer's Manual", Volume 3, chapter 7.5: + * "Advanced Programmable Interrupt Controller (APIC)" + * + * Local APIC is present since + * - INTEL P6 (PPro) + * - AMD K7 (Athlon), Model 2 + * + * In non-SMP-boards, local APIC is disabled, but + * can be activated by writing to a MSR register. + * For using APIC see packets cpufreq and l4rtl. + * + * See linux/include/asm-i386/i82489.h for further details. + */ + +#define APIC_PHYS_BASE 0xFEE00000 +#define APIC_MAP_BASE 0xA0200000 +#define APIC_BASE_MSR 0x1b + +#define APIC_ID 0x20 +#define GET_APIC_ID(x) (((x)>>24)&0x0F) +#define APIC_LVR 0x30 +#define GET_APIC_VERSION(x) ((x)&0xFF) +#define APIC_TASKPRI 0x80 +#define APIC_TPRI_MASK 0xFF +#define APIC_EOI 0xB0 +#define APIC_LDR 0xD0 +#define APIC_LDR_MASK (0xFF<<24) +#define APIC_DFR 0xE0 +#define SET_APIC_DFR(x) ((x)<<28) +#define APIC_SPIV 0xF0 +#define APIC_LVTT 0x320 +#define APIC_LVTPC 0x340 +#define APIC_LVT0 0x350 +#define SET_APIC_TIMER_BASE(x) (((x)<<18)) +#define APIC_TIMER_BASE_DIV 0x2 +#define APIC_LVT1 0x360 +#define APIC_LVTERR 0x370 +#define APIC_TMICT 0x380 +#define APIC_TMCCT 0x390 +#define APIC_TDCR 0x3E0 + +#define APIC_LVT_MASKED (1<<16) +#define APIC_LVT_TIMER_PERIODIC (1<<17) +#define APIC_TDR_DIV_1 0xB +#define APIC_TDR_DIV_2 0x0 +#define APIC_TDR_DIV_4 0x1 +#define APIC_TDR_DIV_8 0x2 +#define APIC_TDR_DIV_16 0x3 +#define APIC_TDR_DIV_32 0x8 +#define APIC_TDR_DIV_64 0x9 +#define APIC_TDR_DIV_128 0xA + +#include +#include + +EXTERN_C_BEGIN + +/* prototypes */ +extern unsigned long apic_map_base; +extern unsigned long apic_timer_divisor; + +extern unsigned long l4_scaler_apic_to_ms; + +L4_CV void apic_show_registers(void); +L4_CV int apic_check_working(void); +L4_CV void apic_activate_by_io(void); +L4_CV void apic_timer_set_divisor(int divisor); + +L4_CV unsigned long l4_calibrate_apic(void); + +EXTERN_C_END + +L4_INLINE void apic_write(unsigned long reg, unsigned long v); +L4_INLINE unsigned long apic_read(unsigned long reg); +L4_INLINE void apic_activate_by_msr(void); +L4_INLINE void apic_deactivate_by_msr(void); +L4_INLINE unsigned long apic_read_phys_address(void); +L4_INLINE int apic_test_present(void); +L4_INLINE void apic_soft_enable(void); +L4_INLINE void apic_init(unsigned long map_addr); +L4_INLINE void apic_done(void); +L4_INLINE void apic_irq_ack(void); + +L4_INLINE void apic_lvt0_disable_irq(void); +L4_INLINE void apic_lvt0_enable_irq(void); +L4_INLINE void apic_lvt1_disable_irq(void); +L4_INLINE void apic_lvt1_enable_irq(void); + +L4_INLINE void apic_timer_write(unsigned long value); +L4_INLINE unsigned long apic_timer_read(void); +L4_INLINE void apic_timer_disable_irq(void); +L4_INLINE void apic_timer_enable_irq(void); +L4_INLINE void apic_timer_assign_irq(unsigned long vector); +L4_INLINE void apic_timer_set_periodic(void); +L4_INLINE void apic_timer_set_one_shot(void); + +L4_INLINE void apic_perf_disable_irq(void); +L4_INLINE void apic_perf_enable_irq(void); +L4_INLINE void apic_perf_assign_irq(unsigned long vector); + + +/* write APIC register */ +L4_INLINE void +apic_write(unsigned long reg, unsigned long v) +{ + *((volatile unsigned long *)(apic_map_base+reg))=v; +} + + +/* read APIC register */ +L4_INLINE unsigned long +apic_read(unsigned long reg) +{ + return *((volatile unsigned long *)(apic_map_base+reg)); +} + + +/* disable LINT0 */ +L4_INLINE void +apic_lvt0_disable_irq(void) +{ + unsigned long tmp_val; + tmp_val = apic_read(APIC_LVT0); + tmp_val |= APIC_LVT_MASKED; + apic_write(APIC_LVT0, tmp_val); +} + + +/* enable LINT0 */ +L4_INLINE void +apic_lvt0_enable_irq(void) +{ + unsigned long tmp_val; + tmp_val = apic_read(APIC_LVT0); + tmp_val &= ~(APIC_LVT_MASKED); + apic_write(APIC_LVT0, tmp_val); +} + + +/* disable LINT1 */ +L4_INLINE void +apic_lvt1_disable_irq(void) +{ + unsigned long tmp_val; + tmp_val = apic_read(APIC_LVT1); + tmp_val |= APIC_LVT_MASKED; + apic_write(APIC_LVT1, tmp_val); +} + + +/* enable LINT1 */ +L4_INLINE void +apic_lvt1_enable_irq(void) +{ + unsigned long tmp_val; + tmp_val = apic_read(APIC_LVT1); + tmp_val &= ~(APIC_LVT_MASKED); + apic_write(APIC_LVT1, tmp_val); +} + + +/* write APIC timer register */ +L4_INLINE void +apic_timer_write(unsigned long value) +{ + apic_read(APIC_TMICT); + apic_write(APIC_TMICT,value); +} + + +/* read APIC timer register */ +L4_INLINE unsigned long +apic_timer_read(void) +{ + return apic_read(APIC_TMCCT); +} + + +/* disable IRQ when APIC timer passes 0 */ +L4_INLINE void +apic_timer_disable_irq(void) +{ + unsigned long tmp_val; + tmp_val = apic_read(APIC_LVTT); + tmp_val |= APIC_LVT_MASKED; + apic_write(APIC_LVTT, tmp_val); +} + + +/* enable IRQ when APIC timer passes 0 */ +L4_INLINE void +apic_timer_enable_irq(void) +{ + unsigned long tmp_val; + tmp_val = apic_read(APIC_LVTT); + tmp_val &= ~(APIC_LVT_MASKED); + apic_write(APIC_LVTT, tmp_val); +} + + +L4_INLINE void +apic_timer_set_periodic(void) +{ + unsigned long tmp_val; + tmp_val = apic_read(APIC_LVTT); + tmp_val |= APIC_LVT_TIMER_PERIODIC; + tmp_val |= APIC_LVT_MASKED; + apic_write(APIC_LVTT, tmp_val); +} + + +L4_INLINE void +apic_timer_set_one_shot(void) +{ + unsigned long tmp_val; + tmp_val = apic_read(APIC_LVTT); + tmp_val &= ~APIC_LVT_TIMER_PERIODIC; + tmp_val |= APIC_LVT_MASKED; + apic_write(APIC_LVTT, tmp_val); +} + + +/* set vector of APIC timer irq */ +L4_INLINE void +apic_timer_assign_irq(unsigned long vector) +{ + unsigned long tmp_val; + tmp_val = apic_read(APIC_LVTT); + tmp_val &= 0xffffff00; + tmp_val |= vector; + tmp_val |= APIC_LVT_MASKED; + apic_write(APIC_LVTT, tmp_val); +} + + +/* disable IRQ when performance counter passes 0 */ +L4_INLINE void +apic_perf_disable_irq(void) +{ + unsigned long tmp_val; + tmp_val = apic_read(APIC_LVTPC); + tmp_val |= APIC_LVT_MASKED; + apic_write(APIC_LVTPC, tmp_val); +} + + +/* enable IRQ when performance counter passes 0 */ +L4_INLINE void +apic_perf_enable_irq(void) +{ + unsigned long tmp_val; + tmp_val = apic_read(APIC_LVTPC); + tmp_val &= ~(APIC_LVT_MASKED); + apic_write(APIC_LVTPC, tmp_val); +} + + +/* set vector of performance counter irq */ +L4_INLINE void +apic_perf_assign_irq(unsigned long vector) +{ + unsigned long tmp_val; + tmp_val = apic_read(APIC_LVTPC); + tmp_val &= 0xffffff00; + tmp_val |= vector; + tmp_val |= APIC_LVT_MASKED; + apic_write(APIC_LVTPC, tmp_val); +} + + +/* activate APIC by writing to appropriate MSR */ +L4_INLINE void +apic_activate_by_msr(void) +{ + unsigned long low; + unsigned long high; + + /* rdmsr */ + asm volatile(".byte 0xf; .byte 0x32\n" + :"=a" (low), + "=d" (high) + :"c" (APIC_BASE_MSR) + ); + + low |= 0x800; /* activate APIC */ + low &= 0x00000fff; + low |= (APIC_PHYS_BASE & 0xfffff000); /* set address */ + + /* wrmsr */ + asm volatile(".byte 0xf; .byte 0x30\n" + : + :"c" (APIC_BASE_MSR), + "a" (low), + "d" (high) + ); +} + + +/* deactivate APIC by writing to appropriate MSR */ +L4_INLINE void +apic_deactivate_by_msr(void) +{ + unsigned long low; + unsigned long high; + + /* rdmsr */ + asm volatile(".byte 0xf; .byte 0x32\n" + :"=a" (low), + "=d" (high) + :"c" (APIC_BASE_MSR) + ); + + low &= 0xfffff7ff; /* deactivate APIC */ + + /* wrmsr */ + asm volatile(".byte 0xf; .byte 0x30\n" + : + :"c" (APIC_BASE_MSR), + "a" (low), + "d" (high) + ); +} + + +/* read memory mapped address of apic */ +L4_INLINE unsigned long +apic_read_phys_address(void) +{ + unsigned long low; + unsigned long high; + + /* rdmsr */ + asm volatile(".byte 0xf; .byte 0x32\n" + :"=a" (low), + "=d" (high) + :"c" (APIC_BASE_MSR) + ); + + return (low &= 0xfffff000); +} + + +/* test if APIC present */ +L4_INLINE int +apic_test_present(void) +{ + unsigned int dummy; + unsigned int capability; + + asm volatile("pushl %%ebx ; cpuid ; popl %%ebx" + : "=a" (dummy), + "=c" (dummy), + "=d" (capability) + : "a" (0x00000001) + : "cc"); + + return ((capability & 1<<9) !=0); +} + + +L4_INLINE void +apic_soft_enable(void) +{ + unsigned long tmp_val; + tmp_val = apic_read(APIC_SPIV); + tmp_val |= (1<<8); /* enable APIC */ + tmp_val &= ~(1<<9); /* enable Focus Processor Checking */ + tmp_val |= 0xff; /* Set spurious IRQ vector to 0xff */ + apic_write(APIC_SPIV, tmp_val); +} + + +L4_INLINE void +apic_init(unsigned long base_addr) +{ + apic_map_base = base_addr; +} + + +L4_INLINE void +apic_done(void) +{ + apic_map_base = 0; +} + + +L4_INLINE void +apic_irq_ack(void) +{ + apic_read(APIC_SPIV); + apic_write(APIC_EOI, 0); +} + + +#endif /* __L4_UTIL_APIC_H */ diff --git a/l4/pkg/l4util/include/ARCH-x86/atomic_arch.h b/l4/pkg/l4util/include/ARCH-x86/atomic_arch.h new file mode 100644 index 00000000..1e4a8699 --- /dev/null +++ b/l4/pkg/l4util/include/ARCH-x86/atomic_arch.h @@ -0,0 +1,363 @@ +/*****************************************************************************/ +/** + * \file + * \brief i386 atomic operations + * \ingroup atomic + * + * \date 10/20/2000 + * \author Lars Reuther , + * Jork Loeser */ +/* + * (c) 2000-2009 Author(s) + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ + +/*****************************************************************************/ +#ifndef __L4UTIL__INCLUDE__ARCH_X86__ATOMIC_ARCH_H__ +#define __L4UTIL__INCLUDE__ARCH_X86__ATOMIC_ARCH_H__ + +/***************************************************************************** + *** Implementation + *****************************************************************************/ + +EXTERN_C_BEGIN + +#define LOCK "lock;" + +/* atomic compare and exchange 64 bit value */ +#define __L4UTIL_ATOMIC_HAVE_ARCH_CMPXCHG64 +L4_INLINE int +l4util_cmpxchg64(volatile l4_uint64_t * dest, + l4_uint64_t cmp_val, l4_uint64_t new_val) +{ + unsigned char ret; + l4_umword_t dummy; + + __asm__ __volatile__ + ( +#ifdef __PIC__ + LOCK "xchg %%esi,%%ebx\n\t" +#endif + LOCK "cmpxchg8b %5\n\t" + "sete %0\n\t" +#ifdef __PIC__ + "xchg %%esi,%%ebx\n\t" +#endif + : + "=a" (ret), /* return val, 0 or 1 */ + "=d" (dummy) + : + "A" (cmp_val), + "c" ((unsigned int)(new_val>>32ULL)), +#ifdef __PIC__ + "S" +#else + "b" +#endif + ((unsigned int)new_val), + "m" (*dest) /* 3 mem, destination operand */ + : + "memory", "cc" + ); + + return ret; +} + +/* atomic compare and exchange 32 bit value */ +#define __L4UTIL_ATOMIC_HAVE_ARCH_CMPXCHG32 +L4_INLINE int +l4util_cmpxchg32(volatile l4_uint32_t * dest, + l4_uint32_t cmp_val, l4_uint32_t new_val) +{ + l4_uint32_t tmp; + + __asm__ __volatile__ + ( + LOCK "cmpxchgl %1, %3 \n\t" + : + "=a" (tmp) /* 0 EAX, return val */ + : + "r" (new_val), /* 1 reg, new value */ + "0" (cmp_val), /* 2 EAX, compare value */ + "m" (*dest) /* 3 mem, destination operand */ + : + "memory", "cc" + ); + + return tmp == cmp_val; +} + +/* atomic compare and exchange 16 bit value */ +#define __L4UTIL_ATOMIC_HAVE_ARCH_CMPXCHG16 +L4_INLINE int +l4util_cmpxchg16(volatile l4_uint16_t * dest, + l4_uint16_t cmp_val, l4_uint16_t new_val) +{ + l4_uint16_t tmp; + + __asm__ __volatile__ + ( + LOCK "cmpxchgw %1, %3 \n\t" + : + "=a" (tmp) /* 0 AX, return value */ + : + "c" (new_val), /* 1 CX, new value */ + "0" (cmp_val), /* 2 AX, compare value */ + "m" (*dest) /* 3 mem, destination operand */ + : + "memory", "cc" + ); + + return tmp == cmp_val; +} + +/* atomic compare and exchange 8 bit value */ +#define __L4UTIL_ATOMIC_HAVE_ARCH_CMPXCHG8 +L4_INLINE int +l4util_cmpxchg8(volatile l4_uint8_t * dest, + l4_uint8_t cmp_val, l4_uint8_t new_val) +{ + l4_uint8_t tmp; + + __asm__ __volatile__ + ( + LOCK "cmpxchgb %1, %3 \n\t" + : + "=a" (tmp) /* 0 AL, return value */ + : + "c" (new_val), /* 1 CL, new value */ + "0" (cmp_val), /* 2 AL, compare value */ + "m" (*dest) /* 3 mem, destination operand */ + : + "memory", "cc" + ); + + return tmp == cmp_val; +} + +#define __L4UTIL_ATOMIC_HAVE_ARCH_CMPXCHG +L4_INLINE int +l4util_cmpxchg(volatile l4_umword_t * dest, + l4_umword_t cmp_val, l4_umword_t new_val) +{ + return l4util_cmpxchg32((volatile l4_uint32_t *)dest, + (l4_uint32_t)cmp_val, (l4_uint32_t)new_val); +} + +/* atomic exchange 32 bit value */ +#define __L4UTIL_ATOMIC_HAVE_ARCH_XCHG32 +L4_INLINE l4_uint32_t +l4util_xchg32(volatile l4_uint32_t * dest, l4_uint32_t val) +{ + __asm__ __volatile__ + ( + LOCK "xchg %0, %1 \n\t" + : + "=r" (val) + : + "m" (*dest), "0" (val) + : + "memory" + ); + + return val; +} + +/* atomic exchange 16 bit value */ +#define __L4UTIL_ATOMIC_HAVE_ARCH_XCHG16 +L4_INLINE l4_uint16_t +l4util_xchg16(volatile l4_uint16_t * dest, l4_uint16_t val) +{ + __asm__ __volatile__ + ( + LOCK "xchg %w0, %1 \n\t" + : + "=r" (val) + : + "m" (*dest), "0" (val) + : + "memory" + ); + + return val; +} + +/* atomic exchange 8 bit value */ +#define __L4UTIL_ATOMIC_HAVE_ARCH_XCHG8 +L4_INLINE l4_uint8_t +l4util_xchg8(volatile l4_uint8_t * dest, l4_uint8_t val) +{ + __asm__ __volatile__ + ( + LOCK "xchg %b0, %1 \n\t" + : + "=r" (val) + : + "m" (*dest), "0" (val) + : + "memory" + ); + + return val; +} + +/* atomic exchange machine width */ +#define __L4UTIL_ATOMIC_HAVE_ARCH_XCHG +L4_INLINE l4_umword_t +l4util_xchg(volatile l4_umword_t * dest, l4_umword_t val) +{ + return l4util_xchg32((volatile l4_uint32_t *)dest, (l4_uint32_t)val); +} + +#define l4util_gen_allop(args...) \ +l4util_genop( 8,"b", "", args) \ +l4util_genop(16,"w", "", args) \ +l4util_genop(32,"l", "", args) + +#define __L4UTIL_ATOMIC_HAVE_ARCH_ADD8 +#define __L4UTIL_ATOMIC_HAVE_ARCH_ADD16 +#define __L4UTIL_ATOMIC_HAVE_ARCH_ADD32 +#define __L4UTIL_ATOMIC_HAVE_ARCH_SUB8 +#define __L4UTIL_ATOMIC_HAVE_ARCH_SUB16 +#define __L4UTIL_ATOMIC_HAVE_ARCH_SUB32 +#define __L4UTIL_ATOMIC_HAVE_ARCH_AND8 +#define __L4UTIL_ATOMIC_HAVE_ARCH_AND16 +#define __L4UTIL_ATOMIC_HAVE_ARCH_AND32 +#define __L4UTIL_ATOMIC_HAVE_ARCH_OR8 +#define __L4UTIL_ATOMIC_HAVE_ARCH_OR16 +#define __L4UTIL_ATOMIC_HAVE_ARCH_OR32 +/* Generate void l4util_{add,sub,and,or}{8,16,32}(*dest) */ +#undef l4util_genop +#define l4util_genop(bit, mod, op1, opname) \ +L4_INLINE void \ +l4util_##opname##bit(volatile l4_uint##bit##_t* dest, l4_uint##bit##_t val) \ +{ \ + __asm__ __volatile__ \ + ( \ + LOCK #opname mod " %1,%0 \n\t" \ + : \ + : \ + "m" (*dest), "ir" (val) \ + : \ + "memory" \ + ); \ +} +l4util_gen_allop(add) +l4util_gen_allop(sub) +l4util_gen_allop(and) +l4util_gen_allop(or) + +#define __L4UTIL_ATOMIC_HAVE_ARCH_ADD8_RES +#define __L4UTIL_ATOMIC_HAVE_ARCH_ADD16_RES +#define __L4UTIL_ATOMIC_HAVE_ARCH_ADD32_RES +#define __L4UTIL_ATOMIC_HAVE_ARCH_SUB8_RES +#define __L4UTIL_ATOMIC_HAVE_ARCH_SUB16_RES +#define __L4UTIL_ATOMIC_HAVE_ARCH_SUB32_RES +#define __L4UTIL_ATOMIC_HAVE_ARCH_AND8_RES +#define __L4UTIL_ATOMIC_HAVE_ARCH_AND16_RES +#define __L4UTIL_ATOMIC_HAVE_ARCH_AND32_RES +#define __L4UTIL_ATOMIC_HAVE_ARCH_OR8_RES +#define __L4UTIL_ATOMIC_HAVE_ARCH_OR16_RES +#define __L4UTIL_ATOMIC_HAVE_ARCH_OR32_RES +/* Generate l4_uint{8,16,32} l4util_{add,sub,and,or}{8,16,32}_res(*dest) */ +#undef l4util_genop +#define l4util_genop(bit, mod, op1, opname, opchar) \ +L4_INLINE l4_uint##bit##_t \ +l4util_##opname##bit##_res(volatile l4_uint##bit##_t* dest, \ + l4_uint##bit##_t val) \ +{ \ + l4_uint##bit##_t res, old; \ + \ + do \ + { \ + old = *dest; \ + res = old opchar val; \ + } \ + while (!l4util_cmpxchg##bit(dest, old, res)); \ + \ + return res; \ +} +l4util_gen_allop(add, +) +l4util_gen_allop(sub, -) +l4util_gen_allop(and, &) +l4util_gen_allop(or, |) + +#define __L4UTIL_ATOMIC_HAVE_ARCH_INC8 +#define __L4UTIL_ATOMIC_HAVE_ARCH_INC16 +#define __L4UTIL_ATOMIC_HAVE_ARCH_INC32 +#define __L4UTIL_ATOMIC_HAVE_ARCH_DEC8 +#define __L4UTIL_ATOMIC_HAVE_ARCH_DEC16 +#define __L4UTIL_ATOMIC_HAVE_ARCH_DEC32 +/* Generate void l4util_{inc,dec}{8,16,32}(*dest) */ +#undef l4util_genop +#define l4util_genop(bit, mod, op1, opname) \ +L4_INLINE void \ +l4util_##opname##bit(volatile l4_uint##bit##_t* dest) \ +{ \ + __asm__ __volatile__ \ + ( \ + LOCK #opname mod " %0 \n\t" \ + : \ + : \ + "m" (*dest) \ + : \ + "memory" \ + ); \ +} +l4util_gen_allop(inc) +l4util_gen_allop(dec) + +#define __L4UTIL_ATOMIC_HAVE_ARCH_INC8_RES +#define __L4UTIL_ATOMIC_HAVE_ARCH_INC16_RES +#define __L4UTIL_ATOMIC_HAVE_ARCH_INC32_RES +#define __L4UTIL_ATOMIC_HAVE_ARCH_DEC8_RES +#define __L4UTIL_ATOMIC_HAVE_ARCH_DEC16_RES +#define __L4UTIL_ATOMIC_HAVE_ARCH_DEC32_RES +/* Generate l4_uint{8,16,32} l4util_{inc,dec}{8,16,32}_res(*dest) */ +#undef l4util_genop +#define l4util_genop(bit, mod, op1, opname, opchar) \ +L4_INLINE l4_uint##bit##_t \ +l4util_##opname##bit##_res(volatile l4_uint##bit##_t* dest) \ +{ \ + l4_uint##bit##_t res, old; \ + \ + do \ + { \ + res = *dest; \ + old = res opchar; \ + } \ + while (!l4util_cmpxchg##bit(dest, old, res)); \ + \ + return res; \ +} +l4util_gen_allop(inc, ++) +l4util_gen_allop(dec, --) + +#undef l4util_genop +#undef l4util_gen_allop + + +#define __L4UTIL_ATOMIC_HAVE_ARCH_ADD +L4_INLINE void +l4util_atomic_add(volatile long *dest, long val) +{ + __asm__ __volatile__(LOCK "addl %1, %0 \n" + : "=m" (*dest) + : "ri" (val), "m" (*dest)); +} + +#define __L4UTIL_ATOMIC_HAVE_ARCH_INC +L4_INLINE void +l4util_atomic_inc(volatile long *dest) +{ + __asm__ __volatile__(LOCK "incl %0" + : "=m" (*dest) + : "m" (*dest)); +} + +EXTERN_C_END + +#endif /* ! __L4UTIL__INCLUDE__ARCH_X86__ATOMIC_ARCH_H__ */ diff --git a/l4/pkg/l4util/include/ARCH-x86/bitops_arch.h b/l4/pkg/l4util/include/ARCH-x86/bitops_arch.h new file mode 100644 index 00000000..52160d9a --- /dev/null +++ b/l4/pkg/l4util/include/ARCH-x86/bitops_arch.h @@ -0,0 +1,294 @@ +/*****************************************************************************/ +/** + * \file + * \brief x86 bit manipulation functions + * \ingroup bitops + * + * \date 07/03/2001 + * \author Lars Reuther */ +/* + * (c) 2000-2009 Author(s) + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ + +/*****************************************************************************/ +#ifndef __L4UTIL__INCLUDE__ARCH_X86__BITOPS_ARCH_H__ +#define __L4UTIL__INCLUDE__ARCH_X86__BITOPS_ARCH_H__ + +/***************************************************************************** + *** Implementation + *****************************************************************************/ + +EXTERN_C_BEGIN + +/* set bit */ +#define __L4UTIL_BITOPS_HAVE_ARCH_SET_BIT32 +L4_INLINE void +l4util_set_bit32(int b, volatile l4_uint32_t * dest) +{ + __asm__ __volatile__ + ( + "btsl %1,%0 \n\t" + : + : + "m" (*dest), /* 0 mem, destination operand */ + "Ir" (b) /* 1, bit number */ + : + "memory", "cc" + ); +} + +#define __L4UTIL_BITOPS_HAVE_ARCH_SET_BIT +L4_INLINE void +l4util_set_bit(int b, volatile l4_umword_t * dest) +{ + return l4util_set_bit32(b, (volatile l4_uint32_t*)dest); +} + +/* clear bit */ +#define __L4UTIL_BITOPS_HAVE_ARCH_CLEAR_BIT32 +L4_INLINE void +l4util_clear_bit32(int b, volatile l4_uint32_t * dest) +{ + __asm__ __volatile__ + ( + "btrl %1,%0 \n\t" + : + : + "m" (*dest), /* 0 mem, destination operand */ + "Ir" (b) /* 1, bit number */ + : + "memory", "cc" + ); +} + +#define __L4UTIL_BITOPS_HAVE_ARCH_CLEAR_BIT +L4_INLINE void +l4util_clear_bit(int b, volatile l4_umword_t * dest) +{ + return l4util_clear_bit32(b, (volatile l4_uint32_t*)dest); +} + +/* change bit */ +#define __L4UTIL_BITOPS_HAVE_ARCH_COMPLEMENT_BIT +L4_INLINE void +l4util_complement_bit(int b, volatile l4_umword_t * dest) +{ + __asm__ __volatile__ + ( + "btcl %1,%0 \n\t" + : + : + "m" (*dest), /* 0 mem, destination operand */ + "Ir" (b) /* 1, bit number */ + : + "memory", "cc" + ); +} + +/* test bit */ +#define __L4UTIL_BITOPS_HAVE_ARCH_TEST_BIT32 +L4_INLINE int +l4util_test_bit32(int b, const volatile l4_uint32_t * dest) +{ + l4_int8_t bit; + + __asm__ __volatile__ + ( + "btl %2,%1 \n\t" + "setc %0 \n\t" + : + "=q" (bit) /* 0, old bit value */ + : + "m" (*dest), /* 1 mem, destination operand */ + "Ir" (b) /* 2, bit number */ + : + "memory", "cc" + ); + + return (int)bit; +} + +/* test bit */ +#define __L4UTIL_BITOPS_HAVE_ARCH_TEST_BIT +L4_INLINE int +l4util_test_bit(int b, const volatile l4_umword_t * dest) +{ + return l4util_test_bit32(b, (const volatile l4_uint32_t*)dest); +} + +/* bit test and set */ +#define __L4UTIL_BITOPS_HAVE_ARCH_BIT_TEST_AND_SET +L4_INLINE int +l4util_bts(int b, volatile l4_umword_t * dest) +{ + l4_int8_t bit; + + __asm__ __volatile__ + ( + "btsl %2,%1 \n\t" + "setc %0 \n\t" + : + "=q" (bit) /* 0, old bit value */ + : + "m" (*dest), /* 1 mem, destination operand */ + "Ir" (b) /* 2, bit number */ + : + "memory", "cc" + ); + + return (int)bit; +} + +/* bit test and reset */ +#define __L4UTIL_BITOPS_HAVE_ARCH_BIT_TEST_AND_RESET +L4_INLINE int +l4util_btr(int b, volatile l4_umword_t * dest) +{ + l4_int8_t bit; + + __asm__ __volatile__ + ( + "btrl %2,%1 \n\t" + "setc %0 \n\t" + : + "=q" (bit) /* 0, old bit value */ + : + "m" (*dest), /* 1 mem, destination operand */ + "Ir" (b) /* 2, bit number */ + : + "memory", "cc" + ); + + return (int)bit; +} + +/* bit test and complement */ +#define __L4UTIL_BITOPS_HAVE_ARCH_BIT_TEST_AND_COMPLEMENT +L4_INLINE int +l4util_btc(int b, volatile l4_umword_t * dest) +{ + l4_int8_t bit; + + __asm__ __volatile__ + ( + "btcl %2,%1 \n\t" + "setc %0 \n\t" + : + "=q" (bit) /* 0, old bit value */ + : + "m" (*dest), /* 1 mem, destination operand */ + "Ir" (b) /* 2, bit number */ + : + "memory", "cc" + ); + + return (int)bit; +} + +/* bit scan reverse */ +#define __L4UTIL_BITOPS_HAVE_ARCH_BIT_SCAN_REVERSE +L4_INLINE int +l4util_bsr(l4_umword_t word) +{ + int tmp; + + if (EXPECT_FALSE(word == 0)) + return -1; + + __asm__ __volatile__ + ( + "bsrl %1,%0 \n\t" + : + "=r" (tmp) /* 0, index of most significant set bit */ + : + "r" (word) /* 1, argument */ + ); + + return tmp; +} + +/* bit scan forwad */ +#define __L4UTIL_BITOPS_HAVE_ARCH_BIT_SCAN_FORWARD +L4_INLINE int +l4util_bsf(l4_umword_t word) +{ + int tmp; + + if (EXPECT_FALSE(word == 0)) + return -1; + + __asm__ __volatile__ + ( + "bsfl %1,%0 \n\t" + : + "=r" (tmp) /* 0, index of least significant set bit */ + : + "r" (word) /* 1, argument */ + ); + + return tmp; +} + +#define __L4UTIL_BITOPS_HAVE_ARCH_FIND_FIRST_SET_BIT +L4_INLINE int +l4util_find_first_set_bit(const void * dest, l4_size_t size) +{ + l4_mword_t dummy0, dummy1, res; + + __asm__ __volatile__ + ( + "repe; scasl \n\t" + "jz 1f \n\t" + "leal -4(%%edi),%%edi \n\t" + "bsfl (%%edi),%%eax \n" + "1: \n\t" + "subl %%esi,%%edi \n\t" + "shll $3,%%edi \n\t" + "addl %%edi,%%eax \n\t" + : + "=a" (res), "=c" (dummy0), "=D" (dummy1) + : + "a"(0), "c" ((size+31) >> 5), "D" (dest), "S" (dest) + : + "cc", "memory"); + + return res; +} + +#define __L4UTIL_BITOPS_HAVE_ARCH_FIND_FIRST_ZERO_BIT +L4_INLINE int +l4util_find_first_zero_bit(const void * dest, l4_size_t size) +{ + l4_mword_t dummy0, dummy1, dummy2, res; + + if (!size) + return 0; + + __asm__ __volatile__ + ( + "repe; scasl \n\t" + "je 1f \n\t" + "xorl -4(%%edi),%%eax \n\t" + "subl $4,%%edi \n\t" + "bsfl %%eax,%%edx \n" + "1: \n\t" + "subl %%esi,%%edi \n\t" + "shll $3,%%edi \n\t" + "addl %%edi,%%edx \n\t" + : + "=d" (res), "=c" (dummy0), "=D" (dummy1), "=a" (dummy2) + : + "a" (~0), "c" ((size+31) >> 5), "d"(0), "D" (dest), "S" (dest) + : + "cc", "memory"); + + return res; +} + +EXTERN_C_END + +#endif /* ! __L4UTIL__INCLUDE__ARCH_X86__BITOPS_ARCH_H__ */ diff --git a/l4/pkg/l4util/include/ARCH-x86/cpu.h b/l4/pkg/l4util/include/ARCH-x86/cpu.h new file mode 100644 index 00000000..04ad05ca --- /dev/null +++ b/l4/pkg/l4util/include/ARCH-x86/cpu.h @@ -0,0 +1,125 @@ +/** + * \file + * \brief CPU related functions + * + * \author Frank Mehnert */ + +/* + * (c) 2004-2009 Author(s) + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ + +#ifndef __L4_UTIL_CPU_H +#define __L4_UTIL_CPU_H + +#include + +EXTERN_C_BEGIN + +/** + * \defgroup l4util_cpu CPU related functions + * \ingroup l4util_api + */ +/*@{*/ + +/** + * Check whether the CPU supports the "cpuid" instruction. + * + * \return 1 if it has, 0 if it has not + */ +L4_INLINE int l4util_cpu_has_cpuid(void); + +/** + * Returns the CPU capabilities if the "cpuid" instruction is available. + * + * \return CPU capabilities if the "cpuid" instruction is available, + * 0 if the "cpuid" instruction is not supported. + */ +L4_INLINE unsigned int l4util_cpu_capabilities(void); + +/** + * Returns the CPU capabilities. + * + * \return CPU capabilities. + */ +L4_INLINE unsigned int l4util_cpu_capabilities_nocheck(void); + +/** + * Generic CPUID access function. + */ +L4_INLINE void +l4util_cpu_cpuid(unsigned long mode, + unsigned long *eax, unsigned long *ebx, + unsigned long *ecx, unsigned long *edx); + +/*@}*/ +static inline void +l4util_cpu_pause(void) +{ + __asm__ __volatile__ ("rep; nop"); +} + +L4_INLINE int +l4util_cpu_has_cpuid(void) +{ + unsigned long eax; + + asm volatile("pushfl \t\n" + "popl %%eax \t\n" /* get eflags */ + "movl %%eax, %%ebx \t\n" /* save it */ + "xorl $0x200000, %%eax \t\n" /* toggle ID bit */ + "pushl %%eax \t\n" + "popfl \t\n" /* set again */ + "pushfl \t\n" + "popl %%eax \t\n" /* get it again */ + "xorl %%eax, %%ebx \t\n" + "pushl %%ebx \t\n" + "popfl \t\n" /* restore saved flags */ + : "=a" (eax) + : /* no input */ + : "ebx"); + + return eax & 0x200000; +} + +L4_INLINE void +l4util_cpu_cpuid(unsigned long mode, + unsigned long *eax, unsigned long *ebx, + unsigned long *ecx, unsigned long *edx) +{ + asm volatile("cpuid" + : "=a" (*eax), + "=b" (*ebx), + "=c" (*ecx), + "=d" (*edx) + : "a" (mode) + : "cc"); +} + +L4_INLINE unsigned int +l4util_cpu_capabilities_nocheck(void) +{ + unsigned long dummy, capability; + + /* get CPU capabilities */ + l4util_cpu_cpuid(1, &dummy, &dummy, &dummy, &capability); + + return capability; +} + +L4_INLINE unsigned int +l4util_cpu_capabilities(void) +{ + if (!l4util_cpu_has_cpuid()) + return 0; /* CPU has not cpuid instruction */ + + return l4util_cpu_capabilities_nocheck(); +} + +EXTERN_C_END + +#endif + diff --git a/l4/pkg/l4util/include/ARCH-x86/idt.h b/l4/pkg/l4util/include/ARCH-x86/idt.h new file mode 100644 index 00000000..a1334745 --- /dev/null +++ b/l4/pkg/l4util/include/ARCH-x86/idt.h @@ -0,0 +1,87 @@ +/** + * \file + * \brief IDT related functions + * \ingroup irq + * + * \date 2003 + * \author Frank Mehnert */ + +/* + * (c) 2003-2009 Author(s) + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ + +#ifndef __L4UTIL_IDT_H +#define __L4UTIL_IDT_H + +#include +#include + +EXTERN_C_BEGIN + +/** + * \defgroup l4util_idt Functions to manipulate the local IDT + * \ingroup l4util_api + */ +/*@{*/ + +/** IDT entry. + */ +typedef struct +{ + l4_uint32_t a, b; /**< see Intel doc */ +} __attribute__ ((packed)) l4util_idt_desc_t; + +/** Header of an IDT table. + */ +typedef struct +{ + l4_uint16_t limit; /**< limit field (see Intel doc) */ + void *base; /**< idt base (see Intel doc) */ + l4util_idt_desc_t desc[0]; +} __attribute__ ((packed)) l4util_idt_header_t; + +/** Create an IDT entry. + * \param idt pointer to idt table header + * \param nr # of exception vector + * \param handler exception handler + */ +static inline void +l4util_idt_entry(l4util_idt_header_t *idt, int nr, void(*handler)(void)) +{ + idt->desc[nr].a = (l4_uint32_t)handler & 0x0000ffff; + idt->desc[nr].b = 0x0000ef00 | ((l4_uint32_t)handler & 0xffff0000); +} + +/** Initializes an IDT. + * \param idt pointer to idt table header + * \param entries # of of exception entries to hold by the idt table + */ +static inline void +l4util_idt_init(l4util_idt_header_t *idt, int entries) +{ + int i; + idt->limit = entries*8 - 1; + idt->base = &idt->desc; + + for (i=0; i + * Frank Mehnert */ + +/* + * (c) 2003-2009 Author(s) + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ + +#ifndef __L4_IRQ_H__ +#define __L4_IRQ_H__ + +#include +#include + +EXTERN_C_BEGIN + +/** Acknowledge IRQ at PIC in fully special nested mode. + * \param irq number of interrupt to acknowledge + */ +L4_INLINE void +l4util_irq_acknowledge(unsigned int irq); + +/** Disable all interrupts + */ +static inline void +l4util_cli (void) +{ + __asm__ __volatile__ ("cli" : : : "memory"); +} + +/** Enable all interrupts + */ +static inline void +l4util_sti (void) +{ + __asm__ __volatile__ ("sti" : : : "memory"); +} + +/** Save the processor flags. Can be used to save and later restore the + * interrupt flag + */ +static inline void +l4util_flags_save (l4_umword_t *flags) +{ + __asm__ __volatile__ ("pushfl ; popl %0 " :"=g" (*flags) : :"memory"); +} + +/** Restore processor flags. Can be used to restore the interrupt flag + */ +static inline void +l4util_flags_restore (l4_umword_t *flags) +{ + __asm__ __volatile__ ("pushl %0 ; popfl" : :"g" (*flags) : "memory"); +} + +L4_INLINE void +l4util_irq_acknowledge(unsigned int irq) +{ + if (irq > 7) + { + l4util_out8(0x60+(irq & 7), 0xA0); + l4util_out8(0x0B,0xA0); + if (l4util_in8(0xA0) == 0) + l4util_out8(0x60 + 2, 0x20); + } + else + l4util_out8(0x60+irq, 0x20); /* acknowledge the irq */ +}; + +EXTERN_C_END + +#endif diff --git a/l4/pkg/l4util/include/ARCH-x86/l4_macros.h b/l4/pkg/l4util/include/ARCH-x86/l4_macros.h new file mode 100644 index 00000000..ccf6b8d9 --- /dev/null +++ b/l4/pkg/l4util/include/ARCH-x86/l4_macros.h @@ -0,0 +1,24 @@ +/** + * \file + * \brief Main function + * + * \date 08/29/2000 + * \author Frank Mehnert */ + +/* + * (c) 2006-2009 Author(s) + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ + + +#ifndef _L4UTIL__ARCH_X86__L4_MACROS_H +#define _L4UTIL__ARCH_X86__L4_MACROS_H + +#ifndef l4_addr_fmt +# define l4_addr_fmt "%08lx" +#endif + +#endif /* !_L4UTIL__ARCH_X86__L4_MACROS_H */ diff --git a/l4/pkg/l4util/include/ARCH-x86/mbi_argv.h b/l4/pkg/l4util/include/ARCH-x86/mbi_argv.h new file mode 100644 index 00000000..9f20c3c0 --- /dev/null +++ b/l4/pkg/l4util/include/ARCH-x86/mbi_argv.h @@ -0,0 +1,33 @@ +/** + * \file + * \brief command line handling + * + * \date 2003 + * \author Frank Mehnert */ + +/* + * (c) 2003-2009 Author(s) + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ + +#ifndef L4UTIL_MBI_ARGV +#define L4UTIL_MBI_ARGV + +#include +#include +#include + +EXTERN_C_BEGIN + +void l4util_mbi_to_argv(l4_mword_t flag, l4util_mb_info_t *mbi); + +extern int l4util_argc; +extern char *l4util_argv[]; + +EXTERN_C_END + +#endif + diff --git a/l4/pkg/l4util/include/ARCH-x86/perform.h b/l4/pkg/l4util/include/ARCH-x86/perform.h new file mode 100644 index 00000000..41bea798 --- /dev/null +++ b/l4/pkg/l4util/include/ARCH-x86/perform.h @@ -0,0 +1,452 @@ +/** + * \file + * \brief Perfomance Monitoring using P5/P6 Measurement Counters. + * + * Define either CPU_PENTIUM or CPU_P6 + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Frank Mehnert , + * Lars Reuther + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ + +#ifndef __L4UTIL_PERFORM_H +#define __L4UTIL_PERFORM_H + +#include +#include + +EXTERN_C_BEGIN + +extern const char*strp6pmc_event(l4_uint32_t event); + +#ifndef CONFIG_PERFORM_ONLY_PROTOTYPES + +#if ! (defined CPU_PENTIUM ^ defined CPU_P6 ^ defined CPU_K7) + +#error You must define your target architecture. +#error Define EITHER CPU_PENTIUM for Intel Pentium or CPU_P6 for Intel PPro/PII/PIII. + +#else + +/* P5/P6/K7 section */ + +/* Makros for access to model specific registers (MSR) */ + +/* Write the 64-Bit Model Specific Register. First argument is the register, + second the 64-Bit value. This can only be called at priviledge level 0. + With L4, the kernel emulates the WRMSR when calling in PL 3. + */ +static inline void l4_i586_wrmsr(unsigned reg,unsigned long long*val){ + unsigned long dummyeax, dummyecx, dummyedx; + + asm volatile( + ".byte 0xf; .byte 0x30\n" /* wrmsr */ + : "=a" (dummyeax), "=d" (dummyedx), "=c" (dummyecx) + : "2" (reg), "0" (*(unsigned *)val), "1" (*((unsigned *)val+1)) + ); +} + +/* Read the 64-Bit Model Specific Register. First argument is the register, + second the address to a 64-Bit value. This can only be called at + priviledge level 0. With L4, the kernel emulates the RDMSR when calling + in PL 3. + */ +static inline void l4_i586_rdmsr(unsigned reg,unsigned long long*val){ + unsigned dummy; + + asm volatile( + ".byte 0xf; .byte 0x32\n" /* rdmsr */ + : "=a" (*(unsigned *)val), "=d" (*((unsigned *)val+1)), "=c" (dummy) + : "2" (reg) + ); +} + + +#ifdef CPU_PENTIUM +/* Pentium section */ + +/* functions and events defined here are only usable at Pentium + Processors. P6 architecture does NOT support this kind of measuring and + these events. P6 architecture has its own counters and its own events. + See P6-section for details. */ + +/* from l4linux/arch/l4-i386/include/perform.h */ + +static inline void +l4_i586_reset_event_counter(void){ + asm volatile("xor %%eax, %%eax\n" + "xor %%edx, %%edx\n" + "movl $0x12, %%ecx\n" + ".byte 0x0f, 0x30\n" + "movl $0x13, %%ecx\n" + ".byte 0x0f, 0x30\n" + : : : "cx", "ax", "dx" + ); +}; + +static inline void +l4_i586_read_event_counter_long(long long *counter0, long long *counter1) +{ + asm volatile( + /* "movl $0, %%eax\n" + "movl $0x11, %%ecx\n" + ".byte 0x0f, 0x30\n" *//* stop event counting */ + "movl $0x12, %%ecx\n" + ".byte 0x0f, 0x32\n" + "movl %%eax, (%%ebx)\n" + "movl %%edx, 4(%%ebx)\n" + "movl $0x13, %%ecx\n" + ".byte 0x0f, 0x32\n" + "movl %%eax, (%%esi)\n" + "movl %%edx, 4(%%esi)\n" + : /* no output */ + : "b" (counter0), "S" (counter1) + : "ax", "cx", "dx" + ); +} + +static inline void +l4_i586_read_event_counter(int *counter0, int *counter1) +{ + asm volatile("pushl %%edx\n" + ".byte 0x0f, 0x30\n" + "movl $0x12, %%ecx\n" + ".byte 0x0f, 0x32\n" + "movl %%eax, %%ebx\n" + "movl $0x13, %%ecx\n" + ".byte 0x0f, 0x32\n" + "popl %%edx\n" + : "=b" (*counter0), "=a" (*counter1) + : "1" (0), "c" (0x11) + ); +} + +static inline void +l4_i586_select_event(int event0, int event1) +{ + asm volatile(".byte 0x0f, 0x30\n" + : + : + "a" (event0 + (event1 << 16)), + "d" (0), + "c" (0x11) + ); +}; + +#define P5_RD_MISS 0x003 /* 000011B */ +#define P5_WR_MISS 0x008 /* 000100B */ +#define P5_RW_MISS 0x029 /* 101001B */ +#define P5_EX_MISS 0x00e /* 001110B */ + +#define P5_D_WBACK 0x006 /* 000110B */ + +#define P5_RW_TLB 0x002 /* 00010B */ +#define P5_EX_TLB 0x00d /* 01101B */ + +#define P5_A_STALL 0x01f /* 11111B */ +#define P5_W_STALL 0x019 /* 11001B */ +#define P5_R_STALL 0x01a /* 11010B */ +#define P5_X_STALL 0x01b /* 11011B */ + +#define P5_AGI_STALL 0x01f /* 11111B */ + +#define P5_PIPLINE_FLUSH 0x015 /* 10101B */ + +#define P5_NON_CACHE_RD 0x01e /* 11110B */ +#define P5_NCACHE_REFS 0x01e /* 11110B */ +#define P5_LOCKED_BUS 0x01c /* 11100B */ + +#define P5_MEM2PIPE 0x009 /* 01001B */ +#define P5_BANK_CONF 0x00a /* 01010B */ + + +#define P5_INSTRS_EX 0x016 /* 10110B */ +#define P5_INSTRS_EX_V 0x017 /* 10111B */ + + +#define P5_CNT_NOTHING (0x00 << 6) /* 00B << 6 */ +#define P5_CNT_EVENT_PL0 (0x01 << 6) /* 01B << 6 */ +#define P5_CNT_EVENT_PL3 (0x02 << 6) /* 10B << 6 */ +#define P5_CNT_EVENT (0x03 << 6) /* 11B << 6 */ +#define P5_CNT_CLOCKS_PL0 (0x05 << 6) /* 101B << 6 */ +#define P5_CNT_CLOCKS_PL3 (0x06 << 6) /* 110B << 6 */ +#define P5_CNT_CLOCKS (0x07 << 6) /* 111B << 6 */ + + +#else +#if defined CPU_P6 +/* PPro/PII/PIII section */ + +/*- + * Copyright (c) 1997 The President and Fellows of Harvard College. + * All rights reserved. + * Copyright (c) 1997 Aaron B. Brown. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Harvard University + * and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY HARVARD AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL HARVARD UNIVERSITY OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/********************************************************************* + ** Symbolic names for counter numbers (used in select_p6counter()) ** + ********************************************************************* + * + * These correspond in order to the Pentium Pro counters. Add new counters at + * the end. These agree with the mneumonics in the Pentium Pro Family + * Developer's Manual, vol 3. + * + * Those events marked with a $ require a MESI unit field; those marked with + * a @ require a self/any unit field. Those marked with a 0 are only supported + * in counter 0; those marked with 1 are only supported in counter 1. + */ + +/* Data cache unit */ +#define P6_DATA_MEM_REFS 0x43 /* total memory refs */ +#define P6_DCU_LINES_IN 0x45 /* all lines allocated in cache unit */ +#define P6_DCU_M_LINES_IN 0x46 /* M lines allocated in cache unit */ +#define P6_DCU_M_LINES_OUT 0x47 /* M lines evicted from cache */ +#define P6_DCU_MISS_OUTSTANDING 0x48 /* #cycles a miss is outstanding */ + +/* Instruction fetch unit */ +#define P6_IFU_IFETCH 0x80 /* instruction fetches */ +#define P6_IFU_IFETCH_MISS 0x81 /* instruction fetch misses */ +#define P6_ITLB_MISS 0x85 /* ITLB misses */ +#define P6_IFU_MEM_STALL 0x86 /* number of cycles IFU is stalled */ +#define P6_ILD_STALL 0x87 /* #stalls in instr length decode */ + +/* L2 Cache */ +#define P6_L2_IFETCH 0x28 /* ($) l2 ifetches */ +#define P6_L2_LD 0x29 /* ($) l2 data loads */ +#define P6_L2_ST 0x2a /* ($) l2 data stores */ +#define P6_L2_LINES_IN 0x24 /* lines allocated in l2 */ +#define P6_L2_LINES_OUT 0x26 /* lines removed from l2 */ +#define P6_L2_M_LINES_INM 0x25 /* modified lines allocated in L2 */ +#define P6_L2_M_LINES_OUTM 0x27 /* modified lines removed from L2 */ +#define P6_L2_RQSTS 0x2e /* ($) number of l2 requests */ +#define P6_L2_ADS 0x21 /* number of l2 addr strobes */ +#define P6_L2_DBUS_BUSY 0x22 /* number of data bus busy cycles */ +#define P6_L2_DBUS_BUSY_RD 0x23 /* #bus cycles xferring l2->cpu */ + +/* External bus logic */ +#define P6_BUS_DRDY_CLOCKS 0x62 /* (@) #clocks DRDY is asserted */ +#define P6_BUS_LOCK_CLOCKS 0x63 /* (@) #clocks LOCK is asserted */ +#define P6_BUS_REQ_OUTSTANDING 0x60 /* #bus requests outstanding */ +#define P6_BUS_TRAN_BRD 0x65 /* (@) bus burst read txns */ +#define P6_BUS_TRAN_RFO 0x66 /* (@) bus read for ownership txns */ +#define P6_BUS_TRAN_WB 0x67 /* (@) bus writeback txns */ +#define P6_BUS_TRAN_IFETCH 0x68 /* (@) bus instr fetch txns */ +#define P6_BUS_TRAN_INVAL 0x69 /* (@) bus invalidate txns */ +#define P6_BUS_TRAN_PWR 0x6a /* (@) bus partial write txns */ +#define P6_BUS_TRANS_P 0x6b /* (@) bus partial txns */ +#define P6_BUS_TRANS_IO 0x6c /* (@) bus I/O txns */ +#define P6_BUS_TRAN_DEF 0x6d /* (@) bus deferred txns */ +#define P6_BUS_TRAN_BURST 0x6e /* (@) bus burst txns */ +#define P6_BUS_TRAN_ANY 0x70 /* (@) total bus txns */ +#define P6_BUS_TRAN_MEM 0x6f /* (@) total memory txns */ +#define P6_BUS_DATA_RCV 0x64 /* #busclocks CPU is receiving data */ +#define P6_BUS_BNR_DRV 0x61 /* #busclocks CPU is driving BNR pin */ +#define P6_BUS_HIT_DRV 0x7a /* #busclocks CPU is driving HIT pin */ +#define P6_BUS_HITM_DRV 0x7b /* #busclocks CPU is driving HITM pin*/ +#define P6_BUS_SNOOP_STALL 0x7e /* #clkcycles bus is snoop-stalled */ + +/* FPU */ +#define P6_FLOPS 0xc1 /* (0) number of FP ops retired */ +#define P6_FP_COMP_OPS 0x10 /* (0) computational FPOPS exec'd */ +#define P6_FP_ASSIST 0x11 /* (1) FP excep's handled in ucode */ +#define P6_MUL 0x12 /* (1) number of FP multiplies */ +#define P6_DIV 0x13 /* (1) number of FP divides */ +#define P6_CYCLES_DIV_BUSY 0x14 /* (0) number of cycles divider busy */ + +/* Memory ordering */ +#define P6_LD_BLOCKS 0x03 /* number of store buffer blocks */ +#define P6_SB_DRAINS 0x04 /* # of store buffer drain cycles */ +#define P6_MISALING_MEM_REF 0x05 /* # misaligned data memory refs */ + +/* Instruction decoding and retirement */ +#define P6_INST_RETIRED 0xc0 /* number of instrs retired */ +#define P6_UOPS_RETIRED 0xc2 /* number of micro-ops retired */ +#define P6_INST_DECODER 0xd0 /* number of instructions decoded */ + +/* Interrupts */ +#define P6_HW_INT_RX 0xc8 /* number of hardware interrupts */ +#define P6_CYCLES_INT_MASKED 0xc6 /* number of cycles hardints masked */ +#define P6_CYCLES_INT_PENDING_AND_MASKED 0xc7 /* #cycles masked but pending */ + +/* Branches */ +#define P6_BR_INST_RETIRED 0xc4 /* number of branch instrs retired */ +#define P6_BR_MISS_PRED_RETIRED 0xc5 /* number of mispred'd brs retired */ +#define P6_BR_TAKEN_RETIRED 0xc9 /* number of taken branches retired */ +#define P6_BR_MISS_PRED_TAKEN_RET 0xca /* #taken mispredictions br's retired*/ +#define P6_BR_INST_DECODED 0xe0 /* number of branch instrs decoded */ +#define P6_BTB_MISSES 0xe2 /* # of branches that missed in BTB */ +#define P6_BR_BOGUS 0xe4 /* number of bogus branches */ +#define P6_BACLEARS 0xe6 /* # times BACLEAR is asserted */ + +/* Stalls */ +#define P6_RESOURCE_STALLS 0xa2 /* # resource-related stall cycles */ +#define P6_PARTIAL_RAT_STALLS 0xd2 /* # cycles/events for partial stalls*/ + +/* Segment register loads */ +#define P6_SEGMENT_REG_LOADS 0x06 /* number of segment register loads */ + +/* Clocks */ +#define P6_CPU_CLK_UNHALTED 0x79 /* #clocks CPU is not halted */ + +/* Unit field tags */ +#define P6_UNIT_M 0x0800 +#define P6_UNIT_E 0x0400 +#define P6_UNIT_S 0x0200 +#define P6_UNIT_I 0x0100 +#define P6_UNIT_MESI 0x0f00 + +#define P6_UNIT_SELF 0x0000 +#define P6_UNIT_ANY 0x2000 + +/**************************************************************************** + ** Flag bit definitions (used for the 'flag' field in select_p6counter()) ** + **************************************************************************** + * + * The driver accepts fully-formed counter specifications from user-level. + * The following flags are mneumonics for the bits that get set in the + * PerfEvtSel0 and PerfEvtSel1 MSR's + * + */ +#define P6CNT_U 0x010000 /* Monitor user-level events */ +#define P6CNT_K 0x020000 /* Monitor kernel-level events */ +#define P6CNT_E 0x040000 /* Edge detect: count state transitions */ +#define P6CNT_PC 0x080000 /* Pin control: ?? */ +#define P6CNT_IE 0x100000 /* Int enable: enable interrupt on overflow */ +#define P6CNT_F 0x200000 /* Freeze counter (handled in software) */ +#define P6CNT_EN 0x400000 /* enable counters (in PerfEvtSel0) */ +#define P6CNT_IV 0x800000 /* Invert counter mask comparison result */ + +/***************************** + ** Miscellaneous constants ** + ***************************** + * + * Number of Pentium Pro programable hardware counters. + */ +#define NUM_P6HWC 2 + +/***************************************************************************** +* +* End of Copyright by Harvard College +* +*****************************************************************************/ + + +#define MSR_P6_EVNTSEL0 0x186 +#define MSR_P6_EVNTSEL1 0x187 +#define MSR_P6_PERFCTR0 0xc1 +#define MSR_P6_PERFCTR1 0xc2 + +/* P6-specific Makros to manipulate and read counters */ + +/* Read the 40 bit performance monitoring counter. This requires + the PCE-flag in CR4 to be set. Otherwise GP0 is raised. Works only + at P6. + */ +#define l4_i686_rdpmc(cntr, res_p) \ + __asm __volatile( \ + "movl %2, %%ecx # put counter number in \n\ + .byte 0xf; .byte 0x33 # RDPMC instruction \n\ + movl %%edx, %1 # High order 32 bits \n\ + movl %%eax, %0 # Low order 32 bits" \ + : "=g" (*(int *)(res_p)), "=g" (*(((int *)res_p)+1)) \ + : "g" (cntr) \ + : "ecx", "eax", "edx") + +static inline l4_uint32_t l4_i686_rdpmc_32(int cntr){ + l4_uint32_t x; + + __asm__ __volatile__( + ".byte 0xf; .byte 0x33 # RDPMC instruction" + : "=a" (x) + : "c" (cntr) + : "ecx", "eax", "edx"); + return x; +} + +static inline void l4_i686_select_perfctr_event(int counter, + unsigned long long val){ + l4_i586_wrmsr(MSR_P6_EVNTSEL0+counter, &val); +} + +static inline void l4_i686_select_perfctr0_event(long long *val){ + asm volatile( + "movl $MSR_P6_EVNTSEL0, %%ecx\n" + "movl (%%ebx), %%eax\n" + "movl 4(%%ebx), %%edx\n" + //".byte 0xcc, 0xeb, 0x01, 0x21\n" + ".byte 0x0f, 0x30\n" // wrmsr + //".byte 0xcc, 0xeb, 0x01, 0x21\n" + : /* no output */ + : "b" (val) + : "ax", "cx", "dx", "bx" + ); + +} + +/* end of P6 section */ +#else + +#define K7CNT_U 0x010000 /* Monitor user-level events */ +#define K7CNT_K 0x020000 /* Monitor kernel-level events */ +#define K7CNT_E 0x040000 /* Edge detect: count state transitions */ +#define K7CNT_PC 0x080000 /* Pin control: ?? */ +#define K7CNT_IE 0x100000 /* Int enable: enable interrupt on overflow */ +#define K7CNT_F 0x200000 /* Freeze counter (handled in software) */ +#define K7CNT_EN 0x400000 /* enable counters (in PerfEvtSel0) */ +#define K7CNT_IV 0x800000 /* Invert counter mask comparison result */ + +#define MSR_K7_EVNTSEL0 0xC0010000 +#define MSR_K7_EVNTSEL1 0xC0010001 +#define MSR_K7_EVNTSEL2 0xC0010002 +#define MSR_K7_EVNTSEL3 0xC0010003 +#define MSR_K7_PERFCTR0 0xC0010004 +#define MSR_K7_PERFCTR1 0xC0010005 +#define MSR_K7_PERFCTR2 0xC0010006 +#define MSR_K7_PERFCTR3 0xC0010007 + +#endif + +#endif + +/* end of P5/P6/K7 section*/ +#endif + +/* end of not only lib-prototypes section */ +#endif + +EXTERN_C_END + +#endif diff --git a/l4/pkg/l4util/include/ARCH-x86/port_io.h b/l4/pkg/l4util/include/ARCH-x86/port_io.h new file mode 100644 index 00000000..6b86fd6d --- /dev/null +++ b/l4/pkg/l4util/include/ARCH-x86/port_io.h @@ -0,0 +1,274 @@ +/*****************************************************************************/ +/** + * \file + * \brief x86 port I/O + * + * \date 06/2003 + * \author Frank Mehnert + */ +/*****************************************************************************/ + +/* + * (c) 2003-2009 Author(s) + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ + +#ifndef _L4UTIL_PORT_IO_H +#define _L4UTIL_PORT_IO_H + +/** + * \defgroup l4util_portio IA32 Port I/O API + * \ingroup l4util_api + */ + +/* L4 includes */ +#include +#include +#include + +/***************************************************************************** + *** Prototypes + *****************************************************************************/ + +EXTERN_C_BEGIN +/** + * \addtogroup l4util_portio + */ +/*@{*/ +/** + * \brief Read byte from I/O port + * + * \param port I/O port address + * \return value + */ +L4_INLINE l4_uint8_t +l4util_in8(l4_uint16_t port); + +/** + * \brief Read 16-bit-value from I/O port + * + * \param port I/O port address + * \return value + */ +L4_INLINE l4_uint16_t +l4util_in16(l4_uint16_t port); + +/** + * \brief Read 32-bit-value from I/O port + * + * \param port I/O port address + * \return value + */ +L4_INLINE l4_uint32_t +l4util_in32(l4_uint16_t port); + +/** + * \brief Read a block of 8-bit-values from I/O ports + * + * \param port I/O port address + * \param addr address of buffer + * \param count number of I/O operations + */ +L4_INLINE void +l4util_ins8(l4_uint16_t port, l4_umword_t addr, l4_umword_t count); + +/** + * \brief Read a block of 16-bit-values from I/O ports + * + * \param port I/O port address + * \param addr address of buffer + * \param count number of I/O operations + */ +L4_INLINE void +l4util_ins16(l4_uint16_t port, l4_umword_t addr, l4_umword_t count); + +/** + * \brief Read a block of 32-bit-values from I/O ports + * + * \param port I/O port address + * \param addr address of buffer + * \param count number of I/O operations + */ +L4_INLINE void +l4util_ins32(l4_uint16_t port, l4_umword_t addr, l4_umword_t count); + +/** + * \brief Write byte to I/O port + * + * \param port I/O port address + * \param value value to write + */ +L4_INLINE void +l4util_out8(l4_uint8_t value, l4_uint16_t port); + +/** + * \brief Write 16-bit-value to I/O port + * \ingroup port_io + * + * \param port I/O port address + * \param value value to write + */ +L4_INLINE void +l4util_out16(l4_uint16_t value, l4_uint16_t port); + +/** + * \brief Write 32-bit-value to I/O port + * + * \param port I/O port address + * \param value value to write + */ +L4_INLINE void +l4util_out32(l4_uint32_t value, l4_uint16_t port); + +/** + * \brief Write a block of bytes to I/O port + * + * \param port I/O port address + * \param addr address of buffer + * \param count number of I/O operations + */ +L4_INLINE void +l4util_outs8(l4_uint16_t port, l4_umword_t addr, l4_umword_t count); + +/** + * \brief Write a block of 16-bit-values to I/O port + * \ingroup port_io + * + * \param port I/O port address + * \param addr address of buffer + * \param count number of I/O operations + */ +L4_INLINE void +l4util_outs16(l4_uint16_t port, l4_umword_t addr, l4_umword_t count); + +/** + * \brief Write block of 32-bit-values to I/O port + * + * \param port I/O port address + * \param addr address of buffer + * \param count number of I/O operations + */ +L4_INLINE void +l4util_outs32(l4_uint16_t port, l4_umword_t addr, l4_umword_t count); + +/** + * \brief delay I/O port access by writing to port 0x80 + */ +L4_INLINE void +l4util_iodelay(void); + +/*@}*/ + +EXTERN_C_END + + +/***************************************************************************** + *** Implementation + *****************************************************************************/ + +L4_INLINE l4_uint8_t +l4util_in8(l4_uint16_t port) +{ + l4_uint8_t value; + asm volatile ("inb %w1, %b0" : "=a" (value) : "Nd" (port)); + return value; +} + +L4_INLINE l4_uint16_t +l4util_in16(l4_uint16_t port) +{ + l4_uint16_t value; + asm volatile ("inw %w1, %w0" : "=a" (value) : "Nd" (port)); + return value; +} + +L4_INLINE l4_uint32_t +l4util_in32(l4_uint16_t port) +{ + l4_uint32_t value; + asm volatile ("inl %w1, %0" : "=a" (value) : "Nd" (port)); + return value; +} + +L4_INLINE void +l4util_ins8(l4_uint16_t port, l4_umword_t addr, l4_umword_t count) +{ + l4_umword_t dummy1, dummy2; + asm volatile ("rep insb" : "=D"(dummy1), "=c"(dummy2) + : "d" (port), "D" (addr), "c"(count) + : "memory"); +} + +L4_INLINE void +l4util_ins16(l4_uint16_t port, l4_umword_t addr, l4_umword_t count) +{ + l4_umword_t dummy1, dummy2; + asm volatile ("rep insw" : "=D"(dummy1), "=c"(dummy2) + : "d" (port), "D" (addr), "c"(count) + : "memory"); +} + +L4_INLINE void +l4util_ins32(l4_uint16_t port, l4_umword_t addr, l4_umword_t count) +{ + l4_umword_t dummy1, dummy2; + asm volatile ("rep insl" : "=D"(dummy1), "=c"(dummy2) + : "d" (port), "D" (addr), "c"(count) + : "memory"); +} + +L4_INLINE void +l4util_out8(l4_uint8_t value, l4_uint16_t port) +{ + asm volatile ("outb %b0, %w1" : : "a" (value), "Nd" (port)); +} + +L4_INLINE void +l4util_out16(l4_uint16_t value, l4_uint16_t port) +{ + asm volatile ("outw %w0, %w1" : : "a" (value), "Nd" (port)); +} + +L4_INLINE void +l4util_out32(l4_uint32_t value, l4_uint16_t port) +{ + asm volatile ("outl %0, %w1" : : "a" (value), "Nd" (port)); +} + +L4_INLINE void +l4util_outs8(l4_uint16_t port, l4_umword_t addr, l4_umword_t count) +{ + l4_umword_t dummy1, dummy2; + asm volatile ("rep outsb" : "=S"(dummy1), "=c"(dummy2) + : "d" (port), "S" (addr), "c"(count) + : "memory"); +} + +L4_INLINE void +l4util_outs16(l4_uint16_t port, l4_umword_t addr, l4_umword_t count) +{ + l4_umword_t dummy1, dummy2; + asm volatile ("rep outsw" : "=S"(dummy1), "=c"(dummy2) + : "d" (port), "S" (addr), "c"(count) + : "memory"); +} + +L4_INLINE void +l4util_outs32(l4_uint16_t port, l4_umword_t addr, l4_umword_t count) +{ + l4_umword_t dummy1, dummy2; + asm volatile ("rep outsl" : "=S"(dummy1), "=c"(dummy2) + : "d" (port), "S" (addr), "c"(count) + : "memory"); +} + +L4_INLINE void +l4util_iodelay(void) +{ + asm volatile ("outb %al,$0x80"); +} + +#endif diff --git a/l4/pkg/l4util/include/ARCH-x86/rdtsc.h b/l4/pkg/l4util/include/ARCH-x86/rdtsc.h new file mode 100644 index 00000000..18c5bfd4 --- /dev/null +++ b/l4/pkg/l4util/include/ARCH-x86/rdtsc.h @@ -0,0 +1,365 @@ +/** + * \file + * \brief time stamp counter related functions + * + * \author Frank Mehnert + * \ingroup l4util_tsc + */ + +/* + * (c) 2003-2009 Adam Lackorzynski , + * Alexander Warg , + * Frank Mehnert , + * Jork Löser , + * Martin Pohlack + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ + +#ifndef __l4_rdtsc_h +#define __l4_rdtsc_h + +/** + * \defgroup l4util_tsc Timestamp Counter + * \ingroup l4util_api + */ + +#include +#include +#include + +EXTERN_C_BEGIN + +/* interface */ +/** + * \addtogroup l4util_tsc + */ +/*@{*/ + +#define L4_TSC_INIT_AUTO 0 ///< Automatic init +#define L4_TSC_INIT_KERNEL 1 ///< Initialized by kernel +#define L4_TSC_INIT_CALIBRATE 2 ///< Initialized by user-level + +extern l4_uint32_t l4_scaler_tsc_to_ns; +extern l4_uint32_t l4_scaler_tsc_to_us; +extern l4_uint32_t l4_scaler_ns_to_tsc; +extern l4_uint32_t l4_scaler_tsc_linux; + +/** + * \brief Read current value of CPU-internal time stamp counter. + * \return 64-bit time stamp + */ +L4_INLINE l4_cpu_time_t +l4_rdtsc (void); + +/** + * \brief Read the lest significant 32 bit of the TSC. + * + * Useful for smaller differences, needs less cycles. + */ +L4_INLINE +l4_uint32_t l4_rdtsc_32(void); + +/** + * \brief Return current value of CPU-internal performance measurement counter. + * \param nr Number of counter (0 or 1) + * \return 64-bit PMC */ +L4_INLINE l4_cpu_time_t +l4_rdpmc (int nr); + +/** + * \brief Return the least significant 32 bit of a performance counter. + * + * Useful for smaller differences, needs less cycles. + */ +L4_INLINE +l4_uint32_t l4_rdpmc_32(int nr); + +/** Convert time stamp to ns value. + * \param tsc time value in CPU ticks + * \return time value in ns + */ +L4_INLINE l4_uint64_t +l4_tsc_to_ns (l4_cpu_time_t tsc); + +/** Convert time stamp into micro seconds value. + * \param tsc time value in CPU ticks + * \return time value in micro seconds + */ +L4_INLINE l4_uint64_t +l4_tsc_to_us (l4_cpu_time_t tsc); + +/** Convert time stamp to s.ns value. + * \param tsc time value in CPU ticks + * \retval s seconds + * \retval ns nano seconds + */ +L4_INLINE void +l4_tsc_to_s_and_ns (l4_cpu_time_t tsc, l4_uint32_t *s, l4_uint32_t *ns); + +/** + * \brief Convert nano seconds into CPU ticks. + * \param ns nano seconds + * \return CPU ticks + */ +L4_INLINE l4_cpu_time_t +l4_ns_to_tsc (l4_uint64_t ns); + +/** + * \brief Wait busy for a small amount of time. + * \param ns nano seconds to wait + * \attention Not intendet for any use! + */ +L4_INLINE void +l4_busy_wait_ns (l4_uint64_t ns); + +/** + * \brief Wait busy for a small amount of time. + * \param us micro seconds to wait + * \attention Not intendet for any use! + */ +L4_INLINE void +l4_busy_wait_us (l4_uint64_t us); + +EXTERN_C_BEGIN + +/** + * \brief Calibrate scalers for time stamp calculations. + * + * Determine some scalers to be able to convert between real time and CPU + * ticks. This test uses channel 0 of the PIT (i8254) or the kernel KIP, + * depending on availability. + * Just calls l4_tsc_init(L4_TSC_INIT_AUTO). + */ +L4_INLINE l4_uint32_t +l4_calibrate_tsc (l4_kernel_info_t *kip); + +/** + * \brief Initialitze scaler for TSC calicaltions. + * + * Initialize the scalers needed by l4_tsc_to_ns()/l4_ns_to_tsc() and so on. + * Current versions of Fiasco export these scalers from kernel into userland. + * The programmer may decide whether he allows to use these scalers or if an + * calibration should be performed. + * \param constraint programmers constraint: + * - #L4_TSC_INIT_AUTO if the kernel exports the scalers + * then use them. If not, perform calibration using + * channel 0 of the PIT (i8254). The latter case may + * lead into short (unpredictable) periods where + * interrupts are disabled. + * - #L4_TSC_INIT_KERNEL depend on retrieving the scalers + * from kernel. If the scalers are not available, + * return 0. + * - #L4_TSC_INIT_CALIBRATE Ignore possible scalers + * exported by the scaler, instead insist on + * calibration using the PIT. + * \param kip KIP pointer + * \return 0 on error (no scalers exported by kernel, calibrating failed ...) + * otherwise returns (2^32 / (tsc per µsec)). This value has the + * same semantics as the value returned by the calibrate_delay_loop() + * function of the Linux kernel. + */ +L4_CV l4_uint32_t +l4_tsc_init (int constraint, l4_kernel_info_t *kip); + +/** + * \brief Get CPU frequency in Hz + * \return frequency in Hz + */ +L4_CV l4_uint32_t +l4_get_hz (void); + +/*@}*/ + +EXTERN_C_END + +/* implementaion */ + +L4_INLINE l4_uint32_t +l4_calibrate_tsc (l4_kernel_info_t *kip) +{ + return l4_tsc_init(L4_TSC_INIT_AUTO, kip); +} + +L4_INLINE l4_cpu_time_t +l4_rdtsc (void) +{ + l4_cpu_time_t v; + + __asm__ __volatile__ + (" \n\t" + ".byte 0x0f, 0x31 \n\t" + /*"rdtsc\n\t"*/ + : + "=A" (v) + : /* no inputs */ + ); + + return v; +} + +/* the same, but only 32 bit. Useful for smaller differences, + needs less cycles. */ +L4_INLINE +l4_uint32_t l4_rdtsc_32(void) +{ + l4_uint32_t x; + + __asm__ __volatile__ ( + ".byte 0x0f, 0x31\n\t" // rdtsc + : "=a" (x) + : + : "edx"); + + return x; +} + +L4_INLINE l4_cpu_time_t +l4_rdpmc (int nr) +{ + l4_cpu_time_t v; + + __asm__ __volatile__ ( + "rdpmc \n\t" + : + "=A" (v) + : "c" (nr) + ); + + return v; +} + +/* the same, but only 32 bit. Useful for smaller differences, + needs less cycles. */ +L4_INLINE +l4_uint32_t l4_rdpmc_32(int nr) +{ + l4_uint32_t x; + + __asm__ __volatile__ ( + "rdpmc \n\t" + : "=a" (x) + : "c" (nr) + : "edx"); + + return x; +} + +L4_INLINE l4_uint64_t +l4_tsc_to_ns (l4_cpu_time_t tsc) +{ + l4_uint32_t dummy; + l4_uint64_t ns; + __asm__ + (" \n\t" + "movl %%edx, %%ecx \n\t" + "mull %3 \n\t" + "movl %%ecx, %%eax \n\t" + "movl %%edx, %%ecx \n\t" + "mull %3 \n\t" + "addl %%ecx, %%eax \n\t" + "adcl $0, %%edx \n\t" + "shld $5, %%eax, %%edx \n\t" + "shll $5, %%eax \n\t" + :"=A" (ns), + "=&c" (dummy) + :"0" (tsc), + "g" (l4_scaler_tsc_to_ns) + ); + return ns; +} + +L4_INLINE l4_uint64_t +l4_tsc_to_us (l4_cpu_time_t tsc) +{ + l4_uint32_t dummy; + l4_uint64_t us; + __asm__ + (" \n\t" + "movl %%edx, %%ecx \n\t" + "mull %3 \n\t" + "movl %%ecx, %%eax \n\t" + "movl %%edx, %%ecx \n\t" + "mull %3 \n\t" + "addl %%ecx, %%eax \n\t" + "adcl $0, %%edx \n\t" + :"=A" (us), + "=&c" (dummy) + :"0" (tsc), + "g" (l4_scaler_tsc_to_us) + ); + return us; +} + +L4_INLINE void +l4_tsc_to_s_and_ns (l4_cpu_time_t tsc, l4_uint32_t *s, l4_uint32_t *ns) +{ + l4_uint32_t dummy; + __asm__ + (" \n\t" + "movl %%edx, %%ecx \n\t" + "mull %4 \n\t" + "movl %%ecx, %%eax \n\t" + "movl %%edx, %%ecx \n\t" + "mull %4 \n\t" + "addl %%ecx, %%eax \n\t" + "adcl $0, %%edx \n\t" + "movl $1000000000, %%ecx \n\t" + "shld $5, %%eax, %%edx \n\t" + "shll $5, %%eax \n\t" + "divl %%ecx \n\t" + :"=a" (*s), "=d" (*ns), "=&c" (dummy) + : "A" (tsc), "g" (l4_scaler_tsc_to_ns) + ); +} + +L4_INLINE l4_cpu_time_t +l4_ns_to_tsc (l4_uint64_t ns) +{ + l4_uint32_t dummy; + l4_cpu_time_t tsc; + __asm__ + (" \n\t" + "movl %%edx, %%ecx \n\t" + "mull %3 \n\t" + "movl %%ecx, %%eax \n\t" + "movl %%edx, %%ecx \n\t" + "mull %3 \n\t" + "addl %%ecx, %%eax \n\t" + "adcl $0, %%edx \n\t" + "shld $5, %%eax, %%edx \n\t" + "shll $5, %%eax \n\t" + :"=A" (tsc), + "=&c" (dummy) + :"0" (ns), + "g" (l4_scaler_ns_to_tsc) + ); + return tsc; +} + +L4_INLINE void +l4_busy_wait_ns (l4_uint64_t ns) +{ + l4_cpu_time_t stop = l4_rdtsc(); + stop += l4_ns_to_tsc(ns); + + while (l4_rdtsc() < stop) + ; +} + +L4_INLINE void +l4_busy_wait_us (l4_uint64_t us) +{ + l4_cpu_time_t stop = l4_rdtsc (); + stop += l4_ns_to_tsc(us*1000ULL); + + while (l4_rdtsc() < stop) + ; +} + +EXTERN_C_END + +#endif /* __l4_rdtsc_h */ + diff --git a/l4/pkg/l4util/include/ARCH-x86/spin.h b/l4/pkg/l4util/include/ARCH-x86/spin.h new file mode 100644 index 00000000..b9db6742 --- /dev/null +++ b/l4/pkg/l4util/include/ARCH-x86/spin.h @@ -0,0 +1,41 @@ +/** + * \file + * \brief Spinning for x86 + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Frank Mehnert + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ +#ifndef __l4util_spin_h +#define __l4util_spin_h + +#include + +EXTERN_C_BEGIN + +L4_CV void l4_spin(int x,int y); +L4_CV void l4_spin_vga(int x,int y); +L4_CV void l4_spin_n_text(int x, int y, int len, const char*s); +L4_CV void l4_spin_n_text_vga(int x, int y, int len, const char*s); + +/**************************************************************************** +* * +* spin_text() - spinning wheel at the hercules screen. The given text * +* must be a text constant, no variables or arrays. Its * +* size is determined with the sizeof operator, it's much * +* faster than the strlen function. * +* spin_text_vga() - same for vga. * +* * +****************************************************************************/ +#define l4_spin_text(x, y, text) \ + l4_spin_n_text((x), (y), sizeof(text)-1, "" text) +#define l4_spin_text_vga(x, y, text) \ + l4_spin_n_text_vga((x), (y), sizeof(text)-1, "" text) + +EXTERN_C_END + +#endif diff --git a/l4/pkg/l4util/include/ARCH-x86/stack_impl.h b/l4/pkg/l4util/include/ARCH-x86/stack_impl.h new file mode 100644 index 00000000..18fc3d4d --- /dev/null +++ b/l4/pkg/l4util/include/ARCH-x86/stack_impl.h @@ -0,0 +1,31 @@ +/** + * \file + * \brief Stack utilities for x86 + */ +/* + * (c) 2008-2009 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ +#ifndef __L4UTIL__INCLUDE__ARCH_X86__STACK_IMPL_H__ +#define __L4UTIL__INCLUDE__ARCH_X86__STACK_IMPL_H__ + +#ifndef _L4UTIL_STACK_H +#error Do not include stack_impl.h directly, use stack.h instead +#endif + +EXTERN_C_BEGIN + +L4_INLINE l4_addr_t l4util_stack_get_sp(void) +{ + l4_addr_t esp; + + asm("movl %%esp, %0\n\t" : "=r" (esp) : ); + return esp; +} + +EXTERN_C_END + +#endif /* ! __L4UTIL__INCLUDE__ARCH_ARM__STACK_IMPL_H__ */ diff --git a/l4/pkg/l4util/include/ARCH-x86/util.h b/l4/pkg/l4util/include/ARCH-x86/util.h new file mode 100644 index 00000000..e6be4766 --- /dev/null +++ b/l4/pkg/l4util/include/ARCH-x86/util.h @@ -0,0 +1,90 @@ +/** + * \file + * \brief Utilities for x86 + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg , + * Frank Mehnert , + * Jork Löser + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ +#ifndef __UTIL_H +#define __UTIL_H + +#include +#include +#include + +EXTERN_C_BEGIN + +/** Calculate l4 timeouts + * \param mus time in microseconds. Special cases: + * - 0 - > timeout 0 + * - ~0U -> timeout NEVER + * \return the corresponding l4_timeout value + */ +L4_CV l4_timeout_s l4util_micros2l4to(unsigned int mus) L4_NOTHROW; + +/** Suspend thread for a period of milliseconds */ +L4_CV void l4_sleep(int ms) L4_NOTHROW; + +/* Suspend thread for a period of micro seconds. + * WARNING: This function is mostly bogus since the timer resolution of + * current L4 implementations is about 1ms! */ +L4_CV void l4_usleep(int us) L4_NOTHROW; + +/** + * \brief Go sleep and never wake up. + * \ingroup l4util_api + * + */ +L4_INLINE void l4_sleep_forever(void) L4_NOTHROW __attribute__((noreturn)); + +L4_INLINE void +l4_sleep_forever(void) L4_NOTHROW +{ + for (;;) + l4_ipc_sleep(L4_IPC_NEVER); +} + +/** Touch data areas to force mapping read-only */ +static inline void +l4_touch_ro(const void*addr, unsigned size) L4_NOTHROW +{ + const char *bptr, *eptr; + + bptr = (const char*)(((l4_addr_t)addr) & L4_PAGEMASK); + eptr = (const char*)(((l4_addr_t)addr+size-1) & L4_PAGEMASK); + for(;bptr<=eptr;bptr+=L4_PAGESIZE){ + asm volatile("or %0,%%eax \n" + : + : "m" (*(const unsigned*)bptr) + : "eax" ); + } +} + + +/** Touch data areas to force mapping read-write */ +static inline void +l4_touch_rw(const void*addr, unsigned size) L4_NOTHROW +{ + const char *bptr, *eptr; + + bptr = (const char*)(((l4_addr_t)addr) & L4_PAGEMASK); + eptr = (const char*)(((l4_addr_t)addr+size-1) & L4_PAGEMASK); + for(;bptr<=eptr;bptr+=L4_PAGESIZE){ + asm volatile("or $0,%0 \n" + : + : "m" (*(const unsigned*)bptr) + ); + } +} + +EXTERN_C_END + +#endif + diff --git a/l4/pkg/l4util/include/Makefile b/l4/pkg/l4util/include/Makefile new file mode 100644 index 00000000..6efe95fc --- /dev/null +++ b/l4/pkg/l4util/include/Makefile @@ -0,0 +1,6 @@ +PKGDIR = .. +L4DIR ?= $(PKGDIR)/../.. + +PKGNAME = util + +include $(L4DIR)/mk/include.mk diff --git a/l4/pkg/l4util/include/alloc.h b/l4/pkg/l4util/include/alloc.h new file mode 100644 index 00000000..dd7a8222 --- /dev/null +++ b/l4/pkg/l4util/include/alloc.h @@ -0,0 +1,38 @@ +/*! + * \file + * \brief Allocator using a bit-array + * + * \date 09/14/2004 + * \author Jork Loeser + * + */ +/* + * (c) 2004-2009 Author(s) + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ +#ifndef __UTIL_INCLUDE_ALLOC_H_ +#define __UTIL_INCLUDE_ALLOC_H_ +#include +#include +#include + +EXTERN_C_BEGIN + +typedef struct { + int base, count, next_elem; + l4_umword_t *bits; +} l4util_alloc_t; + +#define L4UTIL_ALLOC_BITS_SIZE (8 * sizeof(l4_umword_t)) + +L4_CV l4util_alloc_t *l4util_alloc_init(int count, int base); +L4_CV int l4util_alloc_avail(l4util_alloc_t *alloc, int elem); +L4_CV int l4util_alloc_occupy(l4util_alloc_t *alloc, int elem); +L4_CV int l4util_alloc_alloc(l4util_alloc_t *alloc); +L4_CV int l4util_alloc_free(l4util_alloc_t *alloc, int elem); + +EXTERN_C_END +#endif diff --git a/l4/pkg/l4util/include/assert.h b/l4/pkg/l4util/include/assert.h new file mode 100644 index 00000000..4af0a010 --- /dev/null +++ b/l4/pkg/l4util/include/assert.h @@ -0,0 +1,107 @@ +/*****************************************************************************/ +/** + * \file + * \brief Some useful assert-style macros. + * + * \date 09/2009 + * \author Bjoern Doebel + */ +/* + * (c) 2009 Author(s) + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ + +/*****************************************************************************/ +#pragma once + +#ifndef DEBUG + +#define DO_NOTHING do {} while (0) +#define ASSERT_VALID(c) DO_NOTHING +#define ASSERT_EQUAL(a,b) DO_NOTHING +#define ASSERT_NOT_EQUAL(a,b) DO_NOTHING +#define ASSERT_LOWER_EQ(a,b) DO_NOTHING +#define ASSERT_GREATER_EQ(a,b) DO_NOTHING +#define ASSERT_BETWEEN(a,b,c) DO_NOTHING +#define ASSERT_IPC_OK(i) DO_NOTHING +#define ASSERT_OK(e) do { (void)e; } while (0) +#define ASSERT_NOT_NULL(p) DO_NOTHING +#ifndef assert +#define assert(cond) DO_NOTHING +#endif + +#else // DEBUG + +#include +#include +#include + +#define ASSERT_VALID(cap) \ + do { \ + if (l4_is_invalid_cap(cap)) { \ + printf("%s: Cap invalid.\n", __func__); \ + assert(l4_is_invalid_cap(cap)); \ + } \ + } while (0) + + +#define ASSERT_EQUAL(a, b) \ + do { \ + if ((a) != (b)) { \ + printf("%s:\n", __func__); \ + printf(" "#a" (%lx) != "#b" (%lx)\n", (unsigned long)(a), (unsigned long)(b)); \ + assert((a)==(b)); \ + } \ + } while (0) + + +#define ASSERT_NOT_EQUAL(a, b) \ + do { \ + if ((a) == (b)) { \ + printf("%s:\n", __func__); \ + printf(" "#a" (%lx) == "#b" (%lx)\n", (unsigned long)(a), (unsigned long)(b)); \ + assert((a)!=(b)); \ + } \ + } while (0) + + +#define ASSERT_LOWER_EQ(val, max) \ + do { \ + if ((val) > (max)) { \ + printf("%s:\n", __func__); \ + printf(" "#val" (%lx) > "#max" (%lx)\n", (unsigned long)(val), (unsigned long)(max)); \ + assert((val)<=(max)); \ + } \ + } while (0) + + +#define ASSERT_GREATER_EQ(val, min) \ + do { \ + if ((val) < (min)) { \ + printf("%s:\n", __func__); \ + printf(" "#val" (%lx) < "#min" (%lx)\n", (unsigned long)(val), (unsigned long)(min)); \ + assert((val)>=(min)); \ + } \ + } while (0) + + +#define ASSERT_BETWEEN(val, min, max) \ + ASSERT_LOWER_EQ((val), (max)); \ + ASSERT_GREATER_EQ((val), (min)); + + +#define ASSERT_IPC_OK(msgtag) \ + do { \ + if (l4_ipc_error((msgtag), l4_utcb())) { \ + printf("%s: IPC Error: %lx\n", __func__, l4_ipc_error(msgtag)); \ + assert(!l4_ipc_error(msgtag)); \ + } \ + } while (0) + +#define ASSERT_OK(val) ASSERT_EQUAL((val), 0) +#define ASSERT_NOT_NULL(ptr) ASSERT_NOT_EQUAL((ptr), NULL) + +#endif // DEBUG diff --git a/l4/pkg/l4util/include/atomic.h b/l4/pkg/l4util/include/atomic.h new file mode 100644 index 00000000..9fc05eff --- /dev/null +++ b/l4/pkg/l4util/include/atomic.h @@ -0,0 +1,559 @@ +/*****************************************************************************/ +/** + * \file + * \brief atomic operations header and generic implementations + * \ingroup l4util_atomic + * + * \date 10/20/2000 + * \author Lars Reuther , + * Jork Loeser */ +/* + * (c) 2000-2009 Author(s) + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ + +/*****************************************************************************/ +#ifndef __L4UTIL__INCLUDE__ATOMIC_H__ +#define __L4UTIL__INCLUDE__ATOMIC_H__ + +#include +#include + +/***************************************************************************** + *** Prototypes + *****************************************************************************/ + +EXTERN_C_BEGIN + +/** + * \defgroup l4util_atomic Atomic Instructions + * \ingroup l4util_api + */ + +/** + * \brief Atomic compare and exchange (64 bit version) + * \ingroup l4util_atomic + * + * \param dest destination operand + * \param cmp_val compare value + * \param new_val new value for dest + * + * \return 0 if comparison failed, 1 otherwise + * + * Compare the value in \em dest with \em cmp_val, if equal set \em dest to + * \em new_val + */ +L4_INLINE int +l4util_cmpxchg64(volatile l4_uint64_t * dest, + l4_uint64_t cmp_val, l4_uint64_t new_val); + +/** + * \brief Atomic compare and exchange (32 bit version) + * \ingroup l4util_atomic + * + * \param dest destination operand + * \param cmp_val compare value + * \param new_val new value for dest + * + * \return 0 if comparison failed, !=0 otherwise + * + * Compare the value in \em dest with \em cmp_val, if equal set \em dest to + * \em new_val + */ +L4_INLINE int +l4util_cmpxchg32(volatile l4_uint32_t * dest, + l4_uint32_t cmp_val, l4_uint32_t new_val); + +/** + * \brief Atomic compare and exchange (16 bit version) + * \ingroup l4util_atomic + * + * \param dest destination operand + * \param cmp_val compare value + * \param new_val new value for dest + * + * \return 0 if comparison failed, !=0 otherwise + * + * Compare the value in \em dest with \em cmp_val, if equal set \em dest to + * \em new_val + */ +L4_INLINE int +l4util_cmpxchg16(volatile l4_uint16_t * dest, + l4_uint16_t cmp_val, l4_uint16_t new_val); + +/** + * \brief Atomic compare and exchange (8 bit version) + * \ingroup l4util_atomic + * + * \param dest destination operand + * \param cmp_val compare value + * \param new_val new value for dest + * + * \return 0 if comparison failed, !=0 otherwise + * + * Compare the value in \em dest with \em cmp_val, if equal set \em dest to + * \em new_val + */ +L4_INLINE int +l4util_cmpxchg8(volatile l4_uint8_t * dest, + l4_uint8_t cmp_val, l4_uint8_t new_val); + +/** + * \brief Atomic compare and exchange (machine wide fields) + * \ingroup l4util_atomic + * + * \param dest destination operand + * \param cmp_val compare value + * \param new_val new value for dest + * + * \return 0 if comparison failed, 1 otherwise + * + * Compare the value in \em dest with \em cmp_val, if equal set \em dest to + * \em new_val + */ +L4_INLINE int +l4util_cmpxchg(volatile l4_umword_t * dest, + l4_umword_t cmp_val, l4_umword_t new_val); + +/** + * \brief Atomic exchange (32 bit version) + * \ingroup l4util_atomic + * + * \param dest destination operand + * \param val new value for dest + * + * \return old value at destination + */ +L4_INLINE l4_uint32_t +l4util_xchg32(volatile l4_uint32_t * dest, l4_uint32_t val); + +/** + * \brief Atomic exchange (16 bit version) + * \ingroup l4util_atomic + * + * \param dest destination operand + * \param val new value for dest + * + * \return old value at destination + */ +L4_INLINE l4_uint16_t +l4util_xchg16(volatile l4_uint16_t * dest, l4_uint16_t val); + +/** + * \brief Atomic exchange (8 bit version) + * \ingroup l4util_atomic + * + * \param dest destination operand + * \param val new value for dest + * + * \return old value at destination + */ +L4_INLINE l4_uint8_t +l4util_xchg8(volatile l4_uint8_t * dest, l4_uint8_t val); + +/** + * \brief Atomic exchange (machine wide fields) + * \ingroup l4util_atomic + * + * \param dest destination operand + * \param val new value for dest + * + * \return old value at destination + */ +L4_INLINE l4_umword_t +l4util_xchg(volatile l4_umword_t * dest, l4_umword_t val); + +//!@name Atomic add/sub/and/or (8,16,32 bit version) without result +/** @{ + * \ingroup l4util_atomic + * + * \param dest destination operand + * \param val value to add/sub/and/or + */ +L4_INLINE void +l4util_add8(volatile l4_uint8_t *dest, l4_uint8_t val); +L4_INLINE void +l4util_add16(volatile l4_uint16_t *dest, l4_uint16_t val); +L4_INLINE void +l4util_add32(volatile l4_uint32_t *dest, l4_uint32_t val); +L4_INLINE void +l4util_sub8(volatile l4_uint8_t *dest, l4_uint8_t val); +L4_INLINE void +l4util_sub16(volatile l4_uint16_t *dest, l4_uint16_t val); +L4_INLINE void +l4util_sub32(volatile l4_uint32_t *dest, l4_uint32_t val); +L4_INLINE void +l4util_and8(volatile l4_uint8_t *dest, l4_uint8_t val); +L4_INLINE void +l4util_and16(volatile l4_uint16_t *dest, l4_uint16_t val); +L4_INLINE void +l4util_and32(volatile l4_uint32_t *dest, l4_uint32_t val); +L4_INLINE void +l4util_or8(volatile l4_uint8_t *dest, l4_uint8_t val); +L4_INLINE void +l4util_or16(volatile l4_uint16_t *dest, l4_uint16_t val); +L4_INLINE void +l4util_or32(volatile l4_uint32_t *dest, l4_uint32_t val); +//@} + +//!@name Atomic add/sub/and/or operations (8,16,32 bit) with result +/** @{ + * \ingroup l4util_atomic + * + * \param dest destination operand + * \param val value to add/sub/and/or + * \return res + */ +L4_INLINE l4_uint8_t +l4util_add8_res(volatile l4_uint8_t *dest, l4_uint8_t val); +L4_INLINE l4_uint16_t +l4util_add16_res(volatile l4_uint16_t *dest, l4_uint16_t val); +L4_INLINE l4_uint32_t +l4util_add32_res(volatile l4_uint32_t *dest, l4_uint32_t val); +L4_INLINE l4_uint8_t +l4util_sub8_res(volatile l4_uint8_t *dest, l4_uint8_t val); +L4_INLINE l4_uint16_t +l4util_sub16_res(volatile l4_uint16_t *dest, l4_uint16_t val); +L4_INLINE l4_uint32_t +l4util_sub32_res(volatile l4_uint32_t *dest, l4_uint32_t val); +L4_INLINE l4_uint8_t +l4util_and8_res(volatile l4_uint8_t *dest, l4_uint8_t val); +L4_INLINE l4_uint16_t +l4util_and16_res(volatile l4_uint16_t *dest, l4_uint16_t val); +L4_INLINE l4_uint32_t +l4util_and32_res(volatile l4_uint32_t *dest, l4_uint32_t val); +L4_INLINE l4_uint8_t +l4util_or8_res(volatile l4_uint8_t *dest, l4_uint8_t val); +L4_INLINE l4_uint16_t +l4util_or16_res(volatile l4_uint16_t *dest, l4_uint16_t val); +L4_INLINE l4_uint32_t +l4util_or32_res(volatile l4_uint32_t *dest, l4_uint32_t val); +//@} + +//!@name Atomic inc/dec (8,16,32 bit) without result +/** @{ + * \ingroup l4util_atomic + * + * \param dest destination operand + */ +L4_INLINE void +l4util_inc8(volatile l4_uint8_t *dest); +L4_INLINE void +l4util_inc16(volatile l4_uint16_t *dest); +L4_INLINE void +l4util_inc32(volatile l4_uint32_t *dest); +L4_INLINE void +l4util_dec8(volatile l4_uint8_t *dest); +L4_INLINE void +l4util_dec16(volatile l4_uint16_t *dest); +L4_INLINE void +l4util_dec32(volatile l4_uint32_t *dest); +//@} + +//!@name Atomic inc/dec (8,16,32 bit) with result +/** @{ + * \ingroup l4util_atomic + * + * \param dest destination operand + * \return res + */ +L4_INLINE l4_uint8_t +l4util_inc8_res(volatile l4_uint8_t *dest); +L4_INLINE l4_uint16_t +l4util_inc16_res(volatile l4_uint16_t *dest); +L4_INLINE l4_uint32_t +l4util_inc32_res(volatile l4_uint32_t *dest); +L4_INLINE l4_uint8_t +l4util_dec8_res(volatile l4_uint8_t *dest); +L4_INLINE l4_uint16_t +l4util_dec16_res(volatile l4_uint16_t *dest); +L4_INLINE l4_uint32_t +l4util_dec32_res(volatile l4_uint32_t *dest); +//@} + +/** + * \brief Atomic add + * \ingroup l4util_atomic + * + * \param dest destination operand + * \param val value to add + */ +L4_INLINE void +l4util_atomic_add(volatile long *dest, long val); + +/** + * \brief Atomic increment + * \ingroup l4util_atomic + * + * \param dest destination operand + */ +L4_INLINE void +l4util_atomic_inc(volatile long *dest); + +EXTERN_C_END + +/***************************************************************************** + *** Get architecture specific implementations + *****************************************************************************/ +#include + +#ifdef __GNUC__ + +/* Non-implemented version, catch with a linker warning */ + +extern int __this_l4util_atomic_function_is_not_implemented_for_this_arch__sorry(void); + +#ifndef __L4UTIL_ATOMIC_HAVE_ARCH_INC8 +L4_INLINE void +l4util_inc8(volatile l4_uint8_t *dest) +{ (void)dest; __this_l4util_atomic_function_is_not_implemented_for_this_arch__sorry(); } +#endif + +#ifndef __L4UTIL_ATOMIC_HAVE_ARCH_INC16 +L4_INLINE void +l4util_inc16(volatile l4_uint16_t *dest) +{ (void)dest; __this_l4util_atomic_function_is_not_implemented_for_this_arch__sorry(); } +#endif + +#ifndef __L4UTIL_ATOMIC_HAVE_ARCH_DEC8 +L4_INLINE void +l4util_dec8(volatile l4_uint8_t *dest) +{ (void)dest; __this_l4util_atomic_function_is_not_implemented_for_this_arch__sorry(); } +#endif + +#ifndef __L4UTIL_ATOMIC_HAVE_ARCH_DEC16 +L4_INLINE void +l4util_dec16(volatile l4_uint16_t *dest) +{ (void)dest; __this_l4util_atomic_function_is_not_implemented_for_this_arch__sorry(); } +#endif + + + +#ifndef __L4UTIL_ATOMIC_HAVE_ARCH_INC8_RES +L4_INLINE l4_uint8_t +l4util_inc8_res(volatile l4_uint8_t *dest) +{ (void)dest; __this_l4util_atomic_function_is_not_implemented_for_this_arch__sorry(); return 0; } +#endif + +#ifndef __L4UTIL_ATOMIC_HAVE_ARCH_INC16_RES +L4_INLINE l4_uint16_t +l4util_inc16_res(volatile l4_uint16_t *dest) +{ (void)dest; __this_l4util_atomic_function_is_not_implemented_for_this_arch__sorry(); return 0; } +#endif + +#ifndef __L4UTIL_ATOMIC_HAVE_ARCH_DEC8_RES +L4_INLINE l4_uint8_t +l4util_dec8_res(volatile l4_uint8_t *dest) +{ (void)dest; __this_l4util_atomic_function_is_not_implemented_for_this_arch__sorry(); return 0; } +#endif + +#ifndef __L4UTIL_ATOMIC_HAVE_ARCH_DEC16_RES +L4_INLINE l4_uint16_t +l4util_dec16_res(volatile l4_uint16_t *dest) +{ (void)dest; __this_l4util_atomic_function_is_not_implemented_for_this_arch__sorry(); return 0; } +#endif + +#ifndef __L4UTIL_ATOMIC_HAVE_ARCH_CMPXCHG64 +L4_INLINE int +l4util_cmpxchg64(volatile l4_uint64_t * dest, + l4_uint64_t cmp_val, l4_uint64_t new_val) +{ (void)dest; (void)cmp_val; (void)new_val; __this_l4util_atomic_function_is_not_implemented_for_this_arch__sorry(); return 0; } +#endif + +#ifndef __L4UTIL_ATOMIC_HAVE_ARCH_CMPXCHG8 +L4_INLINE int +l4util_cmpxchg8(volatile l4_uint8_t * dest, + l4_uint8_t cmp_val, l4_uint8_t new_val) +{ (void)dest; (void)cmp_val; (void)new_val; __this_l4util_atomic_function_is_not_implemented_for_this_arch__sorry(); return 0; } +#endif + +#ifndef __L4UTIL_ATOMIC_HAVE_ARCH_CMPXCHG16 +L4_INLINE int +l4util_cmpxchg16(volatile l4_uint16_t * dest, + l4_uint16_t cmp_val, l4_uint16_t new_val) +{ (void)dest; (void)cmp_val; (void)new_val; __this_l4util_atomic_function_is_not_implemented_for_this_arch__sorry(); return 0; } +#endif + +#ifndef __L4UTIL_ATOMIC_HAVE_ARCH_CMPXCHG +L4_INLINE int +l4util_cmpxchg(volatile l4_umword_t * dest, + l4_umword_t cmp_val, l4_umword_t new_val) +{ (void)dest; (void)cmp_val; (void)new_val; __this_l4util_atomic_function_is_not_implemented_for_this_arch__sorry(); return 0; } +#endif + +#ifndef __L4UTIL_ATOMIC_HAVE_ARCH_XCHG32 +L4_INLINE l4_uint32_t +l4util_xchg32(volatile l4_uint32_t * dest, l4_uint32_t val) +{ (void)dest; (void)val; __this_l4util_atomic_function_is_not_implemented_for_this_arch__sorry(); return 0; } +#endif + +#ifndef __L4UTIL_ATOMIC_HAVE_ARCH_XCHG16 +L4_INLINE l4_uint16_t +l4util_xchg16(volatile l4_uint16_t * dest, l4_uint16_t val) +{ (void)dest; (void)val; __this_l4util_atomic_function_is_not_implemented_for_this_arch__sorry(); return 0; } +#endif + +#ifndef __L4UTIL_ATOMIC_HAVE_ARCH_XCHG8 +L4_INLINE l4_uint8_t +l4util_xchg8(volatile l4_uint8_t * dest, l4_uint8_t val) +{ (void)dest; (void)val; __this_l4util_atomic_function_is_not_implemented_for_this_arch__sorry(); return 0; } +#endif + +#ifndef __L4UTIL_ATOMIC_HAVE_ARCH_XCHG +L4_INLINE l4_umword_t +l4util_xchg(volatile l4_umword_t * dest, l4_umword_t val) +{ (void)dest; (void)val; __this_l4util_atomic_function_is_not_implemented_for_this_arch__sorry(); return 0; } +#endif + +#ifndef __L4UTIL_ATOMIC_HAVE_ARCH_ADD8 +L4_INLINE void +l4util_add8(volatile l4_uint8_t *dest, l4_uint8_t val) +{ (void)dest; (void)val; __this_l4util_atomic_function_is_not_implemented_for_this_arch__sorry(); } +#endif + +#ifndef __L4UTIL_ATOMIC_HAVE_ARCH_ADD16 +L4_INLINE void +l4util_add16(volatile l4_uint16_t *dest, l4_uint16_t val) +{ (void)dest; (void)val; __this_l4util_atomic_function_is_not_implemented_for_this_arch__sorry(); } +#endif + +#ifndef __L4UTIL_ATOMIC_HAVE_ARCH_ADD32 +L4_INLINE void +l4util_add32(volatile l4_uint32_t *dest, l4_uint32_t val) +{ (void)dest; (void)val; __this_l4util_atomic_function_is_not_implemented_for_this_arch__sorry(); } +#endif + + +#ifndef __L4UTIL_ATOMIC_HAVE_ARCH_SUB8 +L4_INLINE void +l4util_sub8(volatile l4_uint8_t *dest, l4_uint8_t val) +{ (void)dest; (void)val; __this_l4util_atomic_function_is_not_implemented_for_this_arch__sorry(); } +#endif + +#ifndef __L4UTIL_ATOMIC_HAVE_ARCH_SUB16 +L4_INLINE void +l4util_sub16(volatile l4_uint16_t *dest, l4_uint16_t val) +{ (void)dest; (void)val; __this_l4util_atomic_function_is_not_implemented_for_this_arch__sorry(); } +#endif + +#ifndef __L4UTIL_ATOMIC_HAVE_ARCH_SUB32 +L4_INLINE void +l4util_sub32(volatile l4_uint32_t *dest, l4_uint32_t val) +{ (void)dest; (void)val; __this_l4util_atomic_function_is_not_implemented_for_this_arch__sorry(); } +#endif + +#ifndef __L4UTIL_ATOMIC_HAVE_ARCH_AND8 +L4_INLINE void +l4util_and8(volatile l4_uint8_t *dest, l4_uint8_t val) +{ (void)dest; (void)val; __this_l4util_atomic_function_is_not_implemented_for_this_arch__sorry(); } +#endif + +#ifndef __L4UTIL_ATOMIC_HAVE_ARCH_AND16 +L4_INLINE void +l4util_and16(volatile l4_uint16_t *dest, l4_uint16_t val) +{ (void)dest; (void)val; __this_l4util_atomic_function_is_not_implemented_for_this_arch__sorry(); } +#endif + +#ifndef __L4UTIL_ATOMIC_HAVE_ARCH_AND32 +L4_INLINE void +l4util_and32(volatile l4_uint32_t *dest, l4_uint32_t val) +{ (void)dest; (void)val; __this_l4util_atomic_function_is_not_implemented_for_this_arch__sorry(); } +#endif + +#ifndef __L4UTIL_ATOMIC_HAVE_ARCH_OR8 +L4_INLINE void +l4util_or8(volatile l4_uint8_t *dest, l4_uint8_t val) +{ (void)dest; (void)val; __this_l4util_atomic_function_is_not_implemented_for_this_arch__sorry(); } +#endif + +#ifndef __L4UTIL_ATOMIC_HAVE_ARCH_OR16 +L4_INLINE void +l4util_or16(volatile l4_uint16_t *dest, l4_uint16_t val) +{ (void)dest; (void)val; __this_l4util_atomic_function_is_not_implemented_for_this_arch__sorry(); } +#endif + +#ifndef __L4UTIL_ATOMIC_HAVE_ARCH_OR32 +L4_INLINE void +l4util_or32(volatile l4_uint32_t *dest, l4_uint32_t val) +{ (void)dest; (void)val; __this_l4util_atomic_function_is_not_implemented_for_this_arch__sorry(); } +#endif + +#ifndef __L4UTIL_ATOMIC_HAVE_ARCH_ADD8_RES +L4_INLINE l4_uint8_t +l4util_add8_res(volatile l4_uint8_t *dest, l4_uint8_t val) +{ (void)dest; (void)val; __this_l4util_atomic_function_is_not_implemented_for_this_arch__sorry(); return 0;} +#endif + +#ifndef __L4UTIL_ATOMIC_HAVE_ARCH_ADD16_RES +L4_INLINE l4_uint16_t +l4util_add16_res(volatile l4_uint16_t *dest, l4_uint16_t val) +{ (void)dest; (void)val; __this_l4util_atomic_function_is_not_implemented_for_this_arch__sorry(); return 0;} +#endif + +#ifndef __L4UTIL_ATOMIC_HAVE_ARCH_ADD32_RES +L4_INLINE l4_uint32_t +l4util_add32_res(volatile l4_uint32_t *dest, l4_uint32_t val) +{ (void)dest; (void)val; __this_l4util_atomic_function_is_not_implemented_for_this_arch__sorry(); return 0;} +#endif + +#ifndef __L4UTIL_ATOMIC_HAVE_ARCH_SUB8_RES +L4_INLINE l4_uint8_t +l4util_sub8_res(volatile l4_uint8_t *dest, l4_uint8_t val) +{ (void)dest; (void)val; __this_l4util_atomic_function_is_not_implemented_for_this_arch__sorry(); return 0;} +#endif + +#ifndef __L4UTIL_ATOMIC_HAVE_ARCH_SUB16_RES +L4_INLINE l4_uint16_t +l4util_sub16_res(volatile l4_uint16_t *dest, l4_uint16_t val) +{ (void)dest; (void)val; __this_l4util_atomic_function_is_not_implemented_for_this_arch__sorry(); return 0;} +#endif + +#ifndef __L4UTIL_ATOMIC_HAVE_ARCH_SUB32_RES +L4_INLINE l4_uint32_t +l4util_sub32_res(volatile l4_uint32_t *dest, l4_uint32_t val) +{ (void)dest; (void)val; __this_l4util_atomic_function_is_not_implemented_for_this_arch__sorry(); return 0;} +#endif + +#ifndef __L4UTIL_ATOMIC_HAVE_ARCH_AND8_RES +L4_INLINE l4_uint8_t +l4util_and8_res(volatile l4_uint8_t *dest, l4_uint8_t val) +{ (void)dest; (void)val; __this_l4util_atomic_function_is_not_implemented_for_this_arch__sorry(); return 0;} +#endif + +#ifndef __L4UTIL_ATOMIC_HAVE_ARCH_AND16_RES +L4_INLINE l4_uint16_t +l4util_and16_res(volatile l4_uint16_t *dest, l4_uint16_t val) +{ (void)dest; (void)val; __this_l4util_atomic_function_is_not_implemented_for_this_arch__sorry(); return 0;} +#endif + +#ifndef __L4UTIL_ATOMIC_HAVE_ARCH_AND32_RES +L4_INLINE l4_uint32_t +l4util_and32_res(volatile l4_uint32_t *dest, l4_uint32_t val) +{ (void)dest; (void)val; __this_l4util_atomic_function_is_not_implemented_for_this_arch__sorry(); return 0;} +#endif + +#ifndef __L4UTIL_ATOMIC_HAVE_ARCH_OR8_RES +L4_INLINE l4_uint8_t +l4util_or8_res(volatile l4_uint8_t *dest, l4_uint8_t val) +{ (void)dest; (void)val; __this_l4util_atomic_function_is_not_implemented_for_this_arch__sorry(); return 0;} +#endif + +#ifndef __L4UTIL_ATOMIC_HAVE_ARCH_OR16_RES +L4_INLINE l4_uint16_t +l4util_or16_res(volatile l4_uint16_t *dest, l4_uint16_t val) +{ (void)dest; (void)val; __this_l4util_atomic_function_is_not_implemented_for_this_arch__sorry(); return 0;} +#endif + +#ifndef __L4UTIL_ATOMIC_HAVE_ARCH_OR32_RES +L4_INLINE l4_uint32_t +l4util_or32_res(volatile l4_uint32_t *dest, l4_uint32_t val) +{ (void)dest; (void)val; __this_l4util_atomic_function_is_not_implemented_for_this_arch__sorry(); return 0;} +#endif + + +#endif //_GNUC__ + +#endif /* ! __L4UTIL__INCLUDE__ATOMIC_H__ */ diff --git a/l4/pkg/l4util/include/backtrace.h b/l4/pkg/l4util/include/backtrace.h new file mode 100644 index 00000000..db34dec5 --- /dev/null +++ b/l4/pkg/l4util/include/backtrace.h @@ -0,0 +1,28 @@ +/** + * \file + * \brief Backtrace + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ +#pragma once + +#include + +__BEGIN_DECLS + +/** + * \brief Fill backtrace structure. + * + * \param pc_array Array of instruction pointers. + * \param max_len Length of array. + * \return Number of entries + */ +int l4util_backtrace(void **pc_array, int max_len); + +__END_DECLS diff --git a/l4/pkg/l4util/include/base64.h b/l4/pkg/l4util/include/base64.h new file mode 100644 index 00000000..23513065 --- /dev/null +++ b/l4/pkg/l4util/include/base64.h @@ -0,0 +1,58 @@ +/*! + * \file + * \brief base 64 encoding and decoding functions + * adapted from Bob Trower 08/04/01 + * \ingroup utils + * + * \date 04/26/2002 + * \author Joerg Nothnagel + */ +/* + * (c) 2008-2009 Author(s) + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ + +#ifndef B64_EN_DECODE +#define B64_EN_DECODE + +#include + +EXTERN_C_BEGIN + +/** + * \defgroup l4util_internal Internal functions + * \ingroup l4util_api + */ +/*@{*/ + +/*! + * \brief base-64-encode string \a infile + * \internal + * + * \param infile string to be encoded + * \param in_size length of \a infile + * \retval outfile the base-64-encoded representation of \a infile + * + * base-64-encode string \a infile adding padding as per spec + */ +L4_CV void base64_encode( const char *infile, unsigned int in_size, char **outfile); + +/*! + * \brief decode base-64-encoded string \a infile + * \internal + * + * \param infile string to be decoded + * \param in_size length of \a infile + * \retval outfile the decoded representation of \a infile + * + * base-64-decode string \a infile discarding padding, line breaks and noise + */ +L4_CV void base64_decode(const char *infile, unsigned int in_size, char **outfile); + +EXTERN_C_END + +/*@}*/ +#endif //B64_EN_DECODE diff --git a/l4/pkg/l4util/include/bitops.h b/l4/pkg/l4util/include/bitops.h new file mode 100644 index 00000000..0f77758f --- /dev/null +++ b/l4/pkg/l4util/include/bitops.h @@ -0,0 +1,445 @@ +/*****************************************************************************/ +/** + * \file + * \brief bit manipulation functions + * \ingroup l4util_bitops + * + * \date 07/03/2001 + * \author Lars Reuther */ +/* + * (c) 2000-2009 Author(s) + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ + +/*****************************************************************************/ +#ifndef __L4UTIL__INCLUDE__BITOPS_H__ +#define __L4UTIL__INCLUDE__BITOPS_H__ + +/* L4 includes */ +#include +#include + +/** define some more usual names */ +#define l4util_test_and_clear_bit(b, dest) l4util_btr(b, dest) +#define l4util_test_and_set_bit(b, dest) l4util_bts(b, dest) +#define l4util_test_and_change_bit(b, dest) l4util_btc(b, dest) +#define l4util_log2(word) l4util_bsr(word) + +/***************************************************************************** + *** Prototypes + *****************************************************************************/ + +EXTERN_C_BEGIN + +/** + * \defgroup l4util_bitops Bit Manipulation + * \ingroup l4util_api + */ + +/** + * \brief Set bit in memory + * \ingroup l4util_bitops + * + * \param b bit position + * \param dest destination operand + */ +L4_INLINE void +l4util_set_bit(int b, volatile l4_umword_t * dest); + +L4_INLINE void +l4util_set_bit32(int b, volatile l4_uint32_t * dest); + +#if L4_MWORD_BITS >= 64 +L4_INLINE void +l4util_set_bit64(int b, volatile l4_uint64_t * dest); +#endif + +/** + * \brief Clear bit in memory + * \ingroup l4util_bitops + * + * \param b bit position + * \param dest destination operand + */ +L4_INLINE void +l4util_clear_bit(int b, volatile l4_umword_t * dest); + +L4_INLINE void +l4util_clear_bit32(int b, volatile l4_uint32_t * dest); + +#if L4_MWORD_BITS >= 64 +L4_INLINE void +l4util_clear_bit64(int b, volatile l4_uint64_t * dest); +#endif + +/** + * \brief Complement bit in memory + * \ingroup l4util_bitops + * + * \param b bit position + * \param dest destination operand + */ +L4_INLINE void +l4util_complement_bit(int b, volatile l4_umword_t * dest); + +/** + * \brief Test bit (return value of bit) + * \ingroup l4util_bitops + * + * \param b bit position + * \param dest destination operand + * + * \return Value of bit \em b. + */ +L4_INLINE int +l4util_test_bit(int b, const volatile l4_umword_t * dest); + +L4_INLINE int +l4util_test_bit32(int b, const volatile l4_uint32_t * dest); + +#if L4_MWORD_BITS >= 64 +L4_INLINE int +l4util_test_bit64(int b, const volatile l4_uint64_t * dest); +#endif + +/** + * \brief Bit test and set + * \ingroup l4util_bitops + * + * \param b bit position + * \param dest destination operand + * + * \return Old value of bit \em b. + * + * Set the \em b bit of \em dest to 1 and return the old value. + */ +L4_INLINE int +l4util_bts(int b, volatile l4_umword_t * dest); + +/** + * \brief Bit test and reset + * \ingroup l4util_bitops + * + * \param b bit position + * \param dest destination operand + * + * \return Old value of bit \em b. + * + * Reset bit \em b and return old value. + */ +L4_INLINE int +l4util_btr(int b, volatile l4_umword_t * dest); + +/** + * \brief Bit test and complement + * \ingroup l4util_bitops + * + * \param b bit position + * \param dest destination operand + * + * \return Old value of bit \em b. + * + * Complement bit \em b and return old value. + */ +L4_INLINE int +l4util_btc(int b, volatile l4_umword_t * dest); + +/** + * \brief Bit scan reverse + * \ingroup l4util_bitops + * + * \param word value (machine size) + * + * \return index of most significant set bit in word, + * -1 if no bit is set (word == 0) + * + * "bit scan reverse", find most significant set bit in word (-> LOG2(word)) + */ +L4_INLINE int +l4util_bsr(l4_umword_t word); + +/** + * \brief Bit scan forward + * \ingroup l4util_bitops + * + * \param word value (machine size) + * + * \return index of least significant bit set in word, + * -1 if no bit is set (word == 0) + * + * "bit scan forward", find least significant bit set in word. + */ +L4_INLINE int +l4util_bsf(l4_umword_t word); + +/** + * \brief Find the first set bit in a memory region + * \ingroup l4util_bitops + * + * \param dest bit string + * \param size size of string in bits (must be a multiple of 32!) + * + * \return number of the first set bit, + * >= size if no bit is set + */ +L4_INLINE int +l4util_find_first_set_bit(const void * dest, l4_size_t size); + +/** + * \brief Find the first zero bit in a memory region + * \ingroup l4util_bitops + * + * \param dest bit string + * \param size size of string in bits (must be a multiple of 32!) + * + * \return number of the first zero bit, + * >= size if no bit is set + */ +L4_INLINE int +l4util_find_first_zero_bit(const void * dest, l4_size_t size); + + +/** + * \brief Find the next power of 2 for a given number. + * \ingroup l4util_bitops + * + * \param val initial value + * + * \return next-highest power of 2 + */ +L4_INLINE int +l4util_next_power2(const unsigned long val); + +EXTERN_C_END + +/***************************************************************************** + *** Implementation of specific version + *****************************************************************************/ + +#include + +/***************************************************************************** + *** Generic implementations + *****************************************************************************/ + +#ifndef __L4UTIL_BITOPS_HAVE_ARCH_SET_BIT +#include +L4_INLINE void +l4util_set_bit(int b, volatile l4_umword_t * dest) +{ + l4_umword_t oldval, newval; + + dest += b / (sizeof(*dest) * 8); /* advance dest to the proper element */ + b &= sizeof(*dest) * 8 - 1; /* modulo; cut off all upper bits */ + + do + { + oldval = *dest; + newval = oldval | (1 << b); + } + while (!l4util_cmpxchg(dest, oldval, newval)); +} +#endif + +#ifndef __L4UTIL_BITOPS_HAVE_ARCH_CLEAR_BIT +#include +L4_INLINE void +l4util_clear_bit(int b, volatile l4_umword_t * dest) +{ + l4_umword_t oldval, newval; + + dest += b / (sizeof(*dest) * 8); + b &= sizeof(*dest) * 8 - 1; + + do + { + oldval = *dest; + newval = oldval & ~(1 << b); + } + while (!l4util_cmpxchg(dest, oldval, newval)); +} +#endif + +#ifndef __L4UTIL_BITOPS_HAVE_ARCH_TEST_BIT +L4_INLINE int +l4util_test_bit(int b, const volatile l4_umword_t * dest) +{ + dest += b / (sizeof(*dest) * 8); + b &= sizeof(*dest) * 8 - 1; + + return (*dest >> b) & 1; +} +#endif + +#ifndef __L4UTIL_BITOPS_HAVE_ARCH_TEST_BIT32 +L4_INLINE int +l4util_test_bit32(int b, const volatile l4_uint32_t * dest) +{ + dest += b / (sizeof(*dest) * 8); + b &= sizeof(*dest) * 8 - 1; + + return (*dest >> b) & 1; +} +#endif + +#ifndef __L4UTIL_BITOPS_HAVE_ARCH_BIT_TEST_AND_SET +#include +L4_INLINE int +l4util_bts(int b, volatile l4_umword_t * dest) +{ + l4_umword_t oldval, newval; + + dest += b / (sizeof(*dest) * 8); + b &= sizeof(*dest) * 8 - 1; + + do + { + oldval = *dest; + newval = oldval | (1 << b); + } + while (!l4util_cmpxchg(dest, oldval, newval)); + + /* Return old bit */ + return (oldval >> b) & 1; +} +#endif + +#ifndef __L4UTIL_BITOPS_HAVE_ARCH_BIT_TEST_AND_RESET +#include +L4_INLINE int +l4util_btr(int b, volatile l4_umword_t * dest) +{ + l4_umword_t oldval, newval; + + dest += b / (sizeof(*dest) * 8); + b &= sizeof(*dest) * 8 - 1; + + do + { + oldval = *dest; + newval = oldval & ~(1 << b); + } + while (!l4util_cmpxchg(dest, oldval, newval)); + + /* Return old bit */ + return (oldval >> b) & 1; +} +#endif + +#ifndef __L4UTIL_BITOPS_HAVE_ARCH_BIT_SCAN_REVERSE +L4_INLINE int +l4util_bsr(l4_umword_t word) +{ + int i; + + if (!word) + return -1; + + for (i = 8 * sizeof(word) - 1; i >= 0; i--) + if ((1 << i) & word) + return i; + + return -1; +} +#endif + +#ifndef __L4UTIL_BITOPS_HAVE_ARCH_BIT_SCAN_FORWARD +L4_INLINE int +l4util_bsf(l4_umword_t word) +{ + unsigned int i; + + if (!word) + return -1; + + for (i = 0; i < sizeof(word) * 8; i++) + if ((1 << i) & word) + return i; + + return -1; +} +#endif + +#ifndef __L4UTIL_BITOPS_HAVE_ARCH_FIND_FIRST_ZERO_BIT +L4_INLINE int +l4util_find_first_zero_bit(const void * dest, l4_size_t size) +{ + l4_size_t i, j; + unsigned long *v = (unsigned long*)dest; + + if (!size) + return 0; + + size = (size + 31) & ~0x1f; /* Grmbl: adapt to x86 implementation... */ + + for (i = j = 0; i < size; i++, j++) + { + if (j >= sizeof(*v) * 8) + { + j = 0; + v++; + } + if (!((1 << j) & *v)) + return i; + } + return size + 1; +} +#endif + +#ifndef __L4UTIL_BITOPS_HAVE_ARCH_COMPLEMENT_BIT +L4_INLINE void +l4util_complement_bit(int b, volatile l4_umword_t * dest) +{ + dest += b / (sizeof(*dest) * 8); + b &= sizeof(*dest) * 8 - 1; + + *dest ^= 1UL << b; +} +#endif + +/* + * Adapted from: + * http://en.wikipedia.org/wiki/Power_of_two#Algorithm_to_find_the_next-highest_power_of_two + */ +L4_INLINE int +l4util_next_power2(unsigned long val) +{ + unsigned i; + + if (val == 0) + return 1; + + val--; + for (i=1; i < sizeof(unsigned long)*8; i<<=1) + val = val | val >> i; + + return val+1; +} + + +/* Non-implemented version, catch with a linker warning */ + +extern int __this_l4util_bitops_function_is_not_implemented_for_this_arch__sorry(void); + +#ifndef __L4UTIL_BITOPS_HAVE_ARCH_CLEAR_BIT32 +L4_INLINE void +l4util_clear_bit32(int b, volatile l4_uint32_t * dest) +{ (void)b; (void)dest; __this_l4util_bitops_function_is_not_implemented_for_this_arch__sorry(); } +#endif + +#ifndef __L4UTIL_BITOPS_HAVE_ARCH_BIT_TEST_AND_COMPLEMENT +L4_INLINE int +l4util_btc(int b, volatile l4_umword_t * dest) +{ (void)b; (void)dest; __this_l4util_bitops_function_is_not_implemented_for_this_arch__sorry(); return 0; } +#endif + +#ifndef __L4UTIL_BITOPS_HAVE_ARCH_FIND_FIRST_SET_BIT +L4_INLINE int +l4util_find_first_set_bit(const void * dest, l4_size_t size) +{ (void)dest; (void)size; __this_l4util_bitops_function_is_not_implemented_for_this_arch__sorry(); return 0; } +#endif + +#endif /* ! __L4UTIL__INCLUDE__BITOPS_H__ */ diff --git a/l4/pkg/l4util/include/elf.h b/l4/pkg/l4util/include/elf.h new file mode 100644 index 00000000..65c5496a --- /dev/null +++ b/l4/pkg/l4util/include/elf.h @@ -0,0 +1,873 @@ +/** + * \file + * \brief ELF definition + * + * \date 08/18/2000 + * \author Frank Mehnert + * Alexander Warg + * + * Many structs from + * "Executable and Linkable Format (ELF)", + * Portable Formats Specification, Version 1.1 + * and + * "System V Application Binary Interface - DRAFT - April 29, 1998" + * The Santa Cruz Operation, Inc. + * (see http://www.sco.com/developer/gabi/contents.html) + * + * \ingroup l4util_elf + */ +/* + * (c) 2008-2009 Author(s) + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ + +/* (c) 2003-2006 Technische Universitaet Dresden + * This file is part of the exec package, which is distributed under + * the terms of the GNU General Public License 2. Please see the + * COPYING file for details. */ + +#ifndef _L4_EXEC_ELF_H +#define _L4_EXEC_ELF_H + +#include + +/** + * \defgroup l4util_elf ELF binary format + * \ingroup l4util_api + * \brief Functions and types related to ELF binaries. + */ + +/** \name ELF types + * \ingroup l4util_elf + */ +/*@{*/ +typedef l4_uint32_t Elf32_Addr; /**< size 4 align 4 \ingroup l4util_elf*/ +typedef l4_uint32_t Elf32_Off; /**< size 4 align 4 \ingroup l4util_elf*/ +typedef l4_uint16_t Elf32_Half; /**< size 2 align 2 \ingroup l4util_elf*/ +typedef l4_uint32_t Elf32_Word; /**< size 4 align 4 \ingroup l4util_elf*/ +typedef l4_int32_t Elf32_Sword; /**< size 4 align 4 \ingroup l4util_elf*/ +typedef l4_uint64_t Elf64_Addr; /**< size 8 align 8 \ingroup l4util_elf*/ +typedef l4_uint64_t Elf64_Off; /**< size 8 align 8 \ingroup l4util_elf*/ +typedef l4_uint16_t Elf64_Half; /**< size 2 align 2 \ingroup l4util_elf*/ +typedef l4_uint32_t Elf64_Word; /**< size 4 align 4 \ingroup l4util_elf*/ +typedef l4_int32_t Elf64_Sword; /**< size 4 align 4 \ingroup l4util_elf*/ +typedef l4_uint64_t Elf64_Xword; /**< size 8 align 8 \ingroup l4util_elf*/ +typedef l4_int64_t Elf64_Sxword; /**< size 8 align 8 \ingroup l4util_elf*/ +/*@}*/ + +#if L4_MWORD_BITS == 64 +/** + * \brief Use 64 or 32 bits types depending on the target architecture. + * \ingroup l4util_elf + */ +#define ElfW(type) _ElfW(Elf, 64, type) +#else +#define ElfW(type) _ElfW(Elf, 32, type) +#endif +#define _ElfW(e,w,t) __ElfW(e, w, _##t) +#define __ElfW(e,w,t) e##w##t + +#ifdef ARCH_x86 +#define L4_ARCH_EI_DATA ELFDATA2LSB +#define L4_ARCH_E_MACHINE EM_386 +#define L4_ARCH_EI_CLASS ELFCLASS32 +#else +#ifdef ARCH_amd64 +#define L4_ARCH_EI_DATA ELFDATA2LSB +#define L4_ARCH_E_MACHINE EM_AMD64 +#define L4_ARCH_EI_CLASS ELFCLASS64 +#else +#ifdef ARCH_arm +#define L4_ARCH_EI_DATA ELFDATA2LSB +#define L4_ARCH_E_MACHINE EM_ARM +#define L4_ARCH_EI_CLASS ELFCLASS32 +#else +#ifdef ARCH_ppc32 +#define L4_ARCH_EI_DATA ELFDATA2MSB +#define L4_ARCH_E_MACHINE EM_PPC +#define L4_ARCH_EI_CLASS ELFCLASS32 +#else +#ifdef ARCH_sparc +#define L4_ARCH_EI_DATA ELFDATA2MSB +#define L4_ARCH_E_MACHINE EM_SPARC +#define L4_ARCH_EI_CLASS ELFCLASS32 +#else +#warning elf.h: Unsupported build architecture! +#endif +#endif +#endif +#endif +#endif + + +/*************************************/ +/* ELF Header - figure 1-3, page 1-3 */ +/*************************************/ + +/** \addtogroup l4util_elf */ + +/*@{*/ + +#define EI_NIDENT 16 /**< \brief number of characters */ +/** + * \brief ELF32 header. + */ +typedef struct { + unsigned char e_ident[EI_NIDENT]; + Elf32_Half e_type; /**< type of ELF file */ + Elf32_Half e_machine; /**< required architecture */ + Elf32_Word e_version; /**< file version */ + Elf32_Addr e_entry; /**< initial eip */ + Elf32_Off e_phoff; /**< offset of program header table */ + Elf32_Off e_shoff; /**< offset of file header table */ + Elf32_Word e_flags; /**< processor-specific flags */ + Elf32_Half e_ehsize; /**< size of ELF header */ + Elf32_Half e_phentsize; /**< size of program header entry */ + Elf32_Half e_phnum; /**< # of entries in prog. head. tab. */ + Elf32_Half e_shentsize; /**< size of section header entry */ + Elf32_Half e_shnum; /**< # of entries in sect. head. tab. */ + Elf32_Half e_shstrndx; /**< sect.head.tab.idx of strtab */ +} Elf32_Ehdr; + +/** + * \brief ELF64 header. + */ +typedef struct { + unsigned char e_ident[EI_NIDENT]; + Elf64_Half e_type; /**< \brief type of ELF file */ + Elf64_Half e_machine; /**< \brief required architecture */ + Elf64_Word e_version; /**< \brief file version */ + Elf64_Addr e_entry; /**< \brief initial eip */ + Elf64_Off e_phoff; /**< \brief offset of program header table */ + Elf64_Off e_shoff; /**< \brief offset of file header table */ + Elf64_Word e_flags; /**< \brief processor-specific flags */ + Elf64_Half e_ehsize; /**< \brief size of ELF header */ + Elf64_Half e_phentsize; /**< \brief size of program header entry */ + Elf64_Half e_phnum; /**< \brief # of entries in prog. head. tab. */ + Elf64_Half e_shentsize; /**< \brief size of section header entry */ + Elf64_Half e_shnum; /**< \brief # of entries in sect. head. tab. */ + Elf64_Half e_shstrndx; /**< \brief sect.head.tab.idx of strtab */ +} Elf64_Ehdr; + +#define EI_CLASS 4 /**< \brief ELF class byte index */ +#define ELFCLASSNONE 0 /**< \brief Invalid ELF class */ +#define ELFCLASS32 1 /**< \brief 32-bit objects */ +#define ELFCLASS64 2 /**< \brief 64-bit objects */ +#define ELFCLASSNUM 3 /**< \brief Mask for 32-bit or 64-bit class */ + +#define EI_DATA 5 /**< Data encoding byte index */ +#define ELFDATANONE 0 /**< Invalid data encoding */ +#define ELFDATA2LSB 1 /**< 2's complement, little endian */ +#define ELFDATA2MSB 2 /**< 2's complement, big endian */ +#define ELFDATANUM 3 + +#define EI_VERSION 6 /**< File version byte index */ + /**< Value must be EV_CURRENT */ + +#define EI_OSABI 7 /**< OS ABI identification */ +#define ELFOSABI_NONE 0 /**< UNIX System V ABI */ +#define ELFOSABI_SYSV 0 /**< Alias. */ +#define ELFOSABI_HPUX 1 /**< HP-UX */ +#define ELFOSABI_NETBSD 2 /**< NetBSD. */ +#define ELFOSABI_LINUX 3 /**< Linux. */ +#define ELFOSABI_SOLARIS 6 /**< Sun Solaris. */ +#define ELFOSABI_AIX 7 /**< IBM AIX. */ +#define ELFOSABI_IRIX 8 /**< SGI Irix. */ +#define ELFOSABI_FREEBSD 9 /**< FreeBSD. */ +#define ELFOSABI_TRU64 10 /**< Compaq TRU64 UNIX. */ +#define ELFOSABI_MODESTO 11 /**< Novell Modesto. */ +#define ELFOSABI_OPENBSD 12 /**< OpenBSD. */ +#define ELFOSABI_ARM 97 /**< ARM */ +#define ELFOSABI_STANDALONE 255 /**< Standalone (embedded) application */ + +#define EI_ABIVERSION 8 /**< ABI version */ + +#define EI_PAD 9 /**< Byte index of padding bytes */ + +/* object file type - page 1-3 (e_type) */ + +#define ET_NONE 0 /**< no file type */ +#define ET_REL 1 /**< relocatable file */ +#define ET_EXEC 2 /**< executable file */ +#define ET_DYN 3 /**< shared object file */ +#define ET_CORE 4 /**< core file */ +#define ET_LOPROC 0xff00 /**< processor-specific */ +#define ET_HIPROC 0xffff /**< processor-specific */ + +/* required architecture - page 1-4 (e_machine) */ + +#define EM_NONE 0 /**< no machine */ +#define EM_M32 1 /**< AT&T WE 32100 */ +#define EM_SPARC 2 /**< SPARC */ +#define EM_386 3 /**< Intel 80386 */ +#define EM_68K 4 /**< Motorola 68000 */ +#define EM_88K 5 /**< Motorola 88000 */ +#define EM_860 7 /**< Intel 80860 */ +#define EM_MIPS 8 /**< MIPS RS3000 big-endian */ +#define EM_MIPS_RS4_BE 10 /**< MIPS RS4000 big-endian */ +#define EM_SPARC64 11 /**< SPARC 64-bit */ +#define EM_PARISC 15 /**< HP PA-RISC */ +#define EM_VPP500 17 /**< Fujitsu VPP500 */ +#define EM_SPARC32PLUS 18 /**< Sun's V8plus */ +#define EM_960 19 /**< Intel 80960 */ +#define EM_PPC 20 /**< PowerPC */ +#define EM_V800 36 /**< NEC V800 */ +#define EM_FR20 37 /**< Fujitsu FR20 */ +#define EM_RH32 38 /**< TRW RH-32 */ +#define EM_RCE 39 /**< Motorola RCE */ +#define EM_ARM 40 /**< Advanced RISC Machines ARM */ +#define EM_ALPHA 41 /**< Digital Alpha */ +#define EM_SH 42 /**< Hitachi SuperH */ +#define EM_SPARCV9 43 /**< SPARC v9 64-bit */ +#define EM_TRICORE 44 /**< Siemens Tricore embedded processor */ +#define EM_ARC 45 /**< Argonaut RISC Core, Argonaut Techn Inc. */ +#define EM_H8_300 46 /**< Hitachi H8/300 */ +#define EM_H8_300H 47 /**< Hitachi H8/300H */ +#define EM_H8S 48 /**< Hitachi H8/S */ +#define EM_H8_500 49 /**< Hitachi H8/500 */ +#define EM_IA_64 50 /**< HP/Intel IA-64 */ +#define EM_MIPS_X 51 /**< Stanford MIPS-X */ +#define EM_COLDFIRE 52 /**< Motorola Coldfire */ +#define EM_68HC12 53 /**< Motorola M68HC12 */ +#define EM_AMD64 62 + +#if 0 +#define EM_ALPHA 0x9026 /* interium value used by Linux until the + committee comes up with a final number */ +#define EM_S390 0xA390 /* interium value used for IBM S390 */ +#endif + +/* object file version - page 1-4 (e_version) */ + +#define EV_NONE 0 /**< Invalid version */ +#define EV_CURRENT 1 /**< Current version */ + +/* e_ident[] Identification Indexes - figure 1-4, page 1-5 */ + +#define EI_MAG0 0 /**< file id */ +#define EI_MAG1 1 /**< file id */ +#define EI_MAG2 2 /**< file id */ +#define EI_MAG3 3 /**< file id */ +#define EI_CLASS 4 /**< file class */ +#define EI_DATA 5 /**< data encoding */ +#define EI_VERSION 6 /**< file version */ +#define EI_OSABI 7 /**< Operating system / ABI identification */ +#define EI_ABIVERSION 8 /**< ABI version */ +#define EI_PAD 9 /**< start of padding bytes */ + +/* magic number - page 1-5 */ + +#define ELFMAG0 0x7f /**< e_ident[EI_MAG0] */ +#define ELFMAG1 'E' /**< e_ident[EI_MAG1] */ +#define ELFMAG2 'L' /**< e_ident[EI_MAG2] */ +#define ELFMAG3 'F' /**< e_ident[EI_MAG3] */ + +/* file class or capacity - page 1-6 */ + +#define ELFCLASSNONE 0 /**< Invalid class */ +#define ELFCLASSS32 1 /**< 32-bit object */ +#define ELFCLASSS64 2 /**< 64-bit object */ + +/* data encoding - page 1-6 */ + +#define ELFDATANONE 0 /**< invalid data encoding */ +#define ELFDATA2LSB 1 /**< 0x01020304 => [ 0x04|0x03|0x02|0x01 ] */ +#define ELFDATA2MSB 2 /**< 0x01020304 => [ 0x01|0x02|0x03|0x04 ] */ + +/* Identify operating system and ABI to which the object is targeted */ + +#define ELFOSABI_SYSV 0 /**< UNIX System V ABI (this specification) */ +#define ELFOSABI_HPUX 1 /**< HP-UX operating system */ +#define ELFOSABI_STANDALONE 255 /**< Standalone (embedded) application */ + + +/***********************/ +/* Sections - page 1-8 */ +/***********************/ + +/* special section indexes */ + +#define SHN_UNDEF 0 /**< undefined section header entry */ +#define SHN_LORESERVE 0xff00 /**< lower bound of reserved indexes */ +#define SHN_LOPROC 0xff00 /**< lower bound of proc spec entr */ +#define SHN_HIPROC 0xff1f /**< upper bound of proc spec entr */ +#define SHN_ABS 0xfff1 /**< absolute values for ref */ +#define SHN_COMMON 0xfff2 /**< common symbols */ +#define SHN_HIRESERVE 0xffff /**< upper bound of reserved indexes */ + +/** ELF32 section header - figure 1-9, page 1-9 */ +typedef struct { + Elf32_Word sh_name; /**< name of sect (idx into strtab) */ + Elf32_Word sh_type; /**< section's type */ + Elf32_Word sh_flags; /**< section's flags */ + Elf32_Addr sh_addr; /**< memory address of section */ + Elf32_Off sh_offset; /**< file offset of section */ + Elf32_Word sh_size; /**< file size of section */ + Elf32_Word sh_link; /**< idx to associated header section */ + Elf32_Word sh_info; /**< extra info of header section */ + Elf32_Word sh_addralign; /**< address alignment constraints */ + Elf32_Word sh_entsize; /**< size of entry if sect is table */ +} Elf32_Shdr; + +/** ELF64 section header */ +typedef struct { + Elf64_Word sh_name; /**< name of sect (idx into strtab) */ + Elf64_Word sh_type; /**< section's type */ + Elf64_Xword sh_flags; /**< section's flags */ + Elf64_Addr sh_addr; /**< memory address of section */ + Elf64_Off sh_offset; /**< file offset of section */ + Elf64_Xword sh_size; /**< file size of section */ + Elf64_Word sh_link; /**< idx to associated header section */ + Elf64_Word sh_info; /**< extra info of header section */ + Elf64_Xword sh_addralign; /**< address alignment constraints */ + Elf64_Xword sh_entsize; /**< size of entry if sect is table */ +} Elf64_Shdr; + +/* section type - figure 1-10, page 1-10 */ + +#define SHT_NULL 0 +#define SHT_PROGBITS 1 +#define SHT_SYMTAB 2 +#define SHT_STRTAB 3 +#define SHT_RELA 4 +#define SHT_HASH 5 +#define SHT_DYNAMIC 6 +#define SHT_NOTE 7 +#define SHT_NOBITS 8 +#define SHT_REL 9 +#define SHT_SHLIB 10 +#define SHT_DYNSYM 11 +#define SHT_INIT_ARRAY 14 /**< Array of constructors */ +#define SHT_FINI_ARRAY 15 /**< Array of destructors */ +#define SHT_PREINIT_ARRAY 16 /**< Array of pre-constructors */ +#define SHT_GROUP 17 /**< Section group */ +#define SHT_SYMTAB_SHNDX 18 /**< Extended section indeces */ +#define SHT_NUM 19 /**< Number of defined types. */ +#define SHT_LOOS 0x60000000 +#define SHT_HIOS 0x6fffffff +#define SHT_LOPROC 0x70000000 +#define SHT_HIPROC 0x7fffffff +#define SHT_LOUSER 0x80000000 +#define SHT_HIUSER 0xffffffff + +/* section attribute flags - page 1-12, figure 1-12 */ + +#define SHF_WRITE 0x1 /**< writeable during execution */ +#define SHF_ALLOC 0x2 /**< section occupies virt memory */ +#define SHF_EXECINSTR 0x4 /**< code section */ +#define SHF_MERGE 0x10 /**< Might be merged */ +#define SHF_STRINGS 0x20 /**< Contains nul-terminated strings */ +#define SHF_INFO_LINK 0x40 /**< `sh_info' contains SHT index */ +#define SHF_LINK_ORDER 0x80 /**< Preserve order after combining */ +#define SHF_OS_NONCONFORMING 0x100 /**< Non-standard OS specific handling + required */ +#define SHF_GROUP 0x200 /**< Section is member of a group. */ +#define SHF_TLS 0x400 /**< Section hold thread-local data. */ +#define SHF_MASKOS 0x0ff00000 /**< OS-specific. */ +#define SHF_MASKPROC 0xf0000000 /**< proc spec mask */ + + +/*****************************************/ +/* Program Header - figure 2-1, page 2-2 */ +/*****************************************/ + +/** ELF32 program header */ +typedef struct { + Elf32_Word p_type; /**< type of program section */ + Elf32_Off p_offset; /**< file offset of program section */ + Elf32_Addr p_vaddr; /**< memory address of prog section */ + Elf32_Addr p_paddr; /**< physical address (ignored) */ + Elf32_Word p_filesz; /**< file size of program section */ + Elf32_Word p_memsz; /**< memory size of program section */ + Elf32_Word p_flags; /**< flags */ + Elf32_Word p_align; /**< alignment of section */ +} Elf32_Phdr; + +/** ELF64 program header */ +typedef struct { + Elf64_Word p_type; /**< type of program section */ + Elf64_Word p_flags; /**< flags */ + Elf64_Off p_offset; /**< file offset of program section */ + Elf64_Addr p_vaddr; /**< memory address of prog section */ + Elf64_Addr p_paddr; /**< physical address (ignored) */ + Elf64_Xword p_filesz; /**< file size of program section */ + Elf64_Xword p_memsz; /**< memory size of program section */ + Elf64_Xword p_align; /**< alignment of section */ +} Elf64_Phdr; + +/* segment types - figure 2-2, page 2-3 */ + +#define PT_NULL 0 /**< array is unused */ +#define PT_LOAD 1 /**< loadable */ +#define PT_DYNAMIC 2 /**< dynamic linking information */ +#define PT_INTERP 3 /**< path to interpreter */ +#define PT_NOTE 4 /**< auxiliary information */ +#define PT_SHLIB 5 /**< reserved */ +#define PT_PHDR 6 /**< location of the pht itself */ +#define PT_TLS 7 /**< Thread-local storage segment */ +#define PT_NUM 8 /**< Number of defined types */ +#define PT_LOOS 0x60000000 /**< os spec. */ +#define PT_HIOS 0x6fffffff /**< os spec. */ +#define PT_LOPROC 0x70000000 /**< processor spec. */ +#define PT_HIPROC 0x7fffffff /**< processor spec. */ + +#define PT_GNU_EH_FRAME (PT_LOOS + 0x474e550) /**< EH frame information. */ +#define PT_GNU_STACK (PT_LOOS + 0x474e551) /**< Flags for stack. */ +#define PT_GNU_RELRO (PT_LOOS + 0x474e552) /**< Read only after reloc. */ + +#define PT_L4_STACK (PT_LOOS + 0x12) /**< Address of the stack. */ +#define PT_L4_KIP (PT_LOOS + 0x13) /**< Address of the KIP. */ +#define PT_L4_AUX (PT_LOOS + 0x14) /**< Address of the AUX strcutures. */ + +/* segment permissions - page 2-3 */ + +#define PF_X 0x1 +#define PF_W 0x2 +#define PF_R 0x4 +#define PF_MASKOS 0x0ff00000 +#define PF_MASKPROC 0x7fffffff + +/* Legal values for note segment descriptor types for core files. */ + +#define NT_PRSTATUS 1 /**< Contains copy of prstatus struct */ +#define NT_FPREGSET 2 /**< Contains copy of fpregset struct */ +#define NT_PRPSINFO 3 /**< Contains copy of prpsinfo struct */ +#define NT_PRXREG 4 /**< Contains copy of prxregset struct */ +#define NT_TASKSTRUCT 4 /**< Contains copy of task structure */ +#define NT_PLATFORM 5 /**< String from sysinfo(SI_PLATFORM) */ +#define NT_AUXV 6 /**< Contains copy of auxv array */ +#define NT_GWINDOWS 7 /**< Contains copy of gwindows struct */ +#define NT_ASRS 8 /**< Contains copy of asrset struct */ +#define NT_PSTATUS 10 /**< Contains copy of pstatus struct */ +#define NT_PSINFO 13 /**< Contains copy of psinfo struct */ +#define NT_PRCRED 14 /**< Contains copy of prcred struct */ +#define NT_UTSNAME 15 /**< Contains copy of utsname struct */ +#define NT_LWPSTATUS 16 /**< Contains copy of lwpstatus struct */ +#define NT_LWPSINFO 17 /**< Contains copy of lwpinfo struct */ +#define NT_PRFPXREG 20 /**< Contains copy of fprxregset struct*/ + +/* Legal values for the note segment descriptor types for object files. */ + +#define NT_VERSION 1 /**< Contains a version string. */ + +/* Dynamic structure - figure 2-9, page 2-12 */ + +/** ELF32 dynamic entry */ +typedef struct { + Elf32_Sword d_tag; /**< see DT_ values */ + union { + Elf32_Word d_val; /**< integer values with various interpret. */ + Elf32_Addr d_ptr; /**< program virtual addresses */ + } d_un; +} Elf32_Dyn; + +/** ELF64 dynamic entry */ +typedef struct { + Elf64_Sxword d_tag; /**< see DT_ values */ + union { + Elf64_Xword d_val; /**< integer values with various interpret. */ + Elf64_Addr d_ptr; /**< program virtual addresses */ + } d_un; +} Elf64_Dyn; + +/** Dynamic Array Tags, d_tag - figure 2-10, page 2-12 */ + +#define DT_NULL 0 /**< end of _DYNAMIC array */ +#define DT_NEEDED 1 /**< name of a needed library */ +#define DT_PLTRELSZ 2 /**< total size of relocation entry */ +#define DT_PLTGOT 3 /**< address assoc with prog link table */ +#define DT_HASH 4 /**< address of symbol hash table */ +#define DT_STRTAB 5 /**< address of string table */ +#define DT_SYMTAB 6 /**< address of symbol table */ +#define DT_RELA 7 /**< address of relocation table */ +#define DT_RELASZ 8 /**< total size of relocation table */ +#define DT_RELAENT 9 /**< size of DT_RELA relocation entry */ +#define DT_STRSZ 10 /**< size of the string table */ +#define DT_SYMENT 11 /**< size of a symbol table entry */ +#define DT_INIT 12 /**< address of initialization function */ +#define DT_FINI 13 /**< address of termination function */ +#define DT_SONAME 14 /**< name of the shared object */ +#define DT_RPATH 15 /**< search library path */ +#define DT_SYMBOLIC 16 /**< alter symbol resolution algorithm */ +#define DT_REL 17 /**< address of relocation table */ +#define DT_RELSZ 18 /**< total size of DT_REL relocation table */ +#define DT_RELENT 19 /**< size of the DT_REL relocation entry */ +#define DT_PTRREL 20 /**< type of relocation entry */ +#define DT_DEBUG 21 /**< for debugging purposes */ +#define DT_TEXTREL 22 /**< at least on entry changes r/o section */ +#define DT_JMPREL 23 /**< address of relocation entries */ +#define DT_BIND_NOW 24 /**< Process relocations of object */ +#define DT_INIT_ARRAY 25 /**< Array with addresses of init fct */ +#define DT_FINI_ARRAY 26 /**< Array with addresses of fini fct */ +#define DT_INIT_ARRAYSZ 27 /**< Size in bytes of DT_INIT_ARRAY */ +#define DT_FINI_ARRAYSZ 28 /**< Size in bytes of DT_FINI_ARRAY */ +#define DT_RUNPATH 29 /**< Library search path */ +#define DT_FLAGS 30 /**< Flags for the object being loaded */ +#define DT_ENCODING 32 /**< Start of encoded range */ +#define DT_PREINIT_ARRAY 32 /**< Array with addresses of preinit fct*/ +#define DT_PREINIT_ARRAYSZ 33 /**< size in bytes of DT_PREINIT_ARRAY */ +#define DT_NUM 34 /**< Number used */ +#define DT_LOOS 0x6000000d /**< Start of OS-specific */ +#define DT_HIOS 0x6ffff000 /**< End of OS-specific */ +#define DT_LOPROC 0x70000000 /**< processor spec. */ +#define DT_HIPROC 0x7fffffff /**< processor spec. */ + +/* Values of `d_un.d_val' in the DT_FLAGS entry. */ +#define DF_ORIGIN 0x00000001 /**< Object may use DF_ORIGIN */ +#define DF_SYMBOLIC 0x00000002 /**< Symbol resolutions starts here */ +#define DF_TEXTREL 0x00000004 /**< Object contains text relocations */ +#define DF_BIND_NOW 0x00000008 /**< No lazy binding for this object */ +#define DF_STATIC_TLS 0x00000010 /**< Module uses the static TLS model */ + +/* State flags selectable in the `d_un.d_val' element of the DT_FLAGS_1 + entry in the dynamic section. */ +#define DF_1_NOW 0x00000001 /**< Set RTLD_NOW for this object. */ +#define DF_1_GLOBAL 0x00000002 /**< Set RTLD_GLOBAL for this object. */ +#define DF_1_GROUP 0x00000004 /**< Set RTLD_GROUP for this object. */ +#define DF_1_NODELETE 0x00000008 /**< Set RTLD_NODELETE for this object.*/ +#define DF_1_LOADFLTR 0x00000010 /**< Trigger filtee loading at runtime.*/ +#define DF_1_INITFIRST 0x00000020 /**< Set RTLD_INITFIRST for this object*/ +#define DF_1_NOOPEN 0x00000040 /**< Set RTLD_NOOPEN for this object. */ +#define DF_1_ORIGIN 0x00000080 /**< $ORIGIN must be handled. */ +#define DF_1_DIRECT 0x00000100 /**< Direct binding enabled. */ +#define DF_1_TRANS 0x00000200 +#define DF_1_INTERPOSE 0x00000400 /**< Object is used to interpose. */ +#define DF_1_NODEFLIB 0x00000800 /**< Ignore default lib search path. */ +#define DF_1_NODUMP 0x00001000 /**< Object can't be dldump'ed. */ +#define DF_1_CONFALT 0x00002000 /**< Configuration alternative created.*/ +#define DF_1_ENDFILTEE 0x00004000 /**< Filtee terminates filters search. */ +#define DF_1_DISPRELDNE 0x00008000 /**< Disp reloc applied at build time. */ +#define DF_1_DISPRELPND 0x00010000 /**< Disp reloc applied at run-time. */ + +/* Flags for the feature selection in DT_FEATURE_1. */ +#define DTF_1_PARINIT 0x00000001 +#define DTF_1_CONFEXP 0x00000002 + +/* Flags in the DT_POSFLAG_1 entry effecting only the next DT_* entry. */ +#define DF_P1_LAZYLOAD 0x00000001 /**< Lazyload following object. */ +#define DF_P1_GROUPPERM 0x00000002 /**< Symbols from next object are not + generally available. */ + +/* Relocation - page 1-21, figure 1-20 */ + +typedef struct { + Elf32_Addr r_offset; + Elf32_Word r_info; +} Elf32_Rel; + +typedef struct { + Elf32_Addr r_offset; + Elf32_Word r_info; + Elf32_Sword r_addend; +} Elf32_Rela; + +typedef struct { + Elf64_Addr r_offset; + Elf64_Xword r_info; +} Elf64_Rel; + +typedef struct { + Elf64_Addr r_offset; + Elf64_Xword r_info; + Elf64_Sxword r_addend; +} Elf64_Rela; + +#define ELF32_R_SYM(i) ((i)>>8) +#define ELF32_R_TYPE(i) ((unsigned char)(i)) +#define ELF32_R_INFO(s,t) (((s)<<8)+(unsigned char)(t)) + +#define ELF64_R_SYM(i) ((i)>>32) +#define ELF64_R_TYPE(i) ((i)&0xffffffffL) +#define ELF64_R_INFO(s,t) (((s)<<32)+(t)&0xffffffffL) + +/* Relocation types (processor specific) - page 1-23, figure 1-22 */ + +#define R_386_NONE 0 /**< none */ +#define R_386_32 1 /**< S + A */ +#define R_386_PC32 2 /**< S + A - P */ +#define R_386_GOT32 3 /**< G + A - P */ +#define R_386_PLT32 4 /**< L + A - P */ +#define R_386_COPY 5 /**< none */ +#define R_386_GLOB_DAT 6 /**< S */ +#define R_386_JMP_SLOT 7 /**< S */ +#define R_386_RELATIVE 8 /**< B + A */ +#define R_386_GOTOFF 9 /**< S + A - GOT */ +#define R_386_GOTPC 10 /**< GOT + A - P */ +#define R_386_32PLT 11 +#define R_386_TLS_TPOFF 14 /* Offset in static TLS block */ +#define R_386_TLS_IE 15 /* Address of GOT entry for static TLS + block offset */ +#define R_386_TLS_GOTIE 16 /* GOT entry for static TLS block + offset */ +#define R_386_TLS_LE 17 /* Offset relative to static TLS + block */ +#define R_386_TLS_GD 18 /* Direct 32 bit for GNU version of + general dynamic thread local data */ +#define R_386_TLS_LDM 19 /* Direct 32 bit for GNU version of + local dynamic thread local data + in LE code */ +#define R_386_16 20 +#define R_386_PC16 21 +#define R_386_8 22 +#define R_386_PC8 23 +#define R_386_TLS_GD_32 24 /* Direct 32 bit for general dynamic + thread local data */ +#define R_386_TLS_GD_PUSH 25 /* Tag for pushl in GD TLS code */ +#define R_386_TLS_GD_CALL 26 /* Relocation for call to + __tls_get_addr() */ +#define R_386_TLS_GD_POP 27 /* Tag for popl in GD TLS code */ +#define R_386_TLS_LDM_32 28 /* Direct 32 bit for local dynamic + thread local data in LE code */ +#define R_386_TLS_LDM_PUSH 29 /* Tag for pushl in LDM TLS code */ +#define R_386_TLS_LDM_CALL 30 /* Relocation for call to + __tls_get_addr() in LDM code */ +#define R_386_TLS_LDM_POP 31 /* Tag for popl in LDM TLS code */ +#define R_386_TLS_LDO_32 32 /* Offset relative to TLS block */ +#define R_386_TLS_IE_32 33 /* GOT entry for negated static TLS + block offset */ +#define R_386_TLS_LE_32 34 /* Negated offset relative to static + TLS block */ +#define R_386_TLS_DTPMOD32 35 /* ID of module containing symbol */ +#define R_386_TLS_DTPOFF32 36 /* Offset in TLS block */ +#define R_386_TLS_TPOFF32 37 /* Negated offset in static TLS block */ +/* Keep this the last entry. */ +#define R_386_NUM 38 + +/* ARM specific declarations */ + +/* Processor specific flags for the ELF header e_flags field. */ +#define EF_ARM_RELEXEC 0x01 +#define EF_ARM_HASENTRY 0x02 +#define EF_ARM_INTERWORK 0x04 +#define EF_ARM_APCS_26 0x08 +#define EF_ARM_APCS_FLOAT 0x10 +#define EF_ARM_PIC 0x20 +#define EF_ARM_ALIGN8 0x40 /* 8-bit structure alignment is in use */ +#define EF_ARM_NEW_ABI 0x80 +#define EF_ARM_OLD_ABI 0x100 + +/* Other constants defined in the ARM ELF spec. version B-01. */ +/* NB. These conflict with values defined above. */ +#define EF_ARM_SYMSARESORTED 0x04 +#define EF_ARM_DYNSYMSUSESEGIDX 0x08 +#define EF_ARM_MAPSYMSFIRST 0x10 +#define EF_ARM_EABIMASK 0XFF000000 + +#define EF_ARM_EABI_VERSION(flags) ((flags) & EF_ARM_EABIMASK) +#define EF_ARM_EABI_UNKNOWN 0x00000000 +#define EF_ARM_EABI_VER1 0x01000000 +#define EF_ARM_EABI_VER2 0x02000000 + +/* Additional symbol types for Thumb */ +#define STT_ARM_TFUNC 0xd + +/* ARM-specific values for sh_flags */ +#define SHF_ARM_ENTRYSECT 0x10000000 /* Section contains an entry point */ +#define SHF_ARM_COMDEF 0x80000000 /* Section may be multiply defined + in the input to a link step */ + +/* ARM-specific program header flags */ +#define PF_ARM_SB 0x10000000 /* Segment contains the location + addressed by the static base */ + +/* ARM relocs. */ +#define R_ARM_NONE 0 /* No reloc */ +#define R_ARM_PC24 1 /* PC relative 26 bit branch */ +#define R_ARM_ABS32 2 /* Direct 32 bit */ +#define R_ARM_REL32 3 /* PC relative 32 bit */ +#define R_ARM_PC13 4 +#define R_ARM_ABS16 5 /* Direct 16 bit */ +#define R_ARM_ABS12 6 /* Direct 12 bit */ +#define R_ARM_THM_ABS5 7 +#define R_ARM_ABS8 8 /* Direct 8 bit */ +#define R_ARM_SBREL32 9 +#define R_ARM_THM_PC22 10 +#define R_ARM_THM_PC8 11 +#define R_ARM_AMP_VCALL9 12 +#define R_ARM_SWI24 13 +#define R_ARM_THM_SWI8 14 +#define R_ARM_XPC25 15 +#define R_ARM_THM_XPC22 16 +#define R_ARM_COPY 20 /* Copy symbol at runtime */ +#define R_ARM_GLOB_DAT 21 /* Create GOT entry */ +#define R_ARM_JUMP_SLOT 22 /* Create PLT entry */ +#define R_ARM_RELATIVE 23 /* Adjust by program base */ +#define R_ARM_GOTOFF 24 /* 32 bit offset to GOT */ +#define R_ARM_GOTPC 25 /* 32 bit PC relative offset to GOT */ +#define R_ARM_GOT32 26 /* 32 bit GOT entry */ +#define R_ARM_PLT32 27 /* 32 bit PLT address */ +#define R_ARM_ALU_PCREL_7_0 32 +#define R_ARM_ALU_PCREL_15_8 33 +#define R_ARM_ALU_PCREL_23_15 34 +#define R_ARM_LDR_SBREL_11_0 35 +#define R_ARM_ALU_SBREL_19_12 36 +#define R_ARM_ALU_SBREL_27_20 37 +#define R_ARM_GNU_VTENTRY 100 +#define R_ARM_GNU_VTINHERIT 101 +#define R_ARM_THM_PC11 102 /* thumb unconditional branch */ +#define R_ARM_THM_PC9 103 /* thumb conditional branch */ +#define R_ARM_RXPC25 249 +#define R_ARM_RSBREL32 250 +#define R_ARM_THM_RPC22 251 +#define R_ARM_RREL32 252 +#define R_ARM_RABS22 253 +#define R_ARM_RPC24 254 +#define R_ARM_RBASE 255 +/* Keep this the last entry. */ +#define R_ARM_NUM 256 + +/* AMD x86-64 relocations. */ +#define R_X86_64_NONE 0 /* No reloc */ +#define R_X86_64_64 1 /* Direct 64 bit */ +#define R_X86_64_PC32 2 /* PC relative 32 bit signed */ +#define R_X86_64_GOT32 3 /* 32 bit GOT entry */ +#define R_X86_64_PLT32 4 /* 32 bit PLT address */ +#define R_X86_64_COPY 5 /* Copy symbol at runtime */ +#define R_X86_64_GLOB_DAT 6 /* Create GOT entry */ +#define R_X86_64_JUMP_SLOT 7 /* Create PLT entry */ +#define R_X86_64_RELATIVE 8 /* Adjust by program base */ +#define R_X86_64_GOTPCREL 9 /* 32 bit signed PC relative + offset to GOT */ +#define R_X86_64_32 10 /* Direct 32 bit zero extended */ +#define R_X86_64_32S 11 /* Direct 32 bit sign extended */ +#define R_X86_64_16 12 /* Direct 16 bit zero extended */ +#define R_X86_64_PC16 13 /* 16 bit sign extended pc relative */ +#define R_X86_64_8 14 /* Direct 8 bit sign extended */ +#define R_X86_64_PC8 15 /* 8 bit sign extended pc relative */ +#define R_X86_64_DTPMOD64 16 /* ID of module containing symbol */ +#define R_X86_64_DTPOFF64 17 /* Offset in module's TLS block */ +#define R_X86_64_TPOFF64 18 /* Offset in initial TLS block */ +#define R_X86_64_TLSGD 19 /* 32 bit signed PC relative offset + to two GOT entries for GD symbol */ +#define R_X86_64_TLSLD 20 /* 32 bit signed PC relative offset + to two GOT entries for LD symbol */ +#define R_X86_64_DTPOFF32 21 /* Offset in TLS block */ +#define R_X86_64_GOTTPOFF 22 /* 32 bit signed PC relative offset + to GOT entry for IE symbol */ +#define R_X86_64_TPOFF32 23 /* Offset in initial TLS block */ + +#define R_X86_64_NUM 24 + +/* Symbol Table Entry - page 1-17, figure 1-16 */ + +#define STN_UNDEF 0 + +/** ELF32 symbol table entry */ +typedef struct { + Elf32_Word st_name; /**< name of symbol (idx symstrtab) */ + Elf32_Addr st_value; /**< value of associated symbol */ + Elf32_Word st_size; /**< size of associated symbol */ + unsigned char st_info; /**< type and binding info */ + unsigned char st_other; /**< undefined */ + Elf32_Half st_shndx; /**< associated section header */ +} Elf32_Sym; + +/** ELF64 symbol table entry */ +typedef struct { + Elf64_Word st_name; /**< name of symbol (idx symstrtab) */ + unsigned char st_info; /**< type and binding info */ + unsigned char st_other; /**< undefined */ + Elf64_Half st_shndx; /**< associated section header */ + Elf64_Addr st_value; /**< value of associated symbol */ + Elf64_Xword st_size; /**< size of associated symbol */ +} Elf64_Sym; + +#define ELF32_ST_BIND(i) ((i)>>4) +#define ELF32_ST_TYPE(i) ((i)&0xf) +#define ELF32_ST_INFO(b,t) (((b)<<4)+((t)&0xf)) + +#define ELF64_ST_BIND(i) ((i)>>4) +#define ELF64_ST_TYPE(i) ((i)&0xf) +#define ELF64_ST_INFO(b,t) (((b)<<4)+((t)&0xf)) + +/* Symbol Binding - page 1-18, figure 1-17 */ + +#define STB_LOCAL 0 /**< not visible outside object file */ +#define STB_GLOBAL 1 /**< visible to all objects beeing combined */ +#define STB_WEAK 2 /**< resemble global symbols */ +#define STB_LOOS 10 /**< os specific */ +#define STB_HIOS 12 /**< os specific */ +#define STB_LOPROC 13 /**< proc specific */ +#define STB_HIPROC 15 /**< proc specific */ + +/* Symbol Types - page 1-19, figure 1-18 */ + +#define STT_NOTYPE 0 /**< symbol's type not specified */ +#define STT_OBJECT 1 /**< associated with a data object */ +#define STT_FUNC 2 /**< associated with a function or other code */ +#define STT_SECTION 3 /**< associated with a section */ +#define STT_FILE 4 /**< source file name associated with object */ +#define STT_LOOS 10 /**< os specific */ +#define STT_HIOS 12 /**< os specific */ +#define STT_LOPROC 13 /**< proc specific */ +#define STT_HIPROC 15 /**< proc specific */ + +enum Elf_ATs +{ + AT_NULL = 0, + AT_IGNORE = 1, + AT_EXECFD = 2, + AT_PHDR = 3, + AT_PHENT = 4, + AT_PHNUM = 5, + AT_PAGESZ = 6, + AT_BASE = 7, + AT_FLAGS = 8, + AT_ENTRY = 9, + AT_NOTELF = 10, + AT_UID = 11, + AT_EUID = 12, + AT_GID = 13, + AT_EGID = 14, + + AT_L4_AUX = 0xf0, + AT_L4_ENV = 0xf1, +}; + +typedef struct Elf32_Auxv +{ + Elf32_Word atype; + Elf32_Word avalue; +} Elf32_Auxv; + +typedef struct Elf64_Auxv +{ + Elf64_Word atype; + Elf64_Word avalue; +} Elf64_Auxv; + +/* Some helpers */ +static inline int l4util_elf_check_magic(ElfW(Ehdr) *hdr); +static inline int l4util_elf_check_arch(ElfW(Ehdr) *hdr); +static inline ElfW(Phdr) *l4util_elf_phdr(ElfW(Ehdr) *hdr); + + +/* Implemeantions */ +static inline +int l4util_elf_check_magic(ElfW(Ehdr) *hdr) +{ + return hdr->e_ident[EI_MAG0] == ELFMAG0 + && hdr->e_ident[EI_MAG1] == ELFMAG1 + && hdr->e_ident[EI_MAG2] == ELFMAG2 + && hdr->e_ident[EI_MAG3] == ELFMAG3; +} + +static inline +int l4util_elf_check_arch(ElfW(Ehdr) *hdr) +{ + return hdr->e_ident[EI_CLASS] == L4_ARCH_EI_CLASS + && hdr->e_ident[EI_DATA] == L4_ARCH_EI_DATA + && hdr->e_machine == L4_ARCH_E_MACHINE; +} + +static inline +ElfW(Phdr) *l4util_elf_phdr(ElfW(Ehdr) *hdr) +{ + return (ElfW(Phdr) *)((char *)hdr + hdr->e_phoff); +} +/*@}*/ + +#endif /* _L4_EXEC_ELF_H */ diff --git a/l4/pkg/l4util/include/getopt.h b/l4/pkg/l4util/include/getopt.h new file mode 100644 index 00000000..e729359c --- /dev/null +++ b/l4/pkg/l4util/include/getopt.h @@ -0,0 +1,107 @@ +/** + * \file + * \brief getopt + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ +#ifndef _GETOPT_H +#define _GETOPT_H + +#ifndef NULL +#define NULL 0 +#endif + +#include + +EXTERN_C_BEGIN + +/* For communication from `getopt' to the caller. + When `getopt' finds an option that takes an argument, + the argument value is returned here. + Also, when `ordering' is RETURN_IN_ORDER, + each non-option ARGV-element is returned here. */ + +extern char *optarg; + +/* Index in ARGV of the next element to be scanned. + This is used for communication to and from the caller + and for communication between successive calls to `getopt'. + + On entry to `getopt', zero means this is the first call; initialize. + + When `getopt' returns -1, this is the index of the first of the + non-option elements that the caller should itself scan. + + Otherwise, `optind' communicates from one call to the next + how much of ARGV has been scanned so far. */ + +extern int optind; + +/* Callers store zero here to inhibit the error message `getopt' prints + for unrecognized options. */ + +extern int opterr; + +/* Set to an option character which was unrecognized. */ + +extern int optopt; + +/* Describe the long-named options requested by the application. + The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector + of `struct option' terminated by an element containing a name which is + zero. + + The field `has_arg' is: + no_argument (or 0) if the option does not take an argument, + required_argument (or 1) if the option requires an argument, + optional_argument (or 2) if the option takes an optional argument. + + If the field `flag' is not NULL, it points to a variable that is set + to the value given in the field `val' when the option is found, but + left unchanged if the option is not found. + + To have a long-named option do something other than set an `int' to + a compiled-in constant, such as set a value from `optarg', set the + option's `flag' field to zero and its `val' field to a nonzero + value (the equivalent single-letter option character, if there is + one). For long options that have a zero `flag' field, `getopt' + returns the contents of the `val' field. */ + +struct option +{ + const char *name; + /* has_arg can't be an enum because some compilers complain about + type mismatches in all the code that assumes it is an int. */ + int has_arg; + int *flag; + int val; +}; + +/* Names for the values of the `has_arg' field of `struct option'. */ + +#define no_argument 0 +#define required_argument 1 +#define optional_argument 2 + +L4_CV int getopt (int argc, char *const *argv, const char *shortopts); + +L4_CV int getopt_long (int argc, char *const *argv, const char *shortopts, + const struct option *longopts, int *longind); +L4_CV int getopt_long_only (int argc, char *const *argv, + const char *shortopts, + const struct option *longopts, int *longind); + +L4_CV int _getopt_internal (int argc, char *const *argv, + const char *shortopts, + const struct option *longopts, int *longind, + int long_only); + +EXTERN_C_END + +#endif /* _GETOPT_H */ diff --git a/l4/pkg/l4util/include/keymap.h b/l4/pkg/l4util/include/keymap.h new file mode 100644 index 00000000..94b97e71 --- /dev/null +++ b/l4/pkg/l4util/include/keymap.h @@ -0,0 +1,24 @@ +/** + * \file + * \brief Event to ASCII key mapping + */ +/* + * (c) 2009 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ +#ifndef __L4UTIL__KEYMAP_H__ +#define __L4UTIL__KEYMAP_H__ + +#include + +__BEGIN_DECLS + +int l4util_map_event_to_keymap(unsigned value, unsigned shift); + +__END_DECLS + + +#endif /* __L4UTIL__KEYMAP_H__ */ diff --git a/l4/pkg/l4util/include/kip.h b/l4/pkg/l4util/include/kip.h new file mode 100644 index 00000000..637b0953 --- /dev/null +++ b/l4/pkg/l4util/include/kip.h @@ -0,0 +1,78 @@ +/** + * \file + * \ingroup l4util_kip_api + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ + +#pragma once + +#include +#include + +/** + * \defgroup l4util_kip_api Kernel Interface Page API + * \ingroup l4util_api + */ +/*@{*/ + + +EXTERN_C_BEGIN + +/** + * \brief Return whether the kernel is running native or under UX. + * + * Returns whether the kernel is running natively or under UX. The KIP will + * be mapped if not already mapped. The KIP will not be unmapped again. + * + * \return 1 when running under UX, 0 if not running under UX + */ +L4_CV int l4util_kip_kernel_is_ux(l4_kernel_info_t *); + +/** + * \brief Check if kernel supports a feature. + * + * \param str Feature name to check. + * + * \return 1 if the kernel supports the feature, 0 if not. + * + * Checks the feature field in the KIP for the given string. The KIP will be + * mapped if not already mapped. The KIP will not be unmapped again. + */ +L4_CV int l4util_kip_kernel_has_feature(l4_kernel_info_t *, const char *str); + +/** + * \brief Return kernel ABI version. + * + * \return Kernel ABI version. + */ +L4_CV unsigned long l4util_kip_kernel_abi_version(l4_kernel_info_t *); + +/** + * \brief Return end of virtual memory. + * \ingroup l4util_memdesc + * + * \return 0 if memory descriptor could not be found, + * last address of address space otherwise + */ +L4_CV l4_addr_t l4util_memdesc_vm_high(l4_kernel_info_t *kinfo); + +EXTERN_C_END + +/** + * \brief Cycle through kernel features given in the KIP. + * + * Cycles through all KIP kernel feature strings. s must be a character + * pointer (char *) initialized with l4util_kip_version_string(). + */ +#define l4util_kip_for_each_feature(s) \ + for (s += strlen(s) + 1; *s; s += strlen(s) + 1) + +/*@}*/ + diff --git a/l4/pkg/l4util/include/kprintf.h b/l4/pkg/l4util/include/kprintf.h new file mode 100644 index 00000000..cd40c21f --- /dev/null +++ b/l4/pkg/l4util/include/kprintf.h @@ -0,0 +1,29 @@ +/*****************************************************************************/ +/** + * \file + * \brief printf using the kernel debugger + * + * \date 04/05/2007 + * \author Adam Lackorzynski , + */ +/* + * (c) 2007-2009 Author(s) + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ + +#ifndef __L4UTIL__INCLUDE__KPRINTF_H__ +#define __L4UTIL__INCLUDE__KPRINTF_H__ + +#include + +EXTERN_C_BEGIN + +L4_CV int l4_kprintf(const char *fmt, ...) + __attribute__((format (printf, 1, 2))); + +EXTERN_C_END + +#endif /* ! __L4UTIL__INCLUDE__KPRINTF_H__ */ diff --git a/l4/pkg/l4util/include/list_alloc.h b/l4/pkg/l4util/include/list_alloc.h new file mode 100644 index 00000000..d99103bb --- /dev/null +++ b/l4/pkg/l4util/include/list_alloc.h @@ -0,0 +1,59 @@ +/** + * \file + * \brief Simple list-based allocator. Taken from the Fiasco kernel. + * + * \date Alexander Warg + * Frank Mehnert */ + +/* + * (c) 2003-2009 Adam Lackorzynski , + * Frank Mehnert + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ + +#ifndef L4UTIL_L4LA_H +#define L4UTIL_L4LA_H + +#include +#include + +typedef struct l4la_free_t_s +{ + struct l4la_free_t_s *next; + l4_size_t size; +} l4la_free_t; + +#define L4LA_INITIALIZER { 0 } + +EXTERN_C_BEGIN + +/** Add free memory to memory pool. + * \param first list identifier + * \param block address of unused memory block + * \param size size of memory block */ +L4_CV void l4la_free(l4la_free_t **first, void *block, l4_size_t size); + +/** Allocate memory from pool. + * \param first list identifier + * \param size length of memory block to allocate + * \param align alignment */ +L4_CV void* l4la_alloc(l4la_free_t **first, l4_size_t size, unsigned align); + +/** Show all list members. + * \param first list identifier */ +L4_CV void l4la_dump(l4la_free_t **first); + +/** Init memory pool. + * \param first list identifier */ +L4_CV void l4la_init(l4la_free_t **first); + +/** Show available memory in pool. + * \param first list identifier */ +L4_CV l4_size_t l4la_avail(l4la_free_t **first); + +EXTERN_C_END + +#endif diff --git a/l4/pkg/l4util/include/llulc.h b/l4/pkg/l4util/include/llulc.h new file mode 100644 index 00000000..b30eeb88 --- /dev/null +++ b/l4/pkg/l4util/include/llulc.h @@ -0,0 +1,47 @@ +/* + * (c) 2011 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +/* + * Note, do _NOT_ use this lock unless you got advised to do so. + */ +#pragma once + +#include +#include + +__BEGIN_DECLS + +struct l4lllock_struct_t; +typedef struct l4ullulock_struct_t l4ullulock_t; + +#ifdef __cplusplus +#define DEFAULT_UTCB = l4_utcb() +#else +#define DEFAULT_UTCB +#endif + +int l4ullulock_init(l4ullulock_t **t, + void *(*mem_alloc)(size_t x), + void (*mem_free)(void *p), + l4_cap_idx_t (*cap_alloc)(void), + void (*cap_free)(l4_cap_idx_t c), + l4_cap_idx_t factory); +int l4ullulock_deinit(l4ullulock_t *t); +int l4ullulock_lock(l4ullulock_t *t, l4_utcb_t *u DEFAULT_UTCB); +int l4ullulock_unlock(l4ullulock_t *t, l4_utcb_t *u DEFAULT_UTCB); + +__END_DECLS diff --git a/l4/pkg/l4util/include/lock.h b/l4/pkg/l4util/include/lock.h new file mode 100644 index 00000000..504c270d --- /dev/null +++ b/l4/pkg/l4util/include/lock.h @@ -0,0 +1,69 @@ +/*****************************************************************************/ +/** + * \file + * \brief Simple lock implementation. + * Does only work if all thread have the same priority! + * + * \date 02/1997 + * \author Michael Hohmuth */ +/* + * (c) 2000-2009 Author(s) + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ + +/*****************************************************************************/ +#ifndef __L4UTIL_LOCK_H__ +#define __L4UTIL_LOCK_H__ + +#include +#include +#include + +EXTERN_C_BEGIN + +typedef l4_uint32_t l4util_simple_lock_t; + +L4_INLINE int l4_simple_try_lock(l4util_simple_lock_t *lock); +L4_INLINE void l4_simple_unlock(l4util_simple_lock_t *lock); +L4_INLINE int l4_simple_lock_locked(l4util_simple_lock_t *lock); +L4_INLINE void l4_simple_lock_solid(register l4util_simple_lock_t *p); +L4_INLINE void l4_simple_lock(l4util_simple_lock_t * lock); + +L4_INLINE int +l4_simple_try_lock(l4util_simple_lock_t *lock) +{ + return l4util_xchg32(lock, 1) == 0; +} + +L4_INLINE void +l4_simple_unlock(l4util_simple_lock_t *lock) +{ + *lock = 0; +} + +L4_INLINE int +l4_simple_lock_locked(l4util_simple_lock_t *lock) +{ + return (*lock == 0) ? 0 : 1; +} + +L4_INLINE void +l4_simple_lock_solid(register l4util_simple_lock_t *p) +{ + while (l4_simple_lock_locked(p) || !l4_simple_try_lock(p)) + l4_thread_switch(L4_INVALID_CAP); +} + +L4_INLINE void +l4_simple_lock(l4util_simple_lock_t * lock) +{ + if (!l4_simple_try_lock(lock)) + l4_simple_lock_solid(lock); +} + +EXTERN_C_END + +#endif diff --git a/l4/pkg/l4util/include/lock_wq.h b/l4/pkg/l4util/include/lock_wq.h new file mode 100644 index 00000000..e9a44491 --- /dev/null +++ b/l4/pkg/l4util/include/lock_wq.h @@ -0,0 +1,134 @@ +/*****************************************************************************/ +/** + * \file + * \brief Better lock implementation (in comparison to lock.h). In the + * case of contention we are going into sleep and wait for the + * current locker to be woken up. Nevertheless this code has + * some limitations considering different thread priorities. + * + * \author Jork Loeser */ + +/* + * (c) 2003-2009 Author(s) + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ + +#ifndef __L4UTIL_LOCK_WQ_H__ +#define __L4UTIL_LOCK_WQ_H__ + +#include +//#include +#include +#include + +EXTERN_C_BEGIN + +typedef struct l4util_wq_lock_queue_elem_t +{ + volatile struct l4util_wq_lock_queue_elem_t *next, *prev; + l4_cap_idx_t id; +} l4util_wq_lock_queue_elem_t; + +typedef struct +{ + l4util_wq_lock_queue_elem_t *last; +} l4util_wq_lock_queue_base_t; + +static inline int +l4util_wq_lock_lock(l4util_wq_lock_queue_base_t *queue, + l4util_wq_lock_queue_elem_t *q, + l4_cap_idx_t myself); +static inline int +l4util_wq_lock_unlock(l4util_wq_lock_queue_base_t *queue, + l4util_wq_lock_queue_elem_t *q); +static inline int +l4util_wq_lock_locked(l4util_wq_lock_queue_base_t *queue); + +/* Implementation */ +inline int +l4util_wq_lock_lock(l4util_wq_lock_queue_base_t *queue, + l4util_wq_lock_queue_elem_t *q, + l4_cap_idx_t myself) +{ + l4util_wq_lock_queue_elem_t *old; + l4_msgtag_t err; + + q->next = 0; + q->id = myself; + old = (l4util_wq_lock_queue_elem_t*) + l4util_xchg((l4_umword_t*)(&queue->last), (l4_umword_t)q); + if (old != 0) + { + /* already locked */ + old->next = q; + q->prev = old; + err = l4_ipc_receive(old->id, L4_IPC_NEVER); + if (L4_IPC_ERROR(l4_utcb()->error)) + return l4_utcb()->error; + err = l4_ipc_send(old->id, l4_msgtag(0, 0, 0, 0), L4_IPC_NEVER); + if (L4_IPC_ERROR(l4_utcb()->error)) + return l4_utcb()->error; + } + return 0; +} + +inline int +l4util_wq_lock_unlock(l4util_wq_lock_queue_base_t *queue, + l4util_wq_lock_queue_elem_t *q) +{ + volatile l4util_wq_lock_queue_elem_t *other; + l4_msgtag_t err; + + other = (l4util_wq_lock_queue_elem_t*) + l4util_cmpxchg_res((l4_umword_t*)(&queue->last), + (l4_umword_t)q, + (l4_umword_t)NULL); + if (other == q) + { + /* nobody wants the lock */ + } + else + { + /* someone wants the lock */ + while(q->next != other) + { + /* 2 possibilities: + - other is next, but didn't sign, give it the time + - other is not next, find the next by backward iteration */ + if (other->prev == NULL) + { + /* - other didn't sign its prev, give it the time to do this */ + //l4_thread_switch(other->id); + // FIXME: what to do? + } + else if (other->prev!=q) + { + /* 2 poss: + - if other is next it might be signed up to now + (other->prev == q) + - other is not something else then next (its not NULL, + we know this), go backward */ + other = other->prev; + } + } + /* now we have the next in other */ + /* send an ipc, timeout never */ + err = l4_ipc_call(q->next->id, l4_msgtag(0, 0, 0, 0), L4_IPC_NEVER); + if (L4_IPC_IS_ERROR(l4_utcb()->error)) + return L4_IPC_ERROR(l4_utcb()->error); + } + return 0; +} + +inline int +l4util_wq_lock_locked(l4util_wq_lock_queue_base_t *queue) +{ + return queue->last != NULL; +} + +EXTERN_C_END + +#endif diff --git a/l4/pkg/l4util/include/macros.h b/l4/pkg/l4util/include/macros.h new file mode 100644 index 00000000..8ec7fb2b --- /dev/null +++ b/l4/pkg/l4util/include/macros.h @@ -0,0 +1,130 @@ +/** + * \file + * \brief Utility macros. + */ +/* + * (c) 2000-2009 Adam Lackorzynski , + * Frank Mehnert , + * Lars Reuther + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ +/*****************************************************************************/ +/*****************************************************************************/ +#ifndef _L4UTIL_MACROS_H +#define _L4UTIL_MACROS_H + +/* L4 includes */ +#include +#include +#include + +/***************************************************************************** + *** generic macros + *****************************************************************************/ + +#ifdef ___________MOVED_TO_LOG_PKG + +/* print message and enter kernel debugger */ +#ifndef Panic + +// Don't include here, leads to trouble. +// Don't use exit() here since we want to terminate ASAP. +// We might be executed in context of the region manager. +EXTERN_C_BEGIN +void _exit(int status) __attribute__ ((__noreturn__)); +EXTERN_C_END + +# ifdef L4BID_RELEASE_MODE +# define Panic(args...) do \ + { \ + LOG(args); \ + LOG_flush(); \ + _exit(-1); \ + } \ + while (1) +# else +# define Panic(args...) do \ + { \ + LOG(args); \ + LOG_flush(); \ + enter_kdebug("PANIC, 'g' for exit");\ + _exit(-1); \ + } \ + while (1) +# endif +#endif + +/* assertion */ +#ifndef Assert +# define Assert(expr) do \ + { \ + if (!(expr)) \ + { \ + LOG_printf(#expr "\n"); \ + Panic("Assertion failed"); \ + } \ + } \ + while (0) +#endif + +/* enter kernel debugger */ +#ifndef Kdebug +# define Kdebug(args...) do \ + { \ + LOG(args); \ + LOG_flush(); \ + enter_kdebug("KD"); \ + } \ + while (0) +#endif +#endif + +/***************************************************************************** + *** debug stuff (to be removed, use LOG* macros instead!) + *****************************************************************************/ + +/* we use our own debug macros */ +#ifdef KDEBUG +# undef KDEBUG +#endif +#ifdef ASSERT +# undef ASSERT +#endif +#ifdef PANIC +# undef PANIC +#endif + +#ifdef DEBUG + +#define KDEBUG(args...) do \ + { \ + LOGl(args); \ + LOG_flush(); \ + enter_kdebug("KD"); \ + } \ + while (0) + +#ifdef DEBUG_ASSERTIONS +# define ASSERT(expr) Assert(expr) +#else +# define ASSERT(expr) do {} while (0) +#endif + +#ifdef DEBUG_ERRORS +# define PANIC(format, args...) Panic(format, ## args) +#else +# define PANIC(args...) do {} while (0) +#endif + +#else /* !DEBUG */ + +#define KDEBUG(args...) do {} while (0) +#define ASSERT(expr) do {} while (0) +#define PANIC(args...) do {} while (0) + +#endif /* !DEBUG */ + +#endif /* !_L4UTIL_MACROS_H */ diff --git a/l4/pkg/l4util/include/mb_info.h b/l4/pkg/l4util/include/mb_info.h new file mode 100644 index 00000000..ca486e0c --- /dev/null +++ b/l4/pkg/l4util/include/mb_info.h @@ -0,0 +1,301 @@ +/** + * \file + * + * \brief Multiboot info structure as defined by GRUB */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Frank Mehnert + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ + +#ifndef L4UTIL_MB_INFO_H +#define L4UTIL_MB_INFO_H + +#ifndef __ASSEMBLY__ + +#include + +/** + * \anchor struct_l4util_mod_list + * The structure type "mod_list" is used by the + * \ref struct_l4util_mb_info "multiboot_info" structure. + */ + +typedef struct +{ + l4_uint32_t mod_start; /**< Starting address of module in memory. */ + l4_uint32_t mod_end; /**< End address of module in memory. */ + l4_uint32_t cmdline; /**< Module command line */ + l4_uint32_t pad; /**< padding to take it to 16 bytes */ +} l4util_mb_mod_t; + + +/** + * INT-15, AX=E820 style "AddressRangeDescriptor" + * ...with a "size" parameter on the front which is the structure size - 4, + * pointing to the next one, up until the full buffer length of the memory + * map has been reached. + */ + +typedef struct __attribute__((packed)) +{ + l4_uint32_t struct_size; /** mmap_addr; \ + (unsigned long)i < mbi->mmap_addr + mbi->mmap_length; \ + i = (l4util_mb_addr_range_t *)((unsigned long)i + mmap->struct_size + sizeof (mmap->struct_size))) + +/** usable memory "Type", all others are reserved. */ +#define MB_ARD_MEMORY 1 + +/** + * Address Range Types (ART) from "Advanced Configuration and Power Interface + * Specification" Rev3.0a (p. 390). Other values are undefined. + */ +#define MB_ART_MEMORY 1 /**< available, usable RAM */ +#define MB_ART_RESERVED 2 /**< in use or reserved by system */ +#define MB_ART_ACPI 3 /**< ACPI Reclaim Memory (RAM that contains + ACPI tables) */ +#define MB_ART_NVS 4 /**< ACPI NVS Memory (must not be used by the OS */ +#define MB_ART_UNUSABLE 5 /**< memory in which errores have been detected */ + + +/** Drive Info structure. */ +typedef struct +{ + l4_uint32_t size; /** = VESA version 1.2 + * @{ */ + l4_uint16_t x_resolution; + l4_uint16_t y_resolution; + l4_uint8_t x_char_size; + l4_uint8_t y_char_size; + l4_uint8_t number_of_planes; + l4_uint8_t bits_per_pixel; + l4_uint8_t number_of_banks; + l4_uint8_t memory_model; + l4_uint8_t bank_size; + l4_uint8_t number_of_image_pages; + l4_uint8_t reserved0; + /** @} */ + + /** @name direct color + * @{ */ + l4_uint8_t red_mask_size; + l4_uint8_t red_field_position; + l4_uint8_t green_mask_size; + l4_uint8_t green_field_position; + l4_uint8_t blue_mask_size; + l4_uint8_t blue_field_position; + l4_uint8_t reserved_mask_size; + l4_uint8_t reserved_field_position; + l4_uint8_t direct_color_mode_info; + /** @} */ + + /** @name >= VESA version 2.0 + * @{*/ + l4_uint32_t phys_base; + l4_uint32_t reserved1; + l4_uint16_t reversed2; + /** @} */ + + /** @name >= VESA version 3.0 + * @{*/ + l4_uint16_t linear_bytes_per_scanline; + l4_uint8_t banked_number_of_image_pages; + l4_uint8_t linear_number_of_image_pages; + l4_uint8_t linear_red_mask_size; + l4_uint8_t linear_red_field_position; + l4_uint8_t linear_green_mask_size; + l4_uint8_t linear_green_field_position; + l4_uint8_t linear_blue_mask_size; + l4_uint8_t linear_blue_field_position; + l4_uint8_t linear_reserved_mask_size; + l4_uint8_t linear_reserved_field_position; + l4_uint32_t max_pixel_clock; + + /* The VBE spec says this structure should have a size of 256 bytes but + * the described structure layout is only 255 bytes... */ + l4_uint8_t reserved3[189 + 1]; + /** @} */ +} __attribute__ ((packed)) l4util_mb_vbe_mode_t; + + +/** + * \anchor struct_l4util_mb_info + * MultiBoot Info description + * + * This is the struct passed to the boot image. This is done by placing + * its address in the EAX register. + */ + +typedef struct +{ + l4_uint32_t flags; /**< MultiBoot info version number */ + l4_uint32_t mem_lower; /**< available memory below 1MB */ + l4_uint32_t mem_upper; /**< available memory starting from 1MB [kB] */ + l4_uint32_t boot_device; /**< "root" partition */ + l4_uint32_t cmdline; /**< Kernel command line */ + l4_uint32_t mods_count; /**< number of modules */ + l4_uint32_t mods_addr; /**< module list */ + + union + { + struct + { + /** (a.out) Kernel symbol table info */ + l4_uint32_t tabsize; + l4_uint32_t strsize; + l4_uint32_t addr; + l4_uint32_t pad; + } + a; + + struct + { + /** (ELF) Kernel section header table */ + l4_uint32_t num; + l4_uint32_t size; + l4_uint32_t addr; + l4_uint32_t shndx; + } + e; + } + syms; + + l4_uint32_t mmap_length; /**< size of memory mapping buffer */ + l4_uint32_t mmap_addr; /**< address of memory mapping buffer */ + l4_uint32_t drives_length; /**< size of drive info buffer */ + l4_uint32_t drives_addr; /**< address of driver info buffer */ + l4_uint32_t config_table; /**< ROM configuration table */ + l4_uint32_t boot_loader_name; /**< Boot Loader Name */ + l4_uint32_t apm_table; /**< APM table */ + l4_uint32_t vbe_ctrl_info; /**< VESA video contoller info */ + l4_uint32_t vbe_mode_info; /**< VESA video mode info */ + l4_uint16_t vbe_mode; /**< VESA video mode number */ + l4_uint16_t vbe_interface_seg; /**< VESA segment of prot BIOS interface */ + l4_uint16_t vbe_interface_off; /**< VESA offset of prot BIOS interface */ + l4_uint16_t vbe_interface_len; /**< VESA lenght of prot BIOS interface */ +} l4util_mb_info_t; + +#endif /* ! __ASSEMBLY__ */ + +/** + * Flags to be set in the 'flags' parameter above + */ + +/** is there basic lower/upper memory information? */ +#define L4UTIL_MB_MEMORY 0x00000001 + +/** is there a boot device set? */ +#define L4UTIL_MB_BOOTDEV 0x00000002 + +/** is the command-line defined? */ +#define L4UTIL_MB_CMDLINE 0x00000004 + +/** are there modules to do something with? */ +#define L4UTIL_MB_MODS 0x00000008 + +/* These next two are mutually exclusive */ +/** is there a symbol table loaded? */ +#define L4UTIL_MB_AOUT_SYMS 0x00000010 + +/** is there an ELF section header table? */ +#define L4UTIL_MB_ELF_SHDR 0x00000020 + +/** is there a full memory map? */ +#define L4UTIL_MB_MEM_MAP 0x00000040 + +/** Is there drive info? */ +#define L4UTIL_MB_DRIVE_INFO 0x00000080 + +/** Is there a config table? */ +#define L4UTIL_MB_CONFIG_TABLE 0x00000100 + +/** Is there a boot loader name? */ +#define L4UTIL_MB_BOOT_LOADER_NAME 0x00000200 + +/** Is there a APM table? */ +#define L4UTIL_MB_APM_TABLE 0x00000400 + +/** Is there video information? */ +#define L4UTIL_MB_VIDEO_INFO 0x00000800 + + +/** If we are multiboot-compliant, this value is present in the eax register */ +#define L4UTIL_MB_VALID 0x2BADB002UL +#define L4UTIL_MB_VALID_ASM 0x2BADB002 + + +#endif + diff --git a/l4/pkg/l4util/include/parse_cmd.h b/l4/pkg/l4util/include/parse_cmd.h new file mode 100644 index 00000000..d18d4c3c --- /dev/null +++ b/l4/pkg/l4util/include/parse_cmd.h @@ -0,0 +1,149 @@ +/** + * \file + * \brief comfortable command-line parsing + * + * \date 2002 + * \author Jork Loeser + */ + +/* + * (c) 2003-2009 Author(s) + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ + +#ifndef __PARSE_CMD_H +#define __PARSE_CMD_H + +#include +#include + +/** + * \defgroup l4util_parse_cmd Comfortable Command Line Parsing + * \ingroup l4util_api + */ +/*@{*/ + +/** + * \brief Types for parsing + */ +enum parse_cmd_type { + PARSE_CMD_INT, + PARSE_CMD_SWITCH, + PARSE_CMD_STRING, + PARSE_CMD_FN, + PARSE_CMD_FN_ARG, + PARSE_CMD_INC, + PARSE_CMD_DEC, +}; + +/** + * \brief Function type for PARSE_CMD_FN + */ +typedef L4_CV void (*parse_cmd_fn_t)(int); + +/** + * \brief Function type for PARSE_CMD_FN_ARG + */ +typedef L4_CV void (*parse_cmd_fn_arg_t)(int, const char*, int); + +EXTERN_C_BEGIN + +/** Parse the command-line for specified arguments and store the values into + * variables. + * + * This Functions gets the command-line, and a list of + * command-descriptors. Then, the command-line is parsed according to + * the given descriptors, storing strings, switches and numeric + * arguments at given addresses, and possibly calling specified + * functions. A default help descriptor is added. Its purpose is to + * present a short command overview in the case the given command-line + * does not fit to the descriptors. + * + * Each command-descriptor has the following form: + * + * \e short \e option \e char, \e long \e option \e name, + * \e comment, \e type, \e val, \e addr. + * + * The \e short \e option \e char specifies the short form of the + * described option. The short form will be recognized after a single + * dash, or in a group of short options preceeded by a single dash. + * Specify ' ' if no short form should be used. + * + * The \e long \e option \e name specifies the long form of the + * described option. The long form will be recognized after two + * dashes. Specify 0 if no long form should be used for this option. + * + * The \e comment is a string that will be used when presenting the short + * command-line help. + * + * The \e type specifies, if the option should be recognized as + * - a number (\c PARSE_CMD_INT), + * - a switch (\c PARSE_CMD_SWITCH), + * - a string (\c PARSE_CMD_STRING), + * - a function call (\c PARSE_CMD_FN, \c PARSE_CMD_FN_ARG), + * - an increment/decrement operator (\c PARSE_CMD_INC, \c PARSE_CMD_DEC). + * + * If type is \c PARSE_CMD_INT, the option requires a second argument + * on the command-line after the option. This argument is parsed as a + * number. It can be preceeded by 0x to present a hex-value or by 0 to + * present an octal form. \e addr is interpreted as an int-pointer. + * The scanned argument from the command-line is stored in this + * pointer. + * + * If \e type is \c PARSE_CMD_SWITCH, \e addr must be a pointer to + * int, and the value from \e val is stored at this pointer. + * + * With \c PARSE_CMD_STRING, an additional argument is expected at the + * cmdline. \e addr must be a pointer to const char*, and a pointer to + * the argument on the command line is stored at this pointer. The + * value in \e val is a default value, which is stored at \e addr if + * the corresponding option is not given on the command line. + * + * \With \c PARSE_CMD_FN_ARG, \e addr is interpreted as a function + * pointer of type #parse_cmd_fn_t. It will be called with \e val as + * argument if the corresponding option is found. + * + * If \e type is \c PARSE_CMD_FN_ARG, \e addr is as a function pointer + * of type #parse_cmd_fn_arg_t, and handled similar to + * \c PARSE_CMD_FN. An additional argument is expected at the command + * line, however. It is given to the called function as 2nd argument, + * and parsed as an integer as with \c PARSE_CMD_INT as a third + * argument. + * + * If \e type is \c PARSE_CMD_INC or \c PARSE_CMD_DEC, \e addr is + * interpreted as an int-pointer. The value of \e val is stored to + * this pointer first. For every occurence of the option in the + * command line, the integer referenced by \e addr is incremented or + * decremented, respectively. + * + * The list of command-descriptors is terminated by specifying a binary 0 for + * the short option char. + * + * Note: The short option char 'h' and the long option name "help" must not be + * specified. They are used for the default help descriptor and produce a short + * command-options help when specified on the command-line. + * + * \param argc pointer to number of command line parameters as passed to main + * \param argv pointer to array of command line parameters as passed to main + * \param arg0 format list describing the command line options to parse for + * \return 0 if the command-line was successfully parsed, otherwise: + * - -1 if the given descriptors are somehow wrong. + * - -2 if not enough memory was available to hold temporary structs. + * - -3 if the given command-line args did not meet the specified set. + * - -4 if the help-option was given. + * + * Upon return, argc and argv point to a list of arguments that were not + * scanned as arguments. See \c getoptlong for details on scanning. */ +L4_CV int parse_cmdline(int *argc, const char***argv, char arg0, ...); +L4_CV int parse_cmdlinev(int *argc, const char***argv, char arg0, va_list va); +L4_CV int parse_cmdline_extra(const char*argv0, const char*line, char delim, + char arg0,...); + +EXTERN_C_END +/*@}*/ + +#endif + diff --git a/l4/pkg/l4util/include/prio.h b/l4/pkg/l4util/include/prio.h new file mode 100644 index 00000000..2c718fc5 --- /dev/null +++ b/l4/pkg/l4util/include/prio.h @@ -0,0 +1,59 @@ +/*! + * \file + * \brief Thread priority related functions. + * + * \date 11/22/2005 + * \author Adam Lackorzynski + * + */ +/* + * (c) 2004-2009 Author(s) + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ +#ifndef __L4UTIL__PRIO_H__ +#define __L4UTIL__PRIO_H__ + +#include + +EXTERN_C_BEGIN + +/** + * \defgroup l4util_prio Priority related functions + * \ingroup l4util_api + */ +/*@{*/ + +/** + * \brief Set priority of a thread. + * + * \param id Id of the thread to set the priority for + * \param prio Priority of the thread. + * + * \return 0 for success, !0 for failure. + */ +static inline int +l4util_prio_thread_set(l4_threadid_t id, unsigned prio) +{ + l4_sched_param_t p; + l4_threadid_t dummy = L4_INVALID_ID; + + l4_thread_schedule(id, L4_INVALID_SCHED_PARAM, &dummy, &dummy, &p); + + if (!l4_is_invalid_sched_param(p)) + { + p.sp.prio = prio; + p.sp.state = 0; + l4_thread_schedule(id, p, &dummy, &dummy, &p); + if (!l4_is_invalid_sched_param(p)) + return 0; + } + + return 1; +} +/*@}*/ +EXTERN_C_END + +#endif /* ! __L4UTIL__PRIO_H__ */ diff --git a/l4/pkg/l4util/include/queue.h b/l4/pkg/l4util/include/queue.h new file mode 100644 index 00000000..59e24eec --- /dev/null +++ b/l4/pkg/l4util/include/queue.h @@ -0,0 +1,37 @@ +/** + * \file + * \brief Queue + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg , + * Frank Mehnert + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ +#ifndef __L4UTIL_QUEUE_H__ +#define __L4UTIL_QUEUE_H__ + +#include +#include + +EXTERN_C_BEGIN + +struct l4util_buffer_head +{ + l4_threadid_t src; + l4_uint32_t len; + char *buffer; +}; + +L4_CV int l4util_queue_dequeue(struct l4util_buffer_head **buffer); + +L4_CV int l4util_queue_init(int queue_threadno, + void *(*malloc_func)(l4_uint32_t size), + l4_uint32_t max_rcv); + +EXTERN_C_END + +#endif /* !__L4UTIL_QUEUE_H__ */ diff --git a/l4/pkg/l4util/include/rand.h b/l4/pkg/l4util/include/rand.h new file mode 100644 index 00000000..15bda230 --- /dev/null +++ b/l4/pkg/l4util/include/rand.h @@ -0,0 +1,51 @@ +/** + * \file + * \brief Simple Pseudo-Random Number Generator + * \ingroup l4util_api + * + * \date 1998 + * \author Lars Reuther */ +/* + * (c) 2008-2009 Author(s) + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ + +#ifndef __L4UTIL_RAND_H +#define __L4UTIL_RAND_H + +#define L4_RAND_MAX 65535 + +#include +#include + +EXTERN_C_BEGIN + +/** + * \defgroup l4util_random Random number support + * \ingroup l4util_api + */ + +/** + * \brief Deliver next random number + * \ingroup l4util_random + * + * \return A new random number + */ +L4_CV l4_uint32_t +l4util_rand(void); + +/** + * \brief Initialize random number generator + * \ingroup l4util_random + * + * \param seed Value to initialize + */ +L4_CV void +l4util_srand (l4_uint32_t seed); + +EXTERN_C_END + +#endif /* __L4UTIL_RAND_H */ diff --git a/l4/pkg/l4util/include/reboot.h b/l4/pkg/l4util/include/reboot.h new file mode 100644 index 00000000..3631f770 --- /dev/null +++ b/l4/pkg/l4util/include/reboot.h @@ -0,0 +1,33 @@ +/** + * \file + * \brief Machine restarting functions. + */ +/* + * (c) 2000-2009 Adam Lackorzynski , + * Alexander Warg , + * Norman Feske + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ +/*****************************************************************************/ +#ifndef _L4UTIL_REBOOT_H +#define _L4UTIL_REBOOT_H + +#include + +/** + * \defgroup l4util_reboot Machine Restarting Function + * \ingroup l4util_api + */ + +/** + * \brief Machine reboot + * \ingroup l4util_reboot + */ +EXTERN_C_BEGIN +L4_CV void l4util_reboot(void) __attribute__ ((__noreturn__)); +EXTERN_C_END + +#endif /* ! _L4UTIL_REBOOT_H */ diff --git a/l4/pkg/l4util/include/sll.h b/l4/pkg/l4util/include/sll.h new file mode 100644 index 00000000..770c1784 --- /dev/null +++ b/l4/pkg/l4util/include/sll.h @@ -0,0 +1,286 @@ +/** + * \file + * \brief List implemenation + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Ronald Aigner + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ +#ifndef __L4UTIL__SLL_H__ +#define __L4UTIL__SLL_H__ + +#include + +#include + +EXTERN_C_BEGIN + +/* + * the linked list structure + */ + +typedef struct slist_t +{ + struct slist_t *next; /* pointer to next node */ + void *data; /* void pointer for user data */ +} slist_t; + +/* + * function prototypes + */ +static inline slist_t* +list_new_entry(void *data); + +static inline slist_t* +list_append(slist_t *list, slist_t *new_node); + +static inline slist_t* +list_remove(slist_t *list, slist_t *node); + +static inline void +list_free_entry(slist_t **list); + +static inline unsigned char +list_is_empty(slist_t *list); + +static inline slist_t* +list_get_at(slist_t *list, int n); + +static inline slist_t* +list_add(slist_t *list, slist_t *new_node); + +static inline void +list_insert_after(slist_t *after, slist_t *new_node); + +static inline int +list_elements(slist_t *head); + +/* + * allocateNode() + * allocate a new node. + * + * Parameters: + * void *data a generic pointer to object data + * + * Return Values: + * pointer to slist_t if succeeds + * NULL otherwise + * + */ +static inline slist_t* +list_new_entry(void *data) +{ + slist_t *sll; + + sll = malloc(sizeof(slist_t)); + if (!sll) + return ((slist_t *) NULL); + + sll->data=data; + sll->next=NULL; + + return (sll); +} + +/* + * appendNode() + * appends a node to the end of a list + * + * Parameters: + * slist_t *head - modify the list + * slist_t *new - appends this node + * + * Return Values: + * the new list + * + */ +static inline slist_t* +list_append(slist_t *head, slist_t *new_node) +{ + slist_t *ret = head; + if (!head) + return new_node; + + while (head->next) + head = head->next; + head->next = new_node; + return ret; +} + +/* + * insertNode() + * insert a node at the beginning of a list + * + * Parameters: + * slist_t *head - modify this list + * slist_t *new - appends this node + * + * Return Values: + * the new list + * + */ +static inline slist_t* +list_add(slist_t *head, slist_t *new_node) +{ + if (!new_node) + return head; + new_node->next = head; + return new_node; +} + +/* + * insertNode() + * insert a node at the beginning of a list + * + * Parameters: + * slist_t *head - modify this list + * slist_t *new - appends this node + * + * Return Values: + * the new list + * + */ +static inline void +list_insert_after(slist_t *after, slist_t *new_node) +{ + if (!new_node) + return; + if (!after) + return; + new_node->next = after->next; + after->next = new_node; +} + + +/* + * emptyList() + * check if a list variable is NULL + * + * Parameters: + * slist_t *list list + * + * Return Values: + * TRUE if empty + * FALSE if not empty + * + */ +static inline unsigned char +list_is_empty(slist_t *list) +{ + return ((list) ? 0 : 1); +} + +/* + * delNode() + * remove a node from a list + * + * Parameters: + * slist_t *head - list to modify + * slist_t *node - node to remove + * + * Return Values: + * none + * + */ +static inline slist_t* +list_remove(slist_t *head, slist_t *node) +{ + slist_t *ret = head; + if (list_is_empty(head)) + return ret; + if (!node) + return ret; + + if (head == node) + { + ret = head->next; + } + else + { + while (head && (head->next != node)) + head = head->next; + if (!head) + return ret; + else + head->next = node->next; + } + list_free_entry(&node); + return ret; +} + +/* + * freeNode() + * frees a node + * + * Parameters: + * slist_t *list node to free + * + * Return Values: + * none + * + */ +static inline void +list_free_entry(slist_t **list) +{ + if (*list) + { + free ((void *) (*list)); + (*list)=NULL; + } +} + + +/* + * getNthNode() + * get nth node in a list + * + * Parameters: + * slist_t *list - the head list + * int n - return the node + * Return Values: + * a pointer to the list at position n + * NULL if there's no such node at posion n + * + */ +static inline slist_t* +list_get_at(slist_t *list, int n) +{ + int j=0; + + while (list) + { + j++; + if (j == n) + return (list); + list = list->next; + } + + return ((slist_t *) NULL); +} + +/* + * numNodes() + * returns number of nodes in the list + * + * Parameters: + * slist_t *head - the head node of the list + * + * Return Values: + * number of node/s + * + */ +static inline int +list_elements(slist_t *head) +{ + register int n; + for (n=0; head; head=head->next) n++; + return (n); +} + +EXTERN_C_END + +#endif /* __L4UTIL__SLL_H__ */ diff --git a/l4/pkg/l4util/include/slmap.h b/l4/pkg/l4util/include/slmap.h new file mode 100644 index 00000000..d15bf12f --- /dev/null +++ b/l4/pkg/l4util/include/slmap.h @@ -0,0 +1,99 @@ +/** + * \file + * \brief Map implementation + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Ronald Aigner + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ +#ifndef SLMAP_H +#define SLMAP_H + +#include + +#include + +EXTERN_C_BEGIN + +/* + * the map structure + * + * its basically a single linked list with a + * key and a data entry + */ +typedef struct slmap_t +{ + struct slmap_t* next; /* pointer to next entry */ + void *key; /* the key of the map entry */ + unsigned key_size; /* the size of the key entry */ + void *data; /* the data of the map entry */ +} slmap_t; + +/* + * function prototypes + */ + +L4_CV slmap_t* +map_new_entry(void* key, unsigned key_size, void *data); + +L4_CV slmap_t* +map_new_sentry(char* key, void* data); + +L4_CV slmap_t* +map_append(slmap_t* list, slmap_t* new_entry); + +L4_CV slmap_t* +map_remove(slmap_t* list, slmap_t* entry); + +L4_CV void +map_free_entry(slmap_t** entry); + +L4_CV slmap_t* +map_get_at(slmap_t* list, int n); + +L4_CV slmap_t* +map_add(slmap_t* list, slmap_t* new_entry); + +L4_CV void +map_insert_after(slmap_t* after, slmap_t* new_entry); + +L4_CV slmap_t* +map_find(slmap_t* list, void* key, unsigned key_size); + +L4_CV slmap_t* +map_sfind(slmap_t* list, const char* key); + +/* + * implementatic of static inline + */ + +static inline unsigned char +map_is_empty(slmap_t* list) +{ + return (list) ? 0 : 1; +} + +static inline void +map_free(slmap_t **list) +{ + while (*list) + *list = map_remove(*list, *list); +} + +static inline int +map_elements(slmap_t* list) +{ + register int n; + for (n=0; list; list=list->next) + n++; + return n; +} + +EXTERN_C_END + +#endif /* SLMAP_H */ + diff --git a/l4/pkg/l4util/include/splitlog2.h b/l4/pkg/l4util/include/splitlog2.h new file mode 100644 index 00000000..eaf1865c --- /dev/null +++ b/l4/pkg/l4util/include/splitlog2.h @@ -0,0 +1,82 @@ +/** + * \file + * \brief Split a range in log2 aligned and size-aligned chunks. + */ +/* + * (c) 2008-2009 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ +#ifndef __L4UTIL__INCLUDE__SPLITLOG2_H__ +#define __L4UTIL__INCLUDE__SPLITLOG2_H__ + +#include +#include +#include + +EXTERN_C_BEGIN + +/** + * \brief Split a range into log2 base and size aligned chunks. + * \ingroup l4util_api + * + * \param start Start of range + * \param end End of range (inclusive) (e.g. 2-4 is len 3) + * \param handler Handler function that is called with start and end + * (both inclusive) of the chunk. On success, the handler + * must return 0, if it returns !=0 the function will + * immediately return with the return code of the handler. + * \return 0 on success, != 0 otherwise + */ +L4_INLINE long +l4util_splitlog2_hdl(l4_addr_t start, l4_addr_t end, + long (*handler)(l4_addr_t s, l4_addr_t e, int log2size)); + +/** + * \brief Return log2 base and size aligned length of a range. + * \ingroup l4util_api + * + * \param start Start of range + * \param end End of range (inclusive) (e.g. 2-4 is len 3) + * \return length of elements in log2size (length is 1 << log2size) + */ +L4_INLINE l4_addr_t +l4util_splitlog2_size(l4_addr_t start, l4_addr_t end); + +EXTERN_C_END + +/* Implementation */ + +L4_INLINE long +l4util_splitlog2_hdl(l4_addr_t start, l4_addr_t end, + long (*handler)(l4_addr_t s, l4_addr_t e, int log2size)) +{ + if (end < start) + return -L4_EINVAL; + + while (start <= end) + { + long retval; + int len2 = l4util_splitlog2_size(start, end); + l4_addr_t len = 1UL << len2; + if ((retval = handler(start, start + len - 1, len2))) + return retval; + start += len; + } + return 0; +} + +L4_INLINE l4_addr_t +l4util_splitlog2_size(l4_addr_t start, l4_addr_t end) +{ + int start_bits = l4util_bsf(start); + int len_bits = l4util_bsr(end - start + 1); + if (start_bits != -1 && len_bits > start_bits) + len_bits = start_bits; + + return len_bits; +} + +#endif /* ! __L4UTIL__INCLUDE__SPLITLOG2_H__ */ diff --git a/l4/pkg/l4util/include/stack.h b/l4/pkg/l4util/include/stack.h new file mode 100644 index 00000000..7ddc3e08 --- /dev/null +++ b/l4/pkg/l4util/include/stack.h @@ -0,0 +1,54 @@ +/** + * \file + * \brief Some helper functions for stack manipulation. Newer versions of + * gcc forbid to cast the lvalue of an expression resulting that + * the following expression is invalid: + * + * *--((l4_threadid_t)esp) = tid + * + * \date 03/2004 + * \author Frank Mehnert */ + +/* + * (c) 2003-2009 Author(s) + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ + +#ifndef _L4UTIL_STACK_H +#define _L4UTIL_STACK_H + +#include +#include + +EXTERN_C_BEGIN + +L4_INLINE void l4util_stack_push_mword(l4_addr_t *stack, l4_mword_t val); + +/*****************************************************************************/ +/** + * \brief Get current stack pointer. + * + * \return stack pointer. + */ +L4_INLINE l4_addr_t l4util_stack_get_sp(void); + +/* + * Implementations. + */ + +#include + +L4_INLINE void +l4util_stack_push_mword(l4_addr_t *stack, l4_mword_t val) +{ + l4_mword_t *esp = (l4_mword_t*)(*stack); + *--esp = val; + *stack = (l4_addr_t)esp; +} + +EXTERN_C_END + +#endif diff --git a/l4/pkg/l4util/include/thread.h b/l4/pkg/l4util/include/thread.h new file mode 100644 index 00000000..a869ad9a --- /dev/null +++ b/l4/pkg/l4util/include/thread.h @@ -0,0 +1,55 @@ +/** + * \file + * \brief Low-level Thread Functions + * + * \date 1997 + * \author Sebastian Schönberg */ + +/* + * (c) 2003-2009 Author(s) + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ + +#ifndef __L4_THREAD_H +#define __L4_THREAD_H + +#include +#include + +EXTERN_C_BEGIN + +/** + * \defgroup l4util_thread Low-Level Thread Functions + * \ingroup l4util_api + */ + +/** + * \internal + * \brief Create an L4 thread. + * \ingroup l4util_thread + * \note You should only use this when you know what you're doing, thanks. + * \param id Cap-idx of new thread + * \param thread_utcb Utcb of the new thread + * \param factory Factory to create the thread from + * \param pc Initial value of instruction pointer + * \param sp Initial value of stack pointer + * \param pager Pager of the thread + * \param task Task to put thread in + * \param scheduler Scheduler to use, specify L4_INVALID_CAP for not + * calling the scheduler. + * \param sp Scheduler params to use + * \return 0 on success, <0 on error + */ +L4_CV long +l4util_create_thread(l4_cap_idx_t id, l4_utcb_t *thread_utcb, + l4_cap_idx_t factory, + l4_umword_t pc, l4_umword_t sp, l4_cap_idx_t pager, + l4_cap_idx_t task, + l4_cap_idx_t scheduler, l4_sched_param_t scp) L4_NOTHROW; + +EXTERN_C_END + +#endif /* __L4_THREAD_H */ diff --git a/l4/pkg/l4util/include/util.h b/l4/pkg/l4util/include/util.h new file mode 100644 index 00000000..4210cf0b --- /dev/null +++ b/l4/pkg/l4util/include/util.h @@ -0,0 +1,92 @@ +/** + * \file + * \brief Utilities, generic file + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg , + * Frank Mehnert + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ +#ifndef __L4UTIL__UTIL_H__ +#define __L4UTIL__UTIL_H__ + +#include +#include +#include + +/** + * \defgroup l4util_api Utility Functions + */ + +EXTERN_C_BEGIN + +/** + * \brief Calculate l4 timeouts + * \ingroup l4util_api + * \param mus time in microseconds. Special cases: + * - 0 - > timeout 0 + * - ~0U -> timeout NEVER + * \return the corresponding l4_timeout value + */ +L4_CV l4_timeout_s l4util_micros2l4to(unsigned int mus) L4_NOTHROW; + +/** Suspend thread for a period of milliseconds */ +L4_CV void l4_sleep(int ms) L4_NOTHROW; + +/* \brief Suspend thread for a period of micro seconds. + * \ingroup l4util_api + * WARNING: This function is mostly bogus since the timer resolution of + * current L4 implementations is about 1ms! */ +L4_CV void l4_usleep(int us) L4_NOTHROW; + +/** + * \brief Go sleep and never wake up. + * \ingroup l4util_api + * + */ +L4_INLINE void l4_sleep_forever(void) L4_NOTHROW __attribute__((noreturn)); + +L4_INLINE void +l4_sleep_forever(void) L4_NOTHROW +{ + for (;;) + l4_ipc_sleep(L4_IPC_NEVER); +} + +/** Touch data areas to force mapping read-only */ +static inline void +l4_touch_ro(const void*addr, unsigned size) L4_NOTHROW +{ + volatile const char *bptr, *eptr; + + bptr = (const char*)(((unsigned)addr) & L4_PAGEMASK); + eptr = (const char*)(((unsigned)addr+size-1) & L4_PAGEMASK); + for(;bptr<=eptr;bptr+=L4_PAGESIZE) { + (void)(*bptr); + } +} + + +/** Touch data areas to force mapping read-write */ +static inline void +l4_touch_rw(const void*addr, unsigned size) L4_NOTHROW +{ + volatile char *bptr; + volatile const char *eptr; + + bptr = (char*)(((unsigned)addr) & L4_PAGEMASK); + eptr = (const char*)(((unsigned)addr+size-1) & L4_PAGEMASK); + for(;bptr<=eptr;bptr+=L4_PAGESIZE) { + char x = *bptr; + *bptr = x; + } +} + +EXTERN_C_END + + +#endif /* __L4UTIL__UTIL_H__ */ diff --git a/l4/pkg/l4util/lib/Makefile b/l4/pkg/l4util/lib/Makefile new file mode 100644 index 00000000..16ccaf1e --- /dev/null +++ b/l4/pkg/l4util/lib/Makefile @@ -0,0 +1,4 @@ +PKGDIR = .. +L4DIR ?= $(PKGDIR)/../.. + +include $(L4DIR)/mk/subdir.mk diff --git a/l4/pkg/l4util/lib/src/ARCH-amd64/apic.c b/l4/pkg/l4util/lib/src/ARCH-amd64/apic.c new file mode 100644 index 00000000..f4d6ee9d --- /dev/null +++ b/l4/pkg/l4util/lib/src/ARCH-amd64/apic.c @@ -0,0 +1,226 @@ +/* + * (c) 2008-2009 Torsten Frenzel + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ + +#include +#include +#include +#include +#include +#include + + +unsigned long apic_map_base = 0; +unsigned long apic_timer_divisor = 1; +unsigned long l4_scaler_apic_to_ms = 0; + +void +apic_show_registers(void) +{ + static void + apic_show_register_block(unsigned int beg, unsigned int len) + { + unsigned int i; + outhex16(beg); + outchar(':'); + for (i=beg; i>= 1; + } + + if (div != -1) + { + apic_timer_divisor = newdiv; + tmp_value = apic_read(APIC_TDCR); + tmp_value &= ~0x1F; + tmp_value |= div; + apic_write(APIC_TDCR, tmp_value); + } +} + + +int +apic_check_working(void) +{ +#define CLOCK_TICK_RATE 1193180 /* i8254 ticks per second */ + unsigned long count; + unsigned long tt1, tt2; + + unsigned int calibrate_latch = (CLOCK_TICK_RATE / 20); /* 50 ms */ + + if (!apic_map_base) + return 0; + + apic_timer_disable_irq(); + apic_timer_set_divisor(1); + apic_timer_write(1000000000); + + /* Set the Gate high, disable speaker */ + l4util_out8((l4util_in8(0x61) & ~0x02) | 0x01, 0x61); + + l4util_out8(0xb0, 0x43); /* binary, mode 0, LSB/MSB, Ch 2 */ + l4util_out8(calibrate_latch & 0xff, 0x42); /* LSB of count */ + l4util_out8(calibrate_latch >> 8, 0x42); /* MSB of count */ + + tt1=apic_timer_read(); + count = 0; + do + { + count++; + } while ((l4util_in8(0x61) & 0x20) == 0); + + tt2=apic_timer_read(); + return (tt1-tt2) != 0; +} + + +/* activate APIC after activating by MSR was successful * + * see "Intel Architecture Software Developer's Manual, * + * Volume 3: System Programming Guide, Appendix E" */ +void +apic_activate_by_io(void) +{ + char old_21, old_A1; + unsigned long tmp_val; + l4_uint32_t flags; + + /* mask 8259 interrupts */ + old_21 = l4util_in8(0x21); + l4util_out8(0xff, 0x21); + old_A1 = l4util_in8(0xA1); + l4util_out8(0xff, 0xA1); + + l4util_flags_save(&flags); + l4util_cli(); + + apic_soft_enable(); + + /* set LINT0 to ExtINT, edge triggered */ + tmp_val = apic_read(APIC_LVT0); + tmp_val &= 0xfffe58ff; + tmp_val |= 0x00000700; + apic_write(APIC_LVT0, tmp_val); + + /* set LINT1 to NMI, edge triggered */ + tmp_val = apic_read(APIC_LVT1); + tmp_val &= 0xfffe58ff; + tmp_val |= 0x00000400; + apic_write(APIC_LVT1, tmp_val); + + /* unmask 8259 interrupts */ + l4util_flags_restore(&flags); + l4util_out8(old_A1, 0xA1); + l4util_out8(old_21, 0x21); +} + +/* + * Return APIC clocks per ms + */ +unsigned long +l4_calibrate_apic (void) +{ + unsigned int calibrate_latch = (CLOCK_TICK_RATE / 20); /* 50 ms */ + unsigned int calibrate_time = 50; /* 50 ms */ + + if (!apic_map_base) + return 0; + + apic_timer_disable_irq(); + apic_timer_set_divisor(apic_timer_divisor); + apic_timer_write(1000000000); + + /* Set the Gate high, disable speaker */ + l4util_out8((l4util_in8(0x61) & ~0x02) | 0x01, 0x61); + + l4util_out8(0xb0, 0x43); /* binary, mode 0, LSB/MSB, Ch 2 */ + l4util_out8(calibrate_latch & 0xff, 0x42); /* LSB of count */ + l4util_out8(calibrate_latch >> 8, 0x42); /* MSB of count */ + + { + unsigned long count; + unsigned long tt1, tt2; + unsigned long result; + + tt1=apic_timer_read(); + count = 0; + do + { + count++; + } while ((l4util_in8(0x61) & 0x20) == 0); + tt2=apic_timer_read(); + + result = (tt1-tt2)*apic_timer_divisor; + + /* Error: ECTCNEVERSET */ + if (count <= 1) + goto bad_ctc; + + /* Error: ECPUTOOSLOW */ + if (result <= calibrate_time) + goto bad_ctc; + + __asm__ ("divl %1" + :"=a" (result) + :"r" (calibrate_time), + "0" (result), + "d" (0)); + + l4_scaler_apic_to_ms = result; + + return result; + } + +bad_ctc: + return 0; +} + diff --git a/l4/pkg/l4util/lib/src/ARCH-amd64/backtrace.c b/l4/pkg/l4util/lib/src/ARCH-amd64/backtrace.c new file mode 100644 index 00000000..7a21ea2d --- /dev/null +++ b/l4/pkg/l4util/lib/src/ARCH-amd64/backtrace.c @@ -0,0 +1,89 @@ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ +#include + +#include +#include + +#if defined NOT_FOR_L4 && defined __PIC__ + +#include + +static _Unwind_Reason_Code (*uw_bt) (_Unwind_Trace_Fn, void *); +static _Unwind_Ptr (*uw_getpc) (struct _Unwind_Context *); + +static void +init (void) +{ + void *handle = dlopen ("libgcc_s.so.1", 0); + + if (handle == NULL) + return; + + uw_bt = dlsym (handle, "_Unwind_Backtrace"); + uw_getpc = dlsym (handle, "_Unwind_GetIP"); + if (uw_getpc == NULL) + uw_bt = NULL; +} +#else + +#define uw_getgr _Unwind_GetGR +#define uw_getpc _Unwind_GetIP +#define uw_bt _Unwind_Backtrace +#define uw_getcfa _Unwind_GetCFA + +#endif + +struct Bt_arg +{ + void **pc_array; + int cnt, max; +}; + + +static _Unwind_Reason_Code +__bt_helper(struct _Unwind_Context *ctx, void *a) +{ + struct Bt_arg *arg = a; + + /* Skip first function, it is l4util_backtrace ... */ + if (arg->cnt != -1) + arg->pc_array[arg->cnt] = (void *)uw_getpc (ctx); + if (++arg->cnt == arg->max) + return _URC_END_OF_STACK; + + return _URC_NO_REASON; +} + + +int +l4util_backtrace(void **pc_array, int max) +{ + struct Bt_arg arg = { .pc_array = pc_array, .max = max, .cnt = -1 }; + +#if defined NOT_FOR_L4 && defined __PIC__ + static int initialized = 0; + if (!initialized) + { + initialized = 1; + init(); + } + + if (uw_bt == NULL) + return 0; +#endif + + if (max >= 1) + uw_bt (__bt_helper, &arg); + + if (arg.cnt > 1 && arg.pc_array[arg.cnt - 1] == (void*)0) + --arg.cnt; + return arg.cnt != -1 ? arg.cnt : 0; +} + diff --git a/l4/pkg/l4util/lib/src/ARCH-amd64/perform.c b/l4/pkg/l4util/lib/src/ARCH-amd64/perform.c new file mode 100644 index 00000000..09540c79 --- /dev/null +++ b/l4/pkg/l4util/lib/src/ARCH-amd64/perform.c @@ -0,0 +1,38 @@ +/* + * (c) 2008-2009 Torsten Frenzel + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ +/** + * \brief lib for performance mesaurement counters. + */ + +#include + +#define CONFIG_PERFORM_ONLY_PROTOTYPES +#include + +typedef struct +{ + l4_uint32_t index; + const char *string; +} event_entry; + +static const event_entry event_array[]= +{ +#include "pmc_events.h" +}; + +const char* +strp6pmc_event(l4_uint32_t event) +{ + int i; + + for (i=0; i + * \author Torsten Frenzel + * + */ +/* + * (c) 2004-2009 Author(s) + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ +#include + +int l4_thread_setjmp(l4_thread_jmp_buf env); +__asm__ ( + /* rdi points to jmp buffer */ + "mov %r8, 0x00(%rdi) \n\t" + "mov %r9, 0x08(%rdi) \n\t" + "mov %r10, 0x10(%rdi) \n\t" + "mov %r11, 0x18(%rdi) \n\t" + "mov %r12, 0x20(%rdi) \n\t" + "mov %r13, 0x28(%rdi) \n\t" + "mov %r14, 0x30(%rdi) \n\t" + "mov %r15, 0x38(%rdi) \n\t" + "mov %rbx, 0x40(%rdi) \n\t" + "mov %rsi, 0x48(%rdi) \n\t" + "mov %rbp, 0x50(%rdi) \n\t" + "mov %rdi, 0x58(%rdi) \n\t" /* rsp */ + "movabs $1f, %rcx \n\t" + "mov %rcx, 0x60(%rdi) \n\t" /* rip */ + "mov (%rsp), %rcx \n\t" + "mov %rcx, 0x68(%rdi) \n\t" /* rip caller */ + "pushf \n\t" + "pop %rcx \n\t" + "mov %rcx, 0x70(%rax) \n\t" /* rflags */ + "xor %rax,%rax \n\t" +"ret \n\t" +/* return from longjmp. ptr to jmp_buf is on intermediate stack. + * retval is on intermediate stack + * rsp must be restored. */ +"1:" +"pop %rax \n\t" /* return value */ +"pop %rdi \n\t" /* rdi points to jmp buf */ +"mov 0x00(%rdi), %r8 \n\t" +"mov 0x08(%rdi), %r9 \n\t" +"mov 0x10(%rdi), %r10 \n\t" +"mov 0x18(%rdi), %r11 \n\t" +"mov 0x20(%rdi), %r12 \n\t" +"mov 0x28(%rdi), %r13 \n\t" +"mov 0x30(%rdi), %r14 \n\t" +"mov 0x38(%rdi), %r15 \n\t" +"mov 0x40(%rdi), %rbx \n\t" +"mov 0x48(%rdi), %rsi \n\t" +"mov 0x50(%rdi), %rbp \n\t" +"mov 0x58(%rdi), %rsp \n\t" /* rsp */ +"mov 0x70(%rdi), %rcx \n\t" /* rflags */ +"push %rcx \n\t" +"popf \n\t" +"jmp *0x68(%rdi) \n\t" /* rip caller */ +); + +void l4_thread_longjmp(l4_threadid_t thread, l4_thread_jmp_buf env, + int val){ + l4_thread_jmp_buf_u* buf = (l4_thread_jmp_buf_u*)env; + l4_threadid_t preempter = L4_INVALID_ID, pager=L4_INVALID_ID; + l4_umword_t *stack = (l4_umword_t*)((void*)buf->s.stack + + sizeof(buf->s.stack)); + l4_umword_t dummy; + + *--stack=(l4_umword_t)env; // the buffer + *--stack=val?val:1; // the ret-value + + l4_thread_ex_regs(thread, buf->s.rip, (l4_umword_t)stack, + &preempter, &pager, + &dummy, &dummy, &dummy); +} diff --git a/l4/pkg/l4util/lib/src/ARCH-amd64/spin.c b/l4/pkg/l4util/lib/src/ARCH-amd64/spin.c new file mode 100644 index 00000000..9838a665 --- /dev/null +++ b/l4/pkg/l4util/lib/src/ARCH-amd64/spin.c @@ -0,0 +1,67 @@ +/* + * (c) 2008-2009 Torsten Frenzel + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ +#include + +static void spin_gen(void*addr,int x,int y){ + unsigned char c,*p; + + p=addr+(x+80*y)*2; + c=*p; + c=(c=='|')?'/':(c=='/')?'-':(c=='-')?'\\':(c=='\\')?'|':'-'; + *p=c; +} + +/**************************************************************************** +* * +* l4_spin() - spinning wheel at the hercules screen, position is from * +* upper left. Each call turns the wheel. * +* l4_spin_vga() - the same for vga. * +* * +****************************************************************************/ +void l4_spin(int x,int y){ + spin_gen((void*)0xb0000, x, y); +} +void l4_spin_vga(int x, int y){ + spin_gen((void*)0xb8000, x, y); +} + +static void spin_n_text_gen(void*addr, int x,int y, int len, const char*s){ + unsigned char c,*p; + int i; + + p=addr+(x+len+80*y)*2; + c=*p; + c=(c=='|')?'/':(c=='/')?'-':(c=='-')?'\\':(c=='\\')?'|':'.'; + if(c=='.'){ + if(s){ + p=addr+(x+80*y)*2; + for(i=0;i + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ +#include + +int +l4util_backtrace(void **pc_array, int max) +{ (void)pc_array; (void)max; return 0; } + diff --git a/l4/pkg/l4util/lib/src/ARCH-ppc32/backtrace.c b/l4/pkg/l4util/lib/src/ARCH-ppc32/backtrace.c new file mode 100644 index 00000000..60e9c25f --- /dev/null +++ b/l4/pkg/l4util/lib/src/ARCH-ppc32/backtrace.c @@ -0,0 +1,16 @@ +/* + * (c) 2008-2009 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ +#include + +int +l4util_backtrace(void **pc_array, int max) +{ + (void)pc_array; + (void)max; + return 0; +} diff --git a/l4/pkg/l4util/lib/src/ARCH-ppc32/rdtsc.c b/l4/pkg/l4util/lib/src/ARCH-ppc32/rdtsc.c new file mode 100644 index 00000000..3f62bea4 --- /dev/null +++ b/l4/pkg/l4util/lib/src/ARCH-ppc32/rdtsc.c @@ -0,0 +1,25 @@ +/* + * (c) 2009 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ +#include +#include + +l4_uint32_t l4_scaler_tsc_to_us; +l4_uint32_t l4_scaler_timer_to_tsc; + +l4_uint32_t +l4_tsc_init (int constraint, l4_kernel_info_t *kip) +{ + (void)constraint; + l4_scaler_timer_to_tsc = (kip->frequency_cpu * 1000) + / (kip->frequency_bus / 4); + l4_scaler_tsc_to_us = (kip->frequency_cpu) / 1000; + + return 1; +} + + diff --git a/l4/pkg/l4util/lib/src/ARCH-sparc/backtrace.c b/l4/pkg/l4util/lib/src/ARCH-sparc/backtrace.c new file mode 100644 index 00000000..60e9c25f --- /dev/null +++ b/l4/pkg/l4util/lib/src/ARCH-sparc/backtrace.c @@ -0,0 +1,16 @@ +/* + * (c) 2008-2009 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ +#include + +int +l4util_backtrace(void **pc_array, int max) +{ + (void)pc_array; + (void)max; + return 0; +} diff --git a/l4/pkg/l4util/lib/src/ARCH-x86/apic.c b/l4/pkg/l4util/lib/src/ARCH-x86/apic.c new file mode 100644 index 00000000..0f8bb7e0 --- /dev/null +++ b/l4/pkg/l4util/lib/src/ARCH-x86/apic.c @@ -0,0 +1,226 @@ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Frank Mehnert + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ + +#include +#include +#include +#include +#include + + +unsigned long apic_map_base = 0; +unsigned long apic_timer_divisor = 1; +unsigned long l4_scaler_apic_to_ms = 0; + +static void +apic_show_register_block(unsigned int beg, unsigned int len) +{ + unsigned int i; + outhex16(beg); + outchar(':'); + for (i=beg; i>= 1; + } + + if (div != -1) + { + apic_timer_divisor = newdiv; + tmp_value = apic_read(APIC_TDCR); + tmp_value &= ~0x1F; + tmp_value |= div; + apic_write(APIC_TDCR, tmp_value); + } +} + + +L4_CV int +apic_check_working(void) +{ +#define CLOCK_TICK_RATE 1193180 /* i8254 ticks per second */ + unsigned long count; + unsigned long tt1, tt2; + + unsigned int calibrate_latch = (CLOCK_TICK_RATE / 20); /* 50 ms */ + + if (!apic_map_base) + return 0; + + apic_timer_disable_irq(); + apic_timer_set_divisor(1); + apic_timer_write(1000000000); + + /* Set the Gate high, disable speaker */ + l4util_out8((l4util_in8(0x61) & ~0x02) | 0x01, 0x61); + + l4util_out8(0xb0, 0x43); /* binary, mode 0, LSB/MSB, Ch 2 */ + l4util_out8(calibrate_latch & 0xff, 0x42); /* LSB of count */ + l4util_out8(calibrate_latch >> 8, 0x42); /* MSB of count */ + + tt1=apic_timer_read(); + count = 0; + do + { + count++; + } while ((l4util_in8(0x61) & 0x20) == 0); + + tt2=apic_timer_read(); + return (tt1-tt2) != 0; +} + + +/* activate APIC after activating by MSR was successful * + * see "Intel Architecture Software Developer's Manual, * + * Volume 3: System Programming Guide, Appendix E" */ +L4_CV void +apic_activate_by_io(void) +{ + char old_21, old_A1; + unsigned long tmp_val; + l4_umword_t flags; + + /* mask 8259 interrupts */ + old_21 = l4util_in8(0x21); + l4util_out8(0xff, 0x21); + old_A1 = l4util_in8(0xA1); + l4util_out8(0xff, 0xA1); + + l4util_flags_save(&flags); + l4util_cli(); + + apic_soft_enable(); + + /* set LINT0 to ExtINT, edge triggered */ + tmp_val = apic_read(APIC_LVT0); + tmp_val &= 0xfffe58ff; + tmp_val |= 0x00000700; + apic_write(APIC_LVT0, tmp_val); + + /* set LINT1 to NMI, edge triggered */ + tmp_val = apic_read(APIC_LVT1); + tmp_val &= 0xfffe58ff; + tmp_val |= 0x00000400; + apic_write(APIC_LVT1, tmp_val); + + /* unmask 8259 interrupts */ + l4util_flags_restore(&flags); + l4util_out8(old_A1, 0xA1); + l4util_out8(old_21, 0x21); +} + +/* + * Return APIC clocks per ms + */ +L4_CV unsigned long +l4_calibrate_apic (void) +{ + unsigned int calibrate_latch = (CLOCK_TICK_RATE / 20); /* 50 ms */ + unsigned int calibrate_time = 50; /* 50 ms */ + + if (!apic_map_base) + return 0; + + apic_timer_disable_irq(); + apic_timer_set_divisor(apic_timer_divisor); + apic_timer_write(1000000000); + + /* Set the Gate high, disable speaker */ + l4util_out8((l4util_in8(0x61) & ~0x02) | 0x01, 0x61); + + l4util_out8(0xb0, 0x43); /* binary, mode 0, LSB/MSB, Ch 2 */ + l4util_out8(calibrate_latch & 0xff, 0x42); /* LSB of count */ + l4util_out8(calibrate_latch >> 8, 0x42); /* MSB of count */ + + { + unsigned long count; + unsigned long tt1, tt2; + unsigned long result; + + tt1=apic_timer_read(); + count = 0; + do + { + count++; + } while ((l4util_in8(0x61) & 0x20) == 0); + tt2=apic_timer_read(); + + result = (tt1-tt2)*apic_timer_divisor; + + /* Error: ECTCNEVERSET */ + if (count <= 1) + goto bad_ctc; + + /* Error: ECPUTOOSLOW */ + if (result <= calibrate_time) + goto bad_ctc; + + __asm__ ("divl %1" + :"=a" (result) + :"r" (calibrate_time), + "0" (result), + "d" (0)); + + l4_scaler_apic_to_ms = result; + + return result; + } + +bad_ctc: + return 0; +} + diff --git a/l4/pkg/l4util/lib/src/ARCH-x86/backtrace.c b/l4/pkg/l4util/lib/src/ARCH-x86/backtrace.c new file mode 100644 index 00000000..d58cb7cb --- /dev/null +++ b/l4/pkg/l4util/lib/src/ARCH-x86/backtrace.c @@ -0,0 +1,118 @@ +/* + * (c) 2008-2009 Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ +#include + +#include +#include + +#if defined NOT_FOR_L4 && defined __PIC__ + +#include + +static _Unwind_Reason_Code (*uw_bt) (_Unwind_Trace_Fn, void *); +static _Unwind_Ptr (*uw_getpc) (struct _Unwind_Context *); +static _Unwind_Ptr (*uw_getcfa) (struct _Unwind_Context *); +static _Unwind_Ptr (*uw_getgr) (struct _Unwind_Context *, int); + +static void +init (void) +{ + void *handle = dlopen ("libgcc_s.so.1", 0); + + if (handle == NULL) + return; + + uw_bt = dlsym (handle, "_Unwind_Backtrace"); + uw_getpc = dlsym (handle, "_Unwind_GetIP"); + uw_getcfa = dlsym (handle, "_Unwind_GetCFA"); + uw_getgr = dlsym (handle, "_Unwind_GetGR"); + if (uw_getpc == NULL || uw_getgr == NULL || uw_getcfa == NULL) + uw_bt = NULL; +} +#else + +#define uw_getgr _Unwind_GetGR +#define uw_getpc _Unwind_GetIP +#define uw_bt _Unwind_Backtrace +#define uw_getcfa _Unwind_GetCFA + +#endif + +struct Bt_arg +{ + void **pc_array; + int cnt, max; + void *last_frame; + void *last_sp; +}; + + +static _Unwind_Reason_Code +__bt_helper(struct _Unwind_Context *ctx, void *a) +{ + struct Bt_arg *arg = a; + + /* Skip first function, it is l4util_backtrace ... */ + if (arg->cnt != -1) + arg->pc_array[arg->cnt] = (void *)uw_getpc (ctx); + if (++arg->cnt == arg->max) + return _URC_END_OF_STACK; + + /* IA32: %ebp is DWARF2 register 5 */ + arg->last_sp = (void *)uw_getcfa (ctx); + arg->last_frame = (void *)uw_getgr (ctx, 5); + return _URC_NO_REASON; +} +struct Frame +{ + struct Frame *fp; + void *ret; +}; + + +int +l4util_backtrace(void **pc_array, int max) +{ + struct Bt_arg arg = { .pc_array = pc_array, .max = max, .cnt = -1 }; + +#if defined NOT_FOR_L4 && defined __PIC__ + static int initialized = 0; + if (!initialized) + { + initialized = 1; + init(); + } + + if (uw_bt == NULL) + return 0; +#endif + + if (max >= 1) + uw_bt (__bt_helper, &arg); + + if (arg.cnt > 1 && arg.pc_array[arg.cnt - 1] == (void*)0) + --arg.cnt; + else if (arg.cnt < max) + { + struct Frame *fp = (struct Frame *)arg.last_frame; + + while (arg.cnt < max) + { + /* Check for out of range. */ + if ((void *)fp < arg.last_sp + /* || (void *) ebp > __libc_stack_end*/ + || ((long)fp & 3)) + break; + + pc_array[arg.cnt++] = fp->ret; + fp = fp->fp; + } + } + return arg.cnt != -1 ? arg.cnt : 0; +} + diff --git a/l4/pkg/l4util/lib/src/ARCH-x86/perform.c b/l4/pkg/l4util/lib/src/ARCH-x86/perform.c new file mode 100644 index 00000000..752cf1a2 --- /dev/null +++ b/l4/pkg/l4util/lib/src/ARCH-x86/perform.c @@ -0,0 +1,40 @@ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Frank Mehnert , + * Jork Löser + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ +/** + * \brief lib for performance mesaurement counters. + */ + +#include + +#define CONFIG_PERFORM_ONLY_PROTOTYPES +#include + +typedef struct +{ + l4_uint32_t index; + const char *string; +} event_entry; + +static const event_entry event_array[]= +{ +#include "pmc_events.h" +}; + +const char* +strp6pmc_event(l4_uint32_t event) +{ + unsigned i; + + for (i=0; i, + * Alexander Warg , + * Frank Mehnert + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ +#include +#include +#include +#include +#include +#include +#include + +l4_uint32_t l4_scaler_tsc_to_ns; +l4_uint32_t l4_scaler_tsc_to_us; +l4_uint32_t l4_scaler_ns_to_tsc; +l4_uint32_t l4_scaler_tsc_linux; + + +static inline l4_uint32_t +muldiv (l4_uint32_t a, l4_uint32_t mul, l4_uint32_t div) +{ + l4_uint32_t dummy; + asm ("mull %4 ; divl %3\n\t" + :"=a" (a), "=d" (dummy) + :"a" (a), "c" (div), "d" (mul)); + return a; +} + + +/* + * Return 2^32 / (tsc clocks per usec) + * + * Note, l4_tsc_init(L4_TSC_INIT_CALIBRATE) needs to have + * I/O ports 0x20, 0x42, 0x43 and 0x61 + */ +L4_CV l4_uint32_t +l4_tsc_init (int constraint, l4_kernel_info_t *kip) +{ + l4_scaler_tsc_linux = 0; + + if (constraint != L4_TSC_INIT_CALIBRATE) + { + /* + * First, lets try to get the info out of the kernel info page so that + * we don't need to do port i/o. If we're unable to get the information + * there, measure it ourselves. + */ + if (kip) + { + if (kip->frequency_cpu + && kip->frequency_cpu < 50000000 /* sanity check*/) + { + l4_scaler_tsc_linux = muldiv(1U<<30, 4000, kip->frequency_cpu); + l4_scaler_ns_to_tsc = muldiv(1U<<27, kip->frequency_cpu, 1000000); + + /* l4_scaler_ns_to_tsc = (2^32 * Hz) / (32 * 1.000.000.000) */ + } + else + printf("CPU frequency not set in KIP or invalid.\n"); + } + else + printf("No KIP available!\n"); + } + if ( (l4_scaler_tsc_linux == 0) + && (constraint != L4_TSC_INIT_KERNEL)) + { + const unsigned clock_tick_rate = 1193180; + const unsigned calibrate_time = 50000 /*us*/ + 1; + const unsigned calibrate_latch = clock_tick_rate / 20; /* 20Hz = 50ms */ + + // l4_umword_t flags; + l4_uint64_t tsc_start, tsc_end; + register l4_uint32_t count; + + /* disable interrupts */ + // l4util_flags_save(&flags); + // l4util_cli(); + + /* Set the Gate high, disable speaker */ + l4util_out8 ((l4util_in8 (0x61) & ~0x02) | 0x01, 0x61); + + l4util_out8 (0xb0, 0x43); /* binary, mode 0, LSB/MSB, Ch 2 */ + l4util_out8 (calibrate_latch & 0xff, 0x42); /* LSB of count */ + l4util_out8 (calibrate_latch >> 8, 0x42); /* MSB of count */ + + tsc_start = l4_rdtsc (); + count = 0; + do + { + count++; + } + while ((l4util_in8 (0x61) & 0x20) == 0); + tsc_end = l4_rdtsc (); + + /* restore flags */ + // l4util_flags_restore(&flags); + + /* Error: ECTCNEVERSET */ + if (count <= 1) + goto bad_ctc; + + /* 64-bit subtract - gcc just messes up with long longs */ + tsc_end -= tsc_start; + + /* Error: ECPUTOOFAST */ + if (tsc_end & 0xffffffff00000000LL) + goto bad_ctc; + + /* Error: ECPUTOOSLOW */ + if ((tsc_end & 0xffffffffL) <= calibrate_time) + goto bad_ctc; + + l4_scaler_tsc_linux = muldiv(1U<<30, (1U<<2) * calibrate_time, (l4_uint32_t)tsc_end); + l4_scaler_ns_to_tsc = muldiv(((1ULL<<32)/1000ULL), (l4_uint32_t)tsc_end, + calibrate_time * (1<<5)); + } + + l4_scaler_tsc_to_ns = muldiv(l4_scaler_tsc_linux, 1000, 1<<5); + l4_scaler_tsc_to_us = l4_scaler_tsc_linux; + + return l4_scaler_tsc_linux; + + /* + * The CTC wasn't reliable: we got a hit on the very first read, + * or the CPU was so fast/slow that the quotient wouldn't fit in + * 32 bits.. + */ +bad_ctc: + return 0; +} + +L4_CV l4_uint32_t +l4_get_hz (void) +{ + if (!l4_scaler_tsc_to_ns) + return 0; + + return (l4_uint32_t)(l4_ns_to_tsc(1000000000UL)); +} + diff --git a/l4/pkg/l4util/lib/src/ARCH-x86/setjmp.c b/l4/pkg/l4util/lib/src/ARCH-x86/setjmp.c new file mode 100644 index 00000000..a4fea0a9 --- /dev/null +++ b/l4/pkg/l4util/lib/src/ARCH-x86/setjmp.c @@ -0,0 +1,74 @@ +/*! + * \file l4util/lib/src/setjmp.c + * \brief inter-thread setjmp/longjmp + * + * \date 11/26/2004 + * \author Jork Loeser + * + */ +/* + * (c) 2004-2009 Author(s) + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ +#include + +int l4_thread_setjmp(l4_thread_jmp_buf env); +__asm__ ( + "l4_thread_setjmp: \n\t" + ".global l4_thread_setjmp \n\t" + "movl 4(%esp), %eax \n\t" /* the jump buffer */ + "movl %ebx, (%eax) \n\t" + "movl %esi, 4(%eax) \n\t" + "movl %edi, 8(%eax) \n\t" + "movl %ebp, 12(%eax) \n\t" + "movl %eax, 16(%eax) \n\t" /* esp */ +#ifdef __PIC__ + "call 0f \n\t" + "0: \n\t" + "addl $(1f-0b),(%esp) \n\t" +#else + "lea 1f,%ecx \n\t" +#endif + "movl %ecx, 20(%eax) \n\t" /* eip */ + "movl (%esp), %ecx \n\t" + "movl %ecx, 24(%eax) \n\t" /* eip caller */ + "pushf \n\t" + "popl %ecx \n\t" + "movl %ecx, 28(%eax) \n\t" /* eflags */ + "xorl %eax,%eax \n\t" + "ret \n\t" + /* return from longjmp. ptr to jmp_buf is on intermediate stack. + * retval is on intermediate stack + * esp must be restored. */ + "1: \n\t" + "popl %eax \n\t" /* return value */ + "popl %edx \n\t" /* jmp buf */ + "movl (%edx), %ebx \n\t" + "movl 4(%edx), %esi \n\t" + "movl 8(%edx), %edi \n\t" + "movl 12(%edx), %ebp \n\t" + "movl 16(%edx), %esp \n\t" + "movl 28(%edx), %ecx \n\t" + "push %ecx \n\t" + "popf \n\t" + "jmp *24(%edx) \n\t" + ); + +void l4_thread_longjmp(l4_threadid_t thread, l4_thread_jmp_buf env, + int val){ + l4_thread_jmp_buf_u* buf = (l4_thread_jmp_buf_u*)env; + l4_threadid_t preempter = L4_INVALID_ID, pager=L4_INVALID_ID; + l4_umword_t *stack = (l4_umword_t*)((void*)buf->s.stack + + sizeof(buf->s.stack)); + l4_umword_t dummy; + + *--stack=(l4_umword_t)env; // the buffer + *--stack=val?val:1; // the ret-value + + l4_thread_ex_regs(thread, buf->s.eip, (l4_umword_t)stack, + &preempter, &pager, + &dummy, &dummy, &dummy); +} diff --git a/l4/pkg/l4util/lib/src/ARCH-x86/spin.c b/l4/pkg/l4util/lib/src/ARCH-x86/spin.c new file mode 100644 index 00000000..b1b0168f --- /dev/null +++ b/l4/pkg/l4util/lib/src/ARCH-x86/spin.c @@ -0,0 +1,67 @@ +/* + * (c) 2008-2009 Jork Löser + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ +#include + +static void spin_gen(void*addr,int x,int y){ + unsigned char c,*p; + + p=addr+(x+80*y)*2; + c=*p; + c=(c=='|')?'/':(c=='/')?'-':(c=='-')?'\\':(c=='\\')?'|':'-'; + *p=c; +} + +/**************************************************************************** +* * +* l4_spin() - spinning wheel at the hercules screen, position is from * +* upper left. Each call turns the wheel. * +* l4_spin_vga() - the same for vga. * +* * +****************************************************************************/ +L4_CV void l4_spin(int x,int y){ + spin_gen((void*)0xb0000, x, y); +} +L4_CV void l4_spin_vga(int x, int y){ + spin_gen((void*)0xb8000, x, y); +} + +static void spin_n_text_gen(void*addr, int x,int y, int len, const char*s){ + unsigned char c,*p; + int i; + + p=addr+(x+len+80*y)*2; + c=*p; + c=(c=='|')?'/':(c=='/')?'-':(c=='-')?'\\':(c=='\\')?'|':'.'; + if(c=='.'){ + if(s){ + p=addr+(x+80*y)*2; + for(i=0;i $(OBJ_DIR)/$(^F).sorted || rm $(OBJ_DIR)/$(^F).sorted + $(VERBOSE)echo "/* created automatically from $^, do not edit */" > $@ + $(VERBOSE)awk '/^[0-9a-fA-F][0-9a-fA-F].*/{print "{0x"toupper($$1)", \""$$2"\"},"}' < $(OBJ_DIR)/$(^F).sorted >> $@ || rm $@ + $(VERBOSE)rm $(OBJ_DIR)/$(^F).sorted + +vpath pmc_events.in $(SRC_DIR)/ARCH-x86 diff --git a/l4/pkg/l4util/lib/src/__main.c b/l4/pkg/l4util/lib/src/__main.c new file mode 100644 index 00000000..dee83fc9 --- /dev/null +++ b/l4/pkg/l4util/lib/src/__main.c @@ -0,0 +1,25 @@ +/* + * (c) 2008-2009 Alexander Warg , + * Frank Mehnert + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ + +#include +#include +#include + +extern int main(int argc, char const *argv[]); + +void +__main(int argc, char const *argv[]) +{ + /* call constructors */ + crt0_construction(); + + /* call main */ + exit(main(argc, argv)); +} + diff --git a/l4/pkg/l4util/lib/src/alloc.c b/l4/pkg/l4util/lib/src/alloc.c new file mode 100644 index 00000000..5aa79bcb --- /dev/null +++ b/l4/pkg/l4util/lib/src/alloc.c @@ -0,0 +1,94 @@ +/*! + * \file l4util/lib/src/alloc.c + * \brief allocator using a bit-array + * + * \date 08/25/2004 + * \author Jork Loeser + * + */ +/* + * (c) 2004-2009 Author(s) + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ + +#include +#include +#include + + +/*!\brief Initialize allocator array + */ +L4_CV l4util_alloc_t *l4util_alloc_init(int count, int base){ + l4util_alloc_t *alloc; + if((alloc=malloc(sizeof(l4util_alloc_t)))==0) return 0; + if((alloc->bits = malloc((count+(L4UTIL_ALLOC_BITS_SIZE-1))/8))==0){ + free(alloc); + return 0; + } + memset(alloc->bits, 0, (count+(L4UTIL_ALLOC_BITS_SIZE-1))/8); + alloc->count = count; + alloc->base=base; + alloc->next_elem = base; + return alloc; +} + +/*!\brief Return if an element is avail + * + * \retval 0 not avail + * \retval 1 avail + */ +L4_CV int l4util_alloc_avail(l4util_alloc_t *alloc, int elem){ + if(elembase || elem >= alloc->base+alloc->count) return 0; + elem-=alloc->base; + return !l4util_test_bit(elem&(L4UTIL_ALLOC_BITS_SIZE-1), + alloc->bits+(elem/L4UTIL_ALLOC_BITS_SIZE)); +} + +/*!\brief Set an element busy + * + * \param elem element + * \retval 0 OK + * \retval 1 was occupied already or out of bound + */ +L4_CV int l4util_alloc_occupy(l4util_alloc_t *alloc, int elem){ + if(elembase || elem >= alloc->base+alloc->count) return 1; + elem-=alloc->base; + return l4util_test_and_set_bit(elem&(L4UTIL_ALLOC_BITS_SIZE-1), + alloc->bits+(elem/L4UTIL_ALLOC_BITS_SIZE))?1:0; +} + +/*!\brief Allocate any element + * + * \retval >0 element + * \retval -1 Error, none free + */ +L4_CV int l4util_alloc_alloc(l4util_alloc_t *alloc){ + int elem=alloc->next_elem; + + while(l4util_alloc_occupy(alloc, elem)){ + if(++elem >= alloc->base + alloc->count) elem=0; + if(elem==alloc->next_elem) return -1; + } + alloc->next_elem = elem + 1; + if(alloc->next_elem == alloc->base + alloc->count){ + alloc->next_elem = alloc->base; + } + return elem; +} + +/*!\brief Free an element + * \param elem element to free + * \retval 0 OK + * \retval 1 was not occupied or out of bound + */ +L4_CV int l4util_alloc_free(l4util_alloc_t *alloc, int elem){ + if(elem < alloc->base || elem >= alloc->base+alloc->count){ + return 1; + } + elem-=alloc->base; + return l4util_test_and_clear_bit(elem&(L4UTIL_ALLOC_BITS_SIZE-1), + alloc->bits+(elem/L4UTIL_ALLOC_BITS_SIZE))?0:1; +} diff --git a/l4/pkg/l4util/lib/src/base64.c b/l4/pkg/l4util/lib/src/base64.c new file mode 100644 index 00000000..b1388972 --- /dev/null +++ b/l4/pkg/l4util/lib/src/base64.c @@ -0,0 +1,360 @@ +/*! + * \file l4util/lib/src/base64.c + * \ingroup utils + * + * \date 04/26/2002 + * \author Joerg Nothnagel + */ + +//code adapted from b64.c + +/*********************************************************************\ + +MODULE NAME: b64.c + +AUTHOR: Bob Trower 08/04/01 + +PROJECT: Crypt Data Packaging + +COPYRIGHT: Copyright (c) Trantor Standard Systems Inc., 2001 + +NOTE: This source code may be used as you wish, subject to + the MIT license. See the LICENCE section below. + +DESCRIPTION: + This little utility implements the Base64 + Content-Transfer-Encoding standard described in + RFC1113 (http://www.faqs.org/rfcs/rfc1113.html). + + This is the coding scheme used by MIME to allow + binary data to be transferred by SMTP mail. + + Groups of 3 bytes from a binary stream are coded as + groups of 4 bytes in a text stream. + + The input stream is 'padded' with zeros to create + an input that is an even multiple of 3. + + A special character ('=') is used to denote padding so + that the stream can be decoded back to its exact size. + + Encoded output is formatted in lines which should + be a maximum of 72 characters to conform to the + specification. This program defaults to 72 characters, + but will allow more or less through the use of a + switch. The program enforces a minimum line size + of 4 characters. + + Example encoding: + + The stream 'ABCD' is 32 bits long. It is mapped as + follows: + + ABCD + + A (65) B (66) C (67) D (68) (None) (None) + 01000001 01000010 01000011 01000100 + + 16 (Q) 20 (U) 9 (J) 3 (D) 17 (R) 0 (A) NA (=) NA (=) + 010000 010100 001001 000011 010001 000000 000000 000000 + + + QUJDRA== + + Decoding is the process in reverse. A 'decode' lookup + table has been created to avoid string scans. + +DESIGN GOALS: Specifically: + Code is a stand-alone utility to perform base64 + encoding/decoding. It should be genuinely useful + when the need arises and it meets a need that is + likely to occur for some users. + Code acts as sample code to show the author's + design and coding style. + + Generally: + This program is designed to survive: + Everything you need is in a single source file. + It compiles cleanly using a vanilla ANSI C compiler. + It does its job correctly with a minimum of fuss. + The code is not overly clever, not overly simplistic + and not overly verbose. + Access is 'cut and paste' from a web page. + Terms of use are reasonable. + +VALIDATION: Non-trivial code is never without errors. This + file likely has some problems, since it has only + been tested by the author. It is expected with most + source code that there is a period of 'burn-in' when + problems are identified and corrected. That being + said, it is possible to have 'reasonably correct' + code by following a regime of unit test that covers + the most likely cases and regression testing prior + to release. This has been done with this code and + it has a good probability of performing as expected. + + Unit Test Cases: + + case 0:empty file: + CASE0.DAT -> -> + (Zero length target file created + on both encode and decode.) + + case 1:One input character: + CASE1.DAT A -> QQ== -> A + + case 2:Two input characters: + CASE2.DAT AB -> QUJD -> AB + + case 3:Three input characters: + CASE3.DAT ABC -> QUJD -> ABC + + case 4:Four input characters: + case4.dat ABCD -> QUJDRA== -> ABCD + + case 5:All chars from 0 to ff, linesize set to 50: + + AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIj + JCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZH + SElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWpr + bG1ub3BxcnN0dXZ3eHl6e3x9fn+AgYKDhIWGh4iJiouMjY6P + kJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq+wsbKz + tLW2t7i5uru8vb6/wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX + 2Nna29zd3t/g4eLj5OXm5+jp6uvs7e7v8PHy8/T19vf4+fr7 + /P3+/w== + + case 6:Mime Block from e-mail: + (Data same as test case 5) + + case 7: Large files: + Tested 28 MB file in/out. + + case 8: Random Binary Integrity: + This binary program (b64.exe) was encoded to base64, + back to binary and then executed. + + case 9 Stress: + All files in a working directory encoded/decoded + and compared with file comparison utility to + ensure that multiple runs do not cause problems + such as exhausting file handles, tmp storage, etc. + + ------------- + + Syntax, operation and failure: + All options/switches tested. Performs as + expected. + + case 10: + No Args -- Shows Usage Screen + Return Code 1 (Invalid Syntax) + case 11: + One Arg (invalid) -- Shows Usage Screen + Return Code 1 (Invalid Syntax) + case 12: + One Arg Help (-?) -- Shows detailed Usage Screen. + Return Code 0 (Success -- help request is valid). + case 13: + One Arg Help (-h) -- Shows detailed Usage Screen. + Return Code 0 (Success -- help request is valid). + case 14: + One Arg (valid) -- Uses stdin/stdout (filter) + Return Code 0 (Sucess) + case 15: + Two Args (invalid file) -- shows system error. + Return Code 2 (File Error) + case 16: + Encode non-existent file -- shows system error. + Return Code 2 (File Error) + case 17: + Out of disk space -- shows system error. + Return Code 3 (File I/O Error) + + ------------- + + Compile/Regression test: + gcc compiled binary under Cygwin + Microsoft Visual Studio under Windows 2000 + Microsoft Version 6.0 C under Windows 2000 + +DEPENDENCIES: None + +LICENCE: Copyright (c) 2001 Bob Trower, Trantor Standard Systems Inc. + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated + documentation files (the "Software"), to deal in the + Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, + sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, + subject to the following conditions: + + The above copyright notice and this permission notice shall + be included in all copies or substantial portions of the + Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS + OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +VERSION HISTORY: + Bob Trower 08/04/01 -- Create Version 0.00.00B + +\******************************************************************* */ + + +// local includes + +#include // we implement these functions + +// global includes + +#include + +// private variables + +/*! + * \ingroup utils_internal + * Translation Table as described in RFC1113 + */ +static const char cb64[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +/*! + * \ingroup utils_internal + * Translation Table to decode (created by Bob Trower) + */ +static const char cd64[]="|$$$}rstuvwxyz{$$$$$$$>?@ABCDEFGHIJKLMNOPQRSTUVW$$$$$$XYZ[\\]^_`abcdefghijklmnopq"; + +//private functions + +/*! + * \brief encode 3 8-bit binary bytes as 4 '6-bit' characters + * \ingroup utils_internal + * + * + * \param in array of bytes to be encoded + * \param len real number of bytes to encode + * \retval out encoded representation of \a in + * encode 3 8-bit binary bytes as 4 '6-bit' characters + */ +static void base64_encodeblock(unsigned char in[3], unsigned char out[4], int len); + +/*! + * \brief decode 4 '6-bit' characters into 3 8-bit binary bytes + * \ingroup utils_internal + * + * + * \param in array of bytes to be decoded + * \retval out decoded representation of \a in + * decode 4 '6-bit' characters into 3 8-bit binary bytes + */ +static void base64_decodeblock(unsigned char in[4], unsigned char out[3]); + + +// implementation of public functions + +L4_CV void base64_encode( const char *infile, unsigned int in_size, char **outfile) +{ + unsigned char in[3], out[4]; + int i, len = 0; + unsigned int in_count=0, out_count=0; + + char *temp=malloc(in_size*2);//to be on the safe side; + while(in_count 122) ? 0 : cd64[ v - 43 ]); + if( v ) + { + v = (unsigned char) ((v == '$') ? 0 : v - 61); + } + } + if( in_count> 2 ]; + out[1] = cb64[ ((in[0] & 0x03) << 4) | ((in[1] & 0xf0) >> 4) ]; + out[2] = (unsigned char) (len > 1 ? cb64[ ((in[1] & 0x0f) << 2) | ((in[2] & 0xc0) >> 6) ] : '='); + out[3] = (unsigned char) (len > 2 ? cb64[ in[2] & 0x3f ] : '='); +} + +static void base64_decodeblock( unsigned char in[4], unsigned char out[3] ) +{ + out[ 0 ] = (unsigned char ) (in[0] << 2 | in[1] >> 4); + out[ 1 ] = (unsigned char ) (in[1] << 4 | in[2] >> 2); + out[ 2 ] = (unsigned char ) (((in[2] << 6) & 0xc0) | in[3]); +} + diff --git a/l4/pkg/l4util/lib/src/getopt2.c b/l4/pkg/l4util/lib/src/getopt2.c new file mode 100644 index 00000000..402c2015 --- /dev/null +++ b/l4/pkg/l4util/lib/src/getopt2.c @@ -0,0 +1,94 @@ +/** + * \file l4util/lib/src/getopt2.c + * \brief initialize argc/argv from multiboot structure + * + * \author Frank Mehnert */ + +/* + * (c) 2003-2009 Author(s) + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ + +#include +#include + +//#include +//#include + +#define MAXARGC 50 +#define MAXENVC 50 + +char *l4util_argv[MAXARGC]; +int l4util_argc = 0; + +#define isspace(c) ((c)==' '||(c)=='\t'||(c)=='\r'||(c)=='\n') + +void __l4util_parse_args(char *argbuf); +void __l4util_parse_args(char *argbuf) +{ + char *cp; + char quote = 0; + + /* make l4util_argc, l4util_argv */ + l4util_argc = 0; + cp = argbuf; + + /* Note, there's no support for escaping quotes! */ + + while (*cp && l4util_argc < MAXARGC-1) + { + /* Skip whitespace */ + while (*cp && isspace(*cp)) + cp++; + + /* New elem? */ + if (*cp) + { + /* Start of a quote? */ + if (*cp == '"' || *cp == '\'') + { + quote = *cp; + cp++; + } + + l4util_argv[l4util_argc++] = cp; + + /* Forward to next whitespace / quote character */ + while (*cp && ((!quote && !isspace(*cp)) || (quote && *cp != quote))) + cp++; + + /* Terminate array elem */ + if (*cp) + *cp++ = '\0'; + + quote = 0; + } + } + + if(*cp && l4util_argc == MAXARGC-1) + printf("WARNING: parse_args() truncated at %dth argument!\n", MAXARGC); + + l4util_argv[l4util_argc] = (void*) 0; +} + +#if 0 +static void +arg_init(char* cmdline) +{ + if (cmdline) + { + l4util_parse_args(cmdline); + } +} + +void +l4util_mbi_to_argv(l4_mword_t flag, l4util_mb_info_t *mbi) +{ + if (flag == L4UTIL_MB_VALID + && mbi && (mbi->flags & L4UTIL_MB_CMDLINE)) + arg_init((char*)(l4_addr_t)mbi->cmdline); +} +#endif diff --git a/l4/pkg/l4util/lib/src/keymap.c b/l4/pkg/l4util/lib/src/keymap.c new file mode 100644 index 00000000..06683e7e --- /dev/null +++ b/l4/pkg/l4util/lib/src/keymap.c @@ -0,0 +1,31 @@ +/*! + * \file keymap.c + * \brief convert keyboard value to ascii value + * + * \date Dec 2007 + * \author Adam Lackorznynski + * + */ +/* + * (c) 2007-2009 Author(s) + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ + +#include + +#ifdef USE_DE_KEYMAP +#include "keymap_de.h" +#else +#include "keymap_en.h" +#endif + +int l4util_map_event_to_keymap(unsigned value, unsigned shift) +{ + if (value < 128 && shift < 2) + return keymap[value][shift]; + + return 0; +} diff --git a/l4/pkg/l4util/lib/src/keymap_de.h b/l4/pkg/l4util/lib/src/keymap_de.h new file mode 100644 index 00000000..097465f8 --- /dev/null +++ b/l4/pkg/l4util/lib/src/keymap_de.h @@ -0,0 +1,145 @@ +/* + * (c) 2009 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ +#ifndef __L4UTIL__INCLUDE__KEYMAP_DE_H__ +#define __L4UTIL__INCLUDE__KEYMAP_DE_H__ + +#define SHIFT -1 + +static char keymap[128][2] = +{ + {0}, /* 0 */ + {27, 27}, /* 1 - ESC */ + {'1', '!'}, /* 2 */ + {'2', '"'}, + {'3', '§'}, + {'4', '$'}, + {'5', '%'}, + {'6', '&'}, + {'7', '/'}, + {'8', '('}, + {'9', ')'}, + {'0', '='}, + {'ß', '?'}, + {'\'', '`'}, + {8, 8}, /* 14 - Backspace */ + {'\t', '\t'}, /* 15 */ + {'q', 'Q'}, + {'w', 'W'}, + {'e', 'E'}, + {'r', 'R'}, + {'t', 'T'}, + {'z', 'Z'}, + {'u', 'U'}, + {'i', 'I'}, + {'o', 'O'}, + {'p', 'P'}, + {'ü', 'Ü'}, + {'+', '*'}, /* 27 */ + {'\r', '\r'}, /* 28 - Enter */ + {0, 0}, /* 29 - Ctrl */ + {'a', 'A'}, /* 30 */ + {'s', 'S'}, + {'d', 'D'}, + {'f', 'F'}, + {'g', 'G'}, + {'h', 'H'}, + {'j', 'J'}, + {'k', 'K'}, + {'l', 'L'}, + {'ö', 'Ö'}, + {'ä', 'Ä'}, /* 40 */ + {'^', '°'}, /* 41 */ + {SHIFT, SHIFT}, /* 42 - Left Shift */ + {'#', '\''}, /* 43 */ + {'y', 'Y'}, /* 44 */ + {'x', 'X'}, + {'c', 'C'}, + {'v', 'V'}, + {'b', 'B'}, + {'n', 'N'}, + {'m', 'M'}, + {',', ';'}, + {'.', ':'}, + {'-', '_'}, /* 53 */ + {SHIFT, SHIFT}, /* 54 - Right Shift */ + {0, 0}, /* 55 - Print Screen */ + {0, 0}, /* 56 - Alt */ + {' ', ' '}, /* 57 - Space bar */ + {0, 0}, /* 58 - Caps Lock */ + {0, 0}, /* 59 - F1 */ + {0, 0}, /* 60 - F2 */ + {0, 0}, /* 61 - F3 */ + {0, 0}, /* 62 - F4 */ + {0, 0}, /* 63 - F5 */ + {0, 0}, /* 64 - F6 */ + {0, 0}, /* 65 - F7 */ + {0, 0}, /* 66 - F8 */ + {0, 0}, /* 67 - F9 */ + {0, 0}, /* 68 - F10 */ + {0, 0}, /* 69 - Num Lock */ + {0, 0}, /* 70 - Scroll Lock */ + {'7', '7'}, /* 71 - Numeric keypad 7 */ + {'8', '8'}, /* 72 - Numeric keypad 8 */ + {'9', '9'}, /* 73 - Numeric keypad 9 */ + {'-', '-'}, /* 74 - Numeric keypad '-' */ + {'4', '4'}, /* 75 - Numeric keypad 4 */ + {'5', '5'}, /* 76 - Numeric keypad 5 */ + {'6', '6'}, /* 77 - Numeric keypad 6 */ + {'+', '+'}, /* 78 - Numeric keypad '+' */ + {'1', '1'}, /* 79 - Numeric keypad 1 */ + {'2', '2'}, /* 80 - Numeric keypad 2 */ + {'3', '3'}, /* 81 - Numeric keypad 3 */ + {'0', '0'}, /* 82 - Numeric keypad 0 */ + {'.', '.'}, /* 83 - Numeric keypad '.' */ + {0, 0}, + {0, 0}, + {'<', '>'}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, /* 103 - arrow up */ + {0, 0}, + {0, 0}, /* 105 - arrow left */ + {0, 0}, /* 106 - arrow right */ + {0, 0}, + {0, 0}, /* 108 - arrow down */ + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, +}; + +#endif diff --git a/l4/pkg/l4util/lib/src/keymap_en.h b/l4/pkg/l4util/lib/src/keymap_en.h new file mode 100644 index 00000000..47b62e3b --- /dev/null +++ b/l4/pkg/l4util/lib/src/keymap_en.h @@ -0,0 +1,145 @@ +/* + * (c) 2009 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ +#ifndef __L4UTIL__INCLUDE__KEYMAP__EN_H__ +#define __L4UTIL__INCLUDE__KEYMAP__EN_H__ + +#define SHIFT -1 + +static char keymap[128][2] = +{ + {0}, /* 0 */ + {27, 27}, /* 1 - ESC */ + {'1', '!'}, /* 2 */ + {'2', '@'}, + {'3', '#'}, + {'4', '$'}, + {'5', '%'}, + {'6', '^'}, + {'7', '&'}, + {'8', '*'}, + {'9', '('}, + {'0', ')'}, + {'-', '_'}, + {'=', '+'}, + {8, 8}, /* 14 - Backspace */ + {'\t', '\t'}, /* 15 */ + {'q', 'Q'}, + {'w', 'W'}, + {'e', 'E'}, + {'r', 'R'}, + {'t', 'T'}, + {'y', 'Y'}, + {'u', 'U'}, + {'i', 'I'}, + {'o', 'O'}, + {'p', 'P'}, + {'[', '{'}, + {']', '}'}, /* 27 */ + {'\r', '\r'}, /* 28 - Enter */ + {0, 0}, /* 29 - Ctrl */ + {'a', 'A'}, /* 30 */ + {'s', 'S'}, + {'d', 'D'}, + {'f', 'F'}, + {'g', 'G'}, + {'h', 'H'}, + {'j', 'J'}, + {'k', 'K'}, + {'l', 'L'}, + {';', ':'}, + {'\'', '"'}, /* 40 */ + {'`', '~'}, /* 41 */ + {SHIFT, SHIFT}, /* 42 - Left Shift */ + {'\\', '|'}, /* 43 */ + {'z', 'Z'}, /* 44 */ + {'x', 'X'}, + {'c', 'C'}, + {'v', 'V'}, + {'b', 'B'}, + {'n', 'N'}, + {'m', 'M'}, + {',', '<'}, + {'.', '>'}, + {'/', '?'}, /* 53 */ + {SHIFT, SHIFT}, /* 54 - Right Shift */ + {0, 0}, /* 55 - Print Screen */ + {0, 0}, /* 56 - Alt */ + {' ', ' '}, /* 57 - Space bar */ + {0, 0}, /* 58 - Caps Lock */ + {0, 0}, /* 59 - F1 */ + {0, 0}, /* 60 - F2 */ + {0, 0}, /* 61 - F3 */ + {0, 0}, /* 62 - F4 */ + {0, 0}, /* 63 - F5 */ + {0, 0}, /* 64 - F6 */ + {0, 0}, /* 65 - F7 */ + {0, 0}, /* 66 - F8 */ + {0, 0}, /* 67 - F9 */ + {0, 0}, /* 68 - F10 */ + {0, 0}, /* 69 - Num Lock */ + {0, 0}, /* 70 - Scroll Lock */ + {'7', '7'}, /* 71 - Numeric keypad 7 */ + {'8', '8'}, /* 72 - Numeric keypad 8 */ + {'9', '9'}, /* 73 - Numeric keypad 9 */ + {'-', '-'}, /* 74 - Numeric keypad '-' */ + {'4', '4'}, /* 75 - Numeric keypad 4 */ + {'5', '5'}, /* 76 - Numeric keypad 5 */ + {'6', '6'}, /* 77 - Numeric keypad 6 */ + {'+', '+'}, /* 78 - Numeric keypad '+' */ + {'1', '1'}, /* 79 - Numeric keypad 1 */ + {'2', '2'}, /* 80 - Numeric keypad 2 */ + {'3', '3'}, /* 81 - Numeric keypad 3 */ + {'0', '0'}, /* 82 - Numeric keypad 0 */ + {'.', '.'}, /* 83 - Numeric keypad '.' */ + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, /* 103 - arrow up */ + {0, 0}, + {0, 0}, /* 105 - arrow left */ + {0, 0}, /* 106 - arrow right */ + {0, 0}, + {0, 0}, /* 108 - arrow down */ + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, +}; + +#endif diff --git a/l4/pkg/l4util/lib/src/kip.c b/l4/pkg/l4util/lib/src/kip.c new file mode 100644 index 00000000..e4fab1b4 --- /dev/null +++ b/l4/pkg/l4util/lib/src/kip.c @@ -0,0 +1,58 @@ +/* + * (c) 2008-2009 Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ +#include +#include + +#include +#include +#include + + +L4_CV int +l4util_kip_kernel_is_ux(l4_kernel_info_t *k) +{ + const char *s = l4_kip_version_string(k); + + if (s && strstr(s, "(ux)")) + return 1; + return 0; +} + +L4_CV int +l4util_kip_kernel_has_feature(l4_kernel_info_t *k, const char *str) +{ + const char *s = l4_kip_version_string(k); + + if (!s) + return 0; + + l4util_kip_for_each_feature(s) + { + if (strcmp(s, str) == 0) + return 1; + } + + return 0; +} + +L4_CV unsigned long +l4util_kip_kernel_abi_version(l4_kernel_info_t *k) +{ + const char *s = l4_kip_version_string(k); + + if (!s) + return 0; + + l4util_kip_for_each_feature(s) + { + if (strncmp(s, "abiver:", 7) == 0) + return strtoul(s + 7, NULL, 0); + } + + return 0; +} diff --git a/l4/pkg/l4util/lib/src/kprintf.c b/l4/pkg/l4util/lib/src/kprintf.c new file mode 100644 index 00000000..837644ae --- /dev/null +++ b/l4/pkg/l4util/lib/src/kprintf.c @@ -0,0 +1,41 @@ +/*! + * \file l4util/lib/src/kprintf.c + * \brief simple(!) -- non threaded -- printf using kernel debugger output + * + * \date 04/05/2007 + * \author Adam Lackorzynski + * + */ +/* + * (c) 2007-2009 Author(s) + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ + +#include +#include + +#include +#include + +/* This is in the BSS on purpose to not put more load on the stack, + * and we know that this is suited for threading this way + */ +static char buffer[500]; + +L4_CV int l4_kprintf(const char *fmt, ...) +{ + va_list list; + int err; + + va_start(list, fmt); + err = vsnprintf(buffer, sizeof(buffer), fmt, list); + buffer[sizeof(buffer) - 1] = 0; + va_end(list); + + outstring(buffer); + + return err; +} diff --git a/l4/pkg/l4util/lib/src/list_alloc.c b/l4/pkg/l4util/lib/src/list_alloc.c new file mode 100644 index 00000000..db67c82c --- /dev/null +++ b/l4/pkg/l4util/lib/src/list_alloc.c @@ -0,0 +1,256 @@ +/** + * \file l4util/lib/src/list_alloc.c + * \brief Simple list-based allocator. Taken from the Fiasco kernel. + * + * \author Alexander Warg + * Frank Mehnert + */ +/* + * (c) 2003-2009 Author(s) + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ + +#include +#include +#include + +#include +#include + +#define ALIGN_MASK (sizeof(l4la_free_t) - 1) + +#define DEBUG +#ifdef DEBUG + +static void +__check_overlap(l4la_free_t **first, void *b, l4_size_t s) +{ + l4la_free_t *c = *first; + for (; c; c = c->next) + { + l4_addr_t x_s = (l4_addr_t)b; + l4_addr_t x_e = x_s + s; + l4_addr_t b_s = (l4_addr_t)c; + l4_addr_t b_e = b_s + c->size; + + if ( (x_s >= b_s && x_s < b_e) + || (x_e > b_s && x_e <= b_e) + || (b_s >= x_s && b_s < x_e) + || (b_e > x_s && b_e <= x_e)) + { + printf("trying to free memory that is already free: \n" + " [%lx-%lx) overlaps [%lx-%lx)\n", + x_s, x_e, b_s, b_e ); + enter_kdebug("l4la"); + } + } +} + +static void +__sanity_check_list(l4la_free_t **first, char const *func, char const *info) +{ + l4la_free_t *c = *first; + for (;c ; c = c->next) + { + if (c->next) + { + if (c >= c->next) + { + printf("%s: %s(%s): list order violation\n", + __FILE__, func, info); + enter_kdebug("l4la"); + } + + if (((l4_addr_t)c) + c->size > (l4_addr_t)c->next) + { + printf("%s: %s(%s): overlapping blocks\n", + __FILE__, func, info); + enter_kdebug("l4la"); + } + } + } +} + +#else + +static inline void +__check_overlap(l4la_free_t **first, void *b, l4_size_t s) {}; + +static inline void +__sanity_check_list(l4la_free_t **first, char const *f, char const *i) {}; + +#endif + +static void +__merge(l4la_free_t **first) +{ + __sanity_check_list(first, __FUNCTION__, "entry"); + + l4la_free_t *c = *first; + while (c && c->next) + { + l4_addr_t f_start = (l4_addr_t)c; + l4_addr_t f_end = f_start + c->size; + l4_addr_t n_start = (l4_addr_t)c->next; + + if (f_end == n_start) + { + c->size += c->next->size; + assert(c->size >= sizeof(l4la_free_t)); + c->next = c->next->next; + continue; + } + + c = c->next; + } + + __sanity_check_list(first, __FUNCTION__, "exit"); +} + +L4_CV void +l4la_free(l4la_free_t **first, void *block, l4_size_t size) +{ + l4la_free_t **c = first; + l4la_free_t *next = 0; + + __sanity_check_list(first, __FUNCTION__, "entry"); + __check_overlap(first, block, size); + + size = (size + ALIGN_MASK) & ~ALIGN_MASK; + + if (*c) + { + while (*c && *c < (l4la_free_t*)block) + c = &(*c)->next; + + next = *c; + } + + assert(*c != block); + *c = (l4la_free_t*)block; + assert(*c != next); + + (*c)->next = next; + (*c)->size = size; + + assert((!next) || ((l4_addr_t)(*c) + size <= (l4_addr_t)next)); + + __merge(first); + + __sanity_check_list(first, __FUNCTION__, "exit"); +} + +L4_CV void * +l4la_alloc(l4la_free_t **first, l4_size_t size, unsigned align) +{ + void *ret = 0; + l4_addr_t almask = (1 << align) - 1; + l4la_free_t **c = first; + void *b = 0; + + __sanity_check_list(first, __FUNCTION__, "entry"); + + size = (size + ALIGN_MASK) & ~ALIGN_MASK; + + for (; *c; c=&(*c)->next) + { + l4_addr_t n_start = (l4_addr_t)(*c); + l4_addr_t a_start; + l4_addr_t a_size; + + if ((*c)->size < size) + continue; + + if (!(n_start & almask)) + { + if ((*c)->size >= size) + { + if ((*c)->size == size) + { + b = *c; + *c = (*c)->next; + ret = b; + goto done; + } + + l4la_free_t *m = (l4la_free_t*)(n_start + size); + m->next = (*c)->next; + m->size = (*c)->size - size; + assert(m->size >= sizeof(l4la_free_t)); + b = *c; + *c = m; + ret = b; + goto done; + } + + continue; + } + + a_start = (n_start & ~almask) + 1 + almask; + if (a_start - n_start >= (*c)->size) + continue; + + a_size = (*c)->size - a_start + n_start; + + if (a_size >= size) + { + if (a_size == size) + { + (*c)->size -= a_size; + ret = (void*)a_start; + goto done; + } + l4la_free_t *m = (l4la_free_t*)(a_start + size); + m->next = (*c)->next; + m->size = a_size - size; + assert(m->size >= sizeof(l4la_free_t)); + (*c)->size -= a_size; + assert((*c)->size >= sizeof(l4la_free_t)); + (*c)->next = m; + ret = (void*)a_start; + goto done; + } + } + +done: + return ret; +} + +L4_CV l4_size_t +l4la_avail(l4la_free_t **first) +{ + __sanity_check_list(first, __FUNCTION__, "entry"); + + l4la_free_t *c = *first; + l4_addr_t a = 0; + while (c) + { + a += c->size; + c = c->next; + } + + return a; +} + +L4_CV void +l4la_dump(l4la_free_t **first) +{ + printf("List_alloc [first=%p]\n", *first); + l4la_free_t *c = *first; + for (;c && c!=c->next ; c = c->next) + printf(" mem_block_t [this=%p size=0x%lx (%ldkB) next=%p]\n", c, + (l4_addr_t)c->size, + (l4_addr_t)(c->size+1023)/1024, c->next); + + if (c && c == c->next) + printf(" BUG: loop detected\n"); +} + +L4_CV void +l4la_init(l4la_free_t **first) +{ + *first = 0; +} diff --git a/l4/pkg/l4util/lib/src/llulc.cc b/l4/pkg/l4util/lib/src/llulc.cc new file mode 100644 index 00000000..9d1fd481 --- /dev/null +++ b/l4/pkg/l4util/lib/src/llulc.cc @@ -0,0 +1,293 @@ +/* + * (c) 2011 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +/* + * Note, do _NOT_ use this lock unless you got advised to do so. + */ +/* + * This lock-implementation is quite simplistic, especially its list of + * blockers on a lock will only grow, i.e. ex-blockers will not be removed. + * We also have one kernel-provided irq per lock+thread. For general use, + * this is too much. + */ + +#include +#include +#include +#include + +struct l4ullulock_struct_t { + unsigned long lock; + void * blocklistroot; + l4_umword_t block_cnt; + void * (*mem_alloc)(size_t); + void (*mem_free)(void *); + l4_cap_idx_t (*cap_alloc)(void); + void (*cap_free)(l4_cap_idx_t c); + L4::Cap factory; +}; + +static l4_umword_t add_atomic(l4_umword_t *x, int delta) +{ + l4_umword_t oldval, newval; + do + { + oldval = *x; + newval = oldval + delta; + } + while (!l4util_cmpxchg(x, oldval, newval)); + + return oldval; +} + +class Lock +{ +public: + typedef L4::Cap Lockcap; + typedef l4ullulock_t Allocator; + + explicit Lock(l4_utcb_t *u, Allocator *al) + : _utcb(u), _triggers(0), _next(0), _allocator(al) + {} + + void init_root() { _next = this; } + + void lock(Lockcap c) { _lock = c; } + + void block() throw() + { _lock->receive(); add_atomic(&_triggers, -1); } + + void wakeup() throw() + { + if (_triggers < 2) + { + add_atomic(&_triggers, 1); + _lock->trigger(); + } + } + + static Lock *get_dummy(l4ullulock_t *t) + { return reinterpret_cast(t->blocklistroot); } + + void enqueue(l4ullulock_t *t) + { + Lock *r = get_dummy(t); + l4_umword_t oldval, newval; + + do + { + _next = r->_next; + oldval = (l4_umword_t)r->_next; + newval = (l4_umword_t)this; + } + while (!l4util_cmpxchg((volatile l4_umword_t*)&r->_next, oldval, newval)); + } + + void *operator new(size_t, void *p) + { return p; } + + void operator delete(void *p) + { reinterpret_cast(p)->_allocator->mem_free(p); } + + static void shift(l4ullulock_t *t) + { t->blocklistroot = (void *)get_dummy(t)->_next; } + + static void free_list(l4ullulock_t *t); + + static Lock *find(l4ullulock_t *t, l4_utcb_t *u); + static void wakeup_others(l4ullulock_t *t, l4_utcb_t *u); + +private: + l4_utcb_t *_utcb; + L4::Cap _lock; + l4_umword_t _triggers; + Lock *_next; + Allocator *_allocator; +}; + + +Lock *Lock::find(l4ullulock_t *t, l4_utcb_t *u) +{ + Lock *r = get_dummy(t)->_next; + Lock *i = r; + + do + { + if (u == i->_utcb) + return i; + i = i->_next; + } + while (i != r); + + return 0; +} + +void Lock::wakeup_others(l4ullulock_t *t, l4_utcb_t *u) +{ + Lock *r = get_dummy(t)->_next; + Lock *i = r; + + do + { + if (i->_utcb && u != i->_utcb) + i->wakeup(); + i = i->_next; + } + while (i != r); +} + +void Lock::free_list(l4ullulock_t *t) +{ + Lock *r = get_dummy(t)->_next; + Lock *i = r; + + do + { + Lock *d = i; + i = i->_next; + delete d; + } + while (i != r); + + delete r; +} + +static Lock *create_new_thread_lock(l4ullulock_t *t, l4_utcb_t *u) +{ + int err; + L4::Cap f; + void *p = t->mem_alloc(sizeof(Lock)); + if (!p) + return 0; + + Lock *x = new (p) Lock(u, t); + + L4::Cap c = L4::Cap(t->cap_alloc()); + if (!c.is_valid()) + goto fail1; + + f = L4::Cap(t->factory); + + err = l4_error(f->create_irq(c)); + if (err < 0) + goto fail2; + + err = l4_error(c->attach(24, L4::Cap::Invalid)); + if (err < 0) + goto fail3; + + x->lock(c); + return x; + +fail3: + l4_task_unmap(L4_BASE_TASK_CAP, + l4_obj_fpage(c.cap(), 0, L4_FPAGE_RWX), + L4_FP_ALL_SPACES); +fail2: + t->cap_free(c.cap()); +fail1: + delete x; + return 0; +} + +int l4ullulock_init(l4ullulock_t **t, + void *(*mem_alloc)(size_t x), + void (*mem_free)(void *p), + l4_cap_idx_t (*cap_alloc)(void), + void (*cap_free)(l4_cap_idx_t c), + l4_cap_idx_t factory) +{ + l4ullulock_t *_t = (l4ullulock_t *)mem_alloc(sizeof(*_t)); + if (!_t) + return -L4_ENOMEM; + + _t->lock = 0; + _t->block_cnt = 0; + _t->mem_alloc = mem_alloc; + _t->mem_free = mem_free; + _t->cap_alloc = cap_alloc; + _t->cap_free = cap_free; + _t->factory = L4::Cap(factory); + + void *p = mem_alloc(sizeof(Lock)); + if (!p) + { + mem_free(_t); + return -L4_ENOMEM; + } + + Lock *l = new (p) Lock(0, _t); + l->init_root(); + _t->blocklistroot = l; + *t = _t; + return 0; +} + +int l4ullulock_deinit(l4ullulock_t *t) +{ + Lock::free_list(t); + t->mem_free(t); + return 0; +} + +int l4ullulock_lock(l4ullulock_t *t, l4_utcb_t *u) +{ + while (add_atomic(&t->lock, 1) > 0) + { + // we need to block, someone has the lock already + Lock *tl = Lock::find(t, u); + if (!tl) + { + tl = create_new_thread_lock(t, u); + if (!tl) + { + add_atomic(&t->lock, -1); + return -L4_ENOMEM; + } + + tl->enqueue(t); + + add_atomic(&t->lock, -1); + continue; + } + + add_atomic(&t->lock, -1); + asm volatile("" : : : "memory"); + add_atomic(&t->block_cnt, 1); + asm volatile("" : : : "memory"); + + tl->block(); + + asm volatile("" : : : "memory"); + add_atomic(&t->block_cnt, -1); + } + + return 0; +} + +int l4ullulock_unlock(l4ullulock_t *t, l4_utcb_t *u) +{ + add_atomic(&t->lock, -1); + asm volatile("" : : : "memory"); + if (t->block_cnt > 0) + { + Lock::shift(t); + Lock::wakeup_others(t, u); + } + + return 0; +} diff --git a/l4/pkg/l4util/lib/src/memdesc.c b/l4/pkg/l4util/lib/src/memdesc.c new file mode 100644 index 00000000..4bee3b9e --- /dev/null +++ b/l4/pkg/l4util/lib/src/memdesc.c @@ -0,0 +1,30 @@ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg , + * Frank Mehnert + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ +/* + * Some convenience functions for memory descriptors. + */ + +#include +#include +#include + +l4_addr_t +l4util_memdesc_vm_high(l4_kernel_info_t *kinfo) +{ + l4_kernel_info_mem_desc_t *md = l4_kernel_info_get_mem_descs(kinfo); + int nr = l4_kernel_info_get_num_mem_descs(kinfo); + int i; + + for (i = 0; i < nr; i++, md++) + if (l4_kernel_info_get_mem_desc_is_virtual(md)) + return l4_kernel_info_get_mem_desc_end(md); + + return 0; +} diff --git a/l4/pkg/l4util/lib/src/micros2l4to.c b/l4/pkg/l4util/lib/src/micros2l4to.c new file mode 100644 index 00000000..f6e9b429 --- /dev/null +++ b/l4/pkg/l4util/lib/src/micros2l4to.c @@ -0,0 +1,54 @@ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg , + * Frank Mehnert , + * Michael Hohmuth , + * Jork Löser , + * Lars Reuther + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ +/* + */ + +/***************************************************************************** + * libl4util/src/micros2l4to.c * + * calculate L4 timeout * + *****************************************************************************/ + +#include +#include +#include +#include +#include + +L4_CV l4_timeout_s +l4util_micros2l4to(unsigned int mus) +{ + l4_timeout_s t; + if (mus == 0) + t = L4_IPC_TIMEOUT_0; + else if (mus == ~0U) + t = L4_IPC_TIMEOUT_NEVER; + else + { + int e = l4util_log2(mus) - 7; + unsigned m; + + if (e < 0) e = 0; + m = mus / (1UL << e); + + if ((e > 31) || (m > 1023)) + { + printf("l4util_micros2l4to(): " + "invalid timeout %d, using max. values\n", mus); + e = 0; + m = 1023; + } + t.t = (e << 10) | m; + } + return t; +} + diff --git a/l4/pkg/l4util/lib/src/parse_cmdline.c b/l4/pkg/l4util/lib/src/parse_cmdline.c new file mode 100644 index 00000000..29554dfe --- /dev/null +++ b/l4/pkg/l4util/lib/src/parse_cmdline.c @@ -0,0 +1,344 @@ +/* + * (c) 2008-2009 Frank Mehnert , + * Torsten Frenzel , + * Jork Löser + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ +/* + * Parse the command-line for specified arguments and store the values into + * variables. + * + * For a more detailed documentation, see parse_cmd.h in the include dir. + */ + +#include +#include +#include +#include +#include +#include +#include + +struct parse_cmdline_struct{ + enum parse_cmd_type type; // which type (int, switch, string) + char shortform; // short symbol + const char *longform; // long name + union{ + void *argptr; // ptr to variable getting the value + parse_cmd_fn_t fn; // function to call + parse_cmd_fn_arg_t fn_arg; // function to call with args + } arg; + union{ + int switch_to; // value a switch sets + const char* default_string; // default string value + unsigned default_int; // default int value + int id; // identifier to pass to function + }val; + const char *comment; // a description for the generated help +}; + +#define TRASH(type, val) { type dummy __attribute__ ((unused)) = (val); } + +L4_CV int parse_cmdline(int *argc, const char***argv, char arg0, ...){ + va_list va; + int err; + + /* calculate the number of argument-descriptors */ + va_start(va, arg0); + err = parse_cmdlinev(argc, argv, arg0, va); + va_end(va); + return err; +} + +L4_CV int parse_cmdlinev(int *argc, const char***argv, char arg0, va_list va0){ + va_list va; + int c, count, shortform, cur_longopt; + struct option *longopts, *longptr; + char *optstring, *optptr; + struct parse_cmdline_struct *pa; + int err; + + va_copy(va, va0); + /* calculate the number of argument-descriptors */ + shortform = arg0; + for(count=0; shortform; count++){ + int type; + int standard_int, *int_p; + const char *standard_string, **string_p; + + va_arg(va, const char*); /* skip long form */ + va_arg(va, const char*); /* skip comment */ + type = va_arg(va, int); + switch(type){ + case PARSE_CMD_INT: + standard_int = va_arg(va, int); + int_p = va_arg(va, int*); + *int_p = standard_int; + break; + case PARSE_CMD_SWITCH: + TRASH(int, va_arg(va, int)); + TRASH(int*, va_arg(va, int*)); + break; + case PARSE_CMD_STRING: + standard_string = va_arg(va, char*); + string_p = va_arg(va, const char**); + *string_p = standard_string; + break; + case PARSE_CMD_FN: + case PARSE_CMD_FN_ARG: + TRASH(int, va_arg(va, int)); + TRASH(parse_cmd_fn_t, va_arg(va, parse_cmd_fn_t)); + break; + case PARSE_CMD_INC: + standard_int = va_arg(va, int); + int_p = va_arg(va, int*); + *int_p = standard_int; + break; + case PARSE_CMD_DEC: + standard_int = va_arg(va, int); + int_p = va_arg(va, int*); + *int_p = standard_int; + break; + default: + return -1; + } + shortform = va_arg(va, int); + } + + /* consider the --help and -h */ + count++; + + /* allocate the fields for short options, long options and parse args */ + longopts = (struct option*)alloca(sizeof(struct option)*(count+1)); + if(longopts==0) return -2; + + optstring = (char*)alloca(count*2+1); + if(optstring==0) return -2; + + pa = (struct parse_cmdline_struct*) + alloca(count * sizeof(struct parse_cmdline_struct)); + if(pa==0) return -2; + + /* fill in the short options field, longopts and parse args */ + va_copy(va, va0); + shortform = arg0; + optptr = optstring; + longptr = longopts; + + /* Prefill the 'help' switches. We know it is the first entry, so + we can check for idx 0 when parsing the table. */ + *optptr++='h'; + pa->shortform = 'h'; + pa->longform = "help"; + pa->comment = "this help"; + pa->type = PARSE_CMD_SWITCH; + longptr->name = pa->longform; + longptr->flag = &cur_longopt; + longptr->val = 0; + longptr->has_arg = 0; + longptr++; + + for(c=1;shortform; c++){ + if(shortform!=' ') *optptr++ = shortform; + pa[c].shortform = shortform; + pa[c].longform = va_arg(va, const char*); + pa[c].comment = va_arg(va, const char*); + pa[c].type = va_arg(va, int); + + /* prefill a few of the longoptions fields */ + if(pa[c].longform){ + longptr->name = pa[c].longform; + longptr->flag = &cur_longopt; + longptr->val = c; + } + switch(pa[c].type){ + case PARSE_CMD_INT: + if(shortform!=' ') *optptr++ = ':'; + if(pa[c].longform) longptr->has_arg = 1; + + pa[c].val.default_int = va_arg(va, int); + pa[c].arg.argptr = va_arg(va, int*); + break; + + case PARSE_CMD_SWITCH: + if(pa[c].longform) longptr->has_arg = 0; + + pa[c].val.switch_to = va_arg(va, int); + pa[c].arg.argptr = va_arg(va, int*); + break; + case PARSE_CMD_STRING: + if(shortform!=' ') *optptr++ = ':'; + if(pa[c].longform) longptr->has_arg = 1; + + pa[c].val.default_string = va_arg(va, char*); + pa[c].arg.argptr = va_arg(va, char**); + break; + case PARSE_CMD_FN: + if(pa[c].longform) longptr->has_arg = 0; + + pa[c].val.id = va_arg(va, int); + pa[c].arg.fn = va_arg(va, parse_cmd_fn_t); + break; + case PARSE_CMD_FN_ARG: + if(shortform!=' ') *optptr++ = ':'; + if(pa[c].longform) longptr->has_arg = 1; + + pa[c].val.id = va_arg(va, int); + pa[c].arg.fn_arg = va_arg(va, parse_cmd_fn_arg_t); + break; + case PARSE_CMD_INC: + case PARSE_CMD_DEC: + if(pa[c].longform) longptr->has_arg = 0; + + TRASH(int, va_arg(va, int)); + pa[c].arg.argptr = va_arg(va, int*); + break; + } + + if(pa[c].longform) longptr++; + // next short form + shortform = va_arg(va, int); + } + + // end the optstring string + *optptr=0; + + // end the longopt field + longptr->name=0; + longptr->has_arg=0; + longptr->flag=0; + longptr->val=0; + + err = -3; + + /* now, parse the arguments */ + do{ + int val; + int idx; + + val = getopt_long_only(*argc, (char**)*argv, optstring, longopts, &idx); + switch(val){ + case ':': + printf("Option -%c requires an argument\n",optopt); + goto e_help; + case '?': + if(opterr){ + printf("Unrecognized option: - %c\n", optopt ? optopt : '?'); + goto e_help; + } + break; + case -1: + *argc-=optind; + *argv+=optind; + optind=1; + return 0; + default: + /* we got an option. If it is a short option (val!=0), + lookup the index. */ + if(val!=0){ + for(idx = 0; idx < count; idx++){ + if(pa[idx].shortform == val) break; + } + } else { + /* it was a long option. We are lucky, the pa-element is + stored in the cur_longopt variable. */ + idx = cur_longopt; + } + if(idx == 0){ + err = -4; + goto e_help; + } + if(idx. Option list:\n", *argv[0]); + for(c=0;c, + * Alexander Warg , + * Frank Mehnert , + * Michael Hohmuth , + * Lars Reuther + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ + +/* IPC message queueing functions */ + +#include +#include +#include +#include +#include + +#define STACK_SIZE 512 + +l4_threadid_t l4util_queue_id; + +static void *(*queue_malloc)(l4_uint32_t size); +static l4_uint32_t max_rcv_size; + +struct buffer +{ + struct l4util_buffer_head head; + struct buffer *next, *prev; + l4_umword_t d1, d2; /* must come last - just before the + string buffer */ +}; + +static struct buffer *q_head = 0, *q_tail = 0; +static l4util_simple_lock_t q_lock = 0; + +/* dequeue a message queued by the queue thread */ +int +l4util_queue_dequeue(struct l4util_buffer_head **buffer) +{ + l4_simple_lock(&q_lock); + + if ((*buffer = (struct l4util_buffer_head *) q_head) != 0) + if ((q_head = q_head->next) == 0) + { + q_tail = 0; + } + + l4_simple_unlock(&q_lock); + + return *buffer ? 0 : -1; +} + +/* the queue thread: it takes messages from any sender and queues them. */ + +static void queue_thread(void) +{ + static struct + { + l4_fpage_t fpage; + l4_msgdope_t dope; + l4_msgdope_t snd_dope; + l4_umword_t d1, d2; + l4_strdope_t str; + } rcv_buffer + = + { + {fpage: 0}, + {md: {0, 0, 0, 0, 0, 0, 1, 0}}, + {msgdope: 0}, + 0, 0, {0, 0, 0, 0} + }; + + int error; + l4_msgdope_t result; + + rcv_buffer.str.rcv_size = max_rcv_size - 8; /* 2 mandantory dwords = 8 byte */ + + for (;;) + { + struct buffer *b = queue_malloc(max_rcv_size - 8 + + sizeof(struct buffer)); + rcv_buffer.str.rcv_str = (l4_umword_t) &b->d1; + b->head.buffer = (char *) &b->d1; + + error = l4_ipc_wait(&b->head.src, &rcv_buffer, + &b->d1, &b->d2, + L4_IPC_NEVER, &result); + + if (error) + continue; + + b->head.len = rcv_buffer.str.snd_size; + + l4_simple_lock(&q_lock); + + b->next = 0; + if (! q_tail) + q_head = b; + else + q_tail->next = b; + q_tail = b; + + l4_simple_unlock(&q_lock); + } +} + + +/* initialization */ + +int +l4util_queue_init(int queue_threadno, + void *(*malloc_func)(l4_uint32_t size), + l4_uint32_t max_rcv) +{ + char *th_stack; + l4_umword_t dummy; + l4_threadid_t my_preempter, my_pager; + l4_threadid_t me; + + queue_malloc = malloc_func; + max_rcv_size = max_rcv; + + th_stack = queue_malloc(STACK_SIZE); + if (! th_stack) + return -1; + + me = l4_myself(); + my_preempter = L4_INVALID_ID; + my_pager = L4_INVALID_ID; + l4_thread_ex_regs(me, (l4_umword_t) -1, (l4_umword_t) -1, + &my_preempter, + &my_pager, + &dummy, + &dummy, + &dummy); + l4util_queue_id = me; + l4util_queue_id.id.lthread = queue_threadno; + + l4_thread_ex_regs(l4util_queue_id, (l4_umword_t) queue_thread, + ((l4_umword_t) th_stack) + STACK_SIZE, + &my_preempter, + &my_pager, + &dummy, + &dummy, + &dummy); + + return 0; +} + diff --git a/l4/pkg/l4util/lib/src/rand.c b/l4/pkg/l4util/lib/src/rand.c new file mode 100644 index 00000000..6b726246 --- /dev/null +++ b/l4/pkg/l4util/lib/src/rand.c @@ -0,0 +1,34 @@ +/* + * (c) 2008-2009 Frank Mehnert , + * Michael Hohmuth , + * Lars Reuther + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ +/* + */ + +/***************************************************************************** + * random.c * + * pseudo-random number generator * + *****************************************************************************/ + +#include + +static unsigned int l4_rand_next = 1; + +L4_CV l4_uint32_t +l4util_rand(void) +{ + l4_rand_next = l4_rand_next * 1103515245 + 12345; + return ((l4_rand_next >>16) & L4_RAND_MAX); +} + +L4_CV void +l4util_srand (l4_uint32_t seed) +{ + l4_rand_next = seed; +} + diff --git a/l4/pkg/l4util/lib/src/reboot.c b/l4/pkg/l4util/lib/src/reboot.c new file mode 100644 index 00000000..90f291bc --- /dev/null +++ b/l4/pkg/l4util/lib/src/reboot.c @@ -0,0 +1,21 @@ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ +#include +#include + +L4_CV void +l4util_reboot(void) +{ + enter_kdebug("*#^"); /* Always available */ + + enter_kdebug("Exit failed!"); /* Should we loop here? */ + + while (1) + ; +} diff --git a/l4/pkg/l4util/lib/src/sleep.c b/l4/pkg/l4util/lib/src/sleep.c new file mode 100644 index 00000000..0a5be855 --- /dev/null +++ b/l4/pkg/l4util/lib/src/sleep.c @@ -0,0 +1,59 @@ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg , + * Frank Mehnert , + * Michael Hohmuth , + * Jork Löser , + * Lars Reuther + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ +/* + */ + +/***************************************************************************** + * libl4util/src/sleep.c * + * suspend thread * + *****************************************************************************/ + +#include +#include +#include +#include +#include + +L4_CV void l4_sleep(int ms) +{ + l4_timeout_t to; + l4_msgtag_t tag; + l4_utcb_t *u = l4_utcb(); + + if (ms != -1) + /* calculate timeout */ + to = l4_timeout(L4_IPC_TIMEOUT_NEVER,l4util_micros2l4to(ms * 1000)); + else + to = L4_IPC_NEVER; + + tag = l4_ipc_receive(L4_INVALID_CAP, u, to); + + if (l4_ipc_error(tag, u) != L4_IPC_RETIMEOUT) + printf("l4_sleep(): IPC error %02x\n", l4_ipc_error_code(u)); +} + + +L4_CV void l4_usleep(int us) +{ + l4_msgtag_t tag; + l4_timeout_t to; + l4_utcb_t *u = l4_utcb(); + + /* calculate timeout */ + to = l4_timeout(L4_IPC_TIMEOUT_NEVER, l4util_micros2l4to(us)); + + tag = l4_ipc_sleep(to); + + if (l4_ipc_error(tag, u) != L4_IPC_RETIMEOUT) + printf("l4_sleep(): IPC error %02x\n", l4_ipc_error_code(u)); +} diff --git a/l4/pkg/l4util/lib/src/slmap.c b/l4/pkg/l4util/lib/src/slmap.c new file mode 100644 index 00000000..155584fe --- /dev/null +++ b/l4/pkg/l4util/lib/src/slmap.c @@ -0,0 +1,144 @@ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Ronald Aigner + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ +#include +#include + +/* + * function implementations + */ + +L4_CV slmap_t* +map_new_entry(void* key, unsigned key_size, void* data) +{ + slmap_t* map; + + map = malloc(sizeof(slmap_t)); + if (!map) + return (slmap_t*)0; + + map->key = key; + map->key_size = key_size; + map->data = data; + map->next = 0; + + if ((!map->key) && map->key_size) + map->key_size = 0; + + return map; +} + +L4_CV slmap_t* +map_new_sentry(char *key, void* data) +{ + if (!key) + return (slmap_t*)0; + return map_new_entry((void*)key, strlen(key), data); +} + +L4_CV slmap_t* +map_append(slmap_t* list, slmap_t* new_entry) +{ + slmap_t *ret = list; + if (!list) + return new_entry; + + while (list->next) list = list->next; + list->next = new_entry; + return ret; +} + +L4_CV slmap_t* +map_remove(slmap_t* list, slmap_t* entry) +{ + slmap_t* ret = list; + if (!list) + return list; + if (!entry) + return list; + + // search entry + if (list == entry) + ret = list->next; + else + { + while (list && (list->next != entry)) + list = list->next; + if (list) + list->next = entry->next; + else + return ret; + } + map_free_entry(&entry); + return ret; +} + +L4_CV void +map_free_entry(slmap_t **entry) +{ + if (*entry) + { + free(*entry); + *entry = 0; + } +} + +L4_CV slmap_t* +map_get_at(slmap_t* list, int n) +{ + int i=0; + while (list) + { + i++; + if (i==n) + break; + list = list->next; + } + return list; +} + +L4_CV slmap_t* +map_add(slmap_t* list, slmap_t* entry) +{ + if (!entry) + return list; + + entry->next = list; + return entry; +} + +L4_CV void +map_insert_after(slmap_t* after, slmap_t* new_entry) +{ + if (!new_entry) + return; + if (!after) + return; + new_entry->next = after->next; + after->next = new_entry; +} + +L4_CV slmap_t* +map_find(slmap_t* list, void* key, unsigned key_size) +{ + while (list) + { + if (memcmp(list->key, key, (key_size < list->key_size) ? key_size : list->key_size) == 0) + return list; + list = list->next; + } + return (slmap_t*)0; +} + +L4_CV slmap_t* +map_sfind(slmap_t* list, const char* key) +{ + if (!key) + return (slmap_t*)0; + return map_find(list, (void*)key, strlen(key)); +} diff --git a/l4/pkg/l4util/lib/src/thread.c b/l4/pkg/l4util/lib/src/thread.c new file mode 100644 index 00000000..d381079e --- /dev/null +++ b/l4/pkg/l4util/lib/src/thread.c @@ -0,0 +1,50 @@ +/** + * \file + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Michael Hohmuth + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ + +#include +#include +#include +#include + +#include + +L4_CV long +l4util_create_thread(l4_cap_idx_t id, l4_utcb_t *thread_utcb, + l4_cap_idx_t factory, + l4_umword_t pc, l4_umword_t sp, l4_cap_idx_t pager, + l4_cap_idx_t task, + l4_cap_idx_t scheduler, l4_sched_param_t scp) L4_NOTHROW +{ + l4_msgtag_t res = l4_factory_create_thread(factory, id); + if (l4_error(res)) + return l4_error(res); + + l4_thread_control_start(); + l4_thread_control_pager(pager); + l4_thread_control_bind(thread_utcb, task); + res = l4_thread_control_commit(id); + if (l4_error(res)) + return l4_error(res); + + res = l4_thread_ex_regs(id, pc, sp, 0); + if (l4_error(res)) + return l4_error(res); + + if (!l4_is_invalid_cap(scheduler)) + { + res = l4_scheduler_run_thread(scheduler, id, &scp); + if (l4_error(res)) + return l4_error(res); + } + + return 0; +} diff --git a/l4/pkg/ldscripts/ARCH-amd64/main_dyn.ld b/l4/pkg/ldscripts/ARCH-amd64/main_dyn.ld new file mode 100644 index 00000000..59055209 --- /dev/null +++ b/l4/pkg/ldscripts/ARCH-amd64/main_dyn.ld @@ -0,0 +1,289 @@ +/* Default linker script, for normal executables */ +OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", + "elf64-x86-64") +OUTPUT_ARCH(i386:x86-64) +ENTRY(_start) + +PHDRS +{ + phdr PT_PHDR PHDRS; + interp PT_INTERP; + ro PT_LOAD FILEHDR PHDRS; + rw PT_LOAD; + dyn PT_DYNAMIC; + tls PT_TLS; + ehf PT_GNU_EH_FRAME; + L4_DEFINE_L4PHDRS +} + + +SECTIONS +{ + L4_DEFINE_X86_KERNEL_ENTRY_SYMS + + /* No program code/data before _stext/_prog_img_start! */ + + /* Read-only sections, merged into text segment: */ + PROVIDE (__executable_start = 0x400000); . = 0x400000 + SIZEOF_HEADERS; + .interp : { *(.interp) } :ro :interp + .note.gnu.build-id : { *(.note.gnu.build-id) } :ro + .hash : { *(.hash) } + .gnu.hash : { *(.gnu.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .gnu.version : { *(.gnu.version) } + .gnu.version_d : { *(.gnu.version_d) } + .gnu.version_r : { *(.gnu.version_r) } + .rel.init : { *(.rel.init) } + .rela.init : { *(.rela.init) } + .rel.text : { *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) } + .rela.text : { *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) } + .rel.fini : { *(.rel.fini) } + .rela.fini : { *(.rela.fini) } + .rel.rodata : { *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) } + .rela.rodata : { *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) } + .rel.data.rel.ro : { *(.rel.data.rel.ro* .rel.gnu.linkonce.d.rel.ro.*) } + .rela.data.rel.ro : { *(.rela.data.rel.ro* .rela.gnu.linkonce.d.rel.ro.*) } + .rel.data : { *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) } + .rela.data : { *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) } + .rel.tdata : { *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) } + .rela.tdata : { *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) } + .rel.tbss : { *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) } + .rela.tbss : { *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) } + .rel.ctors : { *(.rel.ctors) } + .rela.ctors : { *(.rela.ctors) } + .rel.dtors : { *(.rel.dtors) } + .rela.dtors : { *(.rela.dtors) } + .rel.got : { *(.rel.got) } + .rela.got : { *(.rela.got) } + .rel.bss : { *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) } + .rela.bss : { *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) } + .rel.ldata : { *(.rel.ldata .rel.ldata.* .rel.gnu.linkonce.l.*) } + .rela.ldata : { *(.rela.ldata .rela.ldata.* .rela.gnu.linkonce.l.*) } + .rel.lbss : { *(.rel.lbss .rel.lbss.* .rel.gnu.linkonce.lb.*) } + .rela.lbss : { *(.rela.lbss .rela.lbss.* .rela.gnu.linkonce.lb.*) } + .rel.lrodata : { *(.rel.lrodata .rel.lrodata.* .rel.gnu.linkonce.lr.*) } + .rela.lrodata : { *(.rela.lrodata .rela.lrodata.* .rela.gnu.linkonce.lr.*) } + .rel.plt : { *(.rel.plt) } + .rela.plt : { *(.rela.plt) } + .init : + { + KEEP (*(.init)) + } =0x90909090 + .plt : { *(.plt) } + .text : + { + _stext = .; + _prog_img_start = _stext; + *(.text .stub .text.* .gnu.linkonce.t.*) + KEEP (*(.text.*personality*)) + /* .gnu.warning sections are handled specially by elf32.em. */ + *(.gnu.warning) + } =0x90909090 + .fini : + { + KEEP (*(.fini)) + /* LONG(0xc3) * terminate .fini */ + } = 0x90909090 + + PROVIDE (_etext = .); + PROVIDE (etext = .); + .rol4re_elf_aux : { + KEEP (*(.rol4re_elf_aux)) + } : ro : l4re_aux + .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } : ro + .rodata1 : { *(.rodata1) } + .eh_frame_hdr : { *(.eh_frame_hdr) } :ehf :ro + + .eh_frame : ONLY_IF_RO + { + PROVIDE(__eh_frame_start__ = .); + KEEP (*(.eh_frame)) + KEEP (*(.eh_frame_terminator)) + } :ro + + .gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) } :ro + /* Adjust the address for the data segment. We want to adjust up to + the same address within the page on the next page up. */ + . = ALIGN (CONSTANT (MAXPAGESIZE)) - ((CONSTANT (MAXPAGESIZE) - .) & (CONSTANT (MAXPAGESIZE) - 1)); . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE)); + PROVIDE (_sdata = .); + /* Exception handling */ + .eh_frame : ONLY_IF_RW + { + PROVIDE (__eh_frame_start__ = .); + KEEP (*(.eh_frame)) + KEEP (*(.eh_frame_terminator)) + } :rw + .gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) } :rw + /* Thread Local Storage sections */ + .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) } :rw : tls + .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } : rw + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + } + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(.fini_array)) + KEEP (*(SORT(.fini_array.*))) + PROVIDE_HIDDEN (__fini_array_end = .); + } + .ctors : + { +/* KEEP (*(.mark_beg_l4dde_ctors)) + KEEP (*(.l4dde_ctors)) + KEEP (*(.mark_end_l4dde_ctors)) + + KEEP (*(.mark_beg_ctors)) */ + + /* gcc uses crtbegin.o to find the start of + the constructors, so we make sure it is + first. Because this is a wildcard, it + doesn't matter if the user does not + actually link against crtbegin.o; the + linker won't look for a file to match a + wildcard. The wildcard also means that it + doesn't matter which directory crtbegin.o + is in. */ + KEEP (*crtbegin.o(.ctors)) + KEEP (*crtbegin?.o(.ctors)) + /* We don't want to include the .ctor section from + the crtend.o file until after the sorted ctors. + The .ctor section from the crtend file contains the + end of ctors marker and it must be last */ + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + /* + KEEP (*(.mark_end_ctors)) + + KEEP (*(.mark_beg_c_ctors)) + KEEP (*(SORT(.c_ctors.?))) + KEEP (*(SORT(.c_ctors.??))) + KEEP (*(SORT(.c_ctors.???))) + KEEP (*(SORT(.c_ctors.????))) + KEEP (*(SORT(.c_ctors.?????))) + KEEP (*(.c_ctors)) + KEEP (*(.mark_end_c_ctors)) + */ + } + + .dtors : + { + /* + KEEP (*(.mark_beg_dtors))*/ + KEEP (*crtbegin.o(.dtors)) + KEEP (*crtbegin?.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + /* + KEEP (*(.mark_end_dtors)) + + KEEP (*(.mark_beg_c_sys_dtors)) + KEEP (*(SORT(.c_dtors.?))) + KEEP (*(SORT(.c_dtors.??))) + KEEP (*(.mark_end_c_sys_dtors)) + + KEEP (*(.mark_beg_c_dtors)) + KEEP (*(SORT(.c_dtors.???))) + KEEP (*(SORT(.c_dtors.????))) + KEEP (*(SORT(.c_dtors.?????))) + KEEP (*(.c_dtors)) + KEEP (*(.mark_end_c_dtors))*/ + } + .jcr : { KEEP (*(.jcr)) } + .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro* .gnu.linkonce.d.rel.ro.*) } + .dynamic : { *(.dynamic) } :dyn :rw + .got : { *(.got) } :rw + . = DATA_SEGMENT_RELRO_END (24, .); + .got.plt : { *(.got.plt) } + .data : + { + *(.data .data.* .gnu.linkonce.d.*) + KEEP (*(.gnu.linkonce.d.*personality*)) + SORT(CONSTRUCTORS) + } + .data1 : { *(.data1) } + _edata = .; PROVIDE (edata = .); + __bss_start = .; + .bss : + { + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + /* Align here to ensure that the .bss section occupies space up to + _end. Align after .bss to ensure correct alignment even if the + .bss section disappears because there are no input sections. + FIXME: Why do we need it? When there is no .bss section, we don't + pad the .data section. */ + . = ALIGN(. != 0 ? 64 / 8 : 1); + } + .lbss : + { + *(.dynlbss) + *(.lbss .lbss.* .gnu.linkonce.lb.*) + *(LARGE_COMMON) + } + . = ALIGN(64 / 8); + .lrodata ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) : + { + *(.lrodata .lrodata.* .gnu.linkonce.lr.*) + } + .ldata ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) : + { + *(.ldata .ldata.* .gnu.linkonce.l.*) + . = ALIGN(. != 0 ? 64 / 8 : 1); + } + . = ALIGN(64 / 8); + _end = .; PROVIDE (end = .); + . = DATA_SEGMENT_END (.); + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } :NONE + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to the beginning + of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /* DWARF 3 */ + .debug_pubtypes 0 : { *(.debug_pubtypes) } + .debug_ranges 0 : { *(.debug_ranges) } + .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) } + /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) } +} diff --git a/l4/pkg/ldscripts/ARCH-amd64/main_rel.ld b/l4/pkg/ldscripts/ARCH-amd64/main_rel.ld new file mode 100644 index 00000000..588daa21 --- /dev/null +++ b/l4/pkg/ldscripts/ARCH-amd64/main_rel.ld @@ -0,0 +1,212 @@ +/* Script for --shared -z combreloc: shared library, combine & sort relocs */ +OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", + "elf64-x86-64") +OUTPUT_ARCH(i386:x86-64) +ENTRY(_start) +SECTIONS +{ + /* Read-only sections, merged into text segment: */ + . = 0 + SIZEOF_HEADERS; + .note.gnu.build-id : { *(.note.gnu.build-id) } + .hash : { *(.hash) } + .gnu.hash : { *(.gnu.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .gnu.version : { *(.gnu.version) } + .gnu.version_d : { *(.gnu.version_d) } + .gnu.version_r : { *(.gnu.version_r) } + .rela.dyn : + { + *(.rela.init) + *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) + *(.rela.fini) + *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) + *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) + *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) + *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) + *(.rela.ctors) + *(.rela.dtors) + *(.rela.got) + *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) + *(.rela.ldata .rela.ldata.* .rela.gnu.linkonce.l.*) + *(.rela.lbss .rela.lbss.* .rela.gnu.linkonce.lb.*) + *(.rela.lrodata .rela.lrodata.* .rela.gnu.linkonce.lr.*) + *(.rela.ifunc) + } + .rela.plt : + { + *(.rela.plt) + *(.rela.iplt) + } + .init : + { + KEEP (*(.init)) + } =0x90909090 + /*. = ALIGN(16);*/ + .plt : { *(.plt) *(.iplt) } + .text : + { + *(.text.unlikely .text.*_unlikely) + *(.text.exit .text.exit.*) + *(.text.startup .text.startup.*) + *(.text.hot .text.hot.*) + *(.text .stub .text.* .gnu.linkonce.t.*) + KEEP (*(.text.*personality*)) + /* .gnu.warning sections are handled specially by elf32.em. */ + *(.gnu.warning) + } =0x90909090 + .fini : + { + KEEP (*(.fini)) + } =0x90909090 + PROVIDE (__etext = .); + PROVIDE (_etext = .); + PROVIDE (etext = .); + .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } + .rodata1 : { *(.rodata1) } + .eh_frame_hdr : { *(.eh_frame_hdr) } + .eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) } + .gcc_except_table : ONLY_IF_RO { *(.gcc_except_table + .gcc_except_table.*) } + /* These sections are generated by the Sun/Oracle C++ compiler. */ + .exception_ranges : ONLY_IF_RO { *(.exception_ranges + .exception_ranges*) } + /* Adjust the address for the data segment. We want to adjust up to + the same address within the page on the next page up. */ + . = ALIGN (CONSTANT (MAXPAGESIZE)) - ((CONSTANT (MAXPAGESIZE) - .) & (CONSTANT (MAXPAGESIZE) - 1)); . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE)); + PROVIDE (_sdata = .); + /* Exception handling */ + .eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) } + .gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) } + .exception_ranges : ONLY_IF_RW { *(.exception_ranges .exception_ranges*) } + /* Thread Local Storage sections */ + .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) } + .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } + .preinit_array : + { + KEEP (*(.preinit_array)) + } + .init_array : + { + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + } + .fini_array : + { + KEEP (*(.fini_array)) + KEEP (*(SORT(.fini_array.*))) + } + .ctors : + { + /* gcc uses crtbegin.o to find the start of + the constructors, so we make sure it is + first. Because this is a wildcard, it + doesn't matter if the user does not + actually link against crtbegin.o; the + linker won't look for a file to match a + wildcard. The wildcard also means that it + doesn't matter which directory crtbegin.o + is in. */ + KEEP (*crtbegin.o(.ctors)) + KEEP (*crtbegin?.o(.ctors)) + /* We don't want to include the .ctor section from + the crtend.o file until after the sorted ctors. + The .ctor section from the crtend file contains the + end of ctors marker and it must be last */ + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + } + .dtors : + { + KEEP (*crtbegin.o(.dtors)) + KEEP (*crtbegin?.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + } + .jcr : { KEEP (*(.jcr)) } + .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro* .gnu.linkonce.d.rel.ro.*) } + .dynamic : { *(.dynamic) } + .got : { *(.got) *(.igot) } + . = DATA_SEGMENT_RELRO_END (24, .); + .got.plt : { *(.got.plt) *(.igot.plt) } + .data : + { + *(.data .data.* .gnu.linkonce.d.*) + KEEP (*(.gnu.linkonce.d.*personality*)) + SORT(CONSTRUCTORS) + } + .data1 : { *(.data1) } + _edata = .; PROVIDE (edata = .); + __bss_start = .; + .bss : + { + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + /* Align here to ensure that the .bss section occupies space up to + _end. Align after .bss to ensure correct alignment even if the + .bss section disappears because there are no input sections. + FIXME: Why do we need it? When there is no .bss section, we don't + pad the .data section. */ + . = ALIGN(. != 0 ? 64 / 8 : 1); + } + .lbss : + { + *(.dynlbss) + *(.lbss .lbss.* .gnu.linkonce.lb.*) + *(LARGE_COMMON) + } + . = ALIGN(64 / 8); + .lrodata ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) : + { + *(.lrodata .lrodata.* .gnu.linkonce.lr.*) + } + .ldata ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) : + { + *(.ldata .ldata.* .gnu.linkonce.l.*) + . = ALIGN(. != 0 ? 64 / 8 : 1); + } + . = ALIGN(64 / 8); + _end = .; PROVIDE (end = .); + . = DATA_SEGMENT_END (.); + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to the beginning + of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /* DWARF 3 */ + .debug_pubtypes 0 : { *(.debug_pubtypes) } + .debug_ranges 0 : { *(.debug_ranges) } + .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) } + /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) } +} diff --git a/l4/pkg/ldscripts/ARCH-amd64/main_stat.ld b/l4/pkg/ldscripts/ARCH-amd64/main_stat.ld new file mode 100644 index 00000000..203c3e6f --- /dev/null +++ b/l4/pkg/ldscripts/ARCH-amd64/main_stat.ld @@ -0,0 +1,265 @@ +/* -*- Makefile -*- */ +ENTRY(_start) + +PHDRS +{ + phdr PT_PHDR PHDRS; + ro PT_LOAD FILEHDR PHDRS; + rw PT_LOAD; + tls PT_TLS; + L4_DEFINE_L4PHDRS +} + + +SECTIONS +{ + L4_DEFINE_X86_KERNEL_ENTRY_SYMS + PROVIDE (__executable_start = 0x0100000); + . = __executable_start + SIZEOF_HEADERS; + + /* No program code/data before _stext/_prog_img_start! */ + + /* Read-only sections, merged into text segment. The start address of + * the text segment is : */ + /DISCARD/ : + { *(.note.gnu.build-id) + *(.hash) + *(.gnu.hash) + *(.dynsym) + *(.dynstr) + *(.gnu.version) + *(.gnu.version_d) + *(.gnu.version_r) + *(.rel.init) + *(.rela.init) + *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) + *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) + *(.rel.fini) + *(.rela.fini) + *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) + *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) + *(.rel.data.rel.ro* .rel.gnu.linkonce.d.rel.ro.*) + *(.rela.data.rel.ro* .rela.gnu.linkonce.d.rel.ro.*) + *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) + *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) + *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) + *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) + *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) + *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) + *(.rel.ctors) + *(.rela.ctors) + *(.rel.dtors) + *(.rela.dtors) + *(.rel.got) + *(.rela.got) + *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) + *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) + *(.rel.plt) + *(.rela.plt) + *(.stapsdt.*) + *(.note.stapsdt) + *(.plt) } + .text : ALIGN(0x1000) + { + _stext = .; + *(.text .text.* .gnu.linkonce.t.*) + *(.text .stub .text.* .gnu.linkonce.t.*) + KEEP (*(.text.*personality*)) + /* .gnu.warning sections are handled specially by elf32.em. */ + *(.gnu.warning) + } :ro =0x90909090 + .init : + { + KEEP (*(.init)) + } :ro =0x90909090 + .fini : + { + KEEP (*(.fini)) + } :ro = 0x9090 + + PROVIDE (_etext = .); + PROVIDE (etext = .); + .rol4re_elf_aux : { + KEEP (*(.rol4re_elf_aux)) + } : l4re_aux : ro + .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } : ro + .rodata1 : { *(.rodata1) } + .eh_frame_hdr : { *(.eh_frame_hdr) } :ro + + .eh_frame : ONLY_IF_RO + { + PROVIDE(__eh_frame_start__ = .); + KEEP (*(.eh_frame)) + KEEP (*(.eh_frame_terminator)) + } :ro + + .gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) } + + + . = ALIGN(CONSTANT(MAXPAGESIZE)); + /* Adjust the address for the data segment. We want to adjust up to + the same address within the page on the next page up. */ + . = ALIGN (CONSTANT (MAXPAGESIZE)) - ((CONSTANT (MAXPAGESIZE) - .) & (CONSTANT (MAXPAGESIZE) - 1)); . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE)); + PROVIDE (_sdata = .); + /* Exception handling */ + .eh_frame : ONLY_IF_RW + { + PROVIDE (__eh_frame_start__ = .); + KEEP (*(.eh_frame)) + KEEP (*(.eh_frame_terminator)) + } :rw + .gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) } :rw + /* Thread Local Storage sections */ + .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) } : rw : tls + .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } : rw + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + } + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(.fini_array)) + KEEP (*(SORT(.fini_array.*))) + PROVIDE_HIDDEN (__fini_array_end = .); + } + /* ensure that data starts at a new L4 page */ + /*. = ALIGN(0x1000);*/ + .ctors : + { + + /* gcc uses crtbegin.o to find the start of + the constructors, so we make sure it is + first. Because this is a wildcard, it + doesn't matter if the user does not + actually link against crtbegin.o; the + linker won't look for a file to match a + wildcard. The wildcard also means that it + doesn't matter which directory crtbegin.o + is in. */ + KEEP (*crtbegin.o(.ctors)) + KEEP (*crtbegin?.o(.ctors)) + /* We don't want to include the .ctor section from + the crtend.o file until after the sorted ctors. + The .ctor section from the crtend file contains the + end of ctors marker and it must be last */ + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + /* + KEEP (*(.mark_end_ctors)) + + KEEP (*(.mark_beg_c_ctors)) + KEEP (*(SORT(.c_ctors.?))) + KEEP (*(SORT(.c_ctors.??))) + KEEP (*(SORT(.c_ctors.???))) + KEEP (*(SORT(.c_ctors.????))) + KEEP (*(SORT(.c_ctors.?????))) + KEEP (*(.c_ctors)) + KEEP (*(.mark_end_c_ctors)) + */ + } :rw + + .dtors : + { + /* + KEEP (*(.mark_beg_dtors))*/ + KEEP (*crtbegin.o(.dtors)) + KEEP (*crtbegin?.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + /* + KEEP (*(.mark_end_dtors)) + + KEEP (*(.mark_beg_c_sys_dtors)) + KEEP (*(SORT(.c_dtors.?))) + KEEP (*(SORT(.c_dtors.??))) + KEEP (*(.mark_end_c_sys_dtors)) + + KEEP (*(.mark_beg_c_dtors)) + KEEP (*(SORT(.c_dtors.???))) + KEEP (*(SORT(.c_dtors.????))) + KEEP (*(SORT(.c_dtors.?????))) + KEEP (*(.c_dtors)) + KEEP (*(.mark_end_c_dtors))*/ + } + .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro* .gnu.linkonce.d.rel.ro.*) } + .dynamic : { *(.dynamic) } :rw + .got : { *(.got) } :rw + . = DATA_SEGMENT_RELRO_END (12, .); + .got.plt : { *(.got.plt) } + .data : + { + *(.data .data.* .gnu.linkonce.d.*) + KEEP (*(.gnu.linkonce.d.*personality*)) + SORT(CONSTRUCTORS) + } + .data1 : { *(.data1) } + _edata = .; PROVIDE (edata = .); + __bss_start = .; + .bss : + { + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + /* Align here to ensure that the .bss section occupies space up to + _end. Align after .bss to ensure correct alignment even if the + .bss section disappears because there are no input sections. + FIXME: Why do we need it? When there is no .bss section, we don't + pad the .data section. */ + . = ALIGN(. != 0 ? 64 / 8 : 1); + } + . = ALIGN(64 / 8); + . = ALIGN(64 / 8); + _end = .; PROVIDE (end = .); + . = DATA_SEGMENT_END (.); + . = ALIGN(CONSTANT(MAXPAGESIZE)); + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } :NONE + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to the beginning + of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /* DWARF 3 */ + .debug_pubtypes 0 : { *(.debug_pubtypes) } + .debug_ranges 0 : { *(.debug_ranges) } + .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) } + /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.interp) } +} diff --git a/l4/pkg/ldscripts/ARCH-arm/bits/arm_asm.h b/l4/pkg/ldscripts/ARCH-arm/bits/arm_asm.h new file mode 100644 index 00000000..e69de29b diff --git a/l4/pkg/ldscripts/ARCH-arm/main_dyn.ld b/l4/pkg/ldscripts/ARCH-arm/main_dyn.ld new file mode 100644 index 00000000..e829b257 --- /dev/null +++ b/l4/pkg/ldscripts/ARCH-arm/main_dyn.ld @@ -0,0 +1,222 @@ +/* -*- Makefile -*- */ +ENTRY(_start) + +PHDRS +{ + phdr PT_PHDR PHDRS; + interp PT_INTERP; + ro PT_LOAD FILEHDR PHDRS; + rw PT_LOAD; + dyn PT_DYNAMIC; + tls PT_TLS; + ehf PT_GNU_EH_FRAME; + L4_DEFINE_L4PHDRS +} + + +SECTIONS +{ + + /* Read-only sections, merged into text segment: */ + PROVIDE (__executable_start = 0x00008000); . = 0x00008000 + SIZEOF_HEADERS; + .interp : { *(.interp) } :ro :interp + .note.gnu.build-id : { *(.note.gnu.build-id) } :ro + .hash : { *(.hash) } + .gnu.hash : { *(.gnu.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .gnu.version : { *(.gnu.version) } + .gnu.version_d : { *(.gnu.version_d) } + .gnu.version_r : { *(.gnu.version_r) } + .rel.init : { *(.rel.init) } + .rela.init : { *(.rela.init) } + .rel.text : { *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) } + .rela.text : { *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) } + .rel.fini : { *(.rel.fini) } + .rela.fini : { *(.rela.fini) } + .rel.rodata : { *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) } + .rela.rodata : { *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) } + .rel.data.rel.ro : { *(.rel.data.rel.ro* .rel.gnu.linkonce.d.rel.ro.*) } + .rela.data.rel.ro : { *(.rela.data.rel.ro* .rela.gnu.linkonce.d.rel.ro.*) } + .rel.data : { *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) } + .rela.data : { *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) } + .rel.tdata : { *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) } + .rela.tdata : { *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) } + .rel.tbss : { *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) } + .rela.tbss : { *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) } + .rel.ctors : { *(.rel.ctors) } + .rela.ctors : { *(.rela.ctors) } + .rel.dtors : { *(.rel.dtors) } + .rela.dtors : { *(.rela.dtors) } + .rel.got : { *(.rel.got) } + .rela.got : { *(.rela.got) } + .rel.bss : { *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) } + .rela.bss : { *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) } + .rel.plt : { *(.rel.plt) } + .rela.plt : { *(.rela.plt) } + .init : + { + KEEP (*(.init)) + } =0 + .plt : { *(.plt) } + .text : + { + *(.text .stub .text.* .gnu.linkonce.t.*) + KEEP (*(.text.*personality*)) + /* .gnu.warning sections are handled specially by elf32.em. */ + *(.gnu.warning) + *(.glue_7t) *(.glue_7) *(.vfp11_veneer) + } =0 + .fini : + { + KEEP (*(.fini)) + } =0 + PROVIDE (__etext = .); + PROVIDE (_etext = .); + PROVIDE (etext = .); + .rol4re_elf_aux : { + KEEP (*(.rol4re_elf_aux)) + } : ro : l4re_aux + .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } : ro + .rodata1 : { *(.rodata1) } + .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } + __exidx_start = .; + .ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) } + __exidx_end = .; + .eh_frame_hdr : { *(.eh_frame_hdr) } :ehf :ro + .eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) } :ro + .gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) } :ro + /* Adjust the address for the data segment. We want to adjust up to + the same address within the page on the next page up. */ + . = ALIGN (CONSTANT (MAXPAGESIZE)) - ((CONSTANT (MAXPAGESIZE) - .) & (CONSTANT (MAXPAGESIZE) - 1)); . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE)); + PROVIDE (_sdata = .); + /* Exception handling */ + .eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) } :rw + .gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) } :rw + /* Thread Local Storage sections */ + .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) } :rw : tls + .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } : rw + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + } + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(.fini_array)) + KEEP (*(SORT(.fini_array.*))) + PROVIDE_HIDDEN (__fini_array_end = .); + } + .ctors : + { + /* gcc uses crtbegin.o to find the start of + the constructors, so we make sure it is + first. Because this is a wildcard, it + doesn't matter if the user does not + actually link against crtbegin.o; the + linker won't look for a file to match a + wildcard. The wildcard also means that it + doesn't matter which directory crtbegin.o + is in. */ + KEEP (*crtbegin.o(.ctors)) + KEEP (*crtbegin?.o(.ctors)) + /* We don't want to include the .ctor section from + the crtend.o file until after the sorted ctors. + The .ctor section from the crtend file contains the + end of ctors marker and it must be last */ + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + } + .dtors : + { + KEEP (*crtbegin.o(.dtors)) + KEEP (*crtbegin?.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + } + .jcr : { KEEP (*(.jcr)) } + .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro* .gnu.linkonce.d.rel.ro.*) } + .dynamic : { *(.dynamic) } :dyn :rw + . = DATA_SEGMENT_RELRO_END (0, .); + .got : { *(.got.plt) *(.got) } :rw + .data : + { + __data_start = . ; + *(.data .data.* .gnu.linkonce.d.*) + KEEP (*(.gnu.linkonce.d.*personality*)) + SORT(CONSTRUCTORS) + } :rw + .data1 : { *(.data1) } + _edata = .; PROVIDE (edata = .); + __bss_start = .; + __bss_start__ = .; + .bss : + { + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + /* Align here to ensure that the .bss section occupies space up to + _end. Align after .bss to ensure correct alignment even if the + .bss section disappears because there are no input sections. + FIXME: Why do we need it? When there is no .bss section, we don't + pad the .data section. */ + . = ALIGN(. != 0 ? 32 / 8 : 1); + } + _bss_end__ = . ; __bss_end__ = . ; + . = ALIGN(32 / 8); + . = ALIGN(32 / 8); + __end__ = . ; + _end = .; PROVIDE (end = .); + . = DATA_SEGMENT_END (.); + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to the beginning + of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /* DWARF 3 */ + .debug_pubtypes 0 : { *(.debug_pubtypes) } + .debug_ranges 0 : { *(.debug_ranges) } + .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) } + .note.gnu.arm.ident 0 : { KEEP (*(.note.gnu.arm.ident)) } + /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) } +} + diff --git a/l4/pkg/ldscripts/ARCH-arm/main_rel.ld b/l4/pkg/ldscripts/ARCH-arm/main_rel.ld new file mode 100644 index 00000000..58822186 --- /dev/null +++ b/l4/pkg/ldscripts/ARCH-arm/main_rel.ld @@ -0,0 +1,209 @@ +ENTRY(_start) +SECTIONS +{ + /* Read-only sections, merged into text segment: */ + . = 0 + SIZEOF_HEADERS; + .note.gnu.build-id : { *(.note.gnu.build-id) } + .hash : { *(.hash) } + .gnu.hash : { *(.gnu.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .gnu.version : { *(.gnu.version) } + .gnu.version_d : { *(.gnu.version_d) } + .gnu.version_r : { *(.gnu.version_r) } + .rel.dyn : + { + *(.rel.init) + *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) + *(.rel.fini) + *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) + *(.rel.data.rel.ro* .rel.gnu.linkonce.d.rel.ro.*) + *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) + *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) + *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) + *(.rel.ctors) + *(.rel.dtors) + *(.rel.got) + *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) + *(.rel.iplt) + } + .rela.dyn : + { + *(.rela.init) + *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) + *(.rela.fini) + *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) + *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) + *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) + *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) + *(.rela.ctors) + *(.rela.dtors) + *(.rela.got) + *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) + *(.rela.iplt) + } + .rel.plt : + { + *(.rel.plt) + } + .rela.plt : + { + *(.rela.plt) + } + .init : + { + KEEP (*(.init)) + } =0 + .plt : { *(.plt) } + .iplt : { *(.iplt) } + .text : + { + *(.text.unlikely .text.*_unlikely) + *(.text .stub .text.* .gnu.linkonce.t.*) + KEEP (*(.text.*personality*)) + /* .gnu.warning sections are handled specially by elf32.em. */ + *(.gnu.warning) + *(.glue_7t) *(.glue_7) *(.vfp11_veneer) *(.v4_bx) + } =0 + .fini : + { + KEEP (*(.fini)) + } =0 + PROVIDE (__etext = .); + PROVIDE (_etext = .); + PROVIDE (etext = .); + .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } + .rodata1 : { *(.rodata1) } + .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } + PROVIDE_HIDDEN (__exidx_start = .); + .ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) } + PROVIDE_HIDDEN (__exidx_end = .); + .eh_frame_hdr : { *(.eh_frame_hdr) } + .eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) } + .gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) } + /* Adjust the address for the data segment. We want to adjust up to + the same address within the page on the next page up. */ + . = ALIGN (CONSTANT (MAXPAGESIZE)) - ((CONSTANT (MAXPAGESIZE) - .) & (CONSTANT (MAXPAGESIZE) - 1)); . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE)); + /* Exception handling */ + .eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) } + .gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) } + /* Thread Local Storage sections */ + .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) } + .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } + .preinit_array : + { + KEEP (*(.preinit_array)) + } + .init_array : + { + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + } + .fini_array : + { + KEEP (*(SORT(.fini_array.*))) + KEEP (*(.fini_array)) + } + .ctors : + { + /* gcc uses crtbegin.o to find the start of + the constructors, so we make sure it is + first. Because this is a wildcard, it + doesn't matter if the user does not + actually link against crtbegin.o; the + linker won't look for a file to match a + wildcard. The wildcard also means that it + doesn't matter which directory crtbegin.o + is in. */ + KEEP (*crtbegin.o(.ctors)) + KEEP (*crtbegin?.o(.ctors)) + /* We don't want to include the .ctor section from + the crtend.o file until after the sorted ctors. + The .ctor section from the crtend file contains the + end of ctors marker and it must be last */ + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + } + .dtors : + { + KEEP (*crtbegin.o(.dtors)) + KEEP (*crtbegin?.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + } + .jcr : { KEEP (*(.jcr)) } + .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro* .gnu.linkonce.d.rel.ro.*) } + .dynamic : { *(.dynamic) } + . = DATA_SEGMENT_RELRO_END (0, .); + .got : { *(.got.plt) *(.igot.plt) *(.got) *(.igot) } + .data : + { + PROVIDE (__data_start = .); + *(.data .data.* .gnu.linkonce.d.*) + KEEP (*(.gnu.linkonce.d.*personality*)) + SORT(CONSTRUCTORS) + } + .data1 : { *(.data1) } + _edata = .; PROVIDE (edata = .); + __bss_start = .; + __bss_start__ = .; + .bss : + { + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + /* Align here to ensure that the .bss section occupies space up to + _end. Align after .bss to ensure correct alignment even if the + .bss section disappears because there are no input sections. + FIXME: Why do we need it? When there is no .bss section, we don't + pad the .data section. */ + . = ALIGN(. != 0 ? 32 / 8 : 1); + } + _bss_end__ = . ; __bss_end__ = . ; + . = ALIGN(32 / 8); + . = ALIGN(32 / 8); + __end__ = . ; + _end = .; PROVIDE (end = .); + . = DATA_SEGMENT_END (.); + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to the beginning + of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /* DWARF 3 */ + .debug_pubtypes 0 : { *(.debug_pubtypes) } + .debug_ranges 0 : { *(.debug_ranges) } + .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) } + .note.gnu.arm.ident 0 : { KEEP (*(.note.gnu.arm.ident)) } + /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) } +} diff --git a/l4/pkg/ldscripts/ARCH-arm/main_stat.ld b/l4/pkg/ldscripts/ARCH-arm/main_stat.ld new file mode 100644 index 00000000..ef38a7da --- /dev/null +++ b/l4/pkg/ldscripts/ARCH-arm/main_stat.ld @@ -0,0 +1,274 @@ +/* -*- Makefile -*- */ +OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", + "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) + +PHDRS +{ + phdr PT_PHDR PHDRS; + ro PT_LOAD FILEHDR PHDRS; + rw PT_LOAD; + tls PT_TLS; + L4_DEFINE_L4PHDRS +} + + +SECTIONS +{ + PROVIDE (__executable_start = 0x010000); + . = __executable_start + SIZEOF_HEADERS; + /* No program code/data before _stext/_prog_img_start! */ + + /* Read-only sections, merged into text segment. The start address of + * the text segment is : */ + /DISCARD/ : + { *(.note.gnu.build-id) + *(.hash) + *(.gnu.hash) + *(.dynsym) + *(.dynstr) + *(.gnu.version) + *(.gnu.version_d) + *(.gnu.version_r) + *(.rel.init) + *(.rela.init) + *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) + *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) + *(.rel.fini) + *(.rela.fini) + *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) + *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) + *(.rel.data.rel.ro* .rel.gnu.linkonce.d.rel.ro.*) + *(.rela.data.rel.ro* .rela.gnu.linkonce.d.rel.ro.*) + *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) + *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) + *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) + *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) + *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) + *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) + *(.rel.ctors) + *(.rela.ctors) + *(.rel.dtors) + *(.rela.dtors) + *(.rel.got) + *(.rela.got) + *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) + *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) + *(.rel.plt) + *(.rela.plt) + *(.plt) } + .text : + { + _stext = .; + _prog_img_start = _stext; + *(.text.init) + *(.init) + *(.text .text.* .gnu.linkonce.t.*) + KEEP (*(.text.*personality*)) + *(.glue_7t) *(.glue_7) + /* .gnu.warning sections are handled specially by elf32.em. */ + *(.gnu.warning) + } :ro = 0 + .init : + { + KEEP (*(.init)) + } =0x90909090 + .fini : + { + KEEP (*(.fini)) + /* LONG(0xc3) * terminate .fini */ + } = 0x9090 + . = ALIGN(0x40); + PROVIDE (_etext = .); + PROVIDE (etext = .); + .rol4re_elf_aux : { + KEEP (*(.rol4re_elf_aux)) + } : ro : l4re_aux + .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } : ro + .rodata1 : { *(.rodata1) } + .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } + __exidx_start = .; + .ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) } + __exidx_end = .; + .eh_frame_hdr : { *(.eh_frame_hdr) } :ro + + .eh_frame : ONLY_IF_RO + { +/* PROVIDE(__eh_frame_start__ = .);*/ + KEEP (*(.eh_frame)) +/* KEEP (*(.eh_frame_terminator)) */ + } :ro + + .gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) } + + . = ALIGN(CONSTANT(MAXPAGESIZE)); + /* Adjust the address for the data segment. We want to adjust up to + the same address within the page on the next page up. */ + . = ALIGN (CONSTANT (MAXPAGESIZE)) - ((CONSTANT (MAXPAGESIZE) - .) & (CONSTANT (MAXPAGESIZE) - 1)); . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE)); + PROVIDE (_sdata = .); + /* Exception handling */ + .eh_frame : ONLY_IF_RW + { +/* PROVIDE (__eh_frame_start__ = .); */ + KEEP (*(.eh_frame)) +/* KEEP (*(.eh_frame_terminator)) */ + } :rw + .gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) } :rw + /* Thread Local Storage sections */ + .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) } :rw : tls + .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } : rw + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + } + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(.fini_array)) + KEEP (*(SORT(.fini_array.*))) + PROVIDE_HIDDEN (__fini_array_end = .); + } + /* ensure that data starts at a new L4 page */ + . = ALIGN(4K); + .ctors : + { +/* + KEEP (*(.mark_beg_l4dde_ctors)) + KEEP (*(.l4dde_ctors)) + KEEP (*(.mark_end_l4dde_ctors)) + + KEEP (*(.mark_beg_ctors)) +*/ + + /* gcc uses crtbegin.o to find the start of + the constructors, so we make sure it is + first. Because this is a wildcard, it + doesn't matter if the user does not + actually link against crtbegin.o; the + linker won't look for a file to match a + wildcard. The wildcard also means that it + doesn't matter which directory crtbegin.o + is in. */ + KEEP (*crtbegin.o(.ctors)) + KEEP (*crtbegin?.o(.ctors)) + /* We don't want to include the .ctor section from + the crtend.o file until after the sorted ctors. + The .ctor section from the crtend file contains the + end of ctors marker and it must be last */ + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + /* + KEEP (*(.mark_end_ctors)) + + KEEP (*(.mark_beg_c_ctors)) + KEEP (*(SORT(.c_ctors.?))) + KEEP (*(SORT(.c_ctors.??))) + KEEP (*(SORT(.c_ctors.???))) + KEEP (*(SORT(.c_ctors.????))) + KEEP (*(SORT(.c_ctors.?????))) + KEEP (*(.c_ctors)) + KEEP (*(.mark_end_c_ctors)) + */ + } :rw + . = ALIGN(4); + .dtors : + { + /* + KEEP (*(.mark_beg_dtors))*/ + KEEP (*crtbegin.o(.dtors)) + KEEP (*crtbegin?.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + /* + KEEP (*(.mark_end_dtors)) + + KEEP (*(.mark_beg_c_sys_dtors)) + KEEP (*(SORT(.c_dtors.?))) + KEEP (*(SORT(.c_dtors.??))) + KEEP (*(.mark_end_c_sys_dtors)) + + KEEP (*(.mark_beg_c_dtors)) + KEEP (*(SORT(.c_dtors.???))) + KEEP (*(SORT(.c_dtors.????))) + KEEP (*(SORT(.c_dtors.?????))) + KEEP (*(.c_dtors)) + KEEP (*(.mark_end_c_dtors))*/ + } + .got : { *(.got.plt) *(.igot.plt) *(.got) *(.igot) } + .data : + { + *(.data .data.* .gnu.linkonce.d.*) + KEEP (*(.gnu.linkonce.d.*personality*)) + SORT(CONSTRUCTORS) + } + .data1 : { *(.data1) } + _edata = .; PROVIDE (edata = .); + __bss_start = .; + .bss : + { + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + /* Align here to ensure that the .bss section occupies space up to + _end. Align after .bss to ensure correct alignment even if the + .bss section disappears because there are no input sections. + FIXME: Why do we need it? When there is no .bss section, we don't + pad the .data section. */ + . = ALIGN(. != 0 ? 32 / 8 : 1); + } + . = ALIGN(32 / 8); + . = ALIGN(32 / 8); + _end = .; PROVIDE (end = .); + . = DATA_SEGMENT_END (.); + . = ALIGN(CONSTANT(MAXPAGESIZE)); + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } :NONE + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to the beginning + of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /* DWARF 3 */ + .debug_pubtypes 0 : { *(.debug_pubtypes) } + .debug_ranges 0 : { *(.debug_ranges) } + .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) } + /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.interp) } +} diff --git a/l4/pkg/ldscripts/ARCH-ppc32/main_dyn.ld b/l4/pkg/ldscripts/ARCH-ppc32/main_dyn.ld new file mode 100644 index 00000000..93d17075 --- /dev/null +++ b/l4/pkg/ldscripts/ARCH-ppc32/main_dyn.ld @@ -0,0 +1,249 @@ +/* Default linker script, for normal executables */ +OUTPUT_FORMAT("elf32-powerpc", "elf32-powerpc", + "elf32-powerpc") +OUTPUT_ARCH(powerpc:common) +ENTRY(_start) +SEARCH_DIR("=/usr/local/lib"); SEARCH_DIR("=/lib"); SEARCH_DIR("=/usr/lib"); + +PHDRS +{ + phdr PT_PHDR PHDRS; + interp PT_INTERP; + ro PT_LOAD FILEHDR PHDRS; + rw PT_LOAD; + dyn PT_DYNAMIC; + ehf PT_GNU_EH_FRAME; + L4_DEFINE_L4PHDRS +} + +SECTIONS +{ + /* Read-only sections, merged into text segment: */ + PROVIDE (__executable_start = 0x10000000); . = 0x10000000 + SIZEOF_HEADERS; + .interp : { *(.interp) } + .note.gnu.build-id : { *(.note.gnu.build-id) } + .hash : { *(.hash) } + .gnu.hash : { *(.gnu.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .gnu.version : { *(.gnu.version) } + .gnu.version_d : { *(.gnu.version_d) } + .gnu.version_r : { *(.gnu.version_r) } + .rel.init : { *(.rel.init) } + .rela.init : { *(.rela.init) } + .rel.text : { *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) } + .rela.text : { *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) } + .rel.fini : { *(.rel.fini) } + .rela.fini : { *(.rela.fini) } + .rel.rodata : { *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) } + .rela.rodata : { *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) } + .rel.data.rel.ro : { *(.rel.data.rel.ro* .rel.gnu.linkonce.d.rel.ro.*) } + .rela.data.rel.ro : { *(.rela.data.rel.ro* .rela.gnu.linkonce.d.rel.ro.*) } + .rel.data : { *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) } + .rela.data : { *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) } + .rel.tdata : { *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) } + .rela.tdata : { *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) } + .rel.tbss : { *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) } + .rela.tbss : { *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) } + .rel.ctors : { *(.rel.ctors) } + .rela.ctors : { *(.rela.ctors) } + .rel.dtors : { *(.rel.dtors) } + .rela.dtors : { *(.rela.dtors) } + .rel.got : { *(.rel.got) } + .rela.got : { *(.rela.got) } + .rela.got1 : { *(.rela.got1) } + .rela.got2 : { *(.rela.got2) } + .rel.sdata : { *(.rel.sdata .rel.sdata.* .rel.gnu.linkonce.s.*) } + .rela.sdata : { *(.rela.sdata .rela.sdata.* .rela.gnu.linkonce.s.*) } + .rel.sbss : { *(.rel.sbss .rel.sbss.* .rel.gnu.linkonce.sb.*) } + .rela.sbss : { *(.rela.sbss .rela.sbss.* .rela.gnu.linkonce.sb.*) } + .rel.sdata2 : { *(.rel.sdata2 .rel.sdata2.* .rel.gnu.linkonce.s2.*) } + .rela.sdata2 : { *(.rela.sdata2 .rela.sdata2.* .rela.gnu.linkonce.s2.*) } + .rel.sbss2 : { *(.rel.sbss2 .rel.sbss2.* .rel.gnu.linkonce.sb2.*) } + .rela.sbss2 : { *(.rela.sbss2 .rela.sbss2.* .rela.gnu.linkonce.sb2.*) } + .rel.bss : { *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) } + .rela.bss : { *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) } + .rel.plt : { *(.rel.plt) } + .rela.plt : { *(.rela.plt) } + .init : + { + KEEP (*(.init)) + } =0 + .text : + { + *(.text .stub .text.* .gnu.linkonce.t.*) + KEEP (*(.text.*personality*)) + /* .gnu.warning sections are handled specially by elf32.em. */ + *(.gnu.warning) + *(.glink) + } =0 + .fini : + { + KEEP (*(.fini)) + } =0 + PROVIDE (__etext = .); + PROVIDE (_etext = .); + PROVIDE (etext = .); + .rol4re_elf_aux : { + KEEP (*(.rol4re_elf_aux)) + } : ro : l4re_aux + .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } : ro + .rodata1 : { *(.rodata1) } + .sdata2 : + { + PROVIDE (_SDA2_BASE_ = 32768); + *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) + } + .sbss2 : { *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) } + .eh_frame_hdr : { *(.eh_frame_hdr) } + .eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) } + .gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) } + /* Adjust the address for the data segment. We want to adjust up to + the same address within the page on the next page up. */ + . = ALIGN (CONSTANT (MAXPAGESIZE)) - ((CONSTANT (MAXPAGESIZE) - .) & (CONSTANT (MAXPAGESIZE) - 1)); . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE)); + /* Exception handling */ + .eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) } + .gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) } + /* Thread Local Storage sections */ + .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) } + .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + } + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(.fini_array)) + KEEP (*(SORT(.fini_array.*))) + PROVIDE_HIDDEN (__fini_array_end = .); + } + .ctors : + { + /* gcc uses crtbegin.o to find the start of + the constructors, so we make sure it is + first. Because this is a wildcard, it + doesn't matter if the user does not + actually link against crtbegin.o; the + linker won't look for a file to match a + wildcard. The wildcard also means that it + doesn't matter which directory crtbegin.o + is in. */ + KEEP (*crtbegin.o(.ctors)) + KEEP (*crtbegin?.o(.ctors)) + /* We don't want to include the .ctor section from + the crtend.o file until after the sorted ctors. + The .ctor section from the crtend file contains the + end of ctors marker and it must be last */ + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + } + .dtors : + { + KEEP (*crtbegin.o(.dtors)) + KEEP (*crtbegin?.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + } + .jcr : { KEEP (*(.jcr)) } + .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro* .gnu.linkonce.d.rel.ro.*) } + .got1 : { *(.got1) } + .got2 : { *(.got2) } + .dynamic : { *(.dynamic) } + .got : SPECIAL { *(.got) } + . = DATA_SEGMENT_RELRO_END (0, .); + .plt : SPECIAL { *(.plt) } + .data : + { + *(.data .data.* .gnu.linkonce.d.*) + KEEP (*(.gnu.linkonce.d.*personality*)) + SORT(CONSTRUCTORS) + } + .data1 : { *(.data1) } + .got : SPECIAL { *(.got) } + /* We want the small data sections together, so single-instruction offsets + can access them all, and initialized data all before uninitialized, so + we can shorten the on-disk segment size. */ + .sdata : + { + PROVIDE (_SDA_BASE_ = 32768); + *(.sdata .sdata.* .gnu.linkonce.s.*) + } + _edata = .; PROVIDE (edata = .); + __bss_start = .; + .sbss : + { + PROVIDE (__sbss_start = .); PROVIDE (___sbss_start = .); + *(.dynsbss) + *(.sbss .sbss.* .gnu.linkonce.sb.*) + *(.scommon) + PROVIDE (__sbss_end = .); PROVIDE (___sbss_end = .); + } + .plt : SPECIAL { *(.plt) } + .bss : + { + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + /* Align here to ensure that the .bss section occupies space up to + _end. Align after .bss to ensure correct alignment even if the + .bss section disappears because there are no input sections. + FIXME: Why do we need it? When there is no .bss section, we don't + pad the .data section. */ + . = ALIGN(. != 0 ? 32 / 8 : 1); + } + . = ALIGN(32 / 8); + . = ALIGN(32 / 8); + _end = .; PROVIDE (end = .); + . = DATA_SEGMENT_END (.); + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to the beginning + of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /* DWARF 3 */ + .debug_pubtypes 0 : { *(.debug_pubtypes) } + .debug_ranges 0 : { *(.debug_ranges) } + .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) } + /DISCARD/ : { *(.fixup) } + /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) } +} diff --git a/l4/pkg/ldscripts/ARCH-ppc32/main_rel.ld b/l4/pkg/ldscripts/ARCH-ppc32/main_rel.ld new file mode 100644 index 00000000..47d27bcb --- /dev/null +++ b/l4/pkg/ldscripts/ARCH-ppc32/main_rel.ld @@ -0,0 +1,225 @@ +/* Script for ld --shared: link shared library */ +OUTPUT_FORMAT("elf32-powerpc", "elf32-powerpc", + "elf32-powerpc") +OUTPUT_ARCH(powerpc:common) +ENTRY(_start) +SEARCH_DIR("=/usr/local/lib"); SEARCH_DIR("=/lib"); SEARCH_DIR("=/usr/lib"); +SECTIONS +{ + /* Read-only sections, merged into text segment: */ + . = 0 + SIZEOF_HEADERS; + .note.gnu.build-id : { *(.note.gnu.build-id) } + .hash : { *(.hash) } + .gnu.hash : { *(.gnu.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .gnu.version : { *(.gnu.version) } + .gnu.version_d : { *(.gnu.version_d) } + .gnu.version_r : { *(.gnu.version_r) } + .rel.dyn : + { + *(.rel.init) + *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) + *(.rel.fini) + *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) + *(.rel.data.rel.ro* .rel.gnu.linkonce.d.rel.ro.*) + *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) + *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) + *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) + *(.rel.ctors) + *(.rel.dtors) + *(.rel.got) + *(.rel.sdata .rel.sdata.* .rel.gnu.linkonce.s.*) + *(.rel.sbss .rel.sbss.* .rel.gnu.linkonce.sb.*) + *(.rel.sdata2 .rel.sdata2.* .rel.gnu.linkonce.s2.*) + *(.rel.sbss2 .rel.sbss2.* .rel.gnu.linkonce.sb2.*) + *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) + } + .rela.dyn : + { + *(.rela.init) + *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) + *(.rela.fini) + *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) + *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) + *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) + *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) + *(.rela.ctors) + *(.rela.dtors) + *(.rela.got) + *(.rela.got1) + *(.rela.got2) + *(.rela.sdata .rela.sdata.* .rela.gnu.linkonce.s.*) + *(.rela.sbss .rela.sbss.* .rela.gnu.linkonce.sb.*) + *(.rela.sdata2 .rela.sdata2.* .rela.gnu.linkonce.s2.*) + *(.rela.sbss2 .rela.sbss2.* .rela.gnu.linkonce.sb2.*) + *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) + } + .rel.plt : { *(.rel.plt) } + .rela.plt : { *(.rela.plt) } + .init : + { + KEEP (*(.init)) + } =0 + .text : + { + *(.text .stub .text.* .gnu.linkonce.t.*) + KEEP (*(.text.*personality*)) + /* .gnu.warning sections are handled specially by elf32.em. */ + *(.gnu.warning) + *(.glink) + } =0 + .fini : + { + KEEP (*(.fini)) + } =0 + PROVIDE (__etext = .); + PROVIDE (_etext = .); + PROVIDE (etext = .); + .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } + .rodata1 : { *(.rodata1) } + .eh_frame_hdr : { *(.eh_frame_hdr) } + .eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) } + .gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) } + /* Adjust the address for the data segment. We want to adjust up to + the same address within the page on the next page up. */ + . = ALIGN (CONSTANT (MAXPAGESIZE)) - ((CONSTANT (MAXPAGESIZE) - .) & (CONSTANT (MAXPAGESIZE) - 1)); . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE)); + /* Exception handling */ + .eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) } + .gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) } + /* Thread Local Storage sections */ + .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) } + .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } + .preinit_array : + { + KEEP (*(.preinit_array)) + } + .init_array : + { + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + } + .fini_array : + { + KEEP (*(.fini_array)) + KEEP (*(SORT(.fini_array.*))) + } + .ctors : + { + /* gcc uses crtbegin.o to find the start of + the constructors, so we make sure it is + first. Because this is a wildcard, it + doesn't matter if the user does not + actually link against crtbegin.o; the + linker won't look for a file to match a + wildcard. The wildcard also means that it + doesn't matter which directory crtbegin.o + is in. */ + KEEP (*crtbegin.o(.ctors)) + KEEP (*crtbegin?.o(.ctors)) + /* We don't want to include the .ctor section from + the crtend.o file until after the sorted ctors. + The .ctor section from the crtend file contains the + end of ctors marker and it must be last */ + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + } + .dtors : + { + KEEP (*crtbegin.o(.dtors)) + KEEP (*crtbegin?.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + } + .jcr : { KEEP (*(.jcr)) } + .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro* .gnu.linkonce.d.rel.ro.*) } + .got1 : { *(.got1) } + .got2 : { *(.got2) } + .dynamic : { *(.dynamic) } + .got : SPECIAL { *(.got) } + . = DATA_SEGMENT_RELRO_END (0, .); + .plt : SPECIAL { *(.plt) } + .data : + { + *(.data .data.* .gnu.linkonce.d.*) + KEEP (*(.gnu.linkonce.d.*personality*)) + SORT(CONSTRUCTORS) + } + .data1 : { *(.data1) } + .got : SPECIAL { *(.got) } + /* We want the small data sections together, so single-instruction offsets + can access them all, and initialized data all before uninitialized, so + we can shorten the on-disk segment size. */ + .sdata : + { + *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) + *(.sdata .sdata.* .gnu.linkonce.s.*) + } + _edata = .; PROVIDE (edata = .); + __bss_start = .; + .sbss : + { + *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) + *(.dynsbss) + *(.sbss .sbss.* .gnu.linkonce.sb.*) + *(.scommon) + } + .plt : SPECIAL { *(.plt) } + .bss : + { + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + /* Align here to ensure that the .bss section occupies space up to + _end. Align after .bss to ensure correct alignment even if the + .bss section disappears because there are no input sections. + FIXME: Why do we need it? When there is no .bss section, we don't + pad the .data section. */ + . = ALIGN(. != 0 ? 32 / 8 : 1); + } + . = ALIGN(32 / 8); + . = ALIGN(32 / 8); + _end = .; PROVIDE (end = .); + . = DATA_SEGMENT_END (.); + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to the beginning + of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /* DWARF 3 */ + .debug_pubtypes 0 : { *(.debug_pubtypes) } + .debug_ranges 0 : { *(.debug_ranges) } + .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) } + /DISCARD/ : { *(.fixup) } + /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) } +} diff --git a/l4/pkg/ldscripts/ARCH-ppc32/main_stat.ld b/l4/pkg/ldscripts/ARCH-ppc32/main_stat.ld new file mode 100644 index 00000000..32b5eb9e --- /dev/null +++ b/l4/pkg/ldscripts/ARCH-ppc32/main_stat.ld @@ -0,0 +1,256 @@ +/* Default linker script, for normal executables */ +OUTPUT_FORMAT("elf32-powerpc", "elf32-powerpc", + "elf32-powerpc") +OUTPUT_ARCH(powerpc:common) +ENTRY(_start) +SEARCH_DIR("=/usr/local/lib"); SEARCH_DIR("=/lib"); SEARCH_DIR("=/usr/lib"); + +PHDRS +{ + phdr PT_PHDR PHDRS; + ro PT_LOAD FILEHDR PHDRS; + rw PT_LOAD; + L4_DEFINE_L4PHDRS +} + +SECTIONS +{ + PROVIDE (__executable_start = 0x010000); + . = __executable_start + SIZEOF_HEADERS; + /* Read-only sections, merged into text segment: */ + /* PROVIDE (__executable_start = 0x10000000); . = 0x10000000 + SIZEOF_HEADERS; + */ + /DISCARD/ : + { *(.interp) + *(.note.gnu.build-id) + *(.hash) + *(.gnu.hash) + *(.dynsym) + *(.dynstr) + *(.gnu.version) + *(.gnu.version_d) + *(.gnu.version_r) + *(.rel.init) + *(.rela.init) + *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) + *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) + *(.rel.fini) + *(.rela.fini) + *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) + *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) + *(.rel.data.rel.ro* .rel.gnu.linkonce.d.rel.ro.*) + *(.rela.data.rel.ro* .rela.gnu.linkonce.d.rel.ro.*) + *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) + *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) + *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) + *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) + *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) + *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) + *(.rel.ctors) + *(.rela.ctors) + *(.rel.dtors) + *(.rela.dtors) + *(.rel.got) + *(.rela.got) + *(.rela.got1) + *(.rela.got2) + *(.rel.sdata .rel.sdata.* .rel.gnu.linkonce.s.*) + *(.rela.sdata .rela.sdata.* .rela.gnu.linkonce.s.*) + *(.rel.sbss .rel.sbss.* .rel.gnu.linkonce.sb.*) + *(.rela.sbss .rela.sbss.* .rela.gnu.linkonce.sb.*) + *(.rel.sdata2 .rel.sdata2.* .rel.gnu.linkonce.s2.*) + *(.rela.sdata2 .rela.sdata2.* .rela.gnu.linkonce.s2.*) + *(.rel.sbss2 .rel.sbss2.* .rel.gnu.linkonce.sb2.*) + *(.rela.sbss2 .rela.sbss2.* .rela.gnu.linkonce.sb2.*) + *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) + *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) + *(.rel.plt) + *(.rela.plt) } + .text : + { + _stext = .; + _program_img_start = _stext; + *(.text .stub .text.* .gnu.linkonce.t.*) + KEEP(*(.text.*personality*)) + /* .gnu.warning sections are handled specially by elf32.em. */ + *(.gnu.warning) + *(.glink) + } :ro = 0 + .init : + { + KEEP (*(.init)) + } :ro = 0 + .fini : + { + KEEP (*(.fini)) + } :ro = 0 + PROVIDE (__etext = .); + PROVIDE (_etext = .); + PROVIDE (etext = .); + .rol4re_elf_aux : { + KEEP (*(.rol4re_elf_aux)) + } : ro : l4re_aux + .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } : ro + .rodata1 : { *(.rodata1) } + .sdata2 : + { + PROVIDE (_SDA2_BASE_ = 32768); + *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) + } + .sbss2 : { *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) } + .eh_frame_hdr : { *(.eh_frame_hdr) } :ro + .eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) } + .gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) } + . = ALIGN(CONSTANT(MAXPAGESIZE)); + /* Adjust the address for the data segment. We want to adjust up to + the same address within the page on the next page up. */ + . = ALIGN (CONSTANT (MAXPAGESIZE)) - ((CONSTANT (MAXPAGESIZE) - .) & (CONSTANT (MAXPAGESIZE) - 1)); . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE)); + + PROVIDE(_sdata = .); + /* Exception handling */ + .eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) } :rw + .gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) } :rw + /* Thread Local Storage sections */ + .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) } :rw + .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + } + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(.fini_array)) + KEEP (*(SORT(.fini_array.*))) + PROVIDE_HIDDEN (__fini_array_end = .); + } + /* . = ALIGN(0x1000); */ + .ctors : + { + /* gcc uses crtbegin.o to find the start of + the constructors, so we make sure it is + first. Because this is a wildcard, it + doesn't matter if the user does not + actually link against crtbegin.o; the + linker won't look for a file to match a + wildcard. The wildcard also means that it + doesn't matter which directory crtbegin.o + is in. */ + KEEP (*crtbegin.o(.ctors)) + KEEP (*crtbegin?.o(.ctors)) + /* We don't want to include the .ctor section from + the crtend.o file until after the sorted ctors. + The .ctor section from the crtend file contains the + end of ctors marker and it must be last */ + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + } + .dtors : + { + KEEP (*crtbegin.o(.dtors)) + KEEP (*crtbegin?.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + } + .jcr : { KEEP (*(.jcr)) } + .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro* .gnu.linkonce.d.rel.ro.*) } + .got1 : { *(.got1) } + .got2 : { *(.got2) } + .dynamic : { *(.dynamic) } + .got : SPECIAL { *(.got) } + . = DATA_SEGMENT_RELRO_END (0, .); + .plt : SPECIAL { *(.plt) } + .data : + { + *(.data .data.* .gnu.linkonce.d.*) + KEEP (*(.gnu.linkonce.d.*personality*)) + SORT(CONSTRUCTORS) + } + .data1 : { *(.data1) } + .got : SPECIAL { *(.got) } + /* We want the small data sections together, so single-instruction offsets + can access them all, and initialized data all before uninitialized, so + we can shorten the on-disk segment size. */ + .sdata : + { + PROVIDE (_SDA_BASE_ = 32768); + *(.sdata .sdata.* .gnu.linkonce.s.*) + } + _edata = .; PROVIDE (edata = .); + __bss_start = .; + .sbss : + { + PROVIDE (__sbss_start = .); PROVIDE (___sbss_start = .); + *(.dynsbss) + *(.sbss .sbss.* .gnu.linkonce.sb.*) + *(.scommon) + PROVIDE (__sbss_end = .); PROVIDE (___sbss_end = .); + } + .plt : SPECIAL { *(.plt) } + .bss : + { + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + /* Align here to ensure that the .bss section occupies space up to + _end. Align after .bss to ensure correct alignment even if the + .bss section disappears because there are no input sections. + FIXME: Why do we need it? When there is no .bss section, we don't + pad the .data section. */ + . = ALIGN(. != 0 ? 32 / 8 : 1); + } + . = ALIGN(32 / 8); + . = ALIGN(32 / 8); + _end = .; PROVIDE (end = .); + . = DATA_SEGMENT_END (.); + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to the beginning + of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /* DWARF 3 */ + .debug_pubtypes 0 : { *(.debug_pubtypes) } + .debug_ranges 0 : { *(.debug_ranges) } + .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) } + /DISCARD/ : { *(.fixup) } + /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) } +} diff --git a/l4/pkg/ldscripts/ARCH-sparc/bits/wordsize.h b/l4/pkg/ldscripts/ARCH-sparc/bits/wordsize.h new file mode 100644 index 00000000..c0e600ed --- /dev/null +++ b/l4/pkg/ldscripts/ARCH-sparc/bits/wordsize.h @@ -0,0 +1,20 @@ +/* Determine the wordsize from the preprocessor defines. */ + +#if defined __arch64__ || defined __sparcv9 +# define __WORDSIZE 64 +#else +# define __WORDSIZE 32 +#endif + +#if 0 /* uClibc: done in mathdefs.h: !defined __NO_LONG_DOUBLE_MATH && !defined __LONG_DOUBLE_MATH_OPTIONAL*/ + +# if __WORDSIZE == 32 +/* Signal that in 32bit ABI we didn't used to have a `long double'. + The changes all the `long double' function variants to be redirects + to the double functions. */ +# define __LONG_DOUBLE_MATH_OPTIONAL 1 +# ifndef __LONG_DOUBLE_128__ +# define __NO_LONG_DOUBLE_MATH 1 +# endif +# endif +#endif diff --git a/l4/pkg/ldscripts/ARCH-sparc/main_dyn.ld b/l4/pkg/ldscripts/ARCH-sparc/main_dyn.ld new file mode 100644 index 00000000..3dcf34a7 --- /dev/null +++ b/l4/pkg/ldscripts/ARCH-sparc/main_dyn.ld @@ -0,0 +1,253 @@ +/* Default linker script, for normal executables */ +OUTPUT_FORMAT("elf32-sparc", "elf32-sparc", + "elf32-sparc") +OUTPUT_ARCH(sparc) +ENTRY(_start) + + +PHDRS +{ + phdr PT_PHDR PHDRS; + interp PT_INTERP; + ro PT_LOAD FILEHDR PHDRS; + rw PT_LOAD; + dyn PT_DYNAMIC; + ehf PT_GNU_EH_FRAME; + L4_DEFINE_L4PHDRS +} + +SECTIONS +{ + /* Read-only sections, merged into text segment: */ + PROVIDE (__executable_start = 0x10000000); . = 0x10000000 + SIZEOF_HEADERS; + .interp : { *(.interp) } + .note.gnu.build-id : { *(.note.gnu.build-id) } + .hash : { *(.hash) } + .gnu.hash : { *(.gnu.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .gnu.version : { *(.gnu.version) } + .gnu.version_d : { *(.gnu.version_d) } + .gnu.version_r : { *(.gnu.version_r) } + .rel.init : { *(.rel.init) } + .rela.init : { *(.rela.init) } + .rel.text : { *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) } + .rela.text : { *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) } + .rel.fini : { *(.rel.fini) } + .rela.fini : { *(.rela.fini) } + .rel.rodata : { *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) } + .rela.rodata : { *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) } + .rel.data.rel.ro : { *(.rel.data.rel.ro* .rel.gnu.linkonce.d.rel.ro.*) } + .rela.data.rel.ro : { *(.rela.data.rel.ro* .rela.gnu.linkonce.d.rel.ro.*) } + .rel.data : { *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) } + .rela.data : { *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) } + .rel.tdata : { *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) } + .rela.tdata : { *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) } + .rel.tbss : { *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) } + .rela.tbss : { *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) } + .rel.ctors : { *(.rel.ctors) } + .rela.ctors : { *(.rela.ctors) } + .rel.dtors : { *(.rel.dtors) } + .rela.dtors : { *(.rela.dtors) } + .rel.got : { *(.rel.got) } + .rela.got : { *(.rela.got) } + .rela.got1 : { *(.rela.got1) } + .rela.got2 : { *(.rela.got2) } + .rel.sdata : { *(.rel.sdata .rel.sdata.* .rel.gnu.linkonce.s.*) } + .rela.sdata : { *(.rela.sdata .rela.sdata.* .rela.gnu.linkonce.s.*) } + .rel.sbss : { *(.rel.sbss .rel.sbss.* .rel.gnu.linkonce.sb.*) } + .rela.sbss : { *(.rela.sbss .rela.sbss.* .rela.gnu.linkonce.sb.*) } + .rel.sdata2 : { *(.rel.sdata2 .rel.sdata2.* .rel.gnu.linkonce.s2.*) } + .rela.sdata2 : { *(.rela.sdata2 .rela.sdata2.* .rela.gnu.linkonce.s2.*) } + .rel.sbss2 : { *(.rel.sbss2 .rel.sbss2.* .rel.gnu.linkonce.sb2.*) } + .rela.sbss2 : { *(.rela.sbss2 .rela.sbss2.* .rela.gnu.linkonce.sb2.*) } + .rel.bss : { *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) } + .rela.bss : { *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) } + .rel.plt : { *(.rel.plt) } + .rela.plt : { *(.rela.plt) } + .init : + { + KEEP (*(.init)) + } =0 + .text : + { + *(.text .stub .text.* .gnu.linkonce.t.*) + . = ALIGN (16); + KEEP (*(.text.*personality*)) + /* .gnu.warning sections are handled specially by elf32.em. */ + *(.gnu.warning) + *(.glink) + } =0 + .fini : + { + KEEP (*(.fini)) + } =0 + PROVIDE (__etext = .); + PROVIDE (_etext = .); + PROVIDE (etext = .); + .rol4re_elf_aux : { + KEEP (*(.rol4re_elf_aux)) + } : ro : l4re_aux + .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } : ro + .rodata1 : { *(.rodata1) } + .sdata2 : + { + PROVIDE (_SDA2_BASE_ = 32768); + *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) + } + .sbss2 : { *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) } + .eh_frame_hdr : { *(.eh_frame_hdr) } + .eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) } + .gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) } + /* Adjust the address for the data segment. We want to adjust up to + the same address within the page on the next page up. */ + . = ALIGN (CONSTANT (MAXPAGESIZE)) - ((CONSTANT (MAXPAGESIZE) - .) & (CONSTANT (MAXPAGESIZE) - 1)); . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE)); + /* Exception handling */ + .eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) } + .gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) } + /* Thread Local Storage sections */ + .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) } + .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + } + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(.fini_array)) + KEEP (*(SORT(.fini_array.*))) + PROVIDE_HIDDEN (__fini_array_end = .); + } + + .ctors : + { + /* gcc uses crtbegin.o to find the start of + the constructors, so we make sure it is + first. Because this is a wildcard, it + doesn't matter if the user does not + actually link against crtbegin.o; the + linker won't look for a file to match a + wildcard. The wildcard also means that it + doesn't matter which directory crtbegin.o + is in. */ + KEEP (*crtbegin.o(.ctors)) + KEEP (*crtbegin?.o(.ctors)) + /* We don't want to include the .ctor section from + the crtend.o file until after the sorted ctors. + The .ctor section from the crtend file contains the + end of ctors marker and it must be last */ + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + } + .dtors : + { + KEEP (*crtbegin.o(.dtors)) + KEEP (*crtbegin?.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + } + __DTOR_END__ = .; + + .jcr : { KEEP (*(.jcr)) } + .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro* .gnu.linkonce.d.rel.ro.*) } + .got1 : { *(.got1) } + .got2 : { *(.got2) } + .dynamic : { *(.dynamic) } + .got : SPECIAL { *(.got) } + . = DATA_SEGMENT_RELRO_END (0, .); + .plt : SPECIAL { *(.plt) } + .data : + { + *(.data .data.* .gnu.linkonce.d.*) + KEEP (*(.gnu.linkonce.d.*personality*)) + SORT(CONSTRUCTORS) + } + .data1 : { *(.data1) } + .got : SPECIAL { *(.got) } + /* We want the small data sections together, so single-instruction offsets + can access them all, and initialized data all before uninitialized, so + we can shorten the on-disk segment size. */ + .sdata : + { + PROVIDE (_SDA_BASE_ = 32768); + *(.sdata .sdata.* .gnu.linkonce.s.*) + } + _edata = .; PROVIDE (edata = .); + __bss_start = .; + .sbss : + { + PROVIDE (__sbss_start = .); PROVIDE (___sbss_start = .); + *(.dynsbss) + *(.sbss .sbss.* .gnu.linkonce.sb.*) + *(.scommon) + PROVIDE (__sbss_end = .); PROVIDE (___sbss_end = .); + } + .plt : SPECIAL { *(.plt) } + .bss : + { + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + /* Align here to ensure that the .bss section occupies space up to + _end. Align after .bss to ensure correct alignment even if the + .bss section disappears because there are no input sections. + FIXME: Why do we need it? When there is no .bss section, we don't + pad the .data section. */ + . = ALIGN(. != 0 ? 32 / 8 : 1); + } + . = ALIGN(32 / 8); + . = ALIGN(32 / 8); + _end = .; PROVIDE (end = .); + . = DATA_SEGMENT_END (.); + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to the beginning + of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /* DWARF 3 */ + .debug_pubtypes 0 : { *(.debug_pubtypes) } + .debug_ranges 0 : { *(.debug_ranges) } + .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) } + /DISCARD/ : { *(.fixup) } + /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) } +} diff --git a/l4/pkg/ldscripts/ARCH-sparc/main_rel.ld b/l4/pkg/ldscripts/ARCH-sparc/main_rel.ld new file mode 100644 index 00000000..ea36fab0 --- /dev/null +++ b/l4/pkg/ldscripts/ARCH-sparc/main_rel.ld @@ -0,0 +1,226 @@ +/* Script for ld --shared: link shared library */ +OUTPUT_FORMAT("elf32-sparc", "elf32-sparc", + "elf32-sparc") +OUTPUT_ARCH(sparc) +ENTRY(_start) + +SECTIONS +{ + /* Read-only sections, merged into text segment: */ + . = 0 + SIZEOF_HEADERS; + .note.gnu.build-id : { *(.note.gnu.build-id) } + .hash : { *(.hash) } + .gnu.hash : { *(.gnu.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .gnu.version : { *(.gnu.version) } + .gnu.version_d : { *(.gnu.version_d) } + .gnu.version_r : { *(.gnu.version_r) } + .rel.dyn : + { + *(.rel.init) + *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) + *(.rel.fini) + *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) + *(.rel.data.rel.ro* .rel.gnu.linkonce.d.rel.ro.*) + *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) + *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) + *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) + *(.rel.ctors) + *(.rel.dtors) + *(.rel.got) + *(.rel.sdata .rel.sdata.* .rel.gnu.linkonce.s.*) + *(.rel.sbss .rel.sbss.* .rel.gnu.linkonce.sb.*) + *(.rel.sdata2 .rel.sdata2.* .rel.gnu.linkonce.s2.*) + *(.rel.sbss2 .rel.sbss2.* .rel.gnu.linkonce.sb2.*) + *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) + } + .rela.dyn : + { + *(.rela.init) + *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) + *(.rela.fini) + *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) + *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) + *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) + *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) + *(.rela.ctors) + *(.rela.dtors) + *(.rela.got) + *(.rela.got1) + *(.rela.got2) + *(.rela.sdata .rela.sdata.* .rela.gnu.linkonce.s.*) + *(.rela.sbss .rela.sbss.* .rela.gnu.linkonce.sb.*) + *(.rela.sdata2 .rela.sdata2.* .rela.gnu.linkonce.s2.*) + *(.rela.sbss2 .rela.sbss2.* .rela.gnu.linkonce.sb2.*) + *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) + } + .rel.plt : { *(.rel.plt) } + .rela.plt : { *(.rela.plt) } + .init : + { + KEEP (*(.init)) + } =0 + .text : + { + *(.text .stub .text.* .gnu.linkonce.t.*) + KEEP (*(.text.*personality*)) + /* .gnu.warning sections are handled specially by elf32.em. */ + *(.gnu.warning) + *(.glink) + } =0 + .fini : + { + KEEP (*(.fini)) + } =0 + PROVIDE (__etext = .); + PROVIDE (_etext = .); + PROVIDE (etext = .); + .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } + .rodata1 : { *(.rodata1) } + .eh_frame_hdr : { *(.eh_frame_hdr) } + .eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) } + .gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) } + /* Adjust the address for the data segment. We want to adjust up to + the same address within the page on the next page up. */ + . = ALIGN (CONSTANT (MAXPAGESIZE)) - ((CONSTANT (MAXPAGESIZE) - .) & (CONSTANT (MAXPAGESIZE) - 1)); . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE)); + /* Exception handling */ + .eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) } + .gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) } + /* Thread Local Storage sections */ + .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) } + .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } + .preinit_array : + { + KEEP (*(.preinit_array)) + } + .init_array : + { + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + } + .fini_array : + { + KEEP (*(.fini_array)) + KEEP (*(SORT(.fini_array.*))) + } + .ctors : + { + /* gcc uses crtbegin.o to find the start of + the constructors, so we make sure it is + first. Because this is a wildcard, it + doesn't matter if the user does not + actually link against crtbegin.o; the + linker won't look for a file to match a + wildcard. The wildcard also means that it + doesn't matter which directory crtbegin.o + is in. */ + KEEP (*crtbegin.o(.ctors)) + KEEP (*crtbegin?.o(.ctors)) + /* We don't want to include the .ctor section from + the crtend.o file until after the sorted ctors. + The .ctor section from the crtend file contains the + end of ctors marker and it must be last */ + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + } + .dtors : + { + KEEP (*crtbegin.o(.dtors)) + KEEP (*crtbegin?.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + } + __DTOR_END__ = .; + .jcr : { KEEP (*(.jcr)) } + .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro* .gnu.linkonce.d.rel.ro.*) } + .got1 : { *(.got1) } + .got2 : { *(.got2) } + .dynamic : { *(.dynamic) } + .got : SPECIAL { *(.got) } + . = DATA_SEGMENT_RELRO_END (0, .); + .plt : SPECIAL { *(.plt) } + .data : + { + *(.data .data.* .gnu.linkonce.d.*) + KEEP (*(.gnu.linkonce.d.*personality*)) + SORT(CONSTRUCTORS) + } + .data1 : { *(.data1) } + .got : SPECIAL { *(.got) } + /* We want the small data sections together, so single-instruction offsets + can access them all, and initialized data all before uninitialized, so + we can shorten the on-disk segment size. */ + .sdata : + { + *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) + *(.sdata .sdata.* .gnu.linkonce.s.*) + } + _edata = .; PROVIDE (edata = .); + __bss_start = .; + .sbss : + { + *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) + *(.dynsbss) + *(.sbss .sbss.* .gnu.linkonce.sb.*) + *(.scommon) + } + .plt : SPECIAL { *(.plt) } + .bss : + { + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + /* Align here to ensure that the .bss section occupies space up to + _end. Align after .bss to ensure correct alignment even if the + .bss section disappears because there are no input sections. + FIXME: Why do we need it? When there is no .bss section, we don't + pad the .data section. */ + . = ALIGN(. != 0 ? 32 / 8 : 1); + } + . = ALIGN(32 / 8); + . = ALIGN(32 / 8); + _end = .; PROVIDE (end = .); + . = DATA_SEGMENT_END (.); + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to the beginning + of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /* DWARF 3 */ + .debug_pubtypes 0 : { *(.debug_pubtypes) } + .debug_ranges 0 : { *(.debug_ranges) } + .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) } + /DISCARD/ : { *(.fixup) } + /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) } +} diff --git a/l4/pkg/ldscripts/ARCH-sparc/main_stat.ld b/l4/pkg/ldscripts/ARCH-sparc/main_stat.ld new file mode 100644 index 00000000..28b6e8d8 --- /dev/null +++ b/l4/pkg/ldscripts/ARCH-sparc/main_stat.ld @@ -0,0 +1,273 @@ +/* Default linker script, for normal executables */ +OUTPUT_FORMAT("elf32-sparc", "elf32-sparc", + "elf32-sparc") +OUTPUT_ARCH(sparc) +ENTRY(_start) + +PHDRS +{ + phdr PT_PHDR PHDRS; + ro PT_LOAD FILEHDR PHDRS; + rw PT_LOAD; + L4_DEFINE_L4PHDRS +} + +SECTIONS +{ + PROVIDE (__executable_start = 0x010000); + . = __executable_start + SIZEOF_HEADERS; + + /* Read-only sections, merged into text segment: */ + /* PROVIDE (__executable_start = 0x10000000); . = 0x10000000 + SIZEOF_HEADERS; + */ + /DISCARD/ : + { *(.interp) + *(.note.gnu.build-id) + *(.hash) + *(.gnu.hash) + *(.dynsym) + *(.dynstr) + *(.gnu.version) + *(.gnu.version_d) + *(.gnu.version_r) + *(.rel.init) + *(.rela.init) + *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) + *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) + *(.rel.fini) + *(.rela.fini) + *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) + *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) + *(.rel.data.rel.ro* .rel.gnu.linkonce.d.rel.ro.*) + *(.rela.data.rel.ro* .rela.gnu.linkonce.d.rel.ro.*) + *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) + *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) + *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) + *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) + *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) + *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) + *(.rel.ctors) + *(.rela.ctors) + *(.rel.dtors) + *(.rela.dtors) + *(.rel.got) + *(.rela.got) + *(.rela.got1) + *(.rela.got2) + *(.rel.sdata .rel.sdata.* .rel.gnu.linkonce.s.*) + *(.rela.sdata .rela.sdata.* .rela.gnu.linkonce.s.*) + *(.rel.sbss .rel.sbss.* .rel.gnu.linkonce.sb.*) + *(.rela.sbss .rela.sbss.* .rela.gnu.linkonce.sb.*) + *(.rel.sdata2 .rel.sdata2.* .rel.gnu.linkonce.s2.*) + *(.rela.sdata2 .rela.sdata2.* .rela.gnu.linkonce.s2.*) + *(.rel.sbss2 .rel.sbss2.* .rel.gnu.linkonce.sb2.*) + *(.rela.sbss2 .rela.sbss2.* .rela.gnu.linkonce.sb2.*) + *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) + *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) + *(.rel.plt) + *(.rela.plt) } + .text : + { + _stext = .; + _program_img_start = _stext; + *(.text .stub .text.* .gnu.linkonce.t.*) + . = ALIGN (16); + KEEP(*(.text.*personality*)) + /* .gnu.warning sections are handled specially by elf32.em. */ + *(.gnu.warning) + *(.glink) + } :ro = 0 + .init : + { + KEEP (*(.init)) + } :ro = 0 + .fini : + { + KEEP (*(.fini)) + } :ro = 0 + PROVIDE (__etext = .); + PROVIDE (_etext = .); + PROVIDE (etext = .); + .rol4re_elf_aux : { + KEEP (*(.rol4re_elf_aux)) + } : ro : l4re_aux + _rodata_start = . ; + .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } : ro + .rodata1 : { *(.rodata1) } + _erodata = ALIGN( 0x10 ) ; + .sdata2 : + { + PROVIDE (_SDA2_BASE_ = 32768); + *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) + } + .sbss2 : { *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) } + .eh_frame_hdr : { *(.eh_frame_hdr) } :ro + .eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) } + .gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) } + . = ALIGN(CONSTANT(MAXPAGESIZE)); + /* Adjust the address for the data segment. We want to adjust up to + the same address within the page on the next page up. */ + . = ALIGN (CONSTANT (MAXPAGESIZE)) - ((CONSTANT (MAXPAGESIZE) - .) & (CONSTANT (MAXPAGESIZE) - 1)); . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE)); + + PROVIDE(_sdata = .); + /* Exception handling */ + .eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) } :rw + .gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) } :rw + /* Thread Local Storage sections */ + .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) } :rw + .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + } + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(.fini_array)) + KEEP (*(SORT(.fini_array.*))) + PROVIDE_HIDDEN (__fini_array_end = .); + } + /* . = ALIGN(0x1000); */ + + .ctors : + { + /* gcc uses crtbegin.o to find the start of + the constructors, so we make sure it is + first. Because this is a wildcard, it + doesn't matter if the user does not + actually link against crtbegin.o; the + linker won't look for a file to match a + wildcard. The wildcard also means that it + doesn't matter which directory crtbegin.o + is in. */ + KEEP (*crtbegin.o(.ctors)) + KEEP (*crtbegin?.o(.ctors)) + /* We don't want to include the .ctor section from + the crtend.o file until after the sorted ctors. + The .ctor section from the crtend file contains the + end of ctors marker and it must be last */ + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + } + .dtors : + { + KEEP (*crtbegin.o(.dtors)) + KEEP (*crtbegin?.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + __DTOR_END__ = .; + /* linux style initcalls constructors */ + __leonbare_initcall_start = .; + *(.initcall1.init) + *(.initcall2.init) + *(.initcall3.init) + *(.initcall4.init) + *(.initcall5.init) + *(.initcall6.init) + *(.initcall7.init) + __leonbare_initcall_end = .; + + } + + .jcr : { KEEP (*(.jcr)) } + .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro* .gnu.linkonce.d.rel.ro.*) } + .got1 : { *(.got1) } + .got2 : { *(.got2) } + .dynamic : { *(.dynamic) } + .got : SPECIAL { *(.got) } + . = DATA_SEGMENT_RELRO_END (0, .); + .plt : SPECIAL { *(.plt) } + .data : + { + *(.data .data.* .gnu.linkonce.d.*) + KEEP (*(.gnu.linkonce.d.*personality*)) + SORT(CONSTRUCTORS) + } + .data1 : { *(.data1) } + .got : SPECIAL { *(.got) } + /* We want the small data sections together, so single-instruction offsets + can access them all, and initialized data all before uninitialized, so + we can shorten the on-disk segment size. */ + .sdata : + { + PROVIDE (_SDA_BASE_ = 32768); + *(.sdata .sdata.* .gnu.linkonce.s.*) + } + _edata = .; PROVIDE (edata = .); + __bss_start = .; + .sbss : + { + PROVIDE (__sbss_start = .); PROVIDE (___sbss_start = .); + *(.dynsbss) + *(.sbss .sbss.* .gnu.linkonce.sb.*) + *(.scommon) + PROVIDE (__sbss_end = .); PROVIDE (___sbss_end = .); + } + .plt : SPECIAL { *(.plt) } + .bss : + { + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + /* Align here to ensure that the .bss section occupies space up to + _end. Align after .bss to ensure correct alignment even if the + .bss section disappears because there are no input sections. + FIXME: Why do we need it? When there is no .bss section, we don't + pad the .data section. */ + . = ALIGN(. != 0 ? 32 / 8 : 1); + } + . = ALIGN(32 / 8); + . = ALIGN(32 / 8); + _end = .; PROVIDE (end = .); + . = DATA_SEGMENT_END (.); + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to the beginning + of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /* DWARF 3 */ + .debug_pubtypes 0 : { *(.debug_pubtypes) } + .debug_ranges 0 : { *(.debug_ranges) } + .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) } + /DISCARD/ : { *(.fixup) } + /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) } +} diff --git a/l4/pkg/ldscripts/ARCH-x86/main_dyn.ld b/l4/pkg/ldscripts/ARCH-x86/main_dyn.ld new file mode 100644 index 00000000..9b5297d8 --- /dev/null +++ b/l4/pkg/ldscripts/ARCH-x86/main_dyn.ld @@ -0,0 +1,272 @@ +/* -*- Makefile -*- */ +ENTRY(_start) + +PHDRS +{ + phdr PT_PHDR PHDRS; + interp PT_INTERP; + ro PT_LOAD FILEHDR PHDRS; + rw PT_LOAD; + dyn PT_DYNAMIC; + tls PT_TLS; + ehf PT_GNU_EH_FRAME; + L4_DEFINE_L4PHDRS +} + + +SECTIONS +{ + L4_DEFINE_X86_KERNEL_ENTRY_SYMS + + /* No program code/data before _stext/_prog_img_start! */ + + /* Read-only sections, merged into text segment. The start address of + * the text segment is : */ + PROVIDE (__executable_start = 0x08048000); . = 0x08048000 + SIZEOF_HEADERS; + .interp : { *(.interp) } :ro : interp + .note.gnu.build-id : { *(.note.gnu.build-id) } :ro + .hash : { *(.hash) } + .gnu.hash : { *(.gnu.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .gnu.version : { *(.gnu.version) } + .gnu.version_d : { *(.gnu.version_d) } + .gnu.version_r : { *(.gnu.version_r) } + .rel.init : { *(.rel.init) } + .rela.init : { *(.rela.init) } + .rel.text : { *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) } + .rela.text : { *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) } + .rel.fini : { *(.rel.fini) } + .rela.fini : { *(.rela.fini) } + .rel.rodata : { *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) } + .rela.rodata : { *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) } + .rel.data.rel.ro : { *(.rel.data.rel.ro* .rel.gnu.linkonce.d.rel.ro.*) } + .rela.data.rel.ro : { *(.rela.data.rel.ro* .rela.gnu.linkonce.d.rel.ro.*) } + .rel.data : { *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) } + .rela.data : { *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) } + .rel.tdata : { *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) } + .rela.tdata : { *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) } + .rel.tbss : { *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) } + .rela.tbss : { *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) } + .rel.ctors : { *(.rel.ctors) } + .rela.ctors : { *(.rela.ctors) } + .rel.dtors : { *(.rel.dtors) } + .rela.dtors : { *(.rela.dtors) } + .rel.got : { *(.rel.got) } + .rela.got : { *(.rela.got) } + .rel.bss : { *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) } + .rela.bss : { *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) } + .rel.plt : { *(.rel.plt) } + .rela.plt : { *(.rela.plt) } + .init : + { + KEEP (*(.init)) + } =0x90909090 + .plt : { *(.plt) } + .text : + { + _stext = .; + _prog_img_start = _stext; + *(.text .stub .text.* .gnu.linkonce.t.*) + KEEP (*(.text.*personality*)) + /* .gnu.warning sections are handled specially by elf32.em. */ + *(.gnu.warning) + } =0x90909090 + .fini : + { + KEEP (*(.fini)) + /* LONG(0xc3) * terminate .fini */ + } = 0x9090 + + PROVIDE (_etext = .); + PROVIDE (etext = .); + .rol4re_elf_aux : { + KEEP (*(.rol4re_elf_aux)) + } : ro : l4re_aux + .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } : ro + .rodata1 : { *(.rodata1) } + .eh_frame_hdr : { *(.eh_frame_hdr) } :ehf :ro + + .eh_frame : ONLY_IF_RO + { + PROVIDE(__eh_frame_start__ = .); + KEEP (*(.eh_frame)) + KEEP (*(.eh_frame_terminator)) + } :ro + + .gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) } :ro + + . = ALIGN(CONSTANT(MAXPAGESIZE)); + /* Adjust the address for the data segment. We want to adjust up to + the same address within the page on the next page up. */ + . = ALIGN (CONSTANT (MAXPAGESIZE)) - ((CONSTANT (MAXPAGESIZE) - .) & (CONSTANT (MAXPAGESIZE) - 1)); . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE)); + PROVIDE (_sdata = .); + /* Exception handling */ + .eh_frame : ONLY_IF_RW + { + PROVIDE (__eh_frame_start__ = .); + KEEP (*(.eh_frame)) + KEEP (*(.eh_frame_terminator)) + } :rw + .gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) } :rw + /* Thread Local Storage sections */ + .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) } :rw : tls + .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } : rw + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + } + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(.fini_array)) + KEEP (*(SORT(.fini_array.*))) + PROVIDE_HIDDEN (__fini_array_end = .); + } + /* ensure that data starts at a new L4 page */ + /*. = ALIGN(0x1000);*/ + .ctors : + { +/* KEEP (*(.mark_beg_l4dde_ctors)) + KEEP (*(.l4dde_ctors)) + KEEP (*(.mark_end_l4dde_ctors)) + + KEEP (*(.mark_beg_ctors)) */ + + /* gcc uses crtbegin.o to find the start of + the constructors, so we make sure it is + first. Because this is a wildcard, it + doesn't matter if the user does not + actually link against crtbegin.o; the + linker won't look for a file to match a + wildcard. The wildcard also means that it + doesn't matter which directory crtbegin.o + is in. */ + KEEP (*crtbegin.o(.ctors)) + KEEP (*crtbegin?.o(.ctors)) + /* We don't want to include the .ctor section from + the crtend.o file until after the sorted ctors. + The .ctor section from the crtend file contains the + end of ctors marker and it must be last */ + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + /* + KEEP (*(.mark_end_ctors)) + + KEEP (*(.mark_beg_c_ctors)) + KEEP (*(SORT(.c_ctors.?))) + KEEP (*(SORT(.c_ctors.??))) + KEEP (*(SORT(.c_ctors.???))) + KEEP (*(SORT(.c_ctors.????))) + KEEP (*(SORT(.c_ctors.?????))) + KEEP (*(.c_ctors)) + KEEP (*(.mark_end_c_ctors)) + */ + } + + .dtors : + { + /* + KEEP (*(.mark_beg_dtors))*/ + KEEP (*crtbegin.o(.dtors)) + KEEP (*crtbegin?.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + /* + KEEP (*(.mark_end_dtors)) + + KEEP (*(.mark_beg_c_sys_dtors)) + KEEP (*(SORT(.c_dtors.?))) + KEEP (*(SORT(.c_dtors.??))) + KEEP (*(.mark_end_c_sys_dtors)) + + KEEP (*(.mark_beg_c_dtors)) + KEEP (*(SORT(.c_dtors.???))) + KEEP (*(SORT(.c_dtors.????))) + KEEP (*(SORT(.c_dtors.?????))) + KEEP (*(.c_dtors)) + KEEP (*(.mark_end_c_dtors))*/ + } + .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro* .gnu.linkonce.d.rel.ro.*) } + .dynamic : { *(.dynamic) } :dyn :rw + .got : { *(.got) } :rw + . = DATA_SEGMENT_RELRO_END (12, .); + .got.plt : { *(.got.plt) } + .data : + { + PROVIDE_HIDDEN(__l4sys_invoke_indirect = .); + LONG (0xeacff000) /*__l4sys_invoke_direct)*/ + *(.data .data.* .gnu.linkonce.d.*) + KEEP (*(.gnu.linkonce.d.*personality*)) + SORT(CONSTRUCTORS) + } + .data1 : { *(.data1) } + _edata = .; PROVIDE (edata = .); + __bss_start = .; + .bss : + { + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + /* Align here to ensure that the .bss section occupies space up to + _end. Align after .bss to ensure correct alignment even if the + .bss section disappears because there are no input sections. + FIXME: Why do we need it? When there is no .bss section, we don't + pad the .data section. */ + . = ALIGN(. != 0 ? 32 / 8 : 1); + } + . = ALIGN(32 / 8); + . = ALIGN(32 / 8); + _end = .; PROVIDE (end = .); + . = DATA_SEGMENT_END (.); + . = ALIGN(CONSTANT(MAXPAGESIZE)); + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } :NONE + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to the beginning + of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /* DWARF 3 */ + .debug_pubtypes 0 : { *(.debug_pubtypes) } + .debug_ranges 0 : { *(.debug_ranges) } + .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) } + /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) } +} diff --git a/l4/pkg/ldscripts/ARCH-x86/main_rel.ld b/l4/pkg/ldscripts/ARCH-x86/main_rel.ld new file mode 100644 index 00000000..b41d2569 --- /dev/null +++ b/l4/pkg/ldscripts/ARCH-x86/main_rel.ld @@ -0,0 +1,197 @@ +/* Script for --shared -z combreloc: shared library, combine & sort relocs */ +OUTPUT_FORMAT("elf32-i386", "elf32-i386", + "elf32-i386") +OUTPUT_ARCH(i386) +ENTRY(_start) +SECTIONS +{ + /* Read-only sections, merged into text segment: */ + . = 0 + SIZEOF_HEADERS; + .note.gnu.build-id : { *(.note.gnu.build-id) } + .hash : { *(.hash) } + .gnu.hash : { *(.gnu.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .gnu.version : { *(.gnu.version) } + .gnu.version_d : { *(.gnu.version_d) } + .gnu.version_r : { *(.gnu.version_r) } + .rel.dyn : + { + *(.rel.init) + *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) + *(.rel.fini) + *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) + *(.rel.data.rel.ro* .rel.gnu.linkonce.d.rel.ro.*) + *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) + *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) + *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) + *(.rel.ctors) + *(.rel.dtors) + *(.rel.got) + *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) + *(.rel.ifunc) + } + .rel.plt : + { + *(.rel.plt) + *(.rel.iplt) + } + .init : + { + KEEP (*(.init)) + } =0x90909090 + .plt : { *(.plt) *(.iplt) } + .text : + { + *(.text.unlikely .text.*_unlikely) + *(.text.exit .text.exit.*) + *(.text.startup .text.startup.*) + *(.text.hot .text.hot.*) + *(.text .stub .text.* .gnu.linkonce.t.*) + KEEP (*(.text.*personality*)) + /* .gnu.warning sections are handled specially by elf32.em. */ + *(.gnu.warning) + } =0x90909090 + .fini : + { + KEEP (*(.fini)) + } =0x90909090 + PROVIDE (__etext = .); + PROVIDE (_etext = .); + PROVIDE (etext = .); + .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } + .rodata1 : { *(.rodata1) } + .eh_frame_hdr : { *(.eh_frame_hdr) } + .eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) } + .gcc_except_table : ONLY_IF_RO { *(.gcc_except_table + .gcc_except_table.*) } + /* These sections are generated by the Sun/Oracle C++ compiler. */ + .exception_ranges : ONLY_IF_RO { *(.exception_ranges + .exception_ranges*) } + /* Adjust the address for the data segment. We want to adjust up to + the same address within the page on the next page up. */ + . = ALIGN (CONSTANT (MAXPAGESIZE)) - ((CONSTANT (MAXPAGESIZE) - .) & (CONSTANT (MAXPAGESIZE) - 1)); . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE)); + /* Exception handling */ + PROVIDE (_sdata = .); + /* Exception handling */ + .eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) } + .gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) } + .exception_ranges : ONLY_IF_RW { *(.exception_ranges .exception_ranges*) } + /* Thread Local Storage sections */ + .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) } + .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } + .preinit_array : + { + KEEP (*(.preinit_array)) + } + .init_array : + { + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + } + .fini_array : + { + KEEP (*(.fini_array)) + KEEP (*(SORT(.fini_array.*))) + } + .ctors : + { + /* gcc uses crtbegin.o to find the start of + the constructors, so we make sure it is + first. Because this is a wildcard, it + doesn't matter if the user does not + actually link against crtbegin.o; the + linker won't look for a file to match a + wildcard. The wildcard also means that it + doesn't matter which directory crtbegin.o + is in. */ + KEEP (*crtbegin.o(.ctors)) + KEEP (*crtbegin?.o(.ctors)) + /* We don't want to include the .ctor section from + the crtend.o file until after the sorted ctors. + The .ctor section from the crtend file contains the + end of ctors marker and it must be last */ + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + } + .dtors : + { + KEEP (*crtbegin.o(.dtors)) + KEEP (*crtbegin?.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + } + .jcr : { KEEP (*(.jcr)) } + .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro* .gnu.linkonce.d.rel.ro.*) } + .dynamic : { *(.dynamic) } + .got : { *(.got) *(.igot) } + . = DATA_SEGMENT_RELRO_END (12, .); + .got.plt : { *(.got.plt) *(.igot.plt) } + .data : + { + PROVIDE_HIDDEN(__l4sys_invoke_indirect = .); + LONG (0xeacff000) /*__l4sys_invoke_direct)*/ + *(.data .data.* .gnu.linkonce.d.*) + KEEP (*(.gnu.linkonce.d.*personality*)) + SORT(CONSTRUCTORS) + } + .data1 : { *(.data1) } + _edata = .; PROVIDE (edata = .); + __bss_start = .; + .bss : + { + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + /* Align here to ensure that the .bss section occupies space up to + _end. Align after .bss to ensure correct alignment even if the + .bss section disappears because there are no input sections. + FIXME: Why do we need it? When there is no .bss section, we don't + pad the .data section. */ + . = ALIGN(. != 0 ? 32 / 8 : 1); + } + . = ALIGN(32 / 8); + . = ALIGN(32 / 8); + _end = .; PROVIDE (end = .); + . = DATA_SEGMENT_END (.); + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to the beginning + of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /* DWARF 3 */ + .debug_pubtypes 0 : { *(.debug_pubtypes) } + .debug_ranges 0 : { *(.debug_ranges) } + .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) } + /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) } +} diff --git a/l4/pkg/ldscripts/ARCH-x86/main_stat.ld b/l4/pkg/ldscripts/ARCH-x86/main_stat.ld new file mode 100644 index 00000000..3dc3f9d6 --- /dev/null +++ b/l4/pkg/ldscripts/ARCH-x86/main_stat.ld @@ -0,0 +1,263 @@ +/* -*- Makefile -*- */ +ENTRY(_start) + +PHDRS +{ + phdr PT_PHDR PHDRS; + ro PT_LOAD FILEHDR PHDRS; + rw PT_LOAD; + tls PT_TLS; + L4_DEFINE_L4PHDRS +} + + +SECTIONS +{ + L4_DEFINE_X86_KERNEL_ENTRY_SYMS + PROVIDE (__executable_start = 0x0100000); + . = __executable_start + SIZEOF_HEADERS; + + /* No program code/data before _stext/_prog_img_start! */ + + /* Read-only sections, merged into text segment. The start address of + * the text segment is : */ + /DISCARD/ : + { *(.note.gnu.build-id) + *(.hash) + *(.gnu.hash) + *(.dynsym) + *(.dynstr) + *(.gnu.version) + *(.gnu.version_d) + *(.gnu.version_r) + *(.rel.init) + *(.rela.init) + *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) + *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) + *(.rel.fini) + *(.rela.fini) + *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) + *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) + *(.rel.data.rel.ro* .rel.gnu.linkonce.d.rel.ro.*) + *(.rela.data.rel.ro* .rela.gnu.linkonce.d.rel.ro.*) + *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) + *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) + *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) + *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) + *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) + *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) + *(.rel.ctors) + *(.rela.ctors) + *(.rel.dtors) + *(.rela.dtors) + *(.rel.got) + *(.rela.got) + *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) + *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) + *(.rel.plt) + *(.rela.plt) + *(.stapsdt.*) + *(.note.stapsdt) + *(.plt) } + .text : + { + _stext = .; + _prog_img_start = _stext; + *(.text .stub .text.* .gnu.linkonce.t.*) + KEEP (*(.text.*personality*)) + /* .gnu.warning sections are handled specially by elf32.em. */ + *(.gnu.warning) + } :ro =0x90909090 + .init : + { + KEEP (*(.init)) + } :ro =0x90909090 + .fini : + { + KEEP (*(.fini)) + /* LONG(0xc3) * terminate .fini */ + } :ro = 0x9090 + + PROVIDE (_etext = .); + PROVIDE (etext = .); + .rol4re_elf_aux : { + KEEP (*(.rol4re_elf_aux)) + } : l4re_aux : ro + .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } : ro + .rodata1 : { *(.rodata1) } + .eh_frame_hdr : { *(.eh_frame_hdr) } :ro + + .eh_frame : ONLY_IF_RO + { + PROVIDE(__eh_frame_start__ = .); + KEEP (*(.eh_frame)) + KEEP (*(.eh_frame_terminator)) + } :ro + + .gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) } + + + . = ALIGN(CONSTANT(MAXPAGESIZE)); + /* Adjust the address for the data segment. We want to adjust up to + the same address within the page on the next page up. */ + . = ALIGN (CONSTANT (MAXPAGESIZE)) - ((CONSTANT (MAXPAGESIZE) - .) & (CONSTANT (MAXPAGESIZE) - 1)); . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE)); + PROVIDE (_sdata = .); + /* Exception handling */ + .eh_frame : ONLY_IF_RW + { + PROVIDE (__eh_frame_start__ = .); + KEEP (*(.eh_frame)) + KEEP (*(.eh_frame_terminator)) + } :rw + .gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) } :rw + /* Thread Local Storage sections */ + .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) } : rw : tls + .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } : rw + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + } + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(.fini_array)) + KEEP (*(SORT(.fini_array.*))) + PROVIDE_HIDDEN (__fini_array_end = .); + } + /* ensure that data starts at a new L4 page */ + /*. = ALIGN(0x1000);*/ + .ctors : + { + + /* gcc uses crtbegin.o to find the start of + the constructors, so we make sure it is + first. Because this is a wildcard, it + doesn't matter if the user does not + actually link against crtbegin.o; the + linker won't look for a file to match a + wildcard. The wildcard also means that it + doesn't matter which directory crtbegin.o + is in. */ + KEEP (*crtbegin.o(.ctors)) + KEEP (*crtbegin?.o(.ctors)) + /* We don't want to include the .ctor section from + the crtend.o file until after the sorted ctors. + The .ctor section from the crtend file contains the + end of ctors marker and it must be last */ + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + /* + KEEP (*(.mark_end_ctors)) + + KEEP (*(.mark_beg_c_ctors)) + KEEP (*(SORT(.c_ctors.?))) + KEEP (*(SORT(.c_ctors.??))) + KEEP (*(SORT(.c_ctors.???))) + KEEP (*(SORT(.c_ctors.????))) + KEEP (*(SORT(.c_ctors.?????))) + KEEP (*(.c_ctors)) + KEEP (*(.mark_end_c_ctors)) + */ + } :rw + + .dtors : + { + /* + KEEP (*(.mark_beg_dtors))*/ + KEEP (*crtbegin.o(.dtors)) + KEEP (*crtbegin?.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + /* + KEEP (*(.mark_end_dtors)) + + KEEP (*(.mark_beg_c_sys_dtors)) + KEEP (*(SORT(.c_dtors.?))) + KEEP (*(SORT(.c_dtors.??))) + KEEP (*(.mark_end_c_sys_dtors)) + + KEEP (*(.mark_beg_c_dtors)) + KEEP (*(SORT(.c_dtors.???))) + KEEP (*(SORT(.c_dtors.????))) + KEEP (*(SORT(.c_dtors.?????))) + KEEP (*(.c_dtors)) + KEEP (*(.mark_end_c_dtors))*/ + } + .data : + { + PROVIDE_HIDDEN(__l4sys_invoke_indirect = .); + LONG (0xeacff000) /*__l4sys_invoke_direct)*/ + *(.data .data.* .gnu.linkonce.d.*) + KEEP (*(.gnu.linkonce.d.*personality*)) + SORT(CONSTRUCTORS) + } + .data1 : { *(.data1) } + _edata = .; PROVIDE (edata = .); + __bss_start = .; + .bss : + { + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + /* Align here to ensure that the .bss section occupies space up to + _end. Align after .bss to ensure correct alignment even if the + .bss section disappears because there are no input sections. + FIXME: Why do we need it? When there is no .bss section, we don't + pad the .data section. */ + . = ALIGN(. != 0 ? 32 / 8 : 1); + } + . = ALIGN(32 / 8); + . = ALIGN(32 / 8); + _end = .; PROVIDE (end = .); + . = DATA_SEGMENT_END (.); + . = ALIGN(CONSTANT(MAXPAGESIZE)); + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } :NONE + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to the beginning + of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /* DWARF 3 */ + .debug_pubtypes 0 : { *(.debug_pubtypes) } + .debug_ranges 0 : { *(.debug_ranges) } + .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) } + /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.interp) } +} diff --git a/l4/pkg/ldscripts/Control b/l4/pkg/ldscripts/Control new file mode 100644 index 00000000..31c30f0c --- /dev/null +++ b/l4/pkg/ldscripts/Control @@ -0,0 +1,3 @@ +provides: ldscripts +source-pkg: uclibc +maintainer: warg@os.inf.tu-dresden.de diff --git a/l4/pkg/ldscripts/Makefile b/l4/pkg/ldscripts/Makefile new file mode 100644 index 00000000..e9597771 --- /dev/null +++ b/l4/pkg/ldscripts/Makefile @@ -0,0 +1,54 @@ +PKGDIR ?= . +L4DIR ?= $(PKGDIR)/../.. + +SYSTEMS = $(SYSTEMS_PLAIN) + +# Page sizes for linker +MAXPAGESIZE_amd64 := 0x200000 +COMMONPAGESIZE_amd64 := 0x1000 + +MAXPAGESIZE_x86 := 0x1000 +COMMONPAGESIZE_x86 := 0x1000 + +MAXPAGESIZE_arm := 0x1000 +COMMONPAGESIZE_arm := 0x1000 + +MAXPAGESIZE_ppc32 := 0x1000 +COMMONPAGESIZE_ppc32 := 0x1000 + +LD_SCRIPTS = main_stat.ld main_rel.ld main_dyn.ld + +# Create the wrapper binaries for programs and shared libs from uclibc +# source files (assemply). +# This is done here bacause l4sys.so already depends on the wrappers and must +# not depend on the whole libc package, +# +# to find the uclibc files +UCLIBC_ARCH_x86 := i386 +UCLIBC_ARCH_arm := arm +UCLIBC_ARCH_amd64 := x86_64 +UCLIBC_ARCH_ppc32 := powerpc +UCLIBC_ARCH_sparc := sparc +UCLIBC_BASE = $(PKGDIR)/../uclibc +UCLIBC_SYSDEPS = $(UCLIBC_BASE)/lib/contrib/uclibc/libc/sysdeps/linux/$(UCLIBC_ARCH_$(ARCH)) + +PRIVATE_INCDIR = $(PKGDIR) $(PKGDIR)/ARCH-$(ARCH) + +vpath %.S $(UCLIBC_SYSDEPS) + +INSTALL_TARGET = $(LD_SCRIPTS) crti.o crtn.o crt1.o crti.s.o crtn.s.o crt1.s.o + +include $(L4DIR)/mk/lib.mk + +$(eval $(call BID_MAKE_RULE_template, crti_s.o, crti.S,AS)) + +crti.o: crti_s.o kip_addr.o + @$(GEN_MESSAGE) + $(VERBOSE)$(LD) -r -o $@ $^ + +%.ld: $(PKGDIR)/ARCH-$(ARCH)/%.ld $(SRC_DIR)/Makefile $(SRC_DIR)/generic.h + @$(GEN_MESSAGE) + $(VERBOSE)[ "$(LDVERSION)" -lt "218" ] && \ + CPP_ARGS="-DMAXPAGESIZE=$(MAXPAGESIZE_$(ARCH)) -DCOMMONPAGESIZE=$(COMMONPAGESIZE_$(ARCH)) -DCONSTANT(x)=x"; \ + cpp -nostdinc -include $(SRC_DIR)/generic.h \ + -Wno-trigraphs -Ui386 -P $$CPP_ARGS $< $@ diff --git a/l4/pkg/ldscripts/features.h b/l4/pkg/ldscripts/features.h new file mode 100644 index 00000000..2f4e5b3a --- /dev/null +++ b/l4/pkg/ldscripts/features.h @@ -0,0 +1,4 @@ +#pragma once + +#define __UCLIBC_CTOR_DTOR__ 1 +#define __ARCH_USE_MMU__ 1 diff --git a/l4/pkg/ldscripts/generic.h b/l4/pkg/ldscripts/generic.h new file mode 100644 index 00000000..da458416 --- /dev/null +++ b/l4/pkg/ldscripts/generic.h @@ -0,0 +1,13 @@ +#pragma once + +#define L4_DEFINE_L4PHDRS \ + l4re_aux 0x60000014; + +#define L4_DEFINE_L4PHDRS___DISABLED \ + stack 0x60000012 AT (__L4_STACK_ADDR__); \ + kip 0x60000013 AT (__L4_KIP_ADDR__); \ + l4re_aux 0x60000014; + +#define L4_DEFINE_X86_KERNEL_ENTRY_SYMS \ + PROVIDE(__l4sys_invoke_direct = __L4_KIP_ADDR__ + 0x800); \ + PROVIDE(__l4sys_debugger_direct = __L4_KIP_ADDR__ + 0x900); diff --git a/l4/pkg/ldscripts/kip_addr.c b/l4/pkg/ldscripts/kip_addr.c new file mode 100644 index 00000000..debbf189 --- /dev/null +++ b/l4/pkg/ldscripts/kip_addr.c @@ -0,0 +1,14 @@ +typedef unsigned long l4_umword_t; + +typedef struct l4re_elf_aux_mword_t +{ + l4_umword_t type; + l4_umword_t length; + l4_umword_t value; +} l4re_elf_aux_mword_t; + +extern char const __L4_KIP_ADDR__[]; + +static __attribute__((used, section(".rol4re_elf_aux"))) l4re_elf_aux_mword_t const kip_addr + = { 4, sizeof(l4re_elf_aux_mword_t), (l4_umword_t)__L4_KIP_ADDR__ }; + diff --git a/l4/pkg/libgcc-pure/Control b/l4/pkg/libgcc-pure/Control new file mode 100644 index 00000000..dca4d349 --- /dev/null +++ b/l4/pkg/libgcc-pure/Control @@ -0,0 +1,3 @@ +provides: libgcc-pure +source-pkg: libgcc +maintainer: adam@os.inf.tu-dresden.de diff --git a/l4/pkg/libgcc-pure/Makefile b/l4/pkg/libgcc-pure/Makefile new file mode 100644 index 00000000..1cf0a1b8 --- /dev/null +++ b/l4/pkg/libgcc-pure/Makefile @@ -0,0 +1,4 @@ +PKGDIR = . +L4DIR ?= $(PKGDIR)/../.. + +include $(L4DIR)/mk/subdir.mk diff --git a/l4/pkg/libgcc-pure/lib/Makefile b/l4/pkg/libgcc-pure/lib/Makefile new file mode 100644 index 00000000..fae1eb16 --- /dev/null +++ b/l4/pkg/libgcc-pure/lib/Makefile @@ -0,0 +1,8 @@ +PKGDIR ?= .. +L4DIR ?= $(PKGDIR)/../.. + +SYSTEMS = $(SYSTEMS_PLAIN) +PC_LIBS = -lgcc +LIBGCC_LIB_DIR = $(PKGDIR)/../libgcc/lib + +include $(LIBGCC_LIB_DIR)/Makefile.libgcc diff --git a/l4/pkg/libgcc/Control b/l4/pkg/libgcc/Control new file mode 100644 index 00000000..cfa9885c --- /dev/null +++ b/l4/pkg/libgcc/Control @@ -0,0 +1,3 @@ +provides: libgcc +requires: l4sys +maintainer: adam@os.inf.tu-dresden.de diff --git a/l4/pkg/libgcc/Makefile b/l4/pkg/libgcc/Makefile new file mode 100644 index 00000000..1cf0a1b8 --- /dev/null +++ b/l4/pkg/libgcc/Makefile @@ -0,0 +1,4 @@ +PKGDIR = . +L4DIR ?= $(PKGDIR)/../.. + +include $(L4DIR)/mk/subdir.mk diff --git a/l4/pkg/libgcc/lib/ARCH-arm/l4-atomic-64bit.c b/l4/pkg/libgcc/lib/ARCH-arm/l4-atomic-64bit.c new file mode 100644 index 00000000..313461b2 --- /dev/null +++ b/l4/pkg/libgcc/lib/ARCH-arm/l4-atomic-64bit.c @@ -0,0 +1,170 @@ +/* 64bit Linux-specific atomic operations for ARM EABI. + Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc. + Based on linux-atomic.c + + 64 bit additions david.gilbert@linaro.org + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +. */ + +/* 64bit helper functions for atomic operations; the compiler will + call these when the code is compiled for a CPU without ldrexd/strexd. + (If the CPU had those then the compiler inlines the operation). + + These helpers require a kernel helper that's only present on newer + kernels; we check for that in an init section and bail out rather + unceremoneously. */ + +#ifndef IS_L4 +extern unsigned int __write (int fd, const void *buf, unsigned int count); +extern void abort (void); +#endif + +/* Kernel helper for compare-and-exchange. */ +typedef int (__kernel_cmpxchg64_t) (const long long* oldval, + const long long* newval, + long long *ptr); +#define __kernel_cmpxchg64 (*(__kernel_cmpxchg64_t *) 0xffff0f60) + +/* Kernel helper page version number. */ +#define __kernel_helper_version (*(unsigned int *)0xffff0ffc) + +/* Check that the kernel has a new enough version at load. */ +static void __check_for_sync8_kernelhelper (void) +{ +#ifndef IS_L4 + if (__kernel_helper_version < 5) + { + const char err[] = "A newer kernel is required to run this binary. " + "(__kernel_cmpxchg64 helper)\n"; + /* At this point we need a way to crash with some information + for the user - I'm not sure I can rely on much else being + available at this point, so do the same as generic-morestack.c + write () and abort (). */ + __write (2 /* stderr. */, err, sizeof (err)); + abort (); + } +#endif +}; + +static void (*__sync8_kernelhelper_inithook[]) (void) + __attribute__ ((used, section (".init_array"))) = { + &__check_for_sync8_kernelhelper +}; + +#define HIDDEN __attribute__ ((visibility ("hidden"))) + +#define FETCH_AND_OP_WORD64(OP, PFX_OP, INF_OP) \ + long long HIDDEN \ + __sync_fetch_and_##OP##_8 (long long *ptr, long long val) \ + { \ + int failure; \ + long long tmp,tmp2; \ + \ + do { \ + tmp = *ptr; \ + tmp2 = PFX_OP (tmp INF_OP val); \ + failure = __kernel_cmpxchg64 (&tmp, &tmp2, ptr); \ + } while (failure != 0); \ + \ + return tmp; \ + } + +FETCH_AND_OP_WORD64 (add, , +) +FETCH_AND_OP_WORD64 (sub, , -) +FETCH_AND_OP_WORD64 (or, , |) +FETCH_AND_OP_WORD64 (and, , &) +FETCH_AND_OP_WORD64 (xor, , ^) +FETCH_AND_OP_WORD64 (nand, ~, &) + +#define NAME_oldval(OP, WIDTH) __sync_fetch_and_##OP##_##WIDTH +#define NAME_newval(OP, WIDTH) __sync_##OP##_and_fetch_##WIDTH + +/* Implement both __sync__and_fetch and __sync_fetch_and_ for + subword-sized quantities. */ + +#define OP_AND_FETCH_WORD64(OP, PFX_OP, INF_OP) \ + long long HIDDEN \ + __sync_##OP##_and_fetch_8 (long long *ptr, long long val) \ + { \ + int failure; \ + long long tmp,tmp2; \ + \ + do { \ + tmp = *ptr; \ + tmp2 = PFX_OP (tmp INF_OP val); \ + failure = __kernel_cmpxchg64 (&tmp, &tmp2, ptr); \ + } while (failure != 0); \ + \ + return tmp2; \ + } + +OP_AND_FETCH_WORD64 (add, , +) +OP_AND_FETCH_WORD64 (sub, , -) +OP_AND_FETCH_WORD64 (or, , |) +OP_AND_FETCH_WORD64 (and, , &) +OP_AND_FETCH_WORD64 (xor, , ^) +OP_AND_FETCH_WORD64 (nand, ~, &) + +long long HIDDEN +__sync_val_compare_and_swap_8 (long long *ptr, long long oldval, + long long newval) +{ + int failure; + long long actual_oldval; + + while (1) + { + actual_oldval = *ptr; + + if (__builtin_expect (oldval != actual_oldval, 0)) + return actual_oldval; + + failure = __kernel_cmpxchg64 (&actual_oldval, &newval, ptr); + + if (__builtin_expect (!failure, 1)) + return oldval; + } +} + +typedef unsigned char bool; + +bool HIDDEN +__sync_bool_compare_and_swap_8 (long long *ptr, long long oldval, + long long newval) +{ + int failure = __kernel_cmpxchg64 (&oldval, &newval, ptr); + return (failure == 0); +} + +long long HIDDEN +__sync_lock_test_and_set_8 (long long *ptr, long long val) +{ + int failure; + long long oldval; + + do { + oldval = *ptr; + failure = __kernel_cmpxchg64 (&oldval, &val, ptr); + } while (failure != 0); + + return oldval; +} diff --git a/l4/pkg/libgcc/lib/ARCH-arm/l4-atomic.c b/l4/pkg/libgcc/lib/ARCH-arm/l4-atomic.c new file mode 100644 index 00000000..954724f3 --- /dev/null +++ b/l4/pkg/libgcc/lib/ARCH-arm/l4-atomic.c @@ -0,0 +1,313 @@ +/* Linux-specific atomic operations for ARM EABI. + Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc. + Contributed by CodeSourcery. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +. */ + +/* Kernel helper for compare-and-exchange. */ +#ifdef IS_L4 + +#include +#include +#include +#include + +static inline int __kernel_cmpxchg(int oldval, int newval, int *ptr) +{ + return !l4_atomic_cmpxchg((long *)ptr, oldval, newval); +} + +/* This is just a temporary way of doing it */ +static inline void __kernel_dmb(void) +{ + extern char const __L4_KIP_ADDR__[]; + l4_kernel_info_t *k = (l4_kernel_info_t *)__L4_KIP_ADDR__; + + static_assert( (offsetof(l4_kernel_info_t, platform_info.cpuid) & 0xf) == 0 + && (offsetof(l4_kernel_info_t, platform_info.mp) & 0xf) + == sizeof(k->platform_info.cpuid), + "No proper alignment"); + + if (k->platform_info.mp) + { + unsigned arch = (k->platform_info.cpuid >> 16) & 0xf; + if (arch == 0xf) + asm volatile(".inst 0xf57ff05f" : : : "memory"); + else if (arch == 0x7) + asm volatile("mcr p15, 0, r0, c7, c10, 5" : : : "memory"); + } +} +#else +typedef int (__kernel_cmpxchg_t) (int oldval, int newval, int *ptr); +#define __kernel_cmpxchg (*(__kernel_cmpxchg_t *) 0xffff0fc0) + +/* Kernel helper for memory barrier. */ +typedef void (__kernel_dmb_t) (void); +#define __kernel_dmb (*(__kernel_dmb_t *) 0xffff0fa0) +#endif + +/* Note: we implement byte, short and int versions of atomic operations using + the above kernel helpers; see linux-atomic-64bit.c for "long long" (64-bit) + operations. */ + +#define HIDDEN __attribute__ ((visibility ("hidden"))) + +#ifdef __ARMEL__ +#define INVERT_MASK_1 0 +#define INVERT_MASK_2 0 +#else +#define INVERT_MASK_1 24 +#define INVERT_MASK_2 16 +#endif + +#define MASK_1 0xffu +#define MASK_2 0xffffu + +#define FETCH_AND_OP_WORD(OP, PFX_OP, INF_OP) \ + int HIDDEN \ + __sync_fetch_and_##OP##_4 (int *ptr, int val) \ + { \ + int failure, tmp; \ + \ + do { \ + tmp = *ptr; \ + failure = __kernel_cmpxchg (tmp, PFX_OP (tmp INF_OP val), ptr); \ + } while (failure != 0); \ + \ + return tmp; \ + } + +FETCH_AND_OP_WORD (add, , +) +FETCH_AND_OP_WORD (sub, , -) +FETCH_AND_OP_WORD (or, , |) +FETCH_AND_OP_WORD (and, , &) +FETCH_AND_OP_WORD (xor, , ^) +FETCH_AND_OP_WORD (nand, ~, &) + +#define NAME_oldval(OP, WIDTH) __sync_fetch_and_##OP##_##WIDTH +#define NAME_newval(OP, WIDTH) __sync_##OP##_and_fetch_##WIDTH + +/* Implement both __sync__and_fetch and __sync_fetch_and_ for + subword-sized quantities. */ + +#define SUBWORD_SYNC_OP(OP, PFX_OP, INF_OP, TYPE, WIDTH, RETURN) \ + TYPE HIDDEN \ + NAME##_##RETURN (OP, WIDTH) (TYPE *ptr, TYPE val) \ + { \ + int *wordptr = (int *) ((unsigned int) ptr & ~3); \ + unsigned int mask, shift, oldval, newval; \ + int failure; \ + \ + shift = (((unsigned int) ptr & 3) << 3) ^ INVERT_MASK_##WIDTH; \ + mask = MASK_##WIDTH << shift; \ + \ + do { \ + oldval = *wordptr; \ + newval = ((PFX_OP (((oldval & mask) >> shift) \ + INF_OP (unsigned int) val)) << shift) & mask; \ + newval |= oldval & ~mask; \ + failure = __kernel_cmpxchg (oldval, newval, wordptr); \ + } while (failure != 0); \ + \ + return (RETURN & mask) >> shift; \ + } + +SUBWORD_SYNC_OP (add, , +, unsigned short, 2, oldval) +SUBWORD_SYNC_OP (sub, , -, unsigned short, 2, oldval) +SUBWORD_SYNC_OP (or, , |, unsigned short, 2, oldval) +SUBWORD_SYNC_OP (and, , &, unsigned short, 2, oldval) +SUBWORD_SYNC_OP (xor, , ^, unsigned short, 2, oldval) +SUBWORD_SYNC_OP (nand, ~, &, unsigned short, 2, oldval) + +SUBWORD_SYNC_OP (add, , +, unsigned char, 1, oldval) +SUBWORD_SYNC_OP (sub, , -, unsigned char, 1, oldval) +SUBWORD_SYNC_OP (or, , |, unsigned char, 1, oldval) +SUBWORD_SYNC_OP (and, , &, unsigned char, 1, oldval) +SUBWORD_SYNC_OP (xor, , ^, unsigned char, 1, oldval) +SUBWORD_SYNC_OP (nand, ~, &, unsigned char, 1, oldval) + +#define OP_AND_FETCH_WORD(OP, PFX_OP, INF_OP) \ + int HIDDEN \ + __sync_##OP##_and_fetch_4 (int *ptr, int val) \ + { \ + int tmp, failure; \ + \ + do { \ + tmp = *ptr; \ + failure = __kernel_cmpxchg (tmp, PFX_OP (tmp INF_OP val), ptr); \ + } while (failure != 0); \ + \ + return PFX_OP (tmp INF_OP val); \ + } + +OP_AND_FETCH_WORD (add, , +) +OP_AND_FETCH_WORD (sub, , -) +OP_AND_FETCH_WORD (or, , |) +OP_AND_FETCH_WORD (and, , &) +OP_AND_FETCH_WORD (xor, , ^) +OP_AND_FETCH_WORD (nand, ~, &) + +SUBWORD_SYNC_OP (add, , +, unsigned short, 2, newval) +SUBWORD_SYNC_OP (sub, , -, unsigned short, 2, newval) +SUBWORD_SYNC_OP (or, , |, unsigned short, 2, newval) +SUBWORD_SYNC_OP (and, , &, unsigned short, 2, newval) +SUBWORD_SYNC_OP (xor, , ^, unsigned short, 2, newval) +SUBWORD_SYNC_OP (nand, ~, &, unsigned short, 2, newval) + +SUBWORD_SYNC_OP (add, , +, unsigned char, 1, newval) +SUBWORD_SYNC_OP (sub, , -, unsigned char, 1, newval) +SUBWORD_SYNC_OP (or, , |, unsigned char, 1, newval) +SUBWORD_SYNC_OP (and, , &, unsigned char, 1, newval) +SUBWORD_SYNC_OP (xor, , ^, unsigned char, 1, newval) +SUBWORD_SYNC_OP (nand, ~, &, unsigned char, 1, newval) + +int HIDDEN +__sync_val_compare_and_swap_4 (int *ptr, int oldval, int newval) +{ + int actual_oldval, fail; + + while (1) + { + actual_oldval = *ptr; + + if (__builtin_expect (oldval != actual_oldval, 0)) + return actual_oldval; + + fail = __kernel_cmpxchg (actual_oldval, newval, ptr); + + if (__builtin_expect (!fail, 1)) + return oldval; + } +} + +#define SUBWORD_VAL_CAS(TYPE, WIDTH) \ + TYPE HIDDEN \ + __sync_val_compare_and_swap_##WIDTH (TYPE *ptr, TYPE oldval, \ + TYPE newval) \ + { \ + int *wordptr = (int *)((unsigned int) ptr & ~3), fail; \ + unsigned int mask, shift, actual_oldval, actual_newval; \ + \ + shift = (((unsigned int) ptr & 3) << 3) ^ INVERT_MASK_##WIDTH; \ + mask = MASK_##WIDTH << shift; \ + \ + while (1) \ + { \ + actual_oldval = *wordptr; \ + \ + if (__builtin_expect (((actual_oldval & mask) >> shift) != \ + (unsigned int) oldval, 0)) \ + return (actual_oldval & mask) >> shift; \ + \ + actual_newval = (actual_oldval & ~mask) \ + | (((unsigned int) newval << shift) & mask); \ + \ + fail = __kernel_cmpxchg (actual_oldval, actual_newval, \ + wordptr); \ + \ + if (__builtin_expect (!fail, 1)) \ + return oldval; \ + } \ + } + +SUBWORD_VAL_CAS (unsigned short, 2) +SUBWORD_VAL_CAS (unsigned char, 1) + +typedef unsigned char bool; + +bool HIDDEN +__sync_bool_compare_and_swap_4 (int *ptr, int oldval, int newval) +{ + int failure = __kernel_cmpxchg (oldval, newval, ptr); + return (failure == 0); +} + +#define SUBWORD_BOOL_CAS(TYPE, WIDTH) \ + bool HIDDEN \ + __sync_bool_compare_and_swap_##WIDTH (TYPE *ptr, TYPE oldval, \ + TYPE newval) \ + { \ + TYPE actual_oldval \ + = __sync_val_compare_and_swap_##WIDTH (ptr, oldval, newval); \ + return (oldval == actual_oldval); \ + } + +SUBWORD_BOOL_CAS (unsigned short, 2) +SUBWORD_BOOL_CAS (unsigned char, 1) + +void HIDDEN +__sync_synchronize (void) +{ + __kernel_dmb (); +} + +int HIDDEN +__sync_lock_test_and_set_4 (int *ptr, int val) +{ + int failure, oldval; + + do { + oldval = *ptr; + failure = __kernel_cmpxchg (oldval, val, ptr); + } while (failure != 0); + + return oldval; +} + +#define SUBWORD_TEST_AND_SET(TYPE, WIDTH) \ + TYPE HIDDEN \ + __sync_lock_test_and_set_##WIDTH (TYPE *ptr, TYPE val) \ + { \ + int failure; \ + unsigned int oldval, newval, shift, mask; \ + int *wordptr = (int *) ((unsigned int) ptr & ~3); \ + \ + shift = (((unsigned int) ptr & 3) << 3) ^ INVERT_MASK_##WIDTH; \ + mask = MASK_##WIDTH << shift; \ + \ + do { \ + oldval = *wordptr; \ + newval = (oldval & ~mask) \ + | (((unsigned int) val << shift) & mask); \ + failure = __kernel_cmpxchg (oldval, newval, wordptr); \ + } while (failure != 0); \ + \ + return (oldval & mask) >> shift; \ + } + +SUBWORD_TEST_AND_SET (unsigned short, 2) +SUBWORD_TEST_AND_SET (unsigned char, 1) + +#define SYNC_LOCK_RELEASE(TYPE, WIDTH) \ + void HIDDEN \ + __sync_lock_release_##WIDTH (TYPE *ptr) \ + { \ + /* All writes before this point must be seen before we release \ + the lock itself. */ \ + __kernel_dmb (); \ + *ptr = 0; \ + } + +SYNC_LOCK_RELEASE (long long, 8) +SYNC_LOCK_RELEASE (int, 4) +SYNC_LOCK_RELEASE (short, 2) +SYNC_LOCK_RELEASE (char, 1) diff --git a/l4/pkg/libgcc/lib/Makefile b/l4/pkg/libgcc/lib/Makefile new file mode 100644 index 00000000..df5ca43d --- /dev/null +++ b/l4/pkg/libgcc/lib/Makefile @@ -0,0 +1,15 @@ +PKGDIR ?= .. +L4DIR ?= $(PKGDIR)/../.. + +TARGET = libgcc-l4.a libgcc-l4.so +SRC_C_arm-l4f = ARCH-arm/l4-atomic.c ARCH-arm/l4-atomic-64bit.c +DEFINES += -DIS_L4 +LIBGCC_DO_SHARED = y +LIBGCC_LIB_DIR = $(SRC_DIR) + +PC_FILENAMES = libgcc libgcc-l4 +PC_LIBS_libgcc = -lgcc +PC_LIBS_libgcc-l4 = -lgcc-l4 +INSTALL_TARGET += libgcc-l4.a + +include $(PKGDIR)/lib/Makefile.libgcc diff --git a/l4/pkg/libgcc/lib/Makefile.libgcc b/l4/pkg/libgcc/lib/Makefile.libgcc new file mode 100644 index 00000000..a294180e --- /dev/null +++ b/l4/pkg/libgcc/lib/Makefile.libgcc @@ -0,0 +1,35 @@ +PKGDIR ?= .. +L4DIR ?= $(PKGDIR)/../.. + +INSTALL_TARGET += libgcc.a $(if $(LIBGCC_DO_SHARED),libgcc.so) + +include $(L4DIR)/mk/lib.mk + +define process_libgcc_generic + cp $(1) $(2) +endef + +define process_libgcc_arm + remove="$(filter linux-atomic.o linux-atomic-64bit.o, \ + $(shell $(AR) t $(1)))"; \ + $(CP) $(1) $(2); \ + $(AR) d $(2) $$remove; \ + $(if $(L4API),$(AR) rs $(2) $(if $(3),ARCH-arm/l4-atomic.s.o ARCH-arm/l4-atomic-64bit.s.o,ARCH-arm/l4-atomic.o ARCH-arm/l4-atomic-64bit.o);) +endef + +process_libgcc = $(if $(process_libgcc_$(ARCH)), \ + $(process_libgcc_$(ARCH)), \ + $(process_libgcc_generic)) + +ifneq ($(SYSTEM),) +all:: libgcc.a $(if $(LIBGCC_DO_SHARED),libgcc.so) +endif + +libgcc.a libgcc.so: $(GENERAL_D_LOC) $(LIBGCC_LIB_DIR)/Makefile.libgcc $(foreach f,$(TARGET),$(OBJS_$(f))) $(GCCLIB_HOST) + @$(GEN_MESSAGE) + $(VERBOSE)$(call process_libgcc,$(GCCLIB_HOST),$@,$(filter libgcc.so,$@)) + +clean cleanall:: + $(RM) libgcc.a libgcc.so + +GCCLIB_SO = diff --git a/l4/pkg/libsigma0/Control b/l4/pkg/libsigma0/Control new file mode 100644 index 00000000..c1116a1e --- /dev/null +++ b/l4/pkg/libsigma0/Control @@ -0,0 +1,3 @@ +provides: libsigma0 +requires: l4sys +Maintainer: warg@os.inf.tu-dresden.de diff --git a/l4/pkg/libsigma0/LEGAL b/l4/pkg/libsigma0/LEGAL new file mode 100644 index 00000000..0974b36a --- /dev/null +++ b/l4/pkg/libsigma0/LEGAL @@ -0,0 +1,8 @@ +# Format: (all on one line) +# Source file : Copyright Owner(s) : License +# Please use "TUD" when referring to TU Dresden. +# If sole owner is TUD, the license field defaults to GPL and can be +# left empty. +# Source-file spec can be a directory name or a wildcard like "src/*.c". +Makefile : TUD +README: TUD diff --git a/l4/pkg/libsigma0/Makefile b/l4/pkg/libsigma0/Makefile new file mode 100644 index 00000000..f8ca7cc2 --- /dev/null +++ b/l4/pkg/libsigma0/Makefile @@ -0,0 +1,4 @@ +PKGDIR = . +L4DIR ?= $(PKGDIR)/../.. + +include $(L4DIR)/mk/subdir.mk diff --git a/l4/pkg/libsigma0/doc/Makefile b/l4/pkg/libsigma0/doc/Makefile new file mode 100644 index 00000000..91949f60 --- /dev/null +++ b/l4/pkg/libsigma0/doc/Makefile @@ -0,0 +1,6 @@ +PKGDIR = .. +L4DIR ?= $(PKGDIR)/../.. + +SRC_DOX_REF = libsigma0.cfg + +include $(L4DIR)/mk/doc.mk diff --git a/l4/pkg/libsigma0/doc/files.cfg b/l4/pkg/libsigma0/doc/files.cfg new file mode 100644 index 00000000..ce66fbe6 --- /dev/null +++ b/l4/pkg/libsigma0/doc/files.cfg @@ -0,0 +1 @@ +INPUT += l4/sigma0 diff --git a/l4/pkg/libsigma0/doc/libsigma0.cfg b/l4/pkg/libsigma0/doc/libsigma0.cfg new file mode 100644 index 00000000..96f07296 --- /dev/null +++ b/l4/pkg/libsigma0/doc/libsigma0.cfg @@ -0,0 +1,843 @@ +# Doxyfile 1.2.12 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project +# +# All text after a hash (#) is considered a comment and will be ignored +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" ") + +#--------------------------------------------------------------------------- +# General configuration options +#--------------------------------------------------------------------------- + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded +# by quotes) that should identify the project. + +PROJECT_NAME = "SIGMA0 Protocol Bindings" + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = libsigma0 + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Brazilian, Chinese, Croatian, Czech, Danish, Dutch, Finnish, French, +# German, Hungarian, Italian, Japanese, Korean, Norwegian, Polish, +# Portuguese, Romanian, Russian, Slovak, Slovene, Spanish and Swedish. + +OUTPUT_LANGUAGE = English + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = NO + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = YES + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = YES + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these class will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = YES + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = YES + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = NO + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. It is allowed to use relative paths in the argument list. + +STRIP_FROM_PATH = + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = YES + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower case letters. If set to YES upper case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# users are adviced to set this option to NO. + +CASE_SENSE_NAMES = YES + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful is your file systems +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = NO + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = YES + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like the Qt-style comments (thus requiring an +# explict @brief command for a brief description. + +JAVADOC_AUTOBRIEF = NO + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# reimplements. + +INHERIT_DOCS = YES + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = NO + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 2 + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = NO + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = NO + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = YES + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or define consist of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and defines in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 30 + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources +# only. Doxygen will then generate output that is more tailored for C. +# For instance some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = YES + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = YES + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = YES + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = NO + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = YES + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. + +WARN_FORMAT = + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +@INCLUDE = $(L4DIR)/pkg/libsigma0/doc/files.cfg + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank file matching one of the following patterns are included: +# *.c *.cc *.cxx *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx *.hpp +# *.h++ *.idl + +FILE_PATTERNS = *.h + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. + +EXCLUDE = + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. + +EXCLUDE_PATTERNS = *-server.h *-client.h *include/l4/dm_*/*-sys.h + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. + +INPUT_FILTER = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse. + +FILTER_SOURCE_FILES = NO + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. + +SOURCE_BROWSER = YES + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# If the REFERENCED_BY_RELATION tag is set to YES (the default) +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = YES + +# If the REFERENCES_RELATION tag is set to YES (the default) +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = YES + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = NO + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet + +HTML_STYLESHEET = + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. + +HTML_ALIGN_MEMBERS = YES + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the Html help documentation and to the tree view. + +TOC_EXPAND = NO + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. + +DISABLE_INDEX = YES + +# This tag can be used to set the number of enum values (range [1..20]) +# that doxygen will group on one line in the generated HTML documentation. + +ENUM_VALUES_PER_LINE = 4 + +# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be +# generated containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript and frames is required (for instance Mozilla, Netscape 4.0+, +# or Internet explorer 4.0+). Note that for large projects the tree generation +# can take a very long time. In such cases it is better to disable this feature. +# Windows users are probably better off using the HTML help feature. + +GENERATE_TREEVIEW = NO + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = NO + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = YES + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, a4wide, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = a4wide + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = YES + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = NO + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimised for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assigments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_XML = NO + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = NO + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_PREDEFINED tags. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# in the INCLUDE_PATH (see below) will be search if a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. + +PREDEFINED = + +# If the MACRO_EXPANSION and EXPAND_PREDEF_ONLY tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all function-like macros that are alone +# on a line and do not end with a semicolon. Such function macros are typically +# used for boiler-plate code, and will confuse the parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::addtions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES tag can be used to specify one or more tagfiles. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in Html, RTF and LaTeX) for classes with base or +# super classes. Setting the tag to NO turns the diagrams off. Note that this +# option is superceded by the HAVE_DOT option below. This is only a fallback. It is +# recommended to install and use dot, since it yield more powerful graphs. + +CLASS_DIAGRAMS = NO + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = NO + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# the CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = YES + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = YES + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = YES + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found on the path. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = + +# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width +# (in pixels) of the graphs generated by dot. If a graph becomes larger than +# this value, doxygen will try to truncate the graph, so that it fits within +# the specified constraint. Beware that most browsers cannot cope with very +# large images. + +MAX_DOT_GRAPH_WIDTH = 1024 + +# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height +# (in pixels) of the graphs generated by dot. If a graph becomes larger than +# this value, doxygen will try to truncate the graph, so that it fits within +# the specified constraint. Beware that most browsers cannot cope with very +# large images. + +MAX_DOT_GRAPH_HEIGHT = 1024 + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermedate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES + +#--------------------------------------------------------------------------- +# Configuration::addtions related to the search engine +#--------------------------------------------------------------------------- + +# The SEARCHENGINE tag specifies whether or not a search engine should be +# used. If set to NO the values of all tags below this one will be ignored. + +SEARCHENGINE = NO + +# The CGI_NAME tag should be the name of the CGI script that +# starts the search engine (doxysearch) with the correct parameters. +# A script with this name will be generated by doxygen. + diff --git a/l4/pkg/libsigma0/include/Makefile b/l4/pkg/libsigma0/include/Makefile new file mode 100644 index 00000000..4dac30bf --- /dev/null +++ b/l4/pkg/libsigma0/include/Makefile @@ -0,0 +1,6 @@ +PKGDIR = .. +L4DIR ?= $(PKGDIR)/../.. + +PKGNAME := sigma0 + +include $(L4DIR)/mk/include.mk diff --git a/l4/pkg/libsigma0/include/sigma0.h b/l4/pkg/libsigma0/include/sigma0.h new file mode 100644 index 00000000..b8ffec18 --- /dev/null +++ b/l4/pkg/libsigma0/include/sigma0.h @@ -0,0 +1,226 @@ +/** + * \file + * \brief Sigma0 interface + * \ingroup l4sigma0_api + */ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg , + * Torsten Frenzel + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ +#ifndef __L4_SIGMA0_SIGMA0_H +#define __L4_SIGMA0_SIGMA0_H + +/** + * \defgroup l4sigma0_api Sigma0 API + * + * \brief Sigma0 API bindings. + * + * Convenience bindings for the Sigma0 protocol. + */ + +#include +#include +#include + +/** + * \defgroup l4sigma0_api_internal Internal constants + * \ingroup l4sigma0_api + * \brief Internal sigma0 definitions. + */ +/*@{*/ +#undef SIGMA0_REQ_MAGIC +#undef SIGMA0_REQ_MASK + +# define SIGMA0_REQ_MAGIC ~0xFFUL /**< Request magic */ +# define SIGMA0_REQ_MASK ~0xFFUL /**< Request mask */ + +/* Starting with 0x60 allows to detect components which still use the old + * constants (0x00 ... 0x50) */ +#define SIGMA0_REQ_ID_MASK 0xF0 /**< ID mask */ +#define SIGMA0_REQ_ID_FPAGE_RAM 0x60 /**< RAM */ +#define SIGMA0_REQ_ID_FPAGE_IOMEM 0x70 /**< I/O memory */ +#define SIGMA0_REQ_ID_FPAGE_IOMEM_CACHED 0x80 /**< Cached I/O memory */ +#define SIGMA0_REQ_ID_FPAGE_ANY 0x90 /**< Any */ +#define SIGMA0_REQ_ID_KIP 0xA0 /**< KIP */ +#define SIGMA0_REQ_ID_TBUF 0xB0 /**< TBUF */ +#define SIGMA0_REQ_ID_DEBUG_DUMP 0xC0 /**< Debug dump */ +#define SIGMA0_REQ_ID_NEW_CLIENT 0xD0 /**< New client */ + +#define SIGMA0_IS_MAGIC_REQ(d1) \ + ((d1 & SIGMA0_REQ_MASK) == SIGMA0_REQ_MAGIC) /**< Check if magic */ + +#define SIGMA0_REQ(x) \ + (SIGMA0_REQ_MAGIC + SIGMA0_REQ_ID_ ## x) /**< Construct */ + +/* Use these constants in your code! */ +#define SIGMA0_REQ_FPAGE_RAM (SIGMA0_REQ(FPAGE_RAM)) /**< RAM */ +#define SIGMA0_REQ_FPAGE_IOMEM (SIGMA0_REQ(FPAGE_IOMEM)) /**< I/O memory */ +#define SIGMA0_REQ_FPAGE_IOMEM_CACHED (SIGMA0_REQ(FPAGE_IOMEM_CACHED)) /**< Cache I/O memory*/ +#define SIGMA0_REQ_FPAGE_ANY (SIGMA0_REQ(FPAGE_ANY)) /**< Any */ +#define SIGMA0_REQ_KIP (SIGMA0_REQ(KIP)) /**< KIP */ +#define SIGMA0_REQ_TBUF (SIGMA0_REQ(TBUF)) /**< TBUF */ +#define SIGMA0_REQ_DEBUG_DUMP (SIGMA0_REQ(DEBUG_DUMP)) /**< Debug dump */ +#define SIGMA0_REQ_NEW_CLIENT (SIGMA0_REQ(NEW_CLIENT)) /**< New client */ +/*@}*/ + +/** + * \addtogroup l4sigma0_api + */ +/*@{*/ + +/** + * \brief Return flags of libsigma0 functions. + */ +enum l4sigma0_return_flags_t { + L4SIGMA0_OK, /**< Ok */ + L4SIGMA0_NOTALIGNED, /**< Phys, virt or size not aligned */ + L4SIGMA0_IPCERROR, /**< IPC error */ + L4SIGMA0_NOFPAGE, /**< No fpage received */ + L4SIGMA0_4, + L4SIGMA0_5, + L4SIGMA0_SMALLERFPAGE, /**< Superpage requested but smaller flexpage received */ +}; + +EXTERN_C_BEGIN + +/** + * \brief Map the kernel info page from pager to addr. + * + * \param sigma0 Capability selector for the sigma0 gate. + * \param addr Start of the receive window to receive KIP in. + * \param log2_size Size of the receive window to receive KIP in. + * \return Address KIP was mapped to, 0 indicates an error. + */ +L4_CV l4_kernel_info_t * +l4sigma0_map_kip(l4_cap_idx_t sigma0, void *addr, unsigned log2_size); + +/** + * \brief Request a memory mapping from sigma0. + * \param sigma0 ID of service talking the sigma0 protocol. + * \param phys the physical address of the requested page (must be at least + * aligned to the minimum page size). + * \param virt the virtual address where the paged should be mapped in the + * local address space (must be at least aligned to the minimum + * page size). + * \param size the size of the requested page, this must be a multiple of + * the minimum page size. + * + * \return 0 on success, !0 else (see l4sigma0_map_errstr()). + */ +L4_CV int l4sigma0_map_mem(l4_cap_idx_t sigma0, + l4_addr_t phys, l4_addr_t virt, l4_addr_t size); + +/** + * \brief Request IO memory from sigma0. + * + * This function is similar to l4sigma0_map_mem(), the difference is that + * it requests IO memory. IO memory is everything that is not known + * to be normal RAM. Also ACPI tables or the BIOS memory is treated as IO + * memory. + * + * \param sigma0 usually the thread id of sigma0. + * \param phys the physical address to be requested (page aligned). + * \param virt the virtual address where the memory should be mapped to + * (page aligned). + * \param size the size of the IO memory area to be mapped (multiple of + * page size) + * \param cached requests cacheable IO memory if 1, and uncached if 0. + * + * \return 0 on success, !0 else (see l4sigma0_map_errstr()). + */ +L4_CV int l4sigma0_map_iomem(l4_cap_idx_t sigma0, l4_addr_t phys, + l4_addr_t virt, l4_addr_t size, int cached); +/** + * \brief Request an arbitrary free page of RAM. + * + * This function requests arbitrary free memory from sigma0. It should be used + * whenever spare memory is needed, instead of requesting specific physical + * memory with l4sigma0_map_mem(). + * + * \param sigma0 usually the thread id of sigma0. + * \param map_area the base address of the local virtual memory area where the + * page should be mapped. + * \param log2_map_size the size of the requested page log 2 (the size in + * bytes is 2^log2_map_size). This must be at least the + * minimal page size. By specifing larger sizes the + * largest possible hardware page size will be used. + * \retval base physical address of the page received (i.e., the send base + * of the received mapping if any). + * \param sz Size to map by the server, in 2^sz bytes. + * + * \return 0 on success, !0 else (see l4sigma0_map_errstr()). + */ +L4_CV int l4sigma0_map_anypage(l4_cap_idx_t sigma0, l4_addr_t map_area, + unsigned log2_map_size, l4_addr_t *base, + unsigned sz); + +/** + * \brief Request Fiasco trace buffer. + * + * This is a Fiasco specific feature. Where you can request the kernel + * internal trace buffer for user-level evaluation. This is for special + * debugging tools, such as Ferret. + * + * \param sigma0 as usual the sigma0 thread id. + * \param virt the virtual address where the trace buffer should be mapped, + * + * \return 0 on success, !0 else (see l4sigma0_map_errstr()). + */ +L4_CV int l4sigma0_map_tbuf(l4_cap_idx_t sigma0, l4_addr_t virt); + +/** + * \brief Request sigma0 to dump internal debug information. + * + * The debug information, such as internal memory maps, as well as + * statistics about the internal allocators is dumped to the kernel debugger. + * + * \param sigma0 the sigma0 thread id. + */ +L4_CV void l4sigma0_debug_dump(l4_cap_idx_t sigma0); + +/** + * \brief Create a new IPC gate for a new Sigma0 client. + * \param sigma0 Capability selector for sigma0 gate. + * \param gate Capability selector to use for the new gate. + */ +L4_CV int l4sigma0_new_client(l4_cap_idx_t sigma0, l4_cap_idx_t gate); + +/** + * \brief Get a user readable error messages for the return codes. + * + * \param err the error code reported by the *map* functions. + * \return a string containing the error message. + */ +L4_INLINE char const *l4sigma0_map_errstr(int err); + +/*@}*/ + + +/* Implementations */ + +L4_INLINE char const *l4sigma0_map_errstr(int err) +{ + switch (err) + { + case 0: return "No error"; + case -1: return "Phys, virt or size not aligned"; + case -2: return "IPC error"; + case -3: return "No fpage received"; +#ifndef SIGMA0_REQ_MAGIC + case -4: return "Bad physical address (old protocol only)"; +#endif + case -6: return "Superpage requested but smaller flexpage received"; + case -7: return "Cannot map I/O memory cacheable (old protocol only)"; + default: return "Unknown error"; + } +} + + +EXTERN_C_END + +#endif /* ! __L4_SIGMA0_SIGMA0_H */ diff --git a/l4/pkg/libsigma0/lib/Makefile b/l4/pkg/libsigma0/lib/Makefile new file mode 100644 index 00000000..04ac0da0 --- /dev/null +++ b/l4/pkg/libsigma0/lib/Makefile @@ -0,0 +1,4 @@ +PKGDIR ?= .. +L4DIR ?= $(PKGDIR)/../.. + +include $(L4DIR)/mk/subdir.mk diff --git a/l4/pkg/libsigma0/lib/src/Makefile b/l4/pkg/libsigma0/lib/src/Makefile new file mode 100644 index 00000000..9e0b7d4d --- /dev/null +++ b/l4/pkg/libsigma0/lib/src/Makefile @@ -0,0 +1,7 @@ +PKGDIR ?= ../.. +L4DIR ?= $(PKGDIR)/../.. + +TARGET = libsigma0.a +SRC_C = mem.c iomem.c anypage.c kip.c tbuf.c debug.c client.c + +include $(L4DIR)/mk/lib.mk diff --git a/l4/pkg/libsigma0/lib/src/anypage.c b/l4/pkg/libsigma0/lib/src/anypage.c new file mode 100644 index 00000000..7a68a4ca --- /dev/null +++ b/l4/pkg/libsigma0/lib/src/anypage.c @@ -0,0 +1,57 @@ +/** + * \file sigma0/lib/src/iomem.c + * \brief map any page using sigma0 protocol + * + * \date 02/2006 + * \author Frank Mehnert */ + +/* + * (c) 2006-2009 Author(s) + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ + +#include +#include + + +/** + * Map one page anonymous memory. + * + * \param pager pager implementing the Sigma0 protocol + * \param map_area virtual address of the map area + * \param log2_map_size size of the map area + * \param sz Size to map from the server, in log2. + * \return #0 on success + * -#L4SIGMA0_IPCERROR IPC error + * -#L4SIGMA0_NOFPAGE no fpage received + */ +L4_CV int +l4sigma0_map_anypage(l4_cap_idx_t pager, l4_addr_t map_area, + unsigned log2_map_size, l4_addr_t *base, unsigned sz) +{ + l4_msgtag_t tag = l4_msgtag(L4_PROTO_SIGMA0, 2, 0, 0); + l4_utcb_t *utcb = l4_utcb(); + l4_msg_regs_t *m = l4_utcb_mr_u(utcb); + l4_buf_regs_t *b = l4_utcb_br_u(utcb); + + m->mr[0] = SIGMA0_REQ_FPAGE_ANY; + m->mr[1] = l4_fpage(0, sz, 0).raw; + + b->bdr = 0; + b->br[0] = L4_ITEM_MAP; + b->br[1] = l4_fpage(map_area, log2_map_size, L4_FPAGE_RWX).raw; + + tag = l4_ipc_call(pager, utcb, tag, L4_IPC_NEVER); + if (l4_ipc_error(tag, utcb)) + return -L4SIGMA0_IPCERROR; + + if (l4_msgtag_items(tag) != 1) + return -L4SIGMA0_NOFPAGE; + + *base = m->mr[0] & (~0UL << L4_PAGESHIFT); + + return 0; +} diff --git a/l4/pkg/libsigma0/lib/src/client.c b/l4/pkg/libsigma0/lib/src/client.c new file mode 100644 index 00000000..651d26f3 --- /dev/null +++ b/l4/pkg/libsigma0/lib/src/client.c @@ -0,0 +1,42 @@ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ +#include +#include + +/** + * New client. + * + * \param pager pager implementing Sigma0 protocol + * \param gate slot to attach to + * \return #0 on success + * -#L4SIGMA0_IPCERROR IPC error + * -#L4SIGMA0_NOFPAGE no fpage received + */ +L4_CV int +l4sigma0_new_client(l4_cap_idx_t pager, l4_cap_idx_t gate) +{ + l4_msgtag_t tag = l4_msgtag(L4_PROTO_SIGMA0, 1, 0, 0); + l4_utcb_t *utcb = l4_utcb(); + l4_msg_regs_t *m = l4_utcb_mr_u(utcb); + l4_buf_regs_t *b = l4_utcb_br_u(utcb); + + m->mr[0] = SIGMA0_REQ_NEW_CLIENT; + b->bdr = 0; + b->br[0] = L4_ITEM_MAP; + b->br[1] = l4_obj_fpage(gate, 0, 0).raw; + + tag = l4_ipc_call(pager, utcb, tag, L4_IPC_NEVER); + if (l4_msgtag_has_error(tag)) + return -L4SIGMA0_IPCERROR; + + if (l4_msgtag_items(tag) != 1) + return -L4SIGMA0_NOFPAGE; + + return 0; +} diff --git a/l4/pkg/libsigma0/lib/src/debug.c b/l4/pkg/libsigma0/lib/src/debug.c new file mode 100644 index 00000000..ccb66be6 --- /dev/null +++ b/l4/pkg/libsigma0/lib/src/debug.c @@ -0,0 +1,20 @@ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ + +#include +#include + +L4_CV void +l4sigma0_debug_dump(l4_cap_idx_t pager) +{ + l4_msgtag_t tag = l4_msgtag(L4_PROTO_SIGMA0, 1, 0, 0); + l4_utcb_mr()->mr[0] = SIGMA0_REQ_DEBUG_DUMP; + + l4_ipc_call(pager, l4_utcb(), tag, L4_IPC_NEVER); +} diff --git a/l4/pkg/libsigma0/lib/src/iomem.c b/l4/pkg/libsigma0/lib/src/iomem.c new file mode 100644 index 00000000..f28e2906 --- /dev/null +++ b/l4/pkg/libsigma0/lib/src/iomem.c @@ -0,0 +1,82 @@ +/** + * \file sigma0/lib/src/iomem.c + * \brief map memory-mapped I/O memory using sigma0 protocol + * + * \date 02/2006 + * \author Frank Mehnert */ + +/* + * (c) 2006-2009 Author(s) + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ + +#include +#include + + +/** + * Map memory-mapped I/O memory. + * + * \param pager pager implementing the Sigma0 protocol + * \param phys physical address + * \param virt virtual address + * \param size size in bytes + * \param cached != 0: map page cached, uncached otherwise + * \return #0 on success + * -#L4SIGMA0_NOTALIGNED phys, virt, or size not aligned + * -#L4SIGMA0_IPCERROR IPC error + * -#L4SIGMA0_NOFPAGE no fpage received + */ +L4_CV int +l4sigma0_map_iomem(l4_cap_idx_t pager, + l4_addr_t phys, l4_addr_t virt, l4_addr_t size, int cached) +{ + l4_addr_t d = L4_SUPERPAGESIZE; + unsigned l = L4_LOG2_SUPERPAGESIZE; + l4_msgtag_t tag; + l4_utcb_t *utcb = l4_utcb(); + int error; + + if ((phys & (d-1)) || (size & (d-1)) || (virt & (d-1))) + { + l = L4_LOG2_PAGESIZE; + d = L4_PAGESIZE; + } + + if ((phys & (d-1)) || (size & (d-1)) || (virt & (d-1))) + return -L4SIGMA0_NOTALIGNED; + + for (; size>0; phys+=d, size-=d, virt+=d) + { + do + { + l4_msg_regs_t *m = l4_utcb_mr_u(utcb); + l4_buf_regs_t *b = l4_utcb_br_u(utcb); + tag = l4_msgtag(L4_PROTO_SIGMA0, 2, 0, 0); + m->mr[0] = cached ? SIGMA0_REQ_FPAGE_IOMEM_CACHED + : SIGMA0_REQ_FPAGE_IOMEM; + m->mr[1] = l4_fpage(phys, l, L4_FPAGE_RWX).raw; + + b->bdr = 0; + b->br[0] = L4_ITEM_MAP; + b->br[1] = l4_fpage(virt, l, L4_FPAGE_RWX).raw; + tag = l4_ipc_call(pager, utcb, tag, L4_IPC_NEVER); + if (l4_msgtag_has_error(tag)) + error = l4_utcb_tcr_u(utcb)->error; + else + error = 0; + } + while (error == L4_IPC_SECANCELED || error == L4_IPC_SEABORTED); + + if (error) + return -L4SIGMA0_IPCERROR; + + if (l4_msgtag_items(tag) < 1) + return -L4SIGMA0_NOFPAGE; + } + + return 0; +} diff --git a/l4/pkg/libsigma0/lib/src/kip.c b/l4/pkg/libsigma0/lib/src/kip.c new file mode 100644 index 00000000..27bd755a --- /dev/null +++ b/l4/pkg/libsigma0/lib/src/kip.c @@ -0,0 +1,48 @@ +/** + * \file sigma0/lib/src/kip.c + * \brief map kernel info page using sigma0 protocol + * + * \date 02/2006 + * \author Adam Lackorzynski + * Frank Mehnert */ + +/* + * (c) 2006-2009 Author(s) + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ + +#include +#include + +/* + * \return kip address, 0 on error + */ +L4_CV l4_kernel_info_t * +l4sigma0_map_kip(l4_cap_idx_t pager, void *adr, unsigned log2_size) +{ + l4_msgtag_t tag = l4_msgtag(L4_PROTO_SIGMA0, 1, 0, 0); + l4_utcb_t *utcb = l4_utcb(); + l4_msg_regs_t *m = l4_utcb_mr_u(utcb); + l4_buf_regs_t *b = l4_utcb_br_u(utcb); + + l4_addr_t addr = (l4_addr_t)adr & (~0ULL << log2_size); + m->mr[0] = SIGMA0_REQ_KIP; + b->bdr = 0; + b->br[0] = L4_ITEM_MAP; + b->br[1] = l4_fpage(addr, log2_size, L4_FPAGE_RX).raw; + + tag = l4_ipc_call(pager, utcb, tag, L4_IPC_NEVER); + if (l4_ipc_error(tag, utcb)) + return 0; + + if (l4_msgtag_items(tag) != 1) + return 0; + + l4_addr_t a = addr + (m->mr[0] & (~0UL << L4_PAGESHIFT) & ((1ULL << log2_size)-1)); + + return (l4_kernel_info_t*)a; +} + diff --git a/l4/pkg/libsigma0/lib/src/mem.c b/l4/pkg/libsigma0/lib/src/mem.c new file mode 100644 index 00000000..babd8999 --- /dev/null +++ b/l4/pkg/libsigma0/lib/src/mem.c @@ -0,0 +1,76 @@ +/** + * \file sigma0/lib/src/mem.c + * \brief map memory-mapped I/O memory using sigma0 protocol + * + * \date 02/2006 + * \author Frank Mehnert */ + +/* + * (c) 2006-2009 Author(s) + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ + +#include +#include + +/** + * Map RAM. + * + * \param pager pager implementing Sigma0 protocol + * \return #0 on success + * -#L4SIGMA0_NOTALIGNED phys, virt, or size not aligned + * -#L4SIGMA0_IPCERROR IPC error + * -#L4SIGMA0_NOFPAGE no fpage received + */ +L4_CV int +l4sigma0_map_mem(l4_cap_idx_t pager, + l4_addr_t phys, l4_addr_t virt, l4_addr_t size) +{ + l4_addr_t d = L4_SUPERPAGESIZE; + unsigned l = L4_LOG2_SUPERPAGESIZE; + l4_msgtag_t tag; + int error; + l4_utcb_t *utcb = l4_utcb(); + + if ((phys & (d-1)) || (size & (d-1)) || (virt & (d-1))) + { + l = L4_LOG2_PAGESIZE; + d = L4_PAGESIZE; + } + + if ((phys & (d-1)) || (size & (d-1)) || (virt & (d-1))) + return -L4SIGMA0_NOTALIGNED; + + for (; size>0; phys+=d, size-=d, virt+=d) + { + do + { + l4_msg_regs_t *m = l4_utcb_mr_u(utcb); + l4_buf_regs_t *b = l4_utcb_br_u(utcb); + tag = l4_msgtag(L4_PROTO_SIGMA0, 2, 0, 0); + m->mr[0] = SIGMA0_REQ_FPAGE_RAM; + m->mr[1] = l4_fpage(phys, l, L4_FPAGE_RWX).raw; + + b->bdr = 0; + b->br[0] = L4_ITEM_MAP; + b->br[1] = l4_fpage(virt, l, L4_FPAGE_RWX).raw; + tag = l4_ipc_call(pager, utcb, tag, L4_IPC_NEVER); + if (l4_msgtag_has_error(tag)) + error = l4_utcb_tcr_u(utcb)->error; + else + error = 0; + } + while (error == L4_IPC_SECANCELED || error == L4_IPC_SEABORTED); + + if (error) + return -L4SIGMA0_IPCERROR; + + if (l4_msgtag_items(tag) < 1) + return -L4SIGMA0_NOFPAGE; + } + + return 0; +} diff --git a/l4/pkg/libsigma0/lib/src/tbuf.c b/l4/pkg/libsigma0/lib/src/tbuf.c new file mode 100644 index 00000000..e60078a1 --- /dev/null +++ b/l4/pkg/libsigma0/lib/src/tbuf.c @@ -0,0 +1,50 @@ +/** + * \file sigma0/lib/src/tbuf.c + * \brief map tracebuffer descriptor using sigma0 protocol + * + * \date 02/2006 + * \author Frank Mehnert */ + +/* + * (c) 2006-2009 Author(s) + * economic rights: Technische Universität Dresden (Germany) + * This file is part of TUD:OS and distributed under the terms of the + * GNU Lesser General Public License 2.1. + * Please see the COPYING-LGPL-2.1 file for details. + */ + +#include +#include + +/** + * Map the Fiasco tracebuffer status descriptor using the Sigma0 protocol. + * + * \param pager pager implementing the Sigma0 protocol + * \param virt virtual address the descriptor should be mapped to + * \return #0 on success + * -#L4SIGMA0_IPCERROR IPC error + * -#L4SIGMA0_NOFPAGE no fpage received + */ +L4_CV int +l4sigma0_map_tbuf(l4_cap_idx_t pager, l4_addr_t virt) +{ + //assert(0); + // hand-made assert: + __builtin_trap(); + (void)pager; + (void)virt; +#if 0 + l4_msgdope_t result; + int error; + l4_msgtag_t tag = l4_msgtag(L4_MSGTAG_SIGMA0, 0, 0, 0); + + error = l4_ipc_call(pager, tag, L4_IPC_NEVER, &result, &tag); + + if (error) + return -L4SIGMA0_IPCERROR; + + if (fpage.fpage == 0 || !l4_ipc_fpage_received(result)) + return -L4SIGMA0_NOFPAGE; +#endif + return 0; +} diff --git a/l4/pkg/libvcpu/Control b/l4/pkg/libvcpu/Control new file mode 100644 index 00000000..f3e0a9a2 --- /dev/null +++ b/l4/pkg/libvcpu/Control @@ -0,0 +1,3 @@ +provides: libvcpu +requires: l4re-util libc +maintainer: adam@os.inf.tu-dresden.de diff --git a/l4/pkg/libvcpu/Makefile b/l4/pkg/libvcpu/Makefile new file mode 100644 index 00000000..a6ff4ea7 --- /dev/null +++ b/l4/pkg/libvcpu/Makefile @@ -0,0 +1,4 @@ +PKGDIR = . +L4DIR ?= $(PKGDIR)/../.. + +include $(L4DIR)/mk/subdir.mk diff --git a/l4/pkg/libvcpu/doc/files.cfg b/l4/pkg/libvcpu/doc/files.cfg new file mode 100644 index 00000000..449eec31 --- /dev/null +++ b/l4/pkg/libvcpu/doc/files.cfg @@ -0,0 +1 @@ +INPUT += l4/vcpu diff --git a/l4/pkg/libvcpu/include/ARCH-amd64/vcpu_arch.h b/l4/pkg/libvcpu/include/ARCH-amd64/vcpu_arch.h new file mode 100644 index 00000000..0a27b6f6 --- /dev/null +++ b/l4/pkg/libvcpu/include/ARCH-amd64/vcpu_arch.h @@ -0,0 +1,32 @@ +/* + * (c) 2010 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#pragma once + +L4_CV L4_INLINE +int +l4vcpu_is_irq_entry(l4_vcpu_state_t *vcpu) L4_NOTHROW +{ + return vcpu->r.trapno == 0xfe; +} + +L4_CV L4_INLINE +int +l4vcpu_is_page_fault_entry(l4_vcpu_state_t *vcpu) L4_NOTHROW +{ + return vcpu->r.trapno == 0xe; +} diff --git a/l4/pkg/libvcpu/include/ARCH-arm/vcpu_arch.h b/l4/pkg/libvcpu/include/ARCH-arm/vcpu_arch.h new file mode 100644 index 00000000..2c34f163 --- /dev/null +++ b/l4/pkg/libvcpu/include/ARCH-arm/vcpu_arch.h @@ -0,0 +1,32 @@ +/* + * (c) 2010 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#pragma once + +L4_CV L4_INLINE +int +l4vcpu_is_irq_entry(l4_vcpu_state_t *vcpu) L4_NOTHROW +{ + return vcpu->r.err == 0x00600000; +} + +L4_CV L4_INLINE +int +l4vcpu_is_page_fault_entry(l4_vcpu_state_t *vcpu) L4_NOTHROW +{ + return vcpu->r.err & 0x00010000; +} diff --git a/l4/pkg/libvcpu/include/ARCH-ppc32/vcpu_arch.h b/l4/pkg/libvcpu/include/ARCH-ppc32/vcpu_arch.h new file mode 100644 index 00000000..d0fed7c3 --- /dev/null +++ b/l4/pkg/libvcpu/include/ARCH-ppc32/vcpu_arch.h @@ -0,0 +1,36 @@ +/* + * (c) 2010 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#pragma once + +#warning This file needs to be implemented. + +L4_CV L4_INLINE +int +l4vcpu_is_irq_entry(l4_vcpu_state_t *vcpu) L4_NOTHROW +{ + (void)vcpu; + return 0; // TBD +} + +L4_CV L4_INLINE +int +l4vcpu_is_page_fault_entry(l4_vcpu_state_t *vcpu) L4_NOTHROW +{ + (void)vcpu; + return 0; // TBD +} diff --git a/l4/pkg/libvcpu/include/ARCH-sparc/vcpu_arch.h b/l4/pkg/libvcpu/include/ARCH-sparc/vcpu_arch.h new file mode 100644 index 00000000..d6cc10f1 --- /dev/null +++ b/l4/pkg/libvcpu/include/ARCH-sparc/vcpu_arch.h @@ -0,0 +1,32 @@ +/* + * (c) 2010 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#pragma once + +L4_CV L4_INLINE +int +l4vcpu_is_irq_entry(l4_vcpu_state_t *vcpu) L4_NOTHROW +{ + return 0; // tbd +} + +L4_CV L4_INLINE +int +l4vcpu_is_page_fault_entry(l4_vcpu_state_t *vcpu) L4_NOTHROW +{ + return 0; // tbd +} diff --git a/l4/pkg/libvcpu/include/ARCH-x86/vcpu_arch.h b/l4/pkg/libvcpu/include/ARCH-x86/vcpu_arch.h new file mode 100644 index 00000000..0a27b6f6 --- /dev/null +++ b/l4/pkg/libvcpu/include/ARCH-x86/vcpu_arch.h @@ -0,0 +1,32 @@ +/* + * (c) 2010 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#pragma once + +L4_CV L4_INLINE +int +l4vcpu_is_irq_entry(l4_vcpu_state_t *vcpu) L4_NOTHROW +{ + return vcpu->r.trapno == 0xfe; +} + +L4_CV L4_INLINE +int +l4vcpu_is_page_fault_entry(l4_vcpu_state_t *vcpu) L4_NOTHROW +{ + return vcpu->r.trapno == 0xe; +} diff --git a/l4/pkg/libvcpu/include/Makefile b/l4/pkg/libvcpu/include/Makefile new file mode 100644 index 00000000..adeffb0f --- /dev/null +++ b/l4/pkg/libvcpu/include/Makefile @@ -0,0 +1,7 @@ +PKGDIR = .. +L4DIR ?= $(PKGDIR)/../.. + +PKGNAME = vcpu +EXTRA_TARGET += vcpu + +include $(L4DIR)/mk/include.mk diff --git a/l4/pkg/libvcpu/include/vcpu b/l4/pkg/libvcpu/include/vcpu new file mode 100644 index 00000000..20fd02cb --- /dev/null +++ b/l4/pkg/libvcpu/include/vcpu @@ -0,0 +1,271 @@ +// vi:se ft=cpp: +/* + * (c) 2010 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ + +#pragma once + +#include +#include + +namespace L4vcpu { + +/** + * \brief C++ implementation of state word in the vCPU area + * \ingroup api_libvcpu + */ +class State +{ +public: + State() {} + + /** + * \brief Initialize state. + * + * \param v Initial state. + */ + explicit State(l4vcpu_state_t v) : _s(v) {} + + /** + * \brief Add flags. + * + * \param bits Bits to add to the word. + */ + void add(unsigned bits) throw() { _s |= bits; } + + /** + * \brief Clear flags. + * + * \param bits Bits to clear in the word. + */ + void clear(unsigned bits) throw() { _s &= ~bits; } + + /** + * \brief Set flags. + * + * \param v Set the word to the value of v. + */ + void set(l4vcpu_state_t v) throw() { _s = v; } + +private: + l4vcpu_state_t _s; +}; + +/** + * \brief C++ implementation of the vCPU save state area + * \ingroup api_libvcpu + */ +class Vcpu : private l4_vcpu_state_t +{ +public: + /** + * \brief IRQ status type. + */ + typedef l4vcpu_irq_state_t Irq_state; + + /** + * \brief Disable the vCPU for event delivery. + */ + void irq_disable() throw() + { l4vcpu_irq_disable(this); } + + /** + * \brief Disable the vCPU for event delivery and return previous state. + * \return IRQ state before disabling IRQs. + */ + Irq_state irq_disable_save() throw() + { return l4vcpu_irq_disable_save(this); } + + /** + * \brief Get state word + * \return Pointer to state word in the vCPU + */ + State *state() throw() + { return reinterpret_cast(&(l4_vcpu_state_t::state)); } + + /** + * \brief Get state word + * \return Pointer to state word in the vCPU + */ + State state() const throw() + { return static_cast(l4_vcpu_state_t::state); } + + /** + * \brief Get saved_state word + * \return Pointer to saved_state word in the vCPU + */ + State *saved_state() throw() + { return reinterpret_cast(&(l4_vcpu_state_t::saved_state)); } + + /** + * \brief Get saved_state word + * \return Pointer to saved_state word in the vCPU + */ + State saved_state() const throw() + { return static_cast(l4_vcpu_state_t::saved_state); } + + /** + * \brief Enable the vCPU for event delivery. + * + * \param utcb The UTCB to use. + * \param do_event_work_cb Call-back function that is called in case an + * event (such as an interrupt) is pending. + * \param setup_ipc Call-back function that is called before an + * IPC operation is called. + */ + void irq_enable(l4_utcb_t *utcb, l4vcpu_event_hndl_t do_event_work_cb, + l4vcpu_setup_ipc_t setup_ipc) throw() + { l4vcpu_irq_enable(this, utcb, do_event_work_cb, setup_ipc); } + + /** + * \brief Restore a previously saved IRQ/event state. + * + * \param s IRQ state to be restored. + * \param utcb The UTCB to use. + * \param do_event_work_cb Call-back function that is called in case an + * event (such as an interrupt) is pending. + * \param setup_ipc Call-back function that is called before an + * IPC operation is called. + */ + void irq_restore(Irq_state s, l4_utcb_t *utcb, + l4vcpu_event_hndl_t do_event_work_cb, + l4vcpu_setup_ipc_t setup_ipc) throw() + { l4vcpu_irq_restore(this, s, utcb, do_event_work_cb, setup_ipc); } + + /** + * \brief Halt/block the vCPU. + * + * \param utcb The UTCB to use. + * \param do_event_work_cb Call-back function that is called in case an + * event (such as an interrupt) is pending. + * \param setup_ipc Call-back function that is called before an + * IPC operation is called. + */ + void halt(l4_utcb_t *utcb, l4vcpu_event_hndl_t do_event_work_cb, + l4vcpu_setup_ipc_t setup_ipc) throw() + { l4vcpu_halt(this, utcb, do_event_work_cb, setup_ipc); } + + /** + * \brief Set the task of the vCPU. + * \param task Task to set, defaults to invalid task. + */ + void task(L4::Cap const task = L4::Cap::Invalid) throw() + { user_task = task.cap(); } + + /** + * \brief Return whether the entry reason was a page fault. + * return 0 if not, !=0 otherwise. + */ + int is_page_fault_entry() + { return l4vcpu_is_page_fault_entry(this); } + + /** + * \brief Return whether the entry reason was an IRQ/IPC message. + * return 0 if not, !=0 otherwise. + */ + int is_irq_entry() + { return l4vcpu_is_irq_entry(this); } + + /** + * \brief Return pointer to register state. + * \return Pointer to register state. + */ + l4_vcpu_regs_t *r() throw() + { return &(l4_vcpu_state_t::r); } + + /** + * \brief Return pointer to register state. + * \return Pointer to register state. + */ + l4_vcpu_regs_t const *r() const throw() + { return &(l4_vcpu_state_t::r); } + + /** + * \brief Return pointer to IPC state. + * \return Pointer to IPC state. + */ + l4_vcpu_ipc_regs_t *i() throw() + { return &(l4_vcpu_state_t::i); } + + /** + * \brief Return pointer to IPC state. + * \return Pointer to IPC state. + */ + l4_vcpu_ipc_regs_t const *i() const throw() + { return &(l4_vcpu_state_t::i); } + + /** + * \brief Set vCPU entry stack pointer. + * \param sp Stack pointer address to set. + * + * \note The value is only used when entering from a user-task. + */ + void entry_sp(l4_umword_t sp) + { l4_vcpu_state_t::entry_sp = sp; } + + /** + * \brief Set vCPU entry instruction pointer. + * \param ip Instruction pointer address to set. + */ + void entry_ip(l4_umword_t ip) + { l4_vcpu_state_t::entry_ip = ip; } + + /** + * \brief Allocate state area for an extented vCPU. + * + * \retval vcpu Allocated vcpu-state area. + * \retval ext_state Allocated extended vcpu-state area. + * \param task Task to use for allocation, defaults to own task. + * \param rm Region manager to use for allocation defaults to standard region manager. + * + * \return 0 for success, error code otherwise + */ + L4_CV static int + ext_alloc(Vcpu **vcpu, + l4_addr_t *ext_state, + L4::Cap task = L4Re::Env::env()->task(), + L4::Cap rm = L4Re::Env::env()->rm()) throw(); + + /** + * \brief Cast a void ponter to a class pointer. + * + * \param x Pointer. + * + * \return Pointer to Vcpu class. + */ + static inline Vcpu *cast(void *x) throw() + { return reinterpret_cast(x); } + + /** + * \brief Cast an address to a class pointer. + * + * \param x Pointer. + * + * \return Pointer to Vcpu class. + */ + static inline Vcpu *cast(l4_addr_t x) throw() + { return reinterpret_cast(x); } + + /** + * \brief Print the state of the vCPU. + */ + void print_state(const char *prefix = "") throw() + { l4vcpu_print_state(this, prefix); } +}; + + +} diff --git a/l4/pkg/libvcpu/include/vcpu.h b/l4/pkg/libvcpu/include/vcpu.h new file mode 100644 index 00000000..74291dea --- /dev/null +++ b/l4/pkg/libvcpu/include/vcpu.h @@ -0,0 +1,301 @@ +/* + * (c) 2010 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#pragma once + +#include +#include + +__BEGIN_DECLS + +/** + * \defgroup api_libvcpu vCPU Support Library + * \brief vCPU handling functionality. + * + * This library provides convenience functionality on top of the l4sys vCPU + * interface to ease programming. It wraps commonly used code and abstracts + * architecture depends parts as far as reasonable. + */ + +/** + * \defgroup api_libvcpu_ext Extended vCPU support + * \ingroup api_libvcpu + * \brief extended vCPU handling functionality. + */ + +/** + * \brief IRQ/Event enable and disable flags. + * \ingroup api_libvcpu + */ +typedef enum l4vcpu_irq_state_t +{ + L4VCPU_IRQ_STATE_DISABLED = 0, ///< IRQ/Event delivery disabled + L4VCPU_IRQ_STATE_ENABLED = L4_VCPU_F_IRQ, ///< IRQ/Event delivery enabled +} l4vcpu_irq_state_t; + +typedef l4_umword_t l4vcpu_state_t; +typedef void (*l4vcpu_event_hndl_t)(l4_vcpu_state_t *vcpu); +typedef void (*l4vcpu_setup_ipc_t)(l4_utcb_t *utcb); + +/** + * \brief Return the state flags of a vCPU. + * \ingroup api_libvcpu + * + * \param vcpu Pointer to vCPU area. + */ +L4_CV L4_INLINE +l4vcpu_state_t +l4vcpu_state(l4_vcpu_state_t const *vcpu) L4_NOTHROW; + +/** + * \brief Disable a vCPU for event delivery. + * \ingroup api_libvcpu + * + * \param vcpu Pointer to vCPU area. + */ +L4_CV L4_INLINE +void +l4vcpu_irq_disable(l4_vcpu_state_t *vcpu) L4_NOTHROW; + +/** + * \brief Disable a vCPU for event delivery and return previous state. + * \ingroup api_libvcpu + * + * \param vcpu Pointer to vCPU area. + * + * \return IRQ state before disabling IRQs. + */ +L4_CV L4_INLINE +l4vcpu_irq_state_t +l4vcpu_irq_disable_save(l4_vcpu_state_t *vcpu) L4_NOTHROW; + +/** + * \brief Enable a vCPU for event delivery. + * \ingroup api_libvcpu + * + * \param vcpu Pointer to vCPU area. + * \param utcb Utcb pointer of the calling vCPU. + * \param do_event_work_cb Call-back function that is called in case an + * event (such as an interrupt) is pending. + * \param setup_ipc Function call-back that is called right before + * any IPC operation. + */ +L4_CV L4_INLINE +void +l4vcpu_irq_enable(l4_vcpu_state_t *vcpu, l4_utcb_t *utcb, + l4vcpu_event_hndl_t do_event_work_cb, + l4vcpu_setup_ipc_t setup_ipc) L4_NOTHROW; + +/** + * \brief Restore a previously saved IRQ/event state. + * \ingroup api_libvcpu + * + * \param vcpu Pointer to vCPU area. + * \param s IRQ state to be restored. + * \param utcb Utcb pointer of the calling vCPU. + * \param do_event_work_cb Call-back function that is called in case an + * event (such as an interrupt) is pending after + * enabling. + * \param setup_ipc Function call-back that is called right before + * any IPC operation. + */ +L4_CV L4_INLINE +void +l4vcpu_irq_restore(l4_vcpu_state_t *vcpu, l4vcpu_irq_state_t s, + l4_utcb_t *utcb, + l4vcpu_event_hndl_t do_event_work_cb, + l4vcpu_setup_ipc_t setup_ipc) L4_NOTHROW; + +/** + * \internal + * \ingroup api_libvcpu + * + * \param vcpu Pointer to vCPU area. + * \param utcb Utcb pointer of the calling vCPU. + * \param to Timeout to do IPC operation with. + * \param do_event_work_cb Call-back function that is called in case an + * event (such as an interrupt) is pending after + * enabling. + * \param setup_ipc Function call-back that is called right before + * any IPC operation. + */ +L4_CV L4_INLINE +void +l4vcpu_wait(l4_vcpu_state_t *vcpu, l4_utcb_t *utcb, + l4_timeout_t to, + l4vcpu_event_hndl_t do_event_work_cb, + l4vcpu_setup_ipc_t setup_ipc) L4_NOTHROW; + +/** + * \brief Halt the vCPU (sleep). + * \ingroup api_libvcpu + * + * \param vcpu Pointer to vCPU area. + * \param utcb Utcb pointer of the calling vCPU. + * \param do_event_work_cb Call-back function that is called when the vCPU + * awakes and needs to handle an event/IRQ. + * \param setup_ipc Function call-back that is called right before + * any IPC operation. + */ +L4_CV L4_INLINE +void +l4vcpu_halt(l4_vcpu_state_t *vcpu, l4_utcb_t *utcb, + l4vcpu_event_hndl_t do_event_work_cb, + l4vcpu_setup_ipc_t setup_ipc) L4_NOTHROW; + + +/** + * \brief Print the state of a vCPU. + * \ingroup api_libvcpu + * + * \param vcpu Pointer to vCPU area. + * \param prefix A prefix for each line printed. + */ +L4_CV void +l4vcpu_print_state(l4_vcpu_state_t *vcpu, const char *prefix) L4_NOTHROW; + +/** + * \internal + */ +L4_CV void +l4vcpu_print_state_arch(l4_vcpu_state_t *vcpu, const char *prefix) L4_NOTHROW; + + +/** + * \brief Return whether the entry reason was an IRQ/IPC message. + * \ingroup api_libvcpu + * + * \param vcpu Pointer to vCPU area. + * + * return 0 if not, !=0 otherwise. + */ +L4_CV L4_INLINE +int +l4vcpu_is_irq_entry(l4_vcpu_state_t *vcpu) L4_NOTHROW; + +/** + * \brief Return whether the entry reason was a page fault. + * \ingroup api_libvcpu + * + * \param vcpu Pointer to vCPU area. + * + * return 0 if not, !=0 otherwise. + */ +L4_CV L4_INLINE +int +l4vcpu_is_page_fault_entry(l4_vcpu_state_t *vcpu) L4_NOTHROW; + +/** + * \brief Allocate state area for an extented vCPU. + * \ingroup api_libvcpu_ext + * + * \retval vcpu Allocated vcpu-state area. + * \retval ext_state Allocated extended vcpu-state area. + * \param task Task to use for allocation. + * \param regmgr Region manager to use for allocation. + * + * \return 0 for success, error code otherwise + */ +L4_CV int +l4vcpu_ext_alloc(l4_vcpu_state_t **vcpu, l4_addr_t *ext_state, + l4_cap_idx_t task, l4_cap_idx_t regmgr) L4_NOTHROW; + +/* ===================================================================== */ +/* Implementations */ + +#include +#include + +L4_CV L4_INLINE +l4vcpu_state_t +l4vcpu_state(l4_vcpu_state_t const *vcpu) L4_NOTHROW +{ + return vcpu->state; +} + +L4_CV L4_INLINE +void +l4vcpu_irq_disable(l4_vcpu_state_t *vcpu) L4_NOTHROW +{ + vcpu->state &= ~L4_VCPU_F_IRQ; + l4_barrier(); +} + +L4_CV L4_INLINE +l4vcpu_irq_state_t +l4vcpu_irq_disable_save(l4_vcpu_state_t *vcpu) L4_NOTHROW +{ + l4vcpu_irq_state_t s = (l4vcpu_irq_state_t)l4vcpu_state(vcpu); + l4vcpu_irq_disable(vcpu); + return s; +} + +L4_CV L4_INLINE +void +l4vcpu_wait(l4_vcpu_state_t *vcpu, l4_utcb_t *utcb, + l4_timeout_t to, + l4vcpu_event_hndl_t do_event_work_cb, + l4vcpu_setup_ipc_t setup_ipc) L4_NOTHROW +{ + l4vcpu_irq_disable(vcpu); + setup_ipc(utcb); + vcpu->i.tag = l4_ipc_wait(utcb, &vcpu->i.label, to); + if (EXPECT_TRUE(!l4_msgtag_has_error(vcpu->i.tag))) + do_event_work_cb(vcpu); +} + +L4_CV L4_INLINE +void +l4vcpu_irq_enable(l4_vcpu_state_t *vcpu, l4_utcb_t *utcb, + l4vcpu_event_hndl_t do_event_work_cb, + l4vcpu_setup_ipc_t setup_ipc) L4_NOTHROW +{ + while (1) + { + vcpu->state |= L4_VCPU_F_IRQ; + l4_barrier(); + + if (EXPECT_TRUE(!(vcpu->sticky_flags & L4_VCPU_SF_IRQ_PENDING))) + break; + + l4vcpu_wait(vcpu, utcb, L4_IPC_BOTH_TIMEOUT_0, + do_event_work_cb, setup_ipc); + } +} + +L4_CV L4_INLINE +void +l4vcpu_irq_restore(l4_vcpu_state_t *vcpu, l4vcpu_irq_state_t s, + l4_utcb_t *utcb, + l4vcpu_event_hndl_t do_event_work_cb, + l4vcpu_setup_ipc_t setup_ipc) L4_NOTHROW +{ + if (s & L4_VCPU_F_IRQ) + l4vcpu_irq_enable(vcpu, utcb, do_event_work_cb, setup_ipc); +} + +L4_CV L4_INLINE +void +l4vcpu_halt(l4_vcpu_state_t *vcpu, l4_utcb_t *utcb, + l4vcpu_event_hndl_t do_event_work_cb, + l4vcpu_setup_ipc_t setup_ipc) L4_NOTHROW +{ + l4vcpu_wait(vcpu, utcb, L4_IPC_NEVER, do_event_work_cb, setup_ipc); + l4vcpu_irq_enable(vcpu, utcb, do_event_work_cb, setup_ipc); +} + +__END_DECLS diff --git a/l4/pkg/libvcpu/lib/Makefile b/l4/pkg/libvcpu/lib/Makefile new file mode 100644 index 00000000..174e98af --- /dev/null +++ b/l4/pkg/libvcpu/lib/Makefile @@ -0,0 +1,4 @@ +PKGDIR = .. +L4DIR ?= $(PKGDIR)/../.. + +include $(L4DIR)/mk/subdir.mk diff --git a/l4/pkg/libvcpu/lib/src/ARCH-amd64/arch.cc b/l4/pkg/libvcpu/lib/src/ARCH-amd64/arch.cc new file mode 100644 index 00000000..4cc945bf --- /dev/null +++ b/l4/pkg/libvcpu/lib/src/ARCH-amd64/arch.cc @@ -0,0 +1,32 @@ +/* + * (c) 2010 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ + +#include +#include + +void l4vcpu_print_state_arch(l4_vcpu_state_t *vcpu, + const char *prefix) L4_NOTHROW +{ + printf("%svcpu=%p ip=%08lx sp=%08lx trapno=%08lx label=%lx\n", + prefix, vcpu, vcpu->r.ip, vcpu->r.sp, vcpu->r.trapno, vcpu->i.label); + printf("%sax=%08lx dx=%08lx bx=%08lx cx=%08lx\n", + prefix, vcpu->r.ax, vcpu->r.dx, vcpu->r.bx, vcpu->r.cx); + printf("%ssi=%08lx di=%08lx bp=%08lx flags=%08lx\n", + prefix, vcpu->r.si, vcpu->r.di, vcpu->r.bp, vcpu->r.flags); +} + diff --git a/l4/pkg/libvcpu/lib/src/ARCH-arm/arch.cc b/l4/pkg/libvcpu/lib/src/ARCH-arm/arch.cc new file mode 100644 index 00000000..b60609a2 --- /dev/null +++ b/l4/pkg/libvcpu/lib/src/ARCH-arm/arch.cc @@ -0,0 +1,36 @@ +/* + * (c) 2010 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ + +#include + +#include + +void l4vcpu_print_state_arch(l4_vcpu_state_t *vcpu, + const char *prefix) L4_NOTHROW +{ + printf("%svcpu=%p ip=%08lx sp=%08lx err=%08lx label=%08lx\n", + prefix, vcpu, vcpu->r.ip, vcpu->r.sp, vcpu->r.err, vcpu->i.label); + printf("%s r0=%08lx r1=%08lx r2=%08lx r3=%08lx\n", + prefix, vcpu->r.r[0], vcpu->r.r[1], vcpu->r.r[2], vcpu->r.r[3]); + printf("%s r4=%08lx r5=%08lx r6=%08lx r7=%08lx\n", + prefix, vcpu->r.r[4], vcpu->r.r[5], vcpu->r.r[6], vcpu->r.r[7]); + printf("%s r8=%08lx r9=%08lx r10=%08lx r11=%08lx\n", + prefix, vcpu->r.r[8], vcpu->r.r[9], vcpu->r.r[10], vcpu->r.r[11]); + printf("%sr12=%08lx lr=%08lx flags=%08lx\n", + prefix, vcpu->r.r[12], vcpu->r.lr, vcpu->r.flags); +} diff --git a/l4/pkg/libvcpu/lib/src/ARCH-ppc32/arch.cc b/l4/pkg/libvcpu/lib/src/ARCH-ppc32/arch.cc new file mode 100644 index 00000000..94b48045 --- /dev/null +++ b/l4/pkg/libvcpu/lib/src/ARCH-ppc32/arch.cc @@ -0,0 +1,28 @@ +/* + * (c) 2010 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ +#include + +#include + +void l4vcpu_print_state_arch(l4_vcpu_state_t *vcpu, + const char *prefix) L4_NOTHROW +{ + (void)vcpu; + printf("%sTBD\n", prefix); +} + diff --git a/l4/pkg/libvcpu/lib/src/ARCH-sparc/arch.cc b/l4/pkg/libvcpu/lib/src/ARCH-sparc/arch.cc new file mode 100644 index 00000000..b60609a2 --- /dev/null +++ b/l4/pkg/libvcpu/lib/src/ARCH-sparc/arch.cc @@ -0,0 +1,36 @@ +/* + * (c) 2010 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ + +#include + +#include + +void l4vcpu_print_state_arch(l4_vcpu_state_t *vcpu, + const char *prefix) L4_NOTHROW +{ + printf("%svcpu=%p ip=%08lx sp=%08lx err=%08lx label=%08lx\n", + prefix, vcpu, vcpu->r.ip, vcpu->r.sp, vcpu->r.err, vcpu->i.label); + printf("%s r0=%08lx r1=%08lx r2=%08lx r3=%08lx\n", + prefix, vcpu->r.r[0], vcpu->r.r[1], vcpu->r.r[2], vcpu->r.r[3]); + printf("%s r4=%08lx r5=%08lx r6=%08lx r7=%08lx\n", + prefix, vcpu->r.r[4], vcpu->r.r[5], vcpu->r.r[6], vcpu->r.r[7]); + printf("%s r8=%08lx r9=%08lx r10=%08lx r11=%08lx\n", + prefix, vcpu->r.r[8], vcpu->r.r[9], vcpu->r.r[10], vcpu->r.r[11]); + printf("%sr12=%08lx lr=%08lx flags=%08lx\n", + prefix, vcpu->r.r[12], vcpu->r.lr, vcpu->r.flags); +} diff --git a/l4/pkg/libvcpu/lib/src/ARCH-x86/arch.cc b/l4/pkg/libvcpu/lib/src/ARCH-x86/arch.cc new file mode 100644 index 00000000..cf808e9a --- /dev/null +++ b/l4/pkg/libvcpu/lib/src/ARCH-x86/arch.cc @@ -0,0 +1,34 @@ +/* + * (c) 2010 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ + +#include +#include + +void l4vcpu_print_state_arch(l4_vcpu_state_t *vcpu, + const char *prefix) L4_NOTHROW +{ + printf("%sip=%08lx sp=%08lx trapno=%08lx\n", + prefix, vcpu->r.ip, vcpu->r.sp, vcpu->r.trapno); + printf("%sax=%08lx dx=%08lx bx=%08lx cx=%08lx\n", + prefix, vcpu->r.ax, vcpu->r.dx, vcpu->r.bx, vcpu->r.cx); + printf("%ssi=%08lx di=%08lx bp=%08lx flags=%08lx\n", + prefix, vcpu->r.si, vcpu->r.di, vcpu->r.bp, vcpu->r.flags); + printf("%sds=%08lx es=%08lx gs=%08lx fs=%08lx\n", + prefix, vcpu->r.ds, vcpu->r.es, vcpu->r.gs, vcpu->r.fs); +} + diff --git a/l4/pkg/libvcpu/lib/src/Makefile b/l4/pkg/libvcpu/lib/src/Makefile new file mode 100644 index 00000000..a8b039ec --- /dev/null +++ b/l4/pkg/libvcpu/lib/src/Makefile @@ -0,0 +1,8 @@ +PKGDIR ?= ../.. +L4DIR ?= $(PKGDIR)/../.. + +PC_FILENAME = libvcpu +TARGET = libvcpu.a libvcpu.so +SRC_CC = vcpu.cc ARCH-$(ARCH)/arch.cc + +include $(L4DIR)/mk/lib.mk diff --git a/l4/pkg/libvcpu/lib/src/vcpu.cc b/l4/pkg/libvcpu/lib/src/vcpu.cc new file mode 100644 index 00000000..51bbe1be --- /dev/null +++ b/l4/pkg/libvcpu/lib/src/vcpu.cc @@ -0,0 +1,72 @@ +/* + * (c) 2010 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ + +#include +#include +#include +#include + +L4_CV void +l4vcpu_print_state(l4_vcpu_state_t *vcpu, + const char *prefix) L4_NOTHROW +{ + printf("%svcpu=%p state=%x savedstate=%x label=%lx\n", + prefix, vcpu, vcpu->state, vcpu->saved_state, vcpu->i.label); + printf("%ssticky=%x user_task=%lx\n", + prefix, vcpu->sticky_flags, vcpu->user_task << L4_CAP_SHIFT); + printf("%sentry_sp=%lx entry_ip=%lx\n", + prefix, vcpu->entry_sp, vcpu->entry_ip); + l4vcpu_print_state_arch(vcpu, prefix); +} + +static int +do_l4vcpu_ext_alloc(L4vcpu::Vcpu **vcpu, + l4_addr_t *ext_state, + L4::Cap task, + L4::Cap rm) L4_NOTHROW +{ + int r; + l4_addr_t v; + + if ((r = L4Re::Util::kumem_alloc(&v, 0, task, rm))) + return r; + + *vcpu = L4vcpu::Vcpu::cast(v); + *ext_state = v + L4_VCPU_OFFSET_EXT_STATE; + + return 0; +} + +L4_CV int +l4vcpu_ext_alloc(l4_vcpu_state_t **vcpu, l4_addr_t *ext_state, + l4_cap_idx_t task, l4_cap_idx_t regmgr) L4_NOTHROW +{ + L4::Cap t(task); + L4::Cap r(regmgr); + L4vcpu::Vcpu **v = reinterpret_cast(vcpu); + return do_l4vcpu_ext_alloc(v, ext_state, t, r); +} + +L4_CV int +L4vcpu::Vcpu::ext_alloc(Vcpu **vcpu, + l4_addr_t *ext_state, + L4::Cap task, + L4::Cap rm) throw() +{ + return do_l4vcpu_ext_alloc(vcpu, ext_state, task, rm); +} diff --git a/l4/pkg/sigma0/Control b/l4/pkg/sigma0/Control new file mode 100644 index 00000000..a5bce61c --- /dev/null +++ b/l4/pkg/sigma0/Control @@ -0,0 +1,2 @@ +requires: libc_minimal crtn l4sys l4util libsigma0 cxx_io +Maintainer: warg@os.inf.tu-dresden.de diff --git a/l4/pkg/sigma0/Makefile b/l4/pkg/sigma0/Makefile new file mode 100644 index 00000000..f8ca7cc2 --- /dev/null +++ b/l4/pkg/sigma0/Makefile @@ -0,0 +1,4 @@ +PKGDIR = . +L4DIR ?= $(PKGDIR)/../.. + +include $(L4DIR)/mk/subdir.mk diff --git a/l4/pkg/sigma0/server/Makefile b/l4/pkg/sigma0/server/Makefile new file mode 100644 index 00000000..04ac0da0 --- /dev/null +++ b/l4/pkg/sigma0/server/Makefile @@ -0,0 +1,4 @@ +PKGDIR ?= .. +L4DIR ?= $(PKGDIR)/../.. + +include $(L4DIR)/mk/subdir.mk diff --git a/l4/pkg/sigma0/server/src/ARCH-amd64/crt0.S b/l4/pkg/sigma0/server/src/ARCH-amd64/crt0.S new file mode 100644 index 00000000..7b73e109 --- /dev/null +++ b/l4/pkg/sigma0/server/src/ARCH-amd64/crt0.S @@ -0,0 +1,34 @@ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg , + * Torsten Frenzel + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ +#define __ASSEMBLY__ +#include + + .section .text.init + +ENTRY(__crt_dummy__) +ENTRY(_start) +ENTRY(start) + + test %rdi, %rdi + jne 1f + pop %rdi /* ptr to kernel info page is on init stack */ +1: + lea _stack,%rsp /* reset stack */ + push $_exit + jmp init + +ENTRY(__main) + ret + + .bss + + .space 4096 +ENTRY(_stack) diff --git a/l4/pkg/sigma0/server/src/ARCH-arm/crt0.S b/l4/pkg/sigma0/server/src/ARCH-arm/crt0.S new file mode 100644 index 00000000..551b7fe3 --- /dev/null +++ b/l4/pkg/sigma0/server/src/ARCH-arm/crt0.S @@ -0,0 +1,27 @@ +/* + * (c) 2008-2009 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ + +.section .text.init,#alloc,#execinstr +.type _start,#function +.globl _start +_start: + ldr sp, .LCstack + ldr lr, .LCexit + b init +.LCstack: .word crt0_stack_high +.LCexit: .word _exit + +.section ".bss" + + .align 3 + .global crt0_stack_low +crt0_stack_low: + .space 2048 + .global crt0_stack_high +crt0_stack_high: diff --git a/l4/pkg/sigma0/server/src/ARCH-ppc32/crt0.S b/l4/pkg/sigma0/server/src/ARCH-ppc32/crt0.S new file mode 100644 index 00000000..8019647d --- /dev/null +++ b/l4/pkg/sigma0/server/src/ARCH-ppc32/crt0.S @@ -0,0 +1,23 @@ +/* + * (c) 2009 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ +.section .text.init, "ax" +.type _start, @function +.globl _start +_start: + lis %r1, crt0_stack_high@ha /* load stack pointer */ + addi %r1, %r1, crt0_stack_high@l + b init + +.section ".bss", "aw" + +.global crt0_stack_low +crt0_stack_low: + .space 4096 +.global crt0_stack_high +crt0_stack_high: diff --git a/l4/pkg/sigma0/server/src/ARCH-sparc/crt0.S b/l4/pkg/sigma0/server/src/ARCH-sparc/crt0.S new file mode 100644 index 00000000..e9942b66 --- /dev/null +++ b/l4/pkg/sigma0/server/src/ARCH-sparc/crt0.S @@ -0,0 +1,26 @@ +/* + * (c) 2008-2009 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ + +.section .text.init,#alloc,#execinstr +.type _start,#function +.globl _start +_start: + ta 0 + +.LCstack: .word crt0_stack_high +.LCexit: .word _exit + +.section ".bss" + + .align 4 + .global crt0_stack_low +crt0_stack_low: + .space 2048 + .global crt0_stack_high +crt0_stack_high: diff --git a/l4/pkg/sigma0/server/src/ARCH-x86/crt0.S b/l4/pkg/sigma0/server/src/ARCH-x86/crt0.S new file mode 100644 index 00000000..270751de --- /dev/null +++ b/l4/pkg/sigma0/server/src/ARCH-x86/crt0.S @@ -0,0 +1,34 @@ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ +#define __ASSEMBLY__ +#include + + .section .text + +ENTRY(__crt_dummy__) +ENTRY(_start) +ENTRY(start) + + test %ecx, %ecx + jne 1f + popl %ecx /* ptr to kernel info page is on init stack */ +1: + leal _stack,%esp /* reset stack */ + pushl %ecx /* push args to init() */ + pushl $_exit + jmp init + +ENTRY(__main) + ret + + .bss + + .space 2048 +ENTRY(_stack) diff --git a/l4/pkg/sigma0/server/src/Makefile b/l4/pkg/sigma0/server/src/Makefile new file mode 100644 index 00000000..b94aead3 --- /dev/null +++ b/l4/pkg/sigma0/server/src/Makefile @@ -0,0 +1,32 @@ +PKGDIR ?= ../.. +L4DIR ?= $(PKGDIR)/../.. + +TARGET = sigma0 +MODE = sigma0 +L4_LIBS = -static -nostdlib $(GCCLIB) +REQUIRES_LIBS = libc_minimal cxx_util cxx_io cxx_base \ + cxx_io_kdebug l4sys-direct l4sys +DEFINES += -DL4_MINIMAL_LIBC +DEFAULT_RELOC_x86 := 0x00100000 +DEFAULT_RELOC_amd64 := 0x00100000 +DEFAULT_RELOC_arm := 0x00090000 +DEFAULT_RELOC_sparc := 0x01200000 +DEFAULT_RELOC_ppc32 := 0x00100000 +RELOC_PHYS := y + +PRIVATE_INCDIR = $(SRC_DIR) + +SRC_CC := init.cc memmap.cc page_alloc.cc mem_man.cc io_backend.cc \ + init_mem.cc +SRC_CC_x86-l4f := ioports_x86.cc +SRC_CC_amd64-l4f := ioports_x86.cc +SRC_CC_arm-l4f := ioports_none.cc +SRC_CC_ppc32-l4f := ioports_none.cc +SRC_CC_sparc-l4f := ioports_none.cc +SRC_C := support.c +SRC_S := $(addprefix ARCH-$(ARCH)/, crt0.S) + +include $(L4DIR)/mk/prog.mk +CRT1_stat_bin = + +CXXFLAGS += -DL4_NO_RTTI -fno-rtti -fno-exceptions -Wall diff --git a/l4/pkg/sigma0/server/src/globals.h b/l4/pkg/sigma0/server/src/globals.h new file mode 100644 index 00000000..ad92933f --- /dev/null +++ b/l4/pkg/sigma0/server/src/globals.h @@ -0,0 +1,40 @@ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ +#ifndef GLOBALS_H +#define GLOBALS_H + +#include + +/* Special options for compatibility reasons */ + +enum { + debug_errors = 1, + debug_warnings = 0, + debug_ipc = 0, + debug_memory_maps = 1, + +}; + +/* globals defined here (when included from globals.c) */ +#define PROG_NAME "SIGMA0" + +enum { + sigma0_taskno = 2, + root_taskno = 4 +}; + +extern "C" void L4_NORETURN _exit(int); + +inline void L4_NORETURN abort() +{ + _exit(1); +} + +#endif diff --git a/l4/pkg/sigma0/server/src/init.cc b/l4/pkg/sigma0/server/src/init.cc new file mode 100644 index 00000000..c2608ceb --- /dev/null +++ b/l4/pkg/sigma0/server/src/init.cc @@ -0,0 +1,79 @@ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ +/* startup stuff */ + +/* it should be possible to throw away the text/data/bss of the object + file resulting from this source -- so, we don't define here + anything we could still use at a later time. instead, globals are + defined in globals.c */ + +#include + +#include + +#include "globals.h" +#include "mem_man.h" +#include "page_alloc.h" +#include "memmap.h" +#include "init.h" +#include "init_mem.h" +#include "ioports.h" +#include "mem_man_test.h" +#include + +/* started as the L4 sigma0 task from crt0.S */ + +extern "C" void _init(void); + +typedef void Ctor(); +extern Ctor *__preinit_array_start[]; +extern Ctor *__preinit_array_end []; +extern Ctor *__init_array_start []; +extern Ctor *__init_array_end []; + +static void call_init_array(Ctor **start, Ctor **end) +{ + for (; start < end; ++start) + if (*start) + (*start)(); +} + +void +init(l4_kernel_info_t *info) +{ + call_init_array(__preinit_array_start, __preinit_array_end); + _init(); + call_init_array(__init_array_start, __init_array_end); + + l4_info = info; + + L4::cout << PROG_NAME": Hello!\n"; + L4::cout << " KIP @ " << info << '\n'; + + l4_debugger_set_object_name(L4_BASE_TASK_CAP, "sigma0"); + l4_debugger_set_object_name(L4_BASE_FACTORY_CAP, "root factory"); + l4_debugger_set_object_name(L4_BASE_THREAD_CAP, "sigma0"); + + Page_alloc_base::init(); + + init_memory(info); + init_io_ports(info); + + //mem_man_test(); + + L4::cout << " allocated " << Page_alloc_base::total()/1024 + << "KB for maintenance structures\n"; + + if (debug_memory_maps) + dump_all(); + + /* now start the memory manager */ + pager(); +} diff --git a/l4/pkg/sigma0/server/src/init.h b/l4/pkg/sigma0/server/src/init.h new file mode 100644 index 00000000..077833e0 --- /dev/null +++ b/l4/pkg/sigma0/server/src/init.h @@ -0,0 +1,21 @@ +/* + * (c) 2008-2009 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ +#ifndef INIT_H +#define INIT_H + +#include + +#define INIT_SECTION __attribute__((section (".init"))) + +#ifdef __cplusplus +extern "C" +#endif +void init(l4_kernel_info_t *info) L4_NORETURN; + +#endif diff --git a/l4/pkg/sigma0/server/src/init_mem.cc b/l4/pkg/sigma0/server/src/init_mem.cc new file mode 100644 index 00000000..50bd4b16 --- /dev/null +++ b/l4/pkg/sigma0/server/src/init_mem.cc @@ -0,0 +1,99 @@ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ + +#include "init_mem.h" +#include "memmap.h" +#include "globals.h" + +#include +#include +#include + +using L4::Kip::Mem_desc; + +void +init_memory(l4_kernel_info_t *info) +{ + if (info->version >> 24 != 0x87 /*KIP_VERSION_FIASCO*/ ) + { + L4::cout << PROG_NAME": is designed to run on FIASCO only\n"; + enter_kdebug("FATAL"); + } + + tbuf_status = 0; //fiasco_tbuf_get_status_phys(); + +#ifdef ARCH_x86 + char kip_syscalls = l4_info->kip_sys_calls; + + L4::cout << " Found Fiasco: KIP syscalls: " + << (kip_syscalls ? "yes\n" : "no\n"); +#endif + + iomem.add_free(Region(0, ~0UL)); + + Mem_desc *md = Mem_desc::first(info); + Mem_desc *end = md + Mem_desc::count(info); + + Region mismatch = Region::invalid(); + for (; md < end && !mismatch.valid(); ++md) + { + if (md->is_virtual()) + continue; + + Mem_desc::Mem_type type = md->type(); + unsigned long start, end; + if (type == Mem_desc::Conventional) + { + start = l4_round_page(md->start()); + end = l4_trunc_page(md->end() + 1) - 1; + } + else + { + start = l4_trunc_page(md->start()); + end = l4_round_page(md->end()) - 1; + } + + switch (type) + { + case Mem_desc::Conventional: + Mem_man::ram()->add_free(Region(start, end)); + if (!iomem.reserve(Region(start, end, sigma0_taskno))) + mismatch = Region(start, end, sigma0_taskno); + continue; + case Mem_desc::Reserved: + case Mem_desc::Dedicated: + if ( !iomem.reserve(Region(start, end, sigma0_taskno)) + || !Mem_man::ram()->reserve(Region(start, end, sigma0_taskno))) + mismatch = Region(start, end, sigma0_taskno); + break; + case Mem_desc::Bootloader: + if ( !iomem.reserve(Region(start, end, sigma0_taskno)) + || !Mem_man::ram()->reserve(Region(start, end, root_taskno))) + mismatch = Region(start, end, root_taskno); + break; + case Mem_desc::Arch: + case Mem_desc::Shared: + iomem.add_free(Region(start, end)); + if (!Mem_man::ram()->reserve(Region(start, end, sigma0_taskno))) + mismatch = Region(start, end, root_taskno); + break; + default: + break; + } + } + + if (mismatch.valid()) + { + L4::cout << PROG_NAME": Could not reserve memory\n" + << mismatch << "\n"; + dump_all(); + abort(); + } +} diff --git a/l4/pkg/sigma0/server/src/init_mem.h b/l4/pkg/sigma0/server/src/init_mem.h new file mode 100644 index 00000000..4fb888ce --- /dev/null +++ b/l4/pkg/sigma0/server/src/init_mem.h @@ -0,0 +1,17 @@ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ +#ifndef SIGMA0_INIT_MEM_H__ +#define SIGMA0_INIT_MEM_H__ + +#include + +void init_memory(l4_kernel_info_t *info); + +#endif /* ! SIGMA0_INIT_MEM_H__ */ diff --git a/l4/pkg/sigma0/server/src/io_backend.cc b/l4/pkg/sigma0/server/src/io_backend.cc new file mode 100644 index 00000000..08ffe93a --- /dev/null +++ b/l4/pkg/sigma0/server/src/io_backend.cc @@ -0,0 +1,76 @@ +/* + * (c) 2004-2009 Adam Lackorzynski , + * Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ + +#include +#include +#include +#include +#include + +inline void *operator new (size_t, void *p) { return p; } + +namespace L4 { + + class LogIOBackend : public IOBackend + { + public: + LogIOBackend(); + protected: + void write(char const *str, unsigned len); + }; + + LogIOBackend::LogIOBackend() + {} + + void LogIOBackend::write(char const *str, unsigned len) + { + l4_msg_regs_t store; + l4_msg_regs_t *mr = l4_utcb_mr(); + unsigned l = len; + L4::Cap log(L4_BASE_LOG_CAP); + + __builtin_memcpy(&store, mr, sizeof(store)); + + while (len) + { + l = len; + if (l > L4_VCON_WRITE_SIZE) + l = L4_VCON_WRITE_SIZE; + log->write(str, l); + len -= l; + str += l; + } + + __builtin_memcpy(mr, &store, sizeof(store)); + } + + typedef char Fake_iobackend[sizeof(LogIOBackend)] + __attribute__((aligned(__alignof__(LogIOBackend)))); + typedef char Fake_ostream[sizeof(BasicOStream)] + __attribute__((aligned(__alignof__(BasicOStream)))); + + Fake_ostream cout; + Fake_ostream cerr; + + static Fake_iobackend _iob; + + void iostream_init(); + + void iostream_init() + { + static l4_umword_t _initialized; + if (l4util_xchg(&_initialized, 1) == 0) + { + LogIOBackend *iob = new (&_iob) LogIOBackend(); + new (&cerr) BasicOStream(iob); + new (&cout) BasicOStream(iob); + } + } +}; diff --git a/l4/pkg/sigma0/server/src/ioports.h b/l4/pkg/sigma0/server/src/ioports.h new file mode 100644 index 00000000..8131188f --- /dev/null +++ b/l4/pkg/sigma0/server/src/ioports.h @@ -0,0 +1,21 @@ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ +#ifndef SIGMA0_IO_PORTS_H__ +#define SIGMA0_IO_PORTS_H__ + +#include +#include "memmap_internal.h" + +void init_io_ports(l4_kernel_info_t *info); +void handle_io_page_fault(l4_umword_t t, l4_utcb_t *utcb, Answer *a); + +void dump_io_ports(); + +#endif /* ! SIGMA0_IO_PORTS_H__ */ diff --git a/l4/pkg/sigma0/server/src/ioports_none.cc b/l4/pkg/sigma0/server/src/ioports_none.cc new file mode 100644 index 00000000..7fc7d412 --- /dev/null +++ b/l4/pkg/sigma0/server/src/ioports_none.cc @@ -0,0 +1,29 @@ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ +#include "ioports.h" +#include "mem_man.h" + +#include +#include + +static Mem_man io_ports; + +void init_io_ports(l4_kernel_info_t * /*info*/) +{ +} + +void handle_io_page_fault(l4_umword_t /*t*/, l4_utcb_t * /*utcb*/, Answer *a) +{ + a->error(L4_EINVAL); +} + +void dump_io_ports() +{} + diff --git a/l4/pkg/sigma0/server/src/ioports_x86.cc b/l4/pkg/sigma0/server/src/ioports_x86.cc new file mode 100644 index 00000000..636712d7 --- /dev/null +++ b/l4/pkg/sigma0/server/src/ioports_x86.cc @@ -0,0 +1,46 @@ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ +#include "ioports.h" +#include "mem_man.h" +#include "globals.h" + +#include +#include + +#include + +enum { PORT_SHIFT = 12 }; + +static Mem_man io_ports; + +void init_io_ports(l4_kernel_info_t * /*info*/) +{ + io_ports.add_free(Region::kr(0, (64*1024) << PORT_SHIFT)); +} + +void dump_io_ports() +{ + L4::cout << "IO PORTS--------------------------\n"; + io_ports.dump(); +} + +void handle_io_page_fault(l4_umword_t t, l4_utcb_t *utcb, Answer *a) +{ + unsigned long port, size; + l4_fpage_t fp = (l4_fpage_t&)l4_utcb_mr_u(utcb)->mr[0]; + port = l4_fpage_page(fp) << PORT_SHIFT; + size = l4_fpage_size(fp) + PORT_SHIFT; + + unsigned long i = io_ports.alloc(Region::bs(port, 1UL << size, t)); + if (i == port) + a->snd_fpage(l4_iofpage(port >> PORT_SHIFT, size - PORT_SHIFT)); + else + a->error(L4_ENOMEM); +} diff --git a/l4/pkg/sigma0/server/src/mem_man.cc b/l4/pkg/sigma0/server/src/mem_man.cc new file mode 100644 index 00000000..78329a2b --- /dev/null +++ b/l4/pkg/sigma0/server/src/mem_man.cc @@ -0,0 +1,265 @@ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg , + * Carsten Weinhold + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ +#include "mem_man.h" +#include "globals.h" + +#include +#include + +Mem_man Mem_man::_ram; + +Region const * +Mem_man::find(Region const &r, bool force) const +{ + if (!r.valid()) + return 0; + + Tree::Const_iterator n = _tree.find(r); + if (n == _tree.end()) + return 0; + + if (n->contains(r) || force) + return &(*n); + + return 0; +} + +bool +Mem_man::add(Region const &r) +{ + /* try to merge with prev region */ + Region rs = r; + if (rs.start() > 0) + { + rs.start(rs.start()-1); + + Tree::Node n = _tree.find_node(rs); + if (n && n->owner() == r.owner()) + { + r.start(n->start()); + int err = _tree.remove(*n); + if (err < 0) + { L4::cout << "err=" << err << " dump:\n"; dump(); enter_kdebug("BUG");} + } + } + + /* try to merge with next region */ + rs = r; + if (rs.end() + 1 != 0) + { + rs.end(rs.end()+1); + + Tree::Node n = _tree.find_node(rs); + if (n && n->owner() == r.owner()) + { + r.end(n->end()); + int err = _tree.remove(*n); + if (err < 0) + { L4::cout << "err=" << err << " dump:\n"; dump(); enter_kdebug("BUG");} + } + } + + /* do throw away regions owned by myself */ + if (r.owner() == sigma0_taskno) + return true; + + while (_tree.insert(r).second == -_tree.E_nomem) + if (!ram()->morecore()) + { + if (debug_errors) + L4::cout << PROG_NAME": Out of memory\n"; + return false; + } + + return true; +} + +bool +Mem_man::add_free(Region const &r) +{ + if (!r.valid()) + return true; + + // calculate the combined set of all overlapping regions within the tree + while (1) + { + Tree::Node n = _tree.find_node(r); + + if (!n) + break; + + if (n->start() < r.start()) + r.start(n->start()); + if (n->end() > r.end()) + r.end(n->end()); + + int err = _tree.remove(*n); + if (err < 0) + { L4::cout << "err=" << err << " dump:\n"; dump(); enter_kdebug("BUG");} + } + + return add(r); +} + +bool +Mem_man::alloc_from(Region const *r2, Region const &_r) +{ + Region r(_r); + if (r2->owner() && r2->owner() != r.owner()) + return false; + + if (r2->owner() == r.owner()) + return true; + + if (r == *r2) + { + // L4::cout << "dump " << r << " " << *r2 << "\n"; dump(); + int err = _tree.remove(*r2); + if (err < 0) + { L4::cout << "err=" << err << " dump:\n"; dump(); enter_kdebug("BUG"); } + return add(r); + } + + if (r.start() == r2->start()) + { + r2->start(r.end()+1); + //L4::cout << "move start to " << *r2 << '\n'; + add(r); + return true; + } + + if (r.end() == r2->end()) + { + r2->end(r.start()-1); + //L4::cout << "shrink end to " << *r2 << '\n'; + add(r); + return true; + } + + Region const nr(r.end()+1, r2->end(),r2->owner()); + r2->end(r.start()-1); + //L4::cout << "split to " << *r2 << "; " << nr << '\n'; + if (r.valid()) + add(r); + if (nr.valid()) + add(nr); + + return true; +} + +unsigned long +Mem_man::alloc(Region const &r, bool force) +{ + if (!r.valid()) + return ~0UL; + Region const *r2 = find(r, force); + if (!r2) + return ~0UL; + + //L4::cout << "alloc_from(" << *r2 << ", " << r << ")\n"; + if (!alloc_from(r2, r)) + return ~0UL; + + return r.start(); +} + +bool +Mem_man::reserve(Region const &r) +{ + if (!r.valid()) + return false; + + Region const *r2 = find(r, true); + if (!r2) + return true; + + return alloc_from(r2, r); +} + + +bool +Mem_man::morecore() +{ + Tree::Item_type *n = 0; + for (Tree::Rev_iterator i = _tree.rbegin(); i != _tree.rend(); ++i) + { + if (i->owner()) + continue; + + l4_addr_t st = l4_round_page(i->start()); + + if (st < i->end() && i->end()-st >= L4_PAGESIZE-1) + { + n = &(*i); + break; + } + } + + if (!n) + { + if (debug_memory_maps) + L4::cout << PROG_NAME": morecore did not find more free memory\n"; + return false; + } + + Region a = Region::bs(l4_round_page(n->end() - L4_PAGESIZE -1), L4_PAGESIZE, sigma0_taskno); + + Page_alloc_base::free((void*)a.start()); + + alloc_from(n, a); + + if (debug_memory_maps) + L4::cout << PROG_NAME": morecore: total=" << Page_alloc_base::total() / 1024 + << "kB avail=" << Page_alloc_base::allocator()->avail() / 1024 + << "kB: added " << a << '\n'; + return true; +} + +unsigned long +Mem_man::alloc_first(unsigned long size, unsigned owner) +{ + Tree::Item_type *n = 0; + + for (Tree::Iterator i = _tree.begin(); i != _tree.end(); ++i) + { + if (i->owner()) + continue; + + // wrap-around? + if ((i->start() + size - 1) < i->start()) + continue; + + l4_addr_t st = (i->start() + size-1) & ~(size-1); + //L4::cout << "test: " << (void*)st << " - " << i->end() << '\n'; + + if (st < i->end() && i->end() - st >= size - 1) + { + n = &(*i); + break; + } + } + + if (!n) + return ~0UL; + + Region a = Region::bs((n->start() + size-1) & ~(size-1), size, owner); + + alloc_from(n, a); + + return a.start(); +} + +void +Mem_man::dump() +{ + for (Tree::Iterator i = _tree.begin(); i != _tree.end(); ++i) + L4::cout << *i << '\n'; +} diff --git a/l4/pkg/sigma0/server/src/mem_man.h b/l4/pkg/sigma0/server/src/mem_man.h new file mode 100644 index 00000000..84857f24 --- /dev/null +++ b/l4/pkg/sigma0/server/src/mem_man.h @@ -0,0 +1,48 @@ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ +#ifndef SIGMA0_MEM_MAN_H__ +#define SIGMA0_MEM_MAN_H__ + +#include + +#include "page_alloc.h" +#include "region.h" + + +class Mem_man +{ +private: + bool alloc_from(Region const *r2, Region const &r); + + static Mem_man _ram; + +public: + typedef cxx::Avl_set< Region, cxx::Lt_functor, Slab_alloc> Tree; + +private: + Tree _tree; + +public: + static Mem_man *ram() { return &_ram; } + + unsigned long alloc(Region const &r, bool force = false); + bool reserve(Region const &r); + bool add_free(Region const &r); + bool add(Region const &r); + Region const *find(Region const &r, bool force = false) const; + + bool morecore(); + unsigned long alloc_first(unsigned long size, unsigned owner = 2); + + void dump(); +}; + +#endif + diff --git a/l4/pkg/sigma0/server/src/mem_man_test.cc b/l4/pkg/sigma0/server/src/mem_man_test.cc new file mode 100644 index 00000000..2361e268 --- /dev/null +++ b/l4/pkg/sigma0/server/src/mem_man_test.cc @@ -0,0 +1,44 @@ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ + +#include +#include "mem_man.h" + +#define ADD(a,b) \ + L4::cout << "add_free("#a","#b")\n"; \ + m.add_free(Region(a,b)) + +void mem_man_test() +{ + static Mem_man m; + L4::cout << "mem_man_test: ....\n"; + m.dump(); + ADD(0,9); + ADD(15,20); + ADD(25,30); + ADD(35,40); + ADD(45,50); + m.dump(); + ADD(10,11); + m.dump(); + ADD(14,14); + m.dump(); + ADD(12,13); + m.dump(); + ADD(24,31); + m.dump(); + ADD(21,25); + m.dump(); + ADD(8,37); + m.dump(); + ADD(0,44); + m.dump(); + L4::cout << "mem_man_test: done\n"; +} diff --git a/l4/pkg/sigma0/server/src/mem_man_test.h b/l4/pkg/sigma0/server/src/mem_man_test.h new file mode 100644 index 00000000..c23dfb3f --- /dev/null +++ b/l4/pkg/sigma0/server/src/mem_man_test.h @@ -0,0 +1,14 @@ +/* + * (c) 2008-2009 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ +#ifndef MEM_MAN_TEST_H__ +#define MEM_MAN_TEST_H__ + +void mem_man_test(); + +#endif diff --git a/l4/pkg/sigma0/server/src/memmap.cc b/l4/pkg/sigma0/server/src/memmap.cc new file mode 100644 index 00000000..f6549a75 --- /dev/null +++ b/l4/pkg/sigma0/server/src/memmap.cc @@ -0,0 +1,333 @@ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include "globals.h" +#include "page_alloc.h" +#include "mem_man.h" +#include "memmap.h" +#include "memmap_internal.h" +#include "ioports.h" + + +l4_addr_t mem_high; +l4_kernel_info_t *l4_info; +l4_addr_t tbuf_status; + +Mem_man iomem; + + +enum Requests +{ + None, + Map_free_page, + Map_kip, + Map_tbuf, + Map_ram, + Map_iomem, + Map_iomem_cached, + Debug_dump, +}; + +enum Memory_type { Ram, Io_mem, Io_mem_cached }; + +void dump_all() +{ + L4::cout << PROG_NAME": Dump of all resource maps\n" + << "RAM:------------------------\n"; + Mem_man::ram()->dump(); + L4::cout << "IOMEM:----------------------\n"; + iomem.dump(); + dump_io_ports(); +} + +static +void map_kip(Answer *a) +{ + a->snd_fpage((l4_umword_t) l4_info, L4_LOG2_PAGESIZE, true); +} + +static +void new_client(l4_umword_t, Answer *a) +{ + static l4_cap_idx_t _next_gate = 10 << L4_CAP_SHIFT; + l4_factory_create_gate_u(L4_BASE_FACTORY_CAP, _next_gate, + L4_BASE_THREAD_CAP, (_next_gate >> L4_CAP_SHIFT) << 4, a->utcb); + a->snd_fpage(l4_obj_fpage(_next_gate, 0, L4_FPAGE_RWX)); + _next_gate += L4_CAP_SIZE; + return; +} + +static +void map_tbuf(Answer *a) +{ + if (tbuf_status != 0x00000000 && tbuf_status != ~0UL) + { + a->snd_fpage(tbuf_status, L4_LOG2_PAGESIZE, false); + } +} + +static +void map_free_page(unsigned size, l4_umword_t t, Answer *a) +{ + unsigned long addr; + addr = Mem_man::ram()->alloc_first(1UL << size, t); + if (addr != ~0UL) + { + a->snd_fpage(addr, size); + + if (t < root_taskno) /* sender == kernel? */ + a->do_grant(); /* kernel wants page granted */ + } + else + a->error(L4_ENOMEM); +} + + +static +void map_mem(l4_fpage_t fp, Memory_type fn, l4_umword_t t, Answer *an) +{ + Mem_man *m; + switch (fn) + { + case Ram: + m = Mem_man::ram(); + break; + case Io_mem: + case Io_mem_cached: + m = &iomem; + break; + default: + an->error(L4_EINVAL); + return; + } + + unsigned long addr = m->alloc(Region::bs(fp.raw & ~((1UL << 12) - 1), + 1UL << l4_fpage_size(fp), t)); + + if (addr == ~0UL) + { + an->error(L4_ENOMEM); + return; + } + + /* the Fiasco kernel makes the page non-cachable if the frame + * address is greater than mem_high */ + an->snd_fpage(addr, l4_fpage_size(fp), false, fn != Io_mem); + + return; +} + +/* handler for page fault fault requests */ +static +void +handle_page_fault(l4_umword_t t, l4_utcb_t *utcb, Answer *answer) +{ + unsigned long pfa = l4_utcb_mr_u(utcb)->mr[0] & ~3UL; + + + unsigned long addr + = Mem_man::ram()->alloc(Region::bs(l4_trunc_page(pfa), L4_PAGESIZE, t)); + + if (addr != ~0UL) + { + answer->snd_fpage(addr, L4_LOG2_PAGESIZE); + return; + } + else if (debug_warnings) + L4::cout << PROG_NAME": Page fault, did not find page at " + << L4::hex << pfa << " for " << L4::dec << t << "\n"; + + answer->error(L4_ENOMEM); +} + +static +void handle_service_request(l4_umword_t t, l4_utcb_t *utcb, Answer *answer) +{ + if ((long)l4_utcb_mr_u(utcb)->mr[0] != L4_PROTO_SIGMA0) + { + answer->error(L4_ENODEV); + return; + } + new_client(t, answer); +} + +static +void handle_sigma0_request(l4_umword_t t, l4_utcb_t *utcb, Answer *answer) +{ + if (!SIGMA0_IS_MAGIC_REQ(l4_utcb_mr_u(utcb)->mr[0])) + { + answer->error(L4_ENOSYS); + return; + } + + switch (l4_utcb_mr_u(utcb)->mr[0] & 0x0f0) + { + case SIGMA0_REQ_ID_DEBUG_DUMP: + { + Mem_man::Tree::Node_allocator alloc; + L4::cout << PROG_NAME": Memory usage: a total of " + << Page_alloc_base::total() + << " byte are in the memory pool\n" + << " allocated " + << alloc.total_objects() - alloc.free_objects() + << " of " << alloc.total_objects() << " objects\n" + << " this are " + << (alloc.total_objects() - alloc.free_objects()) + * alloc.object_size + << " of " << alloc.total_objects() * alloc.object_size + << " byte\n"; + dump_all(); + answer->error(0); + } + break; + case SIGMA0_REQ_ID_TBUF: + map_tbuf(answer); + break; + case SIGMA0_REQ_ID_FPAGE_RAM: + map_mem((l4_fpage_t&)l4_utcb_mr_u(utcb)->mr[1], Ram, t, answer); + break; + case SIGMA0_REQ_ID_FPAGE_IOMEM: + map_mem((l4_fpage_t&)l4_utcb_mr_u(utcb)->mr[1], Io_mem, t, answer); + break; + case SIGMA0_REQ_ID_FPAGE_IOMEM_CACHED: + map_mem((l4_fpage_t&)l4_utcb_mr_u(utcb)->mr[1], Io_mem_cached, t, answer); + break; + case SIGMA0_REQ_ID_KIP: + map_kip(answer); + break; + case SIGMA0_REQ_ID_FPAGE_ANY: + map_free_page(l4_fpage_size(*(l4_fpage_t*)(&l4_utcb_mr_u(utcb)->mr[1])), t, answer); + break; + case SIGMA0_REQ_ID_NEW_CLIENT: + new_client(t, answer); + break; + default: + answer->error(L4_ENOSYS); + break; + } +} + +namespace { + +class Sigma0 : + public L4::Kobject_t +{}; + +} + +/* PAGER dispatch loop */ +void +pager(void) +{ + l4_umword_t t; + l4_msgtag_t tag; + + l4_utcb_t *utcb = l4_utcb(); + l4_msg_regs_t *mr = l4_utcb_mr_u(utcb); + Answer answer(utcb); + + /* now start serving the subtasks */ + for (;;) + { + tag = l4_ipc_wait(utcb, &t, L4_IPC_NEVER); +#if 0 + L4::cout << "w: res=" << L4::MsgDope(result) + << " tag=" << L4::dec << l4_msgtag_label(tag) << '\n'; +#endif + //L4::cout << PROG_NAME << ": rcv: " << tag << "\n"; + while (!l4_msgtag_has_error(tag)) + { + l4_umword_t pfa = mr->mr[0]; + t >>= 4; + /* we received a paging request here */ + /* handle the sigma0 protocol */ + + if (debug_ipc) + { + l4_umword_t d1 = mr->mr[0]; + l4_umword_t d2 = mr->mr[1]; + L4::cout << PROG_NAME": received " << tag << " d1=" << L4::hex + << d1 << " d2=" << d2 << L4::dec << " from thread=" + << t << '\n'; + } + + switch(tag.label()) + { + case L4_PROTO_SIGMA0: + handle_sigma0_request(t, utcb, &answer); + break; + case L4::Meta::Protocol: + { + L4::Ipc::Iostream ios(utcb); + ios.Istream::tag() = tag; + answer.tag = l4_msgtag(L4::Util::handle_meta_request(ios), 0, 0, 0); + } + break; + case L4::Factory::Protocol: + handle_service_request(t, utcb, &answer); + break; + case L4_PROTO_PAGE_FAULT: + handle_page_fault(t, utcb, &answer); + break; + case L4_PROTO_IO_PAGE_FAULT: + handle_io_page_fault(t, utcb, &answer); + break; + default: + answer.error(L4_EBADPROTO); + break; + } + + if (answer.failed()) + { + if (debug_warnings) + { + L4::cout << PROG_NAME": can't handle label=" << L4::dec + << l4_msgtag_label(tag) + << " d1=" << L4::hex << pfa + << " d2=" << mr->mr[1] + << " from thread=" << L4::dec << t << '\n'; + if (tag.is_page_fault()) + Mem_man::ram()->dump(); + } + + if (tag.is_exception()) + enter_kdebug("s1"); + } + + if (debug_ipc) + L4::cout << PROG_NAME": sending d1=" << L4::hex << mr->mr[0] + << " d2=" << mr->mr[1] + << " msg=" << answer.tag << L4::dec + << " to thread=" << t << '\n'; + + /* send reply and wait for next message */ + tag = l4_ipc_reply_and_wait(utcb, answer.tag, &t, L4_IPC_SEND_TIMEOUT_0); +#if 0 + L4::cout << "rplw: res=" << L4::MsgDope(result) + << " tag=" << L4::dec << l4_msgtag_label(tag) << '\n'; +#endif + + } + } +} + diff --git a/l4/pkg/sigma0/server/src/memmap.h b/l4/pkg/sigma0/server/src/memmap.h new file mode 100644 index 00000000..7934d5d1 --- /dev/null +++ b/l4/pkg/sigma0/server/src/memmap.h @@ -0,0 +1,37 @@ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ +#ifndef MEMMAP_H +#define MEMMAP_H + +#include +#include +#include + +#include "mem_man.h" +#include "globals.h" + + +extern Mem_man iomem; + +extern l4_kernel_info_t *l4_info; +extern l4_addr_t tbuf_status; + +#ifdef __cplusplus +extern "C" { +#endif +void pager(void) L4_NORETURN; +void dump_all(void); + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/l4/pkg/sigma0/server/src/memmap_internal.h b/l4/pkg/sigma0/server/src/memmap_internal.h new file mode 100644 index 00000000..9c822886 --- /dev/null +++ b/l4/pkg/sigma0/server/src/memmap_internal.h @@ -0,0 +1,63 @@ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ +#pragma once + +#include +#include + +enum +{ + L4_fpage_cached = L4_FPAGE_CACHEABLE << 4, + L4_fpage_uncached = L4_FPAGE_UNCACHEABLE << 4, + L4_fpage_buffered = L4_FPAGE_BUFFERABLE << 4, +}; + +struct Answer +{ +private: + void snd_base(unsigned long base) + { l4_utcb_mr_u(utcb)->mr[0] = (base & (~0UL << 10)) | 8; } + +public: + l4_utcb_t *utcb; + l4_msgtag_t tag; + + Answer(l4_utcb_t *utcb) : utcb(utcb), tag(l4_msgtag(0,0,0,0)) {} + + void error(int err) { tag = l4_msgtag(-err, 0, 0, 0); } + + void snd_fpage(l4_fpage_t const &fp, unsigned long snd_base = 0) + { + this->snd_base(snd_base); + l4_utcb_mr_u(utcb)->mr[1] = fp.raw; + } + + void snd_fpage(unsigned long addr, unsigned size, bool ro = false, + bool cache = true) + { + snd_base(addr); + if (cache) + l4_utcb_mr_u(utcb)->mr[0] |= L4_fpage_cached; + else + l4_utcb_mr_u(utcb)->mr[0] |= L4_fpage_uncached; + + l4_utcb_mr_u(utcb)->mr[1] = l4_fpage(addr, size, + ro ? L4_FPAGE_RX : L4_FPAGE_RWX).raw; + + tag = l4_msgtag(0, 0, 1, 0); + } + + bool failed() const + { return tag.label() < 0; } + + void do_grant() + { l4_utcb_mr_u(utcb)->mr[0] |= 2; } +}; + diff --git a/l4/pkg/sigma0/server/src/page_alloc.cc b/l4/pkg/sigma0/server/src/page_alloc.cc new file mode 100644 index 00000000..46c1ea90 --- /dev/null +++ b/l4/pkg/sigma0/server/src/page_alloc.cc @@ -0,0 +1,17 @@ +/* + * (c) 2008-2009 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ +#include "page_alloc.h" + +Page_alloc_base::Alloc Page_alloc_base::_alloc; +unsigned long Page_alloc_base::_total; + +static char page_alloc_scratch_mem[L4_PAGESIZE] __attribute__((aligned(4096))); + +void Page_alloc_base::init() +{ free(page_alloc_scratch_mem); } diff --git a/l4/pkg/sigma0/server/src/page_alloc.h b/l4/pkg/sigma0/server/src/page_alloc.h new file mode 100644 index 00000000..16db3560 --- /dev/null +++ b/l4/pkg/sigma0/server/src/page_alloc.h @@ -0,0 +1,55 @@ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ +#ifndef SIGMA0_PAGE_ALLOC_H__ +#define SIGMA0_PAGE_ALLOC_H__ + +#include + +#include +#include + +class Page_alloc_base +{ +public: + typedef cxx::List_alloc Alloc; +protected: + static Alloc _alloc; + static unsigned long _total; +public: + static void init(); + static void free(void *m) + { + allocator()->free(m, L4_PAGESIZE); + _total += L4_PAGESIZE; + } + + static Alloc *allocator() { return &_alloc; } + static unsigned long total() { return _total; } +}; + +template< typename T > +class Page_alloc : public Page_alloc_base +{ +public: + enum { can_free = 1 }; + T *alloc() + { return (T*)_alloc.alloc(L4_PAGESIZE,L4_PAGESIZE); } + + void free(T* b) + { _alloc.free(b, L4_PAGESIZE); } +}; + +template< typename Type > +class Slab_alloc +: public cxx::Slab_static +{}; + + +#endif diff --git a/l4/pkg/sigma0/server/src/region.h b/l4/pkg/sigma0/server/src/region.h new file mode 100644 index 00000000..a404c670 --- /dev/null +++ b/l4/pkg/sigma0/server/src/region.h @@ -0,0 +1,63 @@ +/* + * (c) 2008-2009 Adam Lackorzynski + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ +#ifndef SIGMA0_REGION_H__ +#define SIGMA0_REGION_H__ + +class Region +{ +private: + mutable unsigned long _l, _h; +public: + enum { Owner_mask = 0xfff }; + Region() : _l(0), _h(0) {} + Region(unsigned long start, unsigned long end, unsigned owner = 0 /*free*/) + : _l((start & ~Owner_mask) | owner), _h(end) {} + + unsigned owner() const { return _l & Owner_mask; } + unsigned long start() const { return _l & ~Owner_mask; } + unsigned long end() const { return _h; } + + void owner(unsigned owner) const { _l = (_l & ~Owner_mask) | owner; } + void start(unsigned long _start) const + { _l = (_l & Owner_mask) | (_start & ~Owner_mask); } + void end(unsigned long _end) const { _h = _end; } + + bool operator < (Region const &r) const { return end() < r.start(); } + bool contains(Region const &r) const + { return start() <= r.start() && end() >= r.end(); } + + bool operator == (Region const &r) const + { return start() == r.start() && end() == r.end(); } + + bool valid() const { return end() >= start(); } + + static Region invalid() { return Region(~0UL, 0); } + + static Region bs(unsigned long start, unsigned long size, unsigned owner = 0) + { + if (size == 0) + return invalid(); + + return Region(start, start+size-1,owner); + } + + static Region kr(unsigned long start, unsigned long end, unsigned owner = 0) + { return bs(start, end-start, owner); } + +}; + + +template< typename OS > +OS &operator << (OS &os, Region const &r) +{ + os << '[' << r.owner() << ':' << (void*)r.start() << ';' << (void*)r.end() << ']'; + return os; +} +#endif + diff --git a/l4/pkg/sigma0/server/src/support.c b/l4/pkg/sigma0/server/src/support.c new file mode 100644 index 00000000..9dbbad9b --- /dev/null +++ b/l4/pkg/sigma0/server/src/support.c @@ -0,0 +1,25 @@ +/* + * (c) 2008-2009 Adam Lackorzynski , + * Alexander Warg + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + */ +#include + +void __aeabi_unwind_cpp_pr0(void); +void __aeabi_unwind_cpp_pr1(void); +void __aeabi_unwind_cpp_pr0(void) {} +void __aeabi_unwind_cpp_pr1(void) {} + +void _exit(int) __attribute__((noreturn)); + +void _exit(int x) +{ + (void)x; + l4_ipc_sleep(L4_IPC_NEVER); + while (1) + ; +} diff --git a/l4/pkg/uclibc-headers/Control b/l4/pkg/uclibc-headers/Control new file mode 100644 index 00000000..d10fd6e9 --- /dev/null +++ b/l4/pkg/uclibc-headers/Control @@ -0,0 +1,3 @@ +Provides: libc-headers +source-pkg: uclibc +Maintainer: adam@os.inf.tu-dresden.de diff --git a/l4/pkg/uclibc-headers/Makefile b/l4/pkg/uclibc-headers/Makefile new file mode 100644 index 00000000..33a8e2df --- /dev/null +++ b/l4/pkg/uclibc-headers/Makefile @@ -0,0 +1,55 @@ +PKGDIR ?= . +L4DIR ?= $(PKGDIR)/../.. + +LIBCSRC_DIR = $(PKGDIR)/../uclibc/lib/uclibc + +all:: include +include: + +include $(LIBCSRC_DIR)/make_vars.mk + +HEADERS_LST := $(LIBCSRC_DIR_ABS)/target_headers.lst +DST_HEADERS := $(shell cat $(HEADERS_LST)) +HEADER_DIR := $(OBJ_DIR)/install_includes + +# just a few additions, handle them here directly +DST_HEADERS-arm := bits/arm_asm.h +DST_HEADERS-sparc := linux/sockios.h +DST_HEADERS-ppc32 := asm/sockios.h asm/ioctl.h + +DST_HEADERS += $(DST_HEADERS-$(BUILD_ARCH)) + +vpath %.h $(LIBCSRC_DIR)/ARCH-$(BUILD_ARCH)/include +vpath %.h $(LIBCSRC_DIR)/ARCH-all/include +vpath %.h $(CONTRIB_DIR)/libc/sysdeps/linux/$(UCLIBC_ARCH) +vpath %.h $(CONTRIB_DIR)/libc/sysdeps/linux/common +vpath %.h $(CONTRIB_DIR)/include + +all:: $(HEADERS_LST) + +DST_HEADERS := $(addprefix $(HEADER_DIR)/,$(DST_HEADERS)) +INCDIRS_OBJ_m := $(HEADER_DIR)/Makefile + +$(DST_HEADERS): $(HEADER_DIR)/%: % + @$(INSTALL_LINK_MESSAGE) + $(VERBOSE)[ -d $(@D) ] || $(MKDIR) -p $(@D) + $(VERBOSE)$(LN) -sf $(call absfilename,$<) $@ + + +$(INCDIRS_OBJ_m): + $(VERBOSE)install -d $(dir $@) + $(VERBOSE)echo 'PKGDIR ?= $(PKGDIR_ABS)' > $@ + $(VERBOSE)echo 'L4DIR ?= $(L4DIR_ABS)' >> $@ + $(VERBOSE)echo 'OBJ_BASE ?= $(OBJ_BASE)' >> $@ + $(VERBOSE)echo 'OBJ_DIR ?= $(OBJ_DIR)' >> $@ + $(VERBOSE)echo 'INSTALL_INC_PREFIX = uclibc' >> $@ + $(VERBOSE)echo 'include $$(L4DIR)/mk/include.mk' >> $@ + +include: $(DST_HEADERS) $(INCDIRS_OBJ_m) + $(VERBOSE)$(MAKE) $(MKFLAGS) -C $(HEADER_DIR) + $(VERBOSE)$(MAKE) $(MKFLAGS) -C $(LIBCSRC_DIR)/../libpthread/include + + +#all include:: +# $(MAKE) $(MKFLAGS) -C $(PKGDIR)/../uclibc/lib include + diff --git a/l4/pkg/uclibc-minimal/Control b/l4/pkg/uclibc-minimal/Control new file mode 100644 index 00000000..ee03744d --- /dev/null +++ b/l4/pkg/uclibc-minimal/Control @@ -0,0 +1,4 @@ +provides: libc_minimal +requires: libc-headers +source-pkg: uclibc +Maintainer: adam@os.inf.tu-dresden.de diff --git a/l4/pkg/uclibc-minimal/Makefile b/l4/pkg/uclibc-minimal/Makefile new file mode 100644 index 00000000..8599c261 --- /dev/null +++ b/l4/pkg/uclibc-minimal/Makefile @@ -0,0 +1,6 @@ +PKGDIR ?= . +L4DIR ?= $(PKGDIR)/../.. + +TARGET := libc + +include $(L4DIR)/mk/subdir.mk diff --git a/l4/pkg/uclibc-minimal/libc/Make.rules b/l4/pkg/uclibc-minimal/libc/Make.rules new file mode 100644 index 00000000..939349a7 --- /dev/null +++ b/l4/pkg/uclibc-minimal/libc/Make.rules @@ -0,0 +1,33 @@ +# vi:ft=make +PKGDIR ?= .. +L4DIR ?= $(PKGDIR)/../.. + +TARGET := libuc_c_minimal.a +PC_FILENAME := libc_minimal +PC_LIBS := -luc_c_minimal +DEFINES += -DL4_MINIMAL_LIBC +LIBCSRC_DIR ?= $(PKGDIR)/../uclibc/lib/uclibc + +include $(LIBCSRC_DIR)/make_vars.mk +include $(LIBCSRC_DIR)/make_rules.mk +include $(LIBCSRC_DIR)/contrib_files.mk + +DIRS := libc/string libc/pwd_grp libc/unistd libc/signal \ + libc/stdlib libc/stdio libc/stdlib/malloc-standard \ + libc/misc libc/sysdeps/linux libc/termios libm libcrypt + +SUB_MODULES := + +# process all sources for the libc +$(eval $(call PROCESS_src_lists, $(DIRS), $(SUB_MODULES))) +# libm stuff +$(eval $(call PROCESS_template_src, libm, float double)) + +SRC_C_$(TARGET) += $(UCLIBC_SRC_C) $(UCLIBC_SRC_C_libuc_c_minimal.a) \ + libc/stdlib/atexit.c +SRC_CC_$(TARGET) += $(UCLIBC_SRC_CC) $(UCLIBC_SRC_CC_libuc_c_minimal.a) +SRC_S_$(TARGET) += $(UCLIBC_SRC_S) $(UCLIBC_SRC_S_libuc_c_minimal.a) + +$(GENERAL_D_LOC): $(SRC_DIR)/Make.rules $(LIBCSRC_DIR)/contrib_files.mk + + diff --git a/l4/pkg/uclibc-minimal/libc/Makefile b/l4/pkg/uclibc-minimal/libc/Makefile new file mode 100644 index 00000000..52fe527a --- /dev/null +++ b/l4/pkg/uclibc-minimal/libc/Makefile @@ -0,0 +1,9 @@ +PKGDIR ?= .. +L4DIR ?= $(PKGDIR)/../.. + +LIBCSRC_DIR ?= $(PKGDIR)/../uclibc/lib/uclibc +SYSTEMS ?= $(SYSTEMS_PLAIN) + +include $(L4DIR)/mk/Makeconf +include $(LIBCSRC_DIR)/src_rules.mk + diff --git a/l4/pkg/uclibc/Control b/l4/pkg/uclibc/Control new file mode 100644 index 00000000..948a8bbd --- /dev/null +++ b/l4/pkg/uclibc/Control @@ -0,0 +1,3 @@ +Provides: libc libpthread libc_minimal_l4re +requires: l4sys l4re +Maintainer: adam@os.inf.tu-dresden.de diff --git a/l4/pkg/uclibc/LEGAL b/l4/pkg/uclibc/LEGAL new file mode 100644 index 00000000..70fb169b --- /dev/null +++ b/l4/pkg/uclibc/LEGAL @@ -0,0 +1,3 @@ +lib/contrib/uclibc : LGPL +lib/backends : TUD +lib/include : TUD diff --git a/l4/pkg/uclibc/Makefile b/l4/pkg/uclibc/Makefile new file mode 100644 index 00000000..eb41194a --- /dev/null +++ b/l4/pkg/uclibc/Makefile @@ -0,0 +1,7 @@ +# directories we need to know +PKGDIR = . +L4DIR ?= $(PKGDIR)/../.. + +# include subdir role +include $(L4DIR)/mk/subdir.mk + diff --git a/l4/pkg/uclibc/README.L4 b/l4/pkg/uclibc/README.L4 new file mode 100644 index 00000000..fa1d1776 --- /dev/null +++ b/l4/pkg/uclibc/README.L4 @@ -0,0 +1,8 @@ + +Based on git repo: + +commit 2a416f277e43be8301f1fdcdca7515b1e2a4508c +Author: Matt Fleming +Date: Mon Nov 15 15:34:18 2010 +0000 + + diff --git a/l4/pkg/uclibc/doc/Makefile b/l4/pkg/uclibc/doc/Makefile new file mode 100644 index 00000000..bc44ce27 --- /dev/null +++ b/l4/pkg/uclibc/doc/Makefile @@ -0,0 +1,6 @@ +PKGDIR = .. +L4DIR ?= $(PKGDIR)/../.. + +SRC_DOX_REF = uclibc.cfg + +include $(L4DIR)/mk/doc.mk diff --git a/l4/pkg/uclibc/doc/general.dox b/l4/pkg/uclibc/doc/general.dox new file mode 100644 index 00000000..c7535f24 --- /dev/null +++ b/l4/pkg/uclibc/doc/general.dox @@ -0,0 +1,55 @@ +/*!\file doc/general.dox + * + * \brief Mainpage definition and some concept description + */ + +/*!\mainpage uClibc - basic libc support for L4env + +\section p_overview Overview + +UClibc is the port of the uClibc to L4env. It enables you to use +basic libc functionality in L4env-based programs. The supported +functions are listed below. + +\section p_mem Memory allocation + +\par + malloc, free, calloc + +\par + alloca + +\section p_string String functions + +\par + mem*, str* + +\par + bcopy, bzero, bcmp + +\par + snprint, sprintf, vsprintf + +\section p_io I/O: (for debugging) + +\par + printf, vprintf + +\section p_type Type conversion functions + + + ato*, strto* + +\section p_unsupported Functions, not supported by the core of L4env + +- File I/O +- Networking +- Math +- Time +- Pthreads +- Signals + +Functions that are not listed here, may or may not work. + +\author Norman Feske +*/ diff --git a/l4/pkg/uclibc/doc/uclibc.cfg b/l4/pkg/uclibc/doc/uclibc.cfg new file mode 100644 index 00000000..7ed16043 --- /dev/null +++ b/l4/pkg/uclibc/doc/uclibc.cfg @@ -0,0 +1,1220 @@ +# Doxyfile 1.4.2 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project +# +# All text after a hash (#) is considered a comment and will be ignored +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" ") + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded +# by quotes) that should identify the project. + +PROJECT_NAME = "UClibc support for L4env" + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = uclibc + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create +# 4096 sub-directories (in 2 levels) under the output directory of each output +# format and will distribute the generated files over these directories. +# Enabling this option can be useful when feeding doxygen a huge amount of +# source files, where putting all generated files in the same directory would +# otherwise cause performance problems for the file system. + +CREATE_SUBDIRS = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, +# Dutch, Finnish, French, German, Greek, Hungarian, Italian, Japanese, +# Japanese-en (Japanese with English messages), Korean, Korean-en, Norwegian, +# Polish, Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, +# Swedish, and Ukrainian. + +OUTPUT_LANGUAGE = English + +# This tag can be used to specify the encoding used in the generated output. +# The encoding is not always determined by the language that is chosen, +# but also whether or not the output is meant for Windows or non-Windows users. +# In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES +# forces the Windows encoding (this is the default for the Windows binary), +# whereas setting the tag to NO uses a Unix-style encoding (the default for +# all platforms other than Windows). + +USE_WINDOWS_ENCODING = NO + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is +# used as the annotated text. Otherwise, the brief description is used as-is. +# If left blank, the following values are used ("$name" is automatically +# replaced with the name of the entity): "The $name class" "The $name widget" +# "The $name file" "is" "provides" "specifies" "contains" +# "represents" "a" "an" "the" + +ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = NO + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of +# the path mentioned in the documentation of a class, which tells +# the reader which header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that +# are normally passed to the compiler using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful is your file systems +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like the Qt-style comments (thus requiring an +# explicit @brief command for a brief description. + +JAVADOC_AUTOBRIEF = YES + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the DETAILS_AT_TOP tag is set to YES then Doxygen +# will output the detailed description near the top, like JavaDoc. +# If set to NO, the detailed description appears after the member +# documentation. + +DETAILS_AT_TOP = NO + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. + +INHERIT_DOCS = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce +# a new page for each member. If set to NO, the documentation of a member will +# be part of the file/class/namespace that contains it. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 8 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = "reviewer=\par Reviewer:\n" \ + "risks=\par Risks:\n" \ + "requires=\par Requires:\n" + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C +# sources only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources +# only. Doxygen will then generate output that is more tailored for Java. +# For instance, namespaces will be presented as packages, qualified scopes +# will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + +SUBGROUPING = YES + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = NO + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = YES + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = YES + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. +# If set to NO (the default) only methods in the interface are included. + +EXTRACT_LOCAL_METHODS = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = NO + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. + +SORT_BRIEF_DOCS = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the +# alphabetical list. + +SORT_BY_SCOPE_NAME = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or define consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and defines in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = YES + +# If the sources in your project are distributed over multiple directories +# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy +# in the documentation. + +SHOW_DIRECTORIES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from the +# version control system). Doxygen will invoke the program by executing (via +# popen()) the command , where is the value of +# the FILE_VERSION_FILTER tag, and is the name of an input file +# provided by doxygen. Whatever the progam writes to standard output +# is used as the file version. See the manual for examples. + +FILE_VERSION_FILTER = + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = YES + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be abled to get warnings for +# functions that are documented, but have no documentation for their parameters +# or return value. If set to NO (the default) doxygen will only warn about +# wrong or incomplete parameter documentation, but not about the absence of +# documentation. + +WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. Optionally the format may contain +# $version, which will be replaced by the version of the file (if it could +# be obtained via FILE_VERSION_FILTER) + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = $(L4DIR)/pkg/uclibc/doc/general.dox + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx +# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm + +FILE_PATTERNS = + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = NO + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used select whether or not files or +# directories that are symbolic links (a Unix filesystem feature) are excluded +# from the input. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. + +EXCLUDE_PATTERNS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = . + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = . + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. If FILTER_PATTERNS is specified, this tag will be +# ignored. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: +# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further +# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER +# is applied to all files. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + +FILTER_SOURCE_FILES = NO + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. + +SOURCE_BROWSER = YES + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = NO + +# If the REFERENCED_BY_RELATION tag is set to YES (the default) +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = YES + +# If the REFERENCES_RELATION tag is set to YES (the default) +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = YES + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = YES + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own +# stylesheet in the HTML output directory as well, or it will be erased! + +HTML_STYLESHEET = + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. + +HTML_ALIGN_MEMBERS = YES + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + +TOC_EXPAND = NO + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. + +DISABLE_INDEX = NO + +# This tag can be used to set the number of enum values (range [1..20]) +# that doxygen will group on one line in the generated HTML documentation. + +ENUM_VALUES_PER_LINE = 4 + +# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be +# generated containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, +# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are +# probably better off using the HTML help feature. + +GENERATE_TREEVIEW = NO + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = NO + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, a4wide, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = a4wide + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = NO + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = NO + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES = NO + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. + +GENERATE_XML = NO + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + +XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. + +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. This is useful +# if you want to understand what is going on. On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = NO + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_PREDEFINED tags. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# in the INCLUDE_PATH (see below) will be search if a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator +# instead of the = operator. + +PREDEFINED = DOXYGEN + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all function-like macros that are alone +# on a line, have an all uppercase name, and do not end with a semicolon. Such +# function macros are typically used for boiler-plate code, and will confuse +# the parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. +# Optionally an initial location of the external documentation +# can be added for each tagfile. The format of a tag file without +# this location is as follows: +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths or +# URLs. If a location is present for each tag, the installdox tool +# does not have to be run to correct the links. +# Note that each tag file must have a unique name +# (where the name does NOT include the path) +# If a tag file is not located in the directory in which doxygen +# is run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base +# or super classes. Setting the tag to NO turns the diagrams off. Note that +# this option is superseded by the HAVE_DOT option below. This is only a +# fallback. It is recommended to install and use dot, since it yields more +# powerful graphs. + +CLASS_DIAGRAMS = YES + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = NO + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# the CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = YES + +# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for groups, showing the direct groups dependencies + +GROUP_GRAPHS = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. + +UML_LOOK = NO + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = NO + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will +# generate a call dependency graph for every global function or class method. +# Note that enabling this option will significantly increase the time of a run. +# So in most cases it will be better to enable call graphs for selected +# functions only using the \callgraph command. + +CALL_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES +# then doxygen will show the dependencies a directory has on other directories +# in a graphical way. The dependency relations are determined by the #include +# relations between the files in the directories. + +DIRECTORY_GRAPH = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are png, jpg, or gif +# If left blank png will be used. + +DOT_IMAGE_FORMAT = png + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found in the path. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = + +# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width +# (in pixels) of the graphs generated by dot. If a graph becomes larger than +# this value, doxygen will try to truncate the graph, so that it fits within +# the specified constraint. Beware that most browsers cannot cope with very +# large images. + +MAX_DOT_GRAPH_WIDTH = 1024 + +# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height +# (in pixels) of the graphs generated by dot. If a graph becomes larger than +# this value, doxygen will try to truncate the graph, so that it fits within +# the specified constraint. Beware that most browsers cannot cope with very +# large images. + +MAX_DOT_GRAPH_HEIGHT = 1024 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes +# that lay further from the root node will be omitted. Note that setting this +# option to 1 or 2 may greatly reduce the computation time needed for large +# code bases. Also note that a graph may be further truncated if the graph's +# image dimensions are not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH +# and MAX_DOT_GRAPH_HEIGHT). If 0 is used for the depth value (the default), +# the graph is not depth-constrained. + +MAX_DOT_GRAPH_DEPTH = 0 + +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is disabled by default, which results in a white background. +# Warning: Depending on the platform used, enabling this option may lead to +# badly anti-aliased labels on the edges of a graph (i.e. they become hard to +# read). + +DOT_TRANSPARENT = NO + +# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) +# support this, this feature is disabled by default. + +DOT_MULTI_TARGETS = NO + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to the search engine +#--------------------------------------------------------------------------- + +# The SEARCHENGINE tag specifies whether or not a search engine should be +# used. If set to NO the values of all tags below this one will be ignored. + +SEARCHENGINE = NO diff --git a/l4/pkg/uclibc/lib/Makefile b/l4/pkg/uclibc/lib/Makefile new file mode 100644 index 00000000..97421035 --- /dev/null +++ b/l4/pkg/uclibc/lib/Makefile @@ -0,0 +1,6 @@ +PKGDIR ?= .. +L4DIR ?= $(PKGDIR)/../.. + +TARGET = uclibc libpthread minimal_l4re + +include $(L4DIR)/mk/subdir.mk diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/.gitignore b/l4/pkg/uclibc/lib/contrib/uclibc/.gitignore new file mode 100644 index 00000000..c2603a0b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/.gitignore @@ -0,0 +1,36 @@ +# +# Never ignore these +# +!.gitignore + +# +# Generated files +# +*.os +*.oS +*.a +*.i +*.o +*.depend +lib/ +install_dir/ +.config* +.*.dep +/*.log +cscope.* + +# +# Debugging files +# +.gdb_history +.gdbinit +core + +# +# Backups / patches +# +*~ +*.orig +*.rej +/*.patch +/*.diff diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/COPYING.LIB b/l4/pkg/uclibc/lib/contrib/uclibc/COPYING.LIB new file mode 100644 index 00000000..8add30ad --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/COPYING.LIB @@ -0,0 +1,504 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/COPYING.LIB.boilerplate b/l4/pkg/uclibc/lib/contrib/uclibc/COPYING.LIB.boilerplate new file mode 100644 index 00000000..82f597c1 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/COPYING.LIB.boilerplate @@ -0,0 +1 @@ +Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/Changelog b/l4/pkg/uclibc/lib/contrib/uclibc/Changelog new file mode 100644 index 00000000..3774fcf3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/Changelog @@ -0,0 +1,804 @@ +0.9.31 not yet released + + Upgrade notices from previous versions. + o On x86_64 the format of /var/run/utmp changed compared to previous + versions. To retain compatibility with glibc we now define + __WORDSIZE_COMPAT32. If you are certain that you will never use + glibc nor run in i386 mode on your x86_64 installation, you can + remove this definition from wordsize.h. + Otherwise you have to delete /var/run/utmp on x86_64 hosts when + upgrading to 0.9.31 + o The SHARED_LIB_LOADER_PREFIX was renamed to a single path + component called MULTILIB_DIR and defaults to 'lib'. + +0.9.27 12 January 2005 + + This has been a long time in the making... Release highlights: + o New stdio implementation + o New optimized string functions + o Major improvements to the shared lib loader + o Shared libraries work properly on powerpc + o Debugging works on mips + o New architectures: frv, nios, nios2, bfin + o Linux 2.6.x kernel support + o Lots and lots of bug fixes + + This release is NOT binary compatible with uClibc 0.9.26 or any earlier + release, so be prepared to recompile your software if you are still using + an old version of uClibc. + + -Erik + + + +0.9.26 3 January 2004 + + This simply adds a fix for a pthread bug that was noticed a few hours + after the previous release. Otherwise identical to 0.9.25. + + This release remains binary compatible with uClibc 0.9.21-25 as long as + you take care to avoid any configuraton changes that will break things. + We _were_ planning to break binary compatibilty in this release, but + decided to hold those changes so we could push out a bugfix release. + + We _will_ break binary compatibilty in the upcoming 0.9.27 release to + implement a few things we have been postponing. That should hopefully be + the last ABI change before we freeze the ABI for the upcoming 1.0.x + stable uClibc series. + +Release highlights: + o A trivial fix for a pthread bug + o Nothing else + + -Erik + + + +0.9.25 3 January 2004 + +See Changelog.full for the complete list of who did what. + +Note: + This release remains binary compatible with uClibc 0.9.21-24 as long as + you take care to avoid any configuraton changes that will break things. + We _were_ planning to break binary compatibilty in this release, but + decided to hold those changes so we could push out a bugfix release. + + We _will_ break binary compatibilty in the upcoming 0.9.26 release to + implement a few things we have been postponing. That should hopefully be + the last ABI change before we freeze the ABI for the upcoming 1.0.x + stable uClibc series. + +Release highlights: + o Fixed a ton of problems found using the LTP and NIST test suites. + The few remaining test failures are obscure corner cases, such as + a few functions that fail (correctly) with incorrect errno values. + o Fixed a longstanding pthreads bug -- amoung other things, you no + longer need to explicitly add -lpthread for perl to work. + o Added some sh optimized string functions + o Added sh64 shared library support + o The default malloc implementation has been replaced, and will + now actually free memory when told to do so. + o Both popen() and exec*() now behave themselves per SuSv3 + o Better 2.6.x kernel header support + o Added support for Position Independent Executables (PIE) on x86 + o Lots of other minor cleanups + + -Erik + + + +0.9.24 15 December 2003 + +See Changelog.full for the complete list of who did what. + +Note: + This release remains binary compatible with uClibc 0.9.21-23 as + long as you take care to avoid any configuraton changes that will + break things. + + We currently plan to break binary compatibilty in the upcoming 0.9.25 to + implement a few things we have been postponing, which will hopefully be + the last change.... + +Release highlights: + o Fixed several silly configuration problems + o Added arm optimized string functions + o Lots of minor cleanups + + -Erik + + + + + +0.9.23 13 November 2003 + +See Changelog.full for the complete list of who did what. + +Note: + This release is binary compatible with uClibc 0.9.21 and 0.9.22 as + long as you take care to avoid any configuraton changes that will + break things. Enabling or disabling things like soft-float, + locale, wide wchar support, or changing cpu type are all good + examples of things that will break binary compatibility. + +Release highlights: + o Fixed several silly configuration problems that were + present in the 0.9.22 release. + o Fixed compilation problem with soft-float support on + several architectures. + o Lots of cleanup work on the powepc shared lib loader + thanks to Joakim Tjernlund. + o Updated the debian packaging for use in a standalone uClibc + system, rather than being a subordinate library under a + glibc based system. + + -Erik + + + + + +0.9.22 8 November 2003 + +See Changelog.full for the complete list of who did what. + +Note: + This release is binary compatible with the 0.9.21 release + if you take care to avoid any configuraton changes that + might break things for you (i.e. enabling or disabling things + like soft-float, locale, wide wchar support, or changing cpu + type are all good examples of binary incompatible config options). + +Release highlights: + o Added e1, microblaze, and sh64 architectures. + o Much improved soft-float support + o Rewrote the passwd and group handing functions + and implemented all SuSv3 required reentrant + versions. + o Reworked and updated the Config system. You now + get to select your target architecture with the + config system. + o Fixed pthreads for mmuless m68k systems + o Added some x86 optimized string functions. + o Lots and lots of bugs fixed. + + -Erik + + + + + +0.9.21 9 September 2003 + +See Changelog.full for the complete list of who did what. + +Note: + This release is not binary compatible with earlier releases. + Sorry about that. We have never promised to provide binary + compatibility until we hit version 1.0, and even then, if + you change your configuration. + +Release highlights: + o uClibc now has full ANSI/ISO C99 locale support (except + for wcsftime() and collating items in regex). + o Added support for using pre-generated locale data, making + it easy for mere mortals to use uClibc w/locale support. + o Lots of new tuning options added to trade size + for features, allowing for smaller static binaries. + o The "dlopen()'ing libraries that depend on libraries" + problem was fixed. + o A new scanf implementation. Well tested, but + brand new so watch for obscure bugs... + o Reworked and updated the Config system, adding several + nice new features which we now use. + o Lots and lots of sundry bug fixes and cleanups. + + -Erik + + + + + +0.9.20 30 June 2003 + +See Changelog.full for the complete list of who did what. + +Note: + This release remains binary compatible with 0.9.18 and 0.9.19. + + +Release highlights: + o Some ldd, profiling, and gcc wrapper updates + o Updated to support and compile with gcc 3.3 + o Several needed mips updates + o Building under cygwin should now work... + o Prevent non-PIC code getting into PIC libs + o Added mmap64 support + o mmu-less systems now get a 16k default thread stack size + which is much more sane than the old 2 MB default... + o Implemented syscall() for powerpc + o Optionally struct tm extension support + o Lots of other sundry little fixes and cleanups. + o Prevent buffer overflows in the passwd and group functions. + + -Erik + + + + + +0.9.19 3 March 2003 + +See Changelog.full for the complete list of who did what. + +Note: + This release remains binary compatible with 0.9.18 (except + for mips, but then mips was unusable in stock 0.9.18 anyways). + + +Release highlights: + Stefan Allius + o Some Makefile and warning fixes + David Airlie + o Fixed gcc wrapper handling of ctor/dtor stuff when used in + with and w/o the nostdinc and nostdlib options + Erik Andersen + o Fixed a number of system call kernel type/user type translation + problems that scrambled a handful of system calls. + o Fixup powerpc syscalls to eliminate warnings with gcc-3.2 + o Fixed several ioctl special cases for powerpc + o Checked in forgotten mips kernel_types.h changes + o Fixed mips shared library loader bug that caused segfaults + o Major update to the pthreads library. Should improve performance. + o Fixed uClibc's shared library loader so we can properly debug + applications using pthreads (must use gdb 5.3 or newer which + was compiled using uClibc). + o Made uClibc's ldd act just the glibc provided one (i.e. relying + on the shared lib loader to do the work) when it is possible to + doi so, and only rummage about the ELF headers when we have no + other choice (such as when using 'ldd' on cross compiled stuff). + Miles Bader + o header file updates for v850 architecture + o Fixed v850 crt0.S __uClibc_main argument stack space + Jeffrey Damick + o Fixed res_init() so it properly reloads /etc/resolv.conf + Vadim Lebedev + o Fixed ARM setjmp when floating point was disabled + David McCullough + o Removed debug (-g) when building crti.o and crtn.o, as + debug would mess up the build for SH4 and probably others. + o Fixed SH setjmp when floating point was enabled + + + -Erik + + + + + +0.9.18 12 February 2003 + +See Changelog.full for the complete list of who did what. + +Note: + + Once again, this release is _NOT_ binary compatible with earlier + releases. I _think this will be the last time (with the possible + exception of some future changes to our locale support...) + + +Release highlights: + Stefan Allius + o fixed a compile problem when large file support was disabled + o fixed dlib_pic.o to compile with proper flags + o fixed a shared lib loader compile warning + o Made adding libgcc functions to uClibc optional + Erik Andersen + o Fixed scandir64 to not free the wrong pieces of memory + which caused segfaults + o Fixed mismatches between kernel and libc dirent structures + o Fixed mismatches between the size of uClibc's struct dirent + and struct dirent64 so that when _FILE_OFFSET_BITS=64 we + do not lose part of the filename + o Fixed getdents64.c so the build will not break when compiling + vs a 2.0.x Linux kernel when UCLIBC_HAS_LFS is enabled + o Create stub crti.o and crtn.o files when UCLIBC_CTOR_DTOR is disabled + o Fixed licenses for a few files that erroneously were listed as GPL + but were really LGPL after discussing with authors + o sigaction for x86 had an extra and unwanted sigaction syscall + o Fixed debugging of arm binaries by adding a .note.ABI-tag section + Miles Bader + o header file updates for v850 architecture + o Fixed v850 clone syscall + Christian Krause + o Fixed pthread_cond_timedwait to properly uses rt singals + when available + Christophe Massiot + o Added mips _flush_cache syscall + David McCullough + o Added m68k brk syscall + Marshall M. Midden + o Fixed pipe implementation for mips + + + -Erik + + + + + +0.9.17 25 January 2003 + +See Changelog.full for the complete list of who did what. + +Note: + + I have always reserved the right to make binary incompatible changes as + needed prior to the "1.0" release. This release is a good example of + that. A few bugs turned up that needed to be fixed and the only good way + to fix them was to change some fundamental data structure sizes. So I did + just that. As a result, this release is _NOT_ binary compatible with + earlier releases -- you will need to recompile your applications. + + +Release highlights: + Stefan Allius + o fixed a number of shared library loader bugs + o setjmp, longjmp, clone, and vfork cleanups for the SH architecture + o Don't build the config system with ncurses unless asked to + Tobias Anderberg + o cris architecture updates + Erik Andersen + o Changed 'struct stat' and 'struct stat64' so they use types that + are consistant with use elsewhere in the library. Without this, + subtle bugs would occur due to comparing signed and unsigned + types (for example, GNU tar wouldn't work) + o Fixed dlopen so it works with staticly linked apps + o Fixed sigaction on arm architecture so sa_restorer works properly + o Fixed sigaction on x86 architecture for (fixed debugging threads) + o Fixed a wide char related segfault in the regular expression code + o Powerpc pread and pwrite are now implemented correctly + o Powerpc syscall mechanism re-implemented + o Sparc architecture and syscall mechanism fixed up so things compile + o usershell reimplemented + o Fixed global destructors for staticly linked applications + o Added dynamic atexit support (needed for full C++ ctor/dtor support) + o The ldd utility now acts more like the GNU utility + o Added a stub libnsl library to make stupid configure scripts bahave + o Always build crt1.o as well as crt0.o to minimize the need to mess + with the compiler + o Rewrote powerpc crt0.S to properly handle ctors/dtors + o Removed unimplemented and legacy stuff from our header files to + make configure behave better + o Made the lib loader also support libs in /usr/X11R6/lib by default + o Config system updates + o networking function updates + o Large file support updates + o Lots of other little bug fixes and cleanups + Nick Fedchik + o Support ether_aton + Nathan Field + o Fixed pthread_mutex_lock and pthread_mutex_unlock so they + actually work as advertised on mips + o Fixed several nasty pthread bugs fixing debugging + Brett Hunt + o Fixed potential segfaults during 'make menuconfig' + Jay Kulpinski + o Fixed a subtle problem in the DNS resolver that prevented + uncompressed DNS lookup responses from working + David McCullough + o Fixed pclose error handling + David Meggy + o fixed the problem where arm binaries would crash on start + that Erik stupidly caused right before the last release. + Manuel Novoa III + o Major locale support update! + o Allow people to use pregenerated locale data instead of generating + approx 40Mb of glibc locales to get the 300+ locales currently + supported. + o locale dependent collation support + o Fixed locale support tools to work when cross-compiling + o Added the *wprintf functions + o Added the wcsto{inttype} functions + o Added iconv() and a mini iconv utility + o Added hsearch and hsearch_r + o Fixed a silly bug allowing wprintf %s to work correctly. + o Fixed fdopen when used with "a" (append). + o Fixed stdio file position handing to be sure fell() always + gives correct results + Luc Van Oostenryck + o Fixed a buffer overflow in getlogin_r + Yoshinori Sato + o Hitachi h8300 architecture update + Ronald Wahl + o Powerpc shared library relocation fixes + + -Erik + + + +0.9.16 8 November 2002 + +See Changelog.full for the complete list of who did what. + +Release highlights: + o CRIS architecture and shared library support from Tobias Anderberg + o New uClibc configuration system + o shared library global constructors and destructors initialization + ordering fixed by Stefan Allius + o More SuperH architecture fixes from Stefan Allius + o uClibc now compiles with newer versions of gcc (i.e. RedHat 8.0) + o uClibc no longer requires perl to compile + o mips dlopen was fixed by Steven J. Hill + o pty and tty handling fixes + o Manuel Novoa added support for a new /etc/TZ file for globally + setting the system timezone. + o Manuel also fixed up a number of remaining wide char issues. + o Lots of other little bug fixes and cleanups + + -Erik + + + +0.9.15 27 August 2002 + +This is a minor bugfix release. + +See Changelog.full for the complete list of who did what. +Release highlights: + o Eliminated the HAS_LONG_LONG option. gcc always supports + long long, and the option never excluded all long long anyways. + o ctype.h no longer allows multiple argument evaluation in + compliance with ANSI/ISO C99 + o Obscure printf fixes -- one involving %o and one involving %f. + o Bugfixes for locking and reentrance in password/group functions + o Directly use kernel types for most items, eliminating needless + translation and fixing several bugs. + o Directly use kernel struct stat -- no more translating + o More superH (sh) architecture merging from Stefan Allius + o Errno values and strerror are now correct on alpha, sparc, and mips + o Fixed an obscure bug with fclose when custom streams are enabled. + o Lots of other little bug fixes and cleanups + + -Erik + + + +0.9.14 12 August 2002 + +This is a minor bugfix release. + +See Changelog.full for the complete list of who did what. +Release highlights: + o Fix a compile error when RPC and Pthread support + were both enabled. + o Eliminate duplicate define warnings in wstring.c. + o Fix potentially broken preprocessor comparisons. + o Erik was an idiot and broke thread locking in exit(), + atexit() and friends. Fix that. + o Fix the gcc wrapper to use crtbeginS.o and crtendS.o when + compiling PIC code (crtbegin.o and crtend.o) otherwise. + + -Erik + + + + +0.9.13 9 August 2002 + +Security Fixes + o There was an off-by-one buffer overflow in the group + handling code, fix thanks to Joseph Chiu. + o There was an integer overflow bug in calloc, per + http://online.securityfocus.com/bid/5398 + o There was an integer overflow bug in the xdr_array + RPC code, per http://online.securityfocus.com/bid/5356 + +See Changelog.full for the complete list of who did what. +Release highlights: + o Add full shared library support for Hitachi SuperH (sh) + thanks to Stefan Allius and Edie C. Dost + o Lots of reentrance cleanups (we should now be fully + reentrant when compiled with pthread support). + o Miles Bader implemented a new mmap based malloc which is much + smarter than the old "malloc-simple", and actually works, unlike + the old "malloc". This is now the default for mmu-less systems + and should greatly help reduce memory fragmentation and wastage. + o Reworked syscall handling for i386 and ARM, smaller and cleaner. + o Support for the syscall() function on i386 and ARM + o The uClibc g++ wrapper now automagically adds the proper include + search path and and libraries. + o Lots of shared library loader updates + o dlopen'd shred libraries not properly run destructors + when ctor/dtor support is enabled + o pread/pwrite/pread64/pwrite64 now all work as expected + o Lots and lots of other bug fixes and cleanups. + + -Erik + + + + +0.9.12 20 June 2002 + +See Changelog.full for the complete list of who did what. +Release highlights: + o Add full shared library support for mips (big and little + endian), thanks to a lot of hard work from Steven J. Hill + o i960 architecture support, thanks to Martin Proulx + o An initial alpha port (works, but needs some cleanup) + o Fixes shared library support for powerpc + o Fixes for mmu-less systems + o Much improved thread locking and reentrance. + o More gcc wrapper updates. XFree86 really does link + this time around. It still didn't last time. + o Libcrypt now passes conformance tests + o Nearly complete locale supporti thanks to a lot + of hard work by Manuel Novoa III. This stuff is + _way_ smaller than glibc's + o Completely new time handling functions also by Manuel + o Lots of other bug fixes and cleanups. + + -Erik + + + + +Erik Andersen: +0.9.11 10 April 2002 + +Release highlights: + o Lots of bug fixes + o Much better large file support + o Several gcc wrapper bug fixes, so things like iproute2 and + XFree86 should now link properly. + o Fixes a stdio thread locking bug that could cause random + deadlocks on s*printf calls when threading was enabled. + +Erik Andersen: + o Added a generic implementation of truncate64.c and ftruncate64.c + o Added missing creat64, glob64, mkstemp64, getrlimit64, setrlimit64 + o Removed internal erroneous use of __USE_FILE_OFFSET64 + o Made libpthread compile on sparc and powerpc + o Made libpthread soname and symlinks match the other libraries. + o Added finite() to the C89 math lib, since some math functions use it. + o Added missing function pointer to error.c (some apps wanted it) + o Fixed initfini build for arches where gcc tries to be sneaky + o Fixed m68k/bits/setjmp.h which I has broken in the last release. + o Fixed a buffer overflow in the dynamic library loader + o Fixed a stdio thread locking bug that could cause random + deadlocks on s*printf calls when threading was enabled. + o Implemented sqrtf(), needed for libstdc++ on arm +Miles Bader: + o Make clean fixes to not blindly wipe all symlinks + o Re-enabled clnt_perror() + o Re-implemented swab() +Dwayne Fontenot: + o Many updates to the uClibc Working Application List +Steven J. Hill: + o Many updates to the mips dynamic loader. Not yet working but + getting very close now. + o Fixed locking bug in getttyent() + o Support libpthread on mips +Richard June: + o Fixed several bugs in utmp code (pututline was only writing the + first sizeof-a-pointer bytes to the utmpfile). + o setutent() was only opening utmp readonly. +m4@brecis.COM: + o Fixed a silly typing problem with the getuid syscall. +Manuel Novoa III: + o Fixed stdio FILE read/write auto-transition bugs. + o Better stdio errno handling + o Changed setvbuf() to more closely match glibc's behavior + o Fixed getpass() to not echo passwords to the console + o Fixed locale ISblank flag. + o Fixed an arg promotion handling bug in _do_one_spec for %c reported + by Ilguiz Latypov. +Kensuke Otake: + o Implemented swab() +Yoshinori Sato: + o Fixed h8300 architecture support for pthreads and changes to + the include files +David Schleef: + o Made powerpc assembly code PIC-compatible + o Removed powerpc R_PPC_REL24 handling, since it was deceptively useless. +John Traill: + o Several types on powerpc, such as dev_t, are different than on other + architectures. John spotted this, which fixed a _ton_ of problems since + anything calling stat() was previously broken. +Jim Treadway: + o Eliminated use of alarm() from the DNS resolver by converting + it to use select instead (much cleaner). + + + + + + + + +0.9.10 21 March 2002 + +Major new features: + o pthreads support (derived from glibc 2.1.3's linuxthreads library) + by Stefan Soucek and Erik Andersen + o pthreads support for MMU-less systems, by Stefan Soucek + o Complete rewrite of all stdio functions for standards compliance, + small size, pthreads support, wide/narrow stream support, large + file support, unbuffered support, etc, etc by Manuel Novoa III + o gcc wrapper reworked by Erik Andersen. Now operated correctly in + all known cases, and now wraps g++ as well for C++ support. + o constructor/destructor support, for C++ by Erik Andersen. + o Eliminated duplicate include/bits header files, by Erik Andersen. + Now all common include/bits headers are grouped together. + + +Erik Andersen: + o Lots of changes and improvements to the shared library loader + o Cleaned up a piles of bugs + o Fixed a segfault when scandir was called on empty directories. + o Several syscalls added: pread/pwrite + o Makefile/build system cleanups + o Sighandling fixes + o pthreads support (with Stefan Soucek) + o Added ldexp to the C89 math library, per POSIX + o fclose() EINTR handling is now correct per IEEE Std 1003.1-2001 + o Support isblank() + o Reworked libcrypt to avoid leaking private symbols into the namespace + o Added strtof(), strtold(), updwtmp(), strptime() + o Fix ldso build for older arm cross compilers +Miles Bader: + o atexit cleanups + o fixed gcc wrapper handling of -M* options + o Fixed truncate64/ftruncate64 to restrict them to 64-bit systems, + since we can't be sure that the _syscall macros can cope with 64 + bit args on 32 bit arches. + o Large File support on the v850 + o Fixed v850 headers after Erik messed them up + o Eliminate include/features.h namespace pollution +M. R. Brown: + o Fixed pthread support for SH, and fixed SH vfork as well + o Fixed SH headers after Erik messed them up +Geoffrey Espin: + o Mips architecture cleanups. Now works perfectly + with busybox, vi, ash, etc... + o Merged in the random number support (rand, srand, etc) from glibc. +Thomas Fritzsche: + o Fixes DNS resolver bug from 0.9.9 +Steven J. Hill: + o Fixed build to support both mips and mipsel + o Beginnings of a mips ldso port +Andrew Ip: + o Support for gnu error() functions +David McCullough: + o Coldfire platform updates: clone, setjmp + o Fixed simple malloc to work on systems with an MMU +Manuel Novoa III: + o Rewrote all stdio functions for standards compliance, small size, + pthreads support, wide/narrow stream support, large file support, + unbuffered support, etc, etc, etc. + o Rewrote the various string to int functions to be smaller, more + standards compilant, and reduce dependance on libgcc.a. +Yoshinori Sato: + o ptrace for the Hitachi h8300 fix +David Schleef: + o Debian packaging updates + o Check for proper 16-byte aliged stack pointer on powerpc +Stefan Soucek: + o pthreads support for MMU-less systems + o pthreads support (with Erik Andersen) +Brian Stafford: + o Rewrote strcasecmp() per SUSv2. +Bart Visscher: + o Added missing IPV6 support and reentrant networking function + additions so iptables now runs with IPV6 support. + + + + + + +0.9.9 February 4, 2002 + +Erik Andersen: + o A bunch of doc updates. Major update to the working + apps list. + o Added a configurator script (extra/Configs/uClibc_config_fix.pl) + which can simplify configuring uClibc. + o Fixed setjmp/longjmp on x86,arm,powerpc,mips,and sparc. + Hitting ^C in ash kills client apps now, not ash. + o Reworked signal handling code so it now passes POSIX + conformance tests. + o Fixed sleep and usleep to work correctly when + interrupted by signals. + o Made getopt behave the same when staticly linking + as when dynamicly linking. It was using different + implementations depending on how apps were linked. + o Added missing inttypes.h header file + o Eliminate all C++ style comments from header files + o Support statvfs and statfs + o Support getmntent_r + o Scandir and scandir64 were calling malloc without + checking for ENOMEM + o Fixed stpcpy function declaration + o Many large file support improvements. + o Fixed fcntl to work when DOLFS is enabled + o Fixed termios code to do the Right Thing(tm) + o Allow regex to be excluded at compile time + o Implemented mempcpy + o Build ldd and readelf for the target system and for the + host system + o Fix several cases where get-needed-libgcc-objects.sh + could fail, breaking the shared uClibc library. + o Include all shared library loader objects into a + single C file, thereby reducing its size further. + o Reworked the shared library linking process to be more + flexible so that gcc and ld can more easily be built to + target uClibc library. + o Better error checking in the Makefiles. Be more pedantic + about tar, chmod, etc to avoid system dependent failures. + o We can now autodetect the target architecture + o Hide references to wchar_t so GNU autoconf + configure scripts won't get confused and try to + enable wide char support. + o Fixed stdio.h so apps can use varargs.h if they want to. + o Added brk/sbrk support for ARM, powerpc, mips, and sparc + and set them to default to the much faster brk using malloc + o Added missing syscalls: get_kernel_syms, fcntl64, + fdatasync, sched_setparam, sched_getparam, + sched_setscheduler, sched_getscheduler, + sched_get_priority_max, sched_get_priority_min, + sched_rr_get_interval, sigaltstack, sendfile, + pivot_root, sigsuspend, setfsuid, and setfsgid + o Force DOPIC be true when HAVE_SHARED is true. + o Fixed hstrerror() + o Implemented gethostent(), sethostent(), and endhostent() + o Added arch specific support so that sparc and mips actually + compile and work +Miles Bader: + o Fixes for the v850 architecture: crt0, setjmp, + arch autodetection, etc. + o Fixed `make install' to not build ldso stuff on + non-shared-library systems. +Michael E Brown: + o Allow the gcc wrapper to support setting DEVEL_PREFIX + and BUILD_DIR at runtime (no more need to recompile). +M. R. Brown and Erik Andersen: + o Fixed the SH port so it now works. Tested and shown + working on an SH4 Dreamcast system. +Kim Heino: + o Made 'make clean' remove generated bits/syscall.h +David McCullough: + o SH architecture updates. Added brk, sbrk, + o Fixed simple malloc to work on systems with an MMU + o Taught getutent to return NULL if utmp doesn't exist. + o Added insque/remque support + o Fixed DNS resolver version number so apps won't get + confused and use the wrong API. + o Added Config selectable shadow password support +Yoshinori Sato + o Contributed support for the Hitach H8/300H architecture +Cédric Schieli: + o Add support for inet_netof, inet_lnaof, inet_makeaddr + and hstrerror. +David Schleef: + o Added libstrip, a nifty script to automagically + strip unneeded content from the uClibc shared + libraries. +Martin Sieper + o Added getw() and putw() + o Added missing header files -- lastlog.h, sgtty.h, + netipx/ipx.h, sys/perm.h +Stefan Soucek: + o Add rcmd support, i.e. rsh, rlogin, etc. + o Fix rcmd to avoid alloca, which is dangerous + on mmu-less systems +spudmonkey@racsa.co.cr: + o Eliminate a buffer overflow in the shared library loader +Brian Stafford: + o Enable support for Unix98 PTYs, and add option + to disable old style PTYs. + + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/DEDICATION.mjn3 b/l4/pkg/uclibc/lib/contrib/uclibc/DEDICATION.mjn3 new file mode 100644 index 00000000..bc26bc84 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/DEDICATION.mjn3 @@ -0,0 +1,22 @@ + +All of my uClibc and busybox work is dedicated to Toni, my love who +passed away on Feb. 12, 2003. + +I would ask that anyone benefiting from this work, especially those +using it in commercial products, consider making a donation in her +memory to our local non-profit hospice organization that did so much +for us in her last few months. + + In memory of Toni W. Hagan + + Hospice of Acadiana, Inc. + 2600 Johnston St., Suite 200 + Lafayette, LA 70503-3240 + + Phone (337) 232-1234 or 1-800-738-2226 + Fax (337) 232-1297 + + http://www.hospiceacadiana.com/ + + +Manuel Novoa III diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/INSTALL b/l4/pkg/uclibc/lib/contrib/uclibc/INSTALL new file mode 100644 index 00000000..79cde848 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/INSTALL @@ -0,0 +1,80 @@ +SOFTWARE REQUIREMENTS + + Compiling uClibc requires Linux kernel header files. uClibc will + be compiled to match the interfaces available in the provided + version of the Linux kernel headers. Linux kernel version 2.0, + version 2.2, version 2.4 and version 2.6 are known to work. Other + kernel versions may work but haven't been tested. Its also helpful + to have a working version of GNU binutils, and GNU gcc -- using + excessively old versions of these packages can cause very strange + errors that are difficult to find and fix. + + +CONFIGURING uClibc: + + - Users must have a valid configuration file to compile uClibc. Do not + skip this step. New configuration options are added in each + release, and odd configuration options are sometimes removed. + To configure uClibc, you can run: + + make menuconfig + or + make config + + If you have an existing .config file, you can update this file + using the + + make oldconfig + + command, which will only ask you about new configuration options. + + Available configuration commands are: + "make config" Text based configuration, no menus or colors. + "make menuconfig" Text based color menus, radiolists & dialogs. + "make oldconfig" Default all questions based on the contents of + your existing ./.config file. + "make defconfig" Use defaults for all options. + "make randconfig" Use random values for all options. + "make allyesconfig" Set all values to "yes" for all options. + "make allnoconfig" Set all values to "no" for all options. + + +COMPILING uClibc: + + - uClibc does not have proper dependancy checking (yet) so if you + change your uClibc configuration, you must current rebuild the + entire library, by first running + + make clean + + - Once you have a valid configuration file, just run + + make + + to compile uClibc. or if you are cross compiling, you would + instead run something like: + + make CROSS=arm-linux- + + +INSTALLING the uClibc development environment: + + - As root, if necessary, run something like: + + make PREFIX= install + + This will install the uClibc runtime and development system (i.e. + all the header files, libraries, etc) into the directories defined + within your .config file. + + +USING uClibc: + + - To compile programs with uClibc you will need a complete toolchain + (i.e. binutils, gcc, and uClibc) that was built expressly for use + with uClibc. + + - Native and cross compiling toolchains, as well as makefiles for creating + uClibc toolchains, are available from the uClibc website. You may want + to check out "buildroot", which is available from the uClibc download area, + which provides examples of how to build your own uClibc based system. diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/MAINTAINERS b/l4/pkg/uclibc/lib/contrib/uclibc/MAINTAINERS new file mode 100644 index 00000000..d7c0ff96 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/MAINTAINERS @@ -0,0 +1,152 @@ +Arch Maintainers List + +Note: For the hard of thinking, this list is meant to remain in alphabetical +order. If you could add yourselves to it in alphabetical order that would be +so much easier [Ed]. + +P: Person +E: Person's email address +W: Web-page with status/info +S: Status, one of the following: + + Supported: Someone is actually paid to look after this. + Maintained: Someone actually looks after it. + Patches: It has a maintainer but they don't have time to do + much other than throw the odd patch in. See below ... + Unmaintained: No current maintainer [but maybe you could take the + role as you write your new code]. + Obsolete: Old code. Something tagged obsolete generally means + it has been replaced by a better system and you + should be using that. + +---------------------------------------------------------------------- + +ALPHA +S: Unmaintained + + +ARM +N: Erik Andersen +E: andersen@codepoet.org +W: http://www.arm.linux.org.uk/ +S: Maintained + + +AVR32 +N: Hans-Christian Egtvedt +E: hans-christian.egtvedt@atmel.com +N: Haavard Skinnemoen +E: haavard.skinnemoen@atmel.com +W: http://avr32linux.org/ +S: Maintained + + +BFIN +N: Mike Frysinger +E: vapier.adi@gmail.com +W: http://blackfin.uclinux.org/ +S: Maintained + + +CRIS +P: Ricard Wanderlof +M: ricard.wanderlof@axis.com +W: http://developer.axis.com +S: Maintained + + +E1 +S: Unmaintained + + +FRV +S: Unmaintained + + +H8300 +S: Unmaintained + + +HPPA +S: Unmaintained + + +IA64 +S: Unmaintained + + +I386 +N: Erik Andersen +E: andersen@codepoet.org +S: Maintained + + +I960 +S: Unmaintained + + +M68K +S: Unmaintained + + +MICROBLAZE +S: Unmaintained + + +MIPS +N: Erik Andersen +E: andersen@codepoet.org +W: http://www.linux-mips.org +S: Maintained + + +NIOS and NIOS2 +S: Unmaintained + + +POWERPC +N: Joakim Tjernlund +E: joakim.tjernlund@lumentis.se +W: http://penguinppc.org/ +S: Maintained + + +SH and SH64 +P: Paul Mundt +E: lethal@linux-sh.org +W: http://www.linux-sh.org +S: Maintained + + +SH4 (NPTL/TLS) +P: Carmelo Amoroso +E: carmelo.amoroso@st.com +W: http://www.stlinux.com +S: Supported + + +SPARC +P: Austin Foxley +E: austinf@cetoncorp.com +S: Maintained + +VAX +P: Jan-Benedict Glaw +E: jbglaw@lug-owl.de (personal), linux-vax@pergamentum.com (mailing list) +W: http://linux-vax.sourceforge.net/ +S: Maintained + +V850 +S: Unmaintained + + +X86_64 +S: Unmaintained + + +XTENSA +P: Chris Zankel +E: chris@zankel.net +W: http://linux-xtensa.org/ +S: Maintained + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/Makefile new file mode 100644 index 00000000..702430a6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/Makefile @@ -0,0 +1,19 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=./ +top_builddir=$(if $(O),$(O),.)/ +export top_builddir + +# We do not need built-in implicit rules +MAKEFLAGS += -r +CONFIG_SHELL ?= /bin/sh +export CONFIG_SHELL + +include $(top_srcdir)Makefile.in +include $(top_srcdir)Makerules +include $(top_srcdir)Makefile.help diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/Makefile.help b/l4/pkg/uclibc/lib/contrib/uclibc/Makefile.help new file mode 100644 index 00000000..1c2c96e0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/Makefile.help @@ -0,0 +1,63 @@ +# Makefile.help for uClibc +# +# Copyright (C) 2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +help: + @echo 'Cleaning:' + @echo ' clean - delete temporary object files' + @echo ' realclean - delete temporary object files, including dependencies' + @echo ' distclean - delete all non-source files (including .config)' + @echo + @echo 'Build:' + @echo ' all - libraries and generated headers' + @echo ' pregen - generate headers' + @echo ' startfiles - build startfiles (crt)' + @echo ' utils - build target utilities' + @echo ' (ldd, ldconfig, locale, iconv)' + @echo ' hostutils - build host utilities (see utils)' + @echo + @echo 'Configuration:' + @echo ' allnoconfig - disable all symbols in .config' + @echo ' allyesconfig - enable all symbols in .config (see defconfig)' + @echo ' config - text based configurator (of last resort)' + @echo ' defconfig - set .config to arch-specific defaults' + @echo ' menuconfig - interactive curses-based configurator' + @echo ' oldconfig - resolve any unresolved symbols in .config' + @echo ' silentoldconfig - resolve any unresolved symbols in .config, silently' + @echo ' randconfig - generate a random .config' + @echo + @echo 'Installation:' + @echo ' install - install both the runtime and the headers' + @echo ' install_runtime - install the libraries' + @echo ' install_dev - install all headers and static libs' + @echo ' install_startfiles - install startfiles (crt)' + @echo ' install_headers - install headers excluding generated ones' + @echo ' install_utils - install target utilities' + @echo ' install_hostutils - install host utilities' + @echo + @echo 'Development:' + @echo ' check - run testsuite' + @echo ' test_compile - compile testsuite binaries' + @echo ' release - create a distribution tarball' + @echo + @echo 'Environment variables:' + @echo ' O= - Use as object directory' + @echo ' V="" - Quiet build (default)' + @echo ' V=1 - Brief build (show defines, ld flags)' + @echo ' V=2 - Very verbose build' + @echo ' CROSS= - Override CROSS_COMPILER_PREFIX from .config' + @echo ' ARCH= - Use given arch for config targets' + @echo ' SHELL= - Shell to use for make' + @echo ' CONFIG_SHELL= - Shell to use for menuconfig' + @echo + @echo ' PREFIX= - Prepended prefix' + @echo ' RUNTIME_PREFIX= - Prefix for the libdir containing shared objects' + @echo ' (usually "/")' + @echo ' DEVEL_PREFIX= - Prefix for the libdir containing static objects' + @echo ' and the include dir (usually "/usr")' + @echo ' MULTILIB_DIR= - Directory component for libraries (default "lib").' + @echo ' UCLIBC_EXTRA_CFLAGS - extra CFLAGS for compiling uClibc' + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/Makefile.in new file mode 100644 index 00000000..d7a5fca6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/Makefile.in @@ -0,0 +1,489 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +#-------------------------------------------------------------- +# You shouldn't need to mess with anything beyond this point... +#-------------------------------------------------------------- +clean_targets := clean realclean distclean \ + objclean-y headers_clean-y CLEAN_utils +noconfig_targets := menuconfig config oldconfig silentoldconfig randconfig \ + defconfig allyesconfig allnoconfig \ + release dist tags help + +include $(top_srcdir)Rules.mak +sub_headers := headers +ifndef KCONFIG_CONFIG +KCONFIG_CONFIG := $(top_builddir).config +endif +export KCONFIG_CONFIG + +ifeq ($(HAVE_DOT_CONFIG),y) + +all: headers pregen libs +libs: pregen + +# In this section, we need .config +-include $(top_builddir).config.cmd + +else # ifeq ($(HAVE_DOT_CONFIG),y) + +all: menuconfig + +headers: + @echo "Need to make a config file first, run: make menuconfig" + @false + +endif # ifeq ($(HAVE_DOT_CONFIG),y) + +include $(top_srcdir)ldso/Makefile.in +include $(top_srcdir)libcrypt/Makefile.in +include $(top_srcdir)libintl/Makefile.in +include $(top_srcdir)libm/Makefile.in +include $(top_srcdir)libnsl/Makefile.in +include $(top_srcdir)libresolv/Makefile.in +include $(top_srcdir)libutil/Makefile.in +include $(top_srcdir)libpthread/Makefile.in +include $(top_srcdir)librt/Makefile.in +include $(top_srcdir)libubacktrace/Makefile.in +include $(top_srcdir)extra/locale/Makefile.in + +# last included to catch all the objects added by others (locales/threads) +include $(top_srcdir)libc/Makefile.in + +ifeq ($(HAVE_DOT_CONFIG),y) +# If the .config changes then we have to make sure that our includes are +# updated properly. This would normally work by saying that the headers +# have uClibc_config.h as prerequisite but since we _symlink_ the headers +# and do not (?) want to rely on 'make -L' we better update them right here, +# on spot to save us from alot of hazzle. +$(top_builddir)include/bits/uClibc_config.h: $(top_builddir)extra/config/conf $(KCONFIG_CONFIG) $(top_srcdir)extra/scripts/conf-header.sh | $(top_builddir)include/bits $(top_builddir)include/config + @$(disp_gen) + $(Q)@$< -s $(top_srcdir)extra/Configs/Config.in + $(Q)$(top_srcdir)extra/scripts/conf-header.sh $(KCONFIG_CONFIG) > $@ + $(Q)$(MAKE) headers-y + +# The above doesn't work for threads, though. Just using check-symlinks for now. +# XXX: FIXME: this is ugly +MAKEFLAGS += -L + +$(top_builddir)include/config/linuxthreads/old.h $(top_builddir)include/config/linuxthreads/new.h: + @true + +# For the moment, we have to keep re-running this target +# because the fix includes scripts rely on pre-processers +# in order to generate the headers correctly :(. That +# means we can't use the $(HOSTCC) in order to get the +# correct output. +ifeq ($(ARCH_USE_MMU),y) +export header_extra_args = +else +export header_extra_args = -n +endif +HEADERS_BITS_COMMON := $(notdir $(wildcard $(top_srcdir)libc/sysdeps/linux/common/bits/*.h)) +HEADERS_BITS_ARCH := $(notdir $(wildcard $(top_srcdir)libc/sysdeps/linux/$(TARGET_ARCH)/bits/*.h)) +HEADERS_BITS_SUBARCH := +ifneq ($(TARGET_SUBARCH),) +HEADERS_BITS_SUBARCH := $(notdir $(wildcard $(top_srcdir)libc/sysdeps/linux/$(TARGET_ARCH)/bits/$(TARGET_SUBARCH)/*.h)) +endif +HEADERS_BITS_COMMON := $(filter-out $(HEADERS_BITS_ARCH) $(HEADERS_BITS_SUBARCH) $(HEADERS_BITS_PTHREAD),$(HEADERS_BITS_COMMON)) + +HEADERS_SYS_COMMON := $(notdir $(wildcard $(top_srcdir)libc/sysdeps/linux/common/sys/*.h)) +HEADERS_SYS_ARCH := $(notdir $(wildcard $(top_srcdir)libc/sysdeps/linux/$(TARGET_ARCH)/sys/*.h)) +HEADERS_SYS_COMMON := $(filter-out $(HEADERS_SYS_ARCH),$(HEADERS_SYS_COMMON)) + +ALL_HEADERS_COMMON := $(top_builddir)include/fpu_control.h \ + $(top_builddir)include/dl-osinfo.h \ + $(top_builddir)include/hp-timing.h +ALL_HEADERS_BITS_COMMON := $(addprefix $(top_builddir)include/bits/,$(HEADERS_BITS_COMMON)) +ALL_HEADERS_BITS_ARCH := $(addprefix $(top_builddir)include/bits/,$(HEADERS_BITS_ARCH)) +ifneq ($(TARGET_SUBARCH),) +ALL_HEADERS_BITS_SUBARCH := $(addprefix $(top_builddir)include/bits/,$(HEADERS_BITS_SUBARCH)) +else +ALL_HEADERS_BITS_SUBARCH := +endif +ALL_HEADERS_SYS_COMMON := $(addprefix $(top_builddir)include/sys/,$(HEADERS_SYS_COMMON)) +ALL_HEADERS_SYS_ARCH := $(addprefix $(top_builddir)include/sys/,$(HEADERS_SYS_ARCH)) + +target-headers-sysdep := \ + $(ALL_HEADERS_COMMON) \ + $(ALL_HEADERS_BITS_COMMON) \ + $(ALL_HEADERS_BITS_ARCH) \ + $(ALL_HEADERS_BITS_SUBARCH) \ + $(ALL_HEADERS_SYS_COMMON) \ + $(ALL_HEADERS_SYS_ARCH) \ + $(ALL_HEADERS_BITS_PTHREAD) + +$(top_builddir)include/fpu_control.h: + @$(disp_ln) + $(Q)[ -r $(top_srcdir)libc/sysdeps/linux/$(TARGET_ARCH)/$(@F) ] && \ + $(LN) -fs $(call rel_srcdir)libc/sysdeps/linux/$(TARGET_ARCH)/$(@F) $@ || \ + $(LN) -fs $(call rel_srcdir)libc/sysdeps/linux/common/$(@F) $@ + +$(top_builddir)include/dl-osinfo.h $(top_builddir)include/hp-timing.h: + $(do_ln) $(call rel_srcdir)libc/sysdeps/linux/common/$(@F) $@ + +$(ALL_HEADERS_BITS_COMMON): + $(do_ln) $(call rel_srcdir)libc/sysdeps/linux/common/bits/$(@F) $@ + +$(ALL_HEADERS_BITS_ARCH): + $(do_ln) $(call rel_srcdir)libc/sysdeps/linux/$(TARGET_ARCH)/bits/$(@F) $@ + +ifneq ($(TARGET_SUBARCH),) +$(ALL_HEADERS_BITS_SUBARCH): + $(do_ln) $(call rel_srcdir)libc/sysdeps/linux/$(TARGET_ARCH)/bits/$(TARGET_SUBARCH)/$(@F) $@ +endif + +ifneq ($(strip $(ALL_HEADERS_SYS_COMMON)),) +$(ALL_HEADERS_SYS_COMMON): + $(do_ln) $(call rel_srcdir)libc/sysdeps/linux/common/sys/$(@F) $@ +endif + +ifneq ($(strip $(ALL_HEADERS_SYS_ARCH)),) +$(ALL_HEADERS_SYS_ARCH): + $(do_ln) $(call rel_srcdir)libc/sysdeps/linux/$(TARGET_ARCH)/sys/$(@F) $@ +endif + +$(target-headers-sysdep) $(pregen-headers-y): | $(top_builddir)include/bits $(top_builddir)include/sys + +HEADERCLEAN_common: + $(do_rm) $(ALL_HEADERS_COMMON) +headers_clean-y += HEADERCLEAN_common + +# The headers. Arch specific headers are specified via ARCH_HEADERS in +# libc/sysdeps/linux/$(TARGET_ARCH)/Makefile.arch which appends those via +# libc/sysdeps/linux/Makefile.commonarch to headers-y +headers-y += $(target-headers-sysdep) + +headers: $(top_builddir)include/bits/uClibc_config.h $(top_builddir)include/bits/sysnum.h | subdirs +subdirs: $(addprefix $(top_builddir),$(subdirs)) +pregen-headers: $(pregen-headers-y) +pregen: pregen-headers + $(Q)$(if $(UCLIBC_HAS_LOCALE),$(MAKE) -C extra/locale locale_headers) +$(top_builddir)include/bits/sysnum.h: $(top_srcdir)extra/scripts/gen_bits_syscall_h.sh | $(top_builddir)include/bits + @$(disp_gen) + $(Q)set -e; \ + tmp=`mktemp $(top_builddir)include/bits/sysnum.h.XXXXXX 2>/dev/null || true`; \ + [ -z "$$tmp" ] && tmp='$(top_builddir)include/bits/sysnum.h.new'; \ + KERNEL_HEADERS="${KERNEL_HEADERS}" top_builddir="$(top_builddir)" CC="$(CC) $(CPU_CFLAGS)" $(SHELL) $< > $$tmp; \ + if cmp $(top_builddir)include/bits/sysnum.h $$tmp >/dev/null 2>&1; then \ + $(RM) $$tmp; \ + else \ + mv -f $$tmp $(top_builddir)include/bits/sysnum.h; \ + fi + @# Ugly linux specific hack.. + $(Q)if grep -q __NR_ $@; then true; else \ + rm -f $@; \ + echo "ERROR: Could not generate syscalls."; \ + echo "Make sure that you have proper kernel headers."; \ + echo "Your .config in KERNEL_HEADERS=\"\" was set to:"; \ + echo "${KERNEL_HEADERS}"; \ + exit 1; \ + fi + +$(LOCAL_INSTALL_PATH): + $(Q)$(MAKE) PREFIX=$(shell pwd)/$(LOCAL_INSTALL_PATH) RUNTIME_PREFIX=/ \ + DEVEL_PREFIX=/usr/ \ + HOSTCC="$(HOSTCC)" \ + install + +install: install_runtime install_dev + + +RUNTIME_PREFIX_LIB_FROM_DEVEL_PREFIX_LIB=$(shell $(top_srcdir)extra/scripts/relative_path.sh $(DEVEL_PREFIX)$(MULTILIB_DIR) $(RUNTIME_PREFIX)$(MULTILIB_DIR)) + +startfiles: $(crt-y) + +$(top_builddir)extra/scripts/unifdef: |$(top_builddir)extra/scripts +$(top_builddir)extra/scripts/unifdef: $(top_srcdir)extra/scripts/unifdef.c + $(hcompile.u) + +# Installs header files. +# a "y" here means the feature is enabled and so we should *not* rm it. +# if the option expands to nothing though, we can punt the headers. +HEADERS_RM- := \ + internal \ + dl-osinfo.h \ + _lfs_64.h \ + bits/uClibc_arch_features.h \ + bits/kernel_sigaction.h \ + bits/kernel_stat.h \ + bits/kernel_types.h \ + bits/syscalls.h \ + bits/syscalls-common.h \ + bits/uClibc_errno.h \ + bits/uClibc_uintmaxtostr.h \ + bits/sigcontextinfo.h \ + bits/stackinfo.h \ + tls.h \ + rpc/des_crypt.h \ + rpc/key_prot.h \ + rpc/rpc_des.h +HEADERS_RM-$(HAVE_SHARED) += dlfcn.h bits/dlfcn.h +HEADERS_RM-$(PTHREADS_DEBUG_SUPPORT) += thread_db.h +HEADERS_RM-$(UCLIBC_HAS_BSD_ERR) += err.h +HEADERS_RM-$(UCLIBC_HAS_CRYPT) += crypt.h +HEADERS_RM-$(UCLIBC_HAS_EPOLL) += sys/epoll.h +HEADERS_RM-$(UCLIBC_HAS_FENV) += fenv.h bits/fenv.h bits/fenvinline.h +HEADERS_RM-$(UCLIBC_HAS_FLOATS) += complex.h fpu_control.h ieee754.h \ + math.h \ + tgmath.h \ + bits/uClibc_fpmax.h \ + bits/math*.h +HEADERS_RM-$(findstring y,$(UCLIBC_HAS_FTW)$(UCLIBC_HAS_NFTW)) += ftw.h +HEADERS_RM-$(UCLIBC_HAS_GETTEXT_AWARENESS) += libintl.h +HEADERS_RM-$(UCLIBC_HAS_GLIBC_CUSTOM_PRINTF) += printf.h +HEADERS_RM-$(UCLIBC_HAS_GLOB) += glob.h +HEADERS_RM-$(UCLIBC_HAS_GNU_ERROR) += error.h +HEADERS_RM-$(UCLIBC_HAS_GNU_GETOPT)$(UCLIBC_HAS_GETOPT_LONG) += getopt.h +HEADERS_RM-$(UCLIBC_HAS_IPV6) += netinet/ip6.h netinet/icmp6.h +HEADERS_RM-$(UCLIBC_HAS_BACKTRACE) += execinfo.h +HEADERS_RM-$(UCLIBC_HAS_LOCALE) += iconv.h +HEADERS_RM-$(UCLIBC_HAS_PTY) += pty.h +HEADERS_RM-$(UCLIBC_HAS_REALTIME) += mqueue.h bits/mqueue.h sched.h \ + bits/sched.h \ + semaphore.h +HEADERS_RM-$(UCLIBC_HAS_REGEX) += regex.h regexp.h +HEADERS_RM-$(UCLIBC_HAS_RPC) += rpc +HEADERS_RM-$(UCLIBC_HAS_SHADOW) += shadow.h +HEADERS_RM-$(UCLIBC_HAS_SOCKET) += sys/socket.h bits/socket.h sys/socketvar.h +HEADERS_RM-$(UCLIBC_HAS_SYSLOG) += syslog.h sys/syslog.h bits/syslog*.h +HEADERS_RM-$(UCLIBC_HAS_THREADS) += *thread*.h semaphore.h \ + bits/*thread*.h \ + bits/initspin.h +HEADERS_RM-$(UCLIBC_HAS_THREADS_NATIVE) += atomic.h bits/atomic.h +HEADERS_RM-$(UCLIBC_HAS_UTMPX) += bits/utmpx.h utmpx.h +HEADERS_RM-$(UCLIBC_HAS_WCHAR) += wchar.h wctype.h +HEADERS_RM-$(UCLIBC_HAS_WORDEXP) += wordexp.h +HEADERS_RM-$(UCLIBC_HAS_XATTR) += sys/xattr.h +HEADERS_RM-$(UCLIBC_HAS_XLOCALE) += xlocale.h +HEADERS_RM-$(UCLIBC_HAS_LOCALE) += bits/uClibc_ctype.h +HEADERS_RM-$(UCLIBC_LINUX_SPECIFIC) += sys/fsuid.h sys/inotify.h sys/perm.h \ + sys/personality.h \ + sys/prctl.h \ + sys/reboot.h \ + sys/sendfile.h \ + sys/signalfd.h \ + bits/statfs.h \ + sys/statfs.h \ + sys/swap.h \ + sys/sysctl.h \ + sys/sysinfo.h \ + sys/vfs.h +HEADERS_RM-$(UCLIBC_SUPPORT_AI_ADDRCONFIG) += ifaddrs.h +HEADERS_RM-$(UCLIBC_SV4_DEPRECATED) += ustat.h sys/ustat.h bits/ustat.h +HEADERS_RM-$(UCLIBC_SUSV3_LEGACY) += sys/timeb.h regexp.h +HEADERS_RM-$(UCLIBC_SUSV4_LEGACY) += utime.h + # BREAKAGE: include/signal.h uses it, this rm broke bbox compile: + ### ucontext.h + +ifneq ($(findstring install,$(MAKECMDGOALS)),) +$(addprefix $(PREFIX)$(DEVEL_PREFIX),include $(MULTILIB_DIR)): + $(do_mkdir) +# avoid warning about duplicate targets in rule or overrides +ifneq ($(abspath $(RUNTIME_PREFIX)$(MULTILIB_DIR)),$(abspath $(DEVEL_PREFIX)$(MULTILIB_DIR))) +$(PREFIX)$(RUNTIME_PREFIX)$(MULTILIB_DIR): + $(do_mkdir) +endif +endif +install_headers: headers $(top_builddir)extra/scripts/unifdef | $(PREFIX)$(DEVEL_PREFIX)include + @$(call disp_install,"include -> $(PREFIX)$(DEVEL_PREFIX)include") + $(Q)top_builddir=$(top_builddir) \ + $(top_srcdir)extra/scripts/install_headers.sh \ + include $(PREFIX)$(DEVEL_PREFIX)include +ifneq ($(O),) # only run this step in O is set i.e. make O=/my/builddir/ .. + @$(call disp_install,"$(top_builddir)/include -> $(PREFIX)$(DEVEL_PREFIX)include") + $(Q)top_builddir=$(top_builddir) \ + $(top_srcdir)extra/scripts/install_headers.sh \ + $(top_builddir)/include $(PREFIX)$(DEVEL_PREFIX)include +endif + $(Q)cd $(PREFIX)$(DEVEL_PREFIX)include && $(RM) -r $(HEADERS_RM-) +ifeq ($(UCLIBC_HAS_WCHAR),) + $(Q)cd $(PREFIX)$(DEVEL_PREFIX)include && mv -f wchar-stub.h wchar.h +else + $(Q)cd $(PREFIX)$(DEVEL_PREFIX)include && $(RM) -f wchar-stub.h +endif + +# Installs startfiles +install_startfiles: startfiles | $(PREFIX)$(DEVEL_PREFIX)$(MULTILIB_DIR) + -$(INSTALL) -m 644 $(startfiles) $(PREFIX)$(DEVEL_PREFIX)$(MULTILIB_DIR)/ + +# Installs development library links. +install_dev: install_headers install_runtime install_startfiles | $(PREFIX)$(DEVEL_PREFIX)$(MULTILIB_DIR) + -$(INSTALL) -m 644 $(top_builddir)lib/*.a $(PREFIX)$(DEVEL_PREFIX)$(MULTILIB_DIR)/ +ifeq ($(HAVE_SHARED),y) + for i in `cd $(top_builddir) && find lib/ -type l -name 'lib[a-zA-Z]*.so' | \ + $(SED) -e 's/lib\///'` ; do \ + $(LN) -sf $(RUNTIME_PREFIX_LIB_FROM_DEVEL_PREFIX_LIB)$$i.$(ABI_VERSION) \ + $(PREFIX)$(DEVEL_PREFIX)$(MULTILIB_DIR)/$$i; \ + done +ifeq ($(HARDWIRED_ABSPATH),y) + if [ -f $(top_builddir)lib/libc.so -a -f $(PREFIX)$(RUNTIME_PREFIX)$(MULTILIB_DIR)/$(SHARED_LIBNAME) ] ; then \ + $(RM) $(PREFIX)$(DEVEL_PREFIX)$(MULTILIB_DIR)/libc.so; \ + $(SED) -e 's:$(NONSHARED_LIBNAME):$(DEVEL_PREFIX)$(MULTILIB_DIR)/$(NONSHARED_LIBNAME):' \ + -e 's:$(SHARED_LIBNAME):$(RUNTIME_PREFIX)$(MULTILIB_DIR)/$(SHARED_LIBNAME):' \ + -e 's:$(UCLIBC_LDSO):$(RUNTIME_PREFIX)$(MULTILIB_DIR)/$(UCLIBC_LDSO):' \ + $(top_builddir)lib/libc.so > $(PREFIX)$(DEVEL_PREFIX)$(MULTILIB_DIR)/libc.so; \ + fi +else + -$(INSTALL) -m 755 $(top_builddir)lib/libc.so $(PREFIX)$(DEVEL_PREFIX)$(MULTILIB_DIR)/ +endif +ifeq ($(UCLIBC_HAS_BACKTRACE),y) +# Add the AS_NEEDED entry for libubacktrace.so + if [ -f $(top_builddir)lib/libc.so -a -f $(PREFIX)$(RUNTIME_PREFIX)lib/$(SHARED_MAJORNAME) ] ; then \ + echo "GROUP ( $(UBACKTRACE_ASNEEDED) )" >> $(PREFIX)$(DEVEL_PREFIX)lib/libc.so; \ + fi +endif +ifeq ($(UCLIBC_HAS_THREADS),y) +ifneq ($(LINUXTHREADS_OLD),y) +ifeq ($(HARDWIRED_ABSPATH),y) + if [ -f $(top_builddir)lib/libpthread.so -a -f $(PREFIX)$(RUNTIME_PREFIX)$(MULTILIB_DIR)/libpthread.so.$(ABI_VERSION) ] ; then \ + $(RM) $(PREFIX)$(DEVEL_PREFIX)$(MULTILIB_DIR)/libpthread.so; \ + cp $(top_srcdir)extra/scripts/format.lds $(PREFIX)$(DEVEL_PREFIX)$(MULTILIB_DIR)/libpthread.so; \ + echo "GROUP ( $(RUNTIME_PREFIX)$(MULTILIB_DIR)/libpthread.so.$(ABI_VERSION) $(DEVEL_PREFIX)$(MULTILIB_DIR)/libpthread_nonshared.a )" \ + >> $(PREFIX)$(DEVEL_PREFIX)$(MULTILIB_DIR)/libpthread.so; \ + fi +else + -$(INSTALL) -m 755 $(top_builddir)lib/libpthread.so $(PREFIX)$(DEVEL_PREFIX)$(MULTILIB_DIR)/ +endif +endif +endif +ifeq ($(PTHREADS_DEBUG_SUPPORT),y) + $(LN) -sf $(RUNTIME_PREFIX_LIB_FROM_DEVEL_PREFIX_LIB)libthread_db.so.1 \ + $(PREFIX)$(DEVEL_PREFIX)$(MULTILIB_DIR)/libthread_db.so +endif +ifeq ($(DOPIC),y) +# # If we build shared libraries then the static libs are PIC... +# # Make _pic.a symlinks to make mklibs.py and similar tools happy. + if [ -d $(top_builddir)lib ] ; then \ + for i in `cd $(top_builddir) && find lib/ -type f -name 'lib*.a' | $(SED) -e 's/lib\///'` ; do \ + $(LN) -sf $$i $(PREFIX)$(DEVEL_PREFIX)$(MULTILIB_DIR)/`echo $$i \ + | $(SED) -e 's/\.a$$/_pic.a/'`; \ + done ; \ + fi +endif +endif +ifeq ($(UCLIBC_FORMAT_SHARED_FLAT),y) + for file in $(top_builddir)lib/lib*.gdb; do \ + if test -f $$file; then \ + $(INSTALL) -m 755 $$file $(PREFIX)$(DEVEL_PREFIX)$(MULTILIB_DIR); \ + $(INSTALL) -m 755 `echo $$file | $(SED) 's/\.gdb$$//'` \ + $(PREFIX)$(DEVEL_PREFIX)$(MULTILIB_DIR); \ + fi; \ + done +endif + +# Installs run-time libraries +install_runtime: all | $(PREFIX)$(RUNTIME_PREFIX)$(MULTILIB_DIR) +ifeq ($(HAVE_SHARED),y) + $(INSTALL) -m 755 $(top_builddir)lib/lib*-$(VERSION).so \ + $(PREFIX)$(RUNTIME_PREFIX)$(MULTILIB_DIR) + (cd $(top_builddir)lib && $(TAR) -cf - *.so.*) | $(TAR) -xf - -C $(PREFIX)$(RUNTIME_PREFIX)$(MULTILIB_DIR) + @if [ -x $(top_builddir)lib/$(UCLIBC_LDSO_NAME)-$(VERSION).so ] ; then \ + set -e; \ + $(SHELL_SET_X); \ + $(INSTALL) -m 755 $(top_builddir)lib/$(UCLIBC_LDSO_NAME)-$(VERSION).so \ + $(PREFIX)$(RUNTIME_PREFIX)$(MULTILIB_DIR); \ + fi +endif + +utils: | pregen + $(Q)$(MAKE) CROSS="$(CROSS)" CC="$(CC)" -C utils $@ + +# Installs helper applications, such as 'ldd' and 'ldconfig' +install_utils: utils + $(Q)$(MAKE) CROSS="$(CROSS)" CC="$(CC)" -C utils utils_install + +endif # ifeq ($(HAVE_DOT_CONFIG),y) + +hostutils: | pregen + $(Q)$(MAKE) CROSS="$(CROSS)" CC="$(CC)" HOSTCC="$(HOSTCC)" DOTHOST=.host -C utils $@ + +install_hostutils: hostutils + $(Q)$(MAKE) CROSS="$(CROSS)" CC="$(CC)" HOSTCC="$(HOSTCC)" DOTHOST=.host -C utils utils_install + +$(addprefix $(top_builddir),include include/bits include/sys include/config lib extra/config/lxdialog extra/locale extra/scripts $(subdirs)): + $(do_mkdir) + +# configuration +# --------------------------------------------------------------------------- +$(top_builddir)extra/config/conf $(top_builddir)extra/config/mconf: | $(top_builddir)include/config $(top_builddir)extra/config/lxdialog + $(Q)$(MAKE) -C extra/config $(@F) + +menuconfig: $(top_builddir)extra/config/mconf + $(Q)$(top_builddir)extra/config/mconf extra/Configs/Config.in + +config: $(top_builddir)extra/config/conf + $(Q)$(top_builddir)extra/config/conf extra/Configs/Config.in + +oldconfig: $(top_builddir)extra/config/conf + $(Q)$(top_builddir)extra/config/conf -o extra/Configs/Config.in + +silentoldconfig: $(top_builddir)extra/config/conf + $(Q)$(top_builddir)extra/config/conf -s extra/Configs/Config.in + +randconfig: $(top_builddir)extra/config/conf + $(Q)$(top_builddir)extra/config/conf -r extra/Configs/Config.in + +allyesconfig: $(top_builddir)extra/config/conf + $(Q)$(top_builddir)extra/config/conf -y extra/Configs/Config.in + $(SED) -i -e "s/^DODEBUG=.*/# DODEBUG is not set/" \ + -e "s/^DOASSERTS=.*/# DOASSERTS is not set/" \ + -e "s/^SUPPORT_LD_DEBUG_EARLY=.*/# SUPPORT_LD_DEBUG_EARLY is not set/" \ + -e "s/^SUPPORT_LD_DEBUG=.*/# SUPPORT_LD_DEBUG is not set/" \ + -e "s/^UCLIBC_MJN3_ONLY=.*/# UCLIBC_MJN3_ONLY is not set/" \ + $(KCONFIG_CONFIG) + $(Q)$(top_builddir)extra/config/conf -o extra/Configs/Config.in + +allnoconfig: $(top_builddir)extra/config/conf + $(Q)$(top_builddir)extra/config/conf -n extra/Configs/Config.in + +defconfig: $(top_builddir)extra/config/conf + $(Q)$(top_builddir)extra/config/conf -d extra/Configs/Config.in \ + -D extra/Configs/defconfigs/$(ARCH) + +menuconfig-clean-y: + $(Q)$(MAKE) -C extra/config CLEAN_extra/config + +include_clean: + $(Q)$(RM) $(top_builddir)include/fpu_control.h $(top_builddir)include/dl-osinfo.h $(top_builddir)include/hp-timing.h + @set -e; \ + for i in `(cd libc/sysdeps/linux/common/sys; ls *.h)` ; do \ + $(RM) $(top_builddir)include/sys/$$i; \ + done; \ + if [ -d libc/sysdeps/linux/$(TARGET_ARCH)/sys ] ; then \ + for i in `(cd libc/sysdeps/linux/$(TARGET_ARCH)/sys; ls *.h)` ; do \ + $(RM) $(top_builddir)include/sys/$$i; \ + done; \ + fi + +clean: include_clean + $(Q)$(RM) -r $(top_builddir)lib $(top_builddir)include/bits + @$(MAKE) -C utils CLEAN_utils + +$(MAKE) -s -C test clean + @$(RM) $(top_builddir)include/linux $(top_builddir)include/asm* + $(Q)$(RM) $(top_builddir)extra/scripts/unifdef + $(Q)$(RM) -r $(LOCAL_INSTALL_PATH) + +distclean: clean + -find . \( -name core -o -name \*.orig -o -name \*~ -o -name .\*.dep \) -exec $(RM) {} \; + $(RM) $(top_builddir).config $(top_builddir).config.old $(top_builddir).config.cmd + $(RM) $(top_builddir)extra/locale/*.tgz + $(MAKE) -C extra/config distclean + +dist release: + $(RM) ../uClibc-$(VERSION).tar + git archive HEAD --format=tar --prefix=uClibc-$(VERSION)/ \ + > ../uClibc-$(VERSION).tar + cat ../uClibc-$(VERSION).tar | bzip2 -c9 > ../uClibc-$(VERSION).tar.bz2 + cat ../uClibc-$(VERSION).tar | xz -e -c8 > ../uClibc-$(VERSION).tar.xz + du -b ../uClibc-$(VERSION).tar.{bz2,xz} + +test check: test_compile + $(Q)$(MAKE) -C test + +test_compile: $(LOCAL_INSTALL_PATH) + $(Q)$(MAKE) -C test compile diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/Makerules b/l4/pkg/uclibc/lib/contrib/uclibc/Makerules new file mode 100644 index 00000000..84eeaea1 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/Makerules @@ -0,0 +1,487 @@ +# +# Licensed under LGPL v2.1, see the file COPYING.LIB in this tarball for details. +# + +.SUFFIXES: .c .S .o .os .oS .so .a .s .i + +PHONY := FORCE + +.PHONY: dummy $(PHONY) subdirs \ + all check test $(clean_targets) \ + config dist menuconfig oldconfig release \ + utils help + +# order is important, the stripping uses STRIP_FLAGS for lib-so, but not for lib-a +ifeq ($(HAVE_SHARED),y) +.LIBPATTERNS: "lib%.so" +libs: $(lib-so-y) $(lib-a-y) +$(lib-so-y): | $(interp) +else +.LIBPATTERNS: "lib%.a" +ifeq ($(UCLIBC_FORMAT_SHARED_FLAT),y) +libs: $(lib-gdb-y) +endif +libs: $(lib-a-y) +$(lib-a-y): | $(top_builddir)lib +endif +objs: all_objs + +shared_objs = $(libc-y:.o=.os) $(libc-shared-y) $(libc-nonshared-y) \ + $(libcrypt-so-y) $(libdl-so-y) \ + $(libintl-so-y) $(libm-so-y) $(libnsl-so-y) \ + $(libpthread-so-y) $(libpthread-nonshared-y) $(libthread_db-so-y) \ + $(libresolv-so-y) $(librt-so-y) \ + $(ldso-y) \ + $(libutil-so-y) $(libubacktrace-so-y) + +ar_objs = $(libc-y) $(libc-static-y) $(libcrypt-a-y) \ + $(libdl-a-y) $(libintl-a-y) $(libm-a-y) $(libnsl-a-y) \ + $(libpthread-a-y) $(libthread_db-a-y) \ + $(libresolv-a-y) $(librt-a-y) $(libutil-a-y) $(libubacktrace-a-y) +ifeq ($(DOPIC),y) +ar_objs := $(ar_objs:.o=.os) +endif +flat_objs = $(lib-gdb-y) + +ifeq ($(HAVE_SHARED),y) +all_objs: $(sort $(shared_objs) $(ar_objs)) +else +all_objs: $(ar_objs) +endif +$(shared_objs) $(ar_objs): | $(sub_headers) + +headers-y: $(headers-y) + @true + +MAKEFLAGS += --no-print-directory +SHELL_SET_X := set +x +define rel_srcdir + $(shell $(CONFIG_SHELL) $(top_srcdir)/extra/scripts/relative_path.sh $(@D) .) +endef +ifneq ($(findstring -s,$(MAKEFLAGS)),) +export MAKE_IS_SILENT := y +SECHO := -@false +DISP := sil +Q := @ +else +export MAKE_IS_SILENT := n +SECHO := @echo +ifneq ($(V)$(VERBOSE),) +ifeq ($(V),1) +DISP := bri# brief, like pur but with defines +Q := @ +else +SHELL_SET_X := set -x +DISP := ver +Q := +endif +else +DISP := pur +Q := @ +endif +endif + +show_objs = $(subst $(top_builddir),,$(subst ../,,$@)) +define show_defs + $(filter -D%,$(1)) +endef +define show_ldflags + $(subst $(comma), ,$(subst -Wl$(comma),,$(filter -Wl%,$(1)))) +endef + +pur_disp_compile.c = echo " "CC $(show_objs) +pur_disp_compile.i = echo " "CPP $(show_objs) +pur_disp_compile.s = echo " "CC-S $(show_objs) +pur_disp_compile.u = echo " "CC $(show_objs) +pur_disp_compile.S = echo " "AS $(show_objs) +pur_disp_compile.m = $(pur_disp_compile.c) +pur_disp_compile.mi= echo " "CPP-m $(show_objs) +pur_disp_compile-m = echo " "CC-m $(show_objs) +pur_disp_hcompile.u= echo " "HOSTCC $(show_objs) +pur_disp_hcompile.o= echo " "HOSTCC-o $(show_objs) +pur_disp_strip = echo " "STRIP $(STRIP_FLAGS) $@ +pur_disp_t_strip = echo " "STRIP $(STRIP_FLAGS) $@ +pur_disp_ar = echo " "AR $(ARFLAGS) $@ +pur_disp_ld = echo " "LD $(1) +pur_disp_ln = echo " "LN $(show_objs) +pur_disp_mkdir = echo " "MKDIR $(show_objs) +pur_disp_gen = echo " "GEN $(show_objs) +pur_disp_install = echo " "INSTALL $(1) +pur_disp_unifdef = echo " "UNIFDEF $(show_objs) +pur_disp_rm = echo " "CLEAN $(subst CLEAN_,,$(patsubst HEADERCLEAN_%,include \(%\),$@)) + +sil_disp_compile.c = true +sil_disp_compile.i = true +sil_disp_compile.s = true +sil_disp_compile.u = true +sil_disp_compile.S = true +sil_disp_compile.m = true +sil_disp_compile.mi= true +sil_disp_compile-m = true +sil_disp_hcompile.u= true +sil_disp_hcompile.o= true +sil_disp_strip = true +sil_disp_t_strip = true +sil_disp_ar = true +sil_disp_ld = true +sil_disp_ln = true +sil_disp_mkdir = true +sil_disp_gen = true +sil_disp_install = true +sil_disp_unifdef = true +sil_disp_rm = true + +bri_disp_compile.c = $(pur_disp_compile.c) $(call show_defs,$(cmd_compile.c)) +bri_disp_compile.i = $(pur_disp_compile.i) $(call show_defs,$(cmd_compile.i)) +bri_disp_compile.s = $(pur_disp_compile.s) $(call show_defs,$(cmd_compile.s)) +bri_disp_compile.u = $(pur_disp_compile.u) $(call show_defs,$(cmd_compile.u)) +bri_disp_compile.S = $(pur_disp_compile.S) $(call show_defs,$(cmd_compile.S)) +bri_disp_compile.m = $(pur_disp_compile.m) $(call show_defs,$(cmd_compile.m)) +bri_disp_compile.mi = $(pur_disp_compile.mi) $(call show_defs,$(cmd_compile.mi)) +bri_disp_compile-m = $(pur_disp_compile-m) $(call show_defs,$(cmd_compile-m)) +bri_disp_hcompile.u = $(pur_disp_hcompile.u) $(call show_defs,$(cmd_hcompile.u)) +bri_disp_hcompile.o = $(pur_disp_hcompile.o) $(call show_defs,$(cmd_hcompile.o)) +bri_disp_strip = $(pur_disp_strip) +bri_disp_t_strip = $(pur_disp_t_strip) +bri_disp_ar = $(pur_disp_ar) +bri_disp_ld = $(pur_disp_ld) $(call show_ldflags,$(cmd_ld)) +bri_disp_ln = $(pur_disp_ln) +bri_disp_mkdir = $(pur_disp_mkdir) +bri_disp_gen = $(pur_disp_gen) +bri_disp_install = $(pur_disp_install) +bri_disp_unifdef = $(pur_disp_unifdef) +bri_disp_rm = $(pur_disp_rm) + +esc=$(subst ','\'',$(1)) +# ') +ver_disp_compile.c = echo '$(call esc,$(cmd_compile.c))' +ver_disp_compile.i = echo '$(call esc,$(cmd_compile.i))' +ver_disp_compile.s = echo '$(call esc,$(cmd_compile.s))' +ver_disp_compile.u = echo '$(call esc,$(cmd_compile.u))' +ver_disp_compile.S = echo '$(call esc,$(cmd_compile.S))' +ver_disp_compile.m = echo '$(call esc,$(cmd_compile.m))' +ver_disp_compile.mi= echo '$(call esc,$(cmd_compile.mi))' +ver_disp_compile-m = echo '$(call esc,$(cmd_compile-m))' +ver_disp_hcompile.u= echo '$(call esc,$(cmd_hcompile.u))' +ver_disp_hcompile.o= echo '$(call esc,$(cmd_hcompile.o))' +ver_disp_strip = echo '$(call esc,$(cmd_strip))' +ver_disp_t_strip = echo '$(call esc,$(cmd_t_strip))' +ver_disp_ar = echo '$(call esc,$(cmd_ar))' +ver_disp_ld = +ver_disp_ln = +ver_disp_mkdir = +ver_disp_gen = +ver_disp_install = +ver_disp_unifdef = echo '$(call esc,$(cmd_unifdef))' +ver_disp_rm = + +disp_compile.c = $($(DISP)_disp_compile.c) +disp_compile.i = $($(DISP)_disp_compile.i) +disp_compile.s = $($(DISP)_disp_compile.s) +disp_compile.u = $($(DISP)_disp_compile.u) +disp_compile.S = $($(DISP)_disp_compile.S) +disp_compile.m = $($(DISP)_disp_compile.m) +disp_compile.mi= $($(DISP)_disp_compile.mi) +disp_compile-m = $($(DISP)_disp_compile-m) +disp_hcompile.u= $($(DISP)_disp_hcompile.u) +disp_hcompile.o= $($(DISP)_disp_hcompile.o) +disp_strip = $($(DISP)_disp_strip) +disp_t_strip = $($(DISP)_disp_t_strip) +disp_ar = $($(DISP)_disp_ar) +disp_ld = $($(DISP)_disp_ld) +disp_ln = $($(DISP)_disp_ln) +disp_mkdir = $($(DISP)_disp_mkdir) +disp_gen = $($(DISP)_disp_gen) +disp_install = $($(DISP)_disp_install) +disp_unifdef = $($(DISP)_disp_unifdef) +disp_rm = $($(DISP)_disp_rm) + +any-prereq = $(filter-out $(PHONY),$?) $(filter-out $(PHONY) $(wildcard $^),$^) + +# ../foo/bar/baz.ext -> foo_bar_baz.ext +variablify = $(subst /,_,$(subst $(top_builddir),,$(1))) +# strip the top_builddir off everything to make the *string* idempotent for -C +dirify = $(subst $(top_builddir),,$(patsubst -L$(top_builddir)%,-L%,$(patsubst -I$(top_builddir)%,-I%,$(1)))) + +# True if not identical. Neither order nor whitespace nor identical flags +# matter. +compare_flags = \ + $(strip $(filter-out $(call dirify,$(cmd_$(call variablify,$(1)))), \ + $(call dirify,$(cmd_$(call variablify,$(@))))) \ + $(filter-out $(call dirify,$(cmd_$(call variablify,$(@)))), \ + $(call dirify,$(cmd_$(call variablify,$(1)))))) + +# Rebuild if any prerequisite, the used CC or flags changed. +# Previously used flags are stored in the corresponding .%.dep files +maybe_exec = \ + $(if $(strip $(compare_flags) $(any-prereq)), \ + @set -e; \ + $(disp_$(1)); \ + $(cmd_$(1)); \ + echo 'cmd_$(call variablify,$@) := $(call dirify,$(cmd_$(call variablify,$1)))' >> $(dir $@).$(notdir $@).dep) + +# collect flags of domulti prereqs +#collect_multi_flags = $(CFLAGS-$(notdir $(d))) $(CFLAGS-$(notdir $(patsubst %/,%,$(dir $(d))))) +collect_multi_flags = $(CFLAGS-$(notdir $(patsubst %/,%,$(dir $(d))))) + +CFLAGS_gen.dep = -MT $@ -MD -MP -MF $(dir $@).$(notdir $@).dep + +cmd_compile.c = $(CC) -c $< -o $@ $(CFLAGS) \ + $(CFLAGS-$(suffix $@)) \ + $(filter-out $(CFLAGS-OMIT-$(notdir $<)),$(CFLAGS-$(notdir $( $@.tmp + $(Q)echo "#include " >> $@.tmp + $(Q)echo "const char __dl_ldso__[] attribute_hidden __attribute__ ((weak)) __attribute__ ((section " \ + "(\".interp\"))) =\""$(RUNTIME_PREFIX)$(MULTILIB_DIR)/$(UCLIBC_LDSO)"\";" >> $@.tmp + $(Q)mv $@.tmp $@ + +$(interp): $(top_builddir)lib/interp.c | $(sub_headers) + $(compile.c) + $(Q)$(STRIPTOOL) -x -R .note -R .comment $@ + +$(ldso): + $(Q)cd $(top_builddir); $(MAKE) lib/$(patsubst %.$(ABI_VERSION),%,$(notdir $@)) +$(libc): + $(Q)cd $(top_builddir); $(MAKE) lib/$(patsubst %.$(ABI_VERSION),%,$(notdir $@)) + +CRT := crt1 + +ifeq ($(HAVE_SHARED)$(UCLIBC_FORMAT_SHARED_FLAT),y) +CRTS=$(top_builddir)lib/$(CRT).o $(top_builddir)lib/S$(CRT).o +else +CRTS=$(top_builddir)lib/$(CRT).o +endif + +ASFLAGS-$(CRT).o := -DL_$(CRT) +ASFLAGS-S$(CRT).o := $(PIEFLAG) -DL_S$(CRT) +$(CRTS): $(top_srcdir)libc/sysdeps/linux/$(TARGET_ARCH)/$(CRT).S + $(compile.S) + $(Q)$(STRIPTOOL) -x -R .note -R .comment $@ + +ifeq ($(UCLIBC_CTOR_DTOR),y) +CTOR_TARGETS=$(top_builddir)lib/crti.o $(top_builddir)lib/crtn.o +else +CTOR_TARGETS:= +endif + +ifeq ($(UCLIBC_FORMAT_FDPIC_ELF),y) +CRTRELOC=$(top_builddir)lib/crtreloc.o +$(CRTRELOC): $(top_builddir)lib/%.o : $(top_srcdir)libc/sysdeps/linux/$(TARGET_ARCH)/%.c + $(compile.c) +endif + +ifneq ($(wildcard $(top_srcdir)libc/sysdeps/linux/$(TARGET_ARCH)/initfini.c),) +CFLAGS-initfini.s := -S -g0 $(PICFLAG) -fno-inline-functions -finhibit-size-directive +$(top_builddir)lib/initfini.s: $(top_srcdir)libc/sysdeps/linux/$(TARGET_ARCH)/initfini.c | $(top_builddir)lib + $(compile.c) + +$(top_builddir)lib/defs.h: $(top_builddir)lib/initfini.s | $(top_builddir)lib + $(Q)sed -n -e '/@TESTS_BEGIN/,/@TESTS_END/p' $< | \ + gawk -f $(top_srcdir)extra/scripts/defs.awk > $@.tmp + $(Q)mv $@.tmp $@ + +$(top_builddir)lib/crti.S: $(top_builddir)lib/initfini.s $(top_builddir)lib/defs.h + $(Q)sed -n -e '1,/@HEADER_ENDS/p' \ + -e '/@_.*_PROLOG_BEGINS/,/@_.*_PROLOG_ENDS/p' \ + -e '/@TRAILER_BEGINS/,$$p' $< > $@ + +$(top_builddir)lib/crtn.S: $(top_builddir)lib/initfini.s + $(Q)sed -n -e '1,/@HEADER_ENDS/p' \ + -e '/@_.*_EPILOG_BEGINS/,/@_.*_EPILOG_ENDS/p' \ + -e '/@TRAILER_BEGINS/,$$p' $< > $@ + +$(CTOR_TARGETS): $(top_builddir)lib/%.o : $(top_builddir)lib/%.S + $(compile.S) $(PICFLAG) $(SSP_DISABLE_FLAGS) +else +$(CTOR_TARGETS): $(top_builddir)lib/%.o : $(top_srcdir)libc/sysdeps/linux/$(TARGET_ARCH)/%.S + $(compile.S) $(PICFLAG) $(SSP_DISABLE_FLAGS) +endif + +#ifeq ($(TARGET_ARCH),nios) +#CRTS_COMPAT := $(top_builddir)lib/crt0.o +#$(CRTS_COMPAT): +# ln -fs crt1.o $(top_builddir)lib/crt0.o +#else +CRTS_COMPAT := +#endif + +startfiles = $(CRTS) $(CTOR_TARGETS) $(CRTS_COMPAT) $(CRTRELOC) +$(crt-y): $(startfiles) +$(CRTS) $(CTOR_TARGETS) $(CRTS_COMPAT) $(CRTRELOC): | headers +$(CRTS) $(CTOR_TARGETS) $(CRTS_COMPAT) $(CRTRELOC) $(LINK_FLAT_CRTS) $(SHARED_START_FILES) $(SHARED_END_FILES) : | $(top_builddir)lib + +$(top_builddir)lib/$(NONSHARED_LIBNAME): $(libc-nonshared-y) + $(Q)$(RM) $@ + $(do_ar) + +$(top_builddir)lib/libpthread_nonshared.a: $(libpthread-nonshared-y) + $(Q)$(RM) $@ + $(do_ar) + +files.dep := $(libc-a-y) $(libc-so-y) $(libc-nonshared-y) \ + $(libm-a-y) $(libm-so-y) \ + $(libpthread-a-y) $(libpthread-so-y) $(libpthread-nonshared-y) \ + $(libthread_db-a-y) $(libthread_db-so-y) $(libpthread-generated-y) \ + $(librt-a-y) $(librt-so-y) $(libresolv-a-y) $(libresolv-so-y) \ + $(libcrypt-a-y) $(libcrypt-so-y) $(libutil-a-y) $(libutil-so-y) \ + $(libnsl-a-y) $(libnsl-so-y) $(ldso-y) $(libdl-a-y) $(libdl-so-y) \ + $(libubacktrace-a-y) $(libubacktrace-so-y) +.depends.dep := \ + $(patsubst %.s,%.s.dep,$(filter %.s,$(files.dep))) \ + $(patsubst %.o,%.o.dep,$(filter %.o,$(files.dep))) \ + $(patsubst %.os,%.os.dep,$(filter %.os,$(files.dep))) \ + $(patsubst %.oS,%.oS.dep,$(filter %.oS,$(files.dep))) +# Oh, and prepend a dot to the basename so i don't have to change my habit of +# calling 'size thefile.o*' +.depends.dep := $(foreach f,$(.depends.dep),$(dir $(f)).$(notdir $(f))) +.depends.dep := $(wildcard $(.depends.dep)) + +FORCE: + +clean: objclean-y headers_clean-y +realclean: clean menuconfig-clean-y + $(Q)$(RM) $(.depends.dep) + +objclean-y: $(objclean-y) +headers_clean-y: $(headers_clean-y) + +ifeq ($(filter $(noconfig_targets),$(MAKECMDGOALS)),) +ifneq ($(strip $(.depends.dep)),) +.NOEXPORT: +-include $(.depends.dep) +endif +endif + +# vi: ft=make : diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/README b/l4/pkg/uclibc/lib/contrib/uclibc/README new file mode 100644 index 00000000..f8467fb7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/README @@ -0,0 +1,73 @@ + + uClibc - a Small C Library for Linux + Erik Andersen + +uClibc (aka µClibc/pronounced yew-see-lib-see) is a C library for +developing embedded Linux systems. It is much smaller than the +GNU C Library, but nearly all applications supported by glibc +also work perfectly with uClibc. Porting applications from glibc +to uClibc typically involves just recompiling the source code. +uClibc even supports shared libraries and threading. It currently +runs on standard Linux and MMU-less (also known as µClinux) +systems with support for alpha, ARM, cris, e1, h8300, i386, i960, +m68k, microblaze, mips/mipsel, PowerPC, SH, SPARC, and v850 +processors. + +If you are building an embedded Linux system and you find that +glibc is eating up too much space, you should consider using +uClibc. If you are building a huge fileserver with 12 Terabytes +of storage, then using glibc may make more sense. Unless, for +example, that 12 Terabytes will be Network Attached Storage and +you plan to burn Linux into the system's firmware... + +uClibc is maintained by Erik Andersen and is licensed under the +GNU LESSER GENERAL PUBLIC LICENSE. This license allows you to +make closed source commercial applications using an unmodified +version of uClibc (Please consider sharing some of the money you +make ;-). You do not need to give away all your source code just +because you use uClibc and/or run on Linux. You should, however, +carefuly review the license and make certain you understand and +abide by it strictly. + + +For installation instructions, see the file INSTALL. + +uClibc strives to be standards compliant, which means that most +documentation written for SuSv3, or for glibc also applies to +uClibc functions. However, many GNU extensions are not supported +because they have not been ported, or more importantly, would +increase the size of uClibc disproportional to the added +functionality. There is some discussion of these differences +in the "docs" directory. + +Additional information (recent releases, FAQ, mailing list, bugs, +etc.) can be found at http://www.uclibc.org/. + +uClibc may be freely modified and distributed under the terms of +the GNU Lesser General Public License, which can be found in the +file COPYING.LIB. + +Please Note: + + There is an unwholesomely huge amount of code out there + that depends on the presence of GNU libc header files. + We have GNU libc compatible header files. So we have + committed a horrible sin in uClibc. We _lie_ and claim + to be GNU libc in order to force these applications to + work as their developers intended. This is IMHO, + pardonable, since these defines are not really intended + to check for the presence of a particular library, but + rather are used to define an _interface_. Some programs + are especially chummy with glibc, and may need this + behavior disabled by adding CFLAGS+=-D__FORCE_NOGLIBC + + If you want to make special exceptions in your code which are + specifically for uClibc, you can make certain to include features.h, + and then have your code check for uClibc as follows: + + #ifdef __UCLIBC__ + do_something_special(); + #endif + +And most of all, be sure to have some fun! :-) + -Erik diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/Rules.mak b/l4/pkg/uclibc/lib/contrib/uclibc/Rules.mak new file mode 100644 index 00000000..eecdc642 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/Rules.mak @@ -0,0 +1,740 @@ +# Rules.make for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +# make nano-doc +# FOO = bar -- recursively expanded variable. Value is remebered verbatim. +# If it contains references to other variables, these references +# are expanded whenever this variable is _substituted_. +# FOO := bar -- simply expanded variable. Right hand is expanded when +# the variable is _defined_. Therefore faster than =. +# FOO ?= bar -- set a value only if it is not already set +# (behaves as =, not :=). +# FOO += bar -- append; if FOO is not defined, acts like = (not :=). + + +# check for proper make version +ifneq ($(findstring x3.7,x$(MAKE_VERSION)),) +$(error Your make is too old $(MAKE_VERSION). Go get at least 3.80) +endif + +#----------------------------------------------------------- +# This file contains rules which are shared between multiple +# Makefiles. All normal configuration options live in the +# file named ".config". Don't mess with this file unless +# you know what you are doing. + + +#----------------------------------------------------------- +# If you are running a cross compiler, you will want to set +# 'CROSS' to something more interesting ... Target +# architecture is determined by asking the CC compiler what +# arch it compiles things for, so unless your compiler is +# broken, you should not need to specify TARGET_ARCH. +# +# Most people will set this stuff on the command line, i.e. +# make CROSS=arm-linux- +# will build uClibc for 'arm'. + +ifndef CROSS +CROSS= +endif +CC = $(CROSS)gcc +AR = $(CROSS)ar +LD = $(CROSS)ld +NM = $(CROSS)nm +OBJDUMP = $(CROSS)objdump +STRIPTOOL = $(CROSS)strip + +INSTALL = install +LN = ln +RM = rm -f +TAR = tar +SED = sed +AWK = awk + +STRIP_FLAGS ?= -x -R .note -R .comment + +## unused? if yes, remove after 0.9.31 +## UNIFDEF := $(top_builddir)extra/scripts/unifdef + +# Select the compiler needed to build binaries for your development system +HOSTCC = gcc +BUILD_CFLAGS = -Os -Wall + +#--------------------------------------------------------- +# Nothing beyond this point should ever be touched by mere +# mortals. Unless you hang out with the gods, you should +# probably leave all this stuff alone. + +# strip quotes +qstrip = $(strip $(subst ",,$(1))) +#")) + +# Pull in the user's uClibc configuration +ifeq ($(filter $(noconfig_targets),$(MAKECMDGOALS)),) +-include $(top_builddir).config +endif +TARGET_ARCH:=$(call qstrip,$(TARGET_ARCH)) +ifeq ($(TARGET_ARCH),) +ARCH ?= $(shell uname -m | $(SED) -e s/i.86/i386/ \ + -e s/sun.*/sparc/ -e s/sparc.*/sparc/ \ + -e s/arm.*/arm/ -e s/sa110/arm/ \ + -e s/sh.*/sh/ \ + -e s/s390x/s390/ -e s/parisc.*/hppa/ \ + -e s/ppc.*/powerpc/ -e s/mips.*/mips/ \ + -e s/xtensa.*/xtensa/ ) +else +ARCH = $(TARGET_ARCH) +endif +export ARCH + +# Make certain these contain a final "/", but no "//"s. +TARGET_SUBARCH:=$(call qstrip,$(shell grep -s '^TARGET_SUBARCH' $(top_builddir)/.config | $(SED) -e 's/^TARGET_SUBARCH=//')) +TARGET_SUBARCH:=$(call qstrip,$(TARGET_SUBARCH)) +RUNTIME_PREFIX:=$(strip $(subst //,/, $(subst ,/, $(call qstrip,$(RUNTIME_PREFIX))))) +DEVEL_PREFIX:=$(strip $(subst //,/, $(subst ,/, $(call qstrip,$(DEVEL_PREFIX))))) +MULTILIB_DIR:=$(strip $(subst //,/, $(subst ,/, $(call qstrip,$(MULTILIB_DIR))))) +KERNEL_HEADERS:=$(strip $(subst //,/, $(subst ,/, $(call qstrip,$(KERNEL_HEADERS))))) +export RUNTIME_PREFIX DEVEL_PREFIX KERNEL_HEADERS MULTILIB_DIR + + +# Now config hard core +MAJOR_VERSION := 0 +MINOR_VERSION := 9 +SUBLEVEL := 32 +EXTRAVERSION :=-rc1-git +VERSION := $(MAJOR_VERSION).$(MINOR_VERSION).$(SUBLEVEL) +ABI_VERSION := $(MAJOR_VERSION) +ifneq ($(EXTRAVERSION),) +VERSION := $(VERSION)$(EXTRAVERSION) +endif +# Ensure consistent sort order, 'gcc -print-search-dirs' behavior, etc. +LC_ALL := C +export MAJOR_VERSION MINOR_VERSION SUBLEVEL VERSION ABI_VERSION LC_ALL + +LIBC := libc +SHARED_LIBNAME := $(LIBC).so.$(ABI_VERSION) +UBACKTRACE_DSO := libubacktrace.so.$(MAJOR_VERSION) +ifneq ($(findstring $(TARGET_ARCH) , hppa64 ia64 mips64 powerpc64 s390x sparc64 x86_64 ),) +UCLIBC_LDSO_NAME := ld64-uClibc +ARCH_NATIVE_BIT := 64 +else +UCLIBC_LDSO_NAME := ld-uClibc +ARCH_NATIVE_BIT := 32 +endif +UCLIBC_LDSO := $(UCLIBC_LDSO_NAME).so.$(ABI_VERSION) +NONSHARED_LIBNAME := uclibc_nonshared.a +libc := $(top_builddir)lib/$(SHARED_LIBNAME) +libc.depend := $(top_builddir)lib/$(SHARED_LIBNAME:.$(ABI_VERSION)=) +ifneq ($(ARCH_HAS_NO_SHARED),y) +libdl.depend := $(top_builddir)lib/libdl.so +endif +ifneq ($(HAS_NO_THREADS),y) +libpthread.depend := $(top_builddir)lib/libpthread.so +endif +interp := $(top_builddir)lib/interp.os +ldso := $(top_builddir)lib/$(UCLIBC_LDSO) +headers_dep := $(top_builddir)include/bits/sysnum.h +sub_headers := $(headers_dep) + +#LIBS :=$(interp) -L$(top_builddir)lib -lc +LIBS := $(interp) -L$(top_builddir)lib $(libc:.$(ABI_VERSION)=) + +# Make sure DESTDIR and PREFIX can be used to install +# PREFIX is a uClibcism while DESTDIR is a common GNUism +ifndef PREFIX +PREFIX = $(DESTDIR) +endif + +ifneq ($(HAVE_SHARED),y) +libc := +interp := +ldso := +endif + +comma:=, +space:= # + +ifndef CROSS +CROSS=$(call qstrip,$(CROSS_COMPILER_PREFIX)) +endif + +# A nifty macro to make testing gcc features easier +check_gcc=$(shell \ + if $(CC) $(1) -S -o /dev/null -xc /dev/null > /dev/null 2>&1; \ + then echo "$(1)"; else echo "$(2)"; fi) +check_as=$(shell \ + if $(CC) -Wa,$(1) -Wa,-Z -c -o /dev/null -xassembler /dev/null > /dev/null 2>&1; \ + then echo "-Wa,$(1)"; fi) +check_ld=$(shell \ + if $(LD) $(1) -o /dev/null -b binary /dev/null > /dev/null 2>&1; \ + then echo "$(1)"; fi) + +ARFLAGS:=cr + + +# Flags in OPTIMIZATION are used only for non-debug builds + +OPTIMIZATION:= +# Use '-Os' optimization if available, else use -O2, allow Config to override +OPTIMIZATION+=$(call check_gcc,-Os,-O2) +# Use the gcc 3.4 -funit-at-a-time optimization when available +OPTIMIZATION+=$(call check_gcc,-funit-at-a-time,) +# shrinks code by about 0.1% +OPTIMIZATION+=$(call check_gcc,-fmerge-all-constants) + +GCC_MAJOR_VER?=$(shell $(CC) -dumpversion | cut -d . -f 1) +#GCC_MINOR_VER?=$(shell $(CC) -dumpversion | cut -d . -f 2) + +ifeq ($(GCC_MAJOR_VER),4) +# shrinks code, results are from 4.0.2 +# 0.36% +OPTIMIZATION+=$(call check_gcc,-fno-tree-loop-optimize,) +# 0.34% +OPTIMIZATION+=$(call check_gcc,-fno-tree-dominator-opts,) +# 0.1% +OPTIMIZATION+=$(call check_gcc,-fno-strength-reduce,) +endif + + +# CPU_CFLAGS-y contain options which are not warnings, +# not include or library paths, and not optimizations. + +# Why -funsigned-char: I hunted a bug related to incorrect +# sign extension of 'char' type for 10 hours straight. Not fun. +CPU_CFLAGS-y := -funsigned-char -fno-builtin + +CPU_CFLAGS-y += $(call check_gcc,-fno-asm,) + +LDADD_LIBFLOAT= +ifeq ($(UCLIBC_HAS_SOFT_FLOAT),y) +# If -msoft-float isn't supported, we want an error anyway. +# Hmm... might need to revisit this for arm since it has 2 different +# soft float encodings. +ifneq ($(TARGET_ARCH),nios) +ifneq ($(TARGET_ARCH),nios2) +ifneq ($(TARGET_ARCH),sh) +CPU_CFLAGS-y += -msoft-float +endif +endif +endif +ifeq ($(TARGET_ARCH),arm) +# No longer needed with current toolchains, but leave it here for now. +# If anyone is actually still using gcc 2.95 (say), they can uncomment it. +# LDADD_LIBFLOAT=-lfloat +endif +endif + +CPU_CFLAGS-y += $(call check_gcc,-std=gnu99,) + +CPU_CFLAGS-$(UCLIBC_FORMAT_SHARED_FLAT) += -mid-shared-library +CPU_CFLAGS-$(UCLIBC_FORMAT_FLAT_SEP_DATA) += -msep-data + +CPU_LDFLAGS-$(ARCH_LITTLE_ENDIAN) += -Wl,-EL +CPU_LDFLAGS-$(ARCH_BIG_ENDIAN) += -Wl,-EB + +PICFLAG-y := -fPIC +PICFLAG-$(UCLIBC_FORMAT_FDPIC_ELF) := -mfdpic +PICFLAG := $(PICFLAG-y) +PIEFLAG_NAME:=-fPIE + +# Some nice CPU specific optimizations +ifeq ($(TARGET_ARCH),i386) + OPTIMIZATION+=$(call check_gcc,-fomit-frame-pointer,) + +ifeq ($(CONFIG_386)$(CONFIG_486)$(CONFIG_586)$(CONFIG_586MMX),y) + # Non-SSE capable processor. + # NB: this may make SSE insns segfault! + # -O1 -march=pentium3, -Os -msse etc are known to be affected. + # See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=13685 + # -m32 is needed if host is 64-bit + OPTIMIZATION+=$(call check_gcc,-m32 -mpreferred-stack-boundary=2,) +else + OPTIMIZATION+=$(call check_gcc,-mpreferred-stack-boundary=4,) +endif + + # Choice of alignment (please document why!) + # -falign-labels: in-line labels + # (reachable by normal code flow, aligning will insert nops + # which will be executed - may even make things slower) + # -falign-jumps: reachable only by a jump + # Generic: no alignment at all (smallest code) + GCC_FALIGN=$(call check_gcc,-falign-functions=1 -falign-jumps=1 -falign-labels=1 -falign-loops=1,-malign-jumps=1 -malign-loops=1) +ifeq ($(CONFIG_K7),y) + # Align functions to four bytes, use default for jumps and loops (why?) + GCC_FALIGN=$(call check_gcc,-falign-functions=4 -falign-labels=1,-malign-functions=4) +endif +ifeq ($(CONFIG_CRUSOE),y) + # Use compiler's default for functions, jumps and loops (why?) + GCC_FALIGN=$(call check_gcc,-falign-functions=0 -falign-labels=1,-malign-functions=0) +endif +ifeq ($(CONFIG_CYRIXIII),y) + # Use compiler's default for functions, jumps and loops (why?) + GCC_FALIGN=$(call check_gcc,-falign-functions=0 -falign-labels=1,-malign-functions=0) +endif + OPTIMIZATION+=$(GCC_FALIGN) + + # Putting each function and data object into its own section + # allows for kbytes of less text if users link against static uclibc + # using ld --gc-sections. + # ld 2.18 can't do that (yet?) for shared libraries, so we itself + # do not use --gc-sections at shared lib link time. + # However, in combination with sections being sorted by alignment + # it does result in much reduced padding: + # text data bss dec hex + # 235319 1472 5992 242783 3b45f old.so + # 234104 1472 5980 241556 3af94 new.so + # Without -ffunction-sections, all functions will get aligned + # to 4 byte boundary by as/ld. This is arguably a bug in as. + # It specifies 4 byte align for .text even if not told to do so: + # Idx Name Size VMA LMA File off Algn + # 0 .text xxxxxxxx 00000000 00000000 xxxxxxxx 2**2 <===! + CPU_CFLAGS-y += $(call check_gcc,-ffunction-sections -fdata-sections,) +ifneq ($(call check_ld,--sort-common),) + CPU_LDFLAGS-y += -Wl,--sort-common +endif +ifneq ($(call check_ld,--sort-section alignment),) + CPU_LDFLAGS-y += -Wl,--sort-section,alignment +endif + + CPU_LDFLAGS-y+=-m32 + CPU_CFLAGS-y+=-m32 + CPU_CFLAGS-$(CONFIG_386)+=-march=i386 + CPU_CFLAGS-$(CONFIG_486)+=-march=i486 + CPU_CFLAGS-$(CONFIG_ELAN)+=-march=i486 + CPU_CFLAGS-$(CONFIG_586)+=-march=i586 + CPU_CFLAGS-$(CONFIG_586MMX)+=$(call check_gcc,-march=pentium-mmx,-march=i586) + CPU_CFLAGS-$(CONFIG_686)+=-march=i686 + CPU_CFLAGS-$(CONFIG_PENTIUMII)+=$(call check_gcc,-march=pentium2,-march=i686) + CPU_CFLAGS-$(CONFIG_PENTIUMIII)+=$(call check_gcc,-march=pentium3,-march=i686) + CPU_CFLAGS-$(CONFIG_PENTIUM4)+=$(call check_gcc,-march=pentium4,-march=i686) + CPU_CFLAGS-$(CONFIG_K6)+=$(call check_gcc,-march=k6,-march=i586) + CPU_CFLAGS-$(CONFIG_K7)+=$(call check_gcc,-march=athlon,-march=i686) + CPU_CFLAGS-$(CONFIG_CRUSOE)+=-march=i686 + CPU_CFLAGS-$(CONFIG_WINCHIPC6)+=$(call check_gcc,-march=winchip-c6,-march=i586) + CPU_CFLAGS-$(CONFIG_WINCHIP2)+=$(call check_gcc,-march=winchip2,-march=i586) + CPU_CFLAGS-$(CONFIG_CYRIXIII)+=$(call check_gcc,-march=c3,-march=i486) + CPU_CFLAGS-$(CONFIG_NEHEMIAH)+=$(call check_gcc,-march=c3-2,-march=i686) +endif + +ifeq ($(TARGET_ARCH),sparc) + CPU_CFLAGS-$(CONFIG_SPARC_V7)+=-mcpu=v7 + CPU_CFLAGS-$(CONFIG_SPARC_V8)+=-mcpu=v8 + CPU_CFLAGS-$(CONFIG_SPARC_V9)+=-mcpu=v9 + CPU_CFLAGS-$(CONFIG_SPARC_V9B)+=$(call check_gcc,-mcpu=v9b,-mcpu=ultrasparc) +endif + +ifeq ($(TARGET_ARCH),arm) + OPTIMIZATION+=-fstrict-aliasing + CPU_CFLAGS-$(ARCH_LITTLE_ENDIAN)+=-mlittle-endian + CPU_CFLAGS-$(ARCH_BIG_ENDIAN)+=-mbig-endian + CPU_CFLAGS-$(CONFIG_GENERIC_ARM)+= + CPU_CFLAGS-$(CONFIG_ARM610)+=-mtune=arm610 -march=armv3 + CPU_CFLAGS-$(CONFIG_ARM710)+=-mtune=arm710 -march=armv3 + CPU_CFLAGS-$(CONFIG_ARM7TDMI)+=-mtune=arm7tdmi -march=armv4t + CPU_CFLAGS-$(CONFIG_ARM720T)+=-mtune=arm7tdmi -march=armv4t + CPU_CFLAGS-$(CONFIG_ARM920T)+=-mtune=arm9tdmi -march=armv4t + CPU_CFLAGS-$(CONFIG_ARM922T)+=-mtune=arm9tdmi -march=armv4t + CPU_CFLAGS-$(CONFIG_ARM926T)+=-mtune=arm9e -march=armv5te + CPU_CFLAGS-$(CONFIG_ARM10T)+=-mtune=arm10tdmi -march=armv5t + CPU_CFLAGS-$(CONFIG_ARM1136JF_S)+=-mtune=arm1136jf-s -march=armv6 + CPU_CFLAGS-$(CONFIG_ARM1176JZ_S)+=-mtune=arm1176jz-s -march=armv6 + CPU_CFLAGS-$(CONFIG_ARM1176JZF_S)+=-mtune=arm1176jzf-s -march=armv6 + CPU_CFLAGS-$(CONFIG_ARM_SA110)+=-mtune=strongarm110 -march=armv4 + CPU_CFLAGS-$(CONFIG_ARM_SA1100)+=-mtune=strongarm1100 -march=armv4 + CPU_CFLAGS-$(CONFIG_ARM_XSCALE)+=$(call check_gcc,-mtune=xscale,-mtune=strongarm110) + CPU_CFLAGS-$(CONFIG_ARM_XSCALE)+=-march=armv5te -Wa,-mcpu=xscale + CPU_CFLAGS-$(CONFIG_ARM_IWMMXT)+=-march=iwmmxt -Wa,-mcpu=iwmmxt -mabi=iwmmxt + CPU_CFLAGS-$(CONFIG_ARM_CORTEX_M3)+=-mcpu=cortex-m3 -mthumb + CPU_CFLAGS-$(CONFIG_ARM_CORTEX_M1)+=-mcpu=cortex-m1 -mthumb +endif + +ifeq ($(TARGET_ARCH),mips) + OPTIMIZATION+=-mno-split-addresses + CPU_CFLAGS-$(CONFIG_MIPS_ISA_1)+=-mips1 + CPU_CFLAGS-$(CONFIG_MIPS_ISA_2)+=-mips2 -mtune=mips2 + CPU_CFLAGS-$(CONFIG_MIPS_ISA_3)+=-mips3 -mtune=mips3 + CPU_CFLAGS-$(CONFIG_MIPS_ISA_4)+=-mips4 -mtune=mips4 + CPU_CFLAGS-$(CONFIG_MIPS_ISA_MIPS32)+=-mips32 -mtune=mips32 + CPU_CFLAGS-$(CONFIG_MIPS_ISA_MIPS32R2)+=-march=mips32r2 -mtune=mips32r2 + CPU_CFLAGS-$(CONFIG_MIPS_ISA_MIPS64)+=-mips64 -mtune=mips32 + ifeq ($(strip $(ARCH_BIG_ENDIAN)),y) + CPU_LDFLAGS-$(CONFIG_MIPS_N64_ABI)+=-Wl,-melf64btsmip + CPU_LDFLAGS-$(CONFIG_MIPS_O32_ABI)+=-Wl,-melf32btsmip + endif + ifeq ($(strip $(ARCH_LITTLE_ENDIAN)),y) + CPU_LDFLAGS-$(CONFIG_MIPS_N64_ABI)+=-Wl,-melf64ltsmip + CPU_LDFLAGS-$(CONFIG_MIPS_O32_ABI)+=-Wl,-melf32ltsmip + endif + CPU_CFLAGS-$(CONFIG_MIPS_N64_ABI)+=-mabi=64 + CPU_CFLAGS-$(CONFIG_MIPS_O32_ABI)+=-mabi=32 + CPU_CFLAGS-$(CONFIG_MIPS_N32_ABI)+=-mabi=n32 +endif + +ifeq ($(TARGET_ARCH),nios) + OPTIMIZATION+=-funaligned-struct-hack + CPU_LDFLAGS-y+=-Wl,-m32 + CPU_CFLAGS-y+=-Wl,-m32 +endif + +ifeq ($(TARGET_ARCH),sh) + OPTIMIZATION+=-fstrict-aliasing + OPTIMIZATION+= $(call check_gcc,-mprefergot,) + CPU_CFLAGS-$(ARCH_LITTLE_ENDIAN)+=-ml + CPU_CFLAGS-$(ARCH_BIG_ENDIAN)+=-mb + CPU_CFLAGS-$(CONFIG_SH2)+=-m2 + CPU_CFLAGS-$(CONFIG_SH3)+=-m3 +ifeq ($(UCLIBC_HAS_FPU),y) + CPU_CFLAGS-$(CONFIG_SH2A)+=-m2a + CPU_CFLAGS-$(CONFIG_SH4)+=-m4 +else + CPU_CFLAGS-$(CONFIG_SH2A)+=-m2a-nofpu + CPU_CFLAGS-$(CONFIG_SH4)+=-m4-nofpu +endif +endif + +ifeq ($(TARGET_ARCH),sh64) + OPTIMIZATION+=-fstrict-aliasing + CPU_CFLAGS-$(ARCH_LITTLE_ENDIAN):=-ml + CPU_CFLAGS-$(ARCH_BIG_ENDIAN):=-mb + CPU_CFLAGS-$(CONFIG_SH5)+=-m5-32media +endif + +ifeq ($(TARGET_ARCH),h8300) + SYMBOL_PREFIX=_ + CPU_LDFLAGS-$(CONFIG_H8300H)+= -Wl,-ms8300h + CPU_LDFLAGS-$(CONFIG_H8S) += -Wl,-ms8300s + CPU_CFLAGS-$(CONFIG_H8300H) += -mh -mint32 + CPU_CFLAGS-$(CONFIG_H8S) += -ms -mint32 +endif + +ifeq ($(TARGET_ARCH),i960) + OPTIMIZATION+=-mh -mint32 #-fsigned-char +endif + +ifeq ($(TARGET_ARCH),e1) + OPTIMIZATION+=-mgnu-param +endif + +ifeq ($(TARGET_ARCH),cris) + CPU_LDFLAGS-$(CONFIG_CRIS)+=-Wl,-mcrislinux + CPU_LDFLAGS-$(CONFIG_CRISV32)+=-Wl,-mcrislinux + CPU_CFLAGS-$(CONFIG_CRIS)+=-mlinux + PICFLAG:=-fpic + PIEFLAG_NAME:=-fpie +endif + +ifeq ($(TARGET_ARCH),m68k) + # -fPIC is only supported for 68020 and above. It is not supported + # for 68000, 68010, or Coldfire. + PICFLAG:=-fpic + PIEFLAG_NAME:=-fpie +endif + +ifeq ($(TARGET_ARCH),powerpc) +# PowerPC can hold 8192 entries in its GOT with -fpic which is more than +# enough. Therefore use -fpic which will reduce code size and generates +# faster code. + PICFLAG:=-fpic + PIEFLAG_NAME:=-fpie + PPC_HAS_REL16:=$(shell echo -e "\t.text\n\taddis 11,30,_GLOBAL_OFFSET_TABLE_-.@ha" | $(CC) -c -x assembler -o /dev/null - 2> /dev/null && echo -n y || echo -n n) + CPU_CFLAGS-$(PPC_HAS_REL16)+= -DHAVE_ASM_PPC_REL16 + CPU_CFLAGS-$(CONFIG_E500) += "-D__NO_MATH_INLINES" + +endif + +ifeq ($(TARGET_ARCH),bfin) + SYMBOL_PREFIX=_ +ifeq ($(UCLIBC_FORMAT_FDPIC_ELF),y) + CPU_CFLAGS-y:=-mfdpic + CPU_LDFLAGS-y += -Wl,-melf32bfinfd + PICFLAG:=-fpic + PIEFLAG_NAME:=-fpie +endif +ifeq ($(UCLIBC_FORMAT_SHARED_FLAT),y) + PICFLAG := -mleaf-id-shared-library +endif +endif + +ifeq ($(TARGET_ARCH),frv) + CPU_LDFLAGS-$(CONFIG_FRV)+=-Wl,-melf32frvfd + # Using -pie causes the program to have an interpreter, which is + # forbidden, so we must make do with -shared. Unfortunately, + # -shared by itself would get us global function descriptors + # and calls through PLTs, dynamic resolution of symbols, etc, + # which would break as well, but -Bsymbolic comes to the rescue. + export LDPIEFLAG:=-shared -Wl,-Bsymbolic + UCLIBC_LDSO=ld.so.1 +endif + +ifeq ($(strip $(TARGET_ARCH)),avr32) + CPU_CFLAGS-$(CONFIG_AVR32_AP7) += -march=ap + CPU_CFLAGS-$(CONFIG_LINKRELAX) += -mrelax + CPU_LDFLAGS-$(CONFIG_LINKRELAX) += --relax +endif + +ifeq ($(TARGET_ARCH),i960) + SYMBOL_PREFIX=_ +endif + +ifeq ($(TARGET_ARCH),v850) + SYMBOL_PREFIX=_ +endif + +# Keep the check_gcc from being needlessly executed +ifndef PIEFLAG +export PIEFLAG:=$(call check_gcc,$(PIEFLAG_NAME),$(PICFLAG)) +endif +# We need to keep track of both the CC PIE flag (above) as +# well as the LD PIE flag (below) because we can't rely on +# gcc passing -pie if we used -fPIE. We need to directly use -pie +# instead of -Wl,-pie as gcc picks up the wrong startfile/endfile +ifndef LDPIEFLAG +export LDPIEFLAG:=$(shell $(LD) --help 2>/dev/null | grep -q -- -pie && echo "-pie") +endif + +# Check for --as-needed support in linker +ifndef LD_FLAG_ASNEEDED +_LD_FLAG_ASNEEDED:=$(shell $(LD) --help 2>/dev/null | grep -- --as-needed) +ifneq ($(_LD_FLAG_ASNEEDED),) +export LD_FLAG_ASNEEDED:=--as-needed +endif +endif +ifndef LD_FLAG_NO_ASNEEDED +ifdef LD_FLAG_ASNEEDED +export LD_FLAG_NO_ASNEEDED:=--no-as-needed +endif +endif +ifndef CC_FLAG_ASNEEDED +ifdef LD_FLAG_ASNEEDED +export CC_FLAG_ASNEEDED:=-Wl,$(LD_FLAG_ASNEEDED) +endif +endif +ifndef CC_FLAG_NO_ASNEEDED +ifdef LD_FLAG_NO_ASNEEDED +export CC_FLAG_NO_ASNEEDED:=-Wl,$(LD_FLAG_NO_ASNEEDED) +endif +endif +link.asneeded = $(if $(and $(CC_FLAG_ASNEEDED),$(CC_FLAG_NO_ASNEEDED)),$(CC_FLAG_ASNEEDED) $(1) $(CC_FLAG_NO_ASNEEDED)) + +# Check for AS_NEEDED support in linker script (binutils>=2.16.1 has it) +ifndef ASNEEDED +export ASNEEDED:=$(shell $(LD) --help 2>/dev/null | grep -q -- --as-needed && echo "AS_NEEDED ( $(UCLIBC_LDSO) )" || echo "$(UCLIBC_LDSO)") +ifeq ($(UCLIBC_HAS_BACKTRACE),y) +# Only used in installed libc.so linker script +UBACKTRACE_FULL_NAME := $(RUNTIME_PREFIX)lib/$(UBACKTRACE_DSO) +export UBACKTRACE_ASNEEDED:=$(shell $(LD) --help 2>/dev/null | grep -q -- --as-needed && echo "AS_NEEDED ( $(UBACKTRACE_FULL_NAME) )" || echo "$(UBACKTRACE_FULL_NAME)") +else +export UBACKTRACE_ASNEEDED:="" +endif +endif + +# Add a bunch of extra pedantic annoyingly strict checks +XWARNINGS=$(call qstrip,$(WARNINGS)) +XWARNINGS+=$(foreach w,\ + -Wstrict-prototypes \ + -fno-strict-aliasing \ + , $(call check_gcc,$(w),)) +ifeq ($(EXTRA_WARNINGS),y) +XWARNINGS+=$(foreach w,\ + -Wformat=2 \ + -Wmissing-noreturn \ + -Wmissing-format-attribute \ + -Wmissing-prototypes \ + -Wmissing-declarations \ + -Wnested-externs \ + -Wnonnull \ + -Wold-style-declaration \ + -Wold-style-definition \ + -Wshadow \ + -Wundef \ + , $(call check_gcc,$(w),)) +# Works only w/ gcc-3.4 and up, can't be checked for gcc-3.x w/ check_gcc() +#XWARNINGS+=-Wdeclaration-after-statement +endif +CPU_CFLAGS=$(call qstrip,$(CPU_CFLAGS-y)) + +SSP_DISABLE_FLAGS ?= $(call check_gcc,-fno-stack-protector,) +ifeq ($(UCLIBC_BUILD_SSP),y) +SSP_CFLAGS := $(call check_gcc,-fno-stack-protector-all,) +SSP_CFLAGS += $(call check_gcc,-fstack-protector,) +SSP_ALL_CFLAGS ?= $(call check_gcc,-fstack-protector-all,) +else +SSP_CFLAGS := $(SSP_DISABLE_FLAGS) +endif + +NOSTDLIB_CFLAGS:=$(call check_gcc,-nostdlib,) + +# Collect all CFLAGS components +CFLAGS := -include $(top_srcdir)include/libc-symbols.h \ + $(XWARNINGS) $(CPU_CFLAGS) $(SSP_CFLAGS) \ + -nostdinc -I$(top_builddir)include -I$(top_srcdir)include -I. \ + -I$(top_srcdir)libc/sysdeps/linux \ + -I$(top_srcdir)libc/sysdeps/linux/$(TARGET_ARCH) +ifneq ($(strip $(UCLIBC_EXTRA_CFLAGS)),"") +CFLAGS += $(call qstrip,$(UCLIBC_EXTRA_CFLAGS)) +endif + +# We need this to be checked within libc-symbols.h +ifneq ($(HAVE_SHARED),y) +CFLAGS += -DSTATIC +endif + +LDFLAG_WARN_ONCE:=$(if $(call check_ld,--warn-once),-Wl$(comma)--warn-once) +LDFLAG_SORT_COMMON:=$(if $(call check_ld,--sort-common),-Wl$(comma)--sort-common) +LDFLAG_DISCARD_ALL:=$(if $(call check_ld,--discard-all),-Wl$(comma)--discard-all) +LDFLAGS_NOSTRIP:=$(CPU_LDFLAGS-y) -shared \ + -Wl,--warn-common $(LDFLAG_WARN_ONCE) -Wl,-z,combreloc +# binutils-2.16.1 warns about ignored sections, 2.16.91.0.3 and newer are ok +#LDFLAGS_NOSTRIP+=$(call check_ld,--gc-sections) + +ifeq ($(UCLIBC_BUILD_RELRO),y) +LDFLAGS_NOSTRIP+=-Wl,-z,relro +endif + +ifeq ($(UCLIBC_BUILD_NOW),y) +LDFLAGS_NOSTRIP+=-Wl,-z,now +endif + +ifeq ($(LDSO_GNU_HASH_SUPPORT),y) +# Be sure that binutils support it +LDFLAGS_GNUHASH:=$(call check_ld,--hash-style=gnu) +ifeq ($(LDFLAGS_GNUHASH),) +ifneq ($(filter-out $(clean_targets) install_headers headers-y,$(MAKECMDGOALS)),) +$(error Your binutils do not support --hash-style option, while you want to use it) +endif +else +LDFLAGS_NOSTRIP += -Wl,$(LDFLAGS_GNUHASH) +endif +endif + +LDFLAGS:=$(LDFLAGS_NOSTRIP) -Wl,-z,defs +ifeq ($(DODEBUG),y) +CFLAGS += -O0 -g3 -DDEBUG +else +CFLAGS += $(OPTIMIZATION) +endif +ifeq ($(DOSTRIP),y) +LDFLAGS += -Wl,-s +else +STRIPTOOL := true -Stripping_disabled +endif + +ifeq ($(DOMULTI),y) +# we try to compile all sources at once into an object (IMA), but +# gcc-3.3.x does not support it +# gcc-3.4.x supports it, but does not need and support --combine. though fails on many sources +# gcc-4.0.x supports it, supports the --combine flag, but does not need it +# gcc-4.1(200506xx) supports it, but needs the --combine flag, else libs are useless +ifeq ($(GCC_MAJOR_VER),3) +DOMULTI:=n +else +CFLAGS+=$(call check_gcc,--combine,) +endif +else +DOMULTI:=n +endif + +ifneq ($(strip $(UCLIBC_EXTRA_LDFLAGS)),"") +LDFLAGS += $(call qstrip,$(UCLIBC_EXTRA_LDFLAGS)) +endif + +ifeq ($(UCLIBC_HAS_THREADS),y) +ifeq ($(UCLIBC_HAS_THREADS_NATIVE),y) + PTNAME := nptl + CFLAGS += -DHAVE_FORCED_UNWIND +else +ifeq ($(LINUXTHREADS_OLD),y) + PTNAME := linuxthreads.old +else + PTNAME := linuxthreads +endif +endif +PTDIR := libpthread/$(PTNAME) +# set up system dependencies include dirs (NOTE: order matters!) +ifeq ($(UCLIBC_HAS_THREADS_NATIVE),y) +PTINC:= -I$(top_builddir)$(PTDIR) \ + -I$(top_srcdir)$(PTDIR) \ + $(if $(TARGET_ARCH),-I$(top_srcdir)$(PTDIR)/sysdeps/unix/sysv/linux/$(TARGET_ARCH)/$(TARGET_SUBARCH)) \ + -I$(top_srcdir)$(PTDIR)/sysdeps/unix/sysv/linux/$(TARGET_ARCH) \ + -I$(top_builddir)$(PTDIR)/sysdeps/$(TARGET_ARCH) \ + -I$(top_srcdir)$(PTDIR)/sysdeps/$(TARGET_ARCH) \ + -I$(top_builddir)$(PTDIR)/sysdeps/unix/sysv/linux \ + -I$(top_srcdir)$(PTDIR)/sysdeps/unix/sysv/linux \ + -I$(top_srcdir)$(PTDIR)/sysdeps/pthread \ + -I$(top_srcdir)$(PTDIR)/sysdeps/pthread/bits \ + -I$(top_srcdir)$(PTDIR)/sysdeps/generic \ + -I$(top_srcdir)ldso/ldso/$(TARGET_ARCH) \ + -I$(top_srcdir)ldso/include +# +# Test for TLS if NPTL support was selected. +# +GCC_HAS_TLS=$(shell \ + echo "extern __thread int foo;" | $(CC) -o /dev/null -S -xc - 2>&1) +ifneq ($(GCC_HAS_TLS),) +gcc_tls_test_fail: + @echo "####"; + @echo "#### Your compiler does not support TLS and you are trying to build uClibc"; + @echo "#### with NPTL support. Upgrade your binutils and gcc to versions which"; + @echo "#### support TLS for your architecture. Do not contact uClibc maintainers"; + @echo "#### about this problem."; + @echo "####"; + @echo "#### Exiting..."; + @echo "####"; + @exit 1; +endif +else +PTINC := \ + -I$(top_srcdir)$(PTDIR)/sysdeps/unix/sysv/linux/$(TARGET_ARCH) \ + -I$(top_srcdir)$(PTDIR)/sysdeps/$(TARGET_ARCH) \ + -I$(top_srcdir)$(PTDIR)/sysdeps/unix/sysv/linux \ + -I$(top_srcdir)$(PTDIR)/sysdeps/pthread \ + -I$(top_srcdir)$(PTDIR) \ + -I$(top_srcdir)libpthread +endif +CFLAGS+=$(PTINC) +else + PTNAME := + PTINC := +endif +CFLAGS += -I$(top_srcdir)libc/sysdeps/linux/common +CFLAGS += -I$(KERNEL_HEADERS) + +#CFLAGS += -iwithprefix include-fixed -iwithprefix include +CC_IPREFIX := $(shell $(CC) --print-file-name=include) +CC_INC := -isystem $(dir $(CC_IPREFIX))include-fixed -isystem $(CC_IPREFIX) +CFLAGS += $(CC_INC) + +ifneq ($(DOASSERTS),y) +CFLAGS+=-DNDEBUG +endif + +ifeq ($(SYMBOL_PREFIX),_) +CFLAGS+=-D__UCLIBC_UNDERSCORES__ +endif + +# Keep the check_as from being needlessly executed +ifndef ASFLAGS_NOEXEC +ifeq ($(UCLIBC_BUILD_NOEXECSTACK),y) +export ASFLAGS_NOEXEC := $(call check_as,--noexecstack) +else +export ASFLAGS_NOEXEC := +endif +endif +ASFLAGS = $(ASFLAGS_NOEXEC) + +LIBGCC_CFLAGS ?= $(CFLAGS) $(CPU_CFLAGS-y) +LIBGCC:=$(shell $(CC) $(LIBGCC_CFLAGS) -print-libgcc-file-name) +LIBGCC_DIR:=$(dir $(LIBGCC)) + +# moved from libpthread/linuxthreads +ifeq ($(UCLIBC_CTOR_DTOR),y) +SHARED_START_FILES:=$(top_builddir)lib/crti.o $(LIBGCC_DIR)crtbeginS.o +SHARED_END_FILES:=$(LIBGCC_DIR)crtendS.o $(top_builddir)lib/crtn.o +endif + +LOCAL_INSTALL_PATH := install_dir diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/TODO b/l4/pkg/uclibc/lib/contrib/uclibc/TODO new file mode 100644 index 00000000..b94d5415 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/TODO @@ -0,0 +1,188 @@ +TODO list for every uClibc release: +------------------------------------------------- + *) Test cris, i386, mips, mipsel, sh, x86_64, arm, armeb, and powerpc + with the latest LTP testsuite. Fix any regressions and post LTP + testsuite results for each architecture on uclibc.org. + *) Audit header files. Remove prototypes for all functions that + are not supported -- especially needed for the libm headers. + *) Audit header files. When options are disabled, also disable + them in the include files as well by checking for the proper + define from include/bits/uClibc_config.h (pulled in from features.h) + +TODO list for the uClibc 0.9.31 release: +------------------------------------------------- + *) merge NPTL + Settle cancellation + support arches: (- todo; + done) + + arm + + sh + + mips + - i386 + - x86_64 + - ... + *) Go through SUSv4 + TOC: http://www.opengroup.org/onlinepubs/9699919799/xrat/contents.html + shell (busybox): http://www.opengroup.org/onlinepubs/9699919799/xrat/V4_xcu_chap01.html#tag_22_01_01 + interface: + http://www.opengroup.org/onlinepubs/9699919799/xrat/V4_xbd_chap13.html#tag_21_13_02 + http://www.opengroup.org/onlinepubs/9699919799/xrat/V4_xsh_chap01.html#tag_23_01_01 + + +TODO list for the uClibc 0.9.29 release: +------------------------------------------------- + *) as many of the arch-specific issues as possible + *) Remove N instances of libc_hidden_proto() from uClibc internals. + Instead add internal only header(s) defining all hidden prototypes. + This will avoid clutter and guarantee prototype consistancy. + *) The __is*_l() functions were all removed, such that we now only export + the is*_l() functions (no prefix). Before, we had the prefixed versions + for use by libstdc++ and weak versions without prefixes exported because + those functions belong to no std (unless you call glibc a std). This should + be fixed. Similar problems likely were created elsewhere. + *) misc stdio bugs: + http://bugs.uclibc.org/view.php?id=420 + http://bugs.uclibc.org/view.php?id=539 + *) bug in getopt handling: + http://bugs.uclibc.org/view.php?id=61 + http://www.uclibc.org/lists/uclibc/2006-January/013851.html + *) Should integrate test subdir better ... need to propagate CPU + CFLAGS/LDFLAGS to the build/link for target binaries so that when we have + a multilib toolchain, the proper ABI is selected. + + +TODO list for the uClibc 1.0.0 release: +------------------------------------------------- + *) glob / fnmatch tests fail + *) regex should pass AT&T conformance tests + *) Finish hiding uClibc internal symbols from our exported namespace + *) Add system for generating minimal system call asm wrappers that abuse + the C ABI to minimize amount of register/stack manipulation + *) Explicity add some sortof CONFIG_LINUX_2_2_ABI, CONFIG_LINUX_2_4_ABI + and CONFIG_LINUX_2_6_ABI type options, rather than having the abi + depend on the selected set of kernel headers. This will likely also + require that we provide a set of kernel headers (probably a derivitive + of Mazur's linux-libc-headers) that can supplies the 2.2, 2.4, and 2.6 + kernel abi. + *) Documentation updates: + *) Write a uClibc HOWTO document + *) Update README document + *) Update INSTALL document + *) Update docs/Glibc_vs_uClibc_Differences.txt document + and fully document all differences between the feature + set of uClibc and glibc. + *) Update docs/uClibc_vs_SuSv3.txt document + *) Update docs/threads.txt document + *) Write man pages for ldd and ldconfig utility binaries + *) Implement some mechanism (perhaps encoded in the .so name, + perhaps using an abi tag magically embedded into each object) + for flagging config options that break the ABI. Options + such as UCLIBC_HAS_SOFT_FLOAT, UCLIBC_HAS_THREADS, UCLIBC_HAS_LOCALE, + and perhaps others (finalize list) produce a lib with a differing + ABI. Make it so apps cannot use an ABI mis-matched uClibc. + This is most easily done using symbol versioning... + *) Implement the long double versions of math funcs + using wrappers on top of the double versions (size / precision + trade off where size clearly wins). + *) Make all small objects (>~50 bytes) into either inlines or + into a static library + *) Cleanup / rewrite sysconf.c. It should get some information + from ldso (such as HZ). Other stuff it currently just makes + up, which is obviously wrong. Also bits/uClibc_clk_tck.h + needs to be updated at the same time to get proper HZ values. + *) poll emulation using select() for old 2.0.x uClinux kernels + in libc/sysdeps/linux/common/poll.c fails some python self-tests. + Of course, modern systems using the actuall poll() syscall work fine. + *) Cleanup/scrub all the Makefile copyright junk + *) Fix dlopen, for both static and dynamic cases, and make it + fully comply with SuSv3 + + +TODO list for AFTER the uClibc 1.0.0 release: +------------------------------------------------- + *) Add support for 64bit time (to deal withhttp://2038bug.com/): + date -s 011903142038 sets epoch to roll over in a few seconds (2^31) + *) Add support for Linux 2.6.x fast vsyscalls + *) Enable pristine source tree builds + *) Fix regex so it isn't so stinking big + *) Fix glob so it isn't so stinking big + *) run 'nm -D --size-sort -t d libuClibc-0.9.26.so' and work on the + biggest things (i.e. stuff at the end of the list) to make + them smaller. + + + +Arch specific TODO: +------------------------------------------------- + alpha: + ldso is not implemented + arm: + update crt1 code again for nommu (http://bugs.uclibc.org/view.php?id=538) + recruit jbowler and integrate thumb support + frv: + needs to be updated for the new ldso changes and unification of the + uClibc_main funcs (__uClibc_start_main doesnt exist anymore) + hppa: + errno.c test segfaults causes segfault in clone.S (seems to be in glibc too) + i386: + add support for fast system calls + ia64: + ldso is not implemented + m68k: + ldso lazy relocation doesnt work + sh64: + ldso is reasonably broken, presently requiring additional + coaxing/threatening. + sparc: + need a sigaction.c since common one doesnt work (signal tests) + ldso needs to be updated since it's totally broken atm + vax: + pthread support, linktime warning support (implies GAS patches), + general touchups, testing, ldso. + + +----------------------------------------------------------------------------- +Manuel's todo: + + 1) Little things that need fixing: + ---------------------------------- + a) Fix bug in *printf: outdigit precison bug + b) Check that gnu/bsd extension members tm_gmtoff and tm_zone in struct tm + are respected where they should be. + c) Implement the obstack printf funcs for glibc compat. + d) Implement glibc 'a' flag for scanf string conversions. + e) Allow use of the older non-table-based ctype functions when using + stub locale support. (smaller) + f) __drand48_iterate should be void + g) alphasort vs. versionsort. The former seems to be SVID, the latter GNU + i.e. reverse to what we currently do. The latter is unimplemented. + h) ponder removal/configs to turn off: __xpg_*, bsd_signal, dysize, + getw/putw, utimes, + + 2) Additional str{f|p}time issues. + ---------------------------------- + a) Spacing issue wrt strptime. + b) Support locale specific alternate digits. (data is in place) + c) Support locale era in year designations. (data is in place) + d) Deal with mb format string issues in strftime. + e) Implement wcsftime. + + 3) Other locale issues (my implementation): + ------------------------------------------- + a) Do a little more clean up of ctype and wctype. + b) Rework of the locale data organization to make using locales reasonable + when staticly linking. (mmap) + c) Rewrite the locale data generation tools to process the text specifications + rather than relying on glibc. + d) Adapt regex lib to use my collation data and add the necessary collating + item tables to support SUSv3 required features. + e) transliteration of unsupported wchars in 8-bit locales (like glibc). + f) Support ISO/IEC 14652 draft locale extensions (LC_PAPER, etc). + g) Implement strfrom. + h) Shift-state codeset locale support? + + 4) Misc: + -------- + a) Port uClibc to other OSs (including elks), or even bare metal (libgloss). + b) Write a space-efficient gettext substitute, to avoid storing large amounts + of redundant data. + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/docs/Glibc_vs_uClibc_Differences.txt b/l4/pkg/uclibc/lib/contrib/uclibc/docs/Glibc_vs_uClibc_Differences.txt new file mode 100644 index 00000000..ffddbae5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/docs/Glibc_vs_uClibc_Differences.txt @@ -0,0 +1,215 @@ + uClibc and Glibc are not the same -- there are a number of differences which +may or may not cause you problems. This document attempts to list these +differences and, when completed, will contain a full list of all relevant +differences. + + +1) uClibc is smaller than glibc. We attempt to maintain a glibc compatible +interface, allowing applications that compile with glibc to easily compile with +uClibc. However, we do not include _everything_ that glibc includes, and +therefore some applications may not compile. If this happens to you, please +report the failure to the uclibc mailing list, with detailed error messages. + +2) uClibc is much more configurable then glibc. This means that a developer +may have compiled uClibc in such a way that significant amounts of +functionality have been omitted. + +3) uClibc does not even attempt to ensure binary compatibility across releases. +When a new version of uClibc is released, you may or may not need to recompile +all your binaries. + +4) malloc(0) in glibc returns a valid pointer to something(!?!?) while in +uClibc calling malloc(0) returns a NULL. The behavior of malloc(0) is listed +as implementation-defined by SuSv3, so both libraries are equally correct. +This difference also applies to realloc(NULL, 0). I personally feel glibc's +behavior is not particularly safe. To enable glibc behavior, one has to +explicitly enable the MALLOC_GLIBC_COMPAT option. + +4.1) glibc's malloc() implementation has behavior that is tunable via the +MALLOC_CHECK_ environment variable. This is primarily used to provide extra +malloc debugging features. These extended malloc debugging features are not +available within uClibc. There are many good malloc debugging libraries +available for Linux (dmalloc, electric fence, valgrind, etc) that work much +better than the glibc extended malloc debugging. So our omitting this +functionality from uClibc is not a great loss. + +5) uClibc does not provide a database library (libdb). + +6) uClibc does not support NSS (/lib/libnss_*), which allows glibc to easily +support various methods of authentication and DNS resolution. uClibc only +supports flat password files and shadow password files for storing +authentication information. If you need something more complex than this, +you can compile and install pam. + +7) uClibc's libresolv is only a stub. Some, but not all of the functionality +provided by glibc's libresolv is provided internal to uClibc. Other functions +are not at all implemented. + +8) libnsl provides support for Network Information Service (NIS) which was +originally called "Yellow Pages" or "YP", which is an extension of RPC invented +by Sun to share Unix password files over the network. I personally think NIS +is an evil abomination and should not be used. These days, using ldap is much +more effective mechanism for doing the same thing. uClibc provides a stub +libnsl, but has no actual support for Network Information Service (NIS). +We therefore, also do not provide any of the headers files provided by glibc +under /usr/include/rpcsvc. + +9) uClibc's locale support is not 100% complete yet. We are working on it. + +10) uClibc's math library only supports long double as inlines, and even +then the long double support is quite limited. Also, very few of the +float math functions are implemented. Stick with double and you should +be just fine. + +11) uClibc's libcrypt does not support the reentrant crypt_r, setkey_r and +encrypt_r, since these are not required by SuSv3. + +12) uClibc directly uses kernel types to define most opaque data types. + +13) uClibc directly uses the linux kernel's arch specific 'struct stat'. + +14) uClibc's librt library currently lacks all aio routines, all clock + routines, and all shm routines (only the timer routines and the mq + routines are implemented). + + + + + +****************************** Manuel's Notes ****************************** + +Some general comments... + +The intended target for all my uClibc code is ANSI/ISO C99 and SUSv3 +compliance. While some glibc extensions are present, many will eventually +be configurable. Also, even when present, the glibc-like extensions may +differ slightly or be more restrictive than the native glibc counterparts. +They are primarily meant to be porting _aides_ and not necessarily +drop-in replacements. + +Now for some details... + +time functions +-------------- +1) Leap seconds are not supported. +2) /etc/timezone and the whole zoneinfo directory tree are not supported. + To set the timezone, set the TZ environment variable as specified in + http://www.opengroup.org/onlinepubs/007904975/basedefs/xbd_chap08.html + or you may also create an /etc/TZ file of a single line, ending with a + newline, containing the TZ setting. For example + echo CST6CDT > /etc/TZ +3) Currently, locale specific eras and alternate digits are not supported. + They are on my TODO list. + +wide char support +----------------- +1) The only multibyte encoding currently supported is UTF-8. The various + ISO-8859-* encodings are (optionally) supported. The internal + representation of wchar's is assumed to be 31 bit unicode values in + native endian representation. Also, the underlying char encoding is + assumed to match ASCII in the range 0-0x7f. +2) In the next iteration of locale support, I plan to add support for + (at least some) other multibyte encodings. + +locale support +-------------- +1) The target for support is SUSv3 locale functionality. While nl_langinfo + has been extended, similar to glibc, it only returns values for related + locale entries. +2) Currently, all SUSv3 libc locale functionality should be implemented + except for wcsftime and collating item support in regex. + +stdio +----- +1) Conversion of large magnitude floating-point values by printf suffers a loss + of precision due to the algorithm used. +2) uClibc's printf is much stricter than glibcs, especially regarding positional + args. The entire format string is parsed first and an error is returned if + a problem is detected. In locales other than C, the format string is checked + to be a valid multibyte sequence as well. Also, currently at most 10 positional + args are allowed (although this is configurable). +3) BUFSIZ is configurable, but no attempt is made at automatic tuning of internal + buffer sizes for stdio streams. In fact, the stdio code in general sacrifices + sophistication/performace for minimal size. +4) uClibc allows glibc-like custom printf functions. However, while not + currently checked, the specifier must be <= 0x7f. +5) uClibc allows glibc-like custom streams. However, no in-buffer seeking is + done. +6) The functions fcloseall() and __fpending() can behave differently than their + glibc counterparts. +7) uClibc's setvbuf is more restrictive about when it can be called than glibc's + is. The standards specify that setvbuf must occur before any other operations + take place on the stream. +8) Right now, %m is not handled properly by printf when the format uses positional + args. +9) The FILEs created by glibc's fmemopen(), open_memstream(), and fopencookie() + are not capable of wide orientation. The corresponding uClibc routines do + not have this limitation. +10) For scanf, the C99 standard states "The fscanf function returns the value of + the macro EOF if an input failure occurs before any conversion." But glibc's + scanf does not respect conversions for which assignment was surpressed, even + though the standard states that the value is converted but not stored. + +glibc bugs that Ulrich Drepper has refused to acknowledge or comment on + ( http://sources.redhat.com/ml/libc-alpha/2003-09/ ) +----------------------------------------------------------------------- +1) The C99 standard says that for printf, a %s conversion makes no special + provisions for multibyte characters. SUSv3 is even more clear, stating + that bytes are written and a specified precision is in bytes. Yet glibc + treats the arg as a multibyte string when a precision is specified and + not otherwise. +2) Both C99 and C89 state that the %c conversion for scanf reads the exact + number of bytes specified by the optional field width (or 1 if not specified). + uClibc complies with the standard. There is an argument that perhaps the + specified width should be treated as an upper bound, based on some historical + use. However, such behavior should be mentioned in the Conformance document. +3) glibc's scanf is broken regarding some numeric patterns. Some invalid + strings are accepted as valid ("0x.p", "1e", digit grouped strings). + In spite of my posting examples clearly illustrating the bugs, they remain + unacknowledged by the glibc developers. +4) glibc's scanf seems to require a 'p' exponent for hexadecimal float strings. + According to the standard, this is optional. +5) C99 requires that once an EOF is encountered, the stream should be treated + as if at end-of-file even if more data becomes available. Further reading + can be attempted by clearing the EOF flag though, via clearerr() or a file + positioning function. For details concerning the original change, see + Defect Report #141. glibc is currently non-compliant, and the developers + did not comment when I asked for their official position on this issue. +6) glibc's collation routines and/or localedef are broken regarding implicit + and explicit UNDEFINED rules. + +More to follow as I think of it... + + + + +Profiling: +------------------------------------------------------------------- + +uClibc no longer supports 'gcc -fprofile-arcs -pg' style profiling, which +causes your application to generate a 'gmon.out' file that can then be analyzed +by 'gprof'. Not only does this require explicit extra support in uClibc, it +requires that you rebuild everything with profiling support. There is both a +size and performance penalty to profiling your applications this way, as well +as Heisenberg effects, where the act of measuring changes what is measured. + +There exist a number of less invasive alternatives that do not require you to +specially instrument your application, and recompile and relink everything. + +The OProfile system-wide profiler is an excellent alternative: + http://oprofile.sourceforge.net/ + +Many people have had good results using the combination of Valgrind +to generate profiling information and KCachegrind for analysis: + http://developer.kde.org/~sewardj/ + http://kcachegrind.sourceforge.net/ + +Prospect is another alternative based on OProfile: + http://prospect.sourceforge.net/ + +And the Linux Trace Toolkit (LTT) is also a fine tool: + http://www.opersys.com/LTT/ + +FunctionCheck: + http://www710.univ-lyon1.fr/~yperret/fnccheck/ + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/docs/PORTING b/l4/pkg/uclibc/lib/contrib/uclibc/docs/PORTING new file mode 100644 index 00000000..cadb3231 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/docs/PORTING @@ -0,0 +1,138 @@ +Some notes to help future porters. Replace 'ARCH' with whatever arch +you are hacking on. + +==================== +=== Config Files === +==================== +- create extra/Configs/Config.ARCH + See the other arch files for some good examples. powerpc/sparc/alpha + should be pretty simple templates. +- add ARCH to the 'Target Architecture' list in extra/Configs/Config.in +- Initially you will want to disable shared libraries, since making + the shared library loader work requires you first have basic architecture + support working. Thus you should add ARCH_HAS_NO_SHARED and + ARCH_HAS_NO_LDSO to Config.ARCH's TARGET_ARCH + +==================== +=== libc sysdeps === +==================== +(note: if glibc has already been ported to your arch, you can usually just + copy a lot of files from them rather than coding from scratch) +- create libc/sysdeps/linux/ARCH +- copy Makefile and Makefile.arch from libc/sysdeps/linux/i386/ +- set CSRC and SSRC to nothing in Makefile.arch for now + +- create crt1.S which defines the _start function ... you will probably want + to clear the frame pointer to make gdb happy, and then you will want to call + the funcion __uClibc_main() which takes these parameters: + __uClibc_main(main(), argc, argv, _init(), _fini()) + Initially if you wish to make things easier on yourself, you can disable the + UCLIBC_CTOR_DTOR option and just set the init/fini arguments to NULL. + glibc generally stores this function in libc/sysdeps/ARCH/elf/start.S + +- create these additional files in ARCH/bits/ + + (template versions can be found in common/bits/ for you to tweak) + endian.h fcntl.h setjmp.h stackinfo.h uClibc_arch_features.h wordsize.h + + kernel_types.h should be created based upon linux asm-ARCH/posix_types.h + + copy linux asm-ARCH/stat.h to bits/kernel_stat.h + + create syscalls.h based upon linux's unistd.h / glibc's sysdeps.h ... really + you just want to define the _syscall[0-6] macros. It is important that + these syscalls should be PIC safe (or you should provide a PIC and non-PIC + version) if you wish to properly support shared libraries. + +- at this point, you should have enough to generate a working HELLO WORLD + static binary (see test/silly/*.c files) + +- if you want UCLIBC_CTOR_DTOR support, you will need to create crti.S and + crtn.S files which define function prologues/epilogues. + +- for a more stable static port, you will need to create these files (and + update the Makefile.arch values accordingly) + __longjmp bsd-_setjmp bsd-setjmp brk clone setjmp syscall vfork + usually these are written in assembler, but you may be able to cheat and + write them in C ... see other ports for more information + +==================== +=== pthread deps === +==================== + +TODO: nptl / linuxthreads / linuxthreads.old + +==================== +=== ldso sysdeps === +==================== +- elf.h - presumably you've already taught binutils all about the random ELF + relocations your arch needs, so now you need to make sure the defines exist + for uClibc. make sure the EM_### define exists and all of the R_###_### + reloc defines. + +- enable ldso/shared options in your extra/Configs/Config.ARCH file +- you will need to create the following files in ldso/ldso/ARCH/ + dl-debug.h dl-startup.h dl-syscalls.h dl-sysdep.h elfinterp.c resolve.S + +- dl-debug.h: define string versions of all the relocations of your arch in the + _dl_reltypes_tab array ... the index should match the actual reloc type, so + if the value of say R_X86_64_PC16 is 13, then "R_X86_64_PC16" better be at + index 13 of the array + +- dl-startup.h: + - define the _start function which should call _dl_start which takes just one + parameter ... a pointer to argc (usually on the stack) + glibc stores this function in libc/sysdeps/ARCH/dl-machine.h as RTLD_START + - define the GET_ARGV() macro which calculates the value of argv based upon + the parameter passed to _dl_start (usually it's simply just ARGS+1) + - define PERFORM_BOOTSTRAP_RELOC() macro which will handle just the relocs + that the ldso itself will generate + +- dl-syscalls.h: + if you wrote your bits/syscalls.h file correctly in the libc step above, you + can simply copy this file from another arch and be done ... otherwise you + will have to define the syscall[0-6] macros again, but this time setting + _dl_errno instead of just errno + +- dl-sysdep.h: + misc cruft goes in here ... you want to: + - either define or undefine ELF_USES_RELOCA + - define the INIT_GOT macro + - define MAGIC1 to the EM_### value your ELF arch uses + - define ELF_TARGET to a string name for your arch + - define the do_rem() macro + - define misc ALIGN macro's + - define elf_machine_type_class() macro + - define the inline functions elf_machine_dynamic, elf_machine_load_address, + and elf_machine_relative + glibc stores a bunch of these values in libc/sysdeps/ARCH/dl-machine.h + +- elfinterp.c: + define all the relocation functions ... it's best if you just copy from + another arch which uses the same type of relocations (REL or RELA) and + start from there. + +- resolve.S: + front end of lazy relocation ... define the _dl_linux_resolve symbol which + is called by a PLT entry which has yet to be setup ... you will want to: + - set up arguments for _dl_linux_resolver() + - call _dl_linux_resolver() + - clean up after call + - jump to function address now stored in PLT + glibc stores this function in libc/sysdeps/ARCH/dl-trampoline.S + +- utils/ldd.c - if you want support for ldso cache files (spoiler: you do), + then you'll need to teach ldd a little. generally, the fallback code + should be smart and "just work", but you should be explicit. just pop + it open and add an appropriate ifdef for your arch and set MATCH_MACHINE() + and ELFCLASSM. there are plenty examples and you're (hopefully) smart. + +==================== +=== Misc Cruft === +==================== +- utils/readelf.c - not really needed generally speaking, but might as well + add your arch to the giant EM_* list (describe_elf_hdr) + +- MAINTAINERS - presumably you're going to submit this code back to mainline + and since you're the only one who cares about this arch (right now), you + should add yourself to the toplevel MAINTAINERS file. do it. diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/docs/defines.txt b/l4/pkg/uclibc/lib/contrib/uclibc/docs/defines.txt new file mode 100644 index 00000000..6e4a6048 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/docs/defines.txt @@ -0,0 +1,85 @@ +Feeble attempt to document the horde of #defines we deal with. +Editors, please make your descriptions short but informative. + + + +__BEGIN_DECLS, __END_DECLS + Defined to either empty or 'extern "C" {' and '}' if included by C++. + +__USE_GNU, __USE_BSD, __USE_XOPEN[2K], __USE_SVID, __USE_POSIX... + If defined, user program which included us requests compat additions + from relevant standard or Unix flavor. See features.h for full list. + +__USE_FILE_OFFSET64 +__USE_LARGEFILE[64] +_LARGEFILE[64]_SOURCE +_FILE_OFFSET_BITS + ??? + +__THROW + Function annotation "I do not throw anything". +__NTH(func(params)) + Function annotation "I do not throw anything". + Needed for situatuons when it's unclear on what side of "func(params)" + the "throw()" or "attribute((nothrow))" should eventually appear. + Messy, eh? + +return_type __REDIRECT(name, (params), alias) + declare alias to "name(params)" +return_type __REDIRECT_NTH(name, (params), alias) + declare alias to "name(params) __THROW" + +__BIG_ENDIAN 4321 +__LITTLE_ENDIAN 1234 + Should be always as shown. __PDP_ENDIAN is historic, ignore? +__BYTE_ORDER, __FLOAT_WORD_ORDER + Should be defined to __BIG_ENDIAN or __LITTLE_ENDIAN. + Usage: "#if __BYTE_ORDER == __LITTLE_ENDIAN ..." + __USE_BSD adds versions without leading "__" for above four defines. +_BIG_ENDIAN, __BIG_ENDIAN__ +_LITTLE_ENDIAN, __LITTLE_ENDIAN__ + Defined (to what?) by gcc for some architectures to indicate endianness. + Seems that the fact of defined-ness is an indicator, not the value. + +__USE_EXTERN_INLINES + If defined, headers will supply some function as inlines. + uclibc itself is built with this option off and provides + out-of-line version of every inlined function in case user program + calls it instead of using an inline. +_EXTERN_INLINE + If not defined by user prior to #include, will be defined to + "extern inline" or equivalent. IOW, if user defines it prior + #include, it replaces "extern __inline" string in inline definitions + (those enabled by __USE_EXTERN_INLINES) with something else. + A few uclibc .c files use it to create non-inlined functions + by defining it to "". +__extern_inline + Defined to "extern inline", modulo gcc/C standard deviations. + Can't be used by user to play tricks as with _EXTERN_INLINE. + +internal_function + Used to modify function's calling convention, if "standard" one + is suboptimal. Examples: + int func(params) internal_function; + int internal_function func(params) { body } + +_LIBC + Defined only at libc build time. It is physically deleted +from the headers (using unifdef tool) in installed headers ("make install"). + +__UCLIBC_XXX + uclibc-internal and uclibc-specific defines. In particular: +__UCLIBC_HAS_XXX__, __UCLIBC_HAVE_XXX__ + __UCLIBC_HAS_XXX__ are booleans (defined/undefined), defined in + uClibc_config.h and generated from uclibc .config file. + __UCLIBC_HAVE_XXX__ are booleans from bits/uClibc_arch_features.h + (there are more __UCLIBC_XXX defines there) + +_IEEE_LIBM + Always defined at libm build time +__LDBL_COMPAT + Never defined, TODO: remove? + +__SSP_ALL__ + All functions, even small ones, have stack smashing protection + prologue enabled. diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/docs/man/ldconfig.8 b/l4/pkg/uclibc/lib/contrib/uclibc/docs/man/ldconfig.8 new file mode 100644 index 00000000..208d63df --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/docs/man/ldconfig.8 @@ -0,0 +1,73 @@ +.TH LDCONFIG 8 2005-08-15 uClibc "Linux Programmer's Manual" +.SH NAME +ldconfig \- updates symlinks and cache for shared libraries +.SH SYNOPSIS +.B ldconfig +[ +.B -DvqnNX +] [ +.B -f conf +] [ +.B -C cache +] [ +.B -r root +] +.B dir ... +.br +.B ldconfig -l +[ +.B -Dv +] +.B lib ... +.br +.B ldconfig -p +.SH DESCRIPTION +.B ldconfig +creates the necessary links and cache to the most recent shared libraries +found in the directories specified on the command line, in the file +\fI/etc/ld.so.conf\fR, and in the default trusted directories (\fI/lib\fR and +\fI/usr/lib\fR). The cache is used by the run-time linker. +.B ldconfig +checks the header and file names of the libraries it encounters when +determining which versions should have their links updated. + +.B Note: +Some features may not exist depending on how uClibc was built +.SH OPTIONS +.TP +.B -C cache +use specified \fIcache\fR instead of default +.TP +.B -D +debug mode, do not update links +.TP +.B -f conf +use specified \fIconf\fR instead of default +.TP +.B -l +library mode, manually link libraries +.TP +.B -n +do not process standard trusted directories +.TP +.B -N +do not update the library cache +.TP +.B -p +print the current library cache +.TP +.B -q +quiet mode, do not print warnings you should actually be reading +.TP +.B -r root +chroot to \fIroot\fR before running +.TP +.B -v +verbose mode, print things as we go, and generally be annoying +.TP +.B -X +do not update the library links +.SH BUGS +Probably, make sure you complain when you find them: +.br +http://bugs.uclibc.org/ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/docs/man/ldd.1 b/l4/pkg/uclibc/lib/contrib/uclibc/docs/man/ldd.1 new file mode 100644 index 00000000..0b69f730 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/docs/man/ldd.1 @@ -0,0 +1,17 @@ +.TH LDD 1 2005-08-15 uClibc "Linux Programmer's Manual" +.SH NAME +ldd \- Print shared library dependencies +.SH SYNOPSIS +.B ldd +[ +.B OPTIONS +] +.B FILE ... +.SH DESCRIPTION +Prints shared library dependencies. +.SH OPTIONS +None actually, we lied about that part. +.SH BUGS +Probably, make sure you complain when you find them: +.br +http://bugs.uclibc.org/ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/docs/probe_math_exception.c b/l4/pkg/uclibc/lib/contrib/uclibc/docs/probe_math_exception.c new file mode 100644 index 00000000..dbc9020d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/docs/probe_math_exception.c @@ -0,0 +1,64 @@ +/* Small test program for probing how various math functions + * with specific operands set floating point exceptions + */ + +#define _ISOC99_SOURCE 1 +#define _GNU_SOURCE 1 + +#include +#include +#include +#include + +int main(int argc, char **argv) +{ + float largest, small, t, inf_float; + + largest = small = 1; + while (1) { + t = largest + small; + /* optimizations may make plain "t == largest" unreliable */ + if (memcmp(&t, &largest, sizeof(float)) == 0) + break; + if (isfinite(t)) { + largest = t; + small *= 2; + continue; + } + small /= 2; + } + inf_float = largest + largest; + //printf("%.40g ", largest); + //printf("[%llx]\n", (long long) (*(uint32_t *)&largest)); + + feclearexcept(FE_ALL_EXCEPT); + + //t = 1.0 / 0.0; // simple test: FE_DIVBYZERO + //t = nextafterf(largest, 1); // glibc 2.8: no math exceptions raised + //t = nextafterf(largest, largest); // glibc 2.8: no math exceptions raised + //t = nextafterf(largest, inf_float); // glibc 2.8: FE_INEXACT FE_OVERFLOW + +#define PREX(ex) do { if (fetestexcept(ex)) printf(#ex " "); } while(0) +#ifdef FE_INEXACT + PREX(FE_INEXACT); +#endif +#ifdef FE_DIVBYZERO + PREX(FE_DIVBYZERO); +#endif +#ifdef FE_UNDERFLOW + PREX(FE_UNDERFLOW); +#endif +#ifdef FE_OVERFLOW + PREX(FE_OVERFLOW); +#endif +#ifdef FE_INVALID + PREX(FE_INVALID); +#endif + if (fetestexcept(FE_ALL_EXCEPT)) + printf("\n"); + else + printf("no math exceptions raised\n"); + + printf("%.40g\n", t); + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/docs/pthreads_hacking.txt b/l4/pkg/uclibc/lib/contrib/uclibc/docs/pthreads_hacking.txt new file mode 100644 index 00000000..6c23257d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/docs/pthreads_hacking.txt @@ -0,0 +1,748 @@ +# Run me as a shell script in uclibc lib/* + + +# Dump the list of dynamic symbols from libpthread +# and compare libpthread's exported symbols of uclibc with glibc +# (adjust /lib64/libpthread-*.*.so as needed). +# The resulting diff is suspiciously large. +# We export a lot of stuff which glibc does not. + +readelf -sDW libpthread-*.*.so \ +| grep '^ *[0-9]' \ +| sed 's/^[0-9a-f: ]*[^ ]\( *[A-Z]\)/\1/' \ +| sed 's/ [0-9] / N /' | sed 's/ [0-9][0-9] / N /' | sed 's/ [0-9][0-9][0-9] / N /' \ +| sort -k5 | uniq \ +>uclibc.lst + +readelf -sDW /lib64/libpthread-*.*.so \ +| grep '^ *[0-9]' \ +| sed 's/^[0-9a-f: ]*[^ ]\( *[A-Z]\)/\1/' \ +| sed 's/ [0-9] / N /' | sed 's/ [0-9][0-9] / N /' | sed 's/ [0-9][0-9][0-9] / N /' \ +| sort -k5 | uniq \ +>glibc.lst +diff -u uclibc.lst glibc.lst >ug.diff + + +# Check which exported symbols from libpthread are never referenced +# from other libraries. Generally, I'd expect a very few __functions +# with two underscores to be exported and not used by e.g. libc-X.X.X.so, +# as these names are supposed to be internal, i.e. external programs +# usually don't call them. On my system, I got 141 such __functions. +# Examples: +# __flockfilelist - NOP function (why do we need it at all?) +# __pthread_perform_cleanup - called only from within libpthread + +echo *-*.*.*.so | xargs -n1 | grep -v libpthread | xargs readelf -aW >full_dump.lst +>uclibc_unrefd.lst +>uclibc_refd.lst +sed 's/^.* //g' uclibc.lst \ +| while read symbol; do + if grep -F -- "$symbol" full_dump.lst >/dev/null 2>&1; then + echo "$symbol" >>uclibc_refd.lst + else + echo "$symbol" >>uclibc_unrefd.lst + fi +done + +exit + + +In case you don't have a glibc system to try it, +ug.diff from vda's system is below. + +--- uclibc.lst 2009-03-16 03:07:58.000000000 +0100 ++++ glibc.lst 2009-03-16 03:07:58.000000000 +0100 +@@ -1,188 +1,173 @@ +- NOTYPE GLOBAL DEFAULT ABS __bss_start +- FUNC GLOBAL DEFAULT N __compare_and_swap ++ OBJECT GLOBAL DEFAULT ABS GLIBC_2.2.5 ++ OBJECT GLOBAL DEFAULT ABS GLIBC_2.2.6 ++ OBJECT GLOBAL DEFAULT ABS GLIBC_2.3.2 ++ OBJECT GLOBAL DEFAULT ABS GLIBC_2.3.3 ++ OBJECT GLOBAL DEFAULT ABS GLIBC_2.3.4 ++ OBJECT GLOBAL DEFAULT ABS GLIBC_2.4 ++ OBJECT GLOBAL DEFAULT ABS GLIBC_PRIVATE ++ FUNC GLOBAL DEFAULT N _IO_flockfile ++ FUNC GLOBAL DEFAULT N _IO_ftrylockfile ++ FUNC GLOBAL DEFAULT N _IO_funlockfile ++ NOTYPE WEAK DEFAULT UND _Jv_RegisterClasses ++ FUNC GLOBAL DEFAULT UND __clone ++ FUNC WEAK DEFAULT N __close ++ FUNC WEAK DEFAULT N __connect ++ FUNC WEAK DEFAULT UND __cxa_finalize ++ FUNC GLOBAL DEFAULT UND __endmntent + FUNC GLOBAL DEFAULT N __errno_location +- FUNC GLOBAL DEFAULT N __flockfilelist +- FUNC GLOBAL DEFAULT N __fresetlockfiles +- FUNC GLOBAL DEFAULT N __funlockfilelist ++ FUNC WEAK DEFAULT N __fcntl ++ FUNC GLOBAL DEFAULT N __fork ++ FUNC GLOBAL DEFAULT UND __fxstat64 ++ FUNC GLOBAL DEFAULT UND __getdelim ++ FUNC GLOBAL DEFAULT UND __getmntent_r ++ FUNC GLOBAL DEFAULT UND __getpagesize ++ FUNC GLOBAL DEFAULT UND __gettimeofday + FUNC GLOBAL DEFAULT N __h_errno_location +- FUNC GLOBAL DEFAULT N __linuxthreads_create_event +- FUNC GLOBAL DEFAULT N __linuxthreads_death_event +- OBJECT GLOBAL DEFAULT N __linuxthreads_initial_report_events +- OBJECT GLOBAL DEFAULT N __linuxthreads_pthread_key_2ndlevel_size +- OBJECT GLOBAL DEFAULT N __linuxthreads_pthread_keys_max +- OBJECT GLOBAL DEFAULT N __linuxthreads_pthread_sizeof_descr +- OBJECT GLOBAL DEFAULT N __linuxthreads_pthread_threads_max +- FUNC GLOBAL DEFAULT N __linuxthreads_reap_event +- OBJECT GLOBAL DEFAULT N __linuxthreads_version +- FUNC GLOBAL DEFAULT N __pthread_alt_lock +- FUNC GLOBAL DEFAULT N __pthread_alt_timedlock +- FUNC GLOBAL DEFAULT N __pthread_alt_unlock +- FUNC GLOBAL DEFAULT N __pthread_attr_destroy +- FUNC GLOBAL DEFAULT N __pthread_attr_getdetachstate +- FUNC GLOBAL DEFAULT N __pthread_attr_getguardsize +- FUNC GLOBAL DEFAULT N __pthread_attr_getinheritsched +- FUNC GLOBAL DEFAULT N __pthread_attr_getschedparam +- FUNC GLOBAL DEFAULT N __pthread_attr_getschedpolicy +- FUNC GLOBAL DEFAULT N __pthread_attr_getscope +- FUNC GLOBAL DEFAULT N __pthread_attr_getstack +- FUNC GLOBAL DEFAULT N __pthread_attr_getstacksize +- FUNC GLOBAL DEFAULT N __pthread_attr_init +- FUNC GLOBAL DEFAULT N __pthread_attr_setdetachstate +- FUNC GLOBAL DEFAULT N __pthread_attr_setguardsize +- FUNC GLOBAL DEFAULT N __pthread_attr_setinheritsched +- FUNC GLOBAL DEFAULT N __pthread_attr_setschedparam +- FUNC GLOBAL DEFAULT N __pthread_attr_setschedpolicy +- FUNC GLOBAL DEFAULT N __pthread_attr_setscope +- FUNC GLOBAL DEFAULT N __pthread_attr_setstack +- FUNC GLOBAL DEFAULT N __pthread_attr_setstacksize +- FUNC GLOBAL DEFAULT N __pthread_barrierattr_getpshared +- FUNC GLOBAL DEFAULT N __pthread_compare_and_swap +- FUNC GLOBAL DEFAULT N __pthread_cond_broadcast +- FUNC GLOBAL DEFAULT N __pthread_cond_destroy +- FUNC GLOBAL DEFAULT N __pthread_cond_init +- FUNC GLOBAL DEFAULT N __pthread_cond_signal +- FUNC GLOBAL DEFAULT N __pthread_cond_timedwait +- FUNC GLOBAL DEFAULT N __pthread_cond_wait +- FUNC GLOBAL DEFAULT N __pthread_condattr_destroy +- FUNC GLOBAL DEFAULT N __pthread_condattr_init +- FUNC GLOBAL DEFAULT N __pthread_create +- FUNC GLOBAL DEFAULT N __pthread_destroy_specifics +- FUNC GLOBAL DEFAULT N __pthread_do_exit +- FUNC GLOBAL DEFAULT N __pthread_equal +- FUNC GLOBAL DEFAULT N __pthread_exit +- OBJECT GLOBAL DEFAULT N __pthread_exit_code +- OBJECT GLOBAL DEFAULT N __pthread_exit_requested +- FUNC GLOBAL DEFAULT N __pthread_find_self +- OBJECT GLOBAL DEFAULT N __pthread_functions +- FUNC GLOBAL DEFAULT N __pthread_getconcurrency +- FUNC GLOBAL DEFAULT N __pthread_getschedparam +- FUNC WEAK DEFAULT N __pthread_getspecific +- OBJECT GLOBAL DEFAULT N __pthread_handles +- OBJECT GLOBAL DEFAULT N __pthread_handles_num +- OBJECT GLOBAL DEFAULT N __pthread_has_cas +- FUNC GLOBAL DEFAULT N __pthread_init_max_stacksize +- OBJECT GLOBAL DEFAULT N __pthread_initial_thread +- OBJECT GLOBAL DEFAULT N __pthread_initial_thread_bos +- FUNC GLOBAL DEFAULT N __pthread_initialize +- FUNC GLOBAL DEFAULT N __pthread_initialize_manager ++ FUNC GLOBAL DEFAULT N __libc_allocate_rtsig ++ FUNC GLOBAL DEFAULT UND __libc_allocate_rtsig_private ++ FUNC GLOBAL DEFAULT N __libc_current_sigrtmax ++ FUNC GLOBAL DEFAULT UND __libc_current_sigrtmax_private ++ FUNC GLOBAL DEFAULT N __libc_current_sigrtmin ++ FUNC GLOBAL DEFAULT UND __libc_current_sigrtmin_private ++ FUNC GLOBAL DEFAULT UND __libc_dl_error_tsd ++ FUNC GLOBAL DEFAULT UND __libc_dlopen_mode ++ FUNC GLOBAL DEFAULT UND __libc_dlsym ++ FUNC GLOBAL DEFAULT UND __libc_fatal ++ FUNC GLOBAL DEFAULT UND __libc_fork ++ FUNC GLOBAL DEFAULT UND __libc_longjmp ++ FUNC GLOBAL DEFAULT UND __libc_pthread_init ++ OBJECT GLOBAL DEFAULT UND __libc_stack_end ++ FUNC GLOBAL DEFAULT UND __libc_system ++ FUNC GLOBAL DEFAULT UND __libc_thread_freeres ++ FUNC WEAK DEFAULT N __lseek ++ FUNC WEAK DEFAULT N __nanosleep ++ FUNC WEAK DEFAULT N __open ++ FUNC WEAK DEFAULT N __open64 ++ FUNC WEAK DEFAULT N __pread64 ++ FUNC GLOBAL DEFAULT N __pthread_cleanup_routine ++ FUNC GLOBAL DEFAULT N __pthread_clock_gettime ++ FUNC GLOBAL DEFAULT N __pthread_clock_settime ++ FUNC GLOBAL DEFAULT N __pthread_getspecific + FUNC GLOBAL DEFAULT N __pthread_initialize_minimal +- FUNC GLOBAL DEFAULT N __pthread_internal_tsd_address +- FUNC GLOBAL DEFAULT N __pthread_internal_tsd_get +- FUNC GLOBAL DEFAULT N __pthread_internal_tsd_set +- FUNC WEAK DEFAULT N __pthread_key_create +- FUNC GLOBAL DEFAULT N __pthread_kill_other_threads_np +- OBJECT GLOBAL DEFAULT N __pthread_last_event +- FUNC GLOBAL DEFAULT N __pthread_lock +- OBJECT GLOBAL DEFAULT N __pthread_main_thread +- FUNC GLOBAL DEFAULT N __pthread_manager +- FUNC GLOBAL DEFAULT N __pthread_manager_adjust_prio +- FUNC GLOBAL DEFAULT N __pthread_manager_event +- OBJECT GLOBAL DEFAULT N __pthread_manager_reader +- OBJECT GLOBAL DEFAULT N __pthread_manager_request +- FUNC GLOBAL DEFAULT N __pthread_manager_sighandler +- OBJECT GLOBAL DEFAULT N __pthread_manager_thread +- OBJECT GLOBAL DEFAULT N __pthread_manager_thread_bos +- OBJECT GLOBAL DEFAULT N __pthread_manager_thread_tos +- OBJECT GLOBAL DEFAULT N __pthread_max_stacksize +- FUNC WEAK DEFAULT N __pthread_mutex_destroy +- FUNC WEAK DEFAULT N __pthread_mutex_init +- FUNC WEAK DEFAULT N __pthread_mutex_lock +- FUNC GLOBAL DEFAULT N __pthread_mutex_timedlock +- FUNC WEAK DEFAULT N __pthread_mutex_trylock +- FUNC WEAK DEFAULT N __pthread_mutex_unlock +- FUNC WEAK DEFAULT N __pthread_mutexattr_destroy +- FUNC GLOBAL DEFAULT N __pthread_mutexattr_getkind_np +- FUNC GLOBAL DEFAULT N __pthread_mutexattr_getpshared +- FUNC GLOBAL DEFAULT N __pthread_mutexattr_gettype +- FUNC WEAK DEFAULT N __pthread_mutexattr_init +- FUNC GLOBAL DEFAULT N __pthread_mutexattr_setkind_np +- FUNC GLOBAL DEFAULT N __pthread_mutexattr_setpshared +- FUNC WEAK DEFAULT N __pthread_mutexattr_settype +- OBJECT GLOBAL DEFAULT N __pthread_nonstandard_stacks +- FUNC GLOBAL DEFAULT N __pthread_null_sighandler +- OBJECT GLOBAL DEFAULT N __pthread_offsetof_descr +- OBJECT GLOBAL DEFAULT N __pthread_offsetof_pid +- FUNC WEAK DEFAULT N __pthread_once +- FUNC GLOBAL DEFAULT N __pthread_once_fork_child +- FUNC GLOBAL DEFAULT N __pthread_once_fork_parent +- FUNC GLOBAL DEFAULT N __pthread_once_fork_prepare +- FUNC GLOBAL DEFAULT N __pthread_perform_cleanup +- FUNC GLOBAL DEFAULT N __pthread_raise +- FUNC GLOBAL DEFAULT N __pthread_reset_main_thread +- FUNC GLOBAL DEFAULT N __pthread_restart_new +- FUNC WEAK DEFAULT N __pthread_rwlock_destroy +- FUNC WEAK DEFAULT N __pthread_rwlock_init +- FUNC WEAK DEFAULT N __pthread_rwlock_rdlock +- FUNC GLOBAL DEFAULT N __pthread_rwlock_timedrdlock +- FUNC GLOBAL DEFAULT N __pthread_rwlock_timedwrlock +- FUNC WEAK DEFAULT N __pthread_rwlock_tryrdlock +- FUNC WEAK DEFAULT N __pthread_rwlock_trywrlock +- FUNC WEAK DEFAULT N __pthread_rwlock_unlock +- FUNC WEAK DEFAULT N __pthread_rwlock_wrlock +- FUNC GLOBAL DEFAULT N __pthread_rwlockattr_destroy +- FUNC GLOBAL DEFAULT N __pthread_self +- FUNC GLOBAL DEFAULT N __pthread_setcancelstate +- FUNC GLOBAL DEFAULT N __pthread_setcanceltype +- FUNC GLOBAL DEFAULT N __pthread_setconcurrency +- FUNC GLOBAL DEFAULT N __pthread_setschedparam +- FUNC WEAK DEFAULT N __pthread_setspecific +- OBJECT GLOBAL DEFAULT N __pthread_sig_cancel +- OBJECT GLOBAL DEFAULT N __pthread_sig_debug +- OBJECT GLOBAL DEFAULT N __pthread_sig_restart +- FUNC GLOBAL DEFAULT N __pthread_sigaction +- FUNC GLOBAL DEFAULT N __pthread_sighandler +- FUNC GLOBAL DEFAULT N __pthread_sighandler_rt +- FUNC GLOBAL DEFAULT N __pthread_sigwait +- OBJECT GLOBAL DEFAULT N __pthread_sizeof_handle +- OBJECT GLOBAL DEFAULT N __pthread_smp_kernel +- FUNC GLOBAL DEFAULT N __pthread_spin_destroy +- FUNC GLOBAL DEFAULT N __pthread_spin_init +- FUNC GLOBAL DEFAULT N __pthread_spin_lock +- FUNC GLOBAL DEFAULT N __pthread_spin_trylock +- FUNC GLOBAL DEFAULT N __pthread_spin_unlock +- FUNC GLOBAL DEFAULT N __pthread_thread_self +- OBJECT GLOBAL DEFAULT N __pthread_threads_debug +- OBJECT GLOBAL DEFAULT N __pthread_threads_events +- OBJECT GLOBAL DEFAULT N __pthread_threads_max +- FUNC GLOBAL DEFAULT N __pthread_timedsuspend_new +- FUNC GLOBAL DEFAULT N __pthread_unlock +- FUNC GLOBAL DEFAULT N __pthread_wait_for_restart_signal +- FUNC GLOBAL DEFAULT N __register_atfork ++ FUNC GLOBAL DEFAULT N __pthread_key_create ++ FUNC GLOBAL DEFAULT N __pthread_mutex_destroy ++ FUNC GLOBAL DEFAULT N __pthread_mutex_init ++ FUNC GLOBAL DEFAULT N __pthread_mutex_lock ++ FUNC GLOBAL DEFAULT N __pthread_mutex_trylock ++ FUNC GLOBAL DEFAULT N __pthread_mutex_unlock ++ FUNC GLOBAL DEFAULT N __pthread_mutexattr_destroy ++ FUNC GLOBAL DEFAULT N __pthread_mutexattr_init ++ FUNC GLOBAL DEFAULT N __pthread_mutexattr_settype ++ FUNC GLOBAL DEFAULT N __pthread_once ++ FUNC GLOBAL DEFAULT N __pthread_register_cancel ++ FUNC GLOBAL DEFAULT N __pthread_register_cancel_defer ++ FUNC GLOBAL DEFAULT N __pthread_rwlock_destroy ++ FUNC GLOBAL DEFAULT N __pthread_rwlock_init ++ FUNC GLOBAL DEFAULT N __pthread_rwlock_rdlock ++ FUNC GLOBAL DEFAULT N __pthread_rwlock_tryrdlock ++ FUNC GLOBAL DEFAULT N __pthread_rwlock_trywrlock ++ FUNC GLOBAL DEFAULT N __pthread_rwlock_unlock ++ FUNC GLOBAL DEFAULT N __pthread_rwlock_wrlock ++ FUNC GLOBAL DEFAULT N __pthread_setspecific ++ FUNC GLOBAL DEFAULT N __pthread_unregister_cancel ++ FUNC GLOBAL DEFAULT N __pthread_unregister_cancel_restore ++ FUNC GLOBAL DEFAULT N __pthread_unwind ++ FUNC GLOBAL DEFAULT N __pthread_unwind_next ++ FUNC WEAK DEFAULT N __pwrite64 ++ FUNC WEAK DEFAULT N __read ++ FUNC GLOBAL DEFAULT UND __register_atfork ++ FUNC GLOBAL DEFAULT N __res_state ++ TLS GLOBAL DEFAULT UND __resp ++ FUNC GLOBAL DEFAULT UND __sched_getparam ++ FUNC GLOBAL DEFAULT UND __sched_getscheduler ++ FUNC GLOBAL DEFAULT UND __sched_setscheduler ++ FUNC WEAK DEFAULT N __send ++ FUNC GLOBAL DEFAULT UND __setmntent + FUNC GLOBAL DEFAULT N __sigaction +- OBJECT GLOBAL DEFAULT N __sighandler +- NOTYPE GLOBAL DEFAULT ABS _edata +- NOTYPE GLOBAL DEFAULT ABS _end +- FUNC GLOBAL DEFAULT N _fini +- FUNC GLOBAL DEFAULT N _init ++ FUNC GLOBAL DEFAULT UND __statfs ++ FUNC GLOBAL DEFAULT UND __sysconf ++ FUNC GLOBAL DEFAULT UND __tls_get_addr ++ OBJECT GLOBAL DEFAULT UND __vdso_clock_gettime ++ FUNC GLOBAL DEFAULT N __vfork ++ FUNC WEAK DEFAULT N __wait ++ FUNC WEAK DEFAULT N __write ++ FUNC GLOBAL DEFAULT UND _dl_allocate_tls ++ FUNC GLOBAL DEFAULT UND _dl_allocate_tls_init ++ FUNC GLOBAL DEFAULT UND _dl_deallocate_tls ++ FUNC GLOBAL DEFAULT UND _dl_get_tls_static_info ++ FUNC GLOBAL DEFAULT UND _dl_make_stack_executable ++ FUNC GLOBAL DEFAULT UND _exit + FUNC GLOBAL DEFAULT N _pthread_cleanup_pop + FUNC GLOBAL DEFAULT N _pthread_cleanup_pop_restore + FUNC GLOBAL DEFAULT N _pthread_cleanup_push + FUNC GLOBAL DEFAULT N _pthread_cleanup_push_defer +- FUNC GLOBAL DEFAULT N compare_and_swap_is_available +- FUNC GLOBAL DEFAULT N get_eflags ++ OBJECT GLOBAL DEFAULT UND _rtld_global ++ FUNC GLOBAL DEFAULT UND _setjmp ++ FUNC GLOBAL DEFAULT UND abort ++ FUNC WEAK DEFAULT N accept ++ FUNC GLOBAL DEFAULT UND calloc ++ FUNC WEAK DEFAULT N close ++ FUNC WEAK DEFAULT N connect ++ TLS GLOBAL DEFAULT UND errno ++ FUNC GLOBAL DEFAULT UND exit ++ FUNC GLOBAL DEFAULT UND fclose ++ FUNC WEAK DEFAULT N fcntl ++ FUNC WEAK DEFAULT N flockfile ++ FUNC GLOBAL DEFAULT UND fopen ++ FUNC GLOBAL DEFAULT N fork ++ FUNC GLOBAL DEFAULT UND free ++ FUNC WEAK DEFAULT N fsync ++ FUNC WEAK DEFAULT N ftrylockfile ++ FUNC WEAK DEFAULT N funlockfile ++ FUNC GLOBAL DEFAULT UND getrlimit ++ TLS GLOBAL DEFAULT UND h_errno ++ FUNC GLOBAL DEFAULT UND link + FUNC GLOBAL DEFAULT N longjmp ++ FUNC WEAK DEFAULT N lseek ++ FUNC WEAK DEFAULT N lseek64 ++ FUNC GLOBAL DEFAULT UND malloc ++ FUNC GLOBAL DEFAULT UND memcpy ++ FUNC GLOBAL DEFAULT UND mempcpy ++ FUNC GLOBAL DEFAULT UND memset ++ FUNC GLOBAL DEFAULT UND mktemp ++ FUNC GLOBAL DEFAULT UND mmap ++ FUNC GLOBAL DEFAULT UND mprotect ++ FUNC WEAK DEFAULT N msync ++ FUNC GLOBAL DEFAULT UND munmap ++ FUNC WEAK DEFAULT N nanosleep ++ FUNC WEAK DEFAULT N open ++ FUNC WEAK DEFAULT N open64 ++ FUNC WEAK DEFAULT N pause ++ FUNC WEAK DEFAULT N pread ++ FUNC WEAK DEFAULT N pread64 ++ FUNC GLOBAL DEFAULT N pthread_atfork + FUNC GLOBAL DEFAULT N pthread_attr_destroy ++ FUNC GLOBAL DEFAULT N pthread_attr_getaffinity_np + FUNC GLOBAL DEFAULT N pthread_attr_getdetachstate +- FUNC WEAK DEFAULT N pthread_attr_getguardsize ++ FUNC GLOBAL DEFAULT N pthread_attr_getguardsize + FUNC GLOBAL DEFAULT N pthread_attr_getinheritsched + FUNC GLOBAL DEFAULT N pthread_attr_getschedparam + FUNC GLOBAL DEFAULT N pthread_attr_getschedpolicy + FUNC GLOBAL DEFAULT N pthread_attr_getscope +- FUNC WEAK DEFAULT N pthread_attr_getstack +- FUNC WEAK DEFAULT N pthread_attr_getstacksize ++ FUNC GLOBAL DEFAULT N pthread_attr_getstack ++ FUNC GLOBAL DEFAULT N pthread_attr_getstackaddr ++ FUNC GLOBAL DEFAULT N pthread_attr_getstacksize + FUNC GLOBAL DEFAULT N pthread_attr_init ++ FUNC GLOBAL DEFAULT N pthread_attr_setaffinity_np + FUNC GLOBAL DEFAULT N pthread_attr_setdetachstate +- FUNC WEAK DEFAULT N pthread_attr_setguardsize ++ FUNC GLOBAL DEFAULT N pthread_attr_setguardsize + FUNC GLOBAL DEFAULT N pthread_attr_setinheritsched + FUNC GLOBAL DEFAULT N pthread_attr_setschedparam + FUNC GLOBAL DEFAULT N pthread_attr_setschedpolicy + FUNC GLOBAL DEFAULT N pthread_attr_setscope +- FUNC WEAK DEFAULT N pthread_attr_setstack +- FUNC WEAK DEFAULT N pthread_attr_setstacksize ++ FUNC GLOBAL DEFAULT N pthread_attr_setstack ++ FUNC GLOBAL DEFAULT N pthread_attr_setstackaddr ++ FUNC GLOBAL DEFAULT N pthread_attr_setstacksize + FUNC GLOBAL DEFAULT N pthread_barrier_destroy + FUNC GLOBAL DEFAULT N pthread_barrier_init + FUNC GLOBAL DEFAULT N pthread_barrier_wait + FUNC GLOBAL DEFAULT N pthread_barrierattr_destroy ++ FUNC GLOBAL DEFAULT N pthread_barrierattr_getpshared + FUNC GLOBAL DEFAULT N pthread_barrierattr_init + FUNC GLOBAL DEFAULT N pthread_barrierattr_setpshared + FUNC GLOBAL DEFAULT N pthread_cancel +@@ -193,36 +178,49 @@ + FUNC GLOBAL DEFAULT N pthread_cond_timedwait + FUNC GLOBAL DEFAULT N pthread_cond_wait + FUNC GLOBAL DEFAULT N pthread_condattr_destroy ++ FUNC GLOBAL DEFAULT N pthread_condattr_getclock + FUNC GLOBAL DEFAULT N pthread_condattr_getpshared + FUNC GLOBAL DEFAULT N pthread_condattr_init ++ FUNC GLOBAL DEFAULT N pthread_condattr_setclock + FUNC GLOBAL DEFAULT N pthread_condattr_setpshared + FUNC GLOBAL DEFAULT N pthread_create + FUNC GLOBAL DEFAULT N pthread_detach + FUNC GLOBAL DEFAULT N pthread_equal + FUNC GLOBAL DEFAULT N pthread_exit ++ FUNC GLOBAL DEFAULT N pthread_getaffinity_np + FUNC GLOBAL DEFAULT N pthread_getattr_np +- FUNC WEAK DEFAULT N pthread_getconcurrency ++ FUNC GLOBAL DEFAULT N pthread_getconcurrency ++ FUNC GLOBAL DEFAULT N pthread_getcpuclockid + FUNC GLOBAL DEFAULT N pthread_getschedparam + FUNC GLOBAL DEFAULT N pthread_getspecific + FUNC GLOBAL DEFAULT N pthread_join + FUNC GLOBAL DEFAULT N pthread_key_create + FUNC GLOBAL DEFAULT N pthread_key_delete + FUNC GLOBAL DEFAULT N pthread_kill +- FUNC WEAK DEFAULT N pthread_kill_other_threads_np ++ FUNC GLOBAL DEFAULT N pthread_kill_other_threads_np ++ FUNC GLOBAL DEFAULT N pthread_mutex_consistent_np + FUNC GLOBAL DEFAULT N pthread_mutex_destroy ++ FUNC GLOBAL DEFAULT N pthread_mutex_getprioceiling + FUNC GLOBAL DEFAULT N pthread_mutex_init + FUNC GLOBAL DEFAULT N pthread_mutex_lock ++ FUNC GLOBAL DEFAULT N pthread_mutex_setprioceiling + FUNC GLOBAL DEFAULT N pthread_mutex_timedlock + FUNC GLOBAL DEFAULT N pthread_mutex_trylock + FUNC GLOBAL DEFAULT N pthread_mutex_unlock + FUNC GLOBAL DEFAULT N pthread_mutexattr_destroy + FUNC WEAK DEFAULT N pthread_mutexattr_getkind_np +- FUNC WEAK DEFAULT N pthread_mutexattr_getpshared +- FUNC WEAK DEFAULT N pthread_mutexattr_gettype ++ FUNC GLOBAL DEFAULT N pthread_mutexattr_getprioceiling ++ FUNC GLOBAL DEFAULT N pthread_mutexattr_getprotocol ++ FUNC GLOBAL DEFAULT N pthread_mutexattr_getpshared ++ FUNC GLOBAL DEFAULT N pthread_mutexattr_getrobust_np ++ FUNC GLOBAL DEFAULT N pthread_mutexattr_gettype + FUNC GLOBAL DEFAULT N pthread_mutexattr_init + FUNC WEAK DEFAULT N pthread_mutexattr_setkind_np +- FUNC WEAK DEFAULT N pthread_mutexattr_setpshared +- FUNC WEAK DEFAULT N pthread_mutexattr_settype ++ FUNC GLOBAL DEFAULT N pthread_mutexattr_setprioceiling ++ FUNC GLOBAL DEFAULT N pthread_mutexattr_setprotocol ++ FUNC GLOBAL DEFAULT N pthread_mutexattr_setpshared ++ FUNC GLOBAL DEFAULT N pthread_mutexattr_setrobust_np ++ FUNC GLOBAL DEFAULT N pthread_mutexattr_settype + FUNC GLOBAL DEFAULT N pthread_once + FUNC GLOBAL DEFAULT N pthread_rwlock_destroy + FUNC GLOBAL DEFAULT N pthread_rwlock_init +@@ -240,27 +238,35 @@ + FUNC GLOBAL DEFAULT N pthread_rwlockattr_setkind_np + FUNC GLOBAL DEFAULT N pthread_rwlockattr_setpshared + FUNC GLOBAL DEFAULT N pthread_self ++ FUNC GLOBAL DEFAULT N pthread_setaffinity_np + FUNC GLOBAL DEFAULT N pthread_setcancelstate + FUNC GLOBAL DEFAULT N pthread_setcanceltype +- FUNC WEAK DEFAULT N pthread_setconcurrency +- FUNC GLOBAL DEFAULT N pthread_setegid_np +- FUNC GLOBAL DEFAULT N pthread_seteuid_np +- FUNC GLOBAL DEFAULT N pthread_setgid_np +- FUNC GLOBAL DEFAULT N pthread_setregid_np +- FUNC GLOBAL DEFAULT N pthread_setresgid_np +- FUNC GLOBAL DEFAULT N pthread_setresuid_np +- FUNC GLOBAL DEFAULT N pthread_setreuid_np ++ FUNC GLOBAL DEFAULT N pthread_setconcurrency + FUNC GLOBAL DEFAULT N pthread_setschedparam ++ FUNC GLOBAL DEFAULT N pthread_setschedprio + FUNC GLOBAL DEFAULT N pthread_setspecific +- FUNC GLOBAL DEFAULT N pthread_setuid_np + FUNC GLOBAL DEFAULT N pthread_sigmask +- FUNC WEAK DEFAULT N pthread_spin_destroy +- FUNC WEAK DEFAULT N pthread_spin_init +- FUNC WEAK DEFAULT N pthread_spin_lock +- FUNC WEAK DEFAULT N pthread_spin_trylock +- FUNC WEAK DEFAULT N pthread_spin_unlock ++ FUNC GLOBAL DEFAULT N pthread_spin_destroy ++ FUNC GLOBAL DEFAULT N pthread_spin_init ++ FUNC GLOBAL DEFAULT N pthread_spin_lock ++ FUNC GLOBAL DEFAULT N pthread_spin_trylock ++ FUNC GLOBAL DEFAULT N pthread_spin_unlock + FUNC GLOBAL DEFAULT N pthread_testcancel ++ FUNC GLOBAL DEFAULT N pthread_timedjoin_np ++ FUNC GLOBAL DEFAULT N pthread_tryjoin_np ++ FUNC GLOBAL DEFAULT N pthread_yield ++ FUNC WEAK DEFAULT N pwrite ++ FUNC WEAK DEFAULT N pwrite64 + FUNC GLOBAL DEFAULT N raise ++ FUNC WEAK DEFAULT N read ++ FUNC GLOBAL DEFAULT UND realloc ++ FUNC WEAK DEFAULT N recv ++ FUNC WEAK DEFAULT N recvfrom ++ FUNC WEAK DEFAULT N recvmsg ++ FUNC GLOBAL DEFAULT UND sched_get_priority_max ++ FUNC GLOBAL DEFAULT UND sched_get_priority_min ++ FUNC GLOBAL DEFAULT UND sched_setparam ++ FUNC GLOBAL DEFAULT UND sched_yield + FUNC GLOBAL DEFAULT N sem_close + FUNC GLOBAL DEFAULT N sem_destroy + FUNC GLOBAL DEFAULT N sem_getvalue +@@ -271,8 +277,23 @@ + FUNC GLOBAL DEFAULT N sem_trywait + FUNC GLOBAL DEFAULT N sem_unlink + FUNC GLOBAL DEFAULT N sem_wait +- FUNC GLOBAL DEFAULT N set_eflags +- FUNC GLOBAL DEFAULT N sigaction +- FUNC GLOBAL DEFAULT N siglongjmp +- FUNC GLOBAL DEFAULT N sigwait +- FUNC GLOBAL DEFAULT N testandset ++ FUNC WEAK DEFAULT N send ++ FUNC WEAK DEFAULT N sendmsg ++ FUNC WEAK DEFAULT N sendto ++ FUNC WEAK DEFAULT N sigaction ++ FUNC WEAK DEFAULT N siglongjmp ++ FUNC WEAK DEFAULT N sigwait ++ FUNC GLOBAL DEFAULT UND sscanf ++ FUNC GLOBAL DEFAULT UND strcmp ++ FUNC GLOBAL DEFAULT UND strlen ++ FUNC GLOBAL DEFAULT N system ++ FUNC WEAK DEFAULT N tcdrain ++ FUNC GLOBAL DEFAULT UND tdelete ++ FUNC GLOBAL DEFAULT UND tfind ++ FUNC GLOBAL DEFAULT UND tsearch ++ FUNC GLOBAL DEFAULT UND twalk ++ FUNC GLOBAL DEFAULT UND unlink ++ FUNC WEAK DEFAULT N vfork ++ FUNC WEAK DEFAULT N wait ++ FUNC WEAK DEFAULT N waitpid ++ FUNC WEAK DEFAULT N write + + +And uclibc_unrefd.lst is: + +__compare_and_swap +__flockfilelist +__fresetlockfiles +__funlockfilelist +__linuxthreads_create_event +__linuxthreads_death_event +__linuxthreads_initial_report_events +__linuxthreads_pthread_key_2ndlevel_size +__linuxthreads_pthread_keys_max +__linuxthreads_pthread_sizeof_descr +__linuxthreads_pthread_threads_max +__linuxthreads_reap_event +__linuxthreads_version +__pthread_alt_lock +__pthread_alt_timedlock +__pthread_alt_unlock +__pthread_attr_destroy +__pthread_attr_getdetachstate +__pthread_attr_getguardsize +__pthread_attr_getinheritsched +__pthread_attr_getschedparam +__pthread_attr_getschedpolicy +__pthread_attr_getscope +__pthread_attr_getstack +__pthread_attr_getstacksize +__pthread_attr_init +__pthread_attr_setdetachstate +__pthread_attr_setguardsize +__pthread_attr_setinheritsched +__pthread_attr_setschedparam +__pthread_attr_setschedpolicy +__pthread_attr_setscope +__pthread_attr_setstack +__pthread_attr_setstacksize +__pthread_barrierattr_getpshared +__pthread_compare_and_swap +__pthread_cond_broadcast +__pthread_cond_destroy +__pthread_cond_init +__pthread_cond_signal +__pthread_cond_timedwait +__pthread_cond_wait +__pthread_condattr_destroy +__pthread_condattr_init +__pthread_create +__pthread_destroy_specifics +__pthread_do_exit +__pthread_equal +__pthread_exit_code +__pthread_exit_requested +__pthread_find_self +__pthread_functions +__pthread_getconcurrency +__pthread_getschedparam +__pthread_getspecific +__pthread_handles +__pthread_handles_num +__pthread_has_cas +__pthread_init_max_stacksize +__pthread_initial_thread +__pthread_initial_thread_bos +__pthread_initialize_manager +__pthread_internal_tsd_address +__pthread_internal_tsd_get +__pthread_internal_tsd_set +__pthread_key_create +__pthread_kill_other_threads_np +__pthread_last_event +__pthread_lock +__pthread_main_thread +__pthread_manager +__pthread_manager_adjust_prio +__pthread_manager_event +__pthread_manager_reader +__pthread_manager_request +__pthread_manager_sighandler +__pthread_manager_thread +__pthread_manager_thread_bos +__pthread_manager_thread_tos +__pthread_max_stacksize +__pthread_mutex_destroy +__pthread_mutex_timedlock +__pthread_mutexattr_destroy +__pthread_mutexattr_getkind_np +__pthread_mutexattr_getpshared +__pthread_mutexattr_gettype +__pthread_mutexattr_init +__pthread_mutexattr_setkind_np +__pthread_mutexattr_setpshared +__pthread_mutexattr_settype +__pthread_nonstandard_stacks +__pthread_null_sighandler +__pthread_offsetof_descr +__pthread_offsetof_pid +__pthread_once_fork_child +__pthread_once_fork_parent +__pthread_once_fork_prepare +__pthread_perform_cleanup +__pthread_raise +__pthread_reset_main_thread +__pthread_restart_new +__pthread_rwlock_destroy +__pthread_rwlock_init +__pthread_rwlock_rdlock +__pthread_rwlock_timedrdlock +__pthread_rwlock_timedwrlock +__pthread_rwlock_tryrdlock +__pthread_rwlock_trywrlock +__pthread_rwlock_unlock +__pthread_rwlock_wrlock +__pthread_rwlockattr_destroy +__pthread_self +__pthread_setcancelstate +__pthread_setcanceltype +__pthread_setconcurrency +__pthread_setschedparam +__pthread_setspecific +__pthread_sig_cancel +__pthread_sig_debug +__pthread_sig_restart +__pthread_sigaction +__pthread_sighandler +__pthread_sighandler_rt +__pthread_sigwait +__pthread_sizeof_handle +__pthread_smp_kernel +__pthread_spin_destroy +__pthread_spin_init +__pthread_spin_lock +__pthread_spin_trylock +__pthread_spin_unlock +__pthread_thread_self +__pthread_threads_debug +__pthread_threads_events +__pthread_threads_max +__pthread_timedsuspend_new +__pthread_unlock +__pthread_wait_for_restart_signal +__register_atfork +__sigaction +__sighandler +compare_and_swap_is_available +get_eflags +pthread_attr_getguardsize +pthread_attr_getstack +pthread_attr_getstacksize +pthread_attr_setguardsize +pthread_attr_setstack +pthread_attr_setstacksize +pthread_barrier_destroy +pthread_barrier_init +pthread_barrier_wait +pthread_barrierattr_destroy +pthread_barrierattr_init +pthread_barrierattr_setpshared +pthread_cancel +pthread_condattr_getpshared +pthread_condattr_setpshared +pthread_create +pthread_detach +pthread_getattr_np +pthread_getconcurrency +pthread_getspecific +pthread_join +pthread_key_create +pthread_key_delete +pthread_kill +pthread_kill_other_threads_np +pthread_mutex_timedlock +pthread_mutexattr_destroy +pthread_mutexattr_getkind_np +pthread_mutexattr_getpshared +pthread_mutexattr_gettype +pthread_mutexattr_init +pthread_mutexattr_setkind_np +pthread_mutexattr_setpshared +pthread_mutexattr_settype +pthread_rwlock_destroy +pthread_rwlock_init +pthread_rwlock_rdlock +pthread_rwlock_timedrdlock +pthread_rwlock_timedwrlock +pthread_rwlock_tryrdlock +pthread_rwlock_trywrlock +pthread_rwlock_unlock +pthread_rwlock_wrlock +pthread_rwlockattr_destroy +pthread_rwlockattr_getkind_np +pthread_rwlockattr_getpshared +pthread_rwlockattr_init +pthread_rwlockattr_setkind_np +pthread_rwlockattr_setpshared +pthread_setconcurrency +pthread_setegid_np +pthread_seteuid_np +pthread_setgid_np +pthread_setregid_np +pthread_setresgid_np +pthread_setresuid_np +pthread_setreuid_np +pthread_setspecific +pthread_setuid_np +pthread_sigmask +pthread_spin_destroy +pthread_spin_init +pthread_spin_lock +pthread_spin_trylock +pthread_spin_unlock +pthread_testcancel +sem_close +sem_destroy +sem_getvalue +sem_init +sem_open +sem_post +sem_timedwait +sem_trywait +sem_unlink +sem_wait +set_eflags +testandset diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/docs/sigaction.txt b/l4/pkg/uclibc/lib/contrib/uclibc/docs/sigaction.txt new file mode 100644 index 00000000..667eeba4 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/docs/sigaction.txt @@ -0,0 +1,249 @@ + All what you never wanted to know about sigaction(), + struct sigaction, and sigset_t. + + +Before vda started messing with sigset_t, struct sigaction +and sigaction() functions, things looked this way: + + + Structures + +MIPS: + +Ignoring bogus "#if defined(__mips__) ..." block in +libc/sysdeps/linux/common/bits/kernel_sigaction.h +and using +libc/sysdeps/linux/mips/bits/kernel_sigaction.h +as an authoritative source: + +HAVE_SA_RESTORER is #defined +struct old_kernel_sigaction { + unsigned sa_flags; + sighandler_t k_sa_handler; + unsigned long sa_mask; + unsigned pad0[3]; /* reserved, keep size constant */ + /* Abi says here follows reserved int[2] */ + void (*sa_restorer)(void); +#if (_MIPS_SZPTR < 64) + /* For 32 bit code we have to pad struct sigaction to get + * constant size for the ABI */ + int pad1[1]; /* reserved */ +#endif +}; +struct kernel_sigaction { + unsigned int sa_flags; + sighandler_t k_sa_handler; + kernel_sigset_t sa_mask; + void (*sa_restorer)(void); + int s_resv[1]; /* reserved */ +}; +struct sigaction { + unsigned sa_flags; + sighandler_t sa_handler; + sigset_t sa_mask; + /* The ABI says here are two unused ints following. */ + /* Restore handler. */ + void (*sa_restorer)(void); +#if _MIPS_SZPTR < 64 + int sa_resv[1]; +#endif +}; + +IA64: + +Has no old_sigaction. What a relief. + +struct kernel_sigaction { + sighandler_t k_sa_handler; + unsigned long sa_flags; + sigset_t sa_mask; +}; +struct sigaction { + sighandler_t sa_handler; + unsigned long sa_flags; + sigset_t sa_mask; +}; + +Alpha: + +struct old_kernel_sigaction { + sighandler_t k_sa_handler; + unsigned long sa_mask; + unsigned sa_flags; +}; +struct kernel_sigaction { + sighandler_t k_sa_handler; + unsigned sa_flags; + sigset_t sa_mask; +}; +struct sigaction { + sighandler_t sa_handler; + sigset_t sa_mask; + unsigned sa_flags; +}; + +HPPA: + +struct kernel_sigaction { + sighandler_t k_sa_handler; + unsigned long sa_flags; + sigset_t sa_mask; +}; +struct sigaction { + sighandler_t sa_handler; + unsigned long sa_flags; + sigset_t sa_mask; +}; + +The rest, kernel side: + +HAVE_SA_RESTORER #defined +struct old_kernel_sigaction { + sighandler_t k_sa_handler; + unsigned long sa_mask; + unsigned long sa_flags; + void (*sa_restorer)(void); +}; +struct kernel_sigaction { + sighandler_t k_sa_handler; + unsigned long sa_flags; + void (*sa_restorer)(void); + sigset_t sa_mask; +}; + +On userspace side, Sparc has special struct sigaction: + +struct sigaction { + sighandler_t sa_handler; + sigset_t sa_mask; + unsigned long sa_flags; + void (*sa_restorer)(void); /* Not used by Linux/Sparc */ +}; + +And finally the rest has: + +struct sigaction { + sighandler_t sa_handler; + sigset_t sa_mask; + int sa_flags; + void (*sa_restorer)(void); +}; + +Userspace sigset_t was uniformly defined as vector of longs +big enough to hold 1024 (!) bits - carried over from glibc. +Since the only arch whose struct kernel_sigaction contains sa_mask +not as a last member is MIPS, MIPS has special kernel_sigset_t, +which is an array of longs long enough for 128 bits. +Other arches still used userspace sigset_t in struct kernel_sigaction, +but it did not really matter because overlong kernel_sigaction +does not hurt in sigaction() [explained below]. +On kernel side, all arches define _NSIG to 65 (meaning +there are 64 signals, 1..64) except MIPS, which define it to 129. + + + Functions + +sigaction() [libc function] usually has two kernel_sigaction's +on stack and copy (userspace) struct sigaction members into +first one, executes syscall, then pulls out the result from +second one. This accomodates differences in layouts of structs. + +The only typically present quirk is what to do with sa_restorer. + + libc/sysdeps/linux/arm/sigaction.c + +if HAVE_SA_RESTORER and (sa_flags & SA_RESTORER) is not set, +sets sa_restorer to +(flags & SA_SIGINFO) ? __default_rt_sa_restorer : __default_sa_restorer, +and sets SA_RESTORER, +otherwise passes it as-is. Which is kinda strange, because AFAICS +HAVE_SA_RESTORER is *not* defined for ARM. + + libc/sysdeps/linux/i386/sigaction.c + +Forcibly sets SA_RESTORER and sa_restorer: +kact.sa_flags = act->sa_flags | SA_RESTORER; +kact.sa_restorer = ((act->sa_flags & SA_SIGINFO) ? &restore_rt : &restore); + + libc/sysdeps/linux/x86_64/sigaction.c + +Forcibly sets SA_RESTORER and sa_restorer: +kact.sa_flags = act->sa_flags | SA_RESTORER; +kact.sa_restorer = &restore_rt; + + libc/sysdeps/linux/mips/sigaction.c + +# ifdef HAVE_SA_RESTORER +# if _MIPS_SIM == _ABIO32 + kact.sa_restorer = act->sa_restorer; +# else + kact.sa_restorer = &restore_rt; +# endif +# endif +No confusion here, HAVE_SA_RESTORER is #defined for MIPS + + libc/sysdeps/linux/avr32/sigaction.c + +if (kact.sa_flags & SA_RESTORER) { + kact.sa_restorer = act->sa_restorer; +} else { + kact.sa_restorer = __default_rt_sa_restorer; + kact.sa_flags |= SA_RESTORER; +} +Does not check HAVE_SA_RESTORER, but avr32 falls +in "completely ordinary" category on both kernel and +userspace sides, and those have it defined. + + libc/sysdeps/linux/xtensa/sigaction.c + +if (kact.sa_flags & SA_RESTORER) { + kact.sa_restorer = act->sa_restorer; +} else { + kact.sa_restorer = __default_sa_restorer; + kact.sa_flags |= SA_RESTORER; +} +Thus, similar to avr32. + + libc/signal/sigaction.c (i.e. the all other arches) + +# ifdef HAVE_SA_RESTORER + kact.sa_restorer = act->sa_restorer; +# endif +Plain translation, just sa_restorer copy is protected +by HAVE_SA_RESTORER #define check. Looks like here +HAVE_SA_RESTORER will be undef'ed only for IA64, +Alpha an HPPA. + + + Proposed overhaul past 0.9.30 + +Since we can define libc-side structures at will: +make sigset_t and struct sigaction identical on kernel side and libc side +within each arch. If arches do not need special handling of sa_restorer, +then sigaction() can directly use passed struct sigaction as-is. +Otherwise, a copy is still needed, although sigaction() might have +just one struct kernel_sigaction on stack and use it both for passing +data to kernel and for receiving it back. Might save a few bytes. + +To this effect: + +* Make sigset_t size match kernel side on all arches. + This is easy since all arches have 64 signals and only MIPS has 128. + +* Modify libc/sysdeps/linux/$ARCH/bits/sigaction.h + so that its struct sigaction matches kernel's. If sa_restorer + field is present in libc but is missing in kernel_sigaction, + add it at the bottom in order to not mess up kernel_sigaction layout. + +* Modify libc/sysdeps/linux/$ARCH/sigaction.c + to implement the logic above. In "common" pseudo-arch + (libc/signal/sigaction.c file), + we would not even need to do any copying, as described above. + +* Document discovered arch quirks while debugging this mess. + +* struct old_kernel_sigaction can't be disposed of in a similar way, + we need to have userspace struct sigaction unchanged regardless + whether we use "old" or "new" kernel sigaction() syscall. + It's moot anyway because "old" one is long unused, it's from + pre-2.2 kernels. diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/docs/threads.txt b/l4/pkg/uclibc/lib/contrib/uclibc/docs/threads.txt new file mode 100644 index 00000000..182f1be7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/docs/threads.txt @@ -0,0 +1,56 @@ +uClibc thread-safety analysis + +Things that are still known to be needed for thread safety: + + none + + + + +Things that might be nice, but are not required: + + getnetent_r + gethostent_r + getprotoent_r + getnetbyname_r + getnetbyaddr_r + + + + + +Functions that use static data and may still need locking: + + + -------------------------------------------------------------------- + + libc/inet/rpc/rpc_thread.c: + + __rpc_thread_variables is currently disabled, since thread + local storage seems to not be correctly specified as + weak functions. + + -------------------------------------------------------------------- + + unistd/getpass.c: + + static char buf[PWD_BUFFER_SIZE]; + + getpass <--- + + NOTE: This function returns a pointer to a static data structure. + This seems like it requires an _r version of this function. Glibc + does the same thing. Oops! So much for thread-safe glibc! + + -------------------------------------------------------------------- + + unistd/sysconf.c: + + static long int ret_vals[_UCLIBC_SYSCONF_NUM_VALID_ARGS]; + + find_or_add_in_table <--- + main <--- + + NOTE: I'm not sure if this needs to be made reentrant... + + -------------------------------------------------------------------- diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/docs/uClibc_vs_SuSv3.txt b/l4/pkg/uclibc/lib/contrib/uclibc/docs/uClibc_vs_SuSv3.txt new file mode 100644 index 00000000..a5a9dcd4 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/docs/uClibc_vs_SuSv3.txt @@ -0,0 +1,105 @@ +uClibc attempts to fully (and rigorously) support "The Open Group Base +Specifications Issue 6 IEEE Std 1003.1, 2003 Edition" (aka SuSv3). However, as +with any standard, they sometimes require things that are either impossible or +are Completely Stupid(tm). Therefore, we cannot claim full compliance, and +there may be some areas of uClibc that differ from the requirements of this +specification. This document attempts to list these differences and, when +completed, will contain a full list of all relevant differences between uClibc +and the requirements of the SuSv3. + + +*) The uClibc setlocale() function is not threadsafe. + + SuSv3 states that "The locale state is common to all threads + within a process.". But it does not explicitly mention + setlocale() as a function that need not be thread-safe. + Making setlocale() threadsafe would require an absurd amount + of locking (i.e. inside each and every ctype call such as + isalpha()). Furthermore, we consider calling setlocale() + from N threads concurrently while using string functions to + be a terribly dumb thing to do. Therefore, we have decided + that setlocale() shall not be threadsafe. If you are + multi-threaded, and you wish to change the global locale + state, please take care to prevent all other threads from + using any locale or ctype functions until the setlocale() + call has finished. + + + + +---------------------------------------------------------------- +heukelum -- heukelum at freemail dot nl writes: + +Hi everyone, + +I think uClibc is a great project! And, since I found the file +docs/uClibc_vs_SuSv3.txt in the source tarball which mentioned only +fmtmsg as a missing function compared to the SUSv3, I got curious about +the length of the list denoted by "". So I built the +20040305-snapshot using allyesconfig, extracted the symbols from the +(dynamic) libraries, and compared that list to the SUSv3 header files... + +The largest source of omissions was the mathematical interface +(183/355), followed by optional interfaces (134/355). The result: only +38 non-mathematical interfaces are missing compared to the minimal +SUSv3! Naming only one function as missing was over-enthousiastic, but +the result was better than I anticipated. + +A compact list of omissions is appended. +I hope this was a helpful exercise ;) + +Greetings, + Alexander + +P.S. uClibc was compiled with thread support, but did not provide the +interfaces pthread_cleanup_push and pthread_cleanup_pop. + + + +Omissions from obligatory interfaces: +------------------------------------- +stdlib.h: _Exit, lcong48, lldiv, posix_openpt; + ecvt, fcvt +ndbm.h: [all=9] dbm_* +utmpx.h: [all=6] *utx* (but functions without "x" do exist!) +nl_types.h: [all] catclose, catgets, catopen +unistd.h: getwd, ualarm +inttypes.h: imaxdiv +fmtmsg.h: fmtmsg +string.h: strerror_r +setjmp.h: setsigjmp +monetary.h: strfmon +sys/select.h: pselect +sys/socket.h: sockatmark +sys/wait.h: waitid + + +Unimplemented optional interfaces: +---------------------------------- +trace.h: (depends on TRC) [all=50] posix_trace_* +pthread.h: (depends on THR) pthread_cleanup_{push,pop}; + pthread_attr_{g,s}etstack (depend on TSA TSS); + [7] pthread_barrier* (depend on BAR); + pthread_condattr_{g,s}et_clock (depend on CS); + pthread_getcpuclockid (depends on TCT); + pthread_mutex{,attr}_{g,s}etprioceiling (depend on TPP); + pthread_mutexattr_{g,s}etprotocol (depend on TPP|TPI); + pthread_rwlock_timed{rd,rw}lock (depend on TMO); + pthread_setschedprio (depends on TPS); + [5] pthread_spin_* (depend on SPI) +spawn.h: (depends on SPN) [all=21] posix_spawn* +aio.h: (depends on AIO) [all=8] aio_*, lio_* +stropts.h: (depends on XSR) isastream, {g,s}et{,p}msg, fattach, fdetach +sys/mman.h: posix_madvice (depends on ADV); posix_mem_offset, + posix_typed_mem_getinfo, posix_typed_mem_open (depend on TYM); + shm_open, shm_unlink (depend on SHM) +fcntl.h: posix_fallocate (depend on ADV) +signal.h: sigqueue (depends on RTS) + + +Unimplemented mathematical interfaces: +-------------------------------------- +math.h: [126] many +complex.h: [46] all, except cabs +fenv.h: [11] all +_______________________________________________ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/docs/wchar_and_locale.txt b/l4/pkg/uclibc/lib/contrib/uclibc/docs/wchar_and_locale.txt new file mode 100644 index 00000000..976c9aaa --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/docs/wchar_and_locale.txt @@ -0,0 +1,113 @@ + User-configurable + +UCLIBC_HAS_CTYPE_TABLES + Make toupper etc work thru translation tables + and isalhum etc thru lookup tables. Help says: + "While the non-table versions are often smaller when building + statically linked apps, they work only in stub locale mode." + + "stub locale mode" is when !UCLIBC_HAS_LOCALE I presume, + when we are permanently in POSIX/C locale. + +UCLIBC_HAS_CTYPE_SIGNED + Handle sign-extended chars. I.e. if you want + toupper((char)0xa0) => toupper(0xffffffa0) => still works correctly, + as if toupper(0xa0) was called. + +UCLIBC_HAS_CTYPE_UNSAFE/CHECKED/ENFORCED + Do not check ctype function argument's range/check it and return + error/check it and abort(). Help says: + NOTE: This only affects the 'ctype' _functions_. It does not affect + the macro implementations. [so what happens to macros?] + [examples?] + +UCLIBC_HAS_WCHAR + Wide character support. I assume all those wchar_t types and functions + +UCLIBC_HAS_LOCALE/XLOCALE + Support locale / extended locale + +UCLIBC_PREGENERATED_LOCALE_DATA + Not recommended + + + uclibc internal machinery + +__LOCALE_C_ONLY + #defined if !UCLIBC_HAS_LOCALE + +__NO_CTYPE + #defined only by some .c files. Prevents ctype macros to be #defined + (those w/o underscores. __ctype() macros will still be defined). + Looks like user is expected to never mess with defining it. + +__UCLIBC_DO_XLOCALE + #defined only by some .c files. Looks like user is expected to never + mess with defining it. + +__XL_NPP(N) - "add _l suffix if locale support is on" + #defined to N ## _l if __UCLIBC_HAS_XLOCALE__ && __UCLIBC_DO_XLOCALE, + else #defined to just N. + +__CTYPE_HAS_8_BIT_LOCALES +__CTYPE_HAS_UTF_8_LOCALES + Depends on contents of extra/locale/LOCALES data file. Looks like + both will be set if UCLIBC_HAS_LOCALE and extra/locale/LOCALES + is not edited. + +__WCHAR_ENABLED + locale_mmap.h defines it unconditionally, extra/locale/gen_ldc.c + defines it too with a warning, and _then_ includes locale_mmap.h. + Makefile seems to prevent the warning in gen_ldc.c: + ifeq ($(UCLIBC_HAS_WCHAR),y) + BUILD_CFLAGS-gen_wc8bit += -DDO_WIDE_CHAR=1 + BUILD_CFLAGS-gen_ldc += -D__WCHAR_ENABLED=1 + endif + A mess. Why they can't just use __UCLIBC_HAS_WCHAR__? + +__WCHAR_REPLACEMENT_CHAR + Never defined (dead code???) + + + + Actual ctype macros are a bloody mess! + +__C_isspace(c), __C_tolower(c) et al + Defined in bits/uClibc_ctype.h. Non-locale-aware, unsafe + wrt multiple-evaluation, macros. Return unsigned int. + +__isspace(c), __tolower(c) et al + Defined in bits/uClibc_ctype.h. Non-locale-aware, + but safe wrt multiple-evaluation, macros. Return int. + +__isdigit_char, __isdigit_int + Visible only to uclibc code. ((unsigned char/int)((c) - '0') <= 9). + +_tolower(c), _toupper(c) + Even more unsafe versions (they just do | 0x20 or ^ 0x20). Sheesh. + They are mandated by POSIX so we must have them defined, + but I removed all uses in uclibc code. Half of them were buggy. + +isspace(c), tolower(c) et al + Declared as int isXXXX(int c) in bits/uClibc_ctype.h. Then, + if not C++ compile, defined as macros to __usXXXX(c) + +bits/uClibc_ctype.h is included by ctype.h only if !__UCLIBC_HAS_CTYPE_TABLES__. + +Otherwise, ctype.h declares int isXXXX(int c) functions, +then defines macros for isXXXX(c), __isXXX(c), toXXXX(c). +Surprisingly, there are no __toXXXX(c), but if __USE_EXTERN_INLINES, +there are inlines (yes, not macros!) for toXXXX(c) functions, +so those may have both inlines and macros!). +It also defines "unsafe" _toXXXX macros. + +All in all, __isXXXX(c) and __toXXXXX(c) seem to be useless, +they are full equivalents to non-underscored versions. +Remove? + +Macro-ization of isXXX(c) for __UCLIBC_HAS_XLOCALE__ case is problematic: +it is done by indexing: __UCLIBC_CTYPE_B[c], and in __UCLIBC_HAS_XLOCALE__ +case __UCLIBC_CTYPE_B is doing a __ctype_b_loc() call! We do not save +function call! Thus, why not have dedicated optimized functions +for each isXXXX() instead? Looking deeper, __ctype_b_loc() may have +another lever of function calls inside! What a mess... diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.alpha b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.alpha new file mode 100644 index 00000000..144924a6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.alpha @@ -0,0 +1,16 @@ +# +# For a description of the syntax of this configuration file, +# see extra/config/Kconfig-language.txt +# + +config TARGET_ARCH + string + default "alpha" + +config FORCE_OPTIONS_FOR_ARCH + bool + default y + select ARCH_LITTLE_ENDIAN + select ARCH_HAS_MMU + select ARCH_HAS_NO_LDSO + select UCLIBC_HAS_LFS diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.arm b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.arm new file mode 100644 index 00000000..b060ace9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.arm @@ -0,0 +1,133 @@ +# +# For a description of the syntax of this configuration file, +# see extra/config/Kconfig-language.txt +# + +config TARGET_ARCH + string + default "arm" + +config FORCE_OPTIONS_FOR_ARCH + bool + default y + select ARCH_ANY_ENDIAN + +choice + prompt "Target ABI" + default CONFIG_ARM_OABI + help + If you choose "EABI" here, functions and constants required by the + ARM EABI will be built into the library. You should choose "EABI" + if your compiler uses the ARM EABI, in which case you will also + need a kernel supporting the EABI system call interface, or "OABI" + for a compiler using the old Linux ABI. + +config CONFIG_ARM_OABI + bool "OABI" + +config CONFIG_ARM_EABI + bool "EABI" + +endchoice + +config USE_BX + bool "Use BX in function return" + default y + depends on !CONFIG_GENERIC_ARM && !CONFIG_ARM610 && !CONFIG_ARM710 + help + Use BX instruction for THUMB aware architectures. + +choice + prompt "Target Processor Type" + default CONFIG_GENERIC_ARM + help + This is the processor type of your CPU. This information is used for + optimizing purposes. To build a library that will run on all ARMCPU + types (albeit not optimally fast), you can specify "Generic Arm" here. + If you pick anything other than "Generic Arm", there is no guarantee + that uClibc will even run on anything other than the selected + processor type. + + Here are the settings recommended for greatest speed: + - "Generic Arm" select this if your compiler is already setup to + optimize things properly, or if you want to run on pretty much + everything, or you just don't much care. + - For anything else, pick the ARM core type that best matches the + cpu you will be using on your device. + + If you don't know what to do, choose "Generic Arm". + +config CONFIG_GENERIC_ARM + bool "Generic Arm" + +config CONFIG_ARM610 + bool "Arm 610" + select ARCH_HAS_MMU + +config CONFIG_ARM710 + bool "Arm 710" + select ARCH_HAS_MMU + +config CONFIG_ARM7TDMI + bool "Arm 7TDMI" + select ARCH_HAS_NO_MMU + +config CONFIG_ARM720T + bool "Arm 720T" + select ARCH_HAS_MMU + +config CONFIG_ARM920T + bool "Arm 920T" + select ARCH_HAS_MMU + +config CONFIG_ARM922T + bool "Arm 922T" + select ARCH_HAS_MMU + +config CONFIG_ARM926T + bool "Arm 926T" + select ARCH_HAS_MMU + +config CONFIG_ARM10T + bool "Arm 10T" + select ARCH_HAS_MMU + +config CONFIG_ARM1136JF_S + bool "Arm 1136JF-S" + select ARCH_HAS_MMU + +config CONFIG_ARM1176JZ_S + bool "Arm 1176JZ-S" + select ARCH_HAS_MMU + +config CONFIG_ARM1176JZF_S + bool "Arm 1176JZF-S" + select ARCH_HAS_MMU + +config CONFIG_ARM_CORTEX_M3 + bool "Arm Cortex-M3" + select ARCH_HAS_NO_MMU + select USE_BX + +config CONFIG_ARM_CORTEX_M1 + bool "Arm Cortex-M1" + select ARCH_HAS_NO_MMU + select USE_BX + +config CONFIG_ARM_SA110 + bool "Intel StrongArm SA-110" + select ARCH_HAS_MMU + +config CONFIG_ARM_SA1100 + bool "Intel StrongArm SA-1100" + select ARCH_HAS_MMU + +config CONFIG_ARM_XSCALE + bool "Intel Xscale" + select ARCH_HAS_MMU + +config CONFIG_ARM_IWMMXT + bool "Intel Xscale With WMMX PXA27x" + select ARCH_HAS_MMU + +endchoice diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.avr32 b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.avr32 new file mode 100644 index 00000000..cbadb4cf --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.avr32 @@ -0,0 +1,28 @@ +# +# For a description of the syntax of this configuration file, +# see extra/config/Kconfig-language.txt +# + +config TARGET_ARCH + string + default "avr32" + +config FORCE_OPTIONS_FOR_ARCH + bool + default y + select ARCH_BIG_ENDIAN + select FORCE_SHAREABLE_TEXT_SEGMENTS + +choice + prompt "Target CPU Type" + default CONFIG_AVR32_AP7 + +config CONFIG_AVR32_AP7 + bool "AVR32 AP7" + select ARCH_HAS_MMU + +endchoice + +config LINKRELAX + bool "Enable linker optimizations" + default y diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.bfin b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.bfin new file mode 100644 index 00000000..a70afcfd --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.bfin @@ -0,0 +1,14 @@ +# +# For a description of the syntax of this configuration file, +# see extra/config/Kconfig-language.txt +# + +config TARGET_ARCH + string + default "bfin" + +config FORCE_OPTIONS_FOR_ARCH + bool + default y + select ARCH_LITTLE_ENDIAN + select ARCH_HAS_NO_MMU diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.cris b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.cris new file mode 100644 index 00000000..52ca0c36 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.cris @@ -0,0 +1,34 @@ +# +# For a description of the syntax of this configuration file, +# see extra/config/Kconfig-language.txt +# + +config TARGET_ARCH + string + default "cris" + +config FORCE_OPTIONS_FOR_ARCH + bool + default y + select ARCH_LITTLE_ENDIAN + +choice + prompt "Target Architecture Type" + default CONFIG_CRIS + help + This is the architecture type of your CPU. This information + is used for optimizing purposes. + + Possible settings: + - CRIS Generic support for Axis' CRIS architecture. + - CRISv32 Support for Axis' CRISv32 architecture. + +config CONFIG_CRIS + select ARCH_HAS_MMU + bool "CRIS" + +config CONFIG_CRISV32 + select ARCH_HAS_MMU + bool "CRISv32" + +endchoice diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.e1 b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.e1 new file mode 100644 index 00000000..ecaa9f0e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.e1 @@ -0,0 +1,15 @@ +# +# For a description of the syntax of this configuration file, +# see extra/config/Kconfig-language.txt +# + +config TARGET_ARCH + string + default "e1" + +config FORCE_OPTIONS_FOR_ARCH + bool + default y + select ARCH_BIG_ENDIAN + select ARCH_HAS_NO_MMU + select ARCH_HAS_NO_SHARED diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.frv b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.frv new file mode 100644 index 00000000..b389870f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.frv @@ -0,0 +1,15 @@ +# +# For a description of the syntax of this configuration file, +# see extra/config/Kconfig-language.txt +# + +config TARGET_ARCH + string + default "frv" + +config FORCE_OPTIONS_FOR_ARCH + bool + default y + select ARCH_BIG_ENDIAN + select UCLIBC_HAS_FPU + select ARCH_HAS_NO_MMU diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.h8300 b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.h8300 new file mode 100644 index 00000000..ffcb9c83 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.h8300 @@ -0,0 +1,28 @@ +# +# For a description of the syntax of this configuration file, +# see extra/config/Kconfig-language.txt +# + +config TARGET_ARCH + string + default "h8300" + +config FORCE_OPTIONS_FOR_ARCH + bool + default y + select ARCH_ANY_ENDIAN + select ARCH_HAS_NO_MMU + +choice + prompt "Target Processor" + default CONFIG_H8300H + help + This is the processor type of your CPU. + +config CONFIG_H8300H + bool "H8300H" + +config CONFIG_H8S + bool "H8S (edosk2674)" + +endchoice diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.hppa b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.hppa new file mode 100644 index 00000000..1323de22 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.hppa @@ -0,0 +1,17 @@ +# +# For a description of the syntax of this configuration file, +# see extra/config/Kconfig-language.txt +# + +config TARGET_ARCH + string + default "hppa" + +config FORCE_OPTIONS_FOR_ARCH + bool + default y + select ARCH_BIG_ENDIAN + select ARCH_HAS_MMU + select HAS_NO_THREADS + select ARCH_HAS_NO_LDSO + select HAVE_NO_SSP diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.i386 b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.i386 new file mode 100644 index 00000000..288aa5eb --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.i386 @@ -0,0 +1,102 @@ +# +# For a description of the syntax of this configuration file, +# see extra/config/Kconfig-language.txt +# + +config TARGET_ARCH + string + default "i386" + +config FORCE_OPTIONS_FOR_ARCH + bool + default y + select ARCH_LITTLE_ENDIAN + select ARCH_HAS_MMU + +choice + prompt "Target x86 Processor Family" + default CONFIG_486 + help + This is the processor type of your CPU. This information is used for + optimizing purposes. To build a library that will run on all x86 CPU + types (albeit not optimally fast), you can specify "386" here. If + you pick anything other than "386", there is no guarantee that uClibc + will even run on anything other than the selected processor type. + + Here are the settings recommended for greatest speed: + - "Generic 386" select this if your compiler is already setup to + optimize things properly. + - "386" for the AMD/Cyrix/Intel 386DX/DXL/SL/SLC/SX, Cyrix/TI + 486DLC/DLC2, UMC 486SX-S and NexGen Nx586. Only "386" kernels + will run on a 386 class machine. + - "486" for the AMD/Cyrix/IBM/Intel 486DX/DX2/DX4 or + SL/SLC/SLC2/SLC3/SX/SX2 and UMC U5D or U5S. + - "586" for Intel Pentium and other generic Pentium CPUs + - "Pentium-MMX" for the Intel Pentium MMX. + - "Pentium-Pro" for the Intel Pentium Pro/Celeron/Pentium II. + - "Pentium-III" for the Intel Pentium III + and Celerons based on the Coppermine core. + - "Pentium-4" for the Intel Pentium 4. + - "K6" for the AMD K6, K6-II and K6-III (aka K6-3D). + - "Athlon" for the AMD K7 family (Athlon/Duron/Thunderbird). + - "Elan" for the AMD Elan. + - "Crusoe" for the Transmeta Crusoe series. + - "Winchip-C6" for original IDT Winchip. + - "Winchip-2/Winchip-2A/Winchip-3" for IDT Winchip CPUs + - "CyrixIII/VIA C3" for VIA Cyrix III or VIA C3. + - "VIA C3-2 Nehemiah" model 9 and above. + + If you don't know what to do, choose "386". + +config CONFIG_GENERIC_386 + bool "Generic 386" + +config CONFIG_386 + bool "386" + +config CONFIG_486 + bool "486" + +config CONFIG_586 + bool "Pentium/586/K5/5x86/6x86/6x86MX" + +config CONFIG_586MMX + bool "Pentium-MMX" + +config CONFIG_686 + bool "Pentium-Pro" + +config CONFIG_PENTIUMII + bool "Celeron/Pentium-II" + +config CONFIG_PENTIUMIII + bool "Pentium-III/Celeron(Coppermine)/Pentium-III Xeon" + +config CONFIG_PENTIUM4 + bool "Pentium-4/Celeron(P4-based)/Xeon" + +config CONFIG_K6 + bool "K6/K6-II/K6-III" + +config CONFIG_K7 + bool "Athlon/Duron/K7" + +config CONFIG_ELAN + bool "Elan" + +config CONFIG_CRUSOE + bool "Crusoe" + +config CONFIG_WINCHIPC6 + bool "Winchip-C6" + +config CONFIG_WINCHIP2 + bool "Winchip-2/Winchip-2A/Winchip-3" + +config CONFIG_CYRIXIII + bool "CyrixIII/VIA-C3" + +config CONFIG_NEHEMIAH + bool "VIA C3-2 (Nehemiah)" + +endchoice diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.i960 b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.i960 new file mode 100644 index 00000000..798dae0c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.i960 @@ -0,0 +1,15 @@ +# +# For a description of the syntax of this configuration file, +# see extra/config/Kconfig-language.txt +# + +config TARGET_ARCH + string + default "i960" + +config FORCE_OPTIONS_FOR_ARCH + bool + default y + select ARCH_LITTLE_ENDIAN + select ARCH_HAS_NO_MMU + select HAS_NO_THREADS diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.ia64 b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.ia64 new file mode 100644 index 00000000..ae88be77 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.ia64 @@ -0,0 +1,15 @@ +# +# For a description of the syntax of this configuration file, +# see extra/config/Kconfig-language.txt +# + +config TARGET_ARCH + string + default "ia64" + +config FORCE_OPTIONS_FOR_ARCH + bool + default y + select ARCH_LITTLE_ENDIAN + select ARCH_HAS_MMU + select ARCH_HAS_NO_LDSO diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.in b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.in new file mode 100644 index 00000000..aa459e06 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.in @@ -0,0 +1,2365 @@ +# +# For a description of the syntax of this configuration file, +# see extra/config/Kconfig-language.txt +# + +mainmenu "uClibc C Library Configuration" + +config DESIRED_TARGET_ARCH + string + option env="ARCH" + +choice + prompt "Target Architecture" + default TARGET_alpha if DESIRED_TARGET_ARCH = "alpha" + default TARGET_arm if DESIRED_TARGET_ARCH = "arm" + default TARGET_avr32 if DESIRED_TARGET_ARCH = "avr32" + default TARGET_bfin if DESIRED_TARGET_ARCH = "bfin" + default TARGET_cris if DESIRED_TARGET_ARCH = "cris" + default TARGET_e1 if DESIRED_TARGET_ARCH = "e1" + default TARGET_frv if DESIRED_TARGET_ARCH = "frv" + default TARGET_h8300 if DESIRED_TARGET_ARCH = "h8300" + default TARGET_hppa if DESIRED_TARGET_ARCH = "hppa" + default TARGET_i386 if DESIRED_TARGET_ARCH = "i386" + default TARGET_i960 if DESIRED_TARGET_ARCH = "i960" + default TARGET_ia64 if DESIRED_TARGET_ARCH = "ia64" + default TARGET_m68k if DESIRED_TARGET_ARCH = "m68k" + default TARGET_microblaze if DESIRED_TARGET_ARCH = "microblaze" + default TARGET_mips if DESIRED_TARGET_ARCH = "mips" + default TARGET_nios if DESIRED_TARGET_ARCH = "nios" + default TARGET_nios2 if DESIRED_TARGET_ARCH = "nios2" + default TARGET_powerpc if DESIRED_TARGET_ARCH = "powerpc" + default TARGET_sh if DESIRED_TARGET_ARCH = "sh" + default TARGET_sh64 if DESIRED_TARGET_ARCH = "sh64" + default TARGET_sparc if DESIRED_TARGET_ARCH = "sparc" + default TARGET_v850 if DESIRED_TARGET_ARCH = "v850" + default TARGET_vax if DESIRED_TARGET_ARCH = "vax" + default TARGET_x86_64 if DESIRED_TARGET_ARCH = "x86_64" + default TARGET_xtensa if DESIRED_TARGET_ARCH = "xtensa" + help + The architecture of your target. + +config TARGET_alpha + bool "alpha" + +config TARGET_arm + bool "arm" + +config TARGET_avr32 + bool "avr32" + +config TARGET_bfin + bool "bfin" + +config TARGET_cris + bool "cris" + +config TARGET_e1 + bool "e1 (BROKEN)" + +config TARGET_frv + bool "frv (BROKEN)" + +config TARGET_h8300 + bool "h8300 (BROKEN)" + +config TARGET_hppa + bool "hppa" + +config TARGET_i386 + bool "i386" + +config TARGET_i960 + bool "i960 (BROKEN)" + +config TARGET_ia64 + bool "ia64" + +config TARGET_m68k + bool "m68k" + +config TARGET_microblaze + bool "microblaze" + +config TARGET_mips + bool "mips" + +config TARGET_nios + bool "nios" + +config TARGET_nios2 + bool "nios2" + +config TARGET_powerpc + bool "powerpc" + +config TARGET_sh + bool "superh" + +config TARGET_sh64 + bool "sh64" + +config TARGET_sparc + bool "sparc" + +config TARGET_v850 + bool "v850 (BROKEN)" + +config TARGET_vax + bool "vax" + +config TARGET_x86_64 + bool "x86_64" + +config TARGET_xtensa + bool "xtensa" + +endchoice + + +menu "Target Architecture Features and Options" + +if TARGET_alpha +source "extra/Configs/Config.alpha" +endif + +if TARGET_arm +source "extra/Configs/Config.arm" +endif + +if TARGET_avr32 +source "extra/Configs/Config.avr32" +endif + +if TARGET_bfin +source "extra/Configs/Config.bfin" +endif + +if TARGET_cris +source "extra/Configs/Config.cris" +endif + +if TARGET_e1 +source "extra/Configs/Config.e1" +endif + +if TARGET_frv +source "extra/Configs/Config.frv" +endif + +if TARGET_h8300 +source "extra/Configs/Config.h8300" +endif + +if TARGET_hppa +source "extra/Configs/Config.hppa" +endif + +if TARGET_i386 +source "extra/Configs/Config.i386" +endif + +if TARGET_i960 +source "extra/Configs/Config.i960" +endif + +if TARGET_ia64 +source "extra/Configs/Config.ia64" +endif + +if TARGET_m68k +source "extra/Configs/Config.m68k" +endif + +if TARGET_nios +source "extra/Configs/Config.nios" +endif + +if TARGET_nios2 +source "extra/Configs/Config.nios2" +endif + +if TARGET_microblaze +source "extra/Configs/Config.microblaze" +endif + +if TARGET_mips +source "extra/Configs/Config.mips" +endif + +if TARGET_powerpc +source "extra/Configs/Config.powerpc" +endif + +if TARGET_sh +source "extra/Configs/Config.sh" +endif + +if TARGET_sh64 +source "extra/Configs/Config.sh64" +endif + +if TARGET_sparc +source "extra/Configs/Config.sparc" +endif + +if TARGET_v850 +source "extra/Configs/Config.v850" +endif + +if TARGET_vax +source "extra/Configs/Config.vax" +endif + +if TARGET_x86_64 +source "extra/Configs/Config.x86_64" +endif + +if TARGET_xtensa +source "extra/Configs/Config.xtensa" +endif + +config TARGET_SUBARCH + string + default "e500" if CONFIG_E500 + default "classic" if CONFIG_CLASSIC + default "sh4" if CONFIG_SH4 + default "" if CONFIG_GENERIC_386 || CONFIG_386 + default "i486" if CONFIG_486 + default "i586" if CONFIG_586 || CONFIG_586MMX + default "i686" if TARGET_ARCH = "i386" + default "" + +source "extra/Configs/Config.in.arch" + +endmenu + +menu "General Library Settings" + +config HAVE_NO_PIC + bool + default n + +config DOPIC + bool "Generate only Position Independent Code (PIC)" + default y + depends on !HAVE_NO_PIC + help + If you wish to build all of uClibc as PIC objects, then answer Y here. + If you are unsure, then you should answer N. + +config ARCH_HAS_NO_SHARED + bool + default n + +config ARCH_HAS_NO_LDSO + bool + select ARCH_HAS_NO_SHARED + default n + +config HAVE_SHARED + bool "Enable shared libraries" + depends on !ARCH_HAS_NO_SHARED + default y + help + If you wish to build uClibc with support for shared libraries then + answer Y here. If you only want to build uClibc as a static library, + then answer N. + +config FORCE_SHAREABLE_TEXT_SEGMENTS + bool "Only load shared libraries which can share their text segment" + depends on HAVE_SHARED + select DOPIC + default n + help + If you answer Y here, the uClibc native shared library loader will + only load shared libraries, which do not need to modify any + non-writable segments. These libraries haven't set the DT_TEXTREL + tag in the dynamic section (==> objdump). + All your libraries must be compiled with -fPIC or -fpic, and all + assembler function must be written as position independent code (PIC). + Enabling this option will make uClibc's shared library loader a + little bit smaller and guarantee that no memory will be wasted by + badly coded shared libraries. + +config LDSO_LDD_SUPPORT + bool "Native 'ldd' support" + depends on HAVE_SHARED + default y + help + Enable all the code needed to support traditional ldd, + which executes the shared library loader to resolve all dependencies + and then provide a list of shared libraries that are required for an + application to function. Disabling this option will make uClibc's + shared library loader a little bit smaller. + Most people will answer Y. + +config LDSO_CACHE_SUPPORT + bool "Enable library loader cache (ld.so.conf)" + depends on HAVE_SHARED + default y + help + Enable this to make use of /etc/ld.so.conf, the shared library loader + cache configuration file to support for non-standard library paths. + After updating this file, it is necessary to run 'ldconfig' to update + the /etc/ld.so.cache shared library loader cache file. + +config LDSO_PRELOAD_ENV_SUPPORT + bool "Enable library loader LD_PRELOAD environment" + depends on HAVE_SHARED + default y + help + Enable this to make use of LD_PRELOAD environment variable. + A whitespace-separated list of additional, user-specified, ELF shared + libraries to be loaded before all others. This can be used to + selectively override functions in other shared libraries. For + set-user-ID/set-group-ID ELF binaries, only libraries in the standard + search directories that are also set-user-ID will be loaded. + +config LDSO_PRELOAD_FILE_SUPPORT + bool "Enable library loader preload file (ld.so.preload)" + depends on HAVE_SHARED + default n + help + Enable this to make use of /etc/ld.so.preload. This file contains a + whitespace separated list of shared libraries to be loaded before + the program. + +config LDSO_BASE_FILENAME + string "Shared library loader naming prefix" + depends on HAVE_SHARED && (LDSO_CACHE_SUPPORT || LDSO_PRELOAD_FILE_SUPPORT) + default "ld.so" + help + If you wish to support both uClibc and glibc on the same system, it + is necessary to set this to something other than "ld.so" to avoid + conflicts with glibc, which also uses "ld.so". This prevents both + libraries from using the same /etc/ld.so.* files. If you wish to + support both uClibc and glibc on the same system then you should set + this to "ld-uClibc.so". + + Most people will leave this set to the default of "ld.so". + + WARNING: Changing the default prefix could cause problems with + binutils' ld ! + +config UCLIBC_STATIC_LDCONFIG + bool "Link ldconfig statically" + depends on HAVE_SHARED + default y + help + Enable this option to statically link the ldconfig binary. + + Making ldconfig static can be beneficial if you have a library + problem and need to use ldconfig to recover. Sometimes it is + preferable to instead keep the size of the system down, in which + case you should disable this option. + +config LDSO_RUNPATH + bool "Enable ELF RUNPATH tag support" + depends on HAVE_SHARED + default y if LDSO_CACHE_SUPPORT + default n if !LDSO_CACHE_SUPPORT + help + ELF's may have dynamic RPATH/RUNPATH tags. These tags list paths + which extend the library search paths. They are really only useful + if a package installs libraries in non standard locations and + ld.so.conf support is disabled. + + Usage of RUNPATH tags is not too common, so disabling this feature + should be safe for most people. + +config LDSO_SEARCH_INTERP_PATH + bool "Add ldso path to lib search path" + depends on HAVE_SHARED + default y + help + The ldso is told where it is being executed from and can use that + path to find related core libraries. This is useful by default, + but can be annoying in a mixed development environment. + + i.e. if the ldso is run from /foo/boo/ldso.so, it will start its + library search with /foo/boo/ + + If unsure, simply say Y here. + +config UCLIBC_CTOR_DTOR + bool "Support global constructors and destructors" + default y + help + If you wish to build uClibc with support for global constructor + (ctor) and global destructor (dtor) support, then answer Y here. + When ctor/dtor support is enabled, binaries linked with uClibc must + also be linked with crtbegin.o and crtend.o which are provided by gcc + (the "*startfile:" and "*endfile:" settings in your gcc specs file + may need to be adjusted to include these files). This support will + also add a small amount of additional size to each binary compiled vs + uClibc. If you will be using uClibc with C++, or if you need the gcc + __attribute__((constructor)) and __attribute__((destructor)) to work, + then you definitely want to answer Y here. If you don't need ctors + or dtors and want your binaries to be as small as possible, then + answer N. + +config LDSO_GNU_HASH_SUPPORT + bool "Enable GNU hash style support" + depends on HAVE_SHARED + default n + help + Newest binutils support a new hash style named GNU-hash. The dynamic + linker will use the new GNU-hash section (.gnu.hash) for symbol lookup + if present into the ELF binaries, otherwise it will use the old SysV + hash style (.hash). This ensures that it is completely backward + compatible. + Further, being the hash table implementation self-contained into each + executable and shared libraries, objects with mixed hash style can + peacefully coexist in the same process. + + If you want to use this new feature, answer Y + +choice + prompt "Thread support" + #default UCLIBC_HAS_THREADS_NATIVE if (TARGET_alpha || TARGET_arm || TARGET_i386 || TARGET_mips || TARGET_powerpc || TARGET_sh || TARGET_sh64) + default HAS_NO_THREADS + help + If you want to compile uClibc with pthread support, then answer Y. + This will increase the size of uClibc by adding a bunch of locking + to critical data structures, and adding extra code to ensure that + functions are properly reentrant. + +config HAS_NO_THREADS + bool "none" + help + Disable thread support. + +config LINUXTHREADS_OLD + bool "older (stable) version of linuxthreads" + # linuxthreads and linuxthreads.old need nanosleep() + select UCLIBC_HAS_REALTIME + help + There are two versions of linuxthreads. The older (stable) version + has been in uClibc for quite a long time but hasn't seen too many + updates other than bugfixes. + + +config LINUXTHREADS_NEW + bool "slightly newer version of linuxthreads" + help + The new version has not been tested much, and lacks ports for arches + which glibc does not support (like bfin/frv/etc...), but is based on + the latest code from glibc, so it may be the only choice for the + newer ports (like alpha/amd64/64bit arches and hppa). + +config UCLIBC_HAS_THREADS_NATIVE + bool "Native POSIX Threading (NPTL)" + select UCLIBC_HAS_TLS + select UCLIBC_HAS_STDIO_FUTEXES + # NPTL local: + select EXTRA_WARNINGS + # i386 has no lowlevellock support (yet) as opposed to i486 onward + depends on !CONFIG_386 + help + If you want to compile uClibc with NPTL support, then answer Y. + + IMPORTANT NOTE! NPTL requires a Linux 2.6 kernel, binutils + at least version 2.16 and GCC with at least version 4.1.0. NPTL + will not work with older versions of any above sources. If you + ignore any of these guidelines, you do so at your own risk. Do + not ask for help on any of the development mailing lists. + + !!!! WARNING !!!! BIG FAT WARNING !!!! REALLY BIG FAT WARNING !!!! + + This is experimental code and at times it may not even build and + even if it does it might decide to do random damage. This code is + potentially hazardous to your health and sanity. It will remain + that way until further notice at which point this notice will + disappear. Thank you for your support and for not smoking. + +endchoice + +config UCLIBC_HAS_THREADS + def_bool y if !HAS_NO_THREADS + +config UCLIBC_HAS_TLS + bool "Thread-Local Storage" + depends on UCLIBC_HAS_THREADS_NATIVE + default n + help + If you want to enable TLS support then answer Y. + This is fast an efficient way to store per-thread local data + which is not on stack. It needs __thread support enabled in + gcc. + +config PTHREADS_DEBUG_SUPPORT + bool "Build pthreads debugging support" + default n + depends on UCLIBC_HAS_THREADS + help + Say Y here if you wish to be able to debug applications that use + uClibc's pthreads library. By enabling this option, a library + named libthread_db will be built. This library will be dlopen()'d + by gdb and will allow gdb to debug the threads in your application. + + IMPORTANT NOTE! Because gdb must dlopen() the libthread_db library, + you must compile gdb with uClibc in order for pthread debugging to + work properly. + + If you are doing development and want to debug applications using + uClibc's pthread library, answer Y. Otherwise, answer N. + + +config UCLIBC_HAS_SYSLOG + bool "Syslog support" + default y + depends on UCLIBC_HAS_NETWORK_SUPPORT + select UCLIBC_HAS_SOCKET + help + Support sending messages to the system logger. + This requires socket-support. + +config UCLIBC_HAS_LFS + bool "Large File Support" + default y + help + If you wish to build uClibc with support for accessing large files + (i.e. files greater then 2 GiB) then answer Y. Do not enable this + if you are using an older Linux kernel (2.0.x) that lacks large file + support. Enabling this option will increase the size of uClibc. + +choice + prompt "Malloc Implementation" + default MALLOC if ! ARCH_USE_MMU + default MALLOC_STANDARD if ARCH_USE_MMU + +config MALLOC + bool "malloc" + help + "malloc" use mmap for all allocations and so works very well on + MMU-less systems that do not support the brk() system call. It is + pretty smart about reusing already allocated memory, and minimizing + memory wastage. + This is the default for uClinux MMU-less systems. + +config MALLOC_SIMPLE + bool "malloc-simple" + help + "malloc-simple" is trivially simple and slow as molasses. It + was written from scratch for uClibc, and is the simplest possible + (and therefore smallest) malloc implementation. + + This uses only the mmap() system call to allocate and free memory, + and does not use the brk() system call at all, making it a fine + choice for MMU-less systems with very limited memory. It's 100% + standards compliant, thread safe, very small, and releases freed + memory back to the OS immediately rather than keeping it in the + process's heap for reallocation. It is also VERY SLOW. + +config MALLOC_STANDARD + bool "malloc-standard" + depends on ARCH_USE_MMU + help + "malloc-standard" is derived from the public domain dlmalloc + implementation by Doug Lea. It is quite fast, and is pretty smart + about reusing already allocated memory, and minimizing memory + wastage. This uses brk() for small allocations, while using mmap() + for larger allocations. This is the default malloc implementation + for uClibc. + + If unsure, answer "malloc-standard". + +endchoice + +config MALLOC_GLIBC_COMPAT + bool "Malloc returns live pointer for malloc(0)" + default n + help + The behavior of malloc(0) is listed as implementation-defined by + SuSv3. Glibc returns a valid pointer to something, while uClibc + normally returns NULL. I personally feel glibc's behavior is + not particularly safe, and allows buggy applications to hide very + serious problems. + + When this option is enabled, uClibc will act just like glibc, and + return a live pointer when someone calls malloc(0). This pointer + provides a malloc'ed area with a size of 1 byte. This feature is + mostly useful when dealing with applications using autoconf's broken + AC_FUNC_MALLOC macro (which redefines malloc as rpl_malloc if it + does not detect glibc style returning-a-valid-pointer-for-malloc(0) + behavior). Most people can safely answer N. + +config UCLIBC_DYNAMIC_ATEXIT + bool "Dynamic atexit() Support" + default y + help + When this option is enabled, uClibc will support an infinite number, + of atexit() and on_exit() functions, limited only by your available + memory. This can be important when uClibc is used with C++, since + global destructors are implemented via atexit(), and it is quite + possible to exceed the default number when this option is disabled. + Enabling this option adds a few bytes, and more significantly makes + atexit and on_exit depend on malloc, which can be bad when compiling + static executables. + + Unless you use uClibc with C++, you should probably answer N. + +config COMPAT_ATEXIT + bool "Old (visible) atexit Support" + default n + help + Enable this option if you want to update from 0.9.28 to git/0.9.29, + else you will be missing atexit() until you rebuild all apps. + +config UCLIBC_SUSV3_LEGACY + bool "Enable SuSv3 LEGACY functions" + default n + #vfork, + # h_errno + # gethostbyaddr + # gethostbyname + help + Enable this option if you want to have SuSv3 LEGACY functions + in the library, else they are replaced by SuSv3 proposed macros. + Currently applies to: + + bcmp, bcopy, bzero, index, rindex, ftime, + bsd_signal, (ecvt), (fcvt), gcvt, (getcontext), + (getwd), (makecontext), + mktemp, (pthread_attr_getstackaddr), (pthread_attr_setstackaddr), + scalb, (setcontext), (swapcontext), ualarm, usleep, + wcswcs. + + WARNING! ABI incompatibility. + +config UCLIBC_SUSV3_LEGACY_MACROS + bool "Enable SuSv3 LEGACY macros" + default n + help + Enable this option if you want to have SuSv3 LEGACY macros. + Currently applies to bcopy/bzero/bcmp/index/rindex et al. + WARNING! ABI incompatibility. + +config UCLIBC_SUSV4_LEGACY + bool "Enable SuSv4 LEGACY or obsolescent functions" + default n + help + Enable this option if you want to have SuSv4 LEGACY functions + and macros in the library. + Currently applies to: + + - XSI functions: + _longjmp, _setjmp, _tolower, _toupper, ftw, getitimer, + gettimeofday, isascii, pthread_getconcurrency, + pthread_setconcurrency, setitimer, setpgrp, sighold, + sigignore, sigpause, sigrelse, sigset, siginterrupt, + tempnam, toascii, ulimit. + + - Base functions: + asctime, asctime_r, ctime, ctime_r, gets, rand_r, + tmpnam, utime. + + WARNING! ABI incompatibility. + +config UCLIBC_HAS_STUBS + bool "Provide stubs for unavailable functionality" + default n + help + With this option uClibc provides non-functional stubs for + functions which are impossible to implement on the target + architecture. Otherwise, such functions are simply omitted. + + As of 2008-07, this option makes uClibc provide fork() stub + on NOMMU targets. It always sets errno to ENOSYS and returns -1. + + This may be useful if you port a lot of software and cannot + audit all of it and replace or disable fork() usage. + With this option, a program which uses fork() will build + successfully. Of course, it may be useless if fork() + is essential for its operation. + +config UCLIBC_HAS_SHADOW + bool "Shadow Password Support" + default y + help + Answer N if you do not need shadow password support. + Most people will answer Y. + +config UCLIBC_HAS_PROGRAM_INVOCATION_NAME + bool "Support for program_invocation_name" + default n + help + Support for the GNU-specific program_invocation_name and + program_invocation_short_name strings. Some GNU packages + (like tar and coreutils) utilize these for extra useful + output, but in general are not required. + + At startup, these external strings are automatically set + up based on the value of ARGV[0]. + + If unsure, just answer N. + +config UCLIBC_HAS___PROGNAME + bool "Support for __progname" + default y + depends on UCLIBC_HAS_PROGRAM_INVOCATION_NAME + help + Some packages (like openssh) like to peek into internal libc + symbols to make their output a bit more user friendly. + + At startup, __progname is automatically set up based on the + value of ARGV[0]. + + If unsure, just answer N. + +config UCLIBC_HAS_PTY + bool "Support for pseudo-terminals" + default y + help + This enables support for pseudo-terminals (see man 4 pts + and man 7 pty). + + If unsure, just answer Y. + +config ASSUME_DEVPTS + bool "Assume that /dev/pts is a devpts or devfs file system" + default y + depends on UCLIBC_HAS_PTY + help + Enable this if /dev/pts is on a devpts or devfs filesystem. Both + these filesystems automatically manage permissions on the /dev/pts + devices. You may need to mount your devpts or devfs filesystem on + /dev/pts for this to work. + + Most people should answer Y. + +config UNIX98PTY_ONLY + bool "Support only Unix 98 PTYs" + default y + depends on UCLIBC_HAS_PTY + help + If you want to support only Unix 98 PTYs enable this. Some older + applications may need this disabled and will thus use legacy BSD + style PTY handling which is more complex and also bigger than + Unix 98 PTY handling. + + For most current programs, you can generally answer Y. + +if UNIX98PTY_ONLY +config UCLIBC_HAS_GETPT + bool "Support getpt() (glibc-compat)" + default n + depends on UCLIBC_HAS_PTY + help + Some packages may need getpt(). + All of those are non-standard and can be considered + GNU/libc compatibility. + Either use posix_openpt() or just open /dev/ptmx yourself. + + If unsure, just say N. +endif + +if !UNIX98PTY_ONLY +# Have to use __libc_ptyname{1,2}[] and related bloat +config UCLIBC_HAS_GETPT + def_bool y +endif + +config UCLIBC_HAS_LIBUTIL + bool "Provide libutil library and functions" + depends on UCLIBC_HAS_PTY + default n + help + Provide a libutil library. + This non-standard conforming library provides the following + utility functions: + + forkpty(): combines openpty(), fork(2), and login_tty() to + create a new process operating in a pseudo-terminal. + login(): write utmp and wtmp entries + login_tty(): prepares for a login on the tty fd by creating a + new session, making fd the controlling terminal for + the calling process, setting fd to be the standard + input, output, and error streams of the current + process, and closing fd. + logout(): write utmp and wtmp entries + logwtmp(): constructs a utmp structure and calls updwtmp() to + append the structure to the utmp file. + openpty(): finds an available pseudo-terminal and returns + file descriptors for the master and slave + + This library adds about 3k-4k to your system. + +config UCLIBC_HAS_TM_EXTENSIONS + bool "Support 'struct tm' timezone extension fields" + default y + help + Enabling this option adds fields to 'struct tm' in time.h for + tracking the number of seconds east of UTC, and an abbreviation for + the current timezone. These fields are not specified by the SuSv3 + standard, but they are commonly used in both GNU and BSD application + code. + + To strictly follow the SuSv3 standard, leave this disabled. + Most people will probably want to answer Y. + +config UCLIBC_HAS_TZ_CACHING + bool "Enable caching of the last valid timezone 'TZ' string" + default y + help + Answer Y to enable caching of the last valid 'TZ' string describing + the timezone setting. This allows a quick string compare to avoid + repeated parsing of unchanged 'TZ' strings when tzset() is called. + + Most people will answer Y. + +config UCLIBC_HAS_TZ_FILE + bool "Enable '/etc/TZ' file support to set a default timezone (uClibc-specific)" + default y + help + Answer Y to enable the setting of a default timezone for uClibc. + + Ordinarily, uClibc gets the timezone information exclusively from the + 'TZ' environment variable. In particular, there is no support for + the zoneinfo directory tree or the /etc/timezone file used by glibc. + + With this option enabled, uClibc will use the value stored in the + file '/etc/TZ' (default path) to obtain timezone information if the + 'TZ' environment variable is missing or has an invalid value. The + file consists of a single line (newline required) of text describing + the timezone in the format specified for the TZ environment variable. + + Doing 'echo CST6CDT > /etc/TZ' is enough to create a valid file. + See + http://www.opengroup.org/onlinepubs/007904975/basedefs/xbd_chap08.html + for details on valid settings of 'TZ'. + + Most people will answer Y. + +config UCLIBC_HAS_TZ_FILE_READ_MANY + bool "Repeatedly read the '/etc/TZ' file" + depends on UCLIBC_HAS_TZ_FILE + default y + help + Answer Y to enable repeated reading of the '/etc/TZ' file even after + a valid value has been read. This incurs the overhead of an + open/read/close for each tzset() call (explicit or implied). However, + setting this will allow applications to update their timezone + information if the contents of the file change. + + Most people will answer Y. + +config UCLIBC_TZ_FILE_PATH + string "Path to the 'TZ' file for setting the global timezone" + depends on UCLIBC_HAS_TZ_FILE + default "/etc/TZ" + help + This is the path to the 'TZ' file. + + Most people will use the default of '/etc/TZ'. + +config UCLIBC_FALLBACK_TO_ETC_LOCALTIME + bool "Use /etc/localtime as a fallback" + depends on UCLIBC_HAS_TZ_FILE + default y + help + Answer Y to try to use /etc/localtime file. + On glibc systems this file (if it is in TZif2 format) + contains timezone string at the end. + + Most people will answer Y. + +endmenu + +menu "Advanced Library Settings" + +config UCLIBC_PWD_BUFFER_SIZE + int "Buffer size for getpwnam() and friends" + default 256 + range 12 1024 + help + This sets the value of the buffer size for getpwnam() and friends. + By default, this is 256. (For reference, glibc uses 1024). + The value can be found using sysconf() with the _SC_GETPW_R_SIZE_MAX + parameter. + +config UCLIBC_GRP_BUFFER_SIZE + int "Buffer size for getgrnam() and friends" + default 256 + range 12 1024 + help + This sets the value of the buffer size for getgrnam() and friends. + By default, this is 256. (For reference, glibc uses 1024). + The value can be found using sysconf() with the _SC_GETGR_R_SIZE_MAX + parameter. + +comment "Support various families of functions" + +config UCLIBC_LINUX_MODULE_24 + bool "Linux kernel module functions" + default !(TARGET_bfin) + help + create_module, query_module + are used in linux (prior to 2.6) for loadable kernel modules. + + Say N if you do not use kernel modules, or you only support + Linux 2.6+. + +config UCLIBC_LINUX_SPECIFIC + bool "Linux specific functions" + default y + help + capget(), capset(), fstatfs(), inotify_*(), ioperm(), iopl(), + madvise(), modify_ldt(), personality(), prctl()/arch_prctl(), + ppoll(), readahead(), reboot(), remap_file_pages(), + sched_getaffinity(), sched_setaffinity(), sendfile(), + setfsgid(), setfsuid(), setresuid(), + splice(), vmsplice(), tee(), signalfd(), swapoff(), swapon(), + sync_file_range(), sysctl(), sysinfo(), vhangup() + +config UCLIBC_HAS_GNU_ERROR + bool "Support GNU extensions for error-reporting" + default y + help + Support for the GNU-specific error(), error_at_line(), + void (* error_print_progname)(), error_message_count + functions and variables. Some GNU packages + utilize these for extra useful output, but in general + are not required. + + If unsure, just answer N. + +config UCLIBC_BSD_SPECIFIC + bool "BSD specific functions" + default y + help + mincore(), getdomainname(), setdomainname() + + If unsure, say N. + +config UCLIBC_HAS_BSD_ERR + bool "BSD err functions" + default y + help + These functions are non-standard BSD extensions. + err(), errx(), warn(), warnx(), verr(), verrx(), vwarn(), vwarnx() + + If unsure, say N. + +config UCLIBC_HAS_OBSOLETE_BSD_SIGNAL + bool "BSD obsolete signal functions" + default n + help + These functions are provided as a compatibility interface for + programs that make use of the historical System V signal API. + This API is obsolete: + new applications should use the POSIX signal API (sigaction(2), + sigprocmask(2), etc.). + Affected functions: + + sigset(), sighold(), sigrelse(), sigignore() + + If unsure, say N. + +config UCLIBC_HAS_OBSOLETE_SYSV_SIGNAL + bool "SYSV obsolete signal functions" + default n + help + Use of sysv_signal() should be avoided; use sigaction(2) instead. + + If unsure, say N. + +config UCLIBC_NTP_LEGACY + bool "ntp_*() aliases" + default n + help + Provide legacy aliases for ntp functions: + ntp_adjtime(), ntp_gettime() + + It is safe to say N here. + +config UCLIBC_SV4_DEPRECATED + bool "Enable SVr4 deprecated functions" + default n + help + These functions are DEPRECATED in System V release 4. + Say N unless you desparately need one of the functions below: + + ustat() [use statfs(2) in your code instead] + +config UCLIBC_HAS_REALTIME + bool "Realtime-related family of SUSv functions" + default y + help + These functions are part of the Timers option and need not + be available on all implementations. + Includes AIO, message-queue, scheduler, semaphore functions: + + aio.h + mqueue.h + sched.h + semaphore.h + + aio_cancel() + aio_error() + aio_fsync() + aio_read() + lio_listio() + aio_return() + aio_suspend() + aio_write() + clock_getres(), clock_gettime(), clock_settime() + fdatasync() + mlockall(), munlockall() + mlock(), munlock() + mq_close() + mq_getattr() + mq_notify() + mq_open() + mq_receive() + mq_send() + mq_setattr() + mq_unlink() + nanosleep() + sched_getparam() + sched_get_priority_max(), sched_get_priority_min() + sched_getscheduler() + sched_rr_get_interval() + sched_setparam() + sched_setscheduler() + sem_close() + sem_destroy() + sem_getvalue() + sem_init() + sem_open() + sem_post() + sem_trywait(), sem_wait() + sem_unlink() + sigqueue() + sigtimedwait(), sigwaitinfo() + timer_create() + timer_delete() + timer_getoverrun(), timer_gettime(), timer_settime() + +config UCLIBC_HAS_ADVANCED_REALTIME + bool "Advanced realtime-related family of SUSv functions" + default y + depends on UCLIBC_HAS_REALTIME + help + These functions are part of the Timers option and need not + be available on all implementations. + + clock_getcpuclockid() + clock_nanosleep() + mq_timedreceive() + mq_timedsend() + posix_fadvise() + posix_fallocate() + posix_madvise() + posix_memalign() + posix_mem_offset() + posix_spawnattr_destroy(), posix_spawnattr_init() + posix_spawnattr_getflags(), posix_spawnattr_setflags() + posix_spawnattr_getpgroup(), posix_spawnattr_setpgroup() + posix_spawnattr_getschedparam(), posix_spawnattr_setschedparam() + posix_spawnattr_getschedpolicy(), posix_spawnattr_setschedpolicy() + posix_spawnattr_getsigdefault(), posix_spawnattr_setsigdefault() + posix_spawnattr_getsigmask(), posix_spawnattr_setsigmask() + posix_spawn_file_actions_addclose() + posix_spawn_file_actions_adddup2() + posix_spawn_file_actions_addopen() + posix_spawn_file_actions_destroy() + posix_spawn_file_actions_init() + posix_spawn() + posix_spawnp() + posix_typed_mem_get_info() + pthread_mutex_timedlock() + sem_timedwait() + +#config UCLIBC_HAS_TERMIOS +# bool "termios functions" +# default y +# help +# Get and set terminal attributes, line control, get and set baud +# rate. +# termios(), tcgetattr(), tcsetattr(), tcsendbreak(), tcdrain(), +# tcflush(), tcflow(), cfmakeraw(), cfgetospeed(), cfgetispeed(), +# cfsetispeed(), cfsetospeed(), cfsetspeed() +# +# If unsure, say Y. + +config UCLIBC_HAS_EPOLL + bool "epoll" + default y + help + epoll_create(), epoll_ctl(), epoll_wait() functions. + +config UCLIBC_HAS_XATTR + bool "Extended Attributes" + default y + help + Extended Attributes support. + + setxattr() + lsetxattr() + fsetxattr() + getxattr() + lgetxattr() + fgetxattr() + listxattr() + llistxattr() + flistxattr() + removexattr() + lremovexattr() + fremovexattr() + + Say N unless you need support for extended attributes and the + filesystems do actually support them. + +config UCLIBC_HAS_PROFILING + bool "Profiling support" + default y + help + gcc's -finstrument-functions needs these. + + Most people can safely answer N. + +config UCLIBC_HAS_CRYPT_IMPL + bool "libcrypt support" + default y + help + libcrypt contains crypt(), setkey() and encrypt() + +config UCLIBC_HAS_CRYPT_STUB + bool "libcrypt stubs" + default y + depends on !UCLIBC_HAS_CRYPT_IMPL + help + Standards mandate that crypt(3) provides a stub if it is unavailable. + If you enable this option then stubs for + crypt(), setkey() and encrypt() + will be provided in a small libcrypt. + +config UCLIBC_HAS_CRYPT + def_bool y + depends on UCLIBC_HAS_CRYPT_IMPL || UCLIBC_HAS_CRYPT_STUB +endmenu + +menuconfig UCLIBC_HAS_NETWORK_SUPPORT + bool "Networking Support" + default y + help + Say N here if you do not need network support. + +if UCLIBC_HAS_NETWORK_SUPPORT +config UCLIBC_HAS_SOCKET + bool "Socket support" + default y + help + If you want to include support for sockets then answer Y. + +config UCLIBC_HAS_IPV4 + bool "IP version 4 support" + default y + select UCLIBC_HAS_SOCKET + help + If you want to include support for the Internet Protocol + (IP version 4) then answer Y. + + Most people will say Y. + +config UCLIBC_HAS_IPV6 + bool "IP version 6 support" + default n + select UCLIBC_HAS_SOCKET + help + If you want to include support for the next version of the Internet + Protocol (IP version 6) then answer Y. + + Most people should answer N. + +config UCLIBC_HAS_RPC + bool "Remote Procedure Call (RPC) support" + default n + # RPC+socket-ipvX doesn't currently work. + depends on UCLIBC_HAS_IPV4 || UCLIBC_HAS_IPV6 + help + If you want to include RPC support, enable this. RPC is rarely used + for anything except for the NFS filesystem. Unless you plan to use + NFS, you can probably leave this set to N and save some space. + + If you need to use NFS then you should answer Y. + +config UCLIBC_HAS_FULL_RPC + bool "Full RPC support" + depends on UCLIBC_HAS_RPC + default y if !HAVE_SHARED + help + Normally we enable just enough RPC support for things like rshd and + nfs mounts to work. If you find you need the rest of the RPC stuff, + then enable this option. Most people can safely answer N. + +config UCLIBC_HAS_REENTRANT_RPC + bool "Reentrant RPC support" + depends on UCLIBC_HAS_RPC + default y if !HAVE_SHARED + help + Most packages utilize the normal (non-reentrant) RPC functions, but + some (like exportfs from nfs-utils) need these reentrant versions. + + Most people can safely answer N. + +config UCLIBC_USE_NETLINK + bool "Use netlink to query interfaces" + default n + depends on UCLIBC_HAS_SOCKET + help + In newer versions of Linux (2.4.17+), support was added for querying + network device information via netlink rather than the old style + ioctl's. Most of the time, the older ioctl style is sufficient (and + it is smaller than netlink), but if you find that not all of your + devices are being returned by the if_nameindex() function, you will + have to use the netlink implementation. + + Most people can safely answer N. + +config UCLIBC_SUPPORT_AI_ADDRCONFIG + bool "Support the AI_ADDRCONFIG flag" + depends on UCLIBC_USE_NETLINK + default n + help + The implementation of AI_ADDRCONFIG is aligned with the glibc + implementation using netlink to query interfaces to find both + ipv4 and ipv6 support. This is only needed if an application uses + the AI_ADDRCONFIG flag. + + Most people can safely answer N. + +config UCLIBC_HAS_BSD_RES_CLOSE + bool "Support res_close() (bsd-compat)" + default n + help + Answer Y if you desperately want to support BSD compatibility in + the network code. + + Most people will say N. + +config UCLIBC_HAS_COMPAT_RES_STATE + bool "Use compatible but bloated _res" + default y + help + Answer Y if you build network utilities and they muck with resolver + internals a lot (_res global structure). uclibc does not use most + of _res.XXX fields, and with this option OFF they won't even exist. + Which will make e.g. dig build fail. + Answering N saves around 400 bytes in bss. + +config UCLIBC_HAS_EXTRA_COMPAT_RES_STATE + bool "Use extra compatible but extra bloated _res" + default n + help + Answer Y if selecting UCLIBC_HAS_COMPAT_RES_STATE is not enough. + As far as I can say, this should never be needed. + +config UCLIBC_HAS_LIBRESOLV_STUB + bool "Provide libresolv stub" + default n + help + Provide a dummy resolv library. + +config UCLIBC_HAS_LIBNSL_STUB + bool "Provide libnsl stub" + default n + help + Provide a dummy nsl library. + +endif + + +menu "String and Stdio Support" + +config UCLIBC_HAS_STRING_GENERIC_OPT + bool "Use faster (but larger) generic string functions" + default y + help + Answer Y to use the (tweaked) glibc generic string functions. + + In general, they are faster (but 3-5K larger) than the base + uClibc string functions which are optimized solely for size. + + Many people will answer Y. + +config UCLIBC_HAS_STRING_ARCH_OPT + bool "Use arch-specific assembly string functions (where available)" + default y + help + Answer Y to use any archtecture-specific assembly language string + functions available for this target plaform. + + Note that assembly implementations are not available for all string + functions, so some generic (written in C) string functions may + still be used. + + These are small and fast, the only reason _not_ to say Y here is + for debugging purposes. + +config UCLIBC_HAS_CTYPE_TABLES + bool "Use Table Versions Of 'ctype.h' Functions." + default y + help + Answer Y to use table versions of the 'ctype.h' functions. + While the non-table versions are often smaller when building + statically linked apps, they work only in stub locale mode. + + Most people will answer Y. + +config UCLIBC_HAS_CTYPE_SIGNED + bool "Support Signed Characters In 'ctype.h' Functions." + depends on UCLIBC_HAS_CTYPE_TABLES + default y + help + Answer Y to enable support for passing signed char values to + the 'ctype.h' functions. ANSI/ISO C99 and SUSv3 specify that + these functions are only defined for unsigned char values and + EOF. However, glibc allows negative signed char values as well + in order to support 'broken old programs'. + + Most people will answer Y. + +choice + prompt "ctype argument checking" + depends on UCLIBC_HAS_CTYPE_TABLES + default UCLIBC_HAS_CTYPE_UNSAFE + help + Please select the invalid arg behavior you want for the 'ctype' + functions. + + The 'ctype' functions are now implemented using table lookups, with + the arg being the index. This can result in incorrect memory accesses + or even segfaults for args outside of the allowed range. + + NOTE: This only affects the 'ctype' _functions_. It does not affect + the macro implementations. + +config UCLIBC_HAS_CTYPE_UNSAFE + bool "Do not check -- unsafe" + +config UCLIBC_HAS_CTYPE_CHECKED + bool "Detect and handle appropriately" + +config UCLIBC_HAS_CTYPE_ENFORCED + bool "Issue a diagnostic and abort()" + +endchoice + + +config UCLIBC_HAS_WCHAR + bool "Wide Character Support" + default n + help + Answer Y to enable wide character support. This will make uClibc + much larger. It is also currently required for locale support. + + Most people will answer N. + +config UCLIBC_HAS_LOCALE + bool "Locale Support" + select UCLIBC_HAS_WCHAR + select UCLIBC_HAS_CTYPE_TABLES + default n + help + uClibc now has full ANSI/ISO C99 locale support (except for + wcsftime() and collating items in regex). Be aware that enabling + this option will make uClibc much larger. + + Enabling UCLIBC_HAS_LOCALE with the default set of supported locales + (169 UTF-8 locales, and 144 locales for other codesets) will enlarge + uClibc by around 300k. You can reduce this size by building your own + custom set of locate data (see extra/locale/LOCALES for details). + + uClibc's locale support is still under development. For example, + codesets using shift states are not currently supported. Support is + planned in the next iteration of locale support. + + Answer Y to enable locale support. Most people will answer N. + +choice + +prompt "Locale data" + depends on UCLIBC_HAS_LOCALE + default UCLIBC_BUILD_ALL_LOCALE + +config UCLIBC_BUILD_ALL_LOCALE + bool "All locales" + depends on UCLIBC_HAS_LOCALE + help + This builds all the locales that are available on your + host-box. + +config UCLIBC_BUILD_MINIMAL_LOCALE + bool "Only selected locales" + depends on UCLIBC_HAS_LOCALE + help + If you do not need all locales that are available on your + host-box, then set this to 'Y'. + +config UCLIBC_PREGENERATED_LOCALE_DATA + bool "Use Pre-generated Locale Data" + depends on UCLIBC_HAS_LOCALE + help + Use pre-built locale data. + + Note that these pregenerated locales are sensitive to your + target architecture (endianess, bitcount). + + Saying N here is highly recommended. + +endchoice + +config UCLIBC_BUILD_MINIMAL_LOCALES + string "locales to use" + depends on UCLIBC_BUILD_MINIMAL_LOCALE + default "en_US" + help + Space separated list of locales to use. + + E.g.: + en_US en_GB de_AT + default: + en_US + +config UCLIBC_DOWNLOAD_PREGENERATED_LOCALE_DATA + bool "Automagically Download the Pre-generated Locale Data (if necessary)" + depends on UCLIBC_PREGENERATED_LOCALE_DATA + default n + help + If you would like the build process to use 'wget' to automatically + download the pregenerated locale data, enable this option. Otherwise + you will need to obtain the locale data yourself from: + http://www.uclibc.org/downloads/uClibc-locale-*.tgz + and place the uClibc-locale-*.tgz tarball in the extra/locale/ + directory. + + Note that the use of pregenerated locale data is discouraged. + +config UCLIBC_HAS_XLOCALE + bool "Extended Locale Support (experimental/incomplete)" + depends on UCLIBC_HAS_LOCALE + default n + help + Answer Y to enable extended locale support similar to that provided + by glibc. This is primarily intended to support libstd++ + functionality. + However, it also allows thread-specific locale selection via + uselocale(). + + Most people will answer N. + +config UCLIBC_HAS_HEXADECIMAL_FLOATS + bool "Support hexadecimal float notation" + depends on UCLIBC_HAS_CTYPE_TABLES + depends on UCLIBC_HAS_FLOATS + default n + help + Answer Y to enable support for hexadecimal float notation in the + (wchar and) char string to floating point conversion functions, as + well as support for the %a and %A conversion specifiers in the + *printf() and *scanf() functions. + + Most people will answer N. + +config UCLIBC_HAS_GLIBC_DIGIT_GROUPING + bool "Support glibc's \"'\" flag for allowing locale-specific digit grouping" + depends on UCLIBC_HAS_LOCALE + depends on UCLIBC_HAS_FLOATS + default n + help + Answer Y to enable support for glibc's \"'\" flag for allowing + locale-specific digit grouping in base 10 integer conversions and + appropriate floating point conversions in the *printf() and *scanf() + functions. + + Most people will answer N. + +config UCLIBC_HAS_SCANF_LENIENT_DIGIT_GROUPING + bool "Do not require digit grouping when the \"'\" flag is specified" + depends on UCLIBC_HAS_GLIBC_DIGIT_GROUPING + default y + help + Answer Y to make digit grouping optional when the \"'\" flag is + specified. + This is the standard glibc behavior. If the initial string of digits + exceeds the maximum group number, the input will be treated as a + normal non-grouped number. + + Most people will answer N. + +config UCLIBC_HAS_GLIBC_CUSTOM_PRINTF + bool "Support glibc's register_printf_function() (glibc-compat)" + depends on !USE_OLD_VFPRINTF + default n + help + Answer Y to support glibc's register_printf_function() to allow an + application to add its own printf conversion specifiers. + + NOTE: Limits the number or registered specifiers to 10. + NOTE: Requires new conversion specifiers to be ASCII + characters (0-0x7f). This is to avoid problems with processing + format strings in locales with different multibyte conversions. + + Most people will answer N. + +config USE_OLD_VFPRINTF + bool "Use the old vfprintf implementation" + depends on !UCLIBC_HAS_WCHAR + default n + help + Set to true to use the old vfprintf instead of the new. This is + roughly C89 compliant with some extensions, and is much smaller. + However, it does not support wide chars, positional args, or glibc + custom printf specifiers. + + Most people will answer N. + +config UCLIBC_PRINTF_SCANF_POSITIONAL_ARGS + int "Maximum number of positional args. Either 0 or >= 9." + depends on !USE_OLD_VFPRINTF + default 9 + help + Set the maximum number of positional args supported by the + printf/scanf functions. The Single Unix Specification Version 3 + requires a minimum value of 9. Setting this to a value lower than + 9 will disable positional arg support and cause the NL_ARGMAX macro + in limits.h to be #undef'd. + + WARNING! The workspace to support positional args is currently + allocated on the stack. You probably don't want to set + this to too high a value. + + Most people will answer 9. + + +config UCLIBC_HAS_SCANF_GLIBC_A_FLAG + bool "Support glibc's 'a' flag for scanf string conversions (not implemented)" + default n + help + NOTE!!! Currently Not Implemented!!! Just A Place Holder!! NOTE!!! + NOTE!!! Conflicts with an ANSI/ISO C99 scanf flag!! NOTE!!! + + Answer Y to enable support for glibc's 'a' flag for the scanf string + conversions '%s', '%[', '%ls', '%l[', and '%S'. This is used to + auto-allocate sufficient memory to hold the data retrieved. + + Most people will answer N. + +choice + prompt "Stdio buffer size" + default UCLIBC_HAS_STDIO_BUFSIZ_4096 + help + Please select a value for BUFSIZ. This will be used by the + stdio subsystem as the default buffer size for a file, and + affects fopen(), setvbuf(), etc. + + NOTE: Setting this to 'none' will disable buffering completely. + However, BUFSIZ will still be defined in stdio.h as 256 because + many applications use this value. + +config UCLIBC_HAS_STDIO_BUFSIZ_NONE + bool "none (WARNING - BUFSIZ will be 256 in stdio.h)" + depends on !UCLIBC_HAS_WCHAR + +config UCLIBC_HAS_STDIO_BUFSIZ_256 + bool "256 (minimum ANSI/ISO C99 value)" + +config UCLIBC_HAS_STDIO_BUFSIZ_512 + bool "512" + +config UCLIBC_HAS_STDIO_BUFSIZ_1024 + bool "1024" + +config UCLIBC_HAS_STDIO_BUFSIZ_2048 + bool "2048" + +config UCLIBC_HAS_STDIO_BUFSIZ_4096 + bool "4096" + +config UCLIBC_HAS_STDIO_BUFSIZ_8192 + bool "8192" + +# If you add more choices, you will need to update uClibc_stdio.h. + +endchoice + +choice + prompt "Stdio builtin buffer size (uClibc-specific)" + depends on !UCLIBC_HAS_STDIO_BUFSIZ_NONE + default UCLIBC_HAS_STDIO_BUILTIN_BUFFER_NONE + help + When a FILE is created with fopen(), an attempt is made to allocate + a BUFSIZ buffer for it. If the allocation fails, fopen() will still + succeed but the FILE will be unbuffered. + + This option adds a small amount of space to each FILE to act as an + emergency buffer in the event of a buffer allocation failure. + + Most people will answer None. + +config UCLIBC_HAS_STDIO_BUILTIN_BUFFER_NONE + bool "None" + +config UCLIBC_HAS_STDIO_BUILTIN_BUFFER_4 + bool "4" + +config UCLIBC_HAS_STDIO_BUILTIN_BUFFER_8 + bool "8" + +# If you add more choices, you will need to update uClibc_stdio.h. + +endchoice + +config UCLIBC_HAS_STDIO_SHUTDOWN_ON_ABORT + bool "Attempt to shutdown stdio subsystem when abort() is called." + default n + help + ANSI/ISO C99 requires abort() to be asyn-signal-safe. So there was + a behavioral change made in SUSv3. Previously, abort() was required + to have the affect of fclose() on all open streams. The wording has + been changed to "may" from "shall". + + Most people will answer N. + +config UCLIBC_HAS_STDIO_GETC_MACRO + bool "Provide a macro version of getc()" + depends on !UCLIBC_HAS_STDIO_BUFSIZ_NONE + default y + help + Provide a macro version of getc(). + + Most people will answer Y. + +config UCLIBC_HAS_STDIO_PUTC_MACRO + bool "Provide a macro version of putc()" + depends on !UCLIBC_HAS_STDIO_BUFSIZ_NONE + default y + help + Provide a macro version of putc(). + + Most people will answer Y. + +config UCLIBC_HAS_STDIO_AUTO_RW_TRANSITION + bool "Support auto-r/w transition" + default y + help + Answer Y to enable the stdio subsystem to automaticly transition + between reading and writing. This relaxes the ANSI/ISO C99 + requirement: + + When a file is opened with update mode ('+' as the second or third + character in the list of mode argument values), both input and output + may be performed on the associated stream. However, output shall not + be directly followed by input without an intervening call to the + fflush function or to a file positioning function (fseek, fsetpos, + or rewind), and input shall not be directly followed by output without + an intervening call to a file positioning function, unless the input + operation encounters end­of­file. + + Most people will answer Y. + +config UCLIBC_HAS_FOPEN_LARGEFILE_MODE + bool "Support an fopen() 'F' flag for large file mode (uClibc-specific)" + depends on UCLIBC_HAS_LFS + default n + help + Answer Y to enable a uClibc-specific extension to allow passing an + additional 'F' flag in the mode string for fopen() to specify that + the file should be open()ed with the O_LARGEFILE flag set. + + Most people will answer N. + +config UCLIBC_HAS_FOPEN_EXCLUSIVE_MODE + bool "Support an fopen() 'x' flag for exclusive mode (glibc-compat)" + default n + help + Answer Y to support a glibc extension to allow passing + additional 'x' flag in the mode string for fopen() to specify that + the file should be open()ed with the O_EXCL flag set. + + Most people will answer N. + +config UCLIBC_HAS_GLIBC_CUSTOM_STREAMS + bool "Support fmemopen(), open_memstream(), and fopencookie() (glibc-compat)" + default n + help + Answer Y to support the glibc 'custom stream' extension functions + fmemopen(), open_memstream(), and fopencookie(). + + NOTE: There are some minor differences regarding seeking behavior. + + Most people will answer N. + +config UCLIBC_HAS_PRINTF_M_SPEC + bool "Support the '%m' specifier in printf format strings (glibc-compat)" + default n + help + Answer Y to support a glibc extension to interpret '%m' in printf + format strings as an instruction to output the error message string + (as generated by strerror) corresponding to the current value of + 'errno'. + + Most people will answer N. + +config UCLIBC_HAS_ERRNO_MESSAGES + bool "Include the errno message text in the library" + default y + help + Answer Y if you want to include the errno message text in the + library. This adds about 3K to the library, but enables strerror() + to generate text other than 'Unknown error '. + + Most people will answer Y. + +config UCLIBC_HAS_SYS_ERRLIST + bool "Support sys_errlist[] (obsolete-compat)" + depends on UCLIBC_HAS_ERRNO_MESSAGES + default n + help + Answer Y if you want to support the obsolete sys_errlist[]. + This adds about 0.5k to the library, except for the mips + arch where it adds over 4K. + + WARNING! In the future, support for sys_errlist[] may be unavailable + in at least some configurations. In fact, it may be removed + altogether. + + Most people will answer N. + + Application writers: use the strerror(3) function. + +config UCLIBC_HAS_SIGNUM_MESSAGES + bool "Include the signum message text in the library" + default y + help + Answer Y if you want to include the signum message text in the + library. This adds about 0.5K to the library, but enables strsignal() + to generate text other than 'Unknown signal '. + + Most people will answer Y. + +config UCLIBC_HAS_SYS_SIGLIST + bool "Support sys_siglist[] (bsd-compat)" + depends on UCLIBC_HAS_SIGNUM_MESSAGES + default n + help + Answer Y if you want to support sys_siglist[]. + + WARNING! In the future, support for sys_siglist[] may be unavailable + in at least some configurations. In fact, it may be removed + altogether. + + Most people will answer N. + +config UCLIBC_HAS_GETTEXT_AWARENESS + bool "Include gettext awareness" + depends on UCLIBC_HAS_LOCALE && UCLIBC_MJN3_ONLY + default n + help + NOTE!!! Not yet integrated with strerror and strsignal. NOTE!!! + + Answer Y if you want to include weak stub gettext support and + make the *strerror*() and strsignal() functions gettext-aware. + + Currently, to get functional gettext functionality you will need + to use gnu gettext. + + Most people will answer N. + +config UCLIBC_HAS_GNU_GETOPT + bool "Support gnu getopt" + default y + help + Answer Y if you want to include full gnu getopt() instead of a + (much smaller) SUSv3 compatible getopt(). + + Most people will answer Y. + +config UCLIBC_HAS_STDIO_FUTEXES + bool "Use futexes for multithreaded I/O locking" + default n + depends on UCLIBC_HAS_THREADS_NATIVE + help + If you want to compile uClibc to use futexes for low-level + I/O locking, answer Y. Otherwise, answer N. + +config UCLIBC_HAS_GETOPT_LONG + bool "Support getopt_long/getopt_long_only" + depends on !UCLIBC_HAS_GNU_GETOPT + default y + help + Answer Y if you want to include getopt_long[_only() used by many + apps, even busybox. + + Most people will answer Y. + +config UCLIBC_HAS_GNU_GETSUBOPT + bool "Support glibc getsubopt" + default y + help + Answer Y if you want to include glibc getsubopt() instead of a + smaller SUSv3 compatible getsubopt(). + + Most people will answer Y. +endmenu + + +menu "Big and Tall" + +config UCLIBC_HAS_REGEX + bool "Regular Expression Support" + default y + help + POSIX regular expression code is really big -- 53k all by itself. + If you don't use regular expressions, turn this off and save space. + Of course, if you only statically link, leave this on, since it will + only be included in your apps if you use regular expressions. + +config UCLIBC_HAS_REGEX_OLD + bool "Use the older (stable) regular expression code" + depends on UCLIBC_HAS_REGEX + default y + help + There are two versions of regex. The older (stable) version has + been in uClibc for quite a long time but hasn't seen too many + updates. It also has some known issues when dealing with uncommon + corner cases and multibyte/unicode strings. However, it is quite + a bit smaller than the newer version. + + If the older version has worked for you and you don't need unicode + support, then stick with the old version (and say Y here). + Otherwise, you should use the new version (and say N here). + +config UCLIBC_HAS_FNMATCH + bool "fnmatch Support" + default y + help + POSIX fnmatch. + +config UCLIBC_HAS_FNMATCH_OLD + bool "Use the older (stable) fnmatch code" + depends on UCLIBC_HAS_FNMATCH + default y + help + There are two versions of fnmatch. The older (stable) version has + been in uClibc for quite a long time but hasn't seen too many + updates. It also has some known issues when dealing with uncommon + corner cases and multibyte/unicode strings. However, it is quite + a bit smaller than the newer version. + + If the older version has worked for you and you don't need unicode + support, then stick with the old version (and say Y here). + Otherwise, you should use the new version (and say N here). + +config UCLIBC_HAS_WORDEXP + bool "Support the wordexp() interface" + depends on UCLIBC_HAS_GLOB + default n + help + The SuSv3 wordexp() interface performs word expansions per the Shell + and Utilities volume of IEEE Std 1003.1-2001, Section 2.6. It is + intended for use by applications that want to implement all of the + standard Bourne shell expansions on input data. + + This interface is rarely used, and very large. Unless you have a + pressing need for wordexp(), you should probably answer N. + +config UCLIBC_HAS_NFTW + bool "Support the nftw() interface" + default n + help + The SuSv3 nftw() interface is used to recursively descend + directory paths while repeatedly calling a function. + + This interface is rarely used, and adds around 4.5k. Unless you have + a pressing need for nftw(), you should probably answer N. + +config UCLIBC_HAS_FTW + bool "Support the ftw() interface" + default n + depends on UCLIBC_SUSV4_LEGACY + help + The SuSv3 ftw() interface is used to recursively descend + directory paths while repeatedly calling a function. + + This interface is rarely used, and adds around 4.5k. Unless you have + a pressing need for ftw(), you should probably answer N. + + +config UCLIBC_HAS_GLOB + bool "Support the glob() interface" + depends on UCLIBC_HAS_FNMATCH + default y + help + + The glob interface is somewhat large (weighing in at about 2,5k). It + is used fairly often, but is an option since people wanting to go for + absolute minimum size may wish to omit it. + + Most people will answer Y. + +config UCLIBC_HAS_GNU_GLOB + bool "Support gnu glob() interface" + depends on UCLIBC_HAS_GLOB + default n + help + The gnu glob interface is somewhat larger (weighing in at about 4,2k) + than it's SuSv3 counterpart (and is out of date). It is an old copy + from glibc and does not support all the GNU specific options. + + Answer Y if you want to include full gnu glob() instead of the smaller + SUSv3 compatible glob(). + + Most people will answer N. + +config UCLIBC_HAS_UTMPX + bool "utmpx based support for tracking login/logouts to/from the system" + default n + help + Answer y to enable support for accessing user accounting database. + It can be used to track all login/logout to the system. + + If unsure, just answer N. + +endmenu + + + + +menu "Library Installation Options" + +config RUNTIME_PREFIX + string "uClibc runtime library directory" + default "/usr/$(TARGET_ARCH)-linux-uclibc/" + help + RUNTIME_PREFIX is the directory into which the uClibc runtime + libraries will be installed. The result will look something + like the following: + $(RUNTIME_PREFIX)/ + lib/ + usr/bin/ldd + sbin/ldconfig + This value is used by the 'make install' Makefile target. Since this + directory is compiled into the shared library loader, you will need to + recompile uClibc if you change this value... + + For a typical target system this should be set to "/", such that + 'make install' will install /lib/libuClibc-.so + +config DEVEL_PREFIX + string "uClibc development environment directory" + default "/usr/$(TARGET_ARCH)-linux-uclibc/usr/" + help + DEVEL_PREFIX is the directory into which the uClibc development + environment will be installed. The result will look something + like the following: + $(DEVEL_PREFIX)/ + lib/ + include/ + This value is used by the 'make install' Makefile target when + installing a uClibc development environment. + + For a typical target system this should be set to "/usr", such that + 'make install' will install /usr/include/
. + +config MULTILIB_DIR + string "library path component" + default "lib" + help + Path component where libraries reside. + + For a typical target system this should be set to "lib", such that + 'make install' will install libraries to "/lib" and "/usr/lib" + respectively + DEVEL_PREFIX/MULTILIB_DIR + RUNTIME_PREFIX/MULTILIB_DIR + + Other settings may include "lib32" or "lib64". + +config HARDWIRED_ABSPATH + bool "Hardwire absolute paths into linker scripts" + default y + help + This prepends absolute paths to the libraries mentioned in linker + scripts such as libc.so. + + This is a build time optimization. It has no impact on dynamic + linking at runtime, which doesn't use linker scripts. + + You must disable this to use uClibc with old non-sysroot toolchains, + such as the prebuilt binary cross compilers at: + http://uclibc.org/downloads/binaries + + The amount of time saved by this optimization is actually too small to + measure. The linker just had to search the library path to find the + linker script, so the dentries are cache hot if it has to search the + same path again. But it's what glibc does, so we do it too. + +endmenu + + +menu "Security options" + +config UCLIBC_BUILD_PIE + bool "Build utilities as ET_DYN/PIE executables" + depends on HAVE_SHARED + depends on TARGET_arm || TARGET_frv || TARGET_i386 || TARGET_mips || TARGET_powerpc + select FORCE_SHAREABLE_TEXT_SEGMENTS + default n + help + If you answer Y here, ldd and iconv are built as ET_DYN/PIE + executables. + + It requires gcc-3.4 and binutils-2.15 (for arm 2.16) or later. + More about ET_DYN/PIE binaries on . + + WARNING: This option also enables FORCE_SHAREABLE_TEXT_SEGMENTS, so + all libraries have to be built with -fPIC or -fpic, and all + assembler functions must be written as position independent + code (PIC). + +config UCLIBC_HAS_ARC4RANDOM + bool "Include the arc4random() function" + default n + help + Answer Y to support the OpenBSD-like arc4random() function. This + function picks a random number between 0 and N, and will always return + something even if the random driver is dead. If urandom fails then + gettimeofday(2) will be used as the random seed. This function is + designed to be more dependable than invoking /dev/urandom directly. + OpenSSL and OpenNTPD currently support this function. + + Most people will answer N. + +config HAVE_NO_SSP + bool + default n + +config UCLIBC_HAS_SSP + bool "Support for GCC stack smashing protector" + depends on !HAVE_NO_SSP + default n + help + Add code to support GCC's -fstack-protector[-all] option to uClibc. + This requires GCC 4.1 or newer. GCC does not have to provide libssp, + the needed functions are added to ldso/libc instead. + + GCC's stack protector is a reimplementation of IBM's propolice. + See http://www.trl.ibm.com/projects/security/ssp/ and + http://www.linuxfromscratch.org/hints/downloads/files/ssp.txt + for details. + + Note that NOEXECSTACK on a kernel with address space randomization + is generally sufficient to prevent most buffer overflow exploits + without increasing code size. This option essentially adds debugging + code to catch them. + + Most people will answer N. + +config UCLIBC_HAS_SSP_COMPAT + bool "Support for gcc-3.x propolice smashing stack protector" + depends on UCLIBC_HAS_SSP + default n + help + Add gcc-3.x propolice smashing stack protector to the library. + + This requires a patched version of GCC, supporting the + -fstack-protector[-all] options, with the __guard and + __stack_smash_handler functions removed from libgcc. + These functions are added to ldso/libc instead. + + More information at: + + + Most people will answer N. + +config SSP_QUICK_CANARY + bool "Use simple guard values without accessing /dev/urandom" + depends on UCLIBC_HAS_SSP + default n + help + Use gettimeofday(2) to define the __guard without accessing + /dev/urandom. + WARNING: This makes smashing stack protector vulnerable to timing + attacks. + Most people will answer N. + +choice + prompt "Propolice protection blocking signal" + depends on UCLIBC_HAS_SSP + default PROPOLICE_BLOCK_ABRT if ! DODEBUG + default PROPOLICE_BLOCK_SEGV if DODEBUG + help + "abort" use SIGABRT to block offending programs. + This is the default implementation. + + "segfault" use SIGSEGV to block offending programs. + Use this for debugging. + + If unsure, answer "abort". + +config PROPOLICE_BLOCK_ABRT + bool "abort" + +config PROPOLICE_BLOCK_SEGV + bool "segfault" + +endchoice + +config UCLIBC_BUILD_SSP + bool "Build uClibc with -fstack-protector" + depends on UCLIBC_HAS_SSP + default n + help + Build all uClibc libraries and executables with -fstack-protector, + adding extra stack overflow checking to most uClibc functions. + +config UCLIBC_BUILD_RELRO + bool "Build uClibc with linker option -z RELRO" + depends on HAVE_SHARED + default y + help + Build all libraries and executables with "ld -z relro". + + This tells the linker to mark chunks of an executable or shared + library read-only after applying dynamic relocations. (This comes + up when a global const variable is initialized to the address of a + function or the value of another global variable.) + + This is a fairly obscure option the ld man page doesn't even bother + to document properly. It's a security paranoia issue that's more + likely to consume memory (by allocating an extra page) rather than + save it. + + This is explained in more depth at + http://www.airs.com/blog/archives/189 + + Nobody is likely to care whether you say Y or N here. + +config UCLIBC_BUILD_NOW + bool "Build uClibc with linker option -z NOW" + depends on HAVE_SHARED + default n + help + Build all libraries and executables with "ld -z now". + + This tells the linker to resolve all symbols when the library is + first loaded, rather than when each function is first called. This + increases start-up latency by a few microseconds and may do + unnecessary work (resolving symbols that are never used), but the + realtime people like it for making microbenchmark timings slightly + more predictable and in some cases it can be slightly faster due to + CPU cache behavior (not having to fault the linker back in to do + lazy symbol resolution). + + Most people can't tell the difference between selecting Y or N here. + +config UCLIBC_BUILD_NOEXECSTACK + bool "Build uClibc with noexecstack marking" + default y + help + Mark all assembler files as noexecstack, which will mark uClibc + as not requiring an executable stack. (This doesn't prevent other + files you link against from claiming to need an executable stack, it + just won't cause uClibc to request it unnecessarily.) + + This is a security thing to make buffer overflows harder to exploit. + By itself, it's kind of useless, as Linus Torvalds explained in 1998: + http://old.lwn.net/1998/0806/a/linus-noexec.html + + It only actually provides any security when combined with address + space randomization, explained here: http://lwn.net/Articles/121845/ + + Address space randomization is on by default in current linux + kernels (although it can be disabled using the option + CONFIG_COMPAT_BRK). + + You should probably say Y. + +endmenu + +menu "uClibc development/debugging options" + +config CROSS_COMPILER_PREFIX + string "Cross-compiling toolchain prefix" + default "" + help + The prefix used to execute your cross-compiling toolchain. For + example, if you run 'arm-linux-uclibc-gcc' to compile something, + then enter 'arm-linux-uclibc-' here. + +config UCLIBC_EXTRA_CFLAGS + string "Enter any extra CFLAGS to use to build uClibc" + default "" + help + Add any additional CFLAGS to be used to build uClibc. + +config DODEBUG + bool "Build uClibc with debugging symbols" + default n + select EXTRA_WARNINGS + help + Say Y here if you wish to compile uClibc with debugging symbols. + This will allow you to use a debugger to examine uClibc internals + while applications are running. This increases the size of the + library considerably and should only be used when doing development. + If you are doing development and want to debug uClibc, answer Y. + + Otherwise, answer N. + +config DODEBUG_PT + bool "Build pthread with debugging output" + depends on UCLIBC_HAS_THREADS && LINUXTHREADS_OLD + default n + help + Enable debug output in libpthread. This is only useful when doing + development in libpthread itself. + + Otherwise, answer N. + +config DOSTRIP + bool "Strip libraries and executables" + default y + depends on !DODEBUG + help + Say Y here if you do wish to strip all uClibc libraries and + executables. No stripping increases the size of the binaries + considerably, but makes it possible to debug uClibc libraries. + Most people will answer Y. + +config DOASSERTS + bool "Build uClibc with run-time assertion testing" + default n + help + Say Y here to include runtime assertion tests. + This enables runtime assertion testing in some code, which can + increase the size of the library and incur runtime overhead. + If you say N, then this testing will be disabled. + +config SUPPORT_LD_DEBUG + bool "Build the shared library loader with debugging support" + depends on HAVE_SHARED + default n + help + Answer Y here to enable all the extra code needed to debug the uClibc + native shared library loader. The level of debugging noise that is + generated depends on the LD_DEBUG environment variable... Just set + LD_DEBUG to something like: 'LD_DEBUG=token1,token2,.. prog' to + debug your application. Diagnostic messages will then be printed to + the stderr. + + For now these debugging tokens are available: + detail provide more information for some options + move display copy processing + symbols display symbol table processing + reloc display relocation processing; detail shows the + relocation patch + nofixups never fixes up jump relocations + bindings displays the resolve processing (function calls); + detail shows the relocation patch + all Enable everything! + + The additional environment variable: + LD_DEBUG_OUTPUT=file + redirects the diagnostics to an output file created using + the specified name and the process id as a suffix. + + An excellent start is simply: + $ LD_DEBUG=binding,move,symbols,reloc,detail ./appname + or to log everything to a file named 'logfile', try this + $ LD_DEBUG=all LD_DEBUG_OUTPUT=logfile ./appname + + If you are doing development and want to debug uClibc's shared library + loader, answer Y. Mere mortals answer N. + +config SUPPORT_LD_DEBUG_EARLY + bool "Build the shared library loader with early debugging support" + depends on HAVE_SHARED + default n + help + Answer Y here to if you find the uClibc shared library loader is + crashing or otherwise not working very early on. This is typical + only when starting a new port when you haven't figured out how to + properly get the values for argc, argv, environ, etc. This method + allows a degree of visibility into the very early shared library + loader initialization process. If you are doing development and want + to debug the uClibc shared library loader early initialization, + answer Y. Mere mortals answer N. + +config UCLIBC_MALLOC_DEBUGGING + bool "Build malloc with debugging support" + depends on MALLOC || MALLOC_STANDARD + default n + help + Answer Y here to compile extra debugging support code into malloc. + Malloc debugging output may then be enabled at runtime using the + MALLOC_DEBUG environment variable. + + The value of MALLOC_DEBUG should be an integer, which is interpreted + as a bitmask with the following bits: + 1 - do extra consistency checking + 2 - output messages for malloc/free calls and OS + allocation calls + 4 - output messages for the `MMB' layer + 8 - output messages for internal malloc heap manipulation + calls + + Because this increases the size of malloc appreciably (due to strings + etc), you should say N unless you need to debug a malloc problem. + +config UCLIBC_HAS_BACKTRACE + bool "Add support for application self-debugging" + depends on HAVE_SHARED && TARGET_sh + default n + help + Answer Y here to compile support for application self-debugging, by adding + a new shared object "libubacktrace.so" that provides the following new + functions: + backtrace, backtrace_symbols, backtrace_symbols_fd + + The backtrace functionality is currently supported on SH platform, and it + based on dwarf2 informations to properly work, so any application that + want to use backtrace needs to be built with -fexceptions flag. + + The symbol names may be unavailable without the use of special linker + options. For systems using the GNU linker, it is necessary to use the + -rdynamic linker option too. Note that names of "static" functions are not + exposed, and won't be available in the backtrace. + +config WARNINGS + string "Compiler Warnings" + default "-Wall" + help + Set this to the set of gcc warnings you wish to see while compiling. + +config EXTRA_WARNINGS + bool "Enable extra annoying warnings" + default n + help + If you wish to build with extra warnings enabled, say Y here. + +config DOMULTI + bool "Compile all sources at once into an object" + default n + help + Set this to compile all sources at once into an object (IMA). + This mode of compilation uses alot of memory but may produce + smaller binaries. + + Note that you need a very recent GCC for this to work, like + gcc >= 4.3 plus eventually some patches. + + If unsure, keep the default of N. + +config UCLIBC_MJN3_ONLY + bool "Manuel's hidden warnings" + default n + help + Answer Y here to see all Manuel's personal notes, warnings, and todos. + + Most people will answer N. + +endmenu diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.in.arch b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.in.arch new file mode 100644 index 00000000..8a02cb1a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.in.arch @@ -0,0 +1,216 @@ +# +# For a description of the syntax of this configuration file, +# see extra/config/Kconfig-language.txt +# + + +# +# Binary format +# +if !ARCH_USE_MMU +choice + prompt "Target File Format" +config UCLIBC_FORMAT_ELF + bool "ELF" + depends on ARCH_USE_MMU +config UCLIBC_FORMAT_FDPIC_ELF + bool "FDPIC ELF" + depends on !ARCH_USE_MMU + select DOPIC +config UCLIBC_FORMAT_FLAT + bool "STATIC FLAT" + depends on !ARCH_USE_MMU + select ARCH_HAS_NO_LDSO +config UCLIBC_FORMAT_FLAT_SEP_DATA + bool "STATIC FLAT (sep-data)" + depends on !ARCH_USE_MMU + select ARCH_HAS_NO_LDSO +config UCLIBC_FORMAT_SHARED_FLAT + bool "SHARED FLAT" + depends on !ARCH_USE_MMU + select ARCH_HAS_NO_LDSO + help + Pick this one if you are using uClinux and wish to build + uClibc as a flat-format shared library. +endchoice +endif +if ARCH_USE_MMU +comment "Using ELF file format" +endif + +config UCLIBC_SHARED_FLAT_ID + int "Shared library ID" + default 1 + depends on UCLIBC_FORMAT_SHARED_FLAT + help + When using flat shared libraries, every library has a unique + system-wide identifier. Identifier 0 is reserved for + executables and true shared libraries have identifiers + starting at 1. The maximum shared library identifier is + determined by the kernel and is usually 3. Shared library + N must be available on the target system as "/lib/libN.so". + + When a shared C library is used, it usually has identifier 1, + but you can use this option to select a different identifier + if you need to. + + + +# +# Endian Format +# +config ARCH_ANY_ENDIAN + bool +config ARCH_BIG_ENDIAN + bool +config ARCH_LITTLE_ENDIAN + bool +if ARCH_ANY_ENDIAN +choice + prompt "Target Processor Endianness" + help + This is the endianness you wish to use. Choose either Big + Endian, or Little Endian. +config ARCH_WANTS_BIG_ENDIAN + bool "Big Endian" + select ARCH_BIG_ENDIAN +config ARCH_WANTS_LITTLE_ENDIAN + bool "Little Endian" + select ARCH_LITTLE_ENDIAN +endchoice +endif +# if the arch only supports one endian, just display the setting +if !ARCH_ANY_ENDIAN && ARCH_LITTLE_ENDIAN +comment "Using Little Endian" +endif +if !ARCH_ANY_ENDIAN && ARCH_BIG_ENDIAN +comment "Using Big Endian" +endif + +config ARCH_HAS_NO_MMU + bool +if ARCH_HAS_NO_MMU +comment "Target CPU lacks a memory management unit (MMU)" +endif + +config ARCH_HAS_MMU + bool "Target CPU has a memory management unit (MMU)" + depends on !ARCH_HAS_NO_MMU + default y + help + If your target CPU does not have a memory management unit (MMU), + then answer N here. Normally, Linux runs on systems with an MMU. + If you are building a uClinux system, answer N. + + Most people will answer Y. + +config ARCH_USE_MMU + bool "Do you want to utilize the MMU?" + depends on ARCH_HAS_MMU + default y + help + If your target CPU has a MMU, and you wish to actually utilize it, + then answer Y here. Normal Linux requires an MMU. + + If you're unsure, answer Y. + +config UCLIBC_HAS_FLOATS + bool "Enable floating point number support" + default y + help + This option allows you to entirely omit all floating point number + support from uClibc. This will cause floating point functions like + strtod() to be omitted from uClibc. Other floating point functions, + such as printf() and scanf() will still be included in the library, + but will not contain support for floating point numbers. + + Answering N to this option can reduce the size of uClibc. + Most people will answer Y. + +config UCLIBC_HAS_FPU + bool "Target CPU has a floating point unit (FPU)" + depends on UCLIBC_HAS_FLOATS + default y + help + If your target CPU does not have a Floating Point Unit (FPU) or a + kernel FPU emulator, but you still wish to support floating point + functions, then uClibc will need to be compiled with soft floating + point support (-msoft-float). If your target CPU does not have an + FPU or an FPU emulator within the Linux kernel, then you should + answer N. + + Most people will answer Y. + +config UCLIBC_HAS_SOFT_FLOAT + bool + depends on UCLIBC_HAS_FLOATS && !UCLIBC_HAS_FPU + default y + +config DO_C99_MATH + bool "Enable full C99 math library support" + depends on UCLIBC_HAS_FLOATS + default n + help + If you want the uClibc math library to contain the full set C99 + math library features, then answer Y. If you leave this set to + N the math library will contain only the math functions that were + listed as part of the traditional POSIX/IEEE 1003.1b-1993 standard. + Leaving this option set to N will save around 35k on an x86 system. + + If your applications require the newer C99 math library functions, + then answer Y. + +config DO_XSI_MATH + bool "Enable XSI math extensions to the ISO C standard (bessel)" + depends on UCLIBC_HAS_FLOATS + default n + help + X/Open System Interfaces extensions to ISO C math functions + (differential equation functions): + + j0, j1, jn - Bessel functions of the first kind + y0, y1, yn - Bessel functions of the second kind + +config UCLIBC_HAS_FENV + bool "Enable C99 Floating-point environment" + depends on UCLIBC_HAS_FLOATS + default n + help + If you want the uClibc math library to contain the C99 floating + point environment, rounding and exception handling functions then + say Y here. + + NOTE: Supported architectures currently include: + i386 + +config UCLIBC_HAS_LONG_DOUBLE_MATH + bool "Enable long double support" + depends on DO_C99_MATH + depends on TARGET_i386 || TARGET_m68k || TARGET_sparc || TARGET_x86_64 || TARGET_powerpc || TARGET_sh + default y + help + If you want the uClibc math library to contain the full set of C99 + long double math library features, then answer Y. Don't enable it + for sparc w/ 32bit ABI. + +config KERNEL_HEADERS + string "Linux kernel header location" + default "/usr/include" + help + The kernel source you use to compile with should be the same + as the Linux kernel you run your apps on. uClibc doesn't even + try to achieve binary compatibility across kernel versions. + So don't expect, for example, uClibc compiled with Linux kernel + 2.0.x to implement lchown properly, since 2.0.x can't do that. + Similarly, if you compile uClibc vs Linux 2.4.x kernel headers, + but then run on Linux 2.0.x, lchown will be compiled into uClibc, + but won't work at all. You have been warned. + +config UCLIBC_UCLINUX_BROKEN_MUNMAP + bool + depends on !ARCH_USE_MMU + default y + +config HAVE_DOT_CONFIG + bool + default y diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.m68k b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.m68k new file mode 100644 index 00000000..95807c48 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.m68k @@ -0,0 +1,13 @@ +# +# For a description of the syntax of this configuration file, +# see extra/config/Kconfig-language.txt +# + +config TARGET_ARCH + string + default "m68k" + +config FORCE_OPTIONS_FOR_ARCH + bool + default y + select ARCH_BIG_ENDIAN diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.microblaze b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.microblaze new file mode 100644 index 00000000..a426ab51 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.microblaze @@ -0,0 +1,14 @@ +# +# For a description of the syntax of this configuration file, +# see extra/config/Kconfig-language.txt +# + +config TARGET_ARCH + string + default "microblaze" + +config FORCE_OPTIONS_FOR_ARCH + bool + default y + select ARCH_BIG_ENDIAN + select ARCH_HAS_NO_MMU diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.mips b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.mips new file mode 100644 index 00000000..063b07ce --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.mips @@ -0,0 +1,73 @@ +# +# For a description of the syntax of this configuration file, +# see extra/config/Kconfig-language.txt +# + +config TARGET_ARCH + string + default "mips" + +config FORCE_OPTIONS_FOR_ARCH + bool + default y + select ARCH_ANY_ENDIAN + +choice + prompt "Target ABI" + default CONFIG_MIPS_O32_ABI + help + This is the ABI you wish to build use. Choose either O32, N32 + or N64. + +config CONFIG_MIPS_O32_ABI + bool "O32 ABI" + +config CONFIG_MIPS_N32_ABI + bool "N32 ABI" + +config CONFIG_MIPS_N64_ABI + bool "N64 ABI" + +endchoice + +choice + prompt "Target Processor Architecture" + default CONFIG_MIPS_ISA_1 if CONFIG_MIPS_O32_ABI + default CONFIG_MIPS_ISA_3 if CONFIG_MIPS_N32_ABI + default CONFIG_MIPS_ISA_3 if CONFIG_MIPS_N64_ABI + help + This selects the instruction set architecture of your MIPS CPU. This + information is used for optimizing purposes. To build a library that + will run on any MIPS CPU, you can specify "Generic (MIPS I)" here. + If you pick anything other than "Generic (MIPS I)," there is no + guarantee that uClibc will even run on anything other than the + selected processor type. + + You should probably select the MIPS ISA that best matches the + CPU you will be using on your device. uClibc will be tuned + for that architecture. + + If you don't know what to do, choose "Generic (MIPS I)" + +config CONFIG_MIPS_ISA_1 + bool "Generic (MIPS I)" + +config CONFIG_MIPS_ISA_2 + bool "MIPS II" + +config CONFIG_MIPS_ISA_3 + bool "MIPS III" + +config CONFIG_MIPS_ISA_4 + bool "MIPS IV" + +config CONFIG_MIPS_ISA_MIPS32 + bool "MIPS32" + +config CONFIG_MIPS_ISA_MIPS32R2 + bool "MIPS32r2" + +config CONFIG_MIPS_ISA_MIPS64 + bool "MIPS64" + +endchoice diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.nios b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.nios new file mode 100644 index 00000000..4213a4cf --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.nios @@ -0,0 +1,16 @@ +# +# For a description of the syntax of this configuration file, +# see extra/config/Kconfig-language.txt +# + +config TARGET_ARCH + string + default "nios" + +config FORCE_OPTIONS_FOR_ARCH + bool + default y + select ARCH_LITTLE_ENDIAN + select ARCH_HAS_NO_MMU + select ARCH_HAS_NO_LDSO + select HAVE_NO_PIC diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.nios2 b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.nios2 new file mode 100644 index 00000000..2310a46c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.nios2 @@ -0,0 +1,16 @@ +# +# For a description of the syntax of this configuration file, +# see extra/config/Kconfig-language.txt +# + +config TARGET_ARCH + string + default "nios2" + +config FORCE_OPTIONS_FOR_ARCH + bool + default y + select ARCH_LITTLE_ENDIAN + select ARCH_HAS_NO_MMU + select ARCH_HAS_NO_LDSO + select HAVE_NO_PIC diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.powerpc b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.powerpc new file mode 100644 index 00000000..84c44232 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.powerpc @@ -0,0 +1,35 @@ +# +# For a description of the syntax of this configuration file, +# see extra/config/Kconfig-language.txt +# + +config TARGET_ARCH + string + default "powerpc" + +config FORCE_OPTIONS_FOR_ARCH + bool + default y + select ARCH_BIG_ENDIAN + select ARCH_HAS_MMU + +choice + prompt "Target Processor Type" + default CONFIG_CLASSIC + help + This is the processor core of your CPU. This information is used for + determining the correct assembler instructions to use for the core. + + The default is to build for a classic powerpc. + +config CONFIG_CLASSIC + bool "CLASSIC" + help + Classic powerpc architecture. + +config CONFIG_E500 + bool "E500" + help + e500 v1 and v2 core. + +endchoice diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.sh b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.sh new file mode 100644 index 00000000..10e9d8b0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.sh @@ -0,0 +1,52 @@ +# +# For a description of the syntax of this configuration file, +# see extra/config/Kconfig-language.txt +# + +config TARGET_ARCH + string + default "sh" + +config FORCE_OPTIONS_FOR_ARCH + bool + default y + select ARCH_ANY_ENDIAN + +choice + prompt "Target Processor Type" + default CONFIG_SH4 + help + This is the processor type of your CPU. This information is used for + optimizing purposes, as well as to determine if your CPU has an MMU, + an FPU, etc. If you pick the wrong CPU type, there is no guarantee + that uClibc will work at all.... + + Here are the available choices: + - "SH2A" Renesas SH-2A (SH7206) + - "SH2" SuperH SH-2 + - "SH3" SuperH SH-3 + - "SH4" SuperH SH-4 + +config CONFIG_SH2A + select ARCH_HAS_NO_MMU + select HAVE_NO_PIC + bool "SH2A" + +config CONFIG_SH2 + select ARCH_HAS_NO_MMU + bool "SH2" + +config CONFIG_SH3 + select ARCH_HAS_MMU + bool "SH3" + +config CONFIG_SH4 + select FORCE_SHAREABLE_TEXT_SEGMENTS + bool "SH4" + +endchoice + +config ARCH_HAS_BWD_MEMCPY + bool + default y + depends on CONFIG_SH4 diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.sh64 b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.sh64 new file mode 100644 index 00000000..02535b96 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.sh64 @@ -0,0 +1,32 @@ +# +# For a description of the syntax of this configuration file, +# see extra/config/Kconfig-language.txt +# + +config TARGET_ARCH + string + default "sh64" + +config FORCE_OPTIONS_FOR_ARCH + bool + default y + select ARCH_ANY_ENDIAN + +choice + prompt "Target Processor Type" + default CONFIG_SH5 + help + This is the processor type of your CPU. This information is used for + optimizing purposes, as well as to determine if your CPU has an MMU, + an FPU, etc. If you pick the wrong CPU type, there is no guarantee + that uClibc will work at all.... + + Here are the available choices: + - "SH5" SuperH SH-5 101, 103 + +config CONFIG_SH5 + select ARCH_HAS_MMU + select UCLIBC_HAS_LFS + bool "SH5" + +endchoice diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.sparc b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.sparc new file mode 100644 index 00000000..1852efee --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.sparc @@ -0,0 +1,34 @@ +# +# For a description of the syntax of this configuration file, +# see extra/config/Kconfig-language.txt +# + +config TARGET_ARCH + string + default "sparc" + +config FORCE_OPTIONS_FOR_ARCH + bool + default y + select ARCH_BIG_ENDIAN + +choice + prompt "Target Processor Type" + default CONFIG_SPARC_V8 + help + This is the processor type of your CPU. This information is used for + optimizing purposes. Building for a v8 SPARC is pretty safe nowadays. + +config CONFIG_SPARC_V7 + bool "SPARC v7" + +config CONFIG_SPARC_V8 + bool "SPARC v8" + +config CONFIG_SPARC_V9 + bool "SPARC v9" + +config CONFIG_SPARC_V9B + bool "SPARC v9b" + +endchoice diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.v850 b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.v850 new file mode 100644 index 00000000..fb3c4b14 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.v850 @@ -0,0 +1,15 @@ +# +# For a description of the syntax of this configuration file, +# see extra/config/Kconfig-language.txt +# + +config TARGET_ARCH + string + default "v850" + +config FORCE_OPTIONS_FOR_ARCH + bool + default y + select ARCH_LITTLE_ENDIAN + select ARCH_HAS_NO_MMU + select HAVE_NO_PIC diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.vax b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.vax new file mode 100644 index 00000000..989eeeab --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.vax @@ -0,0 +1,14 @@ +# +# For a description of the syntax of this configuration file, +# see extra/config/Kconfig-language.txt +# + +config TARGET_ARCH + string + default "vax" + +config FORCE_OPTIONS_FOR_ARCH + bool + default y + select ARCH_LITTLE_ENDIAN + select ARCH_HAS_NO_LDSO diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.x86_64 b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.x86_64 new file mode 100644 index 00000000..1b280889 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.x86_64 @@ -0,0 +1,14 @@ +# +# For a description of the syntax of this configuration file, +# see extra/config/Kconfig-language.txt +# + +config TARGET_ARCH + string + default "x86_64" + +config FORCE_OPTIONS_FOR_ARCH + bool + default y + select ARCH_LITTLE_ENDIAN + select ARCH_HAS_MMU diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.xtensa b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.xtensa new file mode 100644 index 00000000..d374f91b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/Config.xtensa @@ -0,0 +1,8 @@ +# +# For a description of the syntax of this configuration file, +# see extra/config/kconfig-language.txt +# + +config TARGET_ARCH + string + default "xtensa" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/alpha b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/alpha new file mode 100644 index 00000000..05243d7b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/alpha @@ -0,0 +1 @@ +TARGET_alpha=y diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/arm b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/arm new file mode 100644 index 00000000..aa678903 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/arm @@ -0,0 +1 @@ +TARGET_arm=y diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/avr32 b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/avr32 new file mode 100644 index 00000000..0b890a29 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/avr32 @@ -0,0 +1 @@ +TARGET_avr32=y diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/bfin b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/bfin new file mode 100644 index 00000000..fb5c5ebe --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/bfin @@ -0,0 +1 @@ +TARGET_bfin=y diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/cris b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/cris new file mode 100644 index 00000000..4e981808 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/cris @@ -0,0 +1 @@ +TARGET_cris=y diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/e1 b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/e1 new file mode 100644 index 00000000..e204c877 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/e1 @@ -0,0 +1 @@ +TARGET_e1=y diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/frv b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/frv new file mode 100644 index 00000000..8230316b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/frv @@ -0,0 +1 @@ +TARGET_frv=y diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/h8300 b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/h8300 new file mode 100644 index 00000000..66c4a33b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/h8300 @@ -0,0 +1 @@ +TARGET_h8300=y diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/hppa b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/hppa new file mode 100644 index 00000000..6358dbd1 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/hppa @@ -0,0 +1 @@ +TARGET_hppa=y diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/i386 b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/i386 new file mode 100644 index 00000000..7c351780 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/i386 @@ -0,0 +1 @@ +TARGET_i386=y diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/i960 b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/i960 new file mode 100644 index 00000000..5abe6dc8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/i960 @@ -0,0 +1 @@ +TARGET_i960=y diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/ia64 b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/ia64 new file mode 100644 index 00000000..7f26470a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/ia64 @@ -0,0 +1 @@ +TARGET_ia64=y diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/m68k b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/m68k new file mode 100644 index 00000000..da874a89 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/m68k @@ -0,0 +1 @@ +TARGET_m68k=y diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/microblaze b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/microblaze new file mode 100644 index 00000000..44012004 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/microblaze @@ -0,0 +1 @@ +TARGET_microblaze=y diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/mips b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/mips new file mode 100644 index 00000000..0114a9bd --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/mips @@ -0,0 +1 @@ +TARGET_mips=y diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/nios b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/nios new file mode 100644 index 00000000..2a110b89 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/nios @@ -0,0 +1 @@ +TARGET_nios=y diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/nios2 b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/nios2 new file mode 100644 index 00000000..870bd538 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/nios2 @@ -0,0 +1 @@ +TARGET_nios2=y diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/powerpc b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/powerpc new file mode 100644 index 00000000..38688970 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/powerpc @@ -0,0 +1 @@ +TARGET_powerpc=y diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/sh b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/sh new file mode 100644 index 00000000..650d280e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/sh @@ -0,0 +1 @@ +TARGET_sh=y diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/sh64 b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/sh64 new file mode 100644 index 00000000..4f23a540 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/sh64 @@ -0,0 +1 @@ +TARGET_sh64=y diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/sparc b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/sparc new file mode 100644 index 00000000..c2c74cba --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/sparc @@ -0,0 +1 @@ +TARGET_sparc=y diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/v850 b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/v850 new file mode 100644 index 00000000..046d5d4f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/v850 @@ -0,0 +1 @@ +TARGET_v850=y diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/vax b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/vax new file mode 100644 index 00000000..77a464e2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/vax @@ -0,0 +1 @@ +TARGET_vax=y diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/x86_64 b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/x86_64 new file mode 100644 index 00000000..e03a36aa --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Configs/defconfigs/x86_64 @@ -0,0 +1 @@ +TARGET_x86_64=y diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Makefile new file mode 100644 index 00000000..1dae3579 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../ +top_builddir=../ +include $(top_builddir)Rules.mak +all: objs +include Makefile.in +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Makefile.in new file mode 100644 index 00000000..76f504d8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/Makefile.in @@ -0,0 +1,9 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2006 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +include $(top_srcdir)extra/locale/Makefile.in +include $(top_srcdir)extra/config/Makefile.in diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/.gitignore b/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/.gitignore new file mode 100644 index 00000000..b49584c9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/.gitignore @@ -0,0 +1,19 @@ +# +# Generated files +# +config* +lex.*.c +*.tab.c +*.tab.h +zconf.hash.c +*.moc +lkc_defs.h + +# +# configuration programs +# +conf +mconf +qconf +gconf +kxgettext diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/Makefile new file mode 100644 index 00000000..46c3614a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/Makefile @@ -0,0 +1,86 @@ +top_srcdir ?= ../../ + +include $(top_srcdir)Rules.mak +include $(top_srcdir)Makerules + +# ugh +top_srcdir:=$(shell cd $(top_srcdir) && pwd)/ +ifdef O +top_builddir ?= ../../ +else +top_builddir = ../../ +endif +srctree := $(top_srcdir) +src := extra/config +obj := $(top_builddir)$(src) + +generated := $(patsubst %_shipped,%,$(wildcard *_shipped)) +generated := $(addprefix $(obj)/,$(generated:.c=.o)) + +include $(top_srcdir)extra/config/Makefile.kconfig +PHONY += $(always) +chk-lxdialog := $(top_srcdir)$(src)/lxdialog/check-lxdialog.sh +check-lxdialog := cd $(obj) && $(CONFIG_SHELL) $(chk-lxdialog) +HOST_EXTRACFLAGS = $(shell $(CONFIG_SHELL) -c '$(check-lxdialog) -ccflags') +HOST_LOADLIBES = $(shell $(CONFIG_SHELL) -c '$(check-lxdialog) -ldflags $(HOSTCC)') +HOST_EXTRACFLAGS += -DLOCALE +HOST_EXTRACFLAGS += $(shell $(CONFIG_SHELL) -c '$(srctree)/$(src)/check.sh $(HOSTCC) $(HOSTCFLAGS)') + +# do not create temporary object in the readonly srctree +$(obj)/dochecklxdialog: + $(Q)cd $(obj) && $(CONFIG_SHELL) $(chk-lxdialog) -check $(HOSTCC) $(HOST_EXTRACFLAGS) $(HOST_LOADLIBES) +HOSTCFLAGS_lex.zconf.o := -I$(top_srcdir)$(src) +HOSTCFLAGS_zconf.tab.o := -I$(top_srcdir)$(src) +conf-objs := $(addprefix $(obj)/,$(conf-objs)) +mconf-objs := $(addprefix $(obj)/,$(mconf-objs)) +kxgettext-objs := $(addprefix $(obj)/,$(kxgettext-objs)) + +ifeq ($(findstring mconf,$(MAKECMDGOALS)),mconf) +hostprogs-y += mconf +endif + +#BUILD_CFLAGS-config = -W -Wall -pedantic +#BUILD_CFLAGS-lxdialog = -W -Wall -pedantic + +__hostprogs := $(sort $(hostprogs-y) $(hostprogs-m)) +host-csingle:= $(foreach m,$(__hostprogs),$(if $($(m)-objs),,$(m))) +host-cmulti := $(foreach m,$(__hostprogs),\ + $(if $($(m)-cxxobjs),,$(if $($(m)-objs),$(m)))) +host-cobjs := $(sort $(foreach m,$(__hostprogs),$($(m)-objs))) + +conf mconf kxgettext: %: $(obj)/% +$(obj)/conf $(obj)/mconf $(obj)/kxgettext: BUILD_LDFLAGS=$(HOST_LOADLIBES) +$(obj)/conf: $(conf-objs) + $(hcompile.u) +$(obj)/mconf: $(mconf-objs) + $(hcompile.u) +$(obj)/kxgettext: $(kxgettext-objs) + $(hcompile.u) + +$(host-csingle) $(host-cmulti) $(host-cobjs): BUILD_CFLAGS=$(HOST_EXTRACFLAGS) \ + $(HOSTCFLAGS) $(HOSTCFLAGS_$(@F)) + +host-cobjs.nogen := $(filter-out $(generated),$(host-cobjs)) +host-cobjs.generated := $(filter $(generated),$(host-cobjs)) + +$(host-cobjs.nogen): $(obj)/%.o: $(top_srcdir)$(src)/%.c + $(hcompile.o) +$(host-cobjs.generated): $(obj)/%.o: $(obj)/%.c + $(hcompile.o) + +ifndef LKC_GENPARSER +$(obj)/%:: $(top_srcdir)$(src)/%_shipped + @$(disp_gen) + $(Q)cat $< > $@ +endif +CLEAN_extra/config menuconfig_clean: + $(do_rm) $(clean-files) $(lxdialog) conf $(wildcard *.o) +distclean: clean + $(do_rm) $(lxdialog) $(conf-objs) $(mconf-objs) \ + $(kxgettext-objs) \ + $(hostprogs-y) $(qconf-cxxobjs) $(qconf-objs) $(gconf-objs) \ + .depend + $(do_rm) -r $(top_builddir)include/config + +FORCE: +.PHONY: FORCE clean distclean $(always) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/Makefile.kconfig b/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/Makefile.kconfig new file mode 100644 index 00000000..83c20c47 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/Makefile.kconfig @@ -0,0 +1,289 @@ +# =========================================================================== +# Kernel configuration targets +# These targets are used from top-level makefile + +PHONY += oldconfig xconfig gconfig menuconfig config silentoldconfig update-po-config + +ifdef KBUILD_KCONFIG +Kconfig := $(KBUILD_KCONFIG) +else +Kconfig := arch/$(SRCARCH)/Kconfig +endif + +xconfig: $(obj)/qconf + $< $(Kconfig) + +gconfig: $(obj)/gconf + $< $(Kconfig) + +menuconfig: $(obj)/mconf + $< $(Kconfig) + +config: $(obj)/conf + $< $(Kconfig) + +oldconfig: $(obj)/conf + $< -o $(Kconfig) + +silentoldconfig: $(obj)/conf + $< -s $(Kconfig) + +# Create new linux.pot file +# Adjust charset to UTF-8 in .po file to accept UTF-8 in Kconfig files +# The symlink is used to repair a deficiency in arch/um +update-po-config: $(obj)/kxgettext $(obj)/gconf.glade.h + $(Q)echo " GEN config" + $(Q)xgettext --default-domain=linux \ + --add-comments --keyword=_ --keyword=N_ \ + --from-code=UTF-8 \ + --files-from=scripts/kconfig/POTFILES.in \ + --output $(obj)/config.pot + $(Q)sed -i s/CHARSET/UTF-8/ $(obj)/config.pot + $(Q)ln -fs Kconfig.i386 arch/um/Kconfig.arch + $(Q)(for i in `ls arch/*/Kconfig`; \ + do \ + echo " GEN $$i"; \ + $(obj)/kxgettext $$i \ + >> $(obj)/config.pot; \ + done ) + $(Q)msguniq --sort-by-file --to-code=UTF-8 $(obj)/config.pot \ + --output $(obj)/linux.pot + $(Q)rm -f arch/um/Kconfig.arch + $(Q)rm -f $(obj)/config.pot + +PHONY += randconfig allyesconfig allnoconfig allmodconfig defconfig + +randconfig: $(obj)/conf + $< -r $(Kconfig) + +allyesconfig: $(obj)/conf + $< -y $(Kconfig) + +allnoconfig: $(obj)/conf + $< -n $(Kconfig) + +allmodconfig: $(obj)/conf + $< -m $(Kconfig) + +defconfig: $(obj)/conf +ifeq ($(KBUILD_DEFCONFIG),) + $< -d $(Kconfig) +else + @echo "*** Default configuration is based on '$(KBUILD_DEFCONFIG)'" + $(Q)$< -D arch/$(SRCARCH)/configs/$(KBUILD_DEFCONFIG) $(Kconfig) +endif + +%_defconfig: $(obj)/conf + $(Q)$< -D arch/$(SRCARCH)/configs/$@ $(Kconfig) + +# Help text used by make help +help: + @echo ' config - Update current config utilising a line-oriented program' + @echo ' menuconfig - Update current config utilising a menu based program' + @echo ' xconfig - Update current config utilising a QT based front-end' + @echo ' gconfig - Update current config utilising a GTK based front-end' + @echo ' oldconfig - Update current config utilising a provided .config as base' + @echo ' silentoldconfig - Same as oldconfig, but quietly' + @echo ' randconfig - New config with random answer to all options' + @echo ' defconfig - New config with default answer to all options' + @echo ' allmodconfig - New config selecting modules when possible' + @echo ' allyesconfig - New config where all options are accepted with yes' + @echo ' allnoconfig - New config where all options are answered with no' + +# lxdialog stuff +check-lxdialog := $(srctree)/$(src)/lxdialog/check-lxdialog.sh + +# Use recursively expanded variables so we do not call gcc unless +# we really need to do so. (Do not call gcc as part of make mrproper) +HOST_EXTRACFLAGS = $(shell $(CONFIG_SHELL) $(check-lxdialog) -ccflags) +HOST_LOADLIBES = $(shell $(CONFIG_SHELL) $(check-lxdialog) -ldflags $(HOSTCC)) + +HOST_EXTRACFLAGS += -DLOCALE + + +# =========================================================================== +# Shared Makefile for the various kconfig executables: +# conf: Used for defconfig, oldconfig and related targets +# mconf: Used for the mconfig target. +# Utilizes the lxdialog package +# qconf: Used for the xconfig target +# Based on QT which needs to be installed to compile it +# gconf: Used for the gconfig target +# Based on GTK which needs to be installed to compile it +# object files used by all kconfig flavours + +lxdialog := lxdialog/checklist.o lxdialog/util.o lxdialog/inputbox.o +lxdialog += lxdialog/textbox.o lxdialog/yesno.o lxdialog/menubox.o + +conf-objs := conf.o zconf.tab.o +mconf-objs := mconf.o zconf.tab.o $(lxdialog) +kxgettext-objs := kxgettext.o zconf.tab.o + +hostprogs-y := conf qconf gconf kxgettext + +ifeq ($(MAKECMDGOALS),menuconfig) + hostprogs-y += mconf +endif + +ifeq ($(MAKECMDGOALS),xconfig) + qconf-target := 1 +endif +ifeq ($(MAKECMDGOALS),gconfig) + gconf-target := 1 +endif + + +ifeq ($(qconf-target),1) +qconf-cxxobjs := qconf.o +qconf-objs := kconfig_load.o zconf.tab.o +endif + +ifeq ($(gconf-target),1) +gconf-objs := gconf.o kconfig_load.o zconf.tab.o +endif + +clean-files := lkc_defs.h qconf.moc .tmp_qtcheck \ + .tmp_gtkcheck zconf.tab.c lex.zconf.c zconf.hash.c gconf.glade.h +clean-files += mconf qconf gconf +clean-files += config.pot linux.pot + +# Check that we have the required ncurses stuff installed for lxdialog (menuconfig) +PHONY += $(obj)/dochecklxdialog +$(addprefix $(obj)/,$(lxdialog)): $(obj)/dochecklxdialog +#$(obj)/dochecklxdialog: +# $(Q)$(CONFIG_SHELL) $(check-lxdialog) -check $(HOSTCC) $(HOST_EXTRACFLAGS) $(HOST_LOADLIBES) + +always := dochecklxdialog + +# Add environment specific flags +HOST_EXTRACFLAGS += $(shell $(CONFIG_SHELL) $(srctree)/$(src)/check.sh $(HOSTCC) $(HOSTCFLAGS)) + +# generated files seem to need this to find local include files +HOSTCFLAGS_lex.zconf.o := -I$(src) +HOSTCFLAGS_zconf.tab.o := -I$(src) + +HOSTLOADLIBES_qconf = $(KC_QT_LIBS) -ldl +HOSTCXXFLAGS_qconf.o = $(KC_QT_CFLAGS) -D LKC_DIRECT_LINK + +HOSTLOADLIBES_gconf = `pkg-config --libs gtk+-2.0 gmodule-2.0 libglade-2.0` +HOSTCFLAGS_gconf.o = `pkg-config --cflags gtk+-2.0 gmodule-2.0 libglade-2.0` \ + -D LKC_DIRECT_LINK + +$(obj)/qconf.o: $(obj)/.tmp_qtcheck + +ifeq ($(qconf-target),1) +$(obj)/.tmp_qtcheck: $(src)/Makefile +-include $(obj)/.tmp_qtcheck + +# QT needs some extra effort... +$(obj)/.tmp_qtcheck: + @set -e; echo " CHECK qt"; dir=""; pkg=""; \ + pkg-config --exists qt 2> /dev/null && pkg=qt; \ + pkg-config --exists qt-mt 2> /dev/null && pkg=qt-mt; \ + if [ -n "$$pkg" ]; then \ + cflags="\$$(shell pkg-config $$pkg --cflags)"; \ + libs="\$$(shell pkg-config $$pkg --libs)"; \ + moc="\$$(shell pkg-config $$pkg --variable=prefix)/bin/moc"; \ + dir="$$(pkg-config $$pkg --variable=prefix)"; \ + else \ + for d in $$QTDIR /usr/share/qt* /usr/lib/qt*; do \ + if [ -f $$d/include/qconfig.h ]; then dir=$$d; break; fi; \ + done; \ + if [ -z "$$dir" ]; then \ + echo "*"; \ + echo "* Unable to find the QT3 installation. Please make sure that"; \ + echo "* the QT3 development package is correctly installed and"; \ + echo "* either install pkg-config or set the QTDIR environment"; \ + echo "* variable to the correct location."; \ + echo "*"; \ + false; \ + fi; \ + libpath=$$dir/lib; lib=qt; osdir=""; \ + $(HOSTCXX) -print-multi-os-directory > /dev/null 2>&1 && \ + osdir=x$$($(HOSTCXX) -print-multi-os-directory); \ + test -d $$libpath/$$osdir && libpath=$$libpath/$$osdir; \ + test -f $$libpath/libqt-mt.so && lib=qt-mt; \ + cflags="-I$$dir/include"; \ + libs="-L$$libpath -Wl,-rpath,$$libpath -l$$lib"; \ + moc="$$dir/bin/moc"; \ + fi; \ + if [ ! -x $$dir/bin/moc -a -x /usr/bin/moc ]; then \ + echo "*"; \ + echo "* Unable to find $$dir/bin/moc, using /usr/bin/moc instead."; \ + echo "*"; \ + moc="/usr/bin/moc"; \ + fi; \ + echo "KC_QT_CFLAGS=$$cflags" > $@; \ + echo "KC_QT_LIBS=$$libs" >> $@; \ + echo "KC_QT_MOC=$$moc" >> $@ +endif + +$(obj)/gconf.o: $(obj)/.tmp_gtkcheck + +ifeq ($(gconf-target),1) +-include $(obj)/.tmp_gtkcheck + +# GTK needs some extra effort, too... +$(obj)/.tmp_gtkcheck: + @if `pkg-config --exists gtk+-2.0 gmodule-2.0 libglade-2.0`; then \ + if `pkg-config --atleast-version=2.0.0 gtk+-2.0`; then \ + touch $@; \ + else \ + echo "*"; \ + echo "* GTK+ is present but version >= 2.0.0 is required."; \ + echo "*"; \ + false; \ + fi \ + else \ + echo "*"; \ + echo "* Unable to find the GTK+ installation. Please make sure that"; \ + echo "* the GTK+ 2.0 development package is correctly installed..."; \ + echo "* You need gtk+-2.0, glib-2.0 and libglade-2.0."; \ + echo "*"; \ + false; \ + fi +endif + +$(obj)/zconf.tab.o: $(obj)/lex.zconf.c $(obj)/zconf.hash.c + +$(obj)/kconfig_load.o: $(obj)/lkc_defs.h + +$(obj)/qconf.o: $(obj)/qconf.moc $(obj)/lkc_defs.h + +$(obj)/gconf.o: $(obj)/lkc_defs.h + +$(obj)/%.moc: $(src)/%.h + $(KC_QT_MOC) -i $< -o $@ + +$(obj)/lkc_defs.h: $(src)/lkc_proto.h + sed < $< > $@ 's/P(\([^,]*\),.*/#define \1 (\*\1_p)/' + +# Extract gconf menu items for I18N support +$(obj)/gconf.glade.h: $(obj)/gconf.glade + intltool-extract --type=gettext/glade $(obj)/gconf.glade + +### +# The following requires flex/bison/gperf +# By default we use the _shipped versions, uncomment the following line if +# you are modifying the flex/bison src. +# LKC_GENPARSER := 1 + +ifdef LKC_GENPARSER + +$(obj)/zconf.tab.c: $(src)/zconf.y +$(obj)/lex.zconf.c: $(src)/zconf.l +$(obj)/zconf.hash.c: $(src)/zconf.gperf + +%.tab.c: %.y + bison -l -b $* -p $(notdir $*) $< + cp $@ $@_shipped + +lex.%.c: %.l + flex -L -P$(notdir $*) -o$@ $< + cp $@ $@_shipped + +%.hash.c: %.gperf + gperf < $< > $@ + cp $@ $@_shipped + +endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/POTFILES.in b/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/POTFILES.in new file mode 100644 index 00000000..96745739 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/POTFILES.in @@ -0,0 +1,12 @@ +scripts/kconfig/lxdialog/checklist.c +scripts/kconfig/lxdialog/inputbox.c +scripts/kconfig/lxdialog/menubox.c +scripts/kconfig/lxdialog/textbox.c +scripts/kconfig/lxdialog/util.c +scripts/kconfig/lxdialog/yesno.c +scripts/kconfig/mconf.c +scripts/kconfig/conf.c +scripts/kconfig/confdata.c +scripts/kconfig/gconf.c +scripts/kconfig/gconf.glade.h +scripts/kconfig/qconf.cc diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/README.uClibc b/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/README.uClibc new file mode 100644 index 00000000..b05cabc2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/README.uClibc @@ -0,0 +1,19 @@ +This is a copy of the kconfig code in the kernel tweaked to suit uClibc. + +To update: + cp -r /usr/src/linux/scripts/kconfig extra/config.new + cd extra/config.new + cp /usr/src/linux/Documentation/kbuild/kconfig-language.txt . + mv Makefile Makefile.kconfig + zcat ../config/kconfig-to-uclibc.patch.gz | patch -p1 + cp ../config/README.uClibc . + cp ../config/Makefile . + cd .. + rm -rf config + mv config.new config + +Then verify the toplevel targets work: + config + defconfig + menuconfig + oldconfig diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/check.sh b/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/check.sh new file mode 100644 index 00000000..fa59cbf9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/check.sh @@ -0,0 +1,14 @@ +#!/bin/sh +# Needed for systems without gettext +$* -xc -o /dev/null - > /dev/null 2>&1 << EOF +#include +int main() +{ + gettext(""); + return 0; +} +EOF +if [ ! "$?" -eq "0" ]; then + echo -DKBUILD_NO_NLS; +fi + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/conf.c b/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/conf.c new file mode 100644 index 00000000..d623ed1d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/conf.c @@ -0,0 +1,617 @@ +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define LKC_DIRECT_LINK +#include "lkc.h" + +static void conf(struct menu *menu); +static void check_conf(struct menu *menu); + +enum { + ask_all, + ask_new, + ask_silent, + set_default, + set_yes, + set_mod, + set_no, + set_random +} input_mode = ask_all; +char *defconfig_file; + +static int indent = 1; +static int valid_stdin = 1; +static int sync_kconfig; +static int conf_cnt; +static char line[128]; +static struct menu *rootEntry; + +static char nohelp_text[] = N_("Sorry, no help available for this option yet.\n"); + +static const char *get_help(struct menu *menu) +{ + if (menu_has_help(menu)) + return _(menu_get_help(menu)); + else + return nohelp_text; +} + +static void strip(char *str) +{ + char *p = str; + int l; + + while ((isspace(*p))) + p++; + l = strlen(p); + if (p != str) + memmove(str, p, l + 1); + if (!l) + return; + p = str + l - 1; + while ((isspace(*p))) + *p-- = 0; +} + +static void check_stdin(void) +{ + if (!valid_stdin) { + printf(_("aborted!\n\n")); + printf(_("Console input/output is redirected. ")); + printf(_("Run 'make oldconfig' to update configuration.\n\n")); + exit(1); + } +} + +static int conf_askvalue(struct symbol *sym, const char *def) +{ + enum symbol_type type = sym_get_type(sym); + + if (!sym_has_value(sym)) + printf(_("(NEW) ")); + + line[0] = '\n'; + line[1] = 0; + + if (!sym_is_changable(sym)) { + printf("%s\n", def); + line[0] = '\n'; + line[1] = 0; + return 0; + } + + switch (input_mode) { + case ask_new: + case ask_silent: + if (sym_has_value(sym)) { + printf("%s\n", def); + return 0; + } + check_stdin(); + case ask_all: + fflush(stdout); + fgets(line, 128, stdin); + return 1; + default: + break; + } + + switch (type) { + case S_INT: + case S_HEX: + case S_STRING: + printf("%s\n", def); + return 1; + default: + ; + } + printf("%s", line); + return 1; +} + +int conf_string(struct menu *menu) +{ + struct symbol *sym = menu->sym; + const char *def; + + while (1) { + printf("%*s%s ", indent - 1, "", _(menu->prompt->text)); + printf("(%s) ", sym->name); + def = sym_get_string_value(sym); + if (sym_get_string_value(sym)) + printf("[%s] ", def); + if (!conf_askvalue(sym, def)) + return 0; + switch (line[0]) { + case '\n': + break; + case '?': + /* print help */ + if (line[1] == '\n') { + printf("\n%s\n", get_help(menu)); + def = NULL; + break; + } + default: + line[strlen(line)-1] = 0; + def = line; + } + if (def && sym_set_string_value(sym, def)) + return 0; + } +} + +static int conf_sym(struct menu *menu) +{ + struct symbol *sym = menu->sym; + int type; + tristate oldval, newval; + + while (1) { + printf("%*s%s ", indent - 1, "", _(menu->prompt->text)); + if (sym->name) + printf("(%s) ", sym->name); + type = sym_get_type(sym); + putchar('['); + oldval = sym_get_tristate_value(sym); + switch (oldval) { + case no: + putchar('N'); + break; + case mod: + putchar('M'); + break; + case yes: + putchar('Y'); + break; + } + if (oldval != no && sym_tristate_within_range(sym, no)) + printf("/n"); + if (oldval != mod && sym_tristate_within_range(sym, mod)) + printf("/m"); + if (oldval != yes && sym_tristate_within_range(sym, yes)) + printf("/y"); + if (menu_has_help(menu)) + printf("/?"); + printf("] "); + if (!conf_askvalue(sym, sym_get_string_value(sym))) + return 0; + strip(line); + + switch (line[0]) { + case 'n': + case 'N': + newval = no; + if (!line[1] || !strcmp(&line[1], "o")) + break; + continue; + case 'm': + case 'M': + newval = mod; + if (!line[1]) + break; + continue; + case 'y': + case 'Y': + newval = yes; + if (!line[1] || !strcmp(&line[1], "es")) + break; + continue; + case 0: + newval = oldval; + break; + case '?': + goto help; + default: + continue; + } + if (sym_set_tristate_value(sym, newval)) + return 0; +help: + printf("\n%s\n", get_help(menu)); + } +} + +static int conf_choice(struct menu *menu) +{ + struct symbol *sym, *def_sym; + struct menu *child; + int type; + bool is_new; + + sym = menu->sym; + type = sym_get_type(sym); + is_new = !sym_has_value(sym); + if (sym_is_changable(sym)) { + conf_sym(menu); + sym_calc_value(sym); + switch (sym_get_tristate_value(sym)) { + case no: + return 1; + case mod: + return 0; + case yes: + break; + } + } else { + switch (sym_get_tristate_value(sym)) { + case no: + return 1; + case mod: + printf("%*s%s\n", indent - 1, "", _(menu_get_prompt(menu))); + return 0; + case yes: + break; + } + } + + while (1) { + int cnt, def; + + printf("%*s%s\n", indent - 1, "", _(menu_get_prompt(menu))); + def_sym = sym_get_choice_value(sym); + cnt = def = 0; + line[0] = 0; + for (child = menu->list; child; child = child->next) { + if (!menu_is_visible(child)) + continue; + if (!child->sym) { + printf("%*c %s\n", indent, '*', _(menu_get_prompt(child))); + continue; + } + cnt++; + if (child->sym == def_sym) { + def = cnt; + printf("%*c", indent, '>'); + } else + printf("%*c", indent, ' '); + printf(" %d. %s", cnt, _(menu_get_prompt(child))); + if (child->sym->name) + printf(" (%s)", child->sym->name); + if (!sym_has_value(child->sym)) + printf(_(" (NEW)")); + printf("\n"); + } + printf(_("%*schoice"), indent - 1, ""); + if (cnt == 1) { + printf("[1]: 1\n"); + goto conf_childs; + } + printf("[1-%d", cnt); + if (menu_has_help(menu)) + printf("?"); + printf("]: "); + switch (input_mode) { + case ask_new: + case ask_silent: + if (!is_new) { + cnt = def; + printf("%d\n", cnt); + break; + } + check_stdin(); + case ask_all: + fflush(stdout); + fgets(line, 128, stdin); + strip(line); + if (line[0] == '?') { + printf("\n%s\n", get_help(menu)); + continue; + } + if (!line[0]) + cnt = def; + else if (isdigit(line[0])) + cnt = atoi(line); + else + continue; + break; + default: + break; + } + + conf_childs: + for (child = menu->list; child; child = child->next) { + if (!child->sym || !menu_is_visible(child)) + continue; + if (!--cnt) + break; + } + if (!child) + continue; + if (line[strlen(line) - 1] == '?') { + printf("\n%s\n", get_help(child)); + continue; + } + sym_set_choice_value(sym, child->sym); + for (child = child->list; child; child = child->next) { + indent += 2; + conf(child); + indent -= 2; + } + return 1; + } +} + +static void conf(struct menu *menu) +{ + struct symbol *sym; + struct property *prop; + struct menu *child; + + if (!menu_is_visible(menu)) + return; + + sym = menu->sym; + prop = menu->prompt; + if (prop) { + const char *prompt; + + switch (prop->type) { + case P_MENU: + if (input_mode == ask_silent && rootEntry != menu) { + check_conf(menu); + return; + } + case P_COMMENT: + prompt = menu_get_prompt(menu); + if (prompt) + printf("%*c\n%*c %s\n%*c\n", + indent, '*', + indent, '*', _(prompt), + indent, '*'); + default: + ; + } + } + + if (!sym) + goto conf_childs; + + if (sym_is_choice(sym)) { + conf_choice(menu); + if (sym->curr.tri != mod) + return; + goto conf_childs; + } + + switch (sym->type) { + case S_INT: + case S_HEX: + case S_STRING: + conf_string(menu); + break; + default: + conf_sym(menu); + break; + } + +conf_childs: + if (sym) + indent += 2; + for (child = menu->list; child; child = child->next) + conf(child); + if (sym) + indent -= 2; +} + +static void check_conf(struct menu *menu) +{ + struct symbol *sym; + struct menu *child; + + if (!menu_is_visible(menu)) + return; + + sym = menu->sym; + if (sym && !sym_has_value(sym)) { + if (sym_is_changable(sym) || + (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)) { + if (!conf_cnt++) + printf(_("*\n* Restart config...\n*\n")); + rootEntry = menu_get_parent_menu(menu); + conf(rootEntry); + } + } + + for (child = menu->list; child; child = child->next) + check_conf(child); +} + +int main(int ac, char **av) +{ + int opt; + const char *name; + const char *configname = conf_get_configname(); + struct stat tmpstat; + + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + + while ((opt = getopt(ac, av, "osdD:nmyrh")) != -1) { + switch (opt) { + case 'o': + input_mode = ask_silent; + break; + case 's': + input_mode = ask_silent; + sync_kconfig = 1; + break; + case 'd': + input_mode = set_default; + break; + case 'D': + input_mode = set_default; + defconfig_file = optarg; + break; + case 'n': + input_mode = set_no; + break; + case 'm': + input_mode = set_mod; + break; + case 'y': + input_mode = set_yes; + break; + case 'r': + { + struct timeval now; + unsigned int seed; + + /* + * Use microseconds derived seed, + * compensate for systems where it may be zero + */ + gettimeofday(&now, NULL); + + seed = (unsigned int)((now.tv_sec + 1) * (now.tv_usec + 1)); + srand(seed); + + input_mode = set_random; + break; + } + case 'h': + printf(_("See README for usage info\n")); + exit(0); + break; + default: + fprintf(stderr, _("See README for usage info\n")); + exit(1); + } + } + if (ac == optind) { + printf(_("%s: Kconfig file missing\n"), av[0]); + exit(1); + } + name = av[optind]; + conf_parse(name); + //zconfdump(stdout); + if (sync_kconfig) { + if (stat(configname, &tmpstat)) { + fprintf(stderr, _("***\n" + "*** You have not yet configured!\n" + "*** (missing .config file)\n" + "***\n" + "*** Please run some configurator (e.g. \"make oldconfig\" or\n" + "*** \"make menuconfig\" or \"make xconfig\").\n" + "***\n")); + exit(1); + } + } + + switch (input_mode) { + case set_default: + if (!defconfig_file) + defconfig_file = conf_get_default_confname(); + if (conf_read(defconfig_file)) { + printf(_("***\n" + "*** Can't find default configuration \"%s\"!\n" + "***\n"), defconfig_file); + exit(1); + } + break; + case ask_silent: + case ask_all: + case ask_new: + conf_read(NULL); + break; + case set_no: + case set_mod: + case set_yes: + case set_random: + name = getenv("KCONFIG_ALLCONFIG"); + if (name && !stat(name, &tmpstat)) { + conf_read_simple(name, S_DEF_USER); + break; + } + switch (input_mode) { + case set_no: name = "allno.config"; break; + case set_mod: name = "allmod.config"; break; + case set_yes: name = "allyes.config"; break; + case set_random: name = "allrandom.config"; break; + default: break; + } + if (!stat(name, &tmpstat)) + conf_read_simple(name, S_DEF_USER); + else if (!stat("all.config", &tmpstat)) + conf_read_simple("all.config", S_DEF_USER); + break; + default: + break; + } + + if (sync_kconfig) { + if (conf_get_changed()) { + name = getenv("KCONFIG_NOSILENTUPDATE"); + if (name && *name) { + fprintf(stderr, + _("\n*** configuration requires explicit update.\n\n")); + return 1; + } + } + valid_stdin = isatty(0) && isatty(1) && isatty(2); + } + + switch (input_mode) { + case set_no: + conf_set_all_new_symbols(def_no); + break; + case set_yes: + conf_set_all_new_symbols(def_yes); + break; + case set_mod: + conf_set_all_new_symbols(def_mod); + break; + case set_random: + conf_set_all_new_symbols(def_random); + break; + case set_default: + conf_set_all_new_symbols(def_default); + break; + case ask_new: + case ask_all: + rootEntry = &rootmenu; + conf(&rootmenu); + input_mode = ask_silent; + /* fall through */ + case ask_silent: + /* Update until a loop caused no more changes */ + do { + conf_cnt = 0; + check_conf(&rootmenu); + } while (conf_cnt); + break; + } + + if (sync_kconfig) { + /* silentoldconfig is used during the build so we shall update autoconf. + * All other commands are only used to generate a config. + */ + if (conf_get_changed() && conf_write(NULL)) { + fprintf(stderr, _("\n*** Error during writing of the configuration.\n\n")); + exit(1); + } + if (conf_write_autoconf()) { + fprintf(stderr, _("\n*** Error during update of the configuration.\n\n")); + return 1; + } + } else { + if (conf_write(NULL)) { + fprintf(stderr, _("\n*** Error during writing of the configuration.\n\n")); + exit(1); + } + } + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/confdata.c b/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/confdata.c new file mode 100644 index 00000000..2b848d5d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/confdata.c @@ -0,0 +1,912 @@ +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define LKC_DIRECT_LINK +#include "lkc.h" + +static void conf_warning(const char *fmt, ...) + __attribute__ ((format (printf, 1, 2))); + +static const char *conf_filename; +static int conf_lineno, conf_warnings, conf_unsaved; + +const char conf_defname[] = "extra/Configs/defconfigs/$ARCH"; + +static void conf_warning(const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + fprintf(stderr, "%s:%d:warning: ", conf_filename, conf_lineno); + vfprintf(stderr, fmt, ap); + fprintf(stderr, "\n"); + va_end(ap); + conf_warnings++; +} + +const char *conf_get_configname(void) +{ + char *name = getenv("KCONFIG_CONFIG"); + + return name ? name : ".config"; +} + +static char *conf_expand_value(const char *in) +{ + struct symbol *sym; + const char *src; + static char res_value[SYMBOL_MAXLENGTH]; + char *dst, name[SYMBOL_MAXLENGTH]; + + res_value[0] = 0; + dst = name; + while ((src = strchr(in, '$'))) { + strncat(res_value, in, src - in); + src++; + dst = name; + while (isalnum(*src) || *src == '_') + *dst++ = *src++; + *dst = 0; + sym = sym_lookup(name, 0); + sym_calc_value(sym); + strcat(res_value, sym_get_string_value(sym)); + in = src; + } + strcat(res_value, in); + + return res_value; +} + +char *conf_get_default_confname(void) +{ + struct stat buf; + static char fullname[PATH_MAX+1]; + char *env, *name; + + name = conf_expand_value(conf_defname); + env = getenv(SRCTREE); + if (env) { + sprintf(fullname, "%s/%s", env, name); + if (!stat(fullname, &buf)) + return fullname; + } + return name; +} + +static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p) +{ + char *p2; + + switch (sym->type) { + case S_TRISTATE: + if (p[0] == 'm') { + sym->def[def].tri = mod; + sym->flags |= def_flags; + break; + } + case S_BOOLEAN: + if (p[0] == 'y') { + sym->def[def].tri = yes; + sym->flags |= def_flags; + break; + } + if (p[0] == 'n') { + sym->def[def].tri = no; + sym->flags |= def_flags; + break; + } + conf_warning("symbol value '%s' invalid for %s", p, sym->name); + break; + case S_OTHER: + if (*p != '"') { + for (p2 = p; *p2 && !isspace(*p2); p2++) + ; + sym->type = S_STRING; + goto done; + } + case S_STRING: + if (*p++ != '"') + break; + for (p2 = p; (p2 = strpbrk(p2, "\"\\")); p2++) { + if (*p2 == '"') { + *p2 = 0; + break; + } + memmove(p2, p2 + 1, strlen(p2)); + } + if (!p2) { + conf_warning("invalid string found"); + return 1; + } + case S_INT: + case S_HEX: + done: + if (sym_string_valid(sym, p)) { + sym->def[def].val = strdup(p); + sym->flags |= def_flags; + } else { + conf_warning("symbol value '%s' invalid for %s", p, sym->name); + return 1; + } + break; + default: + ; + } + return 0; +} + +int conf_read_simple(const char *name, int def) +{ + FILE *in = NULL; + char line[1024]; + char *p, *p2; + struct symbol *sym; + int i, def_flags; + + if (name) { + in = zconf_fopen(name); + } else { + struct property *prop; + + name = conf_get_configname(); + in = zconf_fopen(name); + if (in) + goto load; + sym_add_change_count(1); + if (!sym_defconfig_list) + return 1; + + for_all_defaults(sym_defconfig_list, prop) { + if (expr_calc_value(prop->visible.expr) == no || + prop->expr->type != E_SYMBOL) + continue; + name = conf_expand_value(prop->expr->left.sym->name); + in = zconf_fopen(name); + if (in) { + printf(_("#\n" + "# using defaults found in %s\n" + "#\n"), name); + goto load; + } + } + } + if (!in) + return 1; + +load: + conf_filename = name; + conf_lineno = 0; + conf_warnings = 0; + conf_unsaved = 0; + + def_flags = SYMBOL_DEF << def; + for_all_symbols(i, sym) { + sym->flags |= SYMBOL_CHANGED; + sym->flags &= ~(def_flags|SYMBOL_VALID); + if (sym_is_choice(sym)) + sym->flags |= def_flags; + switch (sym->type) { + case S_INT: + case S_HEX: + case S_STRING: + if (sym->def[def].val) + free(sym->def[def].val); + default: + sym->def[def].val = NULL; + sym->def[def].tri = no; + } + } + + while (fgets(line, sizeof(line), in)) { + conf_lineno++; + sym = NULL; + switch (line[0]) { + case '#': + if (line[1] != ' ') + continue; + p = strchr(line + 2, ' '); + if (!p) + continue; + *p++ = 0; + if (strncmp(p, "is not set", 10)) + continue; + if (def == S_DEF_USER) { + sym = sym_find(line + 2); + if (!sym) { + sym_add_change_count(1); + break; + } + } else { + sym = sym_lookup(line + 2, 0); + if (sym->type == S_UNKNOWN) + sym->type = S_BOOLEAN; + } + if (sym->flags & def_flags) { + conf_warning("override: reassigning to symbol %s", sym->name); + } + switch (sym->type) { + case S_BOOLEAN: + case S_TRISTATE: + sym->def[def].tri = no; + sym->flags |= def_flags; + break; + default: + ; + } + break; + case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': case 'H': case 'I': case 'J': case 'K': case 'L': case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z': + p = strchr(line, '='); + if (!p) { + conf_warning("unexpected data '%s'", line); + continue; + } + *p++ = 0; + p2 = strchr(p, '\n'); + if (p2) { + *p2-- = 0; + if (*p2 == '\r') + *p2 = 0; + } + if (def == S_DEF_USER) { + sym = sym_find(line); + if (!sym) { + sym_add_change_count(1); + break; + } + } else { + sym = sym_lookup(line, 0); + if (sym->type == S_UNKNOWN) + sym->type = S_OTHER; + } + if (sym->flags & def_flags) { + conf_warning("override: reassigning to symbol %s", sym->name); + } + if (conf_set_sym_val(sym, def, def_flags, p)) + continue; + break; + case '\r': + case '\n': + break; + default: + conf_warning("unexpected data"); + continue; + } + if (sym && sym_is_choice_value(sym)) { + struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym)); + switch (sym->def[def].tri) { + case no: + break; + case mod: + if (cs->def[def].tri == yes) { + conf_warning("%s creates inconsistent choice state", sym->name); + cs->flags &= ~def_flags; + } + break; + case yes: + if (cs->def[def].tri != no) + conf_warning("override: %s changes choice state", sym->name); + cs->def[def].val = sym; + break; + } + cs->def[def].tri = EXPR_OR(cs->def[def].tri, sym->def[def].tri); + } + } + fclose(in); + + if (modules_sym) + sym_calc_value(modules_sym); + return 0; +} + +int conf_read(const char *name) +{ + struct symbol *sym, *choice_sym; + struct property *prop; + struct expr *e; + int i, flags; + + sym_set_change_count(0); + + if (conf_read_simple(name, S_DEF_USER)) + return 1; + + for_all_symbols(i, sym) { + sym_calc_value(sym); + if (sym_is_choice(sym) || (sym->flags & SYMBOL_AUTO)) + goto sym_ok; + if (sym_has_value(sym) && (sym->flags & SYMBOL_WRITE)) { + /* check that calculated value agrees with saved value */ + switch (sym->type) { + case S_BOOLEAN: + case S_TRISTATE: + if (sym->def[S_DEF_USER].tri != sym_get_tristate_value(sym)) + break; + if (!sym_is_choice(sym)) + goto sym_ok; + default: + if (!strcmp(sym->curr.val, sym->def[S_DEF_USER].val)) + goto sym_ok; + break; + } + } else if (!sym_has_value(sym) && !(sym->flags & SYMBOL_WRITE)) + /* no previous value and not saved */ + goto sym_ok; + conf_unsaved++; + /* maybe print value in verbose mode... */ + sym_ok: + if (!sym_is_choice(sym)) + continue; + /* The choice symbol only has a set value (and thus is not new) + * if all its visible childs have values. + */ + prop = sym_get_choice_prop(sym); + flags = sym->flags; + expr_list_for_each_sym(prop->expr, e, choice_sym) + if (choice_sym->visible != no) + flags &= choice_sym->flags; + sym->flags &= flags | ~SYMBOL_DEF_USER; + } + + for_all_symbols(i, sym) { + if (sym_has_value(sym) && !sym_is_choice_value(sym)) { + /* Reset values of generates values, so they'll appear + * as new, if they should become visible, but that + * doesn't quite work if the Kconfig and the saved + * configuration disagree. + */ + if (sym->visible == no && !conf_unsaved) + sym->flags &= ~SYMBOL_DEF_USER; + switch (sym->type) { + case S_STRING: + case S_INT: + case S_HEX: + /* Reset a string value if it's out of range */ + if (sym_string_within_range(sym, sym->def[S_DEF_USER].val)) + break; + sym->flags &= ~(SYMBOL_VALID|SYMBOL_DEF_USER); + conf_unsaved++; + break; + default: + break; + } + } + } + + sym_add_change_count(conf_warnings || conf_unsaved); + + return 0; +} + +int conf_write(const char *name) +{ + FILE *out; + struct symbol *sym; + struct menu *menu; + const char *basename; + char dirname[128], tmpname[128], newname[128]; + int type, l; + const char *str; + time_t now; + int use_timestamp = 1; + char *env; + + dirname[0] = 0; + if (name == NULL) + name = conf_get_configname(); + if (name && name[0]) { + struct stat st; + char *slash; + + if (!stat(name, &st) && S_ISDIR(st.st_mode)) { + strcpy(dirname, name); + strcat(dirname, "/"); + basename = conf_get_configname(); + } else if ((slash = strrchr(name, '/'))) { + int size = slash - name + 1; + memcpy(dirname, name, size); + dirname[size] = 0; + if (slash[1]) + basename = slash + 1; + else + basename = conf_get_configname(); + } else + basename = name; + } else + basename = conf_get_configname(); + + sprintf(newname, "%s%s", dirname, basename); + env = getenv("KCONFIG_OVERWRITECONFIG"); + if (!env || !*env) { + sprintf(tmpname, "%s.tmpconfig.%d", dirname, (int)getpid()); + out = fopen(tmpname, "w"); + } else { + *tmpname = 0; + out = fopen(newname, "w"); + } + if (!out) + return 1; + + sym = sym_lookup("VERSION", 0); + sym_calc_value(sym); + time(&now); + env = getenv("KCONFIG_NOTIMESTAMP"); + if (env && *env) + use_timestamp = 0; + + fprintf(out, _("#\n" + "# Automatically generated make config: don't edit\n" + "# Version: %s\n" + "%s%s" + "#\n"), + sym_get_string_value(sym), + use_timestamp ? "# " : "", + use_timestamp ? ctime(&now) : ""); + + if (!conf_get_changed()) + sym_clear_all_valid(); + + menu = rootmenu.list; + while (menu) { + sym = menu->sym; + if (!sym) { + if (!menu_is_visible(menu)) + goto next; + str = menu_get_prompt(menu); + fprintf(out, "\n" + "#\n" + "# %s\n" + "#\n", str); + } else if (!(sym->flags & SYMBOL_CHOICE)) { + sym_calc_value(sym); + if (!(sym->flags & SYMBOL_WRITE)) + goto next; + sym->flags &= ~SYMBOL_WRITE; + type = sym->type; + if (type == S_TRISTATE) { + sym_calc_value(modules_sym); + if (modules_sym->curr.tri == no) + type = S_BOOLEAN; + } + switch (type) { + case S_BOOLEAN: + case S_TRISTATE: + switch (sym_get_tristate_value(sym)) { + case no: + fprintf(out, "# %s is not set\n", sym->name); + break; + case mod: + fprintf(out, "%s=m\n", sym->name); + break; + case yes: + fprintf(out, "%s=y\n", sym->name); + break; + } + break; + case S_STRING: + str = sym_get_string_value(sym); + fprintf(out, "%s=\"", sym->name); + while (1) { + l = strcspn(str, "\"\\"); + if (l) { + fwrite(str, l, 1, out); + str += l; + } + if (!*str) + break; + fprintf(out, "\\%c", *str++); + } + fputs("\"\n", out); + break; + case S_HEX: + str = sym_get_string_value(sym); + if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) { + fprintf(out, "%s=%s\n", sym->name, str); + break; + } + case S_INT: + str = sym_get_string_value(sym); + fprintf(out, "%s=%s\n", sym->name, str); + break; + } + } + + next: + if (menu->list) { + menu = menu->list; + continue; + } + if (menu->next) + menu = menu->next; + else while ((menu = menu->parent)) { + if (menu->next) { + menu = menu->next; + break; + } + } + } + fclose(out); + + if (*tmpname) { + strcat(dirname, basename); + strcat(dirname, ".old"); + rename(newname, dirname); + if (rename(tmpname, newname)) + return 1; + } + + printf(_("#\n" + "# configuration written to %s\n" + "#\n"), newname); + + sym_set_change_count(0); + + return 0; +} + +int conf_split_config(void) +{ + char *name, path[128], opwd[512]; + char *s, *d, c; + struct symbol *sym; + struct stat sb; + int res, i, fd; + + name = getenv("KCONFIG_AUTOCONFIG"); + if (!name) + name = "include/config/auto.conf"; + conf_read_simple(name, S_DEF_AUTO); + + if (getcwd(opwd, sizeof(opwd)) == NULL) + return 1; + if (chdir(dirname(strdup(name)))) + return 1; + + res = 0; + for_all_symbols(i, sym) { + sym_calc_value(sym); + if ((sym->flags & SYMBOL_AUTO) || !sym->name) + continue; + if (sym->flags & SYMBOL_WRITE) { + if (sym->flags & SYMBOL_DEF_AUTO) { + /* + * symbol has old and new value, + * so compare them... + */ + switch (sym->type) { + case S_BOOLEAN: + case S_TRISTATE: + if (sym_get_tristate_value(sym) == + sym->def[S_DEF_AUTO].tri) + continue; + break; + case S_STRING: + case S_HEX: + case S_INT: + if (!strcmp(sym_get_string_value(sym), + sym->def[S_DEF_AUTO].val)) + continue; + break; + default: + break; + } + } else { + /* + * If there is no old value, only 'no' (unset) + * is allowed as new value. + */ + switch (sym->type) { + case S_BOOLEAN: + case S_TRISTATE: + if (sym_get_tristate_value(sym) == no) + continue; + break; + default: + break; + } + } + } else if (!(sym->flags & SYMBOL_DEF_AUTO)) + /* There is neither an old nor a new value. */ + continue; + /* else + * There is an old value, but no new value ('no' (unset) + * isn't saved in auto.conf, so the old value is always + * different from 'no'). + */ + + /* Replace all '_' and append ".h" */ + s = sym->name; + d = path; + while ((c = *s++)) { + c = tolower(c); + *d++ = (c == '_') ? '/' : c; + } + strcpy(d, ".h"); + + /* Assume directory path already exists. */ + fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644); + if (fd == -1) { + if (errno != ENOENT) { + res = 1; + break; + } + /* + * Create directory components, + * unless they exist already. + */ + d = path; + while ((d = strchr(d, '/'))) { + *d = 0; + if (stat(path, &sb) && mkdir(path, 0755)) { + res = 1; + goto out; + } + *d++ = '/'; + } + /* Try it again. */ + fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644); + if (fd == -1) { + res = 1; + break; + } + } + close(fd); + } +out: + if (chdir(opwd)) + return 1; + + return res; +} + +int conf_write_autoconf(void) +{ + char opwd[512]; + struct symbol *sym; + const char *str; + char *name; + FILE *out, *out_h; + time_t now; + int i, l; + + if (getcwd(opwd, sizeof(opwd)) == NULL) + return 1; + if (chdir(dirname(strdup(conf_get_configname())))) + return 1; + sym_clear_all_valid(); + + file_write_dep("include/config/auto.conf.cmd"); + + if (conf_split_config()) + return 1; + + out = fopen(".tmpconfig", "w"); + if (!out) + return 1; + + out_h = fopen(".tmpconfig.h", "w"); + if (!out_h) { + fclose(out); + return 1; + } + + sym = sym_lookup("VERSION", 0); + sym_calc_value(sym); + time(&now); + fprintf(out, "#\n" + "# Automatically generated make config: don't edit\n" + "# Version: %s\n" + "# %s" + "#\n", + sym_get_string_value(sym), ctime(&now)); + fprintf(out_h, "/*\n" + " * Automatically generated C config: don't edit\n" + " * Version: %s\n" + " * %s" + " */\n" + "#define AUTOCONF_INCLUDED\n", + sym_get_string_value(sym), ctime(&now)); + + for_all_symbols(i, sym) { + sym_calc_value(sym); + if (!(sym->flags & SYMBOL_WRITE) || !sym->name) + continue; + switch (sym->type) { + case S_BOOLEAN: + case S_TRISTATE: + switch (sym_get_tristate_value(sym)) { + case no: + break; + case mod: + fprintf(out, "CONFIG_%s=m\n", sym->name); + fprintf(out_h, "#define CONFIG_%s_MODULE 1\n", sym->name); + break; + case yes: + fprintf(out, "%s=y\n", sym->name); + fprintf(out_h, "#define %s 1\n", sym->name); + break; + } + break; + case S_STRING: + str = sym_get_string_value(sym); + fprintf(out, "%s=\"", sym->name); + fprintf(out_h, "#define %s \"", sym->name); + while (1) { + l = strcspn(str, "\"\\"); + if (l) { + fwrite(str, l, 1, out); + fwrite(str, l, 1, out_h); + str += l; + } + if (!*str) + break; + fprintf(out, "\\%c", *str); + fprintf(out_h, "\\%c", *str); + str++; + } + fputs("\"\n", out); + fputs("\"\n", out_h); + break; + case S_HEX: + str = sym_get_string_value(sym); + if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) { + fprintf(out, "%s=%s\n", sym->name, str); + fprintf(out_h, "#define %s 0x%s\n", sym->name, str); + break; + } + case S_INT: + str = sym_get_string_value(sym); + fprintf(out, "%s=%s\n", sym->name, str); + fprintf(out_h, "#define %s %s\n", sym->name, str); + break; + default: + break; + } + } + fclose(out); + fclose(out_h); + + name = getenv("KCONFIG_AUTOHEADER"); + if (!name) + name = "include/config/autoconf.h"; + if (rename(".tmpconfig.h", name)) + return 1; + name = getenv("KCONFIG_AUTOCONFIG"); + if (!name) + name = "include/config/auto.conf"; + /* + * This must be the last step, kbuild has a dependency on auto.conf + * and this marks the successful completion of the previous steps. + */ + if (rename(".tmpconfig", name)) + return 1; + chdir(opwd); + return 0; +} + +static int sym_change_count; +static void (*conf_changed_callback)(void); + +void sym_set_change_count(int count) +{ + int _sym_change_count = sym_change_count; + sym_change_count = count; + if (conf_changed_callback && + (bool)_sym_change_count != (bool)count) + conf_changed_callback(); +} + +void sym_add_change_count(int count) +{ + sym_set_change_count(count + sym_change_count); +} + +bool conf_get_changed(void) +{ + return sym_change_count; +} + +void conf_set_changed_callback(void (*fn)(void)) +{ + conf_changed_callback = fn; +} + + +void conf_set_all_new_symbols(enum conf_def_mode mode) +{ + struct symbol *sym, *csym; + struct property *prop; + struct expr *e; + int i, cnt, def; + + for_all_symbols(i, sym) { + if (sym_has_value(sym)) + continue; + switch (sym_get_type(sym)) { + case S_BOOLEAN: + case S_TRISTATE: + switch (mode) { + case def_yes: + sym->def[S_DEF_USER].tri = yes; + break; + case def_mod: + sym->def[S_DEF_USER].tri = mod; + break; + case def_no: + sym->def[S_DEF_USER].tri = no; + break; + case def_random: + sym->def[S_DEF_USER].tri = (tristate)(rand() % 3); + break; + default: + continue; + } + if (!(sym_is_choice(sym) && mode == def_random)) + sym->flags |= SYMBOL_DEF_USER; + break; + default: + break; + } + + } + + sym_clear_all_valid(); + + if (mode != def_random) + return; + /* + * We have different type of choice blocks. + * If curr.tri equal to mod then we can select several + * choice symbols in one block. + * In this case we do nothing. + * If curr.tri equal yes then only one symbol can be + * selected in a choice block and we set it to yes, + * and the rest to no. + */ + for_all_symbols(i, csym) { + if (sym_has_value(csym) || !sym_is_choice(csym)) + continue; + + sym_calc_value(csym); + + if (csym->curr.tri != yes) + continue; + + prop = sym_get_choice_prop(csym); + + /* count entries in choice block */ + cnt = 0; + expr_list_for_each_sym(prop->expr, e, sym) + cnt++; + + /* + * find a random value and set it to yes, + * set the rest to no so we have only one set + */ + def = (rand() % cnt); + + cnt = 0; + expr_list_for_each_sym(prop->expr, e, sym) { + if (def == cnt++) { + sym->def[S_DEF_USER].tri = yes; + csym->def[S_DEF_USER].val = sym; + } + else { + sym->def[S_DEF_USER].tri = no; + } + } + csym->flags |= SYMBOL_DEF_USER; + /* clear VALID to get value calculated */ + csym->flags &= ~(SYMBOL_VALID); + } +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/expr.c b/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/expr.c new file mode 100644 index 00000000..579ece4f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/expr.c @@ -0,0 +1,1106 @@ +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +#include +#include +#include + +#define LKC_DIRECT_LINK +#include "lkc.h" + +#define DEBUG_EXPR 0 + +struct expr *expr_alloc_symbol(struct symbol *sym) +{ + struct expr *e = malloc(sizeof(*e)); + memset(e, 0, sizeof(*e)); + e->type = E_SYMBOL; + e->left.sym = sym; + return e; +} + +struct expr *expr_alloc_one(enum expr_type type, struct expr *ce) +{ + struct expr *e = malloc(sizeof(*e)); + memset(e, 0, sizeof(*e)); + e->type = type; + e->left.expr = ce; + return e; +} + +struct expr *expr_alloc_two(enum expr_type type, struct expr *e1, struct expr *e2) +{ + struct expr *e = malloc(sizeof(*e)); + memset(e, 0, sizeof(*e)); + e->type = type; + e->left.expr = e1; + e->right.expr = e2; + return e; +} + +struct expr *expr_alloc_comp(enum expr_type type, struct symbol *s1, struct symbol *s2) +{ + struct expr *e = malloc(sizeof(*e)); + memset(e, 0, sizeof(*e)); + e->type = type; + e->left.sym = s1; + e->right.sym = s2; + return e; +} + +struct expr *expr_alloc_and(struct expr *e1, struct expr *e2) +{ + if (!e1) + return e2; + return e2 ? expr_alloc_two(E_AND, e1, e2) : e1; +} + +struct expr *expr_alloc_or(struct expr *e1, struct expr *e2) +{ + if (!e1) + return e2; + return e2 ? expr_alloc_two(E_OR, e1, e2) : e1; +} + +struct expr *expr_copy(struct expr *org) +{ + struct expr *e; + + if (!org) + return NULL; + + e = malloc(sizeof(*org)); + memcpy(e, org, sizeof(*org)); + switch (org->type) { + case E_SYMBOL: + e->left = org->left; + break; + case E_NOT: + e->left.expr = expr_copy(org->left.expr); + break; + case E_EQUAL: + case E_UNEQUAL: + e->left.sym = org->left.sym; + e->right.sym = org->right.sym; + break; + case E_AND: + case E_OR: + case E_LIST: + e->left.expr = expr_copy(org->left.expr); + e->right.expr = expr_copy(org->right.expr); + break; + default: + printf("can't copy type %d\n", e->type); + free(e); + e = NULL; + break; + } + + return e; +} + +void expr_free(struct expr *e) +{ + if (!e) + return; + + switch (e->type) { + case E_SYMBOL: + break; + case E_NOT: + expr_free(e->left.expr); + return; + case E_EQUAL: + case E_UNEQUAL: + break; + case E_OR: + case E_AND: + expr_free(e->left.expr); + expr_free(e->right.expr); + break; + default: + printf("how to free type %d?\n", e->type); + break; + } + free(e); +} + +static int trans_count; + +#define e1 (*ep1) +#define e2 (*ep2) + +static void __expr_eliminate_eq(enum expr_type type, struct expr **ep1, struct expr **ep2) +{ + if (e1->type == type) { + __expr_eliminate_eq(type, &e1->left.expr, &e2); + __expr_eliminate_eq(type, &e1->right.expr, &e2); + return; + } + if (e2->type == type) { + __expr_eliminate_eq(type, &e1, &e2->left.expr); + __expr_eliminate_eq(type, &e1, &e2->right.expr); + return; + } + if (e1->type == E_SYMBOL && e2->type == E_SYMBOL && + e1->left.sym == e2->left.sym && + (e1->left.sym == &symbol_yes || e1->left.sym == &symbol_no)) + return; + if (!expr_eq(e1, e2)) + return; + trans_count++; + expr_free(e1); expr_free(e2); + switch (type) { + case E_OR: + e1 = expr_alloc_symbol(&symbol_no); + e2 = expr_alloc_symbol(&symbol_no); + break; + case E_AND: + e1 = expr_alloc_symbol(&symbol_yes); + e2 = expr_alloc_symbol(&symbol_yes); + break; + default: + ; + } +} + +void expr_eliminate_eq(struct expr **ep1, struct expr **ep2) +{ + if (!e1 || !e2) + return; + switch (e1->type) { + case E_OR: + case E_AND: + __expr_eliminate_eq(e1->type, ep1, ep2); + default: + ; + } + if (e1->type != e2->type) switch (e2->type) { + case E_OR: + case E_AND: + __expr_eliminate_eq(e2->type, ep1, ep2); + default: + ; + } + e1 = expr_eliminate_yn(e1); + e2 = expr_eliminate_yn(e2); +} + +#undef e1 +#undef e2 + +int expr_eq(struct expr *e1, struct expr *e2) +{ + int res, old_count; + + if (e1->type != e2->type) + return 0; + switch (e1->type) { + case E_EQUAL: + case E_UNEQUAL: + return e1->left.sym == e2->left.sym && e1->right.sym == e2->right.sym; + case E_SYMBOL: + return e1->left.sym == e2->left.sym; + case E_NOT: + return expr_eq(e1->left.expr, e2->left.expr); + case E_AND: + case E_OR: + e1 = expr_copy(e1); + e2 = expr_copy(e2); + old_count = trans_count; + expr_eliminate_eq(&e1, &e2); + res = (e1->type == E_SYMBOL && e2->type == E_SYMBOL && + e1->left.sym == e2->left.sym); + expr_free(e1); + expr_free(e2); + trans_count = old_count; + return res; + case E_LIST: + case E_RANGE: + case E_NONE: + /* panic */; + } + + if (DEBUG_EXPR) { + expr_fprint(e1, stdout); + printf(" = "); + expr_fprint(e2, stdout); + printf(" ?\n"); + } + + return 0; +} + +struct expr *expr_eliminate_yn(struct expr *e) +{ + struct expr *tmp; + + if (e) switch (e->type) { + case E_AND: + e->left.expr = expr_eliminate_yn(e->left.expr); + e->right.expr = expr_eliminate_yn(e->right.expr); + if (e->left.expr->type == E_SYMBOL) { + if (e->left.expr->left.sym == &symbol_no) { + expr_free(e->left.expr); + expr_free(e->right.expr); + e->type = E_SYMBOL; + e->left.sym = &symbol_no; + e->right.expr = NULL; + return e; + } else if (e->left.expr->left.sym == &symbol_yes) { + free(e->left.expr); + tmp = e->right.expr; + *e = *(e->right.expr); + free(tmp); + return e; + } + } + if (e->right.expr->type == E_SYMBOL) { + if (e->right.expr->left.sym == &symbol_no) { + expr_free(e->left.expr); + expr_free(e->right.expr); + e->type = E_SYMBOL; + e->left.sym = &symbol_no; + e->right.expr = NULL; + return e; + } else if (e->right.expr->left.sym == &symbol_yes) { + free(e->right.expr); + tmp = e->left.expr; + *e = *(e->left.expr); + free(tmp); + return e; + } + } + break; + case E_OR: + e->left.expr = expr_eliminate_yn(e->left.expr); + e->right.expr = expr_eliminate_yn(e->right.expr); + if (e->left.expr->type == E_SYMBOL) { + if (e->left.expr->left.sym == &symbol_no) { + free(e->left.expr); + tmp = e->right.expr; + *e = *(e->right.expr); + free(tmp); + return e; + } else if (e->left.expr->left.sym == &symbol_yes) { + expr_free(e->left.expr); + expr_free(e->right.expr); + e->type = E_SYMBOL; + e->left.sym = &symbol_yes; + e->right.expr = NULL; + return e; + } + } + if (e->right.expr->type == E_SYMBOL) { + if (e->right.expr->left.sym == &symbol_no) { + free(e->right.expr); + tmp = e->left.expr; + *e = *(e->left.expr); + free(tmp); + return e; + } else if (e->right.expr->left.sym == &symbol_yes) { + expr_free(e->left.expr); + expr_free(e->right.expr); + e->type = E_SYMBOL; + e->left.sym = &symbol_yes; + e->right.expr = NULL; + return e; + } + } + break; + default: + ; + } + return e; +} + +/* + * bool FOO!=n => FOO + */ +struct expr *expr_trans_bool(struct expr *e) +{ + if (!e) + return NULL; + switch (e->type) { + case E_AND: + case E_OR: + case E_NOT: + e->left.expr = expr_trans_bool(e->left.expr); + e->right.expr = expr_trans_bool(e->right.expr); + break; + case E_UNEQUAL: + // FOO!=n -> FOO + if (e->left.sym->type == S_TRISTATE) { + if (e->right.sym == &symbol_no) { + e->type = E_SYMBOL; + e->right.sym = NULL; + } + } + break; + default: + ; + } + return e; +} + +/* + * e1 || e2 -> ? + */ +struct expr *expr_join_or(struct expr *e1, struct expr *e2) +{ + struct expr *tmp; + struct symbol *sym1, *sym2; + + if (expr_eq(e1, e2)) + return expr_copy(e1); + if (e1->type != E_EQUAL && e1->type != E_UNEQUAL && e1->type != E_SYMBOL && e1->type != E_NOT) + return NULL; + if (e2->type != E_EQUAL && e2->type != E_UNEQUAL && e2->type != E_SYMBOL && e2->type != E_NOT) + return NULL; + if (e1->type == E_NOT) { + tmp = e1->left.expr; + if (tmp->type != E_EQUAL && tmp->type != E_UNEQUAL && tmp->type != E_SYMBOL) + return NULL; + sym1 = tmp->left.sym; + } else + sym1 = e1->left.sym; + if (e2->type == E_NOT) { + if (e2->left.expr->type != E_SYMBOL) + return NULL; + sym2 = e2->left.expr->left.sym; + } else + sym2 = e2->left.sym; + if (sym1 != sym2) + return NULL; + if (sym1->type != S_BOOLEAN && sym1->type != S_TRISTATE) + return NULL; + if (sym1->type == S_TRISTATE) { + if (e1->type == E_EQUAL && e2->type == E_EQUAL && + ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_mod) || + (e1->right.sym == &symbol_mod && e2->right.sym == &symbol_yes))) { + // (a='y') || (a='m') -> (a!='n') + return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_no); + } + if (e1->type == E_EQUAL && e2->type == E_EQUAL && + ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_no) || + (e1->right.sym == &symbol_no && e2->right.sym == &symbol_yes))) { + // (a='y') || (a='n') -> (a!='m') + return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_mod); + } + if (e1->type == E_EQUAL && e2->type == E_EQUAL && + ((e1->right.sym == &symbol_mod && e2->right.sym == &symbol_no) || + (e1->right.sym == &symbol_no && e2->right.sym == &symbol_mod))) { + // (a='m') || (a='n') -> (a!='y') + return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_yes); + } + } + if (sym1->type == S_BOOLEAN && sym1 == sym2) { + if ((e1->type == E_NOT && e1->left.expr->type == E_SYMBOL && e2->type == E_SYMBOL) || + (e2->type == E_NOT && e2->left.expr->type == E_SYMBOL && e1->type == E_SYMBOL)) + return expr_alloc_symbol(&symbol_yes); + } + + if (DEBUG_EXPR) { + printf("optimize ("); + expr_fprint(e1, stdout); + printf(") || ("); + expr_fprint(e2, stdout); + printf(")?\n"); + } + return NULL; +} + +struct expr *expr_join_and(struct expr *e1, struct expr *e2) +{ + struct expr *tmp; + struct symbol *sym1, *sym2; + + if (expr_eq(e1, e2)) + return expr_copy(e1); + if (e1->type != E_EQUAL && e1->type != E_UNEQUAL && e1->type != E_SYMBOL && e1->type != E_NOT) + return NULL; + if (e2->type != E_EQUAL && e2->type != E_UNEQUAL && e2->type != E_SYMBOL && e2->type != E_NOT) + return NULL; + if (e1->type == E_NOT) { + tmp = e1->left.expr; + if (tmp->type != E_EQUAL && tmp->type != E_UNEQUAL && tmp->type != E_SYMBOL) + return NULL; + sym1 = tmp->left.sym; + } else + sym1 = e1->left.sym; + if (e2->type == E_NOT) { + if (e2->left.expr->type != E_SYMBOL) + return NULL; + sym2 = e2->left.expr->left.sym; + } else + sym2 = e2->left.sym; + if (sym1 != sym2) + return NULL; + if (sym1->type != S_BOOLEAN && sym1->type != S_TRISTATE) + return NULL; + + if ((e1->type == E_SYMBOL && e2->type == E_EQUAL && e2->right.sym == &symbol_yes) || + (e2->type == E_SYMBOL && e1->type == E_EQUAL && e1->right.sym == &symbol_yes)) + // (a) && (a='y') -> (a='y') + return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes); + + if ((e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_no) || + (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_no)) + // (a) && (a!='n') -> (a) + return expr_alloc_symbol(sym1); + + if ((e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_mod) || + (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_mod)) + // (a) && (a!='m') -> (a='y') + return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes); + + if (sym1->type == S_TRISTATE) { + if (e1->type == E_EQUAL && e2->type == E_UNEQUAL) { + // (a='b') && (a!='c') -> 'b'='c' ? 'n' : a='b' + sym2 = e1->right.sym; + if ((e2->right.sym->flags & SYMBOL_CONST) && (sym2->flags & SYMBOL_CONST)) + return sym2 != e2->right.sym ? expr_alloc_comp(E_EQUAL, sym1, sym2) + : expr_alloc_symbol(&symbol_no); + } + if (e1->type == E_UNEQUAL && e2->type == E_EQUAL) { + // (a='b') && (a!='c') -> 'b'='c' ? 'n' : a='b' + sym2 = e2->right.sym; + if ((e1->right.sym->flags & SYMBOL_CONST) && (sym2->flags & SYMBOL_CONST)) + return sym2 != e1->right.sym ? expr_alloc_comp(E_EQUAL, sym1, sym2) + : expr_alloc_symbol(&symbol_no); + } + if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL && + ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_no) || + (e1->right.sym == &symbol_no && e2->right.sym == &symbol_yes))) + // (a!='y') && (a!='n') -> (a='m') + return expr_alloc_comp(E_EQUAL, sym1, &symbol_mod); + + if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL && + ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_mod) || + (e1->right.sym == &symbol_mod && e2->right.sym == &symbol_yes))) + // (a!='y') && (a!='m') -> (a='n') + return expr_alloc_comp(E_EQUAL, sym1, &symbol_no); + + if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL && + ((e1->right.sym == &symbol_mod && e2->right.sym == &symbol_no) || + (e1->right.sym == &symbol_no && e2->right.sym == &symbol_mod))) + // (a!='m') && (a!='n') -> (a='m') + return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes); + + if ((e1->type == E_SYMBOL && e2->type == E_EQUAL && e2->right.sym == &symbol_mod) || + (e2->type == E_SYMBOL && e1->type == E_EQUAL && e1->right.sym == &symbol_mod) || + (e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_yes) || + (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_yes)) + return NULL; + } + + if (DEBUG_EXPR) { + printf("optimize ("); + expr_fprint(e1, stdout); + printf(") && ("); + expr_fprint(e2, stdout); + printf(")?\n"); + } + return NULL; +} + +static void expr_eliminate_dups1(enum expr_type type, struct expr **ep1, struct expr **ep2) +{ +#define e1 (*ep1) +#define e2 (*ep2) + struct expr *tmp; + + if (e1->type == type) { + expr_eliminate_dups1(type, &e1->left.expr, &e2); + expr_eliminate_dups1(type, &e1->right.expr, &e2); + return; + } + if (e2->type == type) { + expr_eliminate_dups1(type, &e1, &e2->left.expr); + expr_eliminate_dups1(type, &e1, &e2->right.expr); + return; + } + if (e1 == e2) + return; + + switch (e1->type) { + case E_OR: case E_AND: + expr_eliminate_dups1(e1->type, &e1, &e1); + default: + ; + } + + switch (type) { + case E_OR: + tmp = expr_join_or(e1, e2); + if (tmp) { + expr_free(e1); expr_free(e2); + e1 = expr_alloc_symbol(&symbol_no); + e2 = tmp; + trans_count++; + } + break; + case E_AND: + tmp = expr_join_and(e1, e2); + if (tmp) { + expr_free(e1); expr_free(e2); + e1 = expr_alloc_symbol(&symbol_yes); + e2 = tmp; + trans_count++; + } + break; + default: + ; + } +#undef e1 +#undef e2 +} + +static void expr_eliminate_dups2(enum expr_type type, struct expr **ep1, struct expr **ep2) +{ +#define e1 (*ep1) +#define e2 (*ep2) + struct expr *tmp, *tmp1, *tmp2; + + if (e1->type == type) { + expr_eliminate_dups2(type, &e1->left.expr, &e2); + expr_eliminate_dups2(type, &e1->right.expr, &e2); + return; + } + if (e2->type == type) { + expr_eliminate_dups2(type, &e1, &e2->left.expr); + expr_eliminate_dups2(type, &e1, &e2->right.expr); + } + if (e1 == e2) + return; + + switch (e1->type) { + case E_OR: + expr_eliminate_dups2(e1->type, &e1, &e1); + // (FOO || BAR) && (!FOO && !BAR) -> n + tmp1 = expr_transform(expr_alloc_one(E_NOT, expr_copy(e1))); + tmp2 = expr_copy(e2); + tmp = expr_extract_eq_and(&tmp1, &tmp2); + if (expr_is_yes(tmp1)) { + expr_free(e1); + e1 = expr_alloc_symbol(&symbol_no); + trans_count++; + } + expr_free(tmp2); + expr_free(tmp1); + expr_free(tmp); + break; + case E_AND: + expr_eliminate_dups2(e1->type, &e1, &e1); + // (FOO && BAR) || (!FOO || !BAR) -> y + tmp1 = expr_transform(expr_alloc_one(E_NOT, expr_copy(e1))); + tmp2 = expr_copy(e2); + tmp = expr_extract_eq_or(&tmp1, &tmp2); + if (expr_is_no(tmp1)) { + expr_free(e1); + e1 = expr_alloc_symbol(&symbol_yes); + trans_count++; + } + expr_free(tmp2); + expr_free(tmp1); + expr_free(tmp); + break; + default: + ; + } +#undef e1 +#undef e2 +} + +struct expr *expr_eliminate_dups(struct expr *e) +{ + int oldcount; + if (!e) + return e; + + oldcount = trans_count; + while (1) { + trans_count = 0; + switch (e->type) { + case E_OR: case E_AND: + expr_eliminate_dups1(e->type, &e, &e); + expr_eliminate_dups2(e->type, &e, &e); + default: + ; + } + if (!trans_count) + break; + e = expr_eliminate_yn(e); + } + trans_count = oldcount; + return e; +} + +struct expr *expr_transform(struct expr *e) +{ + struct expr *tmp; + + if (!e) + return NULL; + switch (e->type) { + case E_EQUAL: + case E_UNEQUAL: + case E_SYMBOL: + case E_LIST: + break; + default: + e->left.expr = expr_transform(e->left.expr); + e->right.expr = expr_transform(e->right.expr); + } + + switch (e->type) { + case E_EQUAL: + if (e->left.sym->type != S_BOOLEAN) + break; + if (e->right.sym == &symbol_no) { + e->type = E_NOT; + e->left.expr = expr_alloc_symbol(e->left.sym); + e->right.sym = NULL; + break; + } + if (e->right.sym == &symbol_mod) { + printf("boolean symbol %s tested for 'm'? test forced to 'n'\n", e->left.sym->name); + e->type = E_SYMBOL; + e->left.sym = &symbol_no; + e->right.sym = NULL; + break; + } + if (e->right.sym == &symbol_yes) { + e->type = E_SYMBOL; + e->right.sym = NULL; + break; + } + break; + case E_UNEQUAL: + if (e->left.sym->type != S_BOOLEAN) + break; + if (e->right.sym == &symbol_no) { + e->type = E_SYMBOL; + e->right.sym = NULL; + break; + } + if (e->right.sym == &symbol_mod) { + printf("boolean symbol %s tested for 'm'? test forced to 'y'\n", e->left.sym->name); + e->type = E_SYMBOL; + e->left.sym = &symbol_yes; + e->right.sym = NULL; + break; + } + if (e->right.sym == &symbol_yes) { + e->type = E_NOT; + e->left.expr = expr_alloc_symbol(e->left.sym); + e->right.sym = NULL; + break; + } + break; + case E_NOT: + switch (e->left.expr->type) { + case E_NOT: + // !!a -> a + tmp = e->left.expr->left.expr; + free(e->left.expr); + free(e); + e = tmp; + e = expr_transform(e); + break; + case E_EQUAL: + case E_UNEQUAL: + // !a='x' -> a!='x' + tmp = e->left.expr; + free(e); + e = tmp; + e->type = e->type == E_EQUAL ? E_UNEQUAL : E_EQUAL; + break; + case E_OR: + // !(a || b) -> !a && !b + tmp = e->left.expr; + e->type = E_AND; + e->right.expr = expr_alloc_one(E_NOT, tmp->right.expr); + tmp->type = E_NOT; + tmp->right.expr = NULL; + e = expr_transform(e); + break; + case E_AND: + // !(a && b) -> !a || !b + tmp = e->left.expr; + e->type = E_OR; + e->right.expr = expr_alloc_one(E_NOT, tmp->right.expr); + tmp->type = E_NOT; + tmp->right.expr = NULL; + e = expr_transform(e); + break; + case E_SYMBOL: + if (e->left.expr->left.sym == &symbol_yes) { + // !'y' -> 'n' + tmp = e->left.expr; + free(e); + e = tmp; + e->type = E_SYMBOL; + e->left.sym = &symbol_no; + break; + } + if (e->left.expr->left.sym == &symbol_mod) { + // !'m' -> 'm' + tmp = e->left.expr; + free(e); + e = tmp; + e->type = E_SYMBOL; + e->left.sym = &symbol_mod; + break; + } + if (e->left.expr->left.sym == &symbol_no) { + // !'n' -> 'y' + tmp = e->left.expr; + free(e); + e = tmp; + e->type = E_SYMBOL; + e->left.sym = &symbol_yes; + break; + } + break; + default: + ; + } + break; + default: + ; + } + return e; +} + +int expr_contains_symbol(struct expr *dep, struct symbol *sym) +{ + if (!dep) + return 0; + + switch (dep->type) { + case E_AND: + case E_OR: + return expr_contains_symbol(dep->left.expr, sym) || + expr_contains_symbol(dep->right.expr, sym); + case E_SYMBOL: + return dep->left.sym == sym; + case E_EQUAL: + case E_UNEQUAL: + return dep->left.sym == sym || + dep->right.sym == sym; + case E_NOT: + return expr_contains_symbol(dep->left.expr, sym); + default: + ; + } + return 0; +} + +bool expr_depends_symbol(struct expr *dep, struct symbol *sym) +{ + if (!dep) + return false; + + switch (dep->type) { + case E_AND: + return expr_depends_symbol(dep->left.expr, sym) || + expr_depends_symbol(dep->right.expr, sym); + case E_SYMBOL: + return dep->left.sym == sym; + case E_EQUAL: + if (dep->left.sym == sym) { + if (dep->right.sym == &symbol_yes || dep->right.sym == &symbol_mod) + return true; + } + break; + case E_UNEQUAL: + if (dep->left.sym == sym) { + if (dep->right.sym == &symbol_no) + return true; + } + break; + default: + ; + } + return false; +} + +struct expr *expr_extract_eq_and(struct expr **ep1, struct expr **ep2) +{ + struct expr *tmp = NULL; + expr_extract_eq(E_AND, &tmp, ep1, ep2); + if (tmp) { + *ep1 = expr_eliminate_yn(*ep1); + *ep2 = expr_eliminate_yn(*ep2); + } + return tmp; +} + +struct expr *expr_extract_eq_or(struct expr **ep1, struct expr **ep2) +{ + struct expr *tmp = NULL; + expr_extract_eq(E_OR, &tmp, ep1, ep2); + if (tmp) { + *ep1 = expr_eliminate_yn(*ep1); + *ep2 = expr_eliminate_yn(*ep2); + } + return tmp; +} + +void expr_extract_eq(enum expr_type type, struct expr **ep, struct expr **ep1, struct expr **ep2) +{ +#define e1 (*ep1) +#define e2 (*ep2) + if (e1->type == type) { + expr_extract_eq(type, ep, &e1->left.expr, &e2); + expr_extract_eq(type, ep, &e1->right.expr, &e2); + return; + } + if (e2->type == type) { + expr_extract_eq(type, ep, ep1, &e2->left.expr); + expr_extract_eq(type, ep, ep1, &e2->right.expr); + return; + } + if (expr_eq(e1, e2)) { + *ep = *ep ? expr_alloc_two(type, *ep, e1) : e1; + expr_free(e2); + if (type == E_AND) { + e1 = expr_alloc_symbol(&symbol_yes); + e2 = expr_alloc_symbol(&symbol_yes); + } else if (type == E_OR) { + e1 = expr_alloc_symbol(&symbol_no); + e2 = expr_alloc_symbol(&symbol_no); + } + } +#undef e1 +#undef e2 +} + +struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symbol *sym) +{ + struct expr *e1, *e2; + + if (!e) { + e = expr_alloc_symbol(sym); + if (type == E_UNEQUAL) + e = expr_alloc_one(E_NOT, e); + return e; + } + switch (e->type) { + case E_AND: + e1 = expr_trans_compare(e->left.expr, E_EQUAL, sym); + e2 = expr_trans_compare(e->right.expr, E_EQUAL, sym); + if (sym == &symbol_yes) + e = expr_alloc_two(E_AND, e1, e2); + if (sym == &symbol_no) + e = expr_alloc_two(E_OR, e1, e2); + if (type == E_UNEQUAL) + e = expr_alloc_one(E_NOT, e); + return e; + case E_OR: + e1 = expr_trans_compare(e->left.expr, E_EQUAL, sym); + e2 = expr_trans_compare(e->right.expr, E_EQUAL, sym); + if (sym == &symbol_yes) + e = expr_alloc_two(E_OR, e1, e2); + if (sym == &symbol_no) + e = expr_alloc_two(E_AND, e1, e2); + if (type == E_UNEQUAL) + e = expr_alloc_one(E_NOT, e); + return e; + case E_NOT: + return expr_trans_compare(e->left.expr, type == E_EQUAL ? E_UNEQUAL : E_EQUAL, sym); + case E_UNEQUAL: + case E_EQUAL: + if (type == E_EQUAL) { + if (sym == &symbol_yes) + return expr_copy(e); + if (sym == &symbol_mod) + return expr_alloc_symbol(&symbol_no); + if (sym == &symbol_no) + return expr_alloc_one(E_NOT, expr_copy(e)); + } else { + if (sym == &symbol_yes) + return expr_alloc_one(E_NOT, expr_copy(e)); + if (sym == &symbol_mod) + return expr_alloc_symbol(&symbol_yes); + if (sym == &symbol_no) + return expr_copy(e); + } + break; + case E_SYMBOL: + return expr_alloc_comp(type, e->left.sym, sym); + case E_LIST: + case E_RANGE: + case E_NONE: + /* panic */; + } + return NULL; +} + +tristate expr_calc_value(struct expr *e) +{ + tristate val1, val2; + const char *str1, *str2; + + if (!e) + return yes; + + switch (e->type) { + case E_SYMBOL: + sym_calc_value(e->left.sym); + return e->left.sym->curr.tri; + case E_AND: + val1 = expr_calc_value(e->left.expr); + val2 = expr_calc_value(e->right.expr); + return EXPR_AND(val1, val2); + case E_OR: + val1 = expr_calc_value(e->left.expr); + val2 = expr_calc_value(e->right.expr); + return EXPR_OR(val1, val2); + case E_NOT: + val1 = expr_calc_value(e->left.expr); + return EXPR_NOT(val1); + case E_EQUAL: + sym_calc_value(e->left.sym); + sym_calc_value(e->right.sym); + str1 = sym_get_string_value(e->left.sym); + str2 = sym_get_string_value(e->right.sym); + return !strcmp(str1, str2) ? yes : no; + case E_UNEQUAL: + sym_calc_value(e->left.sym); + sym_calc_value(e->right.sym); + str1 = sym_get_string_value(e->left.sym); + str2 = sym_get_string_value(e->right.sym); + return !strcmp(str1, str2) ? no : yes; + default: + printf("expr_calc_value: %d?\n", e->type); + return no; + } +} + +int expr_compare_type(enum expr_type t1, enum expr_type t2) +{ +#if 0 + return 1; +#else + if (t1 == t2) + return 0; + switch (t1) { + case E_EQUAL: + case E_UNEQUAL: + if (t2 == E_NOT) + return 1; + case E_NOT: + if (t2 == E_AND) + return 1; + case E_AND: + if (t2 == E_OR) + return 1; + case E_OR: + if (t2 == E_LIST) + return 1; + case E_LIST: + if (t2 == 0) + return 1; + default: + return -1; + } + printf("[%dgt%d?]", t1, t2); + return 0; +#endif +} + +void expr_print(struct expr *e, void (*fn)(void *, struct symbol *, const char *), void *data, int prevtoken) +{ + if (!e) { + fn(data, NULL, "y"); + return; + } + + if (expr_compare_type(prevtoken, e->type) > 0) + fn(data, NULL, "("); + switch (e->type) { + case E_SYMBOL: + if (e->left.sym->name) + fn(data, e->left.sym, e->left.sym->name); + else + fn(data, NULL, ""); + break; + case E_NOT: + fn(data, NULL, "!"); + expr_print(e->left.expr, fn, data, E_NOT); + break; + case E_EQUAL: + if (e->left.sym->name) + fn(data, e->left.sym, e->left.sym->name); + else + fn(data, NULL, ""); + fn(data, NULL, "="); + fn(data, e->right.sym, e->right.sym->name); + break; + case E_UNEQUAL: + if (e->left.sym->name) + fn(data, e->left.sym, e->left.sym->name); + else + fn(data, NULL, ""); + fn(data, NULL, "!="); + fn(data, e->right.sym, e->right.sym->name); + break; + case E_OR: + expr_print(e->left.expr, fn, data, E_OR); + fn(data, NULL, " || "); + expr_print(e->right.expr, fn, data, E_OR); + break; + case E_AND: + expr_print(e->left.expr, fn, data, E_AND); + fn(data, NULL, " && "); + expr_print(e->right.expr, fn, data, E_AND); + break; + case E_LIST: + fn(data, e->right.sym, e->right.sym->name); + if (e->left.expr) { + fn(data, NULL, " ^ "); + expr_print(e->left.expr, fn, data, E_LIST); + } + break; + case E_RANGE: + fn(data, NULL, "["); + fn(data, e->left.sym, e->left.sym->name); + fn(data, NULL, " "); + fn(data, e->right.sym, e->right.sym->name); + fn(data, NULL, "]"); + break; + default: + { + char buf[32]; + sprintf(buf, "", e->type); + fn(data, NULL, buf); + break; + } + } + if (expr_compare_type(prevtoken, e->type) > 0) + fn(data, NULL, ")"); +} + +static void expr_print_file_helper(void *data, struct symbol *sym, const char *str) +{ + fwrite(str, strlen(str), 1, data); +} + +void expr_fprint(struct expr *e, FILE *out) +{ + expr_print(e, expr_print_file_helper, out, E_NONE); +} + +static void expr_print_gstr_helper(void *data, struct symbol *sym, const char *str) +{ + str_append((struct gstr*)data, str); +} + +void expr_gstr_print(struct expr *e, struct gstr *gs) +{ + expr_print(e, expr_print_gstr_helper, gs, E_NONE); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/expr.h b/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/expr.h new file mode 100644 index 00000000..6408fefa --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/expr.h @@ -0,0 +1,228 @@ +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +#ifndef EXPR_H +#define EXPR_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#ifndef __cplusplus +#include +#endif + +struct file { + struct file *next; + struct file *parent; + char *name; + int lineno; + int flags; +}; + +#define FILE_BUSY 0x0001 +#define FILE_SCANNED 0x0002 + +typedef enum tristate { + no, mod, yes +} tristate; + +enum expr_type { + E_NONE, E_OR, E_AND, E_NOT, E_EQUAL, E_UNEQUAL, E_LIST, E_SYMBOL, E_RANGE +}; + +union expr_data { + struct expr *expr; + struct symbol *sym; +}; + +struct expr { + enum expr_type type; + union expr_data left, right; +}; + +#define EXPR_OR(dep1, dep2) (((dep1)>(dep2))?(dep1):(dep2)) +#define EXPR_AND(dep1, dep2) (((dep1)<(dep2))?(dep1):(dep2)) +#define EXPR_NOT(dep) (2-(dep)) + +#define expr_list_for_each_sym(l, e, s) \ + for (e = (l); e && (s = e->right.sym); e = e->left.expr) + +struct expr_value { + struct expr *expr; + tristate tri; +}; + +struct symbol_value { + void *val; + tristate tri; +}; + +enum symbol_type { + S_UNKNOWN, S_BOOLEAN, S_TRISTATE, S_INT, S_HEX, S_STRING, S_OTHER +}; + +/* enum values are used as index to symbol.def[] */ +enum { + S_DEF_USER, /* main user value */ + S_DEF_AUTO, /* values read from auto.conf */ + S_DEF_DEF3, /* Reserved for UI usage */ + S_DEF_DEF4, /* Reserved for UI usage */ + S_DEF_COUNT +}; + +struct symbol { + struct symbol *next; + char *name; + enum symbol_type type; + struct symbol_value curr; + struct symbol_value def[S_DEF_COUNT]; + tristate visible; + int flags; + struct property *prop; + struct expr_value rev_dep; +}; + +#define for_all_symbols(i, sym) for (i = 0; i < 257; i++) for (sym = symbol_hash[i]; sym; sym = sym->next) if (sym->type != S_OTHER) + +#define SYMBOL_CONST 0x0001 /* symbol is const */ +#define SYMBOL_CHECK 0x0008 /* used during dependency checking */ +#define SYMBOL_CHOICE 0x0010 /* start of a choice block (null name) */ +#define SYMBOL_CHOICEVAL 0x0020 /* used as a value in a choice block */ +#define SYMBOL_VALID 0x0080 /* set when symbol.curr is calculated */ +#define SYMBOL_OPTIONAL 0x0100 /* choice is optional - values can be 'n' */ +#define SYMBOL_WRITE 0x0200 /* ? */ +#define SYMBOL_CHANGED 0x0400 /* ? */ +#define SYMBOL_AUTO 0x1000 /* value from environment variable */ +#define SYMBOL_CHECKED 0x2000 /* used during dependency checking */ +#define SYMBOL_WARNED 0x8000 /* warning has been issued */ + +/* Set when symbol.def[] is used */ +#define SYMBOL_DEF 0x10000 /* First bit of SYMBOL_DEF */ +#define SYMBOL_DEF_USER 0x10000 /* symbol.def[S_DEF_USER] is valid */ +#define SYMBOL_DEF_AUTO 0x20000 /* symbol.def[S_DEF_AUTO] is valid */ +#define SYMBOL_DEF3 0x40000 /* symbol.def[S_DEF_3] is valid */ +#define SYMBOL_DEF4 0x80000 /* symbol.def[S_DEF_4] is valid */ + +#define SYMBOL_MAXLENGTH 256 +#define SYMBOL_HASHSIZE 257 +#define SYMBOL_HASHMASK 0xff + +/* A property represent the config options that can be associated + * with a config "symbol". + * Sample: + * config FOO + * default y + * prompt "foo prompt" + * select BAR + * config BAZ + * int "BAZ Value" + * range 1..255 + */ +enum prop_type { + P_UNKNOWN, + P_PROMPT, /* prompt "foo prompt" or "BAZ Value" */ + P_COMMENT, /* text associated with a comment */ + P_MENU, /* prompt associated with a menuconfig option */ + P_DEFAULT, /* default y */ + P_CHOICE, /* choice value */ + P_SELECT, /* select BAR */ + P_RANGE, /* range 7..100 (for a symbol) */ + P_ENV, /* value from environment variable */ +}; + +struct property { + struct property *next; /* next property - null if last */ + struct symbol *sym; /* the symbol for which the property is associated */ + enum prop_type type; /* type of property */ + const char *text; /* the prompt value - P_PROMPT, P_MENU, P_COMMENT */ + struct expr_value visible; + struct expr *expr; /* the optional conditional part of the property */ + struct menu *menu; /* the menu the property are associated with + * valid for: P_SELECT, P_RANGE, P_CHOICE, + * P_PROMPT, P_DEFAULT, P_MENU, P_COMMENT */ + struct file *file; /* what file was this property defined */ + int lineno; /* what lineno was this property defined */ +}; + +#define for_all_properties(sym, st, tok) \ + for (st = sym->prop; st; st = st->next) \ + if (st->type == (tok)) +#define for_all_defaults(sym, st) for_all_properties(sym, st, P_DEFAULT) +#define for_all_choices(sym, st) for_all_properties(sym, st, P_CHOICE) +#define for_all_prompts(sym, st) \ + for (st = sym->prop; st; st = st->next) \ + if (st->text) + +struct menu { + struct menu *next; + struct menu *parent; + struct menu *list; + struct symbol *sym; + struct property *prompt; + struct expr *dep; + unsigned int flags; + char *help; + struct file *file; + int lineno; + void *data; +}; + +#define MENU_CHANGED 0x0001 +#define MENU_ROOT 0x0002 + +#ifndef SWIG + +extern struct file *file_list; +extern struct file *current_file; +struct file *lookup_file(const char *name); + +extern struct symbol symbol_yes, symbol_no, symbol_mod; +extern struct symbol *modules_sym; +extern struct symbol *sym_defconfig_list; +extern int cdebug; +struct expr *expr_alloc_symbol(struct symbol *sym); +struct expr *expr_alloc_one(enum expr_type type, struct expr *ce); +struct expr *expr_alloc_two(enum expr_type type, struct expr *e1, struct expr *e2); +struct expr *expr_alloc_comp(enum expr_type type, struct symbol *s1, struct symbol *s2); +struct expr *expr_alloc_and(struct expr *e1, struct expr *e2); +struct expr *expr_alloc_or(struct expr *e1, struct expr *e2); +struct expr *expr_copy(struct expr *org); +void expr_free(struct expr *e); +int expr_eq(struct expr *e1, struct expr *e2); +void expr_eliminate_eq(struct expr **ep1, struct expr **ep2); +tristate expr_calc_value(struct expr *e); +struct expr *expr_eliminate_yn(struct expr *e); +struct expr *expr_trans_bool(struct expr *e); +struct expr *expr_eliminate_dups(struct expr *e); +struct expr *expr_transform(struct expr *e); +int expr_contains_symbol(struct expr *dep, struct symbol *sym); +bool expr_depends_symbol(struct expr *dep, struct symbol *sym); +struct expr *expr_extract_eq_and(struct expr **ep1, struct expr **ep2); +struct expr *expr_extract_eq_or(struct expr **ep1, struct expr **ep2); +void expr_extract_eq(enum expr_type type, struct expr **ep, struct expr **ep1, struct expr **ep2); +struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symbol *sym); + +void expr_fprint(struct expr *e, FILE *out); +struct gstr; /* forward */ +void expr_gstr_print(struct expr *e, struct gstr *gs); + +static inline int expr_is_yes(struct expr *e) +{ + return !e || (e->type == E_SYMBOL && e->left.sym == &symbol_yes); +} + +static inline int expr_is_no(struct expr *e) +{ + return e && (e->type == E_SYMBOL && e->left.sym == &symbol_no); +} +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* EXPR_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/gconf.c b/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/gconf.c new file mode 100644 index 00000000..540a0ff9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/gconf.c @@ -0,0 +1,1632 @@ +/* Hey EMACS -*- linux-c -*- */ +/* + * + * Copyright (C) 2002-2003 Romain Lievin + * Released under the terms of the GNU GPL v2.0. + * + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "lkc.h" +#include "images.c" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +//#define DEBUG + +enum { + SINGLE_VIEW, SPLIT_VIEW, FULL_VIEW +}; + +static gint view_mode = FULL_VIEW; +static gboolean show_name = TRUE; +static gboolean show_range = TRUE; +static gboolean show_value = TRUE; +static gboolean show_all = FALSE; +static gboolean show_debug = FALSE; +static gboolean resizeable = FALSE; + +GtkWidget *main_wnd = NULL; +GtkWidget *tree1_w = NULL; // left frame +GtkWidget *tree2_w = NULL; // right frame +GtkWidget *text_w = NULL; +GtkWidget *hpaned = NULL; +GtkWidget *vpaned = NULL; +GtkWidget *back_btn = NULL; +GtkWidget *save_btn = NULL; +GtkWidget *save_menu_item = NULL; + +GtkTextTag *tag1, *tag2; +GdkColor color; + +GtkTreeStore *tree1, *tree2, *tree; +GtkTreeModel *model1, *model2; +static GtkTreeIter *parents[256]; +static gint indent; + +static struct menu *current; // current node for SINGLE view +static struct menu *browsed; // browsed node for SPLIT view + +enum { + COL_OPTION, COL_NAME, COL_NO, COL_MOD, COL_YES, COL_VALUE, + COL_MENU, COL_COLOR, COL_EDIT, COL_PIXBUF, + COL_PIXVIS, COL_BTNVIS, COL_BTNACT, COL_BTNINC, COL_BTNRAD, + COL_NUMBER +}; + +static void display_list(void); +static void display_tree(struct menu *menu); +static void display_tree_part(void); +static void update_tree(struct menu *src, GtkTreeIter * dst); +static void set_node(GtkTreeIter * node, struct menu *menu, gchar ** row); +static gchar **fill_row(struct menu *menu); +static void conf_changed(void); + +/* Helping/Debugging Functions */ + + +const char *dbg_print_stype(int val) +{ + static char buf[256]; + + bzero(buf, 256); + + if (val == S_UNKNOWN) + strcpy(buf, "unknown"); + if (val == S_BOOLEAN) + strcpy(buf, "boolean"); + if (val == S_TRISTATE) + strcpy(buf, "tristate"); + if (val == S_INT) + strcpy(buf, "int"); + if (val == S_HEX) + strcpy(buf, "hex"); + if (val == S_STRING) + strcpy(buf, "string"); + if (val == S_OTHER) + strcpy(buf, "other"); + +#ifdef DEBUG + printf("%s", buf); +#endif + + return buf; +} + +const char *dbg_print_flags(int val) +{ + static char buf[256]; + + bzero(buf, 256); + + if (val & SYMBOL_CONST) + strcat(buf, "const/"); + if (val & SYMBOL_CHECK) + strcat(buf, "check/"); + if (val & SYMBOL_CHOICE) + strcat(buf, "choice/"); + if (val & SYMBOL_CHOICEVAL) + strcat(buf, "choiceval/"); + if (val & SYMBOL_VALID) + strcat(buf, "valid/"); + if (val & SYMBOL_OPTIONAL) + strcat(buf, "optional/"); + if (val & SYMBOL_WRITE) + strcat(buf, "write/"); + if (val & SYMBOL_CHANGED) + strcat(buf, "changed/"); + if (val & SYMBOL_AUTO) + strcat(buf, "auto/"); + + buf[strlen(buf) - 1] = '\0'; +#ifdef DEBUG + printf("%s", buf); +#endif + + return buf; +} + +const char *dbg_print_ptype(int val) +{ + static char buf[256]; + + bzero(buf, 256); + + if (val == P_UNKNOWN) + strcpy(buf, "unknown"); + if (val == P_PROMPT) + strcpy(buf, "prompt"); + if (val == P_COMMENT) + strcpy(buf, "comment"); + if (val == P_MENU) + strcpy(buf, "menu"); + if (val == P_DEFAULT) + strcpy(buf, "default"); + if (val == P_CHOICE) + strcpy(buf, "choice"); + +#ifdef DEBUG + printf("%s", buf); +#endif + + return buf; +} + + +void replace_button_icon(GladeXML * xml, GdkDrawable * window, + GtkStyle * style, gchar * btn_name, gchar ** xpm) +{ + GdkPixmap *pixmap; + GdkBitmap *mask; + GtkToolButton *button; + GtkWidget *image; + + pixmap = gdk_pixmap_create_from_xpm_d(window, &mask, + &style->bg[GTK_STATE_NORMAL], + xpm); + + button = GTK_TOOL_BUTTON(glade_xml_get_widget(xml, btn_name)); + image = gtk_image_new_from_pixmap(pixmap, mask); + gtk_widget_show(image); + gtk_tool_button_set_icon_widget(button, image); +} + +/* Main Window Initialization */ +void init_main_window(const gchar * glade_file) +{ + GladeXML *xml; + GtkWidget *widget; + GtkTextBuffer *txtbuf; + char title[256]; + GtkStyle *style; + + xml = glade_xml_new(glade_file, "window1", NULL); + if (!xml) + g_error(_("GUI loading failed !\n")); + glade_xml_signal_autoconnect(xml); + + main_wnd = glade_xml_get_widget(xml, "window1"); + hpaned = glade_xml_get_widget(xml, "hpaned1"); + vpaned = glade_xml_get_widget(xml, "vpaned1"); + tree1_w = glade_xml_get_widget(xml, "treeview1"); + tree2_w = glade_xml_get_widget(xml, "treeview2"); + text_w = glade_xml_get_widget(xml, "textview3"); + + back_btn = glade_xml_get_widget(xml, "button1"); + gtk_widget_set_sensitive(back_btn, FALSE); + + widget = glade_xml_get_widget(xml, "show_name1"); + gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget, + show_name); + + widget = glade_xml_get_widget(xml, "show_range1"); + gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget, + show_range); + + widget = glade_xml_get_widget(xml, "show_data1"); + gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget, + show_value); + + save_btn = glade_xml_get_widget(xml, "button3"); + save_menu_item = glade_xml_get_widget(xml, "save1"); + conf_set_changed_callback(conf_changed); + + style = gtk_widget_get_style(main_wnd); + widget = glade_xml_get_widget(xml, "toolbar1"); + +#if 0 /* Use stock Gtk icons instead */ + replace_button_icon(xml, main_wnd->window, style, + "button1", (gchar **) xpm_back); + replace_button_icon(xml, main_wnd->window, style, + "button2", (gchar **) xpm_load); + replace_button_icon(xml, main_wnd->window, style, + "button3", (gchar **) xpm_save); +#endif + replace_button_icon(xml, main_wnd->window, style, + "button4", (gchar **) xpm_single_view); + replace_button_icon(xml, main_wnd->window, style, + "button5", (gchar **) xpm_split_view); + replace_button_icon(xml, main_wnd->window, style, + "button6", (gchar **) xpm_tree_view); + +#if 0 + switch (view_mode) { + case SINGLE_VIEW: + widget = glade_xml_get_widget(xml, "button4"); + g_signal_emit_by_name(widget, "clicked"); + break; + case SPLIT_VIEW: + widget = glade_xml_get_widget(xml, "button5"); + g_signal_emit_by_name(widget, "clicked"); + break; + case FULL_VIEW: + widget = glade_xml_get_widget(xml, "button6"); + g_signal_emit_by_name(widget, "clicked"); + break; + } +#endif + txtbuf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w)); + tag1 = gtk_text_buffer_create_tag(txtbuf, "mytag1", + "foreground", "red", + "weight", PANGO_WEIGHT_BOLD, + NULL); + tag2 = gtk_text_buffer_create_tag(txtbuf, "mytag2", + /*"style", PANGO_STYLE_OBLIQUE, */ + NULL); + + sprintf(title, _("uClibc v%s Configuration"), + getenv("VERSION")); + gtk_window_set_title(GTK_WINDOW(main_wnd), title); + + gtk_widget_show(main_wnd); +} + +void init_tree_model(void) +{ + gint i; + + tree = tree2 = gtk_tree_store_new(COL_NUMBER, + G_TYPE_STRING, G_TYPE_STRING, + G_TYPE_STRING, G_TYPE_STRING, + G_TYPE_STRING, G_TYPE_STRING, + G_TYPE_POINTER, GDK_TYPE_COLOR, + G_TYPE_BOOLEAN, GDK_TYPE_PIXBUF, + G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, + G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, + G_TYPE_BOOLEAN); + model2 = GTK_TREE_MODEL(tree2); + + for (parents[0] = NULL, i = 1; i < 256; i++) + parents[i] = (GtkTreeIter *) g_malloc(sizeof(GtkTreeIter)); + + tree1 = gtk_tree_store_new(COL_NUMBER, + G_TYPE_STRING, G_TYPE_STRING, + G_TYPE_STRING, G_TYPE_STRING, + G_TYPE_STRING, G_TYPE_STRING, + G_TYPE_POINTER, GDK_TYPE_COLOR, + G_TYPE_BOOLEAN, GDK_TYPE_PIXBUF, + G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, + G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, + G_TYPE_BOOLEAN); + model1 = GTK_TREE_MODEL(tree1); +} + +void init_left_tree(void) +{ + GtkTreeView *view = GTK_TREE_VIEW(tree1_w); + GtkCellRenderer *renderer; + GtkTreeSelection *sel; + GtkTreeViewColumn *column; + + gtk_tree_view_set_model(view, model1); + gtk_tree_view_set_headers_visible(view, TRUE); + gtk_tree_view_set_rules_hint(view, FALSE); + + column = gtk_tree_view_column_new(); + gtk_tree_view_append_column(view, column); + gtk_tree_view_column_set_title(column, _("Options")); + + renderer = gtk_cell_renderer_toggle_new(); + gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column), + renderer, FALSE); + gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column), + renderer, + "active", COL_BTNACT, + "inconsistent", COL_BTNINC, + "visible", COL_BTNVIS, + "radio", COL_BTNRAD, NULL); + renderer = gtk_cell_renderer_text_new(); + gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column), + renderer, FALSE); + gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column), + renderer, + "text", COL_OPTION, + "foreground-gdk", + COL_COLOR, NULL); + + sel = gtk_tree_view_get_selection(view); + gtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE); + gtk_widget_realize(tree1_w); +} + +static void renderer_edited(GtkCellRendererText * cell, + const gchar * path_string, + const gchar * new_text, gpointer user_data); +static void renderer_toggled(GtkCellRendererToggle * cellrenderertoggle, + gchar * arg1, gpointer user_data); + +void init_right_tree(void) +{ + GtkTreeView *view = GTK_TREE_VIEW(tree2_w); + GtkCellRenderer *renderer; + GtkTreeSelection *sel; + GtkTreeViewColumn *column; + gint i; + + gtk_tree_view_set_model(view, model2); + gtk_tree_view_set_headers_visible(view, TRUE); + gtk_tree_view_set_rules_hint(view, FALSE); + + column = gtk_tree_view_column_new(); + gtk_tree_view_append_column(view, column); + gtk_tree_view_column_set_title(column, _("Options")); + + renderer = gtk_cell_renderer_pixbuf_new(); + gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column), + renderer, FALSE); + gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column), + renderer, + "pixbuf", COL_PIXBUF, + "visible", COL_PIXVIS, NULL); + renderer = gtk_cell_renderer_toggle_new(); + gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column), + renderer, FALSE); + gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column), + renderer, + "active", COL_BTNACT, + "inconsistent", COL_BTNINC, + "visible", COL_BTNVIS, + "radio", COL_BTNRAD, NULL); + /*g_signal_connect(G_OBJECT(renderer), "toggled", + G_CALLBACK(renderer_toggled), NULL); */ + renderer = gtk_cell_renderer_text_new(); + gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column), + renderer, FALSE); + gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column), + renderer, + "text", COL_OPTION, + "foreground-gdk", + COL_COLOR, NULL); + + renderer = gtk_cell_renderer_text_new(); + gtk_tree_view_insert_column_with_attributes(view, -1, + _("Name"), renderer, + "text", COL_NAME, + "foreground-gdk", + COL_COLOR, NULL); + renderer = gtk_cell_renderer_text_new(); + gtk_tree_view_insert_column_with_attributes(view, -1, + "N", renderer, + "text", COL_NO, + "foreground-gdk", + COL_COLOR, NULL); + renderer = gtk_cell_renderer_text_new(); + gtk_tree_view_insert_column_with_attributes(view, -1, + "M", renderer, + "text", COL_MOD, + "foreground-gdk", + COL_COLOR, NULL); + renderer = gtk_cell_renderer_text_new(); + gtk_tree_view_insert_column_with_attributes(view, -1, + "Y", renderer, + "text", COL_YES, + "foreground-gdk", + COL_COLOR, NULL); + renderer = gtk_cell_renderer_text_new(); + gtk_tree_view_insert_column_with_attributes(view, -1, + _("Value"), renderer, + "text", COL_VALUE, + "editable", + COL_EDIT, + "foreground-gdk", + COL_COLOR, NULL); + g_signal_connect(G_OBJECT(renderer), "edited", + G_CALLBACK(renderer_edited), NULL); + + column = gtk_tree_view_get_column(view, COL_NAME); + gtk_tree_view_column_set_visible(column, show_name); + column = gtk_tree_view_get_column(view, COL_NO); + gtk_tree_view_column_set_visible(column, show_range); + column = gtk_tree_view_get_column(view, COL_MOD); + gtk_tree_view_column_set_visible(column, show_range); + column = gtk_tree_view_get_column(view, COL_YES); + gtk_tree_view_column_set_visible(column, show_range); + column = gtk_tree_view_get_column(view, COL_VALUE); + gtk_tree_view_column_set_visible(column, show_value); + + if (resizeable) { + for (i = 0; i < COL_VALUE; i++) { + column = gtk_tree_view_get_column(view, i); + gtk_tree_view_column_set_resizable(column, TRUE); + } + } + + sel = gtk_tree_view_get_selection(view); + gtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE); +} + + +/* Utility Functions */ + + +static void text_insert_help(struct menu *menu) +{ + GtkTextBuffer *buffer; + GtkTextIter start, end; + const char *prompt = _(menu_get_prompt(menu)); + gchar *name; + const char *help; + + help = menu_get_help(menu); + + /* Gettextize if the help text not empty */ + if ((help != 0) && (help[0] != 0)) + help = _(help); + + if (menu->sym && menu->sym->name) + name = g_strdup_printf(menu->sym->name); + else + name = g_strdup(""); + + buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w)); + gtk_text_buffer_get_bounds(buffer, &start, &end); + gtk_text_buffer_delete(buffer, &start, &end); + gtk_text_view_set_left_margin(GTK_TEXT_VIEW(text_w), 15); + + gtk_text_buffer_get_end_iter(buffer, &end); + gtk_text_buffer_insert_with_tags(buffer, &end, prompt, -1, tag1, + NULL); + gtk_text_buffer_insert_at_cursor(buffer, " ", 1); + gtk_text_buffer_get_end_iter(buffer, &end); + gtk_text_buffer_insert_with_tags(buffer, &end, name, -1, tag1, + NULL); + gtk_text_buffer_insert_at_cursor(buffer, "\n\n", 2); + gtk_text_buffer_get_end_iter(buffer, &end); + gtk_text_buffer_insert_with_tags(buffer, &end, help, -1, tag2, + NULL); +} + + +static void text_insert_msg(const char *title, const char *message) +{ + GtkTextBuffer *buffer; + GtkTextIter start, end; + const char *msg = message; + + buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w)); + gtk_text_buffer_get_bounds(buffer, &start, &end); + gtk_text_buffer_delete(buffer, &start, &end); + gtk_text_view_set_left_margin(GTK_TEXT_VIEW(text_w), 15); + + gtk_text_buffer_get_end_iter(buffer, &end); + gtk_text_buffer_insert_with_tags(buffer, &end, title, -1, tag1, + NULL); + gtk_text_buffer_insert_at_cursor(buffer, "\n\n", 2); + gtk_text_buffer_get_end_iter(buffer, &end); + gtk_text_buffer_insert_with_tags(buffer, &end, msg, -1, tag2, + NULL); +} + + +/* Main Windows Callbacks */ + +void on_save_activate(GtkMenuItem * menuitem, gpointer user_data); +gboolean on_window1_delete_event(GtkWidget * widget, GdkEvent * event, + gpointer user_data) +{ + GtkWidget *dialog, *label; + gint result; + + if (!conf_get_changed()) + return FALSE; + + dialog = gtk_dialog_new_with_buttons(_("Warning !"), + GTK_WINDOW(main_wnd), + (GtkDialogFlags) + (GTK_DIALOG_MODAL | + GTK_DIALOG_DESTROY_WITH_PARENT), + GTK_STOCK_OK, + GTK_RESPONSE_YES, + GTK_STOCK_NO, + GTK_RESPONSE_NO, + GTK_STOCK_CANCEL, + GTK_RESPONSE_CANCEL, NULL); + gtk_dialog_set_default_response(GTK_DIALOG(dialog), + GTK_RESPONSE_CANCEL); + + label = gtk_label_new(_("\nSave configuration ?\n")); + gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), label); + gtk_widget_show(label); + + result = gtk_dialog_run(GTK_DIALOG(dialog)); + switch (result) { + case GTK_RESPONSE_YES: + on_save_activate(NULL, NULL); + return FALSE; + case GTK_RESPONSE_NO: + return FALSE; + case GTK_RESPONSE_CANCEL: + case GTK_RESPONSE_DELETE_EVENT: + default: + gtk_widget_destroy(dialog); + return TRUE; + } + + return FALSE; +} + + +void on_window1_destroy(GtkObject * object, gpointer user_data) +{ + gtk_main_quit(); +} + + +void +on_window1_size_request(GtkWidget * widget, + GtkRequisition * requisition, gpointer user_data) +{ + static gint old_h; + gint w, h; + + if (widget->window == NULL) + gtk_window_get_default_size(GTK_WINDOW(main_wnd), &w, &h); + else + gdk_window_get_size(widget->window, &w, &h); + + if (h == old_h) + return; + old_h = h; + + gtk_paned_set_position(GTK_PANED(vpaned), 2 * h / 3); +} + + +/* Menu & Toolbar Callbacks */ + + +static void +load_filename(GtkFileSelection * file_selector, gpointer user_data) +{ + const gchar *fn; + + fn = gtk_file_selection_get_filename(GTK_FILE_SELECTION + (user_data)); + + if (conf_read(fn)) + text_insert_msg(_("Error"), _("Unable to load configuration !")); + else + display_tree(&rootmenu); +} + +void on_load1_activate(GtkMenuItem * menuitem, gpointer user_data) +{ + GtkWidget *fs; + + fs = gtk_file_selection_new(_("Load file...")); + g_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(fs)->ok_button), + "clicked", + G_CALLBACK(load_filename), (gpointer) fs); + g_signal_connect_swapped(GTK_OBJECT + (GTK_FILE_SELECTION(fs)->ok_button), + "clicked", G_CALLBACK(gtk_widget_destroy), + (gpointer) fs); + g_signal_connect_swapped(GTK_OBJECT + (GTK_FILE_SELECTION(fs)->cancel_button), + "clicked", G_CALLBACK(gtk_widget_destroy), + (gpointer) fs); + gtk_widget_show(fs); +} + + +void on_save_activate(GtkMenuItem * menuitem, gpointer user_data) +{ + if (conf_write(NULL)) + text_insert_msg(_("Error"), _("Unable to save configuration !")); +} + + +static void +store_filename(GtkFileSelection * file_selector, gpointer user_data) +{ + const gchar *fn; + + fn = gtk_file_selection_get_filename(GTK_FILE_SELECTION + (user_data)); + + if (conf_write(fn)) + text_insert_msg(_("Error"), _("Unable to save configuration !")); + + gtk_widget_destroy(GTK_WIDGET(user_data)); +} + +void on_save_as1_activate(GtkMenuItem * menuitem, gpointer user_data) +{ + GtkWidget *fs; + + fs = gtk_file_selection_new(_("Save file as...")); + g_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(fs)->ok_button), + "clicked", + G_CALLBACK(store_filename), (gpointer) fs); + g_signal_connect_swapped(GTK_OBJECT + (GTK_FILE_SELECTION(fs)->ok_button), + "clicked", G_CALLBACK(gtk_widget_destroy), + (gpointer) fs); + g_signal_connect_swapped(GTK_OBJECT + (GTK_FILE_SELECTION(fs)->cancel_button), + "clicked", G_CALLBACK(gtk_widget_destroy), + (gpointer) fs); + gtk_widget_show(fs); +} + + +void on_quit1_activate(GtkMenuItem * menuitem, gpointer user_data) +{ + if (!on_window1_delete_event(NULL, NULL, NULL)) + gtk_widget_destroy(GTK_WIDGET(main_wnd)); +} + + +void on_show_name1_activate(GtkMenuItem * menuitem, gpointer user_data) +{ + GtkTreeViewColumn *col; + + show_name = GTK_CHECK_MENU_ITEM(menuitem)->active; + col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_NAME); + if (col) + gtk_tree_view_column_set_visible(col, show_name); +} + + +void on_show_range1_activate(GtkMenuItem * menuitem, gpointer user_data) +{ + GtkTreeViewColumn *col; + + show_range = GTK_CHECK_MENU_ITEM(menuitem)->active; + col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_NO); + if (col) + gtk_tree_view_column_set_visible(col, show_range); + col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_MOD); + if (col) + gtk_tree_view_column_set_visible(col, show_range); + col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_YES); + if (col) + gtk_tree_view_column_set_visible(col, show_range); + +} + + +void on_show_data1_activate(GtkMenuItem * menuitem, gpointer user_data) +{ + GtkTreeViewColumn *col; + + show_value = GTK_CHECK_MENU_ITEM(menuitem)->active; + col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_VALUE); + if (col) + gtk_tree_view_column_set_visible(col, show_value); +} + + +void +on_show_all_options1_activate(GtkMenuItem * menuitem, gpointer user_data) +{ + show_all = GTK_CHECK_MENU_ITEM(menuitem)->active; + + gtk_tree_store_clear(tree2); + display_tree(&rootmenu); // instead of update_tree to speed-up +} + + +void +on_show_debug_info1_activate(GtkMenuItem * menuitem, gpointer user_data) +{ + show_debug = GTK_CHECK_MENU_ITEM(menuitem)->active; + update_tree(&rootmenu, NULL); +} + + +void on_introduction1_activate(GtkMenuItem * menuitem, gpointer user_data) +{ + GtkWidget *dialog; + const gchar *intro_text = _( + "Welcome to gkc, the GTK+ graphical configuration tool\n" + "for uClibc.\n" + "For each option, a blank box indicates the feature is disabled, a\n" + "check indicates it is enabled, and a dot indicates that it is to\n" + "be compiled as a module. Clicking on the box will cycle through the three states.\n" + "\n" + "If you do not see an option (e.g., a device driver) that you\n" + "believe should be present, try turning on Show All Options\n" + "under the Options menu.\n" + "Although there is no cross reference yet to help you figure out\n" + "what other options must be enabled to support the option you\n" + "are interested in, you can still view the help of a grayed-out\n" + "option.\n" + "\n" + "Toggling Show Debug Info under the Options menu will show \n" + "the dependencies, which you can then match by examining other options."); + + dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_INFO, + GTK_BUTTONS_CLOSE, intro_text); + g_signal_connect_swapped(GTK_OBJECT(dialog), "response", + G_CALLBACK(gtk_widget_destroy), + GTK_OBJECT(dialog)); + gtk_widget_show_all(dialog); +} + + +void on_about1_activate(GtkMenuItem * menuitem, gpointer user_data) +{ + GtkWidget *dialog; + const gchar *about_text = + _("gkc is copyright (c) 2002 Romain Lievin .\n" + "Based on the source code from Roman Zippel.\n"); + + dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_INFO, + GTK_BUTTONS_CLOSE, about_text); + g_signal_connect_swapped(GTK_OBJECT(dialog), "response", + G_CALLBACK(gtk_widget_destroy), + GTK_OBJECT(dialog)); + gtk_widget_show_all(dialog); +} + + +void on_license1_activate(GtkMenuItem * menuitem, gpointer user_data) +{ + GtkWidget *dialog; + const gchar *license_text = + _("gkc is released under the terms of the GNU GPL v2.\n" + "For more information, please see the source code or\n" + "visit http://www.fsf.org/licenses/licenses.html\n"); + + dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_INFO, + GTK_BUTTONS_CLOSE, license_text); + g_signal_connect_swapped(GTK_OBJECT(dialog), "response", + G_CALLBACK(gtk_widget_destroy), + GTK_OBJECT(dialog)); + gtk_widget_show_all(dialog); +} + + +void on_back_clicked(GtkButton * button, gpointer user_data) +{ + enum prop_type ptype; + + current = current->parent; + ptype = current->prompt ? current->prompt->type : P_UNKNOWN; + if (ptype != P_MENU) + current = current->parent; + display_tree_part(); + + if (current == &rootmenu) + gtk_widget_set_sensitive(back_btn, FALSE); +} + + +void on_load_clicked(GtkButton * button, gpointer user_data) +{ + on_load1_activate(NULL, user_data); +} + + +void on_single_clicked(GtkButton * button, gpointer user_data) +{ + view_mode = SINGLE_VIEW; + gtk_paned_set_position(GTK_PANED(hpaned), 0); + gtk_widget_hide(tree1_w); + current = &rootmenu; + display_tree_part(); +} + + +void on_split_clicked(GtkButton * button, gpointer user_data) +{ + gint w, h; + view_mode = SPLIT_VIEW; + gtk_widget_show(tree1_w); + gtk_window_get_default_size(GTK_WINDOW(main_wnd), &w, &h); + gtk_paned_set_position(GTK_PANED(hpaned), w / 2); + if (tree2) + gtk_tree_store_clear(tree2); + display_list(); + + /* Disable back btn, like in full mode. */ + gtk_widget_set_sensitive(back_btn, FALSE); +} + + +void on_full_clicked(GtkButton * button, gpointer user_data) +{ + view_mode = FULL_VIEW; + gtk_paned_set_position(GTK_PANED(hpaned), 0); + gtk_widget_hide(tree1_w); + if (tree2) + gtk_tree_store_clear(tree2); + display_tree(&rootmenu); + gtk_widget_set_sensitive(back_btn, FALSE); +} + + +void on_collapse_clicked(GtkButton * button, gpointer user_data) +{ + gtk_tree_view_collapse_all(GTK_TREE_VIEW(tree2_w)); +} + + +void on_expand_clicked(GtkButton * button, gpointer user_data) +{ + gtk_tree_view_expand_all(GTK_TREE_VIEW(tree2_w)); +} + + +/* CTree Callbacks */ + +/* Change hex/int/string value in the cell */ +static void renderer_edited(GtkCellRendererText * cell, + const gchar * path_string, + const gchar * new_text, gpointer user_data) +{ + GtkTreePath *path = gtk_tree_path_new_from_string(path_string); + GtkTreeIter iter; + const char *old_def, *new_def; + struct menu *menu; + struct symbol *sym; + + if (!gtk_tree_model_get_iter(model2, &iter, path)) + return; + + gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1); + sym = menu->sym; + + gtk_tree_model_get(model2, &iter, COL_VALUE, &old_def, -1); + new_def = new_text; + + sym_set_string_value(sym, new_def); + + update_tree(&rootmenu, NULL); + + gtk_tree_path_free(path); +} + +/* Change the value of a symbol and update the tree */ +static void change_sym_value(struct menu *menu, gint col) +{ + struct symbol *sym = menu->sym; + tristate oldval, newval; + + if (!sym) + return; + + if (col == COL_NO) + newval = no; + else if (col == COL_MOD) + newval = mod; + else if (col == COL_YES) + newval = yes; + else + return; + + switch (sym_get_type(sym)) { + case S_BOOLEAN: + case S_TRISTATE: + oldval = sym_get_tristate_value(sym); + if (!sym_tristate_within_range(sym, newval)) + newval = yes; + sym_set_tristate_value(sym, newval); + if (view_mode == FULL_VIEW) + update_tree(&rootmenu, NULL); + else if (view_mode == SPLIT_VIEW) { + update_tree(browsed, NULL); + display_list(); + } + else if (view_mode == SINGLE_VIEW) + display_tree_part(); //fixme: keep exp/coll + break; + case S_INT: + case S_HEX: + case S_STRING: + default: + break; + } +} + +static void toggle_sym_value(struct menu *menu) +{ + if (!menu->sym) + return; + + sym_toggle_tristate_value(menu->sym); + if (view_mode == FULL_VIEW) + update_tree(&rootmenu, NULL); + else if (view_mode == SPLIT_VIEW) { + update_tree(browsed, NULL); + display_list(); + } + else if (view_mode == SINGLE_VIEW) + display_tree_part(); //fixme: keep exp/coll +} + +static void renderer_toggled(GtkCellRendererToggle * cell, + gchar * path_string, gpointer user_data) +{ + GtkTreePath *path, *sel_path = NULL; + GtkTreeIter iter, sel_iter; + GtkTreeSelection *sel; + struct menu *menu; + + path = gtk_tree_path_new_from_string(path_string); + if (!gtk_tree_model_get_iter(model2, &iter, path)) + return; + + sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree2_w)); + if (gtk_tree_selection_get_selected(sel, NULL, &sel_iter)) + sel_path = gtk_tree_model_get_path(model2, &sel_iter); + if (!sel_path) + goto out1; + if (gtk_tree_path_compare(path, sel_path)) + goto out2; + + gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1); + toggle_sym_value(menu); + + out2: + gtk_tree_path_free(sel_path); + out1: + gtk_tree_path_free(path); +} + +static gint column2index(GtkTreeViewColumn * column) +{ + gint i; + + for (i = 0; i < COL_NUMBER; i++) { + GtkTreeViewColumn *col; + + col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), i); + if (col == column) + return i; + } + + return -1; +} + + +/* User click: update choice (full) or goes down (single) */ +gboolean +on_treeview2_button_press_event(GtkWidget * widget, + GdkEventButton * event, gpointer user_data) +{ + GtkTreeView *view = GTK_TREE_VIEW(widget); + GtkTreePath *path; + GtkTreeViewColumn *column; + GtkTreeIter iter; + struct menu *menu; + gint col; + +#if GTK_CHECK_VERSION(2,1,4) // bug in ctree with earlier version of GTK + gint tx = (gint) event->x; + gint ty = (gint) event->y; + gint cx, cy; + + gtk_tree_view_get_path_at_pos(view, tx, ty, &path, &column, &cx, + &cy); +#else + gtk_tree_view_get_cursor(view, &path, &column); +#endif + if (path == NULL) + return FALSE; + + if (!gtk_tree_model_get_iter(model2, &iter, path)) + return FALSE; + gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1); + + col = column2index(column); + if (event->type == GDK_2BUTTON_PRESS) { + enum prop_type ptype; + ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN; + + if (ptype == P_MENU && view_mode != FULL_VIEW && col == COL_OPTION) { + // goes down into menu + current = menu; + display_tree_part(); + gtk_widget_set_sensitive(back_btn, TRUE); + } else if ((col == COL_OPTION)) { + toggle_sym_value(menu); + gtk_tree_view_expand_row(view, path, TRUE); + } + } else { + if (col == COL_VALUE) { + toggle_sym_value(menu); + gtk_tree_view_expand_row(view, path, TRUE); + } else if (col == COL_NO || col == COL_MOD + || col == COL_YES) { + change_sym_value(menu, col); + gtk_tree_view_expand_row(view, path, TRUE); + } + } + + return FALSE; +} + +/* Key pressed: update choice */ +gboolean +on_treeview2_key_press_event(GtkWidget * widget, + GdkEventKey * event, gpointer user_data) +{ + GtkTreeView *view = GTK_TREE_VIEW(widget); + GtkTreePath *path; + GtkTreeViewColumn *column; + GtkTreeIter iter; + struct menu *menu; + gint col; + + gtk_tree_view_get_cursor(view, &path, &column); + if (path == NULL) + return FALSE; + + if (event->keyval == GDK_space) { + if (gtk_tree_view_row_expanded(view, path)) + gtk_tree_view_collapse_row(view, path); + else + gtk_tree_view_expand_row(view, path, FALSE); + return TRUE; + } + if (event->keyval == GDK_KP_Enter) { + } + if (widget == tree1_w) + return FALSE; + + gtk_tree_model_get_iter(model2, &iter, path); + gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1); + + if (!strcasecmp(event->string, "n")) + col = COL_NO; + else if (!strcasecmp(event->string, "m")) + col = COL_MOD; + else if (!strcasecmp(event->string, "y")) + col = COL_YES; + else + col = -1; + change_sym_value(menu, col); + + return FALSE; +} + + +/* Row selection changed: update help */ +void +on_treeview2_cursor_changed(GtkTreeView * treeview, gpointer user_data) +{ + GtkTreeSelection *selection; + GtkTreeIter iter; + struct menu *menu; + + selection = gtk_tree_view_get_selection(treeview); + if (gtk_tree_selection_get_selected(selection, &model2, &iter)) { + gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1); + text_insert_help(menu); + } +} + + +/* User click: display sub-tree in the right frame. */ +gboolean +on_treeview1_button_press_event(GtkWidget * widget, + GdkEventButton * event, gpointer user_data) +{ + GtkTreeView *view = GTK_TREE_VIEW(widget); + GtkTreePath *path; + GtkTreeViewColumn *column; + GtkTreeIter iter; + struct menu *menu; + + gint tx = (gint) event->x; + gint ty = (gint) event->y; + gint cx, cy; + + gtk_tree_view_get_path_at_pos(view, tx, ty, &path, &column, &cx, + &cy); + if (path == NULL) + return FALSE; + + gtk_tree_model_get_iter(model1, &iter, path); + gtk_tree_model_get(model1, &iter, COL_MENU, &menu, -1); + + if (event->type == GDK_2BUTTON_PRESS) { + toggle_sym_value(menu); + current = menu; + display_tree_part(); + } else { + browsed = menu; + display_tree_part(); + } + + gtk_widget_realize(tree2_w); + gtk_tree_view_set_cursor(view, path, NULL, FALSE); + gtk_widget_grab_focus(tree2_w); + + return FALSE; +} + + +/* Fill a row of strings */ +static gchar **fill_row(struct menu *menu) +{ + static gchar *row[COL_NUMBER]; + struct symbol *sym = menu->sym; + const char *def; + int stype; + tristate val; + enum prop_type ptype; + int i; + + for (i = COL_OPTION; i <= COL_COLOR; i++) + g_free(row[i]); + bzero(row, sizeof(row)); + + row[COL_OPTION] = + g_strdup_printf("%s %s", _(menu_get_prompt(menu)), + sym && sym_has_value(sym) ? "(NEW)" : ""); + + if (show_all && !menu_is_visible(menu)) + row[COL_COLOR] = g_strdup("DarkGray"); + else + row[COL_COLOR] = g_strdup("Black"); + + ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN; + switch (ptype) { + case P_MENU: + row[COL_PIXBUF] = (gchar *) xpm_menu; + if (view_mode == SINGLE_VIEW) + row[COL_PIXVIS] = GINT_TO_POINTER(TRUE); + row[COL_BTNVIS] = GINT_TO_POINTER(FALSE); + break; + case P_COMMENT: + row[COL_PIXBUF] = (gchar *) xpm_void; + row[COL_PIXVIS] = GINT_TO_POINTER(FALSE); + row[COL_BTNVIS] = GINT_TO_POINTER(FALSE); + break; + default: + row[COL_PIXBUF] = (gchar *) xpm_void; + row[COL_PIXVIS] = GINT_TO_POINTER(FALSE); + row[COL_BTNVIS] = GINT_TO_POINTER(TRUE); + break; + } + + if (!sym) + return row; + row[COL_NAME] = g_strdup(sym->name); + + sym_calc_value(sym); + sym->flags &= ~SYMBOL_CHANGED; + + if (sym_is_choice(sym)) { // parse childs for getting final value + struct menu *child; + struct symbol *def_sym = sym_get_choice_value(sym); + struct menu *def_menu = NULL; + + row[COL_BTNVIS] = GINT_TO_POINTER(FALSE); + + for (child = menu->list; child; child = child->next) { + if (menu_is_visible(child) + && child->sym == def_sym) + def_menu = child; + } + + if (def_menu) + row[COL_VALUE] = + g_strdup(_(menu_get_prompt(def_menu))); + } + if (sym->flags & SYMBOL_CHOICEVAL) + row[COL_BTNRAD] = GINT_TO_POINTER(TRUE); + + stype = sym_get_type(sym); + switch (stype) { + case S_BOOLEAN: + if (GPOINTER_TO_INT(row[COL_PIXVIS]) == FALSE) + row[COL_BTNVIS] = GINT_TO_POINTER(TRUE); + if (sym_is_choice(sym)) + break; + case S_TRISTATE: + val = sym_get_tristate_value(sym); + switch (val) { + case no: + row[COL_NO] = g_strdup("N"); + row[COL_VALUE] = g_strdup("N"); + row[COL_BTNACT] = GINT_TO_POINTER(FALSE); + row[COL_BTNINC] = GINT_TO_POINTER(FALSE); + break; + case mod: + row[COL_MOD] = g_strdup("M"); + row[COL_VALUE] = g_strdup("M"); + row[COL_BTNINC] = GINT_TO_POINTER(TRUE); + break; + case yes: + row[COL_YES] = g_strdup("Y"); + row[COL_VALUE] = g_strdup("Y"); + row[COL_BTNACT] = GINT_TO_POINTER(TRUE); + row[COL_BTNINC] = GINT_TO_POINTER(FALSE); + break; + } + + if (val != no && sym_tristate_within_range(sym, no)) + row[COL_NO] = g_strdup("_"); + if (val != mod && sym_tristate_within_range(sym, mod)) + row[COL_MOD] = g_strdup("_"); + if (val != yes && sym_tristate_within_range(sym, yes)) + row[COL_YES] = g_strdup("_"); + break; + case S_INT: + case S_HEX: + case S_STRING: + def = sym_get_string_value(sym); + row[COL_VALUE] = g_strdup(def); + row[COL_EDIT] = GINT_TO_POINTER(TRUE); + row[COL_BTNVIS] = GINT_TO_POINTER(FALSE); + break; + } + + return row; +} + + +/* Set the node content with a row of strings */ +static void set_node(GtkTreeIter * node, struct menu *menu, gchar ** row) +{ + GdkColor color; + gboolean success; + GdkPixbuf *pix; + + pix = gdk_pixbuf_new_from_xpm_data((const char **) + row[COL_PIXBUF]); + + gdk_color_parse(row[COL_COLOR], &color); + gdk_colormap_alloc_colors(gdk_colormap_get_system(), &color, 1, + FALSE, FALSE, &success); + + gtk_tree_store_set(tree, node, + COL_OPTION, row[COL_OPTION], + COL_NAME, row[COL_NAME], + COL_NO, row[COL_NO], + COL_MOD, row[COL_MOD], + COL_YES, row[COL_YES], + COL_VALUE, row[COL_VALUE], + COL_MENU, (gpointer) menu, + COL_COLOR, &color, + COL_EDIT, GPOINTER_TO_INT(row[COL_EDIT]), + COL_PIXBUF, pix, + COL_PIXVIS, GPOINTER_TO_INT(row[COL_PIXVIS]), + COL_BTNVIS, GPOINTER_TO_INT(row[COL_BTNVIS]), + COL_BTNACT, GPOINTER_TO_INT(row[COL_BTNACT]), + COL_BTNINC, GPOINTER_TO_INT(row[COL_BTNINC]), + COL_BTNRAD, GPOINTER_TO_INT(row[COL_BTNRAD]), + -1); + + g_object_unref(pix); +} + + +/* Add a node to the tree */ +static void place_node(struct menu *menu, char **row) +{ + GtkTreeIter *parent = parents[indent - 1]; + GtkTreeIter *node = parents[indent]; + + gtk_tree_store_append(tree, node, parent); + set_node(node, menu, row); +} + + +/* Find a node in the GTK+ tree */ +static GtkTreeIter found; + +/* + * Find a menu in the GtkTree starting at parent. + */ +GtkTreeIter *gtktree_iter_find_node(GtkTreeIter * parent, + struct menu *tofind) +{ + GtkTreeIter iter; + GtkTreeIter *child = &iter; + gboolean valid; + GtkTreeIter *ret; + + valid = gtk_tree_model_iter_children(model2, child, parent); + while (valid) { + struct menu *menu; + + gtk_tree_model_get(model2, child, 6, &menu, -1); + + if (menu == tofind) { + memcpy(&found, child, sizeof(GtkTreeIter)); + return &found; + } + + ret = gtktree_iter_find_node(child, tofind); + if (ret) + return ret; + + valid = gtk_tree_model_iter_next(model2, child); + } + + return NULL; +} + + +/* + * Update the tree by adding/removing entries + * Does not change other nodes + */ +static void update_tree(struct menu *src, GtkTreeIter * dst) +{ + struct menu *child1; + GtkTreeIter iter, tmp; + GtkTreeIter *child2 = &iter; + gboolean valid; + GtkTreeIter *sibling; + struct symbol *sym; + struct property *prop; + struct menu *menu1, *menu2; + + if (src == &rootmenu) + indent = 1; + + valid = gtk_tree_model_iter_children(model2, child2, dst); + for (child1 = src->list; child1; child1 = child1->next) { + + prop = child1->prompt; + sym = child1->sym; + + reparse: + menu1 = child1; + if (valid) + gtk_tree_model_get(model2, child2, COL_MENU, + &menu2, -1); + else + menu2 = NULL; // force adding of a first child + +#ifdef DEBUG + printf("%*c%s | %s\n", indent, ' ', + menu1 ? menu_get_prompt(menu1) : "nil", + menu2 ? menu_get_prompt(menu2) : "nil"); +#endif + + if (!menu_is_visible(child1) && !show_all) { // remove node + if (gtktree_iter_find_node(dst, menu1) != NULL) { + memcpy(&tmp, child2, sizeof(GtkTreeIter)); + valid = gtk_tree_model_iter_next(model2, + child2); + gtk_tree_store_remove(tree2, &tmp); + if (!valid) + return; // next parent + else + goto reparse; // next child + } else + continue; + } + + if (menu1 != menu2) { + if (gtktree_iter_find_node(dst, menu1) == NULL) { // add node + if (!valid && !menu2) + sibling = NULL; + else + sibling = child2; + gtk_tree_store_insert_before(tree2, + child2, + dst, sibling); + set_node(child2, menu1, fill_row(menu1)); + if (menu2 == NULL) + valid = TRUE; + } else { // remove node + memcpy(&tmp, child2, sizeof(GtkTreeIter)); + valid = gtk_tree_model_iter_next(model2, + child2); + gtk_tree_store_remove(tree2, &tmp); + if (!valid) + return; // next parent + else + goto reparse; // next child + } + } else if (sym && (sym->flags & SYMBOL_CHANGED)) { + set_node(child2, menu1, fill_row(menu1)); + } + + indent++; + update_tree(child1, child2); + indent--; + + valid = gtk_tree_model_iter_next(model2, child2); + } +} + + +/* Display the whole tree (single/split/full view) */ +static void display_tree(struct menu *menu) +{ + struct symbol *sym; + struct property *prop; + struct menu *child; + enum prop_type ptype; + + if (menu == &rootmenu) { + indent = 1; + current = &rootmenu; + } + + for (child = menu->list; child; child = child->next) { + prop = child->prompt; + sym = child->sym; + ptype = prop ? prop->type : P_UNKNOWN; + + if (sym) + sym->flags &= ~SYMBOL_CHANGED; + + if ((view_mode == SPLIT_VIEW) + && !(child->flags & MENU_ROOT) && (tree == tree1)) + continue; + + if ((view_mode == SPLIT_VIEW) && (child->flags & MENU_ROOT) + && (tree == tree2)) + continue; + + if (menu_is_visible(child) || show_all) + place_node(child, fill_row(child)); +#ifdef DEBUG + printf("%*c%s: ", indent, ' ', menu_get_prompt(child)); + printf("%s", child->flags & MENU_ROOT ? "rootmenu | " : ""); + dbg_print_ptype(ptype); + printf(" | "); + if (sym) { + dbg_print_stype(sym->type); + printf(" | "); + dbg_print_flags(sym->flags); + printf("\n"); + } else + printf("\n"); +#endif + if ((view_mode != FULL_VIEW) && (ptype == P_MENU) + && (tree == tree2)) + continue; +/* + if (((menu != &rootmenu) && !(menu->flags & MENU_ROOT)) + || (view_mode == FULL_VIEW) + || (view_mode == SPLIT_VIEW))*/ + if (((view_mode == SINGLE_VIEW) && (menu->flags & MENU_ROOT)) + || (view_mode == FULL_VIEW) + || (view_mode == SPLIT_VIEW)) { + indent++; + display_tree(child); + indent--; + } + } +} + +/* Display a part of the tree starting at current node (single/split view) */ +static void display_tree_part(void) +{ + if (tree2) + gtk_tree_store_clear(tree2); + if (view_mode == SINGLE_VIEW) + display_tree(current); + else if (view_mode == SPLIT_VIEW) + display_tree(browsed); + gtk_tree_view_expand_all(GTK_TREE_VIEW(tree2_w)); +} + +/* Display the list in the left frame (split view) */ +static void display_list(void) +{ + if (tree1) + gtk_tree_store_clear(tree1); + + tree = tree1; + display_tree(&rootmenu); + gtk_tree_view_expand_all(GTK_TREE_VIEW(tree1_w)); + tree = tree2; +} + +void fixup_rootmenu(struct menu *menu) +{ + struct menu *child; + static int menu_cnt = 0; + + menu->flags |= MENU_ROOT; + for (child = menu->list; child; child = child->next) { + if (child->prompt && child->prompt->type == P_MENU) { + menu_cnt++; + fixup_rootmenu(child); + menu_cnt--; + } else if (!menu_cnt) + fixup_rootmenu(child); + } +} + + +/* Main */ +int main(int ac, char *av[]) +{ + const char *name; + char *env; + gchar *glade_file; + +#ifndef LKC_DIRECT_LINK + kconfig_load(); +#endif + + bindtextdomain(PACKAGE, LOCALEDIR); + bind_textdomain_codeset(PACKAGE, "UTF-8"); + textdomain(PACKAGE); + + /* GTK stuffs */ + gtk_set_locale(); + gtk_init(&ac, &av); + glade_init(); + + //add_pixmap_directory (PACKAGE_DATA_DIR "/" PACKAGE "/pixmaps"); + //add_pixmap_directory (PACKAGE_SOURCE_DIR "/pixmaps"); + + /* Determine GUI path */ + env = getenv(SRCTREE); + if (env) + glade_file = g_strconcat(env, "/scripts/kconfig/gconf.glade", NULL); + else if (av[0][0] == '/') + glade_file = g_strconcat(av[0], ".glade", NULL); + else + glade_file = g_strconcat(g_get_current_dir(), "/", av[0], ".glade", NULL); + + /* Load the interface and connect signals */ + init_main_window(glade_file); + init_tree_model(); + init_left_tree(); + init_right_tree(); + + /* Conf stuffs */ + if (ac > 1 && av[1][0] == '-') { + switch (av[1][1]) { + case 'a': + //showAll = 1; + break; + case 'h': + case '?': + printf("%s \n", av[0]); + exit(0); + } + name = av[2]; + } else + name = av[1]; + + conf_parse(name); + fixup_rootmenu(&rootmenu); + conf_read(NULL); + + switch (view_mode) { + case SINGLE_VIEW: + display_tree_part(); + break; + case SPLIT_VIEW: + display_list(); + break; + case FULL_VIEW: + display_tree(&rootmenu); + break; + } + + gtk_main(); + + return 0; +} + +static void conf_changed(void) +{ + bool changed = conf_get_changed(); + gtk_widget_set_sensitive(save_btn, changed); + gtk_widget_set_sensitive(save_menu_item, changed); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/gconf.glade b/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/gconf.glade new file mode 100644 index 00000000..2e2e2f9d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/gconf.glade @@ -0,0 +1,648 @@ + + + + + + + True + Gtk uClibc Configurator + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_NONE + False + 640 + 480 + True + False + True + False + False + GDK_WINDOW_TYPE_HINT_NORMAL + GDK_GRAVITY_NORTH_WEST + + + + + + + True + False + 0 + + + + True + + + + True + _File + True + + + + + + + True + Load a config file + _Load + True + + + + + + True + gtk-open + 1 + 0.5 + 0.5 + 0 + 0 + + + + + + + + True + Save the config in .config + _Save + True + + + + + + True + gtk-save + 1 + 0.5 + 0.5 + 0 + 0 + + + + + + + + True + Save the config in a file + Save _as + True + + + + + True + gtk-save-as + 1 + 0.5 + 0.5 + 0 + 0 + + + + + + + + True + + + + + + True + _Quit + True + + + + + + True + gtk-quit + 1 + 0.5 + 0.5 + 0 + 0 + + + + + + + + + + + + True + _Options + True + + + + + + + True + Show name + Show _name + True + False + + + + + + + True + Show range (Y/M/N) + Show _range + True + False + + + + + + + True + Show value of the option + Show _data + True + False + + + + + + + True + + + + + + True + Show all options + Show all _options + True + False + + + + + + + True + Show masked options + Show _debug info + True + False + + + + + + + + + + + True + _Help + True + + + + + + + True + _Introduction + True + + + + + + True + gtk-dialog-question + 1 + 0.5 + 0.5 + 0 + 0 + + + + + + + + True + _About + True + + + + + + True + gtk-properties + 1 + 0.5 + 0.5 + 0 + 0 + + + + + + + + True + _License + True + + + + + True + gtk-justify-fill + 1 + 0.5 + 0.5 + 0 + 0 + + + + + + + + + + + 0 + False + False + + + + + + True + GTK_SHADOW_OUT + GTK_POS_LEFT + GTK_POS_TOP + + + + True + GTK_ORIENTATION_HORIZONTAL + GTK_TOOLBAR_BOTH + True + True + + + + True + Goes up of one level (single view) + Back + True + gtk-undo + True + True + False + + + + False + True + + + + + + True + True + True + False + + + + True + + + + + False + False + + + + + + True + Load a config file + Load + True + gtk-open + True + True + False + + + + False + True + + + + + + True + Save a config file + Save + True + gtk-save + True + True + False + + + + False + True + + + + + + True + True + True + False + + + + True + + + + + False + False + + + + + + True + Single view + Single + True + gtk-missing-image + True + True + False + + + + False + True + + + + + + True + Split view + Split + True + gtk-missing-image + True + True + False + + + + False + True + + + + + + True + Full view + Full + True + gtk-missing-image + True + True + False + + + + False + True + + + + + + True + True + True + False + + + + True + + + + + False + False + + + + + + True + Collapse the whole tree in the right frame + Collapse + True + gtk-remove + True + True + False + + + + False + True + + + + + + True + Expand the whole tree in the right frame + Expand + True + gtk-add + True + True + False + + + + False + True + + + + + + + 0 + False + False + + + + + + 1 + True + True + 0 + + + + True + GTK_POLICY_AUTOMATIC + GTK_POLICY_AUTOMATIC + GTK_SHADOW_IN + GTK_CORNER_TOP_LEFT + + + + True + True + True + False + False + True + + + + + + + + True + False + + + + + + True + True + 0 + + + + True + GTK_POLICY_AUTOMATIC + GTK_POLICY_AUTOMATIC + GTK_SHADOW_IN + GTK_CORNER_TOP_LEFT + + + + True + True + True + True + False + False + True + + + + + + + + True + False + + + + + + True + GTK_POLICY_NEVER + GTK_POLICY_AUTOMATIC + GTK_SHADOW_IN + GTK_CORNER_TOP_LEFT + + + + True + True + False + False + True + GTK_JUSTIFY_LEFT + GTK_WRAP_WORD + True + 0 + 0 + 0 + 0 + 0 + 0 + Sorry, no help available for this option yet. + + + + + True + True + + + + + True + True + + + + + 0 + True + True + + + + + + + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/images.c b/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/images.c new file mode 100644 index 00000000..d4f84bd4 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/images.c @@ -0,0 +1,326 @@ +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +static const char *xpm_load[] = { +"22 22 5 1", +". c None", +"# c #000000", +"c c #838100", +"a c #ffff00", +"b c #ffffff", +"......................", +"......................", +"......................", +"............####....#.", +"...........#....##.##.", +"..................###.", +".................####.", +".####...........#####.", +"#abab##########.......", +"#babababababab#.......", +"#ababababababa#.......", +"#babababababab#.......", +"#ababab###############", +"#babab##cccccccccccc##", +"#abab##cccccccccccc##.", +"#bab##cccccccccccc##..", +"#ab##cccccccccccc##...", +"#b##cccccccccccc##....", +"###cccccccccccc##.....", +"##cccccccccccc##......", +"###############.......", +"......................"}; + +static const char *xpm_save[] = { +"22 22 5 1", +". c None", +"# c #000000", +"a c #838100", +"b c #c5c2c5", +"c c #cdb6d5", +"......................", +".####################.", +".#aa#bbbbbbbbbbbb#bb#.", +".#aa#bbbbbbbbbbbb#bb#.", +".#aa#bbbbbbbbbcbb####.", +".#aa#bbbccbbbbbbb#aa#.", +".#aa#bbbccbbbbbbb#aa#.", +".#aa#bbbbbbbbbbbb#aa#.", +".#aa#bbbbbbbbbbbb#aa#.", +".#aa#bbbbbbbbbbbb#aa#.", +".#aa#bbbbbbbbbbbb#aa#.", +".#aaa############aaa#.", +".#aaaaaaaaaaaaaaaaaa#.", +".#aaaaaaaaaaaaaaaaaa#.", +".#aaa#############aa#.", +".#aaa#########bbb#aa#.", +".#aaa#########bbb#aa#.", +".#aaa#########bbb#aa#.", +".#aaa#########bbb#aa#.", +".#aaa#########bbb#aa#.", +"..##################..", +"......................"}; + +static const char *xpm_back[] = { +"22 22 3 1", +". c None", +"# c #000083", +"a c #838183", +"......................", +"......................", +"......................", +"......................", +"......................", +"...........######a....", +"..#......##########...", +"..##...####......##a..", +"..###.###.........##..", +"..######..........##..", +"..#####...........##..", +"..######..........##..", +"..#######.........##..", +"..########.......##a..", +"...............a###...", +"...............###....", +"......................", +"......................", +"......................", +"......................", +"......................", +"......................"}; + +static const char *xpm_tree_view[] = { +"22 22 2 1", +". c None", +"# c #000000", +"......................", +"......................", +"......#...............", +"......#...............", +"......#...............", +"......#...............", +"......#...............", +"......########........", +"......#...............", +"......#...............", +"......#...............", +"......#...............", +"......#...............", +"......########........", +"......#...............", +"......#...............", +"......#...............", +"......#...............", +"......#...............", +"......########........", +"......................", +"......................"}; + +static const char *xpm_single_view[] = { +"22 22 2 1", +". c None", +"# c #000000", +"......................", +"......................", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"......................", +"......................"}; + +static const char *xpm_split_view[] = { +"22 22 2 1", +". c None", +"# c #000000", +"......................", +"......................", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......................", +"......................"}; + +static const char *xpm_symbol_no[] = { +"12 12 2 1", +" c white", +". c black", +" ", +" .......... ", +" . . ", +" . . ", +" . . ", +" . . ", +" . . ", +" . . ", +" . . ", +" . . ", +" .......... ", +" "}; + +static const char *xpm_symbol_mod[] = { +"12 12 2 1", +" c white", +". c black", +" ", +" .......... ", +" . . ", +" . . ", +" . .. . ", +" . .... . ", +" . .... . ", +" . .. . ", +" . . ", +" . . ", +" .......... ", +" "}; + +static const char *xpm_symbol_yes[] = { +"12 12 2 1", +" c white", +". c black", +" ", +" .......... ", +" . . ", +" . . ", +" . . . ", +" . .. . ", +" . . .. . ", +" . .... . ", +" . .. . ", +" . . ", +" .......... ", +" "}; + +static const char *xpm_choice_no[] = { +"12 12 2 1", +" c white", +". c black", +" ", +" .... ", +" .. .. ", +" . . ", +" . . ", +" . . ", +" . . ", +" . . ", +" . . ", +" .. .. ", +" .... ", +" "}; + +static const char *xpm_choice_yes[] = { +"12 12 2 1", +" c white", +". c black", +" ", +" .... ", +" .. .. ", +" . . ", +" . .. . ", +" . .... . ", +" . .... . ", +" . .. . ", +" . . ", +" .. .. ", +" .... ", +" "}; + +static const char *xpm_menu[] = { +"12 12 2 1", +" c white", +". c black", +" ", +" .......... ", +" . . ", +" . .. . ", +" . .... . ", +" . ...... . ", +" . ...... . ", +" . .... . ", +" . .. . ", +" . . ", +" .......... ", +" "}; + +static const char *xpm_menu_inv[] = { +"12 12 2 1", +" c white", +". c black", +" ", +" .......... ", +" .......... ", +" .. ...... ", +" .. .... ", +" .. .. ", +" .. .. ", +" .. .... ", +" .. ...... ", +" .......... ", +" .......... ", +" "}; + +static const char *xpm_menuback[] = { +"12 12 2 1", +" c white", +". c black", +" ", +" .......... ", +" . . ", +" . .. . ", +" . .... . ", +" . ...... . ", +" . ...... . ", +" . .... . ", +" . .. . ", +" . . ", +" .......... ", +" "}; + +static const char *xpm_void[] = { +"12 12 2 1", +" c white", +". c black", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" "}; diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/kconfig-language.txt b/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/kconfig-language.txt new file mode 100644 index 00000000..c412c245 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/kconfig-language.txt @@ -0,0 +1,379 @@ +Introduction +------------ + +The configuration database is a collection of configuration options +organized in a tree structure: + + +- Code maturity level options + | +- Prompt for development and/or incomplete code/drivers + +- General setup + | +- Networking support + | +- System V IPC + | +- BSD Process Accounting + | +- Sysctl support + +- Loadable module support + | +- Enable loadable module support + | +- Set version information on all module symbols + | +- Kernel module loader + +- ... + +Every entry has its own dependencies. These dependencies are used +to determine the visibility of an entry. Any child entry is only +visible if its parent entry is also visible. + +Menu entries +------------ + +Most entries define a config option; all other entries help to organize +them. A single configuration option is defined like this: + +config MODVERSIONS + bool "Set version information on all module symbols" + depends on MODULES + help + Usually, modules have to be recompiled whenever you switch to a new + kernel. ... + +Every line starts with a key word and can be followed by multiple +arguments. "config" starts a new config entry. The following lines +define attributes for this config option. Attributes can be the type of +the config option, input prompt, dependencies, help text and default +values. A config option can be defined multiple times with the same +name, but every definition can have only a single input prompt and the +type must not conflict. + +Menu attributes +--------------- + +A menu entry can have a number of attributes. Not all of them are +applicable everywhere (see syntax). + +- type definition: "bool"/"tristate"/"string"/"hex"/"int" + Every config option must have a type. There are only two basic types: + tristate and string; the other types are based on these two. The type + definition optionally accepts an input prompt, so these two examples + are equivalent: + + bool "Networking support" + and + bool + prompt "Networking support" + +- input prompt: "prompt" ["if" ] + Every menu entry can have at most one prompt, which is used to display + to the user. Optionally dependencies only for this prompt can be added + with "if". + +- default value: "default" ["if" ] + A config option can have any number of default values. If multiple + default values are visible, only the first defined one is active. + Default values are not limited to the menu entry where they are + defined. This means the default can be defined somewhere else or be + overridden by an earlier definition. + The default value is only assigned to the config symbol if no other + value was set by the user (via the input prompt above). If an input + prompt is visible the default value is presented to the user and can + be overridden by him. + Optionally, dependencies only for this default value can be added with + "if". + +- type definition + default value: + "def_bool"/"def_tristate" ["if" ] + This is a shorthand notation for a type definition plus a value. + Optionally dependencies for this default value can be added with "if". + +- dependencies: "depends on" + This defines a dependency for this menu entry. If multiple + dependencies are defined, they are connected with '&&'. Dependencies + are applied to all other options within this menu entry (which also + accept an "if" expression), so these two examples are equivalent: + + bool "foo" if BAR + default y if BAR + and + depends on BAR + bool "foo" + default y + +- reverse dependencies: "select" ["if" ] + While normal dependencies reduce the upper limit of a symbol (see + below), reverse dependencies can be used to force a lower limit of + another symbol. The value of the current menu symbol is used as the + minimal value can be set to. If is selected multiple + times, the limit is set to the largest selection. + Reverse dependencies can only be used with boolean or tristate + symbols. + Note: + select should be used with care. select will force + a symbol to a value without visiting the dependencies. + By abusing select you are able to select a symbol FOO even + if FOO depends on BAR that is not set. + In general use select only for non-visible symbols + (no prompts anywhere) and for symbols with no dependencies. + That will limit the usefulness but on the other hand avoid + the illegal configurations all over. + kconfig should one day warn about such things. + +- numerical ranges: "range" ["if" ] + This allows to limit the range of possible input values for int + and hex symbols. The user can only input a value which is larger than + or equal to the first symbol and smaller than or equal to the second + symbol. + +- help text: "help" or "---help---" + This defines a help text. The end of the help text is determined by + the indentation level, this means it ends at the first line which has + a smaller indentation than the first line of the help text. + "---help---" and "help" do not differ in behaviour, "---help---" is + used to help visually separate configuration logic from help within + the file as an aid to developers. + +- misc options: "option" [=] + Various less common options can be defined via this option syntax, + which can modify the behaviour of the menu entry and its config + symbol. These options are currently possible: + + - "defconfig_list" + This declares a list of default entries which can be used when + looking for the default configuration (which is used when the main + .config doesn't exists yet.) + + - "modules" + This declares the symbol to be used as the MODULES symbol, which + enables the third modular state for all config symbols. + + - "env"= + This imports the environment variable into Kconfig. It behaves like + a default, except that the value comes from the environment, this + also means that the behaviour when mixing it with normal defaults is + undefined at this point. The symbol is currently not exported back + to the build environment (if this is desired, it can be done via + another symbol). + +Menu dependencies +----------------- + +Dependencies define the visibility of a menu entry and can also reduce +the input range of tristate symbols. The tristate logic used in the +expressions uses one more state than normal boolean logic to express the +module state. Dependency expressions have the following syntax: + + ::= (1) + '=' (2) + '!=' (3) + '(' ')' (4) + '!' (5) + '&&' (6) + '||' (7) + +Expressions are listed in decreasing order of precedence. + +(1) Convert the symbol into an expression. Boolean and tristate symbols + are simply converted into the respective expression values. All + other symbol types result in 'n'. +(2) If the values of both symbols are equal, it returns 'y', + otherwise 'n'. +(3) If the values of both symbols are equal, it returns 'n', + otherwise 'y'. +(4) Returns the value of the expression. Used to override precedence. +(5) Returns the result of (2-/expr/). +(6) Returns the result of min(/expr/, /expr/). +(7) Returns the result of max(/expr/, /expr/). + +An expression can have a value of 'n', 'm' or 'y' (or 0, 1, 2 +respectively for calculations). A menu entry becomes visible when it's +expression evaluates to 'm' or 'y'. + +There are two types of symbols: constant and non-constant symbols. +Non-constant symbols are the most common ones and are defined with the +'config' statement. Non-constant symbols consist entirely of alphanumeric +characters or underscores. +Constant symbols are only part of expressions. Constant symbols are +always surrounded by single or double quotes. Within the quote, any +other character is allowed and the quotes can be escaped using '\'. + +Menu structure +-------------- + +The position of a menu entry in the tree is determined in two ways. First +it can be specified explicitly: + +menu "Network device support" + depends on NET + +config NETDEVICES + ... + +endmenu + +All entries within the "menu" ... "endmenu" block become a submenu of +"Network device support". All subentries inherit the dependencies from +the menu entry, e.g. this means the dependency "NET" is added to the +dependency list of the config option NETDEVICES. + +The other way to generate the menu structure is done by analyzing the +dependencies. If a menu entry somehow depends on the previous entry, it +can be made a submenu of it. First, the previous (parent) symbol must +be part of the dependency list and then one of these two conditions +must be true: +- the child entry must become invisible, if the parent is set to 'n' +- the child entry must only be visible, if the parent is visible + +config MODULES + bool "Enable loadable module support" + +config MODVERSIONS + bool "Set version information on all module symbols" + depends on MODULES + +comment "module support disabled" + depends on !MODULES + +MODVERSIONS directly depends on MODULES, this means it's only visible if +MODULES is different from 'n'. The comment on the other hand is always +visible when MODULES is visible (the (empty) dependency of MODULES is +also part of the comment dependencies). + + +Kconfig syntax +-------------- + +The configuration file describes a series of menu entries, where every +line starts with a keyword (except help texts). The following keywords +end a menu entry: +- config +- menuconfig +- choice/endchoice +- comment +- menu/endmenu +- if/endif +- source +The first five also start the definition of a menu entry. + +config: + + "config" + + +This defines a config symbol and accepts any of above +attributes as options. + +menuconfig: + "menuconfig" + + +This is similar to the simple config entry above, but it also gives a +hint to front ends, that all suboptions should be displayed as a +separate list of options. + +choices: + + "choice" + + + "endchoice" + +This defines a choice group and accepts any of the above attributes as +options. A choice can only be of type bool or tristate, while a boolean +choice only allows a single config entry to be selected, a tristate +choice also allows any number of config entries to be set to 'm'. This +can be used if multiple drivers for a single hardware exists and only a +single driver can be compiled/loaded into the kernel, but all drivers +can be compiled as modules. +A choice accepts another option "optional", which allows to set the +choice to 'n' and no entry needs to be selected. + +comment: + + "comment" + + +This defines a comment which is displayed to the user during the +configuration process and is also echoed to the output files. The only +possible options are dependencies. + +menu: + + "menu" + + + "endmenu" + +This defines a menu block, see "Menu structure" above for more +information. The only possible options are dependencies. + +if: + + "if" + + "endif" + +This defines an if block. The dependency expression is appended +to all enclosed menu entries. + +source: + + "source" + +This reads the specified configuration file. This file is always parsed. + +mainmenu: + + "mainmenu" + +This sets the config program's title bar if the config program chooses +to use it. + + +Kconfig hints +------------- +This is a collection of Kconfig tips, most of which aren't obvious at +first glance and most of which have become idioms in several Kconfig +files. + +Adding common features and make the usage configurable +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +It is a common idiom to implement a feature/functionality that are +relevant for some architectures but not all. +The recommended way to do so is to use a config variable named HAVE_* +that is defined in a common Kconfig file and selected by the relevant +architectures. +An example is the generic IOMAP functionality. + +We would in lib/Kconfig see: + +# Generic IOMAP is used to ... +config HAVE_GENERIC_IOMAP + +config GENERIC_IOMAP + depends on HAVE_GENERIC_IOMAP && FOO + +And in lib/Makefile we would see: +obj-$(CONFIG_GENERIC_IOMAP) += iomap.o + +For each architecture using the generic IOMAP functionality we would see: + +config X86 + select ... + select HAVE_GENERIC_IOMAP + select ... + +Note: we use the existing config option and avoid creating a new +config variable to select HAVE_GENERIC_IOMAP. + +Note: the use of the internal config variable HAVE_GENERIC_IOMAP, it is +introduced to overcome the limitation of select which will force a +config option to 'y' no matter the dependencies. +The dependencies are moved to the symbol GENERIC_IOMAP and we avoid the +situation where select forces a symbol equals to 'y'. + +Build as module only +~~~~~~~~~~~~~~~~~~~~ +To restrict a component build to module-only, qualify its config symbol +with "depends on m". E.g.: + +config FOO + depends on BAR && m + +limits FOO to module (=m) or disabled (=n). + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/kconfig-to-uclibc.patch.gz b/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/kconfig-to-uclibc.patch.gz new file mode 100644 index 0000000000000000000000000000000000000000..58c41730ec7a749d3fe02fe1b136268a1253e2b9 GIT binary patch literal 5816 zcmb2|=HO^K&Faa(oSmGXmzJ5XTavF^nw*oFl&n{fSdyH<@YW_f{Pu}S^B;zP$uK+k zfPI^xSw(|2iw&pr24fqw$<|MPoCr#Ot>nF{is78kzu#e@<*yS@^Lvz?n`b+Hvck&H z*x1MyTf`)j(2U0)0-~Nu>R`mt9y&qa{Z6kdTZU=E#>7}pUpx!`pm0HrtKV7Q`KNe$wZXQg14V70bSJw^;4l~5 zvf~tkeTri865|^)noinm;5WO@eD2SQ#7669hH17XwP6pYCbr(qO8z^~_`2EA)6u;< z>%_WQB#YI(4z75nesx>q!90xvcir}0NpdZW)H<-$)Sdkn-^~f_cPce9-uqYGjX!tq z+wQ%qH-Gl~{_EM{mmf>rZ~y6R2;6Yx;n(bKt>#`cE?*M46u~_6o|Q%KcPAlEex2)y zcK^#$ekO$eIk{Q)FjwT0nN=qe^$ceFN^G8S^wXVpE;G*`K2aXwYg2dhemv{)Z)M(F z)i!v=O#j@KyD|B8TAsxty9-8g%@^5yzB@Mc*(L@uL`m*C;MLCDIp^i69@po&sZuv? zvA2C^+-v+KEm8QV=i2^#qMw|;Kl?N1&5}9!>P^zJ_t||7l;yVySwFhEH`!s{r9V7} zH|5j{-m?5LVdI~ZT->G~KbRT^&kBz3cM_N9K0jy1gqPpvg^Rsz%1qtD{`~9ILg_QV z&fnDhw_o7)^-w3V4}Ry{bT4i)DB+wiy=DE)d0X$Am8`p7>>RPTjc-ETVdY~orxW%b69x%Vr81xws@V* zSE1D*S`QxnoAPG$^jD=R3b6}MmX&Vq8OjMifvq7%65L+npSBqUt9 z{iATPZ(4(z(X-^_H-Zw{o2oi9jZQd3UAT2eWv`pXq2S+V>MT;EbDUe2n=TLy(O`O~ zY{h?!-zj0n`U`KTb3{ZOfAe}*)!IYX`S0;0)!g~y@SHEwl##`TZ_-=FyB)WMxOA@CyL(5<)j!_NthwI#zOM8Ay<_F?AMM`! zsc)#@V?zo!oiu-<>?%Un-e%+(puYbH#+xJ^{-*1Wgf93AicD?_{ zsdLs)#bA+hYVxIyhSf)x#-vKGZ{nT6^e8}Tvgxe##b9*znwZ)aC*Is93 zrEM;Ver7)%)7W|r6x~L zyLltBbXr5~(|m(auX}YP-1W5eOgrcJGSr{m=PmeAt3oto<)NO9BHI<@3;!}rV+))A zD9!Vo;uY_$wRc=rJSsJ1ov`ows`}bWww!(MJhDSP+oX(-%n_29BxPzQcj&>6+?~J9 ze2`Mpas8>4;Azv|IaOk%vEZU@OWBJToLe9)rz2gm z>D7YG4WH)(?D9PIk&ESK?dl~Gzb=^-e|6jOb0^FFtjaIvCRj7OIotOs)TcjiN*2#P ztsq#zmsWYjv5~KtcEMW{*+~MI@5@hHW)pNPxjyX+pjORi_RPA&a?MhXXfvI zBmdHUSDmPH3tf%t#Hz&#(gpK{t}*P9yP0Tx*N5xQsz-;`T)lHTddArm`X%#=IojU+ zj(z@POR=U-tJq4V~LVt zjgRgV{q`|q-Tw^BWxq8xzgy_B`{spfzBA__3zWU5%3rflA!VYb^(UgKM=vC)JzQSt4snN=cMw?F*LTE1v=!CWUUn>v*{Ij6Uj z+?G{ZC^=JLUfqfLP63ze7%N<7UUbisu8`_`zT~@GXW#M!Jy)|YrTHzHvF{Wm4(#4` z;yK6Jxv#rZ)+q&T4=sGItgGhH+M=a2fAO{W1yf%i>)0t*re!#nH|Orobms4zUoNri zQRL6qV7;!nwdjtP!CD9T8+TYfi0CCB>HQs|uI&=Bp_=p6jE1``rxYxl?PPjj zPu&~GIqi0gCDP4Ta^ezs(h}}memUPcL~(BaG~UVcB_@crDBtgGQ?6qDKIgKfAb-X= z?Mj|4X7fz*v!WhZay(1Dm%Qw?6Tj2#qTNq^UlihN5j8k`t@%NK@>SRDOEXgCvJP#^ zx^>a2;Ol|UvHiavw(NPg@LK|_ScjYSu5Ze98`j>FTRS~H@#HrXv0uA{Z&YhixP`yLg4^z=94k3Sbvuv_fcvAV_ecYhb$`?ad3Nn!FOdx4)_1XZ}W1E%FeJ|{BW)+=|#x}5&IX;adxHhvTQm`k^L*( zEnhO$Wt^#v_+r<$^jUJEJi|M8^G&{N_n4B{nQed1`*Ee^ z1N$7koernlB^FF!{Ufne>GK8t#`0IY`h5&V=So!sYd331yskS@tMuUF*Z0gHavlWd za%(SL@uh78>tux|j~hh)i5_eSIlR>PPGVve+g#DSuxT%ESovz~ac)F^S<=ue# zvRhxH_WgS^jbRDL^xB{WH-E7ly3u~*`jk}0SdJ||uWbwdAAHm=qPu0&pM@`0#wIpQ z5e#e7PS{}Q*vY4KnoqIl=N%45eTAmoD_2eN;%aC9k-jYt(~=n6!q^ zjV>N%Tt6MWT>BwpK{4ZvCf12^3k%oFTXgUC$+{zSL1L5PtJ@9TGxzM!zPy9^uEnx# z68nAgB9c7<4jgj(;~C!XXCkLil)*OpP=ZO~jNncdSKRIZcn zTEh8<@0w=g1qZ2!DO1m0bh-O>?wal^hbD4==vUtEGVinFcU|*Cl`k0uIC}-w8pIY^ z_?RC!6dRyi*rt+V_u!#2d%HSU$wcAGpUY0Pby;4pOz`46uISsr%)03VS8?9Mb!vGk zlMIv$YD!YAI>jy(8>EU@6a+Q?Yfzf(S6&t}XOdsf!NL`M*Ccl8g)Kjpx?t-uInPZO ztCp#-O4=&%i3l{6HkgYYDgNuYJ!i|OHOVvezicXV`{L;F_<-G#Xp5{hi_V1X@l0!& z&hL~d%=0|i+d8@{-H_>nm_myX^S?v}#;M|kp6?VI5^ufO>foo`{X1fUsb=8QbzE_q z&P@xLm>OHM%e?4p?M3Ui4Hx8f?w20Z&YLh4m{M*rI_h{vYbCdh{R?pSo>s-B+ zJ#Jq__SO?OFVEN@!tE5l=17x^Q}(Tm@0|tqKA+4Gw1z#q!)-AKYw01?rm_o;--}pO zZana3HrUCyk58iGnFr(E&27rk|CEm(XrCnQ%x+fXe8ex|sp(th9h_RVc0WpvJh5Y& zam(?0$H(PAUOw`$sGadgd`ra3cn;4(uFeHr$zP@ysH%O_5!Afdd1Q`*#v)EZ>lZA? z1phkmC5tLg_|UIh#Pxm$ujT23+bVWF((pH(UTnwmJ7=@~HoNYQV7Ac2`VHr^944y< zKP))^sM`5^z^bIR^Bku{eLp#KCR6&WRww`GFZSg{>8*MdBYB_2X<3z0_Kb9|I}Jf8 z&m^Qf4CM^jtT}&bUOsR_;jh1eQmu;A%nLRr%wFiM*|uN*{2_v+|GQbSDSnu-((CV+Pa$g(wkGE=RULfim1M+a%xUk(ekr!IxX+sD zWm>1Ua$(Gdn~c{P7&_Na;xyZHYR9ZoYwwgquFPJ>uWDUuxL;Cl;!VNZneBS(8Nw^x zZE+A-81z2*@PoJ+2?zE{fBJD?t$^^u$eNC>Ux%2)jr%Wbw|L^%@Nv%K*&??^B}~`^ zO0|uP4@541uJA1~<8iXuzFmDM{)xQ&KBszt;e2%bg?V znaz?}UhWJsteiNp`4Ow=6DRf!Q`i@&op$GvQd*OCsO3rfjLU8d7P)l>axHf%jk?#; z@}=uaBNz1i%SrZW z>@#Zb9#(N;{LVV{#C?&e#Ro5*x{|JaV&UG}M;Gq>JLh$O@6-Br)mJ(Np*1Ith=tZ4 zVm`jqzuN2LMnSDhD`%fwd13FxAfLKUjqXI5e=~L;_~ZVkG?A-7tZAtNpH;ZJ`xkEZ zkkkvJE4MJMiA?g1Jl-98@W{-+S(`)dCm#L#N-u8ur?zvmR=?$$?y_?BrWV)x1^28@ z9-pEAVNBPZ1;+|!24Nt&#g7CwzEYSiX?5__Cwn6QNm6) zohdS>3flI)dDD^Gj{Lze?f)m9&5yY3)bxI%cCD{lKaG^?r}q2E-DzJJzQAgd#kusuyL(>Ue_l}gQb6A-r#?6X`1;4w@%A+BqNcV5>C^gOY}>%;>AqRf|6cZ4*;W1% z!%M%}X-ga~W4>3}kh0~&YtDPhn#Bo*oEC?b%T;ZA9?$gMAHQBBJ8@A7$B)TYdhY5@ zySAP(wDFeT$Ibr9m-(!uqFv|o!VkCkA4$sY*DlewZ%tphxxDplwd}#;(oMcQ8@1Pc zo|@wJf%`!pd!C3I*P&@Ad^t`zeg3Fs_fB}zp_6LN_k+@>zmo{7_`gL#ee=zO;=BI& zhz2|@EPlW5(XYdcz23aqYJO4Ryj;d*`JbyHj(wT`$0Kf zJ>TeGPrsx-|M6v!^6?-!+shW_aVZOy&9y()>*|k>oyRho| zx<3hW$-jOy#yTiDct@26PptpX99PfSoH(^>Rqhb$~P!_F78E@qe~ zed6;kU7jbpQU9jSDiQj#_)beY`-E`DZmq?ObChp=3|V}>{SW8uQ_LLd%*Y**>mejlYn-_EYqo)Y-;IU%odJZGGix*Lien zjg+m^&rp>U45J@fufozd9!Mu3Wa0ZD!NVO>5nh*I!Ud zo&0&1*{$7cZHmQaFWUV(DSXPhQ*0T!4`0?z_+L3gr|-pikDhIkPyC{|H2(ko$#cNw z>!(=rCB=^C+k05E4Kt^+F4c_UlK)jPjq{_<zvyeKT^AqUlvMcebA8Fn|2=xX zo0#V6T%39G^p})PoAOMe9(Df;`)oh!b-~4>=()Qb<%^#jRWoMmL z`=4_3%}JKC4BjoL-G4B>E4Asq9U^%yi0PS9gj4Xh_f=<`mY(8!qW9=OgVyh&CE`I0 F3;={`V4eT~ literal 0 HcmV?d00001 diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/kconfig_load.c b/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/kconfig_load.c new file mode 100644 index 00000000..dbdcaad8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/kconfig_load.c @@ -0,0 +1,35 @@ +#include +#include +#include + +#include "lkc.h" + +#define P(name,type,arg) type (*name ## _p) arg +#include "lkc_proto.h" +#undef P + +void kconfig_load(void) +{ + void *handle; + char *error; + + handle = dlopen("./libkconfig.so", RTLD_LAZY); + if (!handle) { + handle = dlopen("./scripts/kconfig/libkconfig.so", RTLD_LAZY); + if (!handle) { + fprintf(stderr, "%s\n", dlerror()); + exit(1); + } + } + +#define P(name,type,arg) \ +{ \ + name ## _p = dlsym(handle, #name); \ + if ((error = dlerror())) { \ + fprintf(stderr, "%s\n", error); \ + exit(1); \ + } \ +} +#include "lkc_proto.h" +#undef P +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/kxgettext.c b/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/kxgettext.c new file mode 100644 index 00000000..6eb72a7f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/kxgettext.c @@ -0,0 +1,229 @@ +/* + * Arnaldo Carvalho de Melo , 2005 + * + * Released under the terms of the GNU GPL v2.0 + */ + +#include +#include + +#define LKC_DIRECT_LINK +#include "lkc.h" + +static char *escape(const char* text, char *bf, int len) +{ + char *bfp = bf; + int multiline = strchr(text, '\n') != NULL; + int eol = 0; + int textlen = strlen(text); + + if ((textlen > 0) && (text[textlen-1] == '\n')) + eol = 1; + + *bfp++ = '"'; + --len; + + if (multiline) { + *bfp++ = '"'; + *bfp++ = '\n'; + *bfp++ = '"'; + len -= 3; + } + + while (*text != '\0' && len > 1) { + if (*text == '"') + *bfp++ = '\\'; + else if (*text == '\n') { + *bfp++ = '\\'; + *bfp++ = 'n'; + *bfp++ = '"'; + *bfp++ = '\n'; + *bfp++ = '"'; + len -= 5; + ++text; + goto next; + } + *bfp++ = *text++; +next: + --len; + } + + if (multiline && eol) + bfp -= 3; + + *bfp++ = '"'; + *bfp = '\0'; + + return bf; +} + +struct file_line { + struct file_line *next; + char* file; + int lineno; +}; + +static struct file_line *file_line__new(char *file, int lineno) +{ + struct file_line *self = malloc(sizeof(*self)); + + if (self == NULL) + goto out; + + self->file = file; + self->lineno = lineno; + self->next = NULL; +out: + return self; +} + +struct message { + const char *msg; + const char *option; + struct message *next; + struct file_line *files; +}; + +static struct message *message__list; + +static struct message *message__new(const char *msg, char *option, char *file, int lineno) +{ + struct message *self = malloc(sizeof(*self)); + + if (self == NULL) + goto out; + + self->files = file_line__new(file, lineno); + if (self->files == NULL) + goto out_fail; + + self->msg = strdup(msg); + if (self->msg == NULL) + goto out_fail_msg; + + self->option = option; + self->next = NULL; +out: + return self; +out_fail_msg: + free(self->files); +out_fail: + free(self); + self = NULL; + goto out; +} + +static struct message *mesage__find(const char *msg) +{ + struct message *m = message__list; + + while (m != NULL) { + if (strcmp(m->msg, msg) == 0) + break; + m = m->next; + } + + return m; +} + +static int message__add_file_line(struct message *self, char *file, int lineno) +{ + int rc = -1; + struct file_line *fl = file_line__new(file, lineno); + + if (fl == NULL) + goto out; + + fl->next = self->files; + self->files = fl; + rc = 0; +out: + return rc; +} + +static int message__add(const char *msg, char *option, char *file, int lineno) +{ + int rc = 0; + char bf[16384]; + char *escaped = escape(msg, bf, sizeof(bf)); + struct message *m = mesage__find(escaped); + + if (m != NULL) + rc = message__add_file_line(m, file, lineno); + else { + m = message__new(escaped, option, file, lineno); + + if (m != NULL) { + m->next = message__list; + message__list = m; + } else + rc = -1; + } + return rc; +} + +void menu_build_message_list(struct menu *menu) +{ + struct menu *child; + + message__add(menu_get_prompt(menu), NULL, + menu->file == NULL ? "Root Menu" : menu->file->name, + menu->lineno); + + if (menu->sym != NULL && menu_has_help(menu)) + message__add(menu_get_help(menu), menu->sym->name, + menu->file == NULL ? "Root Menu" : menu->file->name, + menu->lineno); + + for (child = menu->list; child != NULL; child = child->next) + if (child->prompt != NULL) + menu_build_message_list(child); +} + +static void message__print_file_lineno(struct message *self) +{ + struct file_line *fl = self->files; + + putchar('\n'); + if (self->option != NULL) + printf("# %s:00000\n", self->option); + + printf("#: %s:%d", fl->file, fl->lineno); + fl = fl->next; + + while (fl != NULL) { + printf(", %s:%d", fl->file, fl->lineno); + fl = fl->next; + } + + putchar('\n'); +} + +static void message__print_gettext_msgid_msgstr(struct message *self) +{ + message__print_file_lineno(self); + + printf("msgid %s\n" + "msgstr \"\"\n", self->msg); +} + +void menu__xgettext(void) +{ + struct message *m = message__list; + + while (m != NULL) { + /* skip empty lines ("") */ + if (strlen(m->msg) > sizeof("\"\"")) + message__print_gettext_msgid_msgstr(m); + m = m->next; + } +} + +int main(int ac, char **av) +{ + conf_parse(av[1]); + + menu_build_message_list(menu_get_root_menu(NULL)); + menu__xgettext(); + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/lex.zconf.c_shipped b/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/lex.zconf.c_shipped new file mode 100644 index 00000000..f6e38b68 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/lex.zconf.c_shipped @@ -0,0 +1,2416 @@ + +#line 3 "scripts/kconfig/lex.zconf.c" + +#define YY_INT_ALIGNED short int + +/* A lexical scanner generated by flex */ + +#define yy_create_buffer zconf_create_buffer +#define yy_delete_buffer zconf_delete_buffer +#define yy_flex_debug zconf_flex_debug +#define yy_init_buffer zconf_init_buffer +#define yy_flush_buffer zconf_flush_buffer +#define yy_load_buffer_state zconf_load_buffer_state +#define yy_switch_to_buffer zconf_switch_to_buffer +#define yyin zconfin +#define yyleng zconfleng +#define yylex zconflex +#define yylineno zconflineno +#define yyout zconfout +#define yyrestart zconfrestart +#define yytext zconftext +#define yywrap zconfwrap +#define yyalloc zconfalloc +#define yyrealloc zconfrealloc +#define yyfree zconffree + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 5 +#define YY_FLEX_SUBMINOR_VERSION 35 +#if YY_FLEX_SUBMINOR_VERSION > 0 +#define FLEX_BETA +#endif + +/* First, we deal with platform-specific or compiler-specific issues. */ + +/* begin standard C headers. */ +#include +#include +#include +#include + +/* end standard C headers. */ + +/* flex integer type definitions */ + +#ifndef FLEXINT_H +#define FLEXINT_H + +/* C99 systems have . Non-C99 systems may or may not. */ + +#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + +/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, + * if you want the limit (max/min) macros for int types. + */ +#ifndef __STDC_LIMIT_MACROS +#define __STDC_LIMIT_MACROS 1 +#endif + +#include +typedef int8_t flex_int8_t; +typedef uint8_t flex_uint8_t; +typedef int16_t flex_int16_t; +typedef uint16_t flex_uint16_t; +typedef int32_t flex_int32_t; +typedef uint32_t flex_uint32_t; +#else +typedef signed char flex_int8_t; +typedef short int flex_int16_t; +typedef int flex_int32_t; +typedef unsigned char flex_uint8_t; +typedef unsigned short int flex_uint16_t; +typedef unsigned int flex_uint32_t; + +/* Limits of integral types. */ +#ifndef INT8_MIN +#define INT8_MIN (-128) +#endif +#ifndef INT16_MIN +#define INT16_MIN (-32767-1) +#endif +#ifndef INT32_MIN +#define INT32_MIN (-2147483647-1) +#endif +#ifndef INT8_MAX +#define INT8_MAX (127) +#endif +#ifndef INT16_MAX +#define INT16_MAX (32767) +#endif +#ifndef INT32_MAX +#define INT32_MAX (2147483647) +#endif +#ifndef UINT8_MAX +#define UINT8_MAX (255U) +#endif +#ifndef UINT16_MAX +#define UINT16_MAX (65535U) +#endif +#ifndef UINT32_MAX +#define UINT32_MAX (4294967295U) +#endif + +#endif /* ! C99 */ + +#endif /* ! FLEXINT_H */ + +#ifdef __cplusplus + +/* The "const" storage-class-modifier is valid. */ +#define YY_USE_CONST + +#else /* ! __cplusplus */ + +/* C99 requires __STDC__ to be defined as 1. */ +#if defined (__STDC__) + +#define YY_USE_CONST + +#endif /* defined (__STDC__) */ +#endif /* ! __cplusplus */ + +#ifdef YY_USE_CONST +#define yyconst const +#else +#define yyconst +#endif + +/* Returned upon end-of-file. */ +#define YY_NULL 0 + +/* Promotes a possibly negative, possibly signed char to an unsigned + * integer for use as an array index. If the signed char is negative, + * we want to instead treat it as an 8-bit unsigned char, hence the + * double cast. + */ +#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) + +/* Enter a start condition. This macro really ought to take a parameter, + * but we do it the disgusting crufty way forced on us by the ()-less + * definition of BEGIN. + */ +#define BEGIN (yy_start) = 1 + 2 * + +/* Translate the current start state into a value that can be later handed + * to BEGIN to return to the state. The YYSTATE alias is for lex + * compatibility. + */ +#define YY_START (((yy_start) - 1) / 2) +#define YYSTATE YY_START + +/* Action number for EOF rule of a given start state. */ +#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) + +/* Special action meaning "start processing a new file". */ +#define YY_NEW_FILE zconfrestart(zconfin ) + +#define YY_END_OF_BUFFER_CHAR 0 + +/* Size of default input buffer. */ +#ifndef YY_BUF_SIZE +#define YY_BUF_SIZE 16384 +#endif + +/* The state buf must be large enough to hold one state per character in the main buffer. + */ +#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type)) + +#ifndef YY_TYPEDEF_YY_BUFFER_STATE +#define YY_TYPEDEF_YY_BUFFER_STATE +typedef struct yy_buffer_state *YY_BUFFER_STATE; +#endif + +extern int zconfleng; + +extern FILE *zconfin, *zconfout; + +#define EOB_ACT_CONTINUE_SCAN 0 +#define EOB_ACT_END_OF_FILE 1 +#define EOB_ACT_LAST_MATCH 2 + + #define YY_LESS_LINENO(n) + +/* Return all but the first "n" matched characters back to the input stream. */ +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up zconftext. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + *yy_cp = (yy_hold_char); \ + YY_RESTORE_YY_MORE_OFFSET \ + (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ + YY_DO_BEFORE_ACTION; /* set up zconftext again */ \ + } \ + while ( 0 ) + +#define unput(c) yyunput( c, (yytext_ptr) ) + +#ifndef YY_TYPEDEF_YY_SIZE_T +#define YY_TYPEDEF_YY_SIZE_T +typedef size_t yy_size_t; +#endif + +#ifndef YY_STRUCT_YY_BUFFER_STATE +#define YY_STRUCT_YY_BUFFER_STATE +struct yy_buffer_state + { + FILE *yy_input_file; + + char *yy_ch_buf; /* input buffer */ + char *yy_buf_pos; /* current position in input buffer */ + + /* Size of input buffer in bytes, not including room for EOB + * characters. + */ + yy_size_t yy_buf_size; + + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ + int yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to + * delete it. + */ + int yy_is_our_buffer; + + /* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ + int yy_is_interactive; + + /* Whether we're considered to be at the beginning of a line. + * If so, '^' rules will be active on the next match, otherwise + * not. + */ + int yy_at_bol; + + int yy_bs_lineno; /**< The line count. */ + int yy_bs_column; /**< The column count. */ + + /* Whether to try to fill the input buffer when we reach the + * end of it. + */ + int yy_fill_buffer; + + int yy_buffer_status; + +#define YY_BUFFER_NEW 0 +#define YY_BUFFER_NORMAL 1 + /* When an EOF's been seen but there's still some text to process + * then we mark the buffer as YY_EOF_PENDING, to indicate that we + * shouldn't try reading from the input source any more. We might + * still have a bunch of tokens to match, though, because of + * possible backing-up. + * + * When we actually see the EOF, we change the status to "new" + * (via zconfrestart()), so that the user can continue scanning by + * just pointing zconfin at a new input file. + */ +#define YY_BUFFER_EOF_PENDING 2 + + }; +#endif /* !YY_STRUCT_YY_BUFFER_STATE */ + +/* Stack of input buffers. */ +static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */ +static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */ +static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */ + +/* We provide macros for accessing buffer states in case in the + * future we want to put the buffer states in a more general + * "scanner state". + * + * Returns the top of the stack, or NULL. + */ +#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \ + ? (yy_buffer_stack)[(yy_buffer_stack_top)] \ + : NULL) + +/* Same as previous macro, but useful when we know that the buffer stack is not + * NULL or when we need an lvalue. For internal use only. + */ +#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)] + +/* yy_hold_char holds the character lost when zconftext is formed. */ +static char yy_hold_char; +static int yy_n_chars; /* number of characters read into yy_ch_buf */ +int zconfleng; + +/* Points to current character in buffer. */ +static char *yy_c_buf_p = (char *) 0; +static int yy_init = 0; /* whether we need to initialize */ +static int yy_start = 0; /* start state number */ + +/* Flag which is used to allow zconfwrap()'s to do buffer switches + * instead of setting up a fresh zconfin. A bit of a hack ... + */ +static int yy_did_buffer_switch_on_eof; + +void zconfrestart (FILE *input_file ); +void zconf_switch_to_buffer (YY_BUFFER_STATE new_buffer ); +YY_BUFFER_STATE zconf_create_buffer (FILE *file,int size ); +void zconf_delete_buffer (YY_BUFFER_STATE b ); +void zconf_flush_buffer (YY_BUFFER_STATE b ); +void zconfpush_buffer_state (YY_BUFFER_STATE new_buffer ); +void zconfpop_buffer_state (void ); + +static void zconfensure_buffer_stack (void ); +static void zconf_load_buffer_state (void ); +static void zconf_init_buffer (YY_BUFFER_STATE b,FILE *file ); + +#define YY_FLUSH_BUFFER zconf_flush_buffer(YY_CURRENT_BUFFER ) + +YY_BUFFER_STATE zconf_scan_buffer (char *base,yy_size_t size ); +YY_BUFFER_STATE zconf_scan_string (yyconst char *yy_str ); +YY_BUFFER_STATE zconf_scan_bytes (yyconst char *bytes,int len ); + +void *zconfalloc (yy_size_t ); +void *zconfrealloc (void *,yy_size_t ); +void zconffree (void * ); + +#define yy_new_buffer zconf_create_buffer + +#define yy_set_interactive(is_interactive) \ + { \ + if ( ! YY_CURRENT_BUFFER ){ \ + zconfensure_buffer_stack (); \ + YY_CURRENT_BUFFER_LVALUE = \ + zconf_create_buffer(zconfin,YY_BUF_SIZE ); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ + } + +#define yy_set_bol(at_bol) \ + { \ + if ( ! YY_CURRENT_BUFFER ){\ + zconfensure_buffer_stack (); \ + YY_CURRENT_BUFFER_LVALUE = \ + zconf_create_buffer(zconfin,YY_BUF_SIZE ); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ + } + +#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) + +/* Begin user sect3 */ + +#define zconfwrap(n) 1 +#define YY_SKIP_YYWRAP + +typedef unsigned char YY_CHAR; + +FILE *zconfin = (FILE *) 0, *zconfout = (FILE *) 0; + +typedef int yy_state_type; + +extern int zconflineno; + +int zconflineno = 1; + +extern char *zconftext; +#define yytext_ptr zconftext +static yyconst flex_int16_t yy_nxt[][17] = + { + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0 + }, + + { + 11, 12, 13, 14, 12, 12, 15, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12 + }, + + { + 11, 12, 13, 14, 12, 12, 15, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12 + }, + + { + 11, 16, 16, 17, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 18, 16, 16, 16 + }, + + { + 11, 16, 16, 17, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 18, 16, 16, 16 + + }, + + { + 11, 19, 20, 21, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19 + }, + + { + 11, 19, 20, 21, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19 + }, + + { + 11, 22, 22, 23, 22, 24, 22, 22, 24, 22, + 22, 22, 22, 22, 22, 25, 22 + }, + + { + 11, 22, 22, 23, 22, 24, 22, 22, 24, 22, + 22, 22, 22, 22, 22, 25, 22 + }, + + { + 11, 26, 26, 27, 28, 29, 30, 31, 29, 32, + 33, 34, 35, 35, 36, 37, 38 + + }, + + { + 11, 26, 26, 27, 28, 29, 30, 31, 29, 32, + 33, 34, 35, 35, 36, 37, 38 + }, + + { + -11, -11, -11, -11, -11, -11, -11, -11, -11, -11, + -11, -11, -11, -11, -11, -11, -11 + }, + + { + 11, -12, -12, -12, -12, -12, -12, -12, -12, -12, + -12, -12, -12, -12, -12, -12, -12 + }, + + { + 11, -13, 39, 40, -13, -13, 41, -13, -13, -13, + -13, -13, -13, -13, -13, -13, -13 + }, + + { + 11, -14, -14, -14, -14, -14, -14, -14, -14, -14, + -14, -14, -14, -14, -14, -14, -14 + + }, + + { + 11, 42, 42, 43, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42 + }, + + { + 11, -16, -16, -16, -16, -16, -16, -16, -16, -16, + -16, -16, -16, -16, -16, -16, -16 + }, + + { + 11, -17, -17, -17, -17, -17, -17, -17, -17, -17, + -17, -17, -17, -17, -17, -17, -17 + }, + + { + 11, -18, -18, -18, -18, -18, -18, -18, -18, -18, + -18, -18, -18, 44, -18, -18, -18 + }, + + { + 11, 45, 45, -19, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45 + + }, + + { + 11, -20, 46, 47, -20, -20, -20, -20, -20, -20, + -20, -20, -20, -20, -20, -20, -20 + }, + + { + 11, 48, -21, -21, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48 + }, + + { + 11, 49, 49, 50, 49, -22, 49, 49, -22, 49, + 49, 49, 49, 49, 49, -22, 49 + }, + + { + 11, -23, -23, -23, -23, -23, -23, -23, -23, -23, + -23, -23, -23, -23, -23, -23, -23 + }, + + { + 11, -24, -24, -24, -24, -24, -24, -24, -24, -24, + -24, -24, -24, -24, -24, -24, -24 + + }, + + { + 11, 51, 51, 52, 51, 51, 51, 51, 51, 51, + 51, 51, 51, 51, 51, 51, 51 + }, + + { + 11, -26, -26, -26, -26, -26, -26, -26, -26, -26, + -26, -26, -26, -26, -26, -26, -26 + }, + + { + 11, -27, -27, -27, -27, -27, -27, -27, -27, -27, + -27, -27, -27, -27, -27, -27, -27 + }, + + { + 11, -28, -28, -28, -28, -28, -28, -28, -28, -28, + -28, -28, -28, -28, 53, -28, -28 + }, + + { + 11, -29, -29, -29, -29, -29, -29, -29, -29, -29, + -29, -29, -29, -29, -29, -29, -29 + + }, + + { + 11, 54, 54, -30, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54 + }, + + { + 11, -31, -31, -31, -31, -31, -31, 55, -31, -31, + -31, -31, -31, -31, -31, -31, -31 + }, + + { + 11, -32, -32, -32, -32, -32, -32, -32, -32, -32, + -32, -32, -32, -32, -32, -32, -32 + }, + + { + 11, -33, -33, -33, -33, -33, -33, -33, -33, -33, + -33, -33, -33, -33, -33, -33, -33 + }, + + { + 11, -34, -34, -34, -34, -34, -34, -34, -34, -34, + -34, 56, 57, 57, -34, -34, -34 + + }, + + { + 11, -35, -35, -35, -35, -35, -35, -35, -35, -35, + -35, 57, 57, 57, -35, -35, -35 + }, + + { + 11, -36, -36, -36, -36, -36, -36, -36, -36, -36, + -36, -36, -36, -36, -36, -36, -36 + }, + + { + 11, -37, -37, 58, -37, -37, -37, -37, -37, -37, + -37, -37, -37, -37, -37, -37, -37 + }, + + { + 11, -38, -38, -38, -38, -38, -38, -38, -38, -38, + -38, -38, -38, -38, -38, -38, 59 + }, + + { + 11, -39, 39, 40, -39, -39, 41, -39, -39, -39, + -39, -39, -39, -39, -39, -39, -39 + + }, + + { + 11, -40, -40, -40, -40, -40, -40, -40, -40, -40, + -40, -40, -40, -40, -40, -40, -40 + }, + + { + 11, 42, 42, 43, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42 + }, + + { + 11, 42, 42, 43, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42 + }, + + { + 11, -43, -43, -43, -43, -43, -43, -43, -43, -43, + -43, -43, -43, -43, -43, -43, -43 + }, + + { + 11, -44, -44, -44, -44, -44, -44, -44, -44, -44, + -44, -44, -44, 44, -44, -44, -44 + + }, + + { + 11, 45, 45, -45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45 + }, + + { + 11, -46, 46, 47, -46, -46, -46, -46, -46, -46, + -46, -46, -46, -46, -46, -46, -46 + }, + + { + 11, 48, -47, -47, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48 + }, + + { + 11, -48, -48, -48, -48, -48, -48, -48, -48, -48, + -48, -48, -48, -48, -48, -48, -48 + }, + + { + 11, 49, 49, 50, 49, -49, 49, 49, -49, 49, + 49, 49, 49, 49, 49, -49, 49 + + }, + + { + 11, -50, -50, -50, -50, -50, -50, -50, -50, -50, + -50, -50, -50, -50, -50, -50, -50 + }, + + { + 11, -51, -51, 52, -51, -51, -51, -51, -51, -51, + -51, -51, -51, -51, -51, -51, -51 + }, + + { + 11, -52, -52, -52, -52, -52, -52, -52, -52, -52, + -52, -52, -52, -52, -52, -52, -52 + }, + + { + 11, -53, -53, -53, -53, -53, -53, -53, -53, -53, + -53, -53, -53, -53, -53, -53, -53 + }, + + { + 11, 54, 54, -54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54 + + }, + + { + 11, -55, -55, -55, -55, -55, -55, -55, -55, -55, + -55, -55, -55, -55, -55, -55, -55 + }, + + { + 11, -56, -56, -56, -56, -56, -56, -56, -56, -56, + -56, 60, 57, 57, -56, -56, -56 + }, + + { + 11, -57, -57, -57, -57, -57, -57, -57, -57, -57, + -57, 57, 57, 57, -57, -57, -57 + }, + + { + 11, -58, -58, -58, -58, -58, -58, -58, -58, -58, + -58, -58, -58, -58, -58, -58, -58 + }, + + { + 11, -59, -59, -59, -59, -59, -59, -59, -59, -59, + -59, -59, -59, -59, -59, -59, -59 + + }, + + { + 11, -60, -60, -60, -60, -60, -60, -60, -60, -60, + -60, 57, 57, 57, -60, -60, -60 + }, + + } ; + +static yy_state_type yy_get_previous_state (void ); +static yy_state_type yy_try_NUL_trans (yy_state_type current_state ); +static int yy_get_next_buffer (void ); +static void yy_fatal_error (yyconst char msg[] ); + +/* Done after the current pattern has been matched and before the + * corresponding action - sets up zconftext. + */ +#define YY_DO_BEFORE_ACTION \ + (yytext_ptr) = yy_bp; \ + zconfleng = (size_t) (yy_cp - yy_bp); \ + (yy_hold_char) = *yy_cp; \ + *yy_cp = '\0'; \ + (yy_c_buf_p) = yy_cp; + +#define YY_NUM_RULES 33 +#define YY_END_OF_BUFFER 34 +/* This struct is not used in this scanner, + but its presence is necessary. */ +struct yy_trans_info + { + flex_int32_t yy_verify; + flex_int32_t yy_nxt; + }; +static yyconst flex_int16_t yy_accept[61] = + { 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 34, 5, 4, 2, 3, 7, 8, 6, 32, 29, + 31, 24, 28, 27, 26, 22, 17, 13, 16, 20, + 22, 11, 12, 19, 19, 14, 22, 22, 4, 2, + 3, 3, 1, 6, 32, 29, 31, 30, 24, 23, + 26, 25, 15, 20, 9, 19, 19, 21, 10, 18 + } ; + +static yyconst flex_int32_t yy_ec[256] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 4, 5, 6, 1, 1, 7, 8, 9, + 10, 1, 1, 1, 11, 12, 12, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 1, 1, 1, + 14, 1, 1, 1, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 1, 15, 1, 1, 13, 1, 13, 13, 13, 13, + + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 1, 16, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1 + } ; + +extern int zconf_flex_debug; +int zconf_flex_debug = 0; + +/* The intent behind this definition is that it'll catch + * any uses of REJECT which flex missed. + */ +#define REJECT reject_used_but_not_detected +#define yymore() yymore_used_but_not_detected +#define YY_MORE_ADJ 0 +#define YY_RESTORE_YY_MORE_OFFSET +char *zconftext; +#define YY_NO_INPUT 1 + +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +#include +#include +#include +#include +#include + +#define LKC_DIRECT_LINK +#include "lkc.h" + +#define START_STRSIZE 16 + +static struct { + struct file *file; + int lineno; +} current_pos; + +static char *text; +static int text_size, text_asize; + +struct buffer { + struct buffer *parent; + YY_BUFFER_STATE state; +}; + +struct buffer *current_buf; + +static int last_ts, first_ts; + +static void zconf_endhelp(void); +static void zconf_endfile(void); + +void new_string(void) +{ + text = malloc(START_STRSIZE); + text_asize = START_STRSIZE; + text_size = 0; + *text = 0; +} + +void append_string(const char *str, int size) +{ + int new_size = text_size + size + 1; + if (new_size > text_asize) { + new_size += START_STRSIZE - 1; + new_size &= -START_STRSIZE; + text = realloc(text, new_size); + text_asize = new_size; + } + memcpy(text + text_size, str, size); + text_size += size; + text[text_size] = 0; +} + +void alloc_string(const char *str, int size) +{ + text = malloc(size + 1); + memcpy(text, str, size); + text[size] = 0; +} + +#define INITIAL 0 +#define COMMAND 1 +#define HELP 2 +#define STRING 3 +#define PARAM 4 + +#ifndef YY_NO_UNISTD_H +/* Special case for "unistd.h", since it is non-ANSI. We include it way + * down here because we want the user's section 1 to have been scanned first. + * The user has a chance to override it with an option. + */ +#include +#endif + +#ifndef YY_EXTRA_TYPE +#define YY_EXTRA_TYPE void * +#endif + +static int yy_init_globals (void ); + +/* Accessor methods to globals. + These are made visible to non-reentrant scanners for convenience. */ + +int zconflex_destroy (void ); + +int zconfget_debug (void ); + +void zconfset_debug (int debug_flag ); + +YY_EXTRA_TYPE zconfget_extra (void ); + +void zconfset_extra (YY_EXTRA_TYPE user_defined ); + +FILE *zconfget_in (void ); + +void zconfset_in (FILE * in_str ); + +FILE *zconfget_out (void ); + +void zconfset_out (FILE * out_str ); + +int zconfget_leng (void ); + +char *zconfget_text (void ); + +int zconfget_lineno (void ); + +void zconfset_lineno (int line_number ); + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int zconfwrap (void ); +#else +extern int zconfwrap (void ); +#endif +#endif + + static void yyunput (int c,char *buf_ptr ); + +#ifndef yytext_ptr +static void yy_flex_strncpy (char *,yyconst char *,int ); +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen (yyconst char * ); +#endif + +#ifndef YY_NO_INPUT + +#ifdef __cplusplus +static int yyinput (void ); +#else +static int input (void ); +#endif + +#endif + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#define YY_READ_BUF_SIZE 8192 +#endif + +/* Copy whatever the last rule matched to the standard output. */ +#ifndef ECHO +/* This used to be an fputs(), but since the string might contain NUL's, + * we now use fwrite(). + */ +#define ECHO fwrite( zconftext, zconfleng, 1, zconfout ) +#endif + +/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, + * is returned in "result". + */ +#ifndef YY_INPUT +#define YY_INPUT(buf,result,max_size) \ + errno=0; \ + while ( (result = read( fileno(zconfin), (char *) buf, max_size )) < 0 ) \ + { \ + if( errno != EINTR) \ + { \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + break; \ + } \ + errno=0; \ + clearerr(zconfin); \ + }\ +\ + +#endif + +/* No semi-colon after return; correct usage is to write "yyterminate();" - + * we don't want an extra ';' after the "return" because that will cause + * some compilers to complain about unreachable statements. + */ +#ifndef yyterminate +#define yyterminate() return YY_NULL +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Report a fatal error. */ +#ifndef YY_FATAL_ERROR +#define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) +#endif + +/* end tables serialization structures and prototypes */ + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL_IS_OURS 1 + +extern int zconflex (void); + +#define YY_DECL int zconflex (void) +#endif /* !YY_DECL */ + +/* Code executed at the beginning of each rule, after zconftext and zconfleng + * have been set up. + */ +#ifndef YY_USER_ACTION +#define YY_USER_ACTION +#endif + +/* Code executed at the end of each rule. */ +#ifndef YY_BREAK +#define YY_BREAK break; +#endif + +#define YY_RULE_SETUP \ + YY_USER_ACTION + +/** The main scanner function which does all the work. + */ +YY_DECL +{ + register yy_state_type yy_current_state; + register char *yy_cp, *yy_bp; + register int yy_act; + + int str = 0; + int ts, i; + + if ( !(yy_init) ) + { + (yy_init) = 1; + +#ifdef YY_USER_INIT + YY_USER_INIT; +#endif + + if ( ! (yy_start) ) + (yy_start) = 1; /* first start state */ + + if ( ! zconfin ) + zconfin = stdin; + + if ( ! zconfout ) + zconfout = stdout; + + if ( ! YY_CURRENT_BUFFER ) { + zconfensure_buffer_stack (); + YY_CURRENT_BUFFER_LVALUE = + zconf_create_buffer(zconfin,YY_BUF_SIZE ); + } + + zconf_load_buffer_state( ); + } + + while ( 1 ) /* loops until end-of-file is reached */ + { + yy_cp = (yy_c_buf_p); + + /* Support of zconftext. */ + *yy_cp = (yy_hold_char); + + /* yy_bp points to the position in yy_ch_buf of the start of + * the current run. + */ + yy_bp = yy_cp; + + yy_current_state = (yy_start); +yy_match: + while ( (yy_current_state = yy_nxt[yy_current_state][ yy_ec[YY_SC_TO_UI(*yy_cp)] ]) > 0 ) + ++yy_cp; + + yy_current_state = -yy_current_state; + +yy_find_action: + yy_act = yy_accept[yy_current_state]; + + YY_DO_BEFORE_ACTION; + +do_action: /* This label is used only to access EOF actions. */ + + switch ( yy_act ) + { /* beginning of action switch */ +case 1: +/* rule 1 can match eol */ +case 2: +/* rule 2 can match eol */ +YY_RULE_SETUP +{ + current_file->lineno++; + return T_EOL; +} + YY_BREAK +case 3: +YY_RULE_SETUP + + YY_BREAK +case 4: +YY_RULE_SETUP +{ + BEGIN(COMMAND); +} + YY_BREAK +case 5: +YY_RULE_SETUP +{ + unput(zconftext[0]); + BEGIN(COMMAND); +} + YY_BREAK + +case 6: +YY_RULE_SETUP +{ + struct kconf_id *id = kconf_id_lookup(zconftext, zconfleng); + BEGIN(PARAM); + current_pos.file = current_file; + current_pos.lineno = current_file->lineno; + if (id && id->flags & TF_COMMAND) { + zconflval.id = id; + return id->token; + } + alloc_string(zconftext, zconfleng); + zconflval.string = text; + return T_WORD; + } + YY_BREAK +case 7: +YY_RULE_SETUP + + YY_BREAK +case 8: +/* rule 8 can match eol */ +YY_RULE_SETUP +{ + BEGIN(INITIAL); + current_file->lineno++; + return T_EOL; + } + YY_BREAK + +case 9: +YY_RULE_SETUP +return T_AND; + YY_BREAK +case 10: +YY_RULE_SETUP +return T_OR; + YY_BREAK +case 11: +YY_RULE_SETUP +return T_OPEN_PAREN; + YY_BREAK +case 12: +YY_RULE_SETUP +return T_CLOSE_PAREN; + YY_BREAK +case 13: +YY_RULE_SETUP +return T_NOT; + YY_BREAK +case 14: +YY_RULE_SETUP +return T_EQUAL; + YY_BREAK +case 15: +YY_RULE_SETUP +return T_UNEQUAL; + YY_BREAK +case 16: +YY_RULE_SETUP +{ + str = zconftext[0]; + new_string(); + BEGIN(STRING); + } + YY_BREAK +case 17: +/* rule 17 can match eol */ +YY_RULE_SETUP +BEGIN(INITIAL); current_file->lineno++; return T_EOL; + YY_BREAK +case 18: +YY_RULE_SETUP +/* ignore */ + YY_BREAK +case 19: +YY_RULE_SETUP +{ + struct kconf_id *id = kconf_id_lookup(zconftext, zconfleng); + if (id && id->flags & TF_PARAM) { + zconflval.id = id; + return id->token; + } + alloc_string(zconftext, zconfleng); + zconflval.string = text; + return T_WORD; + } + YY_BREAK +case 20: +YY_RULE_SETUP +/* comment */ + YY_BREAK +case 21: +/* rule 21 can match eol */ +YY_RULE_SETUP +current_file->lineno++; + YY_BREAK +case 22: +YY_RULE_SETUP + + YY_BREAK +case YY_STATE_EOF(PARAM): +{ + BEGIN(INITIAL); + } + YY_BREAK + +case 23: +/* rule 23 can match eol */ +*yy_cp = (yy_hold_char); /* undo effects of setting up zconftext */ +(yy_c_buf_p) = yy_cp -= 1; +YY_DO_BEFORE_ACTION; /* set up zconftext again */ +YY_RULE_SETUP +{ + append_string(zconftext, zconfleng); + zconflval.string = text; + return T_WORD_QUOTE; + } + YY_BREAK +case 24: +YY_RULE_SETUP +{ + append_string(zconftext, zconfleng); + } + YY_BREAK +case 25: +/* rule 25 can match eol */ +*yy_cp = (yy_hold_char); /* undo effects of setting up zconftext */ +(yy_c_buf_p) = yy_cp -= 1; +YY_DO_BEFORE_ACTION; /* set up zconftext again */ +YY_RULE_SETUP +{ + append_string(zconftext + 1, zconfleng - 1); + zconflval.string = text; + return T_WORD_QUOTE; + } + YY_BREAK +case 26: +YY_RULE_SETUP +{ + append_string(zconftext + 1, zconfleng - 1); + } + YY_BREAK +case 27: +YY_RULE_SETUP +{ + if (str == zconftext[0]) { + BEGIN(PARAM); + zconflval.string = text; + return T_WORD_QUOTE; + } else + append_string(zconftext, 1); + } + YY_BREAK +case 28: +/* rule 28 can match eol */ +YY_RULE_SETUP +{ + printf("%s:%d:warning: multi-line strings not supported\n", zconf_curname(), zconf_lineno()); + current_file->lineno++; + BEGIN(INITIAL); + return T_EOL; + } + YY_BREAK +case YY_STATE_EOF(STRING): +{ + BEGIN(INITIAL); + } + YY_BREAK + +case 29: +YY_RULE_SETUP +{ + ts = 0; + for (i = 0; i < zconfleng; i++) { + if (zconftext[i] == '\t') + ts = (ts & ~7) + 8; + else + ts++; + } + last_ts = ts; + if (first_ts) { + if (ts < first_ts) { + zconf_endhelp(); + return T_HELPTEXT; + } + ts -= first_ts; + while (ts > 8) { + append_string(" ", 8); + ts -= 8; + } + append_string(" ", ts); + } + } + YY_BREAK +case 30: +/* rule 30 can match eol */ +*yy_cp = (yy_hold_char); /* undo effects of setting up zconftext */ +(yy_c_buf_p) = yy_cp -= 1; +YY_DO_BEFORE_ACTION; /* set up zconftext again */ +YY_RULE_SETUP +{ + current_file->lineno++; + zconf_endhelp(); + return T_HELPTEXT; + } + YY_BREAK +case 31: +/* rule 31 can match eol */ +YY_RULE_SETUP +{ + current_file->lineno++; + append_string("\n", 1); + } + YY_BREAK +case 32: +YY_RULE_SETUP +{ + while (zconfleng) { + if ((zconftext[zconfleng-1] != ' ') && (zconftext[zconfleng-1] != '\t')) + break; + zconfleng--; + } + append_string(zconftext, zconfleng); + if (!first_ts) + first_ts = last_ts; + } + YY_BREAK +case YY_STATE_EOF(HELP): +{ + zconf_endhelp(); + return T_HELPTEXT; + } + YY_BREAK + +case YY_STATE_EOF(INITIAL): +case YY_STATE_EOF(COMMAND): +{ + if (current_file) { + zconf_endfile(); + return T_EOL; + } + fclose(zconfin); + yyterminate(); +} + YY_BREAK +case 33: +YY_RULE_SETUP +YY_FATAL_ERROR( "flex scanner jammed" ); + YY_BREAK + + case YY_END_OF_BUFFER: + { + /* Amount of text matched not including the EOB char. */ + int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1; + + /* Undo the effects of YY_DO_BEFORE_ACTION. */ + *yy_cp = (yy_hold_char); + YY_RESTORE_YY_MORE_OFFSET + + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW ) + { + /* We're scanning a new file or input source. It's + * possible that this happened because the user + * just pointed zconfin at a new source and called + * zconflex(). If so, then we have to assure + * consistency between YY_CURRENT_BUFFER and our + * globals. Here is the right place to do so, because + * this is the first action (other than possibly a + * back-up) that will match for the new input source. + */ + (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + YY_CURRENT_BUFFER_LVALUE->yy_input_file = zconfin; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; + } + + /* Note that here we test for yy_c_buf_p "<=" to the position + * of the first EOB in the buffer, since yy_c_buf_p will + * already have been incremented past the NUL character + * (since all states make transitions on EOB to the + * end-of-buffer state). Contrast this with the test + * in input(). + */ + if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) + { /* This was really a NUL. */ + yy_state_type yy_next_state; + + (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state( ); + + /* Okay, we're now positioned to make the NUL + * transition. We couldn't have + * yy_get_previous_state() go ahead and do it + * for us because it doesn't know how to deal + * with the possibility of jamming (and we don't + * want to build jamming into it because then it + * will run more slowly). + */ + + yy_next_state = yy_try_NUL_trans( yy_current_state ); + + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + + if ( yy_next_state ) + { + /* Consume the NUL. */ + yy_cp = ++(yy_c_buf_p); + yy_current_state = yy_next_state; + goto yy_match; + } + + else + { + yy_cp = (yy_c_buf_p); + goto yy_find_action; + } + } + + else switch ( yy_get_next_buffer( ) ) + { + case EOB_ACT_END_OF_FILE: + { + (yy_did_buffer_switch_on_eof) = 0; + + if ( zconfwrap( ) ) + { + /* Note: because we've taken care in + * yy_get_next_buffer() to have set up + * zconftext, we can now set up + * yy_c_buf_p so that if some total + * hoser (like flex itself) wants to + * call the scanner after we return the + * YY_NULL, it'll still work - another + * YY_NULL will get returned. + */ + (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ; + + yy_act = YY_STATE_EOF(YY_START); + goto do_action; + } + + else + { + if ( ! (yy_did_buffer_switch_on_eof) ) + YY_NEW_FILE; + } + break; + } + + case EOB_ACT_CONTINUE_SCAN: + (yy_c_buf_p) = + (yytext_ptr) + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state( ); + + yy_cp = (yy_c_buf_p); + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + goto yy_match; + + case EOB_ACT_LAST_MATCH: + (yy_c_buf_p) = + &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)]; + + yy_current_state = yy_get_previous_state( ); + + yy_cp = (yy_c_buf_p); + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + goto yy_find_action; + } + break; + } + + default: + YY_FATAL_ERROR( + "fatal flex scanner internal error--no action found" ); + } /* end of action switch */ + } /* end of scanning one token */ +} /* end of zconflex */ + +/* yy_get_next_buffer - try to read in a new buffer + * + * Returns a code representing an action: + * EOB_ACT_LAST_MATCH - + * EOB_ACT_CONTINUE_SCAN - continue scanning from current position + * EOB_ACT_END_OF_FILE - end of file + */ +static int yy_get_next_buffer (void) +{ + register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; + register char *source = (yytext_ptr); + register int number_to_move, i; + int ret_val; + + if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] ) + YY_FATAL_ERROR( + "fatal flex scanner internal error--end of buffer missed" ); + + if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 ) + { /* Don't try to fill the buffer, so this is an EOF. */ + if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 ) + { + /* We matched a single character, the EOB, so + * treat this as a final EOF. + */ + return EOB_ACT_END_OF_FILE; + } + + else + { + /* We matched some text prior to the EOB, first + * process it. + */ + return EOB_ACT_LAST_MATCH; + } + } + + /* Try to read more data. */ + + /* First move last chars to start of buffer. */ + number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1; + + for ( i = 0; i < number_to_move; ++i ) + *(dest++) = *(source++); + + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING ) + /* don't do the read, it's not guaranteed to return an EOF, + * just force an EOF + */ + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0; + + else + { + int num_to_read = + YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; + + while ( num_to_read <= 0 ) + { /* Not enough room in the buffer - grow it. */ + + /* just a shorter name for the current buffer */ + YY_BUFFER_STATE b = YY_CURRENT_BUFFER; + + int yy_c_buf_p_offset = + (int) ((yy_c_buf_p) - b->yy_ch_buf); + + if ( b->yy_is_our_buffer ) + { + int new_size = b->yy_buf_size * 2; + + if ( new_size <= 0 ) + b->yy_buf_size += b->yy_buf_size / 8; + else + b->yy_buf_size *= 2; + + b->yy_ch_buf = (char *) + /* Include room in for 2 EOB chars. */ + zconfrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ); + } + else + /* Can't grow it, we don't own it. */ + b->yy_ch_buf = 0; + + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( + "fatal error - scanner input buffer overflow" ); + + (yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset]; + + num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - + number_to_move - 1; + + } + + if ( num_to_read > YY_READ_BUF_SIZE ) + num_to_read = YY_READ_BUF_SIZE; + + /* Read in more data. */ + YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), + (yy_n_chars), (size_t) num_to_read ); + + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + if ( (yy_n_chars) == 0 ) + { + if ( number_to_move == YY_MORE_ADJ ) + { + ret_val = EOB_ACT_END_OF_FILE; + zconfrestart(zconfin ); + } + + else + { + ret_val = EOB_ACT_LAST_MATCH; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = + YY_BUFFER_EOF_PENDING; + } + } + + else + ret_val = EOB_ACT_CONTINUE_SCAN; + + if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { + /* Extend the array by 50%, plus the number we really need. */ + yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1); + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) zconfrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ); + if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" ); + } + + (yy_n_chars) += number_to_move; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR; + + (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; + + return ret_val; +} + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + + static yy_state_type yy_get_previous_state (void) +{ + register yy_state_type yy_current_state; + register char *yy_cp; + + yy_current_state = (yy_start); + + for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp ) + { + yy_current_state = yy_nxt[yy_current_state][(*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1)]; + } + + return yy_current_state; +} + +/* yy_try_NUL_trans - try to make a transition on the NUL character + * + * synopsis + * next_state = yy_try_NUL_trans( current_state ); + */ + static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state ) +{ + register int yy_is_jam; + + yy_current_state = yy_nxt[yy_current_state][1]; + yy_is_jam = (yy_current_state <= 0); + + return yy_is_jam ? 0 : yy_current_state; +} + + static void yyunput (int c, register char * yy_bp ) +{ + register char *yy_cp; + + yy_cp = (yy_c_buf_p); + + /* undo effects of setting up zconftext */ + *yy_cp = (yy_hold_char); + + if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) + { /* need to shift things up to make room */ + /* +2 for EOB chars. */ + register int number_to_move = (yy_n_chars) + 2; + register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[ + YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2]; + register char *source = + &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]; + + while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) + *--dest = *--source; + + yy_cp += (int) (dest - source); + yy_bp += (int) (dest - source); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = + (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_buf_size; + + if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) + YY_FATAL_ERROR( "flex scanner push-back overflow" ); + } + + *--yy_cp = (char) c; + + (yytext_ptr) = yy_bp; + (yy_hold_char) = *yy_cp; + (yy_c_buf_p) = yy_cp; +} + +#ifndef YY_NO_INPUT +#ifdef __cplusplus + static int yyinput (void) +#else + static int input (void) +#endif + +{ + int c; + + *(yy_c_buf_p) = (yy_hold_char); + + if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR ) + { + /* yy_c_buf_p now points to the character we want to return. + * If this occurs *before* the EOB characters, then it's a + * valid NUL; if not, then we've hit the end of the buffer. + */ + if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) + /* This was really a NUL. */ + *(yy_c_buf_p) = '\0'; + + else + { /* need more input */ + int offset = (yy_c_buf_p) - (yytext_ptr); + ++(yy_c_buf_p); + + switch ( yy_get_next_buffer( ) ) + { + case EOB_ACT_LAST_MATCH: + /* This happens because yy_g_n_b() + * sees that we've accumulated a + * token and flags that we need to + * try matching the token before + * proceeding. But for input(), + * there's no matching to consider. + * So convert the EOB_ACT_LAST_MATCH + * to EOB_ACT_END_OF_FILE. + */ + + /* Reset buffer status. */ + zconfrestart(zconfin ); + + /*FALLTHROUGH*/ + + case EOB_ACT_END_OF_FILE: + { + if ( zconfwrap( ) ) + return EOF; + + if ( ! (yy_did_buffer_switch_on_eof) ) + YY_NEW_FILE; +#ifdef __cplusplus + return yyinput(); +#else + return input(); +#endif + } + + case EOB_ACT_CONTINUE_SCAN: + (yy_c_buf_p) = (yytext_ptr) + offset; + break; + } + } + } + + c = *(unsigned char *) (yy_c_buf_p); /* cast for 8-bit char's */ + *(yy_c_buf_p) = '\0'; /* preserve zconftext */ + (yy_hold_char) = *++(yy_c_buf_p); + + return c; +} +#endif /* ifndef YY_NO_INPUT */ + +/** Immediately switch to a different input stream. + * @param input_file A readable stream. + * + * @note This function does not reset the start condition to @c INITIAL . + */ + void zconfrestart (FILE * input_file ) +{ + + if ( ! YY_CURRENT_BUFFER ){ + zconfensure_buffer_stack (); + YY_CURRENT_BUFFER_LVALUE = + zconf_create_buffer(zconfin,YY_BUF_SIZE ); + } + + zconf_init_buffer(YY_CURRENT_BUFFER,input_file ); + zconf_load_buffer_state( ); +} + +/** Switch to a different input buffer. + * @param new_buffer The new input buffer. + * + */ + void zconf_switch_to_buffer (YY_BUFFER_STATE new_buffer ) +{ + + /* TODO. We should be able to replace this entire function body + * with + * zconfpop_buffer_state(); + * zconfpush_buffer_state(new_buffer); + */ + zconfensure_buffer_stack (); + if ( YY_CURRENT_BUFFER == new_buffer ) + return; + + if ( YY_CURRENT_BUFFER ) + { + /* Flush out information for old buffer. */ + *(yy_c_buf_p) = (yy_hold_char); + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + YY_CURRENT_BUFFER_LVALUE = new_buffer; + zconf_load_buffer_state( ); + + /* We don't actually know whether we did this switch during + * EOF (zconfwrap()) processing, but the only time this flag + * is looked at is after zconfwrap() is called, so it's safe + * to go ahead and always set it. + */ + (yy_did_buffer_switch_on_eof) = 1; +} + +static void zconf_load_buffer_state (void) +{ + (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; + zconfin = YY_CURRENT_BUFFER_LVALUE->yy_input_file; + (yy_hold_char) = *(yy_c_buf_p); +} + +/** Allocate and initialize an input buffer state. + * @param file A readable stream. + * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. + * + * @return the allocated buffer state. + */ + YY_BUFFER_STATE zconf_create_buffer (FILE * file, int size ) +{ + YY_BUFFER_STATE b; + + b = (YY_BUFFER_STATE) zconfalloc(sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in zconf_create_buffer()" ); + + b->yy_buf_size = size; + + /* yy_ch_buf has to be 2 characters longer than the size given because + * we need to put in 2 end-of-buffer characters. + */ + b->yy_ch_buf = (char *) zconfalloc(b->yy_buf_size + 2 ); + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in zconf_create_buffer()" ); + + b->yy_is_our_buffer = 1; + + zconf_init_buffer(b,file ); + + return b; +} + +/** Destroy the buffer. + * @param b a buffer created with zconf_create_buffer() + * + */ + void zconf_delete_buffer (YY_BUFFER_STATE b ) +{ + + if ( ! b ) + return; + + if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */ + YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; + + if ( b->yy_is_our_buffer ) + zconffree((void *) b->yy_ch_buf ); + + zconffree((void *) b ); +} + +/* Initializes or reinitializes a buffer. + * This function is sometimes called more than once on the same buffer, + * such as during a zconfrestart() or at EOF. + */ + static void zconf_init_buffer (YY_BUFFER_STATE b, FILE * file ) + +{ + int oerrno = errno; + + zconf_flush_buffer(b ); + + b->yy_input_file = file; + b->yy_fill_buffer = 1; + + /* If b is the current buffer, then zconf_init_buffer was _probably_ + * called from zconfrestart() or through yy_get_next_buffer. + * In that case, we don't want to reset the lineno or column. + */ + if (b != YY_CURRENT_BUFFER){ + b->yy_bs_lineno = 1; + b->yy_bs_column = 0; + } + + b->yy_is_interactive = 0; + + errno = oerrno; +} + +/** Discard all buffered characters. On the next scan, YY_INPUT will be called. + * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. + * + */ + void zconf_flush_buffer (YY_BUFFER_STATE b ) +{ + if ( ! b ) + return; + + b->yy_n_chars = 0; + + /* We always need two end-of-buffer characters. The first causes + * a transition to the end-of-buffer state. The second causes + * a jam in that state. + */ + b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; + b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; + + b->yy_buf_pos = &b->yy_ch_buf[0]; + + b->yy_at_bol = 1; + b->yy_buffer_status = YY_BUFFER_NEW; + + if ( b == YY_CURRENT_BUFFER ) + zconf_load_buffer_state( ); +} + +/** Pushes the new state onto the stack. The new state becomes + * the current state. This function will allocate the stack + * if necessary. + * @param new_buffer The new state. + * + */ +void zconfpush_buffer_state (YY_BUFFER_STATE new_buffer ) +{ + if (new_buffer == NULL) + return; + + zconfensure_buffer_stack(); + + /* This block is copied from zconf_switch_to_buffer. */ + if ( YY_CURRENT_BUFFER ) + { + /* Flush out information for old buffer. */ + *(yy_c_buf_p) = (yy_hold_char); + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + /* Only push if top exists. Otherwise, replace top. */ + if (YY_CURRENT_BUFFER) + (yy_buffer_stack_top)++; + YY_CURRENT_BUFFER_LVALUE = new_buffer; + + /* copied from zconf_switch_to_buffer. */ + zconf_load_buffer_state( ); + (yy_did_buffer_switch_on_eof) = 1; +} + +/** Removes and deletes the top of the stack, if present. + * The next element becomes the new top. + * + */ +void zconfpop_buffer_state (void) +{ + if (!YY_CURRENT_BUFFER) + return; + + zconf_delete_buffer(YY_CURRENT_BUFFER ); + YY_CURRENT_BUFFER_LVALUE = NULL; + if ((yy_buffer_stack_top) > 0) + --(yy_buffer_stack_top); + + if (YY_CURRENT_BUFFER) { + zconf_load_buffer_state( ); + (yy_did_buffer_switch_on_eof) = 1; + } +} + +/* Allocates the stack if it does not exist. + * Guarantees space for at least one push. + */ +static void zconfensure_buffer_stack (void) +{ + int num_to_alloc; + + if (!(yy_buffer_stack)) { + + /* First allocation is just for 2 elements, since we don't know if this + * scanner will even need a stack. We use 2 instead of 1 to avoid an + * immediate realloc on the next call. + */ + num_to_alloc = 1; + (yy_buffer_stack) = (struct yy_buffer_state**)zconfalloc + (num_to_alloc * sizeof(struct yy_buffer_state*) + ); + if ( ! (yy_buffer_stack) ) + YY_FATAL_ERROR( "out of dynamic memory in zconfensure_buffer_stack()" ); + + memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*)); + + (yy_buffer_stack_max) = num_to_alloc; + (yy_buffer_stack_top) = 0; + return; + } + + if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){ + + /* Increase the buffer to prepare for a possible push. */ + int grow_size = 8 /* arbitrary grow size */; + + num_to_alloc = (yy_buffer_stack_max) + grow_size; + (yy_buffer_stack) = (struct yy_buffer_state**)zconfrealloc + ((yy_buffer_stack), + num_to_alloc * sizeof(struct yy_buffer_state*) + ); + if ( ! (yy_buffer_stack) ) + YY_FATAL_ERROR( "out of dynamic memory in zconfensure_buffer_stack()" ); + + /* zero only the new slots.*/ + memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*)); + (yy_buffer_stack_max) = num_to_alloc; + } +} + +/** Setup the input buffer state to scan directly from a user-specified character buffer. + * @param base the character buffer + * @param size the size in bytes of the character buffer + * + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE zconf_scan_buffer (char * base, yy_size_t size ) +{ + YY_BUFFER_STATE b; + + if ( size < 2 || + base[size-2] != YY_END_OF_BUFFER_CHAR || + base[size-1] != YY_END_OF_BUFFER_CHAR ) + /* They forgot to leave room for the EOB's. */ + return 0; + + b = (YY_BUFFER_STATE) zconfalloc(sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in zconf_scan_buffer()" ); + + b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ + b->yy_buf_pos = b->yy_ch_buf = base; + b->yy_is_our_buffer = 0; + b->yy_input_file = 0; + b->yy_n_chars = b->yy_buf_size; + b->yy_is_interactive = 0; + b->yy_at_bol = 1; + b->yy_fill_buffer = 0; + b->yy_buffer_status = YY_BUFFER_NEW; + + zconf_switch_to_buffer(b ); + + return b; +} + +/** Setup the input buffer state to scan a string. The next call to zconflex() will + * scan from a @e copy of @a str. + * @param yystr a NUL-terminated string to scan + * + * @return the newly allocated buffer state object. + * @note If you want to scan bytes that may contain NUL values, then use + * zconf_scan_bytes() instead. + */ +YY_BUFFER_STATE zconf_scan_string (yyconst char * yystr ) +{ + + return zconf_scan_bytes(yystr,strlen(yystr) ); +} + +/** Setup the input buffer state to scan the given bytes. The next call to zconflex() will + * scan from a @e copy of @a bytes. + * @param bytes the byte buffer to scan + * @param len the number of bytes in the buffer pointed to by @a bytes. + * + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE zconf_scan_bytes (yyconst char * yybytes, int _yybytes_len ) +{ + YY_BUFFER_STATE b; + char *buf; + yy_size_t n; + int i; + + /* Get memory for full buffer, including space for trailing EOB's. */ + n = _yybytes_len + 2; + buf = (char *) zconfalloc(n ); + if ( ! buf ) + YY_FATAL_ERROR( "out of dynamic memory in zconf_scan_bytes()" ); + + for ( i = 0; i < _yybytes_len; ++i ) + buf[i] = yybytes[i]; + + buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR; + + b = zconf_scan_buffer(buf,n ); + if ( ! b ) + YY_FATAL_ERROR( "bad buffer in zconf_scan_bytes()" ); + + /* It's okay to grow etc. this buffer, and we should throw it + * away when we're done. + */ + b->yy_is_our_buffer = 1; + + return b; +} + +#ifndef YY_EXIT_FAILURE +#define YY_EXIT_FAILURE 2 +#endif + +static void yy_fatal_error (yyconst char* msg ) +{ + (void) fprintf( stderr, "%s\n", msg ); + exit( YY_EXIT_FAILURE ); +} + +/* Redefine yyless() so it works in section 3 code. */ + +#undef yyless +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up zconftext. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + zconftext[zconfleng] = (yy_hold_char); \ + (yy_c_buf_p) = zconftext + yyless_macro_arg; \ + (yy_hold_char) = *(yy_c_buf_p); \ + *(yy_c_buf_p) = '\0'; \ + zconfleng = yyless_macro_arg; \ + } \ + while ( 0 ) + +/* Accessor methods (get/set functions) to struct members. */ + +/** Get the current line number. + * + */ +int zconfget_lineno (void) +{ + + return zconflineno; +} + +/** Get the input stream. + * + */ +FILE *zconfget_in (void) +{ + return zconfin; +} + +/** Get the output stream. + * + */ +FILE *zconfget_out (void) +{ + return zconfout; +} + +/** Get the length of the current token. + * + */ +int zconfget_leng (void) +{ + return zconfleng; +} + +/** Get the current token. + * + */ + +char *zconfget_text (void) +{ + return zconftext; +} + +/** Set the current line number. + * @param line_number + * + */ +void zconfset_lineno (int line_number ) +{ + + zconflineno = line_number; +} + +/** Set the input stream. This does not discard the current + * input buffer. + * @param in_str A readable stream. + * + * @see zconf_switch_to_buffer + */ +void zconfset_in (FILE * in_str ) +{ + zconfin = in_str ; +} + +void zconfset_out (FILE * out_str ) +{ + zconfout = out_str ; +} + +int zconfget_debug (void) +{ + return zconf_flex_debug; +} + +void zconfset_debug (int bdebug ) +{ + zconf_flex_debug = bdebug ; +} + +static int yy_init_globals (void) +{ + /* Initialization is the same as for the non-reentrant scanner. + * This function is called from zconflex_destroy(), so don't allocate here. + */ + + (yy_buffer_stack) = 0; + (yy_buffer_stack_top) = 0; + (yy_buffer_stack_max) = 0; + (yy_c_buf_p) = (char *) 0; + (yy_init) = 0; + (yy_start) = 0; + +/* Defined in main.c */ +#ifdef YY_STDINIT + zconfin = stdin; + zconfout = stdout; +#else + zconfin = (FILE *) 0; + zconfout = (FILE *) 0; +#endif + + /* For future reference: Set errno on error, since we are called by + * zconflex_init() + */ + return 0; +} + +/* zconflex_destroy is for both reentrant and non-reentrant scanners. */ +int zconflex_destroy (void) +{ + + /* Pop the buffer stack, destroying each element. */ + while(YY_CURRENT_BUFFER){ + zconf_delete_buffer(YY_CURRENT_BUFFER ); + YY_CURRENT_BUFFER_LVALUE = NULL; + zconfpop_buffer_state(); + } + + /* Destroy the stack itself. */ + zconffree((yy_buffer_stack) ); + (yy_buffer_stack) = NULL; + + /* Reset the globals. This is important in a non-reentrant scanner so the next time + * zconflex() is called, initialization will occur. */ + yy_init_globals( ); + + return 0; +} + +/* + * Internal utility routines. + */ + +#ifndef yytext_ptr +static void yy_flex_strncpy (char* s1, yyconst char * s2, int n ) +{ + register int i; + for ( i = 0; i < n; ++i ) + s1[i] = s2[i]; +} +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen (yyconst char * s ) +{ + register int n; + for ( n = 0; s[n]; ++n ) + ; + + return n; +} +#endif + +void *zconfalloc (yy_size_t size ) +{ + return (void *) malloc( size ); +} + +void *zconfrealloc (void * ptr, yy_size_t size ) +{ + /* The cast to (char *) in the following accommodates both + * implementations that use char* generic pointers, and those + * that use void* generic pointers. It works with the latter + * because both ANSI C and C++ allow castless assignment from + * any pointer type to void*, and deal with argument conversions + * as though doing an assignment. + */ + return (void *) realloc( (char *) ptr, size ); +} + +void zconffree (void * ptr ) +{ + free( (char *) ptr ); /* see zconfrealloc() for (char *) cast */ +} + +#define YYTABLES_NAME "yytables" + +void zconf_starthelp(void) +{ + new_string(); + last_ts = first_ts = 0; + BEGIN(HELP); +} + +static void zconf_endhelp(void) +{ + zconflval.string = text; + BEGIN(INITIAL); +} + +/* + * Try to open specified file with following names: + * ./name + * $(srctree)/name + * The latter is used when srctree is separate from objtree + * when compiling the kernel. + * Return NULL if file is not found. + */ +FILE *zconf_fopen(const char *name) +{ + char *env, fullname[PATH_MAX+1]; + FILE *f; + + f = fopen(name, "r"); + if (!f && name != NULL && name[0] != '/') { + env = getenv(SRCTREE); + if (env) { + sprintf(fullname, "%s/%s", env, name); + f = fopen(fullname, "r"); + } + } + return f; +} + +void zconf_initscan(const char *name) +{ + zconfin = zconf_fopen(name); + if (!zconfin) { + printf("can't find file %s\n", name); + exit(1); + } + + current_buf = malloc(sizeof(*current_buf)); + memset(current_buf, 0, sizeof(*current_buf)); + + current_file = file_lookup(name); + current_file->lineno = 1; + current_file->flags = FILE_BUSY; +} + +void zconf_nextfile(const char *name) +{ + struct file *file = file_lookup(name); + struct buffer *buf = malloc(sizeof(*buf)); + memset(buf, 0, sizeof(*buf)); + + current_buf->state = YY_CURRENT_BUFFER; + zconfin = zconf_fopen(name); + if (!zconfin) { + printf("%s:%d: can't open file \"%s\"\n", zconf_curname(), zconf_lineno(), name); + exit(1); + } + zconf_switch_to_buffer(zconf_create_buffer(zconfin,YY_BUF_SIZE)); + buf->parent = current_buf; + current_buf = buf; + + if (file->flags & FILE_BUSY) { + printf("%s:%d: do not source '%s' from itself\n", + zconf_curname(), zconf_lineno(), name); + exit(1); + } + if (file->flags & FILE_SCANNED) { + printf("%s:%d: file '%s' is already sourced from '%s'\n", + zconf_curname(), zconf_lineno(), name, + file->parent->name); + exit(1); + } + file->flags |= FILE_BUSY; + file->lineno = 1; + file->parent = current_file; + current_file = file; +} + +static void zconf_endfile(void) +{ + struct buffer *parent; + + current_file->flags |= FILE_SCANNED; + current_file->flags &= ~FILE_BUSY; + current_file = current_file->parent; + + parent = current_buf->parent; + if (parent) { + fclose(zconfin); + zconf_delete_buffer(YY_CURRENT_BUFFER); + zconf_switch_to_buffer(parent->state); + } + free(current_buf); + current_buf = parent; +} + +int zconf_lineno(void) +{ + return current_pos.lineno; +} + +char *zconf_curname(void) +{ + return current_pos.file ? current_pos.file->name : ""; +} + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/lkc.h b/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/lkc.h new file mode 100644 index 00000000..4a9af6f7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/lkc.h @@ -0,0 +1,168 @@ +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +#ifndef LKC_H +#define LKC_H + +#include "expr.h" + +#ifndef KBUILD_NO_NLS +# include +#else +static inline const char *gettext(const char *txt) { return txt; } +static inline void textdomain(const char *domainname) {} +static inline void bindtextdomain(const char *name, const char *dir) {} +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef LKC_DIRECT_LINK +#define P(name,type,arg) extern type name arg +#else +#include "lkc_defs.h" +#define P(name,type,arg) extern type (*name ## _p) arg +#endif +#include "lkc_proto.h" +#undef P + +#define SRCTREE "srctree" + +#define PACKAGE "linux" +#define LOCALEDIR "/usr/share/locale" + +#define _(text) gettext(text) +#define N_(text) (text) + + +#define TF_COMMAND 0x0001 +#define TF_PARAM 0x0002 +#define TF_OPTION 0x0004 + +enum conf_def_mode { + def_default, + def_yes, + def_mod, + def_no, + def_random +}; + +#define T_OPT_MODULES 1 +#define T_OPT_DEFCONFIG_LIST 2 +#define T_OPT_ENV 3 + +struct kconf_id { + int name; + int token; + unsigned int flags; + enum symbol_type stype; +}; + +int zconfparse(void); +void zconfdump(FILE *out); + +extern int zconfdebug; +void zconf_starthelp(void); +FILE *zconf_fopen(const char *name); +void zconf_initscan(const char *name); +void zconf_nextfile(const char *name); +int zconf_lineno(void); +char *zconf_curname(void); + +/* confdata.c */ +const char *conf_get_configname(void); +char *conf_get_default_confname(void); +void sym_set_change_count(int count); +void sym_add_change_count(int count); +void conf_set_all_new_symbols(enum conf_def_mode mode); + +/* kconfig_load.c */ +void kconfig_load(void); + +/* menu.c */ +void menu_init(void); +void menu_warn(struct menu *menu, const char *fmt, ...); +struct menu *menu_add_menu(void); +void menu_end_menu(void); +void menu_add_entry(struct symbol *sym); +void menu_end_entry(void); +void menu_add_dep(struct expr *dep); +struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *expr, struct expr *dep); +struct property *menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep); +void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep); +void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep); +void menu_add_option(int token, char *arg); +void menu_finalize(struct menu *parent); +void menu_set_type(int type); + +/* util.c */ +struct file *file_lookup(const char *name); +int file_write_dep(const char *name); + +struct gstr { + size_t len; + char *s; +}; +struct gstr str_new(void); +struct gstr str_assign(const char *s); +void str_free(struct gstr *gs); +void str_append(struct gstr *gs, const char *s); +void str_printf(struct gstr *gs, const char *fmt, ...); +const char *str_get(struct gstr *gs); + +/* symbol.c */ +extern struct expr *sym_env_list; + +void sym_init(void); +void sym_clear_all_valid(void); +void sym_set_all_changed(void); +void sym_set_changed(struct symbol *sym); +struct symbol *sym_check_deps(struct symbol *sym); +struct property *prop_alloc(enum prop_type type, struct symbol *sym); +struct symbol *prop_get_symbol(struct property *prop); +struct property *sym_get_env_prop(struct symbol *sym); + +static inline tristate sym_get_tristate_value(struct symbol *sym) +{ + return sym->curr.tri; +} + + +static inline struct symbol *sym_get_choice_value(struct symbol *sym) +{ + return (struct symbol *)sym->curr.val; +} + +static inline bool sym_set_choice_value(struct symbol *ch, struct symbol *chval) +{ + return sym_set_tristate_value(chval, yes); +} + +static inline bool sym_is_choice(struct symbol *sym) +{ + return sym->flags & SYMBOL_CHOICE ? true : false; +} + +static inline bool sym_is_choice_value(struct symbol *sym) +{ + return sym->flags & SYMBOL_CHOICEVAL ? true : false; +} + +static inline bool sym_is_optional(struct symbol *sym) +{ + return sym->flags & SYMBOL_OPTIONAL ? true : false; +} + +static inline bool sym_has_value(struct symbol *sym) +{ + return sym->flags & SYMBOL_DEF_USER ? true : false; +} + +#ifdef __cplusplus +} +#endif + +#endif /* LKC_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/lkc_proto.h b/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/lkc_proto.h new file mode 100644 index 00000000..8e694613 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/lkc_proto.h @@ -0,0 +1,45 @@ + +/* confdata.c */ +P(conf_parse,void,(const char *name)); +P(conf_read,int,(const char *name)); +P(conf_read_simple,int,(const char *name, int)); +P(conf_write,int,(const char *name)); +P(conf_write_autoconf,int,(void)); +P(conf_get_changed,bool,(void)); +P(conf_set_changed_callback, void,(void (*fn)(void))); + +/* menu.c */ +P(rootmenu,struct menu,); + +P(menu_is_visible,bool,(struct menu *menu)); +P(menu_get_prompt,const char *,(struct menu *menu)); +P(menu_get_root_menu,struct menu *,(struct menu *menu)); +P(menu_get_parent_menu,struct menu *,(struct menu *menu)); +P(menu_has_help,bool,(struct menu *menu)); +P(menu_get_help,const char *,(struct menu *menu)); + +/* symbol.c */ +P(symbol_hash,struct symbol *,[SYMBOL_HASHSIZE]); + +P(sym_lookup,struct symbol *,(const char *name, int flags)); +P(sym_find,struct symbol *,(const char *name)); +P(sym_re_search,struct symbol **,(const char *pattern)); +P(sym_type_name,const char *,(enum symbol_type type)); +P(sym_calc_value,void,(struct symbol *sym)); +P(sym_get_type,enum symbol_type,(struct symbol *sym)); +P(sym_tristate_within_range,bool,(struct symbol *sym,tristate tri)); +P(sym_set_tristate_value,bool,(struct symbol *sym,tristate tri)); +P(sym_toggle_tristate_value,tristate,(struct symbol *sym)); +P(sym_string_valid,bool,(struct symbol *sym, const char *newval)); +P(sym_string_within_range,bool,(struct symbol *sym, const char *str)); +P(sym_set_string_value,bool,(struct symbol *sym, const char *newval)); +P(sym_is_changable,bool,(struct symbol *sym)); +P(sym_get_choice_prop,struct property *,(struct symbol *sym)); +P(sym_get_default_prop,struct property *,(struct symbol *sym)); +P(sym_get_string_value,const char *,(struct symbol *sym)); + +P(prop_get_type_name,const char *,(enum prop_type type)); + +/* expr.c */ +P(expr_compare_type,int,(enum expr_type t1, enum expr_type t2)); +P(expr_print,void,(struct expr *e, void (*fn)(void *, struct symbol *, const char *), void *data, int prevtoken)); diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/lxdialog/.gitignore b/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/lxdialog/.gitignore new file mode 100644 index 00000000..90b08ff0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/lxdialog/.gitignore @@ -0,0 +1,4 @@ +# +# Generated files +# +lxdialog diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/lxdialog/BIG.FAT.WARNING b/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/lxdialog/BIG.FAT.WARNING new file mode 100644 index 00000000..a8999d82 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/lxdialog/BIG.FAT.WARNING @@ -0,0 +1,4 @@ +This is NOT the official version of dialog. This version has been +significantly modified from the original. It is for use by the Linux +kernel configuration script. Please do not bother Savio Lam with +questions about this program. diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/lxdialog/check-lxdialog.sh b/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/lxdialog/check-lxdialog.sh new file mode 100755 index 00000000..d34dfd46 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/lxdialog/check-lxdialog.sh @@ -0,0 +1,86 @@ +#!/bin/sh +# Check ncurses compatibility + +# What library to link +ldflags() +{ + for ext in so a dylib ; do + for lib in ncursesw ncurses curses ; do + $cc -print-file-name=lib${lib}.${ext} | grep -q / + if [ $? -eq 0 ]; then + echo "-l${lib}" + exit + fi + done + done + exit 1 +} + +# Where is ncurses.h? +ccflags() +{ + if [ -f /usr/include/ncursesw/ncurses.h ]; then + echo '-I/usr/include/ncursesw -DCURSES_LOC=""' + elif [ -f /usr/include/ncursesw/curses.h ]; then + echo '-I/usr/include/ncursesw -DCURSES_LOC=""' + elif [ -f /usr/include/ncurses/ncurses.h ]; then + echo '-I/usr/include/ncurses -DCURSES_LOC=""' + elif [ -f /usr/include/ncurses/curses.h ]; then + echo '-I/usr/include/ncurses -DCURSES_LOC=""' + elif [ -f /usr/include/ncurses.h ]; then + echo '-DCURSES_LOC=""' + else + echo '-DCURSES_LOC=""' + fi +} + +# Temp file, try to clean up after us +tmp=.lxdialog.tmp +trap "rm -f $tmp" 0 1 2 3 15 + +# Check if we can link to ncurses +check() { + $cc -xc - -o $tmp 2>/dev/null <<'EOF' +#include CURSES_LOC +main() {} +EOF + if [ $? != 0 ]; then + echo " *** Unable to find the ncurses libraries or the" 1>&2 + echo " *** required header files." 1>&2 + echo " *** 'make menuconfig' requires the ncurses libraries." 1>&2 + echo " *** " 1>&2 + echo " *** Install ncurses (ncurses-devel) and try again." 1>&2 + echo " *** " 1>&2 + exit 1 + fi +} + +usage() { + printf "Usage: $0 [-check compiler options|-ccflags|-ldflags compiler options]\n" +} + +if [ $# -eq 0 ]; then + usage + exit 1 +fi + +cc="" +case "$1" in + "-check") + shift + cc="$@" + check + ;; + "-ccflags") + ccflags + ;; + "-ldflags") + shift + cc="$@" + ldflags + ;; + "*") + usage + exit 1 + ;; +esac diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/lxdialog/checklist.c b/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/lxdialog/checklist.c new file mode 100644 index 00000000..b2a878c9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/lxdialog/checklist.c @@ -0,0 +1,325 @@ +/* + * checklist.c -- implements the checklist box + * + * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) + * Stuart Herbert - S.Herbert@sheffield.ac.uk: radiolist extension + * Alessandro Rubini - rubini@ipvvis.unipv.it: merged the two + * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "dialog.h" + +static int list_width, check_x, item_x; + +/* + * Print list item + */ +static void print_item(WINDOW * win, int choice, int selected) +{ + int i; + + /* Clear 'residue' of last item */ + wattrset(win, dlg.menubox.atr); + wmove(win, choice, 0); + for (i = 0; i < list_width; i++) + waddch(win, ' '); + + wmove(win, choice, check_x); + wattrset(win, selected ? dlg.check_selected.atr + : dlg.check.atr); + wprintw(win, "(%c)", item_is_tag('X') ? 'X' : ' '); + + wattrset(win, selected ? dlg.tag_selected.atr : dlg.tag.atr); + mvwaddch(win, choice, item_x, item_str()[0]); + wattrset(win, selected ? dlg.item_selected.atr : dlg.item.atr); + waddstr(win, (char *)item_str() + 1); + if (selected) { + wmove(win, choice, check_x + 1); + wrefresh(win); + } +} + +/* + * Print the scroll indicators. + */ +static void print_arrows(WINDOW * win, int choice, int item_no, int scroll, + int y, int x, int height) +{ + wmove(win, y, x); + + if (scroll > 0) { + wattrset(win, dlg.uarrow.atr); + waddch(win, ACS_UARROW); + waddstr(win, "(-)"); + } else { + wattrset(win, dlg.menubox.atr); + waddch(win, ACS_HLINE); + waddch(win, ACS_HLINE); + waddch(win, ACS_HLINE); + waddch(win, ACS_HLINE); + } + + y = y + height + 1; + wmove(win, y, x); + + if ((height < item_no) && (scroll + choice < item_no - 1)) { + wattrset(win, dlg.darrow.atr); + waddch(win, ACS_DARROW); + waddstr(win, "(+)"); + } else { + wattrset(win, dlg.menubox_border.atr); + waddch(win, ACS_HLINE); + waddch(win, ACS_HLINE); + waddch(win, ACS_HLINE); + waddch(win, ACS_HLINE); + } +} + +/* + * Display the termination buttons + */ +static void print_buttons(WINDOW * dialog, int height, int width, int selected) +{ + int x = width / 2 - 11; + int y = height - 2; + + print_button(dialog, gettext("Select"), y, x, selected == 0); + print_button(dialog, gettext(" Help "), y, x + 14, selected == 1); + + wmove(dialog, y, x + 1 + 14 * selected); + wrefresh(dialog); +} + +/* + * Display a dialog box with a list of options that can be turned on or off + * in the style of radiolist (only one option turned on at a time). + */ +int dialog_checklist(const char *title, const char *prompt, int height, + int width, int list_height) +{ + int i, x, y, box_x, box_y; + int key = 0, button = 0, choice = 0, scroll = 0, max_choice; + WINDOW *dialog, *list; + + /* which item to highlight */ + item_foreach() { + if (item_is_tag('X')) + choice = item_n(); + if (item_is_selected()) { + choice = item_n(); + break; + } + } + +do_resize: + if (getmaxy(stdscr) < (height + 6)) + return -ERRDISPLAYTOOSMALL; + if (getmaxx(stdscr) < (width + 6)) + return -ERRDISPLAYTOOSMALL; + + max_choice = MIN(list_height, item_count()); + + /* center dialog box on screen */ + x = (COLS - width) / 2; + y = (LINES - height) / 2; + + draw_shadow(stdscr, y, x, height, width); + + dialog = newwin(height, width, y, x); + keypad(dialog, TRUE); + + draw_box(dialog, 0, 0, height, width, + dlg.dialog.atr, dlg.border.atr); + wattrset(dialog, dlg.border.atr); + mvwaddch(dialog, height - 3, 0, ACS_LTEE); + for (i = 0; i < width - 2; i++) + waddch(dialog, ACS_HLINE); + wattrset(dialog, dlg.dialog.atr); + waddch(dialog, ACS_RTEE); + + print_title(dialog, title, width); + + wattrset(dialog, dlg.dialog.atr); + print_autowrap(dialog, prompt, width - 2, 1, 3); + + list_width = width - 6; + box_y = height - list_height - 5; + box_x = (width - list_width) / 2 - 1; + + /* create new window for the list */ + list = subwin(dialog, list_height, list_width, y + box_y + 1, + x + box_x + 1); + + keypad(list, TRUE); + + /* draw a box around the list items */ + draw_box(dialog, box_y, box_x, list_height + 2, list_width + 2, + dlg.menubox_border.atr, dlg.menubox.atr); + + /* Find length of longest item in order to center checklist */ + check_x = 0; + item_foreach() + check_x = MAX(check_x, strlen(item_str()) + 4); + + check_x = (list_width - check_x) / 2; + item_x = check_x + 4; + + if (choice >= list_height) { + scroll = choice - list_height + 1; + choice -= scroll; + } + + /* Print the list */ + for (i = 0; i < max_choice; i++) { + item_set(scroll + i); + print_item(list, i, i == choice); + } + + print_arrows(dialog, choice, item_count(), scroll, + box_y, box_x + check_x + 5, list_height); + + print_buttons(dialog, height, width, 0); + + wnoutrefresh(dialog); + wnoutrefresh(list); + doupdate(); + + while (key != KEY_ESC) { + key = wgetch(dialog); + + for (i = 0; i < max_choice; i++) { + item_set(i + scroll); + if (toupper(key) == toupper(item_str()[0])) + break; + } + + if (i < max_choice || key == KEY_UP || key == KEY_DOWN || + key == '+' || key == '-') { + if (key == KEY_UP || key == '-') { + if (!choice) { + if (!scroll) + continue; + /* Scroll list down */ + if (list_height > 1) { + /* De-highlight current first item */ + item_set(scroll); + print_item(list, 0, FALSE); + scrollok(list, TRUE); + wscrl(list, -1); + scrollok(list, FALSE); + } + scroll--; + item_set(scroll); + print_item(list, 0, TRUE); + print_arrows(dialog, choice, item_count(), + scroll, box_y, box_x + check_x + 5, list_height); + + wnoutrefresh(dialog); + wrefresh(list); + + continue; /* wait for another key press */ + } else + i = choice - 1; + } else if (key == KEY_DOWN || key == '+') { + if (choice == max_choice - 1) { + if (scroll + choice >= item_count() - 1) + continue; + /* Scroll list up */ + if (list_height > 1) { + /* De-highlight current last item before scrolling up */ + item_set(scroll + max_choice - 1); + print_item(list, + max_choice - 1, + FALSE); + scrollok(list, TRUE); + wscrl(list, 1); + scrollok(list, FALSE); + } + scroll++; + item_set(scroll + max_choice - 1); + print_item(list, max_choice - 1, TRUE); + + print_arrows(dialog, choice, item_count(), + scroll, box_y, box_x + check_x + 5, list_height); + + wnoutrefresh(dialog); + wrefresh(list); + + continue; /* wait for another key press */ + } else + i = choice + 1; + } + if (i != choice) { + /* De-highlight current item */ + item_set(scroll + choice); + print_item(list, choice, FALSE); + /* Highlight new item */ + choice = i; + item_set(scroll + choice); + print_item(list, choice, TRUE); + wnoutrefresh(dialog); + wrefresh(list); + } + continue; /* wait for another key press */ + } + switch (key) { + case 'H': + case 'h': + case '?': + button = 1; + /* fall-through */ + case 'S': + case 's': + case ' ': + case '\n': + item_foreach() + item_set_selected(0); + item_set(scroll + choice); + item_set_selected(1); + delwin(list); + delwin(dialog); + return button; + case TAB: + case KEY_LEFT: + case KEY_RIGHT: + button = ((key == KEY_LEFT ? --button : ++button) < 0) + ? 1 : (button > 1 ? 0 : button); + + print_buttons(dialog, height, width, button); + wrefresh(dialog); + break; + case 'X': + case 'x': + key = KEY_ESC; + break; + case KEY_ESC: + key = on_key_esc(dialog); + break; + case KEY_RESIZE: + delwin(list); + delwin(dialog); + on_key_resize(); + goto do_resize; + } + + /* Now, update everything... */ + doupdate(); + } + delwin(list); + delwin(dialog); + return key; /* ESC pressed */ +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/lxdialog/dialog.h b/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/lxdialog/dialog.h new file mode 100644 index 00000000..b5211fce --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/lxdialog/dialog.h @@ -0,0 +1,230 @@ +/* + * dialog.h -- common declarations for all dialog modules + * + * AUTHOR: Savio Lam (lam836@cs.cuhk.hk) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include + +#ifndef KBUILD_NO_NLS +# include +#else +# define gettext(Msgid) ((const char *) (Msgid)) +#endif + +#ifdef __sun__ +#define CURS_MACROS +#endif +#include CURSES_LOC + +/* + * Colors in ncurses 1.9.9e do not work properly since foreground and + * background colors are OR'd rather than separately masked. This version + * of dialog was hacked to work with ncurses 1.9.9e, making it incompatible + * with standard curses. The simplest fix (to make this work with standard + * curses) uses the wbkgdset() function, not used in the original hack. + * Turn it off if we're building with 1.9.9e, since it just confuses things. + */ +#if defined(NCURSES_VERSION) && defined(_NEED_WRAP) && !defined(GCC_PRINTFLIKE) +#define OLD_NCURSES 1 +#undef wbkgdset +#define wbkgdset(w,p) /*nothing */ +#else +#define OLD_NCURSES 0 +#endif + +#define TR(params) _tracef params + +#define KEY_ESC 27 +#define TAB 9 +#define MAX_LEN 2048 +#define BUF_SIZE (10*1024) +#define MIN(x,y) (x < y ? x : y) +#define MAX(x,y) (x > y ? x : y) + +#ifndef ACS_ULCORNER +#define ACS_ULCORNER '+' +#endif +#ifndef ACS_LLCORNER +#define ACS_LLCORNER '+' +#endif +#ifndef ACS_URCORNER +#define ACS_URCORNER '+' +#endif +#ifndef ACS_LRCORNER +#define ACS_LRCORNER '+' +#endif +#ifndef ACS_HLINE +#define ACS_HLINE '-' +#endif +#ifndef ACS_VLINE +#define ACS_VLINE '|' +#endif +#ifndef ACS_LTEE +#define ACS_LTEE '+' +#endif +#ifndef ACS_RTEE +#define ACS_RTEE '+' +#endif +#ifndef ACS_UARROW +#define ACS_UARROW '^' +#endif +#ifndef ACS_DARROW +#define ACS_DARROW 'v' +#endif + +/* error return codes */ +#define ERRDISPLAYTOOSMALL (KEY_MAX + 1) + +/* + * Color definitions + */ +struct dialog_color { + chtype atr; /* Color attribute */ + int fg; /* foreground */ + int bg; /* background */ + int hl; /* highlight this item */ +}; + +struct dialog_info { + const char *backtitle; + struct dialog_color screen; + struct dialog_color shadow; + struct dialog_color dialog; + struct dialog_color title; + struct dialog_color border; + struct dialog_color button_active; + struct dialog_color button_inactive; + struct dialog_color button_key_active; + struct dialog_color button_key_inactive; + struct dialog_color button_label_active; + struct dialog_color button_label_inactive; + struct dialog_color inputbox; + struct dialog_color inputbox_border; + struct dialog_color searchbox; + struct dialog_color searchbox_title; + struct dialog_color searchbox_border; + struct dialog_color position_indicator; + struct dialog_color menubox; + struct dialog_color menubox_border; + struct dialog_color item; + struct dialog_color item_selected; + struct dialog_color tag; + struct dialog_color tag_selected; + struct dialog_color tag_key; + struct dialog_color tag_key_selected; + struct dialog_color check; + struct dialog_color check_selected; + struct dialog_color uarrow; + struct dialog_color darrow; +}; + +/* + * Global variables + */ +extern struct dialog_info dlg; +extern char dialog_input_result[]; + +/* + * Function prototypes + */ + +/* item list as used by checklist and menubox */ +void item_reset(void); +void item_make(const char *fmt, ...); +void item_add_str(const char *fmt, ...); +void item_set_tag(char tag); +void item_set_data(void *p); +void item_set_selected(int val); +int item_activate_selected(void); +void *item_data(void); +char item_tag(void); + +/* item list manipulation for lxdialog use */ +#define MAXITEMSTR 200 +struct dialog_item { + char str[MAXITEMSTR]; /* promtp displayed */ + char tag; + void *data; /* pointer to menu item - used by menubox+checklist */ + int selected; /* Set to 1 by dialog_*() function if selected. */ +}; + +/* list of lialog_items */ +struct dialog_list { + struct dialog_item node; + struct dialog_list *next; +}; + +extern struct dialog_list *item_cur; +extern struct dialog_list item_nil; +extern struct dialog_list *item_head; + +int item_count(void); +void item_set(int n); +int item_n(void); +const char *item_str(void); +int item_is_selected(void); +int item_is_tag(char tag); +#define item_foreach() \ + for (item_cur = item_head ? item_head: item_cur; \ + item_cur && (item_cur != &item_nil); item_cur = item_cur->next) + +/* generic key handlers */ +int on_key_esc(WINDOW *win); +int on_key_resize(void); + +int init_dialog(const char *backtitle); +void set_dialog_backtitle(const char *backtitle); +void end_dialog(int x, int y); +void attr_clear(WINDOW * win, int height, int width, chtype attr); +void dialog_clear(void); +void print_autowrap(WINDOW * win, const char *prompt, int width, int y, int x); +void print_button(WINDOW * win, const char *label, int y, int x, int selected); +void print_title(WINDOW *dialog, const char *title, int width); +void draw_box(WINDOW * win, int y, int x, int height, int width, chtype box, + chtype border); +void draw_shadow(WINDOW * win, int y, int x, int height, int width); + +int first_alpha(const char *string, const char *exempt); +int dialog_yesno(const char *title, const char *prompt, int height, int width); +int dialog_msgbox(const char *title, const char *prompt, int height, + int width, int pause); +int dialog_textbox(const char *title, const char *file, int height, int width); +int dialog_menu(const char *title, const char *prompt, + const void *selected, int *s_scroll); +int dialog_checklist(const char *title, const char *prompt, int height, + int width, int list_height); +extern char dialog_input_result[]; +int dialog_inputbox(const char *title, const char *prompt, int height, + int width, const char *init); + +/* + * This is the base for fictitious keys, which activate + * the buttons. + * + * Mouse-generated keys are the following: + * -- the first 32 are used as numbers, in addition to '0'-'9' + * -- the lowercase are used to signal mouse-enter events (M_EVENT + 'o') + * -- uppercase chars are used to invoke the button (M_EVENT + 'O') + */ +#define M_EVENT (KEY_MAX+1) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/lxdialog/inputbox.c b/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/lxdialog/inputbox.c new file mode 100644 index 00000000..616c6013 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/lxdialog/inputbox.c @@ -0,0 +1,238 @@ +/* + * inputbox.c -- implements the input box + * + * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) + * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "dialog.h" + +char dialog_input_result[MAX_LEN + 1]; + +/* + * Print the termination buttons + */ +static void print_buttons(WINDOW * dialog, int height, int width, int selected) +{ + int x = width / 2 - 11; + int y = height - 2; + + print_button(dialog, gettext(" Ok "), y, x, selected == 0); + print_button(dialog, gettext(" Help "), y, x + 14, selected == 1); + + wmove(dialog, y, x + 1 + 14 * selected); + wrefresh(dialog); +} + +/* + * Display a dialog box for inputing a string + */ +int dialog_inputbox(const char *title, const char *prompt, int height, int width, + const char *init) +{ + int i, x, y, box_y, box_x, box_width; + int input_x = 0, scroll = 0, key = 0, button = -1; + char *instr = dialog_input_result; + WINDOW *dialog; + + if (!init) + instr[0] = '\0'; + else + strcpy(instr, init); + +do_resize: + if (getmaxy(stdscr) <= (height - 2)) + return -ERRDISPLAYTOOSMALL; + if (getmaxx(stdscr) <= (width - 2)) + return -ERRDISPLAYTOOSMALL; + + /* center dialog box on screen */ + x = (COLS - width) / 2; + y = (LINES - height) / 2; + + draw_shadow(stdscr, y, x, height, width); + + dialog = newwin(height, width, y, x); + keypad(dialog, TRUE); + + draw_box(dialog, 0, 0, height, width, + dlg.dialog.atr, dlg.border.atr); + wattrset(dialog, dlg.border.atr); + mvwaddch(dialog, height - 3, 0, ACS_LTEE); + for (i = 0; i < width - 2; i++) + waddch(dialog, ACS_HLINE); + wattrset(dialog, dlg.dialog.atr); + waddch(dialog, ACS_RTEE); + + print_title(dialog, title, width); + + wattrset(dialog, dlg.dialog.atr); + print_autowrap(dialog, prompt, width - 2, 1, 3); + + /* Draw the input field box */ + box_width = width - 6; + getyx(dialog, y, x); + box_y = y + 2; + box_x = (width - box_width) / 2; + draw_box(dialog, y + 1, box_x - 1, 3, box_width + 2, + dlg.dialog.atr, dlg.border.atr); + + print_buttons(dialog, height, width, 0); + + /* Set up the initial value */ + wmove(dialog, box_y, box_x); + wattrset(dialog, dlg.inputbox.atr); + + input_x = strlen(instr); + + if (input_x >= box_width) { + scroll = input_x - box_width + 1; + input_x = box_width - 1; + for (i = 0; i < box_width - 1; i++) + waddch(dialog, instr[scroll + i]); + } else { + waddstr(dialog, instr); + } + + wmove(dialog, box_y, box_x + input_x); + + wrefresh(dialog); + + while (key != KEY_ESC) { + key = wgetch(dialog); + + if (button == -1) { /* Input box selected */ + switch (key) { + case TAB: + case KEY_UP: + case KEY_DOWN: + break; + case KEY_LEFT: + continue; + case KEY_RIGHT: + continue; + case KEY_BACKSPACE: + case 127: + if (input_x || scroll) { + wattrset(dialog, dlg.inputbox.atr); + if (!input_x) { + scroll = scroll < box_width - 1 ? 0 : scroll - (box_width - 1); + wmove(dialog, box_y, box_x); + for (i = 0; i < box_width; i++) + waddch(dialog, + instr[scroll + input_x + i] ? + instr[scroll + input_x + i] : ' '); + input_x = strlen(instr) - scroll; + } else + input_x--; + instr[scroll + input_x] = '\0'; + mvwaddch(dialog, box_y, input_x + box_x, ' '); + wmove(dialog, box_y, input_x + box_x); + wrefresh(dialog); + } + continue; + default: + if (key < 0x100 && isprint(key)) { + if (scroll + input_x < MAX_LEN) { + wattrset(dialog, dlg.inputbox.atr); + instr[scroll + input_x] = key; + instr[scroll + input_x + 1] = '\0'; + if (input_x == box_width - 1) { + scroll++; + wmove(dialog, box_y, box_x); + for (i = 0; i < box_width - 1; i++) + waddch(dialog, instr [scroll + i]); + } else { + wmove(dialog, box_y, input_x++ + box_x); + waddch(dialog, key); + } + wrefresh(dialog); + } else + flash(); /* Alarm user about overflow */ + continue; + } + } + } + switch (key) { + case 'O': + case 'o': + delwin(dialog); + return 0; + case 'H': + case 'h': + delwin(dialog); + return 1; + case KEY_UP: + case KEY_LEFT: + switch (button) { + case -1: + button = 1; /* Indicates "Cancel" button is selected */ + print_buttons(dialog, height, width, 1); + break; + case 0: + button = -1; /* Indicates input box is selected */ + print_buttons(dialog, height, width, 0); + wmove(dialog, box_y, box_x + input_x); + wrefresh(dialog); + break; + case 1: + button = 0; /* Indicates "OK" button is selected */ + print_buttons(dialog, height, width, 0); + break; + } + break; + case TAB: + case KEY_DOWN: + case KEY_RIGHT: + switch (button) { + case -1: + button = 0; /* Indicates "OK" button is selected */ + print_buttons(dialog, height, width, 0); + break; + case 0: + button = 1; /* Indicates "Cancel" button is selected */ + print_buttons(dialog, height, width, 1); + break; + case 1: + button = -1; /* Indicates input box is selected */ + print_buttons(dialog, height, width, 0); + wmove(dialog, box_y, box_x + input_x); + wrefresh(dialog); + break; + } + break; + case ' ': + case '\n': + delwin(dialog); + return (button == -1 ? 0 : button); + case 'X': + case 'x': + key = KEY_ESC; + break; + case KEY_ESC: + key = on_key_esc(dialog); + break; + case KEY_RESIZE: + delwin(dialog); + on_key_resize(); + goto do_resize; + } + } + + delwin(dialog); + return KEY_ESC; /* ESC pressed */ +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/lxdialog/menubox.c b/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/lxdialog/menubox.c new file mode 100644 index 00000000..c689fc03 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/lxdialog/menubox.c @@ -0,0 +1,434 @@ +/* + * menubox.c -- implements the menu box + * + * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) + * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcapw@cfw.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* + * Changes by Clifford Wolf (god@clifford.at) + * + * [ 1998-06-13 ] + * + * *) A bugfix for the Page-Down problem + * + * *) Formerly when I used Page Down and Page Up, the cursor would be set + * to the first position in the menu box. Now lxdialog is a bit + * smarter and works more like other menu systems (just have a look at + * it). + * + * *) Formerly if I selected something my scrolling would be broken because + * lxdialog is re-invoked by the Menuconfig shell script, can't + * remember the last scrolling position, and just sets it so that the + * cursor is at the bottom of the box. Now it writes the temporary file + * lxdialog.scrltmp which contains this information. The file is + * deleted by lxdialog if the user leaves a submenu or enters a new + * one, but it would be nice if Menuconfig could make another "rm -f" + * just to be sure. Just try it out - you will recognise a difference! + * + * [ 1998-06-14 ] + * + * *) Now lxdialog is crash-safe against broken "lxdialog.scrltmp" files + * and menus change their size on the fly. + * + * *) If for some reason the last scrolling position is not saved by + * lxdialog, it sets the scrolling so that the selected item is in the + * middle of the menu box, not at the bottom. + * + * 02 January 1999, Michael Elizabeth Chastain (mec@shout.net) + * Reset 'scroll' to 0 if the value from lxdialog.scrltmp is bogus. + * This fixes a bug in Menuconfig where using ' ' to descend into menus + * would leave mis-synchronized lxdialog.scrltmp files lying around, + * fscanf would read in 'scroll', and eventually that value would get used. + */ + +#include "dialog.h" + +static int menu_width, item_x; + +/* + * Print menu item + */ +static void do_print_item(WINDOW * win, const char *item, int line_y, + int selected, int hotkey) +{ + int j; + char *menu_item = malloc(menu_width + 1); + + strncpy(menu_item, item, menu_width - item_x); + menu_item[menu_width - item_x] = '\0'; + j = first_alpha(menu_item, "YyNnMmHh"); + + /* Clear 'residue' of last item */ + wattrset(win, dlg.menubox.atr); + wmove(win, line_y, 0); +#if OLD_NCURSES + { + int i; + for (i = 0; i < menu_width; i++) + waddch(win, ' '); + } +#else + wclrtoeol(win); +#endif + wattrset(win, selected ? dlg.item_selected.atr : dlg.item.atr); + mvwaddstr(win, line_y, item_x, menu_item); + if (hotkey) { + wattrset(win, selected ? dlg.tag_key_selected.atr + : dlg.tag_key.atr); + mvwaddch(win, line_y, item_x + j, menu_item[j]); + } + if (selected) { + wmove(win, line_y, item_x + 1); + } + free(menu_item); + wrefresh(win); +} + +#define print_item(index, choice, selected) \ +do { \ + item_set(index); \ + do_print_item(menu, item_str(), choice, selected, !item_is_tag(':')); \ +} while (0) + +/* + * Print the scroll indicators. + */ +static void print_arrows(WINDOW * win, int item_no, int scroll, int y, int x, + int height) +{ + int cur_y, cur_x; + + getyx(win, cur_y, cur_x); + + wmove(win, y, x); + + if (scroll > 0) { + wattrset(win, dlg.uarrow.atr); + waddch(win, ACS_UARROW); + waddstr(win, "(-)"); + } else { + wattrset(win, dlg.menubox.atr); + waddch(win, ACS_HLINE); + waddch(win, ACS_HLINE); + waddch(win, ACS_HLINE); + waddch(win, ACS_HLINE); + } + + y = y + height + 1; + wmove(win, y, x); + wrefresh(win); + + if ((height < item_no) && (scroll + height < item_no)) { + wattrset(win, dlg.darrow.atr); + waddch(win, ACS_DARROW); + waddstr(win, "(+)"); + } else { + wattrset(win, dlg.menubox_border.atr); + waddch(win, ACS_HLINE); + waddch(win, ACS_HLINE); + waddch(win, ACS_HLINE); + waddch(win, ACS_HLINE); + } + + wmove(win, cur_y, cur_x); + wrefresh(win); +} + +/* + * Display the termination buttons. + */ +static void print_buttons(WINDOW * win, int height, int width, int selected) +{ + int x = width / 2 - 16; + int y = height - 2; + + print_button(win, gettext("Select"), y, x, selected == 0); + print_button(win, gettext(" Exit "), y, x + 12, selected == 1); + print_button(win, gettext(" Help "), y, x + 24, selected == 2); + + wmove(win, y, x + 1 + 12 * selected); + wrefresh(win); +} + +/* scroll up n lines (n may be negative) */ +static void do_scroll(WINDOW *win, int *scroll, int n) +{ + /* Scroll menu up */ + scrollok(win, TRUE); + wscrl(win, n); + scrollok(win, FALSE); + *scroll = *scroll + n; + wrefresh(win); +} + +/* + * Display a menu for choosing among a number of options + */ +int dialog_menu(const char *title, const char *prompt, + const void *selected, int *s_scroll) +{ + int i, j, x, y, box_x, box_y; + int height, width, menu_height; + int key = 0, button = 0, scroll = 0, choice = 0; + int first_item = 0, max_choice; + WINDOW *dialog, *menu; + +do_resize: + height = getmaxy(stdscr); + width = getmaxx(stdscr); + if (height < 15 || width < 65) + return -ERRDISPLAYTOOSMALL; + + height -= 4; + width -= 5; + menu_height = height - 10; + + max_choice = MIN(menu_height, item_count()); + + /* center dialog box on screen */ + x = (COLS - width) / 2; + y = (LINES - height) / 2; + + draw_shadow(stdscr, y, x, height, width); + + dialog = newwin(height, width, y, x); + keypad(dialog, TRUE); + + draw_box(dialog, 0, 0, height, width, + dlg.dialog.atr, dlg.border.atr); + wattrset(dialog, dlg.border.atr); + mvwaddch(dialog, height - 3, 0, ACS_LTEE); + for (i = 0; i < width - 2; i++) + waddch(dialog, ACS_HLINE); + wattrset(dialog, dlg.dialog.atr); + wbkgdset(dialog, dlg.dialog.atr & A_COLOR); + waddch(dialog, ACS_RTEE); + + print_title(dialog, title, width); + + wattrset(dialog, dlg.dialog.atr); + print_autowrap(dialog, prompt, width - 2, 1, 3); + + menu_width = width - 6; + box_y = height - menu_height - 5; + box_x = (width - menu_width) / 2 - 1; + + /* create new window for the menu */ + menu = subwin(dialog, menu_height, menu_width, + y + box_y + 1, x + box_x + 1); + keypad(menu, TRUE); + + /* draw a box around the menu items */ + draw_box(dialog, box_y, box_x, menu_height + 2, menu_width + 2, + dlg.menubox_border.atr, dlg.menubox.atr); + + if (menu_width >= 80) + item_x = (menu_width - 70) / 2; + else + item_x = 4; + + /* Set choice to default item */ + item_foreach() + if (selected && (selected == item_data())) + choice = item_n(); + /* get the saved scroll info */ + scroll = *s_scroll; + if ((scroll <= choice) && (scroll + max_choice > choice) && + (scroll >= 0) && (scroll + max_choice <= item_count())) { + first_item = scroll; + choice = choice - scroll; + } else { + scroll = 0; + } + if ((choice >= max_choice)) { + if (choice >= item_count() - max_choice / 2) + scroll = first_item = item_count() - max_choice; + else + scroll = first_item = choice - max_choice / 2; + choice = choice - scroll; + } + + /* Print the menu */ + for (i = 0; i < max_choice; i++) { + print_item(first_item + i, i, i == choice); + } + + wnoutrefresh(menu); + + print_arrows(dialog, item_count(), scroll, + box_y, box_x + item_x + 1, menu_height); + + print_buttons(dialog, height, width, 0); + wmove(menu, choice, item_x + 1); + wrefresh(menu); + + while (key != KEY_ESC) { + key = wgetch(menu); + + if (key < 256 && isalpha(key)) + key = tolower(key); + + if (strchr("ynmh", key)) + i = max_choice; + else { + for (i = choice + 1; i < max_choice; i++) { + item_set(scroll + i); + j = first_alpha(item_str(), "YyNnMmHh"); + if (key == tolower(item_str()[j])) + break; + } + if (i == max_choice) + for (i = 0; i < max_choice; i++) { + item_set(scroll + i); + j = first_alpha(item_str(), "YyNnMmHh"); + if (key == tolower(item_str()[j])) + break; + } + } + + if (i < max_choice || + key == KEY_UP || key == KEY_DOWN || + key == '-' || key == '+' || + key == KEY_PPAGE || key == KEY_NPAGE) { + /* Remove highligt of current item */ + print_item(scroll + choice, choice, FALSE); + + if (key == KEY_UP || key == '-') { + if (choice < 2 && scroll) { + /* Scroll menu down */ + do_scroll(menu, &scroll, -1); + + print_item(scroll, 0, FALSE); + } else + choice = MAX(choice - 1, 0); + + } else if (key == KEY_DOWN || key == '+') { + print_item(scroll+choice, choice, FALSE); + + if ((choice > max_choice - 3) && + (scroll + max_choice < item_count())) { + /* Scroll menu up */ + do_scroll(menu, &scroll, 1); + + print_item(scroll+max_choice - 1, + max_choice - 1, FALSE); + } else + choice = MIN(choice + 1, max_choice - 1); + + } else if (key == KEY_PPAGE) { + scrollok(menu, TRUE); + for (i = 0; (i < max_choice); i++) { + if (scroll > 0) { + do_scroll(menu, &scroll, -1); + print_item(scroll, 0, FALSE); + } else { + if (choice > 0) + choice--; + } + } + + } else if (key == KEY_NPAGE) { + for (i = 0; (i < max_choice); i++) { + if (scroll + max_choice < item_count()) { + do_scroll(menu, &scroll, 1); + print_item(scroll+max_choice-1, + max_choice - 1, FALSE); + } else { + if (choice + 1 < max_choice) + choice++; + } + } + } else + choice = i; + + print_item(scroll + choice, choice, TRUE); + + print_arrows(dialog, item_count(), scroll, + box_y, box_x + item_x + 1, menu_height); + + wnoutrefresh(dialog); + wrefresh(menu); + + continue; /* wait for another key press */ + } + + switch (key) { + case KEY_LEFT: + case TAB: + case KEY_RIGHT: + button = ((key == KEY_LEFT ? --button : ++button) < 0) + ? 2 : (button > 2 ? 0 : button); + + print_buttons(dialog, height, width, button); + wrefresh(menu); + break; + case ' ': + case 's': + case 'y': + case 'n': + case 'm': + case '/': + /* save scroll info */ + *s_scroll = scroll; + delwin(menu); + delwin(dialog); + item_set(scroll + choice); + item_set_selected(1); + switch (key) { + case 's': + return 3; + case 'y': + return 3; + case 'n': + return 4; + case 'm': + return 5; + case ' ': + return 6; + case '/': + return 7; + } + return 0; + case 'h': + case '?': + button = 2; + case '\n': + *s_scroll = scroll; + delwin(menu); + delwin(dialog); + item_set(scroll + choice); + item_set_selected(1); + return button; + case 'e': + case 'x': + key = KEY_ESC; + break; + case KEY_ESC: + key = on_key_esc(menu); + break; + case KEY_RESIZE: + on_key_resize(); + delwin(menu); + delwin(dialog); + goto do_resize; + } + } + delwin(menu); + delwin(dialog); + return key; /* ESC pressed */ +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/lxdialog/textbox.c b/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/lxdialog/textbox.c new file mode 100644 index 00000000..c704712d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/lxdialog/textbox.c @@ -0,0 +1,391 @@ +/* + * textbox.c -- implements the text box + * + * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) + * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "dialog.h" + +static void back_lines(int n); +static void print_page(WINDOW * win, int height, int width); +static void print_line(WINDOW * win, int row, int width); +static char *get_line(void); +static void print_position(WINDOW * win); + +static int hscroll; +static int begin_reached, end_reached, page_length; +static const char *buf; +static const char *page; + +/* + * refresh window content + */ +static void refresh_text_box(WINDOW *dialog, WINDOW *box, int boxh, int boxw, + int cur_y, int cur_x) +{ + print_page(box, boxh, boxw); + print_position(dialog); + wmove(dialog, cur_y, cur_x); /* Restore cursor position */ + wrefresh(dialog); +} + + +/* + * Display text from a file in a dialog box. + */ +int dialog_textbox(const char *title, const char *tbuf, + int initial_height, int initial_width) +{ + int i, x, y, cur_x, cur_y, key = 0; + int height, width, boxh, boxw; + int passed_end; + WINDOW *dialog, *box; + + begin_reached = 1; + end_reached = 0; + page_length = 0; + hscroll = 0; + buf = tbuf; + page = buf; /* page is pointer to start of page to be displayed */ + +do_resize: + getmaxyx(stdscr, height, width); + if (height < 8 || width < 8) + return -ERRDISPLAYTOOSMALL; + if (initial_height != 0) + height = initial_height; + else + if (height > 4) + height -= 4; + else + height = 0; + if (initial_width != 0) + width = initial_width; + else + if (width > 5) + width -= 5; + else + width = 0; + + /* center dialog box on screen */ + x = (COLS - width) / 2; + y = (LINES - height) / 2; + + draw_shadow(stdscr, y, x, height, width); + + dialog = newwin(height, width, y, x); + keypad(dialog, TRUE); + + /* Create window for box region, used for scrolling text */ + boxh = height - 4; + boxw = width - 2; + box = subwin(dialog, boxh, boxw, y + 1, x + 1); + wattrset(box, dlg.dialog.atr); + wbkgdset(box, dlg.dialog.atr & A_COLOR); + + keypad(box, TRUE); + + /* register the new window, along with its borders */ + draw_box(dialog, 0, 0, height, width, + dlg.dialog.atr, dlg.border.atr); + + wattrset(dialog, dlg.border.atr); + mvwaddch(dialog, height - 3, 0, ACS_LTEE); + for (i = 0; i < width - 2; i++) + waddch(dialog, ACS_HLINE); + wattrset(dialog, dlg.dialog.atr); + wbkgdset(dialog, dlg.dialog.atr & A_COLOR); + waddch(dialog, ACS_RTEE); + + print_title(dialog, title, width); + + print_button(dialog, gettext(" Exit "), height - 2, width / 2 - 4, TRUE); + wnoutrefresh(dialog); + getyx(dialog, cur_y, cur_x); /* Save cursor position */ + + /* Print first page of text */ + attr_clear(box, boxh, boxw, dlg.dialog.atr); + refresh_text_box(dialog, box, boxh, boxw, cur_y, cur_x); + + while ((key != KEY_ESC) && (key != '\n')) { + key = wgetch(dialog); + switch (key) { + case 'E': /* Exit */ + case 'e': + case 'X': + case 'x': + delwin(box); + delwin(dialog); + return 0; + case 'g': /* First page */ + case KEY_HOME: + if (!begin_reached) { + begin_reached = 1; + page = buf; + refresh_text_box(dialog, box, boxh, boxw, + cur_y, cur_x); + } + break; + case 'G': /* Last page */ + case KEY_END: + + end_reached = 1; + /* point to last char in buf */ + page = buf + strlen(buf); + back_lines(boxh); + refresh_text_box(dialog, box, boxh, boxw, + cur_y, cur_x); + break; + case 'K': /* Previous line */ + case 'k': + case KEY_UP: + if (!begin_reached) { + back_lines(page_length + 1); + + /* We don't call print_page() here but use + * scrolling to ensure faster screen update. + * However, 'end_reached' and 'page_length' + * should still be updated, and 'page' should + * point to start of next page. This is done + * by calling get_line() in the following + * 'for' loop. */ + scrollok(box, TRUE); + wscrl(box, -1); /* Scroll box region down one line */ + scrollok(box, FALSE); + page_length = 0; + passed_end = 0; + for (i = 0; i < boxh; i++) { + if (!i) { + /* print first line of page */ + print_line(box, 0, boxw); + wnoutrefresh(box); + } else + /* Called to update 'end_reached' and 'page' */ + get_line(); + if (!passed_end) + page_length++; + if (end_reached && !passed_end) + passed_end = 1; + } + + print_position(dialog); + wmove(dialog, cur_y, cur_x); /* Restore cursor position */ + wrefresh(dialog); + } + break; + case 'B': /* Previous page */ + case 'b': + case KEY_PPAGE: + if (begin_reached) + break; + back_lines(page_length + boxh); + refresh_text_box(dialog, box, boxh, boxw, + cur_y, cur_x); + break; + case 'J': /* Next line */ + case 'j': + case KEY_DOWN: + if (!end_reached) { + begin_reached = 0; + scrollok(box, TRUE); + scroll(box); /* Scroll box region up one line */ + scrollok(box, FALSE); + print_line(box, boxh - 1, boxw); + wnoutrefresh(box); + print_position(dialog); + wmove(dialog, cur_y, cur_x); /* Restore cursor position */ + wrefresh(dialog); + } + break; + case KEY_NPAGE: /* Next page */ + case ' ': + if (end_reached) + break; + + begin_reached = 0; + refresh_text_box(dialog, box, boxh, boxw, + cur_y, cur_x); + break; + case '0': /* Beginning of line */ + case 'H': /* Scroll left */ + case 'h': + case KEY_LEFT: + if (hscroll <= 0) + break; + + if (key == '0') + hscroll = 0; + else + hscroll--; + /* Reprint current page to scroll horizontally */ + back_lines(page_length); + refresh_text_box(dialog, box, boxh, boxw, + cur_y, cur_x); + break; + case 'L': /* Scroll right */ + case 'l': + case KEY_RIGHT: + if (hscroll >= MAX_LEN) + break; + hscroll++; + /* Reprint current page to scroll horizontally */ + back_lines(page_length); + refresh_text_box(dialog, box, boxh, boxw, + cur_y, cur_x); + break; + case KEY_ESC: + key = on_key_esc(dialog); + break; + case KEY_RESIZE: + back_lines(height); + delwin(box); + delwin(dialog); + on_key_resize(); + goto do_resize; + } + } + delwin(box); + delwin(dialog); + return key; /* ESC pressed */ +} + +/* + * Go back 'n' lines in text. Called by dialog_textbox(). + * 'page' will be updated to point to the desired line in 'buf'. + */ +static void back_lines(int n) +{ + int i; + + begin_reached = 0; + /* Go back 'n' lines */ + for (i = 0; i < n; i++) { + if (*page == '\0') { + if (end_reached) { + end_reached = 0; + continue; + } + } + if (page == buf) { + begin_reached = 1; + return; + } + page--; + do { + if (page == buf) { + begin_reached = 1; + return; + } + page--; + } while (*page != '\n'); + page++; + } +} + +/* + * Print a new page of text. Called by dialog_textbox(). + */ +static void print_page(WINDOW * win, int height, int width) +{ + int i, passed_end = 0; + + page_length = 0; + for (i = 0; i < height; i++) { + print_line(win, i, width); + if (!passed_end) + page_length++; + if (end_reached && !passed_end) + passed_end = 1; + } + wnoutrefresh(win); +} + +/* + * Print a new line of text. Called by dialog_textbox() and print_page(). + */ +static void print_line(WINDOW * win, int row, int width) +{ + int y, x; + char *line; + + line = get_line(); + line += MIN(strlen(line), hscroll); /* Scroll horizontally */ + wmove(win, row, 0); /* move cursor to correct line */ + waddch(win, ' '); + waddnstr(win, line, MIN(strlen(line), width - 2)); + + getyx(win, y, x); + /* Clear 'residue' of previous line */ +#if OLD_NCURSES + { + int i; + for (i = 0; i < width - x; i++) + waddch(win, ' '); + } +#else + wclrtoeol(win); +#endif +} + +/* + * Return current line of text. Called by dialog_textbox() and print_line(). + * 'page' should point to start of current line before calling, and will be + * updated to point to start of next line. + */ +static char *get_line(void) +{ + int i = 0; + static char line[MAX_LEN + 1]; + + end_reached = 0; + while (*page != '\n') { + if (*page == '\0') { + if (!end_reached) { + end_reached = 1; + break; + } + } else if (i < MAX_LEN) + line[i++] = *(page++); + else { + /* Truncate lines longer than MAX_LEN characters */ + if (i == MAX_LEN) + line[i++] = '\0'; + page++; + } + } + if (i <= MAX_LEN) + line[i] = '\0'; + if (!end_reached) + page++; /* move pass '\n' */ + + return line; +} + +/* + * Print current position + */ +static void print_position(WINDOW * win) +{ + int percent; + + wattrset(win, dlg.position_indicator.atr); + wbkgdset(win, dlg.position_indicator.atr & A_COLOR); + percent = (page - buf) * 100 / strlen(buf); + wmove(win, getmaxy(win) - 3, getmaxx(win) - 9); + wprintw(win, "(%3d%%)", percent); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/lxdialog/util.c b/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/lxdialog/util.c new file mode 100644 index 00000000..86d95cca --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/lxdialog/util.c @@ -0,0 +1,655 @@ +/* + * util.c + * + * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) + * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "dialog.h" + +struct dialog_info dlg; + +static void set_mono_theme(void) +{ + dlg.screen.atr = A_NORMAL; + dlg.shadow.atr = A_NORMAL; + dlg.dialog.atr = A_NORMAL; + dlg.title.atr = A_BOLD; + dlg.border.atr = A_NORMAL; + dlg.button_active.atr = A_REVERSE; + dlg.button_inactive.atr = A_DIM; + dlg.button_key_active.atr = A_REVERSE; + dlg.button_key_inactive.atr = A_BOLD; + dlg.button_label_active.atr = A_REVERSE; + dlg.button_label_inactive.atr = A_NORMAL; + dlg.inputbox.atr = A_NORMAL; + dlg.inputbox_border.atr = A_NORMAL; + dlg.searchbox.atr = A_NORMAL; + dlg.searchbox_title.atr = A_BOLD; + dlg.searchbox_border.atr = A_NORMAL; + dlg.position_indicator.atr = A_BOLD; + dlg.menubox.atr = A_NORMAL; + dlg.menubox_border.atr = A_NORMAL; + dlg.item.atr = A_NORMAL; + dlg.item_selected.atr = A_REVERSE; + dlg.tag.atr = A_BOLD; + dlg.tag_selected.atr = A_REVERSE; + dlg.tag_key.atr = A_BOLD; + dlg.tag_key_selected.atr = A_REVERSE; + dlg.check.atr = A_BOLD; + dlg.check_selected.atr = A_REVERSE; + dlg.uarrow.atr = A_BOLD; + dlg.darrow.atr = A_BOLD; +} + +#define DLG_COLOR(dialog, f, b, h) \ +do { \ + dlg.dialog.fg = (f); \ + dlg.dialog.bg = (b); \ + dlg.dialog.hl = (h); \ +} while (0) + +static void set_classic_theme(void) +{ + DLG_COLOR(screen, COLOR_CYAN, COLOR_BLUE, true); + DLG_COLOR(shadow, COLOR_BLACK, COLOR_BLACK, true); + DLG_COLOR(dialog, COLOR_BLACK, COLOR_WHITE, false); + DLG_COLOR(title, COLOR_YELLOW, COLOR_WHITE, true); + DLG_COLOR(border, COLOR_WHITE, COLOR_WHITE, true); + DLG_COLOR(button_active, COLOR_WHITE, COLOR_BLUE, true); + DLG_COLOR(button_inactive, COLOR_BLACK, COLOR_WHITE, false); + DLG_COLOR(button_key_active, COLOR_WHITE, COLOR_BLUE, true); + DLG_COLOR(button_key_inactive, COLOR_RED, COLOR_WHITE, false); + DLG_COLOR(button_label_active, COLOR_YELLOW, COLOR_BLUE, true); + DLG_COLOR(button_label_inactive, COLOR_BLACK, COLOR_WHITE, true); + DLG_COLOR(inputbox, COLOR_BLACK, COLOR_WHITE, false); + DLG_COLOR(inputbox_border, COLOR_BLACK, COLOR_WHITE, false); + DLG_COLOR(searchbox, COLOR_BLACK, COLOR_WHITE, false); + DLG_COLOR(searchbox_title, COLOR_YELLOW, COLOR_WHITE, true); + DLG_COLOR(searchbox_border, COLOR_WHITE, COLOR_WHITE, true); + DLG_COLOR(position_indicator, COLOR_YELLOW, COLOR_WHITE, true); + DLG_COLOR(menubox, COLOR_BLACK, COLOR_WHITE, false); + DLG_COLOR(menubox_border, COLOR_WHITE, COLOR_WHITE, true); + DLG_COLOR(item, COLOR_BLACK, COLOR_WHITE, false); + DLG_COLOR(item_selected, COLOR_WHITE, COLOR_BLUE, true); + DLG_COLOR(tag, COLOR_YELLOW, COLOR_WHITE, true); + DLG_COLOR(tag_selected, COLOR_YELLOW, COLOR_BLUE, true); + DLG_COLOR(tag_key, COLOR_YELLOW, COLOR_WHITE, true); + DLG_COLOR(tag_key_selected, COLOR_YELLOW, COLOR_BLUE, true); + DLG_COLOR(check, COLOR_BLACK, COLOR_WHITE, false); + DLG_COLOR(check_selected, COLOR_WHITE, COLOR_BLUE, true); + DLG_COLOR(uarrow, COLOR_GREEN, COLOR_WHITE, true); + DLG_COLOR(darrow, COLOR_GREEN, COLOR_WHITE, true); +} + +static void set_blackbg_theme(void) +{ + DLG_COLOR(screen, COLOR_RED, COLOR_BLACK, true); + DLG_COLOR(shadow, COLOR_BLACK, COLOR_BLACK, false); + DLG_COLOR(dialog, COLOR_WHITE, COLOR_BLACK, false); + DLG_COLOR(title, COLOR_RED, COLOR_BLACK, false); + DLG_COLOR(border, COLOR_BLACK, COLOR_BLACK, true); + + DLG_COLOR(button_active, COLOR_YELLOW, COLOR_RED, false); + DLG_COLOR(button_inactive, COLOR_YELLOW, COLOR_BLACK, false); + DLG_COLOR(button_key_active, COLOR_YELLOW, COLOR_RED, true); + DLG_COLOR(button_key_inactive, COLOR_RED, COLOR_BLACK, false); + DLG_COLOR(button_label_active, COLOR_WHITE, COLOR_RED, false); + DLG_COLOR(button_label_inactive, COLOR_BLACK, COLOR_BLACK, true); + + DLG_COLOR(inputbox, COLOR_YELLOW, COLOR_BLACK, false); + DLG_COLOR(inputbox_border, COLOR_YELLOW, COLOR_BLACK, false); + + DLG_COLOR(searchbox, COLOR_YELLOW, COLOR_BLACK, false); + DLG_COLOR(searchbox_title, COLOR_YELLOW, COLOR_BLACK, true); + DLG_COLOR(searchbox_border, COLOR_BLACK, COLOR_BLACK, true); + + DLG_COLOR(position_indicator, COLOR_RED, COLOR_BLACK, false); + + DLG_COLOR(menubox, COLOR_YELLOW, COLOR_BLACK, false); + DLG_COLOR(menubox_border, COLOR_BLACK, COLOR_BLACK, true); + + DLG_COLOR(item, COLOR_WHITE, COLOR_BLACK, false); + DLG_COLOR(item_selected, COLOR_WHITE, COLOR_RED, false); + + DLG_COLOR(tag, COLOR_RED, COLOR_BLACK, false); + DLG_COLOR(tag_selected, COLOR_YELLOW, COLOR_RED, true); + DLG_COLOR(tag_key, COLOR_RED, COLOR_BLACK, false); + DLG_COLOR(tag_key_selected, COLOR_YELLOW, COLOR_RED, true); + + DLG_COLOR(check, COLOR_YELLOW, COLOR_BLACK, false); + DLG_COLOR(check_selected, COLOR_YELLOW, COLOR_RED, true); + + DLG_COLOR(uarrow, COLOR_RED, COLOR_BLACK, false); + DLG_COLOR(darrow, COLOR_RED, COLOR_BLACK, false); +} + +static void set_bluetitle_theme(void) +{ + set_classic_theme(); + DLG_COLOR(title, COLOR_BLUE, COLOR_WHITE, true); + DLG_COLOR(button_key_active, COLOR_YELLOW, COLOR_BLUE, true); + DLG_COLOR(button_label_active, COLOR_WHITE, COLOR_BLUE, true); + DLG_COLOR(searchbox_title, COLOR_BLUE, COLOR_WHITE, true); + DLG_COLOR(position_indicator, COLOR_BLUE, COLOR_WHITE, true); + DLG_COLOR(tag, COLOR_BLUE, COLOR_WHITE, true); + DLG_COLOR(tag_key, COLOR_BLUE, COLOR_WHITE, true); + +} + +/* + * Select color theme + */ +static int set_theme(const char *theme) +{ + int use_color = 1; + if (!theme) + set_bluetitle_theme(); + else if (strcmp(theme, "classic") == 0) + set_classic_theme(); + else if (strcmp(theme, "bluetitle") == 0) + set_bluetitle_theme(); + else if (strcmp(theme, "blackbg") == 0) + set_blackbg_theme(); + else if (strcmp(theme, "mono") == 0) + use_color = 0; + + return use_color; +} + +static void init_one_color(struct dialog_color *color) +{ + static int pair = 0; + + pair++; + init_pair(pair, color->fg, color->bg); + if (color->hl) + color->atr = A_BOLD | COLOR_PAIR(pair); + else + color->atr = COLOR_PAIR(pair); +} + +static void init_dialog_colors(void) +{ + init_one_color(&dlg.screen); + init_one_color(&dlg.shadow); + init_one_color(&dlg.dialog); + init_one_color(&dlg.title); + init_one_color(&dlg.border); + init_one_color(&dlg.button_active); + init_one_color(&dlg.button_inactive); + init_one_color(&dlg.button_key_active); + init_one_color(&dlg.button_key_inactive); + init_one_color(&dlg.button_label_active); + init_one_color(&dlg.button_label_inactive); + init_one_color(&dlg.inputbox); + init_one_color(&dlg.inputbox_border); + init_one_color(&dlg.searchbox); + init_one_color(&dlg.searchbox_title); + init_one_color(&dlg.searchbox_border); + init_one_color(&dlg.position_indicator); + init_one_color(&dlg.menubox); + init_one_color(&dlg.menubox_border); + init_one_color(&dlg.item); + init_one_color(&dlg.item_selected); + init_one_color(&dlg.tag); + init_one_color(&dlg.tag_selected); + init_one_color(&dlg.tag_key); + init_one_color(&dlg.tag_key_selected); + init_one_color(&dlg.check); + init_one_color(&dlg.check_selected); + init_one_color(&dlg.uarrow); + init_one_color(&dlg.darrow); +} + +/* + * Setup for color display + */ +static void color_setup(const char *theme) +{ + int use_color; + + use_color = set_theme(theme); + if (use_color && has_colors()) { + start_color(); + init_dialog_colors(); + } else + set_mono_theme(); +} + +/* + * Set window to attribute 'attr' + */ +void attr_clear(WINDOW * win, int height, int width, chtype attr) +{ + int i, j; + + wattrset(win, attr); + for (i = 0; i < height; i++) { + wmove(win, i, 0); + for (j = 0; j < width; j++) + waddch(win, ' '); + } + touchwin(win); +} + +void dialog_clear(void) +{ + attr_clear(stdscr, LINES, COLS, dlg.screen.atr); + /* Display background title if it exists ... - SLH */ + if (dlg.backtitle != NULL) { + int i; + + wattrset(stdscr, dlg.screen.atr); + mvwaddstr(stdscr, 0, 1, (char *)dlg.backtitle); + wmove(stdscr, 1, 1); + for (i = 1; i < COLS - 1; i++) + waddch(stdscr, ACS_HLINE); + } + wnoutrefresh(stdscr); +} + +/* + * Do some initialization for dialog + */ +int init_dialog(const char *backtitle) +{ + int height, width; + + initscr(); /* Init curses */ + getmaxyx(stdscr, height, width); + if (height < 19 || width < 80) { + endwin(); + return -ERRDISPLAYTOOSMALL; + } + + dlg.backtitle = backtitle; + color_setup(getenv("MENUCONFIG_COLOR")); + + keypad(stdscr, TRUE); + cbreak(); + noecho(); + dialog_clear(); + + return 0; +} + +void set_dialog_backtitle(const char *backtitle) +{ + dlg.backtitle = backtitle; +} + +/* + * End using dialog functions. + */ +void end_dialog(int x, int y) +{ + /* move cursor back to original position */ + move(y, x); + refresh(); + endwin(); +} + +/* Print the title of the dialog. Center the title and truncate + * tile if wider than dialog (- 2 chars). + **/ +void print_title(WINDOW *dialog, const char *title, int width) +{ + if (title) { + int tlen = MIN(width - 2, strlen(title)); + wattrset(dialog, dlg.title.atr); + mvwaddch(dialog, 0, (width - tlen) / 2 - 1, ' '); + mvwaddnstr(dialog, 0, (width - tlen)/2, title, tlen); + waddch(dialog, ' '); + } +} + +/* + * Print a string of text in a window, automatically wrap around to the + * next line if the string is too long to fit on one line. Newline + * characters '\n' are replaced by spaces. We start on a new line + * if there is no room for at least 4 nonblanks following a double-space. + */ +void print_autowrap(WINDOW * win, const char *prompt, int width, int y, int x) +{ + int newl, cur_x, cur_y; + int i, prompt_len, room, wlen; + char tempstr[MAX_LEN + 1], *word, *sp, *sp2; + + strcpy(tempstr, prompt); + + prompt_len = strlen(tempstr); + + /* + * Remove newlines + */ + for (i = 0; i < prompt_len; i++) { + if (tempstr[i] == '\n') + tempstr[i] = ' '; + } + + if (prompt_len <= width - x * 2) { /* If prompt is short */ + wmove(win, y, (width - prompt_len) / 2); + waddstr(win, tempstr); + } else { + cur_x = x; + cur_y = y; + newl = 1; + word = tempstr; + while (word && *word) { + sp = strchr(word, ' '); + if (sp) + *sp++ = 0; + + /* Wrap to next line if either the word does not fit, + or it is the first word of a new sentence, and it is + short, and the next word does not fit. */ + room = width - cur_x; + wlen = strlen(word); + if (wlen > room || + (newl && wlen < 4 && sp + && wlen + 1 + strlen(sp) > room + && (!(sp2 = strchr(sp, ' ')) + || wlen + 1 + (sp2 - sp) > room))) { + cur_y++; + cur_x = x; + } + wmove(win, cur_y, cur_x); + waddstr(win, word); + getyx(win, cur_y, cur_x); + cur_x++; + if (sp && *sp == ' ') { + cur_x++; /* double space */ + while (*++sp == ' ') ; + newl = 1; + } else + newl = 0; + word = sp; + } + } +} + +/* + * Print a button + */ +void print_button(WINDOW * win, const char *label, int y, int x, int selected) +{ + int i, temp; + + wmove(win, y, x); + wattrset(win, selected ? dlg.button_active.atr + : dlg.button_inactive.atr); + waddstr(win, "<"); + temp = strspn(label, " "); + label += temp; + wattrset(win, selected ? dlg.button_label_active.atr + : dlg.button_label_inactive.atr); + for (i = 0; i < temp; i++) + waddch(win, ' '); + wattrset(win, selected ? dlg.button_key_active.atr + : dlg.button_key_inactive.atr); + waddch(win, label[0]); + wattrset(win, selected ? dlg.button_label_active.atr + : dlg.button_label_inactive.atr); + waddstr(win, (char *)label + 1); + wattrset(win, selected ? dlg.button_active.atr + : dlg.button_inactive.atr); + waddstr(win, ">"); + wmove(win, y, x + temp + 1); +} + +/* + * Draw a rectangular box with line drawing characters + */ +void +draw_box(WINDOW * win, int y, int x, int height, int width, + chtype box, chtype border) +{ + int i, j; + + wattrset(win, 0); + for (i = 0; i < height; i++) { + wmove(win, y + i, x); + for (j = 0; j < width; j++) + if (!i && !j) + waddch(win, border | ACS_ULCORNER); + else if (i == height - 1 && !j) + waddch(win, border | ACS_LLCORNER); + else if (!i && j == width - 1) + waddch(win, box | ACS_URCORNER); + else if (i == height - 1 && j == width - 1) + waddch(win, box | ACS_LRCORNER); + else if (!i) + waddch(win, border | ACS_HLINE); + else if (i == height - 1) + waddch(win, box | ACS_HLINE); + else if (!j) + waddch(win, border | ACS_VLINE); + else if (j == width - 1) + waddch(win, box | ACS_VLINE); + else + waddch(win, box | ' '); + } +} + +/* + * Draw shadows along the right and bottom edge to give a more 3D look + * to the boxes + */ +void draw_shadow(WINDOW * win, int y, int x, int height, int width) +{ + int i; + + if (has_colors()) { /* Whether terminal supports color? */ + wattrset(win, dlg.shadow.atr); + wmove(win, y + height, x + 2); + for (i = 0; i < width; i++) + waddch(win, winch(win) & A_CHARTEXT); + for (i = y + 1; i < y + height + 1; i++) { + wmove(win, i, x + width); + waddch(win, winch(win) & A_CHARTEXT); + waddch(win, winch(win) & A_CHARTEXT); + } + wnoutrefresh(win); + } +} + +/* + * Return the position of the first alphabetic character in a string. + */ +int first_alpha(const char *string, const char *exempt) +{ + int i, in_paren = 0, c; + + for (i = 0; i < strlen(string); i++) { + c = tolower(string[i]); + + if (strchr("<[(", c)) + ++in_paren; + if (strchr(">])", c) && in_paren > 0) + --in_paren; + + if ((!in_paren) && isalpha(c) && strchr(exempt, c) == 0) + return i; + } + + return 0; +} + +/* + * ncurses uses ESC to detect escaped char sequences. This resutl in + * a small timeout before ESC is actually delivered to the application. + * lxdialog suggest which is correctly translated to two + * times esc. But then we need to ignore the second esc to avoid stepping + * out one menu too much. Filter away all escaped key sequences since + * keypad(FALSE) turn off ncurses support for escape sequences - and thats + * needed to make notimeout() do as expected. + */ +int on_key_esc(WINDOW *win) +{ + int key; + int key2; + int key3; + + nodelay(win, TRUE); + keypad(win, FALSE); + key = wgetch(win); + key2 = wgetch(win); + do { + key3 = wgetch(win); + } while (key3 != ERR); + nodelay(win, FALSE); + keypad(win, TRUE); + if (key == KEY_ESC && key2 == ERR) + return KEY_ESC; + else if (key != ERR && key != KEY_ESC && key2 == ERR) + ungetch(key); + + return -1; +} + +/* redraw screen in new size */ +int on_key_resize(void) +{ + dialog_clear(); + return KEY_RESIZE; +} + +struct dialog_list *item_cur; +struct dialog_list item_nil; +struct dialog_list *item_head; + +void item_reset(void) +{ + struct dialog_list *p, *next; + + for (p = item_head; p; p = next) { + next = p->next; + free(p); + } + item_head = NULL; + item_cur = &item_nil; +} + +void item_make(const char *fmt, ...) +{ + va_list ap; + struct dialog_list *p = malloc(sizeof(*p)); + + if (item_head) + item_cur->next = p; + else + item_head = p; + item_cur = p; + memset(p, 0, sizeof(*p)); + + va_start(ap, fmt); + vsnprintf(item_cur->node.str, sizeof(item_cur->node.str), fmt, ap); + va_end(ap); +} + +void item_add_str(const char *fmt, ...) +{ + va_list ap; + size_t avail; + + avail = sizeof(item_cur->node.str) - strlen(item_cur->node.str); + + va_start(ap, fmt); + vsnprintf(item_cur->node.str + strlen(item_cur->node.str), + avail, fmt, ap); + item_cur->node.str[sizeof(item_cur->node.str) - 1] = '\0'; + va_end(ap); +} + +void item_set_tag(char tag) +{ + item_cur->node.tag = tag; +} +void item_set_data(void *ptr) +{ + item_cur->node.data = ptr; +} + +void item_set_selected(int val) +{ + item_cur->node.selected = val; +} + +int item_activate_selected(void) +{ + item_foreach() + if (item_is_selected()) + return 1; + return 0; +} + +void *item_data(void) +{ + return item_cur->node.data; +} + +char item_tag(void) +{ + return item_cur->node.tag; +} + +int item_count(void) +{ + int n = 0; + struct dialog_list *p; + + for (p = item_head; p; p = p->next) + n++; + return n; +} + +void item_set(int n) +{ + int i = 0; + item_foreach() + if (i++ == n) + return; +} + +int item_n(void) +{ + int n = 0; + struct dialog_list *p; + + for (p = item_head; p; p = p->next) { + if (p == item_cur) + return n; + n++; + } + return 0; +} + +const char *item_str(void) +{ + return item_cur->node.str; +} + +int item_is_selected(void) +{ + return (item_cur->node.selected != 0); +} + +int item_is_tag(char tag) +{ + return (item_cur->node.tag == tag); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/lxdialog/yesno.c b/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/lxdialog/yesno.c new file mode 100644 index 00000000..4e6e8090 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/lxdialog/yesno.c @@ -0,0 +1,114 @@ +/* + * yesno.c -- implements the yes/no box + * + * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) + * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "dialog.h" + +/* + * Display termination buttons + */ +static void print_buttons(WINDOW * dialog, int height, int width, int selected) +{ + int x = width / 2 - 10; + int y = height - 2; + + print_button(dialog, gettext(" Yes "), y, x, selected == 0); + print_button(dialog, gettext(" No "), y, x + 13, selected == 1); + + wmove(dialog, y, x + 1 + 13 * selected); + wrefresh(dialog); +} + +/* + * Display a dialog box with two buttons - Yes and No + */ +int dialog_yesno(const char *title, const char *prompt, int height, int width) +{ + int i, x, y, key = 0, button = 0; + WINDOW *dialog; + +do_resize: + if (getmaxy(stdscr) < (height + 4)) + return -ERRDISPLAYTOOSMALL; + if (getmaxx(stdscr) < (width + 4)) + return -ERRDISPLAYTOOSMALL; + + /* center dialog box on screen */ + x = (COLS - width) / 2; + y = (LINES - height) / 2; + + draw_shadow(stdscr, y, x, height, width); + + dialog = newwin(height, width, y, x); + keypad(dialog, TRUE); + + draw_box(dialog, 0, 0, height, width, + dlg.dialog.atr, dlg.border.atr); + wattrset(dialog, dlg.border.atr); + mvwaddch(dialog, height - 3, 0, ACS_LTEE); + for (i = 0; i < width - 2; i++) + waddch(dialog, ACS_HLINE); + wattrset(dialog, dlg.dialog.atr); + waddch(dialog, ACS_RTEE); + + print_title(dialog, title, width); + + wattrset(dialog, dlg.dialog.atr); + print_autowrap(dialog, prompt, width - 2, 1, 3); + + print_buttons(dialog, height, width, 0); + + while (key != KEY_ESC) { + key = wgetch(dialog); + switch (key) { + case 'Y': + case 'y': + delwin(dialog); + return 0; + case 'N': + case 'n': + delwin(dialog); + return 1; + + case TAB: + case KEY_LEFT: + case KEY_RIGHT: + button = ((key == KEY_LEFT ? --button : ++button) < 0) ? 1 : (button > 1 ? 0 : button); + + print_buttons(dialog, height, width, button); + wrefresh(dialog); + break; + case ' ': + case '\n': + delwin(dialog); + return button; + case KEY_ESC: + key = on_key_esc(dialog); + break; + case KEY_RESIZE: + delwin(dialog); + on_key_resize(); + goto do_resize; + } + } + + delwin(dialog); + return key; /* ESC pressed */ +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/mconf.c b/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/mconf.c new file mode 100644 index 00000000..18583bd4 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/mconf.c @@ -0,0 +1,930 @@ +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + * + * Introduced single menu mode (show all sub-menus in one large tree). + * 2002-11-06 Petr Baudis + * + * i18n, 2005, Arnaldo Carvalho de Melo + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define LKC_DIRECT_LINK +#include "lkc.h" +#include "lxdialog/dialog.h" + +static const char mconf_readme[] = N_( +"Overview\n" +"--------\n" +"Some features may be built directly into uClibc. Some features\n" +"may be completely removed altogether. There are also certain\n" +"parameters which are not really features, but must be\n" +"entered in as decimal or hexadecimal numbers or possibly text.\n" +"\n" +"Menu items beginning with following braces represent features that\n" +" [ ] can be built in or removed\n" +" < > can be built in, modularized or removed\n" +" { } can be built in or modularized (selected by other feature)\n" +" - - are selected by other feature,\n" +"while *, M or whitespace inside braces means to build in, build as\n" +"a module or to exclude the feature respectively.\n" +"\n" +"To change any of these features, highlight it with the cursor\n" +"keys and press to build it in, to make it a module or\n" +" to removed it. You may also press the to cycle\n" +"through the available options (ie. Y->N->M->Y).\n" +"\n" +"Some additional keyboard hints:\n" +"\n" +"Menus\n" +"----------\n" +"o Use the Up/Down arrow keys (cursor keys) to highlight the item\n" +" you wish to change or submenu wish to select and press .\n" +" Submenus are designated by \"--->\".\n" +"\n" +" Shortcut: Press the option's highlighted letter (hotkey).\n" +" Pressing a hotkey more than once will sequence\n" +" through all visible items which use that hotkey.\n" +"\n" +" You may also use the and keys to scroll\n" +" unseen options into view.\n" +"\n" +"o To exit a menu use the cursor keys to highlight the button\n" +" and press .\n" +"\n" +" Shortcut: Press or or if there is no hotkey\n" +" using those letters. You may press a single , but\n" +" there is a delayed response which you may find annoying.\n" +"\n" +" Also, the and cursor keys will cycle between and\n" +" \n" +"\n" +"\n" +"Data Entry\n" +"-----------\n" +"o Enter the requested information and press \n" +" If you are entering hexadecimal values, it is not necessary to\n" +" add the '0x' prefix to the entry.\n" +"\n" +"o For help, use the or cursor keys to highlight the help option\n" +" and press . You can try as well.\n" +"\n" +"\n" +"Text Box (Help Window)\n" +"--------\n" +"o Use the cursor keys to scroll up/down/left/right. The VI editor\n" +" keys h,j,k,l function here as do and for those\n" +" who are familiar with less and lynx.\n" +"\n" +"o Press , , or to exit.\n" +"\n" +"\n" +"Alternate Configuration Files\n" +"-----------------------------\n" +"Menuconfig supports the use of alternate configuration files for\n" +"those who, for various reasons, find it necessary to switch\n" +"between different configurations.\n" +"\n" +"At the end of the main menu you will find two options. One is\n" +"for saving the current configuration to a file of your choosing.\n" +"The other option is for loading a previously saved alternate\n" +"configuration.\n" +"\n" +"Even if you don't use alternate configuration files, but you\n" +"find during a Menuconfig session that you have completely messed\n" +"up your settings, you may use the \"Load Alternate...\" option to\n" +"restore your previously saved settings from \".config\" without\n" +"restarting Menuconfig.\n" +"\n" +"Other information\n" +"-----------------\n" +"If you use Menuconfig in an XTERM window make sure you have your\n" +"$TERM variable set to point to a xterm definition which supports color.\n" +"Otherwise, Menuconfig will look rather bad. Menuconfig will not\n" +"display correctly in a RXVT window because rxvt displays only one\n" +"intensity of color, bright.\n" +"\n" +"Menuconfig will display larger menus on screens or xterms which are\n" +"set to display more than the standard 25 row by 80 column geometry.\n" +"In order for this to work, the \"stty size\" command must be able to\n" +"display the screen's current row and column geometry. I STRONGLY\n" +"RECOMMEND that you make sure you do NOT have the shell variables\n" +"LINES and COLUMNS exported into your environment. Some distributions\n" +"export those variables via /etc/profile. Some ncurses programs can\n" +"become confused when those variables (LINES & COLUMNS) don't reflect\n" +"the true screen size.\n" +"\n" +"Optional personality available\n" +"------------------------------\n" +"If you prefer to have all of the options listed in a single\n" +"menu, rather than the default multimenu hierarchy, run the menuconfig\n" +"with MENUCONFIG_MODE environment variable set to single_menu. Example:\n" +"\n" +"make MENUCONFIG_MODE=single_menu menuconfig\n" +"\n" +" will then unroll the appropriate category, or enfold it if it\n" +"is already unrolled.\n" +"\n" +"Note that this mode can eventually be a little more CPU expensive\n" +"(especially with a larger number of unrolled categories) than the\n" +"default mode.\n" +"\n" +"Different color themes available\n" +"--------------------------------\n" +"It is possible to select different color themes using the variable\n" +"MENUCONFIG_COLOR. To select a theme use:\n" +"\n" +"make MENUCONFIG_COLOR= menuconfig\n" +"\n" +"Available themes are\n" +" mono => selects colors suitable for monochrome displays\n" +" blackbg => selects a color scheme with black background\n" +" classic => theme with blue background. The classic look\n" +" bluetitle => a LCD friendly version of classic. (default)\n" +"\n"), +menu_instructions[] = N_( + "Arrow keys navigate the menu. " + " selects submenus --->. " + "Highlighted letters are hotkeys. " + "Pressing selectes a feature, while will exclude a feature. " + "Press to exit, for Help, for Search. " + "Legend: [*] feature is selected [ ] feature is excluded"), +radiolist_instructions[] = N_( + "Use the arrow keys to navigate this window or " + "press the hotkey of the item you wish to select " + "followed by the . " + "Press for additional information about this option."), +inputbox_instructions_int[] = N_( + "Please enter a decimal value. " + "Fractions will not be accepted. " + "Use the key to move from the input field to the buttons below it."), +inputbox_instructions_hex[] = N_( + "Please enter a hexadecimal value. " + "Use the key to move from the input field to the buttons below it."), +inputbox_instructions_string[] = N_( + "Please enter a string value. " + "Use the key to move from the input field to the buttons below it."), +setmod_text[] = N_( + "This feature depends on another which has been configured as a module.\n" + "As a result, this feature will be built as a module."), +nohelp_text[] = N_( + "There is no help available for this option.\n"), +load_config_text[] = N_( + "Enter the name of the configuration file you wish to load. " + "Accept the name shown to restore the configuration you " + "last retrieved. Leave blank to abort."), +load_config_help[] = N_( + "\n" + "For various reasons, one may wish to keep several different\n" + "configurations available on a single machine.\n" + "\n" + "If you have saved a previous configuration in a file other than the\n" + "default, entering the name of the file here will allow you\n" + "to modify that configuration.\n" + "\n" + "If you are uncertain, then you have probably never used alternate\n" + "configuration files. You should therefor leave this blank to abort.\n"), +save_config_text[] = N_( + "Enter a filename to which this configuration should be saved " + "as an alternate. Leave blank to abort."), +save_config_help[] = N_( + "\n" + "For various reasons, one may wish to keep different\n" + "configurations available on a single machine.\n" + "\n" + "Entering a file name here will allow you to later retrieve, modify\n" + "and use the current configuration as an alternate to whatever\n" + "configuration options you have selected at that time.\n" + "\n" + "If you are uncertain what all this means then you should probably\n" + "leave this blank.\n"), +search_help[] = N_( + "\n" + "Search for CONFIG_ symbols and display their relations.\n" + "Regular expressions are allowed.\n" + "Example: search for \"^FOO\"\n" + "Result:\n" + "-----------------------------------------------------------------\n" + "Symbol: FOO [=m]\n" + "Prompt: Foo bus is used to drive the bar HW\n" + "Defined at drivers/pci/Kconfig:47\n" + "Depends on: X86_LOCAL_APIC && X86_IO_APIC || IA64\n" + "Location:\n" + " -> Bus options (PCI, PCMCIA, EISA, MCA, ISA)\n" + " -> PCI support (PCI [=y])\n" + " -> PCI access mode ( [=y])\n" + "Selects: LIBCRC32\n" + "Selected by: BAR\n" + "-----------------------------------------------------------------\n" + "o The line 'Prompt:' shows the text used in the menu structure for\n" + " this CONFIG_ symbol\n" + "o The 'Defined at' line tell at what file / line number the symbol\n" + " is defined\n" + "o The 'Depends on:' line tell what symbols needs to be defined for\n" + " this symbol to be visible in the menu (selectable)\n" + "o The 'Location:' lines tell where in the menu structure this symbol\n" + " is located\n" + " A location followed by a [=y] indicate that this is a selectable\n" + " menu item - and current value is displayed inside brackets.\n" + "o The 'Selects:' line tell what symbol will be automatically\n" + " selected if this symbol is selected (y or m)\n" + "o The 'Selected by' line tell what symbol has selected this symbol\n" + "\n" + "Only relevant lines are shown.\n" + "\n\n" + "Search examples:\n" + "Examples: USB => find all CONFIG_ symbols containing USB\n" + " ^USB => find all CONFIG_ symbols starting with USB\n" + " USB$ => find all CONFIG_ symbols ending with USB\n" + "\n"); + +static int indent; +static struct menu *current_menu; +static int child_count; +static int single_menu_mode; + +static void conf(struct menu *menu); +static void conf_choice(struct menu *menu); +static void conf_string(struct menu *menu); +static void conf_load(void); +static void conf_save(void); +static void show_textbox(const char *title, const char *text, int r, int c); +static void show_helptext(const char *title, const char *text); +static void show_help(struct menu *menu); + +static void get_prompt_str(struct gstr *r, struct property *prop) +{ + int i, j; + struct menu *submenu[8], *menu; + + str_printf(r, _("Prompt: %s\n"), _(prop->text)); + str_printf(r, _(" Defined at %s:%d\n"), prop->menu->file->name, + prop->menu->lineno); + if (!expr_is_yes(prop->visible.expr)) { + str_append(r, _(" Depends on: ")); + expr_gstr_print(prop->visible.expr, r); + str_append(r, "\n"); + } + menu = prop->menu->parent; + for (i = 0; menu != &rootmenu && i < 8; menu = menu->parent) + submenu[i++] = menu; + if (i > 0) { + str_printf(r, _(" Location:\n")); + for (j = 4; --i >= 0; j += 2) { + menu = submenu[i]; + str_printf(r, "%*c-> %s", j, ' ', _(menu_get_prompt(menu))); + if (menu->sym) { + str_printf(r, " (%s [=%s])", menu->sym->name ? + menu->sym->name : _(""), + sym_get_string_value(menu->sym)); + } + str_append(r, "\n"); + } + } +} + +static void get_symbol_str(struct gstr *r, struct symbol *sym) +{ + bool hit; + struct property *prop; + + if (sym && sym->name) + str_printf(r, "Symbol: %s [=%s]\n", sym->name, + sym_get_string_value(sym)); + for_all_prompts(sym, prop) + get_prompt_str(r, prop); + hit = false; + for_all_properties(sym, prop, P_SELECT) { + if (!hit) { + str_append(r, " Selects: "); + hit = true; + } else + str_printf(r, " && "); + expr_gstr_print(prop->expr, r); + } + if (hit) + str_append(r, "\n"); + if (sym->rev_dep.expr) { + str_append(r, _(" Selected by: ")); + expr_gstr_print(sym->rev_dep.expr, r); + str_append(r, "\n"); + } + str_append(r, "\n\n"); +} + +static struct gstr get_relations_str(struct symbol **sym_arr) +{ + struct symbol *sym; + struct gstr res = str_new(); + int i; + + for (i = 0; sym_arr && (sym = sym_arr[i]); i++) + get_symbol_str(&res, sym); + if (!i) + str_append(&res, _("No matches found.\n")); + return res; +} + +static char filename[PATH_MAX+1]; +static void set_config_filename(const char *config_filename) +{ + static char menu_backtitle[PATH_MAX+128]; + int size; + struct symbol *sym; + + sym = sym_lookup("VERSION", 0); + sym_calc_value(sym); + size = snprintf(menu_backtitle, sizeof(menu_backtitle), + _("%s - uClibc v%s Configuration"), + config_filename, sym_get_string_value(sym)); + if (size >= sizeof(menu_backtitle)) + menu_backtitle[sizeof(menu_backtitle)-1] = '\0'; + set_dialog_backtitle(menu_backtitle); + + size = snprintf(filename, sizeof(filename), "%s", config_filename); + if (size >= sizeof(filename)) + filename[sizeof(filename)-1] = '\0'; +} + + +static void search_conf(void) +{ + struct symbol **sym_arr; + struct gstr res; + char *dialog_input; + int dres; +again: + dialog_clear(); + dres = dialog_inputbox(_("Search Configuration Parameter"), + _("Enter CONFIG_ (sub)string to search for " + "(with or without \"CONFIG\")"), + 10, 75, ""); + switch (dres) { + case 0: + break; + case 1: + show_helptext(_("Search Configuration"), search_help); + goto again; + default: + return; + } + + /* strip CONFIG_ if necessary */ + dialog_input = dialog_input_result; + if (strncasecmp(dialog_input_result, "CONFIG_", 7) == 0) + dialog_input += 7; + + sym_arr = sym_re_search(dialog_input); + res = get_relations_str(sym_arr); + free(sym_arr); + show_textbox(_("Search Results"), str_get(&res), 0, 0); + str_free(&res); +} + +static void build_conf(struct menu *menu) +{ + struct symbol *sym; + struct property *prop; + struct menu *child; + int type, tmp, doint = 2; + tristate val; + char ch; + + if (!menu_is_visible(menu)) + return; + + sym = menu->sym; + prop = menu->prompt; + if (!sym) { + if (prop && menu != current_menu) { + const char *prompt = menu_get_prompt(menu); + switch (prop->type) { + case P_MENU: + child_count++; + prompt = _(prompt); + if (single_menu_mode) { + item_make("%s%*c%s", + menu->data ? "-->" : "++>", + indent + 1, ' ', prompt); + } else + item_make(" %*c%s --->", indent + 1, ' ', prompt); + + item_set_tag('m'); + item_set_data(menu); + if (single_menu_mode && menu->data) + goto conf_childs; + return; + case P_COMMENT: + if (prompt) { + child_count++; + item_make(" %*c*** %s ***", indent + 1, ' ', _(prompt)); + item_set_tag(':'); + item_set_data(menu); + } + break; + default: + if (prompt) { + child_count++; + item_make("---%*c%s", indent + 1, ' ', _(prompt)); + item_set_tag(':'); + item_set_data(menu); + } + } + } else + doint = 0; + goto conf_childs; + } + + type = sym_get_type(sym); + if (sym_is_choice(sym)) { + struct symbol *def_sym = sym_get_choice_value(sym); + struct menu *def_menu = NULL; + + child_count++; + for (child = menu->list; child; child = child->next) { + if (menu_is_visible(child) && child->sym == def_sym) + def_menu = child; + } + + val = sym_get_tristate_value(sym); + if (sym_is_changable(sym)) { + switch (type) { + case S_BOOLEAN: + item_make("[%c]", val == no ? ' ' : '*'); + break; + case S_TRISTATE: + switch (val) { + case yes: ch = '*'; break; + case mod: ch = 'M'; break; + default: ch = ' '; break; + } + item_make("<%c>", ch); + break; + } + item_set_tag('t'); + item_set_data(menu); + } else { + item_make(" "); + item_set_tag(def_menu ? 't' : ':'); + item_set_data(menu); + } + + item_add_str("%*c%s", indent + 1, ' ', _(menu_get_prompt(menu))); + if (val == yes) { + if (def_menu) { + item_add_str(" (%s)", _(menu_get_prompt(def_menu))); + item_add_str(" --->"); + if (def_menu->list) { + indent += 2; + build_conf(def_menu); + indent -= 2; + } + } + return; + } + } else { + if (menu == current_menu) { + item_make("---%*c%s", indent + 1, ' ', _(menu_get_prompt(menu))); + item_set_tag(':'); + item_set_data(menu); + goto conf_childs; + } + child_count++; + val = sym_get_tristate_value(sym); + if (sym_is_choice_value(sym) && val == yes) { + item_make(" "); + item_set_tag(':'); + item_set_data(menu); + } else { + switch (type) { + case S_BOOLEAN: + if (sym_is_changable(sym)) + item_make("[%c]", val == no ? ' ' : '*'); + else + item_make("-%c-", val == no ? ' ' : '*'); + item_set_tag('t'); + item_set_data(menu); + break; + case S_TRISTATE: + switch (val) { + case yes: ch = '*'; break; + case mod: ch = 'M'; break; + default: ch = ' '; break; + } + if (sym_is_changable(sym)) { + if (sym->rev_dep.tri == mod) + item_make("{%c}", ch); + else + item_make("<%c>", ch); + } else + item_make("-%c-", ch); + item_set_tag('t'); + item_set_data(menu); + break; + default: + tmp = 2 + strlen(sym_get_string_value(sym)); /* () = 2 */ + item_make("(%s)", sym_get_string_value(sym)); + tmp = indent - tmp + 4; + if (tmp < 0) + tmp = 0; + item_add_str("%*c%s%s", tmp, ' ', _(menu_get_prompt(menu)), + (sym_has_value(sym) || !sym_is_changable(sym)) ? + "" : _(" (NEW)")); + item_set_tag('s'); + item_set_data(menu); + goto conf_childs; + } + } + item_add_str("%*c%s%s", indent + 1, ' ', _(menu_get_prompt(menu)), + (sym_has_value(sym) || !sym_is_changable(sym)) ? + "" : _(" (NEW)")); + if (menu->prompt->type == P_MENU) { + item_add_str(" --->"); + return; + } + } + +conf_childs: + indent += doint; + for (child = menu->list; child; child = child->next) + build_conf(child); + indent -= doint; +} + +static void conf(struct menu *menu) +{ + struct menu *submenu; + const char *prompt = menu_get_prompt(menu); + struct symbol *sym; + struct menu *active_menu = NULL; + int res; + int s_scroll = 0; + + while (1) { + item_reset(); + current_menu = menu; + build_conf(menu); + if (!child_count) + break; + if (menu == &rootmenu) { + item_make("--- "); + item_set_tag(':'); + item_make(_(" Load an Alternate Configuration File")); + item_set_tag('L'); + item_make(_(" Save an Alternate Configuration File")); + item_set_tag('S'); + } + dialog_clear(); + res = dialog_menu(prompt ? _(prompt) : _("Main Menu"), + _(menu_instructions), + active_menu, &s_scroll); + if (res == 1 || res == KEY_ESC || res == -ERRDISPLAYTOOSMALL) + break; + if (!item_activate_selected()) + continue; + if (!item_tag()) + continue; + + submenu = item_data(); + active_menu = item_data(); + if (submenu) + sym = submenu->sym; + else + sym = NULL; + + switch (res) { + case 0: + switch (item_tag()) { + case 'm': + if (single_menu_mode) + submenu->data = (void *) (long) !submenu->data; + else + conf(submenu); + break; + case 't': + if (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes) + conf_choice(submenu); + else if (submenu->prompt->type == P_MENU) + conf(submenu); + break; + case 's': + conf_string(submenu); + break; + case 'L': + conf_load(); + break; + case 'S': + conf_save(); + break; + } + break; + case 2: + if (sym) + show_help(submenu); + else + show_helptext(_("README"), _(mconf_readme)); + break; + case 3: + if (item_is_tag('t')) { + if (sym_set_tristate_value(sym, yes)) + break; + if (sym_set_tristate_value(sym, mod)) + show_textbox(NULL, setmod_text, 6, 74); + } + break; + case 4: + if (item_is_tag('t')) + sym_set_tristate_value(sym, no); + break; + case 5: + if (item_is_tag('t')) + sym_set_tristate_value(sym, mod); + break; + case 6: + if (item_is_tag('t')) + sym_toggle_tristate_value(sym); + else if (item_is_tag('m')) + conf(submenu); + break; + case 7: + search_conf(); + break; + } + } +} + +static void show_textbox(const char *title, const char *text, int r, int c) +{ + dialog_clear(); + dialog_textbox(title, text, r, c); +} + +static void show_helptext(const char *title, const char *text) +{ + show_textbox(title, text, 0, 0); +} + +static void show_help(struct menu *menu) +{ + struct gstr help = str_new(); + struct symbol *sym = menu->sym; + + if (menu_has_help(menu)) + { + if (sym->name) { + str_printf(&help, "%s:\n\n", sym->name); + } + str_append(&help, _(menu_get_help(menu))); + str_append(&help, "\n"); + } else if (menu_has_help(sym->prop->menu->parent)) { + str_append(&help, _(menu_get_help(sym->prop->menu->parent))); + str_append(&help, "\n"); + } else { + str_append(&help, nohelp_text); + } + get_symbol_str(&help, sym); + show_helptext(_(menu_get_prompt(menu)), str_get(&help)); + str_free(&help); +} + +static void conf_choice(struct menu *menu) +{ + const char *prompt = _(menu_get_prompt(menu)); + struct menu *child; + struct symbol *active; + + active = sym_get_choice_value(menu->sym); + while (1) { + int res; + int selected; + item_reset(); + + current_menu = menu; + for (child = menu->list; child; child = child->next) { + if (!menu_is_visible(child)) + continue; + item_make("%s", _(menu_get_prompt(child))); + item_set_data(child); + if (child->sym == active) + item_set_selected(1); + if (child->sym == sym_get_choice_value(menu->sym)) + item_set_tag('X'); + } + dialog_clear(); + res = dialog_checklist(prompt ? _(prompt) : _("Main Menu"), + _(radiolist_instructions), + 15, 70, 6); + selected = item_activate_selected(); + switch (res) { + case 0: + if (selected) { + child = item_data(); + sym_set_tristate_value(child->sym, yes); + } + return; + case 1: + if (selected) { + child = item_data(); + show_help(child); + active = child->sym; + } else + show_help(menu); + break; + case KEY_ESC: + return; + case -ERRDISPLAYTOOSMALL: + return; + } + } +} + +static void conf_string(struct menu *menu) +{ + const char *prompt = menu_get_prompt(menu); + + while (1) { + int res; + const char *heading; + + switch (sym_get_type(menu->sym)) { + case S_INT: + heading = _(inputbox_instructions_int); + break; + case S_HEX: + heading = _(inputbox_instructions_hex); + break; + case S_STRING: + heading = _(inputbox_instructions_string); + break; + default: + heading = _("Internal mconf error!"); + } + dialog_clear(); + res = dialog_inputbox(prompt ? _(prompt) : _("Main Menu"), + heading, 10, 75, + sym_get_string_value(menu->sym)); + switch (res) { + case 0: + if (sym_set_string_value(menu->sym, dialog_input_result)) + return; + show_textbox(NULL, _("You have made an invalid entry."), 5, 43); + break; + case 1: + show_help(menu); + break; + case KEY_ESC: + return; + } + } +} + +static void conf_load(void) +{ + + while (1) { + int res; + dialog_clear(); + res = dialog_inputbox(NULL, load_config_text, + 11, 55, filename); + switch(res) { + case 0: + if (!dialog_input_result[0]) + return; + if (!conf_read(dialog_input_result)) { + set_config_filename(dialog_input_result); + sym_set_change_count(1); + return; + } + show_textbox(NULL, _("File does not exist!"), 5, 38); + break; + case 1: + show_helptext(_("Load Alternate Configuration"), load_config_help); + break; + case KEY_ESC: + return; + } + } +} + +static void conf_save(void) +{ + while (1) { + int res; + dialog_clear(); + res = dialog_inputbox(NULL, save_config_text, + 11, 55, filename); + switch(res) { + case 0: + if (!dialog_input_result[0]) + return; + if (!conf_write(dialog_input_result)) { + set_config_filename(dialog_input_result); + return; + } + show_textbox(NULL, _("Can't create file! Probably a nonexistent directory."), 5, 60); + break; + case 1: + show_helptext(_("Save Alternate Configuration"), save_config_help); + break; + case KEY_ESC: + return; + } + } +} + +int main(int ac, char **av) +{ + int saved_x, saved_y; + char *mode; + int res; + + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + + conf_parse(av[1]); + conf_read(NULL); + + mode = getenv("MENUCONFIG_MODE"); + if (mode) { + if (!strcasecmp(mode, "single_menu")) + single_menu_mode = 1; + } + + getyx(stdscr, saved_y, saved_x); + if (init_dialog(NULL)) { + fprintf(stderr, N_("Your display is too small to run Menuconfig!\n")); + fprintf(stderr, N_("It must be at least 19 lines by 80 columns.\n")); + return 1; + } + + set_config_filename(conf_get_configname()); + do { + conf(&rootmenu); + dialog_clear(); + if (conf_get_changed()) + res = dialog_yesno(NULL, + _("Do you wish to save your " + "new configuration?\n" + " to continue."), + 6, 60); + else + res = -1; + } while (res == KEY_ESC); + end_dialog(saved_x, saved_y); + + switch (res) { + case 0: + if (conf_write(filename)) { + fprintf(stderr, _("\n\n" + "Error during writing of the configuration.\n" + "Your configuration changes were NOT saved." + "\n\n")); + return 1; + } + case -1: + printf(_("\n\n" + "*** End of configuration.\n" + "*** Execute 'make' to build or try 'make help'." + "\n\n")); + break; + default: + fprintf(stderr, _("\n\n" + "Your configuration changes were NOT saved." + "\n\n")); + } + + return conf_write_autoconf(); +} + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/menu.c b/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/menu.c new file mode 100644 index 00000000..07ff8d10 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/menu.c @@ -0,0 +1,453 @@ +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +#include +#include + +#define LKC_DIRECT_LINK +#include "lkc.h" + +struct menu rootmenu; +static struct menu **last_entry_ptr; + +struct file *file_list; +struct file *current_file; + +void menu_warn(struct menu *menu, const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + fprintf(stderr, "%s:%d:warning: ", menu->file->name, menu->lineno); + vfprintf(stderr, fmt, ap); + fprintf(stderr, "\n"); + va_end(ap); +} + +static void prop_warn(struct property *prop, const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + fprintf(stderr, "%s:%d:warning: ", prop->file->name, prop->lineno); + vfprintf(stderr, fmt, ap); + fprintf(stderr, "\n"); + va_end(ap); +} + +void menu_init(void) +{ + current_entry = current_menu = &rootmenu; + last_entry_ptr = &rootmenu.list; +} + +void menu_add_entry(struct symbol *sym) +{ + struct menu *menu; + + menu = malloc(sizeof(*menu)); + memset(menu, 0, sizeof(*menu)); + menu->sym = sym; + menu->parent = current_menu; + menu->file = current_file; + menu->lineno = zconf_lineno(); + + *last_entry_ptr = menu; + last_entry_ptr = &menu->next; + current_entry = menu; +} + +void menu_end_entry(void) +{ +} + +struct menu *menu_add_menu(void) +{ + menu_end_entry(); + last_entry_ptr = ¤t_entry->list; + return current_menu = current_entry; +} + +void menu_end_menu(void) +{ + last_entry_ptr = ¤t_menu->next; + current_menu = current_menu->parent; +} + +struct expr *menu_check_dep(struct expr *e) +{ + if (!e) + return e; + + switch (e->type) { + case E_NOT: + e->left.expr = menu_check_dep(e->left.expr); + break; + case E_OR: + case E_AND: + e->left.expr = menu_check_dep(e->left.expr); + e->right.expr = menu_check_dep(e->right.expr); + break; + case E_SYMBOL: + /* change 'm' into 'm' && MODULES */ + if (e->left.sym == &symbol_mod) + return expr_alloc_and(e, expr_alloc_symbol(modules_sym)); + break; + default: + break; + } + return e; +} + +void menu_add_dep(struct expr *dep) +{ + current_entry->dep = expr_alloc_and(current_entry->dep, menu_check_dep(dep)); +} + +void menu_set_type(int type) +{ + struct symbol *sym = current_entry->sym; + + if (sym->type == type) + return; + if (sym->type == S_UNKNOWN) { + sym->type = type; + return; + } + menu_warn(current_entry, "type of '%s' redefined from '%s' to '%s'", + sym->name ? sym->name : "", + sym_type_name(sym->type), sym_type_name(type)); +} + +struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *expr, struct expr *dep) +{ + struct property *prop = prop_alloc(type, current_entry->sym); + + prop->menu = current_entry; + prop->expr = expr; + prop->visible.expr = menu_check_dep(dep); + + if (prompt) { + if (isspace(*prompt)) { + prop_warn(prop, "leading whitespace ignored"); + while (isspace(*prompt)) + prompt++; + } + if (current_entry->prompt) + prop_warn(prop, "prompt redefined"); + current_entry->prompt = prop; + } + prop->text = prompt; + + return prop; +} + +struct property *menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep) +{ + return menu_add_prop(type, prompt, NULL, dep); +} + +void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep) +{ + menu_add_prop(type, NULL, expr, dep); +} + +void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep) +{ + menu_add_prop(type, NULL, expr_alloc_symbol(sym), dep); +} + +void menu_add_option(int token, char *arg) +{ + struct property *prop; + + switch (token) { + case T_OPT_MODULES: + prop = prop_alloc(P_DEFAULT, modules_sym); + prop->expr = expr_alloc_symbol(current_entry->sym); + break; + case T_OPT_DEFCONFIG_LIST: + if (!sym_defconfig_list) + sym_defconfig_list = current_entry->sym; + else if (sym_defconfig_list != current_entry->sym) + zconf_error("trying to redefine defconfig symbol"); + break; + case T_OPT_ENV: + prop_add_env(arg); + break; + } +} + +static int menu_range_valid_sym(struct symbol *sym, struct symbol *sym2) +{ + return sym2->type == S_INT || sym2->type == S_HEX || + (sym2->type == S_UNKNOWN && sym_string_valid(sym, sym2->name)); +} + +void sym_check_prop(struct symbol *sym) +{ + struct property *prop; + struct symbol *sym2; + for (prop = sym->prop; prop; prop = prop->next) { + switch (prop->type) { + case P_DEFAULT: + if ((sym->type == S_STRING || sym->type == S_INT || sym->type == S_HEX) && + prop->expr->type != E_SYMBOL) + prop_warn(prop, + "default for config symbol '%'" + " must be a single symbol", sym->name); + break; + case P_SELECT: + sym2 = prop_get_symbol(prop); + if (sym->type != S_BOOLEAN && sym->type != S_TRISTATE) + prop_warn(prop, + "config symbol '%s' uses select, but is " + "not boolean or tristate", sym->name); + else if (sym2->type != S_UNKNOWN && + sym2->type != S_BOOLEAN && + sym2->type != S_TRISTATE) + prop_warn(prop, + "'%s' has wrong type. 'select' only " + "accept arguments of boolean and " + "tristate type", sym2->name); + break; + case P_RANGE: + if (sym->type != S_INT && sym->type != S_HEX) + prop_warn(prop, "range is only allowed " + "for int or hex symbols"); + if (!menu_range_valid_sym(sym, prop->expr->left.sym) || + !menu_range_valid_sym(sym, prop->expr->right.sym)) + prop_warn(prop, "range is invalid"); + break; + default: + ; + } + } +} + +void menu_finalize(struct menu *parent) +{ + struct menu *menu, *last_menu; + struct symbol *sym; + struct property *prop; + struct expr *parentdep, *basedep, *dep, *dep2, **ep; + + sym = parent->sym; + if (parent->list) { + if (sym && sym_is_choice(sym)) { + if (sym->type == S_UNKNOWN) { + /* find the first choice value to find out choice type */ + current_entry = parent; + for (menu = parent->list; menu; menu = menu->next) { + if (menu->sym && menu->sym->type != S_UNKNOWN) { + menu_set_type(menu->sym->type); + break; + } + } + } + /* set the type of the remaining choice values */ + for (menu = parent->list; menu; menu = menu->next) { + current_entry = menu; + if (menu->sym && menu->sym->type == S_UNKNOWN) + menu_set_type(sym->type); + } + parentdep = expr_alloc_symbol(sym); + } else if (parent->prompt) + parentdep = parent->prompt->visible.expr; + else + parentdep = parent->dep; + + for (menu = parent->list; menu; menu = menu->next) { + basedep = expr_transform(menu->dep); + basedep = expr_alloc_and(expr_copy(parentdep), basedep); + basedep = expr_eliminate_dups(basedep); + menu->dep = basedep; + if (menu->sym) + prop = menu->sym->prop; + else + prop = menu->prompt; + for (; prop; prop = prop->next) { + if (prop->menu != menu) + continue; + dep = expr_transform(prop->visible.expr); + dep = expr_alloc_and(expr_copy(basedep), dep); + dep = expr_eliminate_dups(dep); + if (menu->sym && menu->sym->type != S_TRISTATE) + dep = expr_trans_bool(dep); + prop->visible.expr = dep; + if (prop->type == P_SELECT) { + struct symbol *es = prop_get_symbol(prop); + es->rev_dep.expr = expr_alloc_or(es->rev_dep.expr, + expr_alloc_and(expr_alloc_symbol(menu->sym), expr_copy(dep))); + } + } + } + for (menu = parent->list; menu; menu = menu->next) + menu_finalize(menu); + } else if (sym) { + basedep = parent->prompt ? parent->prompt->visible.expr : NULL; + basedep = expr_trans_compare(basedep, E_UNEQUAL, &symbol_no); + basedep = expr_eliminate_dups(expr_transform(basedep)); + last_menu = NULL; + for (menu = parent->next; menu; menu = menu->next) { + dep = menu->prompt ? menu->prompt->visible.expr : menu->dep; + if (!expr_contains_symbol(dep, sym)) + break; + if (expr_depends_symbol(dep, sym)) + goto next; + dep = expr_trans_compare(dep, E_UNEQUAL, &symbol_no); + dep = expr_eliminate_dups(expr_transform(dep)); + dep2 = expr_copy(basedep); + expr_eliminate_eq(&dep, &dep2); + expr_free(dep); + if (!expr_is_yes(dep2)) { + expr_free(dep2); + break; + } + expr_free(dep2); + next: + menu_finalize(menu); + menu->parent = parent; + last_menu = menu; + } + if (last_menu) { + parent->list = parent->next; + parent->next = last_menu->next; + last_menu->next = NULL; + } + } + for (menu = parent->list; menu; menu = menu->next) { + if (sym && sym_is_choice(sym) && + menu->sym && !sym_is_choice_value(menu->sym)) { + current_entry = menu; + menu->sym->flags |= SYMBOL_CHOICEVAL; + if (!menu->prompt) + menu_warn(menu, "choice value must have a prompt"); + for (prop = menu->sym->prop; prop; prop = prop->next) { + if (prop->type == P_DEFAULT) + prop_warn(prop, "defaults for choice " + "values not supported"); + if (prop->menu == menu) + continue; + if (prop->type == P_PROMPT && + prop->menu->parent->sym != sym) + prop_warn(prop, "choice value used outside its choice group"); + } + /* Non-tristate choice values of tristate choices must + * depend on the choice being set to Y. The choice + * values' dependencies were propagated to their + * properties above, so the change here must be re- + * propagated. + */ + if (sym->type == S_TRISTATE && menu->sym->type != S_TRISTATE) { + basedep = expr_alloc_comp(E_EQUAL, sym, &symbol_yes); + menu->dep = expr_alloc_and(basedep, menu->dep); + for (prop = menu->sym->prop; prop; prop = prop->next) { + if (prop->menu != menu) + continue; + prop->visible.expr = expr_alloc_and(expr_copy(basedep), + prop->visible.expr); + } + } + menu_add_symbol(P_CHOICE, sym, NULL); + prop = sym_get_choice_prop(sym); + for (ep = &prop->expr; *ep; ep = &(*ep)->left.expr) + ; + *ep = expr_alloc_one(E_LIST, NULL); + (*ep)->right.sym = menu->sym; + } + if (menu->list && (!menu->prompt || !menu->prompt->text)) { + for (last_menu = menu->list; ; last_menu = last_menu->next) { + last_menu->parent = parent; + if (!last_menu->next) + break; + } + last_menu->next = menu->next; + menu->next = menu->list; + menu->list = NULL; + } + } + + if (sym && !(sym->flags & SYMBOL_WARNED)) { + if (sym->type == S_UNKNOWN) + menu_warn(parent, "config symbol defined without type"); + + if (sym_is_choice(sym) && !parent->prompt) + menu_warn(parent, "choice must have a prompt"); + + /* Check properties connected to this symbol */ + sym_check_prop(sym); + sym->flags |= SYMBOL_WARNED; + } + + if (sym && !sym_is_optional(sym) && parent->prompt) { + sym->rev_dep.expr = expr_alloc_or(sym->rev_dep.expr, + expr_alloc_and(parent->prompt->visible.expr, + expr_alloc_symbol(&symbol_mod))); + } +} + +bool menu_is_visible(struct menu *menu) +{ + struct menu *child; + struct symbol *sym; + tristate visible; + + if (!menu->prompt) + return false; + sym = menu->sym; + if (sym) { + sym_calc_value(sym); + visible = menu->prompt->visible.tri; + } else + visible = menu->prompt->visible.tri = expr_calc_value(menu->prompt->visible.expr); + + if (visible != no) + return true; + if (!sym || sym_get_tristate_value(menu->sym) == no) + return false; + + for (child = menu->list; child; child = child->next) + if (menu_is_visible(child)) + return true; + return false; +} + +const char *menu_get_prompt(struct menu *menu) +{ + if (menu->prompt) + return menu->prompt->text; + else if (menu->sym) + return menu->sym->name; + return NULL; +} + +struct menu *menu_get_root_menu(struct menu *menu) +{ + return &rootmenu; +} + +struct menu *menu_get_parent_menu(struct menu *menu) +{ + enum prop_type type; + + for (; menu != &rootmenu; menu = menu->parent) { + type = menu->prompt ? menu->prompt->type : 0; + if (type == P_MENU) + break; + } + return menu; +} + +bool menu_has_help(struct menu *menu) +{ + return menu->help != NULL; +} + +const char *menu_get_help(struct menu *menu) +{ + if (menu->help) + return menu->help; + else + return ""; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/qconf.cc b/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/qconf.cc new file mode 100644 index 00000000..ec89fd7f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/qconf.cc @@ -0,0 +1,1759 @@ +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "lkc.h" +#include "qconf.h" + +#include "qconf.moc" +#include "images.c" + +#ifdef _ +# undef _ +# define _ qgettext +#endif + +static QApplication *configApp; +static ConfigSettings *configSettings; + +QAction *ConfigMainWindow::saveAction; + +static inline QString qgettext(const char* str) +{ + return QString::fromLocal8Bit(gettext(str)); +} + +static inline QString qgettext(const QString& str) +{ + return QString::fromLocal8Bit(gettext(str.latin1())); +} + +/** + * Reads a list of integer values from the application settings. + */ +QValueList ConfigSettings::readSizes(const QString& key, bool *ok) +{ + QValueList result; + QStringList entryList = readListEntry(key, ok); + if (ok) { + QStringList::Iterator it; + for (it = entryList.begin(); it != entryList.end(); ++it) + result.push_back((*it).toInt()); + } + + return result; +} + +/** + * Writes a list of integer values to the application settings. + */ +bool ConfigSettings::writeSizes(const QString& key, const QValueList& value) +{ + QStringList stringList; + QValueList::ConstIterator it; + + for (it = value.begin(); it != value.end(); ++it) + stringList.push_back(QString::number(*it)); + return writeEntry(key, stringList); +} + + +#if QT_VERSION >= 300 +/* + * set the new data + * TODO check the value + */ +void ConfigItem::okRename(int col) +{ + Parent::okRename(col); + sym_set_string_value(menu->sym, text(dataColIdx).latin1()); + listView()->updateList(this); +} +#endif + +/* + * update the displayed of a menu entry + */ +void ConfigItem::updateMenu(void) +{ + ConfigList* list; + struct symbol* sym; + struct property *prop; + QString prompt; + int type; + tristate expr; + + list = listView(); + if (goParent) { + setPixmap(promptColIdx, list->menuBackPix); + prompt = ".."; + goto set_prompt; + } + + sym = menu->sym; + prop = menu->prompt; + prompt = _(menu_get_prompt(menu)); + + if (prop) switch (prop->type) { + case P_MENU: + if (list->mode == singleMode || list->mode == symbolMode) { + /* a menuconfig entry is displayed differently + * depending whether it's at the view root or a child. + */ + if (sym && list->rootEntry == menu) + break; + setPixmap(promptColIdx, list->menuPix); + } else { + if (sym) + break; + setPixmap(promptColIdx, 0); + } + goto set_prompt; + case P_COMMENT: + setPixmap(promptColIdx, 0); + goto set_prompt; + default: + ; + } + if (!sym) + goto set_prompt; + + setText(nameColIdx, QString::fromLocal8Bit(sym->name)); + + type = sym_get_type(sym); + switch (type) { + case S_BOOLEAN: + case S_TRISTATE: + char ch; + + if (!sym_is_changable(sym) && !list->showAll) { + setPixmap(promptColIdx, 0); + setText(noColIdx, QString::null); + setText(modColIdx, QString::null); + setText(yesColIdx, QString::null); + break; + } + expr = sym_get_tristate_value(sym); + switch (expr) { + case yes: + if (sym_is_choice_value(sym) && type == S_BOOLEAN) + setPixmap(promptColIdx, list->choiceYesPix); + else + setPixmap(promptColIdx, list->symbolYesPix); + setText(yesColIdx, "Y"); + ch = 'Y'; + break; + case mod: + setPixmap(promptColIdx, list->symbolModPix); + setText(modColIdx, "M"); + ch = 'M'; + break; + default: + if (sym_is_choice_value(sym) && type == S_BOOLEAN) + setPixmap(promptColIdx, list->choiceNoPix); + else + setPixmap(promptColIdx, list->symbolNoPix); + setText(noColIdx, "N"); + ch = 'N'; + break; + } + if (expr != no) + setText(noColIdx, sym_tristate_within_range(sym, no) ? "_" : 0); + if (expr != mod) + setText(modColIdx, sym_tristate_within_range(sym, mod) ? "_" : 0); + if (expr != yes) + setText(yesColIdx, sym_tristate_within_range(sym, yes) ? "_" : 0); + + setText(dataColIdx, QChar(ch)); + break; + case S_INT: + case S_HEX: + case S_STRING: + const char* data; + + data = sym_get_string_value(sym); + +#if QT_VERSION >= 300 + int i = list->mapIdx(dataColIdx); + if (i >= 0) + setRenameEnabled(i, TRUE); +#endif + setText(dataColIdx, data); + if (type == S_STRING) + prompt = QString("%1: %2").arg(prompt).arg(data); + else + prompt = QString("(%2) %1").arg(prompt).arg(data); + break; + } + if (!sym_has_value(sym) && visible) + prompt += _(" (NEW)"); +set_prompt: + setText(promptColIdx, prompt); +} + +void ConfigItem::testUpdateMenu(bool v) +{ + ConfigItem* i; + + visible = v; + if (!menu) + return; + + sym_calc_value(menu->sym); + if (menu->flags & MENU_CHANGED) { + /* the menu entry changed, so update all list items */ + menu->flags &= ~MENU_CHANGED; + for (i = (ConfigItem*)menu->data; i; i = i->nextItem) + i->updateMenu(); + } else if (listView()->updateAll) + updateMenu(); +} + +void ConfigItem::paintCell(QPainter* p, const QColorGroup& cg, int column, int width, int align) +{ + ConfigList* list = listView(); + + if (visible) { + if (isSelected() && !list->hasFocus() && list->mode == menuMode) + Parent::paintCell(p, list->inactivedColorGroup, column, width, align); + else + Parent::paintCell(p, cg, column, width, align); + } else + Parent::paintCell(p, list->disabledColorGroup, column, width, align); +} + +/* + * construct a menu entry + */ +void ConfigItem::init(void) +{ + if (menu) { + ConfigList* list = listView(); + nextItem = (ConfigItem*)menu->data; + menu->data = this; + + if (list->mode != fullMode) + setOpen(TRUE); + sym_calc_value(menu->sym); + } + updateMenu(); +} + +/* + * destruct a menu entry + */ +ConfigItem::~ConfigItem(void) +{ + if (menu) { + ConfigItem** ip = (ConfigItem**)&menu->data; + for (; *ip; ip = &(*ip)->nextItem) { + if (*ip == this) { + *ip = nextItem; + break; + } + } + } +} + +ConfigLineEdit::ConfigLineEdit(ConfigView* parent) + : Parent(parent) +{ + connect(this, SIGNAL(lostFocus()), SLOT(hide())); +} + +void ConfigLineEdit::show(ConfigItem* i) +{ + item = i; + if (sym_get_string_value(item->menu->sym)) + setText(QString::fromLocal8Bit(sym_get_string_value(item->menu->sym))); + else + setText(QString::null); + Parent::show(); + setFocus(); +} + +void ConfigLineEdit::keyPressEvent(QKeyEvent* e) +{ + switch (e->key()) { + case Key_Escape: + break; + case Key_Return: + case Key_Enter: + sym_set_string_value(item->menu->sym, text().latin1()); + parent()->updateList(item); + break; + default: + Parent::keyPressEvent(e); + return; + } + e->accept(); + parent()->list->setFocus(); + hide(); +} + +ConfigList::ConfigList(ConfigView* p, const char *name) + : Parent(p, name), + updateAll(false), + symbolYesPix(xpm_symbol_yes), symbolModPix(xpm_symbol_mod), symbolNoPix(xpm_symbol_no), + choiceYesPix(xpm_choice_yes), choiceNoPix(xpm_choice_no), + menuPix(xpm_menu), menuInvPix(xpm_menu_inv), menuBackPix(xpm_menuback), voidPix(xpm_void), + showAll(false), showName(false), showRange(false), showData(false), + rootEntry(0), headerPopup(0) +{ + int i; + + setSorting(-1); + setRootIsDecorated(TRUE); + disabledColorGroup = palette().active(); + disabledColorGroup.setColor(QColorGroup::Text, palette().disabled().text()); + inactivedColorGroup = palette().active(); + inactivedColorGroup.setColor(QColorGroup::Highlight, palette().disabled().highlight()); + + connect(this, SIGNAL(selectionChanged(void)), + SLOT(updateSelection(void))); + + if (name) { + configSettings->beginGroup(name); + showAll = configSettings->readBoolEntry("/showAll", false); + showName = configSettings->readBoolEntry("/showName", false); + showRange = configSettings->readBoolEntry("/showRange", false); + showData = configSettings->readBoolEntry("/showData", false); + configSettings->endGroup(); + connect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings())); + } + + for (i = 0; i < colNr; i++) + colMap[i] = colRevMap[i] = -1; + addColumn(promptColIdx, _("Option")); + + reinit(); +} + +void ConfigList::reinit(void) +{ + removeColumn(dataColIdx); + removeColumn(yesColIdx); + removeColumn(modColIdx); + removeColumn(noColIdx); + removeColumn(nameColIdx); + + if (showName) + addColumn(nameColIdx, _("Name")); + if (showRange) { + addColumn(noColIdx, "N"); + addColumn(modColIdx, "M"); + addColumn(yesColIdx, "Y"); + } + if (showData) + addColumn(dataColIdx, _("Value")); + + updateListAll(); +} + +void ConfigList::saveSettings(void) +{ + if (name()) { + configSettings->beginGroup(name()); + configSettings->writeEntry("/showName", showName); + configSettings->writeEntry("/showRange", showRange); + configSettings->writeEntry("/showData", showData); + configSettings->writeEntry("/showAll", showAll); + configSettings->endGroup(); + } +} + +ConfigItem* ConfigList::findConfigItem(struct menu *menu) +{ + ConfigItem* item = (ConfigItem*)menu->data; + + for (; item; item = item->nextItem) { + if (this == item->listView()) + break; + } + + return item; +} + +void ConfigList::updateSelection(void) +{ + struct menu *menu; + enum prop_type type; + + ConfigItem* item = (ConfigItem*)selectedItem(); + if (!item) + return; + + menu = item->menu; + emit menuChanged(menu); + if (!menu) + return; + type = menu->prompt ? menu->prompt->type : P_UNKNOWN; + if (mode == menuMode && type == P_MENU) + emit menuSelected(menu); +} + +void ConfigList::updateList(ConfigItem* item) +{ + ConfigItem* last = 0; + + if (!rootEntry) { + if (mode != listMode) + goto update; + QListViewItemIterator it(this); + ConfigItem* item; + + for (; it.current(); ++it) { + item = (ConfigItem*)it.current(); + if (!item->menu) + continue; + item->testUpdateMenu(menu_is_visible(item->menu)); + } + return; + } + + if (rootEntry != &rootmenu && (mode == singleMode || + (mode == symbolMode && rootEntry->parent != &rootmenu))) { + item = firstChild(); + if (!item) + item = new ConfigItem(this, 0, true); + last = item; + } + if ((mode == singleMode || (mode == symbolMode && !(rootEntry->flags & MENU_ROOT))) && + rootEntry->sym && rootEntry->prompt) { + item = last ? last->nextSibling() : firstChild(); + if (!item) + item = new ConfigItem(this, last, rootEntry, true); + else + item->testUpdateMenu(true); + + updateMenuList(item, rootEntry); + triggerUpdate(); + return; + } +update: + updateMenuList(this, rootEntry); + triggerUpdate(); +} + +void ConfigList::setValue(ConfigItem* item, tristate val) +{ + struct symbol* sym; + int type; + tristate oldval; + + sym = item->menu ? item->menu->sym : 0; + if (!sym) + return; + + type = sym_get_type(sym); + switch (type) { + case S_BOOLEAN: + case S_TRISTATE: + oldval = sym_get_tristate_value(sym); + + if (!sym_set_tristate_value(sym, val)) + return; + if (oldval == no && item->menu->list) + item->setOpen(TRUE); + parent()->updateList(item); + break; + } +} + +void ConfigList::changeValue(ConfigItem* item) +{ + struct symbol* sym; + struct menu* menu; + int type, oldexpr, newexpr; + + menu = item->menu; + if (!menu) + return; + sym = menu->sym; + if (!sym) { + if (item->menu->list) + item->setOpen(!item->isOpen()); + return; + } + + type = sym_get_type(sym); + switch (type) { + case S_BOOLEAN: + case S_TRISTATE: + oldexpr = sym_get_tristate_value(sym); + newexpr = sym_toggle_tristate_value(sym); + if (item->menu->list) { + if (oldexpr == newexpr) + item->setOpen(!item->isOpen()); + else if (oldexpr == no) + item->setOpen(TRUE); + } + if (oldexpr != newexpr) + parent()->updateList(item); + break; + case S_INT: + case S_HEX: + case S_STRING: +#if QT_VERSION >= 300 + if (colMap[dataColIdx] >= 0) + item->startRename(colMap[dataColIdx]); + else +#endif + parent()->lineEdit->show(item); + break; + } +} + +void ConfigList::setRootMenu(struct menu *menu) +{ + enum prop_type type; + + if (rootEntry == menu) + return; + type = menu && menu->prompt ? menu->prompt->type : P_UNKNOWN; + if (type != P_MENU) + return; + updateMenuList(this, 0); + rootEntry = menu; + updateListAll(); + setSelected(currentItem(), hasFocus()); + ensureItemVisible(currentItem()); +} + +void ConfigList::setParentMenu(void) +{ + ConfigItem* item; + struct menu *oldroot; + + oldroot = rootEntry; + if (rootEntry == &rootmenu) + return; + setRootMenu(menu_get_parent_menu(rootEntry->parent)); + + QListViewItemIterator it(this); + for (; (item = (ConfigItem*)it.current()); it++) { + if (item->menu == oldroot) { + setCurrentItem(item); + ensureItemVisible(item); + break; + } + } +} + +/* + * update all the children of a menu entry + * removes/adds the entries from the parent widget as necessary + * + * parent: either the menu list widget or a menu entry widget + * menu: entry to be updated + */ +template +void ConfigList::updateMenuList(P* parent, struct menu* menu) +{ + struct menu* child; + ConfigItem* item; + ConfigItem* last; + bool visible; + enum prop_type type; + + if (!menu) { + while ((item = parent->firstChild())) + delete item; + return; + } + + last = parent->firstChild(); + if (last && !last->goParent) + last = 0; + for (child = menu->list; child; child = child->next) { + item = last ? last->nextSibling() : parent->firstChild(); + type = child->prompt ? child->prompt->type : P_UNKNOWN; + + switch (mode) { + case menuMode: + if (!(child->flags & MENU_ROOT)) + goto hide; + break; + case symbolMode: + if (child->flags & MENU_ROOT) + goto hide; + break; + default: + break; + } + + visible = menu_is_visible(child); + if (showAll || visible) { + if (!child->sym && !child->list && !child->prompt) + continue; + if (!item || item->menu != child) + item = new ConfigItem(parent, last, child, visible); + else + item->testUpdateMenu(visible); + + if (mode == fullMode || mode == menuMode || type != P_MENU) + updateMenuList(item, child); + else + updateMenuList(item, 0); + last = item; + continue; + } + hide: + if (item && item->menu == child) { + last = parent->firstChild(); + if (last == item) + last = 0; + else while (last->nextSibling() != item) + last = last->nextSibling(); + delete item; + } + } +} + +void ConfigList::keyPressEvent(QKeyEvent* ev) +{ + QListViewItem* i = currentItem(); + ConfigItem* item; + struct menu *menu; + enum prop_type type; + + if (ev->key() == Key_Escape && mode != fullMode && mode != listMode) { + emit parentSelected(); + ev->accept(); + return; + } + + if (!i) { + Parent::keyPressEvent(ev); + return; + } + item = (ConfigItem*)i; + + switch (ev->key()) { + case Key_Return: + case Key_Enter: + if (item->goParent) { + emit parentSelected(); + break; + } + menu = item->menu; + if (!menu) + break; + type = menu->prompt ? menu->prompt->type : P_UNKNOWN; + if (type == P_MENU && rootEntry != menu && + mode != fullMode && mode != menuMode) { + emit menuSelected(menu); + break; + } + case Key_Space: + changeValue(item); + break; + case Key_N: + setValue(item, no); + break; + case Key_M: + setValue(item, mod); + break; + case Key_Y: + setValue(item, yes); + break; + default: + Parent::keyPressEvent(ev); + return; + } + ev->accept(); +} + +void ConfigList::contentsMousePressEvent(QMouseEvent* e) +{ + //QPoint p(contentsToViewport(e->pos())); + //printf("contentsMousePressEvent: %d,%d\n", p.x(), p.y()); + Parent::contentsMousePressEvent(e); +} + +void ConfigList::contentsMouseReleaseEvent(QMouseEvent* e) +{ + QPoint p(contentsToViewport(e->pos())); + ConfigItem* item = (ConfigItem*)itemAt(p); + struct menu *menu; + enum prop_type ptype; + const QPixmap* pm; + int idx, x; + + if (!item) + goto skip; + + menu = item->menu; + x = header()->offset() + p.x(); + idx = colRevMap[header()->sectionAt(x)]; + switch (idx) { + case promptColIdx: + pm = item->pixmap(promptColIdx); + if (pm) { + int off = header()->sectionPos(0) + itemMargin() + + treeStepSize() * (item->depth() + (rootIsDecorated() ? 1 : 0)); + if (x >= off && x < off + pm->width()) { + if (item->goParent) { + emit parentSelected(); + break; + } else if (!menu) + break; + ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN; + if (ptype == P_MENU && rootEntry != menu && + mode != fullMode && mode != menuMode) + emit menuSelected(menu); + else + changeValue(item); + } + } + break; + case noColIdx: + setValue(item, no); + break; + case modColIdx: + setValue(item, mod); + break; + case yesColIdx: + setValue(item, yes); + break; + case dataColIdx: + changeValue(item); + break; + } + +skip: + //printf("contentsMouseReleaseEvent: %d,%d\n", p.x(), p.y()); + Parent::contentsMouseReleaseEvent(e); +} + +void ConfigList::contentsMouseMoveEvent(QMouseEvent* e) +{ + //QPoint p(contentsToViewport(e->pos())); + //printf("contentsMouseMoveEvent: %d,%d\n", p.x(), p.y()); + Parent::contentsMouseMoveEvent(e); +} + +void ConfigList::contentsMouseDoubleClickEvent(QMouseEvent* e) +{ + QPoint p(contentsToViewport(e->pos())); + ConfigItem* item = (ConfigItem*)itemAt(p); + struct menu *menu; + enum prop_type ptype; + + if (!item) + goto skip; + if (item->goParent) { + emit parentSelected(); + goto skip; + } + menu = item->menu; + if (!menu) + goto skip; + ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN; + if (ptype == P_MENU && (mode == singleMode || mode == symbolMode)) + emit menuSelected(menu); + else if (menu->sym) + changeValue(item); + +skip: + //printf("contentsMouseDoubleClickEvent: %d,%d\n", p.x(), p.y()); + Parent::contentsMouseDoubleClickEvent(e); +} + +void ConfigList::focusInEvent(QFocusEvent *e) +{ + struct menu *menu = NULL; + + Parent::focusInEvent(e); + + ConfigItem* item = (ConfigItem *)currentItem(); + if (item) { + setSelected(item, TRUE); + menu = item->menu; + } + emit gotFocus(menu); +} + +void ConfigList::contextMenuEvent(QContextMenuEvent *e) +{ + if (e->y() <= header()->geometry().bottom()) { + if (!headerPopup) { + QAction *action; + + headerPopup = new QPopupMenu(this); + action = new QAction(NULL, _("Show Name"), 0, this); + action->setToggleAction(TRUE); + connect(action, SIGNAL(toggled(bool)), + parent(), SLOT(setShowName(bool))); + connect(parent(), SIGNAL(showNameChanged(bool)), + action, SLOT(setOn(bool))); + action->setOn(showName); + action->addTo(headerPopup); + action = new QAction(NULL, _("Show Range"), 0, this); + action->setToggleAction(TRUE); + connect(action, SIGNAL(toggled(bool)), + parent(), SLOT(setShowRange(bool))); + connect(parent(), SIGNAL(showRangeChanged(bool)), + action, SLOT(setOn(bool))); + action->setOn(showRange); + action->addTo(headerPopup); + action = new QAction(NULL, _("Show Data"), 0, this); + action->setToggleAction(TRUE); + connect(action, SIGNAL(toggled(bool)), + parent(), SLOT(setShowData(bool))); + connect(parent(), SIGNAL(showDataChanged(bool)), + action, SLOT(setOn(bool))); + action->setOn(showData); + action->addTo(headerPopup); + } + headerPopup->exec(e->globalPos()); + e->accept(); + } else + e->ignore(); +} + +ConfigView* ConfigView::viewList; + +ConfigView::ConfigView(QWidget* parent, const char *name) + : Parent(parent, name) +{ + list = new ConfigList(this, name); + lineEdit = new ConfigLineEdit(this); + lineEdit->hide(); + + this->nextView = viewList; + viewList = this; +} + +ConfigView::~ConfigView(void) +{ + ConfigView** vp; + + for (vp = &viewList; *vp; vp = &(*vp)->nextView) { + if (*vp == this) { + *vp = nextView; + break; + } + } +} + +void ConfigView::setShowAll(bool b) +{ + if (list->showAll != b) { + list->showAll = b; + list->updateListAll(); + emit showAllChanged(b); + } +} + +void ConfigView::setShowName(bool b) +{ + if (list->showName != b) { + list->showName = b; + list->reinit(); + emit showNameChanged(b); + } +} + +void ConfigView::setShowRange(bool b) +{ + if (list->showRange != b) { + list->showRange = b; + list->reinit(); + emit showRangeChanged(b); + } +} + +void ConfigView::setShowData(bool b) +{ + if (list->showData != b) { + list->showData = b; + list->reinit(); + emit showDataChanged(b); + } +} + +void ConfigList::setAllOpen(bool open) +{ + QListViewItemIterator it(this); + + for (; it.current(); it++) + it.current()->setOpen(open); +} + +void ConfigView::updateList(ConfigItem* item) +{ + ConfigView* v; + + for (v = viewList; v; v = v->nextView) + v->list->updateList(item); +} + +void ConfigView::updateListAll(void) +{ + ConfigView* v; + + for (v = viewList; v; v = v->nextView) + v->list->updateListAll(); +} + +ConfigInfoView::ConfigInfoView(QWidget* parent, const char *name) + : Parent(parent, name), menu(0), sym(0) +{ + if (name) { + configSettings->beginGroup(name); + _showDebug = configSettings->readBoolEntry("/showDebug", false); + configSettings->endGroup(); + connect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings())); + } +} + +void ConfigInfoView::saveSettings(void) +{ + if (name()) { + configSettings->beginGroup(name()); + configSettings->writeEntry("/showDebug", showDebug()); + configSettings->endGroup(); + } +} + +void ConfigInfoView::setShowDebug(bool b) +{ + if (_showDebug != b) { + _showDebug = b; + if (menu) + menuInfo(); + else if (sym) + symbolInfo(); + emit showDebugChanged(b); + } +} + +void ConfigInfoView::setInfo(struct menu *m) +{ + if (menu == m) + return; + menu = m; + sym = NULL; + if (!menu) + clear(); + else + menuInfo(); +} + +void ConfigInfoView::setSource(const QString& name) +{ + const char *p = name.latin1(); + + menu = NULL; + sym = NULL; + + switch (p[0]) { + case 'm': + struct menu *m; + + if (sscanf(p, "m%p", &m) == 1 && menu != m) { + menu = m; + menuInfo(); + emit menuSelected(menu); + } + break; + case 's': + struct symbol *s; + + if (sscanf(p, "s%p", &s) == 1 && sym != s) { + sym = s; + symbolInfo(); + } + break; + } +} + +void ConfigInfoView::symbolInfo(void) +{ + QString str; + + str += "Symbol: "; + str += print_filter(sym->name); + str += "

value: "; + str += print_filter(sym_get_string_value(sym)); + str += "
visibility: "; + str += sym->visible == yes ? "y" : sym->visible == mod ? "m" : "n"; + str += "
"; + str += debug_info(sym); + + setText(str); +} + +void ConfigInfoView::menuInfo(void) +{ + struct symbol* sym; + QString head, debug, help; + + sym = menu->sym; + if (sym) { + if (menu->prompt) { + head += ""; + head += print_filter(_(menu->prompt->text)); + head += ""; + if (sym->name) { + head += " ("; + if (showDebug()) + head += QString().sprintf("", sym); + head += print_filter(sym->name); + if (showDebug()) + head += ""; + head += ")"; + } + } else if (sym->name) { + head += ""; + if (showDebug()) + head += QString().sprintf("", sym); + head += print_filter(sym->name); + if (showDebug()) + head += ""; + head += ""; + } + head += "

"; + + if (showDebug()) + debug = debug_info(sym); + + help = menu_get_help(menu); + /* Gettextize if the help text not empty */ + if (help.isEmpty()) + help = print_filter(menu_get_help(menu)); + else + help = print_filter(_(menu_get_help(menu))); + } else if (menu->prompt) { + head += ""; + head += print_filter(_(menu->prompt->text)); + head += "

"; + if (showDebug()) { + if (menu->prompt->visible.expr) { + debug += "  dep: "; + expr_print(menu->prompt->visible.expr, expr_print_help, &debug, E_NONE); + debug += "

"; + } + } + } + if (showDebug()) + debug += QString().sprintf("defined at %s:%d

", menu->file->name, menu->lineno); + + setText(head + debug + help); +} + +QString ConfigInfoView::debug_info(struct symbol *sym) +{ + QString debug; + + debug += "type: "; + debug += print_filter(sym_type_name(sym->type)); + if (sym_is_choice(sym)) + debug += " (choice)"; + debug += "
"; + if (sym->rev_dep.expr) { + debug += "reverse dep: "; + expr_print(sym->rev_dep.expr, expr_print_help, &debug, E_NONE); + debug += "
"; + } + for (struct property *prop = sym->prop; prop; prop = prop->next) { + switch (prop->type) { + case P_PROMPT: + case P_MENU: + debug += QString().sprintf("prompt: ", prop->menu); + debug += print_filter(_(prop->text)); + debug += "
"; + break; + case P_DEFAULT: + case P_SELECT: + case P_RANGE: + case P_ENV: + debug += prop_get_type_name(prop->type); + debug += ": "; + expr_print(prop->expr, expr_print_help, &debug, E_NONE); + debug += "
"; + break; + case P_CHOICE: + if (sym_is_choice(sym)) { + debug += "choice: "; + expr_print(prop->expr, expr_print_help, &debug, E_NONE); + debug += "
"; + } + break; + default: + debug += "unknown property: "; + debug += prop_get_type_name(prop->type); + debug += "
"; + } + if (prop->visible.expr) { + debug += "    dep: "; + expr_print(prop->visible.expr, expr_print_help, &debug, E_NONE); + debug += "
"; + } + } + debug += "
"; + + return debug; +} + +QString ConfigInfoView::print_filter(const QString &str) +{ + QRegExp re("[<>&\"\\n]"); + QString res = str; + for (int i = 0; (i = res.find(re, i)) >= 0;) { + switch (res[i].latin1()) { + case '<': + res.replace(i, 1, "<"); + i += 4; + break; + case '>': + res.replace(i, 1, ">"); + i += 4; + break; + case '&': + res.replace(i, 1, "&"); + i += 5; + break; + case '"': + res.replace(i, 1, """); + i += 6; + break; + case '\n': + res.replace(i, 1, "
"); + i += 4; + break; + } + } + return res; +} + +void ConfigInfoView::expr_print_help(void *data, struct symbol *sym, const char *str) +{ + QString* text = reinterpret_cast(data); + QString str2 = print_filter(str); + + if (sym && sym->name && !(sym->flags & SYMBOL_CONST)) { + *text += QString().sprintf("", sym); + *text += str2; + *text += ""; + } else + *text += str2; +} + +QPopupMenu* ConfigInfoView::createPopupMenu(const QPoint& pos) +{ + QPopupMenu* popup = Parent::createPopupMenu(pos); + QAction* action = new QAction(NULL, _("Show Debug Info"), 0, popup); + action->setToggleAction(TRUE); + connect(action, SIGNAL(toggled(bool)), SLOT(setShowDebug(bool))); + connect(this, SIGNAL(showDebugChanged(bool)), action, SLOT(setOn(bool))); + action->setOn(showDebug()); + popup->insertSeparator(); + action->addTo(popup); + return popup; +} + +void ConfigInfoView::contentsContextMenuEvent(QContextMenuEvent *e) +{ + Parent::contentsContextMenuEvent(e); +} + +ConfigSearchWindow::ConfigSearchWindow(ConfigMainWindow* parent, const char *name) + : Parent(parent, name), result(NULL) +{ + setCaption("Search Config"); + + QVBoxLayout* layout1 = new QVBoxLayout(this, 11, 6); + QHBoxLayout* layout2 = new QHBoxLayout(0, 0, 6); + layout2->addWidget(new QLabel(_("Find:"), this)); + editField = new QLineEdit(this); + connect(editField, SIGNAL(returnPressed()), SLOT(search())); + layout2->addWidget(editField); + searchButton = new QPushButton(_("Search"), this); + searchButton->setAutoDefault(FALSE); + connect(searchButton, SIGNAL(clicked()), SLOT(search())); + layout2->addWidget(searchButton); + layout1->addLayout(layout2); + + split = new QSplitter(this); + split->setOrientation(QSplitter::Vertical); + list = new ConfigView(split, name); + list->list->mode = listMode; + info = new ConfigInfoView(split, name); + connect(list->list, SIGNAL(menuChanged(struct menu *)), + info, SLOT(setInfo(struct menu *))); + connect(list->list, SIGNAL(menuChanged(struct menu *)), + parent, SLOT(setMenuLink(struct menu *))); + + layout1->addWidget(split); + + if (name) { + int x, y, width, height; + bool ok; + + configSettings->beginGroup(name); + width = configSettings->readNumEntry("/window width", parent->width() / 2); + height = configSettings->readNumEntry("/window height", parent->height() / 2); + resize(width, height); + x = configSettings->readNumEntry("/window x", 0, &ok); + if (ok) + y = configSettings->readNumEntry("/window y", 0, &ok); + if (ok) + move(x, y); + QValueList sizes = configSettings->readSizes("/split", &ok); + if (ok) + split->setSizes(sizes); + configSettings->endGroup(); + connect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings())); + } +} + +void ConfigSearchWindow::saveSettings(void) +{ + if (name()) { + configSettings->beginGroup(name()); + configSettings->writeEntry("/window x", pos().x()); + configSettings->writeEntry("/window y", pos().y()); + configSettings->writeEntry("/window width", size().width()); + configSettings->writeEntry("/window height", size().height()); + configSettings->writeSizes("/split", split->sizes()); + configSettings->endGroup(); + } +} + +void ConfigSearchWindow::search(void) +{ + struct symbol **p; + struct property *prop; + ConfigItem *lastItem = NULL; + + free(result); + list->list->clear(); + info->clear(); + + result = sym_re_search(editField->text().latin1()); + if (!result) + return; + for (p = result; *p; p++) { + for_all_prompts((*p), prop) + lastItem = new ConfigItem(list->list, lastItem, prop->menu, + menu_is_visible(prop->menu)); + } +} + +/* + * Construct the complete config widget + */ +ConfigMainWindow::ConfigMainWindow(void) + : searchWindow(0) +{ + QMenuBar* menu; + bool ok; + int x, y, width, height; + char title[256]; + + QWidget *d = configApp->desktop(); + snprintf(title, sizeof(title), _("uClibc v%s Configuration"), + getenv("VERSION")); + setCaption(title); + + width = configSettings->readNumEntry("/window width", d->width() - 64); + height = configSettings->readNumEntry("/window height", d->height() - 64); + resize(width, height); + x = configSettings->readNumEntry("/window x", 0, &ok); + if (ok) + y = configSettings->readNumEntry("/window y", 0, &ok); + if (ok) + move(x, y); + + split1 = new QSplitter(this); + split1->setOrientation(QSplitter::Horizontal); + setCentralWidget(split1); + + menuView = new ConfigView(split1, "menu"); + menuList = menuView->list; + + split2 = new QSplitter(split1); + split2->setOrientation(QSplitter::Vertical); + + // create config tree + configView = new ConfigView(split2, "config"); + configList = configView->list; + + helpText = new ConfigInfoView(split2, "help"); + helpText->setTextFormat(Qt::RichText); + + setTabOrder(configList, helpText); + configList->setFocus(); + + menu = menuBar(); + toolBar = new QToolBar("Tools", this); + + backAction = new QAction("Back", QPixmap(xpm_back), _("Back"), 0, this); + connect(backAction, SIGNAL(activated()), SLOT(goBack())); + backAction->setEnabled(FALSE); + QAction *quitAction = new QAction("Quit", _("&Quit"), CTRL+Key_Q, this); + connect(quitAction, SIGNAL(activated()), SLOT(close())); + QAction *loadAction = new QAction("Load", QPixmap(xpm_load), _("&Load"), CTRL+Key_L, this); + connect(loadAction, SIGNAL(activated()), SLOT(loadConfig())); + saveAction = new QAction("Save", QPixmap(xpm_save), _("&Save"), CTRL+Key_S, this); + connect(saveAction, SIGNAL(activated()), SLOT(saveConfig())); + conf_set_changed_callback(conf_changed); + // Set saveAction's initial state + conf_changed(); + QAction *saveAsAction = new QAction("Save As...", _("Save &As..."), 0, this); + connect(saveAsAction, SIGNAL(activated()), SLOT(saveConfigAs())); + QAction *searchAction = new QAction("Find", _("&Find"), CTRL+Key_F, this); + connect(searchAction, SIGNAL(activated()), SLOT(searchConfig())); + QAction *singleViewAction = new QAction("Single View", QPixmap(xpm_single_view), _("Single View"), 0, this); + connect(singleViewAction, SIGNAL(activated()), SLOT(showSingleView())); + QAction *splitViewAction = new QAction("Split View", QPixmap(xpm_split_view), _("Split View"), 0, this); + connect(splitViewAction, SIGNAL(activated()), SLOT(showSplitView())); + QAction *fullViewAction = new QAction("Full View", QPixmap(xpm_tree_view), _("Full View"), 0, this); + connect(fullViewAction, SIGNAL(activated()), SLOT(showFullView())); + + QAction *showNameAction = new QAction(NULL, _("Show Name"), 0, this); + showNameAction->setToggleAction(TRUE); + connect(showNameAction, SIGNAL(toggled(bool)), configView, SLOT(setShowName(bool))); + connect(configView, SIGNAL(showNameChanged(bool)), showNameAction, SLOT(setOn(bool))); + showNameAction->setOn(configView->showName()); + QAction *showRangeAction = new QAction(NULL, _("Show Range"), 0, this); + showRangeAction->setToggleAction(TRUE); + connect(showRangeAction, SIGNAL(toggled(bool)), configView, SLOT(setShowRange(bool))); + connect(configView, SIGNAL(showRangeChanged(bool)), showRangeAction, SLOT(setOn(bool))); + showRangeAction->setOn(configList->showRange); + QAction *showDataAction = new QAction(NULL, _("Show Data"), 0, this); + showDataAction->setToggleAction(TRUE); + connect(showDataAction, SIGNAL(toggled(bool)), configView, SLOT(setShowData(bool))); + connect(configView, SIGNAL(showDataChanged(bool)), showDataAction, SLOT(setOn(bool))); + showDataAction->setOn(configList->showData); + QAction *showAllAction = new QAction(NULL, _("Show All Options"), 0, this); + showAllAction->setToggleAction(TRUE); + connect(showAllAction, SIGNAL(toggled(bool)), configView, SLOT(setShowAll(bool))); + connect(showAllAction, SIGNAL(toggled(bool)), menuView, SLOT(setShowAll(bool))); + showAllAction->setOn(configList->showAll); + QAction *showDebugAction = new QAction(NULL, _("Show Debug Info"), 0, this); + showDebugAction->setToggleAction(TRUE); + connect(showDebugAction, SIGNAL(toggled(bool)), helpText, SLOT(setShowDebug(bool))); + connect(helpText, SIGNAL(showDebugChanged(bool)), showDebugAction, SLOT(setOn(bool))); + showDebugAction->setOn(helpText->showDebug()); + + QAction *showIntroAction = new QAction(NULL, _("Introduction"), 0, this); + connect(showIntroAction, SIGNAL(activated()), SLOT(showIntro())); + QAction *showAboutAction = new QAction(NULL, _("About"), 0, this); + connect(showAboutAction, SIGNAL(activated()), SLOT(showAbout())); + + // init tool bar + backAction->addTo(toolBar); + toolBar->addSeparator(); + loadAction->addTo(toolBar); + saveAction->addTo(toolBar); + toolBar->addSeparator(); + singleViewAction->addTo(toolBar); + splitViewAction->addTo(toolBar); + fullViewAction->addTo(toolBar); + + // create config menu + QPopupMenu* config = new QPopupMenu(this); + menu->insertItem(_("&File"), config); + loadAction->addTo(config); + saveAction->addTo(config); + saveAsAction->addTo(config); + config->insertSeparator(); + quitAction->addTo(config); + + // create edit menu + QPopupMenu* editMenu = new QPopupMenu(this); + menu->insertItem(_("&Edit"), editMenu); + searchAction->addTo(editMenu); + + // create options menu + QPopupMenu* optionMenu = new QPopupMenu(this); + menu->insertItem(_("&Option"), optionMenu); + showNameAction->addTo(optionMenu); + showRangeAction->addTo(optionMenu); + showDataAction->addTo(optionMenu); + optionMenu->insertSeparator(); + showAllAction->addTo(optionMenu); + showDebugAction->addTo(optionMenu); + + // create help menu + QPopupMenu* helpMenu = new QPopupMenu(this); + menu->insertSeparator(); + menu->insertItem(_("&Help"), helpMenu); + showIntroAction->addTo(helpMenu); + showAboutAction->addTo(helpMenu); + + connect(configList, SIGNAL(menuChanged(struct menu *)), + helpText, SLOT(setInfo(struct menu *))); + connect(configList, SIGNAL(menuSelected(struct menu *)), + SLOT(changeMenu(struct menu *))); + connect(configList, SIGNAL(parentSelected()), + SLOT(goBack())); + connect(menuList, SIGNAL(menuChanged(struct menu *)), + helpText, SLOT(setInfo(struct menu *))); + connect(menuList, SIGNAL(menuSelected(struct menu *)), + SLOT(changeMenu(struct menu *))); + + connect(configList, SIGNAL(gotFocus(struct menu *)), + helpText, SLOT(setInfo(struct menu *))); + connect(menuList, SIGNAL(gotFocus(struct menu *)), + helpText, SLOT(setInfo(struct menu *))); + connect(menuList, SIGNAL(gotFocus(struct menu *)), + SLOT(listFocusChanged(void))); + connect(helpText, SIGNAL(menuSelected(struct menu *)), + SLOT(setMenuLink(struct menu *))); + + QString listMode = configSettings->readEntry("/listMode", "symbol"); + if (listMode == "single") + showSingleView(); + else if (listMode == "full") + showFullView(); + else /*if (listMode == "split")*/ + showSplitView(); + + // UI setup done, restore splitter positions + QValueList sizes = configSettings->readSizes("/split1", &ok); + if (ok) + split1->setSizes(sizes); + + sizes = configSettings->readSizes("/split2", &ok); + if (ok) + split2->setSizes(sizes); +} + +void ConfigMainWindow::loadConfig(void) +{ + QString s = QFileDialog::getOpenFileName(".config", NULL, this); + if (s.isNull()) + return; + if (conf_read(QFile::encodeName(s))) + QMessageBox::information(this, "qconf", _("Unable to load configuration!")); + ConfigView::updateListAll(); +} + +void ConfigMainWindow::saveConfig(void) +{ + if (conf_write(NULL)) + QMessageBox::information(this, "qconf", _("Unable to save configuration!")); +} + +void ConfigMainWindow::saveConfigAs(void) +{ + QString s = QFileDialog::getSaveFileName(".config", NULL, this); + if (s.isNull()) + return; + if (conf_write(QFile::encodeName(s))) + QMessageBox::information(this, "qconf", _("Unable to save configuration!")); +} + +void ConfigMainWindow::searchConfig(void) +{ + if (!searchWindow) + searchWindow = new ConfigSearchWindow(this, "search"); + searchWindow->show(); +} + +void ConfigMainWindow::changeMenu(struct menu *menu) +{ + configList->setRootMenu(menu); + if (configList->rootEntry->parent == &rootmenu) + backAction->setEnabled(FALSE); + else + backAction->setEnabled(TRUE); +} + +void ConfigMainWindow::setMenuLink(struct menu *menu) +{ + struct menu *parent; + ConfigList* list = NULL; + ConfigItem* item; + + if (!menu_is_visible(menu) && !configView->showAll()) + return; + + switch (configList->mode) { + case singleMode: + list = configList; + parent = menu_get_parent_menu(menu); + if (!parent) + return; + list->setRootMenu(parent); + break; + case symbolMode: + if (menu->flags & MENU_ROOT) { + configList->setRootMenu(menu); + configList->clearSelection(); + list = menuList; + } else { + list = configList; + parent = menu_get_parent_menu(menu->parent); + if (!parent) + return; + item = menuList->findConfigItem(parent); + if (item) { + menuList->setSelected(item, TRUE); + menuList->ensureItemVisible(item); + } + list->setRootMenu(parent); + } + break; + case fullMode: + list = configList; + break; + } + + if (list) { + item = list->findConfigItem(menu); + if (item) { + list->setSelected(item, TRUE); + list->ensureItemVisible(item); + list->setFocus(); + } + } +} + +void ConfigMainWindow::listFocusChanged(void) +{ + if (menuList->mode == menuMode) + configList->clearSelection(); +} + +void ConfigMainWindow::goBack(void) +{ + ConfigItem* item; + + configList->setParentMenu(); + if (configList->rootEntry == &rootmenu) + backAction->setEnabled(FALSE); + item = (ConfigItem*)menuList->selectedItem(); + while (item) { + if (item->menu == configList->rootEntry) { + menuList->setSelected(item, TRUE); + break; + } + item = (ConfigItem*)item->parent(); + } +} + +void ConfigMainWindow::showSingleView(void) +{ + menuView->hide(); + menuList->setRootMenu(0); + configList->mode = singleMode; + if (configList->rootEntry == &rootmenu) + configList->updateListAll(); + else + configList->setRootMenu(&rootmenu); + configList->setAllOpen(TRUE); + configList->setFocus(); +} + +void ConfigMainWindow::showSplitView(void) +{ + configList->mode = symbolMode; + if (configList->rootEntry == &rootmenu) + configList->updateListAll(); + else + configList->setRootMenu(&rootmenu); + configList->setAllOpen(TRUE); + configApp->processEvents(); + menuList->mode = menuMode; + menuList->setRootMenu(&rootmenu); + menuList->setAllOpen(TRUE); + menuView->show(); + menuList->setFocus(); +} + +void ConfigMainWindow::showFullView(void) +{ + menuView->hide(); + menuList->setRootMenu(0); + configList->mode = fullMode; + if (configList->rootEntry == &rootmenu) + configList->updateListAll(); + else + configList->setRootMenu(&rootmenu); + configList->setAllOpen(FALSE); + configList->setFocus(); +} + +/* + * ask for saving configuration before quitting + * TODO ask only when something changed + */ +void ConfigMainWindow::closeEvent(QCloseEvent* e) +{ + if (!conf_get_changed()) { + e->accept(); + return; + } + QMessageBox mb("qconf", _("Save configuration?"), QMessageBox::Warning, + QMessageBox::Yes | QMessageBox::Default, QMessageBox::No, QMessageBox::Cancel | QMessageBox::Escape); + mb.setButtonText(QMessageBox::Yes, _("&Save Changes")); + mb.setButtonText(QMessageBox::No, _("&Discard Changes")); + mb.setButtonText(QMessageBox::Cancel, _("Cancel Exit")); + switch (mb.exec()) { + case QMessageBox::Yes: + conf_write(NULL); + case QMessageBox::No: + e->accept(); + break; + case QMessageBox::Cancel: + e->ignore(); + break; + } +} + +void ConfigMainWindow::showIntro(void) +{ + static const QString str = _("Welcome to the qconf graphical configuration tool for uClibc.\n\n" + "For each option, a blank box indicates the feature is disabled, a check\n" + "indicates it is enabled, and a dot indicates that it is to be compiled\n" + "as a module. Clicking on the box will cycle through the three states.\n\n" + "If you do not see an option (e.g., a device driver) that you believe\n" + "should be present, try turning on Show All Options under the Options menu.\n" + "Although there is no cross reference yet to help you figure out what other\n" + "options must be enabled to support the option you are interested in, you can\n" + "still view the help of a grayed-out option.\n\n" + "Toggling Show Debug Info under the Options menu will show the dependencies,\n" + "which you can then match by examining other options.\n\n"); + + QMessageBox::information(this, "qconf", str); +} + +void ConfigMainWindow::showAbout(void) +{ + static const QString str = _("qconf is Copyright (C) 2002 Roman Zippel .\n\n" + "Bug reports and feature request can also be entered at https://bugs.uClibc.org/\n"); + + QMessageBox::information(this, "qconf", str); +} + +void ConfigMainWindow::saveSettings(void) +{ + configSettings->writeEntry("/window x", pos().x()); + configSettings->writeEntry("/window y", pos().y()); + configSettings->writeEntry("/window width", size().width()); + configSettings->writeEntry("/window height", size().height()); + + QString entry; + switch(configList->mode) { + case singleMode : + entry = "single"; + break; + + case symbolMode : + entry = "split"; + break; + + case fullMode : + entry = "full"; + break; + } + configSettings->writeEntry("/listMode", entry); + + configSettings->writeSizes("/split1", split1->sizes()); + configSettings->writeSizes("/split2", split2->sizes()); +} + +void ConfigMainWindow::conf_changed(void) +{ + if (saveAction) + saveAction->setEnabled(conf_get_changed()); +} + +void fixup_rootmenu(struct menu *menu) +{ + struct menu *child; + static int menu_cnt = 0; + + menu->flags |= MENU_ROOT; + for (child = menu->list; child; child = child->next) { + if (child->prompt && child->prompt->type == P_MENU) { + menu_cnt++; + fixup_rootmenu(child); + menu_cnt--; + } else if (!menu_cnt) + fixup_rootmenu(child); + } +} + +static const char *progname; + +static void usage(void) +{ + printf(_("%s \n"), progname); + exit(0); +} + +int main(int ac, char** av) +{ + ConfigMainWindow* v; + const char *name; + + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + +#ifndef LKC_DIRECT_LINK + kconfig_load(); +#endif + + progname = av[0]; + configApp = new QApplication(ac, av); + if (ac > 1 && av[1][0] == '-') { + switch (av[1][1]) { + case 'h': + case '?': + usage(); + } + name = av[2]; + } else + name = av[1]; + if (!name) + usage(); + + conf_parse(name); + fixup_rootmenu(&rootmenu); + conf_read(NULL); + //zconfdump(stdout); + + configSettings = new ConfigSettings(); + configSettings->beginGroup("/kconfig/qconf"); + v = new ConfigMainWindow(); + + //zconfdump(stdout); + configApp->setMainWidget(v); + configApp->connect(configApp, SIGNAL(lastWindowClosed()), SLOT(quit())); + configApp->connect(configApp, SIGNAL(aboutToQuit()), v, SLOT(saveSettings())); + v->show(); + configApp->exec(); + + configSettings->endGroup(); + delete configSettings; + + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/qconf.h b/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/qconf.h new file mode 100644 index 00000000..b3b5657b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/qconf.h @@ -0,0 +1,334 @@ +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +#include +#if QT_VERSION >= 300 +#include +#else +class QSettings { +public: + void beginGroup(const QString& group) { } + void endGroup(void) { } + bool readBoolEntry(const QString& key, bool def = FALSE, bool* ok = 0) const + { if (ok) *ok = FALSE; return def; } + int readNumEntry(const QString& key, int def = 0, bool* ok = 0) const + { if (ok) *ok = FALSE; return def; } + QString readEntry(const QString& key, const QString& def = QString::null, bool* ok = 0) const + { if (ok) *ok = FALSE; return def; } + QStringList readListEntry(const QString& key, bool* ok = 0) const + { if (ok) *ok = FALSE; return QStringList(); } + template + bool writeEntry(const QString& key, t value) + { return TRUE; } +}; +#endif + +class ConfigView; +class ConfigList; +class ConfigItem; +class ConfigLineEdit; +class ConfigMainWindow; + + +class ConfigSettings : public QSettings { +public: + QValueList readSizes(const QString& key, bool *ok); + bool writeSizes(const QString& key, const QValueList& value); +}; + +enum colIdx { + promptColIdx, nameColIdx, noColIdx, modColIdx, yesColIdx, dataColIdx, colNr +}; +enum listMode { + singleMode, menuMode, symbolMode, fullMode, listMode +}; + +class ConfigList : public QListView { + Q_OBJECT + typedef class QListView Parent; +public: + ConfigList(ConfigView* p, const char *name = 0); + void reinit(void); + ConfigView* parent(void) const + { + return (ConfigView*)Parent::parent(); + } + ConfigItem* findConfigItem(struct menu *); + +protected: + void keyPressEvent(QKeyEvent *e); + void contentsMousePressEvent(QMouseEvent *e); + void contentsMouseReleaseEvent(QMouseEvent *e); + void contentsMouseMoveEvent(QMouseEvent *e); + void contentsMouseDoubleClickEvent(QMouseEvent *e); + void focusInEvent(QFocusEvent *e); + void contextMenuEvent(QContextMenuEvent *e); + +public slots: + void setRootMenu(struct menu *menu); + + void updateList(ConfigItem *item); + void setValue(ConfigItem* item, tristate val); + void changeValue(ConfigItem* item); + void updateSelection(void); + void saveSettings(void); +signals: + void menuChanged(struct menu *menu); + void menuSelected(struct menu *menu); + void parentSelected(void); + void gotFocus(struct menu *); + +public: + void updateListAll(void) + { + updateAll = true; + updateList(NULL); + updateAll = false; + } + ConfigList* listView() + { + return this; + } + ConfigItem* firstChild() const + { + return (ConfigItem *)Parent::firstChild(); + } + int mapIdx(colIdx idx) + { + return colMap[idx]; + } + void addColumn(colIdx idx, const QString& label) + { + colMap[idx] = Parent::addColumn(label); + colRevMap[colMap[idx]] = idx; + } + void removeColumn(colIdx idx) + { + int col = colMap[idx]; + if (col >= 0) { + Parent::removeColumn(col); + colRevMap[col] = colMap[idx] = -1; + } + } + void setAllOpen(bool open); + void setParentMenu(void); + + template + void updateMenuList(P*, struct menu*); + + bool updateAll; + + QPixmap symbolYesPix, symbolModPix, symbolNoPix; + QPixmap choiceYesPix, choiceNoPix; + QPixmap menuPix, menuInvPix, menuBackPix, voidPix; + + bool showAll, showName, showRange, showData; + enum listMode mode; + struct menu *rootEntry; + QColorGroup disabledColorGroup; + QColorGroup inactivedColorGroup; + QPopupMenu* headerPopup; + +private: + int colMap[colNr]; + int colRevMap[colNr]; +}; + +class ConfigItem : public QListViewItem { + typedef class QListViewItem Parent; +public: + ConfigItem(QListView *parent, ConfigItem *after, struct menu *m, bool v) + : Parent(parent, after), menu(m), visible(v), goParent(false) + { + init(); + } + ConfigItem(ConfigItem *parent, ConfigItem *after, struct menu *m, bool v) + : Parent(parent, after), menu(m), visible(v), goParent(false) + { + init(); + } + ConfigItem(QListView *parent, ConfigItem *after, bool v) + : Parent(parent, after), menu(0), visible(v), goParent(true) + { + init(); + } + ~ConfigItem(void); + void init(void); +#if QT_VERSION >= 300 + void okRename(int col); +#endif + void updateMenu(void); + void testUpdateMenu(bool v); + ConfigList* listView() const + { + return (ConfigList*)Parent::listView(); + } + ConfigItem* firstChild() const + { + return (ConfigItem *)Parent::firstChild(); + } + ConfigItem* nextSibling() const + { + return (ConfigItem *)Parent::nextSibling(); + } + void setText(colIdx idx, const QString& text) + { + Parent::setText(listView()->mapIdx(idx), text); + } + QString text(colIdx idx) const + { + return Parent::text(listView()->mapIdx(idx)); + } + void setPixmap(colIdx idx, const QPixmap& pm) + { + Parent::setPixmap(listView()->mapIdx(idx), pm); + } + const QPixmap* pixmap(colIdx idx) const + { + return Parent::pixmap(listView()->mapIdx(idx)); + } + void paintCell(QPainter* p, const QColorGroup& cg, int column, int width, int align); + + ConfigItem* nextItem; + struct menu *menu; + bool visible; + bool goParent; +}; + +class ConfigLineEdit : public QLineEdit { + Q_OBJECT + typedef class QLineEdit Parent; +public: + ConfigLineEdit(ConfigView* parent); + ConfigView* parent(void) const + { + return (ConfigView*)Parent::parent(); + } + void show(ConfigItem *i); + void keyPressEvent(QKeyEvent *e); + +public: + ConfigItem *item; +}; + +class ConfigView : public QVBox { + Q_OBJECT + typedef class QVBox Parent; +public: + ConfigView(QWidget* parent, const char *name = 0); + ~ConfigView(void); + static void updateList(ConfigItem* item); + static void updateListAll(void); + + bool showAll(void) const { return list->showAll; } + bool showName(void) const { return list->showName; } + bool showRange(void) const { return list->showRange; } + bool showData(void) const { return list->showData; } +public slots: + void setShowAll(bool); + void setShowName(bool); + void setShowRange(bool); + void setShowData(bool); +signals: + void showAllChanged(bool); + void showNameChanged(bool); + void showRangeChanged(bool); + void showDataChanged(bool); +public: + ConfigList* list; + ConfigLineEdit* lineEdit; + + static ConfigView* viewList; + ConfigView* nextView; +}; + +class ConfigInfoView : public QTextBrowser { + Q_OBJECT + typedef class QTextBrowser Parent; +public: + ConfigInfoView(QWidget* parent, const char *name = 0); + bool showDebug(void) const { return _showDebug; } + +public slots: + void setInfo(struct menu *menu); + void saveSettings(void); + void setSource(const QString& name); + void setShowDebug(bool); + +signals: + void showDebugChanged(bool); + void menuSelected(struct menu *); + +protected: + void symbolInfo(void); + void menuInfo(void); + QString debug_info(struct symbol *sym); + static QString print_filter(const QString &str); + static void expr_print_help(void *data, struct symbol *sym, const char *str); + QPopupMenu* createPopupMenu(const QPoint& pos); + void contentsContextMenuEvent(QContextMenuEvent *e); + + struct symbol *sym; + struct menu *menu; + bool _showDebug; +}; + +class ConfigSearchWindow : public QDialog { + Q_OBJECT + typedef class QDialog Parent; +public: + ConfigSearchWindow(ConfigMainWindow* parent, const char *name = 0); + +public slots: + void saveSettings(void); + void search(void); + +protected: + QLineEdit* editField; + QPushButton* searchButton; + QSplitter* split; + ConfigView* list; + ConfigInfoView* info; + + struct symbol **result; +}; + +class ConfigMainWindow : public QMainWindow { + Q_OBJECT + + static QAction *saveAction; + static void conf_changed(void); +public: + ConfigMainWindow(void); +public slots: + void changeMenu(struct menu *); + void setMenuLink(struct menu *); + void listFocusChanged(void); + void goBack(void); + void loadConfig(void); + void saveConfig(void); + void saveConfigAs(void); + void searchConfig(void); + void showSingleView(void); + void showSplitView(void); + void showFullView(void); + void showIntro(void); + void showAbout(void); + void saveSettings(void); + +protected: + void closeEvent(QCloseEvent *e); + + ConfigSearchWindow *searchWindow; + ConfigView *menuView; + ConfigList *menuList; + ConfigView *configView; + ConfigList *configList; + ConfigInfoView *helpText; + QToolBar *toolBar; + QAction *backAction; + QSplitter* split1; + QSplitter* split2; +}; diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/symbol.c b/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/symbol.c new file mode 100644 index 00000000..b27047c3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/symbol.c @@ -0,0 +1,973 @@ +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +#include +#include +#include +#include + +#define LKC_DIRECT_LINK +#include "lkc.h" + +struct symbol symbol_yes = { + .name = "y", + .curr = { "y", yes }, + .flags = SYMBOL_CONST|SYMBOL_VALID, +}, symbol_mod = { + .name = "m", + .curr = { "m", mod }, + .flags = SYMBOL_CONST|SYMBOL_VALID, +}, symbol_no = { + .name = "n", + .curr = { "n", no }, + .flags = SYMBOL_CONST|SYMBOL_VALID, +}, symbol_empty = { + .name = "", + .curr = { "", no }, + .flags = SYMBOL_VALID, +}; + +struct symbol *sym_defconfig_list; +struct symbol *modules_sym; +tristate modules_val; + +struct expr *sym_env_list; + +void sym_add_default(struct symbol *sym, const char *def) +{ + struct property *prop = prop_alloc(P_DEFAULT, sym); + + prop->expr = expr_alloc_symbol(sym_lookup(def, SYMBOL_CONST)); +} + +void sym_init(void) +{ + struct symbol *sym; + char *p; + static bool inited = false; + + if (inited) + return; + inited = true; + + p = getenv("VERSION"); + if (p) { + sym = sym_lookup("VERSION", 0); + sym->type = S_STRING; + sym->flags |= SYMBOL_AUTO; + sym_add_default(sym, p); + } +} + +enum symbol_type sym_get_type(struct symbol *sym) +{ + enum symbol_type type = sym->type; + + if (type == S_TRISTATE) { + if (sym_is_choice_value(sym) && sym->visible == yes) + type = S_BOOLEAN; + else if (modules_val == no) + type = S_BOOLEAN; + } + return type; +} + +const char *sym_type_name(enum symbol_type type) +{ + switch (type) { + case S_BOOLEAN: + return "boolean"; + case S_TRISTATE: + return "tristate"; + case S_INT: + return "integer"; + case S_HEX: + return "hex"; + case S_STRING: + return "string"; + case S_UNKNOWN: + return "unknown"; + case S_OTHER: + break; + } + return "???"; +} + +struct property *sym_get_choice_prop(struct symbol *sym) +{ + struct property *prop; + + for_all_choices(sym, prop) + return prop; + return NULL; +} + +struct property *sym_get_env_prop(struct symbol *sym) +{ + struct property *prop; + + for_all_properties(sym, prop, P_ENV) + return prop; + return NULL; +} + +struct property *sym_get_default_prop(struct symbol *sym) +{ + struct property *prop; + + for_all_defaults(sym, prop) { + prop->visible.tri = expr_calc_value(prop->visible.expr); + if (prop->visible.tri != no) + return prop; + } + return NULL; +} + +struct property *sym_get_range_prop(struct symbol *sym) +{ + struct property *prop; + + for_all_properties(sym, prop, P_RANGE) { + prop->visible.tri = expr_calc_value(prop->visible.expr); + if (prop->visible.tri != no) + return prop; + } + return NULL; +} + +static int sym_get_range_val(struct symbol *sym, int base) +{ + sym_calc_value(sym); + switch (sym->type) { + case S_INT: + base = 10; + break; + case S_HEX: + base = 16; + break; + default: + break; + } + return strtol(sym->curr.val, NULL, base); +} + +static void sym_validate_range(struct symbol *sym) +{ + struct property *prop; + int base, val, val2; + char str[64]; + + switch (sym->type) { + case S_INT: + base = 10; + break; + case S_HEX: + base = 16; + break; + default: + return; + } + prop = sym_get_range_prop(sym); + if (!prop) + return; + val = strtol(sym->curr.val, NULL, base); + val2 = sym_get_range_val(prop->expr->left.sym, base); + if (val >= val2) { + val2 = sym_get_range_val(prop->expr->right.sym, base); + if (val <= val2) + return; + } + if (sym->type == S_INT) + sprintf(str, "%d", val2); + else + sprintf(str, "0x%x", val2); + sym->curr.val = strdup(str); +} + +static void sym_calc_visibility(struct symbol *sym) +{ + struct property *prop; + tristate tri; + + /* any prompt visible? */ + tri = no; + for_all_prompts(sym, prop) { + prop->visible.tri = expr_calc_value(prop->visible.expr); + tri = EXPR_OR(tri, prop->visible.tri); + } + if (tri == mod && (sym->type != S_TRISTATE || modules_val == no)) + tri = yes; + if (sym->visible != tri) { + sym->visible = tri; + sym_set_changed(sym); + } + if (sym_is_choice_value(sym)) + return; + tri = no; + if (sym->rev_dep.expr) + tri = expr_calc_value(sym->rev_dep.expr); + if (tri == mod && sym_get_type(sym) == S_BOOLEAN) + tri = yes; + if (sym->rev_dep.tri != tri) { + sym->rev_dep.tri = tri; + sym_set_changed(sym); + } +} + +static struct symbol *sym_calc_choice(struct symbol *sym) +{ + struct symbol *def_sym; + struct property *prop; + struct expr *e; + + /* is the user choice visible? */ + def_sym = sym->def[S_DEF_USER].val; + if (def_sym) { + sym_calc_visibility(def_sym); + if (def_sym->visible != no) + return def_sym; + } + + /* any of the defaults visible? */ + for_all_defaults(sym, prop) { + prop->visible.tri = expr_calc_value(prop->visible.expr); + if (prop->visible.tri == no) + continue; + def_sym = prop_get_symbol(prop); + sym_calc_visibility(def_sym); + if (def_sym->visible != no) + return def_sym; + } + + /* just get the first visible value */ + prop = sym_get_choice_prop(sym); + expr_list_for_each_sym(prop->expr, e, def_sym) { + sym_calc_visibility(def_sym); + if (def_sym->visible != no) + return def_sym; + } + + /* no choice? reset tristate value */ + sym->curr.tri = no; + return NULL; +} + +void sym_calc_value(struct symbol *sym) +{ + struct symbol_value newval, oldval; + struct property *prop; + struct expr *e; + + if (!sym) + return; + + if (sym->flags & SYMBOL_VALID) + return; + sym->flags |= SYMBOL_VALID; + + oldval = sym->curr; + + switch (sym->type) { + case S_INT: + case S_HEX: + case S_STRING: + newval = symbol_empty.curr; + break; + case S_BOOLEAN: + case S_TRISTATE: + newval = symbol_no.curr; + break; + default: + sym->curr.val = sym->name; + sym->curr.tri = no; + return; + } + if (!sym_is_choice_value(sym)) + sym->flags &= ~SYMBOL_WRITE; + + sym_calc_visibility(sym); + + /* set default if recursively called */ + sym->curr = newval; + + switch (sym_get_type(sym)) { + case S_BOOLEAN: + case S_TRISTATE: + if (sym_is_choice_value(sym) && sym->visible == yes) { + prop = sym_get_choice_prop(sym); + newval.tri = (prop_get_symbol(prop)->curr.val == sym) ? yes : no; + } else { + if (sym->visible != no) { + /* if the symbol is visible use the user value + * if available, otherwise try the default value + */ + sym->flags |= SYMBOL_WRITE; + if (sym_has_value(sym)) { + newval.tri = EXPR_AND(sym->def[S_DEF_USER].tri, + sym->visible); + goto calc_newval; + } + } + if (sym->rev_dep.tri != no) + sym->flags |= SYMBOL_WRITE; + if (!sym_is_choice(sym)) { + prop = sym_get_default_prop(sym); + if (prop) { + sym->flags |= SYMBOL_WRITE; + newval.tri = EXPR_AND(expr_calc_value(prop->expr), + prop->visible.tri); + } + } + calc_newval: + newval.tri = EXPR_OR(newval.tri, sym->rev_dep.tri); + } + if (newval.tri == mod && sym_get_type(sym) == S_BOOLEAN) + newval.tri = yes; + break; + case S_STRING: + case S_HEX: + case S_INT: + if (sym->visible != no) { + sym->flags |= SYMBOL_WRITE; + if (sym_has_value(sym)) { + newval.val = sym->def[S_DEF_USER].val; + break; + } + } + prop = sym_get_default_prop(sym); + if (prop) { + struct symbol *ds = prop_get_symbol(prop); + if (ds) { + sym->flags |= SYMBOL_WRITE; + sym_calc_value(ds); + newval.val = ds->curr.val; + } + } + break; + default: + ; + } + + sym->curr = newval; + if (sym_is_choice(sym) && newval.tri == yes) + sym->curr.val = sym_calc_choice(sym); + sym_validate_range(sym); + + if (memcmp(&oldval, &sym->curr, sizeof(oldval))) { + sym_set_changed(sym); + if (modules_sym == sym) { + sym_set_all_changed(); + modules_val = modules_sym->curr.tri; + } + } + + if (sym_is_choice(sym)) { + struct symbol *choice_sym; + int flags = sym->flags & (SYMBOL_CHANGED | SYMBOL_WRITE); + + prop = sym_get_choice_prop(sym); + expr_list_for_each_sym(prop->expr, e, choice_sym) { + choice_sym->flags |= flags; + if (flags & SYMBOL_CHANGED) + sym_set_changed(choice_sym); + } + } + + if (sym->flags & SYMBOL_AUTO) + sym->flags &= ~SYMBOL_WRITE; +} + +void sym_clear_all_valid(void) +{ + struct symbol *sym; + int i; + + for_all_symbols(i, sym) + sym->flags &= ~SYMBOL_VALID; + sym_add_change_count(1); + if (modules_sym) + sym_calc_value(modules_sym); +} + +void sym_set_changed(struct symbol *sym) +{ + struct property *prop; + + sym->flags |= SYMBOL_CHANGED; + for (prop = sym->prop; prop; prop = prop->next) { + if (prop->menu) + prop->menu->flags |= MENU_CHANGED; + } +} + +void sym_set_all_changed(void) +{ + struct symbol *sym; + int i; + + for_all_symbols(i, sym) + sym_set_changed(sym); +} + +bool sym_tristate_within_range(struct symbol *sym, tristate val) +{ + int type = sym_get_type(sym); + + if (sym->visible == no) + return false; + + if (type != S_BOOLEAN && type != S_TRISTATE) + return false; + + if (type == S_BOOLEAN && val == mod) + return false; + if (sym->visible <= sym->rev_dep.tri) + return false; + if (sym_is_choice_value(sym) && sym->visible == yes) + return val == yes; + return val >= sym->rev_dep.tri && val <= sym->visible; +} + +bool sym_set_tristate_value(struct symbol *sym, tristate val) +{ + tristate oldval = sym_get_tristate_value(sym); + + if (oldval != val && !sym_tristate_within_range(sym, val)) + return false; + + if (!(sym->flags & SYMBOL_DEF_USER)) { + sym->flags |= SYMBOL_DEF_USER; + sym_set_changed(sym); + } + /* + * setting a choice value also resets the new flag of the choice + * symbol and all other choice values. + */ + if (sym_is_choice_value(sym) && val == yes) { + struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym)); + struct property *prop; + struct expr *e; + + cs->def[S_DEF_USER].val = sym; + cs->flags |= SYMBOL_DEF_USER; + prop = sym_get_choice_prop(cs); + for (e = prop->expr; e; e = e->left.expr) { + if (e->right.sym->visible != no) + e->right.sym->flags |= SYMBOL_DEF_USER; + } + } + + sym->def[S_DEF_USER].tri = val; + if (oldval != val) + sym_clear_all_valid(); + + return true; +} + +tristate sym_toggle_tristate_value(struct symbol *sym) +{ + tristate oldval, newval; + + oldval = newval = sym_get_tristate_value(sym); + do { + switch (newval) { + case no: + newval = mod; + break; + case mod: + newval = yes; + break; + case yes: + newval = no; + break; + } + if (sym_set_tristate_value(sym, newval)) + break; + } while (oldval != newval); + return newval; +} + +bool sym_string_valid(struct symbol *sym, const char *str) +{ + signed char ch; + + switch (sym->type) { + case S_STRING: + return true; + case S_INT: + ch = *str++; + if (ch == '-') + ch = *str++; + if (!isdigit(ch)) + return false; + if (ch == '0' && *str != 0) + return false; + while ((ch = *str++)) { + if (!isdigit(ch)) + return false; + } + return true; + case S_HEX: + if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) + str += 2; + ch = *str++; + do { + if (!isxdigit(ch)) + return false; + } while ((ch = *str++)); + return true; + case S_BOOLEAN: + case S_TRISTATE: + switch (str[0]) { + case 'y': case 'Y': + case 'm': case 'M': + case 'n': case 'N': + return true; + } + return false; + default: + return false; + } +} + +bool sym_string_within_range(struct symbol *sym, const char *str) +{ + struct property *prop; + int val; + + switch (sym->type) { + case S_STRING: + return sym_string_valid(sym, str); + case S_INT: + if (!sym_string_valid(sym, str)) + return false; + prop = sym_get_range_prop(sym); + if (!prop) + return true; + val = strtol(str, NULL, 10); + return val >= sym_get_range_val(prop->expr->left.sym, 10) && + val <= sym_get_range_val(prop->expr->right.sym, 10); + case S_HEX: + if (!sym_string_valid(sym, str)) + return false; + prop = sym_get_range_prop(sym); + if (!prop) + return true; + val = strtol(str, NULL, 16); + return val >= sym_get_range_val(prop->expr->left.sym, 16) && + val <= sym_get_range_val(prop->expr->right.sym, 16); + case S_BOOLEAN: + case S_TRISTATE: + switch (str[0]) { + case 'y': case 'Y': + return sym_tristate_within_range(sym, yes); + case 'm': case 'M': + return sym_tristate_within_range(sym, mod); + case 'n': case 'N': + return sym_tristate_within_range(sym, no); + } + return false; + default: + return false; + } +} + +bool sym_set_string_value(struct symbol *sym, const char *newval) +{ + const char *oldval; + char *val; + int size; + + switch (sym->type) { + case S_BOOLEAN: + case S_TRISTATE: + switch (newval[0]) { + case 'y': case 'Y': + return sym_set_tristate_value(sym, yes); + case 'm': case 'M': + return sym_set_tristate_value(sym, mod); + case 'n': case 'N': + return sym_set_tristate_value(sym, no); + } + return false; + default: + ; + } + + if (!sym_string_within_range(sym, newval)) + return false; + + if (!(sym->flags & SYMBOL_DEF_USER)) { + sym->flags |= SYMBOL_DEF_USER; + sym_set_changed(sym); + } + + oldval = sym->def[S_DEF_USER].val; + size = strlen(newval) + 1; + if (sym->type == S_HEX && (newval[0] != '0' || (newval[1] != 'x' && newval[1] != 'X'))) { + size += 2; + sym->def[S_DEF_USER].val = val = malloc(size); + *val++ = '0'; + *val++ = 'x'; + } else if (!oldval || strcmp(oldval, newval)) + sym->def[S_DEF_USER].val = val = malloc(size); + else + return true; + + strcpy(val, newval); + free((void *)oldval); + sym_clear_all_valid(); + + return true; +} + +const char *sym_get_string_value(struct symbol *sym) +{ + tristate val; + + switch (sym->type) { + case S_BOOLEAN: + case S_TRISTATE: + val = sym_get_tristate_value(sym); + switch (val) { + case no: + return "n"; + case mod: + return "m"; + case yes: + return "y"; + } + break; + default: + ; + } + return (const char *)sym->curr.val; +} + +bool sym_is_changable(struct symbol *sym) +{ + return sym->visible > sym->rev_dep.tri; +} + +struct symbol *sym_lookup(const char *name, int flags) +{ + struct symbol *symbol; + const char *ptr; + char *new_name; + int hash = 0; + + if (name) { + if (name[0] && !name[1]) { + switch (name[0]) { + case 'y': return &symbol_yes; + case 'm': return &symbol_mod; + case 'n': return &symbol_no; + } + } + for (ptr = name; *ptr; ptr++) + hash += *ptr; + hash &= 0xff; + + for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) { + if (!strcmp(symbol->name, name) && + (flags ? symbol->flags & flags + : !(symbol->flags & (SYMBOL_CONST|SYMBOL_CHOICE)))) + return symbol; + } + new_name = strdup(name); + } else { + new_name = NULL; + hash = 256; + } + + symbol = malloc(sizeof(*symbol)); + memset(symbol, 0, sizeof(*symbol)); + symbol->name = new_name; + symbol->type = S_UNKNOWN; + symbol->flags |= flags; + + symbol->next = symbol_hash[hash]; + symbol_hash[hash] = symbol; + + return symbol; +} + +struct symbol *sym_find(const char *name) +{ + struct symbol *symbol = NULL; + const char *ptr; + int hash = 0; + + if (!name) + return NULL; + + if (name[0] && !name[1]) { + switch (name[0]) { + case 'y': return &symbol_yes; + case 'm': return &symbol_mod; + case 'n': return &symbol_no; + } + } + for (ptr = name; *ptr; ptr++) + hash += *ptr; + hash &= 0xff; + + for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) { + if (!strcmp(symbol->name, name) && + !(symbol->flags & SYMBOL_CONST)) + break; + } + + return symbol; +} + +struct symbol **sym_re_search(const char *pattern) +{ + struct symbol *sym, **sym_arr = NULL; + int i, cnt, size; + regex_t re; + + cnt = size = 0; + /* Skip if empty */ + if (strlen(pattern) == 0) + return NULL; + if (regcomp(&re, pattern, REG_EXTENDED|REG_NOSUB|REG_ICASE)) + return NULL; + + for_all_symbols(i, sym) { + if (sym->flags & SYMBOL_CONST || !sym->name) + continue; + if (regexec(&re, sym->name, 0, NULL, 0)) + continue; + if (cnt + 1 >= size) { + void *tmp = sym_arr; + size += 16; + sym_arr = realloc(sym_arr, size * sizeof(struct symbol *)); + if (!sym_arr) { + free(tmp); + return NULL; + } + } + sym_arr[cnt++] = sym; + } + if (sym_arr) + sym_arr[cnt] = NULL; + regfree(&re); + + return sym_arr; +} + + +static struct symbol *sym_check_expr_deps(struct expr *e) +{ + struct symbol *sym; + + if (!e) + return NULL; + switch (e->type) { + case E_OR: + case E_AND: + sym = sym_check_expr_deps(e->left.expr); + if (sym) + return sym; + return sym_check_expr_deps(e->right.expr); + case E_NOT: + return sym_check_expr_deps(e->left.expr); + case E_EQUAL: + case E_UNEQUAL: + sym = sym_check_deps(e->left.sym); + if (sym) + return sym; + return sym_check_deps(e->right.sym); + case E_SYMBOL: + return sym_check_deps(e->left.sym); + default: + break; + } + printf("Oops! How to check %d?\n", e->type); + return NULL; +} + +/* return NULL when dependencies are OK */ +static struct symbol *sym_check_sym_deps(struct symbol *sym) +{ + struct symbol *sym2; + struct property *prop; + + sym2 = sym_check_expr_deps(sym->rev_dep.expr); + if (sym2) + return sym2; + + for (prop = sym->prop; prop; prop = prop->next) { + if (prop->type == P_CHOICE || prop->type == P_SELECT) + continue; + sym2 = sym_check_expr_deps(prop->visible.expr); + if (sym2) + break; + if (prop->type != P_DEFAULT || sym_is_choice(sym)) + continue; + sym2 = sym_check_expr_deps(prop->expr); + if (sym2) + break; + } + + return sym2; +} + +static struct symbol *sym_check_choice_deps(struct symbol *choice) +{ + struct symbol *sym, *sym2; + struct property *prop; + struct expr *e; + + prop = sym_get_choice_prop(choice); + expr_list_for_each_sym(prop->expr, e, sym) + sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED); + + choice->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED); + sym2 = sym_check_sym_deps(choice); + choice->flags &= ~SYMBOL_CHECK; + if (sym2) + goto out; + + expr_list_for_each_sym(prop->expr, e, sym) { + sym2 = sym_check_sym_deps(sym); + if (sym2) { + fprintf(stderr, " -> %s", sym->name); + break; + } + } +out: + expr_list_for_each_sym(prop->expr, e, sym) + sym->flags &= ~SYMBOL_CHECK; + + if (sym2 && sym_is_choice_value(sym2) && + prop_get_symbol(sym_get_choice_prop(sym2)) == choice) + sym2 = choice; + + return sym2; +} + +struct symbol *sym_check_deps(struct symbol *sym) +{ + struct symbol *sym2; + struct property *prop; + + if (sym->flags & SYMBOL_CHECK) { + fprintf(stderr, "%s:%d:error: found recursive dependency: %s", + sym->prop->file->name, sym->prop->lineno, + sym->name ? sym->name : ""); + return sym; + } + if (sym->flags & SYMBOL_CHECKED) + return NULL; + + if (sym_is_choice_value(sym)) { + /* for choice groups start the check with main choice symbol */ + prop = sym_get_choice_prop(sym); + sym2 = sym_check_deps(prop_get_symbol(prop)); + } else if (sym_is_choice(sym)) { + sym2 = sym_check_choice_deps(sym); + } else { + sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED); + sym2 = sym_check_sym_deps(sym); + sym->flags &= ~SYMBOL_CHECK; + } + + if (sym2) { + fprintf(stderr, " -> %s", sym->name ? sym->name : ""); + if (sym2 == sym) { + fprintf(stderr, "\n"); + zconfnerrs++; + sym2 = NULL; + } + } + + return sym2; +} + +struct property *prop_alloc(enum prop_type type, struct symbol *sym) +{ + struct property *prop; + struct property **propp; + + prop = malloc(sizeof(*prop)); + memset(prop, 0, sizeof(*prop)); + prop->type = type; + prop->sym = sym; + prop->file = current_file; + prop->lineno = zconf_lineno(); + + /* append property to the prop list of symbol */ + if (sym) { + for (propp = &sym->prop; *propp; propp = &(*propp)->next) + ; + *propp = prop; + } + + return prop; +} + +struct symbol *prop_get_symbol(struct property *prop) +{ + if (prop->expr && (prop->expr->type == E_SYMBOL || + prop->expr->type == E_LIST)) + return prop->expr->left.sym; + return NULL; +} + +const char *prop_get_type_name(enum prop_type type) +{ + switch (type) { + case P_PROMPT: + return "prompt"; + case P_ENV: + return "env"; + case P_COMMENT: + return "comment"; + case P_MENU: + return "menu"; + case P_DEFAULT: + return "default"; + case P_CHOICE: + return "choice"; + case P_SELECT: + return "select"; + case P_RANGE: + return "range"; + case P_UNKNOWN: + break; + } + return "unknown"; +} + +void prop_add_env(const char *env) +{ + struct symbol *sym, *sym2; + struct property *prop; + char *p; + + sym = current_entry->sym; + sym->flags |= SYMBOL_AUTO; + for_all_properties(sym, prop, P_ENV) { + sym2 = prop_get_symbol(prop); + if (strcmp(sym2->name, env)) + menu_warn(current_entry, "redefining environment symbol from %s", + sym2->name); + return; + } + + prop = prop_alloc(P_ENV, sym); + prop->expr = expr_alloc_symbol(sym_lookup(env, SYMBOL_CONST)); + + sym_env_list = expr_alloc_one(E_LIST, sym_env_list); + sym_env_list->right.sym = sym; + + p = getenv(env); + if (p) + sym_add_default(sym, p); + else + menu_warn(current_entry, "environment variable %s undefined", env); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/util.c b/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/util.c new file mode 100644 index 00000000..3cc9f936 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/util.c @@ -0,0 +1,133 @@ +/* + * Copyright (C) 2002-2005 Roman Zippel + * Copyright (C) 2002-2005 Sam Ravnborg + * + * Released under the terms of the GNU GPL v2.0. + */ + +#include +#include "lkc.h" + +/* file already present in list? If not add it */ +struct file *file_lookup(const char *name) +{ + struct file *file; + + for (file = file_list; file; file = file->next) { + if (!strcmp(name, file->name)) + return file; + } + + file = malloc(sizeof(*file)); + memset(file, 0, sizeof(*file)); + file->name = strdup(name); + file->next = file_list; + file_list = file; + return file; +} + +/* write a dependency file as used by kbuild to track dependencies */ +int file_write_dep(const char *name) +{ + struct symbol *sym, *env_sym; + struct expr *e; + struct file *file; + FILE *out; + + if (!name) + name = ".kconfig.d"; + out = fopen("..config.tmp", "w"); + if (!out) + return 1; + fprintf(out, "deps_config := \\\n"); + for (file = file_list; file; file = file->next) { + if (file->next) + fprintf(out, "\t%s \\\n", file->name); + else + fprintf(out, "\t%s\n", file->name); + } + fprintf(out, "\ninclude/config/auto.conf: \\\n" + "\t$(deps_config)\n\n"); + + expr_list_for_each_sym(sym_env_list, e, sym) { + struct property *prop; + const char *value; + + prop = sym_get_env_prop(sym); + env_sym = prop_get_symbol(prop); + if (!env_sym) + continue; + value = getenv(env_sym->name); + if (!value) + value = ""; + fprintf(out, "ifneq \"$(%s)\" \"%s\"\n", env_sym->name, value); + fprintf(out, "include/config/auto.conf: FORCE\n"); + fprintf(out, "endif\n"); + } + + fprintf(out, "\n$(deps_config): ;\n"); + fclose(out); + rename("..config.tmp", name); + return 0; +} + + +/* Allocate initial growable sting */ +struct gstr str_new(void) +{ + struct gstr gs; + gs.s = malloc(sizeof(char) * 64); + gs.len = 64; + strcpy(gs.s, "\0"); + return gs; +} + +/* Allocate and assign growable string */ +struct gstr str_assign(const char *s) +{ + struct gstr gs; + gs.s = strdup(s); + gs.len = strlen(s) + 1; + return gs; +} + +/* Free storage for growable string */ +void str_free(struct gstr *gs) +{ + if (gs->s) + free(gs->s); + gs->s = NULL; + gs->len = 0; +} + +/* Append to growable string */ +void str_append(struct gstr *gs, const char *s) +{ + size_t l; + if (s) { + l = strlen(gs->s) + strlen(s) + 1; + if (l > gs->len) { + gs->s = realloc(gs->s, l); + gs->len = l; + } + strcat(gs->s, s); + } +} + +/* Append printf formatted string to growable string */ +void str_printf(struct gstr *gs, const char *fmt, ...) +{ + va_list ap; + char s[10000]; /* big enough... */ + va_start(ap, fmt); + vsnprintf(s, sizeof(s), fmt, ap); + str_append(gs, s); + va_end(ap); +} + +/* Retrieve value of growable string */ +const char *str_get(struct gstr *gs) +{ + return gs->s; +} + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/zconf.gperf b/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/zconf.gperf new file mode 100644 index 00000000..25ef5d01 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/zconf.gperf @@ -0,0 +1,44 @@ +%language=ANSI-C +%define hash-function-name kconf_id_hash +%define lookup-function-name kconf_id_lookup +%define string-pool-name kconf_id_strings +%compare-strncmp +%enum +%pic +%struct-type + +struct kconf_id; + +%% +mainmenu, T_MAINMENU, TF_COMMAND +menu, T_MENU, TF_COMMAND +endmenu, T_ENDMENU, TF_COMMAND +source, T_SOURCE, TF_COMMAND +choice, T_CHOICE, TF_COMMAND +endchoice, T_ENDCHOICE, TF_COMMAND +comment, T_COMMENT, TF_COMMAND +config, T_CONFIG, TF_COMMAND +menuconfig, T_MENUCONFIG, TF_COMMAND +help, T_HELP, TF_COMMAND +if, T_IF, TF_COMMAND|TF_PARAM +endif, T_ENDIF, TF_COMMAND +depends, T_DEPENDS, TF_COMMAND +optional, T_OPTIONAL, TF_COMMAND +default, T_DEFAULT, TF_COMMAND, S_UNKNOWN +prompt, T_PROMPT, TF_COMMAND +tristate, T_TYPE, TF_COMMAND, S_TRISTATE +def_tristate, T_DEFAULT, TF_COMMAND, S_TRISTATE +bool, T_TYPE, TF_COMMAND, S_BOOLEAN +boolean, T_TYPE, TF_COMMAND, S_BOOLEAN +def_bool, T_DEFAULT, TF_COMMAND, S_BOOLEAN +int, T_TYPE, TF_COMMAND, S_INT +hex, T_TYPE, TF_COMMAND, S_HEX +string, T_TYPE, TF_COMMAND, S_STRING +select, T_SELECT, TF_COMMAND +range, T_RANGE, TF_COMMAND +option, T_OPTION, TF_COMMAND +on, T_ON, TF_PARAM +modules, T_OPT_MODULES, TF_OPTION +defconfig_list, T_OPT_DEFCONFIG_LIST,TF_OPTION +env, T_OPT_ENV, TF_OPTION +%% diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/zconf.hash.c_shipped b/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/zconf.hash.c_shipped new file mode 100644 index 00000000..5c73d513 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/zconf.hash.c_shipped @@ -0,0 +1,237 @@ +/* ANSI-C code produced by gperf version 3.0.3 */ +/* Command-line: gperf */ +/* Computed positions: -k'1,3' */ + +#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \ + && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \ + && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \ + && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \ + && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \ + && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \ + && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \ + && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \ + && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \ + && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \ + && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \ + && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \ + && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \ + && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \ + && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \ + && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \ + && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \ + && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \ + && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \ + && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \ + && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \ + && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \ + && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126)) +/* The character set is not based on ISO-646. */ +#error "gperf generated tables don't work with this execution character set. Please report a bug to ." +#endif + +struct kconf_id; +/* maximum key range = 47, duplicates = 0 */ + +#ifdef __GNUC__ +__inline +#else +#ifdef __cplusplus +inline +#endif +#endif +static unsigned int +kconf_id_hash (register const char *str, register unsigned int len) +{ + static unsigned char asso_values[] = + { + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 11, 5, + 0, 0, 5, 49, 5, 20, 49, 49, 5, 20, + 5, 0, 30, 49, 0, 15, 0, 10, 0, 49, + 25, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, + 49, 49, 49, 49, 49, 49 + }; + register int hval = len; + + switch (hval) + { + default: + hval += asso_values[(unsigned char)str[2]]; + /*FALLTHROUGH*/ + case 2: + case 1: + hval += asso_values[(unsigned char)str[0]]; + break; + } + return hval; +} + +struct kconf_id_strings_t + { + char kconf_id_strings_str2[sizeof("on")]; + char kconf_id_strings_str3[sizeof("env")]; + char kconf_id_strings_str5[sizeof("endif")]; + char kconf_id_strings_str6[sizeof("option")]; + char kconf_id_strings_str7[sizeof("endmenu")]; + char kconf_id_strings_str8[sizeof("optional")]; + char kconf_id_strings_str9[sizeof("endchoice")]; + char kconf_id_strings_str10[sizeof("range")]; + char kconf_id_strings_str11[sizeof("choice")]; + char kconf_id_strings_str12[sizeof("default")]; + char kconf_id_strings_str13[sizeof("def_bool")]; + char kconf_id_strings_str14[sizeof("help")]; + char kconf_id_strings_str15[sizeof("bool")]; + char kconf_id_strings_str16[sizeof("config")]; + char kconf_id_strings_str17[sizeof("def_tristate")]; + char kconf_id_strings_str18[sizeof("boolean")]; + char kconf_id_strings_str19[sizeof("defconfig_list")]; + char kconf_id_strings_str21[sizeof("string")]; + char kconf_id_strings_str22[sizeof("if")]; + char kconf_id_strings_str23[sizeof("int")]; + char kconf_id_strings_str26[sizeof("select")]; + char kconf_id_strings_str27[sizeof("modules")]; + char kconf_id_strings_str28[sizeof("tristate")]; + char kconf_id_strings_str29[sizeof("menu")]; + char kconf_id_strings_str31[sizeof("source")]; + char kconf_id_strings_str32[sizeof("comment")]; + char kconf_id_strings_str33[sizeof("hex")]; + char kconf_id_strings_str35[sizeof("menuconfig")]; + char kconf_id_strings_str36[sizeof("prompt")]; + char kconf_id_strings_str37[sizeof("depends")]; + char kconf_id_strings_str48[sizeof("mainmenu")]; + }; +static struct kconf_id_strings_t kconf_id_strings_contents = + { + "on", + "env", + "endif", + "option", + "endmenu", + "optional", + "endchoice", + "range", + "choice", + "default", + "def_bool", + "help", + "bool", + "config", + "def_tristate", + "boolean", + "defconfig_list", + "string", + "if", + "int", + "select", + "modules", + "tristate", + "menu", + "source", + "comment", + "hex", + "menuconfig", + "prompt", + "depends", + "mainmenu" + }; +#define kconf_id_strings ((const char *) &kconf_id_strings_contents) +#ifdef __GNUC__ +__inline +#ifdef __GNUC_STDC_INLINE__ +__attribute__ ((__gnu_inline__)) +#endif +#endif +struct kconf_id * +kconf_id_lookup (register const char *str, register unsigned int len) +{ + enum + { + TOTAL_KEYWORDS = 31, + MIN_WORD_LENGTH = 2, + MAX_WORD_LENGTH = 14, + MIN_HASH_VALUE = 2, + MAX_HASH_VALUE = 48 + }; + + static struct kconf_id wordlist[] = + { + {-1}, {-1}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str2, T_ON, TF_PARAM}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str3, T_OPT_ENV, TF_OPTION}, + {-1}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str5, T_ENDIF, TF_COMMAND}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str6, T_OPTION, TF_COMMAND}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str7, T_ENDMENU, TF_COMMAND}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str8, T_OPTIONAL, TF_COMMAND}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str9, T_ENDCHOICE, TF_COMMAND}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str10, T_RANGE, TF_COMMAND}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str11, T_CHOICE, TF_COMMAND}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str12, T_DEFAULT, TF_COMMAND, S_UNKNOWN}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str13, T_DEFAULT, TF_COMMAND, S_BOOLEAN}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str14, T_HELP, TF_COMMAND}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str15, T_TYPE, TF_COMMAND, S_BOOLEAN}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str16, T_CONFIG, TF_COMMAND}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str17, T_DEFAULT, TF_COMMAND, S_TRISTATE}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str18, T_TYPE, TF_COMMAND, S_BOOLEAN}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str19, T_OPT_DEFCONFIG_LIST,TF_OPTION}, + {-1}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str21, T_TYPE, TF_COMMAND, S_STRING}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str22, T_IF, TF_COMMAND|TF_PARAM}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str23, T_TYPE, TF_COMMAND, S_INT}, + {-1}, {-1}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str26, T_SELECT, TF_COMMAND}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str27, T_OPT_MODULES, TF_OPTION}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str28, T_TYPE, TF_COMMAND, S_TRISTATE}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str29, T_MENU, TF_COMMAND}, + {-1}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str31, T_SOURCE, TF_COMMAND}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str32, T_COMMENT, TF_COMMAND}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str33, T_TYPE, TF_COMMAND, S_HEX}, + {-1}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str35, T_MENUCONFIG, TF_COMMAND}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str36, T_PROMPT, TF_COMMAND}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str37, T_DEPENDS, TF_COMMAND}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str48, T_MAINMENU, TF_COMMAND} + }; + + if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) + { + register int key = kconf_id_hash (str, len); + + if (key <= MAX_HASH_VALUE && key >= 0) + { + register int o = wordlist[key].name; + if (o >= 0) + { + register const char *s = o + kconf_id_strings; + + if (*str == *s && !strncmp (str + 1, s + 1, len - 1) && s[len] == '\0') + return &wordlist[key]; + } + } + } + return 0; +} + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/zconf.l b/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/zconf.l new file mode 100644 index 00000000..21ff69c9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/zconf.l @@ -0,0 +1,359 @@ +%option backup nostdinit noyywrap never-interactive full ecs +%option 8bit backup nodefault perf-report perf-report +%option noinput +%x COMMAND HELP STRING PARAM +%{ +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +#include +#include +#include +#include +#include + +#define LKC_DIRECT_LINK +#include "lkc.h" + +#define START_STRSIZE 16 + +static struct { + struct file *file; + int lineno; +} current_pos; + +static char *text; +static int text_size, text_asize; + +struct buffer { + struct buffer *parent; + YY_BUFFER_STATE state; +}; + +struct buffer *current_buf; + +static int last_ts, first_ts; + +static void zconf_endhelp(void); +static void zconf_endfile(void); + +void new_string(void) +{ + text = malloc(START_STRSIZE); + text_asize = START_STRSIZE; + text_size = 0; + *text = 0; +} + +void append_string(const char *str, int size) +{ + int new_size = text_size + size + 1; + if (new_size > text_asize) { + new_size += START_STRSIZE - 1; + new_size &= -START_STRSIZE; + text = realloc(text, new_size); + text_asize = new_size; + } + memcpy(text + text_size, str, size); + text_size += size; + text[text_size] = 0; +} + +void alloc_string(const char *str, int size) +{ + text = malloc(size + 1); + memcpy(text, str, size); + text[size] = 0; +} +%} + +ws [ \n\t] +n [A-Za-z0-9_] + +%% + int str = 0; + int ts, i; + +[ \t]*#.*\n | +[ \t]*\n { + current_file->lineno++; + return T_EOL; +} +[ \t]*#.* + + +[ \t]+ { + BEGIN(COMMAND); +} + +. { + unput(yytext[0]); + BEGIN(COMMAND); +} + + +{ + {n}+ { + struct kconf_id *id = kconf_id_lookup(yytext, yyleng); + BEGIN(PARAM); + current_pos.file = current_file; + current_pos.lineno = current_file->lineno; + if (id && id->flags & TF_COMMAND) { + zconflval.id = id; + return id->token; + } + alloc_string(yytext, yyleng); + zconflval.string = text; + return T_WORD; + } + . + \n { + BEGIN(INITIAL); + current_file->lineno++; + return T_EOL; + } +} + +{ + "&&" return T_AND; + "||" return T_OR; + "(" return T_OPEN_PAREN; + ")" return T_CLOSE_PAREN; + "!" return T_NOT; + "=" return T_EQUAL; + "!=" return T_UNEQUAL; + \"|\' { + str = yytext[0]; + new_string(); + BEGIN(STRING); + } + \n BEGIN(INITIAL); current_file->lineno++; return T_EOL; + --- /* ignore */ + ({n}|[-/.])+ { + struct kconf_id *id = kconf_id_lookup(yytext, yyleng); + if (id && id->flags & TF_PARAM) { + zconflval.id = id; + return id->token; + } + alloc_string(yytext, yyleng); + zconflval.string = text; + return T_WORD; + } + #.* /* comment */ + \\\n current_file->lineno++; + . + <> { + BEGIN(INITIAL); + } +} + +{ + [^'"\\\n]+/\n { + append_string(yytext, yyleng); + zconflval.string = text; + return T_WORD_QUOTE; + } + [^'"\\\n]+ { + append_string(yytext, yyleng); + } + \\.?/\n { + append_string(yytext + 1, yyleng - 1); + zconflval.string = text; + return T_WORD_QUOTE; + } + \\.? { + append_string(yytext + 1, yyleng - 1); + } + \'|\" { + if (str == yytext[0]) { + BEGIN(PARAM); + zconflval.string = text; + return T_WORD_QUOTE; + } else + append_string(yytext, 1); + } + \n { + printf("%s:%d:warning: multi-line strings not supported\n", zconf_curname(), zconf_lineno()); + current_file->lineno++; + BEGIN(INITIAL); + return T_EOL; + } + <> { + BEGIN(INITIAL); + } +} + +{ + [ \t]+ { + ts = 0; + for (i = 0; i < yyleng; i++) { + if (yytext[i] == '\t') + ts = (ts & ~7) + 8; + else + ts++; + } + last_ts = ts; + if (first_ts) { + if (ts < first_ts) { + zconf_endhelp(); + return T_HELPTEXT; + } + ts -= first_ts; + while (ts > 8) { + append_string(" ", 8); + ts -= 8; + } + append_string(" ", ts); + } + } + [ \t]*\n/[^ \t\n] { + current_file->lineno++; + zconf_endhelp(); + return T_HELPTEXT; + } + [ \t]*\n { + current_file->lineno++; + append_string("\n", 1); + } + [^ \t\n].* { + while (yyleng) { + if ((yytext[yyleng-1] != ' ') && (yytext[yyleng-1] != '\t')) + break; + yyleng--; + } + append_string(yytext, yyleng); + if (!first_ts) + first_ts = last_ts; + } + <> { + zconf_endhelp(); + return T_HELPTEXT; + } +} + +<> { + if (current_file) { + zconf_endfile(); + return T_EOL; + } + fclose(yyin); + yyterminate(); +} + +%% +void zconf_starthelp(void) +{ + new_string(); + last_ts = first_ts = 0; + BEGIN(HELP); +} + +static void zconf_endhelp(void) +{ + zconflval.string = text; + BEGIN(INITIAL); +} + + +/* + * Try to open specified file with following names: + * ./name + * $(srctree)/name + * The latter is used when srctree is separate from objtree + * when compiling the kernel. + * Return NULL if file is not found. + */ +FILE *zconf_fopen(const char *name) +{ + char *env, fullname[PATH_MAX+1]; + FILE *f; + + f = fopen(name, "r"); + if (!f && name != NULL && name[0] != '/') { + env = getenv(SRCTREE); + if (env) { + sprintf(fullname, "%s/%s", env, name); + f = fopen(fullname, "r"); + } + } + return f; +} + +void zconf_initscan(const char *name) +{ + yyin = zconf_fopen(name); + if (!yyin) { + printf("can't find file %s\n", name); + exit(1); + } + + current_buf = malloc(sizeof(*current_buf)); + memset(current_buf, 0, sizeof(*current_buf)); + + current_file = file_lookup(name); + current_file->lineno = 1; + current_file->flags = FILE_BUSY; +} + +void zconf_nextfile(const char *name) +{ + struct file *file = file_lookup(name); + struct buffer *buf = malloc(sizeof(*buf)); + memset(buf, 0, sizeof(*buf)); + + current_buf->state = YY_CURRENT_BUFFER; + yyin = zconf_fopen(name); + if (!yyin) { + printf("%s:%d: can't open file \"%s\"\n", zconf_curname(), zconf_lineno(), name); + exit(1); + } + yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE)); + buf->parent = current_buf; + current_buf = buf; + + if (file->flags & FILE_BUSY) { + printf("%s:%d: do not source '%s' from itself\n", + zconf_curname(), zconf_lineno(), name); + exit(1); + } + if (file->flags & FILE_SCANNED) { + printf("%s:%d: file '%s' is already sourced from '%s'\n", + zconf_curname(), zconf_lineno(), name, + file->parent->name); + exit(1); + } + file->flags |= FILE_BUSY; + file->lineno = 1; + file->parent = current_file; + current_file = file; +} + +static void zconf_endfile(void) +{ + struct buffer *parent; + + current_file->flags |= FILE_SCANNED; + current_file->flags &= ~FILE_BUSY; + current_file = current_file->parent; + + parent = current_buf->parent; + if (parent) { + fclose(yyin); + yy_delete_buffer(YY_CURRENT_BUFFER); + yy_switch_to_buffer(parent->state); + } + free(current_buf); + current_buf = parent; +} + +int zconf_lineno(void) +{ + return current_pos.lineno; +} + +char *zconf_curname(void) +{ + return current_pos.file ? current_pos.file->name : ""; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/zconf.tab.c_shipped b/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/zconf.tab.c_shipped new file mode 100644 index 00000000..aa9cc287 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/zconf.tab.c_shipped @@ -0,0 +1,2490 @@ +/* A Bison parser, made by GNU Bison 2.3. */ + +/* Skeleton implementation for Bison's Yacc-like parsers in C + + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 + Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. */ + +/* As a special exception, you may create a larger work that contains + part or all of the Bison parser skeleton and distribute that work + under terms of your choice, so long as that work isn't itself a + parser generator using the skeleton or a modified version thereof + as a parser skeleton. Alternatively, if you modify or redistribute + the parser skeleton itself, you may (at your option) remove this + special exception, which will cause the skeleton and the resulting + Bison output files to be licensed under the GNU General Public + License without this special exception. + + This special exception was added by the Free Software Foundation in + version 2.2 of Bison. */ + +/* C LALR(1) parser skeleton written by Richard Stallman, by + simplifying the original so-called "semantic" parser. */ + +/* All symbols defined below should begin with yy or YY, to avoid + infringing on user name space. This should be done even for local + variables, as they might otherwise be expanded by user macros. + There are some unavoidable exceptions within include files to + define necessary library symbols; they are noted "INFRINGES ON + USER NAME SPACE" below. */ + +/* Identify Bison output. */ +#define YYBISON 1 + +/* Bison version. */ +#define YYBISON_VERSION "2.3" + +/* Skeleton name. */ +#define YYSKELETON_NAME "yacc.c" + +/* Pure parsers. */ +#define YYPURE 0 + +/* Using locations. */ +#define YYLSP_NEEDED 0 + +/* Substitute the variable and function names. */ +#define yyparse zconfparse +#define yylex zconflex +#define yyerror zconferror +#define yylval zconflval +#define yychar zconfchar +#define yydebug zconfdebug +#define yynerrs zconfnerrs + + +/* Tokens. */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE + /* Put the tokens into the symbol table, so that GDB and other debuggers + know about them. */ + enum yytokentype { + T_MAINMENU = 258, + T_MENU = 259, + T_ENDMENU = 260, + T_SOURCE = 261, + T_CHOICE = 262, + T_ENDCHOICE = 263, + T_COMMENT = 264, + T_CONFIG = 265, + T_MENUCONFIG = 266, + T_HELP = 267, + T_HELPTEXT = 268, + T_IF = 269, + T_ENDIF = 270, + T_DEPENDS = 271, + T_OPTIONAL = 272, + T_PROMPT = 273, + T_TYPE = 274, + T_DEFAULT = 275, + T_SELECT = 276, + T_RANGE = 277, + T_OPTION = 278, + T_ON = 279, + T_WORD = 280, + T_WORD_QUOTE = 281, + T_UNEQUAL = 282, + T_CLOSE_PAREN = 283, + T_OPEN_PAREN = 284, + T_EOL = 285, + T_OR = 286, + T_AND = 287, + T_EQUAL = 288, + T_NOT = 289 + }; +#endif +/* Tokens. */ +#define T_MAINMENU 258 +#define T_MENU 259 +#define T_ENDMENU 260 +#define T_SOURCE 261 +#define T_CHOICE 262 +#define T_ENDCHOICE 263 +#define T_COMMENT 264 +#define T_CONFIG 265 +#define T_MENUCONFIG 266 +#define T_HELP 267 +#define T_HELPTEXT 268 +#define T_IF 269 +#define T_ENDIF 270 +#define T_DEPENDS 271 +#define T_OPTIONAL 272 +#define T_PROMPT 273 +#define T_TYPE 274 +#define T_DEFAULT 275 +#define T_SELECT 276 +#define T_RANGE 277 +#define T_OPTION 278 +#define T_ON 279 +#define T_WORD 280 +#define T_WORD_QUOTE 281 +#define T_UNEQUAL 282 +#define T_CLOSE_PAREN 283 +#define T_OPEN_PAREN 284 +#define T_EOL 285 +#define T_OR 286 +#define T_AND 287 +#define T_EQUAL 288 +#define T_NOT 289 + + + + +/* Copy the first part of user declarations. */ + + +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +#include +#include +#include +#include +#include +#include + +#define LKC_DIRECT_LINK +#include "lkc.h" + +#include "zconf.hash.c" + +#define printd(mask, fmt...) if (cdebug & (mask)) printf(fmt) + +#define PRINTD 0x0001 +#define DEBUG_PARSE 0x0002 + +int cdebug = PRINTD; + +extern int zconflex(void); +static void zconfprint(const char *err, ...); +static void zconf_error(const char *err, ...); +static void zconferror(const char *err); +static bool zconf_endtoken(struct kconf_id *id, int starttoken, int endtoken); + +struct symbol *symbol_hash[257]; + +static struct menu *current_menu, *current_entry; + +#define YYDEBUG 0 +#if YYDEBUG +#define YYERROR_VERBOSE +#endif + + +/* Enabling traces. */ +#ifndef YYDEBUG +# define YYDEBUG 0 +#endif + +/* Enabling verbose error messages. */ +#ifdef YYERROR_VERBOSE +# undef YYERROR_VERBOSE +# define YYERROR_VERBOSE 1 +#else +# define YYERROR_VERBOSE 0 +#endif + +/* Enabling the token table. */ +#ifndef YYTOKEN_TABLE +# define YYTOKEN_TABLE 0 +#endif + +#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED +typedef union YYSTYPE + +{ + char *string; + struct file *file; + struct symbol *symbol; + struct expr *expr; + struct menu *menu; + struct kconf_id *id; +} +/* Line 187 of yacc.c. */ + + YYSTYPE; +# define yystype YYSTYPE /* obsolescent; will be withdrawn */ +# define YYSTYPE_IS_DECLARED 1 +# define YYSTYPE_IS_TRIVIAL 1 +#endif + + + +/* Copy the second part of user declarations. */ + + +/* Line 216 of yacc.c. */ + + +#ifdef short +# undef short +#endif + +#ifdef YYTYPE_UINT8 +typedef YYTYPE_UINT8 yytype_uint8; +#else +typedef unsigned char yytype_uint8; +#endif + +#ifdef YYTYPE_INT8 +typedef YYTYPE_INT8 yytype_int8; +#elif (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +typedef signed char yytype_int8; +#else +typedef short int yytype_int8; +#endif + +#ifdef YYTYPE_UINT16 +typedef YYTYPE_UINT16 yytype_uint16; +#else +typedef unsigned short int yytype_uint16; +#endif + +#ifdef YYTYPE_INT16 +typedef YYTYPE_INT16 yytype_int16; +#else +typedef short int yytype_int16; +#endif + +#ifndef YYSIZE_T +# ifdef __SIZE_TYPE__ +# define YYSIZE_T __SIZE_TYPE__ +# elif defined size_t +# define YYSIZE_T size_t +# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +# include /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +# else +# define YYSIZE_T unsigned int +# endif +#endif + +#define YYSIZE_MAXIMUM ((YYSIZE_T) -1) + +#ifndef YY_ +# if YYENABLE_NLS +# if ENABLE_NLS +# include /* INFRINGES ON USER NAME SPACE */ +# define YY_(msgid) dgettext ("bison-runtime", msgid) +# endif +# endif +# ifndef YY_ +# define YY_(msgid) msgid +# endif +#endif + +/* Suppress unused-variable warnings by "using" E. */ +#if ! defined lint || defined __GNUC__ +# define YYUSE(e) ((void) (e)) +#else +# define YYUSE(e) /* empty */ +#endif + +/* Identity function, used to suppress warnings about constant conditions. */ +#ifndef lint +# define YYID(n) (n) +#else +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static int +YYID (int i) +#else +static int +YYID (i) + int i; +#endif +{ + return i; +} +#endif + +#if ! defined yyoverflow || YYERROR_VERBOSE + +/* The parser invokes alloca or malloc; define the necessary symbols. */ + +# ifdef YYSTACK_USE_ALLOCA +# if YYSTACK_USE_ALLOCA +# ifdef __GNUC__ +# define YYSTACK_ALLOC __builtin_alloca +# elif defined __BUILTIN_VA_ARG_INCR +# include /* INFRINGES ON USER NAME SPACE */ +# elif defined _AIX +# define YYSTACK_ALLOC __alloca +# elif defined _MSC_VER +# include /* INFRINGES ON USER NAME SPACE */ +# define alloca _alloca +# else +# define YYSTACK_ALLOC alloca +# if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +# include /* INFRINGES ON USER NAME SPACE */ +# ifndef _STDLIB_H +# define _STDLIB_H 1 +# endif +# endif +# endif +# endif +# endif + +# ifdef YYSTACK_ALLOC + /* Pacify GCC's `empty if-body' warning. */ +# define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0)) +# ifndef YYSTACK_ALLOC_MAXIMUM + /* The OS might guarantee only one guard page at the bottom of the stack, + and a page size can be as small as 4096 bytes. So we cannot safely + invoke alloca (N) if N exceeds 4096. Use a slightly smaller number + to allow for a few compiler-allocated temporary stack slots. */ +# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */ +# endif +# else +# define YYSTACK_ALLOC YYMALLOC +# define YYSTACK_FREE YYFREE +# ifndef YYSTACK_ALLOC_MAXIMUM +# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM +# endif +# if (defined __cplusplus && ! defined _STDLIB_H \ + && ! ((defined YYMALLOC || defined malloc) \ + && (defined YYFREE || defined free))) +# include /* INFRINGES ON USER NAME SPACE */ +# ifndef _STDLIB_H +# define _STDLIB_H 1 +# endif +# endif +# ifndef YYMALLOC +# define YYMALLOC malloc +# if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# ifndef YYFREE +# define YYFREE free +# if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +void free (void *); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# endif +#endif /* ! defined yyoverflow || YYERROR_VERBOSE */ + + +#if (! defined yyoverflow \ + && (! defined __cplusplus \ + || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) + +/* A type that is properly aligned for any stack member. */ +union yyalloc +{ + yytype_int16 yyss; + YYSTYPE yyvs; + }; + +/* The size of the maximum gap between one aligned stack and the next. */ +# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) + +/* The size of an array large to enough to hold all stacks, each with + N elements. */ +# define YYSTACK_BYTES(N) \ + ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \ + + YYSTACK_GAP_MAXIMUM) + +/* Copy COUNT objects from FROM to TO. The source and destination do + not overlap. */ +# ifndef YYCOPY +# if defined __GNUC__ && 1 < __GNUC__ +# define YYCOPY(To, From, Count) \ + __builtin_memcpy (To, From, (Count) * sizeof (*(From))) +# else +# define YYCOPY(To, From, Count) \ + do \ + { \ + YYSIZE_T yyi; \ + for (yyi = 0; yyi < (Count); yyi++) \ + (To)[yyi] = (From)[yyi]; \ + } \ + while (YYID (0)) +# endif +# endif + +/* Relocate STACK from its old location to the new one. The + local variables YYSIZE and YYSTACKSIZE give the old and new number of + elements in the stack, and YYPTR gives the new location of the + stack. Advance YYPTR to a properly aligned location for the next + stack. */ +# define YYSTACK_RELOCATE(Stack) \ + do \ + { \ + YYSIZE_T yynewbytes; \ + YYCOPY (&yyptr->Stack, Stack, yysize); \ + Stack = &yyptr->Stack; \ + yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ + yyptr += yynewbytes / sizeof (*yyptr); \ + } \ + while (YYID (0)) + +#endif + +/* YYFINAL -- State number of the termination state. */ +#define YYFINAL 3 +/* YYLAST -- Last index in YYTABLE. */ +#define YYLAST 259 + +/* YYNTOKENS -- Number of terminals. */ +#define YYNTOKENS 35 +/* YYNNTS -- Number of nonterminals. */ +#define YYNNTS 46 +/* YYNRULES -- Number of rules. */ +#define YYNRULES 110 +/* YYNRULES -- Number of states. */ +#define YYNSTATES 180 + +/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ +#define YYUNDEFTOK 2 +#define YYMAXUTOK 289 + +#define YYTRANSLATE(YYX) \ + ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) + +/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */ +static const yytype_uint8 yytranslate[] = +{ + 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, 32, 33, 34 +}; + +#if YYDEBUG +/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in + YYRHS. */ +static const yytype_uint16 yyprhs[] = +{ + 0, 0, 3, 5, 6, 9, 12, 15, 20, 23, + 28, 33, 37, 39, 41, 43, 45, 47, 49, 51, + 53, 55, 57, 59, 61, 63, 67, 70, 74, 77, + 81, 84, 85, 88, 91, 94, 97, 100, 103, 107, + 112, 117, 122, 128, 132, 133, 137, 138, 141, 145, + 148, 150, 154, 155, 158, 161, 164, 167, 170, 175, + 179, 182, 187, 188, 191, 195, 197, 201, 202, 205, + 208, 211, 215, 218, 220, 224, 225, 228, 231, 234, + 238, 242, 245, 248, 251, 252, 255, 258, 261, 266, + 267, 270, 272, 274, 277, 280, 283, 285, 288, 289, + 292, 294, 298, 302, 306, 309, 313, 317, 319, 321, + 322 +}; + +/* YYRHS -- A `-1'-separated list of the rules' RHS. */ +static const yytype_int8 yyrhs[] = +{ + 36, 0, -1, 37, -1, -1, 37, 39, -1, 37, + 53, -1, 37, 64, -1, 37, 3, 74, 76, -1, + 37, 75, -1, 37, 25, 1, 30, -1, 37, 38, + 1, 30, -1, 37, 1, 30, -1, 16, -1, 18, + -1, 19, -1, 21, -1, 17, -1, 22, -1, 20, + -1, 30, -1, 59, -1, 68, -1, 42, -1, 44, + -1, 66, -1, 25, 1, 30, -1, 1, 30, -1, + 10, 25, 30, -1, 41, 45, -1, 11, 25, 30, + -1, 43, 45, -1, -1, 45, 46, -1, 45, 47, + -1, 45, 72, -1, 45, 70, -1, 45, 40, -1, + 45, 30, -1, 19, 73, 30, -1, 18, 74, 77, + 30, -1, 20, 78, 77, 30, -1, 21, 25, 77, + 30, -1, 22, 79, 79, 77, 30, -1, 23, 48, + 30, -1, -1, 48, 25, 49, -1, -1, 33, 74, + -1, 7, 80, 30, -1, 50, 54, -1, 75, -1, + 51, 56, 52, -1, -1, 54, 55, -1, 54, 72, + -1, 54, 70, -1, 54, 30, -1, 54, 40, -1, + 18, 74, 77, 30, -1, 19, 73, 30, -1, 17, + 30, -1, 20, 25, 77, 30, -1, -1, 56, 39, + -1, 14, 78, 76, -1, 75, -1, 57, 60, 58, + -1, -1, 60, 39, -1, 60, 64, -1, 60, 53, + -1, 4, 74, 30, -1, 61, 71, -1, 75, -1, + 62, 65, 63, -1, -1, 65, 39, -1, 65, 64, + -1, 65, 53, -1, 6, 74, 30, -1, 9, 74, + 30, -1, 67, 71, -1, 12, 30, -1, 69, 13, + -1, -1, 71, 72, -1, 71, 30, -1, 71, 40, + -1, 16, 24, 78, 30, -1, -1, 74, 77, -1, + 25, -1, 26, -1, 5, 30, -1, 8, 30, -1, + 15, 30, -1, 30, -1, 76, 30, -1, -1, 14, + 78, -1, 79, -1, 79, 33, 79, -1, 79, 27, + 79, -1, 29, 78, 28, -1, 34, 78, -1, 78, + 31, 78, -1, 78, 32, 78, -1, 25, -1, 26, + -1, -1, 25, -1 +}; + +/* YYRLINE[YYN] -- source line where rule number YYN was defined. */ +static const yytype_uint16 yyrline[] = +{ + 0, 104, 104, 106, 108, 109, 110, 111, 112, 113, + 114, 118, 122, 122, 122, 122, 122, 122, 122, 126, + 127, 128, 129, 130, 131, 135, 136, 142, 150, 156, + 164, 174, 176, 177, 178, 179, 180, 181, 184, 192, + 198, 208, 214, 220, 223, 225, 236, 237, 242, 251, + 256, 264, 267, 269, 270, 271, 272, 273, 276, 282, + 293, 299, 309, 311, 316, 324, 332, 335, 337, 338, + 339, 344, 351, 356, 364, 367, 369, 370, 371, 374, + 382, 389, 396, 402, 409, 411, 412, 413, 416, 424, + 426, 431, 432, 435, 436, 437, 441, 442, 445, 446, + 449, 450, 451, 452, 453, 454, 455, 458, 459, 462, + 463 +}; +#endif + +#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE +/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. + First, the terminals, then, starting at YYNTOKENS, nonterminals. */ +static const char *const yytname[] = +{ + "$end", "error", "$undefined", "T_MAINMENU", "T_MENU", "T_ENDMENU", + "T_SOURCE", "T_CHOICE", "T_ENDCHOICE", "T_COMMENT", "T_CONFIG", + "T_MENUCONFIG", "T_HELP", "T_HELPTEXT", "T_IF", "T_ENDIF", "T_DEPENDS", + "T_OPTIONAL", "T_PROMPT", "T_TYPE", "T_DEFAULT", "T_SELECT", "T_RANGE", + "T_OPTION", "T_ON", "T_WORD", "T_WORD_QUOTE", "T_UNEQUAL", + "T_CLOSE_PAREN", "T_OPEN_PAREN", "T_EOL", "T_OR", "T_AND", "T_EQUAL", + "T_NOT", "$accept", "input", "stmt_list", "option_name", "common_stmt", + "option_error", "config_entry_start", "config_stmt", + "menuconfig_entry_start", "menuconfig_stmt", "config_option_list", + "config_option", "symbol_option", "symbol_option_list", + "symbol_option_arg", "choice", "choice_entry", "choice_end", + "choice_stmt", "choice_option_list", "choice_option", "choice_block", + "if_entry", "if_end", "if_stmt", "if_block", "menu", "menu_entry", + "menu_end", "menu_stmt", "menu_block", "source_stmt", "comment", + "comment_stmt", "help_start", "help", "depends_list", "depends", + "prompt_stmt_opt", "prompt", "end", "nl", "if_expr", "expr", "symbol", + "word_opt", 0 +}; +#endif + +# ifdef YYPRINT +/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to + token YYLEX-NUM. */ +static const yytype_uint16 yytoknum[] = +{ + 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, + 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, + 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, + 285, 286, 287, 288, 289 +}; +# endif + +/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ +static const yytype_uint8 yyr1[] = +{ + 0, 35, 36, 37, 37, 37, 37, 37, 37, 37, + 37, 37, 38, 38, 38, 38, 38, 38, 38, 39, + 39, 39, 39, 39, 39, 40, 40, 41, 42, 43, + 44, 45, 45, 45, 45, 45, 45, 45, 46, 46, + 46, 46, 46, 47, 48, 48, 49, 49, 50, 51, + 52, 53, 54, 54, 54, 54, 54, 54, 55, 55, + 55, 55, 56, 56, 57, 58, 59, 60, 60, 60, + 60, 61, 62, 63, 64, 65, 65, 65, 65, 66, + 67, 68, 69, 70, 71, 71, 71, 71, 72, 73, + 73, 74, 74, 75, 75, 75, 76, 76, 77, 77, + 78, 78, 78, 78, 78, 78, 78, 79, 79, 80, + 80 +}; + +/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ +static const yytype_uint8 yyr2[] = +{ + 0, 2, 1, 0, 2, 2, 2, 4, 2, 4, + 4, 3, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 3, 2, 3, 2, 3, + 2, 0, 2, 2, 2, 2, 2, 2, 3, 4, + 4, 4, 5, 3, 0, 3, 0, 2, 3, 2, + 1, 3, 0, 2, 2, 2, 2, 2, 4, 3, + 2, 4, 0, 2, 3, 1, 3, 0, 2, 2, + 2, 3, 2, 1, 3, 0, 2, 2, 2, 3, + 3, 2, 2, 2, 0, 2, 2, 2, 4, 0, + 2, 1, 1, 2, 2, 2, 1, 2, 0, 2, + 1, 3, 3, 3, 2, 3, 3, 1, 1, 0, + 1 +}; + +/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state + STATE-NUM when YYTABLE doesn't specify something else to do. Zero + means the default is an error. */ +static const yytype_uint8 yydefact[] = +{ + 3, 0, 0, 1, 0, 0, 0, 0, 0, 109, + 0, 0, 0, 0, 0, 0, 12, 16, 13, 14, + 18, 15, 17, 0, 19, 0, 4, 31, 22, 31, + 23, 52, 62, 5, 67, 20, 84, 75, 6, 24, + 84, 21, 8, 11, 91, 92, 0, 0, 93, 0, + 110, 0, 94, 0, 0, 0, 107, 108, 0, 0, + 0, 100, 95, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 96, 7, 71, 79, 48, 80, 27, + 29, 0, 104, 0, 0, 64, 0, 0, 9, 10, + 0, 0, 0, 0, 89, 0, 0, 0, 44, 0, + 37, 36, 32, 33, 0, 35, 34, 0, 0, 89, + 0, 56, 57, 53, 55, 54, 63, 51, 50, 68, + 70, 66, 69, 65, 86, 87, 85, 76, 78, 74, + 77, 73, 97, 103, 105, 106, 102, 101, 26, 82, + 0, 98, 0, 98, 98, 98, 0, 0, 0, 83, + 60, 98, 0, 98, 0, 0, 0, 38, 90, 0, + 0, 98, 46, 43, 25, 0, 59, 0, 88, 99, + 39, 40, 41, 0, 0, 45, 58, 61, 42, 47 +}; + +/* YYDEFGOTO[NTERM-NUM]. */ +static const yytype_int16 yydefgoto[] = +{ + -1, 1, 2, 25, 26, 101, 27, 28, 29, 30, + 65, 102, 103, 147, 175, 31, 32, 117, 33, 67, + 113, 68, 34, 121, 35, 69, 36, 37, 129, 38, + 71, 39, 40, 41, 104, 105, 70, 106, 142, 143, + 42, 74, 156, 60, 61, 51 +}; + +/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing + STATE-NUM. */ +#define YYPACT_NINF -80 +static const yytype_int16 yypact[] = +{ + -80, 2, 132, -80, -13, -1, -1, -2, -1, 9, + 33, -1, 27, 40, -3, 38, -80, -80, -80, -80, + -80, -80, -80, 71, -80, 77, -80, -80, -80, -80, + -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, + -80, -80, -80, -80, -80, -80, 57, 61, -80, 63, + -80, 76, -80, 87, 101, 133, -80, -80, -3, -3, + 195, -6, -80, 136, 149, 39, 104, 65, 150, 5, + 194, 5, 167, -80, 176, -80, -80, -80, -80, -80, + -80, 68, -80, -3, -3, 176, 72, 72, -80, -80, + 177, 187, 78, -1, -1, -3, 196, 72, -80, 222, + -80, -80, -80, -80, 221, -80, -80, 205, -1, -1, + 211, -80, -80, -80, -80, -80, -80, -80, -80, -80, + -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, + -80, -80, -80, -80, 206, -80, -80, -80, -80, -80, + -3, 223, 209, 223, 197, 223, 72, 7, 210, -80, + -80, 223, 212, 223, 201, -3, 213, -80, -80, 214, + 215, 223, 208, -80, -80, 216, -80, 217, -80, 113, + -80, -80, -80, 218, -1, -80, -80, -80, -80, -80 +}; + +/* YYPGOTO[NTERM-NUM]. */ +static const yytype_int16 yypgoto[] = +{ + -80, -80, -80, -80, 122, -34, -80, -80, -80, -80, + 220, -80, -80, -80, -80, -80, -80, -80, 59, -80, + -80, -80, -80, -80, -80, -80, -80, -80, -80, 125, + -80, -80, -80, -80, -80, 183, 219, 22, 142, -5, + 147, 192, 69, -54, -79, -80 +}; + +/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If + positive, shift that token. If negative, reduce the rule which + number is the opposite. If zero, do what YYDEFACT says. + If YYTABLE_NINF, syntax error. */ +#define YYTABLE_NINF -82 +static const yytype_int16 yytable[] = +{ + 46, 47, 3, 49, 81, 82, 53, 136, 137, 6, + 7, 8, 9, 10, 11, 12, 13, 43, 146, 14, + 15, 86, 56, 57, 44, 45, 58, 87, 48, 134, + 135, 59, 162, 112, 50, 24, 125, 163, 125, -28, + 90, 144, -28, -28, -28, -28, -28, -28, -28, -28, + -28, 91, 54, -28, -28, 92, -28, 93, 94, 95, + 96, 97, 98, 52, 99, 55, 90, 161, 62, 100, + -49, -49, 63, -49, -49, -49, -49, 91, 64, -49, + -49, 92, 107, 108, 109, 110, 154, 73, 141, 115, + 99, 75, 126, 76, 126, 111, 133, 56, 57, 83, + 84, 169, 140, 151, -30, 90, 77, -30, -30, -30, + -30, -30, -30, -30, -30, -30, 91, 78, -30, -30, + 92, -30, 93, 94, 95, 96, 97, 98, 120, 99, + 128, 79, -2, 4, 100, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 83, 84, 14, 15, 16, 17, + 18, 19, 20, 21, 22, 7, 8, 23, 10, 11, + 12, 13, 24, 80, 14, 15, 88, -81, 90, 179, + -81, -81, -81, -81, -81, -81, -81, -81, -81, 89, + 24, -81, -81, 92, -81, -81, -81, -81, -81, -81, + 116, 119, 99, 127, 122, 90, 130, 124, -72, -72, + -72, -72, -72, -72, -72, -72, 132, 138, -72, -72, + 92, 155, 158, 159, 160, 118, 123, 139, 131, 99, + 165, 145, 167, 148, 124, 73, 83, 84, 83, 84, + 173, 168, 83, 84, 149, 150, 153, 155, 84, 157, + 164, 174, 166, 170, 171, 172, 176, 177, 178, 66, + 114, 152, 85, 0, 0, 0, 0, 0, 0, 72 +}; + +static const yytype_int16 yycheck[] = +{ + 5, 6, 0, 8, 58, 59, 11, 86, 87, 4, + 5, 6, 7, 8, 9, 10, 11, 30, 97, 14, + 15, 27, 25, 26, 25, 26, 29, 33, 30, 83, + 84, 34, 25, 67, 25, 30, 70, 30, 72, 0, + 1, 95, 3, 4, 5, 6, 7, 8, 9, 10, + 11, 12, 25, 14, 15, 16, 17, 18, 19, 20, + 21, 22, 23, 30, 25, 25, 1, 146, 30, 30, + 5, 6, 1, 8, 9, 10, 11, 12, 1, 14, + 15, 16, 17, 18, 19, 20, 140, 30, 93, 67, + 25, 30, 70, 30, 72, 30, 28, 25, 26, 31, + 32, 155, 24, 108, 0, 1, 30, 3, 4, 5, + 6, 7, 8, 9, 10, 11, 12, 30, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 69, 25, + 71, 30, 0, 1, 30, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 31, 32, 14, 15, 16, 17, + 18, 19, 20, 21, 22, 5, 6, 25, 8, 9, + 10, 11, 30, 30, 14, 15, 30, 0, 1, 174, + 3, 4, 5, 6, 7, 8, 9, 10, 11, 30, + 30, 14, 15, 16, 17, 18, 19, 20, 21, 22, + 68, 69, 25, 71, 69, 1, 71, 30, 4, 5, + 6, 7, 8, 9, 10, 11, 30, 30, 14, 15, + 16, 14, 143, 144, 145, 68, 69, 30, 71, 25, + 151, 25, 153, 1, 30, 30, 31, 32, 31, 32, + 161, 30, 31, 32, 13, 30, 25, 14, 32, 30, + 30, 33, 30, 30, 30, 30, 30, 30, 30, 29, + 67, 109, 60, -1, -1, -1, -1, -1, -1, 40 +}; + +/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing + symbol of state STATE-NUM. */ +static const yytype_uint8 yystos[] = +{ + 0, 36, 37, 0, 1, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 25, 30, 38, 39, 41, 42, 43, + 44, 50, 51, 53, 57, 59, 61, 62, 64, 66, + 67, 68, 75, 30, 25, 26, 74, 74, 30, 74, + 25, 80, 30, 74, 25, 25, 25, 26, 29, 34, + 78, 79, 30, 1, 1, 45, 45, 54, 56, 60, + 71, 65, 71, 30, 76, 30, 30, 30, 30, 30, + 30, 78, 78, 31, 32, 76, 27, 33, 30, 30, + 1, 12, 16, 18, 19, 20, 21, 22, 23, 25, + 30, 40, 46, 47, 69, 70, 72, 17, 18, 19, + 20, 30, 40, 55, 70, 72, 39, 52, 75, 39, + 53, 58, 64, 75, 30, 40, 72, 39, 53, 63, + 64, 75, 30, 28, 78, 78, 79, 79, 30, 30, + 24, 74, 73, 74, 78, 25, 79, 48, 1, 13, + 30, 74, 73, 25, 78, 14, 77, 30, 77, 77, + 77, 79, 25, 30, 30, 77, 30, 77, 30, 78, + 30, 30, 30, 77, 33, 49, 30, 30, 30, 74 +}; + +#define yyerrok (yyerrstatus = 0) +#define yyclearin (yychar = YYEMPTY) +#define YYEMPTY (-2) +#define YYEOF 0 + +#define YYACCEPT goto yyacceptlab +#define YYABORT goto yyabortlab +#define YYERROR goto yyerrorlab + + +/* Like YYERROR except do call yyerror. This remains here temporarily + to ease the transition to the new meaning of YYERROR, for GCC. + Once GCC version 2 has supplanted version 1, this can go. */ + +#define YYFAIL goto yyerrlab + +#define YYRECOVERING() (!!yyerrstatus) + +#define YYBACKUP(Token, Value) \ +do \ + if (yychar == YYEMPTY && yylen == 1) \ + { \ + yychar = (Token); \ + yylval = (Value); \ + yytoken = YYTRANSLATE (yychar); \ + YYPOPSTACK (1); \ + goto yybackup; \ + } \ + else \ + { \ + yyerror (YY_("syntax error: cannot back up")); \ + YYERROR; \ + } \ +while (YYID (0)) + + +#define YYTERROR 1 +#define YYERRCODE 256 + + +/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. + If N is 0, then set CURRENT to the empty location which ends + the previous symbol: RHS[0] (always defined). */ + +#define YYRHSLOC(Rhs, K) ((Rhs)[K]) +#ifndef YYLLOC_DEFAULT +# define YYLLOC_DEFAULT(Current, Rhs, N) \ + do \ + if (YYID (N)) \ + { \ + (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ + (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ + (Current).last_line = YYRHSLOC (Rhs, N).last_line; \ + (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ + } \ + else \ + { \ + (Current).first_line = (Current).last_line = \ + YYRHSLOC (Rhs, 0).last_line; \ + (Current).first_column = (Current).last_column = \ + YYRHSLOC (Rhs, 0).last_column; \ + } \ + while (YYID (0)) +#endif + + +/* YY_LOCATION_PRINT -- Print the location on the stream. + This macro was not mandated originally: define only if we know + we won't break user code: when these are the locations we know. */ + +#ifndef YY_LOCATION_PRINT +# if YYLTYPE_IS_TRIVIAL +# define YY_LOCATION_PRINT(File, Loc) \ + fprintf (File, "%d.%d-%d.%d", \ + (Loc).first_line, (Loc).first_column, \ + (Loc).last_line, (Loc).last_column) +# else +# define YY_LOCATION_PRINT(File, Loc) ((void) 0) +# endif +#endif + + +/* YYLEX -- calling `yylex' with the right arguments. */ + +#ifdef YYLEX_PARAM +# define YYLEX yylex (YYLEX_PARAM) +#else +# define YYLEX yylex () +#endif + +/* Enable debugging if requested. */ +#if YYDEBUG + +# ifndef YYFPRINTF +# include /* INFRINGES ON USER NAME SPACE */ +# define YYFPRINTF fprintf +# endif + +# define YYDPRINTF(Args) \ +do { \ + if (yydebug) \ + YYFPRINTF Args; \ +} while (YYID (0)) + +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ +do { \ + if (yydebug) \ + { \ + YYFPRINTF (stderr, "%s ", Title); \ + yy_symbol_print (stderr, \ + Type, Value); \ + YYFPRINTF (stderr, "\n"); \ + } \ +} while (YYID (0)) + + +/*--------------------------------. +| Print this symbol on YYOUTPUT. | +`--------------------------------*/ + +/*ARGSUSED*/ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) +#else +static void +yy_symbol_value_print (yyoutput, yytype, yyvaluep) + FILE *yyoutput; + int yytype; + YYSTYPE const * const yyvaluep; +#endif +{ + if (!yyvaluep) + return; +# ifdef YYPRINT + if (yytype < YYNTOKENS) + YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); +# else + YYUSE (yyoutput); +# endif + switch (yytype) + { + default: + break; + } +} + + +/*--------------------------------. +| Print this symbol on YYOUTPUT. | +`--------------------------------*/ + +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) +#else +static void +yy_symbol_print (yyoutput, yytype, yyvaluep) + FILE *yyoutput; + int yytype; + YYSTYPE const * const yyvaluep; +#endif +{ + if (yytype < YYNTOKENS) + YYFPRINTF (yyoutput, "token %s (", yytname[yytype]); + else + YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); + + yy_symbol_value_print (yyoutput, yytype, yyvaluep); + YYFPRINTF (yyoutput, ")"); +} + +/*------------------------------------------------------------------. +| yy_stack_print -- Print the state stack from its BOTTOM up to its | +| TOP (included). | +`------------------------------------------------------------------*/ + +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_stack_print (yytype_int16 *bottom, yytype_int16 *top) +#else +static void +yy_stack_print (bottom, top) + yytype_int16 *bottom; + yytype_int16 *top; +#endif +{ + YYFPRINTF (stderr, "Stack now"); + for (; bottom <= top; ++bottom) + YYFPRINTF (stderr, " %d", *bottom); + YYFPRINTF (stderr, "\n"); +} + +# define YY_STACK_PRINT(Bottom, Top) \ +do { \ + if (yydebug) \ + yy_stack_print ((Bottom), (Top)); \ +} while (YYID (0)) + + +/*------------------------------------------------. +| Report that the YYRULE is going to be reduced. | +`------------------------------------------------*/ + +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_reduce_print (YYSTYPE *yyvsp, int yyrule) +#else +static void +yy_reduce_print (yyvsp, yyrule) + YYSTYPE *yyvsp; + int yyrule; +#endif +{ + int yynrhs = yyr2[yyrule]; + int yyi; + unsigned long int yylno = yyrline[yyrule]; + YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n", + yyrule - 1, yylno); + /* The symbols being reduced. */ + for (yyi = 0; yyi < yynrhs; yyi++) + { + fprintf (stderr, " $%d = ", yyi + 1); + yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi], + &(yyvsp[(yyi + 1) - (yynrhs)]) + ); + fprintf (stderr, "\n"); + } +} + +# define YY_REDUCE_PRINT(Rule) \ +do { \ + if (yydebug) \ + yy_reduce_print (yyvsp, Rule); \ +} while (YYID (0)) + +/* Nonzero means print parse trace. It is left uninitialized so that + multiple parsers can coexist. */ +int yydebug; +#else /* !YYDEBUG */ +# define YYDPRINTF(Args) +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) +# define YY_STACK_PRINT(Bottom, Top) +# define YY_REDUCE_PRINT(Rule) +#endif /* !YYDEBUG */ + + +/* YYINITDEPTH -- initial size of the parser's stacks. */ +#ifndef YYINITDEPTH +# define YYINITDEPTH 200 +#endif + +/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only + if the built-in stack extension method is used). + + Do not make this value too large; the results are undefined if + YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) + evaluated with infinite-precision integer arithmetic. */ + +#ifndef YYMAXDEPTH +# define YYMAXDEPTH 10000 +#endif + + + +#if YYERROR_VERBOSE + +# ifndef yystrlen +# if defined __GLIBC__ && defined _STRING_H +# define yystrlen strlen +# else +/* Return the length of YYSTR. */ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static YYSIZE_T +yystrlen (const char *yystr) +#else +static YYSIZE_T +yystrlen (yystr) + const char *yystr; +#endif +{ + YYSIZE_T yylen; + for (yylen = 0; yystr[yylen]; yylen++) + continue; + return yylen; +} +# endif +# endif + +# ifndef yystpcpy +# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE +# define yystpcpy stpcpy +# else +/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in + YYDEST. */ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static char * +yystpcpy (char *yydest, const char *yysrc) +#else +static char * +yystpcpy (yydest, yysrc) + char *yydest; + const char *yysrc; +#endif +{ + char *yyd = yydest; + const char *yys = yysrc; + + while ((*yyd++ = *yys++) != '\0') + continue; + + return yyd - 1; +} +# endif +# endif + +# ifndef yytnamerr +/* Copy to YYRES the contents of YYSTR after stripping away unnecessary + quotes and backslashes, so that it's suitable for yyerror. The + heuristic is that double-quoting is unnecessary unless the string + contains an apostrophe, a comma, or backslash (other than + backslash-backslash). YYSTR is taken from yytname. If YYRES is + null, do not copy; instead, return the length of what the result + would have been. */ +static YYSIZE_T +yytnamerr (char *yyres, const char *yystr) +{ + if (*yystr == '"') + { + YYSIZE_T yyn = 0; + char const *yyp = yystr; + + for (;;) + switch (*++yyp) + { + case '\'': + case ',': + goto do_not_strip_quotes; + + case '\\': + if (*++yyp != '\\') + goto do_not_strip_quotes; + /* Fall through. */ + default: + if (yyres) + yyres[yyn] = *yyp; + yyn++; + break; + + case '"': + if (yyres) + yyres[yyn] = '\0'; + return yyn; + } + do_not_strip_quotes: ; + } + + if (! yyres) + return yystrlen (yystr); + + return yystpcpy (yyres, yystr) - yyres; +} +# endif + +/* Copy into YYRESULT an error message about the unexpected token + YYCHAR while in state YYSTATE. Return the number of bytes copied, + including the terminating null byte. If YYRESULT is null, do not + copy anything; just return the number of bytes that would be + copied. As a special case, return 0 if an ordinary "syntax error" + message will do. Return YYSIZE_MAXIMUM if overflow occurs during + size calculation. */ +static YYSIZE_T +yysyntax_error (char *yyresult, int yystate, int yychar) +{ + int yyn = yypact[yystate]; + + if (! (YYPACT_NINF < yyn && yyn <= YYLAST)) + return 0; + else + { + int yytype = YYTRANSLATE (yychar); + YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]); + YYSIZE_T yysize = yysize0; + YYSIZE_T yysize1; + int yysize_overflow = 0; + enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; + char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; + int yyx; + +# if 0 + /* This is so xgettext sees the translatable formats that are + constructed on the fly. */ + YY_("syntax error, unexpected %s"); + YY_("syntax error, unexpected %s, expecting %s"); + YY_("syntax error, unexpected %s, expecting %s or %s"); + YY_("syntax error, unexpected %s, expecting %s or %s or %s"); + YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"); +# endif + char *yyfmt; + char const *yyf; + static char const yyunexpected[] = "syntax error, unexpected %s"; + static char const yyexpecting[] = ", expecting %s"; + static char const yyor[] = " or %s"; + char yyformat[sizeof yyunexpected + + sizeof yyexpecting - 1 + + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2) + * (sizeof yyor - 1))]; + char const *yyprefix = yyexpecting; + + /* Start YYX at -YYN if negative to avoid negative indexes in + YYCHECK. */ + int yyxbegin = yyn < 0 ? -yyn : 0; + + /* Stay within bounds of both yycheck and yytname. */ + int yychecklim = YYLAST - yyn + 1; + int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; + int yycount = 1; + + yyarg[0] = yytname[yytype]; + yyfmt = yystpcpy (yyformat, yyunexpected); + + for (yyx = yyxbegin; yyx < yyxend; ++yyx) + if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) + { + if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) + { + yycount = 1; + yysize = yysize0; + yyformat[sizeof yyunexpected - 1] = '\0'; + break; + } + yyarg[yycount++] = yytname[yyx]; + yysize1 = yysize + yytnamerr (0, yytname[yyx]); + yysize_overflow |= (yysize1 < yysize); + yysize = yysize1; + yyfmt = yystpcpy (yyfmt, yyprefix); + yyprefix = yyor; + } + + yyf = YY_(yyformat); + yysize1 = yysize + yystrlen (yyf); + yysize_overflow |= (yysize1 < yysize); + yysize = yysize1; + + if (yysize_overflow) + return YYSIZE_MAXIMUM; + + if (yyresult) + { + /* Avoid sprintf, as that infringes on the user's name space. + Don't have undefined behavior even if the translation + produced a string with the wrong number of "%s"s. */ + char *yyp = yyresult; + int yyi = 0; + while ((*yyp = *yyf) != '\0') + { + if (*yyp == '%' && yyf[1] == 's' && yyi < yycount) + { + yyp += yytnamerr (yyp, yyarg[yyi++]); + yyf += 2; + } + else + { + yyp++; + yyf++; + } + } + } + return yysize; + } +} +#endif /* YYERROR_VERBOSE */ + + +/*-----------------------------------------------. +| Release the memory associated to this symbol. | +`-----------------------------------------------*/ + +/*ARGSUSED*/ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep) +#else +static void +yydestruct (yymsg, yytype, yyvaluep) + const char *yymsg; + int yytype; + YYSTYPE *yyvaluep; +#endif +{ + YYUSE (yyvaluep); + + if (!yymsg) + yymsg = "Deleting"; + YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); + + switch (yytype) + { + case 51: /* "choice_entry" */ + + { + fprintf(stderr, "%s:%d: missing end statement for this entry\n", + (yyvaluep->menu)->file->name, (yyvaluep->menu)->lineno); + if (current_menu == (yyvaluep->menu)) + menu_end_menu(); +}; + + break; + case 57: /* "if_entry" */ + + { + fprintf(stderr, "%s:%d: missing end statement for this entry\n", + (yyvaluep->menu)->file->name, (yyvaluep->menu)->lineno); + if (current_menu == (yyvaluep->menu)) + menu_end_menu(); +}; + + break; + case 62: /* "menu_entry" */ + + { + fprintf(stderr, "%s:%d: missing end statement for this entry\n", + (yyvaluep->menu)->file->name, (yyvaluep->menu)->lineno); + if (current_menu == (yyvaluep->menu)) + menu_end_menu(); +}; + + break; + + default: + break; + } +} + + +/* Prevent warnings from -Wmissing-prototypes. */ + +#ifdef YYPARSE_PARAM +#if defined __STDC__ || defined __cplusplus +int yyparse (void *YYPARSE_PARAM); +#else +int yyparse (); +#endif +#else /* ! YYPARSE_PARAM */ +#if defined __STDC__ || defined __cplusplus +int yyparse (void); +#else +int yyparse (); +#endif +#endif /* ! YYPARSE_PARAM */ + + + +/* The look-ahead symbol. */ +int yychar; + +/* The semantic value of the look-ahead symbol. */ +YYSTYPE yylval; + +/* Number of syntax errors so far. */ +int yynerrs; + + + +/*----------. +| yyparse. | +`----------*/ + +#ifdef YYPARSE_PARAM +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +int +yyparse (void *YYPARSE_PARAM) +#else +int +yyparse (YYPARSE_PARAM) + void *YYPARSE_PARAM; +#endif +#else /* ! YYPARSE_PARAM */ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +int +yyparse (void) +#else +int +yyparse () + +#endif +#endif +{ + + int yystate; + int yyn; + int yyresult; + /* Number of tokens to shift before error messages enabled. */ + int yyerrstatus; + /* Look-ahead token as an internal (translated) token number. */ + int yytoken = 0; +#if YYERROR_VERBOSE + /* Buffer for error messages, and its allocated size. */ + char yymsgbuf[128]; + char *yymsg = yymsgbuf; + YYSIZE_T yymsg_alloc = sizeof yymsgbuf; +#endif + + /* Three stacks and their tools: + `yyss': related to states, + `yyvs': related to semantic values, + `yyls': related to locations. + + Refer to the stacks thru separate pointers, to allow yyoverflow + to reallocate them elsewhere. */ + + /* The state stack. */ + yytype_int16 yyssa[YYINITDEPTH]; + yytype_int16 *yyss = yyssa; + yytype_int16 *yyssp; + + /* The semantic value stack. */ + YYSTYPE yyvsa[YYINITDEPTH]; + YYSTYPE *yyvs = yyvsa; + YYSTYPE *yyvsp; + + + +#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N)) + + YYSIZE_T yystacksize = YYINITDEPTH; + + /* The variables used to return semantic value and location from the + action routines. */ + YYSTYPE yyval; + + + /* The number of symbols on the RHS of the reduced rule. + Keep to zero when no symbol should be popped. */ + int yylen = 0; + + YYDPRINTF ((stderr, "Starting parse\n")); + + yystate = 0; + yyerrstatus = 0; + yynerrs = 0; + yychar = YYEMPTY; /* Cause a token to be read. */ + + /* Initialize stack pointers. + Waste one element of value and location stack + so that they stay on the same level as the state stack. + The wasted elements are never initialized. */ + + yyssp = yyss; + yyvsp = yyvs; + + goto yysetstate; + +/*------------------------------------------------------------. +| yynewstate -- Push a new state, which is found in yystate. | +`------------------------------------------------------------*/ + yynewstate: + /* In all cases, when you get here, the value and location stacks + have just been pushed. So pushing a state here evens the stacks. */ + yyssp++; + + yysetstate: + *yyssp = yystate; + + if (yyss + yystacksize - 1 <= yyssp) + { + /* Get the current used size of the three stacks, in elements. */ + YYSIZE_T yysize = yyssp - yyss + 1; + +#ifdef yyoverflow + { + /* Give user a chance to reallocate the stack. Use copies of + these so that the &'s don't force the real ones into + memory. */ + YYSTYPE *yyvs1 = yyvs; + yytype_int16 *yyss1 = yyss; + + + /* Each stack pointer address is followed by the size of the + data in use in that stack, in bytes. This used to be a + conditional around just the two extra args, but that might + be undefined if yyoverflow is a macro. */ + yyoverflow (YY_("memory exhausted"), + &yyss1, yysize * sizeof (*yyssp), + &yyvs1, yysize * sizeof (*yyvsp), + + &yystacksize); + + yyss = yyss1; + yyvs = yyvs1; + } +#else /* no yyoverflow */ +# ifndef YYSTACK_RELOCATE + goto yyexhaustedlab; +# else + /* Extend the stack our own way. */ + if (YYMAXDEPTH <= yystacksize) + goto yyexhaustedlab; + yystacksize *= 2; + if (YYMAXDEPTH < yystacksize) + yystacksize = YYMAXDEPTH; + + { + yytype_int16 *yyss1 = yyss; + union yyalloc *yyptr = + (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); + if (! yyptr) + goto yyexhaustedlab; + YYSTACK_RELOCATE (yyss); + YYSTACK_RELOCATE (yyvs); + +# undef YYSTACK_RELOCATE + if (yyss1 != yyssa) + YYSTACK_FREE (yyss1); + } +# endif +#endif /* no yyoverflow */ + + yyssp = yyss + yysize - 1; + yyvsp = yyvs + yysize - 1; + + + YYDPRINTF ((stderr, "Stack size increased to %lu\n", + (unsigned long int) yystacksize)); + + if (yyss + yystacksize - 1 <= yyssp) + YYABORT; + } + + YYDPRINTF ((stderr, "Entering state %d\n", yystate)); + + goto yybackup; + +/*-----------. +| yybackup. | +`-----------*/ +yybackup: + + /* Do appropriate processing given the current state. Read a + look-ahead token if we need one and don't already have one. */ + + /* First try to decide what to do without reference to look-ahead token. */ + yyn = yypact[yystate]; + if (yyn == YYPACT_NINF) + goto yydefault; + + /* Not known => get a look-ahead token if don't already have one. */ + + /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol. */ + if (yychar == YYEMPTY) + { + YYDPRINTF ((stderr, "Reading a token: ")); + yychar = YYLEX; + } + + if (yychar <= YYEOF) + { + yychar = yytoken = YYEOF; + YYDPRINTF ((stderr, "Now at end of input.\n")); + } + else + { + yytoken = YYTRANSLATE (yychar); + YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); + } + + /* If the proper action on seeing token YYTOKEN is to reduce or to + detect an error, take that action. */ + yyn += yytoken; + if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) + goto yydefault; + yyn = yytable[yyn]; + if (yyn <= 0) + { + if (yyn == 0 || yyn == YYTABLE_NINF) + goto yyerrlab; + yyn = -yyn; + goto yyreduce; + } + + if (yyn == YYFINAL) + YYACCEPT; + + /* Count tokens shifted since error; after three, turn off error + status. */ + if (yyerrstatus) + yyerrstatus--; + + /* Shift the look-ahead token. */ + YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); + + /* Discard the shifted token unless it is eof. */ + if (yychar != YYEOF) + yychar = YYEMPTY; + + yystate = yyn; + *++yyvsp = yylval; + + goto yynewstate; + + +/*-----------------------------------------------------------. +| yydefault -- do the default action for the current state. | +`-----------------------------------------------------------*/ +yydefault: + yyn = yydefact[yystate]; + if (yyn == 0) + goto yyerrlab; + goto yyreduce; + + +/*-----------------------------. +| yyreduce -- Do a reduction. | +`-----------------------------*/ +yyreduce: + /* yyn is the number of a rule to reduce with. */ + yylen = yyr2[yyn]; + + /* If YYLEN is nonzero, implement the default value of the action: + `$$ = $1'. + + Otherwise, the following line sets YYVAL to garbage. + This behavior is undocumented and Bison + users should not rely upon it. Assigning to YYVAL + unconditionally makes the parser a bit smaller, and it avoids a + GCC warning that YYVAL may be used uninitialized. */ + yyval = yyvsp[1-yylen]; + + + YY_REDUCE_PRINT (yyn); + switch (yyn) + { + case 8: + + { zconf_error("unexpected end statement"); ;} + break; + + case 9: + + { zconf_error("unknown statement \"%s\"", (yyvsp[(2) - (4)].string)); ;} + break; + + case 10: + + { + zconf_error("unexpected option \"%s\"", kconf_id_strings + (yyvsp[(2) - (4)].id)->name); +;} + break; + + case 11: + + { zconf_error("invalid statement"); ;} + break; + + case 25: + + { zconf_error("unknown option \"%s\"", (yyvsp[(1) - (3)].string)); ;} + break; + + case 26: + + { zconf_error("invalid option"); ;} + break; + + case 27: + + { + struct symbol *sym = sym_lookup((yyvsp[(2) - (3)].string), 0); + sym->flags |= SYMBOL_OPTIONAL; + menu_add_entry(sym); + printd(DEBUG_PARSE, "%s:%d:config %s\n", zconf_curname(), zconf_lineno(), (yyvsp[(2) - (3)].string)); +;} + break; + + case 28: + + { + menu_end_entry(); + printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno()); +;} + break; + + case 29: + + { + struct symbol *sym = sym_lookup((yyvsp[(2) - (3)].string), 0); + sym->flags |= SYMBOL_OPTIONAL; + menu_add_entry(sym); + printd(DEBUG_PARSE, "%s:%d:menuconfig %s\n", zconf_curname(), zconf_lineno(), (yyvsp[(2) - (3)].string)); +;} + break; + + case 30: + + { + if (current_entry->prompt) + current_entry->prompt->type = P_MENU; + else + zconfprint("warning: menuconfig statement without prompt"); + menu_end_entry(); + printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno()); +;} + break; + + case 38: + + { + menu_set_type((yyvsp[(1) - (3)].id)->stype); + printd(DEBUG_PARSE, "%s:%d:type(%u)\n", + zconf_curname(), zconf_lineno(), + (yyvsp[(1) - (3)].id)->stype); +;} + break; + + case 39: + + { + menu_add_prompt(P_PROMPT, (yyvsp[(2) - (4)].string), (yyvsp[(3) - (4)].expr)); + printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno()); +;} + break; + + case 40: + + { + menu_add_expr(P_DEFAULT, (yyvsp[(2) - (4)].expr), (yyvsp[(3) - (4)].expr)); + if ((yyvsp[(1) - (4)].id)->stype != S_UNKNOWN) + menu_set_type((yyvsp[(1) - (4)].id)->stype); + printd(DEBUG_PARSE, "%s:%d:default(%u)\n", + zconf_curname(), zconf_lineno(), + (yyvsp[(1) - (4)].id)->stype); +;} + break; + + case 41: + + { + menu_add_symbol(P_SELECT, sym_lookup((yyvsp[(2) - (4)].string), 0), (yyvsp[(3) - (4)].expr)); + printd(DEBUG_PARSE, "%s:%d:select\n", zconf_curname(), zconf_lineno()); +;} + break; + + case 42: + + { + menu_add_expr(P_RANGE, expr_alloc_comp(E_RANGE,(yyvsp[(2) - (5)].symbol), (yyvsp[(3) - (5)].symbol)), (yyvsp[(4) - (5)].expr)); + printd(DEBUG_PARSE, "%s:%d:range\n", zconf_curname(), zconf_lineno()); +;} + break; + + case 45: + + { + struct kconf_id *id = kconf_id_lookup((yyvsp[(2) - (3)].string), strlen((yyvsp[(2) - (3)].string))); + if (id && id->flags & TF_OPTION) + menu_add_option(id->token, (yyvsp[(3) - (3)].string)); + else + zconfprint("warning: ignoring unknown option %s", (yyvsp[(2) - (3)].string)); + free((yyvsp[(2) - (3)].string)); +;} + break; + + case 46: + + { (yyval.string) = NULL; ;} + break; + + case 47: + + { (yyval.string) = (yyvsp[(2) - (2)].string); ;} + break; + + case 48: + + { + struct symbol *sym = sym_lookup((yyvsp[(2) - (3)].string), SYMBOL_CHOICE); + sym->flags |= SYMBOL_AUTO; + menu_add_entry(sym); + menu_add_expr(P_CHOICE, NULL, NULL); + printd(DEBUG_PARSE, "%s:%d:choice\n", zconf_curname(), zconf_lineno()); +;} + break; + + case 49: + + { + (yyval.menu) = menu_add_menu(); +;} + break; + + case 50: + + { + if (zconf_endtoken((yyvsp[(1) - (1)].id), T_CHOICE, T_ENDCHOICE)) { + menu_end_menu(); + printd(DEBUG_PARSE, "%s:%d:endchoice\n", zconf_curname(), zconf_lineno()); + } +;} + break; + + case 58: + + { + menu_add_prompt(P_PROMPT, (yyvsp[(2) - (4)].string), (yyvsp[(3) - (4)].expr)); + printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno()); +;} + break; + + case 59: + + { + if ((yyvsp[(1) - (3)].id)->stype == S_BOOLEAN || (yyvsp[(1) - (3)].id)->stype == S_TRISTATE) { + menu_set_type((yyvsp[(1) - (3)].id)->stype); + printd(DEBUG_PARSE, "%s:%d:type(%u)\n", + zconf_curname(), zconf_lineno(), + (yyvsp[(1) - (3)].id)->stype); + } else + YYERROR; +;} + break; + + case 60: + + { + current_entry->sym->flags |= SYMBOL_OPTIONAL; + printd(DEBUG_PARSE, "%s:%d:optional\n", zconf_curname(), zconf_lineno()); +;} + break; + + case 61: + + { + if ((yyvsp[(1) - (4)].id)->stype == S_UNKNOWN) { + menu_add_symbol(P_DEFAULT, sym_lookup((yyvsp[(2) - (4)].string), 0), (yyvsp[(3) - (4)].expr)); + printd(DEBUG_PARSE, "%s:%d:default\n", + zconf_curname(), zconf_lineno()); + } else + YYERROR; +;} + break; + + case 64: + + { + printd(DEBUG_PARSE, "%s:%d:if\n", zconf_curname(), zconf_lineno()); + menu_add_entry(NULL); + menu_add_dep((yyvsp[(2) - (3)].expr)); + (yyval.menu) = menu_add_menu(); +;} + break; + + case 65: + + { + if (zconf_endtoken((yyvsp[(1) - (1)].id), T_IF, T_ENDIF)) { + menu_end_menu(); + printd(DEBUG_PARSE, "%s:%d:endif\n", zconf_curname(), zconf_lineno()); + } +;} + break; + + case 71: + + { + menu_add_entry(NULL); + menu_add_prompt(P_MENU, (yyvsp[(2) - (3)].string), NULL); + printd(DEBUG_PARSE, "%s:%d:menu\n", zconf_curname(), zconf_lineno()); +;} + break; + + case 72: + + { + (yyval.menu) = menu_add_menu(); +;} + break; + + case 73: + + { + if (zconf_endtoken((yyvsp[(1) - (1)].id), T_MENU, T_ENDMENU)) { + menu_end_menu(); + printd(DEBUG_PARSE, "%s:%d:endmenu\n", zconf_curname(), zconf_lineno()); + } +;} + break; + + case 79: + + { + printd(DEBUG_PARSE, "%s:%d:source %s\n", zconf_curname(), zconf_lineno(), (yyvsp[(2) - (3)].string)); + zconf_nextfile((yyvsp[(2) - (3)].string)); +;} + break; + + case 80: + + { + menu_add_entry(NULL); + menu_add_prompt(P_COMMENT, (yyvsp[(2) - (3)].string), NULL); + printd(DEBUG_PARSE, "%s:%d:comment\n", zconf_curname(), zconf_lineno()); +;} + break; + + case 81: + + { + menu_end_entry(); +;} + break; + + case 82: + + { + printd(DEBUG_PARSE, "%s:%d:help\n", zconf_curname(), zconf_lineno()); + zconf_starthelp(); +;} + break; + + case 83: + + { + current_entry->help = (yyvsp[(2) - (2)].string); +;} + break; + + case 88: + + { + menu_add_dep((yyvsp[(3) - (4)].expr)); + printd(DEBUG_PARSE, "%s:%d:depends on\n", zconf_curname(), zconf_lineno()); +;} + break; + + case 90: + + { + menu_add_prompt(P_PROMPT, (yyvsp[(1) - (2)].string), (yyvsp[(2) - (2)].expr)); +;} + break; + + case 93: + + { (yyval.id) = (yyvsp[(1) - (2)].id); ;} + break; + + case 94: + + { (yyval.id) = (yyvsp[(1) - (2)].id); ;} + break; + + case 95: + + { (yyval.id) = (yyvsp[(1) - (2)].id); ;} + break; + + case 98: + + { (yyval.expr) = NULL; ;} + break; + + case 99: + + { (yyval.expr) = (yyvsp[(2) - (2)].expr); ;} + break; + + case 100: + + { (yyval.expr) = expr_alloc_symbol((yyvsp[(1) - (1)].symbol)); ;} + break; + + case 101: + + { (yyval.expr) = expr_alloc_comp(E_EQUAL, (yyvsp[(1) - (3)].symbol), (yyvsp[(3) - (3)].symbol)); ;} + break; + + case 102: + + { (yyval.expr) = expr_alloc_comp(E_UNEQUAL, (yyvsp[(1) - (3)].symbol), (yyvsp[(3) - (3)].symbol)); ;} + break; + + case 103: + + { (yyval.expr) = (yyvsp[(2) - (3)].expr); ;} + break; + + case 104: + + { (yyval.expr) = expr_alloc_one(E_NOT, (yyvsp[(2) - (2)].expr)); ;} + break; + + case 105: + + { (yyval.expr) = expr_alloc_two(E_OR, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;} + break; + + case 106: + + { (yyval.expr) = expr_alloc_two(E_AND, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;} + break; + + case 107: + + { (yyval.symbol) = sym_lookup((yyvsp[(1) - (1)].string), 0); free((yyvsp[(1) - (1)].string)); ;} + break; + + case 108: + + { (yyval.symbol) = sym_lookup((yyvsp[(1) - (1)].string), SYMBOL_CONST); free((yyvsp[(1) - (1)].string)); ;} + break; + + case 109: + + { (yyval.string) = NULL; ;} + break; + + +/* Line 1267 of yacc.c. */ + + default: break; + } + YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); + + YYPOPSTACK (yylen); + yylen = 0; + YY_STACK_PRINT (yyss, yyssp); + + *++yyvsp = yyval; + + + /* Now `shift' the result of the reduction. Determine what state + that goes to, based on the state we popped back to and the rule + number reduced by. */ + + yyn = yyr1[yyn]; + + yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; + if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) + yystate = yytable[yystate]; + else + yystate = yydefgoto[yyn - YYNTOKENS]; + + goto yynewstate; + + +/*------------------------------------. +| yyerrlab -- here on detecting error | +`------------------------------------*/ +yyerrlab: + /* If not already recovering from an error, report this error. */ + if (!yyerrstatus) + { + ++yynerrs; +#if ! YYERROR_VERBOSE + yyerror (YY_("syntax error")); +#else + { + YYSIZE_T yysize = yysyntax_error (0, yystate, yychar); + if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM) + { + YYSIZE_T yyalloc = 2 * yysize; + if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM)) + yyalloc = YYSTACK_ALLOC_MAXIMUM; + if (yymsg != yymsgbuf) + YYSTACK_FREE (yymsg); + yymsg = (char *) YYSTACK_ALLOC (yyalloc); + if (yymsg) + yymsg_alloc = yyalloc; + else + { + yymsg = yymsgbuf; + yymsg_alloc = sizeof yymsgbuf; + } + } + + if (0 < yysize && yysize <= yymsg_alloc) + { + (void) yysyntax_error (yymsg, yystate, yychar); + yyerror (yymsg); + } + else + { + yyerror (YY_("syntax error")); + if (yysize != 0) + goto yyexhaustedlab; + } + } +#endif + } + + + + if (yyerrstatus == 3) + { + /* If just tried and failed to reuse look-ahead token after an + error, discard it. */ + + if (yychar <= YYEOF) + { + /* Return failure if at end of input. */ + if (yychar == YYEOF) + YYABORT; + } + else + { + yydestruct ("Error: discarding", + yytoken, &yylval); + yychar = YYEMPTY; + } + } + + /* Else will try to reuse look-ahead token after shifting the error + token. */ + goto yyerrlab1; + + +/*---------------------------------------------------. +| yyerrorlab -- error raised explicitly by YYERROR. | +`---------------------------------------------------*/ +yyerrorlab: + + /* Pacify compilers like GCC when the user code never invokes + YYERROR and the label yyerrorlab therefore never appears in user + code. */ + if (/*CONSTCOND*/ 0) + goto yyerrorlab; + + /* Do not reclaim the symbols of the rule which action triggered + this YYERROR. */ + YYPOPSTACK (yylen); + yylen = 0; + YY_STACK_PRINT (yyss, yyssp); + yystate = *yyssp; + goto yyerrlab1; + + +/*-------------------------------------------------------------. +| yyerrlab1 -- common code for both syntax error and YYERROR. | +`-------------------------------------------------------------*/ +yyerrlab1: + yyerrstatus = 3; /* Each real token shifted decrements this. */ + + for (;;) + { + yyn = yypact[yystate]; + if (yyn != YYPACT_NINF) + { + yyn += YYTERROR; + if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) + { + yyn = yytable[yyn]; + if (0 < yyn) + break; + } + } + + /* Pop the current state because it cannot handle the error token. */ + if (yyssp == yyss) + YYABORT; + + + yydestruct ("Error: popping", + yystos[yystate], yyvsp); + YYPOPSTACK (1); + yystate = *yyssp; + YY_STACK_PRINT (yyss, yyssp); + } + + if (yyn == YYFINAL) + YYACCEPT; + + *++yyvsp = yylval; + + + /* Shift the error token. */ + YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp); + + yystate = yyn; + goto yynewstate; + + +/*-------------------------------------. +| yyacceptlab -- YYACCEPT comes here. | +`-------------------------------------*/ +yyacceptlab: + yyresult = 0; + goto yyreturn; + +/*-----------------------------------. +| yyabortlab -- YYABORT comes here. | +`-----------------------------------*/ +yyabortlab: + yyresult = 1; + goto yyreturn; + +#ifndef yyoverflow +/*-------------------------------------------------. +| yyexhaustedlab -- memory exhaustion comes here. | +`-------------------------------------------------*/ +yyexhaustedlab: + yyerror (YY_("memory exhausted")); + yyresult = 2; + /* Fall through. */ +#endif + +yyreturn: + if (yychar != YYEOF && yychar != YYEMPTY) + yydestruct ("Cleanup: discarding lookahead", + yytoken, &yylval); + /* Do not reclaim the symbols of the rule which action triggered + this YYABORT or YYACCEPT. */ + YYPOPSTACK (yylen); + YY_STACK_PRINT (yyss, yyssp); + while (yyssp != yyss) + { + yydestruct ("Cleanup: popping", + yystos[*yyssp], yyvsp); + YYPOPSTACK (1); + } +#ifndef yyoverflow + if (yyss != yyssa) + YYSTACK_FREE (yyss); +#endif +#if YYERROR_VERBOSE + if (yymsg != yymsgbuf) + YYSTACK_FREE (yymsg); +#endif + /* Make sure YYID is used. */ + return YYID (yyresult); +} + + + + + +void conf_parse(const char *name) +{ + struct symbol *sym; + int i; + + zconf_initscan(name); + + sym_init(); + menu_init(); + modules_sym = sym_lookup(NULL, 0); + modules_sym->type = S_BOOLEAN; + modules_sym->flags |= SYMBOL_AUTO; + rootmenu.prompt = menu_add_prompt(P_MENU, "uClibc Configuration", NULL); + +#if YYDEBUG + if (getenv("ZCONF_DEBUG")) + zconfdebug = 1; +#endif + zconfparse(); + if (zconfnerrs) + exit(1); + if (!modules_sym->prop) { + struct property *prop; + + prop = prop_alloc(P_DEFAULT, modules_sym); + prop->expr = expr_alloc_symbol(sym_lookup("MODULES", 0)); + } + menu_finalize(&rootmenu); + for_all_symbols(i, sym) { + if (sym_check_deps(sym)) + zconfnerrs++; + } + if (zconfnerrs) + exit(1); + sym_set_change_count(1); +} + +const char *zconf_tokenname(int token) +{ + switch (token) { + case T_MENU: return "menu"; + case T_ENDMENU: return "endmenu"; + case T_CHOICE: return "choice"; + case T_ENDCHOICE: return "endchoice"; + case T_IF: return "if"; + case T_ENDIF: return "endif"; + case T_DEPENDS: return "depends"; + } + return ""; +} + +static bool zconf_endtoken(struct kconf_id *id, int starttoken, int endtoken) +{ + if (id->token != endtoken) { + zconf_error("unexpected '%s' within %s block", + kconf_id_strings + id->name, zconf_tokenname(starttoken)); + zconfnerrs++; + return false; + } + if (current_menu->file != current_file) { + zconf_error("'%s' in different file than '%s'", + kconf_id_strings + id->name, zconf_tokenname(starttoken)); + fprintf(stderr, "%s:%d: location of the '%s'\n", + current_menu->file->name, current_menu->lineno, + zconf_tokenname(starttoken)); + zconfnerrs++; + return false; + } + return true; +} + +static void zconfprint(const char *err, ...) +{ + va_list ap; + + fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno()); + va_start(ap, err); + vfprintf(stderr, err, ap); + va_end(ap); + fprintf(stderr, "\n"); +} + +static void zconf_error(const char *err, ...) +{ + va_list ap; + + zconfnerrs++; + fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno()); + va_start(ap, err); + vfprintf(stderr, err, ap); + va_end(ap); + fprintf(stderr, "\n"); +} + +static void zconferror(const char *err) +{ +#if YYDEBUG + fprintf(stderr, "%s:%d: %s\n", zconf_curname(), zconf_lineno() + 1, err); +#endif +} + +void print_quoted_string(FILE *out, const char *str) +{ + const char *p; + int len; + + putc('"', out); + while ((p = strchr(str, '"'))) { + len = p - str; + if (len) + fprintf(out, "%.*s", len, str); + fputs("\\\"", out); + str = p + 1; + } + fputs(str, out); + putc('"', out); +} + +void print_symbol(FILE *out, struct menu *menu) +{ + struct symbol *sym = menu->sym; + struct property *prop; + + if (sym_is_choice(sym)) + fprintf(out, "choice\n"); + else + fprintf(out, "config %s\n", sym->name); + switch (sym->type) { + case S_BOOLEAN: + fputs(" boolean\n", out); + break; + case S_TRISTATE: + fputs(" tristate\n", out); + break; + case S_STRING: + fputs(" string\n", out); + break; + case S_INT: + fputs(" integer\n", out); + break; + case S_HEX: + fputs(" hex\n", out); + break; + default: + fputs(" ???\n", out); + break; + } + for (prop = sym->prop; prop; prop = prop->next) { + if (prop->menu != menu) + continue; + switch (prop->type) { + case P_PROMPT: + fputs(" prompt ", out); + print_quoted_string(out, prop->text); + if (!expr_is_yes(prop->visible.expr)) { + fputs(" if ", out); + expr_fprint(prop->visible.expr, out); + } + fputc('\n', out); + break; + case P_DEFAULT: + fputs( " default ", out); + expr_fprint(prop->expr, out); + if (!expr_is_yes(prop->visible.expr)) { + fputs(" if ", out); + expr_fprint(prop->visible.expr, out); + } + fputc('\n', out); + break; + case P_CHOICE: + fputs(" #choice value\n", out); + break; + default: + fprintf(out, " unknown prop %d!\n", prop->type); + break; + } + } + if (menu->help) { + int len = strlen(menu->help); + while (menu->help[--len] == '\n') + menu->help[len] = 0; + fprintf(out, " help\n%s\n", menu->help); + } + fputc('\n', out); +} + +void zconfdump(FILE *out) +{ + struct property *prop; + struct symbol *sym; + struct menu *menu; + + menu = rootmenu.list; + while (menu) { + if ((sym = menu->sym)) + print_symbol(out, menu); + else if ((prop = menu->prompt)) { + switch (prop->type) { + case P_COMMENT: + fputs("\ncomment ", out); + print_quoted_string(out, prop->text); + fputs("\n", out); + break; + case P_MENU: + fputs("\nmenu ", out); + print_quoted_string(out, prop->text); + fputs("\n", out); + break; + default: + ; + } + if (!expr_is_yes(prop->visible.expr)) { + fputs(" depends ", out); + expr_fprint(prop->visible.expr, out); + fputc('\n', out); + } + fputs("\n", out); + } + + if (menu->list) + menu = menu->list; + else if (menu->next) + menu = menu->next; + else while ((menu = menu->parent)) { + if (menu->prompt && menu->prompt->type == P_MENU) + fputs("\nendmenu\n", out); + if (menu->next) { + menu = menu->next; + break; + } + } + } +} + +#include "lex.zconf.c" +#include "util.c" +#include "confdata.c" +#include "expr.c" +#include "symbol.c" +#include "menu.c" + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/zconf.y b/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/zconf.y new file mode 100644 index 00000000..029c9b6c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/config/zconf.y @@ -0,0 +1,706 @@ +%{ +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +#include +#include +#include +#include +#include +#include + +#define LKC_DIRECT_LINK +#include "lkc.h" + +#include "zconf.hash.c" + +#define printd(mask, fmt...) if (cdebug & (mask)) printf(fmt) + +#define PRINTD 0x0001 +#define DEBUG_PARSE 0x0002 + +int cdebug = PRINTD; + +extern int zconflex(void); +static void zconfprint(const char *err, ...); +static void zconf_error(const char *err, ...); +static void zconferror(const char *err); +static bool zconf_endtoken(struct kconf_id *id, int starttoken, int endtoken); + +struct symbol *symbol_hash[257]; + +static struct menu *current_menu, *current_entry; + +#define YYDEBUG 0 +#if YYDEBUG +#define YYERROR_VERBOSE +#endif +%} +%expect 26 + +%union +{ + char *string; + struct file *file; + struct symbol *symbol; + struct expr *expr; + struct menu *menu; + struct kconf_id *id; +} + +%token T_MAINMENU +%token T_MENU +%token T_ENDMENU +%token T_SOURCE +%token T_CHOICE +%token T_ENDCHOICE +%token T_COMMENT +%token T_CONFIG +%token T_MENUCONFIG +%token T_HELP +%token T_HELPTEXT +%token T_IF +%token T_ENDIF +%token T_DEPENDS +%token T_OPTIONAL +%token T_PROMPT +%token T_TYPE +%token T_DEFAULT +%token T_SELECT +%token T_RANGE +%token T_OPTION +%token T_ON +%token T_WORD +%token T_WORD_QUOTE +%token T_UNEQUAL +%token T_CLOSE_PAREN +%token T_OPEN_PAREN +%token T_EOL + +%left T_OR +%left T_AND +%left T_EQUAL T_UNEQUAL +%nonassoc T_NOT + +%type prompt +%type symbol +%type expr +%type if_expr +%type end +%type option_name +%type if_entry menu_entry choice_entry +%type symbol_option_arg word_opt + +%destructor { + fprintf(stderr, "%s:%d: missing end statement for this entry\n", + $$->file->name, $$->lineno); + if (current_menu == $$) + menu_end_menu(); +} if_entry menu_entry choice_entry + +%% +input: stmt_list; + +stmt_list: + /* empty */ + | stmt_list common_stmt + | stmt_list choice_stmt + | stmt_list menu_stmt + | stmt_list T_MAINMENU prompt nl + | stmt_list end { zconf_error("unexpected end statement"); } + | stmt_list T_WORD error T_EOL { zconf_error("unknown statement \"%s\"", $2); } + | stmt_list option_name error T_EOL +{ + zconf_error("unexpected option \"%s\"", kconf_id_strings + $2->name); +} + | stmt_list error T_EOL { zconf_error("invalid statement"); } +; + +option_name: + T_DEPENDS | T_PROMPT | T_TYPE | T_SELECT | T_OPTIONAL | T_RANGE | T_DEFAULT +; + +common_stmt: + T_EOL + | if_stmt + | comment_stmt + | config_stmt + | menuconfig_stmt + | source_stmt +; + +option_error: + T_WORD error T_EOL { zconf_error("unknown option \"%s\"", $1); } + | error T_EOL { zconf_error("invalid option"); } +; + + +/* config/menuconfig entry */ + +config_entry_start: T_CONFIG T_WORD T_EOL +{ + struct symbol *sym = sym_lookup($2, 0); + sym->flags |= SYMBOL_OPTIONAL; + menu_add_entry(sym); + printd(DEBUG_PARSE, "%s:%d:config %s\n", zconf_curname(), zconf_lineno(), $2); +}; + +config_stmt: config_entry_start config_option_list +{ + menu_end_entry(); + printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno()); +}; + +menuconfig_entry_start: T_MENUCONFIG T_WORD T_EOL +{ + struct symbol *sym = sym_lookup($2, 0); + sym->flags |= SYMBOL_OPTIONAL; + menu_add_entry(sym); + printd(DEBUG_PARSE, "%s:%d:menuconfig %s\n", zconf_curname(), zconf_lineno(), $2); +}; + +menuconfig_stmt: menuconfig_entry_start config_option_list +{ + if (current_entry->prompt) + current_entry->prompt->type = P_MENU; + else + zconfprint("warning: menuconfig statement without prompt"); + menu_end_entry(); + printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno()); +}; + +config_option_list: + /* empty */ + | config_option_list config_option + | config_option_list symbol_option + | config_option_list depends + | config_option_list help + | config_option_list option_error + | config_option_list T_EOL +; + +config_option: T_TYPE prompt_stmt_opt T_EOL +{ + menu_set_type($1->stype); + printd(DEBUG_PARSE, "%s:%d:type(%u)\n", + zconf_curname(), zconf_lineno(), + $1->stype); +}; + +config_option: T_PROMPT prompt if_expr T_EOL +{ + menu_add_prompt(P_PROMPT, $2, $3); + printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno()); +}; + +config_option: T_DEFAULT expr if_expr T_EOL +{ + menu_add_expr(P_DEFAULT, $2, $3); + if ($1->stype != S_UNKNOWN) + menu_set_type($1->stype); + printd(DEBUG_PARSE, "%s:%d:default(%u)\n", + zconf_curname(), zconf_lineno(), + $1->stype); +}; + +config_option: T_SELECT T_WORD if_expr T_EOL +{ + menu_add_symbol(P_SELECT, sym_lookup($2, 0), $3); + printd(DEBUG_PARSE, "%s:%d:select\n", zconf_curname(), zconf_lineno()); +}; + +config_option: T_RANGE symbol symbol if_expr T_EOL +{ + menu_add_expr(P_RANGE, expr_alloc_comp(E_RANGE,$2, $3), $4); + printd(DEBUG_PARSE, "%s:%d:range\n", zconf_curname(), zconf_lineno()); +}; + +symbol_option: T_OPTION symbol_option_list T_EOL +; + +symbol_option_list: + /* empty */ + | symbol_option_list T_WORD symbol_option_arg +{ + struct kconf_id *id = kconf_id_lookup($2, strlen($2)); + if (id && id->flags & TF_OPTION) + menu_add_option(id->token, $3); + else + zconfprint("warning: ignoring unknown option %s", $2); + free($2); +}; + +symbol_option_arg: + /* empty */ { $$ = NULL; } + | T_EQUAL prompt { $$ = $2; } +; + +/* choice entry */ + +choice: T_CHOICE word_opt T_EOL +{ + struct symbol *sym = sym_lookup($2, SYMBOL_CHOICE); + sym->flags |= SYMBOL_AUTO; + menu_add_entry(sym); + menu_add_expr(P_CHOICE, NULL, NULL); + printd(DEBUG_PARSE, "%s:%d:choice\n", zconf_curname(), zconf_lineno()); +}; + +choice_entry: choice choice_option_list +{ + $$ = menu_add_menu(); +}; + +choice_end: end +{ + if (zconf_endtoken($1, T_CHOICE, T_ENDCHOICE)) { + menu_end_menu(); + printd(DEBUG_PARSE, "%s:%d:endchoice\n", zconf_curname(), zconf_lineno()); + } +}; + +choice_stmt: choice_entry choice_block choice_end +; + +choice_option_list: + /* empty */ + | choice_option_list choice_option + | choice_option_list depends + | choice_option_list help + | choice_option_list T_EOL + | choice_option_list option_error +; + +choice_option: T_PROMPT prompt if_expr T_EOL +{ + menu_add_prompt(P_PROMPT, $2, $3); + printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno()); +}; + +choice_option: T_TYPE prompt_stmt_opt T_EOL +{ + if ($1->stype == S_BOOLEAN || $1->stype == S_TRISTATE) { + menu_set_type($1->stype); + printd(DEBUG_PARSE, "%s:%d:type(%u)\n", + zconf_curname(), zconf_lineno(), + $1->stype); + } else + YYERROR; +}; + +choice_option: T_OPTIONAL T_EOL +{ + current_entry->sym->flags |= SYMBOL_OPTIONAL; + printd(DEBUG_PARSE, "%s:%d:optional\n", zconf_curname(), zconf_lineno()); +}; + +choice_option: T_DEFAULT T_WORD if_expr T_EOL +{ + if ($1->stype == S_UNKNOWN) { + menu_add_symbol(P_DEFAULT, sym_lookup($2, 0), $3); + printd(DEBUG_PARSE, "%s:%d:default\n", + zconf_curname(), zconf_lineno()); + } else + YYERROR; +}; + +choice_block: + /* empty */ + | choice_block common_stmt +; + +/* if entry */ + +if_entry: T_IF expr nl +{ + printd(DEBUG_PARSE, "%s:%d:if\n", zconf_curname(), zconf_lineno()); + menu_add_entry(NULL); + menu_add_dep($2); + $$ = menu_add_menu(); +}; + +if_end: end +{ + if (zconf_endtoken($1, T_IF, T_ENDIF)) { + menu_end_menu(); + printd(DEBUG_PARSE, "%s:%d:endif\n", zconf_curname(), zconf_lineno()); + } +}; + +if_stmt: if_entry if_block if_end +; + +if_block: + /* empty */ + | if_block common_stmt + | if_block menu_stmt + | if_block choice_stmt +; + +/* menu entry */ + +menu: T_MENU prompt T_EOL +{ + menu_add_entry(NULL); + menu_add_prompt(P_MENU, $2, NULL); + printd(DEBUG_PARSE, "%s:%d:menu\n", zconf_curname(), zconf_lineno()); +}; + +menu_entry: menu depends_list +{ + $$ = menu_add_menu(); +}; + +menu_end: end +{ + if (zconf_endtoken($1, T_MENU, T_ENDMENU)) { + menu_end_menu(); + printd(DEBUG_PARSE, "%s:%d:endmenu\n", zconf_curname(), zconf_lineno()); + } +}; + +menu_stmt: menu_entry menu_block menu_end +; + +menu_block: + /* empty */ + | menu_block common_stmt + | menu_block menu_stmt + | menu_block choice_stmt +; + +source_stmt: T_SOURCE prompt T_EOL +{ + printd(DEBUG_PARSE, "%s:%d:source %s\n", zconf_curname(), zconf_lineno(), $2); + zconf_nextfile($2); +}; + +/* comment entry */ + +comment: T_COMMENT prompt T_EOL +{ + menu_add_entry(NULL); + menu_add_prompt(P_COMMENT, $2, NULL); + printd(DEBUG_PARSE, "%s:%d:comment\n", zconf_curname(), zconf_lineno()); +}; + +comment_stmt: comment depends_list +{ + menu_end_entry(); +}; + +/* help option */ + +help_start: T_HELP T_EOL +{ + printd(DEBUG_PARSE, "%s:%d:help\n", zconf_curname(), zconf_lineno()); + zconf_starthelp(); +}; + +help: help_start T_HELPTEXT +{ + current_entry->help = $2; +}; + +/* depends option */ + +depends_list: + /* empty */ + | depends_list depends + | depends_list T_EOL + | depends_list option_error +; + +depends: T_DEPENDS T_ON expr T_EOL +{ + menu_add_dep($3); + printd(DEBUG_PARSE, "%s:%d:depends on\n", zconf_curname(), zconf_lineno()); +}; + +/* prompt statement */ + +prompt_stmt_opt: + /* empty */ + | prompt if_expr +{ + menu_add_prompt(P_PROMPT, $1, $2); +}; + +prompt: T_WORD + | T_WORD_QUOTE +; + +end: T_ENDMENU T_EOL { $$ = $1; } + | T_ENDCHOICE T_EOL { $$ = $1; } + | T_ENDIF T_EOL { $$ = $1; } +; + +nl: + T_EOL + | nl T_EOL +; + +if_expr: /* empty */ { $$ = NULL; } + | T_IF expr { $$ = $2; } +; + +expr: symbol { $$ = expr_alloc_symbol($1); } + | symbol T_EQUAL symbol { $$ = expr_alloc_comp(E_EQUAL, $1, $3); } + | symbol T_UNEQUAL symbol { $$ = expr_alloc_comp(E_UNEQUAL, $1, $3); } + | T_OPEN_PAREN expr T_CLOSE_PAREN { $$ = $2; } + | T_NOT expr { $$ = expr_alloc_one(E_NOT, $2); } + | expr T_OR expr { $$ = expr_alloc_two(E_OR, $1, $3); } + | expr T_AND expr { $$ = expr_alloc_two(E_AND, $1, $3); } +; + +symbol: T_WORD { $$ = sym_lookup($1, 0); free($1); } + | T_WORD_QUOTE { $$ = sym_lookup($1, SYMBOL_CONST); free($1); } +; + +word_opt: /* empty */ { $$ = NULL; } + | T_WORD + +%% + +void conf_parse(const char *name) +{ + struct symbol *sym; + int i; + + zconf_initscan(name); + + sym_init(); + menu_init(); + modules_sym = sym_lookup(NULL, 0); + modules_sym->type = S_BOOLEAN; + modules_sym->flags |= SYMBOL_AUTO; + rootmenu.prompt = menu_add_prompt(P_MENU, "uClibc Configuration", NULL); + +#if YYDEBUG + if (getenv("ZCONF_DEBUG")) + zconfdebug = 1; +#endif + zconfparse(); + if (zconfnerrs) + exit(1); + if (!modules_sym->prop) { + struct property *prop; + + prop = prop_alloc(P_DEFAULT, modules_sym); + prop->expr = expr_alloc_symbol(sym_lookup("MODULES", 0)); + } + menu_finalize(&rootmenu); + for_all_symbols(i, sym) { + if (sym_check_deps(sym)) + zconfnerrs++; + } + if (zconfnerrs) + exit(1); + sym_set_change_count(1); +} + +const char *zconf_tokenname(int token) +{ + switch (token) { + case T_MENU: return "menu"; + case T_ENDMENU: return "endmenu"; + case T_CHOICE: return "choice"; + case T_ENDCHOICE: return "endchoice"; + case T_IF: return "if"; + case T_ENDIF: return "endif"; + case T_DEPENDS: return "depends"; + } + return ""; +} + +static bool zconf_endtoken(struct kconf_id *id, int starttoken, int endtoken) +{ + if (id->token != endtoken) { + zconf_error("unexpected '%s' within %s block", + kconf_id_strings + id->name, zconf_tokenname(starttoken)); + zconfnerrs++; + return false; + } + if (current_menu->file != current_file) { + zconf_error("'%s' in different file than '%s'", + kconf_id_strings + id->name, zconf_tokenname(starttoken)); + fprintf(stderr, "%s:%d: location of the '%s'\n", + current_menu->file->name, current_menu->lineno, + zconf_tokenname(starttoken)); + zconfnerrs++; + return false; + } + return true; +} + +static void zconfprint(const char *err, ...) +{ + va_list ap; + + fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno()); + va_start(ap, err); + vfprintf(stderr, err, ap); + va_end(ap); + fprintf(stderr, "\n"); +} + +static void zconf_error(const char *err, ...) +{ + va_list ap; + + zconfnerrs++; + fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno()); + va_start(ap, err); + vfprintf(stderr, err, ap); + va_end(ap); + fprintf(stderr, "\n"); +} + +static void zconferror(const char *err) +{ +#if YYDEBUG + fprintf(stderr, "%s:%d: %s\n", zconf_curname(), zconf_lineno() + 1, err); +#endif +} + +void print_quoted_string(FILE *out, const char *str) +{ + const char *p; + int len; + + putc('"', out); + while ((p = strchr(str, '"'))) { + len = p - str; + if (len) + fprintf(out, "%.*s", len, str); + fputs("\\\"", out); + str = p + 1; + } + fputs(str, out); + putc('"', out); +} + +void print_symbol(FILE *out, struct menu *menu) +{ + struct symbol *sym = menu->sym; + struct property *prop; + + if (sym_is_choice(sym)) + fprintf(out, "choice\n"); + else + fprintf(out, "config %s\n", sym->name); + switch (sym->type) { + case S_BOOLEAN: + fputs(" boolean\n", out); + break; + case S_TRISTATE: + fputs(" tristate\n", out); + break; + case S_STRING: + fputs(" string\n", out); + break; + case S_INT: + fputs(" integer\n", out); + break; + case S_HEX: + fputs(" hex\n", out); + break; + default: + fputs(" ???\n", out); + break; + } + for (prop = sym->prop; prop; prop = prop->next) { + if (prop->menu != menu) + continue; + switch (prop->type) { + case P_PROMPT: + fputs(" prompt ", out); + print_quoted_string(out, prop->text); + if (!expr_is_yes(prop->visible.expr)) { + fputs(" if ", out); + expr_fprint(prop->visible.expr, out); + } + fputc('\n', out); + break; + case P_DEFAULT: + fputs( " default ", out); + expr_fprint(prop->expr, out); + if (!expr_is_yes(prop->visible.expr)) { + fputs(" if ", out); + expr_fprint(prop->visible.expr, out); + } + fputc('\n', out); + break; + case P_CHOICE: + fputs(" #choice value\n", out); + break; + default: + fprintf(out, " unknown prop %d!\n", prop->type); + break; + } + } + if (menu->help) { + int len = strlen(menu->help); + while (menu->help[--len] == '\n') + menu->help[len] = 0; + fprintf(out, " help\n%s\n", menu->help); + } + fputc('\n', out); +} + +void zconfdump(FILE *out) +{ + struct property *prop; + struct symbol *sym; + struct menu *menu; + + menu = rootmenu.list; + while (menu) { + if ((sym = menu->sym)) + print_symbol(out, menu); + else if ((prop = menu->prompt)) { + switch (prop->type) { + case P_COMMENT: + fputs("\ncomment ", out); + print_quoted_string(out, prop->text); + fputs("\n", out); + break; + case P_MENU: + fputs("\nmenu ", out); + print_quoted_string(out, prop->text); + fputs("\n", out); + break; + default: + ; + } + if (!expr_is_yes(prop->visible.expr)) { + fputs(" depends ", out); + expr_fprint(prop->visible.expr, out); + fputc('\n', out); + } + fputs("\n", out); + } + + if (menu->list) + menu = menu->list; + else if (menu->next) + menu = menu->next; + else while ((menu = menu->parent)) { + if (menu->prompt && menu->prompt->type == P_MENU) + fputs("\nendmenu\n", out); + if (menu->next) { + menu = menu->next; + break; + } + } + } +} + +#include "lex.zconf.c" +#include "util.c" +#include "confdata.c" +#include "expr.c" +#include "symbol.c" +#include "menu.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/libstrip/libstrip b/l4/pkg/uclibc/lib/contrib/uclibc/extra/libstrip/libstrip new file mode 100755 index 00000000..69a10438 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/libstrip/libstrip @@ -0,0 +1,72 @@ +#!/usr/bin/perl -w +# vi: set ts=4: + +# Libstrip - A utility to optimize libraries for specific executables +# Copyright (C) 2001 David A. Schleef +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of version 2 of the GNU General Public License as +# published by the Free Software Foundation. +# +# This is a surprisingly simple script that gets a list of +# unresolved symbols in a list of executables specified on the +# command line, and then relinks the uClibc shared object file +# with only the those symbols and their dependencies. This +# results in a shared object that is optimized for the executables +# listed, and thus may not work with other executables. +# +# Example: optimizing uClibc for BusyBox +# Compile uClibc and BusyBox as normal. Then, in this +# directory, run: +# libstrip path/to/busybox +# After the script completes, there should be a new +# libuClibc-0.9.5.so in the current directory, which +# is optimized for busybox. +# +# How it works: +# The uClibc Makefiles create libuClibc.so by first creating +# the ar archive libc.a with all the object files, then links +# the final libuClibc.so by using 'ld --shared --whole-archive'. +# We take advantage of the linker command line option --undefined, +# which pulls in a symbol and all its dependencies, and so relink +# the library using --undefined for each symbol in place of +# --whole-archive. The linker script is used only to avoid +# having very long command lines. + +$topdir="../.."; + +# This is the name of the default ldscript for shared libs. The +# file name will be different for other architectures. +$ldscript="/usr/lib/ldscripts/elf_i386.xs"; + +my @syms; +my @allsyms; +my $s; + +while($exec = shift @ARGV){ + #print "$exec\n"; + @syms=`nm --dynamic $exec`; + for $s (@syms){ + chomp $s; + if($s =~ m/^.{8} [BUV] (.+)/){ + my $x = $1; + if(!grep { m/^$x$/; } @allsyms){ + unshift @allsyms, $x; + } + } + } +} + +open(LDSCRIPT, ">ldscript"); +print LDSCRIPT "INCLUDE $ldscript\n"; +for $s (@allsyms) { + print LDSCRIPT "EXTERN($s)\n"; +} + + +`gcc -s -nostdlib -Wl,-warn-common -shared \\ + -o libuClibc-0.9.5.so \\ + -Wl,-soname,libc.so.0 -Wl,--script=ldscript \\ + $topdir/libc/libc.a \\ + $topdir/libc/tmp/libgcc-need.a` + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/.gitignore b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/.gitignore new file mode 100644 index 00000000..3ea19652 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/.gitignore @@ -0,0 +1,26 @@ +# +# Never ignore these +# +!.gitignore + +# +# Generated files +# +/c8tables.h +/codesets.txt +/locale_collate.h +/locale_data.c +/locale_tables.h +/locales.txt +/lt_defines.h +/uClibc_locale_data.h +/wctables.h +# +# generators +# +/gen_collate +/gen_ldc +/gen_locale +/gen_wc8bit +/gen_wctype + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/LOCALES b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/LOCALES new file mode 100644 index 00000000..0a30cc10 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/LOCALES @@ -0,0 +1,346 @@ +# First some @modifier mappings. Internally, the modifier is signaled by +# replacing '_' in the locale name with a unique identifying character. +# For example, internally we map "ca_ES@euro" to "caeES". This allows for +# smaller code and easier processing of locale names. + +@euro e +@cyrillic c + +#--------------------------------------------------------------------------- +# Next, set to {y}es to enable and {n}o to disable the UTF-8 and the 8-bit +# codeset locales. Of course, you must have built the c8tables.h and +# the wctables.h files appropriately. + + +UTF-8 yes +8-BIT yes + +#--------------------------------------------------------------------------- +# Now the locales + +af_ZA ISO-8859-1 +af_ZA.UTF-8 UTF-8 +am_ET UTF-8 +ar_AE ISO-8859-6 +ar_AE.UTF-8 UTF-8 +ar_BH ISO-8859-6 +ar_BH.UTF-8 UTF-8 +ar_DZ ISO-8859-6 +ar_DZ.UTF-8 UTF-8 +ar_EG ISO-8859-6 +ar_EG.UTF-8 UTF-8 +ar_IN UTF-8 +ar_IQ ISO-8859-6 +ar_IQ.UTF-8 UTF-8 +ar_JO ISO-8859-6 +ar_JO.UTF-8 UTF-8 +ar_KW ISO-8859-6 +ar_KW.UTF-8 UTF-8 +ar_LB ISO-8859-6 +ar_LB.UTF-8 UTF-8 +ar_LY ISO-8859-6 +ar_LY.UTF-8 UTF-8 +ar_MA ISO-8859-6 +ar_MA.UTF-8 UTF-8 +ar_OM ISO-8859-6 +ar_OM.UTF-8 UTF-8 +ar_QA ISO-8859-6 +ar_QA.UTF-8 UTF-8 +ar_SA ISO-8859-6 +ar_SA.UTF-8 UTF-8 +ar_SD ISO-8859-6 +ar_SD.UTF-8 UTF-8 +ar_SY ISO-8859-6 +ar_SY.UTF-8 UTF-8 +ar_TN ISO-8859-6 +ar_TN.UTF-8 UTF-8 +ar_YE ISO-8859-6 +ar_YE.UTF-8 UTF-8 +# az_AZ ISO-8859-9E +az_AZ ISO-8859-9 +az_AZ.UTF-8 UTF-8 +be_BY CP1251 +be_BY.UTF-8 UTF-8 +bg_BG CP1251 +bg_BG.UTF-8 UTF-8 +bn_BD UTF-8 +bn_IN UTF-8 +br_FR ISO-8859-1 +br_FR.UTF-8 UTF-8 +bs_BA ISO-8859-2 +bs_BA.UTF-8 UTF-8 +ca_ES ISO-8859-1 +ca_ES.UTF-8 UTF-8 +ca_ES.UTF-8@euro UTF-8 +ca_ES@euro ISO-8859-15 +cs_CZ ISO-8859-2 +cs_CZ.UTF-8 UTF-8 +cy_GB ISO-8859-14 +cy_GB.UTF-8 UTF-8 +da_DK ISO-8859-1 +da_DK.UTF-8 UTF-8 +de_AT ISO-8859-1 +de_AT.UTF-8 UTF-8 +de_AT.UTF-8@euro UTF-8 +de_AT@euro ISO-8859-15 +de_BE ISO-8859-1 +de_BE.UTF-8 UTF-8 +de_BE.UTF-8@euro UTF-8 +de_BE@euro ISO-8859-15 +de_CH ISO-8859-1 +de_CH.UTF-8 UTF-8 +de_DE ISO-8859-1 +de_DE.UTF-8 UTF-8 +de_DE.UTF-8@euro UTF-8 +de_DE@euro ISO-8859-15 +de_LU ISO-8859-1 +de_LU.UTF-8 UTF-8 +de_LU.UTF-8@euro UTF-8 +de_LU@euro ISO-8859-15 +el_GR ISO-8859-7 +el_GR.UTF-8 UTF-8 +en_AU ISO-8859-1 +en_AU.UTF-8 UTF-8 +en_BW ISO-8859-1 +en_BW.UTF-8 UTF-8 +en_CA ISO-8859-1 +en_CA.UTF-8 UTF-8 +en_DK ISO-8859-1 +en_DK.UTF-8 UTF-8 +en_GB ISO-8859-1 +en_GB.UTF-8 UTF-8 +en_HK ISO-8859-1 +en_HK.UTF-8 UTF-8 +en_IE ISO-8859-1 +en_IE.UTF-8 UTF-8 +en_IE.UTF-8@euro UTF-8 +en_IE@euro ISO-8859-15 +en_IN UTF-8 +en_NZ ISO-8859-1 +en_NZ.UTF-8 UTF-8 +en_PH ISO-8859-1 +en_PH.UTF-8 UTF-8 +en_SG ISO-8859-1 +en_SG.UTF-8 UTF-8 +en_US ISO-8859-1 +en_US.UTF-8 UTF-8 +en_ZA ISO-8859-1 +en_ZA.UTF-8 UTF-8 +en_ZW ISO-8859-1 +en_ZW.UTF-8 UTF-8 +eo_EO.UTF-8 UTF-8 +es_AR ISO-8859-1 +es_AR.UTF-8 UTF-8 +es_BO ISO-8859-1 +es_BO.UTF-8 UTF-8 +es_CL ISO-8859-1 +es_CL.UTF-8 UTF-8 +es_CO ISO-8859-1 +es_CO.UTF-8 UTF-8 +es_CR ISO-8859-1 +es_CR.UTF-8 UTF-8 +es_DO ISO-8859-1 +es_DO.UTF-8 UTF-8 +es_EC ISO-8859-1 +es_EC.UTF-8 UTF-8 +es_ES ISO-8859-1 +es_ES.UTF-8 UTF-8 +es_ES.UTF-8@euro UTF-8 +es_ES@euro ISO-8859-15 +es_GT ISO-8859-1 +es_GT.UTF-8 UTF-8 +es_HN ISO-8859-1 +es_HN.UTF-8 UTF-8 +es_MX ISO-8859-1 +es_MX.UTF-8 UTF-8 +es_NI ISO-8859-1 +es_NI.UTF-8 UTF-8 +es_PA ISO-8859-1 +es_PA.UTF-8 UTF-8 +es_PE ISO-8859-1 +es_PE.UTF-8 UTF-8 +es_PR ISO-8859-1 +es_PR.UTF-8 UTF-8 +es_PY ISO-8859-1 +es_PY.UTF-8 UTF-8 +es_SV ISO-8859-1 +es_SV.UTF-8 UTF-8 +es_US ISO-8859-1 +es_US.UTF-8 UTF-8 +es_UY ISO-8859-1 +es_UY.UTF-8 UTF-8 +es_VE ISO-8859-1 +es_VE.UTF-8 UTF-8 +et_EE ISO-8859-1 +et_EE.UTF-8 UTF-8 +eu_ES ISO-8859-1 +eu_ES.UTF-8 UTF-8 +eu_ES.UTF-8@euro UTF-8 +eu_ES@euro ISO-8859-15 +fa_IR UTF-8 +fa_IR.UTF-8 UTF-8 +fi_FI ISO-8859-1 +fi_FI.UTF-8 UTF-8 +fi_FI.UTF-8@euro UTF-8 +fi_FI@euro ISO-8859-15 +fo_FO ISO-8859-1 +fo_FO.UTF-8 UTF-8 +fr_BE ISO-8859-1 +fr_BE.UTF-8 UTF-8 +fr_BE.UTF-8@euro UTF-8 +fr_BE@euro ISO-8859-15 +fr_CA ISO-8859-1 +fr_CA.UTF-8 UTF-8 +fr_CH ISO-8859-1 +fr_CH.UTF-8 UTF-8 +fr_FR ISO-8859-1 +fr_FR.UTF-8 UTF-8 +fr_FR.UTF-8@euro UTF-8 +fr_FR@euro ISO-8859-15 +fr_LU ISO-8859-1 +fr_LU.UTF-8 UTF-8 +fr_LU.UTF-8@euro UTF-8 +fr_LU@euro ISO-8859-15 +ga_IE ISO-8859-1 +ga_IE.UTF-8 UTF-8 +ga_IE.UTF-8@euro UTF-8 +ga_IE@euro ISO-8859-15 +gd_GB ISO-8859-15 +gd_GB.UTF-8 UTF-8 +gl_ES ISO-8859-1 +gl_ES.UTF-8 UTF-8 +gl_ES.UTF-8@euro UTF-8 +gl_ES@euro ISO-8859-15 +gv_GB ISO-8859-1 +gv_GB.UTF-8 UTF-8 +he_IL ISO-8859-8 +he_IL.UTF-8 UTF-8 +hi_IN UTF-8 +hi_IN.UTF-8 UTF-8 +hr_HR ISO-8859-2 +hr_HR.UTF-8 UTF-8 +hu_HU ISO-8859-2 +hu_HU.UTF-8 UTF-8 +hy_AM ARMSCII-8 +hy_AM.UTF-8 UTF-8 +id_ID ISO-8859-1 +id_ID.UTF-8 UTF-8 +is_IS ISO-8859-1 +is_IS.UTF-8 UTF-8 +it_CH ISO-8859-1 +it_CH.UTF-8 UTF-8 +it_IT ISO-8859-1 +it_IT.UTF-8 UTF-8 +it_IT.UTF-8@euro UTF-8 +it_IT@euro ISO-8859-15 +iw_IL ISO-8859-8 +iw_IL.UTF-8 UTF-8 +ja_JP.UTF-8 UTF-8 +ka_GE GEORGIAN-PS +ka_GE.UTF-8 UTF-8 +kl_GL ISO-8859-1 +kl_GL.UTF-8 UTF-8 +ko_KR.UTF-8 UTF-8 +kw_GB ISO-8859-1 +kw_GB.UTF-8 UTF-8 +lt_LT ISO-8859-13 +lt_LT.UTF-8 UTF-8 +lv_LV ISO-8859-13 +lv_LV.UTF-8 UTF-8 +mi_NZ ISO-8859-13 +mi_NZ.UTF-8 UTF-8 +mk_MK ISO-8859-5 +mk_MK.UTF-8 UTF-8 +mr_IN UTF-8 +mr_IN.UTF-8 UTF-8 +ms_MY ISO-8859-1 +ms_MY.UTF-8 UTF-8 +mt_MT ISO-8859-3 +mt_MT.UTF-8 UTF-8 +nl_BE ISO-8859-1 +nl_BE.UTF-8 UTF-8 +nl_BE.UTF-8@euro UTF-8 +nl_BE@euro ISO-8859-15 +nl_NL ISO-8859-1 +nl_NL.UTF-8 UTF-8 +nl_NL.UTF-8@euro UTF-8 +nl_NL@euro ISO-8859-15 +nn_NO ISO-8859-1 +nn_NO.UTF-8 UTF-8 +no_NO ISO-8859-1 +no_NO.UTF-8 UTF-8 +oc_FR ISO-8859-1 +oc_FR.UTF-8 UTF-8 +pl_PL ISO-8859-2 +pl_PL.UTF-8 UTF-8 +pt_BR ISO-8859-1 +pt_BR.UTF-8 UTF-8 +pt_PT ISO-8859-1 +pt_PT.UTF-8 UTF-8 +pt_PT.UTF-8@euro UTF-8 +pt_PT@euro ISO-8859-15 +ro_RO ISO-8859-2 +ro_RO.UTF-8 UTF-8 +ru_RU ISO-8859-5 +ru_RU.KOI8-R KOI8-R +ru_RU.UTF-8 UTF-8 +ru_UA KOI8-U +ru_UA.UTF-8 UTF-8 +se_NO UTF-8 +sk_SK ISO-8859-2 +sk_SK.UTF-8 UTF-8 +sl_SI ISO-8859-2 +sl_SI.UTF-8 UTF-8 +sq_AL ISO-8859-1 +sq_AL.UTF-8 UTF-8 +sr_YU ISO-8859-2 +sr_YU.UTF-8 UTF-8 +sr_YU.UTF-8@cyrillic UTF-8 +sr_YU@cyrillic ISO-8859-5 +sv_FI ISO-8859-1 +sv_FI.UTF-8 UTF-8 +sv_FI.UTF-8@euro UTF-8 +sv_FI@euro ISO-8859-15 +sv_SE ISO-8859-1 +sv_SE.UTF-8 UTF-8 +ta_IN UTF-8 +te_IN UTF-8 +tg_TJ KOI8-T +tg_TJ.UTF-8 UTF-8 +th_TH TIS-620 +th_TH.UTF-8 UTF-8 +ti_ER UTF-8 +ti_ET UTF-8 +tl_PH ISO-8859-1 +tl_PH.UTF-8 UTF-8 +tr_TR ISO-8859-9 +tr_TR.UTF-8 UTF-8 +# tt_RU TATAR-CYR +tt_RU.UTF-8 UTF-8 +uk_UA KOI8-U +uk_UA.UTF-8 UTF-8 +ur_PK UTF-8 +uz_UZ ISO-8859-1 +uz_UZ.UTF-8 UTF-8 +vi_VN UTF-8 +vi_VN.UTF-8 UTF-8 +wa_BE ISO-8859-1 +wa_BE.UTF-8 UTF-8 +wa_BE@euro ISO-8859-15 +yi_US CP1255 +yi_US.UTF-8 UTF-8 +zh_CN.UTF-8 UTF-8 +zh_HK.UTF-8 UTF-8 +zh_SG UTF-8 +zh_TW.UTF-8 UTF-8 + +# The following are standard locales, but we currently don't support +# the necessary multibyte encodings. +# ja_JP.EUC-JP EUC-JP +# ko_KR.EUC-KR EUC-KR +# zh_CN GB2312 +# zh_CN.GB18030 GB18030 +# zh_CN.GBK GBK +# zh_TW.EUC-TW EUC-TW +# zh_HK BIG5-HKSCS +# zh_TW BIG5 diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/Makefile new file mode 100644 index 00000000..ff229e20 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# +top_srcdir=../../ +top_builddir=$(if $(O),$(O),../../)/ + +all: objs +include $(top_srcdir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/Makefile.in new file mode 100644 index 00000000..221a5158 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/Makefile.in @@ -0,0 +1,242 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +locale_DIR := $(top_srcdir)extra/locale +locale_OUT := $(top_builddir)extra/locale + +# command used to download source code +WGET := wget --passive-ftp + +LOCALE_DATA_FILENAME := uClibc-locale-20081111-$(ARCH_NATIVE_BIT)-$(if $(ARCH_LITTLE_ENDIAN),el,eb).tgz + +BUILD_CFLAGS-locale-common := \ + -D__UCLIBC_GEN_LOCALE \ + -I$(top_builddir) + +BUILD_CFLAGS-gen_wc8bit := $(BUILD_CFLAGS-locale-common) -DCTYPE_PACKED=1 +BUILD_CFLAGS-gen_wctype := $(BUILD_CFLAGS-locale-common) +BUILD_CFLAGS-gen_ldc := -I$(locale_OUT) +ifeq ($(UCLIBC_HAS_WCHAR),y) +BUILD_CFLAGS-gen_wc8bit += -DDO_WIDE_CHAR=1 +BUILD_CFLAGS-gen_ldc += -D__WCHAR_ENABLED=1 +endif +BUILD_CFLAGS-gen_locale := -D_GNU_SOURCE -I$(locale_OUT) +BUILD_CFLAGS-gen_collate := -D_GNU_SOURCE + +locale_headers-$(UCLIBC_HAS_LOCALE) := $(top_builddir)include/bits/uClibc_locale_data.h + +#DEPH-locale := $(top_builddir)include/bits/sysnum.h +DEPH-locale := $(top_builddir)include/bits/uClibc_config.h +DEPH-gen_collate := $(DEPH-locale) +DEPH-gen_ldc := $(addprefix $(locale_OUT)/,c8tables.h wctables.h locale_tables.h locale_collate.h) $(DEPH-locale) +DEPH-gen_locale := $(addprefix $(locale_OUT)/,c8tables.h) $(DEPH-locale) +DEPH-gen_wc8bit := $(top_builddir)include/bits/uClibc_ctype.h $(DEPH-locale) +DEPH-gen_wctype := $(top_builddir)include/bits/uClibc_ctype.h $(DEPH-locale) + +locale_HOBJ := gen_collate gen_ldc gen_locale gen_wc8bit gen_wctype +locale_HOBJ := $(addprefix $(locale_OUT)/,$(locale_HOBJ)) +$(locale_HOBJ): | $(locale_OUT) + +locale_SRC := $(locale_OUT)/locale_data.c +locale_OBJ := $(locale_OUT)/locale_data.o + +CFLAGS-locale_data.c := -D__WCHAR_ENABLED -I$(locale_OUT) -I$(locale_DIR) + +#headers-$(UCLIBC_HAS_LOCALE) += $(locale_headers-y) +headers: $(locale_headers-y) + +libc-$(UCLIBC_HAS_LOCALE) += $(locale_OBJ) +libc-nomulti-$(UCLIBC_HAS_LOCALE) += $(locale_OBJ) + +$(locale_OUT)%.o: $(locale_OUT)%.c FORCE ; $(compile.c) +$(locale_OUT)%.os: $(locale_OUT)%.c FORCE ; $(compile.c) +$(locale_OUT)%.oS: $(locale_OUT)%.c FORCE ; $(compile.c) +$(locale_OUT)%.o: $(locale_OUT)%.S FORCE ; $(compile.S) +$(locale_OUT)%.os: $(locale_OUT)%.S FORCE ; $(compile.S) +$(locale_OUT)%.oS: $(locale_OUT)%.S FORCE ; $(compile.S) +$(locale_OUT)%.o: $(locale_OUT)%.s FORCE ; $(compile.S) +$(locale_OUT)%.os: $(locale_OUT)%.s FORCE ; $(compile.S) +$(locale_OUT)%.oS: $(locale_OUT)%.s FORCE ; $(compile.S) +$(locale_OUT)%.i: $(locale_OUT)%.c FORCE ; $(compile.i) +$(locale_OUT)%.i: $(locale_OUT)%.S FORCE ; $(compile.i) +$(locale_OUT)%.s: $(locale_OUT)%.c FORCE ; $(compile.s) +$(locale_OUT)%.s: $(locale_OUT)%.S FORCE ; $(compile.s) +$(locale_OUT)%.dep: + + +locale_headers: headers $(top_builddir)include/bits/uClibc_locale_data.h + +# make sure that the host system has locales (this check is ok for uClibc/glibc) +# we do not know though which locales were really enabled for libc at build time +ifeq ($(wildcard /usr/include/iconv.h),) + +$(locale_OUT)/codesets.txt: + @if [ ! -f $@ ] ; then \ + set -e; \ + echo " "; \ + echo "You do not have a codesets.txt file. Please create this "; \ + echo "file in the $(locale_OUT) directory by running something like: "; \ + echo " find $(CURDIR)/$(locale_DIR)/charmaps -name \"*.pairs\" > \\"; \ + echo " $@"; \ + echo "and then edit that file to disable/enable the codesets you wish to support. "; \ + echo " "; \ + false; \ + fi + +$(locale_OUT)/locales.txt: + @if [ ! -f $@ ] ; then \ + set -e; \ + echo " "; \ + echo "You do not have a locales.txt file in the $(locale_OUT) "; \ + echo "directory, Please copy the LOCALES file to locales.txt by "; \ + echo "running something like: "; \ + echo " cp $(locale_DIR)/LOCALES \\ "; \ + echo " $@ "; \ + echo "then edit locales.txt to disable/enable the locales you wish "; \ + echo "to support. "; \ + echo " "; \ + false; \ + fi + +else + +$(locale_OUT)/codesets.txt: + @$(disp_gen) +ifeq ($(UCLIBC_BUILD_MINIMAL_LOCALE),y) + $(Q)echo "$(CURDIR)/$(locale_DIR)/charmaps/ASCII.pairs" > $@ + $(Q)echo "$(CURDIR)/$(locale_DIR)/charmaps/ISO-8859-1.pairs" >> $@ +else + $(Q)set -e; \ + tmp=`mktemp $@.XXXXXX 2>/dev/null || true`; \ + [ -z "$$tmp" ] && tmp='$@.new'; \ + find $(CURDIR)/$(locale_DIR)/charmaps/ -name '*.pairs' | \ + sort > $$tmp; \ + [ -s $$tmp ]; \ + if cmp $@ $$tmp >/dev/null 2>&1; then \ + $(RM) $$tmp; \ + else \ + mv -f $$tmp $@; \ + fi +endif + +# the lines beginning w/ '#-' are mandatory +# at least one conversion is needed (euro/cyrillic) +$(locale_OUT)/locales.txt: $(locale_DIR)/LOCALES + @$(disp_gen) +ifeq ($(UCLIBC_BUILD_MINIMAL_LOCALE),y) + $(Q)echo "@euro e" > $@ + $(Q)echo "#-" >> $@ + $(Q)echo "UTF-8 yes" >> $@ + $(Q)echo "8-BIT yes" >> $@ + $(Q)echo "#-" >> $@ + $(Q)for locale in $(call qstrip,$(UCLIBC_BUILD_MINIMAL_LOCALES)); do \ + echo "$$locale.UTF-8 UTF-8"; \ + echo "$$locale ISO-8859-1"; \ + done >> $@ +else + $(Q)cat $< > $@ +endif + +endif + +$(locale_DIR)/gen_collate.c: $(DEPH-gen_collate) +$(locale_OUT)/gen_collate : $(locale_DIR)/gen_collate.c + $(hcompile.u) +$(locale_DIR)/gen_ldc.c: $(DEPH-gen_ldc) +$(locale_OUT)/gen_ldc : $(locale_DIR)/gen_ldc.c + $(hcompile.u) +$(locale_DIR)/gen_locale.c: $(DEPH-gen_locale) +$(locale_OUT)/gen_locale : $(locale_DIR)/gen_locale.c + $(hcompile.u) +$(locale_DIR)/gen_wc8bit.c: $(DEPH-gen_wc8bit) +$(locale_OUT)/gen_wc8bit : $(locale_DIR)/gen_wc8bit.c + $(hcompile.u) +$(locale_DIR)/gen_wctype.c: $(DEPH-gen_wctype) +$(locale_OUT)/gen_wctype : $(locale_DIR)/gen_wctype.c + $(hcompile.u) + +ifneq ($(V),) +ifeq ($(V),1) +FLAG-locale-verbose := -v +endif +ifeq ($(V),2) +FLAG-locale-verbose := -v -v +endif +endif + +# code needs to be modified to support top_builddir in almost all apps that write directly to a file +# grep fopen *.c +$(locale_OUT)/c8tables.h: $(locale_OUT)/gen_wc8bit $(locale_OUT)/codesets.txt + @$(disp_gen) + $(Q)$< `cat $(word 2,$^)` > $@ + +# Warning! Beware tr_TR toupper/tolower exceptions! +$(locale_OUT)/wctables.h: $(locale_OUT)/gen_wctype + @$(disp_gen) + $(Q)for locale in $(call qstrip,$(UCLIBC_BUILD_MINIMAL_LOCALES)) en_US en_GB; do \ + $< $(FLAG-locale-verbose) $$locale > $@ || \ + $< $(FLAG-locale-verbose) $$locale.UTF-8 > $@ || \ + $< $(FLAG-locale-verbose) $$locale.iso8859-1 > $@ && break; \ + done + +$(locale_OUT)/locale_tables.h: $(locale_OUT)/gen_locale $(locale_OUT)/locales.txt + @$(disp_gen) + $(Q)$< $(FLAG-locale-verbose) -o $@ $(word 2,$^) + +$(locale_OUT)/lt_defines.h: $(locale_OUT)/locale_tables.h $(locale_OUT)/locale_collate.h + @$(disp_gen) + $(Q)grep "^#define" $< > $@ + $(Q)grep "^#define __lc" $(word 2,$^) >> $@ + +$(locale_OUT)/locale_collate.h: $(locale_OUT)/gen_collate $(locale_OUT)/locale_tables.h + @$(disp_gen) + $(Q)grep COL_IDX_ $(word 2,$^) | \ + $(SED) -e "s/^.*COL_IDX_\([^, ]*\).*$$/\1/" | sort | uniq | \ + xargs $< $(locale_DIR)/collation $(FLAG-locale-verbose) -o $@ + +$(locale_OUT)/$(LOCALE_DATA_FILENAME): +ifeq ($(UCLIBC_DOWNLOAD_PREGENERATED_LOCALE_DATA),y) + ( cd $(@D); $(WGET) http://www.uclibc.org/downloads/$(@F) ) +endif + +ifeq ($(UCLIBC_PREGENERATED_LOCALE_DATA),y) + +$(locale_SRC): $(locale_OUT)/$(LOCALE_DATA_FILENAME) + zcat $< | $(TAR) -xv -C $(@D) -f - + touch $@ + # we use the one in locale_DIR + #$(RM) $(locale_OUT)/locale_mmap.h + +# for arch specific versions we have to at least overwrite +# lt_defines.h/locale_data.c/uClibc_locale_data.h + +$(locale_OUT)/uClibc_locale_data.h: $(locale_SRC) + +else + +$(locale_SRC): $(locale_OUT)/gen_ldc $(locale_OUT)/lt_defines.h + @$(disp_gen) + $(Q)$< $@ + +$(locale_OUT)/uClibc_locale_data.h: $(locale_OUT)/lt_defines.h $(locale_OUT)/c8tables.h $(locale_OUT)/wctables.h $(locale_DIR)/locale_mmap.h | $(locale_SRC) + @$(disp_gen) + $(Q)grep -v "define __LC" $< > $@ + $(Q)cat $(wordlist 2,4,$^) >> $@ + +endif + +$(top_builddir)include/bits/uClibc_locale_data.h: $(locale_OUT)/uClibc_locale_data.h | $(top_builddir)include/bits/uClibc_config.h + @$(disp_gen) + $(Q)$(AWK) 'BEGIN{i=1}{if (/WANT_/) i=/endif/;else if (i) print $0}' \ + $< > $@ + +objclean-y += CLEAN_extra/locale + +# lmmtolso.c/gen_mmap.c/tst-*.c not used +CLEAN_extra/locale: + $(do_rm) $(locale_HOBJ) $(locale_SRC) $(addprefix $(locale_OUT)/*., o os txt) \ + $(addprefix $(locale_OUT)/,$(addsuffix .h,uClibc_locale_data lt_defines c8tables wctables locale_tables locale_collate) lmmtolso gen_mmap locale.mmap) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/README b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/README new file mode 100644 index 00000000..244b9253 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/README @@ -0,0 +1,71 @@ +Warning!!! Warning!!! Warning!!! Warning!!! Warning!!! Warning!!! +Warning!!! Warning!!! Warning!!! Warning!!! Warning!!! Warning!!! + +The programs in this directory are strictly cut-and-paste hack jobs to +extract the data I needed from glibc's locale database. I'm ashamed to +even let them into the light of day, and I consider them complete garbage. + +However, they are currently necessary to build the data needed for the +locale support I've implemented, so I'm forced to include them here. + +NOTE: While its possible to use this stuff for native != target arch, +you'll have to either write a converter to account for endianess and +struct padding issues, or run the mmap file generator on your target +arch. But all these programs will be rewritten at some point. + +All that being said, LC_CTYPE support has been added and supports the +ctype.h and wctype.h function. Also, LC_TIME, LC_MONETARY, LC_NUMERIC, +and LC_MESSAGES are supported wrt SUSv3. localeconv() works in both +real and stub locale modes. nl_langinfo() currently only works with +real locales enabled. That will be fixed though. wc->mb unsupported +char replacement and basic translit support is on the way as well. +Finally, some basic 8-bit codeset LC_COLLATE support should be in place +in the next week or two (similar to what was in the previous locale +implementation). + +Also, as one can probably guess, I'm working towards having the locale +data accessed via a shared mmap. That will allow non-mmu platforms +to use this without the current bloat. + +Currently, the output of size for my locale_data.o file is + text data bss dec hex filename + 59072 4 0 59076 e6c4 extra/locale/locale_data.o +which is for the C locale (automatic of course) + all codesets in +charmaps/ and all 268 locales in LOCALES. I estimate that the +translit support for those 8-bit codesets will add another 7-10k. + +One difference of note is that the special case upper/lower mappings +in the turkish locale are currently not implemented. That will be +fixed. + +Manuel + +Warning!!! Warning!!! Warning!!! Warning!!! Warning!!! Warning!!! +Warning!!! Warning!!! Warning!!! Warning!!! Warning!!! Warning!!! + + +1) In the toplevel dir, 'make headers'. + +2) Create a codesets.txt file in this dir listing the codesets you want + to support. The easiest way to do this is to edit the output of + 'find ./charmaps -name "*.pairs" > codesets.txt'. + NOTE: UTF-8 support is always included if you build with wide chars enabled. + NOTE: The files in charmaps/ were created from glibc's charmap files + with the awk script at the end of this file. You can add others + but only single byte codesets are supported. + +3) Create a locales.txt file to select the locales you want to support. + You can copy and edit the LOCALES file for example. Other locales could + added provided you've included the appropriate codesets in step 2. + NOTE: You have to have the approprite locales available for glibc! + +4) Run make here. + +5) Continue building uClibc from the toplevel dir. + + + + +Script used to generate the charmaps/*.pairs files: + +cat $1 | awk 'BEGIN { i = 0 } ; { if ($1 == "CHARMAP") i=1 ; else if ($1 == "END") i=0 ; else if (i==1) { sub("/","0",$2) ; sub("","",$1) ; print "{", $2, ",", $1, "}," } }' diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/ARMSCII-8.pairs b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/ARMSCII-8.pairs new file mode 100644 index 00000000..6a0f4412 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/ARMSCII-8.pairs @@ -0,0 +1,254 @@ +{ 0x00 , 0x0000 }, +{ 0x01 , 0x0001 }, +{ 0x02 , 0x0002 }, +{ 0x03 , 0x0003 }, +{ 0x04 , 0x0004 }, +{ 0x05 , 0x0005 }, +{ 0x06 , 0x0006 }, +{ 0x07 , 0x0007 }, +{ 0x08 , 0x0008 }, +{ 0x09 , 0x0009 }, +{ 0x0a , 0x000A }, +{ 0x0b , 0x000B }, +{ 0x0c , 0x000C }, +{ 0x0d , 0x000D }, +{ 0x0e , 0x000E }, +{ 0x0f , 0x000F }, +{ 0x10 , 0x0010 }, +{ 0x11 , 0x0011 }, +{ 0x12 , 0x0012 }, +{ 0x13 , 0x0013 }, +{ 0x14 , 0x0014 }, +{ 0x15 , 0x0015 }, +{ 0x16 , 0x0016 }, +{ 0x17 , 0x0017 }, +{ 0x18 , 0x0018 }, +{ 0x19 , 0x0019 }, +{ 0x1a , 0x001A }, +{ 0x1b , 0x001B }, +{ 0x1c , 0x001C }, +{ 0x1d , 0x001D }, +{ 0x1e , 0x001E }, +{ 0x1f , 0x001F }, +{ 0x20 , 0x0020 }, +{ 0x21 , 0x0021 }, +{ 0x22 , 0x0022 }, +{ 0x23 , 0x0023 }, +{ 0x24 , 0x0024 }, +{ 0x25 , 0x0025 }, +{ 0x26 , 0x0026 }, +{ 0x27 , 0x0027 }, +{ 0x28 , 0x0028 }, +{ 0x29 , 0x0029 }, +{ 0x2a , 0x002A }, +{ 0x2b , 0x002B }, +{ 0x2c , 0x002C }, +{ 0x2d , 0x002D }, +{ 0x2e , 0x002E }, +{ 0x2f , 0x002F }, +{ 0x30 , 0x0030 }, +{ 0x31 , 0x0031 }, +{ 0x32 , 0x0032 }, +{ 0x33 , 0x0033 }, +{ 0x34 , 0x0034 }, +{ 0x35 , 0x0035 }, +{ 0x36 , 0x0036 }, +{ 0x37 , 0x0037 }, +{ 0x38 , 0x0038 }, +{ 0x39 , 0x0039 }, +{ 0x3a , 0x003A }, +{ 0x3b , 0x003B }, +{ 0x3c , 0x003C }, +{ 0x3d , 0x003D }, +{ 0x3e , 0x003E }, +{ 0x3f , 0x003F }, +{ 0x40 , 0x0040 }, +{ 0x41 , 0x0041 }, +{ 0x42 , 0x0042 }, +{ 0x43 , 0x0043 }, +{ 0x44 , 0x0044 }, +{ 0x45 , 0x0045 }, +{ 0x46 , 0x0046 }, +{ 0x47 , 0x0047 }, +{ 0x48 , 0x0048 }, +{ 0x49 , 0x0049 }, +{ 0x4a , 0x004A }, +{ 0x4b , 0x004B }, +{ 0x4c , 0x004C }, +{ 0x4d , 0x004D }, +{ 0x4e , 0x004E }, +{ 0x4f , 0x004F }, +{ 0x50 , 0x0050 }, +{ 0x51 , 0x0051 }, +{ 0x52 , 0x0052 }, +{ 0x53 , 0x0053 }, +{ 0x54 , 0x0054 }, +{ 0x55 , 0x0055 }, +{ 0x56 , 0x0056 }, +{ 0x57 , 0x0057 }, +{ 0x58 , 0x0058 }, +{ 0x59 , 0x0059 }, +{ 0x5a , 0x005A }, +{ 0x5b , 0x005B }, +{ 0x5c , 0x005C }, +{ 0x5d , 0x005D }, +{ 0x5e , 0x005E }, +{ 0x5f , 0x005F }, +{ 0x60 , 0x0060 }, +{ 0x61 , 0x0061 }, +{ 0x62 , 0x0062 }, +{ 0x63 , 0x0063 }, +{ 0x64 , 0x0064 }, +{ 0x65 , 0x0065 }, +{ 0x66 , 0x0066 }, +{ 0x67 , 0x0067 }, +{ 0x68 , 0x0068 }, +{ 0x69 , 0x0069 }, +{ 0x6a , 0x006A }, +{ 0x6b , 0x006B }, +{ 0x6c , 0x006C }, +{ 0x6d , 0x006D }, +{ 0x6e , 0x006E }, +{ 0x6f , 0x006F }, +{ 0x70 , 0x0070 }, +{ 0x71 , 0x0071 }, +{ 0x72 , 0x0072 }, +{ 0x73 , 0x0073 }, +{ 0x74 , 0x0074 }, +{ 0x75 , 0x0075 }, +{ 0x76 , 0x0076 }, +{ 0x77 , 0x0077 }, +{ 0x78 , 0x0078 }, +{ 0x79 , 0x0079 }, +{ 0x7a , 0x007A }, +{ 0x7b , 0x007B }, +{ 0x7c , 0x007C }, +{ 0x7d , 0x007D }, +{ 0x7e , 0x007E }, +{ 0x7f , 0x007F }, +{ 0x80 , 0x0080 }, +{ 0x81 , 0x0081 }, +{ 0x82 , 0x0082 }, +{ 0x83 , 0x0083 }, +{ 0x84 , 0x0084 }, +{ 0x85 , 0x0085 }, +{ 0x86 , 0x0086 }, +{ 0x87 , 0x0087 }, +{ 0x88 , 0x0088 }, +{ 0x89 , 0x0089 }, +{ 0x8a , 0x008A }, +{ 0x8b , 0x008B }, +{ 0x8c , 0x008C }, +{ 0x8d , 0x008D }, +{ 0x8e , 0x008E }, +{ 0x8f , 0x008F }, +{ 0x90 , 0x0090 }, +{ 0x91 , 0x0091 }, +{ 0x92 , 0x0092 }, +{ 0x93 , 0x0093 }, +{ 0x94 , 0x0094 }, +{ 0x95 , 0x0095 }, +{ 0x96 , 0x0096 }, +{ 0x97 , 0x0097 }, +{ 0x98 , 0x0098 }, +{ 0x99 , 0x0099 }, +{ 0x9a , 0x009A }, +{ 0x9b , 0x009B }, +{ 0x9c , 0x009C }, +{ 0x9d , 0x009D }, +{ 0x9e , 0x009E }, +{ 0x9f , 0x009F }, +{ 0xa0 , 0x00A0 }, +{ 0xa2 , 0x0587 }, +{ 0xa3 , 0x0589 }, +{ 0xa4 , 0x0029 }, +{ 0xa5 , 0x0028 }, +{ 0xa6 , 0x00BB }, +{ 0xa7 , 0x00AB }, +{ 0xa8 , 0x2014 }, +{ 0xa9 , 0x002E }, +{ 0xaa , 0x055D }, +{ 0xab , 0x002C }, +{ 0xac , 0x002D }, +{ 0xad , 0x058A }, +{ 0xae , 0x2026 }, +{ 0xaf , 0x055C }, +{ 0xb0 , 0x055B }, +{ 0xb1 , 0x055E }, +{ 0xb2 , 0x0531 }, +{ 0xb3 , 0x0561 }, +{ 0xb4 , 0x0532 }, +{ 0xb5 , 0x0562 }, +{ 0xb6 , 0x0533 }, +{ 0xb7 , 0x0563 }, +{ 0xb8 , 0x0534 }, +{ 0xb9 , 0x0564 }, +{ 0xba , 0x0535 }, +{ 0xbb , 0x0565 }, +{ 0xbc , 0x0536 }, +{ 0xbd , 0x0566 }, +{ 0xbe , 0x0537 }, +{ 0xbf , 0x0567 }, +{ 0xc0 , 0x0538 }, +{ 0xc1 , 0x0568 }, +{ 0xc2 , 0x0539 }, +{ 0xc3 , 0x0569 }, +{ 0xc4 , 0x053A }, +{ 0xc5 , 0x056A }, +{ 0xc6 , 0x053B }, +{ 0xc7 , 0x056B }, +{ 0xc8 , 0x053C }, +{ 0xc9 , 0x056C }, +{ 0xca , 0x053D }, +{ 0xcb , 0x056D }, +{ 0xcc , 0x053E }, +{ 0xcd , 0x056E }, +{ 0xce , 0x053F }, +{ 0xcf , 0x056F }, +{ 0xd0 , 0x0540 }, +{ 0xd1 , 0x0570 }, +{ 0xd2 , 0x0541 }, +{ 0xd3 , 0x0571 }, +{ 0xd4 , 0x0542 }, +{ 0xd5 , 0x0572 }, +{ 0xd6 , 0x0543 }, +{ 0xd7 , 0x0573 }, +{ 0xd8 , 0x0544 }, +{ 0xd9 , 0x0574 }, +{ 0xda , 0x0545 }, +{ 0xdb , 0x0575 }, +{ 0xdc , 0x0546 }, +{ 0xdd , 0x0576 }, +{ 0xde , 0x0547 }, +{ 0xdf , 0x0577 }, +{ 0xe0 , 0x0548 }, +{ 0xe1 , 0x0578 }, +{ 0xe2 , 0x0549 }, +{ 0xe3 , 0x0579 }, +{ 0xe4 , 0x054A }, +{ 0xe5 , 0x057A }, +{ 0xe6 , 0x054B }, +{ 0xe7 , 0x057B }, +{ 0xe8 , 0x054C }, +{ 0xe9 , 0x057C }, +{ 0xea , 0x054D }, +{ 0xeb , 0x057D }, +{ 0xec , 0x054E }, +{ 0xed , 0x057E }, +{ 0xee , 0x054F }, +{ 0xef , 0x057F }, +{ 0xf0 , 0x0550 }, +{ 0xf1 , 0x0580 }, +{ 0xf2 , 0x0551 }, +{ 0xf3 , 0x0581 }, +{ 0xf4 , 0x0552 }, +{ 0xf5 , 0x0582 }, +{ 0xf6 , 0x0553 }, +{ 0xf7 , 0x0583 }, +{ 0xf8 , 0x0554 }, +{ 0xf9 , 0x0584 }, +{ 0xfa , 0x0555 }, +{ 0xfb , 0x0585 }, +{ 0xfc , 0x0556 }, +{ 0xfd , 0x0586 }, +{ 0xfe , 0x055A }, diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/ASCII.pairs b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/ASCII.pairs new file mode 100644 index 00000000..038314d1 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/ASCII.pairs @@ -0,0 +1,128 @@ +{ 0x00 , 0x0000 }, +{ 0x01 , 0x0001 }, +{ 0x02 , 0x0002 }, +{ 0x03 , 0x0003 }, +{ 0x04 , 0x0004 }, +{ 0x05 , 0x0005 }, +{ 0x06 , 0x0006 }, +{ 0x07 , 0x0007 }, +{ 0x08 , 0x0008 }, +{ 0x09 , 0x0009 }, +{ 0x0a , 0x000A }, +{ 0x0b , 0x000B }, +{ 0x0c , 0x000C }, +{ 0x0d , 0x000D }, +{ 0x0e , 0x000E }, +{ 0x0f , 0x000F }, +{ 0x10 , 0x0010 }, +{ 0x11 , 0x0011 }, +{ 0x12 , 0x0012 }, +{ 0x13 , 0x0013 }, +{ 0x14 , 0x0014 }, +{ 0x15 , 0x0015 }, +{ 0x16 , 0x0016 }, +{ 0x17 , 0x0017 }, +{ 0x18 , 0x0018 }, +{ 0x19 , 0x0019 }, +{ 0x1a , 0x001A }, +{ 0x1b , 0x001B }, +{ 0x1c , 0x001C }, +{ 0x1d , 0x001D }, +{ 0x1e , 0x001E }, +{ 0x1f , 0x001F }, +{ 0x20 , 0x0020 }, +{ 0x21 , 0x0021 }, +{ 0x22 , 0x0022 }, +{ 0x23 , 0x0023 }, +{ 0x24 , 0x0024 }, +{ 0x25 , 0x0025 }, +{ 0x26 , 0x0026 }, +{ 0x27 , 0x0027 }, +{ 0x28 , 0x0028 }, +{ 0x29 , 0x0029 }, +{ 0x2a , 0x002A }, +{ 0x2b , 0x002B }, +{ 0x2c , 0x002C }, +{ 0x2d , 0x002D }, +{ 0x2e , 0x002E }, +{ 0x2f , 0x002F }, +{ 0x30 , 0x0030 }, +{ 0x31 , 0x0031 }, +{ 0x32 , 0x0032 }, +{ 0x33 , 0x0033 }, +{ 0x34 , 0x0034 }, +{ 0x35 , 0x0035 }, +{ 0x36 , 0x0036 }, +{ 0x37 , 0x0037 }, +{ 0x38 , 0x0038 }, +{ 0x39 , 0x0039 }, +{ 0x3a , 0x003A }, +{ 0x3b , 0x003B }, +{ 0x3c , 0x003C }, +{ 0x3d , 0x003D }, +{ 0x3e , 0x003E }, +{ 0x3f , 0x003F }, +{ 0x40 , 0x0040 }, +{ 0x41 , 0x0041 }, +{ 0x42 , 0x0042 }, +{ 0x43 , 0x0043 }, +{ 0x44 , 0x0044 }, +{ 0x45 , 0x0045 }, +{ 0x46 , 0x0046 }, +{ 0x47 , 0x0047 }, +{ 0x48 , 0x0048 }, +{ 0x49 , 0x0049 }, +{ 0x4a , 0x004A }, +{ 0x4b , 0x004B }, +{ 0x4c , 0x004C }, +{ 0x4d , 0x004D }, +{ 0x4e , 0x004E }, +{ 0x4f , 0x004F }, +{ 0x50 , 0x0050 }, +{ 0x51 , 0x0051 }, +{ 0x52 , 0x0052 }, +{ 0x53 , 0x0053 }, +{ 0x54 , 0x0054 }, +{ 0x55 , 0x0055 }, +{ 0x56 , 0x0056 }, +{ 0x57 , 0x0057 }, +{ 0x58 , 0x0058 }, +{ 0x59 , 0x0059 }, +{ 0x5a , 0x005A }, +{ 0x5b , 0x005B }, +{ 0x5c , 0x005C }, +{ 0x5d , 0x005D }, +{ 0x5e , 0x005E }, +{ 0x5f , 0x005F }, +{ 0x60 , 0x0060 }, +{ 0x61 , 0x0061 }, +{ 0x62 , 0x0062 }, +{ 0x63 , 0x0063 }, +{ 0x64 , 0x0064 }, +{ 0x65 , 0x0065 }, +{ 0x66 , 0x0066 }, +{ 0x67 , 0x0067 }, +{ 0x68 , 0x0068 }, +{ 0x69 , 0x0069 }, +{ 0x6a , 0x006A }, +{ 0x6b , 0x006B }, +{ 0x6c , 0x006C }, +{ 0x6d , 0x006D }, +{ 0x6e , 0x006E }, +{ 0x6f , 0x006F }, +{ 0x70 , 0x0070 }, +{ 0x71 , 0x0071 }, +{ 0x72 , 0x0072 }, +{ 0x73 , 0x0073 }, +{ 0x74 , 0x0074 }, +{ 0x75 , 0x0075 }, +{ 0x76 , 0x0076 }, +{ 0x77 , 0x0077 }, +{ 0x78 , 0x0078 }, +{ 0x79 , 0x0079 }, +{ 0x7a , 0x007A }, +{ 0x7b , 0x007B }, +{ 0x7c , 0x007C }, +{ 0x7d , 0x007D }, +{ 0x7e , 0x007E }, +{ 0x7f , 0x007F }, diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/CP1251.pairs b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/CP1251.pairs new file mode 100644 index 00000000..a5a80d61 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/CP1251.pairs @@ -0,0 +1,255 @@ +{ 0x00 , 0x0000 }, +{ 0x01 , 0x0001 }, +{ 0x02 , 0x0002 }, +{ 0x03 , 0x0003 }, +{ 0x04 , 0x0004 }, +{ 0x05 , 0x0005 }, +{ 0x06 , 0x0006 }, +{ 0x07 , 0x0007 }, +{ 0x08 , 0x0008 }, +{ 0x09 , 0x0009 }, +{ 0x0a , 0x000A }, +{ 0x0b , 0x000B }, +{ 0x0c , 0x000C }, +{ 0x0d , 0x000D }, +{ 0x0e , 0x000E }, +{ 0x0f , 0x000F }, +{ 0x10 , 0x0010 }, +{ 0x11 , 0x0011 }, +{ 0x12 , 0x0012 }, +{ 0x13 , 0x0013 }, +{ 0x14 , 0x0014 }, +{ 0x15 , 0x0015 }, +{ 0x16 , 0x0016 }, +{ 0x17 , 0x0017 }, +{ 0x18 , 0x0018 }, +{ 0x19 , 0x0019 }, +{ 0x1a , 0x001A }, +{ 0x1b , 0x001B }, +{ 0x1c , 0x001C }, +{ 0x1d , 0x001D }, +{ 0x1e , 0x001E }, +{ 0x1f , 0x001F }, +{ 0x20 , 0x0020 }, +{ 0x21 , 0x0021 }, +{ 0x22 , 0x0022 }, +{ 0x23 , 0x0023 }, +{ 0x24 , 0x0024 }, +{ 0x25 , 0x0025 }, +{ 0x26 , 0x0026 }, +{ 0x27 , 0x0027 }, +{ 0x28 , 0x0028 }, +{ 0x29 , 0x0029 }, +{ 0x2a , 0x002A }, +{ 0x2b , 0x002B }, +{ 0x2c , 0x002C }, +{ 0x2d , 0x002D }, +{ 0x2e , 0x002E }, +{ 0x2f , 0x002F }, +{ 0x30 , 0x0030 }, +{ 0x31 , 0x0031 }, +{ 0x32 , 0x0032 }, +{ 0x33 , 0x0033 }, +{ 0x34 , 0x0034 }, +{ 0x35 , 0x0035 }, +{ 0x36 , 0x0036 }, +{ 0x37 , 0x0037 }, +{ 0x38 , 0x0038 }, +{ 0x39 , 0x0039 }, +{ 0x3a , 0x003A }, +{ 0x3b , 0x003B }, +{ 0x3c , 0x003C }, +{ 0x3d , 0x003D }, +{ 0x3e , 0x003E }, +{ 0x3f , 0x003F }, +{ 0x40 , 0x0040 }, +{ 0x41 , 0x0041 }, +{ 0x42 , 0x0042 }, +{ 0x43 , 0x0043 }, +{ 0x44 , 0x0044 }, +{ 0x45 , 0x0045 }, +{ 0x46 , 0x0046 }, +{ 0x47 , 0x0047 }, +{ 0x48 , 0x0048 }, +{ 0x49 , 0x0049 }, +{ 0x4a , 0x004A }, +{ 0x4b , 0x004B }, +{ 0x4c , 0x004C }, +{ 0x4d , 0x004D }, +{ 0x4e , 0x004E }, +{ 0x4f , 0x004F }, +{ 0x50 , 0x0050 }, +{ 0x51 , 0x0051 }, +{ 0x52 , 0x0052 }, +{ 0x53 , 0x0053 }, +{ 0x54 , 0x0054 }, +{ 0x55 , 0x0055 }, +{ 0x56 , 0x0056 }, +{ 0x57 , 0x0057 }, +{ 0x58 , 0x0058 }, +{ 0x59 , 0x0059 }, +{ 0x5a , 0x005A }, +{ 0x5b , 0x005B }, +{ 0x5c , 0x005C }, +{ 0x5d , 0x005D }, +{ 0x5e , 0x005E }, +{ 0x5f , 0x005F }, +{ 0x60 , 0x0060 }, +{ 0x61 , 0x0061 }, +{ 0x62 , 0x0062 }, +{ 0x63 , 0x0063 }, +{ 0x64 , 0x0064 }, +{ 0x65 , 0x0065 }, +{ 0x66 , 0x0066 }, +{ 0x67 , 0x0067 }, +{ 0x68 , 0x0068 }, +{ 0x69 , 0x0069 }, +{ 0x6a , 0x006A }, +{ 0x6b , 0x006B }, +{ 0x6c , 0x006C }, +{ 0x6d , 0x006D }, +{ 0x6e , 0x006E }, +{ 0x6f , 0x006F }, +{ 0x70 , 0x0070 }, +{ 0x71 , 0x0071 }, +{ 0x72 , 0x0072 }, +{ 0x73 , 0x0073 }, +{ 0x74 , 0x0074 }, +{ 0x75 , 0x0075 }, +{ 0x76 , 0x0076 }, +{ 0x77 , 0x0077 }, +{ 0x78 , 0x0078 }, +{ 0x79 , 0x0079 }, +{ 0x7a , 0x007A }, +{ 0x7b , 0x007B }, +{ 0x7c , 0x007C }, +{ 0x7d , 0x007D }, +{ 0x7e , 0x007E }, +{ 0x7f , 0x007F }, +{ 0x80 , 0x0402 }, +{ 0x81 , 0x0403 }, +{ 0x82 , 0x201A }, +{ 0x83 , 0x0453 }, +{ 0x84 , 0x201E }, +{ 0x85 , 0x2026 }, +{ 0x86 , 0x2020 }, +{ 0x87 , 0x2021 }, +{ 0x88 , 0x20AC }, +{ 0x89 , 0x2030 }, +{ 0x8a , 0x0409 }, +{ 0x8b , 0x2039 }, +{ 0x8c , 0x040A }, +{ 0x8d , 0x040C }, +{ 0x8e , 0x040B }, +{ 0x8f , 0x040F }, +{ 0x90 , 0x0452 }, +{ 0x91 , 0x2018 }, +{ 0x92 , 0x2019 }, +{ 0x93 , 0x201C }, +{ 0x94 , 0x201D }, +{ 0x95 , 0x2022 }, +{ 0x96 , 0x2013 }, +{ 0x97 , 0x2014 }, +{ 0x99 , 0x2122 }, +{ 0x9a , 0x0459 }, +{ 0x9b , 0x203A }, +{ 0x9c , 0x045A }, +{ 0x9d , 0x045C }, +{ 0x9e , 0x045B }, +{ 0x9f , 0x045F }, +{ 0xa0 , 0x00A0 }, +{ 0xa1 , 0x040E }, +{ 0xa2 , 0x045E }, +{ 0xa3 , 0x0408 }, +{ 0xa4 , 0x00A4 }, +{ 0xa5 , 0x0490 }, +{ 0xa6 , 0x00A6 }, +{ 0xa7 , 0x00A7 }, +{ 0xa8 , 0x0401 }, +{ 0xa9 , 0x00A9 }, +{ 0xaa , 0x0404 }, +{ 0xab , 0x00AB }, +{ 0xac , 0x00AC }, +{ 0xad , 0x00AD }, +{ 0xae , 0x00AE }, +{ 0xaf , 0x0407 }, +{ 0xb0 , 0x00B0 }, +{ 0xb1 , 0x00B1 }, +{ 0xb2 , 0x0406 }, +{ 0xb3 , 0x0456 }, +{ 0xb4 , 0x0491 }, +{ 0xb5 , 0x00B5 }, +{ 0xb6 , 0x00B6 }, +{ 0xb7 , 0x00B7 }, +{ 0xb8 , 0x0451 }, +{ 0xb9 , 0x2116 }, +{ 0xba , 0x0454 }, +{ 0xbb , 0x00BB }, +{ 0xbc , 0x0458 }, +{ 0xbd , 0x0405 }, +{ 0xbe , 0x0455 }, +{ 0xbf , 0x0457 }, +{ 0xc0 , 0x0410 }, +{ 0xc1 , 0x0411 }, +{ 0xc2 , 0x0412 }, +{ 0xc3 , 0x0413 }, +{ 0xc4 , 0x0414 }, +{ 0xc5 , 0x0415 }, +{ 0xc6 , 0x0416 }, +{ 0xc7 , 0x0417 }, +{ 0xc8 , 0x0418 }, +{ 0xc9 , 0x0419 }, +{ 0xca , 0x041A }, +{ 0xcb , 0x041B }, +{ 0xcc , 0x041C }, +{ 0xcd , 0x041D }, +{ 0xce , 0x041E }, +{ 0xcf , 0x041F }, +{ 0xd0 , 0x0420 }, +{ 0xd1 , 0x0421 }, +{ 0xd2 , 0x0422 }, +{ 0xd3 , 0x0423 }, +{ 0xd4 , 0x0424 }, +{ 0xd5 , 0x0425 }, +{ 0xd6 , 0x0426 }, +{ 0xd7 , 0x0427 }, +{ 0xd8 , 0x0428 }, +{ 0xd9 , 0x0429 }, +{ 0xda , 0x042A }, +{ 0xdb , 0x042B }, +{ 0xdc , 0x042C }, +{ 0xdd , 0x042D }, +{ 0xde , 0x042E }, +{ 0xdf , 0x042F }, +{ 0xe0 , 0x0430 }, +{ 0xe1 , 0x0431 }, +{ 0xe2 , 0x0432 }, +{ 0xe3 , 0x0433 }, +{ 0xe4 , 0x0434 }, +{ 0xe5 , 0x0435 }, +{ 0xe6 , 0x0436 }, +{ 0xe7 , 0x0437 }, +{ 0xe8 , 0x0438 }, +{ 0xe9 , 0x0439 }, +{ 0xea , 0x043A }, +{ 0xeb , 0x043B }, +{ 0xec , 0x043C }, +{ 0xed , 0x043D }, +{ 0xee , 0x043E }, +{ 0xef , 0x043F }, +{ 0xf0 , 0x0440 }, +{ 0xf1 , 0x0441 }, +{ 0xf2 , 0x0442 }, +{ 0xf3 , 0x0443 }, +{ 0xf4 , 0x0444 }, +{ 0xf5 , 0x0445 }, +{ 0xf6 , 0x0446 }, +{ 0xf7 , 0x0447 }, +{ 0xf8 , 0x0448 }, +{ 0xf9 , 0x0449 }, +{ 0xfa , 0x044A }, +{ 0xfb , 0x044B }, +{ 0xfc , 0x044C }, +{ 0xfd , 0x044D }, +{ 0xfe , 0x044E }, +{ 0xff , 0x044F }, diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/CP1255.pairs b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/CP1255.pairs new file mode 100644 index 00000000..123bb5aa --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/CP1255.pairs @@ -0,0 +1,233 @@ +{ 0x00 , 0x0000 }, +{ 0x01 , 0x0001 }, +{ 0x02 , 0x0002 }, +{ 0x03 , 0x0003 }, +{ 0x04 , 0x0004 }, +{ 0x05 , 0x0005 }, +{ 0x06 , 0x0006 }, +{ 0x07 , 0x0007 }, +{ 0x08 , 0x0008 }, +{ 0x09 , 0x0009 }, +{ 0x0a , 0x000A }, +{ 0x0b , 0x000B }, +{ 0x0c , 0x000C }, +{ 0x0d , 0x000D }, +{ 0x0e , 0x000E }, +{ 0x0f , 0x000F }, +{ 0x10 , 0x0010 }, +{ 0x11 , 0x0011 }, +{ 0x12 , 0x0012 }, +{ 0x13 , 0x0013 }, +{ 0x14 , 0x0014 }, +{ 0x15 , 0x0015 }, +{ 0x16 , 0x0016 }, +{ 0x17 , 0x0017 }, +{ 0x18 , 0x0018 }, +{ 0x19 , 0x0019 }, +{ 0x1a , 0x001A }, +{ 0x1b , 0x001B }, +{ 0x1c , 0x001C }, +{ 0x1d , 0x001D }, +{ 0x1e , 0x001E }, +{ 0x1f , 0x001F }, +{ 0x20 , 0x0020 }, +{ 0x21 , 0x0021 }, +{ 0x22 , 0x0022 }, +{ 0x23 , 0x0023 }, +{ 0x24 , 0x0024 }, +{ 0x25 , 0x0025 }, +{ 0x26 , 0x0026 }, +{ 0x27 , 0x0027 }, +{ 0x28 , 0x0028 }, +{ 0x29 , 0x0029 }, +{ 0x2a , 0x002A }, +{ 0x2b , 0x002B }, +{ 0x2c , 0x002C }, +{ 0x2d , 0x002D }, +{ 0x2e , 0x002E }, +{ 0x2f , 0x002F }, +{ 0x30 , 0x0030 }, +{ 0x31 , 0x0031 }, +{ 0x32 , 0x0032 }, +{ 0x33 , 0x0033 }, +{ 0x34 , 0x0034 }, +{ 0x35 , 0x0035 }, +{ 0x36 , 0x0036 }, +{ 0x37 , 0x0037 }, +{ 0x38 , 0x0038 }, +{ 0x39 , 0x0039 }, +{ 0x3a , 0x003A }, +{ 0x3b , 0x003B }, +{ 0x3c , 0x003C }, +{ 0x3d , 0x003D }, +{ 0x3e , 0x003E }, +{ 0x3f , 0x003F }, +{ 0x40 , 0x0040 }, +{ 0x41 , 0x0041 }, +{ 0x42 , 0x0042 }, +{ 0x43 , 0x0043 }, +{ 0x44 , 0x0044 }, +{ 0x45 , 0x0045 }, +{ 0x46 , 0x0046 }, +{ 0x47 , 0x0047 }, +{ 0x48 , 0x0048 }, +{ 0x49 , 0x0049 }, +{ 0x4a , 0x004A }, +{ 0x4b , 0x004B }, +{ 0x4c , 0x004C }, +{ 0x4d , 0x004D }, +{ 0x4e , 0x004E }, +{ 0x4f , 0x004F }, +{ 0x50 , 0x0050 }, +{ 0x51 , 0x0051 }, +{ 0x52 , 0x0052 }, +{ 0x53 , 0x0053 }, +{ 0x54 , 0x0054 }, +{ 0x55 , 0x0055 }, +{ 0x56 , 0x0056 }, +{ 0x57 , 0x0057 }, +{ 0x58 , 0x0058 }, +{ 0x59 , 0x0059 }, +{ 0x5a , 0x005A }, +{ 0x5b , 0x005B }, +{ 0x5c , 0x005C }, +{ 0x5d , 0x005D }, +{ 0x5e , 0x005E }, +{ 0x5f , 0x005F }, +{ 0x60 , 0x0060 }, +{ 0x61 , 0x0061 }, +{ 0x62 , 0x0062 }, +{ 0x63 , 0x0063 }, +{ 0x64 , 0x0064 }, +{ 0x65 , 0x0065 }, +{ 0x66 , 0x0066 }, +{ 0x67 , 0x0067 }, +{ 0x68 , 0x0068 }, +{ 0x69 , 0x0069 }, +{ 0x6a , 0x006A }, +{ 0x6b , 0x006B }, +{ 0x6c , 0x006C }, +{ 0x6d , 0x006D }, +{ 0x6e , 0x006E }, +{ 0x6f , 0x006F }, +{ 0x70 , 0x0070 }, +{ 0x71 , 0x0071 }, +{ 0x72 , 0x0072 }, +{ 0x73 , 0x0073 }, +{ 0x74 , 0x0074 }, +{ 0x75 , 0x0075 }, +{ 0x76 , 0x0076 }, +{ 0x77 , 0x0077 }, +{ 0x78 , 0x0078 }, +{ 0x79 , 0x0079 }, +{ 0x7a , 0x007A }, +{ 0x7b , 0x007B }, +{ 0x7c , 0x007C }, +{ 0x7d , 0x007D }, +{ 0x7e , 0x007E }, +{ 0x7f , 0x007F }, +{ 0x80 , 0x20AC }, +{ 0x82 , 0x201A }, +{ 0x83 , 0x0192 }, +{ 0x84 , 0x201E }, +{ 0x85 , 0x2026 }, +{ 0x86 , 0x2020 }, +{ 0x87 , 0x2021 }, +{ 0x88 , 0x02C6 }, +{ 0x89 , 0x2030 }, +{ 0x8b , 0x2039 }, +{ 0x91 , 0x2018 }, +{ 0x92 , 0x2019 }, +{ 0x93 , 0x201C }, +{ 0x94 , 0x201D }, +{ 0x95 , 0x2022 }, +{ 0x96 , 0x2013 }, +{ 0x97 , 0x2014 }, +{ 0x98 , 0x02DC }, +{ 0x99 , 0x2122 }, +{ 0x9b , 0x203A }, +{ 0xa0 , 0x00A0 }, +{ 0xa1 , 0x00A1 }, +{ 0xa2 , 0x00A2 }, +{ 0xa3 , 0x00A3 }, +{ 0xa4 , 0x20AA }, +{ 0xa5 , 0x00A5 }, +{ 0xa6 , 0x00A6 }, +{ 0xa7 , 0x00A7 }, +{ 0xa8 , 0x00A8 }, +{ 0xa9 , 0x00A9 }, +{ 0xaa , 0x00D7 }, +{ 0xab , 0x00AB }, +{ 0xac , 0x00AC }, +{ 0xad , 0x00AD }, +{ 0xae , 0x00AE }, +{ 0xaf , 0x00AF }, +{ 0xb0 , 0x00B0 }, +{ 0xb1 , 0x00B1 }, +{ 0xb2 , 0x00B2 }, +{ 0xb3 , 0x00B3 }, +{ 0xb4 , 0x00B4 }, +{ 0xb5 , 0x00B5 }, +{ 0xb6 , 0x00B6 }, +{ 0xb7 , 0x00B7 }, +{ 0xb8 , 0x00B8 }, +{ 0xb9 , 0x00B9 }, +{ 0xba , 0x00F7 }, +{ 0xbb , 0x00BB }, +{ 0xbc , 0x00BC }, +{ 0xbd , 0x00BD }, +{ 0xbe , 0x00BE }, +{ 0xbf , 0x00BF }, +{ 0xc0 , 0x05B0 }, +{ 0xc1 , 0x05B1 }, +{ 0xc2 , 0x05B2 }, +{ 0xc3 , 0x05B3 }, +{ 0xc4 , 0x05B4 }, +{ 0xc5 , 0x05B5 }, +{ 0xc6 , 0x05B6 }, +{ 0xc7 , 0x05B7 }, +{ 0xc8 , 0x05B8 }, +{ 0xc9 , 0x05B9 }, +{ 0xcb , 0x05BB }, +{ 0xcc , 0x05BC }, +{ 0xcd , 0x05BD }, +{ 0xce , 0x05BE }, +{ 0xcf , 0x05BF }, +{ 0xd0 , 0x05C0 }, +{ 0xd1 , 0x05C1 }, +{ 0xd2 , 0x05C2 }, +{ 0xd3 , 0x05C3 }, +{ 0xd4 , 0x05F0 }, +{ 0xd5 , 0x05F1 }, +{ 0xd6 , 0x05F2 }, +{ 0xd7 , 0x05F3 }, +{ 0xd8 , 0x05F4 }, +{ 0xe0 , 0x05D0 }, +{ 0xe1 , 0x05D1 }, +{ 0xe2 , 0x05D2 }, +{ 0xe3 , 0x05D3 }, +{ 0xe4 , 0x05D4 }, +{ 0xe5 , 0x05D5 }, +{ 0xe6 , 0x05D6 }, +{ 0xe7 , 0x05D7 }, +{ 0xe8 , 0x05D8 }, +{ 0xe9 , 0x05D9 }, +{ 0xea , 0x05DA }, +{ 0xeb , 0x05DB }, +{ 0xec , 0x05DC }, +{ 0xed , 0x05DD }, +{ 0xee , 0x05DE }, +{ 0xef , 0x05DF }, +{ 0xf0 , 0x05E0 }, +{ 0xf1 , 0x05E1 }, +{ 0xf2 , 0x05E2 }, +{ 0xf3 , 0x05E3 }, +{ 0xf4 , 0x05E4 }, +{ 0xf5 , 0x05E5 }, +{ 0xf6 , 0x05E6 }, +{ 0xf7 , 0x05E7 }, +{ 0xf8 , 0x05E8 }, +{ 0xf9 , 0x05E9 }, +{ 0xfa , 0x05EA }, +{ 0xfd , 0x200E }, +{ 0xfe , 0x200F }, diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/GEORGIAN-PS.pairs b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/GEORGIAN-PS.pairs new file mode 100644 index 00000000..815b2e66 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/GEORGIAN-PS.pairs @@ -0,0 +1,256 @@ +{ 0x00 , 0x0000 }, +{ 0x01 , 0x0001 }, +{ 0x02 , 0x0002 }, +{ 0x03 , 0x0003 }, +{ 0x04 , 0x0004 }, +{ 0x05 , 0x0005 }, +{ 0x06 , 0x0006 }, +{ 0x07 , 0x0007 }, +{ 0x08 , 0x0008 }, +{ 0x09 , 0x0009 }, +{ 0x0a , 0x000A }, +{ 0x0b , 0x000B }, +{ 0x0c , 0x000C }, +{ 0x0d , 0x000D }, +{ 0x0e , 0x000E }, +{ 0x0f , 0x000F }, +{ 0x10 , 0x0010 }, +{ 0x11 , 0x0011 }, +{ 0x12 , 0x0012 }, +{ 0x13 , 0x0013 }, +{ 0x14 , 0x0014 }, +{ 0x15 , 0x0015 }, +{ 0x16 , 0x0016 }, +{ 0x17 , 0x0017 }, +{ 0x18 , 0x0018 }, +{ 0x19 , 0x0019 }, +{ 0x1a , 0x001A }, +{ 0x1b , 0x001B }, +{ 0x1c , 0x001C }, +{ 0x1d , 0x001D }, +{ 0x1e , 0x001E }, +{ 0x1f , 0x001F }, +{ 0x20 , 0x0020 }, +{ 0x21 , 0x0021 }, +{ 0x22 , 0x0022 }, +{ 0x23 , 0x0023 }, +{ 0x24 , 0x0024 }, +{ 0x25 , 0x0025 }, +{ 0x26 , 0x0026 }, +{ 0x27 , 0x0027 }, +{ 0x28 , 0x0028 }, +{ 0x29 , 0x0029 }, +{ 0x2a , 0x002A }, +{ 0x2b , 0x002B }, +{ 0x2c , 0x002C }, +{ 0x2d , 0x002D }, +{ 0x2e , 0x002E }, +{ 0x2f , 0x002F }, +{ 0x30 , 0x0030 }, +{ 0x31 , 0x0031 }, +{ 0x32 , 0x0032 }, +{ 0x33 , 0x0033 }, +{ 0x34 , 0x0034 }, +{ 0x35 , 0x0035 }, +{ 0x36 , 0x0036 }, +{ 0x37 , 0x0037 }, +{ 0x38 , 0x0038 }, +{ 0x39 , 0x0039 }, +{ 0x3a , 0x003A }, +{ 0x3b , 0x003B }, +{ 0x3c , 0x003C }, +{ 0x3d , 0x003D }, +{ 0x3e , 0x003E }, +{ 0x3f , 0x003F }, +{ 0x40 , 0x0040 }, +{ 0x41 , 0x0041 }, +{ 0x42 , 0x0042 }, +{ 0x43 , 0x0043 }, +{ 0x44 , 0x0044 }, +{ 0x45 , 0x0045 }, +{ 0x46 , 0x0046 }, +{ 0x47 , 0x0047 }, +{ 0x48 , 0x0048 }, +{ 0x49 , 0x0049 }, +{ 0x4a , 0x004A }, +{ 0x4b , 0x004B }, +{ 0x4c , 0x004C }, +{ 0x4d , 0x004D }, +{ 0x4e , 0x004E }, +{ 0x4f , 0x004F }, +{ 0x50 , 0x0050 }, +{ 0x51 , 0x0051 }, +{ 0x52 , 0x0052 }, +{ 0x53 , 0x0053 }, +{ 0x54 , 0x0054 }, +{ 0x55 , 0x0055 }, +{ 0x56 , 0x0056 }, +{ 0x57 , 0x0057 }, +{ 0x58 , 0x0058 }, +{ 0x59 , 0x0059 }, +{ 0x5a , 0x005A }, +{ 0x5b , 0x005B }, +{ 0x5c , 0x005C }, +{ 0x5d , 0x005D }, +{ 0x5e , 0x005E }, +{ 0x5f , 0x005F }, +{ 0x60 , 0x0060 }, +{ 0x61 , 0x0061 }, +{ 0x62 , 0x0062 }, +{ 0x63 , 0x0063 }, +{ 0x64 , 0x0064 }, +{ 0x65 , 0x0065 }, +{ 0x66 , 0x0066 }, +{ 0x67 , 0x0067 }, +{ 0x68 , 0x0068 }, +{ 0x69 , 0x0069 }, +{ 0x6a , 0x006A }, +{ 0x6b , 0x006B }, +{ 0x6c , 0x006C }, +{ 0x6d , 0x006D }, +{ 0x6e , 0x006E }, +{ 0x6f , 0x006F }, +{ 0x70 , 0x0070 }, +{ 0x71 , 0x0071 }, +{ 0x72 , 0x0072 }, +{ 0x73 , 0x0073 }, +{ 0x74 , 0x0074 }, +{ 0x75 , 0x0075 }, +{ 0x76 , 0x0076 }, +{ 0x77 , 0x0077 }, +{ 0x78 , 0x0078 }, +{ 0x79 , 0x0079 }, +{ 0x7a , 0x007A }, +{ 0x7b , 0x007B }, +{ 0x7c , 0x007C }, +{ 0x7d , 0x007D }, +{ 0x7e , 0x007E }, +{ 0x7f , 0x007F }, +{ 0x80 , 0x0080 }, +{ 0x81 , 0x0081 }, +{ 0x82 , 0x201A }, +{ 0x83 , 0x0192 }, +{ 0x84 , 0x201E }, +{ 0x85 , 0x2026 }, +{ 0x86 , 0x2020 }, +{ 0x87 , 0x2021 }, +{ 0x88 , 0x02C6 }, +{ 0x89 , 0x2030 }, +{ 0x8a , 0x0160 }, +{ 0x8b , 0x2039 }, +{ 0x8c , 0x0152 }, +{ 0x8d , 0x008D }, +{ 0x8e , 0x008E }, +{ 0x8f , 0x008F }, +{ 0x90 , 0x0090 }, +{ 0x91 , 0x2018 }, +{ 0x92 , 0x2019 }, +{ 0x93 , 0x201C }, +{ 0x94 , 0x201D }, +{ 0x95 , 0x2022 }, +{ 0x96 , 0x2013 }, +{ 0x97 , 0x2014 }, +{ 0x98 , 0x02DC }, +{ 0x99 , 0x2122 }, +{ 0x9a , 0x0161 }, +{ 0x9b , 0x203A }, +{ 0x9c , 0x0153 }, +{ 0x9d , 0x009D }, +{ 0x9e , 0x009E }, +{ 0x9f , 0x0178 }, +{ 0xa0 , 0x00A0 }, +{ 0xa1 , 0x00A1 }, +{ 0xa2 , 0x00A2 }, +{ 0xa3 , 0x00A3 }, +{ 0xa4 , 0x00A4 }, +{ 0xa5 , 0x00A5 }, +{ 0xa6 , 0x00A6 }, +{ 0xa7 , 0x00A7 }, +{ 0xa8 , 0x00A8 }, +{ 0xa9 , 0x00A9 }, +{ 0xaa , 0x00AA }, +{ 0xab , 0x00AB }, +{ 0xac , 0x00AC }, +{ 0xad , 0x00AD }, +{ 0xae , 0x00AE }, +{ 0xaf , 0x00AF }, +{ 0xb0 , 0x00B0 }, +{ 0xb1 , 0x00B1 }, +{ 0xb2 , 0x00B2 }, +{ 0xb3 , 0x00B3 }, +{ 0xb4 , 0x00B4 }, +{ 0xb5 , 0x00B5 }, +{ 0xb6 , 0x00B6 }, +{ 0xb7 , 0x00B7 }, +{ 0xb8 , 0x00B8 }, +{ 0xb9 , 0x00B9 }, +{ 0xba , 0x00BA }, +{ 0xbb , 0x00BB }, +{ 0xbc , 0x00BC }, +{ 0xbd , 0x00BD }, +{ 0xbe , 0x00BE }, +{ 0xbf , 0x00BF }, +{ 0xc0 , 0x10D0 }, +{ 0xc1 , 0x10D1 }, +{ 0xc2 , 0x10D2 }, +{ 0xc3 , 0x10D3 }, +{ 0xc4 , 0x10D4 }, +{ 0xc5 , 0x10D5 }, +{ 0xc6 , 0x10D6 }, +{ 0xc7 , 0x10F1 }, +{ 0xc8 , 0x10D7 }, +{ 0xc9 , 0x10D8 }, +{ 0xca , 0x10D9 }, +{ 0xcb , 0x10DA }, +{ 0xcc , 0x10DB }, +{ 0xcd , 0x10DC }, +{ 0xce , 0x10F2 }, +{ 0xcf , 0x10DD }, +{ 0xd0 , 0x10DE }, +{ 0xd1 , 0x10DF }, +{ 0xd2 , 0x10E0 }, +{ 0xd3 , 0x10E1 }, +{ 0xd4 , 0x10E2 }, +{ 0xd5 , 0x10F3 }, +{ 0xd6 , 0x10E3 }, +{ 0xd7 , 0x10E4 }, +{ 0xd8 , 0x10E5 }, +{ 0xd9 , 0x10E6 }, +{ 0xda , 0x10E7 }, +{ 0xdb , 0x10E8 }, +{ 0xdc , 0x10E9 }, +{ 0xdd , 0x10EA }, +{ 0xde , 0x10EB }, +{ 0xdf , 0x10EC }, +{ 0xe0 , 0x10ED }, +{ 0xe1 , 0x10EE }, +{ 0xe2 , 0x10F4 }, +{ 0xe3 , 0x10EF }, +{ 0xe4 , 0x10F0 }, +{ 0xe5 , 0x10F5 }, +{ 0xe6 , 0x00E6 }, +{ 0xe7 , 0x00E7 }, +{ 0xe8 , 0x00E8 }, +{ 0xe9 , 0x00E9 }, +{ 0xea , 0x00EA }, +{ 0xeb , 0x00EB }, +{ 0xec , 0x00EC }, +{ 0xed , 0x00ED }, +{ 0xee , 0x00EE }, +{ 0xef , 0x00EF }, +{ 0xf0 , 0x00F0 }, +{ 0xf1 , 0x00F1 }, +{ 0xf2 , 0x00F2 }, +{ 0xf3 , 0x00F3 }, +{ 0xf4 , 0x00F4 }, +{ 0xf5 , 0x00F5 }, +{ 0xf6 , 0x00F6 }, +{ 0xf7 , 0x00F7 }, +{ 0xf8 , 0x00F8 }, +{ 0xf9 , 0x00F9 }, +{ 0xfa , 0x00FA }, +{ 0xfb , 0x00FB }, +{ 0xfc , 0x00FC }, +{ 0xfd , 0x00FD }, +{ 0xfe , 0x00FE }, +{ 0xff , 0x00FF }, diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/ISO-8859-1.pairs b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/ISO-8859-1.pairs new file mode 100644 index 00000000..97812a0d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/ISO-8859-1.pairs @@ -0,0 +1,256 @@ +{ 0x00 , 0x0000 }, +{ 0x01 , 0x0001 }, +{ 0x02 , 0x0002 }, +{ 0x03 , 0x0003 }, +{ 0x04 , 0x0004 }, +{ 0x05 , 0x0005 }, +{ 0x06 , 0x0006 }, +{ 0x07 , 0x0007 }, +{ 0x08 , 0x0008 }, +{ 0x09 , 0x0009 }, +{ 0x0a , 0x000A }, +{ 0x0b , 0x000B }, +{ 0x0c , 0x000C }, +{ 0x0d , 0x000D }, +{ 0x0e , 0x000E }, +{ 0x0f , 0x000F }, +{ 0x10 , 0x0010 }, +{ 0x11 , 0x0011 }, +{ 0x12 , 0x0012 }, +{ 0x13 , 0x0013 }, +{ 0x14 , 0x0014 }, +{ 0x15 , 0x0015 }, +{ 0x16 , 0x0016 }, +{ 0x17 , 0x0017 }, +{ 0x18 , 0x0018 }, +{ 0x19 , 0x0019 }, +{ 0x1a , 0x001A }, +{ 0x1b , 0x001B }, +{ 0x1c , 0x001C }, +{ 0x1d , 0x001D }, +{ 0x1e , 0x001E }, +{ 0x1f , 0x001F }, +{ 0x20 , 0x0020 }, +{ 0x21 , 0x0021 }, +{ 0x22 , 0x0022 }, +{ 0x23 , 0x0023 }, +{ 0x24 , 0x0024 }, +{ 0x25 , 0x0025 }, +{ 0x26 , 0x0026 }, +{ 0x27 , 0x0027 }, +{ 0x28 , 0x0028 }, +{ 0x29 , 0x0029 }, +{ 0x2a , 0x002A }, +{ 0x2b , 0x002B }, +{ 0x2c , 0x002C }, +{ 0x2d , 0x002D }, +{ 0x2e , 0x002E }, +{ 0x2f , 0x002F }, +{ 0x30 , 0x0030 }, +{ 0x31 , 0x0031 }, +{ 0x32 , 0x0032 }, +{ 0x33 , 0x0033 }, +{ 0x34 , 0x0034 }, +{ 0x35 , 0x0035 }, +{ 0x36 , 0x0036 }, +{ 0x37 , 0x0037 }, +{ 0x38 , 0x0038 }, +{ 0x39 , 0x0039 }, +{ 0x3a , 0x003A }, +{ 0x3b , 0x003B }, +{ 0x3c , 0x003C }, +{ 0x3d , 0x003D }, +{ 0x3e , 0x003E }, +{ 0x3f , 0x003F }, +{ 0x40 , 0x0040 }, +{ 0x41 , 0x0041 }, +{ 0x42 , 0x0042 }, +{ 0x43 , 0x0043 }, +{ 0x44 , 0x0044 }, +{ 0x45 , 0x0045 }, +{ 0x46 , 0x0046 }, +{ 0x47 , 0x0047 }, +{ 0x48 , 0x0048 }, +{ 0x49 , 0x0049 }, +{ 0x4a , 0x004A }, +{ 0x4b , 0x004B }, +{ 0x4c , 0x004C }, +{ 0x4d , 0x004D }, +{ 0x4e , 0x004E }, +{ 0x4f , 0x004F }, +{ 0x50 , 0x0050 }, +{ 0x51 , 0x0051 }, +{ 0x52 , 0x0052 }, +{ 0x53 , 0x0053 }, +{ 0x54 , 0x0054 }, +{ 0x55 , 0x0055 }, +{ 0x56 , 0x0056 }, +{ 0x57 , 0x0057 }, +{ 0x58 , 0x0058 }, +{ 0x59 , 0x0059 }, +{ 0x5a , 0x005A }, +{ 0x5b , 0x005B }, +{ 0x5c , 0x005C }, +{ 0x5d , 0x005D }, +{ 0x5e , 0x005E }, +{ 0x5f , 0x005F }, +{ 0x60 , 0x0060 }, +{ 0x61 , 0x0061 }, +{ 0x62 , 0x0062 }, +{ 0x63 , 0x0063 }, +{ 0x64 , 0x0064 }, +{ 0x65 , 0x0065 }, +{ 0x66 , 0x0066 }, +{ 0x67 , 0x0067 }, +{ 0x68 , 0x0068 }, +{ 0x69 , 0x0069 }, +{ 0x6a , 0x006A }, +{ 0x6b , 0x006B }, +{ 0x6c , 0x006C }, +{ 0x6d , 0x006D }, +{ 0x6e , 0x006E }, +{ 0x6f , 0x006F }, +{ 0x70 , 0x0070 }, +{ 0x71 , 0x0071 }, +{ 0x72 , 0x0072 }, +{ 0x73 , 0x0073 }, +{ 0x74 , 0x0074 }, +{ 0x75 , 0x0075 }, +{ 0x76 , 0x0076 }, +{ 0x77 , 0x0077 }, +{ 0x78 , 0x0078 }, +{ 0x79 , 0x0079 }, +{ 0x7a , 0x007A }, +{ 0x7b , 0x007B }, +{ 0x7c , 0x007C }, +{ 0x7d , 0x007D }, +{ 0x7e , 0x007E }, +{ 0x7f , 0x007F }, +{ 0x80 , 0x0080 }, +{ 0x81 , 0x0081 }, +{ 0x82 , 0x0082 }, +{ 0x83 , 0x0083 }, +{ 0x84 , 0x0084 }, +{ 0x85 , 0x0085 }, +{ 0x86 , 0x0086 }, +{ 0x87 , 0x0087 }, +{ 0x88 , 0x0088 }, +{ 0x89 , 0x0089 }, +{ 0x8a , 0x008A }, +{ 0x8b , 0x008B }, +{ 0x8c , 0x008C }, +{ 0x8d , 0x008D }, +{ 0x8e , 0x008E }, +{ 0x8f , 0x008F }, +{ 0x90 , 0x0090 }, +{ 0x91 , 0x0091 }, +{ 0x92 , 0x0092 }, +{ 0x93 , 0x0093 }, +{ 0x94 , 0x0094 }, +{ 0x95 , 0x0095 }, +{ 0x96 , 0x0096 }, +{ 0x97 , 0x0097 }, +{ 0x98 , 0x0098 }, +{ 0x99 , 0x0099 }, +{ 0x9a , 0x009A }, +{ 0x9b , 0x009B }, +{ 0x9c , 0x009C }, +{ 0x9d , 0x009D }, +{ 0x9e , 0x009E }, +{ 0x9f , 0x009F }, +{ 0xa0 , 0x00A0 }, +{ 0xa1 , 0x00A1 }, +{ 0xa2 , 0x00A2 }, +{ 0xa3 , 0x00A3 }, +{ 0xa4 , 0x00A4 }, +{ 0xa5 , 0x00A5 }, +{ 0xa6 , 0x00A6 }, +{ 0xa7 , 0x00A7 }, +{ 0xa8 , 0x00A8 }, +{ 0xa9 , 0x00A9 }, +{ 0xaa , 0x00AA }, +{ 0xab , 0x00AB }, +{ 0xac , 0x00AC }, +{ 0xad , 0x00AD }, +{ 0xae , 0x00AE }, +{ 0xaf , 0x00AF }, +{ 0xb0 , 0x00B0 }, +{ 0xb1 , 0x00B1 }, +{ 0xb2 , 0x00B2 }, +{ 0xb3 , 0x00B3 }, +{ 0xb4 , 0x00B4 }, +{ 0xb5 , 0x00B5 }, +{ 0xb6 , 0x00B6 }, +{ 0xb7 , 0x00B7 }, +{ 0xb8 , 0x00B8 }, +{ 0xb9 , 0x00B9 }, +{ 0xba , 0x00BA }, +{ 0xbb , 0x00BB }, +{ 0xbc , 0x00BC }, +{ 0xbd , 0x00BD }, +{ 0xbe , 0x00BE }, +{ 0xbf , 0x00BF }, +{ 0xc0 , 0x00C0 }, +{ 0xc1 , 0x00C1 }, +{ 0xc2 , 0x00C2 }, +{ 0xc3 , 0x00C3 }, +{ 0xc4 , 0x00C4 }, +{ 0xc5 , 0x00C5 }, +{ 0xc6 , 0x00C6 }, +{ 0xc7 , 0x00C7 }, +{ 0xc8 , 0x00C8 }, +{ 0xc9 , 0x00C9 }, +{ 0xca , 0x00CA }, +{ 0xcb , 0x00CB }, +{ 0xcc , 0x00CC }, +{ 0xcd , 0x00CD }, +{ 0xce , 0x00CE }, +{ 0xcf , 0x00CF }, +{ 0xd0 , 0x00D0 }, +{ 0xd1 , 0x00D1 }, +{ 0xd2 , 0x00D2 }, +{ 0xd3 , 0x00D3 }, +{ 0xd4 , 0x00D4 }, +{ 0xd5 , 0x00D5 }, +{ 0xd6 , 0x00D6 }, +{ 0xd7 , 0x00D7 }, +{ 0xd8 , 0x00D8 }, +{ 0xd9 , 0x00D9 }, +{ 0xda , 0x00DA }, +{ 0xdb , 0x00DB }, +{ 0xdc , 0x00DC }, +{ 0xdd , 0x00DD }, +{ 0xde , 0x00DE }, +{ 0xdf , 0x00DF }, +{ 0xe0 , 0x00E0 }, +{ 0xe1 , 0x00E1 }, +{ 0xe2 , 0x00E2 }, +{ 0xe3 , 0x00E3 }, +{ 0xe4 , 0x00E4 }, +{ 0xe5 , 0x00E5 }, +{ 0xe6 , 0x00E6 }, +{ 0xe7 , 0x00E7 }, +{ 0xe8 , 0x00E8 }, +{ 0xe9 , 0x00E9 }, +{ 0xea , 0x00EA }, +{ 0xeb , 0x00EB }, +{ 0xec , 0x00EC }, +{ 0xed , 0x00ED }, +{ 0xee , 0x00EE }, +{ 0xef , 0x00EF }, +{ 0xf0 , 0x00F0 }, +{ 0xf1 , 0x00F1 }, +{ 0xf2 , 0x00F2 }, +{ 0xf3 , 0x00F3 }, +{ 0xf4 , 0x00F4 }, +{ 0xf5 , 0x00F5 }, +{ 0xf6 , 0x00F6 }, +{ 0xf7 , 0x00F7 }, +{ 0xf8 , 0x00F8 }, +{ 0xf9 , 0x00F9 }, +{ 0xfa , 0x00FA }, +{ 0xfb , 0x00FB }, +{ 0xfc , 0x00FC }, +{ 0xfd , 0x00FD }, +{ 0xfe , 0x00FE }, +{ 0xff , 0x00FF }, diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/ISO-8859-10.pairs b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/ISO-8859-10.pairs new file mode 100644 index 00000000..a39892fc --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/ISO-8859-10.pairs @@ -0,0 +1,256 @@ +{ 0x00 , 0x0000 }, +{ 0x01 , 0x0001 }, +{ 0x02 , 0x0002 }, +{ 0x03 , 0x0003 }, +{ 0x04 , 0x0004 }, +{ 0x05 , 0x0005 }, +{ 0x06 , 0x0006 }, +{ 0x07 , 0x0007 }, +{ 0x08 , 0x0008 }, +{ 0x09 , 0x0009 }, +{ 0x0a , 0x000A }, +{ 0x0b , 0x000B }, +{ 0x0c , 0x000C }, +{ 0x0d , 0x000D }, +{ 0x0e , 0x000E }, +{ 0x0f , 0x000F }, +{ 0x10 , 0x0010 }, +{ 0x11 , 0x0011 }, +{ 0x12 , 0x0012 }, +{ 0x13 , 0x0013 }, +{ 0x14 , 0x0014 }, +{ 0x15 , 0x0015 }, +{ 0x16 , 0x0016 }, +{ 0x17 , 0x0017 }, +{ 0x18 , 0x0018 }, +{ 0x19 , 0x0019 }, +{ 0x1a , 0x001A }, +{ 0x1b , 0x001B }, +{ 0x1c , 0x001C }, +{ 0x1d , 0x001D }, +{ 0x1e , 0x001E }, +{ 0x1f , 0x001F }, +{ 0x20 , 0x0020 }, +{ 0x21 , 0x0021 }, +{ 0x22 , 0x0022 }, +{ 0x23 , 0x0023 }, +{ 0x24 , 0x0024 }, +{ 0x25 , 0x0025 }, +{ 0x26 , 0x0026 }, +{ 0x27 , 0x0027 }, +{ 0x28 , 0x0028 }, +{ 0x29 , 0x0029 }, +{ 0x2a , 0x002A }, +{ 0x2b , 0x002B }, +{ 0x2c , 0x002C }, +{ 0x2d , 0x002D }, +{ 0x2e , 0x002E }, +{ 0x2f , 0x002F }, +{ 0x30 , 0x0030 }, +{ 0x31 , 0x0031 }, +{ 0x32 , 0x0032 }, +{ 0x33 , 0x0033 }, +{ 0x34 , 0x0034 }, +{ 0x35 , 0x0035 }, +{ 0x36 , 0x0036 }, +{ 0x37 , 0x0037 }, +{ 0x38 , 0x0038 }, +{ 0x39 , 0x0039 }, +{ 0x3a , 0x003A }, +{ 0x3b , 0x003B }, +{ 0x3c , 0x003C }, +{ 0x3d , 0x003D }, +{ 0x3e , 0x003E }, +{ 0x3f , 0x003F }, +{ 0x40 , 0x0040 }, +{ 0x41 , 0x0041 }, +{ 0x42 , 0x0042 }, +{ 0x43 , 0x0043 }, +{ 0x44 , 0x0044 }, +{ 0x45 , 0x0045 }, +{ 0x46 , 0x0046 }, +{ 0x47 , 0x0047 }, +{ 0x48 , 0x0048 }, +{ 0x49 , 0x0049 }, +{ 0x4a , 0x004A }, +{ 0x4b , 0x004B }, +{ 0x4c , 0x004C }, +{ 0x4d , 0x004D }, +{ 0x4e , 0x004E }, +{ 0x4f , 0x004F }, +{ 0x50 , 0x0050 }, +{ 0x51 , 0x0051 }, +{ 0x52 , 0x0052 }, +{ 0x53 , 0x0053 }, +{ 0x54 , 0x0054 }, +{ 0x55 , 0x0055 }, +{ 0x56 , 0x0056 }, +{ 0x57 , 0x0057 }, +{ 0x58 , 0x0058 }, +{ 0x59 , 0x0059 }, +{ 0x5a , 0x005A }, +{ 0x5b , 0x005B }, +{ 0x5c , 0x005C }, +{ 0x5d , 0x005D }, +{ 0x5e , 0x005E }, +{ 0x5f , 0x005F }, +{ 0x60 , 0x0060 }, +{ 0x61 , 0x0061 }, +{ 0x62 , 0x0062 }, +{ 0x63 , 0x0063 }, +{ 0x64 , 0x0064 }, +{ 0x65 , 0x0065 }, +{ 0x66 , 0x0066 }, +{ 0x67 , 0x0067 }, +{ 0x68 , 0x0068 }, +{ 0x69 , 0x0069 }, +{ 0x6a , 0x006A }, +{ 0x6b , 0x006B }, +{ 0x6c , 0x006C }, +{ 0x6d , 0x006D }, +{ 0x6e , 0x006E }, +{ 0x6f , 0x006F }, +{ 0x70 , 0x0070 }, +{ 0x71 , 0x0071 }, +{ 0x72 , 0x0072 }, +{ 0x73 , 0x0073 }, +{ 0x74 , 0x0074 }, +{ 0x75 , 0x0075 }, +{ 0x76 , 0x0076 }, +{ 0x77 , 0x0077 }, +{ 0x78 , 0x0078 }, +{ 0x79 , 0x0079 }, +{ 0x7a , 0x007A }, +{ 0x7b , 0x007B }, +{ 0x7c , 0x007C }, +{ 0x7d , 0x007D }, +{ 0x7e , 0x007E }, +{ 0x7f , 0x007F }, +{ 0x80 , 0x0080 }, +{ 0x81 , 0x0081 }, +{ 0x82 , 0x0082 }, +{ 0x83 , 0x0083 }, +{ 0x84 , 0x0084 }, +{ 0x85 , 0x0085 }, +{ 0x86 , 0x0086 }, +{ 0x87 , 0x0087 }, +{ 0x88 , 0x0088 }, +{ 0x89 , 0x0089 }, +{ 0x8a , 0x008A }, +{ 0x8b , 0x008B }, +{ 0x8c , 0x008C }, +{ 0x8d , 0x008D }, +{ 0x8e , 0x008E }, +{ 0x8f , 0x008F }, +{ 0x90 , 0x0090 }, +{ 0x91 , 0x0091 }, +{ 0x92 , 0x0092 }, +{ 0x93 , 0x0093 }, +{ 0x94 , 0x0094 }, +{ 0x95 , 0x0095 }, +{ 0x96 , 0x0096 }, +{ 0x97 , 0x0097 }, +{ 0x98 , 0x0098 }, +{ 0x99 , 0x0099 }, +{ 0x9a , 0x009A }, +{ 0x9b , 0x009B }, +{ 0x9c , 0x009C }, +{ 0x9d , 0x009D }, +{ 0x9e , 0x009E }, +{ 0x9f , 0x009F }, +{ 0xa0 , 0x00A0 }, +{ 0xa1 , 0x0104 }, +{ 0xa2 , 0x0112 }, +{ 0xa3 , 0x0122 }, +{ 0xa4 , 0x012A }, +{ 0xa5 , 0x0128 }, +{ 0xa6 , 0x0136 }, +{ 0xa7 , 0x00A7 }, +{ 0xa8 , 0x013B }, +{ 0xa9 , 0x0110 }, +{ 0xaa , 0x0160 }, +{ 0xab , 0x0166 }, +{ 0xac , 0x017D }, +{ 0xad , 0x00AD }, +{ 0xae , 0x016A }, +{ 0xaf , 0x014A }, +{ 0xb0 , 0x00B0 }, +{ 0xb1 , 0x0105 }, +{ 0xb2 , 0x0113 }, +{ 0xb3 , 0x0123 }, +{ 0xb4 , 0x012B }, +{ 0xb5 , 0x0129 }, +{ 0xb6 , 0x0137 }, +{ 0xb7 , 0x00B7 }, +{ 0xb8 , 0x013C }, +{ 0xb9 , 0x0111 }, +{ 0xba , 0x0161 }, +{ 0xbb , 0x0167 }, +{ 0xbc , 0x017E }, +{ 0xbd , 0x2015 }, +{ 0xbe , 0x016B }, +{ 0xbf , 0x014B }, +{ 0xc0 , 0x0100 }, +{ 0xc1 , 0x00C1 }, +{ 0xc2 , 0x00C2 }, +{ 0xc3 , 0x00C3 }, +{ 0xc4 , 0x00C4 }, +{ 0xc5 , 0x00C5 }, +{ 0xc6 , 0x00C6 }, +{ 0xc7 , 0x012E }, +{ 0xc8 , 0x010C }, +{ 0xc9 , 0x00C9 }, +{ 0xca , 0x0118 }, +{ 0xcb , 0x00CB }, +{ 0xcc , 0x0116 }, +{ 0xcd , 0x00CD }, +{ 0xce , 0x00CE }, +{ 0xcf , 0x00CF }, +{ 0xd0 , 0x00D0 }, +{ 0xd1 , 0x0145 }, +{ 0xd2 , 0x014C }, +{ 0xd3 , 0x00D3 }, +{ 0xd4 , 0x00D4 }, +{ 0xd5 , 0x00D5 }, +{ 0xd6 , 0x00D6 }, +{ 0xd7 , 0x0168 }, +{ 0xd8 , 0x00D8 }, +{ 0xd9 , 0x0172 }, +{ 0xda , 0x00DA }, +{ 0xdb , 0x00DB }, +{ 0xdc , 0x00DC }, +{ 0xdd , 0x00DD }, +{ 0xde , 0x00DE }, +{ 0xdf , 0x00DF }, +{ 0xe0 , 0x0101 }, +{ 0xe1 , 0x00E1 }, +{ 0xe2 , 0x00E2 }, +{ 0xe3 , 0x00E3 }, +{ 0xe4 , 0x00E4 }, +{ 0xe5 , 0x00E5 }, +{ 0xe6 , 0x00E6 }, +{ 0xe7 , 0x012F }, +{ 0xe8 , 0x010D }, +{ 0xe9 , 0x00E9 }, +{ 0xea , 0x0119 }, +{ 0xeb , 0x00EB }, +{ 0xec , 0x0117 }, +{ 0xed , 0x00ED }, +{ 0xee , 0x00EE }, +{ 0xef , 0x00EF }, +{ 0xf0 , 0x00F0 }, +{ 0xf1 , 0x0146 }, +{ 0xf2 , 0x014D }, +{ 0xf3 , 0x00F3 }, +{ 0xf4 , 0x00F4 }, +{ 0xf5 , 0x00F5 }, +{ 0xf6 , 0x00F6 }, +{ 0xf7 , 0x0169 }, +{ 0xf8 , 0x00F8 }, +{ 0xf9 , 0x0173 }, +{ 0xfa , 0x00FA }, +{ 0xfb , 0x00FB }, +{ 0xfc , 0x00FC }, +{ 0xfd , 0x00FD }, +{ 0xfe , 0x00FE }, +{ 0xff , 0x0138 }, diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/ISO-8859-13.pairs b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/ISO-8859-13.pairs new file mode 100644 index 00000000..ff95fb44 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/ISO-8859-13.pairs @@ -0,0 +1,256 @@ +{ 0x00 , 0x0000 }, +{ 0x01 , 0x0001 }, +{ 0x02 , 0x0002 }, +{ 0x03 , 0x0003 }, +{ 0x04 , 0x0004 }, +{ 0x05 , 0x0005 }, +{ 0x06 , 0x0006 }, +{ 0x07 , 0x0007 }, +{ 0x08 , 0x0008 }, +{ 0x09 , 0x0009 }, +{ 0x0a , 0x000A }, +{ 0x0b , 0x000B }, +{ 0x0c , 0x000C }, +{ 0x0d , 0x000D }, +{ 0x0e , 0x000E }, +{ 0x0f , 0x000F }, +{ 0x10 , 0x0010 }, +{ 0x11 , 0x0011 }, +{ 0x12 , 0x0012 }, +{ 0x13 , 0x0013 }, +{ 0x14 , 0x0014 }, +{ 0x15 , 0x0015 }, +{ 0x16 , 0x0016 }, +{ 0x17 , 0x0017 }, +{ 0x18 , 0x0018 }, +{ 0x19 , 0x0019 }, +{ 0x1a , 0x001A }, +{ 0x1b , 0x001B }, +{ 0x1c , 0x001C }, +{ 0x1d , 0x001D }, +{ 0x1e , 0x001E }, +{ 0x1f , 0x001F }, +{ 0x20 , 0x0020 }, +{ 0x21 , 0x0021 }, +{ 0x22 , 0x0022 }, +{ 0x23 , 0x0023 }, +{ 0x24 , 0x0024 }, +{ 0x25 , 0x0025 }, +{ 0x26 , 0x0026 }, +{ 0x27 , 0x0027 }, +{ 0x28 , 0x0028 }, +{ 0x29 , 0x0029 }, +{ 0x2a , 0x002A }, +{ 0x2b , 0x002B }, +{ 0x2c , 0x002C }, +{ 0x2d , 0x002D }, +{ 0x2e , 0x002E }, +{ 0x2f , 0x002F }, +{ 0x30 , 0x0030 }, +{ 0x31 , 0x0031 }, +{ 0x32 , 0x0032 }, +{ 0x33 , 0x0033 }, +{ 0x34 , 0x0034 }, +{ 0x35 , 0x0035 }, +{ 0x36 , 0x0036 }, +{ 0x37 , 0x0037 }, +{ 0x38 , 0x0038 }, +{ 0x39 , 0x0039 }, +{ 0x3a , 0x003A }, +{ 0x3b , 0x003B }, +{ 0x3c , 0x003C }, +{ 0x3d , 0x003D }, +{ 0x3e , 0x003E }, +{ 0x3f , 0x003F }, +{ 0x40 , 0x0040 }, +{ 0x41 , 0x0041 }, +{ 0x42 , 0x0042 }, +{ 0x43 , 0x0043 }, +{ 0x44 , 0x0044 }, +{ 0x45 , 0x0045 }, +{ 0x46 , 0x0046 }, +{ 0x47 , 0x0047 }, +{ 0x48 , 0x0048 }, +{ 0x49 , 0x0049 }, +{ 0x4a , 0x004A }, +{ 0x4b , 0x004B }, +{ 0x4c , 0x004C }, +{ 0x4d , 0x004D }, +{ 0x4e , 0x004E }, +{ 0x4f , 0x004F }, +{ 0x50 , 0x0050 }, +{ 0x51 , 0x0051 }, +{ 0x52 , 0x0052 }, +{ 0x53 , 0x0053 }, +{ 0x54 , 0x0054 }, +{ 0x55 , 0x0055 }, +{ 0x56 , 0x0056 }, +{ 0x57 , 0x0057 }, +{ 0x58 , 0x0058 }, +{ 0x59 , 0x0059 }, +{ 0x5a , 0x005A }, +{ 0x5b , 0x005B }, +{ 0x5c , 0x005C }, +{ 0x5d , 0x005D }, +{ 0x5e , 0x005E }, +{ 0x5f , 0x005F }, +{ 0x60 , 0x0060 }, +{ 0x61 , 0x0061 }, +{ 0x62 , 0x0062 }, +{ 0x63 , 0x0063 }, +{ 0x64 , 0x0064 }, +{ 0x65 , 0x0065 }, +{ 0x66 , 0x0066 }, +{ 0x67 , 0x0067 }, +{ 0x68 , 0x0068 }, +{ 0x69 , 0x0069 }, +{ 0x6a , 0x006A }, +{ 0x6b , 0x006B }, +{ 0x6c , 0x006C }, +{ 0x6d , 0x006D }, +{ 0x6e , 0x006E }, +{ 0x6f , 0x006F }, +{ 0x70 , 0x0070 }, +{ 0x71 , 0x0071 }, +{ 0x72 , 0x0072 }, +{ 0x73 , 0x0073 }, +{ 0x74 , 0x0074 }, +{ 0x75 , 0x0075 }, +{ 0x76 , 0x0076 }, +{ 0x77 , 0x0077 }, +{ 0x78 , 0x0078 }, +{ 0x79 , 0x0079 }, +{ 0x7a , 0x007A }, +{ 0x7b , 0x007B }, +{ 0x7c , 0x007C }, +{ 0x7d , 0x007D }, +{ 0x7e , 0x007E }, +{ 0x7f , 0x007F }, +{ 0x80 , 0x0080 }, +{ 0x81 , 0x0081 }, +{ 0x82 , 0x0082 }, +{ 0x83 , 0x0083 }, +{ 0x84 , 0x0084 }, +{ 0x85 , 0x0085 }, +{ 0x86 , 0x0086 }, +{ 0x87 , 0x0087 }, +{ 0x88 , 0x0088 }, +{ 0x89 , 0x0089 }, +{ 0x8a , 0x008A }, +{ 0x8b , 0x008B }, +{ 0x8c , 0x008C }, +{ 0x8d , 0x008D }, +{ 0x8e , 0x008E }, +{ 0x8f , 0x008F }, +{ 0x90 , 0x0090 }, +{ 0x91 , 0x0091 }, +{ 0x92 , 0x0092 }, +{ 0x93 , 0x0093 }, +{ 0x94 , 0x0094 }, +{ 0x95 , 0x0095 }, +{ 0x96 , 0x0096 }, +{ 0x97 , 0x0097 }, +{ 0x98 , 0x0098 }, +{ 0x99 , 0x0099 }, +{ 0x9a , 0x009A }, +{ 0x9b , 0x009B }, +{ 0x9c , 0x009C }, +{ 0x9d , 0x009D }, +{ 0x9e , 0x009E }, +{ 0x9f , 0x009F }, +{ 0xa0 , 0x00A0 }, +{ 0xa1 , 0x201D }, +{ 0xa2 , 0x00A2 }, +{ 0xa3 , 0x00A3 }, +{ 0xa4 , 0x00A4 }, +{ 0xa5 , 0x201E }, +{ 0xa6 , 0x00A6 }, +{ 0xa7 , 0x00A7 }, +{ 0xa8 , 0x00D8 }, +{ 0xa9 , 0x00A9 }, +{ 0xaa , 0x0156 }, +{ 0xab , 0x00AB }, +{ 0xac , 0x00AC }, +{ 0xad , 0x00AD }, +{ 0xae , 0x00AE }, +{ 0xaf , 0x00C6 }, +{ 0xb0 , 0x00B0 }, +{ 0xb1 , 0x00B1 }, +{ 0xb2 , 0x00B2 }, +{ 0xb3 , 0x00B3 }, +{ 0xb4 , 0x201C }, +{ 0xb5 , 0x00B5 }, +{ 0xb6 , 0x00B6 }, +{ 0xb7 , 0x00B7 }, +{ 0xb8 , 0x00F8 }, +{ 0xb9 , 0x00B9 }, +{ 0xba , 0x0157 }, +{ 0xbb , 0x00BB }, +{ 0xbc , 0x00BC }, +{ 0xbd , 0x00BD }, +{ 0xbe , 0x00BE }, +{ 0xbf , 0x00E6 }, +{ 0xc0 , 0x0104 }, +{ 0xc1 , 0x012E }, +{ 0xc2 , 0x0100 }, +{ 0xc3 , 0x0106 }, +{ 0xc4 , 0x00C4 }, +{ 0xc5 , 0x00C5 }, +{ 0xc6 , 0x0118 }, +{ 0xc7 , 0x0112 }, +{ 0xc8 , 0x010C }, +{ 0xc9 , 0x00C9 }, +{ 0xca , 0x0179 }, +{ 0xcb , 0x0116 }, +{ 0xcc , 0x0122 }, +{ 0xcd , 0x0136 }, +{ 0xce , 0x012A }, +{ 0xcf , 0x013B }, +{ 0xd0 , 0x0160 }, +{ 0xd1 , 0x0143 }, +{ 0xd2 , 0x0145 }, +{ 0xd3 , 0x00D3 }, +{ 0xd4 , 0x014C }, +{ 0xd5 , 0x00D5 }, +{ 0xd6 , 0x00D6 }, +{ 0xd7 , 0x00D7 }, +{ 0xd8 , 0x0172 }, +{ 0xd9 , 0x0141 }, +{ 0xda , 0x015A }, +{ 0xdb , 0x016A }, +{ 0xdc , 0x00DC }, +{ 0xdd , 0x017B }, +{ 0xde , 0x017D }, +{ 0xdf , 0x00DF }, +{ 0xe0 , 0x0105 }, +{ 0xe1 , 0x012F }, +{ 0xe2 , 0x0101 }, +{ 0xe3 , 0x0107 }, +{ 0xe4 , 0x00E4 }, +{ 0xe5 , 0x00E5 }, +{ 0xe6 , 0x0119 }, +{ 0xe7 , 0x0113 }, +{ 0xe8 , 0x010D }, +{ 0xe9 , 0x00E9 }, +{ 0xea , 0x017A }, +{ 0xeb , 0x0117 }, +{ 0xec , 0x0123 }, +{ 0xed , 0x0137 }, +{ 0xee , 0x012B }, +{ 0xef , 0x013C }, +{ 0xf0 , 0x0161 }, +{ 0xf1 , 0x0144 }, +{ 0xf2 , 0x0146 }, +{ 0xf3 , 0x00F3 }, +{ 0xf4 , 0x014D }, +{ 0xf5 , 0x00F5 }, +{ 0xf6 , 0x00F6 }, +{ 0xf7 , 0x00F7 }, +{ 0xf8 , 0x0173 }, +{ 0xf9 , 0x0142 }, +{ 0xfa , 0x015B }, +{ 0xfb , 0x016B }, +{ 0xfc , 0x00FC }, +{ 0xfd , 0x017C }, +{ 0xfe , 0x017E }, +{ 0xff , 0x2019 }, diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/ISO-8859-14.pairs b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/ISO-8859-14.pairs new file mode 100644 index 00000000..8a8f06ec --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/ISO-8859-14.pairs @@ -0,0 +1,256 @@ +{ 0x00 , 0x0000 }, +{ 0x01 , 0x0001 }, +{ 0x02 , 0x0002 }, +{ 0x03 , 0x0003 }, +{ 0x04 , 0x0004 }, +{ 0x05 , 0x0005 }, +{ 0x06 , 0x0006 }, +{ 0x07 , 0x0007 }, +{ 0x08 , 0x0008 }, +{ 0x09 , 0x0009 }, +{ 0x0a , 0x000A }, +{ 0x0b , 0x000B }, +{ 0x0c , 0x000C }, +{ 0x0d , 0x000D }, +{ 0x0e , 0x000E }, +{ 0x0f , 0x000F }, +{ 0x10 , 0x0010 }, +{ 0x11 , 0x0011 }, +{ 0x12 , 0x0012 }, +{ 0x13 , 0x0013 }, +{ 0x14 , 0x0014 }, +{ 0x15 , 0x0015 }, +{ 0x16 , 0x0016 }, +{ 0x17 , 0x0017 }, +{ 0x18 , 0x0018 }, +{ 0x19 , 0x0019 }, +{ 0x1a , 0x001A }, +{ 0x1b , 0x001B }, +{ 0x1c , 0x001C }, +{ 0x1d , 0x001D }, +{ 0x1e , 0x001E }, +{ 0x1f , 0x001F }, +{ 0x20 , 0x0020 }, +{ 0x21 , 0x0021 }, +{ 0x22 , 0x0022 }, +{ 0x23 , 0x0023 }, +{ 0x24 , 0x0024 }, +{ 0x25 , 0x0025 }, +{ 0x26 , 0x0026 }, +{ 0x27 , 0x0027 }, +{ 0x28 , 0x0028 }, +{ 0x29 , 0x0029 }, +{ 0x2a , 0x002A }, +{ 0x2b , 0x002B }, +{ 0x2c , 0x002C }, +{ 0x2d , 0x002D }, +{ 0x2e , 0x002E }, +{ 0x2f , 0x002F }, +{ 0x30 , 0x0030 }, +{ 0x31 , 0x0031 }, +{ 0x32 , 0x0032 }, +{ 0x33 , 0x0033 }, +{ 0x34 , 0x0034 }, +{ 0x35 , 0x0035 }, +{ 0x36 , 0x0036 }, +{ 0x37 , 0x0037 }, +{ 0x38 , 0x0038 }, +{ 0x39 , 0x0039 }, +{ 0x3a , 0x003A }, +{ 0x3b , 0x003B }, +{ 0x3c , 0x003C }, +{ 0x3d , 0x003D }, +{ 0x3e , 0x003E }, +{ 0x3f , 0x003F }, +{ 0x40 , 0x0040 }, +{ 0x41 , 0x0041 }, +{ 0x42 , 0x0042 }, +{ 0x43 , 0x0043 }, +{ 0x44 , 0x0044 }, +{ 0x45 , 0x0045 }, +{ 0x46 , 0x0046 }, +{ 0x47 , 0x0047 }, +{ 0x48 , 0x0048 }, +{ 0x49 , 0x0049 }, +{ 0x4a , 0x004A }, +{ 0x4b , 0x004B }, +{ 0x4c , 0x004C }, +{ 0x4d , 0x004D }, +{ 0x4e , 0x004E }, +{ 0x4f , 0x004F }, +{ 0x50 , 0x0050 }, +{ 0x51 , 0x0051 }, +{ 0x52 , 0x0052 }, +{ 0x53 , 0x0053 }, +{ 0x54 , 0x0054 }, +{ 0x55 , 0x0055 }, +{ 0x56 , 0x0056 }, +{ 0x57 , 0x0057 }, +{ 0x58 , 0x0058 }, +{ 0x59 , 0x0059 }, +{ 0x5a , 0x005A }, +{ 0x5b , 0x005B }, +{ 0x5c , 0x005C }, +{ 0x5d , 0x005D }, +{ 0x5e , 0x005E }, +{ 0x5f , 0x005F }, +{ 0x60 , 0x0060 }, +{ 0x61 , 0x0061 }, +{ 0x62 , 0x0062 }, +{ 0x63 , 0x0063 }, +{ 0x64 , 0x0064 }, +{ 0x65 , 0x0065 }, +{ 0x66 , 0x0066 }, +{ 0x67 , 0x0067 }, +{ 0x68 , 0x0068 }, +{ 0x69 , 0x0069 }, +{ 0x6a , 0x006A }, +{ 0x6b , 0x006B }, +{ 0x6c , 0x006C }, +{ 0x6d , 0x006D }, +{ 0x6e , 0x006E }, +{ 0x6f , 0x006F }, +{ 0x70 , 0x0070 }, +{ 0x71 , 0x0071 }, +{ 0x72 , 0x0072 }, +{ 0x73 , 0x0073 }, +{ 0x74 , 0x0074 }, +{ 0x75 , 0x0075 }, +{ 0x76 , 0x0076 }, +{ 0x77 , 0x0077 }, +{ 0x78 , 0x0078 }, +{ 0x79 , 0x0079 }, +{ 0x7a , 0x007A }, +{ 0x7b , 0x007B }, +{ 0x7c , 0x007C }, +{ 0x7d , 0x007D }, +{ 0x7e , 0x007E }, +{ 0x7f , 0x007F }, +{ 0x80 , 0x0080 }, +{ 0x81 , 0x0081 }, +{ 0x82 , 0x0082 }, +{ 0x83 , 0x0083 }, +{ 0x84 , 0x0084 }, +{ 0x85 , 0x0085 }, +{ 0x86 , 0x0086 }, +{ 0x87 , 0x0087 }, +{ 0x88 , 0x0088 }, +{ 0x89 , 0x0089 }, +{ 0x8a , 0x008A }, +{ 0x8b , 0x008B }, +{ 0x8c , 0x008C }, +{ 0x8d , 0x008D }, +{ 0x8e , 0x008E }, +{ 0x8f , 0x008F }, +{ 0x90 , 0x0090 }, +{ 0x91 , 0x0091 }, +{ 0x92 , 0x0092 }, +{ 0x93 , 0x0093 }, +{ 0x94 , 0x0094 }, +{ 0x95 , 0x0095 }, +{ 0x96 , 0x0096 }, +{ 0x97 , 0x0097 }, +{ 0x98 , 0x0098 }, +{ 0x99 , 0x0099 }, +{ 0x9a , 0x009A }, +{ 0x9b , 0x009B }, +{ 0x9c , 0x009C }, +{ 0x9d , 0x009D }, +{ 0x9e , 0x009E }, +{ 0x9f , 0x009F }, +{ 0xa0 , 0x00A0 }, +{ 0xa1 , 0x1E02 }, +{ 0xa2 , 0x1E03 }, +{ 0xa3 , 0x00A3 }, +{ 0xa4 , 0x010A }, +{ 0xa5 , 0x010B }, +{ 0xa6 , 0x1E0A }, +{ 0xa7 , 0x00A7 }, +{ 0xa8 , 0x1E80 }, +{ 0xa9 , 0x00A9 }, +{ 0xaa , 0x1E82 }, +{ 0xab , 0x1E0B }, +{ 0xac , 0x1EF2 }, +{ 0xad , 0x00AD }, +{ 0xae , 0x00AE }, +{ 0xaf , 0x0178 }, +{ 0xb0 , 0x1E1E }, +{ 0xb1 , 0x1E1F }, +{ 0xb2 , 0x0120 }, +{ 0xb3 , 0x0121 }, +{ 0xb4 , 0x1E40 }, +{ 0xb5 , 0x1E41 }, +{ 0xb6 , 0x00B6 }, +{ 0xb7 , 0x1E56 }, +{ 0xb8 , 0x1E81 }, +{ 0xb9 , 0x1E57 }, +{ 0xba , 0x1E83 }, +{ 0xbb , 0x1E60 }, +{ 0xbc , 0x1EF3 }, +{ 0xbd , 0x1E84 }, +{ 0xbe , 0x1E85 }, +{ 0xbf , 0x1E61 }, +{ 0xc0 , 0x00C0 }, +{ 0xc1 , 0x00C1 }, +{ 0xc2 , 0x00C2 }, +{ 0xc3 , 0x00C3 }, +{ 0xc4 , 0x00C4 }, +{ 0xc5 , 0x00C5 }, +{ 0xc6 , 0x00C6 }, +{ 0xc7 , 0x00C7 }, +{ 0xc8 , 0x00C8 }, +{ 0xc9 , 0x00C9 }, +{ 0xca , 0x00CA }, +{ 0xcb , 0x00CB }, +{ 0xcc , 0x00CC }, +{ 0xcd , 0x00CD }, +{ 0xce , 0x00CE }, +{ 0xcf , 0x00CF }, +{ 0xd0 , 0x0174 }, +{ 0xd1 , 0x00D1 }, +{ 0xd2 , 0x00D2 }, +{ 0xd3 , 0x00D3 }, +{ 0xd4 , 0x00D4 }, +{ 0xd5 , 0x00D5 }, +{ 0xd6 , 0x00D6 }, +{ 0xd7 , 0x1E6A }, +{ 0xd8 , 0x00D8 }, +{ 0xd9 , 0x00D9 }, +{ 0xda , 0x00DA }, +{ 0xdb , 0x00DB }, +{ 0xdc , 0x00DC }, +{ 0xdd , 0x00DD }, +{ 0xde , 0x0176 }, +{ 0xdf , 0x00DF }, +{ 0xe0 , 0x00E0 }, +{ 0xe1 , 0x00E1 }, +{ 0xe2 , 0x00E2 }, +{ 0xe3 , 0x00E3 }, +{ 0xe4 , 0x00E4 }, +{ 0xe5 , 0x00E5 }, +{ 0xe6 , 0x00E6 }, +{ 0xe7 , 0x00E7 }, +{ 0xe8 , 0x00E8 }, +{ 0xe9 , 0x00E9 }, +{ 0xea , 0x00EA }, +{ 0xeb , 0x00EB }, +{ 0xec , 0x00EC }, +{ 0xed , 0x00ED }, +{ 0xee , 0x00EE }, +{ 0xef , 0x00EF }, +{ 0xf0 , 0x0175 }, +{ 0xf1 , 0x00F1 }, +{ 0xf2 , 0x00F2 }, +{ 0xf3 , 0x00F3 }, +{ 0xf4 , 0x00F4 }, +{ 0xf5 , 0x00F5 }, +{ 0xf6 , 0x00F6 }, +{ 0xf7 , 0x1E6B }, +{ 0xf8 , 0x00F8 }, +{ 0xf9 , 0x00F9 }, +{ 0xfa , 0x00FA }, +{ 0xfb , 0x00FB }, +{ 0xfc , 0x00FC }, +{ 0xfd , 0x00FD }, +{ 0xfe , 0x0177 }, +{ 0xff , 0x00FF }, diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/ISO-8859-15.pairs b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/ISO-8859-15.pairs new file mode 100644 index 00000000..ca50e22b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/ISO-8859-15.pairs @@ -0,0 +1,256 @@ +{ 0x00 , 0x0000 }, +{ 0x01 , 0x0001 }, +{ 0x02 , 0x0002 }, +{ 0x03 , 0x0003 }, +{ 0x04 , 0x0004 }, +{ 0x05 , 0x0005 }, +{ 0x06 , 0x0006 }, +{ 0x07 , 0x0007 }, +{ 0x08 , 0x0008 }, +{ 0x09 , 0x0009 }, +{ 0x0a , 0x000A }, +{ 0x0b , 0x000B }, +{ 0x0c , 0x000C }, +{ 0x0d , 0x000D }, +{ 0x0e , 0x000E }, +{ 0x0f , 0x000F }, +{ 0x10 , 0x0010 }, +{ 0x11 , 0x0011 }, +{ 0x12 , 0x0012 }, +{ 0x13 , 0x0013 }, +{ 0x14 , 0x0014 }, +{ 0x15 , 0x0015 }, +{ 0x16 , 0x0016 }, +{ 0x17 , 0x0017 }, +{ 0x18 , 0x0018 }, +{ 0x19 , 0x0019 }, +{ 0x1a , 0x001A }, +{ 0x1b , 0x001B }, +{ 0x1c , 0x001C }, +{ 0x1d , 0x001D }, +{ 0x1e , 0x001E }, +{ 0x1f , 0x001F }, +{ 0x20 , 0x0020 }, +{ 0x21 , 0x0021 }, +{ 0x22 , 0x0022 }, +{ 0x23 , 0x0023 }, +{ 0x24 , 0x0024 }, +{ 0x25 , 0x0025 }, +{ 0x26 , 0x0026 }, +{ 0x27 , 0x0027 }, +{ 0x28 , 0x0028 }, +{ 0x29 , 0x0029 }, +{ 0x2a , 0x002A }, +{ 0x2b , 0x002B }, +{ 0x2c , 0x002C }, +{ 0x2d , 0x002D }, +{ 0x2e , 0x002E }, +{ 0x2f , 0x002F }, +{ 0x30 , 0x0030 }, +{ 0x31 , 0x0031 }, +{ 0x32 , 0x0032 }, +{ 0x33 , 0x0033 }, +{ 0x34 , 0x0034 }, +{ 0x35 , 0x0035 }, +{ 0x36 , 0x0036 }, +{ 0x37 , 0x0037 }, +{ 0x38 , 0x0038 }, +{ 0x39 , 0x0039 }, +{ 0x3a , 0x003A }, +{ 0x3b , 0x003B }, +{ 0x3c , 0x003C }, +{ 0x3d , 0x003D }, +{ 0x3e , 0x003E }, +{ 0x3f , 0x003F }, +{ 0x40 , 0x0040 }, +{ 0x41 , 0x0041 }, +{ 0x42 , 0x0042 }, +{ 0x43 , 0x0043 }, +{ 0x44 , 0x0044 }, +{ 0x45 , 0x0045 }, +{ 0x46 , 0x0046 }, +{ 0x47 , 0x0047 }, +{ 0x48 , 0x0048 }, +{ 0x49 , 0x0049 }, +{ 0x4a , 0x004A }, +{ 0x4b , 0x004B }, +{ 0x4c , 0x004C }, +{ 0x4d , 0x004D }, +{ 0x4e , 0x004E }, +{ 0x4f , 0x004F }, +{ 0x50 , 0x0050 }, +{ 0x51 , 0x0051 }, +{ 0x52 , 0x0052 }, +{ 0x53 , 0x0053 }, +{ 0x54 , 0x0054 }, +{ 0x55 , 0x0055 }, +{ 0x56 , 0x0056 }, +{ 0x57 , 0x0057 }, +{ 0x58 , 0x0058 }, +{ 0x59 , 0x0059 }, +{ 0x5a , 0x005A }, +{ 0x5b , 0x005B }, +{ 0x5c , 0x005C }, +{ 0x5d , 0x005D }, +{ 0x5e , 0x005E }, +{ 0x5f , 0x005F }, +{ 0x60 , 0x0060 }, +{ 0x61 , 0x0061 }, +{ 0x62 , 0x0062 }, +{ 0x63 , 0x0063 }, +{ 0x64 , 0x0064 }, +{ 0x65 , 0x0065 }, +{ 0x66 , 0x0066 }, +{ 0x67 , 0x0067 }, +{ 0x68 , 0x0068 }, +{ 0x69 , 0x0069 }, +{ 0x6a , 0x006A }, +{ 0x6b , 0x006B }, +{ 0x6c , 0x006C }, +{ 0x6d , 0x006D }, +{ 0x6e , 0x006E }, +{ 0x6f , 0x006F }, +{ 0x70 , 0x0070 }, +{ 0x71 , 0x0071 }, +{ 0x72 , 0x0072 }, +{ 0x73 , 0x0073 }, +{ 0x74 , 0x0074 }, +{ 0x75 , 0x0075 }, +{ 0x76 , 0x0076 }, +{ 0x77 , 0x0077 }, +{ 0x78 , 0x0078 }, +{ 0x79 , 0x0079 }, +{ 0x7a , 0x007A }, +{ 0x7b , 0x007B }, +{ 0x7c , 0x007C }, +{ 0x7d , 0x007D }, +{ 0x7e , 0x007E }, +{ 0x7f , 0x007F }, +{ 0x80 , 0x0080 }, +{ 0x81 , 0x0081 }, +{ 0x82 , 0x0082 }, +{ 0x83 , 0x0083 }, +{ 0x84 , 0x0084 }, +{ 0x85 , 0x0085 }, +{ 0x86 , 0x0086 }, +{ 0x87 , 0x0087 }, +{ 0x88 , 0x0088 }, +{ 0x89 , 0x0089 }, +{ 0x8a , 0x008A }, +{ 0x8b , 0x008B }, +{ 0x8c , 0x008C }, +{ 0x8d , 0x008D }, +{ 0x8e , 0x008E }, +{ 0x8f , 0x008F }, +{ 0x90 , 0x0090 }, +{ 0x91 , 0x0091 }, +{ 0x92 , 0x0092 }, +{ 0x93 , 0x0093 }, +{ 0x94 , 0x0094 }, +{ 0x95 , 0x0095 }, +{ 0x96 , 0x0096 }, +{ 0x97 , 0x0097 }, +{ 0x98 , 0x0098 }, +{ 0x99 , 0x0099 }, +{ 0x9a , 0x009A }, +{ 0x9b , 0x009B }, +{ 0x9c , 0x009C }, +{ 0x9d , 0x009D }, +{ 0x9e , 0x009E }, +{ 0x9f , 0x009F }, +{ 0xa0 , 0x00A0 }, +{ 0xa1 , 0x00A1 }, +{ 0xa2 , 0x00A2 }, +{ 0xa3 , 0x00A3 }, +{ 0xa4 , 0x20AC }, +{ 0xa5 , 0x00A5 }, +{ 0xa6 , 0x0160 }, +{ 0xa7 , 0x00A7 }, +{ 0xa8 , 0x0161 }, +{ 0xa9 , 0x00A9 }, +{ 0xaa , 0x00AA }, +{ 0xab , 0x00AB }, +{ 0xac , 0x00AC }, +{ 0xad , 0x00AD }, +{ 0xae , 0x00AE }, +{ 0xaf , 0x00AF }, +{ 0xb0 , 0x00B0 }, +{ 0xb1 , 0x00B1 }, +{ 0xb2 , 0x00B2 }, +{ 0xb3 , 0x00B3 }, +{ 0xb4 , 0x017D }, +{ 0xb5 , 0x00B5 }, +{ 0xb6 , 0x00B6 }, +{ 0xb7 , 0x00B7 }, +{ 0xb8 , 0x017E }, +{ 0xb9 , 0x00B9 }, +{ 0xba , 0x00BA }, +{ 0xbb , 0x00BB }, +{ 0xbc , 0x0152 }, +{ 0xbd , 0x0153 }, +{ 0xbe , 0x0178 }, +{ 0xbf , 0x00BF }, +{ 0xc0 , 0x00C0 }, +{ 0xc1 , 0x00C1 }, +{ 0xc2 , 0x00C2 }, +{ 0xc3 , 0x00C3 }, +{ 0xc4 , 0x00C4 }, +{ 0xc5 , 0x00C5 }, +{ 0xc6 , 0x00C6 }, +{ 0xc7 , 0x00C7 }, +{ 0xc8 , 0x00C8 }, +{ 0xc9 , 0x00C9 }, +{ 0xca , 0x00CA }, +{ 0xcb , 0x00CB }, +{ 0xcc , 0x00CC }, +{ 0xcd , 0x00CD }, +{ 0xce , 0x00CE }, +{ 0xcf , 0x00CF }, +{ 0xd0 , 0x00D0 }, +{ 0xd1 , 0x00D1 }, +{ 0xd2 , 0x00D2 }, +{ 0xd3 , 0x00D3 }, +{ 0xd4 , 0x00D4 }, +{ 0xd5 , 0x00D5 }, +{ 0xd6 , 0x00D6 }, +{ 0xd7 , 0x00D7 }, +{ 0xd8 , 0x00D8 }, +{ 0xd9 , 0x00D9 }, +{ 0xda , 0x00DA }, +{ 0xdb , 0x00DB }, +{ 0xdc , 0x00DC }, +{ 0xdd , 0x00DD }, +{ 0xde , 0x00DE }, +{ 0xdf , 0x00DF }, +{ 0xe0 , 0x00E0 }, +{ 0xe1 , 0x00E1 }, +{ 0xe2 , 0x00E2 }, +{ 0xe3 , 0x00E3 }, +{ 0xe4 , 0x00E4 }, +{ 0xe5 , 0x00E5 }, +{ 0xe6 , 0x00E6 }, +{ 0xe7 , 0x00E7 }, +{ 0xe8 , 0x00E8 }, +{ 0xe9 , 0x00E9 }, +{ 0xea , 0x00EA }, +{ 0xeb , 0x00EB }, +{ 0xec , 0x00EC }, +{ 0xed , 0x00ED }, +{ 0xee , 0x00EE }, +{ 0xef , 0x00EF }, +{ 0xf0 , 0x00F0 }, +{ 0xf1 , 0x00F1 }, +{ 0xf2 , 0x00F2 }, +{ 0xf3 , 0x00F3 }, +{ 0xf4 , 0x00F4 }, +{ 0xf5 , 0x00F5 }, +{ 0xf6 , 0x00F6 }, +{ 0xf7 , 0x00F7 }, +{ 0xf8 , 0x00F8 }, +{ 0xf9 , 0x00F9 }, +{ 0xfa , 0x00FA }, +{ 0xfb , 0x00FB }, +{ 0xfc , 0x00FC }, +{ 0xfd , 0x00FD }, +{ 0xfe , 0x00FE }, +{ 0xff , 0x00FF }, diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/ISO-8859-16.pairs b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/ISO-8859-16.pairs new file mode 100644 index 00000000..6b749639 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/ISO-8859-16.pairs @@ -0,0 +1,256 @@ +{ 0x00 , 0x0000 }, +{ 0x01 , 0x0001 }, +{ 0x02 , 0x0002 }, +{ 0x03 , 0x0003 }, +{ 0x04 , 0x0004 }, +{ 0x05 , 0x0005 }, +{ 0x06 , 0x0006 }, +{ 0x07 , 0x0007 }, +{ 0x08 , 0x0008 }, +{ 0x09 , 0x0009 }, +{ 0x0a , 0x000A }, +{ 0x0b , 0x000B }, +{ 0x0c , 0x000C }, +{ 0x0d , 0x000D }, +{ 0x0e , 0x000E }, +{ 0x0f , 0x000F }, +{ 0x10 , 0x0010 }, +{ 0x11 , 0x0011 }, +{ 0x12 , 0x0012 }, +{ 0x13 , 0x0013 }, +{ 0x14 , 0x0014 }, +{ 0x15 , 0x0015 }, +{ 0x16 , 0x0016 }, +{ 0x17 , 0x0017 }, +{ 0x18 , 0x0018 }, +{ 0x19 , 0x0019 }, +{ 0x1a , 0x001A }, +{ 0x1b , 0x001B }, +{ 0x1c , 0x001C }, +{ 0x1d , 0x001D }, +{ 0x1e , 0x001E }, +{ 0x1f , 0x001F }, +{ 0x20 , 0x0020 }, +{ 0x21 , 0x0021 }, +{ 0x22 , 0x0022 }, +{ 0x23 , 0x0023 }, +{ 0x24 , 0x0024 }, +{ 0x25 , 0x0025 }, +{ 0x26 , 0x0026 }, +{ 0x27 , 0x0027 }, +{ 0x28 , 0x0028 }, +{ 0x29 , 0x0029 }, +{ 0x2a , 0x002A }, +{ 0x2b , 0x002B }, +{ 0x2c , 0x002C }, +{ 0x2d , 0x002D }, +{ 0x2e , 0x002E }, +{ 0x2f , 0x002F }, +{ 0x30 , 0x0030 }, +{ 0x31 , 0x0031 }, +{ 0x32 , 0x0032 }, +{ 0x33 , 0x0033 }, +{ 0x34 , 0x0034 }, +{ 0x35 , 0x0035 }, +{ 0x36 , 0x0036 }, +{ 0x37 , 0x0037 }, +{ 0x38 , 0x0038 }, +{ 0x39 , 0x0039 }, +{ 0x3a , 0x003A }, +{ 0x3b , 0x003B }, +{ 0x3c , 0x003C }, +{ 0x3d , 0x003D }, +{ 0x3e , 0x003E }, +{ 0x3f , 0x003F }, +{ 0x40 , 0x0040 }, +{ 0x41 , 0x0041 }, +{ 0x42 , 0x0042 }, +{ 0x43 , 0x0043 }, +{ 0x44 , 0x0044 }, +{ 0x45 , 0x0045 }, +{ 0x46 , 0x0046 }, +{ 0x47 , 0x0047 }, +{ 0x48 , 0x0048 }, +{ 0x49 , 0x0049 }, +{ 0x4a , 0x004A }, +{ 0x4b , 0x004B }, +{ 0x4c , 0x004C }, +{ 0x4d , 0x004D }, +{ 0x4e , 0x004E }, +{ 0x4f , 0x004F }, +{ 0x50 , 0x0050 }, +{ 0x51 , 0x0051 }, +{ 0x52 , 0x0052 }, +{ 0x53 , 0x0053 }, +{ 0x54 , 0x0054 }, +{ 0x55 , 0x0055 }, +{ 0x56 , 0x0056 }, +{ 0x57 , 0x0057 }, +{ 0x58 , 0x0058 }, +{ 0x59 , 0x0059 }, +{ 0x5a , 0x005A }, +{ 0x5b , 0x005B }, +{ 0x5c , 0x005C }, +{ 0x5d , 0x005D }, +{ 0x5e , 0x005E }, +{ 0x5f , 0x005F }, +{ 0x60 , 0x0060 }, +{ 0x61 , 0x0061 }, +{ 0x62 , 0x0062 }, +{ 0x63 , 0x0063 }, +{ 0x64 , 0x0064 }, +{ 0x65 , 0x0065 }, +{ 0x66 , 0x0066 }, +{ 0x67 , 0x0067 }, +{ 0x68 , 0x0068 }, +{ 0x69 , 0x0069 }, +{ 0x6a , 0x006A }, +{ 0x6b , 0x006B }, +{ 0x6c , 0x006C }, +{ 0x6d , 0x006D }, +{ 0x6e , 0x006E }, +{ 0x6f , 0x006F }, +{ 0x70 , 0x0070 }, +{ 0x71 , 0x0071 }, +{ 0x72 , 0x0072 }, +{ 0x73 , 0x0073 }, +{ 0x74 , 0x0074 }, +{ 0x75 , 0x0075 }, +{ 0x76 , 0x0076 }, +{ 0x77 , 0x0077 }, +{ 0x78 , 0x0078 }, +{ 0x79 , 0x0079 }, +{ 0x7a , 0x007A }, +{ 0x7b , 0x007B }, +{ 0x7c , 0x007C }, +{ 0x7d , 0x007D }, +{ 0x7e , 0x007E }, +{ 0x7f , 0x007F }, +{ 0x80 , 0x0080 }, +{ 0x81 , 0x0081 }, +{ 0x82 , 0x0082 }, +{ 0x83 , 0x0083 }, +{ 0x84 , 0x0084 }, +{ 0x85 , 0x0085 }, +{ 0x86 , 0x0086 }, +{ 0x87 , 0x0087 }, +{ 0x88 , 0x0088 }, +{ 0x89 , 0x0089 }, +{ 0x8a , 0x008A }, +{ 0x8b , 0x008B }, +{ 0x8c , 0x008C }, +{ 0x8d , 0x008D }, +{ 0x8e , 0x008E }, +{ 0x8f , 0x008F }, +{ 0x90 , 0x0090 }, +{ 0x91 , 0x0091 }, +{ 0x92 , 0x0092 }, +{ 0x93 , 0x0093 }, +{ 0x94 , 0x0094 }, +{ 0x95 , 0x0095 }, +{ 0x96 , 0x0096 }, +{ 0x97 , 0x0097 }, +{ 0x98 , 0x0098 }, +{ 0x99 , 0x0099 }, +{ 0x9a , 0x009A }, +{ 0x9b , 0x009B }, +{ 0x9c , 0x009C }, +{ 0x9d , 0x009D }, +{ 0x9e , 0x009E }, +{ 0x9f , 0x009F }, +{ 0xa0 , 0x00A0 }, +{ 0xa1 , 0x0104 }, +{ 0xa2 , 0x0105 }, +{ 0xa3 , 0x0141 }, +{ 0xa4 , 0x20AC }, +{ 0xa5 , 0x00AB }, +{ 0xa6 , 0x0160 }, +{ 0xa7 , 0x00A7 }, +{ 0xa8 , 0x0161 }, +{ 0xa9 , 0x00A9 }, +{ 0xaa , 0x0218 }, +{ 0xab , 0x201E }, +{ 0xac , 0x0179 }, +{ 0xad , 0x00AD }, +{ 0xae , 0x017A }, +{ 0xaf , 0x017B }, +{ 0xb0 , 0x00B0 }, +{ 0xb1 , 0x00B1 }, +{ 0xb2 , 0x010C }, +{ 0xb3 , 0x0142 }, +{ 0xb4 , 0x017D }, +{ 0xb5 , 0x201D }, +{ 0xb6 , 0x00B6 }, +{ 0xb7 , 0x00B7 }, +{ 0xb8 , 0x017E }, +{ 0xb9 , 0x010D }, +{ 0xba , 0x0219 }, +{ 0xbb , 0x00BB }, +{ 0xbc , 0x0152 }, +{ 0xbd , 0x0153 }, +{ 0xbe , 0x0178 }, +{ 0xbf , 0x017C }, +{ 0xc0 , 0x00C0 }, +{ 0xc1 , 0x00C1 }, +{ 0xc2 , 0x00C2 }, +{ 0xc3 , 0x0102 }, +{ 0xc4 , 0x00C4 }, +{ 0xc5 , 0x0106 }, +{ 0xc6 , 0x00C6 }, +{ 0xc7 , 0x00C7 }, +{ 0xc8 , 0x00C8 }, +{ 0xc9 , 0x00C9 }, +{ 0xca , 0x00CA }, +{ 0xcb , 0x00CB }, +{ 0xcc , 0x00CC }, +{ 0xcd , 0x00CD }, +{ 0xce , 0x00CE }, +{ 0xcf , 0x00CF }, +{ 0xd0 , 0x0110 }, +{ 0xd1 , 0x0143 }, +{ 0xd2 , 0x00D2 }, +{ 0xd3 , 0x00D3 }, +{ 0xd4 , 0x00D4 }, +{ 0xd5 , 0x0150 }, +{ 0xd6 , 0x00D6 }, +{ 0xd7 , 0x015A }, +{ 0xd8 , 0x0170 }, +{ 0xd9 , 0x00D9 }, +{ 0xda , 0x00DA }, +{ 0xdb , 0x00DB }, +{ 0xdc , 0x00DC }, +{ 0xdd , 0x0118 }, +{ 0xde , 0x021A }, +{ 0xdf , 0x00DF }, +{ 0xe0 , 0x00E0 }, +{ 0xe1 , 0x00E1 }, +{ 0xe2 , 0x00E2 }, +{ 0xe3 , 0x0103 }, +{ 0xe4 , 0x00E4 }, +{ 0xe5 , 0x0107 }, +{ 0xe6 , 0x00E6 }, +{ 0xe7 , 0x00E7 }, +{ 0xe8 , 0x00E8 }, +{ 0xe9 , 0x00E9 }, +{ 0xea , 0x00EA }, +{ 0xeb , 0x00EB }, +{ 0xec , 0x00EC }, +{ 0xed , 0x00ED }, +{ 0xee , 0x00EE }, +{ 0xef , 0x00EF }, +{ 0xf0 , 0x0111 }, +{ 0xf1 , 0x0144 }, +{ 0xf2 , 0x00F2 }, +{ 0xf3 , 0x00F3 }, +{ 0xf4 , 0x00F4 }, +{ 0xf5 , 0x0151 }, +{ 0xf6 , 0x00F6 }, +{ 0xf7 , 0x015B }, +{ 0xf8 , 0x0171 }, +{ 0xf9 , 0x00F9 }, +{ 0xfa , 0x00FA }, +{ 0xfb , 0x00FB }, +{ 0xfc , 0x00FC }, +{ 0xfd , 0x0119 }, +{ 0xfe , 0x021B }, +{ 0xff , 0x00FF }, diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/ISO-8859-2.pairs b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/ISO-8859-2.pairs new file mode 100644 index 00000000..4e92f943 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/ISO-8859-2.pairs @@ -0,0 +1,256 @@ +{ 0x00 , 0x0000 }, +{ 0x01 , 0x0001 }, +{ 0x02 , 0x0002 }, +{ 0x03 , 0x0003 }, +{ 0x04 , 0x0004 }, +{ 0x05 , 0x0005 }, +{ 0x06 , 0x0006 }, +{ 0x07 , 0x0007 }, +{ 0x08 , 0x0008 }, +{ 0x09 , 0x0009 }, +{ 0x0a , 0x000A }, +{ 0x0b , 0x000B }, +{ 0x0c , 0x000C }, +{ 0x0d , 0x000D }, +{ 0x0e , 0x000E }, +{ 0x0f , 0x000F }, +{ 0x10 , 0x0010 }, +{ 0x11 , 0x0011 }, +{ 0x12 , 0x0012 }, +{ 0x13 , 0x0013 }, +{ 0x14 , 0x0014 }, +{ 0x15 , 0x0015 }, +{ 0x16 , 0x0016 }, +{ 0x17 , 0x0017 }, +{ 0x18 , 0x0018 }, +{ 0x19 , 0x0019 }, +{ 0x1a , 0x001A }, +{ 0x1b , 0x001B }, +{ 0x1c , 0x001C }, +{ 0x1d , 0x001D }, +{ 0x1e , 0x001E }, +{ 0x1f , 0x001F }, +{ 0x20 , 0x0020 }, +{ 0x21 , 0x0021 }, +{ 0x22 , 0x0022 }, +{ 0x23 , 0x0023 }, +{ 0x24 , 0x0024 }, +{ 0x25 , 0x0025 }, +{ 0x26 , 0x0026 }, +{ 0x27 , 0x0027 }, +{ 0x28 , 0x0028 }, +{ 0x29 , 0x0029 }, +{ 0x2a , 0x002A }, +{ 0x2b , 0x002B }, +{ 0x2c , 0x002C }, +{ 0x2d , 0x002D }, +{ 0x2e , 0x002E }, +{ 0x2f , 0x002F }, +{ 0x30 , 0x0030 }, +{ 0x31 , 0x0031 }, +{ 0x32 , 0x0032 }, +{ 0x33 , 0x0033 }, +{ 0x34 , 0x0034 }, +{ 0x35 , 0x0035 }, +{ 0x36 , 0x0036 }, +{ 0x37 , 0x0037 }, +{ 0x38 , 0x0038 }, +{ 0x39 , 0x0039 }, +{ 0x3a , 0x003A }, +{ 0x3b , 0x003B }, +{ 0x3c , 0x003C }, +{ 0x3d , 0x003D }, +{ 0x3e , 0x003E }, +{ 0x3f , 0x003F }, +{ 0x40 , 0x0040 }, +{ 0x41 , 0x0041 }, +{ 0x42 , 0x0042 }, +{ 0x43 , 0x0043 }, +{ 0x44 , 0x0044 }, +{ 0x45 , 0x0045 }, +{ 0x46 , 0x0046 }, +{ 0x47 , 0x0047 }, +{ 0x48 , 0x0048 }, +{ 0x49 , 0x0049 }, +{ 0x4a , 0x004A }, +{ 0x4b , 0x004B }, +{ 0x4c , 0x004C }, +{ 0x4d , 0x004D }, +{ 0x4e , 0x004E }, +{ 0x4f , 0x004F }, +{ 0x50 , 0x0050 }, +{ 0x51 , 0x0051 }, +{ 0x52 , 0x0052 }, +{ 0x53 , 0x0053 }, +{ 0x54 , 0x0054 }, +{ 0x55 , 0x0055 }, +{ 0x56 , 0x0056 }, +{ 0x57 , 0x0057 }, +{ 0x58 , 0x0058 }, +{ 0x59 , 0x0059 }, +{ 0x5a , 0x005A }, +{ 0x5b , 0x005B }, +{ 0x5c , 0x005C }, +{ 0x5d , 0x005D }, +{ 0x5e , 0x005E }, +{ 0x5f , 0x005F }, +{ 0x60 , 0x0060 }, +{ 0x61 , 0x0061 }, +{ 0x62 , 0x0062 }, +{ 0x63 , 0x0063 }, +{ 0x64 , 0x0064 }, +{ 0x65 , 0x0065 }, +{ 0x66 , 0x0066 }, +{ 0x67 , 0x0067 }, +{ 0x68 , 0x0068 }, +{ 0x69 , 0x0069 }, +{ 0x6a , 0x006A }, +{ 0x6b , 0x006B }, +{ 0x6c , 0x006C }, +{ 0x6d , 0x006D }, +{ 0x6e , 0x006E }, +{ 0x6f , 0x006F }, +{ 0x70 , 0x0070 }, +{ 0x71 , 0x0071 }, +{ 0x72 , 0x0072 }, +{ 0x73 , 0x0073 }, +{ 0x74 , 0x0074 }, +{ 0x75 , 0x0075 }, +{ 0x76 , 0x0076 }, +{ 0x77 , 0x0077 }, +{ 0x78 , 0x0078 }, +{ 0x79 , 0x0079 }, +{ 0x7a , 0x007A }, +{ 0x7b , 0x007B }, +{ 0x7c , 0x007C }, +{ 0x7d , 0x007D }, +{ 0x7e , 0x007E }, +{ 0x7f , 0x007F }, +{ 0x80 , 0x0080 }, +{ 0x81 , 0x0081 }, +{ 0x82 , 0x0082 }, +{ 0x83 , 0x0083 }, +{ 0x84 , 0x0084 }, +{ 0x85 , 0x0085 }, +{ 0x86 , 0x0086 }, +{ 0x87 , 0x0087 }, +{ 0x88 , 0x0088 }, +{ 0x89 , 0x0089 }, +{ 0x8a , 0x008A }, +{ 0x8b , 0x008B }, +{ 0x8c , 0x008C }, +{ 0x8d , 0x008D }, +{ 0x8e , 0x008E }, +{ 0x8f , 0x008F }, +{ 0x90 , 0x0090 }, +{ 0x91 , 0x0091 }, +{ 0x92 , 0x0092 }, +{ 0x93 , 0x0093 }, +{ 0x94 , 0x0094 }, +{ 0x95 , 0x0095 }, +{ 0x96 , 0x0096 }, +{ 0x97 , 0x0097 }, +{ 0x98 , 0x0098 }, +{ 0x99 , 0x0099 }, +{ 0x9a , 0x009A }, +{ 0x9b , 0x009B }, +{ 0x9c , 0x009C }, +{ 0x9d , 0x009D }, +{ 0x9e , 0x009E }, +{ 0x9f , 0x009F }, +{ 0xa0 , 0x00A0 }, +{ 0xa1 , 0x0104 }, +{ 0xa2 , 0x02D8 }, +{ 0xa3 , 0x0141 }, +{ 0xa4 , 0x00A4 }, +{ 0xa5 , 0x013D }, +{ 0xa6 , 0x015A }, +{ 0xa7 , 0x00A7 }, +{ 0xa8 , 0x00A8 }, +{ 0xa9 , 0x0160 }, +{ 0xaa , 0x015E }, +{ 0xab , 0x0164 }, +{ 0xac , 0x0179 }, +{ 0xad , 0x00AD }, +{ 0xae , 0x017D }, +{ 0xaf , 0x017B }, +{ 0xb0 , 0x00B0 }, +{ 0xb1 , 0x0105 }, +{ 0xb2 , 0x02DB }, +{ 0xb3 , 0x0142 }, +{ 0xb4 , 0x00B4 }, +{ 0xb5 , 0x013E }, +{ 0xb6 , 0x015B }, +{ 0xb7 , 0x02C7 }, +{ 0xb8 , 0x00B8 }, +{ 0xb9 , 0x0161 }, +{ 0xba , 0x015F }, +{ 0xbb , 0x0165 }, +{ 0xbc , 0x017A }, +{ 0xbd , 0x02DD }, +{ 0xbe , 0x017E }, +{ 0xbf , 0x017C }, +{ 0xc0 , 0x0154 }, +{ 0xc1 , 0x00C1 }, +{ 0xc2 , 0x00C2 }, +{ 0xc3 , 0x0102 }, +{ 0xc4 , 0x00C4 }, +{ 0xc5 , 0x0139 }, +{ 0xc6 , 0x0106 }, +{ 0xc7 , 0x00C7 }, +{ 0xc8 , 0x010C }, +{ 0xc9 , 0x00C9 }, +{ 0xca , 0x0118 }, +{ 0xcb , 0x00CB }, +{ 0xcc , 0x011A }, +{ 0xcd , 0x00CD }, +{ 0xce , 0x00CE }, +{ 0xcf , 0x010E }, +{ 0xd0 , 0x0110 }, +{ 0xd1 , 0x0143 }, +{ 0xd2 , 0x0147 }, +{ 0xd3 , 0x00D3 }, +{ 0xd4 , 0x00D4 }, +{ 0xd5 , 0x0150 }, +{ 0xd6 , 0x00D6 }, +{ 0xd7 , 0x00D7 }, +{ 0xd8 , 0x0158 }, +{ 0xd9 , 0x016E }, +{ 0xda , 0x00DA }, +{ 0xdb , 0x0170 }, +{ 0xdc , 0x00DC }, +{ 0xdd , 0x00DD }, +{ 0xde , 0x0162 }, +{ 0xdf , 0x00DF }, +{ 0xe0 , 0x0155 }, +{ 0xe1 , 0x00E1 }, +{ 0xe2 , 0x00E2 }, +{ 0xe3 , 0x0103 }, +{ 0xe4 , 0x00E4 }, +{ 0xe5 , 0x013A }, +{ 0xe6 , 0x0107 }, +{ 0xe7 , 0x00E7 }, +{ 0xe8 , 0x010D }, +{ 0xe9 , 0x00E9 }, +{ 0xea , 0x0119 }, +{ 0xeb , 0x00EB }, +{ 0xec , 0x011B }, +{ 0xed , 0x00ED }, +{ 0xee , 0x00EE }, +{ 0xef , 0x010F }, +{ 0xf0 , 0x0111 }, +{ 0xf1 , 0x0144 }, +{ 0xf2 , 0x0148 }, +{ 0xf3 , 0x00F3 }, +{ 0xf4 , 0x00F4 }, +{ 0xf5 , 0x0151 }, +{ 0xf6 , 0x00F6 }, +{ 0xf7 , 0x00F7 }, +{ 0xf8 , 0x0159 }, +{ 0xf9 , 0x016F }, +{ 0xfa , 0x00FA }, +{ 0xfb , 0x0171 }, +{ 0xfc , 0x00FC }, +{ 0xfd , 0x00FD }, +{ 0xfe , 0x0163 }, +{ 0xff , 0x02D9 }, diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/ISO-8859-3.pairs b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/ISO-8859-3.pairs new file mode 100644 index 00000000..3a8814cd --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/ISO-8859-3.pairs @@ -0,0 +1,249 @@ +{ 0x00 , 0x0000 }, +{ 0x01 , 0x0001 }, +{ 0x02 , 0x0002 }, +{ 0x03 , 0x0003 }, +{ 0x04 , 0x0004 }, +{ 0x05 , 0x0005 }, +{ 0x06 , 0x0006 }, +{ 0x07 , 0x0007 }, +{ 0x08 , 0x0008 }, +{ 0x09 , 0x0009 }, +{ 0x0a , 0x000A }, +{ 0x0b , 0x000B }, +{ 0x0c , 0x000C }, +{ 0x0d , 0x000D }, +{ 0x0e , 0x000E }, +{ 0x0f , 0x000F }, +{ 0x10 , 0x0010 }, +{ 0x11 , 0x0011 }, +{ 0x12 , 0x0012 }, +{ 0x13 , 0x0013 }, +{ 0x14 , 0x0014 }, +{ 0x15 , 0x0015 }, +{ 0x16 , 0x0016 }, +{ 0x17 , 0x0017 }, +{ 0x18 , 0x0018 }, +{ 0x19 , 0x0019 }, +{ 0x1a , 0x001A }, +{ 0x1b , 0x001B }, +{ 0x1c , 0x001C }, +{ 0x1d , 0x001D }, +{ 0x1e , 0x001E }, +{ 0x1f , 0x001F }, +{ 0x20 , 0x0020 }, +{ 0x21 , 0x0021 }, +{ 0x22 , 0x0022 }, +{ 0x23 , 0x0023 }, +{ 0x24 , 0x0024 }, +{ 0x25 , 0x0025 }, +{ 0x26 , 0x0026 }, +{ 0x27 , 0x0027 }, +{ 0x28 , 0x0028 }, +{ 0x29 , 0x0029 }, +{ 0x2a , 0x002A }, +{ 0x2b , 0x002B }, +{ 0x2c , 0x002C }, +{ 0x2d , 0x002D }, +{ 0x2e , 0x002E }, +{ 0x2f , 0x002F }, +{ 0x30 , 0x0030 }, +{ 0x31 , 0x0031 }, +{ 0x32 , 0x0032 }, +{ 0x33 , 0x0033 }, +{ 0x34 , 0x0034 }, +{ 0x35 , 0x0035 }, +{ 0x36 , 0x0036 }, +{ 0x37 , 0x0037 }, +{ 0x38 , 0x0038 }, +{ 0x39 , 0x0039 }, +{ 0x3a , 0x003A }, +{ 0x3b , 0x003B }, +{ 0x3c , 0x003C }, +{ 0x3d , 0x003D }, +{ 0x3e , 0x003E }, +{ 0x3f , 0x003F }, +{ 0x40 , 0x0040 }, +{ 0x41 , 0x0041 }, +{ 0x42 , 0x0042 }, +{ 0x43 , 0x0043 }, +{ 0x44 , 0x0044 }, +{ 0x45 , 0x0045 }, +{ 0x46 , 0x0046 }, +{ 0x47 , 0x0047 }, +{ 0x48 , 0x0048 }, +{ 0x49 , 0x0049 }, +{ 0x4a , 0x004A }, +{ 0x4b , 0x004B }, +{ 0x4c , 0x004C }, +{ 0x4d , 0x004D }, +{ 0x4e , 0x004E }, +{ 0x4f , 0x004F }, +{ 0x50 , 0x0050 }, +{ 0x51 , 0x0051 }, +{ 0x52 , 0x0052 }, +{ 0x53 , 0x0053 }, +{ 0x54 , 0x0054 }, +{ 0x55 , 0x0055 }, +{ 0x56 , 0x0056 }, +{ 0x57 , 0x0057 }, +{ 0x58 , 0x0058 }, +{ 0x59 , 0x0059 }, +{ 0x5a , 0x005A }, +{ 0x5b , 0x005B }, +{ 0x5c , 0x005C }, +{ 0x5d , 0x005D }, +{ 0x5e , 0x005E }, +{ 0x5f , 0x005F }, +{ 0x60 , 0x0060 }, +{ 0x61 , 0x0061 }, +{ 0x62 , 0x0062 }, +{ 0x63 , 0x0063 }, +{ 0x64 , 0x0064 }, +{ 0x65 , 0x0065 }, +{ 0x66 , 0x0066 }, +{ 0x67 , 0x0067 }, +{ 0x68 , 0x0068 }, +{ 0x69 , 0x0069 }, +{ 0x6a , 0x006A }, +{ 0x6b , 0x006B }, +{ 0x6c , 0x006C }, +{ 0x6d , 0x006D }, +{ 0x6e , 0x006E }, +{ 0x6f , 0x006F }, +{ 0x70 , 0x0070 }, +{ 0x71 , 0x0071 }, +{ 0x72 , 0x0072 }, +{ 0x73 , 0x0073 }, +{ 0x74 , 0x0074 }, +{ 0x75 , 0x0075 }, +{ 0x76 , 0x0076 }, +{ 0x77 , 0x0077 }, +{ 0x78 , 0x0078 }, +{ 0x79 , 0x0079 }, +{ 0x7a , 0x007A }, +{ 0x7b , 0x007B }, +{ 0x7c , 0x007C }, +{ 0x7d , 0x007D }, +{ 0x7e , 0x007E }, +{ 0x7f , 0x007F }, +{ 0x80 , 0x0080 }, +{ 0x81 , 0x0081 }, +{ 0x82 , 0x0082 }, +{ 0x83 , 0x0083 }, +{ 0x84 , 0x0084 }, +{ 0x85 , 0x0085 }, +{ 0x86 , 0x0086 }, +{ 0x87 , 0x0087 }, +{ 0x88 , 0x0088 }, +{ 0x89 , 0x0089 }, +{ 0x8a , 0x008A }, +{ 0x8b , 0x008B }, +{ 0x8c , 0x008C }, +{ 0x8d , 0x008D }, +{ 0x8e , 0x008E }, +{ 0x8f , 0x008F }, +{ 0x90 , 0x0090 }, +{ 0x91 , 0x0091 }, +{ 0x92 , 0x0092 }, +{ 0x93 , 0x0093 }, +{ 0x94 , 0x0094 }, +{ 0x95 , 0x0095 }, +{ 0x96 , 0x0096 }, +{ 0x97 , 0x0097 }, +{ 0x98 , 0x0098 }, +{ 0x99 , 0x0099 }, +{ 0x9a , 0x009A }, +{ 0x9b , 0x009B }, +{ 0x9c , 0x009C }, +{ 0x9d , 0x009D }, +{ 0x9e , 0x009E }, +{ 0x9f , 0x009F }, +{ 0xa0 , 0x00A0 }, +{ 0xa1 , 0x0126 }, +{ 0xa2 , 0x02D8 }, +{ 0xa3 , 0x00A3 }, +{ 0xa4 , 0x00A4 }, +{ 0xa6 , 0x0124 }, +{ 0xa7 , 0x00A7 }, +{ 0xa8 , 0x00A8 }, +{ 0xa9 , 0x0130 }, +{ 0xaa , 0x015E }, +{ 0xab , 0x011E }, +{ 0xac , 0x0134 }, +{ 0xad , 0x00AD }, +{ 0xaf , 0x017B }, +{ 0xb0 , 0x00B0 }, +{ 0xb1 , 0x0127 }, +{ 0xb2 , 0x00B2 }, +{ 0xb3 , 0x00B3 }, +{ 0xb4 , 0x00B4 }, +{ 0xb5 , 0x00B5 }, +{ 0xb6 , 0x0125 }, +{ 0xb7 , 0x00B7 }, +{ 0xb8 , 0x00B8 }, +{ 0xb9 , 0x0131 }, +{ 0xba , 0x015F }, +{ 0xbb , 0x011F }, +{ 0xbc , 0x0135 }, +{ 0xbd , 0x00BD }, +{ 0xbf , 0x017C }, +{ 0xc0 , 0x00C0 }, +{ 0xc1 , 0x00C1 }, +{ 0xc2 , 0x00C2 }, +{ 0xc4 , 0x00C4 }, +{ 0xc5 , 0x010A }, +{ 0xc6 , 0x0108 }, +{ 0xc7 , 0x00C7 }, +{ 0xc8 , 0x00C8 }, +{ 0xc9 , 0x00C9 }, +{ 0xca , 0x00CA }, +{ 0xcb , 0x00CB }, +{ 0xcc , 0x00CC }, +{ 0xcd , 0x00CD }, +{ 0xce , 0x00CE }, +{ 0xcf , 0x00CF }, +{ 0xd1 , 0x00D1 }, +{ 0xd2 , 0x00D2 }, +{ 0xd3 , 0x00D3 }, +{ 0xd4 , 0x00D4 }, +{ 0xd5 , 0x0120 }, +{ 0xd6 , 0x00D6 }, +{ 0xd7 , 0x00D7 }, +{ 0xd8 , 0x011C }, +{ 0xd9 , 0x00D9 }, +{ 0xda , 0x00DA }, +{ 0xdb , 0x00DB }, +{ 0xdc , 0x00DC }, +{ 0xdd , 0x016C }, +{ 0xde , 0x015C }, +{ 0xdf , 0x00DF }, +{ 0xe0 , 0x00E0 }, +{ 0xe1 , 0x00E1 }, +{ 0xe2 , 0x00E2 }, +{ 0xe4 , 0x00E4 }, +{ 0xe5 , 0x010B }, +{ 0xe6 , 0x0109 }, +{ 0xe7 , 0x00E7 }, +{ 0xe8 , 0x00E8 }, +{ 0xe9 , 0x00E9 }, +{ 0xea , 0x00EA }, +{ 0xeb , 0x00EB }, +{ 0xec , 0x00EC }, +{ 0xed , 0x00ED }, +{ 0xee , 0x00EE }, +{ 0xef , 0x00EF }, +{ 0xf1 , 0x00F1 }, +{ 0xf2 , 0x00F2 }, +{ 0xf3 , 0x00F3 }, +{ 0xf4 , 0x00F4 }, +{ 0xf5 , 0x0121 }, +{ 0xf6 , 0x00F6 }, +{ 0xf7 , 0x00F7 }, +{ 0xf8 , 0x011D }, +{ 0xf9 , 0x00F9 }, +{ 0xfa , 0x00FA }, +{ 0xfb , 0x00FB }, +{ 0xfc , 0x00FC }, +{ 0xfd , 0x016D }, +{ 0xfe , 0x015D }, +{ 0xff , 0x02D9 }, diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/ISO-8859-4.pairs b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/ISO-8859-4.pairs new file mode 100644 index 00000000..dda865c3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/ISO-8859-4.pairs @@ -0,0 +1,256 @@ +{ 0x00 , 0x0000 }, +{ 0x01 , 0x0001 }, +{ 0x02 , 0x0002 }, +{ 0x03 , 0x0003 }, +{ 0x04 , 0x0004 }, +{ 0x05 , 0x0005 }, +{ 0x06 , 0x0006 }, +{ 0x07 , 0x0007 }, +{ 0x08 , 0x0008 }, +{ 0x09 , 0x0009 }, +{ 0x0a , 0x000A }, +{ 0x0b , 0x000B }, +{ 0x0c , 0x000C }, +{ 0x0d , 0x000D }, +{ 0x0e , 0x000E }, +{ 0x0f , 0x000F }, +{ 0x10 , 0x0010 }, +{ 0x11 , 0x0011 }, +{ 0x12 , 0x0012 }, +{ 0x13 , 0x0013 }, +{ 0x14 , 0x0014 }, +{ 0x15 , 0x0015 }, +{ 0x16 , 0x0016 }, +{ 0x17 , 0x0017 }, +{ 0x18 , 0x0018 }, +{ 0x19 , 0x0019 }, +{ 0x1a , 0x001A }, +{ 0x1b , 0x001B }, +{ 0x1c , 0x001C }, +{ 0x1d , 0x001D }, +{ 0x1e , 0x001E }, +{ 0x1f , 0x001F }, +{ 0x20 , 0x0020 }, +{ 0x21 , 0x0021 }, +{ 0x22 , 0x0022 }, +{ 0x23 , 0x0023 }, +{ 0x24 , 0x0024 }, +{ 0x25 , 0x0025 }, +{ 0x26 , 0x0026 }, +{ 0x27 , 0x0027 }, +{ 0x28 , 0x0028 }, +{ 0x29 , 0x0029 }, +{ 0x2a , 0x002A }, +{ 0x2b , 0x002B }, +{ 0x2c , 0x002C }, +{ 0x2d , 0x002D }, +{ 0x2e , 0x002E }, +{ 0x2f , 0x002F }, +{ 0x30 , 0x0030 }, +{ 0x31 , 0x0031 }, +{ 0x32 , 0x0032 }, +{ 0x33 , 0x0033 }, +{ 0x34 , 0x0034 }, +{ 0x35 , 0x0035 }, +{ 0x36 , 0x0036 }, +{ 0x37 , 0x0037 }, +{ 0x38 , 0x0038 }, +{ 0x39 , 0x0039 }, +{ 0x3a , 0x003A }, +{ 0x3b , 0x003B }, +{ 0x3c , 0x003C }, +{ 0x3d , 0x003D }, +{ 0x3e , 0x003E }, +{ 0x3f , 0x003F }, +{ 0x40 , 0x0040 }, +{ 0x41 , 0x0041 }, +{ 0x42 , 0x0042 }, +{ 0x43 , 0x0043 }, +{ 0x44 , 0x0044 }, +{ 0x45 , 0x0045 }, +{ 0x46 , 0x0046 }, +{ 0x47 , 0x0047 }, +{ 0x48 , 0x0048 }, +{ 0x49 , 0x0049 }, +{ 0x4a , 0x004A }, +{ 0x4b , 0x004B }, +{ 0x4c , 0x004C }, +{ 0x4d , 0x004D }, +{ 0x4e , 0x004E }, +{ 0x4f , 0x004F }, +{ 0x50 , 0x0050 }, +{ 0x51 , 0x0051 }, +{ 0x52 , 0x0052 }, +{ 0x53 , 0x0053 }, +{ 0x54 , 0x0054 }, +{ 0x55 , 0x0055 }, +{ 0x56 , 0x0056 }, +{ 0x57 , 0x0057 }, +{ 0x58 , 0x0058 }, +{ 0x59 , 0x0059 }, +{ 0x5a , 0x005A }, +{ 0x5b , 0x005B }, +{ 0x5c , 0x005C }, +{ 0x5d , 0x005D }, +{ 0x5e , 0x005E }, +{ 0x5f , 0x005F }, +{ 0x60 , 0x0060 }, +{ 0x61 , 0x0061 }, +{ 0x62 , 0x0062 }, +{ 0x63 , 0x0063 }, +{ 0x64 , 0x0064 }, +{ 0x65 , 0x0065 }, +{ 0x66 , 0x0066 }, +{ 0x67 , 0x0067 }, +{ 0x68 , 0x0068 }, +{ 0x69 , 0x0069 }, +{ 0x6a , 0x006A }, +{ 0x6b , 0x006B }, +{ 0x6c , 0x006C }, +{ 0x6d , 0x006D }, +{ 0x6e , 0x006E }, +{ 0x6f , 0x006F }, +{ 0x70 , 0x0070 }, +{ 0x71 , 0x0071 }, +{ 0x72 , 0x0072 }, +{ 0x73 , 0x0073 }, +{ 0x74 , 0x0074 }, +{ 0x75 , 0x0075 }, +{ 0x76 , 0x0076 }, +{ 0x77 , 0x0077 }, +{ 0x78 , 0x0078 }, +{ 0x79 , 0x0079 }, +{ 0x7a , 0x007A }, +{ 0x7b , 0x007B }, +{ 0x7c , 0x007C }, +{ 0x7d , 0x007D }, +{ 0x7e , 0x007E }, +{ 0x7f , 0x007F }, +{ 0x80 , 0x0080 }, +{ 0x81 , 0x0081 }, +{ 0x82 , 0x0082 }, +{ 0x83 , 0x0083 }, +{ 0x84 , 0x0084 }, +{ 0x85 , 0x0085 }, +{ 0x86 , 0x0086 }, +{ 0x87 , 0x0087 }, +{ 0x88 , 0x0088 }, +{ 0x89 , 0x0089 }, +{ 0x8a , 0x008A }, +{ 0x8b , 0x008B }, +{ 0x8c , 0x008C }, +{ 0x8d , 0x008D }, +{ 0x8e , 0x008E }, +{ 0x8f , 0x008F }, +{ 0x90 , 0x0090 }, +{ 0x91 , 0x0091 }, +{ 0x92 , 0x0092 }, +{ 0x93 , 0x0093 }, +{ 0x94 , 0x0094 }, +{ 0x95 , 0x0095 }, +{ 0x96 , 0x0096 }, +{ 0x97 , 0x0097 }, +{ 0x98 , 0x0098 }, +{ 0x99 , 0x0099 }, +{ 0x9a , 0x009A }, +{ 0x9b , 0x009B }, +{ 0x9c , 0x009C }, +{ 0x9d , 0x009D }, +{ 0x9e , 0x009E }, +{ 0x9f , 0x009F }, +{ 0xa0 , 0x00A0 }, +{ 0xa1 , 0x0104 }, +{ 0xa2 , 0x0138 }, +{ 0xa3 , 0x0156 }, +{ 0xa4 , 0x00A4 }, +{ 0xa5 , 0x0128 }, +{ 0xa6 , 0x013B }, +{ 0xa7 , 0x00A7 }, +{ 0xa8 , 0x00A8 }, +{ 0xa9 , 0x0160 }, +{ 0xaa , 0x0112 }, +{ 0xab , 0x0122 }, +{ 0xac , 0x0166 }, +{ 0xad , 0x00AD }, +{ 0xae , 0x017D }, +{ 0xaf , 0x00AF }, +{ 0xb0 , 0x00B0 }, +{ 0xb1 , 0x0105 }, +{ 0xb2 , 0x02DB }, +{ 0xb3 , 0x0157 }, +{ 0xb4 , 0x00B4 }, +{ 0xb5 , 0x0129 }, +{ 0xb6 , 0x013C }, +{ 0xb7 , 0x02C7 }, +{ 0xb8 , 0x00B8 }, +{ 0xb9 , 0x0161 }, +{ 0xba , 0x0113 }, +{ 0xbb , 0x0123 }, +{ 0xbc , 0x0167 }, +{ 0xbd , 0x014A }, +{ 0xbe , 0x017E }, +{ 0xbf , 0x014B }, +{ 0xc0 , 0x0100 }, +{ 0xc1 , 0x00C1 }, +{ 0xc2 , 0x00C2 }, +{ 0xc3 , 0x00C3 }, +{ 0xc4 , 0x00C4 }, +{ 0xc5 , 0x00C5 }, +{ 0xc6 , 0x00C6 }, +{ 0xc7 , 0x012E }, +{ 0xc8 , 0x010C }, +{ 0xc9 , 0x00C9 }, +{ 0xca , 0x0118 }, +{ 0xcb , 0x00CB }, +{ 0xcc , 0x0116 }, +{ 0xcd , 0x00CD }, +{ 0xce , 0x00CE }, +{ 0xcf , 0x012A }, +{ 0xd0 , 0x0110 }, +{ 0xd1 , 0x0145 }, +{ 0xd2 , 0x014C }, +{ 0xd3 , 0x0136 }, +{ 0xd4 , 0x00D4 }, +{ 0xd5 , 0x00D5 }, +{ 0xd6 , 0x00D6 }, +{ 0xd7 , 0x00D7 }, +{ 0xd8 , 0x00D8 }, +{ 0xd9 , 0x0172 }, +{ 0xda , 0x00DA }, +{ 0xdb , 0x00DB }, +{ 0xdc , 0x00DC }, +{ 0xdd , 0x0168 }, +{ 0xde , 0x016A }, +{ 0xdf , 0x00DF }, +{ 0xe0 , 0x0101 }, +{ 0xe1 , 0x00E1 }, +{ 0xe2 , 0x00E2 }, +{ 0xe3 , 0x00E3 }, +{ 0xe4 , 0x00E4 }, +{ 0xe5 , 0x00E5 }, +{ 0xe6 , 0x00E6 }, +{ 0xe7 , 0x012F }, +{ 0xe8 , 0x010D }, +{ 0xe9 , 0x00E9 }, +{ 0xea , 0x0119 }, +{ 0xeb , 0x00EB }, +{ 0xec , 0x0117 }, +{ 0xed , 0x00ED }, +{ 0xee , 0x00EE }, +{ 0xef , 0x012B }, +{ 0xf0 , 0x0111 }, +{ 0xf1 , 0x0146 }, +{ 0xf2 , 0x014D }, +{ 0xf3 , 0x0137 }, +{ 0xf4 , 0x00F4 }, +{ 0xf5 , 0x00F5 }, +{ 0xf6 , 0x00F6 }, +{ 0xf7 , 0x00F7 }, +{ 0xf8 , 0x00F8 }, +{ 0xf9 , 0x0173 }, +{ 0xfa , 0x00FA }, +{ 0xfb , 0x00FB }, +{ 0xfc , 0x00FC }, +{ 0xfd , 0x0169 }, +{ 0xfe , 0x016B }, +{ 0xff , 0x02D9 }, diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/ISO-8859-5.pairs b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/ISO-8859-5.pairs new file mode 100644 index 00000000..08ebcae4 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/ISO-8859-5.pairs @@ -0,0 +1,256 @@ +{ 0x00 , 0x0000 }, +{ 0x01 , 0x0001 }, +{ 0x02 , 0x0002 }, +{ 0x03 , 0x0003 }, +{ 0x04 , 0x0004 }, +{ 0x05 , 0x0005 }, +{ 0x06 , 0x0006 }, +{ 0x07 , 0x0007 }, +{ 0x08 , 0x0008 }, +{ 0x09 , 0x0009 }, +{ 0x0a , 0x000A }, +{ 0x0b , 0x000B }, +{ 0x0c , 0x000C }, +{ 0x0d , 0x000D }, +{ 0x0e , 0x000E }, +{ 0x0f , 0x000F }, +{ 0x10 , 0x0010 }, +{ 0x11 , 0x0011 }, +{ 0x12 , 0x0012 }, +{ 0x13 , 0x0013 }, +{ 0x14 , 0x0014 }, +{ 0x15 , 0x0015 }, +{ 0x16 , 0x0016 }, +{ 0x17 , 0x0017 }, +{ 0x18 , 0x0018 }, +{ 0x19 , 0x0019 }, +{ 0x1a , 0x001A }, +{ 0x1b , 0x001B }, +{ 0x1c , 0x001C }, +{ 0x1d , 0x001D }, +{ 0x1e , 0x001E }, +{ 0x1f , 0x001F }, +{ 0x20 , 0x0020 }, +{ 0x21 , 0x0021 }, +{ 0x22 , 0x0022 }, +{ 0x23 , 0x0023 }, +{ 0x24 , 0x0024 }, +{ 0x25 , 0x0025 }, +{ 0x26 , 0x0026 }, +{ 0x27 , 0x0027 }, +{ 0x28 , 0x0028 }, +{ 0x29 , 0x0029 }, +{ 0x2a , 0x002A }, +{ 0x2b , 0x002B }, +{ 0x2c , 0x002C }, +{ 0x2d , 0x002D }, +{ 0x2e , 0x002E }, +{ 0x2f , 0x002F }, +{ 0x30 , 0x0030 }, +{ 0x31 , 0x0031 }, +{ 0x32 , 0x0032 }, +{ 0x33 , 0x0033 }, +{ 0x34 , 0x0034 }, +{ 0x35 , 0x0035 }, +{ 0x36 , 0x0036 }, +{ 0x37 , 0x0037 }, +{ 0x38 , 0x0038 }, +{ 0x39 , 0x0039 }, +{ 0x3a , 0x003A }, +{ 0x3b , 0x003B }, +{ 0x3c , 0x003C }, +{ 0x3d , 0x003D }, +{ 0x3e , 0x003E }, +{ 0x3f , 0x003F }, +{ 0x40 , 0x0040 }, +{ 0x41 , 0x0041 }, +{ 0x42 , 0x0042 }, +{ 0x43 , 0x0043 }, +{ 0x44 , 0x0044 }, +{ 0x45 , 0x0045 }, +{ 0x46 , 0x0046 }, +{ 0x47 , 0x0047 }, +{ 0x48 , 0x0048 }, +{ 0x49 , 0x0049 }, +{ 0x4a , 0x004A }, +{ 0x4b , 0x004B }, +{ 0x4c , 0x004C }, +{ 0x4d , 0x004D }, +{ 0x4e , 0x004E }, +{ 0x4f , 0x004F }, +{ 0x50 , 0x0050 }, +{ 0x51 , 0x0051 }, +{ 0x52 , 0x0052 }, +{ 0x53 , 0x0053 }, +{ 0x54 , 0x0054 }, +{ 0x55 , 0x0055 }, +{ 0x56 , 0x0056 }, +{ 0x57 , 0x0057 }, +{ 0x58 , 0x0058 }, +{ 0x59 , 0x0059 }, +{ 0x5a , 0x005A }, +{ 0x5b , 0x005B }, +{ 0x5c , 0x005C }, +{ 0x5d , 0x005D }, +{ 0x5e , 0x005E }, +{ 0x5f , 0x005F }, +{ 0x60 , 0x0060 }, +{ 0x61 , 0x0061 }, +{ 0x62 , 0x0062 }, +{ 0x63 , 0x0063 }, +{ 0x64 , 0x0064 }, +{ 0x65 , 0x0065 }, +{ 0x66 , 0x0066 }, +{ 0x67 , 0x0067 }, +{ 0x68 , 0x0068 }, +{ 0x69 , 0x0069 }, +{ 0x6a , 0x006A }, +{ 0x6b , 0x006B }, +{ 0x6c , 0x006C }, +{ 0x6d , 0x006D }, +{ 0x6e , 0x006E }, +{ 0x6f , 0x006F }, +{ 0x70 , 0x0070 }, +{ 0x71 , 0x0071 }, +{ 0x72 , 0x0072 }, +{ 0x73 , 0x0073 }, +{ 0x74 , 0x0074 }, +{ 0x75 , 0x0075 }, +{ 0x76 , 0x0076 }, +{ 0x77 , 0x0077 }, +{ 0x78 , 0x0078 }, +{ 0x79 , 0x0079 }, +{ 0x7a , 0x007A }, +{ 0x7b , 0x007B }, +{ 0x7c , 0x007C }, +{ 0x7d , 0x007D }, +{ 0x7e , 0x007E }, +{ 0x7f , 0x007F }, +{ 0x80 , 0x0080 }, +{ 0x81 , 0x0081 }, +{ 0x82 , 0x0082 }, +{ 0x83 , 0x0083 }, +{ 0x84 , 0x0084 }, +{ 0x85 , 0x0085 }, +{ 0x86 , 0x0086 }, +{ 0x87 , 0x0087 }, +{ 0x88 , 0x0088 }, +{ 0x89 , 0x0089 }, +{ 0x8a , 0x008A }, +{ 0x8b , 0x008B }, +{ 0x8c , 0x008C }, +{ 0x8d , 0x008D }, +{ 0x8e , 0x008E }, +{ 0x8f , 0x008F }, +{ 0x90 , 0x0090 }, +{ 0x91 , 0x0091 }, +{ 0x92 , 0x0092 }, +{ 0x93 , 0x0093 }, +{ 0x94 , 0x0094 }, +{ 0x95 , 0x0095 }, +{ 0x96 , 0x0096 }, +{ 0x97 , 0x0097 }, +{ 0x98 , 0x0098 }, +{ 0x99 , 0x0099 }, +{ 0x9a , 0x009A }, +{ 0x9b , 0x009B }, +{ 0x9c , 0x009C }, +{ 0x9d , 0x009D }, +{ 0x9e , 0x009E }, +{ 0x9f , 0x009F }, +{ 0xa0 , 0x00A0 }, +{ 0xa1 , 0x0401 }, +{ 0xa2 , 0x0402 }, +{ 0xa3 , 0x0403 }, +{ 0xa4 , 0x0404 }, +{ 0xa5 , 0x0405 }, +{ 0xa6 , 0x0406 }, +{ 0xa7 , 0x0407 }, +{ 0xa8 , 0x0408 }, +{ 0xa9 , 0x0409 }, +{ 0xaa , 0x040A }, +{ 0xab , 0x040B }, +{ 0xac , 0x040C }, +{ 0xad , 0x00AD }, +{ 0xae , 0x040E }, +{ 0xaf , 0x040F }, +{ 0xb0 , 0x0410 }, +{ 0xb1 , 0x0411 }, +{ 0xb2 , 0x0412 }, +{ 0xb3 , 0x0413 }, +{ 0xb4 , 0x0414 }, +{ 0xb5 , 0x0415 }, +{ 0xb6 , 0x0416 }, +{ 0xb7 , 0x0417 }, +{ 0xb8 , 0x0418 }, +{ 0xb9 , 0x0419 }, +{ 0xba , 0x041A }, +{ 0xbb , 0x041B }, +{ 0xbc , 0x041C }, +{ 0xbd , 0x041D }, +{ 0xbe , 0x041E }, +{ 0xbf , 0x041F }, +{ 0xc0 , 0x0420 }, +{ 0xc1 , 0x0421 }, +{ 0xc2 , 0x0422 }, +{ 0xc3 , 0x0423 }, +{ 0xc4 , 0x0424 }, +{ 0xc5 , 0x0425 }, +{ 0xc6 , 0x0426 }, +{ 0xc7 , 0x0427 }, +{ 0xc8 , 0x0428 }, +{ 0xc9 , 0x0429 }, +{ 0xca , 0x042A }, +{ 0xcb , 0x042B }, +{ 0xcc , 0x042C }, +{ 0xcd , 0x042D }, +{ 0xce , 0x042E }, +{ 0xcf , 0x042F }, +{ 0xd0 , 0x0430 }, +{ 0xd1 , 0x0431 }, +{ 0xd2 , 0x0432 }, +{ 0xd3 , 0x0433 }, +{ 0xd4 , 0x0434 }, +{ 0xd5 , 0x0435 }, +{ 0xd6 , 0x0436 }, +{ 0xd7 , 0x0437 }, +{ 0xd8 , 0x0438 }, +{ 0xd9 , 0x0439 }, +{ 0xda , 0x043A }, +{ 0xdb , 0x043B }, +{ 0xdc , 0x043C }, +{ 0xdd , 0x043D }, +{ 0xde , 0x043E }, +{ 0xdf , 0x043F }, +{ 0xe0 , 0x0440 }, +{ 0xe1 , 0x0441 }, +{ 0xe2 , 0x0442 }, +{ 0xe3 , 0x0443 }, +{ 0xe4 , 0x0444 }, +{ 0xe5 , 0x0445 }, +{ 0xe6 , 0x0446 }, +{ 0xe7 , 0x0447 }, +{ 0xe8 , 0x0448 }, +{ 0xe9 , 0x0449 }, +{ 0xea , 0x044A }, +{ 0xeb , 0x044B }, +{ 0xec , 0x044C }, +{ 0xed , 0x044D }, +{ 0xee , 0x044E }, +{ 0xef , 0x044F }, +{ 0xf0 , 0x2116 }, +{ 0xf1 , 0x0451 }, +{ 0xf2 , 0x0452 }, +{ 0xf3 , 0x0453 }, +{ 0xf4 , 0x0454 }, +{ 0xf5 , 0x0455 }, +{ 0xf6 , 0x0456 }, +{ 0xf7 , 0x0457 }, +{ 0xf8 , 0x0458 }, +{ 0xf9 , 0x0459 }, +{ 0xfa , 0x045A }, +{ 0xfb , 0x045B }, +{ 0xfc , 0x045C }, +{ 0xfd , 0x00A7 }, +{ 0xfe , 0x045E }, +{ 0xff , 0x045F }, diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/ISO-8859-6.pairs b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/ISO-8859-6.pairs new file mode 100644 index 00000000..ccba9f90 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/ISO-8859-6.pairs @@ -0,0 +1,211 @@ +{ 0x00 , 0x0000 }, +{ 0x01 , 0x0001 }, +{ 0x02 , 0x0002 }, +{ 0x03 , 0x0003 }, +{ 0x04 , 0x0004 }, +{ 0x05 , 0x0005 }, +{ 0x06 , 0x0006 }, +{ 0x07 , 0x0007 }, +{ 0x08 , 0x0008 }, +{ 0x09 , 0x0009 }, +{ 0x0a , 0x000A }, +{ 0x0b , 0x000B }, +{ 0x0c , 0x000C }, +{ 0x0d , 0x000D }, +{ 0x0e , 0x000E }, +{ 0x0f , 0x000F }, +{ 0x10 , 0x0010 }, +{ 0x11 , 0x0011 }, +{ 0x12 , 0x0012 }, +{ 0x13 , 0x0013 }, +{ 0x14 , 0x0014 }, +{ 0x15 , 0x0015 }, +{ 0x16 , 0x0016 }, +{ 0x17 , 0x0017 }, +{ 0x18 , 0x0018 }, +{ 0x19 , 0x0019 }, +{ 0x1a , 0x001A }, +{ 0x1b , 0x001B }, +{ 0x1c , 0x001C }, +{ 0x1d , 0x001D }, +{ 0x1e , 0x001E }, +{ 0x1f , 0x001F }, +{ 0x20 , 0x0020 }, +{ 0x21 , 0x0021 }, +{ 0x22 , 0x0022 }, +{ 0x23 , 0x0023 }, +{ 0x24 , 0x0024 }, +{ 0x25 , 0x0025 }, +{ 0x26 , 0x0026 }, +{ 0x27 , 0x0027 }, +{ 0x28 , 0x0028 }, +{ 0x29 , 0x0029 }, +{ 0x2a , 0x002A }, +{ 0x2b , 0x002B }, +{ 0x2c , 0x002C }, +{ 0x2d , 0x002D }, +{ 0x2e , 0x002E }, +{ 0x2f , 0x002F }, +{ 0x30 , 0x0030 }, +{ 0x31 , 0x0031 }, +{ 0x32 , 0x0032 }, +{ 0x33 , 0x0033 }, +{ 0x34 , 0x0034 }, +{ 0x35 , 0x0035 }, +{ 0x36 , 0x0036 }, +{ 0x37 , 0x0037 }, +{ 0x38 , 0x0038 }, +{ 0x39 , 0x0039 }, +{ 0x3a , 0x003A }, +{ 0x3b , 0x003B }, +{ 0x3c , 0x003C }, +{ 0x3d , 0x003D }, +{ 0x3e , 0x003E }, +{ 0x3f , 0x003F }, +{ 0x40 , 0x0040 }, +{ 0x41 , 0x0041 }, +{ 0x42 , 0x0042 }, +{ 0x43 , 0x0043 }, +{ 0x44 , 0x0044 }, +{ 0x45 , 0x0045 }, +{ 0x46 , 0x0046 }, +{ 0x47 , 0x0047 }, +{ 0x48 , 0x0048 }, +{ 0x49 , 0x0049 }, +{ 0x4a , 0x004A }, +{ 0x4b , 0x004B }, +{ 0x4c , 0x004C }, +{ 0x4d , 0x004D }, +{ 0x4e , 0x004E }, +{ 0x4f , 0x004F }, +{ 0x50 , 0x0050 }, +{ 0x51 , 0x0051 }, +{ 0x52 , 0x0052 }, +{ 0x53 , 0x0053 }, +{ 0x54 , 0x0054 }, +{ 0x55 , 0x0055 }, +{ 0x56 , 0x0056 }, +{ 0x57 , 0x0057 }, +{ 0x58 , 0x0058 }, +{ 0x59 , 0x0059 }, +{ 0x5a , 0x005A }, +{ 0x5b , 0x005B }, +{ 0x5c , 0x005C }, +{ 0x5d , 0x005D }, +{ 0x5e , 0x005E }, +{ 0x5f , 0x005F }, +{ 0x60 , 0x0060 }, +{ 0x61 , 0x0061 }, +{ 0x62 , 0x0062 }, +{ 0x63 , 0x0063 }, +{ 0x64 , 0x0064 }, +{ 0x65 , 0x0065 }, +{ 0x66 , 0x0066 }, +{ 0x67 , 0x0067 }, +{ 0x68 , 0x0068 }, +{ 0x69 , 0x0069 }, +{ 0x6a , 0x006A }, +{ 0x6b , 0x006B }, +{ 0x6c , 0x006C }, +{ 0x6d , 0x006D }, +{ 0x6e , 0x006E }, +{ 0x6f , 0x006F }, +{ 0x70 , 0x0070 }, +{ 0x71 , 0x0071 }, +{ 0x72 , 0x0072 }, +{ 0x73 , 0x0073 }, +{ 0x74 , 0x0074 }, +{ 0x75 , 0x0075 }, +{ 0x76 , 0x0076 }, +{ 0x77 , 0x0077 }, +{ 0x78 , 0x0078 }, +{ 0x79 , 0x0079 }, +{ 0x7a , 0x007A }, +{ 0x7b , 0x007B }, +{ 0x7c , 0x007C }, +{ 0x7d , 0x007D }, +{ 0x7e , 0x007E }, +{ 0x7f , 0x007F }, +{ 0x80 , 0x0080 }, +{ 0x81 , 0x0081 }, +{ 0x82 , 0x0082 }, +{ 0x83 , 0x0083 }, +{ 0x84 , 0x0084 }, +{ 0x85 , 0x0085 }, +{ 0x86 , 0x0086 }, +{ 0x87 , 0x0087 }, +{ 0x88 , 0x0088 }, +{ 0x89 , 0x0089 }, +{ 0x8a , 0x008A }, +{ 0x8b , 0x008B }, +{ 0x8c , 0x008C }, +{ 0x8d , 0x008D }, +{ 0x8e , 0x008E }, +{ 0x8f , 0x008F }, +{ 0x90 , 0x0090 }, +{ 0x91 , 0x0091 }, +{ 0x92 , 0x0092 }, +{ 0x93 , 0x0093 }, +{ 0x94 , 0x0094 }, +{ 0x95 , 0x0095 }, +{ 0x96 , 0x0096 }, +{ 0x97 , 0x0097 }, +{ 0x98 , 0x0098 }, +{ 0x99 , 0x0099 }, +{ 0x9a , 0x009A }, +{ 0x9b , 0x009B }, +{ 0x9c , 0x009C }, +{ 0x9d , 0x009D }, +{ 0x9e , 0x009E }, +{ 0x9f , 0x009F }, +{ 0xa0 , 0x00A0 }, +{ 0xa4 , 0x00A4 }, +{ 0xac , 0x060C }, +{ 0xad , 0x00AD }, +{ 0xbb , 0x061B }, +{ 0xbf , 0x061F }, +{ 0xc1 , 0x0621 }, +{ 0xc2 , 0x0622 }, +{ 0xc3 , 0x0623 }, +{ 0xc4 , 0x0624 }, +{ 0xc5 , 0x0625 }, +{ 0xc6 , 0x0626 }, +{ 0xc7 , 0x0627 }, +{ 0xc8 , 0x0628 }, +{ 0xc9 , 0x0629 }, +{ 0xca , 0x062A }, +{ 0xcb , 0x062B }, +{ 0xcc , 0x062C }, +{ 0xcd , 0x062D }, +{ 0xce , 0x062E }, +{ 0xcf , 0x062F }, +{ 0xd0 , 0x0630 }, +{ 0xd1 , 0x0631 }, +{ 0xd2 , 0x0632 }, +{ 0xd3 , 0x0633 }, +{ 0xd4 , 0x0634 }, +{ 0xd5 , 0x0635 }, +{ 0xd6 , 0x0636 }, +{ 0xd7 , 0x0637 }, +{ 0xd8 , 0x0638 }, +{ 0xd9 , 0x0639 }, +{ 0xda , 0x063A }, +{ 0xe0 , 0x0640 }, +{ 0xe1 , 0x0641 }, +{ 0xe2 , 0x0642 }, +{ 0xe3 , 0x0643 }, +{ 0xe4 , 0x0644 }, +{ 0xe5 , 0x0645 }, +{ 0xe6 , 0x0646 }, +{ 0xe7 , 0x0647 }, +{ 0xe8 , 0x0648 }, +{ 0xe9 , 0x0649 }, +{ 0xea , 0x064A }, +{ 0xeb , 0x064B }, +{ 0xec , 0x064C }, +{ 0xed , 0x064D }, +{ 0xee , 0x064E }, +{ 0xef , 0x064F }, +{ 0xf0 , 0x0650 }, +{ 0xf1 , 0x0651 }, +{ 0xf2 , 0x0652 }, diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/ISO-8859-7.pairs b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/ISO-8859-7.pairs new file mode 100644 index 00000000..36b8ba24 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/ISO-8859-7.pairs @@ -0,0 +1,250 @@ +{ 0x00 , 0x0000 }, +{ 0x01 , 0x0001 }, +{ 0x02 , 0x0002 }, +{ 0x03 , 0x0003 }, +{ 0x04 , 0x0004 }, +{ 0x05 , 0x0005 }, +{ 0x06 , 0x0006 }, +{ 0x07 , 0x0007 }, +{ 0x08 , 0x0008 }, +{ 0x09 , 0x0009 }, +{ 0x0a , 0x000A }, +{ 0x0b , 0x000B }, +{ 0x0c , 0x000C }, +{ 0x0d , 0x000D }, +{ 0x0e , 0x000E }, +{ 0x0f , 0x000F }, +{ 0x10 , 0x0010 }, +{ 0x11 , 0x0011 }, +{ 0x12 , 0x0012 }, +{ 0x13 , 0x0013 }, +{ 0x14 , 0x0014 }, +{ 0x15 , 0x0015 }, +{ 0x16 , 0x0016 }, +{ 0x17 , 0x0017 }, +{ 0x18 , 0x0018 }, +{ 0x19 , 0x0019 }, +{ 0x1a , 0x001A }, +{ 0x1b , 0x001B }, +{ 0x1c , 0x001C }, +{ 0x1d , 0x001D }, +{ 0x1e , 0x001E }, +{ 0x1f , 0x001F }, +{ 0x20 , 0x0020 }, +{ 0x21 , 0x0021 }, +{ 0x22 , 0x0022 }, +{ 0x23 , 0x0023 }, +{ 0x24 , 0x0024 }, +{ 0x25 , 0x0025 }, +{ 0x26 , 0x0026 }, +{ 0x27 , 0x0027 }, +{ 0x28 , 0x0028 }, +{ 0x29 , 0x0029 }, +{ 0x2a , 0x002A }, +{ 0x2b , 0x002B }, +{ 0x2c , 0x002C }, +{ 0x2d , 0x002D }, +{ 0x2e , 0x002E }, +{ 0x2f , 0x002F }, +{ 0x30 , 0x0030 }, +{ 0x31 , 0x0031 }, +{ 0x32 , 0x0032 }, +{ 0x33 , 0x0033 }, +{ 0x34 , 0x0034 }, +{ 0x35 , 0x0035 }, +{ 0x36 , 0x0036 }, +{ 0x37 , 0x0037 }, +{ 0x38 , 0x0038 }, +{ 0x39 , 0x0039 }, +{ 0x3a , 0x003A }, +{ 0x3b , 0x003B }, +{ 0x3c , 0x003C }, +{ 0x3d , 0x003D }, +{ 0x3e , 0x003E }, +{ 0x3f , 0x003F }, +{ 0x40 , 0x0040 }, +{ 0x41 , 0x0041 }, +{ 0x42 , 0x0042 }, +{ 0x43 , 0x0043 }, +{ 0x44 , 0x0044 }, +{ 0x45 , 0x0045 }, +{ 0x46 , 0x0046 }, +{ 0x47 , 0x0047 }, +{ 0x48 , 0x0048 }, +{ 0x49 , 0x0049 }, +{ 0x4a , 0x004A }, +{ 0x4b , 0x004B }, +{ 0x4c , 0x004C }, +{ 0x4d , 0x004D }, +{ 0x4e , 0x004E }, +{ 0x4f , 0x004F }, +{ 0x50 , 0x0050 }, +{ 0x51 , 0x0051 }, +{ 0x52 , 0x0052 }, +{ 0x53 , 0x0053 }, +{ 0x54 , 0x0054 }, +{ 0x55 , 0x0055 }, +{ 0x56 , 0x0056 }, +{ 0x57 , 0x0057 }, +{ 0x58 , 0x0058 }, +{ 0x59 , 0x0059 }, +{ 0x5a , 0x005A }, +{ 0x5b , 0x005B }, +{ 0x5c , 0x005C }, +{ 0x5d , 0x005D }, +{ 0x5e , 0x005E }, +{ 0x5f , 0x005F }, +{ 0x60 , 0x0060 }, +{ 0x61 , 0x0061 }, +{ 0x62 , 0x0062 }, +{ 0x63 , 0x0063 }, +{ 0x64 , 0x0064 }, +{ 0x65 , 0x0065 }, +{ 0x66 , 0x0066 }, +{ 0x67 , 0x0067 }, +{ 0x68 , 0x0068 }, +{ 0x69 , 0x0069 }, +{ 0x6a , 0x006A }, +{ 0x6b , 0x006B }, +{ 0x6c , 0x006C }, +{ 0x6d , 0x006D }, +{ 0x6e , 0x006E }, +{ 0x6f , 0x006F }, +{ 0x70 , 0x0070 }, +{ 0x71 , 0x0071 }, +{ 0x72 , 0x0072 }, +{ 0x73 , 0x0073 }, +{ 0x74 , 0x0074 }, +{ 0x75 , 0x0075 }, +{ 0x76 , 0x0076 }, +{ 0x77 , 0x0077 }, +{ 0x78 , 0x0078 }, +{ 0x79 , 0x0079 }, +{ 0x7a , 0x007A }, +{ 0x7b , 0x007B }, +{ 0x7c , 0x007C }, +{ 0x7d , 0x007D }, +{ 0x7e , 0x007E }, +{ 0x7f , 0x007F }, +{ 0x80 , 0x0080 }, +{ 0x81 , 0x0081 }, +{ 0x82 , 0x0082 }, +{ 0x83 , 0x0083 }, +{ 0x84 , 0x0084 }, +{ 0x85 , 0x0085 }, +{ 0x86 , 0x0086 }, +{ 0x87 , 0x0087 }, +{ 0x88 , 0x0088 }, +{ 0x89 , 0x0089 }, +{ 0x8a , 0x008A }, +{ 0x8b , 0x008B }, +{ 0x8c , 0x008C }, +{ 0x8d , 0x008D }, +{ 0x8e , 0x008E }, +{ 0x8f , 0x008F }, +{ 0x90 , 0x0090 }, +{ 0x91 , 0x0091 }, +{ 0x92 , 0x0092 }, +{ 0x93 , 0x0093 }, +{ 0x94 , 0x0094 }, +{ 0x95 , 0x0095 }, +{ 0x96 , 0x0096 }, +{ 0x97 , 0x0097 }, +{ 0x98 , 0x0098 }, +{ 0x99 , 0x0099 }, +{ 0x9a , 0x009A }, +{ 0x9b , 0x009B }, +{ 0x9c , 0x009C }, +{ 0x9d , 0x009D }, +{ 0x9e , 0x009E }, +{ 0x9f , 0x009F }, +{ 0xa0 , 0x00A0 }, +{ 0xa1 , 0x2018 }, +{ 0xa2 , 0x2019 }, +{ 0xa3 , 0x00A3 }, +{ 0xa6 , 0x00A6 }, +{ 0xa7 , 0x00A7 }, +{ 0xa8 , 0x00A8 }, +{ 0xa9 , 0x00A9 }, +{ 0xab , 0x00AB }, +{ 0xac , 0x00AC }, +{ 0xad , 0x00AD }, +{ 0xaf , 0x2015 }, +{ 0xb0 , 0x00B0 }, +{ 0xb1 , 0x00B1 }, +{ 0xb2 , 0x00B2 }, +{ 0xb3 , 0x00B3 }, +{ 0xb4 , 0x0384 }, +{ 0xb5 , 0x0385 }, +{ 0xb6 , 0x0386 }, +{ 0xb7 , 0x00B7 }, +{ 0xb8 , 0x0388 }, +{ 0xb9 , 0x0389 }, +{ 0xba , 0x038A }, +{ 0xbb , 0x00BB }, +{ 0xbc , 0x038C }, +{ 0xbd , 0x00BD }, +{ 0xbe , 0x038E }, +{ 0xbf , 0x038F }, +{ 0xc0 , 0x0390 }, +{ 0xc1 , 0x0391 }, +{ 0xc2 , 0x0392 }, +{ 0xc3 , 0x0393 }, +{ 0xc4 , 0x0394 }, +{ 0xc5 , 0x0395 }, +{ 0xc6 , 0x0396 }, +{ 0xc7 , 0x0397 }, +{ 0xc8 , 0x0398 }, +{ 0xc9 , 0x0399 }, +{ 0xca , 0x039A }, +{ 0xcb , 0x039B }, +{ 0xcc , 0x039C }, +{ 0xcd , 0x039D }, +{ 0xce , 0x039E }, +{ 0xcf , 0x039F }, +{ 0xd0 , 0x03A0 }, +{ 0xd1 , 0x03A1 }, +{ 0xd3 , 0x03A3 }, +{ 0xd4 , 0x03A4 }, +{ 0xd5 , 0x03A5 }, +{ 0xd6 , 0x03A6 }, +{ 0xd7 , 0x03A7 }, +{ 0xd8 , 0x03A8 }, +{ 0xd9 , 0x03A9 }, +{ 0xda , 0x03AA }, +{ 0xdb , 0x03AB }, +{ 0xdc , 0x03AC }, +{ 0xdd , 0x03AD }, +{ 0xde , 0x03AE }, +{ 0xdf , 0x03AF }, +{ 0xe0 , 0x03B0 }, +{ 0xe1 , 0x03B1 }, +{ 0xe2 , 0x03B2 }, +{ 0xe3 , 0x03B3 }, +{ 0xe4 , 0x03B4 }, +{ 0xe5 , 0x03B5 }, +{ 0xe6 , 0x03B6 }, +{ 0xe7 , 0x03B7 }, +{ 0xe8 , 0x03B8 }, +{ 0xe9 , 0x03B9 }, +{ 0xea , 0x03BA }, +{ 0xeb , 0x03BB }, +{ 0xec , 0x03BC }, +{ 0xed , 0x03BD }, +{ 0xee , 0x03BE }, +{ 0xef , 0x03BF }, +{ 0xf0 , 0x03C0 }, +{ 0xf1 , 0x03C1 }, +{ 0xf2 , 0x03C2 }, +{ 0xf3 , 0x03C3 }, +{ 0xf4 , 0x03C4 }, +{ 0xf5 , 0x03C5 }, +{ 0xf6 , 0x03C6 }, +{ 0xf7 , 0x03C7 }, +{ 0xf8 , 0x03C8 }, +{ 0xf9 , 0x03C9 }, +{ 0xfa , 0x03CA }, +{ 0xfb , 0x03CB }, +{ 0xfc , 0x03CC }, +{ 0xfd , 0x03CD }, +{ 0xfe , 0x03CE }, diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/ISO-8859-8.pairs b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/ISO-8859-8.pairs new file mode 100644 index 00000000..8d32dd85 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/ISO-8859-8.pairs @@ -0,0 +1,220 @@ +{ 0x00 , 0x0000 }, +{ 0x01 , 0x0001 }, +{ 0x02 , 0x0002 }, +{ 0x03 , 0x0003 }, +{ 0x04 , 0x0004 }, +{ 0x05 , 0x0005 }, +{ 0x06 , 0x0006 }, +{ 0x07 , 0x0007 }, +{ 0x08 , 0x0008 }, +{ 0x09 , 0x0009 }, +{ 0x0a , 0x000A }, +{ 0x0b , 0x000B }, +{ 0x0c , 0x000C }, +{ 0x0d , 0x000D }, +{ 0x0e , 0x000E }, +{ 0x0f , 0x000F }, +{ 0x10 , 0x0010 }, +{ 0x11 , 0x0011 }, +{ 0x12 , 0x0012 }, +{ 0x13 , 0x0013 }, +{ 0x14 , 0x0014 }, +{ 0x15 , 0x0015 }, +{ 0x16 , 0x0016 }, +{ 0x17 , 0x0017 }, +{ 0x18 , 0x0018 }, +{ 0x19 , 0x0019 }, +{ 0x1a , 0x001A }, +{ 0x1b , 0x001B }, +{ 0x1c , 0x001C }, +{ 0x1d , 0x001D }, +{ 0x1e , 0x001E }, +{ 0x1f , 0x001F }, +{ 0x20 , 0x0020 }, +{ 0x21 , 0x0021 }, +{ 0x22 , 0x0022 }, +{ 0x23 , 0x0023 }, +{ 0x24 , 0x0024 }, +{ 0x25 , 0x0025 }, +{ 0x26 , 0x0026 }, +{ 0x27 , 0x0027 }, +{ 0x28 , 0x0028 }, +{ 0x29 , 0x0029 }, +{ 0x2a , 0x002A }, +{ 0x2b , 0x002B }, +{ 0x2c , 0x002C }, +{ 0x2d , 0x002D }, +{ 0x2e , 0x002E }, +{ 0x2f , 0x002F }, +{ 0x30 , 0x0030 }, +{ 0x31 , 0x0031 }, +{ 0x32 , 0x0032 }, +{ 0x33 , 0x0033 }, +{ 0x34 , 0x0034 }, +{ 0x35 , 0x0035 }, +{ 0x36 , 0x0036 }, +{ 0x37 , 0x0037 }, +{ 0x38 , 0x0038 }, +{ 0x39 , 0x0039 }, +{ 0x3a , 0x003A }, +{ 0x3b , 0x003B }, +{ 0x3c , 0x003C }, +{ 0x3d , 0x003D }, +{ 0x3e , 0x003E }, +{ 0x3f , 0x003F }, +{ 0x40 , 0x0040 }, +{ 0x41 , 0x0041 }, +{ 0x42 , 0x0042 }, +{ 0x43 , 0x0043 }, +{ 0x44 , 0x0044 }, +{ 0x45 , 0x0045 }, +{ 0x46 , 0x0046 }, +{ 0x47 , 0x0047 }, +{ 0x48 , 0x0048 }, +{ 0x49 , 0x0049 }, +{ 0x4a , 0x004A }, +{ 0x4b , 0x004B }, +{ 0x4c , 0x004C }, +{ 0x4d , 0x004D }, +{ 0x4e , 0x004E }, +{ 0x4f , 0x004F }, +{ 0x50 , 0x0050 }, +{ 0x51 , 0x0051 }, +{ 0x52 , 0x0052 }, +{ 0x53 , 0x0053 }, +{ 0x54 , 0x0054 }, +{ 0x55 , 0x0055 }, +{ 0x56 , 0x0056 }, +{ 0x57 , 0x0057 }, +{ 0x58 , 0x0058 }, +{ 0x59 , 0x0059 }, +{ 0x5a , 0x005A }, +{ 0x5b , 0x005B }, +{ 0x5c , 0x005C }, +{ 0x5d , 0x005D }, +{ 0x5e , 0x005E }, +{ 0x5f , 0x005F }, +{ 0x60 , 0x0060 }, +{ 0x61 , 0x0061 }, +{ 0x62 , 0x0062 }, +{ 0x63 , 0x0063 }, +{ 0x64 , 0x0064 }, +{ 0x65 , 0x0065 }, +{ 0x66 , 0x0066 }, +{ 0x67 , 0x0067 }, +{ 0x68 , 0x0068 }, +{ 0x69 , 0x0069 }, +{ 0x6a , 0x006A }, +{ 0x6b , 0x006B }, +{ 0x6c , 0x006C }, +{ 0x6d , 0x006D }, +{ 0x6e , 0x006E }, +{ 0x6f , 0x006F }, +{ 0x70 , 0x0070 }, +{ 0x71 , 0x0071 }, +{ 0x72 , 0x0072 }, +{ 0x73 , 0x0073 }, +{ 0x74 , 0x0074 }, +{ 0x75 , 0x0075 }, +{ 0x76 , 0x0076 }, +{ 0x77 , 0x0077 }, +{ 0x78 , 0x0078 }, +{ 0x79 , 0x0079 }, +{ 0x7a , 0x007A }, +{ 0x7b , 0x007B }, +{ 0x7c , 0x007C }, +{ 0x7d , 0x007D }, +{ 0x7e , 0x007E }, +{ 0x7f , 0x007F }, +{ 0x80 , 0x0080 }, +{ 0x81 , 0x0081 }, +{ 0x82 , 0x0082 }, +{ 0x83 , 0x0083 }, +{ 0x84 , 0x0084 }, +{ 0x85 , 0x0085 }, +{ 0x86 , 0x0086 }, +{ 0x87 , 0x0087 }, +{ 0x88 , 0x0088 }, +{ 0x89 , 0x0089 }, +{ 0x8a , 0x008A }, +{ 0x8b , 0x008B }, +{ 0x8c , 0x008C }, +{ 0x8d , 0x008D }, +{ 0x8e , 0x008E }, +{ 0x8f , 0x008F }, +{ 0x90 , 0x0090 }, +{ 0x91 , 0x0091 }, +{ 0x92 , 0x0092 }, +{ 0x93 , 0x0093 }, +{ 0x94 , 0x0094 }, +{ 0x95 , 0x0095 }, +{ 0x96 , 0x0096 }, +{ 0x97 , 0x0097 }, +{ 0x98 , 0x0098 }, +{ 0x99 , 0x0099 }, +{ 0x9a , 0x009A }, +{ 0x9b , 0x009B }, +{ 0x9c , 0x009C }, +{ 0x9d , 0x009D }, +{ 0x9e , 0x009E }, +{ 0x9f , 0x009F }, +{ 0xa0 , 0x00A0 }, +{ 0xa2 , 0x00A2 }, +{ 0xa3 , 0x00A3 }, +{ 0xa4 , 0x00A4 }, +{ 0xa5 , 0x00A5 }, +{ 0xa6 , 0x00A6 }, +{ 0xa7 , 0x00A7 }, +{ 0xa8 , 0x00A8 }, +{ 0xa9 , 0x00A9 }, +{ 0xaa , 0x00D7 }, +{ 0xab , 0x00AB }, +{ 0xac , 0x00AC }, +{ 0xad , 0x00AD }, +{ 0xae , 0x00AE }, +{ 0xaf , 0x00AF }, +{ 0xb0 , 0x00B0 }, +{ 0xb1 , 0x00B1 }, +{ 0xb2 , 0x00B2 }, +{ 0xb3 , 0x00B3 }, +{ 0xb4 , 0x00B4 }, +{ 0xb5 , 0x00B5 }, +{ 0xb6 , 0x00B6 }, +{ 0xb7 , 0x00B7 }, +{ 0xb8 , 0x00B8 }, +{ 0xb9 , 0x00B9 }, +{ 0xba , 0x00F7 }, +{ 0xbb , 0x00BB }, +{ 0xbc , 0x00BC }, +{ 0xbd , 0x00BD }, +{ 0xbe , 0x00BE }, +{ 0xdf , 0x2017 }, +{ 0xe0 , 0x05D0 }, +{ 0xe1 , 0x05D1 }, +{ 0xe2 , 0x05D2 }, +{ 0xe3 , 0x05D3 }, +{ 0xe4 , 0x05D4 }, +{ 0xe5 , 0x05D5 }, +{ 0xe6 , 0x05D6 }, +{ 0xe7 , 0x05D7 }, +{ 0xe8 , 0x05D8 }, +{ 0xe9 , 0x05D9 }, +{ 0xea , 0x05DA }, +{ 0xeb , 0x05DB }, +{ 0xec , 0x05DC }, +{ 0xed , 0x05DD }, +{ 0xee , 0x05DE }, +{ 0xef , 0x05DF }, +{ 0xf0 , 0x05E0 }, +{ 0xf1 , 0x05E1 }, +{ 0xf2 , 0x05E2 }, +{ 0xf3 , 0x05E3 }, +{ 0xf4 , 0x05E4 }, +{ 0xf5 , 0x05E5 }, +{ 0xf6 , 0x05E6 }, +{ 0xf7 , 0x05E7 }, +{ 0xf8 , 0x05E8 }, +{ 0xf9 , 0x05E9 }, +{ 0xfa , 0x05EA }, +{ 0xfd , 0x200E }, +{ 0xfe , 0x200F }, diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/ISO-8859-9.pairs b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/ISO-8859-9.pairs new file mode 100644 index 00000000..a5748cda --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/ISO-8859-9.pairs @@ -0,0 +1,256 @@ +{ 0x00 , 0x0000 }, +{ 0x01 , 0x0001 }, +{ 0x02 , 0x0002 }, +{ 0x03 , 0x0003 }, +{ 0x04 , 0x0004 }, +{ 0x05 , 0x0005 }, +{ 0x06 , 0x0006 }, +{ 0x07 , 0x0007 }, +{ 0x08 , 0x0008 }, +{ 0x09 , 0x0009 }, +{ 0x0a , 0x000A }, +{ 0x0b , 0x000B }, +{ 0x0c , 0x000C }, +{ 0x0d , 0x000D }, +{ 0x0e , 0x000E }, +{ 0x0f , 0x000F }, +{ 0x10 , 0x0010 }, +{ 0x11 , 0x0011 }, +{ 0x12 , 0x0012 }, +{ 0x13 , 0x0013 }, +{ 0x14 , 0x0014 }, +{ 0x15 , 0x0015 }, +{ 0x16 , 0x0016 }, +{ 0x17 , 0x0017 }, +{ 0x18 , 0x0018 }, +{ 0x19 , 0x0019 }, +{ 0x1a , 0x001A }, +{ 0x1b , 0x001B }, +{ 0x1c , 0x001C }, +{ 0x1d , 0x001D }, +{ 0x1e , 0x001E }, +{ 0x1f , 0x001F }, +{ 0x20 , 0x0020 }, +{ 0x21 , 0x0021 }, +{ 0x22 , 0x0022 }, +{ 0x23 , 0x0023 }, +{ 0x24 , 0x0024 }, +{ 0x25 , 0x0025 }, +{ 0x26 , 0x0026 }, +{ 0x27 , 0x0027 }, +{ 0x28 , 0x0028 }, +{ 0x29 , 0x0029 }, +{ 0x2a , 0x002A }, +{ 0x2b , 0x002B }, +{ 0x2c , 0x002C }, +{ 0x2d , 0x002D }, +{ 0x2e , 0x002E }, +{ 0x2f , 0x002F }, +{ 0x30 , 0x0030 }, +{ 0x31 , 0x0031 }, +{ 0x32 , 0x0032 }, +{ 0x33 , 0x0033 }, +{ 0x34 , 0x0034 }, +{ 0x35 , 0x0035 }, +{ 0x36 , 0x0036 }, +{ 0x37 , 0x0037 }, +{ 0x38 , 0x0038 }, +{ 0x39 , 0x0039 }, +{ 0x3a , 0x003A }, +{ 0x3b , 0x003B }, +{ 0x3c , 0x003C }, +{ 0x3d , 0x003D }, +{ 0x3e , 0x003E }, +{ 0x3f , 0x003F }, +{ 0x40 , 0x0040 }, +{ 0x41 , 0x0041 }, +{ 0x42 , 0x0042 }, +{ 0x43 , 0x0043 }, +{ 0x44 , 0x0044 }, +{ 0x45 , 0x0045 }, +{ 0x46 , 0x0046 }, +{ 0x47 , 0x0047 }, +{ 0x48 , 0x0048 }, +{ 0x49 , 0x0049 }, +{ 0x4a , 0x004A }, +{ 0x4b , 0x004B }, +{ 0x4c , 0x004C }, +{ 0x4d , 0x004D }, +{ 0x4e , 0x004E }, +{ 0x4f , 0x004F }, +{ 0x50 , 0x0050 }, +{ 0x51 , 0x0051 }, +{ 0x52 , 0x0052 }, +{ 0x53 , 0x0053 }, +{ 0x54 , 0x0054 }, +{ 0x55 , 0x0055 }, +{ 0x56 , 0x0056 }, +{ 0x57 , 0x0057 }, +{ 0x58 , 0x0058 }, +{ 0x59 , 0x0059 }, +{ 0x5a , 0x005A }, +{ 0x5b , 0x005B }, +{ 0x5c , 0x005C }, +{ 0x5d , 0x005D }, +{ 0x5e , 0x005E }, +{ 0x5f , 0x005F }, +{ 0x60 , 0x0060 }, +{ 0x61 , 0x0061 }, +{ 0x62 , 0x0062 }, +{ 0x63 , 0x0063 }, +{ 0x64 , 0x0064 }, +{ 0x65 , 0x0065 }, +{ 0x66 , 0x0066 }, +{ 0x67 , 0x0067 }, +{ 0x68 , 0x0068 }, +{ 0x69 , 0x0069 }, +{ 0x6a , 0x006A }, +{ 0x6b , 0x006B }, +{ 0x6c , 0x006C }, +{ 0x6d , 0x006D }, +{ 0x6e , 0x006E }, +{ 0x6f , 0x006F }, +{ 0x70 , 0x0070 }, +{ 0x71 , 0x0071 }, +{ 0x72 , 0x0072 }, +{ 0x73 , 0x0073 }, +{ 0x74 , 0x0074 }, +{ 0x75 , 0x0075 }, +{ 0x76 , 0x0076 }, +{ 0x77 , 0x0077 }, +{ 0x78 , 0x0078 }, +{ 0x79 , 0x0079 }, +{ 0x7a , 0x007A }, +{ 0x7b , 0x007B }, +{ 0x7c , 0x007C }, +{ 0x7d , 0x007D }, +{ 0x7e , 0x007E }, +{ 0x7f , 0x007F }, +{ 0x80 , 0x0080 }, +{ 0x81 , 0x0081 }, +{ 0x82 , 0x0082 }, +{ 0x83 , 0x0083 }, +{ 0x84 , 0x0084 }, +{ 0x85 , 0x0085 }, +{ 0x86 , 0x0086 }, +{ 0x87 , 0x0087 }, +{ 0x88 , 0x0088 }, +{ 0x89 , 0x0089 }, +{ 0x8a , 0x008A }, +{ 0x8b , 0x008B }, +{ 0x8c , 0x008C }, +{ 0x8d , 0x008D }, +{ 0x8e , 0x008E }, +{ 0x8f , 0x008F }, +{ 0x90 , 0x0090 }, +{ 0x91 , 0x0091 }, +{ 0x92 , 0x0092 }, +{ 0x93 , 0x0093 }, +{ 0x94 , 0x0094 }, +{ 0x95 , 0x0095 }, +{ 0x96 , 0x0096 }, +{ 0x97 , 0x0097 }, +{ 0x98 , 0x0098 }, +{ 0x99 , 0x0099 }, +{ 0x9a , 0x009A }, +{ 0x9b , 0x009B }, +{ 0x9c , 0x009C }, +{ 0x9d , 0x009D }, +{ 0x9e , 0x009E }, +{ 0x9f , 0x009F }, +{ 0xa0 , 0x00A0 }, +{ 0xa1 , 0x00A1 }, +{ 0xa2 , 0x00A2 }, +{ 0xa3 , 0x00A3 }, +{ 0xa4 , 0x00A4 }, +{ 0xa5 , 0x00A5 }, +{ 0xa6 , 0x00A6 }, +{ 0xa7 , 0x00A7 }, +{ 0xa8 , 0x00A8 }, +{ 0xa9 , 0x00A9 }, +{ 0xaa , 0x00AA }, +{ 0xab , 0x00AB }, +{ 0xac , 0x00AC }, +{ 0xad , 0x00AD }, +{ 0xae , 0x00AE }, +{ 0xaf , 0x00AF }, +{ 0xb0 , 0x00B0 }, +{ 0xb1 , 0x00B1 }, +{ 0xb2 , 0x00B2 }, +{ 0xb3 , 0x00B3 }, +{ 0xb4 , 0x00B4 }, +{ 0xb5 , 0x00B5 }, +{ 0xb6 , 0x00B6 }, +{ 0xb7 , 0x00B7 }, +{ 0xb8 , 0x00B8 }, +{ 0xb9 , 0x00B9 }, +{ 0xba , 0x00BA }, +{ 0xbb , 0x00BB }, +{ 0xbc , 0x00BC }, +{ 0xbd , 0x00BD }, +{ 0xbe , 0x00BE }, +{ 0xbf , 0x00BF }, +{ 0xc0 , 0x00C0 }, +{ 0xc1 , 0x00C1 }, +{ 0xc2 , 0x00C2 }, +{ 0xc3 , 0x00C3 }, +{ 0xc4 , 0x00C4 }, +{ 0xc5 , 0x00C5 }, +{ 0xc6 , 0x00C6 }, +{ 0xc7 , 0x00C7 }, +{ 0xc8 , 0x00C8 }, +{ 0xc9 , 0x00C9 }, +{ 0xca , 0x00CA }, +{ 0xcb , 0x00CB }, +{ 0xcc , 0x00CC }, +{ 0xcd , 0x00CD }, +{ 0xce , 0x00CE }, +{ 0xcf , 0x00CF }, +{ 0xd0 , 0x011E }, +{ 0xd1 , 0x00D1 }, +{ 0xd2 , 0x00D2 }, +{ 0xd3 , 0x00D3 }, +{ 0xd4 , 0x00D4 }, +{ 0xd5 , 0x00D5 }, +{ 0xd6 , 0x00D6 }, +{ 0xd7 , 0x00D7 }, +{ 0xd8 , 0x00D8 }, +{ 0xd9 , 0x00D9 }, +{ 0xda , 0x00DA }, +{ 0xdb , 0x00DB }, +{ 0xdc , 0x00DC }, +{ 0xdd , 0x0130 }, +{ 0xde , 0x015E }, +{ 0xdf , 0x00DF }, +{ 0xe0 , 0x00E0 }, +{ 0xe1 , 0x00E1 }, +{ 0xe2 , 0x00E2 }, +{ 0xe3 , 0x00E3 }, +{ 0xe4 , 0x00E4 }, +{ 0xe5 , 0x00E5 }, +{ 0xe6 , 0x00E6 }, +{ 0xe7 , 0x00E7 }, +{ 0xe8 , 0x00E8 }, +{ 0xe9 , 0x00E9 }, +{ 0xea , 0x00EA }, +{ 0xeb , 0x00EB }, +{ 0xec , 0x00EC }, +{ 0xed , 0x00ED }, +{ 0xee , 0x00EE }, +{ 0xef , 0x00EF }, +{ 0xf0 , 0x011F }, +{ 0xf1 , 0x00F1 }, +{ 0xf2 , 0x00F2 }, +{ 0xf3 , 0x00F3 }, +{ 0xf4 , 0x00F4 }, +{ 0xf5 , 0x00F5 }, +{ 0xf6 , 0x00F6 }, +{ 0xf7 , 0x00F7 }, +{ 0xf8 , 0x00F8 }, +{ 0xf9 , 0x00F9 }, +{ 0xfa , 0x00FA }, +{ 0xfb , 0x00FB }, +{ 0xfc , 0x00FC }, +{ 0xfd , 0x0131 }, +{ 0xfe , 0x015F }, +{ 0xff , 0x00FF }, diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/KOI8-R.pairs b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/KOI8-R.pairs new file mode 100644 index 00000000..f34053d9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/KOI8-R.pairs @@ -0,0 +1,256 @@ +{ 0x00 , 0x0000 }, +{ 0x01 , 0x0001 }, +{ 0x02 , 0x0002 }, +{ 0x03 , 0x0003 }, +{ 0x04 , 0x0004 }, +{ 0x05 , 0x0005 }, +{ 0x06 , 0x0006 }, +{ 0x07 , 0x0007 }, +{ 0x08 , 0x0008 }, +{ 0x09 , 0x0009 }, +{ 0x0a , 0x000A }, +{ 0x0b , 0x000B }, +{ 0x0c , 0x000C }, +{ 0x0d , 0x000D }, +{ 0x0e , 0x000E }, +{ 0x0f , 0x000F }, +{ 0x10 , 0x0010 }, +{ 0x11 , 0x0011 }, +{ 0x12 , 0x0012 }, +{ 0x13 , 0x0013 }, +{ 0x14 , 0x0014 }, +{ 0x15 , 0x0015 }, +{ 0x16 , 0x0016 }, +{ 0x17 , 0x0017 }, +{ 0x18 , 0x0018 }, +{ 0x19 , 0x0019 }, +{ 0x1a , 0x001A }, +{ 0x1b , 0x001B }, +{ 0x1c , 0x001C }, +{ 0x1d , 0x001D }, +{ 0x1e , 0x001E }, +{ 0x1f , 0x001F }, +{ 0x20 , 0x0020 }, +{ 0x21 , 0x0021 }, +{ 0x22 , 0x0022 }, +{ 0x23 , 0x0023 }, +{ 0x24 , 0x0024 }, +{ 0x25 , 0x0025 }, +{ 0x26 , 0x0026 }, +{ 0x27 , 0x0027 }, +{ 0x28 , 0x0028 }, +{ 0x29 , 0x0029 }, +{ 0x2a , 0x002A }, +{ 0x2b , 0x002B }, +{ 0x2c , 0x002C }, +{ 0x2d , 0x002D }, +{ 0x2e , 0x002E }, +{ 0x2f , 0x002F }, +{ 0x30 , 0x0030 }, +{ 0x31 , 0x0031 }, +{ 0x32 , 0x0032 }, +{ 0x33 , 0x0033 }, +{ 0x34 , 0x0034 }, +{ 0x35 , 0x0035 }, +{ 0x36 , 0x0036 }, +{ 0x37 , 0x0037 }, +{ 0x38 , 0x0038 }, +{ 0x39 , 0x0039 }, +{ 0x3a , 0x003A }, +{ 0x3b , 0x003B }, +{ 0x3c , 0x003C }, +{ 0x3d , 0x003D }, +{ 0x3e , 0x003E }, +{ 0x3f , 0x003F }, +{ 0x40 , 0x0040 }, +{ 0x41 , 0x0041 }, +{ 0x42 , 0x0042 }, +{ 0x43 , 0x0043 }, +{ 0x44 , 0x0044 }, +{ 0x45 , 0x0045 }, +{ 0x46 , 0x0046 }, +{ 0x47 , 0x0047 }, +{ 0x48 , 0x0048 }, +{ 0x49 , 0x0049 }, +{ 0x4a , 0x004A }, +{ 0x4b , 0x004B }, +{ 0x4c , 0x004C }, +{ 0x4d , 0x004D }, +{ 0x4e , 0x004E }, +{ 0x4f , 0x004F }, +{ 0x50 , 0x0050 }, +{ 0x51 , 0x0051 }, +{ 0x52 , 0x0052 }, +{ 0x53 , 0x0053 }, +{ 0x54 , 0x0054 }, +{ 0x55 , 0x0055 }, +{ 0x56 , 0x0056 }, +{ 0x57 , 0x0057 }, +{ 0x58 , 0x0058 }, +{ 0x59 , 0x0059 }, +{ 0x5a , 0x005A }, +{ 0x5b , 0x005B }, +{ 0x5c , 0x005C }, +{ 0x5d , 0x005D }, +{ 0x5e , 0x005E }, +{ 0x5f , 0x005F }, +{ 0x60 , 0x0060 }, +{ 0x61 , 0x0061 }, +{ 0x62 , 0x0062 }, +{ 0x63 , 0x0063 }, +{ 0x64 , 0x0064 }, +{ 0x65 , 0x0065 }, +{ 0x66 , 0x0066 }, +{ 0x67 , 0x0067 }, +{ 0x68 , 0x0068 }, +{ 0x69 , 0x0069 }, +{ 0x6a , 0x006A }, +{ 0x6b , 0x006B }, +{ 0x6c , 0x006C }, +{ 0x6d , 0x006D }, +{ 0x6e , 0x006E }, +{ 0x6f , 0x006F }, +{ 0x70 , 0x0070 }, +{ 0x71 , 0x0071 }, +{ 0x72 , 0x0072 }, +{ 0x73 , 0x0073 }, +{ 0x74 , 0x0074 }, +{ 0x75 , 0x0075 }, +{ 0x76 , 0x0076 }, +{ 0x77 , 0x0077 }, +{ 0x78 , 0x0078 }, +{ 0x79 , 0x0079 }, +{ 0x7a , 0x007A }, +{ 0x7b , 0x007B }, +{ 0x7c , 0x007C }, +{ 0x7d , 0x007D }, +{ 0x7e , 0x007E }, +{ 0x7f , 0x007F }, +{ 0x80 , 0x2500 }, +{ 0x81 , 0x2502 }, +{ 0x82 , 0x250C }, +{ 0x83 , 0x2510 }, +{ 0x84 , 0x2514 }, +{ 0x85 , 0x2518 }, +{ 0x86 , 0x251C }, +{ 0x87 , 0x2524 }, +{ 0x88 , 0x252C }, +{ 0x89 , 0x2534 }, +{ 0x8a , 0x253C }, +{ 0x8b , 0x2580 }, +{ 0x8c , 0x2584 }, +{ 0x8d , 0x2588 }, +{ 0x8e , 0x258C }, +{ 0x8f , 0x2590 }, +{ 0x90 , 0x2591 }, +{ 0x91 , 0x2592 }, +{ 0x92 , 0x2593 }, +{ 0x93 , 0x2320 }, +{ 0x94 , 0x25A0 }, +{ 0x95 , 0x2219 }, +{ 0x96 , 0x221A }, +{ 0x97 , 0x2248 }, +{ 0x98 , 0x2264 }, +{ 0x99 , 0x2265 }, +{ 0x9a , 0x00A0 }, +{ 0x9b , 0x2321 }, +{ 0x9c , 0x00B0 }, +{ 0x9d , 0x00B2 }, +{ 0x9e , 0x00B7 }, +{ 0x9f , 0x00F7 }, +{ 0xa0 , 0x2550 }, +{ 0xa1 , 0x2551 }, +{ 0xa2 , 0x2552 }, +{ 0xa3 , 0x0451 }, +{ 0xa4 , 0x2553 }, +{ 0xa5 , 0x2554 }, +{ 0xa6 , 0x2555 }, +{ 0xa7 , 0x2556 }, +{ 0xa8 , 0x2557 }, +{ 0xa9 , 0x2558 }, +{ 0xaa , 0x2559 }, +{ 0xab , 0x255A }, +{ 0xac , 0x255B }, +{ 0xad , 0x255C }, +{ 0xae , 0x255D }, +{ 0xaf , 0x255E }, +{ 0xb0 , 0x255F }, +{ 0xb1 , 0x2560 }, +{ 0xb2 , 0x2561 }, +{ 0xb3 , 0x0401 }, +{ 0xb4 , 0x2562 }, +{ 0xb5 , 0x2563 }, +{ 0xb6 , 0x2564 }, +{ 0xb7 , 0x2565 }, +{ 0xb8 , 0x2566 }, +{ 0xb9 , 0x2567 }, +{ 0xba , 0x2568 }, +{ 0xbb , 0x2569 }, +{ 0xbc , 0x256A }, +{ 0xbd , 0x256B }, +{ 0xbe , 0x256C }, +{ 0xbf , 0x00A9 }, +{ 0xc0 , 0x044E }, +{ 0xc1 , 0x0430 }, +{ 0xc2 , 0x0431 }, +{ 0xc3 , 0x0446 }, +{ 0xc4 , 0x0434 }, +{ 0xc5 , 0x0435 }, +{ 0xc6 , 0x0444 }, +{ 0xc7 , 0x0433 }, +{ 0xc8 , 0x0445 }, +{ 0xc9 , 0x0438 }, +{ 0xca , 0x0439 }, +{ 0xcb , 0x043A }, +{ 0xcc , 0x043B }, +{ 0xcd , 0x043C }, +{ 0xce , 0x043D }, +{ 0xcf , 0x043E }, +{ 0xd0 , 0x043F }, +{ 0xd1 , 0x044F }, +{ 0xd2 , 0x0440 }, +{ 0xd3 , 0x0441 }, +{ 0xd4 , 0x0442 }, +{ 0xd5 , 0x0443 }, +{ 0xd6 , 0x0436 }, +{ 0xd7 , 0x0432 }, +{ 0xd8 , 0x044C }, +{ 0xd9 , 0x044B }, +{ 0xda , 0x0437 }, +{ 0xdb , 0x0448 }, +{ 0xdc , 0x044D }, +{ 0xdd , 0x0449 }, +{ 0xde , 0x0447 }, +{ 0xdf , 0x044A }, +{ 0xe0 , 0x042E }, +{ 0xe1 , 0x0410 }, +{ 0xe2 , 0x0411 }, +{ 0xe3 , 0x0426 }, +{ 0xe4 , 0x0414 }, +{ 0xe5 , 0x0415 }, +{ 0xe6 , 0x0424 }, +{ 0xe7 , 0x0413 }, +{ 0xe8 , 0x0425 }, +{ 0xe9 , 0x0418 }, +{ 0xea , 0x0419 }, +{ 0xeb , 0x041A }, +{ 0xec , 0x041B }, +{ 0xed , 0x041C }, +{ 0xee , 0x041D }, +{ 0xef , 0x041E }, +{ 0xf0 , 0x041F }, +{ 0xf1 , 0x042F }, +{ 0xf2 , 0x0420 }, +{ 0xf3 , 0x0421 }, +{ 0xf4 , 0x0422 }, +{ 0xf5 , 0x0423 }, +{ 0xf6 , 0x0416 }, +{ 0xf7 , 0x0412 }, +{ 0xf8 , 0x042C }, +{ 0xf9 , 0x042B }, +{ 0xfa , 0x0417 }, +{ 0xfb , 0x0428 }, +{ 0xfc , 0x042D }, +{ 0xfd , 0x0429 }, +{ 0xfe , 0x0427 }, +{ 0xff , 0x042A }, diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/KOI8-T.pairs b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/KOI8-T.pairs new file mode 100644 index 00000000..aeba5820 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/KOI8-T.pairs @@ -0,0 +1,237 @@ +{ 0x00 , 0x0000 }, +{ 0x01 , 0x0001 }, +{ 0x02 , 0x0002 }, +{ 0x03 , 0x0003 }, +{ 0x04 , 0x0004 }, +{ 0x05 , 0x0005 }, +{ 0x06 , 0x0006 }, +{ 0x07 , 0x0007 }, +{ 0x08 , 0x0008 }, +{ 0x09 , 0x0009 }, +{ 0x0a , 0x000A }, +{ 0x0b , 0x000B }, +{ 0x0c , 0x000C }, +{ 0x0d , 0x000D }, +{ 0x0e , 0x000E }, +{ 0x0f , 0x000F }, +{ 0x10 , 0x0010 }, +{ 0x11 , 0x0011 }, +{ 0x12 , 0x0012 }, +{ 0x13 , 0x0013 }, +{ 0x14 , 0x0014 }, +{ 0x15 , 0x0015 }, +{ 0x16 , 0x0016 }, +{ 0x17 , 0x0017 }, +{ 0x18 , 0x0018 }, +{ 0x19 , 0x0019 }, +{ 0x1a , 0x001A }, +{ 0x1b , 0x001B }, +{ 0x1c , 0x001C }, +{ 0x1d , 0x001D }, +{ 0x1e , 0x001E }, +{ 0x1f , 0x001F }, +{ 0x20 , 0x0020 }, +{ 0x21 , 0x0021 }, +{ 0x22 , 0x0022 }, +{ 0x23 , 0x0023 }, +{ 0x24 , 0x0024 }, +{ 0x25 , 0x0025 }, +{ 0x26 , 0x0026 }, +{ 0x27 , 0x0027 }, +{ 0x28 , 0x0028 }, +{ 0x29 , 0x0029 }, +{ 0x2a , 0x002A }, +{ 0x2b , 0x002B }, +{ 0x2c , 0x002C }, +{ 0x2d , 0x002D }, +{ 0x2e , 0x002E }, +{ 0x2f , 0x002F }, +{ 0x30 , 0x0030 }, +{ 0x31 , 0x0031 }, +{ 0x32 , 0x0032 }, +{ 0x33 , 0x0033 }, +{ 0x34 , 0x0034 }, +{ 0x35 , 0x0035 }, +{ 0x36 , 0x0036 }, +{ 0x37 , 0x0037 }, +{ 0x38 , 0x0038 }, +{ 0x39 , 0x0039 }, +{ 0x3a , 0x003A }, +{ 0x3b , 0x003B }, +{ 0x3c , 0x003C }, +{ 0x3d , 0x003D }, +{ 0x3e , 0x003E }, +{ 0x3f , 0x003F }, +{ 0x40 , 0x0040 }, +{ 0x41 , 0x0041 }, +{ 0x42 , 0x0042 }, +{ 0x43 , 0x0043 }, +{ 0x44 , 0x0044 }, +{ 0x45 , 0x0045 }, +{ 0x46 , 0x0046 }, +{ 0x47 , 0x0047 }, +{ 0x48 , 0x0048 }, +{ 0x49 , 0x0049 }, +{ 0x4a , 0x004A }, +{ 0x4b , 0x004B }, +{ 0x4c , 0x004C }, +{ 0x4d , 0x004D }, +{ 0x4e , 0x004E }, +{ 0x4f , 0x004F }, +{ 0x50 , 0x0050 }, +{ 0x51 , 0x0051 }, +{ 0x52 , 0x0052 }, +{ 0x53 , 0x0053 }, +{ 0x54 , 0x0054 }, +{ 0x55 , 0x0055 }, +{ 0x56 , 0x0056 }, +{ 0x57 , 0x0057 }, +{ 0x58 , 0x0058 }, +{ 0x59 , 0x0059 }, +{ 0x5a , 0x005A }, +{ 0x5b , 0x005B }, +{ 0x5c , 0x005C }, +{ 0x5d , 0x005D }, +{ 0x5e , 0x005E }, +{ 0x5f , 0x005F }, +{ 0x60 , 0x0060 }, +{ 0x61 , 0x0061 }, +{ 0x62 , 0x0062 }, +{ 0x63 , 0x0063 }, +{ 0x64 , 0x0064 }, +{ 0x65 , 0x0065 }, +{ 0x66 , 0x0066 }, +{ 0x67 , 0x0067 }, +{ 0x68 , 0x0068 }, +{ 0x69 , 0x0069 }, +{ 0x6a , 0x006A }, +{ 0x6b , 0x006B }, +{ 0x6c , 0x006C }, +{ 0x6d , 0x006D }, +{ 0x6e , 0x006E }, +{ 0x6f , 0x006F }, +{ 0x70 , 0x0070 }, +{ 0x71 , 0x0071 }, +{ 0x72 , 0x0072 }, +{ 0x73 , 0x0073 }, +{ 0x74 , 0x0074 }, +{ 0x75 , 0x0075 }, +{ 0x76 , 0x0076 }, +{ 0x77 , 0x0077 }, +{ 0x78 , 0x0078 }, +{ 0x79 , 0x0079 }, +{ 0x7a , 0x007A }, +{ 0x7b , 0x007B }, +{ 0x7c , 0x007C }, +{ 0x7d , 0x007D }, +{ 0x7e , 0x007E }, +{ 0x7f , 0x007F }, +{ 0x80 , 0x049B }, +{ 0x81 , 0x0493 }, +{ 0x82 , 0x201A }, +{ 0x83 , 0x0492 }, +{ 0x84 , 0x201E }, +{ 0x85 , 0x2026 }, +{ 0x86 , 0x2020 }, +{ 0x87 , 0x2021 }, +{ 0x89 , 0x2030 }, +{ 0x8a , 0x04B3 }, +{ 0x8b , 0x2039 }, +{ 0x8c , 0x04B2 }, +{ 0x8d , 0x04B7 }, +{ 0x8e , 0x04B6 }, +{ 0x90 , 0x049A }, +{ 0x91 , 0x2018 }, +{ 0x92 , 0x2019 }, +{ 0x93 , 0x201C }, +{ 0x94 , 0x201D }, +{ 0x95 , 0x2022 }, +{ 0x96 , 0x2013 }, +{ 0x97 , 0x2014 }, +{ 0x99 , 0x2122 }, +{ 0x9b , 0x203A }, +{ 0xa1 , 0x04EF }, +{ 0xa2 , 0x04EE }, +{ 0xa3 , 0x0451 }, +{ 0xa4 , 0x00A4 }, +{ 0xa5 , 0x04E3 }, +{ 0xa6 , 0x00A6 }, +{ 0xa7 , 0x00A7 }, +{ 0xab , 0x00AB }, +{ 0xac , 0x00AC }, +{ 0xad , 0x00AD }, +{ 0xae , 0x00AE }, +{ 0xb0 , 0x00B0 }, +{ 0xb1 , 0x00B1 }, +{ 0xb2 , 0x00B2 }, +{ 0xb3 , 0x0401 }, +{ 0xb5 , 0x04E2 }, +{ 0xb6 , 0x00B6 }, +{ 0xb7 , 0x00B7 }, +{ 0xb9 , 0x2116 }, +{ 0xbb , 0x00BB }, +{ 0xbf , 0x00A9 }, +{ 0xc0 , 0x044E }, +{ 0xc1 , 0x0430 }, +{ 0xc2 , 0x0431 }, +{ 0xc3 , 0x0446 }, +{ 0xc4 , 0x0434 }, +{ 0xc5 , 0x0435 }, +{ 0xc6 , 0x0444 }, +{ 0xc7 , 0x0433 }, +{ 0xc8 , 0x0445 }, +{ 0xc9 , 0x0438 }, +{ 0xca , 0x0439 }, +{ 0xcb , 0x043A }, +{ 0xcc , 0x043B }, +{ 0xcd , 0x043C }, +{ 0xce , 0x043D }, +{ 0xcf , 0x043E }, +{ 0xd0 , 0x043F }, +{ 0xd1 , 0x044F }, +{ 0xd2 , 0x0440 }, +{ 0xd3 , 0x0441 }, +{ 0xd4 , 0x0442 }, +{ 0xd5 , 0x0443 }, +{ 0xd6 , 0x0436 }, +{ 0xd7 , 0x0432 }, +{ 0xd8 , 0x044C }, +{ 0xd9 , 0x044B }, +{ 0xda , 0x0437 }, +{ 0xdb , 0x0448 }, +{ 0xdc , 0x044D }, +{ 0xdd , 0x0449 }, +{ 0xde , 0x0447 }, +{ 0xdf , 0x044A }, +{ 0xe0 , 0x042E }, +{ 0xe1 , 0x0410 }, +{ 0xe2 , 0x0411 }, +{ 0xe3 , 0x0426 }, +{ 0xe4 , 0x0414 }, +{ 0xe5 , 0x0415 }, +{ 0xe6 , 0x0424 }, +{ 0xe7 , 0x0413 }, +{ 0xe8 , 0x0425 }, +{ 0xe9 , 0x0418 }, +{ 0xea , 0x0419 }, +{ 0xeb , 0x041A }, +{ 0xec , 0x041B }, +{ 0xed , 0x041C }, +{ 0xee , 0x041D }, +{ 0xef , 0x041E }, +{ 0xf0 , 0x041F }, +{ 0xf1 , 0x042F }, +{ 0xf2 , 0x0420 }, +{ 0xf3 , 0x0421 }, +{ 0xf4 , 0x0422 }, +{ 0xf5 , 0x0423 }, +{ 0xf6 , 0x0416 }, +{ 0xf7 , 0x0412 }, +{ 0xf8 , 0x042C }, +{ 0xf9 , 0x042B }, +{ 0xfa , 0x0417 }, +{ 0xfb , 0x0428 }, +{ 0xfc , 0x042D }, +{ 0xfd , 0x0429 }, +{ 0xfe , 0x0427 }, +{ 0xff , 0x042A }, diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/KOI8-U.pairs b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/KOI8-U.pairs new file mode 100644 index 00000000..ff05ed24 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/KOI8-U.pairs @@ -0,0 +1,256 @@ +{ 0x00 , 0x0000 }, +{ 0x01 , 0x0001 }, +{ 0x02 , 0x0002 }, +{ 0x03 , 0x0003 }, +{ 0x04 , 0x0004 }, +{ 0x05 , 0x0005 }, +{ 0x06 , 0x0006 }, +{ 0x07 , 0x0007 }, +{ 0x08 , 0x0008 }, +{ 0x09 , 0x0009 }, +{ 0x0a , 0x000A }, +{ 0x0b , 0x000B }, +{ 0x0c , 0x000C }, +{ 0x0d , 0x000D }, +{ 0x0e , 0x000E }, +{ 0x0f , 0x000F }, +{ 0x10 , 0x0010 }, +{ 0x11 , 0x0011 }, +{ 0x12 , 0x0012 }, +{ 0x13 , 0x0013 }, +{ 0x14 , 0x0014 }, +{ 0x15 , 0x0015 }, +{ 0x16 , 0x0016 }, +{ 0x17 , 0x0017 }, +{ 0x18 , 0x0018 }, +{ 0x19 , 0x0019 }, +{ 0x1a , 0x001A }, +{ 0x1b , 0x001B }, +{ 0x1c , 0x001C }, +{ 0x1d , 0x001D }, +{ 0x1e , 0x001E }, +{ 0x1f , 0x001F }, +{ 0x20 , 0x0020 }, +{ 0x21 , 0x0021 }, +{ 0x22 , 0x0022 }, +{ 0x23 , 0x0023 }, +{ 0x24 , 0x0024 }, +{ 0x25 , 0x0025 }, +{ 0x26 , 0x0026 }, +{ 0x27 , 0x0027 }, +{ 0x28 , 0x0028 }, +{ 0x29 , 0x0029 }, +{ 0x2a , 0x002A }, +{ 0x2b , 0x002B }, +{ 0x2c , 0x002C }, +{ 0x2d , 0x002D }, +{ 0x2e , 0x002E }, +{ 0x2f , 0x002F }, +{ 0x30 , 0x0030 }, +{ 0x31 , 0x0031 }, +{ 0x32 , 0x0032 }, +{ 0x33 , 0x0033 }, +{ 0x34 , 0x0034 }, +{ 0x35 , 0x0035 }, +{ 0x36 , 0x0036 }, +{ 0x37 , 0x0037 }, +{ 0x38 , 0x0038 }, +{ 0x39 , 0x0039 }, +{ 0x3a , 0x003A }, +{ 0x3b , 0x003B }, +{ 0x3c , 0x003C }, +{ 0x3d , 0x003D }, +{ 0x3e , 0x003E }, +{ 0x3f , 0x003F }, +{ 0x40 , 0x0040 }, +{ 0x41 , 0x0041 }, +{ 0x42 , 0x0042 }, +{ 0x43 , 0x0043 }, +{ 0x44 , 0x0044 }, +{ 0x45 , 0x0045 }, +{ 0x46 , 0x0046 }, +{ 0x47 , 0x0047 }, +{ 0x48 , 0x0048 }, +{ 0x49 , 0x0049 }, +{ 0x4a , 0x004A }, +{ 0x4b , 0x004B }, +{ 0x4c , 0x004C }, +{ 0x4d , 0x004D }, +{ 0x4e , 0x004E }, +{ 0x4f , 0x004F }, +{ 0x50 , 0x0050 }, +{ 0x51 , 0x0051 }, +{ 0x52 , 0x0052 }, +{ 0x53 , 0x0053 }, +{ 0x54 , 0x0054 }, +{ 0x55 , 0x0055 }, +{ 0x56 , 0x0056 }, +{ 0x57 , 0x0057 }, +{ 0x58 , 0x0058 }, +{ 0x59 , 0x0059 }, +{ 0x5a , 0x005A }, +{ 0x5b , 0x005B }, +{ 0x5c , 0x005C }, +{ 0x5d , 0x005D }, +{ 0x5e , 0x005E }, +{ 0x5f , 0x005F }, +{ 0x60 , 0x0060 }, +{ 0x61 , 0x0061 }, +{ 0x62 , 0x0062 }, +{ 0x63 , 0x0063 }, +{ 0x64 , 0x0064 }, +{ 0x65 , 0x0065 }, +{ 0x66 , 0x0066 }, +{ 0x67 , 0x0067 }, +{ 0x68 , 0x0068 }, +{ 0x69 , 0x0069 }, +{ 0x6a , 0x006A }, +{ 0x6b , 0x006B }, +{ 0x6c , 0x006C }, +{ 0x6d , 0x006D }, +{ 0x6e , 0x006E }, +{ 0x6f , 0x006F }, +{ 0x70 , 0x0070 }, +{ 0x71 , 0x0071 }, +{ 0x72 , 0x0072 }, +{ 0x73 , 0x0073 }, +{ 0x74 , 0x0074 }, +{ 0x75 , 0x0075 }, +{ 0x76 , 0x0076 }, +{ 0x77 , 0x0077 }, +{ 0x78 , 0x0078 }, +{ 0x79 , 0x0079 }, +{ 0x7a , 0x007A }, +{ 0x7b , 0x007B }, +{ 0x7c , 0x007C }, +{ 0x7d , 0x007D }, +{ 0x7e , 0x007E }, +{ 0x7f , 0x007F }, +{ 0x80 , 0x2500 }, +{ 0x81 , 0x2502 }, +{ 0x82 , 0x250C }, +{ 0x83 , 0x2510 }, +{ 0x84 , 0x2514 }, +{ 0x85 , 0x2518 }, +{ 0x86 , 0x251C }, +{ 0x87 , 0x2524 }, +{ 0x88 , 0x252C }, +{ 0x89 , 0x2534 }, +{ 0x8a , 0x253C }, +{ 0x8b , 0x2580 }, +{ 0x8c , 0x2584 }, +{ 0x8d , 0x2588 }, +{ 0x8e , 0x258C }, +{ 0x8f , 0x2590 }, +{ 0x90 , 0x2591 }, +{ 0x91 , 0x2592 }, +{ 0x92 , 0x2593 }, +{ 0x93 , 0x2320 }, +{ 0x94 , 0x25A0 }, +{ 0x95 , 0x2219 }, +{ 0x96 , 0x221A }, +{ 0x97 , 0x2248 }, +{ 0x98 , 0x2264 }, +{ 0x99 , 0x2265 }, +{ 0x9a , 0x00A0 }, +{ 0x9b , 0x2321 }, +{ 0x9c , 0x00B0 }, +{ 0x9d , 0x00B2 }, +{ 0x9e , 0x00B7 }, +{ 0x9f , 0x00F7 }, +{ 0xa0 , 0x2550 }, +{ 0xa1 , 0x2551 }, +{ 0xa2 , 0x2552 }, +{ 0xa3 , 0x0451 }, +{ 0xa4 , 0x0454 }, +{ 0xa5 , 0x2554 }, +{ 0xa6 , 0x0456 }, +{ 0xa7 , 0x0457 }, +{ 0xa8 , 0x2557 }, +{ 0xa9 , 0x2558 }, +{ 0xaa , 0x2559 }, +{ 0xab , 0x255A }, +{ 0xac , 0x255B }, +{ 0xad , 0x0491 }, +{ 0xae , 0x255D }, +{ 0xaf , 0x255E }, +{ 0xb0 , 0x255F }, +{ 0xb1 , 0x2560 }, +{ 0xb2 , 0x2561 }, +{ 0xb3 , 0x0401 }, +{ 0xb4 , 0x0404 }, +{ 0xb5 , 0x2563 }, +{ 0xb6 , 0x0406 }, +{ 0xb7 , 0x0407 }, +{ 0xb8 , 0x2566 }, +{ 0xb9 , 0x2567 }, +{ 0xba , 0x2568 }, +{ 0xbb , 0x2569 }, +{ 0xbc , 0x256A }, +{ 0xbd , 0x0490 }, +{ 0xbe , 0x256C }, +{ 0xbf , 0x00A9 }, +{ 0xc0 , 0x044E }, +{ 0xc1 , 0x0430 }, +{ 0xc2 , 0x0431 }, +{ 0xc3 , 0x0446 }, +{ 0xc4 , 0x0434 }, +{ 0xc5 , 0x0435 }, +{ 0xc6 , 0x0444 }, +{ 0xc7 , 0x0433 }, +{ 0xc8 , 0x0445 }, +{ 0xc9 , 0x0438 }, +{ 0xca , 0x0439 }, +{ 0xcb , 0x043A }, +{ 0xcc , 0x043B }, +{ 0xcd , 0x043C }, +{ 0xce , 0x043D }, +{ 0xcf , 0x043E }, +{ 0xd0 , 0x043F }, +{ 0xd1 , 0x044F }, +{ 0xd2 , 0x0440 }, +{ 0xd3 , 0x0441 }, +{ 0xd4 , 0x0442 }, +{ 0xd5 , 0x0443 }, +{ 0xd6 , 0x0436 }, +{ 0xd7 , 0x0432 }, +{ 0xd8 , 0x044C }, +{ 0xd9 , 0x044B }, +{ 0xda , 0x0437 }, +{ 0xdb , 0x0448 }, +{ 0xdc , 0x044D }, +{ 0xdd , 0x0449 }, +{ 0xde , 0x0447 }, +{ 0xdf , 0x044A }, +{ 0xe0 , 0x042E }, +{ 0xe1 , 0x0410 }, +{ 0xe2 , 0x0411 }, +{ 0xe3 , 0x0426 }, +{ 0xe4 , 0x0414 }, +{ 0xe5 , 0x0415 }, +{ 0xe6 , 0x0424 }, +{ 0xe7 , 0x0413 }, +{ 0xe8 , 0x0425 }, +{ 0xe9 , 0x0418 }, +{ 0xea , 0x0419 }, +{ 0xeb , 0x041A }, +{ 0xec , 0x041B }, +{ 0xed , 0x041C }, +{ 0xee , 0x041D }, +{ 0xef , 0x041E }, +{ 0xf0 , 0x041F }, +{ 0xf1 , 0x042F }, +{ 0xf2 , 0x0420 }, +{ 0xf3 , 0x0421 }, +{ 0xf4 , 0x0422 }, +{ 0xf5 , 0x0423 }, +{ 0xf6 , 0x0416 }, +{ 0xf7 , 0x0412 }, +{ 0xf8 , 0x042C }, +{ 0xf9 , 0x042B }, +{ 0xfa , 0x0417 }, +{ 0xfb , 0x0428 }, +{ 0xfc , 0x042D }, +{ 0xfd , 0x0429 }, +{ 0xfe , 0x0427 }, +{ 0xff , 0x042A }, diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/TIS-620.pairs b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/TIS-620.pairs new file mode 100644 index 00000000..618a3be9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/charmaps/TIS-620.pairs @@ -0,0 +1,215 @@ +{ 0x00 , 0x0000 }, +{ 0x01 , 0x0001 }, +{ 0x02 , 0x0002 }, +{ 0x03 , 0x0003 }, +{ 0x04 , 0x0004 }, +{ 0x05 , 0x0005 }, +{ 0x06 , 0x0006 }, +{ 0x07 , 0x0007 }, +{ 0x08 , 0x0008 }, +{ 0x09 , 0x0009 }, +{ 0x0a , 0x000A }, +{ 0x0b , 0x000B }, +{ 0x0c , 0x000C }, +{ 0x0d , 0x000D }, +{ 0x0e , 0x000E }, +{ 0x0f , 0x000F }, +{ 0x10 , 0x0010 }, +{ 0x11 , 0x0011 }, +{ 0x12 , 0x0012 }, +{ 0x13 , 0x0013 }, +{ 0x14 , 0x0014 }, +{ 0x15 , 0x0015 }, +{ 0x16 , 0x0016 }, +{ 0x17 , 0x0017 }, +{ 0x18 , 0x0018 }, +{ 0x19 , 0x0019 }, +{ 0x1a , 0x001A }, +{ 0x1b , 0x001B }, +{ 0x1c , 0x001C }, +{ 0x1d , 0x001D }, +{ 0x1e , 0x001E }, +{ 0x1f , 0x001F }, +{ 0x20 , 0x0020 }, +{ 0x21 , 0x0021 }, +{ 0x22 , 0x0022 }, +{ 0x23 , 0x0023 }, +{ 0x24 , 0x0024 }, +{ 0x25 , 0x0025 }, +{ 0x26 , 0x0026 }, +{ 0x27 , 0x0027 }, +{ 0x28 , 0x0028 }, +{ 0x29 , 0x0029 }, +{ 0x2a , 0x002A }, +{ 0x2b , 0x002B }, +{ 0x2c , 0x002C }, +{ 0x2d , 0x002D }, +{ 0x2e , 0x002E }, +{ 0x2f , 0x002F }, +{ 0x30 , 0x0030 }, +{ 0x31 , 0x0031 }, +{ 0x32 , 0x0032 }, +{ 0x33 , 0x0033 }, +{ 0x34 , 0x0034 }, +{ 0x35 , 0x0035 }, +{ 0x36 , 0x0036 }, +{ 0x37 , 0x0037 }, +{ 0x38 , 0x0038 }, +{ 0x39 , 0x0039 }, +{ 0x3a , 0x003A }, +{ 0x3b , 0x003B }, +{ 0x3c , 0x003C }, +{ 0x3d , 0x003D }, +{ 0x3e , 0x003E }, +{ 0x3f , 0x003F }, +{ 0x40 , 0x0040 }, +{ 0x41 , 0x0041 }, +{ 0x42 , 0x0042 }, +{ 0x43 , 0x0043 }, +{ 0x44 , 0x0044 }, +{ 0x45 , 0x0045 }, +{ 0x46 , 0x0046 }, +{ 0x47 , 0x0047 }, +{ 0x48 , 0x0048 }, +{ 0x49 , 0x0049 }, +{ 0x4a , 0x004A }, +{ 0x4b , 0x004B }, +{ 0x4c , 0x004C }, +{ 0x4d , 0x004D }, +{ 0x4e , 0x004E }, +{ 0x4f , 0x004F }, +{ 0x50 , 0x0050 }, +{ 0x51 , 0x0051 }, +{ 0x52 , 0x0052 }, +{ 0x53 , 0x0053 }, +{ 0x54 , 0x0054 }, +{ 0x55 , 0x0055 }, +{ 0x56 , 0x0056 }, +{ 0x57 , 0x0057 }, +{ 0x58 , 0x0058 }, +{ 0x59 , 0x0059 }, +{ 0x5a , 0x005A }, +{ 0x5b , 0x005B }, +{ 0x5c , 0x005C }, +{ 0x5d , 0x005D }, +{ 0x5e , 0x005E }, +{ 0x5f , 0x005F }, +{ 0x60 , 0x0060 }, +{ 0x61 , 0x0061 }, +{ 0x62 , 0x0062 }, +{ 0x63 , 0x0063 }, +{ 0x64 , 0x0064 }, +{ 0x65 , 0x0065 }, +{ 0x66 , 0x0066 }, +{ 0x67 , 0x0067 }, +{ 0x68 , 0x0068 }, +{ 0x69 , 0x0069 }, +{ 0x6a , 0x006A }, +{ 0x6b , 0x006B }, +{ 0x6c , 0x006C }, +{ 0x6d , 0x006D }, +{ 0x6e , 0x006E }, +{ 0x6f , 0x006F }, +{ 0x70 , 0x0070 }, +{ 0x71 , 0x0071 }, +{ 0x72 , 0x0072 }, +{ 0x73 , 0x0073 }, +{ 0x74 , 0x0074 }, +{ 0x75 , 0x0075 }, +{ 0x76 , 0x0076 }, +{ 0x77 , 0x0077 }, +{ 0x78 , 0x0078 }, +{ 0x79 , 0x0079 }, +{ 0x7a , 0x007A }, +{ 0x7b , 0x007B }, +{ 0x7c , 0x007C }, +{ 0x7d , 0x007D }, +{ 0x7e , 0x007E }, +{ 0x7f , 0x007F }, +{ 0xa1 , 0x0E01 }, +{ 0xa2 , 0x0E02 }, +{ 0xa3 , 0x0E03 }, +{ 0xa4 , 0x0E04 }, +{ 0xa5 , 0x0E05 }, +{ 0xa6 , 0x0E06 }, +{ 0xa7 , 0x0E07 }, +{ 0xa8 , 0x0E08 }, +{ 0xa9 , 0x0E09 }, +{ 0xaa , 0x0E0A }, +{ 0xab , 0x0E0B }, +{ 0xac , 0x0E0C }, +{ 0xad , 0x0E0D }, +{ 0xae , 0x0E0E }, +{ 0xaf , 0x0E0F }, +{ 0xb0 , 0x0E10 }, +{ 0xb1 , 0x0E11 }, +{ 0xb2 , 0x0E12 }, +{ 0xb3 , 0x0E13 }, +{ 0xb4 , 0x0E14 }, +{ 0xb5 , 0x0E15 }, +{ 0xb6 , 0x0E16 }, +{ 0xb7 , 0x0E17 }, +{ 0xb8 , 0x0E18 }, +{ 0xb9 , 0x0E19 }, +{ 0xba , 0x0E1A }, +{ 0xbb , 0x0E1B }, +{ 0xbc , 0x0E1C }, +{ 0xbd , 0x0E1D }, +{ 0xbe , 0x0E1E }, +{ 0xbf , 0x0E1F }, +{ 0xc0 , 0x0E20 }, +{ 0xc1 , 0x0E21 }, +{ 0xc2 , 0x0E22 }, +{ 0xc3 , 0x0E23 }, +{ 0xc4 , 0x0E24 }, +{ 0xc5 , 0x0E25 }, +{ 0xc6 , 0x0E26 }, +{ 0xc7 , 0x0E27 }, +{ 0xc8 , 0x0E28 }, +{ 0xc9 , 0x0E29 }, +{ 0xca , 0x0E2A }, +{ 0xcb , 0x0E2B }, +{ 0xcc , 0x0E2C }, +{ 0xcd , 0x0E2D }, +{ 0xce , 0x0E2E }, +{ 0xcf , 0x0E2F }, +{ 0xd0 , 0x0E30 }, +{ 0xd1 , 0x0E31 }, +{ 0xd2 , 0x0E32 }, +{ 0xd3 , 0x0E33 }, +{ 0xd4 , 0x0E34 }, +{ 0xd5 , 0x0E35 }, +{ 0xd6 , 0x0E36 }, +{ 0xd7 , 0x0E37 }, +{ 0xd8 , 0x0E38 }, +{ 0xd9 , 0x0E39 }, +{ 0xda , 0x0E3A }, +{ 0xdf , 0x0E3F }, +{ 0xe0 , 0x0E40 }, +{ 0xe1 , 0x0E41 }, +{ 0xe2 , 0x0E42 }, +{ 0xe3 , 0x0E43 }, +{ 0xe4 , 0x0E44 }, +{ 0xe5 , 0x0E45 }, +{ 0xe6 , 0x0E46 }, +{ 0xe7 , 0x0E47 }, +{ 0xe8 , 0x0E48 }, +{ 0xe9 , 0x0E49 }, +{ 0xea , 0x0E4A }, +{ 0xeb , 0x0E4B }, +{ 0xec , 0x0E4C }, +{ 0xed , 0x0E4D }, +{ 0xee , 0x0E4E }, +{ 0xef , 0x0E4F }, +{ 0xf0 , 0x0E50 }, +{ 0xf1 , 0x0E51 }, +{ 0xf2 , 0x0E52 }, +{ 0xf3 , 0x0E53 }, +{ 0xf4 , 0x0E54 }, +{ 0xf5 , 0x0E55 }, +{ 0xf6 , 0x0E56 }, +{ 0xf7 , 0x0E57 }, +{ 0xf8 , 0x0E58 }, +{ 0xf9 , 0x0E59 }, +{ 0xfa , 0x0E5A }, +{ 0xfb , 0x0E5B }, diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/af_ZA b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/af_ZA new file mode 100644 index 00000000..d66184ec --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/af_ZA @@ -0,0 +1 @@ +copy "en_DK" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/am_ET b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/am_ET new file mode 100644 index 00000000..94a91817 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/am_ET @@ -0,0 +1,26 @@ + +% Copy the template from ISO/IEC 14651 +copy "iso14651_t1" + +% Correct Unicode Addressing +script +order_start ;forward +# qW qWi + + +# QW QWi + + +# hW hWi + + +# kW kWi + + +# KW KWi + + +# gW gWi + + +order_end diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ar_AE b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ar_AE new file mode 100644 index 00000000..35ae3c60 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ar_AE @@ -0,0 +1,4 @@ + +% Copy the template from ISO/IEC 14651 +copy "iso14651_t1" + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ar_BH b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ar_BH new file mode 100644 index 00000000..35ae3c60 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ar_BH @@ -0,0 +1,4 @@ + +% Copy the template from ISO/IEC 14651 +copy "iso14651_t1" + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ar_DZ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ar_DZ new file mode 100644 index 00000000..35ae3c60 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ar_DZ @@ -0,0 +1,4 @@ + +% Copy the template from ISO/IEC 14651 +copy "iso14651_t1" + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ar_EG b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ar_EG new file mode 100644 index 00000000..35ae3c60 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ar_EG @@ -0,0 +1,4 @@ + +% Copy the template from ISO/IEC 14651 +copy "iso14651_t1" + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ar_IN b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ar_IN new file mode 100644 index 00000000..d05f74d8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ar_IN @@ -0,0 +1,3 @@ +% Copy the template from ISO/IEC 14651 +copy "iso14651_t1" + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ar_IQ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ar_IQ new file mode 100644 index 00000000..35ae3c60 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ar_IQ @@ -0,0 +1,4 @@ + +% Copy the template from ISO/IEC 14651 +copy "iso14651_t1" + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ar_JO b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ar_JO new file mode 100644 index 00000000..35ae3c60 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ar_JO @@ -0,0 +1,4 @@ + +% Copy the template from ISO/IEC 14651 +copy "iso14651_t1" + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ar_KW b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ar_KW new file mode 100644 index 00000000..35ae3c60 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ar_KW @@ -0,0 +1,4 @@ + +% Copy the template from ISO/IEC 14651 +copy "iso14651_t1" + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ar_LB b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ar_LB new file mode 100644 index 00000000..35ae3c60 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ar_LB @@ -0,0 +1,4 @@ + +% Copy the template from ISO/IEC 14651 +copy "iso14651_t1" + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ar_LY b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ar_LY new file mode 100644 index 00000000..35ae3c60 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ar_LY @@ -0,0 +1,4 @@ + +% Copy the template from ISO/IEC 14651 +copy "iso14651_t1" + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ar_MA b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ar_MA new file mode 100644 index 00000000..35ae3c60 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ar_MA @@ -0,0 +1,4 @@ + +% Copy the template from ISO/IEC 14651 +copy "iso14651_t1" + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ar_OM b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ar_OM new file mode 100644 index 00000000..35ae3c60 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ar_OM @@ -0,0 +1,4 @@ + +% Copy the template from ISO/IEC 14651 +copy "iso14651_t1" + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ar_QA b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ar_QA new file mode 100644 index 00000000..35ae3c60 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ar_QA @@ -0,0 +1,4 @@ + +% Copy the template from ISO/IEC 14651 +copy "iso14651_t1" + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ar_SA b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ar_SA new file mode 100644 index 00000000..a01c4ecf --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ar_SA @@ -0,0 +1,220 @@ + + +order_start forward; forward + + + + + + + + + + + + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + ; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + IGNORE + IGNORE + IGNORE + IGNORE + IGNORE + IGNORE + IGNORE + IGNORE + IGNORE + +% UCLIBC -- add an explicit UNDEFINED entry +UNDEFINED +order_end + + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ar_SD b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ar_SD new file mode 100644 index 00000000..35ae3c60 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ar_SD @@ -0,0 +1,4 @@ + +% Copy the template from ISO/IEC 14651 +copy "iso14651_t1" + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ar_SY b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ar_SY new file mode 100644 index 00000000..35ae3c60 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ar_SY @@ -0,0 +1,4 @@ + +% Copy the template from ISO/IEC 14651 +copy "iso14651_t1" + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ar_TN b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ar_TN new file mode 100644 index 00000000..35ae3c60 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ar_TN @@ -0,0 +1,4 @@ + +% Copy the template from ISO/IEC 14651 +copy "iso14651_t1" + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ar_YE b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ar_YE new file mode 100644 index 00000000..35ae3c60 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ar_YE @@ -0,0 +1,4 @@ + +% Copy the template from ISO/IEC 14651 +copy "iso14651_t1" + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/az_AZ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/az_AZ new file mode 100644 index 00000000..daaeacca --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/az_AZ @@ -0,0 +1,137 @@ +% The new (1991) latin azeri alphabet is: +% , , , , , , , , , , , , +% (dotless i), (i with dot), , , , , , , , +% ,

, , , , , , , , , +% +% cyrillic alphabet: +% , , , , , , , , , , , +% , , , , , , , , , , , +% , , , , , , , , + +copy "iso14651_t1" + +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +reorder-after + +reorder-after + +reorder-after + +reorder-after + + + + + + +reorder-after + +reorder-after + +reorder-after + + +reorder-after + +reorder-after + +reorder-after + +reorder-after + +reorder-after + +reorder-after + +reorder-after + + +reorder-after + ;;;IGNORE +reorder-after + ;;;IGNORE + +reorder-after + ;;;IGNORE +reorder-after + ;;;IGNORE + +reorder-after + ;;;IGNORE +reorder-after + ;;;IGNORE + +reorder-after + ;;;IGNORE + ;;;IGNORE +reorder-after + ;;;IGNORE + ;;;IGNORE + +reorder-after + ;;;IGNORE +reorder-after + ;;;IGNORE + +reorder-after + ;;;IGNORE +reorder-after + ;;;IGNORE + +reorder-after + ;;;IGNORE +reorder-after + ;;;IGNORE + +reorder-after + ;;;IGNORE +reorder-after + ;;;IGNORE + +reorder-after + ;;;IGNORE +reorder-after + ;;;IGNORE + +reorder-after + ;;;IGNORE +reorder-after + ;;;IGNORE + +reorder-after + ;;;IGNORE +reorder-after + ;;;IGNORE + +reorder-after + ;;;IGNORE +reorder-after + ;;;IGNORE + +reorder-after + ;;;IGNORE +reorder-after + ;;;IGNORE + +reorder-after + ;;;IGNORE +reorder-after + ;;;IGNORE + +reorder-end + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/be_BY b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/be_BY new file mode 100644 index 00000000..342a761d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/be_BY @@ -0,0 +1,15 @@ +copy "iso14651_t1" + +% iso14651_t1 is missing Ukrainian ghe +collating-symbol + +reorder-after + + +reorder-after + ;;;IGNORE + +reorder-after + ;;;IGNORE + +reorder-end diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/bg_BG b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/bg_BG new file mode 100644 index 00000000..ddf84dcf --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/bg_BG @@ -0,0 +1,106 @@ + +% We have made the following changes to the basic collation scheme in +% the file iso14651_t1: +% 1. The Cyrillic script is first in the order. +% 2. The non-Bulgarian Cyrillic letters are sorted according to +% their transliteration with Bulgarian Cyrillic letters. + +copy "iso14651_t1" +reorder-after <9> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +reorder-after + ;;;IGNORE % Mac. gje +reorder-after + "";"";"";IGNORE % CYR-DJE + "";"";"";IGNORE % CYR-DCHE + "";"";"";IGNORE % CYR-DZE +reorder-after + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE +reorder-after + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE +reorder-after + ;;;IGNORE +reorder-after + "";"";"";IGNORE % CYR-LJE +reorder-after + "";"";"";IGNORE % CYR-NJE +reorder-after + ;;;IGNORE +reorder-after + ;;;IGNORE +reorder-after + ;;;IGNORE % Mac. gje +reorder-after + "";"";"";IGNORE % CYR-DJE + "";"";"";IGNORE % CYR-DCHE + "";"";"";IGNORE % CYR-DZE +reorder-after + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE +reorder-after + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE +reorder-after + ;;;IGNORE +reorder-after + ;;;IGNORE +reorder-after + "";"";"";IGNORE % CYR-LJE +reorder-after + "";"";"";IGNORE % CYR-NJE +reorder-after + ;;;IGNORE +reorder-after + ;;;IGNORE +reorder-end diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/bn_BD b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/bn_BD new file mode 100644 index 00000000..9a3ff3be --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/bn_BD @@ -0,0 +1,2 @@ +% TODO: Bengali sorting should be added +copy "iso14651_t1" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/bn_IN b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/bn_IN new file mode 100644 index 00000000..0caba146 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/bn_IN @@ -0,0 +1,4 @@ +% Copy the template from ISO/IEC 14651 +copy "iso14651_t1" + +% diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/br_FR b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/br_FR new file mode 100644 index 00000000..0887c81b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/br_FR @@ -0,0 +1,40 @@ +copy "iso14651_t1" + +%% a b c ch c'h d e f g h i j k l m n o p q r s t u v w x y z +collating-symbol +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-symbol +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-symbol +collating-symbol + +reorder-after + + +reorder-after + + +reorder-after + + + +reorder-after + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE +reorder-after + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + +reorder-end + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/bs_BA b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/bs_BA new file mode 100644 index 00000000..24be941d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/bs_BA @@ -0,0 +1,91 @@ +copy "iso14651_t1" + +% a b c c' c< d dz< d// e f g h i j k l lj m n nj o p +% q r s s< t u v w x y z z< + +collating-symbol +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-symbol +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-symbol +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +collating-symbol +collating-symbol + +reorder-after + +reorder-after + + +reorder-after + + + + + +reorder-after + +reorder-after + +reorder-after + +reorder-after + + +reorder-after + ;;;IGNORE + ;;;IGNORE +reorder-after + ;;;IGNORE + ;;;IGNORE + +reorder-after + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE +reorder-after + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + +%reorder-after + ;;;IGNORE + ;;;IGNORE +reorder-after + ;;;IGNORE + ;;;IGNORE + +reorder-after + ;;;IGNORE + ;;;IGNORE +reorder-after + ;;;IGNORE + ;;;IGNORE + +reorder-after + ;;;IGNORE +reorder-after + ;;;IGNORE + +reorder-after + ;;;IGNORE +reorder-after + ;;;IGNORE + +reorder-end + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ca_ES b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ca_ES new file mode 100644 index 00000000..2c0a0334 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ca_ES @@ -0,0 +1,2061 @@ + +% Base collation scheme: 1994-03-22 + +% Ordering algorithm: +% 1. Spaces and hyphen (but not soft +% hyphen) before punctuation +% characters, punctuation characters +% before numbers, +% numbers before letters. +% 2. Letters with diacritical marks are +% members of equivalence classes +% 3. A distinction is made with regards +% to case as noted below. +% 4. Special characters are ignored +% when comparing letters, but then +% they are considered +% 5. The alphabets are sorted in order +% of first appearance in ISO 10646: +% Latin, Greek, Cyrillic, etc. +% +% According to Greek specifications, +% the steps 2. and 3. above are reversed +% for the Greek script + +% collating symbols + +% The collating symbol naming is +% mostly taken from ISO 10646-1, +% for example the case and accent +% names are from this standard. + +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +% and +% are for cases like Danish +% and Spanish being treated +% as one letter. + +% The ...... collating +% symbols have defined weights as +% the last character in a group of +% Latin letters. They are used +% to specify deltas by locales using +% a locale as the default ordering +% and by "replace-after" statements +% specifying the changed placement +% in an ordering of a character. + +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +% letter;accent;case;specials + +order_start forward;backward;forward;position + +% or letters first: + + + + + + +% Accents: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ;;;IGNORE + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; +<"=> IGNORE;IGNORE;IGNORE;<"=> + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; +UNDEFINED IGNORE;IGNORE;IGNORE + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + +% Arabic collating + + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + +% katakana/hiragana sorting +% base is katakana, as this is present in most charsets +% normal before voiced before semi-voiced +% small vocals before normal vocals +% katakana before hiragana + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + +order_end + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/comm b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/comm new file mode 100644 index 00000000..356df603 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/comm @@ -0,0 +1,1872 @@ + +% Base collation scheme: 1994-03-22 + +% Ordering algorithm: +% 1. Spaces and hyphen (but not soft +% hyphen) before punctuation +% characters, punctuation characters +% before numbers, +% numbers before letters. +% 2. Letters with diacritical marks are +% members of equivalence classes +% 3. A distinction is made with regards +% to case as noted below. +% 4. Special characters are ignored +% when comparing letters, but then +% they are considered +% 5. The alphabets are sorted in order +% of first appearance in ISO 10646: +% Latin, Greek, Cyrillic, etc. +% +% According to Greek specifications, +% the steps 2. and 3. above are reversed +% for the Greek script + +% collating symbols + +% The collating symbol naming is +% mostly taken from ISO 10646-1, +% for example the case and accent +% names are from this standard. + +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +% and +% are for cases like Danish +% and Spanish being treated +% as one letter. + +% The ...... collating +% symbols have defined weights as +% the last character in a group of +% Latin letters. They are used +% to specify deltas by locales using +% a locale as the default ordering +% and by "replace-after" statements +% specifying the changed placement +% in an ordering of a character. + +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +% letter;accent;case;specials + +order_start forward;backward;forward;position + +% or letters first: + + + +% Accents: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ;;;IGNORE + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; +<"=> IGNORE;IGNORE;IGNORE;<"=> + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; +UNDEFINED IGNORE;IGNORE;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + +% Arabic collating + + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + +% katakana/hiragana sorting +% base is katakana, as this is present in most charsets +% normal before voiced before semi-voiced +% small vocals before normal vocals +% katakana before hiragana + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + +order_end + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/cs_CZ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/cs_CZ new file mode 100644 index 00000000..734f4a79 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/cs_CZ @@ -0,0 +1,2162 @@ + +% Base collation scheme: 1994-03-22 + +% Ordering algorithm: +% 1. Spaces and hyphen (but not soft +% hyphen) before punctuation +% characters, punctuation characters +% before letters, +% numbers after letters. +% 2. Letters with diacritical marks are +% members of equivalence classes +% 3. A distinction is made with regards +% to case as noted below. +% 4. Special characters are ignored +% when comparing letters, but then +% they are considered +% 5. The alphabets are sorted in order +% of first appearance in ISO 10646: +% Latin, Greek, Cyrillic, etc. +% +% According to Greek specifications, +% the steps 2. and 3. above are reversed +% for the Greek script + +% collating symbols + +% The collating symbol naming is +% mostly taken from ISO 10646-1, +% for example the case and accent +% names are from this standard. + +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +% and +% are for cases like Danish +% and Spanish being treated +% as one letter. + +% The ...... collating +% symbols have defined weights as +% the last character in a group of +% Latin letters. They are used +% to specify deltas by locales using +% a locale as the default ordering +% and by "replace-after" statements +% specifying the changed placement +% in an ordering of a character. + +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + + +% Definice písmene ch + +collating-element from "" +collating-element from "" +collating-element from "" + + +% letter;accent;case;specials + +%order_start forward;forward;forward;forward +order_start forward;forward;forward;forward + +% or letters first: + + + + + + +% Accents: +% Poøadí akcentù: nahoøe, dole, vzadu, vpøedu, uvnitø nebo pøes písmeno +% pokud toto nerozhodne zále¾í na poètu a tvaru + + +% nahoøe + % Teèka + % Vodorovná èárka nahoøe + % Èárka ' (napø: á) + % Zpìtná èárka ` + % Støí¹ka ^ (napø: â) + % Háèek + % Tilda (~) + % Dolní pùlkrou¾ek (vypadá jako sjednocení) +% Horní pùlkrou¾ek (vypadá jako prùnik) + % Krou¾ek + % netu¹ím jaké diakritické znaménko to je, pøedpokládám je nahoøe + % netu¹ím jaké diakritické znaménko to je, pøedpokládám je nahoøe + + % Dvì teèky + + % Dvì èárky + % Dvì zpìtné èárky + + + + + + + + + + + + + + + + + + + + + + + + + + + + +% nahoøe a dole + % Zde si nejsem jist jak je to mínìno, zda obì pod + % nebo pouze to druhé + + + + + + + + +% nahoøe a uprostøed + + +% dole + + + + + % Zobáèek pod písmenem vypadá skoro jako s (º) + % Zobáèek pod písmenem obrácený k pøedchozímu (jako c)(ê) + +% za +% pøed + +% uprostøed + % ©krtnutí písmene v prostøedku (polské ³) + + + + + + + + + + + ;;; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Zde jsou v¹echna latinská písmena s diakritikou +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + + + "";"";"";"" + "";"";"";"" + "";"";"";"" + "";"";"";"" + "";"";"";"" + "";"";"";"" + + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + + + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + + ;;; + ;;; + + + + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + + + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + + + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + + + "";"";"";"" + "";"";"";"" + "";"";"";"" + "";"";"";"" + "";"";"";"" + + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + + + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + + + ;;; + ;;; + ;;; + + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + + + "";"";"";"" + "";"";"";"" + + ;;; + ;;; + ;;; + ;;; + + + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + + ;;; + + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + + + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + + + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + + + "";"";"";"" + "";"";"";"" + + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + + + "";"";"";"" + "";"";"";"" + + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + + + ;;; + ;;; + + + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + + ;;; + ;;; + + + ;;; + ;;; + "";"";"";"" + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + + ;;; + ;;; + ;;; + ;;; + + + ;;; + "";"";"";"" + "";"";"";IGNORE + + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + + + "";"";"";"" + "";"";"";"" + + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + + + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + + + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + + + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + + + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + + + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + + + ;;; + ;;; + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Èíslice +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% V¹echny speciální znaky (sna¾il jsem se to seøadit podle normy, ale moc se +% mi nedaøilo) +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + +% znaménka + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; +% Uvozovky + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + +% ustálené znaèky + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + +% grafické znaèky a obrazce lineární + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + +% grafické znaèky a obrazce plo¹né + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + +% Akcenty, nevím kam je zaøadit (nìkteré jsou brány jako uvozovky) + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; +% IGNORE;IGNORE;IGNORE; % pøemístìn do uvozovek +% IGNORE;IGNORE;IGNORE; % pøemístìn do obrazcù lineárních + IGNORE;IGNORE;IGNORE; +% tilda + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + +% Neseøazeno + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; +UNDEFINED IGNORE;IGNORE;IGNORE;IGNORE + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Zbytek vìcí z unikodu +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;IGNORE;IGNORE; + ;IGNORE;IGNORE; + ;IGNORE;IGNORE; + ;IGNORE;IGNORE; + ;IGNORE;IGNORE; + ;IGNORE;IGNORE; + ;IGNORE;IGNORE; + ;IGNORE;IGNORE; + ;IGNORE;IGNORE; + ;IGNORE;IGNORE; + ;IGNORE;IGNORE; + ;IGNORE;IGNORE; + ;IGNORE;IGNORE; + ;IGNORE;IGNORE; + ;IGNORE;IGNORE; + ;IGNORE;IGNORE; + ;IGNORE;IGNORE; + ;IGNORE;IGNORE; + ;IGNORE;IGNORE; + ;IGNORE;IGNORE; + ;IGNORE;IGNORE; + ;IGNORE;IGNORE; + ;IGNORE;IGNORE; + ;IGNORE;IGNORE; + ;IGNORE;IGNORE; + ;IGNORE;IGNORE; + ;IGNORE;IGNORE; + +% Arabic collating + + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + + IGNORE;IGNORE;; + IGNORE;IGNORE;; + IGNORE;IGNORE;; + IGNORE;IGNORE;; + IGNORE;IGNORE;; + IGNORE;IGNORE;; + IGNORE;IGNORE;; + IGNORE;IGNORE;; + IGNORE;IGNORE;; + + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + + "";"";"";"" + "";"";"";"" + "";"";"";"" + "";"";"";"" + "";"";"";"" + "";"";"";"" + "";"";"";"" + "";"";"";"" + +% katakana/hiragana sorting +% base is katakana, as this is present in most charsets +% normal before voiced before semi-voiced +% small vocals before normal vocals +% katakana before hiragana + + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + ;;IGNORE; + +order_end + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/cy_GB b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/cy_GB new file mode 100644 index 00000000..6cda6767 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/cy_GB @@ -0,0 +1,136 @@ +copy "iso14651_t1" + +% Welsh sorting order is: +% a b c ch d dd e f ff g ng h i l ll m n o p ph r rh s t th u w y + +collating-symbol +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-symbol +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-symbol +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-symbol +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-symbol +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-symbol +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-symbol +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-symbol +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-symbol +collating-symbol + +reorder-after + +reorder-after + + +reorder-after + + + +reorder-after + + + +reorder-after + +reorder-after

+collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +# +# / +# +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +# +# +# +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +# +# GREC +# +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +# +# CYRIL +# +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +# Ordre des symboles internes / Order of internal symbols +# +# SYMB. N° +# + + +# forme de base (bas de casse, arabe intrinsèque, +# hébreu intrinsèque, etc. +# basic form (lower case, intrinsic Arabic +# intrinsic Hebrew and so on) +# +# / +# +# + # voir + # isol. +# 3 + # final +# 4 + # initial +# 5 + # medial/mdian +# 6 +# + # 7 + # 8 + # 9 + # 10 + # 11 + +#alternate lower case/ +# 12 +# +#minuscules spéciales après majuscules +# / +# + # accent madda #13 + # accent hamza #14 + # accent hamza/waw #14 1 + # accent hamza under / hamza souscrit #14 2 + # accent under yeh / accent souscrit du ya' #14 3 + # accent hamza/yeh barree #14 4 +# + # 15 +# + # 16 + # 17 + # 18 + # 19 + # 20 + # 21 + # 22 + # 23 + # 24 + # 25 + # 26 + # 27 + # 28 + # 29 + # 30 + # 31 +# +# GREC +# + # accent aigu/tonos/acute accent + # trma/dialytica/diaeresis + # dialytika tonos +# +<0> # 48 +<1> # 49 +<2> # 50 +<3> # 51 +<4> # 52 +<5> # 53 +<6> # 54 +<7> # 55 +<8> # 56 +<9> # 57 +# + # 97 + # 98 + # 99 + # 100 + # 101 + # 102 + # 103 + # 104 + # 105 + # 106 + # 107 + # 108 + # 109 + # 110 + # 111 +

# 112 + # 113 + # 114 + # 115 + # 116 + # 117 + # 118 + # 119 + # 120 + # 121 + # 122 +# 122b +# +# / +# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +# +# +# + + + + + + + + + + + + + + + + + + + + + + + + + + + +# +#GREC +# + + + + + + + + + + + + + + + + + + + + + + + + +# +#CYRIL +# + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +order_start ;forward;backward;forward;forward,position +# +# Tout caractère non précisément défini sera considéré comme caractère spécial +# et considéré uniquement au dernier niveau. +# +# Any character not precisely specified will be considered as a special +# character and considered only at the last level. +# ...... IGNORE;IGNORE;IGNORE;...... +# +# SYMB. N° GLY +# + IGNORE;IGNORE;IGNORE; # 32 + IGNORE;IGNORE;IGNORE; # 33 _ + IGNORE;IGNORE;IGNORE; # 34 <"_> + IGNORE;IGNORE;IGNORE; # 35 - (MACRON) + IGNORE;IGNORE;IGNORE; # 36 + IGNORE;IGNORE;IGNORE; # 37 - + IGNORE;IGNORE;IGNORE; # 38 , + IGNORE;IGNORE;IGNORE; # 39 ; + IGNORE;IGNORE;IGNORE; # 40 : + IGNORE;IGNORE;IGNORE; # 41 ! + IGNORE;IGNORE;IGNORE; # 42 ¡ + IGNORE;IGNORE;IGNORE; # 43 ? + IGNORE;IGNORE;IGNORE; # 44 ¿ + IGNORE;IGNORE;IGNORE; # 45 / + IGNORE;IGNORE;IGNORE; # 46 <"/> + IGNORE;IGNORE;IGNORE; # 47 . + IGNORE;IGNORE;IGNORE; # 58 × + IGNORE;IGNORE;IGNORE; # 59 ¸ + IGNORE;IGNORE;IGNORE; # 60 <";> + IGNORE;IGNORE;IGNORE; # 61 ' + IGNORE;IGNORE;IGNORE; # 62 <'6> + IGNORE;IGNORE;IGNORE; # 63 <'9> + IGNORE;IGNORE;IGNORE; # 64 " + IGNORE;IGNORE;IGNORE; # 65 <"6> + IGNORE;IGNORE;IGNORE; # 66 <"9> + IGNORE;IGNORE;IGNORE; # 67 « + IGNORE;IGNORE;IGNORE; # 68 » + IGNORE;IGNORE;IGNORE; # 69 ( + IGNORE;IGNORE;IGNORE; # 70 <(S> + IGNORE;IGNORE;IGNORE; # 71 ) + IGNORE;IGNORE;IGNORE; # 72 <)S> + IGNORE;IGNORE;IGNORE; # 73 [ + IGNORE;IGNORE;IGNORE; # 74 ] + IGNORE;IGNORE;IGNORE; # 75 { + IGNORE;IGNORE;IGNORE; # 76 } + IGNORE;IGNORE;IGNORE; # 77 § + IGNORE;IGNORE;IGNORE; # 78 ¶ + IGNORE;IGNORE;IGNORE; # 79 © + IGNORE;IGNORE;IGNORE; # 80 ® + IGNORE;IGNORE;IGNORE; # 81 + IGNORE;IGNORE;IGNORE; # 82 @ + IGNORE;IGNORE;IGNORE; # 83 ¤ + IGNORE;IGNORE;IGNORE; # 84 ¢ + IGNORE;IGNORE;IGNORE; # 85 $ + IGNORE;IGNORE;IGNORE; # 86 £ + IGNORE;IGNORE;IGNORE; # 87 ¥ + IGNORE;IGNORE;IGNORE; # ecu + IGNORE;IGNORE;IGNORE; # colon + IGNORE;IGNORE;IGNORE; # cruzeiro + IGNORE;IGNORE;IGNORE; # french franc + IGNORE;IGNORE;IGNORE; # lira + IGNORE;IGNORE;IGNORE; # mill + IGNORE;IGNORE;IGNORE; # naira + IGNORE;IGNORE;IGNORE; # peseta + IGNORE;IGNORE;IGNORE; # rupee + IGNORE;IGNORE;IGNORE; # won + IGNORE;IGNORE;IGNORE; # new sheqel + IGNORE;IGNORE;IGNORE; # dong + IGNORE;IGNORE;IGNORE; # euro + IGNORE;IGNORE;IGNORE; # kip + IGNORE;IGNORE;IGNORE; # tugrik + IGNORE;IGNORE;IGNORE; # drachma + IGNORE;IGNORE;IGNORE; # 88 * + IGNORE;IGNORE;IGNORE; # 89 + IGNORE;IGNORE;IGNORE; # 90 & + IGNORE;IGNORE;IGNORE; # 91 # + IGNORE;IGNORE;IGNORE; # 92 % + IGNORE;IGNORE;IGNORE; # 93 <-S> + IGNORE;IGNORE;IGNORE; # 94 + + IGNORE;IGNORE;IGNORE; # 95 <+S> + IGNORE;IGNORE;IGNORE; # 96 ± + IGNORE;IGNORE;IGNORE;<0> # 123 ´ + IGNORE;IGNORE;IGNORE;<1> # 124 ` + IGNORE;IGNORE;IGNORE;<2> # 125 <"(> + IGNORE;IGNORE;IGNORE;<3> # 126 ^ + IGNORE;IGNORE;IGNORE;<4> # 127 <"<> + IGNORE;IGNORE;IGNORE;<5> # 128 <"0> + IGNORE;IGNORE;IGNORE;<6> # 129 ¨ + IGNORE;IGNORE;IGNORE;<7> # 130 <""> + IGNORE;IGNORE;IGNORE;<8> # 131 ~ + IGNORE;IGNORE;IGNORE;<9> # 132 <".> + IGNORE;IGNORE;IGNORE; # 133 ¸ + IGNORE;IGNORE;IGNORE; # 134 ´ + IGNORE;IGNORE;IGNORE; # 135 + IGNORE;IGNORE;IGNORE; # 136 < + IGNORE;IGNORE;IGNORE; # 137 <=<> + IGNORE;IGNORE;IGNORE; # 138 = + IGNORE;IGNORE;IGNORE; # 139 => + IGNORE;IGNORE;IGNORE; # 140 > + IGNORE;IGNORE;IGNORE; # 141 ¬ + IGNORE;IGNORE;IGNORE; # 142 | + IGNORE;IGNORE;IGNORE; # 143 | + IGNORE;IGNORE;IGNORE; # 144 ° + IGNORE;IGNORE;IGNORE; # 145 m + IGNORE;IGNORE;IGNORE; # 146 + IGNORE;IGNORE;IGNORE; # 147 + IGNORE;IGNORE;IGNORE;

# 148 <_V/>> + IGNORE;IGNORE;IGNORE; # 149 <_V-> + IGNORE;IGNORE;IGNORE; # 150 <_V + IGNORE;IGNORE;IGNORE; # 151 <_!/>> + IGNORE;IGNORE;IGNORE; # 152 <_!-> + IGNORE;IGNORE;IGNORE; # 153 <_!<> + IGNORE;IGNORE;IGNORE; # 154 <_A/>> + IGNORE;IGNORE;IGNORE; # 155 <_-A> + IGNORE;IGNORE;IGNORE; # 156 <_A<> + IGNORE;IGNORE;IGNORE; # 157 <_!> + IGNORE;IGNORE;IGNORE; # 158 <_-> # + IGNORE;IGNORE;IGNORE; # 159 <_=> + IGNORE;IGNORE;IGNORE; # 160 <<-> + IGNORE;IGNORE;IGNORE; # 161 <-/>> + IGNORE;IGNORE;IGNORE; # 162 <"7> + IGNORE;IGNORE;IGNORE; # 163 <-!> + IGNORE;IGNORE;IGNORE; # 164 <-v> + IGNORE;IGNORE;IGNORE; # 165 <_d!> + IGNORE;IGNORE;IGNORE; # 166 <_/>//> + IGNORE;IGNORE;IGNORE; # 167 <_<\> + IGNORE;IGNORE;IGNORE; # 168 <_./>//> + IGNORE;IGNORE;IGNORE; # 169 <_.<\> # # / # + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; # + IGNORE;IGNORE;IGNORE; # + IGNORE;IGNORE;IGNORE; # + IGNORE;IGNORE;IGNORE; # + IGNORE;IGNORE;IGNORE; # + IGNORE;IGNORE;IGNORE; # + IGNORE;IGNORE;IGNORE; # + IGNORE;IGNORE;IGNORE; # + IGNORE;IGNORE;IGNORE; # + IGNORE;IGNORE;IGNORE; # + IGNORE;IGNORE;IGNORE; # + IGNORE;IGNORE;IGNORE; # + IGNORE;IGNORE;IGNORE; # + IGNORE;IGNORE;IGNORE; # + IGNORE;IGNORE;IGNORE; # + IGNORE;IGNORE;IGNORE; # + IGNORE;IGNORE;IGNORE; # + IGNORE;IGNORE;IGNORE; # + IGNORE;IGNORE;IGNORE; # + IGNORE;IGNORE;IGNORE; # + IGNORE;IGNORE;IGNORE; # + IGNORE;IGNORE;IGNORE; # # # # + IGNORE;IGNORE;IGNORE; #point_sheva + IGNORE;IGNORE;IGNORE; #point_hataf_segol + IGNORE;IGNORE;IGNORE; #point_hataf_patah + IGNORE;IGNORE;IGNORE; #point_hataf_qamats + IGNORE;IGNORE;IGNORE; #point_hiriq + IGNORE;IGNORE;IGNORE; #point_tsere + IGNORE;IGNORE;IGNORE; #point_segol + IGNORE;IGNORE;IGNORE; #point_patah + IGNORE;IGNORE;IGNORE; #point_qamats + IGNORE;IGNORE;IGNORE; #point_holam + IGNORE;IGNORE;IGNORE; #point_qubuts + IGNORE;IGNORE;IGNORE; #point_dagesh + IGNORE;IGNORE;IGNORE; #point_meteg + IGNORE;IGNORE;IGNORE; #maqaf + IGNORE;IGNORE;IGNORE; #point_rafe + IGNORE;IGNORE;IGNORE; #paseq + IGNORE;IGNORE;IGNORE; #point_shin_dot + IGNORE;IGNORE;IGNORE; #point_sin_dot + IGNORE;IGNORE;IGNORE; #sof pasuq + +# The comment at the beginning of this section mentions characters which +# are not otherwise covered. But this description cannot express this. +# Therefore we add here a few entries which are used in older implementations +# to be compatible. --drepper + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + +order_start ;forward;backward;forward;forward,position +# + ;;;IGNORE # 170 +# + <0>;;;IGNORE # 171 0 + <1>;;;IGNORE # 172 1 + <2>;;;IGNORE # 173 2 + <3>;;;IGNORE # 174 3 + <4>;;;IGNORE # 175 4 + <5>;;;IGNORE # 176 5 + <6>;;;IGNORE # 177 6 + <7>;;;IGNORE # 178 7 + <8>;;;IGNORE # 179 8 + <9>;;;IGNORE # 180 9 +# + <0>;;;IGNORE # 181 <18> + <0>;;;IGNORE # 182 ¼ + <0>;;;IGNORE # 183 <38> + <0>;;;IGNORE # 184 <58> + <0>;;;IGNORE # 185 <78> + <0>;;;IGNORE # 186 ½ + <0>;;;IGNORE # 187 ¾ + <0>;;;IGNORE # 188 <0S> + <1>;;;IGNORE # 189 ¹ + <2>;;;IGNORE # 190 ² + <3>;;;IGNORE # 191 ³ + <4>;;;IGNORE # 192 <4S> + <5>;;;IGNORE # 193 <5S> + <6>;;;IGNORE # 194 <6S> + <7>;;;IGNORE # 195 <7S> + <8>;;;IGNORE # 196 <8S> + <9>;;;IGNORE # 197 <9S> +# + ;;;IGNORE # 198 a + ;;;IGNORE # 199 ª + ;;;IGNORE # 200 á + ;;;IGNORE # 201 à + ;;;IGNORE # 202 â + ;;;IGNORE # 203 ã + ;;;IGNORE # 204 ä + ;;;IGNORE # 205 å + ;;;IGNORE # 206 + ;;;IGNORE # 207 + ;;;IGNORE # 208 + "";"";"";IGNORE # 209 æ + ;;;IGNORE # 210 b + ;;;IGNORE # 211 c + ;;;IGNORE # 212 ç + ;;;IGNORE # 213 + ;;;IGNORE # 214 > + ;;;IGNORE # 215 + ;;;IGNORE # 216 + ;;;IGNORE # 217 d + ;;;IGNORE # 218 ð + ;;;IGNORE # 219 + ;;;IGNORE # 220 + ;;;IGNORE # 221 e + ;;;IGNORE # 222 é + ;;;IGNORE # 223 è + ;;;IGNORE # 224 ê + ;;;IGNORE # 225 ë + ;;;IGNORE # 226 + ;;;IGNORE # 227 + ;;;IGNORE # 228 + ;;;IGNORE # 229 + ;;;IGNORE # 230 f + ;;;IGNORE # 231 g + ;;;IGNORE # 232 + ;;;IGNORE # 233 > + ;;;IGNORE # 234 + ;;;IGNORE # 235 + ;;;IGNORE # 236 h + ;;;IGNORE # 237 > + ;;;IGNORE # 238 + ;;;IGNORE # 239 i + ;;;IGNORE # 240 í + ;;;IGNORE # 241 ì + ;;;IGNORE # 242 î + ;;;IGNORE # 243 ï + ;;;IGNORE # 244 + ;;;IGNORE # 245 + ;;;IGNORE # 246 + ;;;IGNORE # 247 + "";"";"";IGNORE # 248 + ;;;IGNORE # 249 j + ;;;IGNORE # 250 > + ;;;IGNORE # 251 k + ;;;IGNORE # 252 + ;;;IGNORE # 253 + ;;;IGNORE # 254 l + ;;;IGNORE # 255 + ;;;IGNORE # 256 + ;;;IGNORE # 257 + ;;;IGNORE # 258 + ;;;IGNORE # 259 + ;;;IGNORE # 260 m + ;;;IGNORE # 261 n + ;;;IGNORE # 262 ñ + ;;;IGNORE # 263 <'n> + ;;;IGNORE # 264 + ;;;IGNORE # 265 + ;;;IGNORE # 266 + "";"";"";IGNORE # 267 + ;;;IGNORE # 268 o + ;;;IGNORE # 269 º + ;;;IGNORE # 270 ó + ;;;IGNORE # 271 ò + ;;;IGNORE # 272 ô + ;;;IGNORE # 273 õ + ;;;IGNORE # 274 ö + ;;;IGNORE # 275 ø + ;;;IGNORE # 276 + ;;;IGNORE # 277 + "";"";"";IGNORE # 278 +

;;;IGNORE # 279 p + ;;;IGNORE # 280 q + ;;;IGNORE # 281 r + ;;;IGNORE # 282 + ;;;IGNORE # 283 + ;;;IGNORE # 284 + ;;;IGNORE # 285 s + ;;;IGNORE # 286 + ;;;IGNORE # 287 > + ;;;IGNORE # 288 + ;;;IGNORE # 289 + "";"";"";IGNORE # 290 ß + ;;;IGNORE # 291 t + ;;;IGNORE # 292 + ;;;IGNORE # 293 + ;;;IGNORE # 294 + ;;;IGNORE # 296 u + ;;;IGNORE # 297 ú + ;;;IGNORE # 298 ù + ;;;IGNORE # 299 û + ;;;IGNORE # 300 ü + ;;;IGNORE # 301 + ;;;IGNORE # 302 + ;;;IGNORE # 303 + ;;;IGNORE # 304 + ;;;IGNORE # 305 + ;;;IGNORE # 306 + ;;;IGNORE # 307 v + ;;;IGNORE # 308 w + ;;;IGNORE # 309 > + ;;;IGNORE # 310 x + ;;;IGNORE # 311 y + ;;;IGNORE # 312 ý + ;;;IGNORE # 313 _ + ;;;IGNORE # 314 > + ;;;IGNORE # 315 z + ;;;IGNORE # 316 + ;;;IGNORE # 317 + ;;;IGNORE # 318 + ;;;IGNORE # 318b Þ # + ;;;IGNORE # 319 A + ;;;IGNORE # 320 Á + ;;;IGNORE # 321 À + ;;;IGNORE # 322 Â + ;;;IGNORE # 323 Ã + ;;;IGNORE # 324 Ä + ;;;IGNORE # 325 Å + ;;;IGNORE # 326 + ;;;IGNORE # 327 + ;;;IGNORE # 328 + "";"";"";IGNORE # 329 Æ + ;;;IGNORE # 330 B + ;;;IGNORE # 331 C + ;;;IGNORE # 332 Ç + ;;;IGNORE # 333 + ;;;IGNORE # 334 > + ;;;IGNORE # 335 > + ;;;IGNORE # 336 + ;;;IGNORE # 337 D + ;;;IGNORE # 338 Ð + ;;;IGNORE # 339 + ;;;IGNORE # 340 + ;;;IGNORE # 341 E + ;;;IGNORE # 342 É + ;;;IGNORE # 343 È + ;;;IGNORE # 344 Ê + ;;;IGNORE # 345 Ë + ;;;IGNORE # 346 + ;;;IGNORE # 347 + ;;;IGNORE # 348 + ;;;IGNORE # 349 + ;;;IGNORE # 350 F + ;;;IGNORE # 351 G + ;;;IGNORE # 352 + ;;;IGNORE # 353 > + ;;;IGNORE # 354 + ;;;IGNORE # 355 + ;;;IGNORE # 356 H + ;;;IGNORE # 357 > + ;;;IGNORE # 358 + ;;;IGNORE # 359 I + ;;;IGNORE # 360 Í + ;;;IGNORE # 361 Ì + ;;;IGNORE # 362 Î + ;;;IGNORE # 363 Ï + ;;;IGNORE # 364 + ;;;IGNORE # 365 + ;;;IGNORE # 366 + ;;;IGNORE # 367 + "";"";"";IGNORE # 368 + ;;;IGNORE # 369 J + ;;;IGNORE # 370 > + ;;;IGNORE # 371 K + ;;;IGNORE # 372 + ;;;IGNORE # 373 L + ;;;IGNORE # 374 + ;;;IGNORE # 375 + ;;;IGNORE # 376 + ;;;IGNORE # 377 + ;;;IGNORE # 378 + ;;;IGNORE # 379 M + ;;;IGNORE # 380 N + ;;;IGNORE # 381 Ñ + ;;;IGNORE # 382 + ;;;IGNORE # 383 + ;;;IGNORE # 384 + "";"";"";IGNORE # 385 + ;;;IGNORE # 386 O + ;;;IGNORE # 387 Ó + ;;;IGNORE # 388 Ò + ;;;IGNORE # 389 Ô + ;;;IGNORE # 390 Õ + ;;;IGNORE # 391 Ö + ;;;IGNORE # 392 Ø + ;;;IGNORE # 393 + ;;;IGNORE # 394 + "";"";"";IGNORE # 395 +

;;;IGNORE # 396 P + ;;;IGNORE # 397 Q + ;;;IGNORE # 398 R + ;;;IGNORE # 399 + ;;;IGNORE # 400 + ;;;IGNORE # 401 + ;;;IGNORE # 402 S + ;;;IGNORE # 403 + ;;;IGNORE # 404 > + ;;;IGNORE # 405 + ;;;IGNORE # 406 + ;;;IGNORE # 407 T + ;;;IGNORE # 408 + ;;;IGNORE # 409 + ;;;IGNORE # 410 + ;;;IGNORE # 412 U + ;;;IGNORE # 413 Ú + ;;;IGNORE # 414 Ù + ;;;IGNORE # 415 Û + ;;;IGNORE # 416 Ü + ;;;IGNORE # 417 + ;;;IGNORE # 418 + ;;;IGNORE # 419 + ;;;IGNORE # 420 + ;;;IGNORE # 421 + ;;;IGNORE # 422 + ;;;IGNORE # 423 V + ;;;IGNORE # 424 W + ;;;IGNORE # 425 > + ;;;IGNORE # 426 X + ;;;IGNORE # 427 Y + ;;;IGNORE # 428 Ý + ;;;IGNORE # 429 > + ;;;IGNORE # 430 + ;;;IGNORE # 431 Z + ;;;IGNORE # 432 + ;;;IGNORE # 433 + ;;;IGNORE # 434 + ;;;IGNORE # 411 þ + +order_start ;forward;forward;forward;forward,position + <0>;;;IGNORE + <0>;;;IGNORE + <1>;;;IGNORE + <1>;;;IGNORE + <2>;;;IGNORE + <2>;;;IGNORE + <3>;;;IGNORE + <3>;;;IGNORE + <4>;;;IGNORE + <4>;;;IGNORE + <5>;;;IGNORE + <5>;;;IGNORE + <6>;;;IGNORE + <6>;;;IGNORE + <7>;;;IGNORE + <7>;;;IGNORE + <8>;;;IGNORE + <8>;;;IGNORE + <9>;;;IGNORE + <9>;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + +order_start ;backward;backward;backward;forward,position + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + +order_start ;forward;forward;forward;forward,position + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + +order_start ;forward;backward;forward;forward,position + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE # digamma copte + ;;;IGNORE + ;;;IGNORE # GANGIA COPTE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE # HORI COPTE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE # koppa copte + ;;;IGNORE # KHEI COPTE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE # STIGMA ARCH. + ;;;IGNORE # SHIMA COPTE + ;;;IGNORE + ;;;IGNORE # DEI COPTE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE # FEI COPTE + ;;;IGNORE + ;;;IGNORE # sampi copte + ;;;IGNORE + ;;;IGNORE # SHEI COPTE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE # gangia copte + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE # hori copte + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE # yot + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE # khei copte + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE # shima copte + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE # dei copte + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE # fei copte + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE # shei copte + ;;;IGNORE + ;;;IGNORE + +order_start ;forward;forward;forward;forward,position + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + +order_start ;forward;forward;forward;forward,position +UCLIBC_RANGE ..;IGNORE;IGNORE;IGNORE +# ;IGNORE;IGNORE;IGNORE +#.. ..;IGNORE;IGNORE;IGNORE +# ;IGNORE;IGNORE;IGNORE +# +order_end +# diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/it_CH b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/it_CH new file mode 100644 index 00000000..3738ee3c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/it_CH @@ -0,0 +1 @@ +copy "iso14651_t1" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/it_IT b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/it_IT new file mode 100644 index 00000000..3738ee3c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/it_IT @@ -0,0 +1 @@ +copy "iso14651_t1" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/iw_IL b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/iw_IL new file mode 100644 index 00000000..3738ee3c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/iw_IL @@ -0,0 +1 @@ +copy "iso14651_t1" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ja_JP b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ja_JP new file mode 100644 index 00000000..fa26bac9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ja_JP @@ -0,0 +1,13188 @@ +order_start forward +% +% C0 +% + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +% +% ISO 646 IRV +% + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +% +% C1 +% + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +% +% JIS X 0201 KATAKANA +% + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +% +% JIS X 0208 +% + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +% +% JIS X 0212 +% + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +UNDEFINED +order_end diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ka_GE b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ka_GE new file mode 100644 index 00000000..3738ee3c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ka_GE @@ -0,0 +1 @@ +copy "iso14651_t1" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/kl_GL b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/kl_GL new file mode 100644 index 00000000..b7628e76 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/kl_GL @@ -0,0 +1 @@ +copy "da_DK" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ko_KR b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ko_KR new file mode 100644 index 00000000..d9898f1e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ko_KR @@ -0,0 +1,6010 @@ +order_start forward + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +%%% +% HANGUL SYLLABLES +UCLIBC_RANGE +# +#.. +# +%%% +% HANJA. For the moment, Hanjas defined in KS X 1001 +% are enumerated in the order they're listed in KS X 1001. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +UNDEFINED +order_end diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/kw_GB b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/kw_GB new file mode 100644 index 00000000..3738ee3c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/kw_GB @@ -0,0 +1 @@ +copy "iso14651_t1" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/lt_LT b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/lt_LT new file mode 100644 index 00000000..707d08ea --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/lt_LT @@ -0,0 +1,2061 @@ + +% Base collation scheme: 1994-03-22 + +% Ordering algorithm: +% 1. Spaces and hyphen (but not soft +% hyphen) before punctuation +% characters, punctuation characters +% before numbers, +% numbers before letters. +% 2. Letters with diacritical marks are +% members of equivalence classes +% 3. A distinction is made with regards +% to case as noted below. +% 4. Special characters are ignored +% when comparing letters, but then +% they are considered +% 5. The alphabets are sorted in order +% of first appearance in ISO 10646: +% Latin, Greek, Cyrillic, etc. +% +% According to Greek specifications, +% the steps 2. and 3. above are reversed +% for the Greek script + +% collating symbols + +% The collating symbol naming is +% mostly taken from ISO 10646-1, +% for example the case and accent +% names are from this standard. + +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +% and +% are for cases like Danish +% and Spanish being treated +% as one letter. + +% The ...... collating +% symbols have defined weights as +% the last character in a group of +% Latin letters. They are used +% to specify deltas by locales using +% a locale as the default ordering +% and by "replace-after" statements +% specifying the changed placement +% in an ordering of a character. + +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +% letter;accent;case;specials + +order_start forward;backward;forward;position + +% or letters first: + + + + + + +% Accents: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ;;;IGNORE + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; +<"=> IGNORE;IGNORE;IGNORE;<"=> + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; +UNDEFINED IGNORE;IGNORE;IGNORE + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + +% Arabic collating + + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + +% katakana/hiragana sorting +% base is katakana, as this is present in most charsets +% normal before voiced before semi-voiced +% small vocals before normal vocals +% katakana before hiragana + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + +order_end + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/lv_LV b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/lv_LV new file mode 100644 index 00000000..84927311 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/lv_LV @@ -0,0 +1,2061 @@ + +% Base collation scheme: 1994-03-22 + +% Ordering algorithm: +% 1. Spaces and hyphen (but not soft +% hyphen) before punctuation +% characters, punctuation characters +% before numbers, +% numbers before letters. +% 2. Letters with diacritical marks are +% members of equivalence classes +% 3. A distinction is made with regards +% to case as noted below. +% 4. Special characters are ignored +% when comparing letters, but then +% they are considered +% 5. The alphabets are sorted in order +% of first appearance in ISO 10646: +% Latin, Greek, Cyrillic, etc. +% +% According to Greek specifications, +% the steps 2. and 3. above are reversed +% for the Greek script + +% collating symbols + +% The collating symbol naming is +% mostly taken from ISO 10646-1, +% for example the case and accent +% names are from this standard. + +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +% and +% are for cases like Danish +% and Spanish being treated +% as one letter. + +% The ...... collating +% symbols have defined weights as +% the last character in a group of +% Latin letters. They are used +% to specify deltas by locales using +% a locale as the default ordering +% and by "replace-after" statements +% specifying the changed placement +% in an ordering of a character. + +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +% letter;accent;case;specials + +order_start forward;backward;forward;position + +% or letters first: + + + + + + +% Accents: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ;;;IGNORE + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; +<"=> IGNORE;IGNORE;IGNORE;<"=> + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; +UNDEFINED IGNORE;IGNORE;IGNORE + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + +% Arabic collating + + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + +% katakana/hiragana sorting +% base is katakana, as this is present in most charsets +% normal before voiced before semi-voiced +% small vocals before normal vocals +% katakana before hiragana + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + +order_end + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/mi_NZ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/mi_NZ new file mode 100644 index 00000000..c36305d4 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/mi_NZ @@ -0,0 +1,44 @@ +copy "iso14651_t1" + +%% a b c d e f g h i j k l m n ng o p q r s t u v w wh x y z + +collating-symbol +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-symbol +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-symbol +collating-symbol + +reorder-after + +reorder-after + + +reorder-after + +reorder-after + + +reorder-after + ;;;IGNORE + ;;;IGNORE +reorder-after + ;;;IGNORE + ;;;IGNORE + +reorder-after + ;;;IGNORE + ;;;IGNORE +reorder-after + ;;;IGNORE + ;;;IGNORE + +reorder-end + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/mk_MK b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/mk_MK new file mode 100644 index 00000000..3738ee3c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/mk_MK @@ -0,0 +1 @@ +copy "iso14651_t1" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/mr_IN b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/mr_IN new file mode 100644 index 00000000..35ae3c60 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/mr_IN @@ -0,0 +1,4 @@ + +% Copy the template from ISO/IEC 14651 +copy "iso14651_t1" + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ms_MY b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ms_MY new file mode 100644 index 00000000..35ae3c60 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ms_MY @@ -0,0 +1,4 @@ + +% Copy the template from ISO/IEC 14651 +copy "iso14651_t1" + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/mt_MT b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/mt_MT new file mode 100644 index 00000000..bd028dab --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/mt_MT @@ -0,0 +1,80 @@ + +% a b c c. d e f g. g gh/ h h/ i ie j k l m n o p q r s t u v w x y z. z + +% Copy the template from ISO/IEC 14651 +copy "iso14651_t1" + +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +collating-symbol +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-symbol +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-symbol +collating-symbol + +reorder-after + +reorder-after + + +reorder-after + +reorder-after + +reorder-after + +reorder-after + +reorder-after + +reorder-after + + +reorder-after + ;;;IGNORE +reorder-after + ;;;IGNORE + +reorder-after + ;;;IGNORE +reorder-after + ;;;IGNORE + +reorder-after + ;;;IGNORE + ;;;IGNORE +reorder-after + ;;;IGNORE + ;;;IGNORE + +reorder-after + ;;;IGNORE +reorder-after + ;;;IGNORE + +reorder-after + ;;;IGNORE + ;;;IGNORE +reorder-after + ;;;IGNORE + ;;;IGNORE + +reorder-after + ;;;IGNORE +reorder-after + ;;;IGNORE + +reorder-end + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/nl_BE b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/nl_BE new file mode 100644 index 00000000..3738ee3c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/nl_BE @@ -0,0 +1 @@ +copy "iso14651_t1" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/nl_NL b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/nl_NL new file mode 100644 index 00000000..3738ee3c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/nl_NL @@ -0,0 +1 @@ +copy "iso14651_t1" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/nn_NO b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/nn_NO new file mode 100644 index 00000000..35ae3c60 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/nn_NO @@ -0,0 +1,4 @@ + +% Copy the template from ISO/IEC 14651 +copy "iso14651_t1" + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/no_NO b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/no_NO new file mode 100644 index 00000000..f32dc18c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/no_NO @@ -0,0 +1,2070 @@ +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +% Base collation scheme: 1994-03-22 + +% Ordering algorithm: +% 1. Spaces and hyphen (but not soft +% hyphen) before punctuation +% characters, punctuation characters +% before numbers, +% numbers before letters. +% 2. Letters with diacritical marks are +% members of equivalence classes +% 3. A distinction is made with regards +% to case as noted below. +% 4. Special characters are ignored +% when comparing letters, but then +% they are considered +% 5. The alphabets are sorted in order +% of first appearance in ISO 10646: +% Latin, Greek, Cyrillic, etc. +% +% According to Greek specifications, +% the steps 2. and 3. above are reversed +% for the Greek script + +% collating symbols + +% The collating symbol naming is +% mostly taken from ISO 10646-1, +% for example the case and accent +% names are from this standard. + +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +% and +% are for cases like Danish +% and Spanish being treated +% as one letter. + +% The ...... collating +% symbols have defined weights as +% the last character in a group of +% Latin letters. They are used +% to specify deltas by locales using +% a locale as the default ordering +% and by "replace-after" statements +% specifying the changed placement +% in an ordering of a character. + +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +% letter;accent;case;specials + +order_start forward;backward;forward;position + +% or letters first: + +% before letters + + + + + +% Accents: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ;;;IGNORE + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; +<"=> IGNORE;IGNORE;IGNORE;<"=> + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; +UNDEFINED IGNORE;IGNORE;IGNORE + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + +% Arabic collating + + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + +% katakana/hiragana sorting +% base is katakana, as this is present in most charsets +% normal before voiced before semi-voiced +% small vocals before normal vocals +% katakana before hiragana + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + +order_end + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/oc_FR b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/oc_FR new file mode 100644 index 00000000..d66184ec --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/oc_FR @@ -0,0 +1 @@ +copy "en_DK" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/pl_PL b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/pl_PL new file mode 100644 index 00000000..b4c9a3bc --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/pl_PL @@ -0,0 +1,2061 @@ + +% Base collation scheme: 1994-03-22 + +% Ordering algorithm: +% 1. Spaces and hyphen (but not soft +% hyphen) before punctuation +% characters, punctuation characters +% before numbers, +% numbers before letters. +% 2. Letters with diacritical marks are +% members of equivalence classes +% 3. A distinction is made with regards +% to case as noted below. +% 4. Special characters are ignored +% when comparing letters, but then +% they are considered +% 5. The alphabets are sorted in order +% of first appearance in ISO 10646: +% Latin, Greek, Cyrillic, etc. +% +% According to Greek specifications, +% the steps 2. and 3. above are reversed +% for the Greek script + +% collating symbols + +% The collating symbol naming is +% mostly taken from ISO 10646-1, +% for example the case and accent +% names are from this standard. + +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +% and +% are for cases like Danish +% and Spanish being treated +% as one letter. + +% The ...... collating +% symbols have defined weights as +% the last character in a group of +% Latin letters. They are used +% to specify deltas by locales using +% a locale as the default ordering +% and by "replace-after" statements +% specifying the changed placement +% in an ordering of a character. + +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +% letter;accent;case;specials + +order_start forward;backward;forward;position + +% or letters first: + + + + + + +% Accents: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ;;;IGNORE + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; +<"=> IGNORE;IGNORE;IGNORE;<"=> + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; +UNDEFINED IGNORE;IGNORE;IGNORE + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + +% Arabic collating + + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + +% katakana/hiragana sorting +% base is katakana, as this is present in most charsets +% normal before voiced before semi-voiced +% small vocals before normal vocals +% katakana before hiragana + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + +order_end + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/pt_BR b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/pt_BR new file mode 100644 index 00000000..3738ee3c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/pt_BR @@ -0,0 +1 @@ +copy "iso14651_t1" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/pt_PT b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/pt_PT new file mode 100644 index 00000000..3738ee3c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/pt_PT @@ -0,0 +1 @@ +copy "iso14651_t1" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ro_RO b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ro_RO new file mode 100644 index 00000000..862db75d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ro_RO @@ -0,0 +1,54 @@ + +% Copy the template from ISO/IEC 14651 +copy "iso14651_t1" + +% a a> a( b c d e f g h i i> j k l m n o p q r s s, t t, u v w x y z + +collating-symbol > +collating-symbol +collating-symbol > +collating-symbol +collating-symbol + +reorder-after + + + +reorder-after +> + +reorder-after +> +reorder-after + +reorder-after + + +reorder-after + >;;;IGNORE + ;;;IGNORE +reorder-after + >;;;IGNORE + ;;;IGNORE + +reorder-after + >;;;IGNORE +reorder-after + >;;;IGNORE + +reorder-after + ;;;IGNORE + ;;;IGNORE +reorder-after + ;;;IGNORE + ;;;IGNORE + +reorder-after + ;;;IGNORE + ;;;IGNORE +reorder-after + ;;;IGNORE + ;;;IGNORE + +reorder-end + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ru_RU b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ru_RU new file mode 100644 index 00000000..342a761d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ru_RU @@ -0,0 +1,15 @@ +copy "iso14651_t1" + +% iso14651_t1 is missing Ukrainian ghe +collating-symbol + +reorder-after + + +reorder-after + ;;;IGNORE + +reorder-after + ;;;IGNORE + +reorder-end diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ru_UA b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ru_UA new file mode 100644 index 00000000..342a761d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ru_UA @@ -0,0 +1,15 @@ +copy "iso14651_t1" + +% iso14651_t1 is missing Ukrainian ghe +collating-symbol + +reorder-after + + +reorder-after + ;;;IGNORE + +reorder-after + ;;;IGNORE + +reorder-end diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/se_NO b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/se_NO new file mode 100644 index 00000000..9718edc1 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/se_NO @@ -0,0 +1,149 @@ +copy "iso14651_t1" + +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +% +reorder-after + + +reorder-after + + + + + + +reorder-after + + + + + +reorder-after + + + +reorder-after + + +reorder-after + + + +reorder-after + + +reorder-after + + + +reorder-after + + + + + + +reorder-after + ;;;IGNORE % 201 à + ;;;IGNORE % 200 á + ;;;IGNORE % 202 â + ;;;IGNORE % 203 ã + +reorder-after + ;;;IGNORE % 321 À + ;;;IGNORE % 320 Á + ;;;IGNORE % 322 Â + ;;;IGNORE % 323 Ã + +reorder-after + ;;;IGNORE % 212 ç + ;;;IGNORE % 215 + +reorder-after + ;;;IGNORE % 332 Ç + ;;;IGNORE % 335 + +reorder-after + ;;;IGNORE % ezh + ;;;IGNORE % ezh caron + +reorder-after + ;;;IGNORE % EZH + ;;;IGNORE % EZH caron + +reorder-after + ;;;IGNORE % 218 ð + ;;;IGNORE % 220 + +reorder-after + ;;;IGNORE % 338 Ð + ;;;IGNORE % 340 + +reorder-after + ;;;IGNORE % f WITH HOOK + +reorder-after + ;;;IGNORE % gcaron + ;;;IGNORE % gstroke + +reorder-after + ;;;IGNORE % Gcaron + ;;;IGNORE % Gstroke + +reorder-after + ;;;IGNORE % kcaron +reorder-after + ;;;IGNORE % Kcaron + +reorder-after + ;"";"";IGNORE % ß + ;;;IGNORE % 288 + ;;;IGNORE % 405 + + +reorder-after + ;;;IGNORE % ä + ;;;IGNORE % å + ;;;IGNORE % æ +reorder-after + ;;;IGNORE % ö + ;;;IGNORE % ø + +reorder-after + ;;;IGNORE % Ä + ;;;IGNORE % Å + ;;;IGNORE % Æ +reorder-after + ;;;IGNORE % Ö + ;;;IGNORE % Ø + +% ü/Ü is treated like y/Y but is sorted after the latter +reorder-after + ;;;IGNORE % ü +reorder-after + ;;;IGNORE % Ü +reorder-end + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/sk_SK b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/sk_SK new file mode 100644 index 00000000..245653ce --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/sk_SK @@ -0,0 +1 @@ +copy "cs_CZ" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/sl_SI b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/sl_SI new file mode 100644 index 00000000..7f7ad23e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/sl_SI @@ -0,0 +1,2061 @@ + +% Base collation scheme: 1994-03-22 + +% Ordering algorithm: +% 1. Spaces and hyphen (but not soft +% hyphen) before punctuation +% characters, punctuation characters +% before numbers, +% numbers before letters. +% 2. Letters with diacritical marks are +% members of equivalence classes +% 3. A distinction is made with regards +% to case as noted below. +% 4. Special characters are ignored +% when comparing letters, but then +% they are considered +% 5. The alphabets are sorted in order +% of first appearance in ISO 10646: +% Latin, Greek, Cyrillic, etc. +% +% According to Greek specifications, +% the steps 2. and 3. above are reversed +% for the Greek script + +% collating symbols + +% The collating symbol naming is +% mostly taken from ISO 10646-1, +% for example the case and accent +% names are from this standard. + +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +% and +% are for cases like Danish +% and Spanish being treated +% as one letter. + +% The ...... collating +% symbols have defined weights as +% the last character in a group of +% Latin letters. They are used +% to specify deltas by locales using +% a locale as the default ordering +% and by "replace-after" statements +% specifying the changed placement +% in an ordering of a character. + +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +% letter;accent;case;specials + +order_start forward;backward;forward;position + +% or letters first: + + + + + + +% Accents: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ;;;IGNORE + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; +<"=> IGNORE;IGNORE;IGNORE;<"=> + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; +UNDEFINED IGNORE;IGNORE;IGNORE + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + +% Arabic collating + + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + +% katakana/hiragana sorting +% base is katakana, as this is present in most charsets +% normal before voiced before semi-voiced +% small vocals before normal vocals +% katakana before hiragana + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + +order_end + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/sq_AL b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/sq_AL new file mode 100644 index 00000000..35ae3c60 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/sq_AL @@ -0,0 +1,4 @@ + +% Copy the template from ISO/IEC 14651 +copy "iso14651_t1" + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/sr_YU b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/sr_YU new file mode 100644 index 00000000..1dcd15c4 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/sr_YU @@ -0,0 +1,90 @@ +copy "iso14651_t1" + +% a b c c' c< d dz< d// e f g h i j k l lj m n nj o p +% q r s s< t u v w x y z z< + +collating-symbol +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-symbol +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-symbol +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +collating-symbol +collating-symbol + +reorder-after + +reorder-after + + +reorder-after + + + + + +reorder-after + +reorder-after + +reorder-after + +reorder-after + + +reorder-after + ;;;IGNORE + ;;;IGNORE +reorder-after + ;;;IGNORE + ;;;IGNORE + +reorder-after + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE +reorder-after + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + +reorder-after + ;;;IGNORE + ;;;IGNORE +reorder-after + ;;;IGNORE + ;;;IGNORE + +reorder-after + ;;;IGNORE + ;;;IGNORE +reorder-after + ;;;IGNORE + ;;;IGNORE + +reorder-after + ;;;IGNORE +reorder-after + ;;;IGNORE + +reorder-after + ;;;IGNORE +reorder-after + ;;;IGNORE + +reorder-end diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/sv_FI b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/sv_FI new file mode 100644 index 00000000..ab503862 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/sv_FI @@ -0,0 +1 @@ +copy "fi_FI" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/sv_SE b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/sv_SE new file mode 100644 index 00000000..2d299a47 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/sv_SE @@ -0,0 +1,51 @@ +copy "iso14651_t1" + +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +% æ is sorted after ä and å etc. +reorder-after + + +reorder-after + + + + + +% The letter w is normally not present in the Swedish alphabet. It +% exists in some names in Swedish and foreign words, but is accounted +% for as a variant of 'v'. Words and names with 'w' are in Swedish +% ordered alphabetically among the words and names with 'v'. If two +% words or names are only to be distinguished by 'v' or % 'w', 'v' is +% placed before 'w'. +reorder-after + ;;; % W +reorder-after + ;;; % w + +reorder-after + ;;;IGNORE % ä + ;;;IGNORE % å + ;;;IGNORE % æ +reorder-after + ;;;IGNORE % ö + ;;;IGNORE % ø + +reorder-after + ;;;IGNORE % Ä + ;;;IGNORE % Å + ;;;IGNORE % Æ +reorder-after + ;;;IGNORE % Ö + ;;;IGNORE % Ø + +% ü/Ü is treated like y/Y but is sorted after the latter +reorder-after + ;;;IGNORE % ü +reorder-after + ;;;IGNORE % Ü +reorder-end + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ta_IN b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ta_IN new file mode 100644 index 00000000..35ae3c60 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ta_IN @@ -0,0 +1,4 @@ + +% Copy the template from ISO/IEC 14651 +copy "iso14651_t1" + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/te_IN b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/te_IN new file mode 100644 index 00000000..35ae3c60 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/te_IN @@ -0,0 +1,4 @@ + +% Copy the template from ISO/IEC 14651 +copy "iso14651_t1" + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/tg_TJ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/tg_TJ new file mode 100644 index 00000000..e2f01ae9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/tg_TJ @@ -0,0 +1,63 @@ + +% Tadjik cyrillic alphabet is: +% , , , , (cyr ghe with stroke), , , +% , , , , (cyr i with macron), , , +% (cyr k with descender), , , , , , , +% , , , (cyr u with macron), , , +% (cyr ha with descender), , (cyr che with descender), +% , (cyr hard sign), , , + +copy "iso14651_t1" + +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +reorder-after + +reorder-after + +reorder-after + +reorder-after + +reorder-after + +reorder-after + + +reorder-after + ;;;IGNORE +reorder-after + ;;;IGNORE + +reorder-after + ;;;IGNORE +reorder-after + ;;;IGNORE + +reorder-after + ;;;IGNORE +reorder-after + ;;;IGNORE + +reorder-after + ;;;IGNORE +reorder-after + ;;;IGNORE + +reorder-after + ;;;IGNORE +reorder-after + ;;;IGNORE + +reorder-after + ;;;IGNORE +reorder-after + ;;;IGNORE + +reorder-end + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/th_TH b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/th_TH new file mode 100644 index 00000000..6e3230f8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/th_TH @@ -0,0 +1,746 @@ + +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +order_start forward;forward;forward;forward + +% definitions of extra collating symbols + + + + + + +UNDEFINED IGNORE;IGNORE;IGNORE;IGNORE + +% punctuation marks, ordered after ISO/IEC 14651 + IGNORE;IGNORE;;IGNORE % SPACE + IGNORE;IGNORE;;IGNORE % LOW LINE + IGNORE;IGNORE;;IGNORE % HYPHEN-MINUS + IGNORE;IGNORE;;IGNORE % COMMA + IGNORE;IGNORE;;IGNORE % SEMICOLON + IGNORE;IGNORE;;IGNORE % COLON + IGNORE;IGNORE;;IGNORE % EXCLAMATION MARK + IGNORE;IGNORE;;IGNORE % QUESTION MARK + IGNORE;IGNORE;;IGNORE % SOLIDUS + IGNORE;IGNORE;;IGNORE % FULL STOP + IGNORE;IGNORE;;IGNORE % THAI CHARACTER PAIYANNOI + IGNORE;IGNORE;;IGNORE % THAI CHARACTER MAIYAMOK + IGNORE;IGNORE;;IGNORE % GRAVE ACCENT + IGNORE;IGNORE;;IGNORE % CIRCUMFLEX + IGNORE;IGNORE;;IGNORE % TILDE + IGNORE;IGNORE;;IGNORE % APOSTROPHE + IGNORE;IGNORE;;IGNORE % QUOTATION MARK + IGNORE;IGNORE;;IGNORE % LEFT PAREN. + IGNORE;IGNORE;;IGNORE % LT BRACKET + IGNORE;IGNORE;;IGNORE % LEFT CURLY BRACKET + IGNORE;IGNORE;;IGNORE % RIGHT CURLY BRACKET + IGNORE;IGNORE;;IGNORE % RT BRACKET + IGNORE;IGNORE;;IGNORE % RIGHT PAREN. + IGNORE;IGNORE;;IGNORE % COMMERCIAL AT + IGNORE;IGNORE;;IGNORE % THAI CHARACTER SYMBOL BAHT + IGNORE;IGNORE;;IGNORE % DOLLAR SIGN + IGNORE;IGNORE;;IGNORE % THAI CHARACTER FONGMAN + IGNORE;IGNORE;;IGNORE % THAI CHARACTER ANGKHANKHU + IGNORE;IGNORE;;IGNORE % THAI CHARACTER KHOMUT + IGNORE;IGNORE;;IGNORE % ASTERISK + IGNORE;IGNORE;;IGNORE % BACK SOLIDUS + IGNORE;IGNORE;;IGNORE % AMPERSAND + IGNORE;IGNORE;;IGNORE % NUMBER SIGN + IGNORE;IGNORE;;IGNORE % PERCENT + IGNORE;IGNORE;;IGNORE % PLUS + IGNORE;IGNORE;;IGNORE % LESS THAN + IGNORE;IGNORE;;IGNORE % EQUAL + IGNORE;IGNORE;;IGNORE % GREATER THAN + IGNORE;IGNORE;;IGNORE % VERTICAL LINE + +% Thai tone marks and diacritics + IGNORE;;; % THAI CHARACTER YAMAKKAN + IGNORE;;; % THAI CHARACTER PINTHU + IGNORE;;; % THAI CHARACTER THANTHAKHAT + IGNORE;;; % THAI CHARACTER MAITAIKHU + IGNORE;;; % THAI CHARACTER MAI EK + IGNORE;;; % THAI CHARACTER MAI THO + IGNORE;;; % THAI CHARACTER MAI TRI + IGNORE;;; % THAI CHARACTER MAI CHATTAWA + +% Arabic and Thai decimal digits + ;;; % DIGIT ZERO + ;;; % THAI DIGIT ZERO + ;;; % DIGIT ONE + ;;; % THAI DIGIT ONE + ;;; % DIGIT TWO + ;;; % THAI DIGIT TWO + ;;; % DIGIT THREE + ;;; % THAI DIGIT THREE + ;;; % DIGIT FOUR + ;;; % THAI DIGIT FOUR + ;;; % DIGIT FIVE + ;;; % THAI DIGIT FIVE + ;;; % DIGIT SIX + ;;; % THAI DIGIT SIX + ;;; % DIGIT SEVEN + ;;; % THAI DIGIT SEVEN + ;;; % DIGIT EIGHT + ;;; % THAI DIGIT EIGHT + ;;; % DIGIT NINE + ;;; % THAI DIGIT NINE + +% Latin alphabet + ;;; % A + ;;; % a + ;;; % B + ;;; % b + ;;; % C + ;;; % c + ;;; % D + ;;; % d + ;;; % E + ;;; % e + ;;; % F + ;;; % f + ;;; % G + ;;; % g + ;;; % H + ;;; % h + ;;; % I + ;;; % i + ;;; % J + ;;; % j + ;;; % K + ;;; % k + ;;; % L + ;;; % l + ;;; % M + ;;; % m + ;;; % N + ;;; % n + ;;; % O + ;;; % o + ;;; % P + ;;; % p + ;;; % Q + ;;; % q + ;;; % R + ;;; % r + ;;; % S + ;;; % s + ;;; % T + ;;; % t + ;;; % U + ;;; % u + ;;; % V + ;;; % v + ;;; % W + ;;; % w + ;;; % X + ;;; % x + ;;; % Y + ;;; % y + ;;; % Z + ;;; % z + +% +% Thai consonants, with leading vowels rearrangement +% + ;;; % THAI CHARACTER KO KAI + "";;; + "";;; + "";;; + "";;; + "";;; + + ;;; % THAI CHARACTER KHO KHAI + "";;; + "";;; + "";;; + "";;; + "";;; + + ;;; % THAI CHARACTER KHO KHUAT + "";;; + "";;; + "";;; + "";;; + "";;; + + ;;; % THAI CHARACTER KHO KHWAI + "";;; + "";;; + "";;; + "";;; + "";;; + + ;;; % THAI CHARACTER KHO KHON + "";;; + "";;; + "";;; + "";;; + "";;; + + ;;; % THAI CHARACTER KHO RAKHANG + "";;; + "";;; + "";;; + "";;; + "";;; + + ;;; % THAI CHARACTER NGO NGU + "";;; + "";;; + "";;; + "";;; + "";;; + + ;;; % THAI CHARACTER CHO CHAN + "";;; + "";;; + "";;; + "";;; + "";;; + + ;;; % THAI CHARACTER CHO CHING + "";;; + "";;; + "";;; + "";;; + "";;; + + ;;; % THAI CHARACTER CHO CHANG + "";;; + "";;; + "";;; + "";;; + "";;; + + ;;; % THAI CHARACTER SO SO + "";;; + "";;; + "";;; + "";;; + "";;; + + ;;; % THAI CHARACTER CHO CHOE + "";;; + "";;; + "";;; + "";;; + "";;; + + ;;; % THAI CHARACTER YO YING + "";;; + "";;; + "";;; + "";;; + "";;; + + ;;; % THAI CHARACTER DO CHADA + "";;; + "";;; + "";;; + "";;; + "";;; + + ;;; % THAI CHARACTER TO PATAK + "";;; + "";;; + "";;; + "";;; + "";;; + + ;;; % THAI CHARACTER THO THAN + "";;; + "";;; + "";;; + "";;; + "";;; + + ;;; % THAI CHARACTER THO NANGMONTHO + "";;; + "";;; + "";;; + "";;; + "";;; + + ;;; % THAI CHARACTER THO PHUTHAO + "";;; + "";;; + "";;; + "";;; + "";;; + + ;;; % THAI CHARACTER NO NEN + "";;; + "";;; + "";;; + "";;; + "";;; + + ;;; % THAI CHARACTER DO DEK + "";;; + "";;; + "";;; + "";;; + "";;; + + ;;; % THAI CHARACTER TO TAO + "";;; + "";;; + "";;; + "";;; + "";;; + + ;;; % THAI CHARACTER THO THUNG + "";;; + "";;; + "";;; + "";;; + "";;; + + ;;; % THAI CHARACTER THO THAHAN + "";;; + "";;; + "";;; + "";;; + "";;; + + ;;; % THAI CHARACTER THO THONG + "";;; + "";;; + "";;; + "";;; + "";;; + + ;;; % THAI CHARACTER NO NU + "";;; + "";;; + "";;; + "";;; + "";;; + + ;;; % THAI CHARACTER BO BAIMAI + "";;; + "";;; + "";;; + "";;; + "";;; + + ;;; % THAI CHARACTER PO PLA + "";;; + "";;; + "";;; + "";;; + "";;; + + ;;; % THAI CHARACTER PHO PHUNG + "";;; + "";;; + "";;; + "";;; + "";;; + + ;;; % THAI CHARACTER FO FA + "";;; + "";;; + "";;; + "";;; + "";;; + + ;;; % THAI CHARACTER PHO PHAN + "";;; + "";;; + "";;; + "";;; + "";;; + + ;;; % THAI CHARACTER FO FAN + "";;; + "";;; + "";;; + "";;; + "";;; + + ;;; % THAI CHARACTER PHO SAMPHAO + "";;; + "";;; + "";;; + "";;; + "";;; + + ;;; % THAI CHARACTER MO MA + "";;; + "";;; + "";;; + "";;; + "";;; + + ;;; % THAI CHARACTER YO YAK + "";;; + "";;; + "";;; + "";;; + "";;; + + ;;; % THAI CHARACTER RO RUA + "";;; + "";;; + "";;; + "";;; + "";;; + + ;;; % THAI CHARACTER RU + + ;;; % THAI CHARACTER LO LING + "";;; + "";;; + "";;; + "";;; + "";;; + + ;;; % THAI CHARACTER LU + + ;;; % THAI CHARACTER WO WAEN + "";;; + "";;; + "";;; + "";;; + "";;; + + ;;; % THAI CHARACTER SO SALA + "";;; + "";;; + "";;; + "";;; + "";;; + + ;;; % THAI CHARACTER SO RUSI + "";;; + "";;; + "";;; + "";;; + "";;; + + ;;; % THAI CHARACTER SO SUA + "";;; + "";;; + "";;; + "";;; + "";;; + + ;;; % THAI CHARACTER HO HIP + "";;; + "";;; + "";;; + "";;; + "";;; + + ;;; % THAI CHARACTER LO CHULA + "";;; + "";;; + "";;; + "";;; + "";;; + + ;;; % THAI CHARACTER O ANG + "";;; + "";;; + "";;; + "";;; + "";;; + + ;;; % THAI CHARACTER HO NOKHUK + "";;; + "";;; + "";;; + "";;; + "";;; + + ;;; % THAI CHARACTER NIKHAHIT + +% order of Thai vowels + ;;; % THAI CHARACTER SARA A + ;;; % THAI CHARACTER MAI HAN-AKAT + ;;; % THAI CHARACTER SARA AA + ;;; % THAI CHARACTER LAKKHANGYAO + ;;; % THAI CHARACTER SARA AM + ;;; % THAI CHARACTER SARA I + ;;; % THAI CHARACTER SARA II + ;;; % THAI CHARACTER SARA UE + ;;; % THAI CHARACTER SARA UEE + ;;; % THAI CHARACTER SARA U + ;;; % THAI CHARACTER SARA UU + ;;; % THAI CHARACTER SARA E + ;;; % THAI CHARACTER SARA AE + ;;; % THAI CHARACTER SARA O + ;;; % THAI CHARACTER SARA AI MAIMUAN + ;;; % THAI CHARACTER SARA AI MAIMALAI + +order_end + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ti_ER b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ti_ER new file mode 100644 index 00000000..61b292b1 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ti_ER @@ -0,0 +1 @@ +copy "am_ET" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ti_ET b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ti_ET new file mode 100644 index 00000000..61b292b1 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ti_ET @@ -0,0 +1 @@ +copy "am_ET" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/tl_PH b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/tl_PH new file mode 100644 index 00000000..420168cc --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/tl_PH @@ -0,0 +1,30 @@ +copy "iso14651_t1" + +%% a b c d e f g h i j k l m n ng o p q r s t u v w x y z + +collating-symbol +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-symbol +collating-symbol + +reorder-after + +reorder-after + + +reorder-after + + +reorder-after + ;;;IGNORE + ;;;IGNORE +reorder-after + ;;;IGNORE + ;;;IGNORE + +reorder-end + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/tr_TR b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/tr_TR new file mode 100644 index 00000000..a96c2cf5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/tr_TR @@ -0,0 +1,2061 @@ + +% Base collation scheme: 1994-03-22 + +% Ordering algorithm: +% 1. Spaces and hyphen (but not soft +% hyphen) before punctuation +% characters, punctuation characters +% before numbers, +% numbers before letters. +% 2. Letters with diacritical marks are +% members of equivalence classes +% 3. A distinction is made with regards +% to case as noted below. +% 4. Special characters are ignored +% when comparing letters, but then +% they are considered +% 5. The alphabets are sorted in order +% of first appearance in ISO 10646: +% Latin, Greek, Cyrillic, etc. +% +% According to Greek specifications, +% the steps 2. and 3. above are reversed +% for the Greek script + +% collating symbols + +% The collating symbol naming is +% mostly taken from ISO 10646-1, +% for example the case and accent +% names are from this standard. + +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +% and +% are for cases like Danish +% and Spanish being treated +% as one letter. + +% The ...... collating +% symbols have defined weights as +% the last character in a group of +% Latin letters. They are used +% to specify deltas by locales using +% a locale as the default ordering +% and by "replace-after" statements +% specifying the changed placement +% in an ordering of a character. + +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +% letter;accent;case;specials + +order_start forward;backward;forward;position + +% or letters first: + + + + + + +% Accents: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ;;;IGNORE + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; +<"=> IGNORE;IGNORE;IGNORE;<"=> + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; +UNDEFINED IGNORE;IGNORE;IGNORE + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + +% Arabic collating + + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + +% katakana/hiragana sorting +% base is katakana, as this is present in most charsets +% normal before voiced before semi-voiced +% small vocals before normal vocals +% katakana before hiragana + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + +order_end + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/tt_RU b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/tt_RU new file mode 100644 index 00000000..1ca9685d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/tt_RU @@ -0,0 +1,162 @@ + +% The new (2000) latin tatar alphabet is: +% a, sw, b, c, c,, d, e, f, g, g(, h, i (dotless i), +% i. (i with dot), j, k, q, l, m, n, ng, o, o--, p, r, s, s,, +% t, u, u:, v, w, x, y, z +% ,,,,,,,,,,, +% , , ,,,,,,, +% ,,,,,,,,,,???, ,, +% +% However, a commonly used alphabet in internet uses , and +% for respectively , and + +copy "iso14651_t1" + +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +reorder-after + +reorder-after + +reorder-after + +reorder-after + + + + + +reorder-after + +reorder-after + +reorder-after + +reorder-after + + +% FIXME: check order of cyrillic letters (I copied from cyr Azeri) +reorder-after + +reorder-after + +reorder-after + +reorder-after + +reorder-after + +reorder-after + +reorder-after + +reorder-after + + +reorder-after + ;;;IGNORE + ;;;IGNORE +reorder-after + ;;;IGNORE + ;;;IGNORE + +reorder-after + ;;;IGNORE +reorder-after + ;;;IGNORE + +reorder-after + ;;;IGNORE +reorder-after + ;;;IGNORE + +reorder-after + ;;;IGNORE + ;;;IGNORE +reorder-after + ;;;IGNORE + ;;;IGNORE + +reorder-after + ;;;IGNORE + ;;;IGNORE +reorder-after + ;;;IGNORE + ;;;IGNORE + +reorder-after + ;;;IGNORE + ;;;IGNORE +reorder-after + ;;;IGNORE + ;;;IGNORE + +reorder-after + ;;;IGNORE +reorder-after + ;;;IGNORE + +reorder-after + ;;;IGNORE +reorder-after + ;;;IGNORE + +reorder-after + ;;;IGNORE +reorder-after + ;;;IGNORE + +reorder-after + ;;;IGNORE +reorder-after + ;;;IGNORE + +reorder-after + ;;;IGNORE +reorder-after + ;;;IGNORE + +reorder-after + ;;;IGNORE +reorder-after + ;;;IGNORE + +reorder-after + ;;;IGNORE +reorder-after + ;;;IGNORE + +reorder-after + ;;;IGNORE +reorder-after + ;;;IGNORE + +reorder-after + ;;;IGNORE +reorder-after + ;;;IGNORE + +reorder-after + ;;;IGNORE +reorder-after + ;;;IGNORE + +reorder-end + + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/uk_UA b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/uk_UA new file mode 100644 index 00000000..342a761d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/uk_UA @@ -0,0 +1,15 @@ +copy "iso14651_t1" + +% iso14651_t1 is missing Ukrainian ghe +collating-symbol + +reorder-after + + +reorder-after + ;;;IGNORE + +reorder-after + ;;;IGNORE + +reorder-end diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ur_PK b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ur_PK new file mode 100644 index 00000000..d66184ec --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ur_PK @@ -0,0 +1 @@ +copy "en_DK" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/uz_UZ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/uz_UZ new file mode 100644 index 00000000..afdc7d40 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/uz_UZ @@ -0,0 +1,28 @@ +copy "iso14651_t1" + +%% a b c d e f g g' h i j k l m n o o' p q r s t u v x y z +collating-symbol +collating-element from "" +collating-element from "" +collating-symbol +collating-element from "" +collating-element from "" + +reorder-after + + +reorder-after + + +reorder-after + ;;;IGNORE +reorder-after + ;;;IGNORE + +reorder-after + ;;;IGNORE +reorder-after + ;;;IGNORE + +reorder-end + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/vi_VN b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/vi_VN new file mode 100644 index 00000000..35ae3c60 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/vi_VN @@ -0,0 +1,4 @@ + +% Copy the template from ISO/IEC 14651 +copy "iso14651_t1" + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/wa_BE b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/wa_BE new file mode 100644 index 00000000..be8221cc --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/wa_BE @@ -0,0 +1 @@ +copy "fr_BE" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/yi_US b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/yi_US new file mode 100644 index 00000000..91de1b9c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/yi_US @@ -0,0 +1,43 @@ +copy "iso14651_t1" + +collating-symbol +collating-element from "" +collating-symbol +collating-element from "" +collating-symbol +collating-element from "" +collating-symbol +collating-element from "" +collating-symbol +collating-element from "" +collating-symbol +collating-element from "" + +reorder-after + +reorder-after + +reorder-after + + +reorder-after + + + +reorder-after + ;;;IGNORE +reorder-after + "";"";IGNORE;IGNORE + "";"";IGNORE;IGNORE +reorder-after + "";"";IGNORE;IGNORE + ;;;IGNORE +reorder-after + ;;;IGNORE + ;;;IGNORE +reorder-after + ;;;IGNORE + ;;;IGNORE + +reorder-end + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/zh_CN b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/zh_CN new file mode 100644 index 00000000..3738ee3c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/zh_CN @@ -0,0 +1 @@ +copy "iso14651_t1" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/zh_HK b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/zh_HK new file mode 100644 index 00000000..35ae3c60 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/zh_HK @@ -0,0 +1,4 @@ + +% Copy the template from ISO/IEC 14651 +copy "iso14651_t1" + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/zh_SG b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/zh_SG new file mode 100644 index 00000000..35ae3c60 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/zh_SG @@ -0,0 +1,4 @@ + +% Copy the template from ISO/IEC 14651 +copy "iso14651_t1" + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/zh_TW b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/zh_TW new file mode 100644 index 00000000..3738ee3c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/zh_TW @@ -0,0 +1 @@ +copy "iso14651_t1" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/gen_collate.c b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/gen_collate.c new file mode 100644 index 00000000..15582c1b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/gen_collate.c @@ -0,0 +1,3997 @@ +/* + * Usage: + * gen_collate [-o OUTPUTFILE] LOCALE ... + * + * Generate collation data from locales LOCALE. + * Reads all LOCALE from INPUTDIR and writes collation data to OUTPUTFILE. + * + * The output file defaults to "locales_collate.h". + */ +/* TODO: + * + * add UNDEFINED at end if not specified + * convert POSITION -> FORWARD,POSITION + * + * + * deal with lowercase in + * + * what about reorders that keep the same rule? + * + * remove "unused" collation elements? (probably doesn't save much) + * + * add_rule function ... returns index into rule table after possibly adding custom-indexed rule + * but don't forget about multichar weights... replace with strings of indexes + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef struct { + char *name; /* */ + + int num_weights; /* */ + + int ii_shift; /* */ + int ti_shift; /* */ + int ii_len; /* */ + int ti_len; /* */ + int max_weight; /* */ + int num_col_base; /* */ + int max_col_index; /* */ + int undefined_idx; /* */ + int range_low; /* */ + int range_count; /* high - low */ + int range_base_weight; /* */ + int num_starters; /* */ + + int range_rule_offset; /* */ + int wcs2colidt_offset; /* */ + int index2weight_offset; /* */ + int index2ruleidx_offset; /* */ + int multistart_offset; /* */ + +} base_locale_t; + +#define BASE_LOCALE_LEN 20 +static base_locale_t base_locale_array[BASE_LOCALE_LEN]; +static size_t base_locale_len; + +typedef struct { + char *name; /* */ + + int base_idx; /* */ + + int undefined_idx; /* */ + + int overrides_offset; /* */ + int multistart_offset; /* */ +} der_locale_t; + +#define DER_LOCALE_LEN 300 +static der_locale_t der_locale_array[DER_LOCALE_LEN]; +static size_t der_locale_len; + + +#define OVERRIDE_LEN 50000 +static uint16_t override_buffer[OVERRIDE_LEN]; +static size_t override_len; + +#define MULTISTART_LEN 10000 +static uint16_t multistart_buffer[MULTISTART_LEN]; +static size_t multistart_len; + +#define WCS2COLIDT_LEN 200000 +static uint16_t wcs2colidt_buffer[WCS2COLIDT_LEN]; +static size_t wcs2colidt_len; + +#define INDEX2WEIGHT_LEN 200000 +static uint16_t index2weight_buffer[INDEX2WEIGHT_LEN]; +static size_t index2weight_len; + +static uint16_t index2ruleidx_buffer[INDEX2WEIGHT_LEN]; +static size_t index2ruleidx_len; + +#define WEIGHTSTR_LEN 10000 +static uint16_t weightstr_buffer[WEIGHTSTR_LEN]; +static size_t weightstr_len; + +#define RULETABLE_LEN (1L<<16) +static uint16_t ruletable_buffer[RULETABLE_LEN]; +static size_t ruletable_len; + + +#define RANGE (0x10000UL) + +typedef uint16_t tbl_item; + +static uint16_t u16_buf[10000]; +static int u16_buf_len; +static int u16_starter; + +typedef struct { + uint16_t ii_len; + uint16_t ti_len; + uint16_t ut_len; + + unsigned char ii_shift; + unsigned char ti_shift; + + tbl_item *ii; + tbl_item *ti; + tbl_item *ut; +} table_data; + + +static size_t newopt(tbl_item *ut, size_t usize, int shift, table_data *tbl); + + +#define MAX_COLLATION_WEIGHTS 4 + +#define MAX_FNO 1 +#define MAX_FILES (MAX_FNO + 1) + +static FILE *fstack[MAX_FILES]; +static char *fname[MAX_FILES]; +static int lineno[MAX_FILES]; +static int fno = -1; + +static tbl_item wcs2index[RANGE]; + +static char linebuf[1024]; +static char *pos; +static char *pos_e = NULL; +static char end_of_token = 0; /* slot to save */ + +#define IN_ORDER 0x01 +#define IN_REORDER 0x02 +#define IN_REORDER_SECTIONS 0x04 +static int order_state; +static int cur_num_weights; /* number of weights in current use */ +static char cur_rule[MAX_COLLATION_WEIGHTS]; + +static int anonsection = 0; + +typedef struct ll_item_struct ll_item_t; + +struct ll_item_struct { + ll_item_t *next; + ll_item_t *prev; + void *data; + int data_type; + int idx; +}; + +static ll_item_t *reorder_section_ptr = NULL; +static int superset; +static int superset_order_start_cnt; /* only support one order for now */ +static int superset_in_sync; +static ll_item_t *comm_cur_ptr; +static ll_item_t *comm_prev_ptr; + +enum { + R_FORWARD = 0x01, + R_POSITION = 0x02, + R_BACKWARD = 0x04 /* must be largest in value */ +}; + +typedef struct { + size_t num_weights; + char rule[MAX_COLLATION_WEIGHTS]; + const char *colitem[MAX_COLLATION_WEIGHTS]; +} weight_t; + +static void *root_weight = NULL; +size_t unique_weights = 0; + +typedef struct { + const char *symbol; + weight_t *weight; +} weighted_item_t; + +typedef struct { + const char *symbol1; + const char *symbol2; + int length; + weight_t *weight; +} range_item_t; + +typedef struct { + const char *name; + ll_item_t *itm_list; /* weighted_item_t list .. circular!!! */ + size_t num_items; + size_t num_rules; + char rules[MAX_COLLATION_WEIGHTS]; +} section_t; + +static section_t *cur_section = NULL; + +typedef struct { + const char *symbol; + ll_item_t *node; +} wi_index_t; + +typedef struct col_locale_struct col_locale_t; + +struct col_locale_struct { + char *name; + void *root_colitem; /* all base and derived, or just derived */ + void *root_element; + void *root_scripts; + void *root_wi_index; + void *root_wi_index_reordered; + ll_item_t *section_list; + col_locale_t *base_locale; /* null if this is a base */ + void *root_derived_wi; + ll_item_t *derived_list; + void *root_starter_char; + void *root_starter_all; + ll_item_t *undefined_idx; +}; + +typedef struct { + const char *symbol; + int idx; +} col_index_t; + +static void *root_col_locale = NULL; + +typedef struct { + const char *keyword; + void (*handler)(void); +} keyword_table_t; + +typedef struct { + const char *string; + const char *element; /* NULL if collating symbol */ +} colitem_t; + +static col_locale_t *cur_base = NULL; +static col_locale_t *cur_derived = NULL; +static col_locale_t *cur_col = NULL; + +static void *root_sym = NULL; +static size_t num_sym = 0; +static size_t mem_sym = 0; + +static const char *inputdir; +static size_t inputdir_len; +static unsigned verbose = 0; +enum { + VINFO = (1<<0), + VDETAIL = (1<<1), +}; + +static void error_msg(const char *fmt, ...) __attribute__ ((noreturn, format (printf, 1, 2))); +static void *xmalloc(size_t n); +static char *xsymdup(const char *s); /* only allocate once... store in a tree */ +static void pushfile(char *filename); +static void popfile(void); +static void processfile(void); +static int iscommentchar(int); +static void eatwhitespace(void); +static int next_line(void); +static char *next_token(void); +static void do_unrecognized(void); +static col_locale_t *new_col_locale(char *name); +static ll_item_t *new_ll_item(int data_type, void *data); +static weight_t *register_weight(weight_t *w); +static size_t ll_len(ll_item_t *l); +static size_t ll_count(ll_item_t *l, int mask); +static void add_wi_index(ll_item_t *l); +static size_t tnumnodes(const void *root); +static ll_item_t *find_wi_index(const char *sym, col_locale_t *cl); +static void mark_reordered(const char *sym); +static ll_item_t *find_wi_index_reordered(const char *sym); +static ll_item_t *next_comm_ptr(void); +static ll_item_t *init_comm_ptr(void); +static ll_item_t *find_ll_last(ll_item_t *p); +static void dump_weights(const char *name); +static void finalize_base(void); +static int is_ucode(const char *s); +static int sym_cmp(const void *n1, const void *n2); +static void do_starter_lists(col_locale_t *cl); +static void dump_base_locale(int n); +static void dump_der_locale(int n); +static void dump_collate(FILE *fp); + +enum { + DT_SECTION = 0x01, + DT_WEIGHTED = 0x02, + DT_REORDER = 0x04, /* a section to support reorder_after */ + DT_COL_LOCALE = 0x08, + DT_RANGE = 0x10, +}; + +static int verbose_msg(const unsigned lvl, const char *fmt, ...) +{ + va_list arg; + int ret = 0; + + if (verbose & lvl) { + va_start(arg, fmt); + ret = vfprintf(stderr, fmt, arg); + va_end(arg); + } + return ret; +} +static section_t *new_section(const char *name) +{ + section_t *p; + char buf[128]; + + p = xmalloc(sizeof(section_t)); + if (!name) { /* anonymous section */ + name = buf; + snprintf(buf, sizeof(buf), "anon%05d", anonsection); + ++anonsection; + } else if (*name != '<') { /* reorder */ + name = buf; + snprintf(buf, sizeof(buf), "%s %05d", cur_col->name, anonsection); + ++anonsection; + } +#warning devel code +/* verbose_msg(VDETAIL, "section %s\n", name); */ + p->name = xsymdup(name); + p->itm_list = NULL; + p->num_items = 0; + p->num_rules = 0; + memset(p->rules, 0, MAX_COLLATION_WEIGHTS); +/* cur_num_weights = p->num_rules = 0; */ +/* memset(p->rules, 0, MAX_COLLATION_WEIGHTS); */ +/* memset(cur_rule, R_FORWARD, 4); */ + +#warning devel code + if (*p->name == 'a') { + cur_num_weights = p->num_rules = 4; + memset(p->rules, R_FORWARD, 4); + memset(cur_rule, R_FORWARD, 4); + p->rules[3] |= R_POSITION; + cur_rule[3] |= R_POSITION; + } +/* verbose_msg(VDETAIL, "new section %s -- cur_num_weights = %d\n", p->name, cur_num_weights); */ + + return p; +} + + + +static void do_order_start(void); +static void do_order_end(void); +static void do_reorder_after(void); +static void do_reorder_end(void); +static void do_reorder_sections_after(void); +static void do_reorder_sections_end(void); +static void do_copy(void); +static void do_colsym(void); +static void do_colele(void); +static void do_script(void); +static void do_range(void); + +static col_locale_t *new_col_locale(char *name); +static int colitem_cmp(const void *n1, const void *n2); +static int colelement_cmp(const void *n1, const void *n2); +static void del_colitem(colitem_t *p); +static colitem_t *new_colitem(char *item, char *def); +static void add_colitem(char *item, char *def); +static void add_script(const char *s); +static unsigned int add_rule(weighted_item_t *wi); +static unsigned int add_range_rule(range_item_t *ri); + +static const keyword_table_t keyword_table[] = { + { "collating-symbol", do_colsym }, + { "collating-element", do_colele }, + { "script", do_script }, + { "copy", do_copy }, + { "order_start", do_order_start }, + { "order_end", do_order_end }, + { "order-end", do_order_end }, + { "reorder-after", do_reorder_after }, + { "reorder-end", do_reorder_end }, + { "reorder-sections-after", do_reorder_sections_after }, + { "reorder-sections-end", do_reorder_sections_end }, + { "UCLIBC_RANGE", do_range }, + { NULL, do_unrecognized } +}; + + +static void do_unrecognized(void) +{ +#if 1 + error_msg("warning: unrecognized: %s", pos); +#else +/* verbose_msg(VDETAIL, "warning: unrecognized initial keyword \"%s\"\n", pos); */ + fprintf(stderr, "warning: unrecognized: %s", pos); + if (end_of_token) { + fprintf(stderr, "%c%s", end_of_token, pos_e+1); + } + fprintf(stderr, "\n"); +#endif +} + +/* typedef struct { */ +/* const char *symbol1; */ +/* const char *symbol2; */ +/* int length; */ +/* weight_t *weight; */ +/* } range_item_t; */ + +static void do_range(void) +{ + range_item_t *ri; + weight_t w; + int i; + char *s; + char *s1; + char *s2; + const char **ci; + ll_item_t *lli; + + assert(!superset); + assert(order_state == IN_ORDER); + + s1 = next_token(); + if (!s1) { + error_msg("missing start of range"); + } + if (!is_ucode(s1)) { + error_msg("start of range is not a ucode: %s", s1); + } + s1 = xsymdup(s1); + + s2 = next_token(); + if (!s2) { + error_msg("missing end of range"); + } + if (!is_ucode(s2)) { + error_msg("end of range is not a ucode: %s", s2); + } + s2 = xsymdup(s2); + + ri = (range_item_t *) xmalloc(sizeof(range_item_t)); + ri->symbol1 = s1; + ri->symbol2 = s2; + ri->length = strtoul(s2+2, NULL, 16) - strtoul(s1+2, NULL, 16); + if (ri->length <= 0) { + error_msg("illegal range length %d", ri->length); + } + + s = next_token(); + w.num_weights = cur_num_weights; + + for (i=0 ; i < cur_num_weights ; i++) { + w.rule[i] = cur_rule[i]; + } + ci = w.colitem + (i-1); + /* now i == cur_num_weights */ + +#define STR_DITTO "." + + while (s && *s && i) { + --i; + if (*s == ';') { + ci[-i] = xsymdup(STR_DITTO); + if (*++s) { + continue; + } + } + if (*s) { + ci[-i] = xsymdup(s); + } + s = next_token(); + if (s) { + if (*s == ';') { + ++s; + } else if (i) { + error_msg("missing seperator"); + } + } + } + if (s) { + error_msg("too many weights: %d %d |%s| %d", cur_num_weights, i, s, (int)*s); + } + + while (i) { /* missing weights are not an error */ + --i; + ci[-i] = xsymdup(STR_DITTO); + } + + ri->weight = register_weight(&w); + +/* if ((i = is_ucode(t)) != 0) { */ +/* assert(!t[i]); */ +/* add_colitem(t, NULL); */ +/* } */ + + lli = new_ll_item(DT_RANGE, ri); + if (!cur_section->itm_list) { +/* printf("creating new item list: %s\n", wi->symbol); */ + cur_section->itm_list = lli; + lli->prev = lli->next = lli; + ++cur_section->num_items; + } else { + insque(lli, cur_section->itm_list->prev); +/* printf("adding item to list: %d - %s\n", ll_len(cur_section->itm_list), wi->symbol); */ + ++cur_section->num_items; + } +/* add_wi_index(lli); */ + + +} + +static weighted_item_t *add_weight(char *t) +{ + weighted_item_t *wi; + weight_t w; + int i; + char *s; + const char **ci; + + t = xsymdup(t); + + s = next_token(); + w.num_weights = cur_num_weights; + + for (i=0 ; i < cur_num_weights ; i++) { + w.rule[i] = cur_rule[i]; + } + ci = w.colitem + (i-1); + /* now i == cur_num_weights */ + + while (s && *s && i) { + --i; + if (*s == ';') { + ci[-i] = xsymdup(STR_DITTO); + if (*++s) { + continue; + } + } + if (*s) { + if (!strcmp(s,t)) { + s = STR_DITTO; + } + ci[-i] = xsymdup(s); + } + s = next_token(); + if (s) { + if (*s == ';') { + ++s; + } else if (i) { + error_msg("missing seperator"); + } + } + } + if (s) { + error_msg("too many weights: %d %d |%s| %d", cur_num_weights, i, s, (int)*s); + } + + while (i) { /* missing weights are not an error */ + --i; + ci[-i] = xsymdup(STR_DITTO); + } + + wi = xmalloc(sizeof(weighted_item_t)); + wi->symbol = t; + wi->weight = register_weight(&w); + + if ((i = is_ucode(t)) != 0) { + assert(!t[i]); + add_colitem(t, NULL); + } + + return wi; +} + +static void add_superset_weight(char *t) +{ + ll_item_t *lli; + weighted_item_t *wi; + + if (!comm_cur_ptr + || (strcmp(t, ((weighted_item_t *)(comm_cur_ptr->data))->symbol) != 0) + ) { /* now out of sync */ + if (superset_in_sync) { /* need a new section */ + superset_in_sync = 0; + + cur_section = new_section("R"); + cur_num_weights = cur_section->num_rules + = ((section_t *)(cur_base->section_list->data))->num_rules; + memcpy(cur_rule, + ((section_t *)(cur_base->section_list->data))->rules, + MAX_COLLATION_WEIGHTS); + memcpy(cur_section->rules, + ((section_t *)(cur_base->section_list->data))->rules, + MAX_COLLATION_WEIGHTS); + + insque(new_ll_item(DT_REORDER, cur_section), find_ll_last(cur_col->section_list)); + assert(comm_prev_ptr); + lli = new_ll_item(DT_REORDER, cur_section); + lli->prev = lli->next = lli; + insque(lli, comm_prev_ptr); +/* verbose_msg(VDETAIL, " subsection -----------------------\n"); */ + } + +/* verbose_msg(VDETAIL, " %s %s\n", t, ((weighted_item_t *)(comm_cur_ptr->data))->symbol); */ + wi = add_weight(t); + lli = new_ll_item(DT_WEIGHTED, wi); + mark_reordered(wi->symbol); + /* printf("reorder: %s\n", t); */ + if (!cur_section->itm_list) { + cur_section->itm_list = lli; + lli->prev = lli->next = lli; + ++cur_section->num_items; + } else { + insque(lli, cur_section->itm_list->prev); + ++cur_section->num_items; + } + add_wi_index(lli); + + } else { /* in sync */ + superset_in_sync = 1; + next_comm_ptr(); + } +} + +static void do_weight(char *t) +{ + weighted_item_t *wi; + ll_item_t *lli; + + if (superset) { + add_superset_weight(t); + return; + } + + switch(order_state) { + case 0: +/* fprintf(stdout, "no-order weight: %s\n", t); */ +/* break; */ + case IN_ORDER: + /* in a section */ +/* fprintf(stdout, "weight: %s\n", t); */ + wi = add_weight(t); + lli = new_ll_item(DT_WEIGHTED, wi); + if (!cur_section->itm_list) { +/* fprintf(stdout, "creating new item list: %s %s %p\n", wi->symbol, cur_section->name, lli); */ + cur_section->itm_list = lli; + lli->prev = lli->next = lli; + ++cur_section->num_items; + } else { + insque(lli, cur_section->itm_list->prev); +/* fprintf(stdout, "adding item to list: %d - %s %p\n", ll_len(cur_section->itm_list), wi->symbol, lli); */ + ++cur_section->num_items; + } + add_wi_index(lli); + break; + case IN_REORDER: + /* std rule - but in a block with an insert-after pt */ + wi = add_weight(t); + lli = new_ll_item(DT_WEIGHTED, wi); + mark_reordered(wi->symbol); +/* fprintf(stdout, "reorder: %s %s %p\n", t, cur_section->name, lli); */ + if (!cur_section->itm_list) { + cur_section->itm_list = lli; + lli->prev = lli->next = lli; + ++cur_section->num_items; + } else { + insque(lli, cur_section->itm_list->prev); + ++cur_section->num_items; + } + add_wi_index(lli); + break; + case IN_REORDER_SECTIONS: + t = xsymdup(t); + if (next_token() != NULL) { + error_msg("trailing text in reorder section item: %s", pos); + } + lli = cur_col->section_list; + do { + if (lli->data_type & DT_SECTION) { + if (!strcmp(((section_t *)(lli->data))->name, t)) { + lli->data_type = DT_REORDER; + lli = new_ll_item(DT_REORDER, (section_t *)(lli->data)); + insque(lli, reorder_section_ptr); + reorder_section_ptr = lli; + return; + } + } + lli = lli->next; + } while (lli); + error_msg("reorder_sections_after for non-base item currently not supported: %s", t); +/* fprintf(stdout, "reorder_secitons: %s\n", t); */ + break; + default: + error_msg("invalid order_state %d", order_state); + } +} + +static int col_locale_cmp(const void *n1, const void *n2) +{ + return strcmp(((const col_locale_t *) n1)->name, ((const col_locale_t *) n2)->name); +} + +static void processfile(void) +{ + char *t; + const keyword_table_t *k; + + order_state = 0; +#warning devel code +/* cur_num_weights = 0; */ +/* cur_num_weights = 4; */ +/* memset(cur_rule, R_FORWARD, 4); */ + + if (cur_col != cur_base) { + cur_col->base_locale = cur_base; + cur_col->undefined_idx = cur_base->undefined_idx; + if (!cur_base->derived_list) { + cur_base->derived_list = new_ll_item(DT_COL_LOCALE, cur_col); + } else { + insque(new_ll_item(DT_COL_LOCALE, cur_col), find_ll_last(cur_base->derived_list)); + } + } + + if (tfind(cur_col, &root_col_locale, col_locale_cmp)) { + error_msg("attempt to read locale: %s", cur_col->name); + } + if (!tsearch(cur_col, &root_col_locale, col_locale_cmp)) { + error_msg("OUT OF MEMORY!"); + } + + if (superset) { + superset_order_start_cnt = 0; + superset_in_sync = 0; + init_comm_ptr(); + } + + while (next_line()) { +/* printf("%5d:", lineno[fno]); */ +/* while ((t = next_token()) != NULL) { */ +/* printf(" |%s|", t); */ +/* printf("\n"); */ +/* } */ + t = next_token(); + assert(t); + assert(t == pos); + if ((*t == '<') || (!strcmp(t, "UNDEFINED"))) { + do_weight(t); + } else { + for (k = keyword_table ; k->keyword ; k++) { + if (!strcmp(k->keyword, t)) { + break; + } + } + k->handler(); + } + } + + if (cur_base == cur_col) { + verbose_msg(VDETAIL, "Base: %15s", cur_col->name); + } else { +#if 1 + if (!cur_col->undefined_idx) { +#if 0 + if (superset) { + if (superset_order_start_cnt == 1) { + --superset_order_start_cnt; /* ugh.. hack this */ + } + } +#endif + /* This is an awful hack to get around the problem of unspecified UNDEFINED + * definitions in the supported locales derived from iso14651_t1. */ + if (!strcmp(cur_base->name, "iso14651_t1")) { + fprintf(stderr, "Warning: adding UNDEFINED entry for %s\n", cur_col->name); + strcpy(linebuf, "script \n"); + pos_e = NULL; + pos = linebuf; + t = next_token(); + assert(t); + assert(t == pos); + do_script(); + strcpy(linebuf, "order_start ;forward;backward;forward;forward,position\n"); + pos_e = NULL; + pos = linebuf; + t = next_token(); + assert(t); + assert(t == pos); + do_order_start(); + strcpy(linebuf, "UNDEFINED IGNORE;IGNORE;IGNORE\n"); + pos_e = NULL; + pos = linebuf; + t = next_token(); + assert(t); + assert(t == pos); + do_weight(t); + strcpy(linebuf, "order_end\n"); + pos_e = NULL; + pos = linebuf; + t = next_token(); + assert(t); + assert(t == pos); + do_order_end(); + } else { + error_msg("no definition of UNDEFINED for %s", cur_col->name); + } + } +#endif + + verbose_msg(VDETAIL, " Der: %15s", cur_col->name); + } + { +#if 0 + ll_item_t *p = cur_col->section_list; +#endif + verbose_msg(VDETAIL, "%6u weights", tnumnodes(cur_col->root_wi_index)); + if (cur_base) { + verbose_msg(VDETAIL, " %6u der %6u reor %6u starter - %u new stubs", + tnumnodes(cur_base->root_derived_wi), + tnumnodes(cur_base->root_wi_index_reordered), + tnumnodes(cur_base->root_starter_char), + ll_count(cur_col->section_list, DT_REORDER)); + } + verbose_msg(VDETAIL, "\n"); + +#if 0 + while (p) { + assert(((section_t *)(p->data))->num_items == + ll_len(((section_t *)(p->data))->itm_list)); + + + if (!p->next && + ((*((section_t *)(p->data))->name == 'a') + && (((section_t *)(p->data))->num_items == 0)) + ) { + break; + } + + if (!(p->data_type & DT_REORDER)) { + if ((*((section_t *)(p->data))->name != 'a') + || (((section_t *)(p->data))->num_items > 0) + ) { + verbose_msg(VDETAIL, +/* "\t%-15s %zu\n", */ + "\t%-15s %6u\n", + ((section_t *)(p->data))->name, + ((section_t *)(p->data))->num_items); + } + } + p = p->next; + } +#endif + } + + +} + +static void print_colnode(const void *ptr, VISIT order, int level) +{ + const colitem_t *p = *(const colitem_t **) ptr; + + if (order == postorder || order == leaf) { + printf("collating item = \"%s\"", p->string); + if (p->element) { + printf(" is %s", p->element); + } + printf("\n"); + } +} + +static void print_weight_node(const void *ptr, VISIT order, int level) +{ + const weight_t *p = *(const weight_t **) ptr; + int i; + + if (order == postorder || order == leaf) { + printf("weight: (%d) ", p->num_weights); + for (i = 0 ; i < p->num_weights ; i++) { + if (p->rule[i] & R_FORWARD) { + printf("F"); + } + if (p->rule[i] & R_BACKWARD) { + printf("B"); + } + if (p->rule[i] & R_POSITION) { + printf("P"); + } + printf(","); + } + for (i = 0 ; i < p->num_weights ; i++) { + printf(" %s", p->colitem[i]); + } + printf("\n"); + } +} + + +typedef struct { + const char *der_name; + int base_locale; +} deps_t; + +enum { + BASE_iso14651_t1, + BASE_comm, + BASE_cs_CZ, + BASE_ar_SA, + BASE_th_TH, + BASE_ja_JP, + BASE_ko_KR, + BASE_MAX +}; + +static const char *base_name[] = { + "iso14651_t1", + "comm", + "cs_CZ", + "ar_SA", + "th_TH", + "ja_JP", + "ko_KR" +}; + + + +static ll_item_t *locale_list[BASE_MAX]; + +static void init_locale_list(void) +{ + int i; + + for (i=0 ; i < BASE_MAX ; i++) { + locale_list[i] = (ll_item_t *) xmalloc(sizeof(ll_item_t)); + locale_list[i]->prev = locale_list[i]->next = locale_list[i]; + locale_list[i]->data = (void *) base_name[i]; + } +} + + +deps_t deps[] = { + { "af_ZA", BASE_iso14651_t1 }, + { "am_ET", BASE_iso14651_t1 }, + { "ar_AE", BASE_iso14651_t1 }, + { "ar_BH", BASE_iso14651_t1 }, + { "ar_DZ", BASE_iso14651_t1 }, + { "ar_EG", BASE_iso14651_t1 }, + { "ar_IN", BASE_iso14651_t1 }, + { "ar_IQ", BASE_iso14651_t1 }, + { "ar_JO", BASE_iso14651_t1 }, + { "ar_KW", BASE_iso14651_t1 }, + { "ar_LB", BASE_iso14651_t1 }, + { "ar_LY", BASE_iso14651_t1 }, + { "ar_MA", BASE_iso14651_t1 }, + { "ar_OM", BASE_iso14651_t1 }, + { "ar_QA", BASE_iso14651_t1 }, + { "ar_SA", BASE_ar_SA }, + { "ar_SD", BASE_iso14651_t1 }, + { "ar_SY", BASE_iso14651_t1 }, + { "ar_TN", BASE_iso14651_t1 }, + { "ar_YE", BASE_iso14651_t1 }, + { "az_AZ", BASE_iso14651_t1 }, + { "be_BY", BASE_iso14651_t1 }, + { "bg_BG", BASE_iso14651_t1 }, + { "bn_BD", BASE_iso14651_t1 }, + { "bn_IN", BASE_iso14651_t1 }, + { "br_FR", BASE_iso14651_t1 }, + { "bs_BA", BASE_iso14651_t1 }, + { "ca_ES", BASE_comm }, + { "cs_CZ", BASE_cs_CZ }, + { "cy_GB", BASE_iso14651_t1 }, + { "da_DK", BASE_comm }, + { "de_AT", BASE_iso14651_t1 }, + { "de_BE", BASE_iso14651_t1 }, + { "de_CH", BASE_iso14651_t1 }, + { "de_DE", BASE_iso14651_t1 }, + { "de_LU", BASE_iso14651_t1 }, + { "el_GR", BASE_iso14651_t1 }, + { "en_AU", BASE_iso14651_t1 }, + { "en_BW", BASE_iso14651_t1 }, + { "en_CA", BASE_comm }, + { "en_DK", BASE_iso14651_t1 }, + { "en_GB", BASE_iso14651_t1 }, + { "en_HK", BASE_iso14651_t1 }, + { "en_IE", BASE_iso14651_t1 }, + { "en_IN", BASE_iso14651_t1 }, + { "en_NZ", BASE_iso14651_t1 }, + { "en_PH", BASE_iso14651_t1 }, + { "en_SG", BASE_iso14651_t1 }, + { "en_US", BASE_iso14651_t1 }, + { "en_ZA", BASE_iso14651_t1 }, + { "en_ZW", BASE_iso14651_t1 }, + { "eo_EO", BASE_iso14651_t1 }, + { "es_AR", BASE_comm }, + { "es_BO", BASE_comm }, + { "es_CL", BASE_comm }, + { "es_CO", BASE_comm }, + { "es_CR", BASE_comm }, + { "es_DO", BASE_comm }, + { "es_EC", BASE_comm }, + { "es_ES", BASE_comm }, + { "es_GT", BASE_comm }, + { "es_HN", BASE_comm }, + { "es_MX", BASE_comm }, + { "es_NI", BASE_comm }, + { "es_PA", BASE_comm }, + { "es_PE", BASE_comm }, + { "es_PR", BASE_comm }, + { "es_PY", BASE_comm }, + { "es_SV", BASE_comm }, + { "es_US", BASE_comm }, + { "es_UY", BASE_comm }, + { "es_VE", BASE_comm }, + { "et_EE", BASE_comm }, + { "eu_ES", BASE_iso14651_t1 }, + { "fa_IR", BASE_iso14651_t1 }, + { "fi_FI", BASE_comm }, + { "fo_FO", BASE_comm }, + { "fr_BE", BASE_iso14651_t1 }, + { "fr_CA", BASE_comm }, + { "fr_CH", BASE_iso14651_t1 }, + { "fr_FR", BASE_iso14651_t1 }, + { "fr_LU", BASE_iso14651_t1 }, + { "ga_IE", BASE_iso14651_t1 }, + { "gd_GB", BASE_iso14651_t1 }, + { "gl_ES", BASE_comm }, + { "gv_GB", BASE_iso14651_t1 }, + { "he_IL", BASE_iso14651_t1 }, + { "hi_IN", BASE_iso14651_t1 }, + { "hr_HR", BASE_comm }, + { "hu_HU", BASE_iso14651_t1 }, + { "hy_AM", BASE_iso14651_t1 }, + { "id_ID", BASE_iso14651_t1 }, + { "is_IS", BASE_comm }, + { "it_CH", BASE_iso14651_t1 }, + { "it_IT", BASE_iso14651_t1 }, + { "iw_IL", BASE_iso14651_t1 }, + { "ja_JP", BASE_ja_JP }, + { "ka_GE", BASE_iso14651_t1 }, + { "kl_GL", BASE_comm }, + { "ko_KR", BASE_ko_KR }, + { "kw_GB", BASE_iso14651_t1 }, + { "lt_LT", BASE_comm }, + { "lv_LV", BASE_comm }, + { "mi_NZ", BASE_iso14651_t1 }, + { "mk_MK", BASE_iso14651_t1 }, + { "mr_IN", BASE_iso14651_t1 }, + { "ms_MY", BASE_iso14651_t1 }, + { "mt_MT", BASE_iso14651_t1 }, + { "nl_BE", BASE_iso14651_t1 }, + { "nl_NL", BASE_iso14651_t1 }, + { "nn_NO", BASE_iso14651_t1 }, + { "no_NO", BASE_comm }, + { "oc_FR", BASE_iso14651_t1 }, + { "pl_PL", BASE_comm }, + { "pt_BR", BASE_iso14651_t1 }, + { "pt_PT", BASE_iso14651_t1 }, + { "ro_RO", BASE_iso14651_t1 }, + { "ru_RU", BASE_iso14651_t1 }, + { "ru_UA", BASE_iso14651_t1 }, + { "se_NO", BASE_iso14651_t1 }, + { "sk_SK", BASE_cs_CZ }, + { "sl_SI", BASE_comm }, + { "sq_AL", BASE_iso14651_t1 }, + { "sr_YU", BASE_iso14651_t1 }, + { "sv_FI", BASE_comm }, + { "sv_SE", BASE_iso14651_t1 }, + { "ta_IN", BASE_iso14651_t1 }, + { "te_IN", BASE_iso14651_t1 }, + { "tg_TJ", BASE_iso14651_t1 }, + { "th_TH", BASE_th_TH }, + { "ti_ER", BASE_iso14651_t1 }, + { "ti_ET", BASE_iso14651_t1 }, + { "tl_PH", BASE_iso14651_t1 }, + { "tr_TR", BASE_comm }, + { "tt_RU", BASE_iso14651_t1 }, + { "uk_UA", BASE_iso14651_t1 }, + { "ur_PK", BASE_iso14651_t1 }, + { "uz_UZ", BASE_iso14651_t1 }, + { "vi_VN", BASE_iso14651_t1 }, + { "wa_BE", BASE_iso14651_t1 }, + { "yi_US", BASE_iso14651_t1 }, + { "zh_CN", BASE_iso14651_t1 }, + { "zh_HK", BASE_iso14651_t1 }, + { "zh_SG", BASE_iso14651_t1 }, + { "zh_TW", BASE_iso14651_t1 }, +}; + + +static int der_count[BASE_MAX]; +static const char *new_args[500]; +static int new_arg_count; + +static int dep_cmp(const void *s1, const void *s2) +{ + return strcmp( (const char *) s1, ((const deps_t *) s2)->der_name); +} + +static int old_main(int argc, char **argv); + +int main(int argc, char **argv) +{ + const deps_t *p; + ll_item_t *lli; + int i; + int total; + char *output_file = "locale_collate.h"; + unsigned verbosity = 0; + + if (argc < 3) { + return EXIT_FAILURE; + } + --argc; + inputdir = strdup(*++argv); + inputdir_len = strlen(inputdir); + init_locale_list(); + + while (--argc) { + ++argv; + if (!strcmp(*argv, "-o")) { + --argc; + if (*++argv == NULL) { + printf("-o requires an argument\n"); + return EXIT_FAILURE; + } + output_file = strdup(*argv); + continue; + } else if (!strcmp(*argv, "-v")) { + verbosity++; + continue; + } + p = (const deps_t *) bsearch(*argv, deps, sizeof(deps)/sizeof(deps[0]), sizeof(deps[0]), dep_cmp); + if (!p) { + if (!strcmp("C", *argv)) { + printf("ignoring %s locale\n", *argv); + continue; + } else { + printf("%s not found\n", *argv); + return EXIT_FAILURE; + } + } + + i = p->base_locale; + ++der_count[i]; + + if (!strcmp(base_name[i], *argv)) { + /* same name as base, so skip after count incremented */ + continue; + } + + /* add it to the list. the main body will catch duplicates */ + lli = (ll_item_t *) xmalloc(sizeof(ll_item_t)); + lli->prev = lli->next = NULL; + lli->data = (void *) *argv; + insque(lli, locale_list[i]); + } + + total = 0; + for (i=0 ; i < BASE_MAX ; i++) { +/* printf("der_count[%2d] = %3d\n", i, der_count[i]); */ + total += der_count[i]; + } +/* printf("total = %d\n", total); */ + + new_args[new_arg_count++] = "dummyprogramname"; + for (i=0 ; i < BASE_MAX ; i++) { + if (!der_count[i]) { + continue; + } + new_args[new_arg_count++] = (i == BASE_comm) ? "-c" : "-b"; + lli = locale_list[i]; + do { + new_args[new_arg_count++] = (const char *) (lli->data); + lli = lli->next; + } while (lli != locale_list[i]); + new_args[new_arg_count++] = "-f"; + } + for (i=0; i < verbosity; i++) + new_args[new_arg_count++] = "-v"; + + new_args[new_arg_count++] = "-o"; + new_args[new_arg_count++] = output_file; +/* + for (i=0 ; i < new_arg_count ; i++) { + printf("%3d: %s\n", i, new_args[i]); + } +*/ + return old_main(new_arg_count, (char **) new_args); +} + + +/* usage... prog -b basefile derived {derived} -s single {single} */ + +static int old_main(int argc, char **argv) +{ + int next_is_base = 0; + int next_is_subset = 0; + char *output_file = NULL; + + superset = 0; + + while (--argc) { + ++argv; + if (**argv == '-') { + if ((*argv)[1] == 'd') { + dump_weights((*argv) + 2); + } else if ((*argv)[1] == 'f') { /* dump all weight rules */ + finalize_base(); + } else if ((*argv)[1] == 'R') { /* dump all weight rules */ + twalk(root_weight, print_weight_node); + } else if (((*argv)[1] == 'c') && !(*argv)[2]) { /* new common subset */ + cur_base = cur_derived = NULL; + next_is_subset = 1; + next_is_base = 1; + superset = 0; + } else if (((*argv)[1] == 'b') && !(*argv)[2]) { /* new base locale */ + cur_base = cur_derived = NULL; + next_is_subset = 0; + next_is_base = 1; + superset = 0; + } else if (((*argv)[1] == 's') && !(*argv)[2]) { /* single locales follow */ + cur_base = cur_derived = NULL; + next_is_subset = 0; + next_is_base = 2; + superset = 0; + } else if (((*argv)[1] == 'o') && !(*argv)[2]) { /* output file */ + --argc; + output_file = *++argv; + } else if (((*argv)[1] == 'v') && !(*argv)[2]) { /* verbose */ + ++verbose; + } else { + error_msg("unrecognized option %s", *argv); + } + continue; + } + /* new file */ + new_col_locale(*argv); /* automaticly sets cur_col */ + if (next_is_base) { + cur_base = cur_col; + } else { + cur_derived = cur_col; + } + pushfile(*argv); +/* verbose_msg(VDETAIL, "processing file %s\n", *argv); */ + processfile(); /* this does a popfile */ + +/* twalk(cur_col->root_colitem, print_colnode); */ + + if (next_is_base == 1) { + next_is_base = 0; + } + if (next_is_subset) { + next_is_subset = 0; + superset = 1; + } + } + + verbose_msg(VINFO, "success!\n"); + verbose_msg(VINFO, +/* "num_sym=%zu mem_sym=%zu unique_weights=%zu\n", */ + "num_sym=%u mem_sym=%u unique_weights=%u\n", + num_sym, mem_sym, unique_weights); +/* twalk(root_weight, print_weight_node); */ + + verbose_msg(VINFO, "num base locales = %d num derived locales = %d\n", + base_locale_len, der_locale_len); + + verbose_msg(VINFO, + "override_len = %d multistart_len = %d weightstr_len = %d\n" + "wcs2colidt_len = %d index2weight_len = %d index2ruleidx_len = %d\n" + "ruletable_len = %d\n" + "total size is %d bytes or %d kB\n", + override_len, multistart_len, weightstr_len, + wcs2colidt_len, index2weight_len, index2ruleidx_len, + ruletable_len, +#warning mult by 2 for rule indecies + (override_len + multistart_len + weightstr_len + + wcs2colidt_len + index2weight_len + index2ruleidx_len + ruletable_len) * 2, + (override_len + multistart_len + weightstr_len + + wcs2colidt_len + index2weight_len + index2ruleidx_len + ruletable_len + 511) / 512); + +#if 0 + { + int i; + + for (i=0 ; i < base_locale_len ; i++) { + dump_base_locale(i); + } + for (i=0 ; i < der_locale_len ; i++) { + dump_der_locale(i); + } + } +#endif + + { + FILE *fp = fopen(output_file, "w"); + + if (!fp) { + error_msg("cannot open output file '%s'!", output_file); + } + dump_collate(fp); + if (ferror(fp) || fclose(fp)) { + error_msg("write error or close error for output file!\n"); + } + } + + return EXIT_SUCCESS; +} + +static void error_msg(const char *fmt, ...) +{ + va_list arg; + + fprintf(stderr, "Error: "); + if (fno >= 0) { + fprintf(stderr, "file %s (%d): ", fname[fno], lineno[fno]); + } + va_start(arg, fmt); + vfprintf(stderr, fmt, arg); + va_end(arg); + fprintf(stderr, "\n"); + + exit(EXIT_FAILURE); +} + +static void pushfile(char *filename) +{ + char *inputfile; + size_t inputfile_len; + + if (fno >= MAX_FNO) { + error_msg("file stack size exceeded"); + } + + inputfile_len = inputdir_len + strlen(filename) + 2; + inputfile = xmalloc(inputfile_len); + memset(inputfile, 0, inputfile_len); + sprintf(inputfile, "%s/%s", inputdir, filename); + if (!(fstack[++fno] = fopen(inputfile, "r"))) { + --fno; /* oops */ + error_msg("cannot open file %s: %s", inputfile, strerror(errno)); + } + + fname[fno] = xsymdup(inputfile); + lineno[fno] = 0; +} + +static void popfile(void) +{ + if (fno < 0) { + error_msg("pop on empty file stack"); + } + +/* free(fname[fno]); */ + fclose(fstack[fno]); + --fno; +} + +static void eatwhitespace(void) +{ + while (isspace(*pos)) { + ++pos; + } +} + +static int iscommentchar(int c) +{ + return ((c == '#') || (c == '%')); +} + +static int next_line(void) +{ + size_t n; + char *s = linebuf; + + assert(fno >= 0); + + pos_e = NULL; + do { + if (fgets(s, sizeof(linebuf), fstack[fno]) != NULL) { + ++lineno[fno]; + n = strlen(linebuf); + if ((n == sizeof(linebuf) - 1) && (linebuf[n-1] != '\n')) { + /* Either line is too long or last line is very long with + * no trailing newline. But we'll always treat it as an + * errro. */ + error_msg("line too long?"); + } + + --n; + /* Be careful... last line doesn't need a newline. */ + if (linebuf[n] == '\n') { + linebuf[n--] = 0; /* trim trailing newline */ + } + + pos = linebuf; + eatwhitespace(); + if (*pos && !iscommentchar(*pos)) { /* not empty or comment line */ + return 1; /* got a line */ + } + } else { /* eof */ + popfile(); + } + } while (fno >= 0); + + return 0; +} + +static char *next_token(void) +{ + char *p; + +#if 0 + if (pos_e == NULL) { + return NULL + pos = pos_e; + *pos = end_of_token; + end_of_token = 0; + } +#else + if (pos_e != NULL) { + pos = pos_e; + *pos = end_of_token; + end_of_token = 0; + } +#endif + eatwhitespace(); + p = pos; + + if (!*p || iscommentchar(*p)) { /* end of line or start of comment */ + pos = pos_e = NULL; + *p = 0; /* treat comment as end of line */ +/* fprintf(stdout, "returning NUL token |%s|\n", pos); */ + return NULL; +#if 1 + } else if (*p == '<') { /* collating symbol, element, or value */ + while (*++p) { + if ((*p == '/') && p[1]) { + ++p; + continue; + } + if (*p == '>') { + pos_e = ++p; + end_of_token = *p; + *p = 0; +/* fprintf(stdout, "returning col token |%s|\n", pos); */ + return pos; + } + } + } else if (*p == '"') { /* collating element value? */ + while (*++p) { + if (*p == '"') { /* found the end of the quoted string */ + pos_e = ++p; + end_of_token = *p; + *p = 0; +/* fprintf(stdout, "returning quote token |%s|\n", pos); */ + return pos; + } + } +#endif + } else { /* some kind of keyword */ + while (*++p) { + if (isspace(*p) || (*p == ';')) { + break; + } + } + pos_e = p; + end_of_token = *p; + *p = 0; +/* fprintf(stdout, "returning key token |%s|\n", pos); */ + return pos; + } + + error_msg("illegal token |%s|", pos); +} + +static void *xmalloc(size_t n) +{ + void *p; + + if (!(p = malloc(n))) { + error_msg("OUT OF MEMORY"); + } + return p; +} + +static void do_copy(void) +{ + char *s; + char *e; + + if ((s = next_token()) != NULL) { + e = strchr(s + 1, '"'); + if ((*s == '"') && e && (*e == '"') && !e[1]) { + if (next_token() != NULL) { + error_msg("illegal trailing text: %s", pos); + } + *e = 0; + ++s; + if (cur_base && !strcmp(cur_base->name,s)) { +/* verbose_msg(VDETAIL, "skipping copy of base file %s\n", s); */ +#warning need to update last in order and position or check + return; + } +/* verbose_msg(VDETAIL, "full copy of %s\n", s); */ + pushfile(s); + return; + } + } + error_msg("illegal or missing arg for copy: %s", s); +} + +static void do_colsym(void) +{ + char *s; + char *e; + + if ((s = next_token()) != NULL) { + e = strrchr(s,'>'); + if ((*s == '<') && e && (*e == '>') && !e[1]) { + if (next_token() != NULL) { + error_msg("illegal trailing text: %s", pos); + } + e[1] = 0; /* cleanup in case next_token stored something */ + add_colitem(s,NULL); + return; + } + } + error_msg("illegal or missing arg for collating-symbol: %s", s); +} + +static void do_colele(void) +{ + char *s; + char *e; + char *s1; + char *e1; + int n; + + if ((s = next_token()) != NULL) { + e = strrchr(s,'>'); + if ((*s == '<') && e && (*e == '>') && !e[1]) { + if (((s1 = next_token()) == NULL) + || (strcmp(s1,"from") != 0) + || ((s1 = next_token()) == NULL) + || (*s1 != '\"') + ) { + error_msg("illegal format for collating-element spec"); + } + e1 = strchr(s1 + 1, '"'); + if ((*s1 != '"') || !e1 || (*e1 != '"') || (e1[1] != 0)) { + error_msg("illegal definition for collating-element: %s", s1); + } + if (next_token() != NULL) { + error_msg("illegal trailing text: %s", pos); + } + e[1] = 0; /* cleanup in case next_token stored something */ + e1[1] = 0; + add_colitem(s,s1); + ++s1; + if (!(n = is_ucode(s1))) { + error_msg("starting char must be a code: %s", s1); + } + assert(s1[n] == '<'); + s1[n] = 0; + s = xsymdup(s1); + if (!(tsearch(s, &cur_base->root_starter_char, sym_cmp))) { + error_msg("OUT OF MEMORY"); + } + + return; + } + } + error_msg("illegal or missing arg for collating-element: %s", s); +} + +static ll_item_t *find_section_list_item(const char *name, col_locale_t *loc) +{ + ll_item_t *p; + + if (!loc) { + return NULL; + } + + p = loc->section_list; + + while (p) { +#warning devel code +/* if (!((p->data_type == DT_SECTION) || (p->data_type == DT_REORDER))) { */ +/* verbose_msg(VDETAIL, "fsli = %d\n", p->data_type); */ +/* } */ + assert((p->data_type == DT_SECTION) || (p->data_type == DT_REORDER)); + if (!strcmp(name, ((section_t *)(p->data))->name)) { + break; + } + p = p->next; + } + return p; +} + +static ll_item_t *find_ll_last(ll_item_t *p) +{ + assert(p); + + while (p->next) { + p = p->next; + } + return p; +} + +static void do_script(void) +{ + char *s; + char *e; + + if ((s = next_token()) != NULL) { + e = strrchr(s,'>'); + if ((*s == '<') && e && (*e == '>') && !e[1]) { + if (next_token() != NULL) { + error_msg("illegal trailing text: %s", pos); + } + e[1] = 0; /* cleanup in case next_token stored something */ + add_script(s); + return; + } + } + error_msg("illegal or missing arg for script: %s", s); +} + +static col_locale_t *new_col_locale(char *name) +{ + ll_item_t *lli; + ll_item_t *lli2; + + cur_col = (col_locale_t *) xmalloc(sizeof(col_locale_t)); + cur_col->name = name; + cur_col->root_colitem = NULL; + cur_col->root_element = NULL; + cur_col->root_scripts = NULL; + cur_col->base_locale = NULL; + if (!superset) { + /* start with an anonymous section */ + cur_section = new_section(NULL); + cur_col->section_list = new_ll_item(DT_SECTION, cur_section); + } else { + /* start with a reorder section */ + cur_section = new_section("R"); + cur_num_weights = cur_section->num_rules + = ((section_t *)(cur_base->section_list->data))->num_rules; + memcpy(cur_rule, + ((section_t *)(cur_base->section_list->data))->rules, + MAX_COLLATION_WEIGHTS); + memcpy(cur_section->rules, + ((section_t *)(cur_base->section_list->data))->rules, + MAX_COLLATION_WEIGHTS); + cur_col->section_list = new_ll_item(DT_REORDER, cur_section); + assert(cur_base->section_list->next == NULL); /* currently only one section allowed */ + lli = ((section_t *)(cur_base->section_list->data))->itm_list; + assert(lli); + lli2 = new_ll_item(DT_REORDER, cur_section); + lli2->prev = lli2->next = lli2; + insque(lli2, lli->prev); + ((section_t *)(cur_base->section_list->data))->itm_list = lli2; + } +/* cur_col->section_list = NULL; */ +/* add_script(((section_t *)(cur_col->section_list->data))->name); */ + cur_col->root_wi_index = NULL; + cur_col->root_wi_index_reordered = NULL; + cur_col->root_derived_wi = NULL; + cur_col->derived_list = NULL; + cur_col->root_starter_char = NULL; + cur_col->root_starter_all = NULL; + cur_col->undefined_idx = NULL; + return cur_col; +} + +static int colitem_cmp(const void *n1, const void *n2) +{ + return strcmp(((colitem_t *)n1)->string, ((colitem_t *)n2)->string); +} + +static int colelement_cmp(const void *n1, const void *n2) +{ + int r; + + r = strcmp(((colitem_t *)n1)->string, ((colitem_t *)n2)->string); + if (!r) { + if (((colitem_t *)n1)->element && ((colitem_t *)n2)->element) { + r = strcmp(((colitem_t *)n1)->element, ((colitem_t *)n2)->element); + } else if (((colitem_t *)n1)->element == ((colitem_t *)n2)->element) { + r = 0; /* both null */ + } else { + r = (((colitem_t *)n1)->element == NULL) ? -1 : 1; + } + } + return r; +} + +static void del_colitem(colitem_t *p) +{ +/* free((void *) p->element); */ +/* free((void *) p->string); */ + free(p); +} + +static colitem_t *new_colitem(char *item, char *def) +{ + colitem_t *p; + + p = xmalloc(sizeof(colitem_t)); + p->string = xsymdup(item); + p->element = (!def) ? def : xsymdup(def); + + return p; +} + +static void add_colitem(char *item, char *def) +{ + colitem_t *p; + +#if 0 + printf("adding collation item %s", item); + if (def) { + printf(" with definition %s", def); + } + printf("\n"); +#endif + + p = new_colitem(item, def); + +#warning devel code + if (superset) { + if (tfind(p, &cur_base->root_colitem, colitem_cmp)) { +/* verbose_msg(VDETAIL, "skipping superset duplicate collating item \"%s\"\n", p->string); */ + del_colitem(p); + return; +/* } else { */ +/* verbose_msg(VDETAIL, "superset: new collating item \"%s\" = %s\n", p->string, p->element); */ + } + } + + if (cur_col == cur_derived) { + if (!tfind(p, &cur_base->root_colitem, colitem_cmp)) { + /* not in current but could be in base */ + if (!tsearch(p, &cur_base->root_colitem, colitem_cmp)) { + error_msg("OUT OF MEMORY!"); + } + } else if (!tfind(p, &cur_base->root_colitem, colelement_cmp)) { + error_msg("collating element/symbol mismatch: item=%s def=%s", item, def); + } + } + + + if (!tfind(p, &cur_col->root_colitem, colitem_cmp)) { + /* not in current but could be in base */ + if (!tsearch(p, &cur_col->root_colitem, colitem_cmp)) { + error_msg("OUT OF MEMORY!"); + } + } else if (!tfind(p, &cur_col->root_colitem, colelement_cmp)) { + error_msg("collating element/symbol mismatch"); + } else { /* already there */ + fprintf(stderr, "duplicate collating item \"%s\"\n", p->string); + del_colitem(p); + } +} + +/* add a script (section) to the current locale */ +static void add_script(const char *s) +{ + ll_item_t *l; + + /* make sure it isn't in base if working with derived */ + if (cur_base != cur_col) { + if (find_section_list_item(s, cur_base)) { + error_msg("attempt to add script %s for derived when already in base", s); + } + } + + if (find_section_list_item(s, cur_col)) { + error_msg("attempt to readd script %s", s); + } + + l = find_ll_last(cur_col->section_list); + insque(new_ll_item(DT_SECTION, new_section(s)), l); +} + +static const char str_forward[] = "forward"; +static const char str_backward[] = "backward"; +static const char str_position[] = "position"; + +static void do_order_start(void) +{ + const char *s; + char *e; + ll_item_t *l; + section_t *sect; + int rule; + + if (order_state & ~IN_ORDER) { + error_msg("order_start following reorder{_sections}_after"); + } + order_state |= IN_ORDER; + + if (superset) { + if (++superset_order_start_cnt > 1) { + error_msg("currently only a common order_start is supported in superset"); + } + return; + } + + if (!(s = next_token())) { + s = str_forward; /* if no args */ + } + + if (*s == '<') { /* section (script) */ + e = strrchr(s,'>'); + if ((*s == '<') && e && (*e == '>') && !e[1]) { + e[1] = 0; /* cleanup in case next_token stored something */ + + if (!(l = find_section_list_item(s, cur_col))) { + error_msg("ref of undefined sections: %s", s); + } + sect = (section_t *)(l->data); + if (sect->num_rules) { + error_msg("sections already defined: %s", s); + } + } else { + error_msg("illegal section ref: %s", s); + } + + if (!(s = next_token())) { + s = str_forward; /* if no args */ + } else if (*s != ';') { + error_msg("missing seperator!"); + } + } else { /* need an anonymous section */ + if ((*cur_section->name != '<') && (cur_section->num_items == 0)) { /* already in an empty anonymous section */ + sect = cur_section; +/* fprintf(stdout, "using empty anon section %s\n", sect->name); */ + } else { + sect = new_section(NULL); + l = find_ll_last(cur_col->section_list); + insque(new_ll_item(DT_SECTION, sect), l); +/* fprintf(stdout, "adding order section after section %s\n", ((section_t *)(l->data))->name); */ +/* fprintf(stdout, " last section is %s\n", ((section_t *)(l->next->data))->name); */ + } + sect->num_rules = 0; /* setting this below so nix default */ + } + cur_section = sect; +/* fprintf(stdout, "cur_section now %s\n", cur_section->name); */ + +#warning need to add section to weight list? + + /* now do rules */ + do { + rule = 0; + if (*s == ';') { + ++s; + } + while (*s) { + if (!strncmp(str_forward, s, 7)) { + rule |= R_FORWARD; + s += 7; + } else if (!strncmp(str_backward, s, 8)) { + rule |= R_BACKWARD; + s += 8; + } else if (!strncmp(str_position, s, 8)) { + rule |= R_POSITION; + s += 8; + } + + if (*s == ',') { + ++s; + continue; + } + + if (!*s || (*s == ';')) { + if (sect->num_rules >= MAX_COLLATION_WEIGHTS) { + error_msg("more than %d weight rules!", MAX_COLLATION_WEIGHTS); + } + if (!rule) { + error_msg("missing weight rule!"); + } + if ((rule & (R_FORWARD|R_BACKWARD|R_POSITION)) > R_BACKWARD) { + error_msg("backward paired with forward and/or position!"); + } + + sect->rules[sect->num_rules++] = rule; + rule = 0; + continue; + } + + error_msg("illegal weight rule: %s", s); + } + } while ((s = next_token()) != NULL); + + cur_section = sect; + +/* verbose_msg(VDETAIL, "setting cur_num_weights to %d for %s\n", sect->num_rules, sect->name); */ + cur_num_weights = sect->num_rules; + memcpy(cur_rule, sect->rules, MAX_COLLATION_WEIGHTS); +} + +static void do_order_end(void) +{ + if (!(order_state & IN_ORDER)) { + error_msg("order_end with no matching order_start"); + } + order_state &= ~IN_ORDER; + + cur_section = new_section(NULL); +} + +static void do_reorder_after(void) +{ + char *t; + ll_item_t *lli; + const weight_t *w; + int save_cur_num_weights; + char save_cur_rule[MAX_COLLATION_WEIGHTS]; + + + if (order_state & ~IN_REORDER) { + error_msg("reorder_after following order_start or reorder_sections_after"); + } + order_state |= IN_REORDER; + + if (superset) { + error_msg("currently reorder_after is not supported in supersets"); + } + +#warning have to use rule for current section!!! + + if (!(t = next_token())) { + error_msg("missing arg for reorder_after"); + } + + t = xsymdup(t); + + if (next_token() != NULL) { + error_msg("trailing text reorder_after: %s", pos); + } + + if (cur_col == cur_base) { + error_msg("sorry.. reorder_after in base locale is not currently supported"); + } + + if (!(lli = find_wi_index(t, cur_base))) { + error_msg("reorder_after for non-base item currently not supported: %s", t); + } + + w = ((weighted_item_t *)(lli->data))->weight; + + + save_cur_num_weights = cur_num_weights; + memcpy(save_cur_rule, cur_rule, MAX_COLLATION_WEIGHTS); + + cur_section = new_section("R"); + insque(new_ll_item(DT_REORDER, cur_section), lli); + +#if 0 + + { + ll_item_t *l1; + ll_item_t *l2; + ll_item_t *l3; + l1 = new_ll_item(DT_REORDER, cur_section); + l2 = find_ll_last(cur_col->section_list); + insque(l1, l2); + l3 = find_ll_last(cur_col->section_list); + + verbose_msg(VDETAIL, "reorder_after %p %p %p %s\n", l1, l2, l3, cur_section->name); + } +#else + insque(new_ll_item(DT_REORDER, cur_section), find_ll_last(cur_col->section_list)); +#endif + + cur_num_weights = cur_section->num_rules = save_cur_num_weights; + memcpy(cur_rule, save_cur_rule, MAX_COLLATION_WEIGHTS); + memcpy(cur_section->rules, save_cur_rule, MAX_COLLATION_WEIGHTS); + + +#warning devel code +/* verbose_msg(VDETAIL, "reorder -- %s %d\n", ((weighted_item_t *)(lli->data))->symbol, w->num_weights); */ + +#warning hack to get around hu_HU reorder-after problem +/* if (!w->num_weights) { */ + +/* } else { */ +/* cur_num_weights = w->num_weights; */ +/* memcpy(cur_rule, w->rule, MAX_COLLATION_WEIGHTS); */ +/* } */ + +/* verbose_msg(VDETAIL, "reorder_after succeeded for %s\n", t); */ +} + +static void do_reorder_end(void) +{ + if (!(order_state & IN_REORDER)) { + error_msg("reorder_end with no matching reorder_after"); + } + order_state &= ~IN_REORDER; +} + +static void do_reorder_sections_after(void) +{ + const char *t; + ll_item_t *lli; + + if (order_state & ~IN_REORDER_SECTIONS) { + error_msg("reorder_sections_after following order_start or reorder_after"); + } + order_state |= IN_REORDER_SECTIONS; + + if (superset) { + error_msg("currently reorder_sections_after is not supported in supersets"); + } + + if (!(t = next_token())) { + error_msg("missing arg for reorder_sections_after"); + } + + t = xsymdup(t); + + if (next_token() != NULL) { + error_msg("trailing text reorder_sections_after: %s", pos); + } + + if (cur_col == cur_base) { + error_msg("sorry.. reorder_sections_after in base locale is not currently supported"); + } + + lli = cur_base->section_list; + do { +/* verbose_msg(VDETAIL, "hmm -- |%s|%d|\n", ((section_t *)(lli->data))->name, lli->data_type); */ + if (lli->data_type & DT_SECTION) { +/* verbose_msg(VDETAIL, "checking |%s|%s|\n", ((section_t *)(lli->data))->name, t); */ + if (!strcmp(((section_t *)(lli->data))->name, t)) { + reorder_section_ptr = lli; + return; + } + } + lli = lli->next; + } while (lli); + + error_msg("reorder_sections_after for non-base item currently not supported: %s", t); +} + +static void do_reorder_sections_end(void) +{ + if (!(order_state & IN_REORDER_SECTIONS)) { + error_msg("reorder_sections_end with no matching reorder_sections_after"); + } + order_state &= ~IN_REORDER_SECTIONS; + + reorder_section_ptr = NULL; +} + +static ll_item_t *new_ll_item(int data_type, void *data) +{ + ll_item_t *p; + + p = xmalloc(sizeof(ll_item_t)); + p->next = p->prev = NULL; + p->data_type = data_type; + p->data = data; + p->idx = INT_MIN; + + return p; +} + +static int sym_cmp(const void *n1, const void *n2) +{ +/* verbose_msg(VDETAIL, "sym_cmp: |%s| |%s|\n", (const char *)n1, (const char *)n2); */ + return strcmp((const char *) n1, (const char *) n2); +} + +static char *xsymdup(const char *s) +{ + void *p; + + if (!(p = tfind(s, &root_sym, sym_cmp))) { /* not a currently known symbol */ + if (!(s = strdup(s)) || !(p = tsearch(s, &root_sym, sym_cmp))) { + error_msg("OUT OF MEMORY!"); + } + ++num_sym; + mem_sym += strlen(s) + 1; +/* verbose_msg(VDETAIL, "xsymdup: alloc |%s| %p |%s| %p\n", *(char **)p, p, s, s); */ +/* } else { */ +/* verbose_msg(VDETAIL, "xsymdup: found |%s| %p\n", *(char **)p, p); */ + } + return *(char **) p; +} + +static int weight_cmp(const void *n1, const void *n2) +{ + const weight_t *w1 = (const weight_t *) n1; + const weight_t *w2 = (const weight_t *) n2; + int i, r; + + if (w1->num_weights != w2->num_weights) { + return w1->num_weights - w2->num_weights; + } + + for (i=0 ; i < w1->num_weights ; i++) { + if (w1->rule[i] != w2->rule[i]) { + return w1->rule[i] - w2->rule[i]; + } + if ((r = strcmp(w1->colitem[i], w2->colitem[i])) != 0) { + return r; + } + } + return 0; +} + +static weight_t *register_weight(weight_t *w) +{ + void *p; + + if (!(p = tfind(w, &root_weight, weight_cmp))) { /* new weight */ + p = xmalloc(sizeof(weight_t)); + memcpy(p, w, sizeof(weight_t)); + if (!(p = tsearch(p, &root_weight, weight_cmp))) { + error_msg("OUT OF MEMORY!"); + } + ++unique_weights; +/* } else { */ +/* verbose_msg(VDETAIL, "rw: found\n"); */ + } + return *(weight_t **)p; +} + +static size_t ll_len(ll_item_t *l) +{ + size_t n = 0; + ll_item_t *p = l; + + while (p) { + ++n; + p = p->next; + if (p == l) { /* work for circular too */ + break; + } + } + return n; +} + +static size_t ll_count(ll_item_t *l, int mask) +{ + size_t n = 0; + ll_item_t *p = l; + + while (p) { + if (p->data_type & mask) { + ++n; + } + p = p->next; + if (p == l) { /* work for circular too */ + break; + } + } + return n; +} + + +static int wi_index_cmp(const void *n1, const void *n2) +{ + const char *s1 = ((weighted_item_t *)(((ll_item_t *) n1)->data))->symbol; + const char *s2 = ((weighted_item_t *)(((ll_item_t *) n2)->data))->symbol; + + return strcmp(s1, s2); +} + +static void add_wi_index(ll_item_t *l) +{ + assert(l->data_type == DT_WEIGHTED); + + if (!strcmp(((weighted_item_t *)(l->data))->symbol, "UNDEFINED")) { + cur_col->undefined_idx = l; + } + + if (!tfind(l, &cur_col->root_wi_index, wi_index_cmp)) { /* new wi_index */ + if (!tsearch(l, &cur_col->root_wi_index, wi_index_cmp)) { + error_msg("OUT OF MEMORY!"); + } + } + + if (cur_base != cur_col) { + if (!tfind(l, &cur_base->root_wi_index, wi_index_cmp)) {/* not a base val */ +/* printf("derived: %s\n", ((weighted_item_t *)(l->data))->symbol); */ + if (!tfind(l, &cur_base->root_derived_wi, wi_index_cmp)) { /* new derived */ + if (!tsearch(l, &cur_base->root_derived_wi, wi_index_cmp)) { + error_msg("OUT OF MEMORY!"); + } + } + } + } +} + +static int final_index; + + +static int is_ucode(const char *s) +{ + if ((s[0] == '<') + && (s[1] == 'U') + && isxdigit(s[2]) + && isxdigit(s[3]) + && isxdigit(s[4]) + && isxdigit(s[5]) + && (s[6] == '>') + ) { + return 7; + } else { + return 0; + } +} + +static void add_final_col_index(const char *s) +{ + ENTRY e; + + e.key = (char *) s; + e.data = (void *)(final_index); + if (!hsearch(e, FIND)) { /* not in the table */ + if (!hsearch(e, ENTER)) { + error_msg("OUT OF MEMORY! (hsearch)"); + } +#if 0 + { + int n; + void *v; + colitem_t ci; + colitem_t *p; + const char *t; + + if (!strcmp(s, "UNDEFINED")) { + printf("%6d: %s\n", final_index, s); + } else { + assert(*s == '<'); + if ((n = is_ucode(s)) != 0) { + assert(!s[n]); + printf("%6d: %s\n", final_index, s); + } else { + ci.string = (char *) s; + ci.element = NULL; /* don't care */ + v = tfind(&ci, &cur_base->root_colitem, colitem_cmp); + if (!v) { + verbose_msg(VDETAIL, "%s NOT DEFINED!!!\n", s); + } else { + p = *((colitem_t **) v); + if (p->element != NULL) { + t = p->element; + assert(*t == '"'); + ++t; + n = is_ucode(t); + assert(n); + printf("%6d: %.*s | ", final_index, n, t); + do { + t += n; + assert(*t); + if (*t == '"') { + assert(!t[1]); + break; + } + n = is_ucode(t); + assert(n); + printf("%.*s", n, t); + } while (1); + printf(" collating-element %s\n", s); + } else { + printf("%6d: %s (collating-symbol)\n", final_index, s); + } + } + } + } + } +#endif + ++final_index; + } + +} + +static int final_index_val0(const char *s) +{ + ENTRY *p; + ENTRY e; + e.key = (char *) s; + + if (!(p = hsearch(e, FIND))) { /* not in the table */ + return 0; + } + + return (int)(p->data); +} + +static int final_index_val(const char *s) +{ + ENTRY *p; + ENTRY e; + e.key = (char *) s; + + if (!(p = hsearch(e, FIND))) { /* not in the table */ + error_msg("can't find final index: %s", s); + } + + return (int)(p->data); +} + +static size_t num_tree_nodes; + +static void count_nodes(const void *ptr, VISIT order, int level) +{ + if ((order == postorder) || (order == leaf)) { + ++num_tree_nodes; + } +} + +static size_t tnumnodes(const void *root) +{ + num_tree_nodes = 0; + + twalk(root, count_nodes); + + return num_tree_nodes; + +} + +static ll_item_t *find_wi_index(const char *sym, col_locale_t *cl) +{ + weighted_item_t w; + ll_item_t l; + void *p; + + w.symbol = sym; + l.data = &w; + l.data_type = DT_WEIGHTED; + + p = tfind(&l, &cl->root_wi_index, wi_index_cmp); + + if (p) { + p = *(ll_item_t **)p; + } + + return (ll_item_t *) p; +} + +static void mark_reordered(const char *sym) +{ + ll_item_t *lli; + + lli = find_wi_index(sym, cur_base); + + if (lli) { + if (!tsearch(lli, &cur_base->root_wi_index_reordered, wi_index_cmp)) { + error_msg("OUT OF MEMORY!"); + } + } +} + +static ll_item_t *find_wi_index_reordered(const char *sym) +{ + weighted_item_t w; + ll_item_t l; + void *p; + + w.symbol = sym; + l.data = &w; + l.data_type = DT_WEIGHTED; + + p = tfind(&l, &cur_base->root_wi_index_reordered, wi_index_cmp); + + if (p) { + p = *(ll_item_t **)p; + } + + return (ll_item_t *) p; +} + +static ll_item_t *init_comm_ptr(void) +{ + assert(cur_base); + assert(cur_base->section_list); + /* at the moment, only support one section in comm */ + assert(cur_base->section_list->next == NULL); + + comm_cur_ptr = ((section_t *)(cur_base->section_list->data))->itm_list; + + while (comm_cur_ptr && (comm_cur_ptr->data_type & DT_REORDER)) { + comm_cur_ptr = comm_cur_ptr->next; + } + +#warning devel code +/* { */ +/* ll_item_t *p = comm_cur_ptr; */ +/* verbose_msg(VDETAIL, "init_comm_ptr\n"); */ + +/* while (p != comm_cur_ptr) { */ +/* if (p->data_type & DT_WEIGHTED) { */ +/* verbose_msg(VDETAIL, "%s", ((weighted_item_t *)p)->symbol); */ +/* } */ +/* p = p->next; */ +/* } */ +/* } */ + + assert(comm_cur_ptr); + +/* verbose_msg(VDETAIL, "init_comm_ptr -- %s %p %p %p %d\n", */ +/* ((weighted_item_t *)(comm_cur_ptr->data))->symbol, */ +/* comm_cur_ptr, comm_cur_ptr->prev, comm_cur_ptr->next, */ +/* ll_len(comm_cur_ptr)); */ + + comm_prev_ptr = NULL; + return comm_cur_ptr; +} + +static ll_item_t *next_comm_ptr(void) +{ + /* at the moment, only support one section in comm */ + assert(cur_base->section_list->next == NULL); + + comm_prev_ptr = comm_cur_ptr; + + while (comm_cur_ptr && ((comm_cur_ptr = comm_cur_ptr->next) != NULL)) { + if (!(comm_cur_ptr->data_type & DT_REORDER)) { + break; + } + } + + return comm_cur_ptr; +} + +static int dump_count; + +#if 0 +static void dump_section(section_t *s, int mask, col_locale_t *der) +{ + ll_item_t *lli; + ll_item_t *lli0; + weighted_item_t *w; + weight_t *p; + int i; + + lli0 = lli = s->itm_list; + + if (!lli0) { + return; + } + + do { + if (!(lli->data_type & mask)) { + lli = lli->next; + continue; + } + if (lli->data_type & DT_WEIGHTED) { + ++dump_count; + w = (weighted_item_t *)(lli->data); + p = w->weight; + printf("%6d: %s (%d) ", dump_count, w->symbol, p->num_weights); + for (i = 0 ; i < p->num_weights ; i++) { + if (p->rule[i] & R_FORWARD) { + printf("F"); + } + if (p->rule[i] & R_BACKWARD) { + printf("B"); + } + if (p->rule[i] & R_POSITION) { + printf("P"); + } + printf(","); + } + for (i = 0 ; i < p->num_weights ; i++) { + printf(" %s", p->colitem[i]); + } + printf("\n"); + } else if (lli->data_type & (DT_SECTION|DT_REORDER)) { + + if (lli->data_type == DT_REORDER) { + assert(der); + if (strncmp(((section_t *)(lli->data))->name, der->name, strlen(der->name))) { + lli = lli->next; + continue; + } + } + + if (lli->data_type & DT_SECTION) { + printf("SECTION -----------------\n"); + } else { + printf("REORDER -----------------\n"); + } + + dump_section((section_t *)(lli->data), mask, der); + printf("DONE --------------------\n"); + } + lli = lli->next; + } while (lli != lli0); +} +#else +static int in_reorder_section = 0; + +static void dump_section(section_t *s, int mask, col_locale_t *der) +{ + ll_item_t *lli; + ll_item_t *lli0; + weighted_item_t *w; + weight_t *p; + int i; + + lli0 = lli = s->itm_list; + + if (!lli0) { + return; + } + + do { + if (!(lli->data_type & mask)) { + lli = lli->next; + continue; + } + if (lli->data_type & DT_WEIGHTED) { + ++dump_count; + w = (weighted_item_t *)(lli->data); + p = w->weight; +#if 1 + if (in_reorder_section) { + printf(" %p", w); + } +#else + printf("%6d: %s (%d) ", dump_count, w->symbol, p->num_weights); + for (i = 0 ; i < p->num_weights ; i++) { + if (p->rule[i] & R_FORWARD) { + printf("F"); + } + if (p->rule[i] & R_BACKWARD) { + printf("B"); + } + if (p->rule[i] & R_POSITION) { + printf("P"); + } + printf(","); + } + for (i = 0 ; i < p->num_weights ; i++) { + printf(" %s", p->colitem[i]); + } + printf("\n"); +#endif + } else if (lli->data_type & (DT_SECTION|DT_REORDER)) { + + if (lli->data_type == DT_REORDER) { + assert(der); + if (strncmp(((section_t *)(lli->data))->name, der->name, strlen(der->name))) { + lli = lli->next; + continue; + } + } + + if (lli->data_type & DT_SECTION) { +/* printf("SECTION -----------------\n"); */ + assert(0); + } else { +/* printf("REORDER -----------------\n"); */ + in_reorder_section = 1; + } + + dump_section((section_t *)(lli->data), mask, der); +/* printf("DONE --------------------\n"); */ + printf("\n"); + in_reorder_section = 0; + } + lli = lli->next; + } while (lli != lli0); +} +#endif + +static void dump_weights(const char *name) +{ + ll_item_t *lli; + col_locale_t *base; + col_locale_t *der; + col_locale_t cl; + void *p; + + assert(name); + + if (!*name) { /* use last */ + base = cur_base; + der = cur_derived; + } else { + cl.name = (char *) name; + if (!(p = tfind(&cl, &root_col_locale, col_locale_cmp))) { + error_msg("unknown locale: %s", name); + } + base = *((col_locale_t **) p); + der = NULL; + if (base->base_locale) { /* oops... really derived */ + der = base; + base = der->base_locale; + } + } + + dump_count = 0; + + if (base) { +/* printf("BASE - %s\n", base->name); */ + for (lli = base->section_list ; lli ; lli = lli->next) { +/* printf("SECTION %s\n", ((section_t *)(lli->data))->name); */ + dump_section((section_t *)(lli->data), ~0, der); + } + } + + assert(der != base); + + if (der) { +/* printf("DERIVED - %s\n", der->name); */ + for (lli = der->section_list ; lli ; lli = lli->next) { + if (lli->data_type == DT_SECTION) { + dump_section((section_t *)(lli->data), DT_WEIGHTED, der); + } + } + } +/* printf("DONE\n"); */ +} + +static void print_starter_node(const void *ptr, VISIT order, int level) +{ + if (order == postorder || order == leaf) { + fprintf(stderr, " %s\n", *(const char **) ptr); + } +} + +static void finalize_base(void) +{ + ll_item_t *s; + ll_item_t *h; + ll_item_t *lli; + ll_item_t *h2; + ll_item_t *l2; + ll_item_t *cli; + ll_item_t *rli = NULL; + weighted_item_t *w; + weight_t *p; + int i, n, mr, r, mi; + col_locale_t *cl; + void *mm; + + int num_invariant = 0; + int num_varying = 0; + int max_weight; + int index2weight_len_inc = 1; + + assert(cur_base); + assert(base_locale_len+1 < BASE_LOCALE_LEN); + + base_locale_array[base_locale_len].name = cur_base->name; + base_locale_array[base_locale_len].num_weights = 1; + base_locale_array[base_locale_len].index2weight_offset = index2weight_len; + base_locale_array[base_locale_len].index2ruleidx_offset = index2ruleidx_len; + if (!strcmp(cur_base->name,"ja_JP") || !strcmp(cur_base->name,"ko_KR")) { +#warning fix the index2weight check!! + index2weight_len_inc = 0; + } +/* printf("%s -- index2weight_len = %d\n", cur_base->name, index2weight_len); */ + + if (!hcreate(30000)) { + error_msg("OUT OF MEMORY!"); + } + + /* first pass ... set the fixed indexes */ + final_index = i = 1; + mr = 0; + for (s = cur_base->section_list ; s ; s = s->next) { +#if 1 + if (s->data_type & DT_REORDER) { /* a reordered section */ + verbose_msg(VDETAIL, "pass1: reordered section %s - xxx\n", ((section_t *)(s->data))->name); + lli = ((section_t *)(s->data))->itm_list; + r = 0; + if (lli) { +/* r = ll_len( ((section_t *)(lli->data))->itm_list ); */ + r = ll_len(lli) + 1; + } + if (r > mr) { + mr = r; + } + verbose_msg(VDETAIL, "pass1: reordered section %s - %d\n", ((section_t *)(s->data))->name, r); + continue; + } +#endif + h = lli = ((section_t *)(s->data))->itm_list; + if (!lli) { + continue; + } + do { + if (lli->data_type & DT_RANGE) { + i += mr; + mr = 0; +#warning check ko_kR and 9 +/* ++i; */ + lli->idx = i; + assert(!rli); + rli = lli; + verbose_msg(VDETAIL, "range pre = %d after = ", i); + i += ((range_item_t *)(lli->data))->length + 1; +#warning check ko_kR and 9 +/* ++i; */ + verbose_msg(VDETAIL, "%d\n", i); + if (!index2weight_len_inc) { /* ko_KR hack */ + final_index += ((range_item_t *)(lli->data))->length + 1; + } +/* add_final_col_index("RANGE"); */ + } else if (lli->data_type & DT_WEIGHTED) { + i += mr; + mr = 0; + w = (weighted_item_t *)(lli->data); + if (find_wi_index_reordered(w->symbol)) { /* reordered symbol so skip on first pass */ + ++num_varying; + ++i; + continue; + } + ++num_invariant; + index2weight_buffer[index2weight_len] = lli->idx = i++; + index2weight_len += index2weight_len_inc; + add_final_col_index(w->symbol); + + } else { + assert(lli->data_type & DT_REORDER); + r = ll_len( ((section_t *)(lli->data))->itm_list ); +#warning check ko_kR and 9 + if (r > mr) { + mr = r; + } +/* r = 0; */ + } + } while ((lli = lli->next) != h); + } + + /* second pass ... set the reordered indexes */ + mi = i + mr; + mr = i = 0; + for (s = cur_base->section_list ; s ; s = s->next) { + h = lli = ((section_t *)(s->data))->itm_list; + if (!lli) { + continue; + } + do { + if (lli->data_type & DT_RANGE) { + i += mr; + mr = 0; + i = lli->idx + ((range_item_t *)(lli->data))->length + 1; +#warning check + } else if ((lli->data_type & DT_WEIGHTED) && !(s->data_type & DT_REORDER)) { + i += mr; + mr = 0; + w = (weighted_item_t *)(lli->data); + if (find_wi_index_reordered(w->symbol) /* reordered symbol skipped on first pass */ +#if 0 + || (s->data_type & DT_REORDER) /* or in a reordered section */ +#endif + ) { + assert(!(s->data_type & DT_REORDER)); + index2weight_buffer[index2weight_len] = lli->idx = ++i; + index2weight_len += index2weight_len_inc; + add_final_col_index(w->symbol); + +/* fprintf(stdout, "%11s: r %6d %6d %s\n", */ +/* cur_base->name, lli->idx, final_index_val(w->symbol), w->symbol); */ + + continue; + } + i = lli->idx; + +/* fprintf(stdout, "%11s: w %6d %6d %s\n", */ +/* cur_base->name, lli->idx, final_index_val(w->symbol), w->symbol); */ + + } else { +/* verbose_msg(VDETAIL, "section: %s %d %d\n", ((section_t *)(s->data))->name, */ +/* s->data_type, lli->data_type); */ +/* assert(!(s->data_type & DT_REORDER)); */ +/* assert(lli->data_type & DT_REORDER); */ +#if 1 + if (s->data_type & DT_REORDER) { + h2 = l2 = lli; + if (!h2) { + continue; + } + } else { + assert(s->data_type & DT_SECTION); + h2 = l2 = ((section_t *)(lli->data))->itm_list; + if (!h2) { + continue; + } + } + + +#else + h2 = l2 = ((section_t *)(lli->data))->itm_list; + if (!h2) { + continue; + } +#endif + r = 0; + do { + assert(l2->data_type & DT_WEIGHTED); + ++r; + l2->idx = i + r; + +/* fprintf(stdout, "%s: R %6d %s\n", */ +/* ((section_t *)(lli->data))->name, l2->idx, ((weighted_item_t *)(l2->data))->symbol); */ + + } while ((l2 = l2->next) != h2); + if (r > mr) { + mr = r; + } + } + } while ((lli = lli->next) != h); + } + + /* finally, walk through all derived locales and set non-reordered section items */ + mr = mi; + for (cli = cur_base->derived_list ; cli ; cli = cli->next) { + cl = (col_locale_t *)(cli->data); +/* verbose_msg(VDETAIL, "pass3: %d %s\n", cli->data_type, cl->name); */ + +/* fprintf(stdout, "pass3: %d %s\n", cli->data_type, cl->name); */ + + assert(cli->data_type == DT_COL_LOCALE); + + i = mi; + for (s = cl->section_list ; s ; s = s->next) { +/* if (s->data_type & DT_REORDER) { */ +/* continue; */ +/* } */ + h = lli = ((section_t *)(s->data))->itm_list; + if (!lli) { + continue; + } + do { + assert(!(lli->data_type & DT_RANGE)); + if (lli->data_type & DT_WEIGHTED) { +/* verbose_msg(VDETAIL, " %d %d %s\n", lli->data_type, lli->idx, ((weighted_item_t *)(lli->data))->symbol); */ + add_final_col_index(((weighted_item_t *)(lli->data))->symbol); + if (s->data_type & DT_REORDER) { + continue; + } + assert(lli->idx == INT_MIN); + lli->idx = ++i; + +/* fprintf(stdout, "%11s: S %6d %6d %s\n", */ +/* cl->name, lli->idx, */ +/* final_index_val(((weighted_item_t *)(lli->data))->symbol), */ +/* ((weighted_item_t *)(lli->data))->symbol); */ + + } else { + assert(0); + assert(lli->data_type & DT_SECTION); + + h2 = l2 = ((section_t *)(lli->data))->itm_list; + if (!h2) { + continue; + } + do { + assert(l2->data_type & DT_WEIGHTED); + assert(l2->idx == INT_MIN); + l2->idx = ++i; + add_final_col_index(((weighted_item_t *)(l2->data))->symbol); + } while ((l2 = l2->next) != h2); + } + } while ((lli = lli->next) != h); + } + if (i > mr) { + mr = i; + } + } + max_weight = mr; + + assert(num_varying == tnumnodes(cur_base->root_wi_index_reordered)); + + /* we can now initialize the wcs2index array */ + { + ENTRY *p; + ENTRY e; + char buf[8]; + static const char xd[] = "0123456789ABCDEF"; + int starter_index = final_index; + int wcs2index_count = 0; + + strcpy(buf, ""); + memset(wcs2index, 0, sizeof(wcs2index)); + e.key = (char *) buf; + for (i=1 ; i <= 0xffff ; i++) { + buf[5] = xd[ i & 0xf ]; + buf[4] = xd[ (i >> 4) & 0xf ]; + buf[3] = xd[ (i >> 8) & 0xf ]; + buf[2] = xd[ (i >> 12) & 0xf ]; + + if ((p = hsearch(e, FIND)) != NULL) { + ++wcs2index_count; + if ((tfind(buf, &cur_base->root_starter_char, sym_cmp)) != NULL) { + wcs2index[i] = ++starter_index; +/* verbose_msg(VDETAIL, "wcs2index[ %#06x ] = %d (starter)\n", i, wcs2index[i]); */ + } else { + wcs2index[i] = (int)(p->data); +/* verbose_msg(VDETAIL, "wcs2index[ %#06x ] = %d\n", i, wcs2index[i]); */ + } + } else { + if ((tfind(buf, &cur_base->root_starter_char, sym_cmp)) != NULL) { + error_msg("marked starter but not in hash: %s", buf); + } + } + } + + + /* ---------------------------------------------------------------------- */ + { + int i, n; + table_data table; + size_t t, smallest; + + n = 0; + smallest = SIZE_MAX; + table.ii = NULL; + for (i=0 ; i < 14 ; i++) { + if ((RANGE >> i) < 4) { + break; + } + t = newopt(wcs2index, RANGE, i, &table); + if (smallest >= t) { + n = i; + smallest = t; + /* } else { */ + /* break; */ + } + } + + +/* printf("smallest = %u for range %#x (%u)\n", smallest, RANGE, RANGE); */ + assert(smallest != SIZE_MAX); + if (smallest + wcs2colidt_len >= WCS2COLIDT_LEN) { + error_msg("WCS2COLIDT_LEN too small"); + } + base_locale_array[base_locale_len].wcs2colidt_offset = wcs2colidt_len; + table.ii = wcs2colidt_buffer + wcs2colidt_len; + t = smallest; + smallest = SIZE_MAX; + smallest = newopt(wcs2index, RANGE, n, &table); + assert(t == smallest); + wcs2colidt_len += smallest; +/* verbose_msg(VDETAIL, "smallest = %d wcs2colidt_len = %d\n", smallest, wcs2colidt_len); */ + +#if 0 + { + unsigned int sc, n, i0, i1; + unsigned int u = 0xe40; + table_data *tbl = &table; + +#define __LOCALE_DATA_WCctype_TI_MASK ((1 << tbl->ti_shift)-1) +#define __LOCALE_DATA_WCctype_TI_SHIFT (tbl->ti_shift) +#define __LOCALE_DATA_WCctype_TI_LEN (tbl->ti_len) +#define __LOCALE_DATA_WCctype_II_MASK ((1 << tbl->ii_shift)-1) +#define __LOCALE_DATA_WCctype_II_SHIFT (tbl->ii_shift) +#define __LOCALE_DATA_WCctype_II_LEN (tbl->ii_len) + + sc = u & __LOCALE_DATA_WCctype_TI_MASK; + u >>= __LOCALE_DATA_WCctype_TI_SHIFT; + n = u & __LOCALE_DATA_WCctype_II_MASK; + u >>= __LOCALE_DATA_WCctype_II_SHIFT; + + i0 = tbl->ii[u]; + verbose_msg(VDETAIL, "i0 = %d\n", i0); + i0 <<= __LOCALE_DATA_WCctype_II_SHIFT; + i1 = tbl->ii[__LOCALE_DATA_WCctype_II_LEN + i0 + n]; + /* i1 = tbl->ti[i0 + n]; */ + verbose_msg(VDETAIL, "i1 = %d\n", i1); + i1 <<= __LOCALE_DATA_WCctype_TI_SHIFT; + /* return *(uint16_t *)(&(tbl->ii[__LOCALE_DATA_WCctype_II_LEN + __LOCALE_DATA_WCctype_TI_LEN + i1 + sc])); */ + verbose_msg(VDETAIL, "i2 = %d\n", __LOCALE_DATA_WCctype_II_LEN + __LOCALE_DATA_WCctype_TI_LEN + i1 + sc); + verbose_msg(VDETAIL, "val = %d\n", tbl->ii[__LOCALE_DATA_WCctype_II_LEN + __LOCALE_DATA_WCctype_TI_LEN + i1 + sc]); + /* return tbl->ut[i1 + sc]; */ + + + } +#endif + base_locale_array[base_locale_len].ii_shift = table.ii_shift; + base_locale_array[base_locale_len].ti_shift = table.ti_shift; + base_locale_array[base_locale_len].ii_len = table.ii_len; + base_locale_array[base_locale_len].ti_len = table.ti_len; + } + /* ---------------------------------------------------------------------- */ + + base_locale_array[base_locale_len].num_col_base = num_invariant + num_varying; + base_locale_array[base_locale_len].max_col_index = final_index; + base_locale_array[base_locale_len].max_weight = max_weight; + + verbose_msg(VDETAIL, "%s: %6u invariant %6u varying %6u derived %6u total %6u max weight %6u wcs2\n", + cur_base->name, num_invariant, num_varying, + tnumnodes(cur_base->root_derived_wi), final_index, max_weight, + wcs2index_count); + + } + +#if 1 + /* ok, now we need to dump out the base and derived tables... */ + /* don't forget to break up collating elements!!! */ + +/* fprintf(stdout, "**************************************************\n"); */ + /* first pass ... set the invariants */ + for (s = cur_base->section_list ; s ; s = s->next) { +#if 1 + if (s->data_type & DT_REORDER) { + verbose_msg(VDETAIL, "1: skipping reordered section %s\n", ((section_t *)(s->data))->name); + continue; + } +#endif + h = lli = ((section_t *)(s->data))->itm_list; + if (!lli) { + continue; + } + do { + if (lli->data_type & DT_WEIGHTED) { + w = (weighted_item_t *)(lli->data); + if (find_wi_index_reordered(w->symbol)) { /* reordered symbol so skip on first pass */ + continue; + } + if (index2weight_len_inc) { + index2ruleidx_buffer[index2ruleidx_len++] = + add_rule((weighted_item_t *)(lli->data)); + } +/* fprintf(stdout, "%11s: w %6d %6d %s\n", */ +/* cur_base->name, lli->idx, final_index_val(w->symbol), w->symbol); */ + } + } while ((lli = lli->next) != h); + } + + /* second pass ... set varying */ + for (s = cur_base->section_list ; s ; s = s->next) { +#if 1 + if (s->data_type & DT_REORDER) { + verbose_msg(VDETAIL, "2: skipping reordered section %s\n", ((section_t *)(s->data))->name); + continue; + } +#endif + h = lli = ((section_t *)(s->data))->itm_list; + if (!lli) { + continue; + } + do { + if (lli->data_type & DT_WEIGHTED) { + w = (weighted_item_t *)(lli->data); + if (find_wi_index_reordered(w->symbol)) { /* reordered symbol so skip on first pass */ + if (index2weight_len_inc) { + index2ruleidx_buffer[index2ruleidx_len++] = + add_rule((weighted_item_t *)(lli->data)); + } +/* fprintf(stdout, "%11s: r %6d %6d %s\n", */ +/* cur_base->name, lli->idx, final_index_val(w->symbol), w->symbol); */ + continue; + } + } + } while ((lli = lli->next) != h); + } + + do_starter_lists(cur_base); + + +/* verbose_msg(VDETAIL,"updated final_index = %d\n", final_index); */ + + if (rli) { + base_locale_array[base_locale_len].range_low + = strtoul(((range_item_t *)(rli->data))->symbol1 + 2, NULL, 16); + base_locale_array[base_locale_len].range_count + = ((range_item_t *)(rli->data))->length; + base_locale_array[base_locale_len].range_base_weight = rli->idx; + base_locale_array[base_locale_len].range_rule_offset = add_range_rule((range_item_t *)(rli->data)); +/* fprintf(stdout, "%11s: %6d %6d %s %s (%d)\n", */ +/* "RANGE", rli->idx, -1, */ +/* ((range_item_t *)(rli->data))->symbol1, */ +/* ((range_item_t *)(rli->data))->symbol2, */ +/* ((range_item_t *)(rli->data))->length); */ + } + +/* fprintf(stdout,"\nDerived\n\n"); */ + + /* first, if base name is of the form ll_CC, add a derived locale for it */ + if ((strlen(cur_base->name) == 5) + && islower(cur_base->name[0]) + && islower(cur_base->name[1]) + && (cur_base->name[2] == '_') + && isupper(cur_base->name[3]) + && isupper(cur_base->name[4]) + ) { + + verbose_msg(VDETAIL, "adding special derived for %s\n", cur_base->name); +/* verbose_msg(VDETAIL,"updated final_index = %d\n", final_index); */ + + + assert(der_locale_len+1 < DER_LOCALE_LEN); + + der_locale_array[der_locale_len].name = cur_base->name; + der_locale_array[der_locale_len].base_idx = base_locale_len; + + u16_buf[0] = 1; + u16_buf[1] = 0; + u16_buf_len = 2; + + mm = NULL; + if ((u16_buf_len > override_len) || + !(mm = memmem(override_buffer, override_len*sizeof(override_buffer[0]), + u16_buf, u16_buf_len*sizeof(u16_buf[0]))) + ) { + assert(override_len + u16_buf_len < OVERRIDE_LEN); + memcpy(override_buffer + override_len, u16_buf, u16_buf_len*sizeof(u16_buf[0])); + der_locale_array[der_locale_len].overrides_offset = override_len; + override_len += u16_buf_len; +/* printf("%s: override_len = %d u16_buf_len = %d\n", cl->name, override_len, u16_buf_len); */ + } else if (!(u16_buf_len > override_len)) { + assert(mm); + der_locale_array[der_locale_len].overrides_offset = ((uint16_t *)(mm)) - override_buffer; +/* printf("%s: memmem found a match with u16_buf_len = %d\n", cl->name, u16_buf_len); */ + } + der_locale_array[der_locale_len].multistart_offset + = base_locale_array[base_locale_len].multistart_offset; + der_locale_array[der_locale_len].undefined_idx = final_index_val0("UNDEFINED"); + + if (!der_locale_array[der_locale_len].undefined_idx) { + error_msg("no UNDEFINED definition for %s", cur_base->name); + } + + ++der_locale_len; + } else { + verbose_msg(VDETAIL, "NOT adding special derived for %s\n", cur_base->name); + } + + /* now all the derived... */ + for (cli = cur_base->derived_list ; cli ; cli = cli->next) { + cl = (col_locale_t *)(cli->data); + assert(cli->data_type == DT_COL_LOCALE); + + assert(der_locale_len+1 < DER_LOCALE_LEN); + + der_locale_array[der_locale_len].name = cl->name; + der_locale_array[der_locale_len].base_idx = base_locale_len; + + u16_buf_len = 0; + + for (i = 0 ; i < 2 ; i++) { + if (i) { +/* fprintf(stdout, " section --- (singles)\n"); */ + u16_buf[u16_buf_len++] = 1; /* single */ + } + /* we do this in two passes... first all sequences, then all single reorders */ + for (s = cl->section_list ; s ; s = s->next) { +/* verbose_msg(VDETAIL, "doing section %s\n", ((section_t *)(s->data))->name); */ + h = lli = ((section_t *)(s->data))->itm_list; + if (!lli) { +/* fprintf(stdout, "EMPTY ITEM LIST IN SECTION %s\n", ((section_t *)(s->data))->name ); */ + continue; + } + assert(u16_buf_len +4 < sizeof(u16_buf)/sizeof(u16_buf[0])); + if ((!i && (ll_len(h) > 1) ) || (ll_len(h) == i)) { + if (!i) { +/* fprintf(stdout, " section ----------------- %d %d\n", i, ll_len(h)); */ + u16_buf[u16_buf_len++] = ll_len(h); /* multi */ + assert(lli->data_type & DT_WEIGHTED); +#if 0 + u16_buf[u16_buf_len++] = final_index_val(((weighted_item_t *)(lli->data))->symbol); /* start index */ +#endif + u16_buf[u16_buf_len++] = lli->idx; /* start weight */ + } + do { + assert(lli->data_type & DT_WEIGHTED); + if (lli->data_type & DT_WEIGHTED) { +/* fprintf(stdout, "%11s: S %6d %6d %s\n", */ +/* cl->name, lli->idx, */ +/* final_index_val(((weighted_item_t *)(lli->data))->symbol), */ +/* ((weighted_item_t *)(lli->data))->symbol); */ +#if 0 + if (i) { + assert(u16_buf_len +4 < sizeof(u16_buf)/sizeof(u16_buf[0])); + u16_buf[u16_buf_len++] = final_index_val(((weighted_item_t *)(lli->data))->symbol); + assert(u16_buf[u16_buf_len-1]); + u16_buf[u16_buf_len++] = lli->idx; /* weight */ + } +#else + assert(u16_buf_len +4 < sizeof(u16_buf)/sizeof(u16_buf[0])); + u16_buf[u16_buf_len++] = final_index_val(((weighted_item_t *)(lli->data))->symbol); + assert(u16_buf[u16_buf_len-1]); + if (i) { + u16_buf[u16_buf_len++] = lli->idx; /* weight */ + } +#endif + u16_buf[u16_buf_len++] = add_rule((weighted_item_t *)(lli->data)); + + } + } while ((lli = lli->next) != h); + } + } + } + u16_buf[u16_buf_len++] = 0; + + mm = NULL; + if ((u16_buf_len > override_len) || + !(mm = memmem(override_buffer, override_len*sizeof(override_buffer[0]), + u16_buf, u16_buf_len*sizeof(u16_buf[0]))) + ) { + assert(override_len + u16_buf_len < OVERRIDE_LEN); + memcpy(override_buffer + override_len, u16_buf, u16_buf_len*sizeof(u16_buf[0])); + der_locale_array[der_locale_len].overrides_offset = override_len; + override_len += u16_buf_len; +/* printf("%s: override_len = %d u16_buf_len = %d\n", cl->name, override_len, u16_buf_len); */ + } else if (!(u16_buf_len > override_len)) { + assert(mm); + der_locale_array[der_locale_len].overrides_offset = ((uint16_t *)(mm)) - override_buffer; +/* printf("%s: memmem found a match with u16_buf_len = %d\n", cl->name, u16_buf_len); */ + } + + do_starter_lists(cl); + + der_locale_array[der_locale_len].undefined_idx = final_index_val0("UNDEFINED"); +#if 0 + assert(der_locale_array[der_locale_len].undefined_idx); + if (!der_locale_array[der_locale_len].undefined_idx) { + der_locale_array[der_locale_len].undefined_idx = base_locale_array[base_locale_len].undefined_idx; + } +#endif + + if (!der_locale_array[der_locale_len].undefined_idx) { + error_msg("no UNDEFINED definition for %s", cl->name); + } + + ++der_locale_len; + } + +#endif + +#warning handle UNDEFINED idx specially? what if in only some of derived? +/* base_locale_array[base_locale_len].undefined_idx = final_index_val0("UNDEFINED"); */ + base_locale_array[base_locale_len].undefined_idx = 0; + + + hdestroy(); + + ++base_locale_len; + +/* if (tnumnodes(cur_base->root_starter_char)) { */ +/* verbose_msg(VDETAIL, "starter nodes\n"); */ +/* twalk(cur_base->root_starter_char, print_starter_node); */ +/* } */ +} + +static int starter_all_cmp(const void *n1, const void *n2) +{ + const char *s1 = ((weighted_item_t *) n1)->symbol; + const char *s2 = ((weighted_item_t *) n2)->symbol; + colitem_t x; + colitem_t *p; + int n; + + /* sort by 1st char ... then inverse for string */ + + x.element = NULL; + if (!is_ucode(s1)) { + x.string = s1; + p = tfind(&x, &cur_base->root_colitem, colitem_cmp); + s1 = (*((colitem_t **) p))->element + 1; + } + if (!is_ucode(s2)) { + x.string = s2; + p = tfind(&x, &cur_base->root_colitem, colitem_cmp); + s2 = (*((colitem_t **) p))->element + 1; + } + + /* < */ + /* 01234567 */ + + assert(is_ucode(s1)); + assert(is_ucode(s2)); + + n = strncmp(s1+2, s2+2, 4); + if (n) { + return n; + } + + s1 += 7; + s2 += 7; + + return strcmp(s2, s1); +} + +static void print_starter_all_node(const void *ptr, VISIT order, int level) +{ + const weighted_item_t *w = *(const weighted_item_t **) ptr; + colitem_t *ci; + void *p; + int n; + colitem_t x; + + if (order == postorder || order == leaf) { +#if 0 + if ((n = is_ucode(w->symbol)) != 0) { + printf(" %s\n", w->symbol); + } else { + x.string = w->symbol; + x.element = NULL; + p = tfind(&x, &cur_base->root_colitem, colitem_cmp); + assert(p); + ci = *((colitem_t **) p); + printf("%s = %s\n", ci->element, w->symbol); + } +#else + printf("%s|", w->symbol); +/* if ((n = is_ucode(w->symbol)) != 0) { */ +/* printf("\n"); */ +/* } */ +#endif + } +} + +static void process_starter_node(const void *ptr, VISIT order, int level) +{ + const weighted_item_t *w = *(const weighted_item_t **) ptr; + colitem_t *ci; + void *p; + int n; + colitem_t x; + const char *s; + char buf[32]; + + /* store index of collation item followed by (unprefixed) nul-terminated string */ + if (order == postorder || order == leaf) { + if ((n = is_ucode(w->symbol)) != 0) { + u16_buf[u16_buf_len++] = final_index_val(w->symbol); + assert(u16_buf[u16_buf_len-1]); + u16_buf[u16_buf_len++] = 0; + if (++u16_starter < base_locale_array[base_locale_len].num_starters) { + u16_buf[u16_starter] = u16_buf_len; + } +/* verbose_msg(VDETAIL, "ucode - %d %d\n", u16_buf[u16_starter-1], u16_buf_len); */ + } else { + x.string = w->symbol; + x.element = NULL; + p = tfind(&x, &cur_base->root_colitem, colitem_cmp); + assert(p); + ci = *((colitem_t **) p); + s = ci->element; + u16_buf[u16_buf_len++] = final_index_val(w->symbol); + assert(u16_buf[u16_buf_len-1]); + assert(*s == '"'); + n = is_ucode(++s); +/* verbose_msg(VDETAIL, "s is |%s| with len %d (%d)\n", s, strlen(s), n); */ + assert(n); + s += n; + while (*s != '"') { + n = is_ucode(s); + assert(n); + strncpy(buf, s, n+1); + buf[n] = 0; +/* verbose_msg(VDETAIL, "buf is |%s| with len %d (%d)\n", buf, strlen(buf), n); */ + u16_buf[u16_buf_len++] = final_index_val(buf); + assert(u16_buf[u16_buf_len-1]); + s += n; + } + u16_buf[u16_buf_len++] = 0; + } + } +} + +static void **p_cl_root_starter_all; + +static void complete_starter_node(const void *ptr, VISIT order, int level) +{ + weighted_item_t w; + weighted_item_t *p; + + if (order == postorder || order == leaf) { + w.symbol = *(const char **) ptr; + w.weight = NULL; + if (!tfind(&w, p_cl_root_starter_all, starter_all_cmp)) { + p = xmalloc(sizeof(weighted_item_t)); + p->symbol = w.symbol; + p->weight = NULL; +/* verbose_msg(VDETAIL, "complete_starter_node: %s\n", *(const char **) ptr); */ + if (!tsearch(p, p_cl_root_starter_all, starter_all_cmp)) { + error_msg("OUT OF MEMORY"); + } + } + } +} + +static void do_starter_lists(col_locale_t *cl) +{ + ll_item_t *s; + ll_item_t *h; + ll_item_t *lli; + col_locale_t *c; + colitem_t *ci; + weighted_item_t *w; + void *p; + char buf[32]; + int n; + colitem_t x; + void *mm; + + c = cl; + if (c != cur_base) { + c = cur_base; + } + +/* printf("STARTERS %s --------------------\n", cl->name); */ + LOOP: + for (s = c->section_list ; s ; s = s->next) { + h = lli = ((section_t *)(s->data))->itm_list; + if (!lli) { + continue; + } + do { + if (lli->data_type & DT_WEIGHTED) { + w = (weighted_item_t *)(lli->data); + ci = NULL; + if ((n = is_ucode(w->symbol)) != 0) { + strcpy(buf, w->symbol); + } else { +/* fprintf(stdout, "looking for |%s|\n", w->symbol); */ + x.string = w->symbol; + x.element = NULL; + p = tfind(&x, &cur_base->root_colitem, colitem_cmp); + if (!p) { +/* verbose_msg(VDETAIL, "Whoa... processing starters for %s and couldn't find %s\n", */ +/* cl->name, w->symbol); */ + continue; + } + ci = *((colitem_t **) p); + if (!ci->element) { /* just a collating symbol */ + continue; + } + assert(ci->element[0] == '"'); + n = is_ucode(ci->element + 1); + assert(n); + strncpy(buf, ci->element + 1, n); + } + if ((tfind(buf, &cur_base->root_starter_char, sym_cmp)) != NULL) { +/* fprintf(stdout, "adding from %s: %s", c->name, w->symbol); */ +/* if (ci) { */ +/* fprintf(stdout, " = %s", ci->element); */ +/* } */ +/* fprintf(stdout, "\n"); */ + + if (!tsearch(w, &cl->root_starter_all, starter_all_cmp)) { + error_msg("OUT OF MEMORY"); + } + } + } + } while ((lli = lli->next) != h); + } + + if (c != cl) { + c = cl; + goto LOOP; + } + + p_cl_root_starter_all = &cl->root_starter_all; + twalk(cur_base->root_starter_char, complete_starter_node); + + if (cl == cur_base) { + base_locale_array[base_locale_len].num_starters = tnumnodes(cur_base->root_starter_char); + } + +#if 0 + printf("\nNow walking tree...\n\n"); + twalk(cl->root_starter_all, print_starter_all_node); + printf("\n\n"); + +#endif + u16_starter = 0; + u16_buf[0] = u16_buf_len = base_locale_array[base_locale_len].num_starters; + twalk(cl->root_starter_all, process_starter_node); +/* verbose_msg(VDETAIL, "s=%d n=%d\n", u16_starter, base_locale_array[base_locale_len].num_starters); */ + assert(u16_starter == base_locale_array[base_locale_len].num_starters); + +#if 0 + { int i; + for (i=0 ; i < u16_buf_len ; i++) { + verbose_msg(VDETAIL, "starter %2d: %d - %#06x\n", i, u16_buf[i], u16_buf[i]); + }} +#endif + + mm = NULL; + if (u16_buf_len) { +/* assert(base_locale_array[base_locale_len].num_starters); */ + if ((u16_buf_len > multistart_len) || + !(mm = memmem(multistart_buffer, multistart_len*sizeof(multistart_buffer[0]), + u16_buf, u16_buf_len*sizeof(u16_buf[0]))) + ) { + assert(multistart_len + u16_buf_len < MULTISTART_LEN); + memcpy(multistart_buffer + multistart_len, u16_buf, u16_buf_len*sizeof(u16_buf[0])); + if (cl == cur_base) { + base_locale_array[base_locale_len].multistart_offset = multistart_len; + } else { + der_locale_array[der_locale_len].multistart_offset = multistart_len; + } + multistart_len += u16_buf_len; +/* verbose_msg(VDETAIL, "%s: multistart_len = %d u16_buf_len = %d\n", cl->name, multistart_len, u16_buf_len); */ + } else if (!(u16_buf_len > multistart_len)) { + assert(mm); + if (cl == cur_base) { + base_locale_array[base_locale_len].multistart_offset = ((uint16_t *)(mm)) - multistart_buffer; + } else { + der_locale_array[der_locale_len].multistart_offset = ((uint16_t *)(mm)) - multistart_buffer; + } +/* verbose_msg(VDETAIL, "%s: memmem found a match with u16_buf_len = %d\n", cl->name, u16_buf_len); */ + } + } else { + assert(!base_locale_array[base_locale_len].num_starters); + } + +/* printf("u16_buf_len = %d\n", u16_buf_len); */ + +/* printf("STARTERS %s DONE ---------------\n", cl->name); */ +} + + +/* For sorting the blocks of unsigned chars. */ +static size_t nu_val; + +int nu_memcmp(const void *a, const void *b) +{ + return memcmp(*(unsigned char**)a, *(unsigned char**)b, nu_val * sizeof(tbl_item)); +} + + +size_t newopt(tbl_item *ut, size_t usize, int shift, table_data *tbl) +{ + static int recurse; + tbl_item *ti[RANGE]; /* table index */ + size_t numblocks; + size_t blocksize; + size_t uniq; + size_t i, j; + size_t smallest, t; + tbl_item *ii_save; + int uniqblock[1 << (8*sizeof(tbl_item) - 1)]; + tbl_item uit[RANGE]; + int shift2; + + if (shift > 15) { + return SIZE_MAX; + } + + ii_save = NULL; + blocksize = 1 << shift; + numblocks = usize >> shift; + + /* init table index */ + for (i=j=0 ; i < numblocks ; i++) { + ti[i] = ut + j; + j += blocksize; + } + + /* sort */ + nu_val = blocksize; + qsort(ti, numblocks, sizeof(unsigned char *), nu_memcmp); + + uniq = 1; + uit[(ti[0]-ut)/blocksize] = 0; + for (i=1 ; i < numblocks ; i++) { + if (memcmp(ti[i-1], ti[i], blocksize*sizeof(tbl_item)) < 0) { + if (++uniq > (1 << (8*sizeof(tbl_item) - 1))) { + break; + } + uniqblock[uniq - 1] = i; + } +#if 1 + else if (memcmp(ti[i-1], ti[i], blocksize*sizeof(tbl_item)) > 0) { + printf("bad sort %i!\n", i); + abort(); + } +#endif + uit[(ti[i]-ut)/blocksize] = uniq - 1; + } + + smallest = SIZE_MAX; + shift2 = -1; + if (uniq <= (1 << (8*sizeof(tbl_item) - 1))) { + smallest = numblocks + uniq * blocksize; + if (!recurse) { + ++recurse; + for (j=1 ; j < 14 ; j++) { + if ((numblocks >> j) < 2) break; + if (tbl) { + ii_save = tbl->ii; + tbl->ii = NULL; + } + if ((t = newopt(uit, numblocks, j, tbl)) < SIZE_MAX) { + t += uniq * blocksize; + } + if (tbl) { + tbl->ii = ii_save; + } + if (smallest >= t) { + shift2 = j; + smallest = t; +/* if (!tbl->ii) { */ +/* printf("ishift %u tshift %u size %u\n", */ +/* shift2, shift, t); */ +/* } */ +/* } else { */ +/* break; */ + } + } + --recurse; + } + } else { + return SIZE_MAX; + } + + if (tbl->ii) { + if (recurse) { + tbl->ii_shift = shift; + tbl->ii_len = numblocks; + memcpy(tbl->ii, uit, numblocks*sizeof(tbl_item)); + tbl->ti = tbl->ii + tbl->ii_len; + tbl->ti_len = uniq * blocksize; + for (i=0 ; i < uniq ; i++) { + memcpy(tbl->ti + i * blocksize, ti[uniqblock[i]], blocksize*sizeof(tbl_item)); + } + } else { + ++recurse; +/* printf("setting ishift %u tshift %u\n", shift2, shift); */ + newopt(uit, numblocks, shift2, tbl); + --recurse; + tbl->ti_shift = shift; + tbl->ut_len = uniq * blocksize; + tbl->ut = tbl->ti + tbl->ti_len; + for (i=0 ; i < uniq ; i++) { + memcpy(tbl->ut + i * blocksize, ti[uniqblock[i]], blocksize*sizeof(tbl_item)); + } + } + } + return smallest; +} + +static const int rule2val[8] = { + -1, + (1 << 14), /* forward */ + (2 << 14), /* position */ + (3 << 14), /* forward,position */ + 0, /* backward */ + -1, + -1, + -1, +}; + + +static int final_index_val_x(const char *s, const char *sym) +{ + int r; + + if (!(r = final_index_val0(s))) { + if (!strcmp(s, "IGNORE")) { + r = 0; + } else if (!strcmp(s, "..") || !strcmp(sym, "RANGE")) { + if (*sym == '.') { + final_index_val(sym); /* make sure it's known */ + } + r = 0x3fff; + } else if (!strcmp(s, ".")) { + r = 0x3ffe; + } else { + error_msg("can't find final index: %s", s); + } + } + return r; +} + +/* store rule2val in 2 high bits and collation index in lower. + * for sort strings, store (offset from base) + max colindex as index. + */ +static unsigned int add_rule(weighted_item_t *wi) +{ + weight_t *w = wi->weight; + int i, j, r, n; + uint16_t rbuf[MAX_COLLATION_WEIGHTS]; + uint16_t ws_buf[32]; + void *mm; + char buf[32]; + const char *s; + const char *e; + + for (i=0 ; i < MAX_COLLATION_WEIGHTS ; i++) { + rbuf[i] = rule2val[R_FORWARD]; /* set a default to forward-ignore */ + } + + if (base_locale_array[base_locale_len].num_weights < w->num_weights) { + base_locale_array[base_locale_len].num_weights = w->num_weights; + } + + for (i=0 ; i < w->num_weights ; i++) { + assert(rule2val[(int)(w->rule[i])] >= 0); + assert(w->colitem[i] && *w->colitem[i]); + if (*w->colitem[i] == '"') { /* string... */ + s = w->colitem[i] + 1; + assert(*s == '<'); + n = 0; + do { + e = s; + do { + if (*e == '/') { + e += 2; + continue; + } + } while (*e++ != '>'); + assert(((size_t)(e-s) < sizeof(buf))); + memcpy(buf, s, (size_t)(e-s)); + buf[(size_t)(e-s)] = 0; + + r = final_index_val_x(buf, wi->symbol); + assert(n + 1 < sizeof(ws_buf)/sizeof(ws_buf[0])); + ws_buf[n++] = r | rule2val[(int)(w->rule[i])]; + + s = e; + } while (*s != '"'); + ws_buf[n++] = 0; /* terminator */ + + mm = memmem(weightstr_buffer, weightstr_len*sizeof(weightstr_buffer[0]), + ws_buf, n*sizeof(ws_buf[0])); + + if (!mm) { + assert(weightstr_len + n < WEIGHTSTR_LEN); + memcpy(weightstr_buffer + weightstr_len, ws_buf, n*sizeof(ws_buf[0])); + mm = weightstr_buffer + weightstr_len; + weightstr_len += n; + } + r = (((uint16_t *)(mm)) - weightstr_buffer) + + base_locale_array[base_locale_len].max_col_index + 2; + assert(r < (1 << 14)); + rbuf[i] = r | rule2val[(int)(w->rule[i])]; + } else { /* item */ + r = final_index_val_x(w->colitem[i], wi->symbol); + rbuf[i] = r | rule2val[(int)(w->rule[i])]; + } + } + + for (i=0 ; i < ruletable_len ; i += MAX_COLLATION_WEIGHTS) { + if (!memcmp(ruletable_buffer + i, rbuf, MAX_COLLATION_WEIGHTS*sizeof(ruletable_buffer[0]))) { + return i/MAX_COLLATION_WEIGHTS; + } + } + + memcpy(ruletable_buffer + ruletable_len, rbuf, MAX_COLLATION_WEIGHTS*sizeof(ruletable_buffer[0])); + ruletable_len += MAX_COLLATION_WEIGHTS; + + return (ruletable_len / MAX_COLLATION_WEIGHTS)-1; +} + +static unsigned int add_range_rule(range_item_t *ri) +{ + weight_t *w = ri->weight; + int i, j, r, n; + uint16_t rbuf[MAX_COLLATION_WEIGHTS]; + uint16_t ws_buf[32]; + void *mm; + char buf[32]; + const char *s; + const char *e; + + for (i=0 ; i < MAX_COLLATION_WEIGHTS ; i++) { + rbuf[i] = rule2val[R_FORWARD]; /* set a default to forward-ignore */ + } + + if (base_locale_array[base_locale_len].num_weights < w->num_weights) { + base_locale_array[base_locale_len].num_weights = w->num_weights; + } + + for (i=0 ; i < w->num_weights ; i++) { + assert(rule2val[(int)(w->rule[i])] >= 0); + assert(w->colitem[i] && *w->colitem[i]); + if (*w->colitem[i] == '"') { /* string... */ + s = w->colitem[i] + 1; + assert(*s == '<'); + n = 0; + do { + e = s; + do { + if (*e == '/') { + e += 2; + continue; + } + } while (*e++ != '>'); + assert(((size_t)(e-s) < sizeof(buf))); + memcpy(buf, s, (size_t)(e-s)); + buf[(size_t)(e-s)] = 0; + + r = final_index_val_x(buf, "RANGE"); + assert(n + 1 < sizeof(ws_buf)/sizeof(ws_buf[0])); + ws_buf[n++] = r | rule2val[(int)(w->rule[i])]; + + s = e; + } while (*s != '"'); + ws_buf[n++] = 0; /* terminator */ + + mm = memmem(weightstr_buffer, weightstr_len*sizeof(weightstr_buffer[0]), + ws_buf, n*sizeof(ws_buf[0])); + + if (!mm) { + assert(weightstr_len + n < WEIGHTSTR_LEN); + memcpy(weightstr_buffer + weightstr_len, ws_buf, n*sizeof(ws_buf[0])); + mm = weightstr_buffer + weightstr_len; + weightstr_len += n; + } + r = (((uint16_t *)(mm)) - weightstr_buffer) + + base_locale_array[base_locale_len].max_col_index + 2; + assert(r < (1 << 14)); + rbuf[i] = r | rule2val[(int)(w->rule[i])]; + } else { /* item */ + r = final_index_val_x(w->colitem[i], "RANGE"); + rbuf[i] = r | rule2val[(int)(w->rule[i])]; + } + } + + for (i=0 ; i < ruletable_len ; i += MAX_COLLATION_WEIGHTS) { + if (!memcmp(ruletable_buffer + i, rbuf, MAX_COLLATION_WEIGHTS*sizeof(ruletable_buffer[0]))) { + return i/MAX_COLLATION_WEIGHTS; + } + } + + memcpy(ruletable_buffer + ruletable_len, rbuf, MAX_COLLATION_WEIGHTS*sizeof(ruletable_buffer[0])); + ruletable_len += MAX_COLLATION_WEIGHTS; + + return (ruletable_len / MAX_COLLATION_WEIGHTS)-1; +} + +#define DUMPn(X) fprintf(stderr, "%10d-%-.20s", base_locale_array[n]. X, #X); + +static void dump_base_locale(int n) +{ + assert(n < base_locale_len); + + fprintf(stderr, "Base Locale: %s\n", base_locale_array[n].name); + + DUMPn(num_weights); + + DUMPn(ii_shift); + DUMPn(ti_shift); + DUMPn(ii_len); + DUMPn(ti_len); + DUMPn(max_weight); + fprintf(stderr, "\n"); + DUMPn(num_col_base); + DUMPn(max_col_index); + DUMPn(undefined_idx); + DUMPn(range_low); + DUMPn(range_count); + fprintf(stderr, "\n"); + DUMPn(range_base_weight); + DUMPn(num_starters); + + fprintf(stderr, "\n"); + DUMPn(range_rule_offset); + DUMPn(wcs2colidt_offset); + DUMPn(index2weight_offset); + fprintf(stderr, "\n"); + DUMPn(index2ruleidx_offset); + DUMPn(multistart_offset); + fprintf(stderr, "\n"); +} + +#undef DUMPn +#define DUMPn(X) fprintf(stderr, "%10d-%s", der_locale_array[n]. X, #X); + +static void dump_der_locale(int n) +{ + assert(n < der_locale_len); + + fprintf(stderr, "Derived Locale: %s (%.12s)", + der_locale_array[n].name, + base_locale_array[der_locale_array[n].base_idx].name); + + + DUMPn(base_idx); + + DUMPn(undefined_idx); + + DUMPn(overrides_offset); + DUMPn(multistart_offset); + + fprintf(stderr, "\n"); +} + + +static unsigned long collate_pos; + +static void dump_u16_array(FILE *fp, uint16_t *u, int len, const char *name) +{ + int i; + + fprintf(fp, "\t/* %8lu %s */\n", collate_pos, name); + for (i=0 ; i < len ; i++) { + if (!(i & 7)) { + fprintf(fp, "\n\t"); + } + fprintf(fp," %#06x,", (unsigned int)(u[i])); + } + fprintf(fp,"\n"); + collate_pos += len; +} + +#define OUT_U16C(X,N) fprintf(fp,"\t%10d, /* %8lu %s */\n", X, collate_pos++, N); + +static void dump_collate(FILE *fp) +{ + int n; + + fprintf(fp, "const uint16_t __locale_collate_tbl[] = {\n"); + + OUT_U16C(base_locale_len, "numbef of base locales"); + OUT_U16C(der_locale_len, "number of derived locales"); + OUT_U16C(MAX_COLLATION_WEIGHTS, "max collation weights"); + OUT_U16C(index2weight_len, "number of index2{weight|ruleidx} elements"); + OUT_U16C(weightstr_len, "number of weightstr elements"); + OUT_U16C(multistart_len, "number of multistart elements"); + OUT_U16C(override_len, "number of override elements"); + OUT_U16C(ruletable_len, "number of ruletable elements"); + +#undef DUMPn +#define DUMPn(X) fprintf(fp, "\t%10d, /* %8lu %s */\n", base_locale_array[n]. X, collate_pos++, #X); + for (n=0 ; n < base_locale_len ; n++) { + unsigned wcs2colidt_offset_low = base_locale_array[n].wcs2colidt_offset & 0xffffU; + unsigned wcs2colidt_offset_hi = base_locale_array[n].wcs2colidt_offset >> 16; + fprintf(fp, "\t/* Base Locale %2d: %s */\n", n, base_locale_array[n].name); + DUMPn(num_weights); + DUMPn(num_starters); + DUMPn(ii_shift); + DUMPn(ti_shift); + DUMPn(ii_len); + DUMPn(ti_len); + DUMPn(max_weight); + DUMPn(num_col_base); + DUMPn(max_col_index); + DUMPn(undefined_idx); + DUMPn(range_low); + DUMPn(range_count); + DUMPn(range_base_weight); + DUMPn(range_rule_offset); + DUMPn(index2weight_offset); + DUMPn(index2ruleidx_offset); + DUMPn(multistart_offset); +#undef DUMPn +#define DUMPn(X) fprintf(fp, "\t%10d, /* %8lu %s */\n", X, collate_pos++, #X); + DUMPn(wcs2colidt_offset_low); + DUMPn(wcs2colidt_offset_hi); + } +#undef DUMPn + + + fprintf(fp, "#define COL_IDX_C %5d\n", 0); +#define DUMPn(X) fprintf(fp, "\t%10d, /* %8lu %s */\n", der_locale_array[n]. X, collate_pos++, #X); + for (n=0 ; n < der_locale_len ; n++) { + fprintf(fp, "#define COL_IDX_%s %5d\n", der_locale_array[n].name, n+1); + fprintf(fp, "\t/* Derived Locale %4d: %s (%.12s) */\n", + n, der_locale_array[n].name, + base_locale_array[der_locale_array[n].base_idx].name); + DUMPn(base_idx); + DUMPn(undefined_idx); + DUMPn(overrides_offset); + DUMPn(multistart_offset); + } +#undef DUMPn + + fprintf(fp, "\n"); + + dump_u16_array(fp, index2weight_buffer, index2weight_len, "index2weight"); + dump_u16_array(fp, index2ruleidx_buffer, index2ruleidx_len, "index2ruleidx"); + dump_u16_array(fp, multistart_buffer, multistart_len, "multistart"); + dump_u16_array(fp, override_buffer, override_len, "override"); + dump_u16_array(fp, ruletable_buffer, ruletable_len, "ruletable"); + dump_u16_array(fp, weightstr_buffer, weightstr_len, "weightstr"); + dump_u16_array(fp, wcs2colidt_buffer, wcs2colidt_len, "wcs2colidt"); + + + fprintf(fp,"}; /* %8lu */\n", collate_pos); + + fprintf(fp,"#define __lc_collate_data_LEN %lu\n\n", collate_pos); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/gen_ldc.c b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/gen_ldc.c new file mode 100644 index 00000000..2cedbdda --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/gen_ldc.c @@ -0,0 +1,298 @@ +#include +#include +#include +#include +#include +#include + +#ifndef __WCHAR_ENABLED +#warning WHOA!!! __WCHAR_ENABLED is not defined! defining it now... +#define __WCHAR_ENABLED +#endif + +#define WANT_DATA +#include "c8tables.h" +#ifndef __CTYPE_HAS_8_BIT_LOCALES +#warning __CTYPE_HAS_8_BIT_LOCALES is not defined... +/* #define __CTYPE_HAS_8_BIT_LOCALES */ +#endif + +/* #define __LOCALE_DATA_Cctype_TBL_LEN 328 */ +/* #define __LOCALE_DATA_Cuplow_TBL_LEN 400 */ +/* #define __LOCALE_DATA_Cc2wc_TBL_LEN 1448 */ +/* #define __LOCALE_DATA_Cwc2c_TBL_LEN 3744 */ + +#define WANT_WCctype_data +#define WANT_WCuplow_data +#define WANT_WCuplow_diff_data +/* #define WANT_WCcomb_data */ +/* #define WANT_WCwidth_data */ +#include "wctables.h" +#undef WANT_WCctype_data +#undef WANT_WCuplow_data +#undef WANT_WCuplow_diff_data +/* #undef WANT_WCcomb_data */ +/* #undef WANT_WCwidth_data */ + + #define __LOCALE_DATA_WCctype_TBL_LEN (__LOCALE_DATA_WCctype_II_LEN + __LOCALE_DATA_WCctype_TI_LEN + __LOCALE_DATA_WCctype_UT_LEN) + #define __LOCALE_DATA_WCuplow_TBL_LEN (__LOCALE_DATA_WCuplow_II_LEN + __LOCALE_DATA_WCuplow_TI_LEN + __LOCALE_DATA_WCuplow_UT_LEN) + #define __LOCALE_DATA_WCuplow_diff_TBL_LEN (2 * __LOCALE_DATA_WCuplow_diffs) +/* #define WCcomb_TBL_LEN (WCcomb_II_LEN + WCcomb_TI_LEN + WCcomb_UT_LEN) */ + +#include "locale_collate.h" +#include "locale_tables.h" + +#include "locale_mmap.h" + +/* #undef __PASTE2 */ +/* #define __PASTE2(A,B) A ## B */ +/* #undef __PASTE3 */ +/* #define __PASTE3(A,B,C) A ## B ## C */ + + +/* #define __LOCALE_DATA_MAGIC_SIZE 64 */ + +/* #define COMMON_MMAP(X) \ */ +/* unsigned char __PASTE3(lc_,X,_data)[__PASTE3(__lc_,X,_data_LEN)]; */ + +/* #define COMMON_MMIDX(X) \ */ +/* unsigned char __PASTE3(lc_,X,_rows)[__PASTE3(__lc_,X,_rows_LEN)]; \ */ +/* uint16_t __PASTE3(lc_,X,_item_offsets)[__PASTE3(__lc_,X,_item_offsets_LEN)]; \ */ +/* uint16_t __PASTE3(lc_,X,_item_idx)[__PASTE3(__lc_,X,_item_idx_LEN)]; \ */ + +/* ---------------------------------------------------------------------- */ + +#define COMMON_OFFSETS(X) \ + offsetof(__locale_mmap_t, __PASTE3(lc_,X,_rows)), \ + offsetof(__locale_mmap_t, __PASTE3(lc_,X,_item_offsets)), \ + offsetof(__locale_mmap_t, __PASTE3(lc_,X,_item_idx)), \ + offsetof(__locale_mmap_t, __PASTE3(lc_,X,_data)) \ + + +static const size_t common_tbl_offsets[__LOCALE_DATA_CATEGORIES*4] = { + COMMON_OFFSETS(ctype), + COMMON_OFFSETS(numeric), + COMMON_OFFSETS(monetary), + COMMON_OFFSETS(time), + 0, 0, 0, 0, /* collate */ + COMMON_OFFSETS(messages), +}; + + +void out_uc(FILE *f, const unsigned char *p, size_t n, char *comment) +{ + size_t i; + + fprintf(f, "{\t/* %s */", comment); + for (i = 0 ; i < n ; i++) { + if (!(i & 7)) { + fprintf(f, "\n\t"); + } + if (p[i]) { + fprintf(f, "%#04x, ", p[i]); + } else { + fprintf(f, "%#4x, ", p[i]); + } + } + fprintf(f, "\n},\n"); +} + +void out_u16(FILE *f, const uint16_t *p, size_t n, char *comment) +{ + size_t i; + + fprintf(f, "{\t/* %s */", comment); + for (i = 0 ; i < n ; i++) { + if (!(i & 7)) { + fprintf(f, "\n\t"); + } + if (p[i]) { + fprintf(f, "%#06x, ", p[i]); + } else { + fprintf(f, "%#6x, ", p[i]); + } + } + fprintf(f, "\n},\n"); +} + +void out_i16(FILE *f, const int16_t *p, size_t n, char *comment) +{ + size_t i; + + fprintf(f, "{\t/* %s */", comment); + for (i = 0 ; i < n ; i++) { + if (!(i & 7)) { + fprintf(f, "\n\t"); + } + fprintf(f, "%6d, ", p[i]); + } + fprintf(f, "\n},\n"); +} + +void out_size_t(FILE *f, const size_t *p, size_t n, char *comment) +{ + size_t i; + + fprintf(f, "{\t/* %s */", comment); + for (i = 0 ; i < n ; i++) { + if (!(i & 3)) { + fprintf(f, "\n\t"); + } + if (p[i]) { + fprintf(f, "%#010zx, ", p[i]); + } else { + fprintf(f, "%#10zx, ", p[i]); + } + } + fprintf(f, "\n},\n"); +} + + +int main(int argc, char **argv) +{ + char *output_file = "locale_data.c"; + FILE *lso; /* static object */ + int i; +#ifdef __LOCALE_DATA_MAGIC_SIZE + unsigned char magic[__LOCALE_DATA_MAGIC_SIZE]; + + memset(magic, 0, __LOCALE_DATA_MAGIC_SIZE); +#endif /* __LOCALE_DATA_MAGIC_SIZE */ + + if (argc == 2) + output_file = argv[1]; + if (!(lso = fopen(output_file, "w"))) { + printf("cannot open output file '%s'!\n", output_file); + return EXIT_FAILURE; + } + + fprintf(lso, + "#include \n" + "#include \n" +/* "#define __CTYPE_HAS_8_BIT_LOCALES\n" */ + "#ifndef __WCHAR_ENABLED\n" + "#error __WCHAR_ENABLED not defined\n" + "#endif\n" + "#include \"c8tables.h\"\n" + "#include \"wctables.h\"\n" + "#include \"lt_defines.h\"\n" + "#include \"locale_mmap.h\"\n\n" + "static const __locale_mmap_t locale_mmap = {\n\n" + ); +#ifdef __LOCALE_DATA_MAGIC_SIZE + out_uc(lso, magic, __LOCALE_DATA_MAGIC_SIZE, "magic"); +#endif /* __LOCALE_DATA_MAGIC_SIZE */ +#ifdef __CTYPE_HAS_8_BIT_LOCALES + out_uc(lso, __LOCALE_DATA_Cctype_data, __LOCALE_DATA_Cctype_TBL_LEN, "tbl8ctype"); + out_uc(lso, __LOCALE_DATA_Cuplow_data, __LOCALE_DATA_Cuplow_TBL_LEN, "tbl8uplow"); +#ifdef __WCHAR_ENABLED + out_u16(lso, __LOCALE_DATA_Cc2wc_data, __LOCALE_DATA_Cc2wc_TBL_LEN, "tbl8c2wc"); + out_uc(lso, __LOCALE_DATA_Cwc2c_data, __LOCALE_DATA_Cwc2c_TBL_LEN, "tbl8wc2c"); + /* translit */ +#endif /* __WCHAR_ENABLED */ +#endif /* __CTYPE_HAS_8_BIT_LOCALES */ +#ifdef __WCHAR_ENABLED + out_uc(lso, __LOCALE_DATA_WCctype_data, __LOCALE_DATA_WCctype_TBL_LEN, "tblwctype"); + out_uc(lso, __LOCALE_DATA_WCuplow_data, __LOCALE_DATA_WCuplow_TBL_LEN, "tblwuplow"); + out_i16(lso, __LOCALE_DATA_WCuplow_diff_data, __LOCALE_DATA_WCuplow_diff_TBL_LEN, "tblwuplow_diff"); +/* const unsigned char tblwcomb[WCcomb_TBL_LEN]; */ + /* width?? */ +#endif /* __WCHAR_ENABLED */ + out_uc(lso, __lc_ctype_data, __lc_ctype_data_LEN, "lc_ctype_data"); + out_uc(lso, __lc_numeric_data, __lc_numeric_data_LEN, "lc_numeric_data"); + out_uc(lso, __lc_monetary_data, __lc_monetary_data_LEN, "lc_monetary_data"); + out_uc(lso, __lc_time_data, __lc_time_data_LEN, "lc_time_data"); + /* TODO -- collate*/ + out_uc(lso, __lc_messages_data, __lc_messages_data_LEN, "lc_messages_data"); + +#ifdef __CTYPE_HAS_8_BIT_LOCALES + fprintf(lso, "{ /* codeset_8_bit array */\n"); + for (i = 0 ; i < __LOCALE_DATA_NUM_CODESETS ; i++) { + fprintf(lso, "{ /* codeset_8_bit[%d] */\n", i); + out_uc(lso, codeset_8_bit[i].idx8ctype, __LOCALE_DATA_Cctype_IDX_LEN, "idx8ctype"); + out_uc(lso, codeset_8_bit[i].idx8uplow, __LOCALE_DATA_Cuplow_IDX_LEN, "idx8uplow"); + out_uc(lso, codeset_8_bit[i].idx8c2wc, __LOCALE_DATA_Cc2wc_IDX_LEN, "idx8c2wc"); + out_uc(lso, codeset_8_bit[i].idx8wc2c, __LOCALE_DATA_Cwc2c_II_LEN, "idx8wc2c"); + fprintf(lso, "},\n"); + } + fprintf(lso, "},\n"); +#endif /* __CTYPE_HAS_8_BIT_LOCALES */ + + out_uc(lso, __lc_ctype_rows, __lc_ctype_rows_LEN, "lc_ctype_rows"); + out_u16(lso, __lc_ctype_item_offsets, __lc_ctype_item_offsets_LEN, "lc_ctype_item_offsets"); + out_u16(lso, __lc_ctype_item_idx, __lc_ctype_item_idx_LEN, "lc_ctype_item_idx"); + + out_uc(lso, __lc_numeric_rows, __lc_numeric_rows_LEN, "lc_numeric_rows"); + out_u16(lso, __lc_numeric_item_offsets, __lc_numeric_item_offsets_LEN, "lc_numeric_item_offsets"); + out_u16(lso, __lc_numeric_item_idx, __lc_numeric_item_idx_LEN, "lc_numeric_item_idx"); + + out_uc(lso, __lc_monetary_rows, __lc_monetary_rows_LEN, "lc_monetary_rows"); + out_u16(lso, __lc_monetary_item_offsets, __lc_monetary_item_offsets_LEN, "lc_monetary_item_offsets"); + out_u16(lso, __lc_monetary_item_idx, __lc_monetary_item_idx_LEN, "lc_monetary_item_idx"); + + out_uc(lso, __lc_time_rows, __lc_time_rows_LEN, "lc_time_rows"); + out_u16(lso, __lc_time_item_offsets, __lc_time_item_offsets_LEN, "lc_time_item_offsets"); + out_u16(lso, __lc_time_item_idx, __lc_time_item_idx_LEN, "lc_time_item_idx"); + + out_uc(lso, __lc_messages_rows, __lc_messages_rows_LEN, "lc_messages_rows"); + out_u16(lso, __lc_messages_item_offsets, __lc_messages_item_offsets_LEN, "lc_messages_item_offsets"); + out_u16(lso, __lc_messages_item_idx, __lc_messages_item_idx_LEN, "lc_messages_item_idx"); + + /* collate should be last*/ + assert(sizeof(__locale_collate_tbl)/sizeof(__locale_collate_tbl[0]) == __lc_collate_data_LEN) ; + out_u16(lso, __locale_collate_tbl, __lc_collate_data_LEN, "collate_data"); + + + { + unsigned char co_buf[__LOCALE_DATA_CATEGORIES] = { + __lc_ctype_item_offsets_LEN, + __lc_numeric_item_offsets_LEN, + __lc_monetary_item_offsets_LEN, + __lc_time_item_offsets_LEN, + 0, + __lc_messages_item_offsets_LEN + }; + out_uc(lso, co_buf, __LOCALE_DATA_CATEGORIES, "lc_common_item_offsets_LEN"); + } + + out_size_t(lso, common_tbl_offsets, __LOCALE_DATA_CATEGORIES * 4, "lc_common_tbl_offsets"); + /* offsets from start of locale_mmap_t */ + /* rows, item_offsets, item_idx, data */ + +#ifdef __LOCALE_DATA_NUM_LOCALES + out_uc(lso, __locales, __LOCALE_DATA_NUM_LOCALES * __LOCALE_DATA_WIDTH_LOCALES, "locales"); + out_uc(lso, __locale_names5, 5 * __LOCALE_DATA_NUM_LOCALE_NAMES, "locale_names5"); +#ifdef __LOCALE_DATA_AT_MODIFIERS_LENGTH + out_uc(lso, __locale_at_modifiers, __LOCALE_DATA_AT_MODIFIERS_LENGTH, "locale_at_modifiers"); +#else +#error __LOCALE_DATA_AT_MODIFIERS_LENGTH not defined! +#endif /* __LOCALE_DATA_AT_MODIFIERS_LENGTH */ +#endif /* __LOCALE_DATA_NUM_LOCALES */ + + out_uc(lso, lc_names, __lc_names_LEN, "lc_names"); +#ifdef __CTYPE_HAS_8_BIT_LOCALES + out_uc(lso, (const unsigned char*) __LOCALE_DATA_CODESET_LIST, sizeof(__LOCALE_DATA_CODESET_LIST), "codeset_list"); +#endif /* __CTYPE_HAS_8_BIT_LOCALES */ + + fprintf(lso, + "\n};\n\n" + "const __locale_mmap_t *__locale_mmap = &locale_mmap;\n\n" + ); + + if (ferror(lso) || fclose(lso)) { + printf("error writing!\n"); + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} + +/* ---------------------------------------------------------------------- */ + +/* TODO: + * collate data (8-bit weighted single char only) + * @ mappings! + * codeset list? yes, since we'll want to be able to inspect them... + * that means putting some header stuff in magic + * fix ctype LEN defines in gen_c8tables + */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/gen_locale.c b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/gen_locale.c new file mode 100644 index 00000000..5e893608 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/gen_locale.c @@ -0,0 +1,1337 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "c8tables.h" + + +#define __LOCALE_DATA_CATEGORIES 6 + +/* must agree with ordering of gen_mmap! */ +static const char *lc_names[] = { + "LC_CTYPE", + "LC_NUMERIC", + "LC_MONETARY", + "LC_TIME", + "LC_COLLATE", + "LC_MESSAGES", +#if __LOCALE_DATA_CATEGORIES == 12 + "LC_PAPER", + "LC_NAME", + "LC_ADDRESS", + "LC_TELEPHONE", + "LC_MEASUREMENT", + "LC_IDENTIFICATION", +#elif __LOCALE_DATA_CATEGORIES != 6 +#error unsupported __LOCALE_DATA_CATEGORIES value! +#endif +}; + + + +typedef struct { + char *glibc_name; + char name[5]; + char dot_cs; /* 0 if no codeset specified */ + char cs; + unsigned char idx_name; + unsigned char lc_time_row; + unsigned char lc_numeric_row; + unsigned char lc_monetary_row; + unsigned char lc_messages_row; + unsigned char lc_ctype_row; +#if __LOCALE_DATA_CATEGORIES != 6 +#error unsupported __LOCALE_DATA_CATEGORIES value +#endif +} locale_entry; + +static void read_at_mappings(void); +static void read_enable_disable(void); +static void read_locale_list(void); + +static int find_codeset_num(const char *cs); +static int find_at_string_num(const char *as); +static int le_cmp(const void *, const void *); +static void dump_table8(const char *name, const char *tbl, int len); +static void dump_table8c(const char *name, const char *tbl, int len); +static void dump_table16(const char *name, const int *tbl, int len); + +static void do_lc_time(void); +static void do_lc_numeric(void); +static void do_lc_monetary(void); + +static void do_lc_messages(void); +static void do_lc_ctype(void); + + +static FILE *fp; +static FILE *ofp; +static char line_buf[80]; +static char at_mappings[256]; +static char at_mapto[256]; +static char at_strings[1024]; +static char *at_strings_end; +static locale_entry locales[700]; +static char glibc_locale_names[60000]; + +static int num_locales; + +static int default_utf8; +static int default_8bit; + +static int total_size; +static int null_count; + +static unsigned verbose = 0; +enum { + VINFO = (1<<0), + VDETAIL = (1<<1), +}; +static int verbose_msg(const unsigned lvl, const char *fmt, ...) +{ + va_list arg; + int ret = 0; + + if (verbose & lvl) { + va_start(arg, fmt); + ret = vfprintf(stderr, fmt, arg); + va_end(arg); + } + return ret; +} + +static void error_msg(const char *fmt, ...) __attribute__ ((noreturn, format (printf, 1, 2))); +static void error_msg(const char *fmt, ...) +{ + va_list arg; + + fprintf(stderr, "Error: "); +/* if (fno >= 0) { + fprintf(stderr, "file %s (%d): ", fname[fno], lineno[fno]); + } */ + va_start(arg, fmt); + vfprintf(stderr, fmt, arg); + va_end(arg); + fprintf(stderr, "\n"); + + exit(EXIT_FAILURE); +} + +static void do_locale_names(void) +{ + /* "C" locale name is handled specially by the setlocale code. */ + int uniq = 0; + int i; + + if (num_locales <= 1) { +/* error_msg("only C locale?"); */ + fprintf(ofp, "static const unsigned char __locales[%d];\n", (3 + __LOCALE_DATA_CATEGORIES)); + fprintf(ofp, "static const unsigned char __locale_names5[5];\n"); + } else { + if (default_utf8) { + fprintf(ofp, "#define __CTYPE_HAS_UTF_8_LOCALES\t\t\t1\n"); + } + fprintf(ofp, "#define __LOCALE_DATA_CATEGORIES\t\t\t%d\n", __LOCALE_DATA_CATEGORIES); + fprintf(ofp, "#define __LOCALE_DATA_WIDTH_LOCALES\t\t\t%d\n", 3+__LOCALE_DATA_CATEGORIES); + fprintf(ofp, "#define __LOCALE_DATA_NUM_LOCALES\t\t\t%d\n", num_locales); + fprintf(ofp, "static const unsigned char __locales[%d] = {\n", + (num_locales) * (3 + __LOCALE_DATA_CATEGORIES)); + for (i=0 ; i < num_locales ; i++) { + if (memcmp(locales[i].name, locales[i-1].name, 5) != 0) { + locales[i].idx_name = uniq; + ++uniq; + } else { + locales[i].idx_name = uniq - 1; + } + fprintf(ofp, "\t%#4x, ", (int)((unsigned char) locales[i].idx_name)); + fprintf(ofp, "\t%#4x, ", (int)((unsigned char) locales[i].dot_cs)); + fprintf(ofp, "\t%#4x, ", (int)((unsigned char) locales[i].cs)); + /* lc_ctype would store translit flags and turkish up/low flag. */ + fprintf(ofp, "%#4x, ", (int)((unsigned char) locales[i].lc_ctype_row)); + fprintf(ofp, "%#4x, ", (int)((unsigned char) locales[i].lc_numeric_row)); + fprintf(ofp, "%#4x, ", (int)((unsigned char) locales[i].lc_monetary_row)); + fprintf(ofp, "%#4x, ", (int)((unsigned char) locales[i].lc_time_row)); +#if 1 + /* lc_collate */ + if (strlen(locales[i].glibc_name) >= 5) { + fprintf(ofp, "COL_IDX_%.2s_%.2s, ", locales[i].glibc_name, locales[i].glibc_name+3); + } else if (!strcmp(locales[i].glibc_name, "C")) { + fprintf(ofp, "COL_IDX_C , "); + } else { + error_msg("don't know how to handle COL_IDX_ for %s", locales[i].glibc_name); + } +#else + fprintf(ofp, "%#4x, ", 0); /* place holder for lc_collate */ +#endif + fprintf(ofp, "%#4x, ", (int)((unsigned char) locales[i].lc_messages_row)); + fprintf(ofp, "\t/* %s */\n", locales[i].glibc_name); + } + fprintf(ofp, "};\n\n"); + + fprintf(ofp, "#define __LOCALE_DATA_NUM_LOCALE_NAMES\t\t%d\n", uniq ); + fprintf(ofp, "static const unsigned char __locale_names5[%d] = \n\t", uniq * 5); + uniq = 0; + for (i=1 ; i < num_locales ; i++) { + if (memcmp(locales[i].name, locales[i-1].name, 5) != 0) { + fprintf(ofp, "\"%5.5s\" ", locales[i].name); + ++uniq; + if ((uniq % 8) == 0) { + fprintf(ofp, "\n\t"); + } + } + } + fprintf(ofp,";\n\n"); + + if (at_strings_end > at_strings) { + int i, j; + char *p; + i = 0; + p = at_strings; + while (*p) { + ++i; + p += 1 + (unsigned char) *p; + } + /* len, char, string\0 */ + fprintf(ofp, "#define __LOCALE_DATA_AT_MODIFIERS_LENGTH\t\t%d\n", + i + (at_strings_end - at_strings)); + fprintf(ofp, "static const unsigned char __locale_at_modifiers[%d] = {", + i + (at_strings_end - at_strings)); + i = 0; + p = at_strings; + while (*p) { + fprintf(ofp, "\n\t%4d, '%c',", + (unsigned char) *p, /* len of string\0 */ + at_mapto[i]); + for (j=1 ; j < ((unsigned char) *p) ; j++) { + fprintf(ofp, " '%c',", p[j]); + } + fprintf(ofp, " 0,"); + ++i; + p += 1 + (unsigned char) *p; + } + fprintf(ofp, "\n};\n\n"); + } + + { + int pos[__LOCALE_DATA_CATEGORIES]; + pos[0] = __LOCALE_DATA_CATEGORIES; + for (i=0 ; i < __LOCALE_DATA_CATEGORIES ; i++) { + fprintf(ofp, "#define __%s\t\t%d\n", lc_names[i], i); + if (i + 1 < __LOCALE_DATA_CATEGORIES) { + pos[i+1] = 1 + strlen(lc_names[i]) + pos[i]; + } + } + if (pos[__LOCALE_DATA_CATEGORIES-1] > 255) { + error_msg("lc_names is too big (%d)", pos[__LOCALE_DATA_CATEGORIES-1]); + } + fprintf(ofp, "#define __LC_ALL\t\t%d\n\n", i); + + fprintf(ofp, "#define __lc_names_LEN\t\t%d\n", + pos[__LOCALE_DATA_CATEGORIES-1] + strlen(lc_names[__LOCALE_DATA_CATEGORIES-1]) + 1); + total_size += pos[__LOCALE_DATA_CATEGORIES-1] + strlen(lc_names[__LOCALE_DATA_CATEGORIES-1]) + 1; + + fprintf(ofp, "static unsigned const char lc_names[%d] =\n", + pos[__LOCALE_DATA_CATEGORIES-1] + strlen(lc_names[__LOCALE_DATA_CATEGORIES-1]) + 1); + fprintf(ofp, "\t\""); + for (i=0 ; i < __LOCALE_DATA_CATEGORIES ; i++) { + fprintf(ofp, "\\x%02x", (unsigned char) pos[i]); + } + fprintf(ofp, "\""); + for (i=0 ; i < __LOCALE_DATA_CATEGORIES ; i++) { + fprintf(ofp, "\n\t\"%s\\0\"", lc_names[i]); + } + fprintf(ofp, ";\n\n"); + } + + verbose_msg(VDETAIL,"locale data = %d name data = %d for %d uniq\n", + num_locales * (3 + __LOCALE_DATA_CATEGORIES), uniq * 5, uniq); + + total_size += num_locales * (3 + __LOCALE_DATA_CATEGORIES) + uniq * 5; + } + +} + +static void read_at_mappings(void) +{ + char *p; + char *m; + int mc = 0; + + do { + if (!(p = strtok(line_buf, " \t\n")) || (*p == '#')) { + if (!fgets(line_buf, sizeof(line_buf), fp)) { + if (ferror(fp)) { + error_msg("reading file"); + } + return; /* EOF */ + } + if ((*line_buf == '#') && (line_buf[1] == '-')) { + break; + } + continue; + } + if (*p == '@') { + if (p[1] == 0) { + error_msg("missing @modifier name"); + } + m = p; /* save the modifier name */ + if (!(p = strtok(NULL, " \t\n")) || p[1] || (((unsigned char) *p) > 0x7f)) { + error_msg("missing or illegal @modifier mapping char"); + } + if (at_mappings[(int)((unsigned char) *p)]) { + error_msg("reused @modifier mapping char"); + } + at_mappings[(int)((unsigned char) *p)] = 1; + at_mapto[mc] = *p; + ++mc; + *at_strings_end = (char)( (unsigned char) (strlen(m)) ); + strcpy(++at_strings_end, m+1); + at_strings_end += (unsigned char) at_strings_end[-1]; + + verbose_msg(VDETAIL,"@mapping: \"%s\" to '%c'\n", m, *p); + + if (((p = strtok(NULL, " \t\n")) != NULL) && (*p != '#')) { + fprintf(stderr,"ignoring trailing text: %s...\n", p); + } + *line_buf = 0; + continue; + } + break; + } while (1); + +#if 0 + { + p = at_strings; + + if (!*p) { + verbose_msg(VDETAIL,"no @ strings\n"); + return; + } + + do { + verbose_msg(VDETAIL,"%s\n", p+1); + p += 1 + (unsigned char) *p; + } while (*p); + } +#endif +} + +static void read_enable_disable(void) +{ + char *p; + + do { + if (!(p = strtok(line_buf, " =\t\n")) || (*p == '#')) { + if (!fgets(line_buf, sizeof(line_buf), fp)) { + if (ferror(fp)) { + error_msg("reading file"); + } + return; /* EOF */ + } + if ((*line_buf == '#') && (line_buf[1] == '-')) { + break; + } + continue; + } + if (!strcmp(p, "UTF-8")) { + if (!(p = strtok(NULL, " =\t\n")) + || ((toupper(*p) != 'Y') && (toupper(*p) != 'N'))) { + error_msg("missing or illegal UTF-8 setting"); + } + default_utf8 = (toupper(*p) == 'Y'); + verbose_msg(VINFO,"UTF-8 locales are %sabled\n", "dis\0en"+ (default_utf8 << 2)); + } else if (!strcmp(p, "8-BIT")) { + if (!(p = strtok(NULL, " =\t\n")) + || ((toupper(*p) != 'Y') && (toupper(*p) != 'N'))) { + error_msg("missing or illegal 8-BIT setting"); + } + default_8bit = (toupper(*p) == 'Y'); + verbose_msg(VINFO,"8-BIT locales are %sabled\n", "dis\0en" + (default_8bit << 2)); + } else { + break; + } + + if (((p = strtok(NULL, " \t\n")) != NULL) && (*p != '#')) { + fprintf(stderr,"ignoring trailing text: %s...\n", p); + } + *line_buf = 0; + continue; + + } while (1); +} + +#ifdef __LOCALE_DATA_CODESET_LIST + +static int find_codeset_num(const char *cs) +{ + int r = 2; + char *s = __LOCALE_DATA_CODESET_LIST; + + /* 7-bit is 1, UTF-8 is 2, 8-bits are > 2 */ + + if (strcmp(cs, "UTF-8") != 0) { + ++r; + while (*s && strcmp(__LOCALE_DATA_CODESET_LIST+ ((unsigned char) *s), cs)) { +/* verbose_msg(VDETAIL,"tried %s\n", __LOCALE_DATA_CODESET_LIST + ((unsigned char) *s)); */ + ++r; + ++s; + } + if (!*s) { + error_msg("unsupported codeset %s", cs); + } + } + return r; +} + +#else + +static int find_codeset_num(const char *cs) +{ + int r = 2; + + /* 7-bit is 1, UTF-8 is 2, 8-bits are > 2 */ + + if (strcmp(cs, "UTF-8") != 0) { + error_msg("unsupported codeset %s", cs); + } + return r; +} + +#endif + +static int find_at_string_num(const char *as) +{ + int i = 0; + char *p = at_strings; + + while (*p) { + if (!strcmp(p+1, as)) { + return i; + } + ++i; + p += 1 + (unsigned char) *p; + } + + error_msg("error: unmapped @string %s", as); +} + +static void read_locale_list(void) +{ + char *p; + char *s; + char *ln; /* locale name */ + char *ls; /* locale name ll_CC */ + char *as; /* at string */ + char *ds; /* dot string */ + char *cs; /* codeset */ + int i; + + typedef struct { + char *glibc_name; + char name[5]; + char dot_cs; /* 0 if no codeset specified */ + char cs; + } locale_entry; + + /* First the C locale. */ + locales[0].glibc_name = locales[0].name; + strncpy(locales[0].name,"C",5); + locales[0].dot_cs = 0; + locales[0].cs = 1; /* 7-bit encoding */ + ++num_locales; + + do { + if (!(p = strtok(line_buf, " \t\n")) || (*p == '#')) { + if (!fgets(line_buf, sizeof(line_buf), fp)) { + if (ferror(fp)) { + error_msg("reading file"); + } + return; /* EOF */ + } + if ((*line_buf == '#') && (line_buf[1] == '-')) { + break; + } + continue; + } + + s = glibc_locale_names; + for (i=0 ; i < num_locales ; i++) { + if (!strcmp(s+1, p)) { + break; + } + s += 1 + ((unsigned char) *s); + } + if (i < num_locales) { + fprintf(stderr,"ignoring duplicate locale name: %s", p); + *line_buf = 0; + continue; + } + + /* New locale, but don't increment num until codeset verified! */ + *s = (char)((unsigned char) (strlen(p) + 1)); + strcpy(s+1, p); + locales[num_locales].glibc_name = s+1; + ln = p; /* save locale name */ + + if (!(p = strtok(NULL, " \t\n"))) { + error_msg("missing codeset for locale %s", ln); + } + cs = p; + i = find_codeset_num(p); + if ((i == 2) && !default_utf8) { + fprintf(stderr,"ignoring UTF-8 locale %s\n", ln); + *line_buf = 0; + continue; + } else if ((i > 2) && !default_8bit) { + fprintf(stderr,"ignoring 8-bit codeset locale %s\n", ln); + *line_buf = 0; + continue; + } + locales[num_locales].cs = (char)((unsigned char) i); + + if (((p = strtok(NULL, " \t\n")) != NULL) && (*p != '#')) { + verbose_msg(VINFO,"ignoring trailing text: %s...\n", p); + } + + /* Now go back to locale string for .codeset and @modifier */ + as = strtok(ln, "@"); + if (as) { + as = strtok(NULL, "@"); + } + ds = strtok(ln, "."); + if (ds) { + ds = strtok(NULL, "."); + } + ls = ln; + + if ((strlen(ls) != 5) || (ls[2] != '_')) { + error_msg("illegal locale name %s", ls); + } + + i = 0; /* value for unspecified codeset */ + if (ds) { + i = find_codeset_num(ds); + if ((i == 2) && !default_utf8) { + fprintf(stderr,"ignoring UTF-8 locale %s\n", ln); + *line_buf = 0; + continue; + } else if ((i > 2) && !default_8bit) { + fprintf(stderr,"ignoring 8-bit codeset locale %s\n", ln); + *line_buf = 0; + continue; + } + } + locales[num_locales].dot_cs = (char)((unsigned char) i); + + if (as) { + i = find_at_string_num(as); + ls[2] = at_mapto[i]; + } + memcpy(locales[num_locales].name, ls, 5); +/* verbose_msg(VDETAIL,"locale: %5.5s %2d %2d %s\n", */ +/* locales[num_locales].name, */ +/* locales[num_locales].cs, */ +/* locales[num_locales].dot_cs, */ +/* locales[num_locales].glibc_name */ +/* ); */ + ++num_locales; + *line_buf = 0; + } while (1); +} + +static int le_cmp(const void *a, const void *b) +{ + const locale_entry *p; + const locale_entry *q; + int r; + + p = (const locale_entry *) a; + q = (const locale_entry *) b; + + if (!(r = p->name[0] - q->name[0]) + && !(r = p->name[1] - q->name[1]) + && !(r = p->name[3] - q->name[3]) + && !(r = p->name[4] - q->name[4]) + && !(r = p->name[2] - q->name[2]) + && !(r = -(p->cs - q->cs)) + ) { + r = -(p->dot_cs - q->dot_cs); + /* Reverse the ordering of the codesets so UTF-8 comes last. + * Work-around (hopefully) for glibc bug affecting at least + * the euro currency symbol. */ + } + + return r; +} + +int main(int argc, char **argv) +{ + char *output_file = NULL; + + while (--argc) { + ++argv; + if (!strcmp(*argv, "-o")) { + --argc; + output_file = strdup(*++argv); + } else if (!strcmp(*argv, "-v")) { + verbose++; + } else if (!(fp = fopen(*argv, "r"))) { +no_inputfile: + error_msg("missing filename or file!"); + } + } + if (fp == NULL) + goto no_inputfile; + if (output_file == NULL) + output_file = strdup("locale_tables.h"); + + at_strings_end = at_strings; + + read_at_mappings(); + read_enable_disable(); + read_locale_list(); + + fclose(fp); + + /* handle C locale specially */ + qsort(locales+1, num_locales-1, sizeof(locale_entry), le_cmp); + +#if 0 + for (i=0 ; i < num_locales ; i++) { + verbose_msg(VDETAIL,"locale: %5.5s %2d %2d %s\n", + locales[i].name, + locales[i].cs, + locales[i].dot_cs, + locales[i].glibc_name + ); + } +#endif + if (argc == 3) + output_file = *++argv; + if (output_file == NULL || !(ofp = fopen(output_file, "w"))) { + error_msg("cannot open output file '%s'!", output_file); + } + + do_lc_time(); + do_lc_numeric(); + do_lc_monetary(); + do_lc_messages(); + do_lc_ctype(); + + do_locale_names(); + + fclose(ofp); + + verbose_msg(VINFO, "total data size = %d\n", total_size); + verbose_msg(VDETAIL, "null count = %d\n", null_count); + + return EXIT_SUCCESS; +} + +static char *idx[10000]; +static char buf[100000]; +static char *last; +static int uniq; + +static int addblock(const char *s, size_t n) /* l includes nul terminator */ +{ + int j; + + if (!s) { + ++null_count; + return 0; + } + + for (j=0 ; (j < uniq) && (idx[j] + n < last) ; j++) { + if (!memcmp(s, idx[j], n)) { + return idx[j] - buf; + } + } + if (uniq >= sizeof(idx)) { + error_msg("too many uniq strings!"); + } + if (last + n >= buf + sizeof(buf)) { + error_msg("need to increase size of buf!"); + } + + idx[uniq] = last; + ++uniq; + memcpy(last, s, n); + last += n; + return idx[uniq - 1] - buf; +} + +static int addstring(const char *s) +{ + int j; + size_t l; + + if (!s) { + ++null_count; + return 0; + } + + for (j=0 ; j < uniq ; j++) { + if (!strcmp(s, idx[j])) { + return idx[j] - buf; + } + } + if (uniq >= sizeof(idx)) { + error_msg("too many uniq strings!"); + } + l = strlen(s) + 1; + if (last + l >= buf + sizeof(buf)) { + error_msg("need to increase size of buf!"); + } + + idx[uniq] = last; + ++uniq; + strcpy(last, s); + last += l; + return idx[uniq - 1] - buf; +} + +#define DO_LC_COMMON(CATEGORY) \ + verbose_msg(VDETAIL, "buf-size=%d uniq=%d rows=%d\n", \ + (int)(last - buf), uniq, lc_##CATEGORY##_uniq); \ + verbose_msg(VDETAIL, "total = %d + %d * %d + %d = %d\n", \ + num_locales, lc_##CATEGORY##_uniq, NUM_NL_##CATEGORY, (int)(last - buf), \ + i = num_locales + lc_##CATEGORY##_uniq*NUM_NL_##CATEGORY + (int)(last - buf)); \ + total_size += i; \ + dump_table8c("__lc_" #CATEGORY "_data", buf, (int)(last - buf)); \ + for (i=0 ; i < lc_##CATEGORY##_uniq ; i++) { \ + m = locales[i].lc_##CATEGORY##_row; \ + for (k=0 ; k < NUM_NL_##CATEGORY ; k++) { \ + buf[NUM_NL_##CATEGORY*i + k] = (char)((unsigned char) lc_##CATEGORY##_uniq_X[i][k]); \ + } \ + } \ + dump_table8("__lc_" #CATEGORY "_rows", buf, lc_##CATEGORY##_uniq * NUM_NL_##CATEGORY); \ + buf16[0] =0; \ + for (i=0 ; i < NUM_NL_##CATEGORY - 1 ; i++) { \ + buf16[i+1] = buf16[i] + lc_##CATEGORY##_count[i]; \ + } \ + dump_table16("__lc_" #CATEGORY "_item_offsets", buf16, NUM_NL_##CATEGORY); \ + m = 0; \ + for (k=0 ; k < NUM_NL_##CATEGORY ; k++) { \ + for (i=0 ; i < lc_##CATEGORY##_count[k] ; i++) { \ + buf16[m] = lc_##CATEGORY##_item[k][i]; \ + ++m; \ + } \ + } \ + dump_table16("__lc_" #CATEGORY "_item_idx", buf16, m); + + +#define DL_LC_LOOPTAIL(CATEGORY) \ + if (k > NUM_NL_##CATEGORY) { \ + error_msg("lc_" #CATEGORY " nl_item count > %d!", NUM_NL_##CATEGORY); \ + } \ + { \ + int r; \ + for (r=0 ; r < lc_##CATEGORY##_uniq ; r++) { \ + if (!memcmp(lc_##CATEGORY##_uniq_X[lc_##CATEGORY##_uniq], \ + lc_##CATEGORY##_uniq_X[r], NUM_NL_##CATEGORY)) { \ + break; \ + } \ + } \ + if (r == lc_##CATEGORY##_uniq) { /* new locale row */ \ + ++lc_##CATEGORY##_uniq; \ + if (lc_##CATEGORY##_uniq > 255) { \ + error_msg("too many unique lc_" #CATEGORY " rows!"); \ + } \ + } \ + locales[i].lc_##CATEGORY##_row = r; \ + } + + + +static int buf16[100*256]; + +static void dump_table8(const char *name, const char *tbl, int len) +{ + int i; + + fprintf(ofp, "#define %s_LEN\t\t%d\n", name, len); + fprintf(ofp, "static const unsigned char %s[%d] = {", name, len); + for (i=0 ; i < len ; i++) { + if ((i % 12) == 0) { + fprintf(ofp, "\n\t"); + } + fprintf(ofp, "%#4x, ", (int)((unsigned char) tbl[i])); + } + fprintf(ofp, "\n};\n\n"); +} + +#define __C_isdigit(c) \ + ((sizeof(c) == sizeof(char)) \ + ? (((unsigned char)((c) - '0')) < 10) \ + : (((unsigned int)((c) - '0')) < 10)) +#define __C_isalpha(c) \ + ((sizeof(c) == sizeof(char)) \ + ? (((unsigned char)(((c) | 0x20) - 'a')) < 26) \ + : (((unsigned int)(((c) | 0x20) - 'a')) < 26)) +#define __C_isalnum(c) (__C_isalpha(c) || __C_isdigit(c)) + +static void dump_table8c(const char *name, const char *tbl, int len) +{ + int i; + + fprintf(ofp, "#define %s_LEN\t\t%d\n", name, len); + fprintf(ofp, "static const unsigned char %s[%d] = {", name, len); + for (i=0 ; i < len ; i++) { + if ((i % 12) == 0) { + fprintf(ofp, "\n\t"); + } + if (__C_isalnum(tbl[i]) || (tbl[i] == ' ')) { + fprintf(ofp, " '%c', ", (int)((unsigned char) tbl[i])); + } else { + fprintf(ofp, "%#4x, ", (int)((unsigned char) tbl[i])); + } + } + fprintf(ofp, "\n};\n\n"); +} + +static void dump_table16(const char *name, const int *tbl, int len) +{ + int i; + + fprintf(ofp, "#define %s_LEN\t\t%d\n", name, len); + fprintf(ofp, "static const uint16_t %s[%d] = {", name, len); + for (i=0 ; i < len ; i++) { + if ((i % 8) == 0) { + fprintf(ofp, "\n\t"); + } + if (tbl[i] != (uint16_t) tbl[i]) { + error_msg("falls outside uint16 range!"); + } + fprintf(ofp, "%#6x, ", tbl[i]); + } + fprintf(ofp, "\n};\n\n"); +} + + +#define NUM_NL_time 50 + +static int lc_time_item[NUM_NL_time][256]; +static int lc_time_count[NUM_NL_time]; +static unsigned char lc_time_uniq_X[700][NUM_NL_time]; +static int lc_time_uniq; + +#define DO_NL_S(X) lc_time_S(X, k++) + +static void lc_time_S(int X, int k) +{ + size_t len; + int j, m; + const char *s = nl_langinfo(X); + const char *p; + static const char nulbuf[] = ""; + + if (X == ALT_DIGITS) { + len = 1; + if (!s) { + s = nulbuf; + } + if (*s) { + p = s; + for (j = 0 ; j < 100 ; j++) { + while (*p) { + ++p; + } + ++p; + } + len = p - s; + } + j = addblock(s, len); +/* if (len > 1) verbose_msg(VDETAIL, "alt_digit: called addblock with len %zd\n", len); */ + } else if (X == ERA) { + if (!s) { + s = nulbuf; + } + p = s; + while (*p) { + while (*p) { + ++p; + } + ++p; + } + ++p; + j = addblock(s, p - s); +/* if (p-s > 1) verbose_msg(VDETAIL, "era: called addblock with len %d\n", p-s); */ + } else { + j = addstring(s); + } + for (m=0 ; m < lc_time_count[k] ; m++) { + if (lc_time_item[k][m] == j) { + break; + } + } + if (m == lc_time_count[k]) { /* new for this nl_item */ + if (m > 255) { + error_msg("too many nl_item %d entries in lc_time", k); + } + lc_time_item[k][m] = j; + ++lc_time_count[k]; + } + lc_time_uniq_X[lc_time_uniq][k] = m; +} + +static void do_lc_time(void) +{ + int i, k, m; + + last = buf+1; + uniq = 1; + *buf = 0; + *idx = buf; + + for (i=0 ; i < num_locales ; i++) { + k = 0; + + if (!setlocale(LC_ALL, locales[i].glibc_name)) { + verbose_msg(VDETAIL, "setlocale(LC_ALL,%s) failed!\n", + locales[i].glibc_name); + } + + DO_NL_S(ABDAY_1); + DO_NL_S(ABDAY_2); + DO_NL_S(ABDAY_3); + DO_NL_S(ABDAY_4); + DO_NL_S(ABDAY_5); + DO_NL_S(ABDAY_6); + DO_NL_S(ABDAY_7); + + DO_NL_S(DAY_1); + DO_NL_S(DAY_2); + DO_NL_S(DAY_3); + DO_NL_S(DAY_4); + DO_NL_S(DAY_5); + DO_NL_S(DAY_6); + DO_NL_S(DAY_7); + + DO_NL_S(ABMON_1); + DO_NL_S(ABMON_2); + DO_NL_S(ABMON_3); + DO_NL_S(ABMON_4); + DO_NL_S(ABMON_5); + DO_NL_S(ABMON_6); + DO_NL_S(ABMON_7); + DO_NL_S(ABMON_8); + DO_NL_S(ABMON_9); + DO_NL_S(ABMON_10); + DO_NL_S(ABMON_11); + DO_NL_S(ABMON_12); + + DO_NL_S(MON_1); + DO_NL_S(MON_2); + DO_NL_S(MON_3); + DO_NL_S(MON_4); + DO_NL_S(MON_5); + DO_NL_S(MON_6); + DO_NL_S(MON_7); + DO_NL_S(MON_8); + DO_NL_S(MON_9); + DO_NL_S(MON_10); + DO_NL_S(MON_11); + DO_NL_S(MON_12); + + DO_NL_S(AM_STR); + DO_NL_S(PM_STR); + + DO_NL_S(D_T_FMT); + DO_NL_S(D_FMT); + DO_NL_S(T_FMT); + DO_NL_S(T_FMT_AMPM); + DO_NL_S(ERA); + + DO_NL_S(ERA_YEAR); /* non SuSv3 */ + DO_NL_S(ERA_D_FMT); + DO_NL_S(ALT_DIGITS); + DO_NL_S(ERA_D_T_FMT); + DO_NL_S(ERA_T_FMT); + + DL_LC_LOOPTAIL(time) + } + + DO_LC_COMMON(time) +} + +#undef DO_NL_S + +#define NUM_NL_numeric 3 + +static int lc_numeric_item[NUM_NL_numeric][256]; +static int lc_numeric_count[NUM_NL_numeric]; +static unsigned char lc_numeric_uniq_X[700][NUM_NL_numeric]; +static int lc_numeric_uniq; + +#define DO_NL_S(X) lc_numeric_S(X, k++) + +static void lc_numeric_S(int X, int k) +{ + int j, m; + char buf[256]; + char *e; + char *s; + char c; + + s = nl_langinfo(X); + if (X == GROUPING) { + if (s) { + if ((*s == CHAR_MAX) || (*s == -1)) { /* stupid glibc... :-( */ + s = ""; + } + e = s; + c = 0; + while (*e) { /* find end of string */ + if (*e == CHAR_MAX) { + c = CHAR_MAX; + ++e; + break; + } + ++e; + } + if ((e - s) > sizeof(buf)) { + error_msg("grouping specifier too long"); + } + strncpy(buf, s, (e-s)); + e = buf + (e-s); + *e = 0; /* Make sure we're null-terminated. */ + + if (c != CHAR_MAX) { /* remove duplicate repeats */ + while (e > buf) { + --e; + if (*e != e[-1]) { + break; + } + } + *++e = 0; + } + s = buf; + } + } + j = addstring(s); + for (m=0 ; m < lc_numeric_count[k] ; m++) { + if (lc_numeric_item[k][m] == j) { + break; + } + } + if (m == lc_numeric_count[k]) { /* new for this nl_item */ + if (m > 255) { + error_msg("too many nl_item %d entries in lc_numeric", k); + } + lc_numeric_item[k][m] = j; + ++lc_numeric_count[k]; + } +/* verbose_msg(VDETAIL, "\\x%02x", m); */ + lc_numeric_uniq_X[lc_numeric_uniq][k] = m; +} + +static void do_lc_numeric(void) +{ + int i, k, m; + + last = buf+1; + uniq = 1; + *buf = 0; + *idx = buf; + + for (i=0 ; i < num_locales ; i++) { + k = 0; + + if (!setlocale(LC_ALL, locales[i].glibc_name)) { + verbose_msg(VDETAIL,"setlocale(LC_ALL,%s) failed!\n", + locales[i].glibc_name); + } + + DO_NL_S(RADIXCHAR); /* DECIMAL_POINT */ + DO_NL_S(THOUSEP); /* THOUSANDS_SEP */ + DO_NL_S(GROUPING); + + DL_LC_LOOPTAIL(numeric) + } + + DO_LC_COMMON(numeric) +} + +#undef DO_NL_S + +#define NUM_NL_monetary (7+14+1) + +static int lc_monetary_item[NUM_NL_monetary][256]; +static int lc_monetary_count[NUM_NL_monetary]; +static unsigned char lc_monetary_uniq_X[700][NUM_NL_monetary]; +static int lc_monetary_uniq; + +#define DO_NL_S(X) lc_monetary_S(X, k++) + +/* #define DO_NL_C(X) verbose_msg(VDETAIL,"%#02x", (int)(unsigned char)(*nl_langinfo(X))); */ +#define DO_NL_C(X) lc_monetary_C(X, k++) + +static void lc_monetary_C(int X, int k) +{ + int j, m; + char c_buf[2]; + +#warning fix the char entries for monetary... target signedness of char may be different! + + c_buf[1] = 0; + c_buf[0] = *nl_langinfo(X); + j = addstring(c_buf); + for (m=0 ; m < lc_monetary_count[k] ; m++) { + if (lc_monetary_item[k][m] == j) { + break; + } + } + if (m == lc_monetary_count[k]) { /* new for this nl_item */ + if (m > 255) { + error_msg("too many nl_item %d entries in lc_monetary", k); + } + lc_monetary_item[k][m] = j; + ++lc_monetary_count[k]; + } +/* verbose_msg(VDETAIL,"\\x%02x", m); */ + lc_monetary_uniq_X[lc_monetary_uniq][k] = m; +} + + +static void lc_monetary_S(int X, int k) +{ + int j, m; + char buf[256]; + char *e; + char *s; + char c; + + s = nl_langinfo(X); + if (X == MON_GROUPING) { + if (s) { + if ((*s == CHAR_MAX) || (*s == -1)) { /* stupid glibc... :-( */ + s = ""; + } + e = s; + c = 0; + while (*e) { /* find end of string */ + if (*e == CHAR_MAX) { + c = CHAR_MAX; + ++e; + break; + } + ++e; + } + if ((e - s) > sizeof(buf)) { + error_msg("mon_grouping specifier too long"); + } + strncpy(buf, s, (e-s)); + e = buf + (e-s); + *e = 0; /* Make sure we're null-terminated. */ + + if (c != CHAR_MAX) { /* remove duplicate repeats */ + while (e > buf) { + --e; + if (*e != e[-1]) { + break; + } + } + *++e = 0; + } + s = buf; + } + } + j = addstring(s); + for (m=0 ; m < lc_monetary_count[k] ; m++) { + if (lc_monetary_item[k][m] == j) { + break; + } + } + if (m == lc_monetary_count[k]) { /* new for this nl_item */ + if (m > 255) { + error_msg("too many nl_item %d entries in lc_monetary", k); + } + lc_monetary_item[k][m] = j; + ++lc_monetary_count[k]; + } +/* verbose_msg(VDETAIL,"\\x%02x", m); */ + lc_monetary_uniq_X[lc_monetary_uniq][k] = m; +} + +static void do_lc_monetary(void) +{ + int i, k, m; + + last = buf+1; + uniq = 1; + *buf = 0; + *idx = buf; + + for (i=0 ; i < num_locales ; i++) { + k = 0; + + if (!setlocale(LC_ALL, locales[i].glibc_name)) { + verbose_msg(VDETAIL,"setlocale(LC_ALL,%s) failed!\n", + locales[i].glibc_name); + } + + + /* non SUSv3 */ + DO_NL_S(INT_CURR_SYMBOL); + DO_NL_S(CURRENCY_SYMBOL); + DO_NL_S(MON_DECIMAL_POINT); + DO_NL_S(MON_THOUSANDS_SEP); + DO_NL_S(MON_GROUPING); + DO_NL_S(POSITIVE_SIGN); + DO_NL_S(NEGATIVE_SIGN); + DO_NL_C(INT_FRAC_DIGITS); + DO_NL_C(FRAC_DIGITS); + DO_NL_C(P_CS_PRECEDES); + DO_NL_C(P_SEP_BY_SPACE); + DO_NL_C(N_CS_PRECEDES); + DO_NL_C(N_SEP_BY_SPACE); + DO_NL_C(P_SIGN_POSN); + DO_NL_C(N_SIGN_POSN); + DO_NL_C(INT_P_CS_PRECEDES); + DO_NL_C(INT_P_SEP_BY_SPACE); + DO_NL_C(INT_N_CS_PRECEDES); + DO_NL_C(INT_N_SEP_BY_SPACE); + DO_NL_C(INT_P_SIGN_POSN); + DO_NL_C(INT_N_SIGN_POSN); + + DO_NL_S(CRNCYSTR); /* CURRENCY_SYMBOL */ + + DL_LC_LOOPTAIL(monetary) + } + + DO_LC_COMMON(monetary) +} + + +#undef DO_NL_S + +#define NUM_NL_messages 4 + +static int lc_messages_item[NUM_NL_messages][256]; +static int lc_messages_count[NUM_NL_messages]; +static unsigned char lc_messages_uniq_X[700][NUM_NL_messages]; +static int lc_messages_uniq; + +#define DO_NL_S(X) lc_messages_S(X, k++) + +static void lc_messages_S(int X, int k) +{ + int j, m; + j = addstring(nl_langinfo(X)); + for (m=0 ; m < lc_messages_count[k] ; m++) { + if (lc_messages_item[k][m] == j) { + break; + } + } + if (m == lc_messages_count[k]) { /* new for this nl_item */ + if (m > 255) { + error_msg("too many nl_item %d entries in lc_messages", k); + } + lc_messages_item[k][m] = j; + ++lc_messages_count[k]; + } +/* verbose_msg(VDETAIL, "\\x%02x", m); */ + lc_messages_uniq_X[lc_messages_uniq][k] = m; +} + +static void do_lc_messages(void) +{ + int i, k, m; + + last = buf+1; + uniq = 1; + *buf = 0; + *idx = buf; + + for (i=0 ; i < num_locales ; i++) { + k = 0; + + if (!setlocale(LC_ALL, locales[i].glibc_name)) { + verbose_msg(VDETAIL, "setlocale(LC_ALL,%s) failed!\n", + locales[i].glibc_name); + } + + DO_NL_S(YESEXPR); + DO_NL_S(NOEXPR); + DO_NL_S(YESSTR); + DO_NL_S(NOSTR); + + DL_LC_LOOPTAIL(messages) + } + + DO_LC_COMMON(messages) +} + +#undef DO_NL_S + +#define NUM_NL_ctype 10 + +static int lc_ctype_item[NUM_NL_ctype][256]; +static int lc_ctype_count[NUM_NL_ctype]; +static unsigned char lc_ctype_uniq_X[700][NUM_NL_ctype]; +static int lc_ctype_uniq; + +#define DO_NL_S(X) lc_ctype_S(X, k++) + +static void lc_ctype_S(int X, int k) +{ + int j, m; + j = addstring(nl_langinfo(X)); + for (m=0 ; m < lc_ctype_count[k] ; m++) { + if (lc_ctype_item[k][m] == j) { + break; + } + } + if (m == lc_ctype_count[k]) { /* new for this nl_item */ + if (m > 255) { + error_msg("too many nl_item %d entries in lc_ctype", k); + } + lc_ctype_item[k][m] = j; + ++lc_ctype_count[k]; + } +/* verbose_msg(VDETAIL, "\\x%02x", m); */ + lc_ctype_uniq_X[lc_ctype_uniq][k] = m; +} + +static void do_lc_ctype(void) +{ + int i, k, m; + + last = buf+1; + uniq = 1; + *buf = 0; + *idx = buf; + + for (i=0 ; i < num_locales ; i++) { + k = 0; + + if (!setlocale(LC_ALL, locales[i].glibc_name)) { + verbose_msg(VDETAIL, "setlocale(LC_ALL,%s) failed!\n", + locales[i].glibc_name); + } + + DO_NL_S(_NL_CTYPE_OUTDIGIT0_MB); + DO_NL_S(_NL_CTYPE_OUTDIGIT1_MB); + DO_NL_S(_NL_CTYPE_OUTDIGIT2_MB); + DO_NL_S(_NL_CTYPE_OUTDIGIT3_MB); + DO_NL_S(_NL_CTYPE_OUTDIGIT4_MB); + DO_NL_S(_NL_CTYPE_OUTDIGIT5_MB); + DO_NL_S(_NL_CTYPE_OUTDIGIT6_MB); + DO_NL_S(_NL_CTYPE_OUTDIGIT7_MB); + DO_NL_S(_NL_CTYPE_OUTDIGIT8_MB); + DO_NL_S(_NL_CTYPE_OUTDIGIT9_MB); + + DL_LC_LOOPTAIL(ctype) + } + + DO_LC_COMMON(ctype) +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/gen_mmap.c b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/gen_mmap.c new file mode 100644 index 00000000..1cf0bb9e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/gen_mmap.c @@ -0,0 +1,237 @@ +#include +#include +#include +#include +#include +#include + +#define WANT_DATA +#include "c8tables.h" + +/* #define Cctype_TBL_LEN 328 */ +/* #define Cuplow_TBL_LEN 400 */ +/* #define Cc2wc_TBL_LEN 1448 */ +/* #define Cwc2c_TBL_LEN 3744 */ + +#define WANT_WCctype_data +#define WANT_WCuplow_data +#define WANT_WCuplow_diff_data +/* #define WANT_WCcomb_data */ +/* #define WANT_WCwidth_data */ +#include "wctables.h" +#undef WANT_WCctype_data +#undef WANT_WCuplow_data +#undef WANT_WCuplow_diff_data +/* #undef WANT_WCcomb_data */ +/* #undef WANT_WCwidth_data */ + +/* #define WCctype_TBL_LEN (WCctype_II_LEN + WCctype_TI_LEN + WCctype_UT_LEN) */ +/* #define WCuplow_TBL_LEN (WCuplow_II_LEN + WCuplow_TI_LEN + WCuplow_UT_LEN) */ +/* #define WCuplow_diff_TBL_LEN (2 * WCuplow_diffs) */ +/* #define WCcomb_TBL_LEN (WCcomb_II_LEN + WCcomb_TI_LEN + WCcomb_UT_LEN) */ + +#include "locale_tables.h" + +#include "locale_mmap.h" + +/* #undef __PASTE2 */ +/* #define __PASTE2(A,B) A ## B */ +/* #undef __PASTE3 */ +/* #define __PASTE3(A,B,C) A ## B ## C */ + + +/* #define MAGIC_SIZE 64 */ + +/* #define COMMON_MMAP(X) \ */ +/* unsigned char __PASTE3(lc_,X,_data)[__PASTE3(__lc_,X,_data_LEN)]; */ + +/* #define COMMON_MMIDX(X) \ */ +/* unsigned char __PASTE3(lc_,X,_rows)[__PASTE3(__lc_,X,_rows_LEN)]; \ */ +/* uint16_t __PASTE3(lc_,X,_item_offsets)[__PASTE3(__lc_,X,_item_offsets_LEN)]; \ */ +/* uint16_t __PASTE3(lc_,X,_item_idx)[__PASTE3(__lc_,X,_item_idx_LEN)]; \ */ + +#define WRITE_COMMON_MMAP(X) \ + fseek(fp, (long) offsetof(__locale_mmap_t, __PASTE3(lc_,X,_data)), SEEK_SET); \ + for (i=0 ; i < __PASTE3(__lc_,X,_data_LEN) ; i++) { \ + putc(__PASTE3(__lc_,X,_data)[i], fp); \ + } + +#define WRITE_COMMON_MMIDX(X) \ + fseek(fp, (long) offsetof(__locale_mmap_t, __PASTE3(lc_,X,_rows)), SEEK_SET); \ + for (i=0 ; i < __PASTE3(__lc_,X,_rows_LEN) ; i++) { \ + putc(__PASTE3(__lc_,X,_rows)[i], fp); \ + } \ + fseek(fp, (long) offsetof(__locale_mmap_t, __PASTE3(lc_,X,_item_offsets)), SEEK_SET); \ + for (i=0 ; i < __PASTE3(__lc_,X,_item_offsets_LEN) ; i++) { \ + putc( ((unsigned char *) &(__PASTE3(__lc_,X,_item_offsets)[i]))[0], fp); \ + putc( ((unsigned char *) &(__PASTE3(__lc_,X,_item_offsets)[i]))[1], fp); \ + } \ + fseek(fp, (long) offsetof(__locale_mmap_t, __PASTE3(lc_,X,_item_idx)), SEEK_SET); \ + for (i=0 ; i < __PASTE3(__lc_,X,_item_idx_LEN) ; i++) { \ + putc( ((unsigned char *) &(__PASTE3(__lc_,X,_item_idx)[i]))[0], fp); \ + putc( ((unsigned char *) &(__PASTE3(__lc_,X,_item_idx)[i]))[1], fp); \ + } + +#define WRITE_WC_DATA(X) \ + fseek(fp, (long) offsetof(__locale_mmap_t, __PASTE2(tblw,X)), SEEK_SET); \ + for (i=0 ; i < __PASTE3(WC,X,_TBL_LEN) ; i++) { \ + putc(__PASTE3(WC,X,_data)[i], fp); \ + } + +#define WRITE_WC_I16_DATA(X) \ + fseek(fp, (long) offsetof(__locale_mmap_t, __PASTE2(tblw,X)), SEEK_SET); \ + for (i=0 ; i < __PASTE3(WC,X,_TBL_LEN) ; i++) { \ + putc( ((unsigned char *) &(__PASTE3(WC,X,_data)[i]))[0], fp); \ + putc( ((unsigned char *) &(__PASTE3(WC,X,_data)[i]))[1], fp); \ + } + +#define WRITE_C_DATA(X) \ + fseek(fp, (long) offsetof(__locale_mmap_t, __PASTE2(tbl8,X)), SEEK_SET); \ + for (i=0 ; i < __PASTE3(C,X,_TBL_LEN) ; i++) { \ + putc(__PASTE3(C,X,_data)[i], fp); \ + } + +#define WRITE_C_U16_DATA(X) \ + fseek(fp, (long) offsetof(__locale_mmap_t, __PASTE2(tbl8,X)), SEEK_SET); \ + for (i=0 ; i < __PASTE3(C,X,_TBL_LEN) ; i++) { \ + putc( ((unsigned char *) &(__PASTE3(C,X,_data)[i]))[0], fp); \ + putc( ((unsigned char *) &(__PASTE3(C,X,_data)[i]))[1], fp); \ + } + +/**********************************************************************/ + +#define COMMON_OFFSETS(X) \ + offsetof(__locale_mmap_t, __PASTE3(lc_,X,_rows)), \ + offsetof(__locale_mmap_t, __PASTE3(lc_,X,_item_offsets)), \ + offsetof(__locale_mmap_t, __PASTE3(lc_,X,_item_idx)), \ + offsetof(__locale_mmap_t, __PASTE3(lc_,X,_data)) \ + + +static const size_t common_tbl_offsets[CATEGORIES*4] = { + 0, 0, 0, 0, /* ctype */ + COMMON_OFFSETS(numeric), + COMMON_OFFSETS(monetary), + COMMON_OFFSETS(time), + 0, 0, 0, 0, /* collate */ + COMMON_OFFSETS(messages), +}; + + + + + +int main(void) +{ + FILE *fp; + size_t i; + unsigned char *p; + + if (!(fp = fopen("locale.mmap", "w"))) { + printf("cannot open locale.mmap for writing!"); + return EXIT_FAILURE; + } + + for (i=0 ; i < sizeof(__locale_mmap_t) ; i++) { + putc(0, fp); /* Zero out the file. */ + } + +#ifdef __CTYPE_HAS_8_BIT_LOCALES + WRITE_C_DATA(ctype); + WRITE_C_DATA(uplow); +#ifdef __WCHAR_ENABLED + WRITE_C_U16_DATA(c2wc); + WRITE_C_DATA(wc2c); + /* translit */ +#endif /* __WCHAR_ENABLED */ +#endif /* __CTYPE_HAS_8_BIT_LOCALES */ + +#ifdef __WCHAR_ENABLED + WRITE_WC_DATA(ctype); + WRITE_WC_DATA(uplow); + WRITE_WC_I16_DATA(uplow_diff); +/* WRITE_WC_DATA(comb); */ + /* width?? */ +#endif /* __WCHAR_ENABLED */ + + WRITE_COMMON_MMAP(numeric); + WRITE_COMMON_MMAP(monetary); + WRITE_COMMON_MMAP(time); + /* TODO -- collate*/ + WRITE_COMMON_MMAP(messages); + +#ifdef __CTYPE_HAS_8_BIT_LOCALES + fseek(fp, (long) offsetof(__locale_mmap_t, codeset_8_bit), SEEK_SET); \ + p = (unsigned char *) codeset_8_bit; + for (i=0 ; i < sizeof(codeset_8_bit) ; i++) { + putc(p[i], fp); + } +#endif /* __CTYPE_HAS_8_BIT_LOCALES */ + + WRITE_COMMON_MMIDX(numeric); + WRITE_COMMON_MMIDX(monetary); + WRITE_COMMON_MMIDX(time); + /* TODO -- collate*/ + WRITE_COMMON_MMIDX(messages); + + fseek(fp, (long) offsetof(__locale_mmap_t, lc_common_item_offsets_LEN), SEEK_SET); + putc(1, fp); /* ctype -- (codeset) handled specially */ + putc(__lc_numeric_item_offsets_LEN, fp); + putc(__lc_monetary_item_offsets_LEN, fp); + putc(__lc_time_item_offsets_LEN, fp); + putc(0, fp); /* collate */ + putc(__lc_messages_item_offsets_LEN, fp); + + fseek(fp, (long) offsetof(__locale_mmap_t, lc_common_tbl_offsets), SEEK_SET); + for (i=0 ; i < sizeof(common_tbl_offsets) ; i++) { + putc(((unsigned char *)common_tbl_offsets)[i], fp); + } + +#ifdef NUM_LOCALES + fseek(fp, (long) offsetof(__locale_mmap_t, locales), SEEK_SET); + for (i=0 ; i < (NUM_LOCALES * WIDTH_LOCALES) ; i++) { + putc(__locales[i], fp); + } + + fseek(fp, (long) offsetof(__locale_mmap_t, locale_names5), SEEK_SET); + for (i=0 ; i < 5 * NUM_LOCALE_NAMES ; i++) { + putc(__locale_names5[i], fp); + } + +#ifdef LOCALE_AT_MODIFIERS_LENGTH + fseek(fp, (long) offsetof(__locale_mmap_t, locale_at_modifiers), SEEK_SET); + for (i=0 ; i < LOCALE_AT_MODIFIERS_LENGTH ; i++) { + putc(__locale_at_modifiers[i], fp); + } +#endif /* LOCALE_AT_MODIFIERS_LENGTH */ +#endif /* NUM_LOCALES */ + + fseek(fp, (long) offsetof(__locale_mmap_t, lc_names), SEEK_SET); + for (i=0 ; i < lc_names_LEN ; i++) { + putc(lc_names[i], fp); + } + +#ifdef __CTYPE_HAS_8_BIT_LOCALES + fseek(fp, (long) offsetof(__locale_mmap_t, codeset_list), SEEK_SET); + for (i=0 ; i < sizeof(CODESET_LIST) ; i++) { + putc((unsigned char)(CODESET_LIST[i]), fp); + } +#endif /* __CTYPE_HAS_8_BIT_LOCALES */ + + + if (ferror(fp) || (fclose(fp) == EOF)) { + printf("error - stream in error state or fclose failed!"); + return EXIT_FAILURE; + } + + printf("sizeof(__locale_mmap_t) = %zd\n", sizeof(__locale_mmap_t)); + + return EXIT_SUCCESS; +} + +/* TODO: + * collate data (8-bit weighted single char only) + * @ mappings! + * codeset list? yes, since we'll want to be able to inspect them... + * that means putting some header stuff in magic + * fix ctype LEN defines in gen_c8tables + */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/gen_wc8bit.c b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/gen_wc8bit.c new file mode 100644 index 00000000..a861caac --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/gen_wc8bit.c @@ -0,0 +1,732 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include + +#ifndef _CTYPE_H +#define _CTYPE_H +#endif +#ifndef _WCTYPE_H +#define _WCTYPE_H +#endif +#include "include/bits/uClibc_ctype.h" + +/* TODO: maybe support -v like gen_wctype.c */ +#define verbose_msg(msg...) if (verbose) fprintf(stderr, msg) + +/* #define CTYPE_PACKED */ +#define UPLOW_IDX_SHIFT 3 +/* best if 2 unpacked or 3 packed */ +#define CTYPE_IDX_SHIFT 3 +/* 3 or 4 are very similar */ +#define C2WC_IDX_SHIFT 3 + +#define CTYPE_IDX_LEN (128 >> (CTYPE_IDX_SHIFT)) +#define UPLOW_IDX_LEN (128 >> (UPLOW_IDX_SHIFT)) +#define C2WC_IDX_LEN (128 >> (C2WC_IDX_SHIFT)) + +/* #ifdef CTYPE_PACKED */ +/* #define CTYPE_ROW_LEN (1 << ((CTYPE_IDX_SHIFT)-1)) */ +/* #else */ +#define CTYPE_ROW_LEN (1 << (CTYPE_IDX_SHIFT)) +/* #endif */ +#define UPLOW_ROW_LEN (1 << (UPLOW_IDX_SHIFT)) +#define C2WC_ROW_LEN (1 << (C2WC_IDX_SHIFT)) + + + +#define MAX_WCHAR (0x2600-1) + +static unsigned char ctype_tbl[256 * CTYPE_ROW_LEN]; +static unsigned char uplow_tbl[256 * UPLOW_ROW_LEN]; +#ifdef DO_WIDE_CHAR +static unsigned short c2wc_tbl[256 * C2WC_ROW_LEN]; +#endif +static unsigned char tt[MAX_WCHAR+1]; +static unsigned char ti[MAX_WCHAR+1]; +static unsigned char xi[MAX_WCHAR+1]; + +static int n_ctype_rows; +static int n_uplow_rows; +#ifdef DO_WIDE_CHAR +static int n_c2wc_rows; +#endif +static int tt_num; +static int ti_num; + +#define RANGE MAX_WCHAR + +#define TT_SHIFT 4 +#define TI_SHIFT 4 + +#define II_LEN ((MAX_WCHAR+1) >> (TT_SHIFT+TI_SHIFT)) + +typedef struct { + unsigned long c2w[256]; + unsigned char w2c[MAX_WCHAR]; + unsigned char ii[II_LEN]; + unsigned char ctype_idx[CTYPE_IDX_LEN]; + unsigned char uplow_idx[UPLOW_IDX_LEN]; + unsigned char c2wc_idx[C2WC_IDX_LEN]; +} charset_data; + +int main(int argc, char **argv) +{ + FILE *fp; + charset_data csd[30]; + unsigned long max_wchar; + unsigned char *p; + int numsets; + int i; + int j; + char buf[80]; + unsigned char row[256]; +#ifdef DO_WIDE_CHAR + unsigned short wrow[256]; +#endif + char codeset_list[500]; + char codeset_index[30]; + int codeset_list_end = 0; + int total_size = 0; + + if (!setlocale(LC_CTYPE, "en_US.UTF-8")) { + /* Silly foreigners disabling en_US locales */ + FILE *fp = popen("locale -a", "r"); + if (!fp) + goto locale_failure; + + while (!feof(fp)) { + char buf[256]; + size_t len; + + if (fgets(buf, sizeof(buf) - 10, fp) == NULL) + goto locale_failure; + + len = strlen(buf); + if (len > 0 && buf[len - 1] == '\n') + buf[--len] = '\0'; + if (len < 5 || strcasecmp(&buf[len-5], ".UTF8") != 0) + strcat(buf, ".UTF8"); + if (setlocale(LC_CTYPE, buf)) + goto locale_success; + } + + locale_failure: + printf("could not find a UTF8 locale ... please enable en_US.UTF-8\n"); + return EXIT_FAILURE; + locale_success: + pclose(fp); + } + +#if 0 + if (argc == 1) { + /* User requested 8-bit codesets, but didn't list any... */ + /* Allow to build, just so this feature can be left on in config. */ + printf("#ifdef __CTYPE_HAS_8_BIT_LOCALES\n"); + printf("#warning ignoring 8 bit codesets request" + " as no codesets specified.\n"); + printf("#endif\n"); + printf("#undef __CTYPE_HAS_8_BIT_LOCALES\n\n"); + + printf("#define __LOCALE_DATA_NUM_CODESETS\t\t0\n"); + printf("#define __LOCALE_DATA_CODESET_LIST\t\t\"\"\n"); + return EXIT_SUCCESS; + } + +/* printf("#define __CTYPE_HAS_8_BIT_LOCALES\t1\n\n"); */ + printf("#ifdef __CTYPE_HAS_8_BIT_LOCALES\n\n"); +#endif + + if (argc == 1) { + printf("#undef __CTYPE_HAS_8_BIT_LOCALES\n\n"); + + printf("#define __LOCALE_DATA_NUM_CODESETS\t\t0\n"); + printf("#define __LOCALE_DATA_CODESET_LIST\t\t\"\"\n"); + } else { + printf("#define __CTYPE_HAS_8_BIT_LOCALES\t\t1\n\n"); + } + + printf("#define __LOCALE_DATA_Cctype_IDX_SHIFT\t%d\n", CTYPE_IDX_SHIFT); + printf("#define __LOCALE_DATA_Cctype_IDX_LEN\t\t%d\n", CTYPE_IDX_LEN); +#ifdef CTYPE_PACKED + printf("#define __LOCALE_DATA_Cctype_ROW_LEN\t\t%d\n", CTYPE_ROW_LEN >> 1); + printf("#define __LOCALE_DATA_Cctype_PACKED\t\t1\n"); +#else + printf("#define __LOCALE_DATA_Cctype_ROW_LEN\t\t%d\n", CTYPE_ROW_LEN); + printf("#undef __LOCALE_DATA_Cctype_PACKED\n"); +#endif + + printf("\n#define __LOCALE_DATA_Cuplow_IDX_SHIFT\t%d\n", UPLOW_IDX_SHIFT); + printf("#define __LOCALE_DATA_Cuplow_IDX_LEN\t\t%d\n", UPLOW_IDX_LEN); + printf("#define __LOCALE_DATA_Cuplow_ROW_LEN\t\t%d\n", UPLOW_ROW_LEN); + +#ifdef DO_WIDE_CHAR + printf("\n#define __LOCALE_DATA_Cc2wc_IDX_LEN\t\t%d\n", C2WC_IDX_LEN); + printf("#define __LOCALE_DATA_Cc2wc_IDX_SHIFT\t\t%d\n", C2WC_IDX_SHIFT); + printf("#define __LOCALE_DATA_Cc2wc_ROW_LEN\t\t%d\n", C2WC_ROW_LEN); +#endif + + printf("\ntypedef struct {\n"); + printf("\tunsigned char idx8ctype[%d];\n", CTYPE_IDX_LEN); + printf("\tunsigned char idx8uplow[%d];\n", UPLOW_IDX_LEN); +#ifdef DO_WIDE_CHAR + printf("\tunsigned char idx8c2wc[%d];\n", C2WC_IDX_LEN); + printf("\tunsigned char idx8wc2c[%d];\n", II_LEN); +#endif + printf("} __codeset_8_bit_t;\n\n"); + + printf("#ifdef WANT_DATA\n\n"); + printf("static const __codeset_8_bit_t codeset_8_bit[%d] = {\n", argc-1); + + max_wchar = 0x7f; + numsets = 0; + codeset_index[0] = 0; + while (--argc) { + if (!(fp = fopen(*++argv,"r"))) { + fprintf(stderr, "cannot open file \"%s\"\n", *argv); + return EXIT_FAILURE; + } + fprintf(stderr, "processing %s... ", *argv); + + { + char *s0; + char *s1; + int n; + + s0 = strrchr(*argv, '/'); + if (!s0) { + s0 = *argv; + } else { + ++s0; + } + s1 = strrchr(s0, '.'); + if (!s1) { + n = strlen(s0); + } else { + n = s1 - s0; + } + +/* if ((numsets == 0) && strncmp("ASCII", s0, n)) { */ +/* printf("error - first codeset isn't ASCII!\n"); */ +/* return EXIT_FAILURE; */ +/* } */ + + if (numsets >= sizeof(codeset_index)) { + fprintf(stderr, "error - too many codesets!\n"); + return EXIT_FAILURE; + } + + if (codeset_list_end + n + 1 + numsets + 1 + 1 >= 256) { + fprintf(stderr, "error - codeset list to big!\n"); + return EXIT_FAILURE; + } + + codeset_index[numsets+1] = codeset_index[numsets] + n+1; + strncpy(codeset_list + codeset_list_end, s0, n); + codeset_list_end += (n+1); + codeset_list[codeset_list_end - 1] = 0; + + printf("\t{ /* %.*s */", n, s0); + } + + memset(&csd[numsets], 0, sizeof(charset_data)); + memset(xi, 0, sizeof(xi)); + { + unsigned long c, wc; + int lines; + lines = 0; + while (fgets(buf,sizeof(buf),fp)) { + if ((2 != sscanf(buf, "{ %lx , %lx", &c, &wc)) + || (c >= 256) || (wc > MAX_WCHAR)) { + fprintf(stderr, "error: scanf failure! \"%s\"\n", buf); + return EXIT_FAILURE; + } + + /* don't put in w2c... dynamicly build tt instead. */ + + if (c <= 0x7f) { /* check the 7bit entries but don't store */ + if (c != wc) { + fprintf(stderr, "error: c != wc in %s\n", buf); + return EXIT_FAILURE; + } + csd[numsets].c2w[c] = wc; + csd[numsets].w2c[wc] = 0; /* ignore */ + if (wc > max_wchar) { + max_wchar = wc; + } + } else { + csd[numsets].c2w[c] = wc; + csd[numsets].w2c[wc] = c; + if (wc > max_wchar) { + max_wchar = wc; + } + } + ++lines; + } + fprintf(stderr, "%d lines ", lines); + + for (i = 0 ; i <= MAX_WCHAR ; i += (1 << TT_SHIFT)) { + p = &csd[numsets].w2c[i]; + for (j = 0 ; j < tt_num ; j++) { + if (!memcmp(p, &tt[j << TT_SHIFT], (1 << TT_SHIFT))) { + break; + } + } + if (j == tt_num) { /* new entry */ + memcpy(&tt[j << TT_SHIFT], p, (1 << TT_SHIFT)); + ++tt_num; + } + xi[i >> TT_SHIFT] = j; + } + + for (i = 0 ; i <= (MAX_WCHAR >> TT_SHIFT) ; i += (1 << TI_SHIFT)) { + p = &xi[i]; + for (j = 0 ; j < ti_num ; j++) { + if (!memcmp(p, &ti[j << TI_SHIFT], (1 << TI_SHIFT))) { + break; + } + } + if (j == ti_num) { /* new entry */ + memcpy(&ti[j << TI_SHIFT], p, (1 << TI_SHIFT)); + ++ti_num; + } + csd[numsets].ii[i >> TI_SHIFT] = j; +/* fprintf(stderr, "%d ", i >> TI_SHIFT); */ + } + +#if 1 + printf("\n\t\t/* idx8ctype data */\n\t\t{"); + for (i = 128 ; i < 256 ; i++) { + wchar_t c; + unsigned int d; + +/* if (!(i & 0x7)) { */ +/* printf("\n"); */ +/* } */ + + c = csd[numsets].c2w[i]; + + if (c == 0) { /* non-existant char in codeset */ + d = __CTYPE_unclassified; + } else if (iswdigit(c)) { + d = __CTYPE_digit; + } else if (iswalpha(c)) { + d = __CTYPE_alpha_nonupper_nonlower; + if (iswlower(c)) { + d = __CTYPE_alpha_lower; + if (iswupper(c)) { + d = __CTYPE_alpha_upper_lower; + } + } else if (iswupper(c)) { + d = __CTYPE_alpha_upper; + } + } else if (iswpunct(c)) { + d = __CTYPE_punct; + } else if (iswgraph(c)) { + d = __CTYPE_graph; + } else if (iswprint(c)) { + d = __CTYPE_print_space_nonblank; + if (iswblank(c)) { + d = __CTYPE_print_space_blank; + } + } else if (iswspace(c) && !iswcntrl(c)) { + d = __CTYPE_space_nonblank_noncntrl; + if (iswblank(c)) { + d = __CTYPE_space_blank_noncntrl; + } + } else if (iswcntrl(c)) { + d = __CTYPE_cntrl_nonspace; + if (iswspace(c)) { + d = __CTYPE_cntrl_space_nonblank; + if (iswblank(c)) { + d = __CTYPE_cntrl_space_blank; + } + } + } else { + d = __CTYPE_unclassified; + } + +#if 1 + row[i & (CTYPE_ROW_LEN-1)] = d; + if ((i & (CTYPE_ROW_LEN-1)) == (CTYPE_ROW_LEN-1)) { + p = ctype_tbl; + for (j=0 ; j < n_ctype_rows ; j++) { + if (!memcmp(p, row, CTYPE_ROW_LEN)) { + break; + } + p += CTYPE_ROW_LEN; + } + if (j == n_ctype_rows) { /* new entry */ + if (++n_ctype_rows > 256) { + fprintf(stderr, "error -- to many ctype rows!\n"); + return EXIT_FAILURE; + } + memcpy(p, row, CTYPE_ROW_LEN); + } + csd[numsets].ctype_idx[i >> CTYPE_IDX_SHIFT] = j; + if (!((i >> CTYPE_IDX_SHIFT) & 0x7) + && (i != (127 + CTYPE_ROW_LEN)) + ) { + printf("\n\t\t "); + } + printf(" %#4x,", j); + } +#else + printf(" %#4x,", d); +#endif + } +#endif + printf(" }"); + +#if 1 + printf(",\n\t\t/* idx8uplow data */\n\t\t{"); + for (i = 128 ; i < 256 ; i++) { + wchar_t c, u, l; +/* if (!(i & 0x7)) { */ +/* printf("\n"); */ +/* } */ + c = csd[numsets].c2w[i]; + if ((c != 0) || 1) { + u = towupper(c); + l = towlower(c); + + if (u >= 0x80) u = csd[numsets].w2c[u]; + if (l >= 0x80) l = csd[numsets].w2c[l]; + + if (u == 0) u = i; /* upper is missing, so ignore */ + if (l == 0) l = i; /* lower is missing, so ignore */ + +#if 1 + /* store as unsigned char and let overflow handle it. */ +/* if ((((u-i) < CHAR_MIN) || ((u-i) > CHAR_MAX)) */ +/* || (((i-l) < CHAR_MIN) || ((i-l) > CHAR_MAX)) */ +/* ) { */ +/* fprintf(stderr, "error - uplow diff out of range! %d %ld %ld\n", */ +/* i, u, l); */ +/* return EXIT_FAILURE; */ +/* } */ + + row[i & (UPLOW_ROW_LEN-1)] = ((l==i) ? (u-i) : (i-l)); + if ((i & (UPLOW_ROW_LEN-1)) == (UPLOW_ROW_LEN-1)) { + p = uplow_tbl; + for (j=0 ; j < n_uplow_rows ; j++) { + if (!memcmp(p, row, UPLOW_ROW_LEN)) { + break; + } + p += UPLOW_ROW_LEN; + } + if (j == n_uplow_rows) { /* new entry */ + if (++n_uplow_rows > 256) { + fprintf(stderr, "error -- to many uplow rows!\n"); + return EXIT_FAILURE; + } + memcpy(p, row, UPLOW_ROW_LEN); + } + csd[numsets].uplow_idx[i >> UPLOW_IDX_SHIFT] = j; + if (!((i >> UPLOW_IDX_SHIFT) & 0x7) + && (i != (127 + UPLOW_ROW_LEN)) + ) { + printf("\n\t\t "); + } + printf(" %#4x,", j); + } + +#elif 0 + if (!(i & 0x7) && i) { + printf("\n"); + } + printf(" %4ld,", (l==i) ? (u-i) : (i-l)); +/* printf(" %4ld,", (l==i) ? u : l); */ +#else + if ((u != i) || (l != i)) { +#if 0 + printf(" %#08lx, %#08lx, %#08lx, %#08lx, %#08lx, %#08lx, \n", + (unsigned long) i, + (unsigned long) c, + (unsigned long) l, + (unsigned long) towlower(c), + (unsigned long) u, + (unsigned long) towupper(c)); + +#else + printf(" %#08lx, %8ld, %d, %8ld, %d, %#08lx\n", + (unsigned long) i, + (long) (l - i), + iswupper(c), + (long) (i - u), + iswlower(c), + (unsigned long) c); +#endif + } +#endif + } + } + printf(" }"); +#endif + +#ifndef DO_WIDE_CHAR + printf("\n"); +#else /* DO_WIDE_CHAR */ + +#if 1 + printf(",\n\t\t/* idx8c2wc data */\n\t\t{"); + for (i = 128 ; i < 256 ; i++) { +#if 1 + wrow[i & (C2WC_ROW_LEN-1)] = csd[numsets].c2w[i]; + if ((i & (C2WC_ROW_LEN-1)) == (C2WC_ROW_LEN-1)) { + p = (unsigned char *) c2wc_tbl; + for (j=0 ; j < n_c2wc_rows ; j++) { + if (!memcmp(p, (char *) wrow, 2*C2WC_ROW_LEN)) { + break; + } + p += 2*C2WC_ROW_LEN; + } + if (j == n_c2wc_rows) { /* new entry */ + if (++n_c2wc_rows > 256) { + fprintf(stderr, "error -- to many c2wc rows!\n"); + return EXIT_FAILURE; + } + memcpy(p, (char *) wrow, 2*C2WC_ROW_LEN); + } + csd[numsets].c2wc_idx[i >> C2WC_IDX_SHIFT] = j; + if (!((i >> C2WC_IDX_SHIFT) & 0x7) + && (i != (127 + C2WC_ROW_LEN)) + ) { + printf("\n\t\t "); + } + printf(" %#4x,", j); + } +#else + if (!(i & 0x7) && i) { + printf("\n"); + } + printf(" %#6lx,", csd[numsets].c2w[i]); +#endif + } + printf(" },\n"); +#endif + +#if 1 +/* fprintf(stderr, "\nII_LEN = %d\n", II_LEN); */ + printf("\t\t/* idx8wc2c data */\n\t\t{"); + for (i = 0 ; i < II_LEN ; i++) { + if (!(i & 0x7) && i) { + printf("\n\t\t "); + } + printf(" %#4x,", csd[numsets].ii[i]); + } + printf(" }\n"); +#endif + +#endif /* DO_WIDE_CHAR */ + printf("\t},\n"); + + } + ++numsets; + fprintf(stderr, "done\n"); + } + printf("};\n"); + printf("\n#endif /* WANT_DATA */\n"); + +#ifdef DO_WIDE_CHAR + printf("\n"); + printf("#define __LOCALE_DATA_Cwc2c_DOMAIN_MAX\t%#x\n", RANGE); + printf("#define __LOCALE_DATA_Cwc2c_TI_SHIFT\t\t%d\n", TI_SHIFT); + printf("#define __LOCALE_DATA_Cwc2c_TT_SHIFT\t\t%d\n", TT_SHIFT); + printf("#define __LOCALE_DATA_Cwc2c_II_LEN\t\t%d\n", II_LEN); + printf("#define __LOCALE_DATA_Cwc2c_TI_LEN\t\t%d\n", ti_num << TI_SHIFT); + printf("#define __LOCALE_DATA_Cwc2c_TT_LEN\t\t%d\n", tt_num << TT_SHIFT); + printf("\n"); + + printf("\n#define __LOCALE_DATA_Cwc2c_TBL_LEN\t\t%d\n", + (ti_num << TI_SHIFT) + (tt_num << TT_SHIFT)); + + printf("#ifdef WANT_DATA\n\n"); + printf("static const unsigned char __LOCALE_DATA_Cwc2c_data[%d] = {\n", + (ti_num << TI_SHIFT) + (tt_num << TT_SHIFT)); + printf("\t/* ti_table */\n\t"); + for (i=0 ; i < ti_num << TI_SHIFT ; i++) { + if (!(i & 7) && i) { + printf("\n\t"); + } + printf(" %#4x,", ti[i]); + } + printf("\n"); + printf("\t/* tt_table */\n\t"); + for (i=0 ; i < tt_num << TT_SHIFT ; i++) { + if (!(i & 7) && i) { + printf("\n\t"); + } + printf(" %#4x,", tt[i]); + } + printf("\n};\n"); + + printf("\n#endif /* WANT_DATA */\n"); +#endif /* DO_WIDE_CHAR */ + + printf("\n#define __LOCALE_DATA_Cuplow_TBL_LEN\t\t%d\n", + n_uplow_rows * UPLOW_ROW_LEN); + printf("\n#ifdef WANT_DATA\n\n"); + + printf("\nstatic const unsigned char __LOCALE_DATA_Cuplow_data[%d] = {\n", + n_uplow_rows * UPLOW_ROW_LEN); + p = uplow_tbl; + for (j=0 ; j < n_uplow_rows ; j++) { + printf("\t"); + for (i=0 ; i < UPLOW_ROW_LEN ; i++) { + printf(" %#4x,", (unsigned int)((unsigned char) p[i])); + } + printf("\n"); + p += UPLOW_ROW_LEN; + } + printf("};\n"); + + printf("\n#endif /* WANT_DATA */\n"); + printf("\n#define __LOCALE_DATA_Cctype_TBL_LEN\t\t%d\n", +#ifdef CTYPE_PACKED + n_ctype_rows * CTYPE_ROW_LEN / 2 +#else + n_ctype_rows * CTYPE_ROW_LEN +#endif + ); + printf("\n#ifdef WANT_DATA\n\n"); + + + printf("\nstatic const unsigned char __LOCALE_DATA_Cctype_data[%d] = {\n", +#ifdef CTYPE_PACKED + n_ctype_rows * CTYPE_ROW_LEN / 2 +#else + n_ctype_rows * CTYPE_ROW_LEN +#endif + ); + p = ctype_tbl; + for (j=0 ; j < n_ctype_rows ; j++) { + printf("\t"); + for (i=0 ; i < CTYPE_ROW_LEN ; i++) { +#ifdef CTYPE_PACKED + printf(" %#4x,", (unsigned int)(p[i] + (p[i+1] << 4))); + ++i; +#else + printf(" %#4x,", (unsigned int)p[i]); +#endif + } + printf("\n"); + p += CTYPE_ROW_LEN; + } + printf("};\n"); + + printf("\n#endif /* WANT_DATA */\n"); + +#ifdef DO_WIDE_CHAR + + printf("\n#define __LOCALE_DATA_Cc2wc_TBL_LEN\t\t%d\n", + n_c2wc_rows * C2WC_ROW_LEN); + printf("\n#ifdef WANT_DATA\n\n"); + + printf("\nstatic const unsigned short __LOCALE_DATA_Cc2wc_data[%d] = {\n", + n_c2wc_rows * C2WC_ROW_LEN); + p = (unsigned char *) c2wc_tbl; + for (j=0 ; j < n_c2wc_rows ; j++) { + printf("\t"); + for (i=0 ; i < C2WC_ROW_LEN ; i++) { + printf(" %#6x,", (unsigned int)(((unsigned short *)p)[i])); + } + printf("\n"); + p += 2*C2WC_ROW_LEN; + } + printf("};\n"); + printf("\n#endif /* WANT_DATA */\n"); +#endif /* DO_WIDE_CHAR */ + printf("\n\n"); + + printf("#define __LOCALE_DATA_NUM_CODESETS\t\t%d\n", numsets); + printf("#define __LOCALE_DATA_CODESET_LIST \\\n\t\""); + for (i=0 ; i < numsets ; i++) { + printf("\\x%02x", numsets + 1 + (unsigned char) codeset_index[i]); + if (((i & 7) == 7) && (i + 1 < numsets)) { + printf("\" \\\n\t\""); + } + } + printf("\" \\\n\t\"\\0\""); + for (i=0 ; i < numsets ; i++) { + printf(" \\\n\t\"%s\\0\"", + codeset_list + ((unsigned char)codeset_index[i])); + } + + printf("\n\n"); + for (i=0 ; i < numsets ; i++) { + char buf[30]; + char *z; + strcpy(buf, codeset_list + ((unsigned char)codeset_index[i])); + for (z=buf ; *z ; z++) { + if (*z == '-') { + *z = '_'; + } + } + printf("#define __CTYPE_HAS_CODESET_%s\n", buf); + } +#ifdef DO_WIDE_CHAR + printf("#define __CTYPE_HAS_CODESET_UTF_8\n"); +#endif /* DO_WIDE_CHAR */ + +#if 0 + printf("\n#endif /* __CTYPE_HAS_8_BIT_LOCALES */\n\n"); +#endif + + total_size = 0; +#ifdef DO_WIDE_CHAR + fprintf(stderr, "tt_num = %d ti_num = %d\n", tt_num, ti_num); + fprintf(stderr, "max_wchar = %#lx\n", max_wchar); + + fprintf(stderr, "size is %d * %d + %d * %d + %d * %d = %d\n", + tt_num, 1 << TT_SHIFT, ti_num, 1 << TI_SHIFT, + ((MAX_WCHAR >> (TT_SHIFT + TI_SHIFT)) + 1), numsets, + j = tt_num * (1 << TT_SHIFT) + ti_num * (1 << TI_SHIFT) + + ((MAX_WCHAR >> (TT_SHIFT + TI_SHIFT)) + 1) * numsets); + total_size += j; +#endif /* DO_WIDE_CHAR */ + +#ifdef CTYPE_PACKED + i = 2; +#else + i = 1; +#endif + + fprintf(stderr, "ctype - CTYPE_IDX_SHIFT = %d -- %d * %d + %d * %d = %d\n", + CTYPE_IDX_SHIFT, numsets, CTYPE_IDX_LEN, n_ctype_rows, CTYPE_ROW_LEN / i, + j = numsets * CTYPE_IDX_LEN + n_ctype_rows * CTYPE_ROW_LEN / i); + total_size += j; + + fprintf(stderr, "uplow - UPLOW_IDX_SHIFT = %d -- %d * %d + %d * %d = %d\n", + UPLOW_IDX_SHIFT, numsets, UPLOW_IDX_LEN, n_uplow_rows, UPLOW_ROW_LEN, + j = numsets * UPLOW_IDX_LEN + n_uplow_rows * UPLOW_ROW_LEN); + total_size += j; + +#ifdef DO_WIDE_CHAR + + fprintf(stderr, "c2wc - C2WC_IDX_SHIFT = %d -- %d * %d + 2 * %d * %d = %d\n", + C2WC_IDX_SHIFT, numsets, C2WC_IDX_LEN, n_c2wc_rows, C2WC_ROW_LEN, + j = numsets * C2WC_IDX_LEN + 2 * n_c2wc_rows * C2WC_ROW_LEN); + total_size += j; + +#endif /* DO_WIDE_CHAR */ + + fprintf(stderr, "total size = %d\n", total_size); + +/* for (i=0 ; i < numsets ; i++) { */ +/* printf("codeset_index[i] = %d codeset_list[ci[i]] = \"%s\"\n", */ +/* (unsigned char) codeset_index[i], */ +/* codeset_list + ((unsigned char)codeset_index[i])); */ +/* } */ + + return EXIT_SUCCESS; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/gen_wctype.c b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/gen_wctype.c new file mode 100644 index 00000000..b5d7e391 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/gen_wctype.c @@ -0,0 +1,814 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "include/bits/uClibc_charclass.h" + +/* 0x9 : space blank */ +/* 0xa : space */ +/* 0xb : space */ +/* 0xc : space */ +/* 0xd : space */ +/* 0x20 : space blank */ +/* 0x1680 : space blank */ +/* 0x2000 : space blank */ +/* 0x2001 : space blank */ +/* 0x2002 : space blank */ +/* 0x2003 : space blank */ +/* 0x2004 : space blank */ +/* 0x2005 : space blank */ +/* 0x2006 : space blank */ +/* 0x2008 : space blank */ +/* 0x2009 : space blank */ +/* 0x200a : space blank */ +/* 0x200b : space blank */ +/* 0x2028 : space */ +/* 0x2029 : space */ +/* 0x3000 : space blank */ + +/* typecount[ 0] = 88670 C_alpha_nonupper_nonlower */ +/* typecount[ 1] = 742 C_alpha_lower */ +/* typecount[ 2] = 4 C_alpha_upper_lower */ +/* typecount[ 3] = 731 C_alpha_upper */ +/* typecount[ 4] = 10 C_digit */ +/* typecount[ 5] = 10270 C_punct */ +/* typecount[ 6] = 0 C_graph */ +/* typecount[ 7] = 0 C_print_space_nonblank */ +/* typecount[ 8] = 14 C_print_space_blank */ +/* typecount[ 9] = 0 C_space_nonblank_noncntrl */ +/* typecount[10] = 0 C_space_blank_noncntrl */ +/* typecount[11] = 6 C_cntrl_space_nonblank */ +/* typecount[12] = 1 C_cntrl_space_blank */ +/* typecount[13] = 60 C_cntrl_nonspace */ +/* typecount[14] = 96100 C_unclassified */ +/* typecount[15] = 0 empty_slot */ + + +/* Set to #if 0 to restrict wchars to 16 bits. */ +#if 1 +#define RANGE 0x2ffffUL +#elif 0 +#define RANGE 0x1ffffUL +#else +#define RANGE 0xffffUL /* Restrict for 16-bit wchar_t... */ +#endif + +/* Some macros that test for various (w)ctype classes when passed one of the + * designator values enumerated above. */ +#define mywalnum(D,C) ((unsigned)(D - 1) <= (__CTYPE_digit - 1)) +#define mywalpha(D,C) ((unsigned)(D - 1) <= (__CTYPE_alpha_upper - 1)) +#define mywblank(D,C) ((unsigned)(D - __CTYPE_print_space_nonblank) <= 5 && (D & 1)) +#define mywcntrl(D,C) ((unsigned)(D - __CTYPE_cntrl_space_nonblank) <= 2) +#define mywdigit(D,C) (D == __CTYPE_digit) +#define mywgraph(D,C) ((unsigned)(D - 1) <= (__CTYPE_graph - 1)) +#define mywlower(D,C) ((unsigned)(D - __CTYPE_alpha_lower) <= 1) +#define mywprint(D,C) ((unsigned)(D - 1) <= (__CTYPE_print_space_blank - 1)) +#define mywpunct(D,C) (D == __CTYPE_punct) +#define mywspace(D,C) ((unsigned)(D - __CTYPE_print_space_nonblank) <= 5) +#define mywupper(D,C) ((unsigned)(D - __CTYPE_alpha_upper_lower) <= 1) +/* #define mywxdigit(D,C) -- isxdigit is untestable this way. + * But that's ok as isxdigit() (and isdigit() too) are locale-invariant. */ +#define mywxdigit(D,C) (mywdigit(D,C) || (unsigned)(((C) | 0x20) - 'a') <= 5) + +typedef struct { + short l; + short u; +} uldiff_entry; + +typedef struct { + uint16_t ii_len; + uint16_t ti_len; + uint16_t ut_len; + + unsigned char ii_shift; + unsigned char ti_shift; + + unsigned char *ii; + unsigned char *ti; + unsigned char *ut; +} table_data; + +static unsigned verbose; +#define verbose_msg(msg...) if (verbose) fprintf(stderr, msg) + +void output_table(const char *name, table_data *tbl) +{ + size_t i; + + printf("#define __LOCALE_DATA_WC%s_II_LEN %7u\n", name, tbl->ii_len); + printf("#define __LOCALE_DATA_WC%s_TI_LEN %7u\n", name, tbl->ti_len); + printf("#define __LOCALE_DATA_WC%s_UT_LEN %7u\n", name, tbl->ut_len); + + printf("#define __LOCALE_DATA_WC%s_II_SHIFT %7u\n", name, tbl->ii_shift); + printf("#define __LOCALE_DATA_WC%s_TI_SHIFT %7u\n", name, tbl->ti_shift); + + printf("\n#ifdef WANT_WC%s_data\n", name); + + i = tbl->ii_len + tbl->ti_len + tbl->ut_len; + printf("\nstatic const unsigned char __LOCALE_DATA_WC%s_data[%zu] = {", name, i); + for (i = 0; i < tbl->ii_len; i++) { + if (i % 12 == 0) { + printf("\n"); + } + printf(" %#04x,", tbl->ii[i]); + } + for (i = 0; i < tbl->ti_len; i++) { + if (i % 12 == 0) { + printf("\n"); + } + printf(" %#04x,", tbl->ti[i]); + } + for (i = 0; i < tbl->ut_len; i++) { + if (i % 12 == 0) { + printf("\n"); + } + printf(" %#04x,", tbl->ut[i]); + } + printf("\n};\n\n"); + + printf("#endif /* WANT_WC%s_data */\n\n", name); +} + +static void dump_table_data(table_data *tbl) +{ + verbose_msg("ii_shift = %d ti_shift = %d\n" + "ii_len = %d ti_len = %d ut_len = %d\n" + "total = %d\n", + tbl->ii_shift, tbl->ti_shift, + tbl->ii_len, tbl->ti_len, tbl->ut_len, + (int) tbl->ii_len + (int) tbl->ti_len + (int) tbl->ut_len); +} + +/* For sorting the blocks of unsigned chars. */ +static size_t nu_val; + +int nu_memcmp(const void *a, const void *b) +{ + return memcmp(*(unsigned char**)a, *(unsigned char**)b, nu_val); +} + +static size_t newopt(unsigned char *ut, size_t usize, int shift, table_data *tbl); + +#define MAXTO 255 /* Restrict to minimal unsigned char max. */ + +int main(int argc, char **argv) +{ + long int u, l, tt; + size_t smallest, t; + unsigned int c; + unsigned int d; + int i, n; + int ul_count = 0; + uldiff_entry uldiff[MAXTO]; + table_data cttable; + table_data ultable; +#if 0 + table_data combtable; + table_data widthtable; + long int last_comb = 0; +#endif + unsigned char wct[(RANGE/2)+1]; /* wctype table (nibble per wchar) */ + unsigned char ult[RANGE+1]; /* upper/lower table */ + unsigned char combt[(RANGE/4)+1]; /* combining */ + unsigned char widtht[(RANGE/4)+1]; /* width */ + wctrans_t totitle; + wctype_t is_comb, is_comb3; + + long int typecount[16]; + const char *typename[16]; + static const char empty_slot[] = "empty_slot"; + int built = 0; + +#define INIT_TYPENAME(X) typename[__CTYPE_##X] = "C_" #X + + for (i = 0; i < 16; i++) { + typename[i] = empty_slot; + } + + INIT_TYPENAME(unclassified); + INIT_TYPENAME(alpha_nonupper_nonlower); + INIT_TYPENAME(alpha_lower); + INIT_TYPENAME(alpha_upper_lower); + INIT_TYPENAME(alpha_upper); + INIT_TYPENAME(digit); + INIT_TYPENAME(punct); + INIT_TYPENAME(graph); + INIT_TYPENAME(print_space_nonblank); + INIT_TYPENAME(print_space_blank); + INIT_TYPENAME(space_nonblank_noncntrl); + INIT_TYPENAME(space_blank_noncntrl); + INIT_TYPENAME(cntrl_space_nonblank); + INIT_TYPENAME(cntrl_space_blank); + INIT_TYPENAME(cntrl_nonspace); + + memset(&cttable, 0, sizeof(table_data)); + memset(&ultable, 0, sizeof(table_data)); +#if 0 + memset(combtable, 0, sizeof(table_data)); + memset(widthtable, 0, sizeof(table_data)); +#endif + setvbuf(stdout, NULL, _IONBF, 0); + + while (--argc) { + ++argv; + if (!strcmp(*argv, "-v")) { + ++verbose; + continue; + } + if (!setlocale(LC_CTYPE, *argv)) { + verbose_msg("setlocale(LC_CTYPE,%s) failed! Skipping this locale...\n", *argv); + continue; + } + + if (!(totitle = wctrans("totitle"))) { + verbose_msg("no totitle transformation.\n"); + } + if (!(is_comb = wctype("combining"))) { + verbose_msg("no combining wctype.\n"); + } + if (!(is_comb3 = wctype("combining_level3"))) { + verbose_msg("no combining_level3 wctype.\n"); + } + + if (!built) { + built = 1; + ul_count = 1; + uldiff[0].u = uldiff[0].l = 0; + + memset(wct, 0, sizeof(wct)); + memset(combt, 0, sizeof(combt)); + memset(widtht, 0, sizeof(widtht)); + + for (i = 0; i < 16; i++) { + typecount[i] = 0; + } + + for (c = 0; c <= RANGE; c++) { + if (iswdigit(c)) { + d = __CTYPE_digit; + } else if (iswalpha(c)) { + d = __CTYPE_alpha_nonupper_nonlower; + if (iswlower(c)) { + d = __CTYPE_alpha_lower; + if (iswupper(c)) { + d = __CTYPE_alpha_upper_lower; + } + } else if (iswupper(c)) { + d = __CTYPE_alpha_upper; + } + } else if (iswpunct(c)) { + d = __CTYPE_punct; + } else if (iswgraph(c)) { + d = __CTYPE_graph; + } else if (iswprint(c)) { + d = __CTYPE_print_space_nonblank; + if (iswblank(c)) { + d = __CTYPE_print_space_blank; + } + } else if (iswspace(c) && !iswcntrl(c)) { + d = __CTYPE_space_nonblank_noncntrl; + if (iswblank(c)) { + d = __CTYPE_space_blank_noncntrl; + } + } else if (iswcntrl(c)) { + d = __CTYPE_cntrl_nonspace; + if (iswspace(c)) { + d = __CTYPE_cntrl_space_nonblank; + if (iswblank(c)) { + d = __CTYPE_cntrl_space_blank; + } + } + } else { + d = __CTYPE_unclassified; + } + + ++typecount[d]; +#if 0 + if (iswspace(c)) { + if (iswblank(c)) { + verbose_msg("%#8x : space blank\n", c); + } else { + verbose_msg("%#8x : space\n", c); + } + } +#endif +#if 0 + if (c < 256) { + unsigned int glibc; + + glibc = 0; + if (isalnum(c)) ++glibc; glibc <<= 1; + if (isalpha(c)) ++glibc; glibc <<= 1; + if (isblank(c)) ++glibc; glibc <<= 1; + if (iscntrl(c)) ++glibc; glibc <<= 1; + if (isdigit(c)) ++glibc; glibc <<= 1; + if (isgraph(c)) ++glibc; glibc <<= 1; + if (islower(c)) ++glibc; glibc <<= 1; + if (isprint(c)) ++glibc; glibc <<= 1; + if (ispunct(c)) ++glibc; glibc <<= 1; + if (isspace(c)) ++glibc; glibc <<= 1; + if (isupper(c)) ++glibc; glibc <<= 1; + if (isxdigit(c)) ++glibc; + verbose_msg("%#8x : ctype %#4x\n", c, glibc); + } +#endif +#if 1 + /* Paranoid checking... */ + { + unsigned int glibc; + unsigned int mine; + + glibc = 0; + if (iswalnum(c)) ++glibc; glibc <<= 1; + if (iswalpha(c)) ++glibc; glibc <<= 1; + if (iswblank(c)) ++glibc; glibc <<= 1; + if (iswcntrl(c)) ++glibc; glibc <<= 1; + if (iswdigit(c)) ++glibc; glibc <<= 1; + if (iswgraph(c)) ++glibc; glibc <<= 1; + if (iswlower(c)) ++glibc; glibc <<= 1; + if (iswprint(c)) ++glibc; glibc <<= 1; + if (iswpunct(c)) ++glibc; glibc <<= 1; + if (iswspace(c)) ++glibc; glibc <<= 1; + if (iswupper(c)) ++glibc; glibc <<= 1; + if (iswxdigit(c)) ++glibc; + + mine = 0; + if (mywalnum(d,c)) ++mine; mine <<= 1; + if (mywalpha(d,c)) ++mine; mine <<= 1; + if (mywblank(d,c)) ++mine; mine <<= 1; + if (mywcntrl(d,c)) ++mine; mine <<= 1; + if (mywdigit(d,c)) ++mine; mine <<= 1; + if (mywgraph(d,c)) ++mine; mine <<= 1; + if (mywlower(d,c)) ++mine; mine <<= 1; + if (mywprint(d,c)) ++mine; mine <<= 1; + if (mywpunct(d,c)) ++mine; mine <<= 1; + if (mywspace(d,c)) ++mine; mine <<= 1; + if (mywupper(d,c)) ++mine; mine <<= 1; + if (mywxdigit(d,c)) ++mine; + + if (glibc != mine) { + verbose_msg("%#8x : glibc %#4x != %#4x mine %u\n", c, glibc, mine, d); + return EXIT_FAILURE; + } +#if 0 + if (iswctype(c,is_comb) || iswctype(c,is_comb3)) { +/* if (!iswpunct(c)) { */ + verbose_msg("%#8x : %d %d %#4x\n", + c, iswctype(c,is_comb),iswctype(c,is_comb3), glibc); +/* } */ + } +#endif +#if 0 + if (iswctype(c,is_comb) || iswctype(c,is_comb3)) { + if (!last_comb) { + verbose_msg("%#8x - ", c); + last_comb = c; + } else if (last_comb + 1 < c) { + verbose_msg("%#8x\n%#8x - ", last_comb, c); + last_comb = c; + } else { + last_comb = c; + } + } +#endif + } +#endif + + combt[c/4] |= ((((!!iswctype(c,is_comb)) << 1) | !!iswctype(c,is_comb3)) + << ((c & 3) << 1)); +/* comb3t[c/8] |= ((!!iswctype(c,is_comb3)) << (c & 7)); */ + +/* widtht[c/4] |= (wcwidth(c) << ((c & 3) << 1)); */ + + if (c & 1) { /* Use the high nibble for odd numbered wchars. */ + d <<= 4; + } + wct[c/2] |= d; + + l = (long)(int) towlower(c) - c; + u = (long)(int) towupper(c) - c; + ult[c] = 0; + if (l || u) { + if ((l != (short)l) || (u != (short)u)) { + verbose_msg("range assumption error! %x %ld %ld\n", c, l, u); + return EXIT_FAILURE; + } + for (i = 0; i < ul_count; i++) { + if ((l == uldiff[i].l) && (u == uldiff[i].u)) { + goto found; + } + } + uldiff[ul_count].l = l; + uldiff[ul_count].u = u; + ++ul_count; + if (ul_count > MAXTO) { + verbose_msg("too many touppers/tolowers!\n"); + return EXIT_FAILURE; + } + found: + ult[c] = i; + } + } + + for (i = 0; i < 16; i++) { + verbose_msg("typecount[%2d] = %8ld %s\n", i, typecount[i], typename[i]); + } + + verbose_msg("optimizing is* table..\n"); + n = -1; + smallest = SIZE_MAX; + cttable.ii = NULL; + for (i = 0; i < 14; i++) { + t = newopt(wct, (RANGE/2)+1, i, &cttable); + if (smallest >= t) { + n = i; + smallest = t; +/* } else { */ +/* break; */ + } + } + verbose_msg("smallest = %zu\n", smallest); + if (!(cttable.ii = malloc(smallest))) { + verbose_msg("couldn't allocate space!\n"); + return EXIT_FAILURE; + } + smallest = SIZE_MAX; + newopt(wct, (RANGE/2)+1, n, &cttable); + ++cttable.ti_shift; /* correct for nibble mode */ + + verbose_msg("optimizing u/l-to table..\n"); + smallest = SIZE_MAX; + ultable.ii = NULL; + for (i = 0; i < 14; i++) { + t = newopt(ult, RANGE+1, i, &ultable); + if (smallest >= t) { + n = i; + smallest = t; +/* } else { */ +/* break; */ + } + } + verbose_msg("%lu (smallest) + %lu (u/l diffs) = %lu\n", + (unsigned long) smallest, + (unsigned long) (4 * ul_count), + (unsigned long) (smallest + 4 * ul_count) + ); + verbose_msg("smallest = %zu\n", smallest); + if (!(ultable.ii = malloc(smallest))) { + verbose_msg("couldn't allocate space!\n"); + return EXIT_FAILURE; + } + smallest = SIZE_MAX; + newopt(ult, RANGE+1, n, &ultable); +#if 0 + verbose_msg("optimizing comb table..\n"); + smallest = SIZE_MAX; + combtable.ii = NULL; + for (i = 0; i < 14; i++) { + t = newopt(combt, sizeof(combt), i, &combtable); + if (smallest >= t) { + n = i; + smallest = t; +/* } else { */ +/* break; */ + } + } + verbose_msg("smallest = %zu\n", smallest); + if (!(combtable.ii = malloc(smallest))) { + verbose_msg("couldn't allocate space!\n"); + return EXIT_FAILURE; + } + smallest = SIZE_MAX; + newopt(combt, sizeof(combt), n, &combtable); + combtable.ti_shift += 4; /* correct for 4 entries per */ +#endif +#if 0 + verbose_msg("optimizing width table..\n"); + smallest = SIZE_MAX; + widthtable.ii = NULL; + for (i = 0; i < 14; i++) { + t = newopt(widtht, sizeof(widtht), i, &widthtable); + if (smallest >= t) { + n = i; + smallest = t; +/* } else { */ +/* break; */ + } + } + verbose_msg("smallest = %zu\n", smallest); + if (!(widthtable.ii = malloc(smallest))) { + verbose_msg("couldn't allocate space!\n"); + return EXIT_FAILURE; + } + smallest = SIZE_MAX; + newopt(widtht, sizeof(widtht), n, &widthtable); + widthtable.ti_shift += 4; /* correct for 4 entries per */ +#endif +#if 0 + verbose_msg("optimizing comb3 table..\n"); + smallest = SIZE_MAX; + comb3table.ii = NULL; + for (i = 0; i < 14; i++) { + t = newopt(comb3t, sizeof(comb3t), i, &comb3table); + if (smallest >= t) { + n = i; + smallest = t; +/* } else { */ +/* break; */ + } + } + verbose_msg("smallest = %zu\n", smallest); + if (!(comb3table.ii = malloc(smallest))) { + verbose_msg("couldn't allocate space!\n"); + return EXIT_FAILURE; + } + smallest = SIZE_MAX; + newopt(comb3t, sizeof(comb3t), n, &comb3table); + comb3table.ti_shift += 8; /* correct for 4 entries per */ +#endif + + dump_table_data(&cttable); + dump_table_data(&ultable); +#if 0 + dump_table_data(&combtable); +#endif + } + + verbose_msg("verifying for %s...\n", *argv); +#if RANGE == 0xffffU + for (c = 0; c <= 0xffffUL; c++) +#else + for (c = 0; c <= 0x10ffffUL; c++) +#endif + { + unsigned int glibc; + unsigned int mine; + unsigned int upper, lower; + +#if 0 +#if RANGE < 0x10000UL + if (c == 0x10000UL) { + c = 0x30000UL; /* skip 1st and 2nd sup planes */ + } +#elif RANGE < 0x20000UL + if (c == 0x20000UL) { + c = 0x30000UL; /* skip 2nd sup planes */ + } +#endif +#endif + glibc = 0; + if (iswalnum(c)) ++glibc; glibc <<= 1; + if (iswalpha(c)) ++glibc; glibc <<= 1; + if (iswblank(c)) ++glibc; glibc <<= 1; + if (iswcntrl(c)) ++glibc; glibc <<= 1; + if (iswdigit(c)) ++glibc; glibc <<= 1; + if (iswgraph(c)) ++glibc; glibc <<= 1; + if (iswlower(c)) ++glibc; glibc <<= 1; + if (iswprint(c)) ++glibc; glibc <<= 1; + if (iswpunct(c)) ++glibc; glibc <<= 1; + if (iswspace(c)) ++glibc; glibc <<= 1; + if (iswupper(c)) ++glibc; glibc <<= 1; + if (iswxdigit(c)) ++glibc; + + { + unsigned int u; + int n = 0, sc = 0; /* = 0 for verbose_msg only */ + int i0 = 0, i1 = 0; + + u = c; + if (u <= RANGE) { + sc = u & ((1 << cttable.ti_shift) - 1); + u >>= cttable.ti_shift; + n = u & ((1 << cttable.ii_shift) - 1); + u >>= cttable.ii_shift; + + i0 = cttable.ii[u]; + i0 <<= cttable.ii_shift; + i1 = cttable.ti[i0 + n]; + i1 <<= (cttable.ti_shift - 1); + d = cttable.ut[i1 + (sc >> 1)]; + + if (sc & 1) { + d >>= 4; + } + d &= 0x0f; + } else if (((unsigned)(c - 0xe0020UL) <= 0x5f) || (c == 0xe0001UL)) { + d = __CTYPE_punct; + } else if ((unsigned)(c - 0xf0000UL) < 0x20000UL) { + if ((c & 0xffffU) <= 0xfffdU) { + d = __CTYPE_punct; + } else { + d = __CTYPE_unclassified; + } + } else { + d = __CTYPE_unclassified; + } + + mine = 0; + if (mywalnum(d,c)) ++mine; mine <<= 1; + if (mywalpha(d,c)) ++mine; mine <<= 1; + if (mywblank(d,c)) ++mine; mine <<= 1; + if (mywcntrl(d,c)) ++mine; mine <<= 1; + if (mywdigit(d,c)) ++mine; mine <<= 1; + if (mywgraph(d,c)) ++mine; mine <<= 1; + if (mywlower(d,c)) ++mine; mine <<= 1; + if (mywprint(d,c)) ++mine; mine <<= 1; + if (mywpunct(d,c)) ++mine; mine <<= 1; + if (mywspace(d,c)) ++mine; mine <<= 1; + if (mywupper(d,c)) ++mine; mine <<= 1; + if (mywxdigit(d,c)) ++mine; + + if (glibc != mine) { + verbose_msg("%#8x : glibc %#4x != %#4x mine %d\n", c, glibc, mine, d); + if (c < 0x30000UL) { + verbose_msg("sc=%#x u=%#x n=%#x i0=%#x i1=%#x\n", sc, u, n, i0, i1); + } + } + + upper = lower = u = c; + if (u <= RANGE) { + sc = u & ((1 << ultable.ti_shift) - 1); + u >>= ultable.ti_shift; + n = u & ((1 << ultable.ii_shift) - 1); + u >>= ultable.ii_shift; + + i0 = ultable.ii[u]; + i0 <<= ultable.ii_shift; + i1 = ultable.ti[i0 + n]; + i1 <<= (ultable.ti_shift); + i1 += sc; + i0 = ultable.ut[i1]; + upper = c + uldiff[i0].u; + lower = c + uldiff[i0].l; + } + + if (towupper(c) != upper) { + verbose_msg("%#8x : towupper glibc %#4x != %#4x mine\n", + c, towupper(c), upper); + } + + if (towlower(c) != lower) { + verbose_msg("%#8x : towlower glibc %#4x != %#4x mine i0 = %d\n", + c, towlower(c), lower, i0); + } + + if (totitle && ((tt = towctrans(c, totitle)) != upper)) { + verbose_msg("%#8x : totitle glibc %#4lx != %#4x mine i0 = %d\n", + c, tt, upper, i0); + } + } + + if ((c & 0xfff) == 0xfff) verbose_msg("."); + } + verbose_msg("done\n"); + } + + if (built) { + printf("#define __LOCALE_DATA_WC_TABLE_DOMAIN_MAX %#8lx\n\n", + (unsigned long) RANGE); + output_table("ctype", &cttable); + output_table("uplow", &ultable); + +#warning fix the upper bound on the upper/lower tables... save 200 bytes or so + printf("#define __LOCALE_DATA_WCuplow_diffs %7u\n", ul_count); + printf("\n#ifdef WANT_WCuplow_diff_data\n\n"); + printf("\nstatic const short __LOCALE_DATA_WCuplow_diff_data[%zu] = {", + 2 * (size_t) ul_count); + for (i = 0; i < ul_count; i++) { + if (i % 4 == 0) { + printf("\n"); + } + printf(" %6d, %6d,", uldiff[i].u, uldiff[i].l); + } + printf("\n};\n\n"); + printf("#endif /* WANT_WCuplow_diff_data */\n\n"); + +/* output_table("comb", &combtable); */ +/* output_table("width", &widthtable); */ + } + + return !built; +} + +size_t newopt(unsigned char *ut, size_t usize, int shift, table_data *tbl) +{ + static int recurse; + unsigned char *ti[RANGE+1]; /* table index */ + size_t numblocks; + size_t blocksize; + size_t uniq; + size_t i, j; + size_t smallest, t; + unsigned char *ii_save; + int uniqblock[256]; + unsigned char uit[RANGE+1]; + int shift2; + + memset(uniqblock, 0x00, sizeof(uniqblock)); + + ii_save = NULL; + blocksize = 1 << shift; + numblocks = usize >> shift; + + /* init table index */ + for (i=j = 0; i < numblocks; i++) { + ti[i] = ut + j; + j += blocksize; + } + + /* sort */ + nu_val = blocksize; + qsort(ti, numblocks, sizeof(unsigned char *), nu_memcmp); + + uniq = 1; + uit[(ti[0]-ut)/blocksize] = 0; + for (i=1; i < numblocks; i++) { + if (memcmp(ti[i-1], ti[i], blocksize) < 0) { + if (++uniq > 255) { + break; + } + uniqblock[uniq - 1] = i; + } +#if 1 + else if (memcmp(ti[i-1], ti[i], blocksize) > 0) { + verbose_msg("bad sort %li!\n", (long) i); + abort(); + } +#endif + uit[(ti[i]-ut)/blocksize] = uniq - 1; + } + + smallest = SIZE_MAX; + shift2 = -1; + + if (uniq > 255) + return SIZE_MAX; + + smallest = numblocks + uniq * blocksize; + if (!recurse) { + ++recurse; + for (j=1; j < 14; j++) { + if ((numblocks >> j) < 2) break; + if (tbl) { + ii_save = tbl->ii; + tbl->ii = NULL; + } + if ((t = newopt(uit, numblocks, j, tbl)) < SIZE_MAX) { + t += uniq * blocksize; + } + if (tbl) { + tbl->ii = ii_save; + } + if (smallest >= t) { + shift2 = j; + smallest = t; + if (!tbl->ii) { + verbose_msg("ishift %u tshift %u size %lu\n", + shift2, shift, (unsigned long) t); + } +/* } else { */ +/* break; */ + } + } + --recurse; + } + + if (tbl->ii) { + if (recurse) { + tbl->ii_shift = shift; + tbl->ii_len = numblocks; + memcpy(tbl->ii, uit, numblocks); + tbl->ti = tbl->ii + tbl->ii_len; + tbl->ti_len = uniq * blocksize; + for (i = 0; i < uniq; i++) { + memcpy(tbl->ti + i * blocksize, ti[uniqblock[i]], blocksize); + } + } else { + ++recurse; + verbose_msg("setting ishift %u tshift %u\n", + shift2, shift); + newopt(uit, numblocks, shift2, tbl); + --recurse; + tbl->ti_shift = shift; + tbl->ut_len = uniq * blocksize; + tbl->ut = tbl->ti + tbl->ti_len; + for (i = 0; i < uniq; i++) { + memcpy(tbl->ut + i * blocksize, ti[uniqblock[i]], blocksize); + } + } + } + return smallest; +} +/* vi: set sw=4 ts=4: */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/lmmtolso.c b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/lmmtolso.c new file mode 100644 index 00000000..2437a8f6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/lmmtolso.c @@ -0,0 +1,72 @@ +#include +#include +#include +#include +#include +#include + +int main(void) +{ + FILE *lmm; /* mmap-able file */ + FILE *lso; /* static object */ + struct stat fd_stat; + int c; + size_t i; + + if (!(lmm = fopen("locale.mmap", "r"))) { + printf("cannot open locale.mmap!\n"); + return EXIT_FAILURE; + } + + if (fstat(fileno(lmm), &fd_stat)) { + printf("cannot stat locale.mmap!\n"); + fclose(lmm); + return EXIT_FAILURE; + } + + if (!(lso = fopen("locale_data.c", "w"))) { + printf("cannot open locale_data.c!\n"); + fclose(lmm); + return EXIT_FAILURE; + } + + fprintf(lso, + "#include \n" + "#include \n" + "#include \"lt_defines.h\"\n" + "#include \"locale_mmap.h\"\n\n" + "typedef union {\n" + "\tunsigned char buf[%zu];\n" + "\t__locale_mmap_t lmm;\n" + "} locale_union_t;\n\n" + "static const locale_union_t locale_union = { {", + (size_t) fd_stat.st_size + ); + + i = 0; + while ((c = getc(lmm)) != EOF) { + if (!(i & 0x7)) { + fprintf(lso, "\n\t"); + } + fprintf(lso, "%#04x, ", c); + ++i; + } + fprintf(lso, + "\n} };\n\n" + "const __locale_mmap_t *__locale_mmap = &locale_union.lmm;\n\n" + ); + + if (ferror(lmm)) { + printf("error reading!\n"); + return EXIT_FAILURE; + } + + if (ferror(lso) || fclose(lso)) { + printf("error writing!\n"); + return EXIT_FAILURE; + } + + fclose(lmm); + + return EXIT_SUCCESS; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/locale_mmap.h b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/locale_mmap.h new file mode 100644 index 00000000..5b0df907 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/locale_mmap.h @@ -0,0 +1,91 @@ +/* #define __LOCALE_DATA_MAGIC_SIZE 64 */ +#ifndef __WCHAR_ENABLED +#if 0 +#warning WHOA!!! __WCHAR_ENABLED is not defined! defining it now... +#endif +#define __WCHAR_ENABLED +#endif + +/* TODO - fix */ +#ifdef __WCHAR_ENABLED +#define __LOCALE_DATA_WCctype_TBL_LEN (__LOCALE_DATA_WCctype_II_LEN + __LOCALE_DATA_WCctype_TI_LEN + __LOCALE_DATA_WCctype_UT_LEN) +#define __LOCALE_DATA_WCuplow_TBL_LEN (__LOCALE_DATA_WCuplow_II_LEN + __LOCALE_DATA_WCuplow_TI_LEN + __LOCALE_DATA_WCuplow_UT_LEN) +#define __LOCALE_DATA_WCuplow_diff_TBL_LEN (2 * __LOCALE_DATA_WCuplow_diffs) +/* #define WCcomb_TBL_LEN (WCcomb_II_LEN + WCcomb_TI_LEN + WCcomb_UT_LEN) */ +#endif + +#undef __PASTE2 +#define __PASTE2(A,B) A ## B +#undef __PASTE3 +#define __PASTE3(A,B,C) A ## B ## C + +#define __LOCALE_DATA_COMMON_MMAP(X) \ + unsigned char __PASTE3(lc_,X,_data)[__PASTE3(__lc_,X,_data_LEN)]; + +#define __LOCALE_DATA_COMMON_MMIDX(X) \ + unsigned char __PASTE3(lc_,X,_rows)[__PASTE3(__lc_,X,_rows_LEN)]; \ + uint16_t __PASTE3(lc_,X,_item_offsets)[__PASTE3(__lc_,X,_item_offsets_LEN)]; \ + uint16_t __PASTE3(lc_,X,_item_idx)[__PASTE3(__lc_,X,_item_idx_LEN)]; \ + + +typedef struct { +#ifdef __LOCALE_DATA_MAGIC_SIZE + unsigned char magic[__LOCALE_DATA_MAGIC_SIZE]; +#endif + +#ifdef __CTYPE_HAS_8_BIT_LOCALES + const unsigned char tbl8ctype[__LOCALE_DATA_Cctype_TBL_LEN]; + const unsigned char tbl8uplow[__LOCALE_DATA_Cuplow_TBL_LEN]; +#ifdef __WCHAR_ENABLED + const uint16_t tbl8c2wc[__LOCALE_DATA_Cc2wc_TBL_LEN]; /* char > 0x7f to wide char */ + const unsigned char tbl8wc2c[__LOCALE_DATA_Cwc2c_TBL_LEN]; + /* translit */ +#endif /* __WCHAR_ENABLED */ +#endif /* __CTYPE_HAS_8_BIT_LOCALES */ +#ifdef __WCHAR_ENABLED + const unsigned char tblwctype[__LOCALE_DATA_WCctype_TBL_LEN]; + const unsigned char tblwuplow[__LOCALE_DATA_WCuplow_TBL_LEN]; + const int16_t tblwuplow_diff[__LOCALE_DATA_WCuplow_diff_TBL_LEN]; +/* const unsigned char tblwcomb[WCcomb_TBL_LEN]; */ + /* width?? */ +#endif + + __LOCALE_DATA_COMMON_MMAP(ctype) + __LOCALE_DATA_COMMON_MMAP(numeric) + __LOCALE_DATA_COMMON_MMAP(monetary) + __LOCALE_DATA_COMMON_MMAP(time) + /* collate is different */ + __LOCALE_DATA_COMMON_MMAP(messages) + + +#ifdef __CTYPE_HAS_8_BIT_LOCALES + const __codeset_8_bit_t codeset_8_bit[__LOCALE_DATA_NUM_CODESETS]; +#endif + + __LOCALE_DATA_COMMON_MMIDX(ctype) + __LOCALE_DATA_COMMON_MMIDX(numeric) + __LOCALE_DATA_COMMON_MMIDX(monetary) + __LOCALE_DATA_COMMON_MMIDX(time) + /* collate is different */ + __LOCALE_DATA_COMMON_MMIDX(messages) + + const uint16_t collate_data[__lc_collate_data_LEN]; + + unsigned char lc_common_item_offsets_LEN[__LOCALE_DATA_CATEGORIES]; + size_t lc_common_tbl_offsets[__LOCALE_DATA_CATEGORIES * 4]; + /* offsets from start of locale_mmap_t */ + /* rows, item_offsets, item_idx, data */ + +#ifdef __LOCALE_DATA_NUM_LOCALES + unsigned char locales[__LOCALE_DATA_NUM_LOCALES * __LOCALE_DATA_WIDTH_LOCALES]; + unsigned char locale_names5[5*__LOCALE_DATA_NUM_LOCALE_NAMES]; + unsigned char locale_at_modifiers[__LOCALE_DATA_AT_MODIFIERS_LENGTH]; +#endif + + unsigned char lc_names[__lc_names_LEN]; +#ifdef __CTYPE_HAS_8_BIT_LOCALES + unsigned char codeset_list[sizeof(__LOCALE_DATA_CODESET_LIST)]; /* TODO - fix */ +#endif +} __locale_mmap_t; + +extern const __locale_mmap_t *__locale_mmap; diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/programs/categories.def b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/programs/categories.def new file mode 100644 index 00000000..c248ba73 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/programs/categories.def @@ -0,0 +1,357 @@ +/* + * + * Copyright (c) 2008 STMicroelectronics Ltd + * Filippo Arcidiacono (filippo.arcidiacono@st.com) + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Taken from glibc 2.6 + * + */ + + +/* Definition of all available locale categories and their items. -*- C -*- + + These definitions are used by the 'locale' the program. + + The general format of the descriptions is like this: + + DEFINE_CATEGORY (ID, name, ( items ), setlocale-postload) + + where items itself is an array of entries in the form + + { ID, name, standard, value-type, min, max } + + The usage of the load, check, output functions depends on the individual + program code which loads this file. + + The various value types for the items are `string', `stringarray', `byte' + `bytearray', and `word'. These cover all possible values in the current + locale definitions. `min' and `max' can be individually used again. */ + +#ifndef NO_POSTLOAD +#define NO_POSTLOAD NULL +#endif + +#if 0 +DEFINE_CATEGORY +( + LC_COLLATE, "LC_COLLATE", + ( + DEFINE_ELEMENT (_NL_COLLATE_NRULES, "collate-nrules", std, word) + DEFINE_ELEMENT (_NL_COLLATE_RULESETS, "collate-rulesets", std, string) + DEFINE_ELEMENT (_NL_COLLATE_TABLEMB, "collate-tablemb", std, wstring) + DEFINE_ELEMENT (_NL_COLLATE_WEIGHTMB, "collate-weightmb", std, wstring) + DEFINE_ELEMENT (_NL_COLLATE_EXTRAMB, "collate-extramb", std, wstring) + DEFINE_ELEMENT (_NL_COLLATE_INDIRECTMB, "collate-indirectmb", std, wstring) + DEFINE_ELEMENT (_NL_COLLATE_TABLEWC, "collate-tablewc", std, wstring) + DEFINE_ELEMENT (_NL_COLLATE_WEIGHTWC, "collate-weightwc", std, wstring) + DEFINE_ELEMENT (_NL_COLLATE_EXTRAWC, "collate-extrawc", std, wstring) + DEFINE_ELEMENT (_NL_COLLATE_INDIRECTWC, "collate-indirectwc", std, wstring) + DEFINE_ELEMENT (_NL_COLLATE_SYMB_HASH_SIZEMB, "collate-symb-hash-sizemb", std, word) + DEFINE_ELEMENT (_NL_COLLATE_SYMB_TABLEMB, "collate-symb-tablemb", std, wstring) + DEFINE_ELEMENT (_NL_COLLATE_SYMB_EXTRAMB, "collate-symb-extramb", std, wstring) + DEFINE_ELEMENT (_NL_COLLATE_COLLSEQMB, "collate-collseqmb", std, wstring) + DEFINE_ELEMENT (_NL_COLLATE_COLLSEQWC, "collate-collseqwc", std, wstring) + DEFINE_ELEMENT (_NL_COLLATE_CODESET, "collate-codeset", std, string) + ), NO_POSTLOAD) +#endif + + +/* The actual definition of ctype is meaningless here. It is hard coded in + the code because it has to be handled very specially. Only the names of + the functions and the value types are important. */ +DEFINE_CATEGORY +( + LC_CTYPE, "LC_CTYPE", + ( +#if 0 + DEFINE_ELEMENT (_NL_CTYPE_CLASS, "ctype-class", std, wstring) + DEFINE_ELEMENT (_NL_CTYPE_TOUPPER, "ctype-toupper", std, wstring) + DEFINE_ELEMENT (_NL_CTYPE_TOLOWER, "ctype-tolower", std, wstring) + DEFINE_ELEMENT (_NL_CTYPE_CLASS32, "ctype-class32", std, wstring) + DEFINE_ELEMENT (_NL_CTYPE_CLASS_NAMES, "ctype-class-names", std, stringlist, 10, 32) + DEFINE_ELEMENT (_NL_CTYPE_MAP_NAMES, "ctype-map-names", std, stringlist, 2, 32) + DEFINE_ELEMENT (_NL_CTYPE_WIDTH, "ctype-width", std, bytearray) + DEFINE_ELEMENT (_NL_CTYPE_MB_CUR_MAX, "ctype-mb-cur-max", std, word) + DEFINE_ELEMENT (_NL_CTYPE_CODESET_NAME, "charmap", std, string) + DEFINE_ELEMENT (_NL_CTYPE_TOUPPER32, "ctype-toupper32", std, wstring) + DEFINE_ELEMENT (_NL_CTYPE_TOLOWER32, "ctype-tolower32", std, wstring) + DEFINE_ELEMENT (_NL_CTYPE_CLASS_OFFSET, "ctype-class-offset", std, word) + DEFINE_ELEMENT (_NL_CTYPE_MAP_OFFSET, "ctype-map-offset", std, word) + DEFINE_ELEMENT (_NL_CTYPE_INDIGITS_MB_LEN, "ctype-indigits_mb-len", std, word) + DEFINE_ELEMENT (_NL_CTYPE_INDIGITS0_MB, "ctype-indigits0_mb", std, string) + DEFINE_ELEMENT (_NL_CTYPE_INDIGITS1_MB, "ctype-indigits1_mb", std, string) + DEFINE_ELEMENT (_NL_CTYPE_INDIGITS2_MB, "ctype-indigits2_mb", std, string) + DEFINE_ELEMENT (_NL_CTYPE_INDIGITS3_MB, "ctype-indigits3_mb", std, string) + DEFINE_ELEMENT (_NL_CTYPE_INDIGITS4_MB, "ctype-indigits4_mb", std, string) + DEFINE_ELEMENT (_NL_CTYPE_INDIGITS5_MB, "ctype-indigits5_mb", std, string) + DEFINE_ELEMENT (_NL_CTYPE_INDIGITS6_MB, "ctype-indigits6_mb", std, string) + DEFINE_ELEMENT (_NL_CTYPE_INDIGITS7_MB, "ctype-indigits7_mb", std, string) + DEFINE_ELEMENT (_NL_CTYPE_INDIGITS8_MB, "ctype-indigits8_mb", std, string) + DEFINE_ELEMENT (_NL_CTYPE_INDIGITS9_MB, "ctype-indigits9_mb", std, string) + DEFINE_ELEMENT (_NL_CTYPE_INDIGITS_WC_LEN, "ctype-indigits_wc-len", std, word) + DEFINE_ELEMENT (_NL_CTYPE_INDIGITS0_WC, "ctype-indigits0_wc", std, wstring) + DEFINE_ELEMENT (_NL_CTYPE_INDIGITS1_WC, "ctype-indigits1_wc", std, wstring) + DEFINE_ELEMENT (_NL_CTYPE_INDIGITS2_WC, "ctype-indigits2_wc", std, wstring) + DEFINE_ELEMENT (_NL_CTYPE_INDIGITS3_WC, "ctype-indigits3_wc", std, wstring) + DEFINE_ELEMENT (_NL_CTYPE_INDIGITS4_WC, "ctype-indigits4_wc", std, wstring) + DEFINE_ELEMENT (_NL_CTYPE_INDIGITS5_WC, "ctype-indigits5_wc", std, wstring) + DEFINE_ELEMENT (_NL_CTYPE_INDIGITS6_WC, "ctype-indigits6_wc", std, wstring) + DEFINE_ELEMENT (_NL_CTYPE_INDIGITS7_WC, "ctype-indigits7_wc", std, wstring) + DEFINE_ELEMENT (_NL_CTYPE_INDIGITS8_WC, "ctype-indigits8_wc", std, wstring) + DEFINE_ELEMENT (_NL_CTYPE_INDIGITS9_WC, "ctype-indigits9_wc", std, wstring) +#endif + DEFINE_ELEMENT (_NL_CTYPE_OUTDIGIT0_MB, "ctype-outdigit0_mb", std, string) + DEFINE_ELEMENT (_NL_CTYPE_OUTDIGIT1_MB, "ctype-outdigit1_mb", std, string) + DEFINE_ELEMENT (_NL_CTYPE_OUTDIGIT2_MB, "ctype-outdigit2_mb", std, string) + DEFINE_ELEMENT (_NL_CTYPE_OUTDIGIT3_MB, "ctype-outdigit3_mb", std, string) + DEFINE_ELEMENT (_NL_CTYPE_OUTDIGIT4_MB, "ctype-outdigit4_mb", std, string) + DEFINE_ELEMENT (_NL_CTYPE_OUTDIGIT5_MB, "ctype-outdigit5_mb", std, string) + DEFINE_ELEMENT (_NL_CTYPE_OUTDIGIT6_MB, "ctype-outdigit6_mb", std, string) + DEFINE_ELEMENT (_NL_CTYPE_OUTDIGIT7_MB, "ctype-outdigit7_mb", std, string) + DEFINE_ELEMENT (_NL_CTYPE_OUTDIGIT8_MB, "ctype-outdigit8_mb", std, string) + DEFINE_ELEMENT (_NL_CTYPE_OUTDIGIT9_MB, "ctype-outdigit9_mb", std, string) +#if 0 + DEFINE_ELEMENT (_NL_CTYPE_OUTDIGIT0_WC, "ctype-outdigit0_wc", std, word) + DEFINE_ELEMENT (_NL_CTYPE_OUTDIGIT1_WC, "ctype-outdigit1_wc", std, word) + DEFINE_ELEMENT (_NL_CTYPE_OUTDIGIT2_WC, "ctype-outdigit2_wc", std, word) + DEFINE_ELEMENT (_NL_CTYPE_OUTDIGIT3_WC, "ctype-outdigit3_wc", std, word) + DEFINE_ELEMENT (_NL_CTYPE_OUTDIGIT4_WC, "ctype-outdigit4_wc", std, word) + DEFINE_ELEMENT (_NL_CTYPE_OUTDIGIT5_WC, "ctype-outdigit5_wc", std, word) + DEFINE_ELEMENT (_NL_CTYPE_OUTDIGIT6_WC, "ctype-outdigit6_wc", std, word) + DEFINE_ELEMENT (_NL_CTYPE_OUTDIGIT7_WC, "ctype-outdigit7_wc", std, word) + DEFINE_ELEMENT (_NL_CTYPE_OUTDIGIT8_WC, "ctype-outdigit8_wc", std, word) + DEFINE_ELEMENT (_NL_CTYPE_OUTDIGIT9_WC, "ctype-outdigit9_wc", std, word) + DEFINE_ELEMENT (_NL_CTYPE_TRANSLIT_TAB_SIZE, "ctype-translit-tab-size", std, word) + DEFINE_ELEMENT (_NL_CTYPE_TRANSLIT_FROM_IDX, "ctype-translit-from-idx", std, wstring) + DEFINE_ELEMENT (_NL_CTYPE_TRANSLIT_FROM_TBL, "ctype-translit-from-tbl", std, wstring) + DEFINE_ELEMENT (_NL_CTYPE_TRANSLIT_TO_IDX, "ctype-translit-to-idx", std, wstring) + DEFINE_ELEMENT (_NL_CTYPE_TRANSLIT_TO_TBL, "ctype-translit-to-tbl", std, wstring) + DEFINE_ELEMENT (_NL_CTYPE_TRANSLIT_DEFAULT_MISSING_LEN, "ctype-translit-default-missing-len", std, word) + DEFINE_ELEMENT (_NL_CTYPE_TRANSLIT_DEFAULT_MISSING, "ctype-translit-default-missing", std, wstring) + DEFINE_ELEMENT (_NL_CTYPE_TRANSLIT_IGNORE_LEN, "ctype-translit-ignore-len", std, word) + DEFINE_ELEMENT (_NL_CTYPE_TRANSLIT_IGNORE, "ctype-translit-ignore", std, string) + DEFINE_ELEMENT (_NL_CTYPE_MAP_TO_NONASCII, "map-to-nonascii", std, word) +#endif + ), _nl_postload_ctype) + + +DEFINE_CATEGORY +( + LC_MONETARY, "LC_MONETARY", + ( + DEFINE_ELEMENT (INT_CURR_SYMBOL, "int_curr_symbol", std, string) + DEFINE_ELEMENT (CURRENCY_SYMBOL, "currency_symbol", std, string) + DEFINE_ELEMENT (MON_DECIMAL_POINT, "mon_decimal_point", std, string) + DEFINE_ELEMENT (MON_THOUSANDS_SEP, "mon_thousands_sep", std, string) + DEFINE_ELEMENT (MON_GROUPING, "mon_grouping", std, bytearray) + DEFINE_ELEMENT (POSITIVE_SIGN, "positive_sign", std, string) + DEFINE_ELEMENT (NEGATIVE_SIGN, "negative_sign", std, string) + DEFINE_ELEMENT (INT_FRAC_DIGITS, "int_frac_digits", std, byte) + DEFINE_ELEMENT (FRAC_DIGITS, "frac_digits", std, byte) + DEFINE_ELEMENT (P_CS_PRECEDES, "p_cs_precedes", std, byte, 0, 1) + DEFINE_ELEMENT (P_SEP_BY_SPACE, "p_sep_by_space", std, byte, 0, 2) + DEFINE_ELEMENT (N_CS_PRECEDES, "n_cs_precedes", std, byte, 0, 1) + DEFINE_ELEMENT (N_SEP_BY_SPACE, "n_sep_by_space", std, byte, 0, 2) + DEFINE_ELEMENT (P_SIGN_POSN, "p_sign_posn", std, byte, 0, 4) + DEFINE_ELEMENT (N_SIGN_POSN, "n_sign_posn", std, byte, 0, 4) + DEFINE_ELEMENT (__INT_P_CS_PRECEDES, "int_p_cs_precedes", std, byte, 0, 1) + DEFINE_ELEMENT (__INT_P_SEP_BY_SPACE, "int_p_sep_by_space", std, byte, 0, 2) + DEFINE_ELEMENT (__INT_N_CS_PRECEDES, "int_n_cs_precedes", std, byte, 0, 1) + DEFINE_ELEMENT (__INT_N_SEP_BY_SPACE, "int_n_sep_by_space", std, byte, 0, 2) + DEFINE_ELEMENT (__INT_P_SIGN_POSN, "int_p_sign_posn", std, byte, 0, 4) + DEFINE_ELEMENT (__INT_N_SIGN_POSN, "int_n_sign_posn", std, byte, 0, 4) +#if 0 + DEFINE_ELEMENT (_NL_MONETARY_DUO_INT_CURR_SYMBOL, "duo_int_curr_symbol", std, string) + DEFINE_ELEMENT (_NL_MONETARY_DUO_CURRENCY_SYMBOL, "duo_currency_symbol", std, string) + DEFINE_ELEMENT (_NL_MONETARY_DUO_INT_FRAC_DIGITS, "duo_int_frac_digits", std, byte) + DEFINE_ELEMENT (_NL_MONETARY_DUO_FRAC_DIGITS, "duo_frac_digits", std, byte) + DEFINE_ELEMENT (_NL_MONETARY_DUO_P_CS_PRECEDES, "duo_p_cs_precedes", std, byte, 0, 1) + DEFINE_ELEMENT (_NL_MONETARY_DUO_P_SEP_BY_SPACE, "duo_p_sep_by_space", std, byte, 0, 2) + DEFINE_ELEMENT (_NL_MONETARY_DUO_N_CS_PRECEDES, "duo_n_cs_precedes", std, byte, 0, 1) + DEFINE_ELEMENT (_NL_MONETARY_DUO_N_SEP_BY_SPACE, "duo_n_sep_by_space", std, byte, 0, 2) + DEFINE_ELEMENT (_NL_MONETARY_DUO_INT_P_CS_PRECEDES, "duo_int_p_cs_precedes", std, byte, 0, 1) + DEFINE_ELEMENT (_NL_MONETARY_DUO_INT_P_SEP_BY_SPACE, "duo_int_p_sep_by_space", std, byte, 0, 2) + DEFINE_ELEMENT (_NL_MONETARY_DUO_INT_N_CS_PRECEDES, "duo_int_n_cs_precedes", std, byte, 0, 1) + DEFINE_ELEMENT (_NL_MONETARY_DUO_INT_N_SEP_BY_SPACE, "duo_int_n_sep_by_space", std, byte, 0, 2) + DEFINE_ELEMENT (_NL_MONETARY_DUO_P_SIGN_POSN, "duo_p_sign_posn", std, byte, 0, 4) + DEFINE_ELEMENT (_NL_MONETARY_DUO_N_SIGN_POSN, "duo_n_sign_posn", std, byte, 0, 4) + DEFINE_ELEMENT (_NL_MONETARY_DUO_INT_P_SIGN_POSN, "duo_int_p_sign_posn", std, byte, 0, 4) + DEFINE_ELEMENT (_NL_MONETARY_DUO_INT_N_SIGN_POSN, "duo_int_n_sign_posn", std, byte, 0, 4) + DEFINE_ELEMENT (_NL_MONETARY_UNO_VALID_FROM, "uno_valid_from", std, word) + DEFINE_ELEMENT (_NL_MONETARY_UNO_VALID_TO, "uno_valid_to", std, word) + DEFINE_ELEMENT (_NL_MONETARY_DUO_VALID_FROM, "duo_valid_from", std, word) + DEFINE_ELEMENT (_NL_MONETARY_DUO_VALID_TO, "duo_valid_to", std, word) + DEFINE_ELEMENT (_NL_MONETARY_CONVERSION_RATE, "conversion_rate", std, wordarray, 2, 2) + DEFINE_ELEMENT (_NL_MONETARY_DECIMAL_POINT_WC, "monetary-decimal-point-wc", std, word) + DEFINE_ELEMENT (_NL_MONETARY_THOUSANDS_SEP_WC, "monetary-thousands-sep-wc", std, word) + DEFINE_ELEMENT (_NL_MONETARY_CODESET, "monetary-codeset", std, string) +#else + DEFINE_ELEMENT (_NL_MONETARY_CRNCYSTR, "monetary-crncystr", std, string) +#endif + ), NO_POSTLOAD) + + +DEFINE_CATEGORY +( + LC_NUMERIC, "LC_NUMERIC", + ( + DEFINE_ELEMENT (DECIMAL_POINT, "decimal_point", std, string) + DEFINE_ELEMENT (THOUSANDS_SEP, "thousands_sep", std, string) + DEFINE_ELEMENT (GROUPING, "grouping", std, bytearray) +#if 0 + DEFINE_ELEMENT (_NL_NUMERIC_DECIMAL_POINT_WC, "numeric-decimal-point-wc", std, word) + DEFINE_ELEMENT (_NL_NUMERIC_THOUSANDS_SEP_WC, "numeric-thousands-sep-wc", std, word) + DEFINE_ELEMENT (_NL_NUMERIC_CODESET, "numeric-codeset", std, string) +#endif + + ), NO_POSTLOAD) + + +DEFINE_CATEGORY +( + LC_TIME, "LC_TIME", + ( + DEFINE_ELEMENT (ABDAY_1, "abday", std, stringarray, 7, 7) + DEFINE_ELEMENT (DAY_1, "day", std, stringarray, 7, 7) + DEFINE_ELEMENT (ABMON_1, "abmon", std, stringarray, 12, 12) + DEFINE_ELEMENT (MON_1, "mon", std, stringarray, 12, 12) + DEFINE_ELEMENT (AM_STR, "am_pm", std, stringarray, 2, 2) + DEFINE_ELEMENT (D_T_FMT, "d_t_fmt", std, string) + DEFINE_ELEMENT (D_FMT, "d_fmt", std, string) + DEFINE_ELEMENT (T_FMT, "t_fmt", std, string) + DEFINE_ELEMENT (T_FMT_AMPM, "t_fmt_ampm", std, string) + DEFINE_ELEMENT (ERA, "era", opt, stringlist, 0, 100) + DEFINE_ELEMENT (ERA_YEAR, "era_year", opt, string) + DEFINE_ELEMENT (ERA_D_FMT, "era_d_fmt", opt, string) + DEFINE_ELEMENT (ALT_DIGITS, "alt_digits", opt, stringlist, 100, 100) + DEFINE_ELEMENT (ERA_D_T_FMT, "era_d_t_fmt", opt, string) + DEFINE_ELEMENT (ERA_T_FMT, "era_t_fmt", opt, string) +#if 0 + DEFINE_ELEMENT (_NL_TIME_ERA_NUM_ENTRIES, "time-era-num-entries", opt, word) + DEFINE_ELEMENT (_NL_TIME_ERA_ENTRIES, "time-era-entries", opt, string) + DEFINE_ELEMENT (_NL_WABDAY_1, "wide-abday", std, wstringarray, 7, 7) + DEFINE_ELEMENT (_NL_WDAY_1, "wide-day", std, wstringarray, 7, 7) + DEFINE_ELEMENT (_NL_WABMON_1, "wide-abmon", std, wstringarray, 12, 12) + DEFINE_ELEMENT (_NL_WMON_1, "wide-mon", std, wstringarray, 12, 12) + DEFINE_ELEMENT (_NL_WAM_STR, "wide-am_pm", std, wstringarray, 2, 2) + DEFINE_ELEMENT (_NL_WD_T_FMT, "wide-d_t_fmt", std, wstring) + DEFINE_ELEMENT (_NL_WD_FMT, "wide-d_fmt", std, wstring) + DEFINE_ELEMENT (_NL_WT_FMT, "wide-t_fmt", std, wstring) + DEFINE_ELEMENT (_NL_WT_FMT_AMPM, "wide-t_fmt_ampm", std, wstring) + DEFINE_ELEMENT (_NL_WERA_YEAR, "wide-era_year", opt, wstring) + DEFINE_ELEMENT (_NL_WERA_D_FMT, "wide-era_d_fmt", opt, wstring) + DEFINE_ELEMENT (_NL_WALT_DIGITS, "wide-alt_digits", opt, wstringlist, 1000, 100) + DEFINE_ELEMENT (_NL_WERA_D_T_FMT, "wide-era_d_t_fmt", opt, wstring) + DEFINE_ELEMENT (_NL_WERA_T_FMT, "wide-era_t_fmt", opt, wstring) + DEFINE_ELEMENT (_NL_TIME_WEEK_NDAYS, "week-ndays", std, byte) + DEFINE_ELEMENT (_NL_TIME_WEEK_1STDAY, "week-1stday", std, word) + DEFINE_ELEMENT (_NL_TIME_WEEK_1STWEEK, "week-1stweek", std, byte) + DEFINE_ELEMENT (_NL_TIME_FIRST_WEEKDAY, "first_weekday", std, byte) + DEFINE_ELEMENT (_NL_TIME_FIRST_WORKDAY, "first_workday", std, byte) + DEFINE_ELEMENT (_NL_TIME_CAL_DIRECTION, "cal_direction", std, byte) + DEFINE_ELEMENT (_NL_TIME_TIMEZONE, "timezone", std, string) + DEFINE_ELEMENT (_DATE_FMT, "date_fmt", opt, string) + DEFINE_ELEMENT (_NL_W_DATE_FMT, "wide-date_fmt", opt, wstring) + DEFINE_ELEMENT (_NL_TIME_CODESET, "time-codeset", std, string) +#endif + ), NO_POSTLOAD) + + +DEFINE_CATEGORY +( + LC_MESSAGES, "LC_MESSAGES", + ( + DEFINE_ELEMENT (YESEXPR, "yesexpr", std, string) + DEFINE_ELEMENT (NOEXPR, "noexpr", std, string) + DEFINE_ELEMENT (YESSTR, "yesstr", opt, string) + DEFINE_ELEMENT (NOSTR, "nostr", opt, string) +#if 0 + DEFINE_ELEMENT (_NL_MESSAGES_CODESET, "messages-codeset", std, string) +#endif + ), NO_POSTLOAD) + +#if 0 +DEFINE_CATEGORY +( + LC_PAPER, "LC_PAPER", + ( + DEFINE_ELEMENT (_NL_PAPER_HEIGHT, "height", std, word) + DEFINE_ELEMENT (_NL_PAPER_WIDTH, "width", std, word) + DEFINE_ELEMENT (_NL_PAPER_CODESET, "paper-codeset", std, string) + ), NO_POSTLOAD) + +DEFINE_CATEGORY +( + LC_NAME, "LC_NAME", + ( + DEFINE_ELEMENT (_NL_NAME_NAME_FMT, "name_fmt", std, string) + DEFINE_ELEMENT (_NL_NAME_NAME_GEN, "name_gen", std, string) + DEFINE_ELEMENT (_NL_NAME_NAME_MR, "name_mr", std, string) + DEFINE_ELEMENT (_NL_NAME_NAME_MRS, "name_mrs", std, string) + DEFINE_ELEMENT (_NL_NAME_NAME_MISS, "name_miss", std, string) + DEFINE_ELEMENT (_NL_NAME_NAME_MS, "name_ms", std, string) + DEFINE_ELEMENT (_NL_NAME_CODESET, "name-codeset", std, string) + ), NO_POSTLOAD) + +DEFINE_CATEGORY +( + LC_ADDRESS, "LC_ADDRESS", + ( + DEFINE_ELEMENT (_NL_ADDRESS_POSTAL_FMT, "postal_fmt", std, string) + DEFINE_ELEMENT (_NL_ADDRESS_COUNTRY_NAME, "country_name", std, string) + DEFINE_ELEMENT (_NL_ADDRESS_COUNTRY_POST, "country_post", std, string) + DEFINE_ELEMENT (_NL_ADDRESS_COUNTRY_AB2, "country_ab2", std, string) + DEFINE_ELEMENT (_NL_ADDRESS_COUNTRY_AB3, "country_ab3", std, string) + DEFINE_ELEMENT (_NL_ADDRESS_COUNTRY_CAR, "country_car", std, string) + DEFINE_ELEMENT (_NL_ADDRESS_COUNTRY_NUM, "country_num", std, word) + DEFINE_ELEMENT (_NL_ADDRESS_COUNTRY_ISBN, "country_isbn", std, string) + DEFINE_ELEMENT (_NL_ADDRESS_LANG_NAME, "lang_name", std, string) + DEFINE_ELEMENT (_NL_ADDRESS_LANG_AB, "lang_ab", std, string) + DEFINE_ELEMENT (_NL_ADDRESS_LANG_TERM, "lang_term", std, string) + DEFINE_ELEMENT (_NL_ADDRESS_LANG_LIB, "lang_lib", std, string) + DEFINE_ELEMENT (_NL_ADDRESS_CODESET, "address-codeset", std, string) + ), NO_POSTLOAD) + +DEFINE_CATEGORY +( + LC_TELEPHONE, "LC_TELEPHONE", + ( + DEFINE_ELEMENT (_NL_TELEPHONE_TEL_INT_FMT, "tel_int_fmt", std, string) + DEFINE_ELEMENT (_NL_TELEPHONE_TEL_DOM_FMT, "tel_dom_fmt", std, string) + DEFINE_ELEMENT (_NL_TELEPHONE_INT_SELECT, "int_select", std, string) + DEFINE_ELEMENT (_NL_TELEPHONE_INT_PREFIX, "int_prefix", std, string) + DEFINE_ELEMENT (_NL_TELEPHONE_CODESET, "telephone-codeset", std, string) + ), NO_POSTLOAD) + +DEFINE_CATEGORY +( + LC_MEASUREMENT, "LC_MEASUREMENT", + ( + DEFINE_ELEMENT (_NL_MEASUREMENT_MEASUREMENT, "measurement", std, byte) + DEFINE_ELEMENT (_NL_MEASUREMENT_CODESET, "measurement-codeset", std, string) + ), NO_POSTLOAD) + +DEFINE_CATEGORY +( + LC_IDENTIFICATION, "LC_IDENTIFICATION", + ( + DEFINE_ELEMENT (_NL_IDENTIFICATION_TITLE, "title", std, string) + DEFINE_ELEMENT (_NL_IDENTIFICATION_SOURCE, "source", std, string) + DEFINE_ELEMENT (_NL_IDENTIFICATION_ADDRESS, "address", std, string) + DEFINE_ELEMENT (_NL_IDENTIFICATION_CONTACT, "contact", std, string) + DEFINE_ELEMENT (_NL_IDENTIFICATION_EMAIL, "email", std, string) + DEFINE_ELEMENT (_NL_IDENTIFICATION_TEL, "tel", std, string) + DEFINE_ELEMENT (_NL_IDENTIFICATION_FAX, "fax", std, string) + DEFINE_ELEMENT (_NL_IDENTIFICATION_LANGUAGE, "language", std, string) + DEFINE_ELEMENT (_NL_IDENTIFICATION_TERRITORY, "territory", std, string) + DEFINE_ELEMENT (_NL_IDENTIFICATION_AUDIENCE, "audience", std, string) + DEFINE_ELEMENT (_NL_IDENTIFICATION_APPLICATION, "application", std, string) + DEFINE_ELEMENT (_NL_IDENTIFICATION_ABBREVIATION, "abbreviation", std, string) + DEFINE_ELEMENT (_NL_IDENTIFICATION_REVISION, "revision", std, string) + DEFINE_ELEMENT (_NL_IDENTIFICATION_DATE, "date", std, string) + DEFINE_ELEMENT (_NL_IDENTIFICATION_CATEGORY, "category", std, stringarray, 13, 13) + DEFINE_ELEMENT (_NL_IDENTIFICATION_CODESET, "identification-codeset", std, string) + ), NO_POSTLOAD) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/programs/locale.c b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/programs/locale.c new file mode 100644 index 00000000..dfd20295 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/programs/locale.c @@ -0,0 +1,486 @@ +/* vi: set sw=4 ts=4: */ +/* + * + * Copyright (c) 2008 STMicroelectronics Ltd + * Filippo Arcidiacono (filippo.arcidiacono@st.com) + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * A 'locale' command implementation for uClibc. + * + */ + +#include +#include +#include +#include +#include +#ifdef __UCLIBC_HAS_GETOPT_LONG__ +#include +#endif + +typedef struct { + unsigned char idx_name; + char dot_cs; /* 0 if no codeset specified */ + char cs; + unsigned char lc_ctype_row; + unsigned char lc_numeric_row; + unsigned char lc_monetary_row; + unsigned char lc_time_row; + unsigned char lc_collate_row; + unsigned char lc_messages_row; +} locale_entry; + +/* Need to include this before locale.h and xlocale.h! */ +#include + +#undef CODESET_LIST +#define CODESET_LIST (__locale_mmap->codeset_list) +#include +#define LOCALE_NAMES (__locale_mmap->locale_names5) +#define LOCALES (__locale_mmap->locales) +#define LOCALE_AT_MODIFIERS (__locale_mmap->locale_at_modifiers) +#define CATEGORY_NAMES (__locale_mmap->lc_names) + +#define GET_CODESET_NAME(N) (const char *)(CODESET_LIST + *(CODESET_LIST + N - 3)) +#define GET_LOCALE_ENTRY(R) (locale_entry *)(LOCALES + (__LOCALE_DATA_WIDTH_LOCALES * R)) +#define GET_CATEGORY_NAME(X) (CATEGORY_NAMES + *(CATEGORY_NAMES + X)) +#define GET_LOCALE_NAME(I) (const char *)(LOCALE_NAMES + 5 * (I - 1)) + +static const char utf8[] = "UTF-8"; +static const char ascii[] = "ASCII"; + +/* If set print the name of the category. */ +static int show_category_name = 0; + +/* If set print the name of the item. */ +static int show_keyword_name = 0; + +/* If set print the usage command. */ +static int show_usage = 0; + +/* Print names of all available locales. */ +static int do_all = 0; + +/* Print names of all available character maps. */ +static int do_charmaps = 0; + +static int remaining = 0; + +/* We can map the types of the entries into a few categories. */ +enum value_type { + none, + string, + stringarray, + byte, + bytearray, + word, + stringlist, + wordarray, + wstring, + wstringarray, + wstringlist +}; + +/* Definition of the data structure which represents a category and its + items. */ +struct category { + int cat_id; + const char *name; + size_t number; + struct cat_item { + int item_id; + const char *name; + enum { std, opt } status; + enum value_type value_type; + int min; + int max; + } *item_desc; +}; + +/* Simple helper macro. */ +#define NELEMS(arr) ((sizeof (arr)) / (sizeof (arr[0]))) + +/* For some tricky stuff. */ +#define NO_PAREN(Item, More...) Item, ## More + +/* We have all categories defined in `categories.def'. Now construct + the description and data structure used for all categories. */ +#define DEFINE_ELEMENT(Item, More...) { Item, ## More }, +#define DEFINE_CATEGORY(category, name, items, postload) \ + static struct cat_item category##_desc[] = \ + { \ + NO_PAREN items \ + }; + +#include "categories.def" +#undef DEFINE_CATEGORY + +static struct category category[] = { +#define DEFINE_CATEGORY(category, name, items, postload) \ + [category] = { _NL_NUM_##category, name, NELEMS (category##_desc), \ + category##_desc }, +#include "categories.def" +#undef DEFINE_CATEGORY +}; + +#define NCATEGORIES NELEMS (category) + +static void usage(const char *name); +static void usage(const char *name) +{ + const char *s; + + s = basename(name); +#ifdef __UCLIBC_HAS_GETOPT_LONG__ + fprintf(stderr, + "Usage: %s [-a | -m] [FORMAT] name...\n\n" + "\t-a, --all-locales\tWrite names of all available locales\n" + "\t-m, --charmaps\tWrite names of available charmaps\n" + "\nFORMAT:\n" + "\t-c, --category-name\tWrite names of selected categories\n" + "\t-k, --keyword-name\tWrite names of selected keywords\n" + , s); +#else + fprintf(stderr, + "Usage: %s [-a | -m] [FORMAT] name...\n\n" + "\t-a\tWrite names of all available locales\n" + "\t-m\tWrite names of available charmaps\n" + "\nFORMAT:\n" + "\t-c\tWrite names of selected categories\n" + "\t-k\tWrite names of selected keywords\n" + , s); +#endif +} + +static int argp_parse(int argc, char *argv[]); +static int argp_parse(int argc, char *argv[]) +{ + int c; + char *progname; +#ifdef __UCLIBC_HAS_GETOPT_LONG__ + static const struct option long_options[] = { + {"all-locales", no_argument, NULL, 'a'}, + {"charmaps", no_argument, NULL, 'm'}, + {"category-name", no_argument, NULL, 'c'}, + {"keyword-name", no_argument, NULL, 'k'}, + {"help", no_argument, NULL, 'h'}, + {NULL, 0, NULL, 0}}; +#endif + progname = *argv; +#ifdef __UCLIBC_HAS_GETOPT_LONG__ + while ((c = getopt_long(argc, argv, "amckh", long_options, NULL)) >= 0) +#else + while ((c = getopt(argc, argv, "amckh")) >= 0) +#endif + switch (c) { + case 'a': + do_all = 1; + break; + case 'c': + show_category_name = 1; + break; + case 'm': + do_charmaps = 1; + break; + case 'k': + show_keyword_name = 1; + break; + case 'h': + show_usage = 1; + break; + case '?': + fprintf(stderr, "Unknown option.\n"); + usage(progname); + return 1; + + default: + fprintf(stderr, "This should never happen!\n"); + return 1; + } + + remaining = optind; + + return 0; +} + +static unsigned const char *find_at(char c); +static unsigned const char *find_at(char c) +{ + const unsigned char *q; + + q = LOCALE_AT_MODIFIERS; + do { + if (q[1] == c) { + return (unsigned const char *) q + 2; + } + q += 2 + *q; + } while (*q); + + return NULL; +} + +static void find_locale_string(locale_entry * loc_rec, char *loc) +{ + char at = 0; + unsigned char idx; + uint16_t dotcs, cs; + + idx = loc_rec->idx_name; + if (!idx) { + *loc++ = 'C'; /* jump the first locale (C) */ + *loc = '\0'; + } else { + dotcs = (uint16_t) loc_rec->dot_cs; + cs = (uint16_t) loc_rec->cs;; + loc = strncpy(loc, GET_LOCALE_NAME(idx), 5); + + if (loc[2] == '_') { + sprintf(loc, "%5.5s%c%s\0", loc, (dotcs != 0) ? '.' : ' ', + (cs == 1) ? ascii + : ((cs == 2) ? + utf8 +: GET_CODESET_NAME(cs))); + } else { + at = loc[2]; + loc[2] = '_'; + sprintf(loc, "%5.5s%c%s@%s\0", loc, (dotcs != 0) ? '.' : ' ', + (cs == + 1) ? ascii : ((cs == 2) ? utf8 : GET_CODESET_NAME(cs)), + find_at(at)); + } + } +} + +static void list_locale(void); +static void list_locale() +{ + char loc[40]; + uint16_t n = 0; + locale_entry *locales = (locale_entry *) LOCALES; + + do { + find_locale_string(locales, loc); + printf("%s\n", loc); + ++n; + locales++; + } while (n < __LOCALE_DATA_NUM_LOCALES); +} + +static void list_charmaps(void); +static void list_charmaps() +{ + unsigned const char *cl; + + cl = CODESET_LIST; + do { + printf("%s\n", CODESET_LIST + *cl); + } while (*++cl); + +} + +static void print_item(struct cat_item *item); +static void print_item(struct cat_item *item) +{ + switch (item->value_type) { + case string: + if (show_keyword_name) + printf("%s=\"", item->name); + fputs(nl_langinfo(item->item_id) ? : "", stdout); + if (show_keyword_name) + putchar('"'); + putchar('\n'); + break; + case stringarray: + { + int cnt; + const char *val; + + if (show_keyword_name) + printf("%s=\"", item->name); + + for (cnt = 0; cnt < item->max - 1; ++cnt) { + val = nl_langinfo(item->item_id + cnt); + if (val != NULL) + fputs(val, stdout); + putchar(';'); + } + + val = nl_langinfo(item->item_id + cnt); + if (val != NULL) + fputs(val, stdout); + + if (show_keyword_name) + putchar('"'); + putchar('\n'); + } + break; + case stringlist: + { + int first = 1; + const char *val = nl_langinfo(item->item_id) ? : ""; + int cnt; + + if (show_keyword_name) + printf("%s=", item->name); + + for (cnt = 0; cnt < item->max && *val != '\0'; ++cnt) { + printf("%s%s%s%s", first ? "" : ";", + show_keyword_name ? "\"" : "", val, + show_keyword_name ? "\"" : ""); + val = strchr(val, '\0') + 1; + first = 0; + } + putchar('\n'); + } + break; + case byte: + { + const char *val = nl_langinfo(item->item_id); + + if (show_keyword_name) + printf("%s=", item->name); + + if (val != NULL) + printf("%d", *val == '\177' ? -1 : *val); + putchar('\n'); + } + break; + case bytearray: + { + const char *val = nl_langinfo(item->item_id); + int cnt = val ? strlen(val) : 0; + + if (show_keyword_name) + printf("%s=", item->name); + + while (cnt > 1) { + printf("%d;", *val == '\177' ? -1 : *val); + --cnt; + ++val; + } + + printf("%d\n", cnt == 0 || *val == '\177' ? -1 : *val); + } + break; + case word: + { + union { + unsigned int word; + char *string; + } val; + + val.string = nl_langinfo(item->item_id); + if (show_keyword_name) + printf("%s=", item->name); + + printf("%d\n", val.word); + } + break; + case wstring: + case wstringarray: + case wstringlist: + /* We don't print wide character information since the same + information is available in a multibyte string. */ + default: + break; + + } +} + +/* Show the information request for NAME. */ +static void show_info(const char *name); +static void show_info(const char *name) +{ + size_t cat_no, item_no; + const unsigned char *cat_name; + + /* Now all categories in an unspecified order. */ + for (cat_no = 0; cat_no < __LC_ALL; ++cat_no) { + cat_name = GET_CATEGORY_NAME(cat_no); + if (strcmp(name, (const char *) cat_name) == 0) { + if (show_category_name) + printf("%s\n", name); + + for (item_no = 0; item_no < category[cat_no].number; ++item_no) + print_item(&category[cat_no].item_desc[item_no]); + + return; + } + + for (item_no = 0; item_no < category[cat_no].number; ++item_no) + if (strcmp(name, category[cat_no].item_desc[item_no].name) == 0) { + if (show_category_name != 0) + puts(category[cat_no].name); + + print_item(&category[cat_no].item_desc[item_no]); + return; + } + } +} + +static void show_locale_vars(void); +static void show_locale_vars() +{ + size_t cat_no; + int row; /* locale row */ + const char *lcall = getenv("LC_ALL"); + const char *lang = getenv("LANG") ? : ""; + unsigned char *cur_loc = __global_locale->cur_locale + 1; + char loc_name[40]; + locale_entry *locales; + + /* LANG has to be the first value. */ + printf("LANG=%s\n", lang); + + /* Now all categories in an unspecified order. */ + for (cat_no = 0; cat_no < __LC_ALL; ++cat_no) { + row = (((int) (*cur_loc & 0x7f)) << 7) + (cur_loc[1] & 0x7f); +/* assert(row < __LOCALE_DATA_NUM_LOCALES); */ + + locales = GET_LOCALE_ENTRY(row); + find_locale_string(locales, loc_name); + printf("%s=%s\n", GET_CATEGORY_NAME(cat_no), loc_name); + + cur_loc += 2; + } + + /* The last is the LC_ALL value. */ + printf("LC_ALL=%s\n", lcall ? : ""); +} + +int main(int argc, char *argv[]) +{ + /* Parse and process arguments. */ + if (argp_parse(argc, argv)) + return 1; + + if (do_all) { + list_locale(); + exit(EXIT_SUCCESS); + } + + if (do_charmaps) { + list_charmaps(); + exit(EXIT_SUCCESS); + } + + if (show_usage) { + usage(*argv); + exit(EXIT_SUCCESS); + } + + /* If no real argument is given we have to print the contents of the + current locale definition variables. These are LANG and the LC_*. */ + if (remaining == argc && show_category_name == 0 + && show_keyword_name == 0) { + show_locale_vars(); + exit(EXIT_SUCCESS); + } + + /* Process all given names. */ + while (remaining < argc) + show_info(argv[remaining++]); + + exit(EXIT_SUCCESS); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/tst_nl_langinfo.c b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/tst_nl_langinfo.c new file mode 100644 index 00000000..fcf2fe2e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/tst_nl_langinfo.c @@ -0,0 +1,296 @@ +#include +#include +#include +#include +#include + +#if !defined(__UCLIBC__) && 0 +#define DO_EXTRA +#endif + +int main(int argc, char **argv) +{ + char *l; + const unsigned char *x; +/* const unsigned char *y; */ + const unsigned char *p; + + if (argc > 2) { + printf("invalid args\n"); + return EXIT_FAILURE; + } + if (argc == 1) { + l = ""; + } else { + l = *++argv; + } + + if (!(x = setlocale(LC_ALL,l))) { + printf("couldn't set locale %s\n", l); + return EXIT_FAILURE; + } + +/* printf("\nsetlocale returned:\n "); */ +/* do { */ +/* printf("\\x%02x", *x); */ +/* } while (*x++); */ +/* printf("\n"); */ + +#ifndef __BCC__ +#define STR(X) #X +#else +#define STR(X) __STR(X) +#endif +#define __PASTE2(A,B) A.B + +#define DO_NL_I(X) \ + printf( STR(X) " = %d\n", (int) nl_langinfo(X) ); +#define DO_NL_S(X) \ + printf( STR(X) " = \"%s\"\n", nl_langinfo(X) ); +#define DO_NL_C(X) \ + printf( STR(X) " = \"\\x%02x\"\n", *((unsigned char *) nl_langinfo(X)) ); + + printf("ctype\n"); + + DO_NL_S(CODESET); +#ifdef DO_EXTRA + DO_NL_I(_NL_CTYPE_INDIGITS_MB_LEN); + DO_NL_S(_NL_CTYPE_INDIGITS0_MB); + DO_NL_S(_NL_CTYPE_INDIGITS1_MB); + DO_NL_S(_NL_CTYPE_INDIGITS2_MB); + DO_NL_S(_NL_CTYPE_INDIGITS3_MB); + DO_NL_S(_NL_CTYPE_INDIGITS4_MB); + DO_NL_S(_NL_CTYPE_INDIGITS5_MB); + DO_NL_S(_NL_CTYPE_INDIGITS6_MB); + DO_NL_S(_NL_CTYPE_INDIGITS7_MB); + DO_NL_S(_NL_CTYPE_INDIGITS8_MB); + DO_NL_S(_NL_CTYPE_INDIGITS9_MB); +#endif + DO_NL_S(_NL_CTYPE_OUTDIGIT0_MB); + DO_NL_S(_NL_CTYPE_OUTDIGIT1_MB); + DO_NL_S(_NL_CTYPE_OUTDIGIT2_MB); + DO_NL_S(_NL_CTYPE_OUTDIGIT3_MB); + DO_NL_S(_NL_CTYPE_OUTDIGIT4_MB); + DO_NL_S(_NL_CTYPE_OUTDIGIT5_MB); + DO_NL_S(_NL_CTYPE_OUTDIGIT6_MB); + DO_NL_S(_NL_CTYPE_OUTDIGIT7_MB); + DO_NL_S(_NL_CTYPE_OUTDIGIT8_MB); + DO_NL_S(_NL_CTYPE_OUTDIGIT9_MB); + + + printf("numeric\n"); + + DO_NL_S(RADIXCHAR); /* DECIMAL_POINT */ + DO_NL_S(THOUSEP); /* THOUSANDS_SEP */ +/* DO_NL_S(GROUPING); */ + + printf("GROUPING = \""); + for (p = (unsigned char *) nl_langinfo(GROUPING) ; *p ; p++) { + printf("\\x%02x", *p); + } + printf("\"\n\n"); + + printf("monetary\n"); + + DO_NL_S(INT_CURR_SYMBOL); + DO_NL_S(CURRENCY_SYMBOL); + DO_NL_S(MON_DECIMAL_POINT); + DO_NL_S(MON_THOUSANDS_SEP); +/* DO_NL_S(MON_GROUPING); */ + + printf("MON_GROUPING = \""); + for (p = (unsigned char *) nl_langinfo(MON_GROUPING) ; *p ; p++) { + printf("\\x%02x", *p); + } + printf("\"\n\n"); + + DO_NL_S(POSITIVE_SIGN); + DO_NL_S(NEGATIVE_SIGN); + DO_NL_C(INT_FRAC_DIGITS); + DO_NL_C(FRAC_DIGITS); + DO_NL_C(P_CS_PRECEDES); + DO_NL_C(P_SEP_BY_SPACE); + DO_NL_C(N_CS_PRECEDES); + DO_NL_C(N_SEP_BY_SPACE); + DO_NL_C(P_SIGN_POSN); + DO_NL_C(N_SIGN_POSN); + DO_NL_C(INT_P_CS_PRECEDES); + DO_NL_C(INT_P_SEP_BY_SPACE); + DO_NL_C(INT_N_CS_PRECEDES); + DO_NL_C(INT_N_SEP_BY_SPACE); + DO_NL_C(INT_P_SIGN_POSN); + DO_NL_C(INT_N_SIGN_POSN); + + DO_NL_S(CRNCYSTR); /* CURRENCY_SYMBOL */ + + + printf("time\n"); + + DO_NL_S(ABDAY_1); + DO_NL_S(ABDAY_2); + DO_NL_S(ABDAY_3); + DO_NL_S(ABDAY_4); + DO_NL_S(ABDAY_5); + DO_NL_S(ABDAY_6); + DO_NL_S(ABDAY_7); + + DO_NL_S(DAY_1); + DO_NL_S(DAY_2); + DO_NL_S(DAY_3); + DO_NL_S(DAY_4); + DO_NL_S(DAY_5); + DO_NL_S(DAY_6); + DO_NL_S(DAY_7); + + DO_NL_S(ABMON_1); + DO_NL_S(ABMON_2); + DO_NL_S(ABMON_3); + DO_NL_S(ABMON_4); + DO_NL_S(ABMON_5); + DO_NL_S(ABMON_6); + DO_NL_S(ABMON_7); + DO_NL_S(ABMON_8); + DO_NL_S(ABMON_9); + DO_NL_S(ABMON_10); + DO_NL_S(ABMON_11); + DO_NL_S(ABMON_12); + + DO_NL_S(MON_1); + DO_NL_S(MON_2); + DO_NL_S(MON_3); + DO_NL_S(MON_4); + DO_NL_S(MON_5); + DO_NL_S(MON_6); + DO_NL_S(MON_7); + DO_NL_S(MON_8); + DO_NL_S(MON_9); + DO_NL_S(MON_10); + DO_NL_S(MON_11); + DO_NL_S(MON_12); + + DO_NL_S(AM_STR); + DO_NL_S(PM_STR); + + DO_NL_S(D_T_FMT); + DO_NL_S(D_FMT); + DO_NL_S(T_FMT); + DO_NL_S(T_FMT_AMPM); +/* DO_NL_S(ERA); */ + { + const char *p = nl_langinfo(ERA); + if (!p || !*p) { + printf("ERA = (none)\n"); + } else { + int i; + printf("ERA:\n"); + for (i=0 ; i < 100 ; i++) { + printf(" %3d: \"%s\"\n", i, p); + while (*p) ++p; + ++p; + if (!*p) break; + } + } + } + + DO_NL_S(ERA_YEAR); /* non SuSv3 */ + DO_NL_S(ERA_D_FMT); +/* DO_NL_S(ALT_DIGITS); */ + { + const char *p = nl_langinfo(ALT_DIGITS); + if (!p || !*p) { + printf("ALT_DIGITS = (none)\n"); + } else { + int i; + printf("ALT_DIGITS:\n"); + for (i=0 ; i < 100 ; i++) { + printf(" %3d: \"%s\"\n", i, p); + while (*p) ++p; + ++p; + } + } + } + DO_NL_S(ERA_D_T_FMT); + DO_NL_S(ERA_T_FMT); + +#ifdef DO_EXTRA + DO_NL_C(_NL_TIME_WEEK_NDAYS); + DO_NL_I(_NL_TIME_WEEK_1STDAY); /* grr... this won't work with 16bit ptrs */ + DO_NL_C(_NL_TIME_WEEK_1STWEEK); + DO_NL_C(_NL_TIME_FIRST_WEEKDAY); + DO_NL_C(_NL_TIME_FIRST_WORKDAY); + DO_NL_C(_NL_TIME_CAL_DIRECTION); + DO_NL_S(_NL_TIME_TIMEZONE); + DO_NL_S(_DATE_FMT); +#endif + + printf("messages\n"); + + DO_NL_S(YESEXPR); + DO_NL_S(NOEXPR); + DO_NL_S(YESSTR); + DO_NL_S(NOSTR); + +#ifdef DO_EXTRA + + printf("paper\n"); + + DO_NL_I(_NL_PAPER_HEIGHT); + DO_NL_I(_NL_PAPER_WIDTH); + + printf("name\n"); + + DO_NL_S(_NL_NAME_NAME_FMT); + DO_NL_S(_NL_NAME_NAME_GEN); + DO_NL_S(_NL_NAME_NAME_MR); + DO_NL_S(_NL_NAME_NAME_MRS); + DO_NL_S(_NL_NAME_NAME_MISS); + DO_NL_S(_NL_NAME_NAME_MS); + + printf("address\n"); + + DO_NL_S(_NL_ADDRESS_POSTAL_FMT); + DO_NL_S(_NL_ADDRESS_COUNTRY_NAME); + DO_NL_S(_NL_ADDRESS_COUNTRY_POST); + DO_NL_S(_NL_ADDRESS_COUNTRY_AB2); + DO_NL_S(_NL_ADDRESS_COUNTRY_AB3); + DO_NL_S(_NL_ADDRESS_COUNTRY_CAR); + DO_NL_I(_NL_ADDRESS_COUNTRY_NUM); + DO_NL_S(_NL_ADDRESS_COUNTRY_ISBN); + DO_NL_S(_NL_ADDRESS_LANG_NAME); + DO_NL_S(_NL_ADDRESS_LANG_AB); + DO_NL_S(_NL_ADDRESS_LANG_TERM); + DO_NL_S(_NL_ADDRESS_LANG_LIB); + + printf("telephone\n"); + + DO_NL_S(_NL_TELEPHONE_TEL_INT_FMT); + DO_NL_S(_NL_TELEPHONE_TEL_DOM_FMT); + DO_NL_S(_NL_TELEPHONE_INT_SELECT); + DO_NL_S(_NL_TELEPHONE_INT_PREFIX); + + printf("measurement\n"); + + DO_NL_C(_NL_MEASUREMENT_MEASUREMENT); /* 1 is metric, 2 is US */ + + printf("identification\n"); + + DO_NL_S(_NL_IDENTIFICATION_TITLE); + DO_NL_S(_NL_IDENTIFICATION_SOURCE); + DO_NL_S(_NL_IDENTIFICATION_ADDRESS); + DO_NL_S(_NL_IDENTIFICATION_CONTACT); + DO_NL_S(_NL_IDENTIFICATION_EMAIL); + DO_NL_S(_NL_IDENTIFICATION_TEL); + DO_NL_S(_NL_IDENTIFICATION_FAX); + DO_NL_S(_NL_IDENTIFICATION_LANGUAGE); + DO_NL_S(_NL_IDENTIFICATION_TERRITORY); + DO_NL_S(_NL_IDENTIFICATION_AUDIENCE); + DO_NL_S(_NL_IDENTIFICATION_APPLICATION); + DO_NL_S(_NL_IDENTIFICATION_ABBREVIATION); + DO_NL_S(_NL_IDENTIFICATION_REVISION); + DO_NL_S(_NL_IDENTIFICATION_DATE); + DO_NL_S(_NL_IDENTIFICATION_CATEGORY); + +#endif + + return EXIT_SUCCESS; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/.gitignore b/l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/.gitignore new file mode 100644 index 00000000..d13eda94 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/.gitignore @@ -0,0 +1 @@ +unifdef diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/MAKEALL b/l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/MAKEALL new file mode 100755 index 00000000..6bacc9a7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/MAKEALL @@ -0,0 +1,143 @@ +#!/bin/sh +# +# helper script to quick build testing with cross-compilers +# + +: ${MAKE:=make} + +: ${BUILD_NCPUS:=$(getconf _NPROCESSORS_ONLN)} +if [ "$BUILD_NCPUS" -gt 1 ] ; then + JOBS=-j$((BUILD_NCPUS + 1)) +else + JOBS="" +fi +MAKE="${MAKE} ${JOBS}" + +: ${CROSS_COMPILE:=${CROSS_COMPILER_PREFIX}} + +setconfig() +{ + local opt=$1 + shift + case $1 in + [yn]) ;; + [0-9]*) ;; + *) set -- '"'$*'"' + esac + sed -i \ + -e "/${opt}=/s:=.*:=$*:" \ + .config + echo " ## setconfig ${opt} $*" +} + +get_arches() +{ + case $1 in + sh) echo sh4 sh2 sh3 sh1 sh;; + *) echo $1;; + esac +} + +find_compiler() +{ + local t a v o l + for a in $(get_arches $1) ; do + for v in unknown pc gentoo "" ; do + for o in linux uclinux "" ; do + for l in uclibc "" ; do + t="${a}${v:+-${v}}${o:+-${o}}${l:+-${l}}" + if ${t}-gcc --help > /dev/null 2>&1 ; then + echo ${t}- + return 0 + fi + done + done + done + done +} + +do_make() +{ + echo " ## ${MAKE} -s $*" + ${MAKE} -s "$@" +} + +mark_arch() +{ + local r=$1 a=$2 + eval $r=\"\$$r $a\" +} + +if [ -z "$*" ] ; then + set -- $(awk \ + '$0 ~ /^config TARGET_/ { sub("TARGET_",""); print $NF }' \ + extra/Configs/Config.in | grep -v SUBARCH) +fi +pass="" +fail="" +skip="" +for a in "$@" ; do + if [ -n "${CROSS_COMPILE}" ] ; then + CROSS=${CROSS_COMPILE} + else + CROSS=$(find_compiler ${a}) + fi + + if [ -z "${CROSS}" ] ; then + mark_arch skip $a + echo " ### SKIP: ${a}: could not find compiler" + continue + fi + + rm -f ${a}.log ${a}.fail + ( + set -e + + echo " ### Building target ${a} (${CROSS})" + + do_make distclean + do_make ARCH=$a defconfig + do_make oldconfig + + setconfig CROSS_COMPILER_PREFIX ${CROSS} + + header_path=${KERNEL_HEADERS:-$(echo '#include ' | ${CROSS}cpp 2>/dev/null | grep -o '[^"]*linux/version.h')} || : + if [ -z "${header_path}" ] ; then + for p in /usr/${CROSS%-}/usr/include ; do + if [ -e ${p}/linux/version.h ] ; then + header_path=${p} + break + fi + done + if [ -z "${header_path}" ] ; then + echo " ## unable to locate KERNEL_HEADERS" + fi + fi + setconfig KERNEL_HEADERS ${header_path%/linux/version.h} + + if do_make ; then + echo " ## PASS" + else + echo " ## FAIL" + touch ${a}.fail + fi + ) 2>&1 | tee ${a}.log + + if [ -e ${a}.fail ] ; then + rm -f ${a}.fail + mark_arch fail $a + else + mark_arch pass $a + fi +done + +if [ -n "${skip}" ] ; then + printf '\nSKIPPED: %s\n' "${skip}" +fi +if [ -n "${fail}" ] ; then + printf '\nPASSED: %s\nFAILED: %s\n\n' "${pass}" "${fail}" + exit 1 +else + printf '\nAll arches passed!\n\n' + exit 0 +fi diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/Makefile.arch.lvl3 b/l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/Makefile.arch.lvl3 new file mode 100644 index 00000000..ac006377 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/Makefile.arch.lvl3 @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../ +top_builddir=../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.arch +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/Makefile.arch.lvl4 b/l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/Makefile.arch.lvl4 new file mode 100644 index 00000000..633c91f3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/Makefile.arch.lvl4 @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../../ +top_builddir=../../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.arch +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/Makefile.libs.lvl0 b/l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/Makefile.libs.lvl0 new file mode 100644 index 00000000..4709fc2c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/Makefile.libs.lvl0 @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=./ +top_builddir=./ +#include $(top_builddir)Rules.mak +#all: libs +include Makefile.in +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/Makefile.libs.lvl1 b/l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/Makefile.libs.lvl1 new file mode 100644 index 00000000..c8dc9b46 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/Makefile.libs.lvl1 @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../ +top_builddir=../ +include $(top_builddir)Rules.mak +all: libs +include Makefile.in +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/Makefile.libs.lvl2 b/l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/Makefile.libs.lvl2 new file mode 100644 index 00000000..f9100219 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/Makefile.libs.lvl2 @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../ +top_builddir=../../ +include $(top_builddir)Rules.mak +all: libs +include Makefile.in +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/Makefile.objs.lvl2 b/l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/Makefile.objs.lvl2 new file mode 100644 index 00000000..11f362a5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/Makefile.objs.lvl2 @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../ +top_builddir=../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/Makefile.objs.lvl3 b/l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/Makefile.objs.lvl3 new file mode 100644 index 00000000..4a8f4a07 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/Makefile.objs.lvl3 @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../ +top_builddir=../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/Makefile.objs.lvl4 b/l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/Makefile.objs.lvl4 new file mode 100644 index 00000000..3ed177ae --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/Makefile.objs.lvl4 @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../../ +top_builddir=../../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/Makefile.utils.lvl1 b/l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/Makefile.utils.lvl1 new file mode 100644 index 00000000..bdaea9fd --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/Makefile.utils.lvl1 @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../ +top_builddir=../ +include $(top_builddir)Rules.mak +all: utils +include Makefile.in +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/conf-header.sh b/l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/conf-header.sh new file mode 100755 index 00000000..8044f8c0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/conf-header.sh @@ -0,0 +1,27 @@ +#!/bin/sh -e + +# Turn .config into a header file + +if [ -z "$1" ] ; then + echo "Usage: conf-header.sh <.config>" + exit 1 +fi + +cat < directly; use instead +#endif + +#define __UCLIBC_MAJOR__ ${MAJOR_VERSION} +#define __UCLIBC_MINOR__ ${MINOR_VERSION} +#define __UCLIBC_SUBLEVEL__ ${SUBLEVEL} +EOF + +exec \ +sed \ + -e '/^#$/d' \ + -e '/^[^#]/s:^\([^=]*\)=\(.*\):#define __\1__ \2:' \ + -e '/^#define /s: y$: 1:' \ + -e '/^# .* is not set$/s:^# \(.*\) is not set$:#undef __\1__:' \ + -e 's:^# \(.*\)$:/* \1 */:' \ + $1 diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/create_makefiles.sh b/l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/create_makefiles.sh new file mode 100755 index 00000000..1d94b0d1 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/create_makefiles.sh @@ -0,0 +1,71 @@ +#!/bin/sh +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +# Creates the necessary Makefiles to build w/ the Makefile.{arch,in} files + +DIRS="ldso libc libcrypt libintl libm libnsl libpthread libresolv librt libutil" + +if [ ! -f Makerules ] ; then + echo "Run this command in top_srcdir" + exit 1 +fi + +if [ -z "${USE_CMD}" ] ; then +USE_CMD="cp" +fi + +RM="rm -f" +${RM} Makefile +${USE_CMD} extra/scripts/Makefile.libs.lvl0 Makefile + +#for x in ${DIRS} ; do +# find ./${x} -name Makefile -exec rm -f {} \; +#done + +for x in */Makefile.in ; do + ${RM} `dirname ${x}`/Makefile + ${USE_CMD} extra/scripts/Makefile.libs.lvl1 `dirname ${x}`/Makefile +done + +for x in utils/Makefile.in ; do + ${RM} `dirname ${x}`/Makefile + ${USE_CMD} extra/scripts/Makefile.utils.lvl1 `dirname ${x}`/Makefile +done + +for x in */*/Makefile.in ; do + ${RM} `dirname ${x}`/Makefile + ${USE_CMD} extra/scripts/Makefile.objs.lvl2 `dirname ${x}`/Makefile +done + +# overwrites the earlier ones, we do not add arch specific to libm/arch +for x in ldso/*/Makefile.in libpthread/*/Makefile.in ; do + ${RM} `dirname ${x}`/Makefile + ${USE_CMD} extra/scripts/Makefile.libs.lvl2 `dirname ${x}`/Makefile +done + +for x in */*/*/Makefile.in ; do + ${RM} `dirname ${x}`/Makefile + ${USE_CMD} extra/scripts/Makefile.objs.lvl3 `dirname ${x}`/Makefile +done + +for x in libc/*/*/Makefile.arch ; do + ${RM} `dirname ${x}`/Makefile + ${USE_CMD} extra/scripts/Makefile.arch.lvl3 `dirname ${x}`/Makefile +done + +for x in */*/*/*/Makefile.in ; do + ${RM} `dirname ${x}`/Makefile + ${USE_CMD} extra/scripts/Makefile.objs.lvl4 `dirname ${x}`/Makefile +done + +# we do not add these to libpthread/PTNAME/sysdeps/arch +for x in libc/*/*/*/Makefile.arch ; do + ${RM} `dirname ${x}`/Makefile + ${USE_CMD} extra/scripts/Makefile.arch.lvl4 `dirname ${x}`/Makefile +done + +exit 0 diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/defs.awk b/l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/defs.awk new file mode 100644 index 00000000..1716fb13 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/defs.awk @@ -0,0 +1,27 @@ +/^[ ]*\.endp/ { need_endp = 1 } +/^[ ]*\.end/ { need_end = 1 } +/^[ ]*\.align/ { if($2 > max) max = $2; } + +END { + if(need_endp) + { + print "#define END_INIT .endp _init"; + print "#define END_FINI .endp _fini"; + } else if(need_end) + { + print "#define END_INIT .end _init"; + print "#define END_FINI .end _fini"; + } + else + { + print "#define END_INIT"; + print "#define END_FINI"; + } + if(max) + print "#define ALIGN .align", max; + else + print "#define ALIGN"; + + print "#include "; + #print "weak_extern (__gmon_start__)"; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/format.lds b/l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/format.lds new file mode 100644 index 00000000..c20212eb --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/format.lds @@ -0,0 +1,3 @@ +/* GNU ld script + * Use the shared library, but some functions are only in + * the static library, so try that secondarily. */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/gen-as-const.awk b/l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/gen-as-const.awk new file mode 100644 index 00000000..013bd6e8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/gen-as-const.awk @@ -0,0 +1,33 @@ +# Script used in producing headers of assembly constants from C expressions. +# The input to this script looks like: +# #cpp-directive ... +# NAME1 +# NAME2 expression ... +# The output of this script is C code to be run through gcc -S and then +# massaged to extract the integer constant values of the given C expressions. +# A line giving just a name implies an expression consisting of just that name. + +BEGIN { started = 0 } + +# cpp directives go straight through. +/^#/ { print; next } + +NF >= 1 && !started { + printf "void dummy(void);\n"; + print "void dummy(void) {"; + started = 1; +} + +# Separator. +$1 == "--" { next } + +NF == 1 { sub(/^.*$/, "& &"); } + +NF > 1 { + name = $1; + sub(/^[^ ]+[ ]+/, ""); + printf "__asm__ (\"@@@name@@@%s@@@value@@@%%0@@@end@@@\" : : \"i\" ((long) %s));\n", + name, $0; +} + +END { if (started) print "}" } diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/gen_bits_syscall_h.sh b/l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/gen_bits_syscall_h.sh new file mode 100755 index 00000000..f6353baa --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/gen_bits_syscall_h.sh @@ -0,0 +1,46 @@ +#!/bin/sh +# +# Copyright (C) 2001 Manuel Novoa III +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +# June 27, 2001 Manuel Novoa III +# +# This script expects top_builddir and CC (as used in the Makefiles) to be set +# in the environment, and outputs the appropriate +# $top_builddir/include/bits/sysnum.h # corresponding to +# $top_builddir/include/asm/unistd.h to stdout. +# +# Warning!!! This does _no_ error checking!!! + +INCLUDE_OPTS="-nostdinc -I${KERNEL_HEADERS}" + +case $CC in +*icc*) CC_SYSNUM_ARGS="-dM" ;; +*) CC_SYSNUM_ARGS="-dN" ;; +esac + +( echo "#include "; + echo "#include " | + $CC -E $CC_SYSNUM_ARGS $INCLUDE_OPTS - | + sed -ne 's/^[ ]*#define[ ]*\(__ARM_NR_\|__NR_\)\([A-Za-z0-9_]*\).*/UCLIBC\1\2 \1\2/gp' \ + -e 's/^[ ]*#undef[ ]*\(__ARM_NR_\|__NR_\)\([A-Za-z0-9_]*\).*/UNDEFUCLIBC\1\2 \1\2/gp' # needed to strip out any kernel-internal defines +) | +$CC -E $INCLUDE_OPTS - | +( echo "/* WARNING!!! AUTO-GENERATED FILE!!! DO NOT EDIT!!! */" ; + echo ; + echo "#ifndef _BITS_SYSNUM_H" ; + echo "#define _BITS_SYSNUM_H" ; + echo ; + echo "#ifndef _SYSCALL_H" ; + echo "# error \"Never use directly; include instead.\"" ; + echo "#endif" ; echo ; + sed -ne 's/^UCLIBC\(__ARM_NR_\|__NR_\)\([A-Za-z0-9_]*\) *\(.*\)/#undef \1\2\ +#define \1\2 \3\ +#define SYS_\2 \1\2/gp' \ + -e 's/^UNDEFUCLIBC\(__ARM_NR_\|__NR_\)\([A-Za-z0-9_]*\).*/#undef \1\2/gp' + echo ; + echo "#endif" ; +) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/getent b/l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/getent new file mode 100755 index 00000000..30d515b7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/getent @@ -0,0 +1,43 @@ +#!/bin/sh +# $Header: /var/cvs/uClibc/extra/scripts/getent,v 1.2 2005/02/02 14:18:01 solar Exp $ +# +# Closely (not perfectly) emulate the behavior of glibc's getent utility +# +#passwd|shadow|group|aliases|hosts|networks|ethers|netgroup|protocols|services|rpc +# only returns the first match (by design) +# dns based search is not supported (hosts,networks) +# case-insensitive matches not supported (ethers; others?) +# may return false-positives (hosts,protocols,rpc,services,ethers) + +export PATH="${PATH}:/bin:/usr/bin" + +file="/etc/$1" +case $1 in + passwd|group) + match="^$2:\|^[^:]*:[^:]*:$2:" ;; + shadow) + match="^$2:" ;; + networks|netgroup) + match="^[[:space:]]*$2\>" ;; + hosts|protocols|rpc|services|ethers) + match="\<$2\>" ;; + aliases) + match="^[[:space:]]*$2[[:space:]]*:" ;; + ""|-h|--help) + echo "USAGE: $0 database [key]" + exit 0 ;; + *) + echo "$0: Unknown database: $1" 1>&2 + exit 1 ;; +esac + +if [ ! -f "$file" ] ; then + echo "$0: Could not find database file for $1" 1>&2 + exit 1 +fi + +if [ $# -eq 1 ] ; then + exec cat "$file" +else + sed "s/#.*//; /$match/q; d" "$file" | grep . || exit 2 +fi diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/install_headers.sh b/l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/install_headers.sh new file mode 100644 index 00000000..14d64dc9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/install_headers.sh @@ -0,0 +1,76 @@ +#!/bin/sh +# Parameters: +# $1 = source dir +# $2 = dst dir +# $top_builddir = well you guessed it + +srcdir=${1:-include} +dstdir=${2:-`. ./.config 2>/dev/null && echo ${DEVEL_PREFIX}/include`} +: ${top_builddir:=.} + +die_if_not_dir() +{ + for dir in "$@"; do + test -d "$dir" && continue + echo "Error: '$dir' is not a directory" + exit 1 + done +} + + +# Ensure that created dirs/files have 755/644 perms +umask 022 + + +# Sanity tests +die_if_not_dir "${srcdir}" +mkdir -p "${dstdir}" 2>/dev/null +die_if_not_dir "${dstdir}" +die_if_not_dir "$top_builddir" +if ! test -x "$top_builddir/extra/scripts/unifdef"; then + echo "Error: need '$top_builddir/extra/scripts/unifdef' executable" + exit 1 +fi + + +# Sanitize and copy uclibc headers +( +# We must cd, or else we'll prepend "${srcdir}" to filenames! +cd "${srcdir}" || exit 1 +find . ! -name '.' -a ! -path '*/.*' | sed -e 's/^\.\///' -e '/^config\//d' \ + -e '/^config$/d' +) | \ +( +IFS='' +while read -r filename; do + if test -d "${srcdir}/$filename"; then + mkdir -p "${dstdir}/$filename" 2>/dev/null + continue + fi + if test x"${filename##libc-*.h}" = x""; then + # Do not install libc-XXXX.h files + continue + fi + # NB: unifdef exits with 1 if output is not + # exactly the same as input. That's ok. + # Do not abort the script if unifdef "fails"! + # NB2: careful with sed command arguments, they contain tab character + "$top_builddir/extra/scripts/unifdef" \ + -U_LIBC \ + -U__UCLIBC_GEN_LOCALE \ + -U__NO_CTYPE \ + "${srcdir}/$filename" \ + | sed -e '/^rtld_hidden_proto[ ]*([a-zA-Z0-9_]*)$/d' \ + | sed -e '/^lib\(c\|m\|resolv\|dl\|intl\|rt\|nsl\|util\|crypt\|pthread\)_hidden_proto[ ]*([a-zA-Z0-9_]*)$/d' \ + >"${dstdir}/$filename" +done +) + + +# Fix mode/owner bits +cd "${dstdir}" || exit 1 +chmod -R u=rwX,go=rX . >/dev/null 2>&1 +chown -R `id | sed 's/^uid=\([0-9]*\).*gid=\([0-9]*\).*$/\1:\2/'` . >/dev/null 2>&1 + +# ignore errors on unrelated files +exit 0 diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/randconfig.sh b/l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/randconfig.sh new file mode 100644 index 00000000..4c7126bb --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/randconfig.sh @@ -0,0 +1,44 @@ +#!/bin/sh + +# build random configurations +# Usage: +# ARCH=i386 nohup ./extra/scripts/randconfig.sh & sleep 1800 && touch STOP +# +# The above builds random i386 configs and automatically stops after 30 minutes + +test "x$AWK" = "x" && AWK=awk +test "x$ARCH" = "x" && ARCH=`uname -m` +KCONFIG_ALLCONFIG=.config.allconfig +(echo TARGET_$ARCH=y + echo '# UCLIBC_PREGENERATED_LOCALE_DATA is not set' + echo '# DOMULTI is not set' + echo '# UCLIBC_DOWNLOAD_PREGENERATED_LOCALE_DATA is not set' +) > $KCONFIG_ALLCONFIG +export KCONFIG_ALLCONFIG + +if test "x$NCPU" = "x" +then + test -r /proc/cpuinfo && \ + eval `$AWK 'BEGIN{NCPU=0} +/processor/{let NCPU++} +END{if (NCPU<1) {NCPU=1}; print("NCPU="NCPU);}' /proc/cpuinfo` || \ + NCPU=1 +fi +MAKELEVEL="-j$NCPU" +i=0 +while test ! -f STOP +do + ARCH=$ARCH make $* randconfig > /dev/null + ARCH=$ARCH make $* silentoldconfig > /dev/null + if (make $MAKELEVEL $*) 2>&1 >& mk.log + then + : + else + i=`expr $i + 1` + num=`printf "%.5d" $i` + mv .config FAILED.$num.config + mv mk.log FAILED.$num.log + fi + make distclean > /dev/null || true +done +rm -f STOP diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/relative_path.sh b/l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/relative_path.sh new file mode 100755 index 00000000..4dddefac --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/relative_path.sh @@ -0,0 +1,47 @@ +#! /bin/sh +# +# Copyright 2003 Alexandre Oliva +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +# This script computes a relative pathname from $1 to $2 +# They are assumed to not contain . or .. pathname components, +# but if both directories exist and cd/pwd canonicalizes pathnames, +# this shouldn't matter. PWD_CMD may be set to some pwd command that does. + +from=`(cd $1 > /dev/null && ${PWD_CMD-pwd} || echo $1) 2>/dev/null | sed 's,//*,/,g;s,/*$,,'` +target=`(cd $2 > /dev/null && ${PWD_CMD-pwd} || echo $2) 2>/dev/null | sed 's,//*,/,g;s,/*$,,'` + +case $from in /* | "") ;; *) from=`${PWD_CMD-pwd}`/$from ;; esac +case $target in /* | "") ;; *) target=`${PWD_CMD-pwd}`/$target ;; esac + +case $target in +"$from" | "$from/"*) + dots=`echo $from | sed s,.,.,g` + echo $target | sed "s,^$dots/*,,;s,[^/]$,&/," + exit 0 + ;; +esac + +case $from in +"$target/"*) + dots=`echo $target | sed s,.,.,g` + echo $from/ | sed "s,^$dots/*,,;s,[^/]$,&/,;s,[^/]*/*,../,g;s,[^/]$,&/," + exit 0 + ;; +esac + +# Without trailing slash, from=/usr/lib and target=/uclibc/lib +# mistakenly concludes that prefix=/u +#prefix=`echo $from///$target | sed 's,\(\(/[^/]*\)*\).*///\1.*,\1,'` +prefix=`echo $from///$target | sed 's,\(\(/[^/]*\)*/\).*///\1.*,\1,'` +dots=`echo $prefix | sed s,.,.,g` +from=`echo $from | sed "s,^$dots,,"` +target=`echo $target | sed "s,^$dots,,"` + +from=`echo $from | sed 's,[^/][^/]*,..,g;s,.$,&/,'` +echo ${from}$target/ + +exit 0 diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/relinfo.pl b/l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/relinfo.pl new file mode 100755 index 00000000..ec4a5df1 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/relinfo.pl @@ -0,0 +1,78 @@ +#! /usr/bin/perl +eval "exec /usr/bin/perl -S $0 $*" + if 0; +# Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 Red Hat, Inc. +# Written by Ulrich Drepper , 2000. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +for ($cnt = 0; $cnt <= $#ARGV; ++$cnt) { + $relent = 0; + $relsz = 0; + $relcount = 0; + $pltrelsz = 0; + $extplt = 0; + $users = 0; + + open (READLINK, "readlink -f $ARGV[$cnt] |") || die "cannot open readlink"; + while () { + chop; + $fullpath = $_; + } + close (READLINK); + + open (READELF, "eu-readelf -d $ARGV[$cnt] |") || die "cannot open $ARGV[$cnt]"; + while () { + chop; + if (/.* RELA?ENT *([0-9]*).*/) { + $relent = $1 + 0; + } elsif (/.* RELA?SZ *([0-9]*).*/) { + $relsz = $1 + 0; + } elsif (/.* RELA?COUNT *([0-9]*).*/) { + $relcount = $1 + 0; + } elsif (/.* PLTRELSZ *([0-9]*).*/) { + $pltrelsz = $1 + 0; + } + } + close (READELF); + + open (READELF, "eu-readelf -r $ARGV[$cnt] | sed '/'.gnu.conflict'/,/^\$/d' |") || die "cannot open $ARGV[$cnt]"; + while () { + chop; + if (/.*JU?MP_SLOT *0+ .*/) { + ++$extplt; + } + } + close (READELF); + + if (open (PRELINK, "/usr/sbin/prelink -p 2>/dev/null | fgrep \"$fullpath\" |")) { + while () { + ++$users; + } + close(PRELINK); + } else { + $users = -1; + } + + printf ("%s: %d relocations, %d relative (%d%%), %d PLT entries, %d for local syms (%d%%)", + $ARGV[$cnt], $relent == 0 ? 0 : $relsz / $relent, $relcount, + $relent == 0 ? 0 : ($relcount * 100) / ($relsz / $relent), + $relent == 0 ? 0 : $pltrelsz / $relent, + $relent == 0 ? 0 : $pltrelsz / $relent - $extplt, + $relent == 0 ? 0 : (($pltrelsz / $relent - $extplt) * 100) / ($pltrelsz / $relent)); + if ($users >= 0) { + printf(", %d users", $users); + } + printf("\n"); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/unifdef.c b/l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/unifdef.c new file mode 100644 index 00000000..abc39966 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/unifdef.c @@ -0,0 +1,1074 @@ +/* + * Copyright (c) 2002 - 2005 Tony Finch . All rights reserved. + * + * This code is derived from software contributed to Berkeley by Dave Yost. + * It was rewritten to support ANSI C by Tony Finch. The original version of + * unifdef carried the following copyright notice. None of its code remains + * in this version (though some of the names remain). + * + * Copyright (c) 1985, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#ifndef lint +#if 0 +static const char copyright[] = +"@(#) Copyright (c) 1985, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif +#ifdef __IDSTRING +__IDSTRING(Berkeley, "@(#)unifdef.c 8.1 (Berkeley) 6/6/93"); +__IDSTRING(NetBSD, "$NetBSD: unifdef.c,v 1.8 2000/07/03 02:51:36 matt Exp $"); +__IDSTRING(dotat, "$dotat: things/unifdef.c,v 1.171 2005/03/08 12:38:48 fanf2 Exp $"); +#endif +#endif /* not lint */ +#ifdef __FBSDID +__FBSDID("$FreeBSD: /repoman/r/ncvs/src/usr.bin/unifdef/unifdef.c,v 1.20 2005/05/21 09:55:09 ru Exp $"); +#endif + +/* + * unifdef - remove ifdef'ed lines + * + * Wishlist: + * provide an option which will append the name of the + * appropriate symbol after #else's and #endif's + * provide an option which will check symbols after + * #else's and #endif's to see that they match their + * corresponding #ifdef or #ifndef + * + * The first two items above require better buffer handling, which would + * also make it possible to handle all "dodgy" directives correctly. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* Avoid err.h since uClibc can disable these things */ +#define vwarnx(fmt, args) ({ fprintf(stderr, "unifdef: "); vfprintf(stderr, fmt, args); fprintf(stderr, "\n"); }) +#define warnx(fmt, args...) fprintf(stderr, "unifdef: " fmt "\n", ## args) +#define errx(exit_code, fmt, args...) ({ warnx(fmt, ## args); exit(exit_code); }) +#define err(exit_code, fmt, args...) errx(exit_code, fmt ": %s", ## args, strerror(errno)) + +size_t strlcpy(char *dst, const char *src, size_t siz); + +/* types of input lines: */ +typedef enum { + LT_TRUEI, /* a true #if with ignore flag */ + LT_FALSEI, /* a false #if with ignore flag */ + LT_IF, /* an unknown #if */ + LT_TRUE, /* a true #if */ + LT_FALSE, /* a false #if */ + LT_ELIF, /* an unknown #elif */ + LT_ELTRUE, /* a true #elif */ + LT_ELFALSE, /* a false #elif */ + LT_ELSE, /* #else */ + LT_ENDIF, /* #endif */ + LT_DODGY, /* flag: directive is not on one line */ + LT_DODGY_LAST = LT_DODGY + LT_ENDIF, + LT_PLAIN, /* ordinary line */ + LT_EOF, /* end of file */ + LT_COUNT +} Linetype; + +static char const * const linetype_name[] = { + "TRUEI", "FALSEI", "IF", "TRUE", "FALSE", + "ELIF", "ELTRUE", "ELFALSE", "ELSE", "ENDIF", + "DODGY TRUEI", "DODGY FALSEI", + "DODGY IF", "DODGY TRUE", "DODGY FALSE", + "DODGY ELIF", "DODGY ELTRUE", "DODGY ELFALSE", + "DODGY ELSE", "DODGY ENDIF", + "PLAIN", "EOF" +}; + +/* state of #if processing */ +typedef enum { + IS_OUTSIDE, + IS_FALSE_PREFIX, /* false #if followed by false #elifs */ + IS_TRUE_PREFIX, /* first non-false #(el)if is true */ + IS_PASS_MIDDLE, /* first non-false #(el)if is unknown */ + IS_FALSE_MIDDLE, /* a false #elif after a pass state */ + IS_TRUE_MIDDLE, /* a true #elif after a pass state */ + IS_PASS_ELSE, /* an else after a pass state */ + IS_FALSE_ELSE, /* an else after a true state */ + IS_TRUE_ELSE, /* an else after only false states */ + IS_FALSE_TRAILER, /* #elifs after a true are false */ + IS_COUNT +} Ifstate; + +static char const * const ifstate_name[] = { + "OUTSIDE", "FALSE_PREFIX", "TRUE_PREFIX", + "PASS_MIDDLE", "FALSE_MIDDLE", "TRUE_MIDDLE", + "PASS_ELSE", "FALSE_ELSE", "TRUE_ELSE", + "FALSE_TRAILER" +}; + +/* state of comment parser */ +typedef enum { + NO_COMMENT = false, /* outside a comment */ + C_COMMENT, /* in a comment like this one */ + CXX_COMMENT, /* between // and end of line */ + STARTING_COMMENT, /* just after slash-backslash-newline */ + FINISHING_COMMENT, /* star-backslash-newline in a C comment */ + CHAR_LITERAL, /* inside '' */ + STRING_LITERAL /* inside "" */ +} Comment_state; + +static char const * const comment_name[] = { + "NO", "C", "CXX", "STARTING", "FINISHING", "CHAR", "STRING" +}; + +/* state of preprocessor line parser */ +typedef enum { + LS_START, /* only space and comments on this line */ + LS_HASH, /* only space, comments, and a hash */ + LS_DIRTY /* this line can't be a preprocessor line */ +} Line_state; + +static char const * const linestate_name[] = { + "START", "HASH", "DIRTY" +}; + +/* + * Minimum translation limits from ISO/IEC 9899:1999 5.2.4.1 + */ +#define MAXDEPTH 64 /* maximum #if nesting */ +#define MAXLINE 4096 /* maximum length of line */ +#define MAXSYMS 4096 /* maximum number of symbols */ + +/* + * Sometimes when editing a keyword the replacement text is longer, so + * we leave some space at the end of the tline buffer to accommodate this. + */ +#define EDITSLOP 10 + +/* + * Globals. + */ + +static bool complement; /* -c: do the complement */ +static bool debugging; /* -d: debugging reports */ +static bool iocccok; /* -e: fewer IOCCC errors */ +static bool killconsts; /* -k: eval constant #ifs */ +static bool lnblank; /* -l: blank deleted lines */ +static bool lnnum; /* -n: add #line directives */ +static bool symlist; /* -s: output symbol list */ +static bool text; /* -t: this is a text file */ + +static const char *symname[MAXSYMS]; /* symbol name */ +static const char *value[MAXSYMS]; /* -Dsym=value */ +static bool ignore[MAXSYMS]; /* -iDsym or -iUsym */ +static int nsyms; /* number of symbols */ + +static FILE *input; /* input file pointer */ +static const char *filename; /* input file name */ +static int linenum; /* current line number */ + +static char tline[MAXLINE+EDITSLOP];/* input buffer plus space */ +static char *keyword; /* used for editing #elif's */ + +static Comment_state incomment; /* comment parser state */ +static Line_state linestate; /* #if line parser state */ +static Ifstate ifstate[MAXDEPTH]; /* #if processor state */ +static bool ignoring[MAXDEPTH]; /* ignore comments state */ +static int stifline[MAXDEPTH]; /* start of current #if */ +static int depth; /* current #if nesting */ +static int delcount; /* count of deleted lines */ +static bool keepthis; /* don't delete constant #if */ + +static int exitstat; /* program exit status */ + +static void addsym(bool, bool, char *); +static void debug(const char *, ...); +static void done(void); +static void error(const char *); +static int findsym(const char *); +static void flushline(bool); +static Linetype get_line(void); +static Linetype ifeval(const char **); +static void ignoreoff(void); +static void ignoreon(void); +static void keywordedit(const char *); +static void nest(void); +static void process(void); +static const char *skipcomment(const char *); +static const char *skipsym(const char *); +static void state(Ifstate); +static int strlcmp(const char *, const char *, size_t); +static void unnest(void); +static void usage(void); + +#define endsym(c) (!isalpha((unsigned char)c) && !isdigit((unsigned char)c) && c != '_') + +/* + * The main program. + */ +int +main(int argc, char *argv[]) +{ + int opt; + + while ((opt = getopt(argc, argv, "i:D:U:I:cdeklnst")) != -1) + switch (opt) { + case 'i': /* treat stuff controlled by these symbols as text */ + /* + * For strict backwards-compatibility the U or D + * should be immediately after the -i but it doesn't + * matter much if we relax that requirement. + */ + opt = *optarg++; + if (opt == 'D') + addsym(true, true, optarg); + else if (opt == 'U') + addsym(true, false, optarg); + else + usage(); + break; + case 'D': /* define a symbol */ + addsym(false, true, optarg); + break; + case 'U': /* undef a symbol */ + addsym(false, false, optarg); + break; + case 'I': + /* no-op for compatibility with cpp */ + break; + case 'c': /* treat -D as -U and vice versa */ + complement = true; + break; + case 'd': + debugging = true; + break; + case 'e': /* fewer errors from dodgy lines */ + iocccok = true; + break; + case 'k': /* process constant #ifs */ + killconsts = true; + break; + case 'l': /* blank deleted lines instead of omitting them */ + lnblank = true; + break; + case 'n': /* add #line directive after deleted lines */ + lnnum = true; + break; + case 's': /* only output list of symbols that control #ifs */ + symlist = true; + break; + case 't': /* don't parse C comments */ + text = true; + break; + default: + usage(); + } + argc -= optind; + argv += optind; + if (argc > 1) { + errx(2, "can only do one file"); + } else if (argc == 1 && strcmp(*argv, "-") != 0) { + filename = *argv; + input = fopen(filename, "r"); + if (input == NULL) + err(2, "can't open %s", filename); + } else { + filename = "[stdin]"; + input = stdin; + } + process(); + debug("bug at line %d", __LINE__); + abort(); /* bug */ +} + +static void +usage(void) +{ + fprintf(stderr, "usage: unifdef [-cdeklnst] [-Ipath]" + " [-Dsym[=val]] [-Usym] [-iDsym[=val]] [-iUsym] ... [file]\n"); + exit(2); +} + +/* + * A state transition function alters the global #if processing state + * in a particular way. The table below is indexed by the current + * processing state and the type of the current line. + * + * Nesting is handled by keeping a stack of states; some transition + * functions increase or decrease the depth. They also maintain the + * ignore state on a stack. In some complicated cases they have to + * alter the preprocessor directive, as follows. + * + * When we have processed a group that starts off with a known-false + * #if/#elif sequence (which has therefore been deleted) followed by a + * #elif that we don't understand and therefore must keep, we edit the + * latter into a #if to keep the nesting correct. + * + * When we find a true #elif in a group, the following block will + * always be kept and the rest of the sequence after the next #elif or + * #else will be discarded. We edit the #elif into a #else and the + * following directive to #endif since this has the desired behaviour. + * + * "Dodgy" directives are split across multiple lines, the most common + * example being a multi-line comment hanging off the right of the + * directive. We can handle them correctly only if there is no change + * from printing to dropping (or vice versa) caused by that directive. + * If the directive is the first of a group we have a choice between + * failing with an error, or passing it through unchanged instead of + * evaluating it. The latter is not the default to avoid questions from + * users about unifdef unexpectedly leaving behind preprocessor directives. + */ +typedef void state_fn(void); + +/* report an error */ +static void Eelif (void) { error("Inappropriate #elif"); } +static void Eelse (void) { error("Inappropriate #else"); } +static void Eendif(void) { error("Inappropriate #endif"); } +static void Eeof (void) { error("Premature EOF"); } +static void Eioccc(void) { error("Obfuscated preprocessor control line"); } +/* plain line handling */ +static void print (void) { flushline(true); } +static void drop (void) { flushline(false); } +/* output lacks group's start line */ +static void Strue (void) { drop(); ignoreoff(); state(IS_TRUE_PREFIX); } +static void Sfalse(void) { drop(); ignoreoff(); state(IS_FALSE_PREFIX); } +static void Selse (void) { drop(); state(IS_TRUE_ELSE); } +/* print/pass this block */ +static void Pelif (void) { print(); ignoreoff(); state(IS_PASS_MIDDLE); } +static void Pelse (void) { print(); state(IS_PASS_ELSE); } +static void Pendif(void) { print(); unnest(); } +/* discard this block */ +static void Dfalse(void) { drop(); ignoreoff(); state(IS_FALSE_TRAILER); } +static void Delif (void) { drop(); ignoreoff(); state(IS_FALSE_MIDDLE); } +static void Delse (void) { drop(); state(IS_FALSE_ELSE); } +static void Dendif(void) { drop(); unnest(); } +/* first line of group */ +static void Fdrop (void) { nest(); Dfalse(); } +static void Fpass (void) { nest(); Pelif(); } +static void Ftrue (void) { nest(); Strue(); } +static void Ffalse(void) { nest(); Sfalse(); } +/* variable pedantry for obfuscated lines */ +static void Oiffy (void) { if (!iocccok) Eioccc(); Fpass(); ignoreon(); } +static void Oif (void) { if (!iocccok) Eioccc(); Fpass(); } +static void Oelif (void) { if (!iocccok) Eioccc(); Pelif(); } +/* ignore comments in this block */ +static void Idrop (void) { Fdrop(); ignoreon(); } +static void Itrue (void) { Ftrue(); ignoreon(); } +static void Ifalse(void) { Ffalse(); ignoreon(); } +/* edit this line */ +static void Mpass (void) { strncpy(keyword, "if ", 4); Pelif(); } +static void Mtrue (void) { keywordedit("else\n"); state(IS_TRUE_MIDDLE); } +static void Melif (void) { keywordedit("endif\n"); state(IS_FALSE_TRAILER); } +static void Melse (void) { keywordedit("endif\n"); state(IS_FALSE_ELSE); } + +static state_fn * const trans_table[IS_COUNT][LT_COUNT] = { +/* IS_OUTSIDE */ +{ Itrue, Ifalse,Fpass, Ftrue, Ffalse,Eelif, Eelif, Eelif, Eelse, Eendif, + Oiffy, Oiffy, Fpass, Oif, Oif, Eelif, Eelif, Eelif, Eelse, Eendif, + print, done }, +/* IS_FALSE_PREFIX */ +{ Idrop, Idrop, Fdrop, Fdrop, Fdrop, Mpass, Strue, Sfalse,Selse, Dendif, + Idrop, Idrop, Fdrop, Fdrop, Fdrop, Mpass, Eioccc,Eioccc,Eioccc,Eioccc, + drop, Eeof }, +/* IS_TRUE_PREFIX */ +{ Itrue, Ifalse,Fpass, Ftrue, Ffalse,Dfalse,Dfalse,Dfalse,Delse, Dendif, + Oiffy, Oiffy, Fpass, Oif, Oif, Eioccc,Eioccc,Eioccc,Eioccc,Eioccc, + print, Eeof }, +/* IS_PASS_MIDDLE */ +{ Itrue, Ifalse,Fpass, Ftrue, Ffalse,Pelif, Mtrue, Delif, Pelse, Pendif, + Oiffy, Oiffy, Fpass, Oif, Oif, Pelif, Oelif, Oelif, Pelse, Pendif, + print, Eeof }, +/* IS_FALSE_MIDDLE */ +{ Idrop, Idrop, Fdrop, Fdrop, Fdrop, Pelif, Mtrue, Delif, Pelse, Pendif, + Idrop, Idrop, Fdrop, Fdrop, Fdrop, Eioccc,Eioccc,Eioccc,Eioccc,Eioccc, + drop, Eeof }, +/* IS_TRUE_MIDDLE */ +{ Itrue, Ifalse,Fpass, Ftrue, Ffalse,Melif, Melif, Melif, Melse, Pendif, + Oiffy, Oiffy, Fpass, Oif, Oif, Eioccc,Eioccc,Eioccc,Eioccc,Pendif, + print, Eeof }, +/* IS_PASS_ELSE */ +{ Itrue, Ifalse,Fpass, Ftrue, Ffalse,Eelif, Eelif, Eelif, Eelse, Pendif, + Oiffy, Oiffy, Fpass, Oif, Oif, Eelif, Eelif, Eelif, Eelse, Pendif, + print, Eeof }, +/* IS_FALSE_ELSE */ +{ Idrop, Idrop, Fdrop, Fdrop, Fdrop, Eelif, Eelif, Eelif, Eelse, Dendif, + Idrop, Idrop, Fdrop, Fdrop, Fdrop, Eelif, Eelif, Eelif, Eelse, Eioccc, + drop, Eeof }, +/* IS_TRUE_ELSE */ +{ Itrue, Ifalse,Fpass, Ftrue, Ffalse,Eelif, Eelif, Eelif, Eelse, Dendif, + Oiffy, Oiffy, Fpass, Oif, Oif, Eelif, Eelif, Eelif, Eelse, Eioccc, + print, Eeof }, +/* IS_FALSE_TRAILER */ +{ Idrop, Idrop, Fdrop, Fdrop, Fdrop, Dfalse,Dfalse,Dfalse,Delse, Dendif, + Idrop, Idrop, Fdrop, Fdrop, Fdrop, Dfalse,Dfalse,Dfalse,Delse, Eioccc, + drop, Eeof } +/*TRUEI FALSEI IF TRUE FALSE ELIF ELTRUE ELFALSE ELSE ENDIF + TRUEI FALSEI IF TRUE FALSE ELIF ELTRUE ELFALSE ELSE ENDIF (DODGY) + PLAIN EOF */ +}; + +/* + * State machine utility functions + */ +static void +done(void) +{ + if (incomment) + error("EOF in comment"); + exit(exitstat); +} +static void +ignoreoff(void) +{ + if (depth == 0) { + debug("bug at line %d", __LINE__); + abort(); /* bug */ + } + ignoring[depth] = ignoring[depth-1]; +} +static void +ignoreon(void) +{ + ignoring[depth] = true; +} +static void +keywordedit(const char *replacement) +{ + size_t size = tline + sizeof(tline) - keyword; + char *dst = keyword; + const char *src = replacement; + if (size != 0) { + while ((--size != 0) && (*src != '\0')) + *dst++ = *src++; + *dst = '\0'; + } + print(); +} +static void +nest(void) +{ + depth += 1; + if (depth >= MAXDEPTH) + error("Too many levels of nesting"); + stifline[depth] = linenum; +} +static void +unnest(void) +{ + if (depth == 0) { + debug("bug at line %d", __LINE__); + abort(); /* bug */ + } + depth -= 1; +} +static void +state(Ifstate is) +{ + ifstate[depth] = is; +} + +/* + * Write a line to the output or not, according to command line options. + */ +static void +flushline(bool keep) +{ + if (symlist) + return; + if (keep ^ complement) { + if (lnnum && delcount > 0) + printf("#line %d\n", linenum); + fputs(tline, stdout); + delcount = 0; + } else { + if (lnblank) + putc('\n', stdout); + exitstat = 1; + delcount += 1; + } +} + +/* + * The driver for the state machine. + */ +static void +process(void) +{ + Linetype lineval; + + for (;;) { + linenum++; + lineval = get_line(); + trans_table[ifstate[depth]][lineval](); + debug("process %s -> %s depth %d", + linetype_name[lineval], + ifstate_name[ifstate[depth]], depth); + } +} + +/* + * Parse a line and determine its type. We keep the preprocessor line + * parser state between calls in the global variable linestate, with + * help from skipcomment(). + */ +static Linetype +get_line(void) +{ + const char *cp; + int cursym; + int kwlen; + Linetype retval; + Comment_state wascomment; + + if (fgets(tline, MAXLINE, input) == NULL) + return (LT_EOF); + retval = LT_PLAIN; + wascomment = incomment; + cp = skipcomment(tline); + if (linestate == LS_START) { + if (*cp == '#') { + linestate = LS_HASH; + cp = skipcomment(cp + 1); + } else if (*cp != '\0') + linestate = LS_DIRTY; + } + if (!incomment && linestate == LS_HASH) { + keyword = tline + (cp - tline); + cp = skipsym(cp); + kwlen = cp - keyword; + /* no way can we deal with a continuation inside a keyword */ + if (strncmp(cp, "\\\n", 2) == 0) + Eioccc(); + if (strlcmp("ifdef", keyword, kwlen) == 0 || + strlcmp("ifndef", keyword, kwlen) == 0) { + cp = skipcomment(cp); + if ((cursym = findsym(cp)) < 0) + retval = LT_IF; + else { + retval = (keyword[2] == 'n') + ? LT_FALSE : LT_TRUE; + if (value[cursym] == NULL) + retval = (retval == LT_TRUE) + ? LT_FALSE : LT_TRUE; + if (ignore[cursym]) + retval = (retval == LT_TRUE) + ? LT_TRUEI : LT_FALSEI; + } + cp = skipsym(cp); + } else if (strlcmp("if", keyword, kwlen) == 0) + retval = ifeval(&cp); + else if (strlcmp("elif", keyword, kwlen) == 0) + retval = ifeval(&cp) - LT_IF + LT_ELIF; + else if (strlcmp("else", keyword, kwlen) == 0) + retval = LT_ELSE; + else if (strlcmp("endif", keyword, kwlen) == 0) + retval = LT_ENDIF; + else { + linestate = LS_DIRTY; + retval = LT_PLAIN; + } + cp = skipcomment(cp); + if (*cp != '\0') { + linestate = LS_DIRTY; + if (retval == LT_TRUE || retval == LT_FALSE || + retval == LT_TRUEI || retval == LT_FALSEI) + retval = LT_IF; + if (retval == LT_ELTRUE || retval == LT_ELFALSE) + retval = LT_ELIF; + } + if (retval != LT_PLAIN && (wascomment || incomment)) { + retval += LT_DODGY; + if (incomment) + linestate = LS_DIRTY; + } + /* skipcomment should have changed the state */ +// Hmm hppens sometimes on valid files +// if (linestate == LS_HASH) { +// debug("bug at line %d", __LINE__); +// abort(); /* bug */ +// } + } + if (linestate == LS_DIRTY) { + while (*cp != '\0') + cp = skipcomment(cp + 1); + } + debug("parser %s comment %s line", + comment_name[incomment], linestate_name[linestate]); + return (retval); +} + +/* + * These are the binary operators that are supported by the expression + * evaluator. Note that if support for division is added then we also + * need short-circuiting booleans because of divide-by-zero. + */ +static int op_lt(int a, int b) { return (a < b); } +static int op_gt(int a, int b) { return (a > b); } +static int op_le(int a, int b) { return (a <= b); } +static int op_ge(int a, int b) { return (a >= b); } +static int op_eq(int a, int b) { return (a == b); } +static int op_ne(int a, int b) { return (a != b); } +static int op_or(int a, int b) { return (a || b); } +static int op_and(int a, int b) { return (a && b); } + +/* + * An evaluation function takes three arguments, as follows: (1) a pointer to + * an element of the precedence table which lists the operators at the current + * level of precedence; (2) a pointer to an integer which will receive the + * value of the expression; and (3) a pointer to a char* that points to the + * expression to be evaluated and that is updated to the end of the expression + * when evaluation is complete. The function returns LT_FALSE if the value of + * the expression is zero, LT_TRUE if it is non-zero, or LT_IF if the + * expression could not be evaluated. + */ +struct ops; + +typedef Linetype eval_fn(const struct ops *, int *, const char **); + +static eval_fn eval_table, eval_unary; + +/* + * The precedence table. Expressions involving binary operators are evaluated + * in a table-driven way by eval_table. When it evaluates a subexpression it + * calls the inner function with its first argument pointing to the next + * element of the table. Innermost expressions have special non-table-driven + * handling. + */ +static const struct ops { + eval_fn *inner; + struct op { + const char *str; + int short_circuit_val; + int (*fn)(int, int); + } op[5]; +} eval_ops[] = { + { eval_table, { { "||", 1, op_or } } }, + { eval_table, { { "&&", 0, op_and } } }, + { eval_table, { { "==", -1, op_eq }, + { "!=", -1, op_ne } } }, + { eval_unary, { { "<=", -1, op_le }, + { ">=", -1, op_ge }, + { "<", -1, op_lt }, + { ">", -1, op_gt } } } +}; + +/* + * Function for evaluating the innermost parts of expressions, viz. + * "!expr", "(expr)", "defined(symbol)", "defined symbol", "symbol", "number". + * We reset the keepthis flag when we find a non-constant subexpression. + */ +// TODO: we use LT_IF both as "I don't know whether it's false or true" +// (example: "#if defined FOO") and when we see syntax error +// (example: "#if (1 || 2" - no closing paren!), but this is wrong. +// Binary && and || need to distinguish these cases in order to handle this: +// "#if defined KNOWN_UNDEFINED && FOO" - discard +// "#if defined KNOWN_UNDEFINED && (syntax_error_here" - do not discard! +static Linetype +eval_unary(const struct ops *ops, int *valp, const char **cpp) +{ + const char *cp; + char *ep; + int sym; + + cp = skipcomment(*cpp); + if (*cp == '!') { + debug("eval%d !", ops - eval_ops); + cp++; + if (eval_unary(ops, valp, &cp) == LT_IF) { + *cpp = cp; + return (LT_IF); + } + *valp = !*valp; + + } else if (*cp == '(') { + Linetype expr_res; + + cp++; + debug("eval%d (%s", ops - eval_ops, cp); + expr_res = eval_table(eval_ops, valp, &cp); + cp = skipcomment(cp); + *cpp = cp; + if (*cp++ != ')') + return (LT_IF); + *cpp = cp; + if (expr_res == LT_IF) + return (LT_IF); + + } else if (isdigit((unsigned char)*cp)) { + debug("eval%d number", ops - eval_ops); + *valp = strtol(cp, &ep, 0); + cp = skipsym(cp); + + } else if (strncmp(cp, "defined", 7) == 0 && endsym(cp[7])) { + bool parens; + + cp = skipcomment(cp+7); + debug("eval%d defined '%s'", ops - eval_ops, cp); + parens = (*cp == '('); + if (parens) + cp = skipcomment(cp+1); + sym = findsym(cp); + cp = skipsym(cp); + cp = skipcomment(cp); + if (parens) { + if (*cp != ')') + return (LT_IF); + cp = skipcomment(cp+1); + } + *cpp = cp; + if (sym < 0) { + debug("sym not found, returning LT_IF"); + return (LT_IF); + } + *valp = (value[sym] != NULL); + keepthis = false; + + } else if (!endsym(*cp)) { + debug("eval%d symbol", ops - eval_ops); + sym = findsym(cp); + cp = skipsym(cp); + *cpp = cp; + if (sym < 0) + return (LT_IF); + if (value[sym] == NULL) + *valp = 0; + else { + *valp = strtol(value[sym], &ep, 0); + if (*ep != '\0' || ep == value[sym]) + return (LT_IF); + } + keepthis = false; + + } else { + debug("eval%d bad expr", ops - eval_ops); + return (LT_IF); + } + + *cpp = cp; + debug("eval%d = %d", ops - eval_ops, *valp); + return (*valp ? LT_TRUE : LT_FALSE); +} + +/* + * Table-driven evaluation of binary operators. + */ +static Linetype +eval_table(const struct ops *ops, int *valp, const char **cpp) +{ + Linetype left_side; + const struct op *op; + const char *cp; + int val; + + debug("eval%d '%s'", ops - eval_ops, *cpp); + left_side = ops->inner(ops+1, valp, cpp); + cp = *cpp; + + for (;;) { + Linetype right_side; + + cp = skipcomment(cp); + for (op = ops->op; op->str != NULL; op++) + if (strncmp(cp, op->str, strlen(op->str)) == 0) + break; + if (op->str == NULL) + break; + cp += strlen(op->str); + debug("eval%d '%s'", ops - eval_ops, op->str); + right_side = ops->inner(ops+1, &val, &cp); + *cpp = cp; + + /* If short_circuit_val is 0 or 1, we can ignore + * right side if left size is known, and its value + * (i.e., *valp) is 0 or !0, respectively */ + if (left_side != LT_IF && op->short_circuit_val == !!*valp) { + debug("op->short_circuit_val:%d *valp:%d cp:'%s'", + op->short_circuit_val, *valp, cp); + *valp = !!*valp; + break; + } + /* Same for the right side */ + if (right_side != LT_IF && op->short_circuit_val == !!val) { + debug("op->short_circuit_val:%d val:%d cp:'%s'", + op->short_circuit_val, val, cp); + left_side = right_side; + *valp = !!val; + break; + } + + if (left_side == LT_IF || right_side == LT_IF) + return (LT_IF); + *valp = op->fn(*valp, val); + left_side = right_side; + } + + debug("eval%d = %d LT_IF:%d", ops - eval_ops, *valp, (left_side == LT_IF)); + if (left_side == LT_IF) + return (LT_IF); + return (*valp ? LT_TRUE : LT_FALSE); +} + +/* + * Evaluate the expression on a #if or #elif line. If we can work out + * the result we return LT_TRUE or LT_FALSE accordingly, otherwise we + * return just a generic LT_IF. + */ +static Linetype +ifeval(const char **cpp) +{ + int ret; + int val; + + debug("eval %s", *cpp); + keepthis = killconsts ? false : true; + ret = eval_table(eval_ops, &val, cpp); + debug("val:%d ret:%d keepthis:%d", val, ret, keepthis); + return (keepthis ? LT_IF : ret); +} + +/* + * Skip over comments, strings, and character literals and stop at the + * next character position that is not whitespace. Between calls we keep + * the comment state in the global variable incomment, and we also adjust + * the global variable linestate when we see a newline. + * XXX: doesn't cope with the buffer splitting inside a state transition. + */ +static const char * +skipcomment(const char *cp) +{ + if (text || ignoring[depth]) { + for (; isspace((unsigned char)*cp); cp++) + if (*cp == '\n') + linestate = LS_START; + return (cp); + } + while (*cp != '\0') + /* don't reset to LS_START after a line continuation */ + if (strncmp(cp, "\\\n", 2) == 0) + cp += 2; + else switch (incomment) { + case NO_COMMENT: + if (strncmp(cp, "/\\\n", 3) == 0) { + incomment = STARTING_COMMENT; + cp += 3; + } else if (strncmp(cp, "/*", 2) == 0) { + incomment = C_COMMENT; + cp += 2; + } else if (strncmp(cp, "//", 2) == 0) { + incomment = CXX_COMMENT; + cp += 2; + } else if (strncmp(cp, "\'", 1) == 0) { + incomment = CHAR_LITERAL; + linestate = LS_DIRTY; + cp += 1; + } else if (strncmp(cp, "\"", 1) == 0) { + incomment = STRING_LITERAL; + linestate = LS_DIRTY; + cp += 1; + } else if (strncmp(cp, "\n", 1) == 0) { + linestate = LS_START; + cp += 1; + } else if (strchr(" \t", *cp) != NULL) { + cp += 1; + } else + return (cp); + continue; + case CXX_COMMENT: + if (strncmp(cp, "\n", 1) == 0) { + incomment = NO_COMMENT; + linestate = LS_START; + } + cp += 1; + continue; + case CHAR_LITERAL: + case STRING_LITERAL: + if ((incomment == CHAR_LITERAL && cp[0] == '\'') || + (incomment == STRING_LITERAL && cp[0] == '\"')) { + incomment = NO_COMMENT; + cp += 1; + } else if (cp[0] == '\\') { + if (cp[1] == '\0') + cp += 1; + else + cp += 2; + } else if (strncmp(cp, "\n", 1) == 0) { + if (incomment == CHAR_LITERAL) + error("unterminated char literal"); + else + error("unterminated string literal"); + } else + cp += 1; + continue; + case C_COMMENT: + if (strncmp(cp, "*\\\n", 3) == 0) { + incomment = FINISHING_COMMENT; + cp += 3; + } else if (strncmp(cp, "*/", 2) == 0) { + incomment = NO_COMMENT; + cp += 2; + } else + cp += 1; + continue; + case STARTING_COMMENT: + if (*cp == '*') { + incomment = C_COMMENT; + cp += 1; + } else if (*cp == '/') { + incomment = CXX_COMMENT; + cp += 1; + } else { + incomment = NO_COMMENT; + linestate = LS_DIRTY; + } + continue; + case FINISHING_COMMENT: + if (*cp == '/') { + incomment = NO_COMMENT; + cp += 1; + } else + incomment = C_COMMENT; + continue; + default: + debug("bug at line %d", __LINE__); + abort(); /* bug */ + } + return (cp); +} + +/* + * Skip over an identifier. + */ +static const char * +skipsym(const char *cp) +{ + while (!endsym(*cp)) + ++cp; + return (cp); +} + +/* + * Look for the symbol in the symbol table. If is is found, we return + * the symbol table index, else we return -1. + */ +static int +findsym(const char *str) +{ + const char *cp; + int symind; + + cp = skipsym(str); + if (cp == str) + return (-1); + if (symlist) { + printf("%.*s\n", (int)(cp-str), str); + /* we don't care about the value of the symbol */ + return (0); + } + for (symind = 0; symind < nsyms; ++symind) { + if (strlcmp(symname[symind], str, cp-str) == 0) { + debug("findsym %s %s", symname[symind], + value[symind] ? value[symind] : ""); + return (symind); + } + } + return (-1); +} + +/* + * Add a symbol to the symbol table. + */ +static void +addsym(bool ignorethis, bool definethis, char *sym) +{ + int symind; + char *val; + + symind = findsym(sym); + if (symind < 0) { + if (nsyms >= MAXSYMS) + errx(2, "too many symbols"); + symind = nsyms++; + } + symname[symind] = sym; + ignore[symind] = ignorethis; + val = sym + (skipsym(sym) - sym); + if (definethis) { + if (*val == '=') { + value[symind] = val+1; + *val = '\0'; + } else if (*val == '\0') + value[symind] = ""; + else + usage(); + } else { + if (*val != '\0') + usage(); + value[symind] = NULL; + } +} + +/* + * Compare s with n characters of t. + * The same as strncmp() except that it checks that s[n] == '\0'. + */ +static int +strlcmp(const char *s, const char *t, size_t n) +{ + while (n-- && *t != '\0') + if (*s != *t) + return ((unsigned char)*s - (unsigned char)*t); + else + ++s, ++t; + return ((unsigned char)*s); +} + +/* + * Diagnostics. + */ +static void +debug(const char *msg, ...) +{ + va_list ap; + + if (debugging) { + va_start(ap, msg); + vwarnx(msg, ap); + va_end(ap); + } +} + +static void +error(const char *msg) +{ + if (depth == 0) + warnx("%s: %d: %s", filename, linenum, msg); + else + warnx("%s: %d: %s (#if line %d depth %d)", + filename, linenum, msg, stifline[depth], depth); + errx(2, "output may be truncated"); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/unifdef.test b/l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/unifdef.test new file mode 100644 index 00000000..5ba4e48d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/scripts/unifdef.test @@ -0,0 +1,67 @@ +Run me through unifdef -UA +*** Nothing should be visible here: +#if defined A && defined B +hello world +#endif +#if defined A && B +hello world +#endif +#if defined A && 1 +hello world +#endif +#if defined A && (1 > 0) +hello world +#endif +#if defined B && defined A +hello world +#endif +#if B && defined A +hello world +#endif +#if 1 && defined A +hello world +#endif +#if (1 > 0) && defined A +hello world +#endif +#if defined A && (defined FOO || defined BAR) +hello world +#endif +#if (defined FOO || defined BAR) && defined A +hello world +#endif + +*** Everything should be visible here, but #if/#endif removed: +#if defined B || !defined A +hello world 1 +#endif +#if !defined A || defined B +hello world 2 (last) +#endif + +*** This should be unchanged (#if/#endif not removed): +#if defined A || defined B +I am here 1 +#endif +#if defined B || defined A +I am here 2 +#endif +I am here 3 +#if !defined FOO && !defined BAR \ + && !defined BAZ +# error "I am here 4" +#endif +I am here 5 +#if (!defined FOO \ + && (defined BAR || defined BAZ \ + || defined XYZ)) +I am here 6 +#endif +I am here 7 +#if !defined FOO \ + && defined BAR +I am here 8 +#endif +I am here 9 (last) + +*** End diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/.gitignore b/l4/pkg/uclibc/lib/contrib/uclibc/include/.gitignore new file mode 100644 index 00000000..8df009b6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/.gitignore @@ -0,0 +1,43 @@ +# +# Never ignore these +# +!.gitignore + +# +# Generated files +# +/bits/ +/config/ + +/bfin_fixed_code.h +/bfin_l1layout.h +/bfin_sram.h +/dl-osinfo.h +/fpu_control.h +/hp-timing.h +/pthread.h +/semaphore.h +/thread_db.h +/sgidefs.h + +/sys/acct.h +/sys/asm.h +/sys/cachectl.h +/sys/debugreg.h +/sys/elf.h +/sys/epoll.h +/sys/fpregdef.h +/sys/inotify.h +/sys/io.h +/sys/perm.h +/sys/prctl.h +/sys/procfs.h +/sys/ptrace.h +/sys/reg.h +/sys/regdef.h +/sys/sysmips.h +/sys/tas.h +/sys/timerfd.h +/sys/ucontext.h +/sys/user.h +/sys/vm86.h diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/_lfs_64.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/_lfs_64.h new file mode 100644 index 00000000..deee98a7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/_lfs_64.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ +#include + +#ifdef __UCLIBC_HAS_LFS__ + +#if defined _FILE_OFFSET_BITS && _FILE_OFFSET_BITS != 64 +#undef _FILE_OFFSET_BITS +#define _FILE_OFFSET_BITS 64 +#endif + +#ifndef __USE_LARGEFILE64 +# define __USE_LARGEFILE64 1 +#endif + +/* We absolutely do _NOT_ want interfaces silently + * renamed under us or very bad things will happen... */ +#ifdef __USE_FILE_OFFSET64 +# undef __USE_FILE_OFFSET64 +#endif + +#else + +# error Do not include this header in files not built when LFS is disabled + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/a.out.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/a.out.h new file mode 100644 index 00000000..027c49ad --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/a.out.h @@ -0,0 +1 @@ +#include diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/alloca.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/alloca.h new file mode 100644 index 00000000..2565b483 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/alloca.h @@ -0,0 +1,74 @@ +/* Copyright (C) 1992, 1996, 1997, 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _ALLOCA_H +#define _ALLOCA_H 1 + +#include + +#define __need_size_t +#include + +__BEGIN_DECLS + +/* Remove any previous definitions. */ +#undef alloca + +/* Allocate a block that will be freed when the calling function exits. */ +extern void *alloca (size_t __size) __THROW; + +#ifdef __GNUC__ +# define alloca(size) __builtin_alloca (size) +#endif /* GCC. */ + +#ifdef _LIBC +# define __MAX_ALLOCA_CUTOFF 65536 + +# include +# ifdef _STACK_GROWS_DOWN +# define extend_alloca(buf, len, newlen) \ + (__typeof (buf)) ({ size_t __newlen = (newlen); \ + char *__newbuf = alloca (__newlen); \ + if (__newbuf + __newlen == (char *) buf) \ + len += __newlen; \ + else \ + len = __newlen; \ + __newbuf; }) +# elif defined _STACK_GROWS_UP +# define extend_alloca(buf, len, newlen) \ + (__typeof (buf)) ({ size_t __newlen = (newlen); \ + char *__newbuf = alloca (__newlen); \ + char *__buf = (buf); \ + if (__buf + __newlen == __newbuf) \ + { \ + len += __newlen; \ + __newbuf = __buf; \ + } \ + else \ + len = __newlen; \ + __newbuf; }) +# else +# error unknown stack +# define extend_alloca(buf, len, newlen) \ + alloca (((len) = (newlen))) +# endif +#endif + +__END_DECLS + +#endif /* alloca.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/ar.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/ar.h new file mode 100644 index 00000000..5d157eca --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/ar.h @@ -0,0 +1,48 @@ +/* Header describing `ar' archive file format. + Copyright (C) 1996 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _AR_H +#define _AR_H 1 + +#include + +/* Archive files start with the ARMAG identifying string. Then follows a + `struct ar_hdr', and as many bytes of member file data as its `ar_size' + member indicates, for each member file. */ + +#define ARMAG "!\n" /* String that begins an archive file. */ +#define SARMAG 8 /* Size of that string. */ + +#define ARFMAG "`\n" /* String in ar_fmag at end of each header. */ + +__BEGIN_DECLS + +struct ar_hdr + { + char ar_name[16]; /* Member file name, sometimes / terminated. */ + char ar_date[12]; /* File date, decimal seconds since Epoch. */ + char ar_uid[6], ar_gid[6]; /* User and group IDs, in ASCII decimal. */ + char ar_mode[8]; /* File mode, in ASCII octal. */ + char ar_size[10]; /* File size, in ASCII decimal. */ + char ar_fmag[2]; /* Always contains ARFMAG. */ + }; + +__END_DECLS + +#endif /* ar.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/arpa/ftp.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/arpa/ftp.h new file mode 100644 index 00000000..e5b340db --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/arpa/ftp.h @@ -0,0 +1,105 @@ +/* + * Copyright (c) 1983, 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ftp.h 8.1 (Berkeley) 6/2/93 + */ + +#ifndef _ARPA_FTP_H +#define _ARPA_FTP_H 1 + +/* Definitions for FTP; see RFC-765. */ + +/* + * Reply codes. + */ +#define PRELIM 1 /* positive preliminary */ +#define COMPLETE 2 /* positive completion */ +#define CONTINUE 3 /* positive intermediate */ +#define TRANSIENT 4 /* transient negative completion */ +#define ERROR 5 /* permanent negative completion */ + +/* + * Type codes + */ +#define TYPE_A 1 /* ASCII */ +#define TYPE_E 2 /* EBCDIC */ +#define TYPE_I 3 /* image */ +#define TYPE_L 4 /* local byte size */ + +#ifdef FTP_NAMES +char *typenames[] = {"0", "ASCII", "EBCDIC", "Image", "Local" }; +#endif + +/* + * Form codes + */ +#define FORM_N 1 /* non-print */ +#define FORM_T 2 /* telnet format effectors */ +#define FORM_C 3 /* carriage control (ASA) */ +#ifdef FTP_NAMES +char *formnames[] = {"0", "Nonprint", "Telnet", "Carriage-control" }; +#endif + +/* + * Structure codes + */ +#define STRU_F 1 /* file (no record structure) */ +#define STRU_R 2 /* record structure */ +#define STRU_P 3 /* page structure */ +#ifdef FTP_NAMES +char *strunames[] = {"0", "File", "Record", "Page" }; +#endif + +/* + * Mode types + */ +#define MODE_S 1 /* stream */ +#define MODE_B 2 /* block */ +#define MODE_C 3 /* compressed */ +#ifdef FTP_NAMES +char *modenames[] = {"0", "Stream", "Block", "Compressed" }; +#endif + +/* + * Record Tokens + */ +#define REC_ESC '\377' /* Record-mode Escape */ +#define REC_EOR '\001' /* Record-mode End-of-Record */ +#define REC_EOF '\002' /* Record-mode End-of-File */ + +/* + * Block Header + */ +#define BLK_EOR 0x80 /* Block is End-of-Record */ +#define BLK_EOF 0x40 /* Block is End-of-File */ +#define BLK_ERRORS 0x20 /* Block is suspected of containing errors */ +#define BLK_RESTART 0x10 /* Block is Restart Marker */ + +#define BLK_BYTECOUNT 2 /* Bytes in this block */ + +#endif /* arpa/ftp.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/arpa/inet.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/arpa/inet.h new file mode 100644 index 00000000..fbd715af --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/arpa/inet.h @@ -0,0 +1,121 @@ +/* Copyright (C) 1997, 1999, 2000, 2001, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _ARPA_INET_H +#define _ARPA_INET_H 1 + +#include +#include /* To define `struct in_addr'. */ + +/* Type for length arguments in socket calls. */ +#ifndef __socklen_t_defined +typedef __socklen_t socklen_t; +# define __socklen_t_defined +#endif + +__BEGIN_DECLS + +/* Convert Internet host address from numbers-and-dots notation in CP + into binary data in network byte order. */ +extern in_addr_t inet_addr (__const char *__cp) __THROW; +libc_hidden_proto(inet_addr) + +/* Return the local host address part of the Internet address in IN. */ +extern in_addr_t inet_lnaof (struct in_addr __in) __THROW; + +/* Make Internet host address in network byte order by combining the + network number NET with the local address HOST. */ +extern struct in_addr inet_makeaddr (in_addr_t __net, in_addr_t __host) + __THROW; +libc_hidden_proto(inet_makeaddr) + +/* Return network number part of the Internet address IN. */ +extern in_addr_t inet_netof (struct in_addr __in) __THROW; +libc_hidden_proto(inet_netof) + +/* Extract the network number in network byte order from the address + in numbers-and-dots natation starting at CP. */ +extern in_addr_t inet_network (__const char *__cp) __THROW; +libc_hidden_proto(inet_network) + +/* Convert Internet number in IN to ASCII representation. The return value + is a pointer to an internal array containing the string. */ +extern char *inet_ntoa (struct in_addr __in) __THROW; +libc_hidden_proto(inet_ntoa) +#ifdef __UCLIBC__ +/* Recursion-safe flavor */ +extern char *inet_ntoa_r (struct in_addr __in, char *__buf) __THROW; +libc_hidden_proto(inet_ntoa_r) +#endif + +/* Convert from presentation format of an Internet number in buffer + starting at CP to the binary network format and store result for + interface type AF in buffer starting at BUF. */ +extern int inet_pton (int __af, __const char *__restrict __cp, + void *__restrict __buf) __THROW; +libc_hidden_proto(inet_pton) + +/* Convert a Internet address in binary network format for interface + type AF in buffer starting at CP to presentation form and place + result in buffer of length LEN astarting at BUF. */ +extern __const char *inet_ntop (int __af, __const void *__restrict __cp, + char *__restrict __buf, socklen_t __len) + __THROW; +libc_hidden_proto(inet_ntop) + + +/* The following functions are not part of XNS 5.2. */ +#ifdef __USE_MISC +/* Convert Internet host address from numbers-and-dots notation in CP + into binary data and store the result in the structure INP. */ +extern int inet_aton (__const char *__cp, struct in_addr *__inp) __THROW; +libc_hidden_proto(inet_aton) + +#if 0 +/* Format a network number NET into presentation format and place result + in buffer starting at BUF with length of LEN bytes. */ +extern char *inet_neta (in_addr_t __net, char *__buf, size_t __len) __THROW; + +/* Convert network number for interface type AF in buffer starting at + CP to presentation format. The result will specifiy BITS bits of + the number. */ +extern char *inet_net_ntop (int __af, __const void *__cp, int __bits, + char *__buf, size_t __len) __THROW; + +/* Convert network number for interface type AF from presentation in + buffer starting at CP to network format and store result int + buffer starting at BUF of size LEN. */ +extern int inet_net_pton (int __af, __const char *__cp, + void *__buf, size_t __len) __THROW; + +/* Convert ASCII representation in hexadecimal form of the Internet + address to binary form and place result in buffer of length LEN + starting at BUF. */ +extern unsigned int inet_nsap_addr (__const char *__cp, + unsigned char *__buf, int __len) __THROW; + +/* Convert internet address in binary form in LEN bytes starting at CP + a presentation form and place result in BUF. */ +extern char *inet_nsap_ntoa (int __len, __const unsigned char *__cp, + char *__buf) __THROW; +#endif +#endif + +__END_DECLS + +#endif /* arpa/inet.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/arpa/nameser.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/arpa/nameser.h new file mode 100644 index 00000000..917ba19b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/arpa/nameser.h @@ -0,0 +1,560 @@ +/* + * Copyright (c) 1983, 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Copyright (c) 1996-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* + * $BINDId: nameser.h,v 8.37 2000/03/30 21:16:49 vixie Exp $ + */ + +#ifndef _ARPA_NAMESER_H_ +#define _ARPA_NAMESER_H_ + +#define BIND_4_COMPAT + +#include +#if (!defined(BSD)) || (BSD < 199306) +# include +#else +# include +#endif +#include + +/* + * Revision information. This is the release date in YYYYMMDD format. + * It can change every day so the right thing to do with it is use it + * in preprocessor commands such as "#if (__NAMESER > 19931104)". Do not + * compare for equality; rather, use it to determine whether your libbind.a + * contains a new enough lib/nameser/ to support the feature you need. + */ + +#define __NAMESER 19991006 /* New interface version stamp. */ + +/* + * Define constants based on RFC 883, RFC 1034, RFC 1035 + */ +#define NS_PACKETSZ 512 /* maximum packet size */ +#define NS_MAXDNAME 1025 /* maximum domain name */ +#define NS_MAXCDNAME 255 /* maximum compressed domain name */ +#define NS_MAXLABEL 63 /* maximum length of domain label */ +#define NS_HFIXEDSZ 12 /* #/bytes of fixed data in header */ +#define NS_QFIXEDSZ 4 /* #/bytes of fixed data in query */ +#define NS_RRFIXEDSZ 10 /* #/bytes of fixed data in r record */ +#define NS_INT32SZ 4 /* #/bytes of data in a u_int32_t */ +#define NS_INT16SZ 2 /* #/bytes of data in a u_int16_t */ +#define NS_INT8SZ 1 /* #/bytes of data in a u_int8_t */ +#define NS_INADDRSZ 4 /* IPv4 T_A */ +#define NS_IN6ADDRSZ 16 /* IPv6 T_AAAA */ +#define NS_CMPRSFLGS 0xc0 /* Flag bits indicating name compression. */ +#define NS_DEFAULTPORT 53 /* For both TCP and UDP. */ + +/* + * These can be expanded with synonyms, just keep ns_parse.c:ns_parserecord() + * in synch with it. + */ +typedef enum __ns_sect { + ns_s_qd = 0, /* Query: Question. */ + ns_s_zn = 0, /* Update: Zone. */ + ns_s_an = 1, /* Query: Answer. */ + ns_s_pr = 1, /* Update: Prerequisites. */ + ns_s_ns = 2, /* Query: Name servers. */ + ns_s_ud = 2, /* Update: Update. */ + ns_s_ar = 3, /* Query|Update: Additional records. */ + ns_s_max = 4 +} ns_sect; + +/* + * This is a message handle. It is caller allocated and has no dynamic data. + * This structure is intended to be opaque to all but ns_parse.c, thus the + * leading _'s on the member names. Use the accessor functions, not the _'s. + */ +typedef struct __ns_msg { + const u_char *_msg, *_eom; + u_int16_t _id, _flags, _counts[ns_s_max]; + const u_char *_sections[ns_s_max]; + ns_sect _sect; + int _rrnum; + const u_char *_ptr; +} ns_msg; + +/* Private data structure - do not use from outside library. */ +struct _ns_flagdata { int mask, shift; }; +extern struct _ns_flagdata _ns_flagdata[]; + +/* Accessor macros - this is part of the public interface. */ +#define ns_msg_getflag(handle, flag) ( \ + ((handle)._flags & _ns_flagdata[flag].mask) \ + >> _ns_flagdata[flag].shift \ + ) +#define ns_msg_id(handle) ((handle)._id + 0) +#define ns_msg_base(handle) ((handle)._msg + 0) +#define ns_msg_end(handle) ((handle)._eom + 0) +#define ns_msg_size(handle) ((handle)._eom - (handle)._msg) +#define ns_msg_count(handle, section) ((handle)._counts[section] + 0) + +/* + * This is a parsed record. It is caller allocated and has no dynamic data. + */ +typedef struct __ns_rr { + char name[NS_MAXDNAME]; + u_int16_t type; + u_int16_t rr_class; + u_int32_t ttl; + u_int16_t rdlength; + const u_char * rdata; +} ns_rr; + +/* Accessor macros - this is part of the public interface. */ +#define ns_rr_name(rr) (((rr).name[0] != '\0') ? (rr).name : ".") +#define ns_rr_type(rr) ((ns_type)((rr).type + 0)) +#define ns_rr_class(rr) ((ns_class)((rr).rr_class + 0)) +#define ns_rr_ttl(rr) ((rr).ttl + 0) +#define ns_rr_rdlen(rr) ((rr).rdlength + 0) +#define ns_rr_rdata(rr) ((rr).rdata + 0) + +/* + * These don't have to be in the same order as in the packet flags word, + * and they can even overlap in some cases, but they will need to be kept + * in synch with ns_parse.c:ns_flagdata[]. + */ +typedef enum __ns_flag { + ns_f_qr, /* Question/Response. */ + ns_f_opcode, /* Operation code. */ + ns_f_aa, /* Authoritative Answer. */ + ns_f_tc, /* Truncation occurred. */ + ns_f_rd, /* Recursion Desired. */ + ns_f_ra, /* Recursion Available. */ + ns_f_z, /* MBZ. */ + ns_f_ad, /* Authentic Data (DNSSEC). */ + ns_f_cd, /* Checking Disabled (DNSSEC). */ + ns_f_rcode, /* Response code. */ + ns_f_max +} ns_flag; + +/* + * Currently defined opcodes. + */ +typedef enum __ns_opcode { + ns_o_query = 0, /* Standard query. */ + ns_o_iquery = 1, /* Inverse query (deprecated/unsupported). */ + ns_o_status = 2, /* Name server status query (unsupported). */ + /* Opcode 3 is undefined/reserved. */ + ns_o_notify = 4, /* Zone change notification. */ + ns_o_update = 5, /* Zone update message. */ + ns_o_max = 6 +} ns_opcode; + +/* + * Currently defined response codes. + */ +typedef enum __ns_rcode { + ns_r_noerror = 0, /* No error occurred. */ + ns_r_formerr = 1, /* Format error. */ + ns_r_servfail = 2, /* Server failure. */ + ns_r_nxdomain = 3, /* Name error. */ + ns_r_notimpl = 4, /* Unimplemented. */ + ns_r_refused = 5, /* Operation refused. */ + /* these are for BIND_UPDATE */ + ns_r_yxdomain = 6, /* Name exists */ + ns_r_yxrrset = 7, /* RRset exists */ + ns_r_nxrrset = 8, /* RRset does not exist */ + ns_r_notauth = 9, /* Not authoritative for zone */ + ns_r_notzone = 10, /* Zone of record different from zone section */ + ns_r_max = 11, + /* The following are TSIG extended errors */ + ns_r_badsig = 16, + ns_r_badkey = 17, + ns_r_badtime = 18 +} ns_rcode; + +/* BIND_UPDATE */ +typedef enum __ns_update_operation { + ns_uop_delete = 0, + ns_uop_add = 1, + ns_uop_max = 2 +} ns_update_operation; + +/* + * This structure is used for TSIG authenticated messages + */ +struct ns_tsig_key { + char name[NS_MAXDNAME], alg[NS_MAXDNAME]; + unsigned char *data; + int len; +}; +typedef struct ns_tsig_key ns_tsig_key; + +/* + * This structure is used for TSIG authenticated TCP messages + */ +struct ns_tcp_tsig_state { + int counter; + struct dst_key *key; + void *ctx; + unsigned char sig[NS_PACKETSZ]; + int siglen; +}; +typedef struct ns_tcp_tsig_state ns_tcp_tsig_state; + +#define NS_TSIG_FUDGE 300 +#define NS_TSIG_TCP_COUNT 100 +#define NS_TSIG_ALG_HMAC_MD5 "HMAC-MD5.SIG-ALG.REG.INT" + +#define NS_TSIG_ERROR_NO_TSIG -10 +#define NS_TSIG_ERROR_NO_SPACE -11 +#define NS_TSIG_ERROR_FORMERR -12 + +/* + * Currently defined type values for resources and queries. + */ +typedef enum __ns_type { + ns_t_invalid = 0, /* Cookie. */ + ns_t_a = 1, /* Host address. */ + ns_t_ns = 2, /* Authoritative server. */ + ns_t_md = 3, /* Mail destination. */ + ns_t_mf = 4, /* Mail forwarder. */ + ns_t_cname = 5, /* Canonical name. */ + ns_t_soa = 6, /* Start of authority zone. */ + ns_t_mb = 7, /* Mailbox domain name. */ + ns_t_mg = 8, /* Mail group member. */ + ns_t_mr = 9, /* Mail rename name. */ + ns_t_null = 10, /* Null resource record. */ + ns_t_wks = 11, /* Well known service. */ + ns_t_ptr = 12, /* Domain name pointer. */ + ns_t_hinfo = 13, /* Host information. */ + ns_t_minfo = 14, /* Mailbox information. */ + ns_t_mx = 15, /* Mail routing information. */ + ns_t_txt = 16, /* Text strings. */ + ns_t_rp = 17, /* Responsible person. */ + ns_t_afsdb = 18, /* AFS cell database. */ + ns_t_x25 = 19, /* X_25 calling address. */ + ns_t_isdn = 20, /* ISDN calling address. */ + ns_t_rt = 21, /* Router. */ + ns_t_nsap = 22, /* NSAP address. */ + ns_t_nsap_ptr = 23, /* Reverse NSAP lookup (deprecated). */ + ns_t_sig = 24, /* Security signature. */ + ns_t_key = 25, /* Security key. */ + ns_t_px = 26, /* X.400 mail mapping. */ + ns_t_gpos = 27, /* Geographical position (withdrawn). */ + ns_t_aaaa = 28, /* Ip6 Address. */ + ns_t_loc = 29, /* Location Information. */ + ns_t_nxt = 30, /* Next domain (security). */ + ns_t_eid = 31, /* Endpoint identifier. */ + ns_t_nimloc = 32, /* Nimrod Locator. */ + ns_t_srv = 33, /* Server Selection. */ + ns_t_atma = 34, /* ATM Address */ + ns_t_naptr = 35, /* Naming Authority PoinTeR */ + ns_t_kx = 36, /* Key Exchange */ + ns_t_cert = 37, /* Certification record */ + ns_t_a6 = 38, /* IPv6 address (deprecated, use ns_t_aaaa) */ + ns_t_dname = 39, /* Non-terminal DNAME (for IPv6) */ + ns_t_sink = 40, /* Kitchen sink (experimentatl) */ + ns_t_opt = 41, /* EDNS0 option (meta-RR) */ + ns_t_tsig = 250, /* Transaction signature. */ + ns_t_ixfr = 251, /* Incremental zone transfer. */ + ns_t_axfr = 252, /* Transfer zone of authority. */ + ns_t_mailb = 253, /* Transfer mailbox records. */ + ns_t_maila = 254, /* Transfer mail agent records. */ + ns_t_any = 255, /* Wildcard match. */ + ns_t_zxfr = 256, /* BIND-specific, nonstandard. */ + ns_t_max = 65536 +} ns_type; + +/* Exclusively a QTYPE? (not also an RTYPE) */ +#define ns_t_qt_p(t) (ns_t_xfr_p(t) || (t) == ns_t_any || \ + (t) == ns_t_mailb || (t) == ns_t_maila) +/* Some kind of meta-RR? (not a QTYPE, but also not an RTYPE) */ +#define ns_t_mrr_p(t) ((t) == ns_t_tsig || (t) == ns_t_opt) +/* Exclusively an RTYPE? (not also a QTYPE or a meta-RR) */ +#define ns_t_rr_p(t) (!ns_t_qt_p(t) && !ns_t_mrr_p(t)) +#define ns_t_udp_p(t) ((t) != ns_t_axfr && (t) != ns_t_zxfr) +#define ns_t_xfr_p(t) ((t) == ns_t_axfr || (t) == ns_t_ixfr || \ + (t) == ns_t_zxfr) + +/* + * Values for class field + */ +typedef enum __ns_class { + ns_c_invalid = 0, /* Cookie. */ + ns_c_in = 1, /* Internet. */ + ns_c_2 = 2, /* unallocated/unsupported. */ + ns_c_chaos = 3, /* MIT Chaos-net. */ + ns_c_hs = 4, /* MIT Hesiod. */ + /* Query class values which do not appear in resource records */ + ns_c_none = 254, /* for prereq. sections in update requests */ + ns_c_any = 255, /* Wildcard match. */ + ns_c_max = 65536 +} ns_class; + +/* DNSSEC constants. */ + +typedef enum __ns_key_types { + ns_kt_rsa = 1, /* key type RSA/MD5 */ + ns_kt_dh = 2, /* Diffie Hellman */ + ns_kt_dsa = 3, /* Digital Signature Standard (MANDATORY) */ + ns_kt_private = 254 /* Private key type starts with OID */ +} ns_key_types; + +typedef enum __ns_cert_types { + cert_t_pkix = 1, /* PKIX (X.509v3) */ + cert_t_spki = 2, /* SPKI */ + cert_t_pgp = 3, /* PGP */ + cert_t_url = 253, /* URL private type */ + cert_t_oid = 254 /* OID private type */ +} ns_cert_types; + +/* Flags field of the KEY RR rdata. */ +#define NS_KEY_TYPEMASK 0xC000 /* Mask for "type" bits */ +#define NS_KEY_TYPE_AUTH_CONF 0x0000 /* Key usable for both */ +#define NS_KEY_TYPE_CONF_ONLY 0x8000 /* Key usable for confidentiality */ +#define NS_KEY_TYPE_AUTH_ONLY 0x4000 /* Key usable for authentication */ +#define NS_KEY_TYPE_NO_KEY 0xC000 /* No key usable for either; no key */ +/* The type bits can also be interpreted independently, as single bits: */ +#define NS_KEY_NO_AUTH 0x8000 /* Key unusable for authentication */ +#define NS_KEY_NO_CONF 0x4000 /* Key unusable for confidentiality */ +#define NS_KEY_RESERVED2 0x2000 /* Security is *mandatory* if bit=0 */ +#define NS_KEY_EXTENDED_FLAGS 0x1000 /* reserved - must be zero */ +#define NS_KEY_RESERVED4 0x0800 /* reserved - must be zero */ +#define NS_KEY_RESERVED5 0x0400 /* reserved - must be zero */ +#define NS_KEY_NAME_TYPE 0x0300 /* these bits determine the type */ +#define NS_KEY_NAME_USER 0x0000 /* key is assoc. with user */ +#define NS_KEY_NAME_ENTITY 0x0200 /* key is assoc. with entity eg host */ +#define NS_KEY_NAME_ZONE 0x0100 /* key is zone key */ +#define NS_KEY_NAME_RESERVED 0x0300 /* reserved meaning */ +#define NS_KEY_RESERVED8 0x0080 /* reserved - must be zero */ +#define NS_KEY_RESERVED9 0x0040 /* reserved - must be zero */ +#define NS_KEY_RESERVED10 0x0020 /* reserved - must be zero */ +#define NS_KEY_RESERVED11 0x0010 /* reserved - must be zero */ +#define NS_KEY_SIGNATORYMASK 0x000F /* key can sign RR's of same name */ +#define NS_KEY_RESERVED_BITMASK ( NS_KEY_RESERVED2 | \ + NS_KEY_RESERVED4 | \ + NS_KEY_RESERVED5 | \ + NS_KEY_RESERVED8 | \ + NS_KEY_RESERVED9 | \ + NS_KEY_RESERVED10 | \ + NS_KEY_RESERVED11 ) +#define NS_KEY_RESERVED_BITMASK2 0xFFFF /* no bits defined here */ + +/* The Algorithm field of the KEY and SIG RR's is an integer, {1..254} */ +#define NS_ALG_MD5RSA 1 /* MD5 with RSA */ +#define NS_ALG_DH 2 /* Diffie Hellman KEY */ +#define NS_ALG_DSA 3 /* DSA KEY */ +#define NS_ALG_DSS NS_ALG_DSA +#define NS_ALG_EXPIRE_ONLY 253 /* No alg, no security */ +#define NS_ALG_PRIVATE_OID 254 /* Key begins with OID giving alg */ + +/* Protocol values */ +/* value 0 is reserved */ +#define NS_KEY_PROT_TLS 1 +#define NS_KEY_PROT_EMAIL 2 +#define NS_KEY_PROT_DNSSEC 3 +#define NS_KEY_PROT_IPSEC 4 +#define NS_KEY_PROT_ANY 255 + +/* Signatures */ +#define NS_MD5RSA_MIN_BITS 512 /* Size of a mod or exp in bits */ +#define NS_MD5RSA_MAX_BITS 2552 + /* Total of binary mod and exp */ +#define NS_MD5RSA_MAX_BYTES ((NS_MD5RSA_MAX_BITS+7/8)*2+3) + /* Max length of text sig block */ +#define NS_MD5RSA_MAX_BASE64 (((NS_MD5RSA_MAX_BYTES+2)/3)*4) +#define NS_MD5RSA_MIN_SIZE ((NS_MD5RSA_MIN_BITS+7)/8) +#define NS_MD5RSA_MAX_SIZE ((NS_MD5RSA_MAX_BITS+7)/8) + +#define NS_DSA_SIG_SIZE 41 +#define NS_DSA_MIN_SIZE 213 +#define NS_DSA_MAX_BYTES 405 + +/* Offsets into SIG record rdata to find various values */ +#define NS_SIG_TYPE 0 /* Type flags */ +#define NS_SIG_ALG 2 /* Algorithm */ +#define NS_SIG_LABELS 3 /* How many labels in name */ +#define NS_SIG_OTTL 4 /* Original TTL */ +#define NS_SIG_EXPIR 8 /* Expiration time */ +#define NS_SIG_SIGNED 12 /* Signature time */ +#define NS_SIG_FOOT 16 /* Key footprint */ +#define NS_SIG_SIGNER 18 /* Domain name of who signed it */ + +/* How RR types are represented as bit-flags in NXT records */ +#define NS_NXT_BITS 8 +#define NS_NXT_BIT_SET( n,p) (p[(n)/NS_NXT_BITS] |= (0x80>>((n)%NS_NXT_BITS))) +#define NS_NXT_BIT_CLEAR(n,p) (p[(n)/NS_NXT_BITS] &= ~(0x80>>((n)%NS_NXT_BITS))) +#define NS_NXT_BIT_ISSET(n,p) (p[(n)/NS_NXT_BITS] & (0x80>>((n)%NS_NXT_BITS))) +#define NS_NXT_MAX 127 + +/* + * Inline versions of get/put short/long. Pointer is advanced. + */ +#define NS_GET16(s, cp) do { \ + register u_char *t_cp = (u_char *)(cp); \ + (s) = ((u_int16_t)t_cp[0] << 8) \ + | ((u_int16_t)t_cp[1]) \ + ; \ + (cp) += NS_INT16SZ; \ +} while (0) + +#define NS_GET32(l, cp) do { \ + register u_char *t_cp = (u_char *)(cp); \ + (l) = ((u_int32_t)t_cp[0] << 24) \ + | ((u_int32_t)t_cp[1] << 16) \ + | ((u_int32_t)t_cp[2] << 8) \ + | ((u_int32_t)t_cp[3]) \ + ; \ + (cp) += NS_INT32SZ; \ +} while (0) + +#define NS_PUT16(s, cp) do { \ + register u_int16_t t_s = (u_int16_t)(s); \ + register u_char *t_cp = (u_char *)(cp); \ + *t_cp++ = t_s >> 8; \ + *t_cp = t_s; \ + (cp) += NS_INT16SZ; \ +} while (0) + +#define NS_PUT32(l, cp) do { \ + register u_int32_t t_l = (u_int32_t)(l); \ + register u_char *t_cp = (u_char *)(cp); \ + *t_cp++ = t_l >> 24; \ + *t_cp++ = t_l >> 16; \ + *t_cp++ = t_l >> 8; \ + *t_cp = t_l; \ + (cp) += NS_INT32SZ; \ +} while (0) + +/* + * ANSI C identifier hiding for bind's lib/nameser. + */ +#define ns_get16 __ns_get16 +#define ns_get32 __ns_get32 +#define ns_put16 __ns_put16 +#define ns_put32 __ns_put32 +#define ns_initparse __ns_initparse +#define ns_skiprr __ns_skiprr +#define ns_parserr __ns_parserr +#define ns_sprintrr __ns_sprintrr +#define ns_sprintrrf __ns_sprintrrf +#define ns_format_ttl __ns_format_ttl +#define ns_parse_ttl __ns_parse_ttl +#define ns_datetosecs __ns_datetosecs +#define ns_name_ntol __ns_name_ntol +#define ns_name_ntop __ns_name_ntop +#define ns_name_pton __ns_name_pton +#define ns_name_unpack __ns_name_unpack +#define ns_name_pack __ns_name_pack +#define ns_name_compress __ns_name_compress +#define ns_name_uncompress __ns_name_uncompress +#define ns_name_skip __ns_name_skip +#define ns_name_rollback __ns_name_rollback +#define ns_sign __ns_sign +#define ns_sign_tcp __ns_sign_tcp +#define ns_sign_tcp_init __ns_sign_tcp_init +#define ns_find_tsig __ns_find_tsig +#define ns_verify __ns_verify +#define ns_verify_tcp __ns_verify_tcp +#define ns_verify_tcp_init __ns_verify_tcp_init +#define ns_samedomain __ns_samedomain +#define ns_subdomain __ns_subdomain +#define ns_makecanon __ns_makecanon +#define ns_samename __ns_samename + +__BEGIN_DECLS +u_int ns_get16 (const u_char *) __THROW; +u_long ns_get32 (const u_char *) __THROW; +void ns_put16 (u_int, u_char *) __THROW; +void ns_put32 (u_long, u_char *) __THROW; +int ns_initparse (const u_char *, int, ns_msg *) __THROW; +int ns_skiprr (const u_char *, const u_char *, ns_sect, int) + __THROW; +int ns_parserr (ns_msg *, ns_sect, int, ns_rr *) __THROW; +int ns_sprintrr (const ns_msg *, const ns_rr *, + const char *, const char *, char *, size_t) + __THROW; +int ns_sprintrrf (const u_char *, size_t, const char *, + ns_class, ns_type, u_long, const u_char *, + size_t, const char *, const char *, + char *, size_t) __THROW; +int ns_format_ttl (u_long, char *, size_t) __THROW; +int ns_parse_ttl (const char *, u_long *) __THROW; +u_int32_t ns_datetosecs (const char *cp, int *errp) __THROW; +int ns_name_ntol (const u_char *, u_char *, size_t) __THROW; +int ns_name_ntop (const u_char *, char *, size_t) __THROW; +libc_hidden_proto(ns_name_ntop) +int ns_name_pton (const char *, u_char *, size_t) __THROW; +int ns_name_unpack (const u_char *, const u_char *, + const u_char *, u_char *, size_t) __THROW; +libc_hidden_proto(ns_name_unpack) +int ns_name_pack (const u_char *, u_char *, int, + const u_char **, const u_char **) __THROW; +int ns_name_uncompress (const u_char *, const u_char *, + const u_char *, char *, size_t) __THROW; +libc_hidden_proto(ns_name_uncompress) +int ns_name_compress (const char *, u_char *, size_t, + const u_char **, const u_char **) __THROW; +int ns_name_skip (const u_char **, const u_char *) __THROW; +void ns_name_rollback (const u_char *, const u_char **, + const u_char **) __THROW; +int ns_sign (u_char *, int *, int, int, void *, + const u_char *, int, u_char *, int *, time_t) __THROW; +int ns_sign_tcp (u_char *, int *, int, int, + ns_tcp_tsig_state *, int) __THROW; +int ns_sign_tcp_init (void *, const u_char *, int, + ns_tcp_tsig_state *) __THROW; +u_char *ns_find_tsig (u_char *, u_char *) __THROW; +int ns_verify (u_char *, int *, void *, const u_char *, int, + u_char *, int *, time_t *, int) __THROW; +int ns_verify_tcp (u_char *, int *, ns_tcp_tsig_state *, int) + __THROW; +int ns_verify_tcp_init (void *, const u_char *, int, + ns_tcp_tsig_state *) __THROW; +int ns_samedomain (const char *, const char *) __THROW; +int ns_subdomain (const char *, const char *) __THROW; +int ns_makecanon (const char *, char *, size_t) __THROW; +int ns_samename (const char *, const char *) __THROW; +__END_DECLS + +#ifdef BIND_4_COMPAT +#include +#endif + +#endif /* !_ARPA_NAMESER_H_ */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/arpa/nameser_compat.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/arpa/nameser_compat.h new file mode 100644 index 00000000..7fe46a16 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/arpa/nameser_compat.h @@ -0,0 +1,183 @@ +/* Copyright (c) 1983, 1989 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * from nameser.h 8.1 (Berkeley) 6/2/93 + * $BINDId: nameser_compat.h,v 8.11 1999/01/02 08:00:58 vixie Exp $ + */ + +#ifndef _ARPA_NAMESER_COMPAT_ +#define _ARPA_NAMESER_COMPAT_ + +#define __BIND 19950621 /* (DEAD) interface version stamp. */ + +#include + +/* + * Structure for query header. The order of the fields is machine- and + * compiler-dependent, depending on the byte/bit order and the layout + * of bit fields. We use bit fields only in int variables, as this + * is all ANSI requires. This requires a somewhat confusing rearrangement. + */ + +typedef struct { + unsigned id :16; /* query identification number */ +#if __BYTE_ORDER == __BIG_ENDIAN + /* fields in third byte */ + unsigned qr: 1; /* response flag */ + unsigned opcode: 4; /* purpose of message */ + unsigned aa: 1; /* authoritive answer */ + unsigned tc: 1; /* truncated message */ + unsigned rd: 1; /* recursion desired */ + /* fields in fourth byte */ + unsigned ra: 1; /* recursion available */ + unsigned unused :1; /* unused bits (MBZ as of 4.9.3a3) */ + unsigned ad: 1; /* authentic data from named */ + unsigned cd: 1; /* checking disabled by resolver */ + unsigned rcode :4; /* response code */ +#endif +#if __BYTE_ORDER == __LITTLE_ENDIAN || __BYTE_ORDER == __PDP_ENDIAN + /* fields in third byte */ + unsigned rd :1; /* recursion desired */ + unsigned tc :1; /* truncated message */ + unsigned aa :1; /* authoritive answer */ + unsigned opcode :4; /* purpose of message */ + unsigned qr :1; /* response flag */ + /* fields in fourth byte */ + unsigned rcode :4; /* response code */ + unsigned cd: 1; /* checking disabled by resolver */ + unsigned ad: 1; /* authentic data from named */ + unsigned unused :1; /* unused bits (MBZ as of 4.9.3a3) */ + unsigned ra :1; /* recursion available */ +#endif + /* remaining bytes */ + unsigned qdcount :16; /* number of question entries */ + unsigned ancount :16; /* number of answer entries */ + unsigned nscount :16; /* number of authority entries */ + unsigned arcount :16; /* number of resource entries */ +} HEADER; + +#define PACKETSZ NS_PACKETSZ +#define MAXDNAME NS_MAXDNAME +#define MAXCDNAME NS_MAXCDNAME +#define MAXLABEL NS_MAXLABEL +#define HFIXEDSZ NS_HFIXEDSZ +#define QFIXEDSZ NS_QFIXEDSZ +#define RRFIXEDSZ NS_RRFIXEDSZ +#define INT32SZ NS_INT32SZ +#define INT16SZ NS_INT16SZ +#define INADDRSZ NS_INADDRSZ +#define IN6ADDRSZ NS_IN6ADDRSZ +#define INDIR_MASK NS_CMPRSFLGS +#define NAMESERVER_PORT NS_DEFAULTPORT + +#define S_ZONE ns_s_zn +#define S_PREREQ ns_s_pr +#define S_UPDATE ns_s_ud +#define S_ADDT ns_s_ar + +#define QUERY ns_o_query +#define IQUERY ns_o_iquery +#define STATUS ns_o_status +#define NS_NOTIFY_OP ns_o_notify +#define NS_UPDATE_OP ns_o_update + +#define NOERROR ns_r_noerror +#define FORMERR ns_r_formerr +#define SERVFAIL ns_r_servfail +#define NXDOMAIN ns_r_nxdomain +#define NOTIMP ns_r_notimpl +#define REFUSED ns_r_refused +#define YXDOMAIN ns_r_yxdomain +#define YXRRSET ns_r_yxrrset +#define NXRRSET ns_r_nxrrset +#define NOTAUTH ns_r_notauth +#define NOTZONE ns_r_notzone +/*#define BADSIG ns_r_badsig*/ +/*#define BADKEY ns_r_badkey*/ +/*#define BADTIME ns_r_badtime*/ + + +#define DELETE ns_uop_delete +#define ADD ns_uop_add + +#define T_A ns_t_a +#define T_NS ns_t_ns +#define T_MD ns_t_md +#define T_MF ns_t_mf +#define T_CNAME ns_t_cname +#define T_SOA ns_t_soa +#define T_MB ns_t_mb +#define T_MG ns_t_mg +#define T_MR ns_t_mr +#define T_NULL ns_t_null +#define T_WKS ns_t_wks +#define T_PTR ns_t_ptr +#define T_HINFO ns_t_hinfo +#define T_MINFO ns_t_minfo +#define T_MX ns_t_mx +#define T_TXT ns_t_txt +#define T_RP ns_t_rp +#define T_AFSDB ns_t_afsdb +#define T_X25 ns_t_x25 +#define T_ISDN ns_t_isdn +#define T_RT ns_t_rt +#define T_NSAP ns_t_nsap +#define T_NSAP_PTR ns_t_nsap_ptr +#define T_SIG ns_t_sig +#define T_KEY ns_t_key +#define T_PX ns_t_px +#define T_GPOS ns_t_gpos +#define T_AAAA ns_t_aaaa +#define T_LOC ns_t_loc +#define T_NXT ns_t_nxt +#define T_EID ns_t_eid +#define T_NIMLOC ns_t_nimloc +#define T_SRV ns_t_srv +#define T_ATMA ns_t_atma +#define T_NAPTR ns_t_naptr +#define T_TSIG ns_t_tsig +#define T_IXFR ns_t_ixfr +#define T_AXFR ns_t_axfr +#define T_MAILB ns_t_mailb +#define T_MAILA ns_t_maila +#define T_ANY ns_t_any + +#define C_IN ns_c_in +#define C_CHAOS ns_c_chaos +#define C_HS ns_c_hs +/* BIND_UPDATE */ +#define C_NONE ns_c_none +#define C_ANY ns_c_any + +#define GETSHORT NS_GET16 +#define GETLONG NS_GET32 +#define PUTSHORT NS_PUT16 +#define PUTLONG NS_PUT32 + +#endif /* _ARPA_NAMESER_COMPAT_ */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/arpa/telnet.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/arpa/telnet.h new file mode 100644 index 00000000..3774c892 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/arpa/telnet.h @@ -0,0 +1,316 @@ +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)telnet.h 8.2 (Berkeley) 12/15/93 + */ + +#ifndef _ARPA_TELNET_H +#define _ARPA_TELNET_H 1 + +/* + * Definitions for the TELNET protocol. + */ +#define IAC 255 /* interpret as command: */ +#define DONT 254 /* you are not to use option */ +#define DO 253 /* please, you use option */ +#define WONT 252 /* I won't use option */ +#define WILL 251 /* I will use option */ +#define SB 250 /* interpret as subnegotiation */ +#define GA 249 /* you may reverse the line */ +#define EL 248 /* erase the current line */ +#define EC 247 /* erase the current character */ +#define AYT 246 /* are you there */ +#define AO 245 /* abort output--but let prog finish */ +#define IP 244 /* interrupt process--permanently */ +#define BREAK 243 /* break */ +#define DM 242 /* data mark--for connect. cleaning */ +#define NOP 241 /* nop */ +#define SE 240 /* end sub negotiation */ +#define EOR 239 /* end of record (transparent mode) */ +#define ABORT 238 /* Abort process */ +#define SUSP 237 /* Suspend process */ +#define xEOF 236 /* End of file: EOF is already used... */ + +#define SYNCH 242 /* for telfunc calls */ + +#ifdef TELCMDS +char *telcmds[] = { + "EOF", "SUSP", "ABORT", "EOR", + "SE", "NOP", "DMARK", "BRK", "IP", "AO", "AYT", "EC", + "EL", "GA", "SB", "WILL", "WONT", "DO", "DONT", "IAC", 0, +}; +#else +extern char *telcmds[]; +#endif + +#define TELCMD_FIRST xEOF +#define TELCMD_LAST IAC +#define TELCMD_OK(x) ((unsigned int)(x) <= TELCMD_LAST && \ + (unsigned int)(x) >= TELCMD_FIRST) +#define TELCMD(x) telcmds[(x)-TELCMD_FIRST] + +/* telnet options */ +#define TELOPT_BINARY 0 /* 8-bit data path */ +#define TELOPT_ECHO 1 /* echo */ +#define TELOPT_RCP 2 /* prepare to reconnect */ +#define TELOPT_SGA 3 /* suppress go ahead */ +#define TELOPT_NAMS 4 /* approximate message size */ +#define TELOPT_STATUS 5 /* give status */ +#define TELOPT_TM 6 /* timing mark */ +#define TELOPT_RCTE 7 /* remote controlled transmission and echo */ +#define TELOPT_NAOL 8 /* negotiate about output line width */ +#define TELOPT_NAOP 9 /* negotiate about output page size */ +#define TELOPT_NAOCRD 10 /* negotiate about CR disposition */ +#define TELOPT_NAOHTS 11 /* negotiate about horizontal tabstops */ +#define TELOPT_NAOHTD 12 /* negotiate about horizontal tab disposition */ +#define TELOPT_NAOFFD 13 /* negotiate about formfeed disposition */ +#define TELOPT_NAOVTS 14 /* negotiate about vertical tab stops */ +#define TELOPT_NAOVTD 15 /* negotiate about vertical tab disposition */ +#define TELOPT_NAOLFD 16 /* negotiate about output LF disposition */ +#define TELOPT_XASCII 17 /* extended ascii character set */ +#define TELOPT_LOGOUT 18 /* force logout */ +#define TELOPT_BM 19 /* byte macro */ +#define TELOPT_DET 20 /* data entry terminal */ +#define TELOPT_SUPDUP 21 /* supdup protocol */ +#define TELOPT_SUPDUPOUTPUT 22 /* supdup output */ +#define TELOPT_SNDLOC 23 /* send location */ +#define TELOPT_TTYPE 24 /* terminal type */ +#define TELOPT_EOR 25 /* end or record */ +#define TELOPT_TUID 26 /* TACACS user identification */ +#define TELOPT_OUTMRK 27 /* output marking */ +#define TELOPT_TTYLOC 28 /* terminal location number */ +#define TELOPT_3270REGIME 29 /* 3270 regime */ +#define TELOPT_X3PAD 30 /* X.3 PAD */ +#define TELOPT_NAWS 31 /* window size */ +#define TELOPT_TSPEED 32 /* terminal speed */ +#define TELOPT_LFLOW 33 /* remote flow control */ +#define TELOPT_LINEMODE 34 /* Linemode option */ +#define TELOPT_XDISPLOC 35 /* X Display Location */ +#define TELOPT_OLD_ENVIRON 36 /* Old - Environment variables */ +#define TELOPT_AUTHENTICATION 37/* Authenticate */ +#define TELOPT_ENCRYPT 38 /* Encryption option */ +#define TELOPT_NEW_ENVIRON 39 /* New - Environment variables */ +#define TELOPT_EXOPL 255 /* extended-options-list */ + + +#define NTELOPTS (1+TELOPT_NEW_ENVIRON) +#ifdef TELOPTS +char *telopts[NTELOPTS+1] = { + "BINARY", "ECHO", "RCP", "SUPPRESS GO AHEAD", "NAME", + "STATUS", "TIMING MARK", "RCTE", "NAOL", "NAOP", + "NAOCRD", "NAOHTS", "NAOHTD", "NAOFFD", "NAOVTS", + "NAOVTD", "NAOLFD", "EXTEND ASCII", "LOGOUT", "BYTE MACRO", + "DATA ENTRY TERMINAL", "SUPDUP", "SUPDUP OUTPUT", + "SEND LOCATION", "TERMINAL TYPE", "END OF RECORD", + "TACACS UID", "OUTPUT MARKING", "TTYLOC", + "3270 REGIME", "X.3 PAD", "NAWS", "TSPEED", "LFLOW", + "LINEMODE", "XDISPLOC", "OLD-ENVIRON", "AUTHENTICATION", + "ENCRYPT", "NEW-ENVIRON", + 0, +}; +#define TELOPT_FIRST TELOPT_BINARY +#define TELOPT_LAST TELOPT_NEW_ENVIRON +#define TELOPT_OK(x) ((unsigned int)(x) <= TELOPT_LAST) +#define TELOPT(x) telopts[(x)-TELOPT_FIRST] +#endif + +/* sub-option qualifiers */ +#define TELQUAL_IS 0 /* option is... */ +#define TELQUAL_SEND 1 /* send option */ +#define TELQUAL_INFO 2 /* ENVIRON: informational version of IS */ +#define TELQUAL_REPLY 2 /* AUTHENTICATION: client version of IS */ +#define TELQUAL_NAME 3 /* AUTHENTICATION: client version of IS */ + +#define LFLOW_OFF 0 /* Disable remote flow control */ +#define LFLOW_ON 1 /* Enable remote flow control */ +#define LFLOW_RESTART_ANY 2 /* Restart output on any char */ +#define LFLOW_RESTART_XON 3 /* Restart output only on XON */ + +/* + * LINEMODE suboptions + */ + +#define LM_MODE 1 +#define LM_FORWARDMASK 2 +#define LM_SLC 3 + +#define MODE_EDIT 0x01 +#define MODE_TRAPSIG 0x02 +#define MODE_ACK 0x04 +#define MODE_SOFT_TAB 0x08 +#define MODE_LIT_ECHO 0x10 + +#define MODE_MASK 0x1f + +/* Not part of protocol, but needed to simplify things... */ +#define MODE_FLOW 0x0100 +#define MODE_ECHO 0x0200 +#define MODE_INBIN 0x0400 +#define MODE_OUTBIN 0x0800 +#define MODE_FORCE 0x1000 + +#define SLC_SYNCH 1 +#define SLC_BRK 2 +#define SLC_IP 3 +#define SLC_AO 4 +#define SLC_AYT 5 +#define SLC_EOR 6 +#define SLC_ABORT 7 +#define SLC_EOF 8 +#define SLC_SUSP 9 +#define SLC_EC 10 +#define SLC_EL 11 +#define SLC_EW 12 +#define SLC_RP 13 +#define SLC_LNEXT 14 +#define SLC_XON 15 +#define SLC_XOFF 16 +#define SLC_FORW1 17 +#define SLC_FORW2 18 + +#define NSLC 18 + +/* + * For backwards compatibility, we define SLC_NAMES to be the + * list of names if SLC_NAMES is not defined. + */ +#define SLC_NAMELIST "0", "SYNCH", "BRK", "IP", "AO", "AYT", "EOR", \ + "ABORT", "EOF", "SUSP", "EC", "EL", "EW", "RP", \ + "LNEXT", "XON", "XOFF", "FORW1", "FORW2", 0, +#ifdef SLC_NAMES +char *slc_names[] = { + SLC_NAMELIST +}; +#else +extern char *slc_names[]; +#define SLC_NAMES SLC_NAMELIST +#endif + +#define SLC_NAME_OK(x) ((unsigned int)(x) <= NSLC) +#define SLC_NAME(x) slc_names[x] + +#define SLC_NOSUPPORT 0 +#define SLC_CANTCHANGE 1 +#define SLC_VARIABLE 2 +#define SLC_DEFAULT 3 +#define SLC_LEVELBITS 0x03 + +#define SLC_FUNC 0 +#define SLC_FLAGS 1 +#define SLC_VALUE 2 + +#define SLC_ACK 0x80 +#define SLC_FLUSHIN 0x40 +#define SLC_FLUSHOUT 0x20 + +#define OLD_ENV_VAR 1 +#define OLD_ENV_VALUE 0 +#define NEW_ENV_VAR 0 +#define NEW_ENV_VALUE 1 +#define ENV_ESC 2 +#define ENV_USERVAR 3 + +/* + * AUTHENTICATION suboptions + */ + +/* + * Who is authenticating who ... + */ +#define AUTH_WHO_CLIENT 0 /* Client authenticating server */ +#define AUTH_WHO_SERVER 1 /* Server authenticating client */ +#define AUTH_WHO_MASK 1 + +/* + * amount of authentication done + */ +#define AUTH_HOW_ONE_WAY 0 +#define AUTH_HOW_MUTUAL 2 +#define AUTH_HOW_MASK 2 + +#define AUTHTYPE_NULL 0 +#define AUTHTYPE_KERBEROS_V4 1 +#define AUTHTYPE_KERBEROS_V5 2 +#define AUTHTYPE_SPX 3 +#define AUTHTYPE_MINK 4 +#define AUTHTYPE_CNT 5 + +#define AUTHTYPE_TEST 99 + +#ifdef AUTH_NAMES +char *authtype_names[] = { + "NULL", "KERBEROS_V4", "KERBEROS_V5", "SPX", "MINK", 0, +}; +#else +extern char *authtype_names[]; +#endif + +#define AUTHTYPE_NAME_OK(x) ((unsigned int)(x) < AUTHTYPE_CNT) +#define AUTHTYPE_NAME(x) authtype_names[x] + +/* + * ENCRYPTion suboptions + */ +#define ENCRYPT_IS 0 /* I pick encryption type ... */ +#define ENCRYPT_SUPPORT 1 /* I support encryption types ... */ +#define ENCRYPT_REPLY 2 /* Initial setup response */ +#define ENCRYPT_START 3 /* Am starting to send encrypted */ +#define ENCRYPT_END 4 /* Am ending encrypted */ +#define ENCRYPT_REQSTART 5 /* Request you start encrypting */ +#define ENCRYPT_REQEND 6 /* Request you send encrypting */ +#define ENCRYPT_ENC_KEYID 7 +#define ENCRYPT_DEC_KEYID 8 +#define ENCRYPT_CNT 9 + +#define ENCTYPE_ANY 0 +#define ENCTYPE_DES_CFB64 1 +#define ENCTYPE_DES_OFB64 2 +#define ENCTYPE_CNT 3 + +#ifdef ENCRYPT_NAMES +char *encrypt_names[] = { + "IS", "SUPPORT", "REPLY", "START", "END", + "REQUEST-START", "REQUEST-END", "ENC-KEYID", "DEC-KEYID", + 0, +}; +char *enctype_names[] = { + "ANY", "DES_CFB64", "DES_OFB64", 0, +}; +#else +extern char *encrypt_names[]; +extern char *enctype_names[]; +#endif + + +#define ENCRYPT_NAME_OK(x) ((unsigned int)(x) < ENCRYPT_CNT) +#define ENCRYPT_NAME(x) encrypt_names[x] + +#define ENCTYPE_NAME_OK(x) ((unsigned int)(x) < ENCTYPE_CNT) +#define ENCTYPE_NAME(x) enctype_names[x] + +#endif /* arpa/telnet.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/arpa/tftp.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/arpa/tftp.h new file mode 100644 index 00000000..21b0559e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/arpa/tftp.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)tftp.h 8.1 (Berkeley) 6/2/93 + */ + +#ifndef _ARPA_TFTP_H +#define _ARPA_TFTP_H 1 + +/* + * Trivial File Transfer Protocol (IEN-133) + */ +#define SEGSIZE 512 /* data segment size */ + +/* + * Packet types. + */ +#define RRQ 01 /* read request */ +#define WRQ 02 /* write request */ +#define DATA 03 /* data packet */ +#define ACK 04 /* acknowledgement */ +#define ERROR 05 /* error code */ + +struct tftphdr { + short th_opcode; /* packet type */ + union { + unsigned short tu_block; /* block # */ + short tu_code; /* error code */ + char tu_stuff[1]; /* request packet stuff */ + } __attribute__ ((__packed__)) th_u; + char th_data[1]; /* data or error string */ +} __attribute__ ((__packed__)); + +#define th_block th_u.tu_block +#define th_code th_u.tu_code +#define th_stuff th_u.tu_stuff +#define th_msg th_data + +/* + * Error codes. + */ +#define EUNDEF 0 /* not defined */ +#define ENOTFOUND 1 /* file not found */ +#define EACCESS 2 /* access violation */ +#define ENOSPACE 3 /* disk full or allocation exceeded */ +#define EBADOP 4 /* illegal TFTP operation */ +#define EBADID 5 /* unknown transfer ID */ +#define EEXISTS 6 /* file already exists */ +#define ENOUSER 7 /* no such user */ + +#endif /* arpa/tftp.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/assert.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/assert.h new file mode 100644 index 00000000..40b16059 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/assert.h @@ -0,0 +1,79 @@ +/* Copyright (C) 1991,1992,1994-2001,2003,2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * ISO C99 Standard: 7.2 Diagnostics + */ + +#ifdef _ASSERT_H + +# undef _ASSERT_H +# undef assert +# undef __ASSERT_VOID_CAST + +#endif /* assert.h */ + +#define _ASSERT_H 1 +#include + +#if defined __cplusplus && __GNUC_PREREQ (2,95) +# define __ASSERT_VOID_CAST static_cast +#else +# define __ASSERT_VOID_CAST (void) +#endif + +/* void assert (int expression); + + If NDEBUG is defined, do nothing. + If not, and EXPRESSION is zero, print an error message and abort. */ + +#ifdef NDEBUG + +# define assert(expr) (__ASSERT_VOID_CAST (0)) + +#else /* Not NDEBUG. */ + +__BEGIN_DECLS + +/* This prints an "Assertion failed" message and aborts. */ +extern void __assert(const char *, const char *, unsigned int, const char *) + __THROW __attribute__ ((__noreturn__)); +libc_hidden_proto(__assert) + +__END_DECLS + +# define assert(expr) \ + (__ASSERT_VOID_CAST ((expr) ? 0 : \ + (__assert (__STRING(expr), __FILE__, __LINE__, __ASSERT_FUNCTION), 0))) + +/* Version 2.4 and later of GCC define a magical variable `__PRETTY_FUNCTION__' + which contains the name of the function currently being defined. + This is broken in G++ before version 2.6. + C9x has a similar variable called __func__, but prefer the GCC one since + it demangles C++ function names. */ +# if defined __cplusplus ? __GNUC_PREREQ (2, 6) : __GNUC_PREREQ (2, 4) +# define __ASSERT_FUNCTION __PRETTY_FUNCTION__ +# else +# if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L +# define __ASSERT_FUNCTION __func__ +# else +# define __ASSERT_FUNCTION ((__const char *) 0) +# endif +# endif + +#endif /* NDEBUG. */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/atomic.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/atomic.h new file mode 100644 index 00000000..6383572c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/atomic.h @@ -0,0 +1,537 @@ +/* Internal macros for atomic operations for GNU C Library. + Copyright (C) 2002-2006, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _ATOMIC_H +#define _ATOMIC_H 1 + +/* This header defines three types of macros: + + - atomic arithmetic and logic operation on memory. They all + have the prefix "atomic_". + + - conditionally atomic operations of the same kinds. These + always behave identical but can be faster when atomicity + is not really needed since only one thread has access to + the memory location. In that case the code is slower in + the multi-thread case. The interfaces have the prefix + "catomic_". + + - support functions like barriers. They also have the preifx + "atomic_". + + Architectures must provide a few lowlevel macros (the compare + and exchange definitions). All others are optional. They + should only be provided if the architecture has specific + support for the operation. + + As macros are usually heavily nested and often use local + variables to make sure side-effects are evaluated properly, use for + macro local variables a per-macro unique prefix. This file uses + __atgN_ prefix where N is different in each macro. */ + +#include + +#include + +/* Wrapper macros to call pre_NN_post (mem, ...) where NN is the + bit width of *MEM. The calling macro puts parens around MEM + and following args. */ +#define __atomic_val_bysize(pre, post, mem, ...) \ + ({ \ + __typeof (*mem) __atg1_result; \ + if (sizeof (*mem) == 1) \ + __atg1_result = pre##_8_##post (mem, __VA_ARGS__); \ + else if (sizeof (*mem) == 2) \ + __atg1_result = pre##_16_##post (mem, __VA_ARGS__); \ + else if (sizeof (*mem) == 4) \ + __atg1_result = pre##_32_##post (mem, __VA_ARGS__); \ + else if (sizeof (*mem) == 8) \ + __atg1_result = pre##_64_##post (mem, __VA_ARGS__); \ + else \ + abort (); \ + __atg1_result; \ + }) +#define __atomic_bool_bysize(pre, post, mem, ...) \ + ({ \ + int __atg2_result; \ + if (sizeof (*mem) == 1) \ + __atg2_result = pre##_8_##post (mem, __VA_ARGS__); \ + else if (sizeof (*mem) == 2) \ + __atg2_result = pre##_16_##post (mem, __VA_ARGS__); \ + else if (sizeof (*mem) == 4) \ + __atg2_result = pre##_32_##post (mem, __VA_ARGS__); \ + else if (sizeof (*mem) == 8) \ + __atg2_result = pre##_64_##post (mem, __VA_ARGS__); \ + else \ + abort (); \ + __atg2_result; \ + }) + + +/* Atomically store NEWVAL in *MEM if *MEM is equal to OLDVAL. + Return the old *MEM value. */ +#if !defined atomic_compare_and_exchange_val_acq \ + && defined __arch_compare_and_exchange_val_32_acq +# define atomic_compare_and_exchange_val_acq(mem, newval, oldval) \ + __atomic_val_bysize (__arch_compare_and_exchange_val,acq, \ + mem, newval, oldval) +#endif + + +#ifndef catomic_compare_and_exchange_val_acq +# ifdef __arch_c_compare_and_exchange_val_32_acq +# define catomic_compare_and_exchange_val_acq(mem, newval, oldval) \ + __atomic_val_bysize (__arch_c_compare_and_exchange_val,acq, \ + mem, newval, oldval) +# else +# define catomic_compare_and_exchange_val_acq(mem, newval, oldval) \ + atomic_compare_and_exchange_val_acq (mem, newval, oldval) +# endif +#endif + + +#ifndef catomic_compare_and_exchange_val_rel +# ifndef atomic_compare_and_exchange_val_rel +# define catomic_compare_and_exchange_val_rel(mem, newval, oldval) \ + catomic_compare_and_exchange_val_acq (mem, newval, oldval) +# else +# define catomic_compare_and_exchange_val_rel(mem, newval, oldval) \ + atomic_compare_and_exchange_val_rel (mem, newval, oldval) +# endif +#endif + + +#ifndef atomic_compare_and_exchange_val_rel +# define atomic_compare_and_exchange_val_rel(mem, newval, oldval) \ + atomic_compare_and_exchange_val_acq (mem, newval, oldval) +#endif + + +/* Atomically store NEWVAL in *MEM if *MEM is equal to OLDVAL. + Return zero if *MEM was changed or non-zero if no exchange happened. */ +#ifndef atomic_compare_and_exchange_bool_acq +# ifdef __arch_compare_and_exchange_bool_32_acq +# define atomic_compare_and_exchange_bool_acq(mem, newval, oldval) \ + __atomic_bool_bysize (__arch_compare_and_exchange_bool,acq, \ + mem, newval, oldval) +# else +# define atomic_compare_and_exchange_bool_acq(mem, newval, oldval) \ + ({ /* Cannot use __oldval here, because macros later in this file might \ + call this macro with __oldval argument. */ \ + __typeof (oldval) __atg3_old = (oldval); \ + atomic_compare_and_exchange_val_acq (mem, newval, __atg3_old) \ + != __atg3_old; \ + }) +# endif +#endif + + +#ifndef catomic_compare_and_exchange_bool_acq +# ifdef __arch_c_compare_and_exchange_bool_32_acq +# define catomic_compare_and_exchange_bool_acq(mem, newval, oldval) \ + __atomic_bool_bysize (__arch_c_compare_and_exchange_bool,acq, \ + mem, newval, oldval) +# else +# define catomic_compare_and_exchange_bool_acq(mem, newval, oldval) \ + ({ /* Cannot use __oldval here, because macros later in this file might \ + call this macro with __oldval argument. */ \ + __typeof (oldval) __atg4_old = (oldval); \ + catomic_compare_and_exchange_val_acq (mem, newval, __atg4_old) \ + != __atg4_old; \ + }) +# endif +#endif + + +#ifndef catomic_compare_and_exchange_bool_rel +# ifndef atomic_compare_and_exchange_bool_rel +# define catomic_compare_and_exchange_bool_rel(mem, newval, oldval) \ + catomic_compare_and_exchange_bool_acq (mem, newval, oldval) +# else +# define catomic_compare_and_exchange_bool_rel(mem, newval, oldval) \ + atomic_compare_and_exchange_bool_rel (mem, newval, oldval) +# endif +#endif + + +#ifndef atomic_compare_and_exchange_bool_rel +# define atomic_compare_and_exchange_bool_rel(mem, newval, oldval) \ + atomic_compare_and_exchange_bool_acq (mem, newval, oldval) +#endif + + +/* Store NEWVALUE in *MEM and return the old value. */ +#ifndef atomic_exchange_acq +# define atomic_exchange_acq(mem, newvalue) \ + ({ __typeof (*(mem)) __atg5_oldval; \ + __typeof (mem) __atg5_memp = (mem); \ + __typeof (*(mem)) __atg5_value = (newvalue); \ + \ + do \ + __atg5_oldval = *__atg5_memp; \ + while (__builtin_expect \ + (atomic_compare_and_exchange_bool_acq (__atg5_memp, __atg5_value, \ + __atg5_oldval), 0)); \ + \ + __atg5_oldval; }) +#endif + +#ifndef atomic_exchange_rel +# define atomic_exchange_rel(mem, newvalue) atomic_exchange_acq (mem, newvalue) +#endif + + +/* Add VALUE to *MEM and return the old value of *MEM. */ +#ifndef atomic_exchange_and_add +# define atomic_exchange_and_add(mem, value) \ + ({ __typeof (*(mem)) __atg6_oldval; \ + __typeof (mem) __atg6_memp = (mem); \ + __typeof (*(mem)) __atg6_value = (value); \ + \ + do \ + __atg6_oldval = *__atg6_memp; \ + while (__builtin_expect \ + (atomic_compare_and_exchange_bool_acq (__atg6_memp, \ + __atg6_oldval \ + + __atg6_value, \ + __atg6_oldval), 0)); \ + \ + __atg6_oldval; }) +#endif + + +#ifndef catomic_exchange_and_add +# define catomic_exchange_and_add(mem, value) \ + ({ __typeof (*(mem)) __atg7_oldv; \ + __typeof (mem) __atg7_memp = (mem); \ + __typeof (*(mem)) __atg7_value = (value); \ + \ + do \ + __atg7_oldv = *__atg7_memp; \ + while (__builtin_expect \ + (catomic_compare_and_exchange_bool_acq (__atg7_memp, \ + __atg7_oldv \ + + __atg7_value, \ + __atg7_oldv), 0)); \ + \ + __atg7_oldv; }) +#endif + + +#ifndef atomic_max +# define atomic_max(mem, value) \ + do { \ + __typeof (*(mem)) __atg8_oldval; \ + __typeof (mem) __atg8_memp = (mem); \ + __typeof (*(mem)) __atg8_value = (value); \ + do { \ + __atg8_oldval = *__atg8_memp; \ + if (__atg8_oldval >= __atg8_value) \ + break; \ + } while (__builtin_expect \ + (atomic_compare_and_exchange_bool_acq (__atg8_memp, __atg8_value,\ + __atg8_oldval), 0)); \ + } while (0) +#endif + + +#ifndef catomic_max +# define catomic_max(mem, value) \ + do { \ + __typeof (*(mem)) __atg9_oldv; \ + __typeof (mem) __atg9_memp = (mem); \ + __typeof (*(mem)) __atg9_value = (value); \ + do { \ + __atg9_oldv = *__atg9_memp; \ + if (__atg9_oldv >= __atg9_value) \ + break; \ + } while (__builtin_expect \ + (catomic_compare_and_exchange_bool_acq (__atg9_memp, \ + __atg9_value, \ + __atg9_oldv), 0)); \ + } while (0) +#endif + + +#ifndef atomic_min +# define atomic_min(mem, value) \ + do { \ + __typeof (*(mem)) __atg10_oldval; \ + __typeof (mem) __atg10_memp = (mem); \ + __typeof (*(mem)) __atg10_value = (value); \ + do { \ + __atg10_oldval = *__atg10_memp; \ + if (__atg10_oldval <= __atg10_value) \ + break; \ + } while (__builtin_expect \ + (atomic_compare_and_exchange_bool_acq (__atg10_memp, \ + __atg10_value, \ + __atg10_oldval), 0)); \ + } while (0) +#endif + + +#ifndef atomic_add +# define atomic_add(mem, value) (void) atomic_exchange_and_add ((mem), (value)) +#endif + + +#ifndef catomic_add +# define catomic_add(mem, value) \ + (void) catomic_exchange_and_add ((mem), (value)) +#endif + + +#ifndef atomic_increment +# define atomic_increment(mem) atomic_add ((mem), 1) +#endif + + +#ifndef catomic_increment +# define catomic_increment(mem) catomic_add ((mem), 1) +#endif + + +#ifndef atomic_increment_val +# define atomic_increment_val(mem) (atomic_exchange_and_add ((mem), 1) + 1) +#endif + + +#ifndef catomic_increment_val +# define catomic_increment_val(mem) (catomic_exchange_and_add ((mem), 1) + 1) +#endif + + +/* Add one to *MEM and return true iff it's now zero. */ +#ifndef atomic_increment_and_test +# define atomic_increment_and_test(mem) \ + (atomic_exchange_and_add ((mem), 1) + 1 == 0) +#endif + + +#ifndef atomic_decrement +# define atomic_decrement(mem) atomic_add ((mem), -1) +#endif + + +#ifndef catomic_decrement +# define catomic_decrement(mem) catomic_add ((mem), -1) +#endif + + +#ifndef atomic_decrement_val +# define atomic_decrement_val(mem) (atomic_exchange_and_add ((mem), -1) - 1) +#endif + + +#ifndef catomic_decrement_val +# define catomic_decrement_val(mem) (catomic_exchange_and_add ((mem), -1) - 1) +#endif + + +/* Subtract 1 from *MEM and return true iff it's now zero. */ +#ifndef atomic_decrement_and_test +# define atomic_decrement_and_test(mem) \ + (atomic_exchange_and_add ((mem), -1) == 1) +#endif + + +/* Decrement *MEM if it is > 0, and return the old value. */ +#ifndef atomic_decrement_if_positive +# define atomic_decrement_if_positive(mem) \ + ({ __typeof (*(mem)) __atg11_oldval; \ + __typeof (mem) __atg11_memp = (mem); \ + \ + do \ + { \ + __atg11_oldval = *__atg11_memp; \ + if (__builtin_expect (__atg11_oldval <= 0, 0)) \ + break; \ + } \ + while (__builtin_expect \ + (atomic_compare_and_exchange_bool_acq (__atg11_memp, \ + __atg11_oldval - 1, \ + __atg11_oldval), 0)); \ + __atg11_oldval; }) +#endif + + +#ifndef atomic_add_negative +# define atomic_add_negative(mem, value) \ + ({ __typeof (value) __atg12_value = (value); \ + atomic_exchange_and_add (mem, __atg12_value) < -__atg12_value; }) +#endif + + +#ifndef atomic_add_zero +# define atomic_add_zero(mem, value) \ + ({ __typeof (value) __atg13_value = (value); \ + atomic_exchange_and_add (mem, __atg13_value) == -__atg13_value; }) +#endif + + +#ifndef atomic_bit_set +# define atomic_bit_set(mem, bit) \ + (void) atomic_bit_test_set(mem, bit) +#endif + + +#ifndef atomic_bit_test_set +# define atomic_bit_test_set(mem, bit) \ + ({ __typeof (*(mem)) __atg14_old; \ + __typeof (mem) __atg14_memp = (mem); \ + __typeof (*(mem)) __atg14_mask = ((__typeof (*(mem))) 1 << (bit)); \ + \ + do \ + __atg14_old = (*__atg14_memp); \ + while (__builtin_expect \ + (atomic_compare_and_exchange_bool_acq (__atg14_memp, \ + __atg14_old | __atg14_mask,\ + __atg14_old), 0)); \ + \ + __atg14_old & __atg14_mask; }) +#endif + +/* Atomically *mem &= mask. */ +#ifndef atomic_and +# define atomic_and(mem, mask) \ + do { \ + __typeof (*(mem)) __atg15_old; \ + __typeof (mem) __atg15_memp = (mem); \ + __typeof (*(mem)) __atg15_mask = (mask); \ + \ + do \ + __atg15_old = (*__atg15_memp); \ + while (__builtin_expect \ + (atomic_compare_and_exchange_bool_acq (__atg15_memp, \ + __atg15_old & __atg15_mask, \ + __atg15_old), 0)); \ + } while (0) +#endif + +#ifndef catomic_and +# define catomic_and(mem, mask) \ + do { \ + __typeof (*(mem)) __atg20_old; \ + __typeof (mem) __atg20_memp = (mem); \ + __typeof (*(mem)) __atg20_mask = (mask); \ + \ + do \ + __atg20_old = (*__atg20_memp); \ + while (__builtin_expect \ + (catomic_compare_and_exchange_bool_acq (__atg20_memp, \ + __atg20_old & __atg20_mask,\ + __atg20_old), 0)); \ + } while (0) +#endif + +/* Atomically *mem &= mask and return the old value of *mem. */ +#ifndef atomic_and_val +# define atomic_and_val(mem, mask) \ + ({ __typeof (*(mem)) __atg16_old; \ + __typeof (mem) __atg16_memp = (mem); \ + __typeof (*(mem)) __atg16_mask = (mask); \ + \ + do \ + __atg16_old = (*__atg16_memp); \ + while (__builtin_expect \ + (atomic_compare_and_exchange_bool_acq (__atg16_memp, \ + __atg16_old & __atg16_mask,\ + __atg16_old), 0)); \ + \ + __atg16_old; }) +#endif + +/* Atomically *mem |= mask and return the old value of *mem. */ +#ifndef atomic_or +# define atomic_or(mem, mask) \ + do { \ + __typeof (*(mem)) __atg17_old; \ + __typeof (mem) __atg17_memp = (mem); \ + __typeof (*(mem)) __atg17_mask = (mask); \ + \ + do \ + __atg17_old = (*__atg17_memp); \ + while (__builtin_expect \ + (atomic_compare_and_exchange_bool_acq (__atg17_memp, \ + __atg17_old | __atg17_mask, \ + __atg17_old), 0)); \ + } while (0) +#endif + +#ifndef catomic_or +# define catomic_or(mem, mask) \ + do { \ + __typeof (*(mem)) __atg18_old; \ + __typeof (mem) __atg18_memp = (mem); \ + __typeof (*(mem)) __atg18_mask = (mask); \ + \ + do \ + __atg18_old = (*__atg18_memp); \ + while (__builtin_expect \ + (catomic_compare_and_exchange_bool_acq (__atg18_memp, \ + __atg18_old | __atg18_mask,\ + __atg18_old), 0)); \ + } while (0) +#endif + +/* Atomically *mem |= mask and return the old value of *mem. */ +#ifndef atomic_or_val +# define atomic_or_val(mem, mask) \ + ({ __typeof (*(mem)) __atg19_old; \ + __typeof (mem) __atg19_memp = (mem); \ + __typeof (*(mem)) __atg19_mask = (mask); \ + \ + do \ + __atg19_old = (*__atg19_memp); \ + while (__builtin_expect \ + (atomic_compare_and_exchange_bool_acq (__atg19_memp, \ + __atg19_old | __atg19_mask,\ + __atg19_old), 0)); \ + \ + __atg19_old; }) +#endif + +#ifndef atomic_full_barrier +# define atomic_full_barrier() __asm__ ("" ::: "memory") +#endif + + +#ifndef atomic_read_barrier +# define atomic_read_barrier() atomic_full_barrier () +#endif + + +#ifndef atomic_write_barrier +# define atomic_write_barrier() atomic_full_barrier () +#endif + + +#ifndef atomic_forced_read +# define atomic_forced_read(x) \ + ({ __typeof (x) __x; __asm__ ("" : "=r" (__x) : "0" (x)); __x; }) +#endif + + +#ifndef atomic_delay +# define atomic_delay() do { /* nothing */ } while (0) +#endif + +#endif /* atomic.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/byteswap.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/byteswap.h new file mode 100644 index 00000000..b61d4dda --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/byteswap.h @@ -0,0 +1,40 @@ +/* Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _BYTESWAP_H +#define _BYTESWAP_H 1 + +/* Get the machine specific, optimized definitions. */ +#include + + +/* The following definitions must all be macros since otherwise some + of the possible optimizations are not possible. */ + +/* Return a value with all bytes in the 16 bit argument swapped. */ +#define bswap_16(x) __bswap_16 (x) + +/* Return a value with all bytes in the 32 bit argument swapped. */ +#define bswap_32(x) __bswap_32 (x) + +#if defined __GNUC__ && __GNUC__ >= 2 +/* Return a value with all bytes in the 64 bit argument swapped. */ +# define bswap_64(x) __bswap_64 (x) +#endif + +#endif /* byteswap.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/complex.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/complex.h new file mode 100644 index 00000000..8779bbcd --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/complex.h @@ -0,0 +1,107 @@ +/* Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * ISO C99: 7.3 Complex arithmetic + */ + +#ifndef _COMPLEX_H +#define _COMPLEX_H 1 + +#include + +/* Get general and ISO C99 specific information. */ +#include + +__BEGIN_DECLS + +/* We might need to add support for more compilers here. But since ISO + C99 is out hopefully all maintained compilers will soon provide the data + types `float complex' and `double complex'. */ +#if __GNUC_PREREQ (2, 7) && !__GNUC_PREREQ (2, 97) +# define _Complex __complex__ +#endif + +#define complex _Complex + +/* Narrowest imaginary unit. This depends on the floating-point + evaluation method. + XXX This probably has to go into a gcc related file. */ +#define _Complex_I (__extension__ 1.0iF) + +/* Another more descriptive name is `I'. + XXX Once we have the imaginary support switch this to _Imaginary_I. */ +#undef I +#define I _Complex_I + +/* The file contains the prototypes for all the + actual math functions. These macros are used for those prototypes, + so we can easily declare each function as both `name' and `__name', + and can declare the float versions `namef' and `__namef'. */ + +#define __MATHCALL(function, args) \ + __MATHDECL(_Mdouble_complex_,function, args) +#define __MATHDECL(type, function, args) \ + __MATHDECL_1(type, function, args); \ + __MATHDECL_1(type, __CONCAT(__,function), args) +#define __MATHDECL_1(type, function, args) \ + extern type __MATH_PRECNAME(function) args __THROW + +#define _Mdouble_ double +#define __MATH_PRECNAME(name) name +#include +#undef _Mdouble_ +#undef __MATH_PRECNAME + +/* Now the float versions. */ +#ifndef _Mfloat_ +# define _Mfloat_ float +#endif +#define _Mdouble_ _Mfloat_ +#ifdef __STDC__ +# define __MATH_PRECNAME(name) name##f +#else +# define __MATH_PRECNAME(name) name/**/f +#endif +#include +#undef _Mdouble_ +#undef __MATH_PRECNAME + +/* And the long double versions. It is non-critical to define them + here unconditionally since `long double' is required in ISO C99. */ +#if __STDC__ - 0 || __GNUC__ - 0 && defined __UCLIBC_HAS_LONG_DOUBLE_MATH__ +# ifndef _Mlong_double_ +# define _Mlong_double_ long double +# endif +# define _Mdouble_ _Mlong_double_ +# ifdef __STDC__ +# define __MATH_PRECNAME(name) name##l +# else +# define __MATH_PRECNAME(name) name/**/l +# endif +# include +#endif +#undef _Mdouble_ +#undef __MATH_PRECNAME +#undef __MATHDECL_1 +#undef __MATHDECL +#undef __MATHCALL + +__END_DECLS + +#endif /* complex.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/cpio.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/cpio.h new file mode 100644 index 00000000..fae32752 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/cpio.h @@ -0,0 +1,74 @@ +/* Extended cpio format from POSIX.1. + This file is part of the GNU C Library. + Copyright (C) 1992, 1998 Free Software Foundation, Inc. + NOTE: The canonical source of this file is maintained with the GNU cpio. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _CPIO_H +#define _CPIO_H 1 + +/* A cpio archive consists of a sequence of files. + Each file has a 76 byte header, + a variable length, NUL terminated filename, + and variable length file data. + A header for a filename "TRAILER!!!" indicates the end of the archive. */ + +/* All the fields in the header are ISO 646 (approximately ASCII) strings + of octal numbers, left padded, not NUL terminated. + + Field Name Length in Bytes Notes + c_magic 6 must be "070707" + c_dev 6 + c_ino 6 + c_mode 6 see below for value + c_uid 6 + c_gid 6 + c_nlink 6 + c_rdev 6 only valid for chr and blk special files + c_mtime 11 + c_namesize 6 count includes terminating NUL in pathname + c_filesize 11 must be 0 for FIFOs and directories */ + +/* Value for the field `c_magic'. */ +#define MAGIC "070707" + +/* Values for c_mode, OR'd together: */ + +#define C_IRUSR 000400 +#define C_IWUSR 000200 +#define C_IXUSR 000100 +#define C_IRGRP 000040 +#define C_IWGRP 000020 +#define C_IXGRP 000010 +#define C_IROTH 000004 +#define C_IWOTH 000002 +#define C_IXOTH 000001 + +#define C_ISUID 004000 +#define C_ISGID 002000 +#define C_ISVTX 001000 + +#define C_ISBLK 060000 +#define C_ISCHR 020000 +#define C_ISDIR 040000 +#define C_ISFIFO 010000 +#define C_ISSOCK 0140000 +#define C_ISLNK 0120000 +#define C_ISCTG 0110000 +#define C_ISREG 0100000 + +#endif /* cpio.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/crypt.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/crypt.h new file mode 100644 index 00000000..f62a0305 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/crypt.h @@ -0,0 +1,42 @@ +/* + * crypt(3) implementation for uClibc + * + * The uClibc Library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * The GNU C Library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the GNU C Library; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 USA. + * + */ + +#ifndef _CRYPT_H +#define _CRYPT_H 1 + +#include + +__BEGIN_DECLS + +/* Encrypt characters from KEY using salt to perturb the encryption method. + * If salt begins with "$1$", MD5 hashing is used instead of DES. */ +extern char *crypt (const char *__key, const char *__salt) + __THROW __nonnull ((1, 2)); + +/* Setup DES tables according KEY. */ +extern void setkey (const char *__key) __THROW __nonnull ((1)); + +/* Encrypt data in BLOCK in place if EDFLAG is zero; otherwise decrypt + block in place. */ +extern void encrypt (char *__block, int __edflag) __THROW __nonnull ((1)); + +__END_DECLS + +#endif /* crypt.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/ctype.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/ctype.h new file mode 100644 index 00000000..dcfeb1b3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/ctype.h @@ -0,0 +1,421 @@ +/* Copyright (C) 1991,92,93,95,96,97,98,99,2001,02 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * ISO C99 Standard 7.4: Character handling + */ + +#ifndef _CTYPE_H +#define _CTYPE_H 1 + +#include +#include + +__BEGIN_DECLS +__BEGIN_NAMESPACE_STD + +/* The following names are all functions: + int isCHARACTERISTIC(int c); + which return nonzero iff C has CHARACTERISTIC. + For the meaning of the characteristic names, see the `enum' above. */ +extern int isalnum(int __c) __THROW; +libc_hidden_proto(isalnum) +extern int isalpha(int __c) __THROW; +libc_hidden_proto(isalpha) +extern int iscntrl(int __c) __THROW; +libc_hidden_proto(iscntrl) +extern int isdigit(int __c) __THROW; +libc_hidden_proto(isdigit) +extern int islower(int __c) __THROW; +libc_hidden_proto(islower) +extern int isgraph(int __c) __THROW; +libc_hidden_proto(isgraph) +extern int isprint(int __c) __THROW; +libc_hidden_proto(isprint) +extern int ispunct(int __c) __THROW; +libc_hidden_proto(ispunct) +extern int isspace(int __c) __THROW; +libc_hidden_proto(isspace) +extern int isupper(int __c) __THROW; +libc_hidden_proto(isupper) +extern int isxdigit(int __c) __THROW; +libc_hidden_proto(isxdigit) + + +/* Return the lowercase version of C. */ +extern int tolower(int __c) __THROW; +libc_hidden_proto(tolower) + +/* Return the uppercase version of C. */ +extern int toupper(int __c) __THROW; +libc_hidden_proto(toupper) + +#if (defined __USE_SVID || defined __USE_MISC || defined __USE_XOPEN) && \ + defined __UCLIBC_SUSV4_LEGACY__ +/* Return nonzero iff C is in the ASCII set + (i.e., is no more than 7 bits wide). */ +extern int isascii(int __c) __THROW; +libc_hidden_proto(isascii) +/* Return the part of C that is in the ASCII set + (i.e., the low-order 7 bits of C). */ +extern int toascii(int __c) __THROW; +#endif + +__END_NAMESPACE_STD + + +/* ISO C99 introduced one new function. */ +#ifdef __USE_ISOC99 +__BEGIN_NAMESPACE_C99 + +extern int isblank(int __c) __THROW; +libc_hidden_proto(isblank) + +__END_NAMESPACE_C99 +#endif +__END_DECLS + +#ifndef __UCLIBC_HAS_CTYPE_TABLES__ + +/* "Stub locale": we are permanently in C/POSIX locale. + * Using simple(r) ctype.h machinery in this header instead: */ +#include + +#else + +__BEGIN_DECLS + +#ifndef _ISbit +/* These are all the characteristics of characters. + If there get to be more than 16 distinct characteristics, + __ctype_mask_t will need to be adjusted. */ + +/* libstdc++ from gcc toolchain needs this macro. */ +# define _ISbit(bit) (1 << (bit)) + +enum +{ + _ISupper = _ISbit (0), /* UPPERCASE. */ + _ISlower = _ISbit (1), /* lowercase. */ + _ISalpha = _ISbit (2), /* Alphabetic. */ + _ISdigit = _ISbit (3), /* Numeric. */ + _ISxdigit = _ISbit (4), /* Hexadecimal numeric. */ + _ISspace = _ISbit (5), /* Whitespace. */ + _ISprint = _ISbit (6), /* Printing. */ + _ISgraph = _ISbit (7), /* Graphical. */ + _ISblank = _ISbit (8), /* Blank (usually SPC and TAB). */ + _IScntrl = _ISbit (9), /* Control character. */ + _ISpunct = _ISbit (10), /* Punctuation. */ + _ISalnum = _ISbit (11) /* Alphanumeric. */ +}; +#else +#error _ISbit already defined! +#endif /* ! _ISbit */ + +/* __ctype_XXX_t types and __UCLIBC_CTYPE_x_TBL_OFFSET constants */ +#include + +#ifdef __UCLIBC_HAS_CTYPE_SIGNED__ +# define __UCLIBC_CTYPE_IN_TO_DOMAIN(c) (((unsigned int)((c) + 128)) < 384) +#else +# define __UCLIBC_CTYPE_IN_TO_DOMAIN(c) (((unsigned int)(c)) < 256) +#endif + +/* In the thread-specific locale model (see `uselocale' in ) + we cannot use global variables for these as was done in the past. + Instead, the following accessor functions return the address of + each variable, which is local to the current thread if multithreaded. + + These point into arrays of 384, so they can be indexed by any `unsigned + char' value [0,255]; by EOF (-1); or by any `signed char' value + [-128,-1). ISO C requires that the ctype functions work for `unsigned + char' values and for EOF; we also support negative `signed char' values + for broken old programs. The case conversion arrays are of `int's + rather than `unsigned char's because tolower (EOF) must be EOF, which + doesn't fit into an `unsigned char'. But today more important is that + the arrays are also used for multi-byte character sets. */ + +/* uClibc differences: + * + * When __UCLIBC_HAS_CTYPE_SIGNED is defined, + * + * The upper and lower mapping arrays are type int16_t, so that + * they may store all char values plus EOF. The glibc reasoning + * given above for these being type int is questionable, as the + * ctype mapping functions map from the set of (unsigned) char + * and EOF back into the set. They have no awareness of multi-byte + * or wide characters. + * + * Otherwise, + * + * The ctype array is defined for -1..255. + * The upper and lower mapping arrays are defined for 0..255. + * The upper and lower mapping arrays are type unsigned char. + */ + +/* Pointers to the default C-locale data. */ +extern const __ctype_mask_t *__C_ctype_b; +libc_hidden_proto(__C_ctype_b) +extern const __ctype_touplow_t *__C_ctype_toupper; +libc_hidden_proto(__C_ctype_toupper) +extern const __ctype_touplow_t *__C_ctype_tolower; +libc_hidden_proto(__C_ctype_tolower) + +#ifdef __UCLIBC_HAS_XLOCALE__ + +const __ctype_mask_t **__ctype_b_loc(void) __attribute__ ((const)); +libc_hidden_proto(__ctype_b_loc) +const __ctype_touplow_t **__ctype_tolower_loc(void) __attribute__ ((const)); +libc_hidden_proto(__ctype_tolower_loc) +const __ctype_touplow_t **__ctype_toupper_loc(void) __attribute__ ((const)); +libc_hidden_proto(__ctype_toupper_loc) +#define __UCLIBC_CTYPE_B (*__ctype_b_loc()) +#define __UCLIBC_CTYPE_TOLOWER (*__ctype_tolower_loc()) +#define __UCLIBC_CTYPE_TOUPPER (*__ctype_toupper_loc()) + +#else /* __UCLIBC_HAS_XLOCALE__ */ + +/* Pointers to the current global locale data in use. */ +extern const __ctype_mask_t *__ctype_b; +libc_hidden_proto(__ctype_b) +extern const __ctype_touplow_t *__ctype_toupper; +libc_hidden_proto(__ctype_toupper) +extern const __ctype_touplow_t *__ctype_tolower; +libc_hidden_proto(__ctype_tolower) +#define __UCLIBC_CTYPE_B (__ctype_b) +#define __UCLIBC_CTYPE_TOLOWER (__ctype_tolower) +#define __UCLIBC_CTYPE_TOUPPER (__ctype_toupper) + +#endif /* __UCLIBC_HAS_XLOCALE__ */ + +#ifdef __UCLIBC_SUSV4_LEGACY__ +#define __isascii(c) (((c) & ~0x7f) == 0) /* If C is a 7 bit value. */ +#define __toascii(c) ((c) & 0x7f) /* Mask off high bits. */ +#endif + +#ifdef _LIBC +/* These are uClibc-specific. */ +#define __isdigit_char(C) (((unsigned char)((C) - '0')) <= 9) +#define __isdigit_int(C) (((unsigned int)((C) - '0')) <= 9) +#endif + +#ifdef __USE_GNU +/* Test C for a set of character classes according to MASK. */ +extern int isctype(int __c, int __mask) __THROW; +#endif + +#if (defined __USE_SVID || defined __USE_MISC || defined __USE_XOPEN) \ + && defined __UCLIBC_SUSV4_LEGACY__ +/* These are the same as `toupper' and `tolower' except that they do not + check the argument for being in the range of a `char'. */ +extern int _toupper(int __c) __THROW; +extern int _tolower(int __c) __THROW; +#endif /* Use SVID or use misc. */ + +/* This code is needed for the optimized mapping functions. */ +#define __tobody(c, f, table, args) \ +(__extension__ ({ \ + int __res; \ + if (sizeof(c) > 1) { \ + if (__builtin_constant_p(c)) { \ + int __c = (c); \ + __res = __UCLIBC_CTYPE_IN_TO_DOMAIN(__c) ? (table)[__c] : __c; \ + } else \ + __res = f args; \ + } else \ + __res = (table)[(int) (c)]; \ + __res; \ +})) + +#define __isctype(c, type) ((__UCLIBC_CTYPE_B)[(int)(c)] & (__ctype_mask_t)type) +/* Do not combine in one #if - unifdef tool is not that clever */ +#ifndef __NO_CTYPE +#ifndef __cplusplus +# define isalnum(c) __isctype((c), _ISalnum) +# define isalpha(c) __isctype((c), _ISalpha) +# define iscntrl(c) __isctype((c), _IScntrl) +# define isdigit(c) __isctype((c), _ISdigit) +# define islower(c) __isctype((c), _ISlower) +# define isgraph(c) __isctype((c), _ISgraph) +# define isprint(c) __isctype((c), _ISprint) +# define ispunct(c) __isctype((c), _ISpunct) +# define isspace(c) __isctype((c), _ISspace) +# define isupper(c) __isctype((c), _ISupper) +# define isxdigit(c) __isctype((c), _ISxdigit) +# ifdef __USE_ISOC99 +# define isblank(c) __isctype((c), _ISblank) +# endif + +# ifdef __USE_EXTERN_INLINES +__extern_inline int +__NTH (tolower (int __c)) +{ + return __UCLIBC_CTYPE_IN_TO_DOMAIN(__c) ? (__UCLIBC_CTYPE_TOLOWER)[__c] : __c; +} +__extern_inline int +__NTH (toupper (int __c)) +{ + return __UCLIBC_CTYPE_IN_TO_DOMAIN(__c) ? (__UCLIBC_CTYPE_TOUPPER)[__c] : __c; +} +# endif + +# if __GNUC__ >= 2 && defined __OPTIMIZE__ && !defined __cplusplus +# define tolower(c) __tobody(c, tolower, __UCLIBC_CTYPE_TOLOWER, (c)) +# define toupper(c) __tobody(c, toupper, __UCLIBC_CTYPE_TOUPPER, (c)) +# endif /* Optimizing gcc */ + +# if (defined __USE_SVID || defined __USE_MISC || defined __USE_XOPEN) \ + && defined __UCLIBC_SUSV4_LEGACY__ +# define isascii(c) __isascii (c) +# define toascii(c) __toascii (c) +# define _tolower(c) ((int) (__UCLIBC_CTYPE_TOLOWER)[(int) (c)]) +# define _toupper(c) ((int) (__UCLIBC_CTYPE_TOUPPER)[(int) (c)]) +# endif + +#endif /* not __cplusplus */ +#endif /* not __NO_CTYPE */ + + +#if defined __USE_GNU && defined __UCLIBC_HAS_XLOCALE__ +/* The concept of one static locale per category is not very well + thought out. Many applications will need to process its data using + information from several different locales. Another application is + the implementation of the internationalization handling in the + upcoming ISO C++ standard library. To support this another set of + the functions using locale data exist which have an additional + argument. + + Attention: all these functions are *not* standardized in any form. + This is a proof-of-concept implementation. */ + +/* Structure for reentrant locale using functions. This is an + (almost) opaque type for the user level programs. */ +# include + +/* These definitions are similar to the ones above but all functions + take as an argument a handle for the locale which shall be used. */ +extern int isalnum_l(int, __locale_t) __THROW; +libc_hidden_proto(isalnum_l) +extern int isalpha_l(int, __locale_t) __THROW; +libc_hidden_proto(isalpha_l) +extern int iscntrl_l(int, __locale_t) __THROW; +libc_hidden_proto(iscntrl_l) +extern int isdigit_l(int, __locale_t) __THROW; +libc_hidden_proto(isdigit_l) +extern int islower_l(int, __locale_t) __THROW; +libc_hidden_proto(islower_l) +extern int isgraph_l(int, __locale_t) __THROW; +libc_hidden_proto(isgraph_l) +extern int isprint_l(int, __locale_t) __THROW; +libc_hidden_proto(isprint_l) +extern int ispunct_l(int, __locale_t) __THROW; +libc_hidden_proto(ispunct_l) +extern int isspace_l(int, __locale_t) __THROW; +libc_hidden_proto(isspace_l) +extern int isupper_l(int, __locale_t) __THROW; +libc_hidden_proto(isupper_l) +extern int isxdigit_l(int, __locale_t) __THROW; +libc_hidden_proto(isxdigit_l) +extern int isblank_l(int, __locale_t) __THROW; +libc_hidden_proto(isblank_l) + +# if (defined __USE_SVID || defined __USE_MISC || defined __USE_XOPEN) \ + && defined __UCLIBC_SUSV4_LEGACY__ +/* Return nonzero iff C is in the ASCII set + (i.e., is no more than 7 bits wide). */ +extern int isascii_l (int __c) __THROW; +libc_hidden_proto(isascii_l) + +# endif + +/* Return the lowercase version of C in locale L. */ +/* "ordinary" ctype.h has no __tolower, why we try to have it? + * remove after 0.9.31 + *extern int __tolower_l (int __c, __locale_t __l) __THROW; */ +extern int tolower_l (int __c, __locale_t __l) __THROW; +libc_hidden_proto(tolower_l) + +/* Return the uppercase version of C. */ +/*extern int __toupper_l (int __c, __locale_t __l) __THROW; */ +extern int toupper_l (int __c, __locale_t __l) __THROW; +libc_hidden_proto(toupper_l) + +# if __GNUC__ >= 2 && defined __OPTIMIZE__ && !defined __cplusplus +# define tolower_l(c, locale) __tobody(c, tolower_l, (locale)->__ctype_tolower, (c, locale)) +# define toupper_l(c, locale) __tobody(c, toupper_l, (locale)->__ctype_toupper, (c, locale)) +/*# define __tolower_l(c, locale) tolower_l((c), (locale)) */ +/*# define __toupper_l(c, locale) toupper_l((c), (locale)) */ +# endif /* Optimizing gcc */ + + +# define __isctype_l(c, type, locale) ((locale)->__ctype_b[(int) (c)] & (__ctype_mask_t) type) +# ifndef __NO_CTYPE +# define __isalnum_l(c,l) __isctype_l((c), _ISalnum, (l)) +# define __isalpha_l(c,l) __isctype_l((c), _ISalpha, (l)) +# define __iscntrl_l(c,l) __isctype_l((c), _IScntrl, (l)) +# define __isdigit_l(c,l) __isctype_l((c), _ISdigit, (l)) +# define __islower_l(c,l) __isctype_l((c), _ISlower, (l)) +# define __isgraph_l(c,l) __isctype_l((c), _ISgraph, (l)) +# define __isprint_l(c,l) __isctype_l((c), _ISprint, (l)) +# define __ispunct_l(c,l) __isctype_l((c), _ISpunct, (l)) +# define __isspace_l(c,l) __isctype_l((c), _ISspace, (l)) +# define __isupper_l(c,l) __isctype_l((c), _ISupper, (l)) +# define __isxdigit_l(c,l) __isctype_l((c), _ISxdigit, (l)) +# define __isblank_l(c,l) __isctype_l((c), _ISblank, (l)) + +# if (defined __USE_SVID || defined __USE_MISC || defined __USE_XOPEN) \ + && defined __UCLIBC_SUSV4_LEGACY__ +# define __isascii_l(c,l) ((l), __isascii (c)) +# define __toascii_l(c,l) ((l), __toascii (c)) +# endif + +# define isalnum_l(c,l) __isalnum_l ((c), (l)) +# define isalpha_l(c,l) __isalpha_l ((c), (l)) +# define iscntrl_l(c,l) __iscntrl_l ((c), (l)) +# define isdigit_l(c,l) __isdigit_l ((c), (l)) +# define islower_l(c,l) __islower_l ((c), (l)) +# define isgraph_l(c,l) __isgraph_l ((c), (l)) +# define isprint_l(c,l) __isprint_l ((c), (l)) +# define ispunct_l(c,l) __ispunct_l ((c), (l)) +# define isspace_l(c,l) __isspace_l ((c), (l)) +# define isupper_l(c,l) __isupper_l ((c), (l)) +# define isxdigit_l(c,l) __isxdigit_l ((c), (l)) +# define isblank_l(c,l) __isblank_l ((c), (l)) + +# if (defined __USE_SVID || defined __USE_MISC || defined __USE_XOPEN) \ + && defined __UCLIBC_SUSV4_LEGACY__ +# define isascii_l(c,l) __isascii_l ((c), (l)) +# define toascii_l(c,l) __toascii_l ((c), (l)) +# endif + +# endif /* Not __NO_CTYPE. */ + +#endif /* Use GNU. */ + +__END_DECLS + +#endif /* __UCLIBC_HAS_CTYPE_TABLES__ */ + +/* We define {__,}isascii for internal use only */ +#if defined _LIBC && !defined __UCLIBC_SUSV4_LEGACY__ +# define __isascii(c) (((c) & ~0x7f) == 0) +# define isascii(c) __isascii (c) +#endif + +#endif /* ctype.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/dirent.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/dirent.h new file mode 100644 index 00000000..a9ff465f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/dirent.h @@ -0,0 +1,371 @@ +/* Copyright (C) 1991-2000, 2003-2005, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * POSIX Standard: 5.1.2 Directory Operations + */ + +#ifndef _DIRENT_H +#define _DIRENT_H 1 + +#include + +__BEGIN_DECLS + +#include + +#ifdef __USE_XOPEN +# ifndef __ino_t_defined +# ifndef __USE_FILE_OFFSET64 +typedef __ino_t ino_t; +# else +typedef __ino64_t ino_t; +# endif +# define __ino_t_defined +# endif +# if defined __USE_LARGEFILE64 && !defined __ino64_t_defined +typedef __ino64_t ino64_t; +# define __ino64_t_defined +# endif +#endif + +/* This file defines `struct dirent'. + + It defines the macro `_DIRENT_HAVE_D_NAMLEN' iff there is a `d_namlen' + member that gives the length of `d_name'. + + It defines the macro `_DIRENT_HAVE_D_RECLEN' iff there is a `d_reclen' + member that gives the size of the entire directory entry. + + It defines the macro `_DIRENT_HAVE_D_OFF' iff there is a `d_off' + member that gives the file offset of the next directory entry. + + It defines the macro `_DIRENT_HAVE_D_TYPE' iff there is a `d_type' + member that gives the type of the file. + */ + +#include + +#if (defined __USE_BSD || defined __USE_MISC) && !defined d_fileno +# define d_ino d_fileno /* Backward compatibility. */ +#endif + +/* These macros extract size information from a `struct dirent *'. + They may evaluate their argument multiple times, so it must not + have side effects. Each of these may involve a relatively costly + call to `strlen' on some systems, so these values should be cached. + + _D_EXACT_NAMLEN (DP) returns the length of DP->d_name, not including + its terminating null character. + + _D_ALLOC_NAMLEN (DP) returns a size at least (_D_EXACT_NAMLEN (DP) + 1); + that is, the allocation size needed to hold the DP->d_name string. + Use this macro when you don't need the exact length, just an upper bound. + This macro is less likely to require calling `strlen' than _D_EXACT_NAMLEN. + */ + +#ifdef _DIRENT_HAVE_D_NAMLEN +# define _D_EXACT_NAMLEN(d) ((d)->d_namlen) +# define _D_ALLOC_NAMLEN(d) (_D_EXACT_NAMLEN (d) + 1) +#else +# define _D_EXACT_NAMLEN(d) (strlen ((d)->d_name)) +# ifdef _DIRENT_HAVE_D_RECLEN +# define _D_ALLOC_NAMLEN(d) (((char *) (d) + (d)->d_reclen) - &(d)->d_name[0]) +# else +# define _D_ALLOC_NAMLEN(d) (sizeof (d)->d_name > 1 ? sizeof (d)->d_name : \ + _D_EXACT_NAMLEN (d) + 1) +# endif +#endif + + +#ifdef __USE_BSD +/* File types for `d_type'. */ +enum + { + DT_UNKNOWN = 0, +# define DT_UNKNOWN DT_UNKNOWN + DT_FIFO = 1, +# define DT_FIFO DT_FIFO + DT_CHR = 2, +# define DT_CHR DT_CHR + DT_DIR = 4, +# define DT_DIR DT_DIR + DT_BLK = 6, +# define DT_BLK DT_BLK + DT_REG = 8, +# define DT_REG DT_REG + DT_LNK = 10, +# define DT_LNK DT_LNK + DT_SOCK = 12, +# define DT_SOCK DT_SOCK + DT_WHT = 14 +# define DT_WHT DT_WHT + }; + +/* Convert between stat structure types and directory types. */ +# define IFTODT(mode) (((mode) & 0170000) >> 12) +# define DTTOIF(dirtype) ((dirtype) << 12) +#endif + + +/* This is the data type of directory stream objects. + The actual structure is opaque to users. */ +typedef struct __dirstream DIR; + +/* Open a directory stream on NAME. + Return a DIR stream on the directory, or NULL if it could not be opened. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern DIR *opendir (__const char *__name) __nonnull ((1)); +libc_hidden_proto(opendir) + +#ifdef __USE_XOPEN2K8 +/* Same as opendir, but open the stream on the file descriptor FD. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern DIR *fdopendir (int __fd); +#endif + +/* Close the directory stream DIRP. + Return 0 if successful, -1 if not. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern int closedir (DIR *__dirp) __nonnull ((1)); +libc_hidden_proto(closedir) + +/* Read a directory entry from DIRP. Return a pointer to a `struct + dirent' describing the entry, or NULL for EOF or error. The + storage returned may be overwritten by a later readdir call on the + same DIR stream. + + If the Large File Support API is selected we have to use the + appropriate interface. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +#ifndef __USE_FILE_OFFSET64 +extern struct dirent *readdir (DIR *__dirp) __nonnull ((1)); +libc_hidden_proto(readdir) +#else +# ifdef __REDIRECT +extern struct dirent *__REDIRECT (readdir, (DIR *__dirp), readdir64) + __nonnull ((1)); +# else +# define readdir readdir64 +# endif +#endif + +#ifdef __USE_LARGEFILE64 +extern struct dirent64 *readdir64 (DIR *__dirp) __nonnull ((1)); +libc_hidden_proto(readdir64) +#endif + +#if defined __USE_POSIX || defined __USE_MISC +/* Reentrant version of `readdir'. Return in RESULT a pointer to the + next entry. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +# ifndef __USE_FILE_OFFSET64 +extern int readdir_r (DIR *__restrict __dirp, + struct dirent *__restrict __entry, + struct dirent **__restrict __result) + __nonnull ((1, 2, 3)); +libc_hidden_proto(readdir_r) +# else +# ifdef __REDIRECT +extern int __REDIRECT (readdir_r, + (DIR *__restrict __dirp, + struct dirent *__restrict __entry, + struct dirent **__restrict __result), + readdir64_r) __nonnull ((1, 2, 3)); +# else +# define readdir_r readdir64_r +# endif +# endif + +# ifdef __USE_LARGEFILE64 +extern int readdir64_r (DIR *__restrict __dirp, + struct dirent64 *__restrict __entry, + struct dirent64 **__restrict __result) + __nonnull ((1, 2, 3)); +libc_hidden_proto(readdir64_r) +# endif +#endif /* POSIX or misc */ + +/* Rewind DIRP to the beginning of the directory. */ +extern void rewinddir (DIR *__dirp) __THROW __nonnull ((1)); + +#if defined __USE_BSD || defined __USE_MISC || defined __USE_XOPEN +# include + +/* Seek to position POS on DIRP. */ +extern void seekdir (DIR *__dirp, long int __pos) __THROW __nonnull ((1)); + +/* Return the current position of DIRP. */ +extern long int telldir (DIR *__dirp) __THROW __nonnull ((1)); +#endif + +#if defined __USE_BSD || defined __USE_MISC || defined __XOPEN_2K8 + +/* Return the file descriptor used by DIRP. */ +extern int dirfd (DIR *__dirp) __THROW __nonnull ((1)); +libc_hidden_proto(dirfd) + +# if 0 /* defined __OPTIMIZE__ && defined _DIR_dirfd */ +# define dirfd(dirp) _DIR_dirfd (dirp) +# endif + +# if defined __USE_BSD || defined __USE_MISC +# ifndef MAXNAMLEN +/* Get the definitions of the POSIX.1 limits. */ +# include + +/* `MAXNAMLEN' is the BSD name for what POSIX calls `NAME_MAX'. */ +# ifdef NAME_MAX +# define MAXNAMLEN NAME_MAX +# else +# define MAXNAMLEN 255 +# endif +# endif +# endif + +# define __need_size_t +# include + +/* Scan the directory DIR, calling SELECTOR on each directory entry. + Entries for which SELECT returns nonzero are individually malloc'd, + sorted using qsort with CMP, and collected in a malloc'd array in + *NAMELIST. Returns the number of entries selected, or -1 on error. */ +# ifndef __USE_FILE_OFFSET64 +extern int scandir (__const char *__restrict __dir, + struct dirent ***__restrict __namelist, + int (*__selector) (__const struct dirent *), + int (*__cmp) (__const struct dirent **, + __const struct dirent **)) + __nonnull ((1, 2)); +# else +# ifdef __REDIRECT +extern int __REDIRECT (scandir, + (__const char *__restrict __dir, + struct dirent ***__restrict __namelist, + int (*__selector) (__const struct dirent *), + int (*__cmp) (__const struct dirent **, + __const struct dirent **)), + scandir64) __nonnull ((1, 2)); +# else +# define scandir scandir64 +# endif +# endif + +# if defined __USE_GNU && defined __USE_LARGEFILE64 +/* This function is like `scandir' but it uses the 64bit dirent structure. + Please note that the CMP function must now work with struct dirent64 **. */ +extern int scandir64 (__const char *__restrict __dir, + struct dirent64 ***__restrict __namelist, + int (*__selector) (__const struct dirent64 *), + int (*__cmp) (__const struct dirent64 **, + __const struct dirent64 **)) + __nonnull ((1, 2)); +# endif + +/* Function to compare two `struct dirent's alphabetically. */ +# ifndef __USE_FILE_OFFSET64 +extern int alphasort (__const struct dirent **__e1, + __const struct dirent **__e2) + __THROW __attribute_pure__ __nonnull ((1, 2)); +# else +# ifdef __REDIRECT +extern int __REDIRECT_NTH (alphasort, + (__const struct dirent **__e1, + __const struct dirent **__e2), + alphasort64) __attribute_pure__ __nonnull ((1, 2)); +# else +# define alphasort alphasort64 +# endif +# endif + +# if defined __USE_GNU && defined __USE_LARGEFILE64 +extern int alphasort64 (__const struct dirent64 **__e1, + __const struct dirent64 **__e2) + __THROW __attribute_pure__ __nonnull ((1, 2)); +# endif +#endif /* Use BSD or misc or XPG7. */ + + +#if defined __USE_BSD || defined __USE_MISC +/* Read directory entries from FD into BUF, reading at most NBYTES. + Reading starts at offset *BASEP, and *BASEP is updated with the new + position after reading. Returns the number of bytes read; zero when at + end of directory; or -1 for errors. */ +# ifndef __USE_FILE_OFFSET64 +extern __ssize_t getdirentries (int __fd, char *__restrict __buf, + size_t __nbytes, + __off_t *__restrict __basep) + __THROW __nonnull ((2, 4)); +# else +# ifdef __REDIRECT +extern __ssize_t __REDIRECT_NTH (getdirentries, + (int __fd, char *__restrict __buf, + size_t __nbytes, + __off64_t *__restrict __basep), + getdirentries64) __nonnull ((2, 4)); +# else +# define getdirentries getdirentries64 +# endif +# endif + +# ifdef __USE_LARGEFILE64 +extern __ssize_t getdirentries64 (int __fd, char *__restrict __buf, + size_t __nbytes, + __off64_t *__restrict __basep) + __THROW __nonnull ((2, 4)); +# endif +#endif /* Use BSD or misc. */ + +#ifdef __USE_GNU +/* Function to compare two `struct dirent's by name & version. */ +# ifndef __USE_FILE_OFFSET64 +extern int versionsort (__const struct dirent **__e1, + __const struct dirent **__e2) + __THROW __attribute_pure__ __nonnull ((1, 2)); +# else +# ifdef __REDIRECT +extern int __REDIRECT_NTH (versionsort, + (__const struct dirent **__e1, + __const struct dirent **__e2), + versionsort64) + __attribute_pure__ __nonnull ((1, 2)); +# else +# define versionsort versionsort64 +# endif +# endif + +# ifdef __USE_LARGEFILE64 +extern int versionsort64 (__const struct dirent64 **__e1, + __const struct dirent64 **__e2) + __THROW __attribute_pure__ __nonnull ((1, 2)); +# endif +#endif /* Use GNU. */ + +__END_DECLS + +#endif /* dirent.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/dlfcn.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/dlfcn.h new file mode 100644 index 00000000..2348e436 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/dlfcn.h @@ -0,0 +1,201 @@ +/* User functions for run-time dynamic loading. + Copyright (C) 1995-1999,2000,2001,2003,2004,2006 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _DLFCN_H +#define _DLFCN_H 1 + +#include +#define __need_size_t +#include + +/* Collect various system dependent definitions and declarations. */ +#include + + +#ifdef __USE_GNU +/* If the first argument of `dlsym' or `dlvsym' is set to RTLD_NEXT + the run-time address of the symbol called NAME in the next shared + object is returned. The "next" relation is defined by the order + the shared objects were loaded. */ +# define RTLD_NEXT ((void *) -1l) + +/* If the first argument to `dlsym' or `dlvsym' is set to RTLD_DEFAULT + the run-time address of the symbol called NAME in the global scope + is returned. */ +# define RTLD_DEFAULT ((void *) 0) + + +# if 0 /* uClibc doesnt support this */ +/* Type for namespace indeces. */ +typedef long int Lmid_t; + +/* Special namespace ID values. */ +# define LM_ID_BASE 0 /* Initial namespace. */ +# define LM_ID_NEWLM -1 /* For dlmopen: request new namespace. */ +# endif +#endif + +__BEGIN_DECLS + +/* Open the shared object FILE and map it in; return a handle that can be + passed to `dlsym' to get symbol values from it. */ +extern void *dlopen (__const char *__file, int __mode) __THROW; + +/* Unmap and close a shared object opened by `dlopen'. + The handle cannot be used again after calling `dlclose'. */ +extern int dlclose (void *__handle) __THROW __nonnull ((1)); + +/* Find the run-time address in the shared object HANDLE refers to + of the symbol called NAME. */ +extern void *dlsym (void *__restrict __handle, + __const char *__restrict __name) __THROW __nonnull ((2)); + +#if 0 /*def __USE_GNU*/ +/* Like `dlopen', but request object to be allocated in a new namespace. */ +extern void *dlmopen (Lmid_t __nsid, __const char *__file, int __mode) __THROW; + +/* Find the run-time address in the shared object HANDLE refers to + of the symbol called NAME with VERSION. */ +extern void *dlvsym (void *__restrict __handle, + __const char *__restrict __name, + __const char *__restrict __version) + __THROW __nonnull ((2, 3)); +#endif + +/* When any of the above functions fails, call this function + to return a string describing the error. Each call resets + the error string so that a following call returns null. */ +extern char *dlerror (void) __THROW; + + +#ifdef __USE_GNU +/* Structure containing information about object searched using + `dladdr'. */ +typedef struct +{ + __const char *dli_fname; /* File name of defining object. */ + void *dli_fbase; /* Load address of that object. */ + __const char *dli_sname; /* Name of nearest symbol. */ + void *dli_saddr; /* Exact value of nearest symbol. */ +} Dl_info; + +/* Fill in *INFO with the following information about ADDRESS. + Returns 0 iff no shared object's segments contain that address. */ +extern int dladdr (__const void *__address, Dl_info *__info) + __THROW __nonnull ((2)); + +#if 0 /* not supported by uClibc */ +/* Same as `dladdr', but additionally sets *EXTRA_INFO according to FLAGS. */ +extern int dladdr1 (__const void *__address, Dl_info *__info, + void **__extra_info, int __flags) __THROW __nonnull ((2)); + +/* These are the possible values for the FLAGS argument to `dladdr1'. + This indicates what extra information is stored at *EXTRA_INFO. + It may also be zero, in which case the EXTRA_INFO argument is not used. */ +enum + { + /* Matching symbol table entry (const ElfNN_Sym *). */ + RTLD_DL_SYMENT = 1, + + /* The object containing the address (struct link_map *). */ + RTLD_DL_LINKMAP = 2 + }; + + +/* Get information about the shared object HANDLE refers to. + REQUEST is from among the values below, and determines the use of ARG. + + On success, returns zero. On failure, returns -1 and records an error + message to be fetched with `dlerror'. */ +extern int dlinfo (void *__restrict __handle, + int __request, void *__restrict __arg) + __THROW __nonnull ((1, 3)); + +/* These are the possible values for the REQUEST argument to `dlinfo'. */ +enum + { + /* Treat ARG as `lmid_t *'; store namespace ID for HANDLE there. */ + RTLD_DI_LMID = 1, + + /* Treat ARG as `struct link_map **'; + store the `struct link_map *' for HANDLE there. */ + RTLD_DI_LINKMAP = 2, + + RTLD_DI_CONFIGADDR = 3, /* Unsupported, defined by Solaris. */ + + /* Treat ARG as `Dl_serinfo *' (see below), and fill in to describe the + directories that will be searched for dependencies of this object. + RTLD_DI_SERINFOSIZE fills in just the `dls_cnt' and `dls_size' + entries to indicate the size of the buffer that must be passed to + RTLD_DI_SERINFO to fill in the full information. */ + RTLD_DI_SERINFO = 4, + RTLD_DI_SERINFOSIZE = 5, + + /* Treat ARG as `char *', and store there the directory name used to + expand $ORIGIN in this shared object's dependency file names. */ + RTLD_DI_ORIGIN = 6, + + RTLD_DI_PROFILENAME = 7, /* Unsupported, defined by Solaris. */ + RTLD_DI_PROFILEOUT = 8, /* Unsupported, defined by Solaris. */ + + /* Treat ARG as `size_t *', and store there the TLS module ID + of this object's PT_TLS segment, as used in TLS relocations; + store zero if this object does not define a PT_TLS segment. */ + RTLD_DI_TLS_MODID = 9, + + /* Treat ARG as `void **', and store there a pointer to the calling + thread's TLS block corresponding to this object's PT_TLS segment. + Store a null pointer if this object does not define a PT_TLS + segment, or if the calling thread has not allocated a block for it. */ + RTLD_DI_TLS_DATA = 10, + + RTLD_DI_MAX = 10, + }; + + +/* This is the type of elements in `Dl_serinfo', below. + The `dls_name' member points to space in the buffer passed to `dlinfo'. */ +typedef struct +{ + char *dls_name; /* Name of library search path directory. */ + unsigned int dls_flags; /* Indicates where this directory came from. */ +} Dl_serpath; + +/* This is the structure that must be passed (by reference) to `dlinfo' for + the RTLD_DI_SERINFO and RTLD_DI_SERINFOSIZE requests. */ +typedef struct +{ + size_t dls_size; /* Size in bytes of the whole buffer. */ + unsigned int dls_cnt; /* Number of elements in `dls_serpath'. */ + Dl_serpath dls_serpath[1]; /* Actually longer, dls_cnt elements. */ +} Dl_serinfo; + +#else + +/* Get information about the shared objects currently loaded */ +extern int dlinfo (void); + +#endif +#endif /* __USE_GNU */ + + +__END_DECLS + +#endif /* dlfcn.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/elf.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/elf.h new file mode 100644 index 00000000..b86aa52b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/elf.h @@ -0,0 +1,3070 @@ +/* This file defines standard ELF types, structures, and macros. + Copyright (C) 1995-2003, 2004, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _ELF_H +#define _ELF_H 1 + +/* Avoid features.h here for portability. This stuff matches sys/cdefs.h. */ +#ifdef __cplusplus +extern "C" { +#endif + +/* Standard ELF types. */ + +#include +#include + +/* Type for a 16-bit quantity. */ +typedef uint16_t Elf32_Half; +typedef uint16_t Elf64_Half; + +/* Types for signed and unsigned 32-bit quantities. */ +typedef uint32_t Elf32_Word; +typedef int32_t Elf32_Sword; +typedef uint32_t Elf64_Word; +typedef int32_t Elf64_Sword; + +/* Types for signed and unsigned 64-bit quantities. */ +typedef uint64_t Elf32_Xword; +typedef int64_t Elf32_Sxword; +typedef uint64_t Elf64_Xword; +typedef int64_t Elf64_Sxword; + +/* Type of addresses. */ +typedef uint32_t Elf32_Addr; +typedef uint64_t Elf64_Addr; + +/* Type of file offsets. */ +typedef uint32_t Elf32_Off; +typedef uint64_t Elf64_Off; + +/* Type for section indices, which are 16-bit quantities. */ +typedef uint16_t Elf32_Section; +typedef uint16_t Elf64_Section; + +/* Type for version symbol information. */ +typedef Elf32_Half Elf32_Versym; +typedef Elf64_Half Elf64_Versym; + + +/* The ELF file header. This appears at the start of every ELF file. */ + +#define EI_NIDENT (16) + +typedef struct +{ + unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */ + Elf32_Half e_type; /* Object file type */ + Elf32_Half e_machine; /* Architecture */ + Elf32_Word e_version; /* Object file version */ + Elf32_Addr e_entry; /* Entry point virtual address */ + Elf32_Off e_phoff; /* Program header table file offset */ + Elf32_Off e_shoff; /* Section header table file offset */ + Elf32_Word e_flags; /* Processor-specific flags */ + Elf32_Half e_ehsize; /* ELF header size in bytes */ + Elf32_Half e_phentsize; /* Program header table entry size */ + Elf32_Half e_phnum; /* Program header table entry count */ + Elf32_Half e_shentsize; /* Section header table entry size */ + Elf32_Half e_shnum; /* Section header table entry count */ + Elf32_Half e_shstrndx; /* Section header string table index */ +} Elf32_Ehdr; + +typedef struct +{ + unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */ + Elf64_Half e_type; /* Object file type */ + Elf64_Half e_machine; /* Architecture */ + Elf64_Word e_version; /* Object file version */ + Elf64_Addr e_entry; /* Entry point virtual address */ + Elf64_Off e_phoff; /* Program header table file offset */ + Elf64_Off e_shoff; /* Section header table file offset */ + Elf64_Word e_flags; /* Processor-specific flags */ + Elf64_Half e_ehsize; /* ELF header size in bytes */ + Elf64_Half e_phentsize; /* Program header table entry size */ + Elf64_Half e_phnum; /* Program header table entry count */ + Elf64_Half e_shentsize; /* Section header table entry size */ + Elf64_Half e_shnum; /* Section header table entry count */ + Elf64_Half e_shstrndx; /* Section header string table index */ +} Elf64_Ehdr; + +/* Fields in the e_ident array. The EI_* macros are indices into the + array. The macros under each EI_* macro are the values the byte + may have. */ + +#define EI_MAG0 0 /* File identification byte 0 index */ +#define ELFMAG0 0x7f /* Magic number byte 0 */ + +#define EI_MAG1 1 /* File identification byte 1 index */ +#define ELFMAG1 'E' /* Magic number byte 1 */ + +#define EI_MAG2 2 /* File identification byte 2 index */ +#define ELFMAG2 'L' /* Magic number byte 2 */ + +#define EI_MAG3 3 /* File identification byte 3 index */ +#define ELFMAG3 'F' /* Magic number byte 3 */ + +/* Conglomeration of the identification bytes, for easy testing as a word. */ +#define ELFMAG "\177ELF" +#define SELFMAG 4 +#if __BYTE_ORDER == __LITTLE_ENDIAN +# define ELFMAG_U32 ((uint32_t)(ELFMAG0 + 0x100 * (ELFMAG1 + (0x100 * (ELFMAG2 + 0x100 * ELFMAG3))))) +#elif __BYTE_ORDER == __BIG_ENDIAN +# define ELFMAG_U32 ((uint32_t)((((ELFMAG0 * 0x100) + ELFMAG1) * 0x100 + ELFMAG2) * 0x100 + ELFMAG3)) +#endif + +#define EI_CLASS 4 /* File class byte index */ +#define ELFCLASSNONE 0 /* Invalid class */ +#define ELFCLASS32 1 /* 32-bit objects */ +#define ELFCLASS64 2 /* 64-bit objects */ +#define ELFCLASSNUM 3 + +#define EI_DATA 5 /* Data encoding byte index */ +#define ELFDATANONE 0 /* Invalid data encoding */ +#define ELFDATA2LSB 1 /* 2's complement, little endian */ +#define ELFDATA2MSB 2 /* 2's complement, big endian */ +#define ELFDATANUM 3 + +#define EI_VERSION 6 /* File version byte index */ + /* Value must be EV_CURRENT */ + +#define EI_OSABI 7 /* OS ABI identification */ +#define ELFOSABI_NONE 0 /* UNIX System V ABI */ +#define ELFOSABI_SYSV 0 /* Alias. */ +#define ELFOSABI_HPUX 1 /* HP-UX */ +#define ELFOSABI_NETBSD 2 /* NetBSD. */ +#define ELFOSABI_LINUX 3 /* Linux. */ +#define ELFOSABI_HURD 4 /* GNU/Hurd */ +#define ELFOSABI_SOLARIS 6 /* Sun Solaris. */ +#define ELFOSABI_AIX 7 /* IBM AIX. */ +#define ELFOSABI_IRIX 8 /* SGI Irix. */ +#define ELFOSABI_FREEBSD 9 /* FreeBSD. */ +#define ELFOSABI_TRU64 10 /* Compaq TRU64 UNIX. */ +#define ELFOSABI_MODESTO 11 /* Novell Modesto. */ +#define ELFOSABI_OPENBSD 12 /* OpenBSD. */ +#define ELFOSABI_OPENVMS 13 /* OpenVMS */ +#define ELFOSABI_NSK 14 /* Hewlett-Packard Non-Stop Kernel */ +#define ELFOSABI_AROS 15 /* Amiga Research OS */ +#define ELFOSABI_ARM 97 /* ARM */ +#define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */ + +#define EI_ABIVERSION 8 /* ABI version */ + +#define EI_PAD 9 /* Byte index of padding bytes */ + +/* Legal values for e_type (object file type). */ + +#define ET_NONE 0 /* No file type */ +#define ET_REL 1 /* Relocatable file */ +#define ET_EXEC 2 /* Executable file */ +#define ET_DYN 3 /* Shared object file */ +#define ET_CORE 4 /* Core file */ +#define ET_NUM 5 /* Number of defined types */ +#define ET_LOOS 0xfe00 /* OS-specific range start */ +#define ET_HIOS 0xfeff /* OS-specific range end */ +#define ET_LOPROC 0xff00 /* Processor-specific range start */ +#define ET_HIPROC 0xffff /* Processor-specific range end */ + +/* Legal values for e_machine (architecture). */ + +#define EM_NONE 0 /* No machine */ +#define EM_M32 1 /* AT&T WE 32100 */ +#define EM_SPARC 2 /* SUN SPARC */ +#define EM_386 3 /* Intel 80386 */ +#define EM_68K 4 /* Motorola m68k family */ +#define EM_88K 5 /* Motorola m88k family */ +#define EM_486 6 /* Intel 80486 *//* Reserved for future use */ +#define EM_860 7 /* Intel 80860 */ +#define EM_MIPS 8 /* MIPS R3000 big-endian */ +#define EM_S370 9 /* IBM System/370 */ +#define EM_MIPS_RS3_LE 10 /* MIPS R3000 little-endian */ + +#define EM_PARISC 15 /* HPPA */ +#define EM_VPP500 17 /* Fujitsu VPP500 */ +#define EM_SPARC32PLUS 18 /* Sun's "v8plus" */ +#define EM_960 19 /* Intel 80960 */ +#define EM_PPC 20 /* PowerPC */ +#define EM_PPC64 21 /* PowerPC 64-bit */ +#define EM_S390 22 /* IBM S390 */ + +#define EM_V800 36 /* NEC V800 series */ +#define EM_FR20 37 /* Fujitsu FR20 */ +#define EM_RH32 38 /* TRW RH-32 */ +#define EM_MCORE 39 /* Motorola M*Core */ /* May also be taken by Fujitsu MMA */ +#define EM_RCE 39 /* Old name for MCore */ +#define EM_ARM 40 /* ARM */ +#define EM_FAKE_ALPHA 41 /* Digital Alpha */ +#define EM_SH 42 /* Renesas SH */ +#define EM_SPARCV9 43 /* SPARC v9 64-bit */ +#define EM_TRICORE 44 /* Siemens Tricore */ +#define EM_ARC 45 /* Argonaut RISC Core */ +#define EM_H8_300 46 /* Renesas H8/300 */ +#define EM_H8_300H 47 /* Renesas H8/300H */ +#define EM_H8S 48 /* Renesas H8S */ +#define EM_H8_500 49 /* Renesas H8/500 */ +#define EM_IA_64 50 /* Intel Merced */ +#define EM_MIPS_X 51 /* Stanford MIPS-X */ +#define EM_COLDFIRE 52 /* Motorola Coldfire */ +#define EM_68HC12 53 /* Motorola M68HC12 */ +#define EM_MMA 54 /* Fujitsu MMA Multimedia Accelerator*/ +#define EM_PCP 55 /* Siemens PCP */ +#define EM_NCPU 56 /* Sony nCPU embeeded RISC */ +#define EM_NDR1 57 /* Denso NDR1 microprocessor */ +#define EM_STARCORE 58 /* Motorola Start*Core processor */ +#define EM_ME16 59 /* Toyota ME16 processor */ +#define EM_ST100 60 /* STMicroelectronic ST100 processor */ +#define EM_TINYJ 61 /* Advanced Logic Corp. Tinyj emb.fam*/ +#define EM_X86_64 62 /* AMD x86-64 architecture */ +#define EM_PDSP 63 /* Sony DSP Processor */ + +#define EM_FX66 66 /* Siemens FX66 microcontroller */ +#define EM_ST9PLUS 67 /* STMicroelectronics ST9+ 8/16 mc */ +#define EM_ST7 68 /* STmicroelectronics ST7 8 bit mc */ +#define EM_68HC16 69 /* Motorola MC68HC16 microcontroller */ +#define EM_68HC11 70 /* Motorola MC68HC11 microcontroller */ +#define EM_68HC08 71 /* Motorola MC68HC08 microcontroller */ +#define EM_68HC05 72 /* Motorola MC68HC05 microcontroller */ +#define EM_SVX 73 /* Silicon Graphics SVx */ +#define EM_ST19 74 /* STMicroelectronics ST19 8 bit mc */ +#define EM_VAX 75 /* Digital VAX */ +#define EM_CRIS 76 /* Axis Communications 32-bit embedded processor */ +#define EM_JAVELIN 77 /* Infineon Technologies 32-bit embedded processor */ +#define EM_FIREPATH 78 /* Element 14 64-bit DSP Processor */ +#define EM_ZSP 79 /* LSI Logic 16-bit DSP Processor */ +#define EM_MMIX 80 /* Donald Knuth's educational 64-bit processor */ +#define EM_HUANY 81 /* Harvard University machine-independent object files */ +#define EM_PRISM 82 /* SiTera Prism */ +#define EM_AVR 83 /* Atmel AVR 8-bit microcontroller */ +#define EM_FR30 84 /* Fujitsu FR30 */ +#define EM_D10V 85 /* Mitsubishi D10V */ +#define EM_D30V 86 /* Mitsubishi D30V */ +#define EM_V850 87 /* NEC v850 */ +#define EM_M32R 88 /* Renesas M32R */ +#define EM_MN10300 89 /* Matsushita MN10300 */ +#define EM_MN10200 90 /* Matsushita MN10200 */ +#define EM_PJ 91 /* picoJava */ +#define EM_OPENRISC 92 /* OpenRISC 32-bit embedded processor */ +#define EM_ARC_A5 93 /* ARC Cores Tangent-A5 */ +#define EM_XTENSA 94 /* Tensilica Xtensa Architecture */ +#define EM_IP2K 101 /* Ubicom IP2022 micro controller */ +#define EM_CR 103 /* National Semiconductor CompactRISC */ +#define EM_MSP430 105 /* TI msp430 micro controller */ +#define EM_BLACKFIN 106 /* Analog Devices Blackfin */ +#define EM_ALTERA_NIOS2 113 /* Altera Nios II soft-core processor */ +#define EM_CRX 114 /* National Semiconductor CRX */ +#define EM_NUM 95 + +/* If it is necessary to assign new unofficial EM_* values, please pick large + random numbers (0x8523, 0xa7f2, etc.) to minimize the chances of collision + with official or non-GNU unofficial values. + + NOTE: Do not just increment the most recent number by one. + Somebody else somewhere will do exactly the same thing, and you + will have a collision. Instead, pick a random number. + + Normally, each entity or maintainer responsible for a machine with an + unofficial e_machine number should eventually ask registry@caldera.com for + an officially blessed number to be added to the list above. */ + +/* picoJava */ +#define EM_PJ_OLD 99 + +/* Cygnus PowerPC ELF backend. Written in the absence of an ABI. */ +#define EM_CYGNUS_POWERPC 0x9025 + +/* Old version of Sparc v9, from before the ABI; this should be + removed shortly. */ +#define EM_OLD_SPARCV9 11 + +/* Old version of PowerPC, this should be removed shortly. */ +#define EM_PPC_OLD 17 + +/* (Deprecated) Temporary number for the OpenRISC processor. */ +#define EM_OR32 0x8472 + +/* Renesas M32C and M16C. */ +#define EM_M32C 0xFEB0 + +/* Cygnus M32R ELF backend. Written in the absence of an ABI. */ +#define EM_CYGNUS_M32R 0x9041 + +/* old S/390 backend magic number. Written in the absence of an ABI. */ +#define EM_S390_OLD 0xa390 + +/* D10V backend magic number. Written in the absence of an ABI. */ +#define EM_CYGNUS_D10V 0x7650 + +/* D30V backend magic number. Written in the absence of an ABI. */ +#define EM_CYGNUS_D30V 0x7676 + +/* V850 backend magic number. Written in the absense of an ABI. */ +#define EM_CYGNUS_V850 0x9080 + +/* mn10200 and mn10300 backend magic numbers. + Written in the absense of an ABI. */ +#define EM_CYGNUS_MN10200 0xdead +#define EM_CYGNUS_MN10300 0xbeef + +/* FR30 magic number - no EABI available. */ +#define EM_CYGNUS_FR30 0x3330 + +/* AVR magic number + Written in the absense of an ABI. */ +#define EM_AVR_OLD 0x1057 + +/* OpenRISC magic number + Written in the absense of an ABI. */ +#define EM_OPENRISC_OLD 0x3426 + +/* DLX magic number + Written in the absense of an ABI. */ +#define EM_DLX 0x5aa5 + +#define EM_XSTORMY16 0xad45 + +/* FRV magic number - no EABI available??. */ +#define EM_CYGNUS_FRV 0x5441 + +/* Ubicom IP2xxx; no ABI */ +#define EM_IP2K_OLD 0x8217 + +#define EM_MT 0x2530 /* Morpho MT; no ABI */ + +/* MSP430 magic number + Written in the absense everything. */ +#define EM_MSP430_OLD 0x1059 + +/* Vitesse IQ2000. */ +#define EM_IQ2000 0xFEBA + +/* Old, unofficial value for Xtensa. */ +#define EM_XTENSA_OLD 0xabc7 + +/* Alpha backend magic number. Written in the absence of an ABI. */ +#define EM_ALPHA 0x9026 + +/* NIOS magic number - no EABI available. */ +#define EM_NIOS32 0xFEBB + +/* AVR32 magic number from ATMEL */ +#define EM_AVR32 0x18ad + +/* V850 backend magic number. Written in the absense of an ABI. */ +#define EM_CYGNUS_V850 0x9080 + +/* Legal values for e_version (version). */ + +#define EV_NONE 0 /* Invalid ELF version */ +#define EV_CURRENT 1 /* Current version */ +#define EV_NUM 2 + +/* Section header. */ + +typedef struct +{ + Elf32_Word sh_name; /* Section name (string tbl index) */ + Elf32_Word sh_type; /* Section type */ + Elf32_Word sh_flags; /* Section flags */ + Elf32_Addr sh_addr; /* Section virtual addr at execution */ + Elf32_Off sh_offset; /* Section file offset */ + Elf32_Word sh_size; /* Section size in bytes */ + Elf32_Word sh_link; /* Link to another section */ + Elf32_Word sh_info; /* Additional section information */ + Elf32_Word sh_addralign; /* Section alignment */ + Elf32_Word sh_entsize; /* Entry size if section holds table */ +} Elf32_Shdr; + +typedef struct +{ + Elf64_Word sh_name; /* Section name (string tbl index) */ + Elf64_Word sh_type; /* Section type */ + Elf64_Xword sh_flags; /* Section flags */ + Elf64_Addr sh_addr; /* Section virtual addr at execution */ + Elf64_Off sh_offset; /* Section file offset */ + Elf64_Xword sh_size; /* Section size in bytes */ + Elf64_Word sh_link; /* Link to another section */ + Elf64_Word sh_info; /* Additional section information */ + Elf64_Xword sh_addralign; /* Section alignment */ + Elf64_Xword sh_entsize; /* Entry size if section holds table */ +} Elf64_Shdr; + +/* Special section indices. */ + +#define SHN_UNDEF 0 /* Undefined section */ +#define SHN_LORESERVE 0xff00 /* Start of reserved indices */ +#define SHN_LOPROC 0xff00 /* Start of processor-specific */ +#define SHN_BEFORE 0xff00 /* Order section before all others + (Solaris). */ +#define SHN_AFTER 0xff01 /* Order section after all others + (Solaris). */ +#define SHN_HIPROC 0xff1f /* End of processor-specific */ +#define SHN_LOOS 0xff20 /* Start of OS-specific */ +#define SHN_HIOS 0xff3f /* End of OS-specific */ +#define SHN_ABS 0xfff1 /* Associated symbol is absolute */ +#define SHN_COMMON 0xfff2 /* Associated symbol is common */ +#define SHN_XINDEX 0xffff /* Index is in extra table. */ +#define SHN_HIRESERVE 0xffff /* End of reserved indices */ + +/* Legal values for sh_type (section type). */ + +#define SHT_NULL 0 /* Section header table entry unused */ +#define SHT_PROGBITS 1 /* Program data */ +#define SHT_SYMTAB 2 /* Symbol table */ +#define SHT_STRTAB 3 /* String table */ +#define SHT_RELA 4 /* Relocation entries with addends */ +#define SHT_HASH 5 /* Symbol hash table */ +#define SHT_DYNAMIC 6 /* Dynamic linking information */ +#define SHT_NOTE 7 /* Notes */ +#define SHT_NOBITS 8 /* Program space with no data (bss) */ +#define SHT_REL 9 /* Relocation entries, no addends */ +#define SHT_SHLIB 10 /* Reserved */ +#define SHT_DYNSYM 11 /* Dynamic linker symbol table */ +#define SHT_INIT_ARRAY 14 /* Array of constructors */ +#define SHT_FINI_ARRAY 15 /* Array of destructors */ +#define SHT_PREINIT_ARRAY 16 /* Array of pre-constructors */ +#define SHT_GROUP 17 /* Section group */ +#define SHT_SYMTAB_SHNDX 18 /* Extended section indeces */ +#define SHT_NUM 19 /* Number of defined types. */ +#define SHT_LOOS 0x60000000 /* Start OS-specific */ +#define SHT_GNU_HASH 0x6ffffff6 /* GNU-style hash table. */ +#define SHT_GNU_LIBLIST 0x6ffffff7 /* Prelink library list */ +#define SHT_CHECKSUM 0x6ffffff8 /* Checksum for DSO content. */ +#define SHT_LOSUNW 0x6ffffffa /* Sun-specific low bound. */ +#define SHT_SUNW_move 0x6ffffffa +#define SHT_SUNW_COMDAT 0x6ffffffb +#define SHT_SUNW_syminfo 0x6ffffffc +#define SHT_GNU_verdef 0x6ffffffd /* Version definition section. */ +#define SHT_GNU_verneed 0x6ffffffe /* Version needs section. */ +#define SHT_GNU_versym 0x6fffffff /* Version symbol table. */ +#define SHT_HISUNW 0x6fffffff /* Sun-specific high bound. */ +#define SHT_HIOS 0x6fffffff /* End OS-specific type */ +#define SHT_LOPROC 0x70000000 /* Start of processor-specific */ +#define SHT_HIPROC 0x7fffffff /* End of processor-specific */ +#define SHT_LOUSER 0x80000000 /* Start of application-specific */ +#define SHT_HIUSER 0x8fffffff /* End of application-specific */ + +/* Legal values for sh_flags (section flags). */ + +#define SHF_WRITE (1 << 0) /* Writable */ +#define SHF_ALLOC (1 << 1) /* Occupies memory during execution */ +#define SHF_EXECINSTR (1 << 2) /* Executable */ +#define SHF_MERGE (1 << 4) /* Might be merged */ +#define SHF_STRINGS (1 << 5) /* Contains nul-terminated strings */ +#define SHF_INFO_LINK (1 << 6) /* `sh_info' contains SHT index */ +#define SHF_LINK_ORDER (1 << 7) /* Preserve order after combining */ +#define SHF_OS_NONCONFORMING (1 << 8) /* Non-standard OS specific handling + required */ +#define SHF_GROUP (1 << 9) /* Section is member of a group. */ +#define SHF_TLS (1 << 10) /* Section hold thread-local data. */ +#define SHF_MASKOS 0x0ff00000 /* OS-specific. */ +#define SHF_MASKPROC 0xf0000000 /* Processor-specific */ +#define SHF_ORDERED (1 << 30) /* Special ordering requirement + (Solaris). */ +#define SHF_EXCLUDE (1 << 31) /* Section is excluded unless + referenced or allocated (Solaris).*/ + +/* Section group handling. */ +#define GRP_COMDAT 0x1 /* Mark group as COMDAT. */ + +/* Symbol table entry. */ + +typedef struct +{ + Elf32_Word st_name; /* Symbol name (string tbl index) */ + Elf32_Addr st_value; /* Symbol value */ + Elf32_Word st_size; /* Symbol size */ + unsigned char st_info; /* Symbol type and binding */ + unsigned char st_other; /* Symbol visibility */ + Elf32_Section st_shndx; /* Section index */ +} Elf32_Sym; + +typedef struct +{ + Elf64_Word st_name; /* Symbol name (string tbl index) */ + unsigned char st_info; /* Symbol type and binding */ + unsigned char st_other; /* Symbol visibility */ + Elf64_Section st_shndx; /* Section index */ + Elf64_Addr st_value; /* Symbol value */ + Elf64_Xword st_size; /* Symbol size */ +} Elf64_Sym; + +/* The syminfo section if available contains additional information about + every dynamic symbol. */ + +typedef struct +{ + Elf32_Half si_boundto; /* Direct bindings, symbol bound to */ + Elf32_Half si_flags; /* Per symbol flags */ +} Elf32_Syminfo; + +typedef struct +{ + Elf64_Half si_boundto; /* Direct bindings, symbol bound to */ + Elf64_Half si_flags; /* Per symbol flags */ +} Elf64_Syminfo; + +/* Possible values for si_boundto. */ +#define SYMINFO_BT_SELF 0xffff /* Symbol bound to self */ +#define SYMINFO_BT_PARENT 0xfffe /* Symbol bound to parent */ +#define SYMINFO_BT_LOWRESERVE 0xff00 /* Beginning of reserved entries */ + +/* Possible bitmasks for si_flags. */ +#define SYMINFO_FLG_DIRECT 0x0001 /* Direct bound symbol */ +#define SYMINFO_FLG_PASSTHRU 0x0002 /* Pass-thru symbol for translator */ +#define SYMINFO_FLG_COPY 0x0004 /* Symbol is a copy-reloc */ +#define SYMINFO_FLG_LAZYLOAD 0x0008 /* Symbol bound to object to be lazy + loaded */ +/* Syminfo version values. */ +#define SYMINFO_NONE 0 +#define SYMINFO_CURRENT 1 +#define SYMINFO_NUM 2 + + +/* How to extract and insert information held in the st_info field. */ + +#define ELF32_ST_BIND(val) (((unsigned char) (val)) >> 4) +#define ELF32_ST_TYPE(val) ((val) & 0xf) +#define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf)) + +/* Both Elf32_Sym and Elf64_Sym use the same one-byte st_info field. */ +#define ELF64_ST_BIND(val) ELF32_ST_BIND (val) +#define ELF64_ST_TYPE(val) ELF32_ST_TYPE (val) +#define ELF64_ST_INFO(bind, type) ELF32_ST_INFO ((bind), (type)) + +/* Legal values for ST_BIND subfield of st_info (symbol binding). */ + +#define STB_LOCAL 0 /* Local symbol */ +#define STB_GLOBAL 1 /* Global symbol */ +#define STB_WEAK 2 /* Weak symbol */ +#define STB_NUM 3 /* Number of defined types. */ +#define STB_LOOS 10 /* Start of OS-specific */ +#define STB_HIOS 12 /* End of OS-specific */ +#define STB_LOPROC 13 /* Start of processor-specific */ +#define STB_HIPROC 15 /* End of processor-specific */ + +/* Legal values for ST_TYPE subfield of st_info (symbol type). */ + +#define STT_NOTYPE 0 /* Symbol type is unspecified */ +#define STT_OBJECT 1 /* Symbol is a data object */ +#define STT_FUNC 2 /* Symbol is a code object */ +#define STT_SECTION 3 /* Symbol associated with a section */ +#define STT_FILE 4 /* Symbol's name is file name */ +#define STT_COMMON 5 /* Symbol is a common data object */ +#define STT_TLS 6 /* Symbol is thread-local data object*/ +#define STT_NUM 7 /* Number of defined types. */ +#define STT_LOOS 10 /* Start of OS-specific */ +#define STT_HIOS 12 /* End of OS-specific */ +#define STT_LOPROC 13 /* Start of processor-specific */ +#define STT_HIPROC 15 /* End of processor-specific */ + + +/* Symbol table indices are found in the hash buckets and chain table + of a symbol hash table section. This special index value indicates + the end of a chain, meaning no further symbols are found in that bucket. */ + +#define STN_UNDEF 0 /* End of a chain. */ + + +/* How to extract and insert information held in the st_other field. */ + +#define ELF32_ST_VISIBILITY(o) ((o) & 0x03) + +/* For ELF64 the definitions are the same. */ +#define ELF64_ST_VISIBILITY(o) ELF32_ST_VISIBILITY (o) + +/* Symbol visibility specification encoded in the st_other field. */ +#define STV_DEFAULT 0 /* Default symbol visibility rules */ +#define STV_INTERNAL 1 /* Processor specific hidden class */ +#define STV_HIDDEN 2 /* Sym unavailable in other modules */ +#define STV_PROTECTED 3 /* Not preemptible, not exported */ + + +/* Relocation table entry without addend (in section of type SHT_REL). */ + +typedef struct +{ + Elf32_Addr r_offset; /* Address */ + Elf32_Word r_info; /* Relocation type and symbol index */ +} Elf32_Rel; + +/* I have seen two different definitions of the Elf64_Rel and + Elf64_Rela structures, so we'll leave them out until Novell (or + whoever) gets their act together. */ +/* The following, at least, is used on Sparc v9, MIPS, and Alpha. */ + +typedef struct +{ + Elf64_Addr r_offset; /* Address */ + Elf64_Xword r_info; /* Relocation type and symbol index */ +} Elf64_Rel; + +/* Relocation table entry with addend (in section of type SHT_RELA). */ + +typedef struct +{ + Elf32_Addr r_offset; /* Address */ + Elf32_Word r_info; /* Relocation type and symbol index */ + Elf32_Sword r_addend; /* Addend */ +} Elf32_Rela; + +typedef struct +{ + Elf64_Addr r_offset; /* Address */ + Elf64_Xword r_info; /* Relocation type and symbol index */ + Elf64_Sxword r_addend; /* Addend */ +} Elf64_Rela; + +/* How to extract and insert information held in the r_info field. */ + +#define ELF32_R_SYM(val) ((val) >> 8) +#define ELF32_R_TYPE(val) ((val) & 0xff) +#define ELF32_R_INFO(sym, type) (((sym) << 8) + ((type) & 0xff)) + +#define ELF64_R_SYM(i) ((i) >> 32) +#define ELF64_R_TYPE(i) ((i) & 0xffffffff) +#define ELF64_R_INFO(sym,type) ((((Elf64_Xword) (sym)) << 32) + (type)) + +/* Program segment header. */ + +typedef struct +{ + Elf32_Word p_type; /* Segment type */ + Elf32_Off p_offset; /* Segment file offset */ + Elf32_Addr p_vaddr; /* Segment virtual address */ + Elf32_Addr p_paddr; /* Segment physical address */ + Elf32_Word p_filesz; /* Segment size in file */ + Elf32_Word p_memsz; /* Segment size in memory */ + Elf32_Word p_flags; /* Segment flags */ + Elf32_Word p_align; /* Segment alignment */ +} Elf32_Phdr; + +typedef struct +{ + Elf64_Word p_type; /* Segment type */ + Elf64_Word p_flags; /* Segment flags */ + Elf64_Off p_offset; /* Segment file offset */ + Elf64_Addr p_vaddr; /* Segment virtual address */ + Elf64_Addr p_paddr; /* Segment physical address */ + Elf64_Xword p_filesz; /* Segment size in file */ + Elf64_Xword p_memsz; /* Segment size in memory */ + Elf64_Xword p_align; /* Segment alignment */ +} Elf64_Phdr; + +/* Legal values for p_type (segment type). */ + +#define PT_NULL 0 /* Program header table entry unused */ +#define PT_LOAD 1 /* Loadable program segment */ +#define PT_DYNAMIC 2 /* Dynamic linking information */ +#define PT_INTERP 3 /* Program interpreter */ +#define PT_NOTE 4 /* Auxiliary information */ +#define PT_SHLIB 5 /* Reserved */ +#define PT_PHDR 6 /* Entry for header table itself */ +#define PT_TLS 7 /* Thread-local storage segment */ +#define PT_NUM 8 /* Number of defined types */ +#define PT_LOOS 0x60000000 /* Start of OS-specific */ +#define PT_GNU_EH_FRAME 0x6474e550 /* GCC .eh_frame_hdr segment */ +#define PT_GNU_STACK 0x6474e551 /* Indicates stack executability */ +#define PT_GNU_RELRO 0x6474e552 /* Read-only after relocation */ +#define PT_PAX_FLAGS 0x65041580 /* Indicates PaX flag markings */ +#define PT_LOSUNW 0x6ffffffa +#define PT_SUNWBSS 0x6ffffffa /* Sun Specific segment */ +#define PT_SUNWSTACK 0x6ffffffb /* Stack segment */ +#define PT_HISUNW 0x6fffffff +#define PT_HIOS 0x6fffffff /* End of OS-specific */ +#define PT_LOPROC 0x70000000 /* Start of processor-specific */ +#define PT_HIPROC 0x7fffffff /* End of processor-specific */ + +/* Legal values for p_flags (segment flags). */ + +#define PF_X (1 << 0) /* Segment is executable */ +#define PF_W (1 << 1) /* Segment is writable */ +#define PF_R (1 << 2) /* Segment is readable */ +#define PF_PAGEEXEC (1 << 4) /* Enable PAGEEXEC */ +#define PF_NOPAGEEXEC (1 << 5) /* Disable PAGEEXEC */ +#define PF_SEGMEXEC (1 << 6) /* Enable SEGMEXEC */ +#define PF_NOSEGMEXEC (1 << 7) /* Disable SEGMEXEC */ +#define PF_MPROTECT (1 << 8) /* Enable MPROTECT */ +#define PF_NOMPROTECT (1 << 9) /* Disable MPROTECT */ +#define PF_RANDEXEC (1 << 10) /* Enable RANDEXEC */ +#define PF_NORANDEXEC (1 << 11) /* Disable RANDEXEC */ +#define PF_EMUTRAMP (1 << 12) /* Enable EMUTRAMP */ +#define PF_NOEMUTRAMP (1 << 13) /* Disable EMUTRAMP */ +#define PF_RANDMMAP (1 << 14) /* Enable RANDMMAP */ +#define PF_NORANDMMAP (1 << 15) /* Disable RANDMMAP */ +#define PF_MASKOS 0x0ff00000 /* OS-specific */ +#define PF_MASKPROC 0xf0000000 /* Processor-specific */ + +/* Legal values for note segment descriptor types for core files. */ + +#define NT_PRSTATUS 1 /* Contains copy of prstatus struct */ +#define NT_FPREGSET 2 /* Contains copy of fpregset struct */ +#define NT_PRPSINFO 3 /* Contains copy of prpsinfo struct */ +#define NT_PRXREG 4 /* Contains copy of prxregset struct */ +#define NT_TASKSTRUCT 4 /* Contains copy of task structure */ +#define NT_PLATFORM 5 /* String from sysinfo(SI_PLATFORM) */ +#define NT_AUXV 6 /* Contains copy of auxv array */ +#define NT_GWINDOWS 7 /* Contains copy of gwindows struct */ +#define NT_ASRS 8 /* Contains copy of asrset struct */ +#define NT_PSTATUS 10 /* Contains copy of pstatus struct */ +#define NT_PSINFO 13 /* Contains copy of psinfo struct */ +#define NT_PRCRED 14 /* Contains copy of prcred struct */ +#define NT_UTSNAME 15 /* Contains copy of utsname struct */ +#define NT_LWPSTATUS 16 /* Contains copy of lwpstatus struct */ +#define NT_LWPSINFO 17 /* Contains copy of lwpinfo struct */ +#define NT_PRFPXREG 20 /* Contains copy of fprxregset struct*/ + +/* Legal values for the note segment descriptor types for object files. */ + +#define NT_VERSION 1 /* Contains a version string. */ + + +/* Dynamic section entry. */ + +typedef struct +{ + Elf32_Sword d_tag; /* Dynamic entry type */ + union + { + Elf32_Word d_val; /* Integer value */ + Elf32_Addr d_ptr; /* Address value */ + } d_un; +} Elf32_Dyn; + +typedef struct +{ + Elf64_Sxword d_tag; /* Dynamic entry type */ + union + { + Elf64_Xword d_val; /* Integer value */ + Elf64_Addr d_ptr; /* Address value */ + } d_un; +} Elf64_Dyn; + +/* Legal values for d_tag (dynamic entry type). */ + +#define DT_NULL 0 /* Marks end of dynamic section */ +#define DT_NEEDED 1 /* Name of needed library */ +#define DT_PLTRELSZ 2 /* Size in bytes of PLT relocs */ +#define DT_PLTGOT 3 /* Processor defined value */ +#define DT_HASH 4 /* Address of symbol hash table */ +#define DT_STRTAB 5 /* Address of string table */ +#define DT_SYMTAB 6 /* Address of symbol table */ +#define DT_RELA 7 /* Address of Rela relocs */ +#define DT_RELASZ 8 /* Total size of Rela relocs */ +#define DT_RELAENT 9 /* Size of one Rela reloc */ +#define DT_STRSZ 10 /* Size of string table */ +#define DT_SYMENT 11 /* Size of one symbol table entry */ +#define DT_INIT 12 /* Address of init function */ +#define DT_FINI 13 /* Address of termination function */ +#define DT_SONAME 14 /* Name of shared object */ +#define DT_RPATH 15 /* Library search path (deprecated) */ +#define DT_SYMBOLIC 16 /* Start symbol search here */ +#define DT_REL 17 /* Address of Rel relocs */ +#define DT_RELSZ 18 /* Total size of Rel relocs */ +#define DT_RELENT 19 /* Size of one Rel reloc */ +#define DT_PLTREL 20 /* Type of reloc in PLT */ +#define DT_DEBUG 21 /* For debugging; unspecified */ +#define DT_TEXTREL 22 /* Reloc might modify .text */ +#define DT_JMPREL 23 /* Address of PLT relocs */ +#define DT_BIND_NOW 24 /* Process relocations of object */ +#define DT_INIT_ARRAY 25 /* Array with addresses of init fct */ +#define DT_FINI_ARRAY 26 /* Array with addresses of fini fct */ +#define DT_INIT_ARRAYSZ 27 /* Size in bytes of DT_INIT_ARRAY */ +#define DT_FINI_ARRAYSZ 28 /* Size in bytes of DT_FINI_ARRAY */ +#define DT_RUNPATH 29 /* Library search path */ +#define DT_FLAGS 30 /* Flags for the object being loaded */ +#define DT_ENCODING 32 /* Start of encoded range */ +#define DT_PREINIT_ARRAY 32 /* Array with addresses of preinit fct*/ +#define DT_PREINIT_ARRAYSZ 33 /* size in bytes of DT_PREINIT_ARRAY */ +#define DT_NUM 34 /* Number used */ +#define DT_LOOS 0x6000000d /* Start of OS-specific */ +#define DT_HIOS 0x6ffff000 /* End of OS-specific */ +#define DT_LOPROC 0x70000000 /* Start of processor-specific */ +#define DT_HIPROC 0x7fffffff /* End of processor-specific */ +#define DT_PROCNUM DT_MIPS_NUM /* Most used by any processor */ + +/* DT_* entries which fall between DT_VALRNGHI & DT_VALRNGLO use the + Dyn.d_un.d_val field of the Elf*_Dyn structure. This follows Sun's + approach. */ +#define DT_VALRNGLO 0x6ffffd00 +#define DT_GNU_PRELINKED 0x6ffffdf5 /* Prelinking timestamp */ +#define DT_GNU_CONFLICTSZ 0x6ffffdf6 /* Size of conflict section */ +#define DT_GNU_LIBLISTSZ 0x6ffffdf7 /* Size of library list */ +#define DT_CHECKSUM 0x6ffffdf8 +#define DT_PLTPADSZ 0x6ffffdf9 +#define DT_MOVEENT 0x6ffffdfa +#define DT_MOVESZ 0x6ffffdfb +#define DT_FEATURE_1 0x6ffffdfc /* Feature selection (DTF_*). */ +#define DT_POSFLAG_1 0x6ffffdfd /* Flags for DT_* entries, effecting + the following DT_* entry. */ +#define DT_SYMINSZ 0x6ffffdfe /* Size of syminfo table (in bytes) */ +#define DT_SYMINENT 0x6ffffdff /* Entry size of syminfo */ +#define DT_VALRNGHI 0x6ffffdff +#define DT_VALTAGIDX(tag) (DT_VALRNGHI - (tag)) /* Reverse order! */ +#define DT_VALNUM 12 + +/* DT_* entries which fall between DT_ADDRRNGHI & DT_ADDRRNGLO use the + Dyn.d_un.d_ptr field of the Elf*_Dyn structure. + + If any adjustment is made to the ELF object after it has been + built these entries will need to be adjusted. */ +#define DT_ADDRRNGLO 0x6ffffe00 +#define DT_GNU_HASH 0x6ffffef5 /* GNU-style hash table. */ +#define DT_GNU_CONFLICT 0x6ffffef8 /* Start of conflict section */ +#define DT_GNU_LIBLIST 0x6ffffef9 /* Library list */ +#define DT_CONFIG 0x6ffffefa /* Configuration information. */ +#define DT_DEPAUDIT 0x6ffffefb /* Dependency auditing. */ +#define DT_AUDIT 0x6ffffefc /* Object auditing. */ +#define DT_PLTPAD 0x6ffffefd /* PLT padding. */ +#define DT_MOVETAB 0x6ffffefe /* Move table. */ +#define DT_SYMINFO 0x6ffffeff /* Syminfo table. */ +#define DT_ADDRRNGHI 0x6ffffeff +#define DT_ADDRTAGIDX(tag) (DT_ADDRRNGHI - (tag)) /* Reverse order! */ +#define DT_ADDRNUM 10 + +/* The versioning entry types. The next are defined as part of the + GNU extension. */ +#define DT_VERSYM 0x6ffffff0 + +#define DT_RELACOUNT 0x6ffffff9 +#define DT_RELCOUNT 0x6ffffffa + +/* These were chosen by Sun. */ +#define DT_FLAGS_1 0x6ffffffb /* State flags, see DF_1_* below. */ +#define DT_VERDEF 0x6ffffffc /* Address of version definition + table */ +#define DT_VERDEFNUM 0x6ffffffd /* Number of version definitions */ +#define DT_VERNEED 0x6ffffffe /* Address of table with needed + versions */ +#define DT_VERNEEDNUM 0x6fffffff /* Number of needed versions */ +#define DT_VERSIONTAGIDX(tag) (DT_VERNEEDNUM - (tag)) /* Reverse order! */ +#define DT_VERSIONTAGNUM 16 + +/* Sun added these machine-independent extensions in the "processor-specific" + range. Be compatible. */ +#define DT_AUXILIARY 0x7ffffffd /* Shared object to load before self */ +#define DT_FILTER 0x7fffffff /* Shared object to get values from */ +#define DT_EXTRATAGIDX(tag) ((Elf32_Word)-((Elf32_Sword) (tag) <<1>>1)-1) +#define DT_EXTRANUM 3 + +/* Values of `d_un.d_val' in the DT_FLAGS entry. */ +#define DF_ORIGIN 0x00000001 /* Object may use DF_ORIGIN */ +#define DF_SYMBOLIC 0x00000002 /* Symbol resolutions starts here */ +#define DF_TEXTREL 0x00000004 /* Object contains text relocations */ +#define DF_BIND_NOW 0x00000008 /* No lazy binding for this object */ +#define DF_STATIC_TLS 0x00000010 /* Module uses the static TLS model */ + +/* State flags selectable in the `d_un.d_val' element of the DT_FLAGS_1 + entry in the dynamic section. */ +#define DF_1_NOW 0x00000001 /* Set RTLD_NOW for this object. */ +#define DF_1_GLOBAL 0x00000002 /* Set RTLD_GLOBAL for this object. */ +#define DF_1_GROUP 0x00000004 /* Set RTLD_GROUP for this object. */ +#define DF_1_NODELETE 0x00000008 /* Set RTLD_NODELETE for this object.*/ +#define DF_1_LOADFLTR 0x00000010 /* Trigger filtee loading at runtime.*/ +#define DF_1_INITFIRST 0x00000020 /* Set RTLD_INITFIRST for this object*/ +#define DF_1_NOOPEN 0x00000040 /* Set RTLD_NOOPEN for this object. */ +#define DF_1_ORIGIN 0x00000080 /* $ORIGIN must be handled. */ +#define DF_1_DIRECT 0x00000100 /* Direct binding enabled. */ +#define DF_1_TRANS 0x00000200 +#define DF_1_INTERPOSE 0x00000400 /* Object is used to interpose. */ +#define DF_1_NODEFLIB 0x00000800 /* Ignore default lib search path. */ +#define DF_1_NODUMP 0x00001000 /* Object can't be dldump'ed. */ +#define DF_1_CONFALT 0x00002000 /* Configuration alternative created.*/ +#define DF_1_ENDFILTEE 0x00004000 /* Filtee terminates filters search. */ +#define DF_1_DISPRELDNE 0x00008000 /* Disp reloc applied at build time. */ +#define DF_1_DISPRELPND 0x00010000 /* Disp reloc applied at run-time. */ + +/* Flags for the feature selection in DT_FEATURE_1. */ +#define DTF_1_PARINIT 0x00000001 +#define DTF_1_CONFEXP 0x00000002 + +/* Flags in the DT_POSFLAG_1 entry effecting only the next DT_* entry. */ +#define DF_P1_LAZYLOAD 0x00000001 /* Lazyload following object. */ +#define DF_P1_GROUPPERM 0x00000002 /* Symbols from next object are not + generally available. */ + +/* Version definition sections. */ + +typedef struct +{ + Elf32_Half vd_version; /* Version revision */ + Elf32_Half vd_flags; /* Version information */ + Elf32_Half vd_ndx; /* Version Index */ + Elf32_Half vd_cnt; /* Number of associated aux entries */ + Elf32_Word vd_hash; /* Version name hash value */ + Elf32_Word vd_aux; /* Offset in bytes to verdaux array */ + Elf32_Word vd_next; /* Offset in bytes to next verdef + entry */ +} Elf32_Verdef; + +typedef struct +{ + Elf64_Half vd_version; /* Version revision */ + Elf64_Half vd_flags; /* Version information */ + Elf64_Half vd_ndx; /* Version Index */ + Elf64_Half vd_cnt; /* Number of associated aux entries */ + Elf64_Word vd_hash; /* Version name hash value */ + Elf64_Word vd_aux; /* Offset in bytes to verdaux array */ + Elf64_Word vd_next; /* Offset in bytes to next verdef + entry */ +} Elf64_Verdef; + + +/* Legal values for vd_version (version revision). */ +#define VER_DEF_NONE 0 /* No version */ +#define VER_DEF_CURRENT 1 /* Current version */ +#define VER_DEF_NUM 2 /* Given version number */ + +/* Legal values for vd_flags (version information flags). */ +#define VER_FLG_BASE 0x1 /* Version definition of file itself */ +#define VER_FLG_WEAK 0x2 /* Weak version identifier */ + +/* Versym symbol index values. */ +#define VER_NDX_LOCAL 0 /* Symbol is local. */ +#define VER_NDX_GLOBAL 1 /* Symbol is global. */ +#define VER_NDX_LORESERVE 0xff00 /* Beginning of reserved entries. */ +#define VER_NDX_ELIMINATE 0xff01 /* Symbol is to be eliminated. */ + +/* Auxialiary version information. */ + +typedef struct +{ + Elf32_Word vda_name; /* Version or dependency names */ + Elf32_Word vda_next; /* Offset in bytes to next verdaux + entry */ +} Elf32_Verdaux; + +typedef struct +{ + Elf64_Word vda_name; /* Version or dependency names */ + Elf64_Word vda_next; /* Offset in bytes to next verdaux + entry */ +} Elf64_Verdaux; + + +/* Version dependency section. */ + +typedef struct +{ + Elf32_Half vn_version; /* Version of structure */ + Elf32_Half vn_cnt; /* Number of associated aux entries */ + Elf32_Word vn_file; /* Offset of filename for this + dependency */ + Elf32_Word vn_aux; /* Offset in bytes to vernaux array */ + Elf32_Word vn_next; /* Offset in bytes to next verneed + entry */ +} Elf32_Verneed; + +typedef struct +{ + Elf64_Half vn_version; /* Version of structure */ + Elf64_Half vn_cnt; /* Number of associated aux entries */ + Elf64_Word vn_file; /* Offset of filename for this + dependency */ + Elf64_Word vn_aux; /* Offset in bytes to vernaux array */ + Elf64_Word vn_next; /* Offset in bytes to next verneed + entry */ +} Elf64_Verneed; + + +/* Legal values for vn_version (version revision). */ +#define VER_NEED_NONE 0 /* No version */ +#define VER_NEED_CURRENT 1 /* Current version */ +#define VER_NEED_NUM 2 /* Given version number */ + +/* Auxiliary needed version information. */ + +typedef struct +{ + Elf32_Word vna_hash; /* Hash value of dependency name */ + Elf32_Half vna_flags; /* Dependency specific information */ + Elf32_Half vna_other; /* Unused */ + Elf32_Word vna_name; /* Dependency name string offset */ + Elf32_Word vna_next; /* Offset in bytes to next vernaux + entry */ +} Elf32_Vernaux; + +typedef struct +{ + Elf64_Word vna_hash; /* Hash value of dependency name */ + Elf64_Half vna_flags; /* Dependency specific information */ + Elf64_Half vna_other; /* Unused */ + Elf64_Word vna_name; /* Dependency name string offset */ + Elf64_Word vna_next; /* Offset in bytes to next vernaux + entry */ +} Elf64_Vernaux; + + +/* Legal values for vna_flags. */ +#define VER_FLG_WEAK 0x2 /* Weak version identifier */ + + +/* Auxiliary vector. */ + +/* This vector is normally only used by the program interpreter. The + usual definition in an ABI supplement uses the name auxv_t. The + vector is not usually defined in a standard file, but it + can't hurt. We rename it to avoid conflicts. The sizes of these + types are an arrangement between the exec server and the program + interpreter, so we don't fully specify them here. */ + +typedef struct +{ + uint32_t a_type; /* Entry type */ + union + { + uint32_t a_val; /* Integer value */ + /* We use to have pointer elements added here. We cannot do that, + though, since it does not work when using 32-bit definitions + on 64-bit platforms and vice versa. */ + } a_un; +} Elf32_auxv_t; + +typedef struct +{ + uint64_t a_type; /* Entry type */ + union + { + uint64_t a_val; /* Integer value */ + /* We use to have pointer elements added here. We cannot do that, + though, since it does not work when using 32-bit definitions + on 64-bit platforms and vice versa. */ + } a_un; +} Elf64_auxv_t; + +/* Legal values for a_type (entry type). */ + +#define AT_NULL 0 /* End of vector */ +#define AT_IGNORE 1 /* Entry should be ignored */ +#define AT_EXECFD 2 /* File descriptor of program */ +#define AT_PHDR 3 /* Program headers for program */ +#define AT_PHENT 4 /* Size of program header entry */ +#define AT_PHNUM 5 /* Number of program headers */ +#define AT_PAGESZ 6 /* System page size */ +#define AT_BASE 7 /* Base address of interpreter */ +#define AT_FLAGS 8 /* Flags */ +#define AT_ENTRY 9 /* Entry point of program */ +#define AT_NOTELF 10 /* Program is not ELF */ +#define AT_UID 11 /* Real uid */ +#define AT_EUID 12 /* Effective uid */ +#define AT_GID 13 /* Real gid */ +#define AT_EGID 14 /* Effective gid */ +#define AT_CLKTCK 17 /* Frequency of times() */ + +/* Some more special a_type values describing the hardware. */ +#define AT_PLATFORM 15 /* String identifying platform. */ +#define AT_HWCAP 16 /* Machine dependent hints about + processor capabilities. */ + +/* This entry gives some information about the FPU initialization + performed by the kernel. */ +#define AT_FPUCW 18 /* Used FPU control word. */ + +/* Cache block sizes. */ +#define AT_DCACHEBSIZE 19 /* Data cache block size. */ +#define AT_ICACHEBSIZE 20 /* Instruction cache block size. */ +#define AT_UCACHEBSIZE 21 /* Unified cache block size. */ + +/* A special ignored value for PPC, used by the kernel to control the + interpretation of the AUXV. Must be > 16. */ +#define AT_IGNOREPPC 22 /* Entry should be ignored. */ + +#define AT_SECURE 23 /* Boolean, was exec setuid-like? */ + +/* Pointer to the global system page used for system calls and other + nice things. */ +#define AT_SYSINFO 32 +#define AT_SYSINFO_EHDR 33 + +/* Shapes of the caches. Bits 0-3 contains associativity; bits 4-7 contains + log2 of line size; mask those to get cache size. */ +#define AT_L1I_CACHESHAPE 34 +#define AT_L1D_CACHESHAPE 35 +#define AT_L2_CACHESHAPE 36 +#define AT_L3_CACHESHAPE 37 + +/* Note section contents. Each entry in the note section begins with + a header of a fixed form. */ + +typedef struct +{ + Elf32_Word n_namesz; /* Length of the note's name. */ + Elf32_Word n_descsz; /* Length of the note's descriptor. */ + Elf32_Word n_type; /* Type of the note. */ +} Elf32_Nhdr; + +typedef struct +{ + Elf64_Word n_namesz; /* Length of the note's name. */ + Elf64_Word n_descsz; /* Length of the note's descriptor. */ + Elf64_Word n_type; /* Type of the note. */ +} Elf64_Nhdr; + +/* Known names of notes. */ + +/* Solaris entries in the note section have this name. */ +#define ELF_NOTE_SOLARIS "SUNW Solaris" + +/* Note entries for GNU systems have this name. */ +#define ELF_NOTE_GNU "GNU" + + +/* Defined types of notes for Solaris. */ + +/* Value of descriptor (one word) is desired pagesize for the binary. */ +#define ELF_NOTE_PAGESIZE_HINT 1 + + +/* Defined note types for GNU systems. */ + +/* ABI information. The descriptor consists of words: + word 0: OS descriptor + word 1: major version of the ABI + word 2: minor version of the ABI + word 3: subminor version of the ABI +*/ +#define ELF_NOTE_ABI 1 + +/* Known OSes. These value can appear in word 0 of an ELF_NOTE_ABI + note section entry. */ +#define ELF_NOTE_OS_LINUX 0 +#define ELF_NOTE_OS_GNU 1 +#define ELF_NOTE_OS_SOLARIS2 2 +#define ELF_NOTE_OS_FREEBSD 3 + + +/* Move records. */ +typedef struct +{ + Elf32_Xword m_value; /* Symbol value. */ + Elf32_Word m_info; /* Size and index. */ + Elf32_Word m_poffset; /* Symbol offset. */ + Elf32_Half m_repeat; /* Repeat count. */ + Elf32_Half m_stride; /* Stride info. */ +} Elf32_Move; + +typedef struct +{ + Elf64_Xword m_value; /* Symbol value. */ + Elf64_Xword m_info; /* Size and index. */ + Elf64_Xword m_poffset; /* Symbol offset. */ + Elf64_Half m_repeat; /* Repeat count. */ + Elf64_Half m_stride; /* Stride info. */ +} Elf64_Move; + +/* Macro to construct move records. */ +#define ELF32_M_SYM(info) ((info) >> 8) +#define ELF32_M_SIZE(info) ((unsigned char) (info)) +#define ELF32_M_INFO(sym, size) (((sym) << 8) + (unsigned char) (size)) + +#define ELF64_M_SYM(info) ELF32_M_SYM (info) +#define ELF64_M_SIZE(info) ELF32_M_SIZE (info) +#define ELF64_M_INFO(sym, size) ELF32_M_INFO (sym, size) + + +/* Motorola 68k specific definitions. */ + +/* Values for Elf32_Ehdr.e_flags. */ +#define EF_CPU32 0x00810000 + +/* m68k relocs. */ + +#define R_68K_NONE 0 /* No reloc */ +#define R_68K_32 1 /* Direct 32 bit */ +#define R_68K_16 2 /* Direct 16 bit */ +#define R_68K_8 3 /* Direct 8 bit */ +#define R_68K_PC32 4 /* PC relative 32 bit */ +#define R_68K_PC16 5 /* PC relative 16 bit */ +#define R_68K_PC8 6 /* PC relative 8 bit */ +#define R_68K_GOT32 7 /* 32 bit PC relative GOT entry */ +#define R_68K_GOT16 8 /* 16 bit PC relative GOT entry */ +#define R_68K_GOT8 9 /* 8 bit PC relative GOT entry */ +#define R_68K_GOT32O 10 /* 32 bit GOT offset */ +#define R_68K_GOT16O 11 /* 16 bit GOT offset */ +#define R_68K_GOT8O 12 /* 8 bit GOT offset */ +#define R_68K_PLT32 13 /* 32 bit PC relative PLT address */ +#define R_68K_PLT16 14 /* 16 bit PC relative PLT address */ +#define R_68K_PLT8 15 /* 8 bit PC relative PLT address */ +#define R_68K_PLT32O 16 /* 32 bit PLT offset */ +#define R_68K_PLT16O 17 /* 16 bit PLT offset */ +#define R_68K_PLT8O 18 /* 8 bit PLT offset */ +#define R_68K_COPY 19 /* Copy symbol at runtime */ +#define R_68K_GLOB_DAT 20 /* Create GOT entry */ +#define R_68K_JMP_SLOT 21 /* Create PLT entry */ +#define R_68K_RELATIVE 22 /* Adjust by program base */ +/* Keep this the last entry. */ +#define R_68K_NUM 23 + +/* Intel 80386 specific definitions. */ + +/* i386 relocs. */ + +#define R_386_NONE 0 /* No reloc */ +#define R_386_32 1 /* Direct 32 bit */ +#define R_386_PC32 2 /* PC relative 32 bit */ +#define R_386_GOT32 3 /* 32 bit GOT entry */ +#define R_386_PLT32 4 /* 32 bit PLT address */ +#define R_386_COPY 5 /* Copy symbol at runtime */ +#define R_386_GLOB_DAT 6 /* Create GOT entry */ +#define R_386_JMP_SLOT 7 /* Create PLT entry */ +#define R_386_RELATIVE 8 /* Adjust by program base */ +#define R_386_GOTOFF 9 /* 32 bit offset to GOT */ +#define R_386_GOTPC 10 /* 32 bit PC relative offset to GOT */ +#define R_386_32PLT 11 +#define R_386_TLS_TPOFF 14 /* Offset in static TLS block */ +#define R_386_TLS_IE 15 /* Address of GOT entry for static TLS + block offset */ +#define R_386_TLS_GOTIE 16 /* GOT entry for static TLS block + offset */ +#define R_386_TLS_LE 17 /* Offset relative to static TLS + block */ +#define R_386_TLS_GD 18 /* Direct 32 bit for GNU version of + general dynamic thread local data */ +#define R_386_TLS_LDM 19 /* Direct 32 bit for GNU version of + local dynamic thread local data + in LE code */ +#define R_386_16 20 +#define R_386_PC16 21 +#define R_386_8 22 +#define R_386_PC8 23 +#define R_386_TLS_GD_32 24 /* Direct 32 bit for general dynamic + thread local data */ +#define R_386_TLS_GD_PUSH 25 /* Tag for pushl in GD TLS code */ +#define R_386_TLS_GD_CALL 26 /* Relocation for call to + __tls_get_addr() */ +#define R_386_TLS_GD_POP 27 /* Tag for popl in GD TLS code */ +#define R_386_TLS_LDM_32 28 /* Direct 32 bit for local dynamic + thread local data in LE code */ +#define R_386_TLS_LDM_PUSH 29 /* Tag for pushl in LDM TLS code */ +#define R_386_TLS_LDM_CALL 30 /* Relocation for call to + __tls_get_addr() in LDM code */ +#define R_386_TLS_LDM_POP 31 /* Tag for popl in LDM TLS code */ +#define R_386_TLS_LDO_32 32 /* Offset relative to TLS block */ +#define R_386_TLS_IE_32 33 /* GOT entry for negated static TLS + block offset */ +#define R_386_TLS_LE_32 34 /* Negated offset relative to static + TLS block */ +#define R_386_TLS_DTPMOD32 35 /* ID of module containing symbol */ +#define R_386_TLS_DTPOFF32 36 /* Offset in TLS block */ +#define R_386_TLS_TPOFF32 37 /* Negated offset in static TLS block */ +/* Keep this the last entry. */ +#define R_386_NUM 38 + +/* Blackfin specific definitions. */ +#define R_BFIN_UNUSED0 0x00 +#define R_BFIN_PCREL5M2 0x01 +#define R_BFIN_UNUSED1 0x02 +#define R_BFIN_PCREL10 0x03 +#define R_BFIN_PCREL12_JUMP 0x04 +#define R_BFIN_RIMM16 0x05 +#define R_BFIN_LUIMM16 0x06 +#define R_BFIN_HUIMM16 0x07 +#define R_BFIN_PCREL12_JUMP_S 0x08 +#define R_BFIN_PCREL24_JUMP_X 0x09 +#define R_BFIN_PCREL24 0x0a +#define R_BFIN_UNUSEDB 0x0b +#define R_BFIN_UNUSEDC 0x0c +#define R_BFIN_PCREL24_JUMP_L 0x0d +#define R_BFIN_PCREL24_CALL_X 0x0e +#define R_BFIN_var_eq_symb 0x0f +#define R_BFIN_BYTE_DATA 0x10 +#define R_BFIN_BYTE2_DATA 0x11 +#define R_BFIN_BYTE4_DATA 0x12 +#define R_BFIN_PCREL11 0x13 + +#define R_BFIN_GOT17M4 0x14 +#define R_BFIN_GOTHI 0x15 +#define R_BFIN_GOTLO 0x16 +#define R_BFIN_FUNCDESC 0x17 +#define R_BFIN_FUNCDESC_GOT17M4 0x18 +#define R_BFIN_FUNCDESC_GOTHI 0x19 +#define R_BFIN_FUNCDESC_GOTLO 0x1a +#define R_BFIN_FUNCDESC_VALUE 0x1b +#define R_BFIN_FUNCDESC_GOTOFF17M4 0x1c +#define R_BFIN_FUNCDESC_GOTOFFHI 0x1d +#define R_BFIN_FUNCDESC_GOTOFFLO 0x1e +#define R_BFIN_GOTOFF17M4 0x1f +#define R_BFIN_GOTOFFHI 0x20 +#define R_BFIN_GOTOFFLO 0x21 + +#define EF_BFIN_PIC 0x00000001 /* -fpic */ +#define EF_BFIN_FDPIC 0x00000002 /* -mfdpic */ +#define EF_BFIN_CODE_IN_L1 0x00000010 /* --code-in-l1 */ +#define EF_BFIN_DATA_IN_L1 0x00000020 /* --data-in-l1 */ + +/* FR-V specific definitions. */ +#define R_FRV_NONE 0 /* No reloc. */ +#define R_FRV_32 1 /* Direct 32 bit. */ +/* Canonical function descriptor address. */ +#define R_FRV_FUNCDESC 14 +/* Private function descriptor initialization. */ +#define R_FRV_FUNCDESC_VALUE 18 + + /* gpr support */ +#define EF_FRV_GPR_MASK 0x00000003 /* mask for # of gprs */ +#define EF_FRV_GPR_32 0x00000001 /* -mgpr-32 */ +#define EF_FRV_GPR_64 0x00000002 /* -mgpr-64 */ + + /* fpr support */ +#define EF_FRV_FPR_MASK 0x0000000c /* mask for # of fprs */ +#define EF_FRV_FPR_32 0x00000004 /* -mfpr-32 */ +#define EF_FRV_FPR_64 0x00000008 /* -mfpr-64 */ +#define EF_FRV_FPR_NONE 0x0000000c /* -msoft-float */ + +#define EF_FRV_PIC 0x00000100 +#define EF_FRV_FDPIC 0x00008000 + +/* SUN SPARC specific definitions. */ + +/* Legal values for ST_TYPE subfield of st_info (symbol type). */ + +#define STT_SPARC_REGISTER 13 /* Global register reserved to app. */ + +/* Values for Elf64_Ehdr.e_flags. */ + +#define EF_SPARCV9_MM 3 +#define EF_SPARCV9_TSO 0 +#define EF_SPARCV9_PSO 1 +#define EF_SPARCV9_RMO 2 +#define EF_SPARC_LEDATA 0x800000 /* little endian data */ +#define EF_SPARC_EXT_MASK 0xFFFF00 +#define EF_SPARC_32PLUS 0x000100 /* generic V8+ features */ +#define EF_SPARC_SUN_US1 0x000200 /* Sun UltraSPARC1 extensions */ +#define EF_SPARC_HAL_R1 0x000400 /* HAL R1 extensions */ +#define EF_SPARC_SUN_US3 0x000800 /* Sun UltraSPARCIII extensions */ + +/* SPARC relocs. */ + +#define R_SPARC_NONE 0 /* No reloc */ +#define R_SPARC_8 1 /* Direct 8 bit */ +#define R_SPARC_16 2 /* Direct 16 bit */ +#define R_SPARC_32 3 /* Direct 32 bit */ +#define R_SPARC_DISP8 4 /* PC relative 8 bit */ +#define R_SPARC_DISP16 5 /* PC relative 16 bit */ +#define R_SPARC_DISP32 6 /* PC relative 32 bit */ +#define R_SPARC_WDISP30 7 /* PC relative 30 bit shifted */ +#define R_SPARC_WDISP22 8 /* PC relative 22 bit shifted */ +#define R_SPARC_HI22 9 /* High 22 bit */ +#define R_SPARC_22 10 /* Direct 22 bit */ +#define R_SPARC_13 11 /* Direct 13 bit */ +#define R_SPARC_LO10 12 /* Truncated 10 bit */ +#define R_SPARC_GOT10 13 /* Truncated 10 bit GOT entry */ +#define R_SPARC_GOT13 14 /* 13 bit GOT entry */ +#define R_SPARC_GOT22 15 /* 22 bit GOT entry shifted */ +#define R_SPARC_PC10 16 /* PC relative 10 bit truncated */ +#define R_SPARC_PC22 17 /* PC relative 22 bit shifted */ +#define R_SPARC_WPLT30 18 /* 30 bit PC relative PLT address */ +#define R_SPARC_COPY 19 /* Copy symbol at runtime */ +#define R_SPARC_GLOB_DAT 20 /* Create GOT entry */ +#define R_SPARC_JMP_SLOT 21 /* Create PLT entry */ +#define R_SPARC_RELATIVE 22 /* Adjust by program base */ +#define R_SPARC_UA32 23 /* Direct 32 bit unaligned */ + +/* Additional Sparc64 relocs. */ + +#define R_SPARC_PLT32 24 /* Direct 32 bit ref to PLT entry */ +#define R_SPARC_HIPLT22 25 /* High 22 bit PLT entry */ +#define R_SPARC_LOPLT10 26 /* Truncated 10 bit PLT entry */ +#define R_SPARC_PCPLT32 27 /* PC rel 32 bit ref to PLT entry */ +#define R_SPARC_PCPLT22 28 /* PC rel high 22 bit PLT entry */ +#define R_SPARC_PCPLT10 29 /* PC rel trunc 10 bit PLT entry */ +#define R_SPARC_10 30 /* Direct 10 bit */ +#define R_SPARC_11 31 /* Direct 11 bit */ +#define R_SPARC_64 32 /* Direct 64 bit */ +#define R_SPARC_OLO10 33 /* 10bit with secondary 13bit addend */ +#define R_SPARC_HH22 34 /* Top 22 bits of direct 64 bit */ +#define R_SPARC_HM10 35 /* High middle 10 bits of ... */ +#define R_SPARC_LM22 36 /* Low middle 22 bits of ... */ +#define R_SPARC_PC_HH22 37 /* Top 22 bits of pc rel 64 bit */ +#define R_SPARC_PC_HM10 38 /* High middle 10 bit of ... */ +#define R_SPARC_PC_LM22 39 /* Low miggle 22 bits of ... */ +#define R_SPARC_WDISP16 40 /* PC relative 16 bit shifted */ +#define R_SPARC_WDISP19 41 /* PC relative 19 bit shifted */ +#define R_SPARC_7 43 /* Direct 7 bit */ +#define R_SPARC_5 44 /* Direct 5 bit */ +#define R_SPARC_6 45 /* Direct 6 bit */ +#define R_SPARC_DISP64 46 /* PC relative 64 bit */ +#define R_SPARC_PLT64 47 /* Direct 64 bit ref to PLT entry */ +#define R_SPARC_HIX22 48 /* High 22 bit complemented */ +#define R_SPARC_LOX10 49 /* Truncated 11 bit complemented */ +#define R_SPARC_H44 50 /* Direct high 12 of 44 bit */ +#define R_SPARC_M44 51 /* Direct mid 22 of 44 bit */ +#define R_SPARC_L44 52 /* Direct low 10 of 44 bit */ +#define R_SPARC_REGISTER 53 /* Global register usage */ +#define R_SPARC_UA64 54 /* Direct 64 bit unaligned */ +#define R_SPARC_UA16 55 /* Direct 16 bit unaligned */ +#define R_SPARC_TLS_GD_HI22 56 +#define R_SPARC_TLS_GD_LO10 57 +#define R_SPARC_TLS_GD_ADD 58 +#define R_SPARC_TLS_GD_CALL 59 +#define R_SPARC_TLS_LDM_HI22 60 +#define R_SPARC_TLS_LDM_LO10 61 +#define R_SPARC_TLS_LDM_ADD 62 +#define R_SPARC_TLS_LDM_CALL 63 +#define R_SPARC_TLS_LDO_HIX22 64 +#define R_SPARC_TLS_LDO_LOX10 65 +#define R_SPARC_TLS_LDO_ADD 66 +#define R_SPARC_TLS_IE_HI22 67 +#define R_SPARC_TLS_IE_LO10 68 +#define R_SPARC_TLS_IE_LD 69 +#define R_SPARC_TLS_IE_LDX 70 +#define R_SPARC_TLS_IE_ADD 71 +#define R_SPARC_TLS_LE_HIX22 72 +#define R_SPARC_TLS_LE_LOX10 73 +#define R_SPARC_TLS_DTPMOD32 74 +#define R_SPARC_TLS_DTPMOD64 75 +#define R_SPARC_TLS_DTPOFF32 76 +#define R_SPARC_TLS_DTPOFF64 77 +#define R_SPARC_TLS_TPOFF32 78 +#define R_SPARC_TLS_TPOFF64 79 +/* Keep this the last entry. */ +#define R_SPARC_NUM 80 + +/* For Sparc64, legal values for d_tag of Elf64_Dyn. */ + +#define DT_SPARC_REGISTER 0x70000001 +#define DT_SPARC_NUM 2 + +/* Bits present in AT_HWCAP, primarily for Sparc32. */ + +#define HWCAP_SPARC_FLUSH 1 /* The cpu supports flush insn. */ +#define HWCAP_SPARC_STBAR 2 +#define HWCAP_SPARC_SWAP 4 +#define HWCAP_SPARC_MULDIV 8 +#define HWCAP_SPARC_V9 16 /* The cpu is v9, so v8plus is ok. */ +#define HWCAP_SPARC_ULTRA3 32 + +/* MIPS R3000 specific definitions. */ + +/* Legal values for e_flags field of Elf32_Ehdr. */ + +#define EF_MIPS_NOREORDER 1 /* A .noreorder directive was used */ +#define EF_MIPS_PIC 2 /* Contains PIC code */ +#define EF_MIPS_CPIC 4 /* Uses PIC calling sequence */ +#define EF_MIPS_XGOT 8 +#define EF_MIPS_64BIT_WHIRL 16 +#define EF_MIPS_ABI2 32 +#define EF_MIPS_ABI_ON32 64 +#define EF_MIPS_ARCH 0xf0000000 /* MIPS architecture level */ + +/* Legal values for MIPS architecture level. */ + +#define EF_MIPS_ARCH_1 0x00000000 /* -mips1 code. */ +#define EF_MIPS_ARCH_2 0x10000000 /* -mips2 code. */ +#define EF_MIPS_ARCH_3 0x20000000 /* -mips3 code. */ +#define EF_MIPS_ARCH_4 0x30000000 /* -mips4 code. */ +#define EF_MIPS_ARCH_5 0x40000000 /* -mips5 code. */ +#define EF_MIPS_ARCH_32 0x60000000 /* MIPS32 code. */ +#define EF_MIPS_ARCH_64 0x70000000 /* MIPS64 code. */ + +/* The following are non-official names and should not be used. */ + +#define E_MIPS_ARCH_1 0x00000000 /* -mips1 code. */ +#define E_MIPS_ARCH_2 0x10000000 /* -mips2 code. */ +#define E_MIPS_ARCH_3 0x20000000 /* -mips3 code. */ +#define E_MIPS_ARCH_4 0x30000000 /* -mips4 code. */ +#define E_MIPS_ARCH_5 0x40000000 /* -mips5 code. */ +#define E_MIPS_ARCH_32 0x60000000 /* MIPS32 code. */ +#define E_MIPS_ARCH_64 0x70000000 /* MIPS64 code. */ + +/* Special section indices. */ + +#define SHN_MIPS_ACOMMON 0xff00 /* Allocated common symbols */ +#define SHN_MIPS_TEXT 0xff01 /* Allocated test symbols. */ +#define SHN_MIPS_DATA 0xff02 /* Allocated data symbols. */ +#define SHN_MIPS_SCOMMON 0xff03 /* Small common symbols */ +#define SHN_MIPS_SUNDEFINED 0xff04 /* Small undefined symbols */ + +/* Legal values for sh_type field of Elf32_Shdr. */ + +#define SHT_MIPS_LIBLIST 0x70000000 /* Shared objects used in link */ +#define SHT_MIPS_MSYM 0x70000001 +#define SHT_MIPS_CONFLICT 0x70000002 /* Conflicting symbols */ +#define SHT_MIPS_GPTAB 0x70000003 /* Global data area sizes */ +#define SHT_MIPS_UCODE 0x70000004 /* Reserved for SGI/MIPS compilers */ +#define SHT_MIPS_DEBUG 0x70000005 /* MIPS ECOFF debugging information*/ +#define SHT_MIPS_REGINFO 0x70000006 /* Register usage information */ +#define SHT_MIPS_PACKAGE 0x70000007 +#define SHT_MIPS_PACKSYM 0x70000008 +#define SHT_MIPS_RELD 0x70000009 +#define SHT_MIPS_IFACE 0x7000000b +#define SHT_MIPS_CONTENT 0x7000000c +#define SHT_MIPS_OPTIONS 0x7000000d /* Miscellaneous options. */ +#define SHT_MIPS_SHDR 0x70000010 +#define SHT_MIPS_FDESC 0x70000011 +#define SHT_MIPS_EXTSYM 0x70000012 +#define SHT_MIPS_DENSE 0x70000013 +#define SHT_MIPS_PDESC 0x70000014 +#define SHT_MIPS_LOCSYM 0x70000015 +#define SHT_MIPS_AUXSYM 0x70000016 +#define SHT_MIPS_OPTSYM 0x70000017 +#define SHT_MIPS_LOCSTR 0x70000018 +#define SHT_MIPS_LINE 0x70000019 +#define SHT_MIPS_RFDESC 0x7000001a +#define SHT_MIPS_DELTASYM 0x7000001b +#define SHT_MIPS_DELTAINST 0x7000001c +#define SHT_MIPS_DELTACLASS 0x7000001d +#define SHT_MIPS_DWARF 0x7000001e /* DWARF debugging information. */ +#define SHT_MIPS_DELTADECL 0x7000001f +#define SHT_MIPS_SYMBOL_LIB 0x70000020 +#define SHT_MIPS_EVENTS 0x70000021 /* Event section. */ +#define SHT_MIPS_TRANSLATE 0x70000022 +#define SHT_MIPS_PIXIE 0x70000023 +#define SHT_MIPS_XLATE 0x70000024 +#define SHT_MIPS_XLATE_DEBUG 0x70000025 +#define SHT_MIPS_WHIRL 0x70000026 +#define SHT_MIPS_EH_REGION 0x70000027 +#define SHT_MIPS_XLATE_OLD 0x70000028 +#define SHT_MIPS_PDR_EXCEPTION 0x70000029 + +/* Legal values for sh_flags field of Elf32_Shdr. */ + +#define SHF_MIPS_GPREL 0x10000000 /* Must be part of global data area */ +#define SHF_MIPS_MERGE 0x20000000 +#define SHF_MIPS_ADDR 0x40000000 +#define SHF_MIPS_STRINGS 0x80000000 +#define SHF_MIPS_NOSTRIP 0x08000000 +#define SHF_MIPS_LOCAL 0x04000000 +#define SHF_MIPS_NAMES 0x02000000 +#define SHF_MIPS_NODUPE 0x01000000 + + +/* Symbol tables. */ + +/* MIPS specific values for `st_other'. */ +#define STO_MIPS_DEFAULT 0x0 +#define STO_MIPS_INTERNAL 0x1 +#define STO_MIPS_HIDDEN 0x2 +#define STO_MIPS_PROTECTED 0x3 +#define STO_MIPS_PLT 0x8 +#define STO_MIPS_SC_ALIGN_UNUSED 0xff + +/* MIPS specific values for `st_info'. */ +#define STB_MIPS_SPLIT_COMMON 13 + +/* Entries found in sections of type SHT_MIPS_GPTAB. */ + +typedef union +{ + struct + { + Elf32_Word gt_current_g_value; /* -G value used for compilation */ + Elf32_Word gt_unused; /* Not used */ + } gt_header; /* First entry in section */ + struct + { + Elf32_Word gt_g_value; /* If this value were used for -G */ + Elf32_Word gt_bytes; /* This many bytes would be used */ + } gt_entry; /* Subsequent entries in section */ +} Elf32_gptab; + +/* Entry found in sections of type SHT_MIPS_REGINFO. */ + +typedef struct +{ + Elf32_Word ri_gprmask; /* General registers used */ + Elf32_Word ri_cprmask[4]; /* Coprocessor registers used */ + Elf32_Sword ri_gp_value; /* $gp register value */ +} Elf32_RegInfo; + +/* Entries found in sections of type SHT_MIPS_OPTIONS. */ + +typedef struct +{ + unsigned char kind; /* Determines interpretation of the + variable part of descriptor. */ + unsigned char size; /* Size of descriptor, including header. */ + Elf32_Section section; /* Section header index of section affected, + 0 for global options. */ + Elf32_Word info; /* Kind-specific information. */ +} Elf_Options; + +/* Values for `kind' field in Elf_Options. */ + +#define ODK_NULL 0 /* Undefined. */ +#define ODK_REGINFO 1 /* Register usage information. */ +#define ODK_EXCEPTIONS 2 /* Exception processing options. */ +#define ODK_PAD 3 /* Section padding options. */ +#define ODK_HWPATCH 4 /* Hardware workarounds performed */ +#define ODK_FILL 5 /* record the fill value used by the linker. */ +#define ODK_TAGS 6 /* reserve space for desktop tools to write. */ +#define ODK_HWAND 7 /* HW workarounds. 'AND' bits when merging. */ +#define ODK_HWOR 8 /* HW workarounds. 'OR' bits when merging. */ + +/* Values for `info' in Elf_Options for ODK_EXCEPTIONS entries. */ + +#define OEX_FPU_MIN 0x1f /* FPE's which MUST be enabled. */ +#define OEX_FPU_MAX 0x1f00 /* FPE's which MAY be enabled. */ +#define OEX_PAGE0 0x10000 /* page zero must be mapped. */ +#define OEX_SMM 0x20000 /* Force sequential memory mode? */ +#define OEX_FPDBUG 0x40000 /* Force floating point debug mode? */ +#define OEX_PRECISEFP OEX_FPDBUG +#define OEX_DISMISS 0x80000 /* Dismiss invalid address faults? */ + +#define OEX_FPU_INVAL 0x10 +#define OEX_FPU_DIV0 0x08 +#define OEX_FPU_OFLO 0x04 +#define OEX_FPU_UFLO 0x02 +#define OEX_FPU_INEX 0x01 + +/* Masks for `info' in Elf_Options for an ODK_HWPATCH entry. */ + +#define OHW_R4KEOP 0x1 /* R4000 end-of-page patch. */ +#define OHW_R8KPFETCH 0x2 /* may need R8000 prefetch patch. */ +#define OHW_R5KEOP 0x4 /* R5000 end-of-page patch. */ +#define OHW_R5KCVTL 0x8 /* R5000 cvt.[ds].l bug. clean=1. */ + +#define OPAD_PREFIX 0x1 +#define OPAD_POSTFIX 0x2 +#define OPAD_SYMBOL 0x4 + +/* Entry found in `.options' section. */ + +typedef struct +{ + Elf32_Word hwp_flags1; /* Extra flags. */ + Elf32_Word hwp_flags2; /* Extra flags. */ +} Elf_Options_Hw; + +/* Masks for `info' in ElfOptions for ODK_HWAND and ODK_HWOR entries. */ + +#define OHWA0_R4KEOP_CHECKED 0x00000001 +#define OHWA1_R4KEOP_CLEAN 0x00000002 + +/* MIPS relocs. */ + +#define R_MIPS_NONE 0 /* No reloc */ +#define R_MIPS_16 1 /* Direct 16 bit */ +#define R_MIPS_32 2 /* Direct 32 bit */ +#define R_MIPS_REL32 3 /* PC relative 32 bit */ +#define R_MIPS_26 4 /* Direct 26 bit shifted */ +#define R_MIPS_HI16 5 /* High 16 bit */ +#define R_MIPS_LO16 6 /* Low 16 bit */ +#define R_MIPS_GPREL16 7 /* GP relative 16 bit */ +#define R_MIPS_LITERAL 8 /* 16 bit literal entry */ +#define R_MIPS_GOT16 9 /* 16 bit GOT entry */ +#define R_MIPS_PC16 10 /* PC relative 16 bit */ +#define R_MIPS_CALL16 11 /* 16 bit GOT entry for function */ +#define R_MIPS_GPREL32 12 /* GP relative 32 bit */ + +#define R_MIPS_SHIFT5 16 +#define R_MIPS_SHIFT6 17 +#define R_MIPS_64 18 +#define R_MIPS_GOT_DISP 19 +#define R_MIPS_GOT_PAGE 20 +#define R_MIPS_GOT_OFST 21 +#define R_MIPS_GOT_HI16 22 +#define R_MIPS_GOT_LO16 23 +#define R_MIPS_SUB 24 +#define R_MIPS_INSERT_A 25 +#define R_MIPS_INSERT_B 26 +#define R_MIPS_DELETE 27 +#define R_MIPS_HIGHER 28 +#define R_MIPS_HIGHEST 29 +#define R_MIPS_CALL_HI16 30 +#define R_MIPS_CALL_LO16 31 +#define R_MIPS_SCN_DISP 32 +#define R_MIPS_REL16 33 +#define R_MIPS_ADD_IMMEDIATE 34 +#define R_MIPS_PJUMP 35 +#define R_MIPS_RELGOT 36 +#define R_MIPS_JALR 37 +#define R_MIPS_TLS_DTPMOD32 38 /* Module number 32 bit */ +#define R_MIPS_TLS_DTPREL32 39 /* Module-relative offset 32 bit */ +#define R_MIPS_TLS_DTPMOD64 40 /* Module number 64 bit */ +#define R_MIPS_TLS_DTPREL64 41 /* Module-relative offset 64 bit */ +#define R_MIPS_TLS_GD 42 /* 16 bit GOT offset for GD */ +#define R_MIPS_TLS_LDM 43 /* 16 bit GOT offset for LDM */ +#define R_MIPS_TLS_DTPREL_HI16 44 /* Module-relative offset, high 16 bits */ +#define R_MIPS_TLS_DTPREL_LO16 45 /* Module-relative offset, low 16 bits */ +#define R_MIPS_TLS_GOTTPREL 46 /* 16 bit GOT offset for IE */ +#define R_MIPS_TLS_TPREL32 47 /* TP-relative offset, 32 bit */ +#define R_MIPS_TLS_TPREL64 48 /* TP-relative offset, 64 bit */ +#define R_MIPS_TLS_TPREL_HI16 49 /* TP-relative offset, high 16 bits */ +#define R_MIPS_TLS_TPREL_LO16 50 /* TP-relative offset, low 16 bits */ +#define R_MIPS_GLOB_DAT 51 +#define R_MIPS_COPY 126 +#define R_MIPS_JUMP_SLOT 127 +/* Keep this the last entry. */ +#define R_MIPS_NUM 128 + +/* Legal values for p_type field of Elf32_Phdr. */ + +#define PT_MIPS_REGINFO 0x70000000 /* Register usage information */ +#define PT_MIPS_RTPROC 0x70000001 /* Runtime procedure table. */ +#define PT_MIPS_OPTIONS 0x70000002 + +/* Special program header types. */ + +#define PF_MIPS_LOCAL 0x10000000 + +/* Legal values for d_tag field of Elf32_Dyn. */ + +#define DT_MIPS_RLD_VERSION 0x70000001 /* Runtime linker interface version */ +#define DT_MIPS_TIME_STAMP 0x70000002 /* Timestamp */ +#define DT_MIPS_ICHECKSUM 0x70000003 /* Checksum */ +#define DT_MIPS_IVERSION 0x70000004 /* Version string (string tbl index) */ +#define DT_MIPS_FLAGS 0x70000005 /* Flags */ +#define DT_MIPS_BASE_ADDRESS 0x70000006 /* Base address */ +#define DT_MIPS_MSYM 0x70000007 +#define DT_MIPS_CONFLICT 0x70000008 /* Address of CONFLICT section */ +#define DT_MIPS_LIBLIST 0x70000009 /* Address of LIBLIST section */ +#define DT_MIPS_LOCAL_GOTNO 0x7000000a /* Number of local GOT entries */ +#define DT_MIPS_CONFLICTNO 0x7000000b /* Number of CONFLICT entries */ +#define DT_MIPS_LIBLISTNO 0x70000010 /* Number of LIBLIST entries */ +#define DT_MIPS_SYMTABNO 0x70000011 /* Number of DYNSYM entries */ +#define DT_MIPS_UNREFEXTNO 0x70000012 /* First external DYNSYM */ +#define DT_MIPS_GOTSYM 0x70000013 /* First GOT entry in DYNSYM */ +#define DT_MIPS_HIPAGENO 0x70000014 /* Number of GOT page table entries */ +#define DT_MIPS_RLD_MAP 0x70000016 /* Address of run time loader map. */ +#define DT_MIPS_DELTA_CLASS 0x70000017 /* Delta C++ class definition. */ +#define DT_MIPS_DELTA_CLASS_NO 0x70000018 /* Number of entries in + DT_MIPS_DELTA_CLASS. */ +#define DT_MIPS_DELTA_INSTANCE 0x70000019 /* Delta C++ class instances. */ +#define DT_MIPS_DELTA_INSTANCE_NO 0x7000001a /* Number of entries in + DT_MIPS_DELTA_INSTANCE. */ +#define DT_MIPS_DELTA_RELOC 0x7000001b /* Delta relocations. */ +#define DT_MIPS_DELTA_RELOC_NO 0x7000001c /* Number of entries in + DT_MIPS_DELTA_RELOC. */ +#define DT_MIPS_DELTA_SYM 0x7000001d /* Delta symbols that Delta + relocations refer to. */ +#define DT_MIPS_DELTA_SYM_NO 0x7000001e /* Number of entries in + DT_MIPS_DELTA_SYM. */ +#define DT_MIPS_DELTA_CLASSSYM 0x70000020 /* Delta symbols that hold the + class declaration. */ +#define DT_MIPS_DELTA_CLASSSYM_NO 0x70000021 /* Number of entries in + DT_MIPS_DELTA_CLASSSYM. */ +#define DT_MIPS_CXX_FLAGS 0x70000022 /* Flags indicating for C++ flavor. */ +#define DT_MIPS_PIXIE_INIT 0x70000023 +#define DT_MIPS_SYMBOL_LIB 0x70000024 +#define DT_MIPS_LOCALPAGE_GOTIDX 0x70000025 +#define DT_MIPS_LOCAL_GOTIDX 0x70000026 +#define DT_MIPS_HIDDEN_GOTIDX 0x70000027 +#define DT_MIPS_PROTECTED_GOTIDX 0x70000028 +#define DT_MIPS_OPTIONS 0x70000029 /* Address of .options. */ +#define DT_MIPS_INTERFACE 0x7000002a /* Address of .interface. */ +#define DT_MIPS_DYNSTR_ALIGN 0x7000002b +#define DT_MIPS_INTERFACE_SIZE 0x7000002c /* Size of the .interface section. */ +#define DT_MIPS_RLD_TEXT_RESOLVE_ADDR 0x7000002d /* Address of rld_text_rsolve + function stored in GOT. */ +#define DT_MIPS_PERF_SUFFIX 0x7000002e /* Default suffix of dso to be added + by rld on dlopen() calls. */ +#define DT_MIPS_COMPACT_SIZE 0x7000002f /* (O32)Size of compact rel section. */ +#define DT_MIPS_GP_VALUE 0x70000030 /* GP value for aux GOTs. */ +#define DT_MIPS_AUX_DYNAMIC 0x70000031 /* Address of aux .dynamic. */ +/* The address of .got.plt in an executable using the new non-PIC ABI. */ +#define DT_MIPS_PLTGOT 0x70000032 +/* The base of the PLT in an executable using the new non-PIC ABI if that + PLT is writable. For a non-writable PLT, this is omitted or has a zero + value. */ +#define DT_MIPS_RWPLT 0x70000034 +#define DT_MIPS_NUM 0x35 + +/* Legal values for DT_MIPS_FLAGS Elf32_Dyn entry. */ + +#define RHF_NONE 0 /* No flags */ +#define RHF_QUICKSTART (1 << 0) /* Use quickstart */ +#define RHF_NOTPOT (1 << 1) /* Hash size not power of 2 */ +#define RHF_NO_LIBRARY_REPLACEMENT (1 << 2) /* Ignore LD_LIBRARY_PATH */ +#define RHF_NO_MOVE (1 << 3) +#define RHF_SGI_ONLY (1 << 4) +#define RHF_GUARANTEE_INIT (1 << 5) +#define RHF_DELTA_C_PLUS_PLUS (1 << 6) +#define RHF_GUARANTEE_START_INIT (1 << 7) +#define RHF_PIXIE (1 << 8) +#define RHF_DEFAULT_DELAY_LOAD (1 << 9) +#define RHF_REQUICKSTART (1 << 10) +#define RHF_REQUICKSTARTED (1 << 11) +#define RHF_CORD (1 << 12) +#define RHF_NO_UNRES_UNDEF (1 << 13) +#define RHF_RLD_ORDER_SAFE (1 << 14) + +/* Entries found in sections of type SHT_MIPS_LIBLIST. */ + +typedef struct +{ + Elf32_Word l_name; /* Name (string table index) */ + Elf32_Word l_time_stamp; /* Timestamp */ + Elf32_Word l_checksum; /* Checksum */ + Elf32_Word l_version; /* Interface version */ + Elf32_Word l_flags; /* Flags */ +} Elf32_Lib; + +typedef struct +{ + Elf64_Word l_name; /* Name (string table index) */ + Elf64_Word l_time_stamp; /* Timestamp */ + Elf64_Word l_checksum; /* Checksum */ + Elf64_Word l_version; /* Interface version */ + Elf64_Word l_flags; /* Flags */ +} Elf64_Lib; + + +/* Legal values for l_flags. */ + +#define LL_NONE 0 +#define LL_EXACT_MATCH (1 << 0) /* Require exact match */ +#define LL_IGNORE_INT_VER (1 << 1) /* Ignore interface version */ +#define LL_REQUIRE_MINOR (1 << 2) +#define LL_EXPORTS (1 << 3) +#define LL_DELAY_LOAD (1 << 4) +#define LL_DELTA (1 << 5) + +/* Entries found in sections of type SHT_MIPS_CONFLICT. */ + +typedef Elf32_Addr Elf32_Conflict; + + +/* HPPA specific definitions. */ + +/* Legal values for e_flags field of Elf32_Ehdr. */ + +#define EF_PARISC_TRAPNIL 0x00010000 /* Trap nil pointer dereference. */ +#define EF_PARISC_EXT 0x00020000 /* Program uses arch. extensions. */ +#define EF_PARISC_LSB 0x00040000 /* Program expects little endian. */ +#define EF_PARISC_WIDE 0x00080000 /* Program expects wide mode. */ +#define EF_PARISC_NO_KABP 0x00100000 /* No kernel assisted branch + prediction. */ +#define EF_PARISC_LAZYSWAP 0x00400000 /* Allow lazy swapping. */ +#define EF_PARISC_ARCH 0x0000ffff /* Architecture version. */ + +/* Defined values for `e_flags & EF_PARISC_ARCH' are: */ + +#define EFA_PARISC_1_0 0x020b /* PA-RISC 1.0 big-endian. */ +#define EFA_PARISC_1_1 0x0210 /* PA-RISC 1.1 big-endian. */ +#define EFA_PARISC_2_0 0x0214 /* PA-RISC 2.0 big-endian. */ + +/* Additional section indeces. */ + +#define SHN_PARISC_ANSI_COMMON 0xff00 /* Section for tenatively declared + symbols in ANSI C. */ +#define SHN_PARISC_HUGE_COMMON 0xff01 /* Common blocks in huge model. */ + +/* Legal values for sh_type field of Elf32_Shdr. */ + +#define SHT_PARISC_EXT 0x70000000 /* Contains product specific ext. */ +#define SHT_PARISC_UNWIND 0x70000001 /* Unwind information. */ +#define SHT_PARISC_DOC 0x70000002 /* Debug info for optimized code. */ + +/* Legal values for sh_flags field of Elf32_Shdr. */ + +#define SHF_PARISC_SHORT 0x20000000 /* Section with short addressing. */ +#define SHF_PARISC_HUGE 0x40000000 /* Section far from gp. */ +#define SHF_PARISC_SBP 0x80000000 /* Static branch prediction code. */ + +/* Legal values for ST_TYPE subfield of st_info (symbol type). */ + +#define STT_PARISC_MILLICODE 13 /* Millicode function entry point. */ + +#define STT_HP_OPAQUE (STT_LOOS + 0x1) +#define STT_HP_STUB (STT_LOOS + 0x2) + +/* HPPA relocs. */ + +#define R_PARISC_NONE 0 /* No reloc. */ +#define R_PARISC_DIR32 1 /* Direct 32-bit reference. */ +#define R_PARISC_DIR21L 2 /* Left 21 bits of eff. address. */ +#define R_PARISC_DIR17R 3 /* Right 17 bits of eff. address. */ +#define R_PARISC_DIR17F 4 /* 17 bits of eff. address. */ +#define R_PARISC_DIR14R 6 /* Right 14 bits of eff. address. */ +#define R_PARISC_PCREL32 9 /* 32-bit rel. address. */ +#define R_PARISC_PCREL21L 10 /* Left 21 bits of rel. address. */ +#define R_PARISC_PCREL17R 11 /* Right 17 bits of rel. address. */ +#define R_PARISC_PCREL17F 12 /* 17 bits of rel. address. */ +#define R_PARISC_PCREL14R 14 /* Right 14 bits of rel. address. */ +#define R_PARISC_DPREL21L 18 /* Left 21 bits of rel. address. */ +#define R_PARISC_DPREL14R 22 /* Right 14 bits of rel. address. */ +#define R_PARISC_GPREL21L 26 /* GP-relative, left 21 bits. */ +#define R_PARISC_GPREL14R 30 /* GP-relative, right 14 bits. */ +#define R_PARISC_LTOFF21L 34 /* LT-relative, left 21 bits. */ +#define R_PARISC_LTOFF14R 38 /* LT-relative, right 14 bits. */ +#define R_PARISC_SECREL32 41 /* 32 bits section rel. address. */ +#define R_PARISC_SEGBASE 48 /* No relocation, set segment base. */ +#define R_PARISC_SEGREL32 49 /* 32 bits segment rel. address. */ +#define R_PARISC_PLTOFF21L 50 /* PLT rel. address, left 21 bits. */ +#define R_PARISC_PLTOFF14R 54 /* PLT rel. address, right 14 bits. */ +#define R_PARISC_LTOFF_FPTR32 57 /* 32 bits LT-rel. function pointer. */ +#define R_PARISC_LTOFF_FPTR21L 58 /* LT-rel. fct ptr, left 21 bits. */ +#define R_PARISC_LTOFF_FPTR14R 62 /* LT-rel. fct ptr, right 14 bits. */ +#define R_PARISC_FPTR64 64 /* 64 bits function address. */ +#define R_PARISC_PLABEL32 65 /* 32 bits function address. */ +#define R_PARISC_PCREL64 72 /* 64 bits PC-rel. address. */ +#define R_PARISC_PCREL22F 74 /* 22 bits PC-rel. address. */ +#define R_PARISC_PCREL14WR 75 /* PC-rel. address, right 14 bits. */ +#define R_PARISC_PCREL14DR 76 /* PC rel. address, right 14 bits. */ +#define R_PARISC_PCREL16F 77 /* 16 bits PC-rel. address. */ +#define R_PARISC_PCREL16WF 78 /* 16 bits PC-rel. address. */ +#define R_PARISC_PCREL16DF 79 /* 16 bits PC-rel. address. */ +#define R_PARISC_DIR64 80 /* 64 bits of eff. address. */ +#define R_PARISC_DIR14WR 83 /* 14 bits of eff. address. */ +#define R_PARISC_DIR14DR 84 /* 14 bits of eff. address. */ +#define R_PARISC_DIR16F 85 /* 16 bits of eff. address. */ +#define R_PARISC_DIR16WF 86 /* 16 bits of eff. address. */ +#define R_PARISC_DIR16DF 87 /* 16 bits of eff. address. */ +#define R_PARISC_GPREL64 88 /* 64 bits of GP-rel. address. */ +#define R_PARISC_GPREL14WR 91 /* GP-rel. address, right 14 bits. */ +#define R_PARISC_GPREL14DR 92 /* GP-rel. address, right 14 bits. */ +#define R_PARISC_GPREL16F 93 /* 16 bits GP-rel. address. */ +#define R_PARISC_GPREL16WF 94 /* 16 bits GP-rel. address. */ +#define R_PARISC_GPREL16DF 95 /* 16 bits GP-rel. address. */ +#define R_PARISC_LTOFF64 96 /* 64 bits LT-rel. address. */ +#define R_PARISC_LTOFF14WR 99 /* LT-rel. address, right 14 bits. */ +#define R_PARISC_LTOFF14DR 100 /* LT-rel. address, right 14 bits. */ +#define R_PARISC_LTOFF16F 101 /* 16 bits LT-rel. address. */ +#define R_PARISC_LTOFF16WF 102 /* 16 bits LT-rel. address. */ +#define R_PARISC_LTOFF16DF 103 /* 16 bits LT-rel. address. */ +#define R_PARISC_SECREL64 104 /* 64 bits section rel. address. */ +#define R_PARISC_SEGREL64 112 /* 64 bits segment rel. address. */ +#define R_PARISC_PLTOFF14WR 115 /* PLT-rel. address, right 14 bits. */ +#define R_PARISC_PLTOFF14DR 116 /* PLT-rel. address, right 14 bits. */ +#define R_PARISC_PLTOFF16F 117 /* 16 bits LT-rel. address. */ +#define R_PARISC_PLTOFF16WF 118 /* 16 bits PLT-rel. address. */ +#define R_PARISC_PLTOFF16DF 119 /* 16 bits PLT-rel. address. */ +#define R_PARISC_LTOFF_FPTR64 120 /* 64 bits LT-rel. function ptr. */ +#define R_PARISC_LTOFF_FPTR14WR 123 /* LT-rel. fct. ptr., right 14 bits. */ +#define R_PARISC_LTOFF_FPTR14DR 124 /* LT-rel. fct. ptr., right 14 bits. */ +#define R_PARISC_LTOFF_FPTR16F 125 /* 16 bits LT-rel. function ptr. */ +#define R_PARISC_LTOFF_FPTR16WF 126 /* 16 bits LT-rel. function ptr. */ +#define R_PARISC_LTOFF_FPTR16DF 127 /* 16 bits LT-rel. function ptr. */ +#define R_PARISC_LORESERVE 128 +#define R_PARISC_COPY 128 /* Copy relocation. */ +#define R_PARISC_IPLT 129 /* Dynamic reloc, imported PLT */ +#define R_PARISC_EPLT 130 /* Dynamic reloc, exported PLT */ +#define R_PARISC_TPREL32 153 /* 32 bits TP-rel. address. */ +#define R_PARISC_TPREL21L 154 /* TP-rel. address, left 21 bits. */ +#define R_PARISC_TPREL14R 158 /* TP-rel. address, right 14 bits. */ +#define R_PARISC_LTOFF_TP21L 162 /* LT-TP-rel. address, left 21 bits. */ +#define R_PARISC_LTOFF_TP14R 166 /* LT-TP-rel. address, right 14 bits.*/ +#define R_PARISC_LTOFF_TP14F 167 /* 14 bits LT-TP-rel. address. */ +#define R_PARISC_TPREL64 216 /* 64 bits TP-rel. address. */ +#define R_PARISC_TPREL14WR 219 /* TP-rel. address, right 14 bits. */ +#define R_PARISC_TPREL14DR 220 /* TP-rel. address, right 14 bits. */ +#define R_PARISC_TPREL16F 221 /* 16 bits TP-rel. address. */ +#define R_PARISC_TPREL16WF 222 /* 16 bits TP-rel. address. */ +#define R_PARISC_TPREL16DF 223 /* 16 bits TP-rel. address. */ +#define R_PARISC_LTOFF_TP64 224 /* 64 bits LT-TP-rel. address. */ +#define R_PARISC_LTOFF_TP14WR 227 /* LT-TP-rel. address, right 14 bits.*/ +#define R_PARISC_LTOFF_TP14DR 228 /* LT-TP-rel. address, right 14 bits.*/ +#define R_PARISC_LTOFF_TP16F 229 /* 16 bits LT-TP-rel. address. */ +#define R_PARISC_LTOFF_TP16WF 230 /* 16 bits LT-TP-rel. address. */ +#define R_PARISC_LTOFF_TP16DF 231 /* 16 bits LT-TP-rel. address. */ +#define R_PARISC_HIRESERVE 255 + +/* Legal values for p_type field of Elf32_Phdr/Elf64_Phdr. */ + +#define PT_HP_TLS (PT_LOOS + 0x0) +#define PT_HP_CORE_NONE (PT_LOOS + 0x1) +#define PT_HP_CORE_VERSION (PT_LOOS + 0x2) +#define PT_HP_CORE_KERNEL (PT_LOOS + 0x3) +#define PT_HP_CORE_COMM (PT_LOOS + 0x4) +#define PT_HP_CORE_PROC (PT_LOOS + 0x5) +#define PT_HP_CORE_LOADABLE (PT_LOOS + 0x6) +#define PT_HP_CORE_STACK (PT_LOOS + 0x7) +#define PT_HP_CORE_SHM (PT_LOOS + 0x8) +#define PT_HP_CORE_MMF (PT_LOOS + 0x9) +#define PT_HP_PARALLEL (PT_LOOS + 0x10) +#define PT_HP_FASTBIND (PT_LOOS + 0x11) +#define PT_HP_OPT_ANNOT (PT_LOOS + 0x12) +#define PT_HP_HSL_ANNOT (PT_LOOS + 0x13) +#define PT_HP_STACK (PT_LOOS + 0x14) + +#define PT_PARISC_ARCHEXT 0x70000000 +#define PT_PARISC_UNWIND 0x70000001 + +/* Legal values for p_flags field of Elf32_Phdr/Elf64_Phdr. */ + +#define PF_PARISC_SBP 0x08000000 + +#define PF_HP_PAGE_SIZE 0x00100000 +#define PF_HP_FAR_SHARED 0x00200000 +#define PF_HP_NEAR_SHARED 0x00400000 +#define PF_HP_CODE 0x01000000 +#define PF_HP_MODIFY 0x02000000 +#define PF_HP_LAZYSWAP 0x04000000 +#define PF_HP_SBP 0x08000000 + + +/* Alpha specific definitions. */ + +/* Legal values for e_flags field of Elf64_Ehdr. */ + +#define EF_ALPHA_32BIT 1 /* All addresses must be < 2GB. */ +#define EF_ALPHA_CANRELAX 2 /* Relocations for relaxing exist. */ + +/* Legal values for sh_type field of Elf64_Shdr. */ + +/* These two are primerily concerned with ECOFF debugging info. */ +#define SHT_ALPHA_DEBUG 0x70000001 +#define SHT_ALPHA_REGINFO 0x70000002 + +/* Legal values for sh_flags field of Elf64_Shdr. */ + +#define SHF_ALPHA_GPREL 0x10000000 + +/* Legal values for st_other field of Elf64_Sym. */ +#define STO_ALPHA_NOPV 0x80 /* No PV required. */ +#define STO_ALPHA_STD_GPLOAD 0x88 /* PV only used for initial ldgp. */ + +/* Alpha relocs. */ + +#define R_ALPHA_NONE 0 /* No reloc */ +#define R_ALPHA_REFLONG 1 /* Direct 32 bit */ +#define R_ALPHA_REFQUAD 2 /* Direct 64 bit */ +#define R_ALPHA_GPREL32 3 /* GP relative 32 bit */ +#define R_ALPHA_LITERAL 4 /* GP relative 16 bit w/optimization */ +#define R_ALPHA_LITUSE 5 /* Optimization hint for LITERAL */ +#define R_ALPHA_GPDISP 6 /* Add displacement to GP */ +#define R_ALPHA_BRADDR 7 /* PC+4 relative 23 bit shifted */ +#define R_ALPHA_HINT 8 /* PC+4 relative 16 bit shifted */ +#define R_ALPHA_SREL16 9 /* PC relative 16 bit */ +#define R_ALPHA_SREL32 10 /* PC relative 32 bit */ +#define R_ALPHA_SREL64 11 /* PC relative 64 bit */ +#define R_ALPHA_GPRELHIGH 17 /* GP relative 32 bit, high 16 bits */ +#define R_ALPHA_GPRELLOW 18 /* GP relative 32 bit, low 16 bits */ +#define R_ALPHA_GPREL16 19 /* GP relative 16 bit */ +#define R_ALPHA_COPY 24 /* Copy symbol at runtime */ +#define R_ALPHA_GLOB_DAT 25 /* Create GOT entry */ +#define R_ALPHA_JMP_SLOT 26 /* Create PLT entry */ +#define R_ALPHA_RELATIVE 27 /* Adjust by program base */ +#define R_ALPHA_TLS_GD_HI 28 +#define R_ALPHA_TLSGD 29 +#define R_ALPHA_TLS_LDM 30 +#define R_ALPHA_DTPMOD64 31 +#define R_ALPHA_GOTDTPREL 32 +#define R_ALPHA_DTPREL64 33 +#define R_ALPHA_DTPRELHI 34 +#define R_ALPHA_DTPRELLO 35 +#define R_ALPHA_DTPREL16 36 +#define R_ALPHA_GOTTPREL 37 +#define R_ALPHA_TPREL64 38 +#define R_ALPHA_TPRELHI 39 +#define R_ALPHA_TPRELLO 40 +#define R_ALPHA_TPREL16 41 +/* Keep this the last entry. */ +#define R_ALPHA_NUM 46 + +/* Magic values of the LITUSE relocation addend. */ +#define LITUSE_ALPHA_ADDR 0 +#define LITUSE_ALPHA_BASE 1 +#define LITUSE_ALPHA_BYTOFF 2 +#define LITUSE_ALPHA_JSR 3 +#define LITUSE_ALPHA_TLS_GD 4 +#define LITUSE_ALPHA_TLS_LDM 5 + +/* Legal values for d_tag of Elf64_Dyn. */ +#define DT_ALPHA_PLTRO (DT_LOPROC + 0) +#define DT_ALPHA_NUM 1 + +/* PowerPC specific declarations */ + +/* Values for Elf32/64_Ehdr.e_flags. */ +#define EF_PPC_EMB 0x80000000 /* PowerPC embedded flag */ + +/* Cygnus local bits below */ +#define EF_PPC_RELOCATABLE 0x00010000 /* PowerPC -mrelocatable flag*/ +#define EF_PPC_RELOCATABLE_LIB 0x00008000 /* PowerPC -mrelocatable-lib + flag */ + +/* PowerPC relocations defined by the ABIs */ +#define R_PPC_NONE 0 +#define R_PPC_ADDR32 1 /* 32bit absolute address */ +#define R_PPC_ADDR24 2 /* 26bit address, 2 bits ignored. */ +#define R_PPC_ADDR16 3 /* 16bit absolute address */ +#define R_PPC_ADDR16_LO 4 /* lower 16bit of absolute address */ +#define R_PPC_ADDR16_HI 5 /* high 16bit of absolute address */ +#define R_PPC_ADDR16_HA 6 /* adjusted high 16bit */ +#define R_PPC_ADDR14 7 /* 16bit address, 2 bits ignored */ +#define R_PPC_ADDR14_BRTAKEN 8 +#define R_PPC_ADDR14_BRNTAKEN 9 +#define R_PPC_REL24 10 /* PC relative 26 bit */ +#define R_PPC_REL14 11 /* PC relative 16 bit */ +#define R_PPC_REL14_BRTAKEN 12 +#define R_PPC_REL14_BRNTAKEN 13 +#define R_PPC_GOT16 14 +#define R_PPC_GOT16_LO 15 +#define R_PPC_GOT16_HI 16 +#define R_PPC_GOT16_HA 17 +#define R_PPC_PLTREL24 18 +#define R_PPC_COPY 19 +#define R_PPC_GLOB_DAT 20 +#define R_PPC_JMP_SLOT 21 +#define R_PPC_RELATIVE 22 +#define R_PPC_LOCAL24PC 23 +#define R_PPC_UADDR32 24 +#define R_PPC_UADDR16 25 +#define R_PPC_REL32 26 +#define R_PPC_PLT32 27 +#define R_PPC_PLTREL32 28 +#define R_PPC_PLT16_LO 29 +#define R_PPC_PLT16_HI 30 +#define R_PPC_PLT16_HA 31 +#define R_PPC_SDAREL16 32 +#define R_PPC_SECTOFF 33 +#define R_PPC_SECTOFF_LO 34 +#define R_PPC_SECTOFF_HI 35 +#define R_PPC_SECTOFF_HA 36 + +/* PowerPC relocations defined for the TLS access ABI. */ +#define R_PPC_TLS 67 /* none (sym+add)@tls */ +#define R_PPC_DTPMOD32 68 /* word32 (sym+add)@dtpmod */ +#define R_PPC_TPREL16 69 /* half16* (sym+add)@tprel */ +#define R_PPC_TPREL16_LO 70 /* half16 (sym+add)@tprel@l */ +#define R_PPC_TPREL16_HI 71 /* half16 (sym+add)@tprel@h */ +#define R_PPC_TPREL16_HA 72 /* half16 (sym+add)@tprel@ha */ +#define R_PPC_TPREL32 73 /* word32 (sym+add)@tprel */ +#define R_PPC_DTPREL16 74 /* half16* (sym+add)@dtprel */ +#define R_PPC_DTPREL16_LO 75 /* half16 (sym+add)@dtprel@l */ +#define R_PPC_DTPREL16_HI 76 /* half16 (sym+add)@dtprel@h */ +#define R_PPC_DTPREL16_HA 77 /* half16 (sym+add)@dtprel@ha */ +#define R_PPC_DTPREL32 78 /* word32 (sym+add)@dtprel */ +#define R_PPC_GOT_TLSGD16 79 /* half16* (sym+add)@got@tlsgd */ +#define R_PPC_GOT_TLSGD16_LO 80 /* half16 (sym+add)@got@tlsgd@l */ +#define R_PPC_GOT_TLSGD16_HI 81 /* half16 (sym+add)@got@tlsgd@h */ +#define R_PPC_GOT_TLSGD16_HA 82 /* half16 (sym+add)@got@tlsgd@ha */ +#define R_PPC_GOT_TLSLD16 83 /* half16* (sym+add)@got@tlsld */ +#define R_PPC_GOT_TLSLD16_LO 84 /* half16 (sym+add)@got@tlsld@l */ +#define R_PPC_GOT_TLSLD16_HI 85 /* half16 (sym+add)@got@tlsld@h */ +#define R_PPC_GOT_TLSLD16_HA 86 /* half16 (sym+add)@got@tlsld@ha */ +#define R_PPC_GOT_TPREL16 87 /* half16* (sym+add)@got@tprel */ +#define R_PPC_GOT_TPREL16_LO 88 /* half16 (sym+add)@got@tprel@l */ +#define R_PPC_GOT_TPREL16_HI 89 /* half16 (sym+add)@got@tprel@h */ +#define R_PPC_GOT_TPREL16_HA 90 /* half16 (sym+add)@got@tprel@ha */ +#define R_PPC_GOT_DTPREL16 91 /* half16* (sym+add)@got@dtprel */ +#define R_PPC_GOT_DTPREL16_LO 92 /* half16* (sym+add)@got@dtprel@l */ +#define R_PPC_GOT_DTPREL16_HI 93 /* half16* (sym+add)@got@dtprel@h */ +#define R_PPC_GOT_DTPREL16_HA 94 /* half16* (sym+add)@got@dtprel@ha */ + +/* Keep this the last entry. */ +#define R_PPC_NUM 95 + +/* The remaining relocs are from the Embedded ELF ABI, and are not + in the SVR4 ELF ABI. */ +#define R_PPC_EMB_NADDR32 101 +#define R_PPC_EMB_NADDR16 102 +#define R_PPC_EMB_NADDR16_LO 103 +#define R_PPC_EMB_NADDR16_HI 104 +#define R_PPC_EMB_NADDR16_HA 105 +#define R_PPC_EMB_SDAI16 106 +#define R_PPC_EMB_SDA2I16 107 +#define R_PPC_EMB_SDA2REL 108 +#define R_PPC_EMB_SDA21 109 /* 16 bit offset in SDA */ +#define R_PPC_EMB_MRKREF 110 +#define R_PPC_EMB_RELSEC16 111 +#define R_PPC_EMB_RELST_LO 112 +#define R_PPC_EMB_RELST_HI 113 +#define R_PPC_EMB_RELST_HA 114 +#define R_PPC_EMB_BIT_FLD 115 +#define R_PPC_EMB_RELSDA 116 /* 16 bit relative offset in SDA */ + +/* Diab tool relocations. */ +#define R_PPC_DIAB_SDA21_LO 180 /* like EMB_SDA21, but lower 16 bit */ +#define R_PPC_DIAB_SDA21_HI 181 /* like EMB_SDA21, but high 16 bit */ +#define R_PPC_DIAB_SDA21_HA 182 /* like EMB_SDA21, adjusted high 16 */ +#define R_PPC_DIAB_RELSDA_LO 183 /* like EMB_RELSDA, but lower 16 bit */ +#define R_PPC_DIAB_RELSDA_HI 184 /* like EMB_RELSDA, but high 16 bit */ +#define R_PPC_DIAB_RELSDA_HA 185 /* like EMB_RELSDA, adjusted high 16 */ + +/* GNU relocs used in PIC code sequences. */ +#define R_PPC_REL16 249 /* word32 (sym+add-.) */ +#define R_PPC_REL16_LO 250 /* half16 (sym+add-.)@l */ +#define R_PPC_REL16_HI 251 /* half16 (sym+add-.)@h */ +#define R_PPC_REL16_HA 252 /* half16 (sym+add-.)@ha */ + +/* This is a phony reloc to handle any old fashioned TOC16 references + that may still be in object files. */ +#define R_PPC_TOC16 255 + +/* PowerPC specific values for the Dyn d_tag field. */ +#define DT_PPC_GOT (DT_LOPROC + 0) +#define DT_PPC_NUM 1 + +/* PowerPC64 relocations defined by the ABIs */ +#define R_PPC64_NONE R_PPC_NONE +#define R_PPC64_ADDR32 R_PPC_ADDR32 /* 32bit absolute address */ +#define R_PPC64_ADDR24 R_PPC_ADDR24 /* 26bit address, word aligned */ +#define R_PPC64_ADDR16 R_PPC_ADDR16 /* 16bit absolute address */ +#define R_PPC64_ADDR16_LO R_PPC_ADDR16_LO /* lower 16bits of address */ +#define R_PPC64_ADDR16_HI R_PPC_ADDR16_HI /* high 16bits of address. */ +#define R_PPC64_ADDR16_HA R_PPC_ADDR16_HA /* adjusted high 16bits. */ +#define R_PPC64_ADDR14 R_PPC_ADDR14 /* 16bit address, word aligned */ +#define R_PPC64_ADDR14_BRTAKEN R_PPC_ADDR14_BRTAKEN +#define R_PPC64_ADDR14_BRNTAKEN R_PPC_ADDR14_BRNTAKEN +#define R_PPC64_REL24 R_PPC_REL24 /* PC-rel. 26 bit, word aligned */ +#define R_PPC64_REL14 R_PPC_REL14 /* PC relative 16 bit */ +#define R_PPC64_REL14_BRTAKEN R_PPC_REL14_BRTAKEN +#define R_PPC64_REL14_BRNTAKEN R_PPC_REL14_BRNTAKEN +#define R_PPC64_GOT16 R_PPC_GOT16 +#define R_PPC64_GOT16_LO R_PPC_GOT16_LO +#define R_PPC64_GOT16_HI R_PPC_GOT16_HI +#define R_PPC64_GOT16_HA R_PPC_GOT16_HA + +#define R_PPC64_COPY R_PPC_COPY +#define R_PPC64_GLOB_DAT R_PPC_GLOB_DAT +#define R_PPC64_JMP_SLOT R_PPC_JMP_SLOT +#define R_PPC64_RELATIVE R_PPC_RELATIVE + +#define R_PPC64_UADDR32 R_PPC_UADDR32 +#define R_PPC64_UADDR16 R_PPC_UADDR16 +#define R_PPC64_REL32 R_PPC_REL32 +#define R_PPC64_PLT32 R_PPC_PLT32 +#define R_PPC64_PLTREL32 R_PPC_PLTREL32 +#define R_PPC64_PLT16_LO R_PPC_PLT16_LO +#define R_PPC64_PLT16_HI R_PPC_PLT16_HI +#define R_PPC64_PLT16_HA R_PPC_PLT16_HA + +#define R_PPC64_SECTOFF R_PPC_SECTOFF +#define R_PPC64_SECTOFF_LO R_PPC_SECTOFF_LO +#define R_PPC64_SECTOFF_HI R_PPC_SECTOFF_HI +#define R_PPC64_SECTOFF_HA R_PPC_SECTOFF_HA +#define R_PPC64_ADDR30 37 /* word30 (S + A - P) >> 2 */ +#define R_PPC64_ADDR64 38 /* doubleword64 S + A */ +#define R_PPC64_ADDR16_HIGHER 39 /* half16 #higher(S + A) */ +#define R_PPC64_ADDR16_HIGHERA 40 /* half16 #highera(S + A) */ +#define R_PPC64_ADDR16_HIGHEST 41 /* half16 #highest(S + A) */ +#define R_PPC64_ADDR16_HIGHESTA 42 /* half16 #highesta(S + A) */ +#define R_PPC64_UADDR64 43 /* doubleword64 S + A */ +#define R_PPC64_REL64 44 /* doubleword64 S + A - P */ +#define R_PPC64_PLT64 45 /* doubleword64 L + A */ +#define R_PPC64_PLTREL64 46 /* doubleword64 L + A - P */ +#define R_PPC64_TOC16 47 /* half16* S + A - .TOC */ +#define R_PPC64_TOC16_LO 48 /* half16 #lo(S + A - .TOC.) */ +#define R_PPC64_TOC16_HI 49 /* half16 #hi(S + A - .TOC.) */ +#define R_PPC64_TOC16_HA 50 /* half16 #ha(S + A - .TOC.) */ +#define R_PPC64_TOC 51 /* doubleword64 .TOC */ +#define R_PPC64_PLTGOT16 52 /* half16* M + A */ +#define R_PPC64_PLTGOT16_LO 53 /* half16 #lo(M + A) */ +#define R_PPC64_PLTGOT16_HI 54 /* half16 #hi(M + A) */ +#define R_PPC64_PLTGOT16_HA 55 /* half16 #ha(M + A) */ + +#define R_PPC64_ADDR16_DS 56 /* half16ds* (S + A) >> 2 */ +#define R_PPC64_ADDR16_LO_DS 57 /* half16ds #lo(S + A) >> 2 */ +#define R_PPC64_GOT16_DS 58 /* half16ds* (G + A) >> 2 */ +#define R_PPC64_GOT16_LO_DS 59 /* half16ds #lo(G + A) >> 2 */ +#define R_PPC64_PLT16_LO_DS 60 /* half16ds #lo(L + A) >> 2 */ +#define R_PPC64_SECTOFF_DS 61 /* half16ds* (R + A) >> 2 */ +#define R_PPC64_SECTOFF_LO_DS 62 /* half16ds #lo(R + A) >> 2 */ +#define R_PPC64_TOC16_DS 63 /* half16ds* (S + A - .TOC.) >> 2 */ +#define R_PPC64_TOC16_LO_DS 64 /* half16ds #lo(S + A - .TOC.) >> 2 */ +#define R_PPC64_PLTGOT16_DS 65 /* half16ds* (M + A) >> 2 */ +#define R_PPC64_PLTGOT16_LO_DS 66 /* half16ds #lo(M + A) >> 2 */ + +/* PowerPC64 relocations defined for the TLS access ABI. */ +#define R_PPC64_TLS 67 /* none (sym+add)@tls */ +#define R_PPC64_DTPMOD64 68 /* doubleword64 (sym+add)@dtpmod */ +#define R_PPC64_TPREL16 69 /* half16* (sym+add)@tprel */ +#define R_PPC64_TPREL16_LO 70 /* half16 (sym+add)@tprel@l */ +#define R_PPC64_TPREL16_HI 71 /* half16 (sym+add)@tprel@h */ +#define R_PPC64_TPREL16_HA 72 /* half16 (sym+add)@tprel@ha */ +#define R_PPC64_TPREL64 73 /* doubleword64 (sym+add)@tprel */ +#define R_PPC64_DTPREL16 74 /* half16* (sym+add)@dtprel */ +#define R_PPC64_DTPREL16_LO 75 /* half16 (sym+add)@dtprel@l */ +#define R_PPC64_DTPREL16_HI 76 /* half16 (sym+add)@dtprel@h */ +#define R_PPC64_DTPREL16_HA 77 /* half16 (sym+add)@dtprel@ha */ +#define R_PPC64_DTPREL64 78 /* doubleword64 (sym+add)@dtprel */ +#define R_PPC64_GOT_TLSGD16 79 /* half16* (sym+add)@got@tlsgd */ +#define R_PPC64_GOT_TLSGD16_LO 80 /* half16 (sym+add)@got@tlsgd@l */ +#define R_PPC64_GOT_TLSGD16_HI 81 /* half16 (sym+add)@got@tlsgd@h */ +#define R_PPC64_GOT_TLSGD16_HA 82 /* half16 (sym+add)@got@tlsgd@ha */ +#define R_PPC64_GOT_TLSLD16 83 /* half16* (sym+add)@got@tlsld */ +#define R_PPC64_GOT_TLSLD16_LO 84 /* half16 (sym+add)@got@tlsld@l */ +#define R_PPC64_GOT_TLSLD16_HI 85 /* half16 (sym+add)@got@tlsld@h */ +#define R_PPC64_GOT_TLSLD16_HA 86 /* half16 (sym+add)@got@tlsld@ha */ +#define R_PPC64_GOT_TPREL16_DS 87 /* half16ds* (sym+add)@got@tprel */ +#define R_PPC64_GOT_TPREL16_LO_DS 88 /* half16ds (sym+add)@got@tprel@l */ +#define R_PPC64_GOT_TPREL16_HI 89 /* half16 (sym+add)@got@tprel@h */ +#define R_PPC64_GOT_TPREL16_HA 90 /* half16 (sym+add)@got@tprel@ha */ +#define R_PPC64_GOT_DTPREL16_DS 91 /* half16ds* (sym+add)@got@dtprel */ +#define R_PPC64_GOT_DTPREL16_LO_DS 92 /* half16ds (sym+add)@got@dtprel@l */ +#define R_PPC64_GOT_DTPREL16_HI 93 /* half16 (sym+add)@got@dtprel@h */ +#define R_PPC64_GOT_DTPREL16_HA 94 /* half16 (sym+add)@got@dtprel@ha */ +#define R_PPC64_TPREL16_DS 95 /* half16ds* (sym+add)@tprel */ +#define R_PPC64_TPREL16_LO_DS 96 /* half16ds (sym+add)@tprel@l */ +#define R_PPC64_TPREL16_HIGHER 97 /* half16 (sym+add)@tprel@higher */ +#define R_PPC64_TPREL16_HIGHERA 98 /* half16 (sym+add)@tprel@highera */ +#define R_PPC64_TPREL16_HIGHEST 99 /* half16 (sym+add)@tprel@highest */ +#define R_PPC64_TPREL16_HIGHESTA 100 /* half16 (sym+add)@tprel@highesta */ +#define R_PPC64_DTPREL16_DS 101 /* half16ds* (sym+add)@dtprel */ +#define R_PPC64_DTPREL16_LO_DS 102 /* half16ds (sym+add)@dtprel@l */ +#define R_PPC64_DTPREL16_HIGHER 103 /* half16 (sym+add)@dtprel@higher */ +#define R_PPC64_DTPREL16_HIGHERA 104 /* half16 (sym+add)@dtprel@highera */ +#define R_PPC64_DTPREL16_HIGHEST 105 /* half16 (sym+add)@dtprel@highest */ +#define R_PPC64_DTPREL16_HIGHESTA 106 /* half16 (sym+add)@dtprel@highesta */ + +/* Keep this the last entry. */ +#define R_PPC64_NUM 107 + +/* PowerPC64 specific values for the Dyn d_tag field. */ +#define DT_PPC64_GLINK (DT_LOPROC + 0) +#define DT_PPC64_OPD (DT_LOPROC + 1) +#define DT_PPC64_OPDSZ (DT_LOPROC + 2) +#define DT_PPC64_NUM 3 + + +/* ARM specific declarations */ + +/* Processor specific flags for the ELF header e_flags field. */ +#define EF_ARM_RELEXEC 0x01 +#define EF_ARM_HASENTRY 0x02 +#define EF_ARM_INTERWORK 0x04 +#define EF_ARM_APCS_26 0x08 +#define EF_ARM_APCS_FLOAT 0x10 +#define EF_ARM_PIC 0x20 +#define EF_ARM_ALIGN8 0x40 /* 8-bit structure alignment is in use */ +#define EF_ARM_NEW_ABI 0x80 +#define EF_ARM_OLD_ABI 0x100 + +/* Other constants defined in the ARM ELF spec. version B-01. */ +/* NB. These conflict with values defined above. */ +#define EF_ARM_SYMSARESORTED 0x04 +#define EF_ARM_DYNSYMSUSESEGIDX 0x08 +#define EF_ARM_MAPSYMSFIRST 0x10 +#define EF_ARM_EABIMASK 0XFF000000 + +#define EF_ARM_EABI_VERSION(flags) ((flags) & EF_ARM_EABIMASK) +#define EF_ARM_EABI_UNKNOWN 0x00000000 +#define EF_ARM_EABI_VER1 0x01000000 +#define EF_ARM_EABI_VER2 0x02000000 + +/* Additional symbol types for Thumb */ +#define STT_ARM_TFUNC 0xd + +/* ARM-specific values for sh_flags */ +#define SHF_ARM_ENTRYSECT 0x10000000 /* Section contains an entry point */ +#define SHF_ARM_COMDEF 0x80000000 /* Section may be multiply defined + in the input to a link step */ + +/* ARM-specific program header flags */ +#define PF_ARM_SB 0x10000000 /* Segment contains the location + addressed by the static base */ + +/* Processor specific values for the Phdr p_type field. */ +#define PT_ARM_EXIDX 0x70000001 /* .ARM.exidx segment */ + +/* ARM relocs. */ + +#define R_ARM_NONE 0 /* No reloc */ +#define R_ARM_PC24 1 /* PC relative 26 bit branch */ +#define R_ARM_ABS32 2 /* Direct 32 bit */ +#define R_ARM_REL32 3 /* PC relative 32 bit */ +#define R_ARM_PC13 4 +#define R_ARM_ABS16 5 /* Direct 16 bit */ +#define R_ARM_ABS12 6 /* Direct 12 bit */ +#define R_ARM_THM_ABS5 7 +#define R_ARM_ABS8 8 /* Direct 8 bit */ +#define R_ARM_SBREL32 9 +#define R_ARM_THM_PC22 10 +#define R_ARM_THM_PC8 11 +#define R_ARM_AMP_VCALL9 12 +#define R_ARM_SWI24 13 +#define R_ARM_THM_SWI8 14 +#define R_ARM_XPC25 15 +#define R_ARM_THM_XPC22 16 +#define R_ARM_TLS_DTPMOD32 17 +#define R_ARM_TLS_DTPOFF32 18 +#define R_ARM_TLS_TPOFF32 19 +#define R_ARM_COPY 20 /* Copy symbol at runtime */ +#define R_ARM_GLOB_DAT 21 /* Create GOT entry */ +#define R_ARM_JUMP_SLOT 22 /* Create PLT entry */ +#define R_ARM_RELATIVE 23 /* Adjust by program base */ +#define R_ARM_GOTOFF 24 /* 32 bit offset to GOT */ +#define R_ARM_GOTPC 25 /* 32 bit PC relative offset to GOT */ +#define R_ARM_GOT32 26 /* 32 bit GOT entry */ +#define R_ARM_PLT32 27 /* 32 bit PLT address */ +#define R_ARM_ALU_PCREL_7_0 32 +#define R_ARM_ALU_PCREL_15_8 33 +#define R_ARM_ALU_PCREL_23_15 34 +#define R_ARM_LDR_SBREL_11_0 35 +#define R_ARM_ALU_SBREL_19_12 36 +#define R_ARM_ALU_SBREL_27_20 37 +#define R_ARM_GNU_VTENTRY 100 +#define R_ARM_GNU_VTINHERIT 101 +#define R_ARM_THM_PC11 102 /* thumb unconditional branch */ +#define R_ARM_THM_PC9 103 /* thumb conditional branch */ +#define R_ARM_TLS_GD32 104 +#define R_ARM_TLS_LDM32 105 +#define R_ARM_TLS_LDO32 106 +#define R_ARM_TLS_IE32 107 +#define R_ARM_TLS_LE32 108 +#define R_ARM_TLS_LDO12 109 +#define R_ARM_TLS_LE12 110 +#define R_ARM_TLS_IE12GP 111 +#define R_ARM_RXPC25 249 +#define R_ARM_RSBREL32 250 +#define R_ARM_THM_RPC22 251 +#define R_ARM_RREL32 252 +#define R_ARM_RABS22 253 +#define R_ARM_RPC24 254 +#define R_ARM_RBASE 255 +/* Keep this the last entry. */ +#define R_ARM_NUM 256 + +/* IA-64 specific declarations. */ + +/* Processor specific flags for the Ehdr e_flags field. */ +#define EF_IA_64_MASKOS 0x0000000f /* os-specific flags */ +#define EF_IA_64_ABI64 0x00000010 /* 64-bit ABI */ +#define EF_IA_64_ARCH 0xff000000 /* arch. version mask */ + +/* Processor specific values for the Phdr p_type field. */ +#define PT_IA_64_ARCHEXT (PT_LOPROC + 0) /* arch extension bits */ +#define PT_IA_64_UNWIND (PT_LOPROC + 1) /* ia64 unwind bits */ +#define PT_IA_64_HP_OPT_ANOT (PT_LOOS + 0x12) +#define PT_IA_64_HP_HSL_ANOT (PT_LOOS + 0x13) +#define PT_IA_64_HP_STACK (PT_LOOS + 0x14) + +/* Processor specific flags for the Phdr p_flags field. */ +#define PF_IA_64_NORECOV 0x80000000 /* spec insns w/o recovery */ + +/* Processor specific values for the Shdr sh_type field. */ +#define SHT_IA_64_EXT (SHT_LOPROC + 0) /* extension bits */ +#define SHT_IA_64_UNWIND (SHT_LOPROC + 1) /* unwind bits */ + +/* Processor specific flags for the Shdr sh_flags field. */ +#define SHF_IA_64_SHORT 0x10000000 /* section near gp */ +#define SHF_IA_64_NORECOV 0x20000000 /* spec insns w/o recovery */ + +/* Processor specific values for the Dyn d_tag field. */ +#define DT_IA_64_PLT_RESERVE (DT_LOPROC + 0) +#define DT_IA_64_NUM 1 + +/* IA-64 relocations. */ +#define R_IA64_NONE 0x00 /* none */ +#define R_IA64_IMM14 0x21 /* symbol + addend, add imm14 */ +#define R_IA64_IMM22 0x22 /* symbol + addend, add imm22 */ +#define R_IA64_IMM64 0x23 /* symbol + addend, mov imm64 */ +#define R_IA64_DIR32MSB 0x24 /* symbol + addend, data4 MSB */ +#define R_IA64_DIR32LSB 0x25 /* symbol + addend, data4 LSB */ +#define R_IA64_DIR64MSB 0x26 /* symbol + addend, data8 MSB */ +#define R_IA64_DIR64LSB 0x27 /* symbol + addend, data8 LSB */ +#define R_IA64_GPREL22 0x2a /* @gprel(sym + add), add imm22 */ +#define R_IA64_GPREL64I 0x2b /* @gprel(sym + add), mov imm64 */ +#define R_IA64_GPREL32MSB 0x2c /* @gprel(sym + add), data4 MSB */ +#define R_IA64_GPREL32LSB 0x2d /* @gprel(sym + add), data4 LSB */ +#define R_IA64_GPREL64MSB 0x2e /* @gprel(sym + add), data8 MSB */ +#define R_IA64_GPREL64LSB 0x2f /* @gprel(sym + add), data8 LSB */ +#define R_IA64_LTOFF22 0x32 /* @ltoff(sym + add), add imm22 */ +#define R_IA64_LTOFF64I 0x33 /* @ltoff(sym + add), mov imm64 */ +#define R_IA64_PLTOFF22 0x3a /* @pltoff(sym + add), add imm22 */ +#define R_IA64_PLTOFF64I 0x3b /* @pltoff(sym + add), mov imm64 */ +#define R_IA64_PLTOFF64MSB 0x3e /* @pltoff(sym + add), data8 MSB */ +#define R_IA64_PLTOFF64LSB 0x3f /* @pltoff(sym + add), data8 LSB */ +#define R_IA64_FPTR64I 0x43 /* @fptr(sym + add), mov imm64 */ +#define R_IA64_FPTR32MSB 0x44 /* @fptr(sym + add), data4 MSB */ +#define R_IA64_FPTR32LSB 0x45 /* @fptr(sym + add), data4 LSB */ +#define R_IA64_FPTR64MSB 0x46 /* @fptr(sym + add), data8 MSB */ +#define R_IA64_FPTR64LSB 0x47 /* @fptr(sym + add), data8 LSB */ +#define R_IA64_PCREL60B 0x48 /* @pcrel(sym + add), brl */ +#define R_IA64_PCREL21B 0x49 /* @pcrel(sym + add), ptb, call */ +#define R_IA64_PCREL21M 0x4a /* @pcrel(sym + add), chk.s */ +#define R_IA64_PCREL21F 0x4b /* @pcrel(sym + add), fchkf */ +#define R_IA64_PCREL32MSB 0x4c /* @pcrel(sym + add), data4 MSB */ +#define R_IA64_PCREL32LSB 0x4d /* @pcrel(sym + add), data4 LSB */ +#define R_IA64_PCREL64MSB 0x4e /* @pcrel(sym + add), data8 MSB */ +#define R_IA64_PCREL64LSB 0x4f /* @pcrel(sym + add), data8 LSB */ +#define R_IA64_LTOFF_FPTR22 0x52 /* @ltoff(@fptr(s+a)), imm22 */ +#define R_IA64_LTOFF_FPTR64I 0x53 /* @ltoff(@fptr(s+a)), imm64 */ +#define R_IA64_LTOFF_FPTR32MSB 0x54 /* @ltoff(@fptr(s+a)), data4 MSB */ +#define R_IA64_LTOFF_FPTR32LSB 0x55 /* @ltoff(@fptr(s+a)), data4 LSB */ +#define R_IA64_LTOFF_FPTR64MSB 0x56 /* @ltoff(@fptr(s+a)), data8 MSB */ +#define R_IA64_LTOFF_FPTR64LSB 0x57 /* @ltoff(@fptr(s+a)), data8 LSB */ +#define R_IA64_SEGREL32MSB 0x5c /* @segrel(sym + add), data4 MSB */ +#define R_IA64_SEGREL32LSB 0x5d /* @segrel(sym + add), data4 LSB */ +#define R_IA64_SEGREL64MSB 0x5e /* @segrel(sym + add), data8 MSB */ +#define R_IA64_SEGREL64LSB 0x5f /* @segrel(sym + add), data8 LSB */ +#define R_IA64_SECREL32MSB 0x64 /* @secrel(sym + add), data4 MSB */ +#define R_IA64_SECREL32LSB 0x65 /* @secrel(sym + add), data4 LSB */ +#define R_IA64_SECREL64MSB 0x66 /* @secrel(sym + add), data8 MSB */ +#define R_IA64_SECREL64LSB 0x67 /* @secrel(sym + add), data8 LSB */ +#define R_IA64_REL32MSB 0x6c /* data 4 + REL */ +#define R_IA64_REL32LSB 0x6d /* data 4 + REL */ +#define R_IA64_REL64MSB 0x6e /* data 8 + REL */ +#define R_IA64_REL64LSB 0x6f /* data 8 + REL */ +#define R_IA64_LTV32MSB 0x74 /* symbol + addend, data4 MSB */ +#define R_IA64_LTV32LSB 0x75 /* symbol + addend, data4 LSB */ +#define R_IA64_LTV64MSB 0x76 /* symbol + addend, data8 MSB */ +#define R_IA64_LTV64LSB 0x77 /* symbol + addend, data8 LSB */ +#define R_IA64_PCREL21BI 0x79 /* @pcrel(sym + add), 21bit inst */ +#define R_IA64_PCREL22 0x7a /* @pcrel(sym + add), 22bit inst */ +#define R_IA64_PCREL64I 0x7b /* @pcrel(sym + add), 64bit inst */ +#define R_IA64_IPLTMSB 0x80 /* dynamic reloc, imported PLT, MSB */ +#define R_IA64_IPLTLSB 0x81 /* dynamic reloc, imported PLT, LSB */ +#define R_IA64_COPY 0x84 /* copy relocation */ +#define R_IA64_SUB 0x85 /* Addend and symbol difference */ +#define R_IA64_LTOFF22X 0x86 /* LTOFF22, relaxable. */ +#define R_IA64_LDXMOV 0x87 /* Use of LTOFF22X. */ +#define R_IA64_TPREL14 0x91 /* @tprel(sym + add), imm14 */ +#define R_IA64_TPREL22 0x92 /* @tprel(sym + add), imm22 */ +#define R_IA64_TPREL64I 0x93 /* @tprel(sym + add), imm64 */ +#define R_IA64_TPREL64MSB 0x96 /* @tprel(sym + add), data8 MSB */ +#define R_IA64_TPREL64LSB 0x97 /* @tprel(sym + add), data8 LSB */ +#define R_IA64_LTOFF_TPREL22 0x9a /* @ltoff(@tprel(s+a)), imm2 */ +#define R_IA64_DTPMOD64MSB 0xa6 /* @dtpmod(sym + add), data8 MSB */ +#define R_IA64_DTPMOD64LSB 0xa7 /* @dtpmod(sym + add), data8 LSB */ +#define R_IA64_LTOFF_DTPMOD22 0xaa /* @ltoff(@dtpmod(sym + add)), imm22 */ +#define R_IA64_DTPREL14 0xb1 /* @dtprel(sym + add), imm14 */ +#define R_IA64_DTPREL22 0xb2 /* @dtprel(sym + add), imm22 */ +#define R_IA64_DTPREL64I 0xb3 /* @dtprel(sym + add), imm64 */ +#define R_IA64_DTPREL32MSB 0xb4 /* @dtprel(sym + add), data4 MSB */ +#define R_IA64_DTPREL32LSB 0xb5 /* @dtprel(sym + add), data4 LSB */ +#define R_IA64_DTPREL64MSB 0xb6 /* @dtprel(sym + add), data8 MSB */ +#define R_IA64_DTPREL64LSB 0xb7 /* @dtprel(sym + add), data8 LSB */ +#define R_IA64_LTOFF_DTPREL22 0xba /* @ltoff(@dtprel(s+a)), imm22 */ + +/* SH specific declarations */ + +/* SH specific values for `st_other'. */ + +/* If set, this is a symbol pointing to SHmedia code, which will be branched + to, so need to add 1 to the symbol value. */ +#define STO_SH5_ISA32 (1 << 2) + +/* SH relocs. */ +#define R_SH_NONE 0 +#define R_SH_DIR32 1 +#define R_SH_REL32 2 +#define R_SH_DIR8WPN 3 +#define R_SH_IND12W 4 +#define R_SH_DIR8WPL 5 +#define R_SH_DIR8WPZ 6 +#define R_SH_DIR8BP 7 +#define R_SH_DIR8W 8 +#define R_SH_DIR8L 9 +#define R_SH_SWITCH16 25 +#define R_SH_SWITCH32 26 +#define R_SH_USES 27 +#define R_SH_COUNT 28 +#define R_SH_ALIGN 29 +#define R_SH_CODE 30 +#define R_SH_DATA 31 +#define R_SH_LABEL 32 +#define R_SH_SWITCH8 33 +#define R_SH_GNU_VTINHERIT 34 +#define R_SH_GNU_VTENTRY 35 +#define R_SH_TLS_GD_32 144 +#define R_SH_TLS_LD_32 145 +#define R_SH_TLS_LDO_32 146 +#define R_SH_TLS_IE_32 147 +#define R_SH_TLS_LE_32 148 +#define R_SH_TLS_DTPMOD32 149 +#define R_SH_TLS_DTPOFF32 150 +#define R_SH_TLS_TPOFF32 151 +#define R_SH_GOT32 160 +#define R_SH_PLT32 161 +#define R_SH_COPY 162 +#define R_SH_GLOB_DAT 163 +#define R_SH_JMP_SLOT 164 +#define R_SH_RELATIVE 165 +#define R_SH_GOTOFF 166 +#define R_SH_GOTPC 167 +#define R_SH_RELATIVE_LOW16 197 +#define R_SH_RELATIVE_MEDLOW16 198 +#define R_SH_IMM_LOW16 246 +#define R_SH_IMM_LOW16_PCREL 247 +#define R_SH_IMM_MEDLOW16 248 +#define R_SH_IMM_MEDLOW16_PCREL 249 + +/* Keep this the last entry. */ +#define R_SH_NUM 256 + +/* Additional s390 relocs */ + +#define R_390_NONE 0 /* No reloc. */ +#define R_390_8 1 /* Direct 8 bit. */ +#define R_390_12 2 /* Direct 12 bit. */ +#define R_390_16 3 /* Direct 16 bit. */ +#define R_390_32 4 /* Direct 32 bit. */ +#define R_390_PC32 5 /* PC relative 32 bit. */ +#define R_390_GOT12 6 /* 12 bit GOT offset. */ +#define R_390_GOT32 7 /* 32 bit GOT offset. */ +#define R_390_PLT32 8 /* 32 bit PC relative PLT address. */ +#define R_390_COPY 9 /* Copy symbol at runtime. */ +#define R_390_GLOB_DAT 10 /* Create GOT entry. */ +#define R_390_JMP_SLOT 11 /* Create PLT entry. */ +#define R_390_RELATIVE 12 /* Adjust by program base. */ +#define R_390_GOTOFF32 13 /* 32 bit offset to GOT. */ +#define R_390_GOTPC 14 /* 32 bit PC relative offset to GOT. */ +#define R_390_GOT16 15 /* 16 bit GOT offset. */ +#define R_390_PC16 16 /* PC relative 16 bit. */ +#define R_390_PC16DBL 17 /* PC relative 16 bit shifted by 1. */ +#define R_390_PLT16DBL 18 /* 16 bit PC rel. PLT shifted by 1. */ +#define R_390_PC32DBL 19 /* PC relative 32 bit shifted by 1. */ +#define R_390_PLT32DBL 20 /* 32 bit PC rel. PLT shifted by 1. */ +#define R_390_GOTPCDBL 21 /* 32 bit PC rel. GOT shifted by 1. */ +#define R_390_64 22 /* Direct 64 bit. */ +#define R_390_PC64 23 /* PC relative 64 bit. */ +#define R_390_GOT64 24 /* 64 bit GOT offset. */ +#define R_390_PLT64 25 /* 64 bit PC relative PLT address. */ +#define R_390_GOTENT 26 /* 32 bit PC rel. to GOT entry >> 1. */ +#define R_390_GOTOFF16 27 /* 16 bit offset to GOT. */ +#define R_390_GOTOFF64 28 /* 64 bit offset to GOT. */ +#define R_390_GOTPLT12 29 /* 12 bit offset to jump slot. */ +#define R_390_GOTPLT16 30 /* 16 bit offset to jump slot. */ +#define R_390_GOTPLT32 31 /* 32 bit offset to jump slot. */ +#define R_390_GOTPLT64 32 /* 64 bit offset to jump slot. */ +#define R_390_GOTPLTENT 33 /* 32 bit rel. offset to jump slot. */ +#define R_390_PLTOFF16 34 /* 16 bit offset from GOT to PLT. */ +#define R_390_PLTOFF32 35 /* 32 bit offset from GOT to PLT. */ +#define R_390_PLTOFF64 36 /* 16 bit offset from GOT to PLT. */ +#define R_390_TLS_LOAD 37 /* Tag for load insn in TLS code. */ +#define R_390_TLS_GDCALL 38 /* Tag for function call in general + dynamic TLS code. */ +#define R_390_TLS_LDCALL 39 /* Tag for function call in local + dynamic TLS code. */ +#define R_390_TLS_GD32 40 /* Direct 32 bit for general dynamic + thread local data. */ +#define R_390_TLS_GD64 41 /* Direct 64 bit for general dynamic + thread local data. */ +#define R_390_TLS_GOTIE12 42 /* 12 bit GOT offset for static TLS + block offset. */ +#define R_390_TLS_GOTIE32 43 /* 32 bit GOT offset for static TLS + block offset. */ +#define R_390_TLS_GOTIE64 44 /* 64 bit GOT offset for static TLS + block offset. */ +#define R_390_TLS_LDM32 45 /* Direct 32 bit for local dynamic + thread local data in LE code. */ +#define R_390_TLS_LDM64 46 /* Direct 64 bit for local dynamic + thread local data in LE code. */ +#define R_390_TLS_IE32 47 /* 32 bit address of GOT entry for + negated static TLS block offset. */ +#define R_390_TLS_IE64 48 /* 64 bit address of GOT entry for + negated static TLS block offset. */ +#define R_390_TLS_IEENT 49 /* 32 bit rel. offset to GOT entry for + negated static TLS block offset. */ +#define R_390_TLS_LE32 50 /* 32 bit negated offset relative to + static TLS block. */ +#define R_390_TLS_LE64 51 /* 64 bit negated offset relative to + static TLS block. */ +#define R_390_TLS_LDO32 52 /* 32 bit offset relative to TLS + block. */ +#define R_390_TLS_LDO64 53 /* 64 bit offset relative to TLS + block. */ +#define R_390_TLS_DTPMOD 54 /* ID of module containing symbol. */ +#define R_390_TLS_DTPOFF 55 /* Offset in TLS block. */ +#define R_390_TLS_TPOFF 56 /* Negated offset in static TLS + block. */ +#define R_390_20 57 /* Direct 20 bit. */ +#define R_390_GOT20 58 /* 20 bit GOT offset. */ +#define R_390_GOTPLT20 59 /* 20 bit offset to jump slot. */ +#define R_390_TLS_GOTIE20 60 /* 20 bit GOT offset for static TLS + block offset. */ +/* Keep this the last entry. */ +#define R_390_NUM 61 + + +/* CRIS flags. */ +#define EF_CRIS_VARIANT_MASK 0x0000000e +#define EF_CRIS_VARIANT_ANY_V0_V10 0x00000000 +#define EF_CRIS_VARIANT_V32 0x00000002 +#define EF_CRIS_VARIANT_COMMON_V10_V32 0x00000004 + +/* CRIS relocations. */ +#define R_CRIS_NONE 0 +#define R_CRIS_8 1 +#define R_CRIS_16 2 +#define R_CRIS_32 3 +#define R_CRIS_8_PCREL 4 +#define R_CRIS_16_PCREL 5 +#define R_CRIS_32_PCREL 6 +#define R_CRIS_GNU_VTINHERIT 7 +#define R_CRIS_GNU_VTENTRY 8 +#define R_CRIS_COPY 9 +#define R_CRIS_GLOB_DAT 10 +#define R_CRIS_JUMP_SLOT 11 +#define R_CRIS_RELATIVE 12 +#define R_CRIS_16_GOT 13 +#define R_CRIS_32_GOT 14 +#define R_CRIS_16_GOTPLT 15 +#define R_CRIS_32_GOTPLT 16 +#define R_CRIS_32_GOTREL 17 +#define R_CRIS_32_PLT_GOTREL 18 +#define R_CRIS_32_PLT_PCREL 19 + +/* Keep this the last entry. */ +#define R_CRIS_NUM 20 + + +/* AMD x86-64 relocations. */ +#define R_X86_64_NONE 0 /* No reloc */ +#define R_X86_64_64 1 /* Direct 64 bit */ +#define R_X86_64_PC32 2 /* PC relative 32 bit signed */ +#define R_X86_64_GOT32 3 /* 32 bit GOT entry */ +#define R_X86_64_PLT32 4 /* 32 bit PLT address */ +#define R_X86_64_COPY 5 /* Copy symbol at runtime */ +#define R_X86_64_GLOB_DAT 6 /* Create GOT entry */ +#define R_X86_64_JUMP_SLOT 7 /* Create PLT entry */ +#define R_X86_64_RELATIVE 8 /* Adjust by program base */ +#define R_X86_64_GOTPCREL 9 /* 32 bit signed PC relative + offset to GOT */ +#define R_X86_64_32 10 /* Direct 32 bit zero extended */ +#define R_X86_64_32S 11 /* Direct 32 bit sign extended */ +#define R_X86_64_16 12 /* Direct 16 bit zero extended */ +#define R_X86_64_PC16 13 /* 16 bit sign extended pc relative */ +#define R_X86_64_8 14 /* Direct 8 bit sign extended */ +#define R_X86_64_PC8 15 /* 8 bit sign extended pc relative */ +#define R_X86_64_DTPMOD64 16 /* ID of module containing symbol */ +#define R_X86_64_DTPOFF64 17 /* Offset in module's TLS block */ +#define R_X86_64_TPOFF64 18 /* Offset in initial TLS block */ +#define R_X86_64_TLSGD 19 /* 32 bit signed PC relative offset + to two GOT entries for GD symbol */ +#define R_X86_64_TLSLD 20 /* 32 bit signed PC relative offset + to two GOT entries for LD symbol */ +#define R_X86_64_DTPOFF32 21 /* Offset in TLS block */ +#define R_X86_64_GOTTPOFF 22 /* 32 bit signed PC relative offset + to GOT entry for IE symbol */ +#define R_X86_64_TPOFF32 23 /* Offset in initial TLS block */ + +#define R_X86_64_NUM 24 + + +/* AM33 relocations. */ +#define R_MN10300_NONE 0 /* No reloc. */ +#define R_MN10300_32 1 /* Direct 32 bit. */ +#define R_MN10300_16 2 /* Direct 16 bit. */ +#define R_MN10300_8 3 /* Direct 8 bit. */ +#define R_MN10300_PCREL32 4 /* PC-relative 32-bit. */ +#define R_MN10300_PCREL16 5 /* PC-relative 16-bit signed. */ +#define R_MN10300_PCREL8 6 /* PC-relative 8-bit signed. */ +#define R_MN10300_GNU_VTINHERIT 7 /* Ancient C++ vtable garbage... */ +#define R_MN10300_GNU_VTENTRY 8 /* ... collection annotation. */ +#define R_MN10300_24 9 /* Direct 24 bit. */ +#define R_MN10300_GOTPC32 10 /* 32-bit PCrel offset to GOT. */ +#define R_MN10300_GOTPC16 11 /* 16-bit PCrel offset to GOT. */ +#define R_MN10300_GOTOFF32 12 /* 32-bit offset from GOT. */ +#define R_MN10300_GOTOFF24 13 /* 24-bit offset from GOT. */ +#define R_MN10300_GOTOFF16 14 /* 16-bit offset from GOT. */ +#define R_MN10300_PLT32 15 /* 32-bit PCrel to PLT entry. */ +#define R_MN10300_PLT16 16 /* 16-bit PCrel to PLT entry. */ +#define R_MN10300_GOT32 17 /* 32-bit offset to GOT entry. */ +#define R_MN10300_GOT24 18 /* 24-bit offset to GOT entry. */ +#define R_MN10300_GOT16 19 /* 16-bit offset to GOT entry. */ +#define R_MN10300_COPY 20 /* Copy symbol at runtime. */ +#define R_MN10300_GLOB_DAT 21 /* Create GOT entry. */ +#define R_MN10300_JMP_SLOT 22 /* Create PLT entry. */ +#define R_MN10300_RELATIVE 23 /* Adjust by program base. */ + +#define R_MN10300_NUM 24 + + +/* M32R relocs. */ +#define R_M32R_NONE 0 /* No reloc. */ +#define R_M32R_16 1 /* Direct 16 bit. */ +#define R_M32R_32 2 /* Direct 32 bit. */ +#define R_M32R_24 3 /* Direct 24 bit. */ +#define R_M32R_10_PCREL 4 /* PC relative 10 bit shifted. */ +#define R_M32R_18_PCREL 5 /* PC relative 18 bit shifted. */ +#define R_M32R_26_PCREL 6 /* PC relative 26 bit shifted. */ +#define R_M32R_HI16_ULO 7 /* High 16 bit with unsigned low. */ +#define R_M32R_HI16_SLO 8 /* High 16 bit with signed low. */ +#define R_M32R_LO16 9 /* Low 16 bit. */ +#define R_M32R_SDA16 10 /* 16 bit offset in SDA. */ +#define R_M32R_GNU_VTINHERIT 11 +#define R_M32R_GNU_VTENTRY 12 +/* M32R relocs use SHT_RELA. */ +#define R_M32R_16_RELA 33 /* Direct 16 bit. */ +#define R_M32R_32_RELA 34 /* Direct 32 bit. */ +#define R_M32R_24_RELA 35 /* Direct 24 bit. */ +#define R_M32R_10_PCREL_RELA 36 /* PC relative 10 bit shifted. */ +#define R_M32R_18_PCREL_RELA 37 /* PC relative 18 bit shifted. */ +#define R_M32R_26_PCREL_RELA 38 /* PC relative 26 bit shifted. */ +#define R_M32R_HI16_ULO_RELA 39 /* High 16 bit with unsigned low */ +#define R_M32R_HI16_SLO_RELA 40 /* High 16 bit with signed low */ +#define R_M32R_LO16_RELA 41 /* Low 16 bit */ +#define R_M32R_SDA16_RELA 42 /* 16 bit offset in SDA */ +#define R_M32R_RELA_GNU_VTINHERIT 43 +#define R_M32R_RELA_GNU_VTENTRY 44 + +#define R_M32R_GOT24 48 /* 24 bit GOT entry */ +#define R_M32R_26_PLTREL 49 /* 26 bit PC relative to PLT shifted */ +#define R_M32R_COPY 50 /* Copy symbol at runtime */ +#define R_M32R_GLOB_DAT 51 /* Create GOT entry */ +#define R_M32R_JMP_SLOT 52 /* Create PLT entry */ +#define R_M32R_RELATIVE 53 /* Adjust by program base */ +#define R_M32R_GOTOFF 54 /* 24 bit offset to GOT */ +#define R_M32R_GOTPC24 55 /* 24 bit PC relative offset to GOT */ +#define R_M32R_GOT16_HI_ULO 56 /* High 16 bit GOT entry with unsigned + low */ +#define R_M32R_GOT16_HI_SLO 57 /* High 16 bit GOT entry with signed + low */ +#define R_M32R_GOT16_LO 58 /* Low 16 bit GOT entry */ +#define R_M32R_GOTPC_HI_ULO 59 /* High 16 bit PC relative offset to + GOT with unsigned low */ +#define R_M32R_GOTPC_HI_SLO 60 /* High 16 bit PC relative offset to + GOT with signed low */ +#define R_M32R_GOTPC_LO 61 /* Low 16 bit PC relative offset to + GOT */ +#define R_M32R_GOTOFF_HI_ULO 62 /* High 16 bit offset to GOT + with unsigned low */ +#define R_M32R_GOTOFF_HI_SLO 63 /* High 16 bit offset to GOT + with signed low */ +#define R_M32R_GOTOFF_LO 64 /* Low 16 bit offset to GOT */ +#define R_M32R_NUM 256 /* Keep this the last entry. */ + +/* i960 Relocations */ +#define R_960_NONE 0 +#define R_960_12 1 +#define R_960_32 2 +#define R_960_IP24 3 +#define R_960_SUB 4 +#define R_960_OPTCALL 5 +#define R_960_OPTCALLX 6 +#define R_960_OPTCALLXA 7 +/* Keep this the last entry. */ +#define R_960_NUM 8 + + +/* v850 relocations. */ +#define R_V850_NONE 0 +#define R_V850_9_PCREL 1 +#define R_V850_22_PCREL 2 +#define R_V850_HI16_S 3 +#define R_V850_HI16 4 +#define R_V850_LO16 5 +#define R_V850_32 6 +#define R_V850_16 7 +#define R_V850_8 8 +#define R_V850_SDA_16_16_OFFSET 9 /* For ld.b, st.b, set1, clr1, + not1, tst1, movea, movhi */ +#define R_V850_SDA_15_16_OFFSET 10 /* For ld.w, ld.h, ld.hu, st.w, st.h */ +#define R_V850_ZDA_16_16_OFFSET 11 /* For ld.b, st.b, set1, clr1, + not1, tst1, movea, movhi */ +#define R_V850_ZDA_15_16_OFFSET 12 /* For ld.w, ld.h, ld.hu, st.w, st.h */ +#define R_V850_TDA_6_8_OFFSET 13 /* For sst.w, sld.w */ +#define R_V850_TDA_7_8_OFFSET 14 /* For sst.h, sld.h */ +#define R_V850_TDA_7_7_OFFSET 15 /* For sst.b, sld.b */ +#define R_V850_TDA_16_16_OFFSET 16 /* For set1, clr1, not1, tst1, + movea, movhi */ +/* CYGNUS LOCAL v850e */ +#define R_V850_TDA_4_5_OFFSET 17 /* For sld.hu */ +#define R_V850_TDA_4_4_OFFSET 18 /* For sld.bu */ +#define R_V850_SDA_16_16_SPLIT_OFFSET 19 /* For ld.bu */ +#define R_V850_ZDA_16_16_SPLIT_OFFSET 20 /* For ld.bu */ +#define R_V850_CALLT_6_7_OFFSET 21 /* For callt */ +#define R_V850_CALLT_16_16_OFFSET 22 /* For callt */ +/* END CYGNUS LOCAL */ +#define R_V850_GNU_VTINHERIT 23 +#define R_V850_GNU_VTENTRY 24 +/* Keep this the last entry. */ +#define R_V850_NUM 25 + +/* Atmel AVR32 relocations. */ +#define R_AVR32_NONE 0 +#define R_AVR32_32 1 +#define R_AVR32_16 2 +#define R_AVR32_8 3 +#define R_AVR32_32_PCREL 4 +#define R_AVR32_16_PCREL 5 +#define R_AVR32_8_PCREL 6 +#define R_AVR32_DIFF32 7 +#define R_AVR32_DIFF16 8 +#define R_AVR32_DIFF8 9 +#define R_AVR32_GOT32 10 +#define R_AVR32_GOT16 11 +#define R_AVR32_GOT8 12 +#define R_AVR32_21S 13 +#define R_AVR32_16U 14 +#define R_AVR32_16S 15 +#define R_AVR32_8S 16 +#define R_AVR32_8S_EXT 17 +#define R_AVR32_22H_PCREL 18 +#define R_AVR32_18W_PCREL 19 +#define R_AVR32_16B_PCREL 20 +#define R_AVR32_16N_PCREL 21 +#define R_AVR32_14UW_PCREL 22 +#define R_AVR32_11H_PCREL 23 +#define R_AVR32_10UW_PCREL 24 +#define R_AVR32_9H_PCREL 25 +#define R_AVR32_9UW_PCREL 26 +#define R_AVR32_HI16 27 +#define R_AVR32_LO16 28 +#define R_AVR32_GOTPC 29 +#define R_AVR32_GOTCALL 30 +#define R_AVR32_LDA_GOT 31 +#define R_AVR32_GOT21S 32 +#define R_AVR32_GOT18SW 33 +#define R_AVR32_GOT16S 34 +#define R_AVR32_GOT7UW 35 +#define R_AVR32_32_CPENT 36 +#define R_AVR32_CPCALL 37 +#define R_AVR32_16_CP 38 +#define R_AVR32_9W_CP 39 +#define R_AVR32_RELATIVE 40 +#define R_AVR32_GLOB_DAT 41 +#define R_AVR32_JMP_SLOT 42 +#define R_AVR32_ALIGN 43 +#define R_AVR32_NUM 44 + +/* AVR32 dynamic tags */ +#define DT_AVR32_GOTSZ 0x70000001 /* Total size of GOT in bytes */ + +/* Renesas H8/300 Relocations */ +#define R_H8_NONE 0 +#define R_H8_DIR32 1 +#define R_H8_DIR32_28 2 +#define R_H8_DIR32_24 3 +#define R_H8_DIR32_16 4 +#define R_H8_DIR32U 6 +#define R_H8_DIR32U_28 7 +#define R_H8_DIR32U_24 8 +#define R_H8_DIR32U_20 9 +#define R_H8_DIR32U_16 10 +#define R_H8_DIR24 11 +#define R_H8_DIR24_20 12 +#define R_H8_DIR24_16 13 +#define R_H8_DIR24U 14 +#define R_H8_DIR24U_20 15 +#define R_H8_DIR24U_16 16 +#define R_H8_DIR16 17 +#define R_H8_DIR16U 18 +#define R_H8_DIR16S_32 19 +#define R_H8_DIR16S_28 20 +#define R_H8_DIR16S_24 21 +#define R_H8_DIR16S_20 22 +#define R_H8_DIR16S 23 +#define R_H8_DIR8 24 +#define R_H8_DIR8U 25 +#define R_H8_DIR8Z_32 26 +#define R_H8_DIR8Z_28 27 +#define R_H8_DIR8Z_24 28 +#define R_H8_DIR8Z_20 29 +#define R_H8_DIR8Z_16 30 +#define R_H8_PCREL16 31 +#define R_H8_PCREL8 32 +#define R_H8_BPOS 33 +#define R_H8_PCREL32 34 +#define R_H8_GOT32O 35 +#define R_H8_GOT16O 36 +#define R_H8_DIR16A8 59 +#define R_H8_DIR16R8 60 +#define R_H8_DIR24A8 61 +#define R_H8_DIR24R8 62 +#define R_H8_DIR32A16 63 +#define R_H8_ABS32 65 +#define R_H8_ABS32A16 127 +#define R_H8_NUM 128 + +/* NIOS relocations. */ +#define R_NIOS_NONE 0 +#define R_NIOS_32 1 /* A 32 bit absolute relocation.*/ +#define R_NIOS_LO16_LO5 2 /* A LO-16 5 bit absolute relocation. */ +#define R_NIOS_LO16_HI11 3 /* A LO-16 top 11 bit absolute relocation. */ +#define R_NIOS_HI16_LO5 4 /* A HI-16 5 bit absolute relocation. */ +#define R_NIOS_HI16_HI11 5 /* A HI-16 top 11 bit absolute relocation. */ +#define R_NIOS_PCREL6 6 /* A 6 bit relative relocation. */ +#define R_NIOS_PCREL8 7 /* An 8 bit relative relocation. */ +#define R_NIOS_PCREL11 8 /* An 11 bit relative relocation. */ +#define R_NIOS_16 9 /* A 16 bit absolute relocation. */ +#define R_NIOS_H_LO5 10 /* Low 5-bits of absolute relocation in halfwords. */ +#define R_NIOS_H_HI11 11 /* Top 11 bits of 16-bit absolute relocation in halfwords. */ +#define R_NIOS_H_XLO5 12 /* Low 5 bits of top 16-bits of 32-bit absolute relocation in halfwords. */ +#define R_NIOS_H_XHI11 13 /* Top 11 bits of top 16-bits of 32-bit absolute relocation in halfwords. */ +#define R_NIOS_H_16 14 /* Half-word @h value */ +#define R_NIOS_H_32 15 /* Word @h value */ +#define R_NIOS_GNU_VTINHERIT 200 /* GNU extension to record C++ vtable hierarchy */ +#define R_NIOS_GNU_VTENTRY 201 /* GNU extension to record C++ vtable member usage */ +/* Keep this the last entry. */ +#define R_NIOS_NUM 202 + +/* NIOS II relocations */ +#define R_NIOS2_NONE 0 +#define R_NIOS2_S16 1 +#define R_NIOS2_U16 2 +#define R_NIOS2_PCREL16 3 +#define R_NIOS2_CALL26 4 +#define R_NIOS2_IMM5 5 +#define R_NIOS2_CACHE_OPX 6 +#define R_NIOS2_IMM6 7 +#define R_NIOS2_IMM8 8 +#define R_NIOS2_HI16 9 +#define R_NIOS2_LO16 10 +#define R_NIOS2_HIADJ16 11 +#define R_NIOS2_BFD_RELOC_32 12 +#define R_NIOS2_BFD_RELOC_16 13 +#define R_NIOS2_BFD_RELOC_8 14 +#define R_NIOS2_GPREL 15 +#define R_NIOS2_GNU_VTINHERIT 16 +#define R_NIOS2_GNU_VTENTRY 17 +#define R_NIOS2_UJMP 18 +#define R_NIOS2_CJMP 19 +#define R_NIOS2_CALLR 20 +#define R_NIOS2_ALIGN 21 +/* Keep this the last entry. */ +#define R_NIOS2_NUM 22 + +/* Xtensa-specific declarations */ + +/* Xtensa values for the Dyn d_tag field. */ +#define DT_XTENSA_GOT_LOC_OFF (DT_LOPROC + 0) +#define DT_XTENSA_GOT_LOC_SZ (DT_LOPROC + 1) +#define DT_XTENSA_NUM 2 + +/* Xtensa relocations. */ +#define R_XTENSA_NONE 0 +#define R_XTENSA_32 1 +#define R_XTENSA_RTLD 2 +#define R_XTENSA_GLOB_DAT 3 +#define R_XTENSA_JMP_SLOT 4 +#define R_XTENSA_RELATIVE 5 +#define R_XTENSA_PLT 6 +#define R_XTENSA_OP0 8 +#define R_XTENSA_OP1 9 +#define R_XTENSA_OP2 10 +#define R_XTENSA_ASM_EXPAND 11 +#define R_XTENSA_ASM_SIMPLIFY 12 +#define R_XTENSA_GNU_VTINHERIT 15 +#define R_XTENSA_GNU_VTENTRY 16 +#define R_XTENSA_DIFF8 17 +#define R_XTENSA_DIFF16 18 +#define R_XTENSA_DIFF32 19 +#define R_XTENSA_SLOT0_OP 20 +#define R_XTENSA_SLOT1_OP 21 +#define R_XTENSA_SLOT2_OP 22 +#define R_XTENSA_SLOT3_OP 23 +#define R_XTENSA_SLOT4_OP 24 +#define R_XTENSA_SLOT5_OP 25 +#define R_XTENSA_SLOT6_OP 26 +#define R_XTENSA_SLOT7_OP 27 +#define R_XTENSA_SLOT8_OP 28 +#define R_XTENSA_SLOT9_OP 29 +#define R_XTENSA_SLOT10_OP 30 +#define R_XTENSA_SLOT11_OP 31 +#define R_XTENSA_SLOT12_OP 32 +#define R_XTENSA_SLOT13_OP 33 +#define R_XTENSA_SLOT14_OP 34 +#define R_XTENSA_SLOT0_ALT 35 +#define R_XTENSA_SLOT1_ALT 36 +#define R_XTENSA_SLOT2_ALT 37 +#define R_XTENSA_SLOT3_ALT 38 +#define R_XTENSA_SLOT4_ALT 39 +#define R_XTENSA_SLOT5_ALT 40 +#define R_XTENSA_SLOT6_ALT 41 +#define R_XTENSA_SLOT7_ALT 42 +#define R_XTENSA_SLOT8_ALT 43 +#define R_XTENSA_SLOT9_ALT 44 +#define R_XTENSA_SLOT10_ALT 45 +#define R_XTENSA_SLOT11_ALT 46 +#define R_XTENSA_SLOT12_ALT 47 +#define R_XTENSA_SLOT13_ALT 48 +#define R_XTENSA_SLOT14_ALT 49 +/* Keep this the last entry. */ +#define R_XTENSA_NUM 50 + +#ifdef __cplusplus +} +#endif + +#endif /* elf.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/endian.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/endian.h new file mode 100644 index 00000000..0ba73846 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/endian.h @@ -0,0 +1,96 @@ +/* Copyright (C) 1992, 1996, 1997, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _ENDIAN_H +#define _ENDIAN_H 1 + +#include + +/* Definitions for byte order, according to significance of bytes, + from low addresses to high addresses. The value is what you get by + putting '4' in the most significant byte, '3' in the second most + significant byte, '2' in the second least significant byte, and '1' + in the least significant byte, and then writing down one digit for + each byte, starting with the byte at the lowest address at the left, + and proceeding to the byte with the highest address at the right. */ + +#define __LITTLE_ENDIAN 1234 +#define __BIG_ENDIAN 4321 +#define __PDP_ENDIAN 3412 + +/* This file defines `__BYTE_ORDER' for the particular machine. */ +#include + +/* Some machines may need to use a different endianness for floating point + values. */ +#ifndef __FLOAT_WORD_ORDER +# define __FLOAT_WORD_ORDER __BYTE_ORDER +#endif + +#ifdef __USE_BSD +# define LITTLE_ENDIAN __LITTLE_ENDIAN +# define BIG_ENDIAN __BIG_ENDIAN +# define PDP_ENDIAN __PDP_ENDIAN +# define BYTE_ORDER __BYTE_ORDER +#endif + +#if __BYTE_ORDER == __LITTLE_ENDIAN +# define __LONG_LONG_PAIR(HI, LO) LO, HI +#elif __BYTE_ORDER == __BIG_ENDIAN +# define __LONG_LONG_PAIR(HI, LO) HI, LO +#endif + + +#ifdef __USE_BSD +/* Conversion interfaces. */ +# include + +# if __BYTE_ORDER == __LITTLE_ENDIAN +# define htobe16(x) __bswap_16 (x) +# define htole16(x) (x) +# define be16toh(x) __bswap_16 (x) +# define le16toh(x) (x) + +# define htobe32(x) __bswap_32 (x) +# define htole32(x) (x) +# define be32toh(x) __bswap_32 (x) +# define le32toh(x) (x) + +# define htobe64(x) __bswap_64 (x) +# define htole64(x) (x) +# define be64toh(x) __bswap_64 (x) +# define le64toh(x) (x) +# else +# define htobe16(x) (x) +# define htole16(x) __bswap_16 (x) +# define be16toh(x) (x) +# define le16toh(x) __bswap_16 (x) + +# define htobe32(x) (x) +# define htole32(x) __bswap_32 (x) +# define be32toh(x) (x) +# define le32toh(x) __bswap_32 (x) + +# define htobe64(x) (x) +# define htole64(x) __bswap_64 (x) +# define be64toh(x) (x) +# define le64toh(x) __bswap_64 (x) +# endif +#endif + +#endif /* endian.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/err.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/err.h new file mode 100644 index 00000000..413e1ab2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/err.h @@ -0,0 +1,62 @@ +/* 4.4BSD utility functions for error messages. + Copyright (C) 1995,1996,1997,1998,1999,2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _ERR_H +#define _ERR_H 1 + +#include + +#define __need___va_list +#include +#ifndef __GNUC_VA_LIST +# define __gnuc_va_list __ptr_t +#endif + +__BEGIN_DECLS + +/* Print "program: ", FORMAT, ": ", the standard error string for errno, + and a newline, on stderr. */ +extern void warn (__const char *__format, ...) + __attribute__ ((__format__ (__printf__, 1, 2))); +extern void vwarn (__const char *__format, __gnuc_va_list) + __attribute__ ((__format__ (__printf__, 1, 0))); +libc_hidden_proto(vwarn) + +/* Likewise, but without ": " and the standard error string. */ +extern void warnx (__const char *__format, ...) + __attribute__ ((__format__ (__printf__, 1, 2))); +extern void vwarnx (__const char *__format, __gnuc_va_list) + __attribute__ ((__format__ (__printf__, 1, 0))); +libc_hidden_proto(vwarnx) + +/* Likewise, and then exit with STATUS. */ +extern void err (int __status, __const char *__format, ...) + __attribute__ ((__noreturn__, __format__ (__printf__, 2, 3))); +extern void verr (int __status, __const char *__format, __gnuc_va_list) + __attribute__ ((__noreturn__, __format__ (__printf__, 2, 0))); +libc_hidden_proto(verr) +extern void errx (int __status, __const char *__format, ...) + __attribute__ ((__noreturn__, __format__ (__printf__, 2, 3))); +extern void verrx (int __status, __const char *, __gnuc_va_list) + __attribute__ ((__noreturn__, __format__ (__printf__, 2, 0))); +libc_hidden_proto(verrx) + +__END_DECLS + +#endif /* err.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/errno.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/errno.h new file mode 100644 index 00000000..7f63252d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/errno.h @@ -0,0 +1,89 @@ +/* Copyright (C) 1991,92,93,94,95,96,97,2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * ISO C99 Standard: 7.5 Errors + */ + +#ifndef _ERRNO_H + +/* The includer defined __need_Emath if he wants only the definitions + of EDOM and ERANGE, and not everything else. */ +#ifndef __need_Emath +# define _ERRNO_H 1 +# include +#endif + +__BEGIN_DECLS + +/* Get the error number constants from the system-specific file. + This file will test __need_Emath and _ERRNO_H. */ +#include +#undef __need_Emath + +#ifdef _ERRNO_H + +/* Declare the `errno' variable, unless it's defined as a macro by + bits/errno.h. This is the case in GNU, where it is a per-thread + variable. This redeclaration using the macro still works, but it + will be a function declaration without a prototype and may trigger + a -Wstrict-prototypes warning. */ +#ifndef errno +extern int errno; +#endif + +#if defined __USE_GNU && defined __UCLIBC_HAS_PROGRAM_INVOCATION_NAME__ + +/* The full and simple forms of the name with which the program was + invoked. These variables are set up automatically at startup based on + the value of ARGV[0] (this works only if you use GNU ld). */ +extern const char *program_invocation_name, *program_invocation_short_name; +#endif /* __USE_GNU */ +#endif /* _ERRNO_H */ + +__END_DECLS + +#if defined _LIBC && defined __UCLIBC_HAS_TLS__ +# if !defined NOT_IN_libc || defined IS_IN_libpthread +# undef errno +# ifndef NOT_IN_libc +# define errno __libc_errno +# else +# define errno errno /* For #ifndef errno tests. */ +# endif +extern __thread int errno attribute_tls_model_ie; +# endif +#endif + +#ifndef __set_errno +#define __set_errno(val) (errno = (val)) +#endif + +#endif /* _ERRNO_H */ + +/* The Hurd defines `error_t' as an enumerated type so + that printing `error_t' values in the debugger shows the names. We + might need this definition sometimes even if this file was included + before. */ +#if defined __USE_GNU || defined __need_error_t +# ifndef __error_t_defined +typedef int error_t; +# define __error_t_defined 1 +# endif +# undef __need_error_t +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/error.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/error.h new file mode 100644 index 00000000..b553caeb --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/error.h @@ -0,0 +1,52 @@ +/* Declaration for error-reporting function + Copyright (C) 1995, 1996, 1997, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _ERROR_H +#define _ERROR_H 1 + +#include + +__BEGIN_DECLS + +/* Print a message with `fprintf (stderr, FORMAT, ...)'; + if ERRNUM is nonzero, follow it with ": " and strerror (ERRNUM). + If STATUS is nonzero, terminate the program with `exit (STATUS)'. */ + +extern void error (int __status, int __errnum, const char *__format, ...) + __attribute__ ((__format__ (__printf__, 3, 4))); + +extern void error_at_line (int __status, int __errnum, const char *__fname, + unsigned int __lineno, const char *__format, ...) + __attribute__ ((__format__ (__printf__, 5, 6))); + +/* If NULL, error will flush stdout, then print on stderr the program + name, a colon and a space. Otherwise, error will call this + function without parameters instead. */ +extern void (*error_print_progname) (void); + +/* This variable is incremented each time `error' is called. */ +extern unsigned int error_message_count; + +/* Sometimes we want to have at most one error per line. This + variable controls whether this mode is selected or not. */ +extern int error_one_per_line; + +__END_DECLS + +#endif /* error.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/execinfo.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/execinfo.h new file mode 100644 index 00000000..c1614cc1 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/execinfo.h @@ -0,0 +1,44 @@ +/* Copyright (C) 1998, 1999, 2004, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _EXECINFO_H +#define _EXECINFO_H 1 + +#include + +__BEGIN_DECLS + +/* Store up to SIZE return address of the current program state in + ARRAY and return the exact number of values stored. */ +extern int backtrace (void **__array, int __size) __nonnull ((1)); + + +/* Return names of functions from the backtrace list in ARRAY in a newly + malloc()ed memory block. */ +extern char **backtrace_symbols (void *__const *__array, int __size) + __THROW __nonnull ((1)); + + +/* This function is similar to backtrace_symbols() but it writes the result + immediately to a file. */ +extern void backtrace_symbols_fd (void *__const *__array, int __size, int __fd) + __THROW __nonnull ((1)); + +__END_DECLS + +#endif /* execinfo.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/fcntl.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/fcntl.h new file mode 100644 index 00000000..3a987346 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/fcntl.h @@ -0,0 +1,241 @@ +/* Copyright (C) 1991,1992,1994-2001,2003,2004,2005,2006,2007, 2009 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * POSIX Standard: 6.5 File Control Operations + */ + +#ifndef _FCNTL_H +#define _FCNTL_H 1 + +#include + +/* This must be early so can define types winningly. */ +__BEGIN_DECLS + +/* Get the definitions of O_*, F_*, FD_*: all the + numbers and flag bits for `open', `fcntl', et al. */ +#include + +/* For XPG all symbols from should also be available. */ +#ifdef __USE_XOPEN +# include +#endif + +#ifdef __USE_MISC +# ifndef R_OK /* Verbatim from . Ugh. */ +/* Values for the second argument to access. + These may be OR'd together. */ +# define R_OK 4 /* Test for read permission. */ +# define W_OK 2 /* Test for write permission. */ +# define X_OK 1 /* Test for execute permission. */ +# define F_OK 0 /* Test for existence. */ +# endif +#endif /* Use misc. */ + +/* XPG wants the following symbols. */ +#ifdef __USE_XOPEN /* has the same definitions. */ +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_END 2 /* Seek from end of file. */ +#endif /* XPG */ + +#ifdef __USE_ATFILE +# define AT_FDCWD -100 /* Special value used to indicate + the *at functions should use the + current working directory. */ +# define AT_SYMLINK_NOFOLLOW 0x100 /* Do not follow symbolic links. */ +# define AT_REMOVEDIR 0x200 /* Remove directory instead of + unlinking file. */ +# define AT_SYMLINK_FOLLOW 0x400 /* Follow symbolic links. */ +# define AT_EACCESS 0x200 /* Test access permitted for + effective IDs, not real IDs. */ +#endif + +/* Do the file control operation described by CMD on FD. + The remaining arguments are interpreted depending on CMD. + + This function is a cancellation point and therefore not marked with + __THROW. */ +#if !defined(__USE_FILE_OFFSET64) || defined(__LP64__) +extern int fcntl (int __fd, int __cmd, ...); +libc_hidden_proto(fcntl) +#else +# ifdef __REDIRECT +extern int __REDIRECT (fcntl, (int __fd, int __cmd, ...), fcntl64); +# else +# define fcntl fcntl64 +# endif +#endif +#if defined(__USE_LARGEFILE64) && !defined(__LP64__) +extern int fcntl64 (int __fd, int __cmd, ...); +libc_hidden_proto(fcntl64) +#endif + +/* Open FILE and return a new file descriptor for it, or -1 on error. + OFLAG determines the type of access used. If O_CREAT is on OFLAG, + the third argument is taken as a `mode_t', the mode of the created file. + + This function is a cancellation point and therefore not marked with + __THROW. */ +#ifndef __USE_FILE_OFFSET64 +extern int open (__const char *__file, int __oflag, ...) __nonnull ((1)); +libc_hidden_proto(open) +#else +# ifdef __REDIRECT +extern int __REDIRECT (open, (__const char *__file, int __oflag, ...), open64) + __nonnull ((1)); +# else +# define open open64 +# endif +#endif +#ifdef __USE_LARGEFILE64 +extern int open64 (__const char *__file, int __oflag, ...) __nonnull ((1)); +libc_hidden_proto(open64) +#endif + +#ifdef __USE_ATFILE +/* Similar to `open' but a relative path name is interpreted relative to + the directory for which FD is a descriptor. + + NOTE: some other `openat' implementation support additional functionality + through this interface, especially using the O_XATTR flag. This is not + yet supported here. + + This function is a cancellation point and therefore not marked with + __THROW. */ +# ifndef __USE_FILE_OFFSET64 +extern int openat (int __fd, __const char *__file, int __oflag, ...) + __nonnull ((2)); +libc_hidden_proto(openat) +# else +# ifdef __REDIRECT +extern int __REDIRECT (openat, (int __fd, __const char *__file, int __oflag, + ...), openat64) __nonnull ((2)); +# else +# define openat openat64 +# endif +# endif + +extern int openat64 (int __fd, __const char *__file, int __oflag, ...) + __nonnull ((2)); +libc_hidden_proto(openat64) +#endif + +/* Create and open FILE, with mode MODE. This takes an `int' MODE + argument because that is what `mode_t' will be widened to. + + This function is a cancellation point and therefore not marked with + __THROW. */ +#ifndef __USE_FILE_OFFSET64 +extern int creat (__const char *__file, __mode_t __mode) __nonnull ((1)); +#else +# ifdef __REDIRECT +extern int __REDIRECT (creat, (__const char *__file, __mode_t __mode), + creat64) __nonnull ((1)); +# else +# define creat creat64 +# endif +#endif +#ifdef __USE_LARGEFILE64 +extern int creat64 (__const char *__file, __mode_t __mode) __nonnull ((1)); +#endif + +#if !defined F_LOCK && (defined __USE_MISC || (defined __USE_XOPEN_EXTENDED \ + && !defined __USE_POSIX)) +/* NOTE: These declarations also appear in ; be sure to keep both + files consistent. Some systems have them there and some here, and some + software depends on the macros being defined without including both. */ + +/* `lockf' is a simpler interface to the locking facilities of `fcntl'. + LEN is always relative to the current file position. + The CMD argument is one of the following. */ + +# define F_ULOCK 0 /* Unlock a previously locked region. */ +# define F_LOCK 1 /* Lock a region for exclusive use. */ +# define F_TLOCK 2 /* Test and lock a region for exclusive use. */ +# define F_TEST 3 /* Test a region for other processes locks. */ + +# ifndef __USE_FILE_OFFSET64 +extern int lockf (int __fd, int __cmd, __off_t __len); +libc_hidden_proto(lockf) +# else +# ifdef __REDIRECT +extern int __REDIRECT (lockf, (int __fd, int __cmd, __off64_t __len), lockf64); +# else +# define lockf lockf64 +# endif +# endif +# ifdef __USE_LARGEFILE64 +extern int lockf64 (int __fd, int __cmd, __off64_t __len); +libc_hidden_proto(lockf64) +# endif +#endif + +#if defined __USE_XOPEN2K && defined __UCLIBC_HAS_ADVANCED_REALTIME__ +/* Advice the system about the expected behaviour of the application with + respect to the file associated with FD. */ +# ifndef __USE_FILE_OFFSET64 +extern int posix_fadvise (int __fd, __off_t __offset, __off_t __len, + int __advise) __THROW; +# else +# ifdef __REDIRECT_NTH +extern int __REDIRECT_NTH (posix_fadvise, (int __fd, __off64_t __offset, + __off64_t __len, int __advise), + posix_fadvise64); +# else +# define posix_fadvise posix_fadvise64 +# endif +# endif +# ifdef __USE_LARGEFILE64 +extern int posix_fadvise64 (int __fd, __off64_t __offset, __off64_t __len, + int __advise) __THROW; +# endif + +#endif + +#if 0 /* && defined __UCLIBC_HAS_ADVANCED_REALTIME__ */ + +/* FIXME -- uClibc should probably implement these... */ + +/* Reserve storage for the data of the file associated with FD. + + This function is a possible cancellation points and therefore not + marked with __THROW. */ +# ifndef __USE_FILE_OFFSET64 +extern int posix_fallocate (int __fd, __off_t __offset, __off_t __len); +# else +# ifdef __REDIRECT +extern int __REDIRECT (posix_fallocate, (int __fd, __off64_t __offset, + __off64_t __len), + posix_fallocate64); +# else +# define posix_fallocate posix_fallocate64 +# endif +# endif +# ifdef __USE_LARGEFILE64 +extern int posix_fallocate64 (int __fd, __off64_t __offset, __off64_t __len); +# endif +#endif + +extern int __fcntl_nocancel (int fd, int cmd, ...); + +__END_DECLS + +#endif /* fcntl.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/features.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/features.h new file mode 100644 index 00000000..2d1de525 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/features.h @@ -0,0 +1,452 @@ +/* Copyright (C) 1991-1993,1995-2006,2007,2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FEATURES_H +#define _FEATURES_H 1 + +#ifndef _GNU_SOURCE +# define _GNU_SOURCE 1 +#endif + +/* These are defined by the user (or the compiler) + to specify the desired environment: + + __STRICT_ANSI__ ISO Standard C. + _ISOC99_SOURCE Extensions to ISO C89 from ISO C99. + _POSIX_SOURCE IEEE Std 1003.1. + _POSIX_C_SOURCE If ==1, like _POSIX_SOURCE; if >=2 add IEEE Std 1003.2; + if >=199309L, add IEEE Std 1003.1b-1993; + if >=199506L, add IEEE Std 1003.1c-1995; + if >=200112L, all of IEEE 1003.1-2004 + if >=200809L, all of IEEE 1003.1-2008 + _XOPEN_SOURCE Includes POSIX and XPG things. Set to 500 if + Single Unix conformance is wanted, to 600 for the + sixth revision, to 700 for the seventh revision. + _XOPEN_SOURCE_EXTENDED XPG things and X/Open Unix extensions. + _LARGEFILE_SOURCE Some more functions for correct standard I/O. + _LARGEFILE64_SOURCE Additional functionality from LFS for large files. + _FILE_OFFSET_BITS=N Select default filesystem interface. + _BSD_SOURCE ISO C, POSIX, and 4.3BSD things. + _SVID_SOURCE ISO C, POSIX, and SVID things. + _ATFILE_SOURCE Additional *at interfaces. + _GNU_SOURCE All of the above, plus GNU extensions. + _REENTRANT Select additionally reentrant object. + _THREAD_SAFE Same as _REENTRANT, often used by other systems. + _FORTIFY_SOURCE If set to numeric value > 0 additional security + measures are defined, according to level. + + The `-ansi' switch to the GNU C compiler defines __STRICT_ANSI__. + If none of these are defined, the default is to have _SVID_SOURCE, + _BSD_SOURCE, and _POSIX_SOURCE set to one and _POSIX_C_SOURCE set to + 200112L. If more than one of these are defined, they accumulate. + For example __STRICT_ANSI__, _POSIX_SOURCE and _POSIX_C_SOURCE + together give you ISO C, 1003.1, and 1003.2, but nothing else. + + These are defined by this file and are used by the + header files to decide what to declare or define: + + __USE_ISOC99 Define ISO C99 things. + __USE_ISOC95 Define ISO C90 AMD1 (C95) things. + __USE_POSIX Define IEEE Std 1003.1 things. + __USE_POSIX2 Define IEEE Std 1003.2 things. + __USE_POSIX199309 Define IEEE Std 1003.1, and .1b things. + __USE_POSIX199506 Define IEEE Std 1003.1, .1b, .1c and .1i things. + __USE_XOPEN Define XPG things. + __USE_XOPEN_EXTENDED Define X/Open Unix things. + __USE_UNIX98 Define Single Unix V2 things. + __USE_XOPEN2K Define XPG6 things. + __USE_XOPEN2K8 Define XPG7 things. + __USE_LARGEFILE Define correct standard I/O things. + __USE_LARGEFILE64 Define LFS things with separate names. + __USE_FILE_OFFSET64 Define 64bit interface as default. + __USE_BSD Define 4.3BSD things. + __USE_SVID Define SVID things. + __USE_MISC Define things common to BSD and System V Unix. + __USE_ATFILE Define *at interfaces and AT_* constants for them. + __USE_GNU Define GNU extensions. + __USE_REENTRANT Define reentrant/thread-safe *_r functions. + __USE_FORTIFY_LEVEL Additional security measures used, according to level. + __FAVOR_BSD Favor 4.3BSD things in cases of conflict. + + The macros `__GNU_LIBRARY__', `__GLIBC__', and `__GLIBC_MINOR__' are + defined by this file unconditionally. `__GNU_LIBRARY__' is provided + only for compatibility. All new code should use the other symbols + to test for features. + + All macros listed above as possibly being defined by this file are + explicitly undefined if they are not explicitly defined. + Feature-test macros that are not defined by the user or compiler + but are implied by the other feature-test macros defined (or by the + lack of any definitions) are defined by the file. */ + + +/* Undefine everything, so we get a clean slate. */ +#undef __USE_ISOC99 +#undef __USE_ISOC95 +#undef __USE_POSIX +#undef __USE_POSIX2 +#undef __USE_POSIX199309 +#undef __USE_POSIX199506 +#undef __USE_XOPEN +#undef __USE_XOPEN_EXTENDED +#undef __USE_UNIX98 +#undef __USE_XOPEN2K +#undef __USE_XOPEN2K8 +#undef __USE_LARGEFILE +#undef __USE_LARGEFILE64 +#undef __USE_FILE_OFFSET64 +#undef __USE_BSD +#undef __USE_SVID +#undef __USE_MISC +#undef __USE_ATFILE +#undef __USE_GNU +#undef __USE_REENTRANT +#undef __USE_FORTIFY_LEVEL +#undef __FAVOR_BSD +#undef __KERNEL_STRICT_NAMES + +/* Suppress kernel-name space pollution unless user expressedly asks + for it. */ +#ifndef _LOOSE_KERNEL_NAMES +# define __KERNEL_STRICT_NAMES +#endif + +/* Always use ISO C things. */ +#define __USE_ANSI 1 + +/* Convenience macros to test the versions of glibc and gcc. + Use them like this: + #if __GNUC_PREREQ (2,8) + ... code requiring gcc 2.8 or later ... + #endif + Note - they won't work for gcc1 or glibc1, since the _MINOR macros + were not defined then. */ +#if defined __GNUC__ && defined __GNUC_MINOR__ +# define __GNUC_PREREQ(maj, min) \ + ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min)) +#else +# define __GNUC_PREREQ(maj, min) 0 +#endif + + +/* If _BSD_SOURCE was defined by the user, favor BSD over POSIX. */ +#if defined _BSD_SOURCE && \ + !(defined _POSIX_SOURCE || defined _POSIX_C_SOURCE || \ + defined _XOPEN_SOURCE || defined _XOPEN_SOURCE_EXTENDED || \ + defined _GNU_SOURCE || defined _SVID_SOURCE) +# define __FAVOR_BSD 1 +#endif + +/* If _GNU_SOURCE was defined by the user, turn on all the other features. */ +#ifdef _GNU_SOURCE +# undef _ISOC99_SOURCE +# define _ISOC99_SOURCE 1 +# undef _POSIX_SOURCE +# define _POSIX_SOURCE 1 +# undef _POSIX_C_SOURCE +# define _POSIX_C_SOURCE 200809L +# undef _XOPEN_SOURCE +# define _XOPEN_SOURCE 700 +# undef _XOPEN_SOURCE_EXTENDED +# define _XOPEN_SOURCE_EXTENDED 1 +# undef _LARGEFILE64_SOURCE +# define _LARGEFILE64_SOURCE 1 +# undef _BSD_SOURCE +# define _BSD_SOURCE 1 +# undef _SVID_SOURCE +# define _SVID_SOURCE 1 +# undef _ATFILE_SOURCE +# define _ATFILE_SOURCE 1 +#endif + +/* This macro indicates that the installed library is uClibc. Use + * __UCLIBC_MAJOR__ and __UCLIBC_MINOR__ to test for the features in + * specific releases. */ +#define __UCLIBC__ 1 + +#ifdef __UCLIBC__ +/* Load up the current set of uClibc supported features along + * with the current uClibc major and minor version numbers. + * For uClibc release 0.9.26, these numbers would be: + * #define __UCLIBC_MAJOR__ 0 + * #define __UCLIBC_MINOR__ 9 + * #define __UCLIBC_SUBLEVEL__ 26 + */ +# define __need_uClibc_config_h +# include +# undef __need_uClibc_config_h + +/* For uClibc, always optimize for size -- this should disable + * a lot of expensive inlining... + * TODO: this is wrong! __OPTIMIZE_SIZE__ is an indicator of + * gcc -Os compile. We should not mess with compiler inlines. + * We should instead disable __USE_EXTERN_INLINES unconditionally, + * or maybe actually audit and test uclibc to work correctly + * with __USE_EXTERN_INLINES on. + */ +# define __OPTIMIZE_SIZE__ 1 + +/* disable unsupported features */ +# undef _FORTIFY_SOURCE +# undef __LDBL_COMPAT + +# ifndef __UCLIBC_HAS_THREADS__ +# if defined _REENTRANT || defined _THREAD_SAFE +# warning requested reentrant code, but thread support was disabled +# undef _REENTRANT +# undef _THREAD_SAFE +# endif +# endif + +# ifndef __UCLIBC_HAS_LFS__ +# undef _LARGEFILE64_SOURCE +/* NOTE: This is probably incorrect on a 64-bit arch... */ +# if defined _FILE_OFFSET_BITS && _FILE_OFFSET_BITS == 64 +# error It appears you have defined _FILE_OFFSET_BITS=64. Unfortunately, \ +uClibc was built without large file support enabled. +# endif +# elif defined __BCC__ +# error BCC does not support LFS, please disable it +# endif +#endif /* __UCLIBC__ */ + +/* If nothing (other than _GNU_SOURCE) is defined, + define _BSD_SOURCE and _SVID_SOURCE. */ +#if (!defined __STRICT_ANSI__ && !defined _ISOC99_SOURCE && \ + !defined _POSIX_SOURCE && !defined _POSIX_C_SOURCE && \ + !defined _XOPEN_SOURCE && !defined _XOPEN_SOURCE_EXTENDED && \ + !defined _BSD_SOURCE && !defined _SVID_SOURCE) +# define _BSD_SOURCE 1 +# define _SVID_SOURCE 1 +#endif + +/* This is to enable the ISO C99 extension. Also recognize the old macro + which was used prior to the standard acceptance. This macro will + eventually go away and the features enabled by default once the ISO C99 + standard is widely adopted. */ +#if (defined _ISOC99_SOURCE || defined _ISOC9X_SOURCE \ + || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L)) +# define __USE_ISOC99 1 +#endif + +/* This is to enable the ISO C90 Amendment 1:1995 extension. */ +#if (defined _ISOC99_SOURCE || defined _ISOC9X_SOURCE \ + || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199409L)) +# define __USE_ISOC95 1 +#endif + +/* If none of the ANSI/POSIX macros are defined, use POSIX.1 and POSIX.2 + (and IEEE Std 1003.1b-1993 unless _XOPEN_SOURCE is defined). */ +#if ((!defined __STRICT_ANSI__ || (_XOPEN_SOURCE - 0) >= 500) && \ + !defined _POSIX_SOURCE && !defined _POSIX_C_SOURCE) +# define _POSIX_SOURCE 1 +# if defined _XOPEN_SOURCE && (_XOPEN_SOURCE - 0) < 500 +# define _POSIX_C_SOURCE 2 +# elif defined _XOPEN_SOURCE && (_XOPEN_SOURCE - 0) < 600 +# define _POSIX_C_SOURCE 199506L +# elif defined _XOPEN_SOURCE && (_XOPEN_SOURCE - 0) < 700 +# define _POSIX_C_SOURCE 200112L +# else +# define _POSIX_C_SOURCE 200809L +# endif +# define __USE_POSIX_IMPLICITLY 1 +#endif + +#if defined _POSIX_SOURCE || _POSIX_C_SOURCE >= 1 || defined _XOPEN_SOURCE +# define __USE_POSIX 1 +#endif + +#if defined _POSIX_C_SOURCE && _POSIX_C_SOURCE >= 2 || defined _XOPEN_SOURCE +# define __USE_POSIX2 1 +#endif + +#if (_POSIX_C_SOURCE - 0) >= 199309L +# define __USE_POSIX199309 1 +#endif + +#if (_POSIX_C_SOURCE - 0) >= 199506L +# define __USE_POSIX199506 1 +#endif + +#if (_POSIX_C_SOURCE - 0) >= 200112L +# define __USE_XOPEN2K 1 +# undef __USE_ISOC99 +# define __USE_ISOC99 1 +#endif + +#if (_POSIX_C_SOURCE - 0) >= 200809L +# define __USE_XOPEN2K8 1 +# undef _ATFILE_SOURCE +# define _ATFILE_SOURCE 1 +#endif + +#ifdef _XOPEN_SOURCE +# define __USE_XOPEN 1 +# if (_XOPEN_SOURCE - 0) >= 500 +# define __USE_XOPEN_EXTENDED 1 +# define __USE_UNIX98 1 +# undef _LARGEFILE_SOURCE +# define _LARGEFILE_SOURCE 1 +# if (_XOPEN_SOURCE - 0) >= 600 +# if (_XOPEN_SOURCE - 0) >= 700 +# define __USE_XOPEN2K8 1 +# endif +# define __USE_XOPEN2K 1 +# undef __USE_ISOC99 +# define __USE_ISOC99 1 +# endif +# else +# ifdef _XOPEN_SOURCE_EXTENDED +# define __USE_XOPEN_EXTENDED 1 +# endif +# endif +#endif + +#ifdef _LARGEFILE_SOURCE +# define __USE_LARGEFILE 1 +#endif + +#ifdef _LARGEFILE64_SOURCE +# define __USE_LARGEFILE64 1 +#endif + +#if defined _FILE_OFFSET_BITS && _FILE_OFFSET_BITS == 64 +# define __USE_FILE_OFFSET64 1 +#endif + +#if defined _BSD_SOURCE || defined _SVID_SOURCE +# define __USE_MISC 1 +#endif + +#ifdef _BSD_SOURCE +# define __USE_BSD 1 +#endif + +#ifdef _SVID_SOURCE +# define __USE_SVID 1 +#endif + +#ifdef _ATFILE_SOURCE +# define __USE_ATFILE 1 +#endif + +#ifdef _GNU_SOURCE +# define __USE_GNU 1 +#endif + +#if defined _REENTRANT || defined _THREAD_SAFE +# define __USE_REENTRANT 1 +#endif + +#if defined _FORTIFY_SOURCE && _FORTIFY_SOURCE > 0 \ + && __GNUC_PREREQ (4, 1) && defined __OPTIMIZE__ && __OPTIMIZE__ > 0 +# if _FORTIFY_SOURCE > 1 +# define __USE_FORTIFY_LEVEL 2 +# else +# define __USE_FORTIFY_LEVEL 1 +# endif +#else +# define __USE_FORTIFY_LEVEL 0 +#endif + +/* We do support the IEC 559 math functionality, real and complex. */ +#ifdef __UCLIBC_HAS_FLOATS__ +#define __STDC_IEC_559__ 1 +#define __STDC_IEC_559_COMPLEX__ 1 +#endif + +#ifdef __UCLIBC_HAS_WCHAR__ +/* wchar_t uses ISO 10646-1 (2nd ed., published 2000-09-15) / Unicode 3.1. */ +#define __STDC_ISO_10646__ 200009L +#endif + +/* There is an unwholesomely huge amount of code out there that depends on the + * presence of GNU libc header files. We have GNU libc header files. So here + * we commit a horrible sin. At this point, we _lie_ and claim to be GNU libc + * to make things like /usr/include/linux/socket.h and lots of apps work as + * their developers intended. This is IMHO, pardonable, since these defines + * are not really intended to check for the presence of a particular library, + * but rather are used to define an _interface_. */ +#if !defined __FORCE_NOGLIBC && (!defined _LIBC || defined __FORCE_GLIBC) +/* This macro indicates that the installed library is the GNU C Library. + For historic reasons the value now is 6 and this will stay from now + on. The use of this variable is deprecated. */ +/* uClibc WARNING: leave these aligned to the left, don't put a space after '#', else + * broken apps could fail the check. */ +#undef __GNU_LIBRARY__ +#define __GNU_LIBRARY__ 6 + +/* Major and minor version number of the GNU C library package. Use + these macros to test for features in specific releases. */ +/* Don't do it, if you want to keep uClibc happy. */ +#define __GLIBC__ 2 +#define __GLIBC_MINOR__ 2 +#endif + +#define __GLIBC_PREREQ(maj, min) \ + ((__GLIBC__ << 16) + __GLIBC_MINOR__ >= ((maj) << 16) + (min)) + +#ifndef __UCLIBC__ +/* Decide whether a compiler supports the long long datatypes. */ +#if defined __GNUC__ \ + || (defined __PGI && defined __i386__ ) \ + || (defined __INTEL_COMPILER && (defined __i386__ || defined __ia64__)) \ + || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L) +# define __GLIBC_HAVE_LONG_LONG 1 +#endif +#endif + +/* This is here only because every header file already includes this one. */ +#ifndef __ASSEMBLER__ +# ifndef _SYS_CDEFS_H +# include +# endif + +/* If we don't have __REDIRECT, prototypes will be missing if + __USE_FILE_OFFSET64 but not __USE_LARGEFILE[64]. */ +# if defined __USE_FILE_OFFSET64 && !defined __REDIRECT +# define __USE_LARGEFILE 1 +# ifdef __UCLIBC_HAS_LFS__ +# define __USE_LARGEFILE64 1 +# endif +# endif + +#endif /* !ASSEMBLER */ + +/* Decide whether we can, and are willing to define extern inline + * functions in headers, even if this results in a slightly bigger + * code for user programs built against uclibc. + * Enabled only in -O2 compiles, not -Os. + * uclibc itself is usually built without __USE_EXTERN_INLINES, + * remove "&& !defined __OPTIMIZE_SIZE__" part to do otherwise. + */ +#if __GNUC_PREREQ (2, 7) && defined __OPTIMIZE__ \ + && !defined __OPTIMIZE_SIZE__ && !defined __NO_INLINE__ \ + && (defined __extern_inline || defined __GNUC_GNU_INLINE__) +# define __USE_EXTERN_INLINES 1 +#endif + +#ifdef _LIBC +# ifdef __UCLIBC_HAS_LFS__ +# undef _FILE_OFFSET_BITS +# undef __USE_FILE_OFFSET64 +# endif +# include +#endif + +#endif /* features.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/fenv.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/fenv.h new file mode 100644 index 00000000..8a06f024 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/fenv.h @@ -0,0 +1,136 @@ +/* Copyright (C) 1997, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * ISO C99 7.6: Floating-point environment + */ + +#ifndef _FENV_H +#define _FENV_H 1 + +#include + +/* Get the architecture dependend definitions. The following definitions + are expected to be done: + + fenv_t type for object representing an entire floating-point + environment + + FE_DFL_ENV macro of type pointer to fenv_t to be used as the argument + to functions taking an argument of type fenv_t; in this + case the default environment will be used + + fexcept_t type for object representing the floating-point exception + flags including status associated with the flags + + The following macros are defined iff the implementation supports this + kind of exception. + FE_INEXACT inexact result + FE_DIVBYZERO division by zero + FE_UNDERFLOW result not representable due to underflow + FE_OVERFLOW result not representable due to overflow + FE_INVALID invalid operation + + FE_ALL_EXCEPT bitwise OR of all supported exceptions + + The next macros are defined iff the appropriate rounding mode is + supported by the implementation. + FE_TONEAREST round to nearest + FE_UPWARD round toward +Inf + FE_DOWNWARD round toward -Inf + FE_TOWARDZERO round toward 0 +*/ +#include + +__BEGIN_DECLS + +/* Floating-point exception handling. */ + +/* Clear the supported exceptions represented by EXCEPTS. */ +extern int feclearexcept (int __excepts) __THROW; + +/* Store implementation-defined representation of the exception flags + indicated by EXCEPTS in the object pointed to by FLAGP. */ +extern int fegetexceptflag (fexcept_t *__flagp, int __excepts) __THROW; + +/* Raise the supported exceptions represented by EXCEPTS. */ +extern int feraiseexcept (int __excepts) __THROW; + +/* Set complete status for exceptions indicated by EXCEPTS according to + the representation in the object pointed to by FLAGP. */ +extern int fesetexceptflag (__const fexcept_t *__flagp, int __excepts) __THROW; + +/* Determine which of subset of the exceptions specified by EXCEPTS are + currently set. */ +extern int fetestexcept (int __excepts) __THROW; + + +/* Rounding control. */ + +/* Get current rounding direction. */ +extern int fegetround (void) __THROW; + +/* Establish the rounding direction represented by ROUND. */ +extern int fesetround (int __rounding_direction) __THROW; + + +/* Floating-point environment. */ + +/* Store the current floating-point environment in the object pointed + to by ENVP. */ +extern int fegetenv (fenv_t *__envp) __THROW; + +/* Save the current environment in the object pointed to by ENVP, clear + exception flags and install a non-stop mode (if available) for all + exceptions. */ +extern int feholdexcept (fenv_t *__envp) __THROW; + +/* Establish the floating-point environment represented by the object + pointed to by ENVP. */ +extern int fesetenv (__const fenv_t *__envp) __THROW; + +/* Save current exceptions in temporary storage, install environment + represented by object pointed to by ENVP and raise exceptions + according to saved exceptions. */ +extern int feupdateenv (__const fenv_t *__envp) __THROW; + + +/* Include optimization. */ +#ifdef __OPTIMIZE__ +# include +#endif + +#ifdef __USE_GNU + +/* Enable individual exceptions. Will not enable more exceptions than + EXCEPTS specifies. Returns the previous enabled exceptions if all + exceptions are successfully set, otherwise returns -1. */ +extern int feenableexcept (int __excepts) __THROW; + +/* Disable individual exceptions. Will not disable more exceptions than + EXCEPTS specifies. Returns the previous enabled exceptions if all + exceptions are successfully disabled, otherwise returns -1. */ +extern int fedisableexcept (int __excepts) __THROW; + +/* Return enabled exceptions. */ +extern int fegetexcept (void) __THROW; +#endif + +__END_DECLS + +#endif /* fenv.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/fnmatch.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/fnmatch.h new file mode 100644 index 00000000..9178706f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/fnmatch.h @@ -0,0 +1,73 @@ +/* Copyright (C) 1991-93,96,97,98,99,2001,2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FNMATCH_H +#define _FNMATCH_H 1 + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef const +# if (defined __STDC__ && __STDC__) || defined __cplusplus +# define __const const +# else +# define __const +# endif +#endif + +/* We #undef these before defining them because some losing systems + (HP-UX A.08.07 for example) define these in . */ +#undef FNM_PATHNAME +#undef FNM_NOESCAPE +#undef FNM_PERIOD + +/* Bits set in the FLAGS argument to `fnmatch'. */ +#define FNM_PATHNAME (1 << 0) /* No wildcard can ever match `/'. */ +#define FNM_NOESCAPE (1 << 1) /* Backslashes don't quote special chars. */ +#define FNM_PERIOD (1 << 2) /* Leading `.' is matched only explicitly. */ + +#if !defined _POSIX_C_SOURCE || _POSIX_C_SOURCE < 2 || defined _GNU_SOURCE +# define FNM_FILE_NAME FNM_PATHNAME /* Preferred GNU name. */ +# define FNM_LEADING_DIR (1 << 3) /* Ignore `/...' after a match. */ +# define FNM_CASEFOLD (1 << 4) /* Compare without regard to case. */ +# define FNM_EXTMATCH (1 << 5) /* Use ksh-like extended matching. */ +#endif + +/* Value returned by `fnmatch' if STRING does not match PATTERN. */ +#define FNM_NOMATCH 1 + +/* This value is returned if the implementation does not support + `fnmatch'. Since this is not the case here it will never be + returned but the conformance test suites still require the symbol + to be defined. */ +#ifdef _XOPEN_SOURCE +# define FNM_NOSYS (-1) +#endif + +/* Match NAME against the filename pattern PATTERN, + returning zero if it matches, FNM_NOMATCH if not. */ +extern int fnmatch (__const char *__pattern, __const char *__name, + int __flags); +libc_hidden_proto(fnmatch) + +#ifdef __cplusplus +} +#endif + +#endif /* fnmatch.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/ftw.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/ftw.h new file mode 100644 index 00000000..84f3e14a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/ftw.h @@ -0,0 +1,180 @@ +/* Copyright (C) 1992,1996-1999,2003,2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * X/Open Portability Guide 4.2: ftw.h + */ + +#ifndef _FTW_H +#define _FTW_H 1 + +#include + +#include +#include + + +__BEGIN_DECLS + +/* Values for the FLAG argument to the user function passed to `ftw' + and 'nftw'. */ +enum +{ + FTW_F, /* Regular file. */ +#define FTW_F FTW_F + FTW_D, /* Directory. */ +#define FTW_D FTW_D + FTW_DNR, /* Unreadable directory. */ +#define FTW_DNR FTW_DNR + FTW_NS, /* Unstatable file. */ +#define FTW_NS FTW_NS + +#if defined __USE_BSD || defined __USE_XOPEN_EXTENDED + + FTW_SL, /* Symbolic link. */ +# define FTW_SL FTW_SL +#endif + +#ifdef __USE_XOPEN_EXTENDED +/* These flags are only passed from the `nftw' function. */ + FTW_DP, /* Directory, all subdirs have been visited. */ +# define FTW_DP FTW_DP + FTW_SLN /* Symbolic link naming non-existing file. */ +# define FTW_SLN FTW_SLN + +#endif /* extended X/Open */ +}; + + +#ifdef __USE_XOPEN_EXTENDED +/* Flags for fourth argument of `nftw'. */ +enum +{ + FTW_PHYS = 1, /* Perform physical walk, ignore symlinks. */ +# define FTW_PHYS FTW_PHYS + FTW_MOUNT = 2, /* Report only files on same file system as the + argument. */ +# define FTW_MOUNT FTW_MOUNT + FTW_CHDIR = 4, /* Change to current directory while processing it. */ +# define FTW_CHDIR FTW_CHDIR + FTW_DEPTH = 8 /* Report files in directory before directory itself.*/ +# define FTW_DEPTH FTW_DEPTH +# ifdef __USE_GNU + , + FTW_ACTIONRETVAL = 16 /* Assume callback to return FTW_* values instead of + zero to continue and non-zero to terminate. */ +# define FTW_ACTIONRETVAL FTW_ACTIONRETVAL +# endif +}; + +#ifdef __USE_GNU +/* Return values from callback functions. */ +enum +{ + FTW_CONTINUE = 0, /* Continue with next sibling or for FTW_D with the + first child. */ +# define FTW_CONTINUE FTW_CONTINUE + FTW_STOP = 1, /* Return from `ftw' or `nftw' with FTW_STOP as return + value. */ +# define FTW_STOP FTW_STOP + FTW_SKIP_SUBTREE = 2, /* Only meaningful for FTW_D: Don't walk through the + subtree, instead just continue with its next + sibling. */ +# define FTW_SKIP_SUBTREE FTW_SKIP_SUBTREE + FTW_SKIP_SIBLINGS = 3,/* Continue with FTW_DP callback for current directory + (if FTW_DEPTH) and then its siblings. */ +# define FTW_SKIP_SIBLINGS FTW_SKIP_SIBLINGS +}; +#endif + +/* Structure used for fourth argument to callback function for `nftw'. */ +struct FTW + { + int base; + int level; + }; +#endif /* extended X/Open */ + + +/* Convenient types for callback functions. */ +typedef int (*__ftw_func_t) (__const char *__filename, + __const struct stat *__status, int __flag); +#ifdef __USE_LARGEFILE64 +typedef int (*__ftw64_func_t) (__const char *__filename, + __const struct stat64 *__status, int __flag); +#endif +#ifdef __USE_XOPEN_EXTENDED +typedef int (*__nftw_func_t) (__const char *__filename, + __const struct stat *__status, int __flag, + struct FTW *__info); +# ifdef __USE_LARGEFILE64 +typedef int (*__nftw64_func_t) (__const char *__filename, + __const struct stat64 *__status, + int __flag, struct FTW *__info); +# endif +#endif + +#if __UCLIBC_HAS_FTW__ +/* Call a function on every element in a directory tree. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +# ifndef __USE_FILE_OFFSET64 +extern int ftw (__const char *__dir, __ftw_func_t __func, int __descriptors) + __nonnull ((1, 2)); +# else +# ifdef __REDIRECT +extern int __REDIRECT (ftw, (__const char *__dir, __ftw_func_t __func, + int __descriptors), ftw64) __nonnull ((1, 2)); +# else +# define ftw ftw64 +# endif +# endif +# ifdef __USE_LARGEFILE64 +extern int ftw64 (__const char *__dir, __ftw64_func_t __func, + int __descriptors) __nonnull ((1, 2)); +# endif +#endif + +#if __UCLIBC_HAS_NFTW__ && defined __USE_XOPEN_EXTENDED +/* Call a function on every element in a directory tree. FLAG allows + to specify the behaviour more detailed. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +# ifndef __USE_FILE_OFFSET64 +extern int nftw (__const char *__dir, __nftw_func_t __func, int __descriptors, + int __flag) __nonnull ((1, 2)); +# else +# ifdef __REDIRECT +extern int __REDIRECT (nftw, (__const char *__dir, __nftw_func_t __func, + int __descriptors, int __flag), nftw64) + __nonnull ((1, 2)); +# else +# define nftw nftw64 +# endif +# endif +# ifdef __USE_LARGEFILE64 +extern int nftw64 (__const char *__dir, __nftw64_func_t __func, + int __descriptors, int __flag) __nonnull ((1, 2)); +# endif +#endif + +__END_DECLS + +#endif /* ftw.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/getopt.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/getopt.h new file mode 100644 index 00000000..a682f9ca --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/getopt.h @@ -0,0 +1,4 @@ +/* This file will not be installed if not using gnu getopt. */ + +#include + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/glob.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/glob.h new file mode 100644 index 00000000..875dfc5b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/glob.h @@ -0,0 +1,213 @@ +/* Copyright (C) 1991,92,95-98,2000,2001,2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _GLOB_H +#define _GLOB_H 1 + +#include + +__BEGIN_DECLS + +/* We need `size_t' for the following definitions. */ +#ifndef __size_t +# if defined __GNUC__ && __GNUC__ >= 2 +typedef __SIZE_TYPE__ __size_t; +# ifdef __USE_XOPEN +typedef __SIZE_TYPE__ size_t; +# endif +# else +# include +# ifndef __size_t +# define __size_t size_t +# endif +# endif +#else +/* The GNU CC stddef.h version defines __size_t as empty. We need a real + definition. */ +# undef __size_t +# define __size_t size_t +#endif + +/* Bits set in the FLAGS argument to `glob'. */ +#define GLOB_ERR (1 << 0)/* Return on read errors. */ +#define GLOB_MARK (1 << 1)/* Append a slash to each name. */ +#define GLOB_NOSORT (1 << 2)/* Don't sort the names. */ +#define GLOB_DOOFFS (1 << 3)/* Insert PGLOB->gl_offs NULLs. */ +#define GLOB_NOCHECK (1 << 4)/* If nothing matches, return the pattern. */ +#define GLOB_APPEND (1 << 5)/* Append to results of a previous call. */ +#define GLOB_NOESCAPE (1 << 6)/* Backslashes don't quote metacharacters. */ +#define GLOB_PERIOD (1 << 7)/* Leading `.' can be matched by metachars. */ + +#if ( !defined __USE_POSIX2 || defined __USE_BSD || defined __USE_GNU ) && defined __UCLIBC_HAS_GNU_GLOB__ +# define GLOB_MAGCHAR (1 << 8)/* Set in gl_flags if any metachars seen. */ +#if 1 /* uClibc gnu glob does not support these */ +# define GLOB_ALTDIRFUNC (1 << 9)/* Use gl_opendir et al functions. */ +# define GLOB_BRACE (1 << 10)/* Expand "{a,b}" to "a" "b". */ +# define GLOB_NOMAGIC (1 << 11)/* If no magic chars, return the pattern. */ +# define GLOB_TILDE (1 << 12)/* Expand ~user and ~ to home directories. */ +# define GLOB_ONLYDIR (1 << 13)/* Match only directories. */ +# define GLOB_TILDE_CHECK (1 << 14)/* Like GLOB_TILDE but return an error + if the user name is not available. */ +# define __GLOB_FLAGS (GLOB_ERR|GLOB_MARK|GLOB_NOSORT|GLOB_DOOFFS| \ + GLOB_NOESCAPE|GLOB_NOCHECK|GLOB_APPEND| \ + GLOB_PERIOD|GLOB_ALTDIRFUNC|GLOB_BRACE| \ + GLOB_NOMAGIC|GLOB_TILDE|GLOB_ONLYDIR|GLOB_TILDE_CHECK) +#else +# define __GLOB_FLAGS (GLOB_ERR|GLOB_MARK|GLOB_NOSORT|GLOB_DOOFFS| \ + GLOB_NOESCAPE|GLOB_NOCHECK|GLOB_APPEND| \ + GLOB_PERIOD) +#endif +#else +# define __GLOB_FLAGS (GLOB_ERR|GLOB_MARK|GLOB_NOSORT|GLOB_DOOFFS| \ + GLOB_NOESCAPE|GLOB_NOCHECK|GLOB_APPEND| \ + GLOB_PERIOD) +#endif + +/* Error returns from `glob'. */ +#define GLOB_NOSPACE 1 /* Ran out of memory. */ +#define GLOB_ABORTED 2 /* Read error. */ +#define GLOB_NOMATCH 3 /* No matches found. */ +#define GLOB_NOSYS 4 /* Not implemented. */ +#if defined __USE_GNU && defined __UCLIBC_HAS_GNU_GLOB__ +/* Previous versions of this file defined GLOB_ABEND instead of + GLOB_ABORTED. Provide a compatibility definition here. */ +# define GLOB_ABEND GLOB_ABORTED +#endif + +/* Structure describing a globbing run. */ +#if defined __USE_GNU && defined __UCLIBC_HAS_GNU_GLOB__ +struct stat; +#endif +typedef struct + { + __size_t gl_pathc; /* Count of paths matched by the pattern. */ + char **gl_pathv; /* List of matched pathnames. */ + __size_t gl_offs; /* Slots to reserve in `gl_pathv'. */ +#ifdef __UCLIBC_HAS_GNU_GLOB__ + int gl_flags; /* Set to FLAGS, maybe | GLOB_MAGCHAR. */ + +#if 1 /* uClibc gnu glob does not support these */ + /* If the GLOB_ALTDIRFUNC flag is set, the following functions + are used instead of the normal file access functions. */ + void (*gl_closedir) (void *); +#ifdef __USE_GNU + struct dirent *(*gl_readdir) (void *); +#else + void *(*gl_readdir) (void *); +#endif + void *(*gl_opendir) (__const char *); +#ifdef __USE_GNU + int (*gl_lstat) (__const char *__restrict, struct stat *__restrict); + int (*gl_stat) (__const char *__restrict, struct stat *__restrict); +#else + int (*gl_lstat) (__const char *__restrict, void *__restrict); + int (*gl_stat) (__const char *__restrict, void *__restrict); +#endif +#endif +#endif /* __UCLIBC_HAS_GNU_GLOB__ */ + } glob_t; + +#ifdef __USE_LARGEFILE64 +# if defined __USE_GNU && defined __UCLIBC_HAS_GNU_GLOB__ +struct stat64; +# endif +typedef struct + { + __size_t gl_pathc; + char **gl_pathv; + __size_t gl_offs; +#ifdef __UCLIBC_HAS_GNU_GLOB__ + int gl_flags; + +#if 1 /* uClibc gnu glob does not support these */ + /* If the GLOB_ALTDIRFUNC flag is set, the following functions + are used instead of the normal file access functions. */ + void (*gl_closedir) (void *); +# ifdef __USE_GNU + struct dirent64 *(*gl_readdir) (void *); +# else + void *(*gl_readdir) (void *); +# endif + void *(*gl_opendir) (__const char *); +# ifdef __USE_GNU + int (*gl_lstat) (__const char *__restrict, struct stat64 *__restrict); + int (*gl_stat) (__const char *__restrict, struct stat64 *__restrict); +# else + int (*gl_lstat) (__const char *__restrict, void *__restrict); + int (*gl_stat) (__const char *__restrict, void *__restrict); +# endif +#endif +#endif /* __UCLIBC_HAS_GNU_GLOB__ */ + } glob64_t; +#endif + +#if defined(__USE_FILE_OFFSET64) && __GNUC__ < 2 +# define glob glob64 +# define globfree globfree64 +#endif + +/* Do glob searching for PATTERN, placing results in PGLOB. + The bits defined above may be set in FLAGS. + If a directory cannot be opened or read and ERRFUNC is not nil, + it is called with the pathname that caused the error, and the + `errno' value from the failing call; if it returns non-zero + `glob' returns GLOB_ABEND; if it returns zero, the error is ignored. + If memory cannot be allocated for PGLOB, GLOB_NOSPACE is returned. + Otherwise, `glob' returns zero. */ +#if !defined __USE_FILE_OFFSET64 || __GNUC__ < 2 +extern int glob (__const char *__restrict __pattern, int __flags, + int (*__errfunc) (__const char *, int), + glob_t *__restrict __pglob) __THROW; +libc_hidden_proto(glob) + +/* Free storage allocated in PGLOB by a previous `glob' call. */ +extern void globfree (glob_t *__pglob) __THROW; +libc_hidden_proto(globfree) +#else +extern int __REDIRECT_NTH (glob, (__const char *__restrict __pattern, + int __flags, + int (*__errfunc) (__const char *, int), + glob_t *__restrict __pglob), glob64); + +extern void __REDIRECT_NTH (globfree, (glob_t *__pglob), globfree64); +#endif + +#ifdef __USE_LARGEFILE64 +extern int glob64 (__const char *__restrict __pattern, int __flags, + int (*__errfunc) (__const char *, int), + glob64_t *__restrict __pglob) __THROW; +libc_hidden_proto(glob64) + +extern void globfree64 (glob64_t *__pglob) __THROW; +libc_hidden_proto(globfree64) +#endif + + +#if defined __USE_GNU && defined __UCLIBC_HAS_GNU_GLOB__ +/* Return nonzero if PATTERN contains any metacharacters. + Metacharacters can be quoted with backslashes if QUOTE is nonzero. + + This function is not part of the interface specified by POSIX.2 + but several programs want to use it. */ +extern int glob_pattern_p (__const char *__pattern, int __quote) __THROW; +libc_hidden_proto(glob_pattern_p) +#endif + +__END_DECLS + +#endif /* glob.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/gnu-versions.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/gnu-versions.h new file mode 100644 index 00000000..59e617c4 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/gnu-versions.h @@ -0,0 +1,53 @@ +/* Header with interface version macros for library pieces copied elsewhere. + Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _GNU_VERSIONS_H +#define _GNU_VERSIONS_H 1 + +/* This file exists to define these few macros. Each specifies a version + number associated with the library interface of a piece of the C library + which is also distributed with other GNU packages. These pieces are + both part of the GNU C library and also distributed with other GNU + packages so those packages may use their facilities on systems lacking + the GNU C library. The source files for each piece surround all their + code with `#ifndef ELIDE_CODE' after defining it with this: + + #define OBSTACK_INTERFACE_VERSION 1 + #if !defined (_LIBC) && defined (__GNU_LIBRARY__) && __GNU_LIBRARY__ > 1 + #include + #if _GNU_OBSTACK_INTERFACE_VERSION == OBSTACK_INTERFACE_VERSION + #define ELIDE_CODE + #endif + #endif + + This allows those one to avoid compiling those files when part of a GNU + package not libc, on a system using a GNU C library that supports the + same interface. + + Please preserve the format of the comments after each macro. And + remember, if any of these versions change, the libc.so major version + number must change too (so avoid it)! */ + +#define _GNU_OBSTACK_INTERFACE_VERSION 1 /* vs malloc/obstack.c */ +#define _GNU_REGEX_INTERFACE_VERSION 1 /* vs posix/regex.c */ +#define _GNU_GLOB_INTERFACE_VERSION 1 /* vs posix/glob.c */ +#define _GNU_GETOPT_INTERFACE_VERSION 2 /* vs posix/getopt.c and + posix/getopt1.c */ + +#endif /* gnu-versions.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/grp.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/grp.h new file mode 100644 index 00000000..45b21043 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/grp.h @@ -0,0 +1,215 @@ +/* Copyright (C) 1991,1992,1995-2001,2003,2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * POSIX Standard: 9.2.1 Group Database Access + */ + +#ifndef _GRP_H +#define _GRP_H 1 + +#include + +__BEGIN_DECLS + +#include + +#define __need_size_t +#include + + +/* For the Single Unix specification we must define this type here. */ +#if (defined __USE_XOPEN || defined __USE_XOPEN2K) && !defined __gid_t_defined +typedef __gid_t gid_t; +# define __gid_t_defined +#endif + +/* The group structure. */ +struct group + { + char *gr_name; /* Group name. */ + char *gr_passwd; /* Password. */ + __gid_t gr_gid; /* Group ID. */ + char **gr_mem; /* Member list. */ + }; + + +#if defined __USE_SVID || defined __USE_GNU +# define __need_FILE +# include +#endif + + +#if defined __USE_SVID || defined __USE_BSD || defined __USE_XOPEN_EXTENDED +/* Rewind the group-file stream. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern void setgrent (void); + +/* Close the group-file stream. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern void endgrent (void); + +/* Read an entry from the group-file stream, opening it if necessary. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern struct group *getgrent (void); +#endif + +#ifdef __USE_SVID +/* Read a group entry from STREAM. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern struct group *fgetgrent (FILE *__stream); +#endif + +#ifdef __USE_GNU +/* Write the given entry onto the given stream. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern int putgrent (__const struct group *__restrict __p, + FILE *__restrict __f); +#endif + +/* Search for an entry with a matching group ID. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern struct group *getgrgid (__gid_t __gid); + +/* Search for an entry with a matching group name. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern struct group *getgrnam (__const char *__name); + +#if defined __USE_POSIX || defined __USE_MISC + +# ifdef __USE_MISC +/* Reasonable value for the buffer sized used in the reentrant + functions below. But better use `sysconf'. */ +# define NSS_BUFLEN_GROUP 1024 +# endif + +/* Reentrant versions of some of the functions above. + + PLEASE NOTE: the `getgrent_r' function is not (yet) standardized. + The interface may change in later versions of this library. But + the interface is designed following the principals used for the + other reentrant functions so the chances are good this is what the + POSIX people would choose. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ + +# ifdef __USE_GNU +extern int getgrent_r (struct group *__restrict __resultbuf, + char *__restrict __buffer, size_t __buflen, + struct group **__restrict __result); +libc_hidden_proto(getgrent_r) +# endif + +/* Search for an entry with a matching group ID. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern int getgrgid_r (__gid_t __gid, struct group *__restrict __resultbuf, + char *__restrict __buffer, size_t __buflen, + struct group **__restrict __result); +libc_hidden_proto(getgrgid_r) + +/* Search for an entry with a matching group name. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern int getgrnam_r (__const char *__restrict __name, + struct group *__restrict __resultbuf, + char *__restrict __buffer, size_t __buflen, + struct group **__restrict __result); +libc_hidden_proto(getgrnam_r) + +# ifdef __USE_SVID +/* Read a group entry from STREAM. This function is not standardized + an probably never will. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern int fgetgrent_r (FILE *__restrict __stream, + struct group *__restrict __resultbuf, + char *__restrict __buffer, size_t __buflen, + struct group **__restrict __result); +libc_hidden_proto(fgetgrent_r) +# endif + +#endif /* POSIX or reentrant */ + + +#if defined __USE_BSD || defined __USE_GNU + +# define __need_size_t +# include + +/* Store at most *NGROUPS members of the group set for USER into + *GROUPS. Also include GROUP. The actual number of groups found is + returned in *NGROUPS. Return -1 if the if *NGROUPS is too small. + In all cases the actual number of groups is stored in *NGROUPS. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern int getgrouplist (__const char *__user, __gid_t __group, + __gid_t *__groups, int *__ngroups); + +#endif + +#if defined __USE_BSD + +/* Set the group set for the current user to GROUPS (N of them). */ +extern int setgroups (size_t __n, __const __gid_t *__groups) __THROW; +libc_hidden_proto(setgroups) + +/* Initialize the group set for the current user + by reading the group database and using all groups + of which USER is a member. Also include GROUP. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern int initgroups (__const char *__user, __gid_t __group); + +#endif /* Use BSD. */ + +__END_DECLS + +#endif /* grp.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/iconv.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/iconv.h new file mode 100644 index 00000000..0a19c049 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/iconv.h @@ -0,0 +1,60 @@ +/* Copyright (C) 1997, 1998, 1999, 2000, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _ICONV_H +#define _ICONV_H 1 + +#include +#define __need_size_t +#include + +#ifndef __UCLIBC_HAS_LOCALE__ +#error Attempted to include iconv.h when uClibc was built without locale support. +#endif + + +__BEGIN_DECLS + +/* Identifier for conversion method from one codeset to another. */ +typedef void *iconv_t; + + +/* Allocate descriptor for code conversion from codeset FROMCODE to + codeset TOCODE. + + This function is a possible cancellation points and therefore not + marked with __THROW. */ +extern iconv_t iconv_open (__const char *__tocode, __const char *__fromcode); + +/* Convert at most *INBYTESLEFT bytes from *INBUF according to the + code conversion algorithm specified by CD and place up to + *OUTBYTESLEFT bytes in buffer at *OUTBUF. */ +extern size_t iconv (iconv_t __cd, char **__restrict __inbuf, + size_t *__restrict __inbytesleft, + char **__restrict __outbuf, + size_t *__restrict __outbytesleft); + +/* Free resources allocated for descriptor CD for code conversion. + + This function is a possible cancellation points and therefore not + marked with __THROW. */ +extern int iconv_close (iconv_t __cd); + +__END_DECLS + +#endif /* iconv.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/ieee754.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/ieee754.h new file mode 100644 index 00000000..b17c29ab --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/ieee754.h @@ -0,0 +1,199 @@ +/* Copyright (C) 1992, 1995, 1996, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _IEEE754_H + +#define _IEEE754_H 1 +#include + +#include + +__BEGIN_DECLS + +union ieee754_float + { + float f; + + /* This is the IEEE 754 single-precision format. */ + struct + { +#if __BYTE_ORDER == __BIG_ENDIAN + unsigned int negative:1; + unsigned int exponent:8; + unsigned int mantissa:23; +#endif /* Big endian. */ +#if __BYTE_ORDER == __LITTLE_ENDIAN + unsigned int mantissa:23; + unsigned int exponent:8; + unsigned int negative:1; +#endif /* Little endian. */ + } ieee; + + /* This format makes it easier to see if a NaN is a signalling NaN. */ + struct + { +#if __BYTE_ORDER == __BIG_ENDIAN + unsigned int negative:1; + unsigned int exponent:8; + unsigned int quiet_nan:1; + unsigned int mantissa:22; +#endif /* Big endian. */ +#if __BYTE_ORDER == __LITTLE_ENDIAN + unsigned int mantissa:22; + unsigned int quiet_nan:1; + unsigned int exponent:8; + unsigned int negative:1; +#endif /* Little endian. */ + } ieee_nan; + }; + +#define IEEE754_FLOAT_BIAS 0x7f /* Added to exponent. */ + + +union ieee754_double + { + double d; + + /* This is the IEEE 754 double-precision format. */ + struct + { +#if __BYTE_ORDER == __BIG_ENDIAN + unsigned int negative:1; + unsigned int exponent:11; + /* Together these comprise the mantissa. */ + unsigned int mantissa0:20; + unsigned int mantissa1:32; +#endif /* Big endian. */ +#if __BYTE_ORDER == __LITTLE_ENDIAN +# if __FLOAT_WORD_ORDER == __BIG_ENDIAN + unsigned int mantissa0:20; + unsigned int exponent:11; + unsigned int negative:1; + unsigned int mantissa1:32; +# else + /* Together these comprise the mantissa. */ + unsigned int mantissa1:32; + unsigned int mantissa0:20; + unsigned int exponent:11; + unsigned int negative:1; +# endif +#endif /* Little endian. */ + } ieee; + + /* This format makes it easier to see if a NaN is a signalling NaN. */ + struct + { +#if __BYTE_ORDER == __BIG_ENDIAN + unsigned int negative:1; + unsigned int exponent:11; + unsigned int quiet_nan:1; + /* Together these comprise the mantissa. */ + unsigned int mantissa0:19; + unsigned int mantissa1:32; +#else +# if __FLOAT_WORD_ORDER == __BIG_ENDIAN + unsigned int mantissa0:19; + unsigned int quiet_nan:1; + unsigned int exponent:11; + unsigned int negative:1; + unsigned int mantissa1:32; +# else + /* Together these comprise the mantissa. */ + unsigned int mantissa1:32; + unsigned int mantissa0:19; + unsigned int quiet_nan:1; + unsigned int exponent:11; + unsigned int negative:1; +# endif +#endif + } ieee_nan; + }; + +#define IEEE754_DOUBLE_BIAS 0x3ff /* Added to exponent. */ + + +union ieee854_long_double + { + long double d; + + /* This is the IEEE 854 double-extended-precision format. */ + struct + { +#if __BYTE_ORDER == __BIG_ENDIAN + unsigned int negative:1; + unsigned int exponent:15; + unsigned int empty:16; + unsigned int mantissa0:32; + unsigned int mantissa1:32; +#endif +#if __BYTE_ORDER == __LITTLE_ENDIAN +# if __FLOAT_WORD_ORDER == __BIG_ENDIAN + unsigned int exponent:15; + unsigned int negative:1; + unsigned int empty:16; + unsigned int mantissa0:32; + unsigned int mantissa1:32; +# else + unsigned int mantissa1:32; + unsigned int mantissa0:32; + unsigned int exponent:15; + unsigned int negative:1; + unsigned int empty:16; +# endif +#endif + } ieee; + + /* This is for NaNs in the IEEE 854 double-extended-precision format. */ + struct + { +#if __BYTE_ORDER == __BIG_ENDIAN + unsigned int negative:1; + unsigned int exponent:15; + unsigned int empty:16; + unsigned int one:1; + unsigned int quiet_nan:1; + unsigned int mantissa0:30; + unsigned int mantissa1:32; +#endif +#if __BYTE_ORDER == __LITTLE_ENDIAN +# if __FLOAT_WORD_ORDER == __BIG_ENDIAN + unsigned int exponent:15; + unsigned int negative:1; + unsigned int empty:16; + unsigned int mantissa0:30; + unsigned int quiet_nan:1; + unsigned int one:1; + unsigned int mantissa1:32; +# else + unsigned int mantissa1:32; + unsigned int mantissa0:30; + unsigned int quiet_nan:1; + unsigned int one:1; + unsigned int exponent:15; + unsigned int negative:1; + unsigned int empty:16; +# endif +#endif + } ieee_nan; + }; + +#define IEEE854_LONG_DOUBLE_BIAS 0x3fff + +__END_DECLS + +#endif /* ieee754.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/ifaddrs.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/ifaddrs.h new file mode 100644 index 00000000..ba6a1554 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/ifaddrs.h @@ -0,0 +1,74 @@ +/* ifaddrs.h -- declarations for getting network interface addresses + Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _IFADDRS_H +#define _IFADDRS_H 1 + +#include +#include + +__BEGIN_DECLS + +/* The `getifaddrs' function generates a linked list of these structures. + Each element of the list describes one network interface. */ +struct ifaddrs +{ + struct ifaddrs *ifa_next; /* Pointer to the next structure. */ + + char *ifa_name; /* Name of this network interface. */ + unsigned int ifa_flags; /* Flags as from SIOCGIFFLAGS ioctl. */ + + struct sockaddr *ifa_addr; /* Network address of this interface. */ + struct sockaddr *ifa_netmask; /* Netmask of this interface. */ + union + { + /* At most one of the following two is valid. If the IFF_BROADCAST + bit is set in `ifa_flags', then `ifa_broadaddr' is valid. If the + IFF_POINTOPOINT bit is set, then `ifa_dstaddr' is valid. + It is never the case that both these bits are set at once. */ + struct sockaddr *ifu_broadaddr; /* Broadcast address of this interface. */ + struct sockaddr *ifu_dstaddr; /* Point-to-point destination address. */ + } ifa_ifu; + /* These very same macros are defined by for `struct ifaddr'. + So if they are defined already, the existing definitions will be fine. */ +# ifndef ifa_broadaddr +# define ifa_broadaddr ifa_ifu.ifu_broadaddr +# endif +# ifndef ifa_dstaddr +# define ifa_dstaddr ifa_ifu.ifu_dstaddr +# endif + + void *ifa_data; /* Address-specific data (may be unused). */ +}; + + +/* Create a linked list of `struct ifaddrs' structures, one for each + network interface on the host machine. If successful, store the + list in *IFAP and return 0. On errors, return -1 and set `errno'. + + The storage returned in *IFAP is allocated dynamically and can + only be properly freed by passing it to `freeifaddrs'. */ +extern int getifaddrs (struct ifaddrs **__ifap) __THROW; + +/* Reclaim the storage allocated by a previous `getifaddrs' call. */ +extern void freeifaddrs (struct ifaddrs *__ifa) __THROW; + +__END_DECLS + +#endif /* ifaddrs.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/internal/parse_config.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/internal/parse_config.h new file mode 100644 index 00000000..ebfb87e5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/internal/parse_config.h @@ -0,0 +1,57 @@ +/* vi: set sw=4 ts=4: */ +/* + * config file parser helper + * + * Copyright (C) 2008 by Vladimir Dronnikov + * + * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. + * Also for use in uClibc (http://uclibc.org/) licensed under LGPLv2.1 or later. + */ +#ifndef __INTERNAL_PARSE_CONFIG_H +#define __INTERNAL_PARSE_CONFIG_H + +#include +#ifndef FAST_FUNC +# define FAST_FUNC +#endif + +/* + * Config file parser + */ +enum { + PARSE_COLLAPSE = 0x00010000, /* treat consecutive delimiters as one */ + PARSE_TRIM = 0x00020000, /* trim leading and trailing delimiters */ +/* TODO: COLLAPSE and TRIM seem to always go in pair */ + PARSE_GREEDY = 0x00040000, /* last token takes entire remainder of the line */ + PARSE_MIN_DIE = 0x00100000, /* die if < min tokens found */ + /* keep a copy of current line */ + PARSE_KEEP_COPY = 0x00200000 * 0, /*ENABLE_FEATURE_CROND_D, */ +/* PARSE_ESCAPE = 0x00400000,*/ /* process escape sequences in tokens */ + /* NORMAL is: + * remove leading and trailing delimiters and collapse + multiple delimiters into one + * warn and continue if less than mintokens delimiters found + * grab everything into last token + */ + PARSE_NORMAL = PARSE_COLLAPSE | PARSE_TRIM | PARSE_GREEDY, +}; + +typedef struct parser_t { + FILE *fp; /* input file */ + char *data; /* pointer to data */ + size_t data_len; /* offset into data of begin of line */ + char *line; /* pointer to beginning of line */ + size_t line_len; /* length of line */ + smalluint allocated; +} parser_t; + +parser_t* config_open(const char *filename) FAST_FUNC attribute_hidden; +libc_hidden_proto(config_open) +int config_read(parser_t *parser, char ***tokens, unsigned flags, const char *delims) FAST_FUNC attribute_hidden; +libc_hidden_proto(config_read) +#define config_read(parser, tokens, max, min, str, flags) \ + config_read(parser, tokens, ((flags) | (((min) & 0xFF) << 8) | ((max) & 0xFF)), str) +void config_close(parser_t *parser) FAST_FUNC attribute_hidden; +libc_hidden_proto(config_close) + +#endif /* __INTERNAL_PARSE_CONFIG_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/inttypes.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/inttypes.h new file mode 100644 index 00000000..137d3dbd --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/inttypes.h @@ -0,0 +1,448 @@ +/* Copyright (C) 1997-2001, 2004, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * ISO C99: 7.8 Format conversion of integer types + */ + +#ifndef _INTTYPES_H +#define _INTTYPES_H 1 + +#include +/* Get the type definitions. */ +#include + +#ifdef __UCLIBC_HAS_WCHAR__ +/* Get a definition for wchar_t. But we must not define wchar_t itself. */ +#ifndef ____gwchar_t_defined +# ifdef __cplusplus +# define __gwchar_t wchar_t +# elif defined __WCHAR_TYPE__ +typedef __WCHAR_TYPE__ __gwchar_t; +# else +# define __need_wchar_t +# include +typedef wchar_t __gwchar_t; +# endif +# define ____gwchar_t_defined 1 +#endif +#endif + + +/* The ISO C99 standard specifies that these macros must only be + defined if explicitly requested. */ +#if !defined __cplusplus || defined __STDC_FORMAT_MACROS + +# if __WORDSIZE == 64 +# define __PRI64_PREFIX "l" +# define __PRIPTR_PREFIX "l" +# else +# define __PRI64_PREFIX "ll" +# define __PRIPTR_PREFIX +# endif + +/* Macros for printing format specifiers. */ + +/* Decimal notation. */ +# define PRId8 "d" +# define PRId16 "d" +# define PRId32 "d" +# define PRId64 __PRI64_PREFIX "d" + +# define PRIdLEAST8 "d" +# define PRIdLEAST16 "d" +# define PRIdLEAST32 "d" +# define PRIdLEAST64 __PRI64_PREFIX "d" + +# define PRIdFAST8 "d" +# define PRIdFAST16 __PRIPTR_PREFIX "d" +# define PRIdFAST32 __PRIPTR_PREFIX "d" +# define PRIdFAST64 __PRI64_PREFIX "d" + + +# define PRIi8 "i" +# define PRIi16 "i" +# define PRIi32 "i" +# define PRIi64 __PRI64_PREFIX "i" + +# define PRIiLEAST8 "i" +# define PRIiLEAST16 "i" +# define PRIiLEAST32 "i" +# define PRIiLEAST64 __PRI64_PREFIX "i" + +# define PRIiFAST8 "i" +# define PRIiFAST16 __PRIPTR_PREFIX "i" +# define PRIiFAST32 __PRIPTR_PREFIX "i" +# define PRIiFAST64 __PRI64_PREFIX "i" + +/* Octal notation. */ +# define PRIo8 "o" +# define PRIo16 "o" +# define PRIo32 "o" +# define PRIo64 __PRI64_PREFIX "o" + +# define PRIoLEAST8 "o" +# define PRIoLEAST16 "o" +# define PRIoLEAST32 "o" +# define PRIoLEAST64 __PRI64_PREFIX "o" + +# define PRIoFAST8 "o" +# define PRIoFAST16 __PRIPTR_PREFIX "o" +# define PRIoFAST32 __PRIPTR_PREFIX "o" +# define PRIoFAST64 __PRI64_PREFIX "o" + +/* Unsigned integers. */ +# define PRIu8 "u" +# define PRIu16 "u" +# define PRIu32 "u" +# define PRIu64 __PRI64_PREFIX "u" + +# define PRIuLEAST8 "u" +# define PRIuLEAST16 "u" +# define PRIuLEAST32 "u" +# define PRIuLEAST64 __PRI64_PREFIX "u" + +# define PRIuFAST8 "u" +# define PRIuFAST16 __PRIPTR_PREFIX "u" +# define PRIuFAST32 __PRIPTR_PREFIX "u" +# define PRIuFAST64 __PRI64_PREFIX "u" + +/* lowercase hexadecimal notation. */ +# define PRIx8 "x" +# define PRIx16 "x" +# define PRIx32 "x" +# define PRIx64 __PRI64_PREFIX "x" + +# define PRIxLEAST8 "x" +# define PRIxLEAST16 "x" +# define PRIxLEAST32 "x" +# define PRIxLEAST64 __PRI64_PREFIX "x" + +# define PRIxFAST8 "x" +# define PRIxFAST16 __PRIPTR_PREFIX "x" +# define PRIxFAST32 __PRIPTR_PREFIX "x" +# define PRIxFAST64 __PRI64_PREFIX "x" + +/* UPPERCASE hexadecimal notation. */ +# define PRIX8 "X" +# define PRIX16 "X" +# define PRIX32 "X" +# define PRIX64 __PRI64_PREFIX "X" + +# define PRIXLEAST8 "X" +# define PRIXLEAST16 "X" +# define PRIXLEAST32 "X" +# define PRIXLEAST64 __PRI64_PREFIX "X" + +# define PRIXFAST8 "X" +# define PRIXFAST16 __PRIPTR_PREFIX "X" +# define PRIXFAST32 __PRIPTR_PREFIX "X" +# define PRIXFAST64 __PRI64_PREFIX "X" + + +/* Macros for printing `intmax_t' and `uintmax_t'. */ +# define PRIdMAX __PRI64_PREFIX "d" +# define PRIiMAX __PRI64_PREFIX "i" +# define PRIoMAX __PRI64_PREFIX "o" +# define PRIuMAX __PRI64_PREFIX "u" +# define PRIxMAX __PRI64_PREFIX "x" +# define PRIXMAX __PRI64_PREFIX "X" + + +/* Macros for printing `intptr_t' and `uintptr_t'. */ +# define PRIdPTR __PRIPTR_PREFIX "d" +# define PRIiPTR __PRIPTR_PREFIX "i" +# define PRIoPTR __PRIPTR_PREFIX "o" +# define PRIuPTR __PRIPTR_PREFIX "u" +# define PRIxPTR __PRIPTR_PREFIX "x" +# define PRIXPTR __PRIPTR_PREFIX "X" + + +/* Macros for scanning format specifiers. */ + +/* Signed decimal notation. */ +# define SCNd8 "hhd" +# define SCNd16 "hd" +# define SCNd32 "d" +# define SCNd64 __PRI64_PREFIX "d" + +# define SCNdLEAST8 "hhd" +# define SCNdLEAST16 "hd" +# define SCNdLEAST32 "d" +# define SCNdLEAST64 __PRI64_PREFIX "d" + +# define SCNdFAST8 "hhd" +# define SCNdFAST16 __PRIPTR_PREFIX "d" +# define SCNdFAST32 __PRIPTR_PREFIX "d" +# define SCNdFAST64 __PRI64_PREFIX "d" + +/* Signed decimal notation. */ +# define SCNi8 "hhi" +# define SCNi16 "hi" +# define SCNi32 "i" +# define SCNi64 __PRI64_PREFIX "i" + +# define SCNiLEAST8 "hhi" +# define SCNiLEAST16 "hi" +# define SCNiLEAST32 "i" +# define SCNiLEAST64 __PRI64_PREFIX "i" + +# define SCNiFAST8 "hhi" +# define SCNiFAST16 __PRIPTR_PREFIX "i" +# define SCNiFAST32 __PRIPTR_PREFIX "i" +# define SCNiFAST64 __PRI64_PREFIX "i" + +/* Unsigned decimal notation. */ +# define SCNu8 "hhu" +# define SCNu16 "hu" +# define SCNu32 "u" +# define SCNu64 __PRI64_PREFIX "u" + +# define SCNuLEAST8 "hhu" +# define SCNuLEAST16 "hu" +# define SCNuLEAST32 "u" +# define SCNuLEAST64 __PRI64_PREFIX "u" + +# define SCNuFAST8 "hhu" +# define SCNuFAST16 __PRIPTR_PREFIX "u" +# define SCNuFAST32 __PRIPTR_PREFIX "u" +# define SCNuFAST64 __PRI64_PREFIX "u" + +/* Octal notation. */ +# define SCNo8 "hho" +# define SCNo16 "ho" +# define SCNo32 "o" +# define SCNo64 __PRI64_PREFIX "o" + +# define SCNoLEAST8 "hho" +# define SCNoLEAST16 "ho" +# define SCNoLEAST32 "o" +# define SCNoLEAST64 __PRI64_PREFIX "o" + +# define SCNoFAST8 "hho" +# define SCNoFAST16 __PRIPTR_PREFIX "o" +# define SCNoFAST32 __PRIPTR_PREFIX "o" +# define SCNoFAST64 __PRI64_PREFIX "o" + +/* Hexadecimal notation. */ +# define SCNx8 "hhx" +# define SCNx16 "hx" +# define SCNx32 "x" +# define SCNx64 __PRI64_PREFIX "x" + +# define SCNxLEAST8 "hhx" +# define SCNxLEAST16 "hx" +# define SCNxLEAST32 "x" +# define SCNxLEAST64 __PRI64_PREFIX "x" + +# define SCNxFAST8 "hhx" +# define SCNxFAST16 __PRIPTR_PREFIX "x" +# define SCNxFAST32 __PRIPTR_PREFIX "x" +# define SCNxFAST64 __PRI64_PREFIX "x" + + +/* Macros for scanning `intmax_t' and `uintmax_t'. */ +# define SCNdMAX __PRI64_PREFIX "d" +# define SCNiMAX __PRI64_PREFIX "i" +# define SCNoMAX __PRI64_PREFIX "o" +# define SCNuMAX __PRI64_PREFIX "u" +# define SCNxMAX __PRI64_PREFIX "x" + +/* Macros for scaning `intptr_t' and `uintptr_t'. */ +# define SCNdPTR __PRIPTR_PREFIX "d" +# define SCNiPTR __PRIPTR_PREFIX "i" +# define SCNoPTR __PRIPTR_PREFIX "o" +# define SCNuPTR __PRIPTR_PREFIX "u" +# define SCNxPTR __PRIPTR_PREFIX "x" + +#endif /* C++ && format macros */ + + +__BEGIN_DECLS + +#if __WORDSIZE == 64 + +/* We have to define the `uintmax_t' type using `ldiv_t'. */ +typedef struct + { + long int quot; /* Quotient. */ + long int rem; /* Remainder. */ + } imaxdiv_t; + +#else + +/* We have to define the `uintmax_t' type using `lldiv_t'. */ +typedef struct + { + long long int quot; /* Quotient. */ + long long int rem; /* Remainder. */ + } imaxdiv_t; + +#endif + + +/* Compute absolute value of N. */ +extern intmax_t imaxabs (intmax_t __n) __THROW __attribute__ ((__const__)); + +/* Return the `imaxdiv_t' representation of the value of NUMER over DENOM. */ +extern imaxdiv_t imaxdiv (intmax_t __numer, intmax_t __denom) + __THROW __attribute__ ((__const__)); + +/* Like `strtol' but convert to `intmax_t'. */ +extern intmax_t strtoimax (__const char *__restrict __nptr, + char **__restrict __endptr, int __base) __THROW; + +/* Like `strtoul' but convert to `uintmax_t'. */ +extern uintmax_t strtoumax (__const char *__restrict __nptr, + char ** __restrict __endptr, int __base) __THROW; + +#ifdef __UCLIBC_HAS_WCHAR__ +/* Like `wcstol' but convert to `intmax_t'. */ +extern intmax_t wcstoimax (__const __gwchar_t *__restrict __nptr, + __gwchar_t **__restrict __endptr, int __base) + __THROW; + +/* Like `wcstoul' but convert to `uintmax_t'. */ +extern uintmax_t wcstoumax (__const __gwchar_t *__restrict __nptr, + __gwchar_t ** __restrict __endptr, int __base) + __THROW; +#endif + +#if 0 /*def __USE_EXTERN_INLINES*/ + +# if __WORDSIZE == 64 + +extern long int __strtol_internal (__const char *__restrict __nptr, + char **__restrict __endptr, + int __base, int __group) + __THROW __nonnull ((1)) __wur; +/* Like `strtol' but convert to `intmax_t'. */ +__extern_inline intmax_t +__NTH (strtoimax (__const char *__restrict nptr, char **__restrict endptr, + int base)) +{ + return __strtol_internal (nptr, endptr, base, 0); +} + +extern unsigned long int __strtoul_internal (__const char * + __restrict __nptr, + char ** __restrict __endptr, + int __base, int __group) + __THROW __nonnull ((1)) __wur; +/* Like `strtoul' but convert to `uintmax_t'. */ +__extern_inline uintmax_t +__NTH (strtoumax (__const char *__restrict nptr, char **__restrict endptr, + int base)) +{ + return __strtoul_internal (nptr, endptr, base, 0); +} + +extern long int __wcstol_internal (__const __gwchar_t * __restrict __nptr, + __gwchar_t **__restrict __endptr, + int __base, int __group) + __THROW __nonnull ((1)) __wur; +/* Like `wcstol' but convert to `intmax_t'. */ +__extern_inline intmax_t +__NTH (wcstoimax (__const __gwchar_t *__restrict nptr, + __gwchar_t **__restrict endptr, int base)) +{ + return __wcstol_internal (nptr, endptr, base, 0); +} + +extern unsigned long int __wcstoul_internal (__const __gwchar_t * + __restrict __nptr, + __gwchar_t ** + __restrict __endptr, + int __base, int __group) + __THROW __nonnull ((1)) __wur; +/* Like `wcstoul' but convert to `uintmax_t'. */ +__extern_inline uintmax_t +__NTH (wcstoumax (__const __gwchar_t *__restrict nptr, + __gwchar_t **__restrict endptr, int base)) +{ + return __wcstoul_internal (nptr, endptr, base, 0); +} + +# else /* __WORDSIZE == 32 */ + +__extension__ +extern long long int __strtoll_internal (__const char *__restrict __nptr, + char **__restrict __endptr, + int __base, int __group) + __THROW __nonnull ((1)) __wur; +/* Like `strtol' but convert to `intmax_t'. */ +__extern_inline intmax_t +__NTH (strtoimax (__const char *__restrict nptr, char **__restrict endptr, + int base)) +{ + return __strtoll_internal (nptr, endptr, base, 0); +} + +__extension__ +extern unsigned long long int __strtoull_internal (__const char * + __restrict __nptr, + char ** + __restrict __endptr, + int __base, + int __group) + __THROW __nonnull ((1)) __wur; +/* Like `strtoul' but convert to `uintmax_t'. */ +__extern_inline uintmax_t +__NTH (strtoumax (__const char *__restrict nptr, char **__restrict endptr, + int base)) +{ + return __strtoull_internal (nptr, endptr, base, 0); +} + +__extension__ +extern long long int __wcstoll_internal (__const __gwchar_t * + __restrict __nptr, + __gwchar_t **__restrict __endptr, + int __base, int __group) + __THROW __nonnull ((1)) __wur; +/* Like `wcstol' but convert to `intmax_t'. */ +__extern_inline intmax_t +__NTH (wcstoimax (__const __gwchar_t *__restrict nptr, + __gwchar_t **__restrict endptr, int base)) +{ + return __wcstoll_internal (nptr, endptr, base, 0); +} + + +__extension__ +extern unsigned long long int __wcstoull_internal (__const __gwchar_t * + __restrict __nptr, + __gwchar_t ** + __restrict __endptr, + int __base, + int __group) + __THROW __nonnull ((1)) __wur; +/* Like `wcstoul' but convert to `uintmax_t'. */ +__extern_inline uintmax_t +__NTH (wcstoumax (__const __gwchar_t *__restrict nptr, + __gwchar_t **__restrict endptr, int base)) +{ + return __wcstoull_internal (nptr, endptr, base, 0); +} + +# endif /* __WORDSIZE == 32 */ +#endif /* Use extern inlines. */ + +__END_DECLS + +#endif /* inttypes.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/langinfo.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/langinfo.h new file mode 100644 index 00000000..2e2ee4ec --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/langinfo.h @@ -0,0 +1,637 @@ +/* Access to locale-dependent parameters. + Copyright (C) 1995-2002,2003,2004,2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _LANGINFO_H +#define _LANGINFO_H 1 + +/* Get the type definition. */ +#include + +#include /* Define the __LC_* category names. */ + + +__BEGIN_DECLS + +/* Construct an `nl_item' value for `nl_langinfo' from a locale category + (LC_*) and an item index within the category. Some code may depend on + the item values within a category increasing monotonically with the + indices. */ +#if 0 +#define _NL_ITEM(category, index) (((category) << 16) | (index)) + +/* Extract the category and item index from a constructed `nl_item' value. */ +#define _NL_ITEM_CATEGORY(item) ((int) (item) >> 16) +#define _NL_ITEM_INDEX(item) ((int) (item) & 0xffff) +#else +#define _NL_ITEM(category, index) \ + (((category) << __NL_ITEM_CATEGORY_SHIFT) | (index)) + +/* Extract the category and item index from a constructed `nl_item' value. */ +#define _NL_ITEM_CATEGORY(item) ((int) (item) >> __NL_ITEM_CATEGORY_SHIFT) +#define _NL_ITEM_INDEX(item) ((int) (item) & __NL_ITEM_INDEX_MASK) +#endif + +/* Enumeration of locale items that can be queried with `nl_langinfo'. */ +enum +{ + /* LC_TIME category: date and time formatting. */ + + /* Abbreviated days of the week. */ + ABDAY_1 = _NL_ITEM (__LC_TIME, 0), /* Sun */ +#define ABDAY_1 ABDAY_1 + ABDAY_2, +#define ABDAY_2 ABDAY_2 + ABDAY_3, +#define ABDAY_3 ABDAY_3 + ABDAY_4, +#define ABDAY_4 ABDAY_4 + ABDAY_5, +#define ABDAY_5 ABDAY_5 + ABDAY_6, +#define ABDAY_6 ABDAY_6 + ABDAY_7, +#define ABDAY_7 ABDAY_7 + + /* Long-named days of the week. */ + DAY_1, /* Sunday */ +#define DAY_1 DAY_1 + DAY_2, /* Monday */ +#define DAY_2 DAY_2 + DAY_3, /* Tuesday */ +#define DAY_3 DAY_3 + DAY_4, /* Wednesday */ +#define DAY_4 DAY_4 + DAY_5, /* Thursday */ +#define DAY_5 DAY_5 + DAY_6, /* Friday */ +#define DAY_6 DAY_6 + DAY_7, /* Saturday */ +#define DAY_7 DAY_7 + + /* Abbreviated month names. */ + ABMON_1, /* Jan */ +#define ABMON_1 ABMON_1 + ABMON_2, +#define ABMON_2 ABMON_2 + ABMON_3, +#define ABMON_3 ABMON_3 + ABMON_4, +#define ABMON_4 ABMON_4 + ABMON_5, +#define ABMON_5 ABMON_5 + ABMON_6, +#define ABMON_6 ABMON_6 + ABMON_7, +#define ABMON_7 ABMON_7 + ABMON_8, +#define ABMON_8 ABMON_8 + ABMON_9, +#define ABMON_9 ABMON_9 + ABMON_10, +#define ABMON_10 ABMON_10 + ABMON_11, +#define ABMON_11 ABMON_11 + ABMON_12, +#define ABMON_12 ABMON_12 + + /* Long month names. */ + MON_1, /* January */ +#define MON_1 MON_1 + MON_2, +#define MON_2 MON_2 + MON_3, +#define MON_3 MON_3 + MON_4, +#define MON_4 MON_4 + MON_5, +#define MON_5 MON_5 + MON_6, +#define MON_6 MON_6 + MON_7, +#define MON_7 MON_7 + MON_8, +#define MON_8 MON_8 + MON_9, +#define MON_9 MON_9 + MON_10, +#define MON_10 MON_10 + MON_11, +#define MON_11 MON_11 + MON_12, +#define MON_12 MON_12 + + AM_STR, /* Ante meridian string. */ +#define AM_STR AM_STR + PM_STR, /* Post meridian string. */ +#define PM_STR PM_STR + + D_T_FMT, /* Date and time format for strftime. */ +#define D_T_FMT D_T_FMT + D_FMT, /* Date format for strftime. */ +#define D_FMT D_FMT + T_FMT, /* Time format for strftime. */ +#define T_FMT T_FMT + T_FMT_AMPM, /* 12-hour time format for strftime. */ +#define T_FMT_AMPM T_FMT_AMPM + + ERA, /* Alternate era. */ +#define ERA ERA + __ERA_YEAR, /* Year in alternate era format. */ +#ifdef __USE_GNU +# define ERA_YEAR __ERA_YEAR +#endif + ERA_D_FMT, /* Date in alternate era format. */ +#define ERA_D_FMT ERA_D_FMT + ALT_DIGITS, /* Alternate symbols for digits. */ +#define ALT_DIGITS ALT_DIGITS + ERA_D_T_FMT, /* Date and time in alternate era format. */ +#define ERA_D_T_FMT ERA_D_T_FMT + ERA_T_FMT, /* Time in alternate era format. */ +#define ERA_T_FMT ERA_T_FMT + +#if 0 + _NL_TIME_ERA_NUM_ENTRIES, /* Number entries in the era arrays. */ + _NL_TIME_ERA_ENTRIES, /* Structure with era entries in usable form.*/ + + _NL_WABDAY_1, /* Sun */ + _NL_WABDAY_2, + _NL_WABDAY_3, + _NL_WABDAY_4, + _NL_WABDAY_5, + _NL_WABDAY_6, + _NL_WABDAY_7, + + /* Long-named days of the week. */ + _NL_WDAY_1, /* Sunday */ + _NL_WDAY_2, /* Monday */ + _NL_WDAY_3, /* Tuesday */ + _NL_WDAY_4, /* Wednesday */ + _NL_WDAY_5, /* Thursday */ + _NL_WDAY_6, /* Friday */ + _NL_WDAY_7, /* Saturday */ + + /* Abbreviated month names. */ + _NL_WABMON_1, /* Jan */ + _NL_WABMON_2, + _NL_WABMON_3, + _NL_WABMON_4, + _NL_WABMON_5, + _NL_WABMON_6, + _NL_WABMON_7, + _NL_WABMON_8, + _NL_WABMON_9, + _NL_WABMON_10, + _NL_WABMON_11, + _NL_WABMON_12, + + /* Long month names. */ + _NL_WMON_1, /* January */ + _NL_WMON_2, + _NL_WMON_3, + _NL_WMON_4, + _NL_WMON_5, + _NL_WMON_6, + _NL_WMON_7, + _NL_WMON_8, + _NL_WMON_9, + _NL_WMON_10, + _NL_WMON_11, + _NL_WMON_12, + + _NL_WAM_STR, /* Ante meridian string. */ + _NL_WPM_STR, /* Post meridian string. */ + + _NL_WD_T_FMT, /* Date and time format for strftime. */ + _NL_WD_FMT, /* Date format for strftime. */ + _NL_WT_FMT, /* Time format for strftime. */ + _NL_WT_FMT_AMPM, /* 12-hour time format for strftime. */ + + _NL_WERA_YEAR, /* Year in alternate era format. */ + _NL_WERA_D_FMT, /* Date in alternate era format. */ + _NL_WALT_DIGITS, /* Alternate symbols for digits. */ + _NL_WERA_D_T_FMT, /* Date and time in alternate era format. */ + _NL_WERA_T_FMT, /* Time in alternate era format. */ + + _NL_TIME_WEEK_NDAYS, + _NL_TIME_WEEK_1STDAY, + _NL_TIME_WEEK_1STWEEK, + _NL_TIME_FIRST_WEEKDAY, + _NL_TIME_FIRST_WORKDAY, + _NL_TIME_CAL_DIRECTION, + _NL_TIME_TIMEZONE, + + _DATE_FMT, /* strftime format for date. */ +#define _DATE_FMT _DATE_FMT + _NL_W_DATE_FMT, + + _NL_TIME_CODESET, +#endif /* 0 */ + + _NL_NUM_LC_TIME, /* Number of indices in LC_TIME category. */ + + /* LC_COLLATE category: text sorting. + This information is accessed by the strcoll and strxfrm functions. + These `nl_langinfo' names are used only internally. */ +#if 0 + _NL_COLLATE_NRULES = _NL_ITEM (__LC_COLLATE, 0), + _NL_COLLATE_RULESETS, + _NL_COLLATE_TABLEMB, + _NL_COLLATE_WEIGHTMB, + _NL_COLLATE_EXTRAMB, + _NL_COLLATE_INDIRECTMB, + _NL_COLLATE_GAP1, + _NL_COLLATE_GAP2, + _NL_COLLATE_GAP3, + _NL_COLLATE_TABLEWC, + _NL_COLLATE_WEIGHTWC, + _NL_COLLATE_EXTRAWC, + _NL_COLLATE_INDIRECTWC, + _NL_COLLATE_SYMB_HASH_SIZEMB, + _NL_COLLATE_SYMB_TABLEMB, + _NL_COLLATE_SYMB_EXTRAMB, + _NL_COLLATE_COLLSEQMB, + _NL_COLLATE_COLLSEQWC, + _NL_COLLATE_CODESET, + _NL_NUM_LC_COLLATE, +#endif + + /* LC_CTYPE category: character classification. + This information is accessed by the functions in . + These `nl_langinfo' names are used only internally. */ +#if 0 + _NL_CTYPE_CLASS = _NL_ITEM (__LC_CTYPE, 0), + _NL_CTYPE_TOUPPER, + _NL_CTYPE_GAP1, + _NL_CTYPE_TOLOWER, + _NL_CTYPE_GAP2, + _NL_CTYPE_CLASS32, + _NL_CTYPE_GAP3, + _NL_CTYPE_GAP4, + _NL_CTYPE_GAP5, + _NL_CTYPE_GAP6, + _NL_CTYPE_CLASS_NAMES, + _NL_CTYPE_MAP_NAMES, + _NL_CTYPE_WIDTH, + _NL_CTYPE_MB_CUR_MAX, + _NL_CTYPE_CODESET_NAME, + CODESET = _NL_CTYPE_CODESET_NAME, +#define CODESET CODESET + _NL_CTYPE_TOUPPER32, + _NL_CTYPE_TOLOWER32, + _NL_CTYPE_CLASS_OFFSET, + _NL_CTYPE_MAP_OFFSET, + _NL_CTYPE_INDIGITS_MB_LEN, + _NL_CTYPE_INDIGITS0_MB, + _NL_CTYPE_INDIGITS1_MB, + _NL_CTYPE_INDIGITS2_MB, + _NL_CTYPE_INDIGITS3_MB, + _NL_CTYPE_INDIGITS4_MB, + _NL_CTYPE_INDIGITS5_MB, + _NL_CTYPE_INDIGITS6_MB, + _NL_CTYPE_INDIGITS7_MB, + _NL_CTYPE_INDIGITS8_MB, + _NL_CTYPE_INDIGITS9_MB, + _NL_CTYPE_INDIGITS_WC_LEN, + _NL_CTYPE_INDIGITS0_WC, + _NL_CTYPE_INDIGITS1_WC, + _NL_CTYPE_INDIGITS2_WC, + _NL_CTYPE_INDIGITS3_WC, + _NL_CTYPE_INDIGITS4_WC, + _NL_CTYPE_INDIGITS5_WC, + _NL_CTYPE_INDIGITS6_WC, + _NL_CTYPE_INDIGITS7_WC, + _NL_CTYPE_INDIGITS8_WC, + _NL_CTYPE_INDIGITS9_WC, + _NL_CTYPE_OUTDIGIT0_MB, +#else + _NL_CTYPE_OUTDIGIT0_MB = _NL_ITEM (__LC_CTYPE, 0), +#endif + _NL_CTYPE_OUTDIGIT1_MB, + _NL_CTYPE_OUTDIGIT2_MB, + _NL_CTYPE_OUTDIGIT3_MB, + _NL_CTYPE_OUTDIGIT4_MB, + _NL_CTYPE_OUTDIGIT5_MB, + _NL_CTYPE_OUTDIGIT6_MB, + _NL_CTYPE_OUTDIGIT7_MB, + _NL_CTYPE_OUTDIGIT8_MB, + _NL_CTYPE_OUTDIGIT9_MB, +#if 0 + _NL_CTYPE_OUTDIGIT0_WC, + _NL_CTYPE_OUTDIGIT1_WC, + _NL_CTYPE_OUTDIGIT2_WC, + _NL_CTYPE_OUTDIGIT3_WC, + _NL_CTYPE_OUTDIGIT4_WC, + _NL_CTYPE_OUTDIGIT5_WC, + _NL_CTYPE_OUTDIGIT6_WC, + _NL_CTYPE_OUTDIGIT7_WC, + _NL_CTYPE_OUTDIGIT8_WC, + _NL_CTYPE_OUTDIGIT9_WC, + _NL_CTYPE_TRANSLIT_TAB_SIZE, + _NL_CTYPE_TRANSLIT_FROM_IDX, + _NL_CTYPE_TRANSLIT_FROM_TBL, + _NL_CTYPE_TRANSLIT_TO_IDX, + _NL_CTYPE_TRANSLIT_TO_TBL, + _NL_CTYPE_TRANSLIT_DEFAULT_MISSING_LEN, + _NL_CTYPE_TRANSLIT_DEFAULT_MISSING, + _NL_CTYPE_TRANSLIT_IGNORE_LEN, + _NL_CTYPE_TRANSLIT_IGNORE, + _NL_CTYPE_MAP_TO_NONASCII, + _NL_CTYPE_EXTRA_MAP_1, + _NL_CTYPE_EXTRA_MAP_2, + _NL_CTYPE_EXTRA_MAP_3, + _NL_CTYPE_EXTRA_MAP_4, + _NL_CTYPE_EXTRA_MAP_5, + _NL_CTYPE_EXTRA_MAP_6, + _NL_CTYPE_EXTRA_MAP_7, + _NL_CTYPE_EXTRA_MAP_8, + _NL_CTYPE_EXTRA_MAP_9, + _NL_CTYPE_EXTRA_MAP_10, + _NL_CTYPE_EXTRA_MAP_11, + _NL_CTYPE_EXTRA_MAP_12, + _NL_CTYPE_EXTRA_MAP_13, + _NL_CTYPE_EXTRA_MAP_14, +#else /* 0 */ + _NL_CTYPE_CODESET_NAME, /* uClibc note: MUST BE LAST ENTRY!!! */ + CODESET = _NL_CTYPE_CODESET_NAME, +#define CODESET CODESET +#endif /* 0 */ + _NL_NUM_LC_CTYPE, + + /* LC_MONETARY category: formatting of monetary quantities. + These items each correspond to a member of `struct lconv', + defined in . */ + __INT_CURR_SYMBOL = _NL_ITEM (__LC_MONETARY, 0), +#ifdef __USE_GNU +# define INT_CURR_SYMBOL __INT_CURR_SYMBOL +#endif + __CURRENCY_SYMBOL, +#ifdef __USE_GNU +# define CURRENCY_SYMBOL __CURRENCY_SYMBOL +#endif + __MON_DECIMAL_POINT, +#ifdef __USE_GNU +# define MON_DECIMAL_POINT __MON_DECIMAL_POINT +#endif + __MON_THOUSANDS_SEP, +#ifdef __USE_GNU +# define MON_THOUSANDS_SEP __MON_THOUSANDS_SEP +#endif + __MON_GROUPING, +#ifdef __USE_GNU +# define MON_GROUPING __MON_GROUPING +#endif + __POSITIVE_SIGN, +#ifdef __USE_GNU +# define POSITIVE_SIGN __POSITIVE_SIGN +#endif + __NEGATIVE_SIGN, +#ifdef __USE_GNU +# define NEGATIVE_SIGN __NEGATIVE_SIGN +#endif + __INT_FRAC_DIGITS, +#ifdef __USE_GNU +# define INT_FRAC_DIGITS __INT_FRAC_DIGITS +#endif + __FRAC_DIGITS, +#ifdef __USE_GNU +# define FRAC_DIGITS __FRAC_DIGITS +#endif + __P_CS_PRECEDES, +#ifdef __USE_GNU +# define P_CS_PRECEDES __P_CS_PRECEDES +#endif + __P_SEP_BY_SPACE, +#ifdef __USE_GNU +# define P_SEP_BY_SPACE __P_SEP_BY_SPACE +#endif + __N_CS_PRECEDES, +#ifdef __USE_GNU +# define N_CS_PRECEDES __N_CS_PRECEDES +#endif + __N_SEP_BY_SPACE, +#ifdef __USE_GNU +# define N_SEP_BY_SPACE __N_SEP_BY_SPACE +#endif + __P_SIGN_POSN, +#ifdef __USE_GNU +# define P_SIGN_POSN __P_SIGN_POSN +#endif + __N_SIGN_POSN, +#ifdef __USE_GNU +# define N_SIGN_POSN __N_SIGN_POSN +#endif +#if 0 /* moved below for some reason on uClibc */ + _NL_MONETARY_CRNCYSTR, +#define CRNCYSTR _NL_MONETARY_CRNCYSTR +#endif + __INT_P_CS_PRECEDES, +#ifdef __USE_GNU +# define INT_P_CS_PRECEDES __INT_P_CS_PRECEDES +#endif + __INT_P_SEP_BY_SPACE, +#ifdef __USE_GNU +# define INT_P_SEP_BY_SPACE __INT_P_SEP_BY_SPACE +#endif + __INT_N_CS_PRECEDES, +#ifdef __USE_GNU +# define INT_N_CS_PRECEDES __INT_N_CS_PRECEDES +#endif + __INT_N_SEP_BY_SPACE, +#ifdef __USE_GNU +# define INT_N_SEP_BY_SPACE __INT_N_SEP_BY_SPACE +#endif + __INT_P_SIGN_POSN, +#ifdef __USE_GNU +# define INT_P_SIGN_POSN __INT_P_SIGN_POSN +#endif + __INT_N_SIGN_POSN, +#ifdef __USE_GNU +# define INT_N_SIGN_POSN __INT_N_SIGN_POSN +#endif +#if 1 /* moved here from above */ + _NL_MONETARY_CRNCYSTR, +#define CRNCYSTR _NL_MONETARY_CRNCYSTR +#endif +#if 0 + _NL_MONETARY_DUO_INT_CURR_SYMBOL, + _NL_MONETARY_DUO_CURRENCY_SYMBOL, + _NL_MONETARY_DUO_INT_FRAC_DIGITS, + _NL_MONETARY_DUO_FRAC_DIGITS, + _NL_MONETARY_DUO_P_CS_PRECEDES, + _NL_MONETARY_DUO_P_SEP_BY_SPACE, + _NL_MONETARY_DUO_N_CS_PRECEDES, + _NL_MONETARY_DUO_N_SEP_BY_SPACE, + _NL_MONETARY_DUO_INT_P_CS_PRECEDES, + _NL_MONETARY_DUO_INT_P_SEP_BY_SPACE, + _NL_MONETARY_DUO_INT_N_CS_PRECEDES, + _NL_MONETARY_DUO_INT_N_SEP_BY_SPACE, + _NL_MONETARY_DUO_P_SIGN_POSN, + _NL_MONETARY_DUO_N_SIGN_POSN, + _NL_MONETARY_DUO_INT_P_SIGN_POSN, + _NL_MONETARY_DUO_INT_N_SIGN_POSN, + _NL_MONETARY_UNO_VALID_FROM, + _NL_MONETARY_UNO_VALID_TO, + _NL_MONETARY_DUO_VALID_FROM, + _NL_MONETARY_DUO_VALID_TO, + _NL_MONETARY_CONVERSION_RATE, + _NL_MONETARY_DECIMAL_POINT_WC, + _NL_MONETARY_THOUSANDS_SEP_WC, + _NL_MONETARY_CODESET, +#endif /* 0 */ + _NL_NUM_LC_MONETARY, + + /* LC_NUMERIC category: formatting of numbers. + These also correspond to members of `struct lconv'; see . */ + __DECIMAL_POINT = _NL_ITEM (__LC_NUMERIC, 0), +#ifdef __USE_GNU +# define DECIMAL_POINT __DECIMAL_POINT +#endif + RADIXCHAR = __DECIMAL_POINT, +#define RADIXCHAR RADIXCHAR + __THOUSANDS_SEP, +#ifdef __USE_GNU +# define THOUSANDS_SEP __THOUSANDS_SEP +#endif + THOUSEP = __THOUSANDS_SEP, +#define THOUSEP THOUSEP + __GROUPING, +#ifdef __USE_GNU +# define GROUPING __GROUPING +#endif +#if 0 + _NL_NUMERIC_DECIMAL_POINT_WC, + _NL_NUMERIC_THOUSANDS_SEP_WC, + _NL_NUMERIC_CODESET, +#endif + _NL_NUM_LC_NUMERIC, + + __YESEXPR = _NL_ITEM (__LC_MESSAGES, 0), /* Regex matching ``yes'' input. */ +#define YESEXPR __YESEXPR + __NOEXPR, /* Regex matching ``no'' input. */ +#define NOEXPR __NOEXPR + __YESSTR, /* Output string for ``yes''. */ +#if defined __USE_GNU || (defined __USE_XOPEN && !defined __USE_XOPEN2K) +# define YESSTR __YESSTR +#endif + __NOSTR, /* Output string for ``no''. */ +#if defined __USE_GNU || (defined __USE_XOPEN && !defined __USE_XOPEN2K) +# define NOSTR __NOSTR +#endif +#if 0 + _NL_MESSAGES_CODESET, +#endif + _NL_NUM_LC_MESSAGES, + +#if 0 + _NL_PAPER_HEIGHT = _NL_ITEM (__LC_PAPER, 0), + _NL_PAPER_WIDTH, + _NL_PAPER_CODESET, + _NL_NUM_LC_PAPER, + + _NL_NAME_NAME_FMT = _NL_ITEM (__LC_NAME, 0), + _NL_NAME_NAME_GEN, + _NL_NAME_NAME_MR, + _NL_NAME_NAME_MRS, + _NL_NAME_NAME_MISS, + _NL_NAME_NAME_MS, + _NL_NAME_CODESET, + _NL_NUM_LC_NAME, + + _NL_ADDRESS_POSTAL_FMT = _NL_ITEM (__LC_ADDRESS, 0), + _NL_ADDRESS_COUNTRY_NAME, + _NL_ADDRESS_COUNTRY_POST, + _NL_ADDRESS_COUNTRY_AB2, + _NL_ADDRESS_COUNTRY_AB3, + _NL_ADDRESS_COUNTRY_CAR, + _NL_ADDRESS_COUNTRY_NUM, + _NL_ADDRESS_COUNTRY_ISBN, + _NL_ADDRESS_LANG_NAME, + _NL_ADDRESS_LANG_AB, + _NL_ADDRESS_LANG_TERM, + _NL_ADDRESS_LANG_LIB, + _NL_ADDRESS_CODESET, + _NL_NUM_LC_ADDRESS, + + _NL_TELEPHONE_TEL_INT_FMT = _NL_ITEM (__LC_TELEPHONE, 0), + _NL_TELEPHONE_TEL_DOM_FMT, + _NL_TELEPHONE_INT_SELECT, + _NL_TELEPHONE_INT_PREFIX, + _NL_TELEPHONE_CODESET, + _NL_NUM_LC_TELEPHONE, + + _NL_MEASUREMENT_MEASUREMENT = _NL_ITEM (__LC_MEASUREMENT, 0), + _NL_MEASUREMENT_CODESET, + _NL_NUM_LC_MEASUREMENT, + + _NL_IDENTIFICATION_TITLE = _NL_ITEM (__LC_IDENTIFICATION, 0), + _NL_IDENTIFICATION_SOURCE, + _NL_IDENTIFICATION_ADDRESS, + _NL_IDENTIFICATION_CONTACT, + _NL_IDENTIFICATION_EMAIL, + _NL_IDENTIFICATION_TEL, + _NL_IDENTIFICATION_FAX, + _NL_IDENTIFICATION_LANGUAGE, + _NL_IDENTIFICATION_TERRITORY, + _NL_IDENTIFICATION_AUDIENCE, + _NL_IDENTIFICATION_APPLICATION, + _NL_IDENTIFICATION_ABBREVIATION, + _NL_IDENTIFICATION_REVISION, + _NL_IDENTIFICATION_DATE, + _NL_IDENTIFICATION_CATEGORY, + _NL_IDENTIFICATION_CODESET, + _NL_NUM_LC_IDENTIFICATION, +#endif + + /* This marks the highest value used. */ + _NL_NUM +}; + +/* This macro produces an item you can pass to `nl_langinfo' or + `nl_langinfo_l' to get the name of the locale in use for CATEGORY. */ +#define _NL_LOCALE_NAME(category) _NL_ITEM ((category), -1) +#ifdef __USE_GNU +# define NL_LOCALE_NAME(category) _NL_LOCALE_NAME (category) +#endif + + +/* Return the current locale's value for ITEM. + If ITEM is invalid, an empty string is returned. + + The string returned will not change until `setlocale' is called; + it is usually in read-only memory and cannot be modified. */ + +extern char *nl_langinfo (nl_item __item) __THROW; +libc_hidden_proto(nl_langinfo) + + +#if defined __USE_GNU && defined __UCLIBC_HAS_XLOCALE__ +/* This interface is for the extended locale model. See for + more information. */ + +/* Get locale datatype definition. */ +# include + +/* Just like nl_langinfo but get the information from the locale object L. */ +extern char *nl_langinfo_l (nl_item __item, __locale_t l); +libc_hidden_proto(nl_langinfo_l) +#endif + +__END_DECLS + +#endif /* langinfo.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/lastlog.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/lastlog.h new file mode 100644 index 00000000..8cc42543 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/lastlog.h @@ -0,0 +1,4 @@ +/* This header file is used in 4.3BSD to define `struct lastlog', + which we define in . */ + +#include diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/libc-internal.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/libc-internal.h new file mode 100644 index 00000000..443b1fc5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/libc-internal.h @@ -0,0 +1,80 @@ +/* Copyright (C) 1991,92,93,95,96,97,98,99,2000,2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _LIBC_INTERNAL_H +#define _LIBC_INTERNAL_H 1 + +#include + +#ifdef __UCLIBC_BUILD_RELRO__ +# define attribute_relro __attribute__ ((section (".data.rel.ro"))) +#else +# define attribute_relro +#endif + +#ifdef __UCLIBC_HAS_TLS__ +# define attribute_tls_model_ie __attribute__ ((tls_model ("initial-exec"))) +#endif + +/* Pull in things like __attribute_used__ */ +#include + +/* --- this is added to integrate linuxthreads */ +/*#define __USE_UNIX98 1*/ + +#ifndef __ASSEMBLER__ +# ifdef IS_IN_libc + +# define __need_size_t +# include + +/* sources are built w/ _GNU_SOURCE, this gets undefined */ +#ifdef __USE_GNU +extern int __xpg_strerror_r (int __errnum, char *__buf, size_t __buflen); +libc_hidden_proto(__xpg_strerror_r) +#else +extern char *__glibc_strerror_r (int __errnum, char *__buf, size_t __buflen); +libc_hidden_proto(__glibc_strerror_r) +#endif + +/* #include */ +# ifndef __UCLIBC_HAS_THREADS__ +# define __pthread_mutex_init(mutex, mutexattr) ((void)0) +# define __pthread_mutex_lock(mutex) ((void)0) +# define __pthread_mutex_trylock(mutex) ((void)0) +# define __pthread_mutex_unlock(mutex) ((void)0) +# define _pthread_cleanup_push_defer(mutex) ((void)0) +# define _pthread_cleanup_pop_restore(mutex) ((void)0) +# endif + +/* internal access to program name */ +extern const char *__uclibc_progname attribute_hidden; + +# endif /* IS_IN_libc */ + +#endif /* __ASSEMBLER__ */ + +/* Some people like to build up uClibc with *-elf toolchains, so + * a little grease here until we drop '#ifdef __linux__' checks + * from our source code. + */ +#ifndef __linux__ +# define __linux__ 1 +#endif + +#endif /* _LIBC_INTERNAL_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/libc-symbols.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/libc-symbols.h new file mode 100644 index 00000000..1e06f8e3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/libc-symbols.h @@ -0,0 +1,790 @@ +/* Support macros for making weak and strong aliases for symbols, + and for using symbol sets and linker warnings with GNU ld. + Copyright (C) 1995-1998,2000-2003,2004,2005,2006 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _LIBC_SYMBOLS_H +#define _LIBC_SYMBOLS_H 1 + +/* This is defined for the compilation of all C library code. features.h + tests this to avoid inclusion of stubs.h while compiling the library, + before stubs.h has been generated. Some library code that is shared + with other packages also tests this symbol to see if it is being + compiled as part of the C library. We must define this before including + config.h, because it makes some definitions conditional on whether libc + itself is being compiled, or just some generator program. */ +#define _LIBC 1 + + +/* This file's macros are included implicitly in the compilation of every + file in the C library by -imacros. + + We include uClibc_arch_features.h which is defined by arch devs. + It should define for us the following symbols: + + * HAVE_ASM_SET_DIRECTIVE if we have `.set B, A' instead of `A = B'. + * ASM_GLOBAL_DIRECTIVE with `.globl' or `.global'. + * ASM_TYPE_DIRECTIVE_PREFIX with `@' or `#' or whatever for .type, + or leave it undefined if there is no .type directive. + * HAVE_ELF if using ELF, which supports weak symbols using `.weak'. + * HAVE_ASM_WEAK_DIRECTIVE if we have weak symbols using `.weak'. + * HAVE_ASM_WEAKEXT_DIRECTIVE if we have weak symbols using `.weakext'. + + */ + +#include + +/* Enable declarations of GNU extensions, since we are compiling them. */ +#define _GNU_SOURCE 1 + +/* Prepare for the case that `__builtin_expect' is not available. */ +#if defined __GNUC__ && __GNUC__ == 2 && __GNUC_MINOR__ < 96 +# define __builtin_expect(x, expected_value) (x) +#endif +#ifndef likely +# define likely(x) __builtin_expect((!!(x)),1) +#endif +#ifndef unlikely +# define unlikely(x) __builtin_expect((!!(x)),0) +#endif +#if defined __GNUC__ && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) +# ifndef __cold +# define __cold __attribute__ ((__cold__)) +# endif +# ifndef __hot +# define __hot __attribute__ ((__hot__)) +# endif +#else +# ifndef __cold +# define __cold +# endif +# ifndef __hot +# define __hot +# endif +#endif +#ifndef __LINUX_COMPILER_H +# define __LINUX_COMPILER_H +#endif +#ifndef __cast__ +# define __cast__(_to) +#endif + +#if defined __GNUC__ && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)) +# define attribute_optimize(x) __attribute__ ((optimize(x))) +#else +# define attribute_optimize(x) +#endif + +#define attribute_unused __attribute__ ((unused)) + +#if defined __GNUC__ || defined __ICC +# define attribute_noreturn __attribute__ ((__noreturn__)) +#else +# define attribute_noreturn +#endif + +#define libc_freeres_ptr(decl) \ + __make_section_unallocated ("__libc_freeres_ptrs, \"aw\", %nobits") \ + decl __attribute__ ((section ("__libc_freeres_ptrs" __sec_comment))) +#define __libc_freeres_fn_section \ + __attribute__ ((section ("__libc_freeres_fn"))) + +#ifndef NOT_IN_libc +# define IS_IN_libc 1 +#endif + +/* Indirect stringification. Doing two levels allows + * the parameter to be a macro itself. + */ +#define __stringify_1(x) #x +#define __stringify(x) __stringify_1(x) + +#ifdef __UCLIBC_HAVE_ASM_SET_DIRECTIVE__ +# define HAVE_ASM_SET_DIRECTIVE +#else +# undef HAVE_ASM_SET_DIRECTIVE +#endif + +#ifdef __UCLIBC_ASM_GLOBAL_DIRECTIVE__ +# define ASM_GLOBAL_DIRECTIVE __UCLIBC_ASM_GLOBAL_DIRECTIVE__ +#else +# define ASM_GLOBAL_DIRECTIVE .global +#endif + +#ifdef __UCLIBC_HAVE_ASM_WEAK_DIRECTIVE__ +# define HAVE_ASM_WEAK_DIRECTIVE +#else +# undef HAVE_ASM_WEAK_DIRECTIVE +#endif + +#ifdef __UCLIBC_HAVE_ASM_WEAKEXT_DIRECTIVE__ +# define HAVE_ASM_WEAKEXT_DIRECTIVE +#else +# undef HAVE_ASM_WEAKEXT_DIRECTIVE +#endif + +#ifdef __UCLIBC_HAVE_ASM_GLOBAL_DOT_NAME__ +# define HAVE_ASM_GLOBAL_DOT_NAME +#else +# undef HAVE_ASM_GLOBAL_DOT_NAME +#endif + +#ifdef __UCLIBC_HAVE_ASM_CFI_DIRECTIVES__ +# define HAVE_ASM_CFI_DIRECTIVES +#else +# undef HAVE_ASM_CFI_DIRECTIVES +#endif + +#if defined HAVE_ASM_WEAK_DIRECTIVE || defined HAVE_ASM_WEAKEXT_DIRECTIVE +# define HAVE_WEAK_SYMBOLS +#endif + +#undef C_SYMBOL_NAME +#ifndef C_SYMBOL_NAME +# ifndef __UCLIBC_UNDERSCORES__ +# define C_SYMBOL_NAME(name) name +# else +# define C_SYMBOL_NAME(name) _##name +# endif +#endif + +#ifdef __UCLIBC_ASM_LINE_SEP__ +# define ASM_LINE_SEP __UCLIBC_ASM_LINE_SEP__ +#else +# define ASM_LINE_SEP ; +#endif + +#ifdef HAVE_ASM_GLOBAL_DOT_NAME +# ifndef C_SYMBOL_DOT_NAME +# if defined __GNUC__ && defined __GNUC_MINOR__ \ + && (__GNUC__ << 16) + __GNUC_MINOR__ >= (3 << 16) + 1 +# define C_SYMBOL_DOT_NAME(name) .name +# else +# define C_SYMBOL_DOT_NAME(name) .##name +# endif +# endif +#endif + +#ifndef __ASSEMBLER__ +/* GCC understands weak symbols and aliases; use its interface where + possible, instead of embedded assembly language. */ + +/* Define ALIASNAME as a strong alias for NAME. */ +# define strong_alias(name, aliasname) _strong_alias(name, aliasname) +# define _strong_alias(name, aliasname) \ + extern __typeof (name) aliasname __attribute__ ((alias (#name))); +/* Same, but does not check for type match. Use sparingly. + Example: strong_alias(stat,stat64) may fail, this one works: */ +# define strong_alias_untyped(name, aliasname) \ + _strong_alias_untyped(name, aliasname) +# define _strong_alias_untyped(name, aliasname) \ + extern __typeof (aliasname) aliasname __attribute__ ((alias (#name))); + +/* This comes between the return type and function name in + a function definition to make that definition weak. */ +# define weak_function __attribute__ ((weak)) +# define weak_const_function __attribute__ ((weak, __const__)) + +# ifdef HAVE_WEAK_SYMBOLS + +/* Define ALIASNAME as a weak alias for NAME. + If weak aliases are not available, this defines a strong alias. */ +# define weak_alias(name, aliasname) _weak_alias (name, aliasname) +# define _weak_alias(name, aliasname) \ + extern __typeof (name) aliasname __attribute__ ((weak, alias (#name))); + +/* Declare SYMBOL as weak undefined symbol (resolved to 0 if not defined). */ +# define weak_extern(symbol) _weak_extern (weak symbol) +# define _weak_extern(expr) _Pragma (#expr) + +# else + +# define weak_alias(name, aliasname) strong_alias(name, aliasname) +# define weak_extern(symbol) /* Nothing. */ + +# endif + +#else /* __ASSEMBLER__ */ + +# ifdef HAVE_ASM_SET_DIRECTIVE +# ifdef HAVE_ASM_GLOBAL_DOT_NAME +# define strong_alias(original, alias) \ + ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(alias) ASM_LINE_SEP \ + .set C_SYMBOL_NAME(alias),C_SYMBOL_NAME(original) ASM_LINE_SEP \ + ASM_GLOBAL_DIRECTIVE C_SYMBOL_DOT_NAME(alias) ASM_LINE_SEP \ + .set C_SYMBOL_DOT_NAME(alias),C_SYMBOL_DOT_NAME(original) +# define strong_data_alias(original, alias) \ + ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(alias) ASM_LINE_SEP \ + .set C_SYMBOL_NAME(alias),C_SYMBOL_NAME(original) +# else +# define strong_alias(original, alias) \ + ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(alias) ASM_LINE_SEP \ + .set C_SYMBOL_NAME(alias),C_SYMBOL_NAME(original) +# define strong_data_alias(original, alias) strong_alias(original, alias) +# endif +# else +# ifdef HAVE_ASM_GLOBAL_DOT_NAME +# define strong_alias(original, alias) \ + ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(alias) ASM_LINE_SEP \ + C_SYMBOL_NAME(alias) = C_SYMBOL_NAME(original) ASM_LINE_SEP \ + ASM_GLOBAL_DIRECTIVE C_SYMBOL_DOT_NAME(alias) ASM_LINE_SEP \ + C_SYMBOL_DOT_NAME(alias) = C_SYMBOL_DOT_NAME(original) +# define strong_data_alias(original, alias) \ + ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(alias) ASM_LINE_SEP \ + C_SYMBOL_NAME(alias) = C_SYMBOL_NAME(original) +# else +# define strong_alias(original, alias) \ + ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(alias) ASM_LINE_SEP \ + C_SYMBOL_NAME(alias) = C_SYMBOL_NAME(original) +# define strong_data_alias(original, alias) strong_alias(original, alias) +# endif +# endif + +# ifdef HAVE_WEAK_SYMBOLS +# ifdef HAVE_ASM_WEAKEXT_DIRECTIVE +# ifdef HAVE_ASM_GLOBAL_DOT_NAME +# define weak_alias(original, alias) \ + .weakext C_SYMBOL_NAME(alias),C_SYMBOL_NAME(original) ASM_LINE_SEP \ + .weakext C_SYMBOL_DOT_NAME(alias),C_SYMBOL_DOT_NAME(original) +# else +# define weak_alias(original, alias) \ + .weakext C_SYMBOL_NAME(alias),C_SYMBOL_NAME(original) +# endif +# define weak_extern(symbol) \ + .weakext C_SYMBOL_NAME(symbol) + +# else /* ! HAVE_ASM_WEAKEXT_DIRECTIVE */ + +# ifdef HAVE_ASM_SET_DIRECTIVE +# ifdef HAVE_ASM_GLOBAL_DOT_NAME +# define weak_alias(original, alias) \ + .weak C_SYMBOL_NAME(alias) ASM_LINE_SEP \ + .set C_SYMBOL_NAME(alias),C_SYMBOL_NAME(original) ASM_LINE_SEP \ + .weak C_SYMBOL_DOT_NAME(alias) ASM_LINE_SEP \ + .set C_SYMBOL_DOT_NAME(alias),C_SYMBOL_DOT_NAME(original) +# else +# define weak_alias(original, alias) \ + .weak C_SYMBOL_NAME(alias) ASM_LINE_SEP \ + .set C_SYMBOL_NAME(alias),C_SYMBOL_NAME(original) +# endif +# else /* ! HAVE_ASM_SET_DIRECTIVE */ +# ifdef HAVE_ASM_GLOBAL_DOT_NAME +# define weak_alias(original, alias) \ + .weak C_SYMBOL_NAME(alias) ASM_LINE_SEP \ + C_SYMBOL_NAME(alias) = C_SYMBOL_NAME(original) ASM_LINE_SEP \ + .weak C_SYMBOL_DOT_NAME(alias) ASM_LINE_SEP \ + C_SYMBOL_DOT_NAME(alias) = C_SYMBOL_DOT_NAME(original) +# else +# define weak_alias(original, alias) \ + .weak C_SYMBOL_NAME(alias) ASM_LINE_SEP \ + C_SYMBOL_NAME(alias) = C_SYMBOL_NAME(original) +# endif +# endif +# define weak_extern(symbol) \ + .weak C_SYMBOL_NAME(symbol) + +# endif /* ! HAVE_ASM_WEAKEXT_DIRECTIVE */ + +# else /* ! HAVE_WEAK_SYMBOLS */ + +# define weak_alias(original, alias) strong_alias(original, alias) +# define weak_extern(symbol) /* Nothing */ +# endif /* ! HAVE_WEAK_SYMBOLS */ + +#endif /* __ASSEMBLER__ */ + + +/* On some platforms we can make internal function calls (i.e., calls of + functions not exported) a bit faster by using a different calling + convention. */ +#ifndef internal_function +# define internal_function /* empty */ +#endif + + +/* We want the .gnu.warning.SYMBOL section to be unallocated. */ +#define __make_section_unallocated(section_string) \ + __asm__ (".section " section_string "\n\t.previous"); + + +/* Tacking on "\n#APP\n\t#" to the section name makes gcc put it's bogus + section attributes on what looks like a comment to the assembler. */ +#ifdef __sparc__ /* HAVE_SECTION_QUOTES */ +# define __sec_comment "\"\n#APP\n\t#\"" +#else +# define __sec_comment "\n#APP\n\t#" +#endif + + +/* When a reference to SYMBOL is encountered, the linker will emit a + warning message MSG. */ +#define link_warning(symbol, msg) \ + __make_section_unallocated (".gnu.warning." #symbol) \ + static const char __evoke_link_warning_##symbol[] \ + __attribute__ ((used, section (".gnu.warning." #symbol __sec_comment))) \ + = msg; + +/* Handling on non-exported internal names. We have to do this only + for shared code. */ +#ifdef SHARED +# define INTUSE(name) name##_internal +# define INTDEF(name) strong_alias (name, name##_internal) +# define INTVARDEF(name) _INTVARDEF (name, name##_internal) +# if defined HAVE_VISIBILITY_ATTRIBUTE +# define _INTVARDEF(name, aliasname) \ + extern __typeof (name) aliasname __attribute__ ((alias (#name), \ + visibility ("hidden"))); +# else +# define _INTVARDEF(name, aliasname) \ + extern __typeof (name) aliasname __attribute__ ((alias (#name))); +# endif +# define INTDEF2(name, newname) strong_alias (name, newname##_internal) +# define INTVARDEF2(name, newname) _INTVARDEF (name, newname##_internal) +#else +# define INTUSE(name) name +# define INTDEF(name) +# define INTVARDEF(name) +# define INTDEF2(name, newname) +# define INTVARDEF2(name, newname) +#endif + + +/* The following macros are used for PLT bypassing within libc.so + (and if needed other libraries similarly). + + If calls to foo within libc.so should always go to foo defined in libc.so, + then in include/foo.h you add: + + int foo(int __bar); + libc_hidden_proto(foo) + + line and after the foo function definition: + + int foo(int __bar) { + return __bar; + } + libc_hidden_def(foo) + + or + + int foo(int __bar) { + return __bar; + } + libc_hidden_weak(foo) + + Similarly for global data: if references to foo within libc.so + should always go to foo defined in libc.so, then in include/foo.h: + + extern int foo; + libc_hidden_proto(foo) + + and after foo's definition: + + int foo = INITIAL_FOO_VALUE; + libc_hidden_data_def(foo) + + or + + int foo = INITIAL_FOO_VALUE; + libc_hidden_data_weak(foo) + + If foo is normally just an alias (strong or weak) to some other function, + you should use the normal strong_alias first, then add libc_hidden_def + or libc_hidden_weak: + + int baz(int __bar) { + return __bar; + } + strong_alias(baz, foo) + libc_hidden_weak(foo) + + If the function should be internal to multiple objects, say ld.so and + libc.so, the best way is to use: + + #if !defined NOT_IN_libc || defined IS_IN_rtld + hidden_proto(foo) + #endif + + in include/foo.h and the normal macros at all function definitions + depending on what DSO they belong to. + + If versioned_symbol macro is used to define foo, + libc_hidden_ver macro should be used, as in: + + int __real_foo(int __bar) { + return __bar; + } + versioned_symbol(libc, __real_foo, foo, GLIBC_2_1); + libc_hidden_ver(__real_foo, foo) + */ + +/* uClibc specific (the above comment was copied from glibc): + * + * when ppc64 will be supported, we need changes to support + * strong_data_alias (used by asm hidden_data_def) + * + * no versioning support, hidden[_data]_ver are noop + * + * hidden_def() in asm is _hidden_strong_alias (not strong_alias) + * + * libc_hidden_proto(foo) should be added after declaration + * in the header, or after extern foo... in all source files + * (this is discouraged). + * libc_hidden_def does not hide __GI_foo itself, although the name + * suggests it (hiding is done exclusively by libc_hidden_proto). + +FIXME! - ? + * The reasoning to have it after the header w/ foo's prototype is + * to get first the __REDIRECT from original header and then create + * the __GI_foo alias + + * Hunt for references which still go through PLT (example for x86): + * build shared lib, then disassemble it and search for : + * $ objdump -drx libuClibc-*.so >disasm.txt + * $ grep -F '@plt>:' disasm.txt + * + * In uclibc, malloc/free and related functions should be called + * through PLT (making it possible to use alternative malloc), + * and possibly some __pthread_xxx functions can be called through PLT + * (why?). The rest should not use PLT. + */ + +#if (defined __GNUC__ && defined __GNUC_MINOR__ \ + && (( __GNUC__ >= 3 && __GNUC_MINOR__ >= 3) || __GNUC__ >= 4) \ + ) || defined __ICC +# define attribute_hidden __attribute__ ((visibility ("hidden"))) +# define attribute_protected __attribute__ ((visibility ("protected"))) +# define __hidden_proto_hiddenattr(attrs...) __attribute__ ((visibility ("hidden"), ##attrs)) +#else +# define attribute_hidden +# define attribute_protected +# define __hidden_proto_hiddenattr(attrs...) +#endif + +#if defined NOT_FOR_L4 && /*!defined STATIC &&*/ !defined __BCC__ + +# ifndef __ASSEMBLER__ +# define hidden_proto(name, attrs...) __hidden_proto(name, __GI_##name, ##attrs) +# define __hidden_proto(name, internal, attrs...) \ + extern __typeof (name) name __asm__ (__hidden_asmname (#internal)) \ + __hidden_proto_hiddenattr (attrs); +# define __hidden_asmname(name) __hidden_asmname1 (__USER_LABEL_PREFIX__, name) +# define __hidden_asmname1(prefix, name) __hidden_asmname2(prefix, name) +# define __hidden_asmname2(prefix, name) #prefix name +# define __hidden_ver1(local, internal, name) \ + extern __typeof (name) __EI_##name __asm__(__hidden_asmname (#internal)); \ + extern __typeof (name) __EI_##name __attribute__((alias (__hidden_asmname1 (,#local)))) +# define hidden_ver(local, name) __hidden_ver1(local, __GI_##name, name); +# define hidden_data_ver(local, name) hidden_ver(local, name) +# define hidden_def(name) __hidden_ver1(__GI_##name, name, name); +# define hidden_data_def(name) hidden_def(name) +# define hidden_weak(name) \ + __hidden_ver1(__GI_##name, name, name) __attribute__((weak)); +# define hidden_data_weak(name) hidden_weak(name) + +# else /* __ASSEMBLER__ */ + +# ifdef HAVE_ASM_SET_DIRECTIVE +# ifdef HAVE_ASM_GLOBAL_DOT_NAME +# define _hidden_strong_alias(original, alias) \ + ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(alias) ASM_LINE_SEP \ + .hidden C_SYMBOL_NAME(alias) ASM_LINE_SEP \ + .set C_SYMBOL_NAME(alias),C_SYMBOL_NAME(original) ASM_LINE_SEP \ + ASM_GLOBAL_DIRECTIVE C_SYMBOL_DOT_NAME(alias) ASM_LINE_SEP \ + .hidden C_SYMBOL_DOT_NAME(alias) ASM_LINE_SEP \ + .set C_SYMBOL_DOT_NAME(alias),C_SYMBOL_DOT_NAME(original) +# else +# define _hidden_strong_alias(original, alias) \ + ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(alias) ASM_LINE_SEP \ + .hidden C_SYMBOL_NAME(alias) ASM_LINE_SEP \ + .set C_SYMBOL_NAME(alias),C_SYMBOL_NAME(original) +# endif +# else /* dont have .set directive */ +# ifdef HAVE_ASM_GLOBAL_DOT_NAME +# define _hidden_strong_alias(original, alias) \ + ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(alias) ASM_LINE_SEP \ + .hidden C_SYMBOL_NAME(alias) ASM_LINE_SEP \ + C_SYMBOL_NAME(alias) = C_SYMBOL_NAME(original) ASM_LINE_SEP \ + ASM_GLOBAL_DIRECTIVE C_SYMBOL_DOT_NAME(alias) ASM_LINE_SEP \ + .hidden C_SYMBOL_DOT_NAME(alias) ASM_LINE_SEP \ + C_SYMBOL_DOT_NAME(alias) = C_SYMBOL_DOT_NAME(original) +# else +# define _hidden_strong_alias(original, alias) \ + ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(alias) ASM_LINE_SEP \ + .hidden C_SYMBOL_NAME(alias) ASM_LINE_SEP \ + C_SYMBOL_NAME(alias) = C_SYMBOL_NAME(original) +# endif +# endif + +# ifdef HAVE_ASM_GLOBAL_DOT_NAME +# define _hidden_weak_alias(original, alias) \ + .hidden C_SYMBOL_NAME(alias) ASM_LINE_SEP \ + .hidden C_SYMBOL_DOT_NAME(alias) ASM_LINE_SEP \ + weak_alias(original, alias) +# else +# define _hidden_weak_alias(original, alias) \ + .hidden C_SYMBOL_NAME(alias) ASM_LINE_SEP \ + weak_alias(original, alias) +# endif + +/* For assembly, we need to do the opposite of what we do in C: + in assembly gcc __REDIRECT stuff is not in place, so functions + are defined by its normal name and we need to create the + __GI_* alias to it, in C __REDIRECT causes the function definition + to use __GI_* name and we need to add alias to the real name. + There is no reason to use hidden_weak over hidden_def in assembly, + but we provide it for consistency with the C usage. + hidden_proto doesn't make sense for assembly but the equivalent + is to call via the HIDDEN_JUMPTARGET macro instead of JUMPTARGET. */ +# define hidden_def(name) _hidden_strong_alias (name, __GI_##name) +# define hidden_weak(name) _hidden_weak_alias (name, __GI_##name) +# define hidden_ver(local, name) strong_alias (local, __GI_##name) +# define hidden_data_def(name) _hidden_strong_alias (name, __GI_##name) +# define hidden_data_weak(name) _hidden_weak_alias (name, __GI_##name) +# define hidden_data_ver(local, name) strong_data_alias (local, __GI_##name) +# ifdef HAVE_ASM_GLOBAL_DOT_NAME +# define HIDDEN_JUMPTARGET(name) .__GI_##name +# else +# define HIDDEN_JUMPTARGET(name) __GI_##name +# endif +# endif /* __ASSEMBLER__ */ + +#else /* not SHARED */ + +# ifndef __ASSEMBLER__ +# define hidden_proto(name, attrs...) +# else +# define HIDDEN_JUMPTARGET(name) name +# endif /* not __ASSEMBLER__ */ +# define hidden_weak(name) +# define hidden_def(name) +# define hidden_ver(local, name) +# define hidden_data_weak(name) +# define hidden_data_def(name) +# define hidden_data_ver(local, name) + +#endif /* SHARED / not SHARED */ + + +/* uClibc does not support versioning yet. */ +#define versioned_symbol(lib, local, symbol, version) /* weak_alias(local, symbol) */ +#undef hidden_ver +#define hidden_ver(local, name) /* strong_alias(local, __GI_##name) */ +#undef hidden_data_ver +#define hidden_data_ver(local, name) /* strong_alias(local,__GI_##name) */ + +#if !defined NOT_IN_libc +# define libc_hidden_proto(name, attrs...) hidden_proto (name, ##attrs) +# define libc_hidden_def(name) hidden_def (name) +# define libc_hidden_weak(name) hidden_weak (name) +# define libc_hidden_ver(local, name) hidden_ver (local, name) +# define libc_hidden_data_def(name) hidden_data_def (name) +# define libc_hidden_data_weak(name) hidden_data_weak (name) +# define libc_hidden_data_ver(local, name) hidden_data_ver (local, name) +#else +# define libc_hidden_proto(name, attrs...) +# define libc_hidden_def(name) +# define libc_hidden_weak(name) +# define libc_hidden_ver(local, name) +# define libc_hidden_data_def(name) +# define libc_hidden_data_weak(name) +# define libc_hidden_data_ver(local, name) +#endif + +#if defined NOT_IN_libc && defined IS_IN_rtld +# define rtld_hidden_proto(name, attrs...) hidden_proto (name, ##attrs) +# define rtld_hidden_def(name) hidden_def (name) +# define rtld_hidden_weak(name) hidden_weak (name) +# define rtld_hidden_ver(local, name) hidden_ver (local, name) +# define rtld_hidden_data_def(name) hidden_data_def (name) +# define rtld_hidden_data_weak(name) hidden_data_weak (name) +# define rtld_hidden_data_ver(local, name) hidden_data_ver (local, name) +#else +# define rtld_hidden_proto(name, attrs...) +# define rtld_hidden_def(name) +# define rtld_hidden_weak(name) +# define rtld_hidden_ver(local, name) +# define rtld_hidden_data_def(name) +# define rtld_hidden_data_weak(name) +# define rtld_hidden_data_ver(local, name) +#endif + +#if defined NOT_IN_libc && defined IS_IN_libm +# define libm_hidden_proto(name, attrs...) hidden_proto (name, ##attrs) +# define libm_hidden_def(name) hidden_def (name) +# define libm_hidden_weak(name) hidden_weak (name) +# define libm_hidden_ver(local, name) hidden_ver (local, name) +# define libm_hidden_data_def(name) hidden_data_def (name) +# define libm_hidden_data_weak(name) hidden_data_weak (name) +# define libm_hidden_data_ver(local, name) hidden_data_ver (local, name) +#else +# define libm_hidden_proto(name, attrs...) +# define libm_hidden_def(name) +# define libm_hidden_weak(name) +# define libm_hidden_ver(local, name) +# define libm_hidden_data_def(name) +# define libm_hidden_data_weak(name) +# define libm_hidden_data_ver(local, name) +#endif + +#if defined NOT_IN_libc && defined IS_IN_libresolv +# define libresolv_hidden_proto(name, attrs...) hidden_proto (name, ##attrs) +# define libresolv_hidden_def(name) hidden_def (name) +# define libresolv_hidden_weak(name) hidden_weak (name) +# define libresolv_hidden_ver(local, name) hidden_ver (local, name) +# define libresolv_hidden_data_def(name) hidden_data_def (name) +# define libresolv_hidden_data_weak(name) hidden_data_weak (name) +# define libresolv_hidden_data_ver(local, name) hidden_data_ver (local, name) +#else +# define libresolv_hidden_proto(name, attrs...) +# define libresolv_hidden_def(name) +# define libresolv_hidden_weak(name) +# define libresolv_hidden_ver(local, name) +# define libresolv_hidden_data_def(name) +# define libresolv_hidden_data_weak(name) +# define libresolv_hidden_data_ver(local, name) +#endif + +#if defined NOT_IN_libc && defined IS_IN_librt +# define librt_hidden_proto(name, attrs...) hidden_proto (name, ##attrs) +# define librt_hidden_def(name) hidden_def (name) +# define librt_hidden_weak(name) hidden_weak (name) +# define librt_hidden_ver(local, name) hidden_ver (local, name) +# define librt_hidden_data_def(name) hidden_data_def (name) +# define librt_hidden_data_weak(name) hidden_data_weak (name) +# define librt_hidden_data_ver(local, name) hidden_data_ver (local, name) +#else +# define librt_hidden_proto(name, attrs...) +# define librt_hidden_def(name) +# define librt_hidden_weak(name) +# define librt_hidden_ver(local, name) +# define librt_hidden_data_def(name) +# define librt_hidden_data_weak(name) +# define librt_hidden_data_ver(local, name) +#endif + +#if defined NOT_IN_libc && defined IS_IN_libdl +# define libdl_hidden_proto(name, attrs...) hidden_proto (name, ##attrs) +# define libdl_hidden_def(name) hidden_def (name) +# define libdl_hidden_weak(name) hidden_weak (name) +# define libdl_hidden_ver(local, name) hidden_ver (local, name) +# define libdl_hidden_data_def(name) hidden_data_def (name) +# define libdl_hidden_data_weak(name) hidden_data_weak (name) +# define libdl_hidden_data_ver(local, name) hidden_data_ver (local, name) +#else +# define libdl_hidden_proto(name, attrs...) +# define libdl_hidden_def(name) +# define libdl_hidden_weak(name) +# define libdl_hidden_ver(local, name) +# define libdl_hidden_data_def(name) +# define libdl_hidden_data_weak(name) +# define libdl_hidden_data_ver(local, name) +#endif + +#if defined NOT_IN_libc && defined IS_IN_libintl +# define libintl_hidden_proto(name, attrs...) hidden_proto (name, ##attrs) +# define libintl_hidden_def(name) hidden_def (name) +# define libintl_hidden_weak(name) hidden_weak (name) +# define libintl_hidden_ver(local, name) hidden_ver (local, name) +# define libintl_hidden_data_def(name) hidden_data_def (name) +# define libintl_hidden_data_weak(name) hidden_data_weak (name) +# define libintl_hidden_data_ver(local, name) hidden_data_ver(local, name) +#else +# define libintl_hidden_proto(name, attrs...) +# define libintl_hidden_def(name) +# define libintl_hidden_weak(name) +# define libintl_hidden_ver(local, name) +# define libintl_hidden_data_def(name) +# define libintl_hidden_data_weak(name) +# define libintl_hidden_data_ver(local, name) +#endif + +#if defined NOT_IN_libc && defined IS_IN_libnsl +# define libnsl_hidden_proto(name, attrs...) hidden_proto (name, ##attrs) +# define libnsl_hidden_def(name) hidden_def (name) +# define libnsl_hidden_weak(name) hidden_weak (name) +# define libnsl_hidden_ver(local, name) hidden_ver (local, name) +# define libnsl_hidden_data_def(name) hidden_data_def (name) +# define libnsl_hidden_data_weak(name) hidden_data_weak (name) +# define libnsl_hidden_data_ver(local, name) hidden_data_ver (local, name) +#else +# define libnsl_hidden_proto(name, attrs...) +# define libnsl_hidden_def(name) +# define libnsl_hidden_weak(name) +# define libnsl_hidden_ver(local, name) +# define libnsl_hidden_data_def(name) +# define libnsl_hidden_data_weak(name) +# define libnsl_hidden_data_ver(local, name) +#endif + +#if defined NOT_IN_libc && defined IS_IN_libutil +# define libutil_hidden_proto(name, attrs...) hidden_proto (name, ##attrs) +# define libutil_hidden_def(name) hidden_def (name) +# define libutil_hidden_weak(name) hidden_weak (name) +# define libutil_hidden_ver(local, name) hidden_ver (local, name) +# define libutil_hidden_data_def(name) hidden_data_def (name) +# define libutil_hidden_data_weak(name) hidden_data_weak (name) +# define libutil_hidden_data_ver(local, name) hidden_data_ver (local, name) +#else +# define libutil_hidden_proto(name, attrs...) +# define libutil_hidden_def(name) +# define libutil_hidden_weak(name) +# define libutil_hidden_ver(local, name) +# define libutil_hidden_data_def(name) +# define libutil_hidden_data_weak(name) +# define libutil_hidden_data_ver(local, name) +#endif + +#if defined NOT_IN_libc && defined IS_IN_libcrypt +# define libcrypt_hidden_proto(name, attrs...) hidden_proto (name, ##attrs) +# define libcrypt_hidden_def(name) hidden_def (name) +# define libcrypt_hidden_weak(name) hidden_weak (name) +# define libcrypt_hidden_ver(local, name) hidden_ver (local, name) +# define libcrypt_hidden_data_def(name) hidden_data_def (name) +# define libcrypt_hidden_data_weak(name) hidden_data_weak (name) +# define libcrypt_hidden_data_ver(local, name) hidden_data_ver (local, name) +#else +# define libcrypt_hidden_proto(name, attrs...) +# define libcrypt_hidden_def(name) +# define libcrypt_hidden_weak(name) +# define libcrypt_hidden_ver(local, name) +# define libcrypt_hidden_data_def(name) +# define libcrypt_hidden_data_weak(name) +# define libcrypt_hidden_data_ver(local, name) +#endif + +#if defined NOT_IN_libc && defined IS_IN_libpthread +# define libpthread_hidden_proto(name, attrs...) hidden_proto (name, ##attrs) +# define libpthread_hidden_def(name) hidden_def (name) +# define libpthread_hidden_weak(name) hidden_weak (name) +# define libpthread_hidden_ver(local, name) hidden_ver (local, name) +# define libpthread_hidden_data_def(name) hidden_data_def (name) +# define libpthread_hidden_data_weak(name) hidden_data_weak (name) +# define libpthread_hidden_data_ver(local, name) hidden_data_ver (local, name) +#else +# define libpthread_hidden_proto(name, attrs...) +# define libpthread_hidden_def(name) +# define libpthread_hidden_weak(name) +# define libpthread_hidden_ver(local, name) +# define libpthread_hidden_data_def(name) +# define libpthread_hidden_data_weak(name) +# define libpthread_hidden_data_ver(local, name) +#endif + +#endif /* libc-symbols.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/libgen.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/libgen.h new file mode 100644 index 00000000..b2525435 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/libgen.h @@ -0,0 +1,40 @@ +/* Copyright (C) 1996, 1997, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _LIBGEN_H +#define _LIBGEN_H 1 + +#include + +__BEGIN_DECLS + +/* Return directory part of PATH or "." if none is available. */ +extern char *dirname (char *__path) __THROW; + +/* Return final component of PATH. + + This is the weird XPG version of this function. It sometimes will + modify its argument. Therefore we normally use the GNU version (in + ) and only if this header is included make the XPG + version available under the real name. */ +extern char *__xpg_basename (char *__path) __THROW; +#define basename __xpg_basename + +__END_DECLS + +#endif /* libgen.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/libintl.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/libintl.h new file mode 100644 index 00000000..ba57f169 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/libintl.h @@ -0,0 +1,133 @@ +/* Message catalogs for internationalization. + Copyright (C) 1995-2002, 2004, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + This file is derived from the file libgettext.h in the GNU gettext package. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _LIBINTL_H +#define _LIBINTL_H 1 + +#include + +/* We define an additional symbol to signal that we use the GNU + implementation of gettext. */ +#define __USE_GNU_GETTEXT 1 + +/* Provide information about the supported file formats. Returns the + maximum minor revision number supported for a given major revision. */ +#define __GNU_GETTEXT_SUPPORTED_REVISION(major) \ + ((major) == 0 ? 1 : -1) + +__BEGIN_DECLS + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning "mjn3 FIXME: gettext has a prototype but isn't defined." +#warning "mjn3 FIXME: __OPTIMIZE__ is never defined." +#endif + +/* Look up MSGID in the current default message catalog for the current + LC_MESSAGES locale. If not found, returns MSGID itself (the default + text). */ +extern char *gettext (__const char *__msgid) + __THROW __attribute_format_arg__ (1); + +/* Look up MSGID in the DOMAINNAME message catalog for the current + LC_MESSAGES locale. */ +extern char *dgettext (__const char *__domainname, __const char *__msgid) + __THROW __attribute_format_arg__ (2); +#if 0 /* uClibc: disabled */ +extern char *__dgettext (__const char *__domainname, __const char *__msgid) + __THROW __attribute_format_arg__ (2); +#endif + +/* Look up MSGID in the DOMAINNAME message catalog for the current CATEGORY + locale. */ +extern char *dcgettext (__const char *__domainname, + __const char *__msgid, int __category) + __THROW __attribute_format_arg__ (2); +#if 0 /* uClibc: disabled */ +extern char *__dcgettext (__const char *__domainname, + __const char *__msgid, int __category) + __THROW __attribute_format_arg__ (2); +#endif + + +/* Similar to `gettext' but select the plural form corresponding to the + number N. */ +extern char *ngettext (__const char *__msgid1, __const char *__msgid2, + unsigned long int __n) + __THROW __attribute_format_arg__ (1) __attribute_format_arg__ (2); + +/* Similar to `dgettext' but select the plural form corresponding to the + number N. */ +extern char *dngettext (__const char *__domainname, __const char *__msgid1, + __const char *__msgid2, unsigned long int __n) + __THROW __attribute_format_arg__ (2) __attribute_format_arg__ (3); + +/* Similar to `dcgettext' but select the plural form corresponding to the + number N. */ +extern char *dcngettext (__const char *__domainname, __const char *__msgid1, + __const char *__msgid2, unsigned long int __n, + int __category) + __THROW __attribute_format_arg__ (2) __attribute_format_arg__ (3); + + +/* Set the current default message catalog to DOMAINNAME. + If DOMAINNAME is null, return the current default. + If DOMAINNAME is "", reset to the default of "messages". */ +extern char *textdomain (__const char *__domainname) __THROW; + +/* Specify that the DOMAINNAME message catalog will be found + in DIRNAME rather than in the system locale data base. */ +extern char *bindtextdomain (__const char *__domainname, + __const char *__dirname) __THROW; + +/* Specify the character encoding in which the messages from the + DOMAINNAME message catalog will be returned. */ +extern char *bind_textdomain_codeset (__const char *__domainname, + __const char *__codeset) __THROW; + + +/* Optimized version of the function above. */ +#if defined __OPTIMIZE__ && !defined __cplusplus + +/* We need NULL for `gettext'. */ +# define __need_NULL +# include + +/* We need LC_MESSAGES for `dgettext'. */ +# include + +/* These must be macros. Inlined functions are useless because the + `__builtin_constant_p' predicate in dcgettext would always return + false. */ + +# define gettext(msgid) dgettext (NULL, msgid) + +# define dgettext(domainname, msgid) \ + dcgettext (domainname, msgid, LC_MESSAGES) + +# define ngettext(msgid1, msgid2, n) dngettext (NULL, msgid1, msgid2, n) + +# define dngettext(domainname, msgid1, msgid2, n) \ + dcngettext (domainname, msgid1, msgid2, n, LC_MESSAGES) + +#endif /* Optimizing. */ + +__END_DECLS + +#endif /* libintl.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/limits.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/limits.h new file mode 100644 index 00000000..3e9a5df8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/limits.h @@ -0,0 +1,154 @@ +/* Copyright (C) 1991, 1992, 1996, 1997, 1998, 1999, 2000, 2005 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * ISO C99 Standard: 7.10/5.2.4.2.1 Sizes of integer types + */ + +#ifndef _LIBC_LIMITS_H_ +#define _LIBC_LIMITS_H_ 1 + +#include + + +/* Maximum length of any multibyte character in any locale. + We define this value here since the gcc header does not define + the correct value. */ +#define MB_LEN_MAX 16 + + +/* If we are not using GNU CC we have to define all the symbols ourself. + Otherwise use gcc's definitions (see below). */ +#if !defined __GNUC__ || __GNUC__ < 2 + +/* We only protect from multiple inclusion here, because all the other + #include's protect themselves, and in GCC 2 we may #include_next through + multiple copies of this file before we get to GCC's. */ +# ifndef _LIMITS_H +# define _LIMITS_H 1 + +#include + +/* We don't have #include_next. + Define ANSI for standard 32-bit words. */ + +/* These assume 8-bit `char's, 16-bit `short int's, + and 32-bit `int's and `long int's. */ + +/* Number of bits in a `char'. */ +# define CHAR_BIT 8 + +/* Minimum and maximum values a `signed char' can hold. */ +# define SCHAR_MIN (-128) +# define SCHAR_MAX 127 + +/* Maximum value an `unsigned char' can hold. (Minimum is 0.) */ +# define UCHAR_MAX 255 + +/* Minimum and maximum values a `char' can hold. */ +# ifdef __CHAR_UNSIGNED__ +# define CHAR_MIN 0 +# define CHAR_MAX UCHAR_MAX +# else +# define CHAR_MIN SCHAR_MIN +# define CHAR_MAX SCHAR_MAX +# endif + +/* Minimum and maximum values a `signed short int' can hold. */ +# define SHRT_MIN (-32768) +# define SHRT_MAX 32767 + +/* Maximum value an `unsigned short int' can hold. (Minimum is 0.) */ +# define USHRT_MAX 65535 + +/* Minimum and maximum values a `signed int' can hold. */ +# define INT_MIN (-INT_MAX - 1) +# define INT_MAX 2147483647 + +/* Maximum value an `unsigned int' can hold. (Minimum is 0.) */ +# define UINT_MAX 4294967295U + +/* Minimum and maximum values a `signed long int' can hold. */ +# if __WORDSIZE == 64 +# define LONG_MAX 9223372036854775807L +# else +# define LONG_MAX 2147483647L +# endif +# define LONG_MIN (-LONG_MAX - 1L) + +/* Maximum value an `unsigned long int' can hold. (Minimum is 0.) */ +# if __WORDSIZE == 64 +# define ULONG_MAX 18446744073709551615UL +# else +# define ULONG_MAX 4294967295UL +# endif + +# ifdef __USE_ISOC99 + +/* Minimum and maximum values a `signed long long int' can hold. */ +# define LLONG_MAX 9223372036854775807LL +# define LLONG_MIN (-LLONG_MAX - 1LL) + +/* Maximum value an `unsigned long long int' can hold. (Minimum is 0.) */ +# define ULLONG_MAX 18446744073709551615ULL + +# endif /* ISO C99 */ + +# endif /* limits.h */ +#endif /* GCC 2. */ + +#endif /* !_LIBC_LIMITS_H_ */ + + /* Get the compiler's limits.h, which defines almost all the ISO constants. + + We put this #include_next outside the double inclusion check because + it should be possible to include this file more than once and still get + the definitions from gcc's header. */ +#if defined __GNUC__ && !defined _GCC_LIMITS_H_ +/* `_GCC_LIMITS_H_' is what GCC's file defines. */ +# include_next +#endif + +/* The files in some gcc versions don't define LLONG_MIN, + LLONG_MAX, and ULLONG_MAX. Instead only the values gcc defined for + ages are available. */ +#if defined __USE_ISOC99 && defined __GNUC__ +# ifndef LLONG_MIN +# define LLONG_MIN (-LLONG_MAX-1) +# endif +# ifndef LLONG_MAX +# define LLONG_MAX __LONG_LONG_MAX__ +# endif +# ifndef ULLONG_MAX +# define ULLONG_MAX (LLONG_MAX * 2ULL + 1) +# endif +#endif + +#ifdef __USE_POSIX +/* POSIX adds things to . */ +# include +#endif + +#ifdef __USE_POSIX2 +# include +#endif + +#ifdef __USE_XOPEN +# include +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/link.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/link.h new file mode 100644 index 00000000..cbef6165 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/link.h @@ -0,0 +1,240 @@ +/* Data structure for communication from the run-time dynamic linker for + loaded ELF shared objects. + Copyright (C) 1995-2001, 2004, 2005, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _LINK_H +#define _LINK_H 1 + +#include +#include +#ifdef __HAVE_SHARED__ +#include +#endif +#include +#if defined _LIBC && defined __UCLIBC_HAS_TLS__ +#include +#endif + +/* We use this macro to refer to ELF types independent of the native wordsize. + `ElfW(TYPE)' is used in place of `Elf32_TYPE' or `Elf64_TYPE'. */ +#define ElfW(type) _ElfW (Elf, __ELF_NATIVE_CLASS, type) +#define _ElfW(e,w,t) _ElfW_1 (e, w, _##t) +#define _ElfW_1(e,w,t) e##w##t + +#include /* Defines __ELF_NATIVE_CLASS. */ + +/* Rendezvous structure used by the run-time dynamic linker to communicate + details of shared object loading to the debugger. If the executable's + dynamic section has a DT_DEBUG element, the run-time linker sets that + element's value to the address where this structure can be found. */ + +struct r_debug + { + int r_version; /* Version number for this protocol. */ + + struct link_map *r_map; /* Head of the chain of loaded objects. */ + + /* This is the address of a function internal to the run-time linker, + that will always be called when the linker begins to map in a + library or unmap it, and again when the mapping change is complete. + The debugger can set a breakpoint at this address if it wants to + notice shared object mapping changes. */ + ElfW(Addr) r_brk; + enum + { + /* This state value describes the mapping change taking place when + the `r_brk' address is called. */ + RT_CONSISTENT, /* Mapping change is complete. */ + RT_ADD, /* Beginning to add a new object. */ + RT_DELETE /* Beginning to remove an object mapping. */ + } r_state; + + ElfW(Addr) r_ldbase; /* Base address the linker is loaded at. */ + }; + +/* This is the instance of that structure used by the dynamic linker. */ +extern struct r_debug _r_debug; + +/* This symbol refers to the "dynamic structure" in the `.dynamic' section + of whatever module refers to `_DYNAMIC'. So, to find its own + `struct r_debug', a program could do: + for (dyn = _DYNAMIC; dyn->d_tag != DT_NULL; ++dyn) + if (dyn->d_tag == DT_DEBUG) + r_debug = (struct r_debug *) dyn->d_un.d_ptr; + */ +extern ElfW(Dyn) _DYNAMIC[]; + +#ifdef __FDPIC__ +# include +#endif + +/* Structure describing a loaded shared object. The `l_next' and `l_prev' + members form a chain of all the shared objects loaded at startup. + + These data structures exist in space used by the run-time dynamic linker; + modifying them may have disastrous results. */ + +struct link_map + { + /* These first few members are part of the protocol with the debugger. + This is the same format used in SVR4. */ + +#ifdef __FDPIC__ + struct elf32_fdpic_loadaddr l_addr; +#else + ElfW(Addr) l_addr; /* Base address shared object is loaded at. */ +#endif + char *l_name; /* Absolute file name object was found in. */ + ElfW(Dyn) *l_ld; /* Dynamic section of the shared object. */ + struct link_map *l_next, *l_prev; /* Chain of loaded objects. */ + +#if defined(USE_TLS) && USE_TLS + /* Thread-local storage related info. */ + + /* Start of the initialization image. */ + void *l_tls_initimage; + /* Size of the initialization image. */ + size_t l_tls_initimage_size; + /* Size of the TLS block. */ + size_t l_tls_blocksize; + /* Alignment requirement of the TLS block. */ + size_t l_tls_align; + /* Offset of first byte module alignment. */ + size_t l_tls_firstbyte_offset; +# ifndef NO_TLS_OFFSET +# define NO_TLS_OFFSET 0 +# endif + /* For objects present at startup time: offset in the static TLS block. */ + ptrdiff_t l_tls_offset; + /* Index of the module in the dtv array. */ + size_t l_tls_modid; + /* Nonzero if _dl_init_static_tls should be called for this module */ + unsigned int l_need_tls_init:1; +#endif + }; + +#ifdef __USE_GNU + +#if 0 +/* Version numbers for la_version handshake interface. */ +#define LAV_CURRENT 1 + +/* Activity types signaled through la_activity. */ +enum + { + LA_ACT_CONSISTENT, /* Link map consistent again. */ + LA_ACT_ADD, /* New object will be added. */ + LA_ACT_DELETE /* Objects will be removed. */ + }; + +/* Values representing origin of name for dynamic loading. */ +enum + { + LA_SER_ORIG = 0x01, /* Original name. */ + LA_SER_LIBPATH = 0x02, /* Directory from LD_LIBRARY_PATH. */ + LA_SER_RUNPATH = 0x04, /* Directory from RPATH/RUNPATH. */ + LA_SER_CONFIG = 0x08, /* Found through ldconfig. */ + LA_SER_DEFAULT = 0x40, /* Default directory. */ + LA_SER_SECURE = 0x80 /* Unused. */ + }; + +/* Values for la_objopen return value. */ +enum + { + LA_FLG_BINDTO = 0x01, /* Audit symbols bound to this object. */ + LA_FLG_BINDFROM = 0x02 /* Audit symbols bound from this object. */ + }; + +/* Values for la_symbind flags parameter. */ +enum + { + LA_SYMB_NOPLTENTER = 0x01, /* la_pltenter will not be called. */ + LA_SYMB_NOPLTEXIT = 0x02, /* la_pltexit will not be called. */ + LA_SYMB_STRUCTCALL = 0x04, /* Return value is a structure. */ + LA_SYMB_DLSYM = 0x08, /* Binding due to dlsym call. */ + LA_SYMB_ALTVALUE = 0x10 /* Value has been changed by a previous + la_symbind call. */ + }; +#endif + +struct dl_phdr_info + { +#ifdef __FDPIC__ + struct elf32_fdpic_loadaddr dlpi_addr; +#else + ElfW(Addr) dlpi_addr; +#endif + const char *dlpi_name; + const ElfW(Phdr) *dlpi_phdr; + ElfW(Half) dlpi_phnum; + +#if 0 + /* Note: Following members were introduced after the first + version of this structure was available. Check the SIZE + argument passed to the dl_iterate_phdr callback to determine + whether or not each later member is available. */ + + /* Incremented when a new object may have been added. */ + unsigned long long int dlpi_adds; + /* Incremented when an object may have been removed. */ + unsigned long long int dlpi_subs; + + /* If there is a PT_TLS segment, its module ID as used in + TLS relocations, else zero. */ + size_t dlpi_tls_modid; + + /* The address of the calling thread's instance of this module's + PT_TLS segment, if it has one and it has been allocated + in the calling thread, otherwise a null pointer. */ + void *dlpi_tls_data; +#endif + }; + +__BEGIN_DECLS + +extern int dl_iterate_phdr (int (*__callback) (struct dl_phdr_info *, + size_t, void *), + void *__data); + + +#if 0 +/* Prototypes for the ld.so auditing interfaces. These are not + defined anywhere in ld.so but instead have to be provided by the + auditing DSO. */ +extern unsigned int la_version (unsigned int __version); +extern void la_activity (uintptr_t *__cookie, unsigned int __flag); +extern char *la_objsearch (const char *__name, uintptr_t *__cookie, + unsigned int __flag); +extern unsigned int la_objopen (struct link_map *__map, Lmid_t __lmid, + uintptr_t *__cookie); +extern void la_preinit (uintptr_t *__cookie); +extern uintptr_t la_symbind32 (Elf32_Sym *__sym, unsigned int __ndx, + uintptr_t *__refcook, uintptr_t *__defcook, + unsigned int *__flags, const char *__symname); +extern uintptr_t la_symbind64 (Elf64_Sym *__sym, unsigned int __ndx, + uintptr_t *__refcook, uintptr_t *__defcook, + unsigned int *__flags, const char *__symname); +extern unsigned int la_objclose (uintptr_t *__cookie); +#endif + +__END_DECLS + +#endif + +#endif /* link.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/locale.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/locale.h new file mode 100644 index 00000000..b740908f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/locale.h @@ -0,0 +1,231 @@ +/* Copyright (C) 1991,92,95-99,2000,01,02 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * ISO C99 Standard: 7.11 Localization + */ + +#ifndef _LOCALE_H +#define _LOCALE_H 1 + +#include + +#define __need_NULL +#include +#include + +__BEGIN_DECLS + +/* These are the possibilities for the first argument to setlocale. + The code assumes that the lowest LC_* symbol has the value zero. */ +#define LC_CTYPE __LC_CTYPE +#define LC_NUMERIC __LC_NUMERIC +#define LC_TIME __LC_TIME +#define LC_COLLATE __LC_COLLATE +#define LC_MONETARY __LC_MONETARY +#define LC_MESSAGES __LC_MESSAGES +#define LC_ALL __LC_ALL +#if 0 +#define LC_PAPER __LC_PAPER +#define LC_NAME __LC_NAME +#define LC_ADDRESS __LC_ADDRESS +#define LC_TELEPHONE __LC_TELEPHONE +#define LC_MEASUREMENT __LC_MEASUREMENT +#define LC_IDENTIFICATION __LC_IDENTIFICATION +#endif + + +__BEGIN_NAMESPACE_STD + +/* Structure giving information about numeric and monetary notation. */ +struct lconv +{ + /* Numeric (non-monetary) information. */ + + char *decimal_point; /* Decimal point character. */ + char *thousands_sep; /* Thousands separator. */ + /* Each element is the number of digits in each group; + elements with higher indices are farther left. + An element with value CHAR_MAX means that no further grouping is done. + An element with value 0 means that the previous element is used + for all groups farther left. */ + char *grouping; + + /* Monetary information. */ + + /* First three chars are a currency symbol from ISO 4217. + Fourth char is the separator. Fifth char is '\0'. */ + char *int_curr_symbol; + char *currency_symbol; /* Local currency symbol. */ + char *mon_decimal_point; /* Decimal point character. */ + char *mon_thousands_sep; /* Thousands separator. */ + char *mon_grouping; /* Like `grouping' element (above). */ + char *positive_sign; /* Sign for positive values. */ + char *negative_sign; /* Sign for negative values. */ + char int_frac_digits; /* Int'l fractional digits. */ + char frac_digits; /* Local fractional digits. */ + /* 1 if currency_symbol precedes a positive value, 0 if succeeds. */ + char p_cs_precedes; + /* 1 iff a space separates currency_symbol from a positive value. */ + char p_sep_by_space; + /* 1 if currency_symbol precedes a negative value, 0 if succeeds. */ + char n_cs_precedes; + /* 1 iff a space separates currency_symbol from a negative value. */ + char n_sep_by_space; + /* Positive and negative sign positions: + 0 Parentheses surround the quantity and currency_symbol. + 1 The sign string precedes the quantity and currency_symbol. + 2 The sign string follows the quantity and currency_symbol. + 3 The sign string immediately precedes the currency_symbol. + 4 The sign string immediately follows the currency_symbol. */ + char p_sign_posn; + char n_sign_posn; +#ifdef __USE_ISOC99 + /* 1 if int_curr_symbol precedes a positive value, 0 if succeeds. */ + char int_p_cs_precedes; + /* 1 iff a space separates int_curr_symbol from a positive value. */ + char int_p_sep_by_space; + /* 1 if int_curr_symbol precedes a negative value, 0 if succeeds. */ + char int_n_cs_precedes; + /* 1 iff a space separates int_curr_symbol from a negative value. */ + char int_n_sep_by_space; + /* Positive and negative sign positions: + 0 Parentheses surround the quantity and int_curr_symbol. + 1 The sign string precedes the quantity and int_curr_symbol. + 2 The sign string follows the quantity and int_curr_symbol. + 3 The sign string immediately precedes the int_curr_symbol. + 4 The sign string immediately follows the int_curr_symbol. */ + char int_p_sign_posn; + char int_n_sign_posn; +#else + char __int_p_cs_precedes; + char __int_p_sep_by_space; + char __int_n_cs_precedes; + char __int_n_sep_by_space; + char __int_p_sign_posn; + char __int_n_sign_posn; +#endif +}; + + +/* Set and/or return the current locale. */ +extern char *setlocale (int __category, __const char *__locale) __THROW; + +/* Return the numeric/monetary information for the current locale. */ +extern struct lconv *localeconv (void) __THROW; +libc_hidden_proto(localeconv) + +__END_NAMESPACE_STD + + +#if defined __USE_GNU && defined __UCLIBC_HAS_LOCALE__ +/* The concept of one static locale per category is not very well + thought out. Many applications will need to process its data using + information from several different locales. Another application is + the implementation of the internationalization handling in the + upcoming ISO C++ standard library. To support this another set of + the functions using locale data exist which have an additional + argument. + + Attention: all these functions are *not* standardized in any form. + This is a proof-of-concept implementation. */ + +#ifdef __UCLIBC_HAS_XLOCALE__ +/* Get locale datatype definition. */ +# include +#endif + +typedef __locale_t locale_t; + +/* Return a reference to a data structure representing a set of locale + datasets. Unlike for the CATEGORY parameter for `setlocale' the + CATEGORY_MASK parameter here uses a single bit for each category, + made by OR'ing together LC_*_MASK bits above. */ +extern __locale_t newlocale (int __category_mask, __const char *__locale, + __locale_t __base) __THROW; +libc_hidden_proto(newlocale) + +/* These are the bits that can be set in the CATEGORY_MASK argument to + `newlocale'. In the GNU implementation, LC_FOO_MASK has the value + of (1 << LC_FOO), but this is not a part of the interface that + callers can assume will be true. */ +# define LC_CTYPE_MASK (1 << __LC_CTYPE) +# define LC_NUMERIC_MASK (1 << __LC_NUMERIC) +# define LC_TIME_MASK (1 << __LC_TIME) +# define LC_COLLATE_MASK (1 << __LC_COLLATE) +# define LC_MONETARY_MASK (1 << __LC_MONETARY) +# define LC_MESSAGES_MASK (1 << __LC_MESSAGES) +#ifdef L_newlocale +#warning mask defines for extra locale categories +#endif /* L_newlocale - uClibc note */ +#ifdef LC_PAPER +# define LC_PAPER_MASK (1 << __LC_PAPER) +# define LC_NAME_MASK (1 << __LC_NAME) +# define LC_ADDRESS_MASK (1 << __LC_ADDRESS) +# define LC_TELEPHONE_MASK (1 << __LC_TELEPHONE) +# define LC_MEASUREMENT_MASK (1 << __LC_MEASUREMENT) +# define LC_IDENTIFICATION_MASK (1 << __LC_IDENTIFICATION) +# define LC_ALL_MASK (LC_CTYPE_MASK \ + | LC_NUMERIC_MASK \ + | LC_TIME_MASK \ + | LC_COLLATE_MASK \ + | LC_MONETARY_MASK \ + | LC_MESSAGES_MASK \ + | LC_PAPER_MASK \ + | LC_NAME_MASK \ + | LC_ADDRESS_MASK \ + | LC_TELEPHONE_MASK \ + | LC_MEASUREMENT_MASK \ + | LC_IDENTIFICATION_MASK \ + ) +#else /* LC_PAPER */ +# define LC_ALL_MASK (LC_CTYPE_MASK \ + | LC_NUMERIC_MASK \ + | LC_TIME_MASK \ + | LC_COLLATE_MASK \ + | LC_MONETARY_MASK \ + | LC_MESSAGES_MASK \ + ) +#endif /* LC_PAPER */ + +/* Return a duplicate of the set of locale in DATASET. All usage + counters are increased if necessary. */ +extern __locale_t duplocale (__locale_t __dataset) __THROW; +libc_hidden_proto(duplocale) + +/* Free the data associated with a locale dataset previously returned + by a call to `setlocale_r'. */ +extern void freelocale (__locale_t __dataset) __THROW; + +/* Switch the current thread's locale to DATASET. + If DATASET is null, instead just return the current setting. + The special value LC_GLOBAL_LOCALE is the initial setting + for all threads and can also be installed any time, meaning + the thread uses the global settings controlled by `setlocale'. */ +extern __locale_t uselocale (__locale_t __dataset) __THROW; +libc_hidden_proto(uselocale) + +/* This value can be passed to `uselocale' and may be returned by it. + Passing this value to any other function has undefined behavior. */ +# define LC_GLOBAL_LOCALE ((__locale_t) -1L) + +#endif + +__END_DECLS + +#endif /* locale.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/malloc.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/malloc.h new file mode 100644 index 00000000..1865409f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/malloc.h @@ -0,0 +1,201 @@ +/* Prototypes and definition for malloc implementation. + Copyright (C) 1996, 1997, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _MALLOC_H +#define _MALLOC_H 1 + +#include + +/* + `ptmalloc', a malloc implementation for multiple threads without + lock contention, by Wolfram Gloger . + See the files `ptmalloc.c' or `COPYRIGHT' for copying conditions. + + VERSION 2.6.4-pt Wed Dec 4 00:35:54 MET 1996 + + This work is mainly derived from malloc-2.6.4 by Doug Lea + , which is available from: + + ftp://g.oswego.edu/pub/misc/malloc.c + + This trimmed-down header file only provides function prototypes and + the exported data structures. For more detailed function + descriptions and compile-time options, see the source file + `ptmalloc.c'. +*/ + +#if defined(__STDC__) || defined (__cplusplus) +# include +# define __malloc_ptr_t void * +#else +# undef size_t +# define size_t unsigned int +# undef ptrdiff_t +# define ptrdiff_t int +# define __malloc_ptr_t char * +#endif + +#ifdef _LIBC +/* Used by GNU libc internals. */ +# define __malloc_size_t size_t +# define __malloc_ptrdiff_t ptrdiff_t +#elif !defined __attribute_malloc__ +# define __attribute_malloc__ +#endif + +#ifdef __GNUC__ + +/* GCC can always grok prototypes. For C++ programs we add throw() + to help it optimize the function calls. But this works only with + gcc 2.8.x and egcs. */ +#ifndef __THROW +# if defined __cplusplus && (__GNUC__ >= 3 || __GNUC_MINOR__ >= 8) +# define __THROW throw () +# else +# define __THROW +# endif +#endif +# define __MALLOC_P(args) args __THROW +/* This macro will be used for functions which might take C++ callback + functions. */ +# define __MALLOC_PMT(args) args + +#else /* Not GCC. */ + +# define __THROW + +# if (defined __STDC__ && __STDC__) || defined __cplusplus + +# define __MALLOC_P(args) args +# define __MALLOC_PMT(args) args + +# else /* Not ANSI C or C++. */ + +# define __MALLOC_P(args) () /* No prototypes. */ +# define __MALLOC_PMT(args) () + +# endif /* ANSI C or C++. */ + +#endif /* GCC. */ + +#ifndef NULL +# ifdef __cplusplus +# define NULL 0 +# else +# define NULL ((__malloc_ptr_t) 0) +# endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* Allocate SIZE bytes of memory. */ +extern __malloc_ptr_t malloc __MALLOC_P ((size_t __size)) __attribute_malloc__; + +/* Allocate NMEMB elements of SIZE bytes each, all initialized to 0. */ +extern __malloc_ptr_t calloc __MALLOC_P ((size_t __nmemb, size_t __size)) + __attribute_malloc__; + +/* Re-allocate the previously allocated block in __ptr, making the new + block SIZE bytes long. */ +extern __malloc_ptr_t realloc __MALLOC_P ((__malloc_ptr_t __ptr, + size_t __size)) + __attribute_malloc__; + +/* Free a block allocated by `malloc', `realloc' or `calloc'. */ +extern void free __MALLOC_P ((__malloc_ptr_t __ptr)); + +/* Allocate SIZE bytes allocated to ALIGNMENT bytes. */ +extern __malloc_ptr_t memalign __MALLOC_P ((size_t __alignment, size_t __size)); + +/* Allocate SIZE bytes on a page boundary. */ +extern __malloc_ptr_t valloc __MALLOC_P ((size_t __size)) __attribute_malloc__; + +#ifdef __MALLOC_STANDARD__ + +/* SVID2/XPG mallinfo structure */ +struct mallinfo { + int arena; /* total space allocated from system */ + int ordblks; /* number of non-inuse chunks */ + int smblks; /* unused -- always zero */ + int hblks; /* number of mmapped regions */ + int hblkhd; /* total space in mmapped regions */ + int usmblks; /* unused -- always zero */ + int fsmblks; /* unused -- always zero */ + int uordblks; /* total allocated space */ + int fordblks; /* total non-inuse space */ + int keepcost; /* top-most, releasable (via malloc_trim) space */ +}; + +/* Returns a copy of the updated current mallinfo. */ +extern struct mallinfo mallinfo __MALLOC_P ((void)); +libc_hidden_proto(mallinfo) + +/* Release all but __pad bytes of freed top-most memory back to the + system. Return 1 if successful, else 0. */ +extern int malloc_trim(size_t pad); + +#include +/* Prints brief summary statistics to the specified file. + * Writes to stderr if file is NULL. */ +extern void malloc_stats(FILE *file); + +/* SVID2/XPG mallopt options */ +#ifndef M_MXFAST +# define M_MXFAST 1 /* UNUSED in this malloc */ +#endif +#ifndef M_NLBLKS +# define M_NLBLKS 2 /* UNUSED in this malloc */ +#endif +#ifndef M_GRAIN +# define M_GRAIN 3 /* UNUSED in this malloc */ +#endif +#ifndef M_KEEP +# define M_KEEP 4 /* UNUSED in this malloc */ +#endif + +/* mallopt options that actually do something */ +#define M_TRIM_THRESHOLD -1 +#define M_TOP_PAD -2 +#define M_MMAP_THRESHOLD -3 +#define M_MMAP_MAX -4 +#define M_CHECK_ACTION -5 +#define M_PERTURB -6 + +/* General SVID/XPG interface to tunable parameters. */ +extern int mallopt __MALLOC_P ((int __param, int __val)); + +#endif /* __MALLOC_STANDARD__ */ + +/* uClibc may use malloc internally in situations where user can not be + * notified about out-of-memory condition. In this situation uClibc will + * call __uc_malloc_failed if it is non-NULL, and retry allocation + * if it returns. If __uc_malloc_failed is NULL, uclibc will _exit(1). + * NB: do not use stdio in __uc_malloc_failed handler! */ +extern void *__uc_malloc(size_t size); +libc_hidden_proto(__uc_malloc) +extern void (*__uc_malloc_failed)(size_t size); +libc_hidden_proto(__uc_malloc_failed) + +#ifdef __cplusplus +} /* end of extern "C" */ +#endif + +#endif /* malloc.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/math.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/math.h new file mode 100644 index 00000000..d3f86f9c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/math.h @@ -0,0 +1,506 @@ +/* Declarations for math functions. + Copyright (C) 1991-1993, 1995-1999, 2001, 2002, 2004, 2006 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * ISO C99 Standard: 7.12 Mathematics + */ + +#ifndef _MATH_H +#define _MATH_H 1 + +#include + +__BEGIN_DECLS + +/* Get machine-dependent HUGE_VAL value (returned on overflow). + On all IEEE754 machines, this is +Infinity. */ +#include +#ifdef __USE_ISOC99 +# include +# include + +/* Get machine-dependent INFINITY value. */ +# include + +/* Get machine-dependent NAN value (returned for some domain errors). */ +# include +#endif /* __USE_ISOC99 */ + +/* Get general and ISO C99 specific information. */ +#include + + +/* The file contains the prototypes for all the + actual math functions. These macros are used for those prototypes, + so we can easily declare each function as both `name' and `__name', + and can declare the float versions `namef' and `__namef'. */ + +#define __MATHDECL_1(type,function,suffix,args) \ + extern type __MATH_PRECNAME(function,suffix) args __THROW + +#define __MATHDECL(type,function,suffix,args) \ + __MATHDECL_1(type,function,suffix,args); + +#define __MATHCALL(function,suffix,args) \ + __MATHDECL(_Mdouble_,function,suffix,args) + +#define __MATHDECLX(type,function,suffix,args,attrib) \ + __MATHDECL_1(type,function,suffix,args) __attribute__ (attrib); \ + __MATH_maybe_libm_hidden_proto(function) + +#define __MATHCALLX(function,suffix,args,attrib) \ + __MATHDECLX(_Mdouble_,function,suffix,args,attrib) + +/* Decls which are also used internally in libm. + Only the main variant is used internally, no need to try to avoid relocs + for the {l,f} variants. */ +#define __MATHDECLI(type,function,suffix,args) \ + __MATHDECL_1(type,function,suffix,args); \ + __MATH_maybe_libm_hidden_proto(function) + +#define __MATHCALLI(function,suffix,args) \ + __MATHDECLI(_Mdouble_,function,suffix,args) + +/* Private helpers for purely macro impls below. + Only make __foo{,f,l} visible but not (the macro-only) foo. */ +#if defined _LIBC +# define __MATHDECL_PRIV(type,function,suffix,args,attrib) \ + __MATHDECL_1(type,__CONCAT(__,function),suffix,args) __attribute__ (attrib); \ + libm_hidden_proto(__MATH_PRECNAME(__##function,suffix)) +#else +# define __MATHDECL_PRIV(type,function,suffix,args,attrib) \ + __MATHDECL_1(type,__CONCAT(__,function),suffix,args) __attribute__ (attrib); +#endif + + +/* Include the file of declarations, declaring double versions */ + +#if defined _LIBC +# define __MATH_maybe_libm_hidden_proto(x) libm_hidden_proto(x) +#else +# define __MATH_maybe_libm_hidden_proto(x) +#endif +#define _Mdouble_ double +#define __MATH_PRECNAME(name,r) __CONCAT(name,r) +#define _Mdouble_BEGIN_NAMESPACE __BEGIN_NAMESPACE_STD +#define _Mdouble_END_NAMESPACE __END_NAMESPACE_STD +#include +#undef _Mdouble_ +#undef _Mdouble_BEGIN_NAMESPACE +#undef _Mdouble_END_NAMESPACE +#undef __MATH_PRECNAME +#undef __MATH_maybe_libm_hidden_proto + + +#if defined __USE_MISC || defined __USE_ISOC99 + +/* Include the file of declarations again, this time using `float' + instead of `double' and appending f to each function name. */ + +# define __MATH_maybe_libm_hidden_proto(x) +# ifndef _Mfloat_ +# define _Mfloat_ float +# endif +# define _Mdouble_ _Mfloat_ +# ifdef __STDC__ +# define __MATH_PRECNAME(name,r) name##f##r +# else +# define __MATH_PRECNAME(name,r) name/**/f/**/r +# endif +# define _Mdouble_BEGIN_NAMESPACE __BEGIN_NAMESPACE_C99 +# define _Mdouble_END_NAMESPACE __END_NAMESPACE_C99 +# include +# undef _Mdouble_ +# undef _Mdouble_BEGIN_NAMESPACE +# undef _Mdouble_END_NAMESPACE +# undef __MATH_PRECNAME +# undef __MATH_maybe_libm_hidden_proto + + +# if (defined __STDC__ || defined __GNUC__) \ + && (!defined __NO_LONG_DOUBLE_MATH || defined __LDBL_COMPAT) +# ifdef __LDBL_COMPAT + +# ifdef __USE_ISOC99 +extern float __nldbl_nexttowardf (float __x, long double __y) __THROW + __attribute__ ((__const__)); +# ifdef __REDIRECT_NTH +extern float __REDIRECT_NTH (nexttowardf, (float __x, long double __y), __nldbl_nexttowardf) + __attribute__ ((__const__)); +extern double __REDIRECT_NTH (nexttoward, (double __x, long double __y), nextafter) + __attribute__ ((__const__)); +extern long double __REDIRECT_NTH (nexttowardl, (long double __x, long double __y), nextafter) + __attribute__ ((__const__)); +# endif +# endif + +/* Include the file of declarations again, this time using `long double' + instead of `double' and appending l to each function name. */ + +# undef __MATHDECL_1 +# define __MATHDECL_2(type,function,suffix,args,alias) \ + extern type __REDIRECT_NTH(__MATH_PRECNAME(function,suffix),args,alias) +# define __MATHDECL_1(type,function,suffix,args) \ + __MATHDECL_2(type,function,suffix,args,__CONCAT(function,suffix)) +# endif + +# define __MATH_maybe_libm_hidden_proto(x) +# ifndef _Mlong_double_ +# define _Mlong_double_ long double +# endif +# define _Mdouble_ _Mlong_double_ +# ifdef __STDC__ +# define __MATH_PRECNAME(name,r) name##l##r +# else +# define __MATH_PRECNAME(name,r) name/**/l/**/r +# endif +# define _Mdouble_BEGIN_NAMESPACE __BEGIN_NAMESPACE_C99 +# define _Mdouble_END_NAMESPACE __END_NAMESPACE_C99 +# include +# undef _Mdouble_ +# undef _Mdouble_BEGIN_NAMESPACE +# undef _Mdouble_END_NAMESPACE +# undef __MATH_PRECNAME +# undef __MATH_maybe_libm_hidden_proto + +# endif /* __STDC__ || __GNUC__ */ + +#endif /* Use misc or ISO C99. */ +#undef __MATHDECL_1 +#undef __MATHDECL +#undef __MATHCALL + + +#if defined __USE_MISC || defined __USE_XOPEN +/* This variable is used by `gamma' and `lgamma'. */ +extern int signgam; +#endif + + +/* ISO C99 defines some generic macros which work on any data type. */ +#ifdef __USE_ISOC99 + +/* Get the architecture specific values describing the floating-point + evaluation. The following symbols will get defined: + + float_t floating-point type at least as wide as `float' used + to evaluate `float' expressions + double_t floating-point type at least as wide as `double' used + to evaluate `double' expressions + + FLT_EVAL_METHOD + Defined to + 0 if `float_t' is `float' and `double_t' is `double' + 1 if `float_t' and `double_t' are `double' + 2 if `float_t' and `double_t' are `long double' + else `float_t' and `double_t' are unspecified + + INFINITY representation of the infinity value of type `float' + + FP_FAST_FMA + FP_FAST_FMAF + FP_FAST_FMAL + If defined it indicates that the `fma' function + generally executes about as fast as a multiply and an add. + This macro is defined only iff the `fma' function is + implemented directly with a hardware multiply-add instructions. + + FP_ILOGB0 Expands to a value returned by `ilogb (0.0)'. + FP_ILOGBNAN Expands to a value returned by `ilogb (NAN)'. + + DECIMAL_DIG Number of decimal digits supported by conversion between + decimal and all internal floating-point formats. + +*/ + +/* All floating-point numbers can be put in one of these categories. */ +enum + { + FP_NAN, +# define FP_NAN FP_NAN + FP_INFINITE, +# define FP_INFINITE FP_INFINITE + FP_ZERO, +# define FP_ZERO FP_ZERO + FP_SUBNORMAL, +# define FP_SUBNORMAL FP_SUBNORMAL + FP_NORMAL +# define FP_NORMAL FP_NORMAL + }; + +/* Return number of classification appropriate for X. */ +# ifdef __NO_LONG_DOUBLE_MATH +# define fpclassify(x) \ + (sizeof (x) == sizeof (float) ? __fpclassifyf (x) : __fpclassify (x)) +# else +# define fpclassify(x) \ + (sizeof (x) == sizeof (float) \ + ? __fpclassifyf (x) \ + : sizeof (x) == sizeof (double) \ + ? __fpclassify (x) : __fpclassifyl (x)) +# endif + +/* Return nonzero value if sign of X is negative. */ +# ifdef __NO_LONG_DOUBLE_MATH +# define signbit(x) \ + (sizeof (x) == sizeof (float) ? __signbitf (x) : __signbit (x)) +# else +# define signbit(x) \ + (sizeof (x) == sizeof (float) \ + ? __signbitf (x) \ + : sizeof (x) == sizeof (double) \ + ? __signbit (x) : __signbitl (x)) +# endif + +/* Return nonzero value if X is not +-Inf or NaN. */ +# ifdef __NO_LONG_DOUBLE_MATH +# define isfinite(x) \ + (sizeof (x) == sizeof (float) ? __finitef (x) : __finite (x)) +# else +# define isfinite(x) \ + (sizeof (x) == sizeof (float) \ + ? __finitef (x) \ + : sizeof (x) == sizeof (double) \ + ? __finite (x) : __finitel (x)) +# endif + +/* Return nonzero value if X is neither zero, subnormal, Inf, nor NaN. */ +# define isnormal(x) (fpclassify (x) == FP_NORMAL) + +/* Return nonzero value if X is a NaN. We could use `fpclassify' but + we already have this functions `__isnan' and it is faster. */ +# ifdef __NO_LONG_DOUBLE_MATH +# define isnan(x) \ + (sizeof (x) == sizeof (float) ? __isnanf (x) : __isnan (x)) +# else +# define isnan(x) \ + (sizeof (x) == sizeof (float) \ + ? __isnanf (x) \ + : sizeof (x) == sizeof (double) \ + ? __isnan (x) : __isnanl (x)) +# endif + +/* Return nonzero value is X is positive or negative infinity. */ +# ifdef __NO_LONG_DOUBLE_MATH +# define isinf(x) \ + (sizeof (x) == sizeof (float) ? __isinff (x) : __isinf (x)) +# else +# define isinf(x) \ + (sizeof (x) == sizeof (float) \ + ? __isinff (x) \ + : sizeof (x) == sizeof (double) \ + ? __isinf (x) : __isinfl (x)) +# endif + +/* Bitmasks for the math_errhandling macro. */ +# define MATH_ERRNO 1 /* errno set by math functions. */ +# define MATH_ERREXCEPT 2 /* Exceptions raised by math functions. */ + +#endif /* Use ISO C99. */ + +#ifdef __USE_MISC +/* Support for various different standard error handling behaviors. */ +typedef enum +{ + _IEEE_ = -1, /* According to IEEE 754/IEEE 854. */ + _SVID_, /* According to System V, release 4. */ + _XOPEN_, /* Nowadays also Unix98. */ + _POSIX_, + _ISOC_ /* Actually this is ISO C99. */ +} _LIB_VERSION_TYPE; + +/* This variable can be changed at run-time to any of the values above to + affect floating point error handling behavior (it may also be necessary + to change the hardware FPU exception settings). */ +extern _LIB_VERSION_TYPE _LIB_VERSION; +#endif + + +#ifdef __USE_SVID +/* In SVID error handling, `matherr' is called with this description + of the exceptional condition. + + We have a problem when using C++ since `exception' is a reserved + name in C++. */ +# ifdef __cplusplus +struct __exception +# else +struct exception +# endif + { + int type; + char *name; + double arg1; + double arg2; + double retval; + }; + +# ifdef __cplusplus +extern int matherr (struct __exception *__exc) throw (); +# else +extern int matherr (struct exception *__exc); +# endif + +# define X_TLOSS 1.41484755040568800000e+16 + +/* Types of exceptions in the `type' field. */ +# define DOMAIN 1 +# define SING 2 +# define OVERFLOW 3 +# define UNDERFLOW 4 +# define TLOSS 5 +# define PLOSS 6 + +/* SVID mode specifies returning this large value instead of infinity. */ +# define HUGE 3.40282347e+38F + +#else /* !SVID */ + +# ifdef __USE_XOPEN +# ifdef __UCLIBC_SUSV4_LEGACY__ +/* X/Open wants another strange constant. */ +# define MAXFLOAT 3.40282347e+38F +# endif +# endif + +#endif /* SVID */ + + +/* Some useful constants. */ +#if defined __USE_BSD || defined __USE_XOPEN +# define M_E 2.7182818284590452354 /* e */ +# define M_LOG2E 1.4426950408889634074 /* log_2 e */ +# define M_LOG10E 0.43429448190325182765 /* log_10 e */ +# define M_LN2 0.69314718055994530942 /* log_e 2 */ +# define M_LN10 2.30258509299404568402 /* log_e 10 */ +# define M_PI 3.14159265358979323846 /* pi */ +# define M_PI_2 1.57079632679489661923 /* pi/2 */ +# define M_PI_4 0.78539816339744830962 /* pi/4 */ +# define M_1_PI 0.31830988618379067154 /* 1/pi */ +# define M_2_PI 0.63661977236758134308 /* 2/pi */ +# define M_2_SQRTPI 1.12837916709551257390 /* 2/sqrt(pi) */ +# define M_SQRT2 1.41421356237309504880 /* sqrt(2) */ +# define M_SQRT1_2 0.70710678118654752440 /* 1/sqrt(2) */ +#endif + +/* The above constants are not adequate for computation using `long double's. + Therefore we provide as an extension constants with similar names as a + GNU extension. Provide enough digits for the 128-bit IEEE quad. */ +#ifdef __USE_GNU +# define M_El 2.7182818284590452353602874713526625L /* e */ +# define M_LOG2El 1.4426950408889634073599246810018921L /* log_2 e */ +# define M_LOG10El 0.4342944819032518276511289189166051L /* log_10 e */ +# define M_LN2l 0.6931471805599453094172321214581766L /* log_e 2 */ +# define M_LN10l 2.3025850929940456840179914546843642L /* log_e 10 */ +# define M_PIl 3.1415926535897932384626433832795029L /* pi */ +# define M_PI_2l 1.5707963267948966192313216916397514L /* pi/2 */ +# define M_PI_4l 0.7853981633974483096156608458198757L /* pi/4 */ +# define M_1_PIl 0.3183098861837906715377675267450287L /* 1/pi */ +# define M_2_PIl 0.6366197723675813430755350534900574L /* 2/pi */ +# define M_2_SQRTPIl 1.1283791670955125738961589031215452L /* 2/sqrt(pi) */ +# define M_SQRT2l 1.4142135623730950488016887242096981L /* sqrt(2) */ +# define M_SQRT1_2l 0.7071067811865475244008443621048490L /* 1/sqrt(2) */ +#endif + + +/* When compiling in strict ISO C compatible mode we must not use the + inline functions since they, among other things, do not set the + `errno' variable correctly. */ +#if defined __STRICT_ANSI__ && !defined __NO_MATH_INLINES +# define __NO_MATH_INLINES 1 +#endif + +#if defined __USE_ISOC99 && __GNUC_PREREQ(2,97) +/* ISO C99 defines some macros to compare number while taking care for + unordered numbers. Many FPUs provide special instructions to support + these operations. Generic support in GCC for these as builtins went + in before 3.0.0, but not all cpus added their patterns. We define + versions that use the builtins here, and will + undef/redefine as appropriate for the specific GCC version in use. */ +# define isgreater(x, y) __builtin_isgreater(x, y) +# define isgreaterequal(x, y) __builtin_isgreaterequal(x, y) +# define isless(x, y) __builtin_isless(x, y) +# define islessequal(x, y) __builtin_islessequal(x, y) +# define islessgreater(x, y) __builtin_islessgreater(x, y) +# define isunordered(u, v) __builtin_isunordered(u, v) +#endif + +/* Get machine-dependent inline versions (if there are any). */ +#ifdef __USE_EXTERN_INLINES +# include +#endif + +#ifdef __USE_ISOC99 +/* If we've still got undefined comparison macros, provide defaults. */ + +/* Return nonzero value if X is greater than Y. */ +# ifndef isgreater +# define isgreater(x, y) \ + (__extension__ \ + ({ __typeof__(x) __x = (x); __typeof__(y) __y = (y); \ + !isunordered (__x, __y) && __x > __y; })) +# endif + +/* Return nonzero value if X is greater than or equal to Y. */ +# ifndef isgreaterequal +# define isgreaterequal(x, y) \ + (__extension__ \ + ({ __typeof__(x) __x = (x); __typeof__(y) __y = (y); \ + !isunordered (__x, __y) && __x >= __y; })) +# endif + +/* Return nonzero value if X is less than Y. */ +# ifndef isless +# define isless(x, y) \ + (__extension__ \ + ({ __typeof__(x) __x = (x); __typeof__(y) __y = (y); \ + !isunordered (__x, __y) && __x < __y; })) +# endif + +/* Return nonzero value if X is less than or equal to Y. */ +# ifndef islessequal +# define islessequal(x, y) \ + (__extension__ \ + ({ __typeof__(x) __x = (x); __typeof__(y) __y = (y); \ + !isunordered (__x, __y) && __x <= __y; })) +# endif + +/* Return nonzero value if either X is less than Y or Y is less than X. */ +# ifndef islessgreater +# define islessgreater(x, y) \ + (__extension__ \ + ({ __typeof__(x) __x = (x); __typeof__(y) __y = (y); \ + !isunordered (__x, __y) && (__x < __y || __y < __x); })) +# endif + +/* Return nonzero value if arguments are unordered. */ +# ifndef isunordered +# define isunordered(u, v) \ + (__extension__ \ + ({ __typeof__(u) __u = (u); __typeof__(v) __v = (v); \ + fpclassify (__u) == FP_NAN || fpclassify (__v) == FP_NAN; })) +# endif + +#endif + +__END_DECLS + + +#endif /* math.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/memory.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/memory.h new file mode 100644 index 00000000..743fa6a9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/memory.h @@ -0,0 +1,34 @@ +/* Copyright (C) 1991, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * SVID + */ + +#ifndef _MEMORY_H +#define _MEMORY_H 1 + +#include + + +#ifndef _STRING_H +# include +#endif /* string.h */ + + +#endif /* memory.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/mntent.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/mntent.h new file mode 100644 index 00000000..a936b834 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/mntent.h @@ -0,0 +1,101 @@ +/* Utilities for reading/writing fstab, mtab, etc. + Copyright (C) 1995, 1996, 1997, 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _MNTENT_H +#define _MNTENT_H 1 + +#include +#define __need_FILE +#include +#include + + +/* File listing canonical interesting mount points. */ +#define MNTTAB _PATH_MNTTAB /* Deprecated alias. */ + +/* File listing currently active mount points. */ +#define MOUNTED _PATH_MOUNTED /* Deprecated alias. */ + + +/* General filesystem types. */ +#define MNTTYPE_IGNORE "ignore" /* Ignore this entry. */ +#define MNTTYPE_NFS "nfs" /* Network file system. */ +#define MNTTYPE_SWAP "swap" /* Swap device. */ + + +/* Generic mount options. */ +#define MNTOPT_DEFAULTS "defaults" /* Use all default options. */ +#define MNTOPT_RO "ro" /* Read only. */ +#define MNTOPT_RW "rw" /* Read/write. */ +#define MNTOPT_SUID "suid" /* Set uid allowed. */ +#define MNTOPT_NOSUID "nosuid" /* No set uid allowed. */ +#define MNTOPT_NOAUTO "noauto" /* Do not auto mount. */ + + +__BEGIN_DECLS + +/* Structure describing a mount table entry. */ +struct mntent + { + char *mnt_fsname; /* Device or server for filesystem. */ + char *mnt_dir; /* Directory mounted on. */ + char *mnt_type; /* Type of filesystem: ufs, nfs, etc. */ + char *mnt_opts; /* Comma-separated options for fs. */ + int mnt_freq; /* Dump frequency (in days). */ + int mnt_passno; /* Pass number for `fsck'. */ + }; + + +/* Prepare to begin reading and/or writing mount table entries from the + beginning of FILE. MODE is as for `fopen'. */ +extern FILE *setmntent (__const char *__file, __const char *__mode) __THROW; +libc_hidden_proto(setmntent) + +/* Read one mount table entry from STREAM. Returns a pointer to storage + reused on the next call, or null for EOF or error (use feof/ferror to + check). */ +extern struct mntent *getmntent (FILE *__stream) __THROW; + +#ifdef __USE_MISC +/* Reentrant version of the above function. */ +extern struct mntent *getmntent_r (FILE *__restrict __stream, + struct mntent *__restrict __result, + char *__restrict __buffer, + int __bufsize) __THROW; +libc_hidden_proto(getmntent_r) +#endif + +/* Write the mount table entry described by MNT to STREAM. + Return zero on success, nonzero on failure. */ +extern int addmntent (FILE *__restrict __stream, + __const struct mntent *__restrict __mnt) __THROW; + +/* Close a stream opened with `setmntent'. */ +extern int endmntent (FILE *__stream) __THROW; +libc_hidden_proto(endmntent) + +/* Search MNT->mnt_opts for an option matching OPT. + Returns the address of the substring, or null if none found. */ +extern char *hasmntopt (__const struct mntent *__mnt, + __const char *__opt) __THROW; + + +__END_DECLS + +#endif /* mntent.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/mqueue.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/mqueue.h new file mode 100644 index 00000000..f75b5061 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/mqueue.h @@ -0,0 +1,94 @@ +/* Copyright (C) 2004, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _MQUEUE_H +#define _MQUEUE_H 1 + +#include +#if defined __UCLIBC_HAS_REALTIME__ || \ + defined __UCLIBC_HAS_ADVANCED_REALTIME__ +#include +#include +#define __need_sigevent_t +#include +#define __need_timespec +#include +/* Get the definition of mqd_t and struct mq_attr. */ +#include +#endif + +__BEGIN_DECLS +#if defined __UCLIBC_HAS_REALTIME__ +/* Establish connection between a process and a message queue NAME and + return message queue descriptor or (mqd_t) -1 on error. OFLAG determines + the type of access used. If O_CREAT is on OFLAG, the third argument is + taken as a `mode_t', the mode of the created message queue, and the fourth + argument is taken as `struct mq_attr *', pointer to message queue + attributes. If the fourth argument is NULL, default attributes are + used. */ +extern mqd_t mq_open (const char *__name, int __oflag, ...) __THROW; + +/* Removes the association between message queue descriptor MQDES and its + message queue. */ +extern int mq_close (mqd_t __mqdes) __THROW; + +/* Query status and attributes of message queue MQDES. */ +extern int mq_getattr (mqd_t __mqdes, struct mq_attr *__mqstat) __THROW; + +/* Set attributes associated with message queue MQDES and if OMQSTAT is + not NULL also query its old attributes. */ +extern int mq_setattr (mqd_t __mqdes, + const struct mq_attr *__restrict __mqstat, + struct mq_attr *__restrict __omqstat) __THROW; + +/* Remove message queue named NAME. */ +extern int mq_unlink (const char *__name) __THROW; + +/* Register notification issued upon message arrival to an empty + message queue MQDES. */ +extern int mq_notify (mqd_t __mqdes, const struct sigevent *__notification) + __THROW; + +/* Receive the oldest from highest priority messages in message queue + MQDES. */ +extern ssize_t mq_receive (mqd_t __mqdes, char *__msg_ptr, size_t __msg_len, + unsigned int *__msg_prio); + +/* Add message pointed by MSG_PTR to message queue MQDES. */ +extern int mq_send (mqd_t __mqdes, const char *__msg_ptr, size_t __msg_len, + unsigned int __msg_prio); +#endif + +#if defined __USE_XOPEN2K && defined __UCLIBC_HAS_ADVANCED_REALTIME__ +/* Receive the oldest from highest priority messages in message queue + MQDES, stop waiting if ABS_TIMEOUT expires. */ +extern ssize_t mq_timedreceive (mqd_t __mqdes, char *__restrict __msg_ptr, + size_t __msg_len, + unsigned int *__restrict __msg_prio, + const struct timespec *__restrict __abs_timeout); + +/* Add message pointed by MSG_PTR to message queue MQDES, stop blocking + on full message queue if ABS_TIMEOUT expires. */ +extern int mq_timedsend (mqd_t __mqdes, const char *__msg_ptr, + size_t __msg_len, unsigned int __msg_prio, + const struct timespec *__abs_timeout); +#endif + +__END_DECLS + +#endif /* mqueue.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/net/ethernet.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/net/ethernet.h new file mode 100644 index 00000000..0242d589 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/net/ethernet.h @@ -0,0 +1,84 @@ +/* Copyright (C) 1997, 1999, 2001, 2008 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Based on the FreeBSD version of this file. Curiously, that file + lacks a copyright in the header. */ + +#ifndef __NET_ETHERNET_H +#define __NET_ETHERNET_H 1 + +#include +#include +#include /* IEEE 802.3 Ethernet constants */ + +__BEGIN_DECLS + +/* This is a name for the 48 bit ethernet address available on many + systems. */ +struct ether_addr +{ + u_int8_t ether_addr_octet[ETH_ALEN]; +} __attribute__ ((__packed__)); + +/* 10Mb/s ethernet header */ +struct ether_header +{ + u_int8_t ether_dhost[ETH_ALEN]; /* destination eth addr */ + u_int8_t ether_shost[ETH_ALEN]; /* source ether addr */ + u_int16_t ether_type; /* packet type ID field */ +} __attribute__ ((__packed__)); + +/* Ethernet protocol ID's */ +#define ETHERTYPE_PUP 0x0200 /* Xerox PUP */ +#define ETHERTYPE_SPRITE 0x0500 /* Sprite */ +#define ETHERTYPE_IP 0x0800 /* IP */ +#define ETHERTYPE_ARP 0x0806 /* Address resolution */ +#define ETHERTYPE_REVARP 0x8035 /* Reverse ARP */ +#define ETHERTYPE_AT 0x809B /* AppleTalk protocol */ +#define ETHERTYPE_AARP 0x80F3 /* AppleTalk ARP */ +#define ETHERTYPE_VLAN 0x8100 /* IEEE 802.1Q VLAN tagging */ +#define ETHERTYPE_IPX 0x8137 /* IPX */ +#define ETHERTYPE_IPV6 0x86dd /* IP protocol version 6 */ +#define ETHERTYPE_LOOPBACK 0x9000 /* used to test interfaces */ + + +#define ETHER_ADDR_LEN ETH_ALEN /* size of ethernet addr */ +#define ETHER_TYPE_LEN 2 /* bytes in type field */ +#define ETHER_CRC_LEN 4 /* bytes in CRC field */ +#define ETHER_HDR_LEN ETH_HLEN /* total octets in header */ +#define ETHER_MIN_LEN (ETH_ZLEN + ETHER_CRC_LEN) /* min packet length */ +#define ETHER_MAX_LEN (ETH_FRAME_LEN + ETHER_CRC_LEN) /* max packet length */ + +/* make sure ethenet length is valid */ +#define ETHER_IS_VALID_LEN(foo) \ + ((foo) >= ETHER_MIN_LEN && (foo) <= ETHER_MAX_LEN) + +/* + * The ETHERTYPE_NTRAILER packet types starting at ETHERTYPE_TRAIL have + * (type-ETHERTYPE_TRAIL)*512 bytes of data followed + * by an ETHER type (as given above) and then the (variable-length) header. + */ +#define ETHERTYPE_TRAIL 0x1000 /* Trailer packet */ +#define ETHERTYPE_NTRAILER 16 + +#define ETHERMTU ETH_DATA_LEN +#define ETHERMIN (ETHER_MIN_LEN - ETHER_HDR_LEN - ETHER_CRC_LEN) + +__END_DECLS + +#endif /* net/ethernet.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/net/if.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/net/if.h new file mode 100644 index 00000000..6d6d59a1 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/net/if.h @@ -0,0 +1,208 @@ +/* net/if.h -- declarations for inquiring about network interfaces + Copyright (C) 1997,98,99,2000,2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _NET_IF_H +#define _NET_IF_H 1 + +#include + +#ifdef __USE_MISC +# include +# include +#endif + + +/* Length of interface name. */ +#define IF_NAMESIZE 16 + +struct if_nameindex + { + unsigned int if_index; /* 1, 2, ... */ + char *if_name; /* null terminated name: "eth0", ... */ + }; + + +#ifdef __USE_MISC +/* Standard interface flags. */ +enum + { + IFF_UP = 0x1, /* Interface is up. */ +# define IFF_UP IFF_UP + IFF_BROADCAST = 0x2, /* Broadcast address valid. */ +# define IFF_BROADCAST IFF_BROADCAST + IFF_DEBUG = 0x4, /* Turn on debugging. */ +# define IFF_DEBUG IFF_DEBUG + IFF_LOOPBACK = 0x8, /* Is a loopback net. */ +# define IFF_LOOPBACK IFF_LOOPBACK + IFF_POINTOPOINT = 0x10, /* Interface is point-to-point link. */ +# define IFF_POINTOPOINT IFF_POINTOPOINT + IFF_NOTRAILERS = 0x20, /* Avoid use of trailers. */ +# define IFF_NOTRAILERS IFF_NOTRAILERS + IFF_RUNNING = 0x40, /* Resources allocated. */ +# define IFF_RUNNING IFF_RUNNING + IFF_NOARP = 0x80, /* No address resolution protocol. */ +# define IFF_NOARP IFF_NOARP + IFF_PROMISC = 0x100, /* Receive all packets. */ +# define IFF_PROMISC IFF_PROMISC + + /* Not supported */ + IFF_ALLMULTI = 0x200, /* Receive all multicast packets. */ +# define IFF_ALLMULTI IFF_ALLMULTI + + IFF_MASTER = 0x400, /* Master of a load balancer. */ +# define IFF_MASTER IFF_MASTER + IFF_SLAVE = 0x800, /* Slave of a load balancer. */ +# define IFF_SLAVE IFF_SLAVE + + IFF_MULTICAST = 0x1000, /* Supports multicast. */ +# define IFF_MULTICAST IFF_MULTICAST + + IFF_PORTSEL = 0x2000, /* Can set media type. */ +# define IFF_PORTSEL IFF_PORTSEL + IFF_AUTOMEDIA = 0x4000, /* Auto media select active. */ +# define IFF_AUTOMEDIA IFF_AUTOMEDIA + IFF_DYNAMIC = 0x8000 /* Dialup device with changing addresses. */ +# define IFF_DYNAMIC IFF_DYNAMIC + }; + +/* The ifaddr structure contains information about one address of an + interface. They are maintained by the different address families, + are allocated and attached when an address is set, and are linked + together so all addresses for an interface can be located. */ + +struct ifaddr + { + struct sockaddr ifa_addr; /* Address of interface. */ + union + { + struct sockaddr ifu_broadaddr; + struct sockaddr ifu_dstaddr; + } ifa_ifu; + struct iface *ifa_ifp; /* Back-pointer to interface. */ + struct ifaddr *ifa_next; /* Next address for interface. */ + }; + +# define ifa_broadaddr ifa_ifu.ifu_broadaddr /* broadcast address */ +# define ifa_dstaddr ifa_ifu.ifu_dstaddr /* other end of link */ + +/* Device mapping structure. I'd just gone off and designed a + beautiful scheme using only loadable modules with arguments for + driver options and along come the PCMCIA people 8) + + Ah well. The get() side of this is good for WDSETUP, and it'll be + handy for debugging things. The set side is fine for now and being + very small might be worth keeping for clean configuration. */ + +struct ifmap + { + unsigned long int mem_start; + unsigned long int mem_end; + unsigned short int base_addr; + unsigned char irq; + unsigned char dma; + unsigned char port; + /* 3 bytes spare */ + }; + +/* Interface request structure used for socket ioctl's. All interface + ioctl's must have parameter definitions which begin with ifr_name. + The remainder may be interface specific. */ + +struct ifreq + { +# define IFHWADDRLEN 6 +# define IFNAMSIZ IF_NAMESIZE + union + { + char ifrn_name[IFNAMSIZ]; /* Interface name, e.g. "en0". */ + } ifr_ifrn; + + union + { + struct sockaddr ifru_addr; + struct sockaddr ifru_dstaddr; + struct sockaddr ifru_broadaddr; + struct sockaddr ifru_netmask; + struct sockaddr ifru_hwaddr; + short int ifru_flags; + int ifru_ivalue; + int ifru_mtu; + struct ifmap ifru_map; + char ifru_slave[IFNAMSIZ]; /* Just fits the size */ + char ifru_newname[IFNAMSIZ]; + __caddr_t ifru_data; + } ifr_ifru; + }; +# define ifr_name ifr_ifrn.ifrn_name /* interface name */ +# define ifr_hwaddr ifr_ifru.ifru_hwaddr /* MAC address */ +# define ifr_addr ifr_ifru.ifru_addr /* address */ +# define ifr_dstaddr ifr_ifru.ifru_dstaddr /* other end of p-p lnk */ +# define ifr_broadaddr ifr_ifru.ifru_broadaddr /* broadcast address */ +# define ifr_netmask ifr_ifru.ifru_netmask /* interface net mask */ +# define ifr_flags ifr_ifru.ifru_flags /* flags */ +# define ifr_metric ifr_ifru.ifru_ivalue /* metric */ +# define ifr_mtu ifr_ifru.ifru_mtu /* mtu */ +# define ifr_map ifr_ifru.ifru_map /* device map */ +# define ifr_slave ifr_ifru.ifru_slave /* slave device */ +# define ifr_data ifr_ifru.ifru_data /* for use by interface */ +# define ifr_ifindex ifr_ifru.ifru_ivalue /* interface index */ +# define ifr_bandwidth ifr_ifru.ifru_ivalue /* link bandwidth */ +# define ifr_qlen ifr_ifru.ifru_ivalue /* queue length */ +# define ifr_newname ifr_ifru.ifru_newname /* New name */ +# define _IOT_ifreq _IOT(_IOTS(char),IFNAMSIZ,_IOTS(char),16,0,0) +# define _IOT_ifreq_short _IOT(_IOTS(char),IFNAMSIZ,_IOTS(short),1,0,0) +# define _IOT_ifreq_int _IOT(_IOTS(char),IFNAMSIZ,_IOTS(int),1,0,0) + + +/* Structure used in SIOCGIFCONF request. Used to retrieve interface + configuration for machine (useful for programs which must know all + networks accessible). */ + +struct ifconf + { + int ifc_len; /* Size of buffer. */ + union + { + __caddr_t ifcu_buf; + struct ifreq *ifcu_req; + } ifc_ifcu; + }; +# define ifc_buf ifc_ifcu.ifcu_buf /* Buffer address. */ +# define ifc_req ifc_ifcu.ifcu_req /* Array of structures. */ +# define _IOT_ifconf _IOT(_IOTS(struct ifconf),1,0,0,0,0) /* not right */ +#endif /* Misc. */ + +__BEGIN_DECLS + +/* Convert an interface name to an index, and vice versa. */ +extern unsigned int if_nametoindex (__const char *__ifname) __THROW; +libc_hidden_proto(if_nametoindex) +extern char *if_indextoname (unsigned int __ifindex, char *__ifname) __THROW; + +/* Return a list of all interfaces and their indices. */ +extern struct if_nameindex *if_nameindex (void) __THROW; +libc_hidden_proto(if_nameindex) + +/* Free the data returned from if_nameindex. */ +extern void if_freenameindex (struct if_nameindex *__ptr) __THROW; +libc_hidden_proto(if_freenameindex) + +__END_DECLS + +#endif /* net/if.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/net/if_arp.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/net/if_arp.h new file mode 100644 index 00000000..9608652e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/net/if_arp.h @@ -0,0 +1,182 @@ +/* Definitions for Address Resolution Protocol. + Copyright (C) 1997,1999,2001,2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Based on the 4.4BSD and Linux version of this file. */ + +#ifndef _NET_IF_ARP_H + +#define _NET_IF_ARP_H 1 +#include + +#include +#include + +__BEGIN_DECLS + +/* Some internals from deep down in the kernel. */ +#define MAX_ADDR_LEN 7 + + +/* This structure defines an ethernet arp header. */ + +/* ARP protocol opcodes. */ +#define ARPOP_REQUEST 1 /* ARP request. */ +#define ARPOP_REPLY 2 /* ARP reply. */ +#define ARPOP_RREQUEST 3 /* RARP request. */ +#define ARPOP_RREPLY 4 /* RARP reply. */ +#define ARPOP_InREQUEST 8 /* InARP request. */ +#define ARPOP_InREPLY 9 /* InARP reply. */ +#define ARPOP_NAK 10 /* (ATM)ARP NAK. */ + +/* See RFC 826 for protocol description. ARP packets are variable + in size; the arphdr structure defines the fixed-length portion. + Protocol type values are the same as those for 10 Mb/s Ethernet. + It is followed by the variable-sized fields ar_sha, arp_spa, + arp_tha and arp_tpa in that order, according to the lengths + specified. Field names used correspond to RFC 826. */ + +struct arphdr + { + unsigned short int ar_hrd; /* Format of hardware address. */ + unsigned short int ar_pro; /* Format of protocol address. */ + unsigned char ar_hln; /* Length of hardware address. */ + unsigned char ar_pln; /* Length of protocol address. */ + unsigned short int ar_op; /* ARP opcode (command). */ +#if 0 + /* Ethernet looks like this : This bit is variable sized + however... */ + unsigned char __ar_sha[ETH_ALEN]; /* Sender hardware address. */ + unsigned char __ar_sip[4]; /* Sender IP address. */ + unsigned char __ar_tha[ETH_ALEN]; /* Target hardware address. */ + unsigned char __ar_tip[4]; /* Target IP address. */ +#endif + }; + + +/* ARP protocol HARDWARE identifiers. */ +#define ARPHRD_NETROM 0 /* From KA9Q: NET/ROM pseudo. */ +#define ARPHRD_ETHER 1 /* Ethernet 10/100Mbps. */ +#define ARPHRD_EETHER 2 /* Experimental Ethernet. */ +#define ARPHRD_AX25 3 /* AX.25 Level 2. */ +#define ARPHRD_PRONET 4 /* PROnet token ring. */ +#define ARPHRD_CHAOS 5 /* Chaosnet. */ +#define ARPHRD_IEEE802 6 /* IEEE 802.2 Ethernet/TR/TB. */ +#define ARPHRD_ARCNET 7 /* ARCnet. */ +#define ARPHRD_APPLETLK 8 /* APPLEtalk. */ +#define ARPHRD_DLCI 15 /* Frame Relay DLCI. */ +#define ARPHRD_ATM 19 /* ATM. */ +#define ARPHRD_METRICOM 23 /* Metricom STRIP (new IANA id). */ +#define ARPHRD_IEEE1394 24 /* IEEE 1394 IPv4 - RFC 2734. */ +#define ARPHRD_EUI64 27 /* EUI-64. */ +#define ARPHRD_INFINIBAND 32 /* InfiniBand. */ + +/* Dummy types for non ARP hardware */ +#define ARPHRD_SLIP 256 +#define ARPHRD_CSLIP 257 +#define ARPHRD_SLIP6 258 +#define ARPHRD_CSLIP6 259 +#define ARPHRD_RSRVD 260 /* Notional KISS type. */ +#define ARPHRD_ADAPT 264 +#define ARPHRD_ROSE 270 +#define ARPHRD_X25 271 /* CCITT X.25. */ +#define ARPHRD_HWX25 272 /* Boards with X.25 in firmware. */ +#define ARPHRD_PPP 512 +#define ARPHRD_CISCO 513 /* Cisco HDLC. */ +#define ARPHRD_HDLC ARPHRD_CISCO +#define ARPHRD_LAPB 516 /* LAPB. */ +#define ARPHRD_DDCMP 517 /* Digital's DDCMP. */ +#define ARPHRD_RAWHDLC 518 /* Raw HDLC. */ + +#define ARPHRD_TUNNEL 768 /* IPIP tunnel. */ +#define ARPHRD_TUNNEL6 769 /* IPIP6 tunnel. */ +#define ARPHRD_FRAD 770 /* Frame Relay Access Device. */ +#define ARPHRD_SKIP 771 /* SKIP vif. */ +#define ARPHRD_LOOPBACK 772 /* Loopback device. */ +#define ARPHRD_LOCALTLK 773 /* Localtalk device. */ +#define ARPHRD_FDDI 774 /* Fiber Distributed Data Interface. */ +#define ARPHRD_BIF 775 /* AP1000 BIF. */ +#define ARPHRD_SIT 776 /* sit0 device - IPv6-in-IPv4. */ +#define ARPHRD_IPDDP 777 /* IP-in-DDP tunnel. */ +#define ARPHRD_IPGRE 778 /* GRE over IP. */ +#define ARPHRD_PIMREG 779 /* PIMSM register interface. */ +#define ARPHRD_HIPPI 780 /* High Performance Parallel I'face. */ +#define ARPHRD_ASH 781 /* (Nexus Electronics) Ash. */ +#define ARPHRD_ECONET 782 /* Acorn Econet. */ +#define ARPHRD_IRDA 783 /* Linux-IrDA. */ +#define ARPHRD_FCPP 784 /* Point to point fibrechanel. */ +#define ARPHRD_FCAL 785 /* Fibrechanel arbitrated loop. */ +#define ARPHRD_FCPL 786 /* Fibrechanel public loop. */ +#define ARPHRD_FCFABRIC 787 /* Fibrechanel fabric. */ +#define ARPHRD_IEEE802_TR 800 /* Magic type ident for TR. */ +#define ARPHRD_IEEE80211 801 /* IEEE 802.11. */ +#define ARPHRD_IEEE80211_PRISM 802 /* IEEE 802.11 + Prism2 header. */ +#define ARPHRD_IEEE80211_RADIOTAP 803 /* IEEE 802.11 + radiotap header. */ + +#define ARPHRD_VOID 0xFFFF /* Void type, nothing is known. */ +#define ARPHRD_NONE 0xFFFE /* Zero header length. */ + + +/* ARP ioctl request. */ +struct arpreq + { + struct sockaddr arp_pa; /* Protocol address. */ + struct sockaddr arp_ha; /* Hardware address. */ + int arp_flags; /* Flags. */ + struct sockaddr arp_netmask; /* Netmask (only for proxy arps). */ + char arp_dev[16]; + }; + +struct arpreq_old + { + struct sockaddr arp_pa; /* Protocol address. */ + struct sockaddr arp_ha; /* Hardware address. */ + int arp_flags; /* Flags. */ + struct sockaddr arp_netmask; /* Netmask (only for proxy arps). */ + }; + +/* ARP Flag values. */ +#define ATF_COM 0x02 /* Completed entry (ha valid). */ +#define ATF_PERM 0x04 /* Permanent entry. */ +#define ATF_PUBL 0x08 /* Publish entry. */ +#define ATF_USETRAILERS 0x10 /* Has requested trailers. */ +#define ATF_NETMASK 0x20 /* Want to use a netmask (only + for proxy entries). */ +#define ATF_DONTPUB 0x40 /* Don't answer this addresses. */ +#define ATF_MAGIC 0x80 /* Automatically added entry. */ + + +/* Support for the user space arp daemon, arpd. */ +#define ARPD_UPDATE 0x01 +#define ARPD_LOOKUP 0x02 +#define ARPD_FLUSH 0x03 + +struct arpd_request + { + unsigned short int req; /* Request type. */ + u_int32_t ip; /* IP address of entry. */ + unsigned long int dev; /* Device entry is tied to. */ + unsigned long int stamp; + unsigned long int updated; + unsigned char ha[MAX_ADDR_LEN]; /* Hardware address. */ + }; + +__END_DECLS + +#endif /* net/if_arp.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/net/if_packet.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/net/if_packet.h new file mode 100644 index 00000000..e5184e7f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/net/if_packet.h @@ -0,0 +1,37 @@ +/* Definitions for use with Linux SOCK_PACKET sockets. + Copyright (C) 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef __IF_PACKET_H +#define __IF_PACKET_H + +#include +#include + +/* This is the SOCK_PACKET address structure as used in Linux 2.0. + From Linux 2.1 the AF_PACKET interface is preferred and you should + consider using it in place of this one. */ + +struct sockaddr_pkt + { + __SOCKADDR_COMMON (spkt_); + unsigned char spkt_device[14]; + unsigned short spkt_protocol; + }; + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/net/if_ppp.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/net/if_ppp.h new file mode 100644 index 00000000..1b1c3ea6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/net/if_ppp.h @@ -0,0 +1,169 @@ +/* From: if_ppp.h,v 1.3 1995/06/12 11:36:50 paulus Exp */ + +/* + * if_ppp.h - Point-to-Point Protocol definitions. + * + * Copyright (c) 1989 Carnegie Mellon University. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY CARNEGIE MELLON UNIVERSITY AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/* + * ==FILEVERSION 960926== + * + * NOTE TO MAINTAINERS: + * If you modify this file at all, please set the above date. + * if_ppp.h is shipped with a PPP distribution as well as with the kernel; + * if everyone increases the FILEVERSION number above, then scripts + * can do the right thing when deciding whether to install a new if_ppp.h + * file. Don't change the format of that line otherwise, so the + * installation script can recognize it. + */ + + +#ifndef __NET_IF_PPP_H +#define __NET_IF_PPP_H 1 + +#include +#include + +#include +#include +#include + +__BEGIN_DECLS + +/* + * Packet sizes + */ + +#define PPP_MTU 1500 /* Default MTU (size of Info field) */ +#define PPP_MAXMRU 65000 /* Largest MRU we allow */ +#define PPP_VERSION "2.2.0" +#define PPP_MAGIC 0x5002 /* Magic value for the ppp structure */ +#define PROTO_IPX 0x002b /* protocol numbers */ +#define PROTO_DNA_RT 0x0027 /* DNA Routing */ + + +/* + * Bit definitions for flags. + */ + +#define SC_COMP_PROT 0x00000001 /* protocol compression (output) */ +#define SC_COMP_AC 0x00000002 /* header compression (output) */ +#define SC_COMP_TCP 0x00000004 /* TCP (VJ) compression (output) */ +#define SC_NO_TCP_CCID 0x00000008 /* disable VJ connection-id comp. */ +#define SC_REJ_COMP_AC 0x00000010 /* reject adrs/ctrl comp. on input */ +#define SC_REJ_COMP_TCP 0x00000020 /* reject TCP (VJ) comp. on input */ +#define SC_CCP_OPEN 0x00000040 /* Look at CCP packets */ +#define SC_CCP_UP 0x00000080 /* May send/recv compressed packets */ +#define SC_ENABLE_IP 0x00000100 /* IP packets may be exchanged */ +#define SC_COMP_RUN 0x00001000 /* compressor has been inited */ +#define SC_DECOMP_RUN 0x00002000 /* decompressor has been inited */ +#define SC_DEBUG 0x00010000 /* enable debug messages */ +#define SC_LOG_INPKT 0x00020000 /* log contents of good pkts recvd */ +#define SC_LOG_OUTPKT 0x00040000 /* log contents of pkts sent */ +#define SC_LOG_RAWIN 0x00080000 /* log all chars received */ +#define SC_LOG_FLUSH 0x00100000 /* log all chars flushed */ +#define SC_MASK 0x0fE0ffff /* bits that user can change */ + +/* state bits */ +#define SC_ESCAPED 0x80000000 /* saw a PPP_ESCAPE */ +#define SC_FLUSH 0x40000000 /* flush input until next PPP_FLAG */ +#define SC_VJ_RESET 0x20000000 /* Need to reset the VJ decompressor */ +#define SC_XMIT_BUSY 0x10000000 /* ppp_write_wakeup is active */ +#define SC_RCV_ODDP 0x08000000 /* have rcvd char with odd parity */ +#define SC_RCV_EVNP 0x04000000 /* have rcvd char with even parity */ +#define SC_RCV_B7_1 0x02000000 /* have rcvd char with bit 7 = 1 */ +#define SC_RCV_B7_0 0x01000000 /* have rcvd char with bit 7 = 0 */ +#define SC_DC_FERROR 0x00800000 /* fatal decomp error detected */ +#define SC_DC_ERROR 0x00400000 /* non-fatal decomp error detected */ + +/* + * Ioctl definitions. + */ + +struct npioctl { + int protocol; /* PPP protocol, e.g. PPP_IP */ + enum NPmode mode; +}; + +/* Structure describing a CCP configuration option, for PPPIOCSCOMPRESS */ +struct ppp_option_data { + u_int8_t *ptr; + u_int32_t length; + int transmit; +}; + +struct ifpppstatsreq { + struct ifreq b; + struct ppp_stats stats; /* statistic information */ +}; + +struct ifpppcstatsreq { + struct ifreq b; + struct ppp_comp_stats stats; +}; + +#define ifr__name b.ifr_ifrn.ifrn_name +#define stats_ptr b.ifr_ifru.ifru_data + +/* + * Ioctl definitions. + */ + +#define PPPIOCGFLAGS _IOR('t', 90, int) /* get configuration flags */ +#define PPPIOCSFLAGS _IOW('t', 89, int) /* set configuration flags */ +#define PPPIOCGASYNCMAP _IOR('t', 88, int) /* get async map */ +#define PPPIOCSASYNCMAP _IOW('t', 87, int) /* set async map */ +#define PPPIOCGUNIT _IOR('t', 86, int) /* get ppp unit number */ +#define PPPIOCGRASYNCMAP _IOR('t', 85, int) /* get receive async map */ +#define PPPIOCSRASYNCMAP _IOW('t', 84, int) /* set receive async map */ +#define PPPIOCGMRU _IOR('t', 83, int) /* get max receive unit */ +#define PPPIOCSMRU _IOW('t', 82, int) /* set max receive unit */ +#define PPPIOCSMAXCID _IOW('t', 81, int) /* set VJ max slot ID */ +#define PPPIOCGXASYNCMAP _IOR('t', 80, ext_accm) /* get extended ACCM */ +#define PPPIOCSXASYNCMAP _IOW('t', 79, ext_accm) /* set extended ACCM */ +#define PPPIOCXFERUNIT _IO('t', 78) /* transfer PPP unit */ +#define PPPIOCSCOMPRESS _IOW('t', 77, struct ppp_option_data) +#define PPPIOCGNPMODE _IOWR('t', 76, struct npioctl) /* get NP mode */ +#define PPPIOCSNPMODE _IOW('t', 75, struct npioctl) /* set NP mode */ +#define PPPIOCGDEBUG _IOR('t', 65, int) /* Read debug level */ +#define PPPIOCSDEBUG _IOW('t', 64, int) /* Set debug level */ +#define PPPIOCGIDLE _IOR('t', 63, struct ppp_idle) /* get idle time */ + +#define SIOCGPPPSTATS (SIOCDEVPRIVATE + 0) +#define SIOCGPPPVER (SIOCDEVPRIVATE + 1) /* NEVER change this!! */ +#define SIOCGPPPCSTATS (SIOCDEVPRIVATE + 2) + +#if !defined(ifr_mtu) +#define ifr_mtu ifr_ifru.ifru_metric +#endif + +__END_DECLS + +#endif /* net/if_ppp.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/net/if_shaper.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/net/if_shaper.h new file mode 100644 index 00000000..7060af31 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/net/if_shaper.h @@ -0,0 +1,59 @@ +/* Copyright (C) 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _NET_IF_SHAPER_H +#define _NET_IF_SHAPER_H 1 + +#include +#include +#include +#include + +__BEGIN_DECLS + +#define SHAPER_QLEN 10 +/* + * This is a bit speed dependant (read it shouldnt be a constant!) + * + * 5 is about right for 28.8 upwards. Below that double for every + * halving of speed or so. - ie about 20 for 9600 baud. + */ +#define SHAPER_LATENCY (5 * HZ) +#define SHAPER_MAXSLIP 2 +#define SHAPER_BURST (HZ / 50) /* Good for >128K then */ + +#define SHAPER_SET_DEV 0x0001 +#define SHAPER_SET_SPEED 0x0002 +#define SHAPER_GET_DEV 0x0003 +#define SHAPER_GET_SPEED 0x0004 + +struct shaperconf +{ + u_int16_t ss_cmd; + union + { + char ssu_name[14]; + u_int32_t ssu_speed; + } ss_u; +#define ss_speed ss_u.ssu_speed +#define ss_name ss_u.ssu_name +}; + +__END_DECLS + +#endif /* net/if_shaper.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/net/if_slip.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/net/if_slip.h new file mode 100644 index 00000000..66bd7f30 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/net/if_slip.h @@ -0,0 +1,25 @@ +/* Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _NET_IF_SLIP_H +#define _NET_IF_SLIP_H 1 + +/* We can use the kernel header. */ +#include + +#endif /* net/if_slip.h. */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/net/ppp-comp.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/net/ppp-comp.h new file mode 100644 index 00000000..4a992d54 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/net/ppp-comp.h @@ -0,0 +1 @@ +#include diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/net/ppp_defs.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/net/ppp_defs.h new file mode 100644 index 00000000..f8924c4f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/net/ppp_defs.h @@ -0,0 +1,10 @@ +#ifndef _NET_PPP_DEFS_H +#define _NET_PPP_DEFS_H 1 + +#define __need_time_t +#include + +#include +#include + +#endif /* net/ppp_defs.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/net/route.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/net/route.h new file mode 100644 index 00000000..da5c810c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/net/route.h @@ -0,0 +1,145 @@ +/* Copyright (C) 1997, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Based on the 4.4BSD and Linux version of this file. */ + +#ifndef _NET_ROUTE_H +#define _NET_ROUTE_H 1 + +#include +#include +#include +#include +#include + + +/* This structure gets passed by the SIOCADDRT and SIOCDELRT calls. */ +struct rtentry + { + unsigned long int rt_pad1; + struct sockaddr rt_dst; /* Target address. */ + struct sockaddr rt_gateway; /* Gateway addr (RTF_GATEWAY). */ + struct sockaddr rt_genmask; /* Target network mask (IP). */ + unsigned short int rt_flags; + short int rt_pad2; + unsigned long int rt_pad3; + unsigned char rt_tos; + unsigned char rt_class; +#if __WORDSIZE == 64 + short int rt_pad4[3]; +#else + short int rt_pad4; +#endif + short int rt_metric; /* +1 for binary compatibility! */ + char *rt_dev; /* Forcing the device at add. */ + unsigned long int rt_mtu; /* Per route MTU/Window. */ + unsigned long int rt_window; /* Window clamping. */ + unsigned short int rt_irtt; /* Initial RTT. */ + }; +/* Compatibility hack. */ +#define rt_mss rt_mtu + + +struct in6_rtmsg + { + struct in6_addr rtmsg_dst; + struct in6_addr rtmsg_src; + struct in6_addr rtmsg_gateway; + u_int32_t rtmsg_type; + u_int16_t rtmsg_dst_len; + u_int16_t rtmsg_src_len; + u_int32_t rtmsg_metric; + unsigned long int rtmsg_info; + u_int32_t rtmsg_flags; + int rtmsg_ifindex; + }; + + +#define RTF_UP 0x0001 /* Route usable. */ +#define RTF_GATEWAY 0x0002 /* Destination is a gateway. */ + +#define RTF_HOST 0x0004 /* Host entry (net otherwise). */ +#define RTF_REINSTATE 0x0008 /* Reinstate route after timeout. */ +#define RTF_DYNAMIC 0x0010 /* Created dyn. (by redirect). */ +#define RTF_MODIFIED 0x0020 /* Modified dyn. (by redirect). */ +#define RTF_MTU 0x0040 /* Specific MTU for this route. */ +#define RTF_MSS RTF_MTU /* Compatibility. */ +#define RTF_WINDOW 0x0080 /* Per route window clamping. */ +#define RTF_IRTT 0x0100 /* Initial round trip time. */ +#define RTF_REJECT 0x0200 /* Reject route. */ +#define RTF_STATIC 0x0400 /* Manually injected route. */ +#define RTF_XRESOLVE 0x0800 /* External resolver. */ +#define RTF_NOFORWARD 0x1000 /* Forwarding inhibited. */ +#define RTF_THROW 0x2000 /* Go to next class. */ +#define RTF_NOPMTUDISC 0x4000 /* Do not send packets with DF. */ + +/* for IPv6 */ +#define RTF_DEFAULT 0x00010000 /* default - learned via ND */ +#define RTF_ALLONLINK 0x00020000 /* fallback, no routers on link */ +#define RTF_ADDRCONF 0x00040000 /* addrconf route - RA */ + +#define RTF_LINKRT 0x00100000 /* link specific - device match */ +#define RTF_NONEXTHOP 0x00200000 /* route with no nexthop */ + +#define RTF_CACHE 0x01000000 /* cache entry */ +#define RTF_FLOW 0x02000000 /* flow significant route */ +#define RTF_POLICY 0x04000000 /* policy route */ + +#define RTCF_VALVE 0x00200000 +#define RTCF_MASQ 0x00400000 +#define RTCF_NAT 0x00800000 +#define RTCF_DOREDIRECT 0x01000000 +#define RTCF_LOG 0x02000000 +#define RTCF_DIRECTSRC 0x04000000 + +#define RTF_LOCAL 0x80000000 +#define RTF_INTERFACE 0x40000000 +#define RTF_MULTICAST 0x20000000 +#define RTF_BROADCAST 0x10000000 +#define RTF_NAT 0x08000000 + +#define RTF_ADDRCLASSMASK 0xF8000000 +#define RT_ADDRCLASS(flags) ((__u_int32_t) flags >> 23) + +#define RT_TOS(tos) ((tos) & IPTOS_TOS_MASK) + +#define RT_LOCALADDR(flags) ((flags & RTF_ADDRCLASSMASK) \ + == (RTF_LOCAL|RTF_INTERFACE)) + +#define RT_CLASS_UNSPEC 0 +#define RT_CLASS_DEFAULT 253 + +#define RT_CLASS_MAIN 254 +#define RT_CLASS_LOCAL 255 +#define RT_CLASS_MAX 255 + + +#define RTMSG_ACK NLMSG_ACK +#define RTMSG_OVERRUN NLMSG_OVERRUN + +#define RTMSG_NEWDEVICE 0x11 +#define RTMSG_DELDEVICE 0x12 +#define RTMSG_NEWROUTE 0x21 +#define RTMSG_DELROUTE 0x22 +#define RTMSG_NEWRULE 0x31 +#define RTMSG_DELRULE 0x32 +#define RTMSG_CONTROL 0x40 + +#define RTMSG_AR_FAILED 0x51 /* Address Resolution failed. */ + +#endif /* net/route.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/netax25/ax25.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/netax25/ax25.h new file mode 100644 index 00000000..ce3c7abc --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/netax25/ax25.h @@ -0,0 +1,171 @@ +/* Copyright (C) 1997, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _NETAX25_AX25_H +#define _NETAX25_AX25_H 1 + +#include +#include + +/* Setsockoptions(2) level. Thanks to BSD these must match IPPROTO_xxx. */ +#define SOL_AX25 257 + +/* AX.25 flags: */ +#define AX25_WINDOW 1 +#define AX25_T1 2 +#define AX25_T2 5 +#define AX25_T3 4 +#define AX25_N2 3 +#define AX25_BACKOFF 6 +#define AX25_EXTSEQ 7 +#define AX25_PIDINCL 8 +#define AX25_IDLE 9 +#define AX25_PACLEN 10 +#define AX25_IPMAXQUEUE 11 +#define AX25_IAMDIGI 12 +#define AX25_KILL 99 + +/* AX.25 socket ioctls: */ +#define SIOCAX25GETUID (SIOCPROTOPRIVATE) +#define SIOCAX25ADDUID (SIOCPROTOPRIVATE+1) +#define SIOCAX25DELUID (SIOCPROTOPRIVATE+2) +#define SIOCAX25NOUID (SIOCPROTOPRIVATE+3) +#define SIOCAX25BPQADDR (SIOCPROTOPRIVATE+4) +#define SIOCAX25GETPARMS (SIOCPROTOPRIVATE+5) +#define SIOCAX25SETPARMS (SIOCPROTOPRIVATE+6) +#define SIOCAX25OPTRT (SIOCPROTOPRIVATE+7) +#define SIOCAX25CTLCON (SIOCPROTOPRIVATE+8) +#define SIOCAX25GETINFO (SIOCPROTOPRIVATE+9) +#define SIOCAX25ADDFWD (SIOCPROTOPRIVATE+10) +#define SIOCAX25DELFWD (SIOCPROTOPRIVATE+11) + +/* unknown: */ +#define AX25_NOUID_DEFAULT 0 +#define AX25_NOUID_BLOCK 1 +#define AX25_SET_RT_IPMODE 2 + +/* Digipeating flags: */ +#define AX25_DIGI_INBAND 0x01 /* Allow digipeating within port */ +#define AX25_DIGI_XBAND 0x02 /* Allow digipeating across ports */ + +/* Maximim number of digipeaters: */ +#define AX25_MAX_DIGIS 8 + + +typedef struct + { + char ax25_call[7]; /* 6 call + SSID (shifted ascii) */ + } +ax25_address; + +struct sockaddr_ax25 + { + sa_family_t sax25_family; + ax25_address sax25_call; + int sax25_ndigis; + }; + +/* + * The sockaddr struct with the digipeater adresses: + */ +struct full_sockaddr_ax25 + { + struct sockaddr_ax25 fsa_ax25; + ax25_address fsa_digipeater[AX25_MAX_DIGIS]; + }; +#define sax25_uid sax25_ndigis + +struct ax25_routes_struct + { + ax25_address port_addr; + ax25_address dest_addr; + unsigned char digi_count; + ax25_address digi_addr[AX25_MAX_DIGIS]; + }; + +/* The AX.25 ioctl structure: */ +struct ax25_ctl_struct + { + ax25_address port_addr; + ax25_address source_addr; + ax25_address dest_addr; + unsigned int cmd; + unsigned long arg; + unsigned char digi_count; + ax25_address digi_addr[AX25_MAX_DIGIS]; + }; + +struct ax25_info_struct + { + unsigned int n2, n2count; + unsigned int t1, t1timer; + unsigned int t2, t2timer; + unsigned int t3, t3timer; + unsigned int idle, idletimer; + unsigned int state; + unsigned int rcv_q, snd_q; + }; + +struct ax25_fwd_struct + { + ax25_address port_from; + ax25_address port_to; + }; + +/* AX.25 route structure: */ +struct ax25_route_opt_struct + { + ax25_address port_addr; + ax25_address dest_addr; + int cmd; + int arg; + }; + +/* AX.25 BPQ stuff: */ +struct ax25_bpqaddr_struct + { + char dev[16]; + ax25_address addr; + }; + +/* Definitions for the AX.25 `values' fields: */ +#define AX25_VALUES_IPDEFMODE 0 /* 'D'=DG 'V'=VC */ +#define AX25_VALUES_AXDEFMODE 1 /* 8=Normal 128=Extended Seq Nos */ +#define AX25_VALUES_NETROM 2 /* Allow NET/ROM - 0=No 1=Yes */ +#define AX25_VALUES_TEXT 3 /* Allow PID=Text - 0=No 1=Yes */ +#define AX25_VALUES_BACKOFF 4 /* 'E'=Exponential 'L'=Linear */ +#define AX25_VALUES_CONMODE 5 /* Allow connected modes - 0=No 1=Yes */ +#define AX25_VALUES_WINDOW 6 /* Default window size for standard AX.25 */ +#define AX25_VALUES_EWINDOW 7 /* Default window size for extended AX.25 */ +#define AX25_VALUES_T1 8 /* Default T1 timeout value */ +#define AX25_VALUES_T2 9 /* Default T2 timeout value */ +#define AX25_VALUES_T3 10 /* Default T3 timeout value */ +#define AX25_VALUES_N2 11 /* Default N2 value */ +#define AX25_VALUES_DIGI 12 /* Digipeat mode */ +#define AX25_VALUES_IDLE 13 /* mode vc idle timer */ +#define AX25_VALUES_PACLEN 14 /* AX.25 MTU */ +#define AX25_VALUES_IPMAXQUEUE 15 /* Maximum number of buffers enqueued */ +#define AX25_MAX_VALUES 20 + +struct ax25_parms_struct + { + ax25_address port_addr; + unsigned short values[AX25_MAX_VALUES]; + }; + +#endif /* netax25/ax25.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/netdb.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/netdb.h new file mode 100644 index 00000000..07e1b0d0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/netdb.h @@ -0,0 +1,705 @@ +/* Copyright (C) 1996-2002, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* All data returned by the network data base library are supplied in + host order and returned in network order (suitable for use in + system calls). */ + +#ifndef _NETDB_H +#define _NETDB_H 1 + +#include + +#include +#include +#if defined __USE_MISC && defined __UCLIBC_HAS_RPC__ +/* This is necessary to make this include file properly replace the + Sun version. */ +# include +#endif + +#ifdef __USE_GNU +# define __need_sigevent_t +# include +# define __need_timespec +# include +#endif + +#include + +/* Absolute file name for network data base files. */ +#define _PATH_HEQUIV "/etc/hosts.equiv" +#define _PATH_HOSTS "/etc/hosts" +#define _PATH_NETWORKS "/etc/networks" +#define _PATH_NSSWITCH_CONF "/etc/nsswitch.conf" +#define _PATH_PROTOCOLS "/etc/protocols" +#define _PATH_SERVICES "/etc/services" + + +__BEGIN_DECLS + +/* Error status for non-reentrant lookup functions. + We use a macro to access always the thread-specific `h_errno' variable. */ +#define h_errno (*__h_errno_location ()) + +/* Function to get address of global `h_errno' variable. */ +extern int *__h_errno_location (void) __THROW __attribute__ ((__const__)); +libc_hidden_proto(__h_errno_location) + +/* Macros for accessing h_errno from inside libc. */ +#ifdef _LIBC +# ifdef __UCLIBC_HAS_THREADS__ +# if defined __UCLIBC_HAS_TLS__ \ + && (!defined NOT_IN_libc || defined IS_IN_libpthread) +# undef h_errno +# ifndef NOT_IN_libc +# define h_errno __libc_h_errno +# else +# define h_errno h_errno /* For #ifndef h_errno tests. */ +# endif +extern __thread int h_errno attribute_tls_model_ie; +# define __set_h_errno(x) (h_errno = (x)) +# else +static inline int __set_h_errno (int __err) +{ + return *__h_errno_location () = __err; +} +# endif /* __UCLIBC_HAS_TLS__ */ +# else +# undef h_errno +# define __set_h_errno(x) (h_errno = (x)) +extern int h_errno; +# endif /* __UCLIBC_HAS_THREADS__ */ +#endif /* _LIBC */ + +/* Possible values left in `h_errno'. */ +#define NETDB_INTERNAL -1 /* See errno. */ +#define NETDB_SUCCESS 0 /* No problem. */ +#define HOST_NOT_FOUND 1 /* Authoritative Answer Host not found. */ +#define TRY_AGAIN 2 /* Non-Authoritative Host not found, + or SERVERFAIL. */ +#define NO_RECOVERY 3 /* Non recoverable errors, FORMERR, REFUSED, + NOTIMP. */ +#define NO_DATA 4 /* Valid name, no data record of requested + type. */ +#define NO_ADDRESS NO_DATA /* No address, look for MX record. */ + +#ifdef __USE_XOPEN2K +/* Highest reserved Internet port number. */ +# define IPPORT_RESERVED 1024 +#endif + +#ifdef __USE_GNU +/* Scope delimiter for getaddrinfo(), getnameinfo(). */ +# define SCOPE_DELIMITER '%' +#endif + +/* Print error indicated by `h_errno' variable on standard error. STR + if non-null is printed before the error string. */ +extern void herror (__const char *__str) __THROW; +libc_hidden_proto(herror) + +/* Return string associated with error ERR_NUM. */ +extern __const char *hstrerror (int __err_num) __THROW; + + +/* Description of data base entry for a single host. */ +struct hostent +{ + char *h_name; /* Official name of host. */ + char **h_aliases; /* Alias list. */ + int h_addrtype; /* Host address type. */ + int h_length; /* Length of address. */ + char **h_addr_list; /* List of addresses from name server. */ +#define h_addr h_addr_list[0] /* Address, for backward compatibility. */ +}; + +/* Open host data base files and mark them as staying open even after + a later search if STAY_OPEN is non-zero. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern void sethostent (int __stay_open); + +/* Close host data base files and clear `stay open' flag. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern void endhostent (void); + +/* Get next entry from host data base file. Open data base if + necessary. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern struct hostent *gethostent (void); + +/* Return entry from host data base which address match ADDR with + length LEN and type TYPE. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern struct hostent *gethostbyaddr (__const void *__addr, __socklen_t __len, + int __type); +libc_hidden_proto(gethostbyaddr) + +/* Return entry from host data base for host with NAME. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern struct hostent *gethostbyname (__const char *__name); +libc_hidden_proto(gethostbyname) + +#ifdef __USE_MISC +/* Return entry from host data base for host with NAME. AF must be + set to the address type which is `AF_INET' for IPv4 or `AF_INET6' + for IPv6. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern struct hostent *gethostbyname2 (__const char *__name, int __af); +libc_hidden_proto(gethostbyname2) + +/* Reentrant versions of the functions above. The additional + arguments specify a buffer of BUFLEN starting at BUF. The last + argument is a pointer to a variable which gets the value which + would be stored in the global variable `herrno' by the + non-reentrant functions. + + These functions are not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation they are cancellation points and + therefore not marked with __THROW. */ +extern int gethostent_r (struct hostent *__restrict __result_buf, + char *__restrict __buf, size_t __buflen, + struct hostent **__restrict __result, + int *__restrict __h_errnop); +libc_hidden_proto(gethostent_r) + +extern int gethostbyaddr_r (__const void *__restrict __addr, __socklen_t __len, + int __type, + struct hostent *__restrict __result_buf, + char *__restrict __buf, size_t __buflen, + struct hostent **__restrict __result, + int *__restrict __h_errnop); +libc_hidden_proto(gethostbyaddr_r) + +extern int gethostbyname_r (__const char *__restrict __name, + struct hostent *__restrict __result_buf, + char *__restrict __buf, size_t __buflen, + struct hostent **__restrict __result, + int *__restrict __h_errnop); +libc_hidden_proto(gethostbyname_r) + +extern int gethostbyname2_r (__const char *__restrict __name, int __af, + struct hostent *__restrict __result_buf, + char *__restrict __buf, size_t __buflen, + struct hostent **__restrict __result, + int *__restrict __h_errnop); +libc_hidden_proto(gethostbyname2_r) +#endif /* misc */ + + +/* Open network data base files and mark them as staying open even + after a later search if STAY_OPEN is non-zero. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern void setnetent (int __stay_open); +libc_hidden_proto(setnetent) + +/* Close network data base files and clear `stay open' flag. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern void endnetent (void); +libc_hidden_proto(endnetent) + +/* Get next entry from network data base file. Open data base if + necessary. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern struct netent *getnetent (void); + +/* Return entry from network data base which address match NET and + type TYPE. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern struct netent *getnetbyaddr (uint32_t __net, int __type); + +/* Return entry from network data base for network with NAME. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern struct netent *getnetbyname (__const char *__name); + +#ifdef __USE_MISC +/* Reentrant versions of the functions above. The additional + arguments specify a buffer of BUFLEN starting at BUF. The last + argument is a pointer to a variable which gets the value which + would be stored in the global variable `herrno' by the + non-reentrant functions. + + These functions are not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation they are cancellation points and + therefore not marked with __THROW. */ +extern int getnetent_r (struct netent *__restrict __result_buf, + char *__restrict __buf, size_t __buflen, + struct netent **__restrict __result, + int *__restrict __h_errnop); +libc_hidden_proto(getnetent_r) +extern int getnetbyaddr_r (uint32_t __net, int __type, + struct netent *__restrict __result_buf, + char *__restrict __buf, size_t __buflen, + struct netent **__restrict __result, + int *__restrict __h_errnop); +libc_hidden_proto(getnetbyaddr_r) +extern int getnetbyname_r (__const char *__restrict __name, + struct netent *__restrict __result_buf, + char *__restrict __buf, size_t __buflen, + struct netent **__restrict __result, + int *__restrict __h_errnop); +libc_hidden_proto(getnetbyname_r) +#endif /* __USE_MISC */ + + +/* Description of data base entry for a single service. */ +struct servent +{ + char *s_name; /* Official service name. */ + char **s_aliases; /* Alias list. */ + int s_port; /* Port number. */ + char *s_proto; /* Protocol to use. */ +}; + +/* Open service data base files and mark them as staying open even + after a later search if STAY_OPEN is non-zero. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern void setservent (int __stay_open); +libc_hidden_proto(setservent) + +/* Close service data base files and clear `stay open' flag. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern void endservent (void); +libc_hidden_proto(endservent) + +/* Get next entry from service data base file. Open data base if + necessary. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern struct servent *getservent (void); + +/* Return entry from network data base for network with NAME and + protocol PROTO. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern struct servent *getservbyname (__const char *__name, + __const char *__proto); + +/* Return entry from service data base which matches port PORT and + protocol PROTO. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern struct servent *getservbyport (int __port, __const char *__proto); +libc_hidden_proto(getservbyport) + + +#ifdef __USE_MISC +/* Reentrant versions of the functions above. The additional + arguments specify a buffer of BUFLEN starting at BUF. + + These functions are not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation they are cancellation points and + therefore not marked with __THROW. */ +extern int getservent_r (struct servent *__restrict __result_buf, + char *__restrict __buf, size_t __buflen, + struct servent **__restrict __result); +libc_hidden_proto(getservent_r) + +extern int getservbyname_r (__const char *__restrict __name, + __const char *__restrict __proto, + struct servent *__restrict __result_buf, + char *__restrict __buf, size_t __buflen, + struct servent **__restrict __result); +libc_hidden_proto(getservbyname_r) + +extern int getservbyport_r (int __port, __const char *__restrict __proto, + struct servent *__restrict __result_buf, + char *__restrict __buf, size_t __buflen, + struct servent **__restrict __result); +libc_hidden_proto(getservbyport_r) +#endif /* misc */ + + +/* Description of data base entry for a single service. */ +struct protoent +{ + char *p_name; /* Official protocol name. */ + char **p_aliases; /* Alias list. */ + int p_proto; /* Protocol number. */ +}; + +/* Open protocol data base files and mark them as staying open even + after a later search if STAY_OPEN is non-zero. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern void setprotoent (int __stay_open); +libc_hidden_proto(setprotoent) + +/* Close protocol data base files and clear `stay open' flag. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern void endprotoent (void); +libc_hidden_proto(endprotoent) + +/* Get next entry from protocol data base file. Open data base if + necessary. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern struct protoent *getprotoent (void); + +/* Return entry from protocol data base for network with NAME. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern struct protoent *getprotobyname (__const char *__name); + +/* Return entry from protocol data base which number is PROTO. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern struct protoent *getprotobynumber (int __proto); + + +#ifdef __USE_MISC +/* Reentrant versions of the functions above. The additional + arguments specify a buffer of BUFLEN starting at BUF. + + These functions are not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation they are cancellation points and + therefore not marked with __THROW. */ +extern int getprotoent_r (struct protoent *__restrict __result_buf, + char *__restrict __buf, size_t __buflen, + struct protoent **__restrict __result); +libc_hidden_proto(getprotoent_r) + +extern int getprotobyname_r (__const char *__restrict __name, + struct protoent *__restrict __result_buf, + char *__restrict __buf, size_t __buflen, + struct protoent **__restrict __result); +libc_hidden_proto(getprotobyname_r) + +extern int getprotobynumber_r (int __proto, + struct protoent *__restrict __result_buf, + char *__restrict __buf, size_t __buflen, + struct protoent **__restrict __result); +libc_hidden_proto(getprotobynumber_r) + + +#ifdef __UCLIBC_HAS_NETGROUP__ +/* Establish network group NETGROUP for enumeration. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern int setnetgrent (__const char *__netgroup); + +/* Free all space allocated by previous `setnetgrent' call. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern void endnetgrent (void); + +/* Get next member of netgroup established by last `setnetgrent' call + and return pointers to elements in HOSTP, USERP, and DOMAINP. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern int getnetgrent (char **__restrict __hostp, + char **__restrict __userp, + char **__restrict __domainp); + + +/* Test whether NETGROUP contains the triple (HOST,USER,DOMAIN). + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern int innetgr (__const char *__netgroup, __const char *__host, + __const char *__user, __const char *domain); + +/* Reentrant version of `getnetgrent' where result is placed in BUFFER. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern int getnetgrent_r (char **__restrict __hostp, + char **__restrict __userp, + char **__restrict __domainp, + char *__restrict __buffer, size_t __buflen); +#endif /* UCLIBC_HAS_NETGROUP */ +#endif /* misc */ + + +/* ruserpass - remote password check. + This function also exists in glibc but is undocumented */ +extern int ruserpass(const char *host, const char **aname, const char **apass); +libc_hidden_proto(ruserpass) + + +#ifdef __USE_BSD +/* Call `rshd' at port RPORT on remote machine *AHOST to execute CMD. + The local user is LOCUSER, on the remote machine the command is + executed as REMUSER. In *FD2P the descriptor to the socket for the + connection is returned. The caller must have the right to use a + reserved port. When the function returns *AHOST contains the + official host name. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern int rcmd (char **__restrict __ahost, unsigned short int __rport, + __const char *__restrict __locuser, + __const char *__restrict __remuser, + __const char *__restrict __cmd, int *__restrict __fd2p); + +#if 0 +/* FIXME */ +/* This is the equivalent function where the protocol can be selected + and which therefore can be used for IPv6. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern int rcmd_af (char **__restrict __ahost, unsigned short int __rport, + __const char *__restrict __locuser, + __const char *__restrict __remuser, + __const char *__restrict __cmd, int *__restrict __fd2p, + sa_family_t __af); +#endif + +/* Call `rexecd' at port RPORT on remote machine *AHOST to execute + CMD. The process runs at the remote machine using the ID of user + NAME whose cleartext password is PASSWD. In *FD2P the descriptor + to the socket for the connection is returned. When the function + returns *AHOST contains the official host name. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern int rexec (char **__restrict __ahost, int __rport, + __const char *__restrict __name, + __const char *__restrict __pass, + __const char *__restrict __cmd, int *__restrict __fd2p); + +/* This is the equivalent function where the protocol can be selected + and which therefore can be used for IPv6. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern int rexec_af (char **__restrict __ahost, int __rport, + __const char *__restrict __name, + __const char *__restrict __pass, + __const char *__restrict __cmd, int *__restrict __fd2p, + sa_family_t __af); +libc_hidden_proto(rexec_af) + +/* Check whether user REMUSER on system RHOST is allowed to login as LOCUSER. + If SUSER is not zero the user tries to become superuser. Return 0 if + it is possible. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern int ruserok (__const char *__rhost, int __suser, + __const char *__remuser, __const char *__locuser); + +#if 0 +/* FIXME */ +/* This is the equivalent function where the protocol can be selected + and which therefore can be used for IPv6. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern int ruserok_af (__const char *__rhost, int __suser, + __const char *__remuser, __const char *__locuser, + sa_family_t __af); +#endif + +/* Try to allocate reserved port, returning a descriptor for a socket opened + at this port or -1 if unsuccessful. The search for an available port + will start at ALPORT and continues with lower numbers. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern int rresvport (int *__alport); +libc_hidden_proto(rresvport) + +#if 0 +/* FIXME */ +/* This is the equivalent function where the protocol can be selected + and which therefore can be used for IPv6. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern int rresvport_af (int *__alport, sa_family_t __af); +#endif +#endif + + +/* Extension from POSIX.1g. */ +#ifdef __USE_POSIX +/* Structure to contain information about address of a service provider. */ +struct addrinfo +{ + int ai_flags; /* Input flags. */ + int ai_family; /* Protocol family for socket. */ + int ai_socktype; /* Socket type. */ + int ai_protocol; /* Protocol for socket. */ + socklen_t ai_addrlen; /* Length of socket address. */ + struct sockaddr *ai_addr; /* Socket address for socket. */ + char *ai_canonname; /* Canonical name for service location. */ + struct addrinfo *ai_next; /* Pointer to next in list. */ +}; + +/* Possible values for `ai_flags' field in `addrinfo' structure. */ +# define AI_PASSIVE 0x0001 /* Socket address is intended for `bind'. */ +# define AI_CANONNAME 0x0002 /* Request for canonical name. */ +# define AI_NUMERICHOST 0x0004 /* Don't use name resolution. */ +# define AI_V4MAPPED 0x0008 /* IPv4 mapped addresses are acceptable. */ +# define AI_ALL 0x0010 /* Return IPv4 mapped and IPv6 addresses. */ +# define AI_ADDRCONFIG 0x0020 /* Use configuration of this host to choose + returned address type.. */ +# ifdef __USE_GNU +# define AI_IDN 0x0040 /* IDN encode input (assuming it is encoded + in the current locale's character set) + before looking it up. */ +# define AI_CANONIDN 0x0080 /* Translate canonical name from IDN format. */ +# define AI_IDN_ALLOW_UNASSIGNED 0x0100 /* Don't reject unassigned Unicode + code points. */ +# define AI_IDN_USE_STD3_ASCII_RULES 0x0200 /* Validate strings according to + STD3 rules. */ +# endif +# define AI_NUMERICSERV 0x0400 /* Don't use name resolution. */ + +/* Error values for `getaddrinfo' function. */ +# define EAI_BADFLAGS -1 /* Invalid value for `ai_flags' field. */ +# define EAI_NONAME -2 /* NAME or SERVICE is unknown. */ +# define EAI_AGAIN -3 /* Temporary failure in name resolution. */ +# define EAI_FAIL -4 /* Non-recoverable failure in name res. */ +# define EAI_NODATA -5 /* No address associated with NAME. */ +# define EAI_FAMILY -6 /* `ai_family' not supported. */ +# define EAI_SOCKTYPE -7 /* `ai_socktype' not supported. */ +# define EAI_SERVICE -8 /* SERVICE not supported for `ai_socktype'. */ +# define EAI_ADDRFAMILY -9 /* Address family for NAME not supported. */ +# define EAI_MEMORY -10 /* Memory allocation failure. */ +# define EAI_SYSTEM -11 /* System error returned in `errno'. */ +# define EAI_OVERFLOW -12 /* Argument buffer overflow. */ +# ifdef __USE_GNU +# define EAI_INPROGRESS -100 /* Processing request in progress. */ +# define EAI_CANCELED -101 /* Request canceled. */ +# define EAI_NOTCANCELED -102 /* Request not canceled. */ +# define EAI_ALLDONE -103 /* All requests done. */ +# define EAI_INTR -104 /* Interrupted by a signal. */ +# define EAI_IDN_ENCODE -105 /* IDN encoding failed. */ +# endif + +# define NI_MAXHOST 1025 +# define NI_MAXSERV 32 + +# define NI_NUMERICHOST 1 /* Don't try to look up hostname. */ +# define NI_NUMERICSERV 2 /* Don't convert port number to name. */ +# define NI_NOFQDN 4 /* Only return nodename portion. */ +# define NI_NAMEREQD 8 /* Don't return numeric addresses. */ +# define NI_DGRAM 16 /* Look up UDP service rather than TCP. */ +# ifdef __USE_GNU +# define NI_IDN 32 /* Convert name from IDN format. */ +# define NI_IDN_ALLOW_UNASSIGNED 64 /* Don't reject unassigned Unicode + code points. */ +# define NI_IDN_USE_STD3_ASCII_RULES 128 /* Validate strings according to + STD3 rules. */ +# endif + +/* Translate name of a service location and/or a service name to set of + socket addresses. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern int getaddrinfo (__const char *__restrict __name, + __const char *__restrict __service, + __const struct addrinfo *__restrict __req, + struct addrinfo **__restrict __pai); +libc_hidden_proto(getaddrinfo) + +/* Free `addrinfo' structure AI including associated storage. */ +extern void freeaddrinfo (struct addrinfo *__ai) __THROW; +libc_hidden_proto(freeaddrinfo) + +/* Convert error return from getaddrinfo() to a string. */ +extern __const char *gai_strerror (int __ecode) __THROW; + +/* Translate a socket address to a location and service name. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern int getnameinfo (__const struct sockaddr *__restrict __sa, + socklen_t __salen, char *__restrict __host, + socklen_t __hostlen, char *__restrict __serv, + socklen_t __servlen, unsigned int __flags); +libc_hidden_proto(getnameinfo) +#endif /* POSIX */ + +__END_DECLS + +#endif /* netdb.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/neteconet/ec.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/neteconet/ec.h new file mode 100644 index 00000000..f21601ca --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/neteconet/ec.h @@ -0,0 +1,52 @@ +/* Definitions for use with Linux AF_ECONET sockets. + Copyright (C) 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _NETECONET_EC_H +#define _NETECONET_EC_H 1 + +#include +#include + +struct ec_addr + { + unsigned char station; /* Station number. */ + unsigned char net; /* Network number. */ + }; + +struct sockaddr_ec + { + __SOCKADDR_COMMON (sec_); + unsigned char port; /* Port number. */ + unsigned char cb; /* Control/flag byte. */ + unsigned char type; /* Type of message. */ + struct ec_addr addr; + unsigned long cookie; + }; + +#define ECTYPE_PACKET_RECEIVED 0 /* Packet received */ +#define ECTYPE_TRANSMIT_STATUS 0x10 /* Transmit completed */ + +#define ECTYPE_TRANSMIT_OK 1 +#define ECTYPE_TRANSMIT_NOT_LISTENING 2 +#define ECTYPE_TRANSMIT_NET_ERROR 3 +#define ECTYPE_TRANSMIT_NO_CLOCK 4 +#define ECTYPE_TRANSMIT_LINE_JAMMED 5 +#define ECTYPE_TRANSMIT_NOT_PRESENT 6 + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/netinet/ether.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/netinet/ether.h new file mode 100644 index 00000000..2e52679f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/netinet/ether.h @@ -0,0 +1,64 @@ +/* Functions for storing Ethernet addresses in ASCII and mapping to hostnames. + Copyright (C) 1996, 1997, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _NETINET_ETHER_H +#define _NETINET_ETHER_H 1 + +#include + +/* Get definition of `struct ether_addr'. */ +#include + +#ifdef _LIBC +#define ETHER_FILE_NAME "/etc/ethers" +#endif + +__BEGIN_DECLS + +#if defined __UCLIBC_HAS_SOCKET__ || defined __UCLIBC_HAS_IPV4__ || \ + defined __UCLIBC_HAS_IPV6__ +/* Convert 48 bit Ethernet ADDRess to ASCII. */ +extern char *ether_ntoa (__const struct ether_addr *__addr) __THROW; +extern char *ether_ntoa_r (__const struct ether_addr *__addr, char *__buf) + __THROW; +libc_hidden_proto(ether_ntoa_r) + +/* Convert ASCII string S to 48 bit Ethernet address. */ +extern struct ether_addr *ether_aton (__const char *__asc) __THROW; +extern struct ether_addr *ether_aton_r (__const char *__asc, + struct ether_addr *__addr) __THROW; +libc_hidden_proto(ether_aton_r) + + +/* Map 48 bit Ethernet number ADDR to HOSTNAME. */ +extern int ether_ntohost (char *__hostname, __const struct ether_addr *__addr) + __THROW; + +/* Map HOSTNAME to 48 bit Ethernet address. */ +extern int ether_hostton (__const char *__hostname, struct ether_addr *__addr) + __THROW; + +/* Scan LINE and set ADDR and HOSTNAME. */ +extern int ether_line (__const char *__line, struct ether_addr *__addr, + char *__hostname) __THROW; +#endif + +__END_DECLS + +#endif /* netinet/ether.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/netinet/icmp6.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/netinet/icmp6.h new file mode 100644 index 00000000..225e49e0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/netinet/icmp6.h @@ -0,0 +1,346 @@ +/* Copyright (C) 1991-1997,2000,2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _NETINET_ICMP6_H +#define _NETINET_ICMP6_H 1 + +#include +#include +#include +#include + +#define ICMP6_FILTER 1 + +#define ICMP6_FILTER_BLOCK 1 +#define ICMP6_FILTER_PASS 2 +#define ICMP6_FILTER_BLOCKOTHERS 3 +#define ICMP6_FILTER_PASSONLY 4 + +struct icmp6_filter + { + uint32_t icmp6_filt[8]; + }; + +struct icmp6_hdr + { + uint8_t icmp6_type; /* type field */ + uint8_t icmp6_code; /* code field */ + uint16_t icmp6_cksum; /* checksum field */ + union + { + uint32_t icmp6_un_data32[1]; /* type-specific field */ + uint16_t icmp6_un_data16[2]; /* type-specific field */ + uint8_t icmp6_un_data8[4]; /* type-specific field */ + } icmp6_dataun; + }; + +#define icmp6_data32 icmp6_dataun.icmp6_un_data32 +#define icmp6_data16 icmp6_dataun.icmp6_un_data16 +#define icmp6_data8 icmp6_dataun.icmp6_un_data8 +#define icmp6_pptr icmp6_data32[0] /* parameter prob */ +#define icmp6_mtu icmp6_data32[0] /* packet too big */ +#define icmp6_id icmp6_data16[0] /* echo request/reply */ +#define icmp6_seq icmp6_data16[1] /* echo request/reply */ +#define icmp6_maxdelay icmp6_data16[0] /* mcast group membership */ + +#define ICMP6_DST_UNREACH 1 +#define ICMP6_PACKET_TOO_BIG 2 +#define ICMP6_TIME_EXCEEDED 3 +#define ICMP6_PARAM_PROB 4 + +#define ICMP6_INFOMSG_MASK 0x80 /* all informational messages */ + +#define ICMP6_ECHO_REQUEST 128 +#define ICMP6_ECHO_REPLY 129 +#define MLD_LISTENER_QUERY 130 +#define MLD_LISTENER_REPORT 131 +#define MLD_LISTENER_REDUCTION 132 + +#define ICMP6_DST_UNREACH_NOROUTE 0 /* no route to destination */ +#define ICMP6_DST_UNREACH_ADMIN 1 /* communication with destination */ + /* administratively prohibited */ +#define ICMP6_DST_UNREACH_BEYONDSCOPE 2 /* beyond scope of source address */ +#define ICMP6_DST_UNREACH_ADDR 3 /* address unreachable */ +#define ICMP6_DST_UNREACH_NOPORT 4 /* bad port */ + +#define ICMP6_TIME_EXCEED_TRANSIT 0 /* Hop Limit == 0 in transit */ +#define ICMP6_TIME_EXCEED_REASSEMBLY 1 /* Reassembly time out */ + +#define ICMP6_PARAMPROB_HEADER 0 /* erroneous header field */ +#define ICMP6_PARAMPROB_NEXTHEADER 1 /* unrecognized Next Header */ +#define ICMP6_PARAMPROB_OPTION 2 /* unrecognized IPv6 option */ + +#define ICMP6_FILTER_WILLPASS(type, filterp) \ + ((((filterp)->icmp6_filt[(type) >> 5]) & (1 << ((type) & 31))) == 0) + +#define ICMP6_FILTER_WILLBLOCK(type, filterp) \ + ((((filterp)->icmp6_filt[(type) >> 5]) & (1 << ((type) & 31))) != 0) + +#define ICMP6_FILTER_SETPASS(type, filterp) \ + ((((filterp)->icmp6_filt[(type) >> 5]) &= ~(1 << ((type) & 31)))) + +#define ICMP6_FILTER_SETBLOCK(type, filterp) \ + ((((filterp)->icmp6_filt[(type) >> 5]) |= (1 << ((type) & 31)))) + +#define ICMP6_FILTER_SETPASSALL(filterp) \ + memset (filterp, 0, sizeof (struct icmp6_filter)); + +#define ICMP6_FILTER_SETBLOCKALL(filterp) \ + memset (filterp, 0xFF, sizeof (struct icmp6_filter)); + +#define ND_ROUTER_SOLICIT 133 +#define ND_ROUTER_ADVERT 134 +#define ND_NEIGHBOR_SOLICIT 135 +#define ND_NEIGHBOR_ADVERT 136 +#define ND_REDIRECT 137 + +struct nd_router_solicit /* router solicitation */ + { + struct icmp6_hdr nd_rs_hdr; + /* could be followed by options */ + }; + +#define nd_rs_type nd_rs_hdr.icmp6_type +#define nd_rs_code nd_rs_hdr.icmp6_code +#define nd_rs_cksum nd_rs_hdr.icmp6_cksum +#define nd_rs_reserved nd_rs_hdr.icmp6_data32[0] + +struct nd_router_advert /* router advertisement */ + { + struct icmp6_hdr nd_ra_hdr; + uint32_t nd_ra_reachable; /* reachable time */ + uint32_t nd_ra_retransmit; /* retransmit timer */ + /* could be followed by options */ + }; + +#define nd_ra_type nd_ra_hdr.icmp6_type +#define nd_ra_code nd_ra_hdr.icmp6_code +#define nd_ra_cksum nd_ra_hdr.icmp6_cksum +#define nd_ra_curhoplimit nd_ra_hdr.icmp6_data8[0] +#define nd_ra_flags_reserved nd_ra_hdr.icmp6_data8[1] +#define ND_RA_FLAG_MANAGED 0x80 +#define ND_RA_FLAG_OTHER 0x40 +#define ND_RA_FLAG_HOME_AGENT 0x20 +#define nd_ra_router_lifetime nd_ra_hdr.icmp6_data16[1] + +struct nd_neighbor_solicit /* neighbor solicitation */ + { + struct icmp6_hdr nd_ns_hdr; + struct in6_addr nd_ns_target; /* target address */ + /* could be followed by options */ + }; + +#define nd_ns_type nd_ns_hdr.icmp6_type +#define nd_ns_code nd_ns_hdr.icmp6_code +#define nd_ns_cksum nd_ns_hdr.icmp6_cksum +#define nd_ns_reserved nd_ns_hdr.icmp6_data32[0] + +struct nd_neighbor_advert /* neighbor advertisement */ + { + struct icmp6_hdr nd_na_hdr; + struct in6_addr nd_na_target; /* target address */ + /* could be followed by options */ + }; + +#define nd_na_type nd_na_hdr.icmp6_type +#define nd_na_code nd_na_hdr.icmp6_code +#define nd_na_cksum nd_na_hdr.icmp6_cksum +#define nd_na_flags_reserved nd_na_hdr.icmp6_data32[0] +#if __BYTE_ORDER == __BIG_ENDIAN +#define ND_NA_FLAG_ROUTER 0x80000000 +#define ND_NA_FLAG_SOLICITED 0x40000000 +#define ND_NA_FLAG_OVERRIDE 0x20000000 +#else /* __BYTE_ORDER == __LITTLE_ENDIAN */ +#define ND_NA_FLAG_ROUTER 0x00000080 +#define ND_NA_FLAG_SOLICITED 0x00000040 +#define ND_NA_FLAG_OVERRIDE 0x00000020 +#endif + +struct nd_redirect /* redirect */ + { + struct icmp6_hdr nd_rd_hdr; + struct in6_addr nd_rd_target; /* target address */ + struct in6_addr nd_rd_dst; /* destination address */ + /* could be followed by options */ + }; + +#define nd_rd_type nd_rd_hdr.icmp6_type +#define nd_rd_code nd_rd_hdr.icmp6_code +#define nd_rd_cksum nd_rd_hdr.icmp6_cksum +#define nd_rd_reserved nd_rd_hdr.icmp6_data32[0] + +struct nd_opt_hdr /* Neighbor discovery option header */ + { + uint8_t nd_opt_type; + uint8_t nd_opt_len; /* in units of 8 octets */ + /* followed by option specific data */ + }; + +#define ND_OPT_SOURCE_LINKADDR 1 +#define ND_OPT_TARGET_LINKADDR 2 +#define ND_OPT_PREFIX_INFORMATION 3 +#define ND_OPT_REDIRECTED_HEADER 4 +#define ND_OPT_MTU 5 +#define ND_OPT_RTR_ADV_INTERVAL 7 +#define ND_OPT_HOME_AGENT_INFO 8 + +struct nd_opt_prefix_info /* prefix information */ + { + uint8_t nd_opt_pi_type; + uint8_t nd_opt_pi_len; + uint8_t nd_opt_pi_prefix_len; + uint8_t nd_opt_pi_flags_reserved; + uint32_t nd_opt_pi_valid_time; + uint32_t nd_opt_pi_preferred_time; + uint32_t nd_opt_pi_reserved2; + struct in6_addr nd_opt_pi_prefix; + }; + +#define ND_OPT_PI_FLAG_ONLINK 0x80 +#define ND_OPT_PI_FLAG_AUTO 0x40 +#define ND_OPT_PI_FLAG_RADDR 0x20 + +struct nd_opt_rd_hdr /* redirected header */ + { + uint8_t nd_opt_rh_type; + uint8_t nd_opt_rh_len; + uint16_t nd_opt_rh_reserved1; + uint32_t nd_opt_rh_reserved2; + /* followed by IP header and data */ + }; + +struct nd_opt_mtu /* MTU option */ + { + uint8_t nd_opt_mtu_type; + uint8_t nd_opt_mtu_len; + uint16_t nd_opt_mtu_reserved; + uint32_t nd_opt_mtu_mtu; + }; + +struct mld_hdr + { + struct icmp6_hdr mld_icmp6_hdr; + struct in6_addr mld_addr; /* multicast address */ + }; + +#define mld_type mld_icmp6_hdr.icmp6_type +#define mld_code mld_icmp6_hdr.icmp6_code +#define mld_cksum mld_icmp6_hdr.icmp6_cksum +#define mld_maxdelay mld_icmp6_hdr.icmp6_data16[0] +#define mld_reserved mld_icmp6_hdr.icmp6_data16[1] + +#define ICMP6_ROUTER_RENUMBERING 138 + +struct icmp6_router_renum /* router renumbering header */ + { + struct icmp6_hdr rr_hdr; + uint8_t rr_segnum; + uint8_t rr_flags; + uint16_t rr_maxdelay; + uint32_t rr_reserved; + }; + +#define rr_type rr_hdr.icmp6_type +#define rr_code rr_hdr.icmp6_code +#define rr_cksum rr_hdr.icmp6_cksum +#define rr_seqnum rr_hdr.icmp6_data32[0] + +/* Router renumbering flags */ +#define ICMP6_RR_FLAGS_TEST 0x80 +#define ICMP6_RR_FLAGS_REQRESULT 0x40 +#define ICMP6_RR_FLAGS_FORCEAPPLY 0x20 +#define ICMP6_RR_FLAGS_SPECSITE 0x10 +#define ICMP6_RR_FLAGS_PREVDONE 0x08 + +struct rr_pco_match /* match prefix part */ + { + uint8_t rpm_code; + uint8_t rpm_len; + uint8_t rpm_ordinal; + uint8_t rpm_matchlen; + uint8_t rpm_minlen; + uint8_t rpm_maxlen; + uint16_t rpm_reserved; + struct in6_addr rpm_prefix; + }; + +/* PCO code values */ +#define RPM_PCO_ADD 1 +#define RPM_PCO_CHANGE 2 +#define RPM_PCO_SETGLOBAL 3 + +struct rr_pco_use /* use prefix part */ + { + uint8_t rpu_uselen; + uint8_t rpu_keeplen; + uint8_t rpu_ramask; + uint8_t rpu_raflags; + uint32_t rpu_vltime; + uint32_t rpu_pltime; + uint32_t rpu_flags; + struct in6_addr rpu_prefix; + }; + +#define ICMP6_RR_PCOUSE_RAFLAGS_ONLINK 0x20 +#define ICMP6_RR_PCOUSE_RAFLAGS_AUTO 0x10 + +#if __BYTE_ORDER == __BIG_ENDIAN +# define ICMP6_RR_PCOUSE_FLAGS_DECRVLTIME 0x80000000 +# define ICMP6_RR_PCOUSE_FLAGS_DECRPLTIME 0x40000000 +#elif __BYTE_ORDER == __LITTLE_ENDIAN +# define ICMP6_RR_PCOUSE_FLAGS_DECRVLTIME 0x80 +# define ICMP6_RR_PCOUSE_FLAGS_DECRPLTIME 0x40 +#endif + +struct rr_result /* router renumbering result message */ + { + uint16_t rrr_flags; + uint8_t rrr_ordinal; + uint8_t rrr_matchedlen; + uint32_t rrr_ifid; + struct in6_addr rrr_prefix; + }; + +#if __BYTE_ORDER == __BIG_ENDIAN +# define ICMP6_RR_RESULT_FLAGS_OOB 0x0002 +# define ICMP6_RR_RESULT_FLAGS_FORBIDDEN 0x0001 +#elif __BYTE_ORDER == __LITTLE_ENDIAN +# define ICMP6_RR_RESULT_FLAGS_OOB 0x0200 +# define ICMP6_RR_RESULT_FLAGS_FORBIDDEN 0x0100 +#endif + +/* Mobile IPv6 extension: Advertisement Interval. */ +struct nd_opt_adv_interval + { + uint8_t nd_opt_adv_interval_type; + uint8_t nd_opt_adv_interval_len; + uint16_t nd_opt_adv_interval_reserved; + uint32_t nd_opt_adv_interval_ival; + }; + +/* Mobile IPv6 extension: Home Agent Info. */ +struct nd_opt_home_agent_info + { + uint8_t nd_opt_home_agent_info_type; + uint8_t nd_opt_home_agent_info_len; + uint16_t nd_opt_home_agent_info_reserved; + int16_t nd_opt_home_agent_info_preference; + uint16_t nd_opt_home_agent_info_lifetime; + }; + +#endif /* netinet/icmpv6.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/netinet/if_ether.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/netinet/if_ether.h new file mode 100644 index 00000000..aadb59be --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/netinet/if_ether.h @@ -0,0 +1,105 @@ +/* Copyright (C) 1996, 1997, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef __NETINET_IF_ETHER_H + +#define __NETINET_IF_ETHER_H 1 +#include +#include + +/* Get definitions from kernel header file. */ +#include + +#ifdef __USE_BSD +/* + * Copyright (c) 1982, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)if_ether.h 8.3 (Berkeley) 5/2/95 + * $FreeBSD$ + */ + +#include +#include + +__BEGIN_DECLS +/* + * Ethernet Address Resolution Protocol. + * + * See RFC 826 for protocol description. Structure below is adapted + * to resolving internet addresses. Field names used correspond to + * RFC 826. + */ +struct ether_arp { + struct arphdr ea_hdr; /* fixed-size header */ + u_int8_t arp_sha[ETH_ALEN]; /* sender hardware address */ + u_int8_t arp_spa[4]; /* sender protocol address */ + u_int8_t arp_tha[ETH_ALEN]; /* target hardware address */ + u_int8_t arp_tpa[4]; /* target protocol address */ +}; +#define arp_hrd ea_hdr.ar_hrd +#define arp_pro ea_hdr.ar_pro +#define arp_hln ea_hdr.ar_hln +#define arp_pln ea_hdr.ar_pln +#define arp_op ea_hdr.ar_op + +/* + * Macro to map an IP multicast address to an Ethernet multicast address. + * The high-order 25 bits of the Ethernet address are statically assigned, + * and the low-order 23 bits are taken from the low end of the IP address. + */ +#define ETHER_MAP_IP_MULTICAST(ipaddr, enaddr) \ + /* struct in_addr *ipaddr; */ \ + /* u_char enaddr[ETH_ALEN]; */ \ +{ \ + (enaddr)[0] = 0x01; \ + (enaddr)[1] = 0x00; \ + (enaddr)[2] = 0x5e; \ + (enaddr)[3] = ((u_int8_t *)ipaddr)[1] & 0x7f; \ + (enaddr)[4] = ((u_int8_t *)ipaddr)[2]; \ + (enaddr)[5] = ((u_int8_t *)ipaddr)[3]; \ +} + +__END_DECLS +#endif /* __USE_BSD */ + +#endif /* netinet/if_ether.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/netinet/if_fddi.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/netinet/if_fddi.h new file mode 100644 index 00000000..1a0ec927 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/netinet/if_fddi.h @@ -0,0 +1,37 @@ +/* Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _NETINET_IF_FDDI_H +#define _NETINET_IF_FDDI_H 1 + +#include +#include +#include + +#include + +#ifdef __USE_BSD + +struct fddi_header { + u_int8_t fddi_fc; /* Frame Control (FC) value */ + u_int8_t fddi_dhost[FDDI_K_ALEN]; /* Destination host */ + u_int8_t fddi_shost[FDDI_K_ALEN]; /* Source host */ +}; +#endif + +#endif /* netinet/if_fddi.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/netinet/if_tr.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/netinet/if_tr.h new file mode 100644 index 00000000..45c39115 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/netinet/if_tr.h @@ -0,0 +1,111 @@ +/* Copyright (C) 1997, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _NETINET_IF_TR_H +#define _NETINET_IF_TR_H 1 + +#include +#include + +/* IEEE 802.5 Token-Ring magic constants. The frame sizes omit the preamble + and FCS/CRC (frame check sequence). */ +#define TR_ALEN 6 /* Octets in one token-ring addr */ +#define TR_HLEN (sizeof (struct trh_hdr) + sizeof (struct trllc)) +#define AC 0x10 +#define LLC_FRAME 0x40 + +/* LLC and SNAP constants */ +#define EXTENDED_SAP 0xAA +#define UI_CMD 0x03 + +/* This is an Token-Ring frame header. */ +struct trh_hdr +{ + u_int8_t ac; /* access control field */ + u_int8_t fc; /* frame control field */ + u_int8_t daddr[TR_ALEN]; /* destination address */ + u_int8_t saddr[TR_ALEN]; /* source address */ + u_int16_t rcf; /* route control field */ + u_int16_t rseg[8]; /* routing registers */ +}; + +/* This is an Token-Ring LLC structure */ +struct trllc +{ + u_int8_t dsap; /* destination SAP */ + u_int8_t ssap; /* source SAP */ + u_int8_t llc; /* LLC control field */ + u_int8_t protid[3]; /* protocol id */ + u_int16_t ethertype; /* ether type field */ +}; + +/* Token-Ring statistics collection data. */ +struct tr_statistics +{ + unsigned long rx_packets; /* total packets received */ + unsigned long tx_packets; /* total packets transmitted */ + unsigned long rx_bytes; /* total bytes received */ + unsigned long tx_bytes; /* total bytes transmitted */ + unsigned long rx_errors; /* bad packets received */ + unsigned long tx_errors; /* packet transmit problems */ + unsigned long rx_dropped; /* no space in linux buffers */ + unsigned long tx_dropped; /* no space available in linux */ + unsigned long multicast; /* multicast packets received */ + unsigned long transmit_collision; + + /* detailed Token-Ring errors. See IBM Token-Ring Network + Architecture for more info */ + + unsigned long line_errors; + unsigned long internal_errors; + unsigned long burst_errors; + unsigned long A_C_errors; + unsigned long abort_delimiters; + unsigned long lost_frames; + unsigned long recv_congest_count; + unsigned long frame_copied_errors; + unsigned long frequency_errors; + unsigned long token_errors; + unsigned long dummy1; +}; + +/* source routing stuff */ +#define TR_RII 0x80 +#define TR_RCF_DIR_BIT 0x80 +#define TR_RCF_LEN_MASK 0x1f00 +#define TR_RCF_BROADCAST 0x8000 /* all-routes broadcast */ +#define TR_RCF_LIMITED_BROADCAST 0xC000 /* single-route broadcast */ +#define TR_RCF_FRAME2K 0x20 +#define TR_RCF_BROADCAST_MASK 0xC000 +#define TR_MAXRIFLEN 18 + +#ifdef __USE_BSD + +struct trn_hdr +{ + u_int8_t trn_ac; /* access control field */ + u_int8_t trn_fc; /* field control field */ + u_int8_t trn_dhost[TR_ALEN]; /* destination host */ + u_int8_t trn_shost[TR_ALEN]; /* source host */ + u_int16_t trn_rcf; /* route control field */ + u_int16_t trn_rseg[8]; /* routing registers */ +}; + +#endif + +#endif /* netinet/if_tr.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/netinet/igmp.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/netinet/igmp.h new file mode 100644 index 00000000..67396baa --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/netinet/igmp.h @@ -0,0 +1,126 @@ +/* Copyright (C) 1997, 1999, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _NETINET_IGMP_H +#define _NETINET_IGMP_H 1 + +#include +#include + +#ifdef __USE_BSD + +#include + +__BEGIN_DECLS + +/* + * Copyright (c) 1988 Stephen Deering. + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Stephen Deering of Stanford University. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)igmp.h 8.1 (Berkeley) 6/10/93 + * $FreeBSD$ + */ + +struct igmp { + u_int8_t igmp_type; /* IGMP type */ + u_int8_t igmp_code; /* routing code */ + u_int16_t igmp_cksum; /* checksum */ + struct in_addr igmp_group; /* group address */ +}; + +#define IGMP_MINLEN 8 + +/* + * Message types, including version number. + */ +#define IGMP_MEMBERSHIP_QUERY 0x11 /* membership query */ +#define IGMP_V1_MEMBERSHIP_REPORT 0x12 /* Ver. 1 membership report */ +#define IGMP_V2_MEMBERSHIP_REPORT 0x16 /* Ver. 2 membership report */ +#define IGMP_V2_LEAVE_GROUP 0x17 /* Leave-group message */ + +#define IGMP_DVMRP 0x13 /* DVMRP routing message */ +#define IGMP_PIM 0x14 /* PIM routing message */ +#define IGMP_TRACE 0x15 + +#define IGMP_MTRACE_RESP 0x1e /* traceroute resp.(to sender)*/ +#define IGMP_MTRACE 0x1f /* mcast traceroute messages */ + +#define IGMP_MAX_HOST_REPORT_DELAY 10 /* max delay for response to */ + /* query (in seconds) according */ + /* to RFC1112 */ +#define IGMP_TIMER_SCALE 10 /* denotes that the igmp code field */ + /* specifies time in 10th of seconds*/ + +/* + * States for the IGMP v2 state table. + */ +#define IGMP_DELAYING_MEMBER 1 +#define IGMP_IDLE_MEMBER 2 +#define IGMP_LAZY_MEMBER 3 +#define IGMP_SLEEPING_MEMBER 4 +#define IGMP_AWAKENING_MEMBER 5 + +/* + * States for IGMP router version cache. + */ +#define IGMP_v1_ROUTER 1 +#define IGMP_v2_ROUTER 2 + +/* + * The following four defininitions are for backwards compatibility. + * They should be removed as soon as all applications are updated to + * use the new constant names. + */ +#define IGMP_HOST_MEMBERSHIP_QUERY IGMP_MEMBERSHIP_QUERY +#define IGMP_HOST_MEMBERSHIP_REPORT IGMP_V1_MEMBERSHIP_REPORT +#define IGMP_HOST_NEW_MEMBERSHIP_REPORT IGMP_V2_MEMBERSHIP_REPORT +#define IGMP_HOST_LEAVE_MESSAGE IGMP_V2_LEAVE_GROUP + +__END_DECLS + +#endif + +#endif /* netinet/igmp.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/netinet/in.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/netinet/in.h new file mode 100644 index 00000000..6327001e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/netinet/in.h @@ -0,0 +1,578 @@ +/* Copyright (C) 1991-2001, 2003, 2004, 2006, 2007, 2008 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _NETINET_IN_H +#define _NETINET_IN_H 1 + +#include +#include +#include +#include + + +__BEGIN_DECLS + +/* Standard well-defined IP protocols. */ +enum + { + IPPROTO_IP = 0, /* Dummy protocol for TCP. */ +#define IPPROTO_IP IPPROTO_IP + IPPROTO_HOPOPTS = 0, /* IPv6 Hop-by-Hop options. */ +#define IPPROTO_HOPOPTS IPPROTO_HOPOPTS + IPPROTO_ICMP = 1, /* Internet Control Message Protocol. */ +#define IPPROTO_ICMP IPPROTO_ICMP + IPPROTO_IGMP = 2, /* Internet Group Management Protocol. */ +#define IPPROTO_IGMP IPPROTO_IGMP + IPPROTO_IPIP = 4, /* IPIP tunnels (older KA9Q tunnels use 94). */ +#define IPPROTO_IPIP IPPROTO_IPIP + IPPROTO_TCP = 6, /* Transmission Control Protocol. */ +#define IPPROTO_TCP IPPROTO_TCP + IPPROTO_EGP = 8, /* Exterior Gateway Protocol. */ +#define IPPROTO_EGP IPPROTO_EGP + IPPROTO_PUP = 12, /* PUP protocol. */ +#define IPPROTO_PUP IPPROTO_PUP + IPPROTO_UDP = 17, /* User Datagram Protocol. */ +#define IPPROTO_UDP IPPROTO_UDP + IPPROTO_IDP = 22, /* XNS IDP protocol. */ +#define IPPROTO_IDP IPPROTO_IDP + IPPROTO_TP = 29, /* SO Transport Protocol Class 4. */ +#define IPPROTO_TP IPPROTO_TP + IPPROTO_DCCP = 33, /* Datagram Congestion Control Protocol. */ +#define IPPROTO_DCCP IPPROTO_DCCP + IPPROTO_IPV6 = 41, /* IPv6 header. */ +#define IPPROTO_IPV6 IPPROTO_IPV6 + IPPROTO_ROUTING = 43, /* IPv6 routing header. */ +#define IPPROTO_ROUTING IPPROTO_ROUTING + IPPROTO_FRAGMENT = 44, /* IPv6 fragmentation header. */ +#define IPPROTO_FRAGMENT IPPROTO_FRAGMENT + IPPROTO_RSVP = 46, /* Reservation Protocol. */ +#define IPPROTO_RSVP IPPROTO_RSVP + IPPROTO_GRE = 47, /* General Routing Encapsulation. */ +#define IPPROTO_GRE IPPROTO_GRE + IPPROTO_ESP = 50, /* encapsulating security payload. */ +#define IPPROTO_ESP IPPROTO_ESP + IPPROTO_AH = 51, /* authentication header. */ +#define IPPROTO_AH IPPROTO_AH + IPPROTO_ICMPV6 = 58, /* ICMPv6. */ +#define IPPROTO_ICMPV6 IPPROTO_ICMPV6 + IPPROTO_NONE = 59, /* IPv6 no next header. */ +#define IPPROTO_NONE IPPROTO_NONE + IPPROTO_DSTOPTS = 60, /* IPv6 destination options. */ +#define IPPROTO_DSTOPTS IPPROTO_DSTOPTS + IPPROTO_MTP = 92, /* Multicast Transport Protocol. */ +#define IPPROTO_MTP IPPROTO_MTP + IPPROTO_ENCAP = 98, /* Encapsulation Header. */ +#define IPPROTO_ENCAP IPPROTO_ENCAP + IPPROTO_PIM = 103, /* Protocol Independent Multicast. */ +#define IPPROTO_PIM IPPROTO_PIM + IPPROTO_COMP = 108, /* Compression Header Protocol. */ +#define IPPROTO_COMP IPPROTO_COMP + IPPROTO_SCTP = 132, /* Stream Control Transmission Protocol. */ +#define IPPROTO_SCTP IPPROTO_SCTP + IPPROTO_UDPLITE = 136, /* UDP-Lite protocol. */ +#define IPPROTO_UDPLITE IPPROTO_UDPLITE + IPPROTO_RAW = 255, /* Raw IP packets. */ +#define IPPROTO_RAW IPPROTO_RAW + IPPROTO_MAX + }; + + +/* Type to represent a port. */ +typedef uint16_t in_port_t; + +/* Standard well-known ports. */ +enum + { + IPPORT_ECHO = 7, /* Echo service. */ + IPPORT_DISCARD = 9, /* Discard transmissions service. */ + IPPORT_SYSTAT = 11, /* System status service. */ + IPPORT_DAYTIME = 13, /* Time of day service. */ + IPPORT_NETSTAT = 15, /* Network status service. */ + IPPORT_FTP = 21, /* File Transfer Protocol. */ + IPPORT_TELNET = 23, /* Telnet protocol. */ + IPPORT_SMTP = 25, /* Simple Mail Transfer Protocol. */ + IPPORT_TIMESERVER = 37, /* Timeserver service. */ + IPPORT_NAMESERVER = 42, /* Domain Name Service. */ + IPPORT_WHOIS = 43, /* Internet Whois service. */ + IPPORT_MTP = 57, + + IPPORT_TFTP = 69, /* Trivial File Transfer Protocol. */ + IPPORT_RJE = 77, + IPPORT_FINGER = 79, /* Finger service. */ + IPPORT_TTYLINK = 87, + IPPORT_SUPDUP = 95, /* SUPDUP protocol. */ + + + IPPORT_EXECSERVER = 512, /* execd service. */ + IPPORT_LOGINSERVER = 513, /* rlogind service. */ + IPPORT_CMDSERVER = 514, + IPPORT_EFSSERVER = 520, + + /* UDP ports. */ + IPPORT_BIFFUDP = 512, + IPPORT_WHOSERVER = 513, + IPPORT_ROUTESERVER = 520, + + /* Ports less than this value are reserved for privileged processes. */ + IPPORT_RESERVED = 1024, + + /* Ports greater this value are reserved for (non-privileged) servers. */ + IPPORT_USERRESERVED = 5000 + }; + + +/* Internet address. */ +typedef uint32_t in_addr_t; +struct in_addr + { + in_addr_t s_addr; + }; + + +/* Definitions of the bits in an Internet address integer. + + On subnets, host and network parts are found according to + the subnet mask, not these masks. */ + +#define IN_CLASSA(a) ((((in_addr_t)(a)) & 0x80000000) == 0) +#define IN_CLASSA_NET 0xff000000 +#define IN_CLASSA_NSHIFT 24 +#define IN_CLASSA_HOST (0xffffffff & ~IN_CLASSA_NET) +#define IN_CLASSA_MAX 128 + +#define IN_CLASSB(a) ((((in_addr_t)(a)) & 0xc0000000) == 0x80000000) +#define IN_CLASSB_NET 0xffff0000 +#define IN_CLASSB_NSHIFT 16 +#define IN_CLASSB_HOST (0xffffffff & ~IN_CLASSB_NET) +#define IN_CLASSB_MAX 65536 + +#define IN_CLASSC(a) ((((in_addr_t)(a)) & 0xe0000000) == 0xc0000000) +#define IN_CLASSC_NET 0xffffff00 +#define IN_CLASSC_NSHIFT 8 +#define IN_CLASSC_HOST (0xffffffff & ~IN_CLASSC_NET) + +#define IN_CLASSD(a) ((((in_addr_t)(a)) & 0xf0000000) == 0xe0000000) +#define IN_MULTICAST(a) IN_CLASSD(a) + +#define IN_EXPERIMENTAL(a) ((((in_addr_t)(a)) & 0xe0000000) == 0xe0000000) +#define IN_BADCLASS(a) ((((in_addr_t)(a)) & 0xf0000000) == 0xf0000000) + +/* Address to accept any incoming messages. */ +#define INADDR_ANY ((in_addr_t) 0x00000000) +/* Address to send to all hosts. */ +#define INADDR_BROADCAST ((in_addr_t) 0xffffffff) +/* Address indicating an error return. */ +#define INADDR_NONE ((in_addr_t) 0xffffffff) + +/* Network number for local host loopback. */ +#define IN_LOOPBACKNET 127 +/* Address to loopback in software to local host. */ +#ifndef INADDR_LOOPBACK +# define INADDR_LOOPBACK ((in_addr_t) 0x7f000001) /* Inet 127.0.0.1. */ +#endif + +/* Defines for Multicast INADDR. */ +#define INADDR_UNSPEC_GROUP ((in_addr_t) 0xe0000000) /* 224.0.0.0 */ +#define INADDR_ALLHOSTS_GROUP ((in_addr_t) 0xe0000001) /* 224.0.0.1 */ +#define INADDR_ALLRTRS_GROUP ((in_addr_t) 0xe0000002) /* 224.0.0.2 */ +#define INADDR_MAX_LOCAL_GROUP ((in_addr_t) 0xe00000ff) /* 224.0.0.255 */ + + +/* IPv6 address */ +struct in6_addr + { + union + { + uint8_t __u6_addr8[16]; +#if defined __USE_MISC || defined __USE_GNU + uint16_t __u6_addr16[8]; + uint32_t __u6_addr32[4]; +#endif + } __in6_u; +#define s6_addr __in6_u.__u6_addr8 +#if defined __USE_MISC || defined __USE_GNU +# define s6_addr16 __in6_u.__u6_addr16 +# define s6_addr32 __in6_u.__u6_addr32 +#endif + }; + +extern const struct in6_addr in6addr_any; /* :: */ +extern const struct in6_addr in6addr_loopback; /* ::1 */ +libc_hidden_proto(in6addr_loopback) +#define IN6ADDR_ANY_INIT { { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } } } +#define IN6ADDR_LOOPBACK_INIT { { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 } } } + +#define INET_ADDRSTRLEN 16 +#define INET6_ADDRSTRLEN 46 + + +#if 1 /*def __UCLIBC_HAS_IPV4__*/ +/* Structure describing an Internet socket address. */ +struct sockaddr_in + { + __SOCKADDR_COMMON (sin_); + in_port_t sin_port; /* Port number. */ + struct in_addr sin_addr; /* Internet address. */ + + /* Pad to size of `struct sockaddr'. */ + unsigned char sin_zero[sizeof (struct sockaddr) - + __SOCKADDR_COMMON_SIZE - + sizeof (in_port_t) - + sizeof (struct in_addr)]; + }; +#endif + +/* Ditto, for IPv6. */ +struct sockaddr_in6 + { + __SOCKADDR_COMMON (sin6_); + in_port_t sin6_port; /* Transport layer port # */ + uint32_t sin6_flowinfo; /* IPv6 flow information */ + struct in6_addr sin6_addr; /* IPv6 address */ + uint32_t sin6_scope_id; /* IPv6 scope-id */ + }; + + +#if defined __USE_MISC || defined __USE_GNU +/* IPv4 multicast request. */ +struct ip_mreq + { + /* IP multicast address of group. */ + struct in_addr imr_multiaddr; + + /* Local IP address of interface. */ + struct in_addr imr_interface; + }; + +struct ip_mreq_source + { + /* IP multicast address of group. */ + struct in_addr imr_multiaddr; + + /* IP address of source. */ + struct in_addr imr_interface; + + /* IP address of interface. */ + struct in_addr imr_sourceaddr; + }; +#endif + + +/* Likewise, for IPv6. */ +struct ipv6_mreq + { + /* IPv6 multicast address of group */ + struct in6_addr ipv6mr_multiaddr; + + /* local interface */ + unsigned int ipv6mr_interface; + }; + + +#if defined __USE_MISC || defined __USE_GNU +/* Multicast group request. */ +struct group_req + { + /* Interface index. */ + uint32_t gr_interface; + + /* Group address. */ + struct sockaddr_storage gr_group; + }; + +struct group_source_req + { + /* Interface index. */ + uint32_t gsr_interface; + + /* Group address. */ + struct sockaddr_storage gsr_group; + + /* Source address. */ + struct sockaddr_storage gsr_source; + }; + + +/* Full-state filter operations. */ +struct ip_msfilter + { + /* IP multicast address of group. */ + struct in_addr imsf_multiaddr; + + /* Local IP address of interface. */ + struct in_addr imsf_interface; + + /* Filter mode. */ + uint32_t imsf_fmode; + + /* Number of source addresses. */ + uint32_t imsf_numsrc; + /* Source addresses. */ + struct in_addr imsf_slist[1]; + }; + +#define IP_MSFILTER_SIZE(numsrc) (sizeof (struct ip_msfilter) \ + - sizeof (struct in_addr) \ + + (numsrc) * sizeof (struct in_addr)) + +struct group_filter + { + /* Interface index. */ + uint32_t gf_interface; + + /* Group address. */ + struct sockaddr_storage gf_group; + + /* Filter mode. */ + uint32_t gf_fmode; + + /* Number of source addresses. */ + uint32_t gf_numsrc; + /* Source addresses. */ + struct sockaddr_storage gf_slist[1]; +}; + +#define GROUP_FILTER_SIZE(numsrc) (sizeof (struct group_filter) \ + - sizeof (struct sockaddr_storage) \ + + ((numsrc) \ + * sizeof (struct sockaddr_storage))) +#endif + + +/* Get system-specific definitions. */ +#include + +/* Functions to convert between host and network byte order. + + Please note that these functions normally take `unsigned long int' or + `unsigned short int' values as arguments and also return them. But + this was a short-sighted decision since on different systems the types + may have different representations but the values are always the same. */ + +extern uint32_t ntohl (uint32_t __netlong) __THROW __attribute__ ((__const__)); +libc_hidden_proto(ntohl) +extern uint16_t ntohs (uint16_t __netshort) + __THROW __attribute__ ((__const__)); +libc_hidden_proto(ntohs) +extern uint32_t htonl (uint32_t __hostlong) + __THROW __attribute__ ((__const__)); +libc_hidden_proto(htonl) +extern uint16_t htons (uint16_t __hostshort) + __THROW __attribute__ ((__const__)); +libc_hidden_proto(htons) + +#include + +/* Get machine dependent optimized versions of byte swapping functions. */ +#include + +#ifdef __OPTIMIZE__ +/* We can optimize calls to the conversion functions. Either nothing has + to be done or we are using directly the byte-swapping functions which + often can be inlined. */ +# if __BYTE_ORDER == __BIG_ENDIAN +/* The host byte order is the same as network byte order, + so these functions are all just identity. */ +# define ntohl(x) (x) +# define ntohs(x) (x) +# define htonl(x) (x) +# define htons(x) (x) +# else +# if __BYTE_ORDER == __LITTLE_ENDIAN +# define ntohl(x) __bswap_32 (x) +# define ntohs(x) __bswap_16 (x) +# define htonl(x) __bswap_32 (x) +# define htons(x) __bswap_16 (x) +# endif +# endif +#endif + +#define IN6_IS_ADDR_UNSPECIFIED(a) \ + (((__const uint32_t *) (a))[0] == 0 \ + && ((__const uint32_t *) (a))[1] == 0 \ + && ((__const uint32_t *) (a))[2] == 0 \ + && ((__const uint32_t *) (a))[3] == 0) + +#define IN6_IS_ADDR_LOOPBACK(a) \ + (((__const uint32_t *) (a))[0] == 0 \ + && ((__const uint32_t *) (a))[1] == 0 \ + && ((__const uint32_t *) (a))[2] == 0 \ + && ((__const uint32_t *) (a))[3] == htonl (1)) + +#define IN6_IS_ADDR_MULTICAST(a) (((__const uint8_t *) (a))[0] == 0xff) + +#define IN6_IS_ADDR_LINKLOCAL(a) \ + ((((__const uint32_t *) (a))[0] & htonl (0xffc00000)) \ + == htonl (0xfe800000)) + +#define IN6_IS_ADDR_SITELOCAL(a) \ + ((((__const uint32_t *) (a))[0] & htonl (0xffc00000)) \ + == htonl (0xfec00000)) + +#define IN6_IS_ADDR_V4MAPPED(a) \ + ((((__const uint32_t *) (a))[0] == 0) \ + && (((__const uint32_t *) (a))[1] == 0) \ + && (((__const uint32_t *) (a))[2] == htonl (0xffff))) + +#define IN6_IS_ADDR_V4COMPAT(a) \ + ((((__const uint32_t *) (a))[0] == 0) \ + && (((__const uint32_t *) (a))[1] == 0) \ + && (((__const uint32_t *) (a))[2] == 0) \ + && (ntohl (((__const uint32_t *) (a))[3]) > 1)) + +#define IN6_ARE_ADDR_EQUAL(a,b) \ + ((((__const uint32_t *) (a))[0] == ((__const uint32_t *) (b))[0]) \ + && (((__const uint32_t *) (a))[1] == ((__const uint32_t *) (b))[1]) \ + && (((__const uint32_t *) (a))[2] == ((__const uint32_t *) (b))[2]) \ + && (((__const uint32_t *) (a))[3] == ((__const uint32_t *) (b))[3])) + +#if defined __USE_MISC || defined __USE_GNU +/* Bind socket to a privileged IP port. */ +extern int bindresvport (int __sockfd, struct sockaddr_in *__sock_in) __THROW; +libc_hidden_proto(bindresvport) + +# if 0 /*def __UCLIBC_HAS_IPV6__*/ +/* The IPv6 version of this function. */ +extern int bindresvport6 (int __sockfd, struct sockaddr_in6 *__sock_in) + __THROW; +# endif +#endif + + +#define IN6_IS_ADDR_MC_NODELOCAL(a) \ + (IN6_IS_ADDR_MULTICAST(a) \ + && ((((__const uint8_t *) (a))[1] & 0xf) == 0x1)) + +#define IN6_IS_ADDR_MC_LINKLOCAL(a) \ + (IN6_IS_ADDR_MULTICAST(a) \ + && ((((__const uint8_t *) (a))[1] & 0xf) == 0x2)) + +#define IN6_IS_ADDR_MC_SITELOCAL(a) \ + (IN6_IS_ADDR_MULTICAST(a) \ + && ((((__const uint8_t *) (a))[1] & 0xf) == 0x5)) + +#define IN6_IS_ADDR_MC_ORGLOCAL(a) \ + (IN6_IS_ADDR_MULTICAST(a) \ + && ((((__const uint8_t *) (a))[1] & 0xf) == 0x8)) + +#define IN6_IS_ADDR_MC_GLOBAL(a) \ + (IN6_IS_ADDR_MULTICAST(a) \ + && ((((__const uint8_t *) (a))[1] & 0xf) == 0xe)) + + +#if defined __USE_GNU && defined __UCLIBC_HAS_IPV6__ +/* IPv6 packet information. */ +struct in6_pktinfo + { + struct in6_addr ipi6_addr; /* src/dst IPv6 address */ + unsigned int ipi6_ifindex; /* send/recv interface index */ + }; + +/* IPv6 MTU information. */ +struct ip6_mtuinfo + { + struct sockaddr_in6 ip6m_addr; /* dst address including zone ID */ + uint32_t ip6m_mtu; /* path MTU in host byte order */ + }; +#endif +#if 0 /*def __USE_GNU*/ + +/* Obsolete hop-by-hop and Destination Options Processing (RFC 2292). */ +extern int inet6_option_space (int __nbytes) + __THROW __attribute_deprecated__; +extern int inet6_option_init (void *__bp, struct cmsghdr **__cmsgp, + int __type) __THROW __attribute_deprecated__; +extern int inet6_option_append (struct cmsghdr *__cmsg, + __const uint8_t *__typep, int __multx, + int __plusy) __THROW __attribute_deprecated__; +extern uint8_t *inet6_option_alloc (struct cmsghdr *__cmsg, int __datalen, + int __multx, int __plusy) + __THROW __attribute_deprecated__; +extern int inet6_option_next (__const struct cmsghdr *__cmsg, + uint8_t **__tptrp) + __THROW __attribute_deprecated__; +extern int inet6_option_find (__const struct cmsghdr *__cmsg, + uint8_t **__tptrp, int __type) + __THROW __attribute_deprecated__; + + +/* Hop-by-Hop and Destination Options Processing (RFC 3542). */ +extern int inet6_opt_init (void *__extbuf, socklen_t __extlen) __THROW; +extern int inet6_opt_append (void *__extbuf, socklen_t __extlen, int __offset, + uint8_t __type, socklen_t __len, uint8_t __align, + void **__databufp) __THROW; +extern int inet6_opt_finish (void *__extbuf, socklen_t __extlen, int __offset) + __THROW; +extern int inet6_opt_set_val (void *__databuf, int __offset, void *__val, + socklen_t __vallen) __THROW; +extern int inet6_opt_next (void *__extbuf, socklen_t __extlen, int __offset, + uint8_t *__typep, socklen_t *__lenp, + void **__databufp) __THROW; +extern int inet6_opt_find (void *__extbuf, socklen_t __extlen, int __offset, + uint8_t __type, socklen_t *__lenp, + void **__databufp) __THROW; +extern int inet6_opt_get_val (void *__databuf, int __offset, void *__val, + socklen_t __vallen) __THROW; + + +/* Routing Header Option (RFC 3542). */ +extern socklen_t inet6_rth_space (int __type, int __segments) __THROW; +extern void *inet6_rth_init (void *__bp, socklen_t __bp_len, int __type, + int __segments) __THROW; +extern int inet6_rth_add (void *__bp, __const struct in6_addr *__addr) __THROW; +extern int inet6_rth_reverse (__const void *__in, void *__out) __THROW; +extern int inet6_rth_segments (__const void *__bp) __THROW; +extern struct in6_addr *inet6_rth_getaddr (__const void *__bp, int __index) + __THROW; + + +/* Multicast source filter support. */ + +/* Get IPv4 source filter. */ +extern int getipv4sourcefilter (int __s, struct in_addr __interface_addr, + struct in_addr __group, uint32_t *__fmode, + uint32_t *__numsrc, struct in_addr *__slist) + __THROW; + +/* Set IPv4 source filter. */ +extern int setipv4sourcefilter (int __s, struct in_addr __interface_addr, + struct in_addr __group, uint32_t __fmode, + uint32_t __numsrc, + __const struct in_addr *__slist) + __THROW; + + +/* Get source filter. */ +extern int getsourcefilter (int __s, uint32_t __interface_addr, + __const struct sockaddr *__group, + socklen_t __grouplen, uint32_t *__fmode, + uint32_t *__numsrc, + struct sockaddr_storage *__slist) __THROW; + +/* Set source filter. */ +extern int setsourcefilter (int __s, uint32_t __interface_addr, + __const struct sockaddr *__group, + socklen_t __grouplen, uint32_t __fmode, + uint32_t __numsrc, + __const struct sockaddr_storage *__slist) __THROW; +#endif /* use GNU */ + +__END_DECLS + +#endif /* netinet/in.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/netinet/in_systm.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/netinet/in_systm.h new file mode 100644 index 00000000..51a08e17 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/netinet/in_systm.h @@ -0,0 +1,41 @@ +/* System specific type definitions for networking code. + Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _NETINET_IN_SYSTM_H +#define _NETINET_IN_SYSTM_H 1 + +#include +#include + +__BEGIN_DECLS + +/* + * Network order versions of various data types. Unfortunately, BSD + * assumes specific sizes for shorts (16 bit) and longs (32 bit) which + * don't hold in general. As a consequence, the network order versions + * may not reflect the actual size of the native data types. + */ + +typedef u_int16_t n_short; /* short as received from the net */ +typedef u_int32_t n_long; /* long as received from the net */ +typedef u_int32_t n_time; /* ms since 00:00 GMT, byte rev */ + +__END_DECLS + +#endif /* netinet/in_systm.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/netinet/ip.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/netinet/ip.h new file mode 100644 index 00000000..fc914405 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/netinet/ip.h @@ -0,0 +1,249 @@ +/* Copyright (C) 1991,92,93,95,96,97,98,99,2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef __NETINET_IP_H +#define __NETINET_IP_H 1 + +#include +#include + +#include + +__BEGIN_DECLS + +struct timestamp + { + u_int8_t len; + u_int8_t ptr; +#if __BYTE_ORDER == __LITTLE_ENDIAN + unsigned int flags:4; + unsigned int overflow:4; +#elif __BYTE_ORDER == __BIG_ENDIAN + unsigned int overflow:4; + unsigned int flags:4; +#else +# error "Please fix " +#endif + u_int32_t data[9]; + }; + +struct iphdr + { +#if __BYTE_ORDER == __LITTLE_ENDIAN + unsigned int ihl:4; + unsigned int version:4; +#elif __BYTE_ORDER == __BIG_ENDIAN + unsigned int version:4; + unsigned int ihl:4; +#else +# error "Please fix " +#endif + u_int8_t tos; + u_int16_t tot_len; + u_int16_t id; + u_int16_t frag_off; + u_int8_t ttl; + u_int8_t protocol; + u_int16_t check; + u_int32_t saddr; + u_int32_t daddr; + /*The options start here. */ + }; + +#ifdef __USE_BSD +/* + * Copyright (c) 1982, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ip.h 8.1 (Berkeley) 6/10/93 + */ + +/* + * Definitions for internet protocol version 4. + * Per RFC 791, September 1981. + */ + +/* + * Structure of an internet header, naked of options. + */ +struct ip + { +#if __BYTE_ORDER == __LITTLE_ENDIAN + unsigned int ip_hl:4; /* header length */ + unsigned int ip_v:4; /* version */ +#endif +#if __BYTE_ORDER == __BIG_ENDIAN + unsigned int ip_v:4; /* version */ + unsigned int ip_hl:4; /* header length */ +#endif + u_int8_t ip_tos; /* type of service */ + u_short ip_len; /* total length */ + u_short ip_id; /* identification */ + u_short ip_off; /* fragment offset field */ +#define IP_RF 0x8000 /* reserved fragment flag */ +#define IP_DF 0x4000 /* dont fragment flag */ +#define IP_MF 0x2000 /* more fragments flag */ +#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */ + u_int8_t ip_ttl; /* time to live */ + u_int8_t ip_p; /* protocol */ + u_short ip_sum; /* checksum */ + struct in_addr ip_src, ip_dst; /* source and dest address */ + }; + +/* + * Time stamp option structure. + */ +struct ip_timestamp + { + u_int8_t ipt_code; /* IPOPT_TS */ + u_int8_t ipt_len; /* size of structure (variable) */ + u_int8_t ipt_ptr; /* index of current entry */ +#if __BYTE_ORDER == __LITTLE_ENDIAN + unsigned int ipt_flg:4; /* flags, see below */ + unsigned int ipt_oflw:4; /* overflow counter */ +#endif +#if __BYTE_ORDER == __BIG_ENDIAN + unsigned int ipt_oflw:4; /* overflow counter */ + unsigned int ipt_flg:4; /* flags, see below */ +#endif + u_int32_t data[9]; + }; +#endif /* __USE_BSD */ + +#define IPVERSION 4 /* IP version number */ +#define IP_MAXPACKET 65535 /* maximum packet size */ + +/* + * Definitions for IP type of service (ip_tos) + */ +#define IPTOS_TOS_MASK 0x1E +#define IPTOS_TOS(tos) ((tos) & IPTOS_TOS_MASK) +#define IPTOS_LOWDELAY 0x10 +#define IPTOS_THROUGHPUT 0x08 +#define IPTOS_RELIABILITY 0x04 +#define IPTOS_LOWCOST 0x02 +#define IPTOS_MINCOST IPTOS_LOWCOST + +/* + * Definitions for IP precedence (also in ip_tos) (hopefully unused) + */ +#define IPTOS_PREC_MASK 0xe0 +#define IPTOS_PREC(tos) ((tos) & IPTOS_PREC_MASK) +#define IPTOS_PREC_NETCONTROL 0xe0 +#define IPTOS_PREC_INTERNETCONTROL 0xc0 +#define IPTOS_PREC_CRITIC_ECP 0xa0 +#define IPTOS_PREC_FLASHOVERRIDE 0x80 +#define IPTOS_PREC_FLASH 0x60 +#define IPTOS_PREC_IMMEDIATE 0x40 +#define IPTOS_PREC_PRIORITY 0x20 +#define IPTOS_PREC_ROUTINE 0x00 + +/* + * Definitions for options. + */ +#define IPOPT_COPY 0x80 +#define IPOPT_CLASS_MASK 0x60 +#define IPOPT_NUMBER_MASK 0x1f + +#define IPOPT_COPIED(o) ((o) & IPOPT_COPY) +#define IPOPT_CLASS(o) ((o) & IPOPT_CLASS_MASK) +#define IPOPT_NUMBER(o) ((o) & IPOPT_NUMBER_MASK) + +#define IPOPT_CONTROL 0x00 +#define IPOPT_RESERVED1 0x20 +#define IPOPT_DEBMEAS 0x40 +#define IPOPT_MEASUREMENT IPOPT_DEBMEAS +#define IPOPT_RESERVED2 0x60 + +#define IPOPT_EOL 0 /* end of option list */ +#define IPOPT_END IPOPT_EOL +#define IPOPT_NOP 1 /* no operation */ +#define IPOPT_NOOP IPOPT_NOP + +#define IPOPT_RR 7 /* record packet route */ +#define IPOPT_TS 68 /* timestamp */ +#define IPOPT_TIMESTAMP IPOPT_TS +#define IPOPT_SECURITY 130 /* provide s,c,h,tcc */ +#define IPOPT_SEC IPOPT_SECURITY +#define IPOPT_LSRR 131 /* loose source route */ +#define IPOPT_SATID 136 /* satnet id */ +#define IPOPT_SID IPOPT_SATID +#define IPOPT_SSRR 137 /* strict source route */ +#define IPOPT_RA 148 /* router alert */ + +/* + * Offsets to fields in options other than EOL and NOP. + */ +#define IPOPT_OPTVAL 0 /* option ID */ +#define IPOPT_OLEN 1 /* option length */ +#define IPOPT_OFFSET 2 /* offset within option */ +#define IPOPT_MINOFF 4 /* min value of above */ + +#define MAX_IPOPTLEN 40 + +/* flag bits for ipt_flg */ +#define IPOPT_TS_TSONLY 0 /* timestamps only */ +#define IPOPT_TS_TSANDADDR 1 /* timestamps and addresses */ +#define IPOPT_TS_PRESPEC 3 /* specified modules only */ + +/* bits for security (not byte swapped) */ +#define IPOPT_SECUR_UNCLASS 0x0000 +#define IPOPT_SECUR_CONFID 0xf135 +#define IPOPT_SECUR_EFTO 0x789a +#define IPOPT_SECUR_MMMM 0xbc4d +#define IPOPT_SECUR_RESTR 0xaf13 +#define IPOPT_SECUR_SECRET 0xd788 +#define IPOPT_SECUR_TOPSECRET 0x6bc5 + +/* + * Internet implementation parameters. + */ +#define MAXTTL 255 /* maximum time to live (seconds) */ +#define IPDEFTTL 64 /* default ttl, from RFC 1340 */ +#define IPFRAGTTL 60 /* time to live for frags, slowhz */ +#define IPTTLDEC 1 /* subtracted when forwarding */ + +#define IP_MSS 576 /* default maximum segment size */ + +__END_DECLS + +#endif /* netinet/ip.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/netinet/ip6.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/netinet/ip6.h new file mode 100644 index 00000000..c82b277e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/netinet/ip6.h @@ -0,0 +1,189 @@ +/* Copyright (C) 1991-1997, 2001, 2003, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _NETINET_IP6_H +#define _NETINET_IP6_H 1 + +#include +#include + +struct ip6_hdr + { + union + { + struct ip6_hdrctl + { + uint32_t ip6_un1_flow; /* 4 bits version, 8 bits TC, + 20 bits flow-ID */ + uint16_t ip6_un1_plen; /* payload length */ + uint8_t ip6_un1_nxt; /* next header */ + uint8_t ip6_un1_hlim; /* hop limit */ + } ip6_un1; + uint8_t ip6_un2_vfc; /* 4 bits version, top 4 bits tclass */ + } ip6_ctlun; + struct in6_addr ip6_src; /* source address */ + struct in6_addr ip6_dst; /* destination address */ + }; + +#define ip6_vfc ip6_ctlun.ip6_un2_vfc +#define ip6_flow ip6_ctlun.ip6_un1.ip6_un1_flow +#define ip6_plen ip6_ctlun.ip6_un1.ip6_un1_plen +#define ip6_nxt ip6_ctlun.ip6_un1.ip6_un1_nxt +#define ip6_hlim ip6_ctlun.ip6_un1.ip6_un1_hlim +#define ip6_hops ip6_ctlun.ip6_un1.ip6_un1_hlim + +/* Generic extension header. */ +struct ip6_ext + { + uint8_t ip6e_nxt; /* next header. */ + uint8_t ip6e_len; /* length in units of 8 octets. */ + }; + +/* Hop-by-Hop options header. */ +struct ip6_hbh + { + uint8_t ip6h_nxt; /* next header. */ + uint8_t ip6h_len; /* length in units of 8 octets. */ + /* followed by options */ + }; + +/* Destination options header */ +struct ip6_dest + { + uint8_t ip6d_nxt; /* next header */ + uint8_t ip6d_len; /* length in units of 8 octets */ + /* followed by options */ + }; + +/* Routing header */ +struct ip6_rthdr + { + uint8_t ip6r_nxt; /* next header */ + uint8_t ip6r_len; /* length in units of 8 octets */ + uint8_t ip6r_type; /* routing type */ + uint8_t ip6r_segleft; /* segments left */ + /* followed by routing type specific data */ + }; + +/* Type 0 Routing header */ +struct ip6_rthdr0 + { + uint8_t ip6r0_nxt; /* next header */ + uint8_t ip6r0_len; /* length in units of 8 octets */ + uint8_t ip6r0_type; /* always zero */ + uint8_t ip6r0_segleft; /* segments left */ + uint8_t ip6r0_reserved; /* reserved field */ + uint8_t ip6r0_slmap[3]; /* strict/loose bit map */ + /* followed by up to 127 struct in6_addr */ + struct in6_addr ip6r0_addr[0]; + }; + +/* Fragment header */ +struct ip6_frag + { + uint8_t ip6f_nxt; /* next header */ + uint8_t ip6f_reserved; /* reserved field */ + uint16_t ip6f_offlg; /* offset, reserved, and flag */ + uint32_t ip6f_ident; /* identification */ + }; + +#if __BYTE_ORDER == __BIG_ENDIAN +# define IP6F_OFF_MASK 0xfff8 /* mask out offset from _offlg */ +# define IP6F_RESERVED_MASK 0x0006 /* reserved bits in ip6f_offlg */ +# define IP6F_MORE_FRAG 0x0001 /* more-fragments flag */ +#else /* __BYTE_ORDER == __LITTLE_ENDIAN */ +# define IP6F_OFF_MASK 0xf8ff /* mask out offset from _offlg */ +# define IP6F_RESERVED_MASK 0x0600 /* reserved bits in ip6f_offlg */ +# define IP6F_MORE_FRAG 0x0100 /* more-fragments flag */ +#endif + +/* IPv6 options */ +struct ip6_opt + { + uint8_t ip6o_type; + uint8_t ip6o_len; + }; + +/* The high-order 3 bits of the option type define the behavior + * when processing an unknown option and whether or not the option + * content changes in flight. + */ +#define IP6OPT_TYPE(o) ((o) & 0xc0) +#define IP6OPT_TYPE_SKIP 0x00 +#define IP6OPT_TYPE_DISCARD 0x40 +#define IP6OPT_TYPE_FORCEICMP 0x80 +#define IP6OPT_TYPE_ICMP 0xc0 +#define IP6OPT_TYPE_MUTABLE 0x20 + +/* Special option types for padding. */ +#define IP6OPT_PAD1 0 +#define IP6OPT_PADN 1 + +#define IP6OPT_JUMBO 0xc2 +#define IP6OPT_NSAP_ADDR 0xc3 +#define IP6OPT_TUNNEL_LIMIT 0x04 +#define IP6OPT_ROUTER_ALERT 0x05 + +/* Jumbo Payload Option */ +struct ip6_opt_jumbo + { + uint8_t ip6oj_type; + uint8_t ip6oj_len; + uint8_t ip6oj_jumbo_len[4]; + }; +#define IP6OPT_JUMBO_LEN 6 + +/* NSAP Address Option */ +struct ip6_opt_nsap + { + uint8_t ip6on_type; + uint8_t ip6on_len; + uint8_t ip6on_src_nsap_len; + uint8_t ip6on_dst_nsap_len; + /* followed by source NSAP */ + /* followed by destination NSAP */ + }; + +/* Tunnel Limit Option */ +struct ip6_opt_tunnel + { + uint8_t ip6ot_type; + uint8_t ip6ot_len; + uint8_t ip6ot_encap_limit; + }; + +/* Router Alert Option */ +struct ip6_opt_router + { + uint8_t ip6or_type; + uint8_t ip6or_len; + uint8_t ip6or_value[2]; + }; + +/* Router alert values (in network byte order) */ +#if __BYTE_ORDER == __BIG_ENDIAN +# define IP6_ALERT_MLD 0x0000 +# define IP6_ALERT_RSVP 0x0001 +# define IP6_ALERT_AN 0x0002 +#else /* __BYTE_ORDER == __LITTLE_ENDING */ +# define IP6_ALERT_MLD 0x0000 +# define IP6_ALERT_RSVP 0x0100 +# define IP6_ALERT_AN 0x0200 +#endif + +#endif /* netinet/ip6.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/netinet/ip_icmp.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/netinet/ip_icmp.h new file mode 100644 index 00000000..2fc8e9c1 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/netinet/ip_icmp.h @@ -0,0 +1,283 @@ +/* Copyright (C) 1991, 92, 93, 95, 96, 97, 99 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef __NETINET_IP_ICMP_H +#define __NETINET_IP_ICMP_H 1 + +#include +#include + +__BEGIN_DECLS + +struct icmphdr +{ + u_int8_t type; /* message type */ + u_int8_t code; /* type sub-code */ + u_int16_t checksum; + union + { + struct + { + u_int16_t id; + u_int16_t sequence; + } echo; /* echo datagram */ + u_int32_t gateway; /* gateway address */ + struct + { + u_int16_t __unused; + u_int16_t mtu; + } frag; /* path mtu discovery */ + } un; +}; + +#define ICMP_ECHOREPLY 0 /* Echo Reply */ +#define ICMP_DEST_UNREACH 3 /* Destination Unreachable */ +#define ICMP_SOURCE_QUENCH 4 /* Source Quench */ +#define ICMP_REDIRECT 5 /* Redirect (change route) */ +#define ICMP_ECHO 8 /* Echo Request */ +#define ICMP_TIME_EXCEEDED 11 /* Time Exceeded */ +#define ICMP_PARAMETERPROB 12 /* Parameter Problem */ +#define ICMP_TIMESTAMP 13 /* Timestamp Request */ +#define ICMP_TIMESTAMPREPLY 14 /* Timestamp Reply */ +#define ICMP_INFO_REQUEST 15 /* Information Request */ +#define ICMP_INFO_REPLY 16 /* Information Reply */ +#define ICMP_ADDRESS 17 /* Address Mask Request */ +#define ICMP_ADDRESSREPLY 18 /* Address Mask Reply */ +#define NR_ICMP_TYPES 18 + + +/* Codes for UNREACH. */ +#define ICMP_NET_UNREACH 0 /* Network Unreachable */ +#define ICMP_HOST_UNREACH 1 /* Host Unreachable */ +#define ICMP_PROT_UNREACH 2 /* Protocol Unreachable */ +#define ICMP_PORT_UNREACH 3 /* Port Unreachable */ +#define ICMP_FRAG_NEEDED 4 /* Fragmentation Needed/DF set */ +#define ICMP_SR_FAILED 5 /* Source Route failed */ +#define ICMP_NET_UNKNOWN 6 +#define ICMP_HOST_UNKNOWN 7 +#define ICMP_HOST_ISOLATED 8 +#define ICMP_NET_ANO 9 +#define ICMP_HOST_ANO 10 +#define ICMP_NET_UNR_TOS 11 +#define ICMP_HOST_UNR_TOS 12 +#define ICMP_PKT_FILTERED 13 /* Packet filtered */ +#define ICMP_PREC_VIOLATION 14 /* Precedence violation */ +#define ICMP_PREC_CUTOFF 15 /* Precedence cut off */ +#define NR_ICMP_UNREACH 15 /* instead of hardcoding immediate value */ + +/* Codes for REDIRECT. */ +#define ICMP_REDIR_NET 0 /* Redirect Net */ +#define ICMP_REDIR_HOST 1 /* Redirect Host */ +#define ICMP_REDIR_NETTOS 2 /* Redirect Net for TOS */ +#define ICMP_REDIR_HOSTTOS 3 /* Redirect Host for TOS */ + +/* Codes for TIME_EXCEEDED. */ +#define ICMP_EXC_TTL 0 /* TTL count exceeded */ +#define ICMP_EXC_FRAGTIME 1 /* Fragment Reass time exceeded */ + + +#ifdef __USE_BSD +/* + * Copyright (c) 1982, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ip_icmp.h 8.1 (Berkeley) 6/10/93 + */ + +#include +#include + +/* + * Internal of an ICMP Router Advertisement + */ +struct icmp_ra_addr +{ + u_int32_t ira_addr; + u_int32_t ira_preference; +}; + +struct icmp +{ + u_int8_t icmp_type; /* type of message, see below */ + u_int8_t icmp_code; /* type sub code */ + u_int16_t icmp_cksum; /* ones complement checksum of struct */ + union + { + u_char ih_pptr; /* ICMP_PARAMPROB */ + struct in_addr ih_gwaddr; /* gateway address */ + struct ih_idseq /* echo datagram */ + { + u_int16_t icd_id; + u_int16_t icd_seq; + } ih_idseq; + u_int32_t ih_void; + + /* ICMP_UNREACH_NEEDFRAG -- Path MTU Discovery (RFC1191) */ + struct ih_pmtu + { + u_int16_t ipm_void; + u_int16_t ipm_nextmtu; + } ih_pmtu; + + struct ih_rtradv + { + u_int8_t irt_num_addrs; + u_int8_t irt_wpa; + u_int16_t irt_lifetime; + } ih_rtradv; + } icmp_hun; +#define icmp_pptr icmp_hun.ih_pptr +#define icmp_gwaddr icmp_hun.ih_gwaddr +#define icmp_id icmp_hun.ih_idseq.icd_id +#define icmp_seq icmp_hun.ih_idseq.icd_seq +#define icmp_void icmp_hun.ih_void +#define icmp_pmvoid icmp_hun.ih_pmtu.ipm_void +#define icmp_nextmtu icmp_hun.ih_pmtu.ipm_nextmtu +#define icmp_num_addrs icmp_hun.ih_rtradv.irt_num_addrs +#define icmp_wpa icmp_hun.ih_rtradv.irt_wpa +#define icmp_lifetime icmp_hun.ih_rtradv.irt_lifetime + union + { + struct + { + u_int32_t its_otime; + u_int32_t its_rtime; + u_int32_t its_ttime; + } id_ts; + struct + { + struct ip idi_ip; + /* options and then 64 bits of data */ + } id_ip; + struct icmp_ra_addr id_radv; + u_int32_t id_mask; + u_int8_t id_data[1]; + } icmp_dun; +#define icmp_otime icmp_dun.id_ts.its_otime +#define icmp_rtime icmp_dun.id_ts.its_rtime +#define icmp_ttime icmp_dun.id_ts.its_ttime +#define icmp_ip icmp_dun.id_ip.idi_ip +#define icmp_radv icmp_dun.id_radv +#define icmp_mask icmp_dun.id_mask +#define icmp_data icmp_dun.id_data +}; + +/* + * Lower bounds on packet lengths for various types. + * For the error advice packets must first insure that the + * packet is large enough to contain the returned ip header. + * Only then can we do the check to see if 64 bits of packet + * data have been returned, since we need to check the returned + * ip header length. + */ +#define ICMP_MINLEN 8 /* abs minimum */ +#define ICMP_TSLEN (8 + 3 * sizeof (n_time)) /* timestamp */ +#define ICMP_MASKLEN 12 /* address mask */ +#define ICMP_ADVLENMIN (8 + sizeof (struct ip) + 8) /* min */ +#ifndef _IP_VHL +#define ICMP_ADVLEN(p) (8 + ((p)->icmp_ip.ip_hl << 2) + 8) + /* N.B.: must separately check that ip_hl >= 5 */ +#else +#define ICMP_ADVLEN(p) (8 + (IP_VHL_HL((p)->icmp_ip.ip_vhl) << 2) + 8) + /* N.B.: must separately check that header length >= 5 */ +#endif + +/* Definition of type and code fields. */ +/* defined above: ICMP_ECHOREPLY, ICMP_REDIRECT, ICMP_ECHO */ +#define ICMP_UNREACH 3 /* dest unreachable, codes: */ +#define ICMP_SOURCEQUENCH 4 /* packet lost, slow down */ +#define ICMP_ROUTERADVERT 9 /* router advertisement */ +#define ICMP_ROUTERSOLICIT 10 /* router solicitation */ +#define ICMP_TIMXCEED 11 /* time exceeded, code: */ +#define ICMP_PARAMPROB 12 /* ip header bad */ +#define ICMP_TSTAMP 13 /* timestamp request */ +#define ICMP_TSTAMPREPLY 14 /* timestamp reply */ +#define ICMP_IREQ 15 /* information request */ +#define ICMP_IREQREPLY 16 /* information reply */ +#define ICMP_MASKREQ 17 /* address mask request */ +#define ICMP_MASKREPLY 18 /* address mask reply */ + +#define ICMP_MAXTYPE 18 + +/* UNREACH codes */ +#define ICMP_UNREACH_NET 0 /* bad net */ +#define ICMP_UNREACH_HOST 1 /* bad host */ +#define ICMP_UNREACH_PROTOCOL 2 /* bad protocol */ +#define ICMP_UNREACH_PORT 3 /* bad port */ +#define ICMP_UNREACH_NEEDFRAG 4 /* IP_DF caused drop */ +#define ICMP_UNREACH_SRCFAIL 5 /* src route failed */ +#define ICMP_UNREACH_NET_UNKNOWN 6 /* unknown net */ +#define ICMP_UNREACH_HOST_UNKNOWN 7 /* unknown host */ +#define ICMP_UNREACH_ISOLATED 8 /* src host isolated */ +#define ICMP_UNREACH_NET_PROHIB 9 /* net denied */ +#define ICMP_UNREACH_HOST_PROHIB 10 /* host denied */ +#define ICMP_UNREACH_TOSNET 11 /* bad tos for net */ +#define ICMP_UNREACH_TOSHOST 12 /* bad tos for host */ +#define ICMP_UNREACH_FILTER_PROHIB 13 /* admin prohib */ +#define ICMP_UNREACH_HOST_PRECEDENCE 14 /* host prec vio. */ +#define ICMP_UNREACH_PRECEDENCE_CUTOFF 15 /* prec cutoff */ + +/* REDIRECT codes */ +#define ICMP_REDIRECT_NET 0 /* for network */ +#define ICMP_REDIRECT_HOST 1 /* for host */ +#define ICMP_REDIRECT_TOSNET 2 /* for tos and net */ +#define ICMP_REDIRECT_TOSHOST 3 /* for tos and host */ + +/* TIMEXCEED codes */ +#define ICMP_TIMXCEED_INTRANS 0 /* ttl==0 in transit */ +#define ICMP_TIMXCEED_REASS 1 /* ttl==0 in reass */ + +/* PARAMPROB code */ +#define ICMP_PARAMPROB_OPTABSENT 1 /* req. opt. absent */ + +#define ICMP_INFOTYPE(type) \ + ((type) == ICMP_ECHOREPLY || (type) == ICMP_ECHO || \ + (type) == ICMP_ROUTERADVERT || (type) == ICMP_ROUTERSOLICIT || \ + (type) == ICMP_TSTAMP || (type) == ICMP_TSTAMPREPLY || \ + (type) == ICMP_IREQ || (type) == ICMP_IREQREPLY || \ + (type) == ICMP_MASKREQ || (type) == ICMP_MASKREPLY) + +#endif /* __USE_BSD */ + +__END_DECLS + +#endif /* netinet/ip_icmp.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/netinet/tcp.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/netinet/tcp.h new file mode 100644 index 00000000..06e8414b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/netinet/tcp.h @@ -0,0 +1,246 @@ +/* + * Copyright (c) 1982, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)tcp.h 8.1 (Berkeley) 6/10/93 + */ + +#ifndef _NETINET_TCP_H +#define _NETINET_TCP_H 1 + +#include + +/* + * User-settable options (used with setsockopt). + */ +#define TCP_NODELAY 1 /* Don't delay send to coalesce packets */ +#define TCP_MAXSEG 2 /* Set maximum segment size */ +#define TCP_CORK 3 /* Control sending of partial frames */ +#define TCP_KEEPIDLE 4 /* Start keeplives after this period */ +#define TCP_KEEPINTVL 5 /* Interval between keepalives */ +#define TCP_KEEPCNT 6 /* Number of keepalives before death */ +#define TCP_SYNCNT 7 /* Number of SYN retransmits */ +#define TCP_LINGER2 8 /* Life time of orphaned FIN-WAIT-2 state */ +#define TCP_DEFER_ACCEPT 9 /* Wake up listener only when data arrive */ +#define TCP_WINDOW_CLAMP 10 /* Bound advertised window */ +#define TCP_INFO 11 /* Information about this connection. */ +#define TCP_QUICKACK 12 /* Bock/reenable quick ACKs. */ +#define TCP_CONGESTION 13 /* Congestion control algorithm. */ +#define TCP_MD5SIG 14 /* TCP MD5 Signature (RFC2385) */ + +#ifdef __USE_MISC +# include +# include + +# ifdef __FAVOR_BSD +typedef u_int32_t tcp_seq; +/* + * TCP header. + * Per RFC 793, September, 1981. + */ +struct tcphdr + { + u_int16_t th_sport; /* source port */ + u_int16_t th_dport; /* destination port */ + tcp_seq th_seq; /* sequence number */ + tcp_seq th_ack; /* acknowledgement number */ +# if __BYTE_ORDER == __LITTLE_ENDIAN + u_int8_t th_x2:4; /* (unused) */ + u_int8_t th_off:4; /* data offset */ +# endif +# if __BYTE_ORDER == __BIG_ENDIAN + u_int8_t th_off:4; /* data offset */ + u_int8_t th_x2:4; /* (unused) */ +# endif + u_int8_t th_flags; +# define TH_FIN 0x01 +# define TH_SYN 0x02 +# define TH_RST 0x04 +# define TH_PUSH 0x08 +# define TH_ACK 0x10 +# define TH_URG 0x20 + u_int16_t th_win; /* window */ + u_int16_t th_sum; /* checksum */ + u_int16_t th_urp; /* urgent pointer */ +}; + +# else /* !__FAVOR_BSD */ +struct tcphdr + { + u_int16_t source; + u_int16_t dest; + u_int32_t seq; + u_int32_t ack_seq; +# if __BYTE_ORDER == __LITTLE_ENDIAN + u_int16_t res1:4; + u_int16_t doff:4; + u_int16_t fin:1; + u_int16_t syn:1; + u_int16_t rst:1; + u_int16_t psh:1; + u_int16_t ack:1; + u_int16_t urg:1; + u_int16_t res2:2; +# elif __BYTE_ORDER == __BIG_ENDIAN + u_int16_t doff:4; + u_int16_t res1:4; + u_int16_t res2:2; + u_int16_t urg:1; + u_int16_t ack:1; + u_int16_t psh:1; + u_int16_t rst:1; + u_int16_t syn:1; + u_int16_t fin:1; +# else +# error "Adjust your defines" +# endif + u_int16_t window; + u_int16_t check; + u_int16_t urg_ptr; +}; +# endif /* __FAVOR_BSD */ + +enum +{ + TCP_ESTABLISHED = 1, + TCP_SYN_SENT, + TCP_SYN_RECV, + TCP_FIN_WAIT1, + TCP_FIN_WAIT2, + TCP_TIME_WAIT, + TCP_CLOSE, + TCP_CLOSE_WAIT, + TCP_LAST_ACK, + TCP_LISTEN, + TCP_CLOSING /* now a valid state */ +}; + +# define TCPOPT_EOL 0 +# define TCPOPT_NOP 1 +# define TCPOPT_MAXSEG 2 +# define TCPOLEN_MAXSEG 4 +# define TCPOPT_WINDOW 3 +# define TCPOLEN_WINDOW 3 +# define TCPOPT_SACK_PERMITTED 4 /* Experimental */ +# define TCPOLEN_SACK_PERMITTED 2 +# define TCPOPT_SACK 5 /* Experimental */ +# define TCPOPT_TIMESTAMP 8 +# define TCPOLEN_TIMESTAMP 10 +# define TCPOLEN_TSTAMP_APPA (TCPOLEN_TIMESTAMP+2) /* appendix A */ + +# define TCPOPT_TSTAMP_HDR \ + (TCPOPT_NOP<<24|TCPOPT_NOP<<16|TCPOPT_TIMESTAMP<<8|TCPOLEN_TIMESTAMP) + +/* + * Default maximum segment size for TCP. + * With an IP MSS of 576, this is 536, + * but 512 is probably more convenient. + * This should be defined as MIN(512, IP_MSS - sizeof (struct tcpiphdr)). + */ +# define TCP_MSS 512 + +# define TCP_MAXWIN 65535 /* largest value for (unscaled) window */ + +# define TCP_MAX_WINSHIFT 14 /* maximum window shift */ + +# define SOL_TCP 6 /* TCP level */ + + +# define TCPI_OPT_TIMESTAMPS 1 +# define TCPI_OPT_SACK 2 +# define TCPI_OPT_WSCALE 4 +# define TCPI_OPT_ECN 8 + +/* Values for tcpi_state. */ +enum tcp_ca_state +{ + TCP_CA_Open = 0, + TCP_CA_Disorder = 1, + TCP_CA_CWR = 2, + TCP_CA_Recovery = 3, + TCP_CA_Loss = 4 +}; + +struct tcp_info +{ + u_int8_t tcpi_state; + u_int8_t tcpi_ca_state; + u_int8_t tcpi_retransmits; + u_int8_t tcpi_probes; + u_int8_t tcpi_backoff; + u_int8_t tcpi_options; + u_int8_t tcpi_snd_wscale : 4, tcpi_rcv_wscale : 4; + + u_int32_t tcpi_rto; + u_int32_t tcpi_ato; + u_int32_t tcpi_snd_mss; + u_int32_t tcpi_rcv_mss; + + u_int32_t tcpi_unacked; + u_int32_t tcpi_sacked; + u_int32_t tcpi_lost; + u_int32_t tcpi_retrans; + u_int32_t tcpi_fackets; + + /* Times. */ + u_int32_t tcpi_last_data_sent; + u_int32_t tcpi_last_ack_sent; /* Not remembered, sorry. */ + u_int32_t tcpi_last_data_recv; + u_int32_t tcpi_last_ack_recv; + + /* Metrics. */ + u_int32_t tcpi_pmtu; + u_int32_t tcpi_rcv_ssthresh; + u_int32_t tcpi_rtt; + u_int32_t tcpi_rttvar; + u_int32_t tcpi_snd_ssthresh; + u_int32_t tcpi_snd_cwnd; + u_int32_t tcpi_advmss; + u_int32_t tcpi_reordering; + + u_int32_t tcpi_rcv_rtt; + u_int32_t tcpi_rcv_space; + + u_int32_t tcpi_total_retrans; +}; + + +/* For TCP_MD5SIG socket option. */ +#define TCP_MD5SIG_MAXKEYLEN 80 + +struct tcp_md5sig +{ + struct sockaddr_storage tcpm_addr; /* Address associated. */ + u_int16_t __tcpm_pad1; /* Zero. */ + u_int16_t tcpm_keylen; /* Key length. */ + u_int32_t __tcpm_pad2; /* Zero. */ + u_int8_t tcpm_key[TCP_MD5SIG_MAXKEYLEN]; /* Key (binary). */ +}; + +#endif /* Misc. */ + +#endif /* netinet/tcp.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/netinet/udp.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/netinet/udp.h new file mode 100644 index 00000000..45b69f74 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/netinet/udp.h @@ -0,0 +1,79 @@ +/* Copyright (C) 1991, 92, 93, 95, 96, 97, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * Copyright (C) 1982, 1986 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef __NETINET_UDP_H +#define __NETINET_UDP_H 1 + +#include +#include + + +/* UDP header as specified by RFC 768, August 1980. */ +#ifdef __FAVOR_BSD + +struct udphdr +{ + u_int16_t uh_sport; /* source port */ + u_int16_t uh_dport; /* destination port */ + u_int16_t uh_ulen; /* udp length */ + u_int16_t uh_sum; /* udp checksum */ +}; + +#else + +struct udphdr +{ + u_int16_t source; + u_int16_t dest; + u_int16_t len; + u_int16_t check; +}; +#endif + +#define SOL_UDP 17 /* sockopt level for UDP */ + +#endif /* netinet/udp.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/netipx/ipx.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/netipx/ipx.h new file mode 100644 index 00000000..7eb42ef5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/netipx/ipx.h @@ -0,0 +1,113 @@ +/* Copyright (C) 1991, 92, 93, 95, 96, 97, 98 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef __NETIPX_IPX_H +#define __NETIPX_IPX_H 1 + +#include + +#include +#include + +__BEGIN_DECLS + +#define SOL_IPX 256 /* sockopt level */ + +#define IPX_TYPE 1 +#define IPX_NODE_LEN 6 +#define IPX_MTU 576 + +struct sockaddr_ipx + { + sa_family_t sipx_family; + u_int16_t sipx_port; + u_int32_t sipx_network; + unsigned char sipx_node[IPX_NODE_LEN]; + u_int8_t sipx_type; + unsigned char sipx_zero; /* 16 byte fill */ + }; + +/* + * So we can fit the extra info for SIOCSIFADDR into the address nicely + */ + +#define sipx_special sipx_port +#define sipx_action sipx_zero +#define IPX_DLTITF 0 +#define IPX_CRTITF 1 + +typedef struct ipx_route_definition + { + unsigned long ipx_network; + unsigned long ipx_router_network; + unsigned char ipx_router_node[IPX_NODE_LEN]; + } +ipx_route_definition; + +typedef struct ipx_interface_definition + { + unsigned long ipx_network; + unsigned char ipx_device[16]; + unsigned char ipx_dlink_type; +#define IPX_FRAME_NONE 0 +#define IPX_FRAME_SNAP 1 +#define IPX_FRAME_8022 2 +#define IPX_FRAME_ETHERII 3 +#define IPX_FRAME_8023 4 +#define IPX_FRAME_TR_8022 5 + unsigned char ipx_special; +#define IPX_SPECIAL_NONE 0 +#define IPX_PRIMARY 1 +#define IPX_INTERNAL 2 + unsigned char ipx_node[IPX_NODE_LEN]; + } +ipx_interface_definition; + +typedef struct ipx_config_data + { + unsigned char ipxcfg_auto_select_primary; + unsigned char ipxcfg_auto_create_interfaces; + } +ipx_config_data; + +/* + * OLD Route Definition for backward compatibility. + */ + +struct ipx_route_def + { + unsigned long ipx_network; + unsigned long ipx_router_network; +#define IPX_ROUTE_NO_ROUTER 0 + unsigned char ipx_router_node[IPX_NODE_LEN]; + unsigned char ipx_device[16]; + unsigned short ipx_flags; +#define IPX_RT_SNAP 8 +#define IPX_RT_8022 4 +#define IPX_RT_BLUEBOOK 2 +#define IPX_RT_ROUTED 1 + }; + +#define SIOCAIPXITFCRT (SIOCPROTOPRIVATE) +#define SIOCAIPXPRISLT (SIOCPROTOPRIVATE + 1) +#define SIOCIPXCFGDATA (SIOCPROTOPRIVATE + 2) +#define SIOCIPXNCPCONN (SIOCPROTOPRIVATE + 3) + +__END_DECLS + +#endif /* netipx/ipx.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/netpacket/packet.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/netpacket/packet.h new file mode 100644 index 00000000..6c634282 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/netpacket/packet.h @@ -0,0 +1,64 @@ +/* Definitions for use with Linux AF_PACKET sockets. + Copyright (C) 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef __NETPACKET_PACKET_H +#define __NETPACKET_PACKET_H 1 + +struct sockaddr_ll + { + unsigned short int sll_family; + unsigned short int sll_protocol; + int sll_ifindex; + unsigned short int sll_hatype; + unsigned char sll_pkttype; + unsigned char sll_halen; + unsigned char sll_addr[8]; + }; + +/* Packet types. */ + +#define PACKET_HOST 0 /* To us. */ +#define PACKET_BROADCAST 1 /* To all. */ +#define PACKET_MULTICAST 2 /* To group. */ +#define PACKET_OTHERHOST 3 /* To someone else. */ +#define PACKET_OUTGOING 4 /* Originated by us . */ +#define PACKET_LOOPBACK 5 +#define PACKET_FASTROUTE 6 + +/* Packet socket options. */ + +#define PACKET_ADD_MEMBERSHIP 1 +#define PACKET_DROP_MEMBERSHIP 2 +#define PACKET_RECV_OUTPUT 3 +#define PACKET_RX_RING 5 +#define PACKET_STATISTICS 6 + +struct packet_mreq + { + int mr_ifindex; + unsigned short int mr_type; + unsigned short int mr_alen; + unsigned char mr_address[8]; + }; + +#define PACKET_MR_MULTICAST 0 +#define PACKET_MR_PROMISC 1 +#define PACKET_MR_ALLMULTI 2 + +#endif /* netpacket/packet.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/nl_types.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/nl_types.h new file mode 100644 index 00000000..d6d48ecd --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/nl_types.h @@ -0,0 +1,61 @@ +/* Copyright (C) 1996, 1997, 1999, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _NL_TYPES_H +#define _NL_TYPES_H 1 + +#include + +/* The default message set used by the gencat program. */ +#define NL_SETD 1 + +/* Value for FLAG parameter of `catgets' to say we want XPG4 compliance. */ +#define NL_CAT_LOCALE 1 + + +__BEGIN_DECLS + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning "mjn3 FIXME: None of these prototypes have implementations." +#endif + +/* Message catalog descriptor type. */ +typedef void *nl_catd; + +/* Type used by `nl_langinfo'. */ +typedef int nl_item; + +#if 0 +/* Open message catalog for later use, returning descriptor. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern nl_catd catopen (__const char *__cat_name, int __flag) __nonnull ((1)); + +/* Return translation with NUMBER in SET of CATALOG; if not found + return STRING. */ +extern char *catgets (nl_catd __catalog, int __set, int __number, + __const char *__string) __THROW __nonnull ((1)); + +/* Close message CATALOG. */ +extern int catclose (nl_catd __catalog) __THROW __nonnull ((1)); +#endif + +__END_DECLS + +#endif /* nl_types.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/obstack.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/obstack.h new file mode 100644 index 00000000..65eb2bae --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/obstack.h @@ -0,0 +1,509 @@ +/* obstack.h - object stack macros + Copyright (C) 1988-1994,1996-1999,2003,2004,2005 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. */ + +/* Summary: + +All the apparent functions defined here are macros. The idea +is that you would use these pre-tested macros to solve a +very specific set of problems, and they would run fast. +Caution: no side-effects in arguments please!! They may be +evaluated MANY times!! + +These macros operate a stack of objects. Each object starts life +small, and may grow to maturity. (Consider building a word syllable +by syllable.) An object can move while it is growing. Once it has +been "finished" it never changes address again. So the "top of the +stack" is typically an immature growing object, while the rest of the +stack is of mature, fixed size and fixed address objects. + +These routines grab large chunks of memory, using a function you +supply, called `obstack_chunk_alloc'. On occasion, they free chunks, +by calling `obstack_chunk_free'. You must define them and declare +them before using any obstack macros. + +Each independent stack is represented by a `struct obstack'. +Each of the obstack macros expects a pointer to such a structure +as the first argument. + +One motivation for this package is the problem of growing char strings +in symbol tables. Unless you are "fascist pig with a read-only mind" +--Gosper's immortal quote from HAKMEM item 154, out of context--you +would not like to put any arbitrary upper limit on the length of your +symbols. + +In practice this often means you will build many short symbols and a +few long symbols. At the time you are reading a symbol you don't know +how long it is. One traditional method is to read a symbol into a +buffer, realloc()ating the buffer every time you try to read a symbol +that is longer than the buffer. This is beaut, but you still will +want to copy the symbol from the buffer to a more permanent +symbol-table entry say about half the time. + +With obstacks, you can work differently. Use one obstack for all symbol +names. As you read a symbol, grow the name in the obstack gradually. +When the name is complete, finalize it. Then, if the symbol exists already, +free the newly read name. + +The way we do this is to take a large chunk, allocating memory from +low addresses. When you want to build a symbol in the chunk you just +add chars above the current "high water mark" in the chunk. When you +have finished adding chars, because you got to the end of the symbol, +you know how long the chars are, and you can create a new object. +Mostly the chars will not burst over the highest address of the chunk, +because you would typically expect a chunk to be (say) 100 times as +long as an average object. + +In case that isn't clear, when we have enough chars to make up +the object, THEY ARE ALREADY CONTIGUOUS IN THE CHUNK (guaranteed) +so we just point to it where it lies. No moving of chars is +needed and this is the second win: potentially long strings need +never be explicitly shuffled. Once an object is formed, it does not +change its address during its lifetime. + +When the chars burst over a chunk boundary, we allocate a larger +chunk, and then copy the partly formed object from the end of the old +chunk to the beginning of the new larger chunk. We then carry on +accreting characters to the end of the object as we normally would. + +A special macro is provided to add a single char at a time to a +growing object. This allows the use of register variables, which +break the ordinary 'growth' macro. + +Summary: + We allocate large chunks. + We carve out one object at a time from the current chunk. + Once carved, an object never moves. + We are free to append data of any size to the currently + growing object. + Exactly one object is growing in an obstack at any one time. + You can run one obstack per control block. + You may have as many control blocks as you dare. + Because of the way we do it, you can `unwind' an obstack + back to a previous state. (You may remove objects much + as you would with a stack.) +*/ + + +/* Don't do the contents of this file more than once. */ + +#ifndef _OBSTACK_H +#define _OBSTACK_H 1 + +#ifdef __cplusplus +extern "C" { +#endif + +/* We need the type of a pointer subtraction. If __PTRDIFF_TYPE__ is + defined, as with GNU C, use that; that way we don't pollute the + namespace with 's symbols. Otherwise, include + and use ptrdiff_t. */ + +#ifdef __PTRDIFF_TYPE__ +# define PTR_INT_TYPE __PTRDIFF_TYPE__ +#else +# include +# define PTR_INT_TYPE ptrdiff_t +#endif + +/* If B is the base of an object addressed by P, return the result of + aligning P to the next multiple of A + 1. B and P must be of type + char *. A + 1 must be a power of 2. */ + +#define __BPTR_ALIGN(B, P, A) ((B) + (((P) - (B) + (A)) & ~(A))) + +/* Similiar to _BPTR_ALIGN (B, P, A), except optimize the common case + where pointers can be converted to integers, aligned as integers, + and converted back again. If PTR_INT_TYPE is narrower than a + pointer (e.g., the AS/400), play it safe and compute the alignment + relative to B. Otherwise, use the faster strategy of computing the + alignment relative to 0. */ + +#define __PTR_ALIGN(B, P, A) \ + __BPTR_ALIGN (sizeof (PTR_INT_TYPE) < sizeof (void *) ? (B) : (char *) 0, \ + P, A) + +#include + +struct _obstack_chunk /* Lives at front of each chunk. */ +{ + char *limit; /* 1 past end of this chunk */ + struct _obstack_chunk *prev; /* address of prior chunk or NULL */ + char contents[4]; /* objects begin here */ +}; + +struct obstack /* control current object in current chunk */ +{ + long chunk_size; /* preferred size to allocate chunks in */ + struct _obstack_chunk *chunk; /* address of current struct obstack_chunk */ + char *object_base; /* address of object we are building */ + char *next_free; /* where to add next char to current object */ + char *chunk_limit; /* address of char after current chunk */ + union + { + PTR_INT_TYPE tempint; + void *tempptr; + } temp; /* Temporary for some macros. */ + int alignment_mask; /* Mask of alignment for each object. */ + /* These prototypes vary based on `use_extra_arg', and we use + casts to the prototypeless function type in all assignments, + but having prototypes here quiets -Wstrict-prototypes. */ + struct _obstack_chunk *(*chunkfun) (void *, long); + void (*freefun) (void *, struct _obstack_chunk *); + void *extra_arg; /* first arg for chunk alloc/dealloc funcs */ + unsigned use_extra_arg:1; /* chunk alloc/dealloc funcs take extra arg */ + unsigned maybe_empty_object:1;/* There is a possibility that the current + chunk contains a zero-length object. This + prevents freeing the chunk if we allocate + a bigger chunk to replace it. */ + unsigned alloc_failed:1; /* No longer used, as we now call the failed + handler on error, but retained for binary + compatibility. */ +}; + +/* Declare the external functions we use; they are in obstack.c. */ + +extern void _obstack_newchunk (struct obstack *, int); +extern int _obstack_begin (struct obstack *, int, int, + void *(*) (long), void (*) (void *)); +extern int _obstack_begin_1 (struct obstack *, int, int, + void *(*) (void *, long), + void (*) (void *, void *), void *); +extern int _obstack_memory_used (struct obstack *); + +void obstack_free (struct obstack *obstack, void *block); + + +/* Error handler called when `obstack_chunk_alloc' failed to allocate + more memory. This can be set to a user defined function which + should either abort gracefully or use longjump - but shouldn't + return. The default action is to print a message and abort. */ +extern void (*obstack_alloc_failed_handler) (void); + +/* Exit value used when `print_and_abort' is used. */ +extern int obstack_exit_failure; + +/* Pointer to beginning of object being allocated or to be allocated next. + Note that this might not be the final address of the object + because a new chunk might be needed to hold the final size. */ + +#define obstack_base(h) ((void *) (h)->object_base) + +/* Size for allocating ordinary chunks. */ + +#define obstack_chunk_size(h) ((h)->chunk_size) + +/* Pointer to next byte not yet allocated in current chunk. */ + +#define obstack_next_free(h) ((h)->next_free) + +/* Mask specifying low bits that should be clear in address of an object. */ + +#define obstack_alignment_mask(h) ((h)->alignment_mask) + +/* To prevent prototype warnings provide complete argument list. */ +#define obstack_init(h) \ + _obstack_begin ((h), 0, 0, \ + (void *(*) (long)) obstack_chunk_alloc, \ + (void (*) (void *)) obstack_chunk_free) + +#define obstack_begin(h, size) \ + _obstack_begin ((h), (size), 0, \ + (void *(*) (long)) obstack_chunk_alloc, \ + (void (*) (void *)) obstack_chunk_free) + +#define obstack_specify_allocation(h, size, alignment, chunkfun, freefun) \ + _obstack_begin ((h), (size), (alignment), \ + (void *(*) (long)) (chunkfun), \ + (void (*) (void *)) (freefun)) + +#define obstack_specify_allocation_with_arg(h, size, alignment, chunkfun, freefun, arg) \ + _obstack_begin_1 ((h), (size), (alignment), \ + (void *(*) (void *, long)) (chunkfun), \ + (void (*) (void *, void *)) (freefun), (arg)) + +#define obstack_chunkfun(h, newchunkfun) \ + ((h) -> chunkfun = (struct _obstack_chunk *(*)(void *, long)) (newchunkfun)) + +#define obstack_freefun(h, newfreefun) \ + ((h) -> freefun = (void (*)(void *, struct _obstack_chunk *)) (newfreefun)) + +#define obstack_1grow_fast(h,achar) (*((h)->next_free)++ = (achar)) + +#define obstack_blank_fast(h,n) ((h)->next_free += (n)) + +#define obstack_memory_used(h) _obstack_memory_used (h) + +#if defined __GNUC__ && defined __STDC__ && __STDC__ +/* NextStep 2.0 cc is really gcc 1.93 but it defines __GNUC__ = 2 and + does not implement __extension__. But that compiler doesn't define + __GNUC_MINOR__. */ +# if __GNUC__ < 2 || (defined __NeXT__ && __NeXT__ && !__GNUC_MINOR__) +# define __extension__ +# endif + +/* For GNU C, if not -traditional, + we can define these macros to compute all args only once + without using a global variable. + Also, we can avoid using the `temp' slot, to make faster code. */ + +# define obstack_object_size(OBSTACK) \ + __extension__ \ + ({ struct obstack const *__o = (OBSTACK); \ + (unsigned) (__o->next_free - __o->object_base); }) + +# define obstack_room(OBSTACK) \ + __extension__ \ + ({ struct obstack const *__o = (OBSTACK); \ + (unsigned) (__o->chunk_limit - __o->next_free); }) + +# define obstack_make_room(OBSTACK,length) \ +__extension__ \ +({ struct obstack *__o = (OBSTACK); \ + int __len = (length); \ + if (__o->chunk_limit - __o->next_free < __len) \ + _obstack_newchunk (__o, __len); \ + (void) 0; }) + +# define obstack_empty_p(OBSTACK) \ + __extension__ \ + ({ struct obstack const *__o = (OBSTACK); \ + (__o->chunk->prev == 0 \ + && __o->next_free == __PTR_ALIGN ((char *) __o->chunk, \ + __o->chunk->contents, \ + __o->alignment_mask)); }) + +# define obstack_grow(OBSTACK,where,length) \ +__extension__ \ +({ struct obstack *__o = (OBSTACK); \ + int __len = (length); \ + if (__o->next_free + __len > __o->chunk_limit) \ + _obstack_newchunk (__o, __len); \ + memcpy (__o->next_free, where, __len); \ + __o->next_free += __len; \ + (void) 0; }) + +# define obstack_grow0(OBSTACK,where,length) \ +__extension__ \ +({ struct obstack *__o = (OBSTACK); \ + int __len = (length); \ + if (__o->next_free + __len + 1 > __o->chunk_limit) \ + _obstack_newchunk (__o, __len + 1); \ + memcpy (__o->next_free, where, __len); \ + __o->next_free += __len; \ + *(__o->next_free)++ = 0; \ + (void) 0; }) + +# define obstack_1grow(OBSTACK,datum) \ +__extension__ \ +({ struct obstack *__o = (OBSTACK); \ + if (__o->next_free + 1 > __o->chunk_limit) \ + _obstack_newchunk (__o, 1); \ + obstack_1grow_fast (__o, datum); \ + (void) 0; }) + +/* These assume that the obstack alignment is good enough for pointers + or ints, and that the data added so far to the current object + shares that much alignment. */ + +# define obstack_ptr_grow(OBSTACK,datum) \ +__extension__ \ +({ struct obstack *__o = (OBSTACK); \ + if (__o->next_free + sizeof (void *) > __o->chunk_limit) \ + _obstack_newchunk (__o, sizeof (void *)); \ + obstack_ptr_grow_fast (__o, datum); }) \ + +# define obstack_int_grow(OBSTACK,datum) \ +__extension__ \ +({ struct obstack *__o = (OBSTACK); \ + if (__o->next_free + sizeof (int) > __o->chunk_limit) \ + _obstack_newchunk (__o, sizeof (int)); \ + obstack_int_grow_fast (__o, datum); }) + +# define obstack_ptr_grow_fast(OBSTACK,aptr) \ +__extension__ \ +({ struct obstack *__o1 = (OBSTACK); \ + *(const void **) __o1->next_free = (aptr); \ + __o1->next_free += sizeof (const void *); \ + (void) 0; }) + +# define obstack_int_grow_fast(OBSTACK,aint) \ +__extension__ \ +({ struct obstack *__o1 = (OBSTACK); \ + *(int *) __o1->next_free = (aint); \ + __o1->next_free += sizeof (int); \ + (void) 0; }) + +# define obstack_blank(OBSTACK,length) \ +__extension__ \ +({ struct obstack *__o = (OBSTACK); \ + int __len = (length); \ + if (__o->chunk_limit - __o->next_free < __len) \ + _obstack_newchunk (__o, __len); \ + obstack_blank_fast (__o, __len); \ + (void) 0; }) + +# define obstack_alloc(OBSTACK,length) \ +__extension__ \ +({ struct obstack *__h = (OBSTACK); \ + obstack_blank (__h, (length)); \ + obstack_finish (__h); }) + +# define obstack_copy(OBSTACK,where,length) \ +__extension__ \ +({ struct obstack *__h = (OBSTACK); \ + obstack_grow (__h, (where), (length)); \ + obstack_finish (__h); }) + +# define obstack_copy0(OBSTACK,where,length) \ +__extension__ \ +({ struct obstack *__h = (OBSTACK); \ + obstack_grow0 (__h, (where), (length)); \ + obstack_finish (__h); }) + +/* The local variable is named __o1 to avoid a name conflict + when obstack_blank is called. */ +# define obstack_finish(OBSTACK) \ +__extension__ \ +({ struct obstack *__o1 = (OBSTACK); \ + void *__value = (void *) __o1->object_base; \ + if (__o1->next_free == __value) \ + __o1->maybe_empty_object = 1; \ + __o1->next_free \ + = __PTR_ALIGN (__o1->object_base, __o1->next_free, \ + __o1->alignment_mask); \ + if (__o1->next_free - (char *)__o1->chunk \ + > __o1->chunk_limit - (char *)__o1->chunk) \ + __o1->next_free = __o1->chunk_limit; \ + __o1->object_base = __o1->next_free; \ + __value; }) + +# define obstack_free(OBSTACK, OBJ) \ +__extension__ \ +({ struct obstack *__o = (OBSTACK); \ + void *__obj = (OBJ); \ + if (__obj > (void *)__o->chunk && __obj < (void *)__o->chunk_limit) \ + __o->next_free = __o->object_base = (char *)__obj; \ + else (obstack_free) (__o, __obj); }) + +#else /* not __GNUC__ or not __STDC__ */ + +# define obstack_object_size(h) \ + (unsigned) ((h)->next_free - (h)->object_base) + +# define obstack_room(h) \ + (unsigned) ((h)->chunk_limit - (h)->next_free) + +# define obstack_empty_p(h) \ + ((h)->chunk->prev == 0 \ + && (h)->next_free == __PTR_ALIGN ((char *) (h)->chunk, \ + (h)->chunk->contents, \ + (h)->alignment_mask)) + +/* Note that the call to _obstack_newchunk is enclosed in (..., 0) + so that we can avoid having void expressions + in the arms of the conditional expression. + Casting the third operand to void was tried before, + but some compilers won't accept it. */ + +# define obstack_make_room(h,length) \ +( (h)->temp.tempint = (length), \ + (((h)->next_free + (h)->temp.tempint > (h)->chunk_limit) \ + ? (_obstack_newchunk ((h), (h)->temp.tempint), 0) : 0)) + +# define obstack_grow(h,where,length) \ +( (h)->temp.tempint = (length), \ + (((h)->next_free + (h)->temp.tempint > (h)->chunk_limit) \ + ? (_obstack_newchunk ((h), (h)->temp.tempint), 0) : 0), \ + memcpy ((h)->next_free, where, (h)->temp.tempint), \ + (h)->next_free += (h)->temp.tempint) + +# define obstack_grow0(h,where,length) \ +( (h)->temp.tempint = (length), \ + (((h)->next_free + (h)->temp.tempint + 1 > (h)->chunk_limit) \ + ? (_obstack_newchunk ((h), (h)->temp.tempint + 1), 0) : 0), \ + memcpy ((h)->next_free, where, (h)->temp.tempint), \ + (h)->next_free += (h)->temp.tempint, \ + *((h)->next_free)++ = 0) + +# define obstack_1grow(h,datum) \ +( (((h)->next_free + 1 > (h)->chunk_limit) \ + ? (_obstack_newchunk ((h), 1), 0) : 0), \ + obstack_1grow_fast (h, datum)) + +# define obstack_ptr_grow(h,datum) \ +( (((h)->next_free + sizeof (char *) > (h)->chunk_limit) \ + ? (_obstack_newchunk ((h), sizeof (char *)), 0) : 0), \ + obstack_ptr_grow_fast (h, datum)) + +# define obstack_int_grow(h,datum) \ +( (((h)->next_free + sizeof (int) > (h)->chunk_limit) \ + ? (_obstack_newchunk ((h), sizeof (int)), 0) : 0), \ + obstack_int_grow_fast (h, datum)) + +# define obstack_ptr_grow_fast(h,aptr) \ + (((const void **) ((h)->next_free += sizeof (void *)))[-1] = (aptr)) + +# define obstack_int_grow_fast(h,aint) \ + (((int *) ((h)->next_free += sizeof (int)))[-1] = (aint)) + +# define obstack_blank(h,length) \ +( (h)->temp.tempint = (length), \ + (((h)->chunk_limit - (h)->next_free < (h)->temp.tempint) \ + ? (_obstack_newchunk ((h), (h)->temp.tempint), 0) : 0), \ + obstack_blank_fast (h, (h)->temp.tempint)) + +# define obstack_alloc(h,length) \ + (obstack_blank ((h), (length)), obstack_finish ((h))) + +# define obstack_copy(h,where,length) \ + (obstack_grow ((h), (where), (length)), obstack_finish ((h))) + +# define obstack_copy0(h,where,length) \ + (obstack_grow0 ((h), (where), (length)), obstack_finish ((h))) + +# define obstack_finish(h) \ +( ((h)->next_free == (h)->object_base \ + ? (((h)->maybe_empty_object = 1), 0) \ + : 0), \ + (h)->temp.tempptr = (h)->object_base, \ + (h)->next_free \ + = __PTR_ALIGN ((h)->object_base, (h)->next_free, \ + (h)->alignment_mask), \ + (((h)->next_free - (char *) (h)->chunk \ + > (h)->chunk_limit - (char *) (h)->chunk) \ + ? ((h)->next_free = (h)->chunk_limit) : 0), \ + (h)->object_base = (h)->next_free, \ + (h)->temp.tempptr) + +# define obstack_free(h,obj) \ +( (h)->temp.tempint = (char *) (obj) - (char *) (h)->chunk, \ + ((((h)->temp.tempint > 0 \ + && (h)->temp.tempint < (h)->chunk_limit - (char *) (h)->chunk)) \ + ? (int) ((h)->next_free = (h)->object_base \ + = (h)->temp.tempint + (char *) (h)->chunk) \ + : (((obstack_free) ((h), (h)->temp.tempint + (char *) (h)->chunk), 0), 0))) + +#endif /* not __GNUC__ or not __STDC__ */ + +#ifdef __cplusplus +} /* C++ */ +#endif + +#endif /* obstack.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/paths.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/paths.h new file mode 100644 index 00000000..305937fc --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/paths.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)paths.h 8.1 (Berkeley) 6/2/93 + */ + +#ifndef _PATHS_H_ +#define _PATHS_H_ + +/* Default search path. */ +#define _PATH_DEFPATH "/usr/bin:/bin" +/* All standard utilities path. */ +#define _PATH_STDPATH \ + "/usr/bin:/bin:/usr/sbin:/sbin" + +#define _PATH_BSHELL "/bin/sh" +#define _PATH_CONSOLE "/dev/console" +#define _PATH_CSHELL "/bin/csh" +#define _PATH_DEVDB "/var/run/dev.db" +#define _PATH_DEVNULL "/dev/null" +#define _PATH_DRUM "/dev/drum" +#define _PATH_KLOG "/proc/kmsg" +#define _PATH_KMEM "/dev/kmem" +#define _PATH_LASTLOG "/var/log/lastlog" +#define _PATH_MAILDIR "/var/mail" +#define _PATH_MAN "/usr/share/man" +#define _PATH_MEM "/dev/mem" +#define _PATH_MNTTAB "/etc/fstab" +#define _PATH_MOUNTED "/etc/mtab" +#define _PATH_NOLOGIN "/etc/nologin" +#define _PATH_PRESERVE "/var/lib" +#define _PATH_RWHODIR "/var/spool/rwho" +#define _PATH_SENDMAIL "/usr/sbin/sendmail" +#define _PATH_SHADOW "/etc/shadow" +#define _PATH_SHELLS "/etc/shells" +#define _PATH_TTY "/dev/tty" +#define _PATH_UNIX "/boot/vmlinux" +#define _PATH_UTMP "/var/run/utmp" +#define _PATH_VI "/usr/bin/vi" +#define _PATH_WTMP "/var/log/wtmp" + +#ifdef _LIBC +#define _PATH_PASSWD "/etc/passwd" +#define _PATH_GROUP "/etc/group" +#endif + +/* Provide trailing slash, since mostly used for building pathnames. */ +#define _PATH_DEV "/dev/" +#define _PATH_TMP "/tmp/" +#define _PATH_VARDB "/var/db/" +#define _PATH_VARRUN "/var/run/" +#define _PATH_VARTMP "/var/tmp/" + +#endif /* !_PATHS_H_ */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/poll.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/poll.h new file mode 100644 index 00000000..06fb41ab --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/poll.h @@ -0,0 +1 @@ +#include diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/printf.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/printf.h new file mode 100644 index 00000000..685e31e1 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/printf.h @@ -0,0 +1,237 @@ +/* Copyright (C) 1991-1993,1995-1999,2000,2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* March 11, 2001 Manuel Novoa III + * + * Modified as appropriate for my new stdio lib. + */ + +#ifndef _PRINTF_H + +#define _PRINTF_H 1 +#include + +__BEGIN_DECLS + +#define __need_FILE +#include +#define __need_size_t +#define __need_wchar_t +#include + +/* WARNING -- This is definitely nonportable... but it seems to work + * with gcc, which is currently the only "supported" compiler. + * The library code uses bitmasks for space-efficiency (you can't + * set/test multiple bitfields in one operation). Unfortunatly, we + * need to support bitfields since that's what glibc made visible to users. + * So, we take + * advantage of how gcc lays out bitfields to create an appropriate + * mapping. Inside uclibc (i.e. if _LIBC is defined) we access the + * bitfields using bitmasks in a single flag variable. + * + * WARNING -- This may very well fail if built with -fpack-struct!!! + * + * TODO -- Add a validation test. + * TODO -- Add an option to build in a shim translation function if + * the bitfield<->bitmask mapping fails. + */ +#include + +struct printf_info { + int prec; /* Precision. */ + int width; /* Width. */ +#ifdef __UCLIBC_HAS_WCHAR__ + wchar_t spec; /* Format letter. */ +#else + int spec; +#endif + +#ifndef _LIBC + +#if __BYTE_ORDER == __LITTLE_ENDIAN + unsigned int space:1; /* Space flag. */ + unsigned int showsign:1; /* + flag. */ + unsigned int extra:1; /* For special use. */ + unsigned int left:1; /* - flag. */ + unsigned int alt:1; /* # flag. */ + unsigned int group:1; /* ' flag. */ + unsigned int i18n:1; /* I flag. */ + unsigned int wide:1; /* Nonzero for wide character streams. */ + unsigned int is_char:1; /* hh flag. */ + unsigned int is_short:1; /* h flag. */ + unsigned int is_long:1; /* l flag. */ + unsigned int is_long_double:1;/* L flag. */ + unsigned int __padding:20; /* non-gnu: match _flags width of 32 bits */ +#elif __BYTE_ORDER == __BIG_ENDIAN + unsigned int __padding:20; /* non-gnu: match _flags width of 32 bits */ + unsigned int is_long_double:1;/* L flag. */ + unsigned int is_long:1; /* l flag. */ + unsigned int is_short:1; /* h flag. */ + unsigned int is_char:1; /* hh flag. */ + unsigned int wide:1; /* Nonzero for wide character streams. */ + unsigned int i18n:1; /* I flag. */ + unsigned int group:1; /* ' flag. */ + unsigned int alt:1; /* # flag. */ + unsigned int left:1; /* - flag. */ + unsigned int extra:1; /* For special use. */ + unsigned int showsign:1; /* + flag. */ + unsigned int space:1; /* Space flag. */ +#else +#error unsupported byte order! +#endif + +#else /* _LIBC */ + + uint32_t _flags; /* non-gnu */ +#define __PRINT_INFO_FLAG_space (1<<0) +#define __PRINT_INFO_FLAG_showsign (1<<1) +#define __PRINT_INFO_FLAG_extra (1<<2) +#define __PRINT_INFO_FLAG_left (1<<3) +#define __PRINT_INFO_FLAG_alt (1<<4) +#define __PRINT_INFO_FLAG_group (1<<5) +#define __PRINT_INFO_FLAG_i18n (1<<6) +#define __PRINT_INFO_FLAG_wide (1<<7) + +#define __PRINT_INFO_FLAG_is_char (1<<8) +#define __PRINT_INFO_FLAG_is_short (1<<9) +#define __PRINT_INFO_FLAG_is_long (1<<10) +#define __PRINT_INFO_FLAG_is_long_double (1<<11) + +#define PRINT_INFO_FLAG_VAL(INFO_PTR,BITFIELD) \ + ((INFO_PTR)->_flags & __PRINT_INFO_FLAG_##BITFIELD) +#define PRINT_INFO_SET_FLAG(INFO_PTR,BITFIELD) \ + ((INFO_PTR)->_flags |= __PRINT_INFO_FLAG_##BITFIELD) +#define PRINT_INFO_CLR_FLAG(INFO_PTR,BITFIELD) \ + ((INFO_PTR)->_flags &= ~__PRINT_INFO_FLAG_##BITFIELD) +#define PRINT_INFO_SET_extra(INFO_PTR,VAL) \ + ((INFO_PTR)->_flags |= (((INFO_PTR)->_flags & ~1) | ((VAL) & 1))) + +#endif /* _LIBC */ + +#ifdef __UCLIBC_HAS_WCHAR__ + wchar_t pad; /* Padding character. */ +#else + int pad; +#endif +}; + + +/* Type of a printf specifier-handler function. + STREAM is the FILE on which to write output. + INFO gives information about the format specification. + ARGS is a vector of pointers to the argument data; + the number of pointers will be the number returned + by the associated arginfo function for the same INFO. + + The function should return the number of characters written, + or -1 for errors. */ + +#ifdef __UCLIBC_HAS_GLIBC_CUSTOM_PRINTF__ +typedef int (*printf_function) (FILE *__stream, + __const struct printf_info *__info, + __const void *__const *__args); + +/* Type of a printf specifier-arginfo function. + INFO gives information about the format specification. + N, ARGTYPES, and return value are as for parse_printf_format. */ + +typedef int printf_arginfo_function (__const struct printf_info *__info, + size_t __n, int *__argtypes); + + +/* Register FUNC to be called to format SPEC specifiers; ARGINFO must be + specified to determine how many arguments a SPEC conversion requires and + what their types are. */ + +extern int register_printf_function (int __spec, printf_function __func, + printf_arginfo_function __arginfo); +#endif + + +/* Parse FMT, and fill in N elements of ARGTYPES with the + types needed for the conversions FMT specifies. Returns + the number of arguments required by FMT. + + The ARGINFO function registered with a user-defined format is passed a + `struct printf_info' describing the format spec being parsed. A width + or precision of INT_MIN means a `*' was used to indicate that the + width/precision will come from an arg. The function should fill in the + array it is passed with the types of the arguments it wants, and return + the number of arguments it wants. */ + +extern size_t parse_printf_format (__const char *__restrict __fmt, size_t __n, + int *__restrict __argtypes) __THROW; + + +/* Codes returned by `parse_printf_format' for basic types. + + These values cover all the standard format specifications. + Users can add new values after PA_LAST for their own types. */ + +/* WARNING -- The above is not entirely true, even for glibc. + * As far as the library code is concerned, such args are treated + * as 'your type' pointers if qualified by PA_FLAG_PTR. If they + * aren't qualified as pointers, I _think_ glibc just ignores them + * and carries on. I think it should be treated as an error. */ + +enum { /* C type: */ + PA_INT, /* int */ + PA_CHAR, /* int, cast to char */ + PA_WCHAR, /* wide char */ + PA_STRING, /* const char *, a '\0'-terminated string */ + PA_WSTRING, /* const wchar_t *, wide character string */ + PA_POINTER, /* void * */ + PA_FLOAT, /* float */ + PA_DOUBLE, /* double */ + __PA_NOARG, /* non-glibc -- signals non-arg width or prec */ + PA_LAST +}; + +/* Flag bits that can be set in a type returned by `parse_printf_format'. */ +/* WARNING -- These differ in value from what glibc uses. */ +#define PA_FLAG_MASK (0xff00) +#define __PA_FLAG_CHAR (0x0100) /* non-gnu -- to deal with hh */ +#define PA_FLAG_SHORT (0x0200) +#define PA_FLAG_LONG (0x0400) +#define PA_FLAG_LONG_LONG (0x0800) +#define PA_FLAG_LONG_DOUBLE PA_FLAG_LONG_LONG +#define PA_FLAG_PTR (0x1000) /* TODO -- make dynamic??? */ + +#define __PA_INTMASK (0x0f00) /* non-gnu -- all int flags */ + +#if 0 +/* Function which can be registered as `printf'-handlers. */ + +/* Print floating point value using using abbreviations for the orders + of magnitude used for numbers ('k' for kilo, 'm' for mega etc). If + the format specifier is a uppercase character powers of 1000 are + used. Otherwise powers of 1024. */ +extern int printf_size (FILE *__restrict __fp, + __const struct printf_info *__info, + __const void *__const *__restrict __args) __THROW; + +/* This is the appropriate argument information function for `printf_size'. */ +extern int printf_size_info (__const struct printf_info *__restrict + __info, size_t __n, int *__restrict __argtypes) + __THROW; + +#endif + +__END_DECLS + +#endif /* printf.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/protocols/routed.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/protocols/routed.h new file mode 100644 index 00000000..befd8654 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/protocols/routed.h @@ -0,0 +1,101 @@ +/*- + * Copyright (c) 1983, 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)routed.h 8.1 (Berkeley) 6/2/93 + */ + +#ifndef _PROTOCOLS_ROUTED_H +#define _PROTOCOLS_ROUTED_H 1 + +#include +/* + * Routing Information Protocol + * + * Derived from Xerox NS Routing Information Protocol + * by changing 32-bit net numbers to sockaddr's and + * padding stuff to 32-bit boundaries. + */ +#define RIPVERSION 1 + +struct netinfo { + struct sockaddr rip_dst; /* destination net/host */ + int rip_metric; /* cost of route */ +}; + +struct rip { + u_char rip_cmd; /* request/response */ + u_char rip_vers; /* protocol version # */ + u_char rip_res1[2]; /* pad to 32-bit boundary */ + union { + struct netinfo ru_nets[1]; /* variable length... */ + char ru_tracefile[1]; /* ditto ... */ + } ripun; +#define rip_nets ripun.ru_nets +#define rip_tracefile ripun.ru_tracefile +}; + +/* + * Packet types. + */ +#define RIPCMD_REQUEST 1 /* want info */ +#define RIPCMD_RESPONSE 2 /* responding to request */ +#define RIPCMD_TRACEON 3 /* turn tracing on */ +#define RIPCMD_TRACEOFF 4 /* turn it off */ + +#define RIPCMD_MAX 5 +#ifdef RIPCMDS +char *ripcmds[RIPCMD_MAX] = + { "#0", "REQUEST", "RESPONSE", "TRACEON", "TRACEOFF" }; +#endif + +#define HOPCNT_INFINITY 16 /* per Xerox NS */ +#define MAXPACKETSIZE 512 /* max broadcast size */ + +/* + * Timer values used in managing the routing table. + * Complete tables are broadcast every SUPPLY_INTERVAL seconds. + * If changes occur between updates, dynamic updates containing only changes + * may be sent. When these are sent, a timer is set for a random value + * between MIN_WAITTIME and MAX_WAITTIME, and no additional dynamic updates + * are sent until the timer expires. + * + * Every update of a routing entry forces an entry's timer to be reset. + * After EXPIRE_TIME without updates, the entry is marked invalid, + * but held onto until GARBAGE_TIME so that others may + * see it "be deleted". + */ +#define TIMER_RATE 30 /* alarm clocks every 30 seconds */ + +#define SUPPLY_INTERVAL 30 /* time to supply tables */ +#define MIN_WAITTIME 2 /* min. interval to broadcast changes */ +#define MAX_WAITTIME 5 /* max. time to delay changes */ + +#define EXPIRE_TIME 180 /* time to mark entry invalid */ +#define GARBAGE_TIME 240 /* time to garbage collect */ + +#endif /* protocols/routed.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/protocols/rwhod.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/protocols/rwhod.h new file mode 100644 index 00000000..446d6f97 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/protocols/rwhod.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)rwhod.h 8.1 (Berkeley) 6/2/93 + */ + +#ifndef _PROTOCOLS_RWHOD_H +#define _PROTOCOLS_RWHOD_H 1 + +#include + +/* + * rwho protocol packet format. + */ +struct outmp { + char out_line[8]; /* tty name */ + char out_name[8]; /* user id */ + int32_t out_time; /* time on */ +}; + +struct whod { + char wd_vers; /* protocol version # */ + char wd_type; /* packet type, see below */ + char wd_pad[2]; + int wd_sendtime; /* time stamp by sender */ + int wd_recvtime; /* time stamp applied by receiver */ + char wd_hostname[32]; /* hosts's name */ + int wd_loadav[3]; /* load average as in uptime */ + int wd_boottime; /* time system booted */ + struct whoent { + struct outmp we_utmp; /* active tty info */ + int we_idle; /* tty idle time */ + } wd_we[1024 / sizeof (struct whoent)]; +}; + +#define WHODVERSION 1 +#define WHODTYPE_STATUS 1 /* host status */ + +/* We used to define _PATH_RWHODIR here but it's now in . */ +#include + +#endif /* protocols/rwhod.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/protocols/talkd.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/protocols/talkd.h new file mode 100644 index 00000000..a8f33b1b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/protocols/talkd.h @@ -0,0 +1,113 @@ +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)talkd.h 8.1 (Berkeley) 6/2/93 + */ + +#ifndef _PROTOCOLS_TALKD_H +#define _PROTOCOLS_TALKD_H 1 + +/* + * This describes the protocol used by the talk server and clients. + * + * The talk server acts a repository of invitations, responding to + * requests by clients wishing to rendezvous for the purpose of + * holding a conversation. In normal operation, a client, the caller, + * initiates a rendezvous by sending a CTL_MSG to the server of + * type LOOK_UP. This causes the server to search its invitation + * tables to check if an invitation currently exists for the caller + * (to speak to the callee specified in the message). If the lookup + * fails, the caller then sends an ANNOUNCE message causing the server + * to broadcast an announcement on the callee's login ports requesting + * contact. When the callee responds, the local server uses the + * recorded invitation to respond with the appropriate rendezvous + * address and the caller and callee client programs establish a + * stream connection through which the conversation takes place. + */ + +#include +#include + +/* + * Client->server request message format. + */ +typedef struct { + u_char vers; /* protocol version */ + u_char type; /* request type, see below */ + u_char answer; /* not used */ + u_char pad; + u_int32_t id_num; /* message id */ + struct osockaddr addr; /* old (4.3) style */ + struct osockaddr ctl_addr; /* old (4.3) style */ + int32_t pid; /* caller's process id */ +#define NAME_SIZE 12 + char l_name[NAME_SIZE];/* caller's name */ + char r_name[NAME_SIZE];/* callee's name */ +#define TTY_SIZE 16 + char r_tty[TTY_SIZE];/* callee's tty name */ +} CTL_MSG; + +/* + * Server->client response message format. + */ +typedef struct { + u_char vers; /* protocol version */ + u_char type; /* type of request message, see below */ + u_char answer; /* response to request message, see below */ + u_char pad; + u_int32_t id_num; /* message id */ + struct osockaddr addr; /* address for establishing conversation */ +} CTL_RESPONSE; + +#define TALK_VERSION 1 /* protocol version */ + +/* message type values */ +#define LEAVE_INVITE 0 /* leave invitation with server */ +#define LOOK_UP 1 /* check for invitation by callee */ +#define DELETE 2 /* delete invitation by caller */ +#define ANNOUNCE 3 /* announce invitation by caller */ + +/* answer values */ +#define SUCCESS 0 /* operation completed properly */ +#define NOT_HERE 1 /* callee not logged in */ +#define FAILED 2 /* operation failed for unexplained reason */ +#define MACHINE_UNKNOWN 3 /* caller's machine name unknown */ +#define PERMISSION_DENIED 4 /* callee's tty doesn't permit announce */ +#define UNKNOWN_REQUEST 5 /* request has invalid type value */ +#define BADVERSION 6 /* request has invalid protocol version */ +#define BADADDR 7 /* request has invalid addr value */ +#define BADCTLADDR 8 /* request has invalid ctl_addr value */ + +/* + * Operational parameters. + */ +#define MAX_LIFE 60 /* max time daemon saves invitations */ +/* RING_WAIT should be 10's of seconds less than MAX_LIFE */ +#define RING_WAIT 30 /* time to wait before resending invitation */ + +#endif /* protocols/talkd.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/protocols/timed.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/protocols/timed.h new file mode 100644 index 00000000..8101e992 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/protocols/timed.h @@ -0,0 +1,99 @@ +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)timed.h 8.1 (Berkeley) 6/2/93 + */ + +#ifndef _PROTOCOLS_TIMED_H +#define _PROTOCOLS_TIMED_H 1 + +#ifdef __UCLIBC_HAS_RPC__ +#include +#endif + +/* + * Time Synchronization Protocol + */ + +#define TSPVERSION 1 +#define ANYADDR NULL + +struct tsp { + u_char tsp_type; + u_char tsp_vers; + u_short tsp_seq; + union { + struct timeval tspu_time; + char tspu_hopcnt; + } tsp_u; + char tsp_name[MAXHOSTNAMELEN]; +}; + +#define tsp_time tsp_u.tspu_time +#define tsp_hopcnt tsp_u.tspu_hopcnt + +/* + * Command types. + */ +#define TSP_ANY 0 /* match any types */ +#define TSP_ADJTIME 1 /* send adjtime */ +#define TSP_ACK 2 /* generic acknowledgement */ +#define TSP_MASTERREQ 3 /* ask for master's name */ +#define TSP_MASTERACK 4 /* acknowledge master request */ +#define TSP_SETTIME 5 /* send network time */ +#define TSP_MASTERUP 6 /* inform slaves that master is up */ +#define TSP_SLAVEUP 7 /* slave is up but not polled */ +#define TSP_ELECTION 8 /* advance candidature for master */ +#define TSP_ACCEPT 9 /* support candidature of master */ +#define TSP_REFUSE 10 /* reject candidature of master */ +#define TSP_CONFLICT 11 /* two or more masters present */ +#define TSP_RESOLVE 12 /* masters' conflict resolution */ +#define TSP_QUIT 13 /* reject candidature if master is up */ +#define TSP_DATE 14 /* reset the time (date command) */ +#define TSP_DATEREQ 15 /* remote request to reset the time */ +#define TSP_DATEACK 16 /* acknowledge time setting */ +#define TSP_TRACEON 17 /* turn tracing on */ +#define TSP_TRACEOFF 18 /* turn tracing off */ +#define TSP_MSITE 19 /* find out master's site */ +#define TSP_MSITEREQ 20 /* remote master's site request */ +#define TSP_TEST 21 /* for testing election algo */ +#define TSP_SETDATE 22 /* New from date command */ +#define TSP_SETDATEREQ 23 /* New remote for above */ +#define TSP_LOOP 24 /* loop detection packet */ + +#define TSPTYPENUMBER 25 + +#ifdef TSPTYPES +char *tsptype[TSPTYPENUMBER] = + { "ANY", "ADJTIME", "ACK", "MASTERREQ", "MASTERACK", "SETTIME", "MASTERUP", + "SLAVEUP", "ELECTION", "ACCEPT", "REFUSE", "CONFLICT", "RESOLVE", "QUIT", + "DATE", "DATEREQ", "DATEACK", "TRACEON", "TRACEOFF", "MSITE", "MSITEREQ", + "TEST", "SETDATE", "SETDATEREQ", "LOOP" }; +#endif + +#endif /* protocols/timed.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/pty.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/pty.h new file mode 100644 index 00000000..2d4b5e27 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/pty.h @@ -0,0 +1,44 @@ +/* Functions for pseudo TTY handling. + Copyright (C) 1996, 1997, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _PTY_H +#define _PTY_H 1 + +#include + +#include +#include + + +__BEGIN_DECLS + +/* Create pseudo tty master slave pair with NAME and set terminal + attributes according to TERMP and WINP and return handles for both + ends in AMASTER and ASLAVE. */ +extern int openpty (int *__amaster, int *__aslave, char *__name, + struct termios *__termp, struct winsize *__winp) __THROW; + +/* Create child process and establish the slave pseudo terminal as the + child's controlling terminal. */ +extern int forkpty (int *__amaster, char *__name, + struct termios *__termp, struct winsize *__winp) __THROW; + +__END_DECLS + +#endif /* pty.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/pwd.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/pwd.h new file mode 100644 index 00000000..4623bfdd --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/pwd.h @@ -0,0 +1,190 @@ +/* Copyright (C) 1991,1992,1995-2001,2003,2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * POSIX Standard: 9.2.2 User Database Access + */ + +#ifndef _PWD_H +#define _PWD_H 1 + +#include + +__BEGIN_DECLS + +#include + +#define __need_size_t +#include + +#if defined __USE_XOPEN || defined __USE_XOPEN2K +/* The Single Unix specification says that some more types are + available here. */ +# ifndef __gid_t_defined +typedef __gid_t gid_t; +# define __gid_t_defined +# endif + +# ifndef __uid_t_defined +typedef __uid_t uid_t; +# define __uid_t_defined +# endif +#endif + +/* The passwd structure. */ +struct passwd +{ + char *pw_name; /* Username. */ + char *pw_passwd; /* Password. */ + __uid_t pw_uid; /* User ID. */ + __gid_t pw_gid; /* Group ID. */ + char *pw_gecos; /* Real name. */ + char *pw_dir; /* Home directory. */ + char *pw_shell; /* Shell program. */ +}; + + +#if defined __USE_SVID || defined __USE_GNU +# define __need_FILE +# include +#endif + + +#if defined __USE_SVID || defined __USE_MISC || defined __USE_XOPEN_EXTENDED +/* Rewind the password-file stream. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern void setpwent (void); + +/* Close the password-file stream. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern void endpwent (void); + +/* Read an entry from the password-file stream, opening it if necessary. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern struct passwd *getpwent (void); +#endif + +#ifdef __USE_SVID +/* Read an entry from STREAM. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern struct passwd *fgetpwent (FILE *__stream); + +/* Write the given entry onto the given stream. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern int putpwent (__const struct passwd *__restrict __p, + FILE *__restrict __f); +#endif + +/* Search for an entry with a matching user ID. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern struct passwd *getpwuid (__uid_t __uid); + +/* Search for an entry with a matching username. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern struct passwd *getpwnam (__const char *__name); + +#if defined __USE_POSIX || defined __USE_MISC + +# ifdef __USE_MISC +/* Reasonable value for the buffer sized used in the reentrant + functions below. But better use `sysconf'. */ +# define NSS_BUFLEN_PASSWD 1024 +# endif + +/* Reentrant versions of some of the functions above. + + PLEASE NOTE: the `getpwent_r' function is not (yet) standardized. + The interface may change in later versions of this library. But + the interface is designed following the principals used for the + other reentrant functions so the chances are good this is what the + POSIX people would choose. */ + +# if defined __USE_SVID || defined __USE_MISC +/* This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern int getpwent_r (struct passwd *__restrict __resultbuf, + char *__restrict __buffer, size_t __buflen, + struct passwd **__restrict __result); +libc_hidden_proto(getpwent_r) +# endif + +extern int getpwuid_r (__uid_t __uid, + struct passwd *__restrict __resultbuf, + char *__restrict __buffer, size_t __buflen, + struct passwd **__restrict __result); +libc_hidden_proto(getpwuid_r) + +extern int getpwnam_r (__const char *__restrict __name, + struct passwd *__restrict __resultbuf, + char *__restrict __buffer, size_t __buflen, + struct passwd **__restrict __result); +libc_hidden_proto(getpwnam_r) + + +# ifdef __USE_SVID +/* Read an entry from STREAM. This function is not standardized and + probably never will. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern int fgetpwent_r (FILE *__restrict __stream, + struct passwd *__restrict __resultbuf, + char *__restrict __buffer, size_t __buflen, + struct passwd **__restrict __result); +libc_hidden_proto(fgetpwent_r) +# endif + +#endif /* POSIX or reentrant */ + +#ifdef __USE_GNU +/* Re-construct the password-file line for the given uid + in the given buffer. This knows the format that the caller + will expect, but this need not be the format of the password file. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern int getpw (__uid_t __uid, char *__buffer); +#endif + +__END_DECLS + +#endif /* pwd.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/regex.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/regex.h new file mode 100644 index 00000000..1d4ddd27 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/regex.h @@ -0,0 +1,567 @@ +/* Definitions for data structures and routines for the regular + expression library. + Copyright (C) 1985,1989-93,1995-98,2000,2001,2002,2003,2005 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _REGEX_H +#define _REGEX_H 1 + +#include + +#include + +__BEGIN_DECLS + +/* POSIX says that must be included (by the caller) before + . */ + +#if !defined _POSIX_C_SOURCE && !defined _POSIX_SOURCE && defined VMS +/* VMS doesn't have `size_t' in , even though POSIX says it + should be there. */ +# include +#endif + +/* The following two types have to be signed and unsigned integer type + wide enough to hold a value of a pointer. For most ANSI compilers + ptrdiff_t and size_t should be likely OK. Still size of these two + types is 2 for Microsoft C. Ugh... */ +typedef long int s_reg_t; +typedef unsigned long int active_reg_t; + +/* The following bits are used to determine the regexp syntax we + recognize. The set/not-set meanings are chosen so that Emacs syntax + remains the value 0. The bits are given in alphabetical order, and + the definitions shifted by one from the previous bit; thus, when we + add or remove a bit, only one other definition need change. */ +typedef unsigned long int reg_syntax_t; + +/* If this bit is not set, then \ inside a bracket expression is literal. + If set, then such a \ quotes the following character. */ +#define RE_BACKSLASH_ESCAPE_IN_LISTS ((unsigned long int) 1) + +/* If this bit is not set, then + and ? are operators, and \+ and \? are + literals. + If set, then \+ and \? are operators and + and ? are literals. */ +#define RE_BK_PLUS_QM (RE_BACKSLASH_ESCAPE_IN_LISTS << 1) + +/* If this bit is set, then character classes are supported. They are: + [:alpha:], [:upper:], [:lower:], [:digit:], [:alnum:], [:xdigit:], + [:space:], [:print:], [:punct:], [:graph:], and [:cntrl:]. + If not set, then character classes are not supported. */ +#define RE_CHAR_CLASSES (RE_BK_PLUS_QM << 1) + +/* If this bit is set, then ^ and $ are always anchors (outside bracket + expressions, of course). + If this bit is not set, then it depends: + ^ is an anchor if it is at the beginning of a regular + expression or after an open-group or an alternation operator; + $ is an anchor if it is at the end of a regular expression, or + before a close-group or an alternation operator. + + This bit could be (re)combined with RE_CONTEXT_INDEP_OPS, because + POSIX draft 11.2 says that * etc. in leading positions is undefined. + We already implemented a previous draft which made those constructs + invalid, though, so we haven't changed the code back. */ +#define RE_CONTEXT_INDEP_ANCHORS (RE_CHAR_CLASSES << 1) + +/* If this bit is set, then special characters are always special + regardless of where they are in the pattern. + If this bit is not set, then special characters are special only in + some contexts; otherwise they are ordinary. Specifically, + * + ? and intervals are only special when not after the beginning, + open-group, or alternation operator. */ +#define RE_CONTEXT_INDEP_OPS (RE_CONTEXT_INDEP_ANCHORS << 1) + +/* If this bit is set, then *, +, ?, and { cannot be first in an re or + immediately after an alternation or begin-group operator. */ +#define RE_CONTEXT_INVALID_OPS (RE_CONTEXT_INDEP_OPS << 1) + +/* If this bit is set, then . matches newline. + If not set, then it doesn't. */ +#define RE_DOT_NEWLINE (RE_CONTEXT_INVALID_OPS << 1) + +/* If this bit is set, then . doesn't match NUL. + If not set, then it does. */ +#define RE_DOT_NOT_NULL (RE_DOT_NEWLINE << 1) + +/* If this bit is set, nonmatching lists [^...] do not match newline. + If not set, they do. */ +#define RE_HAT_LISTS_NOT_NEWLINE (RE_DOT_NOT_NULL << 1) + +/* If this bit is set, either \{...\} or {...} defines an + interval, depending on RE_NO_BK_BRACES. + If not set, \{, \}, {, and } are literals. */ +#define RE_INTERVALS (RE_HAT_LISTS_NOT_NEWLINE << 1) + +/* If this bit is set, +, ? and | aren't recognized as operators. + If not set, they are. */ +#define RE_LIMITED_OPS (RE_INTERVALS << 1) + +/* If this bit is set, newline is an alternation operator. + If not set, newline is literal. */ +#define RE_NEWLINE_ALT (RE_LIMITED_OPS << 1) + +/* If this bit is set, then `{...}' defines an interval, and \{ and \} + are literals. + If not set, then `\{...\}' defines an interval. */ +#define RE_NO_BK_BRACES (RE_NEWLINE_ALT << 1) + +/* If this bit is set, (...) defines a group, and \( and \) are literals. + If not set, \(...\) defines a group, and ( and ) are literals. */ +#define RE_NO_BK_PARENS (RE_NO_BK_BRACES << 1) + +/* If this bit is set, then \ matches . + If not set, then \ is a back-reference. */ +#define RE_NO_BK_REFS (RE_NO_BK_PARENS << 1) + +/* If this bit is set, then | is an alternation operator, and \| is literal. + If not set, then \| is an alternation operator, and | is literal. */ +#define RE_NO_BK_VBAR (RE_NO_BK_REFS << 1) + +/* If this bit is set, then an ending range point collating higher + than the starting range point, as in [z-a], is invalid. + If not set, then when ending range point collates higher than the + starting range point, the range is ignored. */ +#define RE_NO_EMPTY_RANGES (RE_NO_BK_VBAR << 1) + +/* If this bit is set, then an unmatched ) is ordinary. + If not set, then an unmatched ) is invalid. */ +#define RE_UNMATCHED_RIGHT_PAREN_ORD (RE_NO_EMPTY_RANGES << 1) + +/* If this bit is set, succeed as soon as we match the whole pattern, + without further backtracking. */ +#define RE_NO_POSIX_BACKTRACKING (RE_UNMATCHED_RIGHT_PAREN_ORD << 1) + +/* If this bit is set, do not process the GNU regex operators. + If not set, then the GNU regex operators are recognized. */ +#define RE_NO_GNU_OPS (RE_NO_POSIX_BACKTRACKING << 1) + +/* If this bit is set, turn on internal regex debugging. + If not set, and debugging was on, turn it off. + This only works if regex.c is compiled -DDEBUG. + We define this bit always, so that all that's needed to turn on + debugging is to recompile regex.c; the calling code can always have + this bit set, and it won't affect anything in the normal case. */ +#define RE_DEBUG (RE_NO_GNU_OPS << 1) + +/* If this bit is set, a syntactically invalid interval is treated as + a string of ordinary characters. For example, the ERE 'a{1' is + treated as 'a\{1'. */ +#define RE_INVALID_INTERVAL_ORD (RE_DEBUG << 1) + +/* If this bit is set, then ignore case when matching. + If not set, then case is significant. */ +#define RE_ICASE (RE_INVALID_INTERVAL_ORD << 1) + +/* This bit is used internally like RE_CONTEXT_INDEP_ANCHORS but only + for ^, because it is difficult to scan the regex backwards to find + whether ^ should be special. */ +#define RE_CARET_ANCHORS_HERE (RE_ICASE << 1) + +/* If this bit is set, then \{ cannot be first in an bre or + immediately after an alternation or begin-group operator. */ +#define RE_CONTEXT_INVALID_DUP (RE_CARET_ANCHORS_HERE << 1) + +/* If this bit is set, then no_sub will be set to 1 during + re_compile_pattern. */ +#define RE_NO_SUB (RE_CONTEXT_INVALID_DUP << 1) + +/* This global variable defines the particular regexp syntax to use (for + some interfaces). When a regexp is compiled, the syntax used is + stored in the pattern buffer, so changing this does not affect + already-compiled regexps. */ +extern reg_syntax_t re_syntax_options; + +/* Define combinations of the above bits for the standard possibilities. + (The [[[ comments delimit what gets put into the Texinfo file, so + don't delete them!) */ +/* [[[begin syntaxes]]] */ +#define RE_SYNTAX_EMACS 0 + +#define RE_SYNTAX_AWK \ + (RE_BACKSLASH_ESCAPE_IN_LISTS | RE_DOT_NOT_NULL \ + | RE_NO_BK_PARENS | RE_NO_BK_REFS \ + | RE_NO_BK_VBAR | RE_NO_EMPTY_RANGES \ + | RE_DOT_NEWLINE | RE_CONTEXT_INDEP_ANCHORS \ + | RE_UNMATCHED_RIGHT_PAREN_ORD | RE_NO_GNU_OPS) + +#define RE_SYNTAX_GNU_AWK \ + ((RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS | RE_DEBUG) \ + & ~(RE_DOT_NOT_NULL | RE_INTERVALS | RE_CONTEXT_INDEP_OPS \ + | RE_CONTEXT_INVALID_OPS )) + +#define RE_SYNTAX_POSIX_AWK \ + (RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS \ + | RE_INTERVALS | RE_NO_GNU_OPS) + +#define RE_SYNTAX_GREP \ + (RE_BK_PLUS_QM | RE_CHAR_CLASSES \ + | RE_HAT_LISTS_NOT_NEWLINE | RE_INTERVALS \ + | RE_NEWLINE_ALT) + +#define RE_SYNTAX_EGREP \ + (RE_CHAR_CLASSES | RE_CONTEXT_INDEP_ANCHORS \ + | RE_CONTEXT_INDEP_OPS | RE_HAT_LISTS_NOT_NEWLINE \ + | RE_NEWLINE_ALT | RE_NO_BK_PARENS \ + | RE_NO_BK_VBAR) + +#define RE_SYNTAX_POSIX_EGREP \ + (RE_SYNTAX_EGREP | RE_INTERVALS | RE_NO_BK_BRACES \ + | RE_INVALID_INTERVAL_ORD) + +/* P1003.2/D11.2, section 4.20.7.1, lines 5078ff. */ +#define RE_SYNTAX_ED RE_SYNTAX_POSIX_BASIC + +#define RE_SYNTAX_SED RE_SYNTAX_POSIX_BASIC + +/* Syntax bits common to both basic and extended POSIX regex syntax. */ +#define _RE_SYNTAX_POSIX_COMMON \ + (RE_CHAR_CLASSES | RE_DOT_NEWLINE | RE_DOT_NOT_NULL \ + | RE_INTERVALS | RE_NO_EMPTY_RANGES) + +#define RE_SYNTAX_POSIX_BASIC \ + (_RE_SYNTAX_POSIX_COMMON | RE_BK_PLUS_QM | RE_CONTEXT_INVALID_DUP) + +/* Differs from ..._POSIX_BASIC only in that RE_BK_PLUS_QM becomes + RE_LIMITED_OPS, i.e., \? \+ \| are not recognized. Actually, this + isn't minimal, since other operators, such as \`, aren't disabled. */ +#define RE_SYNTAX_POSIX_MINIMAL_BASIC \ + (_RE_SYNTAX_POSIX_COMMON | RE_LIMITED_OPS) + +#define RE_SYNTAX_POSIX_EXTENDED \ + (_RE_SYNTAX_POSIX_COMMON | RE_CONTEXT_INDEP_ANCHORS \ + | RE_CONTEXT_INDEP_OPS | RE_NO_BK_BRACES \ + | RE_NO_BK_PARENS | RE_NO_BK_VBAR \ + | RE_CONTEXT_INVALID_OPS | RE_UNMATCHED_RIGHT_PAREN_ORD) + +/* Differs from ..._POSIX_EXTENDED in that RE_CONTEXT_INDEP_OPS is + removed and RE_NO_BK_REFS is added. */ +#define RE_SYNTAX_POSIX_MINIMAL_EXTENDED \ + (_RE_SYNTAX_POSIX_COMMON | RE_CONTEXT_INDEP_ANCHORS \ + | RE_CONTEXT_INVALID_OPS | RE_NO_BK_BRACES \ + | RE_NO_BK_PARENS | RE_NO_BK_REFS \ + | RE_NO_BK_VBAR | RE_UNMATCHED_RIGHT_PAREN_ORD) +/* [[[end syntaxes]]] */ + +/* Maximum number of duplicates an interval can allow. Some systems + (erroneously) define this in other header files, but we want our + value, so remove any previous define. */ +#ifdef RE_DUP_MAX +# undef RE_DUP_MAX +#endif +/* If sizeof(int) == 2, then ((1 << 15) - 1) overflows. */ +#define RE_DUP_MAX (0x7fff) + + +/* POSIX `cflags' bits (i.e., information for `regcomp'). */ + +/* If this bit is set, then use extended regular expression syntax. + If not set, then use basic regular expression syntax. */ +#define REG_EXTENDED 1 + +/* If this bit is set, then ignore case when matching. + If not set, then case is significant. */ +#define REG_ICASE (REG_EXTENDED << 1) + +/* If this bit is set, then anchors do not match at newline + characters in the string. + If not set, then anchors do match at newlines. */ +#define REG_NEWLINE (REG_ICASE << 1) + +/* If this bit is set, then report only success or fail in regexec. + If not set, then returns differ between not matching and errors. */ +#define REG_NOSUB (REG_NEWLINE << 1) + + +/* POSIX `eflags' bits (i.e., information for regexec). */ + +/* If this bit is set, then the beginning-of-line operator doesn't match + the beginning of the string (presumably because it's not the + beginning of a line). + If not set, then the beginning-of-line operator does match the + beginning of the string. */ +#define REG_NOTBOL 1 + +/* Like REG_NOTBOL, except for the end-of-line. */ +#define REG_NOTEOL (1 << 1) + +/* Use PMATCH[0] to delimit the start and end of the search in the + buffer. */ +#define REG_STARTEND (1 << 2) + + +/* If any error codes are removed, changed, or added, update the + `re_error_msg' table in regex.c. */ +typedef enum +{ +#ifdef _XOPEN_SOURCE + REG_ENOSYS = -1, /* This will never happen for this implementation. */ +#endif + + REG_NOERROR = 0, /* Success. */ + REG_NOMATCH, /* Didn't find a match (for regexec). */ + + /* POSIX regcomp return error codes. (In the order listed in the + standard.) */ + REG_BADPAT, /* Invalid pattern. */ + REG_ECOLLATE, /* Invalid collating element. */ + REG_ECTYPE, /* Invalid character class name. */ + REG_EESCAPE, /* Trailing backslash. */ + REG_ESUBREG, /* Invalid back reference. */ + REG_EBRACK, /* Unmatched left bracket. */ + REG_EPAREN, /* Parenthesis imbalance. */ + REG_EBRACE, /* Unmatched \{. */ + REG_BADBR, /* Invalid contents of \{\}. */ + REG_ERANGE, /* Invalid range end. */ + REG_ESPACE, /* Ran out of memory. */ + REG_BADRPT, /* No preceding re for repetition op. */ + + /* Error codes we've added. */ + REG_EEND, /* Premature end. */ + REG_ESIZE, /* Compiled pattern bigger than 2^16 bytes. */ + REG_ERPAREN /* Unmatched ) or \); not returned from regcomp. */ +} reg_errcode_t; + +/* This data structure represents a compiled pattern. Before calling + the pattern compiler, the fields `buffer', `allocated', `fastmap', + `translate', and `no_sub' can be set. After the pattern has been + compiled, the `re_nsub' field is available. All other fields are + private to the regex routines. */ + +#ifndef RE_TRANSLATE_TYPE +# define RE_TRANSLATE_TYPE unsigned char * +#endif + +struct re_pattern_buffer +{ + /* Space that holds the compiled pattern. It is declared as + `unsigned char *' because its elements are sometimes used as + array indexes. */ + unsigned char *buffer; + + /* Number of bytes to which `buffer' points. */ + unsigned long int allocated; + + /* Number of bytes actually used in `buffer'. */ + unsigned long int used; + + /* Syntax setting with which the pattern was compiled. */ + reg_syntax_t syntax; + + /* Pointer to a fastmap, if any, otherwise zero. re_search uses the + fastmap, if there is one, to skip over impossible starting points + for matches. */ + char *fastmap; + + /* Either a translate table to apply to all characters before + comparing them, or zero for no translation. The translation is + applied to a pattern when it is compiled and to a string when it + is matched. */ + RE_TRANSLATE_TYPE translate; + + /* Number of subexpressions found by the compiler. */ + size_t re_nsub; + + /* Zero if this pattern cannot match the empty string, one else. + Well, in truth it's used only in `re_search_2', to see whether or + not we should use the fastmap, so we don't set this absolutely + perfectly; see `re_compile_fastmap' (the `duplicate' case). */ + unsigned can_be_null : 1; + + /* If REGS_UNALLOCATED, allocate space in the `regs' structure + for `max (RE_NREGS, re_nsub + 1)' groups. + If REGS_REALLOCATE, reallocate space if necessary. + If REGS_FIXED, use what's there. */ +#define REGS_UNALLOCATED 0 +#define REGS_REALLOCATE 1 +#define REGS_FIXED 2 + unsigned regs_allocated : 2; + + /* Set to zero when `regex_compile' compiles a pattern; set to one + by `re_compile_fastmap' if it updates the fastmap. */ + unsigned fastmap_accurate : 1; + + /* If set, `re_match_2' does not return information about + subexpressions. */ + unsigned no_sub : 1; + + /* If set, a beginning-of-line anchor doesn't match at the beginning + of the string. */ + unsigned not_bol : 1; + + /* Similarly for an end-of-line anchor. */ + unsigned not_eol : 1; + + /* If true, an anchor at a newline matches. */ + unsigned newline_anchor : 1; +}; + +typedef struct re_pattern_buffer regex_t; + +/* Type for byte offsets within the string. POSIX mandates this. */ +typedef int regoff_t; + + +/* This is the structure we store register match data in. See + regex.texinfo for a full description of what registers match. */ +struct re_registers +{ + unsigned num_regs; + regoff_t *start; + regoff_t *end; +}; + + +/* If `regs_allocated' is REGS_UNALLOCATED in the pattern buffer, + `re_match_2' returns information about at least this many registers + the first time a `regs' structure is passed. */ +#ifndef RE_NREGS +# define RE_NREGS 30 +#endif + + +/* POSIX specification for registers. Aside from the different names than + `re_registers', POSIX uses an array of structures, instead of a + structure of arrays. */ +typedef struct +{ + regoff_t rm_so; /* Byte offset from string's start to substring's start. */ + regoff_t rm_eo; /* Byte offset from string's start to substring's end. */ +} regmatch_t; + +/* Declarations for routines. */ + + +/* Sets the current default syntax to SYNTAX, and return the old syntax. + You can also simply assign to the `re_syntax_options' variable. */ +extern reg_syntax_t re_set_syntax (reg_syntax_t __syntax); + +/* Compile the regular expression PATTERN, with length LENGTH + and syntax given by the global `re_syntax_options', into the buffer + BUFFER. Return NULL if successful, and an error string if not. */ +extern const char *re_compile_pattern (const char *__pattern, size_t __length, + struct re_pattern_buffer *__buffer); + + +/* Compile a fastmap for the compiled pattern in BUFFER; used to + accelerate searches. Return 0 if successful and -2 if was an + internal error. */ +extern int re_compile_fastmap (struct re_pattern_buffer *__buffer); +libc_hidden_proto(re_compile_fastmap) + + +/* Search in the string STRING (with length LENGTH) for the pattern + compiled into BUFFER. Start searching at position START, for RANGE + characters. Return the starting position of the match, -1 for no + match, or -2 for an internal error. Also return register + information in REGS (if REGS and BUFFER->no_sub are nonzero). */ +extern int re_search (struct re_pattern_buffer *__buffer, const char *__string, + int __length, int __start, int __range, + struct re_registers *__regs); +libc_hidden_proto(re_search) + + +/* Like `re_search', but search in the concatenation of STRING1 and + STRING2. Also, stop searching at index START + STOP. */ +extern int re_search_2 (struct re_pattern_buffer *__buffer, + const char *__string1, int __length1, + const char *__string2, int __length2, int __start, + int __range, struct re_registers *__regs, int __stop); +libc_hidden_proto(re_search_2) + + +/* Like `re_search', but return how many characters in STRING the regexp + in BUFFER matched, starting at position START. */ +extern int re_match (struct re_pattern_buffer *__buffer, const char *__string, + int __length, int __start, struct re_registers *__regs); + + +/* Relates to `re_match' as `re_search_2' relates to `re_search'. */ +extern int re_match_2 (struct re_pattern_buffer *__buffer, + const char *__string1, int __length1, + const char *__string2, int __length2, int __start, + struct re_registers *__regs, int __stop); + + +/* Set REGS to hold NUM_REGS registers, storing them in STARTS and + ENDS. Subsequent matches using BUFFER and REGS will use this memory + for recording register information. STARTS and ENDS must be + allocated with malloc, and must each be at least `NUM_REGS * sizeof + (regoff_t)' bytes long. + + If NUM_REGS == 0, then subsequent matches should allocate their own + register data. + + Unless this function is called, the first search or match using + PATTERN_BUFFER will allocate its own register data, without + freeing the old data. */ +extern void re_set_registers (struct re_pattern_buffer *__buffer, + struct re_registers *__regs, + unsigned int __num_regs, + regoff_t *__starts, regoff_t *__ends); + +#if defined _REGEX_RE_COMP || defined _LIBC +# ifndef _CRAY +/* 4.2 bsd compatibility. */ +extern char *re_comp (const char *); +extern int re_exec (const char *); +# endif +#endif + +/* GCC 2.95 and later have "__restrict"; C99 compilers have + "restrict", and "configure" may have defined "restrict". */ +#ifndef __restrict +# if ! (2 < __GNUC__ || (2 == __GNUC__ && 95 <= __GNUC_MINOR__)) +# if defined restrict || 199901L <= __STDC_VERSION__ +# define __restrict restrict +# else +# define __restrict +# endif +# endif +#endif +/* gcc 3.1 and up support the [restrict] syntax. */ +#ifndef __restrict_arr +# if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1) +# define __restrict_arr __restrict +# else +# define __restrict_arr +# endif +#endif + +/* POSIX compatibility. */ +extern int regcomp (regex_t *__restrict __preg, + const char *__restrict __pattern, + int __cflags); + +extern int regexec (const regex_t *__restrict __preg, + const char *__restrict __string, size_t __nmatch, + regmatch_t __pmatch[__restrict_arr], + int __eflags); +libc_hidden_proto(regexec) + +extern size_t regerror (int __errcode, const regex_t *__restrict __preg, + char *__restrict __errbuf, size_t __errbuf_size); + +extern void regfree (regex_t *__preg); +libc_hidden_proto(regfree) + + +__END_DECLS + +#endif /* regex.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/regexp.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/regexp.h new file mode 100644 index 00000000..57b7f93e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/regexp.h @@ -0,0 +1,232 @@ +/* Copyright (C) 1996, 1997, 1998, 1999, 2004, 2008 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1996. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _REGEXP_H +#define _REGEXP_H 1 + +/* The contents of this header file was first standardized in X/Open + System Interface and Headers Issue 2, originally coming from SysV. + In issue 4, version 2, it is marked as TO BE WITDRAWN, and it has + been withdrawn in SUSv3. + + This code shouldn't be used in any newly written code. It is + included only for compatibility reasons. Use the POSIX definition + in for portable applications and a reasonable interface. */ + +#include +#include +#include +#include +#include + +/* The implementation provided here emulates the needed functionality + by mapping to the POSIX regular expression matcher. The interface + for the here included function is weird (this really is a harmless + word). + + The user has to provide six macros before this header file can be + included: + + INIT Declarations vor variables which can be used by the + other macros. + + GETC() Return the value of the next character in the regular + expression pattern. Successive calls should return + successive characters. + + PEEKC() Return the value of the next character in the regular + expression pattern. Immediately successive calls to + PEEKC() should return the same character which should + also be the next character returned by GETC(). + + UNGETC(c) Cause `c' to be returned by the next call to GETC() and + PEEKC(). + + RETURN(ptr) Used for normal exit of the `compile' function. `ptr' + is a pointer to the character after the last character of + the compiled regular expression. + + ERROR(val) Used for abnormal return from `compile'. `val' is the + error number. The error codes are: + 11 Range endpoint too large. + 16 Bad number. + 25 \digit out of range. + 36 Illegal or missing delimiter. + 41 No remembered search string. + 42 \( \) imbalance. + 43 Too many \(. + 44 More tan two numbers given in \{ \}. + 45 } expected after \. + 46 First number exceeds second in \{ \}. + 49 [ ] imbalance. + 50 Regular expression overflow. + + */ + +__BEGIN_DECLS + +#if 0 +/* Interface variables. They contain the results of the successful + calls to `setp' and `advance'. */ +extern char *loc1; +extern char *loc2; + +/* The use of this variable in the `advance' function is not + supported. */ +extern char *locs; +#endif + + +#ifndef __DO_NOT_DEFINE_COMPILE +/* Get and compile the user supplied pattern up to end of line or + string or until EOF is seen, whatever happens first. The result is + placed in the buffer starting at EXPBUF and delimited by ENDBUF. + + This function cannot be defined in the libc itself since it depends + on the macros. */ +char * +compile (char *__restrict instring, char *__restrict expbuf, + __const char *__restrict endbuf, int eof) +{ + char *__input_buffer = NULL; + size_t __input_size = 0; + size_t __current_size = 0; + int __ch; + int __error; + INIT + + /* Align the expression buffer according to the needs for an object + of type `regex_t'. Then check for minimum size of the buffer for + the compiled regular expression. */ + regex_t *__expr_ptr; +# if defined __GNUC__ && __GNUC__ >= 2 + const size_t __req = __alignof__ (regex_t *); +# else + /* How shall we find out? We simply guess it and can change it is + this really proofs to be wrong. */ + const size_t __req = 8; +# endif + expbuf += __req; + expbuf -= (expbuf - ((char *) 0)) % __req; + if (endbuf < expbuf + sizeof (regex_t)) + { + ERROR (50); + } + __expr_ptr = (regex_t *) expbuf; + /* The remaining space in the buffer can be used for the compiled + pattern. */ + __expr_ptr->__REPB_PREFIX (buffer) = expbuf + sizeof (regex_t); + __expr_ptr->__REPB_PREFIX (allocated) + = endbuf - (char *) __expr_ptr->__REPB_PREFIX (buffer); + + while ((__ch = (GETC ())) != eof) + { + if (__ch == '\0' || __ch == '\n') + { + UNGETC (__ch); + break; + } + + if (__current_size + 1 >= __input_size) + { + size_t __new_size = __input_size ? 2 * __input_size : 128; + char *__new_room = (char *) alloca (__new_size); + /* See whether we can use the old buffer. */ + if (__new_room + __new_size == __input_buffer) + { + __input_size += __new_size; + __input_buffer = (char *) memcpy (__new_room, __input_buffer, + __current_size); + } + else if (__input_buffer + __input_size == __new_room) + __input_size += __new_size; + else + { + __input_size = __new_size; + __input_buffer = (char *) memcpy (__new_room, __input_buffer, + __current_size); + } + } + __input_buffer[__current_size++] = __ch; + } + if (__current_size) + __input_buffer[__current_size++] = '\0'; + else + __input_buffer = ""; + + /* Now compile the pattern. */ + __error = regcomp (__expr_ptr, __input_buffer, REG_NEWLINE); + if (__error != 0) + /* Oh well, we have to translate POSIX error codes. */ + switch (__error) + { + case REG_BADPAT: + case REG_ECOLLATE: + case REG_ECTYPE: + case REG_EESCAPE: + case REG_BADRPT: + case REG_EEND: + case REG_ERPAREN: + default: + /* There is no matching error code. */ + RETURN (36); + case REG_ESUBREG: + RETURN (25); + case REG_EBRACK: + RETURN (49); + case REG_EPAREN: + RETURN (42); + case REG_EBRACE: + RETURN (44); + case REG_BADBR: + RETURN (46); + case REG_ERANGE: + RETURN (11); + case REG_ESPACE: + case REG_ESIZE: + ERROR (50); + } + + /* Everything is ok. */ + RETURN ((char *) (__expr_ptr->__REPB_PREFIX (buffer) + + __expr_ptr->__REPB_PREFIX (used))); +} +#endif + + +#if 0 +/* Find the next match in STRING. The compiled regular expression is + found in the buffer starting at EXPBUF. `loc1' will return the + first character matched and `loc2' points to the next unmatched + character. */ +extern int step (__const char *__restrict __string, + __const char *__restrict __expbuf) __THROW; + +/* Match the beginning of STRING with the compiled regular expression + in EXPBUF. If the match is successful `loc2' will contain the + position of the first unmatched character. */ +extern int advance (__const char *__restrict __string, + __const char *__restrict __expbuf) __THROW; +#endif + + +__END_DECLS + +#endif /* regexp.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/resolv.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/resolv.h new file mode 100644 index 00000000..b9ce1e2a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/resolv.h @@ -0,0 +1,443 @@ +/* + * Copyright (c) 1983, 1987, 1989 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Portions Copyright (c) 1996-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* + * @(#)resolv.h 8.1 (Berkeley) 6/2/93 + * $BINDId: resolv.h,v 8.31 2000/03/30 20:16:50 vixie Exp $ + */ + +#ifndef _RESOLV_H_ + +/* These headers are needed for types used in the `struct res_state' + declaration. */ +#include +#include + +#ifndef __need_res_state +# define _RESOLV_H_ + +# include +# include +# include +# include +#endif + +#ifndef __res_state_defined +# define __res_state_defined + +typedef enum { res_goahead, res_nextns, res_modified, res_done, res_error } + res_sendhookact; + +typedef res_sendhookact (*res_send_qhook) (struct sockaddr_in * const *ns, + const u_char **query, + int *querylen, + u_char *ans, + int anssiz, + int *resplen); + +typedef res_sendhookact (*res_send_rhook) (const struct sockaddr_in *ns, + const u_char *query, + int querylen, + u_char *ans, + int anssiz, + int *resplen); + +/* + * Global defines and variables for resolver stub. + */ +# define MAXNS 3 /* max # name servers we'll track */ +# define MAXDFLSRCH 3 /* # default domain levels to try */ +# define MAXDNSRCH 6 /* max # domains in search path */ +# define LOCALDOMAINPARTS 2 /* min levels in name that is "local" */ + +# define RES_TIMEOUT 5 /* min. seconds between retries */ +# define MAXRESOLVSORT 10 /* number of net to sort on */ +# define RES_MAXNDOTS 15 /* should reflect bit field size */ +# define RES_MAXRETRANS 30 /* only for resolv.conf/RES_OPTIONS */ +# define RES_MAXRETRY 5 /* only for resolv.conf/RES_OPTIONS */ +# define RES_DFLRETRY 3 /* Default #/tries. */ +/* (glibc uses RES_DFLRETRY of 2 but also does _res.retry = 4 sometimes (!) */ +# define RES_MAXTIME 65535 /* Infinity, in milliseconds. */ + +/* _res (an instance of this structure) uses 0.5kb in bss + * in "ordinary" libc's (glibc, xBSD). We want to be less wasteful. + * We (1) shuffle and shrink some integer fields, + * and (2) can switch off stuff we don't support. + * Everything inside __UCLIBC_HAS_COMPAT_RES_STATE__ + * is not actually used by uclibc and can be configured off. + * However, this will prevent some programs from building. + * Really obscure stuff with no observed users in the wild is under + * __UCLIBC_HAS_EXTRA_COMPAT_RES_STATE__. + * I guess it's safe to set that to N. + */ +struct __res_state { + /*int retrans, retry; - moved, was here */ + u_int32_t options; /* (was: ulong) option flags - see below. */ + struct sockaddr_in nsaddr_list[MAXNS]; /* address of name server */ +#define nsaddr nsaddr_list[0] /* for backward compatibility */ + char *dnsrch[MAXDNSRCH + 1]; /* components of domain to search */ + /*char defdname[256]; - moved, was here */ + u_int8_t nscount; /* (was: int) number of name servers */ + u_int8_t ndots; /* (was: unsigned:4) threshold for initial abs. query */ + u_int8_t retrans; /* (was: int) retransmission time interval */ + u_int8_t retry; /* (was: int) number of times to retransmit */ +#ifdef __UCLIBC_HAS_COMPAT_RES_STATE__ + /* googling for "_res.defdname" says it's still sometimes used. + * Pity. It's huge, I want to move it to EXTRA_COMPAT... */ + char defdname[256]; /* default domain (deprecated) */ + u_int8_t nsort; /* (was: unsigned:4) number of elements in sort_list[] */ + u_int16_t pfcode; /* (was: ulong) RES_PRF_ flags. Used by dig. */ + unsigned short id; /* current message id */ + int res_h_errno; /* last one set for this context */ + struct { + struct in_addr addr; + u_int32_t mask; + } sort_list[MAXRESOLVSORT]; +#endif + +#ifdef __UCLIBC_HAS_IPV6__ + /* I assume that the intention is to store all + * DNS servers' addresses here, and duplicate in nsaddr_list[] + * those which have IPv4 address. In the case of IPv4 address + * _u._ext.nsaddrs[x] will point to some nsaddr_list[y], + * otherwise it will point into malloc'ed sockaddr_in6. + * nscount is the number of IPv4 addresses and _u._ext.nscount + * is the number of addresses of all kinds. + * + * If this differs from established usage and you need + * to change this, please describe how it is supposed to work. + */ + union { + struct { + struct sockaddr_in6 *nsaddrs[MAXNS]; + u_int8_t nscount; /* (was: u_int16_t) */ +#ifdef __UCLIBC_HAS_COMPAT_RES_STATE__ + /* rather obscure, and differs in BSD and glibc */ + u_int16_t nstimes[MAXNS]; + int nssocks[MAXNS]; + u_int16_t nscount6; + u_int16_t nsinit; + /* glibc also has: */ + /*u_int16_t nsmap[MAXNS];*/ + /*unsigned long long initstamp;*/ +#endif + } _ext; + } _u; +#endif + +#ifdef __UCLIBC_HAS_EXTRA_COMPAT_RES_STATE__ + /* Truly obscure stuff. + * Googling for "_res.XXX" for these members + * turned up basically empty */ + res_send_qhook qhook; /* query hook */ + res_send_rhook rhook; /* response hook */ + int _vcsock; /* PRIVATE: for res_send VC i/o */ + unsigned _flags; /* PRIVATE: see below */ +#endif +}; + +typedef struct __res_state *res_state; +# undef __need_res_state +#endif + +#ifdef _RESOLV_H_ +/* + * Revision information. This is the release date in YYYYMMDD format. + * It can change every day so the right thing to do with it is use it + * in preprocessor commands such as "#if (__RES > 19931104)". Do not + * compare for equality; rather, use it to determine whether your resolver + * is new enough to contain a certain feature. + */ + +#if 0 +#define __RES 19991006 +#else +#define __RES 19960801 +#endif + +/* + * Resolver configuration file. + * Normally not present, but may contain the address of the + * inital name server(s) to query and the domain search list. + */ + +#ifndef _PATH_RESCONF +#define _PATH_RESCONF "/etc/resolv.conf" +#endif + +struct res_sym { + int number; /* Identifying number, like T_MX */ + char * name; /* Its symbolic name, like "MX" */ + char * humanname; /* Its fun name, like "mail exchanger" */ +}; + +/* + * Resolver flags (used to be discrete per-module statics ints). + */ +#define RES_F_VC 0x00000001 /* socket is TCP */ +#define RES_F_CONN 0x00000002 /* socket is connected */ + +/* res_findzonecut() options */ +#define RES_EXHAUSTIVE 0x00000001 /* always do all queries */ + +/* + * Resolver options (keep these in synch with res_debug.c, please) + * (which of these do we really implement??) + */ +#define RES_INIT 0x00000001 /* address initialized */ +#define RES_DEBUG 0x00000002 /* print debug messages */ +#define RES_AAONLY 0x00000004 /* authoritative answers only (!IMPL)*/ +#define RES_USEVC 0x00000008 /* use virtual circuit */ +#define RES_PRIMARY 0x00000010 /* query primary server only (!IMPL) */ +#define RES_IGNTC 0x00000020 /* ignore trucation errors */ +#define RES_RECURSE 0x00000040 /* recursion desired */ +#define RES_DEFNAMES 0x00000080 /* use default domain name */ +#define RES_STAYOPEN 0x00000100 /* Keep TCP socket open */ +#define RES_DNSRCH 0x00000200 /* search up local domain tree */ +#define RES_INSECURE1 0x00000400 /* type 1 security disabled */ +#define RES_INSECURE2 0x00000800 /* type 2 security disabled */ +#define RES_NOALIASES 0x00001000 /* shuts off HOSTALIASES feature */ +#define RES_USE_INET6 0x00002000 /* use/map IPv6 in gethostbyname() */ +#define RES_ROTATE 0x00004000 /* rotate ns list after each query */ +#define RES_NOCHECKNAME 0x00008000 /* do not check names for sanity. */ +#define RES_KEEPTSIG 0x00010000 /* do not strip TSIG records */ +#define RES_BLAST 0x00020000 /* blast all recursive servers */ +#if 0 +#define RES_USEBSTRING 0x00040000 /* IPv6 reverse lookup with byte + strings */ +#define RES_NOIP6DOTINT 0x00080000 /* Do not use .ip6.int in IPv6 + reverse lookup */ + +#define RES_DEFAULT (RES_RECURSE|RES_DEFNAMES|RES_DNSRCH|RES_NOIP6DOTINT) +#else +#define RES_DEFAULT (RES_RECURSE|RES_DEFNAMES|RES_DNSRCH) +#endif + +/* + * Resolver "pfcode" values. Used by dig. + */ +#define RES_PRF_STATS 0x00000001 +#define RES_PRF_UPDATE 0x00000002 +#define RES_PRF_CLASS 0x00000004 +#define RES_PRF_CMD 0x00000008 +#define RES_PRF_QUES 0x00000010 +#define RES_PRF_ANS 0x00000020 +#define RES_PRF_AUTH 0x00000040 +#define RES_PRF_ADD 0x00000080 +#define RES_PRF_HEAD1 0x00000100 +#define RES_PRF_HEAD2 0x00000200 +#define RES_PRF_TTLID 0x00000400 +#define RES_PRF_HEADX 0x00000800 +#define RES_PRF_QUERY 0x00001000 +#define RES_PRF_REPLY 0x00002000 +#define RES_PRF_INIT 0x00004000 +/* 0x00008000 */ + +/* Things involving an internal (static) resolver context. */ +__BEGIN_DECLS +extern struct __res_state *__res_state(void) __attribute__ ((__const__)); +__END_DECLS +#define _res (*__res_state()) + +#define fp_nquery __fp_nquery +#define fp_query __fp_query +#define hostalias __hostalias +#define p_query __p_query +#define res_close __res_close +#define res_init __res_init +#define res_isourserver __res_isourserver +#define res_mkquery __res_mkquery +#define res_query __res_query +#define res_querydomain __res_querydomain +#define res_search __res_search +#define res_send __res_send + +__BEGIN_DECLS +void fp_nquery (const u_char *, int, FILE *) __THROW; +void fp_query (const u_char *, FILE *) __THROW; +const char * hostalias (const char *) __THROW; +void p_query (const u_char *) __THROW; +#ifdef __UCLIBC_HAS_BSD_RES_CLOSE__ +void res_close (void) __THROW; +#endif +int res_init (void) __THROW; +libc_hidden_proto(res_init) +int res_isourserver (const struct sockaddr_in *) __THROW; +int res_mkquery (int, const char *, int, int, const u_char *, + int, const u_char *, u_char *, int) __THROW; +int res_query (const char *, int, int, u_char *, int) __THROW; +libc_hidden_proto(res_query) +int res_querydomain (const char *, const char *, int, int, + u_char *, int) __THROW; +libc_hidden_proto(res_querydomain) +int res_search (const char *, int, int, u_char *, int) __THROW; +int res_send (const u_char *, int, u_char *, int) __THROW; +__END_DECLS + +#define b64_ntop __b64_ntop +#define b64_pton __b64_pton +#define dn_comp __dn_comp +#define dn_count_labels __dn_count_labels +#define dn_expand __dn_expand +#define dn_skipname __dn_skipname +#define fp_resstat __fp_resstat +#define loc_aton __loc_aton +#define loc_ntoa __loc_ntoa +#define p_cdname __p_cdname +#define p_cdnname __p_cdnname +#define p_class __p_class +#define p_fqname __p_fqname +#define p_fqnname __p_fqnname +#define p_option __p_option +#define p_secstodate __p_secstodate +#define p_section __p_section +#define p_time __p_time +#define p_type __p_type +#define p_rcode __p_rcode +#define putlong __putlong +#define putshort __putshort +#define res_dnok __res_dnok +#define res_hnok __res_hnok +#define res_hostalias __res_hostalias +#define res_mailok __res_mailok +#define res_nameinquery __res_nameinquery +#define res_nclose __res_nclose +#define res_ninit __res_ninit +#define res_nmkquery __res_nmkquery +#define res_npquery __res_npquery +#define res_nquery __res_nquery +#define res_nquerydomain __res_nquerydomain +#define res_nsearch __res_nsearch +#define res_nsend __res_nsend +#define res_nisourserver __res_nisourserver +#define res_ownok __res_ownok +#define res_queriesmatch __res_queriesmatch +#define res_randomid __res_randomid +#define sym_ntop __sym_ntop +#define sym_ntos __sym_ntos +#define sym_ston __sym_ston +__BEGIN_DECLS +int res_hnok (const char *) __THROW; +int res_ownok (const char *) __THROW; +int res_mailok (const char *) __THROW; +int res_dnok (const char *) __THROW; +int sym_ston (const struct res_sym *, const char *, int *) __THROW; +const char * sym_ntos (const struct res_sym *, int, int *) __THROW; +const char * sym_ntop (const struct res_sym *, int, int *) __THROW; +int b64_ntop (u_char const *, size_t, char *, size_t) __THROW; +int b64_pton (char const *, u_char *, size_t) __THROW; +int loc_aton (const char *ascii, u_char *binary) __THROW; +const char * loc_ntoa (const u_char *binary, char *ascii) __THROW; +int dn_skipname (const u_char *, const u_char *) __THROW; +void putlong (u_int32_t, u_char *) __THROW; +void putshort (u_int16_t, u_char *) __THROW; +const char * p_class (int) __THROW; +const char * p_time (u_int32_t) __THROW; +const char * p_type (int) __THROW; +const char * p_rcode (int) __THROW; +const u_char * p_cdnname (const u_char *, const u_char *, int, FILE *) + __THROW; +const u_char * p_cdname (const u_char *, const u_char *, FILE *) __THROW; +const u_char * p_fqnname (const u_char *cp, const u_char *msg, + int, char *, int) __THROW; +const u_char * p_fqname (const u_char *, const u_char *, FILE *) __THROW; +const char * p_option (u_long option) __THROW; +char * p_secstodate (u_long) __THROW; +int dn_count_labels (const char *) __THROW; +int dn_comp (const char *, u_char *, int, u_char **, u_char **) + __THROW; +int dn_expand (const u_char *, const u_char *, const u_char *, + char *, int) __THROW; +u_int res_randomid (void) __THROW; +int res_nameinquery (const char *, int, int, + const u_char *, const u_char *) __THROW; +int res_queriesmatch (const u_char *, const u_char *, + const u_char *, const u_char *) __THROW; +const char * p_section (int section, int opcode) __THROW; +/* Things involving a resolver context. */ +int res_ninit (res_state) __THROW; +int res_nisourserver (const res_state, + const struct sockaddr_in *) __THROW; +void fp_resstat (const res_state, FILE *) __THROW; +void res_npquery (const res_state, const u_char *, int, FILE *) + __THROW; +const char * res_hostalias (const res_state, const char *, char *, size_t) + __THROW; +int res_nquery (res_state, const char *, int, int, u_char *, int) + __THROW; +int res_nsearch (res_state, const char *, int, int, u_char *, int) + __THROW; +int res_nquerydomain (res_state, const char *, const char *, int, + int, u_char *, int) __THROW; +int res_nmkquery (res_state, int, const char *, int, int, + const u_char *, int, const u_char *, u_char *, + int) __THROW; +int res_nsend (res_state, const u_char *, int, u_char *, int) + __THROW; +void res_nclose (res_state) __THROW; +__END_DECLS + +# if _LIBC +# ifdef __UCLIBC_HAS_THREADS__ +# if defined __UCLIBC_HAS_TLS__ \ + && (!defined NOT_IN_libc || defined IS_IN_libpthread) +# undef _res +# ifndef NOT_IN_libc +# define __resp __libc_resp +# endif +# define _res (*__resp) +extern __thread struct __res_state *__resp attribute_tls_model_ie; +# endif +# else +# undef _res +# define _res (*__resp) +extern struct __res_state *__resp; +# endif /* __UCLIBC_HAS_THREADS__ */ +# endif /* _LIBC */ + +#endif /* _RESOLV_H_ */ + +#endif /* !_RESOLV_H_ */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/rpc/auth.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/rpc/auth.h new file mode 100644 index 00000000..a156c56f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/rpc/auth.h @@ -0,0 +1,232 @@ +/* @(#)auth.h 2.3 88/08/07 4.0 RPCSRC; from 1.17 88/02/08 SMI */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +/* + * auth.h, Authentication interface. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + * + * The data structures are completely opaque to the client. The client + * is required to pass a AUTH * to routines that create rpc + * "sessions". + */ + +#ifndef _RPC_AUTH_H + +#define _RPC_AUTH_H 1 +#ifdef _LIBC +/* Some adjustments to make the libc source from glibc + * compile more easily with uClibc... */ +#ifndef __FORCE_GLIBC +#define __FORCE_GLIBC +#endif +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif +#define _(X) X +#endif +#include +#include + +__BEGIN_DECLS + +#define MAX_AUTH_BYTES 400 +#define MAXNETNAMELEN 255 /* maximum length of network user's name */ + +/* + * Status returned from authentication check + */ +enum auth_stat { + AUTH_OK=0, + /* + * failed at remote end + */ + AUTH_BADCRED=1, /* bogus credentials (seal broken) */ + AUTH_REJECTEDCRED=2, /* client should begin new session */ + AUTH_BADVERF=3, /* bogus verifier (seal broken) */ + AUTH_REJECTEDVERF=4, /* verifier expired or was replayed */ + AUTH_TOOWEAK=5, /* rejected due to security reasons */ + /* + * failed locally + */ + AUTH_INVALIDRESP=6, /* bogus response verifier */ + AUTH_FAILED=7 /* some unknown reason */ +}; + +union des_block { + struct { + u_int32_t high; + u_int32_t low; + } key; + char c[8]; +}; +typedef union des_block des_block; +extern bool_t xdr_des_block (XDR *__xdrs, des_block *__blkp) __THROW; + +/* + * Authentication info. Opaque to client. + */ +struct opaque_auth { + enum_t oa_flavor; /* flavor of auth */ + caddr_t oa_base; /* address of more auth stuff */ + u_int oa_length; /* not to exceed MAX_AUTH_BYTES */ +}; + +/* + * Auth handle, interface to client side authenticators. + */ +typedef struct AUTH AUTH; +struct AUTH { + struct opaque_auth ah_cred; + struct opaque_auth ah_verf; + union des_block ah_key; + struct auth_ops { + void (*ah_nextverf) (AUTH *); + int (*ah_marshal) (AUTH *, XDR *); /* nextverf & serialize */ + int (*ah_validate) (AUTH *, struct opaque_auth *); + /* validate verifier */ + int (*ah_refresh) (AUTH *); /* refresh credentials */ + void (*ah_destroy) (AUTH *); /* destroy this structure */ + } *ah_ops; + caddr_t ah_private; +}; + + +/* + * Authentication ops. + * The ops and the auth handle provide the interface to the authenticators. + * + * AUTH *auth; + * XDR *xdrs; + * struct opaque_auth verf; + */ +#define AUTH_NEXTVERF(auth) \ + ((*((auth)->ah_ops->ah_nextverf))(auth)) +#define auth_nextverf(auth) \ + ((*((auth)->ah_ops->ah_nextverf))(auth)) + +#define AUTH_MARSHALL(auth, xdrs) \ + ((*((auth)->ah_ops->ah_marshal))(auth, xdrs)) +#define auth_marshall(auth, xdrs) \ + ((*((auth)->ah_ops->ah_marshal))(auth, xdrs)) + +#define AUTH_VALIDATE(auth, verfp) \ + ((*((auth)->ah_ops->ah_validate))((auth), verfp)) +#define auth_validate(auth, verfp) \ + ((*((auth)->ah_ops->ah_validate))((auth), verfp)) + +#define AUTH_REFRESH(auth) \ + ((*((auth)->ah_ops->ah_refresh))(auth)) +#define auth_refresh(auth) \ + ((*((auth)->ah_ops->ah_refresh))(auth)) + +#define AUTH_DESTROY(auth) \ + ((*((auth)->ah_ops->ah_destroy))(auth)) +#define auth_destroy(auth) \ + ((*((auth)->ah_ops->ah_destroy))(auth)) + + +extern struct opaque_auth _null_auth; + + +/* + * These are the various implementations of client side authenticators. + */ + +/* + * Unix style authentication + * AUTH *authunix_create(machname, uid, gid, len, aup_gids) + * char *machname; + * int uid; + * int gid; + * int len; + * int *aup_gids; + */ +extern AUTH *authunix_create (char *__machname, __uid_t __uid, __gid_t __gid, + int __len, __gid_t *__aup_gids); +libc_hidden_proto(authunix_create) +extern AUTH *authunix_create_default (void); +libc_hidden_proto(authunix_create_default) +extern AUTH *authnone_create (void) __THROW; +libc_hidden_proto(authnone_create) +#if 0 +extern AUTH *authdes_create (const char *__servername, u_int __window, + struct sockaddr *__syncaddr, des_block *__ckey) + __THROW; +extern AUTH *authdes_pk_create (const char *, netobj *, u_int, + struct sockaddr *, des_block *) __THROW; +#endif + + +#define AUTH_NONE 0 /* no authentication */ +#define AUTH_NULL 0 /* backward compatibility */ +#define AUTH_SYS 1 /* unix style (uid, gids) */ +#define AUTH_UNIX AUTH_SYS +#define AUTH_SHORT 2 /* short hand unix style */ +#define AUTH_DES 3 /* des style (encrypted timestamps) */ +#define AUTH_DH AUTH_DES /* Diffie-Hellman (this is DES) */ +#define AUTH_KERB 4 /* kerberos style */ + +#if 0 +/* + * Netname manipulating functions + * + */ +extern int getnetname (char *) __THROW; +extern int host2netname (char *, __const char *, __const char *) __THROW; +extern int user2netname (char *, __const uid_t, __const char *) __THROW; +extern int netname2user (__const char *, uid_t *, gid_t *, int *, gid_t *) + __THROW; +extern int netname2host (__const char *, char *, __const int) __THROW; + +/* + * + * These routines interface to the keyserv daemon + * + */ +extern int key_decryptsession (char *, des_block *); +extern int key_decryptsession_pk (char *, netobj *, des_block *); +extern int key_encryptsession (char *, des_block *); +extern int key_encryptsession_pk (char *, netobj *, des_block *); +extern int key_gendes (des_block *); +extern int key_setsecret (char *); +extern int key_secretkey_is_set (void); +extern int key_get_conv (char *, des_block *); +#endif + +/* + * XDR an opaque authentication struct. + */ +extern bool_t xdr_opaque_auth (XDR *, struct opaque_auth *) __THROW; +libc_hidden_proto(xdr_opaque_auth) + +__END_DECLS + +#endif /* rpc/auth.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/rpc/auth_des.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/rpc/auth_des.h new file mode 100644 index 00000000..d51b7ce7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/rpc/auth_des.h @@ -0,0 +1,117 @@ +/* Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _RPC_AUTH_DES_H +#define _RPC_AUTH_DES_H 1 + +#include +#include + +__BEGIN_DECLS + +#if 0 +/* There are two kinds of "names": fullnames and nicknames */ +enum authdes_namekind + { + ADN_FULLNAME, + ADN_NICKNAME + }; + +/* A fullname contains the network name of the client, + a conversation key and the window */ +struct authdes_fullname + { + char *name; /* network name of client, up to MAXNETNAMELEN */ + des_block key; /* conversation key */ + uint32_t window; /* associated window */ + }; + +/* A credential */ +struct authdes_cred + { + enum authdes_namekind adc_namekind; + struct authdes_fullname adc_fullname; + uint32_t adc_nickname; + }; +#endif + +/* A timeval replacement for !32bit platforms */ +struct rpc_timeval + { + uint32_t tv_sec; /* Seconds. */ + uint32_t tv_usec; /* Microseconds. */ + }; + +#if 0 +/* A des authentication verifier */ +struct authdes_verf + { + union + { + struct rpc_timeval adv_ctime; /* clear time */ + des_block adv_xtime; /* crypt time */ + } + adv_time_u; + uint32_t adv_int_u; + }; + +/* des authentication verifier: client variety + + adv_timestamp is the current time. + adv_winverf is the credential window + 1. + Both are encrypted using the conversation key. */ +#define adv_timestamp adv_time_u.adv_ctime +#define adv_xtimestamp adv_time_u.adv_xtime +#define adv_winverf adv_int_u + +/* des authentication verifier: server variety + + adv_timeverf is the client's timestamp + client's window + adv_nickname is the server's nickname for the client. + adv_timeverf is encrypted using the conversation key. */ +#define adv_timeverf adv_time_u.adv_ctime +#define adv_xtimeverf adv_time_u.adv_xtime +#define adv_nickname adv_int_u + +/* Map a des credential into a unix cred. */ +extern int authdes_getucred (__const struct authdes_cred * __adc, + uid_t * __uid, gid_t * __gid, + short *__grouplen, gid_t * __groups) __THROW; + +/* Get the public key for NAME and place it in KEY. NAME can only be + up to MAXNETNAMELEN bytes long and the destination buffer KEY should + have HEXKEYBYTES + 1 bytes long to fit all characters from the key. */ +extern int getpublickey (__const char *__name, char *__key) __THROW; + +/* Get the secret key for NAME and place it in KEY. PASSWD is used to + decrypt the encrypted key stored in the database. NAME can only be + up to MAXNETNAMELEN bytes long and the destination buffer KEY + should have HEXKEYBYTES + 1 bytes long to fit all characters from + the key. */ +extern int getsecretkey (__const char *__name, char *__key, + __const char *__passwd) __THROW; +#endif + +extern int rtime (struct sockaddr_in *__addrp, struct rpc_timeval *__timep, + struct rpc_timeval *__timeout) __THROW; +libc_hidden_proto(rtime) + +__END_DECLS + + +#endif /* rpc/auth_des.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/rpc/auth_unix.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/rpc/auth_unix.h new file mode 100644 index 00000000..713fcb43 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/rpc/auth_unix.h @@ -0,0 +1,91 @@ +/* @(#)auth_unix.h 2.2 88/07/29 4.0 RPCSRC; from 1.8 88/02/08 SMI */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +/* @(#)auth_unix.h 1.5 86/07/16 SMI */ + +/* + * auth_unix.h, Protocol for UNIX style authentication parameters for RPC + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +/* + * The system is very weak. The client uses no encryption for it + * credentials and only sends null verifiers. The server sends backs + * null verifiers or optionally a verifier that suggests a new short hand + * for the credentials. + */ + +#ifndef _RPC_AUTH_UNIX_H +#define _RPC_AUTH_UNIX_H 1 + +#include +#include +#include +#include +#include + +__BEGIN_DECLS + +/* The machine name is part of a credential; it may not exceed 255 bytes */ +#define MAX_MACHINE_NAME 255 + +/* gids compose part of a credential; there may not be more than 16 of them */ +#define NGRPS 16 + +/* + * Unix style credentials. + */ +struct authunix_parms + { + u_long aup_time; + char *aup_machname; + __uid_t aup_uid; + __gid_t aup_gid; + u_int aup_len; + __gid_t *aup_gids; + }; + +extern bool_t xdr_authunix_parms (XDR *__xdrs, struct authunix_parms *__p) + __THROW; +libc_hidden_proto(xdr_authunix_parms) + +/* + * If a response verifier has flavor AUTH_SHORT, + * then the body of the response verifier encapsulates the following structure; + * again it is serialized in the obvious fashion. + */ +struct short_hand_verf + { + struct opaque_auth new_cred; + }; + +__END_DECLS + +#endif /* rpc/auth_unix.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/rpc/clnt.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/rpc/clnt.h new file mode 100644 index 00000000..608c7e7d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/rpc/clnt.h @@ -0,0 +1,433 @@ +/* @(#)clnt.h 2.1 88/07/29 4.0 RPCSRC; from 1.31 88/02/08 SMI*/ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +/* + * clnt.h - Client side remote procedure call interface. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +#ifndef _RPC_CLNT_H +#define _RPC_CLNT_H 1 + +#include +#include +#include +#include +#include + +__BEGIN_DECLS + +/* + * Rpc calls return an enum clnt_stat. This should be looked at more, + * since each implementation is required to live with this (implementation + * independent) list of errors. + */ +enum clnt_stat { + RPC_SUCCESS=0, /* call succeeded */ + /* + * local errors + */ + RPC_CANTENCODEARGS=1, /* can't encode arguments */ + RPC_CANTDECODERES=2, /* can't decode results */ + RPC_CANTSEND=3, /* failure in sending call */ + RPC_CANTRECV=4, /* failure in receiving result */ + RPC_TIMEDOUT=5, /* call timed out */ + /* + * remote errors + */ + RPC_VERSMISMATCH=6, /* rpc versions not compatible */ + RPC_AUTHERROR=7, /* authentication error */ + RPC_PROGUNAVAIL=8, /* program not available */ + RPC_PROGVERSMISMATCH=9, /* program version mismatched */ + RPC_PROCUNAVAIL=10, /* procedure unavailable */ + RPC_CANTDECODEARGS=11, /* decode arguments error */ + RPC_SYSTEMERROR=12, /* generic "other problem" */ + RPC_NOBROADCAST = 21, /* Broadcasting not supported */ + /* + * callrpc & clnt_create errors + */ + RPC_UNKNOWNHOST=13, /* unknown host name */ + RPC_UNKNOWNPROTO=17, /* unknown protocol */ + RPC_UNKNOWNADDR = 19, /* Remote address unknown */ + + /* + * rpcbind errors + */ + RPC_RPCBFAILURE=14, /* portmapper failed in its call */ +#define RPC_PMAPFAILURE RPC_RPCBFAILURE + RPC_PROGNOTREGISTERED=15, /* remote program is not registered */ + RPC_N2AXLATEFAILURE = 22, /* Name to addr translation failed */ + /* + * unspecified error + */ + RPC_FAILED=16, + RPC_INTR=18, + RPC_TLIERROR=20, + RPC_UDERROR=23, + /* + * asynchronous errors + */ + RPC_INPROGRESS = 24, + RPC_STALERACHANDLE = 25 +}; + + +/* + * Error info. + */ +struct rpc_err { + enum clnt_stat re_status; + union { + int RE_errno; /* related system error */ + enum auth_stat RE_why; /* why the auth error occurred */ + struct { + u_long low; /* lowest verion supported */ + u_long high; /* highest verion supported */ + } RE_vers; + struct { /* maybe meaningful if RPC_FAILED */ + long s1; + long s2; + } RE_lb; /* life boot & debugging only */ + } ru; +#define re_errno ru.RE_errno +#define re_why ru.RE_why +#define re_vers ru.RE_vers +#define re_lb ru.RE_lb +}; + + +/* + * Client rpc handle. + * Created by individual implementations, see e.g. rpc_udp.c. + * Client is responsible for initializing auth, see e.g. auth_none.c. + */ +typedef struct CLIENT CLIENT; +struct CLIENT { + AUTH *cl_auth; /* authenticator */ + /* not sure whether non-const-ness is a part of the spec... if it is, + * enclose "const" in #ifdef _LIBC / #endif + * to make it effective only for libc compile */ + const + struct clnt_ops { + enum clnt_stat (*cl_call) (CLIENT *, u_long, xdrproc_t, caddr_t, xdrproc_t, + caddr_t, struct timeval); + /* call remote procedure */ + void (*cl_abort) (void); /* abort a call */ + void (*cl_geterr) (CLIENT *, struct rpc_err *); + /* get specific error code */ + bool_t (*cl_freeres) (CLIENT *, xdrproc_t, caddr_t); + /* frees results */ + void (*cl_destroy) (CLIENT *); /* destroy this structure */ + bool_t (*cl_control) (CLIENT *, int, char *); + /* the ioctl() of rpc */ + } *cl_ops; + caddr_t cl_private; /* private stuff */ +}; + + +/* + * client side rpc interface ops + * + * Parameter types are: + * + */ + +/* + * enum clnt_stat + * CLNT_CALL(rh, proc, xargs, argsp, xres, resp, timeout) + * CLIENT *rh; + * u_long proc; + * xdrproc_t xargs; + * caddr_t argsp; + * xdrproc_t xres; + * caddr_t resp; + * struct timeval timeout; + */ +#define CLNT_CALL(rh, proc, xargs, argsp, xres, resp, secs) \ + ((*(rh)->cl_ops->cl_call)(rh, proc, xargs, argsp, xres, resp, secs)) +#define clnt_call(rh, proc, xargs, argsp, xres, resp, secs) \ + ((*(rh)->cl_ops->cl_call)(rh, proc, xargs, argsp, xres, resp, secs)) + +/* + * void + * CLNT_ABORT(rh); + * CLIENT *rh; + */ +#define CLNT_ABORT(rh) ((*(rh)->cl_ops->cl_abort)(rh)) +#define clnt_abort(rh) ((*(rh)->cl_ops->cl_abort)(rh)) + +/* + * struct rpc_err + * CLNT_GETERR(rh); + * CLIENT *rh; + */ +#define CLNT_GETERR(rh,errp) ((*(rh)->cl_ops->cl_geterr)(rh, errp)) +#define clnt_geterr(rh,errp) ((*(rh)->cl_ops->cl_geterr)(rh, errp)) + + +/* + * bool_t + * CLNT_FREERES(rh, xres, resp); + * CLIENT *rh; + * xdrproc_t xres; + * caddr_t resp; + */ +#define CLNT_FREERES(rh,xres,resp) ((*(rh)->cl_ops->cl_freeres)(rh,xres,resp)) +#define clnt_freeres(rh,xres,resp) ((*(rh)->cl_ops->cl_freeres)(rh,xres,resp)) + +/* + * bool_t + * CLNT_CONTROL(cl, request, info) + * CLIENT *cl; + * u_int request; + * char *info; + */ +#define CLNT_CONTROL(cl,rq,in) ((*(cl)->cl_ops->cl_control)(cl,rq,in)) +#define clnt_control(cl,rq,in) ((*(cl)->cl_ops->cl_control)(cl,rq,in)) + +/* + * control operations that apply to all transports + * + * Note: options marked XXX are no-ops in this implementation of RPC. + * The are present in TI-RPC but can't be implemented here since they + * depend on the presence of STREAMS/TLI, which we don't have. + */ +#define CLSET_TIMEOUT 1 /* set timeout (timeval) */ +#define CLGET_TIMEOUT 2 /* get timeout (timeval) */ +#define CLGET_SERVER_ADDR 3 /* get server's address (sockaddr) */ +#define CLGET_FD 6 /* get connections file descriptor */ +#define CLGET_SVC_ADDR 7 /* get server's address (netbuf) XXX */ +#define CLSET_FD_CLOSE 8 /* close fd while clnt_destroy */ +#define CLSET_FD_NCLOSE 9 /* Do not close fd while clnt_destroy*/ +#define CLGET_XID 10 /* Get xid */ +#define CLSET_XID 11 /* Set xid */ +#define CLGET_VERS 12 /* Get version number */ +#define CLSET_VERS 13 /* Set version number */ +#define CLGET_PROG 14 /* Get program number */ +#define CLSET_PROG 15 /* Set program number */ +#define CLSET_SVC_ADDR 16 /* get server's address (netbuf) XXX */ +#define CLSET_PUSH_TIMOD 17 /* push timod if not already present XXX */ +#define CLSET_POP_TIMOD 18 /* pop timod XXX */ +/* + * Connectionless only control operations + */ +#define CLSET_RETRY_TIMEOUT 4 /* set retry timeout (timeval) */ +#define CLGET_RETRY_TIMEOUT 5 /* get retry timeout (timeval) */ + +/* + * void + * CLNT_DESTROY(rh); + * CLIENT *rh; + */ +#define CLNT_DESTROY(rh) ((*(rh)->cl_ops->cl_destroy)(rh)) +#define clnt_destroy(rh) ((*(rh)->cl_ops->cl_destroy)(rh)) + + +/* + * RPCTEST is a test program which is accessible on every rpc + * transport/port. It is used for testing, performance evaluation, + * and network administration. + */ + +#define RPCTEST_PROGRAM ((u_long)1) +#define RPCTEST_VERSION ((u_long)1) +#define RPCTEST_NULL_PROC ((u_long)2) +#define RPCTEST_NULL_BATCH_PROC ((u_long)3) + +/* + * By convention, procedure 0 takes null arguments and returns them + */ + +#define NULLPROC ((u_long)0) + +/* + * Below are the client handle creation routines for the various + * implementations of client side rpc. They can return NULL if a + * creation failure occurs. + */ + +/* + * Memory based rpc (for speed check and testing) + * CLIENT * + * clntraw_create(prog, vers) + * u_long prog; + * u_long vers; + */ +extern CLIENT *clntraw_create (__const u_long __prog, __const u_long __vers) + __THROW; + + +/* + * Generic client creation routine. Supported protocols are "udp", "tcp" and + * "unix" + * CLIENT * + * clnt_create(host, prog, vers, prot) + * char *host; -- hostname + * u_long prog; -- program number + * u_ong vers; -- version number + * char *prot; -- protocol + */ +extern CLIENT *clnt_create (__const char *__host, __const u_long __prog, + __const u_long __vers, __const char *__prot) + __THROW; + + +/* + * TCP based rpc + * CLIENT * + * clnttcp_create(raddr, prog, vers, sockp, sendsz, recvsz) + * struct sockaddr_in *raddr; + * u_long prog; + * u_long version; + * register int *sockp; + * u_int sendsz; + * u_int recvsz; + */ +extern CLIENT *clnttcp_create (struct sockaddr_in *__raddr, u_long __prog, + u_long __version, int *__sockp, u_int __sendsz, + u_int __recvsz) __THROW; +libc_hidden_proto(clnttcp_create) + +/* + * UDP based rpc. + * CLIENT * + * clntudp_create(raddr, program, version, wait, sockp) + * struct sockaddr_in *raddr; + * u_long program; + * u_long version; + * struct timeval wait_resend; + * int *sockp; + * + * Same as above, but you specify max packet sizes. + * CLIENT * + * clntudp_bufcreate(raddr, program, version, wait, sockp, sendsz, recvsz) + * struct sockaddr_in *raddr; + * u_long program; + * u_long version; + * struct timeval wait_resend; + * int *sockp; + * u_int sendsz; + * u_int recvsz; + */ +extern CLIENT *clntudp_create (struct sockaddr_in *__raddr, u_long __program, + u_long __version, struct timeval __wait_resend, + int *__sockp) __THROW; +libc_hidden_proto(clntudp_create) +extern CLIENT *clntudp_bufcreate (struct sockaddr_in *__raddr, + u_long __program, u_long __version, + struct timeval __wait_resend, int *__sockp, + u_int __sendsz, u_int __recvsz) __THROW; +libc_hidden_proto(clntudp_bufcreate) + + +/* + * AF_UNIX based rpc + * CLIENT * + * clntunix_create(raddr, prog, vers, sockp, sendsz, recvsz) + * struct sockaddr_un *raddr; + * u_long prog; + * u_long version; + * register int *sockp; + * u_int sendsz; + * u_int recvsz; + */ +extern CLIENT *clntunix_create (struct sockaddr_un *__raddr, u_long __program, + u_long __version, int *__sockp, + u_int __sendsz, u_int __recvsz) __THROW; +libc_hidden_proto(clntunix_create) + + +extern int callrpc (__const char *__host, __const u_long __prognum, + __const u_long __versnum, __const u_long __procnum, + __const xdrproc_t __inproc, __const char *__in, + __const xdrproc_t __outproc, char *__out) __THROW; +extern int _rpc_dtablesize (void) __THROW; +libc_hidden_proto(_rpc_dtablesize) + +/* + * Print why creation failed + */ +extern void clnt_pcreateerror (__const char *__msg); /* stderr */ +extern char *clnt_spcreateerror(__const char *__msg) __THROW; /* string */ +libc_hidden_proto(clnt_spcreateerror) + +/* + * Like clnt_perror(), but is more verbose in its output + */ +extern void clnt_perrno (enum clnt_stat __num); /* stderr */ + +/* + * Print an English error message, given the client error code + */ +extern void clnt_perror (CLIENT *__clnt, __const char *__msg); + /* stderr */ +libc_hidden_proto(clnt_perror) +extern char *clnt_sperror (CLIENT *__clnt, __const char *__msg) __THROW; + /* string */ +libc_hidden_proto(clnt_sperror) + + +/* + * If a creation fails, the following allows the user to figure out why. + */ +struct rpc_createerr { + enum clnt_stat cf_stat; + struct rpc_err cf_error; /* useful when cf_stat == RPC_PMAPFAILURE */ +}; + +extern struct rpc_createerr rpc_createerr; + + + +/* + * Copy error message to buffer. + */ +extern char *clnt_sperrno (enum clnt_stat __num) __THROW; /* string */ +libc_hidden_proto(clnt_sperrno) + +/* + * get the port number on the host for the rpc program,version and proto + */ +extern int getrpcport (__const char * __host, u_long __prognum, + u_long __versnum, u_int proto) __THROW; + +/* + * get the local host's IP address without consulting + * name service library functions + */ +extern void get_myaddress (struct sockaddr_in *) __THROW; + +#define UDPMSGSIZE 8800 /* rpc imposed limit on udp msg size */ +#define RPCSMALLMSGSIZE 400 /* a more reasonable packet size */ + +__END_DECLS + +#endif /* rpc/clnt.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/rpc/des_crypt.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/rpc/des_crypt.h new file mode 100644 index 00000000..6a65887d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/rpc/des_crypt.h @@ -0,0 +1,97 @@ +/* + * @(#)des_crypt.h 2.1 88/08/11 4.0 RPCSRC; from 1.4 88/02/08 (C) 1986 SMI + * + * des_crypt.h, des library routine interface + * Copyright (C) 1986, Sun Microsystems, Inc. + */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +#ifndef __DES_CRYPT_H__ +#define __DES_CRYPT_H__ 1 + +#include + +__BEGIN_DECLS + +#define DES_MAXDATA 8192 /* max bytes encrypted in one call */ +#define DES_DIRMASK (1 << 0) +#define DES_ENCRYPT (0*DES_DIRMASK) /* Encrypt */ +#define DES_DECRYPT (1*DES_DIRMASK) /* Decrypt */ + + +#define DES_DEVMASK (1 << 1) +#define DES_HW (0*DES_DEVMASK) /* Use hardware device */ +#define DES_SW (1*DES_DEVMASK) /* Use software device */ + + +#define DESERR_NONE 0 /* succeeded */ +#define DESERR_NOHWDEVICE 1 /* succeeded, but hw device not available */ +#define DESERR_HWERROR 2 /* failed, hardware/driver error */ +#define DESERR_BADPARAM 3 /* failed, bad parameter to call */ + +#define DES_FAILED(err) \ + ((err) > DESERR_NOHWDEVICE) + +/* + * cbc_crypt() + * ecb_crypt() + * + * Encrypt (or decrypt) len bytes of a buffer buf. + * The length must be a multiple of eight. + * The key should have odd parity in the low bit of each byte. + * ivec is the input vector, and is updated to the new one (cbc only). + * The mode is created by oring together the appropriate parameters. + * DESERR_NOHWDEVICE is returned if DES_HW was specified but + * there was no hardware to do it on (the data will still be + * encrypted though, in software). + */ + + +/* + * Cipher Block Chaining mode + */ +extern int cbc_crypt (char *__key, char *__buf, unsigned __len, + unsigned __mode, char *__ivec) __THROW; + +/* + * Electronic Code Book mode + */ +extern int ecb_crypt (char *__key, char *__buf, unsigned __len, + unsigned __mode) __THROW; + +/* + * Set des parity for a key. + * DES parity is odd and in the low bit of each byte + */ +extern void des_setparity (char *__key) __THROW; + +__END_DECLS + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/rpc/key_prot.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/rpc/key_prot.h new file mode 100644 index 00000000..629e2499 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/rpc/key_prot.h @@ -0,0 +1,346 @@ +/* + * Please do not edit this file. + * It was generated using rpcgen. + */ + +#ifndef _KEY_PROT_H_RPCGEN +#define _KEY_PROT_H_RPCGEN + +#include + +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +#if 0 +#pragma ident "@(#)key_prot.x 1.7 94/04/29 SMI" +#endif +/* Copyright (c) 1990, 1991 Sun Microsystems, Inc. */ + +/* + * Compiled from key_prot.x using rpcgen. + * DO NOT EDIT THIS FILE! + * This is NOT source code! + */ +#define PROOT 3 +#define HEXMODULUS "d4a0ba0250b6fd2ec626e7efd637df76c716e22d0944b88b" +#define HEXKEYBYTES 48 +#define KEYSIZE 192 +#define KEYBYTES 24 +#define KEYCHECKSUMSIZE 16 + +enum keystatus { + KEY_SUCCESS = 0, + KEY_NOSECRET = 1, + KEY_UNKNOWN = 2, + KEY_SYSTEMERR = 3, +}; +typedef enum keystatus keystatus; +#ifdef __cplusplus +extern "C" bool_t xdr_keystatus(XDR *, keystatus*); +#elif __STDC__ +extern bool_t xdr_keystatus(XDR *, keystatus*); +#else /* Old Style C */ +bool_t xdr_keystatus(); +#endif /* Old Style C */ + + +typedef char keybuf[HEXKEYBYTES]; +#ifdef __cplusplus +extern "C" bool_t xdr_keybuf(XDR *, keybuf); +#elif __STDC__ +extern bool_t xdr_keybuf(XDR *, keybuf); +#else /* Old Style C */ +bool_t xdr_keybuf(); +#endif /* Old Style C */ + + +typedef char *netnamestr; +#ifdef __cplusplus +extern "C" bool_t xdr_netnamestr(XDR *, netnamestr*); +#elif __STDC__ +extern bool_t xdr_netnamestr(XDR *, netnamestr*); +#else /* Old Style C */ +bool_t xdr_netnamestr(); +#endif /* Old Style C */ + + +struct cryptkeyarg { + netnamestr remotename; + des_block deskey; +}; +typedef struct cryptkeyarg cryptkeyarg; +#ifdef __cplusplus +extern "C" bool_t xdr_cryptkeyarg(XDR *, cryptkeyarg*); +#elif __STDC__ +extern bool_t xdr_cryptkeyarg(XDR *, cryptkeyarg*); +#else /* Old Style C */ +bool_t xdr_cryptkeyarg(); +#endif /* Old Style C */ + + +struct cryptkeyarg2 { + netnamestr remotename; + netobj remotekey; + des_block deskey; +}; +typedef struct cryptkeyarg2 cryptkeyarg2; +#ifdef __cplusplus +extern "C" bool_t xdr_cryptkeyarg2(XDR *, cryptkeyarg2*); +#elif __STDC__ +extern bool_t xdr_cryptkeyarg2(XDR *, cryptkeyarg2*); +#else /* Old Style C */ +bool_t xdr_cryptkeyarg2(); +#endif /* Old Style C */ + + +struct cryptkeyres { + keystatus status; + union { + des_block deskey; + } cryptkeyres_u; +}; +typedef struct cryptkeyres cryptkeyres; +#ifdef __cplusplus +extern "C" bool_t xdr_cryptkeyres(XDR *, cryptkeyres*); +#elif __STDC__ +extern bool_t xdr_cryptkeyres(XDR *, cryptkeyres*); +#else /* Old Style C */ +bool_t xdr_cryptkeyres(); +#endif /* Old Style C */ + +#define MAXGIDS 16 + +struct unixcred { + u_int uid; + u_int gid; + struct { + u_int gids_len; + u_int *gids_val; + } gids; +}; +typedef struct unixcred unixcred; +#ifdef __cplusplus +extern "C" bool_t xdr_unixcred(XDR *, unixcred*); +#elif __STDC__ +extern bool_t xdr_unixcred(XDR *, unixcred*); +#else /* Old Style C */ +bool_t xdr_unixcred(); +#endif /* Old Style C */ + + +struct getcredres { + keystatus status; + union { + unixcred cred; + } getcredres_u; +}; +typedef struct getcredres getcredres; +#ifdef __cplusplus +extern "C" bool_t xdr_getcredres(XDR *, getcredres*); +#elif __STDC__ +extern bool_t xdr_getcredres(XDR *, getcredres*); +#else /* Old Style C */ +bool_t xdr_getcredres(); +#endif /* Old Style C */ + + +struct key_netstarg { + keybuf st_priv_key; + keybuf st_pub_key; + netnamestr st_netname; +}; +typedef struct key_netstarg key_netstarg; +#ifdef __cplusplus +extern "C" bool_t xdr_key_netstarg(XDR *, key_netstarg*); +#elif __STDC__ +extern bool_t xdr_key_netstarg(XDR *, key_netstarg*); +#else /* Old Style C */ +bool_t xdr_key_netstarg(); +#endif /* Old Style C */ + + +struct key_netstres { + keystatus status; + union { + key_netstarg knet; + } key_netstres_u; +}; +typedef struct key_netstres key_netstres; +#ifdef __cplusplus +extern "C" bool_t xdr_key_netstres(XDR *, key_netstres*); +#elif __STDC__ +extern bool_t xdr_key_netstres(XDR *, key_netstres*); +#else /* Old Style C */ +bool_t xdr_key_netstres(); +#endif /* Old Style C */ + + +#ifndef opaque +#define opaque char +#endif + + +#define KEY_PROG ((u_long)100029) +#define KEY_VERS ((u_long)1) + +#ifdef __cplusplus +#define KEY_SET ((u_long)1) +extern "C" keystatus * key_set_1(opaque *, CLIENT *); +extern "C" keystatus * key_set_1_svc(opaque *, struct svc_req *); +#define KEY_ENCRYPT ((u_long)2) +extern "C" cryptkeyres * key_encrypt_1(cryptkeyarg *, CLIENT *); +extern "C" cryptkeyres * key_encrypt_1_svc(cryptkeyarg *, struct svc_req *); +#define KEY_DECRYPT ((u_long)3) +extern "C" cryptkeyres * key_decrypt_1(cryptkeyarg *, CLIENT *); +extern "C" cryptkeyres * key_decrypt_1_svc(cryptkeyarg *, struct svc_req *); +#define KEY_GEN ((u_long)4) +extern "C" des_block * key_gen_1(void *, CLIENT *); +extern "C" des_block * key_gen_1_svc(void *, struct svc_req *); +#define KEY_GETCRED ((u_long)5) +extern "C" getcredres * key_getcred_1(netnamestr *, CLIENT *); +extern "C" getcredres * key_getcred_1_svc(netnamestr *, struct svc_req *); + +#elif __STDC__ +#define KEY_SET ((u_long)1) +extern keystatus * key_set_1(opaque *, CLIENT *); +extern keystatus * key_set_1_svc(opaque *, struct svc_req *); +#define KEY_ENCRYPT ((u_long)2) +extern cryptkeyres * key_encrypt_1(cryptkeyarg *, CLIENT *); +extern cryptkeyres * key_encrypt_1_svc(cryptkeyarg *, struct svc_req *); +#define KEY_DECRYPT ((u_long)3) +extern cryptkeyres * key_decrypt_1(cryptkeyarg *, CLIENT *); +extern cryptkeyres * key_decrypt_1_svc(cryptkeyarg *, struct svc_req *); +#define KEY_GEN ((u_long)4) +extern des_block * key_gen_1(void *, CLIENT *); +extern des_block * key_gen_1_svc(void *, struct svc_req *); +#define KEY_GETCRED ((u_long)5) +extern getcredres * key_getcred_1(netnamestr *, CLIENT *); +extern getcredres * key_getcred_1_svc(netnamestr *, struct svc_req *); + +#else /* Old Style C */ +#define KEY_SET ((u_long)1) +extern keystatus * key_set_1(); +extern keystatus * key_set_1_svc(); +#define KEY_ENCRYPT ((u_long)2) +extern cryptkeyres * key_encrypt_1(); +extern cryptkeyres * key_encrypt_1_svc(); +#define KEY_DECRYPT ((u_long)3) +extern cryptkeyres * key_decrypt_1(); +extern cryptkeyres * key_decrypt_1_svc(); +#define KEY_GEN ((u_long)4) +extern des_block * key_gen_1(); +extern des_block * key_gen_1_svc(); +#define KEY_GETCRED ((u_long)5) +extern getcredres * key_getcred_1(); +extern getcredres * key_getcred_1_svc(); +#endif /* Old Style C */ +#define KEY_VERS2 ((u_long)2) + +#ifdef __cplusplus +extern "C" keystatus * key_set_2(opaque *, CLIENT *); +extern "C" keystatus * key_set_2_svc(opaque *, struct svc_req *); +extern "C" cryptkeyres * key_encrypt_2(cryptkeyarg *, CLIENT *); +extern "C" cryptkeyres * key_encrypt_2_svc(cryptkeyarg *, struct svc_req *); +extern "C" cryptkeyres * key_decrypt_2(cryptkeyarg *, CLIENT *); +extern "C" cryptkeyres * key_decrypt_2_svc(cryptkeyarg *, struct svc_req *); +extern "C" des_block * key_gen_2(void *, CLIENT *); +extern "C" des_block * key_gen_2_svc(void *, struct svc_req *); +extern "C" getcredres * key_getcred_2(netnamestr *, CLIENT *); +extern "C" getcredres * key_getcred_2_svc(netnamestr *, struct svc_req *); +#define KEY_ENCRYPT_PK ((u_long)6) +extern "C" cryptkeyres * key_encrypt_pk_2(cryptkeyarg2 *, CLIENT *); +extern "C" cryptkeyres * key_encrypt_pk_2_svc(cryptkeyarg2 *, struct svc_req *); +#define KEY_DECRYPT_PK ((u_long)7) +extern "C" cryptkeyres * key_decrypt_pk_2(cryptkeyarg2 *, CLIENT *); +extern "C" cryptkeyres * key_decrypt_pk_2_svc(cryptkeyarg2 *, struct svc_req *); +#define KEY_NET_PUT ((u_long)8) +extern "C" keystatus * key_net_put_2(key_netstarg *, CLIENT *); +extern "C" keystatus * key_net_put_2_svc(key_netstarg *, struct svc_req *); +#define KEY_NET_GET ((u_long)9) +extern "C" key_netstres * key_net_get_2(void *, CLIENT *); +extern "C" key_netstres * key_net_get_2_svc(void *, struct svc_req *); +#define KEY_GET_CONV ((u_long)10) +extern "C" cryptkeyres * key_get_conv_2(opaque *, CLIENT *); +extern "C" cryptkeyres * key_get_conv_2_svc(opaque *, struct svc_req *); + +#elif __STDC__ +extern keystatus * key_set_2(opaque *, CLIENT *); +extern keystatus * key_set_2_svc(opaque *, struct svc_req *); +extern cryptkeyres * key_encrypt_2(cryptkeyarg *, CLIENT *); +extern cryptkeyres * key_encrypt_2_svc(cryptkeyarg *, struct svc_req *); +extern cryptkeyres * key_decrypt_2(cryptkeyarg *, CLIENT *); +extern cryptkeyres * key_decrypt_2_svc(cryptkeyarg *, struct svc_req *); +extern des_block * key_gen_2(void *, CLIENT *); +extern des_block * key_gen_2_svc(void *, struct svc_req *); +extern getcredres * key_getcred_2(netnamestr *, CLIENT *); +extern getcredres * key_getcred_2_svc(netnamestr *, struct svc_req *); +#define KEY_ENCRYPT_PK ((u_long)6) +extern cryptkeyres * key_encrypt_pk_2(cryptkeyarg2 *, CLIENT *); +extern cryptkeyres * key_encrypt_pk_2_svc(cryptkeyarg2 *, struct svc_req *); +#define KEY_DECRYPT_PK ((u_long)7) +extern cryptkeyres * key_decrypt_pk_2(cryptkeyarg2 *, CLIENT *); +extern cryptkeyres * key_decrypt_pk_2_svc(cryptkeyarg2 *, struct svc_req *); +#define KEY_NET_PUT ((u_long)8) +extern keystatus * key_net_put_2(key_netstarg *, CLIENT *); +extern keystatus * key_net_put_2_svc(key_netstarg *, struct svc_req *); +#define KEY_NET_GET ((u_long)9) +extern key_netstres * key_net_get_2(void *, CLIENT *); +extern key_netstres * key_net_get_2_svc(void *, struct svc_req *); +#define KEY_GET_CONV ((u_long)10) +extern cryptkeyres * key_get_conv_2(opaque *, CLIENT *); +extern cryptkeyres * key_get_conv_2_svc(opaque *, struct svc_req *); + +#else /* Old Style C */ +extern keystatus * key_set_2(); +extern keystatus * key_set_2_svc(); +extern cryptkeyres * key_encrypt_2(); +extern cryptkeyres * key_encrypt_2_svc(); +extern cryptkeyres * key_decrypt_2(); +extern cryptkeyres * key_decrypt_2_svc(); +extern des_block * key_gen_2(); +extern des_block * key_gen_2_svc(); +extern getcredres * key_getcred_2(); +extern getcredres * key_getcred_2_svc(); +#define KEY_ENCRYPT_PK ((u_long)6) +extern cryptkeyres * key_encrypt_pk_2(); +extern cryptkeyres * key_encrypt_pk_2_svc(); +#define KEY_DECRYPT_PK ((u_long)7) +extern cryptkeyres * key_decrypt_pk_2(); +extern cryptkeyres * key_decrypt_pk_2_svc(); +#define KEY_NET_PUT ((u_long)8) +extern keystatus * key_net_put_2(); +extern keystatus * key_net_put_2_svc(); +#define KEY_NET_GET ((u_long)9) +extern key_netstres * key_net_get_2(); +extern key_netstres * key_net_get_2_svc(); +#define KEY_GET_CONV ((u_long)10) +extern cryptkeyres * key_get_conv_2(); +extern cryptkeyres * key_get_conv_2_svc(); +#endif /* Old Style C */ + +#endif /* !_KEY_PROT_H_RPCGEN */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/rpc/netdb.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/rpc/netdb.h new file mode 100644 index 00000000..e9a6565a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/rpc/netdb.h @@ -0,0 +1,79 @@ +/* @(#)netdb.h 2.1 88/07/29 3.9 RPCSRC */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +/* @(#)rpc.h 1.8 87/07/24 SMI */ + +/* Cleaned up for GNU C library roland@gnu.ai.mit.edu: + added multiple inclusion protection and use of . + In GNU this file is #include'd by . */ + +#ifndef _RPC_NETDB_H +#define _RPC_NETDB_H 1 + +#include + +#define __need_size_t +#include + +__BEGIN_DECLS + +struct rpcent +{ + char *r_name; /* Name of server for this rpc program. */ + char **r_aliases; /* Alias list. */ + int r_number; /* RPC program number. */ +}; + +extern void setrpcent (int __stayopen) __THROW; +libc_hidden_proto(setrpcent) +extern void endrpcent (void) __THROW; +libc_hidden_proto(endrpcent) +extern struct rpcent *getrpcbyname (__const char *__name) __THROW; +libc_hidden_proto(getrpcbyname) +extern struct rpcent *getrpcbynumber (int __number) __THROW; +libc_hidden_proto(getrpcbynumber) +extern struct rpcent *getrpcent (void) __THROW; +libc_hidden_proto(getrpcent) + +#if defined __USE_MISC && defined __UCLIBC_HAS_REENTRANT_RPC__ +extern int getrpcbyname_r (__const char *__name, struct rpcent *__result_buf, + char *__buffer, size_t __buflen, + struct rpcent **__result) __THROW; + +extern int getrpcbynumber_r (int __number, struct rpcent *__result_buf, + char *__buffer, size_t __buflen, + struct rpcent **__result) __THROW; + +extern int getrpcent_r (struct rpcent *__result_buf, char *__buffer, + size_t __buflen, struct rpcent **__result) __THROW; +#endif + +__END_DECLS + +#endif /* rpc/netdb.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/rpc/pmap_clnt.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/rpc/pmap_clnt.h new file mode 100644 index 00000000..f5e825d6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/rpc/pmap_clnt.h @@ -0,0 +1,101 @@ +/* @(#)pmap_clnt.h 2.1 88/07/29 4.0 RPCSRC; from 1.11 88/02/08 SMI */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +/* + * pmap_clnt.h + * Supplies C routines to get to portmap services. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +#ifndef _RPC_PMAP_CLNT_H +#define _RPC_PMAP_CLNT_H 1 + +#include +#include +#include +#include + +__BEGIN_DECLS + +typedef bool_t (*resultproc_t) (caddr_t resp, struct sockaddr_in *raddr); + +/* + * Usage: + * success = pmap_set(program, version, protocol, port); + * success = pmap_unset(program, version); + * port = pmap_getport(address, program, version, protocol); + * head = pmap_getmaps(address); + * clnt_stat = pmap_rmtcall(address, program, version, procedure, + * xdrargs, argsp, xdrres, resp, tout, port_ptr) + * (works for udp only.) + * clnt_stat = clnt_broadcast(program, version, procedure, + * xdrargs, argsp, xdrres, resp, eachresult) + * (like pmap_rmtcall, except the call is broadcasted to all + * locally connected nets. For each valid response received, + * the procedure eachresult is called. Its form is: + * done = eachresult(resp, raddr) + * bool_t done; + * caddr_t resp; + * struct sockaddr_in raddr; + * where resp points to the results of the call and raddr is the + * address if the responder to the broadcast. + */ + +extern bool_t pmap_set (__const u_long __program, __const u_long __vers, + int __protocol, u_short __port) __THROW; +libc_hidden_proto(pmap_set) +extern bool_t pmap_unset (__const u_long __program, __const u_long __vers) + __THROW; +libc_hidden_proto(pmap_unset) +extern struct pmaplist *pmap_getmaps (struct sockaddr_in *__address) __THROW; +extern enum clnt_stat pmap_rmtcall (struct sockaddr_in *__addr, + __const u_long __prog, + __const u_long __vers, + __const u_long __proc, + xdrproc_t __xdrargs, + caddr_t __argsp, xdrproc_t __xdrres, + caddr_t __resp, struct timeval __tout, + u_long *__port_ptr) __THROW; +extern enum clnt_stat clnt_broadcast (__const u_long __prog, + __const u_long __vers, + __const u_long __proc, xdrproc_t __xargs, + caddr_t __argsp, xdrproc_t __xresults, + caddr_t __resultsp, + resultproc_t __eachresult) __THROW; +extern u_short pmap_getport (struct sockaddr_in *__address, + __const u_long __program, + __const u_long __version, u_int __protocol) + __THROW; +libc_hidden_proto(pmap_getport) + +__END_DECLS + +#endif /* rpc/pmap_clnt.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/rpc/pmap_prot.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/rpc/pmap_prot.h new file mode 100644 index 00000000..30b26709 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/rpc/pmap_prot.h @@ -0,0 +1,110 @@ +/* @(#)pmap_prot.h 2.1 88/07/29 4.0 RPCSRC; from 1.14 88/02/08 SMI */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +/* + * pmap_prot.h + * Protocol for the local binder service, or pmap. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +#ifndef _RPC_PMAP_PROT_H +#define _RPC_PMAP_PROT_H 1 + +#include + +#include + +__BEGIN_DECLS + +/* The following procedures are supported by the protocol: + * + * PMAPPROC_NULL() returns () + * takes nothing, returns nothing + * + * PMAPPROC_SET(struct pmap) returns (bool_t) + * TRUE is success, FALSE is failure. Registers the tuple + * [prog, vers, prot, port]. + * + * PMAPPROC_UNSET(struct pmap) returns (bool_t) + * TRUE is success, FALSE is failure. Un-registers pair + * [prog, vers]. prot and port are ignored. + * + * PMAPPROC_GETPORT(struct pmap) returns (long unsigned). + * 0 is failure. Otherwise returns the port number where the pair + * [prog, vers] is registered. It may lie! + * + * PMAPPROC_DUMP() RETURNS (struct pmaplist *) + * + * PMAPPROC_CALLIT(unsigned, unsigned, unsigned, string<>) + * RETURNS (port, string<>); + * usage: encapsulatedresults = PMAPPROC_CALLIT(prog, vers, proc, encapsulatedargs); + * Calls the procedure on the local machine. If it is not registered, + * this procedure is quite; ie it does not return error information!!! + * This procedure only is supported on rpc/udp and calls via + * rpc/udp. This routine only passes null authentication parameters. + * This file has no interface to xdr routines for PMAPPROC_CALLIT. + * + * The service supports remote procedure calls on udp/ip or tcp/ip socket 111. + */ + +#define PMAPPORT ((u_short)111) +#define PMAPPROG ((u_long)100000) +#define PMAPVERS ((u_long)2) +#define PMAPVERS_PROTO ((u_long)2) +#define PMAPVERS_ORIG ((u_long)1) +#define PMAPPROC_NULL ((u_long)0) +#define PMAPPROC_SET ((u_long)1) +#define PMAPPROC_UNSET ((u_long)2) +#define PMAPPROC_GETPORT ((u_long)3) +#define PMAPPROC_DUMP ((u_long)4) +#define PMAPPROC_CALLIT ((u_long)5) + +struct pmap { + long unsigned pm_prog; + long unsigned pm_vers; + long unsigned pm_prot; + long unsigned pm_port; +}; + +extern bool_t xdr_pmap (XDR *__xdrs, struct pmap *__regs) __THROW; +libc_hidden_proto(xdr_pmap) + +struct pmaplist { + struct pmap pml_map; + struct pmaplist *pml_next; +}; + +extern bool_t xdr_pmaplist (XDR *__xdrs, struct pmaplist **__rp) __THROW; +libc_hidden_proto(xdr_pmaplist) + +__END_DECLS + +#endif /* rpc/pmap_prot.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/rpc/pmap_rmt.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/rpc/pmap_rmt.h new file mode 100644 index 00000000..59b4f658 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/rpc/pmap_rmt.h @@ -0,0 +1,71 @@ +/* @(#)pmap_rmt.h 2.1 88/07/29 4.0 RPCSRC; from 1.2 88/02/08 SMI */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +/* + * Structures and XDR routines for parameters to and replies from + * the portmapper remote-call-service. + * + * Copyright (C) 1986, Sun Microsystems, Inc. + */ + +#ifndef _RPC_PMAP_RMT_H +#define _RPC_PMAP_RMT_H 1 + +#include +#include +#include +#include + +__BEGIN_DECLS + +struct rmtcallargs { + u_long prog, vers, proc, arglen; + caddr_t args_ptr; + xdrproc_t xdr_args; +}; + +extern bool_t xdr_rmtcall_args (XDR *__xdrs, struct rmtcallargs *__crp) + __THROW; +libc_hidden_proto(xdr_rmtcall_args) + + +struct rmtcallres { + u_long *port_ptr; + u_long resultslen; + caddr_t results_ptr; + xdrproc_t xdr_results; +}; + +extern bool_t xdr_rmtcallres (XDR *__xdrs, struct rmtcallres *__crp) __THROW; +libc_hidden_proto(xdr_rmtcallres) + +__END_DECLS + +#endif /* rpc/pmap_rmt.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/rpc/rpc.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/rpc/rpc.h new file mode 100644 index 00000000..abcab9e2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/rpc/rpc.h @@ -0,0 +1,119 @@ +/* @(#)rpc.h 2.3 88/08/10 4.0 RPCSRC; from 1.9 88/02/08 SMI */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +/* + * rpc.h, Just includes the billions of rpc header files necessary to + * do remote procedure calling. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +#ifndef _RPC_RPC_H +#define _RPC_RPC_H 1 + +#ifdef _LIBC +/* Some adjustments to make the libc source from glibc + * compile more easily with uClibc... */ +#ifndef __FORCE_GLIBC +#define __FORCE_GLIBC +#endif +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif +#define _(X) X +#include +#endif + +#include /* some typedefs */ +#include + +/* external data representation interfaces */ +#include /* generic (de)serializer */ + +/* Client side only authentication */ +#include /* generic authenticator (client side) */ + +/* Client side (mostly) remote procedure call */ +#include /* generic rpc stuff */ + +/* semi-private protocol headers */ +#include /* protocol for rpc messages */ +#include /* protocol for unix style cred */ +#include /* protocol for des style cred */ + +/* Server side only remote procedure callee */ +#include /* service manager and multiplexer */ +#include /* service side authenticator */ + +/* + * COMMENT OUT THE NEXT INCLUDE IF RUNNING ON SUN OS OR ON A VERSION + * OF UNIX BASED ON NFSSRC. These systems will already have the structures + * defined by included in . + */ +/* routines for parsing /etc/rpc */ +#include /* structures and routines to parse /etc/rpc */ + +__BEGIN_DECLS + +/* Global variables, protected for multi-threaded applications. */ +extern fd_set *__rpc_thread_svc_fdset (void) __attribute__ ((__const__)); +libc_hidden_proto(__rpc_thread_svc_fdset) +#define svc_fdset (*__rpc_thread_svc_fdset ()) + +extern struct rpc_createerr *__rpc_thread_createerr (void) + __attribute__ ((__const__)); +libc_hidden_proto(__rpc_thread_createerr) +#define get_rpc_createerr() (*__rpc_thread_createerr ()) +/* The people who "engineered" RPC should bee punished for naming the + data structure and the variable the same. We cannot always define the + macro 'rpc_createerr' because this would prevent people from defining + object of type 'struct rpc_createerr'. So we leave it up to the user + to select transparent replacement also of this variable. */ +#ifdef _RPC_MT_VARS +# define rpc_createerr (*__rpc_thread_createerr ()) +#endif + +extern struct pollfd **__rpc_thread_svc_pollfd (void) + __attribute__ ((__const__)); +libc_hidden_proto(__rpc_thread_svc_pollfd) +#define svc_pollfd (*__rpc_thread_svc_pollfd ()) + +extern int *__rpc_thread_svc_max_pollfd (void) __attribute__ ((__const__)); +libc_hidden_proto(__rpc_thread_svc_max_pollfd) +#define svc_max_pollfd (*__rpc_thread_svc_max_pollfd ()) + +extern bool_t xdr_accepted_reply (XDR *xdrs, struct accepted_reply *ar); +libc_hidden_proto(xdr_accepted_reply) +extern bool_t xdr_rejected_reply (XDR *xdrs, struct rejected_reply *rr); +libc_hidden_proto(xdr_rejected_reply) + +__END_DECLS + +#endif /* rpc/rpc.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/rpc/rpc_des.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/rpc/rpc_des.h new file mode 100644 index 00000000..96e53698 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/rpc/rpc_des.h @@ -0,0 +1,72 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +/* + * Generic DES driver interface + * Keep this file hardware independent! + * Copyright (c) 1986 by Sun Microsystems, Inc. + */ + +#ifndef _DES_H +#define _DES_H + +#include + +#define DES_MAXLEN 65536 /* maximum # of bytes to encrypt */ +#define DES_QUICKLEN 16 /* maximum # of bytes to encrypt quickly */ + +enum desdir + { + ENCRYPT, DECRYPT + }; +enum desmode + { + CBC, ECB + }; + +/* + * parameters to ioctl call + */ +struct desparams + { + u_char des_key[8]; /* key (with low bit parity) */ + enum desdir des_dir; /* direction */ + enum desmode des_mode; /* mode */ + u_char des_ivec[8]; /* input vector */ + unsigned des_len; /* number of bytes to crypt */ + union + { + u_char UDES_data[DES_QUICKLEN]; + u_char *UDES_buf; + } + UDES; +#define des_data UDES.UDES_data /* direct data here if quick */ +#define des_buf UDES.UDES_buf /* otherwise, pointer to data */ + }; + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/rpc/rpc_msg.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/rpc/rpc_msg.h new file mode 100644 index 00000000..c848b39c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/rpc/rpc_msg.h @@ -0,0 +1,206 @@ +/* @(#)rpc_msg.h 2.1 88/07/29 4.0 RPCSRC */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +/* @(#)rpc_msg.h 1.7 86/07/16 SMI */ + +#ifndef _RPC_MSG_H +#define _RPC_MSG_H 1 + +#include + +#include +#include + +/* + * rpc_msg.h + * rpc message definition + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +#define RPC_MSG_VERSION ((u_long) 2) +#define RPC_SERVICE_PORT ((u_short) 2048) + +__BEGIN_DECLS + +/* + * Bottom up definition of an rpc message. + * NOTE: call and reply use the same overall struct but + * different parts of unions within it. + */ + +enum msg_type { + CALL=0, + REPLY=1 +}; + +enum reply_stat { + MSG_ACCEPTED=0, + MSG_DENIED=1 +}; + +enum accept_stat { + SUCCESS=0, + PROG_UNAVAIL=1, + PROG_MISMATCH=2, + PROC_UNAVAIL=3, + GARBAGE_ARGS=4, + SYSTEM_ERR=5 +}; + +enum reject_stat { + RPC_MISMATCH=0, + AUTH_ERROR=1 +}; + +/* + * Reply part of an rpc exchange + */ + +/* + * Reply to an rpc request that was accepted by the server. + * Note: there could be an error even though the request was + * accepted. + */ +struct accepted_reply { + struct opaque_auth ar_verf; + enum accept_stat ar_stat; + union { + struct { + u_long low; + u_long high; + } AR_versions; + struct { + caddr_t where; + xdrproc_t proc; + } AR_results; + /* and many other null cases */ + } ru; +#define ar_results ru.AR_results +#define ar_vers ru.AR_versions +}; + +/* + * Reply to an rpc request that was rejected by the server. + */ +struct rejected_reply { + enum reject_stat rj_stat; + union { + struct { + u_long low; + u_long high; + } RJ_versions; + enum auth_stat RJ_why; /* why authentication did not work */ + } ru; +#define rj_vers ru.RJ_versions +#define rj_why ru.RJ_why +}; + +/* + * Body of a reply to an rpc request. + */ +struct reply_body { + enum reply_stat rp_stat; + union { + struct accepted_reply RP_ar; + struct rejected_reply RP_dr; + } ru; +#define rp_acpt ru.RP_ar +#define rp_rjct ru.RP_dr +}; + +/* + * Body of an rpc request call. + */ +struct call_body { + u_long cb_rpcvers; /* must be equal to two */ + u_long cb_prog; + u_long cb_vers; + u_long cb_proc; + struct opaque_auth cb_cred; + struct opaque_auth cb_verf; /* protocol specific - provided by client */ +}; + +/* + * The rpc message + */ +struct rpc_msg { + u_long rm_xid; + enum msg_type rm_direction; + union { + struct call_body RM_cmb; + struct reply_body RM_rmb; + } ru; +#define rm_call ru.RM_cmb +#define rm_reply ru.RM_rmb +}; +#define acpted_rply ru.RM_rmb.ru.RP_ar +#define rjcted_rply ru.RM_rmb.ru.RP_dr + + +/* + * XDR routine to handle a rpc message. + * xdr_callmsg(xdrs, cmsg) + * XDR *xdrs; + * struct rpc_msg *cmsg; + */ +extern bool_t xdr_callmsg (XDR *__xdrs, struct rpc_msg *__cmsg) __THROW; +libc_hidden_proto(xdr_callmsg) + +/* + * XDR routine to pre-serialize the static part of a rpc message. + * xdr_callhdr(xdrs, cmsg) + * XDR *xdrs; + * struct rpc_msg *cmsg; + */ +extern bool_t xdr_callhdr (XDR *__xdrs, struct rpc_msg *__cmsg) __THROW; +libc_hidden_proto(xdr_callhdr) + +/* + * XDR routine to handle a rpc reply. + * xdr_replymsg(xdrs, rmsg) + * XDR *xdrs; + * struct rpc_msg *rmsg; + */ +extern bool_t xdr_replymsg (XDR *__xdrs, struct rpc_msg *__rmsg) __THROW; +libc_hidden_proto(xdr_replymsg) + +/* + * Fills in the error part of a reply message. + * _seterr_reply(msg, error) + * struct rpc_msg *msg; + * struct rpc_err *error; + */ +extern void _seterr_reply (struct rpc_msg *__msg, struct rpc_err *__error) + __THROW; +libc_hidden_proto(_seterr_reply) + +__END_DECLS + +#endif /* rpc/rpc_msg.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/rpc/svc.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/rpc/svc.h new file mode 100644 index 00000000..68983254 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/rpc/svc.h @@ -0,0 +1,330 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +/* + * svc.h, Server-side remote procedure call interface. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +#ifndef _RPC_SVC_H +#define _RPC_SVC_H 1 + +#include +#include + +__BEGIN_DECLS + +/* + * This interface must manage two items concerning remote procedure calling: + * + * 1) An arbitrary number of transport connections upon which rpc requests + * are received. The two most notable transports are TCP and UDP; they are + * created and registered by routines in svc_tcp.c and svc_udp.c, respectively; + * they in turn call xprt_register and xprt_unregister. + * + * 2) An arbitrary number of locally registered services. Services are + * described by the following four data: program number, version number, + * "service dispatch" function, a transport handle, and a boolean that + * indicates whether or not the exported program should be registered with a + * local binder service; if true the program's number and version and the + * port number from the transport handle are registered with the binder. + * These data are registered with the rpc svc system via svc_register. + * + * A service's dispatch function is called whenever an rpc request comes in + * on a transport. The request's program and version numbers must match + * those of the registered service. The dispatch function is passed two + * parameters, struct svc_req * and SVCXPRT *, defined below. + */ + +enum xprt_stat { + XPRT_DIED, + XPRT_MOREREQS, + XPRT_IDLE +}; + +/* + * Server side transport handle + */ +typedef struct SVCXPRT SVCXPRT; +struct SVCXPRT { + int xp_sock; + u_short xp_port; /* associated port number */ + const struct xp_ops { + bool_t (*xp_recv) (SVCXPRT *__xprt, struct rpc_msg *__msg); + /* receive incoming requests */ + enum xprt_stat (*xp_stat) (SVCXPRT *__xprt); + /* get transport status */ + bool_t (*xp_getargs) (SVCXPRT *__xprt, xdrproc_t __xdr_args, + caddr_t args_ptr); /* get arguments */ + bool_t (*xp_reply) (SVCXPRT *__xprt, struct rpc_msg *__msg); + /* send reply */ + bool_t (*xp_freeargs) (SVCXPRT *__xprt, xdrproc_t __xdr_args, + caddr_t args_ptr); + /* free mem allocated for args */ + void (*xp_destroy) (SVCXPRT *__xprt); + /* destroy this struct */ + } *xp_ops; + int xp_addrlen; /* length of remote address */ + struct sockaddr_in xp_raddr; /* remote address */ + struct opaque_auth xp_verf; /* raw response verifier */ + caddr_t xp_p1; /* private */ + caddr_t xp_p2; /* private */ + char xp_pad [256]; /* padding, internal use */ +}; + +/* + * Approved way of getting address of caller + */ +#define svc_getcaller(x) (&(x)->xp_raddr) + +/* + * Operations defined on an SVCXPRT handle + * + * SVCXPRT *xprt; + * struct rpc_msg *msg; + * xdrproc_t xargs; + * caddr_t argsp; + */ +#define SVC_RECV(xprt, msg) \ + (*(xprt)->xp_ops->xp_recv)((xprt), (msg)) +#define svc_recv(xprt, msg) \ + (*(xprt)->xp_ops->xp_recv)((xprt), (msg)) + +#define SVC_STAT(xprt) \ + (*(xprt)->xp_ops->xp_stat)(xprt) +#define svc_stat(xprt) \ + (*(xprt)->xp_ops->xp_stat)(xprt) + +#define SVC_GETARGS(xprt, xargs, argsp) \ + (*(xprt)->xp_ops->xp_getargs)((xprt), (xargs), (argsp)) +#define svc_getargs(xprt, xargs, argsp) \ + (*(xprt)->xp_ops->xp_getargs)((xprt), (xargs), (argsp)) + +#define SVC_REPLY(xprt, msg) \ + (*(xprt)->xp_ops->xp_reply) ((xprt), (msg)) +#define svc_reply(xprt, msg) \ + (*(xprt)->xp_ops->xp_reply) ((xprt), (msg)) + +#define SVC_FREEARGS(xprt, xargs, argsp) \ + (*(xprt)->xp_ops->xp_freeargs)((xprt), (xargs), (argsp)) +#define svc_freeargs(xprt, xargs, argsp) \ + (*(xprt)->xp_ops->xp_freeargs)((xprt), (xargs), (argsp)) + +#define SVC_DESTROY(xprt) \ + (*(xprt)->xp_ops->xp_destroy)(xprt) +#define svc_destroy(xprt) \ + (*(xprt)->xp_ops->xp_destroy)(xprt) + + +/* + * Service request + */ +struct svc_req { + rpcprog_t rq_prog; /* service program number */ + rpcvers_t rq_vers; /* service protocol version */ + rpcproc_t rq_proc; /* the desired procedure */ + struct opaque_auth rq_cred; /* raw creds from the wire */ + caddr_t rq_clntcred; /* read only cooked cred */ + SVCXPRT *rq_xprt; /* associated transport */ +}; + +#ifndef __DISPATCH_FN_T +#define __DISPATCH_FN_T +typedef void (*__dispatch_fn_t) (struct svc_req*, SVCXPRT*); +#endif + +/* + * Service registration + * + * svc_register(xprt, prog, vers, dispatch, protocol) + * SVCXPRT *xprt; + * rpcprog_t prog; + * rpcvers_t vers; + * void (*dispatch)(struct svc_req*, SVCXPRT*); + * rpcprot_t protocol; like TCP or UDP, zero means do not register + */ +extern bool_t svc_register (SVCXPRT *__xprt, rpcprog_t __prog, + rpcvers_t __vers, __dispatch_fn_t __dispatch, + rpcprot_t __protocol) __THROW; +libc_hidden_proto(svc_register) + +/* + * Service un-registration + * + * svc_unregister(prog, vers) + * rpcprog_t prog; + * rpcvers_t vers; + */ +extern void svc_unregister (rpcprog_t __prog, rpcvers_t __vers) __THROW; +libc_hidden_proto(svc_unregister) + +/* + * Transport registration. + * + * xprt_register(xprt) + * SVCXPRT *xprt; + */ +extern void xprt_register (SVCXPRT *__xprt) __THROW; +libc_hidden_proto(xprt_register) + +/* + * Transport un-register + * + * xprt_unregister(xprt) + * SVCXPRT *xprt; + */ +extern void xprt_unregister (SVCXPRT *__xprt) __THROW; +libc_hidden_proto(xprt_unregister) + +/* + * When the service routine is called, it must first check to see if it + * knows about the procedure; if not, it should call svcerr_noproc + * and return. If so, it should deserialize its arguments via + * SVC_GETARGS (defined above). If the deserialization does not work, + * svcerr_decode should be called followed by a return. Successful + * decoding of the arguments should be followed the execution of the + * procedure's code and a call to svc_sendreply. + * + * Also, if the service refuses to execute the procedure due to too- + * weak authentication parameters, svcerr_weakauth should be called. + * Note: do not confuse access-control failure with weak authentication! + * + * NB: In pure implementations of rpc, the caller always waits for a reply + * msg. This message is sent when svc_sendreply is called. + * Therefore pure service implementations should always call + * svc_sendreply even if the function logically returns void; use + * xdr.h - xdr_void for the xdr routine. HOWEVER, tcp based rpc allows + * for the abuse of pure rpc via batched calling or pipelining. In the + * case of a batched call, svc_sendreply should NOT be called since + * this would send a return message, which is what batching tries to avoid. + * It is the service/protocol writer's responsibility to know which calls are + * batched and which are not. Warning: responding to batch calls may + * deadlock the caller and server processes! + */ + +extern bool_t svc_sendreply (SVCXPRT *xprt, xdrproc_t __xdr_results, + caddr_t __xdr_location) __THROW; +libc_hidden_proto(svc_sendreply) + +extern void svcerr_decode (SVCXPRT *__xprt) __THROW; +libc_hidden_proto(svcerr_decode) + +extern void svcerr_weakauth (SVCXPRT *__xprt) __THROW; + +extern void svcerr_noproc (SVCXPRT *__xprt) __THROW; + +extern void svcerr_progvers (SVCXPRT *__xprt, rpcvers_t __low_vers, + rpcvers_t __high_vers) __THROW; +libc_hidden_proto(svcerr_progvers) + +extern void svcerr_auth (SVCXPRT *__xprt, enum auth_stat __why) __THROW; +libc_hidden_proto(svcerr_auth) + +extern void svcerr_noprog (SVCXPRT *__xprt) __THROW; +libc_hidden_proto(svcerr_noprog) + +extern void svcerr_systemerr (SVCXPRT *__xprt) __THROW; + +/* + * Lowest level dispatching -OR- who owns this process anyway. + * Somebody has to wait for incoming requests and then call the correct + * service routine. The routine svc_run does infinite waiting; i.e., + * svc_run never returns. + * Since another (coexistent) package may wish to selectively wait for + * incoming calls or other events outside of the rpc architecture, the + * routine svc_getreq is provided. It must be passed readfds, the + * "in-place" results of a select system call (see select, section 2). + */ + +/* + * Global keeper of rpc service descriptors in use + * dynamic; must be inspected before each call to select + */ + +extern struct pollfd *svc_pollfd; +extern int svc_max_pollfd; +extern fd_set svc_fdset; +#define svc_fds svc_fdset.fds_bits[0] /* compatibility */ + +/* + * a small program implemented by the svc_rpc implementation itself; + * also see clnt.h for protocol numbers. + */ +extern void svc_getreq (int __rdfds) __THROW; +libc_hidden_proto(svc_getreq) +extern void svc_getreq_common (const int __fd) __THROW; +libc_hidden_proto(svc_getreq_common) +extern void svc_getreqset (fd_set *__readfds) __THROW; +libc_hidden_proto(svc_getreqset) +extern void svc_getreq_poll (struct pollfd *, const int) __THROW; +libc_hidden_proto(svc_getreq_poll) +extern void svc_exit (void) __THROW; +extern void svc_run (void) __THROW; + +/* + * Socket to use on svcxxx_create call to get default socket + */ +#define RPC_ANYSOCK -1 + +/* + * These are the existing service side transport implementations + */ + +/* + * Memory based rpc for testing and timing. + */ +extern SVCXPRT *svcraw_create (void) __THROW; + +/* + * Udp based rpc. + */ +extern SVCXPRT *svcudp_create (int __sock) __THROW; +libc_hidden_proto(svcudp_create) +extern SVCXPRT *svcudp_bufcreate (int __sock, u_int __sendsz, u_int __recvsz) + __THROW; +libc_hidden_proto(svcudp_bufcreate) + +/* + * Tcp based rpc. + */ +extern SVCXPRT *svctcp_create (int __sock, u_int __sendsize, u_int __recvsize) + __THROW; + + +/* + * Unix based rpc. + */ +extern SVCXPRT *svcunix_create (int __sock, u_int __sendsize, u_int __recvsize, + char *__path) __THROW; + + +__END_DECLS + +#endif /* rpc/svc.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/rpc/svc_auth.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/rpc/svc_auth.h new file mode 100644 index 00000000..834e3c92 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/rpc/svc_auth.h @@ -0,0 +1,55 @@ +/* @(#)svc_auth.h 2.1 88/07/29 4.0 RPCSRC */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +/* @(#)svc_auth.h 1.6 86/07/16 SMI */ + +/* + * svc_auth.h, Service side of rpc authentication. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +#ifndef _RPC_SVC_AUTH_H +#define _RPC_SVC_AUTH_H 1 + +#include +#include + +__BEGIN_DECLS + +/* + * Server side authenticator + */ +extern enum auth_stat _authenticate (struct svc_req *__rqst, + struct rpc_msg *__msg) __THROW; +libc_hidden_proto(_authenticate) + +__END_DECLS + +#endif /* rpc/svc_auth.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/rpc/types.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/rpc/types.h new file mode 100644 index 00000000..05f49c33 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/rpc/types.h @@ -0,0 +1,108 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +/* fixincludes should not add extern "C" to this file */ +/* + * Rpc additions to + */ +#ifndef _RPC_TYPES_H +#define _RPC_TYPES_H 1 + +#ifdef _LIBC +/* Some adjustments to make the libc source from glibc + * compile more easily with uClibc... */ +#ifndef __FORCE_GLIBC +#define __FORCE_GLIBC +#endif +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif +#define _(X) X +#endif +#include + +typedef int bool_t; +typedef int enum_t; +/* This needs to be changed to uint32_t in the future */ +typedef unsigned long rpcprog_t; +typedef unsigned long rpcvers_t; +typedef unsigned long rpcproc_t; +typedef unsigned long rpcprot_t; +typedef unsigned long rpcport_t; + +#define __dontcare__ -1 + +#ifndef FALSE +# define FALSE (0) +#endif + +#ifndef TRUE +# define TRUE (1) +#endif + +#ifndef NULL +# define NULL 0 +#endif + +#include /* For malloc decl. */ +#define mem_alloc(bsize) malloc(bsize) +#define mem_free(ptr, bsize) free(ptr) + +#ifndef makedev /* ie, we haven't already included it */ +#include +#endif + +#ifndef __u_char_defined +typedef __u_char u_char; +typedef __u_short u_short; +typedef __u_int u_int; +typedef __u_long u_long; +typedef __quad_t quad_t; +typedef __u_quad_t u_quad_t; +typedef __fsid_t fsid_t; +# define __u_char_defined +#endif +#ifndef __daddr_t_defined +typedef __daddr_t daddr_t; +typedef __caddr_t caddr_t; +# define __daddr_t_defined +#endif + +#include +#include + +#include + +#ifndef INADDR_LOOPBACK +#define INADDR_LOOPBACK (u_long)0x7F000001 +#endif +#ifndef MAXHOSTNAMELEN +#define MAXHOSTNAMELEN 64 +#endif + +#endif /* rpc/types.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/rpc/xdr.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/rpc/xdr.h new file mode 100644 index 00000000..9981e3ad --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/rpc/xdr.h @@ -0,0 +1,407 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +/* + * xdr.h, External Data Representation Serialization Routines. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +#ifndef _RPC_XDR_H +#define _RPC_XDR_H 1 + +#ifdef _LIBC +/* Some adjustments to make the libc source from glibc + * compile more easily with uClibc... */ +# ifndef __FORCE_GLIBC +# define __FORCE_GLIBC +# endif +# define _(X) X +#endif +#include +#include +#include + +/* We need FILE. */ +#include + +__BEGIN_DECLS + +/* + * XDR provides a conventional way for converting between C data + * types and an external bit-string representation. Library supplied + * routines provide for the conversion on built-in C data types. These + * routines and utility routines defined here are used to help implement + * a type encode/decode routine for each user-defined type. + * + * Each data type provides a single procedure which takes two arguments: + * + * bool_t + * xdrproc(xdrs, argresp) + * XDR *xdrs; + * *argresp; + * + * xdrs is an instance of a XDR handle, to which or from which the data + * type is to be converted. argresp is a pointer to the structure to be + * converted. The XDR handle contains an operation field which indicates + * which of the operations (ENCODE, DECODE * or FREE) is to be performed. + * + * XDR_DECODE may allocate space if the pointer argresp is null. This + * data can be freed with the XDR_FREE operation. + * + * We write only one procedure per data type to make it easy + * to keep the encode and decode procedures for a data type consistent. + * In many cases the same code performs all operations on a user defined type, + * because all the hard work is done in the component type routines. + * decode as a series of calls on the nested data types. + */ + +/* + * Xdr operations. XDR_ENCODE causes the type to be encoded into the + * stream. XDR_DECODE causes the type to be extracted from the stream. + * XDR_FREE can be used to release the space allocated by an XDR_DECODE + * request. + */ +enum xdr_op { + XDR_ENCODE = 0, + XDR_DECODE = 1, + XDR_FREE = 2 +}; + +/* + * This is the number of bytes per unit of external data. + */ +#define BYTES_PER_XDR_UNIT (4) +/* + * This only works if the above is a power of 2. But it's defined to be + * 4 by the appropriate RFCs. So it will work. And it's normally quicker + * than the old routine. + */ +#if 1 +#define RNDUP(x) (((x) + BYTES_PER_XDR_UNIT - 1) & ~(BYTES_PER_XDR_UNIT - 1)) +#else /* this is the old routine */ +#define RNDUP(x) ((((x) + BYTES_PER_XDR_UNIT - 1) / BYTES_PER_XDR_UNIT) \ + * BYTES_PER_XDR_UNIT) +#endif + +/* + * The XDR handle. + * Contains operation which is being applied to the stream, + * an operations vector for the particular implementation (e.g. see xdr_mem.c), + * and two private fields for the use of the particular implementation. + */ +typedef struct XDR XDR; +struct XDR + { + enum xdr_op x_op; /* operation; fast additional param */ + struct xdr_ops + { + bool_t (*x_getlong) (XDR *__xdrs, long *__lp); + /* get a long from underlying stream */ + bool_t (*x_putlong) (XDR *__xdrs, __const long *__lp); + /* put a long to " */ + bool_t (*x_getbytes) (XDR *__xdrs, caddr_t __addr, u_int __len); + /* get some bytes from " */ + bool_t (*x_putbytes) (XDR *__xdrs, __const char *__addr, u_int __len); + /* put some bytes to " */ + u_int (*x_getpostn) (__const XDR *__xdrs); + /* returns bytes off from beginning */ + bool_t (*x_setpostn) (XDR *__xdrs, u_int __pos); + /* lets you reposition the stream */ + int32_t *(*x_inline) (XDR *__xdrs, u_int __len); + /* buf quick ptr to buffered data */ + void (*x_destroy) (XDR *__xdrs); + /* free privates of this xdr_stream */ + bool_t (*x_getint32) (XDR *__xdrs, int32_t *__ip); + /* get a int from underlying stream */ + bool_t (*x_putint32) (XDR *__xdrs, __const int32_t *__ip); + /* put a int to " */ + } + *x_ops; + caddr_t x_public; /* users' data */ + caddr_t x_private; /* pointer to private data */ + caddr_t x_base; /* private used for position info */ + u_int x_handy; /* extra private word */ + }; + +/* + * A xdrproc_t exists for each data type which is to be encoded or decoded. + * + * The second argument to the xdrproc_t is a pointer to an opaque pointer. + * The opaque pointer generally points to a structure of the data type + * to be decoded. If this pointer is 0, then the type routines should + * allocate dynamic storage of the appropriate size and return it. + * bool_t (*xdrproc_t)(XDR *, caddr_t *); + */ +typedef bool_t (*xdrproc_t) (XDR *, void *,...); + + +/* + * Operations defined on a XDR handle + * + * XDR *xdrs; + * int32_t *int32p; + * long *longp; + * caddr_t addr; + * u_int len; + * u_int pos; + */ +#define XDR_GETINT32(xdrs, int32p) \ + (*(xdrs)->x_ops->x_getint32)(xdrs, int32p) +#define xdr_getint32(xdrs, int32p) \ + (*(xdrs)->x_ops->x_getint32)(xdrs, int32p) + +#define XDR_PUTINT32(xdrs, int32p) \ + (*(xdrs)->x_ops->x_putint32)(xdrs, int32p) +#define xdr_putint32(xdrs, int32p) \ + (*(xdrs)->x_ops->x_putint32)(xdrs, int32p) + +#define XDR_GETLONG(xdrs, longp) \ + (*(xdrs)->x_ops->x_getlong)(xdrs, longp) +#define xdr_getlong(xdrs, longp) \ + (*(xdrs)->x_ops->x_getlong)(xdrs, longp) + +#define XDR_PUTLONG(xdrs, longp) \ + (*(xdrs)->x_ops->x_putlong)(xdrs, longp) +#define xdr_putlong(xdrs, longp) \ + (*(xdrs)->x_ops->x_putlong)(xdrs, longp) + +#define XDR_GETBYTES(xdrs, addr, len) \ + (*(xdrs)->x_ops->x_getbytes)(xdrs, addr, len) +#define xdr_getbytes(xdrs, addr, len) \ + (*(xdrs)->x_ops->x_getbytes)(xdrs, addr, len) + +#define XDR_PUTBYTES(xdrs, addr, len) \ + (*(xdrs)->x_ops->x_putbytes)(xdrs, addr, len) +#define xdr_putbytes(xdrs, addr, len) \ + (*(xdrs)->x_ops->x_putbytes)(xdrs, addr, len) + +#define XDR_GETPOS(xdrs) \ + (*(xdrs)->x_ops->x_getpostn)(xdrs) +#define xdr_getpos(xdrs) \ + (*(xdrs)->x_ops->x_getpostn)(xdrs) + +#define XDR_SETPOS(xdrs, pos) \ + (*(xdrs)->x_ops->x_setpostn)(xdrs, pos) +#define xdr_setpos(xdrs, pos) \ + (*(xdrs)->x_ops->x_setpostn)(xdrs, pos) + +#define XDR_INLINE(xdrs, len) \ + (*(xdrs)->x_ops->x_inline)(xdrs, len) +#define xdr_inline(xdrs, len) \ + (*(xdrs)->x_ops->x_inline)(xdrs, len) + +#define XDR_DESTROY(xdrs) \ + do { \ + if ((xdrs)->x_ops->x_destroy) \ + (*(xdrs)->x_ops->x_destroy)(xdrs); \ + } while (0) +#define xdr_destroy(xdrs) \ + do { \ + if ((xdrs)->x_ops->x_destroy) \ + (*(xdrs)->x_ops->x_destroy)(xdrs); \ + } while (0) + +/* + * Support struct for discriminated unions. + * You create an array of xdrdiscrim structures, terminated with + * a entry with a null procedure pointer. The xdr_union routine gets + * the discriminant value and then searches the array of structures + * for a matching value. If a match is found the associated xdr routine + * is called to handle that part of the union. If there is + * no match, then a default routine may be called. + * If there is no match and no default routine it is an error. + */ +#define NULL_xdrproc_t ((xdrproc_t)0) +struct xdr_discrim +{ + int value; + xdrproc_t proc; +}; + +/* + * Inline routines for fast encode/decode of primitive data types. + * Caveat emptor: these use single memory cycles to get the + * data from the underlying buffer, and will fail to operate + * properly if the data is not aligned. The standard way to use these + * is to say: + * if ((buf = XDR_INLINE(xdrs, count)) == NULL) + * return (FALSE); + * <<< macro calls >>> + * where ``count'' is the number of bytes of data occupied + * by the primitive data types. + * + * N.B. and frozen for all time: each data type here uses 4 bytes + * of external representation. + */ + +#define IXDR_GET_INT32(buf) ((int32_t)ntohl((uint32_t)*(buf)++)) +#define IXDR_PUT_INT32(buf, v) (*(buf)++ = (int32_t)htonl((uint32_t)(v))) +#define IXDR_GET_U_INT32(buf) ((uint32_t)IXDR_GET_INT32(buf)) +#define IXDR_PUT_U_INT32(buf, v) IXDR_PUT_INT32(buf, (int32_t)(v)) + +/* WARNING: The IXDR_*_LONG defines are removed by Sun for new platforms + * and shouldn't be used any longer. Code which use this defines or longs + * in the RPC code will not work on 64bit Solaris platforms ! + */ +#define IXDR_GET_LONG(buf) ((long)IXDR_GET_U_INT32(buf)) +#define IXDR_PUT_LONG(buf, v) ((long)IXDR_PUT_INT32(buf, (long)(v))) +#define IXDR_GET_U_LONG(buf) ((u_long)IXDR_GET_LONG(buf)) +#define IXDR_PUT_U_LONG(buf, v) IXDR_PUT_LONG(buf, (long)(v)) + + +#define IXDR_GET_BOOL(buf) ((bool_t)IXDR_GET_LONG(buf)) +#define IXDR_GET_ENUM(buf, t) ((t)IXDR_GET_LONG(buf)) +#define IXDR_GET_SHORT(buf) ((short)IXDR_GET_LONG(buf)) +#define IXDR_GET_U_SHORT(buf) ((u_short)IXDR_GET_LONG(buf)) + +#define IXDR_PUT_BOOL(buf, v) IXDR_PUT_LONG(buf, (long)(v)) +#define IXDR_PUT_ENUM(buf, v) IXDR_PUT_LONG(buf, (long)(v)) +#define IXDR_PUT_SHORT(buf, v) IXDR_PUT_LONG(buf, (long)(v)) +#define IXDR_PUT_U_SHORT(buf, v) IXDR_PUT_LONG(buf, (long)(v)) + +/* + * These are the "generic" xdr routines. + * None of these can have const applied because it's not possible to + * know whether the call is a read or a write to the passed parameter + * also, the XDR structure is always updated by some of these calls. + */ +extern bool_t xdr_void (void) __THROW; +libc_hidden_proto(xdr_void) +extern bool_t xdr_short (XDR *__xdrs, short *__sp) __THROW; +libc_hidden_proto(xdr_short) +extern bool_t xdr_u_short (XDR *__xdrs, u_short *__usp) __THROW; +libc_hidden_proto(xdr_u_short) +extern bool_t xdr_int (XDR *__xdrs, int *__ip) __THROW; +libc_hidden_proto(xdr_int) +extern bool_t xdr_u_int (XDR *__xdrs, u_int *__up) __THROW; +libc_hidden_proto(xdr_u_int) +extern bool_t xdr_long (XDR *__xdrs, long *__lp) __THROW; +libc_hidden_proto(xdr_long) +extern bool_t xdr_u_long (XDR *__xdrs, u_long *__ulp) __THROW; +libc_hidden_proto(xdr_u_long) +extern bool_t xdr_hyper (XDR *__xdrs, quad_t *__llp) __THROW; +libc_hidden_proto(xdr_hyper) +extern bool_t xdr_u_hyper (XDR *__xdrs, u_quad_t *__ullp) __THROW; +libc_hidden_proto(xdr_u_hyper) +extern bool_t xdr_longlong_t (XDR *__xdrs, quad_t *__llp) __THROW; +extern bool_t xdr_u_longlong_t (XDR *__xdrs, u_quad_t *__ullp) __THROW; +extern bool_t xdr_int8_t (XDR *__xdrs, int8_t *__ip) __THROW; +extern bool_t xdr_uint8_t (XDR *__xdrs, uint8_t *__up) __THROW; +extern bool_t xdr_int16_t (XDR *__xdrs, int16_t *__ip) __THROW; +extern bool_t xdr_uint16_t (XDR *__xdrs, uint16_t *__up) __THROW; +extern bool_t xdr_int32_t (XDR *__xdrs, int32_t *__ip) __THROW; +extern bool_t xdr_uint32_t (XDR *__xdrs, uint32_t *__up) __THROW; +extern bool_t xdr_int64_t (XDR *__xdrs, int64_t *__ip) __THROW; +extern bool_t xdr_uint64_t (XDR *__xdrs, uint64_t *__up) __THROW; +extern bool_t xdr_bool (XDR *__xdrs, bool_t *__bp) __THROW; +libc_hidden_proto(xdr_bool) +extern bool_t xdr_enum (XDR *__xdrs, enum_t *__ep) __THROW; +libc_hidden_proto(xdr_enum) +extern bool_t xdr_array (XDR * _xdrs, caddr_t *__addrp, u_int *__sizep, + u_int __maxsize, u_int __elsize, xdrproc_t __elproc) + __THROW; +libc_hidden_proto(xdr_array) +extern bool_t xdr_bytes (XDR *__xdrs, char **__cpp, u_int *__sizep, + u_int __maxsize) __THROW; +libc_hidden_proto(xdr_bytes) +extern bool_t xdr_opaque (XDR *__xdrs, caddr_t __cp, u_int __cnt) __THROW; +libc_hidden_proto(xdr_opaque) +extern bool_t xdr_string (XDR *__xdrs, char **__cpp, u_int __maxsize) __THROW; +libc_hidden_proto(xdr_string) +extern bool_t xdr_union (XDR *__xdrs, enum_t *__dscmp, char *__unp, + __const struct xdr_discrim *__choices, + xdrproc_t dfault) __THROW; +libc_hidden_proto(xdr_union) +extern bool_t xdr_char (XDR *__xdrs, char *__cp) __THROW; +extern bool_t xdr_u_char (XDR *__xdrs, u_char *__cp) __THROW; +extern bool_t xdr_vector (XDR *__xdrs, char *__basep, u_int __nelem, + u_int __elemsize, xdrproc_t __xdr_elem) __THROW; +extern bool_t xdr_float (XDR *__xdrs, float *__fp) __THROW; +extern bool_t xdr_double (XDR *__xdrs, double *__dp) __THROW; +extern bool_t xdr_reference (XDR *__xdrs, caddr_t *__xpp, u_int __size, + xdrproc_t __proc) __THROW; +libc_hidden_proto(xdr_reference) +extern bool_t xdr_pointer (XDR *__xdrs, char **__objpp, + u_int __obj_size, xdrproc_t __xdr_obj) __THROW; +extern bool_t xdr_wrapstring (XDR *__xdrs, char **__cpp) __THROW; +extern u_long xdr_sizeof (xdrproc_t, void *) __THROW; + +/* + * Common opaque bytes objects used by many rpc protocols; + * declared here due to commonality. + */ +#define MAX_NETOBJ_SZ 1024 +struct netobj +{ + u_int n_len; + char *n_bytes; +}; +typedef struct netobj netobj; +extern bool_t xdr_netobj (XDR *__xdrs, struct netobj *__np) __THROW; + +/* + * These are the public routines for the various implementations of + * xdr streams. + */ + +/* XDR using memory buffers */ +extern void xdrmem_create (XDR *__xdrs, __const caddr_t __addr, + u_int __size, enum xdr_op __xop) __THROW; +libc_hidden_proto(xdrmem_create) + +/* XDR using stdio library */ +extern void xdrstdio_create (XDR *__xdrs, FILE *__file, enum xdr_op __xop) + __THROW; + +/* XDR pseudo records for tcp */ +extern void xdrrec_create (XDR *__xdrs, u_int __sendsize, + u_int __recvsize, caddr_t __tcp_handle, + int (*__readit) (char *, char *, int), + int (*__writeit) (char *, char *, int)) __THROW; +libc_hidden_proto(xdrrec_create) + +/* make end of xdr record */ +extern bool_t xdrrec_endofrecord (XDR *__xdrs, bool_t __sendnow) __THROW; +libc_hidden_proto(xdrrec_endofrecord) + +/* move to beginning of next record */ +extern bool_t xdrrec_skiprecord (XDR *__xdrs) __THROW; +libc_hidden_proto(xdrrec_skiprecord) + +/* true if no more input */ +extern bool_t xdrrec_eof (XDR *__xdrs) __THROW; +libc_hidden_proto(xdrrec_eof) + +/* free memory buffers for xdr */ +extern void xdr_free (xdrproc_t __proc, char *__objp) __THROW; + +__END_DECLS + +#endif /* rpc/xdr.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/sched.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/sched.h new file mode 100644 index 00000000..0d110c30 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/sched.h @@ -0,0 +1,92 @@ +/* Definitions for POSIX 1003.1b-1993 (aka POSIX.4) scheduling interface. + Copyright (C) 1996,1997,1999,2001-2003,2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SCHED_H +#define _SCHED_H 1 + +#include + +/* Get type definitions. */ +#include + +#define __need_timespec +#include + +/* Get system specific constant and data structure definitions. */ +#include +/* Define the real names for the elements of `struct sched_param'. */ +#define sched_priority __sched_priority + + +__BEGIN_DECLS + +/* Set scheduling parameters for a process. */ +extern int sched_setparam (__pid_t __pid, __const struct sched_param *__param) + __THROW; + +/* Retrieve scheduling parameters for a particular process. */ +extern int sched_getparam (__pid_t __pid, struct sched_param *__param) __THROW; + +/* Set scheduling algorithm and/or parameters for a process. */ +extern int sched_setscheduler (__pid_t __pid, int __policy, + __const struct sched_param *__param) __THROW; + +/* Retrieve scheduling algorithm for a particular purpose. */ +extern int sched_getscheduler (__pid_t __pid) __THROW; + +/* Yield the processor. */ +extern int sched_yield (void) __THROW; + +/* Get maximum priority value for a scheduler. */ +extern int sched_get_priority_max (int __algorithm) __THROW; + +/* Get minimum priority value for a scheduler. */ +extern int sched_get_priority_min (int __algorithm) __THROW; + +/* Get the SCHED_RR interval for the named process. */ +extern int sched_rr_get_interval (__pid_t __pid, struct timespec *__t) __THROW; + + +#if defined __USE_GNU && defined __UCLIBC_LINUX_SPECIFIC__ +/* Access macros for `cpu_set'. */ +#define CPU_SETSIZE __CPU_SETSIZE +#define CPU_SET(cpu, cpusetp) __CPU_SET (cpu, cpusetp) +#define CPU_CLR(cpu, cpusetp) __CPU_CLR (cpu, cpusetp) +#define CPU_ISSET(cpu, cpusetp) __CPU_ISSET (cpu, cpusetp) +#define CPU_ZERO(cpusetp) __CPU_ZERO (cpusetp) + + +/* Set the CPU affinity for a task */ +extern int sched_setaffinity (__pid_t __pid, size_t __cpusetsize, + __const cpu_set_t *__cpuset) __THROW; + +/* Get the CPU affinity for a task */ +extern int sched_getaffinity (__pid_t __pid, size_t __cpusetsize, + cpu_set_t *__cpuset) __THROW; + +extern int __clone (int (*__fn) (void *__arg), void *__child_stack, + int __flags, void *__arg, ...); +extern int __clone2 (int (*__fn) (void *__arg), void *__child_stack_base, + size_t __child_stack_size, int __flags, void *__arg, ...); + +#endif + +__END_DECLS + +#endif /* sched.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/scsi/scsi.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/scsi/scsi.h new file mode 100644 index 00000000..49ab7580 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/scsi/scsi.h @@ -0,0 +1,226 @@ +/* Copyright (C) 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * This header file contains public constants and structures used by + * the scsi code for linux. + */ + +#ifndef _SCSI_SCSI_H +#define _SCSI_SCSI_H 1 + +#include + +/* + * SCSI opcodes + */ + +#define TEST_UNIT_READY 0x00 +#define REZERO_UNIT 0x01 +#define REQUEST_SENSE 0x03 +#define FORMAT_UNIT 0x04 +#define READ_BLOCK_LIMITS 0x05 +#define REASSIGN_BLOCKS 0x07 +#define READ_6 0x08 +#define WRITE_6 0x0a +#define SEEK_6 0x0b +#define READ_REVERSE 0x0f +#define WRITE_FILEMARKS 0x10 +#define SPACE 0x11 +#define INQUIRY 0x12 +#define RECOVER_BUFFERED_DATA 0x14 +#define MODE_SELECT 0x15 +#define RESERVE 0x16 +#define RELEASE 0x17 +#define COPY 0x18 +#define ERASE 0x19 +#define MODE_SENSE 0x1a +#define START_STOP 0x1b +#define RECEIVE_DIAGNOSTIC 0x1c +#define SEND_DIAGNOSTIC 0x1d +#define ALLOW_MEDIUM_REMOVAL 0x1e + +#define SET_WINDOW 0x24 +#define READ_CAPACITY 0x25 +#define READ_10 0x28 +#define WRITE_10 0x2a +#define SEEK_10 0x2b +#define WRITE_VERIFY 0x2e +#define VERIFY 0x2f +#define SEARCH_HIGH 0x30 +#define SEARCH_EQUAL 0x31 +#define SEARCH_LOW 0x32 +#define SET_LIMITS 0x33 +#define PRE_FETCH 0x34 +#define READ_POSITION 0x34 +#define SYNCHRONIZE_CACHE 0x35 +#define LOCK_UNLOCK_CACHE 0x36 +#define READ_DEFECT_DATA 0x37 +#define MEDIUM_SCAN 0x38 +#define COMPARE 0x39 +#define COPY_VERIFY 0x3a +#define WRITE_BUFFER 0x3b +#define READ_BUFFER 0x3c +#define UPDATE_BLOCK 0x3d +#define READ_LONG 0x3e +#define WRITE_LONG 0x3f +#define CHANGE_DEFINITION 0x40 +#define WRITE_SAME 0x41 +#define READ_TOC 0x43 +#define LOG_SELECT 0x4c +#define LOG_SENSE 0x4d +#define MODE_SELECT_10 0x55 +#define RESERVE_10 0x56 +#define RELEASE_10 0x57 +#define MODE_SENSE_10 0x5a +#define PERSISTENT_RESERVE_IN 0x5e +#define PERSISTENT_RESERVE_OUT 0x5f +#define MOVE_MEDIUM 0xa5 +#define READ_12 0xa8 +#define WRITE_12 0xaa +#define WRITE_VERIFY_12 0xae +#define SEARCH_HIGH_12 0xb0 +#define SEARCH_EQUAL_12 0xb1 +#define SEARCH_LOW_12 0xb2 +#define READ_ELEMENT_STATUS 0xb8 +#define SEND_VOLUME_TAG 0xb6 +#define WRITE_LONG_2 0xea + +/* + * Status codes + */ + +#define GOOD 0x00 +#define CHECK_CONDITION 0x01 +#define CONDITION_GOOD 0x02 +#define BUSY 0x04 +#define INTERMEDIATE_GOOD 0x08 +#define INTERMEDIATE_C_GOOD 0x0a +#define RESERVATION_CONFLICT 0x0c +#define COMMAND_TERMINATED 0x11 +#define QUEUE_FULL 0x14 + +#define STATUS_MASK 0x3e + +/* + * SENSE KEYS + */ + +#define NO_SENSE 0x00 +#define RECOVERED_ERROR 0x01 +#define NOT_READY 0x02 +#define MEDIUM_ERROR 0x03 +#define HARDWARE_ERROR 0x04 +#define ILLEGAL_REQUEST 0x05 +#define UNIT_ATTENTION 0x06 +#define DATA_PROTECT 0x07 +#define BLANK_CHECK 0x08 +#define COPY_ABORTED 0x0a +#define ABORTED_COMMAND 0x0b +#define VOLUME_OVERFLOW 0x0d +#define MISCOMPARE 0x0e + + +/* + * DEVICE TYPES + */ + +#define TYPE_DISK 0x00 +#define TYPE_TAPE 0x01 +#define TYPE_PROCESSOR 0x03 /* HP scanners use this */ +#define TYPE_WORM 0x04 /* Treated as ROM by our system */ +#define TYPE_ROM 0x05 +#define TYPE_SCANNER 0x06 +#define TYPE_MOD 0x07 /* Magneto-optical disk - + * - treated as TYPE_DISK */ +#define TYPE_MEDIUM_CHANGER 0x08 +#define TYPE_ENCLOSURE 0x0d /* Enclosure Services Device */ +#define TYPE_NO_LUN 0x7f + +/* + * standard mode-select header prepended to all mode-select commands + * + * moved here from cdrom.h -- kraxel + */ + +struct ccs_modesel_head + { + unsigned char _r1; /* reserved. */ + unsigned char medium; /* device-specific medium type. */ + unsigned char _r2; /* reserved. */ + unsigned char block_desc_length; /* block descriptor length. */ + unsigned char density; /* device-specific density code. */ + unsigned char number_blocks_hi; /* number of blocks in this block + desc. */ + unsigned char number_blocks_med; + unsigned char number_blocks_lo; + unsigned char _r3; + unsigned char block_length_hi; /* block length for blocks in this + desc. */ + unsigned char block_length_med; + unsigned char block_length_lo; + }; + +/* + * MESSAGE CODES + */ + +#define COMMAND_COMPLETE 0x00 +#define EXTENDED_MESSAGE 0x01 +#define EXTENDED_MODIFY_DATA_POINTER 0x00 +#define EXTENDED_SDTR 0x01 +#define EXTENDED_EXTENDED_IDENTIFY 0x02 /* SCSI-I only */ +#define EXTENDED_WDTR 0x03 +#define SAVE_POINTERS 0x02 +#define RESTORE_POINTERS 0x03 +#define DISCONNECT 0x04 +#define INITIATOR_ERROR 0x05 +#define ABORT 0x06 +#define MESSAGE_REJECT 0x07 +#define NOP 0x08 +#define MSG_PARITY_ERROR 0x09 +#define LINKED_CMD_COMPLETE 0x0a +#define LINKED_FLG_CMD_COMPLETE 0x0b +#define BUS_DEVICE_RESET 0x0c + +#define INITIATE_RECOVERY 0x0f /* SCSI-II only */ +#define RELEASE_RECOVERY 0x10 /* SCSI-II only */ + +#define SIMPLE_QUEUE_TAG 0x20 +#define HEAD_OF_QUEUE_TAG 0x21 +#define ORDERED_QUEUE_TAG 0x22 + +/* + * Here are some scsi specific ioctl commands which are sometimes useful. + */ +/* These are a few other constants only used by scsi devices. */ + +#define SCSI_IOCTL_GET_IDLUN 0x5382 + +/* Used to turn on and off tagged queuing for scsi devices. */ + +#define SCSI_IOCTL_TAGGED_ENABLE 0x5383 +#define SCSI_IOCTL_TAGGED_DISABLE 0x5384 + +/* Used to obtain the host number of a device. */ +#define SCSI_IOCTL_PROBE_HOST 0x5385 + +/* Used to get the bus number for a device. */ +#define SCSI_IOCTL_GET_BUS_NUMBER 0x5386 + +#endif /* scsi/scsi.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/scsi/scsi_ioctl.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/scsi/scsi_ioctl.h new file mode 100644 index 00000000..ba8c84fa --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/scsi/scsi_ioctl.h @@ -0,0 +1,34 @@ +/* Copyright (C) 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SCSI_IOCTL_H +#define _SCSI_IOCTL_H + +/* IOCTLs for SCSI. */ +#define SCSI_IOCTL_SEND_COMMAND 1 /* Send a command to the SCSI host. */ +#define SCSI_IOCTL_TEST_UNIT_READY 2 /* Test if unit is ready. */ +#define SCSI_IOCTL_BENCHMARK_COMMAND 3 +#define SCSI_IOCTL_SYNC 4 /* Request synchronous parameters. */ +#define SCSI_IOCTL_START_UNIT 5 +#define SCSI_IOCTL_STOP_UNIT 6 +#define SCSI_IOCTL_DOORLOCK 0x5380 /* Lock the eject mechanism. */ +#define SCSI_IOCTL_DOORUNLOCK 0x5381 /* Unlock the mechanism. */ + +#endif + + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/scsi/sg.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/scsi/sg.h new file mode 100644 index 00000000..b0dc0ad7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/scsi/sg.h @@ -0,0 +1,275 @@ +/* Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + History: + Started: Aug 9 by Lawrence Foard (entropy@world.std.com), to allow user + process control of SCSI devices. + Development Sponsored by Killy Corp. NY NY +*/ + +#ifndef _SCSI_SG_H +#define _SCSI_SG_H 1 + +#include + + +/* New interface introduced in the 3.x SG drivers follows */ + +/* Same structure as used by readv() Linux system call. It defines one + scatter-gather element. */ +typedef struct sg_iovec +{ + void * iov_base; /* Starting address */ + size_t iov_len; /* Length in bytes */ +} sg_iovec_t; + + +typedef struct sg_io_hdr +{ + int interface_id; /* [i] 'S' for SCSI generic (required) */ + int dxfer_direction; /* [i] data transfer direction */ + unsigned char cmd_len; /* [i] SCSI command length ( <= 16 bytes) */ + unsigned char mx_sb_len; /* [i] max length to write to sbp */ + unsigned short int iovec_count; /* [i] 0 implies no scatter gather */ + unsigned int dxfer_len; /* [i] byte count of data transfer */ + void * dxferp; /* [i], [*io] points to data transfer memory + or scatter gather list */ + unsigned char * cmdp; /* [i], [*i] points to command to perform */ + unsigned char * sbp; /* [i], [*o] points to sense_buffer memory */ + unsigned int timeout; /* [i] MAX_UINT->no timeout (unit: millisec) */ + unsigned int flags; /* [i] 0 -> default, see SG_FLAG... */ + int pack_id; /* [i->o] unused internally (normally) */ + void * usr_ptr; /* [i->o] unused internally */ + unsigned char status; /* [o] scsi status */ + unsigned char masked_status;/* [o] shifted, masked scsi status */ + unsigned char msg_status; /* [o] messaging level data (optional) */ + unsigned char sb_len_wr; /* [o] byte count actually written to sbp */ + unsigned short int host_status; /* [o] errors from host adapter */ + unsigned short int driver_status;/* [o] errors from software driver */ + int resid; /* [o] dxfer_len - actual_transferred */ + unsigned int duration; /* [o] time taken by cmd (unit: millisec) */ + unsigned int info; /* [o] auxiliary information */ +} sg_io_hdr_t; + + +/* Use negative values to flag difference from original sg_header structure. */ +#define SG_DXFER_NONE -1 /* e.g. a SCSI Test Unit Ready command */ +#define SG_DXFER_TO_DEV -2 /* e.g. a SCSI WRITE command */ +#define SG_DXFER_FROM_DEV -3 /* e.g. a SCSI READ command */ +#define SG_DXFER_TO_FROM_DEV -4 /* treated like SG_DXFER_FROM_DEV with the + additional property than during indirect + IO the user buffer is copied into the + kernel buffers before the transfer */ + + +/* following flag values can be "or"-ed together */ +#define SG_FLAG_DIRECT_IO 1 /* default is indirect IO */ +#define SG_FLAG_LUN_INHIBIT 2 /* default is to put device's lun into */ + /* the 2nd byte of SCSI command */ +#define SG_FLAG_NO_DXFER 0x10000 /* no transfer of kernel buffers to/from */ + /* user space (debug indirect IO) */ + +/* The following 'info' values are "or"-ed together. */ +#define SG_INFO_OK_MASK 0x1 +#define SG_INFO_OK 0x0 /* no sense, host nor driver "noise" */ +#define SG_INFO_CHECK 0x1 /* something abnormal happened */ + +#define SG_INFO_DIRECT_IO_MASK 0x6 +#define SG_INFO_INDIRECT_IO 0x0 /* data xfer via kernel buffers (or no xfer) */ +#define SG_INFO_DIRECT_IO 0x2 /* direct IO requested and performed */ +#define SG_INFO_MIXED_IO 0x4 /* part direct, part indirect IO */ + + +/* Request information about a specific SG device, used by + SG_GET_SCSI_ID ioctl (). */ +struct sg_scsi_id { + /* Host number as in "scsi" where 'n' is one of 0, 1, 2 etc. */ + int host_no; + int channel; + /* SCSI id of target device. */ + int scsi_id; + int lun; + /* TYPE_... defined in . */ + int scsi_type; + /* Host (adapter) maximum commands per lun. */ + short int h_cmd_per_lun; + /* Device (or adapter) maximum queue length. */ + short int d_queue_depth; + /* Unused, set to 0 for now. */ + int unused[2]; +}; + +/* Used by SG_GET_REQUEST_TABLE ioctl(). */ +typedef struct sg_req_info { + char req_state; /* 0 -> not used, 1 -> written, 2 -> ready to read */ + char orphan; /* 0 -> normal request, 1 -> from interruped SG_IO */ + char sg_io_owned; /* 0 -> complete with read(), 1 -> owned by SG_IO */ + char problem; /* 0 -> no problem detected, 1 -> error to report */ + int pack_id; /* pack_id associated with request */ + void * usr_ptr; /* user provided pointer (in new interface) */ + unsigned int duration; /* millisecs elapsed since written (req_state==1) + or request duration (req_state==2) */ + int unused; +} sg_req_info_t; + + +/* IOCTLs: Those ioctls that are relevant to the SG 3.x drivers follow. + [Those that only apply to the SG 2.x drivers are at the end of the file.] + (_GET_s yield result via 'int *' 3rd argument unless otherwise indicated) */ + +#define SG_EMULATED_HOST 0x2203 /* true for emulated host adapter (ATAPI) */ + +/* Used to configure SCSI command transformation layer for ATAPI devices */ +/* Only supported by the ide-scsi driver */ +#define SG_SET_TRANSFORM 0x2204 /* N.B. 3rd arg is not pointer but value: */ + /* 3rd arg = 0 to disable transform, 1 to enable it */ +#define SG_GET_TRANSFORM 0x2205 + +#define SG_SET_RESERVED_SIZE 0x2275 /* request a new reserved buffer size */ +#define SG_GET_RESERVED_SIZE 0x2272 /* actual size of reserved buffer */ + +/* The following ioctl has a 'sg_scsi_id_t *' object as its 3rd argument. */ +#define SG_GET_SCSI_ID 0x2276 /* Yields fd's bus, chan, dev, lun + type */ +/* SCSI id information can also be obtained from SCSI_IOCTL_GET_IDLUN */ + +/* Override host setting and always DMA using low memory ( <16MB on i386) */ +#define SG_SET_FORCE_LOW_DMA 0x2279 /* 0-> use adapter setting, 1-> force */ +#define SG_GET_LOW_DMA 0x227a /* 0-> use all ram for dma; 1-> low dma ram */ + +/* When SG_SET_FORCE_PACK_ID set to 1, pack_id is input to read() which + tries to fetch a packet with a matching pack_id, waits, or returns EAGAIN. + If pack_id is -1 then read oldest waiting. When ...FORCE_PACK_ID set to 0 + then pack_id ignored by read() and oldest readable fetched. */ +#define SG_SET_FORCE_PACK_ID 0x227b +#define SG_GET_PACK_ID 0x227c /* Yields oldest readable pack_id (or -1) */ + +#define SG_GET_NUM_WAITING 0x227d /* Number of commands awaiting read() */ + +/* Yields max scatter gather tablesize allowed by current host adapter */ +#define SG_GET_SG_TABLESIZE 0x227F /* 0 implies can't do scatter gather */ + +#define SG_GET_VERSION_NUM 0x2282 /* Example: version 2.1.34 yields 20134 */ + +/* Returns -EBUSY if occupied. 3rd argument pointer to int (see next) */ +#define SG_SCSI_RESET 0x2284 +/* Associated values that can be given to SG_SCSI_RESET follow */ +#define SG_SCSI_RESET_NOTHING 0 +#define SG_SCSI_RESET_DEVICE 1 +#define SG_SCSI_RESET_BUS 2 +#define SG_SCSI_RESET_HOST 3 + +/* synchronous SCSI command ioctl, (only in version 3 interface) */ +#define SG_IO 0x2285 /* similar effect as write() followed by read() */ + +#define SG_GET_REQUEST_TABLE 0x2286 /* yields table of active requests */ + +/* How to treat EINTR during SG_IO ioctl(), only in SG 3.x series */ +#define SG_SET_KEEP_ORPHAN 0x2287 /* 1 -> hold for read(), 0 -> drop (def) */ +#define SG_GET_KEEP_ORPHAN 0x2288 + + +#define SG_SCATTER_SZ (8 * 4096) /* PAGE_SIZE not available to user */ +/* Largest size (in bytes) a single scatter-gather list element can have. + The value must be a power of 2 and <= (PAGE_SIZE * 32) [131072 bytes on + i386]. The minimum value is PAGE_SIZE. If scatter-gather not supported + by adapter then this value is the largest data block that can be + read/written by a single scsi command. The user can find the value of + PAGE_SIZE by calling getpagesize() defined in unistd.h . */ + +#define SG_DEFAULT_RETRIES 1 + +/* Defaults, commented if they differ from original sg driver */ +#define SG_DEF_FORCE_LOW_DMA 0 /* was 1 -> memory below 16MB on i386 */ +#define SG_DEF_FORCE_PACK_ID 0 +#define SG_DEF_KEEP_ORPHAN 0 +#define SG_DEF_RESERVED_SIZE SG_SCATTER_SZ /* load time option */ + +/* maximum outstanding requests, write() yields EDOM if exceeded */ +#define SG_MAX_QUEUE 16 + +#define SG_BIG_BUFF SG_DEF_RESERVED_SIZE /* for backward compatibility */ + +/* Alternate style type names, "..._t" variants preferred */ +typedef struct sg_io_hdr Sg_io_hdr; +typedef struct sg_io_vec Sg_io_vec; +typedef struct sg_scsi_id Sg_scsi_id; +typedef struct sg_req_info Sg_req_info; + + +/* vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv */ +/* The older SG interface based on the 'sg_header' structure follows. */ +/* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ */ + +#define SG_MAX_SENSE 16 /* this only applies to the sg_header interface */ + +struct sg_header + { + /* Length of incoming packet (including header). */ + int pack_len; + /* Maximal length of expected reply. */ + int reply_len; + /* Id number of packet. */ + int pack_id; + /* 0==ok, otherwise error number. */ + int result; + /* Force 12 byte command length for group 6 & 7 commands. */ + unsigned int twelve_byte:1; + /* SCSI status from target. */ + unsigned int target_status:5; + /* Host status (see "DID" codes). */ + unsigned int host_status:8; + /* Driver status+suggestion. */ + unsigned int driver_status:8; + /* Unused. */ + unsigned int other_flags:10; + /* Output in 3 cases: + when target_status is CHECK_CONDITION or + when target_status is COMMAND_TERMINATED or + when (driver_status & DRIVER_SENSE) is true. */ + unsigned char sense_buffer[SG_MAX_SENSE]; + }; + + +/* IOCTLs: The following are not required (or ignored) when the sg_io_hdr_t + interface is used. They are kept for backward compatibility with + the original and version 2 drivers. */ + +#define SG_SET_TIMEOUT 0x2201 /* Set timeout; *(int *)arg==timeout. */ +#define SG_GET_TIMEOUT 0x2202 /* Get timeout; return timeout. */ + +/* Get/set command queuing state per fd (default is SG_DEF_COMMAND_Q). */ +#define SG_GET_COMMAND_Q 0x2270 /* Yields 0 (queuing off) or 1 (on). */ +#define SG_SET_COMMAND_Q 0x2271 /* Change queuing state with 0 or 1. */ + +/* Turn on error sense trace (1..8), dump this device to log/console (9) + or dump all sg device states ( >9 ) to log/console. */ +#define SG_SET_DEBUG 0x227e /* 0 -> turn off debug */ + +#define SG_NEXT_CMD_LEN 0x2283 /* Override SCSI command length with given + number on the next write() on this file + descriptor. */ + +/* Defaults, commented if they differ from original sg driver */ +#define SG_DEFAULT_TIMEOUT (60*HZ) /* HZ == 'jiffies in 1 second' */ +#define SG_DEF_COMMAND_Q 0 /* command queuing is always on when + the new interface is used */ +#define SG_DEF_UNDERRUN_FLAG 0 + + +#endif /* scsi/sg.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/search.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/search.h new file mode 100644 index 00000000..ac1963db --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/search.h @@ -0,0 +1,182 @@ +/* Declarations for System V style searching functions. + Copyright (C) 1995-1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SEARCH_H +#define _SEARCH_H 1 + +#include + +#define __need_size_t +#include + +__BEGIN_DECLS + +#if defined __USE_SVID || defined __USE_XOPEN_EXTENDED +/* Prototype structure for a linked-list data structure. + This is the type used by the `insque' and `remque' functions. */ + +# ifdef __USE_GNU +struct qelem + { + struct qelem *q_forw; + struct qelem *q_back; + char q_data[1]; + }; +# endif + + +/* Insert ELEM into a doubly-linked list, after PREV. */ +extern void insque (void *__elem, void *__prev) __THROW; + +/* Unlink ELEM from the doubly-linked list that it is in. */ +extern void remque (void *__elem) __THROW; +#endif + + +/* For use with hsearch(3). */ +#ifndef __COMPAR_FN_T +# define __COMPAR_FN_T +typedef int (*__compar_fn_t) (__const void *, __const void *); + +# ifdef __USE_GNU +typedef __compar_fn_t comparison_fn_t; +# endif +#endif + +/* Action which shall be performed in the call the hsearch. */ +typedef enum + { + FIND, + ENTER + } +ACTION; + +typedef struct entry + { + char *key; + void *data; + } +ENTRY; + +/* Opaque type for internal use. */ +struct _ENTRY; + +/* Family of hash table handling functions. The functions also + have reentrant counterparts ending with _r. The non-reentrant + functions all work on a signle internal hashing table. */ + +/* Search for entry matching ITEM.key in internal hash table. If + ACTION is `FIND' return found entry or signal error by returning + NULL. If ACTION is `ENTER' replace existing data (if any) with + ITEM.data. */ +extern ENTRY *hsearch (ENTRY __item, ACTION __action) __THROW; + +/* Create a new hashing table which will at most contain NEL elements. */ +extern int hcreate (size_t __nel) __THROW; + +/* Destroy current internal hashing table. */ +extern void hdestroy (void) __THROW; + +#ifdef __USE_GNU +/* Data type for reentrant functions. */ +struct hsearch_data + { + struct _ENTRY *table; + unsigned int size; + unsigned int filled; + }; + +/* Reentrant versions which can handle multiple hashing tables at the + same time. */ +extern int hsearch_r (ENTRY __item, ACTION __action, ENTRY **__retval, + struct hsearch_data *__htab) __THROW; +libc_hidden_proto(hsearch_r) +extern int hcreate_r (size_t __nel, struct hsearch_data *__htab) __THROW; +libc_hidden_proto(hcreate_r) +extern void hdestroy_r (struct hsearch_data *__htab) __THROW; +libc_hidden_proto(hdestroy_r) +#endif + + +/* The tsearch routines are very interesting. They make many + assumptions about the compiler. It assumes that the first field + in node must be the "key" field, which points to the datum. + Everything depends on that. */ +/* For tsearch */ +typedef enum +{ + preorder, + postorder, + endorder, + leaf +} +VISIT; + +/* Search for an entry matching the given KEY in the tree pointed to + by *ROOTP and insert a new element if not found. */ +extern void *tsearch (__const void *__key, void **__rootp, + __compar_fn_t __compar); +libc_hidden_proto(tsearch) + +/* Search for an entry matching the given KEY in the tree pointed to + by *ROOTP. If no matching entry is available return NULL. */ +extern void *tfind (__const void *__key, void *__const *__rootp, + __compar_fn_t __compar); +libc_hidden_proto(tfind) + +/* Remove the element matching KEY from the tree pointed to by *ROOTP. */ +extern void *tdelete (__const void *__restrict __key, + void **__restrict __rootp, + __compar_fn_t __compar); + +#ifndef __ACTION_FN_T +# define __ACTION_FN_T +typedef void (*__action_fn_t) (__const void *__nodep, VISIT __value, + int __level); +#endif + +/* Walk through the whole tree and call the ACTION callback for every node + or leaf. */ +extern void twalk (__const void *__root, __action_fn_t __action); + +#ifdef __USE_GNU +/* Callback type for function to free a tree node. If the keys are atomic + data this function should do nothing. */ +typedef void (*__free_fn_t) (void *__nodep); + +/* Destroy the whole tree, call FREEFCT for each node or leaf. */ +extern void tdestroy (void *__root, __free_fn_t __freefct); +libc_hidden_proto(tdestroy) +#endif + + +/* Perform linear search for KEY by comparing by COMPAR in an array + [BASE,BASE+NMEMB*SIZE). */ +extern void *lfind (__const void *__key, __const void *__base, + size_t *__nmemb, size_t __size, __compar_fn_t __compar); +libc_hidden_proto(lfind) + +/* Perform linear search for KEY by comparing by COMPAR function in + array [BASE,BASE+NMEMB*SIZE) and insert entry if not found. */ +extern void *lsearch (__const void *__key, void *__base, + size_t *__nmemb, size_t __size, __compar_fn_t __compar); + +__END_DECLS + +#endif /* search.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/setjmp.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/setjmp.h new file mode 100644 index 00000000..99e3dc8c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/setjmp.h @@ -0,0 +1,104 @@ +/* Copyright (C) 1991-1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * ISO C99 Standard: 7.13 Nonlocal jumps + */ + +#ifndef _SETJMP_H +#define _SETJMP_H 1 + +#include + +__BEGIN_DECLS + +#include /* Get `__jmp_buf'. */ +#include /* Get `__sigset_t'. */ + +/* Calling environment, plus possibly a saved signal mask. */ +typedef struct __jmp_buf_tag /* C++ doesn't like tagless structs. */ + { + /* NOTE: The machine-dependent definitions of `__sigsetjmp' + assume that a `jmp_buf' begins with a `__jmp_buf' and that + `__mask_was_saved' follows it. Do not move these members + or add others before it. */ + __jmp_buf __jmpbuf; /* Calling environment. */ + int __mask_was_saved; /* Saved the signal mask? */ + __sigset_t __saved_mask; /* Saved signal mask. */ + } jmp_buf[1]; + + +/* Store the calling environment in ENV, also saving the signal mask. + Return 0. */ +extern int setjmp (jmp_buf __env) __THROW; + +/* Store the calling environment in ENV, not saving the signal mask. + Return 0. */ +extern int _setjmp (jmp_buf __env) __THROW; + +/* Store the calling environment in ENV, also saving the + signal mask if SAVEMASK is nonzero. Return 0. + This is the internal name for `sigsetjmp'. */ +extern int __sigsetjmp (jmp_buf __env, int __savemask) __THROW; + +#ifndef __FAVOR_BSD +/* Do not save the signal mask. This is equivalent to the `_setjmp' + BSD function. */ +# define setjmp(env) _setjmp (env) +#else +/* We are in 4.3 BSD-compatibility mode in which `setjmp' + saves the signal mask like `sigsetjmp (ENV, 1)'. We have to + define a macro since ISO C says `setjmp' is one. */ +# define setjmp(env) setjmp (env) +#endif /* Favor BSD. */ + + +/* Jump to the environment saved in ENV, making the + `setjmp' call there return VAL, or 1 if VAL is 0. */ +extern void longjmp (jmp_buf __env, int __val) + __THROW __attribute__ ((__noreturn__)); +#if defined __USE_BSD || defined __USE_XOPEN +/* Same. Usually `_longjmp' is used with `_setjmp', which does not save + the signal mask. But it is how ENV was saved that determines whether + `longjmp' restores the mask; `_longjmp' is just an alias. */ +extern void _longjmp (jmp_buf __env, int __val) + __THROW __attribute__ ((__noreturn__)); +#endif + + +#ifdef __USE_POSIX +/* Use the same type for `jmp_buf' and `sigjmp_buf'. + The `__mask_was_saved' flag determines whether + or not `longjmp' will restore the signal mask. */ +typedef jmp_buf sigjmp_buf; + +/* Store the calling environment in ENV, also saving the + signal mask if SAVEMASK is nonzero. Return 0. */ +# define sigsetjmp(env, savemask) __sigsetjmp (env, savemask) + +/* Jump to the environment saved in ENV, making the + sigsetjmp call there return VAL, or 1 if VAL is 0. + Restore the signal mask if that sigsetjmp call saved it. + This is just an alias `longjmp'. */ +extern void siglongjmp (sigjmp_buf __env, int __val) + __THROW __attribute__ ((__noreturn__)); +#endif /* Use POSIX. */ + +__END_DECLS + +#endif /* setjmp.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/sgtty.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/sgtty.h new file mode 100644 index 00000000..5b2bc418 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/sgtty.h @@ -0,0 +1,41 @@ +/* Copyright (C) 1991, 1992, 1996, 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SGTTY_H +#define _SGTTY_H 1 + +#include + +#include + +/* On some systems this type is not defined by ; + in that case, the functions are just stubs that return ENOSYS. */ +struct sgttyb; + +__BEGIN_DECLS + +/* Fill in *PARAMS with terminal parameters associated with FD. */ +extern int gtty (int __fd, struct sgttyb *__params) __THROW; + +/* Set the terminal parameters associated with FD to *PARAMS. */ +extern int stty (int __fd, __const struct sgttyb *__params) __THROW; + + +__END_DECLS + +#endif /* sgtty.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/shadow.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/shadow.h new file mode 100644 index 00000000..baad1770 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/shadow.h @@ -0,0 +1,153 @@ +/* Copyright (C) 1996, 1997, 1998, 1999, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Declaration of types and functions for shadow password suite. */ + +#ifndef _SHADOW_H +#define _SHADOW_H 1 + +#include + +#include + +#define __need_FILE +#include +#define __need_size_t +#include + +/* Paths to the user database files. */ +#define SHADOW _PATH_SHADOW + + +__BEGIN_DECLS + +/* Structure of the password file. */ +struct spwd + { + char *sp_namp; /* Login name. */ + char *sp_pwdp; /* Encrypted password. */ + long int sp_lstchg; /* Date of last change. */ + long int sp_min; /* Minimum number of days between changes. */ + long int sp_max; /* Maximum number of days between changes. */ + long int sp_warn; /* Number of days to warn user to change + the password. */ + long int sp_inact; /* Number of days the account may be + inactive. */ + long int sp_expire; /* Number of days since 1970-01-01 until + account expires. */ + unsigned long int sp_flag; /* Reserved. */ + }; + + +/* Open database for reading. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern void setspent (void); + +/* Close database. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern void endspent (void); + +/* Get next entry from database, perhaps after opening the file. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern struct spwd *getspent (void); + +/* Get shadow entry matching NAME. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern struct spwd *getspnam (__const char *__name); + +/* Read shadow entry from STRING. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern struct spwd *sgetspent (__const char *__string); + +/* Read next shadow entry from STREAM. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern struct spwd *fgetspent (FILE *__stream); + +/* Write line containing shadow password entry to stream. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern int putspent (__const struct spwd *__p, FILE *__stream); + + +#ifdef __USE_MISC +/* Reentrant versions of some of the functions above. + + These functions are not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation they are cancellation points and + therefore not marked with __THROW. */ +extern int getspent_r (struct spwd *__result_buf, char *__buffer, + size_t __buflen, struct spwd **__result); +libc_hidden_proto(getspent_r) + +extern int getspnam_r (__const char *__name, struct spwd *__result_buf, + char *__buffer, size_t __buflen, + struct spwd **__result); +libc_hidden_proto(getspnam_r) + +extern int sgetspent_r (__const char *__string, struct spwd *__result_buf, + char *__buffer, size_t __buflen, + struct spwd **__result); +libc_hidden_proto(sgetspent_r) + +extern int fgetspent_r (FILE *__stream, struct spwd *__result_buf, + char *__buffer, size_t __buflen, + struct spwd **__result); +libc_hidden_proto(fgetspent_r) +#endif /* misc */ + + +/* The simple locking functionality provided here is not suitable for + multi-threaded applications. */ + +/* Protect password file against multi writers. */ +extern int lckpwdf (void) __THROW; + +/* Unlock password file. */ +extern int ulckpwdf (void) __THROW; + +__END_DECLS + +#endif /* shadow.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/signal.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/signal.h new file mode 100644 index 00000000..0a09c7ad --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/signal.h @@ -0,0 +1,440 @@ +/* Copyright (C) 1991-2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * ISO C99 Standard: 7.14 Signal handling + */ + +#ifndef _SIGNAL_H + +#if !defined __need_sig_atomic_t && !defined __need_sigset_t +# define _SIGNAL_H +#endif + +#include + +__BEGIN_DECLS + +#include /* __sigset_t, __sig_atomic_t. */ + +/* An integral type that can be modified atomically, without the + possibility of a signal arriving in the middle of the operation. */ +#if defined __need_sig_atomic_t || defined _SIGNAL_H +# ifndef __sig_atomic_t_defined +# define __sig_atomic_t_defined +__BEGIN_NAMESPACE_STD +typedef __sig_atomic_t sig_atomic_t; +__END_NAMESPACE_STD +# endif +# undef __need_sig_atomic_t +#endif + +#if defined __need_sigset_t || (defined _SIGNAL_H && defined __USE_POSIX) +# ifndef __sigset_t_defined +# define __sigset_t_defined +typedef __sigset_t sigset_t; +# endif +# undef __need_sigset_t +#endif + +#ifdef _SIGNAL_H + +#include +#include + +/* Fake signal functions. */ +#define SIG_ERR ((__sighandler_t) -1) /* Error return. */ +#define SIG_DFL ((__sighandler_t) 0) /* Default action. */ +#define SIG_IGN ((__sighandler_t) 1) /* Ignore signal. */ +#ifdef __USE_UNIX98 +# define SIG_HOLD ((__sighandler_t) 2) /* Add signal to hold mask. */ +#endif +/* Biggest signal number + 1 (including real-time signals). */ +#ifndef _NSIG /* if arch has not defined it in bits/signum.h... */ +# define _NSIG 65 +#endif +#ifdef __USE_MISC +# define NSIG _NSIG +#endif +/* Real-time signal range */ +#define SIGRTMIN (__libc_current_sigrtmin()) +#define SIGRTMAX (__libc_current_sigrtmax()) +/* These are the hard limits of the kernel. These values should not be + used directly at user level. */ +#ifndef __SIGRTMIN /* if arch has not defined it in bits/signum.h... */ +# define __SIGRTMIN 32 +#endif +#define __SIGRTMAX (_NSIG - 1) + + +#if defined __USE_XOPEN || defined __USE_XOPEN2K +# ifndef __pid_t_defined +typedef __pid_t pid_t; +# define __pid_t_defined +# endif +# ifndef __uid_t_defined +typedef __uid_t uid_t; +# define __uid_t_defined +# endif +#endif /* Unix98 */ + + +/* Type of a signal handler. */ +typedef void (*__sighandler_t) (int); +#if defined __UCLIBC_HAS_OBSOLETE_SYSV_SIGNAL__ +/* The X/Open definition of `signal' specifies the SVID semantic. Use + the additional function `sysv_signal' when X/Open compatibility is + requested. */ +extern __sighandler_t __sysv_signal (int __sig, __sighandler_t __handler) + __THROW; +# ifdef __USE_GNU +extern __sighandler_t sysv_signal (int __sig, __sighandler_t __handler) + __THROW; +# endif +#endif /* __UCLIBC_HAS_OBSOLETE_SYSV_SIGNAL__ */ + +/* Set the handler for the signal SIG to HANDLER, returning the old + handler, or SIG_ERR on error. + By default `signal' has the BSD semantic. */ +__BEGIN_NAMESPACE_STD +#if defined __USE_BSD || !defined __UCLIBC_HAS_OBSOLETE_SYSV_SIGNAL__ +extern __sighandler_t signal (int __sig, __sighandler_t __handler) + __THROW; +libc_hidden_proto(signal) +#else +/* Make sure the used `signal' implementation is the SVID version. */ +# ifdef __REDIRECT_NTH +extern __sighandler_t __REDIRECT_NTH (signal, + (int __sig, __sighandler_t __handler), + __sysv_signal); +# else +# define signal __sysv_signal +# endif +#endif +__END_NAMESPACE_STD + +#if defined __USE_XOPEN && defined __UCLIBC_SUSV3_LEGACY__ +/* The X/Open definition of `signal' conflicts with the BSD version. + So they defined another function `bsd_signal'. */ +extern __sighandler_t bsd_signal (int __sig, __sighandler_t __handler) + __THROW; +#endif + +/* Send signal SIG to process number PID. If PID is zero, + send SIG to all processes in the current process's process group. + If PID is < -1, send SIG to all processes in process group - PID. */ +#ifdef __USE_POSIX +extern int kill (__pid_t __pid, int __sig) __THROW; +libc_hidden_proto(kill) +#endif + +#if defined __USE_BSD || defined __USE_XOPEN_EXTENDED +/* Send SIG to all processes in process group PGRP. + If PGRP is zero, send SIG to all processes in + the current process's process group. */ +extern int killpg (__pid_t __pgrp, int __sig) __THROW; +#endif + +__BEGIN_NAMESPACE_STD +/* Raise signal SIG, i.e., send SIG to yourself. */ +extern int raise (int __sig) __THROW; +libc_hidden_proto(raise) +__END_NAMESPACE_STD + +#ifdef __USE_SVID +/* SVID names for the same things. */ +extern __sighandler_t ssignal (int __sig, __sighandler_t __handler) + __THROW; +extern int gsignal (int __sig) __THROW; +#endif /* Use SVID. */ + +#ifdef __USE_MISC +/* Print a message describing the meaning of the given signal number. */ +extern void psignal (int __sig, __const char *__s); +#endif /* Use misc. */ + + +/* The `sigpause' function has two different interfaces. The original + BSD definition defines the argument as a mask of the signal, while + the more modern interface in X/Open defines it as the signal + number. We go with the BSD version unless the user explicitly + selects the X/Open version. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern int __sigpause (int __sig_or_mask, int __is_sig); +libc_hidden_proto(__sigpause) + +#ifdef __FAVOR_BSD +/* Set the mask of blocked signals to MASK, + wait for a signal to arrive, and then restore the mask. */ +extern int sigpause (int __mask) __THROW __attribute_deprecated__; +# define sigpause(mask) __sigpause ((mask), 0) +#else +# ifdef __USE_XOPEN +/* Remove a signal from the signal mask and suspend the process. */ +# define sigpause(sig) __sigpause ((sig), 1) +# endif +#endif + + +#ifdef __USE_BSD +/* None of the following functions should be used anymore. They are here + only for compatibility. A single word (`int') is not guaranteed to be + enough to hold a complete signal mask and therefore these functions + simply do not work in many situations. Use `sigprocmask' instead. */ + +/* Compute mask for signal SIG. */ +# define sigmask(sig) __sigmask(sig) + +/* Block signals in MASK, returning the old mask. */ +extern int sigblock (int __mask) __THROW; +/* collides with libc_hidden_proto: __attribute_deprecated__; */ +libc_hidden_proto(sigblock) + +/* Set the mask of blocked signals to MASK, returning the old mask. */ +extern int sigsetmask (int __mask) __THROW; +/* collides with libc_hidden_proto: __attribute_deprecated__; */ +libc_hidden_proto(sigsetmask) + +/* Return currently selected signal mask. */ +extern int siggetmask (void) __THROW __attribute_deprecated__; +#endif /* Use BSD. */ + + +#ifdef __USE_GNU +typedef __sighandler_t sighandler_t; +#endif + +/* 4.4 BSD uses the name `sig_t' for this. */ +#ifdef __USE_BSD +typedef __sighandler_t sig_t; +#endif + +#ifdef __USE_POSIX + +# ifdef __USE_POSIX199309 +/* We need `struct timespec' later on. */ +# define __need_timespec +# include + +/* Get the `siginfo_t' type plus the needed symbols. */ +# include +# endif + +/* Clear all signals from SET. */ +extern int sigemptyset (sigset_t *__set) __THROW __nonnull ((1)); +libc_hidden_proto(sigemptyset) + +/* Set all signals in SET. */ +extern int sigfillset (sigset_t *__set) __THROW __nonnull ((1)); +libc_hidden_proto(sigfillset) + +/* Add SIGNO to SET. */ +extern int sigaddset (sigset_t *__set, int __signo) __THROW __nonnull ((1)); +libc_hidden_proto(sigaddset) + +/* Remove SIGNO from SET. */ +extern int sigdelset (sigset_t *__set, int __signo) __THROW __nonnull ((1)); +libc_hidden_proto(sigdelset) + +/* Return 1 if SIGNO is in SET, 0 if not. */ +extern int sigismember (__const sigset_t *__set, int __signo) + __THROW __nonnull ((1)); + +# ifdef __USE_GNU +/* Return non-empty value is SET is not empty. */ +extern int sigisemptyset (__const sigset_t *__set) __THROW __nonnull ((1)); + +/* Build new signal set by combining the two inputs set using logical AND. */ +extern int sigandset (sigset_t *__set, __const sigset_t *__left, + __const sigset_t *__right) __THROW __nonnull ((1, 2, 3)); + +/* Build new signal set by combining the two inputs set using logical OR. */ +extern int sigorset (sigset_t *__set, __const sigset_t *__left, + __const sigset_t *__right) __THROW __nonnull ((1, 2, 3)); +# endif /* GNU */ + +/* Get the system-specific definitions of `struct sigaction' + and the `SA_*' and `SIG_*'. constants. */ +# include + +/* Get and/or change the set of blocked signals. */ +extern int sigprocmask (int __how, __const sigset_t *__restrict __set, + sigset_t *__restrict __oset) __THROW; +libc_hidden_proto(sigprocmask) + +/* Change the set of blocked signals to SET, + wait until a signal arrives, and restore the set of blocked signals. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern int sigsuspend (__const sigset_t *__set) __nonnull ((1)); +libc_hidden_proto(sigsuspend) + +/* Get and/or set the action for signal SIG. */ +extern int sigaction (int __sig, __const struct sigaction *__restrict __act, + struct sigaction *__restrict __oact) __THROW; +libc_hidden_proto(sigaction) + +/* Put in SET all signals that are blocked and waiting to be delivered. */ +extern int sigpending (sigset_t *__set) __THROW __nonnull ((1)); + + +/* Select any of pending signals from SET or wait for any to arrive. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern int sigwait (__const sigset_t *__restrict __set, int *__restrict __sig) + __nonnull ((1, 2)); + +# if defined __USE_POSIX199309 && defined __UCLIBC_HAS_REALTIME__ +/* Select any of pending signals from SET and place information in INFO. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern int sigwaitinfo (__const sigset_t *__restrict __set, + siginfo_t *__restrict __info) __nonnull ((1)); +libc_hidden_proto(sigwaitinfo) + +/* Select any of pending signals from SET and place information in INFO. + Wait the time specified by TIMEOUT if no signal is pending. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern int sigtimedwait (__const sigset_t *__restrict __set, + siginfo_t *__restrict __info, + __const struct timespec *__restrict __timeout) + __nonnull ((1)); +libc_hidden_proto(sigtimedwait) + +/* Send signal SIG to the process PID. Associate data in VAL with the + signal. */ +extern int sigqueue (__pid_t __pid, int __sig, __const union sigval __val) + __THROW; +# endif /* Use POSIX 199306. */ + +#endif /* Use POSIX. */ + +#ifdef __USE_BSD + +# ifdef __UCLIBC_HAS_SYS_SIGLIST__ +/* Names of the signals. This variable exists only for compatibility. + Use `strsignal' instead (see ). */ +# define _sys_siglist sys_siglist +extern __const char *__const sys_siglist[_NSIG]; +# endif + +/* Structure passed to `sigvec'. */ +struct sigvec + { + __sighandler_t sv_handler; /* Signal handler. */ + int sv_mask; /* Mask of signals to be blocked. */ + + int sv_flags; /* Flags (see below). */ +# define sv_onstack sv_flags /* 4.2 BSD compatibility. */ + }; + +/* Bits in `sv_flags'. */ +# define SV_ONSTACK (1 << 0)/* Take the signal on the signal stack. */ +# define SV_INTERRUPT (1 << 1)/* Do not restart system calls. */ +# define SV_RESETHAND (1 << 2)/* Reset handler to SIG_DFL on receipt. */ + + +/* If VEC is non-NULL, set the handler for SIG to the `sv_handler' member + of VEC. The signals in `sv_mask' will be blocked while the handler runs. + If the SV_RESETHAND bit is set in `sv_flags', the handler for SIG will be + reset to SIG_DFL before `sv_handler' is entered. If OVEC is non-NULL, + it is filled in with the old information for SIG. */ +extern int sigvec (int __sig, __const struct sigvec *__vec, + struct sigvec *__ovec) __THROW; + + +/* Get machine-dependent `struct sigcontext' and signal subcodes. */ +# include + +/* Restore the state saved in SCP. */ +extern int sigreturn (struct sigcontext *__scp) __THROW; + +#endif /* use BSD. */ + + +#if defined __USE_BSD || defined __USE_XOPEN_EXTENDED + +# ifdef __UCLIBC_SUSV4_LEGACY__ +/* If INTERRUPT is nonzero, make signal SIG interrupt system calls + (causing them to fail with EINTR); if INTERRUPT is zero, make system + calls be restarted after signal SIG. */ +extern int siginterrupt (int __sig, int __interrupt) __THROW; +# endif + +# include +# ifdef __USE_XOPEN +/* This will define `ucontext_t' and `mcontext_t'. */ +# include +# endif + +/* Run signals handlers on the stack specified by SS (if not NULL). + If OSS is not NULL, it is filled in with the old signal stack status. + This interface is obsolete and on many platform not implemented. */ +extern int sigstack (struct sigstack *__ss, struct sigstack *__oss) + __THROW __attribute_deprecated__; + +/* Alternate signal handler stack interface. + This interface should always be preferred over `sigstack'. */ +extern int sigaltstack (__const struct sigaltstack *__restrict __ss, + struct sigaltstack *__restrict __oss) __THROW; + +#endif /* use BSD or X/Open Unix. */ + +#if defined __USE_XOPEN_EXTENDED && defined __UCLIBC_HAS_OBSOLETE_BSD_SIGNAL__ +/* Simplified interface for signal management. */ + +/* Add SIG to the calling process' signal mask. */ +extern int sighold (int __sig) __THROW; + +/* Remove SIG from the calling process' signal mask. */ +extern int sigrelse (int __sig) __THROW; + +/* Set the disposition of SIG to SIG_IGN. */ +extern int sigignore (int __sig) __THROW; + +/* Set the disposition of SIG. */ +extern __sighandler_t sigset (int __sig, __sighandler_t __disp) __THROW; +#endif + +#if defined __UCLIBC_HAS_THREADS__ && (defined __USE_POSIX199506 || defined __USE_UNIX98) +/* Some of the functions for handling signals in threaded programs must + be defined here. */ +# include +# include +#endif + +/* The following functions are used internally in the C library and in + other code which need deep insights. */ + +/* Return number of available real-time signal with highest priority. */ +extern int __libc_current_sigrtmin (void) __THROW; +/* Return number of available real-time signal with lowest priority. */ +extern int __libc_current_sigrtmax (void) __THROW; + +#endif /* signal.h */ + +__END_DECLS + +#endif /* not signal.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/stdint.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/stdint.h new file mode 100644 index 00000000..465a1b5b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/stdint.h @@ -0,0 +1,332 @@ +/* Copyright (C) 1997,1998,1999,2000,2001,2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * ISO C99: 7.18 Integer types + */ + +#ifndef _STDINT_H +#define _STDINT_H 1 + +#include +#ifdef __UCLIBC_HAS_WCHAR__ +#include +#endif /* __UCLIBC_HAS_WCHAR__ */ +#include + +/* Exact integral types. */ + +/* Signed. */ + +/* There is some amount of overlap with as known by inet code */ +#ifndef __int8_t_defined +# define __int8_t_defined +typedef signed char int8_t; +typedef short int int16_t; +typedef int int32_t; +# if __WORDSIZE == 64 +typedef long int int64_t; +# else +__extension__ +typedef long long int int64_t; +# endif +#endif + +/* Unsigned. */ +typedef unsigned char uint8_t; +typedef unsigned short int uint16_t; +#ifndef __uint32_t_defined +typedef unsigned int uint32_t; +# define __uint32_t_defined +#endif +#if __WORDSIZE == 64 +typedef unsigned long int uint64_t; +#else +__extension__ +typedef unsigned long long int uint64_t; +#endif + + +/* Small types. */ + +/* Signed. */ +typedef signed char int_least8_t; +typedef short int int_least16_t; +typedef int int_least32_t; +#if __WORDSIZE == 64 +typedef long int int_least64_t; +#else +__extension__ +typedef long long int int_least64_t; +#endif + +/* Unsigned. */ +typedef unsigned char uint_least8_t; +typedef unsigned short int uint_least16_t; +typedef unsigned int uint_least32_t; +#if __WORDSIZE == 64 +typedef unsigned long int uint_least64_t; +#else +__extension__ +typedef unsigned long long int uint_least64_t; +#endif + + +/* Fast types. */ + +/* Signed. */ +typedef signed char int_fast8_t; +#if __WORDSIZE == 64 +typedef long int int_fast16_t; +typedef long int int_fast32_t; +typedef long int int_fast64_t; +#else +typedef int int_fast16_t; +typedef int int_fast32_t; +__extension__ +typedef long long int int_fast64_t; +#endif + +/* Unsigned. */ +typedef unsigned char uint_fast8_t; +#if __WORDSIZE == 64 +typedef unsigned long int uint_fast16_t; +typedef unsigned long int uint_fast32_t; +typedef unsigned long int uint_fast64_t; +#else +typedef unsigned int uint_fast16_t; +typedef unsigned int uint_fast32_t; +__extension__ +typedef unsigned long long int uint_fast64_t; +#endif + + +/* Types for `void *' pointers. */ +#if __WORDSIZE == 64 +# ifndef __intptr_t_defined +typedef long int intptr_t; +# define __intptr_t_defined +# endif +typedef unsigned long int uintptr_t; +#else +# ifndef __intptr_t_defined +typedef int intptr_t; +# define __intptr_t_defined +# endif +typedef unsigned int uintptr_t; +#endif + + +/* Largest integral types. */ +#if __WORDSIZE == 64 +typedef long int intmax_t; +typedef unsigned long int uintmax_t; +#else +__extension__ +typedef long long int intmax_t; +__extension__ +typedef unsigned long long int uintmax_t; +#endif + + +/* The ISO C99 standard specifies that in C++ implementations these + macros should only be defined if explicitly requested. */ +#if !defined __cplusplus || defined __STDC_LIMIT_MACROS + +# if __WORDSIZE == 64 +# define __INT64_C(c) c ## L +# define __UINT64_C(c) c ## UL +# else +# define __INT64_C(c) c ## LL +# define __UINT64_C(c) c ## ULL +# endif + +/* Limits of integral types. */ + +/* Minimum of signed integral types. */ +# define INT8_MIN (-128) +# define INT16_MIN (-32767-1) +# define INT32_MIN (-2147483647-1) +# define INT64_MIN (-__INT64_C(9223372036854775807)-1) +/* Maximum of signed integral types. */ +# define INT8_MAX (127) +# define INT16_MAX (32767) +# define INT32_MAX (2147483647) +# define INT64_MAX (__INT64_C(9223372036854775807)) + +/* Maximum of unsigned integral types. */ +# define UINT8_MAX (255) +# define UINT16_MAX (65535) +# define UINT32_MAX (4294967295U) +# define UINT64_MAX (__UINT64_C(18446744073709551615)) + + +/* Minimum of signed integral types having a minimum size. */ +# define INT_LEAST8_MIN (-128) +# define INT_LEAST16_MIN (-32767-1) +# define INT_LEAST32_MIN (-2147483647-1) +# define INT_LEAST64_MIN (-__INT64_C(9223372036854775807)-1) +/* Maximum of signed integral types having a minimum size. */ +# define INT_LEAST8_MAX (127) +# define INT_LEAST16_MAX (32767) +# define INT_LEAST32_MAX (2147483647) +# define INT_LEAST64_MAX (__INT64_C(9223372036854775807)) + +/* Maximum of unsigned integral types having a minimum size. */ +# define UINT_LEAST8_MAX (255) +# define UINT_LEAST16_MAX (65535) +# define UINT_LEAST32_MAX (4294967295U) +# define UINT_LEAST64_MAX (__UINT64_C(18446744073709551615)) + + +/* Minimum of fast signed integral types having a minimum size. */ +# define INT_FAST8_MIN (-128) +# if __WORDSIZE == 64 +# define INT_FAST16_MIN (-9223372036854775807L-1) +# define INT_FAST32_MIN (-9223372036854775807L-1) +# else +# define INT_FAST16_MIN (-2147483647-1) +# define INT_FAST32_MIN (-2147483647-1) +# endif +# define INT_FAST64_MIN (-__INT64_C(9223372036854775807)-1) +/* Maximum of fast signed integral types having a minimum size. */ +# define INT_FAST8_MAX (127) +# if __WORDSIZE == 64 +# define INT_FAST16_MAX (9223372036854775807L) +# define INT_FAST32_MAX (9223372036854775807L) +# else +# define INT_FAST16_MAX (2147483647) +# define INT_FAST32_MAX (2147483647) +# endif +# define INT_FAST64_MAX (__INT64_C(9223372036854775807)) + +/* Maximum of fast unsigned integral types having a minimum size. */ +# define UINT_FAST8_MAX (255) +# if __WORDSIZE == 64 +# define UINT_FAST16_MAX (18446744073709551615UL) +# define UINT_FAST32_MAX (18446744073709551615UL) +# else +# define UINT_FAST16_MAX (4294967295U) +# define UINT_FAST32_MAX (4294967295U) +# endif +# define UINT_FAST64_MAX (__UINT64_C(18446744073709551615)) + + +/* Values to test for integral types holding `void *' pointer. */ +# if __WORDSIZE == 64 +# define INTPTR_MIN (-9223372036854775807L-1) +# define INTPTR_MAX (9223372036854775807L) +# define UINTPTR_MAX (18446744073709551615UL) +# else +# define INTPTR_MIN (-2147483647-1) +# define INTPTR_MAX (2147483647) +# define UINTPTR_MAX (4294967295U) +# endif + +#if !defined(__H8300H__) && !defined(__H8300S__) +/* Minimum for largest signed integral type. */ +# define INTMAX_MIN (-__INT64_C(9223372036854775807)-1) +/* Maximum for largest signed integral type. */ +# define INTMAX_MAX (__INT64_C(9223372036854775807)) + +/* Maximum for largest unsigned integral type. */ +# define UINTMAX_MAX (__UINT64_C(18446744073709551615)) +#else +/* Minimum for largest signed integral type. */ +# define INTMAX_MIN (-LONG_LONG_MAX-1) +/* Maximum for largest signed integral type. */ +# define INTMAX_MAX (LONG_LONG_MAX) + +/* Maximum for largest unsigned integral type. */ +# define UINTMAX_MAX (LONG_LONG_MAX<<1+1) +#endif + +/* Limits of other integer types. */ + +/* Limits of `ptrdiff_t' type. */ +# if __WORDSIZE == 64 +# define PTRDIFF_MIN (-9223372036854775807L-1) +# define PTRDIFF_MAX (9223372036854775807L) +# else +# define PTRDIFF_MIN (-2147483647-1) +# define PTRDIFF_MAX (2147483647) +# endif + +/* Limits of `sig_atomic_t'. */ +# define SIG_ATOMIC_MIN (-2147483647-1) +# define SIG_ATOMIC_MAX (2147483647) + +/* Limit of `size_t' type. */ +# if __WORDSIZE == 64 +# define SIZE_MAX (18446744073709551615UL) +# else +# define SIZE_MAX (4294967295U) +# endif + +#ifdef __UCLIBC_HAS_WCHAR__ +/* Limits of `wchar_t'. */ +# ifndef WCHAR_MIN +/* These constants might also be defined in . */ +# define WCHAR_MIN __WCHAR_MIN +# define WCHAR_MAX __WCHAR_MAX +# endif + +/* Limits of `wint_t'. */ +# define WINT_MIN (0u) +# define WINT_MAX (4294967295u) +#endif /* __UCLIBC_HAS_WCHAR__ */ + +#endif /* C++ && limit macros */ + + +/* The ISO C99 standard specifies that in C++ implementations these + should only be defined if explicitly requested. */ +#if !defined __cplusplus || defined __STDC_CONSTANT_MACROS + +/* Signed. */ +# define INT8_C(c) c +# define INT16_C(c) c +# define INT32_C(c) c +# if __WORDSIZE == 64 +# define INT64_C(c) c ## L +# else +# define INT64_C(c) c ## LL +# endif + +/* Unsigned. */ +# define UINT8_C(c) c +# define UINT16_C(c) c +# define UINT32_C(c) c ## U +# if __WORDSIZE == 64 +# define UINT64_C(c) c ## UL +# else +# define UINT64_C(c) c ## ULL +# endif + +/* Maximal type. */ +# if __WORDSIZE == 64 +# define INTMAX_C(c) c ## L +# define UINTMAX_C(c) c ## UL +# else +# define INTMAX_C(c) c ## LL +# define UINTMAX_C(c) c ## ULL +# endif + +#endif /* C++ && constant macros */ + +#endif /* stdint.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/stdio.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/stdio.h new file mode 100644 index 00000000..3c86f256 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/stdio.h @@ -0,0 +1,938 @@ +/* + Copyright (C) 1991,1994-2002,2003,2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * ISO C99 Standard: 7.19 Input/output + */ + +#ifndef _STDIO_H + +#if !defined __need_FILE && !defined __need___FILE +# define _STDIO_H 1 +# include + +__BEGIN_DECLS + +# define __need_size_t +# define __need_NULL +# include + +# include +# define __need_FILE +# define __need___FILE +#endif /* Don't need FILE. */ + + +#if !defined __FILE_defined && defined __need_FILE + +__BEGIN_NAMESPACE_STD +/* The opaque type of streams. This is the definition used elsewhere. */ +typedef struct __STDIO_FILE_STRUCT FILE; +__END_NAMESPACE_STD +#if defined __USE_LARGEFILE64 || defined __USE_SVID || defined __USE_POSIX \ + || defined __USE_BSD || defined __USE_ISOC99 || defined __USE_XOPEN \ + || defined __USE_POSIX2 +__USING_NAMESPACE_STD(FILE) +#endif + +# define __FILE_defined 1 +#endif /* FILE not defined. */ +#undef __need_FILE + + +#if !defined ____FILE_defined && defined __need___FILE + +/* The opaque type of streams. This is the definition used elsewhere. */ +typedef struct __STDIO_FILE_STRUCT __FILE; + +# define ____FILE_defined 1 +#endif /* __FILE not defined. */ +#undef __need___FILE + + +#ifdef _STDIO_H +#undef _STDIO_USES_IOSTREAM + +#include + +/* This define avoids name pollution if we're using GNU stdarg.h */ +# define __need___va_list +#include + +/* The type of the second argument to `fgetpos' and `fsetpos'. */ +__BEGIN_NAMESPACE_STD +#ifndef __USE_FILE_OFFSET64 +typedef __STDIO_fpos_t fpos_t; +#else +typedef __STDIO_fpos64_t fpos_t; +#endif +__END_NAMESPACE_STD +#ifdef __USE_LARGEFILE64 +typedef __STDIO_fpos64_t fpos64_t; +#endif + +/* The possibilities for the third argument to `setvbuf'. */ +#define _IOFBF __STDIO_IOFBF /* Fully buffered. */ +#define _IOLBF __STDIO_IOLBF /* Line buffered. */ +#define _IONBF __STDIO_IONBF /* No buffering. */ + + +/* Default buffer size. */ +#ifndef BUFSIZ +# define BUFSIZ __STDIO_BUFSIZ +#endif + + +/* End of file character. + Some things throughout the library rely on this being -1. */ +#ifndef EOF +# define EOF (-1) +#endif + + +/* The possibilities for the third argument to `fseek'. + These values should not be changed. */ +#define SEEK_SET 0 /* Seek from beginning of file. */ +#define SEEK_CUR 1 /* Seek from current position. */ +#define SEEK_END 2 /* Seek from end of file. */ + + +#if defined __USE_SVID || defined __USE_XOPEN +/* Default path prefix for `tempnam' and `tmpnam'. */ +# define P_tmpdir "/tmp" +#endif + + +/* Get the values: + L_tmpnam How long an array of chars must be to be passed to `tmpnam'. + TMP_MAX The minimum number of unique filenames generated by tmpnam + (and tempnam when it uses tmpnam's name space), + or tempnam (the two are separate). + L_ctermid How long an array to pass to `ctermid'. + L_cuserid How long an array to pass to `cuserid'. + FOPEN_MAX Minimum number of files that can be open at once. + FILENAME_MAX Maximum length of a filename. */ +#include + + +/* Standard streams. */ +extern FILE *stdin; /* Standard input stream. */ +extern FILE *stdout; /* Standard output stream. */ +extern FILE *stderr; /* Standard error output stream. */ +/* C89/C99 say they're macros. Make them happy. */ +#define stdin stdin +#define stdout stdout +#define stderr stderr + +__BEGIN_NAMESPACE_STD +/* Remove file FILENAME. */ +extern int remove (__const char *__filename) __THROW; +libc_hidden_proto(remove) +/* Rename file OLD to NEW. */ +extern int rename (__const char *__old, __const char *__new) __THROW; +__END_NAMESPACE_STD + +#ifdef __USE_ATFILE +/* Rename file OLD relative to OLDFD to NEW relative to NEWFD. */ +extern int renameat (int __oldfd, __const char *__old, int __newfd, + __const char *__new) __THROW; +#endif + +__BEGIN_NAMESPACE_STD +/* Create a temporary file and open it read/write. + + This function is a possible cancellation points and therefore not + marked with __THROW. */ +#ifndef __USE_FILE_OFFSET64 +extern FILE *tmpfile (void) __wur; +#else +# ifdef __REDIRECT +extern FILE *__REDIRECT (tmpfile, (void), tmpfile64) __wur; +# else +# define tmpfile tmpfile64 +# endif +#endif + +#ifdef __USE_LARGEFILE64 +extern FILE *tmpfile64 (void) __wur; +#endif + +/* Generate a temporary filename. */ +extern char *tmpnam (char *__s) __THROW __wur; +__END_NAMESPACE_STD + +#ifdef __USE_MISC +/* This is the reentrant variant of `tmpnam'. The only difference is + that it does not allow S to be NULL. */ +extern char *tmpnam_r (char *__s) __THROW __wur; +#endif + + +#if defined __USE_SVID || defined __USE_XOPEN +/* Generate a unique temporary filename using up to five characters of PFX + if it is not NULL. The directory to put this file in is searched for + as follows: First the environment variable "TMPDIR" is checked. + If it contains the name of a writable directory, that directory is used. + If not and if DIR is not NULL, that value is checked. If that fails, + P_tmpdir is tried and finally "/tmp". The storage for the filename + is allocated by `malloc'. */ +extern char *tempnam (__const char *__dir, __const char *__pfx) + __THROW __attribute_malloc__ __wur; +#endif + + +__BEGIN_NAMESPACE_STD +/* Close STREAM. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern int fclose (FILE *__stream); +libc_hidden_proto(fclose) +/* Flush STREAM, or all streams if STREAM is NULL. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern int fflush (FILE *__stream); +libc_hidden_proto(fflush) +__END_NAMESPACE_STD + +#ifdef __USE_MISC +/* Faster versions when locking is not required. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern int fflush_unlocked (FILE *__stream); +libc_hidden_proto(fflush_unlocked) +#endif + +#ifdef __USE_GNU +/* Close all streams. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern int fcloseall (void); +#endif + + +__BEGIN_NAMESPACE_STD +#ifndef __USE_FILE_OFFSET64 +/* Open a file and create a new stream for it. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern FILE *fopen (__const char *__restrict __filename, + __const char *__restrict __modes) __wur; +libc_hidden_proto(fopen) +/* Open a file, replacing an existing stream with it. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern FILE *freopen (__const char *__restrict __filename, + __const char *__restrict __modes, + FILE *__restrict __stream) __wur; +#else +# ifdef __REDIRECT +extern FILE *__REDIRECT (fopen, (__const char *__restrict __filename, + __const char *__restrict __modes), fopen64) + __wur; +extern FILE *__REDIRECT (freopen, (__const char *__restrict __filename, + __const char *__restrict __modes, + FILE *__restrict __stream), freopen64) + __wur; +# else +# define fopen fopen64 +# define freopen freopen64 +# endif +#endif +__END_NAMESPACE_STD +#ifdef __USE_LARGEFILE64 +extern FILE *fopen64 (__const char *__restrict __filename, + __const char *__restrict __modes) __wur; +libc_hidden_proto(fopen64) +extern FILE *freopen64 (__const char *__restrict __filename, + __const char *__restrict __modes, + FILE *__restrict __stream) __wur; +#endif + +#ifdef __USE_POSIX +/* Create a new stream that refers to an existing system file descriptor. */ +extern FILE *fdopen (int __fd, __const char *__modes) __THROW __wur; +libc_hidden_proto(fdopen) +#endif + +#ifdef __USE_GNU +#ifdef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ +/* Create a new stream that refers to the given magic cookie, + and uses the given functions for input and output. */ +extern FILE *fopencookie (void *__restrict __magic_cookie, + __const char *__restrict __modes, + _IO_cookie_io_functions_t __io_funcs) __THROW __wur; +libc_hidden_proto(fopencookie) + +/* Create a new stream that refers to a memory buffer. */ +extern FILE *fmemopen (void *__s, size_t __len, __const char *__modes) + __THROW __wur; + +/* Open a stream that writes into a malloc'd buffer that is expanded as + necessary. *BUFLOC and *SIZELOC are updated with the buffer's location + and the number of characters written on fflush or fclose. */ +extern FILE *open_memstream (char **__restrict __bufloc, + size_t *__restrict __sizeloc) __THROW __wur; +libc_hidden_proto(open_memstream) +#endif +#endif + + +__BEGIN_NAMESPACE_STD +/* If BUF is NULL, make STREAM unbuffered. + Else make it use buffer BUF, of size BUFSIZ. */ +extern void setbuf (FILE *__restrict __stream, char *__restrict __buf) __THROW; +/* Make STREAM use buffering mode MODE. + If BUF is not NULL, use N bytes of it for buffering; + else allocate an internal buffer N bytes long. */ +extern int setvbuf (FILE *__restrict __stream, char *__restrict __buf, + int __modes, size_t __n) __THROW; +libc_hidden_proto(setvbuf) +__END_NAMESPACE_STD + +#ifdef __USE_BSD +/* If BUF is NULL, make STREAM unbuffered. + Else make it use SIZE bytes of BUF for buffering. */ +extern void setbuffer (FILE *__restrict __stream, char *__restrict __buf, + size_t __size) __THROW; + +/* Make STREAM line-buffered. */ +extern void setlinebuf (FILE *__stream) __THROW; +#endif + + +__BEGIN_NAMESPACE_STD +/* Write formatted output to STREAM. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern int fprintf (FILE *__restrict __stream, + __const char *__restrict __format, ...); +libc_hidden_proto(fprintf) +/* Write formatted output to stdout. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern int printf (__const char *__restrict __format, ...); +libc_hidden_proto(printf) +/* Write formatted output to S. */ +extern int sprintf (char *__restrict __s, + __const char *__restrict __format, ...) + __THROW __attribute__ ((__format__ (__printf__, 2, 3))); +libc_hidden_proto(sprintf) + +/* Write formatted output to S from argument list ARG. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern int vfprintf (FILE *__restrict __s, __const char *__restrict __format, + __gnuc_va_list __arg); +libc_hidden_proto(vfprintf) +/* Write formatted output to stdout from argument list ARG. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern int vprintf (__const char *__restrict __format, __gnuc_va_list __arg); +/* Write formatted output to S from argument list ARG. */ +extern int vsprintf (char *__restrict __s, __const char *__restrict __format, + __gnuc_va_list __arg) + __THROW __attribute__ ((__format__ (__printf__, 2, 0))); +__END_NAMESPACE_STD + +#if defined __USE_BSD || defined __USE_ISOC99 || defined __USE_UNIX98 +__BEGIN_NAMESPACE_C99 +/* Maximum chars of output to write in MAXLEN. */ +extern int snprintf (char *__restrict __s, size_t __maxlen, + __const char *__restrict __format, ...) + __THROW __attribute__ ((__format__ (__printf__, 3, 4))); +libc_hidden_proto(snprintf) + +extern int vsnprintf (char *__restrict __s, size_t __maxlen, + __const char *__restrict __format, __gnuc_va_list __arg) + __THROW __attribute__ ((__format__ (__printf__, 3, 0))); +libc_hidden_proto(vsnprintf) +__END_NAMESPACE_C99 +#endif + +#ifdef __USE_GNU +/* Write formatted output to a string dynamically allocated with `malloc'. + Store the address of the string in *PTR. */ +extern int vasprintf (char **__restrict __ptr, __const char *__restrict __f, + __gnuc_va_list __arg) + __THROW __attribute__ ((__format__ (__printf__, 2, 0))) __wur; +libc_hidden_proto(vasprintf) +#if 0 /* uClibc: disabled */ +extern int __asprintf (char **__restrict __ptr, + __const char *__restrict __fmt, ...) + __THROW __attribute__ ((__format__ (__printf__, 2, 3))) __wur; +#endif +extern int asprintf (char **__restrict __ptr, + __const char *__restrict __fmt, ...) + __THROW __attribute__ ((__format__ (__printf__, 2, 3))) __wur; +libc_hidden_proto(asprintf) + +/* Write formatted output to a file descriptor. + + These functions are not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation they are cancellation points and + therefore not marked with __THROW. */ +extern int vdprintf (int __fd, __const char *__restrict __fmt, + __gnuc_va_list __arg) + __attribute__ ((__format__ (__printf__, 2, 0))); +libc_hidden_proto(vdprintf) +extern int dprintf (int __fd, __const char *__restrict __fmt, ...) + __attribute__ ((__format__ (__printf__, 2, 3))); +#endif + + +__BEGIN_NAMESPACE_STD +/* Read formatted input from STREAM. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern int fscanf (FILE *__restrict __stream, + __const char *__restrict __format, ...) + __attribute__ ((__format__ (__scanf__, 2, 3))) __wur; +libc_hidden_proto(fscanf) +/* Read formatted input from stdin. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern int scanf (__const char *__restrict __format, ...) + __attribute__ ((__format__ (__scanf__, 1, 2))) __wur; +/* Read formatted input from S. */ +extern int sscanf (__const char *__restrict __s, + __const char *__restrict __format, ...) + __THROW __attribute__ ((__format__ (__scanf__, 2, 3))); +libc_hidden_proto(sscanf) +__END_NAMESPACE_STD + +#ifdef __USE_ISOC99 +__BEGIN_NAMESPACE_C99 +/* Read formatted input from S into argument list ARG. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern int vfscanf (FILE *__restrict __s, __const char *__restrict __format, + __gnuc_va_list __arg) + __attribute__ ((__format__ (__scanf__, 2, 0))) __wur; +libc_hidden_proto(vfscanf) + +/* Read formatted input from stdin into argument list ARG. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern int vscanf (__const char *__restrict __format, __gnuc_va_list __arg) + __attribute__ ((__format__ (__scanf__, 1, 0))) __wur; +libc_hidden_proto(vscanf) + +/* Read formatted input from S into argument list ARG. */ +extern int vsscanf (__const char *__restrict __s, + __const char *__restrict __format, __gnuc_va_list __arg) + __THROW __attribute__ ((__format__ (__scanf__, 2, 0))); +libc_hidden_proto(vsscanf) +__END_NAMESPACE_C99 +#endif /* Use ISO C9x. */ + + +__BEGIN_NAMESPACE_STD +/* Read a character from STREAM. + + These functions are possible cancellation points and therefore not + marked with __THROW. */ +extern int fgetc (FILE *__stream); +libc_hidden_proto(fgetc) +extern int getc (FILE *__stream); + +/* Read a character from stdin. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern int getchar (void); +__END_NAMESPACE_STD + +/* The C standard explicitly says this is a macro, so we always do the + optimization for it. */ +#define getc(_fp) __GETC(_fp) + +#if defined __USE_POSIX || defined __USE_MISC +/* These are defined in POSIX.1:1996. + + These functions are possible cancellation points and therefore not + marked with __THROW. */ +extern int getc_unlocked (FILE *__stream); +libc_hidden_proto(getc_unlocked) +extern int getchar_unlocked (void); +libc_hidden_proto(getchar_unlocked) + +/* SUSv3 allows getc_unlocked to be a macro */ +#define getc_unlocked(_fp) __GETC_UNLOCKED(_fp) +#endif /* Use POSIX or MISC. */ + +#ifdef __USE_MISC +/* Faster version when locking is not necessary. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern int fgetc_unlocked (FILE *__stream); +libc_hidden_proto(fgetc_unlocked) +#endif /* Use MISC. */ + + +__BEGIN_NAMESPACE_STD +/* Write a character to STREAM. + + These functions are possible cancellation points and therefore not + marked with __THROW. + + These functions is a possible cancellation point and therefore not + marked with __THROW. */ +extern int fputc (int __c, FILE *__stream); +libc_hidden_proto(fputc) +extern int putc (int __c, FILE *__stream); +libc_hidden_proto(putc) + +/* Write a character to stdout. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern int putchar (int __c); +__END_NAMESPACE_STD + +/* The C standard explicitly says this can be a macro, + so we always do the optimization for it. */ +#define putc(_ch, _fp) __PUTC(_ch, _fp) + +#ifdef __USE_MISC +/* Faster version when locking is not necessary. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern int fputc_unlocked (int __c, FILE *__stream); +libc_hidden_proto(fputc_unlocked) +#endif /* Use MISC. */ + +#if defined __USE_POSIX || defined __USE_MISC +/* These are defined in POSIX.1:1996. + + These functions are possible cancellation points and therefore not + marked with __THROW. */ +extern int putc_unlocked (int __c, FILE *__stream); +libc_hidden_proto(putc_unlocked) +extern int putchar_unlocked (int __c); + +/* SUSv3 allows putc_unlocked to be a macro */ +#define putc_unlocked(_ch, _fp) __PUTC_UNLOCKED(_ch, _fp) +#endif /* Use POSIX or MISC. */ + + +#if defined __USE_SVID || defined __USE_MISC \ + || (defined __USE_XOPEN && !defined __USE_XOPEN2K) +/* Get a word (int) from STREAM. */ +extern int getw (FILE *__stream); + +/* Write a word (int) to STREAM. */ +extern int putw (int __w, FILE *__stream); +#endif + + +__BEGIN_NAMESPACE_STD +/* Get a newline-terminated string of finite length from STREAM. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern char *fgets (char *__restrict __s, int __n, FILE *__restrict __stream) + __wur; +libc_hidden_proto(fgets) + +/* Get a newline-terminated string from stdin, removing the newline. + DO NOT USE THIS FUNCTION!! There is no limit on how much it will read. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern char *gets (char *__s) __wur; +__END_NAMESPACE_STD + +#ifdef __USE_GNU +/* This function does the same as `fgets' but does not lock the stream. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern char *fgets_unlocked (char *__restrict __s, int __n, + FILE *__restrict __stream) __wur; +libc_hidden_proto(fgets_unlocked) +#endif + + +#ifdef __USE_GNU +/* Read up to (and including) a DELIMITER from STREAM into *LINEPTR + (and null-terminate it). *LINEPTR is a pointer returned from malloc (or + NULL), pointing to *N characters of space. It is realloc'd as + necessary. Returns the number of characters read (not including the + null terminator), or -1 on error or EOF. + + These functions are not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation they are cancellation points and + therefore not marked with __THROW. */ +#if 0 /* uClibc: disabled */ +extern __ssize_t __getdelim (char **__restrict __lineptr, + size_t *__restrict __n, int __delimiter, + FILE *__restrict __stream) __wur; +#endif +extern __ssize_t getdelim (char **__restrict __lineptr, + size_t *__restrict __n, int __delimiter, + FILE *__restrict __stream) __wur; +libc_hidden_proto(getdelim) + +/* Like `getdelim', but reads up to a newline. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern __ssize_t getline (char **__restrict __lineptr, + size_t *__restrict __n, + FILE *__restrict __stream) __wur; +libc_hidden_proto(getline) +#endif + + +__BEGIN_NAMESPACE_STD +/* Write a string to STREAM. + + This function is a possible cancellation points and therefore not + marked with __THROW. */ +extern int fputs (__const char *__restrict __s, FILE *__restrict __stream); +libc_hidden_proto(fputs) + +/* Write a string, followed by a newline, to stdout. + + This function is a possible cancellation points and therefore not + marked with __THROW. */ +extern int puts (__const char *__s); + + +/* Push a character back onto the input buffer of STREAM. + + This function is a possible cancellation points and therefore not + marked with __THROW. */ +extern int ungetc (int __c, FILE *__stream); +libc_hidden_proto(ungetc) + + +/* Read chunks of generic data from STREAM. + + This function is a possible cancellation points and therefore not + marked with __THROW. */ +extern size_t fread (void *__restrict __ptr, size_t __size, + size_t __n, FILE *__restrict __stream) __wur; +libc_hidden_proto(fread) +/* Write chunks of generic data to STREAM. + + This function is a possible cancellation points and therefore not + marked with __THROW. */ +extern size_t fwrite (__const void *__restrict __ptr, size_t __size, + size_t __n, FILE *__restrict __s) __wur; +libc_hidden_proto(fwrite) +__END_NAMESPACE_STD + +#ifdef __USE_GNU +/* This function does the same as `fputs' but does not lock the stream. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern int fputs_unlocked (__const char *__restrict __s, + FILE *__restrict __stream); +libc_hidden_proto(fputs_unlocked) +#endif + +#ifdef __USE_MISC +/* Faster versions when locking is not necessary. + + These functions are not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation they are cancellation points and + therefore not marked with __THROW. */ +extern size_t fread_unlocked (void *__restrict __ptr, size_t __size, + size_t __n, FILE *__restrict __stream) __wur; +libc_hidden_proto(fread_unlocked) +extern size_t fwrite_unlocked (__const void *__restrict __ptr, size_t __size, + size_t __n, FILE *__restrict __stream) __wur; +libc_hidden_proto(fwrite_unlocked) +#endif + + +__BEGIN_NAMESPACE_STD +/* Seek to a certain position on STREAM. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern int fseek (FILE *__stream, long int __off, int __whence); +libc_hidden_proto(fseek) +/* Return the current position of STREAM. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern long int ftell (FILE *__stream) __wur; +libc_hidden_proto(ftell) +/* Rewind to the beginning of STREAM. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern void rewind (FILE *__stream); +libc_hidden_proto(rewind) +__END_NAMESPACE_STD + +/* The Single Unix Specification, Version 2, specifies an alternative, + more adequate interface for the two functions above which deal with + file offset. `long int' is not the right type. These definitions + are originally defined in the Large File Support API. */ + +#if defined __USE_LARGEFILE || defined __USE_XOPEN2K +# ifndef __USE_FILE_OFFSET64 +/* Seek to a certain position on STREAM. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern int fseeko (FILE *__stream, __off_t __off, int __whence); +/* Return the current position of STREAM. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern __off_t ftello (FILE *__stream) __wur; +# else +# ifdef __REDIRECT +extern int __REDIRECT (fseeko, + (FILE *__stream, __off64_t __off, int __whence), + fseeko64); +extern __off64_t __REDIRECT (ftello, (FILE *__stream), ftello64); +# else +# define fseeko fseeko64 +# define ftello ftello64 +# endif +# endif +#endif + +__BEGIN_NAMESPACE_STD +#ifndef __USE_FILE_OFFSET64 +/* Get STREAM's position. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern int fgetpos (FILE *__restrict __stream, fpos_t *__restrict __pos); +/* Set STREAM's position. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern int fsetpos (FILE *__stream, __const fpos_t *__pos); +#else +# ifdef __REDIRECT +extern int __REDIRECT (fgetpos, (FILE *__restrict __stream, + fpos_t *__restrict __pos), fgetpos64); +extern int __REDIRECT (fsetpos, + (FILE *__stream, __const fpos_t *__pos), fsetpos64); +# else +# define fgetpos fgetpos64 +# define fsetpos fsetpos64 +# endif +#endif +__END_NAMESPACE_STD + +#ifdef __USE_LARGEFILE64 +extern int fseeko64 (FILE *__stream, __off64_t __off, int __whence); +libc_hidden_proto(fseeko64) +extern __off64_t ftello64 (FILE *__stream) __wur; +libc_hidden_proto(ftello64) +extern int fgetpos64 (FILE *__restrict __stream, fpos64_t *__restrict __pos); +extern int fsetpos64 (FILE *__stream, __const fpos64_t *__pos); +#endif + +__BEGIN_NAMESPACE_STD +/* Clear the error and EOF indicators for STREAM. */ +extern void clearerr (FILE *__stream) __THROW; +/* Return the EOF indicator for STREAM. */ +extern int feof (FILE *__stream) __THROW __wur; +/* Return the error indicator for STREAM. */ +extern int ferror (FILE *__stream) __THROW __wur; +__END_NAMESPACE_STD + +#ifdef __USE_MISC +/* Faster versions when locking is not required. */ +extern void clearerr_unlocked (FILE *__stream) __THROW; +extern int feof_unlocked (FILE *__stream) __THROW __wur; +extern int ferror_unlocked (FILE *__stream) __THROW __wur; +#endif + + +__BEGIN_NAMESPACE_STD +/* Print a message describing the meaning of the value of errno. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern void perror (__const char *__s); +libc_hidden_proto(perror) +__END_NAMESPACE_STD + +#ifdef __UCLIBC_HAS_SYS_ERRLIST__ +/* These variables normally should not be used directly. The `strerror' + function provides all the needed functionality. */ +#ifdef __USE_BSD +extern int sys_nerr; +extern __const char *__const sys_errlist[]; +#endif +#endif /* __UCLIBC_HAS_SYS_ERRLIST__ */ + + +#ifdef __USE_POSIX +/* Return the system file descriptor for STREAM. */ +extern int fileno (FILE *__stream) __THROW __wur; +libc_hidden_proto(fileno) +#endif /* Use POSIX. */ + +#ifdef __USE_MISC +/* Faster version when locking is not required. */ +extern int fileno_unlocked (FILE *__stream) __THROW __wur; +libc_hidden_proto(fileno_unlocked) +#endif + + +#if (defined __USE_POSIX2 || defined __USE_SVID || defined __USE_BSD || \ + defined __USE_MISC) +/* Create a new stream connected to a pipe running the given command. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern FILE *popen (__const char *__command, __const char *__modes) __wur; + +/* Close a stream opened by popen and return the status of its child. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern int pclose (FILE *__stream); +#endif + + +#ifdef __USE_POSIX +/* Return the name of the controlling terminal. */ +extern char *ctermid (char *__s) __THROW; +#endif /* Use POSIX. */ + + +#ifdef __USE_XOPEN +/* Return the name of the current user. */ +extern char *cuserid (char *__s); +#endif /* Use X/Open, but not issue 6. */ + + +#if 0 /* def __USE_GNU uClibc note: not supported */ +struct obstack; /* See . */ + +/* Write formatted output to an obstack. */ +extern int obstack_printf (struct obstack *__restrict __obstack, + __const char *__restrict __format, ...) + __THROW __attribute__ ((__format__ (__printf__, 2, 3))); +extern int obstack_vprintf (struct obstack *__restrict __obstack, + __const char *__restrict __format, + __gnuc_va_list __args) + __THROW __attribute__ ((__format__ (__printf__, 2, 0))); +#endif /* Use GNU. */ + + +#if defined __USE_POSIX || defined __USE_MISC +/* These are defined in POSIX.1:1996. */ + +/* Acquire ownership of STREAM. */ +extern void flockfile (FILE *__stream) __THROW; + +/* Try to acquire ownership of STREAM but do not block if it is not + possible. */ +extern int ftrylockfile (FILE *__stream) __THROW __wur; + +/* Relinquish the ownership granted for STREAM. */ +extern void funlockfile (FILE *__stream) __THROW; +#endif /* POSIX || misc */ + +#if defined __USE_XOPEN && !defined __USE_XOPEN2K && !defined __USE_GNU +/* The X/Open standard requires some functions and variables to be + declared here which do not belong into this header. But we have to + follow. In GNU mode we don't do this nonsense. */ +# define __need_getopt +# include +#endif /* X/Open, but not issue 6 and not for GNU. */ + +/* If we are compiling with optimizing read this file. It contains + several optimizing inline functions and macros. */ +#define fgetc(_fp) __FGETC(_fp) +#define fputc(_ch, _fp) __FPUTC(_ch, _fp) + +#ifdef __USE_MISC +#define fgetc_unlocked(_fp) __FGETC_UNLOCKED(_fp) +#define fputc_unlocked(_ch, _fp) __FPUTC_UNLOCKED(_ch, _fp) +#endif + +#ifndef __STDIO_GETC_MACRO +#define __stdin stdin +#endif +#define getchar() __GETC(__stdin) + +#ifndef __STDIO_PUTC_MACRO +#define __stdout stdout +#endif +#define putchar(_ch) __PUTC((_ch), __stdout) + +#if defined __USE_POSIX || defined __USE_MISC +#define getchar_unlocked() __GETC_UNLOCKED(__stdin) +#define putchar_unlocked(_ch) __PUTC_UNLOCKED((_ch), __stdout) +#endif + +/* Clear the error and EOF indicators for STREAM. */ +#define clearerr(_fp) __CLEARERR(_fp) +#define feof(_fp) __FEOF(_fp) +#define ferror(_fp) __FERROR(_fp) + +#ifdef __USE_MISC +#define clearerr_unlocked(_fp) __CLEARERR_UNLOCKED(_fp) +#define feof_unlocked(_fp) __FEOF_UNLOCKED(_fp) +#define ferror_unlocked(_fp) __FERROR_UNLOCKED(_fp) +#endif + +__END_DECLS + +#endif /* included. */ + +#endif /* !_STDIO_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/stdio_ext.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/stdio_ext.h new file mode 100644 index 00000000..9ad54f65 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/stdio_ext.h @@ -0,0 +1,88 @@ +/* Functions to access FILE structure internals. + Copyright (C) 2000, 2001, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This header contains the same definitions as the header of the same name + on Sun's Solaris OS. */ + +#ifndef _STDIO_EXT_H +#define _STDIO_EXT_H 1 + +#include + +enum +{ + /* Query current state of the locking status. */ + FSETLOCKING_QUERY = 0, +#define FSETLOCKING_QUERY FSETLOCKING_QUERY + /* The library protects all uses of the stream functions, except for + uses of the *_unlocked functions, by calls equivalent to flockfile(). */ + FSETLOCKING_INTERNAL, +#define FSETLOCKING_INTERNAL FSETLOCKING_INTERNAL + /* The user will take care of locking. */ + FSETLOCKING_BYCALLER +#define FSETLOCKING_BYCALLER FSETLOCKING_BYCALLER +}; + + +__BEGIN_DECLS + +/* Return the size of the buffer of FP in bytes currently in use by + the given stream. */ +extern size_t __fbufsize (FILE *__fp) __THROW; + + +/* Return non-zero value iff the stream FP is opened readonly, or if the + last operation on the stream was a read operation. */ +extern int __freading (FILE *__fp) __THROW; + +/* Return non-zero value iff the stream FP is opened write-only or + append-only, or if the last operation on the stream was a write + operation. */ +extern int __fwriting (FILE *__fp) __THROW; + + +/* Return non-zero value iff stream FP is not opened write-only or + append-only. */ +extern int __freadable (FILE *__fp) __THROW; + +/* Return non-zero value iff stream FP is not opened read-only. */ +extern int __fwritable (FILE *__fp) __THROW; + + +/* Return non-zero value iff the stream FP is line-buffered. */ +extern int __flbf (FILE *__fp) __THROW; + + +/* Discard all pending buffered I/O on the stream FP. */ +extern void __fpurge (FILE *__fp) __THROW; + +/* Return amount of output in bytes pending on a stream FP. */ +extern size_t __fpending (FILE *__fp) __THROW; + +/* Flush all line-buffered files. */ +extern void _flushlbf (void); + + +/* Set locking status of stream FP to TYPE. */ +extern int __fsetlocking (FILE *__fp, int __type) __THROW; +libc_hidden_proto(__fsetlocking) + +__END_DECLS + +#endif /* stdio_ext.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/stdlib.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/stdlib.h new file mode 100644 index 00000000..300edf04 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/stdlib.h @@ -0,0 +1,906 @@ +/* Copyright (C) 1991-2007, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * ISO C99 Standard: 7.20 General utilities + */ + +#ifndef _STDLIB_H + +#include + +/* Get size_t, wchar_t and NULL from . */ +#define __need_size_t +#ifndef __need_malloc_and_calloc +# ifdef __UCLIBC_HAS_WCHAR__ +# define __need_wchar_t +# endif +# define __need_NULL +#endif +#include + +__BEGIN_DECLS + +#ifndef __need_malloc_and_calloc +#define _STDLIB_H 1 + +#if defined __USE_XOPEN && !defined _SYS_WAIT_H +/* XPG requires a few symbols from being defined. */ +# include +# include + +# ifdef __USE_BSD + +/* Lots of hair to allow traditional BSD use of `union wait' + as well as POSIX.1 use of `int' for the status word. */ + +# if defined __GNUC__ && !defined __cplusplus +# define __WAIT_INT(status) \ + (__extension__ ({ union { __typeof(status) __in; int __i; } __u; \ + __u.__in = (status); __u.__i; })) +# else +# define __WAIT_INT(status) (*(int *) &(status)) +# endif + +/* This is the type of the argument to `wait'. The funky union + causes redeclarations with either `int *' or `union wait *' to be + allowed without complaint. __WAIT_STATUS_DEFN is the type used in + the actual function definitions. */ + +# if !defined __GNUC__ || __GNUC__ < 2 || defined __cplusplus +# define __WAIT_STATUS void * +# define __WAIT_STATUS_DEFN void * +# else +/* This works in GCC 2.6.1 and later. */ +typedef union + { + union wait *__uptr; + int *__iptr; + } __WAIT_STATUS __attribute__ ((__transparent_union__)); +# define __WAIT_STATUS_DEFN int * +# endif + +# else /* Don't use BSD. */ + +# define __WAIT_INT(status) (status) +# define __WAIT_STATUS int * +# define __WAIT_STATUS_DEFN int * + +# endif /* Use BSD. */ + +/* Define the macros also would define this way. */ +# define WEXITSTATUS(status) __WEXITSTATUS (__WAIT_INT (status)) +# define WTERMSIG(status) __WTERMSIG (__WAIT_INT (status)) +# define WSTOPSIG(status) __WSTOPSIG (__WAIT_INT (status)) +# define WIFEXITED(status) __WIFEXITED (__WAIT_INT (status)) +# define WIFSIGNALED(status) __WIFSIGNALED (__WAIT_INT (status)) +# define WIFSTOPPED(status) __WIFSTOPPED (__WAIT_INT (status)) +# ifdef __WIFCONTINUED +# define WIFCONTINUED(status) __WIFCONTINUED (__WAIT_INT (status)) +# endif +#endif /* X/Open and not included. */ + +__BEGIN_NAMESPACE_STD +/* Returned by `div'. */ +typedef struct + { + int quot; /* Quotient. */ + int rem; /* Remainder. */ + } div_t; + +/* Returned by `ldiv'. */ +#ifndef __ldiv_t_defined +typedef struct + { + long int quot; /* Quotient. */ + long int rem; /* Remainder. */ + } ldiv_t; +# define __ldiv_t_defined 1 +#endif +__END_NAMESPACE_STD + +#if defined __USE_ISOC99 && !defined __lldiv_t_defined +__BEGIN_NAMESPACE_C99 +/* Returned by `lldiv'. */ +__extension__ typedef struct + { + long long int quot; /* Quotient. */ + long long int rem; /* Remainder. */ + } lldiv_t; +# define __lldiv_t_defined 1 +__END_NAMESPACE_C99 +#endif + + +/* The largest number rand will return (same as INT_MAX). */ +#define RAND_MAX 2147483647 + + +/* We define these the same for all machines. + Changes from this to the outside world should be done in `_exit'. */ +#define EXIT_FAILURE 1 /* Failing exit status. */ +#define EXIT_SUCCESS 0 /* Successful exit status. */ + + +/* Maximum length of a multibyte character in the current locale. */ +#if 0 +#define MB_CUR_MAX (__ctype_get_mb_cur_max ()) +extern size_t __ctype_get_mb_cur_max (void) __THROW __wur; +#else +#ifdef __UCLIBC_HAS_WCHAR__ +#define MB_CUR_MAX (_stdlib_mb_cur_max ()) +extern size_t _stdlib_mb_cur_max (void) __THROW __wur; +libc_hidden_proto(_stdlib_mb_cur_max) +#endif +#endif + + +__BEGIN_NAMESPACE_STD +#ifdef __UCLIBC_HAS_FLOATS__ +/* Convert a string to a floating-point number. */ +extern double atof (__const char *__nptr) + __THROW __attribute_pure__ __nonnull ((1)) __wur; +#endif /* __UCLIBC_HAS_FLOATS__ */ +/* Convert a string to an integer. */ +extern int atoi (__const char *__nptr) + __THROW __attribute_pure__ __nonnull ((1)) __wur; +libc_hidden_proto(atoi) +/* Convert a string to a long integer. */ +extern long int atol (__const char *__nptr) + __THROW __attribute_pure__ __nonnull ((1)) __wur; +libc_hidden_proto(atol) +__END_NAMESPACE_STD + +#if defined __USE_ISOC99 || defined __USE_MISC +__BEGIN_NAMESPACE_C99 +/* Convert a string to a long long integer. */ +__extension__ extern long long int atoll (__const char *__nptr) + __THROW __attribute_pure__ __nonnull ((1)) __wur; +__END_NAMESPACE_C99 +#endif + +#ifdef __UCLIBC_HAS_FLOATS__ +__BEGIN_NAMESPACE_STD +/* Convert a string to a floating-point number. */ +extern double strtod (__const char *__restrict __nptr, + char **__restrict __endptr) + __THROW __nonnull ((1)) __wur; +libc_hidden_proto(strtod) +__END_NAMESPACE_STD + +#ifdef __USE_ISOC99 +__BEGIN_NAMESPACE_C99 +/* Likewise for `float' and `long double' sizes of floating-point numbers. */ +extern float strtof (__const char *__restrict __nptr, + char **__restrict __endptr) __THROW __nonnull ((1)) __wur; + +extern long double strtold (__const char *__restrict __nptr, + char **__restrict __endptr) + __THROW __nonnull ((1)) __wur; +__END_NAMESPACE_C99 +#endif +#endif /* __UCLIBC_HAS_FLOATS__ */ + +__BEGIN_NAMESPACE_STD +/* Convert a string to a long integer. */ +extern long int strtol (__const char *__restrict __nptr, + char **__restrict __endptr, int __base) + __THROW __nonnull ((1)) __wur; +libc_hidden_proto(strtol) +/* Convert a string to an unsigned long integer. */ +extern unsigned long int strtoul (__const char *__restrict __nptr, + char **__restrict __endptr, int __base) + __THROW __nonnull ((1)) __wur; +libc_hidden_proto(strtoul) +__END_NAMESPACE_STD + +#ifdef __USE_BSD +#include /* for u_quad_t */ + +/* Convert a string to a quadword integer. */ +__extension__ +extern quad_t strtoq (__const char *__restrict __nptr, + char **__restrict __endptr, int __base) + __THROW __nonnull ((1)) __wur; +/* Convert a string to an unsigned quadword integer. */ +__extension__ +extern u_quad_t strtouq (__const char *__restrict __nptr, + char **__restrict __endptr, int __base) + __THROW __nonnull ((1)) __wur; +#endif /* GCC and use BSD. */ + +#if defined __USE_ISOC99 || defined __USE_MISC +__BEGIN_NAMESPACE_C99 +/* Convert a string to a quadword integer. */ +__extension__ +extern long long int strtoll (__const char *__restrict __nptr, + char **__restrict __endptr, int __base) + __THROW __nonnull ((1)) __wur; +libc_hidden_proto(strtoll) +/* Convert a string to an unsigned quadword integer. */ +__extension__ +extern unsigned long long int strtoull (__const char *__restrict __nptr, + char **__restrict __endptr, int __base) + __THROW __nonnull ((1)) __wur; +__END_NAMESPACE_C99 +#endif /* ISO C99 or GCC and use MISC. */ + + +#if defined __USE_GNU && defined __UCLIBC_HAS_XLOCALE__ +/* The concept of one static locale per category is not very well + thought out. Many applications will need to process its data using + information from several different locales. Another application is + the implementation of the internationalization handling in the + upcoming ISO C++ standard library. To support this another set of + the functions using locale data exist which have an additional + argument. + + Attention: all these functions are *not* standardized in any form. + This is a proof-of-concept implementation. */ + +/* Structure for reentrant locale using functions. This is an + (almost) opaque type for the user level programs. */ +# include + +/* Special versions of the functions above which take the locale to + use as an additional parameter. */ +extern long int strtol_l (__const char *__restrict __nptr, + char **__restrict __endptr, int __base, + __locale_t __loc) __THROW __nonnull ((1, 4)) __wur; +libc_hidden_proto(strtol_l) + +extern unsigned long int strtoul_l (__const char *__restrict __nptr, + char **__restrict __endptr, + int __base, __locale_t __loc) + __THROW __nonnull ((1, 4)) __wur; +libc_hidden_proto(strtoul_l) + +__extension__ +extern long long int strtoll_l (__const char *__restrict __nptr, + char **__restrict __endptr, int __base, + __locale_t __loc) + __THROW __nonnull ((1, 4)) __wur; + +__extension__ +extern unsigned long long int strtoull_l (__const char *__restrict __nptr, + char **__restrict __endptr, + int __base, __locale_t __loc) + __THROW __nonnull ((1, 4)) __wur; + +#ifdef __UCLIBC_HAS_FLOATS__ +extern double strtod_l (__const char *__restrict __nptr, + char **__restrict __endptr, __locale_t __loc) + __THROW __nonnull ((1, 3)) __wur; + +extern float strtof_l (__const char *__restrict __nptr, + char **__restrict __endptr, __locale_t __loc) + __THROW __nonnull ((1, 3)) __wur; + +extern long double strtold_l (__const char *__restrict __nptr, + char **__restrict __endptr, + __locale_t __loc) + __THROW __nonnull ((1, 3)) __wur; +#endif /* __UCLIBC_HAS_FLOATS__ */ +#endif /* GNU */ + + +#if defined __USE_SVID || defined __USE_XOPEN_EXTENDED +/* Convert N to base 64 using the digits "./0-9A-Za-z", least-significant + digit first. Returns a pointer to static storage overwritten by the + next call. */ +extern char *l64a (long int __n) __THROW __wur; + +/* Read a number from a string S in base 64 as above. */ +extern long int a64l (__const char *__s) + __THROW __attribute_pure__ __nonnull ((1)) __wur; + +#endif /* Use SVID || extended X/Open. */ + +#if defined __USE_SVID || defined __USE_XOPEN_EXTENDED || defined __USE_BSD +# include /* we need int32_t... */ + +/* These are the functions that actually do things. The `random', `srandom', + `initstate' and `setstate' functions are those from BSD Unices. + The `rand' and `srand' functions are required by the ANSI standard. + We provide both interfaces to the same random number generator. */ +/* Return a random long integer between 0 and RAND_MAX inclusive. */ +extern long int random (void) __THROW; +libc_hidden_proto(random) + +/* Seed the random number generator with the given number. */ +extern void srandom (unsigned int __seed) __THROW; + +/* Initialize the random number generator to use state buffer STATEBUF, + of length STATELEN, and seed it with SEED. Optimal lengths are 8, 16, + 32, 64, 128 and 256, the bigger the better; values less than 8 will + cause an error and values greater than 256 will be rounded down. */ +extern char *initstate (unsigned int __seed, char *__statebuf, + size_t __statelen) __THROW __nonnull ((2)); + +/* Switch the random number generator to state buffer STATEBUF, + which should have been previously initialized by `initstate'. */ +extern char *setstate (char *__statebuf) __THROW __nonnull ((1)); + + +# ifdef __USE_MISC +/* Reentrant versions of the `random' family of functions. + These functions all use the following data structure to contain + state, rather than global state variables. */ + +struct random_data + { + int32_t *fptr; /* Front pointer. */ + int32_t *rptr; /* Rear pointer. */ + int32_t *state; /* Array of state values. */ + /* random_r.c, TYPE_x, DEG_x, SEP_x - small enough for int8_t */ + int8_t rand_type; /* Type of random number generator. */ + int8_t rand_deg; /* Degree of random number generator. */ + int8_t rand_sep; /* Distance between front and rear. */ + int32_t *end_ptr; /* Pointer behind state table. */ + }; + +extern int random_r (struct random_data *__restrict __buf, + int32_t *__restrict __result) __THROW __nonnull ((1, 2)); +libc_hidden_proto(random_r) + +extern int srandom_r (unsigned int __seed, struct random_data *__buf) + __THROW __nonnull ((2)); +libc_hidden_proto(srandom_r) + +extern int initstate_r (unsigned int __seed, char *__restrict __statebuf, + size_t __statelen, + struct random_data *__restrict __buf) + __THROW __nonnull ((2, 4)); +libc_hidden_proto(initstate_r) + +extern int setstate_r (char *__restrict __statebuf, + struct random_data *__restrict __buf) + __THROW __nonnull ((1, 2)); +libc_hidden_proto(setstate_r) +# endif /* Use misc. */ +#endif /* Use SVID || extended X/Open || BSD. */ + + +__BEGIN_NAMESPACE_STD +/* Return a random integer between 0 and RAND_MAX inclusive. */ +extern int rand (void) __THROW; +/* Seed the random number generator with the given number. */ +extern void srand (unsigned int __seed) __THROW; +__END_NAMESPACE_STD + +#ifdef __USE_POSIX +/* Reentrant interface according to POSIX.1. */ +extern int rand_r (unsigned int *__seed) __THROW; +#endif + + +#if defined __USE_SVID || defined __USE_XOPEN +/* System V style 48-bit random number generator functions. */ + +#ifdef __UCLIBC_HAS_FLOATS__ +/* Return non-negative, double-precision floating-point value in [0.0,1.0). */ +extern double drand48 (void) __THROW; +extern double erand48 (unsigned short int __xsubi[3]) __THROW __nonnull ((1)); +#endif /* __UCLIBC_HAS_FLOATS__ */ + +/* Return non-negative, long integer in [0,2^31). */ +extern long int lrand48 (void) __THROW; +extern long int nrand48 (unsigned short int __xsubi[3]) + __THROW __nonnull ((1)); + +/* Return signed, long integers in [-2^31,2^31). */ +extern long int mrand48 (void) __THROW; +extern long int jrand48 (unsigned short int __xsubi[3]) + __THROW __nonnull ((1)); + +/* Seed random number generator. */ +extern void srand48 (long int __seedval) __THROW; +extern unsigned short int *seed48 (unsigned short int __seed16v[3]) + __THROW __nonnull ((1)); +extern void lcong48 (unsigned short int __param[7]) __THROW __nonnull ((1)); + +# ifdef __USE_MISC +/* Data structure for communication with thread safe versions. This + type is to be regarded as opaque. It's only exported because users + have to allocate objects of this type. */ +struct drand48_data + { + unsigned short int __x[3]; /* Current state. */ + unsigned short int __old_x[3]; /* Old state. */ + unsigned short int __c; /* Additive const. in congruential formula. */ + unsigned short int __init; /* Flag for initializing. */ + unsigned long long int __a; /* Factor in congruential formula. */ + }; + +#ifdef __UCLIBC_HAS_FLOATS__ +/* Return non-negative, double-precision floating-point value in [0.0,1.0). */ +extern int drand48_r (struct drand48_data *__restrict __buffer, + double *__restrict __result) __THROW __nonnull ((1, 2)); +extern int erand48_r (unsigned short int __xsubi[3], + struct drand48_data *__restrict __buffer, + double *__restrict __result) __THROW __nonnull ((1, 2)); +libc_hidden_proto(erand48_r) +#endif /* __UCLIBC_HAS_FLOATS__ */ + +/* Return non-negative, long integer in [0,2^31). */ +extern int lrand48_r (struct drand48_data *__restrict __buffer, + long int *__restrict __result) + __THROW __nonnull ((1, 2)); +libc_hidden_proto(lrand48_r) +extern int nrand48_r (unsigned short int __xsubi[3], + struct drand48_data *__restrict __buffer, + long int *__restrict __result) + __THROW __nonnull ((1, 2)); +libc_hidden_proto(nrand48_r) + +/* Return signed, long integers in [-2^31,2^31). */ +extern int mrand48_r (struct drand48_data *__restrict __buffer, + long int *__restrict __result) + __THROW __nonnull ((1, 2)); +extern int jrand48_r (unsigned short int __xsubi[3], + struct drand48_data *__restrict __buffer, + long int *__restrict __result) + __THROW __nonnull ((1, 2)); +libc_hidden_proto(jrand48_r) + +/* Seed random number generator. */ +extern int srand48_r (long int __seedval, struct drand48_data *__buffer) + __THROW __nonnull ((2)); +libc_hidden_proto(srand48_r) + +extern int seed48_r (unsigned short int __seed16v[3], + struct drand48_data *__buffer) __THROW __nonnull ((1, 2)); +libc_hidden_proto(seed48_r) + +extern int lcong48_r (unsigned short int __param[7], + struct drand48_data *__buffer) + __THROW __nonnull ((1, 2)); +# endif /* Use misc. */ +#endif /* Use SVID or X/Open. */ + +#endif /* don't just need malloc and calloc */ + +#ifndef __malloc_and_calloc_defined +# define __malloc_and_calloc_defined +__BEGIN_NAMESPACE_STD +/* Allocate SIZE bytes of memory. */ +extern void *malloc (size_t __size) __THROW __attribute_malloc__ __wur; +/* We want the malloc symbols overridable at runtime + * libc_hidden_proto(malloc) */ +/* Allocate NMEMB elements of SIZE bytes each, all initialized to 0. */ +extern void *calloc (size_t __nmemb, size_t __size) + __THROW __attribute_malloc__ __wur; +__END_NAMESPACE_STD +#endif + +#ifndef __need_malloc_and_calloc +__BEGIN_NAMESPACE_STD +/* Re-allocate the previously allocated block + in PTR, making the new block SIZE bytes long. */ +/* __attribute_malloc__ is not used, because if realloc returns + the same pointer that was passed to it, aliasing needs to be allowed + between objects pointed by the old and new pointers. */ +extern void *realloc (void *__ptr, size_t __size) + __THROW __attribute_warn_unused_result__; +/* Free a block allocated by `malloc', `realloc' or `calloc'. */ +extern void free (void *__ptr) __THROW; +__END_NAMESPACE_STD + +#if 0 /*def __USE_MISC*/ +/* Free a block. An alias for `free'. (Sun Unices). */ +extern void cfree (void *__ptr) __THROW; +#endif /* Use misc. */ + +#if defined __USE_GNU || defined __USE_BSD || defined __USE_MISC +# include +#endif /* Use GNU, BSD, or misc. */ + +#if defined __USE_BSD || defined __USE_XOPEN_EXTENDED +/* Allocate SIZE bytes on a page boundary. The storage cannot be freed. */ +extern void *valloc (size_t __size) __THROW __attribute_malloc__ __wur; +#endif + +#if defined __USE_XOPEN2K && defined __UCLIBC_HAS_ADVANCED_REALTIME__ +/* Allocate memory of SIZE bytes with an alignment of ALIGNMENT. */ +extern int posix_memalign (void **__memptr, size_t __alignment, size_t __size) + __THROW __nonnull ((1)) __wur; +#endif + +__BEGIN_NAMESPACE_STD +/* Abort execution and generate a core-dump. */ +extern void abort (void) __THROW __attribute__ ((__noreturn__)); +libc_hidden_proto(abort) + + +/* Register a function to be called when `exit' is called. */ +extern int atexit (void (*__func) (void)) __THROW __nonnull ((1)); +__END_NAMESPACE_STD + +#ifdef __USE_MISC +/* Register a function to be called with the status + given to `exit' and the given argument. */ +extern int on_exit (void (*__func) (int __status, void *__arg), void *__arg) + __THROW __nonnull ((1)); +#endif + +__BEGIN_NAMESPACE_STD +/* Call all functions registered with `atexit' and `on_exit', + in the reverse of the order in which they were registered + perform stdio cleanup, and terminate program execution with STATUS. */ +extern void exit (int __status) __THROW __attribute__ ((__noreturn__)); +libc_hidden_proto(exit) +__END_NAMESPACE_STD + +#ifdef __USE_ISOC99 +__BEGIN_NAMESPACE_C99 +/* Terminate the program with STATUS without calling any of the + functions registered with `atexit' or `on_exit'. */ +extern void _Exit (int __status) __THROW __attribute__ ((__noreturn__)); +__END_NAMESPACE_C99 +#endif + + +__BEGIN_NAMESPACE_STD +/* Return the value of envariable NAME, or NULL if it doesn't exist. */ +extern char *getenv (__const char *__name) __THROW __nonnull ((1)) __wur; +libc_hidden_proto(getenv) +__END_NAMESPACE_STD + +#if 0 +/* This function is similar to the above but returns NULL if the + programs is running with SUID or SGID enabled. */ +extern char *__secure_getenv (__const char *__name) + __THROW __nonnull ((1)) __wur; +#endif + +#if defined __USE_SVID || defined __USE_XOPEN +/* The SVID says this is in , but this seems a better place. */ +/* Put STRING, which is of the form "NAME=VALUE", in the environment. + If there is no `=', remove NAME from the environment. */ +extern int putenv (char *__string) __THROW __nonnull ((1)); +#endif + +#if defined __USE_BSD || defined __USE_XOPEN2K +/* Set NAME to VALUE in the environment. + If REPLACE is nonzero, overwrite an existing value. */ +extern int setenv (__const char *__name, __const char *__value, int __replace) + __THROW __nonnull ((2)); +libc_hidden_proto(setenv) + +/* Remove the variable NAME from the environment. */ +extern int unsetenv (__const char *__name) __THROW; +libc_hidden_proto(unsetenv) +#endif + +/* The following is used by uClibc in atexit.c and sysconf.c */ +/* We have no limit when __UCLIBC_DYNAMIC_ATEXIT__ is enabled. */ +#ifdef __UCLIBC_DYNAMIC_ATEXIT__ +# define __UCLIBC_MAX_ATEXIT INT_MAX +#else +# define __UCLIBC_MAX_ATEXIT 20 +#endif + + +#ifdef __USE_MISC +/* The `clearenv' was planned to be added to POSIX.1 but probably + never made it. Nevertheless the POSIX.9 standard (POSIX bindings + for Fortran 77) requires this function. */ +extern int clearenv (void) __THROW; +#endif + + +#if defined __USE_MISC || defined __USE_XOPEN_EXTENDED +# if defined __UCLIBC_SUSV3_LEGACY__ +/* Generate a unique temporary file name from TEMPLATE. + The last six characters of TEMPLATE must be "XXXXXX"; + they are replaced with a string that makes the file name unique. + Returns TEMPLATE, or a null pointer if it cannot get a unique file name. */ +extern char *mktemp (char *__template) __THROW __nonnull ((1)) __wur; +# endif + +/* Generate a unique temporary file name from TEMPLATE. + The last six characters of TEMPLATE must be "XXXXXX"; + they are replaced with a string that makes the filename unique. + Returns a file descriptor open on the file for reading and writing, + or -1 if it cannot create a uniquely-named file. + + This function is a possible cancellation points and therefore not + marked with __THROW. */ +# ifndef __USE_FILE_OFFSET64 +extern int mkstemp (char *__template) __nonnull ((1)) __wur; +# else +# ifdef __REDIRECT +extern int __REDIRECT (mkstemp, (char *__template), mkstemp64) + __nonnull ((1)) __wur; +# else +# define mkstemp mkstemp64 +# endif +# endif +# ifdef __USE_LARGEFILE64 +extern int mkstemp64 (char *__template) __nonnull ((1)) __wur; +# endif +#endif + +#ifdef __USE_BSD +/* Create a unique temporary directory from TEMPLATE. + The last six characters of TEMPLATE must be "XXXXXX"; + they are replaced with a string that makes the directory name unique. + Returns TEMPLATE, or a null pointer if it cannot get a unique name. + The directory is created mode 700. */ +extern char *mkdtemp (char *__template) __THROW __nonnull ((1)) __wur; +#endif + + +__BEGIN_NAMESPACE_STD +/* Execute the given line as a shell command. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern int system (__const char *__command) __wur; +__END_NAMESPACE_STD + + +#ifdef __USE_GNU +/* Return a malloc'd string containing the canonical absolute name of the + existing named file. */ +extern char *canonicalize_file_name (__const char *__name) + __THROW __nonnull ((1)) __wur; +#endif + +/* Return the canonical absolute name of file NAME. If the + canonical name is PATH_MAX chars or more, returns null + with `errno' set to ENAMETOOLONG; if the name fits in + fewer than PATH_MAX chars, returns the name in RESOLVED. */ +/* we choose to handle __resolved==NULL as crash :) */ +extern char *realpath (__const char *__restrict __name, + char *__restrict __resolved) __THROW __wur; +libc_hidden_proto(realpath) + +/* Shorthand for type of comparison functions. */ +#ifndef __COMPAR_FN_T +# define __COMPAR_FN_T +typedef int (*__compar_fn_t) (__const void *, __const void *); + +# ifdef __USE_GNU +typedef __compar_fn_t comparison_fn_t; +# endif +#endif + +__BEGIN_NAMESPACE_STD +/* Do a binary search for KEY in BASE, which consists of NMEMB elements + of SIZE bytes each, using COMPAR to perform the comparisons. */ +extern void *bsearch (__const void *__key, __const void *__base, + size_t __nmemb, size_t __size, __compar_fn_t __compar) + __nonnull ((1, 2, 5)) __wur; + +/* Sort NMEMB elements of BASE, of SIZE bytes each, + using COMPAR to perform the comparisons. */ +extern void qsort (void *__base, size_t __nmemb, size_t __size, + __compar_fn_t __compar) __nonnull ((1, 4)); +libc_hidden_proto(qsort) + + +/* Return the absolute value of X. */ +extern int abs (int __x) __THROW __attribute__ ((__const__)) __wur; +extern long int labs (long int __x) __THROW __attribute__ ((__const__)) __wur; +__END_NAMESPACE_STD + +#ifdef __USE_ISOC99 +__extension__ extern long long int llabs (long long int __x) + __THROW __attribute__ ((__const__)) __wur; +#endif + + +__BEGIN_NAMESPACE_STD +/* Return the `div_t', `ldiv_t' or `lldiv_t' representation + of the value of NUMER over DENOM. */ +/* GCC may have built-ins for these someday. */ +extern div_t div (int __numer, int __denom) + __THROW __attribute__ ((__const__)) __wur; +extern ldiv_t ldiv (long int __numer, long int __denom) + __THROW __attribute__ ((__const__)) __wur; +__END_NAMESPACE_STD + +#ifdef __USE_ISOC99 +__BEGIN_NAMESPACE_C99 +__extension__ extern lldiv_t lldiv (long long int __numer, + long long int __denom) + __THROW __attribute__ ((__const__)) __wur; +__END_NAMESPACE_C99 +#endif + + +#if ( defined __USE_SVID || defined __USE_XOPEN_EXTENDED ) && defined __UCLIBC_HAS_FLOATS__ +/* Convert floating point numbers to strings. The returned values are + valid only until another call to the same function. */ + +# ifdef __UCLIBC_SUSV3_LEGACY__ +#if 0 +/* Convert VALUE to a string with NDIGIT digits and return a pointer to + this. Set *DECPT with the position of the decimal character and *SIGN + with the sign of the number. */ +extern char *ecvt (double __value, int __ndigit, int *__restrict __decpt, + int *__restrict __sign) __THROW __nonnull ((3, 4)) __wur; + +/* Convert VALUE to a string rounded to NDIGIT decimal digits. Set *DECPT + with the position of the decimal character and *SIGN with the sign of + the number. */ +extern char *fcvt (double __value, int __ndigit, int *__restrict __decpt, + int *__restrict __sign) __THROW __nonnull ((3, 4)) __wur; +#endif + +/* If possible convert VALUE to a string with NDIGIT significant digits. + Otherwise use exponential representation. The resulting string will + be written to BUF. */ +extern char *gcvt (double __value, int __ndigit, char *__buf) + __THROW __nonnull ((3)) __wur; +# endif /* __UCLIBC_SUSV3_LEGACY__ */ + + +# if 0 /*def __USE_MISC*/ +/* Long double versions of above functions. */ +extern char *qecvt (long double __value, int __ndigit, + int *__restrict __decpt, int *__restrict __sign) + __THROW __nonnull ((3, 4)) __wur; +extern char *qfcvt (long double __value, int __ndigit, + int *__restrict __decpt, int *__restrict __sign) + __THROW __nonnull ((3, 4)) __wur; +extern char *qgcvt (long double __value, int __ndigit, char *__buf) + __THROW __nonnull ((3)) __wur; + + +/* Reentrant version of the functions above which provide their own + buffers. */ +extern int ecvt_r (double __value, int __ndigit, int *__restrict __decpt, + int *__restrict __sign, char *__restrict __buf, + size_t __len) __THROW __nonnull ((3, 4, 5)); +extern int fcvt_r (double __value, int __ndigit, int *__restrict __decpt, + int *__restrict __sign, char *__restrict __buf, + size_t __len) __THROW __nonnull ((3, 4, 5)); + +extern int qecvt_r (long double __value, int __ndigit, + int *__restrict __decpt, int *__restrict __sign, + char *__restrict __buf, size_t __len) + __THROW __nonnull ((3, 4, 5)); +extern int qfcvt_r (long double __value, int __ndigit, + int *__restrict __decpt, int *__restrict __sign, + char *__restrict __buf, size_t __len) + __THROW __nonnull ((3, 4, 5)); +# endif /* misc */ +#endif /* use MISC || use X/Open Unix */ + + +#ifdef __UCLIBC_HAS_WCHAR__ +__BEGIN_NAMESPACE_STD +/* Return the length of the multibyte character + in S, which is no longer than N. */ +extern int mblen (__const char *__s, size_t __n) __THROW __wur; +/* Return the length of the given multibyte character, + putting its `wchar_t' representation in *PWC. */ +extern int mbtowc (wchar_t *__restrict __pwc, + __const char *__restrict __s, size_t __n) __THROW __wur; +/* Put the multibyte character represented + by WCHAR in S, returning its length. */ +extern int wctomb (char *__s, wchar_t __wchar) __THROW __wur; + + +/* Convert a multibyte string to a wide char string. */ +extern size_t mbstowcs (wchar_t *__restrict __pwcs, + __const char *__restrict __s, size_t __n) __THROW; +/* Convert a wide char string to multibyte string. */ +extern size_t wcstombs (char *__restrict __s, + __const wchar_t *__restrict __pwcs, size_t __n) + __THROW; +__END_NAMESPACE_STD +#endif /* __UCLIBC_HAS_WCHAR__ */ + + +#if 0 /*def __USE_SVID*/ +/* Determine whether the string value of RESPONSE matches the affirmation + or negative response expression as specified by the LC_MESSAGES category + in the program's current locale. Returns 1 if affirmative, 0 if + negative, and -1 if not matching. */ +extern int rpmatch (__const char *__response) __THROW __nonnull ((1)) __wur; +#endif + + +#ifdef __USE_XOPEN_EXTENDED +/* Parse comma separated suboption from *OPTIONP and match against + strings in TOKENS. If found return index and set *VALUEP to + optional value introduced by an equal sign. If the suboption is + not part of TOKENS return in *VALUEP beginning of unknown + suboption. On exit *OPTIONP is set to the beginning of the next + token or at the terminating NUL character. */ +extern int getsubopt (char **__restrict __optionp, + char *__const *__restrict __tokens, + char **__restrict __valuep) + __THROW __nonnull ((1, 2, 3)) __wur; +#endif + + +#ifdef __USE_XOPEN +# if defined __UCLIBC_HAS_CRYPT__ +/* Setup DES tables according KEY. */ +extern void setkey (__const char *__key) __THROW __nonnull ((1)); +# endif /* __UCLIBC_HAS_CRYPT__ */ +#endif + + +/* X/Open pseudo terminal handling. */ + +#ifdef __USE_XOPEN2K +/* Return a master pseudo-terminal handle. */ +extern int posix_openpt (int __oflag) __wur; +libc_hidden_proto(posix_openpt) +#endif + +#ifdef __USE_XOPEN +/* The next four functions all take a master pseudo-tty fd and + perform an operation on the associated slave: */ +#ifdef __UCLIBC_HAS_PTY__ +/* Chown the slave to the calling user. */ +extern int grantpt (int __fd) __THROW; + +/* Release an internal lock so the slave can be opened. + Call after grantpt(). */ +extern int unlockpt (int __fd) __THROW; + +/* Return the pathname of the pseudo terminal slave assoicated with + the master FD is open on, or NULL on errors. + The returned storage is good until the next call to this function. */ +extern char *ptsname (int __fd) __THROW __wur; +#endif /* __UCLIBC_HAS_PTY__ */ +#endif + +#ifdef __USE_GNU +# if defined __UCLIBC_HAS_PTY__ +/* Store at most BUFLEN characters of the pathname of the slave pseudo + terminal associated with the master FD is open on in BUF. + Return 0 on success, otherwise an error number. */ +extern int ptsname_r (int __fd, char *__buf, size_t __buflen) + __THROW __nonnull ((2)); +libc_hidden_proto(ptsname_r) +# endif +# if defined __UCLIBC_HAS_GETPT__ +/* Open a master pseudo terminal and return its file descriptor. */ +extern int getpt (void); +# endif +#endif + +#if 0 /* def __USE_BSD */ +/* Put the 1 minute, 5 minute and 15 minute load averages into the first + NELEM elements of LOADAVG. Return the number written (never more than + three, but may be less than NELEM), or -1 if an error occurred. */ +extern int getloadavg (double __loadavg[], int __nelem) + __THROW __nonnull ((1)); +#endif + +#ifdef __UCLIBC_HAS_ARC4RANDOM__ +#include +extern uint32_t arc4random(void); +extern void arc4random_stir(void); +libc_hidden_proto(arc4random_stir) +extern void arc4random_addrandom(unsigned char *, int); +#endif + +#endif /* don't just need malloc and calloc */ +#undef __need_malloc_and_calloc + +__END_DECLS + +#endif /* stdlib.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/string.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/string.h new file mode 100644 index 00000000..ca22055e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/string.h @@ -0,0 +1,492 @@ +/* Copyright (C) 1991-1993, 1995-2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * ISO C99 Standard: 7.21 String handling + */ + +#ifndef _STRING_H +#define _STRING_H 1 + +#include + +__BEGIN_DECLS + +/* Get size_t and NULL from . */ +#define __need_size_t +#define __need_NULL +#include + + +__BEGIN_NAMESPACE_STD +/* Copy N bytes of SRC to DEST. */ +extern void *memcpy (void *__restrict __dest, + __const void *__restrict __src, size_t __n) + __THROW __nonnull ((1, 2)); +libc_hidden_proto(memcpy) +/* Copy N bytes of SRC to DEST, guaranteeing + correct behavior for overlapping strings. */ +extern void *memmove (void *__dest, __const void *__src, size_t __n) + __THROW __nonnull ((1, 2)); +libc_hidden_proto(memmove) +__END_NAMESPACE_STD + +/* Copy no more than N bytes of SRC to DEST, stopping when C is found. + Return the position in DEST one byte past where C was copied, + or NULL if C was not found in the first N bytes of SRC. */ +#if defined __USE_SVID || defined __USE_BSD || defined __USE_XOPEN +extern void *memccpy (void *__restrict __dest, __const void *__restrict __src, + int __c, size_t __n) + __THROW __nonnull ((1, 2)); +libc_hidden_proto(memccpy) +#endif /* SVID. */ + + +__BEGIN_NAMESPACE_STD +/* Set N bytes of S to C. */ +extern void *memset (void *__s, int __c, size_t __n) __THROW __nonnull ((1)); +libc_hidden_proto(memset) + +/* Compare N bytes of S1 and S2. */ +extern int memcmp (__const void *__s1, __const void *__s2, size_t __n) + __THROW __attribute_pure__ __nonnull ((1, 2)); +libc_hidden_proto(memcmp) + +/* Search N bytes of S for C. */ +extern void *memchr (__const void *__s, int __c, size_t __n) + __THROW __attribute_pure__ __nonnull ((1)); +libc_hidden_proto(memchr) +__END_NAMESPACE_STD + +#ifdef __USE_GNU +/* Search in S for C. This is similar to `memchr' but there is no + length limit. */ +extern void *rawmemchr (__const void *__s, int __c) + __THROW __attribute_pure__ __nonnull ((1)); +libc_hidden_proto(rawmemchr) + +/* Search N bytes of S for the final occurrence of C. */ +extern void *memrchr (__const void *__s, int __c, size_t __n) + __THROW __attribute_pure__ __nonnull ((1)); +libc_hidden_proto(memrchr) +#endif + + +__BEGIN_NAMESPACE_STD +/* Copy SRC to DEST. */ +extern char *strcpy (char *__restrict __dest, __const char *__restrict __src) + __THROW __nonnull ((1, 2)); +libc_hidden_proto(strcpy) +/* Copy no more than N characters of SRC to DEST. */ +extern char *strncpy (char *__restrict __dest, + __const char *__restrict __src, size_t __n) + __THROW __nonnull ((1, 2)); +libc_hidden_proto(strncpy) + +/* Append SRC onto DEST. */ +extern char *strcat (char *__restrict __dest, __const char *__restrict __src) + __THROW __nonnull ((1, 2)); +libc_hidden_proto(strcat) +/* Append no more than N characters from SRC onto DEST. */ +extern char *strncat (char *__restrict __dest, __const char *__restrict __src, + size_t __n) __THROW __nonnull ((1, 2)); +libc_hidden_proto(strncat) + +/* Compare S1 and S2. */ +extern int strcmp (__const char *__s1, __const char *__s2) + __THROW __attribute_pure__ __nonnull ((1, 2)); +libc_hidden_proto(strcmp) +/* Compare N characters of S1 and S2. */ +extern int strncmp (__const char *__s1, __const char *__s2, size_t __n) + __THROW __attribute_pure__ __nonnull ((1, 2)); +libc_hidden_proto(strncmp) + +/* Compare the collated forms of S1 and S2. */ +extern int strcoll (__const char *__s1, __const char *__s2) + __THROW __attribute_pure__ __nonnull ((1, 2)); +libc_hidden_proto(strcoll) +/* Put a transformation of SRC into no more than N bytes of DEST. */ +extern size_t strxfrm (char *__restrict __dest, + __const char *__restrict __src, size_t __n) + __THROW __nonnull ((2)); +libc_hidden_proto(strxfrm) +__END_NAMESPACE_STD + +#if defined __USE_GNU && defined __UCLIBC_HAS_XLOCALE__ +/* The following functions are equivalent to the both above but they + take the locale they use for the collation as an extra argument. + This is not standardsized but something like will come. */ +# include + +/* Compare the collated forms of S1 and S2 using rules from L. */ +extern int strcoll_l (__const char *__s1, __const char *__s2, __locale_t __l) + __THROW __attribute_pure__ __nonnull ((1, 2, 3)); +libc_hidden_proto(strcoll_l) +/* Put a transformation of SRC into no more than N bytes of DEST. */ +extern size_t strxfrm_l (char *__dest, __const char *__src, size_t __n, + __locale_t __l) __THROW __nonnull ((2, 4)); +libc_hidden_proto(strxfrm_l) +#endif + +#if defined __USE_SVID || defined __USE_BSD || defined __USE_XOPEN_EXTENDED +/* Duplicate S, returning an identical malloc'd string. */ +extern char *strdup (__const char *__s) + __THROW __attribute_malloc__ __nonnull ((1)); +libc_hidden_proto(strdup) +#endif + +/* Return a malloc'd copy of at most N bytes of STRING. The + resultant string is terminated even if no null terminator + appears before STRING[N]. */ +#if defined __USE_GNU +extern char *strndup (__const char *__string, size_t __n) + __THROW __attribute_malloc__ __nonnull ((1)); +libc_hidden_proto(strndup) +#endif + +#if defined __USE_GNU && defined __GNUC__ +/* Duplicate S, returning an identical alloca'd string. */ +# define strdupa(s) \ + (__extension__ \ + ({ \ + __const char *__old = (s); \ + size_t __len = strlen (__old) + 1; \ + char *__new = (char *) __builtin_alloca (__len); \ + (char *) memcpy (__new, __old, __len); \ + })) + +/* Return an alloca'd copy of at most N bytes of string. */ +# define strndupa(s, n) \ + (__extension__ \ + ({ \ + __const char *__old = (s); \ + size_t __len = strnlen (__old, (n)); \ + char *__new = (char *) __builtin_alloca (__len + 1); \ + __new[__len] = '\0'; \ + (char *) memcpy (__new, __old, __len); \ + })) +#endif + +__BEGIN_NAMESPACE_STD +/* Find the first occurrence of C in S. */ +extern char *strchr (__const char *__s, int __c) + __THROW __attribute_pure__ __nonnull ((1)); +libc_hidden_proto(strchr) +/* Find the last occurrence of C in S. */ +extern char *strrchr (__const char *__s, int __c) + __THROW __attribute_pure__ __nonnull ((1)); +libc_hidden_proto(strrchr) +__END_NAMESPACE_STD + +#ifdef __USE_GNU +/* This function is similar to `strchr'. But it returns a pointer to + the closing NUL byte in case C is not found in S. */ +extern char *strchrnul (__const char *__s, int __c) + __THROW __attribute_pure__ __nonnull ((1)); +libc_hidden_proto(strchrnul) +#endif + +__BEGIN_NAMESPACE_STD +/* Return the length of the initial segment of S which + consists entirely of characters not in REJECT. */ +extern size_t strcspn (__const char *__s, __const char *__reject) + __THROW __attribute_pure__ __nonnull ((1, 2)); +libc_hidden_proto(strcspn) +/* Return the length of the initial segment of S which + consists entirely of characters in ACCEPT. */ +extern size_t strspn (__const char *__s, __const char *__accept) + __THROW __attribute_pure__ __nonnull ((1, 2)); +libc_hidden_proto(strspn) +/* Find the first occurrence in S of any character in ACCEPT. */ +extern char *strpbrk (__const char *__s, __const char *__accept) + __THROW __attribute_pure__ __nonnull ((1, 2)); +libc_hidden_proto(strpbrk) +/* Find the first occurrence of NEEDLE in HAYSTACK. */ +extern char *strstr (__const char *__haystack, __const char *__needle) + __THROW __attribute_pure__ __nonnull ((1, 2)); +libc_hidden_proto(strstr) + + +/* Divide S into tokens separated by characters in DELIM. */ +extern char *strtok (char *__restrict __s, __const char *__restrict __delim) + __THROW __nonnull ((2)); +libc_hidden_proto(strtok) +__END_NAMESPACE_STD + +/* Divide S into tokens separated by characters in DELIM. Information + passed between calls are stored in SAVE_PTR. */ +#if 0 /* uClibc: disabled */ +extern char *__strtok_r (char *__restrict __s, + __const char *__restrict __delim, + char **__restrict __save_ptr) + __THROW __nonnull ((2, 3)); +#endif +#if defined __USE_POSIX || defined __USE_MISC +extern char *strtok_r (char *__restrict __s, __const char *__restrict __delim, + char **__restrict __save_ptr) + __THROW __nonnull ((2, 3)); +libc_hidden_proto(strtok_r) +#endif + +#ifdef __USE_GNU +/* Similar to `strstr' but this function ignores the case of both strings. */ +extern char *strcasestr (__const char *__haystack, __const char *__needle) + __THROW __attribute_pure__ __nonnull ((1, 2)); +libc_hidden_proto(strcasestr) +#endif + +#ifdef __USE_GNU +/* Find the first occurrence of NEEDLE in HAYSTACK. + NEEDLE is NEEDLELEN bytes long; + HAYSTACK is HAYSTACKLEN bytes long. */ +extern void *memmem (__const void *__haystack, size_t __haystacklen, + __const void *__needle, size_t __needlelen) + __THROW __attribute_pure__ __nonnull ((1, 3)); +libc_hidden_proto(memmem) + +/* Copy N bytes of SRC to DEST, return pointer to bytes after the + last written byte. */ +#if 0 /* uClibc: disabled */ +extern void *__mempcpy (void *__restrict __dest, + __const void *__restrict __src, size_t __n) + __THROW __nonnull ((1, 2)); +#endif +extern void *mempcpy (void *__restrict __dest, + __const void *__restrict __src, size_t __n) + __THROW __nonnull ((1, 2)); +libc_hidden_proto(mempcpy) +#endif + + +__BEGIN_NAMESPACE_STD +/* Return the length of S. */ +extern size_t strlen (__const char *__s) + __THROW __attribute_pure__ __nonnull ((1)); +libc_hidden_proto(strlen) +__END_NAMESPACE_STD + +#ifdef __USE_GNU +/* Find the length of STRING, but scan at most MAXLEN characters. + If no '\0' terminator is found in that many characters, return MAXLEN. */ +extern size_t strnlen (__const char *__string, size_t __maxlen) + __THROW __attribute_pure__ __nonnull ((1)); +libc_hidden_proto(strnlen) +#endif + + +__BEGIN_NAMESPACE_STD +/* Return a string describing the meaning of the `errno' code in ERRNUM. */ +extern char *strerror (int __errnum) __THROW; +libc_hidden_proto(strerror) +__END_NAMESPACE_STD +#if defined __USE_XOPEN2K || defined __USE_MISC +/* Reentrant version of `strerror'. + There are 2 flavors of `strerror_r', GNU which returns the string + and may or may not use the supplied temporary buffer and POSIX one + which fills the string into the buffer. + To use the POSIX version, -D_XOPEN_SOURCE=600 or -D_POSIX_C_SOURCE=200112L + without -D_GNU_SOURCE is needed, otherwise the GNU version is + preferred. */ +# if defined __USE_XOPEN2K && !defined __USE_GNU +/* Fill BUF with a string describing the meaning of the `errno' code in + ERRNUM. */ +extern int __xpg_strerror_r (int __errnum, char *__buf, size_t __buflen) + __THROW __nonnull ((2)); +libc_hidden_proto(__xpg_strerror_r) +# ifdef __REDIRECT_NTH +extern int __REDIRECT_NTH (strerror_r, + (int __errnum, char *__buf, size_t __buflen), + __xpg_strerror_r) __nonnull ((2)); +# else +# define strerror_r __xpg_strerror_r +# endif +# else +/* If a temporary buffer is required, at most BUFLEN bytes of BUF will be + used. */ +extern char *__glibc_strerror_r (int __errnum, char *__buf, size_t __buflen) + __THROW __nonnull ((2)); +libc_hidden_proto(__glibc_strerror_r) +# ifdef __REDIRECT_NTH +extern char * __REDIRECT_NTH (strerror_r, + (int __errnum, char *__buf, size_t __buflen), + __glibc_strerror_r) __nonnull ((2)); +# else +# define strerror_r __glibc_strerror_r +# endif +# endif +#endif + +/* We define this function always since `bzero' is sometimes needed when + the namespace rules does not allow this. */ +#if 0 /* uClibc: disabled */ +extern void __bzero (void *__s, size_t __n) __THROW __nonnull ((1)); +#endif + +#ifdef __USE_BSD +# ifdef __UCLIBC_SUSV3_LEGACY__ +/* Copy N bytes of SRC to DEST (like memmove, but args reversed). */ +extern void bcopy (__const void *__src, void *__dest, size_t __n) + __THROW __nonnull ((1, 2)); + +/* Set N bytes of S to 0. */ +extern void bzero (void *__s, size_t __n) __THROW __nonnull ((1)); + +/* Compare N bytes of S1 and S2 (same as memcmp). */ +extern int bcmp (__const void *__s1, __const void *__s2, size_t __n) + __THROW __attribute_pure__ __nonnull ((1, 2)); + +/* Find the first occurrence of C in S (same as strchr). */ +extern char *index (__const char *__s, int __c) + __THROW __attribute_pure__ __nonnull ((1)); + +/* Find the last occurrence of C in S (same as strrchr). */ +extern char *rindex (__const char *__s, int __c) + __THROW __attribute_pure__ __nonnull ((1)); +# else +# ifdef __UCLIBC_SUSV3_LEGACY_MACROS__ +/* bcopy/bzero/bcmp/index/rindex are marked LEGACY in SuSv3. + * They are replaced as proposed by SuSv3. Don't sync this part + * with glibc and keep it in sync with strings.h. */ + +# define bcopy(src,dest,n) (memmove((dest), (src), (n)), (void) 0) +# define bzero(s,n) (memset((s), '\0', (n)), (void) 0) +# define bcmp(s1,s2,n) memcmp((s1), (s2), (size_t)(n)) +# define index(s,c) strchr((s), (c)) +# define rindex(s,c) strrchr((s), (c)) +# endif +# endif + +/* Return the position of the first bit set in I, or 0 if none are set. + The least-significant bit is position 1, the most-significant 32. */ +extern int ffs (int __i) __THROW __attribute__ ((__const__)); +libc_hidden_proto(ffs) + +/* The following two functions are non-standard but necessary for non-32 bit + platforms. */ +# if 0 /*#ifdef __USE_GNU*/ +extern int ffsl (long int __l) __THROW __attribute__ ((__const__)); +# ifdef __GNUC__ +__extension__ extern int ffsll (long long int __ll) + __THROW __attribute__ ((__const__)); +# endif +# endif + +/* Compare S1 and S2, ignoring case. */ +extern int strcasecmp (__const char *__s1, __const char *__s2) + __THROW __attribute_pure__ __nonnull ((1, 2)); +libc_hidden_proto(strcasecmp) + +/* Compare no more than N chars of S1 and S2, ignoring case. */ +extern int strncasecmp (__const char *__s1, __const char *__s2, size_t __n) + __THROW __attribute_pure__ __nonnull ((1, 2)); +libc_hidden_proto(strncasecmp) +#endif /* Use BSD. */ + +#if defined __USE_GNU && defined __UCLIBC_HAS_XLOCALE__ +/* Again versions of a few functions which use the given locale instead + of the global one. */ +extern int strcasecmp_l (__const char *__s1, __const char *__s2, + __locale_t __loc) + __THROW __attribute_pure__ __nonnull ((1, 2, 3)); +libc_hidden_proto(strcasecmp_l) + +extern int strncasecmp_l (__const char *__s1, __const char *__s2, + size_t __n, __locale_t __loc) + __THROW __attribute_pure__ __nonnull ((1, 2, 4)); +libc_hidden_proto(strncasecmp_l) +#endif + +#ifdef __USE_BSD +/* Return the next DELIM-delimited token from *STRINGP, + terminating it with a '\0', and update *STRINGP to point past it. */ +extern char *strsep (char **__restrict __stringp, + __const char *__restrict __delim) + __THROW __nonnull ((1, 2)); +libc_hidden_proto(strsep) +#endif + +#ifdef __USE_GNU +/* Compare S1 and S2 as strings holding name & indices/version numbers. */ +extern int strverscmp (__const char *__s1, __const char *__s2) + __THROW __attribute_pure__ __nonnull ((1, 2)); +libc_hidden_proto(strverscmp) + +/* Return a string describing the meaning of the signal number in SIG. */ +extern char *strsignal (int __sig) __THROW; +libc_hidden_proto(strsignal) + +/* Copy SRC to DEST, returning the address of the terminating '\0' in DEST. */ +# if 0 /* uClibc: disabled */ +extern char *__stpcpy (char *__restrict __dest, __const char *__restrict __src) + __THROW __nonnull ((1, 2)); +# endif +extern char *stpcpy (char *__restrict __dest, __const char *__restrict __src) + __THROW __nonnull ((1, 2)); +libc_hidden_proto(stpcpy) + +/* Copy no more than N characters of SRC to DEST, returning the address of + the last character written into DEST. */ +# if 0 /* uClibc: disabled */ +extern char *__stpncpy (char *__restrict __dest, + __const char *__restrict __src, size_t __n) + __THROW __nonnull ((1, 2)); +# endif +extern char *stpncpy (char *__restrict __dest, + __const char *__restrict __src, size_t __n) + __THROW __nonnull ((1, 2)); +libc_hidden_proto(stpncpy) + +# if 0 /* uClibc does not support strfry or memfrob. */ +/* Sautee STRING briskly. */ +extern char *strfry (char *__string) __THROW __nonnull ((1)); + +/* Frobnicate N bytes of S. */ +extern void *memfrob (void *__s, size_t __n) __THROW __nonnull ((1)); +# endif + +# ifndef basename +/* Return the file name within directory of FILENAME. We don't + declare the function if the `basename' macro is available (defined + in ) which makes the XPG version of this function + available. */ +extern char *basename (__const char *__filename) __THROW __nonnull ((1)); +libc_hidden_proto(basename) +# endif +#endif /* __USE_GNU */ + + +#ifdef __USE_BSD +/* Two OpenBSD extension functions. */ +extern size_t strlcat(char *__restrict dst, const char *__restrict src, + size_t n) __THROW __nonnull ((1, 2)); +libc_hidden_proto(strlcat) +extern size_t strlcpy(char *__restrict dst, const char *__restrict src, + size_t n) __THROW __nonnull ((1, 2)); +libc_hidden_proto(strlcpy) +#endif + +__END_DECLS + + +#if defined(_LIBC) && defined(__UCLIBC_HAS_STRING_ARCH_OPT__) +# if defined __i386__ +# include <../libc/string/i386/string.h> +# endif +#endif + +#endif /* string.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/strings.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/strings.h new file mode 100644 index 00000000..7f3a456d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/strings.h @@ -0,0 +1,101 @@ +/* Copyright (C) 1991,92,96,97,99,2000,2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _STRINGS_H +#define _STRINGS_H 1 + +/* We don't need and should not read this file if was already + read. The one exception being that if __USE_BSD isn't defined, then + these aren't defined in string.h, so we need to define them here. */ + +/* keep this file in sync w/ string.h, the glibc version is out of date */ + +#if !defined _STRING_H || !defined __USE_BSD + +# include +# define __need_size_t +# include + +__BEGIN_DECLS + +# ifdef __UCLIBC_SUSV3_LEGACY__ +/* Copy N bytes of SRC to DEST (like memmove, but args reversed). */ +extern void bcopy (__const void *__src, void *__dest, size_t __n) + __THROW __nonnull ((1, 2)); + +/* Set N bytes of S to 0. */ +extern void bzero (void *__s, size_t __n) __THROW __nonnull ((1)); + +/* Compare N bytes of S1 and S2 (same as memcmp). */ +extern int bcmp (__const void *__s1, __const void *__s2, size_t __n) + __THROW __attribute_pure__ __nonnull ((1, 2)); + +/* Find the first occurrence of C in S (same as strchr). */ +extern char *index (__const char *__s, int __c) + __THROW __attribute_pure__ __nonnull ((1)); + +/* Find the last occurrence of C in S (same as strrchr). */ +extern char *rindex (__const char *__s, int __c) + __THROW __attribute_pure__ __nonnull ((1)); +# else +# ifdef __UCLIBC_SUSV3_LEGACY_MACROS__ +/* bcopy/bzero/bcmp/index/rindex are marked LEGACY in SuSv3. + * They are replaced as proposed by SuSv3. Don't sync this part + * with glibc and keep it in sync with string.h. */ + +# define bcopy(src,dest,n) (memmove((dest), (src), (n)), (void) 0) +# define bzero(s,n) (memset((s), '\0', (n)), (void) 0) +# define bcmp(s1,s2,n) memcmp((s1), (s2), (size_t)(n)) +# define index(s,c) strchr((s), (c)) +# define rindex(s,c) strrchr((s), (c)) +# endif +# endif + +/* Return the position of the first bit set in I, or 0 if none are set. + The least-significant bit is position 1, the most-significant 32. */ +extern int ffs (int __i) __THROW __attribute__ ((__const__)); + +/* The following two functions are non-standard but necessary for non-32 bit + platforms. */ +#if 0 /*def __USE_GNU*/ +extern int ffsl (long int __l) __THROW __attribute__ ((__const__)); +# ifdef __GNUC__ +__extension__ extern int ffsll (long long int __ll) + __THROW __attribute__ ((__const__)); +# endif +# endif + +/* Compare S1 and S2, ignoring case. */ +extern int strcasecmp (__const char *__s1, __const char *__s2) + __THROW __attribute_pure__ __nonnull ((1, 2)); + +/* Compare no more than N chars of S1 and S2, ignoring case. */ +extern int strncasecmp (__const char *__s1, __const char *__s2, size_t __n) + __THROW __attribute_pure__ __nonnull ((1, 2)); + +__END_DECLS + + +#ifdef _LIBC +#error " should not be included from libc." +#endif + + +#endif /* string.h */ + +#endif /* strings.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/bitypes.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/bitypes.h new file mode 100644 index 00000000..3a9860f7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/bitypes.h @@ -0,0 +1,3 @@ +/* The GNU defines all the necessary types. */ + +#include diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/cdefs.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/cdefs.h new file mode 100644 index 00000000..57210718 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/cdefs.h @@ -0,0 +1,350 @@ +/* Copyright (C) 1992-2001, 2002, 2004, 2005, 2006, 2007 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_CDEFS_H +#define _SYS_CDEFS_H 1 + +/* We are almost always included from features.h. */ +#ifndef _FEATURES_H +# include +#endif + +/* The GNU libc does not support any K&R compilers or the traditional mode + of ISO C compilers anymore. Check for some of the combinations not + anymore supported. */ +#if defined __GNUC__ && !defined __STDC__ +# error "You need a ISO C conforming compiler to use the glibc headers" +#endif + +/* Some user header file might have defined this before. */ +#undef __P +#undef __PMT + +#ifdef __GNUC__ + +/* GCC can always grok prototypes. For C++ programs we add throw() + to help it optimize the function calls. But this works only with + gcc 2.8.x and egcs. For gcc 3.2 and up we even mark C functions + as non-throwing using a function attribute since programs can use + the -fexceptions options for C code as well. */ +# if !defined __cplusplus && __GNUC_PREREQ (3, 3) +# define __THROW __attribute__ ((__nothrow__)) +# define __NTH(fct) __attribute__ ((__nothrow__)) fct +# else +# if defined __cplusplus && __GNUC_PREREQ (2,8) +# define __THROW throw () +# define __NTH(fct) fct throw () +# else +# define __THROW +# define __NTH(fct) fct +# endif +# endif + +#else /* Not GCC. */ + +# define __inline /* No inline functions. */ + +# define __THROW +# define __NTH(fct) fct + +# define __const const +# define __signed signed +# define __volatile volatile + +#endif /* GCC. */ + +/* These two macros are not used in glibc anymore. They are kept here + only because some other projects expect the macros to be defined. */ +#define __P(args) args +#define __PMT(args) args + +/* For these things, GCC behaves the ANSI way normally, + and the non-ANSI way under -traditional. */ + +#define __CONCAT(x,y) x ## y +#define __STRING(x) #x + +/* This is not a typedef so `const __ptr_t' does the right thing. */ +#define __ptr_t void * +#define __long_double_t long double + + +/* C++ needs to know that types and declarations are C, not C++. */ +#ifdef __cplusplus +# define __BEGIN_DECLS extern "C" { +# define __END_DECLS } +#else +# define __BEGIN_DECLS +# define __END_DECLS +#endif + + +/* The standard library needs the functions from the ISO C90 standard + in the std namespace. At the same time we want to be safe for + future changes and we include the ISO C99 code in the non-standard + namespace __c99. The C++ wrapper header take case of adding the + definitions to the global namespace. */ +#if defined __cplusplus && defined _GLIBCPP_USE_NAMESPACES +# define __BEGIN_NAMESPACE_STD namespace std { +# define __END_NAMESPACE_STD } +# define __USING_NAMESPACE_STD(name) using std::name; +# define __BEGIN_NAMESPACE_C99 namespace __c99 { +# define __END_NAMESPACE_C99 } +# define __USING_NAMESPACE_C99(name) using __c99::name; +#else +/* For compatibility we do not add the declarations into any + namespace. They will end up in the global namespace which is what + old code expects. */ +# define __BEGIN_NAMESPACE_STD +# define __END_NAMESPACE_STD +# define __USING_NAMESPACE_STD(name) +# define __BEGIN_NAMESPACE_C99 +# define __END_NAMESPACE_C99 +# define __USING_NAMESPACE_C99(name) +#endif + + +/* Fortify support. */ +#define __bos(ptr) __builtin_object_size (ptr, __USE_FORTIFY_LEVEL > 1) +#define __bos0(ptr) __builtin_object_size (ptr, 0) + +#if __GNUC_PREREQ (4,3) +# define __warndecl(name, msg) \ + extern void name (void) __attribute__((__warning__ (msg))) +# define __warnattr(msg) __attribute__((__warning__ (msg))) +# define __errordecl(name, msg) \ + extern void name (void) __attribute__((__error__ (msg))) +#else +# define __warndecl(name, msg) extern void name (void) +# define __warnattr(msg) +# define __errordecl(name, msg) extern void name (void) +#endif + +/* Support for flexible arrays. */ +#if __GNUC_PREREQ (2,97) +/* GCC 2.97 supports C99 flexible array members. */ +# define __flexarr [] +#else +# ifdef __GNUC__ +# define __flexarr [0] +# else +# if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L +# define __flexarr [] +# else +/* Some other non-C99 compiler. Approximate with [1]. */ +# define __flexarr [1] +# endif +# endif +#endif + + +/* __asm__ ("xyz") is used throughout the headers to rename functions + at the assembly language level. This is wrapped by the __REDIRECT + macro, in order to support compilers that can do this some other + way. When compilers don't support asm-names at all, we have to do + preprocessor tricks instead (which don't have exactly the right + semantics, but it's the best we can do). + + Example: + int __REDIRECT(setpgrp, (__pid_t pid, __pid_t pgrp), setpgid); */ + +#if defined __GNUC__ && __GNUC__ >= 2 + +# define __REDIRECT(name, proto, alias) name proto __asm__ (__ASMNAME (#alias)) +# ifdef __cplusplus +# define __REDIRECT_NTH(name, proto, alias) \ + name proto __THROW __asm__ (__ASMNAME (#alias)) +# else +# define __REDIRECT_NTH(name, proto, alias) \ + name proto __asm__ (__ASMNAME (#alias)) __THROW +# endif +# define __ASMNAME(cname) __ASMNAME2 (__USER_LABEL_PREFIX__, cname) +# define __ASMNAME2(prefix, cname) __STRING (prefix) cname + +/* +#elif __SOME_OTHER_COMPILER__ + +# define __REDIRECT(name, proto, alias) name proto; \ + _Pragma("let " #name " = " #alias) +*/ +#endif + +/* GCC has various useful declarations that can be made with the + `__attribute__' syntax. All of the ways we use this do fine if + they are omitted for compilers that don't understand it. */ +#if !defined __GNUC__ || __GNUC__ < 2 +# define __attribute__(xyz) /* Ignore */ +#endif + +/* We make this a no-op unless it can be used as both a variable and + a type attribute. gcc 2.8 is known to support both. */ +#if __GNUC_PREREQ (2,8) +# define __attribute_aligned__(size) __attribute__ ((__aligned__ (size))) +#else +# define __attribute_aligned__(size) /* Ignore */ +#endif + +/* At some point during the gcc 2.96 development the `malloc' attribute + for functions was introduced. We don't want to use it unconditionally + (although this would be possible) since it generates warnings. */ +#if __GNUC_PREREQ (2,96) +# define __attribute_malloc__ __attribute__ ((__malloc__)) +#else +# define __attribute_malloc__ /* Ignore */ +#endif + +/* At some point during the gcc 2.96 development the `pure' attribute + for functions was introduced. We don't want to use it unconditionally + (although this would be possible) since it generates warnings. */ +#if __GNUC_PREREQ (2,96) +# define __attribute_pure__ __attribute__ ((__pure__)) +#else +# define __attribute_pure__ /* Ignore */ +#endif + +/* At some point during the gcc 3.1 development the `used' attribute + for functions was introduced. We don't want to use it unconditionally + (although this would be possible) since it generates warnings. */ +#if __GNUC_PREREQ (3,1) +# define __attribute_used__ __attribute__ ((__used__)) +# define __attribute_noinline__ __attribute__ ((__noinline__)) +#else +# define __attribute_used__ __attribute__ ((__unused__)) +# define __attribute_noinline__ /* Ignore */ +#endif + +/* gcc allows marking deprecated functions. */ +#if __GNUC_PREREQ (3,2) && !defined(__UCLIBC_HIDE_DEPRECATED__) +# define __attribute_deprecated__ __attribute__ ((__deprecated__)) +#else +# define __attribute_deprecated__ /* Ignore */ +#endif + +/* At some point during the gcc 2.8 development the `format_arg' attribute + for functions was introduced. We don't want to use it unconditionally + (although this would be possible) since it generates warnings. + If several `format_arg' attributes are given for the same function, in + gcc-3.0 and older, all but the last one are ignored. In newer gccs, + all designated arguments are considered. */ +#if __GNUC_PREREQ (2,8) +# define __attribute_format_arg__(x) __attribute__ ((__format_arg__ (x))) +#else +# define __attribute_format_arg__(x) /* Ignore */ +#endif + +/* At some point during the gcc 2.97 development the `strfmon' format + attribute for functions was introduced. We don't want to use it + unconditionally (although this would be possible) since it + generates warnings. */ +#if __GNUC_PREREQ (2,97) +# define __attribute_format_strfmon__(a,b) \ + __attribute__ ((__format__ (__strfmon__, a, b))) +#else +# define __attribute_format_strfmon__(a,b) /* Ignore */ +#endif + +/* The nonull function attribute allows to mark pointer parameters which + must not be NULL. */ +#if __GNUC_PREREQ (3,3) +# define __nonnull(params) __attribute__ ((__nonnull__ params)) +#else +# define __nonnull(params) +#endif + +/* If fortification mode, we warn about unused results of certain + function calls which can lead to problems. */ +#if __GNUC_PREREQ (3,4) +# define __attribute_warn_unused_result__ \ + __attribute__ ((__warn_unused_result__)) +# if __USE_FORTIFY_LEVEL > 0 +# define __wur __attribute_warn_unused_result__ +# endif +#else +# define __attribute_warn_unused_result__ /* empty */ +#endif +#ifndef __wur +# define __wur /* Ignore */ +#endif + +/* Forces a function to be always inlined. */ +#if __GNUC_PREREQ (3,2) +# define __always_inline __inline __attribute__ ((__always_inline__)) +#else +# define __always_inline __inline +#endif + +/* GCC 4.3 and above with -std=c99 or -std=gnu99 implements ISO C99 + inline semantics, unless -fgnu89-inline is used. + For -std=gnu99, forcing gnu_inline attribute does not change behavior, + but may silence spurious warnings (such as in GCC 4.2). */ +#if !defined __cplusplus || __GNUC_PREREQ (4,3) +# if defined __GNUC_STDC_INLINE__ || defined __GNUC_GNU_INLINE__ || defined __cplusplus +# define __extern_inline extern __inline __attribute__ ((__gnu_inline__)) +# if __GNUC_PREREQ (4,3) +# define __extern_always_inline \ + extern __always_inline __attribute__ ((__gnu_inline__, __artificial__)) +# else +# define __extern_always_inline \ + extern __always_inline __attribute__ ((__gnu_inline__)) +# endif +# else +# define __extern_inline extern __inline +# define __extern_always_inline extern __always_inline +# endif +#endif + +/* GCC 4.3 and above allow passing all anonymous arguments of an + __extern_always_inline function to some other vararg function. */ +#if __GNUC_PREREQ (4,3) +# define __va_arg_pack() __builtin_va_arg_pack () +# define __va_arg_pack_len() __builtin_va_arg_pack_len () +#endif + +/* It is possible to compile containing GCC extensions even if GCC is + run in pedantic mode if the uses are carefully marked using the + `__extension__' keyword. But this is not generally available before + version 2.8. */ +#if !__GNUC_PREREQ (2,8) +# define __extension__ /* Ignore */ +#endif + +/* __restrict is known in EGCS 1.2 and above. */ +#if !__GNUC_PREREQ (2,92) +# define __restrict /* Ignore */ +#endif + +/* ISO C99 also allows to declare arrays as non-overlapping. The syntax is + array_name[restrict] + GCC 3.1 supports this. */ +#if __GNUC_PREREQ (3,1) && !defined __GNUG__ +# define __restrict_arr __restrict +#else +# ifdef __GNUC__ +# define __restrict_arr /* Not supported in old GCC. */ +# else +# if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L +# define __restrict_arr restrict +# else +/* Some other non-C99 compiler. */ +# define __restrict_arr /* Not supported. */ +# endif +# endif +#endif + +#endif /* sys/cdefs.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/dir.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/dir.h new file mode 100644 index 00000000..2611d6cd --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/dir.h @@ -0,0 +1,28 @@ +/* Copyright (C) 1991, 1996 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_DIR_H +#define _SYS_DIR_H 1 + +#include + +#include + +#define direct dirent + +#endif /* sys/dir.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/errno.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/errno.h new file mode 100644 index 00000000..339f4fc1 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/errno.h @@ -0,0 +1 @@ +#include diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/fcntl.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/fcntl.h new file mode 100644 index 00000000..cd304557 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/fcntl.h @@ -0,0 +1 @@ +#include diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/file.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/file.h new file mode 100644 index 00000000..3b8dbc9c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/file.h @@ -0,0 +1,56 @@ +/* Copyright (C) 1991, 92, 96, 97, 98, 99 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_FILE_H +#define _SYS_FILE_H 1 + +#include + +#ifndef _FCNTL_H +# include +#endif + +__BEGIN_DECLS + + +/* Alternate names for values for the WHENCE argument to `lseek'. + These are the same as SEEK_SET, SEEK_CUR, and SEEK_END, respectively. */ +#ifndef L_SET +# define L_SET 0 /* Seek from beginning of file. */ +# define L_INCR 1 /* Seek from current position. */ +# define L_XTND 2 /* Seek from end of file. */ +#endif + + +/* Operations for the `flock' call. */ +#define LOCK_SH 1 /* Shared lock. */ +#define LOCK_EX 2 /* Exclusive lock. */ +#define LOCK_UN 8 /* Unlock. */ + +/* Can be OR'd in to one of the above. */ +#define LOCK_NB 4 /* Don't block when locking. */ + + +/* Apply or remove an advisory lock, according to OPERATION, + on the file FD refers to. */ +extern int flock (int __fd, int __operation) __THROW; + + +__END_DECLS + +#endif /* sys/file.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/fsuid.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/fsuid.h new file mode 100644 index 00000000..4ecb1991 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/fsuid.h @@ -0,0 +1,36 @@ +/* Copyright (C) 1997, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_FSUID_H +#define _SYS_FSUID_H 1 + +#include +#include + +__BEGIN_DECLS + +/* Change uid used for file access control to UID, without affecting + other privileges (such as who can send signals at the process). */ +extern int setfsuid (__uid_t __uid) __THROW; + +/* Ditto for group id. */ +extern int setfsgid (__gid_t __gid) __THROW; + +__END_DECLS + +#endif /* fsuid.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/ioctl.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/ioctl.h new file mode 100644 index 00000000..528403e7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/ioctl.h @@ -0,0 +1,47 @@ +/* Copyright (C) 1991, 92, 93, 94, 96, 98, 99 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_IOCTL_H +#define _SYS_IOCTL_H 1 + +#include + +__BEGIN_DECLS + +/* Get the list of `ioctl' requests and related constants. */ +#include + +/* Define some types used by `ioctl' requests. */ +#include + +/* On a Unix system, the system probably defines some of + the symbols we define in (usually with the same + values). The code to generate has omitted these + symbols to avoid the conflict, but a Unix program expects + to define them, so we must include here. */ +#include + +/* Perform the I/O control operation specified by REQUEST on FD. + One argument may follow; its presence and type depend on REQUEST. + Return value depends on REQUEST. Usually -1 indicates error. */ +extern int ioctl (int __fd, unsigned long int __request, ...) __THROW; +libc_hidden_proto(ioctl) + +__END_DECLS + +#endif /* sys/ioctl.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/ipc.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/ipc.h new file mode 100644 index 00000000..42806db2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/ipc.h @@ -0,0 +1,58 @@ +/* Copyright (C) 1995, 1996, 1997, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_IPC_H +#define _SYS_IPC_H 1 + +#include + +#if !defined __USE_SVID && !defined __USE_XOPEN && __GNUC__ >= 2 +# warning "Files using this header must be compiled with _SVID_SOURCE or _XOPEN_SOURCE" +#endif + +/* Get system dependent definition of `struct ipc_perm' and more. */ +#include + +#ifndef __uid_t_defined +typedef __uid_t uid_t; +# define __uid_t_defined +#endif + +#ifndef __gid_t_defined +typedef __gid_t gid_t; +# define __gid_t_defined +#endif + +#ifndef __mode_t_defined +typedef __mode_t mode_t; +# define __mode_t_defined +#endif + +#ifndef __key_t_defined +typedef __key_t key_t; +# define __key_t_defined +#endif + +__BEGIN_DECLS + +/* Generates key for System V style IPC. */ +extern key_t ftok (__const char *__pathname, int __proj_id) __THROW; + +__END_DECLS + +#endif /* sys/ipc.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/kd.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/kd.h new file mode 100644 index 00000000..d459c079 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/kd.h @@ -0,0 +1,35 @@ +/* Copyright (C) 1996, 1997, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_KD_H +#define _SYS_KD_H 1 + +/* Make sure the header is not loaded. */ +#ifndef _LINUX_TYPES_H +# define _LINUX_TYPES_H 1 +# define __undef_LINUX_TYPES_H +#endif + +#include + +#ifdef __undef_LINUX_TYPES_H +# undef _LINUX_TYPES_H +# undef __undef_LINUX_TYPES_H +#endif + +#endif /* sys/kd.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/kdaemon.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/kdaemon.h new file mode 100644 index 00000000..61491f93 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/kdaemon.h @@ -0,0 +1,33 @@ +/* Copyright (C) 1996, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Interfaces to control the various kernel daemons. */ + +#ifndef _SYS_KDAEMON_H + +#define _SYS_KDAEMON_H 1 +#include + +__BEGIN_DECLS + +/* Start, flush, or tune the kernel's buffer flushing daemon. */ +extern int bdflush (int __func, long int __data) __THROW; + +__END_DECLS + +#endif /* _SYS_KDAEMON_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/klog.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/klog.h new file mode 100644 index 00000000..35f5fe40 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/klog.h @@ -0,0 +1,34 @@ +/* Copyright (C) 1996, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_KLOG_H + +#define _SYS_KLOG_H 1 +#include + +__BEGIN_DECLS + +/* Control the kernel's logging facility. This corresponds exactly to + the kernel's syslog system call, but that name is easily confused + with the user-level syslog facility, which is something completely + different. */ +extern int klogctl (int __type, char *__bufp, int __len) __THROW; + +__END_DECLS + +#endif /* _SYS_KLOG_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/mman.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/mman.h new file mode 100644 index 00000000..470209ed --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/mman.h @@ -0,0 +1,180 @@ +/* Definitions for BSD-style memory management. + Copyright (C) 1994-2000, 2003, 2004, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_MMAN_H +#define _SYS_MMAN_H 1 + +#include +#include +#define __need_size_t +#include + +#ifndef __off_t_defined +# ifndef __USE_FILE_OFFSET64 +typedef __off_t off_t; +# else +typedef __off64_t off_t; +# endif +# define __off_t_defined +#endif + +#ifndef __mode_t_defined +typedef __mode_t mode_t; +# define __mode_t_defined +#endif + +#include + +/* Return value of `mmap' in case of an error. */ +#define MAP_FAILED ((void *) -1) + +__BEGIN_DECLS +/* Map addresses starting near ADDR and extending for LEN bytes. from + OFFSET into the file FD describes according to PROT and FLAGS. If ADDR + is nonzero, it is the desired mapping address. If the MAP_FIXED bit is + set in FLAGS, the mapping will be at ADDR exactly (which must be + page-aligned); otherwise the system chooses a convenient nearby address. + The return value is the actual mapping address chosen or MAP_FAILED + for errors (in which case `errno' is set). A successful `mmap' call + deallocates any previous mapping for the affected region. */ + +#ifndef __USE_FILE_OFFSET64 +extern void *mmap (void *__addr, size_t __len, int __prot, + int __flags, int __fd, __off_t __offset) __THROW; +libc_hidden_proto(mmap) +#else +# ifdef __REDIRECT_NTH +extern void * __REDIRECT_NTH (mmap, + (void *__addr, size_t __len, int __prot, + int __flags, int __fd, __off64_t __offset), + mmap64); +# else +# define mmap mmap64 +# endif +#endif +#ifdef __USE_LARGEFILE64 +extern void *mmap64 (void *__addr, size_t __len, int __prot, + int __flags, int __fd, __off64_t __offset) __THROW; +#endif + +/* Deallocate any mapping for the region starting at ADDR and extending LEN + bytes. Returns 0 if successful, -1 for errors (and sets errno). */ +extern int munmap (void *__addr, size_t __len) __THROW; +libc_hidden_proto(munmap) + +/* Change the memory protection of the region starting at ADDR and + extending LEN bytes to PROT. Returns 0 if successful, -1 for errors + (and sets errno). */ +extern int mprotect (void *__addr, size_t __len, int __prot) __THROW; + +#ifdef __ARCH_USE_MMU__ + +/* Synchronize the region starting at ADDR and extending LEN bytes with the + file it maps. Filesystem operations on a file being mapped are + unpredictable before this is done. Flags are from the MS_* set. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern int msync (void *__addr, size_t __len, int __flags); + +#else + +/* On no-mmu systems you can't have real private mappings. */ +static __inline__ int msync (void *__addr, size_t __len, int __flags) { return 0; } + +#endif + +#if defined __USE_BSD && (defined __UCLIBC_LINUX_SPECIFIC__ || defined __UCLIBC_HAS_THREADS_NATIVE__) +/* Advise the system about particular usage patterns the program follows + for the region starting at ADDR and extending LEN bytes. */ +extern int madvise (void *__addr, size_t __len, int __advice) __THROW; +#endif +#if defined __USE_XOPEN2K && defined __UCLIBC_HAS_ADVANCED_REALTIME__ +/* This is the POSIX name for this function. */ +extern int posix_madvise (void *__addr, size_t __len, int __advice) __THROW; +#endif + +#if defined __UCLIBC_HAS_REALTIME__ +# ifdef __ARCH_USE_MMU__ + +/* Guarantee all whole pages mapped by the range [ADDR,ADDR+LEN) to + be memory resident. */ +extern int mlock (__const void *__addr, size_t __len) __THROW; + +/* Unlock whole pages previously mapped by the range [ADDR,ADDR+LEN). */ +extern int munlock (__const void *__addr, size_t __len) __THROW; + +/* Cause all currently mapped pages of the process to be memory resident + until unlocked by a call to the `munlockall', until the process exits, + or until the process calls `execve'. */ +extern int mlockall (int __flags) __THROW; + +/* All currently mapped pages of the process' address space become + unlocked. */ +extern int munlockall (void) __THROW; + +#else + +/* On no-mmu systems, memory cannot be swapped out, so + * these functions will always succeed. */ +static __inline__ int mlock (__const void *__addr, size_t __len) { return 0; } +static __inline__ int munlock (__const void *__addr, size_t __len) { return 0; } +static __inline__ int mlockall (int __flags) { return 0; } +static __inline__ int munlockall (void) { return 0; } +#endif +#endif /* __UCLIBC_HAS_REALTIME__ */ + +#if defined __USE_MISC && defined __UCLIBC_BSD_SPECIFIC__ +/* mincore returns the memory residency status of the pages in the + current process's address space specified by [start, start + len). + The status is returned in a vector of bytes. The least significant + bit of each byte is 1 if the referenced page is in memory, otherwise + it is zero. */ +extern int mincore (void *__start, size_t __len, unsigned char *__vec) + __THROW; +#endif + +#ifdef __USE_GNU +/* Remap pages mapped by the range [ADDR,ADDR+OLD_LEN) to new length + NEW_LEN. If MREMAP_MAYMOVE is set in FLAGS the returned address + may differ from ADDR. If MREMAP_FIXED is set in FLAGS the function + takes another paramter which is a fixed address at which the block + resides after a successful call. */ +extern void *mremap (void *__addr, size_t __old_len, size_t __new_len, + int __flags, ...) __THROW; +libc_hidden_proto(mremap) + +#ifdef __UCLIBC_LINUX_SPECIFIC__ +/* Remap arbitrary pages of a shared backing store within an existing + VMA. */ +extern int remap_file_pages (void *__start, size_t __size, int __prot, + size_t __pgoff, int __flags) __THROW; +#endif +#endif + + +/* Open shared memory segment. */ +extern int shm_open (__const char *__name, int __oflag, mode_t __mode); + +/* Remove shared memory segment. */ +extern int shm_unlink (__const char *__name); + +__END_DECLS + +#endif /* sys/mman.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/mount.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/mount.h new file mode 100644 index 00000000..57d440f2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/mount.h @@ -0,0 +1,123 @@ +/* Header file for mounting/unmount Linux filesystems. + Copyright (C) 1996,1997,1998,1999,2000,2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This is taken from /usr/include/linux/fs.h. */ + +#ifndef _SYS_MOUNT_H +#define _SYS_MOUNT_H 1 + +#include +#include + +#define BLOCK_SIZE 1024 +#define BLOCK_SIZE_BITS 10 + + +/* These are the fs-independent mount-flags: up to 16 flags are + supported */ +enum +{ + MS_RDONLY = 1, /* Mount read-only. */ +#define MS_RDONLY MS_RDONLY + MS_NOSUID = 2, /* Ignore suid and sgid bits. */ +#define MS_NOSUID MS_NOSUID + MS_NODEV = 4, /* Disallow access to device special files. */ +#define MS_NODEV MS_NODEV + MS_NOEXEC = 8, /* Disallow program execution. */ +#define MS_NOEXEC MS_NOEXEC + MS_SYNCHRONOUS = 16, /* Writes are synced at once. */ +#define MS_SYNCHRONOUS MS_SYNCHRONOUS + MS_REMOUNT = 32, /* Alter flags of a mounted FS. */ +#define MS_REMOUNT MS_REMOUNT + MS_MANDLOCK = 64, /* Allow mandatory locks on an FS. */ +#define MS_MANDLOCK MS_MANDLOCK + S_WRITE = 128, /* Write on file/directory/symlink. */ +#define S_WRITE S_WRITE + S_APPEND = 256, /* Append-only file. */ +#define S_APPEND S_APPEND + S_IMMUTABLE = 512, /* Immutable file. */ +#define S_IMMUTABLE S_IMMUTABLE + MS_NOATIME = 1024, /* Do not update access times. */ +#define MS_NOATIME MS_NOATIME + MS_NODIRATIME = 2048, /* Do not update directory access times. */ +#define MS_NODIRATIME MS_NODIRATIME + MS_BIND = 4096, /* Bind directory at different place. */ +#define MS_BIND MS_BIND +}; + +/* Flags that can be altered by MS_REMOUNT */ +#define MS_RMT_MASK (MS_RDONLY|MS_SYNCHRONOUS|MS_MANDLOCK|MS_NOATIME \ + |MS_NODIRATIME) + + +/* Magic mount flag number. Has to be or-ed to the flag values. */ + +#define MS_MGC_VAL 0xc0ed0000 /* Magic flag number to indicate "new" flags */ +#define MS_MGC_MSK 0xffff0000 /* Magic flag number mask */ + + +/* The read-only stuff doesn't really belong here, but any other place + is probably as bad and I don't want to create yet another include + file. */ + +#define BLKROSET _IO(0x12, 93) /* Set device read-only (0 = read-write). */ +#define BLKROGET _IO(0x12, 94) /* Get read-only status (0 = read_write). */ +#define BLKRRPART _IO(0x12, 95) /* Re-read partition table. */ +#define BLKGETSIZE _IO(0x12, 96) /* Return device size. */ +#define BLKFLSBUF _IO(0x12, 97) /* Flush buffer cache. */ +#define BLKRASET _IO(0x12, 98) /* Set read ahead for block device. */ +#define BLKRAGET _IO(0x12, 99) /* Get current read ahead setting. */ +#define BLKFRASET _IO(0x12,100) /* Set filesystem read-ahead. */ +#define BLKFRAGET _IO(0x12,101) /* Get filesystem read-ahead. */ +#define BLKSECTSET _IO(0x12,102) /* Set max sectors per request. */ +#define BLKSECTGET _IO(0x12,103) /* Get max sectors per request. */ +#define BLKSSZGET _IO(0x12,104) /* Get block device sector size. */ +#define BLKBSZGET _IOR(0x12,112,size_t) +#define BLKBSZSET _IOW(0x12,113,size_t) +#define BLKGETSIZE64 _IOR(0x12,114,size_t) /* return device size. */ + + +/* Possible value for FLAGS parameter of `umount2'. */ +enum +{ + MNT_FORCE = 1, /* Force unmounting. */ +#define MNT_FORCE MNT_FORCE + MNT_DETACH = 2, /* Just detach from the tree. */ +#define MNT_DETACH MNT_DETACH + MNT_EXPIRE = 4 /* Mark for expiry. */ +#define MNT_EXPIRE MNT_EXPIRE +}; + + +__BEGIN_DECLS + +/* Mount a filesystem. */ +extern int mount (__const char *__special_file, __const char *__dir, + __const char *__fstype, unsigned long int __rwflag, + __const void *__data) __THROW; + +/* Unmount a filesystem. */ +extern int umount (__const char *__special_file) __THROW; + +/* Unmount a filesystem. Force unmounting if FLAGS is set to MNT_FORCE. */ +extern int umount2 (__const char *__special_file, int __flags) __THROW; + +__END_DECLS + +#endif /* _SYS_MOUNT_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/msg.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/msg.h new file mode 100644 index 00000000..cdc96be9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/msg.h @@ -0,0 +1,85 @@ +/* Copyright (C) 1995-1997,1999,2000,2003,2006,2007 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_MSG_H +#define _SYS_MSG_H + +#include + +#define __need_size_t +#include + +/* Get common definition of System V style IPC. */ +#include + +/* Get system dependent definition of `struct msqid_ds' and more. */ +#include + +/* Define types required by the standard. */ +#define __need_time_t +#include + +#ifndef __pid_t_defined +typedef __pid_t pid_t; +# define __pid_t_defined +#endif + +#ifndef __ssize_t_defined +typedef __ssize_t ssize_t; +# define __ssize_t_defined +#endif + +/* The following System V style IPC functions implement a message queue + system. The definition is found in XPG2. */ + +#ifdef __USE_GNU +/* Template for struct to be used as argument for `msgsnd' and `msgrcv'. */ +struct msgbuf + { + long int mtype; /* type of received/sent message */ + char mtext[1]; /* text of the message */ + }; +#endif + + +__BEGIN_DECLS + +/* Message queue control operation. */ +extern int msgctl (int __msqid, int __cmd, struct msqid_ds *__buf) __THROW; + +/* Get messages queue. */ +extern int msgget (key_t __key, int __msgflg) __THROW; + +/* Receive message from message queue. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern ssize_t msgrcv (int __msqid, void *__msgp, size_t __msgsz, + long int __msgtyp, int __msgflg); + +/* Send message to message queue. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern int msgsnd (int __msqid, __const void *__msgp, size_t __msgsz, + int __msgflg); + +__END_DECLS + +#endif /* sys/msg.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/mtio.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/mtio.h new file mode 100644 index 00000000..51fa550c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/mtio.h @@ -0,0 +1,277 @@ +/* Structures and definitions for magnetic tape I/O control commands. + Copyright (C) 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Written by H. Bergman . */ + +#ifndef _SYS_MTIO_H +#define _SYS_MTIO_H 1 + +/* Get necessary definitions from system and kernel headers. */ +#include +#include + + +/* Structure for MTIOCTOP - magnetic tape operation command. */ +struct mtop + { + short int mt_op; /* Operations defined below. */ + int mt_count; /* How many of them. */ + }; +#define _IOT_mtop /* Hurd ioctl type field. */ \ + _IOT (_IOTS (short), 1, _IOTS (int), 1, 0, 0) + +/* Magnetic Tape operations [Not all operations supported by all drivers]. */ +#define MTRESET 0 /* +reset drive in case of problems. */ +#define MTFSF 1 /* Forward space over FileMark, + * position at first record of next file. */ +#define MTBSF 2 /* Backward space FileMark (position before FM). */ +#define MTFSR 3 /* Forward space record. */ +#define MTBSR 4 /* Backward space record. */ +#define MTWEOF 5 /* Write an end-of-file record (mark). */ +#define MTREW 6 /* Rewind. */ +#define MTOFFL 7 /* Rewind and put the drive offline (eject?). */ +#define MTNOP 8 /* No op, set status only (read with MTIOCGET). */ +#define MTRETEN 9 /* Retension tape. */ +#define MTBSFM 10 /* +backward space FileMark, position at FM. */ +#define MTFSFM 11 /* +forward space FileMark, position at FM. */ +#define MTEOM 12 /* Goto end of recorded media (for appending files). + MTEOM positions after the last FM, ready for + appending another file. */ +#define MTERASE 13 /* Erase tape -- be careful! */ + +#define MTRAS1 14 /* Run self test 1 (nondestructive). */ +#define MTRAS2 15 /* Run self test 2 (destructive). */ +#define MTRAS3 16 /* Reserved for self test 3. */ + +#define MTSETBLK 20 /* Set block length (SCSI). */ +#define MTSETDENSITY 21 /* Set tape density (SCSI). */ +#define MTSEEK 22 /* Seek to block (Tandberg, etc.). */ +#define MTTELL 23 /* Tell block (Tandberg, etc.). */ +#define MTSETDRVBUFFER 24 /* Set the drive buffering according to SCSI-2. + Ordinary buffered operation with code 1. */ +#define MTFSS 25 /* Space forward over setmarks. */ +#define MTBSS 26 /* Space backward over setmarks. */ +#define MTWSM 27 /* Write setmarks. */ + +#define MTLOCK 28 /* Lock the drive door. */ +#define MTUNLOCK 29 /* Unlock the drive door. */ +#define MTLOAD 30 /* Execute the SCSI load command. */ +#define MTUNLOAD 31 /* Execute the SCSI unload command. */ +#define MTCOMPRESSION 32/* Control compression with SCSI mode page 15. */ +#define MTSETPART 33 /* Change the active tape partition. */ +#define MTMKPART 34 /* Format the tape with one or two partitions. */ + +/* structure for MTIOCGET - mag tape get status command */ + +struct mtget + { + long int mt_type; /* Type of magtape device. */ + long int mt_resid; /* Residual count: (not sure) + number of bytes ignored, or + number of files not skipped, or + number of records not skipped. */ + /* The following registers are device dependent. */ + long int mt_dsreg; /* Status register. */ + long int mt_gstat; /* Generic (device independent) status. */ + long int mt_erreg; /* Error register. */ + /* The next two fields are not always used. */ + __daddr_t mt_fileno; /* Number of current file on tape. */ + __daddr_t mt_blkno; /* Current block number. */ + }; +#define _IOT_mtget /* Hurd ioctl type field. */ \ + _IOT (_IOTS (long), 7, 0, 0, 0, 0) + + +/* Constants for mt_type. Not all of these are supported, and + these are not all of the ones that are supported. */ +#define MT_ISUNKNOWN 0x01 +#define MT_ISQIC02 0x02 /* Generic QIC-02 tape streamer. */ +#define MT_ISWT5150 0x03 /* Wangtek 5150EQ, QIC-150, QIC-02. */ +#define MT_ISARCHIVE_5945L2 0x04 /* Archive 5945L-2, QIC-24, QIC-02?. */ +#define MT_ISCMSJ500 0x05 /* CMS Jumbo 500 (QIC-02?). */ +#define MT_ISTDC3610 0x06 /* Tandberg 6310, QIC-24. */ +#define MT_ISARCHIVE_VP60I 0x07 /* Archive VP60i, QIC-02. */ +#define MT_ISARCHIVE_2150L 0x08 /* Archive Viper 2150L. */ +#define MT_ISARCHIVE_2060L 0x09 /* Archive Viper 2060L. */ +#define MT_ISARCHIVESC499 0x0A /* Archive SC-499 QIC-36 controller. */ +#define MT_ISQIC02_ALL_FEATURES 0x0F /* Generic QIC-02 with all features. */ +#define MT_ISWT5099EEN24 0x11 /* Wangtek 5099-een24, 60MB, QIC-24. */ +#define MT_ISTEAC_MT2ST 0x12 /* Teac MT-2ST 155mb drive, + Teac DC-1 card (Wangtek type). */ +#define MT_ISEVEREX_FT40A 0x32 /* Everex FT40A (QIC-40). */ +#define MT_ISDDS1 0x51 /* DDS device without partitions. */ +#define MT_ISDDS2 0x52 /* DDS device with partitions. */ +#define MT_ISSCSI1 0x71 /* Generic ANSI SCSI-1 tape unit. */ +#define MT_ISSCSI2 0x72 /* Generic ANSI SCSI-2 tape unit. */ + +/* QIC-40/80/3010/3020 ftape supported drives. + 20bit vendor ID + 0x800000 (see vendors.h in ftape distribution). */ +#define MT_ISFTAPE_UNKNOWN 0x800000 /* obsolete */ +#define MT_ISFTAPE_FLAG 0x800000 + +struct mt_tape_info + { + long int t_type; /* Device type id (mt_type). */ + char *t_name; /* Descriptive name. */ + }; + +#define MT_TAPE_INFO \ + { \ + {MT_ISUNKNOWN, "Unknown type of tape device"}, \ + {MT_ISQIC02, "Generic QIC-02 tape streamer"}, \ + {MT_ISWT5150, "Wangtek 5150, QIC-150"}, \ + {MT_ISARCHIVE_5945L2, "Archive 5945L-2"}, \ + {MT_ISCMSJ500, "CMS Jumbo 500"}, \ + {MT_ISTDC3610, "Tandberg TDC 3610, QIC-24"}, \ + {MT_ISARCHIVE_VP60I, "Archive VP60i, QIC-02"}, \ + {MT_ISARCHIVE_2150L, "Archive Viper 2150L"}, \ + {MT_ISARCHIVE_2060L, "Archive Viper 2060L"}, \ + {MT_ISARCHIVESC499, "Archive SC-499 QIC-36 controller"}, \ + {MT_ISQIC02_ALL_FEATURES, "Generic QIC-02 tape, all features"}, \ + {MT_ISWT5099EEN24, "Wangtek 5099-een24, 60MB"}, \ + {MT_ISTEAC_MT2ST, "Teac MT-2ST 155mb data cassette drive"}, \ + {MT_ISEVEREX_FT40A, "Everex FT40A, QIC-40"}, \ + {MT_ISSCSI1, "Generic SCSI-1 tape"}, \ + {MT_ISSCSI2, "Generic SCSI-2 tape"}, \ + {0, NULL} \ + } + + +/* Structure for MTIOCPOS - mag tape get position command. */ + +struct mtpos + { + long int mt_blkno; /* Current block number. */ + }; +#define _IOT_mtpos /* Hurd ioctl type field. */ \ + _IOT_SIMPLE (long) + + +/* Structure for MTIOCGETCONFIG/MTIOCSETCONFIG primarily intended + as an interim solution for QIC-02 until DDI is fully implemented. */ +struct mtconfiginfo + { + long int mt_type; /* Drive type. */ + long int ifc_type; /* Interface card type. */ + unsigned short int irqnr; /* IRQ number to use. */ + unsigned short int dmanr; /* DMA channel to use. */ + unsigned short int port; /* IO port base address. */ + + unsigned long int debug; /* Debugging flags. */ + + unsigned have_dens:1; + unsigned have_bsf:1; + unsigned have_fsr:1; + unsigned have_bsr:1; + unsigned have_eod:1; + unsigned have_seek:1; + unsigned have_tell:1; + unsigned have_ras1:1; + unsigned have_ras2:1; + unsigned have_ras3:1; + unsigned have_qfa:1; + + unsigned pad1:5; + char reserved[10]; + }; +#define _IOT_mtconfiginfo /* Hurd ioctl type field. */ \ + _IOT (_IOTS (long), 2, _IOTS (short), 3, _IOTS (long), 1) /* XXX wrong */ + + +/* Magnetic tape I/O control commands. */ +#define MTIOCTOP _IOW('m', 1, struct mtop) /* Do a mag tape op. */ +#define MTIOCGET _IOR('m', 2, struct mtget) /* Get tape status. */ +#define MTIOCPOS _IOR('m', 3, struct mtpos) /* Get tape position.*/ + +/* The next two are used by the QIC-02 driver for runtime reconfiguration. + See tpqic02.h for struct mtconfiginfo. */ +#define MTIOCGETCONFIG _IOR('m', 4, struct mtconfiginfo) /* Get tape config.*/ +#define MTIOCSETCONFIG _IOW('m', 5, struct mtconfiginfo) /* Set tape config.*/ + +/* Generic Mag Tape (device independent) status macros for examining + mt_gstat -- HP-UX compatible. + There is room for more generic status bits here, but I don't + know which of them are reserved. At least three or so should + be added to make this really useful. */ +#define GMT_EOF(x) ((x) & 0x80000000) +#define GMT_BOT(x) ((x) & 0x40000000) +#define GMT_EOT(x) ((x) & 0x20000000) +#define GMT_SM(x) ((x) & 0x10000000) /* DDS setmark */ +#define GMT_EOD(x) ((x) & 0x08000000) /* DDS EOD */ +#define GMT_WR_PROT(x) ((x) & 0x04000000) +/* #define GMT_ ? ((x) & 0x02000000) */ +#define GMT_ONLINE(x) ((x) & 0x01000000) +#define GMT_D_6250(x) ((x) & 0x00800000) +#define GMT_D_1600(x) ((x) & 0x00400000) +#define GMT_D_800(x) ((x) & 0x00200000) +/* #define GMT_ ? ((x) & 0x00100000) */ +/* #define GMT_ ? ((x) & 0x00080000) */ +#define GMT_DR_OPEN(x) ((x) & 0x00040000) /* Door open (no tape). */ +/* #define GMT_ ? ((x) & 0x00020000) */ +#define GMT_IM_REP_EN(x) ((x) & 0x00010000) /* Immediate report mode.*/ +/* 16 generic status bits unused. */ + + +/* SCSI-tape specific definitions. Bitfield shifts in the status */ +#define MT_ST_BLKSIZE_SHIFT 0 +#define MT_ST_BLKSIZE_MASK 0xffffff +#define MT_ST_DENSITY_SHIFT 24 +#define MT_ST_DENSITY_MASK 0xff000000 + +#define MT_ST_SOFTERR_SHIFT 0 +#define MT_ST_SOFTERR_MASK 0xffff + +/* Bitfields for the MTSETDRVBUFFER ioctl. */ +#define MT_ST_OPTIONS 0xf0000000 +#define MT_ST_BOOLEANS 0x10000000 +#define MT_ST_SETBOOLEANS 0x30000000 +#define MT_ST_CLEARBOOLEANS 0x40000000 +#define MT_ST_WRITE_THRESHOLD 0x20000000 +#define MT_ST_DEF_BLKSIZE 0x50000000 +#define MT_ST_DEF_OPTIONS 0x60000000 + +#define MT_ST_BUFFER_WRITES 0x1 +#define MT_ST_ASYNC_WRITES 0x2 +#define MT_ST_READ_AHEAD 0x4 +#define MT_ST_DEBUGGING 0x8 +#define MT_ST_TWO_FM 0x10 +#define MT_ST_FAST_MTEOM 0x20 +#define MT_ST_AUTO_LOCK 0x40 +#define MT_ST_DEF_WRITES 0x80 +#define MT_ST_CAN_BSR 0x100 +#define MT_ST_NO_BLKLIMS 0x200 +#define MT_ST_CAN_PARTITIONS 0x400 +#define MT_ST_SCSI2LOGICAL 0x800 + +/* The mode parameters to be controlled. Parameter chosen with bits 20-28. */ +#define MT_ST_CLEAR_DEFAULT 0xfffff +#define MT_ST_DEF_DENSITY (MT_ST_DEF_OPTIONS | 0x100000) +#define MT_ST_DEF_COMPRESSION (MT_ST_DEF_OPTIONS | 0x200000) +#define MT_ST_DEF_DRVBUFFER (MT_ST_DEF_OPTIONS | 0x300000) + +/* The offset for the arguments for the special HP changer load command. */ +#define MT_ST_HPLOADER_OFFSET 10000 + + +/* Specify default tape device. */ +#ifndef DEFTAPE +# define DEFTAPE "/dev/tape" +#endif + +#endif /* mtio.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/param.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/param.h new file mode 100644 index 00000000..19c119a2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/param.h @@ -0,0 +1,82 @@ +/* Copyright (C) 1995-1997,2000,2001,2003,2008 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_PARAM_H +#define _SYS_PARAM_H 1 + +#ifndef ARG_MAX +# define __undef_ARG_MAX +#endif + +#include +#include +#include + +/* The kernel headers defines ARG_MAX. The value is wrong, though. */ +#ifndef __undef_ARG_MAX +# undef ARG_MAX +# undef __undef_ARG_MAX +#endif + +/* BSD names for some values. */ + +#define NBBY CHAR_BIT +#ifndef NGROUPS +# define NGROUPS NGROUPS_MAX +#endif +#define MAXSYMLINKS 20 +#define CANBSIZ MAX_CANON +#define MAXPATHLEN PATH_MAX +/* The following are not really correct but it is a value we used for a + long time and which seems to be usable. People should not use NOFILE + and NCARGS anyway. */ +#define NOFILE 256 +#define NCARGS 131072 + + +#include + +/* Bit map related macros. */ +#define setbit(a,i) ((a)[(i)/NBBY] |= 1<<((i)%NBBY)) +#define clrbit(a,i) ((a)[(i)/NBBY] &= ~(1<<((i)%NBBY))) +#define isset(a,i) ((a)[(i)/NBBY] & (1<<((i)%NBBY))) +#define isclr(a,i) (((a)[(i)/NBBY] & (1<<((i)%NBBY))) == 0) + +/* Macros for counting and rounding. */ +#ifndef howmany +# define howmany(x, y) (((x) + ((y) - 1)) / (y)) +#endif +#ifdef __GNUC__ +# define roundup(x, y) (__builtin_constant_p (y) && powerof2 (y) \ + ? (((x) + (y) - 1) & ~((y) - 1)) \ + : ((((x) + ((y) - 1)) / (y)) * (y))) +#else +# define roundup(x, y) ((((x) + ((y) - 1)) / (y)) * (y)) +#endif +#define powerof2(x) ((((x) - 1) & (x)) == 0) + +/* Macros for min/max. */ +#define MIN(a,b) (((a)<(b))?(a):(b)) +#define MAX(a,b) (((a)>(b))?(a):(b)) + + +/* Unit of `st_blocks'. */ +#define DEV_BSIZE 512 + + +#endif /* sys/param.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/personality.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/personality.h new file mode 100644 index 00000000..154b1131 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/personality.h @@ -0,0 +1,73 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Taken verbatim from Linux 2.4 (include/linux/personality.h). */ + +#ifndef _SYS_PERSONALITY_H +#define _SYS_PERSONALITY_H 1 + +#include + +/* Flags for bug emulation. + These occupy the top three bytes. */ +enum + { + MMAP_PAGE_ZERO = 0x0100000, + ADDR_LIMIT_32BIT = 0x0800000, + SHORT_INODE = 0x1000000, + WHOLE_SECONDS = 0x2000000, + STICKY_TIMEOUTS = 0x4000000, + }; + +/* Personality types. + + These go in the low byte. Avoid using the top bit, it will + conflict with error returns. */ +enum + { + PER_LINUX = 0x0000, + PER_LINUX_32BIT = 0x0000 | ADDR_LIMIT_32BIT, + PER_SVR4 = 0x0001 | STICKY_TIMEOUTS | MMAP_PAGE_ZERO, + PER_SVR3 = 0x0002 | STICKY_TIMEOUTS | SHORT_INODE, + PER_SCOSVR3 = 0x0003 | STICKY_TIMEOUTS | WHOLE_SECONDS | SHORT_INODE, + PER_OSR5 = 0x0003 | STICKY_TIMEOUTS | WHOLE_SECONDS, + PER_WYSEV386 = 0x0004 | STICKY_TIMEOUTS | SHORT_INODE, + PER_ISCR4 = 0x0005 | STICKY_TIMEOUTS, + PER_BSD = 0x0006, + PER_SUNOS = 0x0006 | STICKY_TIMEOUTS, + PER_XENIX = 0x0007 | STICKY_TIMEOUTS | SHORT_INODE, + PER_LINUX32 = 0x0008, + PER_IRIX32 = 0x0009 | STICKY_TIMEOUTS, /* IRIX5 32-bit */ + PER_IRIXN32 = 0x000a | STICKY_TIMEOUTS, /* IRIX6 new 32-bit */ + PER_IRIX64 = 0x000b | STICKY_TIMEOUTS, /* IRIX6 64-bit */ + PER_RISCOS = 0x000c, + PER_SOLARIS = 0x000d | STICKY_TIMEOUTS, + PER_UW7 = 0x000e | STICKY_TIMEOUTS | MMAP_PAGE_ZERO, + PER_HPUX = 0x000f, + PER_OSF4 = 0x0010, + PER_MASK = 0x00ff, + }; + +__BEGIN_DECLS + +/* Set different ABIs (personalities). */ +extern int personality (unsigned long int __persona) __THROW; + +__END_DECLS + +#endif /* sys/personality.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/poll.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/poll.h new file mode 100644 index 00000000..53ba6e2e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/poll.h @@ -0,0 +1,76 @@ +/* Compatibility definitions for System V `poll' interface. + Copyright (C) 1994,1996-2001,2004,2005,2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_POLL_H +#define _SYS_POLL_H 1 + +#include + +/* Get the platform dependent bits of `poll'. */ +#include +#ifdef __USE_GNU +/* Get the __sigset_t definition. */ +# include +/* Get the timespec definition. */ +# define __need_timespec +# include +#endif + + +/* Type used for the number of file descriptors. */ +typedef unsigned long int nfds_t; + +/* Data structure describing a polling request. */ +struct pollfd + { + int fd; /* File descriptor to poll. */ + short int events; /* Types of events poller cares about. */ + short int revents; /* Types of events that actually occurred. */ + }; + + +__BEGIN_DECLS + +/* Poll the file descriptors described by the NFDS structures starting at + FDS. If TIMEOUT is nonzero and not -1, allow TIMEOUT milliseconds for + an event to occur; if TIMEOUT is -1, block until an event occurs. + Returns the number of file descriptors with events, zero if timed out, + or -1 for errors. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern int poll (struct pollfd *__fds, nfds_t __nfds, int __timeout); +libc_hidden_proto(poll) + +#if defined __USE_GNU && defined __UCLIBC_LINUX_SPECIFIC__ +/* Like poll, but before waiting the threads signal mask is replaced + with that specified in the fourth parameter. For better usability, + the timeout value is specified using a TIMESPEC object. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern int ppoll (struct pollfd *__fds, nfds_t __nfds, + __const struct timespec *__timeout, + __const __sigset_t *__ss); +libc_hidden_proto(ppoll) +#endif + +__END_DECLS + +#endif /* sys/poll.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/queue.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/queue.h new file mode 100644 index 00000000..0ea0c11f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/queue.h @@ -0,0 +1,618 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)queue.h 8.5 (Berkeley) 8/20/94 + * $FreeBSD: src/sys/sys/queue.h,v 1.68 2006/10/24 11:20:29 ru Exp $ + */ + +#ifndef _SYS_QUEUE_H_ +#define _SYS_QUEUE_H_ + +#include + +/* + * This file defines four types of data structures: singly-linked lists, + * singly-linked tail queues, lists and tail queues. + * + * A singly-linked list is headed by a single forward pointer. The elements + * are singly linked for minimum space and pointer manipulation overhead at + * the expense of O(n) removal for arbitrary elements. New elements can be + * added to the list after an existing element or at the head of the list. + * Elements being removed from the head of the list should use the explicit + * macro for this purpose for optimum efficiency. A singly-linked list may + * only be traversed in the forward direction. Singly-linked lists are ideal + * for applications with large datasets and few or no removals or for + * implementing a LIFO queue. + * + * A singly-linked tail queue is headed by a pair of pointers, one to the + * head of the list and the other to the tail of the list. The elements are + * singly linked for minimum space and pointer manipulation overhead at the + * expense of O(n) removal for arbitrary elements. New elements can be added + * to the list after an existing element, at the head of the list, or at the + * end of the list. Elements being removed from the head of the tail queue + * should use the explicit macro for this purpose for optimum efficiency. + * A singly-linked tail queue may only be traversed in the forward direction. + * Singly-linked tail queues are ideal for applications with large datasets + * and few or no removals or for implementing a FIFO queue. + * + * A list is headed by a single forward pointer (or an array of forward + * pointers for a hash table header). The elements are doubly linked + * so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before + * or after an existing element or at the head of the list. A list + * may only be traversed in the forward direction. + * + * A tail queue is headed by a pair of pointers, one to the head of the + * list and the other to the tail of the list. The elements are doubly + * linked so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before or + * after an existing element, at the head of the list, or at the end of + * the list. A tail queue may be traversed in either direction. + * + * For details on the use of these macros, see the queue(3) manual page. + * + * + * SLIST LIST STAILQ TAILQ + * _HEAD + + + + + * _HEAD_INITIALIZER + + + + + * _ENTRY + + + + + * _INIT + + + + + * _EMPTY + + + + + * _FIRST + + + + + * _NEXT + + + + + * _PREV - - - + + * _LAST - - + + + * _FOREACH + + + + + * _FOREACH_SAFE + + + + + * _FOREACH_REVERSE - - - + + * _FOREACH_REVERSE_SAFE - - - + + * _INSERT_HEAD + + + + + * _INSERT_BEFORE - + - + + * _INSERT_AFTER + + + + + * _INSERT_TAIL - - + + + * _CONCAT - - + + + * _REMOVE_HEAD + - + - + * _REMOVE + + + + + * + */ +#ifdef QUEUE_MACRO_DEBUG +/* Store the last 2 places the queue element or head was altered */ +struct qm_trace { + char * lastfile; + int lastline; + char * prevfile; + int prevline; +}; + +#define TRACEBUF struct qm_trace trace; +#define TRASHIT(x) do {(x) = (void *)-1;} while (0) + +#define QMD_TRACE_HEAD(head) do { \ + (head)->trace.prevline = (head)->trace.lastline; \ + (head)->trace.prevfile = (head)->trace.lastfile; \ + (head)->trace.lastline = __LINE__; \ + (head)->trace.lastfile = __FILE__; \ +} while (0) + +#define QMD_TRACE_ELEM(elem) do { \ + (elem)->trace.prevline = (elem)->trace.lastline; \ + (elem)->trace.prevfile = (elem)->trace.lastfile; \ + (elem)->trace.lastline = __LINE__; \ + (elem)->trace.lastfile = __FILE__; \ +} while (0) + +#else +#define QMD_TRACE_ELEM(elem) +#define QMD_TRACE_HEAD(head) +#define TRACEBUF +#define TRASHIT(x) +#endif /* QUEUE_MACRO_DEBUG */ + +/* + * Singly-linked List declarations. + */ +#define SLIST_HEAD(name, type) \ +struct name { \ + struct type *slh_first; /* first element */ \ +} + +#define SLIST_HEAD_INITIALIZER(head) \ + { NULL } + +#define SLIST_ENTRY(type) \ +struct { \ + struct type *sle_next; /* next element */ \ +} + +/* + * Singly-linked List functions. + */ +#define SLIST_EMPTY(head) ((head)->slh_first == NULL) + +#define SLIST_FIRST(head) ((head)->slh_first) + +#define SLIST_FOREACH(var, head, field) \ + for ((var) = SLIST_FIRST((head)); \ + (var); \ + (var) = SLIST_NEXT((var), field)) + +#define SLIST_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = SLIST_FIRST((head)); \ + (var) && ((tvar) = SLIST_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define SLIST_FOREACH_PREVPTR(var, varp, head, field) \ + for ((varp) = &SLIST_FIRST((head)); \ + ((var) = *(varp)) != NULL; \ + (varp) = &SLIST_NEXT((var), field)) + +#define SLIST_INIT(head) do { \ + SLIST_FIRST((head)) = NULL; \ +} while (0) + +#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \ + SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field); \ + SLIST_NEXT((slistelm), field) = (elm); \ +} while (0) + +#define SLIST_INSERT_HEAD(head, elm, field) do { \ + SLIST_NEXT((elm), field) = SLIST_FIRST((head)); \ + SLIST_FIRST((head)) = (elm); \ +} while (0) + +#define SLIST_NEXT(elm, field) ((elm)->field.sle_next) + +#define SLIST_REMOVE(head, elm, type, field) do { \ + if (SLIST_FIRST((head)) == (elm)) { \ + SLIST_REMOVE_HEAD((head), field); \ + } \ + else { \ + struct type *curelm = SLIST_FIRST((head)); \ + while (SLIST_NEXT(curelm, field) != (elm)) \ + curelm = SLIST_NEXT(curelm, field); \ + SLIST_NEXT(curelm, field) = \ + SLIST_NEXT(SLIST_NEXT(curelm, field), field); \ + } \ + TRASHIT((elm)->field.sle_next); \ +} while (0) + +#define SLIST_REMOVE_HEAD(head, field) do { \ + SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field); \ +} while (0) + +/* + * Singly-linked Tail queue declarations. + */ +#define STAILQ_HEAD(name, type) \ +struct name { \ + struct type *stqh_first;/* first element */ \ + struct type **stqh_last;/* addr of last next element */ \ +} + +#define STAILQ_HEAD_INITIALIZER(head) \ + { NULL, &(head).stqh_first } + +#define STAILQ_ENTRY(type) \ +struct { \ + struct type *stqe_next; /* next element */ \ +} + +/* + * Singly-linked Tail queue functions. + */ +#define STAILQ_CONCAT(head1, head2) do { \ + if (!STAILQ_EMPTY((head2))) { \ + *(head1)->stqh_last = (head2)->stqh_first; \ + (head1)->stqh_last = (head2)->stqh_last; \ + STAILQ_INIT((head2)); \ + } \ +} while (0) + +#define STAILQ_EMPTY(head) ((head)->stqh_first == NULL) + +#define STAILQ_FIRST(head) ((head)->stqh_first) + +#define STAILQ_FOREACH(var, head, field) \ + for((var) = STAILQ_FIRST((head)); \ + (var); \ + (var) = STAILQ_NEXT((var), field)) + + +#define STAILQ_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = STAILQ_FIRST((head)); \ + (var) && ((tvar) = STAILQ_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define STAILQ_INIT(head) do { \ + STAILQ_FIRST((head)) = NULL; \ + (head)->stqh_last = &STAILQ_FIRST((head)); \ +} while (0) + +#define STAILQ_INSERT_AFTER(head, tqelm, elm, field) do { \ + if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field)) == NULL)\ + (head)->stqh_last = &STAILQ_NEXT((elm), field); \ + STAILQ_NEXT((tqelm), field) = (elm); \ +} while (0) + +#define STAILQ_INSERT_HEAD(head, elm, field) do { \ + if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL) \ + (head)->stqh_last = &STAILQ_NEXT((elm), field); \ + STAILQ_FIRST((head)) = (elm); \ +} while (0) + +#define STAILQ_INSERT_TAIL(head, elm, field) do { \ + STAILQ_NEXT((elm), field) = NULL; \ + *(head)->stqh_last = (elm); \ + (head)->stqh_last = &STAILQ_NEXT((elm), field); \ +} while (0) + +#define STAILQ_LAST(head, type, field) \ + (STAILQ_EMPTY((head)) ? \ + NULL : \ + ((struct type *)(void *) \ + ((char *)((head)->stqh_last) - __offsetof(struct type, field)))) + +#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next) + +#define STAILQ_REMOVE(head, elm, type, field) do { \ + if (STAILQ_FIRST((head)) == (elm)) { \ + STAILQ_REMOVE_HEAD((head), field); \ + } \ + else { \ + struct type *curelm = STAILQ_FIRST((head)); \ + while (STAILQ_NEXT(curelm, field) != (elm)) \ + curelm = STAILQ_NEXT(curelm, field); \ + if ((STAILQ_NEXT(curelm, field) = \ + STAILQ_NEXT(STAILQ_NEXT(curelm, field), field)) == NULL)\ + (head)->stqh_last = &STAILQ_NEXT((curelm), field);\ + } \ + TRASHIT((elm)->field.stqe_next); \ +} while (0) + +#define STAILQ_REMOVE_HEAD(head, field) do { \ + if ((STAILQ_FIRST((head)) = \ + STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL) \ + (head)->stqh_last = &STAILQ_FIRST((head)); \ +} while (0) + +/* + * List declarations. + */ +#define LIST_HEAD(name, type) \ +struct name { \ + struct type *lh_first; /* first element */ \ +} + +#define LIST_HEAD_INITIALIZER(head) \ + { NULL } + +#define LIST_ENTRY(type) \ +struct { \ + struct type *le_next; /* next element */ \ + struct type **le_prev; /* address of previous next element */ \ +} + +/* + * List functions. + */ + +#if (defined(_KERNEL) && defined(INVARIANTS)) +#define QMD_LIST_CHECK_HEAD(head, field) do { \ + if (LIST_FIRST((head)) != NULL && \ + LIST_FIRST((head))->field.le_prev != \ + &LIST_FIRST((head))) \ + panic("Bad list head %p first->prev != head", (head)); \ +} while (0) + +#define QMD_LIST_CHECK_NEXT(elm, field) do { \ + if (LIST_NEXT((elm), field) != NULL && \ + LIST_NEXT((elm), field)->field.le_prev != \ + &((elm)->field.le_next)) \ + panic("Bad link elm %p next->prev != elm", (elm)); \ +} while (0) + +#define QMD_LIST_CHECK_PREV(elm, field) do { \ + if (*(elm)->field.le_prev != (elm)) \ + panic("Bad link elm %p prev->next != elm", (elm)); \ +} while (0) +#else +#define QMD_LIST_CHECK_HEAD(head, field) +#define QMD_LIST_CHECK_NEXT(elm, field) +#define QMD_LIST_CHECK_PREV(elm, field) +#endif /* (_KERNEL && INVARIANTS) */ + +#define LIST_EMPTY(head) ((head)->lh_first == NULL) + +#define LIST_FIRST(head) ((head)->lh_first) + +#define LIST_FOREACH(var, head, field) \ + for ((var) = LIST_FIRST((head)); \ + (var); \ + (var) = LIST_NEXT((var), field)) + +#define LIST_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = LIST_FIRST((head)); \ + (var) && ((tvar) = LIST_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define LIST_INIT(head) do { \ + LIST_FIRST((head)) = NULL; \ +} while (0) + +#define LIST_INSERT_AFTER(listelm, elm, field) do { \ + QMD_LIST_CHECK_NEXT(listelm, field); \ + if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL)\ + LIST_NEXT((listelm), field)->field.le_prev = \ + &LIST_NEXT((elm), field); \ + LIST_NEXT((listelm), field) = (elm); \ + (elm)->field.le_prev = &LIST_NEXT((listelm), field); \ +} while (0) + +#define LIST_INSERT_BEFORE(listelm, elm, field) do { \ + QMD_LIST_CHECK_PREV(listelm, field); \ + (elm)->field.le_prev = (listelm)->field.le_prev; \ + LIST_NEXT((elm), field) = (listelm); \ + *(listelm)->field.le_prev = (elm); \ + (listelm)->field.le_prev = &LIST_NEXT((elm), field); \ +} while (0) + +#define LIST_INSERT_HEAD(head, elm, field) do { \ + QMD_LIST_CHECK_HEAD((head), field); \ + if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL) \ + LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field);\ + LIST_FIRST((head)) = (elm); \ + (elm)->field.le_prev = &LIST_FIRST((head)); \ +} while (0) + +#define LIST_NEXT(elm, field) ((elm)->field.le_next) + +#define LIST_REMOVE(elm, field) do { \ + QMD_LIST_CHECK_NEXT(elm, field); \ + QMD_LIST_CHECK_PREV(elm, field); \ + if (LIST_NEXT((elm), field) != NULL) \ + LIST_NEXT((elm), field)->field.le_prev = \ + (elm)->field.le_prev; \ + *(elm)->field.le_prev = LIST_NEXT((elm), field); \ + TRASHIT((elm)->field.le_next); \ + TRASHIT((elm)->field.le_prev); \ +} while (0) + +/* + * Tail queue declarations. + */ +#define TAILQ_HEAD(name, type) \ +struct name { \ + struct type *tqh_first; /* first element */ \ + struct type **tqh_last; /* addr of last next element */ \ + TRACEBUF \ +} + +#define TAILQ_HEAD_INITIALIZER(head) \ + { NULL, &(head).tqh_first } + +#define TAILQ_ENTRY(type) \ +struct { \ + struct type *tqe_next; /* next element */ \ + struct type **tqe_prev; /* address of previous next element */ \ + TRACEBUF \ +} + +/* + * Tail queue functions. + */ +#if (defined(_KERNEL) && defined(INVARIANTS)) +#define QMD_TAILQ_CHECK_HEAD(head, field) do { \ + if (!TAILQ_EMPTY(head) && \ + TAILQ_FIRST((head))->field.tqe_prev != \ + &TAILQ_FIRST((head))) \ + panic("Bad tailq head %p first->prev != head", (head)); \ +} while (0) + +#define QMD_TAILQ_CHECK_TAIL(head, field) do { \ + if (*(head)->tqh_last != NULL) \ + panic("Bad tailq NEXT(%p->tqh_last) != NULL", (head)); \ +} while (0) + +#define QMD_TAILQ_CHECK_NEXT(elm, field) do { \ + if (TAILQ_NEXT((elm), field) != NULL && \ + TAILQ_NEXT((elm), field)->field.tqe_prev != \ + &((elm)->field.tqe_next)) \ + panic("Bad link elm %p next->prev != elm", (elm)); \ +} while (0) + +#define QMD_TAILQ_CHECK_PREV(elm, field) do { \ + if (*(elm)->field.tqe_prev != (elm)) \ + panic("Bad link elm %p prev->next != elm", (elm)); \ +} while (0) +#else +#define QMD_TAILQ_CHECK_HEAD(head, field) +#define QMD_TAILQ_CHECK_TAIL(head, headname) +#define QMD_TAILQ_CHECK_NEXT(elm, field) +#define QMD_TAILQ_CHECK_PREV(elm, field) +#endif /* (_KERNEL && INVARIANTS) */ + +#define TAILQ_CONCAT(head1, head2, field) do { \ + if (!TAILQ_EMPTY(head2)) { \ + *(head1)->tqh_last = (head2)->tqh_first; \ + (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \ + (head1)->tqh_last = (head2)->tqh_last; \ + TAILQ_INIT((head2)); \ + QMD_TRACE_HEAD(head1); \ + QMD_TRACE_HEAD(head2); \ + } \ +} while (0) + +#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL) + +#define TAILQ_FIRST(head) ((head)->tqh_first) + +#define TAILQ_FOREACH(var, head, field) \ + for ((var) = TAILQ_FIRST((head)); \ + (var); \ + (var) = TAILQ_NEXT((var), field)) + +#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = TAILQ_FIRST((head)); \ + (var) && ((tvar) = TAILQ_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \ + for ((var) = TAILQ_LAST((head), headname); \ + (var); \ + (var) = TAILQ_PREV((var), headname, field)) + +#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \ + for ((var) = TAILQ_LAST((head), headname); \ + (var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \ + (var) = (tvar)) + +#define TAILQ_INIT(head) do { \ + TAILQ_FIRST((head)) = NULL; \ + (head)->tqh_last = &TAILQ_FIRST((head)); \ + QMD_TRACE_HEAD(head); \ +} while (0) + +#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ + QMD_TAILQ_CHECK_NEXT(listelm, field); \ + if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL)\ + TAILQ_NEXT((elm), field)->field.tqe_prev = \ + &TAILQ_NEXT((elm), field); \ + else { \ + (head)->tqh_last = &TAILQ_NEXT((elm), field); \ + QMD_TRACE_HEAD(head); \ + } \ + TAILQ_NEXT((listelm), field) = (elm); \ + (elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field); \ + QMD_TRACE_ELEM(&(elm)->field); \ + QMD_TRACE_ELEM(&listelm->field); \ +} while (0) + +#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ + QMD_TAILQ_CHECK_PREV(listelm, field); \ + (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ + TAILQ_NEXT((elm), field) = (listelm); \ + *(listelm)->field.tqe_prev = (elm); \ + (listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field); \ + QMD_TRACE_ELEM(&(elm)->field); \ + QMD_TRACE_ELEM(&listelm->field); \ +} while (0) + +#define TAILQ_INSERT_HEAD(head, elm, field) do { \ + QMD_TAILQ_CHECK_HEAD(head, field); \ + if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL) \ + TAILQ_FIRST((head))->field.tqe_prev = \ + &TAILQ_NEXT((elm), field); \ + else \ + (head)->tqh_last = &TAILQ_NEXT((elm), field); \ + TAILQ_FIRST((head)) = (elm); \ + (elm)->field.tqe_prev = &TAILQ_FIRST((head)); \ + QMD_TRACE_HEAD(head); \ + QMD_TRACE_ELEM(&(elm)->field); \ +} while (0) + +#define TAILQ_INSERT_TAIL(head, elm, field) do { \ + QMD_TAILQ_CHECK_TAIL(head, field); \ + TAILQ_NEXT((elm), field) = NULL; \ + (elm)->field.tqe_prev = (head)->tqh_last; \ + *(head)->tqh_last = (elm); \ + (head)->tqh_last = &TAILQ_NEXT((elm), field); \ + QMD_TRACE_HEAD(head); \ + QMD_TRACE_ELEM(&(elm)->field); \ +} while (0) + +#define TAILQ_LAST(head, headname) \ + (*(((struct headname *)((head)->tqh_last))->tqh_last)) + +#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) + +#define TAILQ_PREV(elm, headname, field) \ + (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) + +#define TAILQ_REMOVE(head, elm, field) do { \ + QMD_TAILQ_CHECK_NEXT(elm, field); \ + QMD_TAILQ_CHECK_PREV(elm, field); \ + if ((TAILQ_NEXT((elm), field)) != NULL) \ + TAILQ_NEXT((elm), field)->field.tqe_prev = \ + (elm)->field.tqe_prev; \ + else { \ + (head)->tqh_last = (elm)->field.tqe_prev; \ + QMD_TRACE_HEAD(head); \ + } \ + *(elm)->field.tqe_prev = TAILQ_NEXT((elm), field); \ + TRASHIT((elm)->field.tqe_next); \ + TRASHIT((elm)->field.tqe_prev); \ + QMD_TRACE_ELEM(&(elm)->field); \ +} while (0) + + +#ifdef _KERNEL + +/* + * XXX insque() and remque() are an old way of handling certain queues. + * They bogusly assumes that all queue heads look alike. + */ + +struct quehead { + struct quehead *qh_link; + struct quehead *qh_rlink; +}; + +#ifdef __CC_SUPPORTS___INLINE + +static __inline void +insque(void *a, void *b) +{ + struct quehead *element = (struct quehead *)a, + *head = (struct quehead *)b; + + element->qh_link = head->qh_link; + element->qh_rlink = head; + head->qh_link = element; + element->qh_link->qh_rlink = element; +} + +static __inline void +remque(void *a) +{ + struct quehead *element = (struct quehead *)a; + + element->qh_link->qh_rlink = element->qh_rlink; + element->qh_rlink->qh_link = element->qh_link; + element->qh_rlink = 0; +} + +#else /* !__CC_SUPPORTS___INLINE */ + +void insque(void *a, void *b); +void remque(void *a); + +#endif /* __CC_SUPPORTS___INLINE */ + +#endif /* _KERNEL */ + +#endif /* !_SYS_QUEUE_H_ */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/quota.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/quota.h new file mode 100644 index 00000000..a6afdbe4 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/quota.h @@ -0,0 +1,158 @@ +/* This just represents the non-kernel parts of . + * + * here's the corresponding copyright: + * Copyright (c) 1982, 1986 Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Robert Elz at The University of Melbourne. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Version: $Id: quota.h,v 1.1 2002/01/03 04:00:09 andersen Exp $ + */ + +#ifndef _SYS_QUOTA_H +#define _SYS_QUOTA_H 1 + +#include +#include + +/* + * Convert diskblocks to blocks and the other way around. + * currently only to fool the BSD source. :-) + */ +#define dbtob(num) ((num) << 10) +#define btodb(num) ((num) >> 10) + +/* + * Convert count of filesystem blocks to diskquota blocks, meant + * for filesystems where i_blksize != BLOCK_SIZE + */ +#define fs_to_dq_blocks(num, blksize) (((num) * (blksize)) / BLOCK_SIZE) + +/* + * Definitions for disk quotas imposed on the average user + * (big brother finally hits Linux). + * + * The following constants define the amount of time given a user + * before the soft limits are treated as hard limits (usually resulting + * in an allocation failure). The timer is started when the user crosses + * their soft limit, it is reset when they go below their soft limit. + */ +#define MAX_IQ_TIME 604800 /* (7*24*60*60) 1 week */ +#define MAX_DQ_TIME 604800 /* (7*24*60*60) 1 week */ + +#define MAXQUOTAS 2 +#define USRQUOTA 0 /* element used for user quotas */ +#define GRPQUOTA 1 /* element used for group quotas */ + +/* + * Definitions for the default names of the quotas files. + */ +#define INITQFNAMES { \ + "user", /* USRQUOTA */ \ + "group", /* GRPQUOTA */ \ + "undefined", \ +}; + +#define QUOTAFILENAME "quota" +#define QUOTAGROUP "staff" + +#define NR_DQHASH 43 /* Just an arbitrary number any suggestions ? */ +#define NR_DQUOTS 256 /* Number of quotas active at one time */ + +/* + * Command definitions for the 'quotactl' system call. + * The commands are broken into a main command defined below + * and a subcommand that is used to convey the type of + * quota that is being manipulated (see above). + */ +#define SUBCMDMASK 0x00ff +#define SUBCMDSHIFT 8 +#define QCMD(cmd, type) (((cmd) << SUBCMDSHIFT) | ((type) & SUBCMDMASK)) + +#define Q_QUOTAON 0x0100 /* enable quotas */ +#define Q_QUOTAOFF 0x0200 /* disable quotas */ +#define Q_GETQUOTA 0x0300 /* get limits and usage */ +#define Q_SETQUOTA 0x0400 /* set limits and usage */ +#define Q_SETUSE 0x0500 /* set usage */ +#define Q_SYNC 0x0600 /* sync disk copy of a filesystems quotas */ +#define Q_SETQLIM 0x0700 /* set limits */ +#define Q_GETSTATS 0x0800 /* get collected stats */ +#define Q_RSQUASH 0x1000 /* set root_squash option */ + +/* + * The following structure defines the format of the disk quota file + * (as it appears on disk) - the file is an array of these structures + * indexed by user or group number. + */ +struct dqblk + { + u_int32_t dqb_bhardlimit; /* absolute limit on disk blks alloc */ + u_int32_t dqb_bsoftlimit; /* preferred limit on disk blks */ + u_int32_t dqb_curblocks; /* current block count */ + u_int32_t dqb_ihardlimit; /* maximum # allocated inodes */ + u_int32_t dqb_isoftlimit; /* preferred inode limit */ + u_int32_t dqb_curinodes; /* current # allocated inodes */ + time_t dqb_btime; /* time limit for excessive disk use */ + time_t dqb_itime; /* time limit for excessive files */ + }; + +/* + * Shorthand notation. + */ +#define dq_bhardlimit dq_dqb.dqb_bhardlimit +#define dq_bsoftlimit dq_dqb.dqb_bsoftlimit +#define dq_curblocks dq_dqb.dqb_curblocks +#define dq_ihardlimit dq_dqb.dqb_ihardlimit +#define dq_isoftlimit dq_dqb.dqb_isoftlimit +#define dq_curinodes dq_dqb.dqb_curinodes +#define dq_btime dq_dqb.dqb_btime +#define dq_itime dq_dqb.dqb_itime + +#define dqoff(UID) ((loff_t)((UID) * sizeof (struct dqblk))) + +struct dqstats + { + u_int32_t lookups; + u_int32_t drops; + u_int32_t reads; + u_int32_t writes; + u_int32_t cache_hits; + u_int32_t pages_allocated; + u_int32_t allocated_dquots; + u_int32_t free_dquots; + u_int32_t syncs; + }; + +__BEGIN_DECLS + +extern int quotactl (int __cmd, const char *__special, int __id, + caddr_t __addr) __THROW; + +__END_DECLS + +#endif /* sys/quota.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/reboot.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/reboot.h new file mode 100644 index 00000000..2a719c7a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/reboot.h @@ -0,0 +1,49 @@ +/* Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This file should define RB_* macros to be used as flag + bits in the argument to the `reboot' system call. */ + +#ifndef _SYS_REBOOT_H +#define _SYS_REBOOT_H 1 + +#include + +/* Perform a hard reset now. */ +#define RB_AUTOBOOT 0x01234567 + +/* Halt the system. */ +#define RB_HALT_SYSTEM 0xcdef0123 + +/* Enable reboot using Ctrl-Alt-Delete keystroke. */ +#define RB_ENABLE_CAD 0x89abcdef + +/* Disable reboot using Ctrl-Alt-Delete keystroke. */ +#define RB_DISABLE_CAD 0 + +/* Stop system and switch power off if possible. */ +#define RB_POWER_OFF 0x4321fedc + +__BEGIN_DECLS + +/* Reboot or halt the system. */ +extern int reboot (int __howto) __THROW; + +__END_DECLS + +#endif /* _SYS_REBOOT_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/resource.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/resource.h new file mode 100644 index 00000000..c7b8e0e4 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/resource.h @@ -0,0 +1,107 @@ +/* Copyright (C) 1992,94,1996-2000,2002,2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_RESOURCE_H +#define _SYS_RESOURCE_H 1 + +#include + +/* Get the system-dependent definitions of structures and bit values. */ +#include + +#ifndef __id_t_defined +typedef __id_t id_t; +# define __id_t_defined +#endif + +__BEGIN_DECLS + +/* The X/Open standard defines that all the functions below must use + `int' as the type for the first argument. When we are compiling with + GNU extensions we change this slightly to provide better error + checking. */ +#if defined __USE_GNU && !defined __cplusplus +typedef enum __rlimit_resource __rlimit_resource_t; +typedef enum __rusage_who __rusage_who_t; +typedef enum __priority_which __priority_which_t; +#else +typedef int __rlimit_resource_t; +typedef int __rusage_who_t; +typedef int __priority_which_t; +#endif + +/* Put the soft and hard limits for RESOURCE in *RLIMITS. + Returns 0 if successful, -1 if not (and sets errno). */ +#ifndef __USE_FILE_OFFSET64 +extern int getrlimit (__rlimit_resource_t __resource, + struct rlimit *__rlimits) __THROW; +libc_hidden_proto(getrlimit) +#else +# ifdef __REDIRECT_NTH +extern int __REDIRECT_NTH (getrlimit, (__rlimit_resource_t __resource, + struct rlimit *__rlimits), getrlimit64); +# else +# define getrlimit getrlimit64 +# endif +#endif +#ifdef __USE_LARGEFILE64 +extern int getrlimit64 (__rlimit_resource_t __resource, + struct rlimit64 *__rlimits) __THROW; +#endif + +/* Set the soft and hard limits for RESOURCE to *RLIMITS. + Only the super-user can increase hard limits. + Return 0 if successful, -1 if not (and sets errno). */ +#ifndef __USE_FILE_OFFSET64 +extern int setrlimit (__rlimit_resource_t __resource, + __const struct rlimit *__rlimits) __THROW; +libc_hidden_proto(setrlimit) +#else +# ifdef __REDIRECT_NTH +extern int __REDIRECT_NTH (setrlimit, (__rlimit_resource_t __resource, + __const struct rlimit *__rlimits), + setrlimit64); +# else +# define setrlimit setrlimit64 +# endif +#endif +#ifdef __USE_LARGEFILE64 +extern int setrlimit64 (__rlimit_resource_t __resource, + __const struct rlimit64 *__rlimits) __THROW; +#endif + +/* Return resource usage information on process indicated by WHO + and put it in *USAGE. Returns 0 for success, -1 for failure. */ +extern int getrusage (__rusage_who_t __who, struct rusage *__usage) __THROW; + +/* Return the highest priority of any process specified by WHICH and WHO + (see above); if WHO is zero, the current process, process group, or user + (as specified by WHO) is used. A lower priority number means higher + priority. Priorities range from PRIO_MIN to PRIO_MAX (above). */ +extern int getpriority (__priority_which_t __which, id_t __who) __THROW; +libc_hidden_proto(getpriority) + +/* Set the priority of all processes specified by WHICH and WHO (see above) + to PRIO. Returns 0 on success, -1 on errors. */ +extern int setpriority (__priority_which_t __which, id_t __who, int __prio) + __THROW; +libc_hidden_proto(setpriority) + +__END_DECLS + +#endif /* sys/resource.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/select.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/select.h new file mode 100644 index 00000000..6ffe4e22 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/select.h @@ -0,0 +1,131 @@ +/* `fd_set' type and related macros, and `select'/`pselect' declarations. + Copyright (C) 1996,97,98,99,2000,01,02,2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* POSIX 1003.1g: 6.2 Select from File Descriptor Sets */ + +#ifndef _SYS_SELECT_H +#define _SYS_SELECT_H 1 + +#include + +/* Get definition of needed basic types. */ +#include + +/* Get __FD_* definitions. */ +#include + +/* Get __sigset_t. */ +#include + +#ifndef __sigset_t_defined +# define __sigset_t_defined +typedef __sigset_t sigset_t; +#endif + +/* Get definition of timer specification structures. */ +#define __need_time_t +#define __need_timespec +#include +#define __need_timeval +#include + +#ifndef __suseconds_t_defined +typedef __suseconds_t suseconds_t; +# define __suseconds_t_defined +#endif + + +/* The fd_set member is required to be an array of longs. */ +typedef long int __fd_mask; + +/* Some versions of define these macros. */ +#undef __NFDBITS +#undef __FDELT +#undef __FDMASK +/* It's easier to assume 8-bit bytes than to get CHAR_BIT. */ +#define __NFDBITS (8 * sizeof (__fd_mask)) +#define __FDELT(d) ((d) / __NFDBITS) +#define __FDMASK(d) ((__fd_mask) 1 << ((d) % __NFDBITS)) + +/* fd_set for select and pselect. */ +typedef struct + { + /* XPG4.2 requires this member name. Otherwise avoid the name + from the global namespace. */ +#ifdef __USE_XOPEN + __fd_mask fds_bits[__FD_SETSIZE / __NFDBITS]; +# define __FDS_BITS(set) ((set)->fds_bits) +#else + __fd_mask __fds_bits[__FD_SETSIZE / __NFDBITS]; +# define __FDS_BITS(set) ((set)->__fds_bits) +#endif + } fd_set; + +/* Maximum number of file descriptors in `fd_set'. */ +#define FD_SETSIZE __FD_SETSIZE + +#ifdef __USE_MISC +/* Sometimes the fd_set member is assumed to have this type. */ +typedef __fd_mask fd_mask; + +/* Number of bits per word of `fd_set' (some code assumes this is 32). */ +# define NFDBITS __NFDBITS +#endif + + +/* Access macros for `fd_set'. */ +#define FD_SET(fd, fdsetp) __FD_SET (fd, fdsetp) +#define FD_CLR(fd, fdsetp) __FD_CLR (fd, fdsetp) +#define FD_ISSET(fd, fdsetp) __FD_ISSET (fd, fdsetp) +#define FD_ZERO(fdsetp) __FD_ZERO (fdsetp) + + +__BEGIN_DECLS + +/* Check the first NFDS descriptors each in READFDS (if not NULL) for read + readiness, in WRITEFDS (if not NULL) for write readiness, and in EXCEPTFDS + (if not NULL) for exceptional conditions. If TIMEOUT is not NULL, time out + after waiting the interval specified therein. Returns the number of ready + descriptors, or -1 for errors. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern int select (int __nfds, fd_set *__restrict __readfds, + fd_set *__restrict __writefds, + fd_set *__restrict __exceptfds, + struct timeval *__restrict __timeout); +libc_hidden_proto(select) + +#ifdef __USE_XOPEN2K +/* Same as above only that the TIMEOUT value is given with higher + resolution and a sigmask which is been set temporarily. This version + should be used. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern int pselect (int __nfds, fd_set *__restrict __readfds, + fd_set *__restrict __writefds, + fd_set *__restrict __exceptfds, + const struct timespec *__restrict __timeout, + const __sigset_t *__restrict __sigmask); +#endif + +__END_DECLS + +#endif /* sys/select.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/sem.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/sem.h new file mode 100644 index 00000000..24a57fc3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/sem.h @@ -0,0 +1,69 @@ +/* Copyright (C) 1995-1999, 2000, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_SEM_H +#define _SYS_SEM_H 1 + +#include + +#define __need_size_t +#include + +/* Get common definition of System V style IPC. */ +#include + +/* Get system dependent definition of `struct semid_ds' and more. */ +#include + +#ifdef __USE_GNU +# define __need_timespec +# include +#endif + +/* The following System V style IPC functions implement a semaphore + handling. The definition is found in XPG2. */ + +/* Structure used for argument to `semop' to describe operations. */ +struct sembuf +{ + unsigned short int sem_num; /* semaphore number */ + short int sem_op; /* semaphore operation */ + short int sem_flg; /* operation flag */ +}; + + +__BEGIN_DECLS + +/* Semaphore control operation. */ +extern int semctl (int __semid, int __semnum, int __cmd, ...) __THROW; + +/* Get semaphore. */ +extern int semget (key_t __key, int __nsems, int __semflg) __THROW; + +/* Operate on semaphore. */ +extern int semop (int __semid, struct sembuf *__sops, size_t __nsops) __THROW; + +#ifdef __USE_GNU +/* Operate on semaphore with timeout. */ +extern int semtimedop (int __semid, struct sembuf *__sops, size_t __nsops, + __const struct timespec *__timeout) __THROW; +#endif + +__END_DECLS + +#endif /* sys/sem.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/sendfile.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/sendfile.h new file mode 100644 index 00000000..4c1367b6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/sendfile.h @@ -0,0 +1,52 @@ +/* sendfile -- copy data directly from one file descriptor to another + Copyright (C) 1998,99,01,2002,2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_SENDFILE_H +#define _SYS_SENDFILE_H 1 + +#include +#include + +__BEGIN_DECLS + +/* Send up to COUNT bytes from file associated with IN_FD starting at + *OFFSET to descriptor OUT_FD. Set *OFFSET to the IN_FD's file position + following the read bytes. If OFFSET is a null pointer, use the normal + file position instead. Return the number of written bytes, or -1 in + case of error. */ +#ifndef __USE_FILE_OFFSET64 +extern ssize_t sendfile (int __out_fd, int __in_fd, off_t *__offset, + size_t __count) __THROW; +#else +# ifdef __REDIRECT_NTH +extern ssize_t __REDIRECT_NTH (sendfile, + (int __out_fd, int __in_fd, __off64_t *__offset, + size_t __count), sendfile64); +# else +# define sendfile sendfile64 +# endif +#endif +#ifdef __USE_LARGEFILE64 +extern ssize_t sendfile64 (int __out_fd, int __in_fd, __off64_t *__offset, + size_t __count) __THROW; +#endif + +__END_DECLS + +#endif /* sys/sendfile.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/shm.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/shm.h new file mode 100644 index 00000000..786ce752 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/shm.h @@ -0,0 +1,65 @@ +/* Copyright (C) 1995-1999, 2000, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_SHM_H +#define _SYS_SHM_H 1 + +#include + +#define __need_size_t +#include + +/* Get common definition of System V style IPC. */ +#include + +/* Get system dependent definition of `struct shmid_ds' and more. */ +#include + +/* Define types required by the standard. */ +#define __need_time_t +#include + +#ifdef __USE_XOPEN +# ifndef __pid_t_defined +typedef __pid_t pid_t; +# define __pid_t_defined +# endif +#endif /* X/Open */ + + +__BEGIN_DECLS + +/* The following System V style IPC functions implement a shared memory + facility. The definition is found in XPG4.2. */ + +/* Shared memory control operation. */ +extern int shmctl (int __shmid, int __cmd, struct shmid_ds *__buf) __THROW; + +/* Get shared memory segment. */ +extern int shmget (key_t __key, size_t __size, int __shmflg) __THROW; + +/* Attach shared memory segment. */ +extern void *shmat (int __shmid, __const void *__shmaddr, int __shmflg) + __THROW; + +/* Detach shared memory segment. */ +extern int shmdt (__const void *__shmaddr) __THROW; + +__END_DECLS + +#endif /* sys/shm.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/signal.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/signal.h new file mode 100644 index 00000000..2e602dad --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/signal.h @@ -0,0 +1 @@ +#include diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/signalfd.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/signalfd.h new file mode 100644 index 00000000..8cee17c5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/signalfd.h @@ -0,0 +1,86 @@ +/* Copyright (C) 2007, 2008 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_SIGNALFD_H +#define _SYS_SIGNALFD_H 1 + +#define __need_sigset_t +#include +#include + + +struct signalfd_siginfo +{ + uint32_t ssi_signo; + int32_t ssi_errno; + int32_t ssi_code; + uint32_t ssi_pid; + uint32_t ssi_uid; + int32_t ssi_fd; + uint32_t ssi_tid; + uint32_t ssi_band; + uint32_t ssi_overrun; + uint32_t ssi_trapno; + int32_t ssi_status; + int32_t ssi_int; + uint64_t ssi_ptr; + uint64_t ssi_utime; + uint64_t ssi_stime; + uint64_t ssi_addr; + uint8_t __pad[48]; +}; + +/* Flags for signalfd. */ +#if defined __sparc__ || defined __sparc64__ +enum + { + SFD_CLOEXEC = 0x400000, +# define SFD_CLOEXEC SFD_CLOEXEC + SFD_NONBLOCK = 0x4000 +# define SFD_NONBLOCK SFD_NONBLOCK + }; + +#elif defined __alpha__ +enum + { + SFD_CLOEXEC = 010000000, +# define SFD_CLOEXEC SFD_CLOEXEC + SFD_NONBLOCK = 04 +# define SFD_NONBLOCK SFD_NONBLOCK + }; + +#else +enum + { + SFD_CLOEXEC = 02000000, +# define SFD_CLOEXEC SFD_CLOEXEC + SFD_NONBLOCK = 04000 +# define SFD_NONBLOCK SFD_NONBLOCK + }; +#endif + +__BEGIN_DECLS + +/* Request notification for delivery of signals in MASK to be + performed using descriptor FD.*/ +extern int signalfd (int __fd, const sigset_t *__mask, int __flags) + __nonnull ((2)) __THROW; + +__END_DECLS + +#endif /* sys/signalfd.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/socket.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/socket.h new file mode 100644 index 00000000..0824fc85 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/socket.h @@ -0,0 +1,254 @@ +/* Declarations of socket constants, types, and functions. + Copyright (C) 1991,92,1994-2001,2003,2005,2007,2008 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_SOCKET_H +#define _SYS_SOCKET_H 1 + +#include + +__BEGIN_DECLS + +#include +#define __need_size_t +#include +#ifdef __USE_GNU +/* Get the __sigset_t definition. */ +# include +#endif + + +/* This operating system-specific header file defines the SOCK_*, PF_*, + AF_*, MSG_*, SOL_*, and SO_* constants, and the `struct sockaddr', + `struct msghdr', and `struct linger' types. */ +#include + +#ifdef __USE_BSD +/* This is the 4.3 BSD `struct sockaddr' format, which is used as wire + format in the grotty old 4.3 `talk' protocol. */ +struct osockaddr + { + unsigned short int sa_family; + unsigned char sa_data[14]; + }; +#endif + +/* The following constants should be used for the second parameter of + `shutdown'. */ +enum +{ + SHUT_RD = 0, /* No more receptions. */ +#define SHUT_RD SHUT_RD + SHUT_WR, /* No more transmissions. */ +#define SHUT_WR SHUT_WR + SHUT_RDWR /* No more receptions or transmissions. */ +#define SHUT_RDWR SHUT_RDWR +}; + +/* This is the type we use for generic socket address arguments. + + With GCC 2.7 and later, the funky union causes redeclarations or + uses with any of the listed types to be allowed without complaint. + G++ 2.7 does not support transparent unions so there we want the + old-style declaration, too. */ +#if defined __cplusplus || !__GNUC_PREREQ (2, 7) || !defined __USE_GNU +# define __SOCKADDR_ARG struct sockaddr *__restrict +# define __CONST_SOCKADDR_ARG __const struct sockaddr * +#else +/* Add more `struct sockaddr_AF' types here as necessary. + These are all the ones I found on NetBSD and Linux. */ +# define __SOCKADDR_ALLTYPES \ + __SOCKADDR_ONETYPE (sockaddr) \ + __SOCKADDR_ONETYPE (sockaddr_at) \ + __SOCKADDR_ONETYPE (sockaddr_ax25) \ + __SOCKADDR_ONETYPE (sockaddr_dl) \ + __SOCKADDR_ONETYPE (sockaddr_eon) \ + __SOCKADDR_ONETYPE (sockaddr_in) \ + __SOCKADDR_ONETYPE (sockaddr_in6) \ + __SOCKADDR_ONETYPE (sockaddr_inarp) \ + __SOCKADDR_ONETYPE (sockaddr_ipx) \ + __SOCKADDR_ONETYPE (sockaddr_iso) \ + __SOCKADDR_ONETYPE (sockaddr_ns) \ + __SOCKADDR_ONETYPE (sockaddr_un) \ + __SOCKADDR_ONETYPE (sockaddr_x25) + +# define __SOCKADDR_ONETYPE(type) struct type *__restrict __##type##__; +typedef union { __SOCKADDR_ALLTYPES + } __SOCKADDR_ARG __attribute__ ((__transparent_union__)); +# undef __SOCKADDR_ONETYPE +# define __SOCKADDR_ONETYPE(type) __const struct type *__restrict __##type##__; +typedef union { __SOCKADDR_ALLTYPES + } __CONST_SOCKADDR_ARG __attribute__ ((__transparent_union__)); +# undef __SOCKADDR_ONETYPE +#endif + + +/* Create a new socket of type TYPE in domain DOMAIN, using + protocol PROTOCOL. If PROTOCOL is zero, one is chosen automatically. + Returns a file descriptor for the new socket, or -1 for errors. */ +extern int socket (int __domain, int __type, int __protocol) __THROW; +libc_hidden_proto(socket) + +/* Create two new sockets, of type TYPE in domain DOMAIN and using + protocol PROTOCOL, which are connected to each other, and put file + descriptors for them in FDS[0] and FDS[1]. If PROTOCOL is zero, + one will be chosen automatically. Returns 0 on success, -1 for errors. */ +extern int socketpair (int __domain, int __type, int __protocol, + int __fds[2]) __THROW; + +/* Give the socket FD the local address ADDR (which is LEN bytes long). */ +extern int bind (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len) + __THROW; +libc_hidden_proto(bind) + +/* Put the local address of FD into *ADDR and its length in *LEN. */ +extern int getsockname (int __fd, __SOCKADDR_ARG __addr, + socklen_t *__restrict __len) __THROW; +libc_hidden_proto(getsockname) + +/* Open a connection on socket FD to peer at ADDR (which LEN bytes long). + For connectionless socket types, just set the default address to send to + and the only address from which to accept transmissions. + Return 0 on success, -1 for errors. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern int connect (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len); +libc_hidden_proto(connect) + +/* Put the address of the peer connected to socket FD into *ADDR + (which is *LEN bytes long), and its actual length into *LEN. */ +extern int getpeername (int __fd, __SOCKADDR_ARG __addr, + socklen_t *__restrict __len) __THROW; + + +/* Send N bytes of BUF to socket FD. Returns the number sent or -1. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern ssize_t send (int __fd, __const void *__buf, size_t __n, int __flags); +libc_hidden_proto(send) + +/* Read N bytes into BUF from socket FD. + Returns the number read or -1 for errors. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern ssize_t recv (int __fd, void *__buf, size_t __n, int __flags); +libc_hidden_proto(recv) + +/* Send N bytes of BUF on socket FD to peer at address ADDR (which is + ADDR_LEN bytes long). Returns the number sent, or -1 for errors. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern ssize_t sendto (int __fd, __const void *__buf, size_t __n, + int __flags, __CONST_SOCKADDR_ARG __addr, + socklen_t __addr_len); +libc_hidden_proto(sendto) + +/* Read N bytes into BUF through socket FD. + If ADDR is not NULL, fill in *ADDR_LEN bytes of it with tha address of + the sender, and store the actual size of the address in *ADDR_LEN. + Returns the number of bytes read or -1 for errors. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern ssize_t recvfrom (int __fd, void *__restrict __buf, size_t __n, + int __flags, __SOCKADDR_ARG __addr, + socklen_t *__restrict __addr_len); +libc_hidden_proto(recvfrom) + + +/* Send a message described MESSAGE on socket FD. + Returns the number of bytes sent, or -1 for errors. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern ssize_t sendmsg (int __fd, __const struct msghdr *__message, + int __flags); +libc_hidden_proto(sendmsg) + +/* Receive a message as described by MESSAGE from socket FD. + Returns the number of bytes read or -1 for errors. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern ssize_t recvmsg (int __fd, struct msghdr *__message, int __flags); +libc_hidden_proto(recvmsg) + + +/* Put the current value for socket FD's option OPTNAME at protocol level LEVEL + into OPTVAL (which is *OPTLEN bytes long), and set *OPTLEN to the value's + actual length. Returns 0 on success, -1 for errors. */ +extern int getsockopt (int __fd, int __level, int __optname, + void *__restrict __optval, + socklen_t *__restrict __optlen) __THROW; + +/* Set socket FD's option OPTNAME at protocol level LEVEL + to *OPTVAL (which is OPTLEN bytes long). + Returns 0 on success, -1 for errors. */ +extern int setsockopt (int __fd, int __level, int __optname, + __const void *__optval, socklen_t __optlen) __THROW; +libc_hidden_proto(setsockopt) + + +/* Prepare to accept connections on socket FD. + N connection requests will be queued before further requests are refused. + Returns 0 on success, -1 for errors. */ +extern int listen (int __fd, int __n) __THROW; +libc_hidden_proto(listen) + +/* Await a connection on socket FD. + When a connection arrives, open a new socket to communicate with it, + set *ADDR (which is *ADDR_LEN bytes long) to the address of the connecting + peer and *ADDR_LEN to the address's actual length, and return the + new socket's descriptor, or -1 for errors. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern int accept (int __fd, __SOCKADDR_ARG __addr, + socklen_t *__restrict __addr_len); +libc_hidden_proto(accept) + +/* Shut down all or part of the connection open on socket FD. + HOW determines what to shut down: + SHUT_RD = No more receptions; + SHUT_WR = No more transmissions; + SHUT_RDWR = No more receptions or transmissions. + Returns 0 on success, -1 for errors. */ +extern int shutdown (int __fd, int __how) __THROW; + + +#if 0 /*def __USE_XOPEN2K*/ +/* Determine wheter socket is at a out-of-band mark. */ +extern int sockatmark (int __fd) __THROW; +#endif + + +#ifdef __USE_MISC +/* FDTYPE is S_IFSOCK or another S_IF* macro defined in ; + returns 1 if FD is open on an object of the indicated type, 0 if not, + or -1 for errors (setting errno). */ +extern int isfdtype (int __fd, int __fdtype) __THROW; +#endif + +__END_DECLS + +#endif /* sys/socket.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/socketvar.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/socketvar.h new file mode 100644 index 00000000..b177158d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/socketvar.h @@ -0,0 +1,3 @@ +/* This header is used on many systems but for GNU we have everything + already defined in the standard header. */ +#include diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/soundcard.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/soundcard.h new file mode 100644 index 00000000..fade986f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/soundcard.h @@ -0,0 +1 @@ +#include diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/stat.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/stat.h new file mode 100644 index 00000000..170a4e63 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/stat.h @@ -0,0 +1,396 @@ +/* Copyright (C) 1991, 1992, 1995-2004, 2005, 2006, 2007, 2009 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * POSIX Standard: 5.6 File Characteristics + */ + +#ifndef _SYS_STAT_H +#define _SYS_STAT_H 1 + +#include + +#include /* For __mode_t and __dev_t. */ + +#if defined __USE_XOPEN || defined __USE_XOPEN2K || defined __USE_MISC \ + || defined __USE_ATFILE +# if defined __USE_XOPEN || defined __USE_XOPEN2K +# define __need_time_t +# endif +# if defined __USE_MISC || defined __USE_ATFILE +# define __need_timespec +# endif +# include /* For time_t resp. timespec. */ +#endif + +#if defined __USE_XOPEN || defined __USE_XOPEN2K +/* The Single Unix specification says that some more types are + available here. */ +# ifndef __dev_t_defined +typedef __dev_t dev_t; +# define __dev_t_defined +# endif + +# ifndef __gid_t_defined +typedef __gid_t gid_t; +# define __gid_t_defined +# endif + +# ifndef __ino_t_defined +# ifndef __USE_FILE_OFFSET64 +typedef __ino_t ino_t; +# else +typedef __ino64_t ino_t; +# endif +# define __ino_t_defined +# endif + +# ifndef __mode_t_defined +typedef __mode_t mode_t; +# define __mode_t_defined +# endif + +# ifndef __nlink_t_defined +typedef __nlink_t nlink_t; +# define __nlink_t_defined +# endif + +# ifndef __off_t_defined +# ifndef __USE_FILE_OFFSET64 +typedef __off_t off_t; +# else +typedef __off64_t off_t; +# endif +# define __off_t_defined +# endif + +# ifndef __uid_t_defined +typedef __uid_t uid_t; +# define __uid_t_defined +# endif +#endif /* X/Open */ + +#ifdef __USE_UNIX98 +# ifndef __blkcnt_t_defined +# ifndef __USE_FILE_OFFSET64 +typedef __blkcnt_t blkcnt_t; +# else +typedef __blkcnt64_t blkcnt_t; +# endif +# define __blkcnt_t_defined +# endif + +# ifndef __blksize_t_defined +typedef __blksize_t blksize_t; +# define __blksize_t_defined +# endif +#endif /* Unix98 */ + +__BEGIN_DECLS + +#include + +#if defined __USE_BSD || defined __USE_MISC || defined __USE_XOPEN +# define S_IFMT __S_IFMT +# define S_IFDIR __S_IFDIR +# define S_IFCHR __S_IFCHR +# define S_IFBLK __S_IFBLK +# define S_IFREG __S_IFREG +# ifdef __S_IFIFO +# define S_IFIFO __S_IFIFO +# endif +# ifdef __S_IFLNK +# define S_IFLNK __S_IFLNK +# endif +# if (defined __USE_BSD || defined __USE_MISC || defined __USE_UNIX98) \ + && defined __S_IFSOCK +# define S_IFSOCK __S_IFSOCK +# endif +#endif + +/* Test macros for file types. */ + +#define __S_ISTYPE(mode, mask) (((mode) & __S_IFMT) == (mask)) + +#define S_ISDIR(mode) __S_ISTYPE((mode), __S_IFDIR) +#define S_ISCHR(mode) __S_ISTYPE((mode), __S_IFCHR) +#define S_ISBLK(mode) __S_ISTYPE((mode), __S_IFBLK) +#define S_ISREG(mode) __S_ISTYPE((mode), __S_IFREG) +#ifdef __S_IFIFO +# define S_ISFIFO(mode) __S_ISTYPE((mode), __S_IFIFO) +#endif +#ifdef __S_IFLNK +# define S_ISLNK(mode) __S_ISTYPE((mode), __S_IFLNK) +#endif + +#if defined __USE_BSD && !defined __S_IFLNK +# define S_ISLNK(mode) 0 +#endif + +#if (defined __USE_BSD || defined __USE_UNIX98) \ + && defined __S_IFSOCK +# define S_ISSOCK(mode) __S_ISTYPE((mode), __S_IFSOCK) +#endif + +/* These are from POSIX.1b. If the objects are not implemented using separate + distinct file types, the macros always will evaluate to zero. Unlike the + other S_* macros the following three take a pointer to a `struct stat' + object as the argument. */ +#ifdef __USE_POSIX199309 +# define S_TYPEISMQ(buf) __S_TYPEISMQ(buf) +# define S_TYPEISSEM(buf) __S_TYPEISSEM(buf) +# define S_TYPEISSHM(buf) __S_TYPEISSHM(buf) +#endif + + +/* Protection bits. */ + +#define S_ISUID __S_ISUID /* Set user ID on execution. */ +#define S_ISGID __S_ISGID /* Set group ID on execution. */ + +#if defined __USE_BSD || defined __USE_MISC || defined __USE_XOPEN +/* Save swapped text after use (sticky bit). This is pretty well obsolete. */ +# define S_ISVTX __S_ISVTX +#endif + +#define S_IRUSR __S_IREAD /* Read by owner. */ +#define S_IWUSR __S_IWRITE /* Write by owner. */ +#define S_IXUSR __S_IEXEC /* Execute by owner. */ +/* Read, write, and execute by owner. */ +#define S_IRWXU (__S_IREAD|__S_IWRITE|__S_IEXEC) + +#if defined __USE_MISC && defined __USE_BSD +# define S_IREAD S_IRUSR +# define S_IWRITE S_IWUSR +# define S_IEXEC S_IXUSR +#endif + +#define S_IRGRP (S_IRUSR >> 3) /* Read by group. */ +#define S_IWGRP (S_IWUSR >> 3) /* Write by group. */ +#define S_IXGRP (S_IXUSR >> 3) /* Execute by group. */ +/* Read, write, and execute by group. */ +#define S_IRWXG (S_IRWXU >> 3) + +#define S_IROTH (S_IRGRP >> 3) /* Read by others. */ +#define S_IWOTH (S_IWGRP >> 3) /* Write by others. */ +#define S_IXOTH (S_IXGRP >> 3) /* Execute by others. */ +/* Read, write, and execute by others. */ +#define S_IRWXO (S_IRWXG >> 3) + + +#ifdef __USE_BSD +/* Macros for common mode bit masks. */ +# define ACCESSPERMS (S_IRWXU|S_IRWXG|S_IRWXO) /* 0777 */ +# define ALLPERMS (S_ISUID|S_ISGID|S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO)/* 07777 */ +# define DEFFILEMODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)/* 0666*/ + +# define S_BLKSIZE 512 /* Block size for `st_blocks'. */ +#endif + + +#ifndef __USE_FILE_OFFSET64 +/* Get file attributes for FILE and put them in BUF. */ +extern int stat (__const char *__restrict __file, + struct stat *__restrict __buf) __THROW __nonnull ((1, 2)); +libc_hidden_proto(stat) + +/* Get file attributes for the file, device, pipe, or socket + that file descriptor FD is open on and put them in BUF. */ +extern int fstat (int __fd, struct stat *__buf) __THROW __nonnull ((2)); +libc_hidden_proto(fstat) +#else +# ifdef __REDIRECT_NTH +extern int __REDIRECT_NTH (stat, (__const char *__restrict __file, + struct stat *__restrict __buf), stat64) + __nonnull ((1, 2)); +extern int __REDIRECT_NTH (fstat, (int __fd, struct stat *__buf), fstat64) + __nonnull ((2)); +# else +# define stat stat64 +# define fstat fstat64 +# endif +#endif +#ifdef __USE_LARGEFILE64 +extern int stat64 (__const char *__restrict __file, + struct stat64 *__restrict __buf) __THROW __nonnull ((1, 2)); +extern int fstat64 (int __fd, struct stat64 *__buf) __THROW __nonnull ((2)); +libc_hidden_proto(stat64) +libc_hidden_proto(fstat64) +#endif + +#ifdef __USE_ATFILE +/* Similar to stat, get the attributes for FILE and put them in BUF. + Relative path names are interpreted relative to FD unless FD is + AT_FDCWD. */ +# ifndef __USE_FILE_OFFSET64 +extern int fstatat (int __fd, __const char *__restrict __file, + struct stat *__restrict __buf, int __flag) + __THROW __nonnull ((2, 3)); +# else +# ifdef __REDIRECT_NTH +extern int __REDIRECT_NTH (fstatat, (int __fd, __const char *__restrict __file, + struct stat *__restrict __buf, + int __flag), + fstatat64) __nonnull ((2, 3)); +# else +# define fstatat fstatat64 +# endif +# endif + +# ifdef __USE_LARGEFILE64 +extern int fstatat64 (int __fd, __const char *__restrict __file, + struct stat64 *__restrict __buf, int __flag) + __THROW __nonnull ((2, 3)); +# endif +#endif + +#if defined __USE_BSD || defined __USE_XOPEN_EXTENDED || defined __USE_XOPEN2K +# ifndef __USE_FILE_OFFSET64 +/* Get file attributes about FILE and put them in BUF. + If FILE is a symbolic link, do not follow it. */ +extern int lstat (__const char *__restrict __file, + struct stat *__restrict __buf) __THROW __nonnull ((1, 2)); +libc_hidden_proto(lstat) +# else +# ifdef __REDIRECT_NTH +extern int __REDIRECT_NTH (lstat, + (__const char *__restrict __file, + struct stat *__restrict __buf), lstat64) + __nonnull ((1, 2)); +# else +# define lstat lstat64 +# endif +# endif +# ifdef __USE_LARGEFILE64 +extern int lstat64 (__const char *__restrict __file, + struct stat64 *__restrict __buf) + __THROW __nonnull ((1, 2)); +libc_hidden_proto(lstat64) +# endif +#endif + +/* Set file access permissions for FILE to MODE. + If FILE is a symbolic link, this affects its target instead. */ +extern int chmod (__const char *__file, __mode_t __mode) + __THROW __nonnull ((1)); +libc_hidden_proto(chmod) + +#if 0 /*def __USE_BSD*/ +/* Set file access permissions for FILE to MODE. + If FILE is a symbolic link, this affects the link itself + rather than its target. */ +extern int lchmod (__const char *__file, __mode_t __mode) + __THROW __nonnull ((1)); +#endif + +/* Set file access permissions of the file FD is open on to MODE. */ +#if defined __USE_BSD || defined __USE_XOPEN_EXTENDED +extern int fchmod (int __fd, __mode_t __mode) __THROW; +#endif + +#ifdef __USE_ATFILE +/* Set file access permissions of FILE relative to + the directory FD is open on. */ +extern int fchmodat (int __fd, __const char *__file, __mode_t __mode, + int __flag) + __THROW __nonnull ((2)) __wur; +#endif /* Use ATFILE. */ + + + +/* Set the file creation mask of the current process to MASK, + and return the old creation mask. */ +extern __mode_t umask (__mode_t __mask) __THROW; + +#if 0 /*def __USE_GNU*/ +/* Get the current `umask' value without changing it. + This function is only available under the GNU Hurd. */ +extern __mode_t getumask (void) __THROW; +#endif + +/* Create a new directory named PATH, with permission bits MODE. */ +extern int mkdir (__const char *__path, __mode_t __mode) + __THROW __nonnull ((1)); +libc_hidden_proto(mkdir) + +#ifdef __USE_ATFILE +/* Like mkdir, create a new directory with permission bits MODE. But + interpret relative PATH names relative to the directory associated + with FD. */ +extern int mkdirat (int __fd, __const char *__path, __mode_t __mode) + __THROW __nonnull ((2)); +#endif + +/* Create a device file named PATH, with permission and special bits MODE + and device number DEV (which can be constructed from major and minor + device numbers with the `makedev' macro above). */ +#if defined __USE_MISC || defined __USE_BSD || defined __USE_XOPEN_EXTENDED +extern int mknod (__const char *__path, __mode_t __mode, __dev_t __dev) + __THROW __nonnull ((1)); +libc_hidden_proto(mknod) + +# ifdef __USE_ATFILE +/* Like mknod, create a new device file with permission bits MODE and + device number DEV. But interpret relative PATH names relative to + the directory associated with FD. */ +extern int mknodat (int __fd, __const char *__path, __mode_t __mode, + __dev_t __dev) __THROW __nonnull ((2)); +libc_hidden_proto(mknodat) +# endif +#endif + + +/* Create a new FIFO named PATH, with permission bits MODE. */ +extern int mkfifo (__const char *__path, __mode_t __mode) + __THROW __nonnull ((1)); + +#ifdef __USE_ATFILE +/* Like mkfifo, create a new FIFO with permission bits MODE. But + interpret relative PATH names relative to the directory associated + with FD. */ +extern int mkfifoat (int __fd, __const char *__path, __mode_t __mode) + __THROW __nonnull ((2)); +#endif + +#ifdef __USE_ATFILE +/* Set file access and modification times relative to directory file + descriptor. */ +extern int utimensat (int __fd, __const char *__path, + __const struct timespec __times[2], + int __flags) + __THROW __nonnull ((2)); +libc_hidden_proto(utimensat) +#endif + +#ifdef __USE_XOPEN2K8 +/* Set file access and modification times of the file associated with FD. */ +extern int futimens (int __fd, __const struct timespec __times[2]) __THROW; +#endif + +/* on uClibc we have unversioned struct stat and mknod. + * bits/stat.h is filled with wrong info, so we undo it here. */ +#undef _STAT_VER +#define _STAT_VER 0 +#undef _MKNOD_VER +#define _MKNOD_VER 0 + +__END_DECLS + + +#endif /* sys/stat.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/statfs.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/statfs.h new file mode 100644 index 00000000..c754ea35 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/statfs.h @@ -0,0 +1,70 @@ +/* Definitions for getting information about a filesystem. + Copyright (C) 1996, 1997, 1998, 1999, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_STATFS_H +#define _SYS_STATFS_H 1 + +#include + +/* Get the system-specific definition of `struct statfs'. */ +#include + +__BEGIN_DECLS + +/* Return information about the filesystem on which FILE resides. */ +#ifndef __USE_FILE_OFFSET64 +extern int statfs (__const char *__file, struct statfs *__buf) + __THROW __nonnull ((1, 2)); +#else +# ifdef __REDIRECT_NTH +extern int __REDIRECT_NTH (statfs, + (__const char *__file, struct statfs *__buf), + statfs64) __nonnull ((1, 2)); +# else +# define statfs statfs64 +# endif +#endif +#ifdef __USE_LARGEFILE64 +extern int statfs64 (__const char *__file, struct statfs64 *__buf) + __THROW __nonnull ((1, 2)); +libc_hidden_proto(statfs64) +#endif + +/* Return information about the filesystem containing the file FILDES + refers to. */ +#ifndef __USE_FILE_OFFSET64 +extern int fstatfs (int __fildes, struct statfs *__buf) + __THROW __nonnull ((2)); +#else +# ifdef __REDIRECT_NTH +extern int __REDIRECT_NTH (fstatfs, (int __fildes, struct statfs *__buf), + fstatfs64) __nonnull ((2)); +# else +# define fstatfs fstatfs64 +# endif +#endif +#ifdef __USE_LARGEFILE64 +extern int fstatfs64 (int __fildes, struct statfs64 *__buf) + __THROW __nonnull ((2)); +libc_hidden_proto(fstatfs64) +#endif + +__END_DECLS + +#endif /* sys/statfs.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/statvfs.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/statvfs.h new file mode 100644 index 00000000..6199c5d0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/statvfs.h @@ -0,0 +1,93 @@ +/* Definitions for getting information about a filesystem. + Copyright (C) 1998, 1999, 2000, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_STATVFS_H +#define _SYS_STATVFS_H 1 + +#include + +/* Get the system-specific definition of `struct statfs'. */ +#include + +#ifndef __USE_FILE_OFFSET64 +# ifndef __fsblkcnt_t_defined +typedef __fsblkcnt_t fsblkcnt_t; /* Type to count file system blocks. */ +# define __fsblkcnt_t_defined +# endif +# ifndef __fsfilcnt_t_defined +typedef __fsfilcnt_t fsfilcnt_t; /* Type to count file system inodes. */ +# define __fsfilcnt_t_defined +# endif +#else +# ifndef __fsblkcnt_t_defined +typedef __fsblkcnt64_t fsblkcnt_t; /* Type to count file system blocks. */ +# define __fsblkcnt_t_defined +# endif +# ifndef __fsfilcnt_t_defined +typedef __fsfilcnt64_t fsfilcnt_t; /* Type to count file system inodes. */ +# define __fsfilcnt_t_defined +# endif +#endif + +__BEGIN_DECLS + +/* Return information about the filesystem on which FILE resides. */ +#ifndef __USE_FILE_OFFSET64 +extern int statvfs (__const char *__restrict __file, + struct statvfs *__restrict __buf) + __THROW __nonnull ((1, 2)); +libc_hidden_proto(statvfs) +#else +# ifdef __REDIRECT_NTH +extern int __REDIRECT_NTH (statvfs, + (__const char *__restrict __file, + struct statvfs *__restrict __buf), statvfs64) + __nonnull ((1, 2)); +# else +# define statvfs statvfs64 +# endif +#endif +#ifdef __USE_LARGEFILE64 +extern int statvfs64 (__const char *__restrict __file, + struct statvfs64 *__restrict __buf) + __THROW __nonnull ((1, 2)); +#endif + +/* Return information about the filesystem containing the file FILDES + refers to. */ +#ifndef __USE_FILE_OFFSET64 +extern int fstatvfs (int __fildes, struct statvfs *__buf) + __THROW __nonnull ((2)); +libc_hidden_proto(fstatvfs) +#else +# ifdef __REDIRECT_NTH +extern int __REDIRECT_NTH (fstatvfs, (int __fildes, struct statvfs *__buf), + fstatvfs64) __nonnull ((2)); +# else +# define fstatvfs fstatvfs64 +# endif +#endif +#ifdef __USE_LARGEFILE64 +extern int fstatvfs64 (int __fildes, struct statvfs64 *__buf) + __THROW __nonnull ((2)); +#endif + +__END_DECLS + +#endif /* sys/statvfs.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/swap.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/swap.h new file mode 100644 index 00000000..b6e7bef5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/swap.h @@ -0,0 +1,43 @@ +/* Calls to enable and disable swapping on specified locations. Linux version. + Copyright (C) 1996, 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_SWAP_H + +#define _SYS_SWAP_H 1 +#include + +/* The swap priority is encoded as: + (prio << SWAP_FLAG_PRIO_SHIFT) & SWAP_FLAG_PRIO_MASK +*/ +#define SWAP_FLAG_PREFER 0x8000 /* Set if swap priority is specified. */ +#define SWAP_FLAG_PRIO_MASK 0x7fff +#define SWAP_FLAG_PRIO_SHIFT 0 + +__BEGIN_DECLS + +/* Make the block special device PATH available to the system for swapping. + This call is restricted to the super-user. */ +extern int swapon (__const char *__path, int __flags) __THROW; + +/* Stop using block special device PATH for swapping. */ +extern int swapoff (__const char *__path) __THROW; + +__END_DECLS + +#endif /* _SYS_SWAP_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/syscall.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/syscall.h new file mode 100644 index 00000000..25264cf9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/syscall.h @@ -0,0 +1,38 @@ +/* Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYSCALL_H +#define _SYSCALL_H 1 + +/* User application code should use syscall(). */ + +#include +#include +#ifdef _LIBC +/* The _syscall#() macros are for uClibc internal use only. + * + * The kernel provided _syscall[0-6] macros from asm/unistd.h are not suitable + * for use in uClibc as they lack PIC support etc, so for uClibc we use our own + * local _syscall# macros to be certain all such variations are handled + * properly. + */ +# include +# include +#endif + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/sysctl.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/sysctl.h new file mode 100644 index 00000000..110efaa7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/sysctl.h @@ -0,0 +1,72 @@ +/* Copyright (C) 1996, 1999, 2002, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_SYSCTL_H +#define _SYS_SYSCTL_H 1 + +#include +#define __need_size_t +#include +/* Prevent more kernel headers than necessary to be included. */ +#ifndef _LINUX_KERNEL_H +# define _LINUX_KERNEL_H 1 +# define __undef_LINUX_KERNEL_H +#endif +#ifndef _LINUX_TYPES_H +# define _LINUX_TYPES_H 1 +# define __undef_LINUX_TYPES_H +#endif +#ifndef _LINUX_LIST_H +# define _LINUX_LIST_H 1 +# define __undef_LINUX_LIST_H +#endif +#ifndef __LINUX_COMPILER_H +# define __LINUX_COMPILER_H 1 +# define __user +# define __undef__LINUX_COMPILER_H +#endif + +#include + +#ifdef __undef_LINUX_KERNEL_H +# undef _LINUX_KERNEL_H +# undef __undef_LINUX_KERNEL_H +#endif +#ifdef __undef_LINUX_TYPES_H +# undef _LINUX_TYPES_H +# undef __undef_LINUX_TYPES_H +#endif +#ifdef __undef_LINUX_LIST_H +# undef _LINUX_LIST_H +# undef __undef_LINUX_LIST_H +#endif +#ifdef __undef__LINUX_COMPILER_H +# undef __LINUX_COMPILER_H +# undef __user +# undef __undef__LINUX_COMPILER_H +#endif + +__BEGIN_DECLS + +/* Read or write system parameters. */ +extern int sysctl (int *__name, int __nlen, void *__oldval, + size_t *__oldlenp, void *__newval, size_t __newlen) __THROW; + +__END_DECLS + +#endif /* _SYS_SYSCTL_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/sysinfo.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/sysinfo.h new file mode 100644 index 00000000..508e4e30 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/sysinfo.h @@ -0,0 +1,68 @@ +/* Copyright (C) 1996, 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_SYSINFO_H +#define _SYS_SYSINFO_H 1 + +#include + +#ifndef _LINUX_KERNEL_H +/* Include our own copy of struct sysinfo to avoid binary compatability + * problems with Linux 2.4, which changed things. Grumble, grumble. */ +#define SI_LOAD_SHIFT 16 +struct sysinfo { + long uptime; /* Seconds since boot */ + unsigned long loads[3]; /* 1, 5, and 15 minute load averages */ + unsigned long totalram; /* Total usable main memory size */ + unsigned long freeram; /* Available memory size */ + unsigned long sharedram; /* Amount of shared memory */ + unsigned long bufferram; /* Memory used by buffers */ + unsigned long totalswap; /* Total swap space size */ + unsigned long freeswap; /* swap space still available */ + unsigned short procs; /* Number of current processes */ + unsigned short pad; /* Padding needed for m68k */ + unsigned long totalhigh; /* Total high memory size */ + unsigned long freehigh; /* Available high memory size */ + unsigned int mem_unit; /* Memory unit size in bytes */ + char _f[20-2*sizeof(long)-sizeof(int)]; /* Padding: libc5 uses this.. */ +}; +#endif + +__BEGIN_DECLS + +/* Returns information on overall system statistics. */ +extern int sysinfo (struct sysinfo *__info) __THROW; + +/* Return number of configured processors. */ +#define get_nprocs_conf() (sysconf(_SC_NPROCESSORS_CONF)) + +/* Return number of available processors. */ +#define get_nprocs() (sysconf(_SC_NPROCESSORS_ONLN)) + + +#if 0 +/* Return number of physical pages of memory in the system. */ +extern long int get_phys_pages (void) __THROW; + +/* Return number of available physical pages of memory in the system. */ +extern long int get_avphys_pages (void) __THROW; +#endif + +__END_DECLS + +#endif /* sys/sysinfo.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/syslog.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/syslog.h new file mode 100644 index 00000000..8fc76884 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/syslog.h @@ -0,0 +1,216 @@ +/* + * Copyright (c) 1982, 1986, 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)syslog.h 8.1 (Berkeley) 6/2/93 + */ + +#ifndef _SYS_SYSLOG_H +#define _SYS_SYSLOG_H 1 + +#include +#define __need___va_list +#include + + +#define _PATH_LOG "/dev/log" + +/* + * priorities/facilities are encoded into a single 32-bit quantity, where the + * bottom 3 bits are the priority (0-7) and the top 28 bits are the facility + * (0-big number). Both the priorities and the facilities map roughly + * one-to-one to strings in the syslogd(8) source code. This mapping is + * included in this file. + * + * priorities (these are ordered) + */ +#define LOG_EMERG 0 /* system is unusable */ +#define LOG_ALERT 1 /* action must be taken immediately */ +#define LOG_CRIT 2 /* critical conditions */ +#define LOG_ERR 3 /* error conditions */ +#define LOG_WARNING 4 /* warning conditions */ +#define LOG_NOTICE 5 /* normal but significant condition */ +#define LOG_INFO 6 /* informational */ +#define LOG_DEBUG 7 /* debug-level messages */ + +#define LOG_PRIMASK 0x07 /* mask to extract priority part (internal) */ + /* extract priority */ +#define LOG_PRI(p) ((p) & LOG_PRIMASK) +#define LOG_MAKEPRI(fac, pri) (((fac) << 3) | (pri)) + +#ifdef SYSLOG_NAMES +#define INTERNAL_NOPRI 0x10 /* the "no priority" priority */ + /* mark "facility" */ +#define INTERNAL_MARK LOG_MAKEPRI(LOG_NFACILITIES, 0) +typedef struct _code { + const char *c_name; + int c_val; +} CODE; + +#ifdef SYSLOG_NAMES_CONST +const +#endif +CODE prioritynames[] = + { + { "alert", LOG_ALERT }, + { "crit", LOG_CRIT }, + { "debug", LOG_DEBUG }, + { "emerg", LOG_EMERG }, + { "err", LOG_ERR }, + { "error", LOG_ERR }, /* DEPRECATED */ + { "info", LOG_INFO }, + { "none", INTERNAL_NOPRI }, /* INTERNAL */ + { "notice", LOG_NOTICE }, + { "panic", LOG_EMERG }, /* DEPRECATED */ + { "warn", LOG_WARNING }, /* DEPRECATED */ + { "warning", LOG_WARNING }, + { NULL, -1 } + }; +#endif + +/* facility codes */ +#define LOG_KERN (0<<3) /* kernel messages */ +#define LOG_USER (1<<3) /* random user-level messages */ +#define LOG_MAIL (2<<3) /* mail system */ +#define LOG_DAEMON (3<<3) /* system daemons */ +#define LOG_AUTH (4<<3) /* security/authorization messages */ +#define LOG_SYSLOG (5<<3) /* messages generated internally by syslogd */ +#define LOG_LPR (6<<3) /* line printer subsystem */ +#define LOG_NEWS (7<<3) /* network news subsystem */ +#define LOG_UUCP (8<<3) /* UUCP subsystem */ +#define LOG_CRON (9<<3) /* clock daemon */ +#define LOG_AUTHPRIV (10<<3) /* security/authorization messages (private) */ +#define LOG_FTP (11<<3) /* ftp daemon */ + + /* other codes through 15 reserved for system use */ +#define LOG_LOCAL0 (16<<3) /* reserved for local use */ +#define LOG_LOCAL1 (17<<3) /* reserved for local use */ +#define LOG_LOCAL2 (18<<3) /* reserved for local use */ +#define LOG_LOCAL3 (19<<3) /* reserved for local use */ +#define LOG_LOCAL4 (20<<3) /* reserved for local use */ +#define LOG_LOCAL5 (21<<3) /* reserved for local use */ +#define LOG_LOCAL6 (22<<3) /* reserved for local use */ +#define LOG_LOCAL7 (23<<3) /* reserved for local use */ + +#define LOG_NFACILITIES 24 /* current number of facilities */ +#define LOG_FACMASK 0x03f8 /* mask to extract facility part */ + /* facility of pri */ +#define LOG_FAC(p) (((p) & LOG_FACMASK) >> 3) + +#ifdef SYSLOG_NAMES +#ifdef SYSLOG_NAMES_CONST +const +#endif +CODE facilitynames[] = + { + { "auth", LOG_AUTH }, + { "authpriv", LOG_AUTHPRIV }, + { "cron", LOG_CRON }, + { "daemon", LOG_DAEMON }, + { "ftp", LOG_FTP }, + { "kern", LOG_KERN }, + { "lpr", LOG_LPR }, + { "mail", LOG_MAIL }, + { "mark", INTERNAL_MARK }, /* INTERNAL */ + { "news", LOG_NEWS }, + { "security", LOG_AUTH }, /* DEPRECATED */ + { "syslog", LOG_SYSLOG }, + { "user", LOG_USER }, + { "uucp", LOG_UUCP }, + { "local0", LOG_LOCAL0 }, + { "local1", LOG_LOCAL1 }, + { "local2", LOG_LOCAL2 }, + { "local3", LOG_LOCAL3 }, + { "local4", LOG_LOCAL4 }, + { "local5", LOG_LOCAL5 }, + { "local6", LOG_LOCAL6 }, + { "local7", LOG_LOCAL7 }, + { NULL, -1 } + }; +#endif + +/* + * arguments to setlogmask. + */ +#define LOG_MASK(pri) (1 << (pri)) /* mask for one priority */ +#define LOG_UPTO(pri) ((1 << ((pri)+1)) - 1) /* all priorities through pri */ + +/* + * Option flags for openlog. + * + * LOG_ODELAY no longer does anything. + * LOG_NDELAY is the inverse of what it used to be. + */ +#define LOG_PID 0x01 /* log the pid with each message */ +#define LOG_CONS 0x02 /* log on the console if errors in sending */ +#define LOG_ODELAY 0x04 /* delay open until first syslog() (default) */ +#define LOG_NDELAY 0x08 /* don't delay open */ +#define LOG_NOWAIT 0x10 /* don't wait for console forks: DEPRECATED */ +#define LOG_PERROR 0x20 /* log to stderr as well */ + +__BEGIN_DECLS + +/* Close descriptor used to write to system logger. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern void closelog (void); +libc_hidden_proto(closelog) + +/* Open connection to system logger. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern void openlog (__const char *__ident, int __option, int __facility); +libc_hidden_proto(openlog) + +/* Set the log mask level. */ +extern int setlogmask (int __mask) __THROW; + +/* Generate a log message using FMT string and option arguments. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern void syslog (int __pri, __const char *__fmt, ...) + __attribute__ ((__format__ (__printf__, 2, 3))); +libc_hidden_proto(syslog) + +#ifdef __USE_BSD +/* Generate a log message using FMT and using arguments pointed to by AP. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern void vsyslog (int __pri, __const char *__fmt, __gnuc_va_list __ap) + __attribute__ ((__format__ (__printf__, 2, 0))); +libc_hidden_proto(vsyslog) +#endif + +__END_DECLS + +#endif /* sys/syslog.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/sysmacros.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/sysmacros.h new file mode 100644 index 00000000..c5efca4f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/sysmacros.h @@ -0,0 +1,69 @@ +/* Definitions of macros to access `dev_t' values. + Copyright (C) 1996, 1997, 1999, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_SYSMACROS_H +#define _SYS_SYSMACROS_H 1 + +#include + +/* If the compiler does not know long long it is out of luck. We are + not going to hack weird hacks to support the dev_t representation + they need. */ +#if 1 /*def __GLIBC_HAVE_LONG_LONG uClibc note: always enable */ +__extension__ +static __inline unsigned int gnu_dev_major (unsigned long long int __dev) + __THROW; +__extension__ +static __inline unsigned int gnu_dev_minor (unsigned long long int __dev) + __THROW; +__extension__ +static __inline unsigned long long int gnu_dev_makedev (unsigned int __major, + unsigned int __minor) + __THROW; + +# if defined __GNUC__ && __GNUC__ >= 2 +__extension__ static __inline unsigned int +__NTH (gnu_dev_major (unsigned long long int __dev)) +{ + return ((__dev >> 8) & 0xfff) | ((unsigned int) (__dev >> 32) & ~0xfff); +} + +__extension__ static __inline unsigned int +__NTH (gnu_dev_minor (unsigned long long int __dev)) +{ + return (__dev & 0xff) | ((unsigned int) (__dev >> 12) & ~0xff); +} + +__extension__ static __inline unsigned long long int +__NTH (gnu_dev_makedev (unsigned int __major, unsigned int __minor)) +{ + return ((__minor & 0xff) | ((__major & 0xfff) << 8) + | (((unsigned long long int) (__minor & ~0xff)) << 12) + | (((unsigned long long int) (__major & ~0xfff)) << 32)); +} +# endif + + +/* Access the functions with their traditional names. */ +# define major(dev) gnu_dev_major (dev) +# define minor(dev) gnu_dev_minor (dev) +# define makedev(maj, min) gnu_dev_makedev (maj, min) +#endif + +#endif /* sys/sysmacros.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/termios.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/termios.h new file mode 100644 index 00000000..3e18805a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/termios.h @@ -0,0 +1,4 @@ +#ifndef _SYS_TERMIOS_H +#define _SYS_TERMIOS_H +#include +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/time.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/time.h new file mode 100644 index 00000000..952e95a3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/time.h @@ -0,0 +1,199 @@ +/* Copyright (C) 1991-1994,1996-2003,2005,2006,2009 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_TIME_H +#define _SYS_TIME_H 1 + +#include + +#include +#define __need_time_t +#include +#define __need_timeval +#include + +#include + +#ifndef __suseconds_t_defined +typedef __suseconds_t suseconds_t; +# define __suseconds_t_defined +#endif + + +__BEGIN_DECLS + +#ifdef __USE_GNU +/* Macros for converting between `struct timeval' and `struct timespec'. */ +# define TIMEVAL_TO_TIMESPEC(tv, ts) { \ + (ts)->tv_sec = (tv)->tv_sec; \ + (ts)->tv_nsec = (tv)->tv_usec * 1000; \ +} +# define TIMESPEC_TO_TIMEVAL(tv, ts) { \ + (tv)->tv_sec = (ts)->tv_sec; \ + (tv)->tv_usec = (ts)->tv_nsec / 1000; \ +} +#endif + + +#ifdef __USE_BSD +/* Structure crudely representing a timezone. + This is obsolete and should never be used. */ +struct timezone + { + int tz_minuteswest; /* Minutes west of GMT. */ + int tz_dsttime; /* Nonzero if DST is ever in effect. */ + }; + +typedef struct timezone *__restrict __timezone_ptr_t; +#else +typedef void *__restrict __timezone_ptr_t; +#endif + +/* Get the current time of day and timezone information, + putting it into *TV and *TZ. If TZ is NULL, *TZ is not filled. + Returns 0 on success, -1 on errors. + NOTE: This form of timezone information is obsolete. + Use the functions and variables declared in instead. */ +extern int gettimeofday (struct timeval *__restrict __tv, + __timezone_ptr_t __tz) __THROW __nonnull ((1)); +libc_hidden_proto(gettimeofday) + +#ifdef __USE_BSD +/* Set the current time of day and timezone information. + This call is restricted to the super-user. */ +extern int settimeofday (__const struct timeval *__tv, + __const struct timezone *__tz) + __THROW __nonnull ((1)); +libc_hidden_proto(settimeofday) + +/* Adjust the current time of day by the amount in DELTA. + If OLDDELTA is not NULL, it is filled in with the amount + of time adjustment remaining to be done from the last `adjtime' call. + This call is restricted to the super-user. */ +extern int adjtime (__const struct timeval *__delta, + struct timeval *__olddelta) __THROW; +#endif + + +/* Values for the first argument to `getitimer' and `setitimer'. */ +enum __itimer_which + { + /* Timers run in real time. */ + ITIMER_REAL = 0, +#define ITIMER_REAL ITIMER_REAL + /* Timers run only when the process is executing. */ + ITIMER_VIRTUAL = 1, +#define ITIMER_VIRTUAL ITIMER_VIRTUAL + /* Timers run when the process is executing and when + the system is executing on behalf of the process. */ + ITIMER_PROF = 2 +#define ITIMER_PROF ITIMER_PROF + }; + +/* Type of the second argument to `getitimer' and + the second and third arguments `setitimer'. */ +struct itimerval + { + /* Value to put into `it_value' when the timer expires. */ + struct timeval it_interval; + /* Time to the next timer expiration. */ + struct timeval it_value; + }; + +#if defined __USE_GNU && !defined __cplusplus +/* Use the nicer parameter type only in GNU mode and not for C++ since the + strict C++ rules prevent the automatic promotion. */ +typedef enum __itimer_which __itimer_which_t; +#else +typedef int __itimer_which_t; +#endif + +/* Set *VALUE to the current setting of timer WHICH. + Return 0 on success, -1 on errors. */ +extern int getitimer (__itimer_which_t __which, + struct itimerval *__value) __THROW; + +/* Set the timer WHICH to *NEW. If OLD is not NULL, + set *OLD to the old value of timer WHICH. + Returns 0 on success, -1 on errors. */ +extern int setitimer (__itimer_which_t __which, + __const struct itimerval *__restrict __new, + struct itimerval *__restrict __old) __THROW; +libc_hidden_proto(setitimer) + +/* Change the access time of FILE to TVP[0] and the modification time of + FILE to TVP[1]. If TVP is a null pointer, use the current time instead. + Returns 0 on success, -1 on errors. */ +extern int utimes (__const char *__file, __const struct timeval __tvp[2]) + __THROW __nonnull ((1)); +libc_hidden_proto(utimes) + +#ifdef __USE_BSD +/* Same as `utimes', but does not follow symbolic links. */ +extern int lutimes (__const char *__file, __const struct timeval __tvp[2]) + __THROW __nonnull ((1)); + +#if 0 +/* Same as `utimes', but takes an open file descriptor instead of a name. */ +extern int futimes (int __fd, __const struct timeval __tvp[2]) __THROW; +#endif +#endif + +#ifdef __USE_GNU +/* Change the access time of FILE relative to FD to TVP[0] and the + modification time of FILE to TVP[1]. If TVP is a null pointer, use + the current time instead. Returns 0 on success, -1 on errors. */ +extern int futimesat (int __fd, __const char *__file, + __const struct timeval __tvp[2]) __THROW; +#endif + + +#ifdef __USE_BSD +/* Convenience macros for operations on timevals. + NOTE: `timercmp' does not work for >= or <=. */ +# define timerisset(tvp) ((tvp)->tv_sec || (tvp)->tv_usec) +# define timerclear(tvp) ((tvp)->tv_sec = (tvp)->tv_usec = 0) +# define timercmp(a, b, CMP) \ + (((a)->tv_sec == (b)->tv_sec) ? \ + ((a)->tv_usec CMP (b)->tv_usec) : \ + ((a)->tv_sec CMP (b)->tv_sec)) +# define timeradd(a, b, result) \ + do { \ + (result)->tv_sec = (a)->tv_sec + (b)->tv_sec; \ + (result)->tv_usec = (a)->tv_usec + (b)->tv_usec; \ + if ((result)->tv_usec >= 1000000) \ + { \ + ++(result)->tv_sec; \ + (result)->tv_usec -= 1000000; \ + } \ + } while (0) +# define timersub(a, b, result) \ + do { \ + (result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \ + (result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \ + if ((result)->tv_usec < 0) { \ + --(result)->tv_sec; \ + (result)->tv_usec += 1000000; \ + } \ + } while (0) +#endif /* BSD */ + +__END_DECLS + +#endif /* sys/time.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/timeb.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/timeb.h new file mode 100644 index 00000000..dbdbf45a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/timeb.h @@ -0,0 +1,46 @@ +/* Copyright (C) 1994, 1995, 1996, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_TIMEB_H +#define _SYS_TIMEB_H 1 + +#include + +#define __need_time_t +#include + + +__BEGIN_DECLS + +/* Structure returned by the `ftime' function. */ + +struct timeb + { + time_t time; /* Seconds since epoch, as from `time'. */ + unsigned short int millitm; /* Additional milliseconds. */ + short int timezone; /* Minutes west of GMT. */ + short int dstflag; /* Nonzero if Daylight Savings Time used. */ + }; + +/* Fill in TIMEBUF with information about the current time. */ + +extern int ftime (struct timeb *__timebuf); + +__END_DECLS + +#endif /* sys/timeb.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/times.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/times.h new file mode 100644 index 00000000..13535a5f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/times.h @@ -0,0 +1,54 @@ +/* Copyright (C) 1991, 1992, 1996, 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * POSIX Standard: 4.5.2 Process Times + */ + +#ifndef _SYS_TIMES_H +#define _SYS_TIMES_H 1 + +#include + +#define __need_clock_t +#include + + +__BEGIN_DECLS + +/* Structure describing CPU time used by a process and its children. */ +struct tms + { + clock_t tms_utime; /* User CPU time. */ + clock_t tms_stime; /* System CPU time. */ + + clock_t tms_cutime; /* User CPU time of dead children. */ + clock_t tms_cstime; /* System CPU time of dead children. */ + }; + + +/* Store the CPU time used by this process and all its + dead children (and their dead children) in BUFFER. + Return the elapsed real time, or (clock_t) -1 for errors. + All times are in CLK_TCKths of a second. */ +extern clock_t times (struct tms *__buffer) __THROW; +libc_hidden_proto(times) + +__END_DECLS + +#endif /* sys/times.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/timex.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/timex.h new file mode 100644 index 00000000..5e82d464 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/timex.h @@ -0,0 +1,132 @@ +/* Copyright (C) 1995, 1996, 1997, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_TIMEX_H +#define _SYS_TIMEX_H 1 + +#include +#include + +/* These definitions from linux/timex.h as of 2.2.0. */ + +struct ntptimeval +{ + struct timeval time; /* current time (ro) */ + long int maxerror; /* maximum error (us) (ro) */ + long int esterror; /* estimated error (us) (ro) */ +}; + +struct timex +{ + unsigned int modes; /* mode selector */ + long int offset; /* time offset (usec) */ + long int freq; /* frequency offset (scaled ppm) */ + long int maxerror; /* maximum error (usec) */ + long int esterror; /* estimated error (usec) */ + int status; /* clock command/status */ + long int constant; /* pll time constant */ + long int precision; /* clock precision (usec) (read only) */ + long int tolerance; /* clock frequency tolerance (ppm) (read only) */ + struct timeval time; /* (read only) */ + long int tick; /* (modified) usecs between clock ticks */ + + long int ppsfreq; /* pps frequency (scaled ppm) (ro) */ + long int jitter; /* pps jitter (us) (ro) */ + int shift; /* interval duration (s) (shift) (ro) */ + long int stabil; /* pps stability (scaled ppm) (ro) */ + long int jitcnt; /* jitter limit exceeded (ro) */ + long int calcnt; /* calibration intervals (ro) */ + long int errcnt; /* calibration errors (ro) */ + long int stbcnt; /* stability limit exceeded (ro) */ + + /* ??? */ + int :32; int :32; int :32; int :32; + int :32; int :32; int :32; int :32; + int :32; int :32; int :32; int :32; +}; + +/* Mode codes (timex.mode) */ +#define ADJ_OFFSET 0x0001 /* time offset */ +#define ADJ_FREQUENCY 0x0002 /* frequency offset */ +#define ADJ_MAXERROR 0x0004 /* maximum time error */ +#define ADJ_ESTERROR 0x0008 /* estimated time error */ +#define ADJ_STATUS 0x0010 /* clock status */ +#define ADJ_TIMECONST 0x0020 /* pll time constant */ +#define ADJ_TICK 0x4000 /* tick value */ +#define ADJ_OFFSET_SINGLESHOT 0x8001 /* old-fashioned adjtime */ + +/* xntp 3.4 compatibility names */ +#define MOD_OFFSET ADJ_OFFSET +#define MOD_FREQUENCY ADJ_FREQUENCY +#define MOD_MAXERROR ADJ_MAXERROR +#define MOD_ESTERROR ADJ_ESTERROR +#define MOD_STATUS ADJ_STATUS +#define MOD_TIMECONST ADJ_TIMECONST +#define MOD_CLKB ADJ_TICK +#define MOD_CLKA ADJ_OFFSET_SINGLESHOT /* 0x8000 in original */ + + +/* Status codes (timex.status) */ +#define STA_PLL 0x0001 /* enable PLL updates (rw) */ +#define STA_PPSFREQ 0x0002 /* enable PPS freq discipline (rw) */ +#define STA_PPSTIME 0x0004 /* enable PPS time discipline (rw) */ +#define STA_FLL 0x0008 /* select frequency-lock mode (rw) */ + +#define STA_INS 0x0010 /* insert leap (rw) */ +#define STA_DEL 0x0020 /* delete leap (rw) */ +#define STA_UNSYNC 0x0040 /* clock unsynchronized (rw) */ +#define STA_FREQHOLD 0x0080 /* hold frequency (rw) */ + +#define STA_PPSSIGNAL 0x0100 /* PPS signal present (ro) */ +#define STA_PPSJITTER 0x0200 /* PPS signal jitter exceeded (ro) */ +#define STA_PPSWANDER 0x0400 /* PPS signal wander exceeded (ro) */ +#define STA_PPSERROR 0x0800 /* PPS signal calibration error (ro) */ + +#define STA_CLOCKERR 0x1000 /* clock hardware fault (ro) */ + +#define STA_RONLY (STA_PPSSIGNAL | STA_PPSJITTER | STA_PPSWANDER | \ + STA_PPSERROR | STA_CLOCKERR) /* read-only bits */ + +/* Clock states (time_state) */ +#define TIME_OK 0 /* clock synchronized, no leap second */ +#define TIME_INS 1 /* insert leap second */ +#define TIME_DEL 2 /* delete leap second */ +#define TIME_OOP 3 /* leap second in progress */ +#define TIME_WAIT 4 /* leap second has occurred */ +#define TIME_ERROR 5 /* clock not synchronized */ +#define TIME_BAD TIME_ERROR /* bw compat */ + +/* Maximum time constant of the PLL. */ +#define MAXTC 6 + +__BEGIN_DECLS + +#if 0 +extern int __adjtimex (struct timex *__ntx) __THROW; +#endif +extern int adjtimex (struct timex *__ntx) __THROW; +libc_hidden_proto(adjtimex) + +#if defined __UCLIBC_NTP_LEGACY__ +extern int ntp_gettime (struct ntptimeval *__ntv) __THROW; +extern int ntp_adjtime (struct timex *__tntx) __THROW; +#endif + +__END_DECLS + +#endif /* sys/timex.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/ttydefaults.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/ttydefaults.h new file mode 100644 index 00000000..bb605a45 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/ttydefaults.h @@ -0,0 +1,100 @@ +/*- + * Copyright (c) 1982, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ttydefaults.h 8.4 (Berkeley) 1/21/94 + */ + +/* + * System wide defaults for terminal state. Linux version. + */ +#ifndef _SYS_TTYDEFAULTS_H_ +#define _SYS_TTYDEFAULTS_H_ + +/* + * Defaults on "first" open. + */ +#define TTYDEF_IFLAG (BRKINT | ISTRIP | ICRNL | IMAXBEL | IXON | IXANY) +#define TTYDEF_OFLAG (OPOST | ONLCR | XTABS) +#define TTYDEF_LFLAG (ECHO | ICANON | ISIG | IEXTEN | ECHOE|ECHOKE|ECHOCTL) +#define TTYDEF_CFLAG (CREAD | CS7 | PARENB | HUPCL) +#define TTYDEF_SPEED (B9600) + +/* + * Control Character Defaults + */ +#define CTRL(x) (x&037) +#define CEOF CTRL('d') +#ifdef _POSIX_VDISABLE +# define CEOL _POSIX_VDISABLE +#else +# define CEOL '\0' /* XXX avoid _POSIX_VDISABLE */ +#endif +#define CERASE 0177 +#define CINTR CTRL('c') +#ifdef _POSIX_VDISABLE +# define CSTATUS _POSIX_VDISABLE +#else +# define CSTATUS '\0' /* XXX avoid _POSIX_VDISABLE */ +#endif +#define CKILL CTRL('u') +#define CMIN 1 +#define CQUIT 034 /* FS, ^\ */ +#define CSUSP CTRL('z') +#define CTIME 0 +#define CDSUSP CTRL('y') +#define CSTART CTRL('q') +#define CSTOP CTRL('s') +#define CLNEXT CTRL('v') +#define CDISCARD CTRL('o') +#define CWERASE CTRL('w') +#define CREPRINT CTRL('r') +#define CEOT CEOF +/* compat */ +#define CBRK CEOL +#define CRPRNT CREPRINT +#define CFLUSH CDISCARD + +/* PROTECTED INCLUSION ENDS HERE */ +#endif /* !_SYS_TTYDEFAULTS_H_ */ + +/* + * #define TTYDEFCHARS to include an array of default control characters. + */ +#ifdef TTYDEFCHARS +cc_t ttydefchars[NCCS] = { + CEOF, CEOL, CEOL, CERASE, CWERASE, CKILL, CREPRINT, + _POSIX_VDISABLE, CINTR, CQUIT, CSUSP, CDSUSP, CSTART, CSTOP, CLNEXT, + CDISCARD, CMIN, CTIME, CSTATUS, _POSIX_VDISABLE +}; +#undef TTYDEFCHARS +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/types.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/types.h new file mode 100644 index 00000000..7e29dc83 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/types.h @@ -0,0 +1,275 @@ +/* Copyright (C) 1991,1992,1994,1995,1996,1997,1998,1999,2000,2001,2002 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * POSIX Standard: 2.6 Primitive System Data Types + */ + +#ifndef _SYS_TYPES_H +#define _SYS_TYPES_H 1 + +#include + +__BEGIN_DECLS + +#include + +#ifdef __USE_BSD +# ifndef __u_char_defined +typedef __u_char u_char; +typedef __u_short u_short; +typedef __u_int u_int; +typedef __u_long u_long; +typedef __quad_t quad_t; +typedef __u_quad_t u_quad_t; +typedef __fsid_t fsid_t; +# define __u_char_defined +# endif +#endif + +typedef __loff_t loff_t; + +#ifndef __ino_t_defined +# ifndef __USE_FILE_OFFSET64 +typedef __ino_t ino_t; +# else +typedef __ino64_t ino_t; +# endif +# define __ino_t_defined +#endif +#if defined __USE_LARGEFILE64 && !defined __ino64_t_defined +typedef __ino64_t ino64_t; +# define __ino64_t_defined +#endif + +#ifndef __dev_t_defined +typedef __dev_t dev_t; +# define __dev_t_defined +#endif + +#ifndef __gid_t_defined +typedef __gid_t gid_t; +# define __gid_t_defined +#endif + +#ifndef __mode_t_defined +typedef __mode_t mode_t; +# define __mode_t_defined +#endif + +#ifndef __nlink_t_defined +typedef __nlink_t nlink_t; +# define __nlink_t_defined +#endif + +#ifndef __uid_t_defined +typedef __uid_t uid_t; +# define __uid_t_defined +#endif + +#ifndef __off_t_defined +# ifndef __USE_FILE_OFFSET64 +typedef __off_t off_t; +# else +typedef __off64_t off_t; +# endif +# define __off_t_defined +#endif +#if defined __USE_LARGEFILE64 && !defined __off64_t_defined +typedef __off64_t off64_t; +# define __off64_t_defined +#endif + +#ifndef __pid_t_defined +typedef __pid_t pid_t; +# define __pid_t_defined +#endif + +#if (defined __USE_SVID || defined __USE_XOPEN) && !defined __id_t_defined +typedef __id_t id_t; +# define __id_t_defined +#endif + +#ifndef __ssize_t_defined +typedef __ssize_t ssize_t; +# define __ssize_t_defined +#endif + +#ifdef __USE_BSD +# ifndef __daddr_t_defined +typedef __daddr_t daddr_t; +typedef __caddr_t caddr_t; +# define __daddr_t_defined +# endif +#endif + +#if (defined __USE_SVID || defined __USE_XOPEN) && !defined __key_t_defined +typedef __key_t key_t; +# define __key_t_defined +#endif + +#ifdef __USE_XOPEN +# define __need_clock_t +#endif +#define __need_time_t +#define __need_timer_t +#define __need_clockid_t +#include + +#ifdef __USE_XOPEN +# ifndef __useconds_t_defined +typedef __useconds_t useconds_t; +# define __useconds_t_defined +# endif +# ifndef __suseconds_t_defined +typedef __suseconds_t suseconds_t; +# define __suseconds_t_defined +# endif +#endif + +#define __need_size_t +#include + +#ifdef __USE_MISC +/* Old compatibility names for C types. */ +typedef unsigned long int ulong; +typedef unsigned short int ushort; +typedef unsigned int uint; +#endif + +/* These size-specific names are used by some of the inet code. */ + +#if !__GNUC_PREREQ (2, 7) + +/* These types are defined by the ISO C99 header . */ +# ifndef __int8_t_defined +# define __int8_t_defined +typedef char int8_t; +typedef short int int16_t; +typedef int int32_t; +# if __WORDSIZE == 64 +typedef long int int64_t; +# elif defined __GNUC__ || defined __ICC +__extension__ typedef long long int int64_t; +# endif +# endif + +/* But these were defined by ISO C without the first `_'. */ +typedef unsigned char u_int8_t; +typedef unsigned short int u_int16_t; +typedef unsigned int u_int32_t; +# if __WORDSIZE == 64 +typedef unsigned long int u_int64_t; +# elif defined __GNUC__ || defined __ICC +__extension__ typedef unsigned long long int u_int64_t; +# endif + +typedef int register_t; + +#else + +/* For GCC 2.7 and later, we can use specific type-size attributes. */ +# define __intN_t(N, MODE) \ + typedef int int##N##_t __attribute__ ((__mode__ (MODE))) +# define __u_intN_t(N, MODE) \ + typedef unsigned int u_int##N##_t __attribute__ ((__mode__ (MODE))) + +# ifndef __int8_t_defined +# define __int8_t_defined +__intN_t (8, __QI__); +__intN_t (16, __HI__); +__intN_t (32, __SI__); +__intN_t (64, __DI__); +# endif + +__u_intN_t (8, __QI__); +__u_intN_t (16, __HI__); +__u_intN_t (32, __SI__); +__u_intN_t (64, __DI__); + +typedef int register_t __attribute__ ((__mode__ (__word__))); + + +/* Some code from BIND tests this macro to see if the types above are + defined. */ +#endif +#define __BIT_TYPES_DEFINED__ 1 + + +#ifdef __USE_BSD +/* In BSD is expected to define BYTE_ORDER. */ +# include + +/* It also defines `fd_set' and the FD_* macros for `select'. */ +# include + +/* BSD defines these symbols, so we follow. */ +# include +#endif /* Use BSD. */ + + +#if defined __USE_UNIX98 && !defined __blksize_t_defined +typedef __blksize_t blksize_t; +# define __blksize_t_defined +#endif + +/* Types from the Large File Support interface. */ +#ifndef __USE_FILE_OFFSET64 +# ifndef __blkcnt_t_defined +typedef __blkcnt_t blkcnt_t; /* Type to count number of disk blocks. */ +# define __blkcnt_t_defined +# endif +# ifndef __fsblkcnt_t_defined +typedef __fsblkcnt_t fsblkcnt_t; /* Type to count file system blocks. */ +# define __fsblkcnt_t_defined +# endif +# ifndef __fsfilcnt_t_defined +typedef __fsfilcnt_t fsfilcnt_t; /* Type to count file system inodes. */ +# define __fsfilcnt_t_defined +# endif +#else +# ifndef __blkcnt_t_defined +typedef __blkcnt64_t blkcnt_t; /* Type to count number of disk blocks. */ +# define __blkcnt_t_defined +# endif +# ifndef __fsblkcnt_t_defined +typedef __fsblkcnt64_t fsblkcnt_t; /* Type to count file system blocks. */ +# define __fsblkcnt_t_defined +# endif +# ifndef __fsfilcnt_t_defined +typedef __fsfilcnt64_t fsfilcnt_t; /* Type to count file system inodes. */ +# define __fsfilcnt_t_defined +# endif +#endif + +#ifdef __USE_LARGEFILE64 +typedef __blkcnt64_t blkcnt64_t; /* Type to count number of disk blocks. */ +typedef __fsblkcnt64_t fsblkcnt64_t; /* Type to count file system blocks. */ +typedef __fsfilcnt64_t fsfilcnt64_t; /* Type to count file system inodes. */ +#endif + + +/* Now add the thread types. */ +#if (defined __USE_POSIX199506 || defined __USE_UNIX98) && defined __UCLIBC_HAS_THREADS__ +# include +#endif + +__END_DECLS + +#endif /* sys/types.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/uio.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/uio.h new file mode 100644 index 00000000..1b203f71 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/uio.h @@ -0,0 +1,54 @@ +/* Copyright (C) 1991, 92, 96, 97, 98, 99, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_UIO_H +#define _SYS_UIO_H 1 + +#include + +#include + +__BEGIN_DECLS + +/* This file defines `struct iovec'. */ +#include + + +/* Read data from file descriptor FD, and put the result in the + buffers described by IOVEC, which is a vector of COUNT `struct iovec's. + The buffers are filled in the order specified. + Operates just like `read' (see ) except that data are + put in IOVEC instead of a contiguous buffer. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern ssize_t readv (int __fd, __const struct iovec *__iovec, int __count); + +/* Write data pointed by the buffers described by IOVEC, which + is a vector of COUNT `struct iovec's, to file descriptor FD. + The data is written in the order specified. + Operates just like `write' (see ) except that the data + are taken from IOVEC instead of a contiguous buffer. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern ssize_t writev (int __fd, __const struct iovec *__iovec, int __count); + +__END_DECLS + +#endif /* sys/uio.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/un.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/un.h new file mode 100644 index 00000000..1fa10e4f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/un.h @@ -0,0 +1,47 @@ +/* Copyright (C) 1991, 1995, 1996, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_UN_H +#define _SYS_UN_H 1 + +#include + +/* Get the definition of the macro to define the common sockaddr members. */ +#include + +__BEGIN_DECLS + +/* Structure describing the address of an AF_LOCAL (aka AF_UNIX) socket. */ +struct sockaddr_un + { + __SOCKADDR_COMMON (sun_); + char sun_path[108]; /* Path name. */ + }; + + +#ifdef __USE_MISC +# include /* For prototype of `strlen'. */ + +/* Evaluate to actual length of the `sockaddr_un' structure. */ +# define SUN_LEN(ptr) ((size_t) (((struct sockaddr_un *) 0)->sun_path) \ + + strlen ((ptr)->sun_path)) +#endif + +__END_DECLS + +#endif /* sys/un.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/unistd.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/unistd.h new file mode 100644 index 00000000..1e823fbd --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/unistd.h @@ -0,0 +1 @@ +#include diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/ustat.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/ustat.h new file mode 100644 index 00000000..7a9cdac0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/ustat.h @@ -0,0 +1,38 @@ +/* Header describing obsolete `ustat' interface. + Copyright (C) 1996, 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * This interface is obsolete. Use instead. + */ + +#ifndef _SYS_USTAT_H +#define _SYS_USTAT_H 1 + +#include + +#include +#include + +__BEGIN_DECLS + +extern int ustat (__dev_t __dev, struct ustat *__ubuf) __THROW; + +__END_DECLS + +#endif /* sys/ustat.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/utsname.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/utsname.h new file mode 100644 index 00000000..7b57888c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/utsname.h @@ -0,0 +1,88 @@ +/* Copyright (C) 1991,92,94,96,97,99,2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * POSIX Standard: 4.4 System Identification + */ + +#ifndef _SYS_UTSNAME_H +#define _SYS_UTSNAME_H 1 + +#include + +__BEGIN_DECLS + +#include + +#ifndef _UTSNAME_SYSNAME_LENGTH +# define _UTSNAME_SYSNAME_LENGTH _UTSNAME_LENGTH +#endif +#ifndef _UTSNAME_NODENAME_LENGTH +# define _UTSNAME_NODENAME_LENGTH _UTSNAME_LENGTH +#endif +#ifndef _UTSNAME_RELEASE_LENGTH +# define _UTSNAME_RELEASE_LENGTH _UTSNAME_LENGTH +#endif +#ifndef _UTSNAME_VERSION_LENGTH +# define _UTSNAME_VERSION_LENGTH _UTSNAME_LENGTH +#endif +#ifndef _UTSNAME_MACHINE_LENGTH +# define _UTSNAME_MACHINE_LENGTH _UTSNAME_LENGTH +#endif + +/* Structure describing the system and machine. */ +struct utsname + { + /* Name of the implementation of the operating system. */ + char sysname[_UTSNAME_SYSNAME_LENGTH]; + + /* Name of this node on the network. */ + char nodename[_UTSNAME_NODENAME_LENGTH]; + + /* Current release level of this implementation. */ + char release[_UTSNAME_RELEASE_LENGTH]; + /* Current version level of this release. */ + char version[_UTSNAME_VERSION_LENGTH]; + + /* Name of the hardware type the system is running on. */ + char machine[_UTSNAME_MACHINE_LENGTH]; + +#if _UTSNAME_DOMAIN_LENGTH - 0 + /* Name of the domain of this node on the network. */ +# ifdef __USE_GNU + char domainname[_UTSNAME_DOMAIN_LENGTH]; +# else + char __domainname[_UTSNAME_DOMAIN_LENGTH]; +# endif +#endif + }; + +#ifdef __USE_SVID +/* Note that SVID assumes all members have the same size. */ +# define SYS_NMLN _UTSNAME_LENGTH +#endif + + +/* Put information about the system in NAME. */ +extern int uname (struct utsname *__name) __THROW; +libc_hidden_proto(uname) + + +__END_DECLS + +#endif /* sys/utsname.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/vfs.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/vfs.h new file mode 100644 index 00000000..fa22d31c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/vfs.h @@ -0,0 +1,4 @@ +/* Other systems declare `struct statfs' et al in , + so we have this file to be compatible with programs expecting it. */ + +#include diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/vt.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/vt.h new file mode 100644 index 00000000..834abfbc --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/vt.h @@ -0,0 +1 @@ +#include diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/wait.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/wait.h new file mode 100644 index 00000000..f283fe22 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/wait.h @@ -0,0 +1,188 @@ +/* Copyright (C) 1991-1994,1996-2001,2003,2004,2005 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * POSIX Standard: 3.2.1 Wait for Process Termination + */ + +#ifndef _SYS_WAIT_H +#define _SYS_WAIT_H 1 + +#include + +__BEGIN_DECLS + +#include +#include + +/* These macros could also be defined in . */ +#if !defined _STDLIB_H || !defined __USE_XOPEN +/* This will define the `W*' macros for the flag + bits to `waitpid', `wait3', and `wait4'. */ +# include + +# ifdef __USE_BSD + +/* Lots of hair to allow traditional BSD use of `union wait' + as well as POSIX.1 use of `int' for the status word. */ + +# if defined __GNUC__ && !defined __cplusplus +# define __WAIT_INT(status) \ + (__extension__ (((union { __typeof(status) __in; int __i; }) \ + { .__in = (status) }).__i)) +# else +# define __WAIT_INT(status) (*(__const int *) &(status)) +# endif + +/* This is the type of the argument to `wait'. The funky union + causes redeclarations with ether `int *' or `union wait *' to be + allowed without complaint. __WAIT_STATUS_DEFN is the type used in + the actual function definitions. */ + +# if !defined __GNUC__ || __GNUC__ < 2 || defined __cplusplus +# define __WAIT_STATUS void * +# define __WAIT_STATUS_DEFN void * +# else +/* This works in GCC 2.6.1 and later. */ +typedef union + { + union wait *__uptr; + int *__iptr; + } __WAIT_STATUS __attribute__ ((__transparent_union__)); +# define __WAIT_STATUS_DEFN int * +# endif + +# else /* Don't use BSD. */ + +# define __WAIT_INT(status) (status) +# define __WAIT_STATUS int * +# define __WAIT_STATUS_DEFN int * + +# endif /* Use BSD. */ + +/* This will define all the `__W*' macros. */ +# include + +# define WEXITSTATUS(status) __WEXITSTATUS(__WAIT_INT(status)) +# define WTERMSIG(status) __WTERMSIG(__WAIT_INT(status)) +# define WSTOPSIG(status) __WSTOPSIG(__WAIT_INT(status)) +# define WIFEXITED(status) __WIFEXITED(__WAIT_INT(status)) +# define WIFSIGNALED(status) __WIFSIGNALED(__WAIT_INT(status)) +# define WIFSTOPPED(status) __WIFSTOPPED(__WAIT_INT(status)) +# ifdef __WIFCONTINUED +# define WIFCONTINUED(status) __WIFCONTINUED(__WAIT_INT(status)) +# endif +#endif /* not included. */ + +#ifdef __USE_BSD +# define WCOREFLAG __WCOREFLAG +# define WCOREDUMP(status) __WCOREDUMP(__WAIT_INT(status)) +# define W_EXITCODE(ret, sig) __W_EXITCODE(ret, sig) +# define W_STOPCODE(sig) __W_STOPCODE(sig) +#endif + +/* The following values are used by the `waitid' function. */ +#if defined __USE_SVID || defined __USE_XOPEN +typedef enum +{ + P_ALL, /* Wait for any child. */ + P_PID, /* Wait for specified process. */ + P_PGID /* Wait for members of process group. */ +} idtype_t; +#endif + + +/* Wait for a child to die. When one does, put its status in *STAT_LOC + and return its process ID. For errors, return (pid_t) -1. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern __pid_t wait (__WAIT_STATUS __stat_loc); + +#ifdef __USE_BSD +/* Special values for the PID argument to `waitpid' and `wait4'. */ +# define WAIT_ANY (-1) /* Any process. */ +# define WAIT_MYPGRP 0 /* Any process in my process group. */ +#endif + +/* Wait for a child matching PID to die. + If PID is greater than 0, match any process whose process ID is PID. + If PID is (pid_t) -1, match any process. + If PID is (pid_t) 0, match any process with the + same process group as the current process. + If PID is less than -1, match any process whose + process group is the absolute value of PID. + If the WNOHANG bit is set in OPTIONS, and that child + is not already dead, return (pid_t) 0. If successful, + return PID and store the dead child's status in STAT_LOC. + Return (pid_t) -1 for errors. If the WUNTRACED bit is + set in OPTIONS, return status for stopped children; otherwise don't. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern __pid_t waitpid (__pid_t __pid, int *__stat_loc, int __options); +libc_hidden_proto(waitpid) + +#if defined __USE_SVID || defined __USE_XOPEN +# define __need_siginfo_t +# include +/* Wait for a childing matching IDTYPE and ID to change the status and + place appropriate information in *INFOP. + If IDTYPE is P_PID, match any process whose process ID is ID. + If IDTYPE is P_PGID, match any process whose process group is ID. + If IDTYPE is P_ALL, match any process. + If the WNOHANG bit is set in OPTIONS, and that child + is not already dead, clear *INFOP and return 0. If successful, store + exit code and status in *INFOP. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern int waitid (idtype_t __idtype, __id_t __id, siginfo_t *__infop, + int __options); +#endif + +#if defined __USE_BSD || defined __USE_XOPEN_EXTENDED +/* This being here makes the prototypes valid whether or not + we have already included to define `struct rusage'. */ +struct rusage; + +/* Wait for a child to exit. When one does, put its status in *STAT_LOC and + return its process ID. For errors return (pid_t) -1. If USAGE is not + nil, store information about the child's resource usage there. If the + WUNTRACED bit is set in OPTIONS, return status for stopped children; + otherwise don't. */ +extern __pid_t wait3 (__WAIT_STATUS __stat_loc, int __options, + struct rusage * __usage) __THROW; +#endif + +#ifdef __USE_BSD +/* This being here makes the prototypes valid whether or not + we have already included to define `struct rusage'. */ +struct rusage; + +/* PID is like waitpid. Other args are like wait3. */ +extern __pid_t wait4 (__pid_t __pid, __WAIT_STATUS __stat_loc, int __options, + struct rusage *__usage) __THROW; +libc_hidden_proto(wait4) +#endif /* Use BSD. */ + + +__END_DECLS + +#endif /* sys/wait.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/xattr.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/xattr.h new file mode 100644 index 00000000..2737f90b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/sys/xattr.h @@ -0,0 +1,104 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_XATTR_H +#define _SYS_XATTR_H 1 + +#include +#include + + +__BEGIN_DECLS + +/* The following constants should be used for the fifth parameter of + `*setxattr'. */ +enum +{ + XATTR_CREATE = 1, /* set value, fail if attr already exists. */ +#define XATTR_CREATE XATTR_CREATE + XATTR_REPLACE = 2 /* set value, fail if attr does not exist. */ +#define XATTR_REPLACE XATTR_REPLACE +}; + +/* Set the attribute NAME of the file pointed to by PATH to VALUE (which + is SIZE bytes long). Return 0 on success, -1 for errors. */ +extern int setxattr (__const char *__path, __const char *__name, + __const void *__value, size_t __size, int __flags) + __THROW; + +/* Set the attribute NAME of the file pointed to by PATH to VALUE (which is + SIZE bytes long), not following symlinks for the last pathname component. + Return 0 on success, -1 for errors. */ +extern int lsetxattr (__const char *__path, __const char *__name, + __const void *__value, size_t __size, int __flags) + __THROW; + +/* Set the attribute NAME of the file descriptor FD to VALUE (which is SIZE + bytes long). Return 0 on success, -1 for errors. */ +extern int fsetxattr (int __fd, __const char *__name, __const void *__value, + size_t __size, int __flags) __THROW; + +/* Get the attribute NAME of the file pointed to by PATH to VALUE (which is + SIZE bytes long). Return 0 on success, -1 for errors. */ +extern ssize_t getxattr (__const char *__path, __const char *__name, + void *__value, size_t __size) __THROW; + +/* Get the attribute NAME of the file pointed to by PATH to VALUE (which is + SIZE bytes long), not following symlinks for the last pathname component. + Return 0 on success, -1 for errors. */ +extern ssize_t lgetxattr (__const char *__path, __const char *__name, + void *__value, size_t __size) __THROW; + +/* Get the attribute NAME of the file descriptor FD to VALUE (which is SIZE + bytes long). Return 0 on success, -1 for errors. */ +extern ssize_t fgetxattr (int __fd, __const char *__name, void *__value, + size_t __size) __THROW; + +/* List attributes of the file pointed to by PATH into the user-supplied + buffer LIST (which is SIZE bytes big). Return 0 on success, -1 for + errors. */ +extern ssize_t listxattr (__const char *__path, char *__list, size_t __size) + __THROW; + +/* List attributes of the file pointed to by PATH into the user-supplied + buffer LIST (which is SIZE bytes big), not following symlinks for the + last pathname component. Return 0 on success, -1 for errors. */ +extern ssize_t llistxattr (__const char *__path, char *__list, size_t __size) + __THROW; + +/* List attributes of the file descriptor FD into the user-supplied buffer + LIST (which is SIZE bytes big). Return 0 on success, -1 for errors. */ +extern ssize_t flistxattr (int __fd, char *__list, size_t __size) + __THROW; + +/* Remove the attribute NAME from the file pointed to by PATH. Return 0 + on success, -1 for errors. */ +extern int removexattr (__const char *__path, __const char *__name) __THROW; + +/* Remove the attribute NAME from the file pointed to by PATH, not + following symlinks for the last pathname component. Return 0 on + success, -1 for errors. */ +extern int lremovexattr (__const char *__path, __const char *__name) __THROW; + +/* Remove the attribute NAME from the file descriptor FD. Return 0 on + success, -1 for errors. */ +extern int fremovexattr (int __fd, __const char *__name) __THROW; + +__END_DECLS + +#endif /* sys/xattr.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/syscall.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/syscall.h new file mode 100644 index 00000000..4c305784 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/syscall.h @@ -0,0 +1 @@ +#include diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/sysexits.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/sysexits.h new file mode 100644 index 00000000..37246b6e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/sysexits.h @@ -0,0 +1,114 @@ +/* + * Copyright (c) 1987, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)sysexits.h 8.1 (Berkeley) 6/2/93 + */ + +#ifndef _SYSEXITS_H +#define _SYSEXITS_H 1 + +/* + * SYSEXITS.H -- Exit status codes for system programs. + * + * This include file attempts to categorize possible error + * exit statuses for system programs, notably delivermail + * and the Berkeley network. + * + * Error numbers begin at EX__BASE to reduce the possibility of + * clashing with other exit statuses that random programs may + * already return. The meaning of the codes is approximately + * as follows: + * + * EX_USAGE -- The command was used incorrectly, e.g., with + * the wrong number of arguments, a bad flag, a bad + * syntax in a parameter, or whatever. + * EX_DATAERR -- The input data was incorrect in some way. + * This should only be used for user's data & not + * system files. + * EX_NOINPUT -- An input file (not a system file) did not + * exist or was not readable. This could also include + * errors like "No message" to a mailer (if it cared + * to catch it). + * EX_NOUSER -- The user specified did not exist. This might + * be used for mail addresses or remote logins. + * EX_NOHOST -- The host specified did not exist. This is used + * in mail addresses or network requests. + * EX_UNAVAILABLE -- A service is unavailable. This can occur + * if a support program or file does not exist. This + * can also be used as a catchall message when something + * you wanted to do doesn't work, but you don't know + * why. + * EX_SOFTWARE -- An internal software error has been detected. + * This should be limited to non-operating system related + * errors as possible. + * EX_OSERR -- An operating system error has been detected. + * This is intended to be used for such things as "cannot + * fork", "cannot create pipe", or the like. It includes + * things like getuid returning a user that does not + * exist in the passwd file. + * EX_OSFILE -- Some system file (e.g., /etc/passwd, /etc/utmp, + * etc.) does not exist, cannot be opened, or has some + * sort of error (e.g., syntax error). + * EX_CANTCREAT -- A (user specified) output file cannot be + * created. + * EX_IOERR -- An error occurred while doing I/O on some file. + * EX_TEMPFAIL -- temporary failure, indicating something that + * is not really an error. In sendmail, this means + * that a mailer (e.g.) could not create a connection, + * and the request should be reattempted later. + * EX_PROTOCOL -- the remote system returned something that + * was "not possible" during a protocol exchange. + * EX_NOPERM -- You did not have sufficient permission to + * perform the operation. This is not intended for + * file system problems, which should use NOINPUT or + * CANTCREAT, but rather for higher level permissions. + */ + +#define EX_OK 0 /* successful termination */ + +#define EX__BASE 64 /* base value for error messages */ + +#define EX_USAGE 64 /* command line usage error */ +#define EX_DATAERR 65 /* data format error */ +#define EX_NOINPUT 66 /* cannot open input */ +#define EX_NOUSER 67 /* addressee unknown */ +#define EX_NOHOST 68 /* host name unknown */ +#define EX_UNAVAILABLE 69 /* service unavailable */ +#define EX_SOFTWARE 70 /* internal software error */ +#define EX_OSERR 71 /* system error (e.g., can't fork) */ +#define EX_OSFILE 72 /* critical OS file missing */ +#define EX_CANTCREAT 73 /* can't create (user) output file */ +#define EX_IOERR 74 /* input/output error */ +#define EX_TEMPFAIL 75 /* temp failure; user is invited to retry */ +#define EX_PROTOCOL 76 /* remote error in protocol */ +#define EX_NOPERM 77 /* permission denied */ +#define EX_CONFIG 78 /* configuration error */ + +#define EX__MAX 78 /* maximum listed value */ + +#endif /* sysexits.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/syslog.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/syslog.h new file mode 100644 index 00000000..830b4928 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/syslog.h @@ -0,0 +1 @@ +#include diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/tar.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/tar.h new file mode 100644 index 00000000..ddfef755 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/tar.h @@ -0,0 +1,108 @@ +/* Extended tar format from POSIX.1. + Copyright (C) 1992, 1996 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Written by David J. MacKenzie. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _TAR_H +#define _TAR_H 1 + +/* A tar archive consists of 512-byte blocks. + Each file in the archive has a header block followed by 0+ data blocks. + Two blocks of NUL bytes indicate the end of the archive. */ + +/* The fields of header blocks: + All strings are stored as ISO 646 (approximately ASCII) strings. + + Fields are numeric unless otherwise noted below; numbers are ISO 646 + representations of octal numbers, with leading zeros as needed. + + linkname is only valid when typeflag==LNKTYPE. It doesn't use prefix; + files that are links to pathnames >100 chars long can not be stored + in a tar archive. + + If typeflag=={LNKTYPE,SYMTYPE,DIRTYPE} then size must be 0. + + devmajor and devminor are only valid for typeflag=={BLKTYPE,CHRTYPE}. + + chksum contains the sum of all 512 bytes in the header block, + treating each byte as an 8-bit unsigned value and treating the + 8 bytes of chksum as blank characters. + + uname and gname are used in preference to uid and gid, if those + names exist locally. + + Field Name Byte Offset Length in Bytes Field Type + name 0 100 NUL-terminated if NUL fits + mode 100 8 + uid 108 8 + gid 116 8 + size 124 12 + mtime 136 12 + chksum 148 8 + typeflag 156 1 see below + linkname 157 100 NUL-terminated if NUL fits + magic 257 6 must be TMAGIC (NUL term.) + version 263 2 must be TVERSION + uname 265 32 NUL-terminated + gname 297 32 NUL-terminated + devmajor 329 8 + devminor 337 8 + prefix 345 155 NUL-terminated if NUL fits + + If the first character of prefix is '\0', the file name is name; + otherwise, it is prefix/name. Files whose pathnames don't fit in that + length can not be stored in a tar archive. */ + +/* The bits in mode: */ +#define TSUID 04000 +#define TSGID 02000 +#define TSVTX 01000 +#define TUREAD 00400 +#define TUWRITE 00200 +#define TUEXEC 00100 +#define TGREAD 00040 +#define TGWRITE 00020 +#define TGEXEC 00010 +#define TOREAD 00004 +#define TOWRITE 00002 +#define TOEXEC 00001 + +/* The values for typeflag: + Values 'A'-'Z' are reserved for custom implementations. + All other values are reserved for future POSIX.1 revisions. */ + +#define REGTYPE '0' /* Regular file (preferred code). */ +#define AREGTYPE '\0' /* Regular file (alternate code). */ +#define LNKTYPE '1' /* Hard link. */ +#define SYMTYPE '2' /* Symbolic link (hard if not supported). */ +#define CHRTYPE '3' /* Character special. */ +#define BLKTYPE '4' /* Block special. */ +#define DIRTYPE '5' /* Directory. */ +#define FIFOTYPE '6' /* Named pipe. */ +#define CONTTYPE '7' /* Contiguous file */ + /* (regular file if not supported). */ + +/* Contents of magic field and its length. */ +#define TMAGIC "ustar" +#define TMAGLEN 6 + +/* Contents of the version field and its length. */ +#define TVERSION "00" +#define TVERSLEN 2 + +#endif /* tar.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/termio.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/termio.h new file mode 100644 index 00000000..0e610f0c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/termio.h @@ -0,0 +1,6 @@ +/* Compatible for old `struct termio' ioctl interface. + This is obsolete; use the POSIX.1 `struct termios' interface + defined in instead. */ + +#include +#include diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/termios.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/termios.h new file mode 100644 index 00000000..512e5842 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/termios.h @@ -0,0 +1,114 @@ +/* Copyright (C) 1991,92,93,94,96,97,98,99, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * POSIX Standard: 7.1-2 General Terminal Interface + */ + +#ifndef _TERMIOS_H +#define _TERMIOS_H 1 + +#include +#ifdef __USE_UNIX98 +/* We need `pid_t'. */ +# include +# ifndef __pid_t_defined +typedef __pid_t pid_t; +# define __pid_t_defined +# endif +#endif + +__BEGIN_DECLS + +/* Get the system-dependent definitions of `struct termios', `tcflag_t', + `cc_t', `speed_t', and all the macros specifying the flag bits. */ +#include + +#ifdef __USE_BSD +/* Compare a character C to a value VAL from the `c_cc' array in a + `struct termios'. If VAL is _POSIX_VDISABLE, no character can match it. */ +# define CCEQ(val, c) ((c) == (val) && (val) != _POSIX_VDISABLE) +#endif + +/* Return the output baud rate stored in *TERMIOS_P. */ +extern speed_t cfgetospeed (__const struct termios *__termios_p) __THROW; + +/* Return the input baud rate stored in *TERMIOS_P. */ +extern speed_t cfgetispeed (__const struct termios *__termios_p) __THROW; + +/* Set the output baud rate stored in *TERMIOS_P to SPEED. */ +extern int cfsetospeed (struct termios *__termios_p, speed_t __speed) __THROW; +libc_hidden_proto(cfsetospeed) + +/* Set the input baud rate stored in *TERMIOS_P to SPEED. */ +extern int cfsetispeed (struct termios *__termios_p, speed_t __speed) __THROW; +libc_hidden_proto(cfsetispeed) + +#ifdef __USE_BSD +/* Set both the input and output baud rates in *TERMIOS_OP to SPEED. */ +extern int cfsetspeed (struct termios *__termios_p, speed_t __speed) __THROW; +#endif + + +/* Put the state of FD into *TERMIOS_P. */ +extern int tcgetattr (int __fd, struct termios *__termios_p) __THROW; +libc_hidden_proto(tcgetattr) + +/* Set the state of FD to *TERMIOS_P. + Values for OPTIONAL_ACTIONS (TCSA*) are in . */ +extern int tcsetattr (int __fd, int __optional_actions, + __const struct termios *__termios_p) __THROW; +libc_hidden_proto(tcsetattr) + + +#ifdef __USE_BSD +/* Set *TERMIOS_P to indicate raw mode. */ +extern void cfmakeraw (struct termios *__termios_p) __THROW; +#endif + +/* Send zero bits on FD. */ +extern int tcsendbreak (int __fd, int __duration) __THROW; + +/* Wait for pending output to be written on FD. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern int tcdrain (int __fd); + +/* Flush pending data on FD. + Values for QUEUE_SELECTOR (TC{I,O,IO}FLUSH) are in . */ +extern int tcflush (int __fd, int __queue_selector) __THROW; + +/* Suspend or restart transmission on FD. + Values for ACTION (TC[IO]{OFF,ON}) are in . */ +extern int tcflow (int __fd, int __action) __THROW; + + +#ifdef __USE_UNIX98 +/* Get process group ID for session leader for controlling terminal FD. */ +extern __pid_t tcgetsid (int __fd) __THROW; +#endif + + +#ifdef __USE_BSD +# include +#endif + +__END_DECLS + +#endif /* termios.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/tgmath.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/tgmath.h new file mode 100644 index 00000000..fc9c9ffa --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/tgmath.h @@ -0,0 +1,432 @@ +/* Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * ISO C99 Standard: 7.22 Type-generic math + */ + +#ifndef _TGMATH_H +#define _TGMATH_H 1 + +/* Include the needed headers. */ +#include +#include + + +/* Since `complex' is currently not really implemented in most C compilers + and if it is implemented, the implementations differ. This makes it + quite difficult to write a generic implementation of this header. We + do not try this for now and instead concentrate only on GNU CC. Once + we have more information support for other compilers might follow. */ + +#if __GNUC_PREREQ (2, 7) + +# ifdef __NO_LONG_DOUBLE_MATH +# define __tgml(fct) fct +# else +# define __tgml(fct) fct ## l +# endif + +/* This is ugly but unless gcc gets appropriate builtins we have to do + something like this. Don't ask how it works. */ + +/* 1 if 'type' is a floating type, 0 if 'type' is an integer type. + Allows for _Bool. Expands to an integer constant expression. */ +# define __floating_type(type) (((type) 0.25) && ((type) 0.25 - 1)) + +/* The tgmath real type for T, where E is 0 if T is an integer type and + 1 for a floating type. */ +# define __tgmath_real_type_sub(T, E) \ + __typeof__(*(0 ? (__typeof__ (0 ? (double *) 0 : (void *) (E))) 0 \ + : (__typeof__ (0 ? (T *) 0 : (void *) (!(E)))) 0)) + +/* The tgmath real type of EXPR. */ +# define __tgmath_real_type(expr) \ + __tgmath_real_type_sub(__typeof__(expr), __floating_type(__typeof__(expr))) + + +/* We have two kinds of generic macros: to support functions which are + only defined on real valued parameters and those which are defined + for complex functions as well. */ +# define __TGMATH_UNARY_REAL_ONLY(Val, Fct) \ + (__extension__ ({ __tgmath_real_type (Val) __tgmres; \ + if (sizeof (Val) == sizeof (double) \ + || __builtin_classify_type (Val) != 8) \ + __tgmres = Fct (Val); \ + else if (sizeof (Val) == sizeof (float)) \ + __tgmres = Fct##f (Val); \ + else \ + __tgmres = __tgml(Fct) (Val); \ + __tgmres; })) + +# define __TGMATH_BINARY_FIRST_REAL_ONLY(Val1, Val2, Fct) \ + (__extension__ ({ __tgmath_real_type (Val1) __tgmres; \ + if (sizeof (Val1) == sizeof (double) \ + || __builtin_classify_type (Val1) != 8) \ + __tgmres = Fct (Val1, Val2); \ + else if (sizeof (Val1) == sizeof (float)) \ + __tgmres = Fct##f (Val1, Val2); \ + else \ + __tgmres = __tgml(Fct) (Val1, Val2); \ + __tgmres; })) + +# define __TGMATH_BINARY_REAL_ONLY(Val1, Val2, Fct) \ + (__extension__ ({ __tgmath_real_type ((Val1) + (Val2)) __tgmres; \ + if ((sizeof (Val1) > sizeof (double) \ + || sizeof (Val2) > sizeof (double)) \ + && __builtin_classify_type ((Val1) + (Val2)) == 8) \ + __tgmres = __tgml(Fct) (Val1, Val2); \ + else if (sizeof (Val1) == sizeof (double) \ + || sizeof (Val2) == sizeof (double) \ + || __builtin_classify_type (Val1) != 8 \ + || __builtin_classify_type (Val2) != 8) \ + __tgmres = Fct (Val1, Val2); \ + else \ + __tgmres = Fct##f (Val1, Val2); \ + __tgmres; })) + +# define __TGMATH_TERNARY_FIRST_SECOND_REAL_ONLY(Val1, Val2, Val3, Fct) \ + (__extension__ ({ __tgmath_real_type ((Val1) + (Val2)) __tgmres; \ + if ((sizeof (Val1) > sizeof (double) \ + || sizeof (Val2) > sizeof (double)) \ + && __builtin_classify_type ((Val1) + (Val2)) == 8) \ + __tgmres = __tgml(Fct) (Val1, Val2, Val3); \ + else if (sizeof (Val1) == sizeof (double) \ + || sizeof (Val2) == sizeof (double) \ + || __builtin_classify_type (Val1) != 8 \ + || __builtin_classify_type (Val2) != 8) \ + __tgmres = Fct (Val1, Val2, Val3); \ + else \ + __tgmres = Fct##f (Val1, Val2, Val3); \ + __tgmres; })) + +# define __TGMATH_TERNARY_REAL_ONLY(Val1, Val2, Val3, Fct) \ + (__extension__ ({ __tgmath_real_type ((Val1) + (Val2) + (Val3)) __tgmres;\ + if ((sizeof (Val1) > sizeof (double) \ + || sizeof (Val2) > sizeof (double) \ + || sizeof (Val3) > sizeof (double)) \ + && __builtin_classify_type ((Val1) + (Val2) \ + + (Val3)) == 8) \ + __tgmres = __tgml(Fct) (Val1, Val2, Val3); \ + else if (sizeof (Val1) == sizeof (double) \ + || sizeof (Val2) == sizeof (double) \ + || sizeof (Val3) == sizeof (double) \ + || __builtin_classify_type (Val1) != 8 \ + || __builtin_classify_type (Val2) != 8 \ + || __builtin_classify_type (Val3) != 8) \ + __tgmres = Fct (Val1, Val2, Val3); \ + else \ + __tgmres = Fct##f (Val1, Val2, Val3); \ + __tgmres; })) + +/* XXX This definition has to be changed as soon as the compiler understands + the imaginary keyword. */ +# define __TGMATH_UNARY_REAL_IMAG(Val, Fct, Cfct) \ + (__extension__ ({ __tgmath_real_type (Val) __tgmres; \ + if (sizeof (__real__ (Val)) > sizeof (double) \ + && __builtin_classify_type (__real__ (Val)) == 8) \ + { \ + if (sizeof (__real__ (Val)) == sizeof (Val)) \ + __tgmres = __tgml(Fct) (Val); \ + else \ + __tgmres = __tgml(Cfct) (Val); \ + } \ + else if (sizeof (__real__ (Val)) == sizeof (double) \ + || __builtin_classify_type (__real__ (Val)) \ + != 8) \ + { \ + if (sizeof (__real__ (Val)) == sizeof (Val)) \ + __tgmres = Fct (Val); \ + else \ + __tgmres = Cfct (Val); \ + } \ + else \ + { \ + if (sizeof (__real__ (Val)) == sizeof (Val)) \ + __tgmres = Fct##f (Val); \ + else \ + __tgmres = Cfct##f (Val); \ + } \ + __tgmres; })) + +/* XXX This definition has to be changed as soon as the compiler understands + the imaginary keyword. */ +# define __TGMATH_UNARY_IMAG_ONLY(Val, Fct) \ + (__extension__ ({ __tgmath_real_type (Val) __tgmres; \ + if (sizeof (Val) == sizeof (__complex__ double) \ + || __builtin_classify_type (__real__ (Val)) != 8) \ + __tgmres = Fct (Val); \ + else if (sizeof (Val) == sizeof (__complex__ float)) \ + __tgmres = Fct##f (Val); \ + else \ + __tgmres = __tgml(Fct) (Val); \ + __tgmres; })) + +/* XXX This definition has to be changed as soon as the compiler understands + the imaginary keyword. */ +# define __TGMATH_BINARY_REAL_IMAG(Val1, Val2, Fct, Cfct) \ + (__extension__ ({ __tgmath_real_type ((Val1) + (Val2)) __tgmres; \ + if ((sizeof (__real__ (Val1)) > sizeof (double) \ + || sizeof (__real__ (Val2)) > sizeof (double)) \ + && __builtin_classify_type (__real__ (Val1) \ + + __real__ (Val2)) \ + == 8) \ + { \ + if (sizeof (__real__ (Val1)) == sizeof (Val1) \ + && sizeof (__real__ (Val2)) == sizeof (Val2)) \ + __tgmres = __tgml(Fct) (Val1, Val2); \ + else \ + __tgmres = __tgml(Cfct) (Val1, Val2); \ + } \ + else if (sizeof (__real__ (Val1)) == sizeof (double) \ + || sizeof (__real__ (Val2)) == sizeof(double) \ + || (__builtin_classify_type (__real__ (Val1)) \ + != 8) \ + || (__builtin_classify_type (__real__ (Val2)) \ + != 8)) \ + { \ + if (sizeof (__real__ (Val1)) == sizeof (Val1) \ + && sizeof (__real__ (Val2)) == sizeof (Val2)) \ + __tgmres = Fct (Val1, Val2); \ + else \ + __tgmres = Cfct (Val1, Val2); \ + } \ + else \ + { \ + if (sizeof (__real__ (Val1)) == sizeof (Val1) \ + && sizeof (__real__ (Val2)) == sizeof (Val2)) \ + __tgmres = Fct##f (Val1, Val2); \ + else \ + __tgmres = Cfct##f (Val1, Val2); \ + } \ + __tgmres; })) +#else +# error "Unsupported compiler; you cannot use " +#endif + + +/* Unary functions defined for real and complex values. */ + + +/* Trigonometric functions. */ + +/* Arc cosine of X. */ +#define acos(Val) __TGMATH_UNARY_REAL_IMAG (Val, acos, cacos) +/* Arc sine of X. */ +#define asin(Val) __TGMATH_UNARY_REAL_IMAG (Val, asin, casin) +/* Arc tangent of X. */ +#define atan(Val) __TGMATH_UNARY_REAL_IMAG (Val, atan, catan) +/* Arc tangent of Y/X. */ +#define atan2(Val1, Val2) __TGMATH_BINARY_REAL_ONLY (Val1, Val2, atan2) + +/* Cosine of X. */ +#define cos(Val) __TGMATH_UNARY_REAL_IMAG (Val, cos, ccos) +/* Sine of X. */ +#define sin(Val) __TGMATH_UNARY_REAL_IMAG (Val, sin, csin) +/* Tangent of X. */ +#define tan(Val) __TGMATH_UNARY_REAL_IMAG (Val, tan, ctan) + + +/* Hyperbolic functions. */ + +/* Hyperbolic arc cosine of X. */ +#define acosh(Val) __TGMATH_UNARY_REAL_IMAG (Val, acosh, cacosh) +/* Hyperbolic arc sine of X. */ +#define asinh(Val) __TGMATH_UNARY_REAL_IMAG (Val, asinh, casinh) +/* Hyperbolic arc tangent of X. */ +#define atanh(Val) __TGMATH_UNARY_REAL_IMAG (Val, atanh, catanh) + +/* Hyperbolic cosine of X. */ +#define cosh(Val) __TGMATH_UNARY_REAL_IMAG (Val, cosh, ccosh) +/* Hyperbolic sine of X. */ +#define sinh(Val) __TGMATH_UNARY_REAL_IMAG (Val, sinh, csinh) +/* Hyperbolic tangent of X. */ +#define tanh(Val) __TGMATH_UNARY_REAL_IMAG (Val, tanh, ctanh) + + +/* Exponential and logarithmic functions. */ + +/* Exponential function of X. */ +#define exp(Val) __TGMATH_UNARY_REAL_IMAG (Val, exp, cexp) + +/* Break VALUE into a normalized fraction and an integral power of 2. */ +#define frexp(Val1, Val2) __TGMATH_BINARY_FIRST_REAL_ONLY (Val1, Val2, frexp) + +/* X times (two to the EXP power). */ +#define ldexp(Val1, Val2) __TGMATH_BINARY_FIRST_REAL_ONLY (Val1, Val2, ldexp) + +/* Natural logarithm of X. */ +#define log(Val) __TGMATH_UNARY_REAL_IMAG (Val, log, clog) + +/* Base-ten logarithm of X. */ +#ifdef __USE_GNU +# define log10(Val) __TGMATH_UNARY_REAL_IMAG (Val, log10, __clog10) +#else +# define log10(Val) __TGMATH_UNARY_REAL_ONLY (Val, log10) +#endif + +/* Return exp(X) - 1. */ +#define expm1(Val) __TGMATH_UNARY_REAL_ONLY (Val, expm1) + +/* Return log(1 + X). */ +#define log1p(Val) __TGMATH_UNARY_REAL_ONLY (Val, log1p) + +/* Return the base 2 signed integral exponent of X. */ +#define logb(Val) __TGMATH_UNARY_REAL_ONLY (Val, logb) + +/* Compute base-2 exponential of X. */ +#define exp2(Val) __TGMATH_UNARY_REAL_ONLY (Val, exp2) + +/* Compute base-2 logarithm of X. */ +#define log2(Val) __TGMATH_UNARY_REAL_ONLY (Val, log2) + + +/* Power functions. */ + +/* Return X to the Y power. */ +#define pow(Val1, Val2) __TGMATH_BINARY_REAL_IMAG (Val1, Val2, pow, cpow) + +/* Return the square root of X. */ +#define sqrt(Val) __TGMATH_UNARY_REAL_IMAG (Val, sqrt, csqrt) + +/* Return `sqrt(X*X + Y*Y)'. */ +#define hypot(Val1, Val2) __TGMATH_BINARY_REAL_ONLY (Val1, Val2, hypot) + +/* Return the cube root of X. */ +#define cbrt(Val) __TGMATH_UNARY_REAL_ONLY (Val, cbrt) + + +/* Nearest integer, absolute value, and remainder functions. */ + +/* Smallest integral value not less than X. */ +#define ceil(Val) __TGMATH_UNARY_REAL_ONLY (Val, ceil) + +/* Absolute value of X. */ +#define fabs(Val) __TGMATH_UNARY_REAL_IMAG (Val, fabs, cabs) + +/* Largest integer not greater than X. */ +#define floor(Val) __TGMATH_UNARY_REAL_ONLY (Val, floor) + +/* Floating-point modulo remainder of X/Y. */ +#define fmod(Val1, Val2) __TGMATH_BINARY_REAL_ONLY (Val1, Val2, fmod) + +/* Round X to integral valuein floating-point format using current + rounding direction, but do not raise inexact exception. */ +#define nearbyint(Val) __TGMATH_UNARY_REAL_ONLY (Val, nearbyint) + +/* Round X to nearest integral value, rounding halfway cases away from + zero. */ +#define round(Val) __TGMATH_UNARY_REAL_ONLY (Val, round) + +/* Round X to the integral value in floating-point format nearest but + not larger in magnitude. */ +#define trunc(Val) __TGMATH_UNARY_REAL_ONLY (Val, trunc) + +/* Compute remainder of X and Y and put in *QUO a value with sign of x/y + and magnitude congruent `mod 2^n' to the magnitude of the integral + quotient x/y, with n >= 3. */ +#define remquo(Val1, Val2, Val3) \ + __TGMATH_TERNARY_FIRST_SECOND_REAL_ONLY (Val1, Val2, Val3, remquo) + +/* Round X to nearest integral value according to current rounding + direction. */ +#define lrint(Val) __TGMATH_UNARY_REAL_ONLY (Val, lrint) +#define llrint(Val) __TGMATH_UNARY_REAL_ONLY (Val, llrint) + +/* Round X to nearest integral value, rounding halfway cases away from + zero. */ +#define lround(Val) __TGMATH_UNARY_REAL_ONLY (Val, lround) +#define llround(Val) __TGMATH_UNARY_REAL_ONLY (Val, llround) + + +/* Return X with its signed changed to Y's. */ +#define copysign(Val1, Val2) __TGMATH_BINARY_REAL_ONLY (Val1, Val2, copysign) + +/* Error and gamma functions. */ +#define erf(Val) __TGMATH_UNARY_REAL_ONLY (Val, erf) +#define erfc(Val) __TGMATH_UNARY_REAL_ONLY (Val, erfc) +#define tgamma(Val) __TGMATH_UNARY_REAL_ONLY (Val, tgamma) +#define lgamma(Val) __TGMATH_UNARY_REAL_ONLY (Val, lgamma) + + +/* Return the integer nearest X in the direction of the + prevailing rounding mode. */ +#define rint(Val) __TGMATH_UNARY_REAL_ONLY (Val, rint) + +/* Return X + epsilon if X < Y, X - epsilon if X > Y. */ +#define nextafter(Val1, Val2) __TGMATH_BINARY_REAL_ONLY (Val1, Val2, nextafter) +#define nexttoward(Val1, Val2) \ + __TGMATH_BINARY_FIRST_REAL_ONLY (Val1, Val2, nexttoward) + +/* Return the remainder of integer divison X / Y with infinite precision. */ +#define remainder(Val1, Val2) __TGMATH_BINARY_REAL_ONLY (Val1, Val2, remainder) + +#if defined __UCLIBC_SUSV3_LEGACY__ +/* Return X times (2 to the Nth power). */ +#if defined __USE_MISC || defined __USE_XOPEN_EXTENDED +# define scalb(Val1, Val2) __TGMATH_BINARY_REAL_ONLY (Val1, Val2, scalb) +#endif + +/* Return X times (2 to the Nth power). */ +#define scalbn(Val1, Val2) __TGMATH_BINARY_FIRST_REAL_ONLY (Val1, Val2, scalbn) + +/* Return X times (2 to the Nth power). */ +#define scalbln(Val1, Val2) \ + __TGMATH_BINARY_FIRST_REAL_ONLY (Val1, Val2, scalbln) +#endif /* UCLIBC_SUSV3_LEGACY */ + +/* Return the binary exponent of X, which must be nonzero. */ +#define ilogb(Val) __TGMATH_UNARY_REAL_ONLY (Val, ilogb) + + +/* Return positive difference between X and Y. */ +#define fdim(Val1, Val2) __TGMATH_BINARY_REAL_ONLY (Val1, Val2, fdim) + +/* Return maximum numeric value from X and Y. */ +#define fmax(Val1, Val2) __TGMATH_BINARY_REAL_ONLY (Val1, Val2, fmax) + +/* Return minimum numeric value from X and Y. */ +#define fmin(Val1, Val2) __TGMATH_BINARY_REAL_ONLY (Val1, Val2, fmin) + + +/* Multiply-add function computed as a ternary operation. */ +#define fma(Val1, Val2, Val3) \ + __TGMATH_TERNARY_REAL_ONLY (Val1, Val2, Val3, fma) + + +/* Absolute value, conjugates, and projection. */ + +/* Argument value of Z. */ +#define carg(Val) __TGMATH_UNARY_IMAG_ONLY (Val, carg) + +/* Complex conjugate of Z. */ +#define conj(Val) __TGMATH_UNARY_IMAG_ONLY (Val, conj) + +/* Projection of Z onto the Riemann sphere. */ +#define cproj(Val) __TGMATH_UNARY_IMAG_ONLY (Val, cproj) + + +/* Decomposing complex values. */ + +/* Imaginary part of Z. */ +#define cimag(Val) __TGMATH_UNARY_IMAG_ONLY (Val, cimag) + +/* Real part of Z. */ +#define creal(Val) __TGMATH_UNARY_IMAG_ONLY (Val, creal) + +#endif /* tgmath.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/time.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/time.h new file mode 100644 index 00000000..7fcdf68e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/time.h @@ -0,0 +1,451 @@ +/* Copyright (C) 1991-1999,2000,2001,2002,2003,2006 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * ISO C99 Standard: 7.23 Date and time + */ + +#ifndef _TIME_H + +#if (! defined __need_time_t && !defined __need_clock_t && \ + ! defined __need_timespec) +# define _TIME_H 1 +# include + +__BEGIN_DECLS + +#endif + +#ifdef _TIME_H +/* Get size_t and NULL from . */ +# define __need_size_t +# define __need_NULL +# include + +/* This defines CLOCKS_PER_SEC, which is the number of processor clock + ticks per second. */ +# include + +/* This is the obsolete POSIX.1-1988 name for the same constant. */ +# if !defined __STRICT_ANSI__ && !defined __USE_XOPEN2K +# ifndef CLK_TCK +# define CLK_TCK CLOCKS_PER_SEC +# endif +# endif + +#endif /* included. */ + +#if !defined __clock_t_defined && (defined _TIME_H || defined __need_clock_t) +# define __clock_t_defined 1 + +# include + +__BEGIN_NAMESPACE_STD +/* Returned by `clock'. */ +typedef __clock_t clock_t; +__END_NAMESPACE_STD +#if defined __USE_XOPEN || defined __USE_POSIX || defined __USE_MISC +__USING_NAMESPACE_STD(clock_t) +#endif + +#endif /* clock_t not defined and or need clock_t. */ +#undef __need_clock_t + +#if !defined __time_t_defined && (defined _TIME_H || defined __need_time_t) +# define __time_t_defined 1 + +# include + +__BEGIN_NAMESPACE_STD +/* Returned by `time'. */ +typedef __time_t time_t; +__END_NAMESPACE_STD +#if defined __USE_POSIX || defined __USE_MISC || defined __USE_SVID +__USING_NAMESPACE_STD(time_t) +#endif + +#endif /* time_t not defined and or need time_t. */ +#undef __need_time_t + +#if !defined __clockid_t_defined && \ + ((defined _TIME_H && defined __USE_POSIX199309) || defined __need_clockid_t) +# define __clockid_t_defined 1 + +# include + +/* Clock ID used in clock and timer functions. */ +typedef __clockid_t clockid_t; + +#endif /* clockid_t not defined and or need clockid_t. */ +#undef __clockid_time_t + +#if !defined __timer_t_defined && \ + ((defined _TIME_H && defined __USE_POSIX199309) || defined __need_timer_t) +# define __timer_t_defined 1 + +# include + +/* Timer ID returned by `timer_create'. */ +typedef __timer_t timer_t; + +#endif /* timer_t not defined and or need timer_t. */ +#undef __need_timer_t + + +#if !defined __timespec_defined && \ + ((defined _TIME_H && \ + (defined __USE_POSIX199309 || defined __USE_MISC)) || \ + defined __need_timespec) +# define __timespec_defined 1 + +# include /* This defines __time_t for us. */ + +/* POSIX.1b structure for a time value. This is like a `struct timeval' but + has nanoseconds instead of microseconds. */ +struct timespec + { + __time_t tv_sec; /* Seconds. */ + long int tv_nsec; /* Nanoseconds. */ + }; + +#endif /* timespec not defined and or need timespec. */ +#undef __need_timespec + + +#ifdef _TIME_H +__BEGIN_NAMESPACE_STD +/* Used by other time functions. */ +struct tm +{ + int tm_sec; /* Seconds. [0-60] (1 leap second) */ + int tm_min; /* Minutes. [0-59] */ + int tm_hour; /* Hours. [0-23] */ + int tm_mday; /* Day. [1-31] */ + int tm_mon; /* Month. [0-11] */ + int tm_year; /* Year - 1900. */ + int tm_wday; /* Day of week. [0-6] */ + int tm_yday; /* Days in year.[0-365] */ + int tm_isdst; /* DST. [-1/0/1]*/ + +#ifdef __UCLIBC_HAS_TM_EXTENSIONS__ +#ifdef __USE_BSD + long int tm_gmtoff; /* Seconds east of UTC. */ + __const char *tm_zone; /* Timezone abbreviation. */ +#else + long int __tm_gmtoff; /* Seconds east of UTC. */ + __const char *__tm_zone; /* Timezone abbreviation. */ +#endif +#endif /* __UCLIBC_HAS_TM_EXTENSIONS__ */ +}; +__END_NAMESPACE_STD +#if defined __USE_XOPEN || defined __USE_POSIX || defined __USE_MISC +__USING_NAMESPACE_STD(tm) +#endif + + +#ifdef __USE_POSIX199309 +/* POSIX.1b structure for timer start values and intervals. */ +struct itimerspec + { + struct timespec it_interval; + struct timespec it_value; + }; + +/* We can use a simple forward declaration. */ +struct sigevent; + +#endif /* POSIX.1b */ + +#ifdef __USE_XOPEN2K +# ifndef __pid_t_defined +typedef __pid_t pid_t; +# define __pid_t_defined +# endif +#endif + + +__BEGIN_NAMESPACE_STD +/* Time used by the program so far (user time + system time). + The result / CLOCKS_PER_SECOND is program time in seconds. */ +extern clock_t clock (void) __THROW; + +/* Return the current time and put it in *TIMER if TIMER is not NULL. */ +extern time_t time (time_t *__timer) __THROW; +libc_hidden_proto(time) + +#ifdef __UCLIBC_HAS_FLOATS__ +/* Return the difference between TIME1 and TIME0. */ +extern double difftime (time_t __time1, time_t __time0) + __THROW __attribute__ ((__const__)); +#endif /* __UCLIBC_HAS_FLOATS__ */ + +#define CLOCK_IDFIELD_SIZE 3 + +/* Return the `time_t' representation of TP and normalize TP. */ +extern time_t mktime (struct tm *__tp) __THROW; + + +/* Format TP into S according to FORMAT. + Write no more than MAXSIZE characters and return the number + of characters written, or 0 if it would exceed MAXSIZE. */ +extern size_t strftime (char *__restrict __s, size_t __maxsize, + __const char *__restrict __format, + __const struct tm *__restrict __tp) __THROW; +libc_hidden_proto(strftime) +__END_NAMESPACE_STD + +# ifdef __USE_XOPEN +/* Parse S according to FORMAT and store binary time information in TP. + The return value is a pointer to the first unparsed character in S. */ +extern char *strptime (__const char *__restrict __s, + __const char *__restrict __fmt, struct tm *__tp) + __THROW; +libc_hidden_proto(strptime) +# endif + +#ifdef __UCLIBC_HAS_XLOCALE__ +# ifdef __USE_GNU +/* Similar to the two functions above but take the information from + the provided locale and not the global locale. */ +# include + +extern size_t strftime_l (char *__restrict __s, size_t __maxsize, + __const char *__restrict __format, + __const struct tm *__restrict __tp, + __locale_t __loc) __THROW; +libc_hidden_proto(strftime_l) + +extern char *strptime_l (__const char *__restrict __s, + __const char *__restrict __fmt, struct tm *__tp, + __locale_t __loc) __THROW; +libc_hidden_proto(strptime_l) +# endif +#endif + + +__BEGIN_NAMESPACE_STD +/* Return the `struct tm' representation of *TIMER + in Universal Coordinated Time (aka Greenwich Mean Time). */ +extern struct tm *gmtime (__const time_t *__timer) __THROW; + +/* Return the `struct tm' representation + of *TIMER in the local timezone. */ +extern struct tm *localtime (__const time_t *__timer) __THROW; +libc_hidden_proto(localtime) +__END_NAMESPACE_STD + +# if defined __USE_POSIX || defined __USE_MISC +/* Return the `struct tm' representation of *TIMER in UTC, + using *TP to store the result. */ +extern struct tm *gmtime_r (__const time_t *__restrict __timer, + struct tm *__restrict __tp) __THROW; + +/* Return the `struct tm' representation of *TIMER in local time, + using *TP to store the result. */ +extern struct tm *localtime_r (__const time_t *__restrict __timer, + struct tm *__restrict __tp) __THROW; +libc_hidden_proto(localtime_r) +# endif /* POSIX or misc */ + +__BEGIN_NAMESPACE_STD +/* Return a string of the form "Day Mon dd hh:mm:ss yyyy\n" + that is the representation of TP in this format. */ +extern char *asctime (__const struct tm *__tp) __THROW; +libc_hidden_proto(asctime) + +/* Equivalent to `asctime (localtime (timer))'. */ +extern char *ctime (__const time_t *__timer) __THROW; +libc_hidden_proto(ctime) +__END_NAMESPACE_STD + +# if defined __USE_POSIX || defined __USE_MISC +/* Reentrant versions of the above functions. */ + +/* Return in BUF a string of the form "Day Mon dd hh:mm:ss yyyy\n" + that is the representation of TP in this format. */ +extern char *asctime_r (__const struct tm *__restrict __tp, + char *__restrict __buf) __THROW; +libc_hidden_proto(asctime_r) + +/* Equivalent to `asctime_r (localtime_r (timer, *TMP*), buf)'. */ +extern char *ctime_r (__const time_t *__restrict __timer, + char *__restrict __buf) __THROW; +# endif /* POSIX or misc */ + + +/* Defined in localtime.c. */ +#ifdef __UCLIBC_MJN3_ONLY__ +#warning "mjn3 FIXME: __tzname, __daylight, and __timezone have a prototype but are not defined." +extern char *__tzname[2]; /* Current timezone names. */ +extern int __daylight; /* If daylight-saving time is ever in use. */ +extern long int __timezone; /* Seconds west of UTC. */ +#endif /* __UCLIBC_MJN3_ONLY__ */ + + +# ifdef __USE_POSIX +/* Same as above. */ +extern char *tzname[2]; + +/* Set time conversion information from the TZ environment variable. + If TZ is not defined, a locale-dependent default is used. */ +extern void tzset (void) __THROW; +libc_hidden_proto(tzset) +# endif + +# if defined __USE_SVID || defined __USE_XOPEN +extern int daylight; +extern long int timezone; +# endif + +# ifdef __USE_SVID +/* Set the system time to *WHEN. + This call is restricted to the superuser. */ +extern int stime (__const time_t *__when) __THROW; +# endif + + +/* Nonzero if YEAR is a leap year (every 4 years, + except every 100th isn't, and every 400th is). */ +# define __isleap(year) \ + ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0)) + + +# ifdef __USE_MISC +/* Miscellaneous functions many Unices inherited from the public domain + localtime package. These are included only for compatibility. */ + +/* Like `mktime', but for TP represents Universal Time, not local time. */ +extern time_t timegm (struct tm *__tp) __THROW; + +/* Another name for `mktime'. */ +extern time_t timelocal (struct tm *__tp) __THROW; + +/* Return the number of days in YEAR. */ +extern int dysize (int __year) __THROW __attribute__ ((__const__)); +# endif + + +# ifdef __USE_POSIX199309 +# if defined __UCLIBC_HAS_REALTIME__ +/* Pause execution for a number of nanoseconds. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern int nanosleep (__const struct timespec *__requested_time, + struct timespec *__remaining); +libc_hidden_proto(nanosleep) + + +/* Get resolution of clock CLOCK_ID. */ +extern int clock_getres (clockid_t __clock_id, struct timespec *__res) __THROW; +libc_hidden_proto(clock_getres) + +/* Get current value of clock CLOCK_ID and store it in TP. */ +extern int clock_gettime (clockid_t __clock_id, struct timespec *__tp) __THROW; + +/* Set clock CLOCK_ID to value TP. */ +extern int clock_settime (clockid_t __clock_id, __const struct timespec *__tp) + __THROW; +# endif /* __UCLIBC_HAS_REALTIME__ */ +# ifdef __UCLIBC_HAS_THREADS_NATIVE__ +# if defined __USE_XOPEN2K && defined __UCLIBC_HAS_ADVANCED_REALTIME__ +/* High-resolution sleep with the specified clock. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern int clock_nanosleep (clockid_t __clock_id, int __flags, + __const struct timespec *__req, + struct timespec *__rem); + +/* Return clock ID for CPU-time clock. */ +extern int clock_getcpuclockid (pid_t __pid, clockid_t *__clock_id) __THROW; +# endif +# endif /* __UCLIBC_HAS_THREADS_NATIVE__ */ + +# if defined __UCLIBC_HAS_REALTIME__ +/* Create new per-process timer using CLOCK_ID. */ +extern int timer_create (clockid_t __clock_id, + struct sigevent *__restrict __evp, + timer_t *__restrict __timerid) __THROW; + +/* Delete timer TIMERID. */ +extern int timer_delete (timer_t __timerid) __THROW; + +/* Set timer TIMERID to VALUE, returning old value in OVLAUE. */ +extern int timer_settime (timer_t __timerid, int __flags, + __const struct itimerspec *__restrict __value, + struct itimerspec *__restrict __ovalue) __THROW; + +/* Get current value of timer TIMERID and store it in VLAUE. */ +extern int timer_gettime (timer_t __timerid, struct itimerspec *__value) + __THROW; + +/* Get expiration overrun for timer TIMERID. */ +extern int timer_getoverrun (timer_t __timerid) __THROW; +# endif /* __UCLIBC_HAS_REALTIME__ */ +# endif /* __USE_POSIX199309 */ + + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning "mjn3 FIXME: a bunch of unimplemented function prototypes." +# ifdef __USE_XOPEN_EXTENDED +/* Set to one of the following values to indicate an error. + 1 the DATEMSK environment variable is null or undefined, + 2 the template file cannot be opened for reading, + 3 failed to get file status information, + 4 the template file is not a regular file, + 5 an error is encountered while reading the template file, + 6 memory allication failed (not enough memory available), + 7 there is no line in the template that matches the input, + 8 invalid input specification Example: February 31 or a time is + specified that can not be represented in a time_t (representing + the time in seconds since 00:00:00 UTC, January 1, 1970) */ +extern int getdate_err; + +/* Parse the given string as a date specification and return a value + representing the value. The templates from the file identified by + the environment variable DATEMSK are used. In case of an error + `getdate_err' is set. + + This function is a possible cancellation points and therefore not + marked with __THROW. */ +extern struct tm *getdate (__const char *__string); +# endif + +# ifdef __USE_GNU +/* Since `getdate' is not reentrant because of the use of `getdate_err' + and the static buffer to return the result in, we provide a thread-safe + variant. The functionality is the same. The result is returned in + the buffer pointed to by RESBUFP and in case of an error the return + value is != 0 with the same values as given above for `getdate_err'. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern int getdate_r (__const char *__restrict __string, + struct tm *__restrict __resbufp); +# endif +#endif /* __UCLIBC_MJN3_ONLY__ */ + +__END_DECLS + +#endif /* included. */ + +#endif /* not already included. */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/tls.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/tls.h new file mode 100644 index 00000000..987cb086 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/tls.h @@ -0,0 +1,20 @@ +/* This file defines USE___THREAD to 1 or 0 to cut down on the #if mess. */ + +#include_next + +#ifndef _include_tls_h +#define _include_tls_h 1 +#if defined USE_TLS && USE_TLS && HAVE___THREAD \ + && (!defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt) + + +# define USE___THREAD 1 + +#else + +# define USE___THREAD 0 + +#endif + +#endif + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/ttyent.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/ttyent.h new file mode 100644 index 00000000..3166e83b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/ttyent.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ttyent.h 8.1 (Berkeley) 6/2/93 + */ + +#ifndef _TTYENT_H +#define _TTYENT_H 1 + +#include + +#define _PATH_TTYS "/etc/ttys" + +#define _TTYS_OFF "off" +#define _TTYS_ON "on" +#define _TTYS_SECURE "secure" +#define _TTYS_WINDOW "window" + +struct ttyent { + char *ty_name; /* terminal device name */ + char *ty_getty; /* command to execute, usually getty */ + char *ty_type; /* terminal type for termcap */ +#define TTY_ON 0x01 /* enable logins (start ty_getty program) */ +#define TTY_SECURE 0x02 /* allow uid of 0 to login */ + int ty_status; /* status flags */ + char *ty_window; /* command to start up window manager */ + char *ty_comment; /* comment field */ +}; + + +__BEGIN_DECLS + +extern struct ttyent *getttyent (void) __THROW; +libc_hidden_proto(getttyent) +extern struct ttyent *getttynam (__const char *__tty) __THROW; +extern int setttyent (void) __THROW; +libc_hidden_proto(setttyent) +extern int endttyent (void) __THROW; +libc_hidden_proto(endttyent) + +__END_DECLS + +#endif /* ttyent.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/ucontext.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/ucontext.h new file mode 100644 index 00000000..5bd46454 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/ucontext.h @@ -0,0 +1,32 @@ +/* Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _UCONTEXT_H +#define _UCONTEXT_H 1 + +#include + +/* Get machine dependent definition of data structures. */ +#include + +/* The System V ABI user-level context switching support functions + * are marked obsolescent by SuSv3, and are not implemented by + * uClibc. This header is therefore empty. */ + + +#endif /* ucontext.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/ulimit.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/ulimit.h new file mode 100644 index 00000000..93b5f379 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/ulimit.h @@ -0,0 +1,48 @@ +/* Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _ULIMIT_H +#define _ULIMIT_H 1 + +#include + +/* Constants used as the first parameter for `ulimit'. They denote limits + which can be set or retrieved using this function. */ +enum +{ + UL_GETFSIZE = 1, /* Return limit on the size of a file, + in units of 512 bytes. */ +#define UL_GETFSIZE UL_GETFSIZE + UL_SETFSIZE, /* Set limit on the size of a file to + second argument. */ +#define UL_SETFSIZE UL_SETFSIZE + __UL_GETMAXBRK, /* Return the maximum possible address + of the data segment. */ + __UL_GETOPENMAX /* Return the maximum number of files + that the calling process can open.*/ +}; + + +__BEGIN_DECLS + +/* Control process limits according to CMD. */ +extern long int ulimit (int __cmd, ...) __THROW; + +__END_DECLS + +#endif /* ulimit.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/unistd.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/unistd.h new file mode 100644 index 00000000..5d3a4cb8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/unistd.h @@ -0,0 +1,1186 @@ +/* Copyright (C) 1991-2002,2003,2004,2005,2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * POSIX Standard: 2.10 Symbolic Constants + */ + +#ifndef _UNISTD_H +#define _UNISTD_H 1 + +#include + +__BEGIN_DECLS + +/* These may be used to determine what facilities are present at compile time. + Their values can be obtained at run time from `sysconf'. */ + +/* POSIX Standard approved as ISO/IEC 9945-1 as of December 2001. */ +#define _POSIX_VERSION 200112L + +/* These are not #ifdef __USE_POSIX2 because they are + in the theoretically application-owned namespace. */ + +/* The utilities on GNU systems also correspond to this version. */ +#define _POSIX2_VERSION 200112L + +/* If defined, the implementation supports the + C Language Bindings Option. */ +#define _POSIX2_C_BIND 200112L + +/* If defined, the implementation supports the + C Language Development Utilities Option. */ +#define _POSIX2_C_DEV 200112L + +/* If defined, the implementation supports the + Software Development Utilities Option. */ +#define _POSIX2_SW_DEV 200112L + +/* If defined, the implementation supports the + creation of locales with the localedef utility. */ +#define _POSIX2_LOCALEDEF 200112L + +/* X/Open version number to which the library conforms. It is selectable. */ +#ifdef __USE_UNIX98 +# define _XOPEN_VERSION 500 +#else +# define _XOPEN_VERSION 4 +#endif + +/* Commands and utilities from XPG4 are available. */ +#define _XOPEN_XCU_VERSION 4 + +/* We are compatible with the old published standards as well. */ +#define _XOPEN_XPG2 1 +#define _XOPEN_XPG3 1 +#define _XOPEN_XPG4 1 + +/* The X/Open Unix extensions are available. */ +#define _XOPEN_UNIX 1 + +/* Encryption is present. */ +#define _XOPEN_CRYPT 1 + +/* The enhanced internationalization capabilities according to XPG4.2 + are present. */ +#define _XOPEN_ENH_I18N 1 + +/* The legacy interfaces are also available. */ +#define _XOPEN_LEGACY 1 + + +/* Get values of POSIX options: + + If these symbols are defined, the corresponding features are + always available. If not, they may be available sometimes. + The current values can be obtained with `sysconf'. + + _POSIX_JOB_CONTROL Job control is supported. + _POSIX_SAVED_IDS Processes have a saved set-user-ID + and a saved set-group-ID. + _POSIX_REALTIME_SIGNALS Real-time, queued signals are supported. + _POSIX_PRIORITY_SCHEDULING Priority scheduling is supported. + _POSIX_TIMERS POSIX.4 clocks and timers are supported. + _POSIX_ASYNCHRONOUS_IO Asynchronous I/O is supported. + _POSIX_PRIORITIZED_IO Prioritized asynchronous I/O is supported. + _POSIX_SYNCHRONIZED_IO Synchronizing file data is supported. + _POSIX_FSYNC The fsync function is present. + _POSIX_MAPPED_FILES Mapping of files to memory is supported. + _POSIX_MEMLOCK Locking of all memory is supported. + _POSIX_MEMLOCK_RANGE Locking of ranges of memory is supported. + _POSIX_MEMORY_PROTECTION Setting of memory protections is supported. + _POSIX_MESSAGE_PASSING POSIX.4 message queues are supported. + _POSIX_SEMAPHORES POSIX.4 counting semaphores are supported. + _POSIX_SHARED_MEMORY_OBJECTS POSIX.4 shared memory objects are supported. + _POSIX_THREADS POSIX.1c pthreads are supported. + _POSIX_THREAD_ATTR_STACKADDR Thread stack address attribute option supported. + _POSIX_THREAD_ATTR_STACKSIZE Thread stack size attribute option supported. + _POSIX_THREAD_SAFE_FUNCTIONS Thread-safe functions are supported. + _POSIX_THREAD_PRIORITY_SCHEDULING + POSIX.1c thread execution scheduling supported. + _POSIX_THREAD_PRIO_INHERIT Thread priority inheritance option supported. + _POSIX_THREAD_PRIO_PROTECT Thread priority protection option supported. + _POSIX_THREAD_PROCESS_SHARED Process-shared synchronization supported. + _POSIX_PII Protocol-independent interfaces are supported. + _POSIX_PII_XTI XTI protocol-indep. interfaces are supported. + _POSIX_PII_SOCKET Socket protocol-indep. interfaces are supported. + _POSIX_PII_INTERNET Internet family of protocols supported. + _POSIX_PII_INTERNET_STREAM Connection-mode Internet protocol supported. + _POSIX_PII_INTERNET_DGRAM Connectionless Internet protocol supported. + _POSIX_PII_OSI ISO/OSI family of protocols supported. + _POSIX_PII_OSI_COTS Connection-mode ISO/OSI service supported. + _POSIX_PII_OSI_CLTS Connectionless ISO/OSI service supported. + _POSIX_POLL Implementation supports `poll' function. + _POSIX_SELECT Implementation supports `select' and `pselect'. + + _XOPEN_REALTIME X/Open realtime support is available. + _XOPEN_REALTIME_THREADS X/Open realtime thread support is available. + _XOPEN_SHM Shared memory interface according to XPG4.2. + + _XBS5_ILP32_OFF32 Implementation provides environment with 32-bit + int, long, pointer, and off_t types. + _XBS5_ILP32_OFFBIG Implementation provides environment with 32-bit + int, long, and pointer and off_t with at least + 64 bits. + _XBS5_LP64_OFF64 Implementation provides environment with 32-bit + int, and 64-bit long, pointer, and off_t types. + _XBS5_LPBIG_OFFBIG Implementation provides environment with at + least 32 bits int and long, pointer, and off_t + with at least 64 bits. + + If any of these symbols is defined as -1, the corresponding option is not + true for any file. If any is defined as other than -1, the corresponding + option is true for all files. If a symbol is not defined at all, the value + for a specific file can be obtained from `pathconf' and `fpathconf'. + + _POSIX_CHOWN_RESTRICTED Only the super user can use `chown' to change + the owner of a file. `chown' can only be used + to change the group ID of a file to a group of + which the calling process is a member. + _POSIX_NO_TRUNC Pathname components longer than + NAME_MAX generate an error. + _POSIX_VDISABLE If defined, if the value of an element of the + `c_cc' member of `struct termios' is + _POSIX_VDISABLE, no character will have the + effect associated with that element. + _POSIX_SYNC_IO Synchronous I/O may be performed. + _POSIX_ASYNC_IO Asynchronous I/O may be performed. + _POSIX_PRIO_IO Prioritized Asynchronous I/O may be performed. + + Support for the Large File Support interface is not generally available. + If it is available the following constants are defined to one. + _LFS64_LARGEFILE Low-level I/O supports large files. + _LFS64_STDIO Standard I/O supports large files. + */ + +#include + +/* Get the environment definitions from Unix98. */ +#ifdef __USE_UNIX98 +# include +#endif + +/* Standard file descriptors. */ +#define STDIN_FILENO 0 /* Standard input. */ +#define STDOUT_FILENO 1 /* Standard output. */ +#define STDERR_FILENO 2 /* Standard error output. */ + + +/* All functions that are not declared anywhere else. */ + +#include + +#ifndef __ssize_t_defined +typedef __ssize_t ssize_t; +# define __ssize_t_defined +#endif + +#define __need_size_t +#define __need_NULL +#include + +#if defined __USE_XOPEN || defined __USE_XOPEN2K +/* The Single Unix specification says that some more types are + available here. */ +# ifndef __gid_t_defined +typedef __gid_t gid_t; +# define __gid_t_defined +# endif + +# ifndef __uid_t_defined +typedef __uid_t uid_t; +# define __uid_t_defined +# endif + +# ifndef __off_t_defined +# ifndef __USE_FILE_OFFSET64 +typedef __off_t off_t; +# else +typedef __off64_t off_t; +# endif +# define __off_t_defined +# endif +# if defined __USE_LARGEFILE64 && !defined __off64_t_defined +typedef __off64_t off64_t; +# define __off64_t_defined +# endif + +# ifndef __useconds_t_defined +typedef __useconds_t useconds_t; +# define __useconds_t_defined +# endif + +# ifndef __pid_t_defined +typedef __pid_t pid_t; +# define __pid_t_defined +# endif +#endif /* X/Open */ + +#if defined __USE_MISC || defined __USE_XOPEN_EXTENDED +# ifndef __intptr_t_defined +typedef __intptr_t intptr_t; +# define __intptr_t_defined +# endif +#endif + +#if defined __USE_BSD || defined __USE_XOPEN +# ifndef __socklen_t_defined +typedef __socklen_t socklen_t; +# define __socklen_t_defined +# endif +#endif + +/* Values for the second argument to access. + These may be OR'd together. */ +#define R_OK 4 /* Test for read permission. */ +#define W_OK 2 /* Test for write permission. */ +#define X_OK 1 /* Test for execute permission. */ +#define F_OK 0 /* Test for existence. */ + +/* Test for access to NAME using the real UID and real GID. */ +extern int access (__const char *__name, int __type) __THROW __nonnull ((1)); + +#if 0 /*def __USE_GNU*/ +/* Test for access to NAME using the effective UID and GID + (as normal file operations use). */ +extern int euidaccess (__const char *__name, int __type) + __THROW __nonnull ((1)); + +/* An alias for `euidaccess', used by some other systems. */ +extern int eaccess (__const char *__name, int __type) + __THROW __nonnull ((1)); +#endif + +#ifdef __USE_ATFILE +/* Test for access to FILE relative to the directory FD is open on. + If AT_EACCESS is set in FLAG, then use effective IDs like `eaccess', + otherwise use real IDs like `access'. */ +extern int faccessat (int __fd, __const char *__file, int __type, int __flag) + __THROW __nonnull ((2)) __wur; +#endif /* Use GNU. */ + + +/* Values for the WHENCE argument to lseek. */ +#ifndef _STDIO_H /* has the same definitions. */ +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_END 2 /* Seek from end of file. */ +#endif + +#if defined __USE_BSD && !defined L_SET +/* Old BSD names for the same constants; just for compatibility. */ +# define L_SET SEEK_SET +# define L_INCR SEEK_CUR +# define L_XTND SEEK_END +#endif + + +/* Move FD's file position to OFFSET bytes from the + beginning of the file (if WHENCE is SEEK_SET), + the current position (if WHENCE is SEEK_CUR), + or the end of the file (if WHENCE is SEEK_END). + Return the new file position. */ +#ifndef __USE_FILE_OFFSET64 +extern __off_t lseek (int __fd, __off_t __offset, int __whence) __THROW; +libc_hidden_proto(lseek) +#else +# ifdef __REDIRECT_NTH +extern __off64_t __REDIRECT_NTH (lseek, + (int __fd, __off64_t __offset, int __whence), + lseek64); +# else +# define lseek lseek64 +# endif +#endif +#ifdef __USE_LARGEFILE64 +extern __off64_t lseek64 (int __fd, __off64_t __offset, int __whence) + __THROW; +libc_hidden_proto(lseek64) +#endif + +/* Close the file descriptor FD. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern int close (int __fd); +libc_hidden_proto(close) + +/* Read NBYTES into BUF from FD. Return the + number read, -1 for errors or 0 for EOF. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern ssize_t read (int __fd, void *__buf, size_t __nbytes) __wur; +libc_hidden_proto(read) + +/* Write N bytes of BUF to FD. Return the number written, or -1. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern ssize_t write (int __fd, __const void *__buf, size_t __n) __wur; +libc_hidden_proto(write) + +#ifdef __USE_UNIX98 +# ifndef __USE_FILE_OFFSET64 +/* Read NBYTES into BUF from FD at the given position OFFSET without + changing the file pointer. Return the number read, -1 for errors + or 0 for EOF. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern ssize_t pread (int __fd, void *__buf, size_t __nbytes, + __off_t __offset) __wur; + +/* Write N bytes of BUF to FD at the given position OFFSET without + changing the file pointer. Return the number written, or -1. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern ssize_t pwrite (int __fd, __const void *__buf, size_t __n, + __off_t __offset) __wur; +# else +# ifdef __REDIRECT +extern ssize_t __REDIRECT (pread, (int __fd, void *__buf, size_t __nbytes, + __off64_t __offset), + pread64) __wur; +extern ssize_t __REDIRECT (pwrite, (int __fd, __const void *__buf, + size_t __nbytes, __off64_t __offset), + pwrite64) __wur; +# else +# define pread pread64 +# define pwrite pwrite64 +# endif +# endif + +# ifdef __USE_LARGEFILE64 +/* Read NBYTES into BUF from FD at the given position OFFSET without + changing the file pointer. Return the number read, -1 for errors + or 0 for EOF. */ +extern ssize_t pread64 (int __fd, void *__buf, size_t __nbytes, + __off64_t __offset) __wur; +/* Write N bytes of BUF to FD at the given position OFFSET without + changing the file pointer. Return the number written, or -1. */ +extern ssize_t pwrite64 (int __fd, __const void *__buf, size_t __n, + __off64_t __offset) __wur; +# endif +#endif + +/* Create a one-way communication channel (pipe). + If successful, two file descriptors are stored in PIPEDES; + bytes written on PIPEDES[1] can be read from PIPEDES[0]. + Returns 0 if successful, -1 if not. */ +extern int pipe (int __pipedes[2]) __THROW __wur; +libc_hidden_proto(pipe) + +/* Schedule an alarm. In SECONDS seconds, the process will get a SIGALRM. + If SECONDS is zero, any currently scheduled alarm will be cancelled. + The function returns the number of seconds remaining until the last + alarm scheduled would have signaled, or zero if there wasn't one. + There is no return value to indicate an error, but you can set `errno' + to 0 and check its value after calling `alarm', and this might tell you. + The signal may come late due to processor scheduling. */ +extern unsigned int alarm (unsigned int __seconds) __THROW; +libc_hidden_proto(alarm) + +/* Make the process sleep for SECONDS seconds, or until a signal arrives + and is not ignored. The function returns the number of seconds less + than SECONDS which it actually slept (thus zero if it slept the full time). + If a signal handler does a `longjmp' or modifies the handling of the + SIGALRM signal while inside `sleep' call, the handling of the SIGALRM + signal afterwards is undefined. There is no return value to indicate + error, but if `sleep' returns SECONDS, it probably didn't work. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern unsigned int sleep (unsigned int __seconds); +libc_hidden_proto(sleep) + +#if (defined __USE_BSD || defined __USE_XOPEN_EXTENDED) \ + && defined __UCLIBC_SUSV3_LEGACY__ +/* Set an alarm to go off (generating a SIGALRM signal) in VALUE + microseconds. If INTERVAL is nonzero, when the alarm goes off, the + timer is reset to go off every INTERVAL microseconds thereafter. + Returns the number of microseconds remaining before the alarm. */ +extern __useconds_t ualarm (__useconds_t __value, __useconds_t __interval) + __THROW; + +/* Sleep USECONDS microseconds, or until a signal arrives that is not blocked + or ignored. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern int usleep (__useconds_t __useconds); +#endif + + +/* Suspend the process until a signal arrives. + This always returns -1 and sets `errno' to EINTR. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern int pause (void); + + +/* Change the owner and group of FILE. */ +extern int chown (__const char *__file, __uid_t __owner, __gid_t __group) + __THROW __nonnull ((1)) __wur; +libc_hidden_proto(chown) + +#if defined __USE_BSD || defined __USE_XOPEN_EXTENDED +/* Change the owner and group of the file that FD is open on. */ +extern int fchown (int __fd, __uid_t __owner, __gid_t __group) __THROW __wur; + + +/* Change owner and group of FILE, if it is a symbolic + link the ownership of the symbolic link is changed. */ +extern int lchown (__const char *__file, __uid_t __owner, __gid_t __group) + __THROW __nonnull ((1)) __wur; + +#endif /* Use BSD || X/Open Unix. */ + +#ifdef __USE_ATFILE +/* Change the owner and group of FILE relative to the directory FD is open + on. */ +extern int fchownat (int __fd, __const char *__file, __uid_t __owner, + __gid_t __group, int __flag) + __THROW __nonnull ((2)) __wur; +#endif /* Use GNU. */ + +/* Change the process's working directory to PATH. */ +extern int chdir (__const char *__path) __THROW __nonnull ((1)) __wur; +libc_hidden_proto(chdir) + +#if defined __USE_BSD || defined __USE_XOPEN_EXTENDED +/* Change the process's working directory to the one FD is open on. */ +extern int fchdir (int __fd) __THROW __wur; +libc_hidden_proto(fchdir) +#endif + +/* Get the pathname of the current working directory, + and put it in SIZE bytes of BUF. Returns NULL if the + directory couldn't be determined or SIZE was too small. + If successful, returns BUF. In GNU, if BUF is NULL, + an array is allocated with `malloc'; the array is SIZE + bytes long, unless SIZE == 0, in which case it is as + big as necessary. */ +extern char *getcwd (char *__buf, size_t __size) __THROW __wur; +libc_hidden_proto(getcwd) + +#ifdef __USE_GNU +/* Return a malloc'd string containing the current directory name. + If the environment variable `PWD' is set, and its value is correct, + that value is used. */ +extern char *get_current_dir_name (void) __THROW; +#endif + +#if 0 /*defined __USE_BSD || defined __USE_XOPEN_EXTENDED*/ +/* Put the absolute pathname of the current working directory in BUF. + If successful, return BUF. If not, put an error message in + BUF and return NULL. BUF should be at least PATH_MAX bytes long. */ +extern char *getwd (char *__buf) + __THROW __nonnull ((1)) __attribute_deprecated__ __wur; +#endif + + +/* Duplicate FD, returning a new file descriptor on the same file. */ +extern int dup (int __fd) __THROW __wur; + +/* Duplicate FD to FD2, closing FD2 and making it open on the same file. */ +extern int dup2 (int __fd, int __fd2) __THROW; +libc_hidden_proto(dup2) + +/* NULL-terminated array of "NAME=VALUE" environment variables. */ +extern char **__environ; +#ifdef __USE_GNU +extern char **environ; +#endif + + +/* Replace the current process, executing PATH with arguments ARGV and + environment ENVP. ARGV and ENVP are terminated by NULL pointers. */ +extern int execve (__const char *__path, char *__const __argv[], + char *__const __envp[]) __THROW __nonnull ((1)); +libc_hidden_proto(execve) + +#if 0 /*def __USE_GNU*/ +/* Execute the file FD refers to, overlaying the running program image. + ARGV and ENVP are passed to the new program, as for `execve'. */ +extern int fexecve (int __fd, char *__const __argv[], char *__const __envp[]) + __THROW; +#endif + + +/* Execute PATH with arguments ARGV and environment from `environ'. */ +extern int execv (__const char *__path, char *__const __argv[]) + __THROW __nonnull ((1)); +libc_hidden_proto(execv) + +/* Execute PATH with all arguments after PATH until a NULL pointer, + and the argument after that for environment. */ +extern int execle (__const char *__path, __const char *__arg, ...) + __THROW __nonnull ((1)); +libc_hidden_proto(execle) + +/* Execute PATH with all arguments after PATH until + a NULL pointer and environment from `environ'. */ +extern int execl (__const char *__path, __const char *__arg, ...) + __THROW __nonnull ((1)); +libc_hidden_proto(execl) + +/* Execute FILE, searching in the `PATH' environment variable if it contains + no slashes, with arguments ARGV and environment from `environ'. */ +extern int execvp (__const char *__file, char *__const __argv[]) + __THROW __nonnull ((1)); +libc_hidden_proto(execvp) + +/* Execute FILE, searching in the `PATH' environment variable if + it contains no slashes, with all arguments after FILE until a + NULL pointer and environment from `environ'. */ +extern int execlp (__const char *__file, __const char *__arg, ...) + __THROW __nonnull ((1)); +libc_hidden_proto(execlp) + + +#if defined __USE_MISC || defined __USE_XOPEN +/* Add INC to priority of the current process. */ +extern int nice (int __inc) __THROW __wur; +#endif + + +/* Terminate program execution with the low-order 8 bits of STATUS. */ +extern void _exit (int __status) __attribute__ ((__noreturn__)); +libc_hidden_proto(_exit) + + +/* Get the `_PC_*' symbols for the NAME argument to `pathconf' and `fpathconf'; + the `_SC_*' symbols for the NAME argument to `sysconf'; + and the `_CS_*' symbols for the NAME argument to `confstr'. */ +#include + +/* Get file-specific configuration information about PATH. */ +extern long int pathconf (__const char *__path, int __name) + __THROW __nonnull ((1)); + +/* Get file-specific configuration about descriptor FD. */ +extern long int fpathconf (int __fd, int __name) __THROW; + +/* Get the value of the system variable NAME. */ +extern long int sysconf (int __name) __THROW; +libc_hidden_proto(sysconf) + +#ifdef __USE_POSIX2 +/* Get the value of the string-valued system variable NAME. */ +extern size_t confstr (int __name, char *__buf, size_t __len) __THROW; +#endif + + +/* Get the process ID of the calling process. */ +extern __pid_t getpid (void) __THROW; +libc_hidden_proto(getpid) + +/* Get the process ID of the calling process's parent. */ +extern __pid_t getppid (void) __THROW; + +/* Get the process group ID of the calling process. + This function is different on old BSD. */ +#ifndef __FAVOR_BSD +extern __pid_t getpgrp (void) __THROW; +#else +# ifdef __REDIRECT_NTH +extern __pid_t __REDIRECT_NTH (getpgrp, (__pid_t __pid), __getpgid); +# else +# define getpgrp __getpgid +# endif +#endif + +/* Get the process group ID of process PID. */ +extern __pid_t __getpgid (__pid_t __pid) __THROW; +#ifdef __USE_XOPEN_EXTENDED +extern __pid_t getpgid (__pid_t __pid) __THROW; +#endif + + +/* Set the process group ID of the process matching PID to PGID. + If PID is zero, the current process's process group ID is set. + If PGID is zero, the process ID of the process is used. */ +extern int setpgid (__pid_t __pid, __pid_t __pgid) __THROW; +libc_hidden_proto(setpgid) + +#if defined __USE_SVID || defined __USE_BSD || defined __USE_XOPEN_EXTENDED +/* Both System V and BSD have `setpgrp' functions, but with different + calling conventions. The BSD function is the same as POSIX.1 `setpgid' + (above). The System V function takes no arguments and puts the calling + process in its on group like `setpgid (0, 0)'. + + New programs should always use `setpgid' instead. + + The default in GNU is to provide the System V function. The BSD + function is available under -D_BSD_SOURCE. */ + +# ifndef __FAVOR_BSD + +/* Set the process group ID of the calling process to its own PID. + This is exactly the same as `setpgid (0, 0)'. */ +extern int setpgrp (void) __THROW; + +# else + +/* Another name for `setpgid' (above). */ +# ifdef __REDIRECT_NTH +extern int __REDIRECT_NTH (setpgrp, (__pid_t __pid, __pid_t __pgrp), setpgid); +# else +# define setpgrp setpgid +# endif + +# endif /* Favor BSD. */ +#endif /* Use SVID or BSD. */ + +/* Create a new session with the calling process as its leader. + The process group IDs of the session and the calling process + are set to the process ID of the calling process, which is returned. */ +extern __pid_t setsid (void) __THROW; +libc_hidden_proto(setsid) + +#ifdef __USE_XOPEN_EXTENDED +/* Return the session ID of the given process. */ +extern __pid_t getsid (__pid_t __pid) __THROW; +libc_hidden_proto(getsid) +#endif + +/* Get the real user ID of the calling process. */ +extern __uid_t getuid (void) __THROW; +libc_hidden_proto(getuid) + +/* Get the effective user ID of the calling process. */ +extern __uid_t geteuid (void) __THROW; +libc_hidden_proto(geteuid) + +/* Get the real group ID of the calling process. */ +extern __gid_t getgid (void) __THROW; +libc_hidden_proto(getgid) + +/* Get the effective group ID of the calling process. */ +extern __gid_t getegid (void) __THROW; +libc_hidden_proto(getegid) + +/* If SIZE is zero, return the number of supplementary groups + the calling process is in. Otherwise, fill in the group IDs + of its supplementary groups in LIST and return the number written. */ +extern int getgroups (int __size, __gid_t __list[]) __THROW __wur; +libc_hidden_proto(getgroups) + +#if 0 /*def __USE_GNU*/ +/* Return nonzero iff the calling process is in group GID. */ +extern int group_member (__gid_t __gid) __THROW; +#endif + +/* Set the user ID of the calling process to UID. + If the calling process is the super-user, set the real + and effective user IDs, and the saved set-user-ID to UID; + if not, the effective user ID is set to UID. */ +extern int setuid (__uid_t __uid) __THROW; + +#if defined __USE_BSD || defined __USE_XOPEN_EXTENDED +/* Set the real user ID of the calling process to RUID, + and the effective user ID of the calling process to EUID. */ +extern int setreuid (__uid_t __ruid, __uid_t __euid) __THROW; +libc_hidden_proto(setreuid) +#endif + +#if defined __USE_BSD || defined __USE_XOPEN2K +/* Set the effective user ID of the calling process to UID. */ +extern int seteuid (__uid_t __uid) __THROW; +libc_hidden_proto(seteuid) +#endif /* Use BSD. */ + +/* Set the group ID of the calling process to GID. + If the calling process is the super-user, set the real + and effective group IDs, and the saved set-group-ID to GID; + if not, the effective group ID is set to GID. */ +extern int setgid (__gid_t __gid) __THROW; + +#if defined __USE_BSD || defined __USE_XOPEN_EXTENDED +/* Set the real group ID of the calling process to RGID, + and the effective group ID of the calling process to EGID. */ +extern int setregid (__gid_t __rgid, __gid_t __egid) __THROW; +libc_hidden_proto(setregid) +#endif + +#if defined __USE_BSD || defined __USE_XOPEN2K +/* Set the effective group ID of the calling process to GID. */ +extern int setegid (__gid_t __gid) __THROW; +#endif /* Use BSD. */ + +#ifdef __USE_GNU +/* Fetch the real user ID, effective user ID, and saved-set user ID, + of the calling process. */ +extern int getresuid (__uid_t *__ruid, __uid_t *__euid, __uid_t *__suid) + __THROW; + +/* Fetch the real group ID, effective group ID, and saved-set group ID, + of the calling process. */ +extern int getresgid (__gid_t *__rgid, __gid_t *__egid, __gid_t *__sgid) + __THROW; + +#if defined __UCLIBC_LINUX_SPECIFIC__ +/* Set the real user ID, effective user ID, and saved-set user ID, + of the calling process to RUID, EUID, and SUID, respectively. */ +extern int setresuid (__uid_t __ruid, __uid_t __euid, __uid_t __suid) + __THROW; +libc_hidden_proto(setresuid) +#endif + +/* Set the real group ID, effective group ID, and saved-set group ID, + of the calling process to RGID, EGID, and SGID, respectively. */ +extern int setresgid (__gid_t __rgid, __gid_t __egid, __gid_t __sgid) + __THROW; +libc_hidden_proto(setresgid) +#endif + + +#if defined __UCLIBC_HAS_STUBS__ || defined __ARCH_USE_MMU__ +/* Clone the calling process, creating an exact copy. + Return -1 for errors, 0 to the new process, + and the process ID of the new process to the old process. */ +extern __pid_t fork (void) __THROW; +libc_hidden_proto(fork) +#endif + +#if defined __USE_BSD || defined __USE_XOPEN_EXTENDED +/* Clone the calling process, but without copying the whole address space. + The calling process is suspended until the new process exits or is + replaced by a call to `execve'. Return -1 for errors, 0 to the new process, + and the process ID of the new process to the old process. */ +extern __pid_t vfork (void) __THROW; +libc_hidden_proto(vfork) +#endif /* Use BSD. */ + +/* Special exit function which only terminates the current thread. */ +extern void __exit_thread (int val) __attribute__ ((__noreturn__)); + +/* Return the pathname of the terminal FD is open on, or NULL on errors. + The returned storage is good only until the next call to this function. */ +extern char *ttyname (int __fd) __THROW; + +/* Store at most BUFLEN characters of the pathname of the terminal FD is + open on in BUF. Return 0 on success, otherwise an error number. */ +extern int ttyname_r (int __fd, char *__buf, size_t __buflen) + __THROW __nonnull ((2)) __wur; +libc_hidden_proto(ttyname_r) + +/* Return 1 if FD is a valid descriptor associated + with a terminal, zero if not. */ +extern int isatty (int __fd) __THROW; +libc_hidden_proto(isatty) + + +#if 0 /*defined __USE_BSD \ + || (defined __USE_XOPEN_EXTENDED && !defined __USE_UNIX98)*/ +/* Return the index into the active-logins file (utmp) for + the controlling terminal. */ +extern int ttyslot (void) __THROW; +#endif + + +/* Make a link to FROM named TO. */ +extern int link (__const char *__from, __const char *__to) + __THROW __nonnull ((1, 2)) __wur; + +#ifdef __USE_ATFILE +/* Like link but relative paths in TO and FROM are interpreted relative + to FROMFD and TOFD respectively. */ +extern int linkat (int __fromfd, __const char *__from, int __tofd, + __const char *__to, int __flags) + __THROW __nonnull ((2, 4)) __wur; +#endif + +#if defined __USE_BSD || defined __USE_XOPEN_EXTENDED || defined __USE_XOPEN2K +/* Make a symbolic link to FROM named TO. */ +extern int symlink (__const char *__from, __const char *__to) + __THROW __nonnull ((1, 2)) __wur; + +/* Read the contents of the symbolic link PATH into no more than + LEN bytes of BUF. The contents are not null-terminated. + Returns the number of characters read, or -1 for errors. */ +extern ssize_t readlink (__const char *__restrict __path, + char *__restrict __buf, size_t __len) + __THROW __nonnull ((1, 2)) __wur; +libc_hidden_proto(readlink) +#endif /* Use BSD. */ + +#ifdef __USE_ATFILE +/* Like symlink but a relative path in TO is interpreted relative to TOFD. */ +extern int symlinkat (__const char *__from, int __tofd, + __const char *__to) __THROW __nonnull ((1, 3)) __wur; + +/* Like readlink but a relative PATH is interpreted relative to FD. */ +extern ssize_t readlinkat (int __fd, __const char *__restrict __path, + char *__restrict __buf, size_t __len) + __THROW __nonnull ((2, 3)) __wur; +#endif + +/* Remove the link NAME. */ +extern int unlink (__const char *__name) __THROW __nonnull ((1)); +libc_hidden_proto(unlink) + +#ifdef __USE_ATFILE +/* Remove the link NAME relative to FD. */ +extern int unlinkat (int __fd, __const char *__name, int __flag) + __THROW __nonnull ((2)); +#endif + +/* Remove the directory PATH. */ +extern int rmdir (__const char *__path) __THROW __nonnull ((1)); +libc_hidden_proto(rmdir) + + +/* Return the foreground process group ID of FD. */ +extern __pid_t tcgetpgrp (int __fd) __THROW; +libc_hidden_proto(tcgetpgrp) + +/* Set the foreground process group ID of FD set PGRP_ID. */ +extern int tcsetpgrp (int __fd, __pid_t __pgrp_id) __THROW; + + +/* Return the login name of the user. + + This function is a possible cancellation points and therefore not + marked with __THROW. */ +extern char *getlogin (void); +libc_hidden_proto(getlogin) +#if defined __USE_REENTRANT || defined __USE_POSIX199506 +/* Return at most NAME_LEN characters of the login name of the user in NAME. + If it cannot be determined or some other error occurred, return the error + code. Otherwise return 0. + + This function is a possible cancellation points and therefore not + marked with __THROW. */ +extern int getlogin_r (char *__name, size_t __name_len) __nonnull ((1)); +#endif + +#if 0 /*def __USE_BSD*/ +/* Set the login name returned by `getlogin'. */ +extern int setlogin (__const char *__name) __THROW __nonnull ((1)); +#endif + + +#ifdef __USE_POSIX2 +/* Get definitions and prototypes for functions to process the + arguments in ARGV (ARGC of them, minus the program name) for + options given in OPTS. */ +# define __need_getopt +/* keep this for uClibc in bits/, we need it when GNU_GETOPT is disabled */ +# include +#endif + + +#if defined __USE_BSD || defined __USE_UNIX98 +/* Put the name of the current host in no more than LEN bytes of NAME. + The result is null-terminated if LEN is large enough for the full + name and the terminator. */ +extern int gethostname (char *__name, size_t __len) __THROW __nonnull ((1)); +libc_hidden_proto(gethostname) +#endif + + +#if defined __USE_BSD || (defined __USE_XOPEN && !defined __USE_UNIX98) +/* Set the name of the current host to NAME, which is LEN bytes long. + This call is restricted to the super-user. */ +extern int sethostname (__const char *__name, size_t __len) + __THROW __nonnull ((1)) __wur; + +/* Set the current machine's Internet number to ID. + This call is restricted to the super-user. */ +extern int sethostid (long int __id) __THROW __wur; + +#if defined __UCLIBC_BSD_SPECIFIC__ || defined _LIBC +/* Get and set the NIS (aka YP) domain name, if any. + Called just like `gethostname' and `sethostname'. + The NIS domain name is usually the empty string when not using NIS. */ +extern int getdomainname (char *__name, size_t __len) + __THROW __nonnull ((1)) __wur; +libc_hidden_proto(getdomainname) +#endif +#if defined __UCLIBC_BSD_SPECIFIC__ +extern int setdomainname (__const char *__name, size_t __len) + __THROW __nonnull ((1)) __wur; +#endif + +#if defined __UCLIBC_LINUX_SPECIFIC__ +/* Revoke access permissions to all processes currently communicating + with the control terminal, and then send a SIGHUP signal to the process + group of the control terminal. */ +extern int vhangup (void) __THROW; +#endif + +#if 0 +/* Revoke the access of all descriptors currently open on FILE. */ +extern int revoke (__const char *__file) __THROW __nonnull ((1)) __wur; + + +/* Enable statistical profiling, writing samples of the PC into at most + SIZE bytes of SAMPLE_BUFFER; every processor clock tick while profiling + is enabled, the system examines the user PC and increments + SAMPLE_BUFFER[((PC - OFFSET) / 2) * SCALE / 65536]. If SCALE is zero, + disable profiling. Returns zero on success, -1 on error. */ +extern int profil (unsigned short int *__sample_buffer, size_t __size, + size_t __offset, unsigned int __scale) + __THROW __nonnull ((1)); +#endif + + +/* Turn accounting on if NAME is an existing file. The system will then write + a record for each process as it terminates, to this file. If NAME is NULL, + turn accounting off. This call is restricted to the super-user. */ +extern int acct (__const char *__name) __THROW; + + +/* Successive calls return the shells listed in `/etc/shells'. */ +extern char *getusershell (void) __THROW; +extern void endusershell (void) __THROW; /* Discard cached info. */ +extern void setusershell (void) __THROW; /* Rewind and re-read the file. */ + + +/* Put the program in the background, and dissociate from the controlling + terminal. If NOCHDIR is zero, do `chdir ("/")'. If NOCLOSE is zero, + redirects stdin, stdout, and stderr to /dev/null. */ +extern int daemon (int __nochdir, int __noclose) __THROW __wur; +#endif /* Use BSD || X/Open. */ + + +#if defined __USE_BSD || (defined __USE_XOPEN && !defined __USE_XOPEN2K) +/* Make PATH be the root directory (the starting point for absolute paths). + This call is restricted to the super-user. */ +extern int chroot (__const char *__path) __THROW __nonnull ((1)) __wur; + +/* Prompt with PROMPT and read a string from the terminal without echoing. + Uses /dev/tty if possible; otherwise stderr and stdin. */ +extern char *getpass (__const char *__prompt) __nonnull ((1)); +#endif /* Use BSD || X/Open. */ + + +#if defined __USE_BSD || defined __USE_XOPEN +/* Make all changes done to FD actually appear on disk. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern int fsync (int __fd); +#endif /* Use BSD || X/Open. */ + + +#if defined __USE_BSD || defined __USE_XOPEN_EXTENDED + +/* Return identifier for the current host. */ +extern long int gethostid (void); + +/* Make all changes done to all files actually appear on disk. */ +extern void sync (void) __THROW; + + +/* Return the number of bytes in a page. This is the system's page size, + which is not necessarily the same as the hardware page size. */ +extern int getpagesize (void) __THROW __attribute__ ((__const__)); +libc_hidden_proto(getpagesize) + + +/* Return the maximum number of file descriptors + the current process could possibly have. */ +extern int getdtablesize (void) __THROW; +libc_hidden_proto(getdtablesize) + + +/* Truncate FILE to LENGTH bytes. */ +# ifndef __USE_FILE_OFFSET64 +extern int truncate (__const char *__file, __off_t __length) + __THROW __nonnull ((1)) __wur; +libc_hidden_proto(truncate) +# else +# ifdef __REDIRECT_NTH +extern int __REDIRECT_NTH (truncate, + (__const char *__file, __off64_t __length), + truncate64) __nonnull ((1)) __wur; +# else +# define truncate truncate64 +# endif +# endif +# ifdef __USE_LARGEFILE64 +extern int truncate64 (__const char *__file, __off64_t __length) + __THROW __nonnull ((1)) __wur; +# endif + +#endif /* Use BSD || X/Open Unix. */ + +#if defined __USE_BSD || defined __USE_XOPEN_EXTENDED || defined __USE_XOPEN2K + +/* Truncate the file FD is open on to LENGTH bytes. */ +# ifndef __USE_FILE_OFFSET64 +extern int ftruncate (int __fd, __off_t __length) __THROW __wur; +libc_hidden_proto(ftruncate) +# else +# ifdef __REDIRECT_NTH +extern int __REDIRECT_NTH (ftruncate, (int __fd, __off64_t __length), + ftruncate64) __wur; +# else +# define ftruncate ftruncate64 +# endif +# endif +# ifdef __USE_LARGEFILE64 +extern int ftruncate64 (int __fd, __off64_t __length) __THROW __wur; +libc_hidden_proto(ftruncate64) +# endif + +#endif /* Use BSD || X/Open Unix || POSIX 2003. */ + + +#if defined __USE_MISC || defined __USE_XOPEN_EXTENDED + +/* Set the end of accessible data space (aka "the break") to ADDR. + Returns zero on success and -1 for errors (with errno set). */ +extern int brk (void *__addr) __THROW __wur; +libc_hidden_proto(brk) + +/* Increase or decrease the end of accessible data space by DELTA bytes. + If successful, returns the address the previous end of data space + (i.e. the beginning of the new space, if DELTA > 0); + returns (void *) -1 for errors (with errno set). */ +extern void *sbrk (intptr_t __delta) __THROW; +libc_hidden_proto(sbrk) +#endif + + +#ifdef __USE_MISC +/* Invoke `system call' number SYSNO, passing it the remaining arguments. + This is completely system-dependent, and not often useful. + + In Unix, `syscall' sets `errno' for all errors and most calls return -1 + for errors; in many systems you cannot pass arguments or get return + values for all system calls (`pipe', `fork', and `getppid' typically + among them). + + In Mach, all system calls take normal arguments and always return an + error code (zero for success). */ +extern long int syscall (long int __sysno, ...) __THROW; + +#endif /* Use misc. */ + + +#if (defined __USE_MISC || defined __USE_XOPEN_EXTENDED) && !defined F_LOCK +/* NOTE: These declarations also appear in ; be sure to keep both + files consistent. Some systems have them there and some here, and some + software depends on the macros being defined without including both. */ + +/* `lockf' is a simpler interface to the locking facilities of `fcntl'. + LEN is always relative to the current file position. + The CMD argument is one of the following. + + This function is a cancellation point and therefore not marked with + __THROW. */ + +# define F_ULOCK 0 /* Unlock a previously locked region. */ +# define F_LOCK 1 /* Lock a region for exclusive use. */ +# define F_TLOCK 2 /* Test and lock a region for exclusive use. */ +# define F_TEST 3 /* Test a region for other processes locks. */ + +# ifndef __USE_FILE_OFFSET64 +extern int lockf (int __fd, int __cmd, __off_t __len) __wur; +libc_hidden_proto(lockf) +# else +# ifdef __REDIRECT +extern int __REDIRECT (lockf, (int __fd, int __cmd, __off64_t __len), + lockf64) __wur; +# else +# define lockf lockf64 +# endif +# endif +# ifdef __USE_LARGEFILE64 +extern int lockf64 (int __fd, int __cmd, __off64_t __len) __wur; +libc_hidden_proto(lockf64) +# endif +#endif /* Use misc and F_LOCK not already defined. */ + + +#ifdef __USE_GNU + +/* Evaluate EXPRESSION, and repeat as long as it returns -1 with `errno' + set to EINTR. */ + +# define TEMP_FAILURE_RETRY(expression) \ + (__extension__ \ + ({ long int __result; \ + do __result = (long int) (expression); \ + while (__result == -1L && errno == EINTR); \ + __result; })) +#endif + +#if (defined __USE_POSIX199309 || defined __USE_UNIX98) \ + && defined __UCLIBC_HAS_REALTIME__ +/* Synchronize at least the data part of a file with the underlying + media. */ +extern int fdatasync (int __fildes) __THROW; +#endif /* Use POSIX199309 */ + + +/* XPG4.2 specifies that prototypes for the encryption functions must + be defined here. */ +#ifdef __USE_XOPEN +# if defined __UCLIBC_HAS_CRYPT__ +/* Encrypt at most 8 characters from KEY using salt to perturb DES. */ +extern char *crypt (__const char *__key, __const char *__salt) + __THROW __nonnull ((1, 2)); + +/* Encrypt data in BLOCK in place if EDFLAG is zero; otherwise decrypt + block in place. */ +extern void encrypt (char *__block, int __edflag) __THROW __nonnull ((1)); +# endif /* __UCLIBC_HAS_CRYPT__ */ + + +/* Swab pairs bytes in the first N bytes of the area pointed to by + FROM and copy the result to TO. The value of TO must not be in the + range [FROM - N + 1, FROM - 1]. If N is odd the first byte in FROM + is without partner. */ +extern void swab (__const void *__restrict __from, void *__restrict __to, + ssize_t __n) __THROW __nonnull ((1, 2)); +#endif + + +/* The Single Unix specification demands this prototype to be here. + It is also found in . */ +#ifdef __USE_XOPEN +/* Return the name of the controlling terminal. */ +extern char *ctermid (char *__s) __THROW; +#endif + + +/* Define some macros helping to catch buffer overflows. */ +#if __USE_FORTIFY_LEVEL > 0 && !defined __cplusplus +# include +#endif + +__END_DECLS + + +#ifdef _LIBC +#ifndef smallint_type /* if arch didn't override it in bits/wordsize.h */ +#define smallint_type int +#endif +typedef signed smallint_type smallint; +typedef unsigned smallint_type smalluint; +#endif + + +#endif /* unistd.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/ustat.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/ustat.h new file mode 100644 index 00000000..cba150e4 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/ustat.h @@ -0,0 +1 @@ +#include diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/utime.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/utime.h new file mode 100644 index 00000000..95942d78 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/utime.h @@ -0,0 +1,53 @@ +/* Copyright (C) 1991, 92, 96, 97, 98, 99, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * POSIX Standard: 5.6.6 Set File Access and Modification Times + */ + +#ifndef _UTIME_H +#define _UTIME_H 1 + +#include + +__BEGIN_DECLS + +#include + +#if defined __USE_XOPEN || defined __USE_XOPEN2K +# define __need_time_t +# include +#endif + +/* Structure describing file times. */ +struct utimbuf + { + __time_t actime; /* Access time. */ + __time_t modtime; /* Modification time. */ + }; + +/* Set the access and modification times of FILE to those given in + *FILE_TIMES. If FILE_TIMES is NULL, set them to the current time. */ +extern int utime (__const char *__file, + __const struct utimbuf *__file_times) + __THROW __nonnull ((1)); +libc_hidden_proto(utime) + +__END_DECLS + +#endif /* utime.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/utmp.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/utmp.h new file mode 100644 index 00000000..e80b65b7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/utmp.h @@ -0,0 +1,106 @@ +/* Copyright (C) 1993, 1996, 1997, 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _UTMP_H +#define _UTMP_H 1 + +#include + +#include + + +__BEGIN_DECLS + +/* Get system dependent values and data structures. */ +#include + +/* Compatibility names for the strings of the canonical file names. */ +#define UTMP_FILE _PATH_UTMP +#define UTMP_FILENAME _PATH_UTMP +#define WTMP_FILE _PATH_WTMP +#define WTMP_FILENAME _PATH_WTMP + + + +#ifdef __UCLIBC_HAS_LIBUTIL__ +/* Make FD be the controlling terminal, stdin, stdout, and stderr; + then close FD. Returns 0 on success, nonzero on error. */ +extern int login_tty (int __fd) __THROW; + + +/* Write the given entry into utmp and wtmp. */ +extern void login (__const struct utmp *__entry) __THROW; + +/* Write the utmp entry to say the user on UT_LINE has logged out. */ +extern int logout (__const char *__ut_line) __THROW; + +/* Append to wtmp an entry for the current time and the given info. */ +extern void logwtmp (__const char *__ut_line, __const char *__ut_name, + __const char *__ut_host) __THROW; +#endif + +/* Append entry UTMP to the wtmp-like file WTMP_FILE. */ +extern void updwtmp (__const char *__wtmp_file, __const struct utmp *__utmp) + __THROW; +libc_hidden_proto(updwtmp) + +/* Change name of the utmp file to be examined. */ +extern int utmpname (__const char *__file) __THROW; +libc_hidden_proto(utmpname) + +/* Read next entry from a utmp-like file. */ +extern struct utmp *getutent (void) __THROW; +libc_hidden_proto(getutent) + +/* Reset the input stream to the beginning of the file. */ +extern void setutent (void) __THROW; +libc_hidden_proto(setutent) + +/* Close the current open file. */ +extern void endutent (void) __THROW; +libc_hidden_proto(endutent) + +/* Search forward from the current point in the utmp file until the + next entry with a ut_type matching ID->ut_type. */ +extern struct utmp *getutid (__const struct utmp *__id) __THROW; + +/* Search forward from the current point in the utmp file until the + next entry with a ut_line matching LINE->ut_line. */ +extern struct utmp *getutline (__const struct utmp *__line) __THROW; +libc_hidden_proto(getutline) + +/* Write out entry pointed to by UTMP_PTR into the utmp file. */ +extern struct utmp *pututline (__const struct utmp *__utmp_ptr) __THROW; +libc_hidden_proto(pututline) + + +#if 0 /* def __USE_MISC */ +/* Reentrant versions of the file for handling utmp files. */ +extern int getutent_r (struct utmp *__buffer, struct utmp **__result) __THROW; + +extern int getutid_r (__const struct utmp *__id, struct utmp *__buffer, + struct utmp **__result) __THROW; + +extern int getutline_r (__const struct utmp *__line, + struct utmp *__buffer, struct utmp **__result) __THROW; + +#endif /* Use misc. */ + +__END_DECLS + +#endif /* utmp.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/utmpx.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/utmpx.h new file mode 100644 index 00000000..8622916a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/utmpx.h @@ -0,0 +1,127 @@ +/* Copyright (C) 1997, 1998, 1999, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _UTMPX_H +#define _UTMPX_H 1 + +#include +#include + +/* Required according to Unix98. */ +#ifndef __pid_t_defined +typedef __pid_t pid_t; +# define __pid_t_defined +#endif + +/* Get system dependent values and data structures. */ +#include + +#ifdef __USE_GNU +/* Compatibility names for the strings of the canonical file names. */ +# define UTMPX_FILE _PATH_UTMPX +# define UTMPX_FILENAME _PATH_UTMPX +# define WTMPX_FILE _PATH_WTMPX +# define WTMPX_FILENAME _PATH_WTMPX +#endif + +/* For the getutmp{,x} functions we need the `struct utmp'. */ +#ifdef __USE_GNU +struct utmp; +#endif + + +__BEGIN_DECLS + +/* Open user accounting database. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern void setutxent (void); + +/* Close user accounting database. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern void endutxent (void); + +/* Get the next entry from the user accounting database. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern struct utmpx *getutxent (void); + +/* Get the user accounting database entry corresponding to ID. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern struct utmpx *getutxid (__const struct utmpx *__id); + +/* Get the user accounting database entry corresponding to LINE. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern struct utmpx *getutxline (__const struct utmpx *__line); + +/* Write the entry UTMPX into the user accounting database. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern struct utmpx *pututxline (__const struct utmpx *__utmpx); + + +#ifdef __USE_GNU +/* Change name of the utmpx file to be examined. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern int utmpxname (__const char *__file); + +/* Append entry UTMP to the wtmpx-like file WTMPX_FILE. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern void updwtmpx (__const char *__wtmpx_file, + __const struct utmpx *__utmpx); + + +/* Copy the information in UTMPX to UTMP. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern void getutmp (__const struct utmpx *__utmpx, + struct utmp *__utmp); + +/* Copy the information in UTMP to UTMPX. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern void getutmpx (__const struct utmp *__utmp, + struct utmpx *__utmpx); +#endif + +__END_DECLS + +#endif /* utmpx.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/values.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/values.h new file mode 100644 index 00000000..daf95118 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/values.h @@ -0,0 +1,73 @@ +/* Old compatibility names for and constants. + Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This interface is obsolete. New programs should use + and/or instead of . */ + +#ifndef _VALUES_H +#define _VALUES_H 1 + +#include + +#include + +#define _TYPEBITS(type) (sizeof (type) * CHAR_BIT) + +#define CHARBITS _TYPEBITS (char) +#define SHORTBITS _TYPEBITS (short int) +#define INTBITS _TYPEBITS (int) +#define LONGBITS _TYPEBITS (long int) +#define PTRBITS _TYPEBITS (char *) +#define DOUBLEBITS _TYPEBITS (double) +#define FLOATBITS _TYPEBITS (float) + +#define MINSHORT SHRT_MIN +#define MININT INT_MIN +#define MINLONG LONG_MIN + +#define MAXSHORT SHRT_MAX +#define MAXINT INT_MAX +#define MAXLONG LONG_MAX + +#define HIBITS MINSHORT +#define HIBITL MINLONG + + +#ifdef __UCLIBC_HAS_FLOATS__ +#include + +#define MAXDOUBLE DBL_MAX +#ifdef __UCLIBC_SUSV4_LEGACY__ +#define MAXFLOAT FLT_MAX +#endif +#define MINDOUBLE DBL_MIN +#define MINFLOAT FLT_MIN +#define DMINEXP DBL_MIN_EXP +#define FMINEXP FLT_MIN_EXP +#define DMAXEXP DBL_MAX_EXP +#define FMAXEXP FLT_MAX_EXP +#endif /* __UCLIBC_HAS_FLOATS__ */ + + +#ifdef __USE_MISC +/* Some systems define this name instead of CHAR_BIT or CHARBITS. */ +# define BITSPERBYTE CHAR_BIT +#endif + +#endif /* values.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/wait.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/wait.h new file mode 100644 index 00000000..d01b8112 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/wait.h @@ -0,0 +1 @@ +#include diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/wchar-stub.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/wchar-stub.h new file mode 100644 index 00000000..0b0aa29a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/wchar-stub.h @@ -0,0 +1,14 @@ +/* This wchar.h is used if wchar support is disabled in uClibc. + * We still want to provide a few basic definitions as the basic + * C standard requires them. And it makes our lives easier with + * no additional overhead. + */ + +#ifndef _WCHAR_H +#define _WCHAR_H + +#define MB_CUR_MAX 1 +typedef unsigned int wint_t; +#define WEOF (0xffffffffu) + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/wchar.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/wchar.h new file mode 100644 index 00000000..3795998a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/wchar.h @@ -0,0 +1,795 @@ +/* Copyright (C) 1995-2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * ISO C99 Standard: 7.24 + * Extended multibyte and wide character utilities + */ + +#ifndef _WCHAR_H + +#ifndef __need_mbstate_t +# define _WCHAR_H 1 +# include +#endif + +#ifndef __UCLIBC_HAS_WCHAR__ +#error Attempted to include wchar.h when uClibc built without wide char support. +#endif + +#ifdef _WCHAR_H +/* Get FILE definition. */ +# define __need___FILE +# ifdef __USE_UNIX98 +# define __need_FILE +# endif +# include +/* Get va_list definition. */ +# define __need___va_list +# include + +/* Get size_t, wchar_t, wint_t and NULL from . */ +# define __need_size_t +# define __need_wchar_t +# define __need_NULL +#endif +#define __need_wint_t +#include + +#include + +/* We try to get wint_t from , but not all GCC versions define it + there. So define it ourselves if it remains undefined. */ +#ifndef _WINT_T +/* Integral type unchanged by default argument promotions that can + hold any value corresponding to members of the extended character + set, as well as at least one value that does not correspond to any + member of the extended character set. */ +# define _WINT_T +typedef unsigned int wint_t; +#else +/* Work around problems with the file which doesn't put + wint_t in the std namespace. */ +# if defined __cplusplus && defined _GLIBCPP_USE_NAMESPACES \ + && defined __WINT_TYPE__ +__BEGIN_NAMESPACE_STD +typedef __WINT_TYPE__ wint_t; +__END_NAMESPACE_STD +# endif +#endif + + +#ifndef __mbstate_t_defined +# define __mbstate_t_defined 1 +/* Conversion state information. */ +#if 1 +typedef struct +{ + wchar_t __mask; + wchar_t __wc; +} __mbstate_t; +#else +typedef struct +{ + int __count; + union + { + wint_t __wch; + char __wchb[4]; + } __value; /* Value so far. */ +} __mbstate_t; +#endif +#endif +#undef __need_mbstate_t + + +/* The rest of the file is only used if used if __need_mbstate_t is not + defined. */ +#ifdef _WCHAR_H + +__BEGIN_NAMESPACE_C99 +/* Public type. */ +typedef __mbstate_t mbstate_t; +__END_NAMESPACE_C99 +#ifdef __USE_GNU +__USING_NAMESPACE_C99(mbstate_t) +#endif + +#ifndef WCHAR_MIN +/* These constants might also be defined in . */ +# define WCHAR_MIN __WCHAR_MIN +# define WCHAR_MAX __WCHAR_MAX +#endif + +#ifndef WEOF +# define WEOF (0xffffffffu) +#endif + +/* For XPG4 compliance we have to define the stuff from here + as well. */ +#if defined __USE_XOPEN && !defined __USE_UNIX98 +# include +#endif + + +__BEGIN_DECLS + +__BEGIN_NAMESPACE_STD +/* This incomplete type is defined in but needed here because + of `wcsftime'. */ +struct tm; +/* XXX We have to clean this up at some point. Since tm is in the std + namespace but wcsftime is in __c99 the type wouldn't be found + without inserting it in the global namespace. */ +__USING_NAMESPACE_STD(tm) +__END_NAMESPACE_STD + + +__BEGIN_NAMESPACE_C99 +/* Copy SRC to DEST. */ +extern wchar_t *wcscpy (wchar_t *__restrict __dest, + __const wchar_t *__restrict __src) __THROW; +/* Copy no more than N wide-characters of SRC to DEST. */ +extern wchar_t *wcsncpy (wchar_t *__restrict __dest, + __const wchar_t *__restrict __src, size_t __n) + __THROW; + +/* Append SRC onto DEST. */ +extern wchar_t *wcscat (wchar_t *__restrict __dest, + __const wchar_t *__restrict __src) __THROW; +libc_hidden_proto(wcscat) +/* Append no more than N wide-characters of SRC onto DEST. */ +extern wchar_t *wcsncat (wchar_t *__restrict __dest, + __const wchar_t *__restrict __src, size_t __n) + __THROW; + +/* Compare S1 and S2. */ +extern int wcscmp (__const wchar_t *__s1, __const wchar_t *__s2) + __THROW __attribute_pure__; +libc_hidden_proto(wcscmp) +/* Compare N wide-characters of S1 and S2. */ +extern int wcsncmp (__const wchar_t *__s1, __const wchar_t *__s2, size_t __n) + __THROW __attribute_pure__; +__END_NAMESPACE_C99 + +#ifdef __USE_GNU +/* Compare S1 and S2, ignoring case. */ +extern int wcscasecmp (__const wchar_t *__s1, __const wchar_t *__s2) __THROW; +libc_hidden_proto(wcscasecmp) + +/* Compare no more than N chars of S1 and S2, ignoring case. */ +extern int wcsncasecmp (__const wchar_t *__s1, __const wchar_t *__s2, + size_t __n) __THROW; +libc_hidden_proto(wcsncasecmp) + +#ifdef __UCLIBC_HAS_XLOCALE__ +/* Similar to the two functions above but take the information from + the provided locale and not the global locale. */ +# include + +extern int wcscasecmp_l (__const wchar_t *__s1, __const wchar_t *__s2, + __locale_t __loc) __THROW; +libc_hidden_proto(wcscasecmp_l) + +extern int wcsncasecmp_l (__const wchar_t *__s1, __const wchar_t *__s2, + size_t __n, __locale_t __loc) __THROW; +libc_hidden_proto(wcsncasecmp_l) +#endif /* __UCLIBC_HAS_XLOCALE__ */ +#endif + +__BEGIN_NAMESPACE_C99 +/* Compare S1 and S2, both interpreted as appropriate to the + LC_COLLATE category of the current locale. */ +extern int wcscoll (__const wchar_t *__s1, __const wchar_t *__s2) __THROW; +libc_hidden_proto(wcscoll) +/* Transform S2 into array pointed to by S1 such that if wcscmp is + applied to two transformed strings the result is the as applying + `wcscoll' to the original strings. */ +extern size_t wcsxfrm (wchar_t *__restrict __s1, + __const wchar_t *__restrict __s2, size_t __n) __THROW; +libc_hidden_proto(wcsxfrm) +__END_NAMESPACE_C99 + +#ifdef __USE_GNU +#ifdef __UCLIBC_HAS_XLOCALE__ +/* Similar to the two functions above but take the information from + the provided locale and not the global locale. */ + +/* Compare S1 and S2, both interpreted as appropriate to the + LC_COLLATE category of the given locale. */ +extern int wcscoll_l (__const wchar_t *__s1, __const wchar_t *__s2, + __locale_t __loc) __THROW; +libc_hidden_proto(wcscoll_l) + +/* Transform S2 into array pointed to by S1 such that if wcscmp is + applied to two transformed strings the result is the as applying + `wcscoll' to the original strings. */ +extern size_t wcsxfrm_l (wchar_t *__s1, __const wchar_t *__s2, + size_t __n, __locale_t __loc) __THROW; +libc_hidden_proto(wcsxfrm_l) + +#endif /* __UCLIBC_HAS_XLOCALE__ */ + +/* Duplicate S, returning an identical malloc'd string. */ +extern wchar_t *wcsdup (__const wchar_t *__s) __THROW __attribute_malloc__; +#endif + +__BEGIN_NAMESPACE_C99 +/* Find the first occurrence of WC in WCS. */ +extern wchar_t *wcschr (__const wchar_t *__wcs, wchar_t __wc) + __THROW __attribute_pure__; +libc_hidden_proto(wcschr) +/* Find the last occurrence of WC in WCS. */ +extern wchar_t *wcsrchr (__const wchar_t *__wcs, wchar_t __wc) + __THROW __attribute_pure__; +__END_NAMESPACE_C99 + +#ifdef __USE_GNU +/* This function is similar to `wcschr'. But it returns a pointer to + the closing NUL wide character in case C is not found in S. */ +extern wchar_t *wcschrnul (__const wchar_t *__s, wchar_t __wc) + __THROW __attribute_pure__; +libc_hidden_proto(wcschrnul) +#endif + +__BEGIN_NAMESPACE_C99 +/* Return the length of the initial segmet of WCS which + consists entirely of wide characters not in REJECT. */ +extern size_t wcscspn (__const wchar_t *__wcs, __const wchar_t *__reject) + __THROW __attribute_pure__; +/* Return the length of the initial segmet of WCS which + consists entirely of wide characters in ACCEPT. */ +extern size_t wcsspn (__const wchar_t *__wcs, __const wchar_t *__accept) + __THROW __attribute_pure__; +libc_hidden_proto(wcsspn) +/* Find the first occurrence in WCS of any character in ACCEPT. */ +extern wchar_t *wcspbrk (__const wchar_t *__wcs, __const wchar_t *__accept) + __THROW __attribute_pure__; +libc_hidden_proto(wcspbrk) +/* Find the first occurrence of NEEDLE in HAYSTACK. */ +extern wchar_t *wcsstr (__const wchar_t *__haystack, __const wchar_t *__needle) + __THROW __attribute_pure__; + +/* Divide WCS into tokens separated by characters in DELIM. */ +extern wchar_t *wcstok (wchar_t *__restrict __s, + __const wchar_t *__restrict __delim, + wchar_t **__restrict __ptr) __THROW; + +/* Return the number of wide characters in S. */ +extern size_t wcslen (__const wchar_t *__s) __THROW __attribute_pure__; +libc_hidden_proto(wcslen) +__END_NAMESPACE_C99 + +#if defined __USE_XOPEN && defined __UCLIBC_SUSV3_LEGACY__ +/* Another name for `wcsstr' from XPG4. */ +extern wchar_t *wcswcs (__const wchar_t *__haystack, __const wchar_t *__needle) + __THROW __attribute_pure__; +#endif + +#ifdef __USE_GNU +/* Return the number of wide characters in S, but at most MAXLEN. */ +extern size_t wcsnlen (__const wchar_t *__s, size_t __maxlen) + __THROW __attribute_pure__; +libc_hidden_proto(wcsnlen) +#endif + + +__BEGIN_NAMESPACE_C99 +/* Search N wide characters of S for C. */ +extern wchar_t *wmemchr (__const wchar_t *__s, wchar_t __c, size_t __n) + __THROW __attribute_pure__; +libc_hidden_proto(wmemchr) + +/* Compare N wide characters of S1 and S2. */ +extern int wmemcmp (__const wchar_t *__restrict __s1, + __const wchar_t *__restrict __s2, size_t __n) + __THROW __attribute_pure__; + +/* Copy N wide characters of SRC to DEST. */ +extern wchar_t *wmemcpy (wchar_t *__restrict __s1, + __const wchar_t *__restrict __s2, size_t __n) __THROW; +libc_hidden_proto(wmemcpy) + +/* Copy N wide characters of SRC to DEST, guaranteeing + correct behavior for overlapping strings. */ +extern wchar_t *wmemmove (wchar_t *__s1, __const wchar_t *__s2, size_t __n) + __THROW; + +/* Set N wide characters of S to C. */ +extern wchar_t *wmemset (wchar_t *__s, wchar_t __c, size_t __n) __THROW; +__END_NAMESPACE_C99 + +#ifdef __USE_GNU +/* Copy N wide characters of SRC to DEST and return pointer to following + wide character. */ +extern wchar_t *wmempcpy (wchar_t *__restrict __s1, + __const wchar_t *__restrict __s2, size_t __n) + __THROW; +libc_hidden_proto(wmempcpy) +#endif + + +__BEGIN_NAMESPACE_C99 +/* Determine whether C constitutes a valid (one-byte) multibyte + character. */ +extern wint_t btowc (int __c) __THROW; +libc_hidden_proto(btowc) + +/* Determine whether C corresponds to a member of the extended + character set whose multibyte representation is a single byte. */ +extern int wctob (wint_t __c) __THROW; + +/* Determine whether PS points to an object representing the initial + state. */ +extern int mbsinit (__const mbstate_t *__ps) __THROW __attribute_pure__; +libc_hidden_proto(mbsinit) + +/* Write wide character representation of multibyte character pointed + to by S to PWC. */ +extern size_t mbrtowc (wchar_t *__restrict __pwc, + __const char *__restrict __s, size_t __n, + mbstate_t *__p) __THROW; +libc_hidden_proto(mbrtowc) + +/* Write multibyte representation of wide character WC to S. */ +extern size_t wcrtomb (char *__restrict __s, wchar_t __wc, + mbstate_t *__restrict __ps) __THROW; +libc_hidden_proto(wcrtomb) + +/* Return number of bytes in multibyte character pointed to by S. */ +#if 0 /* uClibc: disabled */ +extern size_t __mbrlen (__const char *__restrict __s, size_t __n, + mbstate_t *__restrict __ps) __THROW; +#endif +extern size_t mbrlen (__const char *__restrict __s, size_t __n, + mbstate_t *__restrict __ps) __THROW; +libc_hidden_proto(mbrlen) + +/* Write wide character representation of multibyte character string + SRC to DST. */ +extern size_t mbsrtowcs (wchar_t *__restrict __dst, + __const char **__restrict __src, size_t __len, + mbstate_t *__restrict __ps) __THROW; +libc_hidden_proto(mbsrtowcs) + +/* Write multibyte character representation of wide character string + SRC to DST. */ +extern size_t wcsrtombs (char *__restrict __dst, + __const wchar_t **__restrict __src, size_t __len, + mbstate_t *__restrict __ps) __THROW; +libc_hidden_proto(wcsrtombs) +__END_NAMESPACE_C99 + + +#ifdef __USE_GNU +/* Write wide character representation of at most NMC bytes of the + multibyte character string SRC to DST. */ +extern size_t mbsnrtowcs (wchar_t *__restrict __dst, + __const char **__restrict __src, size_t __nmc, + size_t __len, mbstate_t *__restrict __ps) __THROW; +libc_hidden_proto(mbsnrtowcs) + +/* Write multibyte character representation of at most NWC characters + from the wide character string SRC to DST. */ +extern size_t wcsnrtombs (char *__restrict __dst, + __const wchar_t **__restrict __src, + size_t __nwc, size_t __len, + mbstate_t *__restrict __ps) __THROW; +libc_hidden_proto(wcsnrtombs) +#endif /* use GNU */ + + +/* The following functions are extensions found in X/Open CAE. */ +#ifdef __USE_XOPEN +/* Determine number of column positions required for C. */ +extern int wcwidth (wchar_t __c) __THROW; + +/* Determine number of column positions required for first N wide + characters (or fewer if S ends before this) in S. */ +extern int wcswidth (__const wchar_t *__s, size_t __n) __THROW; +libc_hidden_proto(wcswidth) +#endif /* Use X/Open. */ + + +__BEGIN_NAMESPACE_C99 +#ifdef __UCLIBC_HAS_FLOATS__ +/* Convert initial portion of the wide string NPTR to `double' + representation. */ +extern double wcstod (__const wchar_t *__restrict __nptr, + wchar_t **__restrict __endptr) __THROW; + +#ifdef __USE_ISOC99 +/* Likewise for `float' and `long double' sizes of floating-point numbers. */ +extern float wcstof (__const wchar_t *__restrict __nptr, + wchar_t **__restrict __endptr) __THROW; +extern long double wcstold (__const wchar_t *__restrict __nptr, + wchar_t **__restrict __endptr) __THROW; +#endif /* C99 */ +#endif /* __UCLIBC_HAS_FLOATS__ */ + + +/* Convert initial portion of wide string NPTR to `long int' + representation. */ +extern long int wcstol (__const wchar_t *__restrict __nptr, + wchar_t **__restrict __endptr, int __base) __THROW; + +/* Convert initial portion of wide string NPTR to `unsigned long int' + representation. */ +extern unsigned long int wcstoul (__const wchar_t *__restrict __nptr, + wchar_t **__restrict __endptr, int __base) + __THROW; + +#if defined __USE_ISOC99 || (defined __GNUC__ && defined __USE_GNU) +/* Convert initial portion of wide string NPTR to `long int' + representation. */ +__extension__ +extern long long int wcstoll (__const wchar_t *__restrict __nptr, + wchar_t **__restrict __endptr, int __base) + __THROW; + +/* Convert initial portion of wide string NPTR to `unsigned long long int' + representation. */ +__extension__ +extern unsigned long long int wcstoull (__const wchar_t *__restrict __nptr, + wchar_t **__restrict __endptr, + int __base) __THROW; +#endif /* ISO C99 or GCC and GNU. */ +__END_NAMESPACE_C99 + +#if defined __GNUC__ && defined __USE_GNU +/* Convert initial portion of wide string NPTR to `long int' + representation. */ +__extension__ +extern long long int wcstoq (__const wchar_t *__restrict __nptr, + wchar_t **__restrict __endptr, int __base) + __THROW; + +/* Convert initial portion of wide string NPTR to `unsigned long long int' + representation. */ +__extension__ +extern unsigned long long int wcstouq (__const wchar_t *__restrict __nptr, + wchar_t **__restrict __endptr, + int __base) __THROW; +#endif /* GCC and use GNU. */ + +#ifdef __USE_GNU +#ifdef __UCLIBC_HAS_XLOCALE__ +/* The concept of one static locale per category is not very well + thought out. Many applications will need to process its data using + information from several different locales. Another application is + the implementation of the internationalization handling in the + upcoming ISO C++ standard library. To support this another set of + the functions using locale data exist which have an additional + argument. + + Attention: all these functions are *not* standardized in any form. + This is a proof-of-concept implementation. */ + +/* Structure for reentrant locale using functions. This is an + (almost) opaque type for the user level programs. */ +# include + +/* Special versions of the functions above which take the locale to + use as an additional parameter. */ +extern long int wcstol_l (__const wchar_t *__restrict __nptr, + wchar_t **__restrict __endptr, int __base, + __locale_t __loc) __THROW; + +extern unsigned long int wcstoul_l (__const wchar_t *__restrict __nptr, + wchar_t **__restrict __endptr, + int __base, __locale_t __loc) __THROW; + +__extension__ +extern long long int wcstoll_l (__const wchar_t *__restrict __nptr, + wchar_t **__restrict __endptr, + int __base, __locale_t __loc) __THROW; + +__extension__ +extern unsigned long long int wcstoull_l (__const wchar_t *__restrict __nptr, + wchar_t **__restrict __endptr, + int __base, __locale_t __loc) + __THROW; + +#ifdef __UCLIBC_HAS_FLOATS__ +extern double wcstod_l (__const wchar_t *__restrict __nptr, + wchar_t **__restrict __endptr, __locale_t __loc) + __THROW; + +extern float wcstof_l (__const wchar_t *__restrict __nptr, + wchar_t **__restrict __endptr, __locale_t __loc) + __THROW; + +extern long double wcstold_l (__const wchar_t *__restrict __nptr, + wchar_t **__restrict __endptr, + __locale_t __loc) __THROW; +#endif /* __UCLIBC_HAS_FLOATS__ */ +#endif /* __UCLIBC_HAS_XLOCALE__ */ +#endif /* GNU */ + + +#ifdef __USE_GNU +/* Copy SRC to DEST, returning the address of the terminating L'\0' in + DEST. */ +extern wchar_t *wcpcpy (wchar_t *__dest, __const wchar_t *__src) __THROW; + +/* Copy no more than N characters of SRC to DEST, returning the address of + the last character written into DEST. */ +extern wchar_t *wcpncpy (wchar_t *__dest, __const wchar_t *__src, size_t __n) + __THROW; +#endif /* use GNU */ + + +/* Wide character I/O functions. */ +#if defined __USE_ISOC99 || defined __USE_UNIX98 +__BEGIN_NAMESPACE_C99 + +/* Select orientation for stream. */ +extern int fwide (__FILE *__fp, int __mode) __THROW; + + +/* Write formatted output to STREAM. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern int fwprintf (__FILE *__restrict __stream, + __const wchar_t *__restrict __format, ...) + /* __attribute__ ((__format__ (__wprintf__, 2, 3))) */; +libc_hidden_proto(fwprintf) +/* Write formatted output to stdout. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern int wprintf (__const wchar_t *__restrict __format, ...) + /* __attribute__ ((__format__ (__wprintf__, 1, 2))) */; +/* Write formatted output of at most N characters to S. */ +extern int swprintf (wchar_t *__restrict __s, size_t __n, + __const wchar_t *__restrict __format, ...) + __THROW /* __attribute__ ((__format__ (__wprintf__, 3, 4))) */; + +/* Write formatted output to S from argument list ARG. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern int vfwprintf (__FILE *__restrict __s, + __const wchar_t *__restrict __format, + __gnuc_va_list __arg) + /* __attribute__ ((__format__ (__wprintf__, 2, 0))) */; +libc_hidden_proto(vfwprintf) +/* Write formatted output to stdout from argument list ARG. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern int vwprintf (__const wchar_t *__restrict __format, + __gnuc_va_list __arg) + /* __attribute__ ((__format__ (__wprintf__, 1, 0))) */; +/* Write formatted output of at most N character to S from argument + list ARG. */ +extern int vswprintf (wchar_t *__restrict __s, size_t __n, + __const wchar_t *__restrict __format, + __gnuc_va_list __arg) + __THROW /* __attribute__ ((__format__ (__wprintf__, 3, 0))) */; +libc_hidden_proto(vswprintf) + + +/* Read formatted input from STREAM. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern int fwscanf (__FILE *__restrict __stream, + __const wchar_t *__restrict __format, ...) + /* __attribute__ ((__format__ (__wscanf__, 2, 3))) */; +/* Read formatted input from stdin. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern int wscanf (__const wchar_t *__restrict __format, ...) + /* __attribute__ ((__format__ (__wscanf__, 1, 2))) */; +/* Read formatted input from S. */ +extern int swscanf (__const wchar_t *__restrict __s, + __const wchar_t *__restrict __format, ...) + __THROW /* __attribute__ ((__format__ (__wscanf__, 2, 3))) */; + +__END_NAMESPACE_C99 +#endif /* Use ISO C99 and Unix98. */ + +#ifdef __USE_ISOC99 +__BEGIN_NAMESPACE_C99 + +/* Read formatted input from S into argument list ARG. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern int vfwscanf (__FILE *__restrict __s, + __const wchar_t *__restrict __format, + __gnuc_va_list __arg) + /* __attribute__ ((__format__ (__wscanf__, 2, 0))) */; +libc_hidden_proto(vfwscanf) +/* Read formatted input from stdin into argument list ARG. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern int vwscanf (__const wchar_t *__restrict __format, + __gnuc_va_list __arg) + /* __attribute__ ((__format__ (__wscanf__, 1, 0))) */; +/* Read formatted input from S into argument list ARG. */ +extern int vswscanf (__const wchar_t *__restrict __s, + __const wchar_t *__restrict __format, + __gnuc_va_list __arg) + __THROW /* __attribute__ ((__format__ (__wscanf__, 2, 0))) */; +libc_hidden_proto(vswscanf) + +__END_NAMESPACE_C99 +#endif /* Use ISO C99. */ + + +__BEGIN_NAMESPACE_C99 +/* Read a character from STREAM. + + These functions are possible cancellation points and therefore not + marked with __THROW. */ +extern wint_t fgetwc (__FILE *__stream); +libc_hidden_proto(fgetwc) +extern wint_t getwc (__FILE *__stream); + +/* Read a character from stdin. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern wint_t getwchar (void); + + +/* Write a character to STREAM. + + These functions are possible cancellation points and therefore not + marked with __THROW. */ +extern wint_t fputwc (wchar_t __wc, __FILE *__stream); +extern wint_t putwc (wchar_t __wc, __FILE *__stream); + +/* Write a character to stdout. + + This function is a possible cancellation points and therefore not + marked with __THROW. */ +extern wint_t putwchar (wchar_t __wc); + + +/* Get a newline-terminated wide character string of finite length + from STREAM. + + This function is a possible cancellation points and therefore not + marked with __THROW. */ +extern wchar_t *fgetws (wchar_t *__restrict __ws, int __n, + __FILE *__restrict __stream); + +/* Write a string to STREAM. + + This function is a possible cancellation points and therefore not + marked with __THROW. */ +extern int fputws (__const wchar_t *__restrict __ws, + __FILE *__restrict __stream); +libc_hidden_proto(fputws) + + +/* Push a character back onto the input buffer of STREAM. + + This function is a possible cancellation points and therefore not + marked with __THROW. */ +extern wint_t ungetwc (wint_t __wc, __FILE *__stream); +libc_hidden_proto(ungetwc) +__END_NAMESPACE_C99 + + +#ifdef __USE_GNU +/* These are defined to be equivalent to the `char' functions defined + in POSIX.1:1996. + + These functions are not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation they are cancellation points and + therefore not marked with __THROW. */ +extern wint_t getwc_unlocked (__FILE *__stream); +extern wint_t getwchar_unlocked (void); + +/* This is the wide character version of a GNU extension. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern wint_t fgetwc_unlocked (__FILE *__stream); +libc_hidden_proto(fgetwc_unlocked) + +/* Faster version when locking is not necessary. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern wint_t fputwc_unlocked (wchar_t __wc, __FILE *__stream); +libc_hidden_proto(fputwc_unlocked) + +/* These are defined to be equivalent to the `char' functions defined + in POSIX.1:1996. + + These functions are not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation they are cancellation points and + therefore not marked with __THROW. */ +extern wint_t putwc_unlocked (wchar_t __wc, __FILE *__stream); +extern wint_t putwchar_unlocked (wchar_t __wc); + + +/* This function does the same as `fgetws' but does not lock the stream. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern wchar_t *fgetws_unlocked (wchar_t *__restrict __ws, int __n, + __FILE *__restrict __stream); +libc_hidden_proto(fgetws_unlocked) + +/* This function does the same as `fputws' but does not lock the stream. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern int fputws_unlocked (__const wchar_t *__restrict __ws, + __FILE *__restrict __stream); +libc_hidden_proto(fputws_unlocked) +#endif + + +__BEGIN_NAMESPACE_C99 +/* Format TP into S according to FORMAT. + Write no more than MAXSIZE wide characters and return the number + of wide characters written, or 0 if it would exceed MAXSIZE. */ +extern size_t wcsftime (wchar_t *__restrict __s, size_t __maxsize, + __const wchar_t *__restrict __format, + __const struct tm *__restrict __tp) __THROW; +libc_hidden_proto(wcsftime) +__END_NAMESPACE_C99 + +# if defined __USE_GNU && defined __UCLIBC_HAS_XLOCALE__ +# include + +/* Similar to `wcsftime' but takes the information from + the provided locale and not the global locale. */ +extern size_t wcsftime_l (wchar_t *__restrict __s, size_t __maxsize, + __const wchar_t *__restrict __format, + __const struct tm *__restrict __tp, + __locale_t __loc) __THROW; +libc_hidden_proto(wcsftime_l) +# endif + +/* The X/Open standard demands that most of the functions defined in + the header must also appear here. This is probably + because some X/Open members wrote their implementation before the + ISO C standard was published and introduced the better solution. + We have to provide these definitions for compliance reasons but we + do this nonsense only if really necessary. */ +#if defined __USE_UNIX98 && !defined __USE_GNU +# define __need_iswxxx +# include +#endif + +__END_DECLS + +#endif /* _WCHAR_H defined */ + +#endif /* wchar.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/wctype.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/wctype.h new file mode 100644 index 00000000..7b697d2b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/wctype.h @@ -0,0 +1,345 @@ +/* Copyright (C) 1996,97,98,99,2000,01,02 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * ISO C99 Standard: 7.25 + * Wide character classification and mapping utilities + */ + +#ifndef _WCTYPE_H + +#include +#include + +#ifndef __UCLIBC_HAS_WCHAR__ +#error Attempted to include wctype.h when uClibc built without wide char support. +#endif + +#ifndef __need_iswxxx +# define _WCTYPE_H 1 + +/* We try to get wint_t from , but not all GCC versions define it + there. So define it ourselves if it remains undefined. */ +# define __need_wint_t +# include +# ifndef _WINT_T +/* Integral type unchanged by default argument promotions that can + hold any value corresponding to members of the extended character + set, as well as at least one value that does not correspond to any + member of the extended character set. */ +# define _WINT_T +typedef unsigned int wint_t; +# else +# ifdef __USE_ISOC99 +__USING_NAMESPACE_C99(wint_t) +# endif +# endif + +/* Constant expression of type `wint_t' whose value does not correspond + to any member of the extended character set. */ +# ifndef WEOF +# define WEOF (0xffffffffu) +# endif +#endif +#undef __need_iswxxx + + +/* The following part is also used in the header when compiled + in the Unix98 compatibility mode. */ +#ifndef __iswxxx_defined +# define __iswxxx_defined 1 + +__BEGIN_NAMESPACE_C99 +/* Scalar type that can hold values which represent locale-specific + character classifications. */ +/* uClibc note: glibc uses - typedef unsigned long int wctype_t; */ +typedef unsigned int wctype_t; +__END_NAMESPACE_C99 + +# ifndef _ISwbit +# define _ISwbit(bit) (1 << (bit)) + +enum +{ + __ISwupper = 0, /* UPPERCASE. */ + __ISwlower = 1, /* lowercase. */ + __ISwalpha = 2, /* Alphabetic. */ + __ISwdigit = 3, /* Numeric. */ + __ISwxdigit = 4, /* Hexadecimal numeric. */ + __ISwspace = 5, /* Whitespace. */ + __ISwprint = 6, /* Printing. */ + __ISwgraph = 7, /* Graphical. */ + __ISwblank = 8, /* Blank (usually SPC and TAB). */ + __ISwcntrl = 9, /* Control character. */ + __ISwpunct = 10, /* Punctuation. */ + __ISwalnum = 11, /* Alphanumeric. */ + + _ISwupper = _ISwbit (__ISwupper), /* UPPERCASE. */ + _ISwlower = _ISwbit (__ISwlower), /* lowercase. */ + _ISwalpha = _ISwbit (__ISwalpha), /* Alphabetic. */ + _ISwdigit = _ISwbit (__ISwdigit), /* Numeric. */ + _ISwxdigit = _ISwbit (__ISwxdigit), /* Hexadecimal numeric. */ + _ISwspace = _ISwbit (__ISwspace), /* Whitespace. */ + _ISwprint = _ISwbit (__ISwprint), /* Printing. */ + _ISwgraph = _ISwbit (__ISwgraph), /* Graphical. */ + _ISwblank = _ISwbit (__ISwblank), /* Blank (usually SPC and TAB). */ + _ISwcntrl = _ISwbit (__ISwcntrl), /* Control character. */ + _ISwpunct = _ISwbit (__ISwpunct), /* Punctuation. */ + _ISwalnum = _ISwbit (__ISwalnum) /* Alphanumeric. */ +}; +# else +# if defined(__UCLIBC_MJN3_ONLY__) && defined(L_iswctype) +#warning remove _ISwbit already defined check? +#error _ISwbit already defined! +# endif +# endif /* Not _ISwbit */ + + +__BEGIN_DECLS + +__BEGIN_NAMESPACE_C99 +/* + * Wide-character classification functions: 7.15.2.1. + */ + +/* Test for any wide character for which `iswalpha' or `iswdigit' is + true. */ +extern int iswalnum (wint_t __wc) __THROW; +libc_hidden_proto(iswalnum) + +/* Test for any wide character for which `iswupper' or 'iswlower' is + true, or any wide character that is one of a locale-specific set of + wide-characters for which none of `iswcntrl', `iswdigit', + `iswpunct', or `iswspace' is true. */ +extern int iswalpha (wint_t __wc) __THROW; + +/* Test for any control wide character. */ +extern int iswcntrl (wint_t __wc) __THROW; + +/* Test for any wide character that corresponds to a decimal-digit + character. */ +extern int iswdigit (wint_t __wc) __THROW; + +/* Test for any wide character for which `iswprint' is true and + `iswspace' is false. */ +extern int iswgraph (wint_t __wc) __THROW; + +/* Test for any wide character that corresponds to a lowercase letter + or is one of a locale-specific set of wide characters for which + none of `iswcntrl', `iswdigit', `iswpunct', or `iswspace' is true. */ +extern int iswlower (wint_t __wc) __THROW; +libc_hidden_proto(iswlower) + +/* Test for any printing wide character. */ +extern int iswprint (wint_t __wc) __THROW; + +/* Test for any printing wide character that is one of a + locale-specific et of wide characters for which neither `iswspace' + nor `iswalnum' is true. */ +extern int iswpunct (wint_t __wc) __THROW; + +/* Test for any wide character that corresponds to a locale-specific + set of wide characters for which none of `iswalnum', `iswgraph', or + `iswpunct' is true. */ +extern int iswspace (wint_t __wc) __THROW; + +/* Test for any wide character that corresponds to an uppercase letter + or is one of a locale-specific set of wide character for which none + of `iswcntrl', `iswdigit', `iswpunct', or `iswspace' is true. */ +extern int iswupper (wint_t __wc) __THROW; +libc_hidden_proto(iswspace) + +/* Test for any wide character that corresponds to a hexadecimal-digit + character equivalent to that performed be the functions described + in the previous subclause. */ +extern int iswxdigit (wint_t __wc) __THROW; + +/* Test for any wide character that corresponds to a standard blank + wide character or a locale-specific set of wide characters for + which `iswalnum' is false. */ +# ifdef __USE_ISOC99 +extern int iswblank (wint_t __wc) __THROW; +# endif + +/* + * Extensible wide-character classification functions: 7.15.2.2. + */ + +/* Construct value that describes a class of wide characters identified + by the string argument PROPERTY. */ +extern wctype_t wctype (__const char *__property) __THROW; +libc_hidden_proto(wctype) + +/* Determine whether the wide-character WC has the property described by + DESC. */ +extern int iswctype (wint_t __wc, wctype_t __desc) __THROW; +libc_hidden_proto(iswctype) +__END_NAMESPACE_C99 + + +/* + * Wide-character case-mapping functions: 7.15.3.1. + */ + +__BEGIN_NAMESPACE_C99 +/* Scalar type that can hold values which represent locale-specific + character mappings. */ +/* uClibc note: glibc uses - typedef __const __int32_t *wctrans_t; */ +typedef unsigned int wctrans_t; +__END_NAMESPACE_C99 +#ifdef __USE_GNU +__USING_NAMESPACE_C99(wctrans_t) +#endif + +__BEGIN_NAMESPACE_C99 +/* Converts an uppercase letter to the corresponding lowercase letter. */ +extern wint_t towlower (wint_t __wc) __THROW; +libc_hidden_proto(towlower) + +/* Converts an lowercase letter to the corresponding uppercase letter. */ +extern wint_t towupper (wint_t __wc) __THROW; +libc_hidden_proto(towupper) +__END_NAMESPACE_C99 + +__END_DECLS + +#endif /* need iswxxx. */ + + +/* The remaining definitions and declarations must not appear in the + header. */ +#ifdef _WCTYPE_H + +/* + * Extensible wide-character mapping functions: 7.15.3.2. + */ + +__BEGIN_DECLS + +__BEGIN_NAMESPACE_C99 +/* Construct value that describes a mapping between wide characters + identified by the string argument PROPERTY. */ +extern wctrans_t wctrans (__const char *__property) __THROW; +libc_hidden_proto(wctrans) + +/* Map the wide character WC using the mapping described by DESC. */ +extern wint_t towctrans (wint_t __wc, wctrans_t __desc) __THROW; +libc_hidden_proto(towctrans) +__END_NAMESPACE_C99 + +#if defined(__USE_GNU) && defined(__UCLIBC_HAS_XLOCALE__) +/* Declare the interface to extended locale model. */ +# include + +/* Test for any wide character for which `iswalpha' or `iswdigit' is + true. */ +extern int iswalnum_l (wint_t __wc, __locale_t __locale) __THROW; + +/* Test for any wide character for which `iswupper' or 'iswlower' is + true, or any wide character that is one of a locale-specific set of + wide-characters for which none of `iswcntrl', `iswdigit', + `iswpunct', or `iswspace' is true. */ +extern int iswalpha_l (wint_t __wc, __locale_t __locale) __THROW; + +/* Test for any control wide character. */ +extern int iswcntrl_l (wint_t __wc, __locale_t __locale) __THROW; + +/* Test for any wide character that corresponds to a decimal-digit + character. */ +extern int iswdigit_l (wint_t __wc, __locale_t __locale) __THROW; + +/* Test for any wide character for which `iswprint' is true and + `iswspace' is false. */ +extern int iswgraph_l (wint_t __wc, __locale_t __locale) __THROW; + +/* Test for any wide character that corresponds to a lowercase letter + or is one of a locale-specific set of wide characters for which + none of `iswcntrl', `iswdigit', `iswpunct', or `iswspace' is true. */ +extern int iswlower_l (wint_t __wc, __locale_t __locale) __THROW; + +/* Test for any printing wide character. */ +extern int iswprint_l (wint_t __wc, __locale_t __locale) __THROW; + +/* Test for any printing wide character that is one of a + locale-specific et of wide characters for which neither `iswspace' + nor `iswalnum' is true. */ +extern int iswpunct_l (wint_t __wc, __locale_t __locale) __THROW; + +/* Test for any wide character that corresponds to a locale-specific + set of wide characters for which none of `iswalnum', `iswgraph', or + `iswpunct' is true. */ +extern int iswspace_l (wint_t __wc, __locale_t __locale) __THROW; +libc_hidden_proto(iswspace_l) + +/* Test for any wide character that corresponds to an uppercase letter + or is one of a locale-specific set of wide character for which none + of `iswcntrl', `iswdigit', `iswpunct', or `iswspace' is true. */ +extern int iswupper_l (wint_t __wc, __locale_t __locale) __THROW; + +/* Test for any wide character that corresponds to a hexadecimal-digit + character equivalent to that performed be the functions described + in the previous subclause. */ +extern int iswxdigit_l (wint_t __wc, __locale_t __locale) __THROW; + +/* Test for any wide character that corresponds to a standard blank + wide character or a locale-specific set of wide characters for + which `iswalnum' is false. */ +extern int iswblank_l (wint_t __wc, __locale_t __locale) __THROW; + +/* Construct value that describes a class of wide characters identified + by the string argument PROPERTY. */ +extern wctype_t wctype_l (__const char *__property, __locale_t __locale) + __THROW; +libc_hidden_proto(wctype_l) + +/* Determine whether the wide-character WC has the property described by + DESC. */ +extern int iswctype_l (wint_t __wc, wctype_t __desc, __locale_t __locale) + __THROW; +libc_hidden_proto(iswctype_l) + + +/* + * Wide-character case-mapping functions. + */ + +/* Converts an uppercase letter to the corresponding lowercase letter. */ +extern wint_t towlower_l (wint_t __wc, __locale_t __locale) __THROW; +libc_hidden_proto(towlower_l) + +/* Converts an lowercase letter to the corresponding uppercase letter. */ +extern wint_t towupper_l (wint_t __wc, __locale_t __locale) __THROW; +libc_hidden_proto(towupper_l) + +/* Construct value that describes a mapping between wide characters + identified by the string argument PROPERTY. */ +extern wctrans_t wctrans_l (__const char *__property, __locale_t __locale) + __THROW; + +/* Map the wide character WC using the mapping described by DESC. */ +extern wint_t towctrans_l (wint_t __wc, wctrans_t __desc, + __locale_t __locale) __THROW; +libc_hidden_proto(towctrans_l) + +# endif /* Use GNU. */ + +__END_DECLS + +#endif /* __WCTYPE_H defined. */ + +#endif /* wctype.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/wordexp.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/wordexp.h new file mode 100644 index 00000000..f542e92d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/wordexp.h @@ -0,0 +1,72 @@ +/* Copyright (C) 1991, 92, 1996-1999, 2001, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _WORDEXP_H +#define _WORDEXP_H 1 + +#include +#define __need_size_t +#include + +__BEGIN_DECLS + +/* Bits set in the FLAGS argument to `wordexp'. */ +enum + { + WRDE_DOOFFS = (1 << 0), /* Insert PWORDEXP->we_offs NULLs. */ + WRDE_APPEND = (1 << 1), /* Append to results of a previous call. */ + WRDE_NOCMD = (1 << 2), /* Don't do command substitution. */ + WRDE_REUSE = (1 << 3), /* Reuse storage in PWORDEXP. */ + WRDE_SHOWERR = (1 << 4), /* Don't redirect stderr to /dev/null. */ + WRDE_UNDEF = (1 << 5), /* Error for expanding undefined variables. */ + __WRDE_FLAGS = (WRDE_DOOFFS | WRDE_APPEND | WRDE_NOCMD | + WRDE_REUSE | WRDE_SHOWERR | WRDE_UNDEF) + }; + +/* Structure describing a word-expansion run. */ +typedef struct + { + size_t we_wordc; /* Count of words matched. */ + char **we_wordv; /* List of expanded words. */ + size_t we_offs; /* Slots to reserve in `we_wordv'. */ + } wordexp_t; + +/* Possible nonzero return values from `wordexp'. */ +enum + { +#ifdef __USE_XOPEN + WRDE_NOSYS = -1, /* Never used since we support `wordexp'. */ +#endif + WRDE_NOSPACE = 1, /* Ran out of memory. */ + WRDE_BADCHAR, /* A metachar appears in the wrong place. */ + WRDE_BADVAL, /* Undefined var reference with WRDE_UNDEF. */ + WRDE_CMDSUB, /* Command substitution with WRDE_NOCMD. */ + WRDE_SYNTAX /* Shell syntax error. */ + }; + +/* Do word expansion of WORDS into PWORDEXP. */ +extern int wordexp (__const char *__restrict __words, + wordexp_t *__restrict __pwordexp, int __flags); + +/* Free the storage allocated by a `wordexp' call. */ +extern void wordfree (wordexp_t *__wordexp) __THROW; +libc_hidden_proto(wordfree) + +__END_DECLS + +#endif /* wordexp.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/include/xlocale.h b/l4/pkg/uclibc/lib/contrib/uclibc/include/xlocale.h new file mode 100644 index 00000000..51a787f1 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/include/xlocale.h @@ -0,0 +1,62 @@ +/* Definition of locale datatype. + Copyright (C) 1997,2000,02 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _XLOCALE_H +#define _XLOCALE_H 1 + +#include + +#ifndef __UCLIBC_HAS_XLOCALE__ +#error Attempted to include xlocale.h when uClibc built without extended locale support. +#endif + +#include +/* #include */ + +#if 0 +/* Structure for reentrant locale using functions. This is an + (almost) opaque type for the user level programs. The file and + this data structure is not standardized. Don't rely on it. It can + go away without warning. */ +typedef struct __locale_struct +{ +#if 0 + /* Note: LC_ALL is not a valid index into this array. */ + struct locale_data *__locales[13]; /* 13 = __LC_LAST. */ +#endif + + /* To increase the speed of this solution we add some special members. */ +/* const unsigned short int *__ctype_b; */ +/* const int *__ctype_tolower; */ +/* const int *__ctype_toupper; */ + const __uint16_t *__ctype_b; + const __ctype_touplow_t *__ctype_tolower; + const __ctype_touplow_t *__ctype_toupper; + + struct __uclibc_locale_struct *__locale_ptr; + +#if 0 + /* Note: LC_ALL is not a valid index into this array. */ + const char *__names[13]; +#endif +} *__locale_t; +#endif + +#endif /* xlocale.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/COPYRIGHT b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/COPYRIGHT new file mode 100644 index 00000000..fb34248e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/COPYRIGHT @@ -0,0 +1,49 @@ +/* + * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald, David Engel, + * Hongjiu Lu and Mitch D'Souza + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. The name of the above contributors may not be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* Notice of general intent: + * + * The linux operating system generally contains large amounts of code + * that fall under the GNU General Public License, or GPL for short. + * This file contains source code that by it's very nature would always + * be linked with an application program, and because of this a GPL + * type of copyright on this file would place restrictions upon the + * distribution of binary-only commercial software. Since the goal of + * the Linux project as a whole is not to discourage the development and + * distribution of commercial software for Linux, this file has been + * placed under a more relaxed BSD-style of copyright. + * + * It is the general understanding of the above contributors that a + * program executable linked to a library containing code that falls + * under the GPL or GLPL style of license is not subject to the terms of + * the GPL or GLPL license if the program executable(s) that are supplied + * are linked to a shared library form of the GPL or GLPL library, and as + * long as the form of the shared library is such that it is possible for + * the end user to modify and rebuild the library and use it in + * conjunction with the program executable. + */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/Makefile new file mode 100644 index 00000000..c8dc9b46 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../ +top_builddir=../ +include $(top_builddir)Rules.mak +all: libs +include Makefile.in +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/Makefile.in new file mode 100644 index 00000000..7bbef23a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/Makefile.in @@ -0,0 +1,9 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +include $(top_srcdir)ldso/ldso/Makefile.in +include $(top_srcdir)ldso/libdl/Makefile.in diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/README b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/README new file mode 100644 index 00000000..dc37ea65 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/README @@ -0,0 +1,841 @@ + +Apr 20, 2001 -- Manuel Novoa III + +Inital port for uClibc from debian ld.so_1.9.11-9.tar.gz. + +Removed a.out support. + +****************** original ld.so.lsm file ************************** +Begin3 +Title: Linux shared, dynamic linker and utilities. +Version: 1.9.11 +Entered-date: 01MAY99 +Description: This package contains ld.so, ld-linux.so, ldconfig, + ldd and libdl. +Keywords: dynamic linker, shared library, ld.so, ld-linux.so, + ldconfig, ldd, libdl +Author: david@ods.com (David Engel) +Maintained-by: david@ods.com (David Engel) +Primary-site: tsx-11.mit.edu /pub/linux/packages/GCC + ld.so-1.9.11.tar.gz +Alternate-site: sunsite.unc.edu /pub/Linux/GCC + ld.so-1.9.11.tar.gz +Platform: Linux 2.0.0 or later. +Copying-policy: Copyrighted but freely distributable. +End +********************************************************************* + Original README starts here +********************************************************************* + +This package contains my ELF dynamic linkers (ld-linux.so.1), dynamic +linker library (libdl.so.1) and utilities (ldconfig and ldd) for Linux. + +You need Linux kernel 2.0.0 or later with ELF support compiled in +(i.e. not loaded as a module) to use this package. + +The dynamic linker is used to bootstrap programs and load shared +libraries at startup. The dynamic linker library is used to +dynamically load shared libraries after a program is running. +Ldconfig is used to automatically update the symbolic links to shared +libraries and build the cache file used by the dynamic linker. Ldd is +used to list the shared libraries used by a program. + +Please see the included manual pages for further details. + +To install, simply run "sh instldso.sh" as root. Ready-to-go versions +of all end-products are provided so nothing should need to be compiled +or linked. If you are still using libc5 as your primary development +library, you should use the "--devfiles" option when running +instldso.sh to install the file needed to compile with libdl. + +ELF versions of gcc, binutils and libc are now required to compile +everything, including the old, unsupported, a.out dynamic linker. +Finally, an optimization level of O2 or higher must be used to compile +ld-linux.so and libdl.so due the use of inline functions. + +Notable contributors to this package include Eric Youngdale, Peter +MacDonald, Hongjiu Lu, Linus Torvalds, Lars Wirzenius, Mitch D'Souza, +Rik Faith, Andreas Schwab and Adam Richter (not necessarily in that +order). + +###################### IMPORTANT NOTICES ############################# + +A.OUT SUPPORT: + +As of ld.so-1.9.0, the old, a.out dynamic loader is no longer +officially supported. The code is still included and built, but I +make no promises that it will work. I will accept patches for it, +but they will not be tested by me. + +GLIBC (AKA LIBC6) SUPPORT: + +As of ld.so-1.9.0, the main focus of this package is to ease the +transition to libc6. No significant, new features are expected to be +added. If you need new features, switch to libc6. + +Except for libpthread.so, the sonames of the core libraries provided +with libc6 have been chosen so they do not conflict with those +provided by libc5 and ld.so. However, the current plan is not use +new, nonconflicting sonames for other libraries such as ncurses and +X11. This presents two problems. First, libraries using the same +soname for both libc5 and libc6 can not be placed in the same +directory. Second, the dynamic linkers need to make sure not to load +a library for the wrong version of libc. + +The first problem is easy. Just move the old, libc5-based libraries +to new directories (e.g. /lib/libc5-compat, /usr/lib/libc5-compat, +etc.) and add those directories to /etc/ld.so.conf. Then install the +new, libc6-based versions in the standard places. + +The second problem is more difficult. Ideally, the dynamic linkers +would be changed to perform a complete dependency analysis on every +library to be loaded to make sure the wrong versions aren't used. +This approach doesn't seem worth the added complexity, especially +since we now have symbol versioning for ELF libraries. Instead a +simpler approach will be used, at least initially. + +Ldconfig has been modified to perform a (currently simple) dependency +analysis on libraries and to store an indication in /etc/ld.so.cache +of whether a library is for libc5, libc6 or an unknown libc. The +dynamic linkers then only need to make a simple check at run-time to +make sure they don't load the wrong version of a library. + +The dynamic linker for libc5 provided in this package, has already +been modified to use the new information in /etc/ld.so.cache. For +glibc versions 2.0.1 and earlier, the dynamic linker for libc6 needs +the patch contained in glibc.patch. You should apply the patch and +rebuild glibc before using the new ldconfig. + +As stated above, the dependency analysis currently done by ldconfig is +rather simple. Basically, it looks for the sonames used by the +various versions of libc, libm and libdl. For any approach using a +dependency analysis such as this to work, it is very important that +shared libraries be built with complete dependency information. This +can be done by using the appropriate -l options when running 'gcc +-shared'. For example, when building libfoo.so which depends on libc +and libbar, you should add -lbar and -lc gcc command line. + +###################################################################### + +Changes in version 1.9.11: + + Fixed a bug in ld-linux.so where a reference to an + undefined symbol could cause a segfault. + + Added a clarification for LD_PRELOAD to the ld.so manual + page and added a symlink for ld-linux.so (Bug#33123). + + Don't install ldd for Debian except for the m68k arch + because glibc 2.1 now includes it (Bug#35458). + +Changes in version 1.9.10: + + Changed ldconfig to issue a warning and not overwrite a + regular file with a symlink (Bug#30859). + + Changed Debian packaging to conflict with and replace the + ldconfig package (Bug#29398). + +Changes in version 1.9.9: + + Changed ld-linux.so and libdl.so to match glibc by not + allowing user preloads of system libraries into setu/gid + binaries unless the library itself is setuid. + + Fixed problems in ld-linux.so on the sparc architecture + (Juan Cespedes). + +Changes in version 1.9.8: + + Changed ldconfig to allow the expected type for all + libraries in a directory to be optionally specified + (Mark Phillips). See the ldconfig man page. + + Changed ldconfig to use the same type names used in the + change above when the -p option is used. + +Changes in version 1.9.7: + + Changed ldd for m68k to use /lib/ld.so.1 instead of + /lib/ld-linux.so.2. + + Added support for dladdr to libdl.so (Eduard Gode). + + Fixed a small memory leak in libdl.so (Richard Garnish). + + Fixed a bug in ldconfig when the -l option was used on a + filename without a '/' in it. + + Updated the man pages (Bug#6404, Bug#9721, Bug#10652, + Bug#13494 and Bug#14127). They could still use some work. + + No longer install the info page since it's way out of date. + + Fixed minor Debian packaging problems (Bug#13160, + Bug#15577 and Bug#19345). + +Changes in version 1.9.6: + + Changed ldd to not use the glibc dynamic linker when run + on a libc5-based shared library. + + Added a -q option to ldconfig which causes warnings not + to be printed (Bob Tinsley). + + Dropped support for the Debian libdl1-dev package. + + Changed ld-linux.so to be compilable with gcc 2.8.0 (Sven + Verdoolaege) + +Changes in version 1.9.5: + + Fixed a bug in ldd where ld-linux.so.2 was not called + correctly when run on shared libraries. + + Fixed a problem in the previous version where some + Makefiles were not architecture independent. + +Changes in version 1.9.4: + + Fixed a bug in ld.so introduced in the previous version + which broke preloads. + + Turned a.out support back on by default, at least for the + time being. There are no promises to keep it. + +Changes in version 1.9.3: + + Fixed buffer overflow bugs in ld-linux.so and ld.so. + + Changed the README file a little to clarify a couple of + things. + + Changed ldconfig to chroot to the specified directory when + the new -r option is used (Bob Tinsley). + +Changes in version 1.9.2: + + Removed /usr/local/lib from the default /etc/ld.so.conf + for Debian (Bug#8181). + + Changed ldconfig to be 64-bit clean (H.J. Lu). + +Changes in version 1.9.1: + + Changed ldconfig to try to determine which libc a + library is for even if it doesn't have an soname. + + Fixed a bug in ldconfig where an older library using + the glibc naming convention would be used instead of + a newer library. + + Changed to ld-linux.so and libdl.so to not require the + libc5 headers in order to compile. + + Changed ldconfig and ldd to be compilable with either + libc5 or libc6. + +Changes in version 1.9.0: + + Changed to not build the old, a.out dynamic loader by + default. + + Changed instldso.sh to require the --force option to + make sure users read the README file. + + Changed instldso.sh to not install the libdl.so + development files unless the --devfiles option is used. + + Changed instldso.sh to not strip binaries and libraries + if the --no-strip option is used. + + Changed the Debian packaging to put the development files + which conflict with glibc in a new libdl1-dev package. + + Changed ldd to use the glibc dynamic linker, if it is + available, when run on a shared library. + + Changed ld-linux.so to print the load addresses of + libraries, ala glibc, when run by ldd. + + Changed ld-linux.so to allow the libraries listed in + LD_PRELOAD to be separated by white space in addition to + colons. + + Changed ld-linux.so to load the libraries listed in + LD_PRELOAD for setu/gid programs as long as they can be + loaded securely. + + Changed ldconfig to update the symlinks for the dynamic + linkers. + + Changed ldconfig to try to determine if an ELF library is + intended for libc5 or libc6 and save the infomation in the + cache. The mechanism used is rather simplistic and may + need to be enhanced. + + Changed ldconfig to print the type of ELF library when + printing the cache. + + Changed ld-linux.so to only load ELF shared libraries for + use with libc5 or an unknown libc. + +Changes in version 1.8.10: + + Fixed a bug in ldconfig where a symlink could be used + instead of a regular file. + + Fixed a Debian packaging problem for the sparc + architecture. + +Changes in version 1.8.9: + + Changed ldconfig to only cache the symlinks it creates. + This make the behavior of the dynamic linkers consistent + with how they would behave if a cache was not used. + + Changed ldconfig to cache the symlinks that it finds but + use the name of the symlink as the soname instead of the + actual soname. + +Changes in version 1.8.8: + + Minor documentation updates to reflect recent changes. + + Changed ld.so and ld-linux.so to perform more complete + validation on ld.so.cache before using it. + + Changed ldconfig to accept libraries with inconsistent + sonames since glibc is going to use them. A warning is + still printed in debug mode. + + Changed the install script to not strip _dl_debug_state + from ld-linux.so since gdb needs it. + + More sparc fixes (Derrick Brashear). + + Changed ldconfig to not issue a warning when a linker + script disguised as a shared library is found. + + Fixed a bug in ld-linux.so where some registers were + not preserved on the first call to a function causing + problems for non-C-like languages (Tim Renouf). + + Fixed a bug in ld-linux.so where global variables were + not always mapped correctly across dynamically loaded + libraries (Mikihiko Nakao). + + Converted to new Debian source packaging format (Shaya + Potter). + +Changes in version 1.8.6/7: + + Never released as some unofficial patches used these + version numbers. + +Changes in version 1.8.5: + + Fixed a bug in ld.so introduced in the previous changes. + +Changes in version 1.8.4: + + Changed ldconfig to completely ignore symbolic links. + + Changed ldconfig to issue the warning concerning an + inconsistent soname in non-verbose mode. + + Changed ld-linux.so back to not keep ld.so.cache mapped + at all times. + + Changed Debian packaging to compress man pages, strip all + binaries (Bug#5125) and include a shlibs file. + +Changes in version 1.8.3: + + Changed ld-linux.so to process LD_PRELOAD before + /etc/ld.so.preload. + + Fixed a Debian packaging problem where libdl might not + be available if other packages were upgraded at the same + time (Debian Bug#4728). + + Changed ldd to always exit with status 1 if any errors + occur (Debian Bug#4188). + + Fixed some minor problems in instldso.sh (Mike Castle and + Wolfgang Franke). + + Changed ldconfig to issue a warning in verbose mode when + skipping a library because the soname doesn't match. + + More sparc fixes (Miguel de Icaza). + + Don't link with -N when building ld.so (Alan Modra). + + Changed ld-linux.so to better support position-dependant + libraries (NIIBE Yutaka). + +Changes in version 1.8.2: + + Added a texinfo file for ld.so and libdl (Michael + Deutschmann). + + Minor sparc and installation changes (Elliot Lee). + + Added multiple architecture support for Debian (Leland + Lucius). + + Changed libdl to better support RTLD_NEXT (Eric + Youngdale). Note: the exact meaning of ETLD_NEXT is + still not clear in all cases. + + Removed some libc dependencies from libdl. Still need + to remove malloc and free. + +Changes in version 1.8.1: + + Changed ld.so to be compiled as ELF. This also means + that ELF support is now required. A.out support is + still optional. + + Changed ld-linux.so and libdl.so to use the rpath in the + executable instead of in the invoking shared library. + + More m68k fixes (Andreas Schwab). + + Various sparc fixes (Miguel de Icaza). + + Changed ldcnnfig to ignore libraries ending in '~'. + + Changed ldconfig to allow alternative conf and cache + files to be specified on the command-line. + + Changed libdl.so to work when dlsym is passed a NULL + handle pointer. + +Changes in version 1.8.0: + + Changed ld-linux.so to be more liberal when checking to + see if a library is already loaded. This should avoid + the duplicate loading problem for programs linkeed with + the -rpath option. + + Various m68k fixes (Andreas Schwab). + + Changed ld.so to only use LD_AOUT_LIBRARY_PATH and + LD_AOUT_PRELOAD and ld-linux.so to only use + LD_LIBRARY_PATH and LD_PRELOAD. LD_ELF_LIBRARY_PATH + and LD_ELF_PRELOAD are no longer supported. + + Changed ld-linux.so to allow debugging of shared and + dynamically loaded libraries (H.J. Lu, Andreas Schwab). + + Changed ld-linux.so to preload ELF shared libraries + listed in /etc/ld.so.preload. This allows secure + preloads, even for setuid/setgid programs. + + Changed ld-linux.so to keep ld.so.cache mapped at all + times. + + Changed ldconfig to allow #-style comments in ld.so.conf. + + Removed various compiler warnings (Richard Sladkey and + David Engel). + + Changed ldd to work on ELF shared libraries. This may + need a little more work. + +Changes in version 1.7.14: + + Changed ldconfig to recognize ELF shared libraries + generated by post-2.6 versions of ld (Andreas Schwab). + + Changed ldconfig to not remove stale links that do not + have a version number since they may be needed by ld. + +Changes in version 1.7.13: + + Fixed a problem in ld-linux.so where a program linked + with a shared library that was not used could result in + a segmentation fault (H.J. Lu). + +Changes in version 1.7.12: + + Fixed a problem in libdl.so where the wrong library + could be marked as global when RTLD_GLOBAL was used + (Lars Heete). + + Installed dlfcn.h with libdl.so instead of requiring + it to be supplied with libc. + + Removed support for libldso.a since it was nearly + impossible to use anyway. + + Changed ldd to detect when the program being checked + exited abnormally. + +Changes in version 1.7.11: + + Changed ld.so and ld-linux.so to delete all variations + of LD_PRELOAD and LD_LIBRARY_PATH for set[ug]id programs, + This makes it harder for broken set[ug]id programs to be + compromised. + + Fixed a problem in libdl.so where dlsym would not accept + the handle returned from dlopen(0, *). + +Changes in version 1.7.10: + + Changed ld-linux.so and libdl.so to support RTLD_GLOBAL + (Eric Youngdale). + +Changes in version 1.7.9: + + Fixed a problem in ld-linux.so in detecting when the + new user/group information is provided by the kernel. + + Fixed a problem in ld-linux.so where a buffer could be + overflowed if a large number of libraries were loaded + (Thomas Moore). + +Changes in version 1.7.8: + + Changed the Makefiles and install scripts to support + a.out- and ELF-only configurations. + + Changed ld-linux.so to use the user/group information + provided by linux 1.3.23+ instead of making syscalls + to get it. + + Changed libdl.so to support RTLD_NEXT (Glenn Fowler). + + Changed libdl.so to only execute the fini sections + instead of completely closing libraries at exit (Glenn + Fowler). + + Changed ld.so and ld-linux.so to print the required + cache version when a mismatch is detected. + + Changed ld-linux.so to not require on /dev/zero (Ralph + Loader). + + Minor m68k cleanups (Andreas Schwab). + +Changes in version 1.7.7: + + Fixed problems compiling with recent 1.3.x kernels. + + Changed ld-linux.so to not use MAP_DENYWRITE until the + permission issue regarding it is resolved. + +Changes in version 1.7.6: + + Fixed a bug in ld-linux.so dealing with a zero-length + LD_{ELF_}PRELOAD. + + Changed ld.so and ld-linux.so to truncate all variations + of LD_PRELOAD and LD_LIBRARY_PATH for set[ug]id programs. + +Changes in version 1.7.5: + + Changed ldconfig to recognize libraries without any + version number (eg. libXYZ.so). + + Changed ldconfig to not generate a corrupt cache when + the disk is full or other write errors occur. + + Changed ld-linux.so to map files with MAP_DENYWRITE to + keep them from being changed while the file is in use + (Rick Sladkey). + + Changed libdl to not overwrite the scope pointer of a + library if it was already loaded (H.J. Lu). + + Changed ld-linux.so so gdb can be used on constructors + (Eric Youngdale). + + Changed ldconfig to ignore ELF libraries where the soname + does not match the file name on the assumption that it is + a used at compile-time (eg. libcurses.so -> libncruses.so). + +Changes in version 1.7.4: + + Changed ld-linux.so and libdl to use the appropriate + rpaths when searching for shared libraries (Eric + Youngdale). + + Changed ld-linux.so to search rpath before using the + cache. This more closely conforms to the IBCS standard. + +Changes in version 1.7.3: + + Changed ld-linux.so to only print a library name the + first time it is loaded when run from ldd. + + Fixed a bug in ldconfig where an invalid cache could be + generated if a directory was specified multiple times in + ld.so.conf. + + Changed ld-linux.so so it will return the address of a + weak symbol when called from dlsym in libdl (Eric + Youngdale. + +Changes in version 1.7.2: + + Changed libdl.so again to fix the undefined foobar + problem. + +Changes in version 1.7.1: + + Changed libdl so it will compile at optimization level + O3 or higher. + + Changed ldconfig to always create the cache file with + mode 644. + + Changed ldconfig to not ingore valid symlinks. + + Changed ldconfig to use the library name as the soname + for ELF libraries that do not have an soname entry. + + Changed ld-linux.so to print the actual, requested library + name at the time it is loaded instead of trying to figure + it out after the fact. + +Changes in version 1.7.0: + + Changed ldconfig to read the actual soname from the image + for ELF libraries and make it available to ld-linux.so. + The soname for DLL libraries is still determined by + truncating the minor numbers from the image file name. + + Changed ldconfig to no longer support the undocumented + sort options. + + Changed ld.so to require a valid cache to find libraries + in directories specified in ld.so.conf. /usr/lib and /lib + are still searched as a last resort. Ld-linux.so already + operated this way. + + Fixed a bug in libldso.a where the arguments to + shared_loader were not parsed correctly (Wolfram Gloger). + + Added support for RELA-style relocations under Linux/68k + (Andreas Schwab). + + Changed ld-linux.so to only map the cache once for all + libraries instead of individually for each library. + + Changed ld-linux.so continue searching the cache instead of + giving up when failing to load the first entry found. + + Changed ld-linux.so to produce output similar to ld.so when + run from ldd or when errors occur. + +Changes in version 1.6.7: + + Changed the install scripts to make sure that ld.so and + ld-linux.so are always usable. + + Added support for Linux/Sparc (Eric Youngdale). + + Added support for Linux/68k (Andreas Schwab). + + Fixed various bugs in ld-linux.so dealing with closing + files, unmapping memory, dereferencing NULL pointers and + printing library names (David Engel, Eric Youngdale and + Andreas Schwab). + + Replaced the manual page for libdl with a freely + distributable one (Adam Richter). + + Fixed a bug in ld-linux.so where LD_LIBRARY_PATH and + LD_PRELOAD were not cleared for setuid/setgid programs. + + Fixed a bug in libdl where dlsym would not return the + correct address of a symbol if it was redefined in another + library (Oleg Kibirev). + + Changed ld-linux.so to use the following order to search + for libraries: LD_{ELF_}LIBRARY_PATH, ld.so.cache, rpath, + /usr/lib and /lib. + + Changed ld-linux.so to not needlessly allocate memory when + using ld.so.cache. + +Changes in version 1.6.6: + + Changed ldconfig to not warn about removing stale links + unless the -v option is specified. + + Added manual pages for libdl (from FreeBSD/Sun) + + Fixed a bug in ld.so dealing with preloading of objects + generated by recent versions of ld (Mitch D'Souza). + + Fixed bugs in ldd where some errors were either not + detected or not printed. + + Fixed a bug in ld-linux.so where the trailing nul in a + library name was not being copied (Owen Taylor). + +Changes in version 1.6.5: + + Changed ldconfig to remove stale symbolic links. + + Added debug hooks in ld-linux.so and libdl.so to be used + by a future version of gdb (Eric Youngdale). + +Changes in version 1.6.4: + + Change ld-linux.so to print on stdout instead of stderr + when run from ldd. + + Added support for Debian GNU/Linux packaging. + +Changes in version 1.6.3: + + Fixed a bug in libdl when closing a library (H.J. Lu). + +Changes in version 1.6.2: + + Changed the error message printed by ldd when a file is + not a.out or ELF. It used to only list a.out formats. + + Changed ldconfig to no longer cache and set up links for + ld-linux.so. + + Changed ld-linux.so and libdl to not conflict with upcoming + changes in kernel header files. + + Changed ld-linux.so to not print preloaded libraries. + +Changes in version 1.6.1: + + Updated the installation script. + + Changed ld.so and ld-linux.so to look for LD_AOUT_PRELOAD + and LD_ELF_PRELOAD, respectively, before LD_PRELOAD. + + Changed ld.so and ld-linux.so to use LD_AOUT_LIBRARY_PATH + and LD_ELF_LIBRARY_PATH, respectively, instead of + AOUT_LD_LIBRARY_PATH and ELF_LD_LIBRARY_PATH. + +Changes in version 1.6.0: + + Changed ldconfig to process libraries which do not have + a minor version or patch level number. + + Incorporated ld-linux.so and libdl.so. + + Changed ld.so and ld-linux.so to not miss entries in the + cache when the fully qualified library is requested. + + Changed ldconfig to use stdout instead of stderr when + printing the cache. + +Changes in version 1.5.3: + + LD_PRELOAD enhancements (Tristan Gigold). + + LD_PRELOAD patch for linux-68k (Andreas Schwab). + +Changes in version 1.5.2: + + More ELF changes (Mitch D'Souza). + + Changed ldconfig to also update the link for ld-linux.so. + +Changes in version 1.5.1: + + More ELF and LD_PRELOAD changes (Mitch D'Souza). + +Changes in version 1.5.0: + + Chnaged all executables to QMAGIC (Mitch D'Souza and Rick + Sladkey). + + Added preliminary support for ELF to ldd and ldconfig (Eric + Youndale and H.J. Lu). + + Added support for LD_PRELOAD to ld.so (Mitch D'Souza). + + Removed the "advertising" clause from the copyright notices + in all source files. + +Changes in version 1.4.4: + + Changed ldconfig to support QMAGIC libraries. + + Fixed a bug in ld.so where some of the error messages had + transposed arguments. + +Changes in version 1.4.3: + + Fixed an obscure bug in ld.so where an index was not being + incremented when a library was not found using the cache. + +Changes in version 1.4.2: + + Changed ldconfig to issue a warning and continue instead + of an error and exiting when a link can't be updated. + This is useful when some libraries are imported on read- + only file systems, such as an NFS mounted /usr. + + Changed ld.so to be more robust in searching for libraries. + A library is not considered found unless it can actually be + loaded. If a library is not found using the cache, the + standard directories are searched as in pre-cache versions. + +Changes in version 1.4.1: + + Fixed minor Makefile problems. + + Added support for linux-68k. + + Fixed a bug in ld.so where libraries with absolute paths + were not handled correctly. + + Changed ld.so to ignore the directory in the names of + shared libraries by default. This allows older libraries + with absolute paths, such as the XView libraries, to take + advantage of the cache support. + + Added a minimal usage message to ldconfig. + +Changes in version 1.4: + + Fixed bug in ld.so where minor version numbers were not + reported correctly when a minor version incompatibility + was found. + + Fixed bug in ldconfig where libraries with subversion + numbers greater than 9 were not compared correctly. + + Added Mitch D'Souza's support for suppressing warning + messages from ld.so about minor version incompatibilities. + + Added Mitch D'Souza's support for using a cache to speed + up searching for libraries in the standard directories. + + Added Mitch D'Souza's support for a debugging version of + ld.so. Link with -lldso if you think you are experiencing + dynamic linker problems. + +Changes in version 1.3: + + Added support for libraries using absolute pathnames. If I + had known that the XView libraries used them, I would have + added this earlier. + + Fixed a bug handling old libraries using a pathname beginning + with '/' or '/lib/'. + +Changes in version 1.2a: + + Fixed a minor bug in ldd which caused all files, specifically + scripts, to be recognized as binaries. Thanks to Olaf Flebbe + for reporting it. + +David Engel +david@sw.ods.com diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/include/dl-defs.h b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/include/dl-defs.h new file mode 100644 index 00000000..be0a81da --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/include/dl-defs.h @@ -0,0 +1,254 @@ +/* vi: set sw=4 ts=4: */ +/* + * Copyright (C) 2000-2006 by Erik Andersen + * + * GNU Lesser General Public License version 2.1 or later. + */ + +#ifndef _LD_DEFS_H +#define _LD_DEFS_H + +#define FLAG_ANY -1 +#define FLAG_TYPE_MASK 0x00ff +#define FLAG_LIBC4 0x0000 +#define FLAG_ELF 0x0001 +#define FLAG_ELF_LIBC5 0x0002 +#define FLAG_ELF_LIBC6 0x0003 +#define FLAG_ELF_UCLIBC 0x0004 +#define FLAG_REQUIRED_MASK 0xff00 +#define FLAG_SPARC_LIB64 0x0100 +#define FLAG_IA64_LIB64 0x0200 +#define FLAG_X8664_LIB64 0x0300 +#define FLAG_S390_LIB64 0x0400 +#define FLAG_POWERPC_LIB64 0x0500 +#define FLAG_MIPS64_LIBN32 0x0600 +#define FLAG_MIPS64_LIBN64 0x0700 + +#define LIB_ANY -1 +#define LIB_DLL 0 +#define LIB_ELF 1 +#define LIB_ELF64 0x80 +#define LIB_ELF_LIBC5 2 +#define LIB_ELF_LIBC6 3 +#define LIB_ELF_LIBC0 4 + +#if defined(__LDSO_PRELOAD_FILE_SUPPORT__) || defined(__LDSO_CACHE_SUPPORT__) +#ifndef __LDSO_BASE_FILENAME__ +#define __LDSO_BASE_FILENAME__ "ld.so" +#endif +#define LDSO_BASE_PATH UCLIBC_RUNTIME_PREFIX "etc/" __LDSO_BASE_FILENAME__ + +#ifdef __LDSO_PRELOAD_FILE_SUPPORT__ +#define LDSO_PRELOAD LDSO_BASE_PATH ".preload" +#endif + +#ifdef __LDSO_CACHE_SUPPORT__ +#define LDSO_CONF LDSO_BASE_PATH ".conf" +#define LDSO_CACHE LDSO_BASE_PATH ".cache" + +#define LDSO_CACHE_MAGIC "ld.so-" +#define LDSO_CACHE_MAGIC_LEN (sizeof LDSO_CACHE_MAGIC -1) +#define LDSO_CACHE_VER "1.7.0" +#define LDSO_CACHE_VER_LEN (sizeof LDSO_CACHE_VER -1) + +typedef struct { + char magic [LDSO_CACHE_MAGIC_LEN]; + char version [LDSO_CACHE_VER_LEN]; + int nlibs; +} header_t; + +typedef struct { + int flags; + int sooffset; + int liboffset; +} libentry_t; + +#ifdef __ARCH_USE_MMU__ +#define LDSO_CACHE_MMAP_FLAGS (MAP_SHARED) +#else +#define LDSO_CACHE_MMAP_FLAGS (MAP_PRIVATE) +#endif +#endif /* __LDSO_CACHE_SUPPORT__ */ + +#endif + +/* Provide a means for a port to pass additional arguments to the _dl_start + function. */ +#ifndef DL_START +# define DL_START(X) static void * __attribute_used__ _dl_start(X) +#endif + +/* Machines in which different sections may be relocated by different + * amounts should define this and LD_RELOC_ADDR. If you change this, + * make sure you change struct link_map in include/link.h accordingly + * such that it matches a prefix of struct elf_resolve. + */ +#ifndef DL_LOADADDR_TYPE +# define DL_LOADADDR_TYPE ElfW(Addr) +#endif + +/* When DL_LOADADDR_TYPE is not a scalar value, or some different + * computation is needed to relocate an address, define this. + */ +#ifndef DL_RELOC_ADDR +# define DL_RELOC_ADDR(LOADADDR, ADDR) \ + ((LOADADDR) + (ADDR)) +#endif + +/* Initialize the location of the dynamic addr. This is only called + * from DL_START, so additional arguments passed to it may be referenced. */ +#ifndef DL_BOOT_COMPUTE_DYN +#define DL_BOOT_COMPUTE_DYN(DPNT, GOT, LOAD_ADDR) \ + ((DPNT) = ((ElfW(Dyn) *) DL_RELOC_ADDR(LOAD_ADDR, GOT))) +#endif + +/* Initialize the location of the global offset table. This is only called + * from DL_START, so additional arguments passed to it may be referenced. */ +#ifndef DL_BOOT_COMPUTE_GOT +#define DL_BOOT_COMPUTE_GOT(GOT) \ + ((GOT) = elf_machine_dynamic()) +#endif + +/* Initialize a LOADADDR representing the loader itself. It's only + * called from DL_START, so additional arguments passed to it may be + * referenced. + */ +#ifndef DL_INIT_LOADADDR_BOOT +# define DL_INIT_LOADADDR_BOOT(LOADADDR, BASEADDR) \ + ((LOADADDR) = (BASEADDR)) +#endif + +/* Define if any declarations/definitions of local variables are + * needed in a function that calls DT_INIT_LOADADDR or + * DL_INIT_LOADADDR_HDR. Declarations must be properly terminated + * with a semicolon, and non-declaration statements are forbidden. + */ +#ifndef DL_INIT_LOADADDR_EXTRA_DECLS +# define DL_INIT_LOADADDR_EXTRA_DECLS /* int i; */ +#endif + +/* Prepare a DL_LOADADDR_TYPE data structure for incremental + * initialization with DL_INIT_LOADADDR_HDR, given pointers to a base + * load address and to program headers. + */ +#ifndef DL_INIT_LOADADDR +# define DL_INIT_LOADADDR(LOADADDR, BASEADDR, PHDR, PHDRCNT) \ + ((LOADADDR) = (BASEADDR)) +#endif + +/* Initialize a LOADADDR representing the program. It's called from + * DL_BOOT only. + */ +#ifndef DL_INIT_LOADADDR_PROG +# define DL_INIT_LOADADDR_PROG(LOADADDR, BASEADDR) \ + ((LOADADDR) = (DL_LOADADDR_TYPE)(BASEADDR)) +#endif + +/* Update LOADADDR with information about PHDR, just mapped to the + given ADDR. */ +#ifndef DL_INIT_LOADADDR_HDR +# define DL_INIT_LOADADDR_HDR(LOADADDR, ADDR, PHDR) /* Do nothing. */ +#endif + +/* Convert a DL_LOADADDR_TYPE to an identifying pointer. Used mostly + * for debugging. + */ +#ifndef DL_LOADADDR_BASE +# define DL_LOADADDR_BASE(LOADADDR) (LOADADDR) +#endif + +/* Test whether a given ADDR is more likely to be within the memory + * region mapped to TPNT (a struct elf_resolve *) than to TFROM. + * Everywhere that this is used, TFROM is initially NULL, and whenever + * a potential match is found, it's updated. One might want to walk + * the chain of elf_resolve to locate the best match and return false + * whenever TFROM is non-NULL, or use an exact-matching algorithm + * using additional information encoded in DL_LOADADDR_TYPE to test + * for exact containment. + */ +#ifndef DL_ADDR_IN_LOADADDR +# define DL_ADDR_IN_LOADADDR(ADDR, TPNT, TFROM) \ + ((void*)(TPNT)->mapaddr < (void*)(ADDR) \ + && (!(TFROM) || (TFROM)->mapaddr < (TPNT)->mapaddr)) +#endif + +/* This is called from dladdr() to give targets that use function descriptors + * a chance to map a function descriptor's address to the function's entry + * point before trying to find in which library it's defined. */ +#ifndef DL_LOOKUP_ADDRESS +#define DL_LOOKUP_ADDRESS(ADDRESS) (ADDRESS) +#endif + +/* Use this macro to convert a pointer to a function's entry point to + * a pointer to function. The pointer is assumed to have already been + * relocated. LOADADDR is passed because it may contain additional + * information needed to compute the pointer to function. + */ +#ifndef DL_ADDR_TO_FUNC_PTR +# define DL_ADDR_TO_FUNC_PTR(ADDR, LOADADDR) ((void(*)(void))(ADDR)) +#endif + +/* On some platforms, computing a pointer to function is more + expensive than calling a function at a given address, so this + alternative is provided. The function signature must be given + within parentheses, as in a type cast. */ +#ifndef DL_CALL_FUNC_AT_ADDR +# define DL_CALL_FUNC_AT_ADDR(ADDR, LOADADDR, SIGNATURE, ...) \ + ((*SIGNATURE DL_ADDR_TO_FUNC_PTR ((ADDR), (LOADADDR)))(__VA_ARGS__)) +#endif + +/* An alignment value for a memory block returned by _dl_malloc. */ +#ifndef DL_MALLOC_ALIGN +# define DL_MALLOC_ALIGN (__WORDSIZE / 8) +#endif + +#ifdef __UCLIBC_UNDERSCORES__ +# define __C_SYMBOL_PREFIX__ "_" +#else +# define __C_SYMBOL_PREFIX__ "" +#endif + +/* Define this if you want to modify the VALUE returned by + _dl_find_hash for this reloc TYPE. TPNT is the module in which the + matching SYM was found. */ +#ifndef DL_FIND_HASH_VALUE +# define DL_FIND_HASH_VALUE(TPNT, TYPE, SYM) (DL_RELOC_ADDR ((TPNT)->loadaddr, (SYM)->st_value)) +#endif + +/* Unmap all previously-mapped segments accumulated in LOADADDR. + Generally used when an error occurs during loading. */ +#ifndef DL_LOADADDR_UNMAP +# define DL_LOADADDR_UNMAP(LOADADDR, LEN) \ + _dl_munmap((char *) (LOADADDR), (LEN)) +#endif + +/* Similar to DL_LOADADDR_UNMAP, but used for libraries that have been + dlopen()ed successfully, when they're dlclose()d. */ +#ifndef DL_LIB_UNMAP +# define DL_LIB_UNMAP(LIB, LEN) (DL_LOADADDR_UNMAP ((LIB)->loadaddr, (LEN))) +#endif + +/* Define this to verify that a library named LIBNAME, whose ELF + headers are pointed to by EPNT, is suitable for dynamic linking. + If it is not, print an error message (optional) and return NULL. + If the library can have its segments relocated independently, + arrange for PICLIB to be set to 2. If all segments have to be + relocated by the same amount, set it to 1. If it has to be loaded + at physical addresses as specified in the program headers, set it + to 0. A reasonable (?) guess for PICLIB will already be in place, + so it is safe to do nothing here. */ +#ifndef DL_CHECK_LIB_TYPE +# define DL_CHECK_LIB_TYPE(EPNT, PICLIB, PROGNAME, LIBNAME) (void)0 +#endif + +/* Define this if you have special segment. */ +#ifndef DL_IS_SPECIAL_SEGMENT +# define DL_IS_SPECIAL_SEGMENT(EPNT, PPNT) 0 +#endif + +/* Define this if you want to use special method to map the segment. */ +#ifndef DL_MAP_SEGMENT +# define DL_MAP_SEGMENT(EPNT, PPNT, INFILE, FLAGS) 0 +#endif + +#endif /* _LD_DEFS_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/include/dl-elf.h b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/include/dl-elf.h new file mode 100644 index 00000000..7fbb373b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/include/dl-elf.h @@ -0,0 +1,222 @@ +/* vi: set sw=4 ts=4: */ +/* + * Copyright (C) 2000-2005 by Erik Andersen + * + * GNU Lesser General Public License version 2.1 or later. + */ + +#ifndef LINUXELF_H +#define LINUXELF_H + +#include /* before elf.h to get ELF_USES_RELOCA right */ +#include +#include + +/* Forward declarations for stuff defined in ld_hash.h */ +struct dyn_elf; +struct elf_resolve; + +#include +#ifdef __LDSO_CACHE_SUPPORT__ +extern int _dl_map_cache(void); +extern int _dl_unmap_cache(void); +#else +static __inline__ void _dl_map_cache(void) { } +static __inline__ void _dl_unmap_cache(void) { } +#endif + + +/* Function prototypes for non-static stuff in readelflib1.c */ +extern void _dl_parse_lazy_relocation_information(struct dyn_elf *rpnt, + unsigned long rel_addr, unsigned long rel_size); +extern int _dl_parse_relocation_information(struct dyn_elf *rpnt, + unsigned long rel_addr, unsigned long rel_size); +extern struct elf_resolve * _dl_load_shared_library(int secure, + struct dyn_elf **rpnt, struct elf_resolve *tpnt, char *full_libname, + int trace_loaded_objects); +extern struct elf_resolve * _dl_load_elf_shared_library(int secure, + struct dyn_elf **rpnt, char *libname); +extern struct elf_resolve *_dl_check_if_named_library_is_loaded(const char *full_libname, + int trace_loaded_objects); +extern int _dl_linux_resolve(void); +extern int _dl_fixup(struct dyn_elf *rpnt, int flag); +extern void _dl_protect_relro (struct elf_resolve *l); + +/* + * Bitsize related settings for things ElfW() + * does not handle already + */ +#if __WORDSIZE == 64 +# define ELF_ST_BIND(val) ELF64_ST_BIND(val) +# define ELF_ST_TYPE(val) ELF64_ST_TYPE(val) +# define ELF_R_SYM(i) ELF64_R_SYM(i) +# define ELF_R_TYPE(i) ELF64_R_TYPE(i) +# ifndef ELF_CLASS +# define ELF_CLASS ELFCLASS64 +# endif +#else +# define ELF_ST_BIND(val) ELF32_ST_BIND(val) +# define ELF_ST_TYPE(val) ELF32_ST_TYPE(val) +# define ELF_R_SYM(i) ELF32_R_SYM(i) +# define ELF_R_TYPE(i) ELF32_R_TYPE(i) +# ifndef ELF_CLASS +# define ELF_CLASS ELFCLASS32 +# endif +#endif + +/* + * Datatype of a relocation on this platform + */ +#ifdef ELF_USES_RELOCA +# define ELF_RELOC ElfW(Rela) +# define DT_RELOC_TABLE_ADDR DT_RELA +# define DT_RELOC_TABLE_SIZE DT_RELASZ +# define DT_RELOCCOUNT DT_RELACOUNT +# define UNSUPPORTED_RELOC_TYPE DT_REL +# define UNSUPPORTED_RELOC_STR "REL" +#else +# define ELF_RELOC ElfW(Rel) +# define DT_RELOC_TABLE_ADDR DT_REL +# define DT_RELOC_TABLE_SIZE DT_RELSZ +# define DT_RELOCCOUNT DT_RELCOUNT +# define UNSUPPORTED_RELOC_TYPE DT_RELA +# define UNSUPPORTED_RELOC_STR "RELA" +#endif + +/* OS and/or GNU dynamic extensions */ +#ifdef __LDSO_GNU_HASH_SUPPORT__ +# define OS_NUM 2 /* for DT_RELOCCOUNT and DT_GNU_HASH entries */ +#else +# define OS_NUM 1 /* for DT_RELOCCOUNT entry */ +#endif + +#ifndef ARCH_DYNAMIC_INFO + /* define in arch specific code, if needed */ +# define ARCH_NUM 0 +#endif + +#define DYNAMIC_SIZE (DT_NUM+OS_NUM+ARCH_NUM) +/* Keep ARCH specific entries into dynamic section at the end of the array */ +#define DT_RELCONT_IDX (DYNAMIC_SIZE - OS_NUM - ARCH_NUM) + +#ifdef __LDSO_GNU_HASH_SUPPORT__ +/* GNU hash comes just after the relocation count */ +# define DT_GNU_HASH_IDX (DT_RELCONT_IDX + 1) +#endif + +extern unsigned int _dl_parse_dynamic_info(ElfW(Dyn) *dpnt, unsigned long dynamic_info[], + void *debug_addr, DL_LOADADDR_TYPE load_off); + +static __always_inline +unsigned int __dl_parse_dynamic_info(ElfW(Dyn) *dpnt, unsigned long dynamic_info[], + void *debug_addr, DL_LOADADDR_TYPE load_off) +{ + unsigned int rtld_flags = 0; + + for (; dpnt->d_tag; dpnt++) { + if (dpnt->d_tag < DT_NUM) { + dynamic_info[dpnt->d_tag] = dpnt->d_un.d_val; +#ifndef __mips__ + /* we disable for mips because normally this page is readonly + * and modifying the value here needlessly dirties a page. + * see this post for more info: + * http://uclibc.org/lists/uclibc/2006-April/015224.html */ + if (dpnt->d_tag == DT_DEBUG) + dpnt->d_un.d_val = (unsigned long)debug_addr; +#endif + if (dpnt->d_tag == DT_BIND_NOW) + dynamic_info[DT_BIND_NOW] = 1; + if (dpnt->d_tag == DT_FLAGS && + (dpnt->d_un.d_val & DF_BIND_NOW)) + dynamic_info[DT_BIND_NOW] = 1; + if (dpnt->d_tag == DT_TEXTREL) + dynamic_info[DT_TEXTREL] = 1; +#ifdef __LDSO_RUNPATH__ + if (dpnt->d_tag == DT_RUNPATH) + dynamic_info[DT_RPATH] = 0; + if (dpnt->d_tag == DT_RPATH && dynamic_info[DT_RUNPATH]) + dynamic_info[DT_RPATH] = 0; +#endif + } else if (dpnt->d_tag < DT_LOPROC) { + if (dpnt->d_tag == DT_RELOCCOUNT) + dynamic_info[DT_RELCONT_IDX] = dpnt->d_un.d_val; + if (dpnt->d_tag == DT_FLAGS_1) { + if (dpnt->d_un.d_val & DF_1_NOW) + dynamic_info[DT_BIND_NOW] = 1; + if (dpnt->d_un.d_val & DF_1_NODELETE) + rtld_flags |= RTLD_NODELETE; + } +#ifdef __LDSO_GNU_HASH_SUPPORT__ + if (dpnt->d_tag == DT_GNU_HASH) + dynamic_info[DT_GNU_HASH_IDX] = dpnt->d_un.d_ptr; +#endif + } +#ifdef ARCH_DYNAMIC_INFO + else { + ARCH_DYNAMIC_INFO(dpnt, dynamic_info, debug_addr); + } +#endif + } +#define ADJUST_DYN_INFO(tag, load_off) \ + do { \ + if (dynamic_info[tag]) \ + dynamic_info[tag] = (unsigned long) DL_RELOC_ADDR(load_off, dynamic_info[tag]); \ + } while (0) + /* Don't adjust .dynamic unnecessarily. For FDPIC targets, + we'd have to walk all the loadsegs to find out if it was + actually unnecessary, so skip this optimization. */ +#if !defined __FDPIC__ && !defined __DSBT__ + if (load_off != 0) +#endif + { + ADJUST_DYN_INFO(DT_HASH, load_off); + ADJUST_DYN_INFO(DT_PLTGOT, load_off); + ADJUST_DYN_INFO(DT_STRTAB, load_off); + ADJUST_DYN_INFO(DT_SYMTAB, load_off); + ADJUST_DYN_INFO(DT_RELOC_TABLE_ADDR, load_off); + ADJUST_DYN_INFO(DT_JMPREL, load_off); +#ifdef __LDSO_GNU_HASH_SUPPORT__ + ADJUST_DYN_INFO(DT_GNU_HASH_IDX, load_off); +#endif + } +#ifdef __DSBT__ + /* Get the mapped address of the DSBT base. */ + ADJUST_DYN_INFO(DT_DSBT_BASE_IDX, load_off); + + /* Initialize loadmap dsbt info. */ + load_off.map->dsbt_table = dynamic_info[DT_DSBT_BASE_IDX]; + load_off.map->dsbt_size = dynamic_info[DT_DSBT_SIZE_IDX]; + load_off.map->dsbt_index = dynamic_info[DT_DSBT_INDEX_IDX]; +#endif +#undef ADJUST_DYN_INFO + return rtld_flags; +} + +/* Reloc type classes as returned by elf_machine_type_class(). + ELF_RTYPE_CLASS_PLT means this reloc should not be satisfied by + some PLT symbol, ELF_RTYPE_CLASS_COPY means this reloc should not be + satisfied by any symbol in the executable. Some architectures do + not support copy relocations. In this case we define the macro to + zero so that the code for handling them gets automatically optimized + out. */ +#ifdef DL_NO_COPY_RELOCS +# define ELF_RTYPE_CLASS_COPY (0x0) +#else +# define ELF_RTYPE_CLASS_COPY (0x2) +#endif +#define ELF_RTYPE_CLASS_PLT (0x1) + +/* dlsym() calls _dl_find_hash with this value, that enables + DL_FIND_HASH_VALUE to return something different than the symbol + itself, e.g., a function descriptor. */ +#define ELF_RTYPE_CLASS_DLSYM 0x80000000 + + +/* Convert between the Linux flags for page protections and the + ones specified in the ELF standard. */ +#define LXFLAGS(X) ( (((X) & PF_R) ? PROT_READ : 0) | \ + (((X) & PF_W) ? PROT_WRITE : 0) | \ + (((X) & PF_X) ? PROT_EXEC : 0)) + + +#endif /* LINUXELF_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/include/dl-hash.h b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/include/dl-hash.h new file mode 100644 index 00000000..d8b3e3ef --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/include/dl-hash.h @@ -0,0 +1,173 @@ +/* vi: set sw=4 ts=4: */ +/* + * Copyright (C) 2000-2006 by Erik Andersen + * + * GNU Lesser General Public License version 2.1 or later. + */ + +#ifndef _LD_HASH_H_ +#define _LD_HASH_H_ + +#ifndef RTLD_NEXT +#define RTLD_NEXT ((void*)-1) +#endif + +struct init_fini { + struct elf_resolve **init_fini; + unsigned long nlist; /* Number of entries in init_fini */ +}; + +struct dyn_elf { + struct elf_resolve * dyn; + struct dyn_elf * next_handle; /* Used by dlopen et al. */ + struct init_fini init_fini; + struct dyn_elf * next; + struct dyn_elf * prev; +}; + +struct symbol_ref { + const ElfW(Sym) *sym; + struct elf_resolve *tpnt; +}; + +struct elf_resolve { + /* These entries must be in this order to be compatible with the interface used + by gdb to obtain the list of symbols. */ + DL_LOADADDR_TYPE loadaddr; /* Base address shared object is loaded at. */ + char *libname; /* Absolute file name object was found in. */ + ElfW(Dyn) *dynamic_addr; /* Dynamic section of the shared object. */ + struct elf_resolve * next; + struct elf_resolve * prev; + /* Nothing after this address is used by gdb. */ + +#if defined(USE_TLS) && USE_TLS + /* Thread-local storage related info. */ + + /* Start of the initialization image. */ + void *l_tls_initimage; + /* Size of the initialization image. */ + size_t l_tls_initimage_size; + /* Size of the TLS block. */ + size_t l_tls_blocksize; + /* Alignment requirement of the TLS block. */ + size_t l_tls_align; + /* Offset of first byte module alignment. */ + size_t l_tls_firstbyte_offset; +# ifndef NO_TLS_OFFSET +# define NO_TLS_OFFSET 0 +# endif + /* For objects present at startup time: offset in the static TLS block. */ + ptrdiff_t l_tls_offset; + /* Index of the module in the dtv array. */ + size_t l_tls_modid; + /* Nonzero if _dl_init_static_tls should be called for this module */ + unsigned int l_need_tls_init:1; +#endif + + ElfW(Addr) mapaddr; + enum {elf_lib, elf_executable,program_interpreter, loaded_file} libtype; + struct dyn_elf * symbol_scope; + unsigned short usage_count; + unsigned short int init_flag; + unsigned long rtld_flags; /* RTLD_GLOBAL, RTLD_NOW etc. */ + Elf_Symndx nbucket; + +#ifdef __LDSO_GNU_HASH_SUPPORT__ + /* Data needed to support GNU hash style */ + Elf32_Word l_gnu_bitmask_idxbits; + Elf32_Word l_gnu_shift; + const ElfW(Addr) *l_gnu_bitmask; + + union + { + const Elf32_Word *l_gnu_chain_zero; + const Elf_Symndx *elf_buckets; + }; +#else + Elf_Symndx *elf_buckets; +#endif + + struct init_fini_list *init_fini; + struct init_fini_list *rtld_local; /* keep tack of RTLD_LOCAL libs in same group */ + /* + * These are only used with ELF style shared libraries + */ + Elf_Symndx nchain; + +#ifdef __LDSO_GNU_HASH_SUPPORT__ + union + { + const Elf32_Word *l_gnu_buckets; + const Elf_Symndx *chains; + }; +#else + Elf_Symndx *chains; +#endif + unsigned long dynamic_info[DYNAMIC_SIZE]; + + unsigned long n_phent; + ElfW(Phdr) * ppnt; + + ElfW(Addr) relro_addr; + size_t relro_size; + + dev_t st_dev; /* device */ + ino_t st_ino; /* inode */ + +#ifdef __powerpc__ + /* this is used to store the address of relocation data words, so + * we don't have to calculate it every time, which requires a divide */ + unsigned long data_words; +#endif + +#ifdef __FDPIC__ + /* Every loaded module holds a hashtable of function descriptors of + functions defined in it, such that it's easy to release the + memory when the module is dlclose()d. */ + struct funcdesc_ht *funcdesc_ht; +#endif +}; + +#define RELOCS_DONE 0x000001 +#define JMP_RELOCS_DONE 0x000002 +#define INIT_FUNCS_CALLED 0x000004 +#define FINI_FUNCS_CALLED 0x000008 +#define DL_OPENED 0x000010 + +extern struct dyn_elf * _dl_symbol_tables; +extern struct elf_resolve * _dl_loaded_modules; +extern struct dyn_elf * _dl_handles; + +extern struct elf_resolve * _dl_add_elf_hash_table(const char * libname, + DL_LOADADDR_TYPE loadaddr, unsigned long * dynamic_info, + unsigned long dynamic_addr, unsigned long dynamic_size); + +extern char *_dl_find_hash(const char *name, struct dyn_elf *rpnt, + struct elf_resolve *mytpnt, int type_class, + struct symbol_ref *symbol); + +extern int _dl_linux_dynamic_link(void); + +extern char * _dl_library_path; +extern char * _dl_not_lazy; + +static __inline__ int _dl_symbol(char * name) +{ + if (name[0] != '_' || name[1] != 'd' || name[2] != 'l' || name[3] != '_') + return 0; + return 1; +} + +#define LD_ERROR_NOFILE 1 +#define LD_ERROR_NOZERO 2 +#define LD_ERROR_NOTELF 3 +#define LD_ERROR_NOTMAGIC 4 +#define LD_ERROR_NOTDYN 5 +#define LD_ERROR_MMAP_FAILED 6 +#define LD_ERROR_NODYNAMIC 7 +#define LD_ERROR_TLS_FAILED 8 +#define LD_WRONG_RELOCS 9 +#define LD_BAD_HANDLE 10 +#define LD_NO_SYMBOL 11 + +#endif /* _LD_HASH_H_ */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/include/dl-string.h b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/include/dl-string.h new file mode 100644 index 00000000..01ab50ec --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/include/dl-string.h @@ -0,0 +1,365 @@ +/* vi: set sw=4 ts=4: */ +/* + * Copyright (C) 2000-2005 by Erik Andersen + * + * GNU Lesser General Public License version 2.1 or later. + */ + +#ifndef _LINUX_STRING_H_ +#define _LINUX_STRING_H_ + +#include /* for do_rem */ +#include + +/* provide some sane defaults */ +#ifndef do_rem +# define do_rem(result, n, base) ((result) = (n) % (base)) +#endif +#ifndef do_div_10 +# define do_div_10(result, remain) ((result) /= 10) +#endif + +static size_t _dl_strlen(const char *str); +static char *_dl_strcat(char *dst, const char *src); +static char *_dl_strcpy(char *dst, const char *src); +static int _dl_strcmp(const char *s1, const char *s2); +static int _dl_strncmp(const char *s1, const char *s2, size_t len); +static char *_dl_strchr(const char *str, int c); +static char *_dl_strrchr(const char *str, int c); +static char *_dl_strstr(const char *s1, const char *s2); +static void *_dl_memcpy(void *dst, const void *src, size_t len); +static int _dl_memcmp(const void *s1, const void *s2, size_t len); +static void *_dl_memset(void *str, int c, size_t len); +static char *_dl_get_last_path_component(char *path); +static char *_dl_simple_ltoa(char *local, unsigned long i); +static char *_dl_simple_ltoahex(char *local, unsigned long i); + +#ifndef NULL +#define NULL ((void *) 0) +#endif + +static __always_inline size_t _dl_strlen(const char *str) +{ + register const char *ptr = (char *) str-1; + while (*++ptr) + ;/* empty */ + return (ptr - str); +} + +static __always_inline char * _dl_strcat(char *dst, const char *src) +{ + register char *ptr = dst-1; + + src--; + while (*++ptr) + ;/* empty */ + ptr--; + while ((*++ptr = *++src) != 0) + ;/* empty */ + return dst; +} + +static __always_inline char * _dl_strcpy(char *dst, const char *src) +{ + register char *ptr = dst; + + dst--;src--; + while ((*++dst = *++src) != 0) + ;/* empty */ + + return ptr; +} + +static __always_inline int _dl_strcmp(const char *s1, const char *s2) +{ + register unsigned char c1, c2; + s1--;s2--; + do { + c1 = (unsigned char) *++s1; + c2 = (unsigned char) *++s2; + if (c1 == '\0') + return c1 - c2; + } while (c1 == c2); + + return c1 - c2; +} + +static __always_inline int _dl_strncmp(const char *s1, const char *s2, size_t len) +{ + register unsigned char c1 = '\0'; + register unsigned char c2 = '\0'; + + s1--;s2--; + while (len > 0) { + c1 = (unsigned char) *++s1; + c2 = (unsigned char) *++s2; + if (c1 == '\0' || c1 != c2) + return c1 - c2; + len--; + } + return c1 - c2; +} + +static __always_inline char * _dl_strchr(const char *str, int c) +{ + register char ch; + str--; + do { + if ((ch = *++str) == c) + return (char *) str; + } + while (ch); + + return 0; +} + +static __always_inline char * _dl_strrchr(const char *str, int c) +{ + register char *prev = 0; + register char *ptr = (char *) str-1; + + while (*++ptr != '\0') { + if (*ptr == c) + prev = ptr; + } + if (c == '\0') + return(ptr); + return(prev); +} + +static __always_inline char * _dl_strstr(const char *s1, const char *s2) +{ + register const char *s = s1; + register const char *p = s2; + + do { + if (!*p) + return (char *) s1;; + if (*p == *s) { + ++p; + ++s; + } else { + p = s2; + if (!*s) + return NULL; + s = ++s1; + } + } while (1); +} + +static __always_inline void * _dl_memcpy(void *dst, const void *src, size_t len) +{ + register char *a = dst-1; + register const char *b = src-1; + + while (len) { + *++a = *++b; + --len; + } + return dst; +} + +static __always_inline int _dl_memcmp(const void *s1, const void *s2, size_t len) +{ + unsigned char *c1 = (unsigned char *)s1-1; + unsigned char *c2 = (unsigned char *)s2-1; + + while (len) { + if (*++c1 != *++c2) + return *c1 - *c2; + len--; + } + return 0; +} + +#if defined(powerpc) +/* Will generate smaller and faster code due to loop unrolling.*/ +static __always_inline void * _dl_memset(void *to, int c, size_t n) +{ + unsigned long chunks; + unsigned long *tmp_to; + unsigned char *tmp_char; + + chunks = n / 4; + tmp_to = to + n; + c = c << 8 | c; + c = c << 16 | c; + if (!chunks) + goto lessthan4; + do { + *--tmp_to = c; + } while (--chunks); +lessthan4: + n = n % 4; + if (!n) + return to; + tmp_char = (unsigned char *)tmp_to; + do { + *--tmp_char = c; + } while (--n); + return to; +} +#else +static __always_inline void * _dl_memset(void *str, int c, size_t len) +{ + register char *a = str; + + while (len--) + *a++ = c; + + return str; +} +#endif + +static __always_inline char * _dl_get_last_path_component(char *path) +{ + register char *ptr = path-1; + + while (*++ptr) + ;/* empty */ + + /* strip trailing slashes */ + while (ptr != path && *--ptr == '/') { + *ptr = '\0'; + } + + /* find last component */ + while (ptr != path && *--ptr != '/') + ;/* empty */ + return ptr == path ? ptr : ptr+1; +} + +/* Early on, we can't call printf, so use this to print out + * numbers using the SEND_STDERR() macro. Avoid using mod + * or using long division */ +static __always_inline char * _dl_simple_ltoa(char *local, unsigned long i) +{ + /* 20 digits plus a null terminator should be good for + * 64-bit or smaller ints (2^64 - 1)*/ + char *p = &local[22]; + *--p = '\0'; + do { + char temp; + do_rem(temp, i, 10); + *--p = '0' + temp; + do_div_10(i, temp); + } while (i > 0); + return p; +} + +static __always_inline char * _dl_simple_ltoahex(char *local, unsigned long i) +{ + /* 16 digits plus a leading "0x" plus a null terminator, + * should be good for 64-bit or smaller ints */ + char *p = &local[22]; + *--p = '\0'; + do { + char temp = i & 0xf; + if (temp <= 0x09) + *--p = '0' + temp; + else + *--p = 'a' - 0x0a + temp; + i >>= 4; + } while (i > 0); + *--p = 'x'; + *--p = '0'; + return p; +} + + + + +/* The following macros may be used in dl-startup.c to debug + * ldso before ldso has fixed itself up to make function calls */ + +/* On some (wierd) arches, none of this stuff works at all, so + * disable the whole lot... */ +#if defined(__mips__) + +# define SEND_STDERR(X) +# define SEND_ADDRESS_STDERR(X, add_a_newline) +# define SEND_NUMBER_STDERR(X, add_a_newline) + +#else + +/* On some arches constant strings are referenced through the GOT. + * This requires that load_addr must already be defined... */ +#if defined(mc68000) || defined(__arm__) || defined(__thumb__) || \ + defined(__mips__) || defined(__sh__) || defined(__powerpc__) || \ + defined(__avr32__) || defined(__xtensa__) || defined(__sparc__) +# define CONSTANT_STRING_GOT_FIXUP(X) \ + if ((X) < (const char *) load_addr) (X) += load_addr +# define NO_EARLY_SEND_STDERR +#else +# define CONSTANT_STRING_GOT_FIXUP(X) +#endif + +#define SEND_STDERR(X) \ +{ \ + const char *tmp1 = (X); \ + CONSTANT_STRING_GOT_FIXUP(tmp1); \ + _dl_write(2, tmp1, _dl_strlen(tmp1)); \ +} + +#define SEND_ADDRESS_STDERR(ADR, add_a_newline) \ +{ \ + char tmp[26], v, *tmp2, *tmp1 = tmp; \ + unsigned long X = (unsigned long)(ADR); \ + CONSTANT_STRING_GOT_FIXUP(tmp1); \ + tmp2 = tmp1 + sizeof(tmp); \ + *--tmp2 = '\0'; \ + if (add_a_newline) *--tmp2 = '\n'; \ + do { \ + v = (X) & 0xf; \ + if (v <= 0x09) \ + *--tmp2 = '0' + v; \ + else \ + *--tmp2 = 'a' - 0x0a + v; \ + (X) >>= 4; \ + } while ((X) > 0); \ + *--tmp2 = 'x'; \ + *--tmp2 = '0'; \ + _dl_write(2, tmp2, tmp1 - tmp2 + sizeof(tmp) - 1); \ +} + +#define SEND_NUMBER_STDERR(NUM, add_a_newline) \ +{ \ + char tmp[26], v, *tmp2, *tmp1 = tmp; \ + unsigned long X = (unsigned long)(NUM); \ + CONSTANT_STRING_GOT_FIXUP(tmp1); \ + tmp2 = tmp1 + sizeof(tmp); \ + *--tmp2 = '\0'; \ + if (add_a_newline) *--tmp2 = '\n'; \ + do { \ + do_rem(v, (X), 10); \ + *--tmp2 = '0' + v; \ + do_div_10((X), v); \ + } while ((X) > 0); \ + _dl_write(2, tmp2, tmp1 - tmp2 + sizeof(tmp) - 1); \ +} +#endif + +/* Some targets may have to override this to something that doesn't + * reference constant strings through the GOT. This macro should be + * preferred over SEND_STDERR for constant strings before we complete + * bootstrap. + */ +#ifndef SEND_EARLY_STDERR +# define SEND_EARLY_STDERR(S) SEND_STDERR(S) +#else +# define EARLY_STDERR_SPECIAL +#endif + +#ifdef __SUPPORT_LD_DEBUG_EARLY__ +# define SEND_STDERR_DEBUG(X) SEND_STDERR(X) +# define SEND_EARLY_STDERR_DEBUG(X) SEND_EARLY_STDERR(X) +# define SEND_NUMBER_STDERR_DEBUG(X, add_a_newline) SEND_NUMBER_STDERR(X, add_a_newline) +# define SEND_ADDRESS_STDERR_DEBUG(X, add_a_newline) SEND_ADDRESS_STDERR(X, add_a_newline) +#else +# define SEND_STDERR_DEBUG(X) +# define SEND_EARLY_STDERR_DEBUG(X) +# define SEND_NUMBER_STDERR_DEBUG(X, add_a_newline) +# define SEND_ADDRESS_STDERR_DEBUG(X, add_a_newline) +#endif + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/include/dl-syscall.h b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/include/dl-syscall.h new file mode 100644 index 00000000..d07023fc --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/include/dl-syscall.h @@ -0,0 +1,163 @@ +/* vi: set sw=4 ts=4: */ +/* + * Copyright (C) 2000-2005 by Erik Andersen + * + * GNU Lesser General Public License version 2.1 or later. + */ + +#ifndef _LD_SYSCALL_H_ +#define _LD_SYSCALL_H_ + +/* Pull in the arch specific syscall implementation */ +#include +#ifdef NOT_FOR_L4 +/* For MAP_ANONYMOUS -- differs between platforms */ +#define _SYS_MMAN_H 1 +#include +/* Pull in whatever this particular arch's kernel thinks the kernel version of + * struct stat should look like. It turns out that each arch has a different + * opinion on the subject, and different kernel revs use different names... */ +#if defined(__sparc_v9__) && (__WORDSIZE == 64) +#define kernel_stat64 stat +#else +#define kernel_stat stat +#endif +#include +#include + +/* Protection bits. */ +#define S_ISUID 04000 /* Set user ID on execution. */ +#define S_ISGID 02000 /* Set group ID on execution. */ + + +/* Here are the definitions for some syscalls that are used + by the dynamic linker. The idea is that we want to be able + to call these before the errno symbol is dynamicly linked, so + we use our own version here. Note that we cannot assume any + dynamic linking at all, so we cannot return any error codes. + We just punt if there is an error. */ +#define __NR__dl_exit __NR_exit +static __always_inline _syscall1(void, _dl_exit, int, status) + +#define __NR__dl_close __NR_close +static __always_inline _syscall1(int, _dl_close, int, fd) + +#define __NR__dl_open __NR_open +static __always_inline _syscall3(int, _dl_open, const char *, fn, int, flags, + __kernel_mode_t, mode) + +#define __NR__dl_write __NR_write +static __always_inline _syscall3(unsigned long, _dl_write, int, fd, + const void *, buf, unsigned long, count) + +#define __NR__dl_read __NR_read +static __always_inline _syscall3(unsigned long, _dl_read, int, fd, + const void *, buf, unsigned long, count) + +#define __NR__dl_mprotect __NR_mprotect +static __always_inline _syscall3(int, _dl_mprotect, const void *, addr, + unsigned long, len, int, prot) + +#define __NR__dl_stat __NR_stat +static __always_inline _syscall2(int, _dl_stat, const char *, file_name, + struct stat *, buf) + +#define __NR__dl_fstat __NR_fstat +static __always_inline _syscall2(int, _dl_fstat, int, fd, struct stat *, buf) + +#define __NR__dl_munmap __NR_munmap +static __always_inline _syscall2(int, _dl_munmap, void *, start, unsigned long, length) + +#ifdef __NR_getxuid +# define __NR_getuid __NR_getxuid +#endif +#define __NR__dl_getuid __NR_getuid +static __always_inline _syscall0(uid_t, _dl_getuid) + +#ifndef __NR_geteuid +# define __NR_geteuid __NR_getuid +#endif +#define __NR__dl_geteuid __NR_geteuid +static __always_inline _syscall0(uid_t, _dl_geteuid) + +#ifdef __NR_getxgid +# define __NR_getgid __NR_getxgid +#endif +#define __NR__dl_getgid __NR_getgid +static __always_inline _syscall0(gid_t, _dl_getgid) + +#ifndef __NR_getegid +# define __NR_getegid __NR_getgid +#endif +#define __NR__dl_getegid __NR_getegid +static __always_inline _syscall0(gid_t, _dl_getegid) + +#ifdef __NR_getxpid +# define __NR_getpid __NR_getxpid +#endif +#define __NR__dl_getpid __NR_getpid +static __always_inline _syscall0(gid_t, _dl_getpid) + +#define __NR__dl_readlink __NR_readlink +static __always_inline _syscall3(int, _dl_readlink, const char *, path, char *, buf, + size_t, bufsiz) + +#ifdef __UCLIBC_HAS_SSP__ +# include +# define __NR__dl_gettimeofday __NR_gettimeofday +static __always_inline _syscall2(int, _dl_gettimeofday, struct timeval *, tv, +# ifdef __USE_BSD + struct timezone * +# else + void * +# endif + , tz) +#endif + +/* Some architectures always use 12 as page shift for mmap2() eventhough the + * real PAGE_SHIFT != 12. Other architectures use the same value as + * PAGE_SHIFT... + */ +#ifndef MMAP2_PAGE_SHIFT +# define MMAP2_PAGE_SHIFT 12 +#endif + +#define MAP_FAILED ((void *) -1) +#define _dl_mmap_check_error(X) (((void *)X) == MAP_FAILED) + +static __always_inline +void *_dl_mmap(void *addr, unsigned long size, int prot, + int flags, int fd, unsigned long offset) +{ +#if defined(__UCLIBC_MMAP_HAS_6_ARGS__) && defined(__NR_mmap) + /* first try mmap(), syscall6() style */ + return (void *)INLINE_SYSCALL(mmap, 6, addr, size, prot, flags, fd, offset); + +#elif defined(__NR_mmap2) && !defined (__mcoldfire__) + /* then try mmap2() */ + unsigned long shifted; + + if (offset & ((1 << MMAP2_PAGE_SHIFT) - 1)) + return MAP_FAILED; + + /* gcc needs help with putting things onto the stack */ + shifted = offset >> MMAP2_PAGE_SHIFT; + return (void *)INLINE_SYSCALL(mmap2, 6, addr, size, prot, flags, fd, shifted); + +#elif defined(__NR_mmap) + /* finally, fall back to mmap(), syscall1() style */ + unsigned long buffer[6]; + buffer[0] = (unsigned long) addr; + buffer[1] = (unsigned long) size; + buffer[2] = (unsigned long) prot; + buffer[3] = (unsigned long) flags; + buffer[4] = (unsigned long) fd; + buffer[5] = (unsigned long) offset; + return (void *)INLINE_SYSCALL(mmap, 1, buffer); +#else +# error "Your architecture doesn't seem to provide mmap() !?" +#endif +} + +#endif /* not for L4 */ +#endif /* _LD_SYSCALL_H_ */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/include/dlfcn.h b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/include/dlfcn.h new file mode 100644 index 00000000..03afd34f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/include/dlfcn.h @@ -0,0 +1,28 @@ +/* vi: set sw=4 ts=4: */ +/* + * Copyright (C) 2000-2005 by Erik Andersen + * + * GNU Lesser General Public License version 2.1 or later. + */ + +/* User functions for run-time dynamic loading. libdl version */ +#ifndef _DLFCN_H +#define _DLFCN_H 1 + +#include +#include + +#define RTLD_NEXT ((void *) -1l) +#define RTLD_DEFAULT ((void *) 0) + +/* Structure containing information about object searched using + `dladdr'. */ +typedef struct +{ + __const char *dli_fname; /* File name of defining object. */ + void *dli_fbase; /* Load address of that object. */ + __const char *dli_sname; /* Name of nearest symbol. */ + void *dli_saddr; /* Exact value of nearest symbol. */ +} Dl_info; + +#endif /* _DLFCN_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/include/ldso.h b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/include/ldso.h new file mode 100644 index 00000000..69b5dd75 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/include/ldso.h @@ -0,0 +1,159 @@ +/* vi: set sw=4 ts=4: */ +/* + * Copyright (C) 2000-2005 by Erik Andersen + * + * GNU Lesser General Public License version 2.1 or later. + */ + +#ifndef _LDSO_H_ +#define _LDSO_H_ + +#include + +/* Prepare for the case that `__builtin_expect' is not available. */ +#if defined __GNUC__ && __GNUC__ == 2 && __GNUC_MINOR__ < 96 +#define __builtin_expect(x, expected_value) (x) +#endif +#ifndef likely +# define likely(x) __builtin_expect((!!(x)),1) +#endif +#ifndef unlikely +# define unlikely(x) __builtin_expect((!!(x)),0) +#endif +#ifndef __LINUX_COMPILER_H +#define __LINUX_COMPILER_H +#endif + +/* Pull in compiler and arch stuff */ +#include +#include +#define _FCNTL_H +#include +#include +/* Pull in the arch specific type information */ +#include +/* Pull in the arch specific page size */ +#include +/* Pull in the ldso syscalls and string functions */ +#ifndef __ARCH_HAS_NO_SHARED__ +#include +#include +#include +/* Now the ldso specific headers */ +#include +#ifdef __UCLIBC_HAS_TLS__ +/* Defines USE_TLS */ +#include +#endif +#include + +/* common align masks, if not specified by sysdep headers */ +#ifndef ADDR_ALIGN +#define ADDR_ALIGN (_dl_pagesize - 1) +#endif + +#ifndef PAGE_ALIGN +#define PAGE_ALIGN (~ADDR_ALIGN) +#endif + +#ifndef OFFS_ALIGN +#define OFFS_ALIGN (PAGE_ALIGN & ~(1ul << (sizeof(_dl_pagesize) * 8 - 1))) +#endif + +/* For INIT/FINI dependency sorting. */ +struct init_fini_list { + struct init_fini_list *next; + struct elf_resolve *tpnt; +}; + +/* Global variables used within the shared library loader */ +extern char *_dl_library_path; /* Where we look for libraries */ +extern char *_dl_preload; /* Things to be loaded before the libs */ +extern char *_dl_ldsopath; /* Where the shared lib loader was found */ +extern const char *_dl_progname; /* The name of the executable being run */ +extern size_t _dl_pagesize; /* Store the page size for use later */ + +#if defined(USE_TLS) && USE_TLS +extern void _dl_add_to_slotinfo (struct link_map *l); +extern void ** __attribute__ ((const)) _dl_initial_error_catch_tsd (void); +#endif + +#ifdef USE_TLS +void _dl_add_to_slotinfo (struct link_map *l); +void ** __attribute__ ((const)) _dl_initial_error_catch_tsd (void); +#endif +#ifdef __SUPPORT_LD_DEBUG__ +extern char *_dl_debug; +extern char *_dl_debug_symbols; +extern char *_dl_debug_move; +extern char *_dl_debug_reloc; +extern char *_dl_debug_detail; +extern char *_dl_debug_nofixups; +extern char *_dl_debug_bindings; +extern int _dl_debug_file; +# define __dl_debug_dprint(fmt, args...) \ + _dl_dprintf(_dl_debug_file, "%s:%i: " fmt, __FUNCTION__, __LINE__, ## args); +# define _dl_if_debug_dprint(fmt, args...) \ + do { if (_dl_debug) __dl_debug_dprint(fmt, ## args); } while (0) +#else +# define __dl_debug_dprint(fmt, args...) do {} while (0) +# define _dl_if_debug_dprint(fmt, args...) do {} while (0) +# define _dl_debug_file 2 +#endif /* __SUPPORT_LD_DEBUG__ */ + +#ifdef IS_IN_rtld +# ifdef __SUPPORT_LD_DEBUG__ +# define _dl_assert(expr) \ + do { \ + if (!(expr)) { \ + __dl_debug_dprint("assert(%s)\n", #expr); \ + _dl_exit(45); \ + } \ + } while (0) +# else +# define _dl_assert(expr) ((void)0) +# endif +#else +# include +# define _dl_assert(expr) assert(expr) +#endif + +#ifdef __SUPPORT_LD_DEBUG_EARLY__ +# define _dl_debug_early(fmt, args...) __dl_debug_dprint(fmt, ## args) +#else +# define _dl_debug_early(fmt, args...) do {} while (0) +#endif /* __SUPPORT_LD_DEBUG_EARLY__ */ + +#ifndef NULL +#define NULL ((void *) 0) +#endif + +extern void *_dl_malloc(size_t size); +extern void *_dl_calloc(size_t __nmemb, size_t __size); +extern void *_dl_realloc(void *__ptr, size_t __size); +extern void _dl_free(void *); +extern char *_dl_getenv(const char *symbol, char **envp); +extern void _dl_unsetenv(const char *symbol, char **envp); +extern char *_dl_strdup(const char *string); +extern void _dl_dprintf(int, const char *, ...); + +#ifndef DL_GET_READY_TO_RUN_EXTRA_PARMS +# define DL_GET_READY_TO_RUN_EXTRA_PARMS +#endif +#ifndef DL_GET_READY_TO_RUN_EXTRA_ARGS +# define DL_GET_READY_TO_RUN_EXTRA_ARGS +#endif + +extern void _dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr, + ElfW(auxv_t) auxvt[AT_EGID + 1], char **envp, char **argv + DL_GET_READY_TO_RUN_EXTRA_PARMS); + +#ifdef HAVE_DL_INLINES_H +#include +#endif + +#else /* __ARCH_HAS_NO_SHARED__ */ +#include +#endif + +#endif /* _LDSO_H_ */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/include/ldsodefs.h b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/include/ldsodefs.h new file mode 100644 index 00000000..236c0fc3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/include/ldsodefs.h @@ -0,0 +1,147 @@ +#ifndef _LDSODEFS_H +#define _LDSODEFS_H 1 + +#include +#include +#include +#include + +#ifdef __mips__ +/* The MIPS ABI specifies that the dynamic section has to be read-only. */ + +#define DL_RO_DYN_SECTION 1 + +/* TODO: Import in 64-bit relocations from glibc. */ +#endif + +#ifndef SHARED +# define EXTERN extern +#else +# ifdef IS_IN_rtld +# define EXTERN +# else +# define EXTERN extern +# endif +#endif + +/* Non-shared code has no support for multiple namespaces. */ +#ifdef SHARED +# define DL_NNS 16 +#else +# define DL_NNS 1 +#endif + +#define GL(x) _##x +#define GLRO(x) _##x + +/* Variable pointing to the end of the stack (or close to it). This value + must be constant over the runtime of the application. Some programs + might use the variable which results in copy relocations on some + platforms. But this does not matter, ld.so can always use the local + copy. */ +extern void *__libc_stack_end; + +/* Determine next available module ID. */ +extern size_t _dl_next_tls_modid (void) internal_function attribute_hidden; + +/* Calculate offset of the TLS blocks in the static TLS block. */ +extern void _dl_determine_tlsoffset (void) internal_function attribute_hidden; + +/* Set up the data structures for TLS, when they were not set up at startup. + Returns nonzero on malloc failure. + This is called from _dl_map_object_from_fd or by libpthread. */ +extern int _dl_tls_setup (void) internal_function; +rtld_hidden_proto (_dl_tls_setup) + +/* Allocate memory for static TLS block (unless MEM is nonzero) and dtv. */ +extern void *_dl_allocate_tls (void *mem) internal_function; + +/* Get size and alignment requirements of the static TLS block. */ +extern void _dl_get_tls_static_info (size_t *sizep, size_t *alignp) + internal_function; + +extern void _dl_allocate_static_tls (struct link_map *map) + internal_function attribute_hidden; + +/* Taken from glibc/elf/dl-reloc.c */ +#define CHECK_STATIC_TLS(sym_map) \ + do { \ + if (__builtin_expect ((sym_map)->l_tls_offset == NO_TLS_OFFSET, 0)) \ + _dl_allocate_static_tls (sym_map); \ + } while (0) + +/* These are internal entry points to the two halves of _dl_allocate_tls, + only used within rtld.c itself at startup time. */ +extern void *_dl_allocate_tls_storage (void) + internal_function attribute_hidden; +extern void *_dl_allocate_tls_init (void *) internal_function; + +/* Deallocate memory allocated with _dl_allocate_tls. */ +extern void _dl_deallocate_tls (void *tcb, bool dealloc_tcb) internal_function; + +extern void _dl_nothread_init_static_tls (struct link_map *) attribute_hidden; + +/* Highest dtv index currently needed. */ +EXTERN size_t _dl_tls_max_dtv_idx; +/* Flag signalling whether there are gaps in the module ID allocation. */ +EXTERN bool _dl_tls_dtv_gaps; +/* Information about the dtv slots. */ +EXTERN struct dtv_slotinfo_list +{ + size_t len; + struct dtv_slotinfo_list *next; + struct dtv_slotinfo + { + size_t gen; + bool is_static; + struct link_map *map; + } slotinfo[0]; +} *_dl_tls_dtv_slotinfo_list; +/* Number of modules in the static TLS block. */ +EXTERN size_t _dl_tls_static_nelem; +/* Size of the static TLS block. */ +EXTERN size_t _dl_tls_static_size; +/* Size actually allocated in the static TLS block. */ +EXTERN size_t _dl_tls_static_used; +/* Alignment requirement of the static TLS block. */ +EXTERN size_t _dl_tls_static_align; +/* Function pointer for catching TLS errors. */ +EXTERN void **(*_dl_error_catch_tsd) (void) __attribute__ ((const)); + +/* Number of additional entries in the slotinfo array of each slotinfo + list element. A large number makes it almost certain take we never + have to iterate beyond the first element in the slotinfo list. */ +# define TLS_SLOTINFO_SURPLUS (62) + +/* Number of additional slots in the dtv allocated. */ +# define DTV_SURPLUS (14) + +/* Initial dtv of the main thread, not allocated with normal malloc. */ +EXTERN void *_dl_initial_dtv; +/* Generation counter for the dtv. */ +EXTERN size_t _dl_tls_generation; + +EXTERN void (*_dl_init_static_tls) (struct link_map *); + +/* We have the auxiliary vector. */ +#define HAVE_AUX_VECTOR + +/* We can assume that the kernel always provides the AT_UID, AT_EUID, + AT_GID, and AT_EGID values in the auxiliary vector from 2.4.0 or so on. */ +#if __ASSUME_AT_XID +# define HAVE_AUX_XID +#endif + +/* We can assume that the kernel always provides the AT_SECURE value + in the auxiliary vector from 2.5.74 or so on. */ +#if __ASSUME_AT_SECURE +# define HAVE_AUX_SECURE +#endif + +/* Starting with one of the 2.4.0 pre-releases the Linux kernel passes + up the page size information. */ +#if __ASSUME_AT_PAGESIZE +# define HAVE_AUX_PAGESIZE +#endif + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/include/unsecvars.h b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/include/unsecvars.h new file mode 100644 index 00000000..f1ef381e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/include/unsecvars.h @@ -0,0 +1,32 @@ +/* vi: set sw=4 ts=4: */ +/* + * Copyright (C) 2000-2005 by Erik Andersen + * + * GNU Lesser General Public License version 2.1 or later. + */ + +/* + * Environment variable to be removed for SUID programs. The names are all + * stuffed in a single string which means they have to be terminated with a + * '\0' explicitly. + */ + +#define UNSECURE_ENVVARS \ + "LD_PRELOAD\0" \ + "LD_LIBRARY_PATH\0" \ + "LD_DEBUG\0" \ + "LD_DEBUG_OUTPUT\0" \ + "LD_TRACE_LOADED_OBJECTS\0" \ + "TMPDIR\0" + +/* + * LD_TRACE_LOADED_OBJECTS is not in glibc-2.3.5's unsecvars.h + * though used by ldd + * + * These environment variables are defined by glibc but ignored in + * uClibc, but may very well have an equivalent in uClibc. + * + * LD_ORIGIN_PATH, LD_PROFILE, LD_USE_LOAD_BIAS, LD_DYNAMIC_WEAK, LD_SHOW_AUXV, + * GCONV_PATH, GETCONF_DIR, HOSTALIASES, LOCALDOMAIN, LOCPATH, MALLOC_TRACE, + * NLSPATH, RESOLV_HOST_CONF, RES_OPTIONS, TZDIR + */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/Makefile new file mode 100644 index 00000000..f9100219 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../ +top_builddir=../../ +include $(top_builddir)Rules.mak +all: libs +include Makefile.in +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/Makefile.in new file mode 100644 index 00000000..7a9ffa64 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/Makefile.in @@ -0,0 +1,75 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +subdirs += ldso/ldso/$(TARGET_ARCH) + +CFLAGS-ldso := -DNOT_IN_libc -DIS_IN_rtld $(SSP_DISABLE_FLAGS) + +# This stuff will not work with -fomit-frame-pointer +CFLAGS-ldso += -fno-omit-frame-pointer + +CFLAGS-ldso += -I$(top_srcdir)ldso/ldso/$(TARGET_ARCH) -I$(top_srcdir)ldso/include -I$(top_srcdir)ldso/ldso +CFLAGS-ldso += -DUCLIBC_RUNTIME_PREFIX=\"$(RUNTIME_PREFIX)\" -DUCLIBC_LDSO=\"$(UCLIBC_LDSO)\" + +ifeq ($(DODEBUG),y) +# Not really much point in including debugging info, since gdb +# can't really debug ldso, since gdb requires help from ldso to +# debug things.... +# On arm, gcc-4.3.x onwards -Os emits calls to libgcc, which calls _div0, +# which tries to call raise(). And raise comes from libc so a catch 22. +# Using -O2 instead. We could have use -fno-early-inlining with -Os too. + +CFLAGS-ldso += -O2 -g +endif + +CFLAGS-ldso/ldso/$(TARGET_ARCH)/ := $(CFLAGS-ldso) + +CFLAGS-ldso.c := -DLDSO_ELFINTERP=\"$(TARGET_ARCH)/elfinterp.c\" $(CFLAGS-ldso) + +LDFLAGS-$(UCLIBC_FORMAT_DSBT_ELF)-$(UCLIBC_LDSO_NAME).so := -Wl,--dsbt-index=1 +ifneq ($(SUPPORT_LD_DEBUG),y) +LDFLAGS-$(UCLIBC_LDSO_NAME).so := $(LDFLAGS) +else +LDFLAGS-$(UCLIBC_LDSO_NAME).so := $(LDFLAGS_NOSTRIP) -Wl,-z,defs +endif +LDFLAGS-$(UCLIBC_LDSO_NAME).so += -Wl,-e,_start -Wl,-z,now -Wl,-Bsymbolic -Wl,--export-dynamic $(LDFLAG_SORT_COMMON) -Wl,--discard-locals $(LDFLAG_DISCARD_ALL) -Wl,--no-undefined + +ldso_FULL_NAME := $(UCLIBC_LDSO_NAME)-$(VERSION).so + +$(UCLIBC_LDSO_NAME)_DIR := $(top_srcdir)ldso/ldso +$(UCLIBC_LDSO_NAME)_OUT := $(top_builddir)ldso/ldso + +$(UCLIBC_LDSO_NAME)_CSRC := $($(UCLIBC_LDSO_NAME)_DIR)/ldso.c +# prerequesites +$($(UCLIBC_LDSO_NAME)_OUT)/ldso.o $($(UCLIBC_LDSO_NAME)_OUT)/ldso.oS: \ + $($(UCLIBC_LDSO_NAME)_DIR)/dl-debug.c \ + $($(UCLIBC_LDSO_NAME)_DIR)/dl-startup.c \ + $($(UCLIBC_LDSO_NAME)_DIR)/dl-array.c \ + $($(UCLIBC_LDSO_NAME)_DIR)/dl-hash.c \ + $($(UCLIBC_LDSO_NAME)_DIR)/dl-elf.c +$(UCLIBC_LDSO_NAME)_COBJ := $(patsubst $($(UCLIBC_LDSO_NAME)_DIR)/%.c,$($(UCLIBC_LDSO_NAME)_OUT)/%.o,$($(UCLIBC_LDSO_NAME)_CSRC)) + +$(UCLIBC_LDSO_NAME)_SSRC := $(wildcard $($(UCLIBC_LDSO_NAME)_DIR)/$(TARGET_ARCH)/*.S) +$(UCLIBC_LDSO_NAME)_SOBJ := $(patsubst $($(UCLIBC_LDSO_NAME)_DIR)/$(TARGET_ARCH)/%.S,$($(UCLIBC_LDSO_NAME)_OUT)/$(TARGET_ARCH)/%.o,$($(UCLIBC_LDSO_NAME)_SSRC)) + +$(UCLIBC_LDSO_NAME)_OBJS := $($(UCLIBC_LDSO_NAME)_COBJ) $($(UCLIBC_LDSO_NAME)_SOBJ) + +ldso-y := $($(UCLIBC_LDSO_NAME)_OBJS:.o=.oS) + +lib-so-y += $(ldso) +objclean-y += CLEAN_ldso/ldso + +$(ldso): $(ldso:.$(ABI_VERSION)=) +$(ldso:.$(ABI_VERSION)=): $($(UCLIBC_LDSO_NAME)_OUT)/$(UCLIBC_LDSO_NAME)_so.a + $(call link.so,$(ldso_FULL_NAME),$(ABI_VERSION)) + +$($(UCLIBC_LDSO_NAME)_OUT)/$(UCLIBC_LDSO_NAME)_so.a: $(ldso-y) + $(Q)$(RM) $@ + $(do_ar) + +CLEAN_ldso/ldso: + $(do_rm) $(addprefix $($(UCLIBC_LDSO_NAME)_OUT)/,$(foreach e, o os oS a,$(foreach d, *. */*.,$(d)$(e)))) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/arm/aeabi_read_tp.S b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/arm/aeabi_read_tp.S new file mode 100644 index 00000000..564f5933 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/arm/aeabi_read_tp.S @@ -0,0 +1,63 @@ +/* Copyright (C) 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file with other + programs, and to distribute those programs without any restriction + coming from the use of this file. (The GNU Lesser General Public + License restrictions do apply in other respects; for example, they + cover modification of the file, and distribution when not linked + into another program.) + + Note that people who make modified versions of this file are not + obligated to grant this special exception for their modified + versions; it is their choice whether to do so. The GNU Lesser + General Public License gives permission to release a modified + version without this exception; this exception also makes it + possible to release a modified version which carries forward this + exception. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#ifdef __UCLIBC_HAS_THREADS_NATIVE__ + +#include + +/* GCC will emit calls to this routine under -mtp=soft. Linux has an + equivalent helper function (which clobbers fewer registers than + a normal function call) in a high page of memory; tail call to the + helper. + + This function is exported from libc for use by user code. libpthread, librt, + and the dynamic linker get their own private copies, for + performance (and in the case of ld.so, out of necessity); those are + all hidden. */ + +#ifndef NOT_IN_libc + .global __aeabi_read_tp +#else + .hidden __aeabi_read_tp +#endif +ENTRY (__aeabi_read_tp) + mov r0, #0xffff0fff + sub pc, r0, #31 +END (__aeabi_read_tp) + +#endif /* __UCLIBC_HAS_THREADS_NATIVE__ */ + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/arm/dl-debug.h b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/arm/dl-debug.h new file mode 100644 index 00000000..1bca6ff3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/arm/dl-debug.h @@ -0,0 +1,46 @@ +/* vi: set sw=4 ts=4: */ +/* ARM ELF shared library loader suppport + * + * Copyright (C) 2001-2004 Erik Andersen + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. The name of the above contributors may not be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +static const char *_dl_reltypes_tab[] = +{ + [0] "R_ARM_NONE", "R_ARM_PC24", "R_ARM_ABS32", "R_ARM_REL32", + [4] "R_ARM_PC13", "R_ARM_ABS16", "R_ARM_ABS12", "R_ARM_THM_ABS5", + [8] "R_ARM_ABS8", "R_ARM_SBREL32","R_ARM_THM_PC22", "R_ARM_THM_PC8", + [12] "R_ARM_AMP_VCALL9", "R_ARM_SWI24", "R_ARM_THM_SWI8", "R_ARM_XPC25", + [16] "R_ARM_THM_XPC22", "R_ARM_TLS_DTPMOD32", "R_ARM_TLS_DTPOFF32", "R_ARM_TLS_TPOFF32", + [20] "R_ARM_COPY", "R_ARM_GLOB_DAT","R_ARM_JUMP_SLOT", "R_ARM_RELATIVE", + [24] "R_ARM_GOTOFF", "R_ARM_GOTPC", "R_ARM_GOT32", "R_ARM_PLT32", + [32] "R_ARM_ALU_PCREL_7_0","R_ARM_ALU_PCREL_15_8","R_ARM_ALU_PCREL_23_15","R_ARM_LDR_SBREL_11_0", + [36] "R_ARM_ALU_SBREL_19_12","R_ARM_ALU_SBREL_27_20", + [100] "R_ARM_GNU_VTENTRY","R_ARM_GNU_VTINHERIT","R_ARM_THM_PC11","R_ARM_THM_PC9", + [104] "R_ARM_TLS_GD32","R_ARM_TLS_LDM32","R_ARM_TLS_LDO32","R_ARM_TLS_IE32", + [108] "R_ARM_TLS_LE32","R_ARM_TLS_LDO12","R_ARM_TLS_LE12","R_ARM_TLS_IE12GP", + [249] "R_ARM_RXPC25", "R_ARM_RSBREL32", "R_ARM_THM_RPC22", "R_ARM_RREL32", + [253] "R_ARM_RABS22", "R_ARM_RPC24", "R_ARM_RBASE", +}; diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/arm/dl-startup.h b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/arm/dl-startup.h new file mode 100644 index 00000000..a95389d9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/arm/dl-startup.h @@ -0,0 +1,194 @@ +/* vi: set sw=4 ts=4: */ +/* + * Architecture specific code used by dl-startup.c + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +#if !defined(__thumb__) +__asm__( + " .text\n" + " .globl _start\n" + " .type _start,%function\n" + "_start:\n" + " @ at start time, all the args are on the stack\n" + " mov r0, sp\n" + " bl _dl_start\n" + " @ returns user entry point in r0\n" + " mov r6, r0\n" + " @ we are PIC code, so get global offset table\n" + " ldr sl, .L_GET_GOT\n" + " add sl, pc, sl\n" + ".L_GOT_GOT:\n" + " @ See if we were run as a command with the executable file\n" + " @ name as an extra leading argument.\n" + " ldr r4, .L_SKIP_ARGS\n" + " ldr r4, [sl, r4]\n" + " @ get the original arg count\n" + " ldr r1, [sp]\n" + " @ subtract _dl_skip_args from it\n" + " sub r1, r1, r4\n" + " @ adjust the stack pointer to skip them\n" + " add sp, sp, r4, lsl #2\n" + " @ get the argv address\n" + " add r2, sp, #4\n" + " @ store the new argc in the new stack location\n" + " str r1, [sp]\n" + " @ compute envp\n" + " add r3, r2, r1, lsl #2\n" + " add r3, r3, #4\n" + "\n\n" + " @ load the finalizer function\n" + " ldr r0, .L_FINI_PROC\n" + " ldr r0, [sl, r0]\n" + " @ jump to the user_s entry point\n" +#if defined(__USE_BX__) + " bx r6\n" +#else + " mov pc, r6\n" +#endif + ".L_GET_GOT:\n" + " .word _GLOBAL_OFFSET_TABLE_ - .L_GOT_GOT - 4\n" + ".L_SKIP_ARGS:\n" + " .word _dl_skip_args(GOTOFF)\n" + ".L_FINI_PROC:\n" + " .word _dl_fini(GOT)\n" + "\n\n" + " .size _start,.-_start\n" + ".previous\n" +); +#else +__asm__( + " .text\n" + " .arm\n" + " .globl _start\n" + " .type _start,%function\n" + "_start:\n" + " @ dumb: can't persuade the linker to make the start address\n" + " @ odd, so use an arm function and change to thumb (_dl_start\n" + " @ is thumb)\n" + " adr r0, __dl_thumb_start+1\n" + " bx r0\n" + "\n\n" + " .thumb\n" + " .globl __dl_thumb_start\n" + " .thumb_func\n" + " .type __dl_thumb_start,%function\n" + "__dl_thumb_start:\n" + " @ at start time, all the args are on the stack\n" + " mov r0, sp\n" + " bl _dl_start\n" + " @ returns user entry point in r0\n" + " mov r6, r0\n" + " @ we are PIC code, so get global offset table\n" + " ldr r7, .L_GET_GOT\n" + ".L_GOT_GOT:\n" + " add r7, pc\n" + " @ See if we were run as a command with the executable file\n" + " @ name as an extra leading argument.\n" + " ldr r4, .L_SKIP_ARGS\n" + " ldr r4, [r7, r4]\n" + " @ get the original arg count\n" + " ldr r1, [sp]\n" + " @ subtract _dl_skip_args from it\n" + " sub r1, r1, r4\n" + " @ adjust the stack pointer to skip them\n" + " lsl r4, r4, #2\n" + " add sp, r4\n" + " @ get the argv address\n" + " add r2, sp, #4\n" + " @ store the new argc in the new stack location\n" + " str r1, [sp]\n" + " @ compute envp\n" + " lsl r3, r1, #2\n" + " add r3, r3, r2\n" + " add r3, #4\n" + "\n\n" + " @ load the finalizer function\n" + " ldr r0, .L_FINI_PROC\n" + " ldr r0, [r7, r0]\n" + " @ jump to the user_s entry point\n" +#if defined(__USE_BX__) + " bx r6\n" +#else + " mov pc, r6\n" +#endif + "\n\n" + ".L_GET_GOT:\n" + " .word _GLOBAL_OFFSET_TABLE_ - .L_GOT_GOT - 4\n" + ".L_SKIP_ARGS:\n" + " .word _dl_skip_args(GOTOFF)\n" + ".L_FINI_PROC:\n" + " .word _dl_fini(GOT)\n" + "\n\n" + " .size _start,.-_start\n" + ".previous\n" +); +#endif + + +/* Get a pointer to the argv array. On many platforms this can be just + * the address of the first argument, on other platforms we need to + * do something a little more subtle here. */ +#define GET_ARGV(ARGVP, ARGS) ARGVP = (((unsigned long*)ARGS)+1) + +/* Handle relocation of the symbols in the dynamic loader. */ +static __always_inline +void PERFORM_BOOTSTRAP_RELOC(ELF_RELOC *rpnt, unsigned long *reloc_addr, + unsigned long symbol_addr, unsigned long load_addr, Elf32_Sym *symtab) +{ + switch (ELF32_R_TYPE(rpnt->r_info)) { + case R_ARM_NONE: + break; + case R_ARM_ABS32: + *reloc_addr += symbol_addr; + break; + case R_ARM_PC24: + { + unsigned long addend; + long newvalue, topbits; + + addend = *reloc_addr & 0x00ffffff; + if (addend & 0x00800000) addend |= 0xff000000; + + newvalue = symbol_addr - (unsigned long)reloc_addr + (addend << 2); + topbits = newvalue & 0xfe000000; + if (topbits != 0xfe000000 && topbits != 0x00000000) + { +#if 0 + /* Don't bother with this during ldso initilization... */ + newvalue = fix_bad_pc24(reloc_addr, symbol_addr) + - (unsigned long)reloc_addr + (addend << 2); + topbits = newvalue & 0xfe000000; + if (unlikely(topbits != 0xfe000000 && topbits != 0x00000000)) + { + SEND_STDERR("R_ARM_PC24 relocation out of range\n"); + _dl_exit(1); + } +#else + SEND_STDERR("R_ARM_PC24 relocation out of range\n"); + _dl_exit(1); +#endif + } + newvalue >>= 2; + symbol_addr = (*reloc_addr & 0xff000000) | (newvalue & 0x00ffffff); + *reloc_addr = symbol_addr; + break; + } + case R_ARM_GLOB_DAT: + case R_ARM_JUMP_SLOT: + *reloc_addr = symbol_addr; + break; + case R_ARM_RELATIVE: + *reloc_addr += load_addr; + break; + case R_ARM_COPY: + break; + default: + SEND_STDERR("Unsupported relocation type\n"); + _dl_exit(1); + } +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/arm/dl-syscalls.h b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/arm/dl-syscalls.h new file mode 100644 index 00000000..1c0e6699 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/arm/dl-syscalls.h @@ -0,0 +1,42 @@ +/* We can't use the real errno in ldso, since it has not yet + * been dynamicly linked in yet. */ +#include "sys/syscall.h" +extern int _dl_errno; +#undef __set_errno +#define __set_errno(X) {(_dl_errno) = (X);} +/* _call_via_rX calls are used in thumb ldso because of calls via + * function pointers, but ldso is not linked with anything which + * provides them, so define them here (only required for thumb). + */ +#if defined(__thumb__) +__asm__( + ".macro call_via register\n" + " .global _call_via_\\register\n" + " .hidden _call_via_\\register\n" + " .type _call_via_\\register, %function\n" + " .thumb_func\n" + "_call_via_\\register:\n" + " bx \\register\n" + " .size _call_via_\\register, . - _call_via_\\register\n" + ".endm\n" + + ".text\n" + ".thumb\n" + ".align 1\n" + " call_via r0\n" + " call_via r1\n" + " call_via r2\n" + " call_via r3\n" + " call_via r4\n" + " call_via r5\n" + " call_via r6\n" + " call_via r7\n" + " call_via r8\n" + " call_via r9\n" + " call_via r10\n" + " call_via r11\n" + " call_via r12\n" + " call_via r13\n" + " call_via r14\n" +); +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/arm/dl-sysdep.h b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/arm/dl-sysdep.h new file mode 100644 index 00000000..380667e5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/arm/dl-sysdep.h @@ -0,0 +1,155 @@ +/* vi: set sw=4 ts=4: */ +/* + * Various assembly language/system dependent hacks that are required + * so that we can minimize the amount of platform specific code. + * Copyright (C) 2000-2004 by Erik Andersen + */ + +#ifndef _ARCH_DL_SYSDEP +#define _ARCH_DL_SYSDEP + +/* Define this if the system uses RELOCA. */ +#undef ELF_USES_RELOCA +#include +/* Initialization sequence for the GOT. */ +#define INIT_GOT(GOT_BASE,MODULE) \ +{ \ + GOT_BASE[2] = (unsigned long) _dl_linux_resolve; \ + GOT_BASE[1] = (unsigned long) MODULE; \ +} + +static __always_inline unsigned long arm_modulus(unsigned long m, unsigned long p) +{ + unsigned long i,t,inc; + i=p; t=0; + while (!(i&(1<<31))) { + i<<=1; + t++; + } + t--; + for (inc=t;inc>2;inc--) { + i=p<=i) { + m-=i; + i<<=1; + if (i&(1<<31)) + break; + if (i=p) { + m-=p; + } + return m; +} +#define do_rem(result, n, base) ((result) = arm_modulus(n, base)) +#define do_div_10(result, remain) ((result) = (((result) - (remain)) / 2) * -(-1ul / 5ul)) + +/* Here we define the magic numbers that this dynamic loader should accept */ +#define MAGIC1 EM_ARM +#undef MAGIC2 + +/* Used for error messages */ +#define ELF_TARGET "ARM" + +struct elf_resolve; +unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_entry); + +/* 4096 bytes alignment */ +#define PAGE_ALIGN 0xfffff000 +#define ADDR_ALIGN 0xfff +#define OFFS_ALIGN 0x7ffff000 + +/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry or + TLS variable, so undefined references should not be allowed to + define the value. + + ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to one + of the main executable's symbols, as for a COPY reloc. */ +#define elf_machine_type_class(type) \ + ((((type) == R_ARM_JUMP_SLOT || (type) == R_ARM_TLS_DTPMOD32 \ + || (type) == R_ARM_TLS_DTPOFF32 || (type) == R_ARM_TLS_TPOFF32) \ + * ELF_RTYPE_CLASS_PLT) \ + | (((type) == R_ARM_COPY) * ELF_RTYPE_CLASS_COPY)) + +/* Return the link-time address of _DYNAMIC. Conveniently, this is the + first element of the GOT. We used to use the PIC register to do this + without a constant pool reference, but GCC 4.2 will use a pseudo-register + for the PIC base, so it may not be in r10. */ +static __always_inline Elf32_Addr __attribute__ ((unused)) +elf_machine_dynamic (void) +{ + Elf32_Addr dynamic; +#if !defined __thumb__ + __asm__ ("ldr %0, 2f\n" + "1: ldr %0, [pc, %0]\n" + "b 3f\n" + "2: .word _GLOBAL_OFFSET_TABLE_ - (1b+8)\n" + "3:" : "=r" (dynamic)); +#else + int tmp; + __asm__ (".align 2\n" + "bx pc\n" + "nop\n" + ".arm\n" + "ldr %0, 2f\n" + "1: ldr %0, [pc, %0]\n" + "b 3f\n" + "2: .word _GLOBAL_OFFSET_TABLE_ - (1b+8)\n" + "3:" + ".align 2\n" + "orr %1, pc, #1\n" + "bx %1\n" + ".force_thumb\n" + : "=r" (dynamic), "=&r" (tmp)); +#endif + + return dynamic; +} + +extern /*void*/ int __dl_start __asm__ ("_dl_start"); + +/* Return the run-time load address of the shared object. */ +static __always_inline Elf32_Addr __attribute__ ((unused)) +elf_machine_load_address (void) +{ + Elf32_Addr got_addr = (Elf32_Addr) &__dl_start; + Elf32_Addr pcrel_addr; +#if defined __OPTIMIZE__ && !defined __thumb__ + __asm__ ("adr %0, _dl_start" : "=r" (pcrel_addr)); +#else + /* A simple adr does not work in Thumb mode because the offset is + negative, and for debug builds may be too large. */ + int tmp; + __asm__ ("adr %1, 1f\n\t" + "ldr %0, [%1]\n\t" + "add %0, %0, %1\n\t" + "b 2f\n\t" + ".align 2\n\t" + "1: .word _dl_start - 1b\n\t" + "2:" + : "=r" (pcrel_addr), "=r" (tmp)); +#endif + return pcrel_addr - got_addr; +} + +static __always_inline void +elf_machine_relative (Elf32_Addr load_off, const Elf32_Addr rel_addr, + Elf32_Word relative_count) +{ + Elf32_Rel * rpnt = (void *) rel_addr; + --rpnt; + do { + Elf32_Addr *const reloc_addr = (void *) (load_off + (++rpnt)->r_offset); + + *reloc_addr += load_off; + } while (--relative_count); +} +#endif /* !_ARCH_DL_SYSDEP */ + +#ifdef __ARM_EABI__ +#define DL_MALLOC_ALIGN 8 /* EABI needs 8 byte alignment for STRD LDRD */ +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/arm/elfinterp.c b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/arm/elfinterp.c new file mode 100644 index 00000000..707b3174 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/arm/elfinterp.c @@ -0,0 +1,354 @@ +/* vi: set sw=4 ts=4: */ +/* ARM ELF shared library loader suppport + * + * Copyright (C) 2001-2004 Erik Andersen + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. The name of the above contributors may not be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* Program to load an ELF binary on a linux system, and run it. + References to symbols in sharable libraries can be resolved by either + an ELF sharable library or a linux style of shared library. */ + +/* Disclaimer: I have never seen any AT&T source code for SVr4, nor have + I ever taken any courses on internals. This program was developed using + information available through the book "UNIX SYSTEM V RELEASE 4, + Programmers guide: Ansi C and Programming Support Tools", which did + a more than adequate job of explaining everything required to get this + working. */ + +#include "ldso.h" + +extern int _dl_linux_resolve(void); + +unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry) +{ + ELF_RELOC *this_reloc; + char *strtab; + char *symname; + Elf32_Sym *symtab; + ELF_RELOC *rel_addr; + int symtab_index; + unsigned long new_addr; + char **got_addr; + unsigned long instr_addr; + + rel_addr = (ELF_RELOC *) tpnt->dynamic_info[DT_JMPREL]; + + this_reloc = rel_addr + reloc_entry; + symtab_index = ELF32_R_SYM(this_reloc->r_info); + + symtab = (Elf32_Sym *) tpnt->dynamic_info[DT_SYMTAB]; + strtab = (char *) tpnt->dynamic_info[DT_STRTAB]; + symname = strtab + symtab[symtab_index].st_name; + + /* Address of jump instruction to fix up */ + instr_addr = ((unsigned long) this_reloc->r_offset + + (unsigned long) tpnt->loadaddr); + got_addr = (char **) instr_addr; + + /* Get the address of the GOT entry */ + new_addr = _dl_find_hash(symname, tpnt->symbol_scope, + tpnt, ELF_RTYPE_CLASS_PLT, NULL); + if (unlikely(!new_addr)) { + _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", + _dl_progname, symname); + _dl_exit(1); + } +#if defined (__SUPPORT_LD_DEBUG__) +#if !defined __SUPPORT_LD_DEBUG_EARLY__ + if ((unsigned long) got_addr < 0x40000000) +#endif + { + if (_dl_debug_bindings) + { + _dl_dprintf(_dl_debug_file, "\nresolve function: %s", symname); + if (_dl_debug_detail) _dl_dprintf(_dl_debug_file, + "\tpatch %x ==> %x @ %x", *got_addr, new_addr, got_addr); + } + } + if (!_dl_debug_nofixups) { + *got_addr = (char *)new_addr; + } +#else + *got_addr = (char *)new_addr; +#endif + + return new_addr; +} + +static int +_dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope, + unsigned long rel_addr, unsigned long rel_size, + int (*reloc_fnc) (struct elf_resolve *tpnt, struct dyn_elf *scope, + ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)) +{ + int i; + char *strtab; + int goof = 0; + Elf32_Sym *symtab; + ELF_RELOC *rpnt; + int symtab_index; + + /* Now parse the relocation information */ + rpnt = (ELF_RELOC *) rel_addr; + rel_size = rel_size / sizeof(ELF_RELOC); + + symtab = (Elf32_Sym *) tpnt->dynamic_info[DT_SYMTAB]; + strtab = (char *) tpnt->dynamic_info[DT_STRTAB]; + + for (i = 0; i < rel_size; i++, rpnt++) { + int res; + + symtab_index = ELF32_R_SYM(rpnt->r_info); + + debug_sym(symtab,strtab,symtab_index); + debug_reloc(symtab,strtab,rpnt); + + res = reloc_fnc (tpnt, scope, rpnt, symtab, strtab); + + if (res==0) continue; + + _dl_dprintf(2, "\n%s: ",_dl_progname); + + if (symtab_index) + _dl_dprintf(2, "symbol '%s': ", strtab + symtab[symtab_index].st_name); + + if (unlikely(res <0)) + { + int reloc_type = ELF32_R_TYPE(rpnt->r_info); +#if defined (__SUPPORT_LD_DEBUG__) + _dl_dprintf(2, "can't handle reloc type %s\n ", _dl_reltypes(reloc_type)); +#else + _dl_dprintf(2, "can't handle reloc type %x\n", reloc_type); +#endif + _dl_exit(-res); + } + if (unlikely(res >0)) + { + _dl_dprintf(2, "can't resolve symbol\n"); + goof += res; + } + } + return goof; +} + +#if 0 +static unsigned long +fix_bad_pc24 (unsigned long *const reloc_addr, unsigned long value) +{ + static void *fix_page; + static unsigned int fix_offset; + unsigned int *fix_address; + if (! fix_page) + { + fix_page = _dl_mmap (NULL, PAGE_SIZE , PROT_READ | PROT_WRITE | PROT_EXEC, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + fix_offset = 0; + } + + fix_address = (unsigned int *)(fix_page + fix_offset); + fix_address[0] = 0xe51ff004; /* ldr pc, [pc, #-4] */ + fix_address[1] = value; + + fix_offset += 8; + if (fix_offset >= PAGE_SIZE) + fix_page = NULL; + + return (unsigned long)fix_address; +} +#endif + +static int +_dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope, + ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab) +{ + int reloc_type; + int symtab_index; + unsigned long *reloc_addr; + unsigned long symbol_addr; + const Elf32_Sym *def = 0; + struct symbol_ref sym_ref; + struct elf_resolve *def_mod = 0; + int goof = 0; + + reloc_addr = (unsigned long *) (tpnt->loadaddr + (unsigned long) rpnt->r_offset); + + reloc_type = ELF32_R_TYPE(rpnt->r_info); + symtab_index = ELF32_R_SYM(rpnt->r_info); + symbol_addr = 0; + sym_ref.sym = &symtab[symtab_index]; + sym_ref.tpnt = NULL; + + if (symtab_index) { + symbol_addr = _dl_find_hash(strtab + symtab[symtab_index].st_name, + scope, tpnt, elf_machine_type_class(reloc_type), &sym_ref); + + /* + * We want to allow undefined references to weak symbols - this might + * have been intentional. We should not be linking local symbols + * here, so all bases should be covered. + */ + if (!symbol_addr && (ELF_ST_TYPE(symtab[symtab_index].st_info) != STT_TLS) + && (ELF32_ST_BIND(symtab[symtab_index].st_info) != STB_WEAK)) { + /* This may be non-fatal if called from dlopen. */ + return 1; + + } + def_mod = sym_ref.tpnt; + } else { + /* + * Relocs against STN_UNDEF are usually treated as using a + * symbol value of zero, and using the module containing the + * reloc itself. + */ + symbol_addr = symtab[symtab_index].st_value; + def_mod = tpnt; + } + +#if defined (__SUPPORT_LD_DEBUG__) + { + unsigned long old_val = *reloc_addr; +#endif + switch (reloc_type) { + case R_ARM_NONE: + break; + case R_ARM_ABS32: + *reloc_addr += symbol_addr; + break; + case R_ARM_PC24: +#if 0 + { + unsigned long addend; + long newvalue, topbits; + + addend = *reloc_addr & 0x00ffffff; + if (addend & 0x00800000) addend |= 0xff000000; + + newvalue = symbol_addr - (unsigned long)reloc_addr + (addend << 2); + topbits = newvalue & 0xfe000000; + if (topbits != 0xfe000000 && topbits != 0x00000000) + { + newvalue = fix_bad_pc24(reloc_addr, symbol_addr) + - (unsigned long)reloc_addr + (addend << 2); + topbits = newvalue & 0xfe000000; + if (unlikely(topbits != 0xfe000000 && topbits != 0x00000000)) + { + _dl_dprintf(2,"symbol '%s': R_ARM_PC24 relocation out of range.", + symtab[symtab_index].st_name); + _dl_exit(1); + } + } + newvalue >>= 2; + symbol_addr = (*reloc_addr & 0xff000000) | (newvalue & 0x00ffffff); + *reloc_addr = symbol_addr; + break; + } +#else + _dl_dprintf(2,"R_ARM_PC24: Compile shared libraries with -fPIC!\n"); + _dl_exit(1); +#endif + case R_ARM_GLOB_DAT: + case R_ARM_JUMP_SLOT: + *reloc_addr = symbol_addr; + break; + case R_ARM_RELATIVE: + *reloc_addr += (unsigned long) tpnt->loadaddr; + break; + case R_ARM_COPY: + _dl_memcpy((void *) reloc_addr, + (void *) symbol_addr, symtab[symtab_index].st_size); + break; +#if defined USE_TLS && USE_TLS + case R_ARM_TLS_DTPMOD32: + *reloc_addr = def_mod->l_tls_modid; + break; + + case R_ARM_TLS_DTPOFF32: + *reloc_addr += symbol_addr; + break; + + case R_ARM_TLS_TPOFF32: + CHECK_STATIC_TLS ((struct link_map *) def_mod); + *reloc_addr += (symbol_addr + def_mod->l_tls_offset); + break; +#endif + default: + return -1; /*call _dl_exit(1) */ + } +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_reloc && _dl_debug_detail) + _dl_dprintf(_dl_debug_file, "\tpatch: %x ==> %x @ %x", old_val, *reloc_addr, reloc_addr); + } + +#endif + + return goof; +} + +static int +_dl_do_lazy_reloc (struct elf_resolve *tpnt, struct dyn_elf *scope, + ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab) +{ + int reloc_type; + unsigned long *reloc_addr; + + reloc_addr = (unsigned long *) (tpnt->loadaddr + (unsigned long) rpnt->r_offset); + reloc_type = ELF32_R_TYPE(rpnt->r_info); + +#if defined (__SUPPORT_LD_DEBUG__) + { + unsigned long old_val = *reloc_addr; +#endif + switch (reloc_type) { + case R_ARM_NONE: + break; + case R_ARM_JUMP_SLOT: + *reloc_addr += (unsigned long) tpnt->loadaddr; + break; + default: + return -1; /*call _dl_exit(1) */ + } +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_reloc && _dl_debug_detail) + _dl_dprintf(_dl_debug_file, "\tpatch: %x ==> %x @ %x", old_val, *reloc_addr, reloc_addr); + } + +#endif + return 0; + +} + +void _dl_parse_lazy_relocation_information(struct dyn_elf *rpnt, + unsigned long rel_addr, unsigned long rel_size) +{ + (void)_dl_parse(rpnt->dyn, NULL, rel_addr, rel_size, _dl_do_lazy_reloc); +} + +int _dl_parse_relocation_information(struct dyn_elf *rpnt, + unsigned long rel_addr, unsigned long rel_size) +{ + return _dl_parse(rpnt->dyn, rpnt->dyn->symbol_scope, rel_addr, rel_size, _dl_do_reloc); +} + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/arm/resolve.S b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/arm/resolve.S new file mode 100644 index 00000000..08889d06 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/arm/resolve.S @@ -0,0 +1,173 @@ +/* + * + * add ip, pc, #0xNN00000 + * add ip, ip, #0xNN000 + * ldr pc, [ip, #0xNNN]! + * + * So that, effectively, causes the following to happen: + * + * ip : = pc+0x0NNNNNNN + * pc : = *ip + * + * For thumb the above fragment is preceded by "bx pc, nop" to switch to ARM + * mode and the thumb 'bl' must go to PLT-4 - the PLT entry is expanded by + * four bytes to accomodate the trampoline code. + * + * 0x0NNNNNNN is the offset of the GOT entry for this function relative to + * the PLT entry for this function (where the code is). So the code in the + * PLT causes a branch to whatever is in the GOT, leaving the actual address + * of the GOT entry in ip. (Note that the GOT must follow the PLT - the + * added value is 28 bit unsigned). + * + * ip is a pointer to the GOT entry for this function, the first time round + * *ip points to this code: + * + * str lr, [sp, #-4]! @ save lr + * ldr lr, [pc, #4] @ lr : = *dat (&GOT_TABLE[0]-.) + * add lr, pc, lr @ lr += &dat (so lr == &GOT_TABLE[0]) + * ldr pc, [lr, #8]! @ pc : = GOT_TABLE[2] + *dat: *.long &GOT_TABLE[0] - . + * + * (this code is actually held in the first entry of the PLT). The code + * preserves lr then uses it as a scratch register (this preserves the ip + * value calculated above). GOT_TABLE[2] is initialized by INIT_GOT in + * dl-sysdep.h to point to _dl_linux_resolve - this function. The first + * three entries in the GOT are reserved, then they are followed by the + * entries for the PLT entries, in order. + * + * The linker initialises the following (non-reserved) GOT entries to + * the offset of the PLT with an associated relocation so that on load + * the entry is relocated to point to the PLT - the above code. + * + * The net effect of all this is that on the first call to an external (as + * yet unresolved) function all seven of the above instructions are + * executed in sequence and the program ends up executing _dl_linux_resolve + * with the following important values in registers: + * + * ip - a pointer to the GOT entry for the as yet unresolved function + * lr - &GOT_TABLE[2] + * + * GOT_TABLE[2] has already been initialised to _dl_linux_resolve, and + * GOT_TABLE[1] is a pointer to the (elf_resolve*) from INIT_GOT. + * _dl_linux_resolve unfrobnicates the ip and lr values to obtain arguments + * for a call to _dl_linux_resolver (not the additional 'r' on the end) - + * this is in elfinterp.c in this directory. The call takes arguments: + * + * _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry) + * + * And returns the address of the function, it also overwrites the GOT + * table entry so that the next time round only the first code fragment will + * be executed - it will call the function directly. + * + * [[Of course, this simply doesn't work on ARM 4T with a thumb target - because + * 4T did not do the thumb/arm change on ldr pc! It can be made to work by + * changing _dl_linux_resolver to return __%s_from_arm for an STT_TFUNC, but + * this hasn't been done, and there is no guarantee that the linker generated + * that glue anyway.]] + * + * _dl_linux_resolve gets the arguments to call the resolver as follows: + * + * tpnt *GOT_TABLE[1], [lr-4] + * reloc-entry &GOT-&GOT_TABLE[3], (ip - lr - 4)/4 + * + * (I.e. 'GOT' means the table entry for this function, the thing for which + * ip holds the address.) The reloc-entry is passed as an index, since + * since the GOT table has 4 byte entries the code needs to divide this by 4 + * to get the actual index. + * + * John Bowler, August 13, 2005 - determined by experiment and examination + * of generated ARM code (there was no documentation...) + * + * This code is all ARM code - not thumb - _dl_linux_resolver may, itself, + * be thumb, in which case the linker will insert the appropriate glue. A + * call from thumb to the PLT hits the trampoline code described above. + * This code (now) builds a proper stack frame. + * + * The code does *not* set sb (r9,v6) - to do that the basic PLT instructions + * would need to save sb and load the new value and that would require + * support in the linker since it generates those instructions. (Also note + * that linux/uclibc seems to be using r10 - sl - as a PIC base register - see + * dl-startup.c). + */ + +#include +#include + +#include + +#define sl r10 +#define fp r11 +#define ip r12 + + .text + .align 4 @ 16 byte boundary and there are 32 bytes below (arm case) + #if !defined(__thumb__) || defined(__thumb2__) + .arm + .globl _dl_linux_resolve + .type _dl_linux_resolve,%function + .align 4; + +_dl_linux_resolve: + @ _dl_linux_resolver is a standard subroutine call, therefore it + @ preserves everything except r0-r3 (a1-a4), ip and lr. This + @ function must branch to the real function, and that expects + @ r0-r3 and lr to be as they were before the whole PLT stuff - + @ ip can be trashed. + @ This routine is called after pushing lr, so we must push an odd + @ number of words to keep the stack correctly aligned. + + stmdb sp!, {r0, r1, r2, r3, r4} + ldr r0, [lr, #-4] @ r0 : = [lr-4] (GOT_TABLE[1]) + sub r1, lr, ip @ r1 : = (lr-ip) (a multple of 4) + mvn r1, r1, ASR #2 @ r1 : = ~((lr-ip)>>2), since -x = (1+~x) + @ ~x = -x-1, therefore ~(r1>>2) = (-((lr-ip)>>2)-1) + @ = - ((lr-ip)/4) - 1 = (ip - lr - 4)/4, as required + + bl _dl_linux_resolver + + mov ip, r0 + ldmia sp!, {r0, r1, r2, r3, r4, lr} + +#if defined(__USE_BX__) + bx ip +#else + mov pc,ip +#endif +#else + @ In the thumb case _dl_linux_resolver is thumb. If a bl is used + @ from arm code the linker will insert a stub call which, with + @ binutils 2.16, is not PIC. Since this code is accessed by an + @ ldr pc the reasonable fix is to make _dl_linux_resolve thumb too. + .thumb + .globl _dl_linux_resolve + .thumb_func + .type _dl_linux_resolve,%function + _dl_linux_resolve: + @ _dl_linux_resolver is a standard subroutine call, therefore it + @ preserves everything except r0-r3 (a1-a4), ip and lr. This + @ function must branch to the real function, and that expects + @ r0-r3 and lr to be as they were before the whole PLT stuff - + @ ip can be trashed. + @ This routine is called after pushing lr, so we must push an odd + @ number of words to keep the stack correctly aligned. + push {r0-r4} + mov r1, lr @ &GOT_TABLE[2] + sub r0, r1, #4 + mov r2, ip @ &GOT[n] + ldr r0, [r0] @ r0 := GOT_TABLE[1] + @ for the function call r1 := n-3 + sub r1, r2 + asr r1, r1, #2 + mvn r1, r1 @ exactly as in the arm code above + bl _dl_linux_resolver + @ r0 contains the branch address, the return address is above + @ the saved r0..r3 + mov ip, r0 + ldr r1, [sp, #20] + mov lr, r1 + pop {r0-r4} + add sp, #4 + bx ip + +#endif +.size _dl_linux_resolve, .-_dl_linux_resolve diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/arm/thumb_atomics.S b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/arm/thumb_atomics.S new file mode 100644 index 00000000..f6ae3db3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/arm/thumb_atomics.S @@ -0,0 +1,79 @@ +/* Copyright (C) 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file with other + programs, and to distribute those programs without any restriction + coming from the use of this file. (The GNU Lesser General Public + License restrictions do apply in other respects; for example, they + cover modification of the file, and distribution when not linked + into another program.) + + Note that people who make modified versions of this file are not + obligated to grant this special exception for their modified + versions; it is their choice whether to do so. The GNU Lesser + General Public License gives permission to release a modified + version without this exception; this exception also makes it + possible to release a modified version which carries forward this + exception. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#ifdef __UCLIBC_HAS_THREADS_NATIVE__ + +#include + +#if defined __thumb__ + +/* Out-of-line atomic operations that we can't do in Thumb mode. + This ends up in various libraries where it is needed (and + a few .a archives where it isn't). */ + + .hidden __thumb_swpb +ENTRY (__thumb_swpb) + swpb r0, r0, [r1] + bx lr +END (__thumb_swpb) + + .hidden __thumb_swp +ENTRY (__thumb_swp) + swp r0, r0, [r1] + bx lr +END (__thumb_swp) + + .hidden __thumb_cmpxchg +ENTRY (__thumb_cmpxchg) + stmdb sp!, {r4, lr} + mov r4, r0 +0: ldr r3, [r2] + cmp r3, r4 + bne 1f + mov r0, r4 + mov r3, #0xffff0fff + mov lr, pc + add pc, r3, #(0xffff0fc0 - 0xffff0fff) + bcc 0b + mov r3, r4 +1: mov r0, r3 + ldmia sp!, {r4, pc} +END (__thumb_cmpxchg) + +#endif /* __thumb__ */ +#endif /* __UCLIBC_HAS_THREADS_NATIVE__ */ + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/avr32/dl-debug.h b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/avr32/dl-debug.h new file mode 100644 index 00000000..fe35539f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/avr32/dl-debug.h @@ -0,0 +1,45 @@ +/* + * AVR32 ELF shared libary loader support + * + * Copyright (C) 2005-2007 Atmel Corporation + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. The name of the above contributors may not be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +static const char *_dl_reltypes_tab[] = { + "R_AVR32_NONE", + "R_AVR32_32", "R_AVR32_16", "R_AVR32_8", + "R_AVR32_32_PCREL", "R_AVR32_16_PCREL", "R_AVR32_8_PCREL", + "R_AVR32_DIFF32", "R_AVR32_DIFF16", "R_AVR32_DIFF8", + "R_AVR32_GOT32", "R_AVR32_GOT16", "R_AVR32_GOT8", + "R_AVR32_21S", "R_AVR32_16U", "R_AVR32_16S", "R_AVR32_8S", "R_AVR32_8S_EXT", + "R_AVR32_22H_PCREL", "R_AVR32_18W_PCREL", "R_AVR32_16B_PCREL", + "R_AVR32_16N_PCREL", "R_AVR32_14UW_PCREL", "R_AVR32_11H_PCREL", + "R_AVR32_10UW_PCREL", "R_AVR32_9H_PCREL", "R_AVR32_9UW_PCREL", + "R_AVR32_HI16", "R_AVR32_LO16", + "R_AVR32_GOTPC", "R_AVR32_GOTCALL", "R_AVR32_LDA_GOT", + "R_AVR32_GOT21S", "R_AVR32_GOT18SW", "R_AVR32_GOT16S", "R_AVR32_GOT7UW", + "R_AVR32_32_CPENT", "R_AVR32_CPCALL", "R_AVR32_16_CP", "R_AVR32_9W_CP", + "R_AVR32_RELATIVE", "R_AVR32_GLOB_DAT", "R_AVR32_JMP_SLOT", + "R_AVR32_ALIGN", +}; diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/avr32/dl-startup.h b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/avr32/dl-startup.h new file mode 100644 index 00000000..066f65fc --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/avr32/dl-startup.h @@ -0,0 +1,103 @@ +/* + * Architecture specific code used by dl-startup.c + * + * Copyright (C) 2005-2007 Atmel Corporation + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* This is the library loader's main entry point. Let _dl_boot2 do its + * initializations and jump to the application's entry point + * afterwards. */ +__asm__(" .text\n" + " .global _start\n" + " .type _start,@function\n" + "_start:\n" + /* All arguments are on the stack initially */ + " mov r12, sp\n" + " rcall _dl_start\n" + /* Returns user entry point in r12. Save it. */ + " mov r0, r12\n" + /* We're PIC, so get the Global Offset Table */ + " lddpc r6, .L_GOT\n" + ".L_RGOT:\n" + " rsub r6, pc\n" + /* Adjust argc and argv according to _dl_skip_args */ + " ld.w r1, r6[_dl_skip_args@got]\n" + " ld.w r1, r1[0]\n" + " ld.w r2, sp++\n" + " sub r2, r1\n" + " add sp, sp, r1 << 2\n" + " st.w --sp, r2\n" + /* Load the finalizer function */ + " ld.w r12, r6[_dl_fini@got]\n" + /* Jump to the user's entry point */ + " mov pc, r0\n\n" + + " .align 2\n" + ".L_GOT:" + " .long .L_RGOT - _GLOBAL_OFFSET_TABLE_\n" + " .size _start, . - _start\n" + " .previous\n"); + +/* Get a pointer to the argv array. On many platforms this can be just + * the address of the first argument, on other platforms we need to + * do something a little more subtle here. */ +#define GET_ARGV(ARGVP, ARGS) ARGVP = ((unsigned long *)ARGS + 1) + + +/* We can't call functions before the GOT has been initialized */ +#define NO_FUNCS_BEFORE_BOOTSTRAP + +/* + * Relocate the GOT during dynamic loader bootstrap. This will add + * the load address to all entries in the GOT, which is necessary + * because the linker doesn't generate R_AVR32_RELATIVE relocs for the + * GOT. + */ +static __always_inline +void PERFORM_BOOTSTRAP_GOT(struct elf_resolve *tpnt) +{ + Elf32_Addr i, nr_got; + register Elf32_Addr *__r6 __asm__("r6"); + Elf32_Addr *got = __r6; + + nr_got = tpnt->dynamic_info[DT_AVR32_GOTSZ_IDX] / sizeof(*got); + for (i = 2; i < nr_got; i++) + got[i] += tpnt->loadaddr; +} + +#define PERFORM_BOOTSTRAP_GOT(tpnt) PERFORM_BOOTSTRAP_GOT(tpnt) + +/* Handle relocation of the symbols in the dynamic loader. */ +static __always_inline +void PERFORM_BOOTSTRAP_RELOC(ELF_RELOC *rpnt, unsigned long *reloc_addr, + unsigned long symbol_addr, + unsigned long load_addr, Elf32_Sym *symtab) +{ + switch(ELF32_R_TYPE(rpnt->r_info)) { + case R_AVR32_NONE: + break; + case R_AVR32_GLOB_DAT: + case R_AVR32_JMP_SLOT: + *reloc_addr = symbol_addr; + break; + case R_AVR32_RELATIVE: + SEND_STDERR_DEBUG("Applying RELATIVE relocation: "); + SEND_ADDRESS_STDERR_DEBUG(load_addr, 0); + SEND_STDERR_DEBUG(" + "); + SEND_ADDRESS_STDERR_DEBUG(rpnt->r_addend, 1); + *reloc_addr = load_addr + rpnt->r_addend; + break; + default: + SEND_STDERR("BOOTSTRAP_RELOC: unhandled reloc_type "); + SEND_NUMBER_STDERR(ELF32_R_TYPE(rpnt->r_info), 1); + SEND_STDERR("REL, SYMBOL, LOAD: "); + SEND_ADDRESS_STDERR(reloc_addr, 0); + SEND_STDERR(", "); + SEND_ADDRESS_STDERR(symbol_addr, 0); + SEND_STDERR(", "); + SEND_ADDRESS_STDERR(load_addr, 1); + _dl_exit(1); + } +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/avr32/dl-syscalls.h b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/avr32/dl-syscalls.h new file mode 100644 index 00000000..996bb87c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/avr32/dl-syscalls.h @@ -0,0 +1,6 @@ +/* We can't use the real errno in ldso, since it has not yet + * been dynamicly linked in yet. */ +#include "sys/syscall.h" +extern int _dl_errno; +#undef __set_errno +#define __set_errno(X) {(_dl_errno) = (X);} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/avr32/dl-sysdep.h b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/avr32/dl-sysdep.h new file mode 100644 index 00000000..618769b6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/avr32/dl-sysdep.h @@ -0,0 +1,103 @@ +/* + * Various assembly language/system dependent hacks that are required + * so that we can minimize the amount of platform specific code. + * + * Copyright (C) 2004-2007 Atmel Corporation + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* Define this if the system uses RELOCA. */ +#define ELF_USES_RELOCA + +#include + +#define ARCH_NUM 1 +#define DT_AVR32_GOTSZ_IDX (DT_NUM + OS_NUM) + +#define ARCH_DYNAMIC_INFO(dpnt, dynamic, debug_addr) \ + do { \ + if (dpnt->d_tag == DT_AVR32_GOTSZ) \ + dynamic[DT_AVR32_GOTSZ_IDX] = dpnt->d_un.d_val; \ + } while (0) + +/* Initialization sequence for the application/library GOT. */ +#define INIT_GOT(GOT_BASE,MODULE) \ + do { \ + unsigned long _i, _nr_got; \ + \ + GOT_BASE[0] = (unsigned long) _dl_linux_resolve; \ + GOT_BASE[1] = (unsigned long) MODULE; \ + \ + /* Add load address displacement to all GOT entries */ \ + _nr_got = MODULE->dynamic_info[DT_AVR32_GOTSZ_IDX] / 4; \ + for (_i = 2; _i < _nr_got; _i++) \ + GOT_BASE[_i] += (unsigned long)MODULE->loadaddr; \ + } while (0) + +#define do_rem(result, n, base) ((result) = (n) % (base)) + +/* Here we define the magic numbers that this dynamic loader should accept */ +#define MAGIC1 EM_AVR32 +#undef MAGIC2 + +/* Used for error messages */ +#define ELF_TARGET "AVR32" + +/* Need bootstrap relocations */ +#define ARCH_NEEDS_BOOTSTRAP_RELOCS + +unsigned long _dl_linux_resolver(unsigned long got_offset, unsigned long *got); + +#define elf_machine_type_class(type) \ + ((type == R_AVR32_JMP_SLOT) * ELF_RTYPE_CLASS_PLT) + +/* AVR32 doesn't need any COPY relocs */ +#define DL_NO_COPY_RELOCS + +/* Return the link-time address of _DYNAMIC. Conveniently, this is the + first element of the GOT. This must be inlined in a function which + uses global data. */ +static __always_inline Elf32_Addr +elf_machine_dynamic (void) +{ + register Elf32_Addr *got __asm__("r6"); + return *got; +} + +/* Return the run-time load address of the shared object. */ +static __always_inline Elf32_Addr +elf_machine_load_address (void) +{ + extern void __dl_start __asm__("_dl_start"); + Elf32_Addr got_addr = (Elf32_Addr) &__dl_start; + Elf32_Addr pcrel_addr; + + __asm__(" lddpc %0, 2f\n" + "1: add %0, pc\n" + " rjmp 3f\n" + " .align 2\n" + "2: .long _dl_start - 1b\n" + "3:\n" + : "=r"(pcrel_addr) : : "cc"); + + return pcrel_addr - got_addr; +} + +/* + * Perform any RELATIVE relocations specified by DT_RELCOUNT. + * Currently, we don't use that tag, but we might in the future as + * this would reduce the startup time somewhat (although probably not by much). + */ +static __always_inline void +elf_machine_relative (Elf32_Addr load_off, const Elf32_Addr rel_addr, + Elf32_Word relative_count) +{ + Elf32_Rela *rpnt = (void *)rel_addr; + + do { + Elf32_Addr *reloc_addr; + reloc_addr = (void *)(load_off + (rpnt++)->r_offset); + *reloc_addr = load_off + rpnt->r_addend; + } while (--relative_count); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/avr32/elfinterp.c b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/avr32/elfinterp.c new file mode 100644 index 00000000..2d0dbf36 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/avr32/elfinterp.c @@ -0,0 +1,194 @@ +/* + * AVR32 ELF shared library loader suppport + * + * Copyright (C) 2004-2006 Atmel Corporation + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. The name of the above contributors may not be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +unsigned long _dl_linux_resolver(unsigned long got_offset, unsigned long *got) +{ + /* + * AVR32 currently does not do lazy relocation. + */ +#if 0 + struct elf_resolve *tpnt = (struct elf_resolve *)got[1]; + Elf32_Sym *sym; + unsigned long local_gotno; + unsigned long gotsym; + unsigned long new_addr; + char *strtab, *symname; + unsigned long *entry; + unsigned long sym_index = got_offset / 4; + + local_gotno = tpnt->dynamic_info[DT_AVR32_LOCAL_GOTNO]; + gotsym = tpnt->dynamic_info[DT_AVR32_GOTSYM]; + + sym = ((Elf32_Sym *)(tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr)) + + sym_index; + strtab = (char *)(tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr); + symname = strtab + sym->st_name; + + new_addr = (unsigned long) _dl_find_hash(symname, + tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL); + + entry = (unsigned long *)(got + local_gotno + sym_index - gotsym); + *entry = new_addr; + + return new_addr; +#endif + return 0; +} + +static int +_dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope, + unsigned long rel_addr, unsigned long rel_size, + int (*reloc_func)(struct elf_resolve *tpnt, struct dyn_elf *scope, + Elf32_Rela *rpnt, Elf32_Sym *symtab, char *strtab)) +{ + Elf32_Sym *symtab; + Elf32_Rela *rpnt; + char *strtab; + int i; + + rpnt = (Elf32_Rela *)rel_addr; + rel_size /= sizeof(Elf32_Rela); + symtab = (Elf32_Sym *)tpnt->dynamic_info[DT_SYMTAB]; + strtab = (char *)tpnt->dynamic_info[DT_STRTAB]; + + for (i = 0; i < rel_size; i++, rpnt++) { + int symtab_index, res; + + symtab_index = ELF32_R_SYM(rpnt->r_info); + + debug_sym(symtab, strtab, symtab_index); + debug_reloc(symtab, strtab, rpnt); + + res = reloc_func(tpnt, scope, rpnt, symtab, strtab); + + if (res == 0) + continue; + + _dl_dprintf(2, "\n%s: ", _dl_progname); + + if (symtab_index) + _dl_dprintf(2, "symbol '%s': ", + strtab + symtab[symtab_index].st_name); + + if (res < 0) { + int reloc_type = ELF32_R_TYPE(rpnt->r_info); +#if defined(__SUPPORT_LD_DEBUG__) + _dl_dprintf(2, "can't handle reloc type %s\n", + _dl_reltypes(reloc_type)); +#else + _dl_dprintf(2, "can't handle reloc type %x\n", + reloc_type); +#endif + _dl_exit(-res); + } else { + _dl_dprintf(2, "can't resolve symbol\n"); + return res; + } + } + + return 0; +} + +static int _dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, + Elf32_Rela *rpnt, Elf32_Sym *symtab, char *strtab) +{ + int reloc_type; + int symtab_index; + char *symname; + unsigned long *reloc_addr; + unsigned long symbol_addr; +#if defined(__SUPPORT_LD_DEBUG__) + unsigned long old_val; +#endif + struct symbol_ref sym_ref; + + reloc_addr = (unsigned long *)(tpnt->loadaddr + rpnt->r_offset); + reloc_type = ELF32_R_TYPE(rpnt->r_info); + symtab_index = ELF32_R_SYM(rpnt->r_info); + symbol_addr = 0; + sym_ref.sym = &symtab[symtab_index]; + sym_ref.tpnt = NULL; + symname = strtab + symtab[symtab_index].st_name; + + if (symtab_index) { + symbol_addr = (unsigned long) + _dl_find_hash(symname, scope, tpnt, + elf_machine_type_class(reloc_type), &sym_ref); + + /* Allow undefined references to weak symbols */ + if (!symbol_addr && + ELF32_ST_BIND(symtab[symtab_index].st_info) != STB_WEAK) { + _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", + _dl_progname, symname); + return 0; + } + } + +#if defined(__SUPPORT_LD_DEBUG__) + old_val = *reloc_addr; +#endif + switch (reloc_type) { + case R_AVR32_NONE: + break; + case R_AVR32_GLOB_DAT: + case R_AVR32_JMP_SLOT: + *reloc_addr = symbol_addr + rpnt->r_addend; + break; + case R_AVR32_RELATIVE: + *reloc_addr = (unsigned long)tpnt->loadaddr + + rpnt->r_addend; + break; + default: + return -1; + } + +#if defined(__SUPPORT_LD_DEBUG__) + if (_dl_debug_reloc && _dl_debug_detail) + _dl_dprintf(_dl_debug_file, "\tpatched: %x ==> %x @ %x\n", + old_val, *reloc_addr); +#endif + + return 0; +} + +void _dl_parse_lazy_relocation_information(struct dyn_elf *rpnt, + unsigned long rel_addr, + unsigned long rel_size) +{ + /* TODO: Might want to support this in order to get faster + * startup times... */ +} + +int _dl_parse_relocation_information(struct dyn_elf *rpnt, + unsigned long rel_addr, + unsigned long rel_size) +{ + return _dl_parse(rpnt->dyn, rpnt->dyn->symbol_scope, rel_addr, rel_size, + _dl_do_reloc); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/avr32/resolve.S b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/avr32/resolve.S new file mode 100644 index 00000000..e3cb7f4d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/avr32/resolve.S @@ -0,0 +1,28 @@ +/* + * Linux dynamic resolving code for AVR32. Fixes up the GOT entry as + * indicated in register r12 and jumps to the resolved address. + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License. See the file "COPYING.LIB" in the main directory of this + * archive for more details. + * + * Copyright (C) 2004-2007 Atmel Corporation + */ + +#define ip r5 + + .text + .global _dl_linux_resolve + .type _dl_linux_resolve,@function +_dl_linux_resolve: + /* The PLT code pushed r8 for us. It contains the address of this + function's GOT entry, that is entry 0. ip contains the address + of the GOT entry of the function we wanted to call. */ + stm --sp, r9-r12, lr + mov r11, r8 + sub r12, ip, r8 + rcall _dl_linux_resolver + mov ip, r12 + popm r8-r12,lr + mov pc, ip + .size _dl_linux_resolve, . - _dl_linux_resolve diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/bfin/dl-debug.h b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/bfin/dl-debug.h new file mode 100644 index 00000000..3ba0a983 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/bfin/dl-debug.h @@ -0,0 +1,54 @@ +/* vi: set sw=4 ts=4: */ +/* Blackfin ELF shared library loader suppport + * + * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald, + * David Engel, Hongjiu Lu and Mitch D'Souza + * Copyright (C) 2001-2004 Erik Andersen + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. The name of the above contributors may not be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +static const char *_dl_reltypes_tab[] = +{ + [0] "R_BFIN_UNUSED0", "R_BFIN_PCREL5M2", + [2] "R_BFIN_UNUSED1", "R_BFIN_PCREL10", + [4] "R_BFIN_PCREL12_JUMP", "R_BFIN_RIMM16", + [6] "R_BFIN_LUIMM16", "R_BFIN_HUIMM16", + [8] "R_BFIN_PCREL12_JUMP_S","R_BFIN_PCREL24_JUMP_X", + [10] "R_BFIN_PCREL24", "R_BFIN_UNUSEDB", + [12] "R_BFIN_UNUSEDC", "R_BFIN_PCREL24_JUMP_L", + [14] "R_BFIN_PCREL24_CALL_X","R_BFIN_var_eq_symb", + [16] "R_BFIN_BYTE_DATA", "R_BFIN_BYTE2_DATA", "R_BFIN_BYTE4_DATA", + [19] "R_BFIN_PCREL11", + + [20] "R_BFIN_GOT17M4", "R_BFIN_GOTHI", "R_BFIN_GOTLO", + [23] "R_BFIN_FUNCDESC", + [24] "R_BFIN_FUNCDESC_GOT17M4", "R_BFIN_FUNCDESC_GOTHI", "R_BFIN_FUNCDESC_GOTLO", + [27] "R_BFIN_FUNCDESC_VALUE", "R_BFIN_FUNCDESC_GOTOFF17M4", + [29] "R_BFIN_FUNCDESC_GOTOFFHI", "R_BFIN_FUNCDESC_GOTOFFLO", + [31] "R_BFIN_GOTOFF17M4", "R_BFIN_GOTOFFHI", "R_BFIN_GOTOFFLO", +#if 0 + [200] "R_BFIN_GNU_VTINHERIT", "R_BFIN_GNU_VTENTRY" +#endif +}; diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/bfin/dl-inlines.h b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/bfin/dl-inlines.h new file mode 100644 index 00000000..6524f5ed --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/bfin/dl-inlines.h @@ -0,0 +1,593 @@ + /* Copyright (C) 2003, 2004 Red Hat, Inc. + Contributed by Alexandre Oliva + +This file is part of uClibc. + +uClibc is free software; you can redistribute it and/or modify it +under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation; either version 2.1 of the +License, or (at your option) any later version. + +uClibc is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with uClibc; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, +USA. */ + +#include + +#ifndef _dl_assert +# define _dl_assert(expr) +#endif + +/* Initialize a DL_LOADADDR_TYPE given a got pointer and a complete + load map. */ +static __always_inline void +__dl_init_loadaddr_map (struct elf32_fdpic_loadaddr *loadaddr, Elf32_Addr dl_boot_got_pointer, + struct elf32_fdpic_loadmap *map) +{ + if (map->version != 0) + { + SEND_EARLY_STDERR ("Invalid loadmap version number\n"); + _dl_exit(-1); + } + if (map->nsegs == 0) + { + SEND_EARLY_STDERR ("Invalid segment count in loadmap\n"); + _dl_exit(-1); + } + loadaddr->got_value = (void *)dl_boot_got_pointer; + loadaddr->map = map; +} + +/* Figure out how many LOAD segments there are in the given headers, + and allocate a block for the load map big enough for them. + got_value will be properly initialized later on, with INIT_GOT. */ +static __always_inline int +__dl_init_loadaddr (struct elf32_fdpic_loadaddr *loadaddr, Elf32_Phdr *ppnt, + int pcnt) +{ + int count = 0, i; + size_t size; + + for (i = 0; i < pcnt; i++) + if (ppnt[i].p_type == PT_LOAD) + count++; + + loadaddr->got_value = 0; + + size = sizeof (struct elf32_fdpic_loadmap) + + sizeof (struct elf32_fdpic_loadseg) * count; + loadaddr->map = _dl_malloc (size); + if (! loadaddr->map) + _dl_exit (-1); + + loadaddr->map->version = 0; + loadaddr->map->nsegs = 0; + + return count; +} + +/* Incrementally initialize a load map. */ +static __always_inline void +__dl_init_loadaddr_hdr (struct elf32_fdpic_loadaddr loadaddr, void *addr, + Elf32_Phdr *phdr, int maxsegs) +{ + struct elf32_fdpic_loadseg *segdata; + + if (loadaddr.map->nsegs == maxsegs) + _dl_exit (-1); + + segdata = &loadaddr.map->segs[loadaddr.map->nsegs++]; + segdata->addr = (Elf32_Addr) addr; + segdata->p_vaddr = phdr->p_vaddr; + segdata->p_memsz = phdr->p_memsz; + +#if defined (__SUPPORT_LD_DEBUG__) + { + extern char *_dl_debug; + extern int _dl_debug_file; + if (_dl_debug) + _dl_dprintf(_dl_debug_file, "%i: mapped %x at %x, size %x\n", + loadaddr.map->nsegs-1, + segdata->p_vaddr, segdata->addr, segdata->p_memsz); + } +#endif +} + +static __always_inline void __dl_loadaddr_unmap +(struct elf32_fdpic_loadaddr loadaddr, struct funcdesc_ht *funcdesc_ht); + +/* Figure out whether the given address is in one of the mapped + segments. */ +static __always_inline int +__dl_addr_in_loadaddr (void *p, struct elf32_fdpic_loadaddr loadaddr) +{ + struct elf32_fdpic_loadmap *map = loadaddr.map; + int c; + + for (c = 0; c < map->nsegs; c++) + if ((void*)map->segs[c].addr <= p + && (char*)p < (char*)map->segs[c].addr + map->segs[c].p_memsz) + return 1; + + return 0; +} + +static __always_inline void * _dl_funcdesc_for (void *entry_point, void *got_value); + +/* The hashcode handling code below is heavily inspired in libiberty's + hashtab code, but with most adaptation points and support for + deleting elements removed. + + Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. + Contributed by Vladimir Makarov (vmakarov@cygnus.com). */ + +static __always_inline unsigned long +higher_prime_number (unsigned long n) +{ + /* These are primes that are near, but slightly smaller than, a + power of two. */ + static const unsigned long primes[] = { + (unsigned long) 7, + (unsigned long) 13, + (unsigned long) 31, + (unsigned long) 61, + (unsigned long) 127, + (unsigned long) 251, + (unsigned long) 509, + (unsigned long) 1021, + (unsigned long) 2039, + (unsigned long) 4093, + (unsigned long) 8191, + (unsigned long) 16381, + (unsigned long) 32749, + (unsigned long) 65521, + (unsigned long) 131071, + (unsigned long) 262139, + (unsigned long) 524287, + (unsigned long) 1048573, + (unsigned long) 2097143, + (unsigned long) 4194301, + (unsigned long) 8388593, + (unsigned long) 16777213, + (unsigned long) 33554393, + (unsigned long) 67108859, + (unsigned long) 134217689, + (unsigned long) 268435399, + (unsigned long) 536870909, + (unsigned long) 1073741789, + (unsigned long) 2147483647, + /* 4294967291L */ + ((unsigned long) 2147483647) + ((unsigned long) 2147483644), + }; + + const unsigned long *low = &primes[0]; + const unsigned long *high = &primes[sizeof(primes) / sizeof(primes[0])]; + + while (low != high) + { + const unsigned long *mid = low + (high - low) / 2; + if (n > *mid) + low = mid + 1; + else + high = mid; + } + +#if 0 + /* If we've run out of primes, abort. */ + if (n > *low) + { + fprintf (stderr, "Cannot find prime bigger than %lu\n", n); + abort (); + } +#endif + + return *low; +} + +struct funcdesc_ht +{ + /* Table itself. */ + struct funcdesc_value **entries; + + /* Current size (in entries) of the hash table */ + size_t size; + + /* Current number of elements. */ + size_t n_elements; +}; + +static __always_inline int +hash_pointer (const void *p) +{ + return (int) ((long)p >> 3); +} + +static __always_inline struct funcdesc_ht * +htab_create (void) +{ + struct funcdesc_ht *ht = _dl_malloc (sizeof (struct funcdesc_ht)); + + if (! ht) + return NULL; + ht->size = 3; + ht->entries = _dl_malloc (sizeof (struct funcdesc_ht_value *) * ht->size); + if (! ht->entries) + return NULL; + + ht->n_elements = 0; + + _dl_memset (ht->entries, 0, sizeof (struct funcdesc_ht_value *) * ht->size); + + return ht; +} + +/* This is only called from _dl_loadaddr_unmap, so it's safe to call + _dl_free(). See the discussion below. */ +static __always_inline void +htab_delete (struct funcdesc_ht *htab) +{ + int i; + + for (i = htab->size - 1; i >= 0; i--) + if (htab->entries[i]) + _dl_free (htab->entries[i]); + + _dl_free (htab->entries); + _dl_free (htab); +} + +/* Similar to htab_find_slot, but without several unwanted side effects: + - Does not call htab->eq_f when it finds an existing entry. + - Does not change the count of elements/searches/collisions in the + hash table. + This function also assumes there are no deleted entries in the table. + HASH is the hash value for the element to be inserted. */ + +static __always_inline struct funcdesc_value ** +find_empty_slot_for_expand (struct funcdesc_ht *htab, int hash) +{ + size_t size = htab->size; + unsigned int index = hash % size; + struct funcdesc_value **slot = htab->entries + index; + int hash2; + + if (! *slot) + return slot; + + hash2 = 1 + hash % (size - 2); + for (;;) + { + index += hash2; + if (index >= size) + index -= size; + + slot = htab->entries + index; + if (! *slot) + return slot; + } +} + +/* The following function changes size of memory allocated for the + entries and repeatedly inserts the table elements. The occupancy + of the table after the call will be about 50%. Naturally the hash + table must already exist. Remember also that the place of the + table entries is changed. If memory allocation failures are allowed, + this function will return zero, indicating that the table could not be + expanded. If all goes well, it will return a non-zero value. */ + +static __always_inline int +htab_expand (struct funcdesc_ht *htab) +{ + struct funcdesc_value **oentries; + struct funcdesc_value **olimit; + struct funcdesc_value **p; + struct funcdesc_value **nentries; + size_t nsize; + + oentries = htab->entries; + olimit = oentries + htab->size; + + /* Resize only when table after removal of unused elements is either + too full or too empty. */ + if (htab->n_elements * 2 > htab->size) + nsize = higher_prime_number (htab->n_elements * 2); + else + nsize = htab->size; + + nentries = _dl_malloc (sizeof (struct funcdesc_value *) * nsize); + _dl_memset (nentries, 0, sizeof (struct funcdesc_value *) * nsize); + if (nentries == NULL) + return 0; + htab->entries = nentries; + htab->size = nsize; + + p = oentries; + do + { + if (*p) + *find_empty_slot_for_expand (htab, hash_pointer ((*p)->entry_point)) + = *p; + + p++; + } + while (p < olimit); + +#if 0 /* We can't tell whether this was allocated by the _dl_malloc() + built into ld.so or malloc() in the main executable or libc, + and calling free() for something that wasn't malloc()ed could + do Very Bad Things (TM). Take the conservative approach + here, potentially wasting as much memory as actually used by + the hash table, even if multiple growths occur. That's not + so bad as to require some overengineered solution that would + enable us to keep track of how it was allocated. */ + _dl_free (oentries); +#endif + return 1; +} + +/* This function searches for a hash table slot containing an entry + equal to the given element. To delete an entry, call this with + INSERT = 0, then call htab_clear_slot on the slot returned (possibly + after doing some checks). To insert an entry, call this with + INSERT = 1, then write the value you want into the returned slot. + When inserting an entry, NULL may be returned if memory allocation + fails. */ + +static __always_inline struct funcdesc_value ** +htab_find_slot (struct funcdesc_ht *htab, void *ptr, int insert) +{ + unsigned int index; + int hash, hash2; + size_t size; + struct funcdesc_value **entry; + + if (htab->size * 3 <= htab->n_elements * 4 + && htab_expand (htab) == 0) + return NULL; + + hash = hash_pointer (ptr); + + size = htab->size; + index = hash % size; + + entry = &htab->entries[index]; + if (!*entry) + goto empty_entry; + else if ((*entry)->entry_point == ptr) + return entry; + + hash2 = 1 + hash % (size - 2); + for (;;) + { + index += hash2; + if (index >= size) + index -= size; + + entry = &htab->entries[index]; + if (!*entry) + goto empty_entry; + else if ((*entry)->entry_point == ptr) + return entry; + } + + empty_entry: + if (!insert) + return NULL; + + htab->n_elements++; + return entry; +} + +void * +_dl_funcdesc_for (void *entry_point, void *got_value) +{ + struct elf_resolve *tpnt = ((void**)got_value)[2]; + struct funcdesc_ht *ht = tpnt->funcdesc_ht; + struct funcdesc_value **entry; + + _dl_assert (got_value == tpnt->loadaddr.got_value); + + if (! ht) + { + ht = htab_create (); + if (! ht) + return (void*)-1; + tpnt->funcdesc_ht = ht; + } + + entry = htab_find_slot (ht, entry_point, 1); + if (*entry) + { + _dl_assert ((*entry)->entry_point == entry_point); + return _dl_stabilize_funcdesc (*entry); + } + + *entry = _dl_malloc (sizeof (struct funcdesc_value)); + (*entry)->entry_point = entry_point; + (*entry)->got_value = got_value; + + return _dl_stabilize_funcdesc (*entry); +} + +static __always_inline void const * +_dl_lookup_address (void const *address) +{ + struct elf_resolve *rpnt; + struct funcdesc_value const *fd; + + /* Make sure we don't make assumptions about its alignment. */ + __asm__ ("" : "+r" (address)); + + if ((Elf32_Addr)address & 7) + /* It's not a function descriptor. */ + return address; + + fd = (struct funcdesc_value const *)address; + + for (rpnt = _dl_loaded_modules; rpnt; rpnt = rpnt->next) + { + if (! rpnt->funcdesc_ht) + continue; + + if (fd->got_value != rpnt->loadaddr.got_value) + continue; + + address = htab_find_slot (rpnt->funcdesc_ht, (void*)fd->entry_point, 0); + + if (address && *(struct funcdesc_value *const*)address == fd) + { + address = (*(struct funcdesc_value *const*)address)->entry_point; + break; + } + else + address = fd; + } + + return address; +} + +void +__dl_loadaddr_unmap (struct elf32_fdpic_loadaddr loadaddr, + struct funcdesc_ht *funcdesc_ht) +{ + int i; + + for (i = 0; i < loadaddr.map->nsegs; i++) + { + struct elf32_fdpic_loadseg *segdata; + ssize_t offs; + segdata = loadaddr.map->segs + i; + + /* FIXME: + A more cleaner way is to add type for struct elf32_fdpic_loadseg, + and release the memory according to the type. + Currently, we hardcode the memory address of L1 SRAM. */ + if ((segdata->addr & 0xff800000) == 0xff800000) + { + _dl_sram_free ((void *)segdata->addr); + continue; + } + + offs = (segdata->p_vaddr & ADDR_ALIGN); + _dl_munmap ((void*)segdata->addr - offs, + segdata->p_memsz + offs); + } + /* _dl_unmap is only called for dlopen()ed libraries, for which + calling free() is safe, or before we've completed the initial + relocation, in which case calling free() is probably pointless, + but still safe. */ + _dl_free (loadaddr.map); + if (funcdesc_ht) + htab_delete (funcdesc_ht); +} + +static __always_inline int +__dl_is_special_segment (Elf32_Ehdr *epnt, + Elf32_Phdr *ppnt) +{ + if (ppnt->p_type != PT_LOAD) + return 0; + + if ((epnt->e_flags & EF_BFIN_CODE_IN_L1) + && !(ppnt->p_flags & PF_W) + && (ppnt->p_flags & PF_X)) + return 1; + + if ((epnt->e_flags & EF_BFIN_DATA_IN_L1) + && (ppnt->p_flags & PF_W) + && !(ppnt->p_flags & PF_X)) + return 1; + + /* 0xfeb00000, 0xfec00000, 0xff700000, 0xff800000, 0xff900000, + and 0xffa00000 are also used in GNU ld and linux kernel. + They need to be kept synchronized. */ + if (ppnt->p_vaddr == 0xff700000 + || ppnt->p_vaddr == 0xff800000 + || ppnt->p_vaddr == 0xff900000 + || ppnt->p_vaddr == 0xffa00000 + || ppnt->p_vaddr == 0xfeb00000 + || ppnt->p_vaddr == 0xfec00000) + return 1; + + return 0; +} + +static __always_inline char * +__dl_map_segment (Elf32_Ehdr *epnt, + Elf32_Phdr *ppnt, + int infile, + int flags) +{ + char *status, *tryaddr, *addr; + size_t size; + + if (((epnt->e_flags & EF_BFIN_CODE_IN_L1) || ppnt->p_vaddr == 0xffa00000) + && !(ppnt->p_flags & PF_W) + && (ppnt->p_flags & PF_X)) { + status = (char *) _dl_mmap + (tryaddr = 0, + size = (ppnt->p_vaddr & ADDR_ALIGN) + ppnt->p_filesz, + LXFLAGS(ppnt->p_flags), + flags | MAP_EXECUTABLE | MAP_DENYWRITE, + infile, ppnt->p_offset & OFFS_ALIGN); + if (_dl_mmap_check_error(status) + || (tryaddr && tryaddr != status)) + return NULL; + addr = (char *) _dl_sram_alloc (ppnt->p_filesz, L1_INST_SRAM); + if (addr != NULL) + _dl_dma_memcpy (addr, status + (ppnt->p_vaddr & ADDR_ALIGN), ppnt->p_filesz); + _dl_munmap (status, size); + if (addr == NULL) + _dl_dprintf(2, "%s:%i: L1 allocation failed\n", _dl_progname, __LINE__); + return addr; + } + + if (((epnt->e_flags & EF_BFIN_DATA_IN_L1) + || ppnt->p_vaddr == 0xff700000 + || ppnt->p_vaddr == 0xff800000 + || ppnt->p_vaddr == 0xff900000) + && (ppnt->p_flags & PF_W) + && !(ppnt->p_flags & PF_X)) { + if (ppnt->p_vaddr == 0xff800000) + addr = (char *) _dl_sram_alloc (ppnt->p_memsz, L1_DATA_A_SRAM); + else if (ppnt->p_vaddr == 0xff900000) + addr = (char *) _dl_sram_alloc (ppnt->p_memsz, L1_DATA_B_SRAM); + else + addr = (char *) _dl_sram_alloc (ppnt->p_memsz, L1_DATA_SRAM); + if (addr == NULL) { + _dl_dprintf(2, "%s:%i: L1 allocation failed\n", _dl_progname, __LINE__); + } else { + if (_DL_PREAD (infile, addr, ppnt->p_filesz, ppnt->p_offset) != ppnt->p_filesz) { + _dl_sram_free (addr); + return NULL; + } + if (ppnt->p_filesz < ppnt->p_memsz) + _dl_memset (addr + ppnt->p_filesz, 0, ppnt->p_memsz - ppnt->p_filesz); + } + return addr; + } + + if (ppnt->p_vaddr == 0xfeb00000 + || ppnt->p_vaddr == 0xfec00000) { + addr = (char *) _dl_sram_alloc (ppnt->p_memsz, L2_SRAM); + if (addr == NULL) { + _dl_dprintf(2, "%s:%i: L2 allocation failed\n", _dl_progname, __LINE__); + } else { + if (_DL_PREAD (infile, addr, ppnt->p_filesz, ppnt->p_offset) != ppnt->p_filesz) { + _dl_sram_free (addr); + return NULL; + } + if (ppnt->p_filesz < ppnt->p_memsz) + _dl_memset (addr + ppnt->p_filesz, 0, ppnt->p_memsz - ppnt->p_filesz); + } + return addr; + } + + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/bfin/dl-startup.h b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/bfin/dl-startup.h new file mode 100644 index 00000000..550b9bcb --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/bfin/dl-startup.h @@ -0,0 +1,142 @@ + /* Copyright (C) 2003 Red Hat, Inc. + Contributed by Alexandre Oliva + +This file is part of uClibc. + +uClibc is free software; you can redistribute it and/or modify it +under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation; either version 2.1 of the +License, or (at your option) any later version. + +uClibc is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with uClibc; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, +USA. */ + +/* Any assembly language/system dependent hacks needed to setup + * boot1.c so it will work as expected and cope with whatever platform + * specific wierdness is needed for this architecture. + */ + +/* At program start-up, p0 contains a pointer to a + elf32_fdpic_loadmap that describes how the executable was loaded + into memory. p1 contains a pointer to the interpreter (our!) + loadmap, if there is an interpreter, or 0 if we're being run as an + executable. p2 holds a pointer to the interpreter's dynamic + section, if there is an interpreter, or to the executable's dynamic + section, otherwise. If the executable is not dynamic, gr18 is 0. + + We rely on the fact that the linker adds a pointer to the + _GLOBAL_OFFSET_TABLE_ as the last ROFIXUP entry, and that + __self_reloc returns the relocated pointer to us, so that we can + use this value to initialize the PIC register. */ + +__asm__( + " .text\n" \ + " .global __start\n" \ + " .type __start,@function\n" \ + "__start:\n" \ + " call .Lcall\n" \ + ".Lcall:\n" \ + " R4 = RETS;\n" \ + " SP += -32;\n" \ + " R5 = P0;\n" \ + " R6 = P1;\n" \ + " R7 = P2;\n" \ + " R0.L = .Lcall;\n" \ + " R0.H = .Lcall;\n" \ + " R1.L = __ROFIXUP_LIST__;\n" \ + " R1.H = __ROFIXUP_LIST__;\n" \ + " R2.L = __ROFIXUP_END__;\n" \ + " R2.H = __ROFIXUP_END__;\n" \ + " R1 = R1 - R0;\n" \ + " R1 = R1 + R4;\n" \ + " R2 = R2 - R0;\n" \ + " R2 = R2 + R4;\n" \ + " R0 = P1;\n" \ + " CC = R0 == 0;\n" \ + " IF CC R0 = P0;\n" \ + " CALL ___self_reloc;\n" \ + " P3 = R0;\n" \ + " P5 = R0;\n" \ + " R1 = R5;\n" \ + " R2 = R6;\n" \ + " [SP + 12] = R7;\n" \ + " P0 = SP;\n" \ + " P0 += 24;\n" \ + " [SP + 16] = P0;\n" \ + " P0 += 8;\n" \ + " [SP + 20] = P0;\n" \ + " CALL __dl_start;\n" \ + " /* Pass our FINI ptr() to the user in P1 */\n" \ + " R7 = [P5 + __dl_fini@FUNCDESC_GOT17M4];\n" \ + " P4 = [SP + 24];\n" \ + " P3 = [SP + 28];\n" \ + " P0 = R5;\n" \ + " SP += 32;\n" \ + " JUMP (P4);\n" \ + " .size __start,.-__start\n" +); + +#undef DL_START +#define DL_START(X) \ +static void __attribute__ ((used)) \ +_dl_start (Elf32_Addr dl_boot_got_pointer, \ + struct elf32_fdpic_loadmap *dl_boot_progmap, \ + struct elf32_fdpic_loadmap *dl_boot_ldsomap, \ + Elf32_Dyn *dl_boot_ldso_dyn_pointer, \ + struct funcdesc_value *dl_main_funcdesc, \ + X) + +struct elf32_fdpic_loadmap; + +/* + * Get a pointer to the argv array. On many platforms this can be just + * the address of the first argument, on other platforms we need to + * do something a little more subtle here. + */ +#define GET_ARGV(ARGVP, ARGS) ARGVP = (((unsigned long*) ARGS) + 1) + +/* + * Here is a macro to perform a relocation. This is only used when + * bootstrapping the dynamic loader. RELP is the relocation that we + * are performing, REL is the pointer to the address we are relocating. + * SYMBOL is the symbol involved in the relocation, and LOAD is the + * load address. + */ +#define PERFORM_BOOTSTRAP_RELOC(RELP,REL,SYMBOL,LOAD,SYMTAB) \ + switch(ELF32_R_TYPE((RELP)->r_info)){ \ + case R_BFIN_BYTE4_DATA: \ + *(REL) += (SYMBOL); \ + break; \ + case R_BFIN_FUNCDESC_VALUE: \ + { \ + struct funcdesc_value fv = { \ + (void*)((SYMBOL) + *(REL)), \ + (LOAD).got_value \ + }; \ + *(struct funcdesc_value volatile *)(REL) = fv; \ + break; \ + } \ + default: \ + _dl_exit(1); \ + } + +/* + * Transfer control to the user's application, once the dynamic loader + * is done. We return the address of the function's entry point to + * _dl_boot, see boot1_arch.h. + */ +#define START() do { \ + struct elf_resolve *exec_mod = _dl_loaded_modules; \ + dl_main_funcdesc->entry_point = _dl_elf_main; \ + while (exec_mod->libtype != elf_executable) \ + exec_mod = exec_mod->next; \ + dl_main_funcdesc->got_value = exec_mod->loadaddr.got_value; \ + return; \ +} while (0) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/bfin/dl-syscalls.h b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/bfin/dl-syscalls.h new file mode 100644 index 00000000..f74cf1ad --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/bfin/dl-syscalls.h @@ -0,0 +1,208 @@ +/* Copyright (C) 2003, 2004 Red Hat, Inc. + Contributed by Alexandre Oliva + +This file is part of uClibc. + +uClibc is free software; you can redistribute it and/or modify it +under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation; either version 2.1 of the +License, or (at your option) any later version. + +uClibc is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with uClibc; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, +USA. */ + +/* We can't use the real errno in ldso, since it has not yet + * been dynamicly linked in yet. */ +#include "sys/syscall.h" +extern int _dl_errno; +#undef __set_errno +#define __set_errno(X) {(_dl_errno) = (X);} +#include + +/* The code below is extracted from libc/sysdeps/linux/frv/_mmap.c */ + +#if DYNAMIC_LOADER_IN_SIMULATOR +#define __NR___syscall_mmap2 __NR_mmap2 +static __inline__ _syscall6(__ptr_t, __syscall_mmap2, __ptr_t, addr, + size_t, len, int, prot, int, flags, int, fd, off_t, offset) + +/* Make sure we don't get another definition of _dl_mmap from the + machine-independent code. */ +#undef __NR_mmap +#undef __NR_mmap2 + +/* This is always 12, even on architectures where PAGE_SHIFT != 12. */ +# ifndef MMAP2_PAGE_SHIFT +# define MMAP2_PAGE_SHIFT 12 +# endif + +#include /* for PAGE_SIZE */ +static __always_inline void *_dl_memset(void*,int,size_t); +static __always_inline ssize_t _dl_pread(int fd, void *buf, size_t count, off_t offset); + +static __ptr_t +_dl_mmap(__ptr_t addr, size_t len, int prot, int flags, int fd, __off_t offset) +{ + size_t plen = (len + PAGE_SIZE - 1) & -PAGE_SIZE; + +/* This is a hack to enable the dynamic loader to run within a + simulator that doesn't support mmap, with a number of very ugly + tricks. Also, it's not as useful as it sounds, since only dynamic + executables without DT_NEEDED dependencies can be run. AFAIK, they + can only be created with -pie. This trick suffices to enable the + dynamic loader to obtain a blank page that it maps early in the + bootstrap. */ + if ((flags & MAP_FIXED) == 0) + { + void *_dl_mmap_base = 0; + __ptr_t *ret = 0; + + if (! _dl_mmap_base) + { + void *stack; + __asm__ ("mov sp, %0" : "=r" (stack)); + _dl_mmap_base = (void *)(((long)stack + 2 * PAGE_SIZE) & -PAGE_SIZE); + retry: + if (((void **)_dl_mmap_base)[0] == _dl_mmap_base + && ((void **)_dl_mmap_base)[1023] == _dl_mmap_base + && (((void **)_dl_mmap_base)[177] + == ((void **)_dl_mmap_base)[771])) + { + while (((void**)_dl_mmap_base)[177]) + { + _dl_mmap_base = ((void**)_dl_mmap_base)[177]; + if (!(((void **)_dl_mmap_base)[0] == _dl_mmap_base + && ((void **)_dl_mmap_base)[1023] == _dl_mmap_base + && (((void **)_dl_mmap_base)[177] + == ((void**)_dl_mmap_base)[771]))) + ((void(*)())0)(); + } + } + else + { + int i; + for (i = 0; i < (int)PAGE_SIZE; i++) + if (*(char*)(_dl_mmap_base + i)) + break; + if (i != PAGE_SIZE) + { + _dl_mmap_base = (void*)((long)_dl_mmap_base + PAGE_SIZE); + goto retry; + } + ((void**)_dl_mmap_base)[-1] = + ((void**)_dl_mmap_base)[0] = + ((void**)_dl_mmap_base)[1023] = + _dl_mmap_base; + } + } + + if (_dl_mmap_base) + { + if (!(((void **)_dl_mmap_base)[0] == _dl_mmap_base + && ((void **)_dl_mmap_base)[1023] == _dl_mmap_base + && (((void **)_dl_mmap_base)[177] + == ((void**)_dl_mmap_base)[771]))) + ((void(*)())0)(); + ret = (__ptr_t)((char*)_dl_mmap_base + PAGE_SIZE); + _dl_mmap_base = + ((void**)_dl_mmap_base)[177] = + ((void**)_dl_mmap_base)[771] = + (char*)_dl_mmap_base + plen + PAGE_SIZE; + ((void**)_dl_mmap_base)[0] = + ((void**)_dl_mmap_base)[1023] = + _dl_mmap_base; + } + + if ((flags & MAP_ANONYMOUS) != 0) + { + _dl_memset (ret, 0, plen); + return ret; + } + + flags |= MAP_FIXED; + addr = ret; + } + if (offset & ((1 << MMAP2_PAGE_SHIFT) - 1)) { +#if 0 + __set_errno (EINVAL); +#endif + return MAP_FAILED; + } + if ((flags & MAP_FIXED) != 0) + { + if (_dl_pread(fd, addr, len, offset) != (ssize_t)len) + return (void*)MAP_FAILED; + if (plen != len) + _dl_memset (addr + len, 0, plen - len); + return addr; + } + return(__syscall_mmap2(addr, len, prot, flags, fd, (off_t) (offset >> MMAP2_PAGE_SHIFT))); +} +#endif + +#ifdef __NR_pread +#ifdef DYNAMIC_LOADER_IN_SIMULATOR +#include + +#define __NR___syscall_lseek __NR_lseek +static __always_inline unsigned long _dl_read(int fd, const void *buf, unsigned long count); + +static __always_inline _syscall3(__off_t, __syscall_lseek, int, fd, __off_t, offset, + int, whence) +static __always_inline ssize_t +_dl_pread(int fd, void *buf, size_t count, off_t offset) +{ + __off_t orig = __syscall_lseek (fd, 0, SEEK_CUR); + ssize_t ret; + + if (orig == -1) + return -1; + + if (__syscall_lseek (fd, offset, SEEK_SET) != offset) + return -1; + + ret = _dl_read (fd, buf, count); + + if (__syscall_lseek (fd, orig, SEEK_SET) != orig) + ((void(*)())0)(); + + return ret; +} +#else +#define __NR___syscall_pread __NR_pread +static __always_inline _syscall5(ssize_t, __syscall_pread, int, fd, void *, buf, + size_t, count, off_t, offset_hi, off_t, offset_lo) + +static __always_inline ssize_t +_dl_pread(int fd, void *buf, size_t count, off_t offset) +{ + return(__syscall_pread(fd,buf,count,__LONG_LONG_PAIR (offset >> 31, offset))); +} +#endif +#endif + +#ifdef __NR_sram_alloc +#define __NR__dl_sram_alloc __NR_sram_alloc +static __always_inline _syscall2(__ptr_t, _dl_sram_alloc, + size_t, len, unsigned long, flags) +#endif + +#ifdef __NR_sram_free +#define __NR__dl_sram_free __NR_sram_free +static __always_inline _syscall1(int, _dl_sram_free, __ptr_t, addr) +#endif + +#ifdef __NR_dma_memcpy +#define __NR__dl_dma_memcpy __NR_dma_memcpy +static __always_inline _syscall3(__ptr_t, _dl_dma_memcpy, + __ptr_t, dest, __ptr_t, src, size_t, len) +#endif + +#define __UCLIBC_MMAP_HAS_6_ARGS__ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/bfin/dl-sysdep.h b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/bfin/dl-sysdep.h new file mode 100644 index 00000000..50c75099 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/bfin/dl-sysdep.h @@ -0,0 +1,234 @@ + /* Copyright (C) 2003, 2004 Red Hat, Inc. + Contributed by Alexandre Oliva + Based on ../i386/dl-sysdep.h + +This file is part of uClibc. + +uClibc is free software; you can redistribute it and/or modify it +under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation; either version 2.1 of the +License, or (at your option) any later version. + +uClibc is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with uClibc; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, +USA. */ + +/* + * Various assembly language/system dependent hacks that are required + * so that we can minimize the amount of platform specific code. + */ + +/* + * Define this if the system uses RELOCA. + */ +#undef ELF_USES_RELOCA + +/* JMPREL relocs are inside the DT_RELA table. */ +#define ELF_MACHINE_PLTREL_OVERLAP + +#define DL_NO_COPY_RELOCS + +#define HAVE_DL_INLINES_H + +/* + * Initialization sequence for a GOT. Copy the resolver function + * descriptor and the pointer to the elf_resolve/link_map data + * structure. Initialize the got_value in the module while at that. + */ +#define INIT_GOT(GOT_BASE,MODULE) \ +{ \ + (MODULE)->loadaddr.got_value = (GOT_BASE); \ + GOT_BASE[0] = ((unsigned long *)&_dl_linux_resolve)[0]; \ + GOT_BASE[1] = ((unsigned long *)&_dl_linux_resolve)[1]; \ + GOT_BASE[2] = (unsigned long) MODULE; \ +} + +/* Here we define the magic numbers that this dynamic loader should accept */ +#define MAGIC1 EM_BLACKFIN +#undef MAGIC2 + +/* Used for error messages */ +#define ELF_TARGET "BFIN" + +/* Need bootstrap relocations */ +#define ARCH_NEEDS_BOOTSTRAP_RELOCS + +struct elf_resolve; + +struct funcdesc_value +{ + void *entry_point; + void *got_value; +} __attribute__((__aligned__(8))); + + +extern int _dl_linux_resolve(void) __attribute__((__visibility__("hidden"))); + +struct funcdesc_ht; + +#undef SEND_EARLY_STDERR +#define SEND_EARLY_STDERR(S) \ + do { \ + static const char __attribute__((section(".text"))) __s[] = (S); \ + const char *__p, *__scratch; \ + __asm__ ("call 1f;\n1:\n\t" \ + "%1 = RETS;\n\t" \ + "%0 = [%3 + 1b@GOT17M4];\n\t" \ + "%1 = %1 - %0;\n\t" \ + "%1 = %1 + %2;\n\t" \ + : "=&d" (__scratch), "=&d" (__p) \ + : "d" (__s), "a" (dl_boot_got_pointer) : "RETS"); \ + SEND_STDERR (__p); \ + { int __t; \ + for (__t = 0; __t < 0x1000000; __t++) __asm__ __volatile__ (""); } \ + } while (0) + +#define DL_LOADADDR_TYPE struct elf32_fdpic_loadaddr + +#define DL_RELOC_ADDR(LOADADDR, ADDR) \ + ((ElfW(Addr))__reloc_pointer ((void*)(ADDR), (LOADADDR).map)) + +#define DL_ADDR_TO_FUNC_PTR(ADDR, LOADADDR) \ + ((void(*)(void)) _dl_funcdesc_for ((void*)(ADDR), (LOADADDR).got_value)) + +#define _dl_stabilize_funcdesc(val) \ + ({ __asm__ ("" : "+m" (*(val))); (val); }) + +#define DL_CALL_FUNC_AT_ADDR(ADDR, LOADADDR, SIGNATURE, ...) \ + ({ struct funcdesc_value fd = { (void*)(ADDR), (LOADADDR).got_value }; \ + void (*pf)(void) = (void*) _dl_stabilize_funcdesc (&fd); \ + (* SIGNATURE pf)(__VA_ARGS__); }) + +#define DL_INIT_LOADADDR_BOOT(LOADADDR, BASEADDR) \ + (__dl_init_loadaddr_map (&(LOADADDR), dl_boot_got_pointer, \ + dl_boot_ldsomap ?: dl_boot_progmap)) + +#define DL_INIT_LOADADDR_PROG(LOADADDR, BASEADDR) \ + (__dl_init_loadaddr_map (&(LOADADDR), 0, dl_boot_progmap)) + +#define DL_INIT_LOADADDR_EXTRA_DECLS \ + int dl_init_loadaddr_load_count; +#define DL_INIT_LOADADDR(LOADADDR, BASEADDR, PHDR, PHDRCNT) \ + (dl_init_loadaddr_load_count = \ + __dl_init_loadaddr (&(LOADADDR), (PHDR), (PHDRCNT))) +#define DL_INIT_LOADADDR_HDR(LOADADDR, ADDR, PHDR) \ + (__dl_init_loadaddr_hdr ((LOADADDR), (ADDR), (PHDR), \ + dl_init_loadaddr_load_count)) +#define DL_LOADADDR_UNMAP(LOADADDR, LEN) \ + (__dl_loadaddr_unmap ((LOADADDR), (NULL))) +#define DL_LIB_UNMAP(LIB, LEN) \ + (__dl_loadaddr_unmap ((LIB)->loadaddr, (LIB)->funcdesc_ht)) +#define DL_LOADADDR_BASE(LOADADDR) \ + ((LOADADDR).got_value) + +/* This is called from dladdr(), such that we map a function + descriptor's address to the function's entry point before trying to + find in which library it's defined. */ +#define DL_LOOKUP_ADDRESS(ADDRESS) (_dl_lookup_address (ADDRESS)) + +#define DL_ADDR_IN_LOADADDR(ADDR, TPNT, TFROM) \ + (! (TFROM) && __dl_addr_in_loadaddr ((void*)(ADDR), (TPNT)->loadaddr)) + +/* + * Compute the GOT address. On several platforms, we use assembly + * here. on FDPIC, there's no way to compute the GOT address, + * since the offset between text and data is not fixed, so we arrange + * for the ldso assembly entry point to pass this value as an argument + * to _dl_start. */ +#define DL_BOOT_COMPUTE_GOT(got) ((got) = dl_boot_got_pointer) + +#define DL_BOOT_COMPUTE_DYN(dpnt, got, load_addr) \ + ((dpnt) = dl_boot_ldso_dyn_pointer) + +/* We only support loading FDPIC independently-relocatable shared + libraries. It probably wouldn't be too hard to support loading + shared libraries that require relocation by the same amount, but we + don't know that they exist or would be useful, and the dynamic + loader code could leak the whole-library map unless we keeping a + bit more state for DL_LOADADDR_UNMAP and DL_LIB_UNMAP, so let's + keep things simple for now. */ +#define DL_CHECK_LIB_TYPE(epnt, piclib, _dl_progname, libname) \ +do \ +{ \ + if (((epnt)->e_flags & EF_BFIN_FDPIC) && ! ((epnt)->e_flags & EF_BFIN_PIC)) \ + (piclib) = 2; \ + else \ + { \ + _dl_internal_error_number = LD_ERROR_NOTDYN; \ + _dl_dprintf(2, "%s: '%s' is not an FDPIC shared library" \ + "\n", (_dl_progname), (libname)); \ + _dl_close(infile); \ + return NULL; \ + } \ +\ +} \ +while (0) + +/* We want want to apply all relocations in the interpreter during + bootstrap. Because of this, we have to skip the interpreter + relocations in _dl_parse_relocation_information(), see + elfinterp.c. */ +#define DL_SKIP_BOOTSTRAP_RELOC(SYMTAB, INDEX, STRTAB) 0 + +#ifdef __NR_pread +#define _DL_PREAD(FD, BUF, SIZE, OFFSET) \ + (_dl_pread((FD), (BUF), (SIZE), (OFFSET))) +#endif + +/* We want to return to dlsym() a function descriptor if the symbol + turns out to be a function. */ +#define DL_FIND_HASH_VALUE(TPNT, TYPE_CLASS, SYM) \ + (((TYPE_CLASS) & ELF_RTYPE_CLASS_DLSYM) \ + && ELF32_ST_TYPE((SYM)->st_info) == STT_FUNC \ + ? _dl_funcdesc_for ((void *)DL_RELOC_ADDR ((TPNT)->loadaddr, (SYM)->st_value), \ + (TPNT)->loadaddr.got_value) \ + : DL_RELOC_ADDR ((TPNT)->loadaddr, (SYM)->st_value)) + +#define DL_IS_SPECIAL_SEGMENT(EPNT, PPNT) \ + __dl_is_special_segment(EPNT, PPNT) +#define DL_MAP_SEGMENT(EPNT, PPNT, INFILE, FLAGS) \ + __dl_map_segment (EPNT, PPNT, INFILE, FLAGS) + +#define DL_GET_READY_TO_RUN_EXTRA_PARMS \ + , struct elf32_fdpic_loadmap *dl_boot_progmap, Elf32_Addr dl_boot_got_pointer +#define DL_GET_READY_TO_RUN_EXTRA_ARGS \ + , dl_boot_progmap, dl_boot_got_pointer + + +#ifdef __USE_GNU +# include +#else +# define __USE_GNU +# include +# undef __USE_GNU +#endif + +#include + +static __always_inline Elf32_Addr +elf_machine_load_address (void) +{ + /* this is never an issue on Blackfin systems, so screw it */ + return 0; +} + +static __always_inline void +elf_machine_relative (DL_LOADADDR_TYPE load_off, const Elf32_Addr rel_addr, + Elf32_Word relative_count) +{ +#if 0 + Elf32_Rel * rpnt = (void *) rel_addr; + --rpnt; + do { + Elf32_Addr *const reloc_addr = (void *) (load_off + (++rpnt)->r_offset); + + *reloc_addr = DL_RELOC_ADDR (load_off, *reloc_addr); + } while (--relative_count); +#endif +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/bfin/elfinterp.c b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/bfin/elfinterp.c new file mode 100644 index 00000000..48470d50 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/bfin/elfinterp.c @@ -0,0 +1,349 @@ +/* Blackfin ELF shared library loader suppport + Copyright (C) 2003, 2004 Red Hat, Inc. + Contributed by Alexandre Oliva + Lots of code copied from ../i386/elfinterp.c, so: + Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald, + David Engel, Hongjiu Lu and Mitch D'Souza + Copyright (C) 2001-2002, Erik Andersen + All rights reserved. + +This file is part of uClibc. + +uClibc is free software; you can redistribute it and/or modify it +under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation; either version 2.1 of the +License, or (at your option) any later version. + +uClibc is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with uClibc; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, +USA. */ + +#include /* __attribute_used__ */ + +/* Program to load an ELF binary on a linux system, and run it. + References to symbols in sharable libraries can be resolved by either + an ELF sharable library or a linux style of shared library. */ + +/* Disclaimer: I have never seen any AT&T source code for SVr4, nor have + I ever taken any courses on internals. This program was developed using + information available through the book "UNIX SYSTEM V RELEASE 4, + Programmers guide: Ansi C and Programming Support Tools", which did + a more than adequate job of explaining everything required to get this + working. */ + +__attribute__((__visibility__("hidden"))) +struct funcdesc_value volatile * +_dl_linux_resolver (struct elf_resolve *tpnt, int reloc_entry) +{ + ELF_RELOC *this_reloc; + char *strtab; + ElfW(Sym) *symtab; + int symtab_index; + char *rel_addr; + char *new_addr; + struct funcdesc_value funcval; + struct funcdesc_value volatile *got_entry; + char *symname; + struct symbol_ref sym_ref; + + rel_addr = (char *)tpnt->dynamic_info[DT_JMPREL]; + + this_reloc = (ELF_RELOC *)(intptr_t)(rel_addr + reloc_entry); + symtab_index = ELF_R_SYM(this_reloc->r_info); + + symtab = (Elf32_Sym *) tpnt->dynamic_info[DT_SYMTAB]; + strtab = (char *) tpnt->dynamic_info[DT_STRTAB]; + sym_ref.sym = &symtab[symtab_index]; + sym_ref.tpnt = NULL; + symname= strtab + symtab[symtab_index].st_name; + + /* Address of GOT entry fix up */ + got_entry = (struct funcdesc_value *) DL_RELOC_ADDR(tpnt->loadaddr, this_reloc->r_offset); + + /* Get the address to be used to fill in the GOT entry. */ + new_addr = _dl_find_hash(symname, tpnt->symbol_scope, NULL, 0, &sym_ref); + if (!new_addr) { + new_addr = _dl_find_hash(symname, NULL, NULL, 0, &sym_ref); + if (!new_addr) { + _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", + _dl_progname, symname); + _dl_exit(1); + } + } + + funcval.entry_point = new_addr; + funcval.got_value = sym_ref.tpnt->loadaddr.got_value; + +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_bindings) { + _dl_dprintf(_dl_debug_file, "\nresolve function: %s", symname); + if (_dl_debug_detail) + _dl_dprintf(_dl_debug_file, + "\n\tpatched (%x,%x) ==> (%x,%x) @ %x\n", + got_entry->entry_point, got_entry->got_value, + funcval.entry_point, funcval.got_value, + got_entry); + } + if (1 || !_dl_debug_nofixups) { + *got_entry = funcval; + } +#else + *got_entry = funcval; +#endif + + return got_entry; +} + +static int +_dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope, + unsigned long rel_addr, unsigned long rel_size, + int (*reloc_fnc) (struct elf_resolve *tpnt, struct dyn_elf *scope, + ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab)) +{ + unsigned int i; + char *strtab; + ElfW(Sym) *symtab; + ELF_RELOC *rpnt; + int symtab_index; + + /* Now parse the relocation information */ + rpnt = (ELF_RELOC *) rel_addr; + rel_size = rel_size / sizeof(ELF_RELOC); + + symtab = (ElfW(Sym) *) tpnt->dynamic_info[DT_SYMTAB]; + strtab = (char *) tpnt->dynamic_info[DT_STRTAB]; + + for (i = 0; i < rel_size; i++, rpnt++) { + int res; + + symtab_index = ELF_R_SYM(rpnt->r_info); + debug_sym(symtab,strtab,symtab_index); + debug_reloc(symtab,strtab,rpnt); + + res = reloc_fnc (tpnt, scope, rpnt, symtab, strtab); + + if (res==0) continue; + + _dl_dprintf(2, "\n%s: ",_dl_progname); + + if (symtab_index) + _dl_dprintf(2, "symbol '%s': ", strtab + symtab[symtab_index].st_name); + + if (res <0) { + int reloc_type = ELF_R_TYPE(rpnt->r_info); +#if defined (__SUPPORT_LD_DEBUG__) + _dl_dprintf(2, "can't handle reloc type %s\n ", _dl_reltypes(reloc_type)); +#else + _dl_dprintf(2, "can't handle reloc type %x\n", reloc_type); +#endif + _dl_exit(-res); + } else if (res >0) { + _dl_dprintf(2, "can't resolve symbol\n"); + return res; + } + } + return 0; +} + +static int +_dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope, + ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab) +{ + int reloc_type; + int symtab_index; + char *symname; + unsigned long reloc_value = 0, *reloc_addr; + struct { unsigned long v; } __attribute__((__packed__)) + *reloc_addr_packed; + unsigned long symbol_addr; + struct elf_resolve *symbol_tpnt; + struct funcdesc_value funcval; +#if defined (__SUPPORT_LD_DEBUG__) + unsigned long old_val; +#endif + struct symbol_ref sym_ref; + + reloc_addr = (unsigned long *) DL_RELOC_ADDR(tpnt->loadaddr, rpnt->r_offset); + __asm__ ("" : "=r" (reloc_addr_packed) : "0" (reloc_addr)); + reloc_type = ELF_R_TYPE(rpnt->r_info); + symtab_index = ELF_R_SYM(rpnt->r_info); + symbol_addr = 0; + sym_ref.sym = &symtab[symtab_index]; + sym_ref.tpnt = NULL; + symname = strtab + symtab[symtab_index].st_name; + + if (ELF_ST_BIND (symtab[symtab_index].st_info) == STB_LOCAL) { + symbol_addr = (unsigned long) DL_RELOC_ADDR(tpnt->loadaddr, symtab[symtab_index].st_value); + symbol_tpnt = tpnt; + } else { + + symbol_addr = (unsigned long) + _dl_find_hash(symname, scope, NULL, 0, &sym_ref); + + /* + * We want to allow undefined references to weak symbols - this might + * have been intentional. We should not be linking local symbols + * here, so all bases should be covered. + */ + + if (!symbol_addr && ELF_ST_BIND(symtab[symtab_index].st_info) != STB_WEAK) { + _dl_dprintf (2, "%s: can't resolve symbol '%s'\n", + _dl_progname, symname); + _dl_exit (1); + } + symbol_tpnt = sym_ref.tpnt; + } + +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_reloc && _dl_debug_detail) + { + if ((long)reloc_addr_packed & 3) + old_val = reloc_addr_packed->v; + else + old_val = *reloc_addr; + } + else + old_val = 0; +#endif + switch (reloc_type) { + case R_BFIN_UNUSED0: + break; + case R_BFIN_BYTE4_DATA: + if ((long)reloc_addr_packed & 3) + reloc_value = reloc_addr_packed->v += symbol_addr; + else + reloc_value = *reloc_addr += symbol_addr; + break; + case R_BFIN_FUNCDESC_VALUE: + funcval.entry_point = (void*)symbol_addr; + /* The addend of FUNCDESC_VALUE + relocations referencing global + symbols must be ignored, because it + may hold the address of a lazy PLT + entry. */ + if (ELF_ST_BIND(symtab[symtab_index].st_info) == STB_LOCAL) + funcval.entry_point += *reloc_addr; + reloc_value = (unsigned long)funcval.entry_point; + if (symbol_addr) + funcval.got_value + = symbol_tpnt->loadaddr.got_value; + else + funcval.got_value = 0; + __asm__ ("%0 = %2; %1 = %H2;" + : "=m" (*(struct funcdesc_value *)reloc_addr), "=m" (((long *)reloc_addr)[1]) + : "d" (funcval)); + break; + case R_BFIN_FUNCDESC: + if ((long)reloc_addr_packed & 3) + reloc_value = reloc_addr_packed->v; + else + reloc_value = *reloc_addr; + if (symbol_addr) + reloc_value = (unsigned long)_dl_funcdesc_for + ((char *)symbol_addr + reloc_value, + symbol_tpnt->loadaddr.got_value); + else + reloc_value = 0; + if ((long)reloc_addr_packed & 3) + reloc_addr_packed->v = reloc_value; + else + *reloc_addr = reloc_value; + break; + default: + return -1; + } +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_reloc && _dl_debug_detail) { + _dl_dprintf(_dl_debug_file, "\tpatched: %x ==> %x @ %x", old_val, reloc_value, reloc_addr); + switch (reloc_type) { + case R_BFIN_FUNCDESC_VALUE: + _dl_dprintf(_dl_debug_file, " got %x", ((struct funcdesc_value *)reloc_value)->got_value); + break; + case R_BFIN_FUNCDESC: + if (! reloc_value) + break; + _dl_dprintf(_dl_debug_file, " funcdesc (%x,%x)", + ((struct funcdesc_value *)reloc_value)->entry_point, + ((struct funcdesc_value *)reloc_value)->got_value); + break; + } + } +#endif + + return 0; +} + +static int +_dl_do_lazy_reloc (struct elf_resolve *tpnt, + struct dyn_elf *scope __attribute__((unused)), + ELF_RELOC *rpnt, ElfW(Sym) *symtab __attribute__((unused)), + char *strtab __attribute__((unused))) +{ + int reloc_type; + struct funcdesc_value volatile *reloc_addr; + struct funcdesc_value funcval; +#if defined (__SUPPORT_LD_DEBUG__) + unsigned long old_val; +#endif + + reloc_addr = (struct funcdesc_value *) DL_RELOC_ADDR(tpnt->loadaddr, rpnt->r_offset); + reloc_type = ELF_R_TYPE(rpnt->r_info); + +#if defined (__SUPPORT_LD_DEBUG__) + old_val = (unsigned long)reloc_addr->entry_point; +#endif + switch (reloc_type) { + case R_BFIN_UNUSED0: + break; + case R_BFIN_FUNCDESC_VALUE: + funcval = *reloc_addr; + funcval.entry_point = (void *) DL_RELOC_ADDR(tpnt->loadaddr, funcval.entry_point); + funcval.got_value = tpnt->loadaddr.got_value; + *reloc_addr = funcval; + break; + default: + return -1; + } +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_reloc && _dl_debug_detail) + _dl_dprintf(_dl_debug_file, "\tpatched: %x ==> %x @ %x\n", old_val, reloc_addr->entry_point, reloc_addr); +#endif + return 0; + +} + +void +_dl_parse_lazy_relocation_information +(struct dyn_elf *rpnt, unsigned long rel_addr, unsigned long rel_size) +{ + _dl_parse(rpnt->dyn, NULL, rel_addr, rel_size, _dl_do_lazy_reloc); +} + +int +_dl_parse_relocation_information +(struct dyn_elf *rpnt, unsigned long rel_addr, unsigned long rel_size) +{ + return _dl_parse(rpnt->dyn, rpnt->dyn->symbol_scope, rel_addr, rel_size, _dl_do_reloc); +} + +/* We don't have copy relocs. */ + +int +_dl_parse_copy_information +(struct dyn_elf *rpnt __attribute__((unused)), + unsigned long rel_addr __attribute__((unused)), + unsigned long rel_size __attribute__((unused))) +{ + return 0; +} + +#ifndef IS_IN_libdl +# include "../../libc/sysdeps/linux/bfin/crtreloc.c" +#endif + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/bfin/resolve.S b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/bfin/resolve.S new file mode 100644 index 00000000..ae7f4a4c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/bfin/resolve.S @@ -0,0 +1,77 @@ + /* Copyright (C) 2003 Red Hat, Inc. + Contributed by Alexandre Oliva + +This file is part of uClibc. + +uClibc is free software; you can redistribute it and/or modify it +under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation; either version 2.1 of the +License, or (at your option) any later version. + +uClibc is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with uClibc; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, +USA. */ + + /* The function below is tail-called by resolver stubs when a + lazily-bound function is called. It must preserve all + registers that could be used to pass arguments to the actual + function. Upon _dl_linux_resolve entry, GR14 holds the + address of a lazy PLT entry, so @(GR14,-4) is the lazy + relocation number that we have to pass to _dl_linux_resolver. + GR15 holds the caller's GOT, from which we extract the + elf_resolve* that _dl_linux_resolver needs as well. + + _dl_linux_resolver() figures out where the jump symbol is + _really_ supposed to have jumped to and returns that to us. + Once we have that, we prepare to tail-call the actual + function, clean up after ourselves, restoring the original + arguments, then jump to the fixed up address. */ + + .text + .p2align 4 + + .hidden __dl_linux_resolve + .global __dl_linux_resolve + .type __dl_linux_resolve,@function + +__dl_linux_resolve: + /* Preserve arguments. */ + [--SP] = RETS; + [--SP] = P0; + [--SP] = R0; + [--SP] = R1; + [--SP] = R2; + sp += -12; + + /* Prepare to call _dl_linux_resolver. */ + R0 = [P3 + 8]; + /* Not aligned for space reasons. */ + R1 = W[P1 + -4] (Z); + P1 += -2; + R1.H = W[P1]; + + P3 = R3; + CALL __dl_linux_resolver; + + /* Move aside return value that contains the FUNCDESC_VALUE. */ + P3 = R0; + P1 = [P3]; + P3 = [P3 + 4]; + + /* Restore arguments. */ + sp += 12; + R2 = [SP++]; + R1 = [SP++]; + R0 = [SP++]; + P0 = [SP++]; + RETS = [SP++]; + + /* Now jump to the actual function. */ + JUMP (P1); + .size __dl_linux_resolve, . - __dl_linux_resolve diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/c6x/dl-debug.h b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/c6x/dl-debug.h new file mode 100644 index 00000000..9c6edab0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/c6x/dl-debug.h @@ -0,0 +1,49 @@ +/* C6X DSBT ELF shared library loader suppport. + * + * Copyright (C) 2010 Texas Instruments Incorporated + * Contributed by Mark Salter + * + * All rights reserved. + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +static const char *_dl_reltypes_tab[] = +{ + "R_C6000_NONE", /* 0 */ + "R_C6000_ABS32", + "R_C6000_ABS16", + "R_C6000_ABS8", + "R_C6000_PCR_S21", + "R_C6000_PCR_S12", /* 5 */ + "R_C6000_PCR_S10", + "R_C6000_PCR_S7", + "R_C6000_ABS_S16", + "R_C6000_ABS_L16", + "R_C6000_ABS_H16", /* 10 */ + "R_C6000_SBR_U15_B", + "R_C6000_SBR_U15_H", + "R_C6000_SBR_U15_W", + "R_C6000_SBR_S16", + "R_C6000_SBR_L16_B", /* 15 */ + "R_C6000_SBR_L16_H", + "R_C6000_SBR_L16_W", + "R_C6000_SBR_H16_B", + "R_C6000_SBR_H16_H", + "R_C6000_SBR_H16_W", /* 20 */ + "R_C6000_SBR_GOT_U15_W", + "R_C6000_SBR_GOT_L16_W", + "R_C6000_SBR_GOT_H16_W", + "R_C6000_DSBT_INDEX", + "R_C6000_PREL31", /* 25 */ + "R_C6000_COPY", + "R_C6000_JUMP_SLOT", + "R_C6000_SBR_GOT32", + "R_C6000_PCR_H16", + "R_C6000_PCR_L16", /* 30 */ +#if 0 + "R_C6000_ALIGN", /* 253 */ + "R_C6000_FPHEAD", /* 254 */ + "R_C6000_NOCMP", /* 255 */ +#endif +}; diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/c6x/dl-inlines.h b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/c6x/dl-inlines.h new file mode 100644 index 00000000..d8fb42c5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/c6x/dl-inlines.h @@ -0,0 +1,91 @@ +/* Copyright (C) 2010 Texas Instruments Incorporated + * Contributed by Mark Salter + * + * Borrowed heavily from frv arch: + * Copyright (C) 2003, 2004 Red Hat, Inc. + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* Figure out whether the given address is in one of the mapped + segments. */ +static __always_inline int +__dl_addr_in_loadaddr (void *p, struct elf32_dsbt_loadaddr loadaddr) +{ + struct elf32_dsbt_loadmap *map = loadaddr.map; + int c; + + for (c = 0; c < map->nsegs; c++) + if ((void*)map->segs[c].addr <= p + && (char*)p < (char*)map->segs[c].addr + map->segs[c].p_memsz) + return 1; + + return 0; +} + +/* Figure out how many LOAD segments there are in the given headers, + and allocate a block for the load map big enough for them. + got_value will be properly initialized later on, with INIT_GOT. */ +static __always_inline int +__dl_init_loadaddr (struct elf32_dsbt_loadaddr *loadaddr, Elf32_Phdr *ppnt, + int pcnt) +{ + int count = 0, i; + size_t size; + + for (i = 0; i < pcnt; i++) + if (ppnt[i].p_type == PT_LOAD) + count++; + + size = sizeof (struct elf32_dsbt_loadmap) + + sizeof (struct elf32_dsbt_loadseg) * count; + loadaddr->map = _dl_malloc (size); + if (! loadaddr->map) + _dl_exit (-1); + + loadaddr->map->version = 0; + loadaddr->map->nsegs = 0; + + return count; +} + +/* Incrementally initialize a load map. */ +static __always_inline void +__dl_init_loadaddr_hdr (struct elf32_dsbt_loadaddr loadaddr, void *addr, + Elf32_Phdr *phdr, int maxsegs) +{ + struct elf32_dsbt_loadseg *segdata; + + if (loadaddr.map->nsegs == maxsegs) + _dl_exit (-1); + + segdata = &loadaddr.map->segs[loadaddr.map->nsegs++]; + segdata->addr = (Elf32_Addr) addr; + segdata->p_vaddr = phdr->p_vaddr; + segdata->p_memsz = phdr->p_memsz; + +#if defined (__SUPPORT_LD_DEBUG__) + { + if (_dl_debug) + _dl_dprintf(_dl_debug_file, "%i: mapped %x at %x, size %x\n", + loadaddr.map->nsegs-1, + segdata->p_vaddr, segdata->addr, segdata->p_memsz); + } +#endif +} + +static __always_inline void +__dl_loadaddr_unmap (struct elf32_dsbt_loadaddr loadaddr) +{ + int i; + + for (i = 0; i < loadaddr.map->nsegs; i++) + _dl_munmap ((void*)loadaddr.map->segs[i].addr, + loadaddr.map->segs[i].p_memsz); + + /* _dl_unmap is only called for dlopen()ed libraries, for which + calling free() is safe, or before we've completed the initial + relocation, in which case calling free() is probably pointless, + but still safe. */ + _dl_free (loadaddr.map); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/c6x/dl-startup.h b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/c6x/dl-startup.h new file mode 100644 index 00000000..b9ea3040 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/c6x/dl-startup.h @@ -0,0 +1,122 @@ +/* Copyright (C) 2010 Texas Instruments Incorporated + * Contributed by Mark Salter + * + * Borrowed heavily from frv arch: + * Copyright (C) 2003 Red Hat, Inc. + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#undef DL_START +#define DL_START(X) \ +int \ +_dl_start (unsigned placeholder, \ + struct elf32_dsbt_loadmap *dl_boot_progmap, \ + struct elf32_dsbt_loadmap *dl_boot_ldsomap, \ + Elf32_Dyn *dl_boot_ldso_dyn_pointer, \ + X) + +/* + * On entry, the kernel has set up the stack thusly: + * + * 0(sp) pad0 + * 4(sp) pad1 + * 8(sp) argc + * 12(sp) argv[0] + * ... + * (4*(argc+3))(sp) NULL + * (4*(argc+4))(sp) envp[0] + * ... + * NULL + * + * Register values are unspecified, except: + * + * B4 --> executable loadmap address + * A6 --> interpreter loadmap address + * B6 --> dynamic section address + * B14 --> our DP setup by kernel + * + * NB: DSBT index is always 0 for the executable + * and 1 for the interpreter + */ + +__asm__(" .text\n" + ".globl _start\n" + "_start:\n" + " B .S2 _dl_start\n" + " STW .D2T2 B14, *+B14[1]\n" + " ADD .D1X B15,8,A8\n" + " ADDKPC .S2 ret_from_dl,B3,2\n" + "ret_from_dl:\n" + " B .S2X A4\n" + " || LDW .D2T2 *+B14[0],B14\n" + " ADDKPC .S2 __dl_fini,B0,0\n" + " MV .S1X B0,A4\n" + " NOP\n" + " NOP\n" + " NOP\n" + "__dl_fini:\n" + " LDW .D2T2 *+B14[1],B14\n" + " NOP 4\n" + " LDW .D2T1 *+B14($GOT(_dl_fini)), A0\n" + " NOP 4\n" + " BNOP .S2X A0, 5\n"); + +__asm__(" .text\n" + "__c6x_cache_sync:\n" + " MVK .S2 330,B0\n" + " SWE\n" + " NOP\n" + " BNOP .S2 B3,5\n" + " NOP\n" + " NOP\n" + " NOP\n" + " NOP\n" + "\n" +); + +/* + * Get a pointer to the argv array. On many platforms this can be just + * the address of the first argument, on other platforms we need to + * do something a little more subtle here. + */ +#define GET_ARGV(ARGVP, ARGS) ARGVP = (((unsigned long*) ARGS) + 1) + +struct elf32_dsbt_loadmap; + +/* + * Here is a macro to perform a relocation. This is only used when + * bootstrapping the dynamic loader. RELP is the relocation that we + * are performing, REL is the pointer to the address we are relocating. + * SYMBOL is the symbol involved in the relocation, and LOAD is the + * load address. + */ +#define PERFORM_BOOTSTRAP_RELOC(RELP,REL,SYMBOL,LOAD,SYMTAB) \ + switch(ELF32_R_TYPE((RELP)->r_info)){ \ + case R_C6000_ABS_L16: \ + { \ + unsigned int opcode = *(REL); \ + unsigned int v = (SYMBOL) + (RELP)->r_addend; \ + opcode &= ~0x7fff80; \ + opcode |= ((v & 0xffff) << 7); \ + *(REL) = opcode; \ + } \ + break; \ + case R_C6000_ABS_H16: \ + { \ + unsigned int opcode = *(REL); \ + unsigned int v = (SYMBOL) + (RELP)->r_addend; \ + opcode &= ~0x7fff80; \ + opcode |= ((v >> 9) & 0x7fff80); \ + *(REL) = opcode; \ + } \ + break; \ + case R_C6000_ABS32: \ + *(REL) = (SYMBOL) + (RELP)->r_addend; \ + break; \ + default: \ + _dl_exit(1); \ + } + +extern void __c6x_cache_sync(unsigned long start, unsigned long end) + attribute_hidden; diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/c6x/dl-syscalls.h b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/c6x/dl-syscalls.h new file mode 100644 index 00000000..9ff3358b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/c6x/dl-syscalls.h @@ -0,0 +1,25 @@ +/* Copyright (C) 2010 Texas Instruments Incorporated + * Contributed by Mark Salter + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* We can't use the real errno in ldso, since it has not yet + * been dynamicly linked in yet. */ +#include "sys/syscall.h" +extern int _dl_errno; +#undef __set_errno +#define __set_errno(X) {(_dl_errno) = (X);} +#include + +#ifdef __NR_pread64 +#define __NR___syscall_pread __NR_pread64 +static __always_inline _syscall5(ssize_t, __syscall_pread, int, fd, void *, buf, + size_t, count, off_t, offset_hi, off_t, offset_lo); + +static __always_inline ssize_t +_dl_pread(int fd, void *buf, size_t count, off_t offset) +{ + return(__syscall_pread(fd,buf,count, offset, offset >> 31)); +} +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/c6x/dl-sysdep.h b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/c6x/dl-sysdep.h new file mode 100644 index 00000000..8f1b122d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/c6x/dl-sysdep.h @@ -0,0 +1,209 @@ +/* Copyright (C) 2010 Texas Instruments Incorporated + * Contributed by Mark Salter + * + * Borrowed heavily from frv arch: + * Copyright (C) 2003, 2004 Red Hat, Inc. + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +/* + * Define this if the system uses RELOCA. + */ +#define ELF_USES_RELOCA 1 + +/* JMPREL relocs are inside the DT_RELA table. */ +/* Actually looks like a linker bug sets DT_JMPREL anyway */ +#define ELF_MACHINE_PLTREL_OVERLAP 1 + +#undef DL_NO_COPY_RELOCS + +#define HAVE_DL_INLINES_H + + +/* + * Various assembly language/system dependent hacks that are required + * so that we can minimize the amount of platform specific code. + */ + +/* Initialization sequence for the GOT. */ +#define INIT_GOT(GOT_BASE,MODULE) \ +{ \ + GOT_BASE[0] = (unsigned long) _dl_linux_resolve; \ + GOT_BASE[1] = (unsigned long) MODULE; \ +} + +/* Here we define the magic numbers that this dynamic loader should accept */ +#define MAGIC1 EM_TI_C6000 +#undef MAGIC2 + +/* Used for error messages */ +#define ELF_TARGET "C6000" + +/* Need bootstrap relocations */ +#define ARCH_NEEDS_BOOTSTRAP_RELOCS + +struct elf_resolve; + +extern int _dl_linux_resolve(void) attribute_hidden; + +struct funcdesc_ht; +struct elf32_dsbt_loadaddr; + +/* We must force strings used early in the bootstrap into the text + segment (const data), such that they are referenced relative to + the DP register rather than through the GOT which will not have + been relocated when these are used. */ +#undef SEND_EARLY_STDERR +#define SEND_EARLY_STDERR(S) \ + do { static char __s[] = (S); SEND_STDERR (__s); } while (0) + +#define DL_LOADADDR_TYPE struct elf32_dsbt_loadaddr + +#define DL_RELOC_ADDR(LOADADDR, ADDR) \ + ((ElfW(Addr))__reloc_pointer ((void*)(ADDR), (LOADADDR).map)) + +#define DL_INIT_LOADADDR_BOOT(LOADADDR, BASEADDR) \ + do { \ + struct elf32_dsbt_loadmap *map; \ + map = dl_boot_ldsomap ?: dl_boot_progmap; \ + if (map->version != 0) { \ + SEND_EARLY_STDERR ("Invalid loadmap version number\n"); \ + _dl_exit(-1); \ + } \ + if (map->nsegs < 2) { \ + SEND_EARLY_STDERR ("Invalid segment count in loadmap\n"); \ + _dl_exit(-1); \ + } \ + (LOADADDR).map = map; \ + } while(0) + +#define DL_INIT_LOADADDR_PROG(LOADADDR, BASEADDR) \ + do { \ + if (dl_boot_progmap->version != 0) { \ + SEND_EARLY_STDERR ("Invalid loadmap version number\n"); \ + _dl_exit(-1); \ + } \ + if (dl_boot_progmap->nsegs < 2) { \ + SEND_EARLY_STDERR ("Invalid segment count in loadmap\n"); \ + _dl_exit(-1); \ + } \ + (LOADADDR).map = dl_boot_progmap; \ + } while(0) + +#define DL_INIT_LOADADDR_EXTRA_DECLS \ + int dl_init_loadaddr_load_count; + +#define DL_INIT_LOADADDR(LOADADDR, BASEADDR, PHDR, PHDRCNT) \ + (dl_init_loadaddr_load_count = \ + __dl_init_loadaddr (&(LOADADDR), (PHDR), (PHDRCNT))) + +#define DL_INIT_LOADADDR_HDR(LOADADDR, ADDR, PHDR) \ + (__dl_init_loadaddr_hdr ((LOADADDR), (ADDR), (PHDR), \ + dl_init_loadaddr_load_count)) + +#define DL_LOADADDR_UNMAP(LOADADDR, LEN) \ + (__dl_loadaddr_unmap ((LOADADDR))) + +#define DL_LIB_UNMAP(LIB, LEN) \ + (__dl_loadaddr_unmap ((LIB)->loadaddr)) + +#define DL_LOADADDR_BASE(LOADADDR) \ + ((LOADADDR).map->dsbt_table) + +#define DL_ADDR_IN_LOADADDR(ADDR, TPNT, TFROM) \ + (! (TFROM) && __dl_addr_in_loadaddr ((void*)(ADDR), (TPNT)->loadaddr)) + + +/* We only support loading DSBT relocatable shared libraries. + It probably wouldn't be too hard to support loading statically + linked executables that require relocation.*/ +#define DL_CHECK_LIB_TYPE(epnt, piclib, _dl_progname, libname) \ +do \ +{ \ + (piclib) = 2; \ +} \ +while (0) + +/* We want want to apply all relocations in the interpreter during + bootstrap. Because of this, we have to skip the interpreter + relocations in _dl_parse_relocation_information(), see + elfinterp.c. */ +#define DL_SKIP_BOOTSTRAP_RELOC(SYMTAB, INDEX, STRTAB) 0 + +#ifdef __NR_pread64 +#define _DL_PREAD(FD, BUF, SIZE, OFFSET) \ + (_dl_pread((FD), (BUF), (SIZE), (OFFSET))) +#endif + +#define DL_GET_READY_TO_RUN_EXTRA_PARMS \ + , struct elf32_dsbt_loadmap *dl_boot_progmap \ + , struct elf32_dsbt_loadmap *dl_boot_ldsomap +#define DL_GET_READY_TO_RUN_EXTRA_ARGS \ + , dl_boot_progmap \ + , dl_boot_ldsomap + + +/* + * Compute the GOT address. + * Also setup program and interpreter DSBT table entries. + */ +#define DL_BOOT_COMPUTE_GOT(GOT) \ + do { \ + unsigned long *ldso_dsbt, *prog_dsbt; \ + ldso_dsbt = dl_boot_ldsomap->dsbt_table; \ + prog_dsbt = dl_boot_progmap->dsbt_table; \ + ldso_dsbt[0] = prog_dsbt[0] = (unsigned long)prog_dsbt; \ + ldso_dsbt[1] = prog_dsbt[1] = (unsigned long)ldso_dsbt; \ + (GOT) = ldso_dsbt + dl_boot_ldsomap->dsbt_size; \ + } while(0) + +#define DL_BOOT_COMPUTE_DYN(dpnt, got, load_addr) \ + ((dpnt) = dl_boot_ldso_dyn_pointer) + + +#ifdef __USE_GNU +# include +#else +# define __USE_GNU +# include +# undef __USE_GNU +#endif + +static __always_inline Elf32_Addr +elf_machine_load_address (void) +{ + /* this is never an issue on DSBT systems */ + return 0; +} + +static __always_inline void +elf_machine_relative (DL_LOADADDR_TYPE load_off, const Elf32_Addr rel_addr, + Elf32_Word relative_count) +{ +} + +/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry, so + PLT entries should not be allowed to define the value. + ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to one + of the main executable's symbols, as for a COPY reloc. */ +#define elf_machine_type_class(type) \ + ((((type) == R_C6000_JUMP_SLOT) * ELF_RTYPE_CLASS_PLT) \ + | (((type) == R_C6000_COPY) * ELF_RTYPE_CLASS_COPY)) + +#define ARCH_NUM 3 +#define DT_DSBT_BASE_IDX (DT_NUM + OS_NUM) +#define DT_DSBT_SIZE_IDX (DT_NUM + OS_NUM + 1) +#define DT_DSBT_INDEX_IDX (DT_NUM + OS_NUM + 2) + +#define ARCH_DYNAMIC_INFO(dpnt, dynamic, debug_addr) \ +do { \ +if (dpnt->d_tag == DT_C6000_DSBT_BASE) \ + dynamic[DT_DSBT_BASE_IDX] = dpnt->d_un.d_val; \ +else if (dpnt->d_tag == DT_C6000_DSBT_SIZE) \ + dynamic[DT_DSBT_SIZE_IDX] = dpnt->d_un.d_val; \ +else if (dpnt->d_tag == DT_C6000_DSBT_INDEX) \ + dynamic[DT_DSBT_INDEX_IDX] = dpnt->d_un.d_val; \ +} while (0) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/c6x/elfinterp.c b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/c6x/elfinterp.c new file mode 100644 index 00000000..7c79171c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/c6x/elfinterp.c @@ -0,0 +1,296 @@ +/* TI C64X DSBT ELF shared library loader suppport + * Copyright (C) 2010 Texas Instruments Incorporated + * Contributed by Mark Salter + * + * Borrowed heavily from frv arch: + * Copyright (C) 2003, 2004 Red Hat, Inc. + * Contributed by Alexandre Oliva + * Lots of code copied from ../i386/elfinterp.c, so: + * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald, + * David Engel, Hongjiu Lu and Mitch D'Souza + * Copyright (C) 2001-2002, Erik Andersen + * All rights reserved. + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +/* Program to load an ELF binary on a linux system, and run it. + References to symbols in sharable libraries can be resolved by either + an ELF sharable library or a linux style of shared library. */ + +/* Disclaimer: I have never seen any AT&T source code for SVr4, nor have + I ever taken any courses on internals. This program was developed using + information available through the book "UNIX SYSTEM V RELEASE 4, + Programmers guide: Ansi C and Programming Support Tools", which did + a more than adequate job of explaining everything required to get this + working. */ + +extern void __c6x_cache_sync(unsigned long start, unsigned long end) + attribute_hidden; + +static void +_dl_c6x_flush_relocs(struct elf32_dsbt_loadmap *map) +{ + unsigned long s, e; + s = map->segs[0].addr; + e = s + map->segs[0].p_memsz; + __c6x_cache_sync(s, e); + s = map->segs[1].addr; + e = s + map->segs[1].p_memsz; + __c6x_cache_sync(s, e); +} + + +attribute_hidden +char * +_dl_linux_resolver (struct elf_resolve *tpnt, int reloc_entry) +{ + ELF_RELOC *this_reloc; + char *strtab; + ElfW(Sym) *symtab; + int symtab_index; + char *rel_addr; + char *new_addr; + char **got_addr; + char *symname; + + rel_addr = (char *)tpnt->dynamic_info[DT_JMPREL]; + + this_reloc = (ELF_RELOC *)(intptr_t)(rel_addr + reloc_entry); + symtab_index = ELF_R_SYM(this_reloc->r_info); + + symtab = (Elf32_Sym *) tpnt->dynamic_info[DT_SYMTAB]; + strtab = (char *) tpnt->dynamic_info[DT_STRTAB]; + symname = strtab + symtab[symtab_index].st_name; + + /* Address of GOT entry fix up */ + got_addr = (char **) DL_RELOC_ADDR(tpnt->loadaddr, this_reloc->r_offset); + + /* Get the address to be used to fill in the GOT entry. */ + new_addr = _dl_find_hash(symname, tpnt->symbol_scope, tpnt, + ELF_RTYPE_CLASS_PLT, NULL); + if (unlikely(!new_addr)) { + _dl_dprintf(2, "%s: can't resolve symbol '%s' in lib '%s'.\n", _dl_progname, symname, tpnt->libname); + _dl_exit(1); + } + + +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_bindings) { + _dl_dprintf(_dl_debug_file, "\nresolve function: %s", symname); + if (_dl_debug_detail) + _dl_dprintf(_dl_debug_file, + "\n\tpatched %x ==> %x @ %x\n", + *got_addr, new_addr, got_addr); + } + if (!_dl_debug_nofixups) { + *got_addr = new_addr; + } +#else + *got_addr = new_addr; +#endif + + return new_addr; +} + +static int +_dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope, + unsigned long rel_addr, unsigned long rel_size, + int (*reloc_fnc) (struct elf_resolve *tpnt, struct dyn_elf *scope, + ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)) +{ + unsigned int i; + char *strtab; + Elf32_Sym *symtab; + ELF_RELOC *rpnt; + int symtab_index; + + /* Now parse the relocation information */ + rpnt = (ELF_RELOC *)rel_addr; + rel_size = rel_size / sizeof(ELF_RELOC); + + symtab = (Elf32_Sym *)tpnt->dynamic_info[DT_SYMTAB]; + strtab = (char *)tpnt->dynamic_info[DT_STRTAB]; + + for (i = 0; i < rel_size; i++, rpnt++) { + int res; + + symtab_index = ELF32_R_SYM(rpnt->r_info); + debug_sym(symtab,strtab,symtab_index); + debug_reloc(symtab,strtab,rpnt); + + res = reloc_fnc (tpnt, scope, rpnt, symtab, strtab); + + if (res==0) continue; + + _dl_dprintf(2, "\n%s: ",_dl_progname); + + if (symtab_index) + _dl_dprintf(2, "symbol '%s': ", strtab + symtab[symtab_index].st_name); + + if (res <0) { + int reloc_type = ELF32_R_TYPE(rpnt->r_info); +#if defined (__SUPPORT_LD_DEBUG__) + _dl_dprintf(2, "can't handle reloc type %s\n ", _dl_reltypes(reloc_type)); +#else + _dl_dprintf(2, "can't handle reloc type %x\n", reloc_type); +#endif + _dl_exit(-res); + } else if (res >0) { + _dl_dprintf(2, "can't resolve symbol\n"); + return res; + } + } + _dl_c6x_flush_relocs(tpnt->loadaddr.map); + return 0; +} + +static int +_dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope, + ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab) +{ + int reloc_type; + int symtab_index; + char *symname; + unsigned long *reloc_addr; + unsigned long symbol_addr, sym_val; + long reloc_addend; + unsigned long old_val, new_val; + + reloc_addr = (unsigned long *)(intptr_t) + DL_RELOC_ADDR (tpnt->loadaddr, rpnt->r_offset); + + reloc_type = ELF32_R_TYPE(rpnt->r_info); + reloc_addend = rpnt->r_addend; + symtab_index = ELF32_R_SYM(rpnt->r_info); + symbol_addr = 0; + symname = strtab + symtab[symtab_index].st_name; + + if (ELF32_ST_BIND (symtab[symtab_index].st_info) == STB_LOCAL) { + symbol_addr = (unsigned long) + DL_RELOC_ADDR (tpnt->loadaddr, symtab[symtab_index].st_value); + } else { + symbol_addr = (unsigned long) _dl_find_hash(strtab + symtab[symtab_index].st_name, + scope, tpnt, elf_machine_type_class(reloc_type), + NULL); + /* + * We want to allow undefined references to weak symbols - this might + * have been intentional. We should not be linking local symbols + * here, so all bases should be covered. + */ + + if (!symbol_addr && ELF32_ST_BIND(symtab[symtab_index].st_info) != STB_WEAK) { + _dl_dprintf (2, "%s: can't resolve symbol '%s'\n", + _dl_progname, strtab + symtab[symtab_index].st_name); + _dl_exit (1); + } + } + old_val = *reloc_addr; + sym_val = symbol_addr + reloc_addend; + + switch (reloc_type) { + case R_C6000_NONE: + break; + case R_C6000_ABS32: + case R_C6000_JUMP_SLOT: + new_val = sym_val; + *reloc_addr = sym_val; + break; + case R_C6000_ABS_L16: + new_val = (old_val & ~0x007fff80) | ((sym_val & 0xffff) << 7); + *reloc_addr = new_val; + break; + case R_C6000_ABS_H16: + new_val = (old_val & ~0x007fff80) | ((sym_val >> 9) & 0x007fff80); + *reloc_addr = new_val; + break; + case R_C6000_PCR_S21: + new_val = sym_val - (((unsigned long)reloc_addr) & ~31); + *reloc_addr = (old_val & ~0x0fffff80) | (((new_val >> 2) & 0x1fffff) << 7); + break; + case R_C6000_COPY: + if (symbol_addr) { +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_move) + _dl_dprintf(_dl_debug_file, + "\n%s move %d bytes from %x to %x", + symname, symtab[symtab_index].st_size, + symbol_addr, reloc_addr); +#endif + + _dl_memcpy((char *)reloc_addr, + (char *)symbol_addr, + symtab[symtab_index].st_size); + } + break; + default: + return -1; /*call _dl_exit(1) */ + } +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_reloc && _dl_debug_detail && reloc_type != R_C6000_NONE) { + _dl_dprintf(_dl_debug_file, "\tpatched: %x ==> %x @ %x\n", old_val, new_val, reloc_addr); + } +#endif + return 0; +} + +static int +_dl_do_lazy_reloc (struct elf_resolve *tpnt, + struct dyn_elf *scope attribute_unused, + ELF_RELOC *rpnt, ElfW(Sym) *symtab attribute_unused, + char *strtab attribute_unused) +{ + int reloc_type; + unsigned long *reloc_addr; + unsigned long old_val; + + reloc_addr = (unsigned long *) DL_RELOC_ADDR(tpnt->loadaddr, rpnt->r_offset); + reloc_type = ELF_R_TYPE(rpnt->r_info); + + old_val = *reloc_addr; + + switch (reloc_type) { + case R_C6000_NONE: + break; + case R_C6000_JUMP_SLOT: + *reloc_addr = DL_RELOC_ADDR(tpnt->loadaddr, old_val); + break; + default: + return -1; + } + +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_reloc && _dl_debug_detail) + _dl_dprintf(_dl_debug_file, "\n\tpatched: %x ==> %x @ %x\n", + old_val, *reloc_addr, reloc_addr); +#endif + + return 0; +} + +void +_dl_parse_lazy_relocation_information +(struct dyn_elf *rpnt, unsigned long rel_addr, unsigned long rel_size) +{ + _dl_parse(rpnt->dyn, NULL, rel_addr, rel_size, _dl_do_lazy_reloc); +} + +int +_dl_parse_relocation_information +(struct dyn_elf *rpnt, unsigned long rel_addr, unsigned long rel_size) +{ + return _dl_parse(rpnt->dyn, rpnt->dyn->symbol_scope, rel_addr, rel_size, _dl_do_reloc); +} + +/* We don't have copy relocs. */ +int +_dl_parse_copy_information +(struct dyn_elf *rpnt, + unsigned long rel_addr, + unsigned long rel_size) +{ + return 0; +} + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/c6x/resolve.S b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/c6x/resolve.S new file mode 100644 index 00000000..ce3cbe79 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/c6x/resolve.S @@ -0,0 +1,68 @@ +;; +;; Copyright (C) 2010 Texas Instruments Incorporated +;; Mark Salter +;; +;; Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +;; + +;; The function below is tail-called by resolver stubs when a +;; lazily-bound function is called. It must preserve all +;; registers that could be used to pass arguments to the actual +;; function. + +;; _dl_linux_resolver() figures out where the jump symbol is +;; _really_ supposed to have jumped to and returns that to us. +;; Once we have that, we prepare to tail-call the actual +;; function, clean up after ourselves, restoring the original +;; arguments, then jump to the fixed up address. */ + +; resolver stub - called from PLT to resolve target address and update GOT +; +; B0 : reloc offset (bytes from DT_RELPLT) +; B1 : module pointer, loaded from GOT[1] +; DP : caller's DP +; A4,B4, etc: callee's arguments +; B3 : return address + + .text + .align 5 + .global _dl_linux_resolve +_dl_linux_resolve: + stw .d2t2 B14, *B15--[2] + stdw .d2t1 A15:A14, *B15-- + stdw .d2t2 B13:B12, *B15-- + stdw .d2t1 A13:A12, *B15-- + stdw .d2t2 B11:B10, *B15-- + stdw .d2t1 A11:A10, *B15-- + stdw .d2t2 B9:B8, *B15-- + stdw .d2t1 A9:A8, *B15-- + stdw .d2t2 B7:B6, *B15-- + stdw .d2t1 A7:A6, *B15-- + stdw .d2t2 B5:B4, *B15-- + stdw .d2t1 A5:A4, *B15-- + stdw .d2t2 B3:B2, *B15-- + stdw .d2t1 A3:A2, *B15-- + + ; call lookup routine + MV .S1X B1, A4 ; arg 1: module id +|| MV .S2 B0,B4 ; arg 2: reloc offset + CALLP .S2 _dl_linux_resolver, B3 ; returns &f in A4 + MV .S2X A4,B0 ; &f + + lddw .d2t1 *++B15, A3:A2 + lddw .d2t2 *++B15, B3:B2 + lddw .d2t1 *++B15, A5:A4 + lddw .d2t2 *++B15, B5:B4 + lddw .d2t1 *++B15, A7:A6 + lddw .d2t2 *++B15, B7:B6 + lddw .d2t1 *++B15, A9:A8 + lddw .d2t2 *++B15, B9:B8 + lddw .d2t1 *++B15, A11:A10 + lddw .d2t2 *++B15, B11:B10 + lddw .d2t1 *++B15, A13:A12 + lddw .d2t2 *++B15, B13:B12 + lddw .d2t1 *++B15, A15:A14 + ldw .d2t2 *++B15[2], B14 + + B .S2 B0 ; tail-call f + NOP 5 diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/cris/dl-debug.h b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/cris/dl-debug.h new file mode 100644 index 00000000..f6c03d21 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/cris/dl-debug.h @@ -0,0 +1,42 @@ +/* + * CRIS ELF shared library loader support. + * + * Program to load an elf binary on a linux system, and run it. + * References to symbols in sharable libraries can be resolved + * by either an ELF sharable library or a linux style of shared + * library. + * + * Copyright (C) 2002-2004, Axis Communications AB + * All rights reserved + * + * Author: Tobias Anderberg, + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. The name of the above contributors may not be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +static const char *_dl_reltypes_tab[] = { + [0] "R_CRIS_NONE", "R_CRIS_8", "R_CRIS_16", "R_CRIS_32", + [4] "R_CRIS_8_PCREL", "R_CRIS_16_PCREL", "R_CRIS_32_PCREL", "R_CRIS_GNU_VTINHERIT", + [8] "R_CRIS_GNU_VTENTRY", "R_CRIS_COPY", "R_CRIS_GLOB_DAT", "R_CRIS_JUMP_SLOT", + [16] "R_CRIS_RELATIVE", "R_CRIS_16_GOT", "R_CRIS_32_GOT", "R_CRIS_16_GOTPLT", + [32] "R_CRIS_32_GOTPLT", "R_CRIS_32_GOTREL", "R_CRIS_32_PLT_GOTREL", "R_CRIS_32_PLT_PCREL", +}; diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/cris/dl-startup.h b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/cris/dl-startup.h new file mode 100644 index 00000000..0bc48f87 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/cris/dl-startup.h @@ -0,0 +1,81 @@ +/* + * Architecture specific code used by dl-startup.c + */ + +/* This code fixes the stack pointer so that the dynamic linker + * can find argc, argv and auxvt (Auxillary Vector Table). */ +#ifdef __arch_v32 + +__asm__("" \ +" .text\n" \ +" .globl _start\n" \ +" .type _start,@function\n" \ +"_start:\n" \ +" move.d $sp,$r10\n" \ +" lapc _dl_start,$r9\n" \ +" jsr $r9\n" \ +" nop\n" \ +" moveq 0,$r8\n" \ +" jump $r10\n" \ +" move $r8,$srp\n" \ +" .size _start,.-_start\n" \ +" .previous\n" \ +); + +#else + +__asm__("" \ +" .text\n" \ +" .globl _start\n" \ +" .type _start,@function\n" \ +"_start:\n" \ +" move.d $sp,$r10\n" \ +" move.d $pc,$r9\n" \ +" add.d _dl_start - ., $r9\n" \ +" jsr $r9\n" \ +" moveq 0,$r8\n" \ +" move $r8,$srp\n" \ +" jump $r10\n" \ +" .size _start,.-_start\n" \ +" .previous\n" \ +); + +#endif /* __arch_v32 */ + +/* Get a pointer to the argv array. On many platforms this can be just + * the address of the first argument, on other platforms we need to + * do something a little more subtle here. */ +#define GET_ARGV(ARGVP, ARGS) ARGVP = (((unsigned long *) ARGS)+1) + + +/* We can't call functions earlier in the dl startup process */ +#define NO_FUNCS_BEFORE_BOOTSTRAP + + +/* Handle relocation of the symbols in the dynamic loader. */ +static __always_inline +void PERFORM_BOOTSTRAP_RELOC(ELF_RELOC *rpnt, unsigned long *reloc_addr, + unsigned long symbol_addr, unsigned long load_addr, Elf32_Sym *symtab) +{ + switch (ELF32_R_TYPE(rpnt->r_info)) { + case R_CRIS_GLOB_DAT: + case R_CRIS_JUMP_SLOT: + case R_CRIS_32: + *reloc_addr = symbol_addr; + break; + case R_CRIS_16_PCREL: + *(short *) *reloc_addr = symbol_addr + rpnt->r_addend - *reloc_addr - 2; + break; + case R_CRIS_32_PCREL: + *reloc_addr = symbol_addr + rpnt->r_addend - *reloc_addr - 4; + break; + case R_CRIS_NONE: + break; + case R_CRIS_RELATIVE: + *reloc_addr = load_addr + rpnt->r_addend; + break; + default: + _dl_exit(1); + break; + } +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/cris/dl-syscalls.h b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/cris/dl-syscalls.h new file mode 100644 index 00000000..996bb87c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/cris/dl-syscalls.h @@ -0,0 +1,6 @@ +/* We can't use the real errno in ldso, since it has not yet + * been dynamicly linked in yet. */ +#include "sys/syscall.h" +extern int _dl_errno; +#undef __set_errno +#define __set_errno(X) {(_dl_errno) = (X);} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/cris/dl-sysdep.h b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/cris/dl-sysdep.h new file mode 100644 index 00000000..e454c10a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/cris/dl-sysdep.h @@ -0,0 +1,109 @@ +/* CRIS can never use Elf32_Rel relocations. */ +#define ELF_USES_RELOCA + +#include + +/* Initialization sequence for the GOT. */ +#define INIT_GOT(GOT_BASE,MODULE) \ +{ \ + GOT_BASE[1] = (unsigned long) MODULE; \ + GOT_BASE[2] = (unsigned long) _dl_linux_resolve; \ +} + +/* Defined some magic numbers that this ld.so should accept. */ +#define MAGIC1 EM_CRIS +#undef MAGIC2 +#define ELF_TARGET "CRIS" + +/* Need bootstrap relocations */ +#define ARCH_NEEDS_BOOTSTRAP_RELOCS + +struct elf_resolve; +extern unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry); + +/* The union of reloc-type-classes where the reloc TYPE is a member. + + TYPE is in the class ELF_RTYPE_CLASS_PLT if it can describe a + relocation for a PLT entry, that is, for which a PLT entry should not + be allowed to define the value. The GNU linker for CRIS can merge a + .got.plt entry (R_CRIS_JUMP_SLOT) with a .got entry (R_CRIS_GLOB_DAT), + so we need to match both these reloc types. + + TYPE is in the class ELF_RTYPE_CLASS_NOCOPY if it should not be allowed + to resolve to one of the main executable's symbols, as for a COPY + reloc. */ +#define elf_machine_type_class(type) \ + ((((((type) == R_CRIS_JUMP_SLOT)) \ + || ((type) == R_CRIS_GLOB_DAT)) * ELF_RTYPE_CLASS_PLT) \ + | (((type) == R_CRIS_COPY) * ELF_RTYPE_CLASS_COPY)) + +static __always_inline Elf32_Addr +elf_machine_dynamic(void) +{ + /* Don't just set this to an asm variable "r0" since that's not logical + (like, the variable is uninitialized and the register is fixed) and + may make GCC trip over itself doing register allocation. Yes, I'm + paranoid. Why do you ask? */ + Elf32_Addr *got; + + __asm__ ("move.d $r0,%0" : "=rm" (got)); + return *got; +} + +/* Return the run-time load address of the shared object. We do it like + m68k and i386, by taking an arbitrary local symbol, forcing a GOT entry + for it, and peeking into the GOT table, which is set to the link-time + file-relative symbol value (regardless of whether the target is REL or + RELA). We subtract this link-time file-relative value from the "local" + value we calculate from GOT position and GOT offset. FIXME: Perhaps + there's some other symbol we could use, that we don't *have* to force a + GOT entry for. */ + +static __always_inline Elf32_Addr +elf_machine_load_address(void) +{ + Elf32_Addr gotaddr_diff; + +#ifdef __arch_v32 + extern char ___CRISv32_dummy[] __asm__ ("_dl_start"); + + __asm__ ("addo.w _dl_start:GOT16,$r0,$acr\n\t" + "lapc _dl_start,%0\n\t" + "sub.d [$acr],%0" + /* For v32, we need to force GCC to have R0 loaded with + _GLOBAL_OFFSET_TABLE_ at this point, which might not + otherwise have happened in the caller. (For v10, it's + loaded for non-global variables too, so we don't need + anything special there.) We accomplish this by faking the + address of a global variable (as seen by GCC) as input to + the asm; that address calculation goes through the GOT. + Use of this function happens before we've filled in the + GOT, so the address itself will not be correctly + calculated, therefore we don't use any symbol whose + address may be re-used later on. Let's just reuse the + _dl_start symbol, faking it as a global by renaming it as + another variable through an asm. */ + : "=r" (gotaddr_diff) + : "g" (___CRISv32_dummy) + : "acr"); +#else + __asm__ ("sub.d [$r0+_dl_start:GOT16],$r0,%0\n\t" + "add.d _dl_start:GOTOFF,%0" : "=r" (gotaddr_diff)); +#endif + return gotaddr_diff; +} + +static __always_inline void +elf_machine_relative(Elf32_Addr load_off, const Elf32_Addr rel_addr, + Elf32_Word relative_count) +{ + Elf32_Rela *rpnt = (void *)rel_addr; + + --rpnt; + do { + Elf32_Addr *const reloc_addr = + (void *)(load_off + (++rpnt)->r_offset); + + *reloc_addr = load_off + rpnt->r_addend; + } while (--relative_count); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/cris/elfinterp.c b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/cris/elfinterp.c new file mode 100644 index 00000000..3cb8297e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/cris/elfinterp.c @@ -0,0 +1,289 @@ +/* + * CRIS ELF shared library loader support. + * + * Program to load an elf binary on a linux system, and run it. + * References to symbols in sharable libraries can be resolved + * by either an ELF sharable library or a linux style of shared + * library. + * + * Copyright (C) 2002-2004, Axis Communications AB + * All rights reserved + * + * Author: Tobias Anderberg, + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. The name of the above contributors may not be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "ldso.h" + +/* Defined in resolve.S. */ +extern int _dl_linux_resolve(void); + +unsigned long +_dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry) +{ + int symtab_index; + char *strtab; + char *symname; + char *new_addr; + char *rel_addr; + char **got_addr; + Elf32_Sym *symtab; + ELF_RELOC *this_reloc; + unsigned long instr_addr; + + rel_addr = (char *)tpnt->dynamic_info[DT_JMPREL]; + + this_reloc = (ELF_RELOC *)(intptr_t)(rel_addr + reloc_entry); + symtab_index = ELF32_R_SYM(this_reloc->r_info); + + symtab = (Elf32_Sym *)(intptr_t)tpnt->dynamic_info[DT_SYMTAB]; + strtab = (char *)tpnt->dynamic_info[DT_STRTAB]; + symname = strtab + symtab[symtab_index].st_name; + + /* Address of the jump instruction to fix up. */ + instr_addr = ((unsigned long)this_reloc->r_offset + + (unsigned long)tpnt->loadaddr); + got_addr = (char **)instr_addr; + + /* Get the address of the GOT entry. */ + new_addr = _dl_find_hash(symname, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL); + if (unlikely(!new_addr)) { + _dl_dprintf(2, "%s: Can't resolve symbol '%s'\n", _dl_progname, symname); + _dl_exit(1); + } + +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_bindings) { + _dl_dprintf(_dl_debug_file, "\nresolve function: %s", symname); + if (_dl_debug_detail) + _dl_dprintf(_dl_debug_file, + "\n\tpatched: %x ==> %x @ %x\n", + *got_addr, new_addr, got_addr); + } + if (!_dl_debug_nofixups) { + *got_addr = new_addr; + } +#else + *got_addr = new_addr; +#endif + + return (unsigned long)new_addr; +} + +static int +_dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope, + unsigned long rel_addr, unsigned long rel_size, + int (*reloc_fnc)(struct elf_resolve *tpnt, struct dyn_elf *scope, + ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)) +{ + int symtab_index; + unsigned int i; + char *strtab; + Elf32_Sym *symtab; + ELF_RELOC *rpnt; + + /* Parse the relocation information. */ + rpnt = (ELF_RELOC *)(intptr_t)rel_addr; + rel_size /= sizeof(ELF_RELOC); + + symtab = (Elf32_Sym *)(intptr_t)tpnt->dynamic_info[DT_SYMTAB]; + strtab = (char *)tpnt->dynamic_info[DT_STRTAB]; + + for (i = 0; i < rel_size; i++, rpnt++) { + int res; + + symtab_index = ELF32_R_SYM(rpnt->r_info); + + debug_sym(symtab, strtab, symtab_index); + debug_reloc(symtab, strtab, rpnt); + + /* Pass over to actual relocation function. */ + res = reloc_fnc(tpnt, scope, rpnt, symtab, strtab); + + if (res == 0) + continue; + + _dl_dprintf(2, "\n%s: ", _dl_progname); + + if (symtab_index) + _dl_dprintf(2, "symbol '%s': ", + strtab + symtab[symtab_index].st_name); + + if (unlikely(res < 0)) { + int reloc_type = ELF32_R_TYPE(rpnt->r_info); + +#if defined (__SUPPORT_LD_DEBUG__) + _dl_dprintf(2, "can't handle reloc type %s\n", + _dl_reltypes(reloc_type)); +#else + _dl_dprintf(2, "can't handle reloc type %x\n", + reloc_type); +#endif + _dl_exit(-res); + } else if (unlikely(res > 0)) { + _dl_dprintf(2, "can't resolve symbol\n"); + return res; + } + } + + return 0; +} + +static int +_dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, + ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab) +{ + int reloc_type; + int symtab_index; + char *symname; + unsigned long *reloc_addr; + unsigned long symbol_addr; +#if defined (__SUPPORT_LD_DEBUG__) + unsigned long old_val; +#endif + struct symbol_ref sym_ref; + + reloc_addr = (unsigned long *)(intptr_t)(tpnt->loadaddr + (unsigned long)rpnt->r_offset); + reloc_type = ELF32_R_TYPE(rpnt->r_info); + symtab_index = ELF32_R_SYM(rpnt->r_info); + symbol_addr = 0; + sym_ref.sym = &symtab[symtab_index]; + sym_ref.tpnt = NULL; + symname = strtab + symtab[symtab_index].st_name; + + if (symtab_index) { + if (symtab[symtab_index].st_shndx != SHN_UNDEF && + ELF32_ST_BIND(symtab[symtab_index].st_info) == STB_LOCAL) { + symbol_addr = (unsigned long)tpnt->loadaddr; + } else { + symbol_addr = (unsigned long)_dl_find_hash(symname, scope, tpnt, + elf_machine_type_class(reloc_type), &sym_ref); + } + + if (unlikely(!symbol_addr && ELF32_ST_BIND(symtab[symtab_index].st_info) != STB_WEAK)) { + _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", _dl_progname, symname); + _dl_exit(1); + } + + symbol_addr += rpnt->r_addend; + } + +#if defined (__SUPPORT_LD_DEBUG__) + old_val = *reloc_addr; +#endif + + switch (reloc_type) { + case R_CRIS_NONE: + break; + case R_CRIS_GLOB_DAT: + case R_CRIS_JUMP_SLOT: + case R_CRIS_32: + *reloc_addr = symbol_addr; + break; + case R_CRIS_COPY: +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_move) + _dl_dprintf(_dl_debug_file, + "\n%s move %d bytes from %x to %x", + symname, symtab[symtab_index].st_size, + symbol_addr, reloc_addr); +#endif + + _dl_memcpy((char *)reloc_addr, + (char *)symbol_addr, + symtab[symtab_index].st_size); + break; + case R_CRIS_RELATIVE: + *reloc_addr = (unsigned long)tpnt->loadaddr + rpnt->r_addend; + break; + default: + return -1; /* Calls _dl_exit(1). */ + } + +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_reloc && _dl_debug_detail) + _dl_dprintf(_dl_debug_file, "\n\tpatched: %x ==> %x @ %x\n", + old_val, *reloc_addr, reloc_addr); +#endif + + return 0; +} + +static int +_dl_do_lazy_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, + ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab) +{ + int reloc_type; + unsigned long *reloc_addr; +#if defined (__SUPPORT_LD_DEBUG__) + unsigned long old_val; +#endif + + /* Don't care about these, just keep the compiler happy. */ + (void)scope; + (void)symtab; + (void)strtab; + + reloc_addr = (unsigned long *)(intptr_t)(tpnt->loadaddr + (unsigned long)rpnt->r_offset); + reloc_type = ELF32_R_TYPE(rpnt->r_info); + +#if defined (__SUPPORT_LD_DEBUG__) + old_val = *reloc_addr; +#endif + + switch (reloc_type) { + case R_CRIS_NONE: + break; + case R_CRIS_JUMP_SLOT: + *reloc_addr += (unsigned long)tpnt->loadaddr; + break; + default: + return -1; /* Calls _dl_exit(1). */ + } + +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_reloc && _dl_debug_detail) + _dl_dprintf(_dl_debug_file, "\n\tpatched: %x ==> %x @ %x\n", + old_val, *reloc_addr, reloc_addr); +#endif + + return 0; +} + +/* External interface to the generic part of the dynamic linker. */ + +void +_dl_parse_lazy_relocation_information(struct dyn_elf *rpnt, + unsigned long rel_addr, + unsigned long rel_size) +{ + (void)_dl_parse(rpnt->dyn, NULL, rel_addr, rel_size, _dl_do_lazy_reloc); +} + +int +_dl_parse_relocation_information(struct dyn_elf *rpnt, + unsigned long rel_addr, + unsigned long rel_size) +{ + return _dl_parse(rpnt->dyn, rpnt->dyn->symbol_scope, rel_addr, rel_size, _dl_do_reloc); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/cris/resolve.S b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/cris/resolve.S new file mode 100644 index 00000000..9ca27b5e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/cris/resolve.S @@ -0,0 +1,89 @@ +/* + * This function is _not_ called directly. It is jumped to from PLT when + * attempting to use a symbol that has not yet been resolved. The first time a + * jump symbol (such as a function call inside a shared library) is used + * (before it gets resolved) it will jump here. When we get called the stack + * contains reloc_offset and tpnt is in MOF. + * + * We save all the registers, setup R10 and R11 with the right arguments then + * call _dl_linux_resolver(tpnt, reloc_offset). _dl_linux_resolver() figures + * out where the jump symbol is _really_ supposed to have jumped to and returns + * that to us. Once we have that, we overwrite tpnt with this fixed up + * address. We then clean up after ourselves, put all the registers back how we + * found them, then we jump to where the fixed up address, which is where the + * jump symbol that got us here really wanted to jump to in the first place. + */ + +.globl _dl_linux_resolve +.type _dl_linux_resolve,@function + +#ifdef __arch_v32 + +_dl_linux_resolve: + subq 4,$sp + move.d $r0,[$sp] + subq 4,$sp + move.d $r13,[$sp] + subq 4,$sp + move.d $r12,[$sp] + subq 4,$sp + move.d $r11,[$sp] + subq 4,$sp + addoq 5*4,$sp,$acr + move.d $r10,[$sp] + subq 4,$sp + move $mof,$r10 + move.d $r9,[$sp] + subq 4,$sp + move.d [$acr],$r11 + move $srp,[$sp] + lapc _GLOBAL_OFFSET_TABLE_,$r0 + move.d _dl_linux_resolver:PLTG,$r9 + add.d $r0,$r9 + jsr $r9 + nop + move.d $r10,$acr + move [$sp+],$srp + move.d [$sp+],$r9 + move.d [$sp+],$r10 + move.d [$sp+],$r11 + move.d [$sp+],$r12 + move.d [$sp+],$r13 + move.d [$sp+],$r0 + jump $acr + addq 4,$sp + +#else + +_dl_linux_resolve: + push $r13 + push $r12 + push $r11 + push $r10 + push $r9 + push $r0 + push $srp + move.d [$sp+7*4],$r11 + move $mof,$r10 +#ifdef __PIC__ + move.d $pc,$r0 + sub.d .:GOTOFF,$r0 + move.d _dl_linux_resolver:PLTG,$r9 + add.d $r0,$r9 + jsr $r9 +#else + jsr _dl_linux_resolver +#endif + move.d $r10,[$sp+7*4] + pop $srp + pop $r0 + pop $r9 + pop $r10 + pop $r11 + pop $r12 + pop $r13 + jump [$sp+] + +#endif /* __arch_v32 */ + + .size _dl_linux_resolve, . - _dl_linux_resolve diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/dl-array.c b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/dl-array.c new file mode 100644 index 00000000..dabb466f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/dl-array.c @@ -0,0 +1,84 @@ +/* vi: set sw=4 ts=4: */ +/* + * This file contains the helper routines to run init and fini functions. + * + * Copyright (C) 2000-2006 by Erik Andersen + * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald, + * David Engel, Hongjiu Lu and Mitch D'Souza + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. The name of the above contributors may not be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#include "ldso.h" + +static void _dl_run_array_forward(unsigned long array, unsigned long size, + DL_LOADADDR_TYPE loadaddr) +{ + if (array != 0) { + unsigned int j; + unsigned int jm; + ElfW(Addr) *addrs; + jm = size / sizeof (ElfW(Addr)); + addrs = (ElfW(Addr) *) DL_RELOC_ADDR(loadaddr, array); + for (j = 0; j < jm; ++j) { + void (*dl_elf_func) (void); + dl_elf_func = (void (*)(void)) (intptr_t) addrs[j]; + DL_CALL_FUNC_AT_ADDR (dl_elf_func, loadaddr, (void (*)(void))); + } + } +} + +void _dl_run_init_array(struct elf_resolve *tpnt); +void _dl_run_init_array(struct elf_resolve *tpnt) +{ + _dl_run_array_forward(tpnt->dynamic_info[DT_INIT_ARRAY], + tpnt->dynamic_info[DT_INIT_ARRAYSZ], + tpnt->loadaddr); +} + +void _dl_app_init_array(void); +void _dl_app_init_array(void) +{ + _dl_run_init_array(_dl_loaded_modules); +} + +void _dl_run_fini_array(struct elf_resolve *tpnt); +void _dl_run_fini_array(struct elf_resolve *tpnt) +{ + if (tpnt->dynamic_info[DT_FINI_ARRAY]) { + ElfW(Addr) *array = (ElfW(Addr) *) DL_RELOC_ADDR(tpnt->loadaddr, tpnt->dynamic_info[DT_FINI_ARRAY]); + unsigned int i = (tpnt->dynamic_info[DT_FINI_ARRAYSZ] / sizeof(ElfW(Addr))); + while (i-- > 0) { + void (*dl_elf_func) (void); + dl_elf_func = (void (*)(void)) (intptr_t) array[i]; + DL_CALL_FUNC_AT_ADDR (dl_elf_func, tpnt->loadaddr, (void (*)(void))); + } + } +} + +void _dl_app_fini_array(void); +void _dl_app_fini_array(void) +{ + _dl_run_fini_array(_dl_loaded_modules); +} + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/dl-debug.c b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/dl-debug.c new file mode 100644 index 00000000..7ce8bfbc --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/dl-debug.c @@ -0,0 +1,106 @@ +/* vi: set sw=4 ts=4: */ +/* common debug code for ELF shared library loader + * + * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald, + * David Engel, Hongjiu Lu and Mitch D'Souza + * Copyright (C) 2001-2004 Erik Andersen + * Copyright (C) 2002-2004, Axis Communications AB + * Copyright (C) 2003, 2004 Red Hat, Inc. + * Copyright (C) 2002, Steven J. Hill (sjhill@realitydiluted.com) + * Copyright (C) 2001-2002 David A. Schleef + * Copyright (C) 2004 Joakim Tjernlund + * Copyright (C) 2002, Stefan Allius and + * Eddie C. Dost + * Copyright (C) 2003, 2004, 2005 Paul Mundt + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. The name of the above contributors may not be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "ldso.h" + +#if defined (__SUPPORT_LD_DEBUG__) + +/* include the arch-specific _dl_reltypes_tab */ +#include "dl-debug.h" + +static const char *_dl_reltypes(int type) +{ + static char buf[50]; + const char *str; + int tabsize; + + tabsize = (int)(sizeof(_dl_reltypes_tab) / sizeof(_dl_reltypes_tab[0])); + + if (type >= tabsize || (str = _dl_reltypes_tab[type]) == NULL) + str = _dl_simple_ltoa(buf, (unsigned long)type); + + return str; +} +static void debug_sym(ElfW(Sym) *symtab, char *strtab, int symtab_index) +{ + if (!_dl_debug_symbols || !symtab_index) + return; + + _dl_dprintf(_dl_debug_file, + "\n%s\n\tvalue=%x\tsize=%x\tinfo=%x\tother=%x\tshndx=%x", + strtab + symtab[symtab_index].st_name, + symtab[symtab_index].st_value, + symtab[symtab_index].st_size, + symtab[symtab_index].st_info, + symtab[symtab_index].st_other, + symtab[symtab_index].st_shndx); +} + +static void debug_reloc(ElfW(Sym) *symtab, char *strtab, ELF_RELOC *rpnt) +{ + if (!_dl_debug_reloc) + return; + + if (_dl_debug_symbols) { + _dl_dprintf(_dl_debug_file, "\n\t"); + } else { + int symtab_index; + const char *sym; + + symtab_index = ELF_R_SYM(rpnt->r_info); + sym = symtab_index ? strtab + symtab[symtab_index].st_name : "sym=0x0"; + + _dl_dprintf(_dl_debug_file, "\n%s\n\t", sym); + } + + _dl_dprintf(_dl_debug_file, "%s\toffset=%x", + _dl_reltypes(ELF_R_TYPE(rpnt->r_info)), + rpnt->r_offset); +#ifdef ELF_USES_RELOCA + _dl_dprintf(_dl_debug_file, "\taddend=%x", rpnt->r_addend); +#endif + _dl_dprintf(_dl_debug_file, "\n"); +} + +#else + +#define debug_sym(symtab, strtab, symtab_index) +#define debug_reloc(symtab, strtab, rpnt) + +#endif /* __SUPPORT_LD_DEBUG__ */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/dl-elf.c b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/dl-elf.c new file mode 100644 index 00000000..a63b997c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/dl-elf.c @@ -0,0 +1,1074 @@ +/* vi: set sw=4 ts=4: */ +/* + * This file contains the helper routines to load an ELF shared + * library into memory and add the symbol table info to the chain. + * + * Copyright (C) 2000-2006 by Erik Andersen + * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald, + * David Engel, Hongjiu Lu and Mitch D'Souza + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. The name of the above contributors may not be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#include "ldso.h" + +#ifdef __LDSO_CACHE_SUPPORT__ + +static caddr_t _dl_cache_addr = NULL; +static size_t _dl_cache_size = 0; + +int _dl_map_cache(void) +{ + int fd; + struct stat st; + header_t *header; + libentry_t *libent; + int i, strtabsize; + + if (_dl_cache_addr == MAP_FAILED) + return -1; + else if (_dl_cache_addr != NULL) + return 0; + + if (_dl_stat(LDSO_CACHE, &st) + || (fd = _dl_open(LDSO_CACHE, O_RDONLY|O_CLOEXEC, 0)) < 0) { + _dl_cache_addr = MAP_FAILED; /* so we won't try again */ + return -1; + } + + _dl_cache_size = st.st_size; + _dl_cache_addr = _dl_mmap(0, _dl_cache_size, PROT_READ, LDSO_CACHE_MMAP_FLAGS, fd, 0); + _dl_close(fd); + if (_dl_mmap_check_error(_dl_cache_addr)) { + _dl_dprintf(2, "%s:%i: can't map '%s'\n", + _dl_progname, __LINE__, LDSO_CACHE); + return -1; + } + + header = (header_t *) _dl_cache_addr; + + if (_dl_cache_size < sizeof(header_t) || + _dl_memcmp(header->magic, LDSO_CACHE_MAGIC, LDSO_CACHE_MAGIC_LEN) + || _dl_memcmp(header->version, LDSO_CACHE_VER, LDSO_CACHE_VER_LEN) + || _dl_cache_size < + (sizeof(header_t) + header->nlibs * sizeof(libentry_t)) + || _dl_cache_addr[_dl_cache_size - 1] != '\0') + { + _dl_dprintf(2, "%s: cache '%s' is corrupt\n", _dl_progname, + LDSO_CACHE); + goto fail; + } + + strtabsize = _dl_cache_size - sizeof(header_t) - + header->nlibs * sizeof(libentry_t); + libent = (libentry_t *) & header[1]; + + for (i = 0; i < header->nlibs; i++) { + if (libent[i].sooffset >= strtabsize || + libent[i].liboffset >= strtabsize) + { + _dl_dprintf(2, "%s: cache '%s' is corrupt\n", _dl_progname, LDSO_CACHE); + goto fail; + } + } + + return 0; + +fail: + _dl_munmap(_dl_cache_addr, _dl_cache_size); + _dl_cache_addr = MAP_FAILED; + return -1; +} + +int _dl_unmap_cache(void) +{ + if (_dl_cache_addr == NULL || _dl_cache_addr == MAP_FAILED) + return -1; + +#if 1 + _dl_munmap(_dl_cache_addr, _dl_cache_size); + _dl_cache_addr = NULL; +#endif + + return 0; +} +#endif + + +void +_dl_protect_relro (struct elf_resolve *l) +{ + ElfW(Addr) base = (ElfW(Addr)) DL_RELOC_ADDR(l->loadaddr, l->relro_addr); + ElfW(Addr) start = (base & PAGE_ALIGN); + ElfW(Addr) end = ((base + l->relro_size) & PAGE_ALIGN); + _dl_if_debug_dprint("RELRO protecting %s: start:%x, end:%x\n", l->libname, start, end); + if (start != end && + _dl_mprotect ((void *) start, end - start, PROT_READ) < 0) { + _dl_dprintf(2, "%s: cannot apply additional memory protection after relocation", l->libname); + _dl_exit(0); + } +} + +/* This function's behavior must exactly match that + * in uClibc/ldso/util/ldd.c */ +static struct elf_resolve * +search_for_named_library(const char *name, int secure, const char *path_list, + struct dyn_elf **rpnt) +{ + char *path, *path_n, *mylibname; + struct elf_resolve *tpnt; + int done; + + if (path_list==NULL) + return NULL; + + /* We need a writable copy of this string, but we don't + * need this allocated permanently since we don't want + * to leak memory, so use alloca to put path on the stack */ + done = _dl_strlen(path_list); + path = alloca(done + 1); + + /* another bit of local storage */ + mylibname = alloca(2050); + + _dl_memcpy(path, path_list, done+1); + + /* Unlike ldd.c, don't bother to eliminate double //s */ + + /* Replace colons with zeros in path_list */ + /* : at the beginning or end of path maps to CWD */ + /* :: anywhere maps CWD */ + /* "" maps to CWD */ + done = 0; + path_n = path; + do { + if (*path == 0) { + *path = ':'; + done = 1; + } + if (*path == ':') { + *path = 0; + if (*path_n) + _dl_strcpy(mylibname, path_n); + else + _dl_strcpy(mylibname, "."); /* Assume current dir if empty path */ + _dl_strcat(mylibname, "/"); + _dl_strcat(mylibname, name); + if ((tpnt = _dl_load_elf_shared_library(secure, rpnt, mylibname)) != NULL) + return tpnt; + path_n = path+1; + } + path++; + } while (!done); + return NULL; +} + +/* Used to return error codes back to dlopen et. al. */ +unsigned long _dl_error_number; +unsigned long _dl_internal_error_number; + +struct elf_resolve *_dl_load_shared_library(int secure, struct dyn_elf **rpnt, + struct elf_resolve *tpnt, char *full_libname, int __attribute__((unused)) trace_loaded_objects) +{ (void)tpnt; + char *pnt; + struct elf_resolve *tpnt1; + char *libname; + + _dl_internal_error_number = 0; + libname = full_libname; + + /* quick hack to ensure mylibname buffer doesn't overflow. don't + allow full_libname or any directory to be longer than 1024. */ + if (_dl_strlen(full_libname) > 1024) + goto goof; + + /* Skip over any initial initial './' and '/' stuff to + * get the short form libname with no path garbage */ + pnt = _dl_strrchr(libname, '/'); + if (pnt) { + libname = pnt + 1; + } + + _dl_if_debug_dprint("\tfind library='%s'; searching\n", libname); + /* If the filename has any '/', try it straight and leave it at that. + For IBCS2 compatibility under linux, we substitute the string + /usr/i486-sysv4/lib for /usr/lib in library names. */ + + if (libname != full_libname) { + _dl_if_debug_dprint("\ttrying file='%s'\n", full_libname); + tpnt1 = _dl_load_elf_shared_library(secure, rpnt, full_libname); + if (tpnt1) { + return tpnt1; + } + } + + /* + * The ABI specifies that RPATH is searched before LD_LIBRARY_PATH or + * the default path of /usr/lib. Check in rpath directories. + */ +#ifdef __LDSO_RUNPATH__ + pnt = (tpnt ? (char *) tpnt->dynamic_info[DT_RPATH] : NULL); + if (pnt) { + pnt += (unsigned long) tpnt->dynamic_info[DT_STRTAB]; + _dl_if_debug_dprint("\tsearching RPATH='%s'\n", pnt); + if ((tpnt1 = search_for_named_library(libname, secure, pnt, rpnt)) != NULL) + return tpnt1; + } +#endif + + /* Check in LD_{ELF_}LIBRARY_PATH, if specified and allowed */ + if (_dl_library_path) { + _dl_if_debug_dprint("\tsearching LD_LIBRARY_PATH='%s'\n", _dl_library_path); + if ((tpnt1 = search_for_named_library(libname, secure, _dl_library_path, rpnt)) != NULL) + { + return tpnt1; + } + } + + /* + * The ABI specifies that RUNPATH is searched after LD_LIBRARY_PATH. + */ +#ifdef __LDSO_RUNPATH__ + pnt = (tpnt ? (char *)tpnt->dynamic_info[DT_RUNPATH] : NULL); + if (pnt) { + pnt += (unsigned long) tpnt->dynamic_info[DT_STRTAB]; + _dl_if_debug_dprint("\tsearching RUNPATH='%s'\n", pnt); + if ((tpnt1 = search_for_named_library(libname, secure, pnt, rpnt)) != NULL) + return tpnt1; + } +#endif + + /* + * Where should the cache be searched? There is no such concept in the + * ABI, so we have some flexibility here. For now, search it before + * the hard coded paths that follow (i.e before /lib and /usr/lib). + */ +#ifdef __LDSO_CACHE_SUPPORT__ + if (_dl_cache_addr != NULL && _dl_cache_addr != MAP_FAILED) { + int i; + header_t *header = (header_t *) _dl_cache_addr; + libentry_t *libent = (libentry_t *) & header[1]; + char *strs = (char *) &libent[header->nlibs]; + + _dl_if_debug_dprint("\tsearching cache='%s'\n", LDSO_CACHE); + for (i = 0; i < header->nlibs; i++) { + if ((libent[i].flags == LIB_ELF + || libent[i].flags == LIB_ELF_LIBC0 + || libent[i].flags == LIB_ELF_LIBC5) + && _dl_strcmp(libname, strs + libent[i].sooffset) == 0 + && (tpnt1 = _dl_load_elf_shared_library(secure, rpnt, strs + libent[i].liboffset)) + ) { + return tpnt1; + } + } + } +#endif + + /* Look for libraries wherever the shared library loader + * was installed */ + _dl_if_debug_dprint("\tsearching ldso dir='%s'\n", _dl_ldsopath); + tpnt1 = search_for_named_library(libname, secure, _dl_ldsopath, rpnt); + if (tpnt1 != NULL) + return tpnt1; + + /* Lastly, search the standard list of paths for the library. + This list must exactly match the list in uClibc/ldso/util/ldd.c */ + _dl_if_debug_dprint("\tsearching full lib path list\n"); + tpnt1 = search_for_named_library(libname, secure, + UCLIBC_RUNTIME_PREFIX "lib:" + UCLIBC_RUNTIME_PREFIX "usr/lib" +#ifndef __LDSO_CACHE_SUPPORT__ + ":" UCLIBC_RUNTIME_PREFIX "usr/X11R6/lib" +#endif + , rpnt); + if (tpnt1 != NULL) + return tpnt1; + +goof: + /* Well, we shot our wad on that one. All we can do now is punt */ + if (_dl_internal_error_number) + _dl_error_number = _dl_internal_error_number; + else + _dl_error_number = LD_ERROR_NOFILE; + _dl_if_debug_dprint("Bummer: could not find '%s'!\n", libname); + return NULL; +} + + +/* + * Read one ELF library into memory, mmap it into the correct locations and + * add the symbol info to the symbol chain. Perform any relocations that + * are required. + */ + +struct elf_resolve *_dl_load_elf_shared_library(int secure, + struct dyn_elf **rpnt, char *libname) +{ + ElfW(Ehdr) *epnt; + unsigned long dynamic_addr = 0; + ElfW(Dyn) *dpnt; + struct elf_resolve *tpnt; + ElfW(Phdr) *ppnt; +#if defined(USE_TLS) && USE_TLS + ElfW(Phdr) *tlsppnt = NULL; +#endif + char *status, *header; + unsigned long dynamic_info[DYNAMIC_SIZE]; + unsigned long *lpnt; + unsigned long libaddr; + unsigned long minvma = 0xffffffff, maxvma = 0; + unsigned int rtld_flags; + int i, flags, piclib, infile; + ElfW(Addr) relro_addr = 0; + size_t relro_size = 0; + struct stat st; + uint32_t *p32; + DL_LOADADDR_TYPE lib_loadaddr; + DL_INIT_LOADADDR_EXTRA_DECLS + + libaddr = 0; + infile = _dl_open(libname, O_RDONLY, 0); + if (infile < 0) { + _dl_internal_error_number = LD_ERROR_NOFILE; + return NULL; + } + + if (_dl_fstat(infile, &st) < 0) { + _dl_internal_error_number = LD_ERROR_NOFILE; + _dl_close(infile); + return NULL; + } + /* If we are in secure mode (i.e. a setu/gid binary using LD_PRELOAD), + we don't load the library if it isn't setuid. */ + if (secure) { + if (!(st.st_mode & S_ISUID)) { + _dl_close(infile); + return NULL; + } + } + + /* Check if file is already loaded */ + for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next) { +#ifndef __NOT_FOR_L4__ + if (_dl_cap_equal(tpnt->st_dev, st.st_dev)) { +#else + if (tpnt->st_dev == st.st_dev && tpnt->st_ino == st.st_ino) { +#endif + /* Already loaded */ + tpnt->usage_count++; + _dl_close(infile); + return tpnt; + } + } + header = _dl_mmap((void *) 0, _dl_pagesize, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS | MAP_UNINITIALIZE, -1, 0); + if (_dl_mmap_check_error(header)) { + _dl_dprintf(2, "%s:%i: can't map '%s'\n", _dl_progname, __LINE__, libname); + _dl_internal_error_number = LD_ERROR_MMAP_FAILED; + _dl_close(infile); + return NULL; + } + + _dl_read(infile, header, _dl_pagesize); + epnt = (ElfW(Ehdr) *) (intptr_t) header; + p32 = (uint32_t*)&epnt->e_ident; + if (*p32 != ELFMAG_U32) { + _dl_dprintf(2, "%s: '%s' is not an ELF file\n", _dl_progname, + libname); + _dl_internal_error_number = LD_ERROR_NOTELF; + _dl_close(infile); + _dl_munmap(header, _dl_pagesize); + return NULL; + } + + if ((epnt->e_type != ET_DYN) || (epnt->e_machine != MAGIC1 +#ifdef MAGIC2 + && epnt->e_machine != MAGIC2 +#endif + )) + { + _dl_internal_error_number = + (epnt->e_type != ET_DYN ? LD_ERROR_NOTDYN : LD_ERROR_NOTMAGIC); + _dl_dprintf(2, "%s: '%s' is not an ELF executable for " ELF_TARGET + "\n", _dl_progname, libname); + _dl_close(infile); + _dl_munmap(header, _dl_pagesize); + return NULL; + } + + ppnt = (ElfW(Phdr) *)(intptr_t) & header[epnt->e_phoff]; + + piclib = 1; + for (i = 0; i < epnt->e_phnum; i++) { + + if (ppnt->p_type == PT_DYNAMIC) { + if (dynamic_addr) + _dl_dprintf(2, "%s: '%s' has more than one dynamic section\n", + _dl_progname, libname); + dynamic_addr = ppnt->p_vaddr; + } + + if (ppnt->p_type == PT_LOAD) { + /* See if this is a PIC library. */ + if (i == 0 && ppnt->p_vaddr > 0x1000000) { + piclib = 0; + minvma = ppnt->p_vaddr; + } + if (piclib && ppnt->p_vaddr < minvma) { + minvma = ppnt->p_vaddr; + } + if (((unsigned long) ppnt->p_vaddr + ppnt->p_memsz) > maxvma) { + maxvma = ppnt->p_vaddr + ppnt->p_memsz; + } + } + if (ppnt->p_type == PT_TLS) { +#if defined(USE_TLS) && USE_TLS + if (ppnt->p_memsz == 0) + /* Nothing to do for an empty segment. */ + continue; + else + /* Save for after 'tpnt' is actually allocated. */ + tlsppnt = ppnt; +#else + /* + * Yup, the user was an idiot and tried to sneak in a library with + * TLS in it and we don't support it. Let's fall on our own sword + * and scream at the luser while we die. + */ + _dl_dprintf(2, "%s: '%s' library contains unsupported TLS\n", + _dl_progname, libname); + _dl_internal_error_number = LD_ERROR_TLS_FAILED; + _dl_close(infile); + _dl_munmap(header, _dl_pagesize); + return NULL; +#endif + } + ppnt++; + } + + DL_CHECK_LIB_TYPE (epnt, piclib, _dl_progname, libname); + + maxvma = (maxvma + ADDR_ALIGN) & PAGE_ALIGN; + minvma = minvma & ~ADDR_ALIGN; + + flags = MAP_PRIVATE /*| MAP_DENYWRITE */ ; + if (!piclib) + flags |= MAP_FIXED; + + if (piclib == 0 || piclib == 1) { +#ifdef __NOT_FOR_L4__ + status = (char *) _dl_mmap((char *) (piclib ? 0 : minvma), + maxvma - minvma, PROT_NONE, flags | MAP_ANONYMOUS, -1, 0); +#else + status = (char *) _dl_mmap((char *) (piclib ? 0 : minvma), + maxvma - minvma, PROT_NONE, flags | MAP_ANONYMOUS | 0x1000000, -1, 0); +#endif + if (_dl_mmap_check_error(status)) { + _dl_dprintf(2, "%s:%i: can't map '%s'\n", _dl_progname, __LINE__, libname); + _dl_internal_error_number = LD_ERROR_MMAP_FAILED; + _dl_close(infile); + _dl_munmap(header, _dl_pagesize); + return NULL; + } + libaddr = (unsigned long) status; + flags |= MAP_FIXED; + } + + /* Get the memory to store the library */ + ppnt = (ElfW(Phdr) *)(intptr_t) & header[epnt->e_phoff]; + + DL_INIT_LOADADDR(lib_loadaddr, libaddr, ppnt, epnt->e_phnum); + + for (i = 0; i < epnt->e_phnum; i++) { + if (DL_IS_SPECIAL_SEGMENT (epnt, ppnt)) { + char *addr; + + addr = DL_MAP_SEGMENT (epnt, ppnt, infile, flags); + if (addr == NULL) + goto cant_map; + + DL_INIT_LOADADDR_HDR (lib_loadaddr, addr, ppnt); + ppnt++; + continue; + } + if (ppnt->p_type == PT_GNU_RELRO) { + relro_addr = ppnt->p_vaddr; + relro_size = ppnt->p_memsz; + } + if (ppnt->p_type == PT_LOAD) { + char *tryaddr; + ssize_t size; + + /* See if this is a PIC library. */ + if (i == 0 && ppnt->p_vaddr > 0x1000000) { + piclib = 0; + /* flags |= MAP_FIXED; */ + } + + if (ppnt->p_flags & PF_W) { + unsigned long map_size; + char *cpnt; + char *piclib2map = 0; + + if (piclib == 2 && + /* We might be able to avoid this + call if memsz doesn't require + an additional page, but this + would require mmap to always + return page-aligned addresses + and a whole number of pages + allocated. Unfortunately on + uClinux may return misaligned + addresses and may allocate + partial pages, so we may end up + doing unnecessary mmap calls. + + This is what we could do if we + knew mmap would always return + aligned pages: + + ((ppnt->p_vaddr + ppnt->p_filesz + + ADDR_ALIGN) + & PAGE_ALIGN) + < ppnt->p_vaddr + ppnt->p_memsz) + + Instead, we have to do this: */ + ppnt->p_filesz < ppnt->p_memsz) + { + piclib2map = (char *) + _dl_mmap(0, (ppnt->p_vaddr & ADDR_ALIGN) + + ppnt->p_memsz, + LXFLAGS(ppnt->p_flags), + flags | MAP_ANONYMOUS, -1, 0); + if (_dl_mmap_check_error(piclib2map)) + goto cant_map; + DL_INIT_LOADADDR_HDR + (lib_loadaddr, piclib2map + + (ppnt->p_vaddr & ADDR_ALIGN), ppnt); + } + + tryaddr = piclib == 2 ? piclib2map + : ((char*) (piclib ? libaddr : 0) + + (ppnt->p_vaddr & PAGE_ALIGN)); + + size = (ppnt->p_vaddr & ADDR_ALIGN) + + ppnt->p_filesz; + + /* For !MMU, mmap to fixed address will fail. + So instead of desperately call mmap and fail, + we set status to MAP_FAILED to save a call + to mmap (). */ +#ifndef __ARCH_USE_MMU__ + if (piclib2map == 0) +#endif + status = (char *) _dl_mmap + (tryaddr, size, LXFLAGS(ppnt->p_flags), + flags | (piclib2map ? MAP_FIXED : 0), + infile, ppnt->p_offset & OFFS_ALIGN); +#ifndef __ARCH_USE_MMU__ + else + status = MAP_FAILED; +#endif +#ifdef _DL_PREAD + if (_dl_mmap_check_error(status) && piclib2map + && (_DL_PREAD (infile, tryaddr, size, + ppnt->p_offset & OFFS_ALIGN) + == size)) + status = tryaddr; +#endif + if (_dl_mmap_check_error(status) + || (tryaddr && tryaddr != status)) { + cant_map: + _dl_dprintf(2, "%s:%i: can't map '%s'\n", + _dl_progname, __LINE__, libname); + _dl_internal_error_number = LD_ERROR_MMAP_FAILED; + DL_LOADADDR_UNMAP (lib_loadaddr, maxvma - minvma); + _dl_close(infile); + _dl_munmap(header, _dl_pagesize); + return NULL; + } + + if (! piclib2map) { + DL_INIT_LOADADDR_HDR + (lib_loadaddr, status + + (ppnt->p_vaddr & ADDR_ALIGN), ppnt); + } + /* Now we want to allocate and + zero-out any data from the end of + the region we mapped in from the + file (filesz) to the end of the + loadable segment (memsz). We may + need additional pages for memsz, + that we map in below, and we can + count on the kernel to zero them + out, but we have to zero out stuff + in the last page that we mapped in + from the file. However, we can't + assume to have actually obtained + full pages from the kernel, since + we didn't ask for them, and uClibc + may not give us full pages for + small allocations. So only zero + out up to memsz or the end of the + page, whichever comes first. */ + + /* CPNT is the beginning of the memsz + portion not backed by filesz. */ + cpnt = (char *) (status + size); + + /* MAP_SIZE is the address of the + beginning of the next page. */ + map_size = (ppnt->p_vaddr + ppnt->p_filesz + + ADDR_ALIGN) & PAGE_ALIGN; + +#ifndef MIN +# define MIN(a,b) ((a) < (b) ? (a) : (b)) +#endif + _dl_memset (cpnt, 0, + MIN (map_size + - (ppnt->p_vaddr + + ppnt->p_filesz), + ppnt->p_memsz + - ppnt->p_filesz)); + + if (map_size < ppnt->p_vaddr + ppnt->p_memsz + && !piclib2map) { + tryaddr = map_size + (char*)(piclib ? libaddr : 0); + status = (char *) _dl_mmap(tryaddr, + ppnt->p_vaddr + ppnt->p_memsz - map_size, + LXFLAGS(ppnt->p_flags), flags | MAP_ANONYMOUS | MAP_FIXED, -1, 0); + if (_dl_mmap_check_error(status) + || tryaddr != status) + goto cant_map; + } + } else { + tryaddr = (piclib == 2 ? 0 + : (char *) (ppnt->p_vaddr & PAGE_ALIGN) + + (piclib ? libaddr : 0)); + size = (ppnt->p_vaddr & ADDR_ALIGN) + ppnt->p_filesz; + status = (char *) _dl_mmap + (tryaddr, size, LXFLAGS(ppnt->p_flags), + flags | (piclib == 2 ? MAP_EXECUTABLE + | MAP_DENYWRITE : 0), + infile, ppnt->p_offset & OFFS_ALIGN); + if (_dl_mmap_check_error(status) + || (tryaddr && tryaddr != status)) + goto cant_map; + DL_INIT_LOADADDR_HDR + (lib_loadaddr, status + + (ppnt->p_vaddr & ADDR_ALIGN), ppnt); + } + + /* if (libaddr == 0 && piclib) { + libaddr = (unsigned long) status; + flags |= MAP_FIXED; + } */ + } + ppnt++; + } + _dl_close(infile); + + /* For a non-PIC library, the addresses are all absolute */ + if (piclib) { + dynamic_addr = (unsigned long) DL_RELOC_ADDR(lib_loadaddr, dynamic_addr); + } + + /* + * OK, the ELF library is now loaded into VM in the correct locations + * The next step is to go through and do the dynamic linking (if needed). + */ + + /* Start by scanning the dynamic section to get all of the pointers */ + + if (!dynamic_addr) { + _dl_internal_error_number = LD_ERROR_NODYNAMIC; + _dl_dprintf(2, "%s: '%s' is missing a dynamic section\n", + _dl_progname, libname); + _dl_munmap(header, _dl_pagesize); + return NULL; + } + + dpnt = (ElfW(Dyn) *) dynamic_addr; + _dl_memset(dynamic_info, 0, sizeof(dynamic_info)); + rtld_flags = _dl_parse_dynamic_info(dpnt, dynamic_info, NULL, lib_loadaddr); + /* If the TEXTREL is set, this means that we need to make the pages + writable before we perform relocations. Do this now. They get set + back again later. */ + + if (dynamic_info[DT_TEXTREL]) { +#ifndef __FORCE_SHAREABLE_TEXT_SEGMENTS__ + ppnt = (ElfW(Phdr) *)(intptr_t) & header[epnt->e_phoff]; + for (i = 0; i < epnt->e_phnum; i++, ppnt++) { + if (ppnt->p_type == PT_LOAD && !(ppnt->p_flags & PF_W)) { + _dl_mprotect((void *) ((piclib ? libaddr : 0) + + (ppnt->p_vaddr & PAGE_ALIGN)), + (ppnt->p_vaddr & ADDR_ALIGN) + (unsigned long) ppnt->p_filesz, + PROT_READ | PROT_WRITE | PROT_EXEC); + } + } +#else + _dl_dprintf(_dl_debug_file, "Can't modify %s's text section." + " Use GCC option -fPIC for shared objects, please.\n", + libname); + _dl_exit(1); +#endif + } + + tpnt = _dl_add_elf_hash_table(libname, lib_loadaddr, dynamic_info, + dynamic_addr, 0); + tpnt->relro_addr = relro_addr; + tpnt->relro_size = relro_size; + tpnt->st_dev = st.st_dev; + tpnt->st_ino = st.st_ino; + tpnt->ppnt = (ElfW(Phdr) *) DL_RELOC_ADDR(tpnt->loadaddr, epnt->e_phoff); + tpnt->n_phent = epnt->e_phnum; + tpnt->rtld_flags |= rtld_flags; + +#if defined(USE_TLS) && USE_TLS + if (tlsppnt) { + _dl_debug_early("Found TLS header for %s\n", libname); +# if NO_TLS_OFFSET != 0 + tpnt->l_tls_offset = NO_TLS_OFFSET; +# endif + tpnt->l_tls_blocksize = tlsppnt->p_memsz; + tpnt->l_tls_align = tlsppnt->p_align; + if (tlsppnt->p_align == 0) + tpnt->l_tls_firstbyte_offset = 0; + else + tpnt->l_tls_firstbyte_offset = tlsppnt->p_vaddr & + (tlsppnt->p_align - 1); + tpnt->l_tls_initimage_size = tlsppnt->p_filesz; + tpnt->l_tls_initimage = (void *) tlsppnt->p_vaddr; + + /* Assign the next available module ID. */ + tpnt->l_tls_modid = _dl_next_tls_modid (); + + /* We know the load address, so add it to the offset. */ + if (tpnt->l_tls_initimage != NULL) + { +# ifdef __SUPPORT_LD_DEBUG_EARLY__ + unsigned int tmp = (unsigned int) tpnt->l_tls_initimage; + tpnt->l_tls_initimage = (char *) tlsppnt->p_vaddr + tpnt->loadaddr; + _dl_debug_early("Relocated TLS initial image from %x to %x (size = %x)\n", tmp, tpnt->l_tls_initimage, tpnt->l_tls_initimage_size); + tmp = 0; +# else + tpnt->l_tls_initimage = (char *) tlsppnt->p_vaddr + tpnt->loadaddr; +# endif + } + } +#endif + + /* + * Add this object into the symbol chain + */ + if (*rpnt) { + (*rpnt)->next = _dl_malloc(sizeof(struct dyn_elf)); + _dl_memset((*rpnt)->next, 0, sizeof(struct dyn_elf)); + (*rpnt)->next->prev = (*rpnt); + *rpnt = (*rpnt)->next; + } +#ifndef SHARED + /* When statically linked, the first time we dlopen a DSO + * the *rpnt is NULL, so we need to allocate memory for it, + * and initialize the _dl_symbol_table. + */ + else { + *rpnt = _dl_symbol_tables = _dl_malloc(sizeof(struct dyn_elf)); + _dl_memset(*rpnt, 0, sizeof(struct dyn_elf)); + } +#endif + (*rpnt)->dyn = tpnt; + tpnt->symbol_scope = _dl_symbol_tables; + tpnt->usage_count++; + tpnt->libtype = elf_lib; + + /* + * OK, the next thing we need to do is to insert the dynamic linker into + * the proper entry in the GOT so that the PLT symbols can be properly + * resolved. + */ + + lpnt = (unsigned long *) dynamic_info[DT_PLTGOT]; + + if (lpnt) { + lpnt = (unsigned long *) (dynamic_info[DT_PLTGOT]); + INIT_GOT(lpnt, tpnt); + } + +#ifdef __DSBT__ + /* Handle DSBT initialization */ + { + struct elf_resolve *t, *ref = NULL; + int idx = tpnt->loadaddr.map->dsbt_index; + unsigned *dsbt = tpnt->loadaddr.map->dsbt_table; + + if (idx == 0) { + /* This DSO has not been assigned an index */ + _dl_dprintf(2, "%s: '%s' is missing a dsbt index assignment!\n", + _dl_progname, libname); + _dl_exit(1); + } + + /* + * Setup dsbt slot for this module in dsbt of all modules. + */ + for (t = _dl_loaded_modules; t; t = t->next) { + /* find a dsbt table from another module */ + if (ref == NULL && t != tpnt) { + ref = t; + + /* make sure index is not already used */ + if (t->loadaddr.map->dsbt_table[idx]) { + struct elf_resolve *dup; + char *dup_name; + + for (dup = _dl_loaded_modules; dup; dup = dup->next) + if (dup != tpnt && dup->loadaddr.map->dsbt_index == idx) + break; + if (dup) + dup_name = dup->libname; + else if (idx == 1) + dup_name = "runtime linker"; + else + dup_name = "unknown library"; + _dl_dprintf(2, "%s: '%s' dsbt index %d already used by %s!\n", + _dl_progname, libname, idx, dup_name); + _dl_exit(1); + } + } + t->loadaddr.map->dsbt_table[idx] = (unsigned)dsbt; + } + if (ref) + _dl_memcpy(dsbt, ref->loadaddr.map->dsbt_table, + tpnt->loadaddr.map->dsbt_size * sizeof(unsigned *)); + } +#endif + _dl_if_debug_dprint("\n\tfile='%s'; generating link map\n", libname); + _dl_if_debug_dprint("\t\tdynamic: %x base: %x\n", dynamic_addr, DL_LOADADDR_BASE(lib_loadaddr)); + _dl_if_debug_dprint("\t\t entry: %x phdr: %x phnum: %x\n\n", + DL_RELOC_ADDR(lib_loadaddr, epnt->e_entry), tpnt->ppnt, tpnt->n_phent); + + _dl_munmap(header, _dl_pagesize); + + return tpnt; +} + +/* now_flag must be RTLD_NOW or zero */ +int _dl_fixup(struct dyn_elf *rpnt, int now_flag) +{ + int goof = 0; + struct elf_resolve *tpnt; + ElfW(Word) reloc_size, relative_count; + ElfW(Addr) reloc_addr; + + if (rpnt->next) + goof = _dl_fixup(rpnt->next, now_flag); + if (goof) + return goof; + tpnt = rpnt->dyn; + + if (!(tpnt->init_flag & RELOCS_DONE)) + _dl_if_debug_dprint("relocation processing: %s\n", tpnt->libname); + + if (unlikely(tpnt->dynamic_info[UNSUPPORTED_RELOC_TYPE])) { + _dl_if_debug_dprint("%s: can't handle %s relocation records\n", + _dl_progname, UNSUPPORTED_RELOC_STR); + goof++; + return goof; + } + + reloc_size = tpnt->dynamic_info[DT_RELOC_TABLE_SIZE]; +/* On some machines, notably SPARC & PPC, DT_REL* includes DT_JMPREL in its + range. Note that according to the ELF spec, this is completely legal! */ +#ifdef ELF_MACHINE_PLTREL_OVERLAP + reloc_size -= tpnt->dynamic_info [DT_PLTRELSZ]; +#endif + if (tpnt->dynamic_info[DT_RELOC_TABLE_ADDR] && + !(tpnt->init_flag & RELOCS_DONE)) { + reloc_addr = tpnt->dynamic_info[DT_RELOC_TABLE_ADDR]; + relative_count = tpnt->dynamic_info[DT_RELCONT_IDX]; + if (relative_count) { /* Optimize the XX_RELATIVE relocations if possible */ + reloc_size -= relative_count * sizeof(ELF_RELOC); + elf_machine_relative(tpnt->loadaddr, reloc_addr, relative_count); + reloc_addr += relative_count * sizeof(ELF_RELOC); + } + goof += _dl_parse_relocation_information(rpnt, + reloc_addr, + reloc_size); + tpnt->init_flag |= RELOCS_DONE; + } + if (tpnt->dynamic_info[DT_BIND_NOW]) + now_flag = RTLD_NOW; + if (tpnt->dynamic_info[DT_JMPREL] && + (!(tpnt->init_flag & JMP_RELOCS_DONE) || + (now_flag && !(tpnt->rtld_flags & now_flag)))) { + tpnt->rtld_flags |= now_flag; + if (!(tpnt->rtld_flags & RTLD_NOW)) { + _dl_parse_lazy_relocation_information(rpnt, + tpnt->dynamic_info[DT_JMPREL], + tpnt->dynamic_info [DT_PLTRELSZ]); + } else { + goof += _dl_parse_relocation_information(rpnt, + tpnt->dynamic_info[DT_JMPREL], + tpnt->dynamic_info[DT_PLTRELSZ]); + } + tpnt->init_flag |= JMP_RELOCS_DONE; + } + +#if 0 +/* _dl_add_to_slotinfo is called by init_tls() for initial DSO + or by dlopen() for dynamically loaded DSO. */ +#if defined(USE_TLS) && USE_TLS + /* Add object to slot information data if necessasy. */ + if (tpnt->l_tls_blocksize != 0 && tls_init_tp_called) + _dl_add_to_slotinfo ((struct link_map *) tpnt); +#endif +#endif + return goof; +} +#ifndef NOT_FOR_L4 +#include +#endif + +/* Minimal printf which handles only %s, %d, and %x */ +void _dl_dprintf(int fd, const char *fmt, ...) +{ +#if __WORDSIZE > 32 + long int num; +#else + int num; +#endif + va_list args; + char *start, *ptr, *string; + char *buf; + + if (!fmt) + return; + +#ifndef NOT_FOR_L4 + l4_msg_regs_t store_mr; + l4_buf_regs_t store_br; + l4_msg_regs_t *mr = l4_utcb_mr(); + l4_buf_regs_t *br = l4_utcb_br(); + + _dl_memcpy(&store_mr, mr, sizeof(store_mr)); + _dl_memcpy(&store_br, br, sizeof(store_br)); +#endif + + buf = _dl_mmap((void *) 0, _dl_pagesize, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (_dl_mmap_check_error(buf)) { + _dl_write(fd, "mmap of a spare page failed!\n", 29); + _dl_exit(20); + } + + start = ptr = buf; + + if (_dl_strlen(fmt) >= (_dl_pagesize - 1)) { + _dl_write(fd, "overflow\n", 11); + _dl_exit(20); + } + + _dl_strcpy(buf, fmt); + va_start(args, fmt); + + while (start) { + while (*ptr != '%' && *ptr) { + ptr++; + } + + if (*ptr == '%') { + *ptr++ = '\0'; + _dl_write(fd, start, _dl_strlen(start)); + + switch (*ptr++) { + case 's': + string = va_arg(args, char *); + + if (!string) + _dl_write(fd, "(null)", 6); + else + _dl_write(fd, string, _dl_strlen(string)); + break; + + case 'i': + case 'd': + { + char tmp[22]; +#if __WORDSIZE > 32 + num = va_arg(args, long int); +#else + num = va_arg(args, int); +#endif + string = _dl_simple_ltoa(tmp, num); + _dl_write(fd, string, _dl_strlen(string)); + break; + } + case 'x': + case 'X': + { + char tmp[22]; +#if __WORDSIZE > 32 + num = va_arg(args, long int); +#else + num = va_arg(args, int); +#endif + string = _dl_simple_ltoahex(tmp, num); + _dl_write(fd, string, _dl_strlen(string)); + break; + } + default: + _dl_write(fd, "(null)", 6); + break; + } + + start = ptr; + } else { + _dl_write(fd, start, _dl_strlen(start)); + start = NULL; + } + } + _dl_munmap(buf, _dl_pagesize); +#ifndef NOT_FOR_L4 + _dl_memcpy(mr, &store_mr, sizeof(store_mr)); + _dl_memcpy(br, &store_br, sizeof(store_br)); +#endif + return; +} + +char *_dl_strdup(const char *string) +{ + char *retval; + int len; + + len = _dl_strlen(string); + retval = _dl_malloc(len + 1); + _dl_strcpy(retval, string); + return retval; +} + +unsigned int _dl_parse_dynamic_info(ElfW(Dyn) *dpnt, unsigned long dynamic_info[], + void *debug_addr, DL_LOADADDR_TYPE load_off) +{ + return __dl_parse_dynamic_info(dpnt, dynamic_info, debug_addr, load_off); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/dl-hash.c b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/dl-hash.c new file mode 100644 index 00000000..12f9ce3e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/dl-hash.c @@ -0,0 +1,380 @@ +/* vi: set sw=4 ts=4: */ +/* + * Program to load an ELF binary on a linux system, and run it + * after resolving ELF shared library symbols + * + * Copyright (C) 2004 by Joakim Tjernlund + * Copyright (C) 2000-2006 by Erik Andersen + * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald, + * David Engel, Hongjiu Lu and Mitch D'Souza + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. The name of the above contributors may not be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +/* Various symbol table handling functions, including symbol lookup */ +/* + * This is the list of modules that are loaded when the image is first + * started. As we add more via dlopen, they get added into other + * chains. + */ +struct dyn_elf *_dl_symbol_tables = NULL; + +/* + * This is the list of modules that are loaded via dlopen. We may need + * to search these for RTLD_GLOBAL files. + */ +struct dyn_elf *_dl_handles = NULL; + +#ifdef __LDSO_GNU_HASH_SUPPORT__ +/* This is the new hash function that is used by the ELF linker to generate the + * GNU hash table that each executable and library will have if --hash-style=[gnu,both] + * is passed to the linker. We need it to decode the GNU hash table. */ +static __inline__ Elf_Symndx _dl_gnu_hash (const unsigned char *name) +{ + unsigned long h = 5381; + unsigned char c; + for (c = *name; c != '\0'; c = *++name) + h = h * 33 + c; + return h & 0xffffffff; +} +#endif + +/* This is the hash function that is used by the ELF linker to generate the + * hash table that each executable and library is required to have. We need + * it to decode the hash table. */ +static __inline__ Elf_Symndx _dl_elf_hash(const unsigned char *name) +{ + unsigned long hash=0; + unsigned long tmp; + + while (*name) { + hash = (hash << 4) + *name++; + tmp = hash & 0xf0000000; + /* The algorithm specified in the ELF ABI is as follows: + if (tmp != 0) + hash ^= tmp >> 24; + hash &= ~tmp; + But the following is equivalent and a lot + faster, especially on modern processors. */ + hash ^= tmp; + hash ^= tmp >> 24; + } + return hash; +} + +/* + * We call this function when we have just read an ELF library or executable. + * We add the relevant info to the symbol chain, so that we can resolve all + * externals properly. + */ +struct elf_resolve *_dl_add_elf_hash_table(const char *libname, + DL_LOADADDR_TYPE loadaddr, unsigned long *dynamic_info, unsigned long dynamic_addr, + attribute_unused unsigned long dynamic_size) +{ + Elf_Symndx *hash_addr; + struct elf_resolve *tpnt; + int i; + + tpnt = _dl_malloc(sizeof(struct elf_resolve)); + _dl_memset(tpnt, 0, sizeof(struct elf_resolve)); + + if (!_dl_loaded_modules) + _dl_loaded_modules = tpnt; + else { + struct elf_resolve *t = _dl_loaded_modules; + while (t->next) + t = t->next; + t->next = tpnt; + t->next->prev = t; + tpnt = t->next; + } + + tpnt->next = NULL; + tpnt->init_flag = 0; + tpnt->libname = _dl_strdup(libname); + tpnt->dynamic_addr = (ElfW(Dyn) *)dynamic_addr; + tpnt->libtype = loaded_file; + +#ifdef __LDSO_GNU_HASH_SUPPORT__ + if (dynamic_info[DT_GNU_HASH_IDX] != 0) { + Elf32_Word *hash32 = (Elf_Symndx*)dynamic_info[DT_GNU_HASH_IDX]; + + tpnt->nbucket = *hash32++; + Elf32_Word symbias = *hash32++; + Elf32_Word bitmask_nwords = *hash32++; + /* Must be a power of two. */ + _dl_assert ((bitmask_nwords & (bitmask_nwords - 1)) == 0); + tpnt->l_gnu_bitmask_idxbits = bitmask_nwords - 1; + tpnt->l_gnu_shift = *hash32++; + + tpnt->l_gnu_bitmask = (ElfW(Addr) *) hash32; + hash32 += __ELF_NATIVE_CLASS / 32 * bitmask_nwords; + + tpnt->l_gnu_buckets = hash32; + hash32 += tpnt->nbucket; + tpnt->l_gnu_chain_zero = hash32 - symbias; + } else + /* Fall using old SysV hash table if GNU hash is not present */ +#endif + + if (dynamic_info[DT_HASH] != 0) { + hash_addr = (Elf_Symndx*)dynamic_info[DT_HASH]; + tpnt->nbucket = *hash_addr++; + tpnt->nchain = *hash_addr++; + tpnt->elf_buckets = hash_addr; + hash_addr += tpnt->nbucket; + tpnt->chains = hash_addr; + } + tpnt->loadaddr = loadaddr; + tpnt->mapaddr = DL_RELOC_ADDR(loadaddr, 0); + for (i = 0; i < DYNAMIC_SIZE; i++) + tpnt->dynamic_info[i] = dynamic_info[i]; + return tpnt; +} + + +/* Routine to check whether the symbol matches. */ +static __attribute_noinline__ const ElfW(Sym) * +check_match (const ElfW(Sym) *sym, char *strtab, const char* undef_name, int type_class) +{ + +#if defined(USE_TLS) && USE_TLS + if ((sym->st_value == 0 && (ELF_ST_TYPE(sym->st_info) != STT_TLS)) + || (type_class & (sym->st_shndx == SHN_UNDEF))) + /* No value or undefined symbol itself */ + return NULL; + + if (ELF_ST_TYPE(sym->st_info) > STT_FUNC + && ELF_ST_TYPE(sym->st_info) != STT_COMMON + && ELF_ST_TYPE(sym->st_info) != STT_TLS) + /* Ignore all but STT_NOTYPE, STT_OBJECT, STT_FUNC and STT_COMMON + * entries (and STT_TLS if TLS is supported) since these + * are no code/data definitions. + */ + return NULL; +#else + if (type_class & (sym->st_shndx == SHN_UNDEF)) + /* undefined symbol itself */ + return NULL; + + if (sym->st_value == 0) + /* No value */ + return NULL; + + if (ELF_ST_TYPE(sym->st_info) > STT_FUNC + && ELF_ST_TYPE(sym->st_info) != STT_COMMON) + /* Ignore all but STT_NOTYPE, STT_OBJECT, STT_FUNC + * and STT_COMMON entries since these are no + * code/data definitions + */ + return NULL; +#endif + if (_dl_strcmp(strtab + sym->st_name, undef_name) != 0) + return NULL; + + /* This is the matching symbol */ + return sym; +} + + +#ifdef __LDSO_GNU_HASH_SUPPORT__ + +static __always_inline const ElfW(Sym) * +_dl_lookup_gnu_hash(struct elf_resolve *tpnt, ElfW(Sym) *symtab, unsigned long hash, + const char* undef_name, int type_class) +{ + Elf_Symndx symidx; + const ElfW(Sym) *sym; + char *strtab; + + const ElfW(Addr) *bitmask = tpnt->l_gnu_bitmask; + + ElfW(Addr) bitmask_word = bitmask[(hash / __ELF_NATIVE_CLASS) & tpnt->l_gnu_bitmask_idxbits]; + + unsigned int hashbit1 = hash & (__ELF_NATIVE_CLASS - 1); + unsigned int hashbit2 = ((hash >> tpnt->l_gnu_shift) & (__ELF_NATIVE_CLASS - 1)); + _dl_assert (bitmask != NULL); + + if (unlikely((bitmask_word >> hashbit1) & (bitmask_word >> hashbit2) & 1)) { + unsigned long rem; + Elf32_Word bucket; + + do_rem (rem, hash, tpnt->nbucket); + bucket = tpnt->l_gnu_buckets[rem]; + + if (bucket != 0) { + const Elf32_Word *hasharr = &tpnt->l_gnu_chain_zero[bucket]; + do { + if (((*hasharr ^ hash) >> 1) == 0) { + symidx = hasharr - tpnt->l_gnu_chain_zero; + strtab = (char *) (tpnt->dynamic_info[DT_STRTAB]); + sym = check_match (&symtab[symidx], strtab, undef_name, type_class); + if (sym != NULL) + return sym; + } + } while ((*hasharr++ & 1u) == 0); + } + } + /* No symbol found. */ + return NULL; +} +#endif + +static __always_inline const ElfW(Sym) * +_dl_lookup_sysv_hash(struct elf_resolve *tpnt, ElfW(Sym) *symtab, unsigned long hash, const char* undef_name, int type_class) +{ + unsigned long hn; + char *strtab; + const ElfW(Sym) *sym; + Elf_Symndx symidx; + + /* Avoid calling .urem here. */ + do_rem(hn, hash, tpnt->nbucket); + strtab = (char *) (tpnt->dynamic_info[DT_STRTAB]); + + _dl_assert(tpnt->elf_buckets != NULL); + + for (symidx = tpnt->elf_buckets[hn]; symidx != STN_UNDEF; symidx = tpnt->chains[symidx]) { + sym = check_match (&symtab[symidx], strtab, undef_name, type_class); + if (sym != NULL) + /* At this point the symbol is that we are looking for */ + return sym; + } + /* No symbol found into the current module*/ + return NULL; +} + +/* + * This function resolves externals, and this is either called when we process + * relocations or when we call an entry in the PLT table for the first time. + */ +char *_dl_find_hash(const char *name, struct dyn_elf *rpnt, struct elf_resolve *mytpnt, + int type_class, struct symbol_ref *sym_ref) +{ + struct elf_resolve *tpnt = NULL; + ElfW(Sym) *symtab; + + unsigned long elf_hash_number = 0xffffffff; + const ElfW(Sym) *sym = NULL; + + char *weak_result = NULL; + +#ifdef __LDSO_GNU_HASH_SUPPORT__ + unsigned long gnu_hash_number = _dl_gnu_hash((const unsigned char *)name); +#endif + + /* aw11: added STB_LOCAL case to prevent searching locally linked symbols in + * other object files. This happens when we have TLS stuff with local + * linkage. + */ + if ((sym_ref) && (sym_ref->sym) && ((ELF32_ST_VISIBILITY(sym_ref->sym->st_other) == STV_PROTECTED) || (ELF32_ST_BIND(sym_ref->sym->st_info) == STB_LOCAL))) { + sym = sym_ref->sym; + if (mytpnt) + tpnt = mytpnt; + } else + for (; rpnt; rpnt = rpnt->next) { + tpnt = rpnt->dyn; + + if (!(tpnt->rtld_flags & RTLD_GLOBAL) && mytpnt) { + if (mytpnt == tpnt) + ; + else { + struct init_fini_list *tmp; + + for (tmp = mytpnt->rtld_local; tmp; tmp = tmp->next) { + if (tmp->tpnt == tpnt) + break; + } + if (!tmp) + continue; + } + } + /* Don't search the executable when resolving a copy reloc. */ + if ((type_class & ELF_RTYPE_CLASS_COPY) && tpnt->libtype == elf_executable) + continue; + + /* If the hash table is empty there is nothing to do here. */ + if (tpnt->nbucket == 0) + continue; + + symtab = (ElfW(Sym) *) (intptr_t) (tpnt->dynamic_info[DT_SYMTAB]); + +#ifdef __LDSO_GNU_HASH_SUPPORT__ + /* Prefer GNU hash style, if any */ + if (tpnt->l_gnu_bitmask) { + sym = _dl_lookup_gnu_hash(tpnt, symtab, gnu_hash_number, name, type_class); + if (sym != NULL) + /* If sym has been found, do not search further */ + break; + } else { +#endif + /* Use the old SysV-style hash table */ + + /* Calculate the old sysv hash number only once */ + if (elf_hash_number == 0xffffffff) + elf_hash_number = _dl_elf_hash((const unsigned char *)name); + + sym = _dl_lookup_sysv_hash(tpnt, symtab, elf_hash_number, name, type_class); + if (sym != NULL) + break; +#ifdef __LDSO_GNU_HASH_SUPPORT__ + } +#endif + } /* end of for (; rpnt; rpnt = rpnt->next) { */ + + if (sym) { + /* At this point we have found the requested symbol, do binding */ +#if defined(USE_TLS) && USE_TLS + if (ELF_ST_TYPE(sym->st_info) == STT_TLS) { + _dl_assert(sym_ref != NULL); + sym_ref->tpnt = tpnt; + return (char *)sym->st_value; + } +#endif + + switch (ELF_ST_BIND(sym->st_info)) { + case STB_WEAK: +#if 0 + /* Perhaps we should support old style weak symbol handling + * per what glibc does when you export LD_DYNAMIC_WEAK */ + if (!weak_result) + weak_result = (char *)DL_FIND_HASH_VALUE(tpnt, type_class, sym); + break; +#endif + case STB_GLOBAL: + case 10: /* DAS IS VON MIR GNU STB UNIQUE aw11 L4 und so, eigentlich muss das anders */ +#ifdef __FDPIC__ + if (sym_ref) + sym_ref->tpnt = tpnt; +#endif + return (char *)DL_FIND_HASH_VALUE(tpnt, type_class, sym); + default: /* Local symbols not handled here */ + break; + } + } +#ifdef __FDPIC__ + if (sym_ref) + sym_ref->tpnt = tpnt; +#endif + return weak_result; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/dl-startup.c b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/dl-startup.c new file mode 100644 index 00000000..a2cc71ae --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/dl-startup.c @@ -0,0 +1,392 @@ +/* vi: set sw=4 ts=4: */ +/* + * Program to load an ELF binary on a linux system, and run it + * after resolving ELF shared library symbols + * + * Copyright (C) 2005 by Joakim Tjernlund + * Copyright (C) 2000-2006 by Erik Andersen + * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald, + * David Engel, Hongjiu Lu and Mitch D'Souza + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. The name of the above contributors may not be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * The main trick with this program is that initially, we ourselves are not + * dynamicly linked. This means that we cannot access any global variables or + * call any functions. No globals initially, since the Global Offset Table + * (GOT) is initialized by the linker assuming a virtual address of 0, and no + * function calls initially since the Procedure Linkage Table (PLT) is not yet + * initialized. + * + * There are additional initial restrictions - we cannot use large switch + * statements, since the compiler generates tables of addresses and jumps + * through them. We cannot use normal syscall stubs, because these all + * reference the errno global variable which is not yet initialized. We _can_ + * use all of the local stack variables that we want. We _can_ use inline + * functions, because these do not transfer control to a new address, but they + * must be static so that they are not exported from the modules. + * + * Life is further complicated by the fact that initially we do not want to do + * a complete dynamic linking. We want to allow the user to supply new + * functions to override symbols (i.e. weak symbols and/or LD_PRELOAD). So + * initially, we only perform relocations for variables that start with "_dl_" + * since ANSI specifies that the user is not supposed to redefine any of these + * variables. + * + * Fortunately, the linker itself leaves a few clues lying around, and when the + * kernel starts the image, there are a few further clues. First of all, there + * is Auxiliary Vector Table information sitting on which is provided to us by + * the kernel, and which includes information about the load address that the + * program interpreter was loaded at, the number of sections, the address the + * application was loaded at and so forth. Here this information is stored in + * the array auxvt. For details see linux/fs/binfmt_elf.c where it calls + * NEW_AUX_ENT() a bunch of time.... + * + * Next, we need to find the GOT. On most arches there is a register pointing + * to the GOT, but just in case (and for new ports) I've added some (slow) C + * code to locate the GOT for you. + * + * This code was originally written for SVr4, and there the kernel would load + * all text pages R/O, so they needed to call mprotect a zillion times to mark + * all text pages as writable so dynamic linking would succeed. Then when they + * were done, they would change the protections for all the pages back again. + * Well, under Linux everything is loaded writable (since Linux does copy on + * write anyways) so all the mprotect stuff has been disabled. + * + * Initially, we do not have access to _dl_malloc since we can't yet make + * function calls, so we mmap one page to use as scratch space. Later on, when + * we can call _dl_malloc we reuse this this memory. This is also beneficial, + * since we do not want to use the same memory pool as malloc anyway - esp if + * the user redefines malloc to do something funky. + * + * Our first task is to perform a minimal linking so that we can call other + * portions of the dynamic linker. Once we have done this, we then build the + * list of modules that the application requires, using LD_LIBRARY_PATH if this + * is not a suid program (/usr/lib otherwise). Once this is done, we can do + * the dynamic linking as required, and we must omit the things we did to get + * the dynamic linker up and running in the first place. After we have done + * this, we just have a few housekeeping chores and we can transfer control to + * the user's application. + */ + +#include "ldso.h" + +/* Pull in all the arch specific stuff */ +#include "dl-startup.h" + +/* Static declarations */ +static int (*_dl_elf_main) (int, char **, char **); + +static void* __rtld_stack_end; /* Points to argc on stack, e.g *((long *)__rtld_stackend) == argc */ +strong_alias(__rtld_stack_end, __libc_stack_end) /* Exported version of __rtld_stack_end */ + +#ifndef __NOT_FOR_L4__ +attribute_hidden void *__rtld_l4re_global_env; +strong_alias(__rtld_l4re_global_env, l4re_global_env) +#endif + +/* When we enter this piece of code, the program stack looks like this: + argc argument counter (integer) + argv[0] program name (pointer) + argv[1..argc-1] program args (pointers) + NULL + env[0...N] environment variables (pointers) + NULL + auxvt[0...N] Auxiliary Vector Table elements (mixed types) +*/ +DL_START(unsigned long args) +{ + unsigned int argc; + char **argv, **envp; + DL_LOADADDR_TYPE load_addr; + /*ElfW(Addr) got; aw11: dropped this in favour of phdrs*/ + unsigned long *aux_dat; + ElfW(Ehdr) *header; + ElfW(Phdr) *phdr; /* aw11: use phdrs to find dynamic info */ + int i; /* aw11: use to iterate the phdrs */ + struct elf_resolve tpnt_tmp; + struct elf_resolve *tpnt = &tpnt_tmp; + ElfW(auxv_t) auxvt[AT_EGID + 1]; + ElfW(Dyn) *dpnt; + uint32_t *p32; +#ifndef NOT_FOR_L4 + void *l4re_env = 0; +#endif + + /* WARNING! -- we cannot make _any_ function calls until we have + * taken care of fixing up our own relocations. Making static + * inline calls is ok, but _no_ function calls. Not yet + * anyways. */ + + /* First obtain the information on the stack that tells us more about + what binary is loaded, where it is loaded, etc, etc */ + GET_ARGV(aux_dat, args); + argc = aux_dat[-1]; + argv = (char **) aux_dat; + aux_dat += argc; /* Skip over the argv pointers */ + aux_dat++; /* Skip over NULL at end of argv */ + envp = (char **) aux_dat; +#if !defined(NO_EARLY_SEND_STDERR) + SEND_EARLY_STDERR_DEBUG("argc="); + SEND_NUMBER_STDERR_DEBUG(argc, 0); + SEND_EARLY_STDERR_DEBUG(" argv="); + SEND_ADDRESS_STDERR_DEBUG(argv, 0); + SEND_EARLY_STDERR_DEBUG(" envp="); + SEND_ADDRESS_STDERR_DEBUG(envp, 1); +#endif + while (*aux_dat) + aux_dat++; /* Skip over the envp pointers */ + aux_dat++; /* Skip over NULL at end of envp */ + + /* Place -1 here as a checkpoint. We later check if it was changed + * when we read in the auxvt */ + auxvt[AT_UID].a_type = -1; + + /* The junk on the stack immediately following the environment is + * the Auxiliary Vector Table. Read out the elements of the auxvt, + * sort and store them in auxvt for later use. */ + while (*aux_dat) { + ElfW(auxv_t) *auxv_entry = (ElfW(auxv_t) *) aux_dat; + + if (auxv_entry->a_type <= AT_EGID) { + _dl_memcpy(&(auxvt[auxv_entry->a_type]), auxv_entry, sizeof(ElfW(auxv_t))); + } +#ifndef L4_ONLY + if (auxv_entry->a_type == 0xf1) { + l4re_env = (void*)auxv_entry->a_un.a_val; + } +#endif + aux_dat += 2; + } + + /* locate the ELF header. We need this done as soon as possible + * (esp since SEND_STDERR() needs this on some platforms... */ + if (!auxvt[AT_BASE].a_un.a_val) + auxvt[AT_BASE].a_un.a_val = elf_machine_load_address(); + DL_INIT_LOADADDR_BOOT(load_addr, auxvt[AT_BASE].a_un.a_val); + header = (ElfW(Ehdr) *) auxvt[AT_BASE].a_un.a_val; + + /* Check the ELF header to make sure everything looks ok. */ + if (!header || header->e_ident[EI_CLASS] != ELF_CLASS || + header->e_ident[EI_VERSION] != EV_CURRENT + /* Do not use an inline _dl_strncmp here or some arches + * will blow chunks, i.e. those that need to relocate all + * string constants... */ + || *(p32 = (uint32_t*)&header->e_ident) != ELFMAG_U32 + ) { + SEND_EARLY_STDERR("Invalid ELF header\n"); + _dl_exit(0); + } + SEND_EARLY_STDERR_DEBUG("ELF header="); + SEND_ADDRESS_STDERR_DEBUG(DL_LOADADDR_BASE(load_addr), 1); + + /* aw11: iterate the phdrs of ldso to find our dynamic info not the GOT, + * as GNU gold does not provide tge GOT entry. + * begin: ----------------> */ +#if 0 /* original code */ + /* Locate the global offset table. Since this code must be PIC + * we can take advantage of the magic offset register, if we + * happen to know what that is for this architecture. If not, + * we can always read stuff out of the ELF file to find it... */ + DL_BOOT_COMPUTE_GOT(got); + + /* Now, finally, fix up the location of the dynamic stuff */ + DL_BOOT_COMPUTE_DYN(dpnt, got, load_addr); +#else /* aw11 code */ + /* locate the ELF phdrs. We need this for finding the dynamic infos + */ + SEND_EARLY_STDERR_DEBUG("AT_PHDR="); + SEND_ADDRESS_STDERR_DEBUG(header->e_phoff, 1); + phdr = (ElfW(Phdr) *) DL_RELOC_ADDR(load_addr, header->e_phoff); + dpnt = 0; + for (i = 0; i < header->e_phnum; ++i) { + if (phdr[i].p_type == PT_DYNAMIC) { + DL_BOOT_COMPUTE_DYN(dpnt, phdr[i].p_vaddr, load_addr); + break; + } + } +#endif + /* aw11: end <------------- */ + + SEND_EARLY_STDERR_DEBUG("First Dynamic section entry="); + SEND_ADDRESS_STDERR_DEBUG(dpnt, 1); + _dl_memset(tpnt, 0, sizeof(struct elf_resolve)); + tpnt->loadaddr = load_addr; + /* OK, that was easy. Next scan the DYNAMIC section of the image. + We are only doing ourself right now - we will have to do the rest later */ + SEND_EARLY_STDERR_DEBUG("Scanning DYNAMIC section\n"); + tpnt->dynamic_addr = dpnt; +#if defined(NO_FUNCS_BEFORE_BOOTSTRAP) + /* Some architectures cannot call functions here, must inline */ + __dl_parse_dynamic_info(dpnt, tpnt->dynamic_info, NULL, load_addr); +#else + _dl_parse_dynamic_info(dpnt, tpnt->dynamic_info, NULL, load_addr); +#endif + + /* + * BIG ASSUMPTION: We assume that the dynamic loader does not + * have any TLS data itself. If this ever occurs + * more work than what is done below for the + * loader will have to happen. + */ +#if defined(USE_TLS) && USE_TLS + /* This was done by _dl_memset above. */ + /* tpnt->l_tls_modid = 0; */ +# if NO_TLS_OFFSET != 0 + tpnt->l_tls_offset = NO_TLS_OFFSET; +# endif +#endif + + SEND_EARLY_STDERR_DEBUG("Done scanning DYNAMIC section\n"); + +#if defined(PERFORM_BOOTSTRAP_GOT) + SEND_EARLY_STDERR_DEBUG("About to do specific GOT bootstrap\n"); + /* some arches (like MIPS) we have to tweak the GOT before relocations */ + PERFORM_BOOTSTRAP_GOT(tpnt); +#endif + +#if !defined(PERFORM_BOOTSTRAP_GOT) || defined(__avr32__) + + /* OK, now do the relocations. We do not do a lazy binding here, so + that once we are done, we have considerably more flexibility. */ + SEND_EARLY_STDERR_DEBUG("About to do library loader relocations\n"); + + { + int indx; +#if defined(ELF_MACHINE_PLTREL_OVERLAP) +# define INDX_MAX 1 +#else +# define INDX_MAX 2 +#endif + for (indx = 0; indx < INDX_MAX; indx++) { + unsigned long rel_addr, rel_size; + ElfW(Word) relative_count = tpnt->dynamic_info[DT_RELCONT_IDX]; + + rel_addr = (indx ? tpnt->dynamic_info[DT_JMPREL] : + tpnt->dynamic_info[DT_RELOC_TABLE_ADDR]); + rel_size = (indx ? tpnt->dynamic_info[DT_PLTRELSZ] : + tpnt->dynamic_info[DT_RELOC_TABLE_SIZE]); + + if (!rel_addr) + continue; + + if (!indx && relative_count) { + rel_size -= relative_count * sizeof(ELF_RELOC); + elf_machine_relative(load_addr, rel_addr, relative_count); + rel_addr += relative_count * sizeof(ELF_RELOC); + } + + /* + * Since ldso is linked with -Bsymbolic, all relocs should be RELATIVE. All archs + * that need bootstrap relocations need to define ARCH_NEEDS_BOOTSTRAP_RELOCS. + */ +#if 1 //def ARCH_NEEDS_BOOTSTRAP_RELOCS + { + ELF_RELOC *rpnt; + unsigned int i; + ElfW(Sym) *sym; + unsigned long symbol_addr; + int symtab_index; + unsigned long *reloc_addr; + + /* Now parse the relocation information */ + rpnt = (ELF_RELOC *) rel_addr; + for (i = 0; i < rel_size; i += sizeof(ELF_RELOC), rpnt++) { + reloc_addr = (unsigned long *) DL_RELOC_ADDR(load_addr, (unsigned long)rpnt->r_offset); + symtab_index = ELF_R_SYM(rpnt->r_info); + symbol_addr = 0; + sym = NULL; + if (symtab_index) { + char *strtab; + ElfW(Sym) *symtab; + + symtab = (ElfW(Sym) *) tpnt->dynamic_info[DT_SYMTAB]; + strtab = (char *) tpnt->dynamic_info[DT_STRTAB]; + sym = &symtab[symtab_index]; + symbol_addr = (unsigned long) DL_RELOC_ADDR(load_addr, sym->st_value); +#if !defined(EARLY_STDERR_SPECIAL) + SEND_STDERR_DEBUG("relocating symbol: "); + SEND_STDERR_DEBUG(strtab + sym->st_name); + SEND_STDERR_DEBUG("\n"); +#endif + } else { + SEND_STDERR_DEBUG("relocating unknown symbol\n"); + } + /* Use this machine-specific macro to perform the actual relocation. */ + PERFORM_BOOTSTRAP_RELOC(rpnt, reloc_addr, symbol_addr, load_addr, sym); + } + } +#else /* ARCH_NEEDS_BOOTSTRAP_RELOCS */ + if (rel_size) { + SEND_EARLY_STDERR("Cannot continue, found non relative relocs during the bootstrap.\n"); + _dl_exit(14); + } +#endif + } + } +#endif + + SEND_STDERR_DEBUG("Done relocating ldso; we can now use globals and make function calls!\n"); + + /* Now we have done the mandatory linking of some things. We are now + free to start using global variables, since these things have all been + fixed up by now. Still no function calls outside of this library, + since the dynamic resolver is not yet ready. */ + + __rtld_stack_end = (void *)(argv - 1); + +#ifndef __ONLY_FOR_L4__ + { + __rtld_l4re_global_env = l4re_env; + ElfW(Dyn) *dpnt = tpnt->dynamic_addr; + void (**ia)(void) = 0; + int ia_sz = 0; + extern void _init(void); + _init(); + + for (; dpnt->d_tag; dpnt++) { + if (dpnt->d_tag == DT_INIT_ARRAY) + ia = (void (**)(void))(dpnt->d_un.d_val + load_addr); + else if (dpnt->d_tag == DT_INIT_ARRAYSZ) + ia_sz = dpnt->d_un.d_val; + } + + ia_sz /= sizeof(void*); + for (; ia_sz > 0; --ia_sz, ++ia) + (*ia)(); + } +#endif + _dl_get_ready_to_run(tpnt, load_addr, auxvt, envp, argv + DL_GET_READY_TO_RUN_EXTRA_ARGS); + + /* Transfer control to the application. */ + SEND_STDERR_DEBUG("transfering control to application @ "); + _dl_elf_main = (int (*)(int, char **, char **)) auxvt[AT_ENTRY].a_un.a_val; + SEND_ADDRESS_STDERR_DEBUG(_dl_elf_main, 1); + +#if !defined(START) + return _dl_elf_main; +#else + START(); +#endif +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/dl-symbols.c b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/dl-symbols.c new file mode 100644 index 00000000..e5c00211 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/dl-symbols.c @@ -0,0 +1,21 @@ +/* + * This contains all symbols shared between + * dynamic linker ld.so and into static libc + * + * Copyright (c) 2008 STMicroelectronics Ltd + * Author: Carmelo Amoroso + * + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + */ + +/* + * This is the start of the linked list that describes all of the files present + * in the system with pointers to all of the symbol, string, and hash tables, + * as well as all of the other good stuff in the binary. + */ +#include + +struct elf_resolve *_dl_loaded_modules = NULL; + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/dl-tls.c b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/dl-tls.c new file mode 100644 index 00000000..543bc973 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/dl-tls.c @@ -0,0 +1,1043 @@ +/* vi: set sw=4 ts=4: */ +/* + * Thread-local storage handling in the ELF dynamic linker. + * + * Copyright (C) 2005 by Steven J. Hill + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. The name of the above contributors may not be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include + +void *(*_dl_calloc_function) (size_t __nmemb, size_t __size) = NULL; +void *(*_dl_realloc_function) (void *__ptr, size_t __size) = NULL; +void *(*_dl_memalign_function) (size_t __boundary, size_t __size) = NULL; + +void (*_dl_free_function) (void *__ptr); +void *_dl_memalign (size_t __boundary, size_t __size); +struct link_map *_dl_update_slotinfo (unsigned long int req_modid); + +/* Round up N to the nearest multiple of P, where P is a power of 2 + --- without using libgcc division routines. */ +#define roundup_pow2(n, p) (((n) + (p) - 1) & ~((p) - 1)) + +void * +_dl_calloc (size_t __nmemb, size_t __size) +{ + void *result; + size_t size = (__size * __nmemb); + + if (_dl_calloc_function) + return (*_dl_calloc_function) (__nmemb, __size); + + if ((result = _dl_malloc(size)) != NULL) { + _dl_memset(result, 0, size); + } + + return result; +} + +void * +_dl_realloc (void * __ptr, size_t __size) +{ + if (_dl_realloc_function) + return (*_dl_realloc_function) (__ptr, __size); + + _dl_debug_early("NOT IMPLEMENTED PROPERLY!!!\n"); + return NULL; +} + +/* The __tls_get_addr function has two basic forms which differ in the + arguments. The IA-64 form takes two parameters, the module ID and + offset. The form used, among others, on IA-32 takes a reference to + a special structure which contain the same information. The second + form seems to be more often used (in the moment) so we default to + it. Users of the IA-64 form have to provide adequate definitions + of the following macros. */ +#ifndef GET_ADDR_ARGS +# define GET_ADDR_ARGS tls_index *ti +#endif +#ifndef GET_ADDR_MODULE +# define GET_ADDR_MODULE ti->ti_module +#endif +#ifndef GET_ADDR_OFFSET +# define GET_ADDR_OFFSET ti->ti_offset +#endif + +/* + * Amount of excess space to allocate in the static TLS area + * to allow dynamic loading of modules defining IE-model TLS data. + */ +#define TLS_STATIC_SURPLUS 64 + DL_NNS * 100 + +/* Value used for dtv entries for which the allocation is delayed. */ +#define TLS_DTV_UNALLOCATED ((void *) -1l) + +/* + * We are trying to perform a static TLS relocation in MAP, but it was + * dynamically loaded. This can only work if there is enough surplus in + * the static TLS area already allocated for each running thread. If this + * object's TLS segment is too big to fit, we fail. If it fits, + * we set MAP->l_tls_offset and return. + * This function intentionally does not return any value but signals error + * directly, as static TLS should be rare and code handling it should + * not be inlined as much as possible. + */ +void +internal_function __attribute_noinline__ +_dl_allocate_static_tls (struct link_map *map) +{ + /* If the alignment requirements are too high fail. */ + if (map->l_tls_align > _dl_tls_static_align) + { +fail: + _dl_dprintf(2, "cannot allocate memory in static TLS block"); + _dl_exit(30); + } + +# ifdef TLS_TCB_AT_TP + size_t freebytes; + size_t n; + size_t blsize; + + freebytes = _dl_tls_static_size - _dl_tls_static_used - TLS_TCB_SIZE; + + blsize = map->l_tls_blocksize + map->l_tls_firstbyte_offset; + if (freebytes < blsize) + goto fail; + + n = (freebytes - blsize) & ~(map->l_tls_align - 1); + + size_t offset = _dl_tls_static_used + (freebytes - n + - map->l_tls_firstbyte_offset); + + map->l_tls_offset = _dl_tls_static_used = offset; +# elif defined(TLS_DTV_AT_TP) + size_t used; + size_t check; + + size_t offset = roundup_pow2 (_dl_tls_static_used, map->l_tls_align); + used = offset + map->l_tls_blocksize; + check = used; + + /* dl_tls_static_used includes the TCB at the beginning. */ + if (check > _dl_tls_static_size) + goto fail; + + map->l_tls_offset = offset; + _dl_tls_static_used = used; +# else +# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined" +# endif + + /* + * If the object is not yet relocated we cannot initialize the + * static TLS region. Delay it. + */ + if (((struct elf_resolve *) map)->init_flag & RELOCS_DONE) + { +#ifdef SHARED + /* + * Update the slot information data for at least the generation of + * the DSO we are allocating data for. + */ + if (__builtin_expect (THREAD_DTV()[0].counter != _dl_tls_generation, 0)) + (void) _dl_update_slotinfo (map->l_tls_modid); +#endif + _dl_init_static_tls (map); + } + else + map->l_need_tls_init = 1; +} + +#ifdef SHARED +/* Initialize static TLS area and DTV for current (only) thread. + libpthread implementations should provide their own hook + to handle all threads. */ +void +attribute_hidden __attribute_noinline__ +_dl_nothread_init_static_tls (struct link_map *map) +{ +# ifdef TLS_TCB_AT_TP + void *dest = (char *) THREAD_SELF - map->l_tls_offset; +# elif defined(TLS_DTV_AT_TP) + void *dest = (char *) THREAD_SELF + map->l_tls_offset + TLS_PRE_TCB_SIZE; +# else +# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined" +# endif + + /* Fill in the DTV slot so that a later LD/GD access will find it. */ + dtv_t *dtv = THREAD_DTV (); + if (!(map->l_tls_modid <= dtv[-1].counter)) { + _dl_dprintf(2, "map->l_tls_modid <= dtv[-1].counter FAILED!\n"); + _dl_exit(30); + } + dtv[map->l_tls_modid].pointer.val = dest; + dtv[map->l_tls_modid].pointer.is_static = true; + + /* Initialize the memory. */ + _dl_memcpy(dest, map->l_tls_initimage, map->l_tls_initimage_size); + _dl_memset((dest + map->l_tls_initimage_size), '\0', + map->l_tls_blocksize - map->l_tls_initimage_size); +} +#endif + +/* Taken from glibc/sysdeps/generic/dl-tls.c */ +static void +oom (void) +{ + _dl_debug_early("cannot allocate thread-local memory: ABORT\n"); + _dl_exit(30); +} + +size_t +internal_function +_dl_next_tls_modid (void) +{ + size_t result; + + if (__builtin_expect (_dl_tls_dtv_gaps, false)) + { + size_t disp = 0; + struct dtv_slotinfo_list *runp = _dl_tls_dtv_slotinfo_list; + + /* Note that this branch will never be executed during program + start since there are no gaps at that time. Therefore it + does not matter that the dl_tls_dtv_slotinfo is not allocated + yet when the function is called for the first times. + + NB: the offset +1 is due to the fact that DTV[0] is used + for something else. */ + result = _dl_tls_static_nelem + 1; + if (result <= _dl_tls_max_dtv_idx) + do + { + while (result - disp < runp->len) + { + if (runp->slotinfo[result - disp].map == NULL) + break; + + ++result; + _dl_assert (result <= _dl_tls_max_dtv_idx + 1); + } + + if (result - disp < runp->len) + break; + + disp += runp->len; + } + while ((runp = runp->next) != NULL); + + if (result > _dl_tls_max_dtv_idx) + { + /* The new index must indeed be exactly one higher than the + previous high. */ + _dl_assert (result == _dl_tls_max_dtv_idx + 1); + /* There is no gap anymore. */ + _dl_tls_dtv_gaps = false; + + goto nogaps; + } + } + else + { + /* No gaps, allocate a new entry. */ + nogaps: + + result = ++_dl_tls_max_dtv_idx; + } + + return result; +} + +#ifndef MAX +# define MAX(x,y) (((x) > (y)) ? (x) : (y)) +#endif + +void +internal_function +_dl_determine_tlsoffset (void) +{ + size_t max_align = TLS_TCB_ALIGN; + size_t freetop = 0; + size_t freebottom = 0; + + /* The first element of the dtv slot info list is allocated. */ + _dl_assert (_dl_tls_dtv_slotinfo_list != NULL); + /* There is at this point only one element in the + dl_tls_dtv_slotinfo_list list. */ + _dl_assert (_dl_tls_dtv_slotinfo_list->next == NULL); + + struct dtv_slotinfo *slotinfo = _dl_tls_dtv_slotinfo_list->slotinfo; + + /* Determining the offset of the various parts of the static TLS + block has several dependencies. In addition we have to work + around bugs in some toolchains. + + Each TLS block from the objects available at link time has a size + and an alignment requirement. The GNU ld computes the alignment + requirements for the data at the positions *in the file*, though. + I.e, it is not simply possible to allocate a block with the size + of the TLS program header entry. The data is layed out assuming + that the first byte of the TLS block fulfills + + p_vaddr mod p_align == &TLS_BLOCK mod p_align + + This means we have to add artificial padding at the beginning of + the TLS block. These bytes are never used for the TLS data in + this module but the first byte allocated must be aligned + according to mod p_align == 0 so that the first byte of the TLS + block is aligned according to p_vaddr mod p_align. This is ugly + and the linker can help by computing the offsets in the TLS block + assuming the first byte of the TLS block is aligned according to + p_align. + + The extra space which might be allocated before the first byte of + the TLS block need not go unused. The code below tries to use + that memory for the next TLS block. This can work if the total + memory requirement for the next TLS block is smaller than the + gap. */ + +# ifdef TLS_TCB_AT_TP + /* We simply start with zero. */ + size_t cnt, offset = 0; + + for (cnt = 1; slotinfo[cnt].map != NULL; ++cnt) + { + _dl_assert (cnt < _dl_tls_dtv_slotinfo_list->len); + + size_t firstbyte = (-slotinfo[cnt].map->l_tls_firstbyte_offset + & (slotinfo[cnt].map->l_tls_align - 1)); + size_t off; + max_align = MAX (max_align, slotinfo[cnt].map->l_tls_align); + + if (freebottom - freetop >= slotinfo[cnt].map->l_tls_blocksize) + { + off = roundup_pow2 (freetop + slotinfo[cnt].map->l_tls_blocksize + - firstbyte, slotinfo[cnt].map->l_tls_align) + + firstbyte; + if (off <= freebottom) + { + freetop = off; + + /* XXX For some architectures we perhaps should store the + negative offset. */ + slotinfo[cnt].map->l_tls_offset = off; + continue; + } + } + + off = roundup_pow2 (offset + slotinfo[cnt].map->l_tls_blocksize + - firstbyte, slotinfo[cnt].map->l_tls_align) + + firstbyte; + if (off > offset + slotinfo[cnt].map->l_tls_blocksize + + (freebottom - freetop)) + { + freetop = offset; + freebottom = off - slotinfo[cnt].map->l_tls_blocksize; + } + offset = off; + + /* XXX For some architectures we perhaps should store the + negative offset. */ + slotinfo[cnt].map->l_tls_offset = off; + } + + _dl_tls_static_used = offset; + _dl_tls_static_size = (roundup_pow2 (offset + TLS_STATIC_SURPLUS, max_align) + + TLS_TCB_SIZE); +# elif defined(TLS_DTV_AT_TP) + /* The TLS blocks start right after the TCB. */ + size_t offset = TLS_TCB_SIZE; + size_t cnt; + + for (cnt = 1; slotinfo[cnt].map != NULL; ++cnt) + { + _dl_assert (cnt < _dl_tls_dtv_slotinfo_list->len); + + size_t firstbyte = (-slotinfo[cnt].map->l_tls_firstbyte_offset + & (slotinfo[cnt].map->l_tls_align - 1)); + size_t off; + max_align = MAX (max_align, slotinfo[cnt].map->l_tls_align); + + if (slotinfo[cnt].map->l_tls_blocksize <= freetop - freebottom) + { + off = roundup_pow2 (freebottom, slotinfo[cnt].map->l_tls_align); + if (off - freebottom < firstbyte) + off += slotinfo[cnt].map->l_tls_align; + if (off + slotinfo[cnt].map->l_tls_blocksize - firstbyte <= freetop) + { + slotinfo[cnt].map->l_tls_offset = off - firstbyte; + freebottom = (off + slotinfo[cnt].map->l_tls_blocksize + - firstbyte); + continue; + } + } + + off = roundup_pow2 (offset, slotinfo[cnt].map->l_tls_align); + if (off - offset < firstbyte) + off += slotinfo[cnt].map->l_tls_align; + + slotinfo[cnt].map->l_tls_offset = off - firstbyte; + if (off - firstbyte - offset > freetop - freebottom) + { + freebottom = offset; + freetop = off - firstbyte; + } + + offset = off + slotinfo[cnt].map->l_tls_blocksize - firstbyte; + } + + _dl_tls_static_used = offset; + _dl_tls_static_size = roundup_pow2 (offset + TLS_STATIC_SURPLUS, + TLS_TCB_ALIGN); +# else +# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined" +# endif + + /* The alignment requirement for the static TLS block. */ + _dl_tls_static_align = max_align; +} + +/* This is called only when the data structure setup was skipped at startup, + when there was no need for it then. Now we have dynamically loaded + something needing TLS, or libpthread needs it. */ +rtld_hidden_proto(_dl_tls_setup) +int +internal_function +_dl_tls_setup (void) +{ + _dl_assert (_dl_tls_dtv_slotinfo_list == NULL); + _dl_assert (_dl_tls_max_dtv_idx == 0); + + const size_t nelem = 2 + TLS_SLOTINFO_SURPLUS; + + _dl_tls_dtv_slotinfo_list + = _dl_calloc (1, (sizeof (struct dtv_slotinfo_list) + + nelem * sizeof (struct dtv_slotinfo))); + if (_dl_tls_dtv_slotinfo_list == NULL) + return -1; + + _dl_tls_dtv_slotinfo_list->len = nelem; + + /* Number of elements in the static TLS block. It can't be zero + because of various assumptions. The one element is null. */ + _dl_tls_static_nelem = _dl_tls_max_dtv_idx = 1; + + /* This initializes more variables for us. */ + _dl_determine_tlsoffset (); + + return 0; +} +rtld_hidden_def (_dl_tls_setup) + +static void * +internal_function +allocate_dtv (void *result) +{ + dtv_t *dtv; + size_t dtv_length; + + /* We allocate a few more elements in the dtv than are needed for the + initial set of modules. This should avoid in most cases expansions + of the dtv. */ + dtv_length = _dl_tls_max_dtv_idx + DTV_SURPLUS; + dtv = _dl_calloc (dtv_length + 2, sizeof (dtv_t)); + if (dtv != NULL) + { + /* This is the initial length of the dtv. */ + dtv[0].counter = dtv_length; + + /* The rest of the dtv (including the generation counter) is + Initialize with zero to indicate nothing there. */ + + /* Add the dtv to the thread data structures. */ + INSTALL_DTV (result, dtv); + } + else + result = NULL; + + return result; +} + +/* Get size and alignment requirements of the static TLS block. */ +void +internal_function +_dl_get_tls_static_info (size_t *sizep, size_t *alignp) +{ + *sizep = _dl_tls_static_size; + *alignp = _dl_tls_static_align; +} + +void * +internal_function +_dl_allocate_tls_storage (void) +{ + void *result; + size_t size = _dl_tls_static_size; + +# if defined(TLS_DTV_AT_TP) + /* Memory layout is: + [ TLS_PRE_TCB_SIZE ] [ TLS_TCB_SIZE ] [ TLS blocks ] + ^ This should be returned. */ + size += (TLS_PRE_TCB_SIZE + _dl_tls_static_align - 1) + & ~(_dl_tls_static_align - 1); +# endif + + /* Allocate a correctly aligned chunk of memory. */ + result = _dl_memalign (_dl_tls_static_align, size); + if (__builtin_expect (result != NULL, 1)) + { + /* Allocate the DTV. */ + void *allocated = result; + +# ifdef TLS_TCB_AT_TP + /* The TCB follows the TLS blocks. */ + result = (char *) result + size - TLS_TCB_SIZE; + + /* Clear the TCB data structure. We can't ask the caller (i.e. + libpthread) to do it, because we will initialize the DTV et al. */ + _dl_memset (result, '\0', TLS_TCB_SIZE); +# elif defined(TLS_DTV_AT_TP) + result = (char *) result + size - _dl_tls_static_size; + + /* Clear the TCB data structure and TLS_PRE_TCB_SIZE bytes before it. + We can't ask the caller (i.e. libpthread) to do it, because we will + initialize the DTV et al. */ + _dl_memset ((char *) result - TLS_PRE_TCB_SIZE, '\0', + TLS_PRE_TCB_SIZE + TLS_TCB_SIZE); +# endif + + result = allocate_dtv (result); + if (result == NULL) + _dl_free (allocated); + } + + return result; +} + +void * +internal_function +_dl_allocate_tls_init (void *result) +{ + if (result == NULL) + /* The memory allocation failed. */ + return NULL; + + dtv_t *dtv = GET_DTV (result); + struct dtv_slotinfo_list *listp; + size_t total = 0; + size_t maxgen = 0; + + /* We have to prepare the dtv for all currently loaded modules using + TLS. For those which are dynamically loaded we add the values + indicating deferred allocation. */ + listp = _dl_tls_dtv_slotinfo_list; + while (1) + { + size_t cnt; + + for (cnt = total == 0 ? 1 : 0; cnt < listp->len; ++cnt) + { + struct link_map *map; + void *dest; + + /* Check for the total number of used slots. */ + if (total + cnt > _dl_tls_max_dtv_idx) + break; + + map = listp->slotinfo[cnt].map; + if (map == NULL) + /* Unused entry. */ + continue; + + /* Keep track of the maximum generation number. This might + not be the generation counter. */ + maxgen = MAX (maxgen, listp->slotinfo[cnt].gen); + + if (map->l_tls_offset == NO_TLS_OFFSET) + { + /* For dynamically loaded modules we simply store + the value indicating deferred allocation. */ + dtv[map->l_tls_modid].pointer.val = TLS_DTV_UNALLOCATED; + dtv[map->l_tls_modid].pointer.is_static = false; + continue; + } + + _dl_assert (map->l_tls_modid == cnt); + _dl_assert (map->l_tls_blocksize >= map->l_tls_initimage_size); +# ifdef TLS_TCB_AT_TP + _dl_assert ((size_t) map->l_tls_offset >= map->l_tls_blocksize); + dest = (char *) result - map->l_tls_offset; +# elif defined(TLS_DTV_AT_TP) + dest = (char *) result + map->l_tls_offset; +# else +# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined" +# endif + + /* Copy the initialization image and clear the BSS part. */ + dtv[map->l_tls_modid].pointer.val = dest; + dtv[map->l_tls_modid].pointer.is_static = true; + _dl_memcpy(dest, map->l_tls_initimage, map->l_tls_initimage_size); + _dl_memset((dest + map->l_tls_initimage_size), '\0', + map->l_tls_blocksize - map->l_tls_initimage_size); + + } + + total += cnt; + if (total >= _dl_tls_max_dtv_idx) + break; + + listp = listp->next; + _dl_assert (listp != NULL); + } + + /* The DTV version is up-to-date now. */ + dtv[0].counter = maxgen; + + return result; +} + +void * +internal_function +_dl_allocate_tls (void *mem) +{ + return _dl_allocate_tls_init (mem == NULL + ? _dl_allocate_tls_storage () + : allocate_dtv (mem)); +} + +void +internal_function +_dl_deallocate_tls (void *tcb, bool dealloc_tcb) +{ + dtv_t *dtv = GET_DTV (tcb); + size_t cnt; + + /* We need to free the memory allocated for non-static TLS. */ + for (cnt = 0; cnt < dtv[-1].counter; ++cnt) + if (! dtv[1 + cnt].pointer.is_static + && dtv[1 + cnt].pointer.val != TLS_DTV_UNALLOCATED) + _dl_free (dtv[1 + cnt].pointer.val); + + /* The array starts with dtv[-1]. */ + if (dtv != _dl_initial_dtv) + _dl_free (dtv - 1); + + if (dealloc_tcb) + { +# ifdef TLS_TCB_AT_TP + /* The TCB follows the TLS blocks. Back up to free the whole block. */ + tcb -= _dl_tls_static_size - TLS_TCB_SIZE; +# elif defined(TLS_DTV_AT_TP) + /* Back up the TLS_PRE_TCB_SIZE bytes. */ + tcb -= (TLS_PRE_TCB_SIZE + _dl_tls_static_align - 1) + & ~(_dl_tls_static_align - 1); +# endif + _dl_free (tcb); + } +} + +static void * +allocate_and_init (struct link_map *map) +{ + void *newp; + + newp = _dl_memalign (map->l_tls_align, map->l_tls_blocksize); + if (newp == NULL) + { + _dl_dprintf(2, "%s:%d: Out of memory!!!\n", __FUNCTION__, __LINE__); + _dl_exit(1); + } + + /* Initialize the memory. */ + _dl_memcpy (newp, map->l_tls_initimage, map->l_tls_initimage_size); + _dl_memset ((newp + map->l_tls_initimage_size), '\0', + map->l_tls_blocksize - map->l_tls_initimage_size); + + return newp; +} + +struct link_map * +_dl_update_slotinfo (unsigned long int req_modid) +{ + struct link_map *the_map = NULL; + dtv_t *dtv = THREAD_DTV (); + + /* The global dl_tls_dtv_slotinfo array contains for each module + index the generation counter current when the entry was created. + This array never shrinks so that all module indices which were + valid at some time can be used to access it. Before the first + use of a new module index in this function the array was extended + appropriately. Access also does not have to be guarded against + modifications of the array. It is assumed that pointer-size + values can be read atomically even in SMP environments. It is + possible that other threads at the same time dynamically load + code and therefore add to the slotinfo list. This is a problem + since we must not pick up any information about incomplete work. + The solution to this is to ignore all dtv slots which were + created after the one we are currently interested. We know that + dynamic loading for this module is completed and this is the last + load operation we know finished. */ + unsigned long int idx = req_modid; + struct dtv_slotinfo_list *listp = _dl_tls_dtv_slotinfo_list; + + _dl_debug_early ("Updating slotinfo for module %d\n", req_modid); + + while (idx >= listp->len) + { + idx -= listp->len; + listp = listp->next; + } + + if (dtv[0].counter < listp->slotinfo[idx].gen) + { + /* The generation counter for the slot is higher than what the + current dtv implements. We have to update the whole dtv but + only those entries with a generation counter <= the one for + the entry we need. */ + size_t new_gen = listp->slotinfo[idx].gen; + size_t total = 0; + + /* We have to look through the entire dtv slotinfo list. */ + listp = _dl_tls_dtv_slotinfo_list; + do + { + size_t cnt; + + for (cnt = total == 0 ? 1 : 0; cnt < listp->len; ++cnt) + { + size_t gen = listp->slotinfo[cnt].gen; + + if (gen > new_gen) + /* This is a slot for a generation younger than the + one we are handling now. It might be incompletely + set up so ignore it. */ + continue; + + /* If the entry is older than the current dtv layout we + know we don't have to handle it. */ + if (gen <= dtv[0].counter) + continue; + + /* If there is no map this means the entry is empty. */ + struct link_map *map = listp->slotinfo[cnt].map; + if (map == NULL) + { + /* If this modid was used at some point the memory + might still be allocated. */ + if (! dtv[total + cnt].pointer.is_static + && dtv[total + cnt].pointer.val != TLS_DTV_UNALLOCATED) + { + _dl_free (dtv[total + cnt].pointer.val); + dtv[total + cnt].pointer.val = TLS_DTV_UNALLOCATED; + } + + continue; + } + + /* Check whether the current dtv array is large enough. */ + size_t modid = map->l_tls_modid; + _dl_assert (total + cnt == modid); + if (dtv[-1].counter < modid) + { + /* Reallocate the dtv. */ + dtv_t *newp; + size_t newsize = _dl_tls_max_dtv_idx + DTV_SURPLUS; + size_t oldsize = dtv[-1].counter; + + _dl_assert (map->l_tls_modid <= newsize); + + if (dtv == _dl_initial_dtv) + { + /* This is the initial dtv that was allocated + during rtld startup using the dl-minimal.c + malloc instead of the real malloc. We can't + free it, we have to abandon the old storage. */ + + newp = _dl_malloc ((2 + newsize) * sizeof (dtv_t)); + if (newp == NULL) + oom (); + _dl_memcpy (newp, &dtv[-1], oldsize * sizeof (dtv_t)); + } + else + { + newp = _dl_realloc (&dtv[-1], + (2 + newsize) * sizeof (dtv_t)); + if (newp == NULL) + oom (); + } + + newp[0].counter = newsize; + + /* Clear the newly allocated part. */ + _dl_memset (newp + 2 + oldsize, '\0', + (newsize - oldsize) * sizeof (dtv_t)); + + /* Point dtv to the generation counter. */ + dtv = &newp[1]; + + /* Install this new dtv in the thread data + structures. */ + INSTALL_NEW_DTV (dtv); + } + + /* If there is currently memory allocate for this + dtv entry free it. */ + /* XXX Ideally we will at some point create a memory + pool. */ + if (! dtv[modid].pointer.is_static + && dtv[modid].pointer.val != TLS_DTV_UNALLOCATED) + /* Note that free is called for NULL is well. We + deallocate even if it is this dtv entry we are + supposed to load. The reason is that we call + memalign and not malloc. */ + _dl_free (dtv[modid].pointer.val); + + /* This module is loaded dynamically- We defer memory + allocation. */ + dtv[modid].pointer.is_static = false; + dtv[modid].pointer.val = TLS_DTV_UNALLOCATED; + + if (modid == req_modid) + the_map = map; + } + + total += listp->len; + } + while ((listp = listp->next) != NULL); + + /* This will be the new maximum generation counter. */ + dtv[0].counter = new_gen; + } + + return the_map; +} + + +/* The generic dynamic and local dynamic model cannot be used in + statically linked applications. */ +void * +__tls_get_addr (GET_ADDR_ARGS) +{ + dtv_t *dtv = THREAD_DTV (); + struct link_map *the_map = NULL; + void *p; + + if (__builtin_expect (dtv[0].counter != _dl_tls_generation, 0)) + { + the_map = _dl_update_slotinfo (GET_ADDR_MODULE); + dtv = THREAD_DTV (); + } + + p = dtv[GET_ADDR_MODULE].pointer.val; + + if (__builtin_expect (p == TLS_DTV_UNALLOCATED, 0)) + { + /* The allocation was deferred. Do it now. */ + if (the_map == NULL) + { + /* Find the link map for this module. */ + size_t idx = GET_ADDR_MODULE; + struct dtv_slotinfo_list *listp = _dl_tls_dtv_slotinfo_list; + + while (idx >= listp->len) + { + idx -= listp->len; + listp = listp->next; + } + + the_map = listp->slotinfo[idx].map; + } + + p = dtv[GET_ADDR_MODULE].pointer.val = allocate_and_init (the_map); + dtv[GET_ADDR_MODULE].pointer.is_static = false; + } + + return (char *) p + GET_ADDR_OFFSET; +} + +void +_dl_add_to_slotinfo (struct link_map *l) +{ + /* Now that we know the object is loaded successfully add + modules containing TLS data to the dtv info table. We + might have to increase its size. */ + struct dtv_slotinfo_list *listp; + struct dtv_slotinfo_list *prevp; + size_t idx = l->l_tls_modid; + + _dl_debug_early("Adding to slotinfo for %s\n", l->l_name); + + /* Find the place in the dtv slotinfo list. */ + listp = _dl_tls_dtv_slotinfo_list; + prevp = NULL; /* Needed to shut up gcc. */ + do + { + /* Does it fit in the array of this list element? */ + if (idx < listp->len) + break; + idx -= listp->len; + prevp = listp; + listp = listp->next; + } + while (listp != NULL); + + if (listp == NULL) + { + /* When we come here it means we have to add a new element + to the slotinfo list. And the new module must be in + the first slot. */ + _dl_assert (idx == 0); + + listp = prevp->next = (struct dtv_slotinfo_list *) + _dl_malloc (sizeof (struct dtv_slotinfo_list) + + TLS_SLOTINFO_SURPLUS * sizeof (struct dtv_slotinfo)); + if (listp == NULL) + { + /* We ran out of memory. We will simply fail this + call but don't undo anything we did so far. The + application will crash or be terminated anyway very + soon. */ + + /* We have to do this since some entries in the dtv + slotinfo array might already point to this + generation. */ + ++_dl_tls_generation; + + _dl_dprintf (_dl_debug_file, + "cannot create TLS data structures: ABORT\n"); + _dl_exit (127); + } + + listp->len = TLS_SLOTINFO_SURPLUS; + listp->next = NULL; + _dl_memset (listp->slotinfo, '\0', + TLS_SLOTINFO_SURPLUS * sizeof (struct dtv_slotinfo)); + } + + /* Add the information into the slotinfo data structure. */ + listp->slotinfo[idx].map = l; + listp->slotinfo[idx].gen = _dl_tls_generation + 1; + /* ??? ideally this would be done once per call to dlopen. However there's + no easy way to indicate whether a library used TLS, so do it here + instead. */ + /* Bump the TLS generation number. */ + _dl_tls_generation++; +} + +/* Taken from glibc/elf/rtld.c */ +static bool tls_init_tp_called; + +/* _dl_error_catch_tsd points to this for the single-threaded case. + It's reset by the thread library for multithreaded programs. */ +void ** __attribute__ ((const)) +_dl_initial_error_catch_tsd (void) +{ + static void *data; + return &data; +} + +#ifdef SHARED +void* +internal_function +init_tls (void); + +rtld_hidden_proto(init_tls) +void * +internal_function +init_tls (void) +{ + /* Number of elements in the static TLS block. */ + _dl_tls_static_nelem = _dl_tls_max_dtv_idx; + + /* Do not do this twice. The audit interface might have required + the DTV interfaces to be set up early. */ + if (_dl_initial_dtv != NULL) + return NULL; + + /* Allocate the array which contains the information about the + dtv slots. We allocate a few entries more than needed to + avoid the need for reallocation. */ + size_t nelem = _dl_tls_max_dtv_idx + 1 + TLS_SLOTINFO_SURPLUS; + + /* Allocate. */ + _dl_assert (_dl_tls_dtv_slotinfo_list == NULL); + _dl_tls_dtv_slotinfo_list = (struct dtv_slotinfo_list *) + _dl_calloc (sizeof (struct dtv_slotinfo_list) + + nelem * sizeof (struct dtv_slotinfo), 1); + /* No need to check the return value. If memory allocation failed + the program would have been terminated. */ + + struct dtv_slotinfo *slotinfo = _dl_tls_dtv_slotinfo_list->slotinfo; + _dl_tls_dtv_slotinfo_list->len = nelem; + _dl_tls_dtv_slotinfo_list->next = NULL; + + /* Fill in the information from the loaded modules. No namespace + but the base one can be filled at this time. */ + int i = 0; + struct link_map *l; + for (l = (struct link_map *) _dl_loaded_modules; l != NULL; l = l->l_next) + if (l->l_tls_blocksize != 0) + { + /* This is a module with TLS data. Store the map reference. + The generation counter is zero. */ + + /* Skeep slot[0]: it will be never used */ + slotinfo[++i].map = l; + } + _dl_assert (i == _dl_tls_max_dtv_idx); + + /* Compute the TLS offsets for the various blocks. */ + _dl_determine_tlsoffset (); + + /* Construct the static TLS block and the dtv for the initial + thread. For some platforms this will include allocating memory + for the thread descriptor. The memory for the TLS block will + never be freed. It should be allocated accordingly. The dtv + array can be changed if dynamic loading requires it. */ + void *tcbp = _dl_allocate_tls_storage (); + if (tcbp == NULL) { + _dl_debug_early("\ncannot allocate TLS data structures for initial thread"); + _dl_exit(30); + } + + /* Store for detection of the special case by __tls_get_addr + so it knows not to pass this dtv to the normal realloc. */ + _dl_initial_dtv = GET_DTV (tcbp); + + /* And finally install it for the main thread. If ld.so itself uses + TLS we know the thread pointer was initialized earlier. */ + const char *lossage = TLS_INIT_TP (tcbp, USE___THREAD); + if(__builtin_expect (lossage != NULL, 0)) { + _dl_debug_early("cannot set up thread-local storage: %s\n", lossage); + _dl_exit(30); + } + tls_init_tp_called = true; + + return tcbp; +} +rtld_hidden_def (init_tls) +#endif + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/frv/dl-debug.h b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/frv/dl-debug.h new file mode 100644 index 00000000..9b146a62 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/frv/dl-debug.h @@ -0,0 +1,29 @@ +/* FR-V FDPIC ELF shared library loader suppport + * Copyright (C) 2003, 2004 Red Hat, Inc. + * Contributed by Alexandre Oliva + * Lots of code copied from ../i386/elfinterp.c, so: + * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald, + * David Engel, Hongjiu Lu and Mitch D'Souza + * Copyright (C) 2001-2002, Erik Andersen + * All rights reserved. + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +static const char *_dl_reltypes_tab[] = +{ + [0] "R_FRV_NONE", "R_FRV_32", + [2] "R_FRV_LABEL16", "R_FRV_LABEL24", + [4] "R_FRV_LO16", "R_FRV_HI16", + [6] "R_FRV_GPREL12", "R_FRV_GPRELU12", + [8] "R_FRV_GPREL32", "R_FRV_GPRELHI", "R_FRV_GPRELLO", + [11] "R_FRV_GOT12", "R_FRV_GOTHI", "R_FRV_GOTLO", + [14] "R_FRV_FUNCDESC", + [15] "R_FRV_FUNCDESC_GOT12", "R_FRV_FUNCDESC_GOTHI", "R_FRV_FUNCDESC_GOTLO", + [18] "R_FRV_FUNCDESC_VALUE", "R_FRV_FUNCDESC_GOTOFF12", + [20] "R_FRV_FUNCDESC_GOTOFFHI", "R_FRV_FUNCDESC_GOTOFFLO", + [22] "R_FRV_GOTOFF12", "R_FRV_GOTOFFHI", "R_FRV_GOTOFFLO", +#if 0 + [200] "R_FRV_GNU_VTINHERIT", "R_FRV_GNU_VTENTRY" +#endif +}; diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/frv/dl-inlines.h b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/frv/dl-inlines.h new file mode 100644 index 00000000..95233a7c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/frv/dl-inlines.h @@ -0,0 +1,456 @@ +/* Copyright (C) 2003, 2004 Red Hat, Inc. + * Contributed by Alexandre Oliva + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#ifndef _dl_assert +# define _dl_assert(expr) +#endif + +/* Initialize a DL_LOADADDR_TYPE given a got pointer and a complete + load map. */ +static __always_inline void +__dl_init_loadaddr_map (struct elf32_fdpic_loadaddr *loadaddr, void *got_value, + struct elf32_fdpic_loadmap *map) +{ + if (map->version != 0) + { + SEND_EARLY_STDERR ("Invalid loadmap version number\n"); + _dl_exit(-1); + } + if (map->nsegs == 0) + { + SEND_EARLY_STDERR ("Invalid segment count in loadmap\n"); + _dl_exit(-1); + } + loadaddr->got_value = got_value; + loadaddr->map = map; +} + +/* Figure out how many LOAD segments there are in the given headers, + and allocate a block for the load map big enough for them. + got_value will be properly initialized later on, with INIT_GOT. */ +static __always_inline int +__dl_init_loadaddr (struct elf32_fdpic_loadaddr *loadaddr, Elf32_Phdr *ppnt, + int pcnt) +{ + int count = 0, i; + size_t size; + + for (i = 0; i < pcnt; i++) + if (ppnt[i].p_type == PT_LOAD) + count++; + + loadaddr->got_value = 0; + + size = sizeof (struct elf32_fdpic_loadmap) + + sizeof (struct elf32_fdpic_loadseg) * count; + loadaddr->map = _dl_malloc (size); + if (! loadaddr->map) + _dl_exit (-1); + + loadaddr->map->version = 0; + loadaddr->map->nsegs = 0; + + return count; +} + +/* Incrementally initialize a load map. */ +static __always_inline void +__dl_init_loadaddr_hdr (struct elf32_fdpic_loadaddr loadaddr, void *addr, + Elf32_Phdr *phdr, int maxsegs) +{ + struct elf32_fdpic_loadseg *segdata; + + if (loadaddr.map->nsegs == maxsegs) + _dl_exit (-1); + + segdata = &loadaddr.map->segs[loadaddr.map->nsegs++]; + segdata->addr = (Elf32_Addr) addr; + segdata->p_vaddr = phdr->p_vaddr; + segdata->p_memsz = phdr->p_memsz; + +#if defined (__SUPPORT_LD_DEBUG__) + { + extern char *_dl_debug; + extern int _dl_debug_file; + if (_dl_debug) + _dl_dprintf(_dl_debug_file, "%i: mapped %x at %x, size %x\n", + loadaddr.map->nsegs-1, + segdata->p_vaddr, segdata->addr, segdata->p_memsz); + } +#endif +} + +static __always_inline void __dl_loadaddr_unmap +(struct elf32_fdpic_loadaddr loadaddr, struct funcdesc_ht *funcdesc_ht); + +/* Figure out whether the given address is in one of the mapped + segments. */ +static __always_inline int +__dl_addr_in_loadaddr (void *p, struct elf32_fdpic_loadaddr loadaddr) +{ + struct elf32_fdpic_loadmap *map = loadaddr.map; + int c; + + for (c = 0; c < map->nsegs; c++) + if ((void*)map->segs[c].addr <= p + && (char*)p < (char*)map->segs[c].addr + map->segs[c].p_memsz) + return 1; + + return 0; +} + +static __always_inline void * _dl_funcdesc_for (void *entry_point, void *got_value); + +/* The hashcode handling code below is heavily inspired in libiberty's + hashtab code, but with most adaptation points and support for + deleting elements removed. + + Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. + Contributed by Vladimir Makarov (vmakarov@cygnus.com). */ + +static __always_inline unsigned long +higher_prime_number (unsigned long n) +{ + /* These are primes that are near, but slightly smaller than, a + power of two. */ + static const unsigned long primes[] = { + (unsigned long) 7, + (unsigned long) 13, + (unsigned long) 31, + (unsigned long) 61, + (unsigned long) 127, + (unsigned long) 251, + (unsigned long) 509, + (unsigned long) 1021, + (unsigned long) 2039, + (unsigned long) 4093, + (unsigned long) 8191, + (unsigned long) 16381, + (unsigned long) 32749, + (unsigned long) 65521, + (unsigned long) 131071, + (unsigned long) 262139, + (unsigned long) 524287, + (unsigned long) 1048573, + (unsigned long) 2097143, + (unsigned long) 4194301, + (unsigned long) 8388593, + (unsigned long) 16777213, + (unsigned long) 33554393, + (unsigned long) 67108859, + (unsigned long) 134217689, + (unsigned long) 268435399, + (unsigned long) 536870909, + (unsigned long) 1073741789, + (unsigned long) 2147483647, + /* 4294967291L */ + ((unsigned long) 2147483647) + ((unsigned long) 2147483644), + }; + + const unsigned long *low = &primes[0]; + const unsigned long *high = &primes[sizeof(primes) / sizeof(primes[0])]; + + while (low != high) + { + const unsigned long *mid = low + (high - low) / 2; + if (n > *mid) + low = mid + 1; + else + high = mid; + } + +#if 0 + /* If we've run out of primes, abort. */ + if (n > *low) + { + fprintf (stderr, "Cannot find prime bigger than %lu\n", n); + abort (); + } +#endif + + return *low; +} + +struct funcdesc_ht +{ + /* Table itself. */ + struct funcdesc_value **entries; + + /* Current size (in entries) of the hash table */ + size_t size; + + /* Current number of elements. */ + size_t n_elements; +}; + +static __always_inline int +hash_pointer (const void *p) +{ + return (int) ((long)p >> 3); +} + +static __always_inline struct funcdesc_ht * +htab_create (void) +{ + struct funcdesc_ht *ht = _dl_malloc (sizeof (struct funcdesc_ht)); + + if (! ht) + return NULL; + ht->size = 3; + ht->entries = _dl_malloc (sizeof (struct funcdesc_ht_value *) * ht->size); + if (! ht->entries) + return NULL; + + ht->n_elements = 0; + + _dl_memset (ht->entries, 0, sizeof (struct funcdesc_ht_value *) * ht->size); + + return ht; +} + +/* This is only called from _dl_loadaddr_unmap, so it's safe to call + _dl_free(). See the discussion below. */ +static __always_inline void +htab_delete (struct funcdesc_ht *htab) +{ + int i; + + for (i = htab->size - 1; i >= 0; i--) + if (htab->entries[i]) + _dl_free (htab->entries[i]); + + _dl_free (htab->entries); + _dl_free (htab); +} + +/* Similar to htab_find_slot, but without several unwanted side effects: + - Does not call htab->eq_f when it finds an existing entry. + - Does not change the count of elements/searches/collisions in the + hash table. + This function also assumes there are no deleted entries in the table. + HASH is the hash value for the element to be inserted. */ + +static __always_inline struct funcdesc_value ** +find_empty_slot_for_expand (struct funcdesc_ht *htab, int hash) +{ + size_t size = htab->size; + unsigned int index = hash % size; + struct funcdesc_value **slot = htab->entries + index; + int hash2; + + if (! *slot) + return slot; + + hash2 = 1 + hash % (size - 2); + for (;;) + { + index += hash2; + if (index >= size) + index -= size; + + slot = htab->entries + index; + if (! *slot) + return slot; + } +} + +/* The following function changes size of memory allocated for the + entries and repeatedly inserts the table elements. The occupancy + of the table after the call will be about 50%. Naturally the hash + table must already exist. Remember also that the place of the + table entries is changed. If memory allocation failures are allowed, + this function will return zero, indicating that the table could not be + expanded. If all goes well, it will return a non-zero value. */ + +static __always_inline int +htab_expand (struct funcdesc_ht *htab) +{ + struct funcdesc_value **oentries; + struct funcdesc_value **olimit; + struct funcdesc_value **p; + struct funcdesc_value **nentries; + size_t nsize; + + oentries = htab->entries; + olimit = oentries + htab->size; + + /* Resize only when table after removal of unused elements is either + too full or too empty. */ + if (htab->n_elements * 2 > htab->size) + nsize = higher_prime_number (htab->n_elements * 2); + else + nsize = htab->size; + + nentries = _dl_malloc (sizeof (struct funcdesc_value *) * nsize); + _dl_memset (nentries, 0, sizeof (struct funcdesc_value *) * nsize); + if (nentries == NULL) + return 0; + htab->entries = nentries; + htab->size = nsize; + + p = oentries; + do + { + if (*p) + *find_empty_slot_for_expand (htab, hash_pointer ((*p)->entry_point)) + = *p; + + p++; + } + while (p < olimit); + +#if 0 /* We can't tell whether this was allocated by the _dl_malloc() + built into ld.so or malloc() in the main executable or libc, + and calling free() for something that wasn't malloc()ed could + do Very Bad Things (TM). Take the conservative approach + here, potentially wasting as much memory as actually used by + the hash table, even if multiple growths occur. That's not + so bad as to require some overengineered solution that would + enable us to keep track of how it was allocated. */ + _dl_free (oentries); +#endif + return 1; +} + +/* This function searches for a hash table slot containing an entry + equal to the given element. To delete an entry, call this with + INSERT = 0, then call htab_clear_slot on the slot returned (possibly + after doing some checks). To insert an entry, call this with + INSERT = 1, then write the value you want into the returned slot. + When inserting an entry, NULL may be returned if memory allocation + fails. */ + +static __always_inline struct funcdesc_value ** +htab_find_slot (struct funcdesc_ht *htab, void *ptr, int insert) +{ + unsigned int index; + int hash, hash2; + size_t size; + struct funcdesc_value **entry; + + if (htab->size * 3 <= htab->n_elements * 4 + && htab_expand (htab) == 0) + return NULL; + + hash = hash_pointer (ptr); + + size = htab->size; + index = hash % size; + + entry = &htab->entries[index]; + if (!*entry) + goto empty_entry; + else if ((*entry)->entry_point == ptr) + return entry; + + hash2 = 1 + hash % (size - 2); + for (;;) + { + index += hash2; + if (index >= size) + index -= size; + + entry = &htab->entries[index]; + if (!*entry) + goto empty_entry; + else if ((*entry)->entry_point == ptr) + return entry; + } + + empty_entry: + if (!insert) + return NULL; + + htab->n_elements++; + return entry; +} + +void * +_dl_funcdesc_for (void *entry_point, void *got_value) +{ + struct elf_resolve *tpnt = ((void**)got_value)[2]; + struct funcdesc_ht *ht = tpnt->funcdesc_ht; + struct funcdesc_value **entry; + + _dl_assert (got_value == tpnt->loadaddr.got_value); + + if (! ht) + { + ht = htab_create (); + if (! ht) + return (void*)-1; + tpnt->funcdesc_ht = ht; + } + + entry = htab_find_slot (ht, entry_point, 1); + if (*entry) + { + _dl_assert ((*entry)->entry_point == entry_point); + return _dl_stabilize_funcdesc (*entry); + } + + *entry = _dl_malloc (sizeof (struct funcdesc_value)); + (*entry)->entry_point = entry_point; + (*entry)->got_value = got_value; + + return _dl_stabilize_funcdesc (*entry); +} + +static __always_inline void const * +_dl_lookup_address (void const *address) +{ + struct elf_resolve *rpnt; + struct funcdesc_value const *fd; + + /* Make sure we don't make assumptions about its alignment. */ + __asm__ ("" : "+r" (address)); + + if ((Elf32_Addr)address & 7) + /* It's not a function descriptor. */ + return address; + + fd = (struct funcdesc_value const *)address; + + for (rpnt = _dl_loaded_modules; rpnt; rpnt = rpnt->next) + { + if (! rpnt->funcdesc_ht) + continue; + + if (fd->got_value != rpnt->loadaddr.got_value) + continue; + + address = htab_find_slot (rpnt->funcdesc_ht, (void*)fd->entry_point, 0); + + if (address && *(struct funcdesc_value *const*)address == fd) + { + address = (*(struct funcdesc_value *const*)address)->entry_point; + break; + } + else + address = fd; + } + + return address; +} + +void +__dl_loadaddr_unmap (struct elf32_fdpic_loadaddr loadaddr, + struct funcdesc_ht *funcdesc_ht) +{ + int i; + + for (i = 0; i < loadaddr.map->nsegs; i++) + _dl_munmap ((void*)loadaddr.map->segs[i].addr, + loadaddr.map->segs[i].p_memsz); + + /* _dl_unmap is only called for dlopen()ed libraries, for which + calling free() is safe, or before we've completed the initial + relocation, in which case calling free() is probably pointless, + but still safe. */ + _dl_free (loadaddr.map); + if (funcdesc_ht) + htab_delete (funcdesc_ht); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/frv/dl-startup.h b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/frv/dl-startup.h new file mode 100644 index 00000000..72bea680 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/frv/dl-startup.h @@ -0,0 +1,133 @@ +/* Copyright (C) 2003 Red Hat, Inc. + * Contributed by Alexandre Oliva + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* Any assembly language/system dependent hacks needed to setup + * boot1.c so it will work as expected and cope with whatever platform + * specific wierdness is needed for this architecture. + + * We override the default _dl_boot function, and replace it with a + * bit of asm. Then call the real _dl_boot function, which is now + * named _dl_boot2. */ + +/* At program start-up, gr16 contains a pointer to a + elf32_fdpic_loadmap that describes how the executable was loaded + into memory. gr17 contains a pointer to the interpreter (our!) + loadmap, if there is an interpreter, or 0 if we're being run as an + executable. gr18 holds a pointer to the interpreter's dynamic + section, if there is an interpreter, or to the executable's dynamic + section, otherwise. If the executable is not dynamic, gr18 is 0. + + We rely on the fact that the linker adds a pointer to the + _GLOBAL_OFFSET_TABLE_ as the last ROFIXUP entry, and that + __self_reloc returns the relocated pointer to us, so that we can + use this value to initialize the PIC register. */ + +__asm__("" \ +" .text\n" \ +" .global _dl_boot\n" \ +" .type _dl_boot,@function\n" \ +"_dl_boot:\n" \ +" call .Lcall\n" \ +".Lcall:\n" \ +" movsg lr, gr4\n" \ +" sethi.p #gprelhi(.Lcall), gr5\n"\ +" setlo #gprello(.Lcall), gr5\n"\ +" mov.p gr17, gr8\n" \ +" cmp gr17, gr0, icc0\n" \ +" sub.p gr4, gr5, gr4\n" \ +" ckeq icc0, cc4\n" \ +" cmov.p gr16, gr8, cc4, 1\n" \ +" sethi #gprelhi(__ROFIXUP_LIST__), gr9\n" \ +" sethi.p #gprelhi(__ROFIXUP_END__), gr10\n" \ +" setlo #gprello(__ROFIXUP_LIST__), gr9\n" \ +" setlo.p #gprello(__ROFIXUP_END__), gr10\n" \ +" add gr9, gr4, gr9\n" \ +" add.p gr10, gr4, gr10\n" \ +" call __self_reloc\n" \ +" mov.p gr8, gr15\n" \ +" mov gr16, gr9\n" \ +" mov.p gr17, gr10\n" \ +" mov gr18, gr11\n" \ +" addi.p sp, #4, gr13\n" \ +" addi sp, #-8, sp\n" \ +" mov.p sp, gr12\n" \ +" call _dl_boot2\n" \ +" ldd.p @(sp, gr0), gr14\n" \ +" addi sp, #8, sp\n" \ +" movgs gr0, lr\n" \ +" jmpl @(gr14, gr0)\n" \ +" .size _dl_boot,.-_dl_boot\n" \ +); + +#define _dl_boot _dl_boot2 +#define DL_BOOT(X) \ +static void __attribute__ ((used)) \ +_dl_boot (void *dl_boot_got_pointer, \ + struct elf32_fdpic_loadmap *dl_boot_progmap, \ + struct elf32_fdpic_loadmap *dl_boot_ldsomap, \ + Elf32_Dyn *dl_boot_ldso_dyn_pointer, \ + struct funcdesc_value *dl_main_funcdesc, \ + X) + +struct elf32_fdpic_loadmap; + +/* + * Get a pointer to the argv array. On many platforms this can be just + * the address of the first argument, on other platforms we need to + * do something a little more subtle here. + */ +#define GET_ARGV(ARGVP, ARGS) ARGVP = ((unsigned long*) ARGS) + +/* + * Compute the GOT address. On several platforms, we use assembly + * here. on FR-V FDPIC, there's no way to compute the GOT address, + * since the offset between text and data is not fixed, so we arrange + * for the assembly _dl_boot to pass this value as an argument to + * _dl_boot. */ +#define DL_BOOT_COMPUTE_GOT(got) ((got) = dl_boot_got_pointer) + +#define DL_BOOT_COMPUTE_DYN(dpnt, got, load_addr) \ + ((dpnt) = dl_boot_ldso_dyn_pointer) + +/* + * Here is a macro to perform a relocation. This is only used when + * bootstrapping the dynamic loader. RELP is the relocation that we + * are performing, REL is the pointer to the address we are relocating. + * SYMBOL is the symbol involved in the relocation, and LOAD is the + * load address. + */ +#define PERFORM_BOOTSTRAP_RELOC(RELP,REL,SYMBOL,LOAD,SYMTAB) \ + switch(ELF32_R_TYPE((RELP)->r_info)){ \ + case R_FRV_32: \ + *(REL) += (SYMBOL); \ + break; \ + case R_FRV_FUNCDESC_VALUE: \ + { \ + struct funcdesc_value fv = { \ + (void*)((SYMBOL) + *(REL)), \ + (LOAD).got_value \ + }; \ + *(struct funcdesc_value volatile *)(REL) = fv; \ + break; \ + } \ + default: \ + _dl_exit(1); \ + } + +/* + * Transfer control to the user's application, once the dynamic loader + * is done. We return the address of the function's entry point to + * _dl_boot, see boot1_arch.h. + */ +#define START() do { \ + struct elf_resolve *exec_mod = _dl_loaded_modules; \ + dl_main_funcdesc->entry_point = _dl_elf_main; \ + while (exec_mod->libtype != elf_executable) \ + exec_mod = exec_mod->next; \ + dl_main_funcdesc->got_value = exec_mod->loadaddr.got_value; \ + /* _dl_dprintf(2, "entry point is (%x,%x)\n", dl_main_funcdesc->entry_point, dl_main_funcdesc->got_value); */ \ + return; \ +} while (0) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/frv/dl-syscalls.h b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/frv/dl-syscalls.h new file mode 100644 index 00000000..a4bff1d4 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/frv/dl-syscalls.h @@ -0,0 +1,175 @@ +/* Copyright (C) 2003, 2004 Red Hat, Inc. + * Contributed by Alexandre Oliva + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* We can't use the real errno in ldso, since it has not yet + * been dynamicly linked in yet. */ +#include "sys/syscall.h" +extern int _dl_errno; +#undef __set_errno +#define __set_errno(X) {(_dl_errno) = (X);} +#include + +/* The code below is extracted from libc/sysdeps/linux/frv/_mmap.c */ + +#if DYNAMIC_LOADER_IN_SIMULATOR +#define __NR___syscall_mmap2 __NR_mmap2 +static __inline__ _syscall6(__ptr_t, __syscall_mmap2, __ptr_t, addr, + size_t, len, int, prot, int, flags, int, fd, off_t, offset); + +/* Make sure we don't get another definition of _dl_mmap from the + machine-independent code. */ +#undef __NR_mmap +#undef __NR_mmap2 + +/* This is always 12, even on architectures where PAGE_SHIFT != 12. */ +# ifndef MMAP2_PAGE_SHIFT +# define MMAP2_PAGE_SHIFT 12 +# endif + +#include /* for PAGE_SIZE */ +static __always_inline void *_dl_memset(void*,int,size_t); +static __always_inline ssize_t _dl_pread(int fd, void *buf, size_t count, off_t offset); + +static __ptr_t +_dl_mmap(__ptr_t addr, size_t len, int prot, int flags, int fd, __off_t offset) +{ + size_t plen = (len + PAGE_SIZE - 1) & -PAGE_SIZE; + +/* This is a hack to enable the dynamic loader to run within a + simulator that doesn't support mmap, with a number of very ugly + tricks. Also, it's not as useful as it sounds, since only dynamic + executables without DT_NEEDED dependencies can be run. AFAIK, they + can only be created with -pie. This trick suffices to enable the + dynamic loader to obtain a blank page that it maps early in the + bootstrap. */ + if ((flags & MAP_FIXED) == 0) + { + void *_dl_mmap_base = 0; + __ptr_t *ret = 0; + + if (! _dl_mmap_base) + { + void *stack; + __asm__ ("mov sp, %0" : "=r" (stack)); + _dl_mmap_base = (void *)(((long)stack + 2 * PAGE_SIZE) & -PAGE_SIZE); + retry: + if (((void **)_dl_mmap_base)[0] == _dl_mmap_base + && ((void **)_dl_mmap_base)[1023] == _dl_mmap_base + && (((void **)_dl_mmap_base)[177] + == ((void **)_dl_mmap_base)[771])) + { + while (((void**)_dl_mmap_base)[177]) + { + _dl_mmap_base = ((void**)_dl_mmap_base)[177]; + if (!(((void **)_dl_mmap_base)[0] == _dl_mmap_base + && ((void **)_dl_mmap_base)[1023] == _dl_mmap_base + && (((void **)_dl_mmap_base)[177] + == ((void**)_dl_mmap_base)[771]))) + ((void(*)())0)(); + } + } + else + { + int i; + for (i = 0; i < (int)PAGE_SIZE; i++) + if (*(char*)(_dl_mmap_base + i)) + break; + if (i != PAGE_SIZE) + { + _dl_mmap_base = (void*)((long)_dl_mmap_base + PAGE_SIZE); + goto retry; + } + ((void**)_dl_mmap_base)[-1] = + ((void**)_dl_mmap_base)[0] = + ((void**)_dl_mmap_base)[1023] = + _dl_mmap_base; + } + } + + if (_dl_mmap_base) + { + if (!(((void **)_dl_mmap_base)[0] == _dl_mmap_base + && ((void **)_dl_mmap_base)[1023] == _dl_mmap_base + && (((void **)_dl_mmap_base)[177] + == ((void**)_dl_mmap_base)[771]))) + ((void(*)())0)(); + ret = (__ptr_t)((char*)_dl_mmap_base + PAGE_SIZE); + _dl_mmap_base = + ((void**)_dl_mmap_base)[177] = + ((void**)_dl_mmap_base)[771] = + (char*)_dl_mmap_base + plen + PAGE_SIZE; + ((void**)_dl_mmap_base)[0] = + ((void**)_dl_mmap_base)[1023] = + _dl_mmap_base; + } + + if ((flags & MAP_ANONYMOUS) != 0) + { + _dl_memset (ret, 0, plen); + return ret; + } + + flags |= MAP_FIXED; + addr = ret; + } + if (offset & ((1 << MMAP2_PAGE_SHIFT) - 1)) { +#if 0 + __set_errno (EINVAL); +#endif + return MAP_FAILED; + } + if ((flags & MAP_FIXED) != 0) + { + if (_dl_pread(fd, addr, len, offset) != (ssize_t)len) + return (void*)MAP_FAILED; + if (plen != len) + _dl_memset (addr + len, 0, plen - len); + return addr; + } + return(__syscall_mmap2(addr, len, prot, flags, fd, (off_t) (offset >> MMAP2_PAGE_SHIFT))); +} +#endif + +#ifdef __NR_pread +#ifdef DYNAMIC_LOADER_IN_SIMULATOR +#include + +#define __NR___syscall_lseek __NR_lseek +static __always_inline unsigned long _dl_read(int fd, const void *buf, unsigned long count); + +static __always_inline _syscall3(__off_t, __syscall_lseek, int, fd, __off_t, offset, + int, whence); +static __always_inline ssize_t +_dl_pread(int fd, void *buf, size_t count, off_t offset) +{ + __off_t orig = __syscall_lseek (fd, 0, SEEK_CUR); + ssize_t ret; + + if (orig == -1) + return -1; + + if (__syscall_lseek (fd, offset, SEEK_SET) != offset) + return -1; + + ret = _dl_read (fd, buf, count); + + if (__syscall_lseek (fd, orig, SEEK_SET) != orig) + ((void(*)())0)(); + + return ret; +} +#else +#define __NR___syscall_pread __NR_pread +static __always_inline _syscall5(ssize_t, __syscall_pread, int, fd, void *, buf, + size_t, count, off_t, offset_hi, off_t, offset_lo); + +static __always_inline ssize_t +_dl_pread(int fd, void *buf, size_t count, off_t offset) +{ + return(__syscall_pread(fd,buf,count,__LONG_LONG_PAIR (offset >> 31, offset))); +} +#endif +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/frv/dl-sysdep.h b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/frv/dl-sysdep.h new file mode 100644 index 00000000..e9c847a6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/frv/dl-sysdep.h @@ -0,0 +1,188 @@ +/* Copyright (C) 2003, 2004 Red Hat, Inc. + * Contributed by Alexandre Oliva + * Based on ../i386/dl-sysdep.h + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* + * Various assembly language/system dependent hacks that are required + * so that we can minimize the amount of platform specific code. + */ + +/* + * Define this if the system uses RELOCA. + */ +#undef ELF_USES_RELOCA + +/* JMPREL relocs are inside the DT_RELA table. */ +#define ELF_MACHINE_PLTREL_OVERLAP + +#define DL_NO_COPY_RELOCS + +/* + * Initialization sequence for a GOT. Copy the resolver function + * descriptor and the pointer to the elf_resolve/link_map data + * structure. Initialize the got_value in the module while at that. + */ +#define INIT_GOT(GOT_BASE,MODULE) \ +{ \ + (MODULE)->loadaddr.got_value = (GOT_BASE); \ + GOT_BASE[0] = ((unsigned long *)&_dl_linux_resolve)[0]; \ + GOT_BASE[1] = ((unsigned long *)&_dl_linux_resolve)[1]; \ + GOT_BASE[2] = (unsigned long) MODULE; \ +} + +/* Here we define the magic numbers that this dynamic loader should accept */ +#define MAGIC1 EM_CYGNUS_FRV +#undef MAGIC2 + +/* Used for error messages */ +#define ELF_TARGET "FR-V" + +/* Need bootstrap relocations */ +#define ARCH_NEEDS_BOOTSTRAP_RELOCS + +struct elf_resolve; + +struct funcdesc_value +{ + void *entry_point; + void *got_value; +} __attribute__((__aligned__(8))); + + +extern int _dl_linux_resolve(void) __attribute__((__visibility__("hidden"))); + +struct funcdesc_ht; + +/* We must force strings used early in the bootstrap into the data + segment, such that they are referenced with GOTOFF instead of + GPREL, because GPREL needs the GOT to have already been + relocated. */ +#undef SEND_EARLY_STDERR +#define SEND_EARLY_STDERR(S) \ + do { static char __s[] = (S); SEND_STDERR (__s); } while (0) + +#define DL_LOADADDR_TYPE struct elf32_fdpic_loadaddr + +#define DL_RELOC_ADDR(ADDR, LOADADDR) \ + (__reloc_pointer ((void*)(ADDR), (LOADADDR).map)) + +#define DL_ADDR_TO_FUNC_PTR(ADDR, LOADADDR) \ + ((void(*)(void)) _dl_funcdesc_for ((void*)(ADDR), (LOADADDR).got_value)) + +#define _dl_stabilize_funcdesc(val) \ + ({ __asm__ ("" : "+m" (*(val))); (val); }) + +#define DL_CALL_FUNC_AT_ADDR(ADDR, LOADADDR, SIGNATURE, ...) \ + ({ struct funcdesc_value fd = { (void*)(ADDR), (LOADADDR).got_value }; \ + void (*pf)(void) = (void*) _dl_stabilize_funcdesc (&fd); \ + (* SIGNATURE pf)(__VA_ARGS__); }) + +#define DL_INIT_LOADADDR_BOOT(LOADADDR, BASEADDR) \ + (__dl_init_loadaddr_map (&(LOADADDR), dl_boot_got_pointer, \ + dl_boot_ldsomap ?: dl_boot_progmap)) + +#define DL_INIT_LOADADDR_PROG(LOADADDR, BASEADDR) \ + (__dl_init_loadaddr_map (&(LOADADDR), 0, dl_boot_progmap)) + +#define DL_INIT_LOADADDR_EXTRA_DECLS \ + int dl_init_loadaddr_load_count; +#define DL_INIT_LOADADDR(LOADADDR, BASEADDR, PHDR, PHDRCNT) \ + (dl_init_loadaddr_load_count = \ + __dl_init_loadaddr (&(LOADADDR), (PHDR), (PHDRCNT))) +#define DL_INIT_LOADADDR_HDR(LOADADDR, ADDR, PHDR) \ + (__dl_init_loadaddr_hdr ((LOADADDR), (ADDR), (PHDR), \ + dl_init_loadaddr_load_count)) +#define DL_LOADADDR_UNMAP(LOADADDR, LEN) \ + (__dl_loadaddr_unmap ((LOADADDR), (NULL))) +#define DL_LIB_UNMAP(LIB, LEN) \ + (__dl_loadaddr_unmap ((LIB)->loadaddr, (LIB)->funcdesc_ht)) +#define DL_LOADADDR_BASE(LOADADDR) \ + ((LOADADDR).got_value) + +/* This is called from dladdr(), such that we map a function + descriptor's address to the function's entry point before trying to + find in which library it's defined. */ +#define DL_LOOKUP_ADDRESS(ADDRESS) (_dl_lookup_address (ADDRESS)) + +#define DL_ADDR_IN_LOADADDR(ADDR, TPNT, TFROM) \ + (! (TFROM) && __dl_addr_in_loadaddr ((void*)(ADDR), (TPNT)->loadaddr)) + +/* Make sure we only load libraries that use the same number of + general-purpose and floating-point registers the dynamic loader was + compiled for. */ +#define DL_CHECK_REG_COUNT(flags) \ + (((flags & EF_FRV_GPR_MASK) == EF_FRV_GPR_32 ? __FRV_GPR__ == 32 : 1) \ + && ((flags & EF_FRV_GPR_MASK) == EF_FRV_GPR_64 ? __FRV_GPR__ == 64 : 1) \ + && ((flags & EF_FRV_FPR_MASK) == EF_FRV_FPR_32 ? __FRV_FPR__ == 32 : 1) \ + && ((flags & EF_FRV_FPR_MASK) == EF_FRV_FPR_64 ? __FRV_FPR__ == 64 : 1) \ + && ((flags & EF_FRV_FPR_MASK) == EF_FRV_FPR_NONE ? __FRV_FPR__ == 0 : 1)) + +/* We only support loading FDPIC independently-relocatable shared + libraries. It probably wouldn't be too hard to support loading + shared libraries that require relocation by the same amount, but we + don't know that they exist or would be useful, and the dynamic + loader code could leak the whole-library map unless we keeping a + bit more state for DL_LOADADDR_UNMAP and DL_LIB_UNMAP, so let's + keep things simple for now. */ +#define DL_CHECK_LIB_TYPE(epnt, piclib, _dl_progname, libname) \ +do \ +{ \ + if (((epnt)->e_flags & EF_FRV_FDPIC) && ! ((epnt)->e_flags & EF_FRV_PIC)) \ + (piclib) = 2; \ + else \ + { \ + _dl_internal_error_number = LD_ERROR_NOTDYN; \ + _dl_dprintf(2, "%s: '%s' is not an FDPIC shared library" \ + "\n", (_dl_progname), (libname)); \ + _dl_close(infile); \ + return NULL; \ + } \ +\ + if (! DL_CHECK_REG_COUNT ((epnt)->e_flags)) \ + { \ + _dl_internal_error_number = LD_ERROR_NOTDYN; \ + _dl_dprintf(2, "%s: '%s' assumes different register counts" \ + "\n", (_dl_progname), (libname)); \ + _dl_close(infile); \ + } \ +} \ +while (0) + +/* We want want to apply all relocations in the interpreter during + bootstrap. Because of this, we have to skip the interpreter + relocations in _dl_parse_relocation_information(), see + elfinterp.c. */ +#define DL_SKIP_BOOTSTRAP_RELOC(SYMTAB, INDEX, STRTAB) 0 + +#ifdef __NR_pread +#define _DL_PREAD(FD, BUF, SIZE, OFFSET) \ + (_dl_pread((FD), (BUF), (SIZE), (OFFSET))) +#endif + +/* We want to return to dlsym() a function descriptor if the symbol + turns out to be a function. */ +#define DL_FIND_HASH_VALUE(TPNT, TYPE_CLASS, SYM) \ + (((TYPE_CLASS) & ELF_RTYPE_CLASS_DLSYM) \ + && ELF32_ST_TYPE((SYM)->st_info) == STT_FUNC \ + ? _dl_funcdesc_for (DL_RELOC_ADDR ((SYM)->st_value, (TPNT)->loadaddr), \ + (TPNT)->loadaddr.got_value) \ + : DL_RELOC_ADDR ((SYM)->st_value, (TPNT)->loadaddr)) + +#define DL_GET_READY_TO_RUN_EXTRA_PARMS \ + , struct elf32_fdpic_loadmap *dl_boot_progmap +#define DL_GET_READY_TO_RUN_EXTRA_ARGS \ + , dl_boot_progmap + + + + +#ifdef __USE_GNU +# include +#else +# define __USE_GNU +# include +# undef __USE_GNU +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/frv/elfinterp.c b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/frv/elfinterp.c new file mode 100644 index 00000000..4b94033d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/frv/elfinterp.c @@ -0,0 +1,347 @@ +/* FR-V FDPIC ELF shared library loader suppport + * Copyright (C) 2003, 2004 Red Hat, Inc. + * Contributed by Alexandre Oliva + * Lots of code copied from ../i386/elfinterp.c, so: + * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald, + * David Engel, Hongjiu Lu and Mitch D'Souza + * Copyright (C) 2001-2002, Erik Andersen + * All rights reserved. + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +/* Program to load an ELF binary on a linux system, and run it. + References to symbols in sharable libraries can be resolved by either + an ELF sharable library or a linux style of shared library. */ + +/* Disclaimer: I have never seen any AT&T source code for SVr4, nor have + I ever taken any courses on internals. This program was developed using + information available through the book "UNIX SYSTEM V RELEASE 4, + Programmers guide: Ansi C and Programming Support Tools", which did + a more than adequate job of explaining everything required to get this + working. */ + +struct funcdesc_value volatile attribute_hidden * +_dl_linux_resolver (struct elf_resolve *tpnt, int reloc_entry) +{ + ELF_RELOC *this_reloc; + char *strtab; + Elf32_Sym *symtab; + int symtab_index; + char *rel_addr; + struct elf_resolve *new_tpnt; + char *new_addr; + struct funcdesc_value funcval; + struct funcdesc_value volatile *got_entry; + char *symname; + + rel_addr = DL_RELOC_ADDR (tpnt->dynamic_info[DT_JMPREL], + tpnt->loadaddr); + + this_reloc = (ELF_RELOC *)(intptr_t)(rel_addr + reloc_entry); + symtab_index = ELF32_R_SYM(this_reloc->r_info); + + symtab = (Elf32_Sym *)(intptr_t) + DL_RELOC_ADDR (tpnt->dynamic_info[DT_SYMTAB], + tpnt->loadaddr); + strtab = DL_RELOC_ADDR (tpnt->dynamic_info[DT_STRTAB], tpnt->loadaddr); + symname= strtab + symtab[symtab_index].st_name; + + /* Address of GOT entry fix up */ + got_entry = (struct funcdesc_value *) + DL_RELOC_ADDR (this_reloc->r_offset, tpnt->loadaddr); + + /* Get the address to be used to fill in the GOT entry. */ + new_addr = _dl_find_hash_mod(symname, tpnt->symbol_scope, NULL, 0, + &new_tpnt); + if (!new_addr) { + new_addr = _dl_find_hash_mod(symname, NULL, NULL, 0, + &new_tpnt); + if (!new_addr) { + _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", + _dl_progname, symname); + _dl_exit(1); + } + } + + funcval.entry_point = new_addr; + funcval.got_value = new_tpnt->loadaddr.got_value; + +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_bindings) + { + _dl_dprintf(_dl_debug_file, "\nresolve function: %s", symname); + if (_dl_debug_detail) + _dl_dprintf(_dl_debug_file, + "\n\tpatched (%x,%x) ==> (%x,%x) @ %x\n", + got_entry->entry_point, got_entry->got_value, + funcval.entry_point, funcval.got_value, + got_entry); + } + if (!_dl_debug_nofixups) { + *got_entry = funcval; + } +#else + *got_entry = funcval; +#endif + + return got_entry; +} + +static int +_dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope, + unsigned long rel_addr, unsigned long rel_size, + int (*reloc_fnc) (struct elf_resolve *tpnt, struct dyn_elf *scope, + ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)) +{ + unsigned int i; + char *strtab; + Elf32_Sym *symtab; + ELF_RELOC *rpnt; + int symtab_index; + + /* Now parse the relocation information */ + rpnt = (ELF_RELOC *)(intptr_t) DL_RELOC_ADDR (rel_addr, tpnt->loadaddr); + rel_size = rel_size / sizeof(ELF_RELOC); + + symtab = (Elf32_Sym *)(intptr_t) + DL_RELOC_ADDR (tpnt->dynamic_info[DT_SYMTAB], tpnt->loadaddr); + strtab = DL_RELOC_ADDR (tpnt->dynamic_info[DT_STRTAB], tpnt->loadaddr); + + for (i = 0; i < rel_size; i++, rpnt++) { + int res; + + symtab_index = ELF32_R_SYM(rpnt->r_info); + debug_sym(symtab,strtab,symtab_index); + debug_reloc(symtab,strtab,rpnt); + + res = reloc_fnc (tpnt, scope, rpnt, symtab, strtab); + + if (res==0) continue; + + _dl_dprintf(2, "\n%s: ",_dl_progname); + + if (symtab_index) + _dl_dprintf(2, "symbol '%s': ", strtab + symtab[symtab_index].st_name); + + if (res <0) + { + int reloc_type = ELF32_R_TYPE(rpnt->r_info); +#if defined (__SUPPORT_LD_DEBUG__) + _dl_dprintf(2, "can't handle reloc type %s\n ", _dl_reltypes(reloc_type)); +#else + _dl_dprintf(2, "can't handle reloc type %x\n", reloc_type); +#endif + _dl_exit(-res); + } + else if (res >0) + { + _dl_dprintf(2, "can't resolve symbol\n"); + return res; + } + } + return 0; +} + +static int +_dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope, + ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab) +{ + int reloc_type; + int symtab_index; + char *symname; + unsigned long reloc_value = 0, *reloc_addr; + struct { unsigned long v; } __attribute__((__packed__)) + *reloc_addr_packed; + unsigned long symbol_addr; + struct elf_resolve *symbol_tpnt; + struct funcdesc_value funcval; +#if defined (__SUPPORT_LD_DEBUG__) + unsigned long old_val; +#endif + + reloc_addr = (unsigned long *)(intptr_t) + DL_RELOC_ADDR (rpnt->r_offset, tpnt->loadaddr); + __asm__ ("" : "=r" (reloc_addr_packed) : "0" (reloc_addr)); + reloc_type = ELF32_R_TYPE(rpnt->r_info); + symtab_index = ELF32_R_SYM(rpnt->r_info); + symbol_addr = 0; + symname = strtab + symtab[symtab_index].st_name; + + if (ELF32_ST_BIND (symtab[symtab_index].st_info) == STB_LOCAL) { + symbol_addr = (unsigned long) + DL_RELOC_ADDR (symtab[symtab_index].st_value, + tpnt->loadaddr); + symbol_tpnt = tpnt; + } else { + + symbol_addr = (unsigned long) + _dl_find_hash_mod(symname, scope, NULL, 0, &symbol_tpnt); + + /* + * We want to allow undefined references to weak symbols - this might + * have been intentional. We should not be linking local symbols + * here, so all bases should be covered. + */ + + if (!symbol_addr && ELF32_ST_BIND(symtab[symtab_index].st_info) != STB_WEAK) { + _dl_dprintf (2, "%s: can't resolve symbol '%s'\n", + _dl_progname, strtab + symtab[symtab_index].st_name); + _dl_exit (1); + } + } + +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_reloc && _dl_debug_detail) + { + if ((long)reloc_addr_packed & 3) + old_val = reloc_addr_packed->v; + else + old_val = *reloc_addr; + } + else + old_val = 0; +#endif + switch (reloc_type) { + case R_FRV_NONE: + break; + case R_FRV_32: + if ((long)reloc_addr_packed & 3) + reloc_value = reloc_addr_packed->v += symbol_addr; + else + reloc_value = *reloc_addr += symbol_addr; + break; + case R_FRV_FUNCDESC_VALUE: + funcval.entry_point = (void*)symbol_addr; + /* The addend of FUNCDESC_VALUE + relocations referencing global + symbols must be ignored, because it + may hold the address of a lazy PLT + entry. */ + if (ELF32_ST_BIND + (symtab[symtab_index].st_info) + == STB_LOCAL) + funcval.entry_point += *reloc_addr; + reloc_value = (unsigned long)funcval.entry_point; + if (symbol_addr) + funcval.got_value + = symbol_tpnt->loadaddr.got_value; + else + funcval.got_value = 0; + __asm__ ("std%I0\t%1, %M0" + : "=m" (*(struct funcdesc_value *)reloc_addr) + : "e" (funcval)); + break; + case R_FRV_FUNCDESC: + if ((long)reloc_addr_packed & 3) + reloc_value = reloc_addr_packed->v; + else + reloc_value = *reloc_addr; + if (symbol_addr) + reloc_value = (unsigned long)_dl_funcdesc_for + ((char *)symbol_addr + reloc_value, + symbol_tpnt->loadaddr.got_value); + else + reloc_value = 0; + if ((long)reloc_addr_packed & 3) + reloc_addr_packed->v = reloc_value; + else + *reloc_addr = reloc_value; + break; + default: + return -1; /*call _dl_exit(1) */ + } +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_reloc && _dl_debug_detail) { + _dl_dprintf(_dl_debug_file, "\tpatched: %x ==> %x @ %x", old_val, reloc_value, reloc_addr); + switch (reloc_type) { + case R_FRV_FUNCDESC_VALUE: + _dl_dprintf(_dl_debug_file, " got %x", ((struct funcdesc_value *)reloc_value)->got_value); + break; + case R_FRV_FUNCDESC: + if (! reloc_value) + break; + _dl_dprintf(_dl_debug_file, " funcdesc (%x,%x)", + ((struct funcdesc_value *)reloc_value)->entry_point, + ((struct funcdesc_value *)reloc_value)->got_value); + break; + } + } +#endif + + return 0; +} + +static int +_dl_do_lazy_reloc (struct elf_resolve *tpnt, + struct dyn_elf *scope __attribute_used__, + ELF_RELOC *rpnt, Elf32_Sym *symtab __attribute_used__, + char *strtab __attribute_used__) +{ + int reloc_type; + struct funcdesc_value volatile *reloc_addr; + struct funcdesc_value funcval; +#if defined (__SUPPORT_LD_DEBUG__) + unsigned long old_val; +#endif + + reloc_addr = (struct funcdesc_value *)(intptr_t) + DL_RELOC_ADDR (rpnt->r_offset, tpnt->loadaddr); + reloc_type = ELF32_R_TYPE(rpnt->r_info); + +#if defined (__SUPPORT_LD_DEBUG__) + old_val = (unsigned long)reloc_addr->entry_point; +#endif + switch (reloc_type) { + case R_FRV_NONE: + break; + case R_FRV_FUNCDESC_VALUE: + funcval = *reloc_addr; + funcval.entry_point = + DL_RELOC_ADDR (funcval.entry_point, + tpnt->loadaddr); + funcval.got_value = tpnt->loadaddr.got_value; + *reloc_addr = funcval; + break; + default: + return -1; /*call _dl_exit(1) */ + } +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_reloc && _dl_debug_detail) + _dl_dprintf(_dl_debug_file, "\tpatched: %x ==> %x @ %x\n", old_val, reloc_addr->entry_point, reloc_addr); +#endif + return 0; + +} + +void +_dl_parse_lazy_relocation_information +(struct dyn_elf *rpnt, unsigned long rel_addr, unsigned long rel_size) +{ + _dl_parse(rpnt->dyn, NULL, rel_addr, rel_size, _dl_do_lazy_reloc); +} + +int +_dl_parse_relocation_information +(struct dyn_elf *rpnt, unsigned long rel_addr, unsigned long rel_size) +{ + return _dl_parse(rpnt->dyn, rpnt->dyn->symbol_scope, rel_addr, rel_size, _dl_do_reloc); +} + +/* We don't have copy relocs. */ + +int +_dl_parse_copy_information +(struct dyn_elf *rpnt __attribute_used__, + unsigned long rel_addr __attribute_used__, + unsigned long rel_size __attribute_used__) +{ + return 0; +} + +#ifndef LIBDL +# include "../../libc/sysdeps/linux/frv/crtreloc.c" +#endif + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/frv/resolve.S b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/frv/resolve.S new file mode 100644 index 00000000..9dde7275 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/frv/resolve.S @@ -0,0 +1,57 @@ +/* Copyright (C) 2003 Red Hat, Inc. + * Contributed by Alexandre Oliva + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + + /* The function below is tail-called by resolver stubs when a + lazily-bound function is called. It must preserve all + registers that could be used to pass arguments to the actual + function. Upon _dl_linux_resolve entry, GR14 holds the + address of a lazy PLT entry, so @(GR14,-4) is the lazy + relocation number that we have to pass to _dl_linux_resolver. + GR15 holds the caller's GOT, from which we extract the + elf_resolve* that _dl_linux_resolver needs as well. + + _dl_linux_resolver() figures out where the jump symbol is + _really_ supposed to have jumped to and returns that to us. + Once we have that, we prepare to tail-call the actual + function, clean up after ourselves, restoring the original + arguments, then jump to the fixed up address. */ + + .text + .p2align 4 + + .hidden _dl_linux_resolve + .global _dl_linux_resolve + .type _dl_linux_resolve,@function + +_dl_linux_resolve: + /* Preserve arguments. */ + addi sp, -8*4, sp + stdi gr8, @(sp, 8) + stdi gr10, @(sp, 16) + stdi gr12, @(sp, 24) + movsg lr,gr8 + st gr8, @(sp,gr0) + + /* Prepare to call _dl_linux_resolver. */ + ldi @(gr15, 8), gr8 + ldi @(gr14, -4), gr9 + mov.p gr5, gr15 + call _dl_linux_resolver + + /* Move aside return value that contains the FUNCDESC_VALUE. */ + ldd @(gr8,gr0),gr14 + + /* Restore arguments. */ + ld @(sp, gr0), gr8 + movgs gr8,lr + lddi @(sp, 24), gr12 + lddi @(sp, 16), gr10 + lddi @(sp, 8), gr8 + addi sp, 8*4, sp + + /* Now jump to the actual function. */ + jmpl @(gr14, gr0) + .size _dl_linux_resolve, . - _dl_linux_resolve diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/i386/dl-debug.h b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/i386/dl-debug.h new file mode 100644 index 00000000..72a01f8d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/i386/dl-debug.h @@ -0,0 +1,36 @@ +/* vi: set sw=4 ts=4: */ +/* i386 ELF shared library loader suppport + * + * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald, + * David Engel, Hongjiu Lu and Mitch D'Souza + * Copyright (C) 2001-2004 Erik Andersen + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. The name of the above contributors may not be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +static const char *_dl_reltypes_tab[] = { + [0] "R_386_NONE", "R_386_32", "R_386_PC32", "R_386_GOT32", + [4] "R_386_PLT32", "R_386_COPY", "R_386_GLOB_DAT", "R_386_JMP_SLOT", + [8] "R_386_RELATIVE", "R_386_GOTOFF", "R_386_GOTPC", +}; diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/i386/dl-startup.h b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/i386/dl-startup.h new file mode 100644 index 00000000..0c345148 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/i386/dl-startup.h @@ -0,0 +1,65 @@ +/* vi: set sw=4 ts=4: */ +/* + * Architecture specific code used by dl-startup.c + * Copyright (C) 2000-2004 by Erik Andersen + */ +__asm__ ( + " .text\n" + " .globl _start\n" + " .type _start,@function\n" + "_start:\n" + " call _dl_start\n" + " # Save the user entry point address in %edi.\n" + " movl %eax, %edi\n" + " # Point %ebx at the GOT.\n" + " call 1f\n" + "1: popl %ebx\n" + " addl $_GLOBAL_OFFSET_TABLE_+[.-1b], %ebx\n" + " # See if we were run as a command with the executable file\n" + " # name as an extra leading argument.\n" + " movl _dl_skip_args@GOTOFF(%ebx), %eax\n" + " # Pop the original argument count.\n" + " popl %edx\n" + " # Adjust the stack pointer to skip _dl_skip_args words.\n" + " leal (%esp,%eax,4), %esp\n" + " # Subtract _dl_skip_args from argc.\n" + " subl %eax, %edx\n" + " # Push argc back on the stack.\n" + " push %edx\n" + " # Pass our FINI ptr() to the user in %edx, as per ELF ABI.\n" + " leal _dl_fini@GOTOFF(%ebx), %edx\n" + " # Jump to the user's entry point.\n" + " jmp *%edi\n" + " .size _start,.-_start\n" + " .previous\n" +); + +/* Get a pointer to the argv array. On many platforms this can be just + * the address of the first argument, on other platforms we need to + * do something a little more subtle here. */ +#define GET_ARGV(ARGVP, ARGS) ARGVP = (((unsigned long*) & ARGS)+1) + +/* Handle relocation of the symbols in the dynamic loader. */ +static __always_inline +void PERFORM_BOOTSTRAP_RELOC(ELF_RELOC *rpnt, unsigned long *reloc_addr, + unsigned long symbol_addr, unsigned long load_addr, attribute_unused Elf32_Sym *symtab) +{ + switch (ELF32_R_TYPE(rpnt->r_info)) + { + case R_386_32: + *reloc_addr += symbol_addr; + break; + case R_386_PC32: + *reloc_addr += symbol_addr - (unsigned long) reloc_addr; + break; + case R_386_GLOB_DAT: + case R_386_JMP_SLOT: + *reloc_addr = symbol_addr; + break; + case R_386_RELATIVE: + *reloc_addr += load_addr; + break; + default: + _dl_exit(1); + } +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/i386/dl-syscalls.h b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/i386/dl-syscalls.h new file mode 100644 index 00000000..996bb87c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/i386/dl-syscalls.h @@ -0,0 +1,6 @@ +/* We can't use the real errno in ldso, since it has not yet + * been dynamicly linked in yet. */ +#include "sys/syscall.h" +extern int _dl_errno; +#undef __set_errno +#define __set_errno(X) {(_dl_errno) = (X);} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/i386/dl-sysdep.h b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/i386/dl-sysdep.h new file mode 100644 index 00000000..a66c8021 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/i386/dl-sysdep.h @@ -0,0 +1,78 @@ +/* vi: set sw=4 ts=4: */ +/* + * Various assembly language/system dependent hacks that are required + * so that we can minimize the amount of platform specific code. + * Copyright (C) 2000-2004 by Erik Andersen + */ + +/* Define this if the system uses RELOCA. */ +#undef ELF_USES_RELOCA +#include +/* Initialization sequence for the GOT. */ +#define INIT_GOT(GOT_BASE,MODULE) \ +do { \ + GOT_BASE[2] = (unsigned long) _dl_linux_resolve; \ + GOT_BASE[1] = (unsigned long) MODULE; \ +} while(0) + +/* Here we define the magic numbers that this dynamic loader should accept */ +#define MAGIC1 EM_386 +#undef MAGIC2 + +/* Used for error messages */ +#define ELF_TARGET "386" + +struct elf_resolve; +extern unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_entry); + +/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry or + TLS variable, so undefined references should not be allowed to + define the value. + ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to one + of the main executable's symbols, as for a COPY reloc. */ +#define elf_machine_type_class(type) \ + ((((type) == R_386_JMP_SLOT || (type) == R_386_TLS_DTPMOD32 \ + || (type) == R_386_TLS_DTPOFF32 || (type) == R_386_TLS_TPOFF32 \ + || (type) == R_386_TLS_TPOFF) * ELF_RTYPE_CLASS_PLT) \ + | (((type) == R_386_COPY) * ELF_RTYPE_CLASS_COPY)) + +/* Return the link-time address of _DYNAMIC. Conveniently, this is the + first element of the GOT. This must be inlined in a function which + uses global data. */ +static __always_inline Elf32_Addr elf_machine_dynamic (void) attribute_unused; +static __always_inline Elf32_Addr +elf_machine_dynamic (void) +{ + register Elf32_Addr *got __asm__ ("%ebx"); + return *got; +} + + +/* Return the run-time load address of the shared object. */ +static __always_inline Elf32_Addr elf_machine_load_address (void) attribute_unused; +static __always_inline Elf32_Addr +elf_machine_load_address (void) +{ + /* It doesn't matter what variable this is, the reference never makes + it to assembly. We need a dummy reference to some global variable + via the GOT to make sure the compiler initialized %ebx in time. */ + Elf32_Addr addr; + int tmp; + __asm__ ("leal _dl_start@GOTOFF(%%ebx), %0\n" + "subl _dl_start@GOT(%%ebx), %0" + : "=r" (addr) : "m" (tmp) : "cc"); + return addr; +} + +static __always_inline void +elf_machine_relative (Elf32_Addr load_off, const Elf32_Addr rel_addr, + Elf32_Word relative_count) +{ + Elf32_Rel * rpnt = (void *) rel_addr; + --rpnt; + do { + Elf32_Addr *const reloc_addr = (void *) (load_off + (++rpnt)->r_offset); + + *reloc_addr += load_off; + } while (--relative_count); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/i386/elfinterp.c b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/i386/elfinterp.c new file mode 100644 index 00000000..c2929fe9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/i386/elfinterp.c @@ -0,0 +1,324 @@ +/* vi: set sw=4 ts=4: */ +/* i386 ELF shared library loader suppport + * + * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald, + * David Engel, Hongjiu Lu and Mitch D'Souza + * Copyright (C) 2001-2004 Erik Andersen + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. The name of the above contributors may not be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "ldso.h" + +/* Program to load an ELF binary on a linux system, and run it. + References to symbols in sharable libraries can be resolved by either + an ELF sharable library or a linux style of shared library. */ + +/* Disclaimer: I have never seen any AT&T source code for SVr4, nor have + I ever taken any courses on internals. This program was developed using + information available through the book "UNIX SYSTEM V RELEASE 4, + Programmers guide: Ansi C and Programming Support Tools", which did + a more than adequate job of explaining everything required to get this + working. */ + +extern int _dl_linux_resolve(void); + +unsigned long +_dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry) +{ + ELF_RELOC *this_reloc; + char *strtab; + Elf32_Sym *symtab; + int symtab_index; + char *rel_addr; + char *new_addr; + char **got_addr; + unsigned long instr_addr; + char *symname; + + rel_addr = (char *)tpnt->dynamic_info[DT_JMPREL]; + this_reloc = (ELF_RELOC *)(intptr_t)(rel_addr + reloc_entry); + symtab_index = ELF32_R_SYM(this_reloc->r_info); + + symtab = (Elf32_Sym *)(intptr_t)tpnt->dynamic_info[DT_SYMTAB]; + strtab = (char *)tpnt->dynamic_info[DT_STRTAB]; + symname = strtab + symtab[symtab_index].st_name; + + /* Address of the jump instruction to fix up. */ + instr_addr = ((unsigned long)this_reloc->r_offset + + (unsigned long)tpnt->loadaddr); + got_addr = (char **)instr_addr; + + /* Get the address of the GOT entry. */ + new_addr = _dl_find_hash(symname, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL); + if (unlikely(!new_addr)) { + _dl_dprintf(2, "%s: can't resolve symbol '%s' in lib '%s'.\n", _dl_progname, symname, tpnt->libname); + _dl_exit(1); + } + +#if defined (__SUPPORT_LD_DEBUG__) + if ((unsigned long)got_addr < 0x40000000) { + if (_dl_debug_bindings) { + _dl_dprintf(_dl_debug_file, "\nresolve function: %s", symname); + if (_dl_debug_detail) + _dl_dprintf(_dl_debug_file, + "\n\tpatched: %x ==> %x @ %x", + *got_addr, new_addr, got_addr); + } + } + if (!_dl_debug_nofixups) { + *got_addr = new_addr; + } +#else + *got_addr = new_addr; +#endif + + return (unsigned long)new_addr; +} + +static int +_dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope, + unsigned long rel_addr, unsigned long rel_size, + int (*reloc_fnc)(struct elf_resolve *tpnt, struct dyn_elf *scope, + ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)) +{ + unsigned int i; + char *strtab; + Elf32_Sym *symtab; + ELF_RELOC *rpnt; + int symtab_index; + + /* Parse the relocation information. */ + rpnt = (ELF_RELOC *)(intptr_t)rel_addr; + rel_size /= sizeof(ELF_RELOC); + + symtab = (Elf32_Sym *)(intptr_t)tpnt->dynamic_info[DT_SYMTAB]; + strtab = (char *)tpnt->dynamic_info[DT_STRTAB]; + + for (i = 0; i < rel_size; i++, rpnt++) { + int res; + + symtab_index = ELF32_R_SYM(rpnt->r_info); + + debug_sym(symtab, strtab, symtab_index); + debug_reloc(symtab, strtab, rpnt); + + res = reloc_fnc(tpnt, scope, rpnt, symtab, strtab); + + if (res == 0) + continue; + + _dl_dprintf(2, "\n%s: ", _dl_progname); + + if (symtab_index) + _dl_dprintf(2, "symbol '%s': ", + strtab + symtab[symtab_index].st_name); + + if (unlikely(res < 0)) { + int reloc_type = ELF32_R_TYPE(rpnt->r_info); + +#if defined (__SUPPORT_LD_DEBUG__) + _dl_dprintf(2, "can't handle reloc type '%s' in lib '%s'\n", + _dl_reltypes(reloc_type), tpnt->libname); +#else + _dl_dprintf(2, "can't handle reloc type %x in lib '%s'\n", + reloc_type, tpnt->libname); +#endif + return res; + } else if (unlikely(res > 0)) { + _dl_dprintf(2, "can't resolve symbol in lib '%s'.\n", tpnt->libname); + return res; + } + } + + return 0; +} + +static int +_dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, + ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab) +{ + int reloc_type; + int symtab_index; + char *symname; + struct elf_resolve *tls_tpnt = NULL; + unsigned long *reloc_addr; + unsigned long symbol_addr; +#if defined (__SUPPORT_LD_DEBUG__) + unsigned long old_val; +#endif + struct symbol_ref sym_ref; + + reloc_addr = (unsigned long *)(intptr_t)(tpnt->loadaddr + (unsigned long)rpnt->r_offset); + reloc_type = ELF32_R_TYPE(rpnt->r_info); + symtab_index = ELF32_R_SYM(rpnt->r_info); + symbol_addr = 0; + sym_ref.sym = &symtab[symtab_index]; + sym_ref.tpnt = NULL; + symname = strtab + symtab[symtab_index].st_name; + + if (symtab_index) { + symbol_addr = (unsigned long)_dl_find_hash(symname, scope, tpnt, + elf_machine_type_class(reloc_type), &sym_ref); + + /* + * We want to allow undefined references to weak symbols - this + * might have been intentional. We should not be linking local + * symbols here, so all bases should be covered. + */ + if (unlikely(!symbol_addr && (ELF_ST_TYPE(symtab[symtab_index].st_info) != STT_TLS) + && ELF32_ST_BIND(symtab[symtab_index].st_info) != STB_WEAK)) + return 1; + tls_tpnt = sym_ref.tpnt; + } else { + symbol_addr = symtab[symtab_index].st_value; + tls_tpnt = tpnt; + } + + +#if defined (__SUPPORT_LD_DEBUG__) + /* Start: aw11: fixed pagefault with empty relocations */ + if (reloc_type != R_386_NONE) old_val = *reloc_addr; else old_val = 0; + /* End: aw11 */ +#endif + + switch (reloc_type) { + case R_386_NONE: + break; + case R_386_32: + *reloc_addr += symbol_addr; + break; + case R_386_PC32: + *reloc_addr += symbol_addr - (unsigned long)reloc_addr; + break; + case R_386_GLOB_DAT: + case R_386_JMP_SLOT: + *reloc_addr = symbol_addr; + break; + case R_386_RELATIVE: + *reloc_addr += (unsigned long)tpnt->loadaddr; + break; + case R_386_COPY: + if (symbol_addr) { +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_move) + _dl_dprintf(_dl_debug_file, + "\n%s move %d bytes from %x to %x", + symname, symtab[symtab_index].st_size, + symbol_addr, reloc_addr); +#endif + + _dl_memcpy((char *)reloc_addr, + (char *)symbol_addr, + symtab[symtab_index].st_size); + } + break; +#if defined USE_TLS && USE_TLS + case R_386_TLS_DTPMOD32: + *reloc_addr = tls_tpnt->l_tls_modid; + break; + case R_386_TLS_DTPOFF32: + /* During relocation all TLS symbols are defined and used. + * Therefore the offset is already correct. */ + *reloc_addr = symbol_addr; + break; + case R_386_TLS_TPOFF32: + /* The offset is positive, backward from the thread pointer. */ + CHECK_STATIC_TLS((struct link_map*) tls_tpnt); + *reloc_addr += tls_tpnt->l_tls_offset - symbol_addr; + break; + case R_386_TLS_TPOFF: + /* The offset is negative, forward from the thread pointer. */ + CHECK_STATIC_TLS((struct link_map*) tls_tpnt); + *reloc_addr += symbol_addr - tls_tpnt->l_tls_offset; + break; +#endif + default: + return -1; + } + +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_reloc && _dl_debug_detail) + _dl_dprintf(_dl_debug_file, "\n\tpatched: %x ==> %x @ %x\n", + old_val, *reloc_addr, reloc_addr); +#endif + + return 0; +} + +static int +_dl_do_lazy_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, + ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab) +{ + int reloc_type; + unsigned long *reloc_addr; +#if defined (__SUPPORT_LD_DEBUG__) + unsigned long old_val; +#endif + + (void)scope; + (void)symtab; + (void)strtab; + + reloc_addr = (unsigned long *)(intptr_t)(tpnt->loadaddr + (unsigned long)rpnt->r_offset); + reloc_type = ELF32_R_TYPE(rpnt->r_info); + +#if defined (__SUPPORT_LD_DEBUG__) + old_val = *reloc_addr; +#endif + + switch (reloc_type) { + case R_386_NONE: + break; + case R_386_JMP_SLOT: + *reloc_addr += (unsigned long)tpnt->loadaddr; + break; + default: + return -1; + } + +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_reloc && _dl_debug_detail) + _dl_dprintf(_dl_debug_file, "\n\tpatched: %x ==> %x @ %x\n", + old_val, *reloc_addr, reloc_addr); +#endif + + return 0; +} + +void +_dl_parse_lazy_relocation_information(struct dyn_elf *rpnt, + unsigned long rel_addr, + unsigned long rel_size) +{ + (void)_dl_parse(rpnt->dyn, NULL, rel_addr, rel_size, _dl_do_lazy_reloc); +} + +int +_dl_parse_relocation_information(struct dyn_elf *rpnt, + unsigned long rel_addr, + unsigned long rel_size) +{ + return _dl_parse(rpnt->dyn, rpnt->dyn->symbol_scope, rel_addr, rel_size, _dl_do_reloc); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/i386/resolve.S b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/i386/resolve.S new file mode 100644 index 00000000..e8d77bb1 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/i386/resolve.S @@ -0,0 +1,51 @@ +/* + * This function is _not_ called directly. It is jumped to (so no return + * address is on the stack) when attempting to use a symbol that has not yet + * been resolved. The first time a jump symbol (such as a function call inside + * a shared library) is used (before it gets resolved) it will jump here to + * _dl_linux_resolve. When we get called the stack looks like this: + * reloc_entry + * tpnt + * + * This function saves all the registers, puts a copy of reloc_entry and tpnt + * on the stack (as function arguments) then make the function call + * _dl_linux_resolver(tpnt, reloc_entry). _dl_linux_resolver() figures out + * where the jump symbol is _really_ supposed to have jumped to and returns + * that to us. Once we have that, we overwrite tpnt with this fixed up + * address. We then clean up after ourselves, put all the registers back how we + * found them, then we jump to where the fixed up address, which is where the + * jump symbol that got us here really wanted to jump to in the first place. + * found them, then we jump to the fixed up address, which is where the jump + * symbol that got us here really wanted to jump to in the first place. + * -Erik Andersen + */ + +.text + +.globl _dl_linux_resolve +.type _dl_linux_resolve,@function + +_dl_linux_resolve: + pusha /* preserve all regs */ + lea 0x20(%esp),%eax /* eax = tpnt and reloc_entry params */ + pushl 4(%eax) /* push copy of reloc_entry param */ + pushl (%eax) /* push copy of tpnt param */ + +#ifdef __PIC__ + call .L24 +.L24: + popl %ebx + addl $_GLOBAL_OFFSET_TABLE_+[.-.L24],%ebx + movl _dl_linux_resolver@GOT(%ebx),%ebx /* eax = resolved func */ + call *%ebx +#else + call _dl_linux_resolver +#endif + movl %eax,0x28(%esp) /* store func addr over original + * tpnt param */ + addl $0x8,%esp /* remove copy parameters */ + popa /* restore regs */ + ret $4 /* jump to func removing original + * reloc_entry param from stack */ +.LFE2: + .size _dl_linux_resolve,.LFE2-_dl_linux_resolve diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/ldso.c b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/ldso.c new file mode 100644 index 00000000..af837dcf --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/ldso.c @@ -0,0 +1,1146 @@ +/* vi: set sw=4 ts=4: */ +/* + * Program to load an ELF binary on a linux system, and run it + * after resolving ELF shared library symbols + * + * Copyright (C) 2005 by Joakim Tjernlund + * Copyright (C) 2000-2006 by Erik Andersen + * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald, + * David Engel, Hongjiu Lu and Mitch D'Souza + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. The name of the above contributors may not be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "ldso.h" +#include "unsecvars.h" + +/* Pull in common debug code */ +#include "dl-debug.c" + +#define ALLOW_ZERO_PLTGOT + +#if defined(USE_TLS) && USE_TLS +#include "dl-tls.c" +#endif + +/* Pull in the value of _dl_progname */ +#include LDSO_ELFINTERP + +/* Global variables used within the shared library loader */ +char *_dl_library_path = NULL; /* Where we look for libraries */ +#ifdef __LDSO_PRELOAD_ENV_SUPPORT__ +char *_dl_preload = NULL; /* Things to be loaded before the libs */ +#endif +char *_dl_ldsopath = NULL; /* Location of the shared lib loader */ +int _dl_errno = 0; /* We can't use the real errno in ldso */ +size_t _dl_pagesize = 0; /* Store the page size for use later */ +struct r_debug *_dl_debug_addr = NULL; /* Used to communicate with the gdb debugger */ +void *(*_dl_malloc_function) (size_t size) = NULL; +void (*_dl_free_function) (void *p) = NULL; + +static int _dl_secure = 1; /* Are we dealing with setuid stuff? */ + +#ifdef __SUPPORT_LD_DEBUG__ +char *_dl_debug = NULL; +char *_dl_debug_symbols = NULL; +char *_dl_debug_move = NULL; +char *_dl_debug_reloc = NULL; +char *_dl_debug_detail = NULL; +char *_dl_debug_nofixups = NULL; +char *_dl_debug_bindings = NULL; +int _dl_debug_file = 2; +#endif + +/* Needed for standalone execution. */ +unsigned long attribute_hidden _dl_skip_args = 0; +const char *_dl_progname = UCLIBC_LDSO; /* The name of the executable being run */ +#include "dl-startup.c" +#include "dl-symbols.c" +#include "dl-array.c" + +/* + * This stub function is used by some debuggers. The idea is that they + * can set an internal breakpoint on it, so that we are notified when the + * address mapping is changed in some way. + */ +void _dl_debug_state(void); +rtld_hidden_proto(_dl_debug_state, noinline); +void _dl_debug_state(void) +{ + /* Make sure GCC doesn't recognize this function as pure, to avoid + * having the calls optimized away. + */ + __asm__(""); +} +rtld_hidden_def(_dl_debug_state); + +static unsigned char *_dl_malloc_addr = NULL; /* Lets _dl_malloc use the already allocated memory page */ +static unsigned char *_dl_mmap_zero = NULL; /* Also used by _dl_malloc */ + +static struct elf_resolve **init_fini_list; +static unsigned int nlist; /* # items in init_fini_list */ +extern void _start(void); + +#ifdef __UCLIBC_HAS_SSP__ +# include +static uintptr_t stack_chk_guard; +# ifndef THREAD_SET_STACK_GUARD +/* Only exported for architectures that don't store the stack guard canary + * in local thread area. */ +uintptr_t __stack_chk_guard attribute_relro; +# endif +# ifdef __UCLIBC_HAS_SSP_COMPAT__ +uintptr_t __guard attribute_relro; +# endif +#endif + +char *_dl_getenv(const char *symbol, char **envp) +{ + char *pnt; + const char *pnt1; + + while ((pnt = *envp++)) { + pnt1 = symbol; + while (*pnt && *pnt == *pnt1) + pnt1++, pnt++; + if (!*pnt || *pnt != '=' || *pnt1) + continue; + return pnt + 1; + } + return 0; +} + +void _dl_unsetenv(const char *symbol, char **envp) +{ + char *pnt; + const char *pnt1; + char **newenvp = envp; + + for (pnt = *envp; pnt; pnt = *++envp) { + pnt1 = symbol; + while (*pnt && *pnt == *pnt1) + pnt1++, pnt++; + if (!*pnt || *pnt != '=' || *pnt1) + *newenvp++ = *envp; + } + *newenvp++ = *envp; + return; +} + +static int _dl_suid_ok(void) +{ +#ifdef NOT_FOR_L4 + __kernel_uid_t uid, euid; + __kernel_gid_t gid, egid; + + uid = _dl_getuid(); + euid = _dl_geteuid(); + gid = _dl_getgid(); + egid = _dl_getegid(); + + if (uid == euid && gid == egid) { + return 1; + } +#endif + return 0; +} + +void *_dl_malloc(size_t size) +{ + void *retval; + +#if 0 + _dl_debug_early("request for %d bytes\n", size); +#endif + + if (_dl_malloc_function) + return (*_dl_malloc_function) (size); + + if (_dl_malloc_addr - _dl_mmap_zero + size > _dl_pagesize) { + size_t rounded_size; + + /* Since the above assumes we get a full page even if + we request less than that, make sure we request a + full page, since uClinux may give us less than than + a full page. We might round even + larger-than-a-page sizes, but we end up never + reusing _dl_mmap_zero/_dl_malloc_addr in that case, + so we don't do it. + + The actual page size doesn't really matter; as long + as we're self-consistent here, we're safe. */ + if (size < _dl_pagesize) + rounded_size = (size + ADDR_ALIGN) & _dl_pagesize; + else + rounded_size = size; + + _dl_debug_early("mmapping more memory\n"); + _dl_mmap_zero = _dl_malloc_addr = _dl_mmap((void *) 0, rounded_size, + PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_UNINITIALIZE, -1, 0); + if (_dl_mmap_check_error(_dl_mmap_zero)) { + _dl_dprintf(_dl_debug_file, "%s: mmap of a spare page failed!\n", _dl_progname); + _dl_exit(20); + } + } + retval = _dl_malloc_addr; + _dl_malloc_addr += size; + + /* + * Align memory to DL_MALLOC_ALIGN byte boundary. Some + * platforms require this, others simply get better + * performance. + */ + _dl_malloc_addr = (unsigned char *) (((unsigned long) _dl_malloc_addr + DL_MALLOC_ALIGN - 1) & ~(DL_MALLOC_ALIGN - 1)); + return retval; +} + +static void *_dl_zalloc(size_t size) +{ + void *p = _dl_malloc(size); + if (p) + _dl_memset(p, 0, size); + return p; +} + +void _dl_free(void *p) +{ + if (_dl_free_function) + (*_dl_free_function) (p); +} + +#if defined(USE_TLS) && USE_TLS +void *_dl_memalign(size_t __boundary, size_t __size) +{ + void *result; + int i = 0; + size_t delta; + size_t rounded = 0; + + if (_dl_memalign_function) + return (*_dl_memalign_function) (__boundary, __size); + + while (rounded < __boundary) { + rounded = (1 << i++); + } + + delta = (((size_t) _dl_malloc_addr + __size) & (rounded - 1)); + + if ((result = _dl_malloc(rounded - delta)) == NULL) + return result; + + result = _dl_malloc(__size); + + return result; +} +#endif + +static void __attribute__ ((destructor)) __attribute_used__ _dl_fini(void) +{ + unsigned int i; + struct elf_resolve * tpnt; + + for (i = 0; i < nlist; ++i) { + tpnt = init_fini_list[i]; + if (tpnt->init_flag & FINI_FUNCS_CALLED) + continue; + tpnt->init_flag |= FINI_FUNCS_CALLED; + _dl_run_fini_array(tpnt); + if (tpnt->dynamic_info[DT_FINI]) { + void (*dl_elf_func) (void); + + dl_elf_func = (void (*)(void)) (intptr_t) DL_RELOC_ADDR(tpnt->loadaddr, tpnt->dynamic_info[DT_FINI]); + _dl_if_debug_dprint("\ncalling FINI: %s\n\n", tpnt->libname); + DL_CALL_FUNC_AT_ADDR (dl_elf_func, tpnt->loadaddr, (void(*)(void))); + } + } +} + +#ifndef __AW11_LIB_DEP_SORT__ +static int _dl_lib_deps_cmp(struct elf_resolve *a, struct elf_resolve *b) +{ + struct init_fini_list *runp = a->init_fini; + for (; runp; runp = runp->next) + if (runp->tpnt == b) + return 1; + return 0; +} + +static void _dl_lib_deps_swap(struct elf_resolve **x, int a, int b) +{ + struct elf_resolve *tmp; + + _dl_if_debug_dprint("Swap %s at %d and %s at %d in INIT/FINI list\n", x[a]->libname, a, x[b]->libname, b); + + tmp = x[a]; + x[a] = x[b]; + x[b] = tmp; +} + +static void _dl_lib_deps_sort(struct elf_resolve **a, int len) +{ + if (!len) + return; + + do { + int min = len - 1; + int i; + for (i = len - 2; i > 0; --i) + if (_dl_lib_deps_cmp(a[min], a[i])) { + min = i; + i = len - 1; + } + + if (min != len - 1) + _dl_lib_deps_swap(a, min, len - 1); + + --len; + } while (len); +} +#endif + +void _dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr, + ElfW(auxv_t) auxvt[AT_EGID + 1], char **envp, + char **argv + DL_GET_READY_TO_RUN_EXTRA_PARMS) +{ + ElfW(Addr) app_mapaddr = 0; + ElfW(Phdr) *ppnt; + ElfW(Dyn) *dpnt; + char *lpntstr; + unsigned int i; + int unlazy = 0, trace_loaded_objects = 0; + struct dyn_elf *rpnt; + struct elf_resolve *tcurr; + struct elf_resolve *tpnt1; + struct elf_resolve app_tpnt_tmp; + struct elf_resolve *app_tpnt = &app_tpnt_tmp; + struct r_debug *debug_addr; + unsigned long *lpnt; + unsigned long *_dl_envp; /* The environment address */ + ElfW(Addr) relro_addr = 0; + size_t relro_size = 0; + struct stat st; +#if defined(USE_TLS) && USE_TLS + void *tcbp = NULL; +#endif + + /* Wahoo!!! We managed to make a function call! Get malloc + * setup so we can use _dl_dprintf() to print debug noise + * instead of the SEND_STDERR macros used in dl-startup.c */ + + _dl_memset(app_tpnt, 0, sizeof(*app_tpnt)); + + /* Store the page size for later use */ + _dl_pagesize = (auxvt[AT_PAGESZ].a_un.a_val) ? (size_t) auxvt[AT_PAGESZ].a_un.a_val : PAGE_SIZE; + /* Make it so _dl_malloc can use the page of memory we have already + * allocated. We shouldn't need to grab any more memory. This must + * be first since things like _dl_dprintf() use _dl_malloc()... + */ + _dl_malloc_addr = (unsigned char *)_dl_pagesize; + _dl_mmap_zero = 0; + + /* Wahoo!!! */ + _dl_debug_early("Cool, ldso survived making function calls\n"); + + /* Now we have done the mandatory linking of some things. We are now + * free to start using global variables, since these things have all + * been fixed up by now. Still no function calls outside of this + * library, since the dynamic resolver is not yet ready. + */ + if (argv[0]) { + _dl_progname = argv[0]; + } + + if (_start == (void *) auxvt[AT_ENTRY].a_un.a_val) { + _dl_dprintf(_dl_debug_file, "Standalone execution is not supported yet\n"); + _dl_exit(1); + } + + /* Start to build the tables of the modules that are required for + * this beast to run. We start with the basic executable, and then + * go from there. Eventually we will run across ourself, and we + * will need to properly deal with that as well. + */ + rpnt = NULL; + if (_dl_getenv("LD_BIND_NOW", envp)) + unlazy = RTLD_NOW; + + /* Now we need to figure out what kind of options are selected. + * Note that for SUID programs we ignore the settings in + * LD_LIBRARY_PATH. + */ + if ((auxvt[AT_UID].a_un.a_val == (size_t)-1 && _dl_suid_ok()) || + (auxvt[AT_UID].a_un.a_val != (size_t)-1 && + auxvt[AT_UID].a_un.a_val == auxvt[AT_EUID].a_un.a_val && + auxvt[AT_GID].a_un.a_val == auxvt[AT_EGID].a_un.a_val)) { + _dl_secure = 0; +#ifdef __LDSO_PRELOAD_ENV_SUPPORT__ + _dl_preload = _dl_getenv("LD_PRELOAD", envp); +#endif + _dl_library_path = _dl_getenv("LD_LIBRARY_PATH", envp); + } else { + static const char unsecure_envvars[] = +#ifdef EXTRA_UNSECURE_ENVVARS + EXTRA_UNSECURE_ENVVARS +#endif + UNSECURE_ENVVARS; + const char *nextp; + _dl_secure = 1; + + nextp = unsecure_envvars; + do { + _dl_unsetenv (nextp, envp); + /* We could use rawmemchr but this need not be fast. */ + nextp = _dl_strchr(nextp, '\0') + 1; + } while (*nextp != '\0'); +#ifdef __LDSO_PRELOAD_ENV_SUPPORT__ + _dl_preload = NULL; +#endif + _dl_library_path = NULL; + /* SUID binaries can be exploited if they do LAZY relocation. */ + unlazy = RTLD_NOW; + } + +#if defined(USE_TLS) && USE_TLS + _dl_error_catch_tsd = &_dl_initial_error_catch_tsd; + _dl_init_static_tls = &_dl_nothread_init_static_tls; +#endif + + /* At this point we are now free to examine the user application, + * and figure out which libraries are supposed to be called. Until + * we have this list, we will not be completely ready for dynamic + * linking. + */ + + /* Find the runtime load address of the main executable. This may be + * different from what the ELF header says for ET_DYN/PIE executables. + */ + { + unsigned int idx; + ElfW(Phdr) *phdr = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_val; + + for (idx = 0; idx < auxvt[AT_PHNUM].a_un.a_val; idx++, phdr++) + if (phdr->p_type == PT_PHDR) { + DL_INIT_LOADADDR_PROG(app_tpnt->loadaddr, auxvt[AT_PHDR].a_un.a_val - phdr->p_vaddr); + break; + } + + if (DL_LOADADDR_BASE(app_tpnt->loadaddr)) + _dl_debug_early("Position Independent Executable: " + "app_tpnt->loadaddr=%x\n", DL_LOADADDR_BASE(app_tpnt->loadaddr)); + } + + /* + * This is used by gdb to locate the chain of shared libraries that are + * currently loaded. + */ + debug_addr = _dl_zalloc(sizeof(struct r_debug)); + + ppnt = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_val; + for (i = 0; i < auxvt[AT_PHNUM].a_un.a_val; i++, ppnt++) { + if (ppnt->p_type == PT_GNU_RELRO) { + relro_addr = ppnt->p_vaddr; + relro_size = ppnt->p_memsz; + } + if (!app_mapaddr && (ppnt->p_type == PT_LOAD)) { + app_mapaddr = DL_RELOC_ADDR (app_tpnt->loadaddr, ppnt->p_vaddr); + } + if (ppnt->p_type == PT_DYNAMIC) { + dpnt = (ElfW(Dyn) *) DL_RELOC_ADDR(app_tpnt->loadaddr, ppnt->p_vaddr); + _dl_parse_dynamic_info(dpnt, app_tpnt->dynamic_info, debug_addr, app_tpnt->loadaddr); +#ifndef __FORCE_SHAREABLE_TEXT_SEGMENTS__ + /* Ugly, ugly. We need to call mprotect to change the + * protection of the text pages so that we can do the + * dynamic linking. We can set the protection back + * again once we are done. + */ + _dl_debug_early("calling mprotect on the application program\n"); + /* Now cover the application program. */ + if (app_tpnt->dynamic_info[DT_TEXTREL]) { + ElfW(Phdr) *ppnt_outer = ppnt; + ppnt = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_val; + for (i = 0; i < auxvt[AT_PHNUM].a_un.a_val; i++, ppnt++) { + if (ppnt->p_type == PT_LOAD && !(ppnt->p_flags & PF_W)) + _dl_mprotect((void *) (DL_RELOC_ADDR(app_tpnt->loadaddr, ppnt->p_vaddr) & PAGE_ALIGN), + (DL_RELOC_ADDR(app_tpnt->loadaddr, ppnt->p_vaddr) & ADDR_ALIGN) + + (unsigned long) ppnt->p_filesz, + PROT_READ | PROT_WRITE | PROT_EXEC); + } + ppnt = ppnt_outer; + } +#else + if (app_tpnt->dynamic_info[DT_TEXTREL]) { + _dl_dprintf(_dl_debug_file, "Can't modify application's text section; use the GCC option -fPIE for position-independent executables.\n"); + _dl_exit(1); + } +#endif + +#ifndef ALLOW_ZERO_PLTGOT + /* make sure it's really there. */ + if (app_tpnt->dynamic_info[DT_PLTGOT] == 0) + continue; +#endif + /* OK, we have what we need - slip this one into the list. */ + app_tpnt = _dl_add_elf_hash_table(_dl_progname, app_tpnt->loadaddr, + app_tpnt->dynamic_info, + (unsigned long) DL_RELOC_ADDR(app_tpnt->loadaddr, ppnt->p_vaddr), + ppnt->p_filesz); + _dl_loaded_modules->libtype = elf_executable; + _dl_loaded_modules->ppnt = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_val; + _dl_loaded_modules->n_phent = auxvt[AT_PHNUM].a_un.a_val; + _dl_symbol_tables = rpnt = _dl_zalloc(sizeof(struct dyn_elf)); + rpnt->dyn = _dl_loaded_modules; + app_tpnt->mapaddr = app_mapaddr; + app_tpnt->rtld_flags = unlazy | RTLD_GLOBAL; + app_tpnt->usage_count++; + app_tpnt->symbol_scope = _dl_symbol_tables; + lpnt = (unsigned long *) (app_tpnt->dynamic_info[DT_PLTGOT]); +#ifdef ALLOW_ZERO_PLTGOT + if (lpnt) +#endif + INIT_GOT(lpnt, _dl_loaded_modules); + } + + /* OK, fill this in - we did not have this before */ + if (ppnt->p_type == PT_INTERP) { + tpnt->libname = (char *) DL_RELOC_ADDR(app_tpnt->loadaddr, ppnt->p_vaddr); +#ifdef __LDSO_SEARCH_INTERP_PATH__ + { + char *ptmp; + /* Store the path where the shared lib loader was found + * for later use + */ + _dl_ldsopath = _dl_strdup(tpnt->libname); + ptmp = _dl_strrchr(_dl_ldsopath, '/'); + if (ptmp != _dl_ldsopath) + *ptmp = '\0'; + } + _dl_debug_early("Lib Loader: (%x) %s\n", (unsigned) DL_LOADADDR_BASE(tpnt->loadaddr), tpnt->libname); +#endif + } + + /* Discover any TLS sections if the target supports them. */ + if (ppnt->p_type == PT_TLS) { +#if defined(USE_TLS) && USE_TLS + if (ppnt->p_memsz > 0) { + app_tpnt->l_tls_blocksize = ppnt->p_memsz; + app_tpnt->l_tls_align = ppnt->p_align; + if (ppnt->p_align == 0) + app_tpnt->l_tls_firstbyte_offset = 0; + else + app_tpnt->l_tls_firstbyte_offset = + (ppnt->p_vaddr & (ppnt->p_align - 1)); + app_tpnt->l_tls_initimage_size = ppnt->p_filesz; + app_tpnt->l_tls_initimage = (void *) ppnt->p_vaddr; + + /* This image gets the ID one. */ + _dl_tls_max_dtv_idx = app_tpnt->l_tls_modid = 1; + + } + _dl_debug_early("Found TLS header for appplication program\n"); + break; +#else + _dl_dprintf(_dl_debug_file, "Program uses unsupported TLS data!\n"); + _dl_exit(1); +#endif + } + } + app_tpnt->relro_addr = relro_addr; + app_tpnt->relro_size = relro_size; + +#if defined(USE_TLS) && USE_TLS + /* + * Adjust the address of the TLS initialization image in + * case the executable is actually an ET_DYN object. + */ + if (app_tpnt->l_tls_initimage != NULL) { + app_tpnt->l_tls_initimage = + (char *) app_tpnt->l_tls_initimage + app_tpnt->loadaddr; + _dl_debug_early("Relocated TLS initial image from %x to %x (size = %x)\n", + (unsigned int)app_tpnt->l_tls_initimage, + app_tpnt->l_tls_initimage, app_tpnt->l_tls_initimage_size); + } +#endif + +#ifdef __SUPPORT_LD_DEBUG__ + _dl_debug = _dl_getenv("LD_DEBUG", envp); + if (_dl_debug) { + if (_dl_strstr(_dl_debug, "all")) { + _dl_debug_detail = _dl_debug_move = _dl_debug_symbols + = _dl_debug_reloc = _dl_debug_bindings = _dl_debug_nofixups = (void*)1; + } else { + _dl_debug_detail = _dl_strstr(_dl_debug, "detail"); + _dl_debug_move = _dl_strstr(_dl_debug, "move"); + _dl_debug_symbols = _dl_strstr(_dl_debug, "sym"); + _dl_debug_reloc = _dl_strstr(_dl_debug, "reloc"); + _dl_debug_nofixups = _dl_strstr(_dl_debug, "nofix"); + _dl_debug_bindings = _dl_strstr(_dl_debug, "bind"); + } + } + + { + const char *dl_debug_output; + + dl_debug_output = _dl_getenv("LD_DEBUG_OUTPUT", envp); + + if (dl_debug_output) { + char tmp[22], *tmp1, *filename; + int len1, len2; + + _dl_memset(tmp, 0, sizeof(tmp)); + tmp1 = _dl_simple_ltoa( tmp, (unsigned long)_dl_getpid()); + + len1 = _dl_strlen(dl_debug_output); + len2 = _dl_strlen(tmp1); + + filename = _dl_malloc(len1 + len2 + 2); + + if (filename) { + _dl_strcpy (filename, dl_debug_output); + filename[len1] = '.'; + _dl_strcpy (&filename[len1+1], tmp1); + + _dl_debug_file = _dl_open(filename, O_WRONLY|O_CREAT, 0644); + if (_dl_debug_file < 0) { + _dl_debug_file = 2; + _dl_dprintf(_dl_debug_file, "can't open file: '%s'\n",filename); + } + } + } + } +#endif + + if (_dl_getenv("LD_TRACE_LOADED_OBJECTS", envp) != NULL) { + trace_loaded_objects++; + } + +#ifndef __LDSO_LDD_SUPPORT__ + if (trace_loaded_objects) { + _dl_dprintf(_dl_debug_file, "Use the ldd provided by uClibc\n"); + _dl_exit(1); + } +#endif + + /* + * OK, fix one more thing - set up debug_addr so it will point + * to our chain. Later we may need to fill in more fields, but this + * should be enough for now. + */ + debug_addr->r_map = (struct link_map *) _dl_loaded_modules; + debug_addr->r_version = 1; + debug_addr->r_ldbase = (ElfW(Addr)) DL_LOADADDR_BASE(load_addr); + debug_addr->r_brk = (unsigned long) &_dl_debug_state; + _dl_debug_addr = debug_addr; + + /* Do not notify the debugger until the interpreter is in the list */ + + /* OK, we now have the application in the list, and we have some + * basic stuff in place. Now search through the list for other shared + * libraries that should be loaded, and insert them on the list in the + * correct order. + */ + + _dl_map_cache(); + +#ifdef __LDSO_PRELOAD_ENV_SUPPORT__ + if (_dl_preload) { + char c, *str, *str2; + + str = _dl_preload; + while (*str == ':' || *str == ' ' || *str == '\t') + str++; + + while (*str) { + str2 = str; + while (*str2 && *str2 != ':' && *str2 != ' ' && *str2 != '\t') + str2++; + c = *str2; + *str2 = '\0'; + + if (!_dl_secure || _dl_strchr(str, '/') == NULL) { + _dl_if_debug_dprint("\tfile='%s'; needed by '%s'\n", str, _dl_progname); + + tpnt1 = _dl_load_shared_library(_dl_secure, &rpnt, NULL, str, trace_loaded_objects); + if (!tpnt1) { +#ifdef __LDSO_LDD_SUPPORT__ + if (trace_loaded_objects) + _dl_dprintf(1, "\t%s => not found\n", str); + else +#endif + { + _dl_dprintf(_dl_debug_file, "%s: can't load " "library '%s'\n", _dl_progname, str); + _dl_exit(15); + } + } else { + tpnt1->rtld_flags = unlazy | RTLD_GLOBAL; + + _dl_debug_early("Loading: (%x) %s\n", DL_LOADADDR_BASE(tpnt1->loadaddr), tpnt1->libname); + +#ifdef __LDSO_LDD_SUPPORT__ + if (trace_loaded_objects && + tpnt1->usage_count == 1) { + /* This is a real hack to make + * ldd not print the library + * itself when run on a + * library. + */ + if (_dl_strcmp(_dl_progname, str) != 0) + _dl_dprintf(1, "\t%s => %s (%x)\n", str, tpnt1->libname, + DL_LOADADDR_BASE(tpnt1->loadaddr)); + } +#endif + } + } + + *str2 = c; + str = str2; + while (*str == ':' || *str == ' ' || *str == '\t') + str++; + } + } +#endif /* __LDSO_PRELOAD_ENV_SUPPORT__ */ + +#ifdef __LDSO_PRELOAD_FILE_SUPPORT__ + do { + char *preload; + int fd; + char c, *cp, *cp2; + + if (_dl_stat(LDSO_PRELOAD, &st) || st.st_size == 0) { + break; + } + + if ((fd = _dl_open(LDSO_PRELOAD, O_RDONLY, 0)) < 0) { + _dl_dprintf(_dl_debug_file, "%s: can't open file '%s'\n", + _dl_progname, LDSO_PRELOAD); + break; + } + + preload = (caddr_t) _dl_mmap(0, st.st_size + 1, + PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); + _dl_close(fd); + if (preload == (caddr_t) -1) { + _dl_dprintf(_dl_debug_file, "%s:%i: can't map '%s'\n", + _dl_progname, __LINE__, LDSO_PRELOAD); + break; + } + + /* convert all separators and comments to spaces */ + for (cp = preload; *cp; /*nada */ ) { + if (*cp == ':' || *cp == '\t' || *cp == '\n') { + *cp++ = ' '; + } else if (*cp == '#') { + do { + *cp++ = ' '; + } while (*cp != '\n' && *cp != '\0'); + } else { + cp++; + } + } + + /* find start of first library */ + for (cp = preload; *cp && *cp == ' '; cp++) + /*nada */ ; + + while (*cp) { + /* find end of library */ + for (cp2 = cp; *cp && *cp != ' '; cp++) + /*nada */ ; + c = *cp; + *cp = '\0'; + + _dl_if_debug_dprint("\tfile='%s'; needed by '%s'\n", cp2, _dl_progname); + + tpnt1 = _dl_load_shared_library(0, &rpnt, NULL, cp2, trace_loaded_objects); + if (!tpnt1) { +# ifdef __LDSO_LDD_SUPPORT__ + if (trace_loaded_objects) + _dl_dprintf(1, "\t%s => not found\n", cp2); + else +# endif + { + _dl_dprintf(_dl_debug_file, "%s: can't load library '%s'\n", _dl_progname, cp2); + _dl_exit(15); + } + } else { + tpnt1->rtld_flags = unlazy | RTLD_GLOBAL; + + _dl_debug_early("Loading: (%x) %s\n", DL_LOADADDR_BASE(tpnt1->loadaddr), tpnt1->libname); + +# ifdef __LDSO_LDD_SUPPORT__ + if (trace_loaded_objects && + tpnt1->usage_count == 1) { + _dl_dprintf(1, "\t%s => %s (%x)\n", + cp2, tpnt1->libname, + DL_LOADADDR_BASE(tpnt1->loadaddr)); + } +# endif + } + + /* find start of next library */ + *cp = c; + for ( /*nada */ ; *cp && *cp == ' '; cp++) + /*nada */ ; + } + + _dl_munmap(preload, st.st_size + 1); + } while (0); +#endif /* __LDSO_PRELOAD_FILE_SUPPORT__ */ + + nlist = 0; + for (tcurr = _dl_loaded_modules; tcurr; tcurr = tcurr->next) { + ElfW(Dyn) *this_dpnt; + + nlist++; + for (this_dpnt = (ElfW(Dyn) *) tcurr->dynamic_addr; this_dpnt->d_tag; this_dpnt++) { + if (this_dpnt->d_tag == DT_NEEDED) { + char *name; + struct init_fini_list *tmp; + + lpntstr = (char*) (tcurr->dynamic_info[DT_STRTAB] + this_dpnt->d_un.d_val); + name = _dl_get_last_path_component(lpntstr); + if (_dl_strcmp(name, UCLIBC_LDSO) == 0) + continue; + + _dl_if_debug_dprint("\tfile='%s'; needed by '%s'\n", lpntstr, _dl_progname); + + if (!(tpnt1 = _dl_load_shared_library(0, &rpnt, tcurr, lpntstr, trace_loaded_objects))) { +#ifdef __LDSO_LDD_SUPPORT__ + if (trace_loaded_objects) { + _dl_dprintf(1, "\t%s => not found\n", lpntstr); + continue; + } else +#endif + { + _dl_dprintf(_dl_debug_file, "%s: can't load library '%s'\n", _dl_progname, lpntstr); + _dl_exit(16); + } + } + + tmp = alloca(sizeof(struct init_fini_list)); /* Allocates on stack, no need to free this memory */ + tmp->tpnt = tpnt1; + tmp->next = tcurr->init_fini; + tcurr->init_fini = tmp; + + tpnt1->rtld_flags = unlazy | RTLD_GLOBAL; + + _dl_debug_early("Loading: (%x) %s\n", DL_LOADADDR_BASE(tpnt1->loadaddr), tpnt1->libname); + +#ifdef __LDSO_LDD_SUPPORT__ + if (trace_loaded_objects && + tpnt1->usage_count == 1) { + _dl_dprintf(1, "\t%s => %s (%x)\n", + lpntstr, tpnt1->libname, + DL_LOADADDR_BASE(tpnt1->loadaddr)); + } +#endif + } + } + } + _dl_unmap_cache(); + + --nlist; /* Exclude the application. */ + init_fini_list = _dl_malloc(nlist * sizeof(struct elf_resolve *)); + i = 0; + for (tcurr = _dl_loaded_modules->next; tcurr; tcurr = tcurr->next) { + init_fini_list[i++] = tcurr; + } + + /* Sort the INIT/FINI list in dependency order. */ +#ifndef __AW11_LIB_DEP_SORT__ + _dl_lib_deps_sort(init_fini_list, nlist); +#else + for (tcurr = _dl_loaded_modules->next; tcurr; tcurr = tcurr->next) { + unsigned int j, k; + + for (j = 0; init_fini_list[j] != tcurr; ++j) + /* Empty */; + for (k = j + 1; k < nlist; ++k) { + struct init_fini_list *runp = init_fini_list[k]->init_fini; + + for (; runp; runp = runp->next) { + if (runp->tpnt == tcurr) { + struct elf_resolve *here = init_fini_list[k]; + _dl_if_debug_dprint("Move %s from pos %d to %d in INIT/FINI list\n", here->libname, k, j); + for (i = (k - j); i; --i) + init_fini_list[i+j] = init_fini_list[i+j-1]; + init_fini_list[j] = here; + ++j; + break; + } + } + } + } +#endif +#ifdef __SUPPORT_LD_DEBUG__ + if (_dl_debug) { + _dl_dprintf(_dl_debug_file, "\nINIT/FINI order and dependencies:\n"); + for (i = 0; i < nlist; i++) { + struct init_fini_list *tmp; + + _dl_dprintf(_dl_debug_file, "lib: %s has deps:\n", + init_fini_list[i]->libname); + tmp = init_fini_list[i]->init_fini; + for (; tmp; tmp = tmp->next) + _dl_dprintf(_dl_debug_file, " %s ", tmp->tpnt->libname); + _dl_dprintf(_dl_debug_file, "\n"); + } + } +#endif + + /* + * If the program interpreter is not in the module chain, add it. + * This will be required for dlopen to be able to access the internal + * functions in the dynamic linker and to relocate the interpreter + * again once all libs are loaded. + */ + if (tpnt) { + ElfW(Ehdr) *epnt = (ElfW(Ehdr) *) auxvt[AT_BASE].a_un.a_val; + ElfW(Phdr) *myppnt = (ElfW(Phdr) *) DL_RELOC_ADDR(load_addr, epnt->e_phoff); + int j; +#ifdef __DSBT__ + struct elf_resolve *ref = _dl_loaded_modules; + _dl_if_debug_dprint("ref is %x, dsbt %x, ref-dsbt %x size %x\n", + ref, tpnt->loadaddr.map->dsbt_table, + ref->loadaddr.map->dsbt_table, + tpnt->loadaddr.map->dsbt_size); + + _dl_memcpy(tpnt->loadaddr.map->dsbt_table, ref->loadaddr.map->dsbt_table, + tpnt->loadaddr.map->dsbt_size * sizeof(unsigned *)); +#endif + tpnt = _dl_add_elf_hash_table(tpnt->libname, load_addr, + tpnt->dynamic_info, + (unsigned long)tpnt->dynamic_addr, + 0); + + if (_dl_stat(tpnt->libname, &st) >= 0) { + tpnt->st_dev = st.st_dev; + tpnt->st_ino = st.st_ino; + } + tpnt->n_phent = epnt->e_phnum; + tpnt->ppnt = myppnt; + for (j = 0; j < epnt->e_phnum; j++, myppnt++) { + if (myppnt->p_type == PT_GNU_RELRO) { + tpnt->relro_addr = myppnt->p_vaddr; + tpnt->relro_size = myppnt->p_memsz; + break; + } + } + tpnt->libtype = program_interpreter; + tpnt->usage_count++; + tpnt->symbol_scope = _dl_symbol_tables; + if (rpnt) { + rpnt->next = _dl_zalloc(sizeof(struct dyn_elf)); + rpnt->next->prev = rpnt; + rpnt = rpnt->next; + } else { + rpnt = _dl_zalloc(sizeof(struct dyn_elf)); + } + rpnt->dyn = tpnt; + tpnt->rtld_flags = RTLD_NOW | RTLD_GLOBAL; /* Must not be LAZY */ +#ifdef RERELOCATE_LDSO + /* Only rerelocate functions for now. */ + tpnt->init_flag = RELOCS_DONE; + lpnt = (unsigned long *) (tpnt->dynamic_info[DT_PLTGOT]); +# ifdef ALLOW_ZERO_PLTGOT + if (tpnt->dynamic_info[DT_PLTGOT]) +# endif + INIT_GOT(lpnt, tpnt); +#else + tpnt->init_flag = RELOCS_DONE | JMP_RELOCS_DONE; +#endif + tpnt = NULL; + } + +#ifdef __LDSO_LDD_SUPPORT__ + /* End of the line for ldd.... */ + if (trace_loaded_objects) { + _dl_dprintf(1, "\t%s => %s (%x)\n", + rpnt->dyn->libname + _dl_strlen(_dl_ldsopath) + 1, + rpnt->dyn->libname, DL_LOADADDR_BASE(rpnt->dyn->loadaddr)); + _dl_exit(0); + } +#endif + +#if defined(USE_TLS) && USE_TLS + /* We do not initialize any of the TLS functionality unless any of the + * initial modules uses TLS. This makes dynamic loading of modules with + * TLS impossible, but to support it requires either eagerly doing setup + * now or lazily doing it later. Doing it now makes us incompatible with + * an old kernel that can't perform TLS_INIT_TP, even if no TLS is ever + * used. Trying to do it lazily is too hairy to try when there could be + * multiple threads (from a non-TLS-using libpthread). */ + bool was_tls_init_tp_called = tls_init_tp_called; + if (tcbp == NULL) { + _dl_debug_early("Calling init_tls()!\n"); + tcbp = init_tls (); + } +#endif +#ifdef __UCLIBC_HAS_SSP__ + /* Set up the stack checker's canary. */ + stack_chk_guard = _dl_setup_stack_chk_guard (); +# ifdef THREAD_SET_STACK_GUARD + THREAD_SET_STACK_GUARD (stack_chk_guard); +# else + __stack_chk_guard = stack_chk_guard; +# endif +# ifdef __UCLIBC_HAS_SSP_COMPAT__ + __guard = stack_chk_guard; +# endif +#endif + + + _dl_debug_early("Beginning relocation fixups\n"); + +#ifdef __mips__ + /* + * Relocation of the GOT entries for MIPS have to be done + * after all the libraries have been loaded. + */ + _dl_perform_mips_global_got_relocations(_dl_loaded_modules, !unlazy); +#endif + + /* + * OK, now all of the kids are tucked into bed in their proper + * addresses. Now we go through and look for REL and RELA records that + * indicate fixups to the GOT tables. We need to do this in reverse + * order so that COPY directives work correctly. + */ + if (_dl_symbol_tables) + if (_dl_fixup(_dl_symbol_tables, unlazy)) + _dl_exit(-1); + + for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next) { + if (tpnt->relro_size) + _dl_protect_relro (tpnt); + } + +#if defined(USE_TLS) && USE_TLS + if (!was_tls_init_tp_called && _dl_tls_max_dtv_idx > 0) + ++_dl_tls_generation; + + _dl_debug_early("Calling _dl_allocate_tls_init()!\n"); + + /* Now that we have completed relocation, the initializer data + for the TLS blocks has its final values and we can copy them + into the main thread's TLS area, which we allocated above. */ + _dl_allocate_tls_init (tcbp); + + /* And finally install it for the main thread. If ld.so itself uses + TLS we know the thread pointer was initialized earlier. */ + if (! tls_init_tp_called) { + const char *lossage = (char *) TLS_INIT_TP (tcbp, USE___THREAD); + if (__builtin_expect (lossage != NULL, 0)) { + _dl_debug_early("cannot set up thread-local storage: %s\n", lossage); + _dl_exit(30); + } + } +#endif /* USE_TLS */ + + /* OK, at this point things are pretty much ready to run. Now we need + * to touch up a few items that are required, and then we can let the + * user application have at it. Note that the dynamic linker itself + * is not guaranteed to be fully dynamicly linked if we are using + * ld.so.1, so we have to look up each symbol individually. + */ + + _dl_envp = (unsigned long *) (intptr_t) _dl_find_hash(__C_SYMBOL_PREFIX__ "__environ", _dl_symbol_tables, NULL, 0, NULL); + if (_dl_envp) + *_dl_envp = (unsigned long) envp; + +#ifndef __FORCE_SHAREABLE_TEXT_SEGMENTS__ + { + unsigned int j; + ElfW(Phdr) *myppnt; + + /* We had to set the protections of all pages to R/W for + * dynamic linking. Set text pages back to R/O. + */ + for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next) { + for (myppnt = tpnt->ppnt, j = 0; j < tpnt->n_phent; j++, myppnt++) { + if (myppnt->p_type == PT_LOAD && !(myppnt->p_flags & PF_W) && tpnt->dynamic_info[DT_TEXTREL]) { + _dl_mprotect((void *) (DL_RELOC_ADDR(tpnt->loadaddr, myppnt->p_vaddr) & PAGE_ALIGN), + (myppnt->p_vaddr & ADDR_ALIGN) + (unsigned long) myppnt->p_filesz, LXFLAGS(myppnt->p_flags)); + } + } + } + + } +#endif + /* Notify the debugger we have added some objects. */ + _dl_debug_addr->r_state = RT_ADD; + _dl_debug_state(); + + /* Run pre-initialization functions for the executable. */ + _dl_run_array_forward(_dl_loaded_modules->dynamic_info[DT_PREINIT_ARRAY], + _dl_loaded_modules->dynamic_info[DT_PREINIT_ARRAYSZ], + _dl_loaded_modules->loadaddr); + + /* Run initialization functions for loaded objects. For the + main executable, they will be run from __uClibc_main. */ + for (i = nlist; i; --i) { + tpnt = init_fini_list[i-1]; + tpnt->init_fini = NULL; /* Clear, since alloca was used */ + if (tpnt->init_flag & INIT_FUNCS_CALLED) + continue; + tpnt->init_flag |= INIT_FUNCS_CALLED; + + if (tpnt->dynamic_info[DT_INIT]) { + void (*dl_elf_func) (void); + + dl_elf_func = (void (*)(void)) DL_RELOC_ADDR(tpnt->loadaddr, tpnt->dynamic_info[DT_INIT]); + + _dl_if_debug_dprint("calling INIT: %s\n\n", tpnt->libname); + + DL_CALL_FUNC_AT_ADDR (dl_elf_func, tpnt->loadaddr, (void(*)(void))); + } + + _dl_run_init_array(tpnt); + } + + /* Find the real malloc function and make ldso functions use that from now on */ + _dl_malloc_function = (void* (*)(size_t)) (intptr_t) _dl_find_hash(__C_SYMBOL_PREFIX__ "malloc", + _dl_symbol_tables, NULL, ELF_RTYPE_CLASS_PLT, NULL); + +#if defined(USE_TLS) && USE_TLS + /* Find the real functions and make ldso functions use them from now on */ + _dl_calloc_function = (void* (*)(size_t, size_t)) (intptr_t) + _dl_find_hash(__C_SYMBOL_PREFIX__ "calloc", _dl_symbol_tables, NULL, ELF_RTYPE_CLASS_PLT, NULL); + + _dl_realloc_function = (void* (*)(void *, size_t)) (intptr_t) + _dl_find_hash(__C_SYMBOL_PREFIX__ "realloc", _dl_symbol_tables, NULL, ELF_RTYPE_CLASS_PLT, NULL); + + _dl_free_function = (void (*)(void *)) (intptr_t) + _dl_find_hash(__C_SYMBOL_PREFIX__ "free", _dl_symbol_tables, NULL, ELF_RTYPE_CLASS_PLT, NULL); + + _dl_memalign_function = (void* (*)(size_t, size_t)) (intptr_t) + _dl_find_hash(__C_SYMBOL_PREFIX__ "memalign", _dl_symbol_tables, NULL, ELF_RTYPE_CLASS_PLT, NULL); + +#endif + + /* Notify the debugger that all objects are now mapped in. */ + _dl_debug_addr->r_state = RT_CONSISTENT; + _dl_debug_state(); +} + +#include "dl-hash.c" +#include "dl-elf.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/m68k/dl-debug.h b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/m68k/dl-debug.h new file mode 100644 index 00000000..a9a80a06 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/m68k/dl-debug.h @@ -0,0 +1,42 @@ +/* vi: set sw=4 ts=4: */ +/* m68k ELF shared library loader suppport + * + * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald, + * David Engel, Hongjiu Lu and Mitch D'Souza + * Adapted to ELF/68k by Andreas Schwab. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. The name of the above contributors may not be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +static const char *_dl_reltypes_tab[] = { + [0] "R_68K_NONE", + [1] "R_68K_32", "R_68K_16", "R_68K_8", + [4] "R_68K_PC32", "R_68K_PC16", "R_68K_PC8", + [7] "R_68K_GOT32", "R_68K_GOT16", "R_68K_GOT8", + [10] "R_68K_GOT32O", "R_68K_GOT16O", "R_68K_GOT8O", + [13] "R_68K_PLT32", "R_68K_PLT16", "R_68K_PLT8", + [16] "R_68K_PLT32O", "R_68K_PLT16O", "R_68K_PLT8O", + [19] "R_68K_COPY", "R_68K_GLOB_DAT", "R_68K_JMP_SLOT", "R_68K_RELATIVE", + [23] "R_68K_NUM" +}; diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/m68k/dl-startup.h b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/m68k/dl-startup.h new file mode 100644 index 00000000..13530e05 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/m68k/dl-startup.h @@ -0,0 +1,97 @@ +/* vi: set sw=4 ts=4: */ +/* + * Architecture specific code used by dl-startup.c + * Copyright (C) 2005 by Erik Andersen + */ + +/* Perform operation OP with PC-relative SRC as the first operand and + * DST as the second. TMP is available as a temporary if needed. */ + +#ifdef __mcoldfire__ +#define PCREL_OP(OP, SRC, DST, TMP, PC) \ + "move.l #" SRC " - ., " TMP "\n\t" OP " (-8, " PC ", " TMP "), " DST +#else +#define PCREL_OP(OP, SRC, DST, TMP, PC) \ + OP " " SRC "(" PC "), " DST +#endif + +__asm__ ("\ + .text\n\ + .globl _start\n\ + .type _start,@function\n\ +_start:\n\ + move.l %sp, -(%sp)\n\ + jbsr _dl_start\n\ + addq.l #4, %sp\n\ + /* FALLTHRU */\n\ +\n\ + .globl _dl_start_user\n\ +.type _dl_start_user,@function\n\ +_dl_start_user:\n\ + # Save the user entry point address in %a4.\n\ + move.l %d0, %a4\n\ + # See if we were run as a command with the executable file\n\ + # name as an extra leading argument.\n\ + " PCREL_OP ("move.l", "_dl_skip_args", "%d0", "%d0", "%pc") "\n\ + # Pop the original argument count\n\ + move.l (%sp)+, %d1\n\ + # Subtract _dl_skip_args from it.\n\ + sub.l %d0, %d1\n\ + # Adjust the stack pointer to skip _dl_skip_args words.\n\ + lea (%sp, %d0*4), %sp\n\ + # Push back the modified argument count.\n\ + move.l %d1, -(%sp)\n\ + # Pass our finalizer function to the user in %a1.\n\ + " PCREL_OP ("lea", "_dl_fini", "%a1", "%a1", "%pc") "\n\ + # Initialize %fp with the stack pointer.\n\ + move.l %sp, %fp\n\ + # Jump to the user's entry point.\n\ + jmp (%a4)\n\ + .size _dl_start_user, . - _dl_start_user\n\ + .previous"); + +/* Get a pointer to the argv array. On many platforms this can be just + * the address of the first argument, on other platforms we need to + * do something a little more subtle here. */ +#define GET_ARGV(ARGVP, ARGS) ARGVP = (((unsigned long *) ARGS) + 1) + +/* Handle relocation of the symbols in the dynamic loader. */ +static __always_inline +void PERFORM_BOOTSTRAP_RELOC(ELF_RELOC *rpnt, unsigned long *reloc_addr, + unsigned long symbol_addr, unsigned long load_addr, Elf32_Sym *symtab) +{ + switch (ELF32_R_TYPE(rpnt->r_info)) + { + case R_68K_8: + *(char *) reloc_addr = symbol_addr + rpnt->r_addend; + break; + case R_68K_16: + *(short *) reloc_addr = symbol_addr + rpnt->r_addend; + break; + case R_68K_32: + *reloc_addr = symbol_addr + rpnt->r_addend; + break; + case R_68K_PC8: + *(char *) reloc_addr = (symbol_addr + rpnt->r_addend + - (unsigned int) reloc_addr); + break; + case R_68K_PC16: + *(short *) reloc_addr = (symbol_addr + rpnt->r_addend + - (unsigned int) reloc_addr); + break; + case R_68K_PC32: + *reloc_addr = (symbol_addr + rpnt->r_addend + - (unsigned int) reloc_addr); + break; + case R_68K_GLOB_DAT: + case R_68K_JMP_SLOT: + *reloc_addr = symbol_addr; + break; + case R_68K_RELATIVE: + *reloc_addr = ((unsigned int) load_addr + + (rpnt->r_addend ? : *reloc_addr)); + break; + default: + _dl_exit (1); + } +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/m68k/dl-syscalls.h b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/m68k/dl-syscalls.h new file mode 100644 index 00000000..996bb87c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/m68k/dl-syscalls.h @@ -0,0 +1,6 @@ +/* We can't use the real errno in ldso, since it has not yet + * been dynamicly linked in yet. */ +#include "sys/syscall.h" +extern int _dl_errno; +#undef __set_errno +#define __set_errno(X) {(_dl_errno) = (X);} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/m68k/dl-sysdep.h b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/m68k/dl-sysdep.h new file mode 100644 index 00000000..b5eda4e9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/m68k/dl-sysdep.h @@ -0,0 +1,82 @@ +/* vi: set sw=4 ts=4: */ +/* + * Various assembly language/system dependent hacks that are required + * so that we can minimize the amount of platform specific code. + * Copyright (C) 2005 by Erik Andersen + */ + +/* Define this if the system uses RELOCA. */ +#define ELF_USES_RELOCA +#include +/* Initialization sequence for a GOT. */ +#define INIT_GOT(GOT_BASE,MODULE) \ +do { \ + GOT_BASE[2] = (unsigned long) _dl_linux_resolve; \ + GOT_BASE[1] = (unsigned long) (MODULE); \ +} while(0) + +/* Here we define the magic numbers that this dynamic loader should accept */ +#define MAGIC1 EM_68K +#undef MAGIC2 + +/* Used for error messages */ +#define ELF_TARGET "m68k" + +/* Need bootstrap relocations */ +#define ARCH_NEEDS_BOOTSTRAP_RELOCS + +struct elf_resolve; +extern unsigned long _dl_linux_resolver (struct elf_resolve *, int); + +/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry, so + PLT entries should not be allowed to define the value. + ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to one + of the main executable's symbols, as for a COPY reloc. */ +#define elf_machine_type_class(type) \ + ((((type) == R_68K_JMP_SLOT) * ELF_RTYPE_CLASS_PLT) \ + | (((type) == R_68K_COPY) * ELF_RTYPE_CLASS_COPY)) + +/* Return the link-time address of _DYNAMIC. Conveniently, this is the + first element of the GOT. This must be inlined in a function which + uses global data. */ +static __always_inline Elf32_Addr +elf_machine_dynamic (void) +{ + Elf32_Addr got; + + __asm__ ("move.l _DYNAMIC@GOT.w(%%a5), %0" + : "=a" (got)); + return got; +} + +#ifdef __mcoldfire__ +#define PCREL_OP(OP, SRC, DST, TMP, PC) \ + "move.l #" SRC " - ., " TMP "\n\t" OP " (-8, " PC ", " TMP "), " DST +#else +#define PCREL_OP(OP, SRC, DST, TMP, PC) \ + OP " " SRC "(" PC "), " DST +#endif + +/* Return the run-time load address of the shared object. */ +static __always_inline Elf32_Addr +elf_machine_load_address (void) +{ + Elf32_Addr addr; + __asm__ (PCREL_OP ("lea", "_dl_start", "%0", "%0", "%%pc") "\n\t" + "sub.l _dl_start@GOT.w(%%a5), %0" + : "=a" (addr)); + return addr; +} + +static __always_inline void +elf_machine_relative (Elf32_Addr load_off, const Elf32_Addr rel_addr, + Elf32_Word relative_count) +{ + Elf32_Rela * rpnt = (void *)rel_addr; + --rpnt; + do { + Elf32_Addr *const reloc_addr = (void *) (load_off + (++rpnt)->r_offset); + + *reloc_addr = load_off + rpnt->r_addend; + } while (--relative_count); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/m68k/elfinterp.c b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/m68k/elfinterp.c new file mode 100644 index 00000000..3dfd50e9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/m68k/elfinterp.c @@ -0,0 +1,319 @@ +/* vi: set sw=4 ts=4: */ +/* m68k ELF shared library loader suppport + * + * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald, + * David Engel, Hongjiu Lu and Mitch D'Souza + * Adapted to ELF/68k by Andreas Schwab. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. The name of the above contributors may not be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* Program to load an ELF binary on a linux system, and run it. + References to symbols in sharable libraries can be resolved by either + an ELF sharable library or a linux style of shared library. */ + +/* Disclaimer: I have never seen any AT&T source code for SVr4, nor have + I ever taken any courses on internals. This program was developed using + information available through the book "UNIX SYSTEM V RELEASE 4, + Programmers guide: Ansi C and Programming Support Tools", which did + a more than adequate job of explaining everything required to get this + working. */ + +#include "ldso.h" + +extern int _dl_linux_resolve(void); + +unsigned long +_dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry) +{ + ELF_RELOC *this_reloc; + char *strtab; + ElfW(Sym) *symtab; + int symtab_index; + char *rel_addr; + char *new_addr; + char **got_addr; + ElfW(Addr) instr_addr; + char *symname; + + rel_addr = (char *)tpnt->dynamic_info[DT_JMPREL]; + this_reloc = (ELF_RELOC *)(rel_addr + reloc_entry); + symtab_index = ELF_R_SYM(this_reloc->r_info); + + symtab = (ElfW(Sym) *)tpnt->dynamic_info[DT_SYMTAB]; + strtab = (char *)tpnt->dynamic_info[DT_STRTAB]; + symname = strtab + symtab[symtab_index].st_name; + + /* Address of the jump instruction to fix up. */ + instr_addr = (this_reloc->r_offset + tpnt->loadaddr); + got_addr = (char **)instr_addr; + + /* Get the address of the GOT entry. */ + new_addr = _dl_find_hash(symname, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL); + if (unlikely(!new_addr)) { + _dl_dprintf(2, "%s: Can't resolve symbol '%s'\n", _dl_progname, symname); + _dl_exit(1); + } + +#if defined (__SUPPORT_LD_DEBUG__) + if ((unsigned long)got_addr < 0x40000000) { + if (_dl_debug_bindings) { + _dl_dprintf(_dl_debug_file, "\nresolve function: %s", symname); + if (_dl_debug_detail) + _dl_dprintf(_dl_debug_file, + "\tpatched: %x ==> %x @ %x\n", + *got_addr, new_addr, got_addr); + } + } + if (!_dl_debug_nofixups) +#endif + *got_addr = new_addr; + + return (unsigned int)new_addr; +} + +static int +_dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope, + unsigned long rel_addr, unsigned long rel_size, + int (*reloc_fnc)(struct elf_resolve *tpnt, struct dyn_elf *scope, + ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab)) +{ + unsigned int i; + char *strtab; + ElfW(Sym) *symtab; + ELF_RELOC *rpnt; + int symtab_index; + + /* Parse the relocation information. */ + rpnt = (ELF_RELOC *)rel_addr; + rel_size /= sizeof(ELF_RELOC); + + symtab = (ElfW(Sym) *)tpnt->dynamic_info[DT_SYMTAB]; + strtab = (char *)tpnt->dynamic_info[DT_STRTAB]; + + for (i = 0; i < rel_size; i++, rpnt++) { + int res; + + symtab_index = ELF_R_SYM(rpnt->r_info); + + debug_sym(symtab, strtab, symtab_index); + debug_reloc(symtab, strtab, rpnt); + + res = reloc_fnc(tpnt, scope, rpnt, symtab, strtab); + + if (res == 0) + continue; + + _dl_dprintf(2, "\n%s: ", _dl_progname); + + if (symtab_index) + _dl_dprintf(2, "symbol '%s': ", + strtab + symtab[symtab_index].st_name); + + if (unlikely(res < 0)) { + int reloc_type = ELF_R_TYPE(rpnt->r_info); + + _dl_dprintf(2, "can't handle reloc type " +#if defined (__SUPPORT_LD_DEBUG__) + "%s\n", _dl_reltypes(reloc_type)); +#else + "%x\n", reloc_type); +#endif + _dl_exit(-res); + } else if (unlikely(res > 0)) { + _dl_dprintf(2, "can't resolve symbol\n"); + return res; + } + } + + return 0; +} + +static int +_dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, + ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab) +{ + int reloc_type; + int symtab_index; + char *symname; + struct symbol_ref sym_ref; + ElfW(Addr) *reloc_addr; + ElfW(Addr) symbol_addr; +#if defined (__SUPPORT_LD_DEBUG__) + ElfW(Addr) old_val; +#endif + + reloc_addr = (ElfW(Addr)*)(tpnt->loadaddr + (unsigned long)rpnt->r_offset); + reloc_type = ELF_R_TYPE(rpnt->r_info); + symtab_index = ELF_R_SYM(rpnt->r_info); + sym_ref.sym = &symtab[symtab_index]; + sym_ref.tpnt = NULL; + symbol_addr = 0; + symname = strtab + sym_ref.sym->st_name; + + if (symtab_index) { + symbol_addr = (ElfW(Addr))_dl_find_hash(symname, scope, tpnt, + elf_machine_type_class(reloc_type), &sym_ref); + /* + * We want to allow undefined references to weak symbols - this + * might have been intentional. We should not be linking local + * symbols here, so all bases should be covered. + */ + if (unlikely(!symbol_addr && ELF_ST_BIND(sym_ref.sym->st_info) != STB_WEAK)) { + _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", _dl_progname, symname); + _dl_exit(1); + } + } + +#if defined (__SUPPORT_LD_DEBUG__) + old_val = *reloc_addr; +#endif + + switch (reloc_type) { + case R_68K_NONE: + break; + case R_68K_8: + *(char *) reloc_addr = symbol_addr + rpnt->r_addend; + break; + case R_68K_16: + *(short *) reloc_addr = symbol_addr + rpnt->r_addend; + break; + case R_68K_32: + *reloc_addr = symbol_addr + rpnt->r_addend; + break; + case R_68K_PC8: + *(char *) reloc_addr = (symbol_addr + rpnt->r_addend + - (unsigned int) reloc_addr); + break; + case R_68K_PC16: + *(short *) reloc_addr = (symbol_addr + rpnt->r_addend + - (unsigned int) reloc_addr); + break; + case R_68K_PC32: + *reloc_addr = (symbol_addr + rpnt->r_addend + - (unsigned int) reloc_addr); + break; + case R_68K_GLOB_DAT: + case R_68K_JMP_SLOT: + *reloc_addr = symbol_addr + rpnt->r_addend; + break; + /* handled by elf_machine_relative() + case R_68K_RELATIVE: + *reloc_addr = ((unsigned int) tpnt->loadaddr + / * Compatibility kludge. * / + + (rpnt->r_addend ? : *reloc_addr)); + */ + break; + case R_68K_COPY: + if (symbol_addr) { +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_move) + _dl_dprintf(_dl_debug_file, + "\t%s move %d bytes from %x to %x\n", + symname, sym_ref.sym->st_size, + symbol_addr, reloc_addr); +#endif + _dl_memcpy ((void *) reloc_addr, + (void *) symbol_addr, + sym_ref.sym->st_size); + } else + _dl_dprintf(_dl_debug_file, "no symbol_addr to copy !?\n"); + break; + + default: + return -1; /* Calls _dl_exit(1). */ + } + +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_reloc && _dl_debug_detail) + _dl_dprintf(_dl_debug_file, "\tpatched: %x ==> %x @ %x\n", + old_val, *reloc_addr, reloc_addr); +#endif + + return 0; +} + +#undef LAZY_RELOC_WORKS +#ifdef LAZY_RELOC_WORKS +static int +_dl_do_lazy_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, + ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab) +{ + int reloc_type; + int symtab_index; + ElfW(Addr) *reloc_addr; +#if defined (__SUPPORT_LD_DEBUG__) + ElfW(Addr) old_val; +#endif + + (void)scope; + symtab_index = ELF_R_SYM(rpnt->r_info); + (void)strtab; + + reloc_addr = (ElfW(Addr)*)(tpnt->loadaddr + rpnt->r_offset); + reloc_type = ELF_R_TYPE(rpnt->r_info); + +#if defined (__SUPPORT_LD_DEBUG__) + old_val = *reloc_addr; +#endif + + switch (reloc_type) { + case R_68K_NONE: + break; + case R_68K_JMP_SLOT: + *reloc_addr += (unsigned int) tpnt->loadaddr; + break; + default: + _dl_exit(1); + } + +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_reloc && _dl_debug_detail) + _dl_dprintf(_dl_debug_file, "\tpatched_lazy: %x ==> %x @ %x\n", + old_val, *reloc_addr, reloc_addr); +#endif + + return 0; +} +#endif + +void +_dl_parse_lazy_relocation_information(struct dyn_elf *rpnt, + unsigned long rel_addr, + unsigned long rel_size) +{ +#ifdef LAZY_RELOC_WORKS + (void)_dl_parse(rpnt->dyn, NULL, rel_addr, rel_size, _dl_do_lazy_reloc); +#else + _dl_parse_relocation_information(rpnt, rel_addr, rel_size); +#endif +} + +int +_dl_parse_relocation_information(struct dyn_elf *rpnt, + unsigned long rel_addr, + unsigned long rel_size) +{ + return _dl_parse(rpnt->dyn, rpnt->dyn->symbol_scope, rel_addr, rel_size, _dl_do_reloc); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/m68k/resolve.S b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/m68k/resolve.S new file mode 100644 index 00000000..1bd5c009 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/m68k/resolve.S @@ -0,0 +1,28 @@ +/* + * These are various helper routines that are needed to run an ELF image. + */ + +.text +.even + +.globl _dl_linux_resolve + .type _dl_linux_resolve,@function +_dl_linux_resolve: + # Save %a0 (struct return address) and %a1. + move.l %a0, -(%sp) + move.l %a1, -(%sp) + # Call the real address resolver. + jbsr _dl_linux_resolver + # Restore register %a0 and %a1. + move.l (%sp)+, %a1 + move.l (%sp)+, %a0 + # Pop parameters + addq.l #8, %sp + # Call real function. +#if defined __mcoldfire__ + move.l %d0,-(%sp) + rts +#else + jmp (%d0) +#endif +.size _dl_linux_resolve,.-_dl_linux_resolve diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/mips/README b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/mips/README new file mode 100644 index 00000000..9ca6a869 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/mips/README @@ -0,0 +1,52 @@ +Almost all of the code present in these source files was taken +from GLIBC. In the descriptions below, all files mentioned are +with respect to the top level GLIBC source directory accept for +code taken from the Linux kernel. + +boot1_arch.h +------------ +Contains code to fix up the stack pointer so that the dynamic +linker can find argc, argv and Auxillary Vector Table (AVT). +The code is taken from the function 'RTLD_START' in the file +'sysdeps/mips/dl-machine.h'. + +elfinterp.c +----------- +Contains the runtime resolver code taken from the function +'__dl_runtime_resolve' in 'sysdeps/mips/dl-machine.h'. Also +contains the function to perform relocations for objects +other than the linker itself. The code was taken from the +function 'elf_machine_rel' in 'sysdeps/mips/dl-machine.h'. + +dl-syscalls.h +------------- +Used to contain all the macro functions for the system calls +as well as the list of system calls supported. We now include + but with the __set_errno macro defined empty +so we can use the same file for the linker as well as userspace. +Original code was taken from the Linux kernel source 2.4.17 and +can be found in the file 'include/asm-mips/unistd.h'. + +dl-sysdep.h +----------- +Contains bootstrap code for the dynamic linker, magic numbers +for detecting MIPS target types and some macros. The macro +function 'PERFORM_BOOTSTRAP_GOT' is used to relocate the dynamic +linker's GOT so that function calls can be made. The code is +taken from the function 'ELF_MACHINE_BEFORE_RTLD_RELOC' in the +file 'sysdeps/mips/dl-machine.h'. The other macro function +'PERFORM_BOOTSTRAP_RELOC' is used to do the relocations for +the dynamic loader. The code is taken from the function +'elf_machine_rel' in the file 'sysdeps/mips/dl-machine.h'. The +final macro function is 'INIT_GOT' which initializes the GOT +for the application being dynamically linked and loaded. The +code is taken from the functions 'elf_machine_runtime_setup' +and 'elf_machine_got_rel' in 'sysdeps/mips/dl-machine.h'. + +resolve.S +--------- +Contains the low-level assembly code for the dynamic runtime +resolver. The code is taken from the assembly code function +'_dl_runtime_resolve' in the file 'sysdeps/mips/dl-machine.h'. +The code looks a bit different since we only need to pass the +symbol index and the old GP register. diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/mips/dl-debug.h b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/mips/dl-debug.h new file mode 100644 index 00000000..07a2addf --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/mips/dl-debug.h @@ -0,0 +1,45 @@ +/* vi: set sw=4 ts=4: */ +/* mips/mipsel ELF shared library loader suppport + * + Copyright (C) 2002, Steven J. Hill (sjhill@realitydiluted.com) + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. The name of the above contributors may not be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +static const char *_dl_reltypes_tab[] = +{ + [0] "R_MIPS_NONE", "R_MIPS_16", "R_MIPS_32", + [3] "R_MIPS_REL32", "R_MIPS_26", "R_MIPS_HI16", + [6] "R_MIPS_LO16", "R_MIPS_GPREL16", "R_MIPS_LITERAL", + [9] "R_MIPS_GOT16", "R_MIPS_PC16", "R_MIPS_CALL16", + [12] "R_MIPS_GPREL32", + [16] "R_MIPS_SHIFT5", "R_MIPS_SHIFT6", "R_MIPS_64", + [19] "R_MIPS_GOT_DISP", "R_MIPS_GOT_PAGE", "R_MIPS_GOT_OFST", + [22] "R_MIPS_GOT_HI16", "R_MIPS_GOT_LO16", "R_MIPS_SUB", + [25] "R_MIPS_INSERT_A", "R_MIPS_INSERT_B", "R_MIPS_DELETE", + [28] "R_MIPS_HIGHER", "R_MIPS_HIGHEST", "R_MIPS_CALL_HI16", + [31] "R_MIPS_CALL_LO16", "R_MIPS_SCN_DISP", "R_MIPS_REL16", + [34] "R_MIPS_ADD_IMMEDIATE", "R_MIPS_PJUMP", "R_MIPS_RELGOT", + [37] "R_MIPS_JALR", +}; diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/mips/dl-startup.h b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/mips/dl-startup.h new file mode 100644 index 00000000..31730d4a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/mips/dl-startup.h @@ -0,0 +1,190 @@ +/* Any assembly language/system dependent hacks needed to setup boot1.c so it + * will work as expected and cope with whatever platform specific wierdness is + * needed for this architecture. + * Copyright (C) 2005 by Joakim Tjernlund + * Copyright (C) 2005 by Erik Andersen + */ + + +#include +__asm__("" + " .text\n" + " .globl _start\n" + " .ent _start\n" + " .type _start,@function\n" + "_start:\n" + " .set noreorder\n" + " move $25, $31\n" + " bal 0f\n" + " nop\n" + "0:\n" +#if _MIPS_SIM == _MIPS_SIM_ABI32 + " .cpload $31\n" +#else /* N32 || N64 */ + " .cpsetup $31, $2, 0b\n" +#endif /* N32 || N64 */ + " move $31, $25\n" + " .set reorder\n" +#if _MIPS_SIM == _MIPS_SIM_ABI64 + " dla $4, _DYNAMIC\n" + " sd $4, -0x7ff0($28)\n" +#else /* O32 || N32 */ + " la $4, _DYNAMIC\n" + " sw $4, -0x7ff0($28)\n" +#endif /* O32 || N32 */ + " move $4, $29\n" +#if _MIPS_SIM == _MIPS_SIM_ABI32 + " subu $29, 16\n" +#endif +#if _MIPS_SIM == _MIPS_SIM_ABI64 + " dla $8, .coff\n" +#else /* O32 || N32 */ + " la $8, .coff\n" +#endif /* O32 || N32 */ + " bltzal $8, .coff\n" + ".coff:\n" +#if _MIPS_SIM == _MIPS_SIM_ABI64 + " dsubu $8, $31, $8\n" + " dla $25, _dl_start\n" + " daddu $25, $8\n" +#else /* O32 || N32 */ + " subu $8, $31, $8\n" + " la $25, _dl_start\n" + " addu $25, $8\n" +#endif /* O32 || N32 */ + " jalr $25\n" +#if _MIPS_SIM == _MIPS_SIM_ABI32 + " addiu $29, 16\n" +#endif + " move $16, $28\n" + " move $17, $2\n" +#if _MIPS_SIM == _MIPS_SIM_ABI64 + " ld $2, _dl_skip_args\n" + " beq $2, $0, 1f\n" + " ld $4, 0($29)\n" + " dsubu $4, $2\n" + " dsll $2, 2\n" + " daddu $29, $2\n" + " sd $4, 0($29)\n" + "1:\n" + " ld $5, 0($29)\n" + " dla $6, 8 ($29)\n" + " dsll $7, $5, 2\n" + " daddu $7, $7, $6\n" + " daddu $7, $7, 4\n" + " and $2, $29, -4 * 4\n" + " sd $29, -8($2)\n" + " dsubu $29, $2, 32\n" + " ld $29, 24($29)\n" + " dla $2, _dl_fini\n" +#else /* O32 || N32 */ + " lw $2, _dl_skip_args\n" + " beq $2, $0, 1f\n" + " lw $4, 0($29)\n" + " subu $4, $2\n" + " sll $2, 2\n" + " addu $29, $2\n" + " sw $4, 0($29)\n" + "1:\n" + " lw $5, 0($29)\n" + " la $6, 4 ($29)\n" + " sll $7, $5, 2\n" + " addu $7, $7, $6\n" + " addu $7, $7, 4\n" + " and $2, $29, -2 * 4\n" + " sw $29, -4($2)\n" + " subu $29, $2, 32\n" +#if _MIPS_SIM == _MIPS_SIM_ABI32 + " .cprestore 16\n" +#endif + " lw $29, 28($29)\n" + " la $2, _dl_fini\n" +#endif /* O32 || N32 */ + " move $25, $17\n" + " jr $25\n" + ".end _start\n" + ".size _start, . -_start\n" + "\n\n" + "\n\n" + ".previous\n" +); + +/* + * Get a pointer to the argv array. On many platforms this can be just + * the address of the first argument, on other platforms we need to + * do something a little more subtle here. + */ +#define GET_ARGV(ARGVP, ARGS) ARGVP = (((unsigned long *) ARGS)+1) + + +/* We can't call functions earlier in the dl startup process */ +#define NO_FUNCS_BEFORE_BOOTSTRAP + + +/* + * Here is a macro to perform the GOT relocation. This is only + * used when bootstrapping the dynamic loader. + */ +#define PERFORM_BOOTSTRAP_GOT(tpnt) \ +do { \ + ElfW(Sym) *sym; \ + ElfW(Addr) i; \ + register ElfW(Addr) gp __asm__ ("$28"); \ + ElfW(Addr) *mipsgot = elf_mips_got_from_gpreg (gp); \ + \ + /* Add load address displacement to all local GOT entries */ \ + i = 2; \ + while (i < tpnt->dynamic_info[DT_MIPS_LOCAL_GOTNO_IDX]) \ + mipsgot[i++] += tpnt->loadaddr; \ + \ + /* Handle global GOT entries */ \ + mipsgot += tpnt->dynamic_info[DT_MIPS_LOCAL_GOTNO_IDX]; \ + sym = (ElfW(Sym) *) tpnt->dynamic_info[DT_SYMTAB] + \ + tpnt->dynamic_info[DT_MIPS_GOTSYM_IDX]; \ + i = tpnt->dynamic_info[DT_MIPS_SYMTABNO_IDX] - tpnt->dynamic_info[DT_MIPS_GOTSYM_IDX];\ + \ + while (i--) { \ + if (sym->st_shndx == SHN_UNDEF || \ + sym->st_shndx == SHN_COMMON) \ + *mipsgot = tpnt->loadaddr + sym->st_value; \ + else if (ELF_ST_TYPE(sym->st_info) == STT_FUNC && \ + *mipsgot != sym->st_value) \ + *mipsgot += tpnt->loadaddr; \ + else if (ELF_ST_TYPE(sym->st_info) == STT_SECTION) { \ + if (sym->st_other == 0) \ + *mipsgot += tpnt->loadaddr; \ + } \ + else \ + *mipsgot = tpnt->loadaddr + sym->st_value; \ + \ + mipsgot++; \ + sym++; \ + } \ +} while (0) + +/* + * Here is a macro to perform a relocation. This is only used when + * bootstrapping the dynamic loader. + */ +#if _MIPS_SIM == _MIPS_SIM_ABI64 /* consult with glibc sysdeps/mips/dl-machine.h 1.69 */ +#define R_MIPS_BOOTSTRAP_RELOC ((R_MIPS_64 << 8) | R_MIPS_REL32) +#else /* N32 || O32 */ +#define R_MIPS_BOOTSTRAP_RELOC R_MIPS_REL32 +#endif +#define PERFORM_BOOTSTRAP_RELOC(RELP,REL,SYMBOL,LOAD,SYMTAB) \ + switch(ELF_R_TYPE((RELP)->r_info)) { \ + case R_MIPS_BOOTSTRAP_RELOC: \ + if (SYMTAB) { \ + if (symtab_indexdynamic_info[DT_MIPS_GOTSYM_IDX])\ + *REL += SYMBOL; \ + } \ + else { \ + *REL += LOAD; \ + } \ + break; \ + case R_MIPS_NONE: \ + break; \ + default: \ + SEND_STDERR("Aiieeee!"); \ + _dl_exit(1); \ + } diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/mips/dl-syscalls.h b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/mips/dl-syscalls.h new file mode 100644 index 00000000..996bb87c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/mips/dl-syscalls.h @@ -0,0 +1,6 @@ +/* We can't use the real errno in ldso, since it has not yet + * been dynamicly linked in yet. */ +#include "sys/syscall.h" +extern int _dl_errno; +#undef __set_errno +#define __set_errno(X) {(_dl_errno) = (X);} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/mips/dl-sysdep.h b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/mips/dl-sysdep.h new file mode 100644 index 00000000..80c089ae --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/mips/dl-sysdep.h @@ -0,0 +1,242 @@ +/* vi: set sw=8 ts=8: */ + +/* + * Various assembly language/system dependent hacks that are required + * so that we can minimize the amount of platform specific code. + */ + +/* Define this if the system uses RELOCA. */ +#undef ELF_USES_RELOCA +#include + +#ifdef __mips64 /* from glibc sysdeps/mips/elf/ldsodefs.h 1.4 */ +/* The 64-bit MIPS ELF ABI uses an unusual reloc format. Each + relocation entry specifies up to three actual relocations, all at + the same address. The first relocation which required a symbol + uses the symbol in the r_sym field. The second relocation which + requires a symbol uses the symbol in the r_ssym field. If all + three relocations require a symbol, the third one uses a zero + value. + + We define these structures in internal headers because we're not + sure we want to make them part of the ABI yet. Eventually, some of + this may move into elf/elf.h. */ + +/* An entry in a 64 bit SHT_REL section. */ + +typedef struct +{ + Elf32_Word r_sym; /* Symbol index */ + unsigned char r_ssym; /* Special symbol for 2nd relocation */ + unsigned char r_type3; /* 3rd relocation type */ + unsigned char r_type2; /* 2nd relocation type */ + unsigned char r_type1; /* 1st relocation type */ +} _Elf64_Mips_R_Info; + +typedef union +{ + Elf64_Xword r_info_number; + _Elf64_Mips_R_Info r_info_fields; +} _Elf64_Mips_R_Info_union; + +typedef struct +{ + Elf64_Addr r_offset; /* Address */ + _Elf64_Mips_R_Info_union r_info; /* Relocation type and symbol index */ +} Elf64_Mips_Rel; + +typedef struct +{ + Elf64_Addr r_offset; /* Address */ + _Elf64_Mips_R_Info_union r_info; /* Relocation type and symbol index */ + Elf64_Sxword r_addend; /* Addend */ +} Elf64_Mips_Rela; + +#define ELF64_MIPS_R_SYM(i) \ + ((__extension__ (_Elf64_Mips_R_Info_union)(i)).r_info_fields.r_sym) +#define ELF64_MIPS_R_TYPE(i) \ + (((_Elf64_Mips_R_Info_union)(i)).r_info_fields.r_type1 \ + | ((Elf32_Word)(__extension__ (_Elf64_Mips_R_Info_union)(i) \ + ).r_info_fields.r_type2 << 8) \ + | ((Elf32_Word)(__extension__ (_Elf64_Mips_R_Info_union)(i) \ + ).r_info_fields.r_type3 << 16) \ + | ((Elf32_Word)(__extension__ (_Elf64_Mips_R_Info_union)(i) \ + ).r_info_fields.r_ssym << 24)) +#define ELF64_MIPS_R_INFO(sym, type) \ + (__extension__ (_Elf64_Mips_R_Info_union) \ + (__extension__ (_Elf64_Mips_R_Info) \ + { (sym), ELF64_MIPS_R_SSYM (type), \ + ELF64_MIPS_R_TYPE3 (type), \ + ELF64_MIPS_R_TYPE2 (type), \ + ELF64_MIPS_R_TYPE1 (type) \ + }).r_info_number) +/* These macros decompose the value returned by ELF64_MIPS_R_TYPE, and + compose it back into a value that it can be used as an argument to + ELF64_MIPS_R_INFO. */ +#define ELF64_MIPS_R_SSYM(i) (((i) >> 24) & 0xff) +#define ELF64_MIPS_R_TYPE3(i) (((i) >> 16) & 0xff) +#define ELF64_MIPS_R_TYPE2(i) (((i) >> 8) & 0xff) +#define ELF64_MIPS_R_TYPE1(i) ((i) & 0xff) +#define ELF64_MIPS_R_TYPEENC(type1, type2, type3, ssym) \ + ((type1) \ + | ((Elf32_Word)(type2) << 8) \ + | ((Elf32_Word)(type3) << 16) \ + | ((Elf32_Word)(ssym) << 24)) + +#undef ELF64_R_SYM +#define ELF64_R_SYM(i) ELF64_MIPS_R_SYM (i) +#undef ELF64_R_TYPE +#define ELF64_R_TYPE(i) ELF64_MIPS_R_TYPE (i) +#undef ELF64_R_INFO +#define ELF64_R_INFO(sym, type) ELF64_MIPS_R_INFO ((sym), (type)) +#endif /* __mips64 */ + +#include + +#define ARCH_NUM 4 +#define DT_MIPS_GOTSYM_IDX (DT_NUM + OS_NUM) +#define DT_MIPS_LOCAL_GOTNO_IDX (DT_NUM + OS_NUM +1) +#define DT_MIPS_SYMTABNO_IDX (DT_NUM + OS_NUM +2) +#define DT_MIPS_PLTGOT_IDX (DT_NUM + OS_NUM +3) + +#define ARCH_DYNAMIC_INFO(dpnt, dynamic, debug_addr) \ +do { \ +if (dpnt->d_tag == DT_MIPS_GOTSYM) \ + dynamic[DT_MIPS_GOTSYM_IDX] = dpnt->d_un.d_val; \ +else if (dpnt->d_tag == DT_MIPS_LOCAL_GOTNO) \ + dynamic[DT_MIPS_LOCAL_GOTNO_IDX] = dpnt->d_un.d_val; \ +else if (dpnt->d_tag == DT_MIPS_SYMTABNO) \ + dynamic[DT_MIPS_SYMTABNO_IDX] = dpnt->d_un.d_val; \ +else if (dpnt->d_tag == DT_MIPS_PLTGOT) \ + dynamic[DT_MIPS_PLTGOT_IDX] = dpnt->d_un.d_val; \ +else if ((dpnt->d_tag == DT_MIPS_RLD_MAP) && (dpnt->d_un.d_ptr)) \ + *(ElfW(Addr) *)(dpnt->d_un.d_ptr) = (ElfW(Addr)) debug_addr; \ +} while (0) + +/* Initialization sequence for the application/library GOT. */ +#define INIT_GOT(GOT_BASE,MODULE) \ +do { \ + unsigned long idx; \ + unsigned long *pltgot; \ + \ + /* Check if this is the dynamic linker itself */ \ + if (MODULE->libtype == program_interpreter) \ + continue; \ + \ + /* Fill in first two GOT entries according to the ABI */ \ + GOT_BASE[0] = (unsigned long) _dl_runtime_resolve; \ + GOT_BASE[1] = (unsigned long) MODULE; \ + \ + pltgot = MODULE->dynamic_info[DT_MIPS_PLTGOT_IDX]; \ + if (pltgot) { \ + pltgot[0] = (unsigned long) _dl_runtime_pltresolve; \ + pltgot[1] = (unsigned long) MODULE; \ + } \ + \ + /* Add load address displacement to all local GOT entries */ \ + idx = 2; \ + while (idx < MODULE->dynamic_info[DT_MIPS_LOCAL_GOTNO_IDX]) \ + GOT_BASE[idx++] += (unsigned long) MODULE->loadaddr; \ + \ +} while (0) + + +/* Here we define the magic numbers that this dynamic loader should accept */ +#define MAGIC1 EM_MIPS +#define MAGIC2 EM_MIPS_RS3_LE + + +/* Used for error messages */ +#define ELF_TARGET "MIPS" + +/* Need bootstrap relocations */ +#define ARCH_NEEDS_BOOTSTRAP_RELOCS + +unsigned long __dl_runtime_resolve(unsigned long sym_index, + unsigned long old_gpreg); + +struct elf_resolve; +void _dl_perform_mips_global_got_relocations(struct elf_resolve *tpnt, int lazy); + +/* 4096 bytes alignment */ +#if _MIPS_SIM == _MIPS_SIM_ABI64 +#define OFFS_ALIGN (0x10000000000UL-0x1000) +#endif /* O32 || N32 */ + +#if defined USE_TLS +# if _MIPS_SIM == _MIPS_SIM_ABI64 +# define elf_machine_type_class(type) \ + ((((type) == R_MIPS_JUMP_SLOT || (type) == R_MIPS_TLS_DTPMOD64 \ + || (type) == R_MIPS_TLS_DTPREL64 || (type) == R_MIPS_TLS_TPREL64) \ + * ELF_RTYPE_CLASS_PLT) \ + | (((type) == R_MIPS_COPY) * ELF_RTYPE_CLASS_COPY)) +# else +# define elf_machine_type_class(type) \ + ((((type) == R_MIPS_JUMP_SLOT || (type) == R_MIPS_TLS_DTPMOD32 \ + || (type) == R_MIPS_TLS_DTPREL32 || (type) == R_MIPS_TLS_TPREL32) \ + * ELF_RTYPE_CLASS_PLT) \ + | (((type) == R_MIPS_COPY) * ELF_RTYPE_CLASS_COPY)) +# endif /* _MIPS_SIM == _MIPS_SIM_ABI64 */ +#else +#define elf_machine_type_class(type) \ + ((((type) == R_MIPS_JUMP_SLOT) * ELF_RTYPE_CLASS_PLT) \ + | (((type) == R_MIPS_COPY) * ELF_RTYPE_CLASS_COPY)) +#endif /* USE_TLS */ + +#define OFFSET_GP_GOT 0x7ff0 + +static __always_inline ElfW(Addr) * +elf_mips_got_from_gpreg (ElfW(Addr) gpreg) +{ + /* FIXME: the offset of gp from GOT may be system-dependent. */ + return (ElfW(Addr) *) (gpreg - OFFSET_GP_GOT); +} + +/* Return the link-time address of _DYNAMIC. Conveniently, this is the + first element of the GOT. This must be inlined in a function which + uses global data. We assume its $gp points to the primary GOT. */ +static __always_inline ElfW(Addr) +elf_machine_dynamic (void) +{ + register ElfW(Addr) gp __asm__ ("$28"); + return *elf_mips_got_from_gpreg (gp); +} + +#define STRINGXP(X) __STRING(X) +#define STRINGXV(X) STRINGV_(X) +#define STRINGV_(...) # __VA_ARGS__ +#if _MIPS_SIM == _MIPS_SIM_ABI64 +#define PTR_LA dla +#define PTR_SUBU dsubu +#else +#define PTR_LA la +#define PTR_SUBU subu +#endif + +/* Return the run-time load address of the shared object. */ +static __always_inline ElfW(Addr) +elf_machine_load_address (void) +{ + ElfW(Addr) addr; + __asm__ (" .set noreorder\n" + " " STRINGXP (PTR_LA) " %0, 0f\n" + " bltzal $0, 0f\n" + " nop\n" + "0: " STRINGXP (PTR_SUBU) " %0, $31, %0\n" + " .set reorder\n" + : "=r" (addr) + : /* No inputs */ + : "$31"); + return addr; +} + +static __always_inline void +elf_machine_relative (ElfW(Addr) load_off, const ElfW(Addr) rel_addr, + ElfW(Word) relative_count) +{ + /* No RELATIVE relocs in MIPS? */ +} + +#ifdef __mips64 +#define DL_MALLOC_ALIGN 8 /* N64/N32 needs 8 byte alignment */ +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/mips/elfinterp.c b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/mips/elfinterp.c new file mode 100644 index 00000000..2886f333 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/mips/elfinterp.c @@ -0,0 +1,390 @@ +/* vi: set sw=4 ts=4: */ +/* mips/mipsel ELF shared library loader suppport + * + Copyright (C) 2002, Steven J. Hill (sjhill@realitydiluted.com) + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. The name of the above contributors may not be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "ldso.h" + +extern int _dl_runtime_resolve(void); +extern int _dl_runtime_pltresolve(void); + +#define OFFSET_GP_GOT 0x7ff0 + +unsigned long __dl_runtime_resolve(unsigned long sym_index, + unsigned long old_gpreg) +{ + unsigned long *got = (unsigned long *) (old_gpreg - OFFSET_GP_GOT); + struct elf_resolve *tpnt = (struct elf_resolve *) got[1]; + ElfW(Sym) *sym; + char *strtab; + unsigned long local_gotno; + unsigned long gotsym; + unsigned long new_addr; + unsigned long instr_addr; + char **got_addr; + char *symname; + + gotsym = tpnt->dynamic_info[DT_MIPS_GOTSYM_IDX]; + local_gotno = tpnt->dynamic_info[DT_MIPS_LOCAL_GOTNO_IDX]; + + sym = ((ElfW(Sym) *) tpnt->dynamic_info[DT_SYMTAB]) + sym_index; + strtab = (char *) tpnt->dynamic_info[DT_STRTAB]; + symname = strtab + sym->st_name; + + new_addr = (unsigned long) _dl_find_hash(symname, + tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL); + if (unlikely(!new_addr)) { + _dl_dprintf (2, "%s: can't resolve symbol '%s'\n", + _dl_progname, symname); + _dl_exit (1); + } + + /* Address of jump instruction to fix up */ + instr_addr = (unsigned long) (got + local_gotno + sym_index - gotsym); + got_addr = (char **) instr_addr; + +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_bindings) + { + _dl_dprintf(_dl_debug_file, "\nresolve function: %s", symname); + if (_dl_debug_detail) _dl_dprintf(_dl_debug_file, + "\n\tpatched %x ==> %x @ %x\n", *got_addr, new_addr, got_addr); + } + if (!_dl_debug_nofixups) { + *got_addr = (char*)new_addr; + } +#else + *got_addr = (char*)new_addr; +#endif + + return new_addr; +} + +unsigned long +__dl_runtime_pltresolve(struct elf_resolve *tpnt, int reloc_entry) +{ + ELF_RELOC *this_reloc; + char *strtab; + Elf32_Sym *symtab; + int symtab_index; + char *rel_addr; + char *new_addr; + char **got_addr; + unsigned long instr_addr; + char *symname; + + rel_addr = (char *)tpnt->dynamic_info[DT_JMPREL]; + this_reloc = (ELF_RELOC *)(intptr_t)(rel_addr + reloc_entry); + symtab_index = ELF32_R_SYM(this_reloc->r_info); + + symtab = (Elf32_Sym *)(intptr_t)tpnt->dynamic_info[DT_SYMTAB]; + strtab = (char *)tpnt->dynamic_info[DT_STRTAB]; + symname = strtab + symtab[symtab_index].st_name; + + /* Address of the jump instruction to fix up. */ + instr_addr = ((unsigned long)this_reloc->r_offset + + (unsigned long)tpnt->loadaddr); + got_addr = (char **)instr_addr; + + /* Get the address of the GOT entry. */ + new_addr = _dl_find_hash(symname, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL); + if (unlikely(!new_addr)) { + _dl_dprintf(2, "%s: can't resolve symbol '%s' in lib '%s'.\n", _dl_progname, symname, tpnt->libname); + _dl_exit(1); + } + +#if defined (__SUPPORT_LD_DEBUG__) + if ((unsigned long)got_addr < 0x40000000) { + if (_dl_debug_bindings) { + _dl_dprintf(_dl_debug_file, "\nresolve function: %s", symname); + if (_dl_debug_detail) + _dl_dprintf(_dl_debug_file, + "\n\tpatched: %x ==> %x @ %x", + *got_addr, new_addr, got_addr); + } + } + if (!_dl_debug_nofixups) { + *got_addr = new_addr; + } +#else + *got_addr = new_addr; +#endif + + return (unsigned long)new_addr; +} + +void _dl_parse_lazy_relocation_information(struct dyn_elf *rpnt, + unsigned long rel_addr, unsigned long rel_size) +{ + /* Nothing to do */ + return; +} + +int _dl_parse_relocation_information(struct dyn_elf *xpnt, + unsigned long rel_addr, unsigned long rel_size) +{ + ElfW(Sym) *symtab; + ELF_RELOC *rpnt; + char *strtab; + unsigned long i; + unsigned long *got; + unsigned long *reloc_addr=NULL; + unsigned long symbol_addr; + int reloc_type, symtab_index; + struct elf_resolve *tpnt = xpnt->dyn; + char *symname = NULL; +#if defined (__SUPPORT_LD_DEBUG__) + unsigned long old_val=0; +#endif + + /* Now parse the relocation information */ + rel_size = rel_size / sizeof(ElfW(Rel)); + rpnt = (ELF_RELOC *) rel_addr; + + symtab = (ElfW(Sym) *) tpnt->dynamic_info[DT_SYMTAB]; + strtab = (char *) tpnt->dynamic_info[DT_STRTAB]; + got = (unsigned long *) tpnt->dynamic_info[DT_PLTGOT]; + + for (i = 0; i < rel_size; i++, rpnt++) { + reloc_addr = (unsigned long *) (tpnt->loadaddr + + (unsigned long) rpnt->r_offset); + reloc_type = ELF_R_TYPE(rpnt->r_info); + symtab_index = ELF_R_SYM(rpnt->r_info); + symbol_addr = 0; + + debug_sym(symtab,strtab,symtab_index); + debug_reloc(symtab,strtab,rpnt); + symname = strtab + symtab[symtab_index].st_name; +#if defined (__SUPPORT_LD_DEBUG__) + if (reloc_addr) + old_val = *reloc_addr; +#endif + + if (reloc_type == R_MIPS_JUMP_SLOT || reloc_type == R_MIPS_COPY) { + symbol_addr = (unsigned long)_dl_find_hash(symname, + tpnt->symbol_scope, + tpnt, + elf_machine_type_class(reloc_type), NULL); + if (unlikely(!symbol_addr && ELF32_ST_BIND(symtab[symtab_index].st_info) != STB_WEAK)) + return 1; + } + if (!symtab_index) { + /* Relocs against STN_UNDEF are usually treated as using a + * symbol value of zero, and using the module containing the + * reloc itself. + */ + symbol_addr = symtab[symtab_index].st_value; + } + + switch (reloc_type) { +#if defined USE_TLS && USE_TLS +# if _MIPS_SIM == _MIPS_SIM_ABI64 + case R_MIPS_TLS_DTPMOD64: + case R_MIPS_TLS_DTPREL64: + case R_MIPS_TLS_TPREL64: +# else + case R_MIPS_TLS_DTPMOD32: + case R_MIPS_TLS_DTPREL32: + case R_MIPS_TLS_TPREL32: +# endif + { + struct elf_resolve *tls_tpnt = NULL; + struct symbol_ref sym_ref; + sym_ref.sym = &symtab[symtab_index]; + sym_ref.tpnt = NULL; + + if (ELF32_ST_BIND(symtab[symtab_index].st_info) != STB_LOCAL) { + symbol_addr = (unsigned long) _dl_find_hash(symname, tpnt->symbol_scope, + tpnt, elf_machine_type_class(reloc_type), &sym_ref); + tls_tpnt = sym_ref.tpnt; + } + /* In case of a TLS reloc, tls_tpnt NULL means we have an 'anonymous' + symbol. This is the case for a static tls variable, so the lookup + module is just that one is referencing the tls variable. */ + if (!tls_tpnt) + tls_tpnt = tpnt; + + switch (reloc_type) { + case R_MIPS_TLS_DTPMOD64: + case R_MIPS_TLS_DTPMOD32: + if (tls_tpnt) + *(ElfW(Word) *)reloc_addr = tls_tpnt->l_tls_modid; +#ifdef __SUPPORT_LD_DEBUG__ + _dl_dprintf(2, "TLS_DTPMOD : %s, %d, %d\n", + symname, old_val, *((unsigned int *)reloc_addr)); +#endif + break; + + case R_MIPS_TLS_DTPREL64: + case R_MIPS_TLS_DTPREL32: + *(ElfW(Word) *)reloc_addr += + TLS_DTPREL_VALUE (symbol_addr); +#ifdef __SUPPORT_LD_DEBUG__ + _dl_dprintf(2, "TLS_DTPREL : %s, %x, %x\n", + symname, old_val, *((unsigned int *)reloc_addr)); +#endif + break; + + case R_MIPS_TLS_TPREL32: + case R_MIPS_TLS_TPREL64: + CHECK_STATIC_TLS((struct link_map *)tls_tpnt); + *(ElfW(Word) *)reloc_addr += + TLS_TPREL_VALUE (tls_tpnt, symbol_addr); +#ifdef __SUPPORT_LD_DEBUG__ + _dl_dprintf(2, "TLS_TPREL : %s, %x, %x\n", + symname, old_val, *((unsigned int *)reloc_addr)); +#endif + break; + } + + break; + } +#endif /* USE_TLS */ +#if _MIPS_SIM == _MIPS_SIM_ABI64 + case (R_MIPS_64 << 8) | R_MIPS_REL32: +#else /* O32 || N32 */ + case R_MIPS_REL32: +#endif /* O32 || N32 */ + if (symtab_index) { + if (symtab_index < tpnt->dynamic_info[DT_MIPS_GOTSYM_IDX]) + *reloc_addr += + symtab[symtab_index].st_value + + (unsigned long) tpnt->loadaddr; + else { + *reloc_addr += got[symtab_index + tpnt->dynamic_info[DT_MIPS_LOCAL_GOTNO_IDX] - + tpnt->dynamic_info[DT_MIPS_GOTSYM_IDX]]; + } + } + else { + *reloc_addr += (unsigned long) tpnt->loadaddr; + } + break; + case R_MIPS_JUMP_SLOT: + *reloc_addr = symbol_addr; + break; + case R_MIPS_COPY: + if (symbol_addr) { +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_move) + _dl_dprintf(_dl_debug_file, + "\n%s move %d bytes from %x to %x", + symname, symtab[symtab_index].st_size, + symbol_addr, reloc_addr); +#endif + + _dl_memcpy((char *)reloc_addr, + (char *)symbol_addr, + symtab[symtab_index].st_size); + } + break; + case R_MIPS_NONE: + break; + default: + { + _dl_dprintf(2, "\n%s: ",_dl_progname); + + if (symtab_index) + _dl_dprintf(2, "symbol '%s': ", symname); + +#if defined (__SUPPORT_LD_DEBUG__) + _dl_dprintf(2, "can't handle reloc type '%s' in lib '%s'\n", _dl_reltypes(reloc_type), tpnt->libname); +#else + _dl_dprintf(2, "can't handle reloc type %x in lib '%s'\n", reloc_type, tpnt->libname); +#endif + _dl_exit(1); + } + } + + } +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_reloc && _dl_debug_detail && reloc_addr) + _dl_dprintf(_dl_debug_file, "\tpatched: %x ==> %x @ %x\n", old_val, *reloc_addr, reloc_addr); +#endif + + return 0; +} + +/* Relocate the global GOT entries for the object */ +void _dl_perform_mips_global_got_relocations(struct elf_resolve *tpnt, int lazy) +{ + ElfW(Sym) *sym; + char *strtab; + unsigned long i, tmp_lazy; + unsigned long *got_entry; + + for (; tpnt ; tpnt = tpnt->next) { + + /* We don't touch the dynamic linker */ + if (tpnt->libtype == program_interpreter) + continue; + + /* Setup the loop variables */ + got_entry = (unsigned long *) (tpnt->dynamic_info[DT_PLTGOT]) + + tpnt->dynamic_info[DT_MIPS_LOCAL_GOTNO_IDX]; + sym = (ElfW(Sym) *) tpnt->dynamic_info[DT_SYMTAB] + tpnt->dynamic_info[DT_MIPS_GOTSYM_IDX]; + strtab = (char *) tpnt->dynamic_info[DT_STRTAB]; + i = tpnt->dynamic_info[DT_MIPS_SYMTABNO_IDX] - tpnt->dynamic_info[DT_MIPS_GOTSYM_IDX]; + +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_reloc) + _dl_dprintf(2, "_dl_perform_mips_global_got_relocations for '%s'\n", tpnt->libname); +#endif + tmp_lazy = lazy && !tpnt->dynamic_info[DT_BIND_NOW]; + /* Relocate the global GOT entries for the object */ + while (i--) { + if (sym->st_shndx == SHN_UNDEF) { + if (ELF_ST_TYPE(sym->st_info) == STT_FUNC && sym->st_value && tmp_lazy) { + *got_entry = sym->st_value + (unsigned long) tpnt->loadaddr; + } + else { + *got_entry = (unsigned long) _dl_find_hash(strtab + + sym->st_name, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL); + } + } + else if (sym->st_shndx == SHN_COMMON) { + *got_entry = (unsigned long) _dl_find_hash(strtab + + sym->st_name, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL); + } + else if (ELF_ST_TYPE(sym->st_info) == STT_FUNC && + *got_entry != sym->st_value && tmp_lazy) { + *got_entry += (unsigned long) tpnt->loadaddr; + } + else if (ELF_ST_TYPE(sym->st_info) == STT_SECTION) { + if (sym->st_other == 0) + *got_entry += (unsigned long) tpnt->loadaddr; + } + else { + *got_entry = (unsigned long) _dl_find_hash(strtab + + sym->st_name, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL); + } + + got_entry++; + sym++; + } + } +} + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/mips/resolve.S b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/mips/resolve.S new file mode 100644 index 00000000..d7951a1b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/mips/resolve.S @@ -0,0 +1,165 @@ +/* + * Linux dynamic resolving code for MIPS. Fixes up the GOT entry as + * indicated in register t8 and jumps to the resolved address. Shamelessly + * ripped from 'sysdeps/mips/dl-machine.h' in glibc-2.2.5. + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License. See the file "COPYING.LIB" in the main directory of this + * archive for more details. + * + * Copyright (C) 1996-2001 Kazumoto Kojima + * Copyright (C) 2002 Steven J. Hill + * + */ + +#include +.text +.align 2 +.globl _dl_runtime_resolve +.type _dl_runtime_resolve,@function +.ent _dl_runtime_resolve +_dl_runtime_resolve: +#if _MIPS_SIM == _MIPS_SIM_ABI32 + .frame $29, 40, $31 + .set noreorder + + /* Save GP. */ + move $3, $28 + + /* Save arguments and sp value on stack. */ + subu $29, 40 + + /* Modify t9 ($25) so as to point .cpload instruction. */ + addiu $25, 12 + + /* Compute GP. */ + .set noreorder + .cpload $25 + .set reorder + + /* Save slot call pc. */ + move $2, $31 + .cprestore 32 + + /* Store function arguments from registers to stack */ + sw $15, 36($29) + sw $4, 16($29) + sw $5, 20($29) + sw $6, 24($29) + sw $7, 28($29) + + /* Setup functions args and call __dl_runtime_resolve */ + move $4, $24 + move $5, $3 + jal __dl_runtime_resolve + + /* Restore function arguments from stack to registers */ + lw $31, 36($29) + lw $4, 16($29) + lw $5, 20($29) + lw $6, 24($29) + lw $7, 28($29) + + /* Do a tail call to the original function */ + addiu $29, 40 +#else /* N32 || N64 */ + .set noreorder + + /* Save GP. */ + move $3, $28 + + /* Save arguments and sp value on stack. */ + dsubu $29, 80 + + /* Compute GP. */ + .set noreorder + .cpsetup $25, 0, _dl_runtime_resolve + .set reorder + + /* Store function arguments from registers to stack */ + sd $15, 72($29) + sd $4, 8($29) + sd $5, 16($29) + sd $6, 24($29) + sd $7, 32($29) + sd $8, 40($29) + sd $9, 48($29) + sd $10, 56($29) + sd $11, 64($29) + + /* Setup functions args and call __dl_runtime_resolve */ + move $4, $24 + move $5, $3 + jal __dl_runtime_resolve + + /* Restore function arguments from stack to registers */ + ld $31, 72($29) + ld $4, 8($29) + ld $5, 16($29) + ld $6, 24($29) + ld $7, 32($29) + ld $8, 40($29) + ld $9, 48($29) + ld $10, 56($29) + ld $11, 64($29) + + /* Do a tail call to the original function */ + .cpreturn + daddu $29, 80 +#endif /* N32 || N64 */ + move $25, $2 + jr $25 +.end _dl_runtime_resolve +.previous + +/* Assembler veneer called from the PLT header code when using the + non-PIC ABI. + + Code in each PLT entry puts the caller's return address into t7 ($15), + the PLT entry index into t8 ($24), the address of _dl_runtime_pltresolve + into t9 ($25) and the address of .got.plt into gp ($28). __dl_runtime_pltresolve + needs a0 ($4) to hold the link map and a1 ($5) to hold the index into + .rel.plt (== PLT entry index * 4). */ + + .text + .align 2 + .globl _dl_runtime_pltresolve + .type _dl_runtime_pltresolve,@function + .ent _dl_runtime_pltresolve +_dl_runtime_pltresolve: + .frame $29, 40, $31 + .set noreorder + # Save arguments and sp value in stack. + subu $29, 40 + lw $10, 4($28) + # Modify t9 ($25) so as to point .cpload instruction. + addiu $25, 12 + # Compute GP. + .cpload $25 + .set reorder + + /* Store function arguments from registers to stack */ + sw $15, 36($29) + sw $4, 16($29) + sw $5, 20($29) + sw $6, 24($29) + sw $7, 28($29) + + /* Setup functions args and call __dl_runtime_pltresolve. */ + move $4, $10 + sll $5, $24, 3 + jal __dl_runtime_pltresolve + + /* Restore function arguments from stack to registers */ + lw $31, 36($29) + lw $4, 16($29) + lw $5, 20($29) + lw $6, 24($29) + lw $7, 28($29) + + /* Do a tail call to the original function */ + addiu $29, 40 + move $25, $2 + jr $25 + .end _dl_runtime_pltresolve + .previous diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/powerpc/dl-debug.h b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/powerpc/dl-debug.h new file mode 100644 index 00000000..cf203d25 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/powerpc/dl-debug.h @@ -0,0 +1,44 @@ +/* vi: set sw=4 ts=4: */ +/* powerpc shared library loader suppport + * + * Copyright (C) 2001-2002 David A. Schleef + * Copyright (C) 2003-2004 Erik Andersen + * Copyright (C) 2004 Joakim Tjernlund + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. The name of the above contributors may not be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +static const char *_dl_reltypes_tab[] = + { "R_PPC_NONE", "R_PPC_ADDR32", "R_PPC_ADDR24", "R_PPC_ADDR16", + "R_PPC_ADDR16_LO", "R_PPC_ADDR16_HI", "R_PPC_ADDR16_HA", + "R_PPC_ADDR14", "R_PPC_ADDR14_BRTAKEN", "R_PPC_ADDR14_BRNTAKEN", + "R_PPC_REL24", "R_PPC_REL14", "R_PPC_REL14_BRTAKEN", + "R_PPC_REL14_BRNTAKEN", "R_PPC_GOT16", "R_PPC_GOT16_LO", + "R_PPC_GOT16_HI", "R_PPC_GOT16_HA", "R_PPC_PLTREL24", + "R_PPC_COPY", "R_PPC_GLOB_DAT", "R_PPC_JMP_SLOT", "R_PPC_RELATIVE", + "R_PPC_LOCAL24PC", "R_PPC_UADDR32", "R_PPC_UADDR16", "R_PPC_REL32", + "R_PPC_PLT32", "R_PPC_PLTREL32", "R_PPC_PLT16_LO", "R_PPC_PLT16_HI", + "R_PPC_PLT16_HA", "R_PPC_SDAREL16", "R_PPC_SECTOFF", + "R_PPC_SECTOFF_LO", "R_PPC_SECTOFF_HI", "R_PPC_SECTOFF_HA", +}; diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/powerpc/dl-startup.h b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/powerpc/dl-startup.h new file mode 100644 index 00000000..e471aa03 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/powerpc/dl-startup.h @@ -0,0 +1,89 @@ +/* Any assembly language/system dependent hacks needed to setup boot1.c so it + * will work as expected and cope with whatever platform specific wierdness is + * needed for this architecture. + * Copyright (C) 2005 by Joakim Tjernlund + */ + +__asm__( + " .text\n" + " .globl _start\n" + " .type _start,@function\n" + "_start:\n" + " mr 3,1\n" /* Pass SP to _dl_start in r3 */ + " li 0,0\n" + " stwu 1,-16(1)\n" /* Make room on stack for _dl_start to store LR */ + " stw 0,0(1)\n" /* Clear Stack frame */ + " bl _dl_start@local\n" /* Perform relocation */ + /* Save the address of the apps entry point in CTR register */ + " mtctr 3\n" /* application entry point */ +#ifdef HAVE_ASM_PPC_REL16 + " bcl 20,31,1f\n" + "1: mflr 31\n" + " addis 31,31,_GLOBAL_OFFSET_TABLE_-1b@ha\n" + " addi 31,31,_GLOBAL_OFFSET_TABLE_-1b@l\n" +#else + " bl _GLOBAL_OFFSET_TABLE_-4@local\n" /* Put our GOT pointer in r31, */ + " mflr 31\n" +#endif + " addi 1,1,16\n" /* Restore SP */ + " lwz 7,_dl_skip_args@got(31)\n" /* load EA of _dl_skip_args */ + " lwz 7,0(7)\n" /* Load word from _dl_skip_args */ + " lwz 8,0(1)\n" /* Load argc from stack */ + " subf 8,7,8\n" /* Subtract _dl_skip_args from argc. */ + " slwi 7,7,2\n" /* Multiply by 4 */ + " stwux 8,1,7\n" /* Adjust the stack pointer to skip _dl_skip_args words and store adjusted argc on stack. */ +#if 0 + /* Try beeing SVR4 ABI compliant?, even though it is not needed for uClibc on Linux */ + /* argc */ + " lwz 3,0(1)\n" + /* find argv one word offset from the stack pointer */ + " addi 4,1,4\n" + /* find environment pointer (argv+argc+1) */ + " lwz 5,0(1)\n" + " addi 5,5,1\n" + " rlwinm 5,5,2,0,29\n" + " add 5,5,4\n" + /* pass the auxilary vector in r6. This is passed to us just after _envp. */ + "2: lwzu 0,4(6)\n" + " cmpwi 0,0\n" + " bne 2b\n" + " addi 6,6,4\n" +#endif + /* Pass a termination function pointer (in this case _dl_fini) in r3. */ + /* Paulus promized he would keep r3 zero in the exec ABI. */ + " lwz 3,_dl_fini@got(31)\n" + " mr 7,3\n" /* Pass _dl_fini in r7 to maintain compat */ + " bctr\n" /* Jump to entry point */ + " .size _start,.-_start\n" + " .previous\n" +); + +/* + * Get a pointer to the argv array. On many platforms this can be just + * the address of the first argument, on other platforms we need to + * do something a little more subtle here. + */ +#define GET_ARGV(ARGVP, ARGS) ARGVP = (((unsigned long*) ARGS)+1) + +/* + * Here is a macro to perform a relocation. This is only used when + * bootstrapping the dynamic loader. RELP is the relocation that we + * are performing, REL is the pointer to the address we are relocating. + * SYMBOL is the symbol involved in the relocation, and LOAD is the + * load address. + */ +#define PERFORM_BOOTSTRAP_RELOC(RELP,REL,SYMBOL,LOAD,SYMTAB) \ + {int type=ELF32_R_TYPE((RELP)->r_info); \ + Elf32_Addr finaladdr=(SYMBOL)+(RELP)->r_addend;\ + if (type==R_PPC_RELATIVE) { \ + *REL=(Elf32_Word)(LOAD)+(RELP)->r_addend;\ + } else if (type==R_PPC_ADDR32 || type==R_PPC_GLOB_DAT) {\ + *REL=finaladdr; \ + } else if (type==R_PPC_JMP_SLOT) { \ + Elf32_Sword delta=finaladdr-(Elf32_Word)(REL);\ + *REL=OPCODE_B(delta); \ + PPC_DCBST(REL); PPC_SYNC; PPC_ICBI(REL);\ + } else { \ + _dl_exit(100+ELF32_R_TYPE((RELP)->r_info));\ + } \ + } diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/powerpc/dl-syscalls.h b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/powerpc/dl-syscalls.h new file mode 100644 index 00000000..996bb87c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/powerpc/dl-syscalls.h @@ -0,0 +1,6 @@ +/* We can't use the real errno in ldso, since it has not yet + * been dynamicly linked in yet. */ +#include "sys/syscall.h" +extern int _dl_errno; +#undef __set_errno +#define __set_errno(X) {(_dl_errno) = (X);} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/powerpc/dl-sysdep.h b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/powerpc/dl-sysdep.h new file mode 100644 index 00000000..a665d4e7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/powerpc/dl-sysdep.h @@ -0,0 +1,184 @@ +/* + * Various assembly language/system dependent hacks that are required + * so that we can minimize the amount of platform specific code. + */ + +/* + * Define this if the system uses RELOCA. + */ +#define ELF_USES_RELOCA +#include +/* + * Initialization sequence for a GOT. + */ +#define INIT_GOT(GOT_BASE,MODULE) _dl_init_got(GOT_BASE,MODULE) + +/* Stuff for the PLT. */ +#define PLT_INITIAL_ENTRY_WORDS 18 +#define PLT_LONGBRANCH_ENTRY_WORDS 0 +#define PLT_TRAMPOLINE_ENTRY_WORDS 6 +#define PLT_DOUBLE_SIZE (1<<13) +#define PLT_ENTRY_START_WORDS(entry_number) \ + (PLT_INITIAL_ENTRY_WORDS + (entry_number)*2 \ + + ((entry_number) > PLT_DOUBLE_SIZE \ + ? ((entry_number) - PLT_DOUBLE_SIZE)*2 \ + : 0)) +#define PLT_DATA_START_WORDS(num_entries) PLT_ENTRY_START_WORDS(num_entries) + +/* Macros to build PowerPC opcode words. */ +#define OPCODE_ADDI(rd,ra,simm) \ + (0x38000000 | (rd) << 21 | (ra) << 16 | ((simm) & 0xffff)) +#define OPCODE_ADDIS(rd,ra,simm) \ + (0x3c000000 | (rd) << 21 | (ra) << 16 | ((simm) & 0xffff)) +#define OPCODE_ADD(rd,ra,rb) \ + (0x7c000214 | (rd) << 21 | (ra) << 16 | (rb) << 11) +#define OPCODE_B(target) (0x48000000 | ((target) & 0x03fffffc)) +#define OPCODE_BA(target) (0x48000002 | ((target) & 0x03fffffc)) +#define OPCODE_BCTR() 0x4e800420 +#define OPCODE_LWZ(rd,d,ra) \ + (0x80000000 | (rd) << 21 | (ra) << 16 | ((d) & 0xffff)) +#define OPCODE_LWZU(rd,d,ra) \ + (0x84000000 | (rd) << 21 | (ra) << 16 | ((d) & 0xffff)) +#define OPCODE_MTCTR(rd) (0x7C0903A6 | (rd) << 21) +#define OPCODE_RLWINM(ra,rs,sh,mb,me) \ + (0x54000000 | (rs) << 21 | (ra) << 16 | (sh) << 11 | (mb) << 6 | (me) << 1) + +#define OPCODE_LI(rd,simm) OPCODE_ADDI(rd,0,simm) +#define OPCODE_ADDIS_HI(rd,ra,value) \ + OPCODE_ADDIS(rd,ra,((value) + 0x8000) >> 16) +#define OPCODE_LIS_HI(rd,value) OPCODE_ADDIS_HI(rd,0,value) +#define OPCODE_SLWI(ra,rs,sh) OPCODE_RLWINM(ra,rs,sh,0,31-sh) + + +#define PPC_DCBST(where) __asm__ __volatile__ ("dcbst 0,%0" : : "r"(where) : "memory") +#define PPC_SYNC __asm__ __volatile__ ("sync" : : : "memory") +#define PPC_ISYNC __asm__ __volatile__ ("sync; isync" : : : "memory") +#define PPC_ICBI(where) __asm__ __volatile__ ("icbi 0,%0" : : "r"(where) : "memory") +#define PPC_DIE __asm__ __volatile__ ("tweq 0,0") + +/* Here we define the magic numbers that this dynamic loader should accept */ + +#define MAGIC1 EM_PPC +#undef MAGIC2 +/* Used for error messages */ +#define ELF_TARGET "powerpc" + +struct elf_resolve; +extern unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_entry); +void _dl_init_got(unsigned long *lpnt,struct elf_resolve *tpnt); + +/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry, so + PLT entries should not be allowed to define the value. + ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to one + of the main executable's symbols, as for a COPY reloc. */ +/* We never want to use a PLT entry as the destination of a + reloc, when what is being relocated is a branch. This is + partly for efficiency, but mostly so we avoid loops. */ +#define elf_machine_type_class(type) \ + ((((type) == R_PPC_JMP_SLOT \ + || (type) == R_PPC_REL24 \ + || ((type) >= R_PPC_DTPMOD32 /* contiguous TLS */ \ + && (type) <= R_PPC_DTPREL32) \ + || (type) == R_PPC_ADDR24) * ELF_RTYPE_CLASS_PLT) \ + | (((type) == R_PPC_COPY) * ELF_RTYPE_CLASS_COPY)) + +/* The SVR4 ABI specifies that the JMPREL relocs must be inside the + DT_RELA table. */ +#define ELF_MACHINE_PLTREL_OVERLAP 1 + +/* Return the value of the GOT pointer. */ +static __always_inline Elf32_Addr * __attribute__ ((const)) +ppc_got (void) +{ + Elf32_Addr *got; +#ifdef HAVE_ASM_PPC_REL16 + __asm__ (" bcl 20,31,1f\n" + "1:mflr %0\n" + " addis %0,%0,_GLOBAL_OFFSET_TABLE_-1b@ha\n" + " addi %0,%0,_GLOBAL_OFFSET_TABLE_-1b@l\n" + : "=b" (got) : : "lr"); +#else + __asm__ (" bl _GLOBAL_OFFSET_TABLE_-4@local" + : "=l" (got)); +#endif + return got; +} + +/* Return the link-time address of _DYNAMIC, stored as + the first value in the GOT. */ +static __always_inline Elf32_Addr __attribute__ ((const)) +elf_machine_dynamic (void) +{ + return *ppc_got(); +} + +/* Return the run-time load address of the shared object. */ +static __always_inline Elf32_Addr __attribute__ ((const)) +elf_machine_load_address (void) +{ + Elf32_Addr *branchaddr; + Elf32_Addr runtime_dynamic; + + /* This is much harder than you'd expect. Possibly I'm missing something. + The 'obvious' way: + + Apparently, "bcl 20,31,$+4" is what should be used to load LR + with the address of the next instruction. + I think this is so that machines that do bl/blr pairing don't + get confused. + + __asm__ ("bcl 20,31,0f ;" + "0: mflr 0 ;" + "lis %0,0b@ha;" + "addi %0,%0,0b@l;" + "subf %0,%0,0" + : "=b" (addr) : : "r0", "lr"); + + doesn't work, because the linker doesn't have to (and in fact doesn't) + update the @ha and @l references; the loader (which runs after this + code) will do that. + + Instead, we use the following trick: + + The linker puts the _link-time_ address of _DYNAMIC at the first + word in the GOT. We could branch to that address, if we wanted, + by using an @local reloc; the linker works this out, so it's safe + to use now. We can't, of course, actually branch there, because + we'd cause an illegal instruction exception; so we need to compute + the address ourselves. That gives us the following code: */ + + /* Get address of the 'b _DYNAMIC@local'... */ + __asm__ ("bcl 20,31,0f;" + "b _DYNAMIC@local;" + "0:" + : "=l"(branchaddr)); + + /* So now work out the difference between where the branch actually points, + and the offset of that location in memory from the start of the file. */ + runtime_dynamic = ((Elf32_Addr) branchaddr + + ((Elf32_Sword) (*branchaddr << 6 & 0xffffff00) >> 6)); + + return runtime_dynamic - elf_machine_dynamic (); +} + +static __always_inline void +elf_machine_relative (Elf32_Addr load_off, const Elf32_Addr rel_addr, + Elf32_Word relative_count) +{ + Elf32_Rela * rpnt = (void *)rel_addr; + --rpnt; + do { /* PowerPC handles pre increment/decrement better */ + Elf32_Addr *const reloc_addr = (void *) (load_off + (++rpnt)->r_offset); + + *reloc_addr = load_off + rpnt->r_addend; + } while (--relative_count); +} + +#define ARCH_NUM 1 +#define DT_PPC_GOT_IDX (DT_NUM + OS_NUM) + +#define ARCH_DYNAMIC_INFO(dpnt, dynamic, debug_addr) \ +do { \ +if (dpnt->d_tag == DT_PPC_GOT) \ + dynamic[DT_PPC_GOT_IDX] = dpnt->d_un.d_ptr; \ +} while (0) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/powerpc/elfinterp.c b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/powerpc/elfinterp.c new file mode 100644 index 00000000..dd35eef5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/powerpc/elfinterp.c @@ -0,0 +1,448 @@ +/* vi: set sw=4 ts=4: */ +/* powerpc shared library loader suppport + * + * Copyright (C) 2001-2002 David A. Schleef + * Copyright (C) 2003-2004 Erik Andersen + * Copyright (C) 2004 Joakim Tjernlund + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. The name of the above contributors may not be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "ldso.h" +#define TLS_DTV_OFFSET 0x8000 +#define TLS_TP_OFFSET 0x7000 + +extern int _dl_linux_resolve(void); + +void _dl_init_got(unsigned long *plt,struct elf_resolve *tpnt) +{ + Elf32_Word *tramp; + Elf32_Word num_plt_entries; + Elf32_Word data_words; + Elf32_Word rel_offset_words; + Elf32_Word dlrr = (Elf32_Word) _dl_linux_resolve; + + if (tpnt->dynamic_info[DT_JMPREL] == 0) + return; + if (tpnt->dynamic_info[DT_PPC_GOT_IDX] != 0) { + tpnt->dynamic_info[DT_PPC_GOT_IDX] += tpnt->loadaddr; + return; + } + num_plt_entries = tpnt->dynamic_info[DT_PLTRELSZ] / sizeof(ELF_RELOC); + rel_offset_words = PLT_DATA_START_WORDS(num_plt_entries); + data_words = (Elf32_Word) (plt + rel_offset_words); + tpnt->data_words = data_words; + + plt[PLT_LONGBRANCH_ENTRY_WORDS] = OPCODE_ADDIS_HI(11, 11, data_words); + plt[PLT_LONGBRANCH_ENTRY_WORDS+1] = OPCODE_LWZ(11,data_words,11); + + plt[PLT_LONGBRANCH_ENTRY_WORDS+2] = OPCODE_MTCTR(11); + plt[PLT_LONGBRANCH_ENTRY_WORDS+3] = OPCODE_BCTR(); + + /* [4] */ + /* [5] */ + tramp = (Elf32_Word *) (plt + PLT_TRAMPOLINE_ENTRY_WORDS); + + /* For the long entries, subtract off data_words. */ + tramp[0] = OPCODE_ADDIS_HI(11,11,-data_words); + tramp[1] = OPCODE_ADDI(11,11,-data_words); + + /* Multiply index of entry by 3 (in r11). */ + tramp[2] = OPCODE_SLWI(12,11,1); + tramp[3] = OPCODE_ADD(11,12,11); + if (dlrr <= 0x01fffffc || dlrr >= 0xfe000000) { + /* Load address of link map in r12. */ + tramp[4] = OPCODE_LI (12, (Elf32_Word) tpnt); + tramp[5] = OPCODE_ADDIS_HI (12, 12, (Elf32_Word) tpnt); + + /* Call _dl_linux_resolve . */ + tramp[6] = OPCODE_BA (dlrr); + } else { + /* Get address of _dl_linux_resolve in CTR. */ + tramp[4] = OPCODE_LI(12,dlrr); + tramp[5] = OPCODE_ADDIS_HI(12,12,dlrr); + tramp[6] = OPCODE_MTCTR(12); + + /* Load address of link map in r12. */ + tramp[7] = OPCODE_LI(12,(Elf32_Word) tpnt); + tramp[8] = OPCODE_ADDIS_HI(12,12,(Elf32_Word) tpnt); + + /* Call _dl_linux_resolve. */ + tramp[9] = OPCODE_BCTR(); + } + /* [16] unused */ + /* [17] unused */ + + PPC_DCBST(plt); + PPC_DCBST(plt+4); + PPC_DCBST(plt+8); + PPC_DCBST(plt+12); + PPC_DCBST(plt+16-1); + PPC_SYNC; + PPC_ICBI(plt); + PPC_ICBI(plt+16-1); + PPC_ISYNC; +} + +unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry) +{ + ELF_RELOC *this_reloc; + char *strtab; + Elf32_Sym *symtab; + ELF_RELOC *rel_addr; + int symtab_index; + char *symname; + Elf32_Addr *reloc_addr; + Elf32_Addr finaladdr; + Elf32_Sword delta; + + rel_addr = (ELF_RELOC *)tpnt->dynamic_info[DT_JMPREL]; + + this_reloc = (void *)rel_addr + reloc_entry; + symtab_index = ELF32_R_SYM(this_reloc->r_info); + + symtab = (Elf32_Sym *)tpnt->dynamic_info[DT_SYMTAB]; + strtab = (char *)tpnt->dynamic_info[DT_STRTAB]; + symname = strtab + symtab[symtab_index].st_name; + + debug_sym(symtab,strtab,symtab_index); + debug_reloc(symtab,strtab,this_reloc); + + /* Address of dump instruction to fix up */ + reloc_addr = (Elf32_Addr *) (tpnt->loadaddr + this_reloc->r_offset); + +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_reloc && _dl_debug_detail) + _dl_dprintf(_dl_debug_file, "\n\tResolving symbol %s %x --> ", symname, (Elf32_Addr)reloc_addr); +#endif + + /* Get the address of the GOT entry */ + finaladdr = (Elf32_Addr) _dl_find_hash(symname, + tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL); + if (unlikely(!finaladdr)) { + _dl_dprintf(2, "%s: can't resolve symbol '%s' in lib '%s'.\n", _dl_progname, symname, tpnt->libname); + _dl_exit(1); + } + finaladdr += this_reloc->r_addend; +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_reloc && _dl_debug_detail) + _dl_dprintf(_dl_debug_file, "%x\n", finaladdr); +#endif + if (tpnt->dynamic_info[DT_PPC_GOT_IDX] != 0) { + *reloc_addr = finaladdr; + } else { + delta = finaladdr - (Elf32_Word)reloc_addr; + if (delta<<6>>6 == delta) { + *reloc_addr = OPCODE_B(delta); + } else if (finaladdr <= 0x01fffffc) { + *reloc_addr = OPCODE_BA (finaladdr); + } else { + /* Warning: we don't handle double-sized PLT entries */ + Elf32_Word *plt, *data_words, idx, offset; + + plt = (Elf32_Word *)tpnt->dynamic_info[DT_PLTGOT]; + offset = reloc_addr - plt; + idx = (offset - PLT_INITIAL_ENTRY_WORDS)/2; + data_words = (Elf32_Word *)tpnt->data_words; + reloc_addr += 1; + + data_words[idx] = finaladdr; + PPC_SYNC; + *reloc_addr = OPCODE_B ((PLT_LONGBRANCH_ENTRY_WORDS - (offset+1)) * 4); + } + + /* instructions were modified */ + PPC_DCBST(reloc_addr); + PPC_SYNC; + PPC_ICBI(reloc_addr); + PPC_ISYNC; + } + return finaladdr; +} + +static __inline__ int +_dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope, + ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab) +{ + int reloc_type; + int symtab_index; + struct symbol_ref sym_ref; + Elf32_Addr *reloc_addr; + Elf32_Addr finaladdr; + struct elf_resolve *tls_tpnt = NULL; + unsigned long symbol_addr; + char *symname; +#if defined (__SUPPORT_LD_DEBUG__) + unsigned long old_val; +#endif + + symbol_addr = tpnt->loadaddr; /* For R_PPC_RELATIVE */ + reloc_addr = (Elf32_Addr *)(intptr_t) (symbol_addr + (unsigned long) rpnt->r_offset); + reloc_type = ELF32_R_TYPE(rpnt->r_info); + symtab_index = ELF32_R_SYM(rpnt->r_info); + sym_ref.sym = &symtab[symtab_index]; + sym_ref.tpnt = NULL; + symname = strtab + sym_ref.sym->st_name; + if (symtab_index) { + symbol_addr = (unsigned long) _dl_find_hash(symname, scope, tpnt, + elf_machine_type_class(reloc_type), &sym_ref); + /* We want to allow undefined references to weak symbols - this might + * have been intentional. We should not be linking local symbols + * here, so all bases should be covered. + */ + if (unlikely(!symbol_addr + && (ELF32_ST_TYPE(sym_ref.sym->st_info) != STT_TLS + && ELF32_ST_BIND(sym_ref.sym->st_info) != STB_WEAK))) + return 1; + tls_tpnt = sym_ref.tpnt; + } else { + symbol_addr = sym_ref.sym->st_value; + tls_tpnt = tpnt; + } +#if defined (__SUPPORT_LD_DEBUG__) + old_val = *reloc_addr; +#endif + finaladdr = (Elf32_Addr) (symbol_addr + rpnt->r_addend); + + switch (reloc_type) { + case R_PPC_RELATIVE: + case R_PPC_ADDR32: + case R_PPC_GLOB_DAT: + *reloc_addr = finaladdr; + goto out_nocode; /* No code code modified */ + case R_PPC_JMP_SLOT: + { + if (tpnt->dynamic_info[DT_PPC_GOT_IDX] != 0) { + *reloc_addr = finaladdr; + goto out_nocode; /* No code code modified */ + } else { + Elf32_Sword delta = finaladdr - (Elf32_Word)reloc_addr; + if (delta<<6>>6 == delta) { + *reloc_addr = OPCODE_B(delta); + } else if (finaladdr <= 0x01fffffc) { + *reloc_addr = OPCODE_BA (finaladdr); + } else { + /* Warning: we don't handle double-sized PLT entries */ + Elf32_Word *plt, *data_words, idx, offset; + + plt = (Elf32_Word *)tpnt->dynamic_info[DT_PLTGOT]; + offset = reloc_addr - plt; + idx = (offset - PLT_INITIAL_ENTRY_WORDS)/2; + data_words = (Elf32_Word *)tpnt->data_words; + + data_words[idx] = finaladdr; + reloc_addr[0] = OPCODE_LI(11,idx*4); + reloc_addr[1] = OPCODE_B((PLT_LONGBRANCH_ENTRY_WORDS - (offset+1)) * 4); + + /* instructions were modified */ + PPC_DCBST(reloc_addr+1); + PPC_SYNC; + PPC_ICBI(reloc_addr+1); + } + } + break; + } + case R_PPC_COPY: +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_move) + _dl_dprintf(_dl_debug_file,"\n%s move %x bytes from %x to %x", + symname, sym_ref.sym->st_size, + symbol_addr, reloc_addr); +#endif + _dl_memcpy((char *) reloc_addr, (char *) finaladdr, sym_ref.sym->st_size); + goto out_nocode; /* No code code modified */ + case R_PPC_ADDR16_HA: + finaladdr += 0x8000; /* fall through. */ + case R_PPC_ADDR16_HI: + finaladdr >>= 16; /* fall through. */ + case R_PPC_ADDR16_LO: + *(short *)reloc_addr = finaladdr; + break; +#if USE_TLS + case R_PPC_DTPMOD32: + *reloc_addr = tls_tpnt->l_tls_modid; + break; + case R_PPC_DTPREL32: + /* During relocation all TLS symbols are defined and used. + Therefore the offset is already correct. */ + *reloc_addr = finaladdr - TLS_DTV_OFFSET; + break; + case R_PPC_TPREL32: + *reloc_addr = tls_tpnt->l_tls_offset + finaladdr - TLS_TP_OFFSET; + break; +#endif + case R_PPC_REL24: +#if 0 + { + Elf32_Sword delta = finaladdr - (Elf32_Word)reloc_addr; + if (unlikely(delta<<6>>6 != delta)) { + _dl_dprintf(2, "%s: symbol '%s' R_PPC_REL24 is out of range.\n\t" + "Compile shared libraries with -fPIC!\n", + _dl_progname, symname); + _dl_exit(1); + } + *reloc_addr = (*reloc_addr & 0xfc000003) | (delta & 0x3fffffc); + break; + } +#else + _dl_dprintf(2,"R_PPC_REL24: Compile shared libraries with -fPIC!\n"); + return -1; +#endif + case R_PPC_NONE: + goto out_nocode; /* No code code modified */ + default: + _dl_dprintf(2, "%s: can't handle reloc type ", _dl_progname); +#if defined (__SUPPORT_LD_DEBUG__) + _dl_dprintf(2, "%s ", _dl_reltypes(reloc_type)); +#endif + if (symtab_index) + _dl_dprintf(2, "'%s'\n", symname); + return -1; + } + + /* instructions were modified */ + PPC_DCBST(reloc_addr); + PPC_SYNC; + PPC_ICBI(reloc_addr); + PPC_ISYNC; + out_nocode: +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_reloc && _dl_debug_detail) + _dl_dprintf(_dl_debug_file, "\tpatched: %x ==> %x @ %x\n", old_val, *reloc_addr, reloc_addr); +#endif + return 0; +} + +void _dl_parse_lazy_relocation_information(struct dyn_elf *rpnt, + unsigned long rel_addr, unsigned long rel_size) +{ + struct elf_resolve *tpnt = rpnt->dyn; + Elf32_Word *plt, offset, i, num_plt_entries, rel_offset_words; + + num_plt_entries = rel_size / sizeof(ELF_RELOC); + plt = (Elf32_Word *)tpnt->dynamic_info[DT_PLTGOT]; + if (tpnt->dynamic_info[DT_PPC_GOT_IDX] != 0) { + /* Secure PLT */ + Elf32_Addr *got = (Elf32_Addr *)tpnt->dynamic_info[DT_PPC_GOT_IDX]; + Elf32_Word dlrr = (Elf32_Word) _dl_linux_resolve; + + got[1] = (Elf32_Addr) dlrr; + got[2] = (Elf32_Addr) tpnt; + + /* Relocate everything in .plt by the load address offset. */ + while (num_plt_entries-- != 0) + *plt++ += tpnt->loadaddr; + return; + } + + rel_offset_words = PLT_DATA_START_WORDS(num_plt_entries); + + /* Set up the lazy PLT entries. */ + offset = PLT_INITIAL_ENTRY_WORDS; + i = 0; + /* Warning: we don't handle double-sized PLT entries */ + while (i < num_plt_entries) { + plt[offset ] = OPCODE_LI(11, i * 4); + plt[offset+1] = OPCODE_B((PLT_TRAMPOLINE_ENTRY_WORDS + 2 - (offset+1)) * 4); + i++; + offset += 2; + } + /* Now, we've modified code. We need to write the changes from + the data cache to a second-level unified cache, then make + sure that stale data in the instruction cache is removed. + (In a multiprocessor system, the effect is more complex.) + Most of the PLT shouldn't be in the instruction cache, but + there may be a little overlap at the start and the end. + + Assumes that dcbst and icbi apply to lines of 16 bytes or + more. Current known line sizes are 16, 32, and 128 bytes. */ + for (i = 0; i < rel_offset_words; i += 4) + PPC_DCBST (plt + i); + PPC_DCBST (plt + rel_offset_words - 1); + PPC_SYNC; + PPC_ICBI (plt); + PPC_ICBI (plt + rel_offset_words - 1); + PPC_ISYNC; +} + +static __inline__ int +_dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope, + unsigned long rel_addr, unsigned long rel_size, + int (*reloc_fnc) (struct elf_resolve *tpnt, struct dyn_elf *scope, + ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)) +{ + unsigned int i; + char *strtab; + Elf32_Sym *symtab; + ELF_RELOC *rpnt; + int symtab_index; + + /* Now parse the relocation information */ + rpnt = (ELF_RELOC *)(intptr_t)rel_addr; + rel_size = rel_size / sizeof(ELF_RELOC); + + symtab = (Elf32_Sym *)(intptr_t)tpnt->dynamic_info[DT_SYMTAB]; + strtab = (char *)tpnt->dynamic_info[DT_STRTAB]; + + for (i = 0; i < rel_size; i++, rpnt++) { + int res; + + symtab_index = ELF32_R_SYM(rpnt->r_info); + + debug_sym(symtab,strtab,symtab_index); + debug_reloc(symtab,strtab,rpnt); + + res = reloc_fnc (tpnt, scope, rpnt, symtab, strtab); + + if (res==0) continue; + + _dl_dprintf(2, "\n%s: ",_dl_progname); + + if (symtab_index) + _dl_dprintf(2, "symbol '%s': ", strtab + symtab[symtab_index].st_name); + + if (unlikely(res <0)) + { + int reloc_type = ELF32_R_TYPE(rpnt->r_info); +#if defined (__SUPPORT_LD_DEBUG__) + _dl_dprintf(2, "can't handle reloc type '%s' in lib '%s'\n", _dl_reltypes(reloc_type), tpnt->libname); +#else + _dl_dprintf(2, "can't handle reloc type %x in lib '%s'\n", reloc_type, tpnt->libname); +#endif + return res; + } + if (unlikely(res >0)) + { + _dl_dprintf(2, "can't resolve symbol in lib '%s'.\n", tpnt->libname); + return res; + } + } + return 0; +} + +int _dl_parse_relocation_information(struct dyn_elf *rpnt, + unsigned long rel_addr, unsigned long rel_size) +{ + return _dl_parse(rpnt->dyn, rpnt->dyn->symbol_scope, rel_addr, rel_size, _dl_do_reloc); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/powerpc/resolve.S b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/powerpc/resolve.S new file mode 100644 index 00000000..c83337cc --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/powerpc/resolve.S @@ -0,0 +1,57 @@ +/* + * Stolen from glibc-2.2.2 by David Schleef + */ + +.text +.align 4 + +.globl _dl_linux_resolver + +.globl _dl_linux_resolve +.type _dl_linux_resolve,@function + +_dl_linux_resolve: +/* We need to save the registers used to pass parameters, and register 0, + which is used by _mcount; the registers are saved in a stack frame. */ + stwu 1,-64(1) + stw 0,12(1) + stw 3,16(1) + stw 4,20(1) +/* The code that calls this has put parameters for 'fixup' in r12 and r11. */ + mr 3,12 + stw 5,24(1) + mr 4,11 + stw 6,28(1) + mflr 0 +/* We also need to save some of the condition register fields. */ + stw 7,32(1) + stw 0,48(1) + stw 8,36(1) + mfcr 0 + stw 9,40(1) + stw 10,44(1) + stw 0,8(1) + bl _dl_linux_resolver@local +/* 'fixup' returns the address we want to branch to. */ + mtctr 3 +/* Put the registers back... */ + lwz 0,48(1) + lwz 10,44(1) + lwz 9,40(1) + mtlr 0 + lwz 8,36(1) + lwz 0,8(1) + lwz 7,32(1) + lwz 6,28(1) + mtcrf 0xFF,0 + lwz 5,24(1) + lwz 4,20(1) + lwz 3,16(1) + lwz 0,12(1) +/* ...unwind the stack frame, and jump to the PLT entry we updated. */ + addi 1,1,64 + bctr + +.LFE2: + .size _dl_linux_resolve,.LFE2-_dl_linux_resolve + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/sh/dl-debug.h b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/sh/dl-debug.h new file mode 100644 index 00000000..e2e74f8e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/sh/dl-debug.h @@ -0,0 +1,43 @@ +/* vi: set sw=4 ts=4: */ +/* SuperH ELF shared library loader suppport + * + * Copyright (C) 2002, Stefan Allius and + * Eddie C. Dost + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. The name of the above contributors may not be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +static const char *_dl_reltypes_tab[] = +{ + [0] "R_SH_NONE", "R_SH_DIR32", "R_SH_REL32", "R_SH_DIR8WPN", + [4] "R_SH_IND12W", "R_SH_DIR8WPL", "R_SH_DIR8WPZ", "R_SH_DIR8BP", + [8] "R_SH_DIR8W", "R_SH_DIR8L", + [25] "R_SH_SWITCH16","R_SH_SWITCH32","R_SH_USES", + [28] "R_SH_COUNT", "R_SH_ALIGN", "R_SH_CODE", "R_SH_DATA", + [32] "R_SH_LABEL", "R_SH_SWITCH8", "R_SH_GNU_VTINHERIT","R_SH_GNU_VTENTRY", +[144] "R_SH_TLS_GD_32","R_SH_TLS_LD_32", "R_SH_TLS_LDO_32", "R_SH_TLS_IE_32", +[148] "R_SH_TLS_LE_32","R_SH_TLS_DTPMOD32", "R_SH_TLS_DTPOFF32", "R_SH_TLS_TPOFF32", +[160] "R_SH_GOT32", "R_SH_PLT32", "R_SH_COPY", "R_SH_GLOB_DAT", +[164] "R_SH_JMP_SLOT","R_SH_RELATIVE","R_SH_GOTOFF", "R_SH_GOTPC", +}; diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/sh/dl-startup.h b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/sh/dl-startup.h new file mode 100644 index 00000000..ae7e2248 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/sh/dl-startup.h @@ -0,0 +1,68 @@ +/* Any assembly language/system dependent hacks needed to setup boot1.c so it + * will work as expected and cope with whatever platform specific wierdness is + * needed for this architecture. */ + +__asm__( + " .text\n" + " .globl _start\n" + " .type _start,@function\n" + "_start:\n" + " mov r15, r4\n" + " mov.l .L_dl_start, r0\n" + " bsrf r0\n" + " add #4, r4\n" + ".jmp_loc:\n" + " mov r0, r8 ! Save the user entry point address in r8\n" + " mov.l .L_got, r12 ! Load the GOT on r12\n" + " mova .L_got, r0\n" + " add r0, r12\n" + " mov.l .L_dl_fini, r0\n" + " mov.l @(r0,r12), r4 ! Pass the finalizer in r4\n" + " jmp @r8\n" + " nop\n" + ".L_dl_start:\n" + " .long _dl_start-.jmp_loc\n" + ".L_dl_fini:\n" + " .long _dl_fini@GOT\n" + ".L_got:\n" + " .long _GLOBAL_OFFSET_TABLE_\n" + " .size _start,.-_start\n" + " .previous\n" +); + +/* + * Get a pointer to the argv array. On many platforms this can be just + * the address of the first argument, on other platforms we need to + * do something a little more subtle here. + */ +#define GET_ARGV(ARGVP, ARGS) ARGVP = ((unsigned long*) ARGS) + +/* We can't call functions earlier in the dl startup process */ +#define NO_FUNCS_BEFORE_BOOTSTRAP + +/* + * Here is a macro to perform a relocation. This is only used when + * bootstrapping the dynamic loader. RELP is the relocation that we + * are performing, REL is the pointer to the address we are relocating. + * SYMBOL is the symbol involved in the relocation, and LOAD is the + * load address. + */ +#define PERFORM_BOOTSTRAP_RELOC(RELP,REL,SYMBOL,LOAD,SYMTAB) \ + switch(ELF32_R_TYPE((RELP)->r_info)){ \ + case R_SH_REL32: \ + *(REL) = (SYMBOL) + (RELP)->r_addend \ + - (unsigned long)(REL); \ + break; \ + case R_SH_DIR32: \ + case R_SH_GLOB_DAT: \ + case R_SH_JMP_SLOT: \ + *(REL) = (SYMBOL) + (RELP)->r_addend; \ + break; \ + case R_SH_RELATIVE: \ + *(REL) = (LOAD) + (RELP)->r_addend; \ + break; \ + case R_SH_NONE: \ + break; \ + default: \ + _dl_exit(1); \ + } diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/sh/dl-syscalls.h b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/sh/dl-syscalls.h new file mode 100644 index 00000000..712852c4 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/sh/dl-syscalls.h @@ -0,0 +1,14 @@ +/* We can't use the real errno in ldso, since it has not yet + * been dynamicly linked in yet. */ +#include "sys/syscall.h" +extern int _dl_errno; +#undef __set_errno +#define __set_errno(X) {(_dl_errno) = (X);} + +#if __GNUC_PREREQ (4, 1) +#warning !!! gcc 4.1 and later have problems with __always_inline so redefined as inline +# ifdef __always_inline +# undef __always_inline +# define __always_inline __inline__ +# endif +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/sh/dl-sysdep.h b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/sh/dl-sysdep.h new file mode 100644 index 00000000..21244ec1 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/sh/dl-sysdep.h @@ -0,0 +1,171 @@ +/* + * Various assembly language/system dependent hacks that are required + * so that we can minimize the amount of platform specific code. + */ + +/* Define this if the system uses RELOCA. */ +#define ELF_USES_RELOCA +#include +/* + * Initialization sequence for a GOT. + */ +#define INIT_GOT(GOT_BASE,MODULE) \ +{ \ + GOT_BASE[2] = (unsigned long) _dl_linux_resolve; \ + GOT_BASE[1] = (unsigned long) (MODULE); \ +} + +/* Here we define the magic numbers that this dynamic loader should accept */ +#define MAGIC1 EM_SH +#undef MAGIC2 + +/* Used for error messages */ +#define ELF_TARGET "sh" + +struct elf_resolve; +extern unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_entry); + +static __always_inline unsigned int +_dl_urem(unsigned int n, unsigned int base) +{ + int res; + + __asm__ (""\ + "mov #0, r0\n\t" \ + "div0u\n\t" \ + "" \ + "! get one bit from the msb of the numerator into the T\n\t" \ + "! bit and divide it by whats in %2. Put the answer bit\n\t" \ + "! into the T bit so it can come out again at the bottom\n\t" \ + "" \ + "rotcl %1 ; div1 %2, r0\n\t" \ + "rotcl %1 ; div1 %2, r0\n\t" \ + "rotcl %1 ; div1 %2, r0\n\t" \ + "rotcl %1 ; div1 %2, r0\n\t" \ + "rotcl %1 ; div1 %2, r0\n\t" \ + "rotcl %1 ; div1 %2, r0\n\t" \ + "rotcl %1 ; div1 %2, r0\n\t" \ + "rotcl %1 ; div1 %2, r0\n\t" \ + "" \ + "rotcl %1 ; div1 %2, r0\n\t" \ + "rotcl %1 ; div1 %2, r0\n\t" \ + "rotcl %1 ; div1 %2, r0\n\t" \ + "rotcl %1 ; div1 %2, r0\n\t" \ + "rotcl %1 ; div1 %2, r0\n\t" \ + "rotcl %1 ; div1 %2, r0\n\t" \ + "rotcl %1 ; div1 %2, r0\n\t" \ + "rotcl %1 ; div1 %2, r0\n\t" \ + "" \ + "rotcl %1 ; div1 %2, r0\n\t" \ + "rotcl %1 ; div1 %2, r0\n\t" \ + "rotcl %1 ; div1 %2, r0\n\t" \ + "rotcl %1 ; div1 %2, r0\n\t" \ + "rotcl %1 ; div1 %2, r0\n\t" \ + "rotcl %1 ; div1 %2, r0\n\t" \ + "rotcl %1 ; div1 %2, r0\n\t" \ + "rotcl %1 ; div1 %2, r0\n\t" \ + "" \ + "rotcl %1 ; div1 %2, r0\n\t" \ + "rotcl %1 ; div1 %2, r0\n\t" \ + "rotcl %1 ; div1 %2, r0\n\t" \ + "rotcl %1 ; div1 %2, r0\n\t" \ + "rotcl %1 ; div1 %2, r0\n\t" \ + "rotcl %1 ; div1 %2, r0\n\t" \ + "rotcl %1 ; div1 %2, r0\n\t" \ + "rotcl %1 ; div1 %2, r0\n\t" \ + "rotcl %1\n\t" + : "=r" (res) + : "0" (n), "r" (base) + : "r0","cc"); + + return n - (base * res); +} + +#define do_rem(result, n, base) ((result) = _dl_urem((n), (base))) + +/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry or + TLS variable, so undefined references should not be allowed to + define the value. + ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to one + of the main executable's symbols, as for a COPY reloc. */ +# define elf_machine_type_class(type) \ + ((((type) == R_SH_JMP_SLOT || (type) == R_SH_TLS_DTPMOD32 \ + || (type) == R_SH_TLS_DTPOFF32 || (type) == R_SH_TLS_TPOFF32) \ + * ELF_RTYPE_CLASS_PLT) \ + | (((type) == R_SH_COPY) * ELF_RTYPE_CLASS_COPY)) + +/* Return the link-time address of _DYNAMIC. Conveniently, this is the + first element of the GOT. This must be inlined in a function which + uses global data. */ +static __always_inline Elf32_Addr __attribute__ ((unused)) +elf_machine_dynamic (void) +{ + register Elf32_Addr *got; + __asm__ ("mov r12,%0" :"=r" (got)); + return *got; +} + +/* Return the run-time load address of the shared object. */ +static __always_inline Elf32_Addr __attribute__ ((unused)) +elf_machine_load_address (void) +{ + Elf32_Addr addr; + __asm__ ("mov.l 1f,r0\n\ + mov.l 3f,r2\n\ + add r12,r2\n\ + mov.l @(r0,r12),r0\n\ + bra 2f\n\ + sub r0,r2\n\ + .align 2\n\ + 1: .long _dl_start@GOT\n\ + 3: .long _dl_start@GOTOFF\n\ + 2: mov r2,%0" + : "=r" (addr) : : "r0", "r1", "r2"); + return addr; +} + +#define COPY_UNALIGNED_WORD(swp, twp, align) \ + { \ + void *__s = (swp), *__t = (twp); \ + unsigned char *__s1 = __s, *__t1 = __t; \ + unsigned short *__s2 = __s, *__t2 = __t; \ + unsigned long *__s4 = __s, *__t4 = __t; \ + switch ((align)) \ + { \ + case 0: \ + *__t4 = *__s4; \ + break; \ + case 2: \ + *__t2++ = *__s2++; \ + *__t2 = *__s2; \ + break; \ + default: \ + *__t1++ = *__s1++; \ + *__t1++ = *__s1++; \ + *__t1++ = *__s1++; \ + *__t1 = *__s1; \ + break; \ + } \ + } + +static __always_inline void +elf_machine_relative (Elf32_Addr load_off, const Elf32_Addr rel_addr, + Elf32_Word relative_count) +{ + Elf32_Addr value; + Elf32_Rela * rpnt = (void *)rel_addr; + + do { + Elf32_Addr *const reloc_addr = (void *) (load_off + rpnt->r_offset); + + if (rpnt->r_addend) + value = load_off + rpnt->r_addend; + else { + COPY_UNALIGNED_WORD (reloc_addr, &value, (int) reloc_addr & 3); + value += load_off; + } + COPY_UNALIGNED_WORD (&value, reloc_addr, (int) reloc_addr & 3); + rpnt++; + } while (--relative_count); +#undef COPY_UNALIGNED_WORD +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/sh/elfinterp.c b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/sh/elfinterp.c new file mode 100644 index 00000000..be3b98cf --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/sh/elfinterp.c @@ -0,0 +1,303 @@ +/* vi: set sw=4 ts=4: */ +/* SuperH ELF shared library loader suppport + * + * Copyright (C) 2002, Stefan Allius and + * Eddie C. Dost + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. The name of the above contributors may not be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* Program to load an ELF binary on a linux system, and run it. + References to symbols in sharable libraries can be resolved by either + an ELF sharable library or a linux style of shared library. */ + +/* Disclaimer: I have never seen any AT&T source code for SVr4, nor have + I ever taken any courses on internals. This program was developed using + information available through the book "UNIX SYSTEM V RELEASE 4, + Programmers guide: Ansi C and Programming Support Tools", which did + a more than adequate job of explaining everything required to get this + working. */ + +#include "ldso.h" + +extern int _dl_linux_resolve(void); + +unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry) +{ + ELF_RELOC *this_reloc; + char *strtab; + Elf32_Sym *symtab; + int symtab_index; + char *rel_addr; + char *new_addr; + char **got_addr; + unsigned long instr_addr; + char *symname; + + rel_addr = (char *)tpnt->dynamic_info[DT_JMPREL]; + + this_reloc = (ELF_RELOC *)(intptr_t)(rel_addr + reloc_entry); + symtab_index = ELF32_R_SYM(this_reloc->r_info); + + symtab = (Elf32_Sym *)(intptr_t) tpnt->dynamic_info[DT_SYMTAB]; + strtab = (char *)tpnt->dynamic_info[DT_STRTAB]; + symname = strtab + symtab[symtab_index].st_name; + + /* Address of jump instruction to fix up */ + instr_addr = (unsigned long) (this_reloc->r_offset + tpnt->loadaddr); + got_addr = (char **) instr_addr; + + /* Get the address of the GOT entry */ + new_addr = _dl_find_hash(symname, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL); + + if (unlikely(!new_addr)) { + _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", _dl_progname, symname); + _dl_exit(1); + } + +#if defined (__SUPPORT_LD_DEBUG__) + if ((unsigned long) got_addr < 0x20000000) { + if (_dl_debug_bindings) { + _dl_dprintf(_dl_debug_file, "\nresolve function: %s", symname); + if (_dl_debug_detail) _dl_dprintf(_dl_debug_file, + "\n\tpatched %x ==> %x @ %x\n", *got_addr, new_addr, got_addr); + } + } + if (!_dl_debug_nofixups) + *got_addr = new_addr; +#else + *got_addr = new_addr; +#endif + + return (unsigned long) new_addr; +} + + +static int +_dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope, + unsigned long rel_addr, unsigned long rel_size, + int (*reloc_fnc) (struct elf_resolve *tpnt, struct dyn_elf *scope, + ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)) +{ + unsigned int i; + char *strtab; + Elf32_Sym *symtab; + ELF_RELOC *rpnt; + int symtab_index; + /* Now parse the relocation information */ + + rpnt = (ELF_RELOC *)(intptr_t) rel_addr; + rel_size = rel_size / sizeof(ELF_RELOC); + + symtab = (Elf32_Sym *)(intptr_t)tpnt->dynamic_info[DT_SYMTAB]; + strtab = (char *)tpnt->dynamic_info[DT_STRTAB]; + + for (i = 0; i < rel_size; i++, rpnt++) { + int res; + + symtab_index = ELF32_R_SYM(rpnt->r_info); + debug_sym(symtab,strtab,symtab_index); + debug_reloc(symtab,strtab,rpnt); + + res = reloc_fnc(tpnt, scope, rpnt, symtab, strtab); + + if (res == 0) continue; + + _dl_dprintf(2, "\n%s: ",_dl_progname); + + if (symtab_index) + _dl_dprintf(2, "symbol '%s': ", strtab + symtab[symtab_index].st_name); + + if (unlikely(res < 0)) { + int reloc_type = ELF32_R_TYPE(rpnt->r_info); +#if defined (__SUPPORT_LD_DEBUG__) + _dl_dprintf(2, "can't handle reloc type %s\n ", _dl_reltypes(reloc_type)); +#else + _dl_dprintf(2, "can't handle reloc type %x\n", reloc_type); +#endif + _dl_exit(-res); + } + if (unlikely(res > 0)) { + _dl_dprintf(2, "can't resolve symbol\n"); + return res; + } + } + return 0; +} + + +static int +_dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope, + ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab) +{ + int reloc_type; + int symtab_index; + char *symname; + unsigned long *reloc_addr; + unsigned long symbol_addr; +#if defined (__SUPPORT_LD_DEBUG__) + unsigned long old_val; +#endif + + struct elf_resolve *tls_tpnt = NULL; + struct symbol_ref sym_ref; + + reloc_addr = (unsigned long *)(intptr_t) (tpnt->loadaddr + (unsigned long) rpnt->r_offset); + reloc_type = ELF32_R_TYPE(rpnt->r_info); + symtab_index = ELF32_R_SYM(rpnt->r_info); + symbol_addr = 0; + sym_ref.sym = &symtab[symtab_index]; + sym_ref.tpnt = NULL; + + if (symtab_index) { + symname = strtab + symtab[symtab_index].st_name; + symbol_addr = (unsigned long) _dl_find_hash(symname, scope, tpnt, + elf_machine_type_class(reloc_type), &sym_ref); + /* + * We want to allow undefined references to weak symbols - this might + * have been intentional. We should not be linking local symbols + * here, so all bases should be covered. + */ + + if (!symbol_addr + && (ELF_ST_TYPE(symtab[symtab_index].st_info) != STT_TLS) + && (ELF32_ST_BIND(symtab[symtab_index].st_info) != STB_WEAK)) { + _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", + _dl_progname, symname); + + /* Let the caller to handle the error: it may be non fatal if called from dlopen */ + return 1; + } + tls_tpnt = sym_ref.tpnt; + } + +#if defined (__SUPPORT_LD_DEBUG__) + old_val = *reloc_addr; +#endif + +#if defined USE_TLS && USE_TLS + /* In case of a TLS reloc, tls_tpnt NULL means we have an 'anonymous' + symbol. This is the case for a static tls variable, so the lookup + module is just that one is referencing the tls variable. */ + if (!tls_tpnt) + tls_tpnt = tpnt; +#endif + switch (reloc_type) { + case R_SH_NONE: + break; + case R_SH_COPY: + if (symbol_addr) { +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_move) + _dl_dprintf(_dl_debug_file,"\n%s move %x bytes from %x to %x", + symname, symtab[symtab_index].st_size, + symbol_addr, reloc_addr); +#endif + _dl_memcpy((char *) reloc_addr, (char *) symbol_addr, symtab[symtab_index].st_size); + } + return 0; /* no further LD_DEBUG messages for copy relocs */ + case R_SH_DIR32: + case R_SH_GLOB_DAT: + case R_SH_JMP_SLOT: + *reloc_addr = symbol_addr + rpnt->r_addend; + break; + case R_SH_REL32: + *reloc_addr = symbol_addr + rpnt->r_addend - + (unsigned long) reloc_addr; + break; + case R_SH_RELATIVE: + *reloc_addr = (unsigned long) tpnt->loadaddr + rpnt->r_addend; + break; +#if defined USE_TLS && USE_TLS + case R_SH_TLS_DTPMOD32: + *reloc_addr = tls_tpnt->l_tls_modid; + break; + case R_SH_TLS_DTPOFF32: + *reloc_addr = symbol_addr; + break; + case R_SH_TLS_TPOFF32: + CHECK_STATIC_TLS ((struct link_map *) tls_tpnt); + *reloc_addr = tls_tpnt->l_tls_offset + symbol_addr + rpnt->r_addend; + break; +#endif + default: + + return -1; + } +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_reloc && _dl_debug_detail) + _dl_dprintf(_dl_debug_file, "\tpatched: %x ==> %x @ %x\n", old_val, *reloc_addr, reloc_addr); +#endif + + return 0; +} + + +static int +_dl_do_lazy_reloc (struct elf_resolve *tpnt, struct dyn_elf *scope, + ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab) +{ + int reloc_type; + unsigned long *reloc_addr; +#if defined (__SUPPORT_LD_DEBUG__) + unsigned long old_val; +#endif + (void)scope; + (void)symtab; + (void)strtab; + + reloc_addr = (unsigned long *)(intptr_t) (tpnt->loadaddr + (unsigned long) rpnt->r_offset); + reloc_type = ELF32_R_TYPE(rpnt->r_info); + +#if defined (__SUPPORT_LD_DEBUG__) + old_val = *reloc_addr; +#endif + switch (reloc_type) { + case R_SH_NONE: + break; + case R_SH_JMP_SLOT: + *reloc_addr += (unsigned long) tpnt->loadaddr; + break; + default: + return -1; + } +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_reloc && _dl_debug_detail) + _dl_dprintf(_dl_debug_file, "\tpatched: %x ==> %x @ %x\n", old_val, *reloc_addr, reloc_addr); +#endif + return 0; + +} + +void _dl_parse_lazy_relocation_information(struct dyn_elf *rpnt, + unsigned long rel_addr, unsigned long rel_size) +{ + (void)_dl_parse(rpnt->dyn, NULL, rel_addr, rel_size, _dl_do_lazy_reloc); +} + +int _dl_parse_relocation_information(struct dyn_elf *rpnt, + unsigned long rel_addr, unsigned long rel_size) +{ + return _dl_parse(rpnt->dyn, rpnt->dyn->symbol_scope, rel_addr, rel_size, _dl_do_reloc); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/sh/resolve.S b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/sh/resolve.S new file mode 100644 index 00000000..e66d316e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/sh/resolve.S @@ -0,0 +1,98 @@ +/* + * Stolen from glibc-2.2.2 by Eddie C. Dost + */ + + .text + .globl _dl_linux_resolver + .globl _dl_linux_resolve + .type _dl_linux_resolve, @function + .balign 16 +_dl_linux_resolve: + mov.l r2, @-r15 ! see Note2 below + mov.l r3, @-r15 + mov.l r4, @-r15 + mov.l r5, @-r15 + mov.l r6, @-r15 + mov.l r7, @-r15 + mov.l r12, @-r15 + movt r3 ! Save T flag + mov.l r3, @-r15 + +#ifdef HAVE_FPU + sts.l fpscr, @-r15 + mov #8,r3 + swap.w r3, r3 + lds r3, fpscr + fmov.s fr11, @-r15 + fmov.s fr10, @-r15 + fmov.s fr9, @-r15 + fmov.s fr8, @-r15 + fmov.s fr7, @-r15 + fmov.s fr6, @-r15 + fmov.s fr5, @-r15 + fmov.s fr4, @-r15 +#endif + sts.l pr, @-r15 +/* Note - The PLT entries have been "optimised" not to use r2. r2 is used by + GCC to return the address of large structures, so it should not be + corrupted here. This does mean however, that those PLTs does not conform + to the SH PIC ABI. That spec says that r0 contains the type of the PLT + and r2 contains the GOT id. The GNU Plt version stores the GOT id in r0 and + ignores the type. We can easily detect this difference however, + since the type will always be 0 or 8, and the GOT ids will always be + greater than or equal to 12. + + Found in binutils/bfd/elf32-sh.c by Stefan Allius + + Note2 - we also have to preserve r2 on the stack as the call into + C code (_dl_linux_resolver) will use r2 as a scratch register and we + need it for the address for returning structures, + David McCullough . + */ + mov #8 ,r5 + cmp/gt r5, r0 + bt 1f + mov r2, r0 ! link map address in r2 (SH PIC ABI) +1: + mov r0, r4 ! link map address in r0 (GNUs PLT) + mova .LG, r0 + mov.l .LG, r5 + add r5, r0 + mov.l 3f, r5 + mov.l @(r0, r5),r5 + jsr @r5 + mov r1, r5 ! Reloc offset + + lds.l @r15+, pr ! Get register content back + +#ifdef HAVE_FPU + fmov.s @r15+, fr4 + fmov.s @r15+, fr5 + fmov.s @r15+, fr6 + fmov.s @r15+, fr7 + fmov.s @r15+, fr8 + fmov.s @r15+, fr9 + fmov.s @r15+, fr10 + fmov.s @r15+, fr11 + lds.l @r15+, fpscr +#endif + + mov.l @r15+, r3 + shal r3 ! Load T flag + mov.l @r15+, r12 + mov.l @r15+, r7 + mov.l @r15+, r6 + mov.l @r15+, r5 + mov.l @r15+, r4 + mov.l @r15+, r3 + jmp @r0 ! Jump to function address + mov.l @r15+, r2 ! see Note2 above + + .balign 4 + +3: + .long _dl_linux_resolver@GOT +.LG: + .long _GLOBAL_OFFSET_TABLE_ + .size _dl_linux_resolve, . - _dl_linux_resolve + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/sh64/dl-debug.h b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/sh64/dl-debug.h new file mode 100644 index 00000000..485aac7f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/sh64/dl-debug.h @@ -0,0 +1,79 @@ +/* vi: set sw=8 ts=8: */ +/* + * ldso/ldso/sh64/elfinterp.c + * + * SuperH (sh64) ELF shared library loader suppport + * + * Copyright (C) 2003, 2004, 2005 Paul Mundt + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. The name of the above contributors may not be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +static const char *_dl_reltypes_tab[] = { + /* SHcompact relocs */ + [0] = "R_SH_NONE", "R_SH_DIR32", + "R_SH_REL32", "R_SH_DIR8WPN", + [4] = "R_SH_IND12W", "R_SH_DIR8WPL", + "R_SH_DIR8WPZ", "R_SH_DIR8BP", + [8] = "R_SH_DIR8W", "R_SH_DIR8L", + [25] = "R_SH_SWITCH16", "R_SH_SWITCH32", + "R_SH_USES", "R_SH_COUNT", + [29] = "R_SH_ALIGN", "R_SH_CODE", + "R_SH_DATA", "R_SH_LABEL", + [33] = "R_SH_SWITCH8", "R_SH_GNU_VTINHERIT", + "R_SH_GNU_VTENTRY", + [160] = "R_SH_GOT32", "R_SH_PLT32", + "R_SH_COPY", "R_SH_GLOB_DAT", + [164] = "R_SH_JMP_SLOT", "R_SH_RELATIVE", + "R_SH_GOTOFF", "R_SH_GOTPC", + + /* SHmedia relocs */ + [45] = "R_SH_DIR5U", "R_SH_DIR6U", + "R_SH_DIR6S", "R_SH_DIR10S", + [49] = "R_SH_DIR10SW", "R_SH_DIR10SL", + "R_SH_DIR10SQ", + [169] = "R_SH_GOT_LOW16", "R_SH_GOT_MEDLOW16", + "R_SH_GOT_MEDHI16", "R_SH_GOT_HI16", + [173] = "R_SH_GOTPLT_LOW16", "R_SH_GOTPLT_MEDLOW16", + "R_SH_GOTPLT_MEDHI16", "R_SH_GOTPLT_HI16", + [177] = "R_SH_PLT_LOW16", "R_SH_PLT_MEDLOW16", + "R_SH_PLT_MEDHI16", "R_SH_PLT_HI16", + [181] = "R_SH_GOTOFF_LOW16", "R_SH_GOTOFF_MEDLOW16", + "R_SH_GOTOFF_MEDHI16", "R_SH_GOTOFF_HI16", + [185] = "R_SH_GOTPC_LOW16", "R_SH_GOTPC_MEDLOW16", + "R_SH_GOTPC_MEDHI16", "R_SH_GOTPC_HI16", + [189] = "R_SH_GOT10BY4", "R_SH_GOTPLT10BY4", + "R_SH_GOT10BY8", "R_SH_GOTPLT10BY8", + [193] = "R_SH_COPY64", "R_SH_GLOB_DAT64", + "R_SH_JMP_SLOT64", "R_SH_RELATIVE64", + [197] = "R_SH_RELATIVE_LOW16", "R_SH_RELATIVE_MEDLOW16", + "R_SH_RELATIVE_MEDHI16","R_SH_RELATIVE_HI16", + [242] = "R_SH_SHMEDIA_CODE", "R_SH_PT_16", + "R_SH_IMMS16", "R_SH_IMMU16", + [246] = "R_SH_IMM_LOW16", "R_SH_IMM_LOW16_PCREL", + "R_SH_IMM_MEDLOW16", "R_SH_IMM_MEDLOW16_PCREL", + [250] = "R_SH_IMM_MEDHI16", "R_SH_IMM_MEDHI16_PCREL", + "R_SH_IMM_HI16", "R_SH_IMM_HI16_PCREL", + [254] = "R_SH_64", "R_SH_64_PCREL", +}; diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/sh64/dl-startup.h b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/sh64/dl-startup.h new file mode 100644 index 00000000..75313411 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/sh64/dl-startup.h @@ -0,0 +1,117 @@ +/* Any assembly language/system dependent hacks needed to setup boot1.c so it + * will work as expected and cope with whatever platform specific wierdness is + * needed for this architecture. + */ + +__asm__("" \ +" .section .text..SHmedia32,\"ax\"\n" \ +" .globl _start\n" \ +" .type _start, @function\n" \ +" .align 5\n" \ +"_start:\n" \ +" ! Set r12 to point to GOT\n" \ +" movi (((datalabel _GLOBAL_OFFSET_TABLE_-(.LZZZ3-.)) >> 16) & 0xffff), r12\n" \ +" shori ((datalabel _GLOBAL_OFFSET_TABLE_-(.LZZZ3-.)) & 0xffff), r12\n" \ +".LZZZ3:\n" \ +" ptrel/u r12, tr0\n" \ +" gettr tr0, r12 ! GOT address\n" \ +" add r18, r63, r11 ! save return address - needed?\n" \ +" add r15, r63, r2 ! arg = stack pointer\n" \ +" pt _dl_start, tr0 ! should work even if PIC\n" \ +" blink tr0, r18 ! call _dl_start - user EP is in r2\n" \ +" add r2, r63, r28\n" \ +" movi (((_dl_fini@GOT) >> 16) & 0xffff), r1\n" \ +" shori ((_dl_fini@GOT) & 0xffff), r1\n" \ +" ldx.l r1, r12, r2\n" \ +" add r11, r63, r18\n" \ +" ptabs/l r28, tr0\n" \ +" blink tr0, r63\n" \ +" .size _start,.-_start\n" +" .previous\n" +); + +/* + * Get a pointer to the argv array. On many platforms this can be just + * the address of the first argument, on other platforms we need to + * do something a little more subtle here. + */ +#define GET_ARGV(ARGVP, ARGS) ARGVP = (((unsigned long *)ARGS)+1) + +/* + * Here is a macro to perform a relocation. This is only used when + * bootstrapping the dynamic loader. RELP is the relocation that we + * are performing, REL is the pointer to the address we are relocating. + * SYMBOL is the symbol involved in the relocation, and LOAD is the + * load address. + */ + +#include + +#define PERFORM_BOOTSTRAP_RELOC(RELP,REL,SYMBOL,LOAD,SYMTAB) \ + const unsigned int r_type = ELF32_R_TYPE((RELP)->r_info); \ + int lsb = !!((SYMTAB)->st_other & STO_SH5_ISA32); \ + \ + switch (r_type) { \ + case R_SH_REL32: \ + *(REL) = (SYMBOL) + (RELP)->r_addend \ + - (unsigned long)(REL); \ + break; \ + case R_SH_DIR32: \ + case R_SH_GLOB_DAT: \ + case R_SH_JMP_SLOT: \ + *(REL) = ((SYMBOL) + (RELP)->r_addend) | lsb; \ + break; \ + case R_SH_RELATIVE: \ + *(REL) = (LOAD) + (RELP)->r_addend; \ + break; \ + case R_SH_RELATIVE_LOW16: \ + case R_SH_RELATIVE_MEDLOW16: \ + { \ + unsigned long word, value; \ + \ + word = (unsigned long)(REL) & ~0x3fffc00; \ + value = (LOAD) + (RELP)->r_addend; \ + \ + if (r_type == R_SH_RELATIVE_MEDLOW16) \ + value >>= 16; \ + \ + word |= (value & 0xffff) << 10; \ + *(REL) = word; \ + break; \ + } \ + case R_SH_IMM_LOW16: \ + case R_SH_IMM_MEDLOW16: \ + { \ + unsigned long word, value; \ + \ + word = (unsigned long)(REL) & ~0x3fffc00; \ + value = ((SYMBOL) + (RELP)->r_addend) | lsb; \ + \ + if (r_type == R_SH_IMM_MEDLOW16) \ + value >>= 16; \ + \ + word |= (value & 0xffff) << 10; \ + *(REL) = word; \ + break; \ + } \ + case R_SH_IMM_LOW16_PCREL: \ + case R_SH_IMM_MEDLOW16_PCREL: \ + { \ + unsigned long word, value; \ + \ + word = (unsigned long)(REL) & ~0x3fffc00; \ + value = (SYMBOL) + (RELP)->r_addend \ + - (unsigned long)(REL); \ + \ + if (r_type == R_SH_IMM_MEDLOW16_PCREL) \ + value >>= 16; \ + \ + word |= (value & 0xffff) << 10; \ + *(REL) = word; \ + break; \ + } \ + case R_SH_NONE: \ + break; \ + default: \ + _dl_exit(1); \ + } diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/sh64/dl-syscalls.h b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/sh64/dl-syscalls.h new file mode 100644 index 00000000..4fe50fac --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/sh64/dl-syscalls.h @@ -0,0 +1,25 @@ +/* We can't use the real errno in ldso, since it has not yet + * been dynamicly linked in yet. */ +#include "sys/syscall.h" +extern int _dl_errno; +#undef __set_errno +#define __set_errno(X) {(_dl_errno) = (X);} + +#undef __syscall_return +#define __syscall_return(type, res) \ +do { \ + /* \ + * Note: when returning from kernel the return value is in r9 \ + * \ + * This prevents conflicts between return value and arg1 \ + * when dispatching signal handler, in other words makes \ + * life easier in the system call epilogue (see entry.S) \ + */ \ + register unsigned long __sr2 __asm__ ("r2") = res; \ + if ((unsigned long)(res) >= (unsigned long)(-125)) { \ + _dl_errno = -(res); \ + __sr2 = -1; \ + } \ + return (type)(__sr2); \ +} while (0) + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/sh64/dl-sysdep.h b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/sh64/dl-sysdep.h new file mode 100644 index 00000000..15d9b5eb --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/sh64/dl-sysdep.h @@ -0,0 +1,168 @@ +/* vi: set sw=8 ts=8: */ +/* + * Various assembly language/system dependent hacks that are required + * so that we can minimize the amount of platform specific code. + */ + +/* Define this if the system uses RELOCA. */ +#define ELF_USES_RELOCA +#include +/* + * Initialization sequence for a GOT. + */ +#define INIT_GOT(GOT_BASE,MODULE) \ +{ \ + GOT_BASE[2] = (unsigned long)_dl_linux_resolve; \ + GOT_BASE[1] = (unsigned long)(MODULE); \ +} + +/* Here we define the magic numbers that this dynamic loader should accept */ +#define MAGIC1 EM_SH +#undef MAGIC2 + +/* Used for error messages */ +#define ELF_TARGET "sh64" + +/* Need bootstrap relocations */ +#define ARCH_NEEDS_BOOTSTRAP_RELOCS + +struct elf_resolve; +extern unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_entry); + +/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry or + TLS variable, so undefined references should not be allowed to + define the value. + ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to one + of the main executable's symbols, as for a COPY reloc. */ +#define elf_machine_type_class(type) \ + ((((type) == R_SH_JMP_SLOT) * ELF_RTYPE_CLASS_PLT) \ + | (((type) == R_SH_COPY) * ELF_RTYPE_CLASS_COPY)) + +/* Return the link-time address of _DYNAMIC. Conveniently, this is the + first element of the GOT. This must be inlined in a function which + uses global data. */ +static __always_inline Elf32_Addr elf_machine_dynamic(void) +{ + register Elf32_Addr *got; + + /* + * The toolchain adds 32768 to the GOT address, we compensate for + * that in the movi/sub pair. + * + * XXX: If this is cleaned up in the toolchain, we can end up + * saving 2 instructions and subsequently free up r1 from the + * clobber list.. + */ + __asm__ ( + "movi\t(((datalabel _GLOBAL_OFFSET_TABLE_-(.LZZZ1-.)) >> 16) & 0xffff), r2\n\t" + "shori\t((datalabel _GLOBAL_OFFSET_TABLE_-(.LZZZ1-.)) & 0xffff), r2\n\t" + ".LZZZ1:\tptrel/u r2, tr0\n\t" + "movi\t32768, r1\n\t" + "gettr\ttr0, r2\n\t" + "sub\tr2, r1, %0\n\t" + : "=r" (got) + : /* no inputs */ + : "r1", "r2", "tr0" + ); + + return *got; +} + +/* Return the run-time load address of the shared object. */ +static __always_inline Elf32_Addr elf_machine_load_address(void) +{ + Elf32_Addr addr; + + __asm__ ( + "movi\t(((datalabel _GLOBAL_OFFSET_TABLE_-(.LZZZ2-.)) >> 16) & 0xffff), r0\n\t" + "shori\t((datalabel _GLOBAL_OFFSET_TABLE_-(.LZZZ2-.)) & 0xffff), r0\n\t" + ".LZZZ2:\tptrel/u r0, tr0\n\t" + "movi\t(((_dl_start@GOTOFF) >> 16) & 0xffff), r2\n\t" + "shori\t((_dl_start@GOTOFF) & 0xffff), r2\n\t" + "gettr\ttr0, r0\n\t" + "add\tr2, r0, r2\n\t" + "movi\t(((_dl_start@GOT) >> 16) & 0xffff), r1\n\t" + "shori\t((_dl_start@GOT) & 0xffff), r1\n\t" + "ldx.l\tr1, r0, r1\n\t" + "sub\tr2, r1, %0\n\t" + : "=r" (addr) + : /* no inputs */ + : "r0", "r1", "r2", "tr0" + ); + + return addr; +} + +/* + * XXX: As we don't need to worry about r25 clobbering, we could probably + * get away with inlining {st,ld}{x,}.l and friends here instead and + * forego gcc's idea of code generation. + */ +#define COPY_UNALIGNED_WORD(swp, twp, align) \ +{ \ + void *__s = (swp), *__t = (twp); \ + unsigned char *__s1 = __s, *__t1 = __t; \ + unsigned short *__s2 = __s, *__t2 = __t; \ + unsigned long *__s4 = __s, *__t4 = __t; \ + \ + switch ((align)) { \ + case 0: \ + *__t4 = *__s4; \ + break; \ + case 2: \ + *__t2++ = *__s2++; \ + *__t2 = *__s2; \ + break; \ + default: \ + *__t1++ = *__s1++; \ + *__t1++ = *__s1++; \ + *__t1++ = *__s1++; \ + *__t1 = *__s1; \ + break; \ + } \ +} + +static __always_inline void +elf_machine_relative(Elf32_Addr load_off, const Elf32_Addr rel_addr, + Elf32_Word relative_count) +{ + Elf32_Addr value, word; + Elf32_Rela *rpnt = (void *)rel_addr; + int reloc_type = ELF32_R_TYPE(rpnt->r_info); + + do { + Elf32_Addr *const reloc_addr = + (void *)(load_off + rpnt->r_offset); + int align = (int)reloc_addr & 3; + + switch (reloc_type) { + case R_SH_RELATIVE_LOW16: + COPY_UNALIGNED_WORD(reloc_addr, &word, align); + word &= ~0x3fffc00; + value = (rpnt->r_addend + load_off); + word |= (value & 0xffff) << 10; + COPY_UNALIGNED_WORD(&word, reloc_addr, align); + break; + case R_SH_RELATIVE_MEDLOW16: + COPY_UNALIGNED_WORD(reloc_addr, &word, align); + word &= ~0x3fffc00; + value = (rpnt->r_addend + load_off) >> 16; + word |= (value & 0xffff) << 10; + COPY_UNALIGNED_WORD(&word, reloc_addr, align); + break; + default: + if (rpnt->r_addend) { + value = load_off + rpnt->r_addend; + } else { + COPY_UNALIGNED_WORD(reloc_addr, &value, align); + value += load_off; + } + + COPY_UNALIGNED_WORD(&value, reloc_addr, align); + break; + } + + rpnt++; + } while (--relative_count); +#undef COPY_UNALIGNED_WORD +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/sh64/elfinterp.c b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/sh64/elfinterp.c new file mode 100644 index 00000000..990aed15 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/sh64/elfinterp.c @@ -0,0 +1,341 @@ +/* vi: set sw=8 ts=8: */ +/* + * ldso/ldso/sh64/elfinterp.c + * + * SuperH (sh64) ELF shared library loader suppport + * + * Copyright (C) 2003, 2004, 2005 Paul Mundt + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. The name of the above contributors may not be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* Program to load an ELF binary on a linux system, and run it. + References to symbols in sharable libraries can be resolved by either + an ELF sharable library or a linux style of shared library. */ + +/* Disclaimer: I have never seen any AT&T source code for SVr4, nor have + I ever taken any courses on internals. This program was developed using + information available through the book "UNIX SYSTEM V RELEASE 4, + Programmers guide: Ansi C and Programming Support Tools", which did + a more than adequate job of explaining everything required to get this + working. */ + +#include "ldso.h" + +extern int _dl_linux_resolve(void); + +unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry) +{ + ELF_RELOC *this_reloc; + char *strtab; + Elf32_Sym *symtab; + int symtab_index; + char *rel_addr; + char *new_addr; + char **got_addr; + unsigned long instr_addr; + char *symname; + + rel_addr = (char *)tpnt->dynamic_info[DT_JMPREL]; + + this_reloc = (ELF_RELOC *)(intptr_t)(rel_addr + reloc_entry); + symtab_index = ELF32_R_SYM(this_reloc->r_info); + + symtab = (Elf32_Sym *)(intptr_t)tpnt->dynamic_info[DT_SYMTAB]; + strtab = (char *)tpnt->dynamic_info[DT_STRTAB]; + symname = strtab + symtab[symtab_index].st_name; + + /* Address of jump instruction to fix up */ + instr_addr = ((unsigned long)this_reloc->r_offset + + (unsigned long)tpnt->loadaddr); + got_addr = (char **)instr_addr; + + + /* Get the address of the GOT entry */ + new_addr = _dl_find_hash(symname, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL); + if (unlikely(!new_addr)) { + _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", + _dl_progname, symname); + _dl_exit(1); + } + +#ifdef __SUPPORT_LD_DEBUG__ + if ((unsigned long)got_addr < 0x20000000) { + if (_dl_debug_bindings) { + _dl_dprintf(_dl_debug_file, "\nresolve function: %s", + symname); + + if (_dl_debug_detail) + _dl_dprintf(_dl_debug_file, + "\n\tpatched %x ==> %x @ %x\n", + *got_addr, new_addr, got_addr); + } + } + + if (!_dl_debug_nofixups) + *got_addr = new_addr; +#else + *got_addr = new_addr; +#endif + + return (unsigned long)new_addr; +} + +static int _dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope, + unsigned long rel_addr, unsigned long rel_size, + int (*reloc_fnc)(struct elf_resolve *tpnt, + struct dyn_elf *scope, + ELF_RELOC *rpnt, Elf32_Sym *symtab, + char *strtab)) +{ + unsigned int i; + char *strtab; + Elf32_Sym *symtab; + ELF_RELOC *rpnt; + int symtab_index; + + /* Now parse the relocation information */ + rpnt = (ELF_RELOC *)(intptr_t)rel_addr; + rel_size = rel_size / sizeof(ELF_RELOC); + + symtab = (Elf32_Sym *)(intptr_t)tpnt->dynamic_info[DT_SYMTAB]; + strtab = (char *)tpnt->dynamic_info[DT_STRTAB]; + + for (i = 0; i < rel_size; i++, rpnt++) { + int res; + + symtab_index = ELF32_R_SYM(rpnt->r_info); + debug_sym(symtab,strtab,symtab_index); + debug_reloc(symtab,strtab,rpnt); + + res = reloc_fnc (tpnt, scope, rpnt, symtab, strtab); + if (res == 0) + continue; + + _dl_dprintf(2, "\n%s: ",_dl_progname); + + if (symtab_index) + _dl_dprintf(2, "symbol '%s': ", + strtab + symtab[symtab_index].st_name); + + if (unlikely(res < 0)) { + int reloc_type = ELF32_R_TYPE(rpnt->r_info); + + _dl_dprintf(2, "can't handle reloc type " +#ifdef __SUPPORT_LD_DEBUG__ + "%s\n", _dl_reltypes(reloc_type) +#else + "%x\n", reloc_type +#endif + ); + + _dl_exit(-res); + } + if (unlikely(res > 0)) { + _dl_dprintf(2, "can't resolve symbol\n"); + + return res; + } + } + + return 0; +} + +static int _dl_do_reloc(struct elf_resolve *tpnt,struct dyn_elf *scope, + ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab) +{ + int reloc_type; + int symtab_index, lsb; + char *symname; + unsigned long *reloc_addr; + unsigned long symbol_addr; +#ifdef __SUPPORT_LD_DEBUG__ + unsigned long old_val; +#endif + struct symbol_ref sym_ref; + + reloc_type = ELF32_R_TYPE(rpnt->r_info); + symtab_index = ELF32_R_SYM(rpnt->r_info); + symbol_addr = 0; + lsb = !!(symtab[symtab_index].st_other & STO_SH5_ISA32); + sym_ref.sym = &symtab[symtab_index]; + sym_ref.tpnt = NULL; + symname = strtab + symtab[symtab_index].st_name; + reloc_addr = (unsigned long *)(intptr_t) + (tpnt->loadaddr + (unsigned long)rpnt->r_offset); + + if (symtab_index) { + int stb; + + symbol_addr = (unsigned long)_dl_find_hash(symname, scope, tpnt, + elf_machine_type_class(reloc_type), &sym_ref); + + /* + * We want to allow undefined references to weak symbols - this + * might have been intentional. We should not be linking local + * symbols here, so all bases should be covered. + */ + stb = ELF32_ST_BIND(symtab[symtab_index].st_info); + + if (stb != STB_WEAK && !symbol_addr) { + _dl_dprintf (2, "%s: can't resolve symbol '%s'\n", + _dl_progname, symname); + _dl_exit (1); + } + } + +#ifdef __SUPPORT_LD_DEBUG__ + old_val = *reloc_addr; +#endif + + switch (reloc_type) { + case R_SH_NONE: + break; + case R_SH_COPY: + _dl_memcpy((char *)reloc_addr, + (char *)symbol_addr, symtab[symtab_index].st_size); + break; + case R_SH_DIR32: + case R_SH_GLOB_DAT: + case R_SH_JMP_SLOT: + *reloc_addr = (symbol_addr + rpnt->r_addend) | lsb; + break; + case R_SH_REL32: + *reloc_addr = symbol_addr + rpnt->r_addend - + (unsigned long)reloc_addr; + break; + case R_SH_RELATIVE: + *reloc_addr = (unsigned long)tpnt->loadaddr + rpnt->r_addend; + break; + case R_SH_RELATIVE_LOW16: + case R_SH_RELATIVE_MEDLOW16: + { + unsigned long word, value; + + word = (unsigned long)reloc_addr & ~0x3fffc00; + value = (unsigned long)tpnt->loadaddr + rpnt->r_addend; + + if (reloc_type == R_SH_RELATIVE_MEDLOW16) + value >>= 16; + + word |= (value & 0xffff) << 10; + *reloc_addr = word; + + break; + } + case R_SH_IMM_LOW16: + case R_SH_IMM_MEDLOW16: + { + unsigned long word, value; + + word = (unsigned long)reloc_addr & ~0x3fffc00; + value = (symbol_addr + rpnt->r_addend) | lsb; + + if (reloc_type == R_SH_IMM_MEDLOW16) + value >>= 16; + + word |= (value & 0xffff) << 10; + *reloc_addr = word; + + break; + } + case R_SH_IMM_LOW16_PCREL: + case R_SH_IMM_MEDLOW16_PCREL: + { + unsigned long word, value; + + word = (unsigned long)reloc_addr & ~0x3fffc00; + value = symbol_addr + rpnt->r_addend - + (unsigned long)reloc_addr; + + if (reloc_type == R_SH_IMM_MEDLOW16_PCREL) + value >>= 16; + + word |= (value & 0xffff) << 10; + *reloc_addr = word; + + break; + } + default: + return -1; /*call _dl_exit(1) */ + } + +#ifdef __SUPPORT_LD_DEBUG__ + if (_dl_debug_reloc && _dl_debug_detail) + _dl_dprintf(_dl_debug_file, "\tpatched: %x ==> %x @ %x\n", + old_val, *reloc_addr, reloc_addr); +#endif + + return 0; +} + +static int _dl_do_lazy_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, + ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab) +{ + int reloc_type, symtab_index, lsb; + unsigned long *reloc_addr; +#ifdef __SUPPORT_LD_DEBUG__ + unsigned long old_val; +#endif + + reloc_type = ELF32_R_TYPE(rpnt->r_info); + symtab_index = ELF32_R_SYM(rpnt->r_info); + lsb = !!(symtab[symtab_index].st_other & STO_SH5_ISA32); + reloc_addr = (unsigned long *)(intptr_t) + (tpnt->loadaddr + (unsigned long)rpnt->r_offset); + +#ifdef __SUPPORT_LD_DEBUG__ + old_val = *reloc_addr; +#endif + + switch (reloc_type) { + case R_SH_NONE: + break; + case R_SH_JMP_SLOT: + *reloc_addr += (unsigned long)tpnt->loadaddr | lsb; + break; + default: + return -1; /*call _dl_exit(1) */ + } + +#ifdef __SUPPORT_LD_DEBUG__ + if (_dl_debug_reloc && _dl_debug_detail) + _dl_dprintf(_dl_debug_file, "\tpatched: %x ==> %x @ %x\n", + old_val, *reloc_addr, reloc_addr); +#endif + + return 0; +} + +void _dl_parse_lazy_relocation_information(struct dyn_elf *rpnt, + unsigned long rel_addr, unsigned long rel_size) +{ + (void)_dl_parse(rpnt->dyn, NULL, rel_addr, rel_size, _dl_do_lazy_reloc); +} + +int _dl_parse_relocation_information(struct dyn_elf *rpnt, + unsigned long rel_addr, unsigned long rel_size) +{ + return _dl_parse(rpnt->dyn, rpnt->dyn->symbol_scope, rel_addr, rel_size, _dl_do_reloc); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/sh64/resolve.S b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/sh64/resolve.S new file mode 100644 index 00000000..ca915d2e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/sh64/resolve.S @@ -0,0 +1,95 @@ +/* vi: set sw=8 ts=8: */ +/* + * ldso/ldso/sh64/resolve.S + * + * SuperH (sh64) dynamic resolver support + * + * Copyright (C) 2003 Paul Mundt + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. The name of the above contributors may not be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + .section .text..SHmedia32,"ax" + .globl _dl_linux_resolver + .globl _dl_linux_resolve + .type _dl_linux_resolve, @function + + .balign 16 +_dl_linux_resolve: + addi r15, -72, r15 ! make room on the stack + pt _dl_linux_resolver, tr0 + st.q r15, 0, r2 ! save regs + st.q r15, 8, r3 + st.q r15, 16, r4 + st.q r15, 24, r5 + st.q r15, 32, r6 + st.q r15, 40, r7 + st.q r15, 48, r8 + st.q r15, 56, r9 + st.q r15, 64, r18 + +#ifdef HAVE_FPU + addi r15, -48, r15 ! make room for FP regs + fst.d r15, 0, dr0 ! save FP regs + fst.d r15, 8, dr2 + fst.d r15, 16, dr4 + fst.d r15, 24, dr6 + fst.d r15, 32, dr8 + fst.d r15, 40, dr10 +#endif + + /* + * Args for _dl_linux_resolver(), set in r17/r21 by PLT code + */ + + add r17, r63, r2 ! link map address + add r21, r63, r3 ! GOT offset + blink tr0, r18 ! call _dl_linux_resolver() + ptabs/l r2, tr0 ! save result = addr of function called + +#ifdef HAVE_FPU + fld.d r15, 0, dr0 ! restore FP regs + fld.d r15, 8, dr2 + fld.d r15, 16, dr4 + fld.d r15, 24, dr6 + fld.d r15, 32, dr8 + fld.d r15, 40, dr10 + addi r15, 48, r15 +#endif + + ld.q r15, 0, r2 ! restore regs + ld.q r15, 8, r3 + ld.q r15, 16, r4 + ld.q r15, 24, r5 + ld.q r15, 32, r6 + ld.q r15, 40, r7 + ld.q r15, 48, r8 + ld.q r15, 56, r9 + ld.q r15, 64, r18 + + addi r15, 72, r15 + blink tr0, r63 ! jump to function address + + .size _dl_linux_resolve, . - _dl_linux_resolve + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/sparc/dl-debug.h b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/sparc/dl-debug.h new file mode 100644 index 00000000..1249f779 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/sparc/dl-debug.h @@ -0,0 +1,40 @@ +/* vi: set sw=4 ts=4: */ +/* sparc ELF shared library loader suppport + * + * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald, + * David Engel, Hongjiu Lu and Mitch D'Souza + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. The name of the above contributors may not be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +static const char * _dl_reltypes_tab[] = { + "R_SPARC_NONE", "R_SPARC_8", + "R_SPARC_16", "R_SPARC_32", "R_SPARC_DISP8", "R_SPARC_DISP16", + "R_SPARC_DISP32", "R_SPARC_WDISP30", "R_SPARC_WDISP22", + "R_SPARC_HI22", "R_SPARC_22", "R_SPARC_13", "R_SPARC_LO10", + "R_SPARC_GOT10", "R_SPARC_GOT13", "R_SPARC_GOT22", "R_SPARC_PC10", + "R_SPARC_PC22", "R_SPARC_WPLT30", "R_SPARC_COPY", + "R_SPARC_GLOB_DAT", "R_SPARC_JMP_SLOT", "R_SPARC_RELATIVE", + "R_SPARC_UA32" +}; diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/sparc/dl-startup.h b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/sparc/dl-startup.h new file mode 100644 index 00000000..1abad112 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/sparc/dl-startup.h @@ -0,0 +1,78 @@ +/* Any assembly language/system dependent hacks needed to setup boot1.c so it + * will work as expected and cope with whatever platform specific wierdness is + * needed for this architecture. See arm/boot1_arch.h for an example of what + * can be done. + */ + +__asm__ ("\ + .text\n\ + .global _start\n\ + .type _start,%function\n\ + .align 32\n\ + .register %g2, #scratch\n\ +_start:\n\ + /* Allocate space for functions to drop their arguments. */\n\ + sub %sp, 6*4, %sp\n\ + /* Pass pointer to argument block to _dl_start. */\n\ + call _dl_start\n\ + add %sp, 22*4, %o0\n\ + /* FALTHRU */\n\ + .globl _dl_start_user\n\ + .type _dl_start_user, @function\n\ +_dl_start_user:\n\ + /* Load the PIC register. */\n\ +1: call 2f\n\ + sethi %hi(_GLOBAL_OFFSET_TABLE_-(1b-.)), %l7\n\ +2: or %l7, %lo(_GLOBAL_OFFSET_TABLE_-(1b-.)), %l7\n\ + add %l7, %o7, %l7\n\ + /* Save the user entry point address in %l0 */\n\ + mov %o0, %l0\n\ + /* See if we were run as a command with the executable file name as an\n\ + extra leading argument. If so, adjust the contents of the stack. */\n\ + sethi %hi(_dl_skip_args), %g2\n\ + or %g2, %lo(_dl_skip_args), %g2\n\ + ld [%l7+%g2], %i0\n\ + ld [%i0], %i0\n\ + tst %i0\n\ + /* Pass our finalizer function to the user in %g1. */\n\ + sethi %hi(_dl_fini), %g1\n\ + or %g1, %lo(_dl_fini), %g1\n\ + ld [%l7+%g1], %g1\n\ + /* Jump to the user's entry point and deallocate the extra stack we got. */\n\ + jmp %l0\n\ + add %sp, 6*4, %sp\n\ + .size _dl_start_user, . - _dl_start_user\n\ + .previous\n\ +"); + +/* + * Get a pointer to the argv array. On many platforms this can be just + * the address of the first argument, on other platforms we need to + * do something a little more subtle here. We assume that argc is stored + * at the word just below the argvp that we return here. + */ +#define GET_ARGV(ARGVP, ARGS) ARGVP = (((unsigned long *) ARGS) + 1) + +/* + * Here is a macro to perform a relocation. This is only used when + * bootstrapping the dynamic loader. + */ +#define PERFORM_BOOTSTRAP_RELOC(RELP,REL,SYMBOL,LOAD,SYMTAB) \ +switch(ELF_R_TYPE((RELP)->r_info)) { \ + case R_SPARC_32: \ + case R_SPARC_GLOB_DAT: \ + *REL = SYMBOL + (RELP)->r_addend; \ + break; \ + case R_SPARC_JMP_SLOT: \ + REL[1] = 0x03000000 | ((SYMBOL >> 10) & 0x3fffff); \ + REL[2] = 0x81c06000 | (SYMBOL & 0x3ff); \ + break; \ + case R_SPARC_NONE: \ + case R_SPARC_WDISP30: \ + break; \ + case R_SPARC_RELATIVE: \ + *REL += (unsigned int) LOAD + (RELP)->r_addend; \ + break; \ + default: \ + _dl_exit(1); \ +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/sparc/dl-syscalls.h b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/sparc/dl-syscalls.h new file mode 100644 index 00000000..996bb87c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/sparc/dl-syscalls.h @@ -0,0 +1,6 @@ +/* We can't use the real errno in ldso, since it has not yet + * been dynamicly linked in yet. */ +#include "sys/syscall.h" +extern int _dl_errno; +#undef __set_errno +#define __set_errno(X) {(_dl_errno) = (X);} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/sparc/dl-sysdep.h b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/sparc/dl-sysdep.h new file mode 100644 index 00000000..d35a3914 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/sparc/dl-sysdep.h @@ -0,0 +1,164 @@ +/* vi: set sw=4 ts=4: */ +/* + * Various assembly language/system dependent hacks that are required + * so that we can minimize the amount of platform specific code. + * Copyright (C) 2000-2004 by Erik Andersen + */ + +/* Define this if the system uses RELOCA. */ +#define ELF_USES_RELOCA +#include +/* + * Initialization sequence for a GOT. For the Sparc, this points to the + * PLT, and we need to initialize a couple of the slots. The PLT should + * look like: + * + * save %sp, -64, %sp + * call _dl_linux_resolve + * nop + * .word implementation_dependent + */ +#define INIT_GOT(GOT_BASE,MODULE) \ +{ \ + GOT_BASE[0] = 0x9de3bfc0; /* save %sp, -64, %sp */ \ + GOT_BASE[1] = 0x40000000 | (((unsigned int) _dl_linux_resolve - (unsigned int) GOT_BASE - 4) >> 2); \ + GOT_BASE[2] = 0x01000000; /* nop */ \ + GOT_BASE[3] = (int) MODULE; \ +} + +/* Here we define the magic numbers that this dynamic loader should accept + * Note that SPARCV9 doesn't use EM_SPARCV9 since the userland is still 32-bit. + */ +#if defined(__sparc_v9__) +#define MAGIC1 EM_SPARC32PLUS +#else +#define MAGIC1 EM_SPARC +#endif + +#undef MAGIC2 + +/* Used for error messages */ +#define ELF_TARGET "sparc" + +/* Need bootstrap relocations */ +#define ARCH_NEEDS_BOOTSTRAP_RELOCS + +struct elf_resolve; +unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_entry); + +/* + * Define this if you want a dynamic loader that works on Solaris. + */ + +#ifndef COMPILE_ASM +/* Cheap modulo implementation, taken from arm/ld_sysdep.h. */ +static __always_inline unsigned long +sparc_mod(unsigned long m, unsigned long p) +{ + unsigned long i, t, inc; + + i = p; + t = 0; + + while (!(i & (1 << 31))) { + i <<= 1; + t++; + } + + t--; + + for (inc = t; inc > 2; inc--) { + i = p << inc; + + if (i & (1 << 31)) + break; + + while (m >= i) { + m -= i; + i <<= 1; + if (i & (1 << 31)) + break; + if (i < p) + break; + } + } + + while (m >= p) + m -= p; + + return m; +} + +#define do_rem(result, n, base) ((result) = sparc_mod(n, base)) +#endif + +/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry, so + PLT entries should not be allowed to define the value. + ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to one + of the main executable's symbols, as for a COPY reloc. */ +#define elf_machine_type_class(type) \ + ((((type) == R_SPARC_JMP_SLOT || (type) == R_SPARC_TLS_DTPMOD32 \ + || (type) == R_SPARC_TLS_DTPOFF32 || (type) == R_SPARC_TLS_TPOFF32) \ + * ELF_RTYPE_CLASS_PLT) \ + | (((type) == R_SPARC_COPY) * ELF_RTYPE_CLASS_COPY)) + +/* The SPARC overlaps DT_RELA and DT_PLTREL. */ +#define ELF_MACHINE_PLTREL_OVERLAP 1 + +/* We have to do this because elf_machine_{dynamic,load_address} can be + invoked from functions that have no GOT references, and thus the compiler + has no obligation to load the PIC register. */ +#define LOAD_PIC_REG(PIC_REG) \ +do { register Elf32_Addr pc __asm__("o7"); \ + __asm__("sethi %%hi(_GLOBAL_OFFSET_TABLE_-4), %1\n\t" \ + "call 1f\n\t" \ + "add %1, %%lo(_GLOBAL_OFFSET_TABLE_+4), %1\n" \ + "1:\tadd %1, %0, %1" \ + : "=r" (pc), "=r" (PIC_REG)); \ +} while (0) + +/* Return the link-time address of _DYNAMIC. Conveniently, this is the + first element of the GOT. This must be inlined in a function which + uses global data. */ +static __always_inline Elf32_Addr +elf_machine_dynamic (void) +{ + register Elf32_Addr *got __asm__ ("%l7"); + + LOAD_PIC_REG (got); + + return *got; +} + +/* Return the run-time load address of the shared object. */ +static __always_inline Elf32_Addr +elf_machine_load_address (void) +{ + register Elf32_Addr *pc __asm__ ("%o7"), *got __asm__ ("%l7"); + + __asm__ ("sethi %%hi(_GLOBAL_OFFSET_TABLE_-4), %1\n\t" + "call 1f\n\t" + " add %1, %%lo(_GLOBAL_OFFSET_TABLE_+4), %1\n\t" + "call _DYNAMIC\n\t" + "call _GLOBAL_OFFSET_TABLE_\n" + "1:\tadd %1, %0, %1\n\t" : "=r" (pc), "=r" (got)); + + /* got is now l_addr + _GLOBAL_OFFSET_TABLE_ + *got is _DYNAMIC + pc[2]*4 is l_addr + _DYNAMIC - (long)pc - 8 + pc[3]*4 is l_addr + _GLOBAL_OFFSET_TABLE_ - (long)pc - 12 */ + return (Elf32_Addr) got - *got + (pc[2] - pc[3]) * 4 - 4; +} + +static __always_inline void +elf_machine_relative (Elf32_Addr load_off, const Elf32_Addr rel_addr, + Elf32_Word relative_count) +{ + Elf32_Rela * rpnt = (void *)rel_addr; + --rpnt; + do { + Elf32_Addr *const reloc_addr = (void *) (load_off + (++rpnt)->r_offset); + + *reloc_addr = load_off + rpnt->r_addend; + } while (--relative_count); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/sparc/elfinterp.c b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/sparc/elfinterp.c new file mode 100644 index 00000000..c684378c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/sparc/elfinterp.c @@ -0,0 +1,371 @@ +/* vi: set sw=4 ts=4: */ +/* sparc ELF shared library loader suppport + * + * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald, + * David Engel, Hongjiu Lu and Mitch D'Souza + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. The name of the above contributors may not be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* Program to load an ELF binary on a linux system, and run it. +References to symbols in sharable libraries can be resolved by either +an ELF sharable library or a linux style of shared library. */ + +/* Disclaimer: I have never seen any AT&T source code for SVr4, nor have + I ever taken any courses on internals. This program was developed using + information available through the book "UNIX SYSTEM V RELEASE 4, + Programmers guide: Ansi C and Programming Support Tools", which did + a more than adequate job of explaining everything required to get this + working. */ + +/* Some SPARC opcodes we need to use for self-modifying code. */ +#define OPCODE_NOP 0x01000000 /* nop */ +#define OPCODE_CALL 0x40000000 /* call ?; add PC-rel word address */ +#define OPCODE_SETHI_G1 0x03000000 /* sethi ?, %g1; add value>>10 */ +#define OPCODE_JMP_G1 0x81c06000 /* jmp %g1+?; add lo 10 bits of value */ +#define OPCODE_SAVE_SP 0x9de3bfa8 /* save %sp, -(16+6)*4, %sp */ +#define OPCODE_BA 0x30800000 /* b,a ?; add PC-rel word address */ + +extern int _dl_linux_resolve(void); + +unsigned long +_dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry) +{ + ELF_RELOC *this_reloc; + char *strtab; + ElfW(Sym) *symtab; + int symtab_index; + char *rel_addr; + char *new_addr; + char **got_addr; + ElfW(Addr) instr_addr; + char *symname; + + rel_addr = (char *)tpnt->dynamic_info[DT_JMPREL]; + /* + * Generate the correct relocation index into the .rela.plt section. + */ + reloc_entry = (reloc_entry >> 10) - 0xc; + + this_reloc = (ELF_RELOC *)(rel_addr + reloc_entry); + symtab_index = ELF_R_SYM(this_reloc->r_info); + + symtab = (ElfW(Sym) *)tpnt->dynamic_info[DT_SYMTAB]; + strtab = (char *)tpnt->dynamic_info[DT_STRTAB]; + symname = strtab + symtab[symtab_index].st_name; + + /* Address of the jump instruction to fix up. */ + instr_addr = (this_reloc->r_offset + tpnt->loadaddr); + got_addr = (char **)instr_addr; + + /* Get the address of the GOT entry */ + new_addr = _dl_find_hash(symname, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL); + if (unlikely(!new_addr)) { + _dl_dprintf(2, "%s: Can't resolve symbol '%s'\n", _dl_progname, symname); + _dl_exit(1); + } + +#if defined (__SUPPORT_LD_DEBUG__) + if ((unsigned long)got_addr < 0x40000000) { + if (_dl_debug_bindings) { + _dl_dprintf(_dl_debug_file, "\nresolve function: %s", symname); + if (_dl_debug_detail) + _dl_dprintf(_dl_debug_file, + "\tpatched: %x ==> %x @ %x\n", + *got_addr, new_addr, got_addr); + } + } + if (!_dl_debug_nofixups) +#endif + { + got_addr[1] = (char *) (OPCODE_SETHI_G1 | (((unsigned int) new_addr >> 10) & 0x3fffff)); + got_addr[2] = (char *) (OPCODE_JMP_G1 | ((unsigned int) new_addr & 0x3ff)); + } + + return (unsigned long)new_addr; +} + +static int +_dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope, + unsigned long rel_addr, unsigned long rel_size, + int (*reloc_fnc)(struct elf_resolve *tpnt, struct dyn_elf *scope, + ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab)) +{ + unsigned int i; + char *strtab; + ElfW(Sym) *symtab; + ELF_RELOC *rpnt; + int symtab_index; + + /* Parse the relocation information. */ + rpnt = (ELF_RELOC *)rel_addr; + rel_size /= sizeof(ELF_RELOC); + + symtab = (ElfW(Sym) *)tpnt->dynamic_info[DT_SYMTAB]; + strtab = (char *)tpnt->dynamic_info[DT_STRTAB]; + + for (i = 0; i < rel_size; i++, rpnt++) { + int res; + + symtab_index = ELF_R_SYM(rpnt->r_info); + + debug_sym(symtab, strtab, symtab_index); + debug_reloc(symtab, strtab, rpnt); + + res = reloc_fnc(tpnt, scope, rpnt, symtab, strtab); + + if (res == 0) + continue; + + _dl_dprintf(2, "\n%s: ", _dl_progname); + + if (symtab_index) + _dl_dprintf(2, "symbol '%s': ", + strtab + symtab[symtab_index].st_name); + + if (unlikely(res < 0)) { + int reloc_type = ELF_R_TYPE(rpnt->r_info); + + _dl_dprintf(2, "can't handle reloc type " +#if defined (__SUPPORT_LD_DEBUG__) + "%s\n", _dl_reltypes(reloc_type)); +#else + "%x\n", reloc_type); +#endif + _dl_exit(-res); + } else if (unlikely(res > 0)) { + _dl_dprintf(2, "can't resolve symbol\n"); + return res; + } + } + + return 0; +} + +static int +_dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, + ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab) +{ + int reloc_type; + int symtab_index; + char *symname; + struct elf_resolve *tls_tpnt = NULL; + struct symbol_ref sym_ref; + ElfW(Addr) *reloc_addr; + ElfW(Addr) symbol_addr; +#if defined (__SUPPORT_LD_DEBUG__) + ElfW(Addr) old_val; +#endif + + reloc_addr = (ElfW(Addr)*)(tpnt->loadaddr + (unsigned long)rpnt->r_offset); + reloc_type = ELF_R_TYPE(rpnt->r_info); + symtab_index = ELF_R_SYM(rpnt->r_info); + sym_ref.sym = &symtab[symtab_index]; + sym_ref.tpnt = NULL; + symbol_addr = 0; + symname = strtab + sym_ref.sym->st_name; + + if (symtab_index) { + symbol_addr = (ElfW(Addr))_dl_find_hash(symname, scope, tpnt, + elf_machine_type_class(reloc_type), &sym_ref); + /* + * We want to allow undefined references to weak symbols - this + * might have been intentional. We should not be linking local + * symbols here, so all bases should be covered. + */ + if (unlikely(!symbol_addr && (ELF_ST_TYPE(sym_ref.sym->st_info) != STT_TLS) + && (ELF_ST_BIND(sym_ref.sym->st_info) != STB_WEAK))) { + /* This may be non-fatal if called from dlopen. */ + return 1; + + } + tls_tpnt = sym_ref.tpnt; + } else { + /* Relocs against STN_UNDEF are usually treated as using a + * symbol value of zero, and using the module containing the + * reloc itself. */ + symbol_addr = sym_ref.sym->st_value; + tls_tpnt = tpnt; + } + +#if defined (__SUPPORT_LD_DEBUG__) + old_val = *reloc_addr; +#endif + + symbol_addr += rpnt->r_addend; /* Assume copy relocs have zero addend. */ + + switch (reloc_type) { + case R_SPARC_NONE: + break; + + case R_SPARC_DISP32: + *reloc_addr = symbol_addr - (unsigned int) reloc_addr; + break; + + case R_SPARC_LO10: + if (!symbol_addr) + symbol_addr = tpnt->loadaddr + rpnt->r_addend; + else + symbol_addr += rpnt->r_addend; + *reloc_addr = (*reloc_addr & ~0x3ff) | (symbol_addr & 0x3ff); + break; + + case R_SPARC_GLOB_DAT: + case R_SPARC_32: + *reloc_addr = symbol_addr; + break; + + case R_SPARC_JMP_SLOT: + reloc_addr[1] = OPCODE_SETHI_G1 | (( symbol_addr >> 10 ) & 0x3fffff); + reloc_addr[2] = OPCODE_JMP_G1 | ( symbol_addr & 0x3ff ); + break; + + case R_SPARC_RELATIVE: + *reloc_addr += tpnt->loadaddr + rpnt->r_addend; + break; + + case R_SPARC_WDISP30: + *reloc_addr = (*reloc_addr & 0xc0000000)| + ((symbol_addr - (unsigned int) reloc_addr) >> 2); + break; + + case R_SPARC_HI22: + if (!symbol_addr) + symbol_addr = tpnt->loadaddr + rpnt->r_addend; + else + symbol_addr += rpnt->r_addend; + *reloc_addr = (*reloc_addr & 0xffc00000) | (symbol_addr >> 10); + break; + + case R_SPARC_COPY: + if (symbol_addr) { +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_move) + _dl_dprintf(_dl_debug_file, + "\t%s move %d bytes from %x to %x\n", + symname, sym_ref.sym->st_size, + symbol_addr, reloc_addr); +#endif + + _dl_memcpy((char *)reloc_addr, + (char *)symbol_addr, + sym_ref.sym->st_size); + } else + _dl_dprintf(_dl_debug_file, "no symbol_addr to copy !?\n"); + break; +#if defined USE_TLS && USE_TLS + case R_SPARC_TLS_DTPMOD32: + *reloc_addr = tls_tpnt->l_tls_modid; + break; + + case R_SPARC_TLS_DTPOFF32: + /* During relocation all TLS symbols are defined and used. + * Therefore the offset is already correct. */ + *reloc_addr = sym_ref.sym->st_value + rpnt->r_addend; + break; + + case R_SPARC_TLS_TPOFF32: + /* The offset is negative, forward from the thread pointer. + * We know the offset of the object the symbol is contained in. + * It is a negative value which will be added to the + * thread pointer. */ + CHECK_STATIC_TLS ((struct link_map *) tls_tpnt); + *reloc_addr = sym_ref.sym->st_value - tls_tpnt->l_tls_offset + rpnt->r_addend; + break; +#endif + default: + return -1; /* Calls _dl_exit(1). */ + } + +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_reloc && _dl_debug_detail) + _dl_dprintf(_dl_debug_file, "\tpatched: %x ==> %x @ %x\n", + old_val, *reloc_addr, reloc_addr); +#endif + + return 0; +} + +#undef __SPARC_LAZY_RELOC_WORKS +#ifdef __SPARC_LAZY_RELOC_WORKS +static int +_dl_do_lazy_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, + ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab) +{ + int reloc_type; + int symtab_index; + ElfW(Addr) *reloc_addr; +#if defined (__SUPPORT_LD_DEBUG__) + ElfW(Addr) old_val; +#endif + + (void)scope; + symtab_index = ELF_R_SYM(rpnt->r_info); + (void)strtab; + + reloc_addr = (ElfW(Addr)*)(tpnt->loadaddr + rpnt->r_offset); + reloc_type = ELF_R_TYPE(rpnt->r_info); + +#if defined (__SUPPORT_LD_DEBUG__) + old_val = *reloc_addr; +#endif + + switch (reloc_type) { + case R_SPARC_NONE: + break; + case R_SPARC_JMP_SLOT: + break; + default: + _dl_exit(1); + } + +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_reloc && _dl_debug_detail) + _dl_dprintf(_dl_debug_file, "\tpatched_lazy: %x ==> %x @ %x\n", + old_val, *reloc_addr, reloc_addr); +#endif + + return 0; +} +#endif + +void +_dl_parse_lazy_relocation_information(struct dyn_elf *rpnt, + unsigned long rel_addr, + unsigned long rel_size) +{ +#ifdef __SPARC_LAZY_RELOC_WORKS + (void)_dl_parse(rpnt->dyn, NULL, rel_addr, rel_size, _dl_do_lazy_reloc); +#else + _dl_parse_relocation_information(rpnt, rel_addr, rel_size); +#endif +} + +int +_dl_parse_relocation_information(struct dyn_elf *rpnt, + unsigned long rel_addr, + unsigned long rel_size) +{ + return _dl_parse(rpnt->dyn, rpnt->dyn->symbol_scope, rel_addr, rel_size, _dl_do_reloc); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/sparc/resolve.S b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/sparc/resolve.S new file mode 100644 index 00000000..253400ae --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/sparc/resolve.S @@ -0,0 +1,22 @@ +/* + * These are various helper routines that are needed to run an ELF image. + */ + +.text +.align 16 + +.globl _dl_linux_resolve +.type _dl_linux_resolve,#function +_dl_linux_resolve: + /* + * Call the resolver - pass the address of the PLT so that we can + * figure out which module we are in. + */ + mov %o7,%o1 + call _dl_linux_resolver + mov %g1,%o0 + + jmpl %o0,%o7 + restore +.LFE2: + .size _dl_linux_resolve,.LFE2-_dl_linux_resolve diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/x86_64/dl-debug.h b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/x86_64/dl-debug.h new file mode 100644 index 00000000..d605a038 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/x86_64/dl-debug.h @@ -0,0 +1,39 @@ +/* vi: set sw=4 ts=4: */ +/* x86_64 debug code for ELF shared library loader suppport + * + * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald, + * David Engel, Hongjiu Lu and Mitch D'Souza + * Copyright (C) 2001-2004 Erik Andersen + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. The name of the above contributors may not be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +static const char *_dl_reltypes_tab[] = { + [ 0] "R_X86_64_NONE", "R_X86_64_64", "R_X86_64_PC32", "R_X86_64_GOT32", + [ 4] "R_X86_64_PLT32", "R_X86_64_COPY", "R_X86_64_GLOB_DAT", "R_X86_64_JUMP_SLOT", + [ 8] "R_X86_64_RELATIVE", "R_X86_64_GOTPCREL", "R_X86_64_32", "R_X86_64_32S", + [12] "R_X86_64_16", "R_X86_64_PC16", "R_X86_64_8", "R_X86_64_PC8", + [16] "R_X86_64_DTPMOD64", "R_X86_64_DTPOFF64", "R_X86_64_TPOFF64", "R_X86_64_TLSGD", + [20] "R_X86_64_TLSLD", "R_X86_64_DTPOFF32", "R_X86_64_GOTTPOFF", "R_X86_64_TPOFF32" +}; diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/x86_64/dl-startup.h b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/x86_64/dl-startup.h new file mode 100644 index 00000000..29fb70a0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/x86_64/dl-startup.h @@ -0,0 +1,69 @@ +/* vi: set sw=4 ts=4: */ +/* + * Architecture specific code used by dl-startup.c + * Copyright (C) 2000-2005 by Erik Andersen + * Copyright (C) 2005 by Mike Frysinger + * + * Parts taken from glibc/sysdeps/x86_64/dl-machine.h + */ +__asm__ ( + " .text\n" + " .global _start\n" + " .type _start,%function\n" + "_start:\n" + " movq %rsp, %rdi\n" + " call _dl_start\n" + " # Save the user entry point address in %r12.\n" + " movq %rax, %r12\n" + " # See if we were run as a command with the executable file\n" + " # name as an extra leading argument.\n" + " movl _dl_skip_args(%rip), %eax\n" + " # Pop the original argument count.\n" + " popq %rdx\n" + " # Adjust the stack pointer to skip _dl_skip_args words.\n" + " leaq (%rsp,%rax,8), %rsp\n" + " # Subtract _dl_skip_args from argc.\n" + " subl %eax, %edx\n" + " # Push argc back on the stack.\n" + " pushq %rdx\n" + " # Pass our finalizer function to the user in %rdx, as per ELF ABI.\n" + " leaq _dl_fini(%rip), %rdx\n" + " # Jump to the user's entry point.\n" + " jmp *%r12\n" + " .size _start,.-_start\n" + " .previous\n" +); + +/* Get a pointer to the argv array. On many platforms this can be just + * the address of the first argument, on other platforms we need to + * do something a little more subtle here. */ +#define GET_ARGV(ARGVP, ARGS) ARGVP = (((unsigned long*) ARGS)+1) + +/* Handle relocation of the symbols in the dynamic loader. */ +static __always_inline +void PERFORM_BOOTSTRAP_RELOC(ELF_RELOC *rpnt, ElfW(Addr) *reloc_addr, + ElfW(Addr) symbol_addr, ElfW(Addr) load_addr, ElfW(Sym) *sym) +{ + switch (ELF_R_TYPE(rpnt->r_info)) { + case R_X86_64_GLOB_DAT: + case R_X86_64_JUMP_SLOT: + *reloc_addr = symbol_addr + rpnt->r_addend; + break; + case R_X86_64_DTPMOD64: + *reloc_addr = 1; + break; + case R_X86_64_NONE: + case R_X86_64_DTPOFF64: + break; + case R_X86_64_TPOFF64: + *reloc_addr = sym->st_value + rpnt->r_addend - symbol_addr; + break; + /* Start: added by aw11 */ + case R_X86_64_RELATIVE: + *reloc_addr += load_addr; + break; + /* End: added by aw11 */ + default: + _dl_exit(1); + } +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/x86_64/dl-syscalls.h b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/x86_64/dl-syscalls.h new file mode 100644 index 00000000..996bb87c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/x86_64/dl-syscalls.h @@ -0,0 +1,6 @@ +/* We can't use the real errno in ldso, since it has not yet + * been dynamicly linked in yet. */ +#include "sys/syscall.h" +extern int _dl_errno; +#undef __set_errno +#define __set_errno(X) {(_dl_errno) = (X);} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/x86_64/dl-sysdep.h b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/x86_64/dl-sysdep.h new file mode 100644 index 00000000..ae3542ae --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/x86_64/dl-sysdep.h @@ -0,0 +1,112 @@ +/* vi: set sw=4 ts=4: */ +/* yoinked from glibc/sysdeps/x86_64/dl-machine.h */ +/* Machine-dependent ELF dynamic relocation inline functions. x86-64 version. + Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Andreas Jaeger . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Define this if the system uses RELOCA. */ +#define ELF_USES_RELOCA +#include +#include +/* Initialization sequence for the GOT. */ +#define INIT_GOT(GOT_BASE,MODULE) \ +do { \ + GOT_BASE[2] = (unsigned long) _dl_linux_resolve; \ + GOT_BASE[1] = (unsigned long) MODULE; \ +} while(0) + +/* Here we define the magic numbers that this dynamic loader should accept */ +#define MAGIC1 EM_X86_64 +#undef MAGIC2 + +/* Used for error messages */ +#define ELF_TARGET "x86_64" + +struct elf_resolve; +extern unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_entry); + +/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry or + TLS variable, so undefined references should not be allowed to + define the value. + ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to one + of the main executable's symbols, as for a COPY reloc. */ +#define elf_machine_type_class(type) \ + ((((type) == R_X86_64_JUMP_SLOT \ + || (type) == R_X86_64_DTPMOD64 \ + || (type) == R_X86_64_DTPOFF64 \ + || (type) == R_X86_64_TPOFF64) \ + * ELF_RTYPE_CLASS_PLT) \ + | (((type) == R_X86_64_COPY) * ELF_RTYPE_CLASS_COPY)) + +/* Return the link-time address of _DYNAMIC. Conveniently, this is the + first element of the GOT. This must be inlined in a function which + uses global data. */ +static __always_inline Elf64_Addr __attribute__ ((unused)) +elf_machine_dynamic (void) +{ + Elf64_Addr addr; + + /* This works because we have our GOT address available in the small PIC + model. */ + addr = (Elf64_Addr) &_DYNAMIC; + + return addr; +} + + +/* Return the run-time load address of the shared object. */ +static __always_inline Elf64_Addr __attribute__ ((unused)) +elf_machine_load_address (void) +{ + register Elf64_Addr addr, tmp; + + /* The easy way is just the same as on x86: + leaq _dl_start, %0 + leaq _dl_start(%%rip), %1 + subq %0, %1 + but this does not work with binutils since we then have + a R_X86_64_32S relocation in a shared lib. + + Instead we store the address of _dl_start in the data section + and compare it with the current value that we can get via + an RIP relative addressing mode. */ + + __asm__ ("movq 1f(%%rip), %1\n" + "0:\tleaq _dl_start(%%rip), %0\n\t" + "subq %1, %0\n\t" + ".section\t.data\n" + "1:\t.quad _dl_start\n\t" + ".previous\n\t" + : "=r" (addr), "=r" (tmp) : : "cc"); + + return addr; +} + +static __always_inline void +elf_machine_relative(Elf64_Addr load_off, const Elf64_Addr rel_addr, + Elf64_Word relative_count) +{ + Elf64_Rela *rpnt = (Elf64_Rela*)rel_addr; + --rpnt; + do { + Elf64_Addr *const reloc_addr = (Elf64_Addr*)(load_off + (++rpnt)->r_offset); + + *reloc_addr = load_off + rpnt->r_addend; + } while (--relative_count); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/x86_64/elfinterp.c b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/x86_64/elfinterp.c new file mode 100644 index 00000000..664c9ee8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/x86_64/elfinterp.c @@ -0,0 +1,339 @@ +/* vi: set sw=4 ts=4: */ +/* x86_64 ELF shared library loader suppport + * + * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald, + * David Engel, Hongjiu Lu and Mitch D'Souza + * Copyright (C) 2001-2004 Erik Andersen + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. The name of the above contributors may not be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "ldso.h" + +/* Program to load an ELF binary on a linux system, and run it. + References to symbols in sharable libraries can be resolved by either + an ELF sharable library or a linux style of shared library. */ + +/* Disclaimer: I have never seen any AT&T source code for SVr4, nor have + I ever taken any courses on internals. This program was developed using + information available through the book "UNIX SYSTEM V RELEASE 4, + Programmers guide: Ansi C and Programming Support Tools", which did + a more than adequate job of explaining everything required to get this + working. */ + +extern int _dl_linux_resolve(void); + +unsigned long +_dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry) +{ + ELF_RELOC *this_reloc; + char *strtab; + ElfW(Sym) *symtab; + int symtab_index; + char *rel_addr; + char *new_addr; + char **got_addr; + ElfW(Addr) instr_addr; + char *symname; + + rel_addr = (char *)tpnt->dynamic_info[DT_JMPREL]; + this_reloc = (ELF_RELOC *)(rel_addr + reloc_entry); + symtab_index = ELF_R_SYM(this_reloc->r_info); + + symtab = (ElfW(Sym) *)tpnt->dynamic_info[DT_SYMTAB]; + strtab = (char *)tpnt->dynamic_info[DT_STRTAB]; + symname = strtab + symtab[symtab_index].st_name; + + /* Address of the jump instruction to fix up. */ + instr_addr = (this_reloc->r_offset + tpnt->loadaddr); + got_addr = (char **)instr_addr; + + /* Get the address of the GOT entry. */ + new_addr = _dl_find_hash(symname, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL); + if (unlikely(!new_addr)) { + _dl_dprintf(2, "%s: Can't resolve symbol '%s'\n", _dl_progname, symname); + _dl_exit(1); + } + +#if defined (__SUPPORT_LD_DEBUG__) + if ((unsigned long)got_addr < 0x40000000) { + if (_dl_debug_bindings) { + _dl_dprintf(_dl_debug_file, "\nresolve function: %s", symname); + if (_dl_debug_detail) + _dl_dprintf(_dl_debug_file, + "\tpatched: %x ==> %x @ %x\n", + *got_addr, new_addr, got_addr); + } + } + if (!_dl_debug_nofixups) +#endif + *got_addr = new_addr; + + return (unsigned long)new_addr; +} + +static int +_dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope, + unsigned long rel_addr, unsigned long rel_size, + int (*reloc_fnc)(struct elf_resolve *tpnt, struct dyn_elf *scope, + ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab)) +{ + unsigned int i; + char *strtab; + ElfW(Sym) *symtab; + ELF_RELOC *rpnt; + int symtab_index; + + /* Parse the relocation information. */ + rpnt = (ELF_RELOC *)rel_addr; + rel_size /= sizeof(ELF_RELOC); + + symtab = (ElfW(Sym) *)tpnt->dynamic_info[DT_SYMTAB]; + strtab = (char *)tpnt->dynamic_info[DT_STRTAB]; + + for (i = 0; i < rel_size; i++, rpnt++) { + int res; + + symtab_index = ELF_R_SYM(rpnt->r_info); + + debug_sym(symtab, strtab, symtab_index); + debug_reloc(symtab, strtab, rpnt); + + res = reloc_fnc(tpnt, scope, rpnt, symtab, strtab); + + if (res == 0) + continue; + + _dl_dprintf(2, "\n%s: ", _dl_progname); + + if (symtab_index) + _dl_dprintf(2, "symbol '%s': ", + strtab + symtab[symtab_index].st_name); + + if (unlikely(res < 0)) { + int reloc_type = ELF_R_TYPE(rpnt->r_info); + + _dl_dprintf(2, "can't handle reloc type " +#if defined (__SUPPORT_LD_DEBUG__) + "%s\n", _dl_reltypes(reloc_type)); +#else + "%x\n", reloc_type); +#endif + _dl_exit(-res); + } else if (unlikely(res > 0)) { + _dl_dprintf(2, "can't resolve symbol\n"); + return res; + } + } + + return 0; +} + +static int +_dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, + ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab) +{ + int reloc_type; + int symtab_index; + char *symname; + struct elf_resolve *tls_tpnt = NULL; + struct symbol_ref sym_ref; + ElfW(Addr) *reloc_addr; + ElfW(Addr) symbol_addr; +#if defined (__SUPPORT_LD_DEBUG__) + ElfW(Addr) old_val; +#endif + + reloc_addr = (ElfW(Addr)*)(tpnt->loadaddr + (unsigned long)rpnt->r_offset); + reloc_type = ELF_R_TYPE(rpnt->r_info); + symtab_index = ELF_R_SYM(rpnt->r_info); + sym_ref.sym = &symtab[symtab_index]; + sym_ref.tpnt = NULL; + symbol_addr = 0; + symname = strtab + sym_ref.sym->st_name; + + if (symtab_index) { + symbol_addr = (ElfW(Addr))_dl_find_hash(symname, scope, tpnt, + elf_machine_type_class(reloc_type), &sym_ref); + /* + * We want to allow undefined references to weak symbols - this + * might have been intentional. We should not be linking local + * symbols here, so all bases should be covered. + */ + if (unlikely(!symbol_addr && (ELF_ST_TYPE(sym_ref.sym->st_info) != STT_TLS) + && (ELF_ST_BIND(sym_ref.sym->st_info) != STB_WEAK))) { + /* This may be non-fatal if called from dlopen. */ + return 1; + } + tls_tpnt = sym_ref.tpnt; + } else { + /* Relocs against STN_UNDEF are usually treated as using a + * symbol value of zero, and using the module containing the + * reloc itself. */ + symbol_addr = sym_ref.sym->st_value; + tls_tpnt = tpnt; + } + + +#if defined (__SUPPORT_LD_DEBUG__) + old_val = *reloc_addr; +#endif + + switch (reloc_type) { + case R_X86_64_NONE: + break; + + case R_X86_64_64: + *reloc_addr = symbol_addr + rpnt->r_addend; + break; + + case R_X86_64_PC32: + *reloc_addr = symbol_addr + rpnt->r_addend - rpnt->r_offset; + break; + + case R_X86_64_GLOB_DAT: + case R_X86_64_JUMP_SLOT: + *reloc_addr = symbol_addr + rpnt->r_addend; + break; + + /* handled by elf_machine_relative() + case R_X86_64_RELATIVE: + *reloc_addr = map->l_addr + rpnt->r_addend; + break; + */ +#if defined USE_TLS && USE_TLS + case R_X86_64_DTPMOD64: + *reloc_addr = tls_tpnt->l_tls_modid; + break; + case R_X86_64_DTPOFF64: + /* During relocation all TLS symbols are defined and used. + * Therefore the offset is already correct. */ + *reloc_addr = symbol_addr + rpnt->r_addend; + break; + case R_X86_64_TPOFF64: + /* The offset is negative, forward from the thread pointer. + * We know the offset of the object the symbol is contained in. + * It is a negative value which will be added to the + * thread pointer. */ + CHECK_STATIC_TLS ((struct link_map *) tls_tpnt); + *reloc_addr = symbol_addr - tls_tpnt->l_tls_offset + rpnt->r_addend; + break; +#endif + case R_X86_64_32: + *(unsigned int *) reloc_addr = symbol_addr + rpnt->r_addend; + /* XXX: should check for overflow eh ? */ + break; +#ifndef __DONE_BY_AW11__ + case R_X86_64_RELATIVE: + *reloc_addr += (unsigned long)tpnt->loadaddr; + /* XXX: should check for overflow eh ? */ + break; +#endif + + case R_X86_64_COPY: + if (symbol_addr) { +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_move) + _dl_dprintf(_dl_debug_file, + "\t%s move %d bytes from %x to %x\n", + symname, sym_ref.sym->st_size, + symbol_addr, reloc_addr); +#endif + + _dl_memcpy((char *)reloc_addr, + (char *)symbol_addr, + sym_ref.sym->st_size); + } else + _dl_dprintf(_dl_debug_file, "no symbol_addr to copy !?\n"); + break; + + default: + return -1; /* Calls _dl_exit(1). */ + } + +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_reloc && _dl_debug_detail) + _dl_dprintf(_dl_debug_file, "\tpatched: %x ==> %x @ %x\n", + old_val, *reloc_addr, reloc_addr); +#endif + + return 0; +} + +static int +_dl_do_lazy_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope, + ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab) +{ + int reloc_type; + int symtab_index; + ElfW(Addr) *reloc_addr; +#if defined (__SUPPORT_LD_DEBUG__) + ElfW(Addr) old_val; +#endif + + (void)scope; + symtab_index = ELF_R_SYM(rpnt->r_info); + (void)strtab; + + reloc_addr = (ElfW(Addr)*)(tpnt->loadaddr + rpnt->r_offset); + reloc_type = ELF_R_TYPE(rpnt->r_info); + +#if defined (__SUPPORT_LD_DEBUG__) + old_val = *reloc_addr; +#endif + + switch (reloc_type) { + case R_X86_64_NONE: + break; + case R_X86_64_JUMP_SLOT: + *reloc_addr += (unsigned long)tpnt->loadaddr; + break; + default: + _dl_exit(1); + } + +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_reloc && _dl_debug_detail) + _dl_dprintf(_dl_debug_file, "\tpatched_lazy: %x ==> %x @ %x\n", + old_val, *reloc_addr, reloc_addr); +#endif + + return 0; +} + +void +_dl_parse_lazy_relocation_information(struct dyn_elf *rpnt, + unsigned long rel_addr, + unsigned long rel_size) +{ + (void)_dl_parse(rpnt->dyn, NULL, rel_addr, rel_size, _dl_do_lazy_reloc); +} + +int +_dl_parse_relocation_information(struct dyn_elf *rpnt, + unsigned long rel_addr, + unsigned long rel_size) +{ + return _dl_parse(rpnt->dyn, rpnt->dyn->symbol_scope, rel_addr, rel_size, _dl_do_reloc); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/x86_64/resolve.S b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/x86_64/resolve.S new file mode 100644 index 00000000..ac1d1822 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/x86_64/resolve.S @@ -0,0 +1,62 @@ +/* + * This function is _not_ called directly. It is jumped to (so no return + * address is on the stack) when attempting to use a symbol that has not yet + * been resolved. The first time a jump symbol (such as a function call inside + * a shared library) is used (before it gets resolved) it will jump here to + * _dl_linux_resolve. When we get called the stack looks like this: + * reloc_entry + * tpnt + * + * This function saves all the registers, puts a copy of reloc_entry and tpnt + * on the stack (as function arguments) then make the function call + * _dl_linux_resolver(tpnt, reloc_entry). _dl_linux_resolver() figures out + * where the jump symbol is _really_ supposed to have jumped to and returns + * that to us. Once we have that, we overwrite tpnt with this fixed up + * address. We then clean up after ourselves, put all the registers back how we + * found them, then we jump to where the fixed up address, which is where the + * jump symbol that got us here really wanted to jump to in the first place. + * found them, then we jump to the fixed up address, which is where the jump + * symbol that got us here really wanted to jump to in the first place. + * -Erik Andersen + */ + +/* more info taken from glibc/sysdeps/x86_64/dl-trampoline.S */ + +.text + +.global _dl_linux_resolve +.type _dl_linux_resolve,%function + +_dl_linux_resolve: + subq $56,%rsp + /* Preserve registers otherwise clobbered. */ + movq %rax, (%rsp) + movq %rcx, 8(%rsp) + movq %rdx, 16(%rsp) + movq %rsi, 24(%rsp) + movq %rdi, 32(%rsp) + movq %r8, 40(%rsp) + movq %r9, 48(%rsp) + + movq 64(%rsp), %rsi /* Copy args pushed by PLT in register. */ + movq %rsi, %r11 /* Multiply by 24 */ + addq %r11, %rsi + addq %r11, %rsi + shlq $3, %rsi + movq 56(%rsp), %rdi /* %rdi: link_map, %rsi: reloc_offset */ + call _dl_linux_resolver /* Call resolver. */ + movq %rax, %r11 /* Save return value */ + + /* Get register content back. */ + movq 48(%rsp), %r9 + movq 40(%rsp), %r8 + movq 32(%rsp), %rdi + movq 24(%rsp), %rsi + movq 16(%rsp), %rdx + movq 8(%rsp), %rcx + movq (%rsp), %rax + + addq $72, %rsp /* Adjust stack(PLT did 2 pushes) */ + jmp *%r11 /* Jump to function address. */ + +.size _dl_linux_resolve,.-_dl_linux_resolve diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/xtensa/dl-debug.h b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/xtensa/dl-debug.h new file mode 100644 index 00000000..327defc0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/xtensa/dl-debug.h @@ -0,0 +1,61 @@ +/* vi: set sw=4 ts=4: */ +/* Xtensa ELF shared library loader suppport + * + * Copyright (C) 2007 Tensilica Inc. + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +static const char *_dl_reltypes_tab[] = +{ + "R_XTENSA_NONE", + "R_XTENSA_32", + "R_XTENSA_RTLD", + "R_XTENSA_GLOB_DAT", + "R_XTENSA_JMP_SLOT", + "R_XTENSA_RELATIVE", + "R_XTENSA_PLT", + "R_XTENSA_UNUSED7", + "R_XTENSA_OP0", + "R_XTENSA_OP1", + "R_XTENSA_OP2", + "R_XTENSA_ASM_EXPAND", + "R_XTENSA_ASM_SIMPLIFY", + "R_XTENSA_UNUSED13", + "R_XTENSA_UNUSED14", + "R_XTENSA_GNU_VTINHERIT", + "R_XTENSA_GNU_VTENTRY", + "R_XTENSA_DIFF8", + "R_XTENSA_DIFF16", + "R_XTENSA_DIFF32", + "R_XTENSA_SLOT0_OP", + "R_XTENSA_SLOT1_OP", + "R_XTENSA_SLOT2_OP", + "R_XTENSA_SLOT3_OP", + "R_XTENSA_SLOT4_OP", + "R_XTENSA_SLOT5_OP", + "R_XTENSA_SLOT6_OP", + "R_XTENSA_SLOT7_OP", + "R_XTENSA_SLOT8_OP", + "R_XTENSA_SLOT9_OP", + "R_XTENSA_SLOT10_OP", + "R_XTENSA_SLOT11_OP", + "R_XTENSA_SLOT12_OP", + "R_XTENSA_SLOT13_OP", + "R_XTENSA_SLOT14_OP", + "R_XTENSA_SLOT0_ALT", + "R_XTENSA_SLOT1_ALT", + "R_XTENSA_SLOT2_ALT", + "R_XTENSA_SLOT3_ALT", + "R_XTENSA_SLOT4_ALT", + "R_XTENSA_SLOT5_ALT", + "R_XTENSA_SLOT6_ALT", + "R_XTENSA_SLOT7_ALT", + "R_XTENSA_SLOT8_ALT", + "R_XTENSA_SLOT9_ALT", + "R_XTENSA_SLOT10_ALT", + "R_XTENSA_SLOT11_ALT", + "R_XTENSA_SLOT12_ALT", + "R_XTENSA_SLOT13_ALT", + "R_XTENSA_SLOT14_ALT" +}; diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/xtensa/dl-startup.h b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/xtensa/dl-startup.h new file mode 100644 index 00000000..8ae96240 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/xtensa/dl-startup.h @@ -0,0 +1,106 @@ +/* vi: set sw=4 ts=4: */ +/* + * Xtensa ELF code used by dl-startup.c. + * + * Copyright (C) 2007 Tensilica Inc. + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * Parts taken from glibc/sysdeps/xtensa/dl-machine.h. + */ + +__asm__ ( + " .text\n" + " .align 4\n" + " .global _start\n" + " .type _start, @function\n" + "_start:\n" + " # Compute load offset in a2: the GOT has not yet been relocated\n" + " # but the entries for local symbols contain the relative offsets\n" + " # and we can explicitly add the load offset in this code.\n" + " _call0 0f\n" + " .align 4\n" + "0: movi a3, _start+3\n" + " sub a2, a0, a3\n" + " # Make sure a0 is cleared to mark the top of stack.\n" + " movi a0, 0\n" + " # user_entry_point = _dl_start(pointer to argument block)\n" + " movi a4, _dl_start\n" + " mov a6, sp\n" + " add a4, a4, a2\n" + " callx4 a4\n" + " # Save user_entry_point so we can jump to it.\n" + " mov a3, a6\n" + " l32i a7, sp, 0 # load argc\n" + " # Load _dl_skip_args into a4.\n" + " movi a4, _dl_skip_args\n" + " l32i a4, a4, 0\n" + " bnez a4, .Lfixup_stack\n" + ".Lfixup_stack_ret:\n" + " # Pass finalizer (_dl_fini) in a2 to the user entry point.\n" + " movi a2, _dl_fini\n" + " # Jump to user's entry point (_start).\n" + " jx a3\n" + ".Lfixup_stack:\n" + " # argc -= _dl_skip_args (with argc @ sp+0)\n" + " sub a7, a7, a4\n" + " s32i a7, sp, 0\n" + " # Shift everything by _dl_skip_args.\n" + " addi a5, sp, 4 # a5 = destination ptr = argv\n" + " add a4, a5, a4 # a4 = source ptr = argv + _dl_skip_args\n" + " # Shift argv.\n" + "1: l32i a6, a4, 0\n" + " addi a4, a4, 4\n" + " s32i a6, a5, 0\n" + " addi a5, a5, 4\n" + " bnez a6, 1b\n" + " # Shift envp.\n" + "2: l32i a6, a4, 0\n" + " addi a4, a4, 4\n" + " s32i a6, a5, 0\n" + " addi a5, a5, 4\n" + " bnez a6, 2b\n" + " # Shift auxiliary table.\n" + "3: l32i a6, a4, 0\n" + " l32i a8, a4, 4\n" + " addi a4, a4, 8\n" + " s32i a6, a5, 0\n" + " s32i a8, a5, 4\n" + " addi a5, a5, 8\n" + " bnez a6, 3b\n" + " j .Lfixup_stack_ret"); + +/* Get a pointer to the argv value. */ +#define GET_ARGV(ARGVP, ARGS) ARGVP = (((unsigned long *) ARGS) + 1) + +/* Function calls are not safe until the GOT relocations have been done. */ +#define NO_FUNCS_BEFORE_BOOTSTRAP + +#define PERFORM_BOOTSTRAP_GOT(tpnt) \ +do { \ + xtensa_got_location *got_loc; \ + unsigned long l_addr = tpnt->loadaddr; \ + Elf32_Word relative_count; \ + unsigned long rel_addr; \ + int x; \ +\ + got_loc = (xtensa_got_location *) \ + (tpnt->dynamic_info[DT_XTENSA (GOT_LOC_OFF)] + l_addr); \ +\ + for (x = 0; x < tpnt->dynamic_info[DT_XTENSA (GOT_LOC_SZ)]; x++) { \ + Elf32_Addr got_start, got_end; \ + got_start = got_loc[x].offset & ~(PAGE_SIZE - 1); \ + got_end = ((got_loc[x].offset + got_loc[x].length + PAGE_SIZE - 1) \ + & ~(PAGE_SIZE - 1)); \ + _dl_mprotect ((void *)(got_start + l_addr), got_end - got_start, \ + PROT_READ | PROT_WRITE | PROT_EXEC); \ + } \ +\ + /* The following is a stripped down version of the code following \ + the invocation of PERFORM_BOOTSTRAP_GOT in dl-startup.c. That \ + code is skipped when PERFORM_BOOTSTRAP_GOT is defined, so it has \ + to be done here instead. */ \ + relative_count = tpnt->dynamic_info[DT_RELCONT_IDX]; \ + rel_addr = tpnt->dynamic_info[DT_RELOC_TABLE_ADDR]; \ + if (rel_addr) \ + elf_machine_relative(load_addr, rel_addr, relative_count); \ +} while (0) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/xtensa/dl-syscalls.h b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/xtensa/dl-syscalls.h new file mode 100644 index 00000000..4b42a57e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/xtensa/dl-syscalls.h @@ -0,0 +1,7 @@ +/* We can't use the real errno in ldso, since it has not yet + * been dynamicly linked in yet. */ +#include "sys/syscall.h" +extern int _dl_errno; +#undef __set_errno +#define __set_errno(X) {(_dl_errno) = (X);} + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/xtensa/dl-sysdep.h b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/xtensa/dl-sysdep.h new file mode 100644 index 00000000..07b9b79e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/xtensa/dl-sysdep.h @@ -0,0 +1,130 @@ +/* Machine-dependent ELF dynamic relocation. + Parts copied from glibc/sysdeps/xtensa/dl-machine.h + Copyright (C) 2001, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street - Fifth Floor, + Boston, MA 02110-1301, USA. */ + +/* Define this if the system uses RELOCA. */ +#define ELF_USES_RELOCA +#include +#include + +/* Translate a processor specific dynamic tag to the index + in l_info array. */ +#define DT_XTENSA(x) (DT_XTENSA_##x - DT_LOPROC + DT_NUM + OS_NUM) + +typedef struct xtensa_got_location_struct { + Elf32_Off offset; + Elf32_Word length; +} xtensa_got_location; + +/* Initialization sequence for the GOT. */ +#define INIT_GOT(GOT_BASE, MODULE) \ + do { \ + xtensa_got_location *got_loc; \ + Elf32_Addr l_addr = MODULE->loadaddr; \ + int x; \ + \ + got_loc = (xtensa_got_location *) \ + (MODULE->dynamic_info[DT_XTENSA (GOT_LOC_OFF)] + l_addr); \ + \ + for (x = 0; x < MODULE->dynamic_info[DT_XTENSA (GOT_LOC_SZ)]; x++) \ + { \ + Elf32_Addr got_start, got_end; \ + got_start = got_loc[x].offset & ~(PAGE_SIZE - 1); \ + got_end = ((got_loc[x].offset + got_loc[x].length + PAGE_SIZE - 1) \ + & ~(PAGE_SIZE - 1)); \ + _dl_mprotect ((void *)(got_start + l_addr) , got_end - got_start, \ + PROT_READ | PROT_WRITE | PROT_EXEC); \ + } \ + \ + /* Fill in first GOT entry according to the ABI. */ \ + GOT_BASE[0] = (unsigned long) _dl_linux_resolve; \ + } while (0) + +/* Parse dynamic info */ +#define ARCH_NUM 2 +#define ARCH_DYNAMIC_INFO(dpnt, dynamic, debug_addr) \ + do { \ + if (dpnt->d_tag == DT_XTENSA_GOT_LOC_OFF) \ + dynamic[DT_XTENSA (GOT_LOC_OFF)] = dpnt->d_un.d_ptr; \ + else if (dpnt->d_tag == DT_XTENSA_GOT_LOC_SZ) \ + dynamic[DT_XTENSA (GOT_LOC_SZ)] = dpnt->d_un.d_val; \ + } while (0) + +/* Here we define the magic numbers that this dynamic loader should accept. */ +#define MAGIC1 EM_XTENSA +#undef MAGIC2 + +/* Used for error messages. */ +#define ELF_TARGET "Xtensa" + +/* Need bootstrap relocations */ +#define ARCH_NEEDS_BOOTSTRAP_RELOCS + +struct elf_resolve; +extern unsigned long _dl_linux_resolver (struct elf_resolve *, int); + +/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry, so + undefined references should not be allowed to define the value. */ +#define elf_machine_type_class(type) \ + (((type) == R_XTENSA_JMP_SLOT) * ELF_RTYPE_CLASS_PLT) + +/* Return the link-time address of _DYNAMIC. */ +static __always_inline Elf32_Addr +elf_machine_dynamic (void) +{ + /* This function is only used while bootstrapping the runtime linker. + The "_DYNAMIC" symbol is always local so its GOT entry will initially + contain the link-time address. */ + return (Elf32_Addr) &_DYNAMIC; +} + +/* Return the run-time load address of the shared object. */ +static __always_inline Elf32_Addr +elf_machine_load_address (void) +{ + Elf32_Addr addr, tmp; + + /* At this point, the runtime linker is being bootstrapped and the GOT + entry used for ".Lhere" will contain the link address. The CALL0 will + produce the dynamic address of ".Lhere" + 3. Thus, the end result is + equal to "dynamic_address(.Lhere) - link_address(.Lhere)". */ + __asm__ ("\ + movi %0, .Lhere\n\ + mov %1, a0\n\ +.Lhere: _call0 0f\n\ + .align 4\n\ +0: sub %0, a0, %0\n\ + mov a0, %1" + : "=a" (addr), "=a" (tmp)); + + return addr - 3; +} + +static __always_inline void +elf_machine_relative (Elf32_Addr load_off, const Elf32_Addr rel_addr, + Elf32_Word relative_count) +{ + Elf32_Rela *rpnt = (Elf32_Rela *) rel_addr; + while (relative_count--) + { + Elf32_Addr *const reloc_addr = (Elf32_Addr *) (load_off + rpnt->r_offset); + *reloc_addr += load_off + rpnt->r_addend; + rpnt++; + } +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/xtensa/elfinterp.c b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/xtensa/elfinterp.c new file mode 100644 index 00000000..8eb60091 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/xtensa/elfinterp.c @@ -0,0 +1,278 @@ +/* vi: set sw=4 ts=4: */ +/* Xtensa ELF shared library loader suppport + * + * Copyright (C) 2007 Tensilica Inc. + * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald, + * David Engel, Hongjiu Lu and Mitch D'Souza + * Copyright (C) 2001-2004 Erik Andersen + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. The name of the above contributors may not be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "ldso.h" + +unsigned long +_dl_linux_resolver (struct elf_resolve *tpnt, int reloc_entry) +{ + ELF_RELOC *this_reloc; + char *strtab; + Elf32_Sym *symtab; + int symtab_index; + char *rel_addr; + char *new_addr; + char **got_addr; + char *symname; + + rel_addr = (char *) tpnt->dynamic_info[DT_JMPREL]; + this_reloc = (ELF_RELOC *) (rel_addr + reloc_entry); + symtab_index = ELF32_R_SYM (this_reloc->r_info); + + symtab = (Elf32_Sym *) tpnt->dynamic_info[DT_SYMTAB]; + strtab = (char *) tpnt->dynamic_info[DT_STRTAB]; + symname = strtab + symtab[symtab_index].st_name; + + /* Address of the literal to fix up. */ + got_addr = (char **) (this_reloc->r_offset + tpnt->loadaddr); + + /* Get the address of the GOT entry. */ + new_addr = _dl_find_hash (symname, tpnt->symbol_scope, tpnt, + ELF_RTYPE_CLASS_PLT, NULL); + if (unlikely (!new_addr)) { + _dl_dprintf (2, "%s: can't resolve symbol '%s'\n", + _dl_progname, symname); + _dl_exit (1); + } + +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_bindings) { + _dl_dprintf (_dl_debug_file, "\nresolve function: %s", symname); + if (_dl_debug_detail) + _dl_dprintf (_dl_debug_file, "\n\tpatched %x ==> %x @ %x\n", + *got_addr, new_addr, got_addr); + } + if (!_dl_debug_nofixups) + *got_addr = new_addr; +#else + *got_addr = new_addr; +#endif + + return (unsigned long) new_addr; +} + + +static int +_dl_parse (struct elf_resolve *tpnt, struct dyn_elf *scope, + unsigned long rel_addr, unsigned long rel_size, + int (*reloc_fnc) (struct elf_resolve *tpnt, struct dyn_elf *scope, + ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)) +{ + unsigned int i; + char *strtab; + Elf32_Sym *symtab; + ELF_RELOC *rpnt; + int symtab_index; + + /* Parse the relocation information. */ + rpnt = (ELF_RELOC *) rel_addr; + rel_size /= sizeof (ELF_RELOC); + + symtab = (Elf32_Sym *) tpnt->dynamic_info[DT_SYMTAB]; + strtab = (char *) tpnt->dynamic_info[DT_STRTAB]; + + for (i = 0; i < rel_size; i++, rpnt++) { + int res; + + symtab_index = ELF32_R_SYM (rpnt->r_info); + + debug_sym (symtab, strtab, symtab_index); + debug_reloc (symtab, strtab, rpnt); + + res = reloc_fnc (tpnt, scope, rpnt, symtab, strtab); + + if (res == 0) + continue; + + _dl_dprintf (2, "\n%s: ", _dl_progname); + + if (symtab_index) + _dl_dprintf (2, "symbol '%s': ", + strtab + symtab[symtab_index].st_name); + + if (unlikely (res < 0)) { + int reloc_type = ELF32_R_TYPE (rpnt->r_info); +#if defined (__SUPPORT_LD_DEBUG__) + _dl_dprintf (2, "can't handle reloc type %s\n", + _dl_reltypes (reloc_type)); +#else + _dl_dprintf (2, "can't handle reloc type %x\n", reloc_type); +#endif + _dl_exit (-res); + } + if (unlikely (res > 0)) { + _dl_dprintf (2, "can't resolve symbol\n"); + return res; + } + } + + return 0; +} + + +static int +_dl_do_reloc (struct elf_resolve *tpnt, struct dyn_elf *scope, + ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab) +{ + int reloc_type; + int symtab_index; + char *symname; + struct symbol_ref sym_ref; + Elf32_Addr *reloc_addr; + Elf32_Addr symbol_addr; +#if defined (__SUPPORT_LD_DEBUG__) + Elf32_Addr old_val; +#endif + + reloc_addr = (Elf32_Addr *) (tpnt->loadaddr + rpnt->r_offset); + reloc_type = ELF32_R_TYPE (rpnt->r_info); + symtab_index = ELF32_R_SYM (rpnt->r_info); + sym_ref.sym = &symtab[symtab_index]; + sym_ref.tpnt = NULL; + symbol_addr = 0; + symname = strtab + sym_ref.sym->st_name; + + if (symtab_index) { + symbol_addr = (Elf32_Addr) + _dl_find_hash (symname, scope, tpnt, + elf_machine_type_class (reloc_type), &sym_ref); + + /* + * We want to allow undefined references to weak symbols - this might + * have been intentional. We should not be linking local symbols + * here, so all bases should be covered. + */ + if (unlikely (!symbol_addr && + ELF32_ST_BIND (sym_ref.sym->st_info) != STB_WEAK)) { + _dl_dprintf (2, "%s: can't resolve symbol '%s'\n", + _dl_progname, symname); + _dl_exit (1); + } + } + +#if defined (__SUPPORT_LD_DEBUG__) + old_val = *reloc_addr; +#endif + + switch (reloc_type) { + case R_XTENSA_NONE: + break; + + case R_XTENSA_GLOB_DAT: + case R_XTENSA_JMP_SLOT: + *reloc_addr = symbol_addr + rpnt->r_addend; + break; + + case R_XTENSA_RTLD: + if (rpnt->r_addend == 1) { + /* Grab the function pointer stashed at the beginning of the + GOT by the GOT_INIT function. */ + *reloc_addr = *(Elf32_Addr *) tpnt->dynamic_info[DT_PLTGOT]; + } else if (rpnt->r_addend == 2) { + /* Store the link map for the object. */ + *reloc_addr = (Elf32_Addr) tpnt; + } else { + _dl_exit (1); + } + break; + + case R_XTENSA_RELATIVE: + *reloc_addr += tpnt->loadaddr + rpnt->r_addend; + break; + + default: + return -1; /* Calls _dl_exit(1). */ + } +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_reloc && _dl_debug_detail) + _dl_dprintf (_dl_debug_file, "\tpatched: %x ==> %x @ %x\n", + old_val, *reloc_addr, reloc_addr); +#endif + + return 0; +} + + +static int +_dl_do_lazy_reloc (struct elf_resolve *tpnt, struct dyn_elf *scope, + ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab) +{ + int reloc_type; + Elf32_Addr *reloc_addr; +#if defined (__SUPPORT_LD_DEBUG__) + Elf32_Addr old_val; +#endif + + reloc_addr = (Elf32_Addr *) (tpnt->loadaddr + rpnt->r_offset); + reloc_type = ELF32_R_TYPE (rpnt->r_info); + +#if defined (__SUPPORT_LD_DEBUG__) + old_val = *reloc_addr; +#endif + + switch (reloc_type) { + case R_XTENSA_JMP_SLOT: + /* Perform a RELATIVE reloc on the GOT entry that transfers + to the stub function. */ + *reloc_addr += tpnt->loadaddr; + break; + case R_XTENSA_NONE: + break; + default: + _dl_exit (1); + } + +#if defined (__SUPPORT_LD_DEBUG__) + if (_dl_debug_reloc && _dl_debug_detail) + _dl_dprintf (_dl_debug_file, "\tpatched: %x ==> %x @ %x\n", + old_val, *reloc_addr, reloc_addr); +#endif + return 0; + +} + +void +_dl_parse_lazy_relocation_information (struct dyn_elf *rpnt, + unsigned long rel_addr, + unsigned long rel_size) +{ + (void) _dl_parse (rpnt->dyn, NULL, rel_addr, rel_size, _dl_do_lazy_reloc); +} + +int +_dl_parse_relocation_information (struct dyn_elf *rpnt, + unsigned long rel_addr, + unsigned long rel_size) +{ + return _dl_parse (rpnt->dyn, rpnt->dyn->symbol_scope, rel_addr, rel_size, + _dl_do_reloc); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/xtensa/resolve.S b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/xtensa/resolve.S new file mode 100644 index 00000000..902cd823 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/ldso/xtensa/resolve.S @@ -0,0 +1,57 @@ +/* Xtensa dynamic resolver. + Parts copied from glibc/sysdeps/xtensa/dl-trampoline.S + Copyright (C) 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street - Fifth Floor, + Boston, MA 02110-1301, USA. */ + +#define MIN_FRAME_SIZE 32 + +#ifdef __XTENSA_EB__ +#define XTENSA_IMM12_FLD_OFFSET 8 +#else /* __XTENSA_EL__ */ +#define XTENSA_IMM12_FLD_OFFSET 12 +#endif /* __XTENSA_EL__ */ + + .text + .align 4 + .global _dl_linux_resolve + .type _dl_linux_resolve, @function +_dl_linux_resolve: + /* Fix up the high 2 bits of the return address. */ + movi a13, 0f + slli a12, a0, 2 +0: extui a13, a13, 30, 2 + ssai 2 + src a12, a13, a12 + + /* Call the fixup function. */ + movi a8, _dl_linux_resolver + callx8 a8 + + /* Extract the target's frame size from the ENTRY instruction. */ + l32i a11, a10, 0 + extui a11, a11, XTENSA_IMM12_FLD_OFFSET, 12 + slli a11, a11, 3 + + addi a11, a11, -MIN_FRAME_SIZE + sub a11, sp, a11 + movsp sp, a11 + + /* Jump to the next instruction past the ENTRY. */ + addi a10, a10, 3 + jx a10 + .size _dl_linux_resolve, . - _dl_linux_resolve diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/libdl/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/libdl/Makefile new file mode 100644 index 00000000..f9100219 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/libdl/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../ +top_builddir=../../ +include $(top_builddir)Rules.mak +all: libs +include Makefile.in +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/libdl/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/libdl/Makefile.in new file mode 100644 index 00000000..152185e3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/libdl/Makefile.in @@ -0,0 +1,60 @@ +# Makefile.in for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +subdirs += ldso/libdl + +CFLAGS-libdl := -DNOT_IN_libc -DIS_IN_libdl $(SSP_ALL_CFLAGS) + +CFLAGS-libdl += -I$(top_srcdir)ldso/ldso/$(TARGET_ARCH) -I$(top_srcdir)ldso/include -I$(top_srcdir)ldso/ldso + +CFLAGS-libdl += -DUCLIBC_RUNTIME_PREFIX=\"$(RUNTIME_PREFIX)\" + +ifeq ($(SUPPORT_LD_DEBUG),y) +CFLAGS-libdl += -D__SUPPORT_LD_DEBUG__ +endif + +CFLAGS-libdl.c := -DLDSO_ELFINTERP=\"$(TARGET_ARCH)/elfinterp.c\" + +LDFLAGS-$(UCLIBC_FORMAT_DSBT_ELF)-libdl.so := -Wl,--dsbt-index=3 +LDFLAGS-libdl.so := $(LDFLAGS) -Wl,-fini,dl_cleanup + +LIBS-libdl.so := $(LIBS) $(ldso) + +libdl_FULL_NAME := libdl-$(VERSION).so + +libdl_DIR := $(top_srcdir)ldso/libdl +libdl_OUT := $(top_builddir)ldso/libdl + +libdl_SRC := $(libdl_DIR)/libdl.c +libdl_OBJ := $(patsubst $(libdl_DIR)/%.c,$(libdl_OUT)/%.o,$(libdl_SRC)) + +resolve := $(top_builddir)ldso/ldso/$(TARGET_ARCH)/resolve.o + +libdl-a-y := $(libdl_OBJ) $(resolve) +ifeq ($(DOPIC),y) +libdl-a-y := $(libdl-a-y:.o=.os) +endif +libdl-so-y := $(libdl_OUT)/libdl.oS + +lib-a-$(HAVE_SHARED) += $(top_builddir)lib/libdl.a +lib-so-y += $(top_builddir)lib/libdl.so +objclean-y += CLEAN_ldso/libdl + +$(top_builddir)lib/libdl.so: $(libdl_OUT)/libdl_so.a $(libc.depend) + $(call link.so,$(libdl_FULL_NAME),$(ABI_VERSION)) + +$(libdl_OUT)/libdl_so.a: $(libdl-so-y) + $(Q)$(RM) $@ + $(do_ar) + +$(top_builddir)lib/libdl.a: $(libdl-a-y) + $(Q)$(INSTALL) -d $(dir $@) + $(Q)$(RM) $@ + $(do_ar) + +CLEAN_ldso/libdl: + $(do_rm) $(addprefix $(libdl_OUT)/*., o os oS a) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/libdl/libdl.c b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/libdl/libdl.c new file mode 100644 index 00000000..b8d3feb6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/libdl/libdl.c @@ -0,0 +1,1130 @@ +/* vi: set sw=4 ts=4: */ +/* + * Program to load an ELF binary on a linux system, and run it + * after resolving ELF shared library symbols + * + * Copyright (C) 2000-2006 by Erik Andersen + * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald, + * David Engel, Hongjiu Lu and Mitch D'Souza + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. The name of the above contributors may not be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#include +#include +#include /* Needed for 'strstr' prototype' */ +#include +#include // L4 addition but needed for struct stat (?!) + +#ifdef __UCLIBC_HAS_TLS__ +#include +#endif + +#if defined(USE_TLS) && USE_TLS +#include +extern void _dl_add_to_slotinfo(struct link_map *l); +#endif + +#ifdef SHARED +# if defined(USE_TLS) && USE_TLS +# include +extern struct link_map *_dl_update_slotinfo(unsigned long int req_modid); +# endif + +/* When libdl is loaded as a shared library, we need to load in + * and use a pile of symbols from ldso... */ + +extern struct elf_resolve * _dl_load_shared_library(int, struct dyn_elf **, + struct elf_resolve *, char *, int); +extern int _dl_fixup(struct dyn_elf *rpnt, int lazy); +extern void _dl_protect_relro(struct elf_resolve * tpnt); +#ifndef _dl_errno +extern int _dl_errno; +#endif +extern struct dyn_elf *_dl_symbol_tables; +extern struct dyn_elf *_dl_handles; +extern struct elf_resolve *_dl_loaded_modules; +extern void _dl_free (void *__ptr); +extern struct r_debug *_dl_debug_addr; +extern unsigned long _dl_error_number; +extern void *(*_dl_malloc_function)(size_t); +extern void (*_dl_free_function) (void *p); +extern void _dl_run_init_array(struct elf_resolve *); +extern void _dl_run_fini_array(struct elf_resolve *); +#ifdef __LDSO_CACHE_SUPPORT__ +int _dl_map_cache(void); +int _dl_unmap_cache(void); +#endif +#ifdef __mips__ +extern void _dl_perform_mips_global_got_relocations(struct elf_resolve *tpnt, int lazy); +#endif +#ifdef __SUPPORT_LD_DEBUG__ +extern char *_dl_debug; +#endif + +#else /* !SHARED */ + +#define _dl_malloc malloc +#define _dl_free free + +/* When libdl is linked as a static library, we need to replace all + * the symbols that otherwise would have been loaded in from ldso... */ + +#ifdef __SUPPORT_LD_DEBUG__ +char *_dl_debug = NULL; +char *_dl_debug_symbols = NULL; +char *_dl_debug_move = NULL; +char *_dl_debug_reloc = NULL; +char *_dl_debug_detail = NULL; +char *_dl_debug_nofixups = NULL; +char *_dl_debug_bindings = NULL; +int _dl_debug_file /*= 2*/; +#endif +const char *_dl_progname = ""; /* Program name */ +void *(*_dl_malloc_function)(size_t); +void (*_dl_free_function) (void *p); +char *_dl_library_path = NULL; /* Where we look for libraries */ +char *_dl_ldsopath = NULL; /* Location of the shared lib loader */ +int _dl_errno = 0; /* We can't use the real errno in ldso */ +size_t _dl_pagesize = PAGE_SIZE; /* Store the page size for use later */ +/* This global variable is also to communicate with debuggers such as gdb. */ +struct r_debug *_dl_debug_addr = NULL; + +#include "../ldso/dl-array.c" +#include "../ldso/dl-debug.c" + + +# if defined(USE_TLS) && USE_TLS +/* + * Giving this initialized value preallocates some surplus bytes in the + * static TLS area, see __libc_setup_tls (libc-tls.c). + */ +size_t _dl_tls_static_size = 2048; +# endif +#include LDSO_ELFINTERP +#include "../ldso/dl-hash.c" +#define _dl_trace_loaded_objects 0 +#include "../ldso/dl-elf.c" +#endif /* SHARED */ + +#ifdef __SUPPORT_LD_DEBUG__ +# define _dl_if_debug_print(fmt, args...) \ + do { \ + if (_dl_debug) \ + fprintf(stderr, "%s():%i: " fmt, __FUNCTION__, __LINE__, ## args); \ + } while (0) +#else +# define _dl_if_debug_print(fmt, args...) +#endif + +static int do_dlclose(void *, int need_fini); + + +static const char *const dl_error_names[] = { + "", + "File not found", + "Unable to open /dev/zero", + "Not an ELF file", +#if defined (__i386__) + "Not i386 binary", +#elif defined (__sparc__) + "Not sparc binary", +#elif defined (__mc68000__) + "Not m68k binary", +#else + "Unrecognized binary type", +#endif + "Not an ELF shared library", + "Unable to mmap file", + "No dynamic section", + "Library contains unsupported TLS", +#ifdef ELF_USES_RELOCA + "Unable to process REL relocs", +#else + "Unable to process RELA relocs", +#endif + "Bad handle", + "Unable to resolve symbol" +}; + + +#if defined(USE_TLS) && USE_TLS +#ifdef SHARED +/* + * Systems which do not have tls_index also probably have to define + * DONT_USE_TLS_INDEX. + */ + +# ifndef __TLS_GET_ADDR +# define __TLS_GET_ADDR __tls_get_addr +# endif + +/* + * Return the symbol address given the map of the module it is in and + * the symbol record. This is used in dl-sym.c. + */ +static void * +internal_function +_dl_tls_symaddr(struct link_map *map, const Elf32_Addr st_value) +{ +# ifndef DONT_USE_TLS_INDEX + tls_index tmp = + { + .ti_module = map->l_tls_modid, + .ti_offset = st_value + }; + + return __TLS_GET_ADDR (&tmp); +# else + return __TLS_GET_ADDR (map->l_tls_modid, st_value); +# endif +} +#endif + +/* Returns true when a non-empty entry was found. */ +static bool +remove_slotinfo(size_t idx, struct dtv_slotinfo_list *listp, size_t disp, + bool should_be_there) +{ + if (idx - disp >= listp->len) { + if (listp->next == NULL) { + /* + * The index is not actually valid in the slotinfo list, + * because this object was closed before it was fully set + * up due to some error. + */ + _dl_assert(!should_be_there); + } else { + if (remove_slotinfo(idx, listp->next, disp + listp->len, + should_be_there)) + return true; + + /* + * No non-empty entry. Search from the end of this element's + * slotinfo array. + */ + idx = disp + listp->len; + } + } else { + struct link_map *old_map = listp->slotinfo[idx - disp].map; + + /* + * The entry might still be in its unused state if we are + * closing an object that wasn't fully set up. + */ + if (__builtin_expect(old_map != NULL, 1)) { + _dl_assert(old_map->l_tls_modid == idx); + + /* Mark the entry as unused. */ + listp->slotinfo[idx - disp].gen = _dl_tls_generation + 1; + listp->slotinfo[idx - disp].map = NULL; + } + + /* + * If this is not the last currently used entry no need to + * look further. + */ + if (idx != _dl_tls_max_dtv_idx) + return true; + } + + while (idx - disp > (disp == 0 ? 1 + _dl_tls_static_nelem : 0)) { + --idx; + + if (listp->slotinfo[idx - disp].map != NULL) { + /* Found a new last used index. */ + _dl_tls_max_dtv_idx = idx; + return true; + } + } + + /* No non-entry in this list element. */ + return false; +} +#endif + +void dl_cleanup(void) __attribute__ ((destructor)); +void dl_cleanup(void) +{ + struct dyn_elf *h, *n; + + for (h = _dl_handles; h; h = n) { + n = h->next_handle; + do_dlclose(h, 1); + } +} + +/* l4: */ void *dlopen(const char *libname, int flag); +void *dlopen(const char *libname, int flag) +{ + struct elf_resolve *tpnt, *tfrom; + struct dyn_elf *dyn_chain, *rpnt = NULL, *dyn_ptr, *relro_ptr, *handle; + ElfW(Addr) from; + struct elf_resolve *tpnt1; + void (*dl_brk) (void); + int now_flag; + struct init_fini_list *tmp, *runp, *runp2, *dep_list; + unsigned int nlist, i; + struct elf_resolve **init_fini_list; + static bool _dl_init; +#if defined(USE_TLS) && USE_TLS + bool any_tls = false; +#endif + + /* A bit of sanity checking... */ + if (!(flag & (RTLD_LAZY|RTLD_NOW))) { + _dl_error_number = LD_BAD_HANDLE; + return NULL; + } + + from = (ElfW(Addr)) __builtin_return_address(0); + + if (!_dl_init) { + _dl_init = true; + _dl_malloc_function = malloc; + _dl_free_function = free; + } + /* Cover the trivial case first */ + if (!libname) + { +// L4: Fix the case that a static program does not have a symbol table for +// the main program but needs to set the error code. LD_NO_SYMBOL has been +// taken because it sounds useful for that case. glibc does seem to have a +// rather strange handling in the static case. +#ifdef SHARED + return _dl_symbol_tables; +#else + _dl_error_number = LD_NO_SYMBOL; + return NULL; +#endif + } + +#ifndef SHARED +# ifdef __SUPPORT_LD_DEBUG__ + _dl_debug = getenv("LD_DEBUG"); + if (_dl_debug) { + if (_dl_strstr(_dl_debug, "all")) { + _dl_debug_detail = _dl_debug_move = _dl_debug_symbols + = _dl_debug_reloc = _dl_debug_bindings = _dl_debug_nofixups = (void*)1; + } else { + _dl_debug_detail = strstr(_dl_debug, "detail"); + _dl_debug_move = strstr(_dl_debug, "move"); + _dl_debug_symbols = strstr(_dl_debug, "sym"); + _dl_debug_reloc = strstr(_dl_debug, "reloc"); + _dl_debug_nofixups = strstr(_dl_debug, "nofix"); + _dl_debug_bindings = strstr(_dl_debug, "bind"); + } + } +# endif +#endif + + _dl_map_cache(); + + /* + * Try and locate the module we were called from - we + * need this so that we get the correct RPATH/RUNPATH. Note that + * this is the current behavior under Solaris, but the + * ABI+ specifies that we should only use the RPATH from + * the application. Thus this may go away at some time + * in the future. + */ + { + struct dyn_elf *dpnt; + tfrom = NULL; + for (dpnt = _dl_symbol_tables; dpnt; dpnt = dpnt->next) { + tpnt = dpnt->dyn; + if (DL_ADDR_IN_LOADADDR(from, tpnt, tfrom)) + tfrom = tpnt; + } + } + for (rpnt = _dl_symbol_tables; rpnt && rpnt->next; rpnt = rpnt->next) + continue; + + relro_ptr = rpnt; + now_flag = (flag & RTLD_NOW) ? RTLD_NOW : 0; + if (getenv("LD_BIND_NOW")) + now_flag = RTLD_NOW; + +#ifndef SHARED + /* When statically linked, the _dl_library_path is not yet initialized */ + _dl_library_path = getenv("LD_LIBRARY_PATH"); +#endif + + /* Try to load the specified library */ + _dl_if_debug_print("Trying to dlopen '%s', RTLD_GLOBAL:%d RTLD_NOW:%d\n", + (char*)libname, (flag & RTLD_GLOBAL ? 1:0), (now_flag & RTLD_NOW ? 1:0)); + tpnt = _dl_load_shared_library(0, &rpnt, tfrom, (char*)libname, 0); + + if (tpnt == NULL) { + _dl_unmap_cache(); + return NULL; + } + dyn_chain = (struct dyn_elf *) malloc(sizeof(struct dyn_elf)); + _dl_memset(dyn_chain, 0, sizeof(struct dyn_elf)); + dyn_chain->dyn = tpnt; + tpnt->rtld_flags |= (flag & RTLD_GLOBAL); + + dyn_chain->next_handle = _dl_handles; + _dl_handles = dyn_ptr = dyn_chain; + + if (tpnt->usage_count > 1) { + _dl_if_debug_print("Lib: %s already opened\n", libname); + /* see if there is a handle from a earlier dlopen */ + for (handle = _dl_handles->next_handle; handle; handle = handle->next_handle) { + if (handle->dyn == tpnt) { + dyn_chain->init_fini.init_fini = handle->init_fini.init_fini; + dyn_chain->init_fini.nlist = handle->init_fini.nlist; + for (i = 0; i < dyn_chain->init_fini.nlist; i++) + dyn_chain->init_fini.init_fini[i]->rtld_flags |= (flag & RTLD_GLOBAL); + dyn_chain->next = handle->next; + break; + } + } + return dyn_chain; + } + + tpnt->init_flag |= DL_OPENED; + + _dl_if_debug_print("Looking for needed libraries\n"); + nlist = 0; + runp = alloca(sizeof(*runp)); + runp->tpnt = tpnt; + runp->next = NULL; + dep_list = runp2 = runp; + for (; runp; runp = runp->next) { + ElfW(Dyn) *dpnt; + char *lpntstr; + + nlist++; + runp->tpnt->init_fini = NULL; /* clear any previous dependcies */ + for (dpnt = (ElfW(Dyn) *) runp->tpnt->dynamic_addr; dpnt->d_tag; dpnt++) { + if (dpnt->d_tag == DT_NEEDED) { + lpntstr = (char*) (runp->tpnt->dynamic_info[DT_STRTAB] + + dpnt->d_un.d_val); + _dl_if_debug_print("Trying to load '%s', needed by '%s'\n", + lpntstr, runp->tpnt->libname); + tpnt1 = _dl_load_shared_library(0, &rpnt, runp->tpnt, lpntstr, 0); + if (!tpnt1) + goto oops; + + tpnt1->rtld_flags |= (flag & RTLD_GLOBAL); + + /* This list is for dlsym() and relocation */ + dyn_ptr->next = (struct dyn_elf *) malloc(sizeof(struct dyn_elf)); + _dl_memset (dyn_ptr->next, 0, sizeof (struct dyn_elf)); + dyn_ptr = dyn_ptr->next; + dyn_ptr->dyn = tpnt1; + /* Used to record RTLD_LOCAL scope */ + tmp = alloca(sizeof(struct init_fini_list)); + tmp->tpnt = tpnt1; + tmp->next = runp->tpnt->init_fini; + runp->tpnt->init_fini = tmp; + + for (tmp=dep_list; tmp; tmp = tmp->next) { + if (tpnt1 == tmp->tpnt) { /* if match => cirular dependency, drop it */ + _dl_if_debug_print("Circular dependency, skipping '%s',\n", + tmp->tpnt->libname); + tpnt1->usage_count--; + break; + } + } + if (!tmp) { /* Don't add if circular dependency detected */ + runp2->next = alloca(sizeof(*runp)); + runp2 = runp2->next; + runp2->tpnt = tpnt1; + runp2->next = NULL; + } + } + } + } + init_fini_list = malloc(nlist * sizeof(struct elf_resolve *)); + dyn_chain->init_fini.init_fini = init_fini_list; + dyn_chain->init_fini.nlist = nlist; + i = 0; + for (runp2 = dep_list; runp2; runp2 = runp2->next) { + init_fini_list[i++] = runp2->tpnt; + for (runp = runp2->tpnt->init_fini; runp; runp = runp->next) { + if (!(runp->tpnt->rtld_flags & RTLD_GLOBAL)) { + tmp = malloc(sizeof(struct init_fini_list)); + tmp->tpnt = runp->tpnt; + tmp->next = runp2->tpnt->rtld_local; + runp2->tpnt->rtld_local = tmp; + } + } + + } + /* Sort the INIT/FINI list in dependency order. */ + for (runp2 = dep_list; runp2; runp2 = runp2->next) { + unsigned int j, k; + for (j = 0; init_fini_list[j] != runp2->tpnt; ++j) + /* Empty */; + for (k = j + 1; k < nlist; ++k) { + struct init_fini_list *ele = init_fini_list[k]->init_fini; + + for (; ele; ele = ele->next) { + if (ele->tpnt == runp2->tpnt) { + struct elf_resolve *here = init_fini_list[k]; + _dl_if_debug_print("Move %s from pos %d to %d in INIT/FINI list.\n", here->libname, k, j); + for (i = (k - j); i; --i) + init_fini_list[i+j] = init_fini_list[i+j-1]; + init_fini_list[j] = here; + ++j; + break; + } + } + } + } +#ifdef __SUPPORT_LD_DEBUG__ + if (_dl_debug) { + fprintf(stderr, "\nINIT/FINI order and dependencies:\n"); + for (i = 0; i < nlist; i++) { + fprintf(stderr, "lib: %s has deps:\n", init_fini_list[i]->libname); + runp = init_fini_list[i]->init_fini; + for (; runp; runp = runp->next) + fprintf(stderr, " %s ", runp->tpnt->libname); + fprintf(stderr, "\n"); + } + } +#endif + + _dl_if_debug_print("Beginning dlopen relocation fixups\n"); + /* + * OK, now all of the kids are tucked into bed in their proper addresses. + * Now we go through and look for REL and RELA records that indicate fixups + * to the GOT tables. We need to do this in reverse order so that COPY + * directives work correctly */ +#ifdef __mips__ + /* + * Relocation of the GOT entries for MIPS have to be done + * after all the libraries have been loaded. + */ + _dl_perform_mips_global_got_relocations(tpnt, !now_flag); +#endif + + if (_dl_fixup(dyn_chain, now_flag)) + goto oops; + + if (relro_ptr) { + for (rpnt = relro_ptr->next; rpnt; rpnt = rpnt->next) { + if (rpnt->dyn->relro_size) + _dl_protect_relro(rpnt->dyn); + } + } + /* TODO: Should we set the protections of all pages back to R/O now ? */ + + +#if defined(USE_TLS) && USE_TLS + + for (i=0; i < nlist; i++) { + struct elf_resolve *tmp_tpnt = init_fini_list[i]; + /* Only add TLS memory if this object is loaded now and + therefore is not yet initialized. */ + + if (!(tmp_tpnt->init_flag & INIT_FUNCS_CALLED) + /* Only if the module defines thread local data. */ + && __builtin_expect (tmp_tpnt->l_tls_blocksize > 0, 0)) { + + /* Now that we know the object is loaded successfully add + modules containing TLS data to the slot info table. We + might have to increase its size. */ + _dl_add_to_slotinfo ((struct link_map*)tmp_tpnt); + + /* It is the case in which we couldn't perform TLS static + initialization at relocation time, and we delayed it until + the relocation has been completed. */ + + if (tmp_tpnt->l_need_tls_init) { + tmp_tpnt->l_need_tls_init = 0; +# ifdef SHARED + /* Update the slot information data for at least the + generation of the DSO we are allocating data for. */ + _dl_update_slotinfo (tmp_tpnt->l_tls_modid); +# endif + + _dl_init_static_tls((struct link_map*)tmp_tpnt); + _dl_assert (tmp_tpnt->l_need_tls_init == 0); + } + + /* We have to bump the generation counter. */ + any_tls = true; + } + } + + /* Bump the generation number if necessary. */ + if (any_tls && __builtin_expect (++_dl_tls_generation == 0, 0)) { + _dl_debug_early("TLS generation counter wrapped! Please report this."); + _dl_exit(30); + } + +#endif + + /* Notify the debugger we have added some objects. */ + if (_dl_debug_addr) { + dl_brk = (void (*)(void)) _dl_debug_addr->r_brk; + if (dl_brk != NULL) { + _dl_debug_addr->r_state = RT_ADD; + (*dl_brk) (); + + _dl_debug_addr->r_state = RT_CONSISTENT; + (*dl_brk) (); + } + } + + /* Run the ctors and setup the dtors */ + for (i = nlist; i; --i) { + tpnt = init_fini_list[i-1]; + if (tpnt->init_flag & INIT_FUNCS_CALLED) + continue; + tpnt->init_flag |= INIT_FUNCS_CALLED; + + if (tpnt->dynamic_info[DT_INIT]) { + void (*dl_elf_func) (void); + dl_elf_func = (void (*)(void)) DL_RELOC_ADDR(tpnt->loadaddr, tpnt->dynamic_info[DT_INIT]); + if (dl_elf_func) { + _dl_if_debug_print("running ctors for library %s at '%p'\n", + tpnt->libname, dl_elf_func); + DL_CALL_FUNC_AT_ADDR (dl_elf_func, tpnt->loadaddr, (void(*)(void))); + } + } + + _dl_run_init_array(tpnt); + } + + _dl_unmap_cache(); + return (void *) dyn_chain; + +oops: + /* Something went wrong. Clean up and return NULL. */ + _dl_unmap_cache(); + do_dlclose(dyn_chain, 0); + return NULL; +} + +/* l4: */ void *dlsym(void *vhandle, const char *name); +void *dlsym(void *vhandle, const char *name) +{ + struct elf_resolve *tpnt, *tfrom; + struct dyn_elf *handle; + ElfW(Addr) from; + struct dyn_elf *rpnt; + void *ret; + struct symbol_ref sym_ref = { NULL, NULL }; + /* Nastiness to support underscore prefixes. */ +#ifdef __UCLIBC_UNDERSCORES__ + char tmp_buf[80]; + char *name2 = tmp_buf; + size_t nlen = strlen (name) + 1; + if (nlen + 1 > sizeof (tmp_buf)) + name2 = malloc (nlen + 1); + if (name2 == 0) { + _dl_error_number = LD_ERROR_MMAP_FAILED; + return 0; + } + name2[0] = '_'; + memcpy (name2 + 1, name, nlen); +#else + const char *name2 = name; +#endif + handle = (struct dyn_elf *) vhandle; + + /* First of all verify that we have a real handle + of some kind. Return NULL if not a valid handle. */ + + if (handle == NULL) + handle = _dl_symbol_tables; + else if (handle != RTLD_NEXT && handle != _dl_symbol_tables) { + for (rpnt = _dl_handles; rpnt; rpnt = rpnt->next_handle) + if (rpnt == handle) + break; + if (!rpnt) { + _dl_error_number = LD_BAD_HANDLE; + ret = NULL; + goto out; + } + } else if (handle == RTLD_NEXT) { + /* + * Try and locate the module we were called from - we + * need this so that we know where to start searching + * from. We never pass RTLD_NEXT down into the actual + * dynamic loader itself, as it doesn't know + * how to properly treat it. + */ + from = (ElfW(Addr)) __builtin_return_address(0); + + tfrom = NULL; + for (rpnt = _dl_symbol_tables; rpnt; rpnt = rpnt->next) { + tpnt = rpnt->dyn; + if (DL_ADDR_IN_LOADADDR(from, tpnt, tfrom)) { + tfrom = tpnt; + handle = rpnt->next; + } + } + } + tpnt = NULL; + if (handle == _dl_symbol_tables) + tpnt = handle->dyn; /* Only search RTLD_GLOBAL objs if global object */ + ret = _dl_find_hash(name2, handle, tpnt, 0, &sym_ref); + +#if defined(USE_TLS) && USE_TLS && defined SHARED + if (sym_ref.tpnt) { + /* The found symbol is a thread-local storage variable. + Return the address for to the current thread. */ + ret = _dl_tls_symaddr ((struct link_map *)sym_ref.tpnt, (Elf32_Addr)ret); + } +#endif + + /* + * Nothing found. + */ + if (!ret) + _dl_error_number = LD_NO_SYMBOL; +out: +#ifdef __UCLIBC_UNDERSCORES__ + if (name2 != tmp_buf) + free (name2); +#endif + return ret; +} + +#if 0 +void *dlvsym(void *vhandle, const char *name, const char *version) +{ + return dlsym(vhandle, name); +} +#endif + +static int do_dlclose(void *vhandle, int need_fini) +{ + struct dyn_elf *rpnt, *rpnt1, *rpnt1_tmp; + struct init_fini_list *runp, *tmp; + ElfW(Phdr) *ppnt; + struct elf_resolve *tpnt, *run_tpnt; + int (*dl_elf_fini) (void); + void (*dl_brk) (void); + struct dyn_elf *handle; + unsigned int end; + unsigned int i, j; +#if defined(USE_TLS) && USE_TLS + bool any_tls = false; + size_t tls_free_start = NO_TLS_OFFSET; + size_t tls_free_end = NO_TLS_OFFSET; + struct link_map *tls_lmap; +#endif + + handle = (struct dyn_elf *) vhandle; + if (handle == _dl_symbol_tables) + return 0; + rpnt1 = NULL; + for (rpnt = _dl_handles; rpnt; rpnt = rpnt->next_handle) { + if (rpnt == handle) + break; + rpnt1 = rpnt; + } + + if (!rpnt) { + _dl_error_number = LD_BAD_HANDLE; + return 1; + } + if (rpnt1) + rpnt1->next_handle = rpnt->next_handle; + else + _dl_handles = rpnt->next_handle; + _dl_if_debug_print("%s: usage count: %d\n", + handle->dyn->libname, handle->dyn->usage_count); + if (handle->dyn->usage_count != 1 || (handle->dyn->rtld_flags & RTLD_NODELETE)) { + handle->dyn->usage_count--; + free(handle); + return 0; + } + /* OK, this is a valid handle - now close out the file */ + for (j = 0; j < handle->init_fini.nlist; ++j) { + tpnt = handle->init_fini.init_fini[j]; + tpnt->usage_count--; + if (tpnt->usage_count == 0 && !(tpnt->rtld_flags & RTLD_NODELETE)) { + if ((tpnt->dynamic_info[DT_FINI] + || tpnt->dynamic_info[DT_FINI_ARRAY]) + && need_fini + && !(tpnt->init_flag & FINI_FUNCS_CALLED) + ) { + tpnt->init_flag |= FINI_FUNCS_CALLED; + _dl_run_fini_array(tpnt); + + if (tpnt->dynamic_info[DT_FINI]) { + dl_elf_fini = (int (*)(void)) DL_RELOC_ADDR(tpnt->loadaddr, tpnt->dynamic_info[DT_FINI]); + _dl_if_debug_print("running dtors for library %s at '%p'\n", + tpnt->libname, dl_elf_fini); + DL_CALL_FUNC_AT_ADDR (dl_elf_fini, tpnt->loadaddr, (int (*)(void))); + } + } + + _dl_if_debug_print("unmapping: %s\n", tpnt->libname); + end = 0; + for (i = 0, ppnt = tpnt->ppnt; + i < tpnt->n_phent; ppnt++, i++) { + if (ppnt->p_type != PT_LOAD) + continue; + if (end < ppnt->p_vaddr + ppnt->p_memsz) + end = ppnt->p_vaddr + ppnt->p_memsz; + } + +#if defined(USE_TLS) && USE_TLS + /* Do the cast to make things easy. */ + tls_lmap = (struct link_map *) tpnt; + + /* Remove the object from the dtv slotinfo array if it uses TLS. */ + if (__builtin_expect (tls_lmap->l_tls_blocksize > 0, 0)) { + any_tls = true; + + if (_dl_tls_dtv_slotinfo_list != NULL + && ! remove_slotinfo (tls_lmap->l_tls_modid, + _dl_tls_dtv_slotinfo_list, 0, + (tpnt->init_flag & INIT_FUNCS_CALLED))) + /* All dynamically loaded modules with TLS are unloaded. */ + _dl_tls_max_dtv_idx = _dl_tls_static_nelem; + + if (tls_lmap->l_tls_offset != NO_TLS_OFFSET) { + /* + * Collect a contiguous chunk built from the objects in + * this search list, going in either direction. When the + * whole chunk is at the end of the used area then we can + * reclaim it. + */ +# if defined(TLS_TCB_AT_TP) + if (tls_free_start == NO_TLS_OFFSET + || (size_t) tls_lmap->l_tls_offset == tls_free_start) { + /* Extend the contiguous chunk being reclaimed. */ + tls_free_start + = tls_lmap->l_tls_offset - + tls_lmap->l_tls_blocksize; + + if (tls_free_end == NO_TLS_OFFSET) + tls_free_end = tls_lmap->l_tls_offset; + } else if (tls_lmap->l_tls_offset - tls_lmap->l_tls_blocksize + == tls_free_end) + /* Extend the chunk backwards. */ + tls_free_end = tls_lmap->l_tls_offset; + else { + /* + * This isn't contiguous with the last chunk freed. + * One of them will be leaked unless we can free + * one block right away. + */ + if (tls_free_end == _dl_tls_static_used) { + _dl_tls_static_used = tls_free_start; + tls_free_end = tls_lmap->l_tls_offset; + tls_free_start + = tls_free_end - tls_lmap->l_tls_blocksize; + } else if ((size_t) tls_lmap->l_tls_offset + == _dl_tls_static_used) + _dl_tls_static_used = tls_lmap->l_tls_offset - + tls_lmap->l_tls_blocksize; + else if (tls_free_end < (size_t) tls_lmap->l_tls_offset) { + /* + * We pick the later block. It has a chance + * to be freed. + */ + tls_free_end = tls_lmap->l_tls_offset; + tls_free_start = tls_free_end - + tls_lmap->l_tls_blocksize; + } + } +# elif defined(TLS_DTV_AT_TP) + if ((size_t) tls_lmap->l_tls_offset == tls_free_end) + /* Extend the contiguous chunk being reclaimed. */ + tls_free_end -= tls_lmap->l_tls_blocksize; + else if (tls_lmap->l_tls_offset + tls_lmap->l_tls_blocksize + == tls_free_start) + /* Extend the chunk backwards. */ + tls_free_start = tls_lmap->l_tls_offset; + else { + /* + * This isn't contiguous with the last chunk + * freed. One of them will be leaked. + */ + if (tls_free_end == _dl_tls_static_used) + _dl_tls_static_used = tls_free_start; + tls_free_start = tls_lmap->l_tls_offset; + tls_free_end = tls_free_start + + tls_lmap->l_tls_blocksize; + } +# else +# error Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined +# endif + } else { + +#define TLS_DTV_UNALLOCATED ((void *) -1l) + + dtv_t *dtv = THREAD_DTV (); + + _dl_assert(!(dtv[tls_lmap->l_tls_modid].pointer.is_static)); + if (dtv[tls_lmap->l_tls_modid].pointer.val != TLS_DTV_UNALLOCATED) { + /* Note that free is called for NULL is well. We + deallocate even if it is this dtv entry we are + supposed to load. The reason is that we call + memalign and not malloc. */ + _dl_free (dtv[tls_lmap->l_tls_modid].pointer.val); + dtv[tls_lmap->l_tls_modid].pointer.val = TLS_DTV_UNALLOCATED; + } + } + } +#endif + + DL_LIB_UNMAP (tpnt, end); + /* Free elements in RTLD_LOCAL scope list */ + for (runp = tpnt->rtld_local; runp; runp = tmp) { + tmp = runp->next; + free(runp); + } + + /* Next, remove tpnt from the loaded_module list */ + if (_dl_loaded_modules == tpnt) { + _dl_loaded_modules = tpnt->next; + if (_dl_loaded_modules) + _dl_loaded_modules->prev = 0; + } else { + for (run_tpnt = _dl_loaded_modules; run_tpnt; run_tpnt = run_tpnt->next) { + if (run_tpnt->next == tpnt) { + _dl_if_debug_print("removing loaded_modules: %s\n", tpnt->libname); + run_tpnt->next = run_tpnt->next->next; + if (run_tpnt->next) + run_tpnt->next->prev = run_tpnt; + break; + } + } + } + + /* Next, remove tpnt from the global symbol table list */ + if (_dl_symbol_tables) { + if (_dl_symbol_tables->dyn == tpnt) { + _dl_symbol_tables = _dl_symbol_tables->next; + if (_dl_symbol_tables) + _dl_symbol_tables->prev = 0; + } else { + for (rpnt1 = _dl_symbol_tables; rpnt1->next; rpnt1 = rpnt1->next) { + if (rpnt1->next->dyn == tpnt) { + _dl_if_debug_print("removing symbol_tables: %s\n", tpnt->libname); + rpnt1_tmp = rpnt1->next->next; + free(rpnt1->next); + rpnt1->next = rpnt1_tmp; + if (rpnt1->next) + rpnt1->next->prev = rpnt1; + break; + } + } + } + } + free(tpnt->libname); + free(tpnt); + } + } + for (rpnt1 = handle->next; rpnt1; rpnt1 = rpnt1_tmp) { + rpnt1_tmp = rpnt1->next; + free(rpnt1); + } + free(handle->init_fini.init_fini); + free(handle); + +#if defined(USE_TLS) && USE_TLS + /* If we removed any object which uses TLS bump the generation counter. */ + if (any_tls) { + if (__builtin_expect(++_dl_tls_generation == 0, 0)) { + _dl_debug_early("TLS generation counter wrapped! Please report to the uClibc mailing list.\n"); + _dl_exit(30); + } + + if (tls_free_end == _dl_tls_static_used) + _dl_tls_static_used = tls_free_start; + } +#endif + + if (_dl_debug_addr) { + dl_brk = (void (*)(void)) _dl_debug_addr->r_brk; + if (dl_brk != NULL) { + _dl_debug_addr->r_state = RT_DELETE; + (*dl_brk) (); + + _dl_debug_addr->r_state = RT_CONSISTENT; + (*dl_brk) (); + } + } + + return 0; +} + +/* l4: */ int dlclose(void *vhandle); +int dlclose(void *vhandle) +{ + return do_dlclose(vhandle, 1); +} + +/* l4: */ char *dlerror(void); +char *dlerror(void) +{ + const char *retval; + + if (!_dl_error_number) + return NULL; + retval = dl_error_names[_dl_error_number]; + _dl_error_number = 0; + return (char *)retval; +} + +/* + * Dump information to stderr about the current loaded modules + */ +#ifdef __USE_GNU +static const char type[][4] = { "Lib", "Exe", "Int", "Mod" }; + +/* l4: */int dlinfo(void); +int dlinfo(void) +{ + struct elf_resolve *tpnt; + struct dyn_elf *rpnt, *hpnt; + + fprintf(stderr, "List of loaded modules\n"); + /* First start with a complete list of all of the loaded files. */ + for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next) { + fprintf(stderr, "\t%p %p %p %s %d %s\n", + (void *)DL_LOADADDR_BASE(tpnt->loadaddr), tpnt, tpnt->symbol_scope, + type[tpnt->libtype], + tpnt->usage_count, tpnt->libname); + } + + /* Next dump the module list for the application itself */ + fprintf(stderr, "\nModules for application (%p):\n", _dl_symbol_tables); + for (rpnt = _dl_symbol_tables; rpnt; rpnt = rpnt->next) + fprintf(stderr, "\t%p %s\n", rpnt->dyn, rpnt->dyn->libname); + + for (hpnt = _dl_handles; hpnt; hpnt = hpnt->next_handle) { + fprintf(stderr, "Modules for handle %p\n", hpnt); + for (rpnt = hpnt; rpnt; rpnt = rpnt->next) + fprintf(stderr, "\t%p %s\n", rpnt->dyn, rpnt->dyn->libname); + } + return 0; +} + +/* l4: */int dladdr(const void *__address, Dl_info * __info); +int dladdr(const void *__address, Dl_info * __info) +{ + struct elf_resolve *pelf; + struct elf_resolve *rpnt; + + _dl_map_cache(); + + /* + * Try and locate the module address is in + */ + pelf = NULL; + + _dl_if_debug_print("__address: %p __info: %p\n", __address, __info); + + __address = DL_LOOKUP_ADDRESS (__address); + + for (rpnt = _dl_loaded_modules; rpnt; rpnt = rpnt->next) { + struct elf_resolve *tpnt; + + tpnt = rpnt; + + _dl_if_debug_print("Module \"%s\" at %p\n", + tpnt->libname, (void *)DL_LOADADDR_BASE(tpnt->loadaddr)); + + if (DL_ADDR_IN_LOADADDR((ElfW(Addr)) __address, tpnt, pelf)) + pelf = tpnt; + } + + if (!pelf) { + return 0; + } + + /* + * Try and locate the symbol of address + */ + + { + char *strtab; + ElfW(Sym) *symtab; + unsigned int hn, si, sn, sf; + ElfW(Addr) sa = 0; + + /* Set the info for the object the address lies in */ + __info->dli_fname = pelf->libname; + __info->dli_fbase = (void *)pelf->mapaddr; + + symtab = (ElfW(Sym) *) (pelf->dynamic_info[DT_SYMTAB]); + strtab = (char *) (pelf->dynamic_info[DT_STRTAB]); + + sf = sn = 0; + +#ifdef __LDSO_GNU_HASH_SUPPORT__ + if (pelf->l_gnu_bitmask) { + for (hn = 0; hn < pelf->nbucket; hn++) { + si = pelf->l_gnu_buckets[hn]; + if (!si) + continue; + + const Elf32_Word *hasharr = &pelf->l_gnu_chain_zero[si]; + do { + ElfW(Addr) symbol_addr; + + symbol_addr = (ElfW(Addr)) DL_RELOC_ADDR(pelf->loadaddr, symtab[si].st_value); + if (symbol_addr <= (ElfW(Addr))__address && (!sf || sa < symbol_addr)) { + sa = symbol_addr; + sn = si; + sf = 1; + } + _dl_if_debug_print("Symbol \"%s\" at %p\n", strtab + symtab[si].st_name, (void *)symbol_addr); + ++si; + } while ((*hasharr++ & 1u) == 0); + } + } else +#endif + for (hn = 0; hn < pelf->nbucket; hn++) { + for (si = pelf->elf_buckets[hn]; si; si = pelf->chains[si]) { + ElfW(Addr) symbol_addr; + + symbol_addr = (ElfW(Addr)) DL_RELOC_ADDR(pelf->loadaddr, symtab[si].st_value); + if (symbol_addr <= (ElfW(Addr))__address && (!sf || sa < symbol_addr)) { + sa = symbol_addr; + sn = si; + sf = 1; + } + + _dl_if_debug_print("Symbol \"%s\" at %p\n", + strtab + symtab[si].st_name, (void *)symbol_addr); + } + } + + if (sf) { + /* A nearest symbol has been found; fill the entries */ + __info->dli_sname = strtab + symtab[sn].st_name; + __info->dli_saddr = (void *)sa; + } else { + /* No symbol found, fill entries with NULL value, + only the containing object will be returned. */ + __info->dli_sname = NULL; + __info->dli_saddr = NULL; + } + return 1; + } +} +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/man/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/man/Makefile new file mode 100644 index 00000000..d36225f5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/man/Makefile @@ -0,0 +1,22 @@ +# Makefile for uClibc +# +# Copyright (C) 2000,2001,2005 Erik Andersen +# +# Derived in part from the Linux-8086 C library, the GNU C Library, and several +# other sundry sources. Files within this library are copyright by their +# respective copyright holders. +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +include ../Config.mk + +ALL = #ld.so.info + +all: $(ALL) + +ld.so.info: ld.so.texi + makeinfo $< + +clean: + $(RM) $(ALL) *~ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/man/dlopen.3 b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/man/dlopen.3 new file mode 100644 index 00000000..8d1e09e7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/man/dlopen.3 @@ -0,0 +1,218 @@ +.\" -*- nroff -*- +.\" Copyright 1995 Yggdrasil Computing, Incorporated. +.\" written by Adam J. Richter (adam@yggdrasil.com), +.\" with typesetting help from Daniel Quinlan (quinlan@yggdrasil.com). +.\" +.\" This is free documentation; you can redistribute it and/or +.\" modify it under the terms of the GNU General Public License as +.\" published by the Free Software Foundation; either version 2 of +.\" the License, or (at your option) any later version. +.\" +.\" The GNU General Public License's references to "object code" +.\" and "executables" are to be interpreted as the output of any +.\" document formatting or typesetting system, including +.\" intermediate and printed output. +.\" +.\" This manual is distributed in the hope that it will be useful, +.\" but WITHOUT ANY WARRANTY; without even the implied warranty of +.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +.\" GNU General Public License for more details. +.\" +.\" You should have received a copy of the GNU General Public +.\" License along with this manual; if not, write to the Free +.\" Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, +.\" USA. +.\" +.TH DLOPEN 3 "16 May 1995" "Linux" "Linux Programmer's Manual" +.SH NAME +dlclose, dlerror, dlopen, dlsym \- Programming interface to dynamic linking loader. +.SH SYNOPSIS +.B #include +.sp +.BI "void *dlopen (const char *" "filename" ", int " flag "); +.br +.BI "const char *dlerror(void);" +.br +.BI "void *dlsym(void *"handle ", char *"symbol ");" +.br +.BI "int dladdr(void *"address ", Dl_info *"dlip ");" +.br +.BI "int dlclose (void *"handle "); +.sp +Special symbols: +.BR "_init" ", " "_fini" ". " +.SH DESCRIPTION +.B dlopen +loads a dynamic library from the file named by the null terminated +string +.I filename +and returns an opaque "handle" for the dynamic library. +If +.I filename +is not an absolute path (i.e., it does not begin with a "/"), then the +file is searched for in the following locations: +.RS +.PP +A colon-separated list of directories in the user's +\fBLD_LIBRARY\fP path environment variable. +.PP +The list of libraries specified in \fI/etc/ld.so.cache\fP. +.PP +\fI/usr/lib\fP, followed by \fI/lib\fP. +.RE +.PP +If +.I filename +is a NULL pointer, then the returned handle is for the main program. +.PP +External references in the library are resolved using the libraries +in that library's dependency list and any other libraries previously +opened with the +.B RTLD_GLOBAL +flag. +If the executable was linked +with the flag "-rdynamic", then the global symbols in the executable +will also be used to resolve references in a dynamically loaded +library. +.PP +.I flag +must be either +.BR RTLD_LAZY , +meaning resolve undefined symbols as code from the dynamic library is +executed, or +.BR RTLD_NOW , +meaning resolve all undefined symbols before +.B dlopen +returns, and fail if this cannot be done. +Optionally, +.B RTLD_GLOBAL +may be or'ed with +.IR flag, +in which case the external symbols defined in the library will be +made available to subsequently loaded libraries. +.PP +If the library exports a routine named +.BR _init , +then that code is executed before dlopen returns. +If the same library is loaded twice with +.BR dlopen() , +the same file handle is returned. The dl library maintains link +counts for dynamic file handles, so a dynamic library is not +deallocated until +.B dlclose +has been called on it as many times as +.B dlopen +has succeeded on it. +.PP +If +.B dlopen +fails for any reason, it returns NULL. +A human readable string describing the most recent error that occurred +from any of the dl routines (dlopen, dlsym or dlclose) can be +extracted with +.BR dlerror() . +.B dlerror +returns NULL if no errors have occurred since initialization or since +it was last called. (Calling +.B dlerror() +twice consecutively, will always result in the second call returning +NULL.) + +.B dlsym +takes a "handle" of a dynamic library returned by dlopen and the null +terminated symbol name, returning the address where that symbol is +loaded. If the symbol is not found, +.B dlsym +returns NULL; however, the correct way to test for an error from +.B dlsym +is to save the result of +.B dlerror +into a variable, and then check if saved value is not NULL. +This is because the value of the symbol could actually be NULL. +It is also necessary to save the results of +.B dlerror +into a variable because if +.B dlerror +is called again, it will return NULL. +.PP +.B dladdr +returns information about the shared library containing the memory +location specified by +.IR address . +.B dladdr +returns zero on success and non-zero on error. +.PP +.B dlclose +decrements the reference count on the dynamic library handle +.IR handle . +If the reference count drops to zero and no other loaded libraries use +symbols in it, then the dynamic library is unloaded. If the dynamic +library exports a routine named +.BR _fini , +then that routine is called just before the library is unloaded. +.SH EXAMPLES +.B Load the math library, and print the cosine of 2.0: +.RS +.nf +.if t .ft CW +#include + +int main(int argc, char **argv) { + void *handle = dlopen ("/lib/libm.so", RTLD_LAZY); + double (*cosine)(double) = dlsym(handle, "cos"); + printf ("%f\\n", (*cosine)(2.0)); + dlclose(handle); +} +.if t .ft P +.fi +.PP +If this program were in a file named "foo.c", you would build the program +with the following command: +.RS +.LP +gcc -rdynamic -o foo foo.c -ldl +.RE +.RE +.LP +.B Do the same thing, but check for errors at every step: +.RS +.nf +.if t .ft CW +#include +#include + +int main(int argc, char **argv) { + void *handle; + double (*cosine)(double); + char *error; + + handle = dlopen ("/lib/libm.so", RTLD_LAZY); + if (!handle) { + fputs (dlerror(), stderr); + exit(1); + } + + cosine = dlsym(handle, "cos"); + if ((error = dlerror()) != NULL) { + fputs(error, stderr); + exit(1); + } + + printf ("%f\\n", (*cosine)(2.0)); + dlclose(handle); +} +.if t .ft P +.fi +.RE +.SH ACKNOWLEDGEMENTS +The dlopen interface standard comes from Solaris. +The Linux dlopen implementation was primarily written by +Eric Youngdale with help from Mitch D'Souza, David Engel, +Hongjiu Lu, Andreas Schwab and others. +The manual page was written by Adam Richter. +.SH SEE ALSO +.BR ld(1) , +.BR ld.so(8) , +.BR ldconfig(8) , +.BR ldd(1) , +.BR ld.so.info . diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/man/ld.so.8 b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/man/ld.so.8 new file mode 100644 index 00000000..59ec8530 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/man/ld.so.8 @@ -0,0 +1,113 @@ +.TH ld.so 8 "14 March 1998" +.SH NAME +ld.so/ld-linux.so \- dynamic linker/loader +.SH DESCRIPTION +.B ld.so +loads the shared libraries needed by a program, prepares the program +to run, and then runs it. +Unless explicitly specified via the +.B \-static +option to +.B ld +during compilation, all Linux programs are incomplete and require +further linking at run time. +.PP +The necessary shared libraries needed by the program are searched for +in the following order +.IP o +Using the environment variable +.B LD_LIBRARY_PATH +.RB ( LD_AOUT_LIBRARY_PATH +for a.out programs). +Except if the executable is a setuid/setgid binary, in which case it +is ignored. +.IP o +From the cache file +.BR /etc/ld.so.cache +which contains a compiled list of candidate libraries previously found +in the augmented library path. +.IP o +In the default path +.BR /usr/lib , +and then +.BR /lib . +.SH ENVIRONMENT +.TP +.B LD_LIBRARY_PATH +A colon-separated list of directories in which to search for +ELF libraries at execution-time. +Similar to the +.B PATH +environment variable. +.TP +.B LD_PRELOAD +A whitespace-separated list of additional, user-specified, ELF shared +libraries to be loaded before all others. +This can be used to selectively override functions in other shared libraries. +For setuid/setgid ELF binaries, only libraries in the standard search +directories that are also setgid will be loaded. +.TP +.B LD_TRACE_LOADED_OBJECTS +If present, causes the program to list its dynamic library dependencies, +as if run by ldd, instead of running normally. +.TP +.B LD_BIND_NOW +If present, causes the dynamic linker to resolve all symbols at program +startup instead of when they are first referenced. +.TP +.B LD_AOUT_LIBRARY_PATH +A colon-separated list of directories in which to search for +a.out libraries at execution-time. +Similar to the +.B PATH +environment variable. +.TP +.B LD_AOUT_PRELOAD +The name of an additional, user-specified, a.out shared library to be loaded +after all others. +This can be used to selectively override functions in other shared libraries. +.TP +.B LD_NOWARN +Suppress warnings about a.out libraries with incompatible minor +version numbers. +.TP +.B LD_KEEPDIR +Don't ignore the directory in the names of a.out libraries to be loaded. +Use of this option is strongly discouraged. +.SH FILES +.PD 0 +.TP 20 +.B /lib/ld.so +a.out dynamic linker/loader +.TP 20 +.B /lib/ld-linux.so.* +ELF dynamic linker/loader +.TP +.B /etc/ld.so.cache +File containing a compiled list of directories in which to search for +libraries and an ordered list of candidate libraries. +.TP +.B /etc/ld.so.preload +File containing a whitespace separated list of ELF shared libraries to +be loaded before the program. +libraries and an ordered list of candidate libraries. +.TP +.B lib*.so* +shared libraries +.PD +.SH SEE ALSO +.BR ldd (1), +.BR ldconfig (8). +.SH BUGS +.LP +Currently +.B ld.so +has no means of unloading and searching for compatible or newer version of +libraries. +.PP +.B ld.so +functionality is only available for executables compiled using libc version +4.4.3 or greater. +.SH AUTHORS +David Engel, Eric Youngdale, Peter MacDonald, Hongjiu Lu, Linus +Torvalds, Lars Wirzenius and Mitch D'Souza (not necessarily in that order). diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/man/ld.so.texi b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/man/ld.so.texi new file mode 100644 index 00000000..4e5fb841 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/man/ld.so.texi @@ -0,0 +1,411 @@ +\input texinfo @c -*-texinfo-*- +@c %**start of header +@setfilename ld.so.info +@settitle ld.so : Dynamic-Link Library support +@c %**end of header + +@ifinfo +This file documents the dynamic-link support libraries and utilities for the +Linux OS, version 1.8.1. + +Copyright 1996 Michael Deutschmann + +This document is subject to the GNU General Public License as published by +the Free Software foundation, version 2 or later (your choice). + +Note: The software described in this document is under a different copyright +and license. + +@end ifinfo + +@titlepage +@title ld.so +@subtitle Dynamic Link library support for the Linux OS. +@author David Engel +@author Eric Youngdale +@author Peter Macdonald +@author Hongjiu Lu +@author Mitch D'Souza +@author Michael Deutschmann (this documentation) + +@page +Copyright @copyright{} 1996 Michael Deutschmann + +This document is subject to the GNU General Public License as published by +the Free Software foundation, version 2 or later (your choice). + +Note: The software described in this document is under a different copyright +and license. +@end titlepage + +@ifinfo +@node Top +@top + +The @code{ld.so} module provides dynamic linked library support in Linux. +This file documents @code{ld.so} and its companion software. + +@menu +* intro:: Introduction + +* ld.so:: The dynamic linker core program +* ldd:: A utility to print out dependencies +* ldconfig:: A utility to maintain the cache and symlinks +* libdl:: Manual dynamic linking library +@end menu + +@end ifinfo + +@node intro +@unnumbered Introduction + +The @code{ld.so} suite contains special files and utilities needed for linux +to handle @dfn{dynamic libraries}. + +Ordinary static libraries (@file{lib*.a} files) are included into executables +that use their functions. A file that only uses static libraries needs less +intelligence to load, but takes up more space. If many executables use the +same library, there can be much wastage of storage space, since multiple +copies of the library functions are scattered across the executables. +However, static libraries are easier to make. + +Dynamic libraries (@file{lib*.so*} files) are not copied into executables --- +the executable is written in such a way that it will automatically load the +libraries. In linux, the executable will first load the special library +@code{ld.so} or @code{ld-linux.so}, which contains the intelligence +to load further dynamic libraries. Since multiple files end up getting +executable data from the same file, dynamic libraries are also known as +shared libraries. + +Linux executables come in two flavors, @sc{elf} and a.out. + +a.out is the original executable format used by Linux. It has somewhat less +overhead than @sc{elf}. However creating shared libraries for a.out is +@emph{very} involved, and each a.out shared library must be explicitly +registered. + +@sc{elf} is a more recent format, which supports a much simpler method of +creating libraries. @sc{elf} libraries may also be linked manually +(@pxref{libdl}). + +Since many library authors prefer @sc{elf} and no longer release shared a.out +libraries, a.out is moribund on Linux. This version of the @code{ld.so} can +be compiled to support only @sc{elf}, or to support both formats. (The last +release of ld.so to support a.out alone was 1.8.0.) + +@node ld.so +@chapter @code{ld.so}: Dynamic linker core + +@code{ld.so} works behind the scenes to handle dynamic libraries in Linux. +Users will almost never have to deal with it directly, but in special cases +one can send instructions to it through environment variables. Also, if +something is wrong with your libraries (usually an incorrect version) ld.so +will give error messages. + +Actually @code{ld.so} is the a.out linker. The new @sc{elf} executables are +handled by a related program @code{ld-linux.so}. + +@menu +* files:: Configuration files used by the suite +* environment:: Environment settings that tweak @code{ld.so} +* errors:: Complaints @code{ld.so} might make +@end menu + +@node files +@section Configuration Files + +@table @file +@item /etc/ld.so.cache +A file created by @code{ldconfig} and used to speed linking. It's structure +is private to the suite. + +@item /etc/ld.so.conf +A simple list of directories to scan for libraries, in addition to +@file{/usr/lib} and @file{/lib}, which are hardwired. It may contain +comments started with a @samp{#}. + +@item /etc/ld.so.preload +A list of libraries to preload. This allows preloading libraries for +setuid/setgid executables securely. It may contain comments. +@end table + +@node environment +@section Environment Variables + +@table @code +@item LD_AOUT_LIBRARY_PATH +@itemx LD_LIBRARY_PATH +These variables supply a library path for finding dynamic libraries, in the +standard colon seperated format. These variables are ignored when executing +setuid/setgid programs, because otherwise they would be a security hazard. +@code{ld.so} will use @code{LD_AOUT_LIBRARY_PATH} and @code{ld-linux.so} will +use @code{LD_LIBRARY_PATH}. + +@item LD_AOUT_PRELOAD +@itemx LD_PRELOAD +These variables allow an extra library not specified in the executable to be +loaded. Generally this is only useful if you want to override a function. +These are also ignored when running setuid/setgid executables. @code{ld.so} +will use @code{LD_AOUT_PRELOAD} and @code{ld-linux.so} will use +@code{LD_PRELOAD}. + +@item LD_NOWARN +If non-empty, errors about incompatible minor revisions are suppressed. + +@item LD_KEEPDIR +If non-empty, allow executables to specify absolute library names. This +option is deprecated. +@c FIXME: +@c The following are things I noticed in the ld-linux.so source. +@c I don't really understand 'em. Could someone help me? +@c +@c @item LD_BIND_NOW +@c This option is used by the @code{ld-linux.so} only. I don't know +@c what it does. (I suspect, looking at the code, that it specifies +@c "RTLD_NOW" rather than "RTLD_LAZY" mode for the shared libraries.) +@c +@c @item LD_TRACE_LOADED_OBJECTS +@c @itemx LD_WARN +@c These seem to have something to do with the communication between the +@c @code{ld-linux.so} and @code{ldd}. I don't know more. +@end table + +@node errors +@section Errors + +@table @samp +@item Can't find library @var{library} +The executable required a dynamically linked library that ld.so cannot find. +Your symbolic links may be not set right, or you may have not installed a +library needed by the program. + +@item Can't load library @var{library} +The library is corrupt. + +@item Incompatible library @var{library} +@itemx Require major version @var{x} and found @var{y} +Your version of the library is incompatible with the executable. Recompiling +the executable, or upgrading the library will fix the problem. + +@item using incompatible library @var{library} +@itemx Desire minor version >= @var{x} and found @var{y}. +Your version of the library is older than that expected by the executable, +but not so old that the library interface has radically changed, so the +linker will attempt to run anyway. There is a chance that it will work, but +you should upgrade the library or recompile the software. The environment +variable @code{LD_NOWARN} can be used to supress this message. + +@item too many directories in library path +The linker only supports up to 32 library directories. You have too many. + +@item dynamic linker error in @var{blah} +The linker is having trouble handling a binary - it is probably corrupt. + +@item can't map cache file @var{cache-file} +@itemx cache file @var{cache-file} @var{blah} +The linker cache file (generally @file{/etc/ld.so.cache}) is corrupt or +non-existent. These errors can be ignored, and can be prevented by +regenerating the cache file with @code{ldconfig}. +@end table + +@node ldd +@chapter @code{ldd}: Dependency scanner + +@code{ldd} is a utility that prints out the dynamic libraries that an +executable is linked to. + +Actually @code{ldd} works by signalling ld.so to print the dependencies. +For a.out executables this is done by starting the executable with +@code{argc} equal to 0. The linker detects this and prints the dependencies. +(This can cause problems with @emph{very} old binaries, which would run as +normal only with an inappropriate @code{argc}.) + +For @sc{elf} executables, special environment variables are used to tell the +linker to print the dependencies. + +@code{ldd} has a few options: + +@table @samp +@item -v +Print the version number of @code{ldd} itself + +@item -V +Print the version number of the dynamic linker + +@item -d +Report missing functions. This is only supported for @sc{elf} executables. + +@item -r +Report missing objects. This is also only available for @sc{elf} +executables. +@end table + +@node ldconfig +@chapter @code{ldconfig}: Setup program + +This utility is used by the system administrator to automatically set up +symbolic links needed by the libraries, and also to set up the cache file. + +@code{ldconfig} is run after new dynamic libraries are installed, and if the +cache file or links are damaged. It is also run when upgrading the +@code{ld.so} suite itself. + +The @file{/lib} and @file{/usr/lib} directories, and any listed in the file +@file{/etc/ld.so.conf} are scanned by default unless @samp{-n} is used. +Additional directories may be specified on the command line. + +It has the following options: + +@table @samp +@item -D +Enter debug mode. Implies @samp{-N} and @samp{-X}. + +@item -v +Verbose. Print out links created and directories scanned. + +@item -n +Check directories specified on the commandline @emph{only}. + +@item -N +Do not regenerate the cache. + +@item -X +Do not rebuild symbolic links. + +@item -l +Set up symbolic links for only libraries presented on the command line. + +@item -p +Print out the library pathnames in the cache file (@file{/etc/ld.so.cache}) +@end table + +@node libdl +@chapter User dynamic linking library + +The @code{ld.so} package includes a small library of functions +(@code{libdl}) to allow manual dynamic linking. Normally programs are linked +so that dynamic functions and objects are automagically available. These +functions allow one to manually load and access a symbol from a library. +They are only available for @sc{elf} executables. + +@menu +* using libdl:: General points +* functions:: How to use the functions +* example:: A sample program +@end menu + +@node using libdl +@section Overview + +To access this library, add the flag @samp{-ldl} to your compile command when +linking the executable. You also must include the header file +@code{dlfcn.h}. You may also need the flag @samp{-rdynamic}, which enables +resolving references in the loaded libraries against your executable. + +Generally, you will first use @code{dlopen} to open a library. Then you use +@code{dlsym} one or more times to access symbols. Finally you use +@code{dlclose} to close the library. + +These facilities are most useful for language interpreters that provide +access to external libraries. Without @code{libdl}, it would be neccessary +to link the interpreter executable with any and all external libraries +needed by the programs it runs. With @code{libdl}, the interpreter only +needs to be linked with the libraries it uses itself, and can dynamically +load in additional ones if programs need it. + +@node functions +@section Functions + +@deftypefun void *dlopen ( const char @var{filename}, int @var{flags} ) + +This function opens the dynamic library specified by @var{filename} +and returns an abstract handle, which can be used in subsequent calls to +@code{dlsym}. The function will respect the @code{LD_ELF_LIBRARY_PATH} and +@code{LD_LIBRARY_PATH} environment variables. + +@end deftypefun + +The following flags can be used with @code{dlopen}: + +@deftypevr Macro int RTLD_LAZY +Resolve symbols in the library as they are needed. +@end deftypevr + +@deftypevr Macro int RTLD_NOW +Resolve all symbols in the library before returning, and fail if not all can +be resolved. This is mutually exclusive with @code{RTLD_LAZY}. +@end deftypevr + +@deftypevr Macro int RTLD_GLOBAL +Make symbols in this library available for resolving symbols in other +libraries loaded with @code{dlopen}. +@end deftypevr + +@deftypefun int dlclose ( void *@var{handle} ) + +This function releases a library handle. + +Note that if a library opened twice, the handle will be the same. However, +a reference count is used, so you should still close the library as many +times as you open it. + +@end deftypefun + +@deftypefun void *dlsym (void *@var{handle},char *@var{symbol-name}) + +This function looks up the name @var{symbol-name} in the library and returns +it in the void pointer. + +If there is an error, a null pointer will be returned. However, it is +possible for a valid name in the library to have a null value, so +@code{dlerror} should be used to check if there was an error. + +@end deftypefun + +@deftypefun {libdl function} {const char} *dlerror( void ) + +This function is used to read the error state. It returns a human-readable +string describing the last error, or null, meaning no error. + +The function resets the error value each time it is called, so the result +should be copied into a variable. If the function is called more than once +after an error, the second and subsequent calls will return null. + +@end deftypefun + +@node example +@section Example program + +Here is an example program that prints the cosine of two by manually linking +to the math library: + +@example +@c The following was snarfed verbatim from the dlopen.3 man file. +#include +#include + +int main(int argc, char **argv) @{ + void *handle; + double (*cosine)(double); + char *error; + + handle = dlopen ("/lib/libm.so", RTLD_LAZY); + if (!handle) @{ + fputs (dlerror(), stderr); + exit(1); + @} + + cosine = dlsym(handle, "cos"); + if ((error = dlerror()) != NULL) @{ + fputs(error, stderr); + exit(1); + @} + + printf ("%f\\n", (*cosine)(2.0)); + dlclose(handle); +@} +@end example + +@contents + +@bye diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/man/ldconfig.8 b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/man/ldconfig.8 new file mode 100644 index 00000000..82285291 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/man/ldconfig.8 @@ -0,0 +1,189 @@ +.TH ldconfig 8 "14 March 1998" +.SH NAME +ldconfig \- determine run-time link bindings +.SH SYNOPSIS +ldconfig +.RB [ \-DvqnNX ] +.RB [ \-f\ conf ] +.RB [ \-C\ cache ] +.RB [ \-r\ root ] +.IR directory \ ... +.PD 0 +.PP +.PD +ldconfig +.B \-l +.RB [ \-Dvq ] +.IR library \ ... +.PD 0 +.PP +.PD +ldconfig +.B \-p +.SH DESCRIPTION +.B ldconfig +creates the necessary links and cache (for use by the run-time linker, +.IR ld.so ) +to the most recent shared libraries found in the directories specified +on the command line, in the file +.IR /etc/ld.so.conf , +and in the trusted directories +.RI ( /usr/lib +and +.IR /lib ). +.B ldconfig +checks the header and file names of the libraries it encounters when +determining which versions should have their links updated. +.B ldconfig +ignores symbolic links when scanning for libraries. +.PP +.B ldconfig +will attempt to deduce the type of ELF libs (ie. libc5 or libc6/glibc) +based on what C libs if any the library was linked against, therefore when +making dynamic libraries, it is wise to explicitly link against libc (use -lc). +.PP +Some existing libs do not contain enough information to allow the deduction of +their type, therefore the +.IR /etc/ld.so.conf +file format allows the specification of an expected type. This is +.B only +used for those ELF libs which we can not work out. The format +is like this "dirname=TYPE", where type can be libc4, libc5 or libc6. +(This syntax also works on the command line). Spaces are +.B not +allowed. Also see the +.B -p +option. +.PP +Directory names containing an +.B = are no longer legal +unless they also have an expected type specifier. +.PP +.B ldconfig +should normally be run by the super-user as it may require write +permission on some root owned directories and files. +It is normally run automatically at bootup, from /etc/rc, or manually +whenever new DLL's are installed. +.SH OPTIONS +.TP +.B \-D +Debug mode. +Implies +.B \-N +and +.BR \-X . +.TP +.B \-v +Verbose mode. +Print current version number, the name of each directory as it +is scanned and any links that are created. +Overrides quiet mode. +.TP +.B \-q +Quiet mode. +Don't print warnings. +.TP +.B \-n +Only process directories specified on the command line. +Don't process the trusted directories +.RI ( /usr/lib +and +.IR /lib ) +nor those specified in +.IR /etc/ld.so.conf . +Implies +.BR \-N . +.TP +.B \-N +Don't rebuild the cache. +Unless +.B \-X +is also specified, links are still updated. +.TP +.B \-X +Don't update links. +Unless +.B \-N +is also specified, the cache is still rebuilt. +.TP +.B \-f conf +Use +.B conf +instead of +.IR /etc/ld.so.conf . +.TP +.B \-C cache +Use +.B cache +instead of +.IR /etc/ld.so.cache . +.TP +.B \-r root +Change to and use +.B root +as the root directory. +.TP +.B \-l +Library mode. +Manually link individual libraries. +Intended for use by experts only. +.TP +.B \-p +Print the lists of directories and candidate libraries stored in +the current cache. +.SH EXAMPLES +In the bootup file +.I /etc/rc +having the line +.RS + +/sbin/ldconfig -v + +.RE +will set up the correct links for the shared binaries and rebuild +the cache. +.TP +On the command line +.RS + +# /sbin/ldconfig -n /lib + +.RE +as root after the installation of a new DLL, will properly update the +shared library symbolic links in /lib. + +.SH FILES +.PD 0 +.TP 20 +.B /lib/ld.so +execution time linker/loader +.TP 20 +.B /etc/ld.so.conf +File containing a list of colon, space, tab, newline, or comma spearated +directories in which to search for libraries. +.TP 20 +.B /etc/ld.so.cache +File containing an ordered list of libraries found in the directories +specified in +.BR /etc/ld.so.conf . +.TP +.B lib*.so.version +shared libraries +.PD +.SH SEE ALSO +.BR ldd (1), +.BR ld.so (8). +.SH BUGS +.LP +.BR ldconfig 's +functionality, in conjunction with +.BR ld.so , +is only available for executables compiled using libc version 4.4.3 or greater. +.PP +.BR ldconfig , +being a user process, must be run manually and has no means of dynamically +determining and relinking shared libraries for use by +.BR ld.so +when a new DLL is installed. +.SH AUTHORS +David Engel and Mitch D'Souza. diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/ldso/man/ldd.1 b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/man/ldd.1 new file mode 100644 index 00000000..20c55784 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/ldso/man/ldd.1 @@ -0,0 +1,59 @@ +.\" Copyright 1995-2000 David Engel (david@ods.com) +.\" Copyright 1995 Rickard E. Faith (faith@cs.unc.edu) +.\" Most of this was copied from the README file. Do not restrict distribution. +.\" May be distributed under the GNU General Public License +.TH LDD 1 "14 March 1998" +.SH NAME +ldd \- print shared library dependencies +.SH SYNOPSIS +.B ldd +.RB [ \-vVdr ] +program|library ... +.SH DESCRIPTION +.B ldd +prints the shared libraries required by each program or shared library +specified on the command line. +If a shared library name does not contain a '/', +.B ldd +attempts to locate the library in the standard locations. +To run +.B ldd +on a shared library in the current directory, a "./" must be prepended +to its name. +.SH OPTIONS +.TP +.B \-v +Print the version number of +.BR ldd . +.TP +.B \-V +Print the version number of the dynamic linker, +.BR ld.so . +.TP +.B \-d +Perform relocations and report any missing functions (ELF only). +.TP +.B \-r +Perform relocations for both data objects and functions, and +report any missing objects (ELF only). +.SH BUGS +.B ldd +does not work very well on libc.so.5 itself. +.PP +.B ldd +does not work on a.out shared libraries. +.PP +.B ldd +does not work with some extremely old a.out programs which were +built before +.B ldd +support was added to the compiler releases. +If you use +.B ldd +on one of these programs, the program will attempt to run with argc = 0 and +the results will be unpredictable. +.SH AUTHOR +David Engel. +.SH SEE ALSO +.BR ldconfig (8), +.BR ld.so (8). diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libc/Makefile new file mode 100644 index 00000000..c8dc9b46 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../ +top_builddir=../ +include $(top_builddir)Rules.mak +all: libs +include Makefile.in +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/libc/Makefile.in new file mode 100644 index 00000000..dd666ac7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/Makefile.in @@ -0,0 +1,103 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +libc_DIR := $(top_srcdir)libc +libc_OUT := $(top_builddir)libc + +# Check if the target architecture has a version script for +# libc, and if so, include it when linking. +VERSION_SCRIPT := $(wildcard $(libc_DIR)/sysdeps/linux/$(TARGET_ARCH)/libc.map) +ifneq ($(VERSION_SCRIPT),) +VERSION_SCRIPT := -Wl,--version-script,$(VERSION_SCRIPT) +endif + +LDFLAGS-libc.so := $(LDFLAGS) $(VERSION_SCRIPT) -Wl,-init,$(SYMBOL_PREFIX)__uClibc_init +ifeq ($(UCLIBC_HAS_STDIO_FUTEXES),y) +CFLAGS += -D__USE_STDIO_FUTEXES__ +endif +LIBS-libc.so := $(interp) $(ldso) $(top_builddir)lib/$(NONSHARED_LIBNAME) + +# we have SHARED_LIBNAME=libc.so.$(ABI_VERSION) defined in Rules.mak +libc_FULL_NAME := libuClibc-$(VERSION).so + +# this comes first, so duplicate removal works correctly +include $(libc_DIR)/sysdeps/Makefile.in + +include $(libc_DIR)/misc/Makefile.in +include $(libc_DIR)/pwd_grp/Makefile.in +include $(libc_DIR)/stdio/Makefile.in +include $(libc_DIR)/string/Makefile.in +include $(libc_DIR)/termios/Makefile.in +include $(libc_DIR)/inet/Makefile.in +include $(libc_DIR)/signal/Makefile.in +include $(libc_DIR)/stdlib/Makefile.in +include $(libc_DIR)/unistd/Makefile.in + +ifeq ($(DOPIC),y) +libc-a-y = $(libc-y:.o=.os) $(libc-static-y:.o=.os) +else +libc-a-y = $(libc-y) $(libc-static-y) +endif + +ifeq ($(DOMULTI),n) +libc-so-y = $(libc-y:.o=.os) $(libc-shared-y) +else +all_sources = $(libc-y:.o=.c) +all_sources += $(libc-shared-y:.oS=.c) +libc-multi-y = $(filter-out $(libc-nomulti-y:.o=.c),$(all_sources)) +endif + +lib-a-y += $(top_builddir)lib/libc.a +lib-gdb-y += $(top_builddir)lib/libc.gdb +lib-so-y += $(libc.depend) +objclean-y += CLEAN_libc + +OUTPUT_FORMAT = $(CC) $(CFLAGS) -Wl,--verbose 2>&1 | $(SED) -n '/OUTPUT_FORMAT/,/)/p' + +ifeq ($(DOMULTI),n) +$(libc.depend): $(libc_OUT)/libc_so.a $(LIBS-libc.so) + $(call link.so,$(libc_FULL_NAME),$(ABI_VERSION)) +else +$(libc.depend): $(libc_OUT)/libc.oS $(libc-nomulti-y:.o=.oS) | $(LIBS-libc.so) + $(call linkm.so,$(libc_FULL_NAME),$(ABI_VERSION)) +endif + $(Q)$(RM) $@ + $(Q)cat $(top_srcdir)extra/scripts/format.lds > $@.tmp + $(Q)$(OUTPUT_FORMAT) >> $@.tmp +ifeq ($(COMPAT_ATEXIT),y) + $(Q)echo "GROUP ( $(NONSHARED_LIBNAME) $(SHARED_LIBNAME) $(ASNEEDED) )" >> $@.tmp +else + $(Q)echo "GROUP ( $(SHARED_LIBNAME) $(NONSHARED_LIBNAME) $(ASNEEDED) )" >> $@.tmp +endif + $(Q)mv $@.tmp $@ + +$(libc_OUT)/libc_so.a: $(libc-so-y) | $(top_builddir)lib/libc.a $(top_builddir)lib/$(NONSHARED_LIBNAME) + $(Q)$(RM) $@ +ifeq ($(DOPIC),y) + $(Q)$(STRIPTOOL) $(STRIP_FLAGS) $(libc-shared-y) +else + $(do_strip) +endif + $(do_ar) + +$(libc_OUT)/libc.oS: $(libc-multi-y) | $(top_builddir)lib/libc.a $(top_builddir)lib/$(NONSHARED_LIBNAME) + $(Q)$(RM) $@ + $(compile-m) + +$(top_builddir)lib/libc.a: $(libc-a-y) | $(crt-y) + $(Q)$(INSTALL) -d $(dir $@) + $(Q)$(RM) $@ + $(do_ar) + +# We use libc_so.a so that we can compile the shared library with special +# flags - i.e. -mleaf-id-shared-library. The static libc.a needs to be +# compiled without it. +$(top_builddir)lib/libc.gdb: $(libc_OUT)/libc_so.a $(LINK_FLAT_CRTS) + $(call link-flat.so,$(@:.gdb=),$(UCLIBC_SHARED_FLAT_ID)) + +CLEAN_libc: + $(do_rm) $(addprefix $(libc_OUT)/*., o os oS a) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/.indent.pro b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/.indent.pro new file mode 100644 index 00000000..492ecf1c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/.indent.pro @@ -0,0 +1,33 @@ +--blank-lines-after-declarations +--blank-lines-after-procedures +--break-before-boolean-operator +--no-blank-lines-after-commas +--braces-on-if-line +--braces-on-struct-decl-line +--comment-indentation25 +--declaration-comment-column25 +--no-comment-delimiters-on-blank-lines +--cuddle-else +--continuation-indentation4 +--case-indentation0 +--else-endif-column33 +--space-after-cast +--line-comments-indentation0 +--declaration-indentation1 +--dont-format-first-column-comments +--dont-format-comments +--honour-newlines +--indent-level4 +/* changed from 0 to 4 */ +--parameter-indentation4 +--line-length78 /* changed from 75 */ +--continue-at-parentheses +--no-space-after-function-call-names +--dont-break-procedure-type +--dont-star-comments +--leave-optional-blank-lines +--dont-space-special-semicolon +--tab-size4 +/* additions by Mark */ +--case-brace-indentation0 +--leave-preprocessor-space diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/Makefile new file mode 100644 index 00000000..11f362a5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../ +top_builddir=../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/Makefile.in new file mode 100644 index 00000000..abcf2f7d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/Makefile.in @@ -0,0 +1,63 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +subdirs += libc/inet + +include $(top_srcdir)libc/inet/rpc/Makefile.in + +INET_DIR := $(top_srcdir)libc/inet +INET_OUT := $(top_builddir)libc/inet + +CFLAGS-inet := -DRESOLVER="\"resolv.c\"" +CSRC-y := +# des uses ntohl +CSRC-$(findstring y,$(UCLIBC_HAS_CRYPT_IMPL)$(UCLIBC_HAS_IPV4)$(UCLIBC_HAS_IPV6)) += ntohl.c +CSRC-$(findstring y,$(UCLIBC_HAS_IPV4)$(UCLIBC_HAS_IPV6)) += \ + getservice.c getproto.c getnet.c hostid.c \ + inet_net.c herror.c if_index.c gai_strerror.c getaddrinfo.c \ + ifaddrs.c ntop.c +CSRC-$(UCLIBC_HAS_IPV6) += in6_addr.c +# multi source addr.c +CSRC-$(findstring y,$(UCLIBC_HAS_IPV4)$(UCLIBC_HAS_IPV6)) += \ + inet_aton.c inet_addr.c inet_ntoa.c inet_makeaddr.c \ + inet_lnaof.c inet_netof.c +# multi source resolv.c +CSRC-$(findstring y,$(UCLIBC_HAS_IPV4)$(UCLIBC_HAS_IPV6)) += \ + encodeh.c decodeh.c encoded.c decoded.c \ + encodeq.c encodea.c \ + read_etc_hosts_r.c \ + dnslookup.c opennameservers.c closenameservers.c \ + getnameinfo.c \ + gethostent.c gethostent_r.c +CSRC-$(findstring y,$(UCLIBC_HAS_IPV4)$(UCLIBC_HAS_IPV6)) += \ + get_hosts_byaddr_r.c get_hosts_byname_r.c \ + gethostbyaddr_r.c gethostbyname_r.c gethostbyname2_r.c \ + gethostbyaddr.c gethostbyname.c gethostbyname2.c +CSRC-$(findstring y,$(UCLIBC_HAS_IPV4)$(UCLIBC_HAS_IPV6)) += \ + res_init.c res_query.c res_comp.c ns_name.c \ + _res_state.c +## # unused ATM +## CSRC-y += encodep.c decodep.c formquery.c + +# multi source socketcalls.c +socketcalls_CSRC += \ + accept.c bind.c connect.c getpeername.c getsockname.c \ + getsockopt.c listen.c recv.c recvfrom.c recvmsg.c send.c sendmsg.c \ + sendto.c setsockopt.c shutdown.c socket.c socketpair.c +CSRC-$(UCLIBC_HAS_SOCKET) += $(socketcalls_CSRC) opensock.c + +CSRC-$(findstring y,$(UCLIBC_HAS_SOCKET)$(UCLIBC_HAS_IPV4)$(UCLIBC_HAS_IPV6)) += ethers.c ether_addr.c + +INET_SRC := $(patsubst %.c,$(INET_DIR)/%.c,$(CSRC-y)) +INET_OBJ := $(patsubst %.c,$(INET_OUT)/%.o,$(CSRC-y)) + +libc-y += $(INET_OBJ) + +objclean-y += CLEAN_libc/inet + +CLEAN_libc/inet: + $(do_rm) $(addprefix $(INET_OUT)/*., o os) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/_res_state.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/_res_state.c new file mode 100644 index 00000000..dc0d89f4 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/_res_state.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2006 Steven J. Hill + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_res_state +#include RESOLVER diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/accept.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/accept.c new file mode 100644 index 00000000..0217a687 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/accept.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_accept +#include "socketcalls.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/addr.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/addr.c new file mode 100644 index 00000000..c71d4d4f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/addr.c @@ -0,0 +1,210 @@ +/* Copyright (C) 1995,1996 Robert de Bath + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* + * Manuel Novoa III Dec 2000 + * + * Converted to use my new (un)signed long (long) to string routines, which + * are smaller than the previous functions and don't require static buffers. + * In the process, removed the reference to strcat and cut object size of + * inet_ntoa in half (from 190 bytes down to 94). + * + * Manuel Novoa III Feb 2002 + * + * Changed to use _int10tostr. + */ + +#define __FORCE_GLIBC +#include +#include +#include +#include +#include +#include +#include + +#ifdef L_inet_aton +/* + * More undocumented inet_aton features. + * (read: uclibc doesnt support but glibc does) + * http://www.mkssoftware.com/docs/man3/inet_aton.3.asp + * + * *cp can take the form of: + * a.b.c.d - {a,b,c,d} -> 1 byte + * a.b.c - {a,b} -> 1 byte {c} -> 2 bytes + * a.b - {a} -> 1 byte {b} -> 3 bytes + * a - {a} -> 4 bytes + * + * Each part may be decimal, octal, or hexadecimal as in ISO C. + * 0x or 0X -> hexadecimal + * leading 0 -> octal + * all else -> decimal + */ +int inet_aton(const char *cp, struct in_addr *addrptr) +{ + in_addr_t addr; + int value; + int part; + + if (cp == NULL) { + return 0; + } + + addr = 0; + for (part = 1; part <= 4; part++) { + + if (!isdigit(*cp)) + return 0; + + value = 0; + while (isdigit(*cp)) { + value *= 10; + value += *cp++ - '0'; + if (value > 255) + return 0; + } + + if (part < 4) { + if (*cp++ != '.') + return 0; + } else { + char c = *cp++; + if (c != '\0' && !isspace(c)) + return 0; + } + + addr <<= 8; + addr |= value; + } + + /* W. Richard Stevens in his book UNIX Network Programming, + * Volume 1, second edition, on page 71 says: + * + * An undocumented feature of inet_aton is that if addrptr is + * a null pointer, the function still performs it validation + * of the input string, but does not store the result. + */ + if (addrptr) { + addrptr->s_addr = htonl(addr); + } + + return 1; +} +libc_hidden_def(inet_aton) +#endif + +#ifdef L_inet_addr + +in_addr_t inet_addr(const char *cp) +{ + struct in_addr a; + + if (!inet_aton(cp, &a)) + return INADDR_NONE; + else + return a.s_addr; +} +libc_hidden_def(inet_addr) +#endif + +#ifdef L_inet_ntoa + +#define INET_NTOA_MAX_LEN 16 /* max 12 digits + 3 '.'s + 1 nul */ + +char *inet_ntoa_r(struct in_addr in, char buf[INET_NTOA_MAX_LEN]) +{ + in_addr_t addr = ntohl(in.s_addr); + int i; + char *p, *q; + + q = 0; + p = buf + INET_NTOA_MAX_LEN - 1; /* cannot use sizeof(buf) here */ + for (i = 0; i < 4; i++ ) { + p = _int10tostr(p, addr & 0xff) - 1; + addr >>= 8; + if (q) { + *q = '.'; + } + q = p; + } + + return p+1; +} +libc_hidden_def(inet_ntoa_r) + +char *inet_ntoa(struct in_addr in) +{ + static char buf[INET_NTOA_MAX_LEN]; + return inet_ntoa_r(in, buf); +} +libc_hidden_def(inet_ntoa) +#endif + +#ifdef L_inet_makeaddr + +/* for some reason it does not remove the jump relocation */ + +/* + * Formulate an Internet address from network + host. Used in + * building addresses stored in the ifnet structure. + */ +struct in_addr inet_makeaddr(in_addr_t net, in_addr_t host) +{ + in_addr_t addr; + + if (net < 128) + addr = (net << IN_CLASSA_NSHIFT) | (host & IN_CLASSA_HOST); + else if (net < 65536) + addr = (net << IN_CLASSB_NSHIFT) | (host & IN_CLASSB_HOST); + else if (net < 16777216UL) + addr = (net << IN_CLASSC_NSHIFT) | (host & IN_CLASSC_HOST); + else + addr = net | host; + addr = htonl(addr); + return *(struct in_addr *)&addr; +} +libc_hidden_def(inet_makeaddr) +#endif + +#ifdef L_inet_lnaof +/* + * Return the local network address portion of an + * internet address; handles class a/b/c network + * number formats. + */ +in_addr_t inet_lnaof(struct in_addr in) +{ + in_addr_t i = ntohl(in.s_addr); + + if (IN_CLASSA(i)) + return (i & IN_CLASSA_HOST); + else if (IN_CLASSB(i)) + return (i & IN_CLASSB_HOST); + else + return (i & IN_CLASSC_HOST); +} +#endif + +#ifdef L_inet_netof + +/* + * Return the network number from an internet + * address; handles class a/b/c network #'s. + */ +in_addr_t +inet_netof(struct in_addr in) +{ + in_addr_t i = ntohl(in.s_addr); + + if (IN_CLASSA(i)) + return ((i & IN_CLASSA_NET) >> IN_CLASSA_NSHIFT); + else if (IN_CLASSB(i)) + return ((i & IN_CLASSB_NET) >> IN_CLASSB_NSHIFT); + else + return ((i & IN_CLASSC_NET) >> IN_CLASSC_NSHIFT); +} +libc_hidden_def(inet_netof) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/bind.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/bind.c new file mode 100644 index 00000000..d13e2262 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/bind.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_bind +#include "socketcalls.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/closenameservers.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/closenameservers.c new file mode 100644 index 00000000..65889a79 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/closenameservers.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_closenameservers +#include RESOLVER diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/connect.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/connect.c new file mode 100644 index 00000000..bddbe16e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/connect.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_connect +#include "socketcalls.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/decodea.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/decodea.c new file mode 100644 index 00000000..112d5d9e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/decodea.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_decodea +#include RESOLVER diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/decoded.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/decoded.c new file mode 100644 index 00000000..378cbfad --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/decoded.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_decoded +#include RESOLVER diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/decodeh.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/decodeh.c new file mode 100644 index 00000000..7744287f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/decodeh.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_decodeh +#include RESOLVER diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/decodep.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/decodep.c new file mode 100644 index 00000000..0e946e01 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/decodep.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_decodep +#include RESOLVER diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/decodeq.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/decodeq.c new file mode 100644 index 00000000..9e36b95d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/decodeq.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_decodeq +#include RESOLVER diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/dnslookup.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/dnslookup.c new file mode 100644 index 00000000..b9f59a2f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/dnslookup.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_dnslookup +#include RESOLVER diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/encodea.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/encodea.c new file mode 100644 index 00000000..b42ee4a7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/encodea.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_encodea +#include RESOLVER diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/encoded.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/encoded.c new file mode 100644 index 00000000..27f92bec --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/encoded.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_encoded +#include RESOLVER diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/encodeh.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/encodeh.c new file mode 100644 index 00000000..6a69a948 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/encodeh.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_encodeh +#include RESOLVER diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/encodep.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/encodep.c new file mode 100644 index 00000000..d298c213 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/encodep.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_encodep +#include RESOLVER diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/encodeq.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/encodeq.c new file mode 100644 index 00000000..5555aa54 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/encodeq.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_encodeq +#include RESOLVER diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/ether_addr.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/ether_addr.c new file mode 100644 index 00000000..621c6298 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/ether_addr.c @@ -0,0 +1,100 @@ +/* Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1996. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. +*/ + +/* + * 2002-12-24 Nick Fedchik + * - initial uClibc port + */ + +#define __FORCE_GLIBC +#include +#include +#include +#include +#include +#include + +struct ether_addr *ether_aton_r(const char *asc, struct ether_addr *addr) +{ + /* asc is "X:XX:XX:x:xx:xX" */ + int cnt; + + for (cnt = 0; cnt < 6; ++cnt) { + unsigned char number; + char ch; + + /* | 0x20 is cheap tolower(), valid for letters/numbers only */ + ch = (*asc++) | 0x20; + if ((ch < '0' || ch > '9') && (ch < 'a' || ch > 'f')) + return NULL; + number = !(ch > '9') ? (ch - '0') : (ch - 'a' + 10); + + ch = *asc++; + if ((cnt != 5 && ch != ':') /* not last group */ + /* What standard says ASCII ether address representation + * may also finish with whitespace, not only NUL? + * We can get rid of isspace() otherwise */ + || (cnt == 5 && ch != '\0' /*&& !isspace(ch)*/) + ) { + ch |= 0x20; /* cheap tolower() */ + if ((ch < '0' || ch > '9') && (ch < 'a' || ch > 'f')) + return NULL; + number = (number << 4) + (!(ch > '9') ? (ch - '0') : (ch - 'a' + 10)); + + if (cnt != 5) { + ch = *asc++; + if (ch != ':') + return NULL; + } + } + + /* Store result. */ + addr->ether_addr_octet[cnt] = number; + } + /* Looks like we allow garbage after last group? + * "1:2:3:4:5:66anything_at_all"? */ + + return addr; +} +libc_hidden_def(ether_aton_r) + +struct ether_addr *ether_aton(const char *asc) +{ + static struct ether_addr result; + + return ether_aton_r(asc, &result); +} + +char *ether_ntoa_r(const struct ether_addr *addr, char *buf) +{ + sprintf(buf, "%x:%x:%x:%x:%x:%x", + addr->ether_addr_octet[0], addr->ether_addr_octet[1], + addr->ether_addr_octet[2], addr->ether_addr_octet[3], + addr->ether_addr_octet[4], addr->ether_addr_octet[5]); + return buf; +} +libc_hidden_def(ether_ntoa_r) + +char *ether_ntoa(const struct ether_addr *addr) +{ + static char asc[18]; + + return ether_ntoa_r(addr, asc); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/ethers.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/ethers.c new file mode 100644 index 00000000..857e5d16 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/ethers.c @@ -0,0 +1,122 @@ +/* + * libc/inet/ethers.c + * + * Programmatic interface for the /etc/ethers file + * + * Copyright 2007 by Matthew Wilcox + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include + +#define ETHER_LINE_LEN 256 + +/* + * Internal function which returns a pointer to the part of the line + * with the start of the hostname, or NULL if we couldn't parse the line. + * Note that this line may have a comment symbol on it somewhere; if so + * it will return NULL if the # is before or within the ether_addr, and + * succeed if the # is before or within the host. It's up to the callers + * to be aware of this. + * + * I would have preferred to write a NUL to the location of the comment + * character, but ether_line takes a const argument. See __ether_line_w. + */ +static const char *__ether_line(const char *line, struct ether_addr *addr) +{ + struct ether_addr *res = ether_aton_r(line, addr); + if (!res) + return NULL; + + while (*line && (*line != ' ') && (*line != '\t')) + line++; + while (*line && ((*line == ' ') || (*line == '\t'))) + line++; + return (*line) ? line : NULL; +} + +/* + * Strips out the comment before calling __ether_line. We can do this, + * since we know the buffer is writable. + */ +static const char *__ether_line_w(char *line, struct ether_addr *addr) +{ + char *end = strchr(line, '#'); + if (!end) + end = strchr(line, '\n'); + if (end) + *end = '\0'; + return __ether_line(line, addr); +} + +int ether_line(const char *line, struct ether_addr *addr, char *hostname) +{ + const char *name = __ether_line(line, addr); + if (!name) + return -1; + + while (*name) { + if ((*name == '#') || isspace(*name)) + break; + *hostname++ = *name++; + } + *hostname = '\0'; + + return 0; +} + +int ether_ntohost(char *hostname, const struct ether_addr *addr) +{ + int res = -1; + FILE *fp; + char buf[ETHER_LINE_LEN]; + + fp = fopen(ETHER_FILE_NAME, "r"); + if (!fp) + return -1; + + while (fgets(buf, sizeof(buf), fp)) { + struct ether_addr tmp_addr; + const char *cp = __ether_line_w(buf, &tmp_addr); + if (!cp) + continue; + if (memcmp(addr, &tmp_addr, sizeof(tmp_addr))) + continue; + + strcpy(hostname, cp); + res = 0; + break; + } + + fclose(fp); + return res; +} + +int ether_hostton(const char *hostname, struct ether_addr *addr) +{ + int res = -1; + FILE *fp; + char buf[ETHER_LINE_LEN]; + + fp = fopen(ETHER_FILE_NAME, "r"); + if (!fp) + return -1; + + while (fgets(buf, sizeof(buf), fp)) { + const char *cp = __ether_line_w(buf, addr); + if (!cp) + continue; + if (strcasecmp(hostname, cp)) + continue; + + res = 0; + break; + } + + fclose(fp); + return res; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/formquery.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/formquery.c new file mode 100644 index 00000000..4bc0ebe3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/formquery.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_formquery +#include RESOLVER diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/gai_strerror.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/gai_strerror.c new file mode 100644 index 00000000..61688bad --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/gai_strerror.c @@ -0,0 +1,61 @@ +/* Copyright (C) 1997, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Philip Blundell , 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define __FORCE_GLIBC +#include +#include +#include + +#define N_(x) x +#define _(x) x +static const struct + { + int code; + const char *msg; + } +values[] = + { + { EAI_ADDRFAMILY, N_("Address family for hostname not supported") }, + { EAI_AGAIN, N_("Temporary failure in name resolution") }, + { EAI_BADFLAGS, N_("Bad value for ai_flags") }, + { EAI_FAIL, N_("Non-recoverable failure in name resolution") }, + { EAI_FAMILY, N_("ai_family not supported") }, + { EAI_MEMORY, N_("Memory allocation failure") }, + { EAI_NODATA, N_("No address associated with hostname") }, + { EAI_NONAME, N_("Name or service not known") }, + { EAI_SERVICE, N_("Servname not supported for ai_socktype") }, + { EAI_SOCKTYPE, N_("ai_socktype not supported") }, + { EAI_SYSTEM, N_("System error") }, + { EAI_INPROGRESS, N_("Processing request in progress") }, + { EAI_CANCELED, N_("Request canceled") }, + { EAI_NOTCANCELED, N_("Request not canceled") }, + { EAI_ALLDONE, N_("All requests done") }, + { EAI_INTR, N_("Interrupted by a signal") } + }; + +const char * +gai_strerror (int code) +{ + size_t i; + for (i = 0; i < sizeof (values) / sizeof (values[0]); ++i) + if (values[i].code == code) + return _(values[i].msg); + + return _("Unknown error"); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/get_hosts_byaddr_r.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/get_hosts_byaddr_r.c new file mode 100644 index 00000000..eeac8907 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/get_hosts_byaddr_r.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_get_hosts_byaddr_r +#include RESOLVER diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/get_hosts_byname_r.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/get_hosts_byname_r.c new file mode 100644 index 00000000..caad0bcc --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/get_hosts_byname_r.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_get_hosts_byname_r +#include RESOLVER diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/getaddrinfo.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/getaddrinfo.c new file mode 100644 index 00000000..cdfdb72c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/getaddrinfo.c @@ -0,0 +1,878 @@ +/* + * Copyright 1996 by Craig Metz + * Copyright (C) 2000-2006 Erik Andersen + * Portions from the GNU C library, + * Copyright (C) 2003, 2006 Free Software Foundation, Inc. + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* $USAGI: getaddrinfo.c,v 1.16 2001/10/04 09:52:03 sekiya Exp $ */ + +/* The Inner Net License, Version 2.00 + + The author(s) grant permission for redistribution and use in source and +binary forms, with or without modification, of the software and documentation +provided that the following conditions are met: + +0. If you receive a version of the software that is specifically labelled + as not being for redistribution (check the version message and/or README), + you are not permitted to redistribute that version of the software in any + way or form. +1. All terms of the all other applicable copyrights and licenses must be + followed. +2. Redistributions of source code must retain the authors' copyright + notice(s), this list of conditions, and the following disclaimer. +3. Redistributions in binary form must reproduce the authors' copyright + notice(s), this list of conditions, and the following disclaimer in the + documentation and/or other materials provided with the distribution. +4. All advertising materials mentioning features or use of this software + must display the following acknowledgement with the name(s) of the + authors as specified in the copyright notice(s) substituted where + indicated: + + This product includes software developed by , The Inner + Net, and other contributors. + +5. Neither the name(s) of the author(s) nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY ITS AUTHORS AND CONTRIBUTORS ``AS IS'' AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + If these license terms cause you a real problem, contact the author. */ + +#define __FORCE_GLIBC +#include +#include +#include +#include +#ifdef __UCLIBC_HAS_TLS__ +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define GAIH_OKIFUNSPEC 0x0100 +#define GAIH_EAI ~(GAIH_OKIFUNSPEC) + +#ifndef UNIX_PATH_MAX +#define UNIX_PATH_MAX 108 +#endif + +/* Useful for having small structure members/global variables */ +typedef int8_t socktype_t; +typedef int8_t family_t; +typedef int8_t protocol_t; +struct BUG_too_small { + char BUG_socktype_t_too_small[(0 + | SOCK_STREAM + | SOCK_DGRAM + | SOCK_RAW + ) <= 127 ? 1 : -1]; + char BUG_family_t_too_small[(0 + | AF_UNSPEC + | AF_INET + | AF_INET6 + ) <= 127 ? 1 : -1]; + char BUG_protocol_t_too_small[(0 + | IPPROTO_TCP + | IPPROTO_UDP + ) <= 127 ? 1 : -1]; +}; + +struct gaih_service { + const char *name; + int num; +}; + +struct gaih_servtuple { + struct gaih_servtuple *next; + int socktype; + int protocol; + int port; +}; + +struct gaih_addrtuple { + struct gaih_addrtuple *next; + int family; + char addr[16]; + uint32_t scopeid; +}; + +struct gaih_typeproto { + socktype_t socktype; + protocol_t protocol; + int8_t protoflag; + char name[4]; +}; +/* Values for `protoflag'. */ +#define GAI_PROTO_NOSERVICE 1 +#define GAI_PROTO_PROTOANY 2 + +static const struct gaih_typeproto gaih_inet_typeproto[] = { + { 0 , 0 , 0, "" }, + { SOCK_STREAM, IPPROTO_TCP, 0, "tcp" }, + { SOCK_DGRAM , IPPROTO_UDP, 0, "udp" }, + { SOCK_RAW , 0 , GAI_PROTO_PROTOANY|GAI_PROTO_NOSERVICE, "raw" }, + { 0 , 0 , 0, "" }, +}; + +struct gaih { + int family; + int (*gaih)(const char *name, const struct gaih_service *service, + const struct addrinfo *req, struct addrinfo **pai); +}; + +#define SEEN_IPV4 1 +#define SEEN_IPV6 2 + +static unsigned __check_pf(void) +{ + unsigned seen = 0; + +#if defined __UCLIBC_SUPPORT_AI_ADDRCONFIG__ + + struct ifaddrs *ifa; + struct ifaddrs *runp; + + /* Get the interface list via getifaddrs. */ + if (getifaddrs(&ifa) != 0) { + /* We cannot determine what interfaces are available. + * Be optimistic. */ +#if defined __UCLIBC_HAS_IPV4__ + seen |= SEEN_IPV4; +#endif +#if defined __UCLIBC_HAS_IPV6__ + seen |= SEEN_IPV6; +#endif + return seen; + } + + for (runp = ifa; runp != NULL; runp = runp->ifa_next) { + if (runp->ifa_addr == NULL) + continue; +#if defined __UCLIBC_HAS_IPV4__ + if (runp->ifa_addr->sa_family == PF_INET) + seen |= SEEN_IPV4; +#endif +#if defined __UCLIBC_HAS_IPV6__ + if (runp->ifa_addr->sa_family == PF_INET6) + seen |= SEEN_IPV6; +#endif + } + freeifaddrs(ifa); + +#else + + /* AI_ADDRCONFIG is disabled, assume both ipv4 and ipv6 available. */ +#if defined __UCLIBC_HAS_IPV4__ + seen |= SEEN_IPV4; +#endif +#if defined __UCLIBC_HAS_IPV6__ + seen |= SEEN_IPV6; +#endif + +#endif /* __UCLIBC_SUPPORT_AI_ADDRCONFIG__ */ + + return seen; +} + +static int addrconfig(sa_family_t af) +{ + int s; + int ret; + int saved_errno = errno; + unsigned seen; + + seen = __check_pf(); +#if defined __UCLIBC_HAS_IPV4__ + if (af == AF_INET) + ret = seen & SEEN_IPV4; + else +#endif +#if defined __UCLIBC_HAS_IPV6__ + if (af == AF_INET6) + ret = seen & SEEN_IPV6; + else +#endif + { + s = socket(af, SOCK_DGRAM, 0); + ret = 1; /* Assume PF_UNIX. */ + if (s < 0) { + if (errno != EMFILE) + ret = 0; + } else + close(s); + } + __set_errno(saved_errno); + return ret; +} + +#if 0 +/* Using Unix sockets this way is a security risk. */ +static int +gaih_local(const char *name, const struct gaih_service *service, + const struct addrinfo *req, struct addrinfo **pai) +{ + struct utsname utsname; + struct addrinfo *ai = *pai; + + if ((name != NULL) && (req->ai_flags & AI_NUMERICHOST)) + return (GAIH_OKIFUNSPEC | -EAI_NONAME); + + if ((name != NULL) || (req->ai_flags & AI_CANONNAME)) + if (uname(&utsname) < 0) + return -EAI_SYSTEM; + + if (name != NULL) { + if (strcmp(name, "localhost") && + strcmp(name, "local") && + strcmp(name, "unix") && + strcmp(name, utsname.nodename)) + return (GAIH_OKIFUNSPEC | -EAI_NONAME); + } + + if (req->ai_protocol || req->ai_socktype) { + const struct gaih_typeproto *tp = gaih_inet_typeproto + 1; + + while (tp->name[0] + && ((tp->protoflag & GAI_PROTO_NOSERVICE) != 0 + || (req->ai_socktype != 0 && req->ai_socktype != tp->socktype) + || (req->ai_protocol != 0 && !(tp->protoflag & GAI_PROTO_PROTOANY) && req->ai_protocol != tp->protocol)) + ) { + ++tp; + } + if (! tp->name[0]) { + if (req->ai_socktype) + return (GAIH_OKIFUNSPEC | -EAI_SOCKTYPE); + return (GAIH_OKIFUNSPEC | -EAI_SERVICE); + } + } + + *pai = ai = malloc(sizeof(struct addrinfo) + sizeof(struct sockaddr_un) + + ((req->ai_flags & AI_CANONNAME) + ? (strlen(utsname.nodename) + 1) : 0)); + if (ai == NULL) + return -EAI_MEMORY; + + ai->ai_next = NULL; + ai->ai_flags = req->ai_flags; + ai->ai_family = AF_LOCAL; + ai->ai_socktype = req->ai_socktype ? req->ai_socktype : SOCK_STREAM; + ai->ai_protocol = req->ai_protocol; + ai->ai_addrlen = sizeof(struct sockaddr_un); + ai->ai_addr = (void *)ai + sizeof(struct addrinfo); +#if SALEN + ((struct sockaddr_un *)ai->ai_addr)->sun_len = sizeof(struct sockaddr_un); +#endif /* SALEN */ + + ((struct sockaddr_un *)ai->ai_addr)->sun_family = AF_LOCAL; + memset(((struct sockaddr_un *)ai->ai_addr)->sun_path, 0, UNIX_PATH_MAX); + + if (service) { + struct sockaddr_un *sunp = (struct sockaddr_un *)ai->ai_addr; + + if (strchr(service->name, '/') != NULL) { + if (strlen(service->name) >= sizeof(sunp->sun_path)) + return GAIH_OKIFUNSPEC | -EAI_SERVICE; + strcpy(sunp->sun_path, service->name); + } else { + if (strlen(P_tmpdir "/") + 1 + strlen(service->name) >= sizeof(sunp->sun_path)) + return (GAIH_OKIFUNSPEC | -EAI_SERVICE); + stpcpy(stpcpy(sunp->sun_path, P_tmpdir "/"), service->name); + } + } else { + /* This is a dangerous use of the interface since there is a time + window between the test for the file and the actual creation + (done by the caller) in which a file with the same name could + be created. */ + char *buf = ((struct sockaddr_un *)ai->ai_addr)->sun_path; + + if (__path_search(buf, L_tmpnam, NULL, NULL, 0) != 0 + || __gen_tempname(buf, __GT_NOCREATE, 0) != 0 + ) { + return -EAI_SYSTEM; + } + } + + ai->ai_canonname = NULL; + if (req->ai_flags & AI_CANONNAME) + ai->ai_canonname = strcpy((char *)(ai + 1) + sizeof(struct sockaddr_un), + utsname.nodename); + return 0; +} +#endif /* 0 */ + +static int +gaih_inet_serv(const char *servicename, const struct gaih_typeproto *tp, + const struct addrinfo *req, struct gaih_servtuple *st) +{ + struct servent *s; + size_t tmpbuflen = 1024; + struct servent ts; + char *tmpbuf; + int r; + + while (1) { + tmpbuf = alloca(tmpbuflen); + r = getservbyname_r(servicename, tp->name, &ts, tmpbuf, tmpbuflen, &s); + if (r == 0 && s != NULL) + break; + if (r != ERANGE) + return (GAIH_OKIFUNSPEC | -EAI_SERVICE); + tmpbuflen *= 2; + } + st->next = NULL; + st->socktype = tp->socktype; + st->protocol = ((tp->protoflag & GAI_PROTO_PROTOANY) ? req->ai_protocol : tp->protocol); + st->port = s->s_port; + return 0; +} + +/* NB: also uses h,pat,rc,no_data variables */ +#define gethosts(_family, _type) \ +{ \ + int i, herrno; \ + size_t tmpbuflen; \ + struct hostent th; \ + char *tmpbuf; \ + \ + tmpbuflen = 512; \ + no_data = 0; \ + do { \ + tmpbuflen *= 2; \ + tmpbuf = alloca(tmpbuflen); \ + rc = gethostbyname2_r(name, _family, &th, tmpbuf, \ + tmpbuflen, &h, &herrno); \ + } while (rc == ERANGE && herrno == NETDB_INTERNAL); \ + if (rc != 0) { \ + if (herrno == NETDB_INTERNAL) { \ + __set_h_errno(herrno); \ + return -EAI_SYSTEM; \ + } \ + if (herrno == TRY_AGAIN) \ + no_data = EAI_AGAIN; \ + else \ + no_data = (herrno == NO_DATA); \ + } else if (h != NULL) { \ + for (i = 0; h->h_addr_list[i]; i++) { \ + if (*pat == NULL) { \ + *pat = alloca(sizeof(struct gaih_addrtuple)); \ + (*pat)->scopeid = 0; \ + } \ + (*pat)->next = NULL; \ + (*pat)->family = _family; \ + memcpy((*pat)->addr, h->h_addr_list[i], sizeof(_type)); \ + pat = &((*pat)->next); \ + } \ + } \ +} + +static int +gaih_inet(const char *name, const struct gaih_service *service, + const struct addrinfo *req, struct addrinfo **pai) +{ + struct gaih_servtuple nullserv; + + const struct gaih_typeproto *tp = gaih_inet_typeproto; + struct gaih_servtuple *st = &nullserv; + struct gaih_addrtuple *at = NULL; + int rc; + int v4mapped = (req->ai_family == PF_UNSPEC || req->ai_family == PF_INET6) + && (req->ai_flags & AI_V4MAPPED); + unsigned seen = __check_pf(); + + memset(&nullserv, 0, sizeof(nullserv)); + + if (req->ai_protocol || req->ai_socktype) { + ++tp; + while (tp->name[0] + && ((req->ai_socktype != 0 && req->ai_socktype != tp->socktype) + || (req->ai_protocol != 0 && !(tp->protoflag & GAI_PROTO_PROTOANY) && req->ai_protocol != tp->protocol) + ) + ) { + ++tp; + } + if (! tp->name[0]) { + if (req->ai_socktype) + return (GAIH_OKIFUNSPEC | -EAI_SOCKTYPE); + return (GAIH_OKIFUNSPEC | -EAI_SERVICE); + } + } + + if (service != NULL) { + if ((tp->protoflag & GAI_PROTO_NOSERVICE) != 0) + return (GAIH_OKIFUNSPEC | -EAI_SERVICE); + + if (service->num < 0) { + if (tp->name[0]) { + st = alloca(sizeof(struct gaih_servtuple)); + rc = gaih_inet_serv(service->name, tp, req, st); + if (rc) + return rc; + } else { + struct gaih_servtuple **pst = &st; + for (tp++; tp->name[0]; tp++) { + struct gaih_servtuple *newp; + + if ((tp->protoflag & GAI_PROTO_NOSERVICE) != 0) + continue; + + if (req->ai_socktype != 0 && req->ai_socktype != tp->socktype) + continue; + if (req->ai_protocol != 0 + && !(tp->protoflag & GAI_PROTO_PROTOANY) + && req->ai_protocol != tp->protocol) + continue; + + newp = alloca(sizeof(struct gaih_servtuple)); + rc = gaih_inet_serv(service->name, tp, req, newp); + if (rc) { + if (rc & GAIH_OKIFUNSPEC) + continue; + return rc; + } + + *pst = newp; + pst = &(newp->next); + } + if (st == &nullserv) + return (GAIH_OKIFUNSPEC | -EAI_SERVICE); + } + } else { + st = alloca(sizeof(struct gaih_servtuple)); + st->next = NULL; + st->socktype = tp->socktype; + st->protocol = ((tp->protoflag & GAI_PROTO_PROTOANY) + ? req->ai_protocol : tp->protocol); + st->port = htons(service->num); + } + } else if (req->ai_socktype || req->ai_protocol) { + st = alloca(sizeof(struct gaih_servtuple)); + st->next = NULL; + st->socktype = tp->socktype; + st->protocol = ((tp->protoflag & GAI_PROTO_PROTOANY) + ? req->ai_protocol : tp->protocol); + st->port = 0; + } else { + /* + * Neither socket type nor protocol is set. Return all socket types + * we know about. + */ + struct gaih_servtuple **lastp = &st; + for (++tp; tp->name[0]; ++tp) { + struct gaih_servtuple *newp; + + newp = alloca(sizeof(struct gaih_servtuple)); + newp->next = NULL; + newp->socktype = tp->socktype; + newp->protocol = tp->protocol; + newp->port = 0; + + *lastp = newp; + lastp = &newp->next; + } + } + + if (name != NULL) { + at = alloca(sizeof(struct gaih_addrtuple)); + at->family = AF_UNSPEC; + at->scopeid = 0; + at->next = NULL; + + if (inet_pton(AF_INET, name, at->addr) > 0) { + if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET || v4mapped) + at->family = AF_INET; + else + return -EAI_FAMILY; + } + +#if defined __UCLIBC_HAS_IPV6__ + if (at->family == AF_UNSPEC) { + char *namebuf = strdupa(name); + char *scope_delim; + + scope_delim = strchr(namebuf, SCOPE_DELIMITER); + if (scope_delim != NULL) + *scope_delim = '\0'; + + if (inet_pton(AF_INET6, namebuf, at->addr) > 0) { + if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET6) + at->family = AF_INET6; + else + return -EAI_FAMILY; + + if (scope_delim != NULL) { + int try_numericscope = 0; + uint32_t *a32 = (uint32_t*)at->addr; + if (IN6_IS_ADDR_LINKLOCAL(a32) || IN6_IS_ADDR_MC_LINKLOCAL(at->addr)) { + at->scopeid = if_nametoindex(scope_delim + 1); + if (at->scopeid == 0) + try_numericscope = 1; + } else + try_numericscope = 1; + + if (try_numericscope != 0) { + char *end; + assert(sizeof(uint32_t) <= sizeof(unsigned long)); + at->scopeid = (uint32_t)strtoul(scope_delim + 1, &end, 10); + if (*end != '\0') + return (GAIH_OKIFUNSPEC | -EAI_NONAME); + } + } + } + } +#endif + + if (at->family == AF_UNSPEC && (req->ai_flags & AI_NUMERICHOST) == 0) { + struct hostent *h; + struct gaih_addrtuple **pat = &at; + int no_data = 0; + int no_inet6_data; + + /* + * If we are looking for both IPv4 and IPv6 address we don't want + * the lookup functions to automatically promote IPv4 addresses to + * IPv6 addresses. + */ +#if defined __UCLIBC_HAS_IPV6__ + if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET6) + if (!(req->ai_flags & AI_ADDRCONFIG) || (seen & SEEN_IPV6)) + gethosts(AF_INET6, struct in6_addr); +#endif + no_inet6_data = no_data; + + if (req->ai_family == AF_INET + || (!v4mapped && req->ai_family == AF_UNSPEC) + || (v4mapped && (no_inet6_data != 0 || (req->ai_flags & AI_ALL))) + ) { + if (!(req->ai_flags & AI_ADDRCONFIG) || (seen & SEEN_IPV4)) + gethosts(AF_INET, struct in_addr); + } + + if (no_data != 0 && no_inet6_data != 0) { + /* If both requests timed out report this. */ + if (no_data == EAI_AGAIN && no_inet6_data == EAI_AGAIN) + return -EAI_AGAIN; + /* + * We made requests but they turned out no data. + * The name is known, though. + */ + return (GAIH_OKIFUNSPEC | -EAI_AGAIN); + } + } + + if (at->family == AF_UNSPEC) + return (GAIH_OKIFUNSPEC | -EAI_NONAME); + } else { + struct gaih_addrtuple *atr; + + atr = at = alloca(sizeof(struct gaih_addrtuple)); + memset(at, '\0', sizeof(struct gaih_addrtuple)); + if (req->ai_family == 0) { + at->next = alloca(sizeof(struct gaih_addrtuple)); + memset(at->next, '\0', sizeof(struct gaih_addrtuple)); + } +#if defined __UCLIBC_HAS_IPV6__ + if (req->ai_family == 0 || req->ai_family == AF_INET6) { + at->family = AF_INET6; + if ((req->ai_flags & AI_PASSIVE) == 0) + memcpy(at->addr, &in6addr_loopback, sizeof(struct in6_addr)); + atr = at->next; + } +#endif + if (req->ai_family == 0 || req->ai_family == AF_INET) { + atr->family = AF_INET; + if ((req->ai_flags & AI_PASSIVE) == 0) { + uint32_t *a = (uint32_t*)atr->addr; + *a = htonl(INADDR_LOOPBACK); + } + } + } + + if (pai == NULL) + return 0; + + { + const char *c = NULL; + struct gaih_servtuple *st2; + struct gaih_addrtuple *at2 = at; + size_t socklen, namelen; + sa_family_t family; + + /* + * buffer is the size of an unformatted IPv6 address in + * printable format. + */ + char buffer[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")]; + + while (at2 != NULL) { + if (req->ai_flags & AI_CANONNAME) { + struct hostent *h = NULL; + int herrno; + struct hostent th; + size_t tmpbuflen = 512; + char *tmpbuf; + + do { + tmpbuflen *= 2; + tmpbuf = alloca(tmpbuflen); + rc = gethostbyaddr_r(at2->addr, + ((at2->family == AF_INET6) + ? sizeof(struct in6_addr) + : sizeof(struct in_addr)), + at2->family, + &th, tmpbuf, tmpbuflen, + &h, &herrno); + } while (rc == errno && herrno == NETDB_INTERNAL); + + if (rc != 0 && herrno == NETDB_INTERNAL) { + __set_h_errno(herrno); + return -EAI_SYSTEM; + } + + if (h == NULL) + c = inet_ntop(at2->family, at2->addr, buffer, sizeof(buffer)); + else + c = h->h_name; + + if (c == NULL) + return (GAIH_OKIFUNSPEC | -EAI_NONAME); + + namelen = strlen(c) + 1; + } else + namelen = 0; + +#if defined __UCLIBC_HAS_IPV6__ + if (at2->family == AF_INET6 || v4mapped) { + family = AF_INET6; + socklen = sizeof(struct sockaddr_in6); + } +#endif +#if defined __UCLIBC_HAS_IPV4__ && defined __UCLIBC_HAS_IPV6__ + else +#endif +#if defined __UCLIBC_HAS_IPV4__ + { + family = AF_INET; + socklen = sizeof(struct sockaddr_in); + } +#endif + for (st2 = st; st2 != NULL; st2 = st2->next) { + if (req->ai_flags & AI_ADDRCONFIG) { + if (family == AF_INET && !(seen & SEEN_IPV4)) + break; +#if defined __UCLIBC_HAS_IPV6__ + else if (family == AF_INET6 && !(seen & SEEN_IPV6)) + break; +#endif + } + *pai = malloc(sizeof(struct addrinfo) + socklen + namelen); + if (*pai == NULL) + return -EAI_MEMORY; + + (*pai)->ai_flags = req->ai_flags; + (*pai)->ai_family = family; + (*pai)->ai_socktype = st2->socktype; + (*pai)->ai_protocol = st2->protocol; + (*pai)->ai_addrlen = socklen; + (*pai)->ai_addr = (void *) (*pai) + sizeof(struct addrinfo); +#if defined SALEN + (*pai)->ai_addr->sa_len = socklen; +#endif + (*pai)->ai_addr->sa_family = family; + +#if defined __UCLIBC_HAS_IPV6__ + if (family == AF_INET6) { + struct sockaddr_in6 *sin6p = (struct sockaddr_in6 *) (*pai)->ai_addr; + + sin6p->sin6_flowinfo = 0; + if (at2->family == AF_INET6) { + memcpy(&sin6p->sin6_addr, + at2->addr, sizeof(struct in6_addr)); + } else { + sin6p->sin6_addr.s6_addr32[0] = 0; + sin6p->sin6_addr.s6_addr32[1] = 0; + sin6p->sin6_addr.s6_addr32[2] = htonl(0x0000ffff); + memcpy(&sin6p->sin6_addr.s6_addr32[3], + at2->addr, sizeof(sin6p->sin6_addr.s6_addr32[3])); + } + sin6p->sin6_port = st2->port; + sin6p->sin6_scope_id = at2->scopeid; + } +#endif +#if defined __UCLIBC_HAS_IPV4__ && defined __UCLIBC_HAS_IPV6__ + else +#endif +#if defined __UCLIBC_HAS_IPV4__ + { + struct sockaddr_in *sinp = (struct sockaddr_in *) (*pai)->ai_addr; + + memcpy(&sinp->sin_addr, at2->addr, sizeof(struct in_addr)); + sinp->sin_port = st2->port; + memset(sinp->sin_zero, '\0', sizeof(sinp->sin_zero)); + } +#endif + if (c) { + (*pai)->ai_canonname = ((void *) (*pai) + + sizeof(struct addrinfo) + socklen); + strcpy((*pai)->ai_canonname, c); + } else { + (*pai)->ai_canonname = NULL; + } + (*pai)->ai_next = NULL; + pai = &((*pai)->ai_next); + } + + at2 = at2->next; + } + } + return 0; +} + +static const struct gaih gaih[] = { +#if defined __UCLIBC_HAS_IPV6__ + { PF_INET6, gaih_inet }, +#endif + { PF_INET, gaih_inet }, +#if 0 + { PF_LOCAL, gaih_local }, +#endif + { PF_UNSPEC, NULL } +}; + +void +freeaddrinfo(struct addrinfo *ai) +{ + struct addrinfo *p; + + while (ai != NULL) { + p = ai; + ai = ai->ai_next; + free(p); + } +} +libc_hidden_def(freeaddrinfo) + +int +getaddrinfo(const char *name, const char *service, + const struct addrinfo *hints, struct addrinfo **pai) +{ + int i = 0, j, last_i = 0; + struct addrinfo *p = NULL, **end; + const struct gaih *g = gaih, *pg = NULL; + struct gaih_service gaih_service, *pservice; + struct addrinfo default_hints; + + if (name != NULL && name[0] == '*' && name[1] == 0) + name = NULL; + + if (service != NULL && service[0] == '*' && service[1] == 0) + service = NULL; + + if (name == NULL && service == NULL) + return EAI_NONAME; + + if (hints == NULL) { + memset(&default_hints, 0, sizeof(default_hints)); + if (AF_UNSPEC) + default_hints.ai_family = AF_UNSPEC; + hints = &default_hints; + } + + if (hints->ai_flags & ~(AI_PASSIVE|AI_CANONNAME|AI_NUMERICHOST| + AI_ADDRCONFIG|AI_V4MAPPED|AI_NUMERICSERV|AI_ALL)) + return EAI_BADFLAGS; + + if ((hints->ai_flags & AI_CANONNAME) && name == NULL) + return EAI_BADFLAGS; + + if (service && service[0]) { + char *c; + gaih_service.name = service; + gaih_service.num = strtoul(gaih_service.name, &c, 10); + if (*c != '\0') { + if (hints->ai_flags & AI_NUMERICSERV) + return EAI_NONAME; + gaih_service.num = -1; + } else { + /* + * Can't specify a numerical socket unless a protocol + * family was given. + */ + if (hints->ai_socktype == 0 && hints->ai_protocol == 0) + return EAI_SERVICE; + } + pservice = &gaih_service; + } else + pservice = NULL; + + end = NULL; + if (pai) + end = &p; + + j = 0; + while (g->gaih) { + if (hints->ai_family == g->family || hints->ai_family == AF_UNSPEC) { + if ((hints->ai_flags & AI_ADDRCONFIG) && !addrconfig(g->family)) { + ++g; + continue; + } + j++; + if (pg == NULL || pg->gaih != g->gaih) { + pg = g; + i = g->gaih(name, pservice, hints, end); + if (i != 0) { + last_i = i; + if (hints->ai_family == AF_UNSPEC && (i & GAIH_OKIFUNSPEC)) + continue; + if (p) + freeaddrinfo(p); + return -(i & GAIH_EAI); + } + if (end) + while (*end) + end = &((*end)->ai_next); + } + } + ++g; + } + + if (j == 0) + return EAI_FAMILY; + + if (p) { + *pai = p; + return 0; + } + + if (pai == NULL && last_i == 0) + return 0; + + /* if (p) - never happens, see above */ + /* freeaddrinfo(p); */ + + return last_i ? -(last_i & GAIH_EAI) : EAI_NONAME; +} +libc_hidden_def(getaddrinfo) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/gethostbyaddr.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/gethostbyaddr.c new file mode 100644 index 00000000..dc16dd9e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/gethostbyaddr.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_gethostbyaddr +#include RESOLVER diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/gethostbyaddr_r.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/gethostbyaddr_r.c new file mode 100644 index 00000000..6e27e620 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/gethostbyaddr_r.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_gethostbyaddr_r +#include RESOLVER diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/gethostbyname.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/gethostbyname.c new file mode 100644 index 00000000..9c9e9ca0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/gethostbyname.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_gethostbyname +#include RESOLVER diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/gethostbyname2.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/gethostbyname2.c new file mode 100644 index 00000000..5b9e74ba --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/gethostbyname2.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_gethostbyname2 +#include RESOLVER diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/gethostbyname2_r.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/gethostbyname2_r.c new file mode 100644 index 00000000..0de0dd5e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/gethostbyname2_r.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_gethostbyname2_r +#include RESOLVER diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/gethostbyname_r.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/gethostbyname_r.c new file mode 100644 index 00000000..4b34f8d1 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/gethostbyname_r.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_gethostbyname_r +#include RESOLVER diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/gethostent.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/gethostent.c new file mode 100644 index 00000000..64c18317 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/gethostent.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_gethostent +#include RESOLVER diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/gethostent_r.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/gethostent_r.c new file mode 100644 index 00000000..48225d7f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/gethostent_r.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_gethostent_r +#include RESOLVER diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/getnameinfo.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/getnameinfo.c new file mode 100644 index 00000000..86edc51f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/getnameinfo.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_getnameinfo +#include RESOLVER diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/getnet.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/getnet.c new file mode 100644 index 00000000..9049f97a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/getnet.c @@ -0,0 +1,208 @@ +/* vi: set sw=4 ts=4: */ +/* + * Copyright (C) 2010 Bernhard Reutner-Fischer + * + * Licensed under LGPL v2.1 or later, see the file COPYING.LIB in this tarball. + */ + +/* /etc/networks +# network-name number [aliases ...] +loopback 127.0.0.0 # optional aliases + +network-name: symbolic name of the netwkork +number: official number of the network in dotted quad +aliases: case sensitive optional space or tab separated list of other names +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "internal/parse_config.h" + +#include +__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP); + +#define MINTOKENS 2 +#define MAXALIASES 8 +#define MAXTOKENS (MINTOKENS + MAXALIASES + 1) +#define BUFSZ (255) /* one line */ +#define SBUFSIZE (BUFSZ + 1 + (sizeof(char *) * MAXTOKENS)) + +static parser_t *netp = NULL; +static struct netent nete; +static char *netbuf = NULL; +static smallint net_stayopen; + +void setnetent(int stayopen) +{ + __UCLIBC_MUTEX_LOCK(mylock); + if (netp) + config_close(netp); + netp = config_open(_PATH_NETWORKS); + if (stayopen) + net_stayopen = 1; + __UCLIBC_MUTEX_UNLOCK(mylock); +} +libc_hidden_def(setnetent) + +void endnetent(void) +{ + __UCLIBC_MUTEX_LOCK(mylock); + if (netp) { + config_close(netp); + netp = NULL; + } + net_stayopen = 0; + __UCLIBC_MUTEX_UNLOCK(mylock); +} +libc_hidden_def(endnetent) + +int getnetent_r(struct netent *result_buf, + char *buf, size_t buflen, struct netent **result, + int *h_errnop + ) +{ + char **tok = NULL; + const size_t aliaslen = sizeof(char *) * MAXTOKENS; + int ret = ERANGE; + + *result = NULL; + if (buflen < aliaslen + || (buflen - aliaslen) < BUFSZ + 1) + goto DONE_NOUNLOCK; + + __UCLIBC_MUTEX_LOCK(mylock); + ret = ENOENT; + if (netp == NULL) + setnetent(net_stayopen); + if (netp == NULL) + goto DONE; + netp->data = buf; + netp->data_len = aliaslen; + netp->line_len = buflen - aliaslen; + /* [[:space:]][[:space:]][] */ + if (!config_read(netp, &tok, MAXTOKENS-1, MINTOKENS, "# \t/", PARSE_NORMAL)) { + goto DONE; + } + result_buf->n_name = *(tok++); + { + struct addrinfo hints, *addri; +# define sa4_to_uint32(sa) \ + (ntohl(((struct sockaddr_in*)sa)->sin_addr.s_addr)) +#ifdef __UCLIBC_HAS_IPV6__ +# define sa6_to_uint8(sa) \ + (ntohl(((struct sockaddr_in6*)sa)->sin6_addr.s6_addr)) +#endif + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_family = AF_UNSPEC; + hints.ai_flags = AI_NUMERICHOST; + getaddrinfo(*(tok++), NULL, &hints, &addri); + result_buf->n_addrtype = addri->ai_family; + result_buf->n_net = +#if 0 /*FIXME: implement me! def __UCLIBC_HAS_IPV6__ */ + addri->ai_family == AF_INET6 ? sa6_to_uint8(addri->ai_addr) : +#endif + sa4_to_uint32(addri->ai_addr); + freeaddrinfo(addri); + } + result_buf->n_aliases = tok; + *result = result_buf; + ret = 0; + DONE: + __UCLIBC_MUTEX_UNLOCK(mylock); + DONE_NOUNLOCK: + errno = ret; + return errno; +} +libc_hidden_def(getnetent_r) + +static void __initbuf(void) +{ + if (!netbuf) { + netbuf = malloc(SBUFSIZE); + if (!netbuf) + abort(); + } +} + +struct netent *getnetent(void) +{ + struct netent *result; + int herrnop; + + __initbuf(); + getnetent_r(&nete, netbuf, SBUFSIZE, &result, &herrnop); + return result; +} + +int getnetbyname_r(const char *name, + struct netent *result_buf, char *buf, size_t buflen, + struct netent **result, + int *h_errnop + ) +{ + register char **cp; + int ret, herrnop; + + __UCLIBC_MUTEX_LOCK(mylock); + setnetent(net_stayopen); + while (!(ret = getnetent_r(result_buf, buf, buflen, result, &herrnop))) { + if (strcmp(name, result_buf->n_name) == 0) + break; + for (cp = result_buf->n_aliases; *cp; cp++) + if (strcmp(name, *cp) == 0) + goto gotname; + } + gotname: + if (!net_stayopen) + endnetent(); + __UCLIBC_MUTEX_UNLOCK(mylock); + return *result ? 0 : ret; +} +libc_hidden_def(getnetbyname_r) + +struct netent *getnetbyname(const char *name) +{ + struct netent *result; + int herrnop; + + __initbuf(); + getnetbyname_r(name, &nete, netbuf, SBUFSIZE, &result, &herrnop); + return result; +} + +int getnetbyaddr_r(uint32_t net, int type, + struct netent *result_buf, char *buf, + size_t buflen, struct netent **result, + int *h_errnop) +{ + int ret, herrnop; + + __UCLIBC_MUTEX_LOCK(mylock); + setnetent(net_stayopen); + while (!(ret = getnetent_r(result_buf, buf, buflen, result, &herrnop))) { + if (net == result_buf->n_net && type == result_buf->n_addrtype) + break; + } + if (!net_stayopen) + endnetent(); + __UCLIBC_MUTEX_UNLOCK(mylock); + return *result ? 0 : ret; +} +libc_hidden_def(getnetbyaddr_r) + +struct netent *getnetbyaddr(uint32_t net, int type) +{ + struct netent *result; + int herrnop; + + __initbuf(); + getnetbyaddr_r(net, type, &nete, netbuf, SBUFSIZE, &result, &herrnop); + return result; +} + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/getpeername.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/getpeername.c new file mode 100644 index 00000000..74825a7b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/getpeername.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_getpeername +#include "socketcalls.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/getproto.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/getproto.c new file mode 100644 index 00000000..c59da7e6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/getproto.c @@ -0,0 +1,182 @@ +/* vi: set sw=4 ts=4: */ +/* + * Copyright (C) 2010 Bernhard Reutner-Fischer + * + * Licensed under LGPL v2.1 or later, see the file COPYING.LIB in this tarball. + */ + +/* /etc/protocols +# protocol-name number [aliases ...] +ip 0 IP # internet protocol, pseudo protocol number + +protocol-name: case sensitive friendly name of the IP protocol +number: decimal protocol number +aliases: case sensitive optional space or tab separated list of other names +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "internal/parse_config.h" + +#include +__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP); + +#define MINTOKENS 2 +#define MAXALIASES 8 /* will probably never be more than one */ +#define MAXTOKENS (MINTOKENS + MAXALIASES + 1) +#define BUFSZ (255) /* one line */ +#define SBUFSIZE (BUFSZ + 1 + (sizeof(char *) * MAXTOKENS)) + +static parser_t *protop = NULL; +static struct protoent protoe; +static char *protobuf = NULL; +static smallint proto_stayopen; + +void setprotoent(int stayopen) +{ + __UCLIBC_MUTEX_LOCK(mylock); + if (protop) + config_close(protop); + protop = config_open(_PATH_PROTOCOLS); + if (stayopen) + proto_stayopen = 1; + __UCLIBC_MUTEX_UNLOCK(mylock); +} +libc_hidden_def(setprotoent) + +void endprotoent(void) +{ + __UCLIBC_MUTEX_LOCK(mylock); + if (protop) { + config_close(protop); + protop = NULL; + } + proto_stayopen = 0; + __UCLIBC_MUTEX_UNLOCK(mylock); +} +libc_hidden_def(endprotoent) + +int getprotoent_r(struct protoent *result_buf, + char *buf, size_t buflen, struct protoent **result) +{ + char **tok = NULL; + const size_t aliaslen = sizeof(char *) * MAXTOKENS; + int ret = ERANGE; + + *result = NULL; + if (buflen < aliaslen + || (buflen - aliaslen) < BUFSZ + 1) + goto DONE_NOUNLOCK; + + __UCLIBC_MUTEX_LOCK(mylock); + //tok = (char **) buf; + ret = ENOENT; + if (protop == NULL) + setprotoent(proto_stayopen); + if (protop == NULL) + goto DONE; + protop->data = buf; + protop->data_len = aliaslen; + protop->line_len = buflen - aliaslen; + /* [[:space:]][[:space:]][] */ + if (!config_read(protop, &tok, MAXTOKENS - 1, MINTOKENS, "# \t/", PARSE_NORMAL)) { + goto DONE; + } + result_buf->p_name = *(tok++); + result_buf->p_proto = atoi(*(tok++)); + result_buf->p_aliases = tok; + *result = result_buf; + ret = 0; + DONE: + __UCLIBC_MUTEX_UNLOCK(mylock); + DONE_NOUNLOCK: + errno = ret; + return errno; +} +libc_hidden_def(getprotoent_r) + +static void __initbuf(void) +{ + if (!protobuf) { + protobuf = malloc(SBUFSIZE); + if (!protobuf) + abort(); + } +} + +struct protoent *getprotoent(void) +{ + struct protoent *result; + + __initbuf(); + getprotoent_r(&protoe, protobuf, SBUFSIZE, &result); + return result; +} + +int getprotobyname_r(const char *name, + struct protoent *result_buf, char *buf, size_t buflen, + struct protoent **result) +{ + register char **cp; + int ret; + + __UCLIBC_MUTEX_LOCK(mylock); + setprotoent(proto_stayopen); + while (!(ret = getprotoent_r(result_buf, buf, buflen, result))) { + if (strcmp(name, result_buf->p_name) == 0) + break; + for (cp = result_buf->p_aliases; *cp; cp++) + if (strcmp(name, *cp) == 0) + goto gotname; + } + gotname: + if (!proto_stayopen) + endprotoent(); + __UCLIBC_MUTEX_UNLOCK(mylock); + return *result ? 0 : ret; +} +libc_hidden_def(getprotobyname_r) + +struct protoent *getprotobyname(const char *name) +{ + struct protoent *result; + + __initbuf(); + getprotobyname_r(name, &protoe, protobuf, SBUFSIZE, &result); + return result; +} + +int getprotobynumber_r(int proto, + struct protoent *result_buf, char *buf, + size_t buflen, struct protoent **result) +{ + int ret; + + __UCLIBC_MUTEX_LOCK(mylock); + setprotoent(proto_stayopen); + while (!(ret = getprotoent_r(result_buf, buf, buflen, result))) { + if (proto == result_buf->p_proto) + break; + } + if (!proto_stayopen) + endprotoent(); + __UCLIBC_MUTEX_UNLOCK(mylock); + return *result ? 0 : ret; +} +libc_hidden_def(getprotobynumber_r) + +struct protoent *getprotobynumber(int proto) +{ + struct protoent *result; + + __initbuf(); + getprotobynumber_r(proto, &protoe, protobuf, SBUFSIZE, &result); + return result; +} + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/getservice.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/getservice.c new file mode 100644 index 00000000..183099f5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/getservice.c @@ -0,0 +1,190 @@ +/* vi: set sw=4 ts=4: */ +/* + * Copyright (C) 2010 Bernhard Reutner-Fischer + * + * Licensed under LGPL v2.1 or later, see the file COPYING.LIB in this tarball. + */ + +/* /etc/services +# service-name port/protocol [aliases ...] +discard 9/udp sink null + +service-name: case sensitive friendly name of the service +port: decimal port number +protocol: protocols(5) compatible entry +aliases: case sensitive optional space or tab separated list of other names +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "internal/parse_config.h" + +#include +__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP); + +#define MINTOKENS 3 +#define MAXALIASES 8 /* we seldomly need more than 1 alias */ +#define MAXTOKENS (MINTOKENS + MAXALIASES + 1) +#define BUFSZ (255) /* one line */ +#define SBUFSIZE (BUFSZ + 1 + (sizeof(char *) * MAXTOKENS)) + +static parser_t *servp = NULL; +static struct servent serve; +static char *servbuf = NULL; +static size_t servbuf_sz = SBUFSIZE; +static smallint serv_stayopen; + +void setservent(int stayopen) +{ + __UCLIBC_MUTEX_LOCK(mylock); + if (servp) + config_close(servp); + servp = config_open(_PATH_SERVICES); + if (stayopen) + serv_stayopen = 1; + __UCLIBC_MUTEX_UNLOCK(mylock); +} +libc_hidden_def(setservent) + +void endservent(void) +{ + __UCLIBC_MUTEX_LOCK(mylock); + if (servp) { + config_close(servp); + servp = NULL; + } + serv_stayopen = 0; + __UCLIBC_MUTEX_UNLOCK(mylock); +} +libc_hidden_def(endservent) + +int getservent_r(struct servent *result_buf, + char *buf, size_t buflen, struct servent **result) +{ + char **tok = NULL; + const size_t aliaslen = sizeof(char *) * MAXTOKENS; + int ret = ERANGE; + + *result = NULL; + if (buflen < aliaslen + || (buflen - aliaslen) < BUFSZ + 1) + goto DONE_NOUNLOCK; + + __UCLIBC_MUTEX_LOCK(mylock); + ret = ENOENT; + if (servp == NULL) + setservent(serv_stayopen); + if (servp == NULL) + goto DONE; + + servp->data = buf; + servp->data_len = aliaslen; + servp->line_len = buflen - aliaslen; + /* [[:space:]]/[[:space:]][] */ + if (!config_read(servp, &tok, MAXTOKENS - 1, MINTOKENS, "# \t/", PARSE_NORMAL)) { + goto DONE; + } + result_buf->s_name = *(tok++); + result_buf->s_port = htons((u_short) atoi(*(tok++))); + result_buf->s_proto = *(tok++); + result_buf->s_aliases = tok; + *result = result_buf; + ret = 0; + DONE: + __UCLIBC_MUTEX_UNLOCK(mylock); + DONE_NOUNLOCK: + errno = ret; + return errno; +} +libc_hidden_def(getservent_r) + +static void __initbuf(void) +{ + if (!servbuf) + servbuf = malloc(SBUFSIZE); + if (!servbuf) + abort(); +} + +struct servent *getservent(void) +{ + struct servent *result; + + __initbuf(); + getservent_r(&serve, servbuf, servbuf_sz, &result); + return result; +} + +int getservbyname_r(const char *name, const char *proto, + struct servent *result_buf, char *buf, size_t buflen, + struct servent **result) +{ + register char **cp; + int ret; + + __UCLIBC_MUTEX_LOCK(mylock); + setservent(serv_stayopen); + while (!(ret = getservent_r(result_buf, buf, buflen, result))) { + if (strcmp(name, result_buf->s_name) == 0) + goto gotname; + for (cp = result_buf->s_aliases; *cp; cp++) + if (strcmp(name, *cp) == 0) + goto gotname; + continue; + gotname: + if (proto == 0 || strcmp(result_buf->s_proto, proto) == 0) + break; + } + if (!serv_stayopen) + endservent(); + __UCLIBC_MUTEX_UNLOCK(mylock); + return *result ? 0 : ret; +} +libc_hidden_def(getservbyname_r) + +struct servent *getservbyname(const char *name, const char *proto) +{ + struct servent *result; + + __initbuf(); + getservbyname_r(name, proto, &serve, servbuf, servbuf_sz, &result); + return result; +} + + +int getservbyport_r(int port, const char *proto, + struct servent *result_buf, char *buf, + size_t buflen, struct servent **result) +{ + int ret; + + __UCLIBC_MUTEX_LOCK(mylock); + setservent(serv_stayopen); + while (!(ret = getservent_r(result_buf, buf, buflen, result))) { + if (result_buf->s_port != port) + continue; + if (proto == 0 || strcmp(result_buf->s_proto, proto) == 0) + break; + } + if (!serv_stayopen) + endservent(); + __UCLIBC_MUTEX_UNLOCK(mylock); + return *result ? 0 : ret; +} +libc_hidden_def(getservbyport_r) + +struct servent *getservbyport(int port, const char *proto) +{ + struct servent *result; + + __initbuf(); + getservbyport_r(port, proto, &serve, servbuf, servbuf_sz, &result); + return result; +} +libc_hidden_def(getservbyport) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/getsockname.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/getsockname.c new file mode 100644 index 00000000..4a4d6a13 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/getsockname.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_getsockname +#include "socketcalls.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/getsockopt.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/getsockopt.c new file mode 100644 index 00000000..48f72e99 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/getsockopt.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_getsockopt +#include "socketcalls.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/herror.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/herror.c new file mode 100644 index 00000000..a1f94ad6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/herror.c @@ -0,0 +1,65 @@ +/* + * Copyright (c) 1987 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that: (1) source distributions retain this entire copyright + * notice and comment, and (2) distributions including binaries display + * the following acknowledgement: ``This product includes software + * developed by the University of California, Berkeley and its contributors'' + * in the documentation or other materials provided with the distribution + * and in all advertising materials mentioning features or use of this + * software. Neither the name of the University nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#define __FORCE_GLIBC +#include +#include +#include +#include + + +static const char error_msg[] = "Resolver error"; +static const char *const h_errlist[] = { + "Error 0", + "Unknown host", /* 1 HOST_NOT_FOUND */ + "Host name lookup failure", /* 2 TRY_AGAIN */ + "Unknown server error", /* 3 NO_RECOVERY */ + "No address associated with name", /* 4 NO_ADDRESS */ +}; +static const int h_nerr = { sizeof(h_errlist)/sizeof(h_errlist[0]) }; + +/* + * herror -- print the error indicated by the h_errno value. + */ +void herror(const char *s) +{ + static const char colon_space[] = ": "; + const char *p; + const char *c; + + c = colon_space; + if (!s || !*s) { + c += 2; + } + p = error_msg; + if ((h_errno >= 0) && (h_errno < h_nerr)) { + p = h_errlist[h_errno]; + } + fprintf(stderr, "%s%s%s\n", s, c, p); +} +libc_hidden_def(herror) + + +const char *hstrerror(int err) +{ + if ((unsigned)err < h_nerr) + return(h_errlist[err]); + + return error_msg; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/hostid.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/hostid.c new file mode 100644 index 00000000..90b22ae7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/hostid.c @@ -0,0 +1,80 @@ +/* vi: set sw=4 ts=4: */ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define __FORCE_GLIBC +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define HOSTID "/etc/hostid" + +#ifdef __USE_BSD +int sethostid(long int new_id) +{ + int fd; + int ret; + + if (geteuid() || getuid()) + return __set_errno(EPERM); + fd = open_not_cancel(HOSTID, O_CREAT|O_WRONLY, 0644); + if (fd < 0) + return fd; + ret = write_not_cancel(fd, &new_id, sizeof(new_id)) == sizeof(new_id) ? 0 : -1; + close_not_cancel_no_status (fd); + return ret; +} +#endif + +#define _addr(a) (((struct sockaddr_in*)a->ai_addr)->sin_addr.s_addr) +long int gethostid(void) +{ + char host[HOST_NAME_MAX + 1]; + int fd, id = 0; + + /* If hostid was already set then we can return that value. + * It is not an error if we cannot read this file. It is not even an + * error if we cannot read all the bytes, we just carry on trying... + */ + fd = open_not_cancel_2(HOSTID, O_RDONLY); + if (fd >= 0) { + int i = read_not_cancel(fd, &id, sizeof(id)); + close_not_cancel_no_status(fd); + if (i > 0) + return id; + } + /* Try some methods of returning a unique 32 bit id. Clearly IP + * numbers, if on the internet, will have a unique address. If they + * are not on the internet then we can return 0 which means they should + * really set this number via a sethostid() call. If their hostname + * returns the loopback number (i.e. if they have put their hostname + * in the /etc/hosts file with 127.0.0.1) then all such hosts will + * have a non-unique hostid, but it doesn't matter anyway and + * gethostid() will return a non zero number without the need for + * setting one anyway. + * Mitch + */ + if (gethostname(host, HOST_NAME_MAX) >= 0 && *host) { + struct addrinfo hints, *results, *addr; + memset(&hints, 0, sizeof(struct addrinfo)); + if (!getaddrinfo(host, NULL, &hints, &results)) { + for (addr = results; addr; addr = results->ai_next) { + /* Just so it doesn't look exactly like the + IP addr */ + id = _addr(addr) << 16 | _addr(addr) >> 16; + break; + } + freeaddrinfo(results); + } + } + return id; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/if_index.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/if_index.c new file mode 100644 index 00000000..8efcd2a7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/if_index.c @@ -0,0 +1,337 @@ +/* Copyright (C) 1997, 1998, 1999, 2000, 2002, 2003, 2004, 2005 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. + + Reworked Dec 2002 by Erik Andersen + */ + +#define __FORCE_GLIBC +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "netlinkaccess.h" + +extern int __opensock(void) attribute_hidden; + +unsigned int +if_nametoindex(const char* ifname) +{ +#ifndef SIOCGIFINDEX + __set_errno (ENOSYS); + return 0; +#else + struct ifreq ifr; + int fd = __opensock(); + + if (fd < 0) + return 0; + + strncpy (ifr.ifr_name, ifname, sizeof (ifr.ifr_name)); + if (ioctl (fd, SIOCGIFINDEX, &ifr) < 0) + { + /* close never fails here, fd is just a unconnected socket. + *int saved_errno = errno; */ + close_not_cancel_no_status(fd); + /*if (saved_errno == EINVAL) + * __set_errno(ENOSYS); */ + return 0; + } + + close_not_cancel_no_status(fd); + return ifr.ifr_ifindex; +#endif +} +libc_hidden_def(if_nametoindex) + +void +if_freenameindex (struct if_nameindex *ifn) +{ + struct if_nameindex *ptr = ifn; + while (ptr->if_name || ptr->if_index) + { + free (ptr->if_name); + ++ptr; + } + free (ifn); +} +libc_hidden_def(if_freenameindex) + +#if !__ASSUME_NETLINK_SUPPORT +struct if_nameindex * +if_nameindex (void) +{ +#ifndef SIOCGIFINDEX + __set_errno (ENOSYS); + return NULL; +#else + int fd = __opensock (); + struct ifconf ifc; + unsigned int nifs, i; + int rq_len; + struct if_nameindex *idx = NULL; +# define RQ_IFS 4 + + if (fd < 0) + return NULL; + + ifc.ifc_buf = NULL; + + /* Guess on the correct buffer size... */ + rq_len = RQ_IFS * sizeof (struct ifreq); + + /* Read all the interfaces out of the kernel. */ + /* Note: alloca's in this loop are diff from glibc because it's smaller */ + do + { + ifc.ifc_buf = extend_alloca (ifc.ifc_buf, rq_len, 2 * rq_len); + ifc.ifc_len = rq_len; + + if (ioctl (fd, SIOCGIFCONF, &ifc) < 0) + { + close_not_cancel_no_status (fd); + return NULL; + } + } + while (ifc.ifc_len == rq_len); + + nifs = ifc.ifc_len / sizeof(struct ifreq); + + idx = malloc ((nifs + 1) * sizeof (struct if_nameindex)); + if (idx == NULL) + { + close_not_cancel_no_status (fd); + __set_errno(ENOBUFS); + return NULL; + } + + for (i = 0; i < nifs; ++i) + { + struct ifreq *ifr = &ifc.ifc_req[i]; + idx[i].if_name = strdup (ifr->ifr_name); + if (idx[i].if_name == NULL + || ioctl (fd, SIOCGIFINDEX, ifr) < 0) + { + int saved_errno = errno; + unsigned int j; + + for (j = 0; j < i; ++j) + free (idx[j].if_name); + free(idx); + close_not_cancel_no_status (fd); + if (saved_errno == EINVAL) + saved_errno = ENOSYS; + else if (saved_errno == ENOMEM) + saved_errno = ENOBUFS; + __set_errno (saved_errno); + return NULL; + } + idx[i].if_index = ifr->ifr_ifindex; + } + + idx[i].if_index = 0; + idx[i].if_name = NULL; + + close_not_cancel_no_status (fd); + return idx; +#endif +} +#else +struct if_nameindex * +if_nameindex (void) +{ + unsigned int nifs = 0; + struct netlink_handle nh = { 0, 0, 0, NULL, NULL }; + struct if_nameindex *idx = NULL; + struct netlink_res *nlp; + + if (__netlink_open (&nh) < 0) + return NULL; + + + /* Tell the kernel that we wish to get a list of all + active interfaces. Collect all data for every interface. */ + if (__netlink_request (&nh, RTM_GETLINK) < 0) + goto exit_free; + + /* Count the interfaces. */ + for (nlp = nh.nlm_list; nlp; nlp = nlp->next) + { + struct nlmsghdr *nlh; + size_t size = nlp->size; + + if (nlp->nlh == NULL) + continue; + + /* Walk through all entries we got from the kernel and look, which + message type they contain. */ + for (nlh = nlp->nlh; NLMSG_OK (nlh, size); nlh = NLMSG_NEXT (nlh, size)) + { + /* Check if the message is what we want. */ + if ((pid_t) nlh->nlmsg_pid != nh.pid || nlh->nlmsg_seq != nlp->seq) + continue; + + if (nlh->nlmsg_type == NLMSG_DONE) + break; /* ok */ + + if (nlh->nlmsg_type == RTM_NEWLINK) + ++nifs; + } + } + + idx = malloc ((nifs + 1) * sizeof (struct if_nameindex)); + if (idx == NULL) + { + nomem: + __set_errno (ENOBUFS); + goto exit_free; + } + + /* Add the interfaces. */ + nifs = 0; + for (nlp = nh.nlm_list; nlp; nlp = nlp->next) + { + struct nlmsghdr *nlh; + size_t size = nlp->size; + + if (nlp->nlh == NULL) + continue; + + /* Walk through all entries we got from the kernel and look, which + message type they contain. */ + for (nlh = nlp->nlh; NLMSG_OK (nlh, size); nlh = NLMSG_NEXT (nlh, size)) + { + /* Check if the message is what we want. */ + if ((pid_t) nlh->nlmsg_pid != nh.pid || nlh->nlmsg_seq != nlp->seq) + continue; + + if (nlh->nlmsg_type == NLMSG_DONE) + break; /* ok */ + + if (nlh->nlmsg_type == RTM_NEWLINK) + { + struct ifinfomsg *ifim = (struct ifinfomsg *) NLMSG_DATA (nlh); + struct rtattr *rta = IFLA_RTA (ifim); + size_t rtasize = IFLA_PAYLOAD (nlh); + + idx[nifs].if_index = ifim->ifi_index; + + while (RTA_OK (rta, rtasize)) + { + char *rta_data = RTA_DATA (rta); + size_t rta_payload = RTA_PAYLOAD (rta); + + if (rta->rta_type == IFLA_IFNAME) + { + idx[nifs].if_name = strndup (rta_data, rta_payload); + if (idx[nifs].if_name == NULL) + { + idx[nifs].if_index = 0; + if_freenameindex (idx); + idx = NULL; + goto nomem; + } + break; + } + + rta = RTA_NEXT (rta, rtasize); + } + + ++nifs; + } + } + } + + idx[nifs].if_index = 0; + idx[nifs].if_name = NULL; + + exit_free: + __netlink_free_handle (&nh); + __netlink_close (&nh); + + return idx; +} +#endif +libc_hidden_def(if_nameindex) + +char * +if_indextoname (unsigned int ifindex, char *ifname) +{ +#if !defined SIOCGIFINDEX + __set_errno (ENOSYS); + return NULL; +#else +# ifdef SIOCGIFNAME + /* Use ioctl to avoid searching the list. */ + struct ifreq ifr; + int fd; + + fd = __opensock (); + + if (fd < 0) + return NULL; + + ifr.ifr_ifindex = ifindex; + if (ioctl (fd, SIOCGIFNAME, &ifr) < 0) + { + int serrno = errno; + close_not_cancel_no_status (fd); + if (serrno == ENODEV) + /* POSIX requires ENXIO. */ + serrno = ENXIO; + __set_errno (serrno); + return NULL; + } + close_not_cancel_no_status (fd); + + return strncpy (ifname, ifr.ifr_name, IFNAMSIZ); +# else + struct if_nameindex *idx; + struct if_nameindex *p; + char *result = NULL; + + idx = if_nameindex(); + + if (idx != NULL) + { + for (p = idx; p->if_index || p->if_name; ++p) + if (p->if_index == ifindex) + { + result = strncpy (ifname, p->if_name, IFNAMSIZ); + break; + } + + if_freenameindex (idx); + + if (result == NULL) + __set_errno (ENXIO); + } + return result; +# endif +#endif +} + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/ifaddrs.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/ifaddrs.c new file mode 100644 index 00000000..3b8b674c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/ifaddrs.c @@ -0,0 +1,848 @@ +/* getifaddrs -- get names and addresses of all network interfaces + Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define __FORCE_GLIBC +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "netlinkaccess.h" + + +#ifndef __libc_use_alloca +# define __libc_use_alloca(x) (x < __MAX_ALLOCA_CUTOFF) +#endif + + +#if __ASSUME_NETLINK_SUPPORT +#ifdef __UCLIBC_SUPPORT_AI_ADDRCONFIG__ +/* struct to hold the data for one ifaddrs entry, so we can allocate + everything at once. */ +struct ifaddrs_storage +{ + struct ifaddrs ifa; + union + { + /* Save space for the biggest of the four used sockaddr types and + avoid a lot of casts. */ + struct sockaddr sa; + struct sockaddr_ll sl; + struct sockaddr_in s4; + struct sockaddr_in6 s6; + } addr, netmask, broadaddr; + char name[IF_NAMESIZE + 1]; +}; +#endif /* __UCLIBC_SUPPORT_AI_ADDRCONFIG__ */ + + +void +__netlink_free_handle (struct netlink_handle *h) +{ + struct netlink_res *ptr; + + ptr = h->nlm_list; + while (ptr != NULL) + { + struct netlink_res *tmpptr; + + tmpptr = ptr->next; + free (ptr); /* doesn't affect errno */ + ptr = tmpptr; + } +} + + +static int +__netlink_sendreq (struct netlink_handle *h, int type) +{ + struct + { + struct nlmsghdr nlh; + struct rtgenmsg g; + } req; + struct sockaddr_nl nladdr; + + if (h->seq == 0) + h->seq = time (NULL); + + req.nlh.nlmsg_len = sizeof (req); + req.nlh.nlmsg_type = type; + req.nlh.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST; + req.nlh.nlmsg_pid = 0; + req.nlh.nlmsg_seq = h->seq; + req.g.rtgen_family = AF_UNSPEC; + + memset (&nladdr, '\0', sizeof (nladdr)); + nladdr.nl_family = AF_NETLINK; + + return TEMP_FAILURE_RETRY (sendto (h->fd, (void *) &req, sizeof (req), 0, + (struct sockaddr *) &nladdr, + sizeof (nladdr))); +} + + +int +__netlink_request (struct netlink_handle *h, int type) +{ + struct netlink_res *nlm_next; + struct netlink_res **new_nlm_list; + static volatile size_t buf_size = 4096; + char *buf; + struct sockaddr_nl nladdr; + struct nlmsghdr *nlmh; + ssize_t read_len; + bool done = false; + bool use_malloc = false; + + if (__netlink_sendreq (h, type) < 0) + return -1; + + size_t this_buf_size = buf_size; + if (__libc_use_alloca (this_buf_size)) + buf = alloca (this_buf_size); + else + { + buf = malloc (this_buf_size); + if (buf != NULL) + use_malloc = true; + else + goto out_fail; + } + + struct iovec iov = { buf, this_buf_size }; + + if (h->nlm_list != NULL) + new_nlm_list = &h->end_ptr->next; + else + new_nlm_list = &h->nlm_list; + + while (! done) + { + struct msghdr msg = + { + (void *) &nladdr, sizeof (nladdr), + &iov, 1, + NULL, 0, + 0 + }; + + read_len = TEMP_FAILURE_RETRY (recvmsg (h->fd, &msg, 0)); + if (read_len < 0) + goto out_fail; + + if (nladdr.nl_pid != 0) + continue; + + if (__builtin_expect (msg.msg_flags & MSG_TRUNC, 0)) + { + if (this_buf_size >= SIZE_MAX / 2) + goto out_fail; + + nlm_next = *new_nlm_list; + while (nlm_next != NULL) + { + struct netlink_res *tmpptr; + + tmpptr = nlm_next->next; + free (nlm_next); + nlm_next = tmpptr; + } + *new_nlm_list = NULL; + + if (__libc_use_alloca (2 * this_buf_size)) + buf = extend_alloca (buf, this_buf_size, 2 * this_buf_size); + else + { + this_buf_size *= 2; + + char *new_buf = realloc (use_malloc ? buf : NULL, this_buf_size); + if (new_buf == NULL) + goto out_fail; + new_buf = buf; + + use_malloc = true; + } + buf_size = this_buf_size; + + iov.iov_base = buf; + iov.iov_len = this_buf_size; + + /* Increase sequence number, so that we can distinguish + between old and new request messages. */ + h->seq++; + + if (__netlink_sendreq (h, type) < 0) + goto out_fail; + + continue; + } + + size_t count = 0; + size_t remaining_len = read_len; + for (nlmh = (struct nlmsghdr *) buf; + NLMSG_OK (nlmh, remaining_len); + nlmh = (struct nlmsghdr *) NLMSG_NEXT (nlmh, remaining_len)) + { + if ((pid_t) nlmh->nlmsg_pid != h->pid + || nlmh->nlmsg_seq != h->seq) + continue; + + ++count; + if (nlmh->nlmsg_type == NLMSG_DONE) + { + /* We found the end, leave the loop. */ + done = true; + break; + } + if (nlmh->nlmsg_type == NLMSG_ERROR) + { + struct nlmsgerr *nlerr = (struct nlmsgerr *) NLMSG_DATA (nlmh); + if (nlmh->nlmsg_len < NLMSG_LENGTH (sizeof (struct nlmsgerr))) + errno = EIO; + else + errno = -nlerr->error; + goto out_fail; + } + } + + /* If there was nothing with the expected nlmsg_pid and nlmsg_seq, + there is no point to record it. */ + if (count == 0) + continue; + + nlm_next = (struct netlink_res *) malloc (sizeof (struct netlink_res) + + read_len); + if (nlm_next == NULL) + goto out_fail; + nlm_next->next = NULL; + nlm_next->nlh = memcpy (nlm_next + 1, buf, read_len); + nlm_next->size = read_len; + nlm_next->seq = h->seq; + if (h->nlm_list == NULL) + h->nlm_list = nlm_next; + else + h->end_ptr->next = nlm_next; + h->end_ptr = nlm_next; + } + + if (use_malloc) + free (buf); + return 0; + +out_fail: + if (use_malloc) + free (buf); + return -1; +} + + +void +__netlink_close (struct netlink_handle *h) +{ + /* Don't modify errno. */ + int serrno = errno; + close(h->fd); + __set_errno(serrno); +} + + +/* Open a NETLINK socket. */ +int +__netlink_open (struct netlink_handle *h) +{ + struct sockaddr_nl nladdr; + + h->fd = socket (PF_NETLINK, SOCK_RAW, NETLINK_ROUTE); + if (h->fd < 0) + goto out; + + memset (&nladdr, '\0', sizeof (nladdr)); + nladdr.nl_family = AF_NETLINK; + if (bind (h->fd, (struct sockaddr *) &nladdr, sizeof (nladdr)) < 0) + { + close_and_out: + __netlink_close (h); + out: + return -1; + } + /* Determine the ID the kernel assigned for this netlink connection. + It is not necessarily the PID if there is more than one socket + open. */ + socklen_t addr_len = sizeof (nladdr); + if (getsockname (h->fd, (struct sockaddr *) &nladdr, &addr_len) < 0) + goto close_and_out; + h->pid = nladdr.nl_pid; + return 0; +} + + +#ifdef __UCLIBC_SUPPORT_AI_ADDRCONFIG__ +/* We know the number of RTM_NEWLINK entries, so we reserve the first + # of entries for this type. All RTM_NEWADDR entries have an index + pointer to the RTM_NEWLINK entry. To find the entry, create + a table to map kernel index entries to our index numbers. + Since we get at first all RTM_NEWLINK entries, it can never happen + that a RTM_NEWADDR index is not known to this map. */ +static int +internal_function +map_newlink (int idx, struct ifaddrs_storage *ifas, int *map, int max) +{ + int i; + + for (i = 0; i < max; i++) + { + if (map[i] == -1) + { + map[i] = idx; + if (i > 0) + ifas[i - 1].ifa.ifa_next = &ifas[i].ifa; + return i; + } + else if (map[i] == idx) + return i; + } + /* This should never be reached. If this will be reached, we have + a very big problem. */ + abort (); +} + + +/* Create a linked list of `struct ifaddrs' structures, one for each + network interface on the host machine. If successful, store the + list in *IFAP and return 0. On errors, return -1 and set `errno'. */ +int +getifaddrs (struct ifaddrs **ifap) +{ + struct netlink_handle nh = { 0, 0, 0, NULL, NULL }; + struct netlink_res *nlp; + struct ifaddrs_storage *ifas; + unsigned int i, newlink, newaddr, newaddr_idx; + int *map_newlink_data; + size_t ifa_data_size = 0; /* Size to allocate for all ifa_data. */ + char *ifa_data_ptr; /* Pointer to the unused part of memory for + ifa_data. */ + int result = 0; + + if (ifap) + *ifap = NULL; + + if (__netlink_open (&nh) < 0) + { + return -1; + } + + /* Tell the kernel that we wish to get a list of all + active interfaces, collect all data for every interface. */ + if (__netlink_request (&nh, RTM_GETLINK) < 0) + { + result = -1; + goto exit_free; + } + + /* Now ask the kernel for all addresses which are assigned + to an interface and collect all data for every interface. + Since we store the addresses after the interfaces in the + list, we will later always find the interface before the + corresponding addresses. */ + ++nh.seq; + if (__netlink_request (&nh, RTM_GETADDR) < 0) + { + result = -1; + goto exit_free; + } + + /* Count all RTM_NEWLINK and RTM_NEWADDR entries to allocate + enough memory. */ + newlink = newaddr = 0; + for (nlp = nh.nlm_list; nlp; nlp = nlp->next) + { + struct nlmsghdr *nlh; + size_t size = nlp->size; + + if (nlp->nlh == NULL) + continue; + + /* Walk through all entries we got from the kernel and look, which + message type they contain. */ + for (nlh = nlp->nlh; NLMSG_OK (nlh, size); nlh = NLMSG_NEXT (nlh, size)) + { + /* Check if the message is what we want. */ + if ((pid_t) nlh->nlmsg_pid != nh.pid || nlh->nlmsg_seq != nlp->seq) + continue; + + if (nlh->nlmsg_type == NLMSG_DONE) + break; /* ok */ + + if (nlh->nlmsg_type == RTM_NEWLINK) + { + /* A RTM_NEWLINK message can have IFLA_STATS data. We need to + know the size before creating the list to allocate enough + memory. */ + struct ifinfomsg *ifim = (struct ifinfomsg *) NLMSG_DATA (nlh); + struct rtattr *rta = IFLA_RTA (ifim); + size_t rtasize = IFLA_PAYLOAD (nlh); + + while (RTA_OK (rta, rtasize)) + { + size_t rta_payload = RTA_PAYLOAD (rta); + + if (rta->rta_type == IFLA_STATS) + { + ifa_data_size += rta_payload; + break; + } + else + rta = RTA_NEXT (rta, rtasize); + } + ++newlink; + } + else if (nlh->nlmsg_type == RTM_NEWADDR) + ++newaddr; + } + } + + /* Return if no interface is up. */ + if ((newlink + newaddr) == 0) + goto exit_free; + + /* Allocate memory for all entries we have and initialize next + pointer. */ + ifas = calloc (1, (newlink + newaddr) * sizeof (ifas[0]) + ifa_data_size); + if (ifas == NULL) + { + result = -1; + goto exit_free; + } + + /* Table for mapping kernel index to entry in our list. */ + map_newlink_data = alloca (newlink * sizeof (int)); + memset (map_newlink_data, '\xff', newlink * sizeof (int)); + + ifa_data_ptr = (char *) &ifas[newlink + newaddr]; + newaddr_idx = 0; /* Counter for newaddr index. */ + + /* Walk through the list of data we got from the kernel. */ + for (nlp = nh.nlm_list; nlp; nlp = nlp->next) + { + struct nlmsghdr *nlh; + size_t size = nlp->size; + + if (nlp->nlh == NULL) + continue; + + /* Walk through one message and look at the type: If it is our + message, we need RTM_NEWLINK/RTM_NEWADDR and stop if we reach + the end or we find the end marker (in this case we ignore the + following data. */ + for (nlh = nlp->nlh; NLMSG_OK (nlh, size); nlh = NLMSG_NEXT (nlh, size)) + { + int ifa_index = 0; + + /* Check if the message is the one we want */ + if ((pid_t) nlh->nlmsg_pid != nh.pid || nlh->nlmsg_seq != nlp->seq) + continue; + + if (nlh->nlmsg_type == NLMSG_DONE) + break; /* ok */ + + if (nlh->nlmsg_type == RTM_NEWLINK) + { + /* We found a new interface. Now extract everything from the + interface data we got and need. */ + struct ifinfomsg *ifim = (struct ifinfomsg *) NLMSG_DATA (nlh); + struct rtattr *rta = IFLA_RTA (ifim); + size_t rtasize = IFLA_PAYLOAD (nlh); + + /* Interfaces are stored in the first "newlink" entries + of our list, starting in the order as we got from the + kernel. */ + ifa_index = map_newlink (ifim->ifi_index - 1, ifas, + map_newlink_data, newlink); + ifas[ifa_index].ifa.ifa_flags = ifim->ifi_flags; + + while (RTA_OK (rta, rtasize)) + { + char *rta_data = RTA_DATA (rta); + size_t rta_payload = RTA_PAYLOAD (rta); + + switch (rta->rta_type) + { + case IFLA_ADDRESS: + if (rta_payload <= sizeof (ifas[ifa_index].addr)) + { + ifas[ifa_index].addr.sl.sll_family = AF_PACKET; + memcpy (ifas[ifa_index].addr.sl.sll_addr, + (char *) rta_data, rta_payload); + ifas[ifa_index].addr.sl.sll_halen = rta_payload; + ifas[ifa_index].addr.sl.sll_ifindex + = ifim->ifi_index; + ifas[ifa_index].addr.sl.sll_hatype = ifim->ifi_type; + + ifas[ifa_index].ifa.ifa_addr + = &ifas[ifa_index].addr.sa; + } + break; + + case IFLA_BROADCAST: + if (rta_payload <= sizeof (ifas[ifa_index].broadaddr)) + { + ifas[ifa_index].broadaddr.sl.sll_family = AF_PACKET; + memcpy (ifas[ifa_index].broadaddr.sl.sll_addr, + (char *) rta_data, rta_payload); + ifas[ifa_index].broadaddr.sl.sll_halen = rta_payload; + ifas[ifa_index].broadaddr.sl.sll_ifindex + = ifim->ifi_index; + ifas[ifa_index].broadaddr.sl.sll_hatype + = ifim->ifi_type; + + ifas[ifa_index].ifa.ifa_broadaddr + = &ifas[ifa_index].broadaddr.sa; + } + break; + + case IFLA_IFNAME: /* Name of Interface */ + if ((rta_payload + 1) <= sizeof (ifas[ifa_index].name)) + { + ifas[ifa_index].ifa.ifa_name = ifas[ifa_index].name; + *(char *) mempcpy (ifas[ifa_index].name, rta_data, + rta_payload) = '\0'; + } + break; + + case IFLA_STATS: /* Statistics of Interface */ + ifas[ifa_index].ifa.ifa_data = ifa_data_ptr; + ifa_data_ptr += rta_payload; + memcpy (ifas[ifa_index].ifa.ifa_data, rta_data, + rta_payload); + break; + + case IFLA_UNSPEC: + break; + case IFLA_MTU: + break; + case IFLA_LINK: + break; + case IFLA_QDISC: + break; + default: + break; + } + + rta = RTA_NEXT (rta, rtasize); + } + } + else if (nlh->nlmsg_type == RTM_NEWADDR) + { + struct ifaddrmsg *ifam = (struct ifaddrmsg *) NLMSG_DATA (nlh); + struct rtattr *rta = IFA_RTA (ifam); + size_t rtasize = IFA_PAYLOAD (nlh); + + /* New Addresses are stored in the order we got them from + the kernel after the interfaces. Theoretically it is possible + that we have holes in the interface part of the list, + but we always have already the interface for this address. */ + ifa_index = newlink + newaddr_idx; + ifas[ifa_index].ifa.ifa_flags + = ifas[map_newlink (ifam->ifa_index - 1, ifas, + map_newlink_data, newlink)].ifa.ifa_flags; + if (ifa_index > 0) + ifas[ifa_index - 1].ifa.ifa_next = &ifas[ifa_index].ifa; + ++newaddr_idx; + + while (RTA_OK (rta, rtasize)) + { + char *rta_data = RTA_DATA (rta); + size_t rta_payload = RTA_PAYLOAD (rta); + + switch (rta->rta_type) + { + case IFA_ADDRESS: + { + struct sockaddr *sa; + + if (ifas[ifa_index].ifa.ifa_addr != NULL) + { + /* In a point-to-poing network IFA_ADDRESS + contains the destination address, local + address is supplied in IFA_LOCAL attribute. + destination address and broadcast address + are stored in an union, so it doesn't matter + which name we use. */ + ifas[ifa_index].ifa.ifa_broadaddr + = &ifas[ifa_index].broadaddr.sa; + sa = &ifas[ifa_index].broadaddr.sa; + } + else + { + ifas[ifa_index].ifa.ifa_addr + = &ifas[ifa_index].addr.sa; + sa = &ifas[ifa_index].addr.sa; + } + + sa->sa_family = ifam->ifa_family; + + switch (ifam->ifa_family) + { + case AF_INET: + /* Size must match that of an address for IPv4. */ + if (rta_payload == 4) + memcpy (&((struct sockaddr_in *) sa)->sin_addr, + rta_data, rta_payload); + break; + + case AF_INET6: + /* Size must match that of an address for IPv6. */ + if (rta_payload == 16) + { + memcpy (&((struct sockaddr_in6 *) sa)->sin6_addr, + rta_data, rta_payload); + if (IN6_IS_ADDR_LINKLOCAL (rta_data) + || IN6_IS_ADDR_MC_LINKLOCAL (rta_data)) + ((struct sockaddr_in6 *) sa)->sin6_scope_id + = ifam->ifa_index; + } + break; + + default: + if (rta_payload <= sizeof (ifas[ifa_index].addr)) + memcpy (sa->sa_data, rta_data, rta_payload); + break; + } + } + break; + + case IFA_LOCAL: + if (ifas[ifa_index].ifa.ifa_addr != NULL) + { + /* If ifa_addr is set and we get IFA_LOCAL, + assume we have a point-to-point network. + Move address to correct field. */ + ifas[ifa_index].broadaddr = ifas[ifa_index].addr; + ifas[ifa_index].ifa.ifa_broadaddr + = &ifas[ifa_index].broadaddr.sa; + memset (&ifas[ifa_index].addr, '\0', + sizeof (ifas[ifa_index].addr)); + } + + ifas[ifa_index].ifa.ifa_addr = &ifas[ifa_index].addr.sa; + ifas[ifa_index].ifa.ifa_addr->sa_family + = ifam->ifa_family; + + switch (ifam->ifa_family) + { + case AF_INET: + /* Size must match that of an address for IPv4. */ + if (rta_payload == 4) + memcpy (&ifas[ifa_index].addr.s4.sin_addr, + rta_data, rta_payload); + break; + + case AF_INET6: + /* Size must match that of an address for IPv6. */ + if (rta_payload == 16) + { + memcpy (&ifas[ifa_index].addr.s6.sin6_addr, + rta_data, rta_payload); + if (IN6_IS_ADDR_LINKLOCAL (rta_data) + || IN6_IS_ADDR_MC_LINKLOCAL (rta_data)) + ifas[ifa_index].addr.s6.sin6_scope_id = + ifam->ifa_index; + } + break; + + default: + if (rta_payload <= sizeof (ifas[ifa_index].addr)) + memcpy (ifas[ifa_index].addr.sa.sa_data, + rta_data, rta_payload); + break; + } + break; + + case IFA_BROADCAST: + /* We get IFA_BROADCAST, so IFA_LOCAL was too much. */ + if (ifas[ifa_index].ifa.ifa_broadaddr != NULL) + memset (&ifas[ifa_index].broadaddr, '\0', + sizeof (ifas[ifa_index].broadaddr)); + + ifas[ifa_index].ifa.ifa_broadaddr + = &ifas[ifa_index].broadaddr.sa; + ifas[ifa_index].ifa.ifa_broadaddr->sa_family + = ifam->ifa_family; + + switch (ifam->ifa_family) + { + case AF_INET: + /* Size must match that of an address for IPv4. */ + if (rta_payload == 4) + memcpy (&ifas[ifa_index].broadaddr.s4.sin_addr, + rta_data, rta_payload); + break; + + case AF_INET6: + /* Size must match that of an address for IPv6. */ + if (rta_payload == 16) + { + memcpy (&ifas[ifa_index].broadaddr.s6.sin6_addr, + rta_data, rta_payload); + if (IN6_IS_ADDR_LINKLOCAL (rta_data) + || IN6_IS_ADDR_MC_LINKLOCAL (rta_data)) + ifas[ifa_index].broadaddr.s6.sin6_scope_id + = ifam->ifa_index; + } + break; + + default: + if (rta_payload <= sizeof (ifas[ifa_index].addr)) + memcpy (&ifas[ifa_index].broadaddr.sa.sa_data, + rta_data, rta_payload); + break; + } + break; + + case IFA_LABEL: + if (rta_payload + 1 <= sizeof (ifas[ifa_index].name)) + { + ifas[ifa_index].ifa.ifa_name = ifas[ifa_index].name; + *(char *) mempcpy (ifas[ifa_index].name, rta_data, + rta_payload) = '\0'; + } + else + abort (); + break; + + case IFA_UNSPEC: + break; + case IFA_CACHEINFO: + break; + default: + break; + } + + rta = RTA_NEXT (rta, rtasize); + } + + /* If we didn't get the interface name with the + address, use the name from the interface entry. */ + if (ifas[ifa_index].ifa.ifa_name == NULL) + ifas[ifa_index].ifa.ifa_name + = ifas[map_newlink (ifam->ifa_index - 1, ifas, + map_newlink_data, newlink)].ifa.ifa_name; + + /* Calculate the netmask. */ + if (ifas[ifa_index].ifa.ifa_addr + && ifas[ifa_index].ifa.ifa_addr->sa_family != AF_UNSPEC + && ifas[ifa_index].ifa.ifa_addr->sa_family != AF_PACKET) + { + uint32_t max_prefixlen = 0; + char *cp = NULL; + + ifas[ifa_index].ifa.ifa_netmask + = &ifas[ifa_index].netmask.sa; + + switch (ifas[ifa_index].ifa.ifa_addr->sa_family) + { + case AF_INET: + cp = (char *) &ifas[ifa_index].netmask.s4.sin_addr; + max_prefixlen = 32; + break; + + case AF_INET6: + cp = (char *) &ifas[ifa_index].netmask.s6.sin6_addr; + max_prefixlen = 128; + break; + } + + ifas[ifa_index].ifa.ifa_netmask->sa_family + = ifas[ifa_index].ifa.ifa_addr->sa_family; + + if (cp != NULL) + { + char c; + unsigned int preflen; + + if ((max_prefixlen > 0) && + (ifam->ifa_prefixlen > max_prefixlen)) + preflen = max_prefixlen; + else + preflen = ifam->ifa_prefixlen; + + for (i = 0; i < (preflen / 8); i++) + *cp++ = 0xff; + c = 0xff; + c <<= (8 - (preflen % 8)); + *cp = c; + } + } + } + } + } + + assert (ifa_data_ptr <= (char *) &ifas[newlink + newaddr] + ifa_data_size); + + if (newaddr_idx > 0) + { + for (i = 0; i < newlink; ++i) + if (map_newlink_data[i] == -1) + { + /* We have fewer links then we anticipated. Adjust the + forward pointer to the first address entry. */ + ifas[i - 1].ifa.ifa_next = &ifas[newlink].ifa; + } + + if (i == 0 && newlink > 0) + /* No valid link, but we allocated memory. We have to + populate the first entry. */ + memmove (ifas, &ifas[newlink], sizeof (struct ifaddrs_storage)); + } + + if (ifap != NULL) + *ifap = &ifas[0].ifa; + + exit_free: + __netlink_free_handle (&nh); + __netlink_close (&nh); + + return result; +} + + +void +freeifaddrs (struct ifaddrs *ifa) +{ + free (ifa); +} + +#endif /* __UCLIBC_SUPPORT_AI_ADDRCONFIG__ */ + +#endif /* __ASSUME_NETLINK_SUPPORT */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/in6_addr.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/in6_addr.c new file mode 100644 index 00000000..321a9f66 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/in6_addr.c @@ -0,0 +1,32 @@ +/* Copyright (C) 1997, 1998, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Philip Blundell , 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define __FORCE_GLIBC +#include +#include + +#ifdef __UCLIBC_HAS_IPV6__ +const struct in6_addr in6addr_any = +{ { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } } }; +const struct in6_addr in6addr_loopback = +{ { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 } } }; +libc_hidden_data_def(in6addr_loopback) +#endif /* __UCLIBC_HAS_IPV6__ */ + + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/inet_addr.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/inet_addr.c new file mode 100644 index 00000000..445f850a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/inet_addr.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_inet_makeaddr +#include "addr.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/inet_aton.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/inet_aton.c new file mode 100644 index 00000000..d79ba07b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/inet_aton.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_inet_aton +#include "addr.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/inet_lnaof.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/inet_lnaof.c new file mode 100644 index 00000000..9887a434 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/inet_lnaof.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_inet_lnaof +#include "addr.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/inet_makeaddr.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/inet_makeaddr.c new file mode 100644 index 00000000..9f946967 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/inet_makeaddr.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_inet_addr +#include "addr.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/inet_net.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/inet_net.c new file mode 100644 index 00000000..3740311f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/inet_net.c @@ -0,0 +1,99 @@ +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#define __FORCE_GLIBC +#include +#include +#include +#include + +/* + * Internet network address interpretation routine. + * The library routines call this routine to interpret + * network numbers. + */ +in_addr_t +inet_network(const char *cp) +{ + u_char c; + int got_data; + u_int base, dots; + in_addr_t res, val; + + res = 0; + dots = 0; + again: + val = 0; + got_data = 0; + if (*cp == '0') { + cp++; + if (*cp == 'x' || *cp == 'X') { + cp++; + base = 16; + } else { + base = 8; + got_data = 1; + } + } else + base = 10; + while ((c = *cp) != '\0') { + if (isdigit(c)) { + if (base == 8 && c > '7') + return (INADDR_NONE); + val = val * base + c - '0'; + } else if (base == 16 && isxdigit(c)) + val = (val << 4) + 10 - (islower(c) ? 'a' : 'A'); + else + break; + if (val > 0xff) + return (INADDR_NONE); + cp++; + got_data = 1; + } + if (!got_data) + return (INADDR_NONE); + if (dots != 0) + res <<= 8; + res |= val; + if (c == '.') { + if (++dots == 4) + return (INADDR_NONE); + cp++; + goto again; + } + if (c != '\0') + return (INADDR_NONE); + return (res); +} +libc_hidden_def(inet_network) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/inet_netof.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/inet_netof.c new file mode 100644 index 00000000..045c120c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/inet_netof.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_inet_netof +#include "addr.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/inet_ntoa.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/inet_ntoa.c new file mode 100644 index 00000000..83ed1380 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/inet_ntoa.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_inet_ntoa +#include "addr.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/lengthd.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/lengthd.c new file mode 100644 index 00000000..d2db685b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/lengthd.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_lengthd +#include RESOLVER diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/lengthq.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/lengthq.c new file mode 100644 index 00000000..beeafc1d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/lengthq.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_lengthq +#include RESOLVER diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/listen.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/listen.c new file mode 100644 index 00000000..32e34789 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/listen.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_listen +#include "socketcalls.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/netlinkaccess.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/netlinkaccess.h new file mode 100644 index 00000000..5111d380 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/netlinkaccess.h @@ -0,0 +1,69 @@ +/* Copyright (C) 2004, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _NETLINKACCESS_H +#define _NETLINKACCESS_H 1 + +#include +#include +#include +#include + +#if defined __ASSUME_NETLINK_SUPPORT || defined __UCLIBC_USE_NETLINK__ +#define _LINUX_TYPES_H +typedef uint8_t __u8; +typedef uint16_t __u16; +typedef uint32_t __u32; +typedef uint64_t __u64; +typedef int32_t __s32; +#include +#include + +struct netlink_res +{ + struct netlink_res *next; + struct nlmsghdr *nlh; + size_t size; /* Size of response. */ + uint32_t seq; /* sequential number we used. */ +}; + + +struct netlink_handle +{ + int fd; /* Netlink file descriptor. */ + pid_t pid; /* Process ID. */ + uint32_t seq; /* The sequence number we use currently. */ + struct netlink_res *nlm_list; /* Pointer to list of responses. */ + struct netlink_res *end_ptr; /* For faster append of new entries. */ +}; + + +#ifndef __ASSUME_NETLINK_SUPPORT +#define __ASSUME_NETLINK_SUPPORT 1 +#endif + +extern int __netlink_open (struct netlink_handle *h) attribute_hidden; +extern void __netlink_close (struct netlink_handle *h) attribute_hidden; +extern void __netlink_free_handle (struct netlink_handle *h) attribute_hidden; +extern int __netlink_request (struct netlink_handle *h, int type) attribute_hidden; + +#else +#define __ASSUME_NETLINK_SUPPORT 0 +#endif + +#endif /* _NETLINKACCESS_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/ns_name.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/ns_name.c new file mode 100644 index 00000000..9df9464a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/ns_name.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_ns_name +#include RESOLVER diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/ntohl.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/ntohl.c new file mode 100644 index 00000000..1a586328 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/ntohl.c @@ -0,0 +1,66 @@ +/* vi: set sw=4 ts=4: + * Functions to convert between host and network byte order. + * + * Copyright (C) 2003-2006 by Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include + +#undef ntohl +#undef ntohs +#undef htonl +#undef htons + +#if __BYTE_ORDER == __BIG_ENDIAN +uint32_t ntohl (uint32_t x) +{ + return x; +} + +uint16_t ntohs (uint16_t x) +{ + return x; +} + +uint32_t htonl (uint32_t x) +{ + return x; +} + +uint16_t htons (uint16_t x) +{ + return x; +} +#elif __BYTE_ORDER == __LITTLE_ENDIAN +uint32_t ntohl (uint32_t x) +{ + return __bswap_32(x); +} + +uint16_t ntohs (uint16_t x) +{ + return __bswap_16(x); +} + +uint32_t htonl (uint32_t x) +{ + return __bswap_32(x); +} + +uint16_t htons (uint16_t x) +{ + return __bswap_16(x); +} +#else +#error "You seem to have an unsupported byteorder" +#endif + +libc_hidden_def(ntohl) +libc_hidden_def(ntohs) +libc_hidden_def(htonl) +libc_hidden_def(htons) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/ntop.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/ntop.c new file mode 100644 index 00000000..fa733e0a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/ntop.c @@ -0,0 +1,396 @@ +/* + * Copyright (c) 1996-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#define __FORCE_GLIBC +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + + +/* + * WARNING: Don't even consider trying to compile this on a system where + * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX. + */ + + +/* const char * + * inet_ntop4(src, dst, size) + * format an IPv4 address + * return: + * `dst' (as a const) + * notes: + * (1) uses no statics + * (2) takes a u_char* not an in_addr as input + * author: + * Paul Vixie, 1996. + */ +static const char * +inet_ntop4(const u_char *src, char *dst, size_t size) +{ + char tmp[sizeof ("255.255.255.255") + 1]; + int octet; + int i; + + tmp[0] = '\0'; + + i = 0; + for (octet = 0; octet <= 3; octet++) { + +#if 0 /* since src is unsigned char, it will never be > 255 ... */ + if (src[octet] > 255) { + __set_errno(ENOSPC); + return NULL; + } +#endif + tmp[i++] = '0' + src[octet] / 100; + if (tmp[i - 1] == '0') { + tmp[i - 1] = '0' + (src[octet] / 10 % 10); + if (tmp[i - 1] == '0') i--; + } else { + tmp[i++] = '0' + (src[octet] / 10 % 10); + } + tmp[i++] = '0' + src[octet] % 10; + tmp[i++] = '.'; + } + tmp[i - 1] = '\0'; + + if (strlen(tmp) > size) { + __set_errno(ENOSPC); + return NULL; + } + + return strcpy(dst, tmp); +} + + +/* const char * + * inet_ntop6(src, dst, size) + * convert IPv6 binary address into presentation (printable) format + * author: + * Paul Vixie, 1996. + */ + +#ifdef __UCLIBC_HAS_IPV6__ + +static const char * +inet_ntop6(const u_char *src, char *dst, size_t size) +{ + /* + * Note that int32_t and int16_t need only be "at least" large enough + * to contain a value of the specified size. On some systems, like + * Crays, there is no such thing as an integer variable with 16 bits. + * Keep this in mind if you think this function should have been coded + * to use pointer overlays. All the world's not a VAX. + */ + char tmp[sizeof ("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")], *tp; + struct { int base, len; } best, cur; + u_int words[8]; + int i; + + /* + * Preprocess: + * Copy the input (bytewise) array into a wordwise array. + * Find the longest run of 0x00's in src[] for :: shorthanding. + */ + memset(words, '\0', sizeof words); + for (i = 0; i < 16; i += 2) + words[i / 2] = (src[i] << 8) | src[i + 1]; + best.base = -1; + cur.base = -1; + best.len = best.len; /* shutting up compiler warning */ + cur.len = cur.len; /* shutting up compiler warning */ + for (i = 0; i < 8; i++) { + if (words[i] == 0) { + if (cur.base == -1) + cur.base = i, cur.len = 1; + else + cur.len++; + } else { + if (cur.base != -1) { + if (best.base == -1 || cur.len > best.len) + best = cur; + cur.base = -1; + } + } + } + if (cur.base != -1) { + if (best.base == -1 || cur.len > best.len) + best = cur; + } + if (best.base != -1 && best.len < 2) + best.base = -1; + + /* + * Format the result. + */ + tp = tmp; + for (i = 0; i < 8; i++) { + /* Are we inside the best run of 0x00's? */ + if (best.base != -1 && i >= best.base && + i < (best.base + best.len)) { + if (i == best.base) + *tp++ = ':'; + continue; + } + /* Are we following an initial run of 0x00s or any real hex? */ + if (i != 0) + *tp++ = ':'; + /* Is this address an encapsulated IPv4? */ + if (i == 6 && best.base == 0 && + (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) { + if (!inet_ntop4(src+12, tp, sizeof tmp - (tp - tmp))) + return NULL; + tp += strlen(tp); + break; + } + tp += sprintf(tp, "%x", words[i]); + } + /* Was it a trailing run of 0x00's? */ + if (best.base != -1 && (best.base + best.len) == 8) + *tp++ = ':'; + *tp++ = '\0'; + + /* + * Check for overflow, copy, and we're done. + */ + if ((size_t)(tp - tmp) > size) { + __set_errno(ENOSPC); + return NULL; + } + return strcpy(dst, tmp); +} +#endif /* __UCLIBC_HAS_IPV6__ */ + + +/* int + * inet_pton4(src, dst) + * like inet_aton() but without all the hexadecimal and shorthand. + * return: + * 1 if `src' is a valid dotted quad, else 0. + * notice: + * does not touch `dst' unless it's returning 1. + * author: + * Paul Vixie, 1996. + */ +static int +inet_pton4(const char *src, u_char *dst) +{ + int saw_digit, octets, ch; + u_char tmp[4], *tp; + + saw_digit = 0; + octets = 0; + *(tp = tmp) = 0; + while ((ch = *src++) != '\0') { + + if (ch >= '0' && ch <= '9') { + u_int new = *tp * 10 + (ch - '0'); + + if (new > 255) + return 0; + *tp = new; + if (! saw_digit) { + if (++octets > 4) + return 0; + saw_digit = 1; + } + } else if (ch == '.' && saw_digit) { + if (octets == 4) + return 0; + *++tp = 0; + saw_digit = 0; + } else + return 0; + } + if (octets < 4) + return 0; + memcpy(dst, tmp, 4); + return 1; +} + +/* int + * inet_pton6(src, dst) + * convert presentation level address to network order binary form. + * return: + * 1 if `src' is a valid [RFC1884 2.2] address, else 0. + * notice: + * (1) does not touch `dst' unless it's returning 1. + * (2) :: in a full address is silently ignored. + * credit: + * inspired by Mark Andrews. + * author: + * Paul Vixie, 1996. + */ + +#ifdef __UCLIBC_HAS_IPV6__ + +static int +inet_pton6(const char *src, u_char *dst) +{ + static const char xdigits[] = "0123456789abcdef"; + u_char tmp[16], *tp, *endp, *colonp; + const char *curtok; + int ch, saw_xdigit; + u_int val; + + + tp = memset(tmp, '\0', 16); + endp = tp + 16; + colonp = NULL; + /* Leading :: requires some special handling. */ + if (*src == ':') + if (*++src != ':') + return 0; + curtok = src; + saw_xdigit = 0; + val = 0; + while ((ch = *src++) != '\0') { + const char *pch; + + /* | 0x20 is cheap tolower(), valid for letters/numbers only */ + pch = strchr(xdigits, (ch | 0x20)); + if (pch != NULL) { + val <<= 4; + val |= (pch - xdigits); + if (val > 0xffff) + return 0; + saw_xdigit = 1; + continue; + } + if (ch == ':') { + curtok = src; + if (!saw_xdigit) { + if (colonp) + return 0; + colonp = tp; + continue; + } + if (*src == '\0') + return 0; + if (tp + 2 > endp) + return 0; + *tp++ = (u_char) (val >> 8); + *tp++ = (u_char) val; + saw_xdigit = 0; + val = 0; + continue; + } + if (ch == '.' && ((tp + 4) <= endp) && + inet_pton4(curtok, tp) > 0) { + tp += 4; + saw_xdigit = 0; + break; /* '\0' was seen by inet_pton4(). */ + } + return 0; + } + if (saw_xdigit) { + if (tp + 2 > endp) + return 0; + *tp++ = (u_char) (val >> 8); + *tp++ = (u_char) val; + } + if (colonp != NULL) { + /* + * Since some memmove()'s erroneously fail to handle + * overlapping regions, we'll do the shift by hand. + */ + const int n = tp - colonp; + int i; + + if (tp == endp) + return 0; + for (i = 1; i <= n; i++) { + endp[- i] = colonp[n - i]; + colonp[n - i] = 0; + } + tp = endp; + } + if (tp != endp) + return 0; + memcpy(dst, tmp, 16); + return 1; +} + +#endif /* __UCLIBC_HAS_IPV6__ */ + + + +/* char * + * inet_ntop(af, src, dst, size) + * convert a network format address to presentation format. + * return: + * pointer to presentation format address (`dst'), or NULL (see errno). + * author: + * Paul Vixie, 1996. + */ +const char * +inet_ntop(int af, const void *src, char *dst, socklen_t size) +{ + switch (af) { + case AF_INET: + return inet_ntop4(src, dst, size); +#ifdef __UCLIBC_HAS_IPV6__ + case AF_INET6: + return inet_ntop6(src, dst, size); +#endif + default: + __set_errno(EAFNOSUPPORT); + return NULL; + } + /* NOTREACHED */ +} +libc_hidden_def(inet_ntop) + + +/* int + * inet_pton(af, src, dst) + * convert from presentation format (which usually means ASCII printable) + * to network format (which is usually some kind of binary format). + * return: + * 1 if the address was valid for the specified address family + * 0 if the address wasn't valid (`dst' is untouched in this case) + * -1 if some other error occurred (`dst' is untouched in this case, too) + * author: + * Paul Vixie, 1996. + */ +int +inet_pton(int af, const char *src, void *dst) +{ + switch (af) { + case AF_INET: + return inet_pton4(src, dst); +#ifdef __UCLIBC_HAS_IPV6__ + case AF_INET6: + return inet_pton6(src, dst); +#endif + default: + __set_errno(EAFNOSUPPORT); + return -1; + } + /* NOTREACHED */ +} +libc_hidden_def(inet_pton) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/opennameservers.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/opennameservers.c new file mode 100644 index 00000000..576c8cae --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/opennameservers.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_opennameservers +#include RESOLVER diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/opensock.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/opensock.c new file mode 100644 index 00000000..86f8c597 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/opensock.c @@ -0,0 +1,43 @@ +/* Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* Return a socket of any type. The socket can be used in subsequent + ioctl calls to talk to the kernel. */ +int __opensock(void) attribute_hidden; +int +__opensock(void) +{ + int fd = -1; +#ifdef __UCLIBC_HAS_IPV6__ + fd = socket(AF_INET6, SOCK_DGRAM, 0); +#endif +#ifdef __UCLIBC_HAS_IPV4__ + if (fd < 0) + fd = socket(AF_INET, SOCK_DGRAM, 0); +#endif + return fd; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/read_etc_hosts_r.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/read_etc_hosts_r.c new file mode 100644 index 00000000..1ec74a50 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/read_etc_hosts_r.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_read_etc_hosts_r +#include RESOLVER diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/recv.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/recv.c new file mode 100644 index 00000000..1c77ce32 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/recv.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_recv +#include "socketcalls.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/recvfrom.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/recvfrom.c new file mode 100644 index 00000000..ec683f6c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/recvfrom.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_recvfrom +#include "socketcalls.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/recvmsg.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/recvmsg.c new file mode 100644 index 00000000..db51d8b0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/recvmsg.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_recvmsg +#include "socketcalls.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/res_comp.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/res_comp.c new file mode 100644 index 00000000..51ea4f2e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/res_comp.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_res_comp +#include RESOLVER diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/res_init.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/res_init.c new file mode 100644 index 00000000..b1a17575 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/res_init.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_res_init +#include RESOLVER diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/res_query.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/res_query.c new file mode 100644 index 00000000..f3e569fa --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/res_query.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_res_query +#include RESOLVER diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/resolv.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/resolv.c new file mode 100644 index 00000000..47bab751 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/resolv.c @@ -0,0 +1,3332 @@ +/* vi: set sw=4 ts=4: */ +/* resolv.c: DNS Resolver + * + * Copyright (C) 1998 Kenneth Albanowski , + * The Silver Hammer Group, Ltd. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + */ +/* + * Portions Copyright (c) 1985, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +/* + * Portions Copyright (c) 1993 by Digital Equipment Corporation. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies, and that + * the name of Digital Equipment Corporation not be used in advertising or + * publicity pertaining to distribution of the document or software without + * specific, written prior permission. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT + * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ +/* + * Portions Copyright (c) 1996-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ +/* + * 5-Oct-2000 W. Greathouse wgreathouse@smva.com + * Fix memory leak and memory corruption. + * -- Every name resolution resulted in + * a new parse of resolv.conf and new + * copy of nameservers allocated by + * strdup. + * -- Every name resolution resulted in + * a new read of resolv.conf without + * resetting index from prior read... + * resulting in exceeding array bounds. + * + * Limit nameservers read from resolv.conf. + * Add "search" domains from resolv.conf. + * Some systems will return a security + * signature along with query answer for + * dynamic DNS entries -- skip/ignore this answer. + * Include arpa/nameser.h for defines. + * General cleanup. + * + * 20-Jun-2001 Michal Moskal + * partial IPv6 support (i.e. gethostbyname2() and resolve_address2() + * functions added), IPv6 nameservers are also supported. + * + * 6-Oct-2001 Jari Korva + * more IPv6 support (IPv6 support for gethostbyaddr(); + * address family parameter and improved IPv6 support for get_hosts_byname + * and read_etc_hosts; getnameinfo() port from glibc; defined + * defined ip6addr_any and in6addr_loopback) + * + * 2-Feb-2002 Erik Andersen + * Added gethostent(), sethostent(), and endhostent() + * + * 17-Aug-2002 Manuel Novoa III + * Fixed __read_etc_hosts_r to return alias list, and modified buffer + * allocation accordingly. See MAX_ALIASES and ALIAS_DIM below. + * This fixes the segfault in the Python 2.2.1 socket test. + * + * 04-Jan-2003 Jay Kulpinski + * Fixed __decode_dotted to count the terminating null character + * in a host name. + * + * 02-Oct-2003 Tony J. White + * Lifted dn_expand() and dependent ns_name_uncompress(), ns_name_unpack(), + * and ns_name_ntop() from glibc 2.3.2 for compatibility with ipsec-tools + * and openldap. + * + * 7-Sep-2004 Erik Andersen + * Added gethostent_r() + * + * 2008, 2009 Denys Vlasenko + * Cleanups, fixes, readability, more cleanups and more fixes. + * + * March 2010 Bernhard Reutner-Fischer + * Switch to common config parser + */ +/* Nota bene: + * The whole resolver code has several (severe) problems: + * - it doesn't even build without IPv4, i.e. !UCLIBC_HAS_IPV4 but only IPv6 + * - it is way too big + * + * Both points above are considered bugs, patches/reimplementations welcome. + */ +/* RFC 1035 +... +Whenever an octet represents a numeric quantity, the left most bit +in the diagram is the high order or most significant bit. +That is, the bit labeled 0 is the most significant bit. +... + +4.1.1. Header section format + 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | ID | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + |QR| OPCODE |AA|TC|RD|RA| 0 0 0| RCODE | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | QDCOUNT | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | ANCOUNT | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | NSCOUNT | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | ARCOUNT | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +ID 16 bit random identifier assigned by querying peer. + Used to match query/response. +QR message is a query (0), or a response (1). +OPCODE 0 standard query (QUERY) + 1 inverse query (IQUERY) + 2 server status request (STATUS) +AA Authoritative Answer - this bit is valid in responses. + Responding name server is an authority for the domain name + in question section. Answer section may have multiple owner names + because of aliases. The AA bit corresponds to the name which matches + the query name, or the first owner name in the answer section. +TC TrunCation - this message was truncated. +RD Recursion Desired - this bit may be set in a query and + is copied into the response. If RD is set, it directs + the name server to pursue the query recursively. + Recursive query support is optional. +RA Recursion Available - this be is set or cleared in a + response, and denotes whether recursive query support is + available in the name server. +RCODE Response code. + 0 No error condition + 1 Format error + 2 Server failure - server was unable to process the query + due to a problem with the name server. + 3 Name Error - meaningful only for responses from + an authoritative name server. The referenced domain name + does not exist. + 4 Not Implemented. + 5 Refused. +QDCOUNT number of entries in the question section. +ANCOUNT number of records in the answer section. +NSCOUNT number of records in the authority records section. +ARCOUNT number of records in the additional records section. + +4.1.2. Question section format + +The section contains QDCOUNT (usually 1) entries, each of this format: + 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + / QNAME / + / / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | QTYPE | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | QCLASS | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +QNAME a domain name represented as a sequence of labels, where + each label consists of a length octet followed by that + number of octets. The domain name terminates with the + zero length octet for the null label of the root. Note + that this field may be an odd number of octets; no + padding is used. +QTYPE a two octet type of the query. + 1 a host address [REQ_A const] + 2 an authoritative name server + 3 a mail destination (Obsolete - use MX) + 4 a mail forwarder (Obsolete - use MX) + 5 the canonical name for an alias + 6 marks the start of a zone of authority + 7 a mailbox domain name (EXPERIMENTAL) + 8 a mail group member (EXPERIMENTAL) + 9 a mail rename domain name (EXPERIMENTAL) + 10 a null RR (EXPERIMENTAL) + 11 a well known service description + 12 a domain name pointer [REQ_PTR const] + 13 host information + 14 mailbox or mail list information + 15 mail exchange + 16 text strings + 0x1c IPv6? + 252 a request for a transfer of an entire zone + 253 a request for mailbox-related records (MB, MG or MR) + 254 a request for mail agent RRs (Obsolete - see MX) + 255 a request for all records +QCLASS a two octet code that specifies the class of the query. + 1 the Internet + (others are historic only) + 255 any class + +4.1.3. Resource record format + +The answer, authority, and additional sections all share the same format: +a variable number of resource records, where the number of records +is specified in the corresponding count field in the header. +Each resource record has this format: + 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + / / + / NAME / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | TYPE | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | CLASS | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | TTL | + | | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | RDLENGTH | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--| + / RDATA / + / / + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +NAME a domain name to which this resource record pertains. +TYPE two octets containing one of the RR type codes. This + field specifies the meaning of the data in the RDATA field. +CLASS two octets which specify the class of the data in the RDATA field. +TTL a 32 bit unsigned integer that specifies the time interval + (in seconds) that the record may be cached. +RDLENGTH a 16 bit integer, length in octets of the RDATA field. +RDATA a variable length string of octets that describes the resource. + The format of this information varies according to the TYPE + and CLASS of the resource record. + If the TYPE is A and the CLASS is IN, it's a 4 octet IP address. + +4.1.4. Message compression + +In order to reduce the size of messages, domain names can be compressed. +An entire domain name or a list of labels at the end of a domain name +is replaced with a pointer to a prior occurance of the same name. + +The pointer takes the form of a two octet sequence: + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ + | 1 1| OFFSET | + +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ +The first two bits are ones. This allows a pointer to be distinguished +from a label, since the label must begin with two zero bits because +labels are restricted to 63 octets or less. The OFFSET field specifies +an offset from the start of the message (i.e., the first octet +of the ID field in the domain header). +A zero offset specifies the first byte of the ID field, etc. +Domain name in a message can be represented as either: + - a sequence of labels ending in a zero octet + - a pointer + - a sequence of labels ending with a pointer + */ + +#define __FORCE_GLIBC +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "internal/parse_config.h" + +/* poll() is not supported in kernel <= 2.0, therefore if __NR_poll is + * not available, we assume an old Linux kernel is in use and we will + * use select() instead. */ +#include +#ifndef __NR_poll +# define USE_SELECT +#endif + +#if defined __UCLIBC_HAS_IPV4__ && defined __UCLIBC_HAS_IPV6__ +#define IF_HAS_BOTH(...) __VA_ARGS__ +#else +#define IF_HAS_BOTH(...) +#endif + + +#define MAX_RECURSE 5 +#define MAXALIASES (4) +#define BUFSZ (80) /* one line */ +#define SBUFSIZE (BUFSZ + 1 + (sizeof(char *) * MAXALIASES)) + +#undef DEBUG +/* #define DEBUG */ + +#ifdef DEBUG +#define DPRINTF(X,args...) fprintf(stderr, X, ##args) +#else +#define DPRINTF(X,args...) +#endif + +#undef ARRAY_SIZE +#define ARRAY_SIZE(v) (sizeof(v) / sizeof((v)[0])) + +/* Make sure the incoming char * buffer is aligned enough to handle our random + * structures. This define is the same as we use for malloc alignment (which + * has same requirements). The offset is the number of bytes we need to adjust + * in order to attain desired alignment. + */ +#define ALIGN_ATTR __alignof__(double __attribute_aligned__ (sizeof(size_t))) +#define ALIGN_BUFFER_OFFSET(buf) ((ALIGN_ATTR - ((size_t)buf % ALIGN_ATTR)) % ALIGN_ATTR) + + +/* Structs */ +struct resolv_header { + int id; + int qr, opcode, aa, tc, rd, ra, rcode; + int qdcount; + int ancount; + int nscount; + int arcount; +}; + +struct resolv_question { + char *dotted; + int qtype; + int qclass; +}; + +struct resolv_answer { + char *dotted; + int atype; + int aclass; + int ttl; + int rdlength; + const unsigned char *rdata; + int rdoffset; + char* buf; + size_t buflen; + size_t add_count; +}; + +enum etc_hosts_action { + GET_HOSTS_BYNAME = 0, + GETHOSTENT, + GET_HOSTS_BYADDR, +}; + +typedef union sockaddr46_t { + struct sockaddr sa; +#ifdef __UCLIBC_HAS_IPV4__ + struct sockaddr_in sa4; +#endif +#ifdef __UCLIBC_HAS_IPV6__ + struct sockaddr_in6 sa6; +#endif +} sockaddr46_t; + + +__UCLIBC_MUTEX_EXTERN(__resolv_lock); + +/* Protected by __resolv_lock */ +extern void (*__res_sync)(void) attribute_hidden; +/*extern uint32_t __resolv_opts attribute_hidden; */ +extern uint8_t __resolv_timeout attribute_hidden; +extern uint8_t __resolv_attempts attribute_hidden; +extern unsigned __nameservers attribute_hidden; +extern unsigned __searchdomains attribute_hidden; +extern sockaddr46_t *__nameserver attribute_hidden; +extern char **__searchdomain attribute_hidden; +#ifdef __UCLIBC_HAS_IPV4__ +extern const struct sockaddr_in __local_nameserver attribute_hidden; +#else +extern const struct sockaddr_in6 __local_nameserver attribute_hidden; +#endif +/* Arbitrary */ +#define MAXLEN_searchdomain 128 + + +/* prototypes for internal functions */ +extern void endhostent_unlocked(void) attribute_hidden; +extern int __get_hosts_byname_r(const char *name, + int type, + struct hostent *result_buf, + char *buf, + size_t buflen, + struct hostent **result, + int *h_errnop) attribute_hidden; +extern int __get_hosts_byaddr_r(const char *addr, + int len, + int type, + struct hostent *result_buf, + char *buf, + size_t buflen, + struct hostent **result, + int *h_errnop) attribute_hidden; +extern parser_t *__open_etc_hosts(void) attribute_hidden; +extern int __read_etc_hosts_r(parser_t *parser, + const char *name, + int type, + enum etc_hosts_action action, + struct hostent *result_buf, + char *buf, + size_t buflen, + struct hostent **result, + int *h_errnop) attribute_hidden; +extern int __dns_lookup(const char *name, + int type, + unsigned char **outpacket, + struct resolv_answer *a) attribute_hidden; +extern int __encode_dotted(const char *dotted, + unsigned char *dest, + int maxlen) attribute_hidden; +extern int __decode_dotted(const unsigned char *packet, + int offset, + int packet_len, + char *dest, + int dest_len) attribute_hidden; +extern int __encode_header(struct resolv_header *h, + unsigned char *dest, + int maxlen) attribute_hidden; +extern void __decode_header(unsigned char *data, + struct resolv_header *h) attribute_hidden; +extern int __encode_question(const struct resolv_question *q, + unsigned char *dest, + int maxlen) attribute_hidden; +extern int __encode_answer(struct resolv_answer *a, + unsigned char *dest, + int maxlen) attribute_hidden; +extern void __open_nameservers(void) attribute_hidden; +extern void __close_nameservers(void) attribute_hidden; + +/* + * Theory of operation. + * + * gethostbyname, getaddrinfo and friends end up here, and they sometimes + * need to talk to DNS servers. In order to do this, we need to read /etc/resolv.conf + * and determine servers' addresses and the like. resolv.conf format: + * + * nameserver + * Address of DNS server. Cumulative. + * If not specified, assumed to be on localhost. + * search [ ]... + * Append these domains to unqualified names. + * See ndots:n option. + * $LOCALDOMAIN (space-separated list) overrides this. + * domain + * Effectively same as "search" with one domain. + * If no "domain" line is present, the domain is determined + * from the local host name returned by gethostname(); + * the domain part is taken to be everything after the first dot. + * If there are no dots, there will be no "domain". + * The domain and search keywords are mutually exclusive. + * If more than one instance of these keywords is present, + * the last instance wins. + * sortlist 130.155.160.0[/255.255.240.0] 130.155.0.0 + * Allows addresses returned by gethostbyname to be sorted. + * Not supported. + * options option[ option]... + * (so far we support timeout:n and attempts:n) + * $RES_OPTIONS (space-separated list) is to be added to "options" + * debug sets RES_DEBUG in _res.options + * ndots:n how many dots there should be so that name will be tried + * first as an absolute name before any search list elements + * are appended to it. Default 1 + * timeout:n how long to wait for response. Default 5 + * (sun seems to have retrans:n synonym) + * attempts:n number of rounds to do before giving up and returning + * an error. Default 2 + * (sun seems to have retry:n synonym) + * rotate sets RES_ROTATE in _res.options, round robin + * selection of nameservers. Otherwise try + * the first listed server first every time + * no-check-names + * sets RES_NOCHECKNAME in _res.options, which disables + * checking of incoming host names for invalid characters + * such as underscore (_), non-ASCII, or control characters + * inet6 sets RES_USE_INET6 in _res.options. Try a AAAA query + * before an A query inside the gethostbyname(), and map + * IPv4 responses in IPv6 "tunnelled form" if no AAAA records + * are found but an A record set exists + * no_tld_query (FreeBSDism?) + * do not attempt to resolve names without dots + * + * We will read and analyze /etc/resolv.conf as needed before + * we do a DNS request. This happens in __dns_lookup. + * It is reread if its mtime is changed. + * + * BSD has res_init routine which is used to initialize resolver state + * which is held in global structure _res. + * Generally, programs call res_init, then fiddle with _res.XXX + * (_res.options and _res.nscount, _res.nsaddr_list[N] + * are popular targets of fiddling) and expect subsequent calls + * to gethostbyname, getaddrinfo, etc to use modified information. + * + * However, historical _res structure is quite awkward. + * Using it for storing /etc/resolv.conf info is not desirable, + * and __dns_lookup does not use it. + * + * We would like to avoid using it unless absolutely necessary. + * If user doesn't use res_init, we should arrange it so that + * _res structure doesn't even *get linked in* into user's application + * (imagine static uclibc build here). + * + * The solution is a __res_sync function pointer, which is normally NULL. + * But if res_init is called, it gets set and any subsequent gethostbyname + * et al "syncronizes" our internal structures with potentially + * modified _res.XXX stuff by calling __res_sync. + * The trick here is that if res_init is not used and not linked in, + * gethostbyname itself won't reference _res and _res won't be linked in + * either. Other possible methods like + * if (__res_sync_just_an_int_flag) + * __sync_me_with_res() + * would pull in __sync_me_with_res, which pulls in _res. Bad. + */ + + +#ifdef L_encodeh + +int attribute_hidden __encode_header(struct resolv_header *h, unsigned char *dest, int maxlen) +{ + if (maxlen < HFIXEDSZ) + return -1; + + dest[0] = (h->id & 0xff00) >> 8; + dest[1] = (h->id & 0x00ff) >> 0; + dest[2] = (h->qr ? 0x80 : 0) | + ((h->opcode & 0x0f) << 3) | + (h->aa ? 0x04 : 0) | + (h->tc ? 0x02 : 0) | + (h->rd ? 0x01 : 0); + dest[3] = (h->ra ? 0x80 : 0) | (h->rcode & 0x0f); + dest[4] = (h->qdcount & 0xff00) >> 8; + dest[5] = (h->qdcount & 0x00ff) >> 0; + dest[6] = (h->ancount & 0xff00) >> 8; + dest[7] = (h->ancount & 0x00ff) >> 0; + dest[8] = (h->nscount & 0xff00) >> 8; + dest[9] = (h->nscount & 0x00ff) >> 0; + dest[10] = (h->arcount & 0xff00) >> 8; + dest[11] = (h->arcount & 0x00ff) >> 0; + + return HFIXEDSZ; +} +#endif + + +#ifdef L_decodeh + +void attribute_hidden __decode_header(unsigned char *data, + struct resolv_header *h) +{ + h->id = (data[0] << 8) | data[1]; + h->qr = (data[2] & 0x80) ? 1 : 0; + h->opcode = (data[2] >> 3) & 0x0f; + h->aa = (data[2] & 0x04) ? 1 : 0; + h->tc = (data[2] & 0x02) ? 1 : 0; + h->rd = (data[2] & 0x01) ? 1 : 0; + h->ra = (data[3] & 0x80) ? 1 : 0; + h->rcode = data[3] & 0x0f; + h->qdcount = (data[4] << 8) | data[5]; + h->ancount = (data[6] << 8) | data[7]; + h->nscount = (data[8] << 8) | data[9]; + h->arcount = (data[10] << 8) | data[11]; +} +#endif + + +#ifdef L_encoded + +/* Encode a dotted string into nameserver transport-level encoding. + This routine is fairly dumb, and doesn't attempt to compress + the data */ +int attribute_hidden __encode_dotted(const char *dotted, unsigned char *dest, int maxlen) +{ + unsigned used = 0; + + while (dotted && *dotted) { + char *c = strchr(dotted, '.'); + int l = c ? c - dotted : strlen(dotted); + + /* two consecutive dots are not valid */ + if (l == 0) + return -1; + + if (l >= (maxlen - used - 1)) + return -1; + + dest[used++] = l; + memcpy(dest + used, dotted, l); + used += l; + + if (!c) + break; + dotted = c + 1; + } + + if (maxlen < 1) + return -1; + + dest[used++] = 0; + + return used; +} +#endif + + +#ifdef L_decoded + +/* Decode a dotted string from nameserver transport-level encoding. + This routine understands compressed data. */ +int attribute_hidden __decode_dotted(const unsigned char *packet, + int offset, + int packet_len, + char *dest, + int dest_len) +{ + unsigned b; + bool measure = 1; + unsigned total = 0; + unsigned used = 0; + + if (!packet) + return -1; + + while (1) { + if (offset >= packet_len) + return -1; + b = packet[offset++]; + if (b == 0) + break; + + if (measure) + total++; + + if ((b & 0xc0) == 0xc0) { + if (offset >= packet_len) + return -1; + if (measure) + total++; + /* compressed item, redirect */ + offset = ((b & 0x3f) << 8) | packet[offset]; + measure = 0; + continue; + } + + if (used + b + 1 >= dest_len) + return -1; + if (offset + b >= packet_len) + return -1; + memcpy(dest + used, packet + offset, b); + offset += b; + used += b; + + if (measure) + total += b; + + if (packet[offset] != 0) + dest[used++] = '.'; + else + dest[used++] = '\0'; + } + + /* The null byte must be counted too */ + if (measure) + total++; + + DPRINTF("Total decode len = %d\n", total); + + return total; +} +#endif + + +#ifdef L_encodeq + +int attribute_hidden __encode_question(const struct resolv_question *q, + unsigned char *dest, + int maxlen) +{ + int i; + + i = __encode_dotted(q->dotted, dest, maxlen); + if (i < 0) + return i; + + dest += i; + maxlen -= i; + + if (maxlen < 4) + return -1; + + dest[0] = (q->qtype & 0xff00) >> 8; + dest[1] = (q->qtype & 0x00ff) >> 0; + dest[2] = (q->qclass & 0xff00) >> 8; + dest[3] = (q->qclass & 0x00ff) >> 0; + + return i + 4; +} +#endif + + +#ifdef L_encodea + +int attribute_hidden __encode_answer(struct resolv_answer *a, unsigned char *dest, int maxlen) +{ + int i; + + i = __encode_dotted(a->dotted, dest, maxlen); + if (i < 0) + return i; + + dest += i; + maxlen -= i; + + if (maxlen < (RRFIXEDSZ + a->rdlength)) + return -1; + + *dest++ = (a->atype & 0xff00) >> 8; + *dest++ = (a->atype & 0x00ff) >> 0; + *dest++ = (a->aclass & 0xff00) >> 8; + *dest++ = (a->aclass & 0x00ff) >> 0; + *dest++ = (a->ttl & 0xff000000) >> 24; + *dest++ = (a->ttl & 0x00ff0000) >> 16; + *dest++ = (a->ttl & 0x0000ff00) >> 8; + *dest++ = (a->ttl & 0x000000ff) >> 0; + *dest++ = (a->rdlength & 0xff00) >> 8; + *dest++ = (a->rdlength & 0x00ff) >> 0; + memcpy(dest, a->rdata, a->rdlength); + + return i + RRFIXEDSZ + a->rdlength; +} +#endif + + +#ifdef CURRENTLY_UNUSED +#ifdef L_encodep + +int __encode_packet(struct resolv_header *h, + struct resolv_question **q, + struct resolv_answer **an, + struct resolv_answer **ns, + struct resolv_answer **ar, + unsigned char *dest, int maxlen) attribute_hidden; +int __encode_packet(struct resolv_header *h, + struct resolv_question **q, + struct resolv_answer **an, + struct resolv_answer **ns, + struct resolv_answer **ar, + unsigned char *dest, int maxlen) +{ + int i, total = 0; + unsigned j; + + i = __encode_header(h, dest, maxlen); + if (i < 0) + return i; + + dest += i; + maxlen -= i; + total += i; + + for (j = 0; j < h->qdcount; j++) { + i = __encode_question(q[j], dest, maxlen); + if (i < 0) + return i; + dest += i; + maxlen -= i; + total += i; + } + + for (j = 0; j < h->ancount; j++) { + i = __encode_answer(an[j], dest, maxlen); + if (i < 0) + return i; + dest += i; + maxlen -= i; + total += i; + } + for (j = 0; j < h->nscount; j++) { + i = __encode_answer(ns[j], dest, maxlen); + if (i < 0) + return i; + dest += i; + maxlen -= i; + total += i; + } + for (j = 0; j < h->arcount; j++) { + i = __encode_answer(ar[j], dest, maxlen); + if (i < 0) + return i; + dest += i; + maxlen -= i; + total += i; + } + + return total; +} +#endif + + +#ifdef L_decodep + +int __decode_packet(unsigned char *data, struct resolv_header *h) attribute_hidden; +int __decode_packet(unsigned char *data, struct resolv_header *h) +{ + __decode_header(data, h); + return HFIXEDSZ; +} +#endif + + +#ifdef L_formquery + +int __form_query(int id, + const char *name, + int type, + unsigned char *packet, + int maxlen); +int __form_query(int id, + const char *name, + int type, + unsigned char *packet, + int maxlen) +{ + struct resolv_header h; + struct resolv_question q; + int i, j; + + memset(&h, 0, sizeof(h)); + h.id = id; + h.qdcount = 1; + + q.dotted = (char *) name; + q.qtype = type; + q.qclass = C_IN; /* CLASS_IN */ + + i = __encode_header(&h, packet, maxlen); + if (i < 0) + return i; + + j = __encode_question(&q, packet + i, maxlen - i); + if (j < 0) + return j; + + return i + j; +} +#endif +#endif /* CURRENTLY_UNUSED */ + + +#ifdef L_opennameservers + +# if __BYTE_ORDER == __LITTLE_ENDIAN +#define NAMESERVER_PORT_N (__bswap_constant_16(NAMESERVER_PORT)) +#else +#define NAMESERVER_PORT_N NAMESERVER_PORT +#endif + +__UCLIBC_MUTEX_INIT(__resolv_lock, PTHREAD_MUTEX_INITIALIZER); + +/* Protected by __resolv_lock */ +void (*__res_sync)(void); +/*uint32_t __resolv_opts; */ +uint8_t __resolv_timeout = RES_TIMEOUT; +uint8_t __resolv_attempts = RES_DFLRETRY; +unsigned __nameservers; +unsigned __searchdomains; +sockaddr46_t *__nameserver; +char **__searchdomain; +#ifdef __UCLIBC_HAS_IPV4__ +const struct sockaddr_in __local_nameserver = { + .sin_family = AF_INET, + .sin_port = NAMESERVER_PORT_N, +}; +#else +const struct sockaddr_in6 __local_nameserver = { + .sin6_family = AF_INET6, + .sin6_port = NAMESERVER_PORT_N, +}; +#endif + +/* Helpers. Both stop on EOL, if it's '\n', it is converted to NUL first */ +static char *skip_nospace(char *p) +{ + while (*p != '\0' && !isspace(*p)) { + if (*p == '\n') { + *p = '\0'; + break; + } + p++; + } + return p; +} +static char *skip_and_NUL_space(char *p) +{ + /* NB: '\n' is not isspace! */ + while (1) { + char c = *p; + if (c == '\0' || !isspace(c)) + break; + *p = '\0'; + if (c == '\n' || c == '#') + break; + p++; + } + return p; +} + +/* Must be called under __resolv_lock. */ +void attribute_hidden __open_nameservers(void) +{ + static uint32_t resolv_conf_mtime; + + char szBuffer[MAXLEN_searchdomain]; + FILE *fp; + int i; + sockaddr46_t sa; + + if (!__res_sync) { + /* Reread /etc/resolv.conf if it was modified. */ + struct stat sb; + if (stat("/etc/resolv.conf", &sb) != 0) + sb.st_mtime = 0; + if (resolv_conf_mtime != (uint32_t)sb.st_mtime) { + resolv_conf_mtime = sb.st_mtime; + __close_nameservers(); /* force config reread */ + } + } + + if (__nameservers) + goto sync; + + __resolv_timeout = RES_TIMEOUT; + __resolv_attempts = RES_DFLRETRY; + + fp = fopen("/etc/resolv.conf", "r"); +#ifdef FALLBACK_TO_CONFIG_RESOLVCONF + if (!fp) { + /* If we do not have a pre-populated /etc/resolv.conf then + try to use the one from /etc/config which exists on numerous + systems ranging from some uClinux to IRIX installations and + may be the only /etc dir that was mounted rw. */ + fp = fopen("/etc/config/resolv.conf", "r"); + } +#endif + + if (fp) { + while (fgets(szBuffer, sizeof(szBuffer), fp) != NULL) { + void *ptr; + char *keyword, *p; + + keyword = p = skip_and_NUL_space(szBuffer); + /* skip keyword */ + p = skip_nospace(p); + /* find next word */ + p = skip_and_NUL_space(p); + + if (strcmp(keyword, "nameserver") == 0) { + /* terminate IP addr */ + *skip_nospace(p) = '\0'; + memset(&sa, 0, sizeof(sa)); + if (0) /* nothing */; +#ifdef __UCLIBC_HAS_IPV6__ + else if (inet_pton(AF_INET6, p, &sa.sa6.sin6_addr) > 0) { + sa.sa6.sin6_family = AF_INET6; + sa.sa6.sin6_port = htons(NAMESERVER_PORT); + } +#endif +#ifdef __UCLIBC_HAS_IPV4__ + else if (inet_pton(AF_INET, p, &sa.sa4.sin_addr) > 0) { + sa.sa4.sin_family = AF_INET; + sa.sa4.sin_port = htons(NAMESERVER_PORT); + } +#endif + else + continue; /* garbage on this line */ + ptr = realloc(__nameserver, (__nameservers + 1) * sizeof(__nameserver[0])); + if (!ptr) + continue; + __nameserver = ptr; + __nameserver[__nameservers++] = sa; /* struct copy */ + continue; + } + if (strcmp(keyword, "domain") == 0 || strcmp(keyword, "search") == 0) { + char *p1; + + /* free old domains ("last 'domain' or 'search' wins" rule) */ + while (__searchdomains) + free(__searchdomain[--__searchdomains]); + /*free(__searchdomain);*/ + /*__searchdomain = NULL; - not necessary */ + next_word: + /* terminate current word */ + p1 = skip_nospace(p); + /* find next word (maybe) */ + p1 = skip_and_NUL_space(p1); + /* add it */ + ptr = realloc(__searchdomain, (__searchdomains + 1) * sizeof(__searchdomain[0])); + if (!ptr) + continue; + __searchdomain = ptr; + /* NB: strlen(p) <= MAXLEN_searchdomain) because szBuffer[] is smaller */ + ptr = strdup(p); + if (!ptr) + continue; + DPRINTF("adding search %s\n", (char*)ptr); + __searchdomain[__searchdomains++] = (char*)ptr; + p = p1; + if (*p) + goto next_word; + continue; + } + /* if (strcmp(keyword, "sortlist") == 0)... */ + if (strcmp(keyword, "options") == 0) { + char *p1; + uint8_t *what; + + if (p == NULL || (p1 = strchr(p, ':')) == NULL) + continue; + *p1++ = '\0'; + if (strcmp(p, "timeout") == 0) + what = &__resolv_timeout; + else if (strcmp(p, "attempts") == 0) + what = &__resolv_attempts; + else + continue; + *what = atoi(p1); + DPRINTF("option %s:%d\n", p, *what); + } + } + fclose(fp); + } + if (__nameservers == 0) { + /* Have to handle malloc failure! What a mess... + * And it's not only here, we need to be careful + * to never write into __nameserver[0] if it points + * to constant __local_nameserver, or free it. */ + __nameserver = malloc(sizeof(__nameserver[0])); + if (__nameserver) + memcpy(__nameserver, &__local_nameserver, sizeof(__local_nameserver)); + else + __nameserver = (void*) &__local_nameserver; + __nameservers++; + } + if (__searchdomains == 0) { + char buf[256]; + char *p; + i = gethostname(buf, sizeof(buf) - 1); + buf[sizeof(buf) - 1] = '\0'; + if (i == 0 && (p = strchr(buf, '.')) != NULL && p[1]) { + p = strdup(p + 1); + if (!p) + goto err; + __searchdomain = malloc(sizeof(__searchdomain[0])); + if (!__searchdomain) { + free(p); + goto err; + } + __searchdomain[0] = p; + __searchdomains++; + err: ; + } + } + DPRINTF("nameservers = %d\n", __nameservers); + + sync: + if (__res_sync) + __res_sync(); +} +#endif + + +#ifdef L_closenameservers + +/* Must be called under __resolv_lock. */ +void attribute_hidden __close_nameservers(void) +{ + if (__nameserver != (void*) &__local_nameserver) + free(__nameserver); + __nameserver = NULL; + __nameservers = 0; + while (__searchdomains) + free(__searchdomain[--__searchdomains]); + free(__searchdomain); + __searchdomain = NULL; + /*__searchdomains = 0; - already is */ +} +#endif + + +#ifdef L_dnslookup + +/* Helpers */ +static int __length_question(const unsigned char *data, int maxlen) +{ + const unsigned char *start; + unsigned b; + + if (!data) + return -1; + + start = data; + while (1) { + if (maxlen <= 0) + return -1; + b = *data++; + if (b == 0) + break; + if ((b & 0xc0) == 0xc0) { + /* It's a "compressed" name. */ + data++; /* skip lsb of redirected offset */ + maxlen -= 2; + break; + } + data += b; + maxlen -= (b + 1); /* account for data++ above */ + } + /* Up to here we were skipping encoded name */ + + /* Account for QTYPE and QCLASS fields */ + if (maxlen < 4) + return -1; + return data - start + 2 + 2; +} + +static int __decode_answer(const unsigned char *message, /* packet */ + int offset, + int len, /* total packet len */ + struct resolv_answer *a) +{ + char temp[256]; + int i; + + DPRINTF("decode_answer(start): off %d, len %d\n", offset, len); + i = __decode_dotted(message, offset, len, temp, sizeof(temp)); + if (i < 0) + return i; + + message += offset + i; + len -= i + RRFIXEDSZ + offset; + if (len < 0) { + DPRINTF("decode_answer: off %d, len %d, i %d\n", offset, len, i); + return len; + } + +/* TODO: what if strdup fails? */ + a->dotted = strdup(temp); + a->atype = (message[0] << 8) | message[1]; + message += 2; + a->aclass = (message[0] << 8) | message[1]; + message += 2; + a->ttl = (message[0] << 24) | + (message[1] << 16) | (message[2] << 8) | (message[3] << 0); + message += 4; + a->rdlength = (message[0] << 8) | message[1]; + message += 2; + a->rdata = message; + a->rdoffset = offset + i + RRFIXEDSZ; + + DPRINTF("i=%d,rdlength=%d\n", i, a->rdlength); + + if (len < a->rdlength) + return -1; + return i + RRFIXEDSZ + a->rdlength; +} + +/* On entry: + * a.buf(len) = auxiliary buffer for IP addresses after first one + * a.add_count = how many additional addresses are there already + * outpacket = where to save ptr to raw packet? can be NULL + * On exit: + * ret < 0: error, all other data is not valid + * ret >= 0: length of reply packet + * a.add_count & a.buf: updated + * a.rdlength: length of addresses (4 bytes for IPv4) + * *outpacket: updated (packet is malloced, you need to free it) + * a.rdata: points into *outpacket to 1st IP addr + * NB: don't pass outpacket == NULL if you need to use a.rdata! + * a.atype: type of query? + * a.dotted: which name we _actually_ used. May contain search domains + * appended. (why the filed is called "dotted" I have no idea) + * This is a malloced string. May be NULL because strdup failed. + */ +int attribute_hidden __dns_lookup(const char *name, + int type, + unsigned char **outpacket, + struct resolv_answer *a) +{ + /* Protected by __resolv_lock: */ + static int last_ns_num = 0; + static uint16_t last_id = 1; + + int i, j, fd, rc; + int packet_len; + int name_len; +#ifdef USE_SELECT + struct timeval tv; + fd_set fds; +#else + struct pollfd fds; +#endif + struct resolv_header h; + struct resolv_question q; + struct resolv_answer ma; + bool first_answer = 1; + int retries_left; + unsigned char *packet = malloc(PACKETSZ); + char *lookup; + int variant = -1; /* search domain to append, -1: none */ + int local_ns_num = -1; /* Nth server to use */ + int local_id = local_id; /* for compiler */ + int sdomains; + bool ends_with_dot; + sockaddr46_t sa; + + fd = -1; + lookup = NULL; + name_len = strlen(name); + if ((unsigned)name_len >= MAXDNAME - MAXLEN_searchdomain - 2) + goto fail; /* paranoia */ + lookup = malloc(name_len + 1/*for '.'*/ + MAXLEN_searchdomain + 1); + if (!packet || !lookup || !name[0]) + goto fail; + ends_with_dot = (name[name_len - 1] == '.'); + /* no strcpy! paranoia, user might change name[] under us */ + memcpy(lookup, name, name_len); + + DPRINTF("Looking up type %d answer for '%s'\n", type, name); + retries_left = 0; /* for compiler */ + do { + int pos; + unsigned reply_timeout; + + if (fd != -1) { + close(fd); + fd = -1; + } + + /* Mess with globals while under lock */ + /* NB: even data *pointed to* by globals may vanish + * outside the locks. We should assume any and all + * globals can completely change between locked + * code regions. OTOH, this is rare, so we don't need + * to handle it "nicely" (do not skip servers, + * search domains, etc), we only need to ensure + * we do not SEGV, use freed+overwritten data + * or do other Really Bad Things. */ + __UCLIBC_MUTEX_LOCK(__resolv_lock); + __open_nameservers(); + sdomains = __searchdomains; + lookup[name_len] = '\0'; + if ((unsigned)variant < sdomains) { + /* lookup is name_len + 1 + MAXLEN_searchdomain + 1 long */ + /* __searchdomain[] is not bigger than MAXLEN_searchdomain */ + lookup[name_len] = '.'; + strcpy(&lookup[name_len + 1], __searchdomain[variant]); + } + /* first time? pick starting server etc */ + if (local_ns_num < 0) { + local_id = last_id; +/*TODO: implement /etc/resolv.conf's "options rotate" + (a.k.a. RES_ROTATE bit in _res.options) + local_ns_num = 0; + if (_res.options & RES_ROTATE) */ + local_ns_num = last_ns_num; + retries_left = __nameservers * __resolv_attempts; + } + retries_left--; + if (local_ns_num >= __nameservers) + local_ns_num = 0; + local_id++; + local_id &= 0xffff; + /* write new values back while still under lock */ + last_id = local_id; + last_ns_num = local_ns_num; + /* struct copy */ + /* can't just take a pointer, __nameserver[x] + * is not safe to use outside of locks */ + sa = __nameserver[local_ns_num]; + __UCLIBC_MUTEX_UNLOCK(__resolv_lock); + + memset(packet, 0, PACKETSZ); + memset(&h, 0, sizeof(h)); + + /* encode header */ + h.id = local_id; + h.qdcount = 1; + h.rd = 1; + DPRINTF("encoding header\n", h.rd); + i = __encode_header(&h, packet, PACKETSZ); + if (i < 0) + goto fail; + + /* encode question */ + DPRINTF("lookup name: %s\n", lookup); + q.dotted = lookup; + q.qtype = type; + q.qclass = C_IN; /* CLASS_IN */ + j = __encode_question(&q, packet+i, PACKETSZ-i); + if (j < 0) + goto fail; + packet_len = i + j; + + /* send packet */ +#ifdef DEBUG + { + const socklen_t plen = sa.sa.sa_family == AF_INET ? INET_ADDRSTRLEN : INET6_ADDRSTRLEN; + char *pbuf = malloc(plen); + if (pbuf == NULL) ;/* nothing */ +#ifdef __UCLIBC_HAS_IPV6__ + else if (sa.sa.sa_family == AF_INET6) + pbuf = (char*)inet_ntop(AF_INET6, &sa.sa6.sin6_addr, pbuf, plen); +#endif +#ifdef __UCLIBC_HAS_IPV4__ + else if (sa.sa.sa_family == AF_INET) + pbuf = (char*)inet_ntop(AF_INET, &sa.sa4.sin_addr, pbuf, plen); +#endif + DPRINTF("On try %d, sending query to %s, port %d\n", + retries_left, pbuf, NAMESERVER_PORT); + free(pbuf); + } +#endif + fd = socket(sa.sa.sa_family, SOCK_DGRAM, IPPROTO_UDP); + if (fd < 0) /* paranoia */ + goto try_next_server; + rc = connect(fd, &sa.sa, sizeof(sa)); + if (rc < 0) { + /*if (errno == ENETUNREACH) { */ + /* routing error, presume not transient */ + goto try_next_server; + /*} */ +/*For example, what transient error this can be? Can't think of any */ + /* retry */ + /*continue; */ + } + DPRINTF("Xmit packet len:%d id:%d qr:%d\n", packet_len, h.id, h.qr); + /* no error check - if it fails, we time out on recv */ + send(fd, packet, packet_len, 0); + +#ifdef USE_SELECT + reply_timeout = __resolv_timeout; + wait_again: + FD_ZERO(&fds); + FD_SET(fd, &fds); + tv.tv_sec = reply_timeout; + tv.tv_usec = 0; + if (select(fd + 1, &fds, NULL, NULL, &tv) <= 0) { + DPRINTF("Timeout\n"); + /* timed out, so retry send and receive + * to next nameserver */ + goto try_next_server; + } + reply_timeout--; +#else + reply_timeout = __resolv_timeout * 1000; + wait_again: + fds.fd = fd; + fds.events = POLLIN; + if (poll(&fds, 1, reply_timeout) <= 0) { + DPRINTF("Timeout\n"); + /* timed out, so retry send and receive + * to next nameserver */ + goto try_next_server; + } +/*TODO: better timeout accounting?*/ + reply_timeout -= 1000; +#endif + +/* vda: a bogus response seen in real world (caused SEGV in uclibc): + * "ping www.google.com" sending AAAA query and getting + * response with one answer... with answer part missing! + * Fixed by thorough checks for not going past the packet's end. + */ +#ifdef DEBUG + { + static const char test_query[32] = "\0\2\1\0\0\1\0\0\0\0\0\0\3www\6google\3com\0\0\34\0\1"; + static const char test_respn[32] = "\0\2\201\200\0\1\0\1\0\0\0\0\3www\6google\3com\0\0\34\0\1"; + pos = memcmp(packet + 2, test_query + 2, 30); + packet_len = recv(fd, packet, PACKETSZ, MSG_DONTWAIT); + if (pos == 0) { + packet_len = 32; + memcpy(packet + 2, test_respn + 2, 30); + } + } +#else + packet_len = recv(fd, packet, PACKETSZ, MSG_DONTWAIT); +#endif + + if (packet_len < HFIXEDSZ) { + /* too short! + * If the peer did shutdown then retry later, + * try next peer on error. + * it's just a bogus packet from somewhere */ + bogus_packet: + if (packet_len >= 0 && reply_timeout) + goto wait_again; + goto try_next_server; + } + __decode_header(packet, &h); + DPRINTF("len:%d id:%d qr:%d\n", packet_len, h.id, h.qr); + if (h.id != local_id || !h.qr) { + /* unsolicited */ + goto bogus_packet; + } + + DPRINTF("Got response (i think)!\n"); + DPRINTF("qrcount=%d,ancount=%d,nscount=%d,arcount=%d\n", + h.qdcount, h.ancount, h.nscount, h.arcount); + DPRINTF("opcode=%d,aa=%d,tc=%d,rd=%d,ra=%d,rcode=%d\n", + h.opcode, h.aa, h.tc, h.rd, h.ra, h.rcode); + + /* bug 660 says we treat negative response as an error + * and retry, which is, eh, an error. :) + * We were incurring long delays because of this. */ + if (h.rcode == NXDOMAIN) { + /* if possible, try next search domain */ + if (!ends_with_dot) { + DPRINTF("variant:%d sdomains:%d\n", variant, sdomains); + if (variant < sdomains - 1) { + /* next search domain */ + variant++; + continue; + } + /* no more search domains to try */ + } + /* dont loop, this is "no such host" situation */ + h_errno = HOST_NOT_FOUND; + goto fail1; + } + /* Insert other non-fatal errors here, which do not warrant + * switching to next nameserver */ + + /* Strange error, assuming this nameserver is feeling bad */ + if (h.rcode != 0) + goto try_next_server; + + /* Code below won't work correctly with h.ancount == 0, so... */ + if (h.ancount <= 0) { + h_errno = NO_DATA; /* [is this correct code to check for?] */ + goto fail1; + } + pos = HFIXEDSZ; + for (j = 0; j < h.qdcount; j++) { + DPRINTF("Skipping question %d at %d\n", j, pos); + i = __length_question(packet + pos, packet_len - pos); + if (i < 0) { + DPRINTF("Packet'question section " + "is truncated, trying next server\n"); + goto try_next_server; + } + pos += i; + DPRINTF("Length of question %d is %d\n", j, i); + } + DPRINTF("Decoding answer at pos %d\n", pos); + + first_answer = 1; + for (j = 0; j < h.ancount; j++) { + i = __decode_answer(packet, pos, packet_len, &ma); + if (i < 0) { + DPRINTF("failed decode %d\n", i); + /* If the message was truncated but we have + * decoded some answers, pretend it's OK */ + if (j && h.tc) + break; + goto try_next_server; + } + pos += i; + + if (first_answer) { + ma.buf = a->buf; + ma.buflen = a->buflen; + ma.add_count = a->add_count; + memcpy(a, &ma, sizeof(ma)); + if (a->atype != T_SIG && (NULL == a->buf || (type != T_A && type != T_AAAA))) + break; + if (a->atype != type) + continue; + a->add_count = h.ancount - j - 1; + if ((a->rdlength + sizeof(struct in_addr*)) * a->add_count > a->buflen) + break; + a->add_count = 0; + first_answer = 0; + } else { + free(ma.dotted); + if (ma.atype != type) + continue; + if (a->rdlength != ma.rdlength) { + free(a->dotted); + DPRINTF("Answer address len(%u) differs from original(%u)\n", + ma.rdlength, a->rdlength); + goto try_next_server; + } + memcpy(a->buf + (a->add_count * ma.rdlength), ma.rdata, ma.rdlength); + ++a->add_count; + } + } + + /* Success! */ + DPRINTF("Answer name = |%s|\n", a->dotted); + DPRINTF("Answer type = |%d|\n", a->atype); + if (fd != -1) + close(fd); + if (outpacket) + *outpacket = packet; + else + free(packet); + free(lookup); + return packet_len; + + try_next_server: + /* Try next nameserver */ + local_ns_num++; + variant = -1; + } while (retries_left > 0); + + fail: + h_errno = NETDB_INTERNAL; + fail1: + if (fd != -1) + close(fd); + free(lookup); + free(packet); + return -1; +} +#endif + + +#ifdef L_read_etc_hosts_r + +parser_t * __open_etc_hosts(void) +{ + parser_t * parser; + if ((parser = config_open("/etc/hosts")) == NULL) { +#ifdef FALLBACK_TO_CONFIG_RESOLVCONF + parser = config_open("/etc/config/hosts"); +#endif + } + return parser; +} + +#define MINTOKENS 2 //dotted ip address + canonical name +#define MAXTOKENS (MINTOKENS + MAXALIASES) +#define HALISTOFF (sizeof(char*) * MAXTOKENS) +#define INADDROFF (HALISTOFF + 2 * sizeof(char*)) + +int attribute_hidden __read_etc_hosts_r( + parser_t * parser, + const char *name, + int type, + enum etc_hosts_action action, + struct hostent *result_buf, + char *buf, size_t buflen, + struct hostent **result, + int *h_errnop) +{ + char **alias; + char **host_aliases; + char **tok = NULL; + struct in_addr *h_addr0 = NULL; + const size_t aliaslen = INADDROFF + +#ifdef __UCLIBC_HAS_IPV6__ + sizeof(struct in6_addr) +#else + sizeof(struct in_addr) +#endif + ; + int ret = HOST_NOT_FOUND; + + *h_errnop = NETDB_INTERNAL; + if (buflen < aliaslen + || (buflen - aliaslen) < BUFSZ + 1) + return ERANGE; + if (parser == NULL) + parser = __open_etc_hosts(); + if (parser == NULL) { + *result = NULL; + return errno; + } + /* Layout in buf: + * char *alias[MAXTOKENS] = {address, name, aliases...} + * char **h_addr_list[1] = {*in[6]_addr, NULL} + * struct in[6]_addr + * char line_buffer[BUFSZ+]; + */ + parser->data = buf; + parser->data_len = aliaslen; + parser->line_len = buflen - aliaslen; + *h_errnop = HOST_NOT_FOUND; + /* [[:space:]][] */ + while (config_read(parser, &tok, MAXTOKENS, MINTOKENS, "# \t", PARSE_NORMAL)) { + result_buf->h_aliases = alias = host_aliases = tok+1; + if (action == GETHOSTENT) { + /* Return whatever the next entry happens to be. */ + break; + } + if (action == GET_HOSTS_BYADDR) { + if (strcmp(name, *tok) != 0) + continue; + } else { /* GET_HOSTS_BYNAME */ + while (*alias) { + if (strcasecmp(name, *(alias++)) == 0) + goto found; + } + continue; + } +found: + result_buf->h_name = *(result_buf->h_aliases++); + result_buf->h_addr_list = (char**)(buf + HALISTOFF); + *(result_buf->h_addr_list + 1) = '\0'; + h_addr0 = (struct in_addr*)(buf + INADDROFF); + result_buf->h_addr = (char*)h_addr0; + if (0) /* nothing */; +#ifdef __UCLIBC_HAS_IPV4__ + else if (type == AF_INET + && inet_pton(AF_INET, *tok, h_addr0) > 0) { + DPRINTF("Found INET\n"); + result_buf->h_addrtype = AF_INET; + result_buf->h_length = sizeof(struct in_addr); + *result = result_buf; + ret = NETDB_SUCCESS; + } +#endif +#ifdef __UCLIBC_HAS_IPV6__ +#define in6 ((struct in6_addr *)buf) + else if (type == AF_INET6 + && inet_pton(AF_INET6, *tok, h_addr0) > 0) { + DPRINTF("Found INET6\n"); + result_buf->h_addrtype = AF_INET6; + result_buf->h_length = sizeof(struct in6_addr); + *result = result_buf; + ret = NETDB_SUCCESS; + } +#endif + else { + /* continue parsing in the hope the user has multiple + * host types listed in the database like so: + * host + * host + * If looking for an IPv6 addr, don't bail when we got the IPv4 + */ + DPRINTF("Error: Found host but different address family\n"); + /* NB: gethostbyname2_r depends on this feature + * to avoid looking for IPv6 addr of "localhost" etc */ + ret = TRY_AGAIN; + continue; + } + break; + } + if (action != GETHOSTENT) + config_close(parser); + return ret; +#undef in6 +} +#endif + + +#ifdef L_get_hosts_byname_r + +int attribute_hidden __get_hosts_byname_r(const char *name, + int type, + struct hostent *result_buf, + char *buf, + size_t buflen, + struct hostent **result, + int *h_errnop) +{ + return __read_etc_hosts_r(NULL, name, type, GET_HOSTS_BYNAME, + result_buf, buf, buflen, result, h_errnop); +} +#endif + + +#ifdef L_get_hosts_byaddr_r + +int attribute_hidden __get_hosts_byaddr_r(const char *addr, + int len, + int type, + struct hostent *result_buf, + char *buf, + size_t buflen, + struct hostent **result, + int *h_errnop) +{ +#ifndef __UCLIBC_HAS_IPV6__ + char ipaddr[INET_ADDRSTRLEN]; +#else + char ipaddr[INET6_ADDRSTRLEN]; +#endif + + switch (type) { +#ifdef __UCLIBC_HAS_IPV4__ + case AF_INET: + if (len != sizeof(struct in_addr)) + return 0; + break; +#endif +#ifdef __UCLIBC_HAS_IPV6__ + case AF_INET6: + if (len != sizeof(struct in6_addr)) + return 0; + break; +#endif + default: + return 0; + } + + inet_ntop(type, addr, ipaddr, sizeof(ipaddr)); + + return __read_etc_hosts_r(NULL, ipaddr, type, GET_HOSTS_BYADDR, + result_buf, buf, buflen, result, h_errnop); +} +#endif + + +#ifdef L_getnameinfo + +int getnameinfo(const struct sockaddr *sa, + socklen_t addrlen, + char *host, + socklen_t hostlen, + char *serv, + socklen_t servlen, + unsigned flags) +{ + int serrno = errno; + unsigned ok; + struct hostent *hoste = NULL; + char domain[256]; + + if (flags & ~(NI_NUMERICHOST|NI_NUMERICSERV|NI_NOFQDN|NI_NAMEREQD|NI_DGRAM)) + return EAI_BADFLAGS; + + if (sa == NULL || addrlen < sizeof(sa_family_t)) + return EAI_FAMILY; + + ok = sa->sa_family; + if (ok == AF_LOCAL) /* valid */; +#ifdef __UCLIBC_HAS_IPV4__ + else if (ok == AF_INET) { + if (addrlen < sizeof(struct sockaddr_in)) + return EAI_FAMILY; + } +#endif +#ifdef __UCLIBC_HAS_IPV6__ + else if (ok == AF_INET6) { + if (addrlen < sizeof(struct sockaddr_in6)) + return EAI_FAMILY; + } +#endif + else + return EAI_FAMILY; + + ok = 0; + if (host != NULL && hostlen > 0) + switch (sa->sa_family) { + case AF_INET: +#ifdef __UCLIBC_HAS_IPV6__ + case AF_INET6: +#endif + if (!(flags & NI_NUMERICHOST)) { + if (0) /* nothing */; +#ifdef __UCLIBC_HAS_IPV6__ + else if (sa->sa_family == AF_INET6) + hoste = gethostbyaddr((const void *) + &(((const struct sockaddr_in6 *) sa)->sin6_addr), + sizeof(struct in6_addr), AF_INET6); +#endif +#ifdef __UCLIBC_HAS_IPV4__ + else + hoste = gethostbyaddr((const void *) + &(((const struct sockaddr_in *)sa)->sin_addr), + sizeof(struct in_addr), AF_INET); +#endif + + if (hoste) { + char *c; +#undef min +#define min(x,y) (((x) > (y)) ? (y) : (x)) + if ((flags & NI_NOFQDN) + && (getdomainname(domain, sizeof(domain)) == 0) + && (c = strstr(hoste->h_name, domain)) != NULL + && (c != hoste->h_name) && (*(--c) == '.') + ) { + strncpy(host, hoste->h_name, + min(hostlen, (size_t) (c - hoste->h_name))); + host[min(hostlen - 1, (size_t) (c - hoste->h_name))] = '\0'; + } else { + strncpy(host, hoste->h_name, hostlen); + } + ok = 1; +#undef min + } + } + + if (!ok) { + const char *c = NULL; + + if (flags & NI_NAMEREQD) { + errno = serrno; + return EAI_NONAME; + } + if (0) /* nothing */; +#ifdef __UCLIBC_HAS_IPV6__ + else if (sa->sa_family == AF_INET6) { + const struct sockaddr_in6 *sin6p; + + sin6p = (const struct sockaddr_in6 *) sa; + c = inet_ntop(AF_INET6, + (const void *) &sin6p->sin6_addr, + host, hostlen); +#if 0 + /* Does scope id need to be supported? */ + uint32_t scopeid; + scopeid = sin6p->sin6_scope_id; + if (scopeid != 0) { + /* Buffer is >= IFNAMSIZ+1. */ + char scopebuf[IFNAMSIZ + 1]; + char *scopeptr; + int ni_numericscope = 0; + size_t real_hostlen = strnlen(host, hostlen); + size_t scopelen = 0; + + scopebuf[0] = SCOPE_DELIMITER; + scopebuf[1] = '\0'; + scopeptr = &scopebuf[1]; + + if (IN6_IS_ADDR_LINKLOCAL(&sin6p->sin6_addr) + || IN6_IS_ADDR_MC_LINKLOCAL(&sin6p->sin6_addr)) { + if (if_indextoname(scopeid, scopeptr) == NULL) + ++ni_numericscope; + else + scopelen = strlen(scopebuf); + } else { + ++ni_numericscope; + } + + if (ni_numericscope) + scopelen = 1 + snprintf(scopeptr, + (scopebuf + + sizeof scopebuf + - scopeptr), + "%u", scopeid); + + if (real_hostlen + scopelen + 1 > hostlen) + return EAI_SYSTEM; + memcpy(host + real_hostlen, scopebuf, scopelen + 1); + } +#endif + } +#endif /* __UCLIBC_HAS_IPV6__ */ +#if defined __UCLIBC_HAS_IPV4__ + else { + c = inet_ntop(AF_INET, (const void *) + &(((const struct sockaddr_in *) sa)->sin_addr), + host, hostlen); + } +#endif + if (c == NULL) { + errno = serrno; + return EAI_SYSTEM; + } + ok = 1; + } + break; + + case AF_LOCAL: + if (!(flags & NI_NUMERICHOST)) { + struct utsname utsname; + + if (!uname(&utsname)) { + strncpy(host, utsname.nodename, hostlen); + break; + }; + }; + + if (flags & NI_NAMEREQD) { + errno = serrno; + return EAI_NONAME; + } + + strncpy(host, "localhost", hostlen); + break; +/* Already checked above + default: + return EAI_FAMILY; +*/ + } + + if (serv && (servlen > 0)) { + if (sa->sa_family == AF_LOCAL) { + strncpy(serv, ((const struct sockaddr_un *) sa)->sun_path, servlen); + } else { /* AF_INET || AF_INET6 */ + if (!(flags & NI_NUMERICSERV)) { + struct servent *s; + s = getservbyport(((const struct sockaddr_in *) sa)->sin_port, + ((flags & NI_DGRAM) ? "udp" : "tcp")); + if (s) { + strncpy(serv, s->s_name, servlen); + goto DONE; + } + } + snprintf(serv, servlen, "%d", + ntohs(((const struct sockaddr_in *) sa)->sin_port)); + } + } +DONE: + if (host && (hostlen > 0)) + host[hostlen-1] = 0; + if (serv && (servlen > 0)) + serv[servlen-1] = 0; + errno = serrno; + return 0; +} +libc_hidden_def(getnameinfo) +#endif + + +#ifdef L_gethostbyname_r + +/* Bug 671 says: + * "uClibc resolver's gethostbyname does not return the requested name + * as an alias, but instead returns the canonical name. glibc's + * gethostbyname has a similar bug where it returns the requested name + * with the search domain name appended (to make a FQDN) as an alias, + * but not the original name itself. Both contradict POSIX, which says + * that the name argument passed to gethostbyname must be in the alias list" + * This is fixed now, and we differ from glibc: + * + * $ ./gethostbyname_uclibc wer.google.com + * h_name:'c13-ss-2-lb.cnet.com' + * h_length:4 + * h_addrtype:2 AF_INET + * alias:'wer.google.com' <=== + * addr: 0x4174efd8 '216.239.116.65' + * + * $ ./gethostbyname_glibc wer.google.com + * h_name:'c13-ss-2-lb.cnet.com' + * h_length:4 + * h_addrtype:2 AF_INET + * alias:'wer.google.com.com' <=== + * addr:'216.239.116.65' + * + * When examples were run, /etc/resolv.conf contained "search com" line. + */ +int gethostbyname_r(const char *name, + struct hostent *result_buf, + char *buf, + size_t buflen, + struct hostent **result, + int *h_errnop) +{ + struct in_addr **addr_list; + char **alias; + char *alias0; + unsigned char *packet; + struct resolv_answer a; + int i; + int packet_len; + int wrong_af = 0; + + *result = NULL; + if (!name) + return EINVAL; + + /* do /etc/hosts first */ + { + int old_errno = errno; /* save the old errno and reset errno */ + __set_errno(0); /* to check for missing /etc/hosts. */ + i = __get_hosts_byname_r(name, AF_INET, result_buf, + buf, buflen, result, h_errnop); + if (i == NETDB_SUCCESS) { + __set_errno(old_errno); + return i; + } + switch (*h_errnop) { + case HOST_NOT_FOUND: + wrong_af = (i == TRY_AGAIN); + case NO_ADDRESS: + break; + case NETDB_INTERNAL: + if (errno == ENOENT) { + break; + } + /* else fall through */ + default: + return i; + } + __set_errno(old_errno); + } + + DPRINTF("Nothing found in /etc/hosts\n"); + + *h_errnop = NETDB_INTERNAL; + + /* prepare future h_aliases[0] */ + i = strlen(name) + 1; + if ((ssize_t)buflen <= i) + return ERANGE; + memcpy(buf, name, i); /* paranoia: name might change */ + alias0 = buf; + buf += i; + buflen -= i; + /* make sure pointer is aligned */ + i = ALIGN_BUFFER_OFFSET(buf); + buf += i; + buflen -= i; + /* Layout in buf: + * char *alias[2]; + * struct in_addr* addr_list[NN+1]; + * struct in_addr* in[NN]; + */ + alias = (char **)buf; + buf += sizeof(alias[0]) * 2; + buflen -= sizeof(alias[0]) * 2; + addr_list = (struct in_addr **)buf; + /* buflen may be < 0, must do signed compare */ + if ((ssize_t)buflen < 256) + return ERANGE; + + /* we store only one "alias" - the name itself */ +#ifdef __UCLIBC_MJN3_ONLY__ +#warning TODO -- generate the full list +#endif + alias[0] = alias0; + alias[1] = NULL; + + /* maybe it is already an address? */ + { + struct in_addr *in = (struct in_addr *)(buf + sizeof(addr_list[0]) * 2); + if (inet_aton(name, in)) { + addr_list[0] = in; + addr_list[1] = NULL; + result_buf->h_name = alias0; + result_buf->h_aliases = alias; + result_buf->h_addrtype = AF_INET; + result_buf->h_length = sizeof(struct in_addr); + result_buf->h_addr_list = (char **) addr_list; + *result = result_buf; + *h_errnop = NETDB_SUCCESS; + return NETDB_SUCCESS; + } + } + + /* what if /etc/hosts has it but it's not IPv4? + * F.e. "::1 localhost6". We don't do DNS query for such hosts - + * "ping localhost6" should be fast even if DNS server is down! */ + if (wrong_af) { + *h_errnop = HOST_NOT_FOUND; + return TRY_AGAIN; + } + + /* talk to DNS servers */ + a.buf = buf; + /* take into account that at least one address will be there, + * we'll need space of one in_addr + two addr_list[] elems */ + a.buflen = buflen - ((sizeof(addr_list[0]) * 2 + sizeof(struct in_addr))); + a.add_count = 0; + packet_len = __dns_lookup(name, T_A, &packet, &a); + if (packet_len < 0) { + *h_errnop = HOST_NOT_FOUND; + DPRINTF("__dns_lookup returned < 0\n"); + return TRY_AGAIN; + } + + if (a.atype == T_A) { /* ADDRESS */ + /* we need space for addr_list[] and one IPv4 address */ + /* + 1 accounting for 1st addr (it's in a.rdata), + * another + 1 for NULL in last addr_list[]: */ + int need_bytes = sizeof(addr_list[0]) * (a.add_count + 1 + 1) + /* for 1st addr (it's in a.rdata): */ + + sizeof(struct in_addr); + /* how many bytes will 2nd and following addresses take? */ + int ips_len = a.add_count * a.rdlength; + + buflen -= (need_bytes + ips_len); + if ((ssize_t)buflen < 0) { + DPRINTF("buffer too small for all addresses\n"); + /* *h_errnop = NETDB_INTERNAL; - already is */ + i = ERANGE; + goto free_and_ret; + } + + /* if there are additional addresses in buf, + * move them forward so that they are not destroyed */ + DPRINTF("a.add_count:%d a.rdlength:%d a.rdata:%p\n", a.add_count, a.rdlength, a.rdata); + memmove(buf + need_bytes, buf, ips_len); + + /* 1st address is in a.rdata, insert it */ + buf += need_bytes - sizeof(struct in_addr); + memcpy(buf, a.rdata, sizeof(struct in_addr)); + + /* fill addr_list[] */ + for (i = 0; i <= a.add_count; i++) { + addr_list[i] = (struct in_addr*)buf; + buf += sizeof(struct in_addr); + } + addr_list[i] = NULL; + + /* if we have enough space, we can report "better" name + * (it may contain search domains attached by __dns_lookup, + * or CNAME of the host if it is different from the name + * we used to find it) */ + if (a.dotted && buflen > strlen(a.dotted)) { + strcpy(buf, a.dotted); + alias0 = buf; + } + + result_buf->h_name = alias0; + result_buf->h_aliases = alias; + result_buf->h_addrtype = AF_INET; + result_buf->h_length = sizeof(struct in_addr); + result_buf->h_addr_list = (char **) addr_list; + *result = result_buf; + *h_errnop = NETDB_SUCCESS; + i = NETDB_SUCCESS; + goto free_and_ret; + } + + *h_errnop = HOST_NOT_FOUND; + i = TRY_AGAIN; + + free_and_ret: + free(a.dotted); + free(packet); + return i; +} +libc_hidden_def(gethostbyname_r) +link_warning(gethostbyname_r, "gethostbyname_r is obsolescent, use getnameinfo() instead."); +#endif + + +#ifdef L_gethostbyname2_r + +int gethostbyname2_r(const char *name, + int family, + struct hostent *result_buf, + char *buf, + size_t buflen, + struct hostent **result, + int *h_errnop) +{ +#ifndef __UCLIBC_HAS_IPV6__ + return family == (AF_INET) + ? gethostbyname_r(name, result_buf, buf, buflen, result, h_errnop) + : HOST_NOT_FOUND; +#else + struct in6_addr *in; + struct in6_addr **addr_list; + unsigned char *packet; + struct resolv_answer a; + int i; + int nest = 0; + int wrong_af = 0; + + if (family == AF_INET) + return gethostbyname_r(name, result_buf, buf, buflen, result, h_errnop); + + *result = NULL; + if (family != AF_INET6) + return EINVAL; + + if (!name) + return EINVAL; + + /* do /etc/hosts first */ + { + int old_errno = errno; /* Save the old errno and reset errno */ + __set_errno(0); /* to check for missing /etc/hosts. */ + + i = __get_hosts_byname_r(name, AF_INET6 /*family*/, result_buf, + buf, buflen, result, h_errnop); + if (i == NETDB_SUCCESS) { + __set_errno(old_errno); + return i; + } + switch (*h_errnop) { + case HOST_NOT_FOUND: + wrong_af = (i == TRY_AGAIN); + case NO_ADDRESS: + break; + case NETDB_INTERNAL: + if (errno == ENOENT) { + break; + } + /* else fall through */ + default: + return i; + } + __set_errno(old_errno); + } + DPRINTF("Nothing found in /etc/hosts\n"); + + *h_errnop = NETDB_INTERNAL; + + /* make sure pointer is aligned */ + i = ALIGN_BUFFER_OFFSET(buf); + buf += i; + buflen -= i; + /* Layout in buf: + * struct in6_addr* in; + * struct in6_addr* addr_list[2]; + * char scratch_buf[256]; + */ + in = (struct in6_addr*)buf; + buf += sizeof(*in); + buflen -= sizeof(*in); + addr_list = (struct in6_addr**)buf; + buf += sizeof(*addr_list) * 2; + buflen -= sizeof(*addr_list) * 2; + if ((ssize_t)buflen < 256) + return ERANGE; + addr_list[0] = in; + addr_list[1] = NULL; + strncpy(buf, name, buflen); + buf[buflen] = '\0'; + + /* maybe it is already an address? */ + if (inet_pton(AF_INET6, name, in)) { + result_buf->h_name = buf; + result_buf->h_addrtype = AF_INET6; + result_buf->h_length = sizeof(*in); + result_buf->h_addr_list = (char **) addr_list; + /* result_buf->h_aliases = ??? */ + *result = result_buf; + *h_errnop = NETDB_SUCCESS; + return NETDB_SUCCESS; + } + + /* what if /etc/hosts has it but it's not IPv6? + * F.e. "127.0.0.1 localhost". We don't do DNS query for such hosts - + * "ping localhost" should be fast even if DNS server is down! */ + if (wrong_af) { + *h_errnop = HOST_NOT_FOUND; + return TRY_AGAIN; + } + + /* talk to DNS servers */ +/* TODO: why it's so different from gethostbyname_r (IPv4 case)? */ + memset(&a, '\0', sizeof(a)); + for (;;) { + int packet_len; + +/* Hmm why we memset(a) to zeros only once? */ + packet_len = __dns_lookup(buf, T_AAAA, &packet, &a); + if (packet_len < 0) { + *h_errnop = HOST_NOT_FOUND; + return TRY_AGAIN; + } + strncpy(buf, a.dotted, buflen); + free(a.dotted); + + if (a.atype != T_CNAME) + break; + + DPRINTF("Got a CNAME in gethostbyname()\n"); + if (++nest > MAX_RECURSE) { + *h_errnop = NO_RECOVERY; + return -1; + } + i = __decode_dotted(packet, a.rdoffset, packet_len, buf, buflen); + free(packet); + if (i < 0) { + *h_errnop = NO_RECOVERY; + return -1; + } + } + if (a.atype == T_AAAA) { /* ADDRESS */ + memcpy(in, a.rdata, sizeof(*in)); + result_buf->h_name = buf; + result_buf->h_addrtype = AF_INET6; + result_buf->h_length = sizeof(*in); + result_buf->h_addr_list = (char **) addr_list; + /* result_buf->h_aliases = ??? */ + free(packet); + *result = result_buf; + *h_errnop = NETDB_SUCCESS; + return NETDB_SUCCESS; + } + free(packet); + *h_errnop = HOST_NOT_FOUND; + return TRY_AGAIN; + +#endif /* __UCLIBC_HAS_IPV6__ */ +} +libc_hidden_def(gethostbyname2_r) +#endif + + +#ifdef L_gethostbyaddr_r + +int gethostbyaddr_r(const void *addr, socklen_t addrlen, + int type, + struct hostent *result_buf, + char *buf, size_t buflen, + struct hostent **result, + int *h_errnop) + +{ + struct in_addr *in; + struct in_addr **addr_list; + char **alias; + unsigned char *packet; + struct resolv_answer a; + int i; + int packet_len; + int nest = 0; + + *result = NULL; + if (!addr) + return EINVAL; + + switch (type) { +#ifdef __UCLIBC_HAS_IPV4__ + case AF_INET: + if (addrlen != sizeof(struct in_addr)) + return EINVAL; + break; +#endif +#ifdef __UCLIBC_HAS_IPV6__ + case AF_INET6: + if (addrlen != sizeof(struct in6_addr)) + return EINVAL; + break; +#endif + default: + return EINVAL; + } + + /* do /etc/hosts first */ + i = __get_hosts_byaddr_r(addr, addrlen, type, result_buf, + buf, buflen, result, h_errnop); + if (i == 0) + return i; + switch (*h_errnop) { + case HOST_NOT_FOUND: + case NO_ADDRESS: + break; + default: + return i; + } + + *h_errnop = NETDB_INTERNAL; + + /* make sure pointer is aligned */ + i = ALIGN_BUFFER_OFFSET(buf); + buf += i; + buflen -= i; + /* Layout in buf: + * char *alias[ALIAS_DIM]; + * struct in[6]_addr* addr_list[2]; + * struct in[6]_addr in; + * char scratch_buffer[256+]; + */ +#define in6 ((struct in6_addr *)in) + alias = (char **)buf; + addr_list = (struct in_addr**)buf; + buf += sizeof(*addr_list) * 2; + buflen -= sizeof(*addr_list) * 2; + in = (struct in_addr*)buf; +#ifndef __UCLIBC_HAS_IPV6__ + buf += sizeof(*in); + buflen -= sizeof(*in); + if (addrlen > sizeof(*in)) + return ERANGE; +#else + buf += sizeof(*in6); + buflen -= sizeof(*in6); + if (addrlen > sizeof(*in6)) + return ERANGE; +#endif + if ((ssize_t)buflen < 256) + return ERANGE; + alias[0] = buf; + alias[1] = NULL; + addr_list[0] = in; + addr_list[1] = NULL; + memcpy(in, addr, addrlen); + + if (0) /* nothing */; +#ifdef __UCLIBC_HAS_IPV4__ + else IF_HAS_BOTH(if (type == AF_INET)) { + unsigned char *tp = (unsigned char *)addr; + sprintf(buf, "%u.%u.%u.%u.in-addr.arpa", + tp[3], tp[2], tp[1], tp[0]); + } +#endif +#ifdef __UCLIBC_HAS_IPV6__ + else { + char *dst = buf; + unsigned char *tp = (unsigned char *)addr + addrlen - 1; + do { + dst += sprintf(dst, "%x.%x.", tp[0] & 0xf, tp[0] >> 4); + tp--; + } while (tp >= (unsigned char *)addr); + strcpy(dst, "ip6.arpa"); + } +#endif + + memset(&a, '\0', sizeof(a)); + for (;;) { +/* Hmm why we memset(a) to zeros only once? */ + packet_len = __dns_lookup(buf, T_PTR, &packet, &a); + if (packet_len < 0) { + *h_errnop = HOST_NOT_FOUND; + return TRY_AGAIN; + } + + strncpy(buf, a.dotted, buflen); + free(a.dotted); + if (a.atype != T_CNAME) + break; + + DPRINTF("Got a CNAME in gethostbyaddr()\n"); + if (++nest > MAX_RECURSE) { + *h_errnop = NO_RECOVERY; + return -1; + } + /* Decode CNAME into buf, feed it to __dns_lookup() again */ + i = __decode_dotted(packet, a.rdoffset, packet_len, buf, buflen); + free(packet); + if (i < 0) { + *h_errnop = NO_RECOVERY; + return -1; + } + } + + if (a.atype == T_PTR) { /* ADDRESS */ + i = __decode_dotted(packet, a.rdoffset, packet_len, buf, buflen); + free(packet); + result_buf->h_name = buf; + result_buf->h_addrtype = type; + result_buf->h_length = addrlen; + result_buf->h_addr_list = (char **) addr_list; + result_buf->h_aliases = alias; + *result = result_buf; + *h_errnop = NETDB_SUCCESS; + return NETDB_SUCCESS; + } + + free(packet); + *h_errnop = NO_ADDRESS; + return TRY_AGAIN; +#undef in6 +} +libc_hidden_def(gethostbyaddr_r) +link_warning(gethostbyaddr_r, "gethostbyaddr_r is obsolescent, use getaddrinfo() instead."); +#endif + + +#ifdef L_gethostent_r + +__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_MUTEX_INITIALIZER); + +static parser_t *hostp = NULL; +static smallint host_stayopen; + +void endhostent_unlocked(void) +{ + if (hostp) { + config_close(hostp); + hostp = NULL; + } + host_stayopen = 0; +} +void endhostent(void) +{ + __UCLIBC_MUTEX_LOCK(mylock); + endhostent_unlocked(); + __UCLIBC_MUTEX_UNLOCK(mylock); +} + +void sethostent(int stay_open) +{ + __UCLIBC_MUTEX_LOCK(mylock); + if (stay_open) + host_stayopen = 1; + __UCLIBC_MUTEX_UNLOCK(mylock); +} + +int gethostent_r(struct hostent *result_buf, char *buf, size_t buflen, + struct hostent **result, int *h_errnop) +{ + int ret; + + __UCLIBC_MUTEX_LOCK(mylock); + if (hostp == NULL) { + hostp = __open_etc_hosts(); + if (hostp == NULL) { + *result = NULL; + ret = TRY_AGAIN; + goto DONE; + } + } + + ret = __read_etc_hosts_r(hostp, NULL, AF_INET, GETHOSTENT, + result_buf, buf, buflen, result, h_errnop); + if (!host_stayopen) + endhostent_unlocked(); +DONE: + __UCLIBC_MUTEX_UNLOCK(mylock); + return ret; +} +libc_hidden_def(gethostent_r) +#endif + + +#ifdef L_gethostent + +struct hostent *gethostent(void) +{ + static struct hostent hoste; + static char buf[ +#ifndef __UCLIBC_HAS_IPV6__ + sizeof(struct in_addr) + sizeof(struct in_addr *) * 2 + +#else + sizeof(struct in6_addr) + sizeof(struct in6_addr *) * 2 + +#endif /* __UCLIBC_HAS_IPV6__ */ + BUFSZ /*namebuffer*/ + 2 /* margin */]; + struct hostent *host; + + gethostent_r(&hoste, buf, sizeof(buf), &host, &h_errno); + return host; +} +#endif + + +#ifdef L_gethostbyname2 + +struct hostent *gethostbyname2(const char *name, int family) +{ +#ifndef __UCLIBC_HAS_IPV6__ + return family == AF_INET ? gethostbyname(name) : (struct hostent*)NULL; +#else + static struct hostent hoste; + static char buf[sizeof(struct in6_addr) + + sizeof(struct in6_addr *) * 2 + + /*sizeof(char *)*ALIAS_DIM +*/ 384/*namebuffer*/ + 32/* margin */]; + struct hostent *hp; + + gethostbyname2_r(name, family, &hoste, buf, sizeof(buf), &hp, &h_errno); + return hp; +#endif +} +libc_hidden_def(gethostbyname2) +#endif + + +#ifdef L_gethostbyname + +struct hostent *gethostbyname(const char *name) +{ +#ifndef __UCLIBC_HAS_IPV6__ + static struct hostent hoste; + static char buf[sizeof(struct in_addr) + + sizeof(struct in_addr *) * 2 + + /*sizeof(char *)*ALIAS_DIM +*/ 384/*namebuffer*/ + 32/* margin */]; + struct hostent *hp; + + gethostbyname_r(name, &hoste, buf, sizeof(buf), &hp, &h_errno); + return hp; +#else + return gethostbyname2(name, AF_INET); +#endif +} +libc_hidden_def(gethostbyname) +link_warning(gethostbyname, "gethostbyname is obsolescent, use getnameinfo() instead."); +#endif + + +#ifdef L_gethostbyaddr + +struct hostent *gethostbyaddr(const void *addr, socklen_t len, int type) +{ + static struct hostent hoste; + static char buf[ +#ifndef __UCLIBC_HAS_IPV6__ + sizeof(struct in_addr) + sizeof(struct in_addr *)*2 + +#else + sizeof(struct in6_addr) + sizeof(struct in6_addr *)*2 + +#endif /* __UCLIBC_HAS_IPV6__ */ + /*sizeof(char *)*ALIAS_DIM +*/ 384 /*namebuffer*/ + 32 /* margin */]; + struct hostent *hp; + + gethostbyaddr_r(addr, len, type, &hoste, buf, sizeof(buf), &hp, &h_errno); + return hp; +} +libc_hidden_def(gethostbyaddr) +link_warning(gethostbyaddr, "gethostbyaddr is obsolescent, use getaddrinfo() instead."); +#endif + + +#ifdef L_res_comp + +/* + * Expand compressed domain name 'comp_dn' to full domain name. + * 'msg' is a pointer to the begining of the message, + * 'eomorig' points to the first location after the message, + * 'exp_dn' is a pointer to a buffer of size 'length' for the result. + * Return size of compressed name or -1 if there was an error. + */ +int dn_expand(const u_char *msg, const u_char *eom, const u_char *src, + char *dst, int dstsiz) +{ + int n = ns_name_uncompress(msg, eom, src, dst, (size_t)dstsiz); + + if (n > 0 && dst[0] == '.') + dst[0] = '\0'; + return n; +} +#endif /* L_res_comp */ + + +#ifdef L_ns_name + +/* Thinking in noninternationalized USASCII (per the DNS spec), + * is this character visible and not a space when printed ? + */ +static int printable(int ch) +{ + return (ch > 0x20 && ch < 0x7f); +} +/* Thinking in noninternationalized USASCII (per the DNS spec), + * is this characted special ("in need of quoting") ? + */ +static int special(int ch) +{ + switch (ch) { + case 0x22: /* '"' */ + case 0x2E: /* '.' */ + case 0x3B: /* ';' */ + case 0x5C: /* '\\' */ + /* Special modifiers in zone files. */ + case 0x40: /* '@' */ + case 0x24: /* '$' */ + return 1; + default: + return 0; + } +} + +/* + * ns_name_uncompress(msg, eom, src, dst, dstsiz) + * Expand compressed domain name to presentation format. + * return: + * Number of bytes read out of `src', or -1 (with errno set). + * note: + * Root domain returns as "." not "". + */ +int ns_name_uncompress(const u_char *msg, const u_char *eom, + const u_char *src, char *dst, size_t dstsiz) +{ + u_char tmp[NS_MAXCDNAME]; + int n; + + n = ns_name_unpack(msg, eom, src, tmp, sizeof tmp); + if (n == -1) + return -1; + if (ns_name_ntop(tmp, dst, dstsiz) == -1) + return -1; + return n; +} +libc_hidden_def(ns_name_uncompress) + +/* + * ns_name_ntop(src, dst, dstsiz) + * Convert an encoded domain name to printable ascii as per RFC1035. + * return: + * Number of bytes written to buffer, or -1 (with errno set) + * notes: + * The root is returned as "." + * All other domains are returned in non absolute form + */ +int ns_name_ntop(const u_char *src, char *dst, size_t dstsiz) +{ + static const char digits[] = "0123456789"; + + const u_char *cp; + char *dn, *eom; + u_char c; + u_int n; + + cp = src; + dn = dst; + eom = dst + dstsiz; + + while ((n = *cp++) != 0) { + if ((n & NS_CMPRSFLGS) != 0) { + /* Some kind of compression pointer. */ + __set_errno(EMSGSIZE); + return -1; + } + if (dn != dst) { + if (dn >= eom) { + __set_errno(EMSGSIZE); + return -1; + } + *dn++ = '.'; + } + if (dn + n >= eom) { + __set_errno(EMSGSIZE); + return -1; + } + for (; n > 0; n--) { + c = *cp++; + if (special(c)) { + if (dn + 1 >= eom) { + __set_errno(EMSGSIZE); + return -1; + } + *dn++ = '\\'; + *dn++ = (char)c; + } else if (!printable(c)) { + if (dn + 3 >= eom) { + __set_errno(EMSGSIZE); + return -1; + } + *dn++ = '\\'; + *dn++ = digits[c / 100]; + *dn++ = digits[(c % 100) / 10]; + *dn++ = digits[c % 10]; + } else { + if (dn >= eom) { + __set_errno(EMSGSIZE); + return -1; + } + *dn++ = (char)c; + } + } + } + if (dn == dst) { + if (dn >= eom) { + __set_errno(EMSGSIZE); + return -1; + } + *dn++ = '.'; + } + if (dn >= eom) { + __set_errno(EMSGSIZE); + return -1; + } + *dn++ = '\0'; + return (dn - dst); +} +libc_hidden_def(ns_name_ntop) + +/* + * ns_name_unpack(msg, eom, src, dst, dstsiz) + * Unpack a domain name from a message, source may be compressed. + * return: + * -1 if it fails, or consumed octets if it succeeds. + */ +int ns_name_unpack(const u_char *msg, const u_char *eom, const u_char *src, + u_char *dst, size_t dstsiz) +{ + const u_char *srcp, *dstlim; + u_char *dstp; + int n, len, checked; + + len = -1; + checked = 0; + dstp = dst; + srcp = src; + dstlim = dst + dstsiz; + if (srcp < msg || srcp >= eom) { + __set_errno(EMSGSIZE); + return -1; + } + /* Fetch next label in domain name. */ + while ((n = *srcp++) != 0) { + /* Check for indirection. */ + switch (n & NS_CMPRSFLGS) { + case 0: + /* Limit checks. */ + if (dstp + n + 1 >= dstlim || srcp + n >= eom) { + __set_errno(EMSGSIZE); + return -1; + } + checked += n + 1; + *dstp++ = n; + memcpy(dstp, srcp, n); + dstp += n; + srcp += n; + break; + + case NS_CMPRSFLGS: + if (srcp >= eom) { + __set_errno(EMSGSIZE); + return -1; + } + if (len < 0) + len = srcp - src + 1; + srcp = msg + (((n & 0x3f) << 8) | (*srcp & 0xff)); + if (srcp < msg || srcp >= eom) { /* Out of range. */ + __set_errno(EMSGSIZE); + return -1; + } + checked += 2; + /* + * Check for loops in the compressed name; + * if we've looked at the whole message, + * there must be a loop. + */ + if (checked >= eom - msg) { + __set_errno(EMSGSIZE); + return -1; + } + break; + + default: + __set_errno(EMSGSIZE); + return -1; /* flag error */ + } + } + *dstp = '\0'; + if (len < 0) + len = srcp - src; + return len; +} +libc_hidden_def(ns_name_unpack) +#endif /* L_ns_name */ + + +#ifdef L_res_init + +/* Will be called under __resolv_lock. */ +static void res_sync_func(void) +{ + struct __res_state *rp = &(_res); + int n; + + /* If we didn't get malloc failure earlier... */ + if (__nameserver != (void*) &__local_nameserver) { + /* TODO: + * if (__nameservers < rp->nscount) - try to grow __nameserver[]? + */ +#ifdef __UCLIBC_HAS_IPV6__ + if (__nameservers > rp->_u._ext.nscount) + __nameservers = rp->_u._ext.nscount; + n = __nameservers; + while (--n >= 0) + __nameserver[n].sa6 = *rp->_u._ext.nsaddrs[n]; /* struct copy */ +#else /* IPv4 only */ + if (__nameservers > rp->nscount) + __nameservers = rp->nscount; + n = __nameservers; + while (--n >= 0) + __nameserver[n].sa4 = rp->nsaddr_list[n]; /* struct copy */ +#endif + } + __resolv_timeout = rp->retrans ? : RES_TIMEOUT; + __resolv_attempts = rp->retry ? : RES_DFLRETRY; + /* Extend and comment what program is known + * to use which _res.XXX member(s). + + __resolv_opts = rp->options; + ... + */ +} + +/* Our res_init never fails (always returns 0) */ +int res_init(void) +{ + struct __res_state *rp = &(_res); + int i; + int n; +#ifdef __UCLIBC_HAS_IPV6__ + int m = 0; +#endif + + __UCLIBC_MUTEX_LOCK(__resolv_lock); + __close_nameservers(); + __open_nameservers(); + + __res_sync = res_sync_func; + + memset(rp, 0, sizeof(*rp)); + rp->options = RES_INIT; + rp->retrans = RES_TIMEOUT; + rp->retry = RES_DFLRETRY; + rp->ndots = 1; +#ifdef __UCLIBC_HAS_COMPAT_RES_STATE__ + /* Was: "rp->id = random();" but: + * - random() pulls in largish static buffers + * - isn't actually random unless, say, srandom(time(NULL)) was called + * - is not used by uclibc anyway :) + */ + /* rp->id = 0; - memset did it */ +#endif +#ifdef __UCLIBC_HAS_EXTRA_COMPAT_RES_STATE__ + rp->_vcsock = -1; +#endif + + n = __searchdomains; + if (n > ARRAY_SIZE(rp->dnsrch)) + n = ARRAY_SIZE(rp->dnsrch); + for (i = 0; i < n; i++) + rp->dnsrch[i] = __searchdomain[i]; + + /* copy nameservers' addresses */ + i = 0; +#ifdef __UCLIBC_HAS_IPV4__ + n = 0; + while (n < ARRAY_SIZE(rp->nsaddr_list) && i < __nameservers) { + if (__nameserver[i].sa.sa_family == AF_INET) { + rp->nsaddr_list[n] = __nameserver[i].sa4; /* struct copy */ +#ifdef __UCLIBC_HAS_IPV6__ + if (m < ARRAY_SIZE(rp->_u._ext.nsaddrs)) { + rp->_u._ext.nsaddrs[m] = (void*) &rp->nsaddr_list[n]; + m++; + } +#endif + n++; + } +#ifdef __UCLIBC_HAS_IPV6__ + if (__nameserver[i].sa.sa_family == AF_INET6 + && m < ARRAY_SIZE(rp->_u._ext.nsaddrs) + ) { + struct sockaddr_in6 *sa6 = malloc(sizeof(sa6)); + if (sa6) { + *sa6 = __nameserver[i].sa6; /* struct copy */ + rp->_u._ext.nsaddrs[m] = sa6; + m++; + } + } +#endif + i++; + } + rp->nscount = n; +#ifdef __UCLIBC_HAS_IPV6__ + rp->_u._ext.nscount = m; +#endif + +#else /* IPv6 only */ + while (m < ARRAY_SIZE(rp->_u._ext.nsaddrs) && i < __nameservers) { + struct sockaddr_in6 *sa6 = malloc(sizeof(sa6)); + if (sa6) { + *sa6 = __nameserver[i].sa6; /* struct copy */ + rp->_u._ext.nsaddrs[m] = sa6; + m++; + } + i++; + } + rp->_u._ext.nscount = m; +#endif + + __UCLIBC_MUTEX_UNLOCK(__resolv_lock); + return 0; +} +libc_hidden_def(res_init) + +#ifdef __UCLIBC_HAS_BSD_RES_CLOSE__ +void res_close(void) +{ + __UCLIBC_MUTEX_LOCK(__resolv_lock); + __close_nameservers(); + __res_sync = NULL; +#ifdef __UCLIBC_HAS_IPV6__ + { + char *p1 = (char*) &(_res.nsaddr_list[0]); + int m = 0; + /* free nsaddrs[m] if they do not point to nsaddr_list[x] */ + while (m < ARRAY_SIZE(_res._u._ext.nsaddrs)) { + char *p2 = (char*)(_res._u._ext.nsaddrs[m]); + if (p2 < p1 || (p2 - p1) > sizeof(_res.nsaddr_list)) + free(p2); + } + } +#endif + memset(&_res, 0, sizeof(_res)); + __UCLIBC_MUTEX_UNLOCK(__resolv_lock); +} +#endif + +/* This needs to be after the use of _res in res_init, above. */ +#undef _res + +#ifndef __UCLIBC_HAS_THREADS__ +/* The resolver state for use by single-threaded programs. + This differs from plain `struct __res_state _res;' in that it doesn't + create a common definition, but a plain symbol that resides in .bss, + which can have an alias. */ +struct __res_state _res __attribute__((section (".bss"))); +struct __res_state *__resp = &_res; +#else /* __UCLIBC_HAS_THREADS__ */ +struct __res_state _res __attribute__((section (".bss"))) attribute_hidden; + +# if defined __UCLIBC_HAS_TLS__ +# undef __resp +__thread struct __res_state *__resp = &_res; +/* + * FIXME: Add usage of hidden attribute for this when used in the shared + * library. It currently crashes the linker when doing section + * relocations. + */ +extern __thread struct __res_state *__libc_resp + __attribute__ ((alias ("__resp"))) attribute_hidden; +# else +# undef __resp +struct __res_state *__resp = &_res; +# endif +#endif + +#endif /* L_res_init */ + +#ifdef L_res_state +# if defined __UCLIBC_HAS_TLS__ +struct __res_state * +__res_state (void) +{ + return __resp; +} +# else +# undef _res +extern struct __res_state _res; + +/* When threaded, _res may be a per-thread variable. */ +struct __res_state * +weak_const_function +__res_state (void) +{ + return &_res; +} +# endif + +#endif + + +#ifdef L_res_query + +int res_query(const char *dname, int class, int type, + unsigned char *answer, int anslen) +{ + int i; + unsigned char *packet = NULL; + struct resolv_answer a; + + if (!dname || class != 1 /* CLASS_IN */) { + h_errno = NO_RECOVERY; + return -1; + } + + memset(&a, '\0', sizeof(a)); + i = __dns_lookup(dname, type, &packet, &a); + + if (i < 0) { + if (!h_errno) /* TODO: can this ever happen? */ + h_errno = TRY_AGAIN; + return -1; + } + + free(a.dotted); + + if (a.atype == type) { /* CNAME */ + if (i > anslen) + i = anslen; + memcpy(answer, packet, i); + } + free(packet); + return i; +} +libc_hidden_def(res_query) + +/* + * Formulate a normal query, send, and retrieve answer in supplied buffer. + * Return the size of the response on success, -1 on error. + * If enabled, implement search rules until answer or unrecoverable failure + * is detected. Error code, if any, is left in h_errno. + */ +#define __TRAILING_DOT (1<<0) +#define __GOT_NODATA (1<<1) +#define __GOT_SERVFAIL (1<<2) +#define __TRIED_AS_IS (1<<3) +int res_search(const char *name, int class, int type, u_char *answer, + int anslen) +{ + const char *cp; + char **domain; + HEADER *hp = (HEADER *)(void *)answer; + unsigned dots; + unsigned state; + int ret, saved_herrno; + uint32_t _res_options; + unsigned _res_ndots; + char **_res_dnsrch; + + if (!name || !answer) { + h_errno = NETDB_INTERNAL; + return -1; + } + + again: + __UCLIBC_MUTEX_LOCK(__resolv_lock); + _res_options = _res.options; + _res_ndots = _res.ndots; + _res_dnsrch = _res.dnsrch; + __UCLIBC_MUTEX_UNLOCK(__resolv_lock); + if (!(_res_options & RES_INIT)) { + res_init(); /* our res_init never fails */ + goto again; + } + + state = 0; + errno = 0; + h_errno = HOST_NOT_FOUND; /* default, if we never query */ + dots = 0; + for (cp = name; *cp; cp++) + dots += (*cp == '.'); + + if (cp > name && *--cp == '.') + state |= __TRAILING_DOT; + + /* + * If there are dots in the name already, let's just give it a try + * 'as is'. The threshold can be set with the "ndots" option. + */ + saved_herrno = -1; + if (dots >= _res_ndots) { + ret = res_querydomain(name, NULL, class, type, answer, anslen); + if (ret > 0) + return ret; + saved_herrno = h_errno; + state |= __TRIED_AS_IS; + } + + /* + * We do at least one level of search if + * - there is no dot and RES_DEFNAME is set, or + * - there is at least one dot, there is no trailing dot, + * and RES_DNSRCH is set. + */ + if ((!dots && (_res_options & RES_DEFNAMES)) + || (dots && !(state & __TRAILING_DOT) && (_res_options & RES_DNSRCH)) + ) { + bool done = 0; + + for (domain = _res_dnsrch; *domain && !done; domain++) { + + ret = res_querydomain(name, *domain, class, type, + answer, anslen); + if (ret > 0) + return ret; + + /* + * If no server present, give up. + * If name isn't found in this domain, + * keep trying higher domains in the search list + * (if that's enabled). + * On a NO_DATA error, keep trying, otherwise + * a wildcard entry of another type could keep us + * from finding this entry higher in the domain. + * If we get some other error (negative answer or + * server failure), then stop searching up, + * but try the input name below in case it's + * fully-qualified. + */ + if (errno == ECONNREFUSED) { + h_errno = TRY_AGAIN; + return -1; + } + + switch (h_errno) { + case NO_DATA: + state |= __GOT_NODATA; + /* FALLTHROUGH */ + case HOST_NOT_FOUND: + /* keep trying */ + break; + case TRY_AGAIN: + if (hp->rcode == SERVFAIL) { + /* try next search element, if any */ + state |= __GOT_SERVFAIL; + break; + } + /* FALLTHROUGH */ + default: + /* anything else implies that we're done */ + done = 1; + } + /* + * if we got here for some reason other than DNSRCH, + * we only wanted one iteration of the loop, so stop. + */ + if (!(_res_options & RES_DNSRCH)) + done = 1; + } + } + + /* + * if we have not already tried the name "as is", do that now. + * note that we do this regardless of how many dots were in the + * name or whether it ends with a dot. + */ + if (!(state & __TRIED_AS_IS)) { + ret = res_querydomain(name, NULL, class, type, answer, anslen); + if (ret > 0) + return ret; + } + + /* + * if we got here, we didn't satisfy the search. + * if we did an initial full query, return that query's h_errno + * (note that we wouldn't be here if that query had succeeded). + * else if we ever got a nodata, send that back as the reason. + * else send back meaningless h_errno, that being the one from + * the last DNSRCH we did. + */ + if (saved_herrno != -1) + h_errno = saved_herrno; + else if (state & __GOT_NODATA) + h_errno = NO_DATA; + else if (state & __GOT_SERVFAIL) + h_errno = TRY_AGAIN; + return -1; +} +#undef __TRAILING_DOT +#undef __GOT_NODATA +#undef __GOT_SERVFAIL +#undef __TRIED_AS_IS +/* + * Perform a call on res_query on the concatenation of name and domain, + * removing a trailing dot from name if domain is NULL. + */ +int res_querydomain(const char *name, const char *domain, int class, int type, + u_char *answer, int anslen) +{ + char nbuf[MAXDNAME]; + const char *longname = nbuf; + size_t n, d; +#ifdef DEBUG + uint32_t _res_options; +#endif + + if (!name || !answer) { + h_errno = NETDB_INTERNAL; + return -1; + } + +#ifdef DEBUG + again: + __UCLIBC_MUTEX_LOCK(__resolv_lock); + _res_options = _res.options; + __UCLIBC_MUTEX_UNLOCK(__resolv_lock); + if (!(_res_options & RES_INIT)) { + res_init(); /* our res_init never fails */ + goto again; + } + if (_res_options & RES_DEBUG) + printf(";; res_querydomain(%s, %s, %d, %d)\n", + name, (domain ? domain : ""), class, type); +#endif + if (domain == NULL) { + /* + * Check for trailing '.'; + * copy without '.' if present. + */ + n = strlen(name); + if (n + 1 > sizeof(nbuf)) { + h_errno = NO_RECOVERY; + return -1; + } + if (n > 0 && name[--n] == '.') { + strncpy(nbuf, name, n); + nbuf[n] = '\0'; + } else + longname = name; + } else { + n = strlen(name); + d = strlen(domain); + if (n + 1 + d + 1 > sizeof(nbuf)) { + h_errno = NO_RECOVERY; + return -1; + } + snprintf(nbuf, sizeof(nbuf), "%s.%s", name, domain); + } + return res_query(longname, class, type, answer, anslen); +} +libc_hidden_def(res_querydomain) +#endif + +/* Unimplemented: */ +/* res_mkquery */ +/* res_send */ +/* dn_comp */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/.indent.pro b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/.indent.pro new file mode 100644 index 00000000..492ecf1c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/.indent.pro @@ -0,0 +1,33 @@ +--blank-lines-after-declarations +--blank-lines-after-procedures +--break-before-boolean-operator +--no-blank-lines-after-commas +--braces-on-if-line +--braces-on-struct-decl-line +--comment-indentation25 +--declaration-comment-column25 +--no-comment-delimiters-on-blank-lines +--cuddle-else +--continuation-indentation4 +--case-indentation0 +--else-endif-column33 +--space-after-cast +--line-comments-indentation0 +--declaration-indentation1 +--dont-format-first-column-comments +--dont-format-comments +--honour-newlines +--indent-level4 +/* changed from 0 to 4 */ +--parameter-indentation4 +--line-length78 /* changed from 75 */ +--continue-at-parentheses +--no-space-after-function-call-names +--dont-break-procedure-type +--dont-star-comments +--leave-optional-blank-lines +--dont-space-special-semicolon +--tab-size4 +/* additions by Mark */ +--case-brace-indentation0 +--leave-preprocessor-space diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/Makefile new file mode 100644 index 00000000..4a8f4a07 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../ +top_builddir=../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/Makefile.in new file mode 100644 index 00000000..6ec674d1 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/Makefile.in @@ -0,0 +1,47 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +subdirs += libc/inet/rpc + +CFLAGS-rpc := -fno-strict-aliasing + +ifneq ($(UCLIBC_HAS_FULL_RPC),y) +# For now, only compile the stuff needed to do an NFS mount.... +CSRC:= authunix_prot.c auth_none.c auth_unix.c bindresvport.c \ + clnt_perror.c clnt_simple.c clnt_tcp.c clnt_udp.c \ + create_xid.c getrpcent.c \ + pmap_clnt.c pm_getmaps.c pm_getport.c pmap_prot.c pmap_prot2.c \ + rcmd.c rexec.c rpc_cmsg.c rpc_commondata.c rpc_dtablesize.c \ + rpc_prot.c rpc_thread.c rtime.c ruserpass.c sa_len.c \ + svc.c svc_auth.c svc_authux.c \ + xdr.c xdr_array.c xdr_mem.c xdr_rec.c xdr_reference.c +endif + +INET_RPC_DIR:=$(top_srcdir)libc/inet/rpc +INET_RPC_OUT:=$(top_builddir)libc/inet/rpc + +ifeq ($(UCLIBC_HAS_FULL_RPC),y) +INET_RPC_SRC:=$(wildcard $(INET_RPC_DIR)/*.c) +else +INET_RPC_SRC:=$(patsubst %.c,$(INET_RPC_DIR)/%.c,$(CSRC)) +endif +# rpc_thread.oS is better, because the header adds unneeded references to __pthread_internal_tsd* +INET_RPC_SRC:=$(filter-out $(INET_RPC_DIR)/rpc_thread.c,$(INET_RPC_SRC)) + +INET_RPC_OBJ:=$(patsubst $(INET_RPC_DIR)/%.c,$(INET_RPC_OUT)/%.o,$(INET_RPC_SRC)) + +libc-static-$(UCLIBC_HAS_RPC)+=$(INET_RPC_OUT)/rpc_thread.o +libc-shared-$(UCLIBC_HAS_RPC)+=$(INET_RPC_OUT)/rpc_thread.oS + +libc-nomulti-$(UCLIBC_HAS_RPC) += $(INET_RPC_OUT)/rpc_thread.o + +libc-$(UCLIBC_HAS_RPC)+=$(INET_RPC_OBJ) + +objclean-y+=CLEAN_libc/inet/rpc + +CLEAN_libc/inet/rpc: + $(do_rm) $(addprefix $(INET_RPC_OUT)/*., o os oS) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/auth_none.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/auth_none.c new file mode 100644 index 00000000..c48bbfea --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/auth_none.c @@ -0,0 +1,137 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +/* + * Copyright (C) 1984, Sun Microsystems, Inc. + */ +/* + * auth_none.c + * Creates a client authentication handle for passing "null" + * credentials and verifiers to remote systems. + */ + +#define __FORCE_GLIBC +#include +#include "rpc_private.h" + + +#define MAX_MARSHAL_SIZE 20 + +/* + * Authenticator operations routines + */ +static void authnone_verf (AUTH *); +static void authnone_destroy (AUTH *); +static bool_t authnone_marshal (AUTH *, XDR *); +static bool_t authnone_validate (AUTH *, struct opaque_auth *); +static bool_t authnone_refresh (AUTH *); + +static const struct auth_ops ops = { + authnone_verf, + authnone_marshal, + authnone_validate, + authnone_refresh, + authnone_destroy +}; + +/* Internal data and routines */ + +struct authnone_private_s { + AUTH no_client; + char marshalled_client[MAX_MARSHAL_SIZE]; + u_int mcnt; +}; +#ifdef __UCLIBC_HAS_THREADS__ +#define authnone_private (*(struct authnone_private_s **)&RPC_THREAD_VARIABLE(authnone_private_s)) +#else +static struct authnone_private_s *authnone_private; +#endif + +AUTH * +authnone_create (void) +{ + struct authnone_private_s *ap; + XDR xdr_stream; + XDR *xdrs; + + ap = (struct authnone_private_s *) authnone_private; + if (ap == NULL) + { + ap = (struct authnone_private_s *) calloc (1, sizeof (*ap)); + if (ap == NULL) + return NULL; + authnone_private = ap; + } + if (!ap->mcnt) + { + ap->no_client.ah_cred = ap->no_client.ah_verf = _null_auth; + ap->no_client.ah_ops = (struct auth_ops *)&ops; + xdrs = &xdr_stream; + xdrmem_create (xdrs, ap->marshalled_client, (u_int) MAX_MARSHAL_SIZE, + XDR_ENCODE); + (void) xdr_opaque_auth (xdrs, &ap->no_client.ah_cred); + (void) xdr_opaque_auth (xdrs, &ap->no_client.ah_verf); + ap->mcnt = XDR_GETPOS (xdrs); + XDR_DESTROY (xdrs); + } + return (&ap->no_client); +} +libc_hidden_def(authnone_create) + +static bool_t +authnone_marshal (AUTH *client attribute_unused, XDR *xdrs) +{ + struct authnone_private_s *ap; + + ap = authnone_private; + if (ap == NULL) + return FALSE; + return (*xdrs->x_ops->x_putbytes) (xdrs, ap->marshalled_client, ap->mcnt); +} + +static void +authnone_verf (AUTH *auth attribute_unused) +{ +} + +static bool_t +authnone_validate (AUTH *auth attribute_unused, struct opaque_auth *oa attribute_unused) +{ + return TRUE; +} + +static bool_t +authnone_refresh (AUTH *auth attribute_unused) +{ + return FALSE; +} + +static void +authnone_destroy (AUTH *auth attribute_unused) +{ +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/auth_unix.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/auth_unix.c new file mode 100644 index 00000000..1337214e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/auth_unix.c @@ -0,0 +1,336 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +/* + * Copyright (C) 1984, Sun Microsystems, Inc. + */ +/* + * auth_unix.c, Implements UNIX style authentication parameters. + * + * The system is very weak. The client uses no encryption for it's + * credentials and only sends null verifiers. The server sends backs + * null verifiers or optionally a verifier that suggests a new short hand + * for the credentials. + */ + +#define __FORCE_GLIBC +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#ifdef USE_IN_LIBIO +# include +#endif + +/* + * Unix authenticator operations vector + */ +static void authunix_nextverf (AUTH *); +static bool_t authunix_marshal (AUTH *, XDR *); +static bool_t authunix_validate (AUTH *, struct opaque_auth *); +static bool_t authunix_refresh (AUTH *); +static void authunix_destroy (AUTH *); + +static struct auth_ops auth_unix_ops = { + authunix_nextverf, + authunix_marshal, + authunix_validate, + authunix_refresh, + authunix_destroy +}; + +/* + * This struct is pointed to by the ah_private field of an auth_handle. + */ +struct audata { + struct opaque_auth au_origcred; /* original credentials */ + struct opaque_auth au_shcred; /* short hand cred */ + u_long au_shfaults; /* short hand cache faults */ + char au_marshed[MAX_AUTH_BYTES]; + u_int au_mpos; /* xdr pos at end of marshed */ +}; +#define AUTH_PRIVATE(auth) ((struct audata *)auth->ah_private) + +static bool_t marshal_new_auth (AUTH *) internal_function; + + +/* + * Create a unix style authenticator. + * Returns an auth handle with the given stuff in it. + */ +AUTH * +authunix_create (char *machname, uid_t uid, gid_t gid, int len, + gid_t *aup_gids) +{ + struct authunix_parms aup; + char mymem[MAX_AUTH_BYTES]; + struct timeval now; + XDR xdrs; + AUTH *auth; + struct audata *au; + + /* + * Allocate and set up auth handle + */ + auth = (AUTH *) mem_alloc (sizeof (*auth)); + au = (struct audata *) mem_alloc (sizeof (*au)); + if (auth == NULL || au == NULL) + { +no_memory: +#ifdef USE_IN_LIBIO + if (_IO_fwide (stderr, 0) > 0) + (void) fwprintf (stderr, L"%s", + _("authunix_create: out of memory\n")); + else +#endif + (void) fputs (_("authunix_create: out of memory\n"), stderr); + mem_free (auth, sizeof (*auth)); + mem_free (au, sizeof (*au)); + return NULL; + } + auth->ah_ops = &auth_unix_ops; + auth->ah_private = (caddr_t) au; + auth->ah_verf = au->au_shcred = _null_auth; + au->au_shfaults = 0; + + /* + * fill in param struct from the given params + */ + (void) gettimeofday (&now, (struct timezone *) 0); + aup.aup_time = now.tv_sec; + aup.aup_machname = machname; + aup.aup_uid = uid; + aup.aup_gid = gid; + aup.aup_len = (u_int) len; + aup.aup_gids = aup_gids; + + /* + * Serialize the parameters into origcred + */ + xdrmem_create (&xdrs, mymem, MAX_AUTH_BYTES, XDR_ENCODE); + if (!xdr_authunix_parms (&xdrs, &aup)) + abort (); + au->au_origcred.oa_length = len = XDR_GETPOS (&xdrs); + au->au_origcred.oa_flavor = AUTH_UNIX; + au->au_origcred.oa_base = mem_alloc ((u_int) len); + if (au->au_origcred.oa_base == NULL) + goto no_memory; + memcpy(au->au_origcred.oa_base, mymem, (u_int) len); + + /* + * set auth handle to reflect new cred. + */ + auth->ah_cred = au->au_origcred; + marshal_new_auth (auth); + return auth; +} +libc_hidden_def(authunix_create) + +/* + * Returns an auth handle with parameters determined by doing lots of + * syscalls. + */ +AUTH * +authunix_create_default (void) +{ + int len; + char machname[MAX_MACHINE_NAME + 1]; + uid_t uid; + gid_t gid; + int max_nr_groups = sysconf (_SC_NGROUPS_MAX); + gid_t *gids = NULL; + AUTH *ret_auth; + + if (max_nr_groups) { + gids = (gid_t*)malloc(sizeof(*gids) * max_nr_groups); + if (gids == NULL) + abort (); + } + + if (gethostname (machname, MAX_MACHINE_NAME) == -1) + abort (); + machname[MAX_MACHINE_NAME] = 0; + uid = geteuid (); + gid = getegid (); + + if ((len = getgroups (max_nr_groups, gids)) < 0) + abort (); + /* This braindamaged Sun code forces us here to truncate the + list of groups to NGRPS members since the code in + authuxprot.c transforms a fixed array. Grrr. */ + ret_auth = authunix_create (machname, uid, gid, MIN (NGRPS, len), gids); + free (gids); + return ret_auth; +} +libc_hidden_def(authunix_create_default) + +/* + * authunix operations + */ + +static void +authunix_nextverf (AUTH *auth attribute_unused) +{ + /* no action necessary */ +} + +static bool_t +authunix_marshal (AUTH *auth, XDR *xdrs) +{ + struct audata *au = AUTH_PRIVATE (auth); + + return XDR_PUTBYTES (xdrs, au->au_marshed, au->au_mpos); +} + +static bool_t +authunix_validate (AUTH *auth, struct opaque_auth *verf) +{ + struct audata *au; + XDR xdrs; + + if (verf->oa_flavor == AUTH_SHORT) + { + au = AUTH_PRIVATE (auth); + xdrmem_create (&xdrs, verf->oa_base, verf->oa_length, + XDR_DECODE); + + if (au->au_shcred.oa_base != NULL) + { + mem_free (au->au_shcred.oa_base, + au->au_shcred.oa_length); + au->au_shcred.oa_base = NULL; + } + if (xdr_opaque_auth (&xdrs, &au->au_shcred)) + { + auth->ah_cred = au->au_shcred; + } + else + { + xdrs.x_op = XDR_FREE; + (void) xdr_opaque_auth (&xdrs, &au->au_shcred); + au->au_shcred.oa_base = NULL; + auth->ah_cred = au->au_origcred; + } + marshal_new_auth (auth); + } + return TRUE; +} + +static bool_t +authunix_refresh (AUTH *auth) +{ + struct audata *au = AUTH_PRIVATE (auth); + struct authunix_parms aup; + struct timeval now; + XDR xdrs; + int stat; + + if (auth->ah_cred.oa_base == au->au_origcred.oa_base) + { + /* there is no hope. Punt */ + return FALSE; + } + au->au_shfaults++; + + /* first deserialize the creds back into a struct authunix_parms */ + aup.aup_machname = NULL; + aup.aup_gids = (gid_t *) NULL; + xdrmem_create (&xdrs, au->au_origcred.oa_base, + au->au_origcred.oa_length, XDR_DECODE); + stat = xdr_authunix_parms (&xdrs, &aup); + if (!stat) + goto done; + + /* update the time and serialize in place */ + (void) gettimeofday (&now, (struct timezone *) 0); + aup.aup_time = now.tv_sec; + xdrs.x_op = XDR_ENCODE; + XDR_SETPOS (&xdrs, 0); + stat = xdr_authunix_parms (&xdrs, &aup); + if (!stat) + goto done; + auth->ah_cred = au->au_origcred; + marshal_new_auth (auth); +done: + /* free the struct authunix_parms created by deserializing */ + xdrs.x_op = XDR_FREE; + (void) xdr_authunix_parms (&xdrs, &aup); + XDR_DESTROY (&xdrs); + return stat; +} + +static void +authunix_destroy (AUTH *auth) +{ + struct audata *au = AUTH_PRIVATE (auth); + + mem_free (au->au_origcred.oa_base, au->au_origcred.oa_length); + + if (au->au_shcred.oa_base != NULL) + mem_free (au->au_shcred.oa_base, au->au_shcred.oa_length); + + mem_free (auth->ah_private, sizeof (struct audata)); + + if (auth->ah_verf.oa_base != NULL) + mem_free (auth->ah_verf.oa_base, auth->ah_verf.oa_length); + + mem_free ((caddr_t) auth, sizeof (*auth)); +} + +/* + * Marshals (pre-serializes) an auth struct. + * sets private data, au_marshed and au_mpos + */ +static bool_t +internal_function +marshal_new_auth (AUTH *auth) +{ + XDR xdr_stream; + XDR *xdrs = &xdr_stream; + struct audata *au = AUTH_PRIVATE (auth); + + xdrmem_create (xdrs, au->au_marshed, MAX_AUTH_BYTES, XDR_ENCODE); + if ((!xdr_opaque_auth (xdrs, &(auth->ah_cred))) || + (!xdr_opaque_auth (xdrs, &(auth->ah_verf)))) + perror (_("auth_none.c - Fatal marshalling problem")); + else + au->au_mpos = XDR_GETPOS (xdrs); + + XDR_DESTROY (xdrs); + + return TRUE; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/authunix_prot.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/authunix_prot.c new file mode 100644 index 00000000..27299005 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/authunix_prot.c @@ -0,0 +1,67 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +/* + * Copyright (C) 1984, Sun Microsystems, Inc. + */ +/* + * authunix_prot.c + * XDR for UNIX style authentication parameters for RPC + */ + +#include +#include +#include +#include + + +/* + * XDR for unix authentication parameters. + * Unfortunately, none of these can be declared const. + */ +bool_t +xdr_authunix_parms (XDR * xdrs, struct authunix_parms *p) +{ + if (xdr_u_long (xdrs, &(p->aup_time)) + && xdr_string (xdrs, &(p->aup_machname), MAX_MACHINE_NAME) + && (sizeof (uid_t) == sizeof (short int) + ? xdr_u_short (xdrs, (u_short *) & (p->aup_uid)) + : xdr_u_int (xdrs, (u_int *) & (p->aup_uid))) + && (sizeof (gid_t) == sizeof (short int) + ? xdr_u_short (xdrs, (u_short *) & (p->aup_gid)) + : xdr_u_int (xdrs, (u_int *) & (p->aup_gid))) + && xdr_array (xdrs, (caddr_t *) & (p->aup_gids), + & (p->aup_len), NGRPS, sizeof (gid_t), + (sizeof (gid_t) == sizeof (short int) + ? (xdrproc_t) xdr_u_short : (xdrproc_t) xdr_u_int))) + { + return TRUE; + } + return FALSE; +} +libc_hidden_def(xdr_authunix_parms) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/bindresvport.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/bindresvport.c new file mode 100644 index 00000000..fc077af6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/bindresvport.c @@ -0,0 +1,90 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +/* + * Copyright (c) 1987 by Sun Microsystems, Inc. + */ + +#define __FORCE_GLIBC +#include + +#include +#include +#include +#include +#include +#include + + +/* + * Bind a socket to a privileged IP port + */ +int +bindresvport (int sd, struct sockaddr_in *sin) +{ + int res; + static short port; + struct sockaddr_in myaddr; + int i; + +#define STARTPORT 600 +#define ENDPORT (IPPORT_RESERVED - 1) +#define NPORTS (ENDPORT - STARTPORT + 1) + + if (sin == (struct sockaddr_in *) 0) + { + sin = &myaddr; + memset (sin, 0, sizeof (*sin)); + sin->sin_family = AF_INET; + } + else if (sin->sin_family != AF_INET) + { + __set_errno (EPFNOSUPPORT); + return -1; + } + + if (port == 0) + { + port = (getpid () % NPORTS) + STARTPORT; + } + res = -1; + __set_errno (EADDRINUSE); + + for (i = 0; i < NPORTS && res < 0 && errno == EADDRINUSE; ++i) + { + sin->sin_port = htons (port); + if (++port > ENDPORT) + { + port = STARTPORT; + } + res = bind(sd, (struct sockaddr *)sin, sizeof(struct sockaddr_in)); + } + + return res; +} +libc_hidden_def(bindresvport) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/clnt_generic.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/clnt_generic.c new file mode 100644 index 00000000..8aeae1ec --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/clnt_generic.c @@ -0,0 +1,179 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +/* + * Copyright (C) 1987, Sun Microsystems, Inc. + */ + +#define __FORCE_GLIBC +#include + +#include +#include +#include +#include +#include +#include + + +/* + * Generic client creation: takes (hostname, program-number, protocol) and + * returns client handle. Default options are set, which the user can + * change using the rpc equivalent of ioctl()'s. + */ +CLIENT * +clnt_create (const char *hostname, u_long prog, u_long vers, + const char *proto) +{ + struct hostent hostbuf, *h; + size_t hstbuflen; + char *hsttmpbuf; + struct protoent protobuf, *p; + size_t prtbuflen; + char *prttmpbuf; + struct sockaddr_in sin; + struct sockaddr_un sun; + int sock; + struct timeval tv; + CLIENT *client; + int herr; + + if (strcmp (proto, "unix") == 0) + { + memset ((char *)&sun, 0, sizeof (sun)); + sun.sun_family = AF_UNIX; + strcpy (sun.sun_path, hostname); + sock = RPC_ANYSOCK; + client = clntunix_create (&sun, prog, vers, &sock, 0, 0); + if (client == NULL) + return NULL; +#if 0 + /* This is not wanted. This would disable the user from having + a timeout in the clnt_call() call. Only a call to cnlt_control() + by the user should set the timeout value. */ + tv.tv_sec = 25; + tv.tv_usec = 0; + clnt_control (client, CLSET_TIMEOUT, (char *)&tv); +#endif + return client; + } + + hstbuflen = 1024; + hsttmpbuf = alloca (hstbuflen); + while (gethostbyname_r (hostname, &hostbuf, hsttmpbuf, hstbuflen, + &h, &herr) != 0 + || h == NULL) + if (herr != NETDB_INTERNAL || errno != ERANGE) + { + get_rpc_createerr().cf_stat = RPC_UNKNOWNHOST; + return NULL; + } + else + { + /* Enlarge the buffer. */ + hstbuflen *= 2; + hsttmpbuf = alloca (hstbuflen); + } + + if (h->h_addrtype != AF_INET) + { + /* + * Only support INET for now + */ + struct rpc_createerr *ce = &get_rpc_createerr (); + ce->cf_stat = RPC_SYSTEMERROR; + ce->cf_error.re_errno = EAFNOSUPPORT; + return NULL; + } + sin.sin_family = h->h_addrtype; + sin.sin_port = 0; + memset (sin.sin_zero, 0, sizeof (sin.sin_zero)); + memcpy ((char *) &sin.sin_addr, h->h_addr, h->h_length); + + prtbuflen = 1024; + prttmpbuf = alloca (prtbuflen); + while (getprotobyname_r (proto, &protobuf, prttmpbuf, prtbuflen, &p) != 0 + || p == NULL) + if (errno != ERANGE) + { + struct rpc_createerr *ce = &get_rpc_createerr (); + ce->cf_stat = RPC_UNKNOWNPROTO; + ce->cf_error.re_errno = EPFNOSUPPORT; + return NULL; + } + else + { + /* Enlarge the buffer. */ + prtbuflen *= 2; + prttmpbuf = alloca (prtbuflen); + } + + sock = RPC_ANYSOCK; + switch (p->p_proto) + { + case IPPROTO_UDP: + tv.tv_sec = 5; + tv.tv_usec = 0; + client = clntudp_create (&sin, prog, vers, tv, &sock); + if (client == NULL) + { + return NULL; + } +#if 0 + /* This is not wanted. This would disable the user from having + a timeout in the clnt_call() call. Only a call to cnlt_control() + by the user should set the timeout value. */ + tv.tv_sec = 25; + clnt_control (client, CLSET_TIMEOUT, (char *)&tv); +#endif + break; + case IPPROTO_TCP: + client = clnttcp_create (&sin, prog, vers, &sock, 0, 0); + if (client == NULL) + { + return NULL; + } +#if 0 + /* This is not wanted. This would disable the user from having + a timeout in the clnt_call() call. Only a call to cnlt_control() + by the user should set the timeout value. */ + tv.tv_sec = 25; + tv.tv_usec = 0; + clnt_control (client, CLSET_TIMEOUT, (char *)&tv); +#endif + break; + default: + { + struct rpc_createerr *ce = &get_rpc_createerr (); + ce->cf_stat = RPC_SYSTEMERROR; + ce->cf_error.re_errno = EPFNOSUPPORT; + } + return (NULL); + } + return client; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/clnt_perror.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/clnt_perror.c new file mode 100644 index 00000000..8dbae729 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/clnt_perror.c @@ -0,0 +1,435 @@ +/* @(#)clnt_perror.c 2.1 88/07/29 4.0 RPCSRC */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +#if 0 +static char sccsid[] = "@(#)clnt_perror.c 1.15 87/10/07 Copyr 1984 Sun Micro"; +#endif + +/* + * clnt_perror.c + * + * Copyright (C) 1984, Sun Microsystems, Inc. + * + */ + +#define __FORCE_GLIBC +#include + +#include +#include +#include "rpc_private.h" + +#ifdef USE_IN_LIBIO +# include +# include +# define fputs(s, f) _IO_fputs (s, f) +#endif + +static char *auth_errmsg (enum auth_stat stat) internal_function; + +#ifdef __UCLIBC_HAS_THREADS__ +/* + * Making buf a preprocessor macro requires renaming the local + * buf variable in a few functions. Overriding a global variable + * with a local variable of the same name is a bad idea, anyway. + */ +#define buf (*(char **)&RPC_THREAD_VARIABLE(clnt_perr_buf_s)) +#else +static char *buf; +#endif + +static char * +_buf (void) +{ + if (buf == NULL) + buf = (char *) malloc (256); + return buf; +} + +struct rpc_errtab +{ + enum clnt_stat status; + unsigned int message_off; +}; + +static const char rpc_errstr[] = +{ +#define RPC_SUCCESS_IDX 0 + _("RPC: Success") + "\0" +#define RPC_CANTENCODEARGS_IDX (RPC_SUCCESS_IDX + sizeof "RPC: Success") + _("RPC: Can't encode arguments") + "\0" +#define RPC_CANTDECODERES_IDX (RPC_CANTENCODEARGS_IDX \ + + sizeof "RPC: Can't encode arguments") + _("RPC: Can't decode result") + "\0" +#define RPC_CANTSEND_IDX (RPC_CANTDECODERES_IDX \ + + sizeof "RPC: Can't decode result") + _("RPC: Unable to send") + "\0" +#define RPC_CANTRECV_IDX (RPC_CANTSEND_IDX \ + + sizeof "RPC: Unable to send") + _("RPC: Unable to receive") + "\0" +#define RPC_TIMEDOUT_IDX (RPC_CANTRECV_IDX \ + + sizeof "RPC: Unable to receive") + _("RPC: Timed out") + "\0" +#define RPC_VERSMISMATCH_IDX (RPC_TIMEDOUT_IDX \ + + sizeof "RPC: Timed out") + _("RPC: Incompatible versions of RPC") + "\0" +#define RPC_AUTHERROR_IDX (RPC_VERSMISMATCH_IDX \ + + sizeof "RPC: Incompatible versions of RPC") + _("RPC: Authentication error") + "\0" +#define RPC_PROGUNAVAIL_IDX (RPC_AUTHERROR_IDX \ + + sizeof "RPC: Authentication error") + _("RPC: Program unavailable") + "\0" +#define RPC_PROGVERSMISMATCH_IDX (RPC_PROGUNAVAIL_IDX \ + + sizeof "RPC: Program unavailable") + _("RPC: Program/version mismatch") + "\0" +#define RPC_PROCUNAVAIL_IDX (RPC_PROGVERSMISMATCH_IDX \ + + sizeof "RPC: Program/version mismatch") + _("RPC: Procedure unavailable") + "\0" +#define RPC_CANTDECODEARGS_IDX (RPC_PROCUNAVAIL_IDX \ + + sizeof "RPC: Procedure unavailable") + _("RPC: Server can't decode arguments") + "\0" +#define RPC_SYSTEMERROR_IDX (RPC_CANTDECODEARGS_IDX \ + + sizeof "RPC: Server can't decode arguments") + _("RPC: Remote system error") + "\0" +#define RPC_UNKNOWNHOST_IDX (RPC_SYSTEMERROR_IDX \ + + sizeof "RPC: Remote system error") + _("RPC: Unknown host") + "\0" +#define RPC_UNKNOWNPROTO_IDX (RPC_UNKNOWNHOST_IDX \ + + sizeof "RPC: Unknown host") + _("RPC: Unknown protocol") + "\0" +#define RPC_PMAPFAILURE_IDX (RPC_UNKNOWNPROTO_IDX \ + + sizeof "RPC: Unknown protocol") + _("RPC: Port mapper failure") + "\0" +#define RPC_PROGNOTREGISTERED_IDX (RPC_PMAPFAILURE_IDX \ + + sizeof "RPC: Port mapper failure") + _("RPC: Program not registered") + "\0" +#define RPC_FAILED_IDX (RPC_PROGNOTREGISTERED_IDX \ + + sizeof "RPC: Program not registered") + _("RPC: Failed (unspecified error)") +}; + +static const struct rpc_errtab rpc_errlist[] = +{ + { RPC_SUCCESS, RPC_SUCCESS_IDX }, + { RPC_CANTENCODEARGS, RPC_CANTENCODEARGS_IDX }, + { RPC_CANTDECODERES, RPC_CANTDECODERES_IDX }, + { RPC_CANTSEND, RPC_CANTSEND_IDX }, + { RPC_CANTRECV, RPC_CANTRECV_IDX }, + { RPC_TIMEDOUT, RPC_TIMEDOUT_IDX }, + { RPC_VERSMISMATCH, RPC_VERSMISMATCH_IDX }, + { RPC_AUTHERROR, RPC_AUTHERROR_IDX }, + { RPC_PROGUNAVAIL, RPC_PROGUNAVAIL_IDX }, + { RPC_PROGVERSMISMATCH, RPC_PROGVERSMISMATCH_IDX }, + { RPC_PROCUNAVAIL, RPC_PROCUNAVAIL_IDX }, + { RPC_CANTDECODEARGS, RPC_CANTDECODEARGS_IDX }, + { RPC_SYSTEMERROR, RPC_SYSTEMERROR_IDX }, + { RPC_UNKNOWNHOST, RPC_UNKNOWNHOST_IDX }, + { RPC_UNKNOWNPROTO, RPC_UNKNOWNPROTO_IDX }, + { RPC_PMAPFAILURE, RPC_PMAPFAILURE_IDX }, + { RPC_PROGNOTREGISTERED, RPC_PROGNOTREGISTERED_IDX }, + { RPC_FAILED, RPC_FAILED_IDX } +}; + + +/* + * This interface for use by clntrpc + */ +char * +clnt_sperrno (enum clnt_stat stat) +{ + size_t i; + + for (i = 0; i < sizeof (rpc_errlist) / sizeof (struct rpc_errtab); i++) + { + if (rpc_errlist[i].status == stat) + { + return (char*)_(rpc_errstr + rpc_errlist[i].message_off); + } + } + return _("RPC: (unknown error code)"); +} +libc_hidden_def(clnt_sperrno) + +void +clnt_perrno (enum clnt_stat num) +{ +#ifdef USE_IN_LIBIO + if (_IO_fwide (stderr, 0) > 0) + (void) fwprintf (stderr, L"%s", clnt_sperrno (num)); + else +#endif + (void) fputs (clnt_sperrno (num), stderr); +} + +/* + * Print reply error info + */ +char * +clnt_sperror (CLIENT * rpch, const char *msg) +{ + char chrbuf[1024]; + struct rpc_err e; + char *err; + char *str = _buf (); + char *strstart = str; + int len; + + if (str == NULL) + return NULL; + CLNT_GETERR (rpch, &e); + + len = sprintf (str, "%s: ", msg); + str += len; + + (void) strcpy(str, clnt_sperrno(e.re_status)); + str += strlen(str); + + switch (e.re_status) + { + case RPC_SUCCESS: + case RPC_CANTENCODEARGS: + case RPC_CANTDECODERES: + case RPC_TIMEDOUT: + case RPC_PROGUNAVAIL: + case RPC_PROCUNAVAIL: + case RPC_CANTDECODEARGS: + case RPC_SYSTEMERROR: + case RPC_UNKNOWNHOST: + case RPC_UNKNOWNPROTO: + case RPC_PMAPFAILURE: + case RPC_PROGNOTREGISTERED: + case RPC_FAILED: + break; + + case RPC_CANTSEND: + case RPC_CANTRECV: + __glibc_strerror_r (e.re_errno, chrbuf, sizeof chrbuf); + len = sprintf (str, "; errno = %s", chrbuf); + str += len; + break; + + case RPC_VERSMISMATCH: + len= sprintf (str, _("; low version = %lu, high version = %lu"), + e.re_vers.low, e.re_vers.high); + str += len; + break; + + case RPC_AUTHERROR: + err = auth_errmsg (e.re_why); + (void) strcpy(str, _("; why = ")); + str += strlen(str); + + if (err != NULL) + { + (void) strcpy(str, err); + str += strlen(str); + } + else + { + len = sprintf (str, _("(unknown authentication error - %d)"), + (int) e.re_why); + str += len; + } + break; + + case RPC_PROGVERSMISMATCH: + len = sprintf (str, _("; low version = %lu, high version = %lu"), + e.re_vers.low, e.re_vers.high); + str += len; + break; + + default: /* unknown */ + len = sprintf (str, "; s1 = %lu, s2 = %lu", e.re_lb.s1, e.re_lb.s2); + str += len; + break; + } + *str = '\n'; + *++str = '\0'; + return (strstart); +} +libc_hidden_def(clnt_sperror) + +void +clnt_perror (CLIENT * rpch, const char *msg) +{ +#ifdef USE_IN_LIBIO + if (_IO_fwide (stderr, 0) > 0) + (void) fwprintf (stderr, L"%s", clnt_sperror (rpch, msg)); + else +#endif + (void) fputs (clnt_sperror (rpch, msg), stderr); +} +libc_hidden_def(clnt_perror) + +char * +clnt_spcreateerror (const char *msg) +{ + char chrbuf[1024]; + char *str = _buf (); + char *cp; + int len; + struct rpc_createerr *ce; + + if (str == NULL) + return NULL; + ce = &get_rpc_createerr (); + len = sprintf (str, "%s: ", msg); + cp = str + len; + (void) strcpy(cp, clnt_sperrno (ce->cf_stat)); + cp += strlen(cp); + + switch (ce->cf_stat) + { + case RPC_PMAPFAILURE: + (void) strcpy(cp, " - "); + cp += strlen(cp); + + (void) strcpy(cp, clnt_sperrno (ce->cf_error.re_status)); + cp += strlen(cp); + + break; + + case RPC_SYSTEMERROR: + (void) strcpy(cp, " - "); + cp += strlen(cp); + + __glibc_strerror_r (ce->cf_error.re_errno, chrbuf, sizeof chrbuf); + (void) strcpy(cp, chrbuf); + cp += strlen(cp); + break; + default: + break; + } + *cp = '\n'; + *++cp = '\0'; + return str; +} +libc_hidden_def(clnt_spcreateerror) + +void +clnt_pcreateerror (const char *msg) +{ +#ifdef USE_IN_LIBIO + if (_IO_fwide (stderr, 0) > 0) + (void) fwprintf (stderr, L"%s", clnt_spcreateerror (msg)); + else +#endif + (void) fputs (clnt_spcreateerror (msg), stderr); +} + +struct auth_errtab +{ + enum auth_stat status; + unsigned int message_off; +}; + +static const char auth_errstr[] = +{ +#define AUTH_OK_IDX 0 + _("Authentication OK") + "\0" +#define AUTH_BADCRED_IDX (AUTH_OK_IDX + sizeof "Authentication OK") + _("Invalid client credential") + "\0" +#define AUTH_REJECTEDCRED_IDX (AUTH_BADCRED_IDX \ + + sizeof "Invalid client credential") + _("Server rejected credential") + "\0" +#define AUTH_BADVERF_IDX (AUTH_REJECTEDCRED_IDX \ + + sizeof "Server rejected credential") + _("Invalid client verifier") + "\0" +#define AUTH_REJECTEDVERF_IDX (AUTH_BADVERF_IDX \ + + sizeof "Invalid client verifier") + _("Server rejected verifier") + "\0" +#define AUTH_TOOWEAK_IDX (AUTH_REJECTEDVERF_IDX \ + + sizeof "Server rejected verifier") + _("Client credential too weak") + "\0" +#define AUTH_INVALIDRESP_IDX (AUTH_TOOWEAK_IDX \ + + sizeof "Client credential too weak") + _("Invalid server verifier") + "\0" +#define AUTH_FAILED_IDX (AUTH_INVALIDRESP_IDX \ + + sizeof "Invalid server verifier") + _("Failed (unspecified error)") +}; + +static const struct auth_errtab auth_errlist[] = +{ + { AUTH_OK, AUTH_OK_IDX }, + { AUTH_BADCRED, AUTH_BADCRED_IDX }, + { AUTH_REJECTEDCRED, AUTH_REJECTEDCRED_IDX }, + { AUTH_BADVERF, AUTH_BADVERF_IDX }, + { AUTH_REJECTEDVERF, AUTH_REJECTEDVERF_IDX }, + { AUTH_TOOWEAK, AUTH_TOOWEAK_IDX }, + { AUTH_INVALIDRESP, AUTH_INVALIDRESP_IDX }, + { AUTH_FAILED, AUTH_FAILED_IDX } +}; + +static char * +internal_function +auth_errmsg (enum auth_stat stat) +{ + size_t i; + + for (i = 0; i < sizeof (auth_errlist) / sizeof (struct auth_errtab); i++) + { + if (auth_errlist[i].status == stat) + { + return (char*)_(auth_errstr + auth_errlist[i].message_off); + } + } + return NULL; +} + + +static void __attribute_used__ +free_mem (void) +{ + free (buf); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/clnt_raw.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/clnt_raw.c new file mode 100644 index 00000000..75dd9828 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/clnt_raw.c @@ -0,0 +1,248 @@ +/* @(#)clnt_raw.c 2.2 88/08/01 4.0 RPCSRC */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +#if 0 +static char sccsid[] = "@(#)clnt_raw.c 1.22 87/08/11 Copyr 1984 Sun Micro"; +#endif + +/* + * clnt_raw.c + * + * Copyright (C) 1984, Sun Microsystems, Inc. + * + * Memory based rpc for simple testing and timing. + * Interface to create an rpc client and server in the same process. + * This lets us simulate rpc and get round trip overhead, without + * any interference from the kernel. + */ + +#define __FORCE_GLIBC +#include +#include "rpc_private.h" +#include +#include + + +#define MCALL_MSG_SIZE 24 + +/* + * This is the "network" we will be moving stuff over. + */ +struct clntraw_private_s + { + CLIENT client_object; + XDR xdr_stream; + char _raw_buf[UDPMSGSIZE]; + char mashl_callmsg[MCALL_MSG_SIZE]; + u_int mcnt; + }; +#ifdef __UCLIBC_HAS_THREADS__ +#define clntraw_private (*(struct clntraw_private_s **)&RPC_THREAD_VARIABLE(clntraw_private_s)) +#else +static struct clntraw_private_s *clntraw_private; +#endif + +static enum clnt_stat clntraw_call (CLIENT *, u_long, xdrproc_t, caddr_t, + xdrproc_t, caddr_t, struct timeval); +static void clntraw_abort (void); +static void clntraw_geterr (CLIENT *, struct rpc_err *); +static bool_t clntraw_freeres (CLIENT *, xdrproc_t, caddr_t); +static bool_t clntraw_control (CLIENT *, int, char *); +static void clntraw_destroy (CLIENT *); + +static const struct clnt_ops client_ops = +{ + clntraw_call, + clntraw_abort, + clntraw_geterr, + clntraw_freeres, + clntraw_destroy, + clntraw_control +}; + +/* + * Create a client handle for memory based rpc. + */ +CLIENT * +clntraw_create (u_long prog, u_long vers) +{ + struct clntraw_private_s *clp = clntraw_private; + struct rpc_msg call_msg; + XDR *xdrs = &clp->xdr_stream; + CLIENT *client = &clp->client_object; + + if (clp == 0) + { + clp = (struct clntraw_private_s *) calloc (1, sizeof (*clp)); + if (clp == 0) + return (0); + clntraw_private = clp; + } + /* + * pre-serialize the static part of the call msg and stash it away + */ + call_msg.rm_direction = CALL; + call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION; + call_msg.rm_call.cb_prog = prog; + call_msg.rm_call.cb_vers = vers; + xdrmem_create (xdrs, clp->mashl_callmsg, MCALL_MSG_SIZE, XDR_ENCODE); + if (!xdr_callhdr (xdrs, &call_msg)) + { + perror (_ ("clnt_raw.c - Fatal header serialization error.")); + } + clp->mcnt = XDR_GETPOS (xdrs); + XDR_DESTROY (xdrs); + + /* + * Set xdrmem for client/server shared buffer + */ + xdrmem_create (xdrs, clp->_raw_buf, UDPMSGSIZE, XDR_FREE); + + /* + * create client handle + */ + client->cl_ops = &client_ops; + client->cl_auth = authnone_create (); + return client; +} + +static enum clnt_stat +clntraw_call (CLIENT *h, u_long proc, xdrproc_t xargs, caddr_t argsp, + xdrproc_t xresults, caddr_t resultsp, + struct timeval timeout attribute_unused) +{ + struct clntraw_private_s *clp = clntraw_private; + XDR *xdrs = &clp->xdr_stream; + struct rpc_msg msg; + enum clnt_stat status; + struct rpc_err error; + + if (clp == NULL) + return RPC_FAILED; +call_again: + /* + * send request + */ + xdrs->x_op = XDR_ENCODE; + XDR_SETPOS (xdrs, 0); + ((struct rpc_msg *) clp->mashl_callmsg)->rm_xid++; + if ((!XDR_PUTBYTES (xdrs, clp->mashl_callmsg, clp->mcnt)) || + (!XDR_PUTLONG (xdrs, (long *) &proc)) || + (!AUTH_MARSHALL (h->cl_auth, xdrs)) || + (!(*xargs) (xdrs, argsp))) + { + return (RPC_CANTENCODEARGS); + } + (void) XDR_GETPOS (xdrs); /* called just to cause overhead */ + + /* + * We have to call server input routine here because this is + * all going on in one process. Yuk. + */ + svc_getreq (1); + + /* + * get results + */ + xdrs->x_op = XDR_DECODE; + XDR_SETPOS (xdrs, 0); + msg.acpted_rply.ar_verf = _null_auth; + msg.acpted_rply.ar_results.where = resultsp; + msg.acpted_rply.ar_results.proc = xresults; + if (!xdr_replymsg (xdrs, &msg)) + return RPC_CANTDECODERES; + _seterr_reply (&msg, &error); + status = error.re_status; + + if (status == RPC_SUCCESS) + { + if (!AUTH_VALIDATE (h->cl_auth, &msg.acpted_rply.ar_verf)) + { + status = RPC_AUTHERROR; + } + } /* end successful completion */ + else + { + if (AUTH_REFRESH (h->cl_auth)) + goto call_again; + } /* end of unsuccessful completion */ + + if (status == RPC_SUCCESS) + { + if (!AUTH_VALIDATE (h->cl_auth, &msg.acpted_rply.ar_verf)) + { + status = RPC_AUTHERROR; + } + if (msg.acpted_rply.ar_verf.oa_base != NULL) + { + xdrs->x_op = XDR_FREE; + (void) xdr_opaque_auth (xdrs, &(msg.acpted_rply.ar_verf)); + } + } + + return status; +} + +static void +clntraw_geterr (CLIENT *cl attribute_unused, struct rpc_err *err attribute_unused) +{ +} + + +static bool_t +clntraw_freeres (CLIENT *cl attribute_unused, xdrproc_t xdr_res, caddr_t res_ptr) +{ + struct clntraw_private_s *clp = clntraw_private; + XDR *xdrs = &clp->xdr_stream; + bool_t rval; + + if (clp == NULL) + { + rval = (bool_t) RPC_FAILED; + return rval; + } + xdrs->x_op = XDR_FREE; + return (*xdr_res) (xdrs, res_ptr); +} + +static void +clntraw_abort (void) +{ +} + +static bool_t +clntraw_control (CLIENT *cl attribute_unused, int i attribute_unused, char *c attribute_unused) +{ + return FALSE; +} + +static void +clntraw_destroy (CLIENT *cl attribute_unused) +{ +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/clnt_simple.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/clnt_simple.c new file mode 100644 index 00000000..f66228a5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/clnt_simple.c @@ -0,0 +1,164 @@ +/* @(#)clnt_simple.c 2.2 88/08/01 4.0 RPCSRC */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +#if 0 +static char sccsid[] = "@(#)clnt_simple.c 1.35 87/08/11 Copyr 1984 Sun Micro"; +#endif + +/* + * clnt_simple.c + * Simplified front end to rpc. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +#define __FORCE_GLIBC +#include + +#include +#include +#include +#include +#include "rpc_private.h" +#include +#include +#include + + +struct callrpc_private_s + { + CLIENT *client; + int socket; + u_long oldprognum, oldversnum, valid; + char *oldhost; + }; +#ifdef __UCLIBC_HAS_THREADS__ +#define callrpc_private (*(struct callrpc_private_s **)&RPC_THREAD_VARIABLE(callrpc_private_s)) +#else +static struct callrpc_private_s *callrpc_private; +#endif + +int +callrpc (const char *host, u_long prognum, u_long versnum, u_long procnum, + xdrproc_t inproc, const char *in, xdrproc_t outproc, char *out) +{ + struct callrpc_private_s *crp = callrpc_private; + struct sockaddr_in server_addr; + enum clnt_stat clnt_stat; + struct hostent hostbuf, *hp; + struct timeval timeout, tottimeout; + + if (crp == 0) + { + crp = (struct callrpc_private_s *) calloc (1, sizeof (*crp)); + if (crp == 0) + return 0; + callrpc_private = crp; + } + if (crp->oldhost == NULL) + { + crp->oldhost = malloc (256); + crp->oldhost[0] = 0; + crp->socket = RPC_ANYSOCK; + } + if (crp->valid && crp->oldprognum == prognum && crp->oldversnum == versnum + && strcmp (crp->oldhost, host) == 0) + { + /* reuse old client */ + } + else + { + size_t buflen; + char *buffer; + int herr; + + crp->valid = 0; + if (crp->socket != RPC_ANYSOCK) + { + (void) close (crp->socket); + crp->socket = RPC_ANYSOCK; + } + if (crp->client) + { + clnt_destroy (crp->client); + crp->client = NULL; + } + + buflen = 1024; + buffer = alloca (buflen); + while (gethostbyname_r (host, &hostbuf, buffer, buflen, + &hp, &herr) != 0 + || hp == NULL) + if (herr != NETDB_INTERNAL || errno != ERANGE) + return (int) RPC_UNKNOWNHOST; + else + { + /* Enlarge the buffer. */ + buflen *= 2; + buffer = alloca (buflen); + } + + timeout.tv_usec = 0; + timeout.tv_sec = 5; + memcpy ((char *) &server_addr.sin_addr, hp->h_addr, hp->h_length); + server_addr.sin_family = AF_INET; + server_addr.sin_port = 0; + if ((crp->client = clntudp_create (&server_addr, (u_long) prognum, + (u_long) versnum, timeout, &crp->socket)) == NULL) + return (int) get_rpc_createerr().cf_stat; + crp->valid = 1; + crp->oldprognum = prognum; + crp->oldversnum = versnum; + (void) strncpy (crp->oldhost, host, 255); + crp->oldhost[255] = '\0'; + } + tottimeout.tv_sec = 25; + tottimeout.tv_usec = 0; + clnt_stat = clnt_call (crp->client, procnum, inproc, (char *) in, + outproc, out, tottimeout); + /* + * if call failed, empty cache + */ + if (clnt_stat != RPC_SUCCESS) + crp->valid = 0; + return (int) clnt_stat; +} + +#ifdef __UCLIBC_HAS_THREADS__ +void attribute_hidden __rpc_thread_clnt_cleanup (void) +{ + struct callrpc_private_s *rcp = RPC_THREAD_VARIABLE(callrpc_private_s); + + if (rcp) { + if (rcp->client) + CLNT_DESTROY (rcp->client); + free (rcp); + } +} +#endif /* __UCLIBC_HAS_THREADS__ */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/clnt_tcp.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/clnt_tcp.c new file mode 100644 index 00000000..d01fc80d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/clnt_tcp.c @@ -0,0 +1,531 @@ +/* @(#)clnt_tcp.c 2.2 88/08/01 4.0 RPCSRC */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +#if 0 +static char sccsid[] = "@(#)clnt_tcp.c 1.37 87/10/05 Copyr 1984 Sun Micro"; +#endif + +/* + * clnt_tcp.c, Implements a TCP/IP based, client side RPC. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + * + * TCP based RPC supports 'batched calls'. + * A sequence of calls may be batched-up in a send buffer. The rpc call + * return immediately to the client even though the call was not necessarily + * sent. The batching occurs if the results' xdr routine is NULL (0) AND + * the rpc timeout value is zero (see clnt.h, rpc). + * + * Clients should NOT casually batch calls that in fact return results; that is, + * the server side should be aware that a call is batched and not produce any + * return message. Batched calls that produce many result messages can + * deadlock (netlock) the client and the server.... + * + * Now go hang yourself. + */ + +#define __FORCE_GLIBC +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef USE_IN_LIBIO +# include +#endif + +extern u_long _create_xid (void) attribute_hidden; + +#define MCALL_MSG_SIZE 24 + +struct ct_data + { + int ct_sock; + bool_t ct_closeit; + struct timeval ct_wait; + bool_t ct_waitset; /* wait set by clnt_control? */ + struct sockaddr_in ct_addr; + struct rpc_err ct_error; + char ct_mcall[MCALL_MSG_SIZE]; /* marshalled callmsg */ + u_int ct_mpos; /* pos after marshal */ + XDR ct_xdrs; + }; + +static int readtcp (char *, char *, int); +static int writetcp (char *, char *, int); + +static enum clnt_stat clnttcp_call (CLIENT *, u_long, xdrproc_t, caddr_t, + xdrproc_t, caddr_t, struct timeval); +static void clnttcp_abort (void); +static void clnttcp_geterr (CLIENT *, struct rpc_err *); +static bool_t clnttcp_freeres (CLIENT *, xdrproc_t, caddr_t); +static bool_t clnttcp_control (CLIENT *, int, char *); +static void clnttcp_destroy (CLIENT *); + +static const struct clnt_ops tcp_ops = +{ + clnttcp_call, + clnttcp_abort, + clnttcp_geterr, + clnttcp_freeres, + clnttcp_destroy, + clnttcp_control +}; + +/* + * Create a client handle for a tcp/ip connection. + * If *sockp<0, *sockp is set to a newly created TCP socket and it is + * connected to raddr. If *sockp non-negative then + * raddr is ignored. The rpc/tcp package does buffering + * similar to stdio, so the client must pick send and receive buffer sizes,]; + * 0 => use the default. + * If raddr->sin_port is 0, then a binder on the remote machine is + * consulted for the right port number. + * NB: *sockp is copied into a private area. + * NB: It is the clients responsibility to close *sockp. + * NB: The rpch->cl_auth is set null authentication. Caller may wish to set this + * something more useful. + */ +CLIENT * +clnttcp_create (struct sockaddr_in *raddr, u_long prog, u_long vers, + int *sockp, u_int sendsz, u_int recvsz) +{ + CLIENT *h; + struct ct_data *ct; + struct rpc_msg call_msg; + + h = (CLIENT *) mem_alloc (sizeof (*h)); + ct = (struct ct_data *) mem_alloc (sizeof (*ct)); + if (h == NULL || ct == NULL) + { + struct rpc_createerr *ce = &get_rpc_createerr (); +#ifdef USE_IN_LIBIO + if (_IO_fwide (stderr, 0) > 0) + (void) fwprintf (stderr, L"%s", + _("clnttcp_create: out of memory\n")); + else +#endif + (void) fputs (_("clnttcp_create: out of memory\n"), stderr); + ce->cf_stat = RPC_SYSTEMERROR; + ce->cf_error.re_errno = ENOMEM; + goto fooy; + } + + /* + * If no port number given ask the pmap for one + */ + if (raddr->sin_port == 0) + { + u_short port; + if ((port = pmap_getport (raddr, prog, vers, IPPROTO_TCP)) == 0) + { + mem_free ((caddr_t) ct, sizeof (struct ct_data)); + mem_free ((caddr_t) h, sizeof (CLIENT)); + return ((CLIENT *) NULL); + } + raddr->sin_port = htons (port); + } + + /* + * If no socket given, open one + */ + if (*sockp < 0) + { + *sockp = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); + (void) bindresvport (*sockp, (struct sockaddr_in *) 0); + if ((*sockp < 0) + || (connect (*sockp, (struct sockaddr *) raddr, + sizeof (*raddr)) < 0)) + { + struct rpc_createerr *ce = &get_rpc_createerr (); + ce->cf_stat = RPC_SYSTEMERROR; + ce->cf_error.re_errno = errno; + if (*sockp >= 0) + (void) close (*sockp); + goto fooy; + } + ct->ct_closeit = TRUE; + } + else + { + ct->ct_closeit = FALSE; + } + + /* + * Set up private data struct + */ + ct->ct_sock = *sockp; + ct->ct_wait.tv_usec = 0; + ct->ct_waitset = FALSE; + ct->ct_addr = *raddr; + + /* + * Initialize call message + */ + call_msg.rm_xid = _create_xid (); + call_msg.rm_direction = CALL; + call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION; + call_msg.rm_call.cb_prog = prog; + call_msg.rm_call.cb_vers = vers; + + /* + * pre-serialize the static part of the call msg and stash it away + */ + xdrmem_create (&(ct->ct_xdrs), ct->ct_mcall, MCALL_MSG_SIZE, + XDR_ENCODE); + if (!xdr_callhdr (&(ct->ct_xdrs), &call_msg)) + { + if (ct->ct_closeit) + { + (void) close (*sockp); + } + goto fooy; + } + ct->ct_mpos = XDR_GETPOS (&(ct->ct_xdrs)); + XDR_DESTROY (&(ct->ct_xdrs)); + + /* + * Create a client handle which uses xdrrec for serialization + * and authnone for authentication. + */ + xdrrec_create (&(ct->ct_xdrs), sendsz, recvsz, + (caddr_t) ct, readtcp, writetcp); + h->cl_ops = &tcp_ops; + h->cl_private = (caddr_t) ct; + h->cl_auth = authnone_create (); + return h; + +fooy: + /* + * Something goofed, free stuff and barf + */ + mem_free ((caddr_t) ct, sizeof (struct ct_data)); + mem_free ((caddr_t) h, sizeof (CLIENT)); + return ((CLIENT *) NULL); +} +libc_hidden_def(clnttcp_create) + +static enum clnt_stat +clnttcp_call (CLIENT *h, u_long proc, xdrproc_t xdr_args, caddr_t args_ptr, + xdrproc_t xdr_results, caddr_t results_ptr, + struct timeval timeout) +{ + struct ct_data *ct = (struct ct_data *) h->cl_private; + XDR *xdrs = &(ct->ct_xdrs); + struct rpc_msg reply_msg; + u_long x_id; + u_int32_t *msg_x_id = (u_int32_t *) (ct->ct_mcall); /* yuk */ + bool_t shipnow; + int refreshes = 2; + + if (!ct->ct_waitset) + { + ct->ct_wait = timeout; + } + + shipnow = + (xdr_results == (xdrproc_t) 0 && ct->ct_wait.tv_sec == 0 + && ct->ct_wait.tv_usec == 0) ? FALSE : TRUE; + +call_again: + xdrs->x_op = XDR_ENCODE; + ct->ct_error.re_status = RPC_SUCCESS; + x_id = ntohl (--(*msg_x_id)); + if ((!XDR_PUTBYTES (xdrs, ct->ct_mcall, ct->ct_mpos)) || + (!XDR_PUTLONG (xdrs, (long *) &proc)) || + (!AUTH_MARSHALL (h->cl_auth, xdrs)) || + (!(*xdr_args) (xdrs, args_ptr))) + { + if (ct->ct_error.re_status == RPC_SUCCESS) + ct->ct_error.re_status = RPC_CANTENCODEARGS; + (void) xdrrec_endofrecord (xdrs, TRUE); + return (ct->ct_error.re_status); + } + if (!xdrrec_endofrecord (xdrs, shipnow)) + return ct->ct_error.re_status = RPC_CANTSEND; + if (!shipnow) + return RPC_SUCCESS; + /* + * Hack to provide rpc-based message passing + */ + if (ct->ct_wait.tv_sec == 0 && ct->ct_wait.tv_usec == 0) + { + return ct->ct_error.re_status = RPC_TIMEDOUT; + } + + + /* + * Keep receiving until we get a valid transaction id + */ + xdrs->x_op = XDR_DECODE; + while (TRUE) + { + reply_msg.acpted_rply.ar_verf = _null_auth; + reply_msg.acpted_rply.ar_results.where = NULL; + reply_msg.acpted_rply.ar_results.proc = (xdrproc_t)xdr_void; + if (!xdrrec_skiprecord (xdrs)) + return (ct->ct_error.re_status); + /* now decode and validate the response header */ + if (!xdr_replymsg (xdrs, &reply_msg)) + { + if (ct->ct_error.re_status == RPC_SUCCESS) + continue; + return ct->ct_error.re_status; + } + if ((u_int32_t) reply_msg.rm_xid == (u_int32_t) x_id) + break; + } + + /* + * process header + */ + _seterr_reply (&reply_msg, &(ct->ct_error)); + if (ct->ct_error.re_status == RPC_SUCCESS) + { + if (!AUTH_VALIDATE (h->cl_auth, &reply_msg.acpted_rply.ar_verf)) + { + ct->ct_error.re_status = RPC_AUTHERROR; + ct->ct_error.re_why = AUTH_INVALIDRESP; + } + else if (!(*xdr_results) (xdrs, results_ptr)) + { + if (ct->ct_error.re_status == RPC_SUCCESS) + ct->ct_error.re_status = RPC_CANTDECODERES; + } + /* free verifier ... */ + if (reply_msg.acpted_rply.ar_verf.oa_base != NULL) + { + xdrs->x_op = XDR_FREE; + (void) xdr_opaque_auth (xdrs, &(reply_msg.acpted_rply.ar_verf)); + } + } /* end successful completion */ + else + { + /* maybe our credentials need to be refreshed ... */ + if (refreshes-- && AUTH_REFRESH (h->cl_auth)) + goto call_again; + } /* end of unsuccessful completion */ + return ct->ct_error.re_status; +} + +static void +clnttcp_geterr (CLIENT *h, struct rpc_err *errp) +{ + struct ct_data *ct = + (struct ct_data *) h->cl_private; + + *errp = ct->ct_error; +} + +static bool_t +clnttcp_freeres (CLIENT *cl, xdrproc_t xdr_res, caddr_t res_ptr) +{ + struct ct_data *ct = (struct ct_data *) cl->cl_private; + XDR *xdrs = &(ct->ct_xdrs); + + xdrs->x_op = XDR_FREE; + return (*xdr_res) (xdrs, res_ptr); +} + +static void +clnttcp_abort (void) +{ +} + +static bool_t +clnttcp_control (CLIENT *cl, int request, char *info) +{ + struct ct_data *ct = (struct ct_data *) cl->cl_private; + + + switch (request) + { + case CLSET_FD_CLOSE: + ct->ct_closeit = TRUE; + break; + case CLSET_FD_NCLOSE: + ct->ct_closeit = FALSE; + break; + case CLSET_TIMEOUT: + ct->ct_wait = *(struct timeval *) info; + ct->ct_waitset = TRUE; + break; + case CLGET_TIMEOUT: + *(struct timeval *) info = ct->ct_wait; + break; + case CLGET_SERVER_ADDR: + *(struct sockaddr_in *) info = ct->ct_addr; + break; + case CLGET_FD: + *(int *)info = ct->ct_sock; + break; + case CLGET_XID: + /* + * use the knowledge that xid is the + * first element in the call structure *. + * This will get the xid of the PREVIOUS call + */ + *(u_long *)info = ntohl (*(u_long *)ct->ct_mcall); + break; + case CLSET_XID: + /* This will set the xid of the NEXT call */ + *(u_long *)ct->ct_mcall = htonl (*(u_long *)info - 1); + /* decrement by 1 as clnttcp_call() increments once */ + case CLGET_VERS: + /* + * This RELIES on the information that, in the call body, + * the version number field is the fifth field from the + * begining of the RPC header. MUST be changed if the + * call_struct is changed + */ + *(u_long *)info = ntohl (*(u_long *)(ct->ct_mcall + + 4 * BYTES_PER_XDR_UNIT)); + break; + case CLSET_VERS: + *(u_long *)(ct->ct_mcall + 4 * BYTES_PER_XDR_UNIT) + = htonl (*(u_long *)info); + break; + case CLGET_PROG: + /* + * This RELIES on the information that, in the call body, + * the program number field is the field from the + * begining of the RPC header. MUST be changed if the + * call_struct is changed + */ + *(u_long *)info = ntohl(*(u_long *)(ct->ct_mcall + + 3 * BYTES_PER_XDR_UNIT)); + break; + case CLSET_PROG: + *(u_long *)(ct->ct_mcall + 3 * BYTES_PER_XDR_UNIT) + = htonl(*(u_long *)info); + break; + /* The following are only possible with TI-RPC */ + case CLGET_RETRY_TIMEOUT: + case CLSET_RETRY_TIMEOUT: + case CLGET_SVC_ADDR: + case CLSET_SVC_ADDR: + case CLSET_PUSH_TIMOD: + case CLSET_POP_TIMOD: + default: + return FALSE; + } + return TRUE; +} + + +static void +clnttcp_destroy (CLIENT *h) +{ + struct ct_data *ct = + (struct ct_data *) h->cl_private; + + if (ct->ct_closeit) + { + (void) close (ct->ct_sock); + } + XDR_DESTROY (&(ct->ct_xdrs)); + mem_free ((caddr_t) ct, sizeof (struct ct_data)); + mem_free ((caddr_t) h, sizeof (CLIENT)); +} + +/* + * Interface between xdr serializer and tcp connection. + * Behaves like the system calls, read & write, but keeps some error state + * around for the rpc level. + */ +static int +readtcp (char *ctptr, char *buf, int len) +{ + struct ct_data *ct = (struct ct_data *)ctptr; + struct pollfd fd; + int milliseconds = (ct->ct_wait.tv_sec * 1000) + + (ct->ct_wait.tv_usec / 1000); + + if (len == 0) + return 0; + + fd.fd = ct->ct_sock; + fd.events = POLLIN; + while (TRUE) + { + switch (poll(&fd, 1, milliseconds)) + { + case 0: + ct->ct_error.re_status = RPC_TIMEDOUT; + return -1; + + case -1: + if (errno == EINTR) + continue; + ct->ct_error.re_status = RPC_CANTRECV; + ct->ct_error.re_errno = errno; + return -1; + } + break; + } + switch (len = read (ct->ct_sock, buf, len)) + { + + case 0: + /* premature eof */ + ct->ct_error.re_errno = ECONNRESET; + ct->ct_error.re_status = RPC_CANTRECV; + len = -1; /* it's really an error */ + break; + + case -1: + ct->ct_error.re_errno = errno; + ct->ct_error.re_status = RPC_CANTRECV; + break; + } + return len; +} + +static int +writetcp (char *ctptr, char *buf, int len) +{ + int i, cnt; + struct ct_data *ct = (struct ct_data*)ctptr; + + for (cnt = len; cnt > 0; cnt -= i, buf += i) + { + if ((i = write (ct->ct_sock, buf, cnt)) == -1) + { + ct->ct_error.re_errno = errno; + ct->ct_error.re_status = RPC_CANTSEND; + return -1; + } + } + return len; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/clnt_udp.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/clnt_udp.c new file mode 100644 index 00000000..fe8b7f8e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/clnt_udp.c @@ -0,0 +1,608 @@ +/* @(#)clnt_udp.c 2.2 88/08/01 4.0 RPCSRC */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +#if 0 +static char sccsid[] = "@(#)clnt_udp.c 1.39 87/08/11 Copyr 1984 Sun Micro"; +#endif + +/* + * clnt_udp.c, Implements a UDP/IP based, client side RPC. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +#define __FORCE_GLIBC +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef USE_IN_LIBIO +# include +#endif + +#ifdef IP_RECVERR +#include "errqueue.h" +#include +#endif + +/* CMSG_NXTHDR is using it */ + + +extern u_long _create_xid (void) attribute_hidden; + +/* + * UDP bases client side rpc operations + */ +static enum clnt_stat clntudp_call (CLIENT *, u_long, xdrproc_t, caddr_t, + xdrproc_t, caddr_t, struct timeval); +static void clntudp_abort (void); +static void clntudp_geterr (CLIENT *, struct rpc_err *); +static bool_t clntudp_freeres (CLIENT *, xdrproc_t, caddr_t); +static bool_t clntudp_control (CLIENT *, int, char *); +static void clntudp_destroy (CLIENT *); + +static const struct clnt_ops udp_ops = +{ + clntudp_call, + clntudp_abort, + clntudp_geterr, + clntudp_freeres, + clntudp_destroy, + clntudp_control +}; + +/* + * Private data kept per client handle + */ +struct cu_data + { + int cu_sock; + bool_t cu_closeit; + struct sockaddr_in cu_raddr; + int cu_rlen; + struct timeval cu_wait; + struct timeval cu_total; + struct rpc_err cu_error; + XDR cu_outxdrs; + u_int cu_xdrpos; + u_int cu_sendsz; + char *cu_outbuf; + u_int cu_recvsz; + char cu_inbuf[1]; + }; + +/* + * Create a UDP based client handle. + * If *sockp<0, *sockp is set to a newly created UPD socket. + * If raddr->sin_port is 0 a binder on the remote machine + * is consulted for the correct port number. + * NB: It is the clients responsibility to close *sockp. + * NB: The rpch->cl_auth is initialized to null authentication. + * Caller may wish to set this something more useful. + * + * wait is the amount of time used between retransmitting a call if + * no response has been heard; retransmission occurs until the actual + * rpc call times out. + * + * sendsz and recvsz are the maximum allowable packet sizes that can be + * sent and received. + */ +CLIENT * +clntudp_bufcreate (struct sockaddr_in *raddr, u_long program, u_long version, + struct timeval wait, int *sockp, u_int sendsz, + u_int recvsz) +{ + CLIENT *cl; + struct cu_data *cu = NULL; + struct rpc_msg call_msg; + + cl = (CLIENT *) mem_alloc (sizeof (CLIENT)); + sendsz = ((sendsz + 3) / 4) * 4; + recvsz = ((recvsz + 3) / 4) * 4; + cu = (struct cu_data *) mem_alloc (sizeof (*cu) + sendsz + recvsz); + if (cl == NULL || cu == NULL) + { + struct rpc_createerr *ce = &get_rpc_createerr (); +#ifdef USE_IN_LIBIO + if (_IO_fwide (stderr, 0) > 0) + (void) fwprintf (stderr, L"%s", + _("clntudp_create: out of memory\n")); + else +#endif + (void) fputs (_("clntudp_create: out of memory\n"), stderr); + ce->cf_stat = RPC_SYSTEMERROR; + ce->cf_error.re_errno = ENOMEM; + goto fooy; + } + cu->cu_outbuf = &cu->cu_inbuf[recvsz]; + + if (raddr->sin_port == 0) + { + u_short port; + if ((port = + pmap_getport (raddr, program, version, IPPROTO_UDP)) == 0) + { + goto fooy; + } + raddr->sin_port = htons (port); + } + cl->cl_ops = &udp_ops; + cl->cl_private = (caddr_t) cu; + cu->cu_raddr = *raddr; + cu->cu_rlen = sizeof (cu->cu_raddr); + cu->cu_wait = wait; + cu->cu_total.tv_sec = -1; + cu->cu_total.tv_usec = -1; + cu->cu_sendsz = sendsz; + cu->cu_recvsz = recvsz; + call_msg.rm_xid = _create_xid (); + call_msg.rm_direction = CALL; + call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION; + call_msg.rm_call.cb_prog = program; + call_msg.rm_call.cb_vers = version; + xdrmem_create (&(cu->cu_outxdrs), cu->cu_outbuf, + sendsz, XDR_ENCODE); + if (!xdr_callhdr (&(cu->cu_outxdrs), &call_msg)) + { + goto fooy; + } + cu->cu_xdrpos = XDR_GETPOS (&(cu->cu_outxdrs)); + if (*sockp < 0) + { + int dontblock = 1; + + *sockp = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (*sockp < 0) + { + struct rpc_createerr *ce = &get_rpc_createerr (); + ce->cf_stat = RPC_SYSTEMERROR; + ce->cf_error.re_errno = errno; + goto fooy; + } + /* attempt to bind to prov port */ + (void) bindresvport (*sockp, (struct sockaddr_in *) 0); + /* the sockets rpc controls are non-blocking */ + (void) ioctl (*sockp, FIONBIO, (char *) &dontblock); +#ifdef IP_RECVERR + { + int on = 1; + setsockopt(*sockp, SOL_IP, IP_RECVERR, &on, sizeof(on)); + } +#endif + cu->cu_closeit = TRUE; + } + else + { + cu->cu_closeit = FALSE; + } + cu->cu_sock = *sockp; + cl->cl_auth = authnone_create (); + return cl; +fooy: + if (cu) + mem_free ((caddr_t) cu, sizeof (*cu) + sendsz + recvsz); + if (cl) + mem_free ((caddr_t) cl, sizeof (CLIENT)); + return (CLIENT *) NULL; +} +libc_hidden_def(clntudp_bufcreate) + +CLIENT * +clntudp_create (struct sockaddr_in *raddr, u_long program, u_long version, struct timeval wait, int *sockp) +{ + + return clntudp_bufcreate (raddr, program, version, wait, sockp, + UDPMSGSIZE, UDPMSGSIZE); +} +libc_hidden_def(clntudp_create) + +static int +is_network_up (int sock) +{ + struct ifconf ifc; + char buf[UDPMSGSIZE]; + struct ifreq ifreq, *ifr; + int n; + + ifc.ifc_len = sizeof (buf); + ifc.ifc_buf = buf; + if (ioctl(sock, SIOCGIFCONF, (char *) &ifc) == 0) + { + ifr = ifc.ifc_req; + for (n = ifc.ifc_len / sizeof (struct ifreq); n > 0; n--, ifr++) + { + ifreq = *ifr; + if (ioctl (sock, SIOCGIFFLAGS, (char *) &ifreq) < 0) + break; + + if ((ifreq.ifr_flags & IFF_UP) + && ifr->ifr_addr.sa_family == AF_INET) + return 1; + } + } + return 0; +} + +static enum clnt_stat +clntudp_call ( + CLIENT *cl, /* client handle */ + u_long proc, /* procedure number */ + xdrproc_t xargs, /* xdr routine for args */ + caddr_t argsp, /* pointer to args */ + xdrproc_t xresults, /* xdr routine for results */ + caddr_t resultsp, /* pointer to results */ + struct timeval utimeout /* seconds to wait before giving up */) +{ + struct cu_data *cu = (struct cu_data *) cl->cl_private; + XDR *xdrs; + int outlen = 0; + int inlen; + socklen_t fromlen; + struct pollfd fd; + int milliseconds = (cu->cu_wait.tv_sec * 1000) + + (cu->cu_wait.tv_usec / 1000); + struct sockaddr_in from; + struct rpc_msg reply_msg; + XDR reply_xdrs; + struct timeval time_waited; + bool_t ok; + int nrefreshes = 2; /* number of times to refresh cred */ + struct timeval timeout; + int anyup; /* any network interface up */ + + if (cu->cu_total.tv_usec == -1) + { + timeout = utimeout; /* use supplied timeout */ + } + else + { + timeout = cu->cu_total; /* use default timeout */ + } + + time_waited.tv_sec = 0; + time_waited.tv_usec = 0; +call_again: + xdrs = &(cu->cu_outxdrs); + if (xargs == NULL) + goto get_reply; + xdrs->x_op = XDR_ENCODE; + XDR_SETPOS (xdrs, cu->cu_xdrpos); + /* + * the transaction is the first thing in the out buffer + */ + (*(uint32_t *) (cu->cu_outbuf))++; + if ((!XDR_PUTLONG (xdrs, (long *) &proc)) || + (!AUTH_MARSHALL (cl->cl_auth, xdrs)) || + (!(*xargs) (xdrs, argsp))) + return (cu->cu_error.re_status = RPC_CANTENCODEARGS); + outlen = (int) XDR_GETPOS (xdrs); + +send_again: + if (sendto (cu->cu_sock, cu->cu_outbuf, outlen, 0, + (struct sockaddr *) &(cu->cu_raddr), cu->cu_rlen) + != outlen) + { + cu->cu_error.re_errno = errno; + return (cu->cu_error.re_status = RPC_CANTSEND); + } + + /* + * Hack to provide rpc-based message passing + */ + if (timeout.tv_sec == 0 && timeout.tv_usec == 0) + { + return (cu->cu_error.re_status = RPC_TIMEDOUT); + } + get_reply: + /* + * sub-optimal code appears here because we have + * some clock time to spare while the packets are in flight. + * (We assume that this is actually only executed once.) + */ + reply_msg.acpted_rply.ar_verf = _null_auth; + reply_msg.acpted_rply.ar_results.where = resultsp; + reply_msg.acpted_rply.ar_results.proc = xresults; + fd.fd = cu->cu_sock; + fd.events = POLLIN; + anyup = 0; + for (;;) + { + switch (poll (&fd, 1, milliseconds)) + { + + case 0: + if (anyup == 0) + { + anyup = is_network_up (cu->cu_sock); + if (!anyup) + return (cu->cu_error.re_status = RPC_CANTRECV); + } + + time_waited.tv_sec += cu->cu_wait.tv_sec; + time_waited.tv_usec += cu->cu_wait.tv_usec; + while (time_waited.tv_usec >= 1000000) + { + time_waited.tv_sec++; + time_waited.tv_usec -= 1000000; + } + if ((time_waited.tv_sec < timeout.tv_sec) || + ((time_waited.tv_sec == timeout.tv_sec) && + (time_waited.tv_usec < timeout.tv_usec))) + goto send_again; + return (cu->cu_error.re_status = RPC_TIMEDOUT); + + /* + * buggy in other cases because time_waited is not being + * updated. + */ + case -1: + if (errno == EINTR) + continue; + cu->cu_error.re_errno = errno; + return (cu->cu_error.re_status = RPC_CANTRECV); + } +#ifdef IP_RECVERR + if (fd.revents & POLLERR) + { + struct msghdr msg; + struct cmsghdr *cmsg; + struct sock_extended_err *e; + struct sockaddr_in err_addr; + struct iovec iov; + char *cbuf = (char *) alloca (outlen + 256); + int ret; + + iov.iov_base = cbuf + 256; + iov.iov_len = outlen; + msg.msg_name = (void *) &err_addr; + msg.msg_namelen = sizeof (err_addr); + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_flags = 0; + msg.msg_control = cbuf; + msg.msg_controllen = 256; + ret = recvmsg (cu->cu_sock, &msg, MSG_ERRQUEUE); + if (ret >= 0 + && memcmp (cbuf + 256, cu->cu_outbuf, ret) == 0 + && (msg.msg_flags & MSG_ERRQUEUE) + && ((msg.msg_namelen == 0 + && ret >= 12) + || (msg.msg_namelen == sizeof (err_addr) + && err_addr.sin_family == AF_INET + && memcmp (&err_addr.sin_addr, &cu->cu_raddr.sin_addr, + sizeof (err_addr.sin_addr)) == 0 + && err_addr.sin_port == cu->cu_raddr.sin_port))) + for (cmsg = CMSG_FIRSTHDR (&msg); cmsg; + cmsg = CMSG_NXTHDR (&msg, cmsg)) + if (cmsg->cmsg_level == SOL_IP && cmsg->cmsg_type == IP_RECVERR) + { + e = (struct sock_extended_err *) CMSG_DATA(cmsg); + cu->cu_error.re_errno = e->ee_errno; + return (cu->cu_error.re_status = RPC_CANTRECV); + } + } +#endif + do + { + fromlen = sizeof (struct sockaddr); + inlen = recvfrom (cu->cu_sock, cu->cu_inbuf, + (int) cu->cu_recvsz, 0, + (struct sockaddr *) &from, &fromlen); + } + while (inlen < 0 && errno == EINTR); + if (inlen < 0) + { + if (errno == EWOULDBLOCK) + continue; + cu->cu_error.re_errno = errno; + return (cu->cu_error.re_status = RPC_CANTRECV); + } + if (inlen < 4) + continue; + + /* see if reply transaction id matches sent id. + Don't do this if we only wait for a replay */ + if (xargs != NULL + && (*((u_int32_t *) (cu->cu_inbuf)) + != *((u_int32_t *) (cu->cu_outbuf)))) + continue; + /* we now assume we have the proper reply */ + break; + } + + /* + * now decode and validate the response + */ + xdrmem_create (&reply_xdrs, cu->cu_inbuf, (u_int) inlen, XDR_DECODE); + ok = xdr_replymsg (&reply_xdrs, &reply_msg); + /* XDR_DESTROY(&reply_xdrs); save a few cycles on noop destroy */ + if (ok) + { + _seterr_reply (&reply_msg, &(cu->cu_error)); + if (cu->cu_error.re_status == RPC_SUCCESS) + { + if (!AUTH_VALIDATE (cl->cl_auth, + &reply_msg.acpted_rply.ar_verf)) + { + cu->cu_error.re_status = RPC_AUTHERROR; + cu->cu_error.re_why = AUTH_INVALIDRESP; + } + if (reply_msg.acpted_rply.ar_verf.oa_base != NULL) + { + xdrs->x_op = XDR_FREE; + (void) xdr_opaque_auth (xdrs, + &(reply_msg.acpted_rply.ar_verf)); + } + } /* end successful completion */ + else + { + /* maybe our credentials need to be refreshed ... */ + if (nrefreshes > 0 && AUTH_REFRESH (cl->cl_auth)) + { + nrefreshes--; + goto call_again; + } + } /* end of unsuccessful completion */ + } /* end of valid reply message */ + else + { + cu->cu_error.re_status = RPC_CANTDECODERES; + } + return cu->cu_error.re_status; +} + +static void +clntudp_geterr (CLIENT *cl, struct rpc_err *errp) +{ + struct cu_data *cu = (struct cu_data *) cl->cl_private; + + *errp = cu->cu_error; +} + + +static bool_t +clntudp_freeres (CLIENT *cl, xdrproc_t xdr_res, caddr_t res_ptr) +{ + struct cu_data *cu = (struct cu_data *) cl->cl_private; + XDR *xdrs = &(cu->cu_outxdrs); + + xdrs->x_op = XDR_FREE; + return (*xdr_res) (xdrs, res_ptr); +} + +static void +clntudp_abort (void) +{ +} + +static bool_t +clntudp_control (CLIENT *cl, int request, char *info) +{ + struct cu_data *cu = (struct cu_data *) cl->cl_private; + + switch (request) + { + case CLSET_FD_CLOSE: + cu->cu_closeit = TRUE; + break; + case CLSET_FD_NCLOSE: + cu->cu_closeit = FALSE; + break; + case CLSET_TIMEOUT: + cu->cu_total = *(struct timeval *) info; + break; + case CLGET_TIMEOUT: + *(struct timeval *) info = cu->cu_total; + break; + case CLSET_RETRY_TIMEOUT: + cu->cu_wait = *(struct timeval *) info; + break; + case CLGET_RETRY_TIMEOUT: + *(struct timeval *) info = cu->cu_wait; + break; + case CLGET_SERVER_ADDR: + *(struct sockaddr_in *) info = cu->cu_raddr; + break; + case CLGET_FD: + *(int *)info = cu->cu_sock; + break; + case CLGET_XID: + /* + * use the knowledge that xid is the + * first element in the call structure *. + * This will get the xid of the PREVIOUS call + */ + *(u_long *)info = ntohl(*(u_long *)cu->cu_outbuf); + break; + case CLSET_XID: + /* This will set the xid of the NEXT call */ + *(u_long *)cu->cu_outbuf = htonl(*(u_long *)info - 1); + /* decrement by 1 as clntudp_call() increments once */ + case CLGET_VERS: + /* + * This RELIES on the information that, in the call body, + * the version number field is the fifth field from the + * begining of the RPC header. MUST be changed if the + * call_struct is changed + */ + *(u_long *)info = ntohl(*(u_long *)(cu->cu_outbuf + + 4 * BYTES_PER_XDR_UNIT)); + break; + case CLSET_VERS: + *(u_long *)(cu->cu_outbuf + 4 * BYTES_PER_XDR_UNIT) + = htonl(*(u_long *)info); + break; + case CLGET_PROG: + /* + * This RELIES on the information that, in the call body, + * the program number field is the field from the + * begining of the RPC header. MUST be changed if the + * call_struct is changed + */ + *(u_long *)info = ntohl(*(u_long *)(cu->cu_outbuf + + 3 * BYTES_PER_XDR_UNIT)); + break; + case CLSET_PROG: + *(u_long *)(cu->cu_outbuf + 3 * BYTES_PER_XDR_UNIT) + = htonl(*(u_long *)info); + break; + /* The following are only possible with TI-RPC */ + case CLGET_SVC_ADDR: + case CLSET_SVC_ADDR: + case CLSET_PUSH_TIMOD: + case CLSET_POP_TIMOD: + default: + return FALSE; + } + return TRUE; +} + +static void +clntudp_destroy (CLIENT *cl) +{ + struct cu_data *cu = (struct cu_data *) cl->cl_private; + + if (cu->cu_closeit) + { + (void) close (cu->cu_sock); + } + XDR_DESTROY (&(cu->cu_outxdrs)); + mem_free ((caddr_t) cu, (sizeof (*cu) + cu->cu_sendsz + cu->cu_recvsz)); + mem_free ((caddr_t) cl, sizeof (CLIENT)); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/clnt_unix.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/clnt_unix.c new file mode 100644 index 00000000..c7756f70 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/clnt_unix.c @@ -0,0 +1,600 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +/* + * clnt_unix.c, Implements a TCP/IP based, client side RPC. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + * + * TCP based RPC supports 'batched calls'. + * A sequence of calls may be batched-up in a send buffer. The rpc call + * return immediately to the client even though the call was not necessarily + * sent. The batching occurs if the results' xdr routine is NULL (0) AND + * the rpc timeout value is zero (see clnt.h, rpc). + * + * Clients should NOT casually batch calls that in fact return results; that is, + * the server side should be aware that a call is batched and not produce any + * return message. Batched calls that produce many result messages can + * deadlock (netlock) the client and the server.... + * + * Now go hang yourself. + */ + +#define __FORCE_GLIBC +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef USE_IN_LIBIO +# include +#endif + + +extern u_long _create_xid (void) attribute_hidden; + +#define MCALL_MSG_SIZE 24 + +struct ct_data + { + int ct_sock; + bool_t ct_closeit; + struct timeval ct_wait; + bool_t ct_waitset; /* wait set by clnt_control? */ + struct sockaddr_un ct_addr; + struct rpc_err ct_error; + char ct_mcall[MCALL_MSG_SIZE]; /* marshalled callmsg */ + u_int ct_mpos; /* pos after marshal */ + XDR ct_xdrs; + }; + +static int readunix (char *, char *, int); +static int writeunix (char *, char *, int); + +static enum clnt_stat clntunix_call (CLIENT *, u_long, xdrproc_t, caddr_t, + xdrproc_t, caddr_t, struct timeval); +static void clntunix_abort (void); +static void clntunix_geterr (CLIENT *, struct rpc_err *); +static bool_t clntunix_freeres (CLIENT *, xdrproc_t, caddr_t); +static bool_t clntunix_control (CLIENT *, int, char *); +static void clntunix_destroy (CLIENT *); + +static const struct clnt_ops unix_ops = +{ + clntunix_call, + clntunix_abort, + clntunix_geterr, + clntunix_freeres, + clntunix_destroy, + clntunix_control +}; + +/* + * Create a client handle for a tcp/ip connection. + * If *sockp<0, *sockp is set to a newly created TCP socket and it is + * connected to raddr. If *sockp non-negative then + * raddr is ignored. The rpc/tcp package does buffering + * similar to stdio, so the client must pick send and receive buffer sizes,]; + * 0 => use the default. + * If raddr->sin_port is 0, then a binder on the remote machine is + * consulted for the right port number. + * NB: *sockp is copied into a private area. + * NB: It is the clients responsibility to close *sockp. + * NB: The rpch->cl_auth is set null authentication. Caller may wish to set this + * something more useful. + */ +CLIENT * +clntunix_create (struct sockaddr_un *raddr, u_long prog, u_long vers, + int *sockp, u_int sendsz, u_int recvsz) +{ + CLIENT *h; + struct ct_data *ct = (struct ct_data *) mem_alloc (sizeof (*ct)); + struct rpc_msg call_msg; + int len; + + h = (CLIENT *) mem_alloc (sizeof (*h)); + if (h == NULL || ct == NULL) + { + struct rpc_createerr *ce = &get_rpc_createerr (); +#ifdef USE_IN_LIBIO + if (_IO_fwide (stderr, 0) > 0) + (void) fwprintf (stderr, L"%s", + _("clntunix_create: out of memory\n")); + else +#endif + (void) fputs (_("clntunix_create: out of memory\n"), stderr); + ce->cf_stat = RPC_SYSTEMERROR; + ce->cf_error.re_errno = ENOMEM; + goto fooy; + } + + /* + * If no socket given, open one + */ + if (*sockp < 0) + { + *sockp = socket (AF_UNIX, SOCK_STREAM, 0); + len = strlen (raddr->sun_path) + sizeof (raddr->sun_family) + 1; + if (*sockp < 0 + || connect (*sockp, (struct sockaddr *) raddr, len) < 0) + { + struct rpc_createerr *ce = &get_rpc_createerr (); + ce->cf_stat = RPC_SYSTEMERROR; + ce->cf_error.re_errno = errno; + if (*sockp != -1) + close (*sockp); + goto fooy; + } + ct->ct_closeit = TRUE; + } + else + { + ct->ct_closeit = FALSE; + } + + /* + * Set up private data struct + */ + ct->ct_sock = *sockp; + ct->ct_wait.tv_usec = 0; + ct->ct_waitset = FALSE; + ct->ct_addr = *raddr; + + /* + * Initialize call message + */ + call_msg.rm_xid = _create_xid (); + call_msg.rm_direction = CALL; + call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION; + call_msg.rm_call.cb_prog = prog; + call_msg.rm_call.cb_vers = vers; + + /* + * pre-serialize the static part of the call msg and stash it away + */ + xdrmem_create (&(ct->ct_xdrs), ct->ct_mcall, MCALL_MSG_SIZE, XDR_ENCODE); + if (!xdr_callhdr (&(ct->ct_xdrs), &call_msg)) + { + if (ct->ct_closeit) + close (*sockp); + goto fooy; + } + ct->ct_mpos = XDR_GETPOS (&(ct->ct_xdrs)); + XDR_DESTROY (&(ct->ct_xdrs)); + + /* + * Create a client handle which uses xdrrec for serialization + * and authnone for authentication. + */ + xdrrec_create (&(ct->ct_xdrs), sendsz, recvsz, + (caddr_t) ct, readunix, writeunix); + h->cl_ops = &unix_ops; + h->cl_private = (caddr_t) ct; + h->cl_auth = authnone_create (); + return h; + +fooy: + /* + * Something goofed, free stuff and barf + */ + mem_free ((caddr_t) ct, sizeof (struct ct_data)); + mem_free ((caddr_t) h, sizeof (CLIENT)); + return (CLIENT *) NULL; +} +libc_hidden_def(clntunix_create) + +static enum clnt_stat +clntunix_call (CLIENT *h, u_long proc, xdrproc_t xdr_args, caddr_t args_ptr, + xdrproc_t xdr_results, caddr_t results_ptr, + struct timeval timeout) +{ + struct ct_data *ct = (struct ct_data *) h->cl_private; + XDR *xdrs = &(ct->ct_xdrs); + struct rpc_msg reply_msg; + u_long x_id; + u_int32_t *msg_x_id = (u_int32_t *) (ct->ct_mcall); /* yuk */ + bool_t shipnow; + int refreshes = 2; + + if (!ct->ct_waitset) + { + ct->ct_wait = timeout; + } + + shipnow = + (xdr_results == (xdrproc_t) 0 && ct->ct_wait.tv_sec == 0 + && ct->ct_wait.tv_usec == 0) ? FALSE : TRUE; + +call_again: + xdrs->x_op = XDR_ENCODE; + ct->ct_error.re_status = RPC_SUCCESS; + x_id = ntohl (--(*msg_x_id)); + if ((!XDR_PUTBYTES (xdrs, ct->ct_mcall, ct->ct_mpos)) || + (!XDR_PUTLONG (xdrs, (long *) &proc)) || + (!AUTH_MARSHALL (h->cl_auth, xdrs)) || + (!(*xdr_args) (xdrs, args_ptr))) + { + if (ct->ct_error.re_status == RPC_SUCCESS) + ct->ct_error.re_status = RPC_CANTENCODEARGS; + (void) xdrrec_endofrecord (xdrs, TRUE); + return ct->ct_error.re_status; + } + if (!xdrrec_endofrecord (xdrs, shipnow)) + return ct->ct_error.re_status = RPC_CANTSEND; + if (!shipnow) + return RPC_SUCCESS; + /* + * Hack to provide rpc-based message passing + */ + if (ct->ct_wait.tv_sec == 0 && ct->ct_wait.tv_usec == 0) + return ct->ct_error.re_status = RPC_TIMEDOUT; + + + /* + * Keep receiving until we get a valid transaction id + */ + xdrs->x_op = XDR_DECODE; + while (TRUE) + { + reply_msg.acpted_rply.ar_verf = _null_auth; + reply_msg.acpted_rply.ar_results.where = NULL; + reply_msg.acpted_rply.ar_results.proc = (xdrproc_t)xdr_void; + if (!xdrrec_skiprecord (xdrs)) + return ct->ct_error.re_status; + /* now decode and validate the response header */ + if (!xdr_replymsg (xdrs, &reply_msg)) + { + if (ct->ct_error.re_status == RPC_SUCCESS) + continue; + return ct->ct_error.re_status; + } + if (reply_msg.rm_xid == x_id) + break; + } + + /* + * process header + */ + _seterr_reply (&reply_msg, &(ct->ct_error)); + if (ct->ct_error.re_status == RPC_SUCCESS) + { + if (!AUTH_VALIDATE (h->cl_auth, &reply_msg.acpted_rply.ar_verf)) + { + ct->ct_error.re_status = RPC_AUTHERROR; + ct->ct_error.re_why = AUTH_INVALIDRESP; + } + else if (!(*xdr_results) (xdrs, results_ptr)) + { + if (ct->ct_error.re_status == RPC_SUCCESS) + ct->ct_error.re_status = RPC_CANTDECODERES; + } + /* free verifier ... */ + if (reply_msg.acpted_rply.ar_verf.oa_base != NULL) + { + xdrs->x_op = XDR_FREE; + (void) xdr_opaque_auth (xdrs, &(reply_msg.acpted_rply.ar_verf)); + } + } /* end successful completion */ + else + { + /* maybe our credentials need to be refreshed ... */ + if (refreshes-- && AUTH_REFRESH (h->cl_auth)) + goto call_again; + } /* end of unsuccessful completion */ + return ct->ct_error.re_status; +} + +static void +clntunix_geterr (CLIENT *h, struct rpc_err *errp) +{ + struct ct_data *ct = (struct ct_data *) h->cl_private; + + *errp = ct->ct_error; +} + +static bool_t +clntunix_freeres (CLIENT *cl, xdrproc_t xdr_res, caddr_t res_ptr) +{ + struct ct_data *ct = (struct ct_data *) cl->cl_private; + XDR *xdrs = &(ct->ct_xdrs); + + xdrs->x_op = XDR_FREE; + return (*xdr_res) (xdrs, res_ptr); +} + +static void +clntunix_abort (void) +{ +} + +static bool_t +clntunix_control (CLIENT *cl, int request, char *info) +{ + struct ct_data *ct = (struct ct_data *) cl->cl_private; + + + switch (request) + { + case CLSET_FD_CLOSE: + ct->ct_closeit = TRUE; + break; + case CLSET_FD_NCLOSE: + ct->ct_closeit = FALSE; + break; + case CLSET_TIMEOUT: + ct->ct_wait = *(struct timeval *) info; + break; + case CLGET_TIMEOUT: + *(struct timeval *) info = ct->ct_wait; + break; + case CLGET_SERVER_ADDR: + *(struct sockaddr_un *) info = ct->ct_addr; + break; + case CLGET_FD: + *(int *)info = ct->ct_sock; + break; + case CLGET_XID: + /* + * use the knowledge that xid is the + * first element in the call structure *. + * This will get the xid of the PREVIOUS call + */ + *(u_long *) info = ntohl (*(u_long *)ct->ct_mcall); + break; + case CLSET_XID: + /* This will set the xid of the NEXT call */ + *(u_long *) ct->ct_mcall = htonl (*(u_long *)info - 1); + /* decrement by 1 as clntunix_call() increments once */ + case CLGET_VERS: + /* + * This RELIES on the information that, in the call body, + * the version number field is the fifth field from the + * begining of the RPC header. MUST be changed if the + * call_struct is changed + */ + *(u_long *) info = ntohl (*(u_long *) (ct->ct_mcall + + 4 * BYTES_PER_XDR_UNIT)); + break; + case CLSET_VERS: + *(u_long *) (ct->ct_mcall + 4 * BYTES_PER_XDR_UNIT) + = htonl (*(u_long *) info); + break; + case CLGET_PROG: + /* + * This RELIES on the information that, in the call body, + * the program number field is the field from the + * begining of the RPC header. MUST be changed if the + * call_struct is changed + */ + *(u_long *) info = ntohl (*(u_long *) (ct->ct_mcall + + 3 * BYTES_PER_XDR_UNIT)); + break; + case CLSET_PROG: + *(u_long *) (ct->ct_mcall + 3 * BYTES_PER_XDR_UNIT) + = htonl(*(u_long *) info); + break; + /* The following are only possible with TI-RPC */ + case CLGET_RETRY_TIMEOUT: + case CLSET_RETRY_TIMEOUT: + case CLGET_SVC_ADDR: + case CLSET_SVC_ADDR: + case CLSET_PUSH_TIMOD: + case CLSET_POP_TIMOD: + default: + return FALSE; + } + return TRUE; +} + + +static void +clntunix_destroy (CLIENT *h) +{ + struct ct_data *ct = + (struct ct_data *) h->cl_private; + + if (ct->ct_closeit) + { + (void) close (ct->ct_sock); + } + XDR_DESTROY (&(ct->ct_xdrs)); + mem_free ((caddr_t) ct, sizeof (struct ct_data)); + mem_free ((caddr_t) h, sizeof (CLIENT)); +} + +static int +__msgread (int sock, void *data, size_t cnt) +{ + struct iovec iov; + struct msghdr msg; +#ifdef SCM_CREDENTIALS + /*static -why??*/ char cm[CMSG_SPACE(sizeof (struct ucred))]; +#endif + int len; + + iov.iov_base = data; + iov.iov_len = cnt; + + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_name = NULL; + msg.msg_namelen = 0; +#ifdef SCM_CREDENTIALS + msg.msg_control = (caddr_t) &cm; + msg.msg_controllen = CMSG_SPACE(sizeof (struct ucred)); +#endif + msg.msg_flags = 0; + +#ifdef SO_PASSCRED + { + int on = 1; + if (setsockopt (sock, SOL_SOCKET, SO_PASSCRED, &on, sizeof (on))) + return -1; + } +#endif + + restart: + len = recvmsg (sock, &msg, 0); + if (len >= 0) + { + if (msg.msg_flags & MSG_CTRUNC || len == 0) + return 0; + else + return len; + } + if (errno == EINTR) + goto restart; + return -1; +} + +static int +__msgwrite (int sock, void *data, size_t cnt) +{ +#ifndef SCM_CREDENTIALS + /* We cannot implement this reliably. */ + __set_errno (ENOSYS); + return -1; +#else + struct iovec iov; + struct msghdr msg; + struct cmsghdr *cmsg = alloca (CMSG_SPACE(sizeof (struct ucred))); + struct ucred cred; + int len; + + /* XXX I'm not sure, if gete?id() is always correct, or if we should use + get?id(). But since keyserv needs geteuid(), we have no other chance. + It would be much better, if the kernel could pass both to the server. */ + cred.pid = getpid (); + cred.uid = geteuid (); + cred.gid = getegid (); + + memcpy (CMSG_DATA(cmsg), &cred, sizeof (struct ucred)); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_CREDENTIALS; + cmsg->cmsg_len = sizeof(*cmsg) + sizeof(struct ucred); + + iov.iov_base = data; + iov.iov_len = cnt; + + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_name = NULL; + msg.msg_namelen = 0; + msg.msg_control = cmsg; + msg.msg_controllen = CMSG_ALIGN(cmsg->cmsg_len); + msg.msg_flags = 0; + + restart: + len = sendmsg (sock, &msg, 0); + if (len >= 0) + return len; + if (errno == EINTR) + goto restart; + return -1; + +#endif +} + + +/* + * Interface between xdr serializer and unix connection. + * Behaves like the system calls, read & write, but keeps some error state + * around for the rpc level. + */ +static int +readunix (char *ctptr, char *buf, int len) +{ + struct ct_data *ct = (struct ct_data *) ctptr; + struct pollfd fd; + int milliseconds = ((ct->ct_wait.tv_sec * 1000) + + (ct->ct_wait.tv_usec / 1000)); + + if (len == 0) + return 0; + + fd.fd = ct->ct_sock; + fd.events = POLLIN; + while (TRUE) + { + switch (poll (&fd, 1, milliseconds)) + { + case 0: + ct->ct_error.re_status = RPC_TIMEDOUT; + return -1; + + case -1: + if (errno == EINTR) + continue; + ct->ct_error.re_status = RPC_CANTRECV; + ct->ct_error.re_errno = errno; + return -1; + } + break; + } + switch (len = __msgread (ct->ct_sock, buf, len)) + { + + case 0: + /* premature eof */ + ct->ct_error.re_errno = ECONNRESET; + ct->ct_error.re_status = RPC_CANTRECV; + len = -1; /* it's really an error */ + break; + + case -1: + ct->ct_error.re_errno = errno; + ct->ct_error.re_status = RPC_CANTRECV; + break; + } + return len; +} + +static int +writeunix (char *ctptr, char *buf, int len) +{ + int i, cnt; + struct ct_data *ct = (struct ct_data *) ctptr; + + for (cnt = len; cnt > 0; cnt -= i, buf += i) + { + if ((i = __msgwrite (ct->ct_sock, buf, cnt)) == -1) + { + ct->ct_error.re_errno = errno; + ct->ct_error.re_status = RPC_CANTSEND; + return -1; + } + } + return len; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/create_xid.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/create_xid.c new file mode 100644 index 00000000..3b4e8c08 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/create_xid.c @@ -0,0 +1,58 @@ +/* Copyright (c) 1998, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Thorsten Kukuk , 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define __FORCE_GLIBC +#include + +#include +#include +#include +#include + + +/* The RPC code is not threadsafe, but new code should be threadsafe. */ + +#include +__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_MUTEX_INITIALIZER); + +static smallint is_initialized; +static struct drand48_data __rpc_lrand48_data; + +u_long _create_xid (void) attribute_hidden; +u_long _create_xid (void) +{ + long res; + + __UCLIBC_MUTEX_LOCK(mylock); + + if (!is_initialized) + { + struct timeval now; + + gettimeofday (&now, (struct timezone *) 0); + srand48_r (now.tv_sec ^ now.tv_usec, &__rpc_lrand48_data); + is_initialized = 1; + } + + lrand48_r (&__rpc_lrand48_data, &res); + + __UCLIBC_MUTEX_UNLOCK(mylock); + + return res; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/errqueue.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/errqueue.h new file mode 100644 index 00000000..9ed6dc62 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/errqueue.h @@ -0,0 +1,46 @@ +/* Copyright (C) 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Linux version. */ + +#ifndef _BITS_ERRQUEUE_H +#define _BITS_ERRQUEUE_H 1 + +#include +#include + +struct sock_extended_err + { + u_int32_t ee_errno; + u_int8_t ee_origin; + u_int8_t ee_type; + u_int8_t ee_code; + u_int8_t ee_pad; + u_int32_t ee_info; + u_int32_t ee_data; + }; + +#define SO_EE_ORIGIN_NONE 0 +#define SO_EE_ORIGIN_LOCAL 1 +#define SO_EE_ORIGIN_ICMP 2 +#define SO_EE_ORIGIN_ICMP6 3 + +#define SO_EE_OFFENDER(see) \ + ((struct sockaddr *)(((struct sock_extended_err)(see))+1)) + +#endif /* bits/errqueue.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/get_myaddress.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/get_myaddress.c new file mode 100644 index 00000000..ab4ac334 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/get_myaddress.c @@ -0,0 +1,109 @@ +/* @(#)get_myaddress.c 2.1 88/07/29 4.0 RPCSRC */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +#if 0 +static char sccsid[] = "@(#)get_myaddress.c 1.4 87/08/11 Copyr 1984 Sun Micro"; +#endif + +/* + * get_myaddress.c + * + * Get client's IP address via ioctl. This avoids using the yellowpages. + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +/* Order of following two #includes reversed by roland@gnu */ +#include +#include + + +/* + * don't use gethostbyname, which would invoke yellow pages + * + * Avoid loopback interfaces. We return information from a loopback + * interface only if there are no other possible interfaces. + */ +void +get_myaddress (struct sockaddr_in *addr) +{ + int s; + char buf[BUFSIZ]; + struct ifconf ifc; + struct ifreq ifreq, *ifr; + int len, loopback = 0; + + if ((s = socket (AF_INET, SOCK_DGRAM, 0)) < 0) + { + perror ("get_myaddress: socket"); + exit (1); + } + ifc.ifc_len = sizeof (buf); + ifc.ifc_buf = buf; + if (ioctl (s, SIOCGIFCONF, (char *) &ifc) < 0) + { + perror (_("get_myaddress: ioctl (get interface configuration)")); + exit (1); + } + + again: + ifr = ifc.ifc_req; + for (len = ifc.ifc_len; len; len -= sizeof ifreq) + { + ifreq = *ifr; + if (ioctl (s, SIOCGIFFLAGS, (char *) &ifreq) < 0) + { + perror ("get_myaddress: ioctl"); + exit (1); + } + if ((ifreq.ifr_flags & IFF_UP) && (ifr->ifr_addr.sa_family == AF_INET) + && (!(ifreq.ifr_flags & IFF_LOOPBACK) || + (loopback == 1 && (ifreq.ifr_flags & IFF_LOOPBACK)))) + { + *addr = *((struct sockaddr_in *) &ifr->ifr_addr); + addr->sin_port = htons (PMAPPORT); + close (s); + return; + } + ifr++; + } + if (loopback == 0) + { + loopback = 1; + goto again; + } + close (s); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/getrpcent.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/getrpcent.c new file mode 100644 index 00000000..de20d64d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/getrpcent.c @@ -0,0 +1,347 @@ +/* @(#)getrpcent.c 2.2 88/07/29 4.0 RPCSRC */ + +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +/* + * Copyright (c) 1985 by Sun Microsystems, Inc. + */ + +#define __FORCE_GLIBC +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/* + * Internet version. + */ +static struct rpcdata { + FILE *rpcf; + char *current; + int currentlen; + int stayopen; +#define MAXALIASES 35 + char *rpc_aliases[MAXALIASES]; + struct rpcent rpc; + char line[BUFSIZ + 1]; + char *domain; +} *rpcdata; + +static const char RPCDB[] = "/etc/rpc"; + +static struct rpcdata *_rpcdata(void) +{ + register struct rpcdata *d = rpcdata; + + if (d == NULL) { + d = (struct rpcdata *) calloc(1, sizeof(struct rpcdata)); + + rpcdata = d; + } + return d; +} + +void endrpcent(void) +{ + register struct rpcdata *d = _rpcdata(); + + if (d == NULL) + return; + if (d->stayopen) + return; + free(d->current); + d->current = NULL; + if (d->rpcf) { + fclose(d->rpcf); + d->rpcf = NULL; + } +} +libc_hidden_def(endrpcent) + +void setrpcent(int f) +{ + register struct rpcdata *d = _rpcdata(); + + if (d == NULL) + return; + if (d->rpcf == NULL) + d->rpcf = fopen(RPCDB, "r"); + else + rewind(d->rpcf); + free(d->current); + d->current = NULL; + d->stayopen |= f; +} +libc_hidden_def(setrpcent) + +static struct rpcent *interpret(struct rpcdata *); + +static struct rpcent *__get_next_rpcent(struct rpcdata *d) +{ + if (fgets(d->line, BUFSIZ, d->rpcf) == NULL) + return NULL; + return interpret(d); +} + +struct rpcent *getrpcent(void) +{ + register struct rpcdata *d = _rpcdata(); + + if (d == NULL) + return NULL; + if (d->rpcf == NULL && (d->rpcf = fopen(RPCDB, "r")) == NULL) + return NULL; + return __get_next_rpcent(d); +} +libc_hidden_def(getrpcent) + +struct rpcent *getrpcbynumber(register int number) +{ + register struct rpcdata *d = _rpcdata(); + register struct rpcent *rpc; + + if (d == NULL) + return NULL; + setrpcent(0); + while ((rpc = getrpcent())) { + if (rpc->r_number == number) + break; + } + endrpcent(); + return rpc; +} +libc_hidden_def(getrpcbynumber) + +struct rpcent *getrpcbyname(const char *name) +{ + struct rpcent *rpc; + char **rp; + + setrpcent(0); + while ((rpc = getrpcent())) { + if (strcmp(rpc->r_name, name) == 0) + return rpc; + for (rp = rpc->r_aliases; *rp != NULL; rp++) { + if (strcmp(*rp, name) == 0) + return rpc; + } + } + endrpcent(); + return NULL; +} +libc_hidden_def(getrpcbyname) + +#ifdef __linux__ +static char *firstwhite(char *s) +{ + char *s1, *s2; + + s1 = strchr(s, ' '); + s2 = strchr(s, '\t'); + if (s1) { + if (s2) + return (s1 < s2) ? s1 : s2; + else + return s1; + } else + return s2; +} +#endif + +static struct rpcent *interpret(register struct rpcdata *d) +{ + char *p; + register char *cp, **q; + + p = d->line; + d->line[strlen(p)-1] = '\n'; + if (*p == '#') + return __get_next_rpcent(d); + cp = strchr(p, '#'); + if (cp == NULL) { + cp = strchr(p, '\n'); + if (cp == NULL) + return __get_next_rpcent(d); + } + *cp = '\0'; +#ifdef __linux__ + if ((cp = firstwhite(p))) + *cp++ = 0; + else + return __get_next_rpcent(d); +#else + cp = strchr(p, ' '); + if (cp == NULL) { + cp = strchr(p, '\t'); + if (cp == NULL) + return __get_next_rpcent(d); + } + *cp++ = '\0'; +#endif + /* THIS STUFF IS INTERNET SPECIFIC */ + d->rpc.r_name = d->line; + while (*cp == ' ' || *cp == '\t') + cp++; + d->rpc.r_number = atoi(cp); + q = d->rpc.r_aliases = d->rpc_aliases; +#ifdef __linux__ + if ((cp = firstwhite(cp))) + *cp++ = '\0'; +#else + cp = strchr(p, ' '); + if (cp != NULL) + *cp++ = '\0'; + else { + cp = strchr(p, '\t'); + if (cp != NULL) + *cp++ = '\0'; + } +#endif + while (cp && *cp) { + if (*cp == ' ' || *cp == '\t') { + cp++; + continue; + } + if (q < &(d->rpc_aliases[MAXALIASES - 1])) + *q++ = cp; +#ifdef __linux__ + if ((cp = firstwhite(cp))) + *cp++ = '\0'; +#else + cp = strchr(p, ' '); + if (cp != NULL) + *cp++ = '\0'; + else { + cp = strchr(p, '\t'); + if (cp != NULL) + *cp++ = '\0'; + } +#endif + } + *q = NULL; + return &d->rpc; +} + +#if defined(__UCLIBC_HAS_REENTRANT_RPC__) + +#include +__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_MUTEX_INITIALIZER); + + +static int __copy_rpcent(struct rpcent *r, struct rpcent *result_buf, char *buffer, + size_t buflen, struct rpcent **result) +{ + size_t i, s; + + *result = NULL; + + if (!r) + return ENOENT; + + /* copy the struct from the shared mem */ + memset(result_buf, 0x00, sizeof(*result_buf)); + memset(buffer, 0x00, buflen); + + result_buf->r_number = r->r_number; + + /* copy the aliases ... need to not only copy the alias strings, + * but the array of pointers to the alias strings */ + i = 0; + while (r->r_aliases[i++]) ; + + s = i-- * sizeof(char*); + if (buflen < s) + goto err_out; + result_buf->r_aliases = (char**)buffer; + buffer += s; + buflen -= s; + + while (i-- > 0) { + s = strlen(r->r_aliases[i]) + 1; + if (buflen < s) + goto err_out; + result_buf->r_aliases[i] = buffer; + buffer += s; + buflen -= s; + memcpy(result_buf->r_aliases[i], r->r_aliases[i], s); + } + + /* copy the name */ + i = strlen(r->r_name); + if (buflen <= i) + goto err_out; + result_buf->r_name = buffer; + memcpy(result_buf->r_name, r->r_name, i); + + /* that was a hoot eh ? */ + *result = result_buf; + + return 0; +err_out: + return ERANGE; +} + +int getrpcbynumber_r(int number, struct rpcent *result_buf, char *buffer, + size_t buflen, struct rpcent **result) +{ + int ret; + __UCLIBC_MUTEX_LOCK(mylock); + ret = __copy_rpcent(getrpcbynumber(number), result_buf, buffer, buflen, result); + __UCLIBC_MUTEX_UNLOCK(mylock); + return ret; +} + +int getrpcbyname_r(const char *name, struct rpcent *result_buf, char *buffer, + size_t buflen, struct rpcent **result) +{ + int ret; + __UCLIBC_MUTEX_LOCK(mylock); + ret = __copy_rpcent(getrpcbyname(name), result_buf, buffer, buflen, result); + __UCLIBC_MUTEX_UNLOCK(mylock); + return ret; +} + +int getrpcent_r(struct rpcent *result_buf, char *buffer, + size_t buflen, struct rpcent **result) +{ + int ret; + __UCLIBC_MUTEX_LOCK(mylock); + ret = __copy_rpcent(getrpcent(), result_buf, buffer, buflen, result); + __UCLIBC_MUTEX_UNLOCK(mylock); + return ret; +} + +#endif /* __UCLIBC_HAS_REENTRANT_RPC__ */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/getrpcport.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/getrpcport.c new file mode 100644 index 00000000..9c4f443e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/getrpcport.c @@ -0,0 +1,78 @@ +/* @(#)getrpcport.c 2.1 88/07/29 4.0 RPCSRC */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +#if 0 +static char sccsid[] = "@(#)getrpcport.c 1.3 87/08/11 SMI"; +#endif + +/* + * Copyright (c) 1985 by Sun Microsystems, Inc. + */ + +#define __FORCE_GLIBC +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +int +getrpcport (const char *host, u_long prognum, u_long versnum, u_int proto) +{ + struct sockaddr_in addr; + struct hostent hostbuf, *hp; + size_t buflen; + char *buffer; + int herr; + + buflen = 1024; + buffer = alloca (buflen); + while (gethostbyname_r (host, &hostbuf, buffer, buflen, &hp, &herr) != 0 + || hp == NULL) + if (herr != NETDB_INTERNAL || errno != ERANGE) + return 0; + else + { + /* Enlarge the buffer. */ + buflen *= 2; + buffer = alloca (buflen); + } + + memcpy ((char *) &addr.sin_addr, hp->h_addr, hp->h_length); + addr.sin_family = AF_INET; + addr.sin_port = 0; + return pmap_getport (&addr, prognum, versnum, proto); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/pm_getmaps.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/pm_getmaps.c new file mode 100644 index 00000000..e7b97e63 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/pm_getmaps.c @@ -0,0 +1,84 @@ +/* @(#)pmap_getmaps.c 2.2 88/08/01 4.0 RPCSRC */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +#if 0 +static char sccsid[] = "@(#)pmap_getmaps.c 1.10 87/08/11 Copyr 1984 Sun Micro"; +#endif + +/* + * pmap_getmap.c + * Client interface to pmap rpc service. + * contains pmap_getmaps, which is only tcp service involved + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + + +/* + * Get a copy of the current port maps. + * Calls the pmap service remotely to do get the maps. + */ +struct pmaplist * +pmap_getmaps (struct sockaddr_in *address) +{ + struct pmaplist *head = (struct pmaplist *) NULL; + int _socket = -1; + struct timeval minutetimeout; + CLIENT *client; + + minutetimeout.tv_sec = 60; + minutetimeout.tv_usec = 0; + address->sin_port = htons (PMAPPORT); + + /* Don't need a reserved port to get ports from the portmapper. */ + client = clnttcp_create (address, PMAPPROG, + PMAPVERS, &_socket, 50, 500); + if (client != (CLIENT *) NULL) + { + if (CLNT_CALL (client, PMAPPROC_DUMP, (xdrproc_t)xdr_void, NULL, + (xdrproc_t)xdr_pmaplist, (caddr_t)&head, + minutetimeout) != RPC_SUCCESS) + { + clnt_perror (client, _("pmap_getmaps rpc problem")); + } + CLNT_DESTROY (client); + } + /* (void)__close(_socket); CLNT_DESTROY already closed it */ + address->sin_port = 0; + return head; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/pm_getport.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/pm_getport.c new file mode 100644 index 00000000..8a427612 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/pm_getport.c @@ -0,0 +1,94 @@ +/* @(#)pmap_getport.c 2.2 88/08/01 4.0 RPCSRC */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +#if 0 +static char sccsid[] = "@(#)pmap_getport.c 1.9 87/08/11 Copyr 1984 Sun Micro"; +#endif + +/* + * pmap_getport.c + * Client interface to pmap rpc service. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +#include +#include +#include +#include +#include + + +static const struct timeval timeout = +{5, 0}; +static const struct timeval tottimeout = +{60, 0}; + +/* + * Find the mapped port for program,version. + * Calls the pmap service remotely to do the lookup. + * Returns 0 if no map exists. + */ +u_short +pmap_getport (struct sockaddr_in *address, u_long program, u_long version, + u_int protocol) +{ + u_short port = 0; + int _socket = -1; + CLIENT *client; + struct pmap parms; + + address->sin_port = htons (PMAPPORT); + client = clntudp_bufcreate (address, PMAPPROG, + PMAPVERS, timeout, &_socket, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE); + if (client != (CLIENT *) NULL) + { + struct rpc_createerr *ce = &get_rpc_createerr (); + parms.pm_prog = program; + parms.pm_vers = version; + parms.pm_prot = protocol; + parms.pm_port = 0; /* not needed or used */ + if (CLNT_CALL (client, PMAPPROC_GETPORT, (xdrproc_t)xdr_pmap, + (caddr_t)&parms, (xdrproc_t)xdr_u_short, + (caddr_t)&port, tottimeout) != RPC_SUCCESS) + { + ce->cf_stat = RPC_PMAPFAILURE; + clnt_geterr (client, &ce->cf_error); + } + else if (port == 0) + { + ce->cf_stat = RPC_PROGNOTREGISTERED; + } + CLNT_DESTROY (client); + } + /* (void)__close(_socket); CLNT_DESTROY already closed it */ + address->sin_port = 0; + return port; +} +libc_hidden_def(pmap_getport) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/pmap_clnt.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/pmap_clnt.c new file mode 100644 index 00000000..c35a2e97 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/pmap_clnt.c @@ -0,0 +1,176 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +/* + * Copyright (C) 1984, Sun Microsystems, Inc. + */ +/* + * pmap_clnt.c + * Client interface to pmap rpc service. + */ + +#define __FORCE_GLIBC +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/* + * Same as get_myaddress, but we try to use the loopback + * interface. portmap caches interfaces, and on DHCP clients, + * it could be that only loopback is started at this time. + */ +static bool_t +__get_myaddress (struct sockaddr_in *addr) +{ + int s; + char buf[BUFSIZ]; + struct ifconf ifc; + struct ifreq ifreq, *ifr; + int len, loopback = 1; + + if ((s = socket (AF_INET, SOCK_DGRAM, 0)) < 0) + { + perror ("__get_myaddress: socket"); + exit (1); + } + ifc.ifc_len = sizeof (buf); + ifc.ifc_buf = buf; + if (ioctl (s, SIOCGIFCONF, (char *) &ifc) < 0) + { + perror (_("__get_myaddress: ioctl (get interface configuration)")); + exit (1); + } + + again: + ifr = ifc.ifc_req; + for (len = ifc.ifc_len; len; len -= sizeof ifreq) + { + ifreq = *ifr; + if (ioctl (s, SIOCGIFFLAGS, (char *) &ifreq) < 0) + { + perror ("__get_myaddress: ioctl"); + exit (1); + } + if ((ifreq.ifr_flags & IFF_UP) && (ifr->ifr_addr.sa_family == AF_INET) + && ((ifreq.ifr_flags & IFF_LOOPBACK) || (loopback == 0))) + { + *addr = *((struct sockaddr_in *) &ifr->ifr_addr); + addr->sin_port = htons (PMAPPORT); + close (s); + return TRUE; + } + ifr++; + } + if (loopback == 1) + { + loopback = 0; + goto again; + } + close (s); + return FALSE; +} + + +static const struct timeval timeout = {5, 0}; +static const struct timeval tottimeout = {60, 0}; + +/* + * Set a mapping between program,version and port. + * Calls the pmap service remotely to do the mapping. + */ +bool_t +pmap_set (u_long program, u_long version, int protocol, u_short port) +{ + struct sockaddr_in myaddress; + int _socket = -1; + CLIENT *client; + struct pmap parms; + bool_t rslt; + + if (!__get_myaddress (&myaddress)) + return FALSE; + client = clntudp_bufcreate (&myaddress, PMAPPROG, PMAPVERS, + timeout, &_socket, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE); + if (client == (CLIENT *) NULL) + return (FALSE); + parms.pm_prog = program; + parms.pm_vers = version; + parms.pm_prot = protocol; + parms.pm_port = port; + if (CLNT_CALL (client, PMAPPROC_SET, (xdrproc_t)xdr_pmap, (caddr_t)&parms, + (xdrproc_t)xdr_bool, (caddr_t)&rslt, + tottimeout) != RPC_SUCCESS) + { + clnt_perror (client, _("Cannot register service")); + rslt = FALSE; + } + CLNT_DESTROY (client); + /* (void)close(_socket); CLNT_DESTROY closes it */ + return rslt; +} +libc_hidden_def (pmap_set) + +/* + * Remove the mapping between program,version and port. + * Calls the pmap service remotely to do the un-mapping. + */ +bool_t +pmap_unset (u_long program, u_long version) +{ + struct sockaddr_in myaddress; + int _socket = -1; + CLIENT *client; + struct pmap parms; + bool_t rslt; + + if (!__get_myaddress (&myaddress)) + return FALSE; + client = clntudp_bufcreate (&myaddress, PMAPPROG, PMAPVERS, + timeout, &_socket, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE); + if (client == (CLIENT *) NULL) + return FALSE; + parms.pm_prog = program; + parms.pm_vers = version; + parms.pm_port = parms.pm_prot = 0; + CLNT_CALL (client, PMAPPROC_UNSET, (xdrproc_t)xdr_pmap, (caddr_t)&parms, + (xdrproc_t)xdr_bool, (caddr_t)&rslt, tottimeout); + CLNT_DESTROY (client); + /* (void)close(_socket); CLNT_DESTROY already closed it */ + return rslt; +} +libc_hidden_def (pmap_unset) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/pmap_prot.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/pmap_prot.c new file mode 100644 index 00000000..342dbad0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/pmap_prot.c @@ -0,0 +1,56 @@ +/* @(#)pmap_prot.c 2.1 88/07/29 4.0 RPCSRC */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +#if 0 +static char sccsid[] = "@(#)pmap_prot.c 1.17 87/08/11 Copyr 1984 Sun Micro"; +#endif + +/* + * pmap_prot.c + * Protocol for the local binder service, or pmap. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +#include +#include +#include + + +bool_t +xdr_pmap (XDR *xdrs, struct pmap *regs) +{ + + if (xdr_u_long (xdrs, ®s->pm_prog) && + xdr_u_long (xdrs, ®s->pm_vers) && + xdr_u_long (xdrs, ®s->pm_prot)) + return xdr_u_long (xdrs, ®s->pm_port); + return FALSE; +} +libc_hidden_def(xdr_pmap) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/pmap_prot2.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/pmap_prot2.c new file mode 100644 index 00000000..f383757e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/pmap_prot2.c @@ -0,0 +1,117 @@ +/* @(#)pmap_prot2.c 2.1 88/07/29 4.0 RPCSRC */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +#if 0 +static char sccsid[] = "@(#)pmap_prot2.c 1.3 87/08/11 Copyr 1984 Sun Micro"; +#endif + +/* + * pmap_prot2.c + * Protocol for the local binder service, or pmap. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +#include +#include +#include + + +/* + * What is going on with linked lists? (!) + * First recall the link list declaration from pmap_prot.h: + * + * struct pmaplist { + * struct pmap pml_map; + * struct pmaplist *pml_map; + * }; + * + * Compare that declaration with a corresponding xdr declaration that + * is (a) pointer-less, and (b) recursive: + * + * typedef union switch (bool_t) { + * + * case TRUE: struct { + * struct pmap; + * pmaplist_t foo; + * }; + * + * case FALSE: struct {}; + * } pmaplist_t; + * + * Notice that the xdr declaration has no nxt pointer while + * the C declaration has no bool_t variable. The bool_t can be + * interpreted as ``more data follows me''; if FALSE then nothing + * follows this bool_t; if TRUE then the bool_t is followed by + * an actual struct pmap, and then (recursively) by the + * xdr union, pamplist_t. + * + * This could be implemented via the xdr_union primitive, though this + * would cause a one recursive call per element in the list. Rather than do + * that we can ``unwind'' the recursion + * into a while loop and do the union arms in-place. + * + * The head of the list is what the C programmer wishes to past around + * the net, yet is the data that the pointer points to which is interesting; + * this sounds like a job for xdr_reference! + */ +bool_t +xdr_pmaplist (XDR *xdrs, struct pmaplist **rp) +{ + /* + * more_elements is pre-computed in case the direction is + * XDR_ENCODE or XDR_FREE. more_elements is overwritten by + * xdr_bool when the direction is XDR_DECODE. + */ + bool_t more_elements; + int freeing = (xdrs->x_op == XDR_FREE); + struct pmaplist **next = NULL; + + while (TRUE) + { + more_elements = (bool_t) (*rp != NULL); + if (!xdr_bool (xdrs, &more_elements)) + return FALSE; + if (!more_elements) + return TRUE; /* we are done */ + /* + * the unfortunate side effect of non-recursion is that in + * the case of freeing we must remember the next object + * before we free the current object ... + */ + if (freeing) + next = &((*rp)->pml_next); + if (!xdr_reference (xdrs, (caddr_t *) rp, + (u_int) sizeof (struct pmaplist), + (xdrproc_t) xdr_pmap)) + return FALSE; + rp = freeing ? next : &((*rp)->pml_next); + } +} +libc_hidden_def(xdr_pmaplist) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/pmap_rmt.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/pmap_rmt.c new file mode 100644 index 00000000..f9dd6e72 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/pmap_rmt.c @@ -0,0 +1,412 @@ +/* @(#)pmap_rmt.c 2.2 88/08/01 4.0 RPCSRC */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +#if 0 +static char sccsid[] = "@(#)pmap_rmt.c 1.21 87/08/27 Copyr 1984 Sun Micro"; +#endif + +/* + * pmap_rmt.c + * Client interface to pmap rpc service. + * remote call and broadcast service + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +#define __FORCE_GLIBC +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#undef _POSIX_SOURCE /* Ultrix needs --roland@gnu */ +#include /* Ultrix needs before net/if --roland@gnu */ +#include +#include +#include +#define MAX_BROADCAST_SIZE 1400 + + + +extern u_long _create_xid (void) attribute_hidden; + +static const struct timeval timeout = {3, 0}; + +/* + * pmapper remote-call-service interface. + * This routine is used to call the pmapper remote call service + * which will look up a service program in the port maps, and then + * remotely call that routine with the given parameters. This allows + * programs to do a lookup and call in one step. + */ +enum clnt_stat +pmap_rmtcall (struct sockaddr_in *addr, u_long prog, u_long vers, u_long proc, + xdrproc_t xdrargs, caddr_t argsp, xdrproc_t xdrres, caddr_t resp, + struct timeval tout, u_long *port_ptr) +{ + int _socket = -1; + CLIENT *client; + struct rmtcallargs a; + struct rmtcallres r; + enum clnt_stat stat; + + addr->sin_port = htons (PMAPPORT); + client = clntudp_create (addr, PMAPPROG, PMAPVERS, timeout, &_socket); + if (client != (CLIENT *) NULL) + { + a.prog = prog; + a.vers = vers; + a.proc = proc; + a.args_ptr = argsp; + a.xdr_args = xdrargs; + r.port_ptr = port_ptr; + r.results_ptr = resp; + r.xdr_results = xdrres; + stat = CLNT_CALL (client, PMAPPROC_CALLIT, (xdrproc_t)xdr_rmtcall_args, + (caddr_t)&a, (xdrproc_t)xdr_rmtcallres, + (caddr_t)&r, tout); + CLNT_DESTROY (client); + } + else + { + stat = RPC_FAILED; + } + /* (void)close(_socket); CLNT_DESTROY already closed it */ + addr->sin_port = 0; + return stat; +} + + +/* + * XDR remote call arguments + * written for XDR_ENCODE direction only + */ +bool_t +xdr_rmtcall_args (XDR *xdrs, struct rmtcallargs *cap) +{ + u_int lenposition, argposition, position; + + if (xdr_u_long (xdrs, &(cap->prog)) && + xdr_u_long (xdrs, &(cap->vers)) && + xdr_u_long (xdrs, &(cap->proc))) + { + u_long dummy_arglen = 0; + lenposition = XDR_GETPOS (xdrs); + if (!xdr_u_long (xdrs, &dummy_arglen)) + return FALSE; + argposition = XDR_GETPOS (xdrs); + if (!(*(cap->xdr_args)) (xdrs, cap->args_ptr)) + return FALSE; + position = XDR_GETPOS (xdrs); + cap->arglen = (u_long) position - (u_long) argposition; + XDR_SETPOS (xdrs, lenposition); + if (!xdr_u_long (xdrs, &(cap->arglen))) + return FALSE; + XDR_SETPOS (xdrs, position); + return TRUE; + } + return FALSE; +} +libc_hidden_def(xdr_rmtcall_args) + +/* + * XDR remote call results + * written for XDR_DECODE direction only + */ +bool_t +xdr_rmtcallres (XDR *xdrs, struct rmtcallres *crp) +{ + caddr_t port_ptr; + + port_ptr = (caddr_t) crp->port_ptr; + if (xdr_reference (xdrs, &port_ptr, sizeof (u_long), (xdrproc_t) xdr_u_long) + && xdr_u_long (xdrs, &crp->resultslen)) + { + crp->port_ptr = (u_long *) port_ptr; + return (*(crp->xdr_results)) (xdrs, crp->results_ptr); + } + return FALSE; +} +libc_hidden_def(xdr_rmtcallres) + + +/* + * The following is kludged-up support for simple rpc broadcasts. + * Someday a large, complicated system will replace these trivial + * routines which only support udp/ip . + */ + +static int +internal_function +getbroadcastnets (struct in_addr *addrs, int sock, char *buf) + /* int sock: any valid socket will do */ + /* char *buf: why allocate more when we can use existing... */ +{ + struct ifconf ifc; + struct ifreq ifreq, *ifr; + struct sockaddr_in *sin; + int n, i; + + ifc.ifc_len = UDPMSGSIZE; + ifc.ifc_buf = buf; + if (ioctl (sock, SIOCGIFCONF, (char *) &ifc) < 0) + { + perror (_("broadcast: ioctl (get interface configuration)")); + return (0); + } + ifr = ifc.ifc_req; + for (i = 0, n = ifc.ifc_len / sizeof (struct ifreq); n > 0; n--, ifr++) + { + ifreq = *ifr; + if (ioctl (sock, SIOCGIFFLAGS, (char *) &ifreq) < 0) + { + perror (_("broadcast: ioctl (get interface flags)")); + continue; + } + if ((ifreq.ifr_flags & IFF_BROADCAST) && + (ifreq.ifr_flags & IFF_UP) && + ifr->ifr_addr.sa_family == AF_INET) + { + sin = (struct sockaddr_in *) &ifr->ifr_addr; +#ifdef SIOCGIFBRDADDR /* 4.3BSD */ + if (ioctl (sock, SIOCGIFBRDADDR, (char *) &ifreq) < 0) + { + addrs[i++] = inet_makeaddr (inet_netof + /* Changed to pass struct instead of s_addr member + by roland@gnu. */ + (sin->sin_addr), INADDR_ANY); + } + else + { + addrs[i++] = ((struct sockaddr_in *) + &ifreq.ifr_addr)->sin_addr; + } +#else /* 4.2 BSD */ + addrs[i++] = inet_makeaddr (inet_netof + (sin->sin_addr.s_addr), INADDR_ANY); +#endif + } + } + return i; +} + + +enum clnt_stat +clnt_broadcast ( + u_long prog, /* program number */ + u_long vers, /* version number */ + u_long proc, /* procedure number */ + xdrproc_t xargs, /* xdr routine for args */ + caddr_t argsp, /* pointer to args */ + xdrproc_t xresults, /* xdr routine for results */ + caddr_t resultsp, /* pointer to results */ + resultproc_t eachresult /* call with each result obtained */) +{ + enum clnt_stat stat = RPC_FAILED; + AUTH *unix_auth = authunix_create_default (); + XDR xdr_stream; + XDR *xdrs = &xdr_stream; + struct timeval t; + int outlen, inlen, nets; + socklen_t fromlen; + int sock; + int on = 1; + struct pollfd fd; + int milliseconds; + int i; + bool_t done = FALSE; + u_long xid; + u_long port; + struct in_addr addrs[20]; + struct sockaddr_in baddr, raddr; /* broadcast and response addresses */ + struct rmtcallargs a; + struct rmtcallres r; + struct rpc_msg msg; + char outbuf[MAX_BROADCAST_SIZE], inbuf[UDPMSGSIZE]; + + /* + * initialization: create a socket, a broadcast address, and + * preserialize the arguments into a send buffer. + */ + if ((sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) + { + perror (_("Cannot create socket for broadcast rpc")); + stat = RPC_CANTSEND; + goto done_broad; + } +#ifdef SO_BROADCAST + if (setsockopt (sock, SOL_SOCKET, SO_BROADCAST, &on, sizeof (on)) < 0) + { + perror (_("Cannot set socket option SO_BROADCAST")); + stat = RPC_CANTSEND; + goto done_broad; + } +#endif /* def SO_BROADCAST */ + fd.fd = sock; + fd.events = POLLIN; + nets = getbroadcastnets (addrs, sock, inbuf); + memset ((char *) &baddr, 0, sizeof (baddr)); + baddr.sin_family = AF_INET; + baddr.sin_port = htons (PMAPPORT); + baddr.sin_addr.s_addr = htonl (INADDR_ANY); +/* baddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY); */ + msg.rm_xid = xid = _create_xid (); + t.tv_usec = 0; + msg.rm_direction = CALL; + msg.rm_call.cb_rpcvers = RPC_MSG_VERSION; + msg.rm_call.cb_prog = PMAPPROG; + msg.rm_call.cb_vers = PMAPVERS; + msg.rm_call.cb_proc = PMAPPROC_CALLIT; + msg.rm_call.cb_cred = unix_auth->ah_cred; + msg.rm_call.cb_verf = unix_auth->ah_verf; + a.prog = prog; + a.vers = vers; + a.proc = proc; + a.xdr_args = xargs; + a.args_ptr = argsp; + r.port_ptr = &port; + r.xdr_results = xresults; + r.results_ptr = resultsp; + xdrmem_create (xdrs, outbuf, MAX_BROADCAST_SIZE, XDR_ENCODE); + if ((!xdr_callmsg (xdrs, &msg)) || (!xdr_rmtcall_args (xdrs, &a))) + { + stat = RPC_CANTENCODEARGS; + goto done_broad; + } + outlen = (int) xdr_getpos (xdrs); + xdr_destroy (xdrs); + /* + * Basic loop: broadcast a packet and wait a while for response(s). + * The response timeout grows larger per iteration. + */ + for (t.tv_sec = 4; t.tv_sec <= 14; t.tv_sec += 2) + { + for (i = 0; i < nets; i++) + { + baddr.sin_addr = addrs[i]; + if (sendto (sock, outbuf, outlen, 0, + (struct sockaddr *) &baddr, + sizeof (struct sockaddr)) != outlen) + { + perror (_("Cannot send broadcast packet")); + stat = RPC_CANTSEND; + goto done_broad; + } + } + if (eachresult == NULL) + { + stat = RPC_SUCCESS; + goto done_broad; + } + recv_again: + msg.acpted_rply.ar_verf = _null_auth; + msg.acpted_rply.ar_results.where = (caddr_t) & r; + msg.acpted_rply.ar_results.proc = (xdrproc_t) xdr_rmtcallres; + milliseconds = t.tv_sec * 1000 + t.tv_usec / 1000; + switch (poll(&fd, 1, milliseconds)) + { + + case 0: /* timed out */ + stat = RPC_TIMEDOUT; + continue; + + case -1: /* some kind of error */ + if (errno == EINTR) + goto recv_again; + perror (_("Broadcast poll problem")); + stat = RPC_CANTRECV; + goto done_broad; + + } /* end of poll results switch */ + try_again: + fromlen = sizeof (struct sockaddr); + inlen = recvfrom (sock, inbuf, UDPMSGSIZE, 0, + (struct sockaddr *) &raddr, &fromlen); + if (inlen < 0) + { + if (errno == EINTR) + goto try_again; + perror (_("Cannot receive reply to broadcast")); + stat = RPC_CANTRECV; + goto done_broad; + } + if ((size_t) inlen < sizeof (u_long)) + goto recv_again; + /* + * see if reply transaction id matches sent id. + * If so, decode the results. + */ + xdrmem_create (xdrs, inbuf, (u_int) inlen, XDR_DECODE); + if (xdr_replymsg (xdrs, &msg)) + { + if (((u_int32_t) msg.rm_xid == (u_int32_t) xid) && + (msg.rm_reply.rp_stat == MSG_ACCEPTED) && + (msg.acpted_rply.ar_stat == SUCCESS)) + { + raddr.sin_port = htons ((u_short) port); + done = (*eachresult) (resultsp, &raddr); + } + /* otherwise, we just ignore the errors ... */ + } + else + { +#ifdef notdef + /* some kind of deserialization problem ... */ + if ((u_int32_t) msg.rm_xid == (u_int32_t) xid) + fprintf (stderr, "Broadcast deserialization problem"); + /* otherwise, just random garbage */ +#endif + } + xdrs->x_op = XDR_FREE; + msg.acpted_rply.ar_results.proc = (xdrproc_t)xdr_void; + (void) xdr_replymsg (xdrs, &msg); + (void) (*xresults) (xdrs, resultsp); + xdr_destroy (xdrs); + if (done) + { + stat = RPC_SUCCESS; + goto done_broad; + } + else + { + goto recv_again; + } + } +done_broad: + (void) close (sock); + AUTH_DESTROY (unix_auth); + return stat; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/rcmd.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/rcmd.c new file mode 100644 index 00000000..fb1bd932 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/rcmd.c @@ -0,0 +1,689 @@ +/* + * Copyright (C) 1998 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +/* + * Copyright (c) 1983, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if 0 +static char sccsid[] = "@(#)rcmd.c 8.3 (Berkeley) 3/26/94"; +#endif /* LIBC_SCCS and not lint */ + +#define __UCLIBC_HIDE_DEPRECATED__ +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef __UCLIBC_HAS_WCHAR__ +#include +#endif +#include +#include + + +/* some forward declarations */ +static int __ivaliduser2(FILE *hostf, u_int32_t raddr, + const char *luser, const char *ruser, const char *rhost); +static int iruserok2 (u_int32_t raddr, int superuser, const char *ruser, + const char *luser, const char *rhost); + + +int rcmd(char **ahost, u_short rport, const char *locuser, const char *remuser, + const char *cmd, int *fd2p) +{ +#ifdef __UCLIBC_HAS_REENTRANT_RPC__ + int herr; + struct hostent hostbuf; + size_t hstbuflen; + char *tmphstbuf; +#endif + struct hostent *hp; + struct sockaddr_in sin, from; + struct pollfd pfd[2]; + int32_t oldmask; + pid_t pid; + int s, lport, timo; + char c; + + pid = getpid(); + +#ifdef __UCLIBC_HAS_REENTRANT_RPC__ + hstbuflen = 1024; + tmphstbuf = stack_heap_alloc(hstbuflen); + + while (gethostbyname_r (*ahost, &hostbuf, tmphstbuf, + hstbuflen, &hp, &herr) != 0 || hp == NULL) + { + if (herr != NETDB_INTERNAL || errno != ERANGE) + { + __set_h_errno (herr); + stack_heap_free(tmphstbuf); + herror(*ahost); + return -1; + } + else + { + /* Enlarge the buffer. */ + hstbuflen *= 2; + stack_heap_free(tmphstbuf); + tmphstbuf = stack_heap_alloc(hstbuflen); + } + } + stack_heap_free(tmphstbuf); +#else /* call the non-reentrant version */ + if ((hp = gethostbyname(*ahost)) == NULL) { + return -1; + } +#endif + pfd[0].events = POLLIN; + pfd[1].events = POLLIN; + + *ahost = hp->h_name; + oldmask = sigblock(sigmask(SIGURG)); /* __sigblock */ + for (timo = 1, lport = IPPORT_RESERVED - 1;;) { + s = rresvport(&lport); + if (s < 0) { + if (errno == EAGAIN) + (void)fprintf(stderr, + "rcmd: socket: All ports in use\n"); + else + (void)fprintf(stderr, "rcmd: socket: %m\n"); + sigsetmask(oldmask); /* sigsetmask */ + return -1; + } + fcntl(s, F_SETOWN, pid); + sin.sin_family = hp->h_addrtype; + memmove(&sin.sin_addr, hp->h_addr_list[0], + MIN (sizeof (sin.sin_addr), hp->h_length)); + sin.sin_port = rport; + if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) >= 0) /* __connect */ + break; + (void)close(s); + if (errno == EADDRINUSE) { + lport--; + continue; + } + if (errno == ECONNREFUSED && timo <= 16) { + (void)sleep(timo); /* __sleep */ + timo *= 2; + continue; + } + if (hp->h_addr_list[1] != NULL) { + int oerrno = errno; + + (void)fprintf(stderr, "connect to address %s: ", + inet_ntoa(sin.sin_addr)); + __set_errno (oerrno); + perror(0); + hp->h_addr_list++; + memmove(&sin.sin_addr, hp->h_addr_list[0], + MIN (sizeof (sin.sin_addr), hp->h_length)); + (void)fprintf(stderr, "Trying %s...\n", + inet_ntoa(sin.sin_addr)); + continue; + } + (void)fprintf(stderr, "%s: %m\n", hp->h_name); + sigsetmask(oldmask); /* __sigsetmask */ + return -1; + } + lport--; + if (fd2p == 0) { + write(s, "", 1); + lport = 0; + } else { + char num[8]; + int s2 = rresvport(&lport), s3; + socklen_t len = sizeof(from); + + if (s2 < 0) + goto bad; + listen(s2, 1); + (void)snprintf(num, sizeof(num), "%d", lport); /* __snprintf */ + if (write(s, num, strlen(num)+1) != strlen(num)+1) { + (void)fprintf(stderr, + "rcmd: write (setting up stderr): %m\n"); + (void)close(s2); + goto bad; + } + pfd[0].fd = s; + pfd[1].fd = s2; + __set_errno (0); + if (poll (pfd, 2, -1) < 1 || (pfd[1].revents & POLLIN) == 0){ + if (errno != 0) + (void)fprintf(stderr, "rcmd: poll (setting up stderr): %m\n"); + else + (void)fprintf(stderr, "poll: protocol failure in circuit setup\n"); + (void)close(s2); + goto bad; + } + s3 = accept(s2, (struct sockaddr *)&from, &len); + (void)close(s2); + if (s3 < 0) { + (void)fprintf(stderr, + "rcmd: accept: %m\n"); + lport = 0; + goto bad; + } + *fd2p = s3; + from.sin_port = ntohs((u_short)from.sin_port); + if (from.sin_family != AF_INET || + from.sin_port >= IPPORT_RESERVED || + from.sin_port < IPPORT_RESERVED / 2) { + (void)fprintf(stderr, + "socket: protocol failure in circuit setup\n"); + goto bad2; + } + } + (void)write(s, locuser, strlen(locuser)+1); + (void)write(s, remuser, strlen(remuser)+1); + (void)write(s, cmd, strlen(cmd)+1); + if (read(s, &c, 1) != 1) { + (void)fprintf(stderr, + "rcmd: %s: %m\n", *ahost); + goto bad2; + } + if (c != 0) { + while (read(s, &c, 1) == 1) { + (void)write(STDERR_FILENO, &c, 1); + if (c == '\n') + break; + } + goto bad2; + } + sigsetmask(oldmask); + return s; +bad2: + if (lport) + (void)close(*fd2p); +bad: + (void)close(s); + sigsetmask(oldmask); + return -1; +} + +int rresvport(int *alport) +{ + struct sockaddr_in sin; + int s; + + sin.sin_family = AF_INET; + sin.sin_addr.s_addr = INADDR_ANY; + s = socket(AF_INET, SOCK_STREAM, 0); + if (s < 0) + return -1; + for (;;) { + sin.sin_port = htons((u_short)*alport); + if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) >= 0) + return s; + if (errno != EADDRINUSE) { + (void)close(s); + return -1; + } + (*alport)--; + if (*alport == IPPORT_RESERVED/2) { + (void)close(s); + __set_errno (EAGAIN); /* close */ + return -1; + } + } + + return -1; +} +libc_hidden_def(rresvport) + +/* This needs to be exported ... while it is not a documented interface + * for rcp related apps, it's a required one that is used to control the + * rhost behavior. Legacy sucks. + */ +int __check_rhosts_file = 1; + +int ruserok(const char *rhost, int superuser, const char *ruser, + const char *luser) +{ + struct hostent *hp; + u_int32_t addr; + char **ap; +#ifdef __UCLIBC_HAS_REENTRANT_RPC__ + size_t buflen; + char *buffer; + int herr; + struct hostent hostbuf; +#endif + +#ifdef __UCLIBC_HAS_REENTRANT_RPC__ + buflen = 1024; + buffer = stack_heap_alloc(buflen); + + while (gethostbyname_r (rhost, &hostbuf, buffer, + buflen, &hp, &herr) != 0 || hp == NULL) + { + if (herr != NETDB_INTERNAL || errno != ERANGE) { + stack_heap_free(buffer); + return -1; + } else + { + /* Enlarge the buffer. */ + buflen *= 2; + stack_heap_free(buffer); + buffer = stack_heap_alloc(buflen); + } + } + stack_heap_free(buffer); +#else + if ((hp = gethostbyname(rhost)) == NULL) { + return -1; + } +#endif + for (ap = hp->h_addr_list; *ap; ++ap) { + memmove(&addr, *ap, sizeof(addr)); + if (iruserok2(addr, superuser, ruser, luser, rhost) == 0) + return 0; + } + return -1; +} + + +/* Extremely paranoid file open function. */ +static FILE * +iruserfopen (const char *file, uid_t okuser) +{ + struct stat st; + char *cp = NULL; + FILE *res = NULL; + + /* If not a regular file, if owned by someone other than user or + root, if writeable by anyone but the owner, or if hardlinked + anywhere, quit. */ + if (lstat (file, &st)) + cp = "lstat failed"; + else if (!S_ISREG (st.st_mode)) + cp = "not regular file"; + else + { + res = fopen (file, "r"); + if (!res) + cp = "cannot open"; + else if (fstat (fileno (res), &st) < 0) + cp = "fstat failed"; + else if (st.st_uid && st.st_uid != okuser) + cp = "bad owner"; + else if (st.st_mode & (S_IWGRP|S_IWOTH)) + cp = "writeable by other than owner"; + else if (st.st_nlink > 1) + cp = "hard linked somewhere"; + } + + /* If there were any problems, quit. */ + if (cp != NULL) + { + if (res) + fclose (res); + return NULL; + } + + return res; +} + + +/* + * New .rhosts strategy: We are passed an ip address. We spin through + * hosts.equiv and .rhosts looking for a match. When the .rhosts only + * has ip addresses, we don't have to trust a nameserver. When it + * contains hostnames, we spin through the list of addresses the nameserver + * gives us and look for a match. + * + * Returns 0 if ok, -1 if not ok. + */ +static int +iruserok2 (u_int32_t raddr, int superuser, const char *ruser, const char *luser, + const char *rhost) +{ + FILE *hostf = NULL; + int isbad = -1; + + if (!superuser) + hostf = iruserfopen (_PATH_HEQUIV, 0); + + if (hostf) { + isbad = __ivaliduser2 (hostf, raddr, luser, ruser, rhost); + fclose (hostf); + + if (!isbad) + return 0; + } + + if (__check_rhosts_file || superuser) { + char *pbuf; + struct passwd *pwd; + size_t dirlen; + uid_t uid; + +#ifdef __UCLIBC_HAS_REENTRANT_RPC__ + size_t buflen = sysconf (_SC_GETPW_R_SIZE_MAX); + struct passwd pwdbuf; + char *buffer = stack_heap_alloc(buflen); + + if (getpwnam_r (luser, &pwdbuf, buffer, + buflen, &pwd) != 0 || pwd == NULL) + { + stack_heap_free(buffer); + return -1; + } + stack_heap_free(buffer); +#else + if ((pwd = getpwnam(luser)) == NULL) + return -1; +#endif + + dirlen = strlen (pwd->pw_dir); + pbuf = malloc (dirlen + sizeof "/.rhosts"); + strcpy (pbuf, pwd->pw_dir); + strcat (pbuf, "/.rhosts"); + + /* Change effective uid while reading .rhosts. If root and + reading an NFS mounted file system, can't read files that + are protected read/write owner only. */ + uid = geteuid (); + seteuid (pwd->pw_uid); + hostf = iruserfopen (pbuf, pwd->pw_uid); + free(pbuf); + + if (hostf != NULL) { + isbad = __ivaliduser2 (hostf, raddr, luser, ruser, rhost); + fclose (hostf); + } + + seteuid (uid); + return isbad; + } + return -1; +} + +/* This is the exported version. */ +int iruserok (u_int32_t raddr, int superuser, const char * ruser, const char * luser); +int iruserok (u_int32_t raddr, int superuser, const char * ruser, const char * luser) +{ + return iruserok2 (raddr, superuser, ruser, luser, "-"); +} + + +/* + * XXX + * Don't make static, used by lpd(8). + * + * This function is not used anymore. It is only present because lpd(8) + * calls it (!?!). We simply call __invaliduser2() with an illegal rhost + * argument. This means that netgroups won't work in .rhost/hosts.equiv + * files. If you want lpd to work with netgroups, fix lpd to use ruserok() + * or PAM. + * Returns 0 if ok, -1 if not ok. + */ +int +__ivaliduser(FILE *hostf, u_int32_t raddr, const char *luser, const char *ruser); +int +__ivaliduser(FILE *hostf, u_int32_t raddr, const char *luser, const char *ruser) +{ + return __ivaliduser2(hostf, raddr, luser, ruser, "-"); +} + + +/* Returns 1 on positive match, 0 on no match, -1 on negative match. */ +static int +__icheckhost (u_int32_t raddr, char *lhost, const char *rhost) +{ + struct hostent *hp; + u_int32_t laddr; + int negate=1; /* Multiply return with this to get -1 instead of 1 */ + char **pp; + +#ifdef __UCLIBC_HAS_REENTRANT_RPC__ + int save_errno; + size_t buflen; + char *buffer; + struct hostent hostbuf; + int herr; +#endif + +#ifdef HAVE_NETGROUP + /* Check nis netgroup. */ + if (strncmp ("+@", lhost, 2) == 0) + return innetgr (&lhost[2], rhost, NULL, NULL); + + if (strncmp ("-@", lhost, 2) == 0) + return -innetgr (&lhost[2], rhost, NULL, NULL); +#endif /* HAVE_NETGROUP */ + + /* -host */ + if (strncmp ("-", lhost,1) == 0) { + negate = -1; + lhost++; + } else if (strcmp ("+",lhost) == 0) { + return 1; /* asking for trouble, but ok.. */ + } + + /* Try for raw ip address first. */ + if (isdigit (*lhost) && (laddr = inet_addr (lhost)) != INADDR_NONE) + return negate * (! (raddr ^ laddr)); + + /* Better be a hostname. */ +#ifdef __UCLIBC_HAS_REENTRANT_RPC__ + buflen = 1024; + buffer = malloc(buflen); + save_errno = errno; + + while (gethostbyname_r (lhost, &hostbuf, buffer, buflen, &hp, &herr) + != 0) { + free(buffer); + return (0); + } + free(buffer); + __set_errno (save_errno); +#else + hp = gethostbyname(lhost); +#endif /* __UCLIBC_HAS_REENTRANT_RPC__ */ + + if (hp == NULL) + return 0; + + /* Spin through ip addresses. */ + for (pp = hp->h_addr_list; *pp; ++pp) + if (!memcmp (&raddr, *pp, sizeof (u_int32_t))) + return negate; + + /* No match. */ + return (0); +} + +/* Returns 1 on positive match, 0 on no match, -1 on negative match. */ +static int +__icheckuser (const char *luser, const char *ruser) +{ + + /* + luser is user entry from .rhosts/hosts.equiv file + ruser is user id on remote host + */ + +#ifdef HAVE_NETGROUP + /* [-+]@netgroup */ + if (strncmp ("+@", luser, 2) == 0) + return innetgr (&luser[2], NULL, ruser, NULL); + + if (strncmp ("-@", luser,2) == 0) + return -innetgr (&luser[2], NULL, ruser, NULL); +#endif /* HAVE_NETGROUP */ + + /* -user */ + if (strncmp ("-", luser, 1) == 0) + return -(strcmp (&luser[1], ruser) == 0); + + /* + */ + if (strcmp ("+", luser) == 0) + return 1; + + /* simple string match */ + return strcmp (ruser, luser) == 0; +} + +/* + * Returns 1 for blank lines (or only comment lines) and 0 otherwise + */ +static int +__isempty(char *p) +{ + while (*p && isspace (*p)) { + ++p; + } + + return (*p == '\0' || *p == '#') ? 1 : 0 ; +} + +/* + * Returns 0 if positive match, -1 if _not_ ok. + */ +static int +__ivaliduser2(FILE *hostf, u_int32_t raddr, const char *luser, + const char *ruser, const char *rhost) +{ + register const char *user; + register char *p; + int hcheck, ucheck; + char *buf = NULL; + size_t bufsize = 0; + int retval = -1; + + while (getline (&buf, &bufsize, hostf) > 0) { + buf[bufsize - 1] = '\0'; /* Make sure it's terminated. */ + p = buf; + + /* Skip empty or comment lines */ + if (__isempty (p)) { + continue; + } + + /* Skip lines that are too long. */ + if (strchr (p, '\n') == NULL) { + int ch = getc_unlocked (hostf); + + while (ch != '\n' && ch != EOF) + ch = getc_unlocked (hostf); + continue; + } + + for (;*p && !isspace(*p); ++p) { + *p = tolower (*p); + } + + /* Next we want to find the permitted name for the remote user. */ + if (*p == ' ' || *p == '\t') { + /* terminate hostname and skip spaces */ + for (*p++='\0'; *p && isspace (*p); ++p); + + user = p; /* this is the user's name */ + while (*p && !isspace (*p)) + ++p; /* find end of user's name */ + } else + user = p; + + *p = '\0'; /* terminate username (+host?) */ + + /* buf -> host(?) ; user -> username(?) */ + + /* First check host part */ + hcheck = __icheckhost (raddr, buf, rhost); + + if (hcheck < 0) + break; + + if (hcheck) { + /* Then check user part */ + if (! (*user)) + user = luser; + + ucheck = __icheckuser (user, ruser); + + /* Positive 'host user' match? */ + if (ucheck > 0) { + retval = 0; + break; + } + + /* Negative 'host -user' match? */ + if (ucheck < 0) + break; + + /* Neither, go on looking for match */ + } + } + + free (buf); + + return retval; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/rexec.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/rexec.c new file mode 100644 index 00000000..4148fdd0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/rexec.c @@ -0,0 +1,192 @@ +/* + * Copyright (c) 1980, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#define __FORCE_GLIBC +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#define SA_LEN(_x) __libc_sa_len((_x)->sa_family) +extern int __libc_sa_len(sa_family_t __af) __THROW attribute_hidden; + +/* int rexecoptions; - google does not know it */ +static char ahostbuf[NI_MAXHOST]; + +int +rexec_af(char **ahost, int rport, const char *name, const char *pass, const char *cmd, int *fd2p, sa_family_t af) +{ + struct sockaddr_storage sa2, from; + struct addrinfo hints, *res0; + const char *orig_name = name; + const char *orig_pass = pass; + u_short port = 0; + int s, timo = 1, s3; + char c; + int gai; + char servbuff[NI_MAXSERV]; + + if (sizeof(servbuff) < sizeof(int)*3 + 2) { + snprintf(servbuff, sizeof(servbuff), "%d", ntohs(rport)); + servbuff[sizeof(servbuff) - 1] = '\0'; + } else { + sprintf(servbuff, "%d", ntohs(rport)); + } + + memset(&hints, '\0', sizeof(hints)); + hints.ai_family = af; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_CANONNAME; + gai = getaddrinfo(*ahost, servbuff, &hints, &res0); + if (gai) { + /* XXX: set errno? */ + return -1; + } + + if (res0->ai_canonname) { + strncpy(ahostbuf, res0->ai_canonname, sizeof(ahostbuf)); + ahostbuf[sizeof(ahostbuf)-1] = '\0'; + *ahost = ahostbuf; + } + else { + *ahost = NULL; + __set_errno(ENOENT); + return -1; + } + ruserpass(res0->ai_canonname, &name, &pass); +retry: + s = socket(res0->ai_family, res0->ai_socktype, 0); + if (s < 0) { + perror("rexec: socket"); + return -1; + } + if (connect(s, res0->ai_addr, res0->ai_addrlen) < 0) { + if (errno == ECONNREFUSED && timo <= 16) { + (void) close(s); + sleep(timo); + timo *= 2; + goto retry; + } + perror(res0->ai_canonname); + return -1; + } + if (fd2p == 0) { + (void) write(s, "", 1); + port = 0; + } else { + char num[32]; + int s2; + socklen_t sa2len; + + s2 = socket(res0->ai_family, res0->ai_socktype, 0); + if (s2 < 0) { + (void) close(s); + return -1; + } + listen(s2, 1); + sa2len = sizeof(sa2); + if (getsockname(s2, (struct sockaddr *)&sa2, &sa2len) < 0) { + perror("getsockname"); + (void) close(s2); + goto bad; + } else if (sa2len != SA_LEN((struct sockaddr *)&sa2)) { + __set_errno(EINVAL); + (void) close(s2); + goto bad; + } + port = 0; + if (!getnameinfo((struct sockaddr *)&sa2, sa2len, + NULL, 0, servbuff, sizeof(servbuff), + NI_NUMERICSERV)) + port = atoi(servbuff); + (void) sprintf(num, "%u", port); + (void) write(s, num, strlen(num)+1); + { + socklen_t len = sizeof(from); + s3 = TEMP_FAILURE_RETRY(accept(s2, + (struct sockaddr *)&from, &len)); + close(s2); + if (s3 < 0) { + perror("accept"); + port = 0; + goto bad; + } + } + *fd2p = s3; + } + (void) write(s, name, strlen(name) + 1); + /* should public key encypt the password here */ + (void) write(s, pass, strlen(pass) + 1); + (void) write(s, cmd, strlen(cmd) + 1); + + /* We don't need the memory allocated for the name and the password + in ruserpass anymore. */ + if (name != orig_name) + free((char *) name); + if (pass != orig_pass) + free((char *) pass); + + if (read(s, &c, 1) != 1) { + perror(*ahost); + goto bad; + } + if (c != 0) { + while (read(s, &c, 1) == 1) { + (void) write(2, &c, 1); + if (c == '\n') + break; + } + goto bad; + } + freeaddrinfo(res0); + return s; +bad: + if (port) + (void) close(*fd2p); + (void) close(s); + freeaddrinfo(res0); + return -1; +} +libc_hidden_def(rexec_af) + +int +rexec(char **ahost, int rport, const char *name, const char *pass, + const char *cmd, int *fd2p) +{ + return rexec_af(ahost, rport, name, pass, cmd, fd2p, AF_INET); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/rpc_cmsg.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/rpc_cmsg.c new file mode 100644 index 00000000..a8c25734 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/rpc_cmsg.c @@ -0,0 +1,208 @@ +/* @(#)rpc_callmsg.c 2.1 88/07/29 4.0 RPCSRC */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +#if 0 +static char sccsid[] = "@(#)rpc_callmsg.c 1.4 87/08/11 Copyr 1984 Sun Micro"; +#endif + +/* + * rpc_callmsg.c + * + * Copyright (C) 1984, Sun Microsystems, Inc. + * + */ + +#define __FORCE_GLIBC +#include + +#include +#include +#include + + +/* + * XDR a call message + */ +bool_t +xdr_callmsg (XDR *xdrs, struct rpc_msg *cmsg) +{ + int32_t *buf; + struct opaque_auth *oa; + + if (xdrs->x_op == XDR_ENCODE) + { + if (cmsg->rm_call.cb_cred.oa_length > MAX_AUTH_BYTES) + { + return (FALSE); + } + if (cmsg->rm_call.cb_verf.oa_length > MAX_AUTH_BYTES) + { + return (FALSE); + } + buf = XDR_INLINE (xdrs, 8 * BYTES_PER_XDR_UNIT + + RNDUP (cmsg->rm_call.cb_cred.oa_length) + + 2 * BYTES_PER_XDR_UNIT + + RNDUP (cmsg->rm_call.cb_verf.oa_length)); + if (buf != NULL) + { + IXDR_PUT_LONG (buf, cmsg->rm_xid); + IXDR_PUT_ENUM (buf, cmsg->rm_direction); + if (cmsg->rm_direction != CALL) + return FALSE; + IXDR_PUT_LONG (buf, cmsg->rm_call.cb_rpcvers); + if (cmsg->rm_call.cb_rpcvers != RPC_MSG_VERSION) + return FALSE; + IXDR_PUT_LONG (buf, cmsg->rm_call.cb_prog); + IXDR_PUT_LONG (buf, cmsg->rm_call.cb_vers); + IXDR_PUT_LONG (buf, cmsg->rm_call.cb_proc); + oa = &cmsg->rm_call.cb_cred; + IXDR_PUT_ENUM (buf, oa->oa_flavor); + IXDR_PUT_INT32 (buf, oa->oa_length); + if (oa->oa_length) + { + memcpy ((caddr_t) buf, oa->oa_base, oa->oa_length); + buf = (int32_t *) ((char *) buf + RNDUP (oa->oa_length)); + } + oa = &cmsg->rm_call.cb_verf; + IXDR_PUT_ENUM (buf, oa->oa_flavor); + IXDR_PUT_INT32 (buf, oa->oa_length); + if (oa->oa_length) + { + memcpy ((caddr_t) buf, oa->oa_base, oa->oa_length); + /* no real need.... + buf = (long *) ((char *) buf + RNDUP(oa->oa_length)); + */ + } + return TRUE; + } + } + if (xdrs->x_op == XDR_DECODE) + { + buf = XDR_INLINE (xdrs, 8 * BYTES_PER_XDR_UNIT); + if (buf != NULL) + { + cmsg->rm_xid = IXDR_GET_LONG (buf); + cmsg->rm_direction = IXDR_GET_ENUM (buf, enum msg_type); + if (cmsg->rm_direction != CALL) + { + return FALSE; + } + cmsg->rm_call.cb_rpcvers = IXDR_GET_LONG (buf); + if (cmsg->rm_call.cb_rpcvers != RPC_MSG_VERSION) + { + return FALSE; + } + cmsg->rm_call.cb_prog = IXDR_GET_LONG (buf); + cmsg->rm_call.cb_vers = IXDR_GET_LONG (buf); + cmsg->rm_call.cb_proc = IXDR_GET_LONG (buf); + oa = &cmsg->rm_call.cb_cred; + oa->oa_flavor = IXDR_GET_ENUM (buf, enum_t); + oa->oa_length = IXDR_GET_INT32 (buf); + if (oa->oa_length) + { + if (oa->oa_length > MAX_AUTH_BYTES) + return FALSE; + if (oa->oa_base == NULL) + { + oa->oa_base = (caddr_t) + mem_alloc (oa->oa_length); + } + buf = XDR_INLINE (xdrs, RNDUP (oa->oa_length)); + if (buf == NULL) + { + if (xdr_opaque (xdrs, oa->oa_base, + oa->oa_length) == FALSE) + return FALSE; + } + else + { + memcpy (oa->oa_base, (caddr_t) buf, oa->oa_length); + /* no real need.... + buf = (long *) ((char *) buf + + RNDUP(oa->oa_length)); + */ + } + } + oa = &cmsg->rm_call.cb_verf; + buf = XDR_INLINE (xdrs, 2 * BYTES_PER_XDR_UNIT); + if (buf == NULL) + { + if (xdr_enum (xdrs, &oa->oa_flavor) == FALSE || + xdr_u_int (xdrs, &oa->oa_length) == FALSE) + { + return FALSE; + } + } + else + { + oa->oa_flavor = IXDR_GET_ENUM (buf, enum_t); + oa->oa_length = IXDR_GET_INT32 (buf); + } + if (oa->oa_length) + { + if (oa->oa_length > MAX_AUTH_BYTES) + return FALSE; + if (oa->oa_base == NULL) + { + oa->oa_base = (caddr_t) + mem_alloc (oa->oa_length); + } + buf = XDR_INLINE (xdrs, RNDUP (oa->oa_length)); + if (buf == NULL) + { + if (xdr_opaque (xdrs, oa->oa_base, + oa->oa_length) == FALSE) + return FALSE; + } + else + { + memcpy (oa->oa_base, (caddr_t) buf, oa->oa_length); + /* no real need... + buf = (long *) ((char *) buf + + RNDUP(oa->oa_length)); + */ + } + } + return TRUE; + } + } + if ( + xdr_u_long (xdrs, &(cmsg->rm_xid)) && + xdr_enum (xdrs, (enum_t *) & (cmsg->rm_direction)) && + (cmsg->rm_direction == CALL) && + xdr_u_long (xdrs, &(cmsg->rm_call.cb_rpcvers)) && + (cmsg->rm_call.cb_rpcvers == RPC_MSG_VERSION) && + xdr_u_long (xdrs, &(cmsg->rm_call.cb_prog)) && + xdr_u_long (xdrs, &(cmsg->rm_call.cb_vers)) && + xdr_u_long (xdrs, &(cmsg->rm_call.cb_proc)) && + xdr_opaque_auth (xdrs, &(cmsg->rm_call.cb_cred))) + return xdr_opaque_auth (xdrs, &(cmsg->rm_call.cb_verf)); + return FALSE; +} +libc_hidden_def(xdr_callmsg) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/rpc_commondata.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/rpc_commondata.c new file mode 100644 index 00000000..187d915b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/rpc_commondata.c @@ -0,0 +1,47 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +#include +#include +#include + +#undef svc_fdset +#undef rpc_createerr +#undef svc_pollfd +#undef svc_max_pollfd + + +/* + * This file should only contain common data (global data) that is exported + * by public interfaces + */ +struct opaque_auth _null_auth; +fd_set svc_fdset; +struct rpc_createerr rpc_createerr; +struct pollfd *svc_pollfd; +int svc_max_pollfd; diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/rpc_dtablesize.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/rpc_dtablesize.c new file mode 100644 index 00000000..692e8fce --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/rpc_dtablesize.c @@ -0,0 +1,56 @@ +/* @(#)rpc_dtablesize.c 2.1 88/07/29 4.0 RPCSRC */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +#if 0 +static char sccsid[] = "@(#)rpc_dtablesize.c 1.2 87/08/11 Copyr 1987 Sun Micro"; +#endif + +#define __FORCE_GLIBC +#define __USE_BSD +#include + +#include +#include + + +/* + * Cache the result of getdtablesize(), so we don't have to do an + * expensive system call every time. + */ +int +_rpc_dtablesize(void) +{ + static int size; + + if (size == 0) + size = getdtablesize (); + + return size; +} +libc_hidden_def(_rpc_dtablesize) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/rpc_private.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/rpc_private.h new file mode 100644 index 00000000..ede3ddfc --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/rpc_private.h @@ -0,0 +1,55 @@ +#ifndef _RPC_RPC_H +#include + +/* Now define the internal interfaces. */ +extern u_long _create_xid (void) attribute_hidden; + + +/* + * Multi-threaded support + * Group all global and static variables into a single spot. + * This area is allocated on a per-thread basis + */ +#ifdef __UCLIBC_HAS_THREADS__ +#include +struct rpc_thread_variables { + fd_set svc_fdset_s; /* Global, rpc_common.c */ + struct rpc_createerr rpc_createerr_s; /* Global, rpc_common.c */ + struct pollfd *svc_pollfd_s; /* Global, rpc_common.c */ + int svc_max_pollfd_s; /* Global, rpc_common.c */ + + void *authnone_private_s; /* auth_none.c */ + + void *clnt_perr_buf_s; /* clnt_perr.c */ + + void *clntraw_private_s; /* clnt_raw.c */ + + void *callrpc_private_s; /* clnt_simp.c */ + + void *key_call_private_s; /* key_call.c */ + + void *authdes_cache_s; /* svcauth_des.c */ + void *authdes_lru_s; /* svcauth_des.c */ + + void *svc_xports_s; /* svc.c */ + void *svc_head_s; /* svc.c */ + + void *svcraw_private_s; /* svc_raw.c */ + + void *svcsimple_proglst_s; /* svc_simple.c */ + void *svcsimple_transp_s; /* svc_simple.c */ +}; + +extern struct rpc_thread_variables *__rpc_thread_variables(void) + __attribute__ ((const)) attribute_hidden; +extern void __rpc_thread_svc_cleanup (void) attribute_hidden; +extern void __rpc_thread_clnt_cleanup (void) attribute_hidden; +/*extern void __rpc_thread_key_cleanup (void) attribute_hidden;*/ + +extern void __rpc_thread_destroy (void); + +#define RPC_THREAD_VARIABLE(x) (__rpc_thread_variables()->x) + +#endif /* __UCLIBC_HAS_THREADS__ */ + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/rpc_prot.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/rpc_prot.c new file mode 100644 index 00000000..bf55a3cf --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/rpc_prot.c @@ -0,0 +1,285 @@ +/* @(#)rpc_prot.c 2.3 88/08/07 4.0 RPCSRC */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +#if 0 +static char sccsid[] = "@(#)rpc_prot.c 1.36 87/08/11 Copyr 1984 Sun Micro"; +#endif + +/* + * rpc_prot.c + * + * Copyright (C) 1984, Sun Microsystems, Inc. + * + * This set of routines implements the rpc message definition, + * its serializer and some common rpc utility routines. + * The routines are meant for various implementations of rpc - + * they are NOT for the rpc client or rpc service implementations! + * Because authentication stuff is easy and is part of rpc, the opaque + * routines are also in this program. + */ + +#define __FORCE_GLIBC +#include + +#include + +#include + + +/* * * * * * * * * * * * * * XDR Authentication * * * * * * * * * * * */ + +/* + * XDR an opaque authentication struct + * (see auth.h) + */ +bool_t +xdr_opaque_auth (XDR *xdrs, struct opaque_auth *ap) +{ + + if (xdr_enum (xdrs, &(ap->oa_flavor))) + return xdr_bytes (xdrs, &ap->oa_base, + &ap->oa_length, MAX_AUTH_BYTES); + return FALSE; +} +libc_hidden_def(xdr_opaque_auth) + +/* + * XDR a DES block + */ +bool_t +xdr_des_block (XDR *xdrs, des_block *blkp) +{ + return xdr_opaque (xdrs, (caddr_t) blkp, sizeof (des_block)); +} + +/* * * * * * * * * * * * * * XDR RPC MESSAGE * * * * * * * * * * * * * * * */ + +/* + * XDR the MSG_ACCEPTED part of a reply message union + */ +bool_t +xdr_accepted_reply (XDR *xdrs, struct accepted_reply *ar) +{ + /* personalized union, rather than calling xdr_union */ + if (!xdr_opaque_auth (xdrs, &(ar->ar_verf))) + return FALSE; + if (!xdr_enum (xdrs, (enum_t *) & (ar->ar_stat))) + return FALSE; + switch (ar->ar_stat) + { + case SUCCESS: + return ((*(ar->ar_results.proc)) (xdrs, ar->ar_results.where)); + case PROG_MISMATCH: + if (!xdr_u_long (xdrs, &(ar->ar_vers.low))) + return FALSE; + return (xdr_u_long (xdrs, &(ar->ar_vers.high))); + default: + return TRUE; + } + return TRUE; /* TRUE => open ended set of problems */ +} +libc_hidden_def(xdr_accepted_reply) + +/* + * XDR the MSG_DENIED part of a reply message union + */ +bool_t +xdr_rejected_reply (XDR *xdrs, struct rejected_reply *rr) +{ + /* personalized union, rather than calling xdr_union */ + if (!xdr_enum (xdrs, (enum_t *) & (rr->rj_stat))) + return FALSE; + switch (rr->rj_stat) + { + case RPC_MISMATCH: + if (!xdr_u_long (xdrs, &(rr->rj_vers.low))) + return FALSE; + return xdr_u_long (xdrs, &(rr->rj_vers.high)); + + case AUTH_ERROR: + return xdr_enum (xdrs, (enum_t *) & (rr->rj_why)); + } + return FALSE; +} +libc_hidden_def(xdr_rejected_reply) + +static const struct xdr_discrim reply_dscrm[3] = +{ + {(int) MSG_ACCEPTED, (xdrproc_t) xdr_accepted_reply}, + {(int) MSG_DENIED, (xdrproc_t) xdr_rejected_reply}, + {__dontcare__, NULL_xdrproc_t}}; + +/* + * XDR a reply message + */ +bool_t +xdr_replymsg (XDR *xdrs, struct rpc_msg *rmsg) +{ + if (xdr_u_long (xdrs, &(rmsg->rm_xid)) && + xdr_enum (xdrs, (enum_t *) & (rmsg->rm_direction)) && + (rmsg->rm_direction == REPLY)) + return xdr_union (xdrs, (enum_t *) & (rmsg->rm_reply.rp_stat), + (caddr_t) & (rmsg->rm_reply.ru), reply_dscrm, + NULL_xdrproc_t); + return FALSE; +} +libc_hidden_def(xdr_replymsg) + + +/* + * Serializes the "static part" of a call message header. + * The fields include: rm_xid, rm_direction, rpcvers, prog, and vers. + * The rm_xid is not really static, but the user can easily munge on the fly. + */ +bool_t +xdr_callhdr (XDR *xdrs, struct rpc_msg *cmsg) +{ + + cmsg->rm_direction = CALL; + cmsg->rm_call.cb_rpcvers = RPC_MSG_VERSION; + if ( + (xdrs->x_op == XDR_ENCODE) && + xdr_u_long (xdrs, &(cmsg->rm_xid)) && + xdr_enum (xdrs, (enum_t *) & (cmsg->rm_direction)) && + xdr_u_long (xdrs, &(cmsg->rm_call.cb_rpcvers)) && + xdr_u_long (xdrs, &(cmsg->rm_call.cb_prog))) + return xdr_u_long (xdrs, &(cmsg->rm_call.cb_vers)); + return FALSE; +} +libc_hidden_def(xdr_callhdr) + +/* ************************** Client utility routine ************* */ + +static void +accepted (enum accept_stat acpt_stat, + struct rpc_err *error) +{ + switch (acpt_stat) + { + + case PROG_UNAVAIL: + error->re_status = RPC_PROGUNAVAIL; + return; + + case PROG_MISMATCH: + error->re_status = RPC_PROGVERSMISMATCH; + return; + + case PROC_UNAVAIL: + error->re_status = RPC_PROCUNAVAIL; + return; + + case GARBAGE_ARGS: + error->re_status = RPC_CANTDECODEARGS; + return; + + case SYSTEM_ERR: + error->re_status = RPC_SYSTEMERROR; + return; + + case SUCCESS: + error->re_status = RPC_SUCCESS; + return; + } + /* something's wrong, but we don't know what ... */ + error->re_status = RPC_FAILED; + error->re_lb.s1 = (long) MSG_ACCEPTED; + error->re_lb.s2 = (long) acpt_stat; +} + +static void +rejected (enum reject_stat rjct_stat, + struct rpc_err *error) +{ + switch (rjct_stat) + { + case RPC_MISMATCH: + error->re_status = RPC_VERSMISMATCH; + return; + case AUTH_ERROR: + error->re_status = RPC_AUTHERROR; + return; + default: + /* something's wrong, but we don't know what ... */ + error->re_status = RPC_FAILED; + error->re_lb.s1 = (long) MSG_DENIED; + error->re_lb.s2 = (long) rjct_stat; + return; + } +} + +/* + * given a reply message, fills in the error + */ +void +_seterr_reply (struct rpc_msg *msg, + struct rpc_err *error) +{ + /* optimized for normal, SUCCESSful case */ + switch (msg->rm_reply.rp_stat) + { + case MSG_ACCEPTED: + if (msg->acpted_rply.ar_stat == SUCCESS) + { + error->re_status = RPC_SUCCESS; + return; + }; + accepted (msg->acpted_rply.ar_stat, error); + break; + + case MSG_DENIED: + rejected (msg->rjcted_rply.rj_stat, error); + break; + + default: + error->re_status = RPC_FAILED; + error->re_lb.s1 = (long) (msg->rm_reply.rp_stat); + break; + } + switch (error->re_status) + { + + case RPC_VERSMISMATCH: + error->re_vers.low = msg->rjcted_rply.rj_vers.low; + error->re_vers.high = msg->rjcted_rply.rj_vers.high; + break; + + case RPC_AUTHERROR: + error->re_why = msg->rjcted_rply.rj_why; + break; + + case RPC_PROGVERSMISMATCH: + error->re_vers.low = msg->acpted_rply.ar_vers.low; + error->re_vers.high = msg->acpted_rply.ar_vers.high; + break; + default: + break; + } +} +libc_hidden_def(_seterr_reply) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/rpc_thread.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/rpc_thread.c new file mode 100644 index 00000000..71303b2b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/rpc_thread.c @@ -0,0 +1,166 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define __FORCE_GLIBC +#include +#include +#include +#include "rpc_private.h" + + +#ifdef __UCLIBC_HAS_THREADS__ + +#include +#include + +/* Variable used in non-threaded applications or for the first thread. */ +static struct rpc_thread_variables __libc_tsd_RPC_VARS_mem; +__libc_tsd_define (, RPC_VARS) + +/* + * Task-variable destructor + */ +void +__rpc_thread_destroy (void) +{ + struct rpc_thread_variables *tvp = __libc_tsd_get (RPC_VARS); + + if (tvp != NULL && tvp != &__libc_tsd_RPC_VARS_mem) { + __rpc_thread_svc_cleanup (); + __rpc_thread_clnt_cleanup (); + /*__rpc_thread_key_cleanup (); */ + free (tvp->authnone_private_s); + free (tvp->clnt_perr_buf_s); + free (tvp->clntraw_private_s); + free (tvp->svcraw_private_s); + free (tvp->authdes_cache_s); + free (tvp->authdes_lru_s); + free (tvp); + __libc_tsd_set (RPC_VARS, NULL); + } +} + +/* + * Initialize RPC multi-threaded operation + */ +static void +rpc_thread_multi (void) +{ + __libc_tsd_set (RPC_VARS, &__libc_tsd_RPC_VARS_mem); +} + + +struct rpc_thread_variables attribute_hidden * +__rpc_thread_variables (void) +{ + __libc_once_define (static, once); + struct rpc_thread_variables *tvp; + + tvp = __libc_tsd_get (RPC_VARS); + if (tvp == NULL) { + __libc_once (once, rpc_thread_multi); + tvp = __libc_tsd_get (RPC_VARS); + if (tvp == NULL) { + tvp = calloc (1, sizeof *tvp); + if (tvp != NULL) + __libc_tsd_set (RPC_VARS, tvp); + else + tvp = __libc_tsd_get (RPC_VARS); + } + } + return tvp; +} + + +/* Global variables If we're single-threaded, or if this is the first + thread using the variable, use the existing global variable. This + provides backwards compatability for existing applications which + dynamically link against this code. */ +#undef svc_fdset +#undef rpc_createerr +#undef svc_pollfd +#undef svc_max_pollfd + +fd_set * +__rpc_thread_svc_fdset (void) +{ + struct rpc_thread_variables *tvp; + + tvp = __rpc_thread_variables (); + if (tvp == &__libc_tsd_RPC_VARS_mem) + return &svc_fdset; + return &tvp->svc_fdset_s; +} + +struct rpc_createerr * +__rpc_thread_createerr (void) +{ + struct rpc_thread_variables *tvp; + + tvp = __rpc_thread_variables (); + if (tvp == &__libc_tsd_RPC_VARS_mem) + return &rpc_createerr; + return &tvp->rpc_createerr_s; +} + +struct pollfd ** +__rpc_thread_svc_pollfd (void) +{ + struct rpc_thread_variables *tvp; + + tvp = __rpc_thread_variables (); + if (tvp == &__libc_tsd_RPC_VARS_mem) + return &svc_pollfd; + return &tvp->svc_pollfd_s; +} + +int * +__rpc_thread_svc_max_pollfd (void) +{ + struct rpc_thread_variables *tvp; + + tvp = __rpc_thread_variables (); + if (tvp == &__libc_tsd_RPC_VARS_mem) + return &svc_max_pollfd; + return &tvp->svc_max_pollfd_s; +} +#else + +#undef svc_fdset +#undef rpc_createerr +#undef svc_pollfd +#undef svc_max_pollfd + +extern fd_set svc_fdset; +fd_set * __rpc_thread_svc_fdset (void) +{ + return &(svc_fdset); +} + +extern struct rpc_createerr rpc_createerr; +struct rpc_createerr * __rpc_thread_createerr (void) +{ + return &(rpc_createerr); +} + +extern struct pollfd *svc_pollfd; +struct pollfd ** __rpc_thread_svc_pollfd (void) +{ + return &(svc_pollfd); +} + +extern int svc_max_pollfd; +int * __rpc_thread_svc_max_pollfd (void) +{ + return &(svc_max_pollfd); +} + +#endif /* __UCLIBC_HAS_THREADS__ */ + +libc_hidden_def(__rpc_thread_svc_fdset) +libc_hidden_def(__rpc_thread_createerr) +libc_hidden_def(__rpc_thread_svc_pollfd) +libc_hidden_def(__rpc_thread_svc_max_pollfd) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/rtime.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/rtime.c new file mode 100644 index 00000000..f9f1d9e9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/rtime.c @@ -0,0 +1,153 @@ +#if 0 +static char sccsid[] = "@(#)rtime.c 2.2 88/08/10 4.0 RPCSRC; from 1.8 88/02/08 SMI"; +#endif +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +/* + * Copyright (c) 1988 by Sun Microsystems, Inc. + */ +/* + * rtime - get time from remote machine + * + * gets time, obtaining value from host + * on the udp/time socket. Since timeserver returns + * with time of day in seconds since Jan 1, 1900, must + * subtract seconds before Jan 1, 1970 to get + * what unix uses. + */ + +#define __FORCE_GLIBC +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define NYEARS (u_long)(1970 - 1900) +#define TOFFSET (u_long)(60*60*24*(365*NYEARS + (NYEARS/4))) + +static void do_close (int); + +static void +do_close (int s) +{ + int save; + + save = errno; + close (s); + __set_errno (save); +} + +int +rtime (struct sockaddr_in *addrp, struct rpc_timeval *timep, + struct rpc_timeval *timeout) +{ + int s; + struct pollfd fd; + int milliseconds; + int res; + /* RFC 868 says the time is transmitted as a 32-bit value. */ + uint32_t thetime; + struct sockaddr_in from; + socklen_t fromlen; + int type; + + if (timeout == NULL) + type = SOCK_STREAM; + else + type = SOCK_DGRAM; + + s = socket (AF_INET, type, 0); + if (s < 0) + return (-1); + + addrp->sin_family = AF_INET; + addrp->sin_port = htons (IPPORT_TIMESERVER); + if (type == SOCK_DGRAM) + { + res = sendto (s, (char *) &thetime, sizeof (thetime), 0, + (struct sockaddr *) addrp, sizeof (*addrp)); + if (res < 0) + { + do_close (s); + return -1; + } + milliseconds = (timeout->tv_sec * 1000) + (timeout->tv_usec / 1000); + fd.fd = s; + fd.events = POLLIN; + do + res = poll (&fd, 1, milliseconds); + while (res < 0 && errno == EINTR); + if (res <= 0) + { + if (res == 0) + __set_errno (ETIMEDOUT); + do_close (s); + return (-1); + } + fromlen = sizeof (from); + res = recvfrom (s, (char *) &thetime, sizeof (thetime), 0, + (struct sockaddr *) &from, &fromlen); + do_close (s); + if (res < 0) + return -1; + } + else + { + if (connect (s, (struct sockaddr *) addrp, sizeof (*addrp)) < 0) + { + do_close (s); + return -1; + } + res = read (s, (char *) &thetime, sizeof (thetime)); + do_close (s); + if (res < 0) + return (-1); + } + if (res != sizeof (thetime)) + { + __set_errno (EIO); + return -1; + } + thetime = ntohl (thetime); + timep->tv_sec = thetime - TOFFSET; + timep->tv_usec = 0; + return 0; +} +libc_hidden_def (rtime) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/ruserpass.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/ruserpass.c new file mode 100644 index 00000000..0e4b74fc --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/ruserpass.c @@ -0,0 +1,325 @@ +/* + * Copyright (c) 1985, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#define __FORCE_GLIBC +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define _(X) (X) +/* #include "ftp_var.h" */ + +static int token (void); +static FILE *cfile; + +#define DEFAULT 1 +#define LOGIN 2 +#define PASSWD 3 +#define ACCOUNT 4 +#define MACDEF 5 +#define ID 10 +#define MACHINE 11 + +static char tokval[100]; + +static const char tokstr[] = +{ +#define TOK_DEFAULT_IDX 0 + "default\0" +#define TOK_LOGIN_IDX (TOK_DEFAULT_IDX + sizeof "default") + "login\0" +#define TOK_PASSWORD_IDX (TOK_LOGIN_IDX + sizeof "login") + "password\0" +#define TOK_PASSWD_IDX (TOK_PASSWORD_IDX + sizeof "password") + "passwd\0" +#define TOK_ACCOUNT_IDX (TOK_PASSWD_IDX + sizeof "passwd") + "account\0" +#define TOK_MACHINE_IDX (TOK_ACCOUNT_IDX + sizeof "account") + "machine\0" +#define TOK_MACDEF_IDX (TOK_MACHINE_IDX + sizeof "machine") + "macdef" +}; + +static const struct toktab { + int tokstr_off; + int tval; +} toktab[]= { + { TOK_DEFAULT_IDX, DEFAULT }, + { TOK_LOGIN_IDX, LOGIN }, + { TOK_PASSWORD_IDX, PASSWD }, + { TOK_PASSWD_IDX, PASSWD }, + { TOK_ACCOUNT_IDX, ACCOUNT }, + { TOK_MACHINE_IDX, MACHINE }, + { TOK_MACDEF_IDX, MACDEF } +}; + + +/* ruserpass - remote password check. + This function also exists in glibc but is undocumented */ +int ruserpass(const char *host, const char **aname, const char **apass) +{ + char *hdir, *buf, *tmp; + char myname[1024], *mydomain; + int t, usedefault = 0; + struct stat stb; + + /* Give up when running a setuid or setgid app. */ + if ((getuid() != geteuid()) || getgid() != getegid()) + return -1; + hdir = getenv("HOME"); + if (hdir == NULL) { + /* If we can't get HOME, fail instead of trying ".", + which is no improvement. */ + return -1; + } + + buf = alloca (strlen(hdir) + 8); + strcpy(buf, hdir); + strcat(buf, "/.netrc"); + cfile = fopen(buf, "r"); + if (cfile == NULL) { + if (errno != ENOENT) + printf("%s", buf); + return (0); + } + /* No threads use this stream. */ +#ifdef __UCLIBC_HAS_THREADS__ + __fsetlocking (cfile, FSETLOCKING_BYCALLER); +#endif + if (gethostname(myname, sizeof(myname)) < 0) + myname[0] = '\0'; + mydomain = strchr(myname, '.'); + if (mydomain==NULL) { + mydomain=myname + strlen(myname); + } +next: + while ((t = token())) switch(t) { + + case DEFAULT: + usedefault = 1; + /* FALL THROUGH */ + + case MACHINE: + if (!usedefault) { + if (token() != ID) + continue; + /* + * Allow match either for user's input host name + * or official hostname. Also allow match of + * incompletely-specified host in local domain. + */ + if (strcasecmp(host, tokval) == 0) + goto match; + if ((tmp = strchr(host, '.')) != NULL && + strcasecmp(tmp, mydomain) == 0 && + strncasecmp(host, tokval, tmp - host) == 0 && + tokval[tmp - host] == '\0') + goto match; + continue; + } + match: + while ((t = token()) && t != MACHINE && t != DEFAULT) switch(t) { + + case LOGIN: + if (token()) { + if (*aname == 0) { + char *newp; + newp = malloc((unsigned) strlen(tokval) + 1); + if (newp == NULL) + { + printf(_("out of memory")); + goto bad; + } + *aname = strcpy(newp, tokval); + } else { + if (strcmp(*aname, tokval)) + goto next; + } + } + break; + case PASSWD: + if (strcmp(*aname, "anonymous") && + fstat(fileno(cfile), &stb) >= 0 && + (stb.st_mode & 077) != 0) { + printf(_("Error: .netrc file is readable by others.")); + printf(_("Remove password or make file unreadable by others.")); + goto bad; + } + if (token() && *apass == 0) { + char *newp; + newp = malloc((unsigned) strlen(tokval) + 1); + if (newp == NULL) + { + printf(_("out of memory")); + goto bad; + } + *apass = strcpy(newp, tokval); + } + break; + case ACCOUNT: +#if 0 + if (fstat(fileno(cfile), &stb) >= 0 + && (stb.st_mode & 077) != 0) { + printf("Error: .netrc file is readable by others."); + printf("Remove account or make file unreadable by others."); + goto bad; + } + if (token() && *aacct == 0) { + *aacct = malloc((unsigned) strlen(tokval) + 1); + (void) strcpy(*aacct, tokval); + } +#endif + break; + case MACDEF: +#if 0 + if (proxy) { + (void) fclose(cfile); + return (0); + } + while ((c=getc_unlocked(cfile)) != EOF && c == ' ' + || c == '\t'); + if (c == EOF || c == '\n') { + printf("Missing macdef name argument.\n"); + goto bad; + } + if (macnum == 16) { + printf("Limit of 16 macros have already been defined\n"); + goto bad; + } + tmp = macros[macnum].mac_name; + *tmp++ = c; + for (i=0; i < 8 && (c=getc_unlocked(cfile)) != EOF && + !isspace(c); ++i) { + *tmp++ = c; + } + if (c == EOF) { + printf("Macro definition missing null line terminator.\n"); + goto bad; + } + *tmp = '\0'; + if (c != '\n') { + while ((c=getc_unlocked(cfile)) != EOF + && c != '\n'); + } + if (c == EOF) { + printf("Macro definition missing null line terminator.\n"); + goto bad; + } + if (macnum == 0) { + macros[macnum].mac_start = macbuf; + } + else { + macros[macnum].mac_start = macros[macnum-1].mac_end + 1; + } + tmp = macros[macnum].mac_start; + while (tmp != macbuf + 4096) { + if ((c=getc_unlocked(cfile)) == EOF) { + printf("Macro definition missing null line terminator.\n"); + goto bad; + } + *tmp = c; + if (*tmp == '\n') { + if (*(tmp-1) == '\0') { + macros[macnum++].mac_end = tmp - 1; + break; + } + *tmp = '\0'; + } + tmp++; + } + if (tmp == macbuf + 4096) { + printf("4K macro buffer exceeded\n"); + goto bad; + } +#endif + break; + default: + printf(_("Unknown .netrc keyword %s"), tokval); + break; + } + goto done; + } +done: + (void) fclose(cfile); + return (0); +bad: + (void) fclose(cfile); + return (-1); +} +libc_hidden_def(ruserpass) + +static int +token(void) +{ + char *cp; + int c; + int i; + + if (feof_unlocked(cfile) || ferror_unlocked(cfile)) + return (0); + while ((c = getc_unlocked(cfile)) != EOF && + (c == '\n' || c == '\t' || c == ' ' || c == ',')) + continue; + if (c == EOF) + return (0); + cp = tokval; + if (c == '"') { + while ((c = getc_unlocked(cfile)) != EOF && c != '"') { + if (c == '\\') + c = getc_unlocked(cfile); + *cp++ = c; + } + } else { + *cp++ = c; + while ((c = getc_unlocked(cfile)) != EOF + && c != '\n' && c != '\t' && c != ' ' && c != ',') { + if (c == '\\') + c = getc_unlocked(cfile); + *cp++ = c; + } + } + *cp = 0; + if (tokval[0] == 0) + return (0); + for (i = 0; i < (int) (sizeof (toktab) / sizeof (toktab[0])); ++i) + if (!strcmp(&tokstr[toktab[i].tokstr_off], tokval)) + return toktab[i].tval; + return (ID); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/sa_len.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/sa_len.c new file mode 100644 index 00000000..3b37eba4 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/sa_len.c @@ -0,0 +1,63 @@ +/* Copyright (C) 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define __FORCE_GLIBC +#include +#include +#include +#include +#include +#if 0 +#include +#include +#include +#include +#include +#include +#endif + +int __libc_sa_len (sa_family_t af) attribute_hidden; +int __libc_sa_len (sa_family_t af) +{ + switch (af) + { +#if 0 + case AF_APPLETALK: + return sizeof (struct sockaddr_at); + case AF_ASH: + return sizeof (struct sockaddr_ash); + case AF_AX25: + return sizeof (struct sockaddr_ax25); + case AF_ECONET: + return sizeof (struct sockaddr_ec); + case AF_ROSE: + return sizeof (struct sockaddr_rose); + case AF_PACKET: + return sizeof (struct sockaddr_ll); +#endif + case AF_INET: + return sizeof (struct sockaddr_in); + case AF_INET6: + return sizeof (struct sockaddr_in6); + case AF_IPX: + return sizeof (struct sockaddr_ipx); + case AF_LOCAL: + return sizeof (struct sockaddr_un); + } + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/svc.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/svc.c new file mode 100644 index 00000000..0f5300c8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/svc.c @@ -0,0 +1,505 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +/* + * svc.c, Server-side remote procedure call interface. + * + * There are two sets of procedures here. The xprt routines are + * for handling transport handles. The svc routines handle the + * list of service routines. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +#define __FORCE_GLIBC +#include + +#include +#include +#include "rpc_private.h" +#include +#include +#include + +/* used by svc_[max_]pollfd */ +/* used by svc_fdset */ + +#ifdef __UCLIBC_HAS_THREADS__ +#define xports (*(SVCXPRT ***)&RPC_THREAD_VARIABLE(svc_xports_s)) +#else +static SVCXPRT **xports; +#endif + +#define NULL_SVC ((struct svc_callout *)0) +#define RQCRED_SIZE 400 /* this size is excessive */ + +/* The services list + Each entry represents a set of procedures (an rpc program). + The dispatch routine takes request structs and runs the + appropriate procedure. */ +struct svc_callout { + struct svc_callout *sc_next; + rpcprog_t sc_prog; + rpcvers_t sc_vers; + void (*sc_dispatch) (struct svc_req *, SVCXPRT *); +}; +#ifdef __UCLIBC_HAS_THREADS__ +#define svc_head (*(struct svc_callout **)&RPC_THREAD_VARIABLE(svc_head_s)) +#else +static struct svc_callout *svc_head; +#endif + +/* *************** SVCXPRT related stuff **************** */ + +/* Activate a transport handle. */ +void +xprt_register (SVCXPRT *xprt) +{ + register int sock = xprt->xp_sock; + register int i; + + if (xports == NULL) + { + xports = (SVCXPRT **) malloc (_rpc_dtablesize () * sizeof (SVCXPRT *)); + if (xports == NULL) /* Don´t add handle */ + return; + } + + if (sock < _rpc_dtablesize ()) + { + xports[sock] = xprt; + if (sock < FD_SETSIZE) + FD_SET (sock, &svc_fdset); + + /* Check if we have an empty slot */ + for (i = 0; i < svc_max_pollfd; ++i) + if (svc_pollfd[i].fd == -1) + { + svc_pollfd[i].fd = sock; + svc_pollfd[i].events = (POLLIN | POLLPRI | + POLLRDNORM | POLLRDBAND); + return; + } + + ++svc_max_pollfd; + svc_pollfd = realloc (svc_pollfd, + sizeof (struct pollfd) * svc_max_pollfd); + if (svc_pollfd == NULL) /* Out of memory */ + return; + + svc_pollfd[svc_max_pollfd - 1].fd = sock; + svc_pollfd[svc_max_pollfd - 1].events = (POLLIN | POLLPRI | + POLLRDNORM | POLLRDBAND); + } +} +libc_hidden_def(xprt_register) + +/* De-activate a transport handle. */ +void +xprt_unregister (SVCXPRT *xprt) +{ + register int sock = xprt->xp_sock; + register int i; + + if ((sock < _rpc_dtablesize ()) && (xports[sock] == xprt)) + { + xports[sock] = (SVCXPRT *) 0; + + if (sock < FD_SETSIZE) + FD_CLR (sock, &svc_fdset); + + for (i = 0; i < svc_max_pollfd; ++i) + if (svc_pollfd[i].fd == sock) + svc_pollfd[i].fd = -1; + } +} +libc_hidden_def(xprt_unregister) + + +/* ********************** CALLOUT list related stuff ************* */ + +/* Search the callout list for a program number, return the callout + struct. */ +static struct svc_callout * +svc_find (rpcprog_t prog, rpcvers_t vers, struct svc_callout **prev) +{ + register struct svc_callout *s, *p; + + p = NULL_SVC; + for (s = svc_head; s != NULL_SVC; s = s->sc_next) + { + if ((s->sc_prog == prog) && (s->sc_vers == vers)) + goto done; + p = s; + } +done: + *prev = p; + return s; +} + +/* Add a service program to the callout list. + The dispatch routine will be called when a rpc request for this + program number comes in. */ +bool_t +svc_register (SVCXPRT * xprt, rpcprog_t prog, rpcvers_t vers, + void (*dispatch) (struct svc_req *, SVCXPRT *), + rpcproc_t protocol) +{ + struct svc_callout *prev; + register struct svc_callout *s; + + if ((s = svc_find (prog, vers, &prev)) != NULL_SVC) + { + if (s->sc_dispatch == dispatch) + goto pmap_it; /* he is registering another xptr */ + return FALSE; + } + s = (struct svc_callout *) mem_alloc (sizeof (struct svc_callout)); + if (s == (struct svc_callout *) 0) + return FALSE; + + s->sc_prog = prog; + s->sc_vers = vers; + s->sc_dispatch = dispatch; + s->sc_next = svc_head; + svc_head = s; + +pmap_it: + /* now register the information with the local binder service */ + if (protocol) + return pmap_set (prog, vers, protocol, xprt->xp_port); + + return TRUE; +} +libc_hidden_def(svc_register) + +/* Remove a service program from the callout list. */ +void +svc_unregister (rpcprog_t prog, rpcvers_t vers) +{ + struct svc_callout *prev; + register struct svc_callout *s; + + if ((s = svc_find (prog, vers, &prev)) == NULL_SVC) + return; + + if (prev == NULL_SVC) + svc_head = s->sc_next; + else + prev->sc_next = s->sc_next; + + s->sc_next = NULL_SVC; + mem_free ((char *) s, (u_int) sizeof (struct svc_callout)); + /* now unregister the information with the local binder service */ + pmap_unset (prog, vers); +} +libc_hidden_def(svc_unregister) + +/* ******************* REPLY GENERATION ROUTINES ************ */ + +/* Send a reply to an rpc request */ +bool_t +svc_sendreply (register SVCXPRT *xprt, xdrproc_t xdr_results, + caddr_t xdr_location) +{ + struct rpc_msg rply; + + rply.rm_direction = REPLY; + rply.rm_reply.rp_stat = MSG_ACCEPTED; + rply.acpted_rply.ar_verf = xprt->xp_verf; + rply.acpted_rply.ar_stat = SUCCESS; + rply.acpted_rply.ar_results.where = xdr_location; + rply.acpted_rply.ar_results.proc = xdr_results; + return SVC_REPLY (xprt, &rply); +} +libc_hidden_def(svc_sendreply) + +/* No procedure error reply */ +void +svcerr_noproc (register SVCXPRT *xprt) +{ + struct rpc_msg rply; + + rply.rm_direction = REPLY; + rply.rm_reply.rp_stat = MSG_ACCEPTED; + rply.acpted_rply.ar_verf = xprt->xp_verf; + rply.acpted_rply.ar_stat = PROC_UNAVAIL; + SVC_REPLY (xprt, &rply); +} + +/* Can't decode args error reply */ +void +svcerr_decode (register SVCXPRT *xprt) +{ + struct rpc_msg rply; + + rply.rm_direction = REPLY; + rply.rm_reply.rp_stat = MSG_ACCEPTED; + rply.acpted_rply.ar_verf = xprt->xp_verf; + rply.acpted_rply.ar_stat = GARBAGE_ARGS; + SVC_REPLY (xprt, &rply); +} +libc_hidden_def(svcerr_decode) + +/* Some system error */ +void +svcerr_systemerr (register SVCXPRT *xprt) +{ + struct rpc_msg rply; + + rply.rm_direction = REPLY; + rply.rm_reply.rp_stat = MSG_ACCEPTED; + rply.acpted_rply.ar_verf = xprt->xp_verf; + rply.acpted_rply.ar_stat = SYSTEM_ERR; + SVC_REPLY (xprt, &rply); +} + +/* Authentication error reply */ +void +svcerr_auth (SVCXPRT *xprt, enum auth_stat why) +{ + struct rpc_msg rply; + + rply.rm_direction = REPLY; + rply.rm_reply.rp_stat = MSG_DENIED; + rply.rjcted_rply.rj_stat = AUTH_ERROR; + rply.rjcted_rply.rj_why = why; + SVC_REPLY (xprt, &rply); +} +libc_hidden_def(svcerr_auth) + +/* Auth too weak error reply */ +void +svcerr_weakauth (SVCXPRT *xprt) +{ + svcerr_auth (xprt, AUTH_TOOWEAK); +} + +/* Program unavailable error reply */ +void +svcerr_noprog (register SVCXPRT *xprt) +{ + struct rpc_msg rply; + + rply.rm_direction = REPLY; + rply.rm_reply.rp_stat = MSG_ACCEPTED; + rply.acpted_rply.ar_verf = xprt->xp_verf; + rply.acpted_rply.ar_stat = PROG_UNAVAIL; + SVC_REPLY (xprt, &rply); +} +libc_hidden_def(svcerr_noprog) + +/* Program version mismatch error reply */ +void +svcerr_progvers (register SVCXPRT *xprt, rpcvers_t low_vers, + rpcvers_t high_vers) +{ + struct rpc_msg rply; + + rply.rm_direction = REPLY; + rply.rm_reply.rp_stat = MSG_ACCEPTED; + rply.acpted_rply.ar_verf = xprt->xp_verf; + rply.acpted_rply.ar_stat = PROG_MISMATCH; + rply.acpted_rply.ar_vers.low = low_vers; + rply.acpted_rply.ar_vers.high = high_vers; + SVC_REPLY (xprt, &rply); +} +libc_hidden_def(svcerr_progvers) + +/* ******************* SERVER INPUT STUFF ******************* */ + +/* + * Get server side input from some transport. + * + * Statement of authentication parameters management: + * This function owns and manages all authentication parameters, specifically + * the "raw" parameters (msg.rm_call.cb_cred and msg.rm_call.cb_verf) and + * the "cooked" credentials (rqst->rq_clntcred). + * However, this function does not know the structure of the cooked + * credentials, so it make the following assumptions: + * a) the structure is contiguous (no pointers), and + * b) the cred structure size does not exceed RQCRED_SIZE bytes. + * In all events, all three parameters are freed upon exit from this routine. + * The storage is trivially management on the call stack in user land, but + * is mallocated in kernel land. + */ + +void +svc_getreq_common (const int fd) +{ + enum xprt_stat stat; + struct rpc_msg msg; + register SVCXPRT *xprt; + char cred_area[2 * MAX_AUTH_BYTES + RQCRED_SIZE]; + msg.rm_call.cb_cred.oa_base = cred_area; + msg.rm_call.cb_verf.oa_base = &(cred_area[MAX_AUTH_BYTES]); + + xprt = xports[fd]; + /* Do we control fd? */ + if (xprt == NULL) + return; + + /* now receive msgs from xprtprt (support batch calls) */ + do + { + if (SVC_RECV (xprt, &msg)) + { + /* now find the exported program and call it */ + struct svc_callout *s; + struct svc_req r; + enum auth_stat why; + rpcvers_t low_vers; + rpcvers_t high_vers; + int prog_found; + + r.rq_clntcred = &(cred_area[2 * MAX_AUTH_BYTES]); + r.rq_xprt = xprt; + r.rq_prog = msg.rm_call.cb_prog; + r.rq_vers = msg.rm_call.cb_vers; + r.rq_proc = msg.rm_call.cb_proc; + r.rq_cred = msg.rm_call.cb_cred; + + /* first authenticate the message */ + /* Check for null flavor and bypass these calls if possible */ + + if (msg.rm_call.cb_cred.oa_flavor == AUTH_NULL) + { + r.rq_xprt->xp_verf.oa_flavor = _null_auth.oa_flavor; + r.rq_xprt->xp_verf.oa_length = 0; + } + else if ((why = _authenticate (&r, &msg)) != AUTH_OK) + { + svcerr_auth (xprt, why); + goto call_done; + } + + /* now match message with a registered service */ + prog_found = FALSE; + low_vers = 0 - 1; + high_vers = 0; + + for (s = svc_head; s != NULL_SVC; s = s->sc_next) + { + if (s->sc_prog == r.rq_prog) + { + if (s->sc_vers == r.rq_vers) + { + (*s->sc_dispatch) (&r, xprt); + goto call_done; + } + /* found correct version */ + prog_found = TRUE; + if (s->sc_vers < low_vers) + low_vers = s->sc_vers; + if (s->sc_vers > high_vers) + high_vers = s->sc_vers; + } + /* found correct program */ + } + /* if we got here, the program or version + is not served ... */ + if (prog_found) + svcerr_progvers (xprt, low_vers, high_vers); + else + svcerr_noprog (xprt); + /* Fall through to ... */ + } + call_done: + if ((stat = SVC_STAT (xprt)) == XPRT_DIED) + { + SVC_DESTROY (xprt); + break; + } + } + while (stat == XPRT_MOREREQS); +} +libc_hidden_def(svc_getreq_common) + +void +svc_getreqset (fd_set *readfds) +{ + register u_int32_t mask; + register u_int32_t *maskp; + register int setsize; + register int sock; + register int bit; + + setsize = _rpc_dtablesize (); + maskp = (u_int32_t *) readfds->fds_bits; + for (sock = 0; sock < setsize; sock += 32) + for (mask = *maskp++; (bit = ffs (mask)); mask ^= (1 << (bit - 1))) + svc_getreq_common (sock + bit - 1); +} +libc_hidden_def(svc_getreqset) + +void +svc_getreq (int rdfds) +{ + fd_set readfds; + + FD_ZERO (&readfds); + readfds.fds_bits[0] = rdfds; + svc_getreqset (&readfds); +} +libc_hidden_def(svc_getreq) + +void +svc_getreq_poll (struct pollfd *pfdp, int pollretval) +{ + register int i; + register int fds_found; + + for (i = fds_found = 0; i < svc_max_pollfd && fds_found < pollretval; ++i) + { + register struct pollfd *p = &pfdp[i]; + + if (p->fd != -1 && p->revents) + { + /* fd has input waiting */ + ++fds_found; + + if (p->revents & POLLNVAL) + xprt_unregister (xports[p->fd]); + else + svc_getreq_common (p->fd); + } + } +} +libc_hidden_def(svc_getreq_poll) + +#ifdef __UCLIBC_HAS_THREADS__ + +void attribute_hidden __rpc_thread_svc_cleanup (void) +{ + struct svc_callout *svcp; + + while ((svcp = svc_head) != NULL) + svc_unregister (svcp->sc_prog, svcp->sc_vers); +} + +#endif /* __UCLIBC_HAS_THREADS__ */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/svc_auth.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/svc_auth.c new file mode 100644 index 00000000..ae02a44b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/svc_auth.c @@ -0,0 +1,124 @@ +/* @(#)svc_auth.c 2.4 88/08/15 4.0 RPCSRC */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +#if 0 +static char sccsid[] = "@(#)svc_auth.c 1.19 87/08/11 Copyr 1984 Sun Micro"; +#endif + +/* + * svc_auth.c, Server-side rpc authenticator interface. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +#include +#include +#include + +/* + * svcauthsw is the bdevsw of server side authentication. + * + * Server side authenticators are called from authenticate by + * using the client auth struct flavor field to index into svcauthsw. + * The server auth flavors must implement a routine that looks + * like: + * + * enum auth_stat + * flavorx_auth(rqst, msg) + * register struct svc_req *rqst; + * register struct rpc_msg *msg; + * + */ + +static enum auth_stat _svcauth_null (struct svc_req *, struct rpc_msg *); + /* no authentication */ +extern enum auth_stat _svcauth_unix (struct svc_req *, struct rpc_msg *); + /* unix style (uid, gids) */ +extern enum auth_stat _svcauth_short (struct svc_req *, struct rpc_msg *); + /* short hand unix style */ +#ifdef CONFIG_AUTH_DES +extern enum auth_stat _svcauth_des (struct svc_req *, struct rpc_msg *); + /* des style */ +#endif + +static const struct + { + enum auth_stat (*authenticator) (struct svc_req *, struct rpc_msg *); + } +svcauthsw[] = +{ + { _svcauth_null }, /* AUTH_NULL */ + { _svcauth_unix }, /* AUTH_UNIX */ + { _svcauth_short }, /* AUTH_SHORT */ +#ifdef CONFIG_AUTH_DES + { _svcauth_des } /* AUTH_DES */ +#endif +}; +#define AUTH_MAX 3 /* HIGHEST AUTH NUMBER */ + + +/* + * The call rpc message, msg has been obtained from the wire. The msg contains + * the raw form of credentials and verifiers. authenticate returns AUTH_OK + * if the msg is successfully authenticated. If AUTH_OK then the routine also + * does the following things: + * set rqst->rq_xprt->verf to the appropriate response verifier; + * sets rqst->rq_client_cred to the "cooked" form of the credentials. + * + * NB: rqst->rq_cxprt->verf must be pre-allocated; + * its length is set appropriately. + * + * The caller still owns and is responsible for msg->u.cmb.cred and + * msg->u.cmb.verf. The authentication system retains ownership of + * rqst->rq_client_cred, the cooked credentials. + * + * There is an assumption that any flavour less than AUTH_NULL is + * invalid. + */ +enum auth_stat +_authenticate (register struct svc_req *rqst, struct rpc_msg *msg) +{ + register int cred_flavor; + + rqst->rq_cred = msg->rm_call.cb_cred; + rqst->rq_xprt->xp_verf.oa_flavor = _null_auth.oa_flavor; + rqst->rq_xprt->xp_verf.oa_length = 0; + cred_flavor = rqst->rq_cred.oa_flavor; + if ((cred_flavor <= AUTH_MAX) && (cred_flavor >= AUTH_NULL)) + return (*(svcauthsw[cred_flavor].authenticator)) (rqst, msg); + + return AUTH_REJECTEDCRED; +} +libc_hidden_def(_authenticate) + +static enum auth_stat +_svcauth_null (struct svc_req *rqst attribute_unused, struct rpc_msg *msg attribute_unused) +{ + return AUTH_OK; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/svc_authux.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/svc_authux.c new file mode 100644 index 00000000..03ec4d3b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/svc_authux.c @@ -0,0 +1,159 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +/* + * svc_auth_unix.c + * Handles UNIX flavor authentication parameters on the service side of rpc. + * There are two svc auth implementations here: AUTH_UNIX and AUTH_SHORT. + * _svcauth_unix does full blown unix style uid,gid+gids auth, + * _svcauth_short uses a shorthand auth to index into a cache of longhand auths. + * Note: the shorthand has been gutted for efficiency. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +#define __FORCE_GLIBC +#include + +#include +#include +#include +#include + + +/* + * Unix longhand authenticator + */ +enum auth_stat +_svcauth_unix (struct svc_req *rqst, struct rpc_msg *msg) attribute_hidden; +enum auth_stat +_svcauth_unix (struct svc_req *rqst, struct rpc_msg *msg) +{ + enum auth_stat stat; + XDR xdrs; + struct authunix_parms *aup; + int32_t *buf; + struct area + { + struct authunix_parms area_aup; + char area_machname[MAX_MACHINE_NAME + 1]; + gid_t area_gids[NGRPS]; + } + *area; + u_int auth_len; + u_int str_len, gid_len; + u_int i; + + area = (struct area *) rqst->rq_clntcred; + aup = &area->area_aup; + aup->aup_machname = area->area_machname; + aup->aup_gids = area->area_gids; + auth_len = (u_int) msg->rm_call.cb_cred.oa_length; + xdrmem_create (&xdrs, msg->rm_call.cb_cred.oa_base, auth_len, XDR_DECODE); + buf = XDR_INLINE (&xdrs, auth_len); + if (buf != NULL) + { + aup->aup_time = IXDR_GET_LONG (buf); + str_len = IXDR_GET_U_INT32 (buf); + if (str_len > MAX_MACHINE_NAME) + { + stat = AUTH_BADCRED; + goto done; + } + memcpy (aup->aup_machname, (caddr_t) buf, (u_int) str_len); + aup->aup_machname[str_len] = 0; + str_len = RNDUP (str_len); + buf = (int32_t *) ((char *) buf + str_len); + aup->aup_uid = IXDR_GET_LONG (buf); + aup->aup_gid = IXDR_GET_LONG (buf); + gid_len = IXDR_GET_U_INT32 (buf); + if (gid_len > NGRPS) + { + stat = AUTH_BADCRED; + goto done; + } + aup->aup_len = gid_len; + for (i = 0; i < gid_len; i++) + { + aup->aup_gids[i] = IXDR_GET_LONG (buf); + } + /* + * five is the smallest unix credentials structure - + * timestamp, hostname len (0), uid, gid, and gids len (0). + */ + if ((5 + gid_len) * BYTES_PER_XDR_UNIT + str_len > auth_len) + { + (void) printf ("bad auth_len gid %d str %d auth %d\n", + gid_len, str_len, auth_len); + stat = AUTH_BADCRED; + goto done; + } + } + else if (!xdr_authunix_parms (&xdrs, aup)) + { + xdrs.x_op = XDR_FREE; + (void) xdr_authunix_parms (&xdrs, aup); + stat = AUTH_BADCRED; + goto done; + } + + /* get the verifier */ + if ((u_int)msg->rm_call.cb_verf.oa_length) + { + rqst->rq_xprt->xp_verf.oa_flavor = + msg->rm_call.cb_verf.oa_flavor; + rqst->rq_xprt->xp_verf.oa_base = + msg->rm_call.cb_verf.oa_base; + rqst->rq_xprt->xp_verf.oa_length = + msg->rm_call.cb_verf.oa_length; + } + else + { + rqst->rq_xprt->xp_verf.oa_flavor = AUTH_NULL; + rqst->rq_xprt->xp_verf.oa_length = 0; + } + stat = AUTH_OK; +done: + XDR_DESTROY (&xdrs); + return stat; +} + + +/* + * Shorthand unix authenticator + * Looks up longhand in a cache. + */ +/*ARGSUSED */ +enum auth_stat +_svcauth_short (struct svc_req *rqst attribute_unused, struct rpc_msg *msg attribute_unused) attribute_hidden; +enum auth_stat +_svcauth_short (struct svc_req *rqst attribute_unused, struct rpc_msg *msg attribute_unused) +{ + return AUTH_REJECTEDCRED; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/svc_raw.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/svc_raw.c new file mode 100644 index 00000000..f915a7d6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/svc_raw.c @@ -0,0 +1,166 @@ +/* @(#)svc_raw.c 2.1 88/07/29 4.0 RPCSRC */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +#if 0 +static char sccsid[] = "@(#)svc_raw.c 1.15 87/08/11 Copyr 1984 Sun Micro"; +#endif + +/* + * svc_raw.c, This a toy for simple testing and timing. + * Interface to create an rpc client and server in the same UNIX process. + * This lets us simulate rpc and get rpc (round trip) overhead, without + * any interference from the kernel. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +#define __FORCE_GLIBC +#include +#include "rpc_private.h" +#include + + +/* + * This is the "network" that we will be moving data over + */ +struct svcraw_private_s + { + char _raw_buf[UDPMSGSIZE]; + SVCXPRT server; + XDR xdr_stream; + char verf_body[MAX_AUTH_BYTES]; + }; +#ifdef __UCLIBC_HAS_THREADS__ +#define svcraw_private (*(struct svcraw_private_s **)&RPC_THREAD_VARIABLE(svcraw_private_s)) +#else +static struct svcraw_private_s *svcraw_private; +#endif + +static bool_t svcraw_recv (SVCXPRT *, struct rpc_msg *); +static enum xprt_stat svcraw_stat (SVCXPRT *); +static bool_t svcraw_getargs (SVCXPRT *, xdrproc_t, caddr_t); +static bool_t svcraw_reply (SVCXPRT *, struct rpc_msg *); +static bool_t svcraw_freeargs (SVCXPRT *, xdrproc_t, caddr_t); +static void svcraw_destroy (SVCXPRT *); + +static struct xp_ops server_ops = +{ + svcraw_recv, + svcraw_stat, + svcraw_getargs, + svcraw_reply, + svcraw_freeargs, + svcraw_destroy +}; + +SVCXPRT * +svcraw_create (void) +{ + struct svcraw_private_s *srp = svcraw_private; + + if (srp == 0) + { + srp = (struct svcraw_private_s *) calloc (1, sizeof (*srp)); + if (srp == 0) + return NULL; + } + srp->server.xp_sock = 0; + srp->server.xp_port = 0; + srp->server.xp_ops = &server_ops; + srp->server.xp_verf.oa_base = srp->verf_body; + xdrmem_create (&srp->xdr_stream, srp->_raw_buf, UDPMSGSIZE, XDR_FREE); + return &srp->server; +} + +static enum xprt_stat +svcraw_stat (SVCXPRT *xprt attribute_unused) +{ + return XPRT_IDLE; +} + +static bool_t +svcraw_recv (SVCXPRT *xprt attribute_unused, struct rpc_msg *msg) +{ + struct svcraw_private_s *srp = svcraw_private; + XDR *xdrs; + + if (srp == 0) + return FALSE; + xdrs = &srp->xdr_stream; + xdrs->x_op = XDR_DECODE; + XDR_SETPOS (xdrs, 0); + if (!xdr_callmsg (xdrs, msg)) + return FALSE; + return TRUE; +} + +static bool_t +svcraw_reply (SVCXPRT *xprt attribute_unused, struct rpc_msg *msg) +{ + struct svcraw_private_s *srp = svcraw_private; + XDR *xdrs; + + if (srp == 0) + return FALSE; + xdrs = &srp->xdr_stream; + xdrs->x_op = XDR_ENCODE; + XDR_SETPOS (xdrs, 0); + if (!xdr_replymsg (xdrs, msg)) + return FALSE; + (void) XDR_GETPOS (xdrs); /* called just for overhead */ + return TRUE; +} + +static bool_t +svcraw_getargs (SVCXPRT *xprt attribute_unused, xdrproc_t xdr_args, caddr_t args_ptr) +{ + struct svcraw_private_s *srp = svcraw_private; + + if (srp == 0) + return FALSE; + return (*xdr_args) (&srp->xdr_stream, args_ptr); +} + +static bool_t +svcraw_freeargs (SVCXPRT *xprt attribute_unused, xdrproc_t xdr_args, caddr_t args_ptr) +{ + struct svcraw_private_s *srp = svcraw_private; + XDR *xdrs; + + if (srp == 0) + return FALSE; + xdrs = &srp->xdr_stream; + xdrs->x_op = XDR_FREE; + return (*xdr_args) (xdrs, args_ptr); +} + +static void +svcraw_destroy (SVCXPRT *xprt attribute_unused) +{ +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/svc_run.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/svc_run.c new file mode 100644 index 00000000..1442cba5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/svc_run.c @@ -0,0 +1,90 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +/* + * This is the rpc server side idle loop + * Wait for input, call server program. + */ + +#define __FORCE_GLIBC +#include + +#include +#include +#include +#include + +/* used by svc_[max_]pollfd */ + +/* This function can be used as a signal handler to terminate the + server loop. */ +void +svc_exit (void) +{ + free (svc_pollfd); + svc_pollfd = NULL; + svc_max_pollfd = 0; +} + +void +svc_run (void) +{ + int i; + + for (;;) + { + struct pollfd *my_pollfd; + + if (svc_max_pollfd == 0 && svc_pollfd == NULL) + return; + + my_pollfd = malloc (sizeof (struct pollfd) * svc_max_pollfd); + for (i = 0; i < svc_max_pollfd; ++i) + { + my_pollfd[i].fd = svc_pollfd[i].fd; + my_pollfd[i].events = svc_pollfd[i].events; + my_pollfd[i].revents = 0; + } + + switch (i = poll (my_pollfd, svc_max_pollfd, -1)) + { + case -1: + free (my_pollfd); + if (errno == EINTR) + continue; + perror (_("svc_run: - poll failed")); + return; + case 0: + free (my_pollfd); + continue; + default: + svc_getreq_poll (my_pollfd, i); + free (my_pollfd); + } + } +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/svc_simple.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/svc_simple.c new file mode 100644 index 00000000..dceb6acb --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/svc_simple.c @@ -0,0 +1,197 @@ +/* @(#)svc_simple.c 2.2 88/08/01 4.0 RPCSRC */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +#if 0 +static char sccsid[] = "@(#)svc_simple.c 1.18 87/08/11 Copyr 1984 Sun Micro"; +#endif + +/* + * svc_simple.c + * Simplified front end to rpc. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +#define __FORCE_GLIBC +#include + +#include +#include +#include +#include "rpc_private.h" +#include +#include +#include + +#ifdef USE_IN_LIBIO +# include +# include +# define fputs(s, f) _IO_fputs (s, f) +#endif + + +struct proglst_ + { + char *(*p_progname) (char *); + int p_prognum; + int p_procnum; + xdrproc_t p_inproc, p_outproc; + struct proglst_ *p_nxt; + }; +#ifdef __UCLIBC_HAS_THREADS__ +#define proglst (*(struct proglst_ **)&RPC_THREAD_VARIABLE(svcsimple_proglst_s)) +#else +static struct proglst_ *proglst; +#endif + + +static void universal (struct svc_req *rqstp, SVCXPRT *transp_s); +#ifdef __UCLIBC_HAS_THREADS__ +#define transp (*(SVCXPRT **)&RPC_THREAD_VARIABLE(svcsimple_transp_s)) +#else +static SVCXPRT *transp; +#endif + +int registerrpc (u_long prognum, u_long versnum, u_long procnum, + char *(*progname) (char *), xdrproc_t inproc, xdrproc_t outproc); +int +registerrpc (u_long prognum, u_long versnum, u_long procnum, + char *(*progname) (char *), xdrproc_t inproc, xdrproc_t outproc) +{ + struct proglst_ *pl; + char *buf; + + if (procnum == NULLPROC) + { + + (void) asprintf (&buf, _("can't reassign procedure number %ld\n"), + NULLPROC); + goto err_out; + } + if (transp == 0) + { + transp = svcudp_create (RPC_ANYSOCK); + if (transp == NULL) + { + buf = strdup (_("couldn't create an rpc server\n")); + goto err_out; + } + } + (void) pmap_unset ((u_long) prognum, (u_long) versnum); + if (!svc_register (transp, (u_long) prognum, (u_long) versnum, + universal, IPPROTO_UDP)) + { + (void) asprintf (&buf, _("couldn't register prog %ld vers %ld\n"), + prognum, versnum); + goto err_out; + } + pl = (struct proglst_ *) malloc (sizeof (struct proglst_)); + if (pl == NULL) + { + buf = strdup (_("registerrpc: out of memory\n")); + goto err_out; + } + pl->p_progname = progname; + pl->p_prognum = prognum; + pl->p_procnum = procnum; + pl->p_inproc = inproc; + pl->p_outproc = outproc; + pl->p_nxt = proglst; + proglst = pl; + return 0; + + err_out: +#ifdef USE_IN_LIBIO + if (_IO_fwide (stderr, 0) > 0) + (void) __fwprintf (stderr, L"%s", buf); + else +#endif + (void) fputs (buf, stderr); + free (buf); + return -1; +} + +static void +universal (struct svc_req *rqstp, SVCXPRT *transp_l) +{ + int prog, proc; + char *outdata; + char xdrbuf[UDPMSGSIZE]; + struct proglst_ *pl; + char *buf = NULL; + + /* + * enforce "procnum 0 is echo" convention + */ + if (rqstp->rq_proc == NULLPROC) + { + if (svc_sendreply (transp_l, (xdrproc_t)xdr_void, (char *) NULL) == FALSE) + { + write (STDERR_FILENO, "xxx\n", 4); + exit (1); + } + return; + } + prog = rqstp->rq_prog; + proc = rqstp->rq_proc; + for (pl = proglst; pl != NULL; pl = pl->p_nxt) + if (pl->p_prognum == prog && pl->p_procnum == proc) + { + /* decode arguments into a CLEAN buffer */ + memset (xdrbuf, 0, sizeof (xdrbuf)); /* required ! */ + if (!svc_getargs (transp_l, pl->p_inproc, xdrbuf)) + { + svcerr_decode (transp_l); + return; + } + outdata = (*(pl->p_progname)) (xdrbuf); + if (outdata == NULL && pl->p_outproc != (xdrproc_t)xdr_void) + /* there was an error */ + return; + if (!svc_sendreply (transp_l, pl->p_outproc, outdata)) + { + (void) asprintf (&buf, + _("trouble replying to prog %d\n"), + pl->p_prognum); + exit (1); + } + /* free the decoded arguments */ + (void) svc_freeargs (transp_l, pl->p_inproc, xdrbuf); + return; + } + (void) asprintf (&buf, _("never registered prog %d\n"), prog); +#ifdef USE_IN_LIBIO + if (_IO_fwide (stderr, 0) > 0) + __fwprintf (stderr, L"%s", buf); + else +#endif + fputs (buf, stderr); + free (buf); + exit (1); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/svc_tcp.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/svc_tcp.c new file mode 100644 index 00000000..363f2031 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/svc_tcp.c @@ -0,0 +1,428 @@ +/* @(#)svc_tcp.c 2.2 88/08/01 4.0 RPCSRC */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +#if 0 +static char sccsid[] = "@(#)svc_tcp.c 1.21 87/08/11 Copyr 1984 Sun Micro"; +#endif + +/* + * svc_tcp.c, Server side for TCP/IP based RPC. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + * + * Actually implements two flavors of transporter - + * a tcp rendezvouser (a listener and connection establisher) + * and a record/tcp stream. + */ + +#define __FORCE_GLIBC +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef USE_IN_LIBIO +# include +# include +# define fputs(s, f) _IO_fputs (s, f) +#endif + + +/* + * Ops vector for TCP/IP based rpc service handle + */ +static bool_t svctcp_recv (SVCXPRT *, struct rpc_msg *); +static enum xprt_stat svctcp_stat (SVCXPRT *); +static bool_t svctcp_getargs (SVCXPRT *, xdrproc_t, caddr_t); +static bool_t svctcp_reply (SVCXPRT *, struct rpc_msg *); +static bool_t svctcp_freeargs (SVCXPRT *, xdrproc_t, caddr_t); +static void svctcp_destroy (SVCXPRT *); + +static const struct xp_ops svctcp_op = +{ + svctcp_recv, + svctcp_stat, + svctcp_getargs, + svctcp_reply, + svctcp_freeargs, + svctcp_destroy +}; + +/* + * Ops vector for TCP/IP rendezvous handler + */ +static bool_t rendezvous_request (SVCXPRT *, struct rpc_msg *); +static enum xprt_stat rendezvous_stat (SVCXPRT *); +static void svctcp_rendezvous_abort (void) attribute_noreturn; + +/* This function makes sure abort() relocation goes through PLT + and thus can be lazy bound. */ +static void +svctcp_rendezvous_abort (void) +{ + abort (); +}; + +static const struct xp_ops svctcp_rendezvous_op = +{ + rendezvous_request, + rendezvous_stat, + (bool_t (*) (SVCXPRT *, xdrproc_t, caddr_t)) svctcp_rendezvous_abort, + (bool_t (*) (SVCXPRT *, struct rpc_msg *)) svctcp_rendezvous_abort, + (bool_t (*) (SVCXPRT *, xdrproc_t, caddr_t)) svctcp_rendezvous_abort, + svctcp_destroy +}; + +static int readtcp (char*, char *, int); +static int writetcp (char *, char *, int); +static SVCXPRT *makefd_xprt (int, u_int, u_int) internal_function; + +struct tcp_rendezvous + { /* kept in xprt->xp_p1 */ + u_int sendsize; + u_int recvsize; + }; + +struct tcp_conn + { /* kept in xprt->xp_p1 */ + enum xprt_stat strm_stat; + u_long x_id; + XDR xdrs; + char verf_body[MAX_AUTH_BYTES]; + }; + +/* + * Usage: + * xprt = svctcp_create(sock, send_buf_size, recv_buf_size); + * + * Creates, registers, and returns a (rpc) tcp based transporter. + * Once *xprt is initialized, it is registered as a transporter + * see (svc.h, xprt_register). This routine returns + * a NULL if a problem occurred. + * + * If sock<0 then a socket is created, else sock is used. + * If the socket, sock is not bound to a port then svctcp_create + * binds it to an arbitrary port. The routine then starts a tcp + * listener on the socket's associated port. In any (successful) case, + * xprt->xp_sock is the registered socket number and xprt->xp_port is the + * associated port number. + * + * Since tcp streams do buffered io similar to stdio, the caller can specify + * how big the send and receive buffers are via the second and third parms; + * 0 => use the system default. + */ +SVCXPRT * +svctcp_create (int sock, u_int sendsize, u_int recvsize) +{ + bool_t madesock = FALSE; + SVCXPRT *xprt; + struct tcp_rendezvous *r; + struct sockaddr_in addr; + socklen_t len = sizeof (struct sockaddr_in); + + if (sock == RPC_ANYSOCK) + { + if ((sock = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) + { + perror (_("svc_tcp.c - tcp socket creation problem")); + return (SVCXPRT *) NULL; + } + madesock = TRUE; + } + memset ((char *) &addr, 0, sizeof (addr)); + addr.sin_family = AF_INET; + if (bindresvport (sock, &addr)) + { + addr.sin_port = 0; + (void) bind (sock, (struct sockaddr *) &addr, len); + } + if ((getsockname (sock, (struct sockaddr *) &addr, &len) != 0) || + (listen (sock, 2) != 0)) + { + perror (_("svc_tcp.c - cannot getsockname or listen")); + if (madesock) + (void) close (sock); + return (SVCXPRT *) NULL; + } + r = (struct tcp_rendezvous *) mem_alloc (sizeof (*r)); + xprt = (SVCXPRT *) mem_alloc (sizeof (SVCXPRT)); + if (r == NULL || xprt == NULL) + { +#ifdef USE_IN_LIBIO + if (_IO_fwide (stderr, 0) > 0) + (void) __fwprintf (stderr, L"%s", _("svctcp_create: out of memory\n")); + else +#endif + (void) fputs (_("svctcp_create: out of memory\n"), stderr); + mem_free (r, sizeof (*r)); + mem_free (xprt, sizeof (SVCXPRT)); + return NULL; + } + r->sendsize = sendsize; + r->recvsize = recvsize; + xprt->xp_p2 = NULL; + xprt->xp_p1 = (caddr_t) r; + xprt->xp_verf = _null_auth; + xprt->xp_ops = &svctcp_rendezvous_op; + xprt->xp_port = ntohs (addr.sin_port); + xprt->xp_sock = sock; + xprt_register (xprt); + return xprt; +} + +/* + * Like svtcp_create(), except the routine takes any *open* UNIX file + * descriptor as its first input. + */ +SVCXPRT * +svcfd_create (int fd, u_int sendsize, u_int recvsize); +SVCXPRT * +svcfd_create (int fd, u_int sendsize, u_int recvsize) +{ + return makefd_xprt (fd, sendsize, recvsize); +} + +static SVCXPRT * +internal_function +makefd_xprt (int fd, u_int sendsize, u_int recvsize) +{ + SVCXPRT *xprt; + struct tcp_conn *cd; + + xprt = (SVCXPRT *) mem_alloc (sizeof (SVCXPRT)); + cd = (struct tcp_conn *) mem_alloc (sizeof (struct tcp_conn)); + if (xprt == (SVCXPRT *) NULL || cd == NULL) + { +#ifdef USE_IN_LIBIO + if (_IO_fwide (stderr, 0) > 0) + (void) __fwprintf (stderr, L"%s", + _("svc_tcp: makefd_xprt: out of memory\n")); + else +#endif + (void) fputs (_("svc_tcp: makefd_xprt: out of memory\n"), stderr); + mem_free (xprt, sizeof (SVCXPRT)); + mem_free (cd, sizeof (struct tcp_conn)); + return NULL; + } + cd->strm_stat = XPRT_IDLE; + xdrrec_create (&(cd->xdrs), sendsize, recvsize, + (caddr_t) xprt, readtcp, writetcp); + xprt->xp_p2 = NULL; + xprt->xp_p1 = (caddr_t) cd; + xprt->xp_verf.oa_base = cd->verf_body; + xprt->xp_addrlen = 0; + xprt->xp_ops = &svctcp_op; /* truly deals with calls */ + xprt->xp_port = 0; /* this is a connection, not a rendezvouser */ + xprt->xp_sock = fd; + xprt_register (xprt); + return xprt; +} + +static bool_t +rendezvous_request (SVCXPRT *xprt, struct rpc_msg *errmsg attribute_unused) +{ + int sock; + struct tcp_rendezvous *r; + struct sockaddr_in addr; + socklen_t len; + + r = (struct tcp_rendezvous *) xprt->xp_p1; +again: + len = sizeof (struct sockaddr_in); + if ((sock = accept (xprt->xp_sock, (struct sockaddr *) &addr, &len)) < 0) + { + if (errno == EINTR) + goto again; + return FALSE; + } + /* + * make a new transporter (re-uses xprt) + */ + xprt = makefd_xprt (sock, r->sendsize, r->recvsize); + memcpy (&xprt->xp_raddr, &addr, sizeof (addr)); + xprt->xp_addrlen = len; + return FALSE; /* there is never an rpc msg to be processed */ +} + +static enum xprt_stat +rendezvous_stat (SVCXPRT *xprt attribute_unused) +{ + return XPRT_IDLE; +} + +static void +svctcp_destroy (SVCXPRT *xprt) +{ + struct tcp_conn *cd = (struct tcp_conn *) xprt->xp_p1; + + xprt_unregister (xprt); + (void) close (xprt->xp_sock); + if (xprt->xp_port != 0) + { + /* a rendezvouser socket */ + xprt->xp_port = 0; + } + else + { + /* an actual connection socket */ + XDR_DESTROY (&(cd->xdrs)); + } + mem_free ((caddr_t) cd, sizeof (struct tcp_conn)); + mem_free ((caddr_t) xprt, sizeof (SVCXPRT)); +} + + +/* + * reads data from the tcp connection. + * any error is fatal and the connection is closed. + * (And a read of zero bytes is a half closed stream => error.) + */ +static int +readtcp (char *xprtptr, char *buf, int len) +{ + SVCXPRT *xprt = (SVCXPRT *)xprtptr; + int sock = xprt->xp_sock; + int milliseconds = 35 * 1000; + struct pollfd pollfd; + + do + { + pollfd.fd = sock; + pollfd.events = POLLIN; + switch (poll (&pollfd, 1, milliseconds)) + { + case -1: + if (errno == EINTR) + continue; + /*FALLTHROUGH*/ + case 0: + goto fatal_err; + default: + if ((pollfd.revents & POLLERR) || (pollfd.revents & POLLHUP) + || (pollfd.revents & POLLNVAL)) + goto fatal_err; + break; + } + } + while ((pollfd.revents & POLLIN) == 0); + + if ((len = read (sock, buf, len)) > 0) + return len; + + fatal_err: + ((struct tcp_conn *) (xprt->xp_p1))->strm_stat = XPRT_DIED; + return -1; +} + +/* + * writes data to the tcp connection. + * Any error is fatal and the connection is closed. + */ +static int +writetcp (char *xprtptr, char * buf, int len) +{ + SVCXPRT *xprt = (SVCXPRT *)xprtptr; + int i, cnt; + + for (cnt = len; cnt > 0; cnt -= i, buf += i) + { + if ((i = write (xprt->xp_sock, buf, cnt)) < 0) + { + ((struct tcp_conn *) (xprt->xp_p1))->strm_stat = XPRT_DIED; + return -1; + } + } + return len; +} + +static enum xprt_stat +svctcp_stat (SVCXPRT *xprt) +{ + struct tcp_conn *cd = + (struct tcp_conn *) (xprt->xp_p1); + + if (cd->strm_stat == XPRT_DIED) + return XPRT_DIED; + if (!xdrrec_eof (&(cd->xdrs))) + return XPRT_MOREREQS; + return XPRT_IDLE; +} + +static bool_t +svctcp_recv (SVCXPRT *xprt, struct rpc_msg *msg) +{ + struct tcp_conn *cd = (struct tcp_conn *) (xprt->xp_p1); + XDR *xdrs = &(cd->xdrs); + + xdrs->x_op = XDR_DECODE; + (void) xdrrec_skiprecord (xdrs); + if (xdr_callmsg (xdrs, msg)) + { + cd->x_id = msg->rm_xid; + return TRUE; + } + cd->strm_stat = XPRT_DIED; /* XXXX */ + return FALSE; +} + +static bool_t +svctcp_getargs (SVCXPRT *xprt, xdrproc_t xdr_args, caddr_t args_ptr) +{ + return ((*xdr_args) (&(((struct tcp_conn *) + (xprt->xp_p1))->xdrs), args_ptr)); +} + +static bool_t +svctcp_freeargs (SVCXPRT *xprt, xdrproc_t xdr_args, caddr_t args_ptr) +{ + XDR *xdrs = &(((struct tcp_conn *) (xprt->xp_p1))->xdrs); + + xdrs->x_op = XDR_FREE; + return ((*xdr_args) (xdrs, args_ptr)); +} + +static bool_t +svctcp_reply (SVCXPRT *xprt, struct rpc_msg *msg) +{ + struct tcp_conn *cd = (struct tcp_conn *) (xprt->xp_p1); + XDR *xdrs = &(cd->xdrs); + bool_t stat; + + xdrs->x_op = XDR_ENCODE; + msg->rm_xid = cd->x_id; + stat = xdr_replymsg (xdrs, msg); + (void) xdrrec_endofrecord (xdrs, TRUE); + return stat; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/svc_udp.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/svc_udp.c new file mode 100644 index 00000000..87015c6c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/svc_udp.c @@ -0,0 +1,596 @@ +/* @(#)svc_udp.c 2.2 88/07/29 4.0 RPCSRC */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +#if 0 +static char sccsid[] = "@(#)svc_udp.c 1.24 87/08/11 Copyr 1984 Sun Micro"; +#endif + +/* + * svc_udp.c, + * Server side for UDP/IP based RPC. (Does some caching in the hopes of + * achieving execute-at-most-once semantics.) + * + * Copyright (C) 1984, Sun Microsystems, Inc. + */ + +#define __FORCE_GLIBC +#include + +#include +#include +#include +#include +#include +#include + +#ifdef IP_PKTINFO +#include +#endif + +#ifdef USE_IN_LIBIO +# include +# include +# define fputs(s, f) _IO_fputs (s, f) +#endif + + +#define rpc_buffer(xprt) ((xprt)->xp_p1) +#ifndef MAX +#define MAX(a, b) ((a > b) ? a : b) +#endif + +static bool_t svcudp_recv (SVCXPRT *, struct rpc_msg *); +static bool_t svcudp_reply (SVCXPRT *, struct rpc_msg *); +static enum xprt_stat svcudp_stat (SVCXPRT *); +static bool_t svcudp_getargs (SVCXPRT *, xdrproc_t, caddr_t); +static bool_t svcudp_freeargs (SVCXPRT *, xdrproc_t, caddr_t); +static void svcudp_destroy (SVCXPRT *); + +static const struct xp_ops svcudp_op = +{ + svcudp_recv, + svcudp_stat, + svcudp_getargs, + svcudp_reply, + svcudp_freeargs, + svcudp_destroy +}; + +static int cache_get (SVCXPRT *, struct rpc_msg *, char **replyp, + u_long *replylenp); +static void cache_set (SVCXPRT *xprt, u_long replylen); + +/* + * kept in xprt->xp_p2 + */ +struct svcudp_data + { + u_int su_iosz; /* byte size of send.recv buffer */ + u_long su_xid; /* transaction id */ + XDR su_xdrs; /* XDR handle */ + char su_verfbody[MAX_AUTH_BYTES]; /* verifier body */ + char *su_cache; /* cached data, NULL if no cache */ + }; +#define su_data(xprt) ((struct svcudp_data *)(xprt->xp_p2)) + +/* + * Usage: + * xprt = svcudp_create(sock); + * + * If sock<0 then a socket is created, else sock is used. + * If the socket, sock is not bound to a port then svcudp_create + * binds it to an arbitrary port. In any (successful) case, + * xprt->xp_sock is the registered socket number and xprt->xp_port is the + * associated port number. + * Once *xprt is initialized, it is registered as a transporter; + * see (svc.h, xprt_register). + * The routines returns NULL if a problem occurred. + */ +SVCXPRT * +svcudp_bufcreate (int sock, u_int sendsz, u_int recvsz) +{ + bool_t madesock = FALSE; + SVCXPRT *xprt; + struct svcudp_data *su; + struct sockaddr_in addr; + socklen_t len = sizeof (struct sockaddr_in); + int pad; + void *buf; + + if (sock == RPC_ANYSOCK) + { + if ((sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) + { + perror (_("svcudp_create: socket creation problem")); + return (SVCXPRT *) NULL; + } + madesock = TRUE; + } + memset ((char *) &addr, 0, sizeof (addr)); + addr.sin_family = AF_INET; + if (bindresvport (sock, &addr)) + { + addr.sin_port = 0; + (void) bind (sock, (struct sockaddr *) &addr, len); + } + if (getsockname (sock, (struct sockaddr *) &addr, &len) != 0) + { + perror (_("svcudp_create - cannot getsockname")); + if (madesock) + (void) close (sock); + return (SVCXPRT *) NULL; + } + xprt = (SVCXPRT *) mem_alloc (sizeof (SVCXPRT)); + su = (struct svcudp_data *) mem_alloc (sizeof (*su)); + buf = mem_alloc (((MAX (sendsz, recvsz) + 3) / 4) * 4); + if (xprt == NULL || su == NULL || buf == NULL) + { +#ifdef USE_IN_LIBIO + if (_IO_fwide (stderr, 0) > 0) + (void) fwprintf (stderr, L"%s", _("svcudp_create: out of memory\n")); + else +#endif + (void) fputs (_("svcudp_create: out of memory\n"), stderr); + mem_free (xprt, sizeof (SVCXPRT)); + mem_free (su, sizeof (*su)); + mem_free (buf, ((MAX (sendsz, recvsz) + 3) / 4) * 4); + return NULL; + } + su->su_iosz = ((MAX (sendsz, recvsz) + 3) / 4) * 4; + rpc_buffer (xprt) = buf; + xdrmem_create (&(su->su_xdrs), rpc_buffer (xprt), su->su_iosz, XDR_DECODE); + su->su_cache = NULL; + xprt->xp_p2 = (caddr_t) su; + xprt->xp_verf.oa_base = su->su_verfbody; + xprt->xp_ops = &svcudp_op; + xprt->xp_port = ntohs (addr.sin_port); + xprt->xp_sock = sock; + +#ifdef IP_PKTINFO + if ((sizeof (struct iovec) + sizeof (struct msghdr) + + sizeof(struct cmsghdr) + sizeof (struct in_pktinfo)) + > sizeof (xprt->xp_pad)) + { +# ifdef USE_IN_LIBIO + if (_IO_fwide (stderr, 0) > 0) + (void) fwprintf (stderr, L"%s", + _("svcudp_create: xp_pad is too small for IP_PKTINFO\n")); + else +# endif + (void) fputs (_("svcudp_create: xp_pad is too small for IP_PKTINFO\n"), + stderr); + return NULL; + } + pad = 1; + if (setsockopt (sock, SOL_IP, IP_PKTINFO, (void *) &pad, + sizeof (pad)) == 0) + /* Set the padding to all 1s. */ + pad = 0xff; + else +#endif + /* Clear the padding. */ + pad = 0; + memset (&xprt->xp_pad [0], pad, sizeof (xprt->xp_pad)); + + xprt_register (xprt); + return xprt; +} +libc_hidden_def(svcudp_bufcreate) + +SVCXPRT * +svcudp_create (int sock) +{ + + return svcudp_bufcreate (sock, UDPMSGSIZE, UDPMSGSIZE); +} +libc_hidden_def(svcudp_create) + +static enum xprt_stat +svcudp_stat (SVCXPRT *xprt attribute_unused) +{ + + return XPRT_IDLE; +} + +static bool_t +svcudp_recv (SVCXPRT *xprt, struct rpc_msg *msg) +{ + struct svcudp_data *su = su_data (xprt); + XDR *xdrs = &(su->su_xdrs); + int rlen; + char *reply; + u_long replylen; + socklen_t len; + + /* It is very tricky when you have IP aliases. We want to make sure + that we are sending the packet from the IP address where the + incoming packet is addressed to. H.J. */ +#ifdef IP_PKTINFO + struct iovec *iovp; + struct msghdr *mesgp; +#endif + +again: + /* FIXME -- should xp_addrlen be a size_t? */ + len = (socklen_t) sizeof(struct sockaddr_in); +#ifdef IP_PKTINFO + iovp = (struct iovec *) &xprt->xp_pad [0]; + mesgp = (struct msghdr *) &xprt->xp_pad [sizeof (struct iovec)]; + if (mesgp->msg_iovlen) + { + iovp->iov_base = rpc_buffer (xprt); + iovp->iov_len = su->su_iosz; + mesgp->msg_iov = iovp; + mesgp->msg_iovlen = 1; + mesgp->msg_name = &(xprt->xp_raddr); + mesgp->msg_namelen = len; + mesgp->msg_control = &xprt->xp_pad [sizeof (struct iovec) + + sizeof (struct msghdr)]; + mesgp->msg_controllen = sizeof(xprt->xp_pad) + - sizeof (struct iovec) - sizeof (struct msghdr); + rlen = recvmsg (xprt->xp_sock, mesgp, 0); + if (rlen >= 0) + len = mesgp->msg_namelen; + } + else +#endif + rlen = recvfrom (xprt->xp_sock, rpc_buffer (xprt), + (int) su->su_iosz, 0, + (struct sockaddr *) &(xprt->xp_raddr), &len); + xprt->xp_addrlen = len; + if (rlen == -1 && errno == EINTR) + goto again; + if (rlen < 16) /* < 4 32-bit ints? */ + return FALSE; + xdrs->x_op = XDR_DECODE; + XDR_SETPOS (xdrs, 0); + if (!xdr_callmsg (xdrs, msg)) + return FALSE; + su->su_xid = msg->rm_xid; + if (su->su_cache != NULL) + { + if (cache_get (xprt, msg, &reply, &replylen)) + { +#ifdef IP_PKTINFO + if (mesgp->msg_iovlen) + { + iovp->iov_base = reply; + iovp->iov_len = replylen; + (void) sendmsg (xprt->xp_sock, mesgp, 0); + } + else +#endif + (void) sendto (xprt->xp_sock, reply, (int) replylen, 0, + (struct sockaddr *) &xprt->xp_raddr, len); + return TRUE; + } + } + return TRUE; +} + +static bool_t +svcudp_reply (SVCXPRT *xprt, struct rpc_msg *msg) +{ + struct svcudp_data *su = su_data (xprt); + XDR *xdrs = &(su->su_xdrs); + int slen, sent; + bool_t stat = FALSE; +#ifdef IP_PKTINFO + struct iovec *iovp; + struct msghdr *mesgp; +#endif + + xdrs->x_op = XDR_ENCODE; + XDR_SETPOS (xdrs, 0); + msg->rm_xid = su->su_xid; + if (xdr_replymsg (xdrs, msg)) + { + slen = (int) XDR_GETPOS (xdrs); +#ifdef IP_PKTINFO + mesgp = (struct msghdr *) &xprt->xp_pad [sizeof (struct iovec)]; + if (mesgp->msg_iovlen) + { + iovp = (struct iovec *) &xprt->xp_pad [0]; + iovp->iov_base = rpc_buffer (xprt); + iovp->iov_len = slen; + sent = sendmsg (xprt->xp_sock, mesgp, 0); + } + else +#endif + sent = sendto (xprt->xp_sock, rpc_buffer (xprt), slen, 0, + (struct sockaddr *) &(xprt->xp_raddr), + xprt->xp_addrlen); + if (sent == slen) + { + stat = TRUE; + if (su->su_cache && slen >= 0) + { + cache_set (xprt, (u_long) slen); + } + } + } + return stat; +} + +static bool_t +svcudp_getargs (SVCXPRT *xprt, xdrproc_t xdr_args, caddr_t args_ptr) +{ + + return (*xdr_args) (&(su_data (xprt)->su_xdrs), args_ptr); +} + +static bool_t +svcudp_freeargs (SVCXPRT *xprt, xdrproc_t xdr_args, caddr_t args_ptr) +{ + XDR *xdrs = &(su_data (xprt)->su_xdrs); + + xdrs->x_op = XDR_FREE; + return (*xdr_args) (xdrs, args_ptr); +} + +static void +svcudp_destroy (SVCXPRT *xprt) +{ + struct svcudp_data *su = su_data (xprt); + + xprt_unregister (xprt); + (void) close (xprt->xp_sock); + XDR_DESTROY (&(su->su_xdrs)); + mem_free (rpc_buffer (xprt), su->su_iosz); + mem_free ((caddr_t) su, sizeof (struct svcudp_data)); + mem_free ((caddr_t) xprt, sizeof (SVCXPRT)); +} + + +/***********this could be a separate file*********************/ + +/* + * Fifo cache for udp server + * Copies pointers to reply buffers into fifo cache + * Buffers are sent again if retransmissions are detected. + */ + +#define SPARSENESS 4 /* 75% sparse */ + +#ifdef USE_IN_LIBIO +# define CACHE_PERROR(msg) \ + if (_IO_fwide (stderr, 0) > 0) \ + (void) __fwprintf(stderr, L"%s\n", msg); \ + else \ + (void) fprintf(stderr, "%s\n", msg) +#else +# define CACHE_PERROR(msg) \ + (void) fprintf(stderr,"%s\n", msg) +#endif + +#define ALLOC(type, size) \ + (type *) mem_alloc((unsigned) (sizeof(type) * (size))) + +#define BZERO(addr, type, size) \ + memset((char *) addr, 0, sizeof(type) * (int) (size)) + +/* + * An entry in the cache + */ +typedef struct cache_node *cache_ptr; +struct cache_node + { + /* + * Index into cache is xid, proc, vers, prog and address + */ + u_long cache_xid; + u_long cache_proc; + u_long cache_vers; + u_long cache_prog; + struct sockaddr_in cache_addr; + /* + * The cached reply and length + */ + char *cache_reply; + u_long cache_replylen; + /* + * Next node on the list, if there is a collision + */ + cache_ptr cache_next; + }; + + + +/* + * The entire cache + */ +struct udp_cache + { + u_long uc_size; /* size of cache */ + cache_ptr *uc_entries; /* hash table of entries in cache */ + cache_ptr *uc_fifo; /* fifo list of entries in cache */ + u_long uc_nextvictim; /* points to next victim in fifo list */ + u_long uc_prog; /* saved program number */ + u_long uc_vers; /* saved version number */ + u_long uc_proc; /* saved procedure number */ + struct sockaddr_in uc_addr; /* saved caller's address */ + }; + + +/* + * the hashing function + */ +#define CACHE_LOC(transp, xid) \ + (xid % (SPARSENESS*((struct udp_cache *) su_data(transp)->su_cache)->uc_size)) + + +/* + * Enable use of the cache. + * Note: there is no disable. + */ +int svcudp_enablecache (SVCXPRT *transp, u_long size); +int +svcudp_enablecache (SVCXPRT *transp, u_long size) +{ + struct svcudp_data *su = su_data (transp); + struct udp_cache *uc; + + if (su->su_cache != NULL) + { + CACHE_PERROR (_("enablecache: cache already enabled")); + return 0; + } + uc = ALLOC (struct udp_cache, 1); + if (uc == NULL) + { + CACHE_PERROR (_("enablecache: could not allocate cache")); + return 0; + } + uc->uc_size = size; + uc->uc_nextvictim = 0; + uc->uc_entries = ALLOC (cache_ptr, size * SPARSENESS); + if (uc->uc_entries == NULL) + { + CACHE_PERROR (_("enablecache: could not allocate cache data")); + return 0; + } + BZERO (uc->uc_entries, cache_ptr, size * SPARSENESS); + uc->uc_fifo = ALLOC (cache_ptr, size); + if (uc->uc_fifo == NULL) + { + CACHE_PERROR (_("enablecache: could not allocate cache fifo")); + return 0; + } + BZERO (uc->uc_fifo, cache_ptr, size); + su->su_cache = (char *) uc; + return 1; +} + + +/* + * Set an entry in the cache + */ +static void +cache_set (SVCXPRT *xprt, u_long replylen) +{ + cache_ptr victim; + cache_ptr *vicp; + struct svcudp_data *su = su_data (xprt); + struct udp_cache *uc = (struct udp_cache *) su->su_cache; + u_int loc; + char *newbuf; + + /* + * Find space for the new entry, either by + * reusing an old entry, or by mallocing a new one + */ + victim = uc->uc_fifo[uc->uc_nextvictim]; + if (victim != NULL) + { + loc = CACHE_LOC (xprt, victim->cache_xid); + for (vicp = &uc->uc_entries[loc]; + *vicp != NULL && *vicp != victim; + vicp = &(*vicp)->cache_next) + ; + if (*vicp == NULL) + { + CACHE_PERROR (_("cache_set: victim not found")); + return; + } + *vicp = victim->cache_next; /* remote from cache */ + newbuf = victim->cache_reply; + } + else + { + victim = ALLOC (struct cache_node, 1); + if (victim == NULL) + { + CACHE_PERROR (_("cache_set: victim alloc failed")); + return; + } + newbuf = mem_alloc (su->su_iosz); + if (newbuf == NULL) + { + CACHE_PERROR (_("cache_set: could not allocate new rpc_buffer")); + return; + } + } + + /* + * Store it away + */ + victim->cache_replylen = replylen; + victim->cache_reply = rpc_buffer (xprt); + rpc_buffer (xprt) = newbuf; + xdrmem_create (&(su->su_xdrs), rpc_buffer (xprt), su->su_iosz, XDR_ENCODE); + victim->cache_xid = su->su_xid; + victim->cache_proc = uc->uc_proc; + victim->cache_vers = uc->uc_vers; + victim->cache_prog = uc->uc_prog; + victim->cache_addr = uc->uc_addr; + loc = CACHE_LOC (xprt, victim->cache_xid); + victim->cache_next = uc->uc_entries[loc]; + uc->uc_entries[loc] = victim; + uc->uc_fifo[uc->uc_nextvictim++] = victim; + uc->uc_nextvictim %= uc->uc_size; +} + +/* + * Try to get an entry from the cache + * return 1 if found, 0 if not found + */ +static int +cache_get (SVCXPRT *xprt, struct rpc_msg *msg, char **replyp, u_long *replylenp) +{ + u_int loc; + cache_ptr ent; + struct svcudp_data *su = su_data (xprt); + struct udp_cache *uc = (struct udp_cache *) su->su_cache; + +#define EQADDR(a1, a2) (memcmp((char*)&a1, (char*)&a2, sizeof(a1)) == 0) + + loc = CACHE_LOC (xprt, su->su_xid); + for (ent = uc->uc_entries[loc]; ent != NULL; ent = ent->cache_next) + { + if (ent->cache_xid == su->su_xid && + ent->cache_proc == uc->uc_proc && + ent->cache_vers == uc->uc_vers && + ent->cache_prog == uc->uc_prog && + EQADDR (ent->cache_addr, uc->uc_addr)) + { + *replyp = ent->cache_reply; + *replylenp = ent->cache_replylen; + return 1; + } + } + /* + * Failed to find entry + * Remember a few things so we can do a set later + */ + uc->uc_proc = msg->rm_call.cb_proc; + uc->uc_vers = msg->rm_call.cb_vers; + uc->uc_prog = msg->rm_call.cb_prog; + memcpy (&uc->uc_addr, &xprt->xp_raddr, sizeof (uc->uc_addr)); + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/svc_unix.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/svc_unix.c new file mode 100644 index 00000000..61859773 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/svc_unix.c @@ -0,0 +1,536 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +/* + * svc_unix.c, Server side for TCP/IP based RPC. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + * + * Actually implements two flavors of transporter - + * a unix rendezvouser (a listener and connection establisher) + * and a record/unix stream. + */ + +#define __FORCE_GLIBC +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef USE_IN_LIBIO +# include +#endif + + +/* + * Ops vector for AF_UNIX based rpc service handle + */ +static bool_t svcunix_recv (SVCXPRT *, struct rpc_msg *); +static enum xprt_stat svcunix_stat (SVCXPRT *); +static bool_t svcunix_getargs (SVCXPRT *, xdrproc_t, caddr_t); +static bool_t svcunix_reply (SVCXPRT *, struct rpc_msg *); +static bool_t svcunix_freeargs (SVCXPRT *, xdrproc_t, caddr_t); +static void svcunix_destroy (SVCXPRT *); + +static const struct xp_ops svcunix_op = +{ + svcunix_recv, + svcunix_stat, + svcunix_getargs, + svcunix_reply, + svcunix_freeargs, + svcunix_destroy +}; + +/* + * Ops vector for AF_UNIX rendezvous handler + */ +static bool_t rendezvous_request (SVCXPRT *, struct rpc_msg *); +static enum xprt_stat rendezvous_stat (SVCXPRT *); +static void svcunix_rendezvous_abort (void) attribute_noreturn; + +/* This function makes sure abort() relocation goes through PLT + and thus can be lazy bound. */ +static void +svcunix_rendezvous_abort (void) +{ + abort (); +}; + +static const struct xp_ops svcunix_rendezvous_op = +{ + rendezvous_request, + rendezvous_stat, + (bool_t (*) (SVCXPRT *, xdrproc_t, caddr_t)) svcunix_rendezvous_abort, + (bool_t (*) (SVCXPRT *, struct rpc_msg *)) svcunix_rendezvous_abort, + (bool_t (*) (SVCXPRT *, xdrproc_t, caddr_t)) svcunix_rendezvous_abort, + svcunix_destroy +}; + +static int readunix (char*, char *, int); +static int writeunix (char *, char *, int); +static SVCXPRT *makefd_xprt (int, u_int, u_int) internal_function; + +struct unix_rendezvous { /* kept in xprt->xp_p1 */ + u_int sendsize; + u_int recvsize; +}; + +struct unix_conn { /* kept in xprt->xp_p1 */ + enum xprt_stat strm_stat; + u_long x_id; + XDR xdrs; + char verf_body[MAX_AUTH_BYTES]; +}; + +/* + * Usage: + * xprt = svcunix_create(sock, send_buf_size, recv_buf_size); + * + * Creates, registers, and returns a (rpc) unix based transporter. + * Once *xprt is initialized, it is registered as a transporter + * see (svc.h, xprt_register). This routine returns + * a NULL if a problem occurred. + * + * If sock<0 then a socket is created, else sock is used. + * If the socket, sock is not bound to a port then svcunix_create + * binds it to an arbitrary port. The routine then starts a unix + * listener on the socket's associated port. In any (successful) case, + * xprt->xp_sock is the registered socket number and xprt->xp_port is the + * associated port number. + * + * Since unix streams do buffered io similar to stdio, the caller can specify + * how big the send and receive buffers are via the second and third parms; + * 0 => use the system default. + */ +SVCXPRT * +svcunix_create (int sock, u_int sendsize, u_int recvsize, char *path) +{ + bool_t madesock = FALSE; + SVCXPRT *xprt; + struct unix_rendezvous *r; + struct sockaddr_un addr; + socklen_t len = sizeof (struct sockaddr_in); + + if (sock == RPC_ANYSOCK) + { + if ((sock = socket (AF_UNIX, SOCK_STREAM, 0)) < 0) + { + perror (_("svc_unix.c - AF_UNIX socket creation problem")); + return (SVCXPRT *) NULL; + } + madesock = TRUE; + } + memset (&addr, '\0', sizeof (addr)); + addr.sun_family = AF_UNIX; + len = strlen (path) + 1; + memcpy (addr.sun_path, path, len); + len += sizeof (addr.sun_family); + + bind (sock, (struct sockaddr *) &addr, len); + + if (getsockname (sock, (struct sockaddr *) &addr, &len) != 0 + || listen (sock, 2) != 0) + { + perror (_("svc_unix.c - cannot getsockname or listen")); + if (madesock) + close (sock); + return (SVCXPRT *) NULL; + } + + r = (struct unix_rendezvous *) mem_alloc (sizeof (*r)); + xprt = (SVCXPRT *) mem_alloc (sizeof (SVCXPRT)); + if (r == NULL || xprt == NULL) + { +#ifdef USE_IN_LIBIO + if (_IO_fwide (stderr, 0) > 0) + __fwprintf (stderr, L"%s", _("svcunix_create: out of memory\n")); + else +#endif + fputs (_("svcunix_create: out of memory\n"), stderr); + mem_free (r, sizeof (*r)); + mem_free (xprt, sizeof (SVCXPRT)); + return NULL; + } + r->sendsize = sendsize; + r->recvsize = recvsize; + xprt->xp_p2 = NULL; + xprt->xp_p1 = (caddr_t) r; + xprt->xp_verf = _null_auth; + xprt->xp_ops = &svcunix_rendezvous_op; + xprt->xp_port = -1; + xprt->xp_sock = sock; + xprt_register (xprt); + return xprt; +} + +/* + * Like svunix_create(), except the routine takes any *open* UNIX file + * descriptor as its first input. + */ +SVCXPRT * +svcunixfd_create (int fd, u_int sendsize, u_int recvsize); +SVCXPRT * +svcunixfd_create (int fd, u_int sendsize, u_int recvsize) +{ + return makefd_xprt (fd, sendsize, recvsize); +} + +static SVCXPRT * +internal_function +makefd_xprt (int fd, u_int sendsize, u_int recvsize) +{ + SVCXPRT *xprt; + struct unix_conn *cd; + + xprt = (SVCXPRT *) mem_alloc (sizeof (SVCXPRT)); + cd = (struct unix_conn *) mem_alloc (sizeof (struct unix_conn)); + if (xprt == (SVCXPRT *) NULL || cd == (struct unix_conn *) NULL) + { +#ifdef USE_IN_LIBIO + if (_IO_fwide (stderr, 0) > 0) + (void) __fwprintf (stderr, L"%s", + _("svc_unix: makefd_xprt: out of memory\n")); + else +#endif + (void) fputs (_("svc_unix: makefd_xprt: out of memory\n"), stderr); + mem_free (xprt, sizeof (SVCXPRT)); + mem_free (cd, sizeof (struct unix_conn)); + return NULL; + } + cd->strm_stat = XPRT_IDLE; + xdrrec_create (&(cd->xdrs), sendsize, recvsize, + (caddr_t) xprt, readunix, writeunix); + xprt->xp_p2 = NULL; + xprt->xp_p1 = (caddr_t) cd; + xprt->xp_verf.oa_base = cd->verf_body; + xprt->xp_addrlen = 0; + xprt->xp_ops = &svcunix_op; /* truly deals with calls */ + xprt->xp_port = 0; /* this is a connection, not a rendezvouser */ + xprt->xp_sock = fd; + xprt_register (xprt); + return xprt; +} + +static bool_t +rendezvous_request (SVCXPRT *xprt, struct rpc_msg *errmsg attribute_unused) +{ + int sock; + struct unix_rendezvous *r; + struct sockaddr_un addr; + struct sockaddr_in in_addr; + socklen_t len; + + r = (struct unix_rendezvous *) xprt->xp_p1; +again: + len = sizeof (struct sockaddr_un); + if ((sock = accept (xprt->xp_sock, (struct sockaddr *) &addr, &len)) < 0) + { + if (errno == EINTR) + goto again; + return FALSE; + } + /* + * make a new transporter (re-uses xprt) + */ + memset (&in_addr, '\0', sizeof (in_addr)); + in_addr.sin_family = AF_UNIX; + xprt = makefd_xprt (sock, r->sendsize, r->recvsize); + memcpy (&xprt->xp_raddr, &in_addr, sizeof (in_addr)); + xprt->xp_addrlen = len; + return FALSE; /* there is never an rpc msg to be processed */ +} + +static enum xprt_stat +rendezvous_stat (SVCXPRT *xprt attribute_unused) +{ + return XPRT_IDLE; +} + +static void +svcunix_destroy (SVCXPRT *xprt) +{ + struct unix_conn *cd = (struct unix_conn *) xprt->xp_p1; + + xprt_unregister (xprt); + close (xprt->xp_sock); + if (xprt->xp_port != 0) + { + /* a rendezvouser socket */ + xprt->xp_port = 0; + } + else + { + /* an actual connection socket */ + XDR_DESTROY (&(cd->xdrs)); + } + mem_free ((caddr_t) cd, sizeof (struct unix_conn)); + mem_free ((caddr_t) xprt, sizeof (SVCXPRT)); +} + +#ifdef SCM_CREDENTIALS +struct cmessage { + struct cmsghdr cmsg; + struct ucred cmcred; + /* hack to make sure we have enough memory */ + char dummy[(CMSG_ALIGN (sizeof (struct ucred)) - sizeof (struct ucred) + sizeof (long))]; +}; + +/* XXX This is not thread safe, but since the main functions in svc.c + and the rpcgen generated *_svc functions for the daemon are also not + thread safe and uses static global variables, it doesn't matter. */ +static struct cmessage cm; +#endif + +static int +__msgread (int sock, void *data, size_t cnt) +{ + struct iovec iov; + struct msghdr msg; + int len; + + iov.iov_base = data; + iov.iov_len = cnt; + + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_name = NULL; + msg.msg_namelen = 0; +#ifdef SCM_CREDENTIALS + msg.msg_control = (caddr_t) &cm; + msg.msg_controllen = sizeof (struct cmessage); +#endif + msg.msg_flags = 0; + +#ifdef SO_PASSCRED + { + int on = 1; + if (setsockopt (sock, SOL_SOCKET, SO_PASSCRED, &on, sizeof (on))) + return -1; + } +#endif + + restart: + len = recvmsg (sock, &msg, 0); + if (len >= 0) + { + if (msg.msg_flags & MSG_CTRUNC || len == 0) + return 0; + else + return len; + } + if (errno == EINTR) + goto restart; + return -1; +} + +static int +__msgwrite (int sock, void *data, size_t cnt) +{ +#ifndef SCM_CREDENTIALS + /* We cannot implement this reliably. */ + __set_errno (ENOSYS); + return -1; +#else + struct iovec iov; + struct msghdr msg; + struct cmsghdr *cmsg = &cm.cmsg; + struct ucred cred; + int len; + + /* XXX I'm not sure, if gete?id() is always correct, or if we should use + get?id(). But since keyserv needs geteuid(), we have no other chance. + It would be much better, if the kernel could pass both to the server. */ + cred.pid = getpid (); + cred.uid = geteuid (); + cred.gid = getegid (); + + memcpy (CMSG_DATA(cmsg), &cred, sizeof (struct ucred)); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_CREDENTIALS; + cmsg->cmsg_len = sizeof(*cmsg) + sizeof(struct ucred); + + iov.iov_base = data; + iov.iov_len = cnt; + + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_name = NULL; + msg.msg_namelen = 0; + msg.msg_control = cmsg; + msg.msg_controllen = CMSG_ALIGN(cmsg->cmsg_len); + msg.msg_flags = 0; + + restart: + len = sendmsg (sock, &msg, 0); + if (len >= 0) + return len; + if (errno == EINTR) + goto restart; + return -1; + +#endif +} + +/* + * reads data from the unix connection. + * any error is fatal and the connection is closed. + * (And a read of zero bytes is a half closed stream => error.) + */ +static int +readunix (char *xprtptr, char *buf, int len) +{ + SVCXPRT *xprt = (SVCXPRT *) xprtptr; + int sock = xprt->xp_sock; + int milliseconds = 35 * 1000; + struct pollfd pollfd; + + do + { + pollfd.fd = sock; + pollfd.events = POLLIN; + switch (poll (&pollfd, 1, milliseconds)) + { + case -1: + if (errno == EINTR) + continue; + /*FALLTHROUGH*/ + case 0: + goto fatal_err; + default: + if ((pollfd.revents & POLLERR) || (pollfd.revents & POLLHUP) + || (pollfd.revents & POLLNVAL)) + goto fatal_err; + break; + } + } + while ((pollfd.revents & POLLIN) == 0); + + if ((len = __msgread (sock, buf, len)) > 0) + return len; + + fatal_err: + ((struct unix_conn *) (xprt->xp_p1))->strm_stat = XPRT_DIED; + return -1; +} + +/* + * writes data to the unix connection. + * Any error is fatal and the connection is closed. + */ +static int +writeunix (char *xprtptr, char * buf, int len) +{ + SVCXPRT *xprt = (SVCXPRT *) xprtptr; + int i, cnt; + + for (cnt = len; cnt > 0; cnt -= i, buf += i) + { + if ((i = __msgwrite (xprt->xp_sock, buf, cnt)) < 0) + { + ((struct unix_conn *) (xprt->xp_p1))->strm_stat = XPRT_DIED; + return -1; + } + } + return len; +} + +static enum xprt_stat +svcunix_stat (SVCXPRT *xprt) +{ + struct unix_conn *cd = + (struct unix_conn *) (xprt->xp_p1); + + if (cd->strm_stat == XPRT_DIED) + return XPRT_DIED; + if (!xdrrec_eof (&(cd->xdrs))) + return XPRT_MOREREQS; + return XPRT_IDLE; +} + +static bool_t +svcunix_recv (SVCXPRT *xprt, struct rpc_msg *msg) +{ + struct unix_conn *cd = (struct unix_conn *) (xprt->xp_p1); + XDR *xdrs = &(cd->xdrs); + + xdrs->x_op = XDR_DECODE; + xdrrec_skiprecord (xdrs); + if (xdr_callmsg (xdrs, msg)) + { + cd->x_id = msg->rm_xid; + /* set up verifiers */ +#ifdef SCM_CREDENTIALS + msg->rm_call.cb_verf.oa_flavor = AUTH_UNIX; + msg->rm_call.cb_verf.oa_base = (caddr_t) &cm; + msg->rm_call.cb_verf.oa_length = sizeof (cm); +#endif + return TRUE; + } + cd->strm_stat = XPRT_DIED; /* XXXX */ + return FALSE; +} + +static bool_t +svcunix_getargs (SVCXPRT *xprt, xdrproc_t xdr_args, caddr_t args_ptr) +{ + return (*xdr_args) (&(((struct unix_conn *) (xprt->xp_p1))->xdrs), + args_ptr); +} + +static bool_t +svcunix_freeargs (SVCXPRT *xprt, xdrproc_t xdr_args, caddr_t args_ptr) +{ + XDR *xdrs = &(((struct unix_conn *) (xprt->xp_p1))->xdrs); + + xdrs->x_op = XDR_FREE; + return (*xdr_args) (xdrs, args_ptr); +} + +static bool_t +svcunix_reply (SVCXPRT *xprt, struct rpc_msg *msg) +{ + struct unix_conn *cd = (struct unix_conn *) (xprt->xp_p1); + XDR *xdrs = &(cd->xdrs); + bool_t stat; + + xdrs->x_op = XDR_ENCODE; + msg->rm_xid = cd->x_id; + stat = xdr_replymsg (xdrs, msg); + (void) xdrrec_endofrecord (xdrs, TRUE); + return stat; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/xdr.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/xdr.c new file mode 100644 index 00000000..bcf89017 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/xdr.c @@ -0,0 +1,745 @@ +/* @(#)xdr.c 2.1 88/07/29 4.0 RPCSRC */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +#if 0 +static char sccsid[] = "@(#)xdr.c 1.35 87/08/12"; +#endif + +/* + * xdr.c, Generic XDR routines implementation. + * + * Copyright (C) 1986, Sun Microsystems, Inc. + * + * These are the "generic" xdr routines used to serialize and de-serialize + * most common data items. See xdr.h for more info on the interface to + * xdr. + */ + +#define __FORCE_GLIBC +#include + +#include +#include +#include + +#include +#include + +#ifdef USE_IN_LIBIO +# include +#endif + + +/* + * constants specific to the xdr "protocol" + */ +#define XDR_FALSE ((long) 0) +#define XDR_TRUE ((long) 1) +#define LASTUNSIGNED ((u_int) 0-1) + +/* + * for unit alignment + */ +static const char xdr_zero[BYTES_PER_XDR_UNIT] = {0, 0, 0, 0}; + +/* + * Free a data structure using XDR + * Not a filter, but a convenient utility nonetheless + */ +void +xdr_free (xdrproc_t proc, char *objp) +{ + XDR x; + + x.x_op = XDR_FREE; + (*proc) (&x, objp); +} + +/* + * XDR nothing + */ +bool_t +xdr_void (void) +{ + return TRUE; +} +libc_hidden_def(xdr_void) + +/* + * XDR long integers + * The definition of xdr_long() is kept for backward + * compatibility. Instead xdr_int() should be used. + */ +bool_t +xdr_long (XDR *xdrs, long *lp) +{ + if (xdrs->x_op == XDR_ENCODE + && (sizeof (int32_t) == sizeof (long) + || (int32_t) *lp == *lp)) + return XDR_PUTLONG (xdrs, lp); + + if (xdrs->x_op == XDR_DECODE) + return XDR_GETLONG (xdrs, lp); + + if (xdrs->x_op == XDR_FREE) + return TRUE; + + return FALSE; +} +libc_hidden_def(xdr_long) + +/* + * XDR short integers + */ +bool_t +xdr_short (XDR *xdrs, short *sp) +{ + long l; + + switch (xdrs->x_op) + { + case XDR_ENCODE: + l = (long) *sp; + return XDR_PUTLONG (xdrs, &l); + + case XDR_DECODE: + if (!XDR_GETLONG (xdrs, &l)) + { + return FALSE; + } + *sp = (short) l; + return TRUE; + + case XDR_FREE: + return TRUE; + } + return FALSE; +} +libc_hidden_def(xdr_short) + +/* + * XDR integers + */ +bool_t +xdr_int (XDR *xdrs, int *ip) +{ + +#if INT_MAX < LONG_MAX + long l; + + switch (xdrs->x_op) + { + case XDR_ENCODE: + l = (long) *ip; + return XDR_PUTLONG (xdrs, &l); + + case XDR_DECODE: + if (!XDR_GETLONG (xdrs, &l)) + { + return FALSE; + } + *ip = (int) l; + case XDR_FREE: + return TRUE; + } + return FALSE; +#elif INT_MAX == LONG_MAX + return xdr_long (xdrs, (long *) ip); +#elif INT_MAX == SHRT_MAX + return xdr_short (xdrs, (short *) ip); +#else +#error unexpected integer sizes in xdr_int() +#endif +} +libc_hidden_def(xdr_int) + +/* + * XDR unsigned long integers + * The definition of xdr_u_long() is kept for backward + * compatibility. Instead xdr_u_int() should be used. + */ +bool_t +xdr_u_long (XDR *xdrs, u_long *ulp) +{ + switch (xdrs->x_op) + { + case XDR_DECODE: + { + long int tmp; + + if (XDR_GETLONG (xdrs, &tmp) == FALSE) + return FALSE; + + *ulp = (uint32_t) tmp; + return TRUE; + } + + case XDR_ENCODE: + if (sizeof (uint32_t) != sizeof (u_long) + && (uint32_t) *ulp != *ulp) + return FALSE; + + return XDR_PUTLONG (xdrs, (long *) ulp); + + case XDR_FREE: + return TRUE; + } + return FALSE; +} +libc_hidden_def(xdr_u_long) + +/* + * XDR unsigned integers + */ +bool_t +xdr_u_int (XDR *xdrs, u_int *up) +{ +#if UINT_MAX < ULONG_MAX + u_long l; + + switch (xdrs->x_op) + { + case XDR_ENCODE: + l = (u_long) * up; + return XDR_PUTLONG (xdrs, (long *) &l); + + case XDR_DECODE: + if (!XDR_GETLONG (xdrs, (long *) &l)) + { + return FALSE; + } + *up = (u_int) l; + case XDR_FREE: + return TRUE; + } + return FALSE; +#elif UINT_MAX == ULONG_MAX + return xdr_u_long (xdrs, (u_long *) up); +#elif UINT_MAX == USHRT_MAX + return xdr_short (xdrs, (short *) up); +#else +#error unexpected integer sizes in xdr_u_int() +#endif +} +libc_hidden_def(xdr_u_int) + +/* + * XDR hyper integers + * same as xdr_u_hyper - open coded to save a proc call! + */ +bool_t +xdr_hyper (XDR *xdrs, quad_t *llp) +{ + long t1; + unsigned long t2; + + if (xdrs->x_op == XDR_ENCODE) + { + t1 = (long) ((*llp) >> 32); + t2 = (long) (*llp); + return (XDR_PUTLONG(xdrs, &t1) && XDR_PUTLONG(xdrs, (long *) &t2)); + } + + if (xdrs->x_op == XDR_DECODE) + { + if (!XDR_GETLONG(xdrs, &t1) || !XDR_GETLONG(xdrs, (long *) &t2)) + return FALSE; + /* t2 must be unsigned for this to work */ + *llp = ((quad_t) t1) << 32; + *llp |= t2; + return TRUE; + } + + if (xdrs->x_op == XDR_FREE) + return TRUE; + + return FALSE; +} +libc_hidden_def(xdr_hyper) + + +/* + * XDR hyper integers + * same as xdr_hyper - open coded to save a proc call! + */ +bool_t +xdr_u_hyper (XDR *xdrs, u_quad_t *ullp) +{ + unsigned long t1; + unsigned long t2; + + if (xdrs->x_op == XDR_ENCODE) + { + t1 = (unsigned long) ((*ullp) >> 32); + t2 = (unsigned long) (*ullp); + return (XDR_PUTLONG(xdrs, (long *) &t1) && XDR_PUTLONG(xdrs, (long *) &t2)); + } + + if (xdrs->x_op == XDR_DECODE) + { + if (!XDR_GETLONG(xdrs, (long *) &t1) || !XDR_GETLONG(xdrs, (long *) &t2)) + return FALSE; + *ullp = ((u_quad_t) t1) << 32; + *ullp |= t2; + return TRUE; + } + + if (xdrs->x_op == XDR_FREE) + return TRUE; + + return FALSE; +} +libc_hidden_def(xdr_u_hyper) + +bool_t +xdr_longlong_t (XDR *xdrs, quad_t *llp) +{ + return xdr_hyper (xdrs, llp); +} + +bool_t +xdr_u_longlong_t (XDR *xdrs, u_quad_t *ullp) +{ + return xdr_u_hyper (xdrs, ullp); +} + +/* + * XDR unsigned short integers + */ +bool_t +xdr_u_short (XDR *xdrs, u_short *usp) +{ + u_long l; + + switch (xdrs->x_op) + { + case XDR_ENCODE: + l = (u_long) * usp; + return XDR_PUTLONG (xdrs, (long *) &l); + + case XDR_DECODE: + if (!XDR_GETLONG (xdrs, (long *) &l)) + { + return FALSE; + } + *usp = (u_short) l; + return TRUE; + + case XDR_FREE: + return TRUE; + } + return FALSE; +} +libc_hidden_def(xdr_u_short) + + +/* + * XDR a char + */ +bool_t +xdr_char (XDR *xdrs, char *cp) +{ + int i; + + i = (*cp); + if (!xdr_int (xdrs, &i)) + { + return FALSE; + } + *cp = i; + return TRUE; +} + +/* + * XDR an unsigned char + */ +bool_t +xdr_u_char (XDR *xdrs, u_char *cp) +{ + u_int u; + + u = (*cp); + if (!xdr_u_int (xdrs, &u)) + { + return FALSE; + } + *cp = u; + return TRUE; +} + +/* + * XDR booleans + */ +bool_t +xdr_bool (XDR *xdrs, bool_t *bp) +{ + long lb; + + switch (xdrs->x_op) + { + case XDR_ENCODE: + lb = *bp ? XDR_TRUE : XDR_FALSE; + return XDR_PUTLONG (xdrs, &lb); + + case XDR_DECODE: + if (!XDR_GETLONG (xdrs, &lb)) + { + return FALSE; + } + *bp = (lb == XDR_FALSE) ? FALSE : TRUE; + return TRUE; + + case XDR_FREE: + return TRUE; + } + return FALSE; +} +libc_hidden_def(xdr_bool) + +/* + * XDR enumerations + */ +bool_t +xdr_enum (XDR *xdrs, enum_t *ep) +{ + enum sizecheck + { + SIZEVAL + }; /* used to find the size of an enum */ + + /* + * enums are treated as ints + */ + if (sizeof (enum sizecheck) == 4) + { +#if INT_MAX < LONG_MAX + long l; + + switch (xdrs->x_op) + { + case XDR_ENCODE: + l = *ep; + return XDR_PUTLONG (xdrs, &l); + + case XDR_DECODE: + if (!XDR_GETLONG (xdrs, &l)) + { + return FALSE; + } + *ep = l; + case XDR_FREE: + return TRUE; + + } + return FALSE; +#else + return xdr_long (xdrs, (long *) ep); +#endif + } + else if (sizeof (enum sizecheck) == sizeof (short)) + { + return xdr_short (xdrs, (short *) ep); + } + else + { + return FALSE; + } +} +libc_hidden_def(xdr_enum) + +/* + * XDR opaque data + * Allows the specification of a fixed size sequence of opaque bytes. + * cp points to the opaque object and cnt gives the byte length. + */ +bool_t +xdr_opaque (XDR *xdrs, caddr_t cp, u_int cnt) +{ + u_int rndup; + static char crud[BYTES_PER_XDR_UNIT]; + + /* + * if no data we are done + */ + if (cnt == 0) + return TRUE; + + /* + * round byte count to full xdr units + */ + rndup = cnt % BYTES_PER_XDR_UNIT; + if (rndup > 0) + rndup = BYTES_PER_XDR_UNIT - rndup; + + switch (xdrs->x_op) + { + case XDR_DECODE: + if (!XDR_GETBYTES (xdrs, cp, cnt)) + { + return FALSE; + } + if (rndup == 0) + return TRUE; + return XDR_GETBYTES (xdrs, (caddr_t)crud, rndup); + + case XDR_ENCODE: + if (!XDR_PUTBYTES (xdrs, cp, cnt)) + { + return FALSE; + } + if (rndup == 0) + return TRUE; + return XDR_PUTBYTES (xdrs, xdr_zero, rndup); + + case XDR_FREE: + return TRUE; + } + return FALSE; +} +libc_hidden_def(xdr_opaque) + +/* + * XDR counted bytes + * *cpp is a pointer to the bytes, *sizep is the count. + * If *cpp is NULL maxsize bytes are allocated + */ +bool_t +xdr_bytes (XDR *xdrs, char **cpp, u_int *sizep, u_int maxsize) +{ + char *sp = *cpp; /* sp is the actual string pointer */ + u_int nodesize; + + /* + * first deal with the length since xdr bytes are counted + */ + if (!xdr_u_int (xdrs, sizep)) + { + return FALSE; + } + nodesize = *sizep; + if ((nodesize > maxsize) && (xdrs->x_op != XDR_FREE)) + { + return FALSE; + } + + /* + * now deal with the actual bytes + */ + switch (xdrs->x_op) + { + case XDR_DECODE: + if (nodesize == 0) + { + return TRUE; + } + if (sp == NULL) + { + *cpp = sp = (char *) mem_alloc (nodesize); + } + if (sp == NULL) + { +#ifdef USE_IN_LIBIO + if (_IO_fwide (stderr, 0) > 0) + (void) fwprintf (stderr, L"%s", _("xdr_bytes: out of memory\n")); + else +#endif + (void) fputs (_("xdr_bytes: out of memory\n"), stderr); + return FALSE; + } + /* fall into ... */ + + case XDR_ENCODE: + return xdr_opaque (xdrs, sp, nodesize); + + case XDR_FREE: + if (sp != NULL) + { + mem_free (sp, nodesize); + *cpp = NULL; + } + return TRUE; + } + return FALSE; +} +libc_hidden_def(xdr_bytes) + +/* + * Implemented here due to commonality of the object. + */ +bool_t +xdr_netobj (XDR *xdrs, struct netobj *np) +{ + + return xdr_bytes (xdrs, &np->n_bytes, &np->n_len, MAX_NETOBJ_SZ); +} + +/* + * XDR a discriminated union + * Support routine for discriminated unions. + * You create an array of xdrdiscrim structures, terminated with + * an entry with a null procedure pointer. The routine gets + * the discriminant value and then searches the array of xdrdiscrims + * looking for that value. It calls the procedure given in the xdrdiscrim + * to handle the discriminant. If there is no specific routine a default + * routine may be called. + * If there is no specific or default routine an error is returned. + */ +bool_t +xdr_union (XDR *xdrs, enum_t *dscmp, char *unp, const struct xdr_discrim *choices, xdrproc_t dfault) +{ + enum_t dscm; + + /* + * we deal with the discriminator; it's an enum + */ + if (!xdr_enum (xdrs, dscmp)) + { + return FALSE; + } + dscm = *dscmp; + + /* + * search choices for a value that matches the discriminator. + * if we find one, execute the xdr routine for that value. + */ + for (; choices->proc != NULL_xdrproc_t; choices++) + { + if (choices->value == dscm) + return (*(choices->proc)) (xdrs, unp, LASTUNSIGNED); + } + + /* + * no match - execute the default xdr routine if there is one + */ + return ((dfault == NULL_xdrproc_t) ? FALSE : + (*dfault) (xdrs, unp, LASTUNSIGNED)); +} +libc_hidden_def(xdr_union) + +/* + * Non-portable xdr primitives. + * Care should be taken when moving these routines to new architectures. + */ + + +/* + * XDR null terminated ASCII strings + * xdr_string deals with "C strings" - arrays of bytes that are + * terminated by a NULL character. The parameter cpp references a + * pointer to storage; If the pointer is null, then the necessary + * storage is allocated. The last parameter is the max allowed length + * of the string as specified by a protocol. + */ +bool_t +xdr_string (XDR *xdrs, char **cpp, u_int maxsize) +{ + char *sp = *cpp; /* sp is the actual string pointer */ + u_int size; + u_int nodesize; + + /* + * first deal with the length since xdr strings are counted-strings + */ + switch (xdrs->x_op) + { + case XDR_FREE: + if (sp == NULL) + { + return TRUE; /* already free */ + } + /* fall through... */ + case XDR_ENCODE: + if (sp == NULL) + return FALSE; + size = strlen (sp); + break; + case XDR_DECODE: + break; + } + if (!xdr_u_int (xdrs, &size)) + { + return FALSE; + } + if (size > maxsize) + { + return FALSE; + } + nodesize = size + 1; + + /* + * now deal with the actual bytes + */ + switch (xdrs->x_op) + { + case XDR_DECODE: + if (nodesize == 0) + { + return TRUE; + } + if (sp == NULL) + *cpp = sp = (char *) mem_alloc (nodesize); + if (sp == NULL) + { +#ifdef USE_IN_LIBIO + if (_IO_fwide (stderr, 0) > 0) + (void) fwprintf (stderr, L"%s", + _("xdr_string: out of memory\n")); + else +#endif + (void) fputs (_("xdr_string: out of memory\n"), stderr); + return FALSE; + } + sp[size] = 0; + /* fall into ... */ + + case XDR_ENCODE: + return xdr_opaque (xdrs, sp, size); + + case XDR_FREE: + mem_free (sp, nodesize); + *cpp = NULL; + return TRUE; + } + return FALSE; +} +libc_hidden_def(xdr_string) + +/* + * Wrapper for xdr_string that can be called directly from + * routines like clnt_call + */ +bool_t +xdr_wrapstring (XDR *xdrs, char **cpp) +{ + if (xdr_string (xdrs, cpp, LASTUNSIGNED)) + { + return TRUE; + } + return FALSE; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/xdr_array.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/xdr_array.c new file mode 100644 index 00000000..61603edd --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/xdr_array.c @@ -0,0 +1,171 @@ +/* @(#)xdr_array.c 2.1 88/07/29 4.0 RPCSRC */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +#if 0 +static char sccsid[] = "@(#)xdr_array.c 1.10 87/08/11 Copyr 1984 Sun Micro"; +#endif + +/* + * xdr_array.c, Generic XDR routines implementation. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + * + * These are the "non-trivial" xdr primitives used to serialize and de-serialize + * arrays. See xdr.h for more info on the interface to xdr. + */ + +#define __FORCE_GLIBC +#include + +#include +#include +#include +#include +#include + +#ifdef USE_IN_LIBIO +# include +#endif + + +#define LASTUNSIGNED ((u_int)0-1) + + +/* + * XDR an array of arbitrary elements + * *addrp is a pointer to the array, *sizep is the number of elements. + * If addrp is NULL (*sizep * elsize) bytes are allocated. + * elsize is the size (in bytes) of each element, and elproc is the + * xdr procedure to call to handle each element of the array. + */ +bool_t +xdr_array (XDR *xdrs, caddr_t *addrp, u_int *sizep, u_int maxsize, u_int elsize, xdrproc_t elproc) +{ + u_int i; + caddr_t target = *addrp; + u_int c; /* the actual element count */ + bool_t stat = TRUE; + u_int nodesize; + + /* like strings, arrays are really counted arrays */ + if (!xdr_u_int (xdrs, sizep)) + { + return FALSE; + } + c = *sizep; + /* + * XXX: Let the overflow possibly happen with XDR_FREE because mem_free() + * doesn't actually use its second argument anyway. + */ + if ((c > maxsize || c > UINT_MAX / elsize) && (xdrs->x_op != XDR_FREE)) + { + return FALSE; + } + nodesize = c * elsize; + + /* + * if we are deserializing, we may need to allocate an array. + * We also save time by checking for a null array if we are freeing. + */ + if (target == NULL) + switch (xdrs->x_op) + { + case XDR_DECODE: + if (c == 0) + return TRUE; + *addrp = target = mem_alloc (nodesize); + if (target == NULL) + { +#ifdef USE_IN_LIBIO + if (_IO_fwide (stderr, 0) > 0) + (void) fwprintf (stderr, L"%s", + _("xdr_array: out of memory\n")); + else +#endif + (void) fputs (_("xdr_array: out of memory\n"), stderr); + return FALSE; + } + memset (target, 0, nodesize); + break; + + case XDR_FREE: + return TRUE; + default: + break; + } + + /* + * now we xdr each element of array + */ + for (i = 0; (i < c) && stat; i++) + { + stat = (*elproc) (xdrs, target, LASTUNSIGNED); + target += elsize; + } + + /* + * the array may need freeing + */ + if (xdrs->x_op == XDR_FREE) + { + mem_free (*addrp, nodesize); + *addrp = NULL; + } + return stat; +} +libc_hidden_def(xdr_array) + +/* + * xdr_vector(): + * + * XDR a fixed length array. Unlike variable-length arrays, + * the storage of fixed length arrays is static and unfreeable. + * > basep: base of the array + * > size: size of the array + * > elemsize: size of each element + * > xdr_elem: routine to XDR each element + */ +bool_t +xdr_vector (XDR *xdrs, char *basep, u_int nelem, u_int elemsize, + xdrproc_t xdr_elem) +{ + u_int i; + char *elptr; + + elptr = basep; + for (i = 0; i < nelem; i++) + { + if (!(*xdr_elem) (xdrs, elptr, LASTUNSIGNED)) + { + return FALSE; + } + elptr += elemsize; + } + return TRUE; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/xdr_float.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/xdr_float.c new file mode 100644 index 00000000..fd3863ff --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/xdr_float.c @@ -0,0 +1,306 @@ +/* @(#)xdr_float.c 2.1 88/07/29 4.0 RPCSRC */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +#if 0 +static char sccsid[] = "@(#)xdr_float.c 1.12 87/08/11 Copyr 1984 Sun Micro"; +#endif + +/* + * xdr_float.c, Generic XDR routines implementation. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + * + * These are the "floating point" xdr routines used to (de)serialize + * most common data items. See xdr.h for more info on the interface to + * xdr. + */ + +#define __FORCE_GLIBC +#include + +#include +#include + +#include +#include + +/* + * NB: Not portable. + * This routine works on Suns (Sky / 68000's) and Vaxen. + */ + +#define LSW (__FLOAT_WORD_ORDER == __BIG_ENDIAN) + +#ifdef vax + +/* What IEEE single precision floating point looks like on a Vax */ +struct ieee_single { + unsigned int mantissa: 23; + unsigned int exp : 8; + unsigned int sign : 1; +}; + +/* Vax single precision floating point */ +struct vax_single { + unsigned int mantissa1 : 7; + unsigned int exp : 8; + unsigned int sign : 1; + unsigned int mantissa2 : 16; +}; + +#define VAX_SNG_BIAS 0x81 +#define IEEE_SNG_BIAS 0x7f + +static struct sgl_limits { + struct vax_single s; + struct ieee_single ieee; +} sgl_limits[2] = { + {{ 0x7f, 0xff, 0x0, 0xffff }, /* Max Vax */ + { 0x0, 0xff, 0x0 }}, /* Max IEEE */ + {{ 0x0, 0x0, 0x0, 0x0 }, /* Min Vax */ + { 0x0, 0x0, 0x0 }} /* Min IEEE */ +}; +#endif /* vax */ + +bool_t +xdr_float(XDR *xdrs, float *fp) +{ +#ifdef vax + struct ieee_single is; + struct vax_single vs, *vsp; + struct sgl_limits *lim; + int i; +#endif + switch (xdrs->x_op) { + + case XDR_ENCODE: +#ifdef vax + vs = *((struct vax_single *)fp); + for (i = 0, lim = sgl_limits; + i < sizeof(sgl_limits)/sizeof(struct sgl_limits); + i++, lim++) { + if ((vs.mantissa2 == lim->s.mantissa2) && + (vs.exp == lim->s.exp) && + (vs.mantissa1 == lim->s.mantissa1)) { + is = lim->ieee; + goto shipit; + } + } + is.exp = vs.exp - VAX_SNG_BIAS + IEEE_SNG_BIAS; + is.mantissa = (vs.mantissa1 << 16) | vs.mantissa2; + shipit: + is.sign = vs.sign; + return (XDR_PUTLONG(xdrs, (long *)&is)); +#else + if (sizeof(float) == sizeof(long)) + return (XDR_PUTLONG(xdrs, (long *)fp)); + else if (sizeof(float) == sizeof(int)) { + long tmp = *(int *)fp; + return (XDR_PUTLONG(xdrs, &tmp)); + } + break; +#endif + + case XDR_DECODE: +#ifdef vax + vsp = (struct vax_single *)fp; + if (!XDR_GETLONG(xdrs, (long *)&is)) + return (FALSE); + for (i = 0, lim = sgl_limits; + i < sizeof(sgl_limits)/sizeof(struct sgl_limits); + i++, lim++) { + if ((is.exp == lim->ieee.exp) && + (is.mantissa == lim->ieee.mantissa)) { + *vsp = lim->s; + goto doneit; + } + } + vsp->exp = is.exp - IEEE_SNG_BIAS + VAX_SNG_BIAS; + vsp->mantissa2 = is.mantissa; + vsp->mantissa1 = (is.mantissa >> 16); + doneit: + vsp->sign = is.sign; + return (TRUE); +#else + if (sizeof(float) == sizeof(long)) + return (XDR_GETLONG(xdrs, (long *)fp)); + else if (sizeof(float) == sizeof(int)) { + long tmp; + if (XDR_GETLONG(xdrs, &tmp)) { + *(int *)fp = tmp; + return (TRUE); + } + } + break; +#endif + + case XDR_FREE: + return (TRUE); + } + return (FALSE); +} + +/* + * This routine works on Suns (Sky / 68000's) and Vaxen. + */ + +#ifdef vax +/* What IEEE double precision floating point looks like on a Vax */ +struct ieee_double { + unsigned int mantissa1 : 20; + unsigned int exp : 11; + unsigned int sign : 1; + unsigned int mantissa2 : 32; +}; + +/* Vax double precision floating point */ +struct vax_double { + unsigned int mantissa1 : 7; + unsigned int exp : 8; + unsigned int sign : 1; + unsigned int mantissa2 : 16; + unsigned int mantissa3 : 16; + unsigned int mantissa4 : 16; +}; + +#define VAX_DBL_BIAS 0x81 +#define IEEE_DBL_BIAS 0x3ff +#define MASK(nbits) ((1 << nbits) - 1) + +static struct dbl_limits { + struct vax_double d; + struct ieee_double ieee; +} dbl_limits[2] = { + {{ 0x7f, 0xff, 0x0, 0xffff, 0xffff, 0xffff }, /* Max Vax */ + { 0x0, 0x7ff, 0x0, 0x0 }}, /* Max IEEE */ + {{ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, /* Min Vax */ + { 0x0, 0x0, 0x0, 0x0 }} /* Min IEEE */ +}; + +#endif /* vax */ + + +bool_t +xdr_double(XDR *xdrs, double *dp) +{ +#ifdef vax + struct ieee_double id; + struct vax_double vd; + register struct dbl_limits *lim; + int i; +#endif + + switch (xdrs->x_op) { + + case XDR_ENCODE: +#ifdef vax + vd = *((struct vax_double *)dp); + for (i = 0, lim = dbl_limits; + i < sizeof(dbl_limits)/sizeof(struct dbl_limits); + i++, lim++) { + if ((vd.mantissa4 == lim->d.mantissa4) && + (vd.mantissa3 == lim->d.mantissa3) && + (vd.mantissa2 == lim->d.mantissa2) && + (vd.mantissa1 == lim->d.mantissa1) && + (vd.exp == lim->d.exp)) { + id = lim->ieee; + goto shipit; + } + } + id.exp = vd.exp - VAX_DBL_BIAS + IEEE_DBL_BIAS; + id.mantissa1 = (vd.mantissa1 << 13) | (vd.mantissa2 >> 3); + id.mantissa2 = ((vd.mantissa2 & MASK(3)) << 29) | + (vd.mantissa3 << 13) | + ((vd.mantissa4 >> 3) & MASK(13)); + shipit: + id.sign = vd.sign; + dp = (double *)&id; +#endif + if (2*sizeof(long) == sizeof(double)) { + long *lp = (long *)dp; + return (XDR_PUTLONG(xdrs, lp+!LSW) && + XDR_PUTLONG(xdrs, lp+LSW)); + } else if (2*sizeof(int) == sizeof(double)) { + int *ip = (int *)dp; + long tmp[2]; + tmp[0] = ip[!LSW]; + tmp[1] = ip[LSW]; + return (XDR_PUTLONG(xdrs, tmp) && + XDR_PUTLONG(xdrs, tmp+1)); + } + break; + + case XDR_DECODE: +#ifdef vax + lp = (long *)&id; + if (!XDR_GETLONG(xdrs, lp++) || !XDR_GETLONG(xdrs, lp)) + return (FALSE); + for (i = 0, lim = dbl_limits; + i < sizeof(dbl_limits)/sizeof(struct dbl_limits); + i++, lim++) { + if ((id.mantissa2 == lim->ieee.mantissa2) && + (id.mantissa1 == lim->ieee.mantissa1) && + (id.exp == lim->ieee.exp)) { + vd = lim->d; + goto doneit; + } + } + vd.exp = id.exp - IEEE_DBL_BIAS + VAX_DBL_BIAS; + vd.mantissa1 = (id.mantissa1 >> 13); + vd.mantissa2 = ((id.mantissa1 & MASK(13)) << 3) | + (id.mantissa2 >> 29); + vd.mantissa3 = (id.mantissa2 >> 13); + vd.mantissa4 = (id.mantissa2 << 3); + doneit: + vd.sign = id.sign; + *dp = *((double *)&vd); + return (TRUE); +#else + if (2*sizeof(long) == sizeof(double)) { + long *lp = (long *)dp; + return (XDR_GETLONG(xdrs, lp+!LSW) && + XDR_GETLONG(xdrs, lp+LSW)); + } else if (2*sizeof(int) == sizeof(double)) { + int *ip = (int *)dp; + long tmp[2]; + if (XDR_GETLONG(xdrs, tmp+!LSW) && + XDR_GETLONG(xdrs, tmp+LSW)) { + ip[0] = tmp[0]; + ip[1] = tmp[1]; + return (TRUE); + } + } + break; +#endif + + case XDR_FREE: + return (TRUE); + } + return (FALSE); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/xdr_intXX_t.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/xdr_intXX_t.c new file mode 100644 index 00000000..ff217758 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/xdr_intXX_t.c @@ -0,0 +1,203 @@ +/* Copyright (c) 1998, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Thorsten Kukuk , 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +/* XDR 64bit integers */ +bool_t +xdr_int64_t (XDR *xdrs, int64_t *ip) +{ + int32_t t1; + /* This must be unsigned, otherwise we get problems with sign + extension in the DECODE case. */ + uint32_t t2; + + switch (xdrs->x_op) + { + case XDR_ENCODE: + t1 = (int32_t) ((*ip) >> 32); + t2 = (int32_t) (*ip); + return (XDR_PUTINT32(xdrs, &t1) && XDR_PUTINT32(xdrs, (int32_t *) &t2)); + case XDR_DECODE: + if (!XDR_GETINT32(xdrs, &t1) || !XDR_GETINT32(xdrs, (int32_t *) &t2)) + return FALSE; + *ip = ((int64_t) t1) << 32; + *ip |= t2; + return TRUE; + case XDR_FREE: + return TRUE; + default: + return FALSE; + } +} + +/* XDR 64bit unsigned integers */ +bool_t +xdr_uint64_t (XDR *xdrs, uint64_t *uip) +{ + uint32_t t1; + uint32_t t2; + + switch (xdrs->x_op) + { + case XDR_ENCODE: + t1 = (uint32_t) ((*uip) >> 32); + t2 = (uint32_t) (*uip); + return (XDR_PUTINT32 (xdrs, (int32_t *) &t1) && + XDR_PUTINT32(xdrs, (int32_t *) &t2)); + case XDR_DECODE: + if (!XDR_GETINT32(xdrs, (int32_t *) &t1) || + !XDR_GETINT32(xdrs, (int32_t *) &t2)) + return FALSE; + *uip = ((uint64_t) t1) << 32; + *uip |= t2; + return TRUE; + case XDR_FREE: + return TRUE; + default: + return FALSE; + } +} + +/* XDR 32bit integers */ +bool_t +xdr_int32_t (XDR *xdrs, int32_t *lp) +{ + switch (xdrs->x_op) + { + case XDR_ENCODE: + return XDR_PUTINT32 (xdrs, lp); + case XDR_DECODE: + return XDR_GETINT32 (xdrs, lp); + case XDR_FREE: + return TRUE; + default: + return FALSE; + } +} + +/* XDR 32bit unsigned integers */ +bool_t +xdr_uint32_t (XDR *xdrs, uint32_t *ulp) +{ + switch (xdrs->x_op) + { + case XDR_ENCODE: + return XDR_PUTINT32 (xdrs, (int32_t *) ulp); + case XDR_DECODE: + return XDR_GETINT32 (xdrs, (int32_t *) ulp); + case XDR_FREE: + return TRUE; + default: + return FALSE; + } +} + +/* XDR 16bit integers */ +bool_t +xdr_int16_t (XDR *xdrs, int16_t *ip) +{ + int32_t t; + + switch (xdrs->x_op) + { + case XDR_ENCODE: + t = (int32_t) *ip; + return XDR_PUTINT32 (xdrs, &t); + case XDR_DECODE: + if (!XDR_GETINT32 (xdrs, &t)) + return FALSE; + *ip = (int16_t) t; + return TRUE; + case XDR_FREE: + return TRUE; + default: + return FALSE; + } +} + +/* XDR 16bit unsigned integers */ +bool_t +xdr_uint16_t (XDR *xdrs, uint16_t *uip) +{ + uint32_t ut; + + switch (xdrs->x_op) + { + case XDR_ENCODE: + ut = (uint32_t) *uip; + return XDR_PUTINT32 (xdrs, (int32_t *) &ut); + case XDR_DECODE: + if (!XDR_GETINT32 (xdrs, (int32_t *) &ut)) + return FALSE; + *uip = (uint16_t) ut; + return TRUE; + case XDR_FREE: + return TRUE; + default: + return FALSE; + } +} + +/* XDR 8bit integers */ +bool_t +xdr_int8_t (XDR *xdrs, int8_t *ip) +{ + int32_t t; + + switch (xdrs->x_op) + { + case XDR_ENCODE: + t = (int32_t) *ip; + return XDR_PUTINT32 (xdrs, &t); + case XDR_DECODE: + if (!XDR_GETINT32 (xdrs, &t)) + return FALSE; + *ip = (int8_t) t; + return TRUE; + case XDR_FREE: + return TRUE; + default: + return FALSE; + } +} + +/* XDR 8bit unsigned integers */ +bool_t +xdr_uint8_t (XDR *xdrs, uint8_t *uip) +{ + uint32_t ut; + + switch (xdrs->x_op) + { + case XDR_ENCODE: + ut = (uint32_t) *uip; + return XDR_PUTINT32 (xdrs, (int32_t *) &ut); + case XDR_DECODE: + if (!XDR_GETINT32 (xdrs, (int32_t *) &ut)) + return FALSE; + *uip = (uint8_t) ut; + return TRUE; + case XDR_FREE: + return TRUE; + default: + return FALSE; + } +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/xdr_mem.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/xdr_mem.c new file mode 100644 index 00000000..c58fc450 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/xdr_mem.c @@ -0,0 +1,237 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +/* + * xdr_mem.h, XDR implementation using memory buffers. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + * + * If you have some data to be interpreted as external data representation + * or to be converted to external data representation in a memory buffer, + * then this is the package for you. + * + */ + +#include +#include +#include +#include + + +static bool_t xdrmem_getlong (XDR *, long *); +static bool_t xdrmem_putlong (XDR *, const long *); +static bool_t xdrmem_getbytes (XDR *, caddr_t, u_int); +static bool_t xdrmem_putbytes (XDR *, const char *, u_int); +static u_int xdrmem_getpos (const XDR *); +static bool_t xdrmem_setpos (XDR *, u_int); +static int32_t *xdrmem_inline (XDR *, u_int); +static void xdrmem_destroy (XDR *); +static bool_t xdrmem_getint32 (XDR *, int32_t *); +static bool_t xdrmem_putint32 (XDR *, const int32_t *); + +static const struct xdr_ops xdrmem_ops = +{ + xdrmem_getlong, + xdrmem_putlong, + xdrmem_getbytes, + xdrmem_putbytes, + xdrmem_getpos, + xdrmem_setpos, + xdrmem_inline, + xdrmem_destroy, + xdrmem_getint32, + xdrmem_putint32 +}; + +/* + * The procedure xdrmem_create initializes a stream descriptor for a + * memory buffer. + */ +void +xdrmem_create (XDR *xdrs, const caddr_t addr, u_int size, enum xdr_op op) +{ + xdrs->x_op = op; + /* We have to add the const since the `struct xdr_ops' in `struct XDR' + is not `const'. */ + xdrs->x_ops = (struct xdr_ops *) &xdrmem_ops; + xdrs->x_private = xdrs->x_base = addr; + xdrs->x_handy = size; +} +libc_hidden_def(xdrmem_create) + +/* + * Nothing needs to be done for the memory case. The argument is clearly + * const. + */ + +static void +xdrmem_destroy (XDR *xdrs attribute_unused) +{ +} + +/* + * Gets the next word from the memory referenced by xdrs and places it + * in the long pointed to by lp. It then increments the private word to + * point at the next element. Neither object pointed to is const + */ +static bool_t +xdrmem_getlong (XDR *xdrs, long *lp) +{ + if (xdrs->x_handy < 4) + return FALSE; + xdrs->x_handy -= 4; + *lp = (int32_t) ntohl ((*((int32_t *) (xdrs->x_private)))); + xdrs->x_private += 4; + return TRUE; +} + +/* + * Puts the long pointed to by lp in the memory referenced by xdrs. It + * then increments the private word to point at the next element. The + * long pointed at is const + */ +static bool_t +xdrmem_putlong (XDR *xdrs, const long *lp) +{ + if (xdrs->x_handy < 4) + return FALSE; + xdrs->x_handy -= 4; + *(int32_t *) xdrs->x_private = htonl (*lp); + xdrs->x_private += 4; + return TRUE; +} + +/* + * Gets an unaligned number of bytes from the xdrs structure and writes them + * to the address passed in addr. Be very careful when calling this routine + * as it could leave the xdrs pointing to an unaligned structure which is not + * a good idea. None of the things pointed to are const. + */ +static bool_t +xdrmem_getbytes (XDR *xdrs, caddr_t addr, u_int len) +{ + if (xdrs->x_handy < len) + return FALSE; + xdrs->x_handy -= len; + memcpy (addr, xdrs->x_private, len); + xdrs->x_private += len; + return TRUE; +} + +/* + * The complementary function to the above. The same warnings apply about + * unaligned data. The source address is const. + */ +static bool_t +xdrmem_putbytes (XDR *xdrs, const char *addr, u_int len) +{ + if (xdrs->x_handy < len) + return FALSE; + xdrs->x_handy -= len; + memcpy (xdrs->x_private, addr, len); + xdrs->x_private += len; + return TRUE; +} + +/* + * Not sure what this one does. But it clearly doesn't modify the contents + * of xdrs. **FIXME** does this not assume u_int == u_long? + */ +static u_int +xdrmem_getpos (const XDR *xdrs) +{ + return (u_long) xdrs->x_private - (u_long) xdrs->x_base; +} + +/* + * xdrs modified + */ +static bool_t +xdrmem_setpos (XDR *xdrs, u_int pos) +{ + caddr_t newaddr = xdrs->x_base + pos; + caddr_t lastaddr = xdrs->x_private + xdrs->x_handy; + + if ((long) newaddr > (long) lastaddr + || (UINT_MAX < LONG_MAX + && (long) UINT_MAX < (long) lastaddr - (long) newaddr)) + return FALSE; + xdrs->x_private = newaddr; + xdrs->x_handy = (long) lastaddr - (long) newaddr; + return TRUE; +} + +/* + * xdrs modified + */ +static int32_t * +xdrmem_inline (XDR *xdrs, u_int len) +{ + int32_t *buf = 0; + + if (xdrs->x_handy >= len) + { + xdrs->x_handy -= len; + buf = (int32_t *) xdrs->x_private; + xdrs->x_private += len; + } + return buf; +} + +/* + * Gets the next word from the memory referenced by xdrs and places it + * in the int pointed to by ip. It then increments the private word to + * point at the next element. Neither object pointed to is const + */ +static bool_t +xdrmem_getint32 (XDR *xdrs, int32_t *ip) +{ + if (xdrs->x_handy < 4) + return FALSE; + xdrs->x_handy -= 4; + *ip = ntohl ((*((int32_t *) (xdrs->x_private)))); + xdrs->x_private += 4; + return TRUE; +} + +/* + * Puts the long pointed to by lp in the memory referenced by xdrs. It + * then increments the private word to point at the next element. The + * long pointed at is const + */ +static bool_t +xdrmem_putint32 (XDR *xdrs, const int32_t *ip) +{ + if (xdrs->x_handy < 4) + return FALSE; + xdrs->x_handy -= 4; + *(int32_t *) xdrs->x_private = htonl (*ip); + xdrs->x_private += 4; + return TRUE; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/xdr_rec.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/xdr_rec.c new file mode 100644 index 00000000..1e02e7f4 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/xdr_rec.c @@ -0,0 +1,646 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +/* + * xdr_rec.c, Implements TCP/IP based XDR streams with a "record marking" + * layer above tcp (for rpc's use). + * + * Copyright (C) 1984, Sun Microsystems, Inc. + * + * These routines interface XDRSTREAMS to a tcp/ip connection. + * There is a record marking layer between the xdr stream + * and the tcp transport level. A record is composed on one or more + * record fragments. A record fragment is a thirty-two bit header followed + * by n bytes of data, where n is contained in the header. The header + * is represented as a htonl(u_long). The high order bit encodes + * whether or not the fragment is the last fragment of the record + * (1 => fragment is last, 0 => more fragments to follow. + * The other 31 bits encode the byte length of the fragment. + */ + +#define __FORCE_GLIBC +#include + + +#include +#include +#include +#include + +#ifdef USE_IN_LIBIO +# include +# include +# define fputs(s, f) _IO_fputs (s, f) +#endif + + +static bool_t xdrrec_getbytes (XDR *, caddr_t, u_int); +static bool_t xdrrec_putbytes (XDR *, const char *, u_int); +static bool_t xdrrec_getint32 (XDR *, int32_t *); +static bool_t xdrrec_putint32 (XDR *, const int32_t *); +#if ULONG_MAX != 0xffffffff +static bool_t xdrrec_getlong (XDR *, long *); +static bool_t xdrrec_putlong (XDR *, const long *); +#endif +static u_int xdrrec_getpos (const XDR *); +static bool_t xdrrec_setpos (XDR *, u_int); +static int32_t *xdrrec_inline (XDR *, u_int); +static void xdrrec_destroy (XDR *); + +static const struct xdr_ops xdrrec_ops = { +#if ULONG_MAX == 0xffffffff + (bool_t (*)(XDR *, long *)) xdrrec_getint32, + (bool_t (*)(XDR *, const long *)) xdrrec_putint32, +#else + xdrrec_getlong, + xdrrec_putlong, +#endif + xdrrec_getbytes, + xdrrec_putbytes, + xdrrec_getpos, + xdrrec_setpos, + xdrrec_inline, + xdrrec_destroy, + xdrrec_getint32, + xdrrec_putint32 +}; + +/* + * A record is composed of one or more record fragments. + * A record fragment is a two-byte header followed by zero to + * 2**32-1 bytes. The header is treated as a long unsigned and is + * encode/decoded to the network via htonl/ntohl. The low order 31 bits + * are a byte count of the fragment. The highest order bit is a boolean: + * 1 => this fragment is the last fragment of the record, + * 0 => this fragment is followed by more fragment(s). + * + * The fragment/record machinery is not general; it is constructed to + * meet the needs of xdr and rpc based on tcp. + */ + +#define LAST_FRAG (1UL << 31) + +typedef struct rec_strm + { + caddr_t tcp_handle; + caddr_t the_buffer; + /* + * out-going bits + */ + int (*writeit) (char *, char *, int); + caddr_t out_base; /* output buffer (points to frag header) */ + caddr_t out_finger; /* next output position */ + caddr_t out_boundry; /* data cannot up to this address */ + u_int32_t *frag_header; /* beginning of curren fragment */ + bool_t frag_sent; /* true if buffer sent in middle of record */ + /* + * in-coming bits + */ + int (*readit) (char *, char *, int); + u_long in_size; /* fixed size of the input buffer */ + caddr_t in_base; + caddr_t in_finger; /* location of next byte to be had */ + caddr_t in_boundry; /* can read up to this location */ + long fbtbc; /* fragment bytes to be consumed */ + bool_t last_frag; + u_int sendsize; + u_int recvsize; + } +RECSTREAM; + +static u_int fix_buf_size (u_int) internal_function; +static bool_t skip_input_bytes (RECSTREAM *, long) internal_function; +static bool_t flush_out (RECSTREAM *, bool_t) internal_function; +static bool_t set_input_fragment (RECSTREAM *) internal_function; +static bool_t get_input_bytes (RECSTREAM *, caddr_t, int) internal_function; + +/* + * Create an xdr handle for xdrrec + * xdrrec_create fills in xdrs. Sendsize and recvsize are + * send and recv buffer sizes (0 => use default). + * tcp_handle is an opaque handle that is passed as the first parameter to + * the procedures readit and writeit. Readit and writeit are read and + * write respectively. They are like the system + * calls expect that they take an opaque handle rather than an fd. + */ +void +xdrrec_create (XDR *xdrs, u_int sendsize, + u_int recvsize, caddr_t tcp_handle, + int (*readit) (char *, char *, int), + int (*writeit) (char *, char *, int)) +{ + RECSTREAM *rstrm = (RECSTREAM *) mem_alloc (sizeof (RECSTREAM)); + caddr_t tmp; + char *buf; + + sendsize = fix_buf_size (sendsize); + recvsize = fix_buf_size (recvsize); + buf = mem_alloc (sendsize + recvsize + BYTES_PER_XDR_UNIT); + + if (rstrm == NULL || buf == NULL) + { +#ifdef USE_IN_LIBIO + if (_IO_fwide (stderr, 0) > 0) + (void) fwprintf (stderr, L"%s", _("xdrrec_create: out of memory\n")); + else +#endif + (void) fputs (_("xdrrec_create: out of memory\n"), stderr); + mem_free (rstrm, sizeof (RECSTREAM)); + mem_free (buf, sendsize + recvsize + BYTES_PER_XDR_UNIT); + /* + * This is bad. Should rework xdrrec_create to + * return a handle, and in this case return NULL + */ + return; + } + /* + * adjust sizes and allocate buffer quad byte aligned + */ + rstrm->sendsize = sendsize; + rstrm->recvsize = recvsize; + rstrm->the_buffer = buf; + tmp = rstrm->the_buffer; + if ((size_t)tmp % BYTES_PER_XDR_UNIT) + tmp += BYTES_PER_XDR_UNIT - (size_t)tmp % BYTES_PER_XDR_UNIT; + rstrm->out_base = tmp; + rstrm->in_base = tmp + sendsize; + /* + * now the rest ... + */ + /* We have to add the const since the `struct xdr_ops' in `struct XDR' + is not `const'. */ + xdrs->x_ops = (struct xdr_ops *) &xdrrec_ops; + xdrs->x_private = (caddr_t) rstrm; + rstrm->tcp_handle = tcp_handle; + rstrm->readit = readit; + rstrm->writeit = writeit; + rstrm->out_finger = rstrm->out_boundry = rstrm->out_base; + rstrm->frag_header = (u_int32_t *) rstrm->out_base; + rstrm->out_finger += 4; + rstrm->out_boundry += sendsize; + rstrm->frag_sent = FALSE; + rstrm->in_size = recvsize; + rstrm->in_boundry = rstrm->in_base; + rstrm->in_finger = (rstrm->in_boundry += recvsize); + rstrm->fbtbc = 0; + rstrm->last_frag = TRUE; +} +libc_hidden_def(xdrrec_create) + + +/* + * The routines defined below are the xdr ops which will go into the + * xdr handle filled in by xdrrec_create. + */ + +static bool_t +xdrrec_getint32 (XDR *xdrs, int32_t *ip) +{ + RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private; + int32_t *bufip = (int32_t *) rstrm->in_finger; + int32_t mylong; + + /* first try the inline, fast case */ + if (rstrm->fbtbc >= BYTES_PER_XDR_UNIT && + rstrm->in_boundry - (char *) bufip >= BYTES_PER_XDR_UNIT) + { + *ip = ntohl (*bufip); + rstrm->fbtbc -= BYTES_PER_XDR_UNIT; + rstrm->in_finger += BYTES_PER_XDR_UNIT; + } + else + { + if (!xdrrec_getbytes (xdrs, (caddr_t) &mylong, + BYTES_PER_XDR_UNIT)) + return FALSE; + *ip = ntohl (mylong); + } + return TRUE; +} + +#if ULONG_MAX != 0xffffffff +static bool_t +xdrrec_getlong (XDR *xdrs, long *lp) +{ + int32_t v; + bool_t r = xdrrec_getint32 (xdrs, &v); + *lp = v; + return r; +} +#endif + +static bool_t +xdrrec_putint32 (XDR *xdrs, const int32_t *ip) +{ + RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private; + int32_t *dest_ip = (int32_t *) rstrm->out_finger; + + if ((rstrm->out_finger += BYTES_PER_XDR_UNIT) > rstrm->out_boundry) + { + /* + * this case should almost never happen so the code is + * inefficient + */ + rstrm->out_finger -= BYTES_PER_XDR_UNIT; + rstrm->frag_sent = TRUE; + if (!flush_out (rstrm, FALSE)) + return FALSE; + dest_ip = (int32_t *) rstrm->out_finger; + rstrm->out_finger += BYTES_PER_XDR_UNIT; + } + *dest_ip = htonl (*ip); + return TRUE; +} + +#if ULONG_MAX != 0xffffffff +static bool_t +xdrrec_putlong (XDR *xdrs, const long *lp) +{ + int32_t v = *lp; + return xdrrec_putint32 (xdrs, &v); +} +#endif + +static bool_t /* must manage buffers, fragments, and records */ +xdrrec_getbytes (XDR *xdrs, caddr_t addr, u_int len) +{ + RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private; + u_int current; + + while (len > 0) + { + current = rstrm->fbtbc; + if (current == 0) + { + if (rstrm->last_frag) + return FALSE; + if (!set_input_fragment (rstrm)) + return FALSE; + continue; + } + current = (len < current) ? len : current; + if (!get_input_bytes (rstrm, addr, current)) + return FALSE; + addr += current; + rstrm->fbtbc -= current; + len -= current; + } + return TRUE; +} + +static bool_t +xdrrec_putbytes (XDR *xdrs, const char *addr, u_int len) +{ + RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private; + u_int current; + + while (len > 0) + { + current = rstrm->out_boundry - rstrm->out_finger; + current = (len < current) ? len : current; + memcpy (rstrm->out_finger, addr, current); + rstrm->out_finger += current; + addr += current; + len -= current; + if (rstrm->out_finger == rstrm->out_boundry && len > 0) + { + rstrm->frag_sent = TRUE; + if (!flush_out (rstrm, FALSE)) + return FALSE; + } + } + return TRUE; +} + +static u_int +xdrrec_getpos (const XDR *xdrs) +{ + RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private; + long pos; + + pos = lseek ((int) (long) rstrm->tcp_handle, (long) 0, 1); + if (pos != -1) + switch (xdrs->x_op) + { + + case XDR_ENCODE: + pos += rstrm->out_finger - rstrm->out_base; + break; + + case XDR_DECODE: + pos -= rstrm->in_boundry - rstrm->in_finger; + break; + + default: + pos = (u_int) - 1; + break; + } + return (u_int) pos; +} + +static bool_t +xdrrec_setpos (XDR *xdrs, u_int pos) +{ + RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private; + u_int currpos = xdrrec_getpos (xdrs); + int delta = currpos - pos; + caddr_t newpos; + + if ((int) currpos != -1) + switch (xdrs->x_op) + { + + case XDR_ENCODE: + newpos = rstrm->out_finger - delta; + if (newpos > (caddr_t) rstrm->frag_header && + newpos < rstrm->out_boundry) + { + rstrm->out_finger = newpos; + return TRUE; + } + break; + + case XDR_DECODE: + newpos = rstrm->in_finger - delta; + if ((delta < (int) (rstrm->fbtbc)) && + (newpos <= rstrm->in_boundry) && + (newpos >= rstrm->in_base)) + { + rstrm->in_finger = newpos; + rstrm->fbtbc -= delta; + return TRUE; + } + break; + + default: + break; + } + return FALSE; +} + +static int32_t * +xdrrec_inline (XDR *xdrs, u_int len) +{ + RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private; + int32_t *buf = NULL; + + switch (xdrs->x_op) + { + + case XDR_ENCODE: + if ((rstrm->out_finger + len) <= rstrm->out_boundry) + { + buf = (int32_t *) rstrm->out_finger; + rstrm->out_finger += len; + } + break; + + case XDR_DECODE: + if ((len <= rstrm->fbtbc) && + ((rstrm->in_finger + len) <= rstrm->in_boundry)) + { + buf = (int32_t *) rstrm->in_finger; + rstrm->fbtbc -= len; + rstrm->in_finger += len; + } + break; + + default: + break; + } + return buf; +} + +static void +xdrrec_destroy (XDR *xdrs) +{ + RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private; + + mem_free (rstrm->the_buffer, + rstrm->sendsize + rstrm->recvsize + BYTES_PER_XDR_UNIT); + mem_free ((caddr_t) rstrm, sizeof (RECSTREAM)); +} + +/* + * Exported routines to manage xdr records + */ + +/* + * Before reading (deserializing from the stream, one should always call + * this procedure to guarantee proper record alignment. + */ +bool_t +xdrrec_skiprecord (XDR *xdrs) +{ + RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private; + + while (rstrm->fbtbc > 0 || (!rstrm->last_frag)) + { + if (!skip_input_bytes (rstrm, rstrm->fbtbc)) + return FALSE; + rstrm->fbtbc = 0; + if ((!rstrm->last_frag) && (!set_input_fragment (rstrm))) + return FALSE; + } + rstrm->last_frag = FALSE; + return TRUE; +} +libc_hidden_def(xdrrec_skiprecord) + +/* + * Lookahead function. + * Returns TRUE iff there is no more input in the buffer + * after consuming the rest of the current record. + */ +bool_t +xdrrec_eof (XDR *xdrs) +{ + RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private; + + while (rstrm->fbtbc > 0 || (!rstrm->last_frag)) + { + if (!skip_input_bytes (rstrm, rstrm->fbtbc)) + return TRUE; + rstrm->fbtbc = 0; + if ((!rstrm->last_frag) && (!set_input_fragment (rstrm))) + return TRUE; + } + if (rstrm->in_finger == rstrm->in_boundry) + return TRUE; + return FALSE; +} +libc_hidden_def(xdrrec_eof) + +/* + * The client must tell the package when an end-of-record has occurred. + * The second parameter tells whether the record should be flushed to the + * (output) tcp stream. (This lets the package support batched or + * pipelined procedure calls.) TRUE => immediate flush to tcp connection. + */ +bool_t +xdrrec_endofrecord (XDR *xdrs, bool_t sendnow) +{ + RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private; + u_long len; /* fragment length */ + + if (sendnow || rstrm->frag_sent + || rstrm->out_finger + BYTES_PER_XDR_UNIT >= rstrm->out_boundry) + { + rstrm->frag_sent = FALSE; + return flush_out (rstrm, TRUE); + } + len = (rstrm->out_finger - (char *) rstrm->frag_header + - BYTES_PER_XDR_UNIT); + *rstrm->frag_header = htonl ((u_long) len | LAST_FRAG); + rstrm->frag_header = (u_int32_t *) rstrm->out_finger; + rstrm->out_finger += BYTES_PER_XDR_UNIT; + return TRUE; +} +libc_hidden_def(xdrrec_endofrecord) + +/* + * Internal useful routines + */ +static bool_t +internal_function +flush_out (RECSTREAM *rstrm, bool_t eor) +{ + u_long eormask = (eor == TRUE) ? LAST_FRAG : 0; + u_long len = (rstrm->out_finger - (char *) rstrm->frag_header + - BYTES_PER_XDR_UNIT); + + *rstrm->frag_header = htonl (len | eormask); + len = rstrm->out_finger - rstrm->out_base; + if ((*(rstrm->writeit)) (rstrm->tcp_handle, rstrm->out_base, (int) len) + != (int) len) + return FALSE; + rstrm->frag_header = (u_int32_t *) rstrm->out_base; + rstrm->out_finger = (caddr_t) rstrm->out_base + BYTES_PER_XDR_UNIT; + return TRUE; +} + +static bool_t /* knows nothing about records! Only about input buffers */ +fill_input_buf (RECSTREAM *rstrm) +{ + caddr_t where; + size_t i; + int len; + + where = rstrm->in_base; + i = (size_t) rstrm->in_boundry % BYTES_PER_XDR_UNIT; + where += i; + len = rstrm->in_size - i; + if ((len = (*(rstrm->readit)) (rstrm->tcp_handle, where, len)) == -1) + return FALSE; + rstrm->in_finger = where; + where += len; + rstrm->in_boundry = where; + return TRUE; +} + +static bool_t /* knows nothing about records! Only about input buffers */ +internal_function +get_input_bytes (RECSTREAM *rstrm, caddr_t addr, int len) +{ + int current; + + while (len > 0) + { + current = rstrm->in_boundry - rstrm->in_finger; + if (current == 0) + { + if (!fill_input_buf (rstrm)) + return FALSE; + continue; + } + current = (len < current) ? len : current; + memcpy (addr, rstrm->in_finger, current); + rstrm->in_finger += current; + addr += current; + len -= current; + } + return TRUE; +} + +static bool_t /* next two bytes of the input stream are treated as a header */ +internal_function +set_input_fragment (RECSTREAM *rstrm) +{ + uint32_t header; + + if (! get_input_bytes (rstrm, (caddr_t)&header, BYTES_PER_XDR_UNIT)) + return FALSE; + header = ntohl (header); + rstrm->last_frag = ((header & LAST_FRAG) == 0) ? FALSE : TRUE; + /* + * Sanity check. Try not to accept wildly incorrect fragment + * sizes. Unfortunately, only a size of zero can be identified as + * 'wildely incorrect', and this only, if it is not the last + * fragment of a message. Ridiculously large fragment sizes may look + * wrong, but we don't have any way to be certain that they aren't + * what the client actually intended to send us. Many existing RPC + * implementations may sent a fragment of size zero as the last + * fragment of a message. + */ + if (header == 0) + return FALSE; + rstrm->fbtbc = header & ~LAST_FRAG; + return TRUE; +} + +static bool_t /* consumes input bytes; knows nothing about records! */ +internal_function +skip_input_bytes (RECSTREAM *rstrm, long cnt) +{ + int current; + + while (cnt > 0) + { + current = rstrm->in_boundry - rstrm->in_finger; + if (current == 0) + { + if (!fill_input_buf (rstrm)) + return FALSE; + continue; + } + current = (cnt < current) ? cnt : current; + rstrm->in_finger += current; + cnt -= current; + } + return TRUE; +} + +static u_int +internal_function +fix_buf_size (u_int s) +{ + if (s < 100) + s = 4000; + return RNDUP (s); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/xdr_reference.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/xdr_reference.c new file mode 100644 index 00000000..1c601fc9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/xdr_reference.c @@ -0,0 +1,147 @@ +/* @(#)xdr_reference.c 2.1 88/07/29 4.0 RPCSRC */ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +#if 0 +static char sccsid[] = "@(#)xdr_reference.c 1.11 87/08/11 SMI"; +#endif + +/* + * xdr_reference.c, Generic XDR routines implementation. + * + * Copyright (C) 1987, Sun Microsystems, Inc. + * + * These are the "non-trivial" xdr primitives used to serialize and de-serialize + * "pointers". See xdr.h for more info on the interface to xdr. + */ + +#define __FORCE_GLIBC +#include + +#include +#include +#include +#include + +#ifdef USE_IN_LIBIO +# include +# include +# define fputs(s, f) _IO_fputs (s, f) +#endif + + +#define LASTUNSIGNED ((u_int)0-1) + +/* + * XDR an indirect pointer + * xdr_reference is for recursively translating a structure that is + * referenced by a pointer inside the structure that is currently being + * translated. pp references a pointer to storage. If *pp is null + * the necessary storage is allocated. + * size is the size of the referneced structure. + * proc is the routine to handle the referenced structure. + */ +bool_t +xdr_reference (XDR *xdrs, caddr_t *pp, u_int size, xdrproc_t proc) +{ + caddr_t loc = *pp; + bool_t stat; + + if (loc == NULL) + switch (xdrs->x_op) + { + case XDR_FREE: + return TRUE; + + case XDR_DECODE: + *pp = loc = (caddr_t) mem_alloc (size); + if (loc == NULL) + { +#ifdef USE_IN_LIBIO + if (_IO_fwide (stderr, 0) > 0) + (void) fwprintf (stderr, L"%s", + _("xdr_reference: out of memory\n")); + else +#endif + (void) fputs (_("xdr_reference: out of memory\n"), stderr); + return FALSE; + } + memset (loc, 0, (int) size); + break; + default: + break; + } + + stat = (*proc) (xdrs, loc, LASTUNSIGNED); + + if (xdrs->x_op == XDR_FREE) + { + mem_free (loc, size); + *pp = NULL; + } + return stat; +} +libc_hidden_def(xdr_reference) + +/* + * xdr_pointer(): + * + * XDR a pointer to a possibly recursive data structure. This + * differs with xdr_reference in that it can serialize/deserialize + * trees correctly. + * + * What's sent is actually a union: + * + * union object_pointer switch (boolean b) { + * case TRUE: object_data data; + * case FALSE: void nothing; + * } + * + * > objpp: Pointer to the pointer to the object. + * > obj_size: size of the object. + * > xdr_obj: routine to XDR an object. + * + */ +bool_t +xdr_pointer (XDR *xdrs, char **objpp, u_int obj_size, xdrproc_t xdr_obj) +{ + + bool_t more_data; + + more_data = (*objpp != NULL); + if (!xdr_bool (xdrs, &more_data)) + { + return FALSE; + } + if (!more_data) + { + *objpp = NULL; + return TRUE; + } + return xdr_reference (xdrs, objpp, obj_size, xdr_obj); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/xdr_stdio.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/xdr_stdio.c new file mode 100644 index 00000000..a087c9c6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/rpc/xdr_stdio.c @@ -0,0 +1,195 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +/* + * xdr_stdio.c, XDR implementation on standard i/o file. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + * + * This set of routines implements a XDR on a stdio stream. + * XDR_ENCODE serializes onto the stream, XDR_DECODE de-serializes + * from the stream. + */ + +#include +#include +#include + +#ifdef USE_IN_LIBIO +# include +# define fflush(s) _IO_fflush (s) +# define fread(p, m, n, s) _IO_fread (p, m, n, s) +# define ftell(s) _IO_ftell (s) +# define fwrite(p, m, n, s) _IO_fwrite (p, m, n, s) +#endif + + +static bool_t xdrstdio_getlong (XDR *, long *); +static bool_t xdrstdio_putlong (XDR *, const long *); +static bool_t xdrstdio_getbytes (XDR *, caddr_t, u_int); +static bool_t xdrstdio_putbytes (XDR *, const char *, u_int); +static u_int xdrstdio_getpos (const XDR *); +static bool_t xdrstdio_setpos (XDR *, u_int); +static int32_t *xdrstdio_inline (XDR *, u_int); +static void xdrstdio_destroy (XDR *); +static bool_t xdrstdio_getint32 (XDR *, int32_t *); +static bool_t xdrstdio_putint32 (XDR *, const int32_t *); + +/* + * Ops vector for stdio type XDR + */ +static const struct xdr_ops xdrstdio_ops = +{ + xdrstdio_getlong, /* deserialize a long int */ + xdrstdio_putlong, /* serialize a long int */ + xdrstdio_getbytes, /* deserialize counted bytes */ + xdrstdio_putbytes, /* serialize counted bytes */ + xdrstdio_getpos, /* get offset in the stream */ + xdrstdio_setpos, /* set offset in the stream */ + xdrstdio_inline, /* prime stream for inline macros */ + xdrstdio_destroy, /* destroy stream */ + xdrstdio_getint32, /* deserialize a int */ + xdrstdio_putint32 /* serialize a int */ +}; + +/* + * Initialize a stdio xdr stream. + * Sets the xdr stream handle xdrs for use on the stream file. + * Operation flag is set to op. + */ +void +xdrstdio_create (XDR *xdrs, FILE *file, enum xdr_op op) +{ + xdrs->x_op = op; + /* We have to add the const since the `struct xdr_ops' in `struct XDR' + is not `const'. */ + xdrs->x_ops = (struct xdr_ops *) &xdrstdio_ops; + xdrs->x_private = (caddr_t) file; + xdrs->x_handy = 0; + xdrs->x_base = 0; +} + +/* + * Destroy a stdio xdr stream. + * Cleans up the xdr stream handle xdrs previously set up by xdrstdio_create. + */ +static void +xdrstdio_destroy (XDR *xdrs) +{ + (void) fflush ((FILE *) xdrs->x_private); + /* xx should we close the file ?? */ +}; + +static bool_t +xdrstdio_getlong (XDR *xdrs, long *lp) +{ + u_int32_t mycopy; + + if (fread ((caddr_t) &mycopy, 4, 1, (FILE *) xdrs->x_private) != 1) + return FALSE; + *lp = (long) ntohl (mycopy); + return TRUE; +} + +static bool_t +xdrstdio_putlong (XDR *xdrs, const long *lp) +{ + int32_t mycopy = htonl ((u_int32_t) *lp); + + if (fwrite ((caddr_t) &mycopy, 4, 1, (FILE *) xdrs->x_private) != 1) + return FALSE; + return TRUE; +} + +static bool_t +xdrstdio_getbytes (XDR *xdrs, const caddr_t addr, u_int len) +{ + if ((len != 0) && (fread (addr, (int) len, 1, + (FILE *) xdrs->x_private) != 1)) + return FALSE; + return TRUE; +} + +static bool_t +xdrstdio_putbytes (XDR *xdrs, const char *addr, u_int len) +{ + if ((len != 0) && (fwrite (addr, (int) len, 1, + (FILE *) xdrs->x_private) != 1)) + return FALSE; + return TRUE; +} + +static u_int +xdrstdio_getpos (const XDR *xdrs) +{ + return (u_int) ftell ((FILE *) xdrs->x_private); +} + +static bool_t +xdrstdio_setpos (XDR *xdrs, u_int pos) +{ + return fseek ((FILE *) xdrs->x_private, (long) pos, 0) < 0 ? FALSE : TRUE; +} + +static int32_t * +xdrstdio_inline (XDR *xdrs attribute_unused, u_int len attribute_unused) +{ + /* + * Must do some work to implement this: must insure + * enough data in the underlying stdio buffer, + * that the buffer is aligned so that we can indirect through a + * long *, and stuff this pointer in xdrs->x_buf. Doing + * a fread or fwrite to a scratch buffer would defeat + * most of the gains to be had here and require storage + * management on this buffer, so we don't do this. + */ + return NULL; +} + +static bool_t +xdrstdio_getint32 (XDR *xdrs, int32_t *ip) +{ + int32_t mycopy; + + if (fread ((caddr_t) &mycopy, 4, 1, (FILE *) xdrs->x_private) != 1) + return FALSE; + *ip = ntohl (mycopy); + return TRUE; +} + +static bool_t +xdrstdio_putint32 (XDR *xdrs, const int32_t *ip) +{ + int32_t mycopy = htonl (*ip); + + ip = &mycopy; + if (fwrite ((caddr_t) ip, 4, 1, (FILE *) xdrs->x_private) != 1) + return FALSE; + return TRUE; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/send.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/send.c new file mode 100644 index 00000000..6b7d44b5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/send.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_send +#include "socketcalls.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/sendmsg.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/sendmsg.c new file mode 100644 index 00000000..834e8399 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/sendmsg.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_sendmsg +#include "socketcalls.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/sendto.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/sendto.c new file mode 100644 index 00000000..328baa32 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/sendto.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_sendto +#include "socketcalls.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/setsockopt.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/setsockopt.c new file mode 100644 index 00000000..b0f4a4e9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/setsockopt.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_setsockopt +#include "socketcalls.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/shutdown.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/shutdown.c new file mode 100644 index 00000000..0bcdb9f3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/shutdown.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_shutdown +#include "socketcalls.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/socket.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/socket.c new file mode 100644 index 00000000..752744b8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/socket.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_socket +#include "socketcalls.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/socketcalls.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/socketcalls.c new file mode 100644 index 00000000..42a5a563 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/socketcalls.c @@ -0,0 +1,562 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define __FORCE_GLIBC +#include +#include +#include +#include + +#ifdef __NR_socketcall +extern int __socketcall(int call, unsigned long *args) attribute_hidden; + +/* Various socketcall numbers */ +#define SYS_SOCKET 1 +#define SYS_BIND 2 +#define SYS_CONNECT 3 +#define SYS_LISTEN 4 +#define SYS_ACCEPT 5 +#define SYS_GETSOCKNAME 6 +#define SYS_GETPEERNAME 7 +#define SYS_SOCKETPAIR 8 +#define SYS_SEND 9 +#define SYS_RECV 10 +#define SYS_SENDTO 11 +#define SYS_RECVFROM 12 +#define SYS_SHUTDOWN 13 +#define SYS_SETSOCKOPT 14 +#define SYS_GETSOCKOPT 15 +#define SYS_SENDMSG 16 +#define SYS_RECVMSG 17 +#endif + +#ifdef __UCLIBC_HAS_THREADS_NATIVE__ +#include +#include +#else +#define SINGLE_THREAD_P 1 +#endif + +#ifdef L_accept +extern __typeof(accept) __libc_accept; +#ifdef __NR_accept +#define __NR___sys_accept __NR_accept +static +_syscall3(int, __sys_accept, int, call, struct sockaddr *, addr, socklen_t *,addrlen) +int __libc_accept(int s, struct sockaddr *addr, socklen_t * addrlen) +{ + if (SINGLE_THREAD_P) + return __sys_accept(s, addr, addrlen); + +#ifdef __UCLIBC_HAS_THREADS_NATIVE__ + int oldtype = LIBC_CANCEL_ASYNC (); + int result = __sys_accept(s, addr, addrlen); + LIBC_CANCEL_RESET (oldtype); + return result; +#endif +} +#elif defined(__NR_socketcall) +int __libc_accept(int s, struct sockaddr *addr, socklen_t * addrlen) +{ + unsigned long args[3]; + + args[0] = s; + args[1] = (unsigned long) addr; + args[2] = (unsigned long) addrlen; + + if (SINGLE_THREAD_P) + return __socketcall(SYS_ACCEPT, args); + +#ifdef __UCLIBC_HAS_THREADS_NATIVE__ + int oldtype = LIBC_CANCEL_ASYNC (); + int result = __socketcall(SYS_ACCEPT, args); + LIBC_CANCEL_RESET (oldtype); + return result; +#endif +} +#endif +weak_alias(__libc_accept,accept) +libc_hidden_weak(accept) +#endif + +#ifdef L_bind +#ifdef __NR_bind +_syscall3(int, bind, int, sockfd, const struct sockaddr *, myaddr, socklen_t, addrlen) +#elif defined(__NR_socketcall) +int bind(int sockfd, const struct sockaddr *myaddr, socklen_t addrlen) +{ + unsigned long args[3]; + + args[0] = sockfd; + args[1] = (unsigned long) myaddr; + args[2] = addrlen; + return __socketcall(SYS_BIND, args); +} +#endif +libc_hidden_def(bind) +#endif + +#ifdef L_connect +extern __typeof(connect) __libc_connect; +#ifdef __NR_connect +#define __NR___sys_connect __NR_connect +static +_syscall3(int, __sys_connect, int, sockfd, const struct sockaddr *, saddr, socklen_t, addrlen) +int __libc_connect(int sockfd, const struct sockaddr *saddr, socklen_t addrlen) +{ + if (SINGLE_THREAD_P) + return __sys_connect(sockfd, saddr, addrlen); + +#ifdef __UCLIBC_HAS_THREADS_NATIVE__ + int oldtype = LIBC_CANCEL_ASYNC (); + int result = __sys_connect(sockfd, saddr, addrlen); + LIBC_CANCEL_RESET (oldtype); + return result; +#endif +} +#elif defined(__NR_socketcall) +int __libc_connect(int sockfd, const struct sockaddr *saddr, socklen_t addrlen) +{ + unsigned long args[3]; + + args[0] = sockfd; + args[1] = (unsigned long) saddr; + args[2] = addrlen; + + if (SINGLE_THREAD_P) + return __socketcall(SYS_CONNECT, args); + +#ifdef __UCLIBC_HAS_THREADS_NATIVE__ + int oldtype = LIBC_CANCEL_ASYNC (); + int result = __socketcall(SYS_CONNECT, args); + LIBC_CANCEL_RESET (oldtype); + return result; +#endif +} +#endif +weak_alias(__libc_connect,connect) +libc_hidden_weak(connect) +#endif + +#ifdef L_getpeername +#ifdef __NR_getpeername +_syscall3(int, getpeername, int, sockfd, struct sockaddr *, addr, socklen_t *,paddrlen) +#elif defined(__NR_socketcall) +int getpeername(int sockfd, struct sockaddr *addr, socklen_t * paddrlen) +{ + unsigned long args[3]; + + args[0] = sockfd; + args[1] = (unsigned long) addr; + args[2] = (unsigned long) paddrlen; + return __socketcall(SYS_GETPEERNAME, args); +} +#endif +#endif + +#ifdef L_getsockname +#ifdef __NR_getsockname +_syscall3(int, getsockname, int, sockfd, struct sockaddr *, addr, socklen_t *,paddrlen) +#elif defined(__NR_socketcall) +int getsockname(int sockfd, struct sockaddr *addr, socklen_t * paddrlen) +{ + unsigned long args[3]; + + args[0] = sockfd; + args[1] = (unsigned long) addr; + args[2] = (unsigned long) paddrlen; + return __socketcall(SYS_GETSOCKNAME, args); +} +#endif +libc_hidden_def(getsockname) +#endif + +#ifdef L_getsockopt +#ifdef __NR_getsockopt +_syscall5(int, getsockopt, int, fd, int, level, int, optname, __ptr_t, optval, socklen_t *, optlen) +#elif defined(__NR_socketcall) +int getsockopt(int fd, int level, int optname, __ptr_t optval, + socklen_t * optlen) +{ + unsigned long args[5]; + + args[0] = fd; + args[1] = level; + args[2] = optname; + args[3] = (unsigned long) optval; + args[4] = (unsigned long) optlen; + return (__socketcall(SYS_GETSOCKOPT, args)); +} +#endif +#endif + +#ifdef L_listen +#ifdef __NR_listen +_syscall2(int, listen, int, sockfd, int, backlog) +#elif defined(__NR_socketcall) +int listen(int sockfd, int backlog) +{ + unsigned long args[2]; + + args[0] = sockfd; + args[1] = backlog; + return __socketcall(SYS_LISTEN, args); +} +#endif +libc_hidden_def(listen) +#endif + +#ifdef L_recv +extern __typeof(recv) __libc_recv; +#ifdef __NR_recv +#define __NR___sys_recv __NR_recv +static +_syscall4(ssize_t, __sys_recv, int, sockfd, __ptr_t, buffer, size_t, len, + int, flags) +ssize_t __libc_recv(int sockfd, __ptr_t buffer, size_t len, int flags) +{ + if (SINGLE_THREAD_P) + return __sys_recv(sockfd, buffer, len, flags); + +#ifdef __UCLIBC_HAS_THREADS_NATIVE__ + int oldtype = LIBC_CANCEL_ASYNC (); + int result = __sys_recv(sockfd, buffer, len, flags); + LIBC_CANCEL_RESET (oldtype); + return result; +#endif +} +#elif defined(__NR_socketcall) +/* recv, recvfrom added by bir7@leland.stanford.edu */ +ssize_t __libc_recv(int sockfd, __ptr_t buffer, size_t len, int flags) +{ + unsigned long args[4]; + + args[0] = sockfd; + args[1] = (unsigned long) buffer; + args[2] = len; + args[3] = flags; + + if (SINGLE_THREAD_P) + return (__socketcall(SYS_RECV, args)); + +#ifdef __UCLIBC_HAS_THREADS_NATIVE__ + int oldtype = LIBC_CANCEL_ASYNC (); + int result = __socketcall(SYS_RECV, args); + LIBC_CANCEL_RESET (oldtype); + return result; +#endif +} +#elif defined(__NR_recvfrom) +ssize_t __libc_recv(int sockfd, __ptr_t buffer, size_t len, int flags) +{ + return (recvfrom(sockfd, buffer, len, flags, NULL, NULL)); +} +#endif +weak_alias(__libc_recv,recv) +libc_hidden_weak(recv) +#endif + +#ifdef L_recvfrom +extern __typeof(recvfrom) __libc_recvfrom; +#ifdef __NR_recvfrom +#define __NR___sys_recvfrom __NR_recvfrom +static +_syscall6(ssize_t, __sys_recvfrom, int, sockfd, __ptr_t, buffer, size_t, len, + int, flags, struct sockaddr *, to, socklen_t *, tolen) +ssize_t __libc_recvfrom(int sockfd, __ptr_t buffer, size_t len, int flags, + struct sockaddr *to, socklen_t * tolen) +{ + if (SINGLE_THREAD_P) + return __sys_recvfrom(sockfd, buffer, len, flags, to, tolen); + +#ifdef __UCLIBC_HAS_THREADS_NATIVE__ + int oldtype = LIBC_CANCEL_ASYNC (); + int result = __sys_recvfrom(sockfd, buffer, len, flags, to, tolen); + LIBC_CANCEL_RESET (oldtype); + return result; +#endif +} +#elif defined(__NR_socketcall) +/* recv, recvfrom added by bir7@leland.stanford.edu */ +ssize_t __libc_recvfrom(int sockfd, __ptr_t buffer, size_t len, int flags, + struct sockaddr *to, socklen_t * tolen) +{ + unsigned long args[6]; + + args[0] = sockfd; + args[1] = (unsigned long) buffer; + args[2] = len; + args[3] = flags; + args[4] = (unsigned long) to; + args[5] = (unsigned long) tolen; + + if (SINGLE_THREAD_P) + return (__socketcall(SYS_RECVFROM, args)); + +#ifdef __UCLIBC_HAS_THREADS_NATIVE__ + int oldtype = LIBC_CANCEL_ASYNC (); + int result = __socketcall(SYS_RECVFROM, args); + LIBC_CANCEL_RESET (oldtype); + return result; +#endif +} +#endif +weak_alias(__libc_recvfrom,recvfrom) +libc_hidden_weak(recvfrom) +#endif + +#ifdef L_recvmsg +extern __typeof(recvmsg) __libc_recvmsg; +#ifdef __NR_recvmsg +#define __NR___sys_recvmsg __NR_recvmsg +static +_syscall3(ssize_t, __sys_recvmsg, int, sockfd, struct msghdr *, msg, int, flags) +ssize_t __libc_recvmsg(int sockfd, struct msghdr *msg, int flags) +{ + if (SINGLE_THREAD_P) + return __sys_recvmsg(sockfd, msg, flags); + +#ifdef __UCLIBC_HAS_THREADS_NATIVE__ + int oldtype = LIBC_CANCEL_ASYNC (); + int result = __sys_recvmsg(sockfd, msg, flags); + LIBC_CANCEL_RESET (oldtype); + return result; +#endif +} +#elif defined(__NR_socketcall) +ssize_t __libc_recvmsg(int sockfd, struct msghdr *msg, int flags) +{ + unsigned long args[3]; + + args[0] = sockfd; + args[1] = (unsigned long) msg; + args[2] = flags; + + if (SINGLE_THREAD_P) + return (__socketcall(SYS_RECVMSG, args)); + +#ifdef __UCLIBC_HAS_THREADS_NATIVE__ + int oldtype = LIBC_CANCEL_ASYNC (); + int result = __socketcall(SYS_RECVMSG, args); + LIBC_CANCEL_RESET (oldtype); + return result; +#endif +} +#endif +weak_alias(__libc_recvmsg,recvmsg) +libc_hidden_weak(recvmsg) +#endif + +#ifdef L_send +extern __typeof(send) __libc_send; +#ifdef __NR_send +#define __NR___sys_send __NR_send +static +_syscall4(ssize_t, __sys_send, int, sockfd, const void *, buffer, size_t, len, int, flags) +ssize_t __libc_send(int sockfd, const void *buffer, size_t len, int flags) +{ + if (SINGLE_THREAD_P) + return __sys_send(sockfd, buffer, len, flags); + +#ifdef __UCLIBC_HAS_THREADS_NATIVE__ + int oldtype = LIBC_CANCEL_ASYNC (); + int result = __sys_send(sockfd, buffer, len, flags); + LIBC_CANCEL_RESET (oldtype); + return result; +#endif +} +#elif defined(__NR_socketcall) +/* send, sendto added by bir7@leland.stanford.edu */ +ssize_t __libc_send(int sockfd, const void *buffer, size_t len, int flags) +{ + unsigned long args[4]; + + args[0] = sockfd; + args[1] = (unsigned long) buffer; + args[2] = len; + args[3] = flags; + + if (SINGLE_THREAD_P) + return (__socketcall(SYS_SEND, args)); + +#ifdef __UCLIBC_HAS_THREADS_NATIVE__ + int oldtype = LIBC_CANCEL_ASYNC (); + int result = __socketcall(SYS_SEND, args); + LIBC_CANCEL_RESET (oldtype); + return result; +#endif +} + +#elif defined(__NR_sendto) +ssize_t __libc_send(int sockfd, const void *buffer, size_t len, int flags) +{ + return (sendto(sockfd, buffer, len, flags, NULL, 0)); +} +#endif +weak_alias(__libc_send,send) +libc_hidden_weak(send) +#endif + +#ifdef L_sendmsg +extern __typeof(sendmsg) __libc_sendmsg; +#ifdef __NR_sendmsg +#define __NR___sys_sendmsg __NR_sendmsg +static +_syscall3(ssize_t, __sys_sendmsg, int, sockfd, const struct msghdr *, msg, int, flags) +ssize_t __libc_sendmsg(int sockfd, const struct msghdr *msg, int flags) +{ + if (SINGLE_THREAD_P) + return __sys_sendmsg(sockfd, msg, flags); + +#ifdef __UCLIBC_HAS_THREADS_NATIVE__ + int oldtype = LIBC_CANCEL_ASYNC (); + int result = __sys_sendmsg(sockfd, msg, flags); + LIBC_CANCEL_RESET (oldtype); + return result; +#endif +} +#elif defined(__NR_socketcall) +ssize_t __libc_sendmsg(int sockfd, const struct msghdr *msg, int flags) +{ + unsigned long args[3]; + + args[0] = sockfd; + args[1] = (unsigned long) msg; + args[2] = flags; + + if (SINGLE_THREAD_P) + return (__socketcall(SYS_SENDMSG, args)); + +#ifdef __UCLIBC_HAS_THREADS_NATIVE__ + int oldtype = LIBC_CANCEL_ASYNC (); + int result = __socketcall(SYS_SENDMSG, args); + LIBC_CANCEL_RESET (oldtype); + return result; +#endif +} +#endif +weak_alias(__libc_sendmsg,sendmsg) +libc_hidden_weak(sendmsg) +#endif + +#ifdef L_sendto +extern __typeof(sendto) __libc_sendto; +#ifdef __NR_sendto +#define __NR___sys_sendto __NR_sendto +static +_syscall6(ssize_t, __sys_sendto, int, sockfd, const void *, buffer, + size_t, len, int, flags, const struct sockaddr *, to, socklen_t, tolen) +ssize_t __libc_sendto(int sockfd, const void *buffer, size_t len, int flags,const struct sockaddr *to, socklen_t tolen) +{ + if (SINGLE_THREAD_P) + return __sys_sendto(sockfd, buffer, len, flags, to, tolen); + +#ifdef __UCLIBC_HAS_THREADS_NATIVE__ + int oldtype = LIBC_CANCEL_ASYNC (); + int result = __sys_sendto(sockfd, buffer, len, flags, to, tolen); + LIBC_CANCEL_RESET (oldtype); + return result; +#endif +} +#elif defined(__NR_socketcall) +/* send, sendto added by bir7@leland.stanford.edu */ +ssize_t __libc_sendto(int sockfd, const void *buffer, size_t len, int flags, + const struct sockaddr *to, socklen_t tolen) +{ + unsigned long args[6]; + + args[0] = sockfd; + args[1] = (unsigned long) buffer; + args[2] = len; + args[3] = flags; + args[4] = (unsigned long) to; + args[5] = tolen; + + if (SINGLE_THREAD_P) + return (__socketcall(SYS_SENDTO, args)); + +#ifdef __UCLIBC_HAS_THREADS_NATIVE__ + int oldtype = LIBC_CANCEL_ASYNC (); + int result = __socketcall(SYS_SENDTO, args); + LIBC_CANCEL_RESET (oldtype); + return result; +#endif +} +#endif +weak_alias(__libc_sendto,sendto) +libc_hidden_weak(sendto) +#endif + +#ifdef L_setsockopt +#ifdef __NR_setsockopt +_syscall5(int, setsockopt, int, fd, int, level, int, optname, const void *, optval, socklen_t, optlen) +#elif defined(__NR_socketcall) +/* [sg]etsockoptions by bir7@leland.stanford.edu */ +int setsockopt(int fd, int level, int optname, const void *optval, + socklen_t optlen) +{ + unsigned long args[5]; + + args[0] = fd; + args[1] = level; + args[2] = optname; + args[3] = (unsigned long) optval; + args[4] = optlen; + return (__socketcall(SYS_SETSOCKOPT, args)); +} +#endif +libc_hidden_def(setsockopt) +#endif + +#ifdef L_shutdown +#ifdef __NR_shutdown +_syscall2(int, shutdown, int, sockfd, int, how) +#elif defined(__NR_socketcall) +/* shutdown by bir7@leland.stanford.edu */ +int shutdown(int sockfd, int how) +{ + unsigned long args[2]; + + args[0] = sockfd; + args[1] = how; + return (__socketcall(SYS_SHUTDOWN, args)); +} +#endif +#endif + +#ifdef L_socket +#ifdef __NR_socket +_syscall3(int, socket, int, family, int, type, int, protocol) +#elif defined(__NR_socketcall) +int socket(int family, int type, int protocol) +{ + unsigned long args[3]; + + args[0] = family; + args[1] = type; + args[2] = (unsigned long) protocol; + return __socketcall(SYS_SOCKET, args); +} +#endif +libc_hidden_def(socket) +#endif + +#ifdef L_socketpair +#ifdef __NR_socketpair +_syscall4(int, socketpair, int, family, int, type, int, protocol, int *, sockvec) +#elif defined(__NR_socketcall) +int socketpair(int family, int type, int protocol, int sockvec[2]) +{ + unsigned long args[4]; + + args[0] = family; + args[1] = type; + args[2] = protocol; + args[3] = (unsigned long) sockvec; + return __socketcall(SYS_SOCKETPAIR, args); +} +#endif +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/socketpair.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/socketpair.c new file mode 100644 index 00000000..f7c43547 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/inet/socketpair.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_socketpair +#include "socketcalls.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/Makefile new file mode 100644 index 00000000..11f362a5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../ +top_builddir=../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/Makefile.in new file mode 100644 index 00000000..6c09d314 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/Makefile.in @@ -0,0 +1,35 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2006 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +#DIRS:=assert ctype dirent error file fnmatch ftw glob gnu internals intl locale mntent \ +# pthread regex search statfs syslog sysvipc time ttyent utmp wchar wctype wordexp + +include $(top_srcdir)libc/misc/assert/Makefile.in +include $(top_srcdir)libc/misc/ctype/Makefile.in +include $(top_srcdir)libc/misc/dirent/Makefile.in +include $(top_srcdir)libc/misc/error/Makefile.in +include $(top_srcdir)libc/misc/elf/Makefile.in +include $(top_srcdir)libc/misc/file/Makefile.in +include $(top_srcdir)libc/misc/fnmatch/Makefile.in +include $(top_srcdir)libc/misc/ftw/Makefile.in +include $(top_srcdir)libc/misc/glob/Makefile.in +include $(top_srcdir)libc/misc/gnu/Makefile.in +include $(top_srcdir)libc/misc/internals/Makefile.in +include $(top_srcdir)libc/misc/locale/Makefile.in +include $(top_srcdir)libc/misc/mntent/Makefile.in +include $(top_srcdir)libc/misc/pthread/Makefile.in +include $(top_srcdir)libc/misc/regex/Makefile.in +include $(top_srcdir)libc/misc/search/Makefile.in +include $(top_srcdir)libc/misc/statfs/Makefile.in +include $(top_srcdir)libc/misc/syslog/Makefile.in +include $(top_srcdir)libc/misc/sysvipc/Makefile.in +include $(top_srcdir)libc/misc/time/Makefile.in +include $(top_srcdir)libc/misc/ttyent/Makefile.in +include $(top_srcdir)libc/misc/utmp/Makefile.in +include $(top_srcdir)libc/misc/wchar/Makefile.in +include $(top_srcdir)libc/misc/wctype/Makefile.in +include $(top_srcdir)libc/misc/wordexp/Makefile.in diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/assert/.indent.pro b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/assert/.indent.pro new file mode 100644 index 00000000..492ecf1c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/assert/.indent.pro @@ -0,0 +1,33 @@ +--blank-lines-after-declarations +--blank-lines-after-procedures +--break-before-boolean-operator +--no-blank-lines-after-commas +--braces-on-if-line +--braces-on-struct-decl-line +--comment-indentation25 +--declaration-comment-column25 +--no-comment-delimiters-on-blank-lines +--cuddle-else +--continuation-indentation4 +--case-indentation0 +--else-endif-column33 +--space-after-cast +--line-comments-indentation0 +--declaration-indentation1 +--dont-format-first-column-comments +--dont-format-comments +--honour-newlines +--indent-level4 +/* changed from 0 to 4 */ +--parameter-indentation4 +--line-length78 /* changed from 75 */ +--continue-at-parentheses +--no-space-after-function-call-names +--dont-break-procedure-type +--dont-star-comments +--leave-optional-blank-lines +--dont-space-special-semicolon +--tab-size4 +/* additions by Mark */ +--case-brace-indentation0 +--leave-preprocessor-space diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/assert/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/assert/Makefile new file mode 100644 index 00000000..4a8f4a07 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/assert/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../ +top_builddir=../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/assert/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/assert/Makefile.in new file mode 100644 index 00000000..a49e00d2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/assert/Makefile.in @@ -0,0 +1,23 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +subdirs += libc/misc/assert + +CSRC := __assert.c + +MISC_ASSERT_DIR := $(top_srcdir)libc/misc/assert +MISC_ASSERT_OUT := $(top_builddir)libc/misc/assert + +MISC_ASSERT_SRC := $(MISC_ASSERT_DIR)/__assert.c +MISC_ASSERT_OBJ := $(MISC_ASSERT_OUT)/__assert.o + +libc-y += $(MISC_ASSERT_OBJ) + +objclean-y += CLEAN_libc/misc/assert + +CLEAN_libc/misc/assert: + $(do_rm) $(addprefix $(MISC_ASSERT_OUT)/*., o os) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/assert/__assert.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/assert/__assert.c new file mode 100644 index 00000000..8afde52f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/assert/__assert.c @@ -0,0 +1,66 @@ +/* Copyright (C) 2002 Manuel Novoa III + * An __assert() function compatible with the modified glibc assert.h + * that is used by uClibc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* Oct 28, 2002 + * + * ANSI/ISO C99 requires assert() to write to stderr. This means that + * writing to STDERR_FILENO is insufficient, as the user could freopen + * stderr. It is also insufficient to output to fileno(stderr) since + * this would fail in the custom stream case. I didn't remove the + * old code though, as it doesn't use stdio stream functionality + * and is useful in debugging the stdio code. + */ + +#include +#include +#include + +/* Get the prototype from assert.h as a double-check. */ +#undef NDEBUG +#include +#undef assert + + +#define ASSERT_SHOW_PROGNAME 1 + +static smallint in_assert; /* bss inits to 0. */ + +void __assert(const char *assertion, const char * filename, + unsigned int linenumber, register const char * function) +{ + if (!in_assert) { + in_assert = 1; + + fprintf(stderr, +#ifdef ASSERT_SHOW_PROGNAME + "%s: %s: %d: %s: Assertion `%s' failed.\n", __uclibc_progname, +#else + "%s: %d: %s: Assertion `%s' failed.\n", +#endif + filename, + linenumber, + /* Function name isn't available with some compilers. */ + ((function == NULL) ? "?function?" : function), + assertion + ); + } + /* shouldn't we? fflush(stderr); */ + abort(); +} +libc_hidden_def(__assert) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/.indent.pro b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/.indent.pro new file mode 100644 index 00000000..492ecf1c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/.indent.pro @@ -0,0 +1,33 @@ +--blank-lines-after-declarations +--blank-lines-after-procedures +--break-before-boolean-operator +--no-blank-lines-after-commas +--braces-on-if-line +--braces-on-struct-decl-line +--comment-indentation25 +--declaration-comment-column25 +--no-comment-delimiters-on-blank-lines +--cuddle-else +--continuation-indentation4 +--case-indentation0 +--else-endif-column33 +--space-after-cast +--line-comments-indentation0 +--declaration-indentation1 +--dont-format-first-column-comments +--dont-format-comments +--honour-newlines +--indent-level4 +/* changed from 0 to 4 */ +--parameter-indentation4 +--line-length78 /* changed from 75 */ +--continue-at-parentheses +--no-space-after-function-call-names +--dont-break-procedure-type +--dont-star-comments +--leave-optional-blank-lines +--dont-space-special-semicolon +--tab-size4 +/* additions by Mark */ +--case-brace-indentation0 +--leave-preprocessor-space diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/Makefile new file mode 100644 index 00000000..4a8f4a07 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../ +top_builddir=../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/Makefile.in new file mode 100644 index 00000000..125d9169 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/Makefile.in @@ -0,0 +1,42 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +subdirs += libc/misc/ctype + +# multi source ctype.c +COM_SRC := \ + isalnum.c isalpha.c iscntrl.c isdigit.c \ + isgraph.c islower.c isprint.c ispunct.c isspace.c \ + isupper.c isxdigit.c tolower.c toupper.c \ + isblank.c +ifeq ($(UCLIBC_SUSV4_LEGACY),y) +COM_SRC += isascii.c toascii.c +endif +CSRC := $(COM_SRC) + +ifeq ($(UCLIBC_HAS_CTYPE_TABLES),y) +CSRC += __C_ctype_b.c __C_ctype_tolower.c __C_ctype_toupper.c \ + __ctype_b_loc.c __ctype_tolower_loc.c __ctype_toupper_loc.c \ + __ctype_assert.c isctype.c +endif + +ifeq ($(UCLIBC_HAS_XLOCALE),y) +CSRC += $(patsubst %.c,%_l.c,$(COM_SRC)) +endif + +MISC_CTYPE_DIR := $(top_srcdir)libc/misc/ctype +MISC_CTYPE_OUT := $(top_builddir)libc/misc/ctype + +MISC_CTYPE_SRC := $(patsubst %.c,$(MISC_CTYPE_DIR)/%.c,$(CSRC)) +MISC_CTYPE_OBJ := $(patsubst %.c,$(MISC_CTYPE_OUT)/%.o,$(CSRC)) + +libc-y += $(MISC_CTYPE_OBJ) + +objclean-y += CLEAN_libc/misc/ctype + +CLEAN_libc/misc/ctype: + $(do_rm) $(addprefix $(MISC_CTYPE_OUT)/*., o os) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/__C_ctype_b.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/__C_ctype_b.c new file mode 100644 index 00000000..d22359f3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/__C_ctype_b.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2003-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L___C_ctype_b +#include "ctype.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/__C_ctype_tolower.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/__C_ctype_tolower.c new file mode 100644 index 00000000..fc6027f5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/__C_ctype_tolower.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2003-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L___C_ctype_tolower +#include "ctype.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/__C_ctype_toupper.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/__C_ctype_toupper.c new file mode 100644 index 00000000..ec42fbfb --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/__C_ctype_toupper.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2003-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L___C_ctype_toupper +#include "ctype.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/__ctype_assert.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/__ctype_assert.c new file mode 100644 index 00000000..fe459458 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/__ctype_assert.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2003-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L___ctype_assert +#include "ctype.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/__ctype_b_loc.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/__ctype_b_loc.c new file mode 100644 index 00000000..11d50469 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/__ctype_b_loc.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2003-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L___ctype_b_loc +#include "ctype.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/__ctype_tolower_loc.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/__ctype_tolower_loc.c new file mode 100644 index 00000000..54037a59 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/__ctype_tolower_loc.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2003-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L___ctype_tolower_loc +#include "ctype.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/__ctype_toupper_loc.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/__ctype_toupper_loc.c new file mode 100644 index 00000000..e511d0f7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/__ctype_toupper_loc.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2003-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L___ctype_toupper_loc +#include "ctype.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/ctype.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/ctype.c new file mode 100644 index 00000000..e46f66b5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/ctype.c @@ -0,0 +1,1088 @@ +/* Copyright (C) 2003 Manuel Novoa III + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION! + * + * Besides uClibc, I'm using this code in my libc for elks, which is + * a 16-bit environment with a fairly limited compiler. It would make + * things much easier for me if this file isn't modified unnecessarily. + * In particular, please put any new or replacement functions somewhere + * else, and modify the makefile to use your version instead. + * Thanks. Manuel + * + * ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION! */ + +#define __NO_CTYPE + +#include +#include +#include +#include +#include +#include +#include + +#ifdef __UCLIBC_HAS_XLOCALE__ +# include +#endif + +/**********************************************************************/ +#ifdef __UCLIBC_HAS_CTYPE_TABLES__ + +#ifdef __UCLIBC_HAS_CTYPE_SIGNED__ + +#if EOF >= CHAR_MIN +#define CTYPE_DOMAIN_CHECK(C) \ + (((unsigned int)((C) - CHAR_MIN)) <= (UCHAR_MAX - CHAR_MIN)) +#else +#define CTYPE_DOMAIN_CHECK(C) \ + ((((unsigned int)((C) - CHAR_MIN)) <= (UCHAR_MAX - CHAR_MIN)) || ((C) == EOF)) +#endif + +#else /* __UCLIBC_HAS_CTYPE_SIGNED__ */ + +#if EOF == -1 +#define CTYPE_DOMAIN_CHECK(C) \ + (((unsigned int)((C) - EOF)) <= (UCHAR_MAX - EOF)) +#else +#define CTYPE_DOMAIN_CHECK(C) \ + ((((unsigned int)(C)) <= UCHAR_MAX) || ((C) == EOF)) +#endif + +#endif /* __UCLIBC_HAS_CTYPE_SIGNED__ */ + +#endif /* __UCLIBC_HAS_CTYPE_TABLES__ */ +/**********************************************************************/ +#ifdef __UCLIBC_MJN3_ONLY__ +#ifdef L_isspace +/* emit only once */ +#warning CONSIDER: Should we assert when debugging and __UCLIBC_HAS_CTYPE_CHECKED? +#warning TODO: Fix asserts in to{upper|lower}{_l}. +#warning TODO: Optimize the isx*() funcs. +#endif +#endif /* __UCLIBC_MJN3_ONLY__ */ +/**********************************************************************/ +#undef PASTE2 +#define PASTE2(X,Y) X ## Y + +#ifdef __UCLIBC_HAS_CTYPE_TABLES__ + +#undef CTYPE_NAME +#undef ISCTYPE +#undef CTYPE_ALIAS +#undef CTYPE_DEF +#ifdef __UCLIBC_DO_XLOCALE +#define CTYPE_NAME(X) __is ## X ## _l +#define ISCTYPE(C,F) __isctype_l( C, F, locale_arg) +#define CTYPE_ALIAS(NAME) strong_alias( __is ## NAME ## _l , is ## NAME ## _l) +#define CTYPE_DEF(NAME) libc_hidden_def(is ## NAME ## _l) +#else +#define CTYPE_NAME(X) is ## X +#define ISCTYPE(C,F) __isctype( C, F ) +#define CTYPE_ALIAS(NAME) +#define CTYPE_DEF(NAME) libc_hidden_def(is ## NAME) +#endif + + +#undef CTYPE_BODY + +#if defined(__UCLIBC_HAS_CTYPE_ENFORCED__) +/* Make sure assert is active for to*() funcs below. */ +#undef NDEBUG +#include + +extern void __isctype_assert(int c, int mask) __attribute__ ((__noreturn__)) attribute_hidden; + +#define CTYPE_BODY(NAME,C,MASK) \ + if (CTYPE_DOMAIN_CHECK(C)) { \ + return ISCTYPE(C, MASK); \ + } \ + __isctype_assert(C, MASK); + +#elif defined(__UCLIBC_HAS_CTYPE_CHECKED__) + +#define CTYPE_BODY(NAME,C,MASK) \ + return CTYPE_DOMAIN_CHECK(C) \ + ? ISCTYPE(C, MASK) \ + : 0; + +#elif defined(__UCLIBC_HAS_CTYPE_UNSAFE__) + +#define CTYPE_BODY(NAME,C,MASK) \ + return ISCTYPE(C, MASK); + + +#else /* No checking done. */ + +#error Unknown type of ctype checking! + +#endif + + + +#define IS_FUNC_BODY(NAME) \ +int CTYPE_NAME(NAME) (int c __LOCALE_PARAM ); \ +int CTYPE_NAME(NAME) (int c __LOCALE_PARAM ) \ +{ \ + CTYPE_BODY(NAME,c,PASTE2(_IS,NAME)) \ +} \ +CTYPE_DEF(NAME) \ +CTYPE_ALIAS(NAME) + +#else /* __UCLIBC_HAS_CTYPE_TABLES__ */ + +#define C_MACRO(X) PASTE2(__C_is,X)(c) +#define CTYPE_NAME(X) is ## X +#define CTYPE_DEF(NAME) libc_hidden_def(is ## NAME) + +#define IS_FUNC_BODY(NAME) \ +int CTYPE_NAME(NAME) (int c) \ +{ \ + return C_MACRO(NAME); \ +} + +#endif /* __UCLIBC_HAS_CTYPE_TABLES__ */ +/**********************************************************************/ +#ifdef L___ctype_assert +#ifdef __UCLIBC_HAS_CTYPE_ENFORCED__ + + +attribute_hidden void __isctype_assert(int c, int mask) +{ + fprintf(stderr, "%s: __is*{_l}(%d,%#x {locale})\n", __uclibc_progname, c, mask); + abort(); +} + +#endif +#endif +/**********************************************************************/ +#if defined(L_isalnum) || defined(L_isalnum_l) + +IS_FUNC_BODY(alnum); + +#endif +/**********************************************************************/ +#if defined(L_isalpha) || defined(L_isalpha_l) + +IS_FUNC_BODY(alpha); + +#endif +/**********************************************************************/ +#if defined(L_isblank) || defined(L_isblank_l) + +IS_FUNC_BODY(blank); + +#endif +/**********************************************************************/ +#if defined(L_iscntrl) || defined(L_iscntrl_l) + +IS_FUNC_BODY(cntrl); + +#endif +/**********************************************************************/ +#if defined(L_isdigit) || defined(L_isdigit_l) + +#ifdef __UCLIBC_HAS_CTYPE_TABLES__ + +/* The standards require EOF < 0. */ +#if EOF >= CHAR_MIN +#define __isdigit_char_or_EOF(C) __isdigit_char((C)) +#else +#define __isdigit_char_or_EOF(C) __isdigit_int((C)) +#endif + +int CTYPE_NAME(digit) (int C __LOCALE_PARAM); +int CTYPE_NAME(digit) (int C __LOCALE_PARAM) +{ +#if defined(__UCLIBC_HAS_CTYPE_ENFORCED__) + if (CTYPE_DOMAIN_CHECK(C)) { + return __isdigit_char_or_EOF(C); /* C is (unsigned) char or EOF. */ + } + __isctype_assert(C, _ISdigit); +#else + return __isdigit_int(C); /* C could be invalid. */ +#endif +} +CTYPE_DEF(digit) +CTYPE_ALIAS(digit) + +#else /* __UCLIBC_HAS_CTYPE_TABLES__ */ + +IS_FUNC_BODY(digit); + +#endif /* __UCLIBC_HAS_CTYPE_TABLES__ */ + +#endif +/**********************************************************************/ +#if defined(L_isgraph) || defined(L_isgraph_l) + +IS_FUNC_BODY(graph); + +#endif +/**********************************************************************/ +#if defined(L_islower) || defined(L_islower_l) + +IS_FUNC_BODY(lower); + +#endif +/**********************************************************************/ +#if defined(L_isprint) || defined(L_isprint_l) + +IS_FUNC_BODY(print); + +#endif +/**********************************************************************/ +#if defined(L_ispunct) || defined(L_ispunct_l) + +IS_FUNC_BODY(punct); + +#endif +/**********************************************************************/ +#if defined(L_isspace) || defined(L_isspace_l) + +IS_FUNC_BODY(space); + +#endif +/**********************************************************************/ +#if defined(L_isupper) || defined(L_isupper_l) + +IS_FUNC_BODY(upper); + +#endif +/**********************************************************************/ +#if defined(L_isxdigit) || defined(L_isxdigit_l) + +IS_FUNC_BODY(xdigit); + +#endif +/**********************************************************************/ +#ifdef L_tolower + +#undef tolower +#ifdef __UCLIBC_HAS_CTYPE_TABLES__ + +int tolower(int c) +{ +#if defined(__UCLIBC_HAS_CTYPE_ENFORCED__) + assert(CTYPE_DOMAIN_CHECK(c)); +#endif + return __UCLIBC_CTYPE_IN_TO_DOMAIN(c) ? (__UCLIBC_CTYPE_TOLOWER)[c] : c; +} + +#else /* __UCLIBC_HAS_CTYPE_TABLES__ */ + +int tolower(int c) +{ + return __C_tolower(c); +} + +#endif /* __UCLIBC_HAS_CTYPE_TABLES__ */ +libc_hidden_def(tolower) + +#endif +/**********************************************************************/ +#ifdef L_tolower_l + +#undef tolower_l +int tolower_l(int c, __locale_t l) +{ +#if defined(__UCLIBC_HAS_CTYPE_ENFORCED__) + assert(CTYPE_DOMAIN_CHECK(c)); +#endif + return __UCLIBC_CTYPE_IN_TO_DOMAIN(c) ? l->__ctype_tolower[c] : c; +} +libc_hidden_def(tolower_l) +/*remove after 0.9.31. See ctype.h for why. + *weak_alias (tolower_l, __tolower_l) */ + +#endif +/**********************************************************************/ +#ifdef L_toupper + +#undef toupper +#ifdef __UCLIBC_HAS_CTYPE_TABLES__ + +int toupper(int c) +{ +#if defined(__UCLIBC_HAS_CTYPE_ENFORCED__) + assert(CTYPE_DOMAIN_CHECK(c)); +#endif + return __UCLIBC_CTYPE_IN_TO_DOMAIN(c) ? (__UCLIBC_CTYPE_TOUPPER)[c] : c; +} + +#else /* __UCLIBC_HAS_CTYPE_TABLES__ */ + +int toupper(int c) +{ + return __C_toupper(c); +} + +#endif /* __UCLIBC_HAS_CTYPE_TABLES__ */ +libc_hidden_def(toupper) + +#endif +/**********************************************************************/ +#ifdef L_toupper_l + +#undef toupper_l +int toupper_l(int c, __locale_t l) +{ +#if defined(__UCLIBC_HAS_CTYPE_ENFORCED__) + assert(CTYPE_DOMAIN_CHECK(c)); +#endif + return __UCLIBC_CTYPE_IN_TO_DOMAIN(c) ? l->__ctype_toupper[c] : c; +} +libc_hidden_def(toupper_l) +/*remove after 0.9.31. See ctype.h for why. + *weak_alias (toupper_l, __toupper_l) */ + +#endif +/**********************************************************************/ +#if defined(L_isascii) || defined(L_isascii_l) + +#ifdef __UCLIBC_HAS_CTYPE_TABLES__ + +int __XL_NPP(isascii)(int c); +int __XL_NPP(isascii)(int c) +{ + return __isascii(c); /* locale-independent */ +} + +#else /* __UCLIBC_HAS_CTYPE_TABLES__ */ + +int isascii(int c) +{ + return __isascii(c); /* locale-independent */ +} + +#endif /* __UCLIBC_HAS_CTYPE_TABLES__ */ +CTYPE_DEF(ascii) + + +#endif +/**********************************************************************/ +#if defined(L_toascii) || defined(L_toascii_l) + +#ifdef __UCLIBC_HAS_CTYPE_TABLES__ + +int __XL_NPP(toascii)(int c); +int __XL_NPP(toascii)(int c) +{ + return __toascii(c); /* locale-independent */ +} + +#else /* __UCLIBC_HAS_CTYPE_TABLES__ */ + +int toascii(int c) +{ + return __toascii(c); /* locale-independent */ +} + +#endif /* __UCLIBC_HAS_CTYPE_TABLES__ */ + +#endif +/**********************************************************************/ +/* glibc extensions */ +/**********************************************************************/ +#ifdef L_isctype + +int isctype(int c, int mask) +{ + CTYPE_BODY(NAME,c,mask) +} + +#endif +/**********************************************************************/ +#ifdef L___ctype_b_loc + +#ifdef __UCLIBC_HAS_XLOCALE__ + +const __ctype_mask_t **__ctype_b_loc(void) +{ + return &(__UCLIBC_CURLOCALE->__ctype_b); +} + +libc_hidden_def(__ctype_b_loc) +#endif + +#endif +/**********************************************************************/ +#ifdef L___ctype_tolower_loc + +#ifdef __UCLIBC_HAS_XLOCALE__ + +const __ctype_touplow_t **__ctype_tolower_loc(void) +{ + return &(__UCLIBC_CURLOCALE->__ctype_tolower); +} +libc_hidden_def(__ctype_tolower_loc) + +#endif + +#endif +/**********************************************************************/ +#ifdef L___ctype_toupper_loc + +#ifdef __UCLIBC_HAS_XLOCALE__ + +const __ctype_touplow_t **__ctype_toupper_loc(void) +{ + return &(__UCLIBC_CURLOCALE->__ctype_toupper); +} +libc_hidden_def(__ctype_toupper_loc) + +#endif + +#endif +/**********************************************************************/ +#ifdef L___C_ctype_b + +static const __ctype_mask_t __C_ctype_b_data[] = { +#ifdef __UCLIBC_HAS_CTYPE_SIGNED__ + /* -128 M-^@ */ 0, + /* -127 M-^A */ 0, + /* -126 M-^B */ 0, + /* -125 M-^C */ 0, + /* -124 M-^D */ 0, + /* -123 M-^E */ 0, + /* -122 M-^F */ 0, + /* -121 M-^G */ 0, + /* -120 M-^H */ 0, + /* -119 M-^I */ 0, + /* -118 M-^J */ 0, + /* -117 M-^K */ 0, + /* -116 M-^L */ 0, + /* -115 M-^M */ 0, + /* -114 M-^N */ 0, + /* -113 M-^O */ 0, + /* -112 M-^P */ 0, + /* -111 M-^Q */ 0, + /* -110 M-^R */ 0, + /* -109 M-^S */ 0, + /* -108 M-^T */ 0, + /* -107 M-^U */ 0, + /* -106 M-^V */ 0, + /* -105 M-^W */ 0, + /* -104 M-^X */ 0, + /* -103 M-^Y */ 0, + /* -102 M-^Z */ 0, + /* -101 M-^[ */ 0, + /* -100 M-^\ */ 0, + /* -99 M-^] */ 0, + /* -98 M-^^ */ 0, + /* -97 M-^_ */ 0, + /* -96 M- */ 0, + /* -95 M-! */ 0, + /* -94 M-" */ 0, + /* -93 M-# */ 0, + /* -92 M-$ */ 0, + /* -91 M-% */ 0, + /* -90 M-& */ 0, + /* -89 M-' */ 0, + /* -88 M-( */ 0, + /* -87 M-) */ 0, + /* -86 M-* */ 0, + /* -85 M-+ */ 0, + /* -84 M-, */ 0, + /* -83 M-- */ 0, + /* -82 M-. */ 0, + /* -81 M-/ */ 0, + /* -80 M-0 */ 0, + /* -79 M-1 */ 0, + /* -78 M-2 */ 0, + /* -77 M-3 */ 0, + /* -76 M-4 */ 0, + /* -75 M-5 */ 0, + /* -74 M-6 */ 0, + /* -73 M-7 */ 0, + /* -72 M-8 */ 0, + /* -71 M-9 */ 0, + /* -70 M-: */ 0, + /* -69 M-; */ 0, + /* -68 M-< */ 0, + /* -67 M-= */ 0, + /* -66 M-> */ 0, + /* -65 M-? */ 0, + /* -64 M-@ */ 0, + /* -63 M-A */ 0, + /* -62 M-B */ 0, + /* -61 M-C */ 0, + /* -60 M-D */ 0, + /* -59 M-E */ 0, + /* -58 M-F */ 0, + /* -57 M-G */ 0, + /* -56 M-H */ 0, + /* -55 M-I */ 0, + /* -54 M-J */ 0, + /* -53 M-K */ 0, + /* -52 M-L */ 0, + /* -51 M-M */ 0, + /* -50 M-N */ 0, + /* -49 M-O */ 0, + /* -48 M-P */ 0, + /* -47 M-Q */ 0, + /* -46 M-R */ 0, + /* -45 M-S */ 0, + /* -44 M-T */ 0, + /* -43 M-U */ 0, + /* -42 M-V */ 0, + /* -41 M-W */ 0, + /* -40 M-X */ 0, + /* -39 M-Y */ 0, + /* -38 M-Z */ 0, + /* -37 M-[ */ 0, + /* -36 M-\ */ 0, + /* -35 M-] */ 0, + /* -34 M-^ */ 0, + /* -33 M-_ */ 0, + /* -32 M-` */ 0, + /* -31 M-a */ 0, + /* -30 M-b */ 0, + /* -29 M-c */ 0, + /* -28 M-d */ 0, + /* -27 M-e */ 0, + /* -26 M-f */ 0, + /* -25 M-g */ 0, + /* -24 M-h */ 0, + /* -23 M-i */ 0, + /* -22 M-j */ 0, + /* -21 M-k */ 0, + /* -20 M-l */ 0, + /* -19 M-m */ 0, + /* -18 M-n */ 0, + /* -17 M-o */ 0, + /* -16 M-p */ 0, + /* -15 M-q */ 0, + /* -14 M-r */ 0, + /* -13 M-s */ 0, + /* -12 M-t */ 0, + /* -11 M-u */ 0, + /* -10 M-v */ 0, + /* -9 M-w */ 0, + /* -8 M-x */ 0, + /* -7 M-y */ 0, + /* -6 M-z */ 0, + /* -5 M-{ */ 0, + /* -4 M-| */ 0, + /* -3 M-} */ 0, + /* -2 M-~ */ 0, +#endif /* __UCLIBC_HAS_CTYPE_SIGNED__*/ + /* -1 M-^? */ 0, + /* 0 ^@ */ _IScntrl, + /* 1 ^A */ _IScntrl, + /* 2 ^B */ _IScntrl, + /* 3 ^C */ _IScntrl, + /* 4 ^D */ _IScntrl, + /* 5 ^E */ _IScntrl, + /* 6 ^F */ _IScntrl, + /* 7 ^G */ _IScntrl, + /* 8 ^H */ _IScntrl, + /* 9 ^I */ _ISspace|_ISblank|_IScntrl, + /* 10 ^J */ _ISspace|_IScntrl, + /* 11 ^K */ _ISspace|_IScntrl, + /* 12 ^L */ _ISspace|_IScntrl, + /* 13 ^M */ _ISspace|_IScntrl, + /* 14 ^N */ _IScntrl, + /* 15 ^O */ _IScntrl, + /* 16 ^P */ _IScntrl, + /* 17 ^Q */ _IScntrl, + /* 18 ^R */ _IScntrl, + /* 19 ^S */ _IScntrl, + /* 20 ^T */ _IScntrl, + /* 21 ^U */ _IScntrl, + /* 22 ^V */ _IScntrl, + /* 23 ^W */ _IScntrl, + /* 24 ^X */ _IScntrl, + /* 25 ^Y */ _IScntrl, + /* 26 ^Z */ _IScntrl, + /* 27 ^[ */ _IScntrl, + /* 28 ^\ */ _IScntrl, + /* 29 ^] */ _IScntrl, + /* 30 ^^ */ _IScntrl, + /* 31 ^_ */ _IScntrl, + /* 32 */ _ISspace|_ISprint|_ISblank, + /* 33 ! */ _ISprint|_ISgraph|_ISpunct, + /* 34 " */ _ISprint|_ISgraph|_ISpunct, + /* 35 # */ _ISprint|_ISgraph|_ISpunct, + /* 36 $ */ _ISprint|_ISgraph|_ISpunct, + /* 37 % */ _ISprint|_ISgraph|_ISpunct, + /* 38 & */ _ISprint|_ISgraph|_ISpunct, + /* 39 ' */ _ISprint|_ISgraph|_ISpunct, + /* 40 ( */ _ISprint|_ISgraph|_ISpunct, + /* 41 ) */ _ISprint|_ISgraph|_ISpunct, + /* 42 * */ _ISprint|_ISgraph|_ISpunct, + /* 43 + */ _ISprint|_ISgraph|_ISpunct, + /* 44 , */ _ISprint|_ISgraph|_ISpunct, + /* 45 - */ _ISprint|_ISgraph|_ISpunct, + /* 46 . */ _ISprint|_ISgraph|_ISpunct, + /* 47 / */ _ISprint|_ISgraph|_ISpunct, + /* 48 0 */ _ISdigit|_ISxdigit|_ISprint|_ISgraph|_ISalnum, + /* 49 1 */ _ISdigit|_ISxdigit|_ISprint|_ISgraph|_ISalnum, + /* 50 2 */ _ISdigit|_ISxdigit|_ISprint|_ISgraph|_ISalnum, + /* 51 3 */ _ISdigit|_ISxdigit|_ISprint|_ISgraph|_ISalnum, + /* 52 4 */ _ISdigit|_ISxdigit|_ISprint|_ISgraph|_ISalnum, + /* 53 5 */ _ISdigit|_ISxdigit|_ISprint|_ISgraph|_ISalnum, + /* 54 6 */ _ISdigit|_ISxdigit|_ISprint|_ISgraph|_ISalnum, + /* 55 7 */ _ISdigit|_ISxdigit|_ISprint|_ISgraph|_ISalnum, + /* 56 8 */ _ISdigit|_ISxdigit|_ISprint|_ISgraph|_ISalnum, + /* 57 9 */ _ISdigit|_ISxdigit|_ISprint|_ISgraph|_ISalnum, + /* 58 : */ _ISprint|_ISgraph|_ISpunct, + /* 59 ; */ _ISprint|_ISgraph|_ISpunct, + /* 60 < */ _ISprint|_ISgraph|_ISpunct, + /* 61 = */ _ISprint|_ISgraph|_ISpunct, + /* 62 > */ _ISprint|_ISgraph|_ISpunct, + /* 63 ? */ _ISprint|_ISgraph|_ISpunct, + /* 64 @ */ _ISprint|_ISgraph|_ISpunct, + /* 65 A */ _ISupper|_ISalpha|_ISxdigit|_ISprint|_ISgraph|_ISalnum, + /* 66 B */ _ISupper|_ISalpha|_ISxdigit|_ISprint|_ISgraph|_ISalnum, + /* 67 C */ _ISupper|_ISalpha|_ISxdigit|_ISprint|_ISgraph|_ISalnum, + /* 68 D */ _ISupper|_ISalpha|_ISxdigit|_ISprint|_ISgraph|_ISalnum, + /* 69 E */ _ISupper|_ISalpha|_ISxdigit|_ISprint|_ISgraph|_ISalnum, + /* 70 F */ _ISupper|_ISalpha|_ISxdigit|_ISprint|_ISgraph|_ISalnum, + /* 71 G */ _ISupper|_ISalpha|_ISprint|_ISgraph|_ISalnum, + /* 72 H */ _ISupper|_ISalpha|_ISprint|_ISgraph|_ISalnum, + /* 73 I */ _ISupper|_ISalpha|_ISprint|_ISgraph|_ISalnum, + /* 74 J */ _ISupper|_ISalpha|_ISprint|_ISgraph|_ISalnum, + /* 75 K */ _ISupper|_ISalpha|_ISprint|_ISgraph|_ISalnum, + /* 76 L */ _ISupper|_ISalpha|_ISprint|_ISgraph|_ISalnum, + /* 77 M */ _ISupper|_ISalpha|_ISprint|_ISgraph|_ISalnum, + /* 78 N */ _ISupper|_ISalpha|_ISprint|_ISgraph|_ISalnum, + /* 79 O */ _ISupper|_ISalpha|_ISprint|_ISgraph|_ISalnum, + /* 80 P */ _ISupper|_ISalpha|_ISprint|_ISgraph|_ISalnum, + /* 81 Q */ _ISupper|_ISalpha|_ISprint|_ISgraph|_ISalnum, + /* 82 R */ _ISupper|_ISalpha|_ISprint|_ISgraph|_ISalnum, + /* 83 S */ _ISupper|_ISalpha|_ISprint|_ISgraph|_ISalnum, + /* 84 T */ _ISupper|_ISalpha|_ISprint|_ISgraph|_ISalnum, + /* 85 U */ _ISupper|_ISalpha|_ISprint|_ISgraph|_ISalnum, + /* 86 V */ _ISupper|_ISalpha|_ISprint|_ISgraph|_ISalnum, + /* 87 W */ _ISupper|_ISalpha|_ISprint|_ISgraph|_ISalnum, + /* 88 X */ _ISupper|_ISalpha|_ISprint|_ISgraph|_ISalnum, + /* 89 Y */ _ISupper|_ISalpha|_ISprint|_ISgraph|_ISalnum, + /* 90 Z */ _ISupper|_ISalpha|_ISprint|_ISgraph|_ISalnum, + /* 91 [ */ _ISprint|_ISgraph|_ISpunct, + /* 92 \ */ _ISprint|_ISgraph|_ISpunct, + /* 93 ] */ _ISprint|_ISgraph|_ISpunct, + /* 94 ^ */ _ISprint|_ISgraph|_ISpunct, + /* 95 _ */ _ISprint|_ISgraph|_ISpunct, + /* 96 ` */ _ISprint|_ISgraph|_ISpunct, + /* 97 a */ _ISlower|_ISalpha|_ISxdigit|_ISprint|_ISgraph|_ISalnum, + /* 98 b */ _ISlower|_ISalpha|_ISxdigit|_ISprint|_ISgraph|_ISalnum, + /* 99 c */ _ISlower|_ISalpha|_ISxdigit|_ISprint|_ISgraph|_ISalnum, + /* 100 d */ _ISlower|_ISalpha|_ISxdigit|_ISprint|_ISgraph|_ISalnum, + /* 101 e */ _ISlower|_ISalpha|_ISxdigit|_ISprint|_ISgraph|_ISalnum, + /* 102 f */ _ISlower|_ISalpha|_ISxdigit|_ISprint|_ISgraph|_ISalnum, + /* 103 g */ _ISlower|_ISalpha|_ISprint|_ISgraph|_ISalnum, + /* 104 h */ _ISlower|_ISalpha|_ISprint|_ISgraph|_ISalnum, + /* 105 i */ _ISlower|_ISalpha|_ISprint|_ISgraph|_ISalnum, + /* 106 j */ _ISlower|_ISalpha|_ISprint|_ISgraph|_ISalnum, + /* 107 k */ _ISlower|_ISalpha|_ISprint|_ISgraph|_ISalnum, + /* 108 l */ _ISlower|_ISalpha|_ISprint|_ISgraph|_ISalnum, + /* 109 m */ _ISlower|_ISalpha|_ISprint|_ISgraph|_ISalnum, + /* 110 n */ _ISlower|_ISalpha|_ISprint|_ISgraph|_ISalnum, + /* 111 o */ _ISlower|_ISalpha|_ISprint|_ISgraph|_ISalnum, + /* 112 p */ _ISlower|_ISalpha|_ISprint|_ISgraph|_ISalnum, + /* 113 q */ _ISlower|_ISalpha|_ISprint|_ISgraph|_ISalnum, + /* 114 r */ _ISlower|_ISalpha|_ISprint|_ISgraph|_ISalnum, + /* 115 s */ _ISlower|_ISalpha|_ISprint|_ISgraph|_ISalnum, + /* 116 t */ _ISlower|_ISalpha|_ISprint|_ISgraph|_ISalnum, + /* 117 u */ _ISlower|_ISalpha|_ISprint|_ISgraph|_ISalnum, + /* 118 v */ _ISlower|_ISalpha|_ISprint|_ISgraph|_ISalnum, + /* 119 w */ _ISlower|_ISalpha|_ISprint|_ISgraph|_ISalnum, + /* 120 x */ _ISlower|_ISalpha|_ISprint|_ISgraph|_ISalnum, + /* 121 y */ _ISlower|_ISalpha|_ISprint|_ISgraph|_ISalnum, + /* 122 z */ _ISlower|_ISalpha|_ISprint|_ISgraph|_ISalnum, + /* 123 { */ _ISprint|_ISgraph|_ISpunct, + /* 124 | */ _ISprint|_ISgraph|_ISpunct, + /* 125 } */ _ISprint|_ISgraph|_ISpunct, + /* 126 ~ */ _ISprint|_ISgraph|_ISpunct, + /* 127 ^? */ _IScntrl, + /* 128 M-^@ */ 0, + /* 129 M-^A */ 0, + /* 130 M-^B */ 0, + /* 131 M-^C */ 0, + /* 132 M-^D */ 0, + /* 133 M-^E */ 0, + /* 134 M-^F */ 0, + /* 135 M-^G */ 0, + /* 136 M-^H */ 0, + /* 137 M-^I */ 0, + /* 138 M-^J */ 0, + /* 139 M-^K */ 0, + /* 140 M-^L */ 0, + /* 141 M-^M */ 0, + /* 142 M-^N */ 0, + /* 143 M-^O */ 0, + /* 144 M-^P */ 0, + /* 145 M-^Q */ 0, + /* 146 M-^R */ 0, + /* 147 M-^S */ 0, + /* 148 M-^T */ 0, + /* 149 M-^U */ 0, + /* 150 M-^V */ 0, + /* 151 M-^W */ 0, + /* 152 M-^X */ 0, + /* 153 M-^Y */ 0, + /* 154 M-^Z */ 0, + /* 155 M-^[ */ 0, + /* 156 M-^\ */ 0, + /* 157 M-^] */ 0, + /* 158 M-^^ */ 0, + /* 159 M-^_ */ 0, + /* 160 M- */ 0, + /* 161 M-! */ 0, + /* 162 M-" */ 0, + /* 163 M-# */ 0, + /* 164 M-$ */ 0, + /* 165 M-% */ 0, + /* 166 M-& */ 0, + /* 167 M-' */ 0, + /* 168 M-( */ 0, + /* 169 M-) */ 0, + /* 170 M-* */ 0, + /* 171 M-+ */ 0, + /* 172 M-, */ 0, + /* 173 M-- */ 0, + /* 174 M-. */ 0, + /* 175 M-/ */ 0, + /* 176 M-0 */ 0, + /* 177 M-1 */ 0, + /* 178 M-2 */ 0, + /* 179 M-3 */ 0, + /* 180 M-4 */ 0, + /* 181 M-5 */ 0, + /* 182 M-6 */ 0, + /* 183 M-7 */ 0, + /* 184 M-8 */ 0, + /* 185 M-9 */ 0, + /* 186 M-: */ 0, + /* 187 M-; */ 0, + /* 188 M-< */ 0, + /* 189 M-= */ 0, + /* 190 M-> */ 0, + /* 191 M-? */ 0, + /* 192 M-@ */ 0, + /* 193 M-A */ 0, + /* 194 M-B */ 0, + /* 195 M-C */ 0, + /* 196 M-D */ 0, + /* 197 M-E */ 0, + /* 198 M-F */ 0, + /* 199 M-G */ 0, + /* 200 M-H */ 0, + /* 201 M-I */ 0, + /* 202 M-J */ 0, + /* 203 M-K */ 0, + /* 204 M-L */ 0, + /* 205 M-M */ 0, + /* 206 M-N */ 0, + /* 207 M-O */ 0, + /* 208 M-P */ 0, + /* 209 M-Q */ 0, + /* 210 M-R */ 0, + /* 211 M-S */ 0, + /* 212 M-T */ 0, + /* 213 M-U */ 0, + /* 214 M-V */ 0, + /* 215 M-W */ 0, + /* 216 M-X */ 0, + /* 217 M-Y */ 0, + /* 218 M-Z */ 0, + /* 219 M-[ */ 0, + /* 220 M-\ */ 0, + /* 221 M-] */ 0, + /* 222 M-^ */ 0, + /* 223 M-_ */ 0, + /* 224 M-` */ 0, + /* 225 M-a */ 0, + /* 226 M-b */ 0, + /* 227 M-c */ 0, + /* 228 M-d */ 0, + /* 229 M-e */ 0, + /* 230 M-f */ 0, + /* 231 M-g */ 0, + /* 232 M-h */ 0, + /* 233 M-i */ 0, + /* 234 M-j */ 0, + /* 235 M-k */ 0, + /* 236 M-l */ 0, + /* 237 M-m */ 0, + /* 238 M-n */ 0, + /* 239 M-o */ 0, + /* 240 M-p */ 0, + /* 241 M-q */ 0, + /* 242 M-r */ 0, + /* 243 M-s */ 0, + /* 244 M-t */ 0, + /* 245 M-u */ 0, + /* 246 M-v */ 0, + /* 247 M-w */ 0, + /* 248 M-x */ 0, + /* 249 M-y */ 0, + /* 250 M-z */ 0, + /* 251 M-{ */ 0, + /* 252 M-| */ 0, + /* 253 M-} */ 0, + /* 254 M-~ */ 0, + /* 255 M-^? */ 0 +}; + +const __ctype_mask_t *__C_ctype_b = __C_ctype_b_data + __UCLIBC_CTYPE_B_TBL_OFFSET; +libc_hidden_data_def(__C_ctype_b) + +#ifndef __UCLIBC_HAS_XLOCALE__ + +const __ctype_mask_t *__ctype_b = __C_ctype_b_data + __UCLIBC_CTYPE_B_TBL_OFFSET; +libc_hidden_data_def(__ctype_b) + +#endif + +#endif +/**********************************************************************/ +#ifdef L___C_ctype_tolower + +static const __ctype_touplow_t __C_ctype_tolower_data[] = { +#ifdef __UCLIBC_HAS_CTYPE_SIGNED__ + -128, -127, -126, -125, + -124, -123, -122, -121, + -120, -119, -118, -117, + -116, -115, -114, -113, + -112, -111, -110, -109, + -108, -107, -106, -105, + -104, -103, -102, -101, + -100, -99, -98, -97, + -96, -95, -94, -93, + -92, -91, -90, -89, + -88, -87, -86, -85, + -84, -83, -82, -81, + -80, -79, -78, -77, + -76, -75, -74, -73, + -72, -71, -70, -69, + -68, -67, -66, -65, + -64, -63, -62, -61, + -60, -59, -58, -57, + -56, -55, -54, -53, + -52, -51, -50, -49, + -48, -47, -46, -45, + -44, -43, -42, -41, + -40, -39, -38, -37, + -36, -35, -34, -33, + -32, -31, -30, -29, + -28, -27, -26, -25, + -24, -23, -22, -21, + -20, -19, -18, -17, + -16, -15, -14, -13, + -12, -11, -10, -9, + -8, -7, -6, -5, + -4, -3, -2, -1, +#endif /* __UCLIBC_HAS_CTYPE_SIGNED__*/ + 0, 1, 2, 3, + 4, 5, 6, 7, + 8, 9, 10, 11, + 12, 13, 14, 15, + 16, 17, 18, 19, + 20, 21, 22, 23, + 24, 25, 26, 27, + 28, 29, 30, 31, + 32, 33, 34, 35, + 36, 37, 38, 39, + 40, 41, 42, 43, + 44, 45, 46, 47, + 48, 49, 50, 51, + 52, 53, 54, 55, + 56, 57, 58, 59, + 60, 61, 62, 63, + 64, 97 /* a */, 98 /* b */, 99 /* c */, + 100 /* d */, 101 /* e */, 102 /* f */, 103 /* g */, + 104 /* h */, 105 /* i */, 106 /* j */, 107 /* k */, + 108 /* l */, 109 /* m */, 110 /* n */, 111 /* o */, + 112 /* p */, 113 /* q */, 114 /* r */, 115 /* s */, + 116 /* t */, 117 /* u */, 118 /* v */, 119 /* w */, + 120 /* x */, 121 /* y */, 122 /* z */, 91, + 92, 93, 94, 95, + 96, 97, 98, 99, + 100, 101, 102, 103, + 104, 105, 106, 107, + 108, 109, 110, 111, + 112, 113, 114, 115, + 116, 117, 118, 119, + 120, 121, 122, 123, + 124, 125, 126, 127, + 128, 129, 130, 131, + 132, 133, 134, 135, + 136, 137, 138, 139, + 140, 141, 142, 143, + 144, 145, 146, 147, + 148, 149, 150, 151, + 152, 153, 154, 155, + 156, 157, 158, 159, + 160, 161, 162, 163, + 164, 165, 166, 167, + 168, 169, 170, 171, + 172, 173, 174, 175, + 176, 177, 178, 179, + 180, 181, 182, 183, + 184, 185, 186, 187, + 188, 189, 190, 191, + 192, 193, 194, 195, + 196, 197, 198, 199, + 200, 201, 202, 203, + 204, 205, 206, 207, + 208, 209, 210, 211, + 212, 213, 214, 215, + 216, 217, 218, 219, + 220, 221, 222, 223, + 224, 225, 226, 227, + 228, 229, 230, 231, + 232, 233, 234, 235, + 236, 237, 238, 239, + 240, 241, 242, 243, + 244, 245, 246, 247, + 248, 249, 250, 251, + 252, 253, 254, 255 +}; + +const __ctype_touplow_t *__C_ctype_tolower = + __C_ctype_tolower_data + __UCLIBC_CTYPE_TO_TBL_OFFSET; +libc_hidden_data_def(__C_ctype_tolower) + +#ifndef __UCLIBC_HAS_XLOCALE__ + +const __ctype_touplow_t *__ctype_tolower = + __C_ctype_tolower_data + __UCLIBC_CTYPE_TO_TBL_OFFSET; +libc_hidden_data_def(__ctype_tolower) + +#endif + +#endif +/**********************************************************************/ +#ifdef L___C_ctype_toupper + +static const __ctype_touplow_t __C_ctype_toupper_data[] = { +#ifdef __UCLIBC_HAS_CTYPE_SIGNED__ + -128, -127, -126, -125, + -124, -123, -122, -121, + -120, -119, -118, -117, + -116, -115, -114, -113, + -112, -111, -110, -109, + -108, -107, -106, -105, + -104, -103, -102, -101, + -100, -99, -98, -97, + -96, -95, -94, -93, + -92, -91, -90, -89, + -88, -87, -86, -85, + -84, -83, -82, -81, + -80, -79, -78, -77, + -76, -75, -74, -73, + -72, -71, -70, -69, + -68, -67, -66, -65, + -64, -63, -62, -61, + -60, -59, -58, -57, + -56, -55, -54, -53, + -52, -51, -50, -49, + -48, -47, -46, -45, + -44, -43, -42, -41, + -40, -39, -38, -37, + -36, -35, -34, -33, + -32, -31, -30, -29, + -28, -27, -26, -25, + -24, -23, -22, -21, + -20, -19, -18, -17, + -16, -15, -14, -13, + -12, -11, -10, -9, + -8, -7, -6, -5, + -4, -3, -2, -1, +#endif /* __UCLIBC_HAS_CTYPE_SIGNED__*/ + 0, 1, 2, 3, + 4, 5, 6, 7, + 8, 9, 10, 11, + 12, 13, 14, 15, + 16, 17, 18, 19, + 20, 21, 22, 23, + 24, 25, 26, 27, + 28, 29, 30, 31, + 32, 33, 34, 35, + 36, 37, 38, 39, + 40, 41, 42, 43, + 44, 45, 46, 47, + 48, 49, 50, 51, + 52, 53, 54, 55, + 56, 57, 58, 59, + 60, 61, 62, 63, + 64, 65, 66, 67, + 68, 69, 70, 71, + 72, 73, 74, 75, + 76, 77, 78, 79, + 80, 81, 82, 83, + 84, 85, 86, 87, + 88, 89, 90, 91, + 92, 93, 94, 95, + 96, 65 /* A */, 66 /* B */, 67 /* C */, + 68 /* D */, 69 /* E */, 70 /* F */, 71 /* G */, + 72 /* H */, 73 /* I */, 74 /* J */, 75 /* K */, + 76 /* L */, 77 /* M */, 78 /* N */, 79 /* O */, + 80 /* P */, 81 /* Q */, 82 /* R */, 83 /* S */, + 84 /* T */, 85 /* U */, 86 /* V */, 87 /* W */, + 88 /* X */, 89 /* Y */, 90 /* Z */, 123, + 124, 125, 126, 127, + 128, 129, 130, 131, + 132, 133, 134, 135, + 136, 137, 138, 139, + 140, 141, 142, 143, + 144, 145, 146, 147, + 148, 149, 150, 151, + 152, 153, 154, 155, + 156, 157, 158, 159, + 160, 161, 162, 163, + 164, 165, 166, 167, + 168, 169, 170, 171, + 172, 173, 174, 175, + 176, 177, 178, 179, + 180, 181, 182, 183, + 184, 185, 186, 187, + 188, 189, 190, 191, + 192, 193, 194, 195, + 196, 197, 198, 199, + 200, 201, 202, 203, + 204, 205, 206, 207, + 208, 209, 210, 211, + 212, 213, 214, 215, + 216, 217, 218, 219, + 220, 221, 222, 223, + 224, 225, 226, 227, + 228, 229, 230, 231, + 232, 233, 234, 235, + 236, 237, 238, 239, + 240, 241, 242, 243, + 244, 245, 246, 247, + 248, 249, 250, 251, + 252, 253, 254, 255 +}; + +const __ctype_touplow_t *__C_ctype_toupper = + __C_ctype_toupper_data + __UCLIBC_CTYPE_TO_TBL_OFFSET; +libc_hidden_data_def(__C_ctype_toupper) + +#ifndef __UCLIBC_HAS_XLOCALE__ + +const __ctype_touplow_t *__ctype_toupper = + __C_ctype_toupper_data + __UCLIBC_CTYPE_TO_TBL_OFFSET; +libc_hidden_data_def(__ctype_toupper) + +#endif + +#endif +/**********************************************************************/ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/isalnum.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/isalnum.c new file mode 100644 index 00000000..8bc8ad6d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/isalnum.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2003-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_isalnum +#include "ctype.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/isalnum_l.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/isalnum_l.c new file mode 100644 index 00000000..8ecd9d59 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/isalnum_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2003-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_isalnum_l +#define __UCLIBC_DO_XLOCALE +#include "ctype.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/isalpha.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/isalpha.c new file mode 100644 index 00000000..22f23d92 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/isalpha.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2003-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_isalpha +#include "ctype.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/isalpha_l.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/isalpha_l.c new file mode 100644 index 00000000..10a2ecfc --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/isalpha_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2003-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_isalpha_l +#define __UCLIBC_DO_XLOCALE +#include "ctype.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/isascii.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/isascii.c new file mode 100644 index 00000000..84f701f8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/isascii.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2003-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_isascii +#include "ctype.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/isascii_l.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/isascii_l.c new file mode 100644 index 00000000..7fe5545b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/isascii_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2003-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_isascii_l +#define __UCLIBC_DO_XLOCALE +#include "ctype.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/isblank.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/isblank.c new file mode 100644 index 00000000..d11fe26c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/isblank.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2003-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_isblank +#include "ctype.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/isblank_l.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/isblank_l.c new file mode 100644 index 00000000..144cd932 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/isblank_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2003-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_isblank_l +#define __UCLIBC_DO_XLOCALE +#include "ctype.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/iscntrl.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/iscntrl.c new file mode 100644 index 00000000..4a0c09d3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/iscntrl.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2003-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_iscntrl +#include "ctype.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/iscntrl_l.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/iscntrl_l.c new file mode 100644 index 00000000..fbee951c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/iscntrl_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2003-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_iscntrl_l +#define __UCLIBC_DO_XLOCALE +#include "ctype.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/isctype.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/isctype.c new file mode 100644 index 00000000..a2d0b3dd --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/isctype.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2003-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_isctype +#include "ctype.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/isdigit.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/isdigit.c new file mode 100644 index 00000000..e185c89d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/isdigit.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2003-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_isdigit +#include "ctype.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/isdigit_l.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/isdigit_l.c new file mode 100644 index 00000000..5b764f12 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/isdigit_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2003-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_isdigit_l +#define __UCLIBC_DO_XLOCALE +#include "ctype.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/isgraph.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/isgraph.c new file mode 100644 index 00000000..c4ad1b7b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/isgraph.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2003-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_isgraph +#include "ctype.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/isgraph_l.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/isgraph_l.c new file mode 100644 index 00000000..005e19fc --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/isgraph_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2003-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_isgraph_l +#define __UCLIBC_DO_XLOCALE +#include "ctype.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/islower.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/islower.c new file mode 100644 index 00000000..aff65dd9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/islower.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2003-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_islower +#include "ctype.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/islower_l.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/islower_l.c new file mode 100644 index 00000000..dd085578 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/islower_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2003-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_islower_l +#define __UCLIBC_DO_XLOCALE +#include "ctype.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/isprint.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/isprint.c new file mode 100644 index 00000000..b6f7d6cc --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/isprint.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2003-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_isprint +#include "ctype.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/isprint_l.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/isprint_l.c new file mode 100644 index 00000000..32f9b3f3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/isprint_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2003-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_isprint_l +#define __UCLIBC_DO_XLOCALE +#include "ctype.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/ispunct.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/ispunct.c new file mode 100644 index 00000000..08f7b19a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/ispunct.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2003-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_ispunct +#include "ctype.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/ispunct_l.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/ispunct_l.c new file mode 100644 index 00000000..513bb523 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/ispunct_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2003-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_ispunct_l +#define __UCLIBC_DO_XLOCALE +#include "ctype.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/isspace.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/isspace.c new file mode 100644 index 00000000..c8ff5674 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/isspace.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2003-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_isspace +#include "ctype.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/isspace_l.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/isspace_l.c new file mode 100644 index 00000000..97e0c992 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/isspace_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2003-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_isspace_l +#define __UCLIBC_DO_XLOCALE +#include "ctype.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/isupper.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/isupper.c new file mode 100644 index 00000000..36d6e6e9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/isupper.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2003-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_isupper +#include "ctype.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/isupper_l.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/isupper_l.c new file mode 100644 index 00000000..8aa4dbdf --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/isupper_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2003-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_isupper_l +#define __UCLIBC_DO_XLOCALE +#include "ctype.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/isxdigit.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/isxdigit.c new file mode 100644 index 00000000..40919f7b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/isxdigit.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2003-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_isxdigit +#include "ctype.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/isxdigit_l.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/isxdigit_l.c new file mode 100644 index 00000000..5dce7f1a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/isxdigit_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2003-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_isxdigit_l +#define __UCLIBC_DO_XLOCALE +#include "ctype.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/toascii.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/toascii.c new file mode 100644 index 00000000..a63b9934 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/toascii.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2003-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_toascii +#include "ctype.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/toascii_l.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/toascii_l.c new file mode 100644 index 00000000..61795263 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/toascii_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2003-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_toascii_l +#define __UCLIBC_DO_XLOCALE +#include "ctype.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/tolower.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/tolower.c new file mode 100644 index 00000000..3673642c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/tolower.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2003-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_tolower +#include "ctype.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/tolower_l.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/tolower_l.c new file mode 100644 index 00000000..327e63ca --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/tolower_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2003-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_tolower_l +#define __UCLIBC_DO_XLOCALE +#include "ctype.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/toupper.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/toupper.c new file mode 100644 index 00000000..a9d8aab6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/toupper.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2003-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_toupper +#include "ctype.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/toupper_l.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/toupper_l.c new file mode 100644 index 00000000..c91d7915 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ctype/toupper_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2003-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_toupper_l +#define __UCLIBC_DO_XLOCALE +#include "ctype.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/dirent/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/dirent/Makefile new file mode 100644 index 00000000..4a8f4a07 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/dirent/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../ +top_builddir=../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/dirent/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/dirent/Makefile.in new file mode 100644 index 00000000..d42dfeb1 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/dirent/Makefile.in @@ -0,0 +1,28 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +subdirs += libc/misc/dirent + +CSRC := alphasort.c closedir.c dirfd.c opendir.c readdir.c rewinddir.c \ + scandir.c seekdir.c telldir.c readdir_r.c versionsort.c + +ifeq ($(UCLIBC_HAS_LFS),y) +CSRC += readdir64.c alphasort64.c scandir64.c readdir64_r.c versionsort64.c +endif + +MISC_DIRENT_DIR := $(top_srcdir)libc/misc/dirent +MISC_DIRENT_OUT := $(top_builddir)libc/misc/dirent + +MISC_DIRENT_SRC := $(patsubst %.c,$(MISC_DIRENT_DIR)/%.c,$(CSRC)) +MISC_DIRENT_OBJ := $(patsubst %.c,$(MISC_DIRENT_OUT)/%.o,$(CSRC)) + +libc-y += $(MISC_DIRENT_OBJ) + +objclean-y += CLEAN_libc/misc/dirent + +CLEAN_libc/misc/dirent: + $(do_rm) $(addprefix $(MISC_DIRENT_OUT)/*., o os) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/dirent/alphasort.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/dirent/alphasort.c new file mode 100644 index 00000000..eb0dbf23 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/dirent/alphasort.c @@ -0,0 +1,15 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include "dirstream.h" + +int alphasort(const struct dirent **a, const struct dirent **b) +{ + return strcmp((*a)->d_name, (*b)->d_name); +} + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/dirent/alphasort64.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/dirent/alphasort64.c new file mode 100644 index 00000000..d65b5964 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/dirent/alphasort64.c @@ -0,0 +1,16 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include <_lfs_64.h> + +#include +#include +#include "dirstream.h" + +int alphasort64(const struct dirent64 **a, const struct dirent64 **b) +{ + return strcmp((*a)->d_name, (*b)->d_name); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/dirent/closedir.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/dirent/closedir.c new file mode 100644 index 00000000..dfb53f88 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/dirent/closedir.c @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include +#include "dirstream.h" +#include + + +int closedir(DIR * dir) +{ + int fd; + + if (!dir) { + __set_errno(EBADF); + return -1; + } + + /* We need to check dd_fd. */ + if (dir->dd_fd == -1) { + __set_errno(EBADF); + return -1; + } + __UCLIBC_MUTEX_LOCK(dir->dd_lock); + fd = dir->dd_fd; + dir->dd_fd = -1; + __UCLIBC_MUTEX_UNLOCK(dir->dd_lock); + free(dir->dd_buf); + free(dir); + return close_not_cancel(fd); +} +libc_hidden_def(closedir) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/dirent/dirfd.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/dirent/dirfd.c new file mode 100644 index 00000000..649dd4ad --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/dirent/dirfd.c @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include "dirstream.h" + + +int dirfd(DIR * dir) +{ + if (!dir || dir->dd_fd == -1) { + __set_errno(EBADF); + return -1; + } + + return dir->dd_fd; +} +libc_hidden_def(dirfd) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/dirent/dirstream.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/dirent/dirstream.h new file mode 100644 index 00000000..370886aa --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/dirent/dirstream.h @@ -0,0 +1,74 @@ +/* Copyright (C) 1991, 1992 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the, 1992 Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +/* + * POSIX Standard: 5.1.2 Directory Operations + */ + +#ifndef _DIRSTREAM_H + +#define _DIRSTREAM_H 1 + +#include +#include + +#include + +/* For now, syscall readdir () only supports one entry at a time. It + * will be changed in the future. +#define NUMENT 3 +*/ +#ifndef NUMENT +#define NUMENT 1 +#endif + +#define SINGLE_READDIR 11 +#define MULTI_READDIR 12 +#define NEW_READDIR 13 + +/* Directory stream type. */ +struct __dirstream { + /* file descriptor */ + int dd_fd; + + /* offset of the next dir entry in buffer */ + size_t dd_nextloc; + + /* bytes of valid entries in buffer */ + size_t dd_size; + + /* -> directory buffer */ + void *dd_buf; + + /* offset of the next dir entry in directory. */ + off_t dd_nextoff; + + /* total size of buffer */ + size_t dd_max; + + /* lock */ + __UCLIBC_MUTEX(dd_lock); +}; /* stream data from opendir() */ + + +extern ssize_t __getdents(int fd, char *buf, size_t count) attribute_hidden; +#ifdef __UCLIBC_HAS_LFS__ +extern ssize_t __getdents64 (int fd, char *buf, size_t count) attribute_hidden; +#endif + +#endif /* dirent.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/dirent/opendir.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/dirent/opendir.c new file mode 100644 index 00000000..66a5cc9e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/dirent/opendir.c @@ -0,0 +1,117 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "dirstream.h" + +static DIR *fd_to_DIR(int fd, __blksize_t size) +{ + DIR *ptr; + + ptr = malloc(sizeof(*ptr)); + if (!ptr) + return NULL; + + ptr->dd_fd = fd; + ptr->dd_nextloc = ptr->dd_size = ptr->dd_nextoff = 0; + ptr->dd_max = size; + if (ptr->dd_max < 512) + ptr->dd_max = 512; + + ptr->dd_buf = calloc(1, ptr->dd_max); + if (!ptr->dd_buf) { + free(ptr); + return NULL; + } + __UCLIBC_MUTEX_INIT_VAR(ptr->dd_lock); + + return ptr; +} + +DIR *fdopendir(int fd) +{ + int flags; + struct stat st; + + if (fstat(fd, &st)) + return NULL; + if (!S_ISDIR(st.st_mode)) { + __set_errno(ENOTDIR); + return NULL; + } + + flags = fcntl(fd, F_GETFL); + if (flags == -1) + return NULL; + if ((flags & O_ACCMODE) == O_WRONLY) { + __set_errno(EINVAL); + return NULL; + } + + return fd_to_DIR(fd, st.st_blksize); +} + +/* opendir just makes an open() call - it return NULL if it fails + * (open sets errno), otherwise it returns a DIR * pointer. + */ +DIR *opendir(const char *name) +{ + int fd; + struct stat statbuf; + DIR *ptr; + +#ifndef O_DIRECTORY + /* O_DIRECTORY is linux specific and has been around since like 2.1.x */ + if (stat(name, &statbuf)) + return NULL; + if (!S_ISDIR(statbuf.st_mode)) { + __set_errno(ENOTDIR); + return NULL; + } +# define O_DIRECTORY 0 +#endif + fd = open_not_cancel_2(name, O_RDONLY|O_NDELAY|O_DIRECTORY|O_CLOEXEC); + if (fd < 0) + return NULL; + /* Note: we should check to make sure that between the stat() and open() + * call, 'name' didnt change on us, but that's only if O_DIRECTORY isnt + * defined and since Linux has supported it for like ever, i'm not going + * to worry about it right now (if ever). */ + + if (fstat(fd, &statbuf) < 0) { + /* this close() never fails + *int saved_errno; + *saved_errno = errno; */ + close_not_cancel_no_status(fd); + /*__set_errno(saved_errno);*/ + return NULL; + } + + /* According to POSIX, directory streams should be closed when + * exec. From "Anna Pluzhnikov" . + */ +#ifndef __ASSUME_O_CLOEXEC + fcntl_not_cancel(fd, F_SETFD, FD_CLOEXEC); +#endif + + ptr = fd_to_DIR(fd, statbuf.st_blksize); + + if (!ptr) { + close_not_cancel_no_status(fd); + __set_errno(ENOMEM); + } + return ptr; +} +libc_hidden_def(opendir) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/dirent/readdir.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/dirent/readdir.c new file mode 100644 index 00000000..4fcd1cc7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/dirent/readdir.c @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +#include +#include +#include +#include +#include +#include "dirstream.h" + + +struct dirent *readdir(DIR * dir) +{ + ssize_t bytes; + struct dirent *de; + + if (!dir) { + __set_errno(EBADF); + return NULL; + } + + __UCLIBC_MUTEX_LOCK(dir->dd_lock); + + do { + if (dir->dd_size <= dir->dd_nextloc) { + /* read dir->dd_max bytes of directory entries. */ + bytes = __getdents(dir->dd_fd, dir->dd_buf, dir->dd_max); + if (bytes <= 0) { + de = NULL; + goto all_done; + } + dir->dd_size = bytes; + dir->dd_nextloc = 0; + } + + de = (struct dirent *) (((char *) dir->dd_buf) + dir->dd_nextloc); + + /* Am I right? H.J. */ + dir->dd_nextloc += de->d_reclen; + + /* We have to save the next offset here. */ + dir->dd_nextoff = de->d_off; + + /* Skip deleted files. */ + } while (de->d_ino == 0); + +all_done: + __UCLIBC_MUTEX_UNLOCK(dir->dd_lock); + return de; +} +libc_hidden_def(readdir) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/dirent/readdir64.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/dirent/readdir64.c new file mode 100644 index 00000000..1264c38b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/dirent/readdir64.c @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include <_lfs_64.h> + +#include +#include +#include +#include +#include +#include "dirstream.h" + +struct dirent64 *readdir64(DIR * dir) +{ + ssize_t bytes; + struct dirent64 *de; + + if (!dir) { + __set_errno(EBADF); + return NULL; + } + + __UCLIBC_MUTEX_LOCK(dir->dd_lock); + + do { + if (dir->dd_size <= dir->dd_nextloc) { + /* read dir->dd_max bytes of directory entries. */ + bytes = __getdents64(dir->dd_fd, dir->dd_buf, dir->dd_max); + if (bytes <= 0) { + de = NULL; + goto all_done; + } + dir->dd_size = bytes; + dir->dd_nextloc = 0; + } + + de = (struct dirent64 *) (((char *) dir->dd_buf) + dir->dd_nextloc); + + /* Am I right? H.J. */ + dir->dd_nextloc += de->d_reclen; + + /* We have to save the next offset here. */ + dir->dd_nextoff = de->d_off; + + /* Skip deleted files. */ + } while (de->d_ino == 0); + +all_done: + __UCLIBC_MUTEX_UNLOCK(dir->dd_lock); + + return de; +} +libc_hidden_def(readdir64) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/dirent/readdir64_r.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/dirent/readdir64_r.c new file mode 100644 index 00000000..ba726003 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/dirent/readdir64_r.c @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include <_lfs_64.h> + +#include +#include +#include +#include +#include +#include "dirstream.h" + + +int readdir64_r(DIR *dir, struct dirent64 *entry, struct dirent64 **result) +{ + int ret; + ssize_t bytes; + struct dirent64 *de; + + if (!dir) { + __set_errno(EBADF); + return(EBADF); + } + de = NULL; + + __UCLIBC_MUTEX_LOCK(dir->dd_lock); + + do { + if (dir->dd_size <= dir->dd_nextloc) { + /* read dir->dd_max bytes of directory entries. */ + bytes = __getdents64(dir->dd_fd, dir->dd_buf, dir->dd_max); + if (bytes <= 0) { + *result = NULL; + ret = (bytes==0)? 0 : errno; + goto all_done; + } + dir->dd_size = bytes; + dir->dd_nextloc = 0; + } + + de = (struct dirent64 *) (((char *) dir->dd_buf) + dir->dd_nextloc); + + /* Am I right? H.J. */ + dir->dd_nextloc += de->d_reclen; + + /* We have to save the next offset here. */ + dir->dd_nextoff = de->d_off; + /* Skip deleted files. */ + } while (de->d_ino == 0); + + if (de == NULL) { + *result = NULL; + } else { + *result = memcpy (entry, de, de->d_reclen); + } + ret = 0; + +all_done: + + __UCLIBC_MUTEX_UNLOCK(dir->dd_lock); + return((de != NULL)? 0 : ret); +} +libc_hidden_def(readdir64_r) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/dirent/readdir_r.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/dirent/readdir_r.c new file mode 100644 index 00000000..d08997ff --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/dirent/readdir_r.c @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include +#include +#include "dirstream.h" + + +int readdir_r(DIR *dir, struct dirent *entry, struct dirent **result) +{ + int ret; + ssize_t bytes; + struct dirent *de; + + if (!dir) { + __set_errno(EBADF); + return(EBADF); + } + de = NULL; + + __UCLIBC_MUTEX_LOCK(dir->dd_lock); + + do { + if (dir->dd_size <= dir->dd_nextloc) { + /* read dir->dd_max bytes of directory entries. */ + bytes = __getdents(dir->dd_fd, dir->dd_buf, dir->dd_max); + if (bytes <= 0) { + *result = NULL; + ret = (bytes==0)? 0 : errno; + goto all_done; + } + dir->dd_size = bytes; + dir->dd_nextloc = 0; + } + + de = (struct dirent *) (((char *) dir->dd_buf) + dir->dd_nextloc); + + /* Am I right? H.J. */ + dir->dd_nextloc += de->d_reclen; + + /* We have to save the next offset here. */ + dir->dd_nextoff = de->d_off; + /* Skip deleted files. */ + } while (de->d_ino == 0); + + if (de == NULL) { + *result = NULL; + } else { + *result = memcpy (entry, de, de->d_reclen); + } + ret = 0; + +all_done: + + __UCLIBC_MUTEX_UNLOCK(dir->dd_lock); + return((de != NULL)? 0 : ret); +} +libc_hidden_def(readdir_r) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/dirent/rewinddir.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/dirent/rewinddir.c new file mode 100644 index 00000000..0a8f1474 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/dirent/rewinddir.c @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include "dirstream.h" + + +/* rewinddir() just does an lseek(fd,0,0) - see close for comments */ +void rewinddir(DIR * dir) +{ + if (!dir) { + __set_errno(EBADF); + return; + } + __UCLIBC_MUTEX_LOCK(dir->dd_lock); + lseek(dir->dd_fd, 0, SEEK_SET); + dir->dd_nextoff = dir->dd_nextloc = dir->dd_size = 0; + __UCLIBC_MUTEX_UNLOCK(dir->dd_lock); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/dirent/scandir.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/dirent/scandir.c new file mode 100644 index 00000000..bb425648 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/dirent/scandir.c @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include +#include +#include +#include "dirstream.h" + +int scandir(const char *dir, struct dirent ***namelist, + int (*selector) (const struct dirent *), + int (*compar) (const struct dirent **, const struct dirent **)) +{ + DIR *dp = opendir (dir); + struct dirent *current; + struct dirent **names = NULL; + size_t names_size = 0, pos; + int save; + + if (dp == NULL) + return -1; + + save = errno; + __set_errno (0); + + pos = 0; + while ((current = readdir (dp)) != NULL) { + int use_it = selector == NULL; + + if (! use_it) + { + use_it = (*selector) (current); + /* The selector function might have changed errno. + * It was zero before and it need to be again to make + * the latter tests work. */ + if (! use_it) + __set_errno (0); + } + if (use_it) + { + struct dirent *vnew; + size_t dsize; + + /* Ignore errors from selector or readdir */ + __set_errno (0); + + if (unlikely(pos == names_size)) + { + struct dirent **new; + if (names_size == 0) + names_size = 10; + else + names_size *= 2; + new = (struct dirent **) realloc (names, + names_size * sizeof (struct dirent *)); + if (new == NULL) + break; + names = new; + } + + dsize = ¤t->d_name[_D_ALLOC_NAMLEN(current)] - (char*)current; + vnew = (struct dirent *) malloc (dsize); + if (vnew == NULL) + break; + + names[pos++] = (struct dirent *) memcpy (vnew, current, dsize); + } + } + + if (unlikely(errno != 0)) + { + save = errno; + closedir (dp); + while (pos > 0) + free (names[--pos]); + free (names); + __set_errno (save); + return -1; + } + + closedir (dp); + __set_errno (save); + + /* Sort the list if we have a comparison function to sort with. */ + if (compar != NULL) + qsort (names, pos, sizeof (struct dirent *), (comparison_fn_t) compar); + *namelist = names; + return pos; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/dirent/scandir64.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/dirent/scandir64.c new file mode 100644 index 00000000..3d2a250a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/dirent/scandir64.c @@ -0,0 +1,111 @@ +/* Copyright (C) 1992-1998, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. + */ + +/* Modified for uClibc by Erik Andersen + */ + +#include <_lfs_64.h> + +#include +#include +#include +#include +#include +#include +#include "dirstream.h" + +int scandir64(const char *dir, struct dirent64 ***namelist, + int (*selector) (const struct dirent64 *), + int (*compar) (const struct dirent64 **, const struct dirent64 **)) +{ + DIR *dp = opendir (dir); + struct dirent64 *current; + struct dirent64 **names = NULL; + size_t names_size = 0, pos; + int save; + + if (dp == NULL) + return -1; + + save = errno; + __set_errno (0); + + pos = 0; + while ((current = readdir64 (dp)) != NULL) { + int use_it = selector == NULL; + + if (! use_it) + { + use_it = (*selector) (current); + /* The selector function might have changed errno. + * It was zero before and it need to be again to make + * the latter tests work. */ + if (! use_it) + __set_errno (0); + } + if (use_it) + { + struct dirent64 *vnew; + size_t dsize; + + /* Ignore errors from selector or readdir64 */ + __set_errno (0); + + if (unlikely(pos == names_size)) + { + struct dirent64 **new; + if (names_size == 0) + names_size = 10; + else + names_size *= 2; + new = (struct dirent64 **) realloc (names, + names_size * sizeof (struct dirent64 *)); + if (new == NULL) + break; + names = new; + } + + dsize = ¤t->d_name[_D_ALLOC_NAMLEN(current)] - (char*)current; + vnew = (struct dirent64 *) malloc (dsize); + if (vnew == NULL) + break; + + names[pos++] = (struct dirent64 *) memcpy (vnew, current, dsize); + } + } + if (unlikely(errno != 0)) + { + save = errno; + closedir (dp); + while (pos > 0) + free (names[--pos]); + free (names); + __set_errno (save); + return -1; + } + + closedir (dp); + __set_errno (save); + + /* Sort the list if we have a comparison function to sort with. */ + if (compar != NULL) + qsort (names, pos, sizeof (struct dirent64 *), (comparison_fn_t) compar); + *namelist = names; + return pos; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/dirent/seekdir.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/dirent/seekdir.c new file mode 100644 index 00000000..eaf447ea --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/dirent/seekdir.c @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include "dirstream.h" + + +void seekdir(DIR * dir, long int offset) +{ + if (!dir) { + __set_errno(EBADF); + return; + } + __UCLIBC_MUTEX_LOCK(dir->dd_lock); + dir->dd_nextoff = lseek(dir->dd_fd, offset, SEEK_SET); + dir->dd_size = dir->dd_nextloc = 0; + __UCLIBC_MUTEX_UNLOCK(dir->dd_lock); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/dirent/telldir.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/dirent/telldir.c new file mode 100644 index 00000000..3c5deca8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/dirent/telldir.c @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include "dirstream.h" + + +long int telldir(DIR * dir) +{ + if (!dir) { + __set_errno(EBADF); + return -1; + } + + /* The next entry. */ + return dir->dd_nextoff; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/dirent/versionsort.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/dirent/versionsort.c new file mode 100644 index 00000000..d84da1f6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/dirent/versionsort.c @@ -0,0 +1,14 @@ +/* + * Copyright (C) 2008-2009 Hai Zaar, Codefidence Ltd + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include "dirstream.h" + +int versionsort(const struct dirent **a, const struct dirent **b) +{ + return strverscmp((*a)->d_name, (*b)->d_name); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/dirent/versionsort64.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/dirent/versionsort64.c new file mode 100644 index 00000000..af9689ea --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/dirent/versionsort64.c @@ -0,0 +1,16 @@ +/* + * Copyright (C) 2008-2009 Hai Zaar, Codefidence Ltd + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include <_lfs_64.h> + +#include +#include +#include "dirstream.h" + +int versionsort64(const struct dirent64 **a, const struct dirent64 **b) +{ + return strverscmp((*a)->d_name, (*b)->d_name); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/elf/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/elf/Makefile new file mode 100644 index 00000000..4bb6872a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/elf/Makefile @@ -0,0 +1,12 @@ +# Copyright (C) 2008 STMicroelectronics Ltd. +# Author: Carmelo Amoroso + +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../ +top_builddir=../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/elf/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/elf/Makefile.in new file mode 100644 index 00000000..1b4bd8bf --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/elf/Makefile.in @@ -0,0 +1,22 @@ +# Copyright (C) 2008 STMicroelectronics Ltd. +# Author: Carmelo Amoroso + +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +subdirs += libc/misc/elf + +libc_a_CSRC = dl-support.c dl-core.c dl-iterate-phdr.c +CFLAGS-dl-iterate-phdr.c=-D_GNU_SOURCE -I$(top_srcdir)ldso/ldso/$(TARGET_ARCH) -I$(top_srcdir)ldso/include +CFLAGS-dl-core.c=-I$(top_srcdir)ldso/ldso/$(TARGET_ARCH) -I$(top_srcdir)ldso/include + +MISC_ELF_OUT:=$(top_builddir)libc/misc/elf +MISC_ELF_OBJ:=$(patsubst %.c,$(MISC_ELF_OUT)/%.o,$(libc_a_CSRC)) + +libc-static-y += $(MISC_ELF_OBJ) +libc-shared-y += $(MISC_ELF_OUT)/dl-iterate-phdr.oS + +objclean-y+= CLEAN_libc/misc/elf + +CLEAN_libc/misc/elf: + $(do_rm) $(addprefix $(MISC_ELF_OUT)/*., o os oS) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/elf/dl-core.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/elf/dl-core.c new file mode 100644 index 00000000..b32dcf82 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/elf/dl-core.c @@ -0,0 +1,20 @@ +/* + * This contains all symbols and functions to support + * dynamic linking into static libc. + + * Copyright (c) 2008 STMicroelectronics Ltd + * Author: Carmelo Amoroso + * + * Based on draft work by Peter S. Mazinger + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + */ + +#ifdef SHARED +#error "This file is not suitable for linking into dynamic libc" +#else +/* Include ldso symbols and functions used into static libc */ +#include "../../../ldso/ldso/dl-symbols.c" +#endif + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/elf/dl-iterate-phdr.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/elf/dl-iterate-phdr.c new file mode 100644 index 00000000..a7677f11 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/elf/dl-iterate-phdr.c @@ -0,0 +1,83 @@ +/* Get loaded objects program headers. + + Based on GNU C library (file: libc/elf/dl-iteratephdr.c) + + Copyright (C) 2001,2002,2003,2004,2006,2007 Free Software Foundation, Inc. + Contributed by Jakub Jelinek , 2001. + + Copyright (C) 2008 STMicroelectronics Ltd. + Author: Carmelo Amoroso + + Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +*/ + + +#include +#include + +/* we want this in libc but nowhere else */ +#ifdef __USE_GNU + +extern __typeof(dl_iterate_phdr) __dl_iterate_phdr; + +hidden_proto(__dl_iterate_phdr) +int +__dl_iterate_phdr (int (*callback) (struct dl_phdr_info *info, size_t size, void *data), void *data) +{ + int ret = 0; +#ifndef __ARCH_HAS_NO_SHARED__ + struct elf_resolve *l; + struct dl_phdr_info info; + + for (l = _dl_loaded_modules; l != NULL; l = l->next) { + info.dlpi_addr = l->loadaddr; + info.dlpi_name = l->libname; + info.dlpi_phdr = l->ppnt; + info.dlpi_phnum = l->n_phent; + ret = callback (&info, sizeof (struct dl_phdr_info), data); + if (ret) + break; + } +#endif + return ret; +} +hidden_def (__dl_iterate_phdr) + +# ifdef SHARED + +weak_alias(__dl_iterate_phdr, dl_iterate_phdr) + +# else + +/* dl-support.c defines these and initializes them early on. */ +extern ElfW(Phdr) *_dl_phdr; +extern size_t _dl_phnum; + +int +dl_iterate_phdr (int (*callback) (struct dl_phdr_info *info, + size_t size, void *data), void *data) +{ + if (_dl_phnum != 0) + { + /* This entry describes this statically-linked program itself. */ + struct dl_phdr_info info; + int ret; +#ifdef __FDPIC__ + info.dlpi_addr.map = NULL; + info.dlpi_addr.got_value = NULL; +#else + info.dlpi_addr = 0; +#endif + info.dlpi_name = ""; + info.dlpi_phdr = _dl_phdr; + info.dlpi_phnum = _dl_phnum; + ret = (*callback) (&info, sizeof (struct dl_phdr_info), data); + if (ret) + return ret; + } + /* Then invoke callback on loaded modules, if any */ + return __dl_iterate_phdr (callback, data); +} + +# endif +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/elf/dl-support.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/elf/dl-support.c new file mode 100644 index 00000000..3ca7afc6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/elf/dl-support.c @@ -0,0 +1,71 @@ +/* + * Support for dynamic linking code in static libc. + * Copyright (C) 1996-2002, 2003, 2004, 2005 Free Software Foundation, Inc. + * + * Partially based on GNU C Library (file: libc/elf/dl-support.c) + * + * Copyright (C) 2008 STMicroelectronics Ltd. + * Author: Carmelo Amoroso + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + */ + +#include +#include +#if defined(USE_TLS) && USE_TLS +#include +#include +#include +#include +#include +#endif + +#if defined(USE_TLS) && USE_TLS + +void (*_dl_init_static_tls) (struct link_map *) = &_dl_nothread_init_static_tls; + +#endif + +ElfW(Phdr) *_dl_phdr; +size_t _dl_phnum; + +void internal_function _dl_aux_init (ElfW(auxv_t) *av); +void internal_function _dl_aux_init (ElfW(auxv_t) *av) +{ + /* Get the program headers base address from the aux vect */ + _dl_phdr = (ElfW(Phdr) *) av[AT_PHDR].a_un.a_val; + + /* Get the number of program headers from the aux vect */ + _dl_phnum = (size_t) av[AT_PHNUM].a_un.a_val; +} + +#if defined(USE_TLS) && USE_TLS +/* Initialize static TLS area and DTV for current (only) thread. + libpthread implementations should provide their own hook + to handle all threads. */ +void +attribute_hidden +_dl_nothread_init_static_tls (struct link_map *map) +{ +# if defined(TLS_TCB_AT_TP) + void *dest = (char *) THREAD_SELF - map->l_tls_offset; +# elif defined(TLS_DTV_AT_TP) + void *dest = (char *) THREAD_SELF + map->l_tls_offset + TLS_PRE_TCB_SIZE; +# else +# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined" +# endif + + /* Fill in the DTV slot so that a later LD/GD access will find it. */ + dtv_t *dtv = THREAD_DTV (); + assert (map->l_tls_modid <= dtv[-1].counter); + dtv[map->l_tls_modid].pointer.val = dest; + dtv[map->l_tls_modid].pointer.is_static = true; + + /* Initialize the memory. */ + memset (mempcpy (dest, map->l_tls_initimage, map->l_tls_initimage_size), + '\0', map->l_tls_blocksize - map->l_tls_initimage_size); +} + +#endif + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/error/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/error/Makefile new file mode 100644 index 00000000..4a8f4a07 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/error/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../ +top_builddir=../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/error/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/error/Makefile.in new file mode 100644 index 00000000..b76a0dff --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/error/Makefile.in @@ -0,0 +1,29 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +subdirs += libc/misc/error + +CSRC := +ifeq ($(UCLIBC_HAS_BSD_ERR),y) +CSRC += err.c +endif +ifeq ($(UCLIBC_HAS_GNU_ERROR),y) +CSRC += error.c +endif + +MISC_ERROR_DIR := $(top_srcdir)libc/misc/error +MISC_ERROR_OUT := $(top_builddir)libc/misc/error + +MISC_ERROR_SRC := $(patsubst %.c,$(MISC_ERROR_DIR)/%.c,$(CSRC)) +MISC_ERROR_OBJ := $(patsubst %.c,$(MISC_ERROR_OUT)/%.o,$(CSRC)) + +libc-y += $(MISC_ERROR_OBJ) + +objclean-y += CLEAN_libc/misc/error + +CLEAN_libc/misc/error: + $(do_rm) $(addprefix $(MISC_ERROR_OUT)/*., o os) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/error/err.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/error/err.c new file mode 100644 index 00000000..9ddb5962 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/error/err.c @@ -0,0 +1,120 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include +#include +#include +#include +#include +#include +#ifdef __UCLIBC_HAS_THREADS__ +#include +#endif + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning REMINDER: Deal with wide oriented stderr case. +#endif + +#if defined __USE_BSD + + + +static void vwarn_work(const char *format, va_list args, int showerr) +{ + /* 0123 45678 9 a b*/ + static const char fmt[] = "%s: \0: %s\n\0\n"; + const char *f; + char buf[64]; + __STDIO_AUTO_THREADLOCK_VAR; + + /* Do this first, in case something below changes errno. */ + f = fmt + 11; /* At 11. */ + if (showerr) { + f -= 4; /* At 7. */ + __xpg_strerror_r(errno, buf, sizeof(buf)); + } + + __STDIO_AUTO_THREADLOCK(stderr); + + fprintf(stderr, fmt, __uclibc_progname); + if (format) { + vfprintf(stderr, format, args); + f -= 2; /* At 5 (showerr) or 9. */ + } + fprintf(stderr, f, buf); + + __STDIO_AUTO_THREADUNLOCK(stderr); +} + +void vwarn(const char *format, va_list args) +{ + vwarn_work(format, args, 1); +} +libc_hidden_def(vwarn) + +void warn(const char *format, ...) +{ + va_list args; + + va_start(args, format); + vwarn(format, args); + va_end(args); +} + +void vwarnx(const char *format, va_list args) +{ + vwarn_work(format, args, 0); +} +libc_hidden_def(vwarnx) + +void warnx(const char *format, ...) +{ + va_list args; + + va_start(args, format); + vwarnx(format, args); + va_end(args); +} + +void verr(int status, const char *format, va_list args) +{ + vwarn(format, args); + exit(status); +} +libc_hidden_def(verr) + +void attribute_noreturn err(int status, const char *format, ...) +{ + va_list args; + + va_start(args, format); + verr(status, format, args); + /* This should get optimized away. We'll leave it now for safety. */ + /* The loop is added only to keep gcc happy. */ + while(1) + va_end(args); +} + +void verrx(int status, const char *format, va_list args) +{ + vwarnx(format, args); + exit(status); +} +libc_hidden_def(verrx) + +void attribute_noreturn errx(int status, const char *format, ...) +{ + va_list args; + + va_start(args, format); + verrx(status, format, args); + /* This should get optimized away. We'll leave it now for safety. */ + /* The loop is added only to keep gcc happy. */ + while(1) + va_end(args); +} +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/error/error.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/error/error.c new file mode 100644 index 00000000..a30a4dec --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/error/error.c @@ -0,0 +1,106 @@ +/* Error handler for noninteractive utilities + Copyright (C) 1990-1998, 2000-2004, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Written by David MacKenzie . */ +/* Adjusted slightly by Erik Andersen */ + +#include +#include +#include +#include +#include + + +/* This variable is incremented each time `error' is called. */ +unsigned int error_message_count = 0; +/* Sometimes we want to have at most one error per line. This + variable controls whether this mode is selected or not. */ +int error_one_per_line; +/* If NULL, error will flush stdout, then print on stderr the program + name, a colon and a space. Otherwise, error will call this + function without parameters instead. */ +void (*error_print_progname) (void) = NULL; + +extern __typeof(error) __error attribute_hidden; +void __error (int status, int errnum, const char *message, ...) +{ + va_list args; + + fflush (stdout); + + if (error_print_progname) + (*error_print_progname) (); + else + fprintf (stderr, "%s: ", __uclibc_progname); + + va_start (args, message); + vfprintf (stderr, message, args); + va_end (args); + ++error_message_count; + if (errnum) { + fprintf (stderr, ": %s", strerror (errnum)); + } + putc ('\n', stderr); + if (status) + exit (status); +} +weak_alias(__error,error) + +extern __typeof(error_at_line) __error_at_line attribute_hidden; +void __error_at_line (int status, int errnum, const char *file_name, + unsigned int line_number, const char *message, ...) +{ + va_list args; + + if (error_one_per_line) { + static const char *old_file_name; + static unsigned int old_line_number; + + if (old_line_number == line_number && + (file_name == old_file_name || !strcmp (old_file_name, file_name))) + /* Simply return and print nothing. */ + return; + + old_file_name = file_name; + old_line_number = line_number; + } + + fflush (stdout); + + if (error_print_progname) + (*error_print_progname) (); + else + fprintf (stderr, "%s:", __uclibc_progname); + + if (file_name != NULL) + fprintf (stderr, "%s:%d: ", file_name, line_number); + + va_start (args, message); + vfprintf (stderr, message, args); + va_end (args); + + ++error_message_count; + if (errnum) { + fprintf (stderr, ": %s", strerror (errnum)); + } + putc ('\n', stderr); + if (status) + exit (status); +} +weak_alias(__error_at_line,error_at_line) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/file/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/file/Makefile new file mode 100644 index 00000000..4a8f4a07 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/file/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../ +top_builddir=../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/file/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/file/Makefile.in new file mode 100644 index 00000000..ace9db06 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/file/Makefile.in @@ -0,0 +1,26 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +subdirs += libc/misc/file + +MISC_FILE_DIR := $(top_srcdir)libc/misc/file +MISC_FILE_OUT := $(top_builddir)libc/misc/file + +MISC_FILE_SRC := $(wildcard $(MISC_FILE_DIR)/*.c) +ifneq ($(UCLIBC_HAS_LFS),y) +MISC_FILE_SRC := $(filter-out $(MISC_FILE_DIR)/lockf64.c,$(MISC_FILE_SRC)) +endif +MISC_FILE_OBJ := $(patsubst $(MISC_FILE_DIR)/%.c,$(MISC_FILE_OUT)/%.o,$(MISC_FILE_SRC)) + +libc-y += $(MISC_FILE_OBJ) + +libc-nomulti-$(UCLIBC_HAS_LFS) += $(MISC_FILE_OUT)/lockf64.o + +objclean-y += CLEAN_libc/misc/file + +CLEAN_libc/misc/file: + $(do_rm) $(addprefix $(MISC_FILE_OUT)/*., o os oS) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/file/lockf.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/file/lockf.c new file mode 100644 index 00000000..b37ace40 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/file/lockf.c @@ -0,0 +1,75 @@ +/* Copyright (C) 1994, 1996, 1997, 1998, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + +#include +#include +#include +#include +#include + + + +/* lockf is a simplified interface to fcntl's locking facilities. */ + +int lockf (int fd, int cmd, off_t len) +{ + struct flock fl; + + memset ((char *) &fl, '\0', sizeof (fl)); + + /* lockf is always relative to the current file position. */ + fl.l_whence = SEEK_CUR; + fl.l_start = 0; + fl.l_len = len; + + switch (cmd) + { + case F_TEST: + /* Test the lock: return 0 if FD is unlocked or locked by this process; + return -1, set errno to EACCES, if another process holds the lock. */ + fl.l_type = F_RDLCK; + if (fcntl (fd, F_GETLK, &fl) < 0) + return -1; + if (fl.l_type == F_UNLCK || fl.l_pid == getpid ()) + return 0; + __set_errno(EACCES); + return -1; + + case F_ULOCK: + fl.l_type = F_UNLCK; + cmd = F_SETLK; + break; + case F_LOCK: + fl.l_type = F_WRLCK; + cmd = F_SETLKW; + break; + case F_TLOCK: + fl.l_type = F_WRLCK; + cmd = F_SETLK; + break; + + default: + __set_errno(EINVAL); + return -1; + } + + return fcntl(fd, cmd, &fl); +} +libc_hidden_def(lockf) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/file/lockf64.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/file/lockf64.c new file mode 100644 index 00000000..17794244 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/file/lockf64.c @@ -0,0 +1,93 @@ +/* Copyright (C) 1994, 1996, 1997, 1998, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <_lfs_64.h> + +#include +#include +#include +#include +#include +#include + +#ifdef __NR_fcntl64 +#define flock flock64 +#define fcntl fcntl64 +#undef F_GETLK +#define F_GETLK F_GETLK64 +#undef F_SETLK +#define F_SETLK F_SETLK64 +#else +#endif + + +/* lockf is a simplified interface to fcntl's locking facilities. */ + +int lockf64 (int fd, int cmd, off64_t len64) +{ + struct flock fl; + off_t len = (off_t) len64; + + if (len64 != (off64_t) len) + { + /* We can't represent the length. */ + __set_errno(EOVERFLOW); + return -1; + } + + memset((char *) &fl, '\0', sizeof (fl)); + + /* lockf is always relative to the current file position. */ + fl.l_whence = SEEK_CUR; + fl.l_start = 0; + fl.l_len = len; + + switch (cmd) + { + case F_TEST: + /* Test the lock: return 0 if FD is unlocked or locked by this process; + return -1, set errno to EACCES, if another process holds the lock. */ + fl.l_type = F_RDLCK; + if (fcntl (fd, F_GETLK, &fl) < 0) + return -1; + if (fl.l_type == F_UNLCK || fl.l_pid == getpid ()) + return 0; + __set_errno(EACCES); + return -1; + + case F_ULOCK: + fl.l_type = F_UNLCK; + cmd = F_SETLK; + break; + case F_LOCK: + fl.l_type = F_WRLCK; + cmd = F_SETLKW; + break; + case F_TLOCK: + fl.l_type = F_WRLCK; + cmd = F_SETLK; + break; + + default: + __set_errno(EINVAL); + return -1; + } + + return fcntl(fd, cmd, &fl); +} +libc_hidden_def(lockf64) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/fnmatch/.indent.pro b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/fnmatch/.indent.pro new file mode 100644 index 00000000..492ecf1c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/fnmatch/.indent.pro @@ -0,0 +1,33 @@ +--blank-lines-after-declarations +--blank-lines-after-procedures +--break-before-boolean-operator +--no-blank-lines-after-commas +--braces-on-if-line +--braces-on-struct-decl-line +--comment-indentation25 +--declaration-comment-column25 +--no-comment-delimiters-on-blank-lines +--cuddle-else +--continuation-indentation4 +--case-indentation0 +--else-endif-column33 +--space-after-cast +--line-comments-indentation0 +--declaration-indentation1 +--dont-format-first-column-comments +--dont-format-comments +--honour-newlines +--indent-level4 +/* changed from 0 to 4 */ +--parameter-indentation4 +--line-length78 /* changed from 75 */ +--continue-at-parentheses +--no-space-after-function-call-names +--dont-break-procedure-type +--dont-star-comments +--leave-optional-blank-lines +--dont-space-special-semicolon +--tab-size4 +/* additions by Mark */ +--case-brace-indentation0 +--leave-preprocessor-space diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/fnmatch/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/fnmatch/Makefile new file mode 100644 index 00000000..4a8f4a07 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/fnmatch/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../ +top_builddir=../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/fnmatch/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/fnmatch/Makefile.in new file mode 100644 index 00000000..2557b5aa --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/fnmatch/Makefile.in @@ -0,0 +1,27 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +subdirs += libc/misc/fnmatch + +ifeq ($(UCLIBC_HAS_FNMATCH_OLD),y) +CSRC := fnmatch_old.c +else +CSRC := fnmatch.c +endif + +MISC_FNMATCH_DIR := $(top_srcdir)libc/misc/fnmatch +MISC_FNMATCH_OUT := $(top_builddir)libc/misc/fnmatch + +MISC_FNMATCH_SRC := $(patsubst %.c,$(MISC_FNMATCH_DIR)/%.c,$(CSRC)) +MISC_FNMATCH_OBJ := $(patsubst %.c,$(MISC_FNMATCH_OUT)/%.o,$(CSRC)) + +libc-$(UCLIBC_HAS_FNMATCH) += $(MISC_FNMATCH_OBJ) + +objclean-y += CLEAN_libc/misc/fnmatch + +CLEAN_libc/misc/fnmatch: + $(do_rm) $(addprefix $(MISC_FNMATCH_OUT)/*., o os) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/fnmatch/fnmatch.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/fnmatch/fnmatch.c new file mode 100644 index 00000000..0fa043ba --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/fnmatch/fnmatch.c @@ -0,0 +1,440 @@ +/* Copyright (C) 1991,1992,1993,1996,1997,1998,1999,2000,2001,2002,2003 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +/* unistd.h must be included with _LIBC defined: we need smallint */ +#include +#include +#ifdef __UCLIBC__ +# undef _LIBC +# define HAVE_STRING_H 1 +# define STDC_HEADERS +# define HAVE___STRCHRNUL 1 +# ifdef __UCLIBC_HAS_WCHAR__ +# define HAVE_WCHAR_H 1 +# define HAVE_WCTYPE_H 1 +# ifdef __UCLIBC_HAS_LOCALE__ +# define HAVE_MBSTATE_T 1 +# define HAVE_MBSRTOWCS 1 +# endif +# endif +#endif + +#include +#include +#include +#include + +#if HAVE_STRING_H || defined _LIBC +# include +#else +# include +#endif + +#if defined STDC_HEADERS || defined _LIBC +# include +#endif + +#ifdef __UCLIBC__ +# define __memset memset +#endif + +/* For platform which support the ISO C amendement 1 functionality we + support user defined character classes. */ +#if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H) +/* Solaris 2.5 has a bug: must be included before . */ +# include +# include +#endif + +/* We need some of the locale data (the collation sequence information) + but there is no interface to get this information in general. Therefore + we support a correct implementation only in glibc. */ +#ifdef _LIBC +# include "../locale/localeinfo.h" +# include "../locale/elem-hash.h" +# include "../locale/coll-lookup.h" +# include + +# define CONCAT(a,b) __CONCAT(a,b) +# define mbsrtowcs __mbsrtowcs +# define fnmatch __fnmatch +extern int fnmatch (const char *pattern, const char *string, int flags); +#endif + +/* We often have to test for FNM_FILE_NAME and FNM_PERIOD being both set. */ +#define NO_LEADING_PERIOD(flags) \ + ((flags & (FNM_FILE_NAME | FNM_PERIOD)) == (FNM_FILE_NAME | FNM_PERIOD)) + +/* Comment out all this code if we are using the GNU C Library, and are not + actually compiling the library itself. This code is part of the GNU C + Library, but also included in many other GNU distributions. Compiling + and linking in this code is a waste when using the GNU C library + (especially if it is a shared library). Rather than having every GNU + program understand `configure --with-gnu-libc' and omit the object files, + it is simpler to just do this in the source for each such file. */ + +#if defined _LIBC || !defined __GNU_LIBRARY__ + + +# if defined STDC_HEADERS || !defined isascii +# define ISASCII(c) 1 +# else +# define ISASCII(c) isascii(c) +# endif + +# ifdef isblank +# define ISBLANK(c) (ISASCII (c) && isblank (c)) +# else +# define ISBLANK(c) ((c) == ' ' || (c) == '\t') +# endif +# ifdef isgraph +# define ISGRAPH(c) (ISASCII (c) && isgraph (c)) +# else +# define ISGRAPH(c) (ISASCII (c) && isprint (c) && !isspace (c)) +# endif + +# define ISPRINT(c) (ISASCII (c) && isprint (c)) +# define ISDIGIT(c) (ISASCII (c) && isdigit (c)) +# define ISALNUM(c) (ISASCII (c) && isalnum (c)) +# define ISALPHA(c) (ISASCII (c) && isalpha (c)) +# define ISCNTRL(c) (ISASCII (c) && iscntrl (c)) +# define ISLOWER(c) (ISASCII (c) && islower (c)) +# define ISPUNCT(c) (ISASCII (c) && ispunct (c)) +# define ISSPACE(c) (ISASCII (c) && isspace (c)) +# define ISUPPER(c) (ISASCII (c) && isupper (c)) +# define ISXDIGIT(c) (ISASCII (c) && isxdigit (c)) + +# define STREQ(s1, s2) ((strcmp (s1, s2) == 0)) + +# if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H) +/* The GNU C library provides support for user-defined character classes + and the functions from ISO C amendement 1. */ +# ifdef CHARCLASS_NAME_MAX +# define CHAR_CLASS_MAX_LENGTH CHARCLASS_NAME_MAX +# else +/* This shouldn't happen but some implementation might still have this + problem. Use a reasonable default value. */ +# define CHAR_CLASS_MAX_LENGTH 256 +# endif + +# ifdef _LIBC +# define IS_CHAR_CLASS(string) __wctype (string) +# else +# define IS_CHAR_CLASS(string) wctype (string) +# endif + +# ifdef _LIBC +# define ISWCTYPE(WC, WT) __iswctype (WC, WT) +# else +# define ISWCTYPE(WC, WT) iswctype (WC, WT) +# endif + +# if (HAVE_MBSTATE_T && HAVE_MBSRTOWCS) || _LIBC +/* In this case we are implementing the multibyte character handling. */ +# define HANDLE_MULTIBYTE 1 +# endif + +# else +# define CHAR_CLASS_MAX_LENGTH 6 /* Namely, `xdigit'. */ + +# define IS_CHAR_CLASS(string) \ + (STREQ (string, "alpha") || STREQ (string, "upper") \ + || STREQ (string, "lower") || STREQ (string, "digit") \ + || STREQ (string, "alnum") || STREQ (string, "xdigit") \ + || STREQ (string, "space") || STREQ (string, "print") \ + || STREQ (string, "punct") || STREQ (string, "graph") \ + || STREQ (string, "cntrl") || STREQ (string, "blank")) +# endif + +/* Avoid depending on library functions or files + whose names are inconsistent. */ + +# if !defined _LIBC && !defined getenv && !defined __UCLIBC__ +extern char *getenv (); +# endif + +# ifndef errno +extern int errno; +# endif + +/* Global variable. */ +static smallint posixly_correct; + +/* This function doesn't exist on most systems. */ + +# if !defined HAVE___STRCHRNUL && !defined _LIBC +static char * +__strchrnul (s, c) + const char *s; + int c; +{ + char *result = strchr (s, c); + if (result == NULL) + result = strchr (s, '\0'); + return result; +} +# endif + +# if HANDLE_MULTIBYTE && !defined HAVE___STRCHRNUL && !defined _LIBC +static wchar_t * +__wcschrnul (s, c) + const wchar_t *s; + wint_t c; +{ + wchar_t *result = wcschr (s, c); + if (result == NULL) + result = wcschr (s, '\0'); + return result; +} +# endif + +# ifndef internal_function +/* Inside GNU libc we mark some function in a special way. In other + environments simply ignore the marking. */ +# define internal_function +# endif + +/* Note that this evaluates C many times. */ +# ifdef _LIBC +# define FOLD(c) ((flags & FNM_CASEFOLD) ? tolower (c) : (c)) +# else +# define FOLD(c) ((flags & FNM_CASEFOLD) && ISUPPER (c) ? tolower (c) : (c)) +# endif +# define CHAR char +# define UCHAR unsigned char +# define INT int +# define FCT internal_fnmatch +# define EXT ext_match +# define END end_pattern +# define L(CS) CS +# ifdef _LIBC +# define BTOWC(C) __btowc (C) +# else +# define BTOWC(C) btowc (C) +# endif +# define STRLEN(S) strlen (S) +# define STRCAT(D, S) strcat (D, S) +# define MEMPCPY(D, S, N) mempcpy (D, S, N) +# define MEMCHR(S, C, N) memchr (S, C, N) +# define STRCOLL(S1, S2) strcoll (S1, S2) +# include "fnmatch_loop.c" + + +# if HANDLE_MULTIBYTE +/* Note that this evaluates C many times. */ +# ifdef _LIBC +# define FOLD(c) ((flags & FNM_CASEFOLD) ? towlower (c) : (c)) +# else +# define FOLD(c) ((flags & FNM_CASEFOLD) && ISUPPER (c) ? towlower (c) : (c)) +# endif +# define CHAR wchar_t +# define UCHAR wint_t +# define INT wint_t +# define FCT internal_fnwmatch +# define EXT ext_wmatch +# define END end_wpattern +# define L(CS) L##CS +# define BTOWC(C) (C) +# define STRLEN(S) wcslen (S) +# define STRCAT(D, S) wcscat (D, S) +# define MEMPCPY(D, S, N) wmempcpy (D, S, N) +# define MEMCHR(S, C, N) wmemchr (S, C, N) +# define STRCOLL(S1, S2) wcscoll (S1, S2) +# ifndef __UCLIBC__ +# define WIDE_CHAR_VERSION 1 +# endif + +# undef IS_CHAR_CLASS +/* We have to convert the wide character string in a multibyte string. But + we know that the character class names consist of alphanumeric characters + from the portable character set, and since the wide character encoding + for a member of the portable character set is the same code point as + its single-byte encoding, we can use a simplified method to convert the + string to a multibyte character string. */ +static wctype_t +is_char_class (const wchar_t *wcs) +{ + char s[CHAR_CLASS_MAX_LENGTH + 1]; + char *cp = s; + + do + { + /* Test for a printable character from the portable character set. */ +# if defined _LIBC || defined __UCLIBC__ + if (*wcs < 0x20 || *wcs > 0x7e + || *wcs == 0x24 || *wcs == 0x40 || *wcs == 0x60) + return (wctype_t) 0; +# else + switch (*wcs) + { + case L' ': case L'!': case L'"': case L'#': case L'%': + case L'&': case L'\'': case L'(': case L')': case L'*': + case L'+': case L',': case L'-': case L'.': case L'/': + case L'0': case L'1': case L'2': case L'3': case L'4': + case L'5': case L'6': case L'7': case L'8': case L'9': + case L':': case L';': case L'<': case L'=': case L'>': + case L'?': + case L'A': case L'B': case L'C': case L'D': case L'E': + case L'F': case L'G': case L'H': case L'I': case L'J': + case L'K': case L'L': case L'M': case L'N': case L'O': + case L'P': case L'Q': case L'R': case L'S': case L'T': + case L'U': case L'V': case L'W': case L'X': case L'Y': + case L'Z': + case L'[': case L'\\': case L']': case L'^': case L'_': + case L'a': case L'b': case L'c': case L'd': case L'e': + case L'f': case L'g': case L'h': case L'i': case L'j': + case L'k': case L'l': case L'm': case L'n': case L'o': + case L'p': case L'q': case L'r': case L's': case L't': + case L'u': case L'v': case L'w': case L'x': case L'y': + case L'z': case L'{': case L'|': case L'}': case L'~': + break; + default: + return (wctype_t) 0; + } +# endif + + /* Avoid overrunning the buffer. */ + if (cp == s + CHAR_CLASS_MAX_LENGTH) + return (wctype_t) 0; + + *cp++ = (char) *wcs++; + } + while (*wcs != L'\0'); + + *cp = '\0'; + +# ifdef _LIBC + return __wctype (s); +# else + return wctype (s); +# endif +} +# define IS_CHAR_CLASS(string) is_char_class (string) + +# include "fnmatch_loop.c" +# endif + +#ifndef __UCLIBC_HAS_WCHAR__ +# undef MB_CUR_MAX +# define MB_CUR_MAX 1 +#endif + +int +fnmatch (const char *pattern, const char *string, int flags) +{ +# if HANDLE_MULTIBYTE + if (__builtin_expect (MB_CUR_MAX, 1) != 1) + { + mbstate_t ps; + size_t n; + const char *p; + wchar_t *wpattern = NULL; + wchar_t *wstring = NULL; + + /* Convert the strings into wide characters. */ + __memset (&ps, '\0', sizeof (ps)); + p = pattern; +#ifdef _LIBC + n = strnlen (pattern, 1024); +#else + n = strlen (pattern); +#endif + if (__builtin_expect (n < 1024, 1)) + { + wpattern = (wchar_t *) alloca ((n + 1) * sizeof (wchar_t)); + n = mbsrtowcs (wpattern, &p, n + 1, &ps); + if (__builtin_expect (n == (size_t) -1, 0)) + /* Something wrong. + XXX Do we have to set `errno' to something which mbsrtows hasn't + already done? */ + return -1; + if (p) + __memset (&ps, '\0', sizeof (ps)); + } + if (__builtin_expect (p != NULL, 0)) + { + n = mbsrtowcs (NULL, &pattern, 0, &ps); + if (__builtin_expect (n == (size_t) -1, 0)) + /* Something wrong. + XXX Do we have to set `errno' to something which mbsrtows hasn't + already done? */ + return -1; + wpattern = (wchar_t *) alloca ((n + 1) * sizeof (wchar_t)); + assert (mbsinit (&ps)); + (void) mbsrtowcs (wpattern, &pattern, n + 1, &ps); + } + + assert (mbsinit (&ps)); +#ifdef _LIBC + n = strnlen (string, 1024); +#else + n = strlen (string); +#endif + p = string; + if (__builtin_expect (n < 1024, 1)) + { + wstring = (wchar_t *) alloca ((n + 1) * sizeof (wchar_t)); + n = mbsrtowcs (wstring, &p, n + 1, &ps); + if (__builtin_expect (n == (size_t) -1, 0)) + /* Something wrong. + XXX Do we have to set `errno' to something which mbsrtows hasn't + already done? */ + return -1; + if (p) + __memset (&ps, '\0', sizeof (ps)); + } + if (__builtin_expect (p != NULL, 0)) + { + n = mbsrtowcs (NULL, &string, 0, &ps); + if (__builtin_expect (n == (size_t) -1, 0)) + /* Something wrong. + XXX Do we have to set `errno' to something which mbsrtows hasn't + already done? */ + return -1; + wstring = (wchar_t *) alloca ((n + 1) * sizeof (wchar_t)); + assert (mbsinit (&ps)); + (void) mbsrtowcs (wstring, &string, n + 1, &ps); + } + + return internal_fnwmatch (wpattern, wstring, wstring + n, + flags & FNM_PERIOD, flags); + } +# endif /* mbstate_t and mbsrtowcs or _LIBC. */ + + return internal_fnmatch (pattern, string, string + strlen (string), + flags & FNM_PERIOD, flags); +} + +# ifdef _LIBC +# undef fnmatch +versioned_symbol (libc, __fnmatch, fnmatch, GLIBC_2_2_3); +# if SHLIB_COMPAT(libc, GLIBC_2_0, GLIBC_2_2_3) +strong_alias (__fnmatch, __fnmatch_old) +compat_symbol (libc, __fnmatch_old, fnmatch, GLIBC_2_0); +# endif +libc_hidden_ver (__fnmatch, fnmatch) +# else +libc_hidden_def(fnmatch) +# endif + +#endif /* _LIBC or not __GNU_LIBRARY__. */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/fnmatch/fnmatch_loop.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/fnmatch/fnmatch_loop.c new file mode 100644 index 00000000..af41727c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/fnmatch/fnmatch_loop.c @@ -0,0 +1,1205 @@ +/* Copyright (C) 1991,1992,1993,1996,1997,1998,1999,2000,2001,2003,2004,2005 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Match STRING against the filename pattern PATTERN, returning zero if + it matches, nonzero if not. */ +static int FCT (const CHAR *pattern, const CHAR *string, + const CHAR *string_end, int no_leading_period, int flags) + internal_function; +static int EXT (INT opt, const CHAR *pattern, const CHAR *string, + const CHAR *string_end, int no_leading_period, int flags) + internal_function; +static const CHAR *END (const CHAR *patternp) internal_function; + +static int +internal_function +FCT (const CHAR *pattern, const CHAR *string, const CHAR *string_end, + int no_leading_period, int flags) +{ + register const CHAR *p = pattern, *n = string; + register UCHAR c; +#ifdef _LIBC +# if WIDE_CHAR_VERSION + const char *collseq = (const char *) + _NL_CURRENT(LC_COLLATE, _NL_COLLATE_COLLSEQWC); +# else + const UCHAR *collseq = (const UCHAR *) + _NL_CURRENT(LC_COLLATE, _NL_COLLATE_COLLSEQMB); +# endif +#endif + + while ((c = *p++) != L('\0')) + { + int new_no_leading_period = 0; + c = FOLD (c); + + switch (c) + { + case L('?'): + if (__builtin_expect (flags & FNM_EXTMATCH, 0) && *p == '(') + { + int res; + + res = EXT (c, p, n, string_end, no_leading_period, + flags); + if (res != -1) + return res; + } + + if (n == string_end) + return FNM_NOMATCH; + else if (*n == L('/') && (flags & FNM_FILE_NAME)) + return FNM_NOMATCH; + else if (*n == L('.') && no_leading_period) + return FNM_NOMATCH; + break; + + case L('\\'): + if (!(flags & FNM_NOESCAPE)) + { + c = *p++; + if (c == L('\0')) + /* Trailing \ loses. */ + return FNM_NOMATCH; + c = FOLD (c); + } + if (n == string_end || FOLD ((UCHAR) *n) != c) + return FNM_NOMATCH; + break; + + case L('*'): + if (__builtin_expect (flags & FNM_EXTMATCH, 0) && *p == '(') + { + int res; + + res = EXT (c, p, n, string_end, no_leading_period, + flags); + if (res != -1) + return res; + } + + if (n != string_end && *n == L('.') && no_leading_period) + return FNM_NOMATCH; + + for (c = *p++; c == L('?') || c == L('*'); c = *p++) + { + if (*p == L('(') && (flags & FNM_EXTMATCH) != 0) + { + const CHAR *endp = END (p); + if (endp != p) + { + /* This is a pattern. Skip over it. */ + p = endp; + continue; + } + } + + if (c == L('?')) + { + /* A ? needs to match one character. */ + if (n == string_end) + /* There isn't another character; no match. */ + return FNM_NOMATCH; + else if (*n == L('/') + && __builtin_expect (flags & FNM_FILE_NAME, 0)) + /* A slash does not match a wildcard under + FNM_FILE_NAME. */ + return FNM_NOMATCH; + else + /* One character of the string is consumed in matching + this ? wildcard, so *??? won't match if there are + less than three characters. */ + ++n; + } + } + + if (c == L('\0')) + /* The wildcard(s) is/are the last element of the pattern. + If the name is a file name and contains another slash + this means it cannot match, unless the FNM_LEADING_DIR + flag is set. */ + { + int result = (flags & FNM_FILE_NAME) == 0 ? 0 : FNM_NOMATCH; + + if (flags & FNM_FILE_NAME) + { + if (flags & FNM_LEADING_DIR) + result = 0; + else + { + if (MEMCHR (n, L('/'), string_end - n) == NULL) + result = 0; + } + } + + return result; + } + else + { + const CHAR *endp; + + endp = MEMCHR (n, (flags & FNM_FILE_NAME) ? L('/') : L('\0'), + string_end - n); + if (endp == NULL) + endp = string_end; + + if (c == L('[') + || (__builtin_expect (flags & FNM_EXTMATCH, 0) != 0 + && (c == L('@') || c == L('+') || c == L('!')) + && *p == L('('))) + { + int flags2 = ((flags & FNM_FILE_NAME) + ? flags : (flags & ~FNM_PERIOD)); + int no_leading_period2 = no_leading_period; + + for (--p; n < endp; ++n, no_leading_period2 = 0) + if (FCT (p, n, string_end, no_leading_period2, flags2) + == 0) + return 0; + } + else if (c == L('/') && (flags & FNM_FILE_NAME)) + { + while (n < string_end && *n != L('/')) + ++n; + if (n < string_end && *n == L('/') + && (FCT (p, n + 1, string_end, flags & FNM_PERIOD, flags) + == 0)) + return 0; + } + else + { + int flags2 = ((flags & FNM_FILE_NAME) + ? flags : (flags & ~FNM_PERIOD)); + int no_leading_period2 = no_leading_period; + + if (c == L('\\') && !(flags & FNM_NOESCAPE)) + c = *p; + c = FOLD (c); + for (--p; n < endp; ++n, no_leading_period2 = 0) + if (FOLD ((UCHAR) *n) == c + && (FCT (p, n, string_end, no_leading_period2, flags2) + == 0)) + return 0; + } + } + + /* If we come here no match is possible with the wildcard. */ + return FNM_NOMATCH; + + case L('['): + { + /* Nonzero if the sense of the character class is inverted. */ + register int not; + CHAR cold; + UCHAR fn; + + if (posixly_correct == 0) + posixly_correct = getenv ("POSIXLY_CORRECT") != NULL ? 1 : -1; + + if (n == string_end) + return FNM_NOMATCH; + + if (*n == L('.') && no_leading_period) + return FNM_NOMATCH; + + if (*n == L('/') && (flags & FNM_FILE_NAME)) + /* `/' cannot be matched. */ + return FNM_NOMATCH; + + not = (*p == L('!') || (posixly_correct < 0 && *p == L('^'))); + if (not) + ++p; + + fn = FOLD ((UCHAR) *n); + + c = *p++; + for (;;) + { + if (!(flags & FNM_NOESCAPE) && c == L('\\')) + { + if (*p == L('\0')) + return FNM_NOMATCH; + c = FOLD ((UCHAR) *p); + ++p; + + goto normal_bracket; + } + else if (c == L('[') && *p == L(':')) + { + /* Leave room for the null. */ + CHAR str[CHAR_CLASS_MAX_LENGTH + 1]; + size_t c1 = 0; +#if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H) + wctype_t wt; +#endif + const CHAR *startp = p; + + for (;;) + { + if (c1 == CHAR_CLASS_MAX_LENGTH) + /* The name is too long and therefore the pattern + is ill-formed. */ + return FNM_NOMATCH; + + c = *++p; + if (c == L(':') && p[1] == L(']')) + { + p += 2; + break; + } + if (c < L('a') || c >= L('z')) + { + /* This cannot possibly be a character class name. + Match it as a normal range. */ + p = startp; + c = L('['); + goto normal_bracket; + } + str[c1++] = c; + } + str[c1] = L('\0'); + +#if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H) + wt = IS_CHAR_CLASS (str); + if (wt == 0) + /* Invalid character class name. */ + return FNM_NOMATCH; + +# if defined _LIBC && ! WIDE_CHAR_VERSION + /* The following code is glibc specific but does + there a good job in speeding up the code since + we can avoid the btowc() call. */ + if (_ISCTYPE ((UCHAR) *n, wt)) + goto matched; +# else + if (ISWCTYPE (BTOWC ((UCHAR) *n), wt)) + goto matched; +# endif +#else + if ((STREQ (str, L("alnum")) && ISALNUM ((UCHAR) *n)) + || (STREQ (str, L("alpha")) && ISALPHA ((UCHAR) *n)) + || (STREQ (str, L("blank")) && ISBLANK ((UCHAR) *n)) + || (STREQ (str, L("cntrl")) && ISCNTRL ((UCHAR) *n)) + || (STREQ (str, L("digit")) && ISDIGIT ((UCHAR) *n)) + || (STREQ (str, L("graph")) && ISGRAPH ((UCHAR) *n)) + || (STREQ (str, L("lower")) && ISLOWER ((UCHAR) *n)) + || (STREQ (str, L("print")) && ISPRINT ((UCHAR) *n)) + || (STREQ (str, L("punct")) && ISPUNCT ((UCHAR) *n)) + || (STREQ (str, L("space")) && ISSPACE ((UCHAR) *n)) + || (STREQ (str, L("upper")) && ISUPPER ((UCHAR) *n)) + || (STREQ (str, L("xdigit")) && ISXDIGIT ((UCHAR) *n))) + goto matched; +#endif + c = *p++; + } +#ifdef _LIBC + else if (c == L('[') && *p == L('=')) + { + UCHAR str[1]; + uint32_t nrules = + _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); + const CHAR *startp = p; + + c = *++p; + if (c == L('\0')) + { + p = startp; + c = L('['); + goto normal_bracket; + } + str[0] = c; + + c = *++p; + if (c != L('=') || p[1] != L(']')) + { + p = startp; + c = L('['); + goto normal_bracket; + } + p += 2; + + if (nrules == 0) + { + if ((UCHAR) *n == str[0]) + goto matched; + } + else + { + const int32_t *table; +# if WIDE_CHAR_VERSION + const int32_t *weights; + const int32_t *extra; +# else + const unsigned char *weights; + const unsigned char *extra; +# endif + const int32_t *indirect; + int32_t idx; + const UCHAR *cp = (const UCHAR *) str; + + /* This #include defines a local function! */ +# if WIDE_CHAR_VERSION +# include +# else +# include +# endif + +# if WIDE_CHAR_VERSION + table = (const int32_t *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEWC); + weights = (const int32_t *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_WEIGHTWC); + extra = (const int32_t *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAWC); + indirect = (const int32_t *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTWC); +# else + table = (const int32_t *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB); + weights = (const unsigned char *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_WEIGHTMB); + extra = (const unsigned char *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAMB); + indirect = (const int32_t *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTMB); +# endif + + idx = findidx (&cp); + if (idx != 0) + { + /* We found a table entry. Now see whether the + character we are currently at has the same + equivalance class value. */ + int len = weights[idx]; + int32_t idx2; + const UCHAR *np = (const UCHAR *) n; + + idx2 = findidx (&np); + if (idx2 != 0 && len == weights[idx2]) + { + int cnt = 0; + + while (cnt < len + && (weights[idx + 1 + cnt] + == weights[idx2 + 1 + cnt])) + ++cnt; + + if (cnt == len) + goto matched; + } + } + } + + c = *p++; + } +#endif + else if (c == L('\0')) + /* [ (unterminated) loses. */ + return FNM_NOMATCH; + else + { + int is_range = 0; + +#ifdef _LIBC + int is_seqval = 0; + + if (c == L('[') && *p == L('.')) + { + uint32_t nrules = + _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); + const CHAR *startp = p; + size_t c1 = 0; + + while (1) + { + c = *++p; + if (c == L('.') && p[1] == L(']')) + { + p += 2; + break; + } + if (c == '\0') + return FNM_NOMATCH; + ++c1; + } + + /* We have to handling the symbols differently in + ranges since then the collation sequence is + important. */ + is_range = *p == L('-') && p[1] != L('\0'); + + if (nrules == 0) + { + /* There are no names defined in the collation + data. Therefore we only accept the trivial + names consisting of the character itself. */ + if (c1 != 1) + return FNM_NOMATCH; + + if (!is_range && *n == startp[1]) + goto matched; + + cold = startp[1]; + c = *p++; + } + else + { + int32_t table_size; + const int32_t *symb_table; +# ifdef WIDE_CHAR_VERSION + char str[c1]; + unsigned int strcnt; +# else +# define str (startp + 1) +# endif + const unsigned char *extra; + int32_t idx; + int32_t elem; + int32_t second; + int32_t hash; + +# ifdef WIDE_CHAR_VERSION + /* We have to convert the name to a single-byte + string. This is possible since the names + consist of ASCII characters and the internal + representation is UCS4. */ + for (strcnt = 0; strcnt < c1; ++strcnt) + str[strcnt] = startp[1 + strcnt]; +#endif + + table_size = + _NL_CURRENT_WORD (LC_COLLATE, + _NL_COLLATE_SYMB_HASH_SIZEMB); + symb_table = (const int32_t *) + _NL_CURRENT (LC_COLLATE, + _NL_COLLATE_SYMB_TABLEMB); + extra = (const unsigned char *) + _NL_CURRENT (LC_COLLATE, + _NL_COLLATE_SYMB_EXTRAMB); + + /* Locate the character in the hashing table. */ + hash = elem_hash (str, c1); + + idx = 0; + elem = hash % table_size; + if (symb_table[2 * elem] != 0) + { + second = hash % (table_size - 2) + 1; + + do + { + /* First compare the hashing value. */ + if (symb_table[2 * elem] == hash + && (c1 + == extra[symb_table[2 * elem + 1]]) + && __memcmp (str, + &extra[symb_table[2 * elem + + 1] + + 1], c1) == 0) + { + /* Yep, this is the entry. */ + idx = symb_table[2 * elem + 1]; + idx += 1 + extra[idx]; + break; + } + + /* Next entry. */ + elem += second; + } + while (symb_table[2 * elem] != 0); + } + + if (symb_table[2 * elem] != 0) + { + /* Compare the byte sequence but only if + this is not part of a range. */ +# ifdef WIDE_CHAR_VERSION + int32_t *wextra; + + idx += 1 + extra[idx]; + /* Adjust for the alignment. */ + idx = (idx + 3) & ~3; + + wextra = (int32_t *) &extra[idx + 4]; +# endif + + if (! is_range) + { +# ifdef WIDE_CHAR_VERSION + for (c1 = 0; + (int32_t) c1 < wextra[idx]; + ++c1) + if (n[c1] != wextra[1 + c1]) + break; + + if ((int32_t) c1 == wextra[idx]) + goto matched; +# else + for (c1 = 0; c1 < extra[idx]; ++c1) + if (n[c1] != extra[1 + c1]) + break; + + if (c1 == extra[idx]) + goto matched; +# endif + } + + /* Get the collation sequence value. */ + is_seqval = 1; +# ifdef WIDE_CHAR_VERSION + cold = wextra[1 + wextra[idx]]; +# else + /* Adjust for the alignment. */ + idx += 1 + extra[idx]; + idx = (idx + 3) & ~4; + cold = *((int32_t *) &extra[idx]); +# endif + + c = *p++; + } + else if (c1 == 1) + { + /* No valid character. Match it as a + single byte. */ + if (!is_range && *n == str[0]) + goto matched; + + cold = str[0]; + c = *p++; + } + else + return FNM_NOMATCH; + } + } + else +# undef str +#endif + { + c = FOLD (c); + normal_bracket: + + /* We have to handling the symbols differently in + ranges since then the collation sequence is + important. */ + is_range = (*p == L('-') && p[1] != L('\0') + && p[1] != L(']')); + + if (!is_range && c == fn) + goto matched; + + /* This is needed if we goto normal_bracket; from + outside of is_seqval's scope. */ +#ifndef __UCLIBC__ /* this should be probably ifdef _LIBC*/ + is_seqval = 0; +#endif + cold = c; + c = *p++; + } + + if (c == L('-') && *p != L(']')) + { +#if _LIBC + /* We have to find the collation sequence + value for C. Collation sequence is nothing + we can regularly access. The sequence + value is defined by the order in which the + definitions of the collation values for the + various characters appear in the source + file. A strange concept, nowhere + documented. */ + uint32_t fcollseq; + uint32_t lcollseq; + UCHAR cend = *p++; + +# ifdef WIDE_CHAR_VERSION + /* Search in the `names' array for the characters. */ + fcollseq = __collseq_table_lookup (collseq, fn); + if (fcollseq == ~((uint32_t) 0)) + /* XXX We don't know anything about the character + we are supposed to match. This means we are + failing. */ + goto range_not_matched; + + if (is_seqval) + lcollseq = cold; + else + lcollseq = __collseq_table_lookup (collseq, cold); +# else + fcollseq = collseq[fn]; + lcollseq = is_seqval ? cold : collseq[(UCHAR) cold]; +# endif + + is_seqval = 0; + if (cend == L('[') && *p == L('.')) + { + uint32_t nrules = + _NL_CURRENT_WORD (LC_COLLATE, + _NL_COLLATE_NRULES); + const CHAR *startp = p; + size_t c1 = 0; + + while (1) + { + c = *++p; + if (c == L('.') && p[1] == L(']')) + { + p += 2; + break; + } + if (c == '\0') + return FNM_NOMATCH; + ++c1; + } + + if (nrules == 0) + { + /* There are no names defined in the + collation data. Therefore we only + accept the trivial names consisting + of the character itself. */ + if (c1 != 1) + return FNM_NOMATCH; + + cend = startp[1]; + } + else + { + int32_t table_size; + const int32_t *symb_table; +# ifdef WIDE_CHAR_VERSION + char str[c1]; + unsigned int strcnt; +# else +# define str (startp + 1) +# endif + const unsigned char *extra; + int32_t idx; + int32_t elem; + int32_t second; + int32_t hash; + +# ifdef WIDE_CHAR_VERSION + /* We have to convert the name to a single-byte + string. This is possible since the names + consist of ASCII characters and the internal + representation is UCS4. */ + for (strcnt = 0; strcnt < c1; ++strcnt) + str[strcnt] = startp[1 + strcnt]; +# endif + + table_size = + _NL_CURRENT_WORD (LC_COLLATE, + _NL_COLLATE_SYMB_HASH_SIZEMB); + symb_table = (const int32_t *) + _NL_CURRENT (LC_COLLATE, + _NL_COLLATE_SYMB_TABLEMB); + extra = (const unsigned char *) + _NL_CURRENT (LC_COLLATE, + _NL_COLLATE_SYMB_EXTRAMB); + + /* Locate the character in the hashing + table. */ + hash = elem_hash (str, c1); + + idx = 0; + elem = hash % table_size; + if (symb_table[2 * elem] != 0) + { + second = hash % (table_size - 2) + 1; + + do + { + /* First compare the hashing value. */ + if (symb_table[2 * elem] == hash + && (c1 + == extra[symb_table[2 * elem + 1]]) + && __memcmp (str, + &extra[symb_table[2 * elem + 1] + + 1], c1) == 0) + { + /* Yep, this is the entry. */ + idx = symb_table[2 * elem + 1]; + idx += 1 + extra[idx]; + break; + } + + /* Next entry. */ + elem += second; + } + while (symb_table[2 * elem] != 0); + } + + if (symb_table[2 * elem] != 0) + { + /* Compare the byte sequence but only if + this is not part of a range. */ +# ifdef WIDE_CHAR_VERSION + int32_t *wextra; + + idx += 1 + extra[idx]; + /* Adjust for the alignment. */ + idx = (idx + 3) & ~4; + + wextra = (int32_t *) &extra[idx + 4]; +# endif + /* Get the collation sequence value. */ + is_seqval = 1; +# ifdef WIDE_CHAR_VERSION + cend = wextra[1 + wextra[idx]]; +# else + /* Adjust for the alignment. */ + idx += 1 + extra[idx]; + idx = (idx + 3) & ~4; + cend = *((int32_t *) &extra[idx]); +# endif + } + else if (symb_table[2 * elem] != 0 && c1 == 1) + { + cend = str[0]; + c = *p++; + } + else + return FNM_NOMATCH; + } +# undef str + } + else + { + if (!(flags & FNM_NOESCAPE) && cend == L('\\')) + cend = *p++; + if (cend == L('\0')) + return FNM_NOMATCH; + cend = FOLD (cend); + } + + /* XXX It is not entirely clear to me how to handle + characters which are not mentioned in the + collation specification. */ + if ( +# ifdef WIDE_CHAR_VERSION + lcollseq == 0xffffffff || +# endif + lcollseq <= fcollseq) + { + /* We have to look at the upper bound. */ + uint32_t hcollseq; + + if (is_seqval) + hcollseq = cend; + else + { +# ifdef WIDE_CHAR_VERSION + hcollseq = + __collseq_table_lookup (collseq, cend); + if (hcollseq == ~((uint32_t) 0)) + { + /* Hum, no information about the upper + bound. The matching succeeds if the + lower bound is matched exactly. */ + if (lcollseq != fcollseq) + goto range_not_matched; + + goto matched; + } +# else + hcollseq = collseq[cend]; +# endif + } + + if (lcollseq <= hcollseq && fcollseq <= hcollseq) + goto matched; + } +# ifdef WIDE_CHAR_VERSION + range_not_matched: +# endif +#else + /* We use a boring value comparison of the character + values. This is better than comparing using + `strcoll' since the latter would have surprising + and sometimes fatal consequences. */ + UCHAR cend = *p++; + + if (!(flags & FNM_NOESCAPE) && cend == L('\\')) + cend = *p++; + if (cend == L('\0')) + return FNM_NOMATCH; + + /* It is a range. */ + if (cold <= fn && fn <= cend) + goto matched; +#endif + + c = *p++; + } + } + + if (c == L(']')) + break; + } + + if (!not) + return FNM_NOMATCH; + break; + + matched: + /* Skip the rest of the [...] that already matched. */ + do + { + ignore_next: + c = *p++; + + if (c == L('\0')) + /* [... (unterminated) loses. */ + return FNM_NOMATCH; + + if (!(flags & FNM_NOESCAPE) && c == L('\\')) + { + if (*p == L('\0')) + return FNM_NOMATCH; + /* XXX 1003.2d11 is unclear if this is right. */ + ++p; + } + else if (c == L('[') && *p == L(':')) + { + int c1 = 0; + const CHAR *startp = p; + + while (1) + { + c = *++p; + if (++c1 == CHAR_CLASS_MAX_LENGTH) + return FNM_NOMATCH; + + if (*p == L(':') && p[1] == L(']')) + break; + + if (c < L('a') || c >= L('z')) + { + p = startp; + goto ignore_next; + } + } + p += 2; + c = *p++; + } + else if (c == L('[') && *p == L('=')) + { + c = *++p; + if (c == L('\0')) + return FNM_NOMATCH; + c = *++p; + if (c != L('=') || p[1] != L(']')) + return FNM_NOMATCH; + p += 2; + c = *p++; + } + else if (c == L('[') && *p == L('.')) + { + ++p; + while (1) + { + c = *++p; + if (c == '\0') + return FNM_NOMATCH; + + if (*p == L('.') && p[1] == L(']')) + break; + } + p += 2; + c = *p++; + } + } + while (c != L(']')); + if (not) + return FNM_NOMATCH; + } + break; + + case L('+'): + case L('@'): + case L('!'): + if (__builtin_expect (flags & FNM_EXTMATCH, 0) && *p == '(') + { + int res; + + res = EXT (c, p, n, string_end, no_leading_period, flags); + if (res != -1) + return res; + } + goto normal_match; + + case L('/'): + if (NO_LEADING_PERIOD (flags)) + { + if (n == string_end || c != (UCHAR) *n) + return FNM_NOMATCH; + + new_no_leading_period = 1; + break; + } + /* FALLTHROUGH */ + default: + normal_match: + if (n == string_end || c != FOLD ((UCHAR) *n)) + return FNM_NOMATCH; + } + + no_leading_period = new_no_leading_period; + ++n; + } + + if (n == string_end) + return 0; + + if ((flags & FNM_LEADING_DIR) && n != string_end && *n == L('/')) + /* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz". */ + return 0; + + return FNM_NOMATCH; +} + + +static const CHAR * +internal_function +END (const CHAR *pattern) +{ + const CHAR *p = pattern; + + while (1) + if (*++p == L('\0')) + /* This is an invalid pattern. */ + return pattern; + else if (*p == L('[')) + { + /* Handle brackets special. */ + if (posixly_correct == 0) + posixly_correct = getenv ("POSIXLY_CORRECT") != NULL ? 1 : -1; + + /* Skip the not sign. We have to recognize it because of a possibly + following ']'. */ + if (*++p == L('!') || (posixly_correct < 0 && *p == L('^'))) + ++p; + /* A leading ']' is recognized as such. */ + if (*p == L(']')) + ++p; + /* Skip over all characters of the list. */ + while (*p != L(']')) + if (*p++ == L('\0')) + /* This is no valid pattern. */ + return pattern; + } + else if ((*p == L('?') || *p == L('*') || *p == L('+') || *p == L('@') + || *p == L('!')) && p[1] == L('(')) + p = END (p + 1); + else if (*p == L(')')) + break; + + return p + 1; +} + + +static int +internal_function +EXT (INT opt, const CHAR *pattern, const CHAR *string, const CHAR *string_end, + int no_leading_period, int flags) +{ + const CHAR *startp; + int level; + struct patternlist + { + struct patternlist *next; + CHAR str[0]; + } *list = NULL; + struct patternlist **lastp = &list; + size_t pattern_len = STRLEN (pattern); + const CHAR *p; + const CHAR *rs; + + /* Parse the pattern. Store the individual parts in the list. */ + level = 0; + for (startp = p = pattern + 1; level >= 0; ++p) + if (*p == L('\0')) + /* This is an invalid pattern. */ + return -1; + else if (*p == L('[')) + { + /* Handle brackets special. */ + if (posixly_correct == 0) + posixly_correct = getenv ("POSIXLY_CORRECT") != NULL ? 1 : -1; + + /* Skip the not sign. We have to recognize it because of a possibly + following ']'. */ + if (*++p == L('!') || (posixly_correct < 0 && *p == L('^'))) + ++p; + /* A leading ']' is recognized as such. */ + if (*p == L(']')) + ++p; + /* Skip over all characters of the list. */ + while (*p != L(']')) + if (*p++ == L('\0')) + /* This is no valid pattern. */ + return -1; + } + else if ((*p == L('?') || *p == L('*') || *p == L('+') || *p == L('@') + || *p == L('!')) && p[1] == L('(')) + /* Remember the nesting level. */ + ++level; + else if (*p == L(')')) + { + if (level-- == 0) + { + /* This means we found the end of the pattern. */ +#define NEW_PATTERN \ + struct patternlist *newp; \ + \ + if (opt == L('?') || opt == L('@')) \ + newp = alloca (sizeof (struct patternlist) \ + + (pattern_len * sizeof (CHAR))); \ + else \ + newp = alloca (sizeof (struct patternlist) \ + + ((p - startp + 1) * sizeof (CHAR))); \ + *((CHAR *) MEMPCPY (newp->str, startp, p - startp)) = L('\0'); \ + newp->next = NULL; \ + *lastp = newp; \ + lastp = &newp->next + NEW_PATTERN; + } + } + else if (*p == L('|')) + { + if (level == 0) + { + NEW_PATTERN; + startp = p + 1; + } + } + assert (list != NULL); + assert (p[-1] == L(')')); +#undef NEW_PATTERN + + switch (opt) + { + case L('*'): + if (FCT (p, string, string_end, no_leading_period, flags) == 0) + return 0; + /* FALLTHROUGH */ + + case L('+'): + do + { + for (rs = string; rs <= string_end; ++rs) + /* First match the prefix with the current pattern with the + current pattern. */ + if (FCT (list->str, string, rs, no_leading_period, + flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD) == 0 + /* This was successful. Now match the rest with the rest + of the pattern. */ + && (FCT (p, rs, string_end, + rs == string + ? no_leading_period + : rs[-1] == '/' && NO_LEADING_PERIOD (flags) ? 1 : 0, + flags & FNM_FILE_NAME + ? flags : flags & ~FNM_PERIOD) == 0 + /* This didn't work. Try the whole pattern. */ + || (rs != string + && FCT (pattern - 1, rs, string_end, + rs == string + ? no_leading_period + : (rs[-1] == '/' && NO_LEADING_PERIOD (flags) + ? 1 : 0), + flags & FNM_FILE_NAME + ? flags : flags & ~FNM_PERIOD) == 0))) + /* It worked. Signal success. */ + return 0; + } + while ((list = list->next) != NULL); + + /* None of the patterns lead to a match. */ + return FNM_NOMATCH; + + case L('?'): + if (FCT (p, string, string_end, no_leading_period, flags) == 0) + return 0; + /* FALLTHROUGH */ + + case L('@'): + do + /* I cannot believe it but `strcat' is actually acceptable + here. Match the entire string with the prefix from the + pattern list and the rest of the pattern following the + pattern list. */ + if (FCT (STRCAT (list->str, p), string, string_end, + no_leading_period, + flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD) == 0) + /* It worked. Signal success. */ + return 0; + while ((list = list->next) != NULL); + + /* None of the patterns lead to a match. */ + return FNM_NOMATCH; + + case L('!'): + for (rs = string; rs <= string_end; ++rs) + { + struct patternlist *runp; + + for (runp = list; runp != NULL; runp = runp->next) + if (FCT (runp->str, string, rs, no_leading_period, + flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD) == 0) + break; + + /* If none of the patterns matched see whether the rest does. */ + if (runp == NULL + && (FCT (p, rs, string_end, + rs == string + ? no_leading_period + : rs[-1] == '/' && NO_LEADING_PERIOD (flags) ? 1 : 0, + flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD) + == 0)) + /* This is successful. */ + return 0; + } + + /* None of the patterns together with the rest of the pattern + lead to a match. */ + return FNM_NOMATCH; + + default: + assert (! "Invalid extended matching operator"); + break; + } + + return -1; +} + + +#undef FOLD +#undef CHAR +#undef UCHAR +#undef INT +#undef FCT +#undef EXT +#undef END +#undef MEMPCPY +#undef MEMCHR +#undef STRCOLL +#undef STRLEN +#undef STRCAT +#undef L +#undef BTOWC diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/fnmatch/fnmatch_old.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/fnmatch/fnmatch_old.c new file mode 100644 index 00000000..2dece85d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/fnmatch/fnmatch_old.c @@ -0,0 +1,220 @@ +/* Copyright (C) 1991, 1992, 1993, 1996 Free Software Foundation, Inc. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include + + +/* Comment out all this code if we are using the GNU C Library, and are not + actually compiling the library itself. This code is part of the GNU C + Library, but also included in many other GNU distributions. Compiling + and linking in this code is a waste when using the GNU C library + (especially if it is a shared library). Rather than having every GNU + program understand `configure --with-gnu-libc' and omit the object files, + it is simpler to just do this in the source for each such file. */ + +#if defined (_LIBC) || !defined (__GNU_LIBRARY__) + + +# if defined (STDC_HEADERS) || !defined (isascii) +# define ISASCII(c) 1 +# else +# define ISASCII(c) isascii(c) +# endif + +# define ISUPPER(c) (ISASCII (c) && isupper (c)) + + +/* Match STRING against the filename pattern PATTERN, returning zero if + it matches, nonzero if not. */ +int fnmatch(const char *pattern, const char *string, int flags) +{ + register const char *p = pattern, *n = string; + register char c; + +/* Note that this evaluates C many times. */ +# define FOLD(c) ((flags & FNM_CASEFOLD) && ISUPPER (c) ? tolower (c) : (c)) + + while ((c = *p++) != '\0') { + c = FOLD(c); + + switch (c) { + case '?': + if (*n == '\0') + return FNM_NOMATCH; + else if ((flags & FNM_FILE_NAME) && *n == '/') + return FNM_NOMATCH; + else if ((flags & FNM_PERIOD) && *n == '.' && + (n == string + || ((flags & FNM_FILE_NAME) + && n[-1] == '/'))) return FNM_NOMATCH; + break; + + case '\\': + if (!(flags & FNM_NOESCAPE)) { + c = *p++; + if (c == '\0') + /* Trailing \ loses. */ + return FNM_NOMATCH; + c = FOLD(c); + } + if (FOLD(*n) != c) + return FNM_NOMATCH; + break; + + case '*': + if ((flags & FNM_PERIOD) && *n == '.' && + (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/'))) + return FNM_NOMATCH; + + for (c = *p++; c == '?' || c == '*'; c = *p++) { + if ((flags & FNM_FILE_NAME) && *n == '/') + /* A slash does not match a wildcard under FNM_FILE_NAME. */ + return FNM_NOMATCH; + else if (c == '?') { + /* A ? needs to match one character. */ + if (*n == '\0') + /* There isn't another character; no match. */ + return FNM_NOMATCH; + else + /* One character of the string is consumed in matching + this ? wildcard, so *??? won't match if there are + less than three characters. */ + ++n; + } + } + + if (c == '\0') + return 0; + + { + char c1 = (!(flags & FNM_NOESCAPE) && c == '\\') ? *p : c; + + c1 = FOLD(c1); + for (--p; *n != '\0'; ++n) + if ((c == '[' || FOLD(*n) == c1) && + fnmatch(p, n, flags & ~FNM_PERIOD) == 0) + return 0; + return FNM_NOMATCH; + } + + case '[': + { + /* Nonzero if the sense of the character class is inverted. */ + register int not; + + if (*n == '\0') + return FNM_NOMATCH; + + if ((flags & FNM_PERIOD) && *n == '.' && + (n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/'))) + return FNM_NOMATCH; + + not = (*p == '!' || *p == '^'); + if (not) + ++p; + + c = *p++; + for (;;) { + register char cstart = c, cend = c; + + if (!(flags & FNM_NOESCAPE) && c == '\\') { + if (*p == '\0') + return FNM_NOMATCH; + cstart = cend = *p++; + } + + cstart = cend = FOLD(cstart); + + if (c == '\0') + /* [ (unterminated) loses. */ + return FNM_NOMATCH; + + c = *p++; + c = FOLD(c); + + if ((flags & FNM_FILE_NAME) && c == '/') + /* [/] can never match. */ + return FNM_NOMATCH; + + if (c == '-' && *p != ']') { + cend = *p++; + if (!(flags & FNM_NOESCAPE) && cend == '\\') + cend = *p++; + if (cend == '\0') + return FNM_NOMATCH; + cend = FOLD(cend); + + c = *p++; + } + + if (FOLD(*n) >= cstart && FOLD(*n) <= cend) + goto matched; + + if (c == ']') + break; + } + if (!not) + return FNM_NOMATCH; + break; + + matched:; + /* Skip the rest of the [...] that already matched. */ + while (c != ']') { + if (c == '\0') + /* [... (unterminated) loses. */ + return FNM_NOMATCH; + + c = *p++; + if (!(flags & FNM_NOESCAPE) && c == '\\') { + if (*p == '\0') + return FNM_NOMATCH; + /* XXX 1003.2d11 is unclear if this is right. */ + ++p; + } + } + if (not) + return FNM_NOMATCH; + } + break; + + default: + if (c != FOLD(*n)) + return FNM_NOMATCH; + } + + ++n; + } + + if (*n == '\0') + return 0; + + if ((flags & FNM_LEADING_DIR) && *n == '/') + /* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz". */ + return 0; + + return FNM_NOMATCH; + +# undef FOLD +} +libc_hidden_def(fnmatch) +#endif /* _LIBC or not __GNU_LIBRARY__. */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ftw/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ftw/Makefile new file mode 100644 index 00000000..4a8f4a07 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ftw/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../ +top_builddir=../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ftw/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ftw/Makefile.in new file mode 100644 index 00000000..2edd8195 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ftw/Makefile.in @@ -0,0 +1,26 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +subdirs += libc/misc/ftw + +CSRC := ftw.c +ifeq ($(UCLIBC_HAS_LFS),y) +CSRC += ftw64.c +endif + +MISC_FTW_DIR := $(top_srcdir)libc/misc/ftw +MISC_FTW_OUT := $(top_builddir)libc/misc/ftw + +MISC_FTW_SRC := $(patsubst %.c,$(MISC_FTW_DIR)/%.c,$(CSRC)) +MISC_FTW_OBJ := $(patsubst %.c,$(MISC_FTW_OUT)/%.o,$(CSRC)) + +libc-$(findstring y,$(UCLIBC_HAS_FTW)$(UCLIBC_HAS_NFTW)) += $(MISC_FTW_OBJ) + +objclean-y += CLEAN_libc/misc/ftw + +CLEAN_libc/misc/ftw: + $(do_rm) $(addprefix $(MISC_FTW_OUT)/*., o os) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ftw/ftw.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ftw/ftw.c new file mode 100644 index 00000000..4a62e388 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ftw/ftw.c @@ -0,0 +1,807 @@ +/* File tree walker functions. + Copyright (C) 1996-2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1996. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#ifdef __UCLIBC__ +#undef _LIBC +#define HAVE_DIRENT_H 1 +#define HAVE_SYS_PARAM_H 1 +#define HAVE_DECL_STPCPY 1 +#define HAVE_MEMPCPY 1 +#endif + +#if __GNUC__ +# define alloca __builtin_alloca +#else +# if HAVE_ALLOCA_H +# include +# else +# ifdef _AIX + # pragma alloca +# else +char *alloca (); +# endif +# endif +#endif + +#if defined _LIBC +# include +# define NAMLEN(dirent) _D_EXACT_NAMLEN (dirent) +#else +# if HAVE_DIRENT_H +# include +# define NAMLEN(dirent) strlen ((dirent)->d_name) +# else +# define dirent direct +# define NAMLEN(dirent) (dirent)->d_namlen +# if HAVE_SYS_NDIR_H +# include +# endif +# if HAVE_SYS_DIR_H +# include +# endif +# if HAVE_NDIR_H +# include +# endif +# endif +#endif + +#include +#include +#include +#include +#include +#include +#include +#if HAVE_SYS_PARAM_H || defined _LIBC +# include +#endif +#ifdef _LIBC +# include +#else +# include +#endif + +#if !defined _LIBC && !HAVE_DECL_STPCPY && !defined stpcpy +char *stpcpy (); +#endif + +#if !defined _LIBC && ! defined HAVE_MEMPCPY && ! defined mempcpy +/* Be CAREFUL that there are no side effects in N. */ +# define mempcpy(D, S, N) ((void *) ((char *) memcpy (D, S, N) + (N))) +#endif + +/* #define NDEBUG 1 */ +#include + +#if !defined _LIBC +# undef __chdir +# define __chdir chdir +# undef __closedir +# define __closedir closedir +# undef __fchdir +# define __fchdir fchdir +# undef __getcwd +# ifndef __UCLIBC__ +# define __getcwd(P, N) xgetcwd () +extern char *xgetcwd (void); +# else +# define __getcwd getcwd +# endif +# undef __mempcpy +# define __mempcpy mempcpy +# undef __opendir +# define __opendir opendir +# undef __readdir64 +# ifndef __UCLIBC_HAS_LFS__ +# define __readdir64 readdir +# else +# define __readdir64 readdir64 +# endif +# undef __stpcpy +# define __stpcpy stpcpy +# undef __tdestroy +# define __tdestroy tdestroy +# undef __tfind +# define __tfind tfind +# undef __tsearch +# define __tsearch tsearch +# undef internal_function +# define internal_function /* empty */ +# ifndef __UCLIBC_HAS_LFS__ +# undef dirent64 +# define dirent64 dirent +# endif +# undef MAX +# define MAX(a, b) ((a) > (b) ? (a) : (b)) +#endif + +/* Arrange to make lstat calls go through the wrapper function + on systems with an lstat function that does not dereference symlinks + that are specified with a trailing slash. */ +#if !defined _LIBC && !defined LSTAT_FOLLOWS_SLASHED_SYMLINK && !defined __UCLIBC__ +int rpl_lstat (const char *, struct stat *); +# undef lstat +# define lstat(Name, Stat_buf) rpl_lstat(Name, Stat_buf) +#endif + +#ifndef __set_errno +# define __set_errno(Val) errno = (Val) +#endif + +/* Support for the LFS API version. */ +#ifndef FTW_NAME +# define FTW_NAME ftw +# define NFTW_NAME nftw +# define NFTW_OLD_NAME __old_nftw +# define NFTW_NEW_NAME __new_nftw +# define INO_T ino_t +# define STAT stat +# ifdef _LIBC +# define LXSTAT __lxstat +# define XSTAT __xstat +# else +# define LXSTAT(V,f,sb) lstat (f,sb) +# define XSTAT(V,f,sb) stat (f,sb) +# endif +# define FTW_FUNC_T __ftw_func_t +# define NFTW_FUNC_T __nftw_func_t +#endif + +/* We define PATH_MAX if the system does not provide a definition. + This does not artificially limit any operation. PATH_MAX is simply + used as a guesstimate for the expected maximal path length. + Buffers will be enlarged if necessary. */ +#ifndef PATH_MAX +# define PATH_MAX 1024 +#endif + +struct dir_data +{ + DIR *stream; + char *content; +}; + +struct known_object +{ + dev_t dev; + INO_T ino; +}; + +struct ftw_data +{ + /* Array with pointers to open directory streams. */ + struct dir_data **dirstreams; + size_t actdir; + size_t maxdir; + + /* Buffer containing name of currently processed object. */ + char *dirbuf; + size_t dirbufsize; + + /* Passed as fourth argument to `nftw' callback. The `base' member + tracks the content of the `dirbuf'. */ + struct FTW ftw; + + /* Flags passed to `nftw' function. 0 for `ftw'. */ + int flags; + + /* Conversion array for flag values. It is the identity mapping for + `nftw' calls, otherwise it maps the values to those known by + `ftw'. */ + const int *cvt_arr; + + /* Callback function. We always use the `nftw' form. */ + NFTW_FUNC_T func; + + /* Device of starting point. Needed for FTW_MOUNT. */ + dev_t dev; + + /* Data structure for keeping fingerprints of already processed + object. This is needed when not using FTW_PHYS. */ + void *known_objects; +}; + + +/* Internally we use the FTW_* constants used for `nftw'. When invoked + as `ftw', map each flag to the subset of values used by `ftw'. */ +static const int nftw_arr[] = +{ + FTW_F, FTW_D, FTW_DNR, FTW_NS, FTW_SL, FTW_DP, FTW_SLN +}; + +static const int ftw_arr[] = +{ + FTW_F, FTW_D, FTW_DNR, FTW_NS, FTW_F, FTW_D, FTW_NS +}; + + +/* Forward declarations of local functions. */ +static int ftw_dir (struct ftw_data *data, struct STAT *st, + struct dir_data *old_dir) internal_function; + + +static int +object_compare (const void *p1, const void *p2) +{ + /* We don't need a sophisticated and useful comparison. We are only + interested in equality. However, we must be careful not to + accidentally compare `holes' in the structure. */ + const struct known_object *kp1 = p1, *kp2 = p2; + int cmp1; + cmp1 = (kp1->ino > kp2->ino) - (kp1->ino < kp2->ino); + if (cmp1 != 0) + return cmp1; + return (kp1->dev > kp2->dev) - (kp1->dev < kp2->dev); +} + + +static __inline__ int +add_object (struct ftw_data *data, struct STAT *st) +{ + struct known_object *newp = malloc (sizeof (struct known_object)); + if (newp == NULL) + return -1; + newp->dev = st->st_dev; + newp->ino = st->st_ino; + return __tsearch (newp, &data->known_objects, object_compare) ? 0 : -1; +} + + +static __inline__ int +find_object (struct ftw_data *data, struct STAT *st) +{ + struct known_object obj; + obj.dev = st->st_dev; + obj.ino = st->st_ino; + return __tfind (&obj, &data->known_objects, object_compare) != NULL; +} + + +static __inline__ int +__attribute ((always_inline)) +open_dir_stream (struct ftw_data *data, struct dir_data *dirp) +{ + int result = 0; + + if (data->dirstreams[data->actdir] != NULL) + { + /* Oh, oh. We must close this stream. Get all remaining + entries and store them as a list in the `content' member of + the `struct dir_data' variable. */ + size_t bufsize = 1024; + char *buf = malloc (bufsize); + + if (buf == NULL) + result = -1; + else + { + DIR *st = data->dirstreams[data->actdir]->stream; + struct dirent64 *d; + size_t actsize = 0; + + while ((d = __readdir64 (st)) != NULL) + { + size_t this_len = NAMLEN (d); + if (actsize + this_len + 2 >= bufsize) + { + char *newp; + bufsize += MAX (1024, 2 * this_len); + newp = (char *) realloc (buf, bufsize); + if (newp == NULL) + { + /* No more memory. */ + int save_err = errno; + free (buf); + __set_errno (save_err); + result = -1; + break; + } + buf = newp; + } + + *((char *) __mempcpy (buf + actsize, d->d_name, this_len)) + = '\0'; + actsize += this_len + 1; + } + + /* Terminate the list with an additional NUL byte. */ + buf[actsize++] = '\0'; + + /* Shrink the buffer to what we actually need. */ + data->dirstreams[data->actdir]->content = realloc (buf, actsize); + if (data->dirstreams[data->actdir]->content == NULL) + { + int save_err = errno; + free (buf); + __set_errno (save_err); + result = -1; + } + else + { + __closedir (st); + data->dirstreams[data->actdir]->stream = NULL; + data->dirstreams[data->actdir] = NULL; + } + } + } + + /* Open the new stream. */ + if (result == 0) + { + const char *name = ((data->flags & FTW_CHDIR) + ? data->dirbuf + data->ftw.base: data->dirbuf); + assert (data->dirstreams[data->actdir] == NULL); + + dirp->stream = __opendir (name); + if (dirp->stream == NULL) + result = -1; + else + { + dirp->content = NULL; + data->dirstreams[data->actdir] = dirp; + + if (++data->actdir == data->maxdir) + data->actdir = 0; + } + } + + return result; +} + + +static int +internal_function +process_entry (struct ftw_data *data, struct dir_data *dir, const char *name, + size_t namlen) +{ + struct STAT st; + int result = 0; + int flag = 0; + size_t new_buflen; + + if (name[0] == '.' && (name[1] == '\0' + || (name[1] == '.' && name[2] == '\0'))) + /* Don't process the "." and ".." entries. */ + return 0; + + new_buflen = data->ftw.base + namlen + 2; + if (data->dirbufsize < new_buflen) + { + /* Enlarge the buffer. */ + char *newp; + + data->dirbufsize = 2 * new_buflen; + newp = (char *) realloc (data->dirbuf, data->dirbufsize); + if (newp == NULL) + return -1; + data->dirbuf = newp; + } + + *((char *) __mempcpy (data->dirbuf + data->ftw.base, name, namlen)) = '\0'; + + if ((data->flags & FTW_CHDIR) == 0) + name = data->dirbuf; + + if (((data->flags & FTW_PHYS) + ? LXSTAT (_STAT_VER, name, &st) + : XSTAT (_STAT_VER, name, &st)) < 0) + { + if (errno != EACCES && errno != ENOENT) + result = -1; + else if (!(data->flags & FTW_PHYS) + && LXSTAT (_STAT_VER, name, &st) == 0 + && S_ISLNK (st.st_mode)) + flag = FTW_SLN; + else + flag = FTW_NS; + } + else + { + if (S_ISDIR (st.st_mode)) + flag = FTW_D; + else if (S_ISLNK (st.st_mode)) + flag = FTW_SL; + else + flag = FTW_F; + } + + if (result == 0 + && (flag == FTW_NS + || !(data->flags & FTW_MOUNT) || st.st_dev == data->dev)) + { + if (flag == FTW_D) + { + if ((data->flags & FTW_PHYS) + || (!find_object (data, &st) + /* Remember the object. */ + && (result = add_object (data, &st)) == 0)) + result = ftw_dir (data, &st, dir); + } + else + result = (*data->func) (data->dirbuf, &st, data->cvt_arr[flag], + &data->ftw); + } + + if ((data->flags & FTW_ACTIONRETVAL) && result == FTW_SKIP_SUBTREE) + result = 0; + + return result; +} + + +static int +__attribute ((noinline)) +internal_function +ftw_dir (struct ftw_data *data, struct STAT *st, struct dir_data *old_dir) +{ + struct dir_data dir; + struct dirent64 *d; + int previous_base = data->ftw.base; + int result; + char *startp; + + /* Open the stream for this directory. This might require that + another stream has to be closed. */ + result = open_dir_stream (data, &dir); + if (result != 0) + { + if (errno == EACCES) + /* We cannot read the directory. Signal this with a special flag. */ + result = (*data->func) (data->dirbuf, st, FTW_DNR, &data->ftw); + + return result; + } + + /* First, report the directory (if not depth-first). */ + if (!(data->flags & FTW_DEPTH)) + { + result = (*data->func) (data->dirbuf, st, FTW_D, &data->ftw); + if (result != 0) + { + int save_err; +fail: + save_err = errno; + __closedir (dir.stream); + __set_errno (save_err); + + if (data->actdir-- == 0) + data->actdir = data->maxdir - 1; + data->dirstreams[data->actdir] = NULL; + return result; + } + } + + /* If necessary, change to this directory. */ + if (data->flags & FTW_CHDIR) + { + if (__fchdir (dirfd (dir.stream)) < 0) + { + result = -1; + goto fail; + } + } + + /* Next, update the `struct FTW' information. */ + ++data->ftw.level; + startp = strchr (data->dirbuf, '\0'); + /* There always must be a directory name. */ + assert (startp != data->dirbuf); + if (startp[-1] != '/') + *startp++ = '/'; + data->ftw.base = startp - data->dirbuf; + + while (dir.stream != NULL && (d = __readdir64 (dir.stream)) != NULL) + { + result = process_entry (data, &dir, d->d_name, NAMLEN (d)); + if (result != 0) + break; + } + + if (dir.stream != NULL) + { + /* The stream is still open. I.e., we did not need more + descriptors. Simply close the stream now. */ + int save_err = errno; + + assert (dir.content == NULL); + + __closedir (dir.stream); + __set_errno (save_err); + + if (data->actdir-- == 0) + data->actdir = data->maxdir - 1; + data->dirstreams[data->actdir] = NULL; + } + else + { + int save_err; + char *runp = dir.content; + + while (result == 0 && *runp != '\0') + { + char *endp = strchr (runp, '\0'); + + result = process_entry (data, &dir, runp, endp - runp); + + runp = endp + 1; + } + + save_err = errno; + free (dir.content); + __set_errno (save_err); + } + + if ((data->flags & FTW_ACTIONRETVAL) && result == FTW_SKIP_SIBLINGS) + result = 0; + + /* Prepare the return, revert the `struct FTW' information. */ + data->dirbuf[data->ftw.base - 1] = '\0'; + --data->ftw.level; + data->ftw.base = previous_base; + + /* Finally, if we process depth-first report the directory. */ + if (result == 0 && (data->flags & FTW_DEPTH)) + result = (*data->func) (data->dirbuf, st, FTW_DP, &data->ftw); + + if (old_dir + && (data->flags & FTW_CHDIR) + && (result == 0 + || ((data->flags & FTW_ACTIONRETVAL) + && (result != -1 && result != FTW_STOP)))) + { + /* Change back to the parent directory. */ + int done = 0; + if (old_dir->stream != NULL) + if (__fchdir (dirfd (old_dir->stream)) == 0) + done = 1; + + if (!done) + { + if (data->ftw.base == 1) + { + if (__chdir ("/") < 0) + result = -1; + } + else + if (__chdir ("..") < 0) + result = -1; + } + } + + return result; +} + + +static int +__attribute ((noinline)) +internal_function +ftw_startup (const char *dir, int is_nftw, void *func, int descriptors, + int flags) +{ + struct ftw_data data; + struct STAT st; + int result = 0; + int save_err; + char *cwd = NULL; + char *cp; + + /* First make sure the parameters are reasonable. */ + if (dir[0] == '\0') + { + __set_errno (ENOENT); + return -1; + } + + data.maxdir = descriptors < 1 ? 1 : descriptors; + data.actdir = 0; + data.dirstreams = (struct dir_data **) alloca (data.maxdir + * sizeof (struct dir_data *)); + memset (data.dirstreams, '\0', data.maxdir * sizeof (struct dir_data *)); + + /* PATH_MAX is always defined when we get here. */ + data.dirbufsize = MAX (2 * strlen (dir), PATH_MAX); + data.dirbuf = (char *) malloc (data.dirbufsize); + if (data.dirbuf == NULL) + return -1; + cp = __stpcpy (data.dirbuf, dir); + /* Strip trailing slashes. */ + while (cp > data.dirbuf + 1 && cp[-1] == '/') + --cp; + *cp = '\0'; + + data.ftw.level = 0; + + /* Find basename. */ + while (cp > data.dirbuf && cp[-1] != '/') + --cp; + data.ftw.base = cp - data.dirbuf; + + data.flags = flags; + + /* This assignment might seem to be strange but it is what we want. + The trick is that the first three arguments to the `ftw' and + `nftw' callback functions are equal. Therefore we can call in + every case the callback using the format of the `nftw' version + and get the correct result since the stack layout for a function + call in C allows this. */ + data.func = (NFTW_FUNC_T) func; + + /* Since we internally use the complete set of FTW_* values we need + to reduce the value range before calling a `ftw' callback. */ + data.cvt_arr = is_nftw ? nftw_arr : ftw_arr; + + /* No object known so far. */ + data.known_objects = NULL; + + /* Now go to the directory containing the initial file/directory. */ + if (flags & FTW_CHDIR) + { + /* GNU extension ahead. */ + cwd = __getcwd (NULL, 0); + if (cwd == NULL) + result = -1; + else if (data.ftw.base > 0) + { + /* Change to the directory the file is in. In data.dirbuf + we have a writable copy of the file name. Just NUL + terminate it for now and change the directory. */ + if (data.ftw.base == 1) + /* I.e., the file is in the root directory. */ + result = __chdir ("/"); + else + { + char ch = data.dirbuf[data.ftw.base - 1]; + data.dirbuf[data.ftw.base - 1] = '\0'; + result = __chdir (data.dirbuf); + data.dirbuf[data.ftw.base - 1] = ch; + } + } + } + + /* Get stat info for start directory. */ + if (result == 0) + { + const char *name = ((data.flags & FTW_CHDIR) + ? data.dirbuf + data.ftw.base + : data.dirbuf); + + if (((flags & FTW_PHYS) + ? LXSTAT (_STAT_VER, name, &st) + : XSTAT (_STAT_VER, name, &st)) < 0) + { + if (!(flags & FTW_PHYS) + && errno == ENOENT + && LXSTAT (_STAT_VER, name, &st) == 0 + && S_ISLNK (st.st_mode)) + result = (*data.func) (data.dirbuf, &st, data.cvt_arr[FTW_SLN], + &data.ftw); + else + /* No need to call the callback since we cannot say anything + about the object. */ + result = -1; + } + else + { + if (S_ISDIR (st.st_mode)) + { + /* Remember the device of the initial directory in case + FTW_MOUNT is given. */ + data.dev = st.st_dev; + + /* We know this directory now. */ + if (!(flags & FTW_PHYS)) + result = add_object (&data, &st); + + if (result == 0) + result = ftw_dir (&data, &st, NULL); + } + else + { + int flag = S_ISLNK (st.st_mode) ? FTW_SL : FTW_F; + + result = (*data.func) (data.dirbuf, &st, data.cvt_arr[flag], + &data.ftw); + } + } + + if ((flags & FTW_ACTIONRETVAL) + && (result == FTW_SKIP_SUBTREE || result == FTW_SKIP_SIBLINGS)) + result = 0; + } + + /* Return to the start directory (if necessary). */ + if (cwd != NULL) + { + save_err = errno; + __chdir (cwd); + free (cwd); + __set_errno (save_err); + } + + /* Free all memory. */ + save_err = errno; + __tdestroy (data.known_objects, free); + free (data.dirbuf); + __set_errno (save_err); + + return result; +} + + + +/* Entry points. */ +#if __UCLIBC_HAS_FTW__ +int +FTW_NAME (const char *path, FTW_FUNC_T func, int descriptors) +{ + return ftw_startup (path, 0, func, descriptors, 0); +} +#endif + +#if __UCLIBC_HAS_NFTW__ +#ifndef _LIBC +int +NFTW_NAME (const char *path, NFTW_FUNC_T func, int descriptors, int flags) +{ + return ftw_startup (path, 1, func, descriptors, flags); +} +#else + +#include + +int NFTW_NEW_NAME (const char *, NFTW_FUNC_T, int, int); + +int +NFTW_NEW_NAME (const char *path, NFTW_FUNC_T func, int descriptors, int flags) +{ + if (flags + & ~(FTW_PHYS | FTW_MOUNT | FTW_CHDIR | FTW_DEPTH | FTW_ACTIONRETVAL)) + { + __set_errno (EINVAL); + return -1; + } + return ftw_startup (path, 1, func, descriptors, flags); +} + +versioned_symbol (libc, NFTW_NEW_NAME, NFTW_NAME, GLIBC_2_3_3); + +#if SHLIB_COMPAT(libc, GLIBC_2_1, GLIBC_2_3_3) + +/* Older nftw* version just ignored all unknown flags. */ + +int NFTW_OLD_NAME (const char *, NFTW_FUNC_T, int, int); + +int +attribute_compat_text_section +NFTW_OLD_NAME (const char *path, NFTW_FUNC_T func, int descriptors, int flags) +{ + flags &= (FTW_PHYS | FTW_MOUNT | FTW_CHDIR | FTW_DEPTH); + return ftw_startup (path, 1, func, descriptors, flags); +} + +compat_symbol (libc, NFTW_OLD_NAME, NFTW_NAME, GLIBC_2_1); +#endif +#endif +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ftw/ftw64.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ftw/ftw64.c new file mode 100644 index 00000000..de2fe22d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ftw/ftw64.c @@ -0,0 +1,32 @@ +/* File tree walker functions. LFS version. + Copyright (C) 1996, 1997, 1998, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1996. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define FTW_NAME ftw64 +#define NFTW_NAME nftw64 +#define NFTW_OLD_NAME __old_nftw64 +#define NFTW_NEW_NAME __new_nftw64 +#define INO_T ino64_t +#define STAT stat64 +#define LXSTAT(V,f,sb) lstat64(f,sb) +#define XSTAT(V,f,sb) stat64(f,sb) +#define FTW_FUNC_T __ftw64_func_t +#define NFTW_FUNC_T __nftw64_func_t + +#include "ftw.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/glob/.indent.pro b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/glob/.indent.pro new file mode 100644 index 00000000..492ecf1c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/glob/.indent.pro @@ -0,0 +1,33 @@ +--blank-lines-after-declarations +--blank-lines-after-procedures +--break-before-boolean-operator +--no-blank-lines-after-commas +--braces-on-if-line +--braces-on-struct-decl-line +--comment-indentation25 +--declaration-comment-column25 +--no-comment-delimiters-on-blank-lines +--cuddle-else +--continuation-indentation4 +--case-indentation0 +--else-endif-column33 +--space-after-cast +--line-comments-indentation0 +--declaration-indentation1 +--dont-format-first-column-comments +--dont-format-comments +--honour-newlines +--indent-level4 +/* changed from 0 to 4 */ +--parameter-indentation4 +--line-length78 /* changed from 75 */ +--continue-at-parentheses +--no-space-after-function-call-names +--dont-break-procedure-type +--dont-star-comments +--leave-optional-blank-lines +--dont-space-special-semicolon +--tab-size4 +/* additions by Mark */ +--case-brace-indentation0 +--leave-preprocessor-space diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/glob/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/glob/Makefile new file mode 100644 index 00000000..4a8f4a07 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/glob/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../ +top_builddir=../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/glob/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/glob/Makefile.in new file mode 100644 index 00000000..03bfcca3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/glob/Makefile.in @@ -0,0 +1,33 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +subdirs += libc/misc/glob + +ifeq ($(UCLIBC_HAS_GNU_GLOB),y) +CSRC := glob.c +ifeq ($(UCLIBC_HAS_LFS),y) +CSRC += glob64.c +endif +else +CSRC := glob-susv3.c +ifeq ($(UCLIBC_HAS_LFS),y) +CSRC += glob64-susv3.c +endif +endif + +MISC_GLOB_DIR := $(top_srcdir)libc/misc/glob +MISC_GLOB_OUT := $(top_builddir)libc/misc/glob + +MISC_GLOB_SRC := $(patsubst %.c,$(MISC_GLOB_DIR)/%.c,$(CSRC)) +MISC_GLOB_OBJ := $(patsubst %.c,$(MISC_GLOB_OUT)/%.o,$(CSRC)) + +libc-$(UCLIBC_HAS_GLOB) += $(MISC_GLOB_OBJ) + +objclean-y += CLEAN_libc/misc/glob + +CLEAN_libc/misc/glob: + $(do_rm) $(addprefix $(MISC_GLOB_OUT)/*., o os) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/glob/glob-susv3.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/glob/glob-susv3.c new file mode 100644 index 00000000..59b4d8e5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/glob/glob-susv3.c @@ -0,0 +1,299 @@ +/* + * Copyright (C) 2006 Rich Felker + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +#ifdef __UCLIBC_HAS_LFS__ +# define BUILD_GLOB64 +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + + +struct match +{ + struct match *next; + char name[1]; +}; + +#ifdef BUILD_GLOB64 +extern int __glob_is_literal(const char *p, int useesc) attribute_hidden; +extern int __glob_append(struct match **tail, const char *name, size_t len, int mark) attribute_hidden; +extern int __glob_ignore_err(const char *path, int err) attribute_hidden; +extern void __glob_freelist(struct match *head) attribute_hidden; +extern int __glob_sort(const void *a, const void *b) attribute_hidden; +extern int __glob_match_in_dir(const char *d, const char *p, int flags, int (*errfunc)(const char *path, int err), struct match **tail) attribute_hidden; +#endif + +#ifdef __UCLIBC_HAS_LFS__ +# define stat stat64 +# define readdir_r readdir64_r +# define dirent dirent64 +# define struct_stat struct stat64 +#else +# define struct_stat struct stat +#endif + +/* keep only one copy of these */ +#ifndef __GLOB64 + +# ifndef BUILD_GLOB64 +static +# endif +int __glob_is_literal(const char *p, int useesc) +{ + int bracket = 0; + for (; *p; p++) { + switch (*p) { + case '\\': + if (!useesc) break; + case '?': + case '*': + return 0; + case '[': + bracket = 1; + break; + case ']': + if (bracket) return 0; + break; + } + } + return 1; +} + +# ifndef BUILD_GLOB64 +static +# endif +int __glob_append(struct match **tail, const char *name, size_t len, int mark) +{ + struct match *new = malloc(sizeof(struct match) + len + 1); + if (!new) return -1; + (*tail)->next = new; + new->next = NULL; + strcpy(new->name, name); + if (mark) strcat(new->name, "/"); + *tail = new; + return 0; +} + +# ifndef BUILD_GLOB64 +static +# endif +int __glob_match_in_dir(const char *d, const char *p, int flags, int (*errfunc)(const char *path, int err), struct match **tail) +{ + DIR *dir; + long long de_buf[(sizeof(struct dirent) + NAME_MAX + sizeof(long long))/sizeof(long long)]; + struct dirent *de; + char pat[strlen(p)+1]; + char *p2; + size_t l = strlen(d); + int literal; + int fnm_flags= ((flags & GLOB_NOESCAPE) ? FNM_NOESCAPE : 0) | FNM_PERIOD; + int error; + + if ((p2 = strchr(p, '/'))) { + strcpy(pat, p); + pat[p2-p] = 0; + for (; *p2 == '/'; p2++); + p = pat; + } + literal = __glob_is_literal(p, !(flags & GLOB_NOESCAPE)); + if (*d == '/' && !*(d+1)) l = 0; + + /* rely on opendir failing for nondirectory objects */ + dir = opendir(*d ? d : "."); + error = errno; + if (!dir) { + /* this is not an error -- we let opendir call stat for us */ + if (error == ENOTDIR) return 0; + if (error == EACCES && !*p) { + struct_stat st; + if (!stat(d, &st) && S_ISDIR(st.st_mode)) { + if (__glob_append(tail, d, l, l)) + return GLOB_NOSPACE; + return 0; + } + } + if (errfunc(d, error) || (flags & GLOB_ERR)) + return GLOB_ABORTED; + return 0; + } + if (!*p) { + error = __glob_append(tail, d, l, l) ? GLOB_NOSPACE : 0; + closedir(dir); + return error; + } + while (!(error = readdir_r(dir, (void *)de_buf, &de)) && de) { + char namebuf[l+de->d_reclen+2], *name = namebuf; + if (!literal && fnmatch(p, de->d_name, fnm_flags)) + continue; + if (literal && strcmp(p, de->d_name)) + continue; + if (p2 && de->d_type && !S_ISDIR(de->d_type<<12) && !S_ISLNK(de->d_type<<12)) + continue; + if (*d) { + memcpy(name, d, l); + name[l] = '/'; + strcpy(name+l+1, de->d_name); + } else { + name = de->d_name; + } + if (p2) { + if ((error = __glob_match_in_dir(name, p2, flags, errfunc, tail))) { + closedir(dir); + return error; + } + } else { + int mark = 0; + if (flags & GLOB_MARK) { + if (de->d_type) + mark = S_ISDIR(de->d_type<<12); + else { + struct_stat st; + stat(name, &st); + mark = S_ISDIR(st.st_mode); + } + } + if (__glob_append(tail, name, l+de->d_reclen+1, mark)) { + closedir(dir); + return GLOB_NOSPACE; + } + } + } + closedir(dir); + if (error && (errfunc(d, error) || (flags & GLOB_ERR))) + return GLOB_ABORTED; + return 0; +} + +# ifndef BUILD_GLOB64 +static +# endif +int __glob_ignore_err(const char * path attribute_unused, + int err attribute_unused) +{ + return 0; +} + +# ifndef BUILD_GLOB64 +static +# endif +void __glob_freelist(struct match *head) +{ + struct match *match, *next; + for (match=head->next; match; match=next) { + next = match->next; + free(match); + } +} + +# ifndef BUILD_GLOB64 +static +# endif +int __glob_sort(const void *a, const void *b) +{ + return strcmp(*(const char **)a, *(const char **)b); +} +#endif /* !__GLOB64 */ + +int glob(const char *pat, int flags, int (*errfunc)(const char *path, int err), glob_t *g) +{ + const char *p=pat, *d; + struct match head = { .next = NULL }, *tail = &head; + size_t cnt, i; + size_t offs = (flags & GLOB_DOOFFS) ? g->gl_offs : 0; + int error = 0; + + if (*p == '/') { + for (; *p == '/'; p++); + d = "/"; + } else { + d = ""; + } + + if (!errfunc) errfunc = __glob_ignore_err; + + if (!(flags & GLOB_APPEND)) { + g->gl_offs = offs; + g->gl_pathc = 0; + g->gl_pathv = NULL; + } + + if (*p) error = __glob_match_in_dir(d, p, flags, errfunc, &tail); + if (error == GLOB_NOSPACE) { + __glob_freelist(&head); + return error; + } + + for (cnt=0, tail=head.next; tail; tail=tail->next, cnt++); + if (!cnt) { + if (flags & GLOB_NOCHECK) { + tail = &head; + if (__glob_append(&tail, pat, strlen(pat), 0)) + return GLOB_NOSPACE; + cnt++; + } else + return GLOB_NOMATCH; + } + + if (flags & GLOB_APPEND) { + char **pathv = realloc(g->gl_pathv, (offs + g->gl_pathc + cnt + 1) * sizeof(char *)); + if (!pathv) { + __glob_freelist(&head); + return GLOB_NOSPACE; + } + g->gl_pathv = pathv; + offs += g->gl_pathc; + } else { + g->gl_pathv = malloc((offs + cnt + 1) * sizeof(char *)); + if (!g->gl_pathv) { + __glob_freelist(&head); + return GLOB_NOSPACE; + } + for (i=0; igl_pathv[i] = NULL; + } + for (i=0, tail=head.next; inext, i++) + g->gl_pathv[offs + i] = tail->name; + g->gl_pathv[offs + i] = NULL; + g->gl_pathc += cnt; + + if (!(flags & GLOB_NOSORT)) + qsort(g->gl_pathv+offs, cnt, sizeof(char *), __glob_sort); + + return error; +} +#ifdef __GLOB64 +libc_hidden_def(glob64) +#else +libc_hidden_def(glob) +#endif + +void globfree(glob_t *g) +{ + size_t i; + for (i=0; igl_pathc; i++) + free(g->gl_pathv[g->gl_offs + i] - offsetof(struct match, name)); + free(g->gl_pathv); + g->gl_pathc = 0; + g->gl_pathv = NULL; +} +#ifdef __GLOB64 +libc_hidden_def(globfree64) +#else +libc_hidden_def(globfree) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/glob/glob.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/glob/glob.c new file mode 100644 index 00000000..488f2297 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/glob/glob.c @@ -0,0 +1,1067 @@ +/* Copyright (C) 1991-2002,2003,2004,2005,2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#undef ENABLE_GLOB_BRACE_EXPANSION +#undef ENABLE_GLOB_TILDE_EXPANSION + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + + +#ifdef ENABLE_GLOB_TILDE_EXPANSION +#include +#endif + +#ifdef COMPILE_GLOB64 +#undef stat +#define stat stat64 +#define struct_stat64 struct stat64 +#define __stat64(fname, buf) stat64 (fname, buf) +#define dirent dirent64 +#define __readdir readdir64 +#define __readdir64 readdir64 +#define glob_t glob64_t +#define glob(pattern, flags, errfunc, pglob) glob64 (pattern, flags, errfunc, pglob) +#define globfree(pglob) globfree64 (pglob) +#else +#define __readdir readdir +#ifdef __UCLIBC_HAS_LFS__ +#define __readdir64 readdir64 +#else +#define __readdir64 readdir +#endif +#define struct_stat64 struct stat +#define __stat64(fname, buf) stat (fname, buf) +#endif + + +/* When used in the GNU libc the symbol _DIRENT_HAVE_D_TYPE is available + if the `d_type' member for `struct dirent' is available. + HAVE_STRUCT_DIRENT_D_TYPE plays the same role in GNULIB. */ +#if defined _DIRENT_HAVE_D_TYPE +/* True if the directory entry D must be of type T. */ +# define DIRENT_MUST_BE(d, t) ((d)->d_type == (t)) + +/* True if the directory entry D might be a symbolic link. */ +# define DIRENT_MIGHT_BE_SYMLINK(d) \ + ((d)->d_type == DT_UNKNOWN || (d)->d_type == DT_LNK) + +/* True if the directory entry D might be a directory. */ +# define DIRENT_MIGHT_BE_DIR(d) \ + ((d)->d_type == DT_DIR || DIRENT_MIGHT_BE_SYMLINK (d)) + +#else /* !HAVE_D_TYPE */ +# define DIRENT_MUST_BE(d, t) false +# define DIRENT_MIGHT_BE_SYMLINK(d) true +# define DIRENT_MIGHT_BE_DIR(d) true +#endif /* HAVE_D_TYPE */ + + +# define NAMLEN(dirent) strlen((dirent)->d_name) +#ifdef _D_NAMLEN +# undef NAMLEN +# define NAMLEN(d) _D_NAMLEN(d) +#endif + +# if defined _DIRENT_HAVE_D_NAMLEN +# define CONVERT_D_NAMLEN(d64, d32) (d64)->d_namlen = (d32)->d_namlen; +# else +# define CONVERT_D_NAMLEN(d64, d32) +# endif + +# define CONVERT_D_INO(d64, d32) (d64)->d_ino = (d32)->d_ino; + +# ifdef _DIRENT_HAVE_D_TYPE +# define CONVERT_D_TYPE(d64, d32) (d64)->d_type = (d32)->d_type; +# else +# define CONVERT_D_TYPE(d64, d32) +# endif + +# define CONVERT_DIRENT_DIRENT64(d64, d32) \ + memcpy ((d64)->d_name, (d32)->d_name, NAMLEN (d32) + 1); \ + CONVERT_D_NAMLEN (d64, d32) \ + CONVERT_D_INO (d64, d32) \ + CONVERT_D_TYPE (d64, d32) + +extern int __collated_compare (const void *a, const void *b) attribute_hidden; +extern int __prefix_array (const char *dirname, char **array, size_t n) attribute_hidden; +#if defined ENABLE_GLOB_BRACE_EXPANSION +extern const char *__next_brace_sub (const char *cp, int flags) attribute_hidden; +#endif + +#ifndef COMPILE_GLOB64 +/* Return nonzero if PATTERN contains any metacharacters. + Metacharacters can be quoted with backslashes if QUOTE is nonzero. */ +int glob_pattern_p(const char *pattern, int quote) +{ + register const char *p; + int open = 0; + + for (p = pattern; *p != '\0'; ++p) + switch (*p) + { + case '?': + case '*': + return 1; + + case '\\': + if (quote && p[1] != '\0') + ++p; + break; + + case '[': + open = 1; + break; + + case ']': + if (open) + return 1; + break; + } + + return 0; +} +libc_hidden_def(glob_pattern_p) + + +/* Do a collated comparison of A and B. */ +int __collated_compare (const void *a, const void *b) +{ + const char *const s1 = *(const char *const * const) a; + const char *const s2 = *(const char *const * const) b; + + if (s1 == s2) + return 0; + if (s1 == NULL) + return 1; + if (s2 == NULL) + return -1; + return strcoll (s1, s2); +} + + +/* Prepend DIRNAME to each of N members of ARRAY, replacing ARRAY's + elements in place. Return nonzero if out of memory, zero if successful. + A slash is inserted between DIRNAME and each elt of ARRAY, + unless DIRNAME is just "/". Each old element of ARRAY is freed. + If ADD_SLASH is non-zero, allocate one character more than + necessary, so that a slash can be appended later. */ +int __prefix_array (const char *dirname, char **array, size_t n) +{ + register size_t i; + size_t dirlen = strlen (dirname); +# define DIRSEP_CHAR '/' + + if (dirlen == 1 && dirname[0] == '/') + /* DIRNAME is just "/", so normal prepending would get us "//foo". + We want "/foo" instead, so don't prepend any chars from DIRNAME. */ + dirlen = 0; + + for (i = 0; i < n; ++i) + { + size_t eltlen = strlen (array[i]) + 1; + char *new = (char *) malloc (dirlen + 1 + eltlen); + if (new == NULL) + { + while (i > 0) + free (array[--i]); + return 1; + } + + { + char *endp = mempcpy (new, dirname, dirlen); + *endp++ = DIRSEP_CHAR; + mempcpy (endp, array[i], eltlen); + } + free (array[i]); + array[i] = new; + } + + return 0; +} + +#if defined ENABLE_GLOB_BRACE_EXPANSION +/* Find the end of the sub-pattern in a brace expression. */ +const char * +__next_brace_sub (const char *cp, int flags) +{ + unsigned int depth = 0; + while (*cp != '\0') + if ((flags & GLOB_NOESCAPE) == 0 && *cp == '\\') + { + if (*++cp == '\0') + break; + ++cp; + } + else + { + if ((*cp == '}' && depth-- == 0) || (*cp == ',' && depth == 0)) + break; + + if (*cp++ == '{') + depth++; + } + + return *cp != '\0' ? cp : NULL; +} +#endif +#endif + + +static int +link_exists_p (const char *dir, size_t dirlen, const char *fname, + glob_t *pglob, int flags) +{ + size_t fnamelen = strlen (fname); + char *fullname = (char *) alloca (dirlen + 1 + fnamelen + 1); + struct stat st; + struct_stat64 st64; + + mempcpy (mempcpy (mempcpy (fullname, dir, dirlen), "/", 1), + fname, fnamelen + 1); + + return (((flags & GLOB_ALTDIRFUNC) + ? (*pglob->gl_stat) (fullname, &st) + : __stat64 (fullname, &st64)) == 0); +} + +/* Like `glob', but PATTERN is a final pathname component, + and matches are searched for in DIRECTORY. + The GLOB_NOSORT bit in FLAGS is ignored. No sorting is ever done. + The GLOB_APPEND flag is assumed to be set (always appends). */ +static int glob_in_dir (const char *pattern, const char *directory, int flags, + int (*errfunc) (const char *, int), + glob_t *pglob) +{ + size_t dirlen = strlen (directory); + void *stream = NULL; + struct globlink + { + struct globlink *next; + char *name; + }; + struct globlink *names = NULL; + size_t nfound; + int meta; + int save; + + meta = glob_pattern_p (pattern, !(flags & GLOB_NOESCAPE)); + if (meta == 0 && (flags & (GLOB_NOCHECK|GLOB_NOMAGIC))) + { + /* We need not do any tests. The PATTERN contains no meta + characters and we must not return an error therefore the + result will always contain exactly one name. */ + flags |= GLOB_NOCHECK; + nfound = 0; + } + else if (meta == 0 && + ((flags & GLOB_NOESCAPE) || strchr (pattern, '\\') == NULL)) + { + /* Since we use the normal file functions we can also use stat() + to verify the file is there. */ + struct stat st; + struct_stat64 st64; + size_t patlen = strlen (pattern); + char *fullname = (char *) alloca (dirlen + 1 + patlen + 1); + + mempcpy (mempcpy (mempcpy (fullname, directory, dirlen), + "/", 1), + pattern, patlen + 1); + if (((flags & GLOB_ALTDIRFUNC) + ? (*pglob->gl_stat) (fullname, &st) + : __stat64 (fullname, &st64)) == 0) + /* We found this file to be existing. Now tell the rest + of the function to copy this name into the result. */ + flags |= GLOB_NOCHECK; + + nfound = 0; + } + else + { + if (pattern[0] == '\0') + { + /* This is a special case for matching directories like in + "*a/". */ + names = (struct globlink *) alloca (sizeof (struct globlink)); + names->name = (char *) malloc (1); + if (names->name == NULL) + goto memory_error; + names->name[0] = '\0'; + names->next = NULL; + nfound = 1; + meta = 0; + } + else + { + stream = ((flags & GLOB_ALTDIRFUNC) + ? (*pglob->gl_opendir) (directory) + : opendir (directory)); + if (stream == NULL) + { + if (errno != ENOTDIR + && ((errfunc != NULL && (*errfunc) (directory, errno)) + || (flags & GLOB_ERR))) + return GLOB_ABORTED; + nfound = 0; + meta = 0; + } + else + { + int fnm_flags = ((!(flags & GLOB_PERIOD) ? FNM_PERIOD : 0) + | ((flags & GLOB_NOESCAPE) ? FNM_NOESCAPE : 0) + ); + nfound = 0; + flags |= GLOB_MAGCHAR; + + while (1) + { + const char *name; + size_t len; +#if defined __UCLIBC_HAS_LFS__ && !defined COMPILE_GLOB64 + struct dirent64 *d; + union + { + struct dirent64 d64; + char room [offsetof (struct dirent64, d_name[0]) + + NAME_MAX + 1]; + } + d64buf; + + if (flags & GLOB_ALTDIRFUNC) + { + struct dirent *d32 = (*pglob->gl_readdir) (stream); + if (d32 != NULL) + { + CONVERT_DIRENT_DIRENT64 (&d64buf.d64, d32); + d = &d64buf.d64; + } + else + d = NULL; + } + else + d = __readdir64 (stream); +#else + struct dirent *d = ((flags & GLOB_ALTDIRFUNC) + ? ((struct dirent *) + (*pglob->gl_readdir) (stream)) + : __readdir (stream)); +#endif + if (d == NULL) + break; +# define REAL_DIR_ENTRY(dp) (dp->d_ino != 0) + if (! REAL_DIR_ENTRY (d)) + continue; + + /* If we shall match only directories use the information + provided by the dirent call if possible. */ + if ((flags & GLOB_ONLYDIR) && !DIRENT_MIGHT_BE_DIR (d)) + continue; + + name = d->d_name; + + if (fnmatch (pattern, name, fnm_flags) == 0) + { + /* If the file we found is a symlink we have to + make sure the target file exists. */ + if (!DIRENT_MIGHT_BE_SYMLINK (d) + || link_exists_p (directory, dirlen, name, pglob, + flags)) + { + struct globlink *new = (struct globlink *) + alloca (sizeof (struct globlink)); + len = NAMLEN (d); + new->name = (char *) malloc (len + 1); + if (new->name == NULL) + goto memory_error; + *((char *) mempcpy (new->name, name, len)) = '\0'; + new->next = names; + names = new; + ++nfound; + } + } + } + } + } + } + + if (nfound == 0 && (flags & GLOB_NOCHECK)) + { + size_t len = strlen (pattern); + nfound = 1; + names = (struct globlink *) alloca (sizeof (struct globlink)); + names->next = NULL; + names->name = (char *) malloc (len + 1); + if (names->name == NULL) + goto memory_error; + *((char *) mempcpy (names->name, pattern, len)) = '\0'; + } + + if (nfound != 0) + { + char **new_gl_pathv; + + new_gl_pathv + = (char **) realloc (pglob->gl_pathv, + (pglob->gl_pathc + pglob->gl_offs + nfound + 1) + * sizeof (char *)); + if (new_gl_pathv == NULL) + goto memory_error; + pglob->gl_pathv = new_gl_pathv; + + for (; names != NULL; names = names->next) + pglob->gl_pathv[pglob->gl_offs + pglob->gl_pathc++] = names->name; + pglob->gl_pathv[pglob->gl_offs + pglob->gl_pathc] = NULL; + + pglob->gl_flags = flags; + } + + save = errno; + if (stream != NULL) + { + if (flags & GLOB_ALTDIRFUNC) + (*pglob->gl_closedir) (stream); + else + closedir (stream); + } + __set_errno (save); + + return nfound == 0 ? GLOB_NOMATCH : 0; + + memory_error: + { + int save2 = errno; + if (flags & GLOB_ALTDIRFUNC) + (*pglob->gl_closedir) (stream); + else + closedir (stream); + __set_errno (save2); + } + while (names != NULL) + { + free (names->name); + names = names->next; + } + return GLOB_NOSPACE; +} + +/* Do glob searching for PATTERN, placing results in PGLOB. + The bits defined above may be set in FLAGS. + If a directory cannot be opened or read and ERRFUNC is not nil, + it is called with the pathname that caused the error, and the + `errno' value from the failing call; if it returns non-zero + `glob' returns GLOB_ABEND; if it returns zero, the error is ignored. + If memory cannot be allocated for PGLOB, GLOB_NOSPACE is returned. + Otherwise, `glob' returns zero. */ +int +glob ( + const char *pattern, + int flags, + int (*errfunc) (const char *, int), + glob_t *pglob) +{ + const char *filename; + const char *dirname; + size_t dirlen; + int status; + size_t oldcount; + + if (pattern == NULL || pglob == NULL || (flags & ~__GLOB_FLAGS) != 0) + { + __set_errno (EINVAL); + return -1; + } + + + if (!(flags & GLOB_DOOFFS)) + /* Have to do this so `globfree' knows where to start freeing. It + also makes all the code that uses gl_offs simpler. */ + pglob->gl_offs = 0; + +#if defined ENABLE_GLOB_BRACE_EXPANSION + if (flags & GLOB_BRACE) + { + const char *begin; + + if (flags & GLOB_NOESCAPE) + begin = strchr (pattern, '{'); + else + { + begin = pattern; + while (1) + { + if (*begin == '\0') + { + begin = NULL; + break; + } + + if (*begin == '\\' && begin[1] != '\0') + ++begin; + else if (*begin == '{') + break; + + ++begin; + } + } + + if (begin != NULL) + { + /* Allocate working buffer large enough for our work. Note that + we have at least an opening and closing brace. */ + size_t firstc; + char *alt_start; + const char *p; + const char *next; + const char *rest; + size_t rest_len; + char onealt[strlen (pattern) - 1]; + + /* We know the prefix for all sub-patterns. */ + alt_start = mempcpy (onealt, pattern, begin - pattern); + + /* Find the first sub-pattern and at the same time find the + rest after the closing brace. */ + next = __next_brace_sub (begin + 1, flags); + if (next == NULL) + { + /* It is an illegal expression. */ + return glob (pattern, flags & ~GLOB_BRACE, errfunc, pglob); + } + + /* Now find the end of the whole brace expression. */ + rest = next; + while (*rest != '}') + { + rest = __next_brace_sub (rest + 1, flags); + if (rest == NULL) + { + /* It is an illegal expression. */ + return glob (pattern, flags & ~GLOB_BRACE, errfunc, pglob); + } + } + /* Please note that we now can be sure the brace expression + is well-formed. */ + rest_len = strlen (++rest) + 1; + + /* We have a brace expression. BEGIN points to the opening {, + NEXT points past the terminator of the first element, and END + points past the final }. We will accumulate result names from + recursive runs for each brace alternative in the buffer using + GLOB_APPEND. */ + + if (!(flags & GLOB_APPEND)) + { + /* This call is to set a new vector, so clear out the + vector so we can append to it. */ + pglob->gl_pathc = 0; + pglob->gl_pathv = NULL; + } + firstc = pglob->gl_pathc; + + p = begin + 1; + while (1) + { + int result; + + /* Construct the new glob expression. */ + mempcpy (mempcpy (alt_start, p, next - p), rest, rest_len); + + result = glob (onealt, + ((flags & ~(GLOB_NOCHECK | GLOB_NOMAGIC)) + | GLOB_APPEND), errfunc, pglob); + + /* If we got an error, return it. */ + if (result && result != GLOB_NOMATCH) + { + if (!(flags & GLOB_APPEND)) + { + globfree (pglob); + pglob->gl_pathc = 0; + } + return result; + } + + if (*next == '}') + /* We saw the last entry. */ + break; + + p = next + 1; + next = __next_brace_sub (p, flags); + /* assert (next != NULL); */ + } + + + if (pglob->gl_pathc != firstc) + /* We found some entries. */ + return 0; + else if (!(flags & (GLOB_NOCHECK|GLOB_NOMAGIC))) + return GLOB_NOMATCH; + } + } +#endif + + /* Find the filename. */ + filename = strrchr (pattern, '/'); + if (filename == NULL) + { + /* This can mean two things: a simple name or "~name". The latter + case is nothing but a notation for a directory. */ + if ((flags & (GLOB_TILDE|GLOB_TILDE_CHECK)) && pattern[0] == '~') + { + dirname = pattern; + dirlen = strlen (pattern); + + /* Set FILENAME to NULL as a special flag. This is ugly but + other solutions would require much more code. We test for + this special case below. */ + filename = NULL; + } + else + { + filename = pattern; + dirname = "."; + dirlen = 0; + } + } + else if (filename == pattern) + { + /* "/pattern". */ + dirname = "/"; + dirlen = 1; + ++filename; + } + else + { + char *newp; + dirlen = filename - pattern; + newp = (char *) alloca (dirlen + 1); + *((char *) mempcpy (newp, pattern, dirlen)) = '\0'; + dirname = newp; + ++filename; + + if (filename[0] == '\0' + && dirlen > 1) + /* "pattern/". Expand "pattern", appending slashes. */ + { + int val = glob (dirname, flags | GLOB_MARK, errfunc, pglob); + if (val == 0) + pglob->gl_flags = ((pglob->gl_flags & ~GLOB_MARK) + | (flags & GLOB_MARK)); + return val; + } + } + + if (!(flags & GLOB_APPEND)) + { + pglob->gl_pathc = 0; + if (!(flags & GLOB_DOOFFS)) + pglob->gl_pathv = NULL; + else + { + size_t i; + pglob->gl_pathv = (char **) malloc ((pglob->gl_offs + 1) + * sizeof (char *)); + if (pglob->gl_pathv == NULL) + return GLOB_NOSPACE; + + for (i = 0; i <= pglob->gl_offs; ++i) + pglob->gl_pathv[i] = NULL; + } + } + + oldcount = pglob->gl_pathc + pglob->gl_offs; + +#if defined ENABLE_GLOB_TILDE_EXPANSION + if ((flags & (GLOB_TILDE|GLOB_TILDE_CHECK)) && dirname[0] == '~') + { + if (dirname[1] == '\0' || dirname[1] == '/') + { + /* Look up home directory. */ + const char *home_dir = getenv ("HOME"); + if (home_dir == NULL || home_dir[0] == '\0') + { + int success; + char *name; +# define GET_LOGIN_NAME_MAX() sysconf (_SC_LOGIN_NAME_MAX) + size_t buflen = GET_LOGIN_NAME_MAX () + 1; + + if (buflen == 0) + /* `sysconf' does not support _SC_LOGIN_NAME_MAX. Try + a moderate value. */ + buflen = 20; + name = (char *) alloca (buflen); + + success = getlogin_r (name, buflen) == 0; + if (success) + { + struct passwd *p; +# define GETPW_R_SIZE_MAX() sysconf (_SC_GETPW_R_SIZE_MAX) + long int pwbuflen = GETPW_R_SIZE_MAX (); + char *pwtmpbuf; + struct passwd pwbuf; + int save = errno; + + pwtmpbuf = (char *) alloca (pwbuflen); + + while (getpwnam_r (name, &pwbuf, pwtmpbuf, pwbuflen, &p) + != 0) + { + if (errno != ERANGE) + { + p = NULL; + break; + } + pwtmpbuf = extend_alloca (pwtmpbuf, pwbuflen, + 2 * pwbuflen); + __set_errno (save); + } + if (p != NULL) + home_dir = p->pw_dir; + } + } + if (home_dir == NULL || home_dir[0] == '\0') + { + if (flags & GLOB_TILDE_CHECK) + return GLOB_NOMATCH; + else + home_dir = "~"; /* No luck. */ + } + /* Now construct the full directory. */ + if (dirname[1] == '\0') + dirname = home_dir; + else + { + char *newp; + size_t home_len = strlen (home_dir); + newp = (char *) alloca (home_len + dirlen); + mempcpy (mempcpy (newp, home_dir, home_len), + &dirname[1], dirlen); + dirname = newp; + } + } + else + { + char *end_name = strchr (dirname, '/'); + const char *user_name; + const char *home_dir; + + if (end_name == NULL) + user_name = dirname + 1; + else + { + char *newp; + newp = (char *) alloca (end_name - dirname); + *((char *) mempcpy (newp, dirname + 1, end_name - dirname)) + = '\0'; + user_name = newp; + } + + /* Look up specific user's home directory. */ + { + struct passwd *p; + long int buflen = GETPW_R_SIZE_MAX (); + char *pwtmpbuf; + struct passwd pwbuf; + int save = errno; + + pwtmpbuf = (char *) alloca (buflen); + + while (getpwnam_r (user_name, &pwbuf, pwtmpbuf, buflen, &p) != 0) + { + if (errno != ERANGE) + { + p = NULL; + break; + } + pwtmpbuf = extend_alloca (pwtmpbuf, buflen, 2 * buflen); + __set_errno (save); + } + if (p != NULL) + home_dir = p->pw_dir; + else + home_dir = NULL; + } + /* If we found a home directory use this. */ + if (home_dir != NULL) + { + char *newp; + size_t home_len = strlen (home_dir); + size_t rest_len = end_name == NULL ? 0 : strlen (end_name); + newp = (char *) alloca (home_len + rest_len + 1); + *((char *) mempcpy (mempcpy (newp, home_dir, home_len), + end_name, rest_len)) = '\0'; + dirname = newp; + } + else + if (flags & GLOB_TILDE_CHECK) + /* We have to regard it as an error if we cannot find the + home directory. */ + return GLOB_NOMATCH; + } + } + + /* Now test whether we looked for "~" or "~NAME". In this case we + can give the answer now. */ + if (filename == NULL) + { + struct stat st; + struct_stat64 st64; + + /* Return the directory if we don't check for error or if it exists. */ + if ((flags & GLOB_NOCHECK) + || (((flags & GLOB_ALTDIRFUNC) + ? ((*pglob->gl_stat) (dirname, &st) == 0 + && S_ISDIR (st.st_mode)) + : (__stat64 (dirname, &st64) == 0 && S_ISDIR (st64.st_mode))))) + { + int newcount = pglob->gl_pathc + pglob->gl_offs; + char **new_gl_pathv; + + new_gl_pathv + = (char **) realloc (pglob->gl_pathv, + (newcount + 1 + 1) * sizeof (char *)); + if (new_gl_pathv == NULL) + { + nospace: + free (pglob->gl_pathv); + pglob->gl_pathv = NULL; + pglob->gl_pathc = 0; + return GLOB_NOSPACE; + } + pglob->gl_pathv = new_gl_pathv; + + pglob->gl_pathv[newcount] = strdup (dirname); + if (pglob->gl_pathv[newcount] == NULL) + goto nospace; + pglob->gl_pathv[++newcount] = NULL; + ++pglob->gl_pathc; + pglob->gl_flags = flags; + + return 0; + } + + /* Not found. */ + return GLOB_NOMATCH; + } +#endif + + if (glob_pattern_p (dirname, !(flags & GLOB_NOESCAPE))) + { + /* The directory name contains metacharacters, so we + have to glob for the directory, and then glob for + the pattern in each directory found. */ + glob_t dirs; + size_t i; + + if ((flags & GLOB_ALTDIRFUNC) != 0) + { + /* Use the alternative access functions also in the recursive + call. */ + dirs.gl_opendir = pglob->gl_opendir; + dirs.gl_readdir = pglob->gl_readdir; + dirs.gl_closedir = pglob->gl_closedir; + dirs.gl_stat = pglob->gl_stat; + dirs.gl_lstat = pglob->gl_lstat; + } + + status = glob (dirname, + ((flags & (GLOB_ERR | GLOB_NOCHECK | GLOB_NOESCAPE + | GLOB_ALTDIRFUNC)) + | GLOB_NOSORT | GLOB_ONLYDIR), + errfunc, &dirs); + if (status != 0) + return status; + + /* We have successfully globbed the preceding directory name. + For each name we found, call glob_in_dir on it and FILENAME, + appending the results to PGLOB. */ + for (i = 0; i < dirs.gl_pathc; ++i) + { + int old_pathc; + + old_pathc = pglob->gl_pathc; + status = glob_in_dir (filename, dirs.gl_pathv[i], + ((flags | GLOB_APPEND) + & ~(GLOB_NOCHECK | GLOB_NOMAGIC)), + errfunc, pglob); + if (status == GLOB_NOMATCH) + /* No matches in this directory. Try the next. */ + continue; + + if (status != 0) + { + globfree (&dirs); + globfree (pglob); + pglob->gl_pathc = 0; + return status; + } + + /* Stick the directory on the front of each name. */ + if (__prefix_array (dirs.gl_pathv[i], + &pglob->gl_pathv[old_pathc + pglob->gl_offs], + pglob->gl_pathc - old_pathc)) + { + globfree (&dirs); + globfree (pglob); + pglob->gl_pathc = 0; + return GLOB_NOSPACE; + } + } + + flags |= GLOB_MAGCHAR; + + /* We have ignored the GLOB_NOCHECK flag in the `glob_in_dir' calls. + But if we have not found any matching entry and the GLOB_NOCHECK + flag was set we must return the input pattern itself. */ + if (pglob->gl_pathc + pglob->gl_offs == oldcount) + { + /* No matches. */ + if (flags & GLOB_NOCHECK) + { + int newcount = pglob->gl_pathc + pglob->gl_offs; + char **new_gl_pathv; + + new_gl_pathv = (char **) realloc (pglob->gl_pathv, + (newcount + 2) + * sizeof (char *)); + if (new_gl_pathv == NULL) + { + globfree (&dirs); + return GLOB_NOSPACE; + } + pglob->gl_pathv = new_gl_pathv; + + pglob->gl_pathv[newcount] = strdup (pattern); + if (pglob->gl_pathv[newcount] == NULL) + { + globfree (&dirs); + globfree (pglob); + pglob->gl_pathc = 0; + return GLOB_NOSPACE; + } + + ++pglob->gl_pathc; + ++newcount; + + pglob->gl_pathv[newcount] = NULL; + pglob->gl_flags = flags; + } + else + { + globfree (&dirs); + return GLOB_NOMATCH; + } + } + + globfree (&dirs); + } + else + { + int old_pathc = pglob->gl_pathc; + + status = glob_in_dir (filename, dirname, flags, errfunc, pglob); + if (status != 0) + return status; + + if (dirlen > 0) + { + /* Stick the directory on the front of each name. */ + if (__prefix_array (dirname, + &pglob->gl_pathv[old_pathc + pglob->gl_offs], + pglob->gl_pathc - old_pathc)) + { + globfree (pglob); + pglob->gl_pathc = 0; + return GLOB_NOSPACE; + } + } + } + + if (flags & GLOB_MARK) + { + /* Append slashes to directory names. */ + size_t i; + struct stat st; + struct_stat64 st64; + + for (i = oldcount; i < pglob->gl_pathc + pglob->gl_offs; ++i) + if (((flags & GLOB_ALTDIRFUNC) + ? ((*pglob->gl_stat) (pglob->gl_pathv[i], &st) == 0 + && S_ISDIR (st.st_mode)) + : (__stat64 (pglob->gl_pathv[i], &st64) == 0 + && S_ISDIR (st64.st_mode)))) + { + size_t len = strlen (pglob->gl_pathv[i]) + 2; + char *new = realloc (pglob->gl_pathv[i], len); + if (new == NULL) + { + globfree (pglob); + pglob->gl_pathc = 0; + return GLOB_NOSPACE; + } + strcpy (&new[len - 2], "/"); + pglob->gl_pathv[i] = new; + } + } + + if (!(flags & GLOB_NOSORT)) + { + /* Sort the vector. */ + qsort (&pglob->gl_pathv[oldcount], + pglob->gl_pathc + pglob->gl_offs - oldcount, + sizeof (char *), __collated_compare); + } + + return 0; +} +#ifdef COMPILE_GLOB64 +libc_hidden_def(glob64) +#else +libc_hidden_def(glob) +#endif + + +/* Free storage allocated in PGLOB by a previous `glob' call. */ +void +globfree (register glob_t *pglob) +{ + if (pglob->gl_pathv != NULL) + { + size_t i; + for (i = 0; i < pglob->gl_pathc; ++i) + if (pglob->gl_pathv[pglob->gl_offs + i] != NULL) + free (pglob->gl_pathv[pglob->gl_offs + i]); + free (pglob->gl_pathv); + pglob->gl_pathv = NULL; + } +} +#ifdef COMPILE_GLOB64 +libc_hidden_def(globfree64) +#else +libc_hidden_def(globfree) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/glob/glob64-susv3.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/glob/glob64-susv3.c new file mode 100644 index 00000000..f73e2c3a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/glob/glob64-susv3.c @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2006 Rich Felker + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include <_lfs_64.h> + +#include +#include +#include + +#define glob_t glob64_t +#define glob(pattern, flags, errfunc, pglob) \ + glob64 (pattern, flags, errfunc, pglob) +#define globfree(pglob) globfree64 (pglob) + +#define __GLOB64 1 + +#include "glob-susv3.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/glob/glob64.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/glob/glob64.c new file mode 100644 index 00000000..b84af92b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/glob/glob64.c @@ -0,0 +1,15 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include <_lfs_64.h> + +#include +#include +#include + +#define COMPILE_GLOB64 1 + +#include "glob.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/gnu/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/gnu/Makefile new file mode 100644 index 00000000..4a8f4a07 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/gnu/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../ +top_builddir=../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/gnu/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/gnu/Makefile.in new file mode 100644 index 00000000..3990e4e8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/gnu/Makefile.in @@ -0,0 +1,23 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +subdirs += libc/misc/gnu + +CSRC := obstack.c + +MISC_GNU_DIR := $(top_srcdir)libc/misc/gnu +MISC_GNU_OUT := $(top_builddir)libc/misc/gnu + +MISC_GNU_SRC := $(MISC_GNU_DIR)/obstack.c +MISC_GNU_OBJ := $(MISC_GNU_OUT)/obstack.o + +libc-y += $(MISC_GNU_OBJ) + +objclean-y += CLEAN_libc/misc/gnu + +CLEAN_libc/misc/gnu: + $(do_rm) $(addprefix $(MISC_GNU_OUT)/*., o os) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/gnu/obstack.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/gnu/obstack.c new file mode 100644 index 00000000..23914638 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/gnu/obstack.c @@ -0,0 +1,456 @@ +/* obstack.c - subroutines used implicitly by object stack macros + Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1996, 1997, 1998, + 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. */ + + +#ifdef HAVE_CONFIG_H +# include +#endif + +#ifdef _LIBC +# include +#ifndef __UCLIBC__ +# include +#else +# define HAVE_INTTYPES_H 1 +# define HAVE_STDINT_H 1 +# define SHLIB_COMPAT(x,y,z) 0 +# undef libc_hidden_def +# define libc_hidden_def(x) +# undef strong_alias +# define strong_alias(x,y) +#endif +#else +# include "obstack.h" +#endif + +/* NOTE BEFORE MODIFYING THIS FILE: This version number must be + incremented whenever callers compiled using an old obstack.h can no + longer properly call the functions in this obstack.c. */ +#define OBSTACK_INTERFACE_VERSION 1 + +/* Comment out all this code if we are using the GNU C Library, and are not + actually compiling the library itself, and the installed library + supports the same library interface we do. This code is part of the GNU + C Library, but also included in many other GNU distributions. Compiling + and linking in this code is a waste when using the GNU C library + (especially if it is a shared library). Rather than having every GNU + program understand `configure --with-gnu-libc' and omit the object + files, it is simpler to just do this in the source for each such file. */ + +#include /* Random thing to get __GNU_LIBRARY__. */ +#if !defined _LIBC && defined __GNU_LIBRARY__ && __GNU_LIBRARY__ > 1 +# include +# if _GNU_OBSTACK_INTERFACE_VERSION == OBSTACK_INTERFACE_VERSION +# define ELIDE_CODE +# endif +#endif + +#include + +#ifndef ELIDE_CODE + + +# if HAVE_INTTYPES_H +# include +# endif +# if HAVE_STDINT_H || defined _LIBC +# include +# endif + +/* Determine default alignment. */ +union fooround +{ + uintmax_t i; + long double d; + void *p; +}; +struct fooalign +{ + char c; + union fooround u; +}; +/* If malloc were really smart, it would round addresses to DEFAULT_ALIGNMENT. + But in fact it might be less smart and round addresses to as much as + DEFAULT_ROUNDING. So we prepare for it to do that. */ +enum + { + DEFAULT_ALIGNMENT = offsetof (struct fooalign, u), + DEFAULT_ROUNDING = sizeof (union fooround) + }; + +/* When we copy a long block of data, this is the unit to do it with. + On some machines, copying successive ints does not work; + in such a case, redefine COPYING_UNIT to `long' (if that works) + or `char' as a last resort. */ +# ifndef COPYING_UNIT +# define COPYING_UNIT int +# endif + + +/* The functions allocating more room by calling `obstack_chunk_alloc' + jump to the handler pointed to by `obstack_alloc_failed_handler'. + This can be set to a user defined function which should either + abort gracefully or use longjump - but shouldn't return. This + variable by default points to the internal function + `print_and_abort'. */ +static void print_and_abort (void); +static void (*__obstack_alloc_failed_handler) (void) = print_and_abort; +weak_alias(__obstack_alloc_failed_handler,obstack_alloc_failed_handler) + +/* Exit value used when `print_and_abort' is used. */ +# include +# ifdef _LIBC +static int __obstack_exit_failure = EXIT_FAILURE; +weak_alias(__obstack_exit_failure,obstack_exit_failure) +# else +# include "exitfail.h" +# define __obstack_exit_failure exit_failure +# endif + +# ifdef _LIBC +# if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3_4) +/* A looong time ago (before 1994, anyway; we're not sure) this global variable + was used by non-GNU-C macros to avoid multiple evaluation. The GNU C + library still exports it because somebody might use it. */ +struct obstack *_obstack_compat; +compat_symbol (libc, _obstack_compat, _obstack, GLIBC_2_0); +# endif +# endif + +/* Define a macro that either calls functions with the traditional malloc/free + calling interface, or calls functions with the mmalloc/mfree interface + (that adds an extra first argument), based on the state of use_extra_arg. + For free, do not use ?:, since some compilers, like the MIPS compilers, + do not allow (expr) ? void : void. */ + +# define CALL_CHUNKFUN(h, size) \ + (((h) -> use_extra_arg) \ + ? (*(h)->chunkfun) ((h)->extra_arg, (size)) \ + : (*(struct _obstack_chunk *(*) (long)) (h)->chunkfun) ((size))) + +# define CALL_FREEFUN(h, old_chunk) \ + do { \ + if ((h) -> use_extra_arg) \ + (*(h)->freefun) ((h)->extra_arg, (old_chunk)); \ + else \ + (*(void (*) (void *)) (h)->freefun) ((old_chunk)); \ + } while (0) + + +/* Initialize an obstack H for use. Specify chunk size SIZE (0 means default). + Objects start on multiples of ALIGNMENT (0 means use default). + CHUNKFUN is the function to use to allocate chunks, + and FREEFUN the function to free them. + + Return nonzero if successful, calls obstack_alloc_failed_handler if + allocation fails. */ + +int +_obstack_begin (struct obstack *h, + int size, int alignment, + void *(*chunkfun) (long), + void (*freefun) (void *)) +{ + register struct _obstack_chunk *chunk; /* points to new chunk */ + + if (alignment == 0) + alignment = DEFAULT_ALIGNMENT; + if (size == 0) + /* Default size is what GNU malloc can fit in a 4096-byte block. */ + { + /* 12 is sizeof (mhead) and 4 is EXTRA from GNU malloc. + Use the values for range checking, because if range checking is off, + the extra bytes won't be missed terribly, but if range checking is on + and we used a larger request, a whole extra 4096 bytes would be + allocated. + + These number are irrelevant to the new GNU malloc. I suspect it is + less sensitive to the size of the request. */ + int extra = ((((12 + DEFAULT_ROUNDING - 1) & ~(DEFAULT_ROUNDING - 1)) + + 4 + DEFAULT_ROUNDING - 1) + & ~(DEFAULT_ROUNDING - 1)); + size = 4096 - extra; + } + + h->chunkfun = (struct _obstack_chunk * (*)(void *, long)) chunkfun; + h->freefun = (void (*) (void *, struct _obstack_chunk *)) freefun; + h->chunk_size = size; + h->alignment_mask = alignment - 1; + h->use_extra_arg = 0; + + chunk = h->chunk = CALL_CHUNKFUN (h, h -> chunk_size); + if (!chunk) + (*__obstack_alloc_failed_handler) (); + h->next_free = h->object_base = __PTR_ALIGN ((char *) chunk, chunk->contents, + alignment - 1); + h->chunk_limit = chunk->limit + = (char *) chunk + h->chunk_size; + chunk->prev = 0; + /* The initial chunk now contains no empty object. */ + h->maybe_empty_object = 0; + h->alloc_failed = 0; + return 1; +} + +int +_obstack_begin_1 (struct obstack *h, int size, int alignment, + void *(*chunkfun) (void *, long), + void (*freefun) (void *, void *), + void *arg) +{ + register struct _obstack_chunk *chunk; /* points to new chunk */ + + if (alignment == 0) + alignment = DEFAULT_ALIGNMENT; + if (size == 0) + /* Default size is what GNU malloc can fit in a 4096-byte block. */ + { + /* 12 is sizeof (mhead) and 4 is EXTRA from GNU malloc. + Use the values for range checking, because if range checking is off, + the extra bytes won't be missed terribly, but if range checking is on + and we used a larger request, a whole extra 4096 bytes would be + allocated. + + These number are irrelevant to the new GNU malloc. I suspect it is + less sensitive to the size of the request. */ + int extra = ((((12 + DEFAULT_ROUNDING - 1) & ~(DEFAULT_ROUNDING - 1)) + + 4 + DEFAULT_ROUNDING - 1) + & ~(DEFAULT_ROUNDING - 1)); + size = 4096 - extra; + } + + h->chunkfun = (struct _obstack_chunk * (*)(void *,long)) chunkfun; + h->freefun = (void (*) (void *, struct _obstack_chunk *)) freefun; + h->chunk_size = size; + h->alignment_mask = alignment - 1; + h->extra_arg = arg; + h->use_extra_arg = 1; + + chunk = h->chunk = CALL_CHUNKFUN (h, h -> chunk_size); + if (!chunk) + (*__obstack_alloc_failed_handler) (); + h->next_free = h->object_base = __PTR_ALIGN ((char *) chunk, chunk->contents, + alignment - 1); + h->chunk_limit = chunk->limit + = (char *) chunk + h->chunk_size; + chunk->prev = 0; + /* The initial chunk now contains no empty object. */ + h->maybe_empty_object = 0; + h->alloc_failed = 0; + return 1; +} + +/* Allocate a new current chunk for the obstack *H + on the assumption that LENGTH bytes need to be added + to the current object, or a new object of length LENGTH allocated. + Copies any partial object from the end of the old chunk + to the beginning of the new one. */ + +void +_obstack_newchunk (struct obstack *h, int length) +{ + register struct _obstack_chunk *old_chunk = h->chunk; + register struct _obstack_chunk *new_chunk; + register long new_size; + register long obj_size = h->next_free - h->object_base; + register long i; + long already; + char *object_base; + + /* Compute size for new chunk. */ + new_size = (obj_size + length) + (obj_size >> 3) + h->alignment_mask + 100; + if (new_size < h->chunk_size) + new_size = h->chunk_size; + + /* Allocate and initialize the new chunk. */ + new_chunk = CALL_CHUNKFUN (h, new_size); + if (!new_chunk) + (*__obstack_alloc_failed_handler) (); + h->chunk = new_chunk; + new_chunk->prev = old_chunk; + new_chunk->limit = h->chunk_limit = (char *) new_chunk + new_size; + + /* Compute an aligned object_base in the new chunk */ + object_base = + __PTR_ALIGN ((char *) new_chunk, new_chunk->contents, h->alignment_mask); + + /* Move the existing object to the new chunk. + Word at a time is fast and is safe if the object + is sufficiently aligned. */ + if (h->alignment_mask + 1 >= DEFAULT_ALIGNMENT) + { + for (i = obj_size / sizeof (COPYING_UNIT) - 1; + i >= 0; i--) + ((COPYING_UNIT *)object_base)[i] + = ((COPYING_UNIT *)h->object_base)[i]; + /* We used to copy the odd few remaining bytes as one extra COPYING_UNIT, + but that can cross a page boundary on a machine + which does not do strict alignment for COPYING_UNITS. */ + already = obj_size / sizeof (COPYING_UNIT) * sizeof (COPYING_UNIT); + } + else + already = 0; + /* Copy remaining bytes one by one. */ + for (i = already; i < obj_size; i++) + object_base[i] = h->object_base[i]; + + /* If the object just copied was the only data in OLD_CHUNK, + free that chunk and remove it from the chain. + But not if that chunk might contain an empty object. */ + if (! h->maybe_empty_object + && (h->object_base + == __PTR_ALIGN ((char *) old_chunk, old_chunk->contents, + h->alignment_mask))) + { + new_chunk->prev = old_chunk->prev; + CALL_FREEFUN (h, old_chunk); + } + + h->object_base = object_base; + h->next_free = h->object_base + obj_size; + /* The new chunk certainly contains no empty object yet. */ + h->maybe_empty_object = 0; +} +# ifdef _LIBC +libc_hidden_def (_obstack_newchunk) +# endif + +/* Return nonzero if object OBJ has been allocated from obstack H. + This is here for debugging. + If you use it in a program, you are probably losing. */ + +/* Suppress -Wmissing-prototypes warning. We don't want to declare this in + obstack.h because it is just for debugging. */ +int _obstack_allocated_p (struct obstack *h, void *obj); + +int +_obstack_allocated_p (struct obstack *h, void *obj) +{ + register struct _obstack_chunk *lp; /* below addr of any objects in this chunk */ + register struct _obstack_chunk *plp; /* point to previous chunk if any */ + + lp = (h)->chunk; + /* We use >= rather than > since the object cannot be exactly at + the beginning of the chunk but might be an empty object exactly + at the end of an adjacent chunk. */ + while (lp != 0 && ((void *) lp >= obj || (void *) (lp)->limit < obj)) + { + plp = lp->prev; + lp = plp; + } + return lp != 0; +} + +/* Free objects in obstack H, including OBJ and everything allocate + more recently than OBJ. If OBJ is zero, free everything in H. */ + +# undef obstack_free + +void +obstack_free (struct obstack *h, void *obj) +{ + register struct _obstack_chunk *lp; /* below addr of any objects in this chunk */ + register struct _obstack_chunk *plp; /* point to previous chunk if any */ + + lp = h->chunk; + /* We use >= because there cannot be an object at the beginning of a chunk. + But there can be an empty object at that address + at the end of another chunk. */ + while (lp != 0 && ((void *) lp >= obj || (void *) (lp)->limit < obj)) + { + plp = lp->prev; + CALL_FREEFUN (h, lp); + lp = plp; + /* If we switch chunks, we can't tell whether the new current + chunk contains an empty object, so assume that it may. */ + h->maybe_empty_object = 1; + } + if (lp) + { + h->object_base = h->next_free = (char *) (obj); + h->chunk_limit = lp->limit; + h->chunk = lp; + } + else if (obj != 0) + /* obj is not in any of the chunks! */ + abort (); +} + +# ifdef _LIBC +/* Older versions of libc used a function _obstack_free intended to be + called by non-GCC compilers. */ +strong_alias (obstack_free, _obstack_free) +# endif + +int +_obstack_memory_used (struct obstack *h) +{ + register struct _obstack_chunk* lp; + register int nbytes = 0; + + for (lp = h->chunk; lp != 0; lp = lp->prev) + { + nbytes += lp->limit - (char *) lp; + } + return nbytes; +} + +/* Define the error handler. */ +# ifdef _LIBC +# include +# else +# include "gettext.h" +# endif +/* NLS: Disable gettext in obstack for now: */ +# undef _ +# define _(Str) (Str) +# ifndef _ +# define _(msgid) gettext (msgid) +# endif + +# if defined _LIBC && !defined __UCLIBC__ +# include +# endif + +# ifndef __attribute__ +/* This feature is available in gcc versions 2.5 and later. */ +# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5) +# define __attribute__(Spec) /* empty */ +# endif +# endif + +static void +attribute_noreturn +print_and_abort (void) +{ + /* Don't change any of these strings. Yes, it would be possible to add + the newline to the string and use fputs or so. But this must not + happen because the "memory exhausted" message appears in other places + like this and the translation should be reused instead of creating + a very similar string which requires a separate translation. */ +# if defined _LIBC && !defined __UCLIBC__ + (void) __fxprintf (NULL, "%s\n", _("memory exhausted")); +# else + fprintf (stderr, "%s\n", _("memory exhausted")); +# endif + exit (__obstack_exit_failure); +} + +#endif /* !ELIDE_CODE */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/internals/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/internals/Makefile new file mode 100644 index 00000000..4a8f4a07 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/internals/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../ +top_builddir=../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/internals/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/internals/Makefile.in new file mode 100644 index 00000000..354dfc98 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/internals/Makefile.in @@ -0,0 +1,43 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +subdirs += libc/misc/internals + +CSRC := tempname.c errno.c __errno_location.c __h_errno_location.c \ + parse_config.c + +MISC_INTERNALS_DIR := $(top_srcdir)libc/misc/internals +MISC_INTERNALS_OUT := $(top_builddir)libc/misc/internals + +MISC_INTERNALS_SRC := $(patsubst %.c,$(MISC_INTERNALS_DIR)/%.c,$(CSRC)) +MISC_INTERNALS_OBJ := $(patsubst %.c,$(MISC_INTERNALS_OUT)/%.o,$(CSRC)) + +CFLAGS-__uClibc_main.c := $(SSP_DISABLE_FLAGS) + + +libc-y += $(MISC_INTERNALS_OBJ) +ifneq ($(UCLIBC_FORMAT_SHARED_FLAT),y) +libc-shared-y += $(MISC_INTERNALS_OUT)/__uClibc_main.oS +else +libc-shared-y += $(MISC_INTERNALS_OUT)/__uClibc_main.os +endif +libc-static-y += $(MISC_INTERNALS_OUT)/__uClibc_main.o +libc-static-$(UCLIBC_FORMAT_FLAT_SEP_DATA) += \ + $(MISC_INTERNALS_OUT)/shared_flat_initfini.o \ + $(MISC_INTERNALS_OUT)/shared_flat_add_library.o +libc-static-$(UCLIBC_FORMAT_SHARED_FLAT) += \ + $(MISC_INTERNALS_OUT)/shared_flat_initfini.o \ + $(MISC_INTERNALS_OUT)/shared_flat_add_library.o +libc-shared-$(UCLIBC_FORMAT_SHARED_FLAT) += \ + $(MISC_INTERNALS_OUT)/shared_flat_initfini.os \ + $(MISC_INTERNALS_OUT)/shared_flat_add_library.os +libc-nomulti-y += $(MISC_INTERNALS_OUT)/__uClibc_main.o + +objclean-y += CLEAN_libc/misc/internals + +CLEAN_libc/misc/internals: + $(do_rm) $(addprefix $(MISC_INTERNALS_OUT)/*., o os oS) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/internals/__errno_location.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/internals/__errno_location.c new file mode 100644 index 00000000..aec7641c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/internals/__errno_location.c @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include "internal_errno.h" + +/* psm: moved to bits/errno.h: */ +int * +#ifndef __UCLIBC_HAS_THREADS__ +weak_const_function +#endif +__errno_location (void) +{ + return &errno; +} +#ifdef IS_IN_libc /* not really need, only to keep in sync w/ libc_hidden_proto */ +libc_hidden_weak(__errno_location) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/internals/__h_errno_location.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/internals/__h_errno_location.c new file mode 100644 index 00000000..213d3989 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/internals/__h_errno_location.c @@ -0,0 +1,13 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include "internal_errno.h" + +int * weak_const_function __h_errno_location (void) +{ + return &h_errno; +} +libc_hidden_weak(__h_errno_location) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/internals/__uClibc_main.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/internals/__uClibc_main.c new file mode 100644 index 00000000..5b9526c8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/internals/__uClibc_main.c @@ -0,0 +1,533 @@ +/* + * Copyright (C) 2006 by Steven J. Hill + * Copyright (C) 2001 by Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * __uClibc_main is the routine to be called by all the arch-specific + * versions of crt1.S in uClibc. + * + * It is meant to handle any special initialization needed by the library + * such as setting the global variable(s) __environ (environ) and + * initializing the stdio package. Using weak symbols, the latter is + * avoided in the static library case. + */ + +#include +#ifndef __UCLIBC_HAS_THREADS_NATIVE__ +#define _ERRNO_H +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef __NOT_FOR_L4__ +#include +#endif +#include +#include +#include +#ifdef __UCLIBC_HAS_THREADS_NATIVE__ +#include +#include +#include +#include +#endif +#ifdef __UCLIBC_HAS_THREADS__ +#include +#endif + +#ifndef SHARED +void *__libc_stack_end = NULL; + +# ifdef __UCLIBC_HAS_SSP__ +# include +# ifndef THREAD_SET_STACK_GUARD +/* Only exported for architectures that don't store the stack guard canary + * in thread local area. */ +# include +uintptr_t stack_chk_guard; +/* for gcc-4.1 non-TLS */ +uintptr_t __stack_chk_guard attribute_relro; +/* for gcc-3.x + Etoh ssp */ +# ifdef __UCLIBC_HAS_SSP_COMPAT__ +# ifdef __HAVE_SHARED__ +strong_alias(__stack_chk_guard,__guard) +# else +uintptr_t __guard attribute_relro; +# endif +# endif +# elif defined __UCLIBC_HAS_SSP_COMPAT__ +uintptr_t __guard attribute_relro; +# endif +# endif + +/* + * Needed to initialize _dl_phdr when statically linked + */ + +void internal_function _dl_aux_init (ElfW(auxv_t) *av); + +#ifdef __UCLIBC_HAS_THREADS__ +/* + * uClibc internal locking requires that we have weak aliases + * for dummy functions in case libpthread.a is not linked in. + * This needs to be in compilation unit that is pulled always + * in or linker will disregard these weaks. + */ + +static int __pthread_return_0 (pthread_mutex_t *unused) { return 0; } +weak_alias (__pthread_return_0, __pthread_mutex_lock) +weak_alias (__pthread_return_0, __pthread_mutex_trylock) +weak_alias (__pthread_return_0, __pthread_mutex_unlock) + +int weak_function +__pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr) +{ + return 0; +} + +void weak_function +_pthread_cleanup_push_defer(struct _pthread_cleanup_buffer *__buffer, + void (*__routine) (void *), void *__arg) +{ + __buffer->__routine = __routine; + __buffer->__arg = __arg; +} + +void weak_function +_pthread_cleanup_pop_restore(struct _pthread_cleanup_buffer *__buffer, + int __execute) +{ + if (__execute) + __buffer->__routine(__buffer->__arg); +} +#endif /* __UCLIBC_HAS_THREADS__ */ + +#endif /* !SHARED */ + +/* Defeat compiler optimization which assumes function addresses are never NULL */ +static __always_inline int not_null_ptr(const void *p) +{ + const void *q; + __asm__ ("" + : "=r" (q) /* output */ + : "0" (p) /* input */ + ); + return q != 0; +} + +/* + * Prototypes. + */ +extern int *weak_const_function __errno_location(void); +extern int *weak_const_function __h_errno_location(void); +/* aw11: hidden and weak in a statically linked library meaningless + * and gold in x86_64 complains about + */ +#ifdef SHARED +extern void weak_function _stdio_init(void) attribute_hidden; +#else +extern void weak_function _stdio_init(void); +#endif +#ifdef __UCLIBC_HAS_LOCALE__ +extern void weak_function _locale_init(void) attribute_hidden; +#endif +#ifdef __UCLIBC_HAS_THREADS__ +#if !defined (__UCLIBC_HAS_THREADS_NATIVE__) || defined (SHARED) +extern void weak_function __pthread_initialize_minimal(void); +#else +extern void __pthread_initialize_minimal(void); +#endif +#endif + +/* If __UCLIBC_FORMAT_SHARED_FLAT__, all array initialisation and finalisation + * is handled by the routines passed to __uClibc_main(). */ +#if defined (__UCLIBC_CTOR_DTOR__) && !defined (__UCLIBC_FORMAT_SHARED_FLAT__) +extern void _dl_app_init_array(void); +extern void _dl_app_fini_array(void); +# ifndef SHARED +/* These magic symbols are provided by the linker. */ +extern void (*__preinit_array_start []) (void) attribute_hidden; +extern void (*__preinit_array_end []) (void) attribute_hidden; +extern void (*__init_array_start []) (void) attribute_hidden; +extern void (*__init_array_end []) (void) attribute_hidden; +extern void (*__fini_array_start []) (void) attribute_hidden; +extern void (*__fini_array_end []) (void) attribute_hidden; +# endif +#endif + +attribute_hidden const char *__uclibc_progname = ""; +#ifdef __UCLIBC_HAS_PROGRAM_INVOCATION_NAME__ +const char *program_invocation_short_name = ""; +const char *program_invocation_name = ""; +#endif +#ifdef __UCLIBC_HAS___PROGNAME__ +weak_alias (program_invocation_short_name, __progname) +weak_alias (program_invocation_name, __progname_full) +#endif + +/* + * Declare the __environ global variable and create a weak alias environ. + * This must be initialized; we cannot have a weak alias into bss. + */ +char **__environ = 0; +weak_alias(__environ, environ) + +/* TODO: don't export __pagesize; we cant now because libpthread uses it */ +size_t __pagesize = 0; + +#ifndef O_NOFOLLOW +# define O_NOFOLLOW 0 +#endif + +#ifndef __ARCH_HAS_NO_LDSO__ +static void __check_one_fd(int fd, int mode) +{ +#ifdef __NOT_FOR_L4__ + /* Check if the specified fd is already open */ + if (fcntl(fd, F_GETFD) == -1) + { + /* The descriptor is probably not open, so try to use /dev/null */ + int nullfd = open(_PATH_DEVNULL, mode); + /* /dev/null is major=1 minor=3. Make absolutely certain + * that is in fact the device that we have opened and not + * some other wierd file... [removed in uclibc] */ + if (nullfd!=fd) + { + abort(); + } + } +#endif +} + +static int __check_suid(void) +{ +#ifdef __NOT_FOR_L4__ + uid_t uid, euid; + gid_t gid, egid; + + uid = getuid(); + euid = geteuid(); + if (uid != euid) + return 1; + gid = getgid(); + egid = getegid(); + if (gid != egid) + return 1; +#endif + return 0; /* we are not suid */ +} +#endif + +/* __uClibc_init completely initialize uClibc so it is ready to use. + * + * On ELF systems (with a dynamic loader) this function must be called + * from the dynamic loader (see TIS and ELF Specification), so that + * constructors of shared libraries (which depend on libc) can use all + * the libc code without restriction. For this we link the shared + * version of the uClibc with -init __uClibc_init so DT_INIT for + * uClibc is the address of __uClibc_init + * + * In all other cases we call it from the main stub + * __uClibc_main. + */ + +extern void __uClibc_init(void); +libc_hidden_proto(__uClibc_init) +void __uClibc_init(void) +{ + /* Don't recurse */ + if (__pagesize) + return; + + /* Setup an initial value. This may not be perfect, but is + * better than malloc using __pagesize=0 for atexit, ctors, etc. */ + __pagesize = PAGE_SIZE; + +#ifdef __UCLIBC_HAS_THREADS__ + /* Before we start initializing uClibc we have to call + * __pthread_initialize_minimal so we can use pthread_locks + * whenever they are needed. + */ +#if !defined (__UCLIBC_HAS_THREADS_NATIVE__) || defined (SHARED) + if (likely(__pthread_initialize_minimal!=NULL)) +#endif + __pthread_initialize_minimal(); +#endif + +#ifndef SHARED +# ifdef __UCLIBC_HAS_SSP__ + /* Set up the stack checker's canary. */ +# ifdef THREAD_SET_STACK_GUARD + uintptr_t stack_chk_guard = _dl_setup_stack_chk_guard(); + THREAD_SET_STACK_GUARD (stack_chk_guard); +# ifdef __UCLIBC_HAS_SSP_COMPAT__ + stack_chk_guard = _dl_setup_stack_chk_guard(); + __guard = stack_chk_guard; +# endif +# else + __stack_chk_guard = stack_chk_guard; +# if !defined __HAVE_SHARED__ && defined __UCLIBC_HAS_SSP_COMPAT__ + __guard = stack_chk_guard; +# endif +# endif +# endif +#endif + +#ifdef __UCLIBC_HAS_LOCALE__ + /* Initialize the global locale structure. */ + if (likely(not_null_ptr(_locale_init))) + _locale_init(); +#endif + + /* + * Initialize stdio here. In the static library case, this will + * be bypassed if not needed because of the weak alias above. + * Thus we get a nice size savings because the stdio functions + * won't be pulled into the final static binary unless used. + */ + if (likely(not_null_ptr(_stdio_init))) + _stdio_init(); + +} +libc_hidden_def(__uClibc_init) + +#ifdef __UCLIBC_CTOR_DTOR__ +void attribute_hidden (*__app_fini)(void) = NULL; +#endif + +void attribute_hidden (*__rtld_fini)(void) = NULL; + +extern void __uClibc_fini(void); +libc_hidden_proto(__uClibc_fini) +void __uClibc_fini(void) +{ +#ifdef __UCLIBC_CTOR_DTOR__ + /* If __UCLIBC_FORMAT_SHARED_FLAT__, all array finalisation is handled + * by __app_fini. */ +# ifdef SHARED + _dl_app_fini_array(); +# elif !defined (__UCLIBC_FORMAT_SHARED_FLAT__) + size_t i = __fini_array_end - __fini_array_start; + while (i-- > 0) + (*__fini_array_start [i]) (); +# endif + if (__app_fini != NULL) + (__app_fini)(); +#endif + if (__rtld_fini != NULL) + (__rtld_fini)(); +} +libc_hidden_def(__uClibc_fini) + +#ifndef __NOT_FOR_L4__ +extern void *l4re_global_env __attribute__((weak)); +#endif + +/* __uClibc_main is the new main stub for uClibc. This function is + * called from crt1 (version 0.9.28 or newer), after ALL shared libraries + * are initialized, just before we call the application's main function. + */ +void __uClibc_main(int (*main)(int, char **, char **), int argc, + char **argv, void (*app_init)(void), void (*app_fini)(void), + void (*rtld_fini)(void), + void *stack_end attribute_unused) attribute_noreturn; +void __uClibc_main(int (*main)(int, char **, char **), int argc, + char **argv, void (*app_init)(void), void (*app_fini)(void), + void (*rtld_fini)(void), void *stack_end attribute_unused) +{ +#ifndef __ARCH_HAS_NO_LDSO__ + unsigned long *aux_dat; + ElfW(auxv_t) auxvt[AT_EGID + 1]; +#endif + +#ifdef __UCLIBC_HAS_THREADS_NATIVE__ + /* Result of the 'main' function. */ + int result; +#endif + +#ifndef SHARED + __libc_stack_end = stack_end; +#endif + + __rtld_fini = rtld_fini; + + /* The environment begins right after argv. */ + __environ = &argv[argc + 1]; + + /* If the first thing after argv is the arguments + * the the environment is empty. */ + if ((char *) __environ == *argv) { + /* Make __environ point to the NULL at argv[argc] */ + __environ = &argv[argc]; + } + +#ifndef __ARCH_HAS_NO_LDSO__ + /* Pull stuff from the ELF header when possible */ + memset(auxvt, 0x00, sizeof(auxvt)); + aux_dat = (unsigned long*)__environ; + while (*aux_dat) { + aux_dat++; + } + aux_dat++; + while (*aux_dat) { + ElfW(auxv_t) *auxv_entry = (ElfW(auxv_t) *) aux_dat; + if (auxv_entry->a_type <= AT_EGID) { + memcpy(&(auxvt[auxv_entry->a_type]), auxv_entry, sizeof(ElfW(auxv_t))); + } +#ifndef __NOT_FOR_L4__ + if (auxv_entry->a_type == 0xf1 && &l4re_global_env) + { + l4re_global_env = (void*)auxv_entry->a_un.a_val; + } +#endif + aux_dat += 2; + } +#ifndef SHARED + /* Get the program headers (_dl_phdr) from the aux vector + It will be used into __libc_setup_tls. */ + + _dl_aux_init (auxvt); +#endif +#endif + + /* We need to initialize uClibc. If we are dynamically linked this + * may have already been completed by the shared lib loader. We call + * __uClibc_init() regardless, to be sure the right thing happens. */ + __uClibc_init(); + +#ifndef __ARCH_HAS_NO_LDSO__ + /* Make certain getpagesize() gives the correct answer */ + __pagesize = (auxvt[AT_PAGESZ].a_un.a_val)? auxvt[AT_PAGESZ].a_un.a_val : PAGE_SIZE; + + /* Prevent starting SUID binaries where the stdin. stdout, and + * stderr file descriptors are not already opened. */ + if ((auxvt[AT_UID].a_un.a_val == (size_t)-1 && __check_suid()) || + (auxvt[AT_UID].a_un.a_val != (size_t)-1 && + (auxvt[AT_UID].a_un.a_val != auxvt[AT_EUID].a_un.a_val || + auxvt[AT_GID].a_un.a_val != auxvt[AT_EGID].a_un.a_val))) + { + __check_one_fd (STDIN_FILENO, O_RDONLY | O_NOFOLLOW); + __check_one_fd (STDOUT_FILENO, O_RDWR | O_NOFOLLOW); + __check_one_fd (STDERR_FILENO, O_RDWR | O_NOFOLLOW); + } +#endif + + __uclibc_progname = *argv; +#ifdef __UCLIBC_HAS_PROGRAM_INVOCATION_NAME__ + if (*argv != NULL) { + program_invocation_name = *argv; + program_invocation_short_name = strrchr(*argv, '/'); + if (program_invocation_short_name != NULL) + ++program_invocation_short_name; + else + program_invocation_short_name = program_invocation_name; + } +#endif + +#ifdef __UCLIBC_CTOR_DTOR__ + /* Arrange for the application's dtors to run before we exit. */ + __app_fini = app_fini; + + /* If __UCLIBC_FORMAT_SHARED_FLAT__, all array initialisation is handled + * by __app_init. */ +# if !defined (SHARED) && !defined (__UCLIBC_FORMAT_SHARED_FLAT__) + /* For dynamically linked executables the preinit array is executed by + the dynamic linker (before initializing any shared object). + For static executables, preinit happens rights before init. */ + { + const size_t size = __preinit_array_end - __preinit_array_start; + size_t i; + for (i = 0; i < size; i++) + (*__preinit_array_start [i]) (); + } +# endif + /* Run all the application's ctors now. */ + if (app_init!=NULL) { + app_init(); + } + /* If __UCLIBC_FORMAT_SHARED_FLAT__, all array initialisation is handled + * by __app_init. */ +# ifdef SHARED + _dl_app_init_array(); +# elif !defined (__UCLIBC_FORMAT_SHARED_FLAT__) + { + const size_t size = __init_array_end - __init_array_start; + size_t i; + for (i = 0; i < size; i++) + (*__init_array_start [i]) (); + } +# endif +#endif + + /* Note: It is possible that any initialization done above could + * have resulted in errno being set nonzero, so set it to 0 before + * we call main. + */ + if (likely(not_null_ptr(__errno_location))) + *(__errno_location()) = 0; + + /* Set h_errno to 0 as well */ + if (likely(not_null_ptr(__h_errno_location))) + *(__h_errno_location()) = 0; + +#if defined HAVE_CLEANUP_JMP_BUF && defined __UCLIBC_HAS_THREADS_NATIVE__ + /* Memory for the cancellation buffer. */ + struct pthread_unwind_buf unwind_buf; + + int not_first_call; + not_first_call = + setjmp ((struct __jmp_buf_tag *) unwind_buf.cancel_jmp_buf); + if (__builtin_expect (! not_first_call, 1)) + { + struct pthread *self = THREAD_SELF; + + /* Store old info. */ + unwind_buf.priv.data.prev = THREAD_GETMEM (self, cleanup_jmp_buf); + unwind_buf.priv.data.cleanup = THREAD_GETMEM (self, cleanup); + + /* Store the new cleanup handler info. */ + THREAD_SETMEM (self, cleanup_jmp_buf, &unwind_buf); + + /* Run the program. */ + result = main (argc, argv, __environ); + } + else + { + /* Remove the thread-local data. */ +# ifdef SHARED + __libc_pthread_functions.ptr__nptl_deallocate_tsd (); +# else + extern void __nptl_deallocate_tsd (void) __attribute ((weak)); + __nptl_deallocate_tsd (); +# endif + + /* One less thread. Decrement the counter. If it is zero we + terminate the entire process. */ + result = 0; +# ifdef SHARED + unsigned int *const ptr = __libc_pthread_functions.ptr_nthreads; +# else + extern unsigned int __nptl_nthreads __attribute ((weak)); + unsigned int *const ptr = &__nptl_nthreads; +# endif + + if (! atomic_decrement_and_test (ptr)) + /* Not much left to do but to exit the thread, not the process. */ + __exit_thread_inline (0); + } + + exit (result); +#else + /* + * Finally, invoke application's main and then exit. + */ + exit (main (argc, argv, __environ)); +#endif +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/internals/errno.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/internals/errno.c new file mode 100644 index 00000000..11d19eee --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/internals/errno.c @@ -0,0 +1,21 @@ +#include + +#ifdef __UCLIBC_HAS_TLS__ +__thread int errno; +__thread int h_errno; + +extern __thread int __libc_errno __attribute__ ((alias ("errno"))) attribute_hidden; +extern __thread int __libc_h_errno __attribute__ ((alias ("h_errno"))) attribute_hidden; +#define h_errno __libc_h_errno + +#else +#include "internal_errno.h" +int errno = 0; +int h_errno = 0; +#ifdef __UCLIBC_HAS_THREADS__ +libc_hidden_def(errno) +weak_alias(errno, _errno) +libc_hidden_def(h_errno) +weak_alias(h_errno, _h_errno) +#endif +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/internals/internal_errno.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/internals/internal_errno.h new file mode 100644 index 00000000..b4919857 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/internals/internal_errno.h @@ -0,0 +1,21 @@ +/* + * + */ + +#include +#include +#include + +#ifndef __UCLIBC_HAS_TLS__ + +#undef errno +#undef h_errno + +extern int h_errno; +extern int errno; + +#ifdef __UCLIBC_HAS_THREADS__ +libc_hidden_proto(h_errno) +libc_hidden_proto(errno) +#endif +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/internals/parse_config.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/internals/parse_config.c new file mode 100644 index 00000000..c17d2555 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/internals/parse_config.c @@ -0,0 +1,277 @@ +/* vi: set sw=4 ts=4: */ +/* + * config file parser helper + * + * Copyright (C) 2008 by Vladimir Dronnikov + * + * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. + * Also for use in uClibc (http://uclibc.org/) licensed under LGPLv2.1 or later. + */ + +#if !defined _LIBC +#include "libbb.h" + +#if defined ENABLE_PARSE && ENABLE_PARSE +int parse_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; +int parse_main(int argc UNUSED_PARAM, char **argv) +{ + const char *delims = "# \t"; + unsigned flags = PARSE_NORMAL; + int mintokens = 0, ntokens = 128; + + opt_complementary = "-1:n+:m+:f+"; + getopt32(argv, "n:m:d:f:", &ntokens, &mintokens, &delims, &flags); + //argc -= optind; + argv += optind; + while (*argv) { + parser_t *p = config_open(*argv); + if (p) { + int n; + char **t = xmalloc(sizeof(char *) * ntokens); + while ((n = config_read(p, t, ntokens, mintokens, delims, flags)) != 0) { + for (int i = 0; i < n; ++i) + printf("[%s]", t[i]); + puts(""); + } + config_close(p); + } + argv++; + } + return EXIT_SUCCESS; +} +#endif +#else +# include +# include +# include +# include +# include "internal/parse_config.h" +# ifndef FAST_FUNC +# define FAST_FUNC +# endif +# define fopen_or_warn_stdin fopen +# define bb_error_msg(...) +# define xstrdup strdup +# define xfunc_die() return 0 +/* Read up to EOF or EOL, treat line-continuations as extending the line. + Return number of bytes read into .line, -1 otherwise */ +static off_t bb_get_chunk_with_continuation(parser_t* parsr) +{ + off_t pos = 0; + char *chp; + + while (1) { + if (fgets(parsr->line + pos, parsr->line_len - pos, parsr->fp) == NULL) { + memset(parsr->line, 0, parsr->line_len); + pos = -1; + break; + } + pos += strlen(parsr->line + pos); + chp = strchr(parsr->line, '\n'); + if (chp) { + --pos; + if (--*chp == '\\') + --pos; + else + break; + } else if (parsr->allocated) { + parsr->line_len += PAGE_SIZE; + parsr->data = realloc(parsr->data, + parsr->data_len + parsr->line_len); + parsr->line = parsr->data + parsr->data_len; + } else { + /* discard rest of line if not enough space in buffer */ + int c; + do { + c = fgetc(parsr->fp); + } while (c != EOF && c != '\n'); + break; + } + } + return pos; +} +#endif + +/* + +Typical usage: + +----- CUT ----- + char *t[3]; // tokens placeholder + parser_t *p = config_open(filename); + if (p) { + // parse line-by-line + while (config_read(p, t, 3, 0, delimiters, flags)) { // 1..3 tokens + // use tokens + bb_error_msg("TOKENS: [%s][%s][%s]", t[0], t[1], t[2]); + } + ... + // free parser + config_close(p); + } +----- CUT ----- + +*/ + +static __always_inline parser_t * FAST_FUNC config_open2(const char *filename, + FILE* FAST_FUNC (*fopen_func)(const char *path, const char *mode)) +{ + parser_t *parser; + FILE* fp; + + fp = fopen_func(filename, "r"); + if (!fp) + return NULL; + parser = calloc(1, sizeof(*parser)); + if (parser) { + parser->fp = fp; + } + return parser; +} + +parser_t attribute_hidden * FAST_FUNC config_open(const char *filename) +{ + return config_open2(filename, fopen_or_warn_stdin); +} + +#ifdef UNUSED +static void config_free_data(parser_t *parser) +{ + free(parser->data); + parser->data = parser->line = NULL; +} +#endif + +void attribute_hidden FAST_FUNC config_close(parser_t *parser) +{ + if (parser) { + fclose(parser->fp); + if (parser->allocated) + free(parser->data); + free(parser); + } +} + +/* +0. If parser is NULL return 0. +1. Read a line from config file. If nothing to read then return 0. + Handle continuation character. Advance lineno for each physical line. + Discard everything past comment character. +2. if PARSE_TRIM is set (default), remove leading and trailing delimiters. +3. If resulting line is empty goto 1. +4. Look for first delimiter. If !PARSE_COLLAPSE or !PARSE_TRIM is set then + remember the token as empty. +5. Else (default) if number of seen tokens is equal to max number of tokens + (token is the last one) and PARSE_GREEDY is set then the remainder + of the line is the last token. + Else (token is not last or PARSE_GREEDY is not set) just replace + first delimiter with '\0' thus delimiting the token. +6. Advance line pointer past the end of token. If number of seen tokens + is less than required number of tokens then goto 4. +7. Check the number of seen tokens is not less the min number of tokens. + Complain or die otherwise depending on PARSE_MIN_DIE. +8. Return the number of seen tokens. + +mintokens > 0 make config_read() print error message if less than mintokens +(but more than 0) are found. Empty lines are always skipped (not warned about). +*/ +#undef config_read +int attribute_hidden FAST_FUNC config_read(parser_t *parser, char ***tokens, + unsigned flags, const char *delims) +{ + char *line; + int ntokens, mintokens; + off_t len; + int t; + + if (parser == NULL) + return 0; + ntokens = flags & 0xFF; + mintokens = (flags & 0xFF00) >> 8; +again: + if (parser->data == NULL) { + if (parser->line_len == 0) + parser->line_len = 81; + if (parser->data_len == 0) + parser->data_len += 1 + ntokens * sizeof(char *); + parser->data = malloc(parser->data_len + parser->line_len); + if (parser->data == NULL) + return 0; + parser->allocated |= 1; + } /* else { assert(parser->data_len > 0); } */ + parser->line = parser->data + parser->data_len; + /*config_free_data(parser);*/ + + /* Read one line (handling continuations with backslash) */ + len = bb_get_chunk_with_continuation(parser); + if (len == -1) + return 0; + *tokens = (char **) parser->data; + memset(*tokens, 0, sizeof(*tokens[0]) * ntokens); + line = parser->line; + + /* Skip multiple token-delimiters in the start of line? */ + if (flags & PARSE_TRIM) + line += strspn(line, delims + 1); + + if (line[0] == '\0' || line[0] == delims[0]) + goto again; + + /* Tokenize the line */ + for (t = 0; *line && *line != delims[0] && t < ntokens; t++) { + /* Pin token */ + *(*tokens + t) = line; + + /* Combine remaining arguments? */ + if ((t != ntokens-1) || !(flags & PARSE_GREEDY)) { + /* Vanilla token, find next delimiter */ + line += strcspn(line, delims[0] ? delims : delims + 1); + } else { + /* Combining, find comment char if any */ + line = strchrnul(line, delims[0]); + + /* Trim any extra delimiters from the end */ + if (flags & PARSE_TRIM) { + while (strchr(delims + 1, line[-1]) != NULL) + line--; + } + } + + /* Token not terminated? */ + if (line[0] == delims[0]) + *line = '\0'; + else if (line[0] != '\0') + *(line++) = '\0'; + +#if 0 /* unused so far */ + if (flags & PARSE_ESCAPE) { + const char *from; + char *to; + + from = to = tokens[t]; + while (*from) { + if (*from == '\\') { + from++; + *to++ = bb_process_escape_sequence(&from); + } else { + *to++ = *from++; + } + } + *to = '\0'; + } +#endif + + /* Skip possible delimiters */ + if (flags & PARSE_COLLAPSE) + line += strspn(line, delims + 1); + } + + if (t < mintokens) { + bb_error_msg(/*"bad line %u: "*/"%d tokens found, %d needed", + /*parser->lineno, */t, mintokens); + if (flags & PARSE_MIN_DIE) + xfunc_die(); + goto again; + } + return t; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/internals/shared_flat_add_library.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/internals/shared_flat_add_library.c new file mode 100644 index 00000000..f03480f5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/internals/shared_flat_add_library.c @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2006 CodeSourcery Inc + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * This file defines __shared_flat_add_library. If a library has + * initialistion and finalisation code, it should use this routine + * to register itself. + */ +#include "shared_flat_lib.h" + +/* The initialisation and finalisation symbols for this library. */ +extern void _init(void) attribute_hidden weak_function; +extern void _fini(void) attribute_hidden weak_function; +extern void (*__preinit_array_start[])(void) attribute_hidden; +extern void (*__preinit_array_end[])(void) attribute_hidden; +extern void (*__init_array_start[])(void) attribute_hidden; +extern void (*__init_array_end[])(void) attribute_hidden; +extern void (*__fini_array_start[])(void) attribute_hidden; +extern void (*__fini_array_end[])(void) attribute_hidden; + +/* The shared_flat_lib structure that describes this library. */ +static struct shared_flat_lib this_lib = { + 0, + 0, + __preinit_array_start, + __preinit_array_end, + __init_array_start, + __init_array_end, + __fini_array_start, + __fini_array_end, + _init, + _fini +}; + +/* Add this_lib to the end of the global list. */ +void __shared_flat_add_library(void) attribute_hidden; +void __shared_flat_add_library(void) +{ + this_lib.prev = __last_shared_lib; + if (this_lib.prev) + this_lib.prev->next = &this_lib; + else + __first_shared_lib = &this_lib; + __last_shared_lib = &this_lib; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/internals/shared_flat_initfini.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/internals/shared_flat_initfini.c new file mode 100644 index 00000000..81e53834 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/internals/shared_flat_initfini.c @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2006 CodeSourcery Inc + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * This file defines the main initialisation and finalisation code for + * shared flat libraries. It in turn calls the initialisation and + * finalisation code for each registered library. + */ +#include "shared_flat_lib.h" + +/* A doubly-linked list of shared libraries. Those nearer the head + * of the list should be initialised first and finalised last. */ +struct shared_flat_lib *__first_shared_lib; +struct shared_flat_lib *__last_shared_lib; + +void __shared_flat_init(void) +{ + struct shared_flat_lib *lib; + void (**start)(void); + void (**end)(void); + + for (lib = __first_shared_lib; lib; lib = lib->next) { + end = lib->preinit_array_end; + for (start = lib->preinit_array_start; start < end; start++) + (*start)(); + } + + for (lib = __first_shared_lib; lib; lib = lib->next) { + if (lib->init) + lib->init(); + + end = lib->init_array_end; + for (start = lib->init_array_start; start < end; start++) + (*start)(); + } +} + +void __shared_flat_fini(void) +{ + struct shared_flat_lib *lib; + void (**start)(void); + void (**end)(void); + + for (lib = __last_shared_lib; lib; lib = lib->prev) { + start = lib->fini_array_start; + for (end = lib->fini_array_end; end > start;) + (*--end)(); + + if (lib->fini) + lib->fini(); + } +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/internals/shared_flat_lib.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/internals/shared_flat_lib.h new file mode 100644 index 00000000..e0121356 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/internals/shared_flat_lib.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2006 CodeSourcery Inc + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * This file defines the shared_flat_lib structure and the global library + * list. The structure is used to provide something close to ELF-like + * initialisation and finalisation when using shared flat libraries. + */ +#ifndef __SHARED_FLAT_LIB__ +#define __SHARED_FLAT_LIB__ + +struct shared_flat_lib { + struct shared_flat_lib *prev; + struct shared_flat_lib *next; + /* .preinit_array is usually only supported for executables. + * However, the distinction between the executable and its + * shared libraries isn't as pronounced for flat files; a shared + * library is really just a part of an executable that can be + * shared with other executables. We therefore allow + * .preinit_array to be used in libraries too. */ + void (**preinit_array_start)(void); + void (**preinit_array_end)(void); + void (**init_array_start)(void); + void (**init_array_end)(void); + void (**fini_array_start)(void); + void (**fini_array_end)(void); + void (*init)(void); + void (*fini)(void); +}; + +extern struct shared_flat_lib *__first_shared_lib; +extern struct shared_flat_lib *__last_shared_lib; + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/internals/tempname.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/internals/tempname.c new file mode 100644 index 00000000..5ad11c67 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/internals/tempname.c @@ -0,0 +1,249 @@ +/* Copyright (C) 1991,92,93,94,95,96,97,98,99 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* March 11, 2002 Manuel Novoa III + * + * Modify code to remove dependency on libgcc long long arith support funcs. + */ + +/* June 6, 2004 Erik Andersen + * + * Don't use brain damaged getpid() based randomness. + */ + +/* April 15, 2005 Mike Frysinger + * + * Use brain damaged getpid() if real random fails. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "tempname.h" + +/* Return nonzero if DIR is an existent directory. */ +static int direxists (const char *dir) +{ + struct stat buf; + return stat(dir, &buf) == 0 && S_ISDIR (buf.st_mode); +} + +/* Path search algorithm, for tmpnam, tmpfile, etc. If DIR is + non-null and exists, uses it; otherwise uses the first of $TMPDIR, + P_tmpdir, /tmp that exists. Copies into TMPL a template suitable + for use with mk[s]temp. Will fail (-1) if DIR is non-null and + doesn't exist, none of the searched dirs exists, or there's not + enough space in TMPL. */ +int attribute_hidden ___path_search (char *tmpl, size_t tmpl_len, const char *dir, + const char *pfx /*, int try_tmpdir*/) +{ + /*const char *d; */ + size_t dlen, plen; + + if (!pfx || !pfx[0]) + { + pfx = "file"; + plen = 4; + } + else + { + plen = strlen (pfx); + if (plen > 5) + plen = 5; + } + + /* Disable support for $TMPDIR */ +#if 0 + if (try_tmpdir) + { + d = __secure_getenv ("TMPDIR"); + if (d != NULL && direxists (d)) + dir = d; + else if (dir != NULL && direxists (dir)) + /* nothing */ ; + else + dir = NULL; + } +#endif + if (dir == NULL) + { + if (direxists (P_tmpdir)) + dir = P_tmpdir; + else if (strcmp (P_tmpdir, "/tmp") != 0 && direxists ("/tmp")) + dir = "/tmp"; + else + { + __set_errno (ENOENT); + return -1; + } + } + + dlen = strlen (dir); + while (dlen > 1 && dir[dlen - 1] == '/') + dlen--; /* remove trailing slashes */ + + /* check we have room for "${dir}/${pfx}XXXXXX\0" */ + if (tmpl_len < dlen + 1 + plen + 6 + 1) + { + __set_errno (EINVAL); + return -1; + } + + sprintf (tmpl, "%.*s/%.*sXXXXXX", (int)dlen, dir, (int)plen, pfx); + return 0; +} + +/* These are the characters used in temporary filenames. */ +static const char letters[] = +"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; +#define NUM_LETTERS (62) + +static unsigned int fillrand(unsigned char *buf, unsigned int len) +{ + int fd; + unsigned int result = -1; + fd = open("/dev/urandom", O_RDONLY); + if (fd < 0) { + fd = open("/dev/random", O_RDONLY | O_NONBLOCK); + } + if (fd >= 0) { + result = read(fd, buf, len); + close(fd); + } + return result; +} + +static void brain_damaged_fillrand(unsigned char *buf, unsigned int len) +{ + unsigned int i, k; + struct timeval tv; + uint32_t high, low, rh; + static uint64_t value; + gettimeofday(&tv, NULL); + value += ((uint64_t) tv.tv_usec << 16) ^ tv.tv_sec ^ getpid(); + low = value & UINT32_MAX; + high = value >> 32; + for (i = 0; i < len; ++i) { + rh = high % NUM_LETTERS; + high /= NUM_LETTERS; +#define L ((UINT32_MAX % NUM_LETTERS + 1) % NUM_LETTERS) + k = (low % NUM_LETTERS) + (L * rh); +#undef L +#define H ((UINT32_MAX / NUM_LETTERS) + ((UINT32_MAX % NUM_LETTERS + 1) / NUM_LETTERS)) + low = (low / NUM_LETTERS) + (H * rh) + (k / NUM_LETTERS); +#undef H + k %= NUM_LETTERS; + buf[i] = letters[k]; + } +} + +/* Generate a temporary file name based on TMPL. TMPL must match the + rules for mk[s]temp (i.e. end in "XXXXXX"). The name constructed + does not exist at the time of the call to __gen_tempname. TMPL is + overwritten with the result. + + KIND may be one of: + __GT_NOCREATE: simply verify that the name does not exist + at the time of the call. mode argument is ignored. + __GT_FILE: create the file using open(O_CREAT|O_EXCL) + and return a read-write fd with given mode. + __GT_BIGFILE: same as __GT_FILE but use open64(). + __GT_DIR: create a directory with given mode. + +*/ +int __gen_tempname (char *tmpl, int kind, mode_t mode) +{ + char *XXXXXX; + unsigned int i; + int fd, save_errno = errno; + unsigned char randomness[6]; + size_t len; + + len = strlen (tmpl); + /* This is where the Xs start. */ + XXXXXX = tmpl + len - 6; + if (len < 6 || strcmp (XXXXXX, "XXXXXX")) + { + __set_errno (EINVAL); + return -1; + } + + for (i = 0; i < TMP_MAX; ++i) { + int j; + /* Get some random data. */ + if (fillrand(randomness, sizeof(randomness)) != sizeof(randomness)) { + /* if random device nodes failed us, lets use the braindamaged ver */ + brain_damaged_fillrand(randomness, sizeof(randomness)); + } + for (j = 0; j < sizeof(randomness); ++j) + XXXXXX[j] = letters[randomness[j] % NUM_LETTERS]; + + switch (kind) { + case __GT_NOCREATE: + { + struct stat st; + if (stat (tmpl, &st) < 0) { + if (errno == ENOENT) { + fd = 0; + goto restore_and_ret; + } else + /* Give up now. */ + return -1; + } else + fd = 0; + } + case __GT_FILE: + fd = open (tmpl, O_RDWR | O_CREAT | O_EXCL, mode); + break; +#if defined __UCLIBC_HAS_LFS__ + case __GT_BIGFILE: + fd = open64 (tmpl, O_RDWR | O_CREAT | O_EXCL, mode); + break; +#endif + case __GT_DIR: + fd = mkdir (tmpl, mode); + break; + default: + fd = -1; + assert (! "invalid KIND in __gen_tempname"); + } + + if (fd >= 0) { +restore_and_ret: + __set_errno (save_errno); + return fd; + } + else if (errno != EEXIST) + /* Any other error will apply also to other names we might + try, and there are 2^32 or so of them, so give up now. */ + return -1; + } + + /* We got out of the loop because we ran out of combinations to try. */ + __set_errno (EEXIST); + return -1; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/internals/tempname.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/internals/tempname.h new file mode 100644 index 00000000..017dc519 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/internals/tempname.h @@ -0,0 +1,21 @@ +#ifndef __TEMPNAME_H__ +#define __TEMPNAME_H__ + +#define __need_size_t +#include +#include + +/* Disable support for $TMPDIR */ +extern int ___path_search (char *tmpl, size_t tmpl_len, const char *dir, + const char *pfx /*, int try_tmpdir */) attribute_hidden; +#define __path_search(tmpl, tmpl_len, dir, pfx, try_tmpdir) ___path_search(tmpl, tmpl_len, dir, pfx) + +extern int __gen_tempname (char *__tmpl, int __kind, mode_t mode); + +/* The __kind argument to __gen_tempname may be one of: */ +#define __GT_FILE 0 /* create a file */ +#define __GT_BIGFILE 1 /* create a file, using open64 */ +#define __GT_DIR 2 /* create a directory */ +#define __GT_NOCREATE 3 /* just find a name not currently in use */ + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/locale/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/locale/Makefile new file mode 100644 index 00000000..4a8f4a07 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/locale/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../ +top_builddir=../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/locale/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/locale/Makefile.in new file mode 100644 index 00000000..c12befd3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/locale/Makefile.in @@ -0,0 +1,30 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +subdirs += libc/misc/locale + +# multi source locale.c +CSRC := setlocale.c localeconv.c _locale_init.c nl_langinfo.c +ifeq ($(UCLIBC_HAS_LOCALE),y) +CSRC += newlocale.c __locale_mbrtowc_l.c +endif +ifeq ($(UCLIBC_HAS_XLOCALE),y) +CSRC += nl_langinfo_l.c duplocale.c freelocale.c uselocale.c __curlocale.c +endif + +MISC_LOCALE_DIR := $(top_srcdir)libc/misc/locale +MISC_LOCALE_OUT := $(top_builddir)libc/misc/locale + +MISC_LOCALE_SRC := $(patsubst %.c,$(MISC_LOCALE_DIR)/%.c,$(CSRC)) +MISC_LOCALE_OBJ := $(patsubst %.c,$(MISC_LOCALE_OUT)/%.o,$(CSRC)) + +libc-y += $(MISC_LOCALE_OBJ) + +objclean-y += CLEAN_libc/misc/locale + +CLEAN_libc/misc/locale: + $(do_rm) $(addprefix $(MISC_LOCALE_OUT)/*., o os) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/locale/__curlocale.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/locale/__curlocale.c new file mode 100644 index 00000000..aa38f434 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/locale/__curlocale.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L___curlocale +#define __UCLIBC_DO_XLOCALE +#include "locale.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/locale/__locale_mbrtowc_l.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/locale/__locale_mbrtowc_l.c new file mode 100644 index 00000000..ea7fbceb --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/locale/__locale_mbrtowc_l.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L___locale_mbrtowc_l +#include "locale.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/locale/_locale_init.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/locale/_locale_init.c new file mode 100644 index 00000000..9ced732a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/locale/_locale_init.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L__locale_init +#include "locale.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/locale/duplocale.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/locale/duplocale.c new file mode 100644 index 00000000..db9c7a3c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/locale/duplocale.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_duplocale +#define __UCLIBC_DO_XLOCALE +#include "locale.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/locale/freelocale.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/locale/freelocale.c new file mode 100644 index 00000000..c1ef8e1c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/locale/freelocale.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_freelocale +#define __UCLIBC_DO_XLOCALE +#include "locale.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/locale/locale.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/locale/locale.c new file mode 100644 index 00000000..52055a2d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/locale/locale.c @@ -0,0 +1,1474 @@ +/* Copyright (C) 2002 Manuel Novoa III + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* Nov. 1, 2002 + * Reworked setlocale() return values and locale arg processing to + * be more like glibc. Applications expecting to be able to + * query locale settings should now work... at the cost of almost + * doubling the size of the setlocale object code. + * Fixed a bug in the internal fixed-size-string locale specifier code. + * + * Dec 20, 2002 + * Added in collation support and updated stub nl_langinfo. + * + * Aug 1, 2003 + * Added glibc-like extended locale stuff (newlocale, duplocale, etc). + * + * Aug 18, 2003 + * Bug in duplocale... collation data wasn't copied. + * Bug in newlocale... translate 1< +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __UCLIBC_MJN3_ONLY__ +#ifdef L_setlocale +#warning TODO: Make the link_warning()s a config option? +#endif +#endif +#undef link_warning +#define link_warning(A,B) + +#undef __LOCALE_C_ONLY +#ifndef __UCLIBC_HAS_LOCALE__ +#define __LOCALE_C_ONLY +#endif /* __UCLIBC_HAS_LOCALE__ */ + + +#ifdef __LOCALE_C_ONLY + +#include + +#else /* __LOCALE_C_ONLY */ + +#ifdef __UCLIBC_MJN3_ONLY__ +#ifdef L_setlocale +#warning TODO: Fix the __CTYPE_HAS_8_BIT_LOCALES define at the top of the file. +#warning TODO: Fix __WCHAR_ENABLED. +#endif +#endif + +/* Need to include this before locale.h and xlocale.h! */ +#include + +#undef CODESET_LIST +#define CODESET_LIST (__locale_mmap->codeset_list) + +#ifdef __UCLIBC_HAS_XLOCALE__ +#include +#include +#else /* __UCLIBC_HAS_XLOCALE__ */ +/* We need this internally... */ +#define __UCLIBC_HAS_XLOCALE__ 1 +#include +#include +#undef __UCLIBC_HAS_XLOCALE__ +#endif /* __UCLIBC_HAS_XLOCALE__ */ + +#include + +#define LOCALE_NAMES (__locale_mmap->locale_names5) +#define LOCALES (__locale_mmap->locales) +#define LOCALE_AT_MODIFIERS (__locale_mmap->locale_at_modifiers) +#define CATEGORY_NAMES (__locale_mmap->lc_names) + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning REMINDER: redo the MAX_LOCALE_STR stuff... +#endif +#define MAX_LOCALE_STR 256 /* TODO: Only sufficient for current case. */ +#define MAX_LOCALE_CATEGORY_STR 32 /* TODO: Only sufficient for current case. */ +/* Note: Best if MAX_LOCALE_CATEGORY_STR is a power of 2. */ + +extern int _locale_set_l(const unsigned char *p, __locale_t base) attribute_hidden; +extern void _locale_init_l(__locale_t base) attribute_hidden; + +#endif /* __LOCALE_C_ONLY */ + +#undef LOCALE_STRING_SIZE +#define LOCALE_SELECTOR_SIZE (2 * __LC_ALL + 2) + +#ifdef __UCLIBC_MJN3_ONLY__ +#ifdef L_setlocale +#warning TODO: Create a C locale selector string. +#endif +#endif +#define C_LOCALE_SELECTOR "\x23\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80" + + +#include +#include + +/**********************************************************************/ +#ifdef L_setlocale + +#ifdef __LOCALE_C_ONLY + +link_warning(setlocale,"REMINDER: The 'setlocale' function supports only C|POSIX locales.") + +static const char C_string[] = "C"; + +char *setlocale(int category, register const char *locale) +{ + return ( (((unsigned int)(category)) <= LC_ALL) + && ( (!locale) /* Request for locale category string. */ + || (!*locale) /* Implementation-defined default is C. */ + || ((*locale == 'C') && !locale[1]) + || (!strcmp(locale, "POSIX"))) ) + ? (char *) C_string /* Always in C/POSIX locale. */ + : NULL; +} + +#else /* ---------------------------------------------- __LOCALE_C_ONLY */ + +#ifdef __UCLIBC_HAS_THREADS__ +link_warning(setlocale,"REMINDER: The 'setlocale' function is _not_ threadsafe except for simple queries.") +#endif + +#if !defined(__LOCALE_DATA_NUM_LOCALES) || (__LOCALE_DATA_NUM_LOCALES <= 1) +#error locales enabled, but not data other than for C locale! +#endif + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning TODO: Move posix and utf8 strings. +#endif +static const char posix[] = "POSIX"; +static const char utf8[] = "UTF-8"; + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning TODO: Fix dimensions of hr_locale. +#endif +/* Individual category strings start at hr_locale + category * MAX_LOCALE_CATEGORY. + * This holds for LC_ALL as well. + */ +static char hr_locale[(MAX_LOCALE_CATEGORY_STR * LC_ALL) + MAX_LOCALE_STR]; + + +static void update_hr_locale(const unsigned char *spec) +{ + const unsigned char *loc; + const unsigned char *s; + char *n; + int i, category, done; + + done = category = 0; + do { + s = spec + 1; + n = hr_locale + category * MAX_LOCALE_CATEGORY_STR; + + if (category == LC_ALL) { + done = 1; + for (i = 0 ; i < LC_ALL-1 ; i += 2) { + if ((s[i] != s[i+2]) || (s[i+1] != s[i+3])) { + goto SKIP; + } + } + /* All categories the same, so simplify string by using a single + * category. */ + category = LC_CTYPE; + } + + SKIP: + i = (category == LC_ALL) ? 0 : category; + s += 2*i; + + do { + if ((*s != 0xff) || (s[1] != 0xff)) { + loc = LOCALES + + __LOCALE_DATA_WIDTH_LOCALES * ((((int)(*s & 0x7f)) << 7) + + (s[1] & 0x7f)); + if (category == LC_ALL) { + /* CATEGORY_NAMES is unsigned char* */ + n = stpcpy(n, (char*) CATEGORY_NAMES + (int) CATEGORY_NAMES[i]); + *n++ = '='; + } + if (*loc == 0) { + *n++ = 'C'; + *n = 0; + } else { + char at = 0; + memcpy(n, LOCALE_NAMES + 5*((*loc)-1), 5); + if (n[2] != '_') { + at = n[2]; + n[2] = '_'; + } + n += 5; + *n++ = '.'; + if (loc[2] == 2) { + n = stpcpy(n, utf8); + } else if (loc[2] >= 3) { + n = stpcpy(n, (char*) CODESET_LIST + (int)(CODESET_LIST[loc[2] - 3])); + } + if (at) { + const char *q; + *n++ = '@'; + q = (char*) LOCALE_AT_MODIFIERS; + do { + if (q[1] == at) { + n = stpcpy(n, q+2); + break; + } + q += 2 + *q; + } while (*q); + } + } + *n++ = ';'; + } + s += 2; + } while (++i < category); + *--n = 0; /* Remove trailing ';' and nul-terminate. */ + + ++category; + } while (!done); +} + +char *setlocale(int category, const char *locale) +{ + if (((unsigned int)(category)) > LC_ALL) { +#if 0 + __set_errno(EINVAL); /* glibc sets errno -- SUSv3 doesn't say. */ +#endif + return NULL; /* Illegal/unsupported category. */ + } + + if (locale != NULL) { /* Not just a query... */ + if (!newlocale((1 << category), locale, __global_locale)) { + return NULL; /* Failed! */ + } + update_hr_locale(__global_locale->cur_locale); + } + + /* Either a query or a successful set, so return current locale string. */ + return hr_locale + (category * MAX_LOCALE_CATEGORY_STR); +} + +#endif /* __LOCALE_C_ONLY */ + +#endif +/**********************************************************************/ +#ifdef L_localeconv + +/* Note: We assume here that the compiler does the sane thing regarding + * placement of the fields in the struct. If necessary, we could ensure + * this usings an array of offsets but at some size cost. */ + + +#ifdef __LOCALE_C_ONLY + +link_warning(localeconv,"REMINDER: The 'localeconv' function is hardwired for C/POSIX locale only.") + +static struct lconv the_lconv; + +static const char decpt[] = "."; + +struct lconv *localeconv(void) +{ + register char *p = (char *)(&the_lconv); + + *((char **)p) = (char *) decpt; + do { + p += sizeof(char **); + *((char **)p) = (char *) (decpt+1); + } while (p < (char *) &the_lconv.negative_sign); + + p = (&the_lconv.int_frac_digits); + do { + *p = CHAR_MAX; + ++p; + } while (p <= &the_lconv.int_n_sign_posn); + + return &the_lconv; +} + +#else /* __LOCALE_C_ONLY */ + +static struct lconv the_lconv; + +struct lconv *localeconv(void) +{ + register char *p = (char *) &the_lconv; + register char **q = (char **) &(__UCLIBC_CURLOCALE->decimal_point); + + do { + *((char **)p) = *q; + p += sizeof(char **); + ++q; + } while (p < &the_lconv.int_frac_digits); + + do { + *p = **q; + ++p; + ++q; + } while (p <= &the_lconv.int_n_sign_posn); + + return &the_lconv; +} + +#endif /* __LOCALE_C_ONLY */ + +libc_hidden_def(localeconv) + +#endif +/**********************************************************************/ +#if defined(L__locale_init) && !defined(__LOCALE_C_ONLY) + +struct __uclibc_locale_struct __global_locale_data; + +__locale_t __global_locale = &__global_locale_data; + +#ifdef __UCLIBC_HAS_XLOCALE__ +__locale_t __curlocale_var = &__global_locale_data; +#endif + +/*----------------------------------------------------------------------*/ +#ifdef __UCLIBC_MJN3_ONLY__ +#warning TODO: Move utf8 and ascii strings. +#endif +static const char utf8[] = "UTF-8"; +static const char ascii[] = "ASCII"; + +typedef struct { + uint16_t num_base; + uint16_t num_der; + uint16_t MAX_WEIGHTS; + uint16_t num_index2weight; +#define num_index2ruleidx num_index2weight + uint16_t num_weightstr; + uint16_t num_multistart; + uint16_t num_override; + uint16_t num_ruletable; +} coldata_header_t; + +typedef struct { + uint16_t num_weights; + uint16_t num_starters; + uint16_t ii_shift; + uint16_t ti_shift; + uint16_t ii_len; + uint16_t ti_len; + uint16_t max_weight; + uint16_t num_col_base; + uint16_t max_col_index; + uint16_t undefined_idx; + uint16_t range_low; + uint16_t range_count; + uint16_t range_base_weight; + uint16_t range_rule_offset; + + uint16_t index2weight_offset; + uint16_t index2ruleidx_offset; + uint16_t multistart_offset; + uint16_t wcs2colidt_offset_low; + uint16_t wcs2colidt_offset_hi; +} coldata_base_t; + +typedef struct { + uint16_t base_idx; + uint16_t undefined_idx; + uint16_t overrides_offset; + uint16_t multistart_offset; +} coldata_der_t; + +static int init_cur_collate(int der_num, __collate_t *cur_collate) +{ + const uint16_t *__locale_collate_tbl = __locale_mmap->collate_data; + coldata_header_t *cdh; + coldata_base_t *cdb; + coldata_der_t *cdd; + const uint16_t *p; + size_t n; + uint16_t i, w; + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning kill of x86-specific asserts +#endif +#if 0 + assert(sizeof(coldata_base_t) == 19*2); + assert(sizeof(coldata_der_t) == 4*2); + assert(sizeof(coldata_header_t) == 8*2); +#endif + + if (!der_num) { /* C locale... special */ + cur_collate->num_weights = 0; + return 1; + } + + --der_num; + + cdh = (coldata_header_t *) __locale_collate_tbl; + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning CONSIDER: Should we assert here? +#endif +#if 0 + if (der_num >= cdh->num_der) { + return 0; + } +#else + assert((der_num < cdh->num_der)); +#endif + + cdd = (coldata_der_t *)(__locale_collate_tbl + + (sizeof(coldata_header_t) + + cdh->num_base * sizeof(coldata_base_t) + + der_num * sizeof(coldata_der_t) + )/2 ); + + cdb = (coldata_base_t *)(__locale_collate_tbl + + (sizeof(coldata_header_t) + + cdd->base_idx * sizeof(coldata_base_t) + )/2 ); + + memcpy(cur_collate, cdb, offsetof(coldata_base_t,index2weight_offset)); + cur_collate->undefined_idx = cdd->undefined_idx; + + cur_collate->ti_mask = (1 << cur_collate->ti_shift)-1; + cur_collate->ii_mask = (1 << cur_collate->ii_shift)-1; + +/* fflush(stdout); */ +/* fprintf(stderr,"base=%d num_col_base: %d %d\n", cdd->base_idx ,cur_collate->num_col_base, cdb->num_col_base); */ + + n = (sizeof(coldata_header_t) + cdh->num_base * sizeof(coldata_base_t) + + cdh->num_der * sizeof(coldata_der_t))/2; + +/* fprintf(stderr,"n = %d\n", n); */ + cur_collate->index2weight_tbl = __locale_collate_tbl + n + cdb->index2weight_offset; +/* fprintf(stderr,"i2w = %d\n", n + cdb->index2weight_offset); */ + n += cdh->num_index2weight; + cur_collate->index2ruleidx_tbl = __locale_collate_tbl + n + cdb->index2ruleidx_offset; +/* fprintf(stderr,"i2r = %d\n", n + cdb->index2ruleidx_offset); */ + n += cdh->num_index2ruleidx; + cur_collate->multistart_tbl = __locale_collate_tbl + n + cdd->multistart_offset; +/* fprintf(stderr,"mts = %d\n", n + cdb->multistart_offset); */ + n += cdh->num_multistart; + cur_collate->overrides_tbl = __locale_collate_tbl + n + cdd->overrides_offset; +/* fprintf(stderr,"ovr = %d\n", n + cdd->overrides_offset); */ + n += cdh->num_override; + cur_collate->ruletable = __locale_collate_tbl + n; +/* fprintf(stderr, "rtb = %d\n", n); */ + n += cdh->num_ruletable; + cur_collate->weightstr = __locale_collate_tbl + n; +/* fprintf(stderr,"wts = %d\n", n); */ + n += cdh->num_weightstr; + cur_collate->wcs2colidt_tbl = __locale_collate_tbl + n + + (((unsigned long)(cdb->wcs2colidt_offset_hi)) << 16) + + cdb->wcs2colidt_offset_low; +/* fprintf(stderr,"wcs = %lu\n", n + (((unsigned long)(cdb->wcs2colidt_offset_hi)) << 16) */ +/* + cdb->wcs2colidt_offset_low); */ + + cur_collate->MAX_WEIGHTS = cdh->MAX_WEIGHTS; + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning CONSIDER: Fix the +1 by increasing max_col_index? +#warning CONSIDER: Since this collate info is dependent only on LC_COLLATE ll_cc and not on codeset, we could just globally allocate this for each in a table +#endif + + cur_collate->index2weight = calloc(2*cur_collate->max_col_index+2, + sizeof(uint16_t)); + if (!cur_collate->index2weight) { + return 0; + } + cur_collate->index2ruleidx = cur_collate->index2weight + + cur_collate->max_col_index + 1; + + memcpy(cur_collate->index2weight, cur_collate->index2weight_tbl, + cur_collate->num_col_base * sizeof(uint16_t)); + memcpy(cur_collate->index2ruleidx, cur_collate->index2ruleidx_tbl, + cur_collate->num_col_base * sizeof(uint16_t)); + + /* now do the overrides */ + p = cur_collate->overrides_tbl; + while (*p > 1) { +/* fprintf(stderr, "processing override -- count = %d\n", *p); */ + n = *p++; + w = *p++; + do { + i = *p++; +/* fprintf(stderr, " i=%d (%#x) w=%d *p=%d\n", i, i, w, *p); */ + cur_collate->index2weight[i-1] = w++; + cur_collate->index2ruleidx[i-1] = *p++; + } while (--n); + } + assert(*p == 1); + while (*++p) { + i = *p; +/* fprintf(stderr, " i=%d (%#x) w=%d *p=%d\n", i, i, p[1], p[2]); */ + cur_collate->index2weight[i-1] = *++p; + cur_collate->index2ruleidx[i-1] = *++p; + } + + + for (i=0 ; i < cur_collate->multistart_tbl[0] ; i++) { + p = cur_collate->multistart_tbl; +/* fprintf(stderr, "%2d of %2d: %d ", i, cur_collate->multistart_tbl[0], p[i]); */ + p += p[i]; + + do { + n = *p++; + do { + if (!*p) { /* found it */ +/* fprintf(stderr, "found: n=%d (%#lx) |%.*ls|\n", n, (int) *cs->s, n, cs->s); */ +/* fprintf(stderr, ": %d - single\n", n); */ + goto FOUND; + } + /* the lookup check here is safe since we're assured that *p is a valid colidex */ +/* fprintf(stderr, "lookup(%lc)==%d *p==%d\n", cs->s[n], lookup(cs->s[n]), (int) *p); */ +/* fprintf(stderr, ": %d - ", n); */ + do { +/* fprintf(stderr, "%d|", *p); */ + } while (*p++); + break; + } while (1); + } while (1); + FOUND: + continue; + } + + return 1; +} + +int attribute_hidden _locale_set_l(const unsigned char *p, __locale_t base) +{ + const char **x; + unsigned char *s = base->cur_locale + 1; + const size_t *stp; + const unsigned char *r; + const uint16_t *io; + const uint16_t *ii; + const unsigned char *d; + int row; /* locale row */ + int crow; /* category row */ + int len; + int c; + int i = 0; + __collate_t newcol; + + ++p; + + newcol.index2weight = NULL; + if ((p[2*LC_COLLATE] != s[2*LC_COLLATE]) + || (p[2*LC_COLLATE + 1] != s[2*LC_COLLATE + 1]) + ) { + row = (((int)(*p & 0x7f)) << 7) + (p[1] & 0x7f); + assert(row < __LOCALE_DATA_NUM_LOCALES); + if (!init_cur_collate(__locale_mmap->locales[ __LOCALE_DATA_WIDTH_LOCALES + * row + 3 + LC_COLLATE ], + &newcol) + ) { + return 0; /* calloc failed. */ + } + free(base->collate.index2weight); + memcpy(&base->collate, &newcol, sizeof(__collate_t)); + } + + do { + if ((*p != *s) || (p[1] != s[1])) { + row = (((int)(*p & 0x7f)) << 7) + (p[1] & 0x7f); + assert(row < __LOCALE_DATA_NUM_LOCALES); + + *s = *p; + s[1] = p[1]; + + if ((i != LC_COLLATE) + && ((len = __locale_mmap->lc_common_item_offsets_LEN[i]) != 0) + ) { + crow = __locale_mmap->locales[ __LOCALE_DATA_WIDTH_LOCALES * row + + 3 + i ] + * len; + + x = (const char **)(((char *) base) + + base->category_offsets[i]); + + stp = __locale_mmap->lc_common_tbl_offsets + 4*i; + r = (const unsigned char *)( ((char *)__locale_mmap) + *stp ); + io = (const uint16_t *)( ((char *)__locale_mmap) + *++stp ); + ii = (const uint16_t *)( ((char *)__locale_mmap) + *++stp ); + d = (const unsigned char *)( ((char *)__locale_mmap) + *++stp ); + for (c = 0; c < len; c++) { + x[c] = (char*)(d + ii[r[crow + c] + io[c]]); + } + } + if (i == LC_CTYPE) { + c = __locale_mmap->locales[ __LOCALE_DATA_WIDTH_LOCALES * row + + 2 ]; /* codeset */ + if (c <= 2) { + if (c == 2) { + base->codeset = utf8; + base->encoding = __ctype_encoding_utf8; + /* TODO - fix for bcc */ + base->mb_cur_max = 6; + } else { + assert(c == 1); + base->codeset = ascii; + base->encoding = __ctype_encoding_7_bit; + base->mb_cur_max = 1; + } + } else { + const __codeset_8_bit_t *c8b; + r = CODESET_LIST; + c -= 3; + base->codeset = (char *) (r + r[c]); + base->encoding = __ctype_encoding_8_bit; +#ifdef __UCLIBC_MJN3_ONLY__ +#warning REMINDER: update 8 bit mb_cur_max when translit implemented! +#endif + /* TODO - update when translit implemented! */ + base->mb_cur_max = 1; + c8b = __locale_mmap->codeset_8_bit + c; +#ifdef __CTYPE_HAS_8_BIT_LOCALES + base->idx8ctype = c8b->idx8ctype; + base->idx8uplow = c8b->idx8uplow; +#ifdef __UCLIBC_HAS_WCHAR__ + base->idx8c2wc = c8b->idx8c2wc; + base->idx8wc2c = c8b->idx8wc2c; + /* translit */ +#endif /* __UCLIBC_HAS_WCHAR__ */ + + /* What follows is fairly bloated, but it is just a hack + * to get the 8-bit codeset ctype stuff functioning. + * All of this will be replaced in the next generation + * of locale support anyway... */ + + memcpy(base->__ctype_b_data, + __C_ctype_b - __UCLIBC_CTYPE_B_TBL_OFFSET, + (256 + __UCLIBC_CTYPE_B_TBL_OFFSET) + * sizeof(__ctype_mask_t)); + memcpy(base->__ctype_tolower_data, + __C_ctype_tolower - __UCLIBC_CTYPE_TO_TBL_OFFSET, + (256 + __UCLIBC_CTYPE_TO_TBL_OFFSET) + * sizeof(__ctype_touplow_t)); + memcpy(base->__ctype_toupper_data, + __C_ctype_toupper - __UCLIBC_CTYPE_TO_TBL_OFFSET, + (256 + __UCLIBC_CTYPE_TO_TBL_OFFSET) + * sizeof(__ctype_touplow_t)); + +#define Cctype_TBL_MASK ((1 << __LOCALE_DATA_Cctype_IDX_SHIFT) - 1) +#define Cctype_IDX_OFFSET (128 >> __LOCALE_DATA_Cctype_IDX_SHIFT) + + { + int u; + __ctype_mask_t m; + + for (u=0 ; u < 128 ; u++) { +#ifdef __LOCALE_DATA_Cctype_PACKED + c = base->tbl8ctype + [ ((int)(c8b->idx8ctype + [(u >> __LOCALE_DATA_Cctype_IDX_SHIFT) ]) + << (__LOCALE_DATA_Cctype_IDX_SHIFT - 1)) + + ((u & Cctype_TBL_MASK) >> 1)]; + c = (u & 1) ? (c >> 4) : (c & 0xf); +#else + c = base->tbl8ctype + [ ((int)(c8b->idx8ctype + [(u >> __LOCALE_DATA_Cctype_IDX_SHIFT) ]) + << __LOCALE_DATA_Cctype_IDX_SHIFT) + + (u & Cctype_TBL_MASK) ]; +#endif + + m = base->code2flag[c]; + + base->__ctype_b_data + [128 + __UCLIBC_CTYPE_B_TBL_OFFSET + u] + = m; + +#ifdef __UCLIBC_HAS_CTYPE_SIGNED__ + if (((signed char)(128 + u)) != -1) { + base->__ctype_b_data[__UCLIBC_CTYPE_B_TBL_OFFSET + + ((signed char)(128 + u))] + = m; + } +#endif + + base->__ctype_tolower_data + [128 + __UCLIBC_CTYPE_TO_TBL_OFFSET + u] + = 128 + u; + base->__ctype_toupper_data + [128 + __UCLIBC_CTYPE_TO_TBL_OFFSET + u] + = 128 + u; + + if (m & (_ISlower|_ISupper)) { + c = base->tbl8uplow + [ ((int)(c8b->idx8uplow + [u >> __LOCALE_DATA_Cuplow_IDX_SHIFT]) + << __LOCALE_DATA_Cuplow_IDX_SHIFT) + + ((128 + u) + & ((1 << __LOCALE_DATA_Cuplow_IDX_SHIFT) + - 1)) ]; + if (m & _ISlower) { + base->__ctype_toupper_data + [128 + __UCLIBC_CTYPE_TO_TBL_OFFSET + u] + = (unsigned char)(128 + u + c); +#ifdef __UCLIBC_HAS_CTYPE_SIGNED__ + if (((signed char)(128 + u)) != -1) { + base->__ctype_toupper_data + [__UCLIBC_CTYPE_TO_TBL_OFFSET + + ((signed char)(128 + u))] + = (unsigned char)(128 + u + c); + } +#endif + } else { + base->__ctype_tolower_data + [128 + __UCLIBC_CTYPE_TO_TBL_OFFSET + u] + = (unsigned char)(128 + u - c); +#ifdef __UCLIBC_HAS_CTYPE_SIGNED__ + if (((signed char)(128 + u)) != -1) { + base->__ctype_tolower_data + [__UCLIBC_CTYPE_TO_TBL_OFFSET + + ((signed char)(128 + u))] + = (unsigned char)(128 + u - c); + } +#endif + } + } + } + } + +#ifdef __UCLIBC_HAS_XLOCALE__ + base->__ctype_b = base->__ctype_b_data + + __UCLIBC_CTYPE_B_TBL_OFFSET; + base->__ctype_tolower = base->__ctype_tolower_data + + __UCLIBC_CTYPE_TO_TBL_OFFSET; + base->__ctype_toupper = base->__ctype_toupper_data + + __UCLIBC_CTYPE_TO_TBL_OFFSET; +#else /* __UCLIBC_HAS_XLOCALE__ */ + __ctype_b = base->__ctype_b_data + + __UCLIBC_CTYPE_B_TBL_OFFSET; + __ctype_tolower = base->__ctype_tolower_data + + __UCLIBC_CTYPE_TO_TBL_OFFSET; + __ctype_toupper = base->__ctype_toupper_data + + __UCLIBC_CTYPE_TO_TBL_OFFSET; +#endif /* __UCLIBC_HAS_XLOCALE__ */ + +#endif /* __CTYPE_HAS_8_BIT_LOCALES */ + } +#ifdef __UCLIBC_MJN3_ONLY__ +#warning TODO: Put the outdigit string length in the locale_mmap object. +#endif + d = base->outdigit_length; + x = &base->outdigit0_mb; + for (c = 0 ; c < 10 ; c++) { + ((unsigned char *)d)[c] = strlen(x[c]); + assert(d[c] > 0); + } + } else if (i == LC_NUMERIC) { + assert(LC_NUMERIC > LC_CTYPE); /* Need ctype initialized. */ + + base->decimal_point_len + = __locale_mbrtowc_l(&base->decimal_point_wc, + base->decimal_point, base); + assert(base->decimal_point_len > 0); + assert(base->decimal_point[base->decimal_point_len] == 0); + + if (*base->grouping) { + base->thousands_sep_len + = __locale_mbrtowc_l(&base->thousands_sep_wc, + base->thousands_sep, base); +#if 1 +#ifdef __UCLIBC_MJN3_ONLY__ +#warning TODO: Remove hack involving grouping without a thousep char (bg_BG). +#endif + assert(base->thousands_sep_len >= 0); + if (base->thousands_sep_len == 0) { + base->grouping = base->thousands_sep; /* empty string */ + } + assert(base->thousands_sep[base->thousands_sep_len] == 0); +#else + assert(base->thousands_sep_len > 0); + assert(base->thousands_sep[base->thousands_sep_len] == 0); +#endif + } + +/* } else if (i == LC_COLLATE) { */ +/* init_cur_collate(__locale_mmap->locales[ __LOCALE_DATA_WIDTH_LOCALES */ +/* * row + 3 + i ], */ +/* &base->collate); */ + } + } + ++i; + p += 2; + s += 2; + } while (i < LC_ALL); + + return 1; +} + +static const uint16_t __code2flag[16] = { + 0, /* unclassified = 0 */ + _ISprint|_ISgraph|_ISalnum|_ISalpha, /* alpha_nonupper_nonlower */ + _ISprint|_ISgraph|_ISalnum|_ISalpha|_ISlower, /* alpha_lower */ + _ISprint|_ISgraph|_ISalnum|_ISalpha|_ISlower|_ISupper, /* alpha_upper_lower */ + _ISprint|_ISgraph|_ISalnum|_ISalpha|_ISupper, /* alpha_upper */ + _ISprint|_ISgraph|_ISalnum|_ISdigit, /* digit */ + _ISprint|_ISgraph|_ISpunct, /* punct */ + _ISprint|_ISgraph, /* graph */ + _ISprint|_ISspace, /* print_space_nonblank */ + _ISprint|_ISspace|_ISblank, /* print_space_blank */ + _ISspace, /* space_nonblank_noncntrl */ + _ISspace|_ISblank, /* space_blank_noncntrl */ + _IScntrl|_ISspace, /* cntrl_space_nonblank */ + _IScntrl|_ISspace|_ISblank, /* cntrl_space_blank */ + _IScntrl /* cntrl_nonspace */ +}; + +void attribute_hidden _locale_init_l(__locale_t base) +{ + memset(base->cur_locale, 0, LOCALE_SELECTOR_SIZE); + base->cur_locale[0] = '#'; + + memcpy(base->category_item_count, + __locale_mmap->lc_common_item_offsets_LEN, + LC_ALL); + + ++base->category_item_count[0]; /* Increment for codeset entry. */ + base->category_offsets[0] = offsetof(struct __uclibc_locale_struct, outdigit0_mb); + base->category_offsets[1] = offsetof(struct __uclibc_locale_struct, decimal_point); + base->category_offsets[2] = offsetof(struct __uclibc_locale_struct, int_curr_symbol); + base->category_offsets[3] = offsetof(struct __uclibc_locale_struct, abday_1); +/* base->category_offsets[4] = offsetof(struct __uclibc_locale_struct, collate???); */ + base->category_offsets[5] = offsetof(struct __uclibc_locale_struct, yesexpr); + +#ifdef __CTYPE_HAS_8_BIT_LOCALES + base->tbl8ctype + = (const unsigned char *) &__locale_mmap->tbl8ctype; + base->tbl8uplow + = (const unsigned char *) &__locale_mmap->tbl8uplow; +#ifdef __UCLIBC_HAS_WCHAR__ + base->tbl8c2wc + = (const uint16_t *) &__locale_mmap->tbl8c2wc; + base->tbl8wc2c + = (const unsigned char *) &__locale_mmap->tbl8wc2c; + /* translit */ +#endif /* __UCLIBC_HAS_WCHAR__ */ +#endif /* __CTYPE_HAS_8_BIT_LOCALES */ +#ifdef __UCLIBC_HAS_WCHAR__ + base->tblwctype + = (const unsigned char *) &__locale_mmap->tblwctype; + base->tblwuplow + = (const unsigned char *) &__locale_mmap->tblwuplow; + base->tblwuplow_diff + = (const int16_t *) &__locale_mmap->tblwuplow_diff; +/* base->tblwcomb */ +/* = (const unsigned char *) &__locale_mmap->tblwcomb; */ + /* width?? */ +#endif /* __UCLIBC_HAS_WCHAR__ */ + + /* Initially, set things up to use the global C ctype tables. + * This is correct for C (ASCII) and UTF-8 based locales (except tr_TR). */ +#ifdef __UCLIBC_HAS_XLOCALE__ + base->__ctype_b = __C_ctype_b; + base->__ctype_tolower = __C_ctype_tolower; + base->__ctype_toupper = __C_ctype_toupper; +#else /* __UCLIBC_HAS_XLOCALE__ */ + __ctype_b = __C_ctype_b; + __ctype_tolower = __C_ctype_tolower; + __ctype_toupper = __C_ctype_toupper; +#endif /* __UCLIBC_HAS_XLOCALE__ */ + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning TODO: Initialize code2flag correctly based on locale_mmap. +#endif + base->code2flag = __code2flag; + + _locale_set_l((unsigned char*) C_LOCALE_SELECTOR, base); +} + +void _locale_init(void) attribute_hidden; +void _locale_init(void) +{ + /* TODO: mmap the locale file */ + + /* TODO - ??? */ + _locale_init_l(__global_locale); +} + +#endif +/**********************************************************************/ +#if defined(L_nl_langinfo) || defined(L_nl_langinfo_l) + +#ifdef __LOCALE_C_ONLY + +/* We need to index 320 bytes of data, so you might initially think we + * need to store the offsets in shorts. But since the offset of the + * 64th item is 182, we'll store "offset - 2*64" for all items >= 64 + * and always calculate the data offset as "offset[i] + 2*(i & 64)". + * This allows us to pack the data offsets in an unsigned char while + * also avoiding an "if". + * + * Note: Category order is assumed to be: + * ctype, numeric, monetary, time, collate, messages, all + */ + +#define C_LC_ALL 6 + +/* Combine the data to avoid size penalty for seperate char arrays when + * compiler aligns objects. The original code is left in as documentation. */ +#define cat_start nl_data +#define C_locale_data (nl_data + C_LC_ALL + 1 + 90) + +static const unsigned char nl_data[C_LC_ALL + 1 + 90 + 320] = { +/* static const char cat_start[LC_ALL + 1] = { */ + '\x00', '\x0b', '\x0e', '\x24', '\x56', '\x56', '\x5a', +/* }; */ +/* static const char item_offset[90] = { */ + '\x00', '\x02', '\x04', '\x06', '\x08', '\x0a', '\x0c', '\x0e', + '\x10', '\x12', '\x14', '\x1a', '\x1b', '\x1b', '\x1b', '\x1b', + '\x1b', '\x1b', '\x1b', '\x1b', '\x1b', '\x1c', '\x1c', '\x1c', + '\x1c', '\x1c', '\x1c', '\x1c', '\x1c', '\x1c', '\x1c', '\x1c', + '\x1c', '\x1c', '\x1c', '\x1e', '\x20', '\x24', '\x28', '\x2c', + '\x30', '\x34', '\x38', '\x3c', '\x43', '\x4a', '\x52', '\x5c', + '\x65', '\x6c', '\x75', '\x79', '\x7d', '\x81', '\x85', '\x89', + '\x8d', '\x91', '\x95', '\x99', '\x9d', '\xa1', '\xa5', '\xad', + '\x36', '\x3c', '\x42', '\x46', '\x4b', '\x50', '\x57', '\x61', + '\x69', '\x72', '\x7b', '\x7e', '\x81', '\x96', '\x9f', '\xa8', + '\xb3', '\xb3', '\xb3', '\xb3', '\xb3', '\xb3', '\xb4', '\xba', + '\xbf', '\xbf', +/* }; */ +/* static const char C_locale_data[320] = { */ + '0', '\x00', '1', '\x00', '2', '\x00', '3', '\x00', + '4', '\x00', '5', '\x00', '6', '\x00', '7', '\x00', + '8', '\x00', '9', '\x00', 'A', 'S', 'C', 'I', + 'I', '\x00', '.', '\x00', '\x7f', '\x00', '-', '\x00', + 'S', 'u', 'n', '\x00', 'M', 'o', 'n', '\x00', + 'T', 'u', 'e', '\x00', 'W', 'e', 'd', '\x00', + 'T', 'h', 'u', '\x00', 'F', 'r', 'i', '\x00', + 'S', 'a', 't', '\x00', 'S', 'u', 'n', 'd', + 'a', 'y', '\x00', 'M', 'o', 'n', 'd', 'a', + 'y', '\x00', 'T', 'u', 'e', 's', 'd', 'a', + 'y', '\x00', 'W', 'e', 'd', 'n', 'e', 's', + 'd', 'a', 'y', '\x00', 'T', 'h', 'u', 'r', + 's', 'd', 'a', 'y', '\x00', 'F', 'r', 'i', + 'd', 'a', 'y', '\x00', 'S', 'a', 't', 'u', + 'r', 'd', 'a', 'y', '\x00', 'J', 'a', 'n', + '\x00', 'F', 'e', 'b', '\x00', 'M', 'a', 'r', + '\x00', 'A', 'p', 'r', '\x00', 'M', 'a', 'y', + '\x00', 'J', 'u', 'n', '\x00', 'J', 'u', 'l', + '\x00', 'A', 'u', 'g', '\x00', 'S', 'e', 'p', + '\x00', 'O', 'c', 't', '\x00', 'N', 'o', 'v', + '\x00', 'D', 'e', 'c', '\x00', 'J', 'a', 'n', + 'u', 'a', 'r', 'y', '\x00', 'F', 'e', 'b', + 'r', 'u', 'a', 'r', 'y', '\x00', 'M', 'a', + 'r', 'c', 'h', '\x00', 'A', 'p', 'r', 'i', + 'l', '\x00', 'M', 'a', 'y', '\x00', 'J', 'u', + 'n', 'e', '\x00', 'J', 'u', 'l', 'y', '\x00', + 'A', 'u', 'g', 'u', 's', 't', '\x00', 'S', + 'e', 'p', 't', 'e', 'm', 'b', 'e', 'r', + '\x00', 'O', 'c', 't', 'o', 'b', 'e', 'r', + '\x00', 'N', 'o', 'v', 'e', 'm', 'b', 'e', + 'r', '\x00', 'D', 'e', 'c', 'e', 'm', 'b', + 'e', 'r', '\x00', 'A', 'M', '\x00', 'P', 'M', + '\x00', '%', 'a', ' ', '%', 'b', ' ', '%', + 'e', ' ', '%', 'H', ':', '%', 'M', ':', + '%', 'S', ' ', '%', 'Y', '\x00', '%', 'm', + '/', '%', 'd', '/', '%', 'y', '\x00', '%', + 'H', ':', '%', 'M', ':', '%', 'S', '\x00', + '%', 'I', ':', '%', 'M', ':', '%', 'S', + ' ', '%', 'p', '\x00', '^', '[', 'y', 'Y', + ']', '\x00', '^', '[', 'n', 'N', ']', '\x00', +}; + +char *nl_langinfo(nl_item item) +{ + unsigned int c; + unsigned int i; + + if ((c = _NL_ITEM_CATEGORY(item)) < C_LC_ALL) { + if ((i = cat_start[c] + _NL_ITEM_INDEX(item)) < cat_start[c+1]) { +/* return (char *) C_locale_data + item_offset[i] + (i & 64); */ + return (char *) C_locale_data + nl_data[C_LC_ALL+1+i] + 2*(i & 64); + } + } + return (char *) cat_start; /* Conveniently, this is the empty string. */ +} +libc_hidden_def(nl_langinfo) + +#else /* __LOCALE_C_ONLY */ + +#if defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) + + + +char *nl_langinfo(nl_item item) +{ + return nl_langinfo_l(item, __UCLIBC_CURLOCALE); +} +libc_hidden_def(nl_langinfo) + +#else /* defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) */ + +libc_hidden_proto(__XL_NPP(nl_langinfo)) + +static const char empty[] = ""; + +char *__XL_NPP(nl_langinfo)(nl_item item __LOCALE_PARAM ) +{ + unsigned int c = _NL_ITEM_CATEGORY(item); + unsigned int i = _NL_ITEM_INDEX(item); + + if ((c < LC_ALL) && (i < __LOCALE_PTR->category_item_count[c])) { + return ((char **)(((char *) __LOCALE_PTR) + + __LOCALE_PTR->category_offsets[c]))[i]; + } + + return (char *) empty; +} +libc_hidden_def(__XL_NPP(nl_langinfo)) + +#endif /* defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) */ + +#endif /* __LOCALE_C_ONLY */ + +#endif +/**********************************************************************/ +#ifdef L_newlocale + + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning TODO: Move posix and utf8 strings. +#endif +static const char posix[] = "POSIX"; +static const char utf8[] = "UTF-8"; + +static int find_locale(int category_mask, const char *p, + unsigned char *new_locale) +{ + int i; + const unsigned char *s; + uint16_t n; + unsigned char lang_cult, codeset; + +#if defined(__LOCALE_DATA_AT_MODIFIERS_LENGTH) && 1 + /* Support standard locale handling for @-modifiers. */ + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning REMINDER: Fix buf size in find_locale. +#endif + char buf[18]; /* TODO: 7+{max codeset name length} */ + const char *q; + + if ((q = strchr(p,'@')) != NULL) { + if ((((size_t)((q-p)-5)) > (sizeof(buf) - 5)) || (p[2] != '_')) { + return 0; + } + /* locale name at least 5 chars long and 3rd char is '_' */ + s = LOCALE_AT_MODIFIERS; + do { + if (!strcmp((char*) (s + 2), q + 1)) { + break; + } + s += 2 + *s; /* TODO - fix this throughout */ + } while (*s); + if (!*s) { + return 0; + } + assert(q - p < sizeof(buf)); + memcpy(buf, p, q-p); + buf[q-p] = 0; + buf[2] = s[1]; + p = buf; + } +#endif + + lang_cult = codeset = 0; /* Assume C and default codeset. */ + if (((*p == 'C') && !p[1]) || !strcmp(p, posix)) { + goto FIND_LOCALE; + } + + if ((strlen(p) > 5) && (p[5] == '.')) { /* Codeset in locale name? */ + /* TODO: maybe CODESET_LIST + *s ??? */ + /* 7bit is 1, UTF-8 is 2, 8-bit is >= 3 */ + codeset = 2; + if (strcasecmp(utf8, p + 6) != 0) {/* TODO - fix! */ + s = CODESET_LIST; + do { + ++codeset; /* Increment codeset first. */ + if (!strcmp((char*) CODESET_LIST + *s, p + 6)) { + goto FIND_LANG_CULT; + } + } while (*++s); + return 0; /* No matching codeset! */ + } + } + + FIND_LANG_CULT: /* Find language_culture number. */ + s = LOCALE_NAMES; + do { /* TODO -- do a binary search? */ + /* TODO -- fix gen_mmap!*/ + ++lang_cult; /* Increment first since C/POSIX is 0. */ + if (!strncmp((char*) s, p, 5)) { /* Found a matching locale name; */ + goto FIND_LOCALE; + } + s += 5; + } while (lang_cult < __LOCALE_DATA_NUM_LOCALE_NAMES); + return 0; /* No matching language_culture! */ + + FIND_LOCALE: /* Find locale row matching name and codeset */ + s = LOCALES; + n = 0; + do { /* TODO -- do a binary search? */ + if ((lang_cult == *s) && ((codeset == s[1]) || (codeset == s[2]))) { + i = 1; + s = new_locale + 1; + do { + if (category_mask & i) { + /* Encode current locale row number. */ + ((unsigned char *) s)[0] = (n >> 7) | 0x80; + ((unsigned char *) s)[1] = (n & 0x7f) | 0x80; + } + s += 2; + i += i; + } while (i < (1 << LC_ALL)); + + return i; /* Return non-zero */ + } + s += __LOCALE_DATA_WIDTH_LOCALES; + ++n; + } while (n <= __LOCALE_DATA_NUM_LOCALES); /* We started at 1!!! */ + + return 0; /* Unsupported locale. */ +} + +static unsigned char *composite_locale(int category_mask, const char *locale, + unsigned char *new_locale) +{ + char buf[MAX_LOCALE_STR]; + char *t; + char *e; + int c; + int component_mask; + + if (!strchr(locale,'=')) { + if (!find_locale(category_mask, locale, new_locale)) { + return NULL; + } + return new_locale; + } + + if (strlen(locale) >= sizeof(buf)) { + return NULL; + } + stpcpy(buf, locale); + + component_mask = 0; + t = strtok_r(buf, "=", &e); /* This can't fail because of strchr test above. */ + do { + c = 0; + /* CATEGORY_NAMES is unsigned char* */ + while (strcmp((char*) CATEGORY_NAMES + (int) CATEGORY_NAMES[c], t)) { + if (++c == LC_ALL) { /* Unknown category name! */ + return NULL; + } + } + t = strtok_r(NULL, ";", &e); + c = (1 << c); + if (component_mask & c) { /* Multiple components for one category. */ + return NULL; + } + component_mask |= c; + if ((category_mask & c) && (!t || !find_locale(c, t, new_locale))) { + return NULL; + } + } while ((t = strtok_r(NULL, "=", &e)) != NULL); + + if (category_mask & ~component_mask) { /* Category component(s) missing. */ + return NULL; + } + + return new_locale; +} + +__locale_t newlocale(int category_mask, const char *locale, __locale_t base) +{ + const char *p; + int i, j, k; + unsigned char new_selector[LOCALE_SELECTOR_SIZE]; + + if (category_mask == (1 << LC_ALL)) { + category_mask = LC_ALL_MASK; + } + + if (!locale || ((unsigned)(category_mask) > LC_ALL_MASK)) { + INVALID: + __set_errno(EINVAL); + return NULL; /* No locale or illegal/unsupported category. */ + } + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning TODO: Rename cur_locale to locale_selector. +#endif + strcpy((char *) new_selector, + (base ? (char *) base->cur_locale : C_LOCALE_SELECTOR)); + + if (!locale[0]) { /* locale == "", so check environment. */ + const char *envstr[4]; + + envstr[0] = "LC_ALL"; + envstr[1] = NULL; + envstr[2] = "LANG"; + envstr[3] = posix; + + i = 1; + k = 0; + do { + if (category_mask & i) { + /* Note: SUSv3 doesn't define a fallback mechanism here. + * So, if LC_ALL is invalid, we do _not_ continue trying + * the other environment vars. */ + envstr[1] = (char*) CATEGORY_NAMES + CATEGORY_NAMES[k]; + j = 0; + while (1) { + p = envstr[j]; + if (++j >= 4) + break; /* now p == "POSIX" */ + p = getenv(p); + if (p && p[0]) + break; + }; + + /* The user set something... is it valid? */ + /* Note: Since we don't support user-supplied locales and + * alternate paths, we don't need to worry about special + * handling for suid/sgid apps. */ + if (!find_locale(i, p, new_selector)) { + goto INVALID; + } + } + i += i; + } while (++k < LC_ALL); + } else if (!composite_locale(category_mask, locale, new_selector)) { + goto INVALID; + } + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning TODO: Do a compatible codeset check! +#endif + + /* If we get here, the new selector corresponds to a valid locale. */ + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning CONSIDER: Probably want a _locale_new func to allow for caching of locales. +#endif +#if 0 + if (base) { + _locale_set_l(new_selector, base); + } else { + base = _locale_new(new_selector); + } +#else + if (!base) { + base = malloc(sizeof(struct __uclibc_locale_struct)); + if (base == NULL) + return base; + _locale_init_l(base); + } + + _locale_set_l(new_selector, base); +#endif + + return base; +} +libc_hidden_def(newlocale) + +#endif +/**********************************************************************/ +#ifdef L_duplocale + + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning REMINDER: When we allocate ctype tables, remember to dup them. +#endif + +__locale_t duplocale(__locale_t dataset) +{ + __locale_t r; + uint16_t * i2w; + size_t n; + + assert(dataset != LC_GLOBAL_LOCALE); + + r = malloc(sizeof(struct __uclibc_locale_struct)); + if (r != NULL) { + n = 2 * dataset->collate.max_col_index + 2; + i2w = calloc(n, sizeof(uint16_t)); + if (i2w != NULL) { + memcpy(r, dataset, sizeof(struct __uclibc_locale_struct)); + r->collate.index2weight = i2w; + memcpy(i2w, dataset->collate.index2weight, n * sizeof(uint16_t)); + } else { + free(r); + r = NULL; + } + } + return r; +} +libc_hidden_def(duplocale) + +#endif +/**********************************************************************/ +#ifdef L_freelocale + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning REMINDER: When we allocate ctype tables, remember to free them. +#endif + +void freelocale(__locale_t dataset) +{ + assert(dataset != __global_locale); + assert(dataset != LC_GLOBAL_LOCALE); + + free(dataset->collate.index2weight); /* Free collation data. */ + free(dataset); /* Free locale */ +} + +#endif +/**********************************************************************/ +#ifdef L_uselocale + +__locale_t uselocale(__locale_t dataset) +{ + __locale_t old; + + if (!dataset) { + old = __UCLIBC_CURLOCALE; + } else { + if (dataset == LC_GLOBAL_LOCALE) { + dataset = __global_locale; + } +#ifdef __UCLIBC_HAS_THREADS__ + old = __curlocale_set(dataset); +#else + old = __curlocale_var; + __curlocale_var = dataset; +#endif + } + + if (old == __global_locale) { + return LC_GLOBAL_LOCALE; + } + return old; +} +libc_hidden_def(uselocale) + +#endif +/**********************************************************************/ +#ifdef L___curlocale + +#ifdef __UCLIBC_HAS_THREADS__ + +__locale_t weak_const_function __curlocale(void) +{ + return __curlocale_var; /* This is overriden by the thread version. */ +} + +__locale_t weak_function __curlocale_set(__locale_t newloc) +{ + __locale_t oldloc = __curlocale_var; + assert(newloc != LC_GLOBAL_LOCALE); + __curlocale_var = newloc; + return oldloc; +} + +#endif + +#endif +/**********************************************************************/ +#ifdef L___locale_mbrtowc_l + +/* NOTE: This returns an int... not size_t. Also, it is not a general + * routine. It is actually a very stripped-down version of mbrtowc + * that takes a __locale_t arg. This is used by strcoll and strxfrm. + * It is also used above to generate wchar_t versions of the decimal point + * and thousands seperator. */ + + +#ifndef __CTYPE_HAS_UTF_8_LOCALES +#warning __CTYPE_HAS_UTF_8_LOCALES not set! +#endif +#ifndef __CTYPE_HAS_8_BIT_LOCALES +#warning __CTYPE_HAS_8_BIT_LOCALES not set! +#endif + +#define Cc2wc_IDX_SHIFT __LOCALE_DATA_Cc2wc_IDX_SHIFT +#define Cc2wc_ROW_LEN __LOCALE_DATA_Cc2wc_ROW_LEN + +extern size_t _wchar_utf8sntowcs(wchar_t *__restrict pwc, size_t wn, + const char **__restrict src, size_t n, + mbstate_t *ps, int allow_continuation) attribute_hidden; + +int attribute_hidden __locale_mbrtowc_l(wchar_t *__restrict dst, + const char *__restrict src, + __locale_t loc ) +{ +#ifdef __CTYPE_HAS_UTF_8_LOCALES + if (loc->encoding == __ctype_encoding_utf8) { + mbstate_t ps; + const char *p = src; + size_t r; + ps.__mask = 0; + r = _wchar_utf8sntowcs(dst, 1, &p, SIZE_MAX, &ps, 1); + return (r == 1) ? (p-src) : r; /* Need to return 0 if nul char. */ + } +#endif + +#ifdef __CTYPE_HAS_8_BIT_LOCALES + assert((loc->encoding == __ctype_encoding_7_bit) || (loc->encoding == __ctype_encoding_8_bit)); +#else + assert(loc->encoding == __ctype_encoding_7_bit); +#endif + + if ((*dst = ((unsigned char)(*src))) < 0x80) { /* ASCII... */ + return (*src != 0); + } + +#ifdef __CTYPE_HAS_8_BIT_LOCALES + if (loc->encoding == __ctype_encoding_8_bit) { + wchar_t wc = *dst - 0x80; + *dst = loc->tbl8c2wc[ + (loc->idx8c2wc[wc >> Cc2wc_IDX_SHIFT] + << Cc2wc_IDX_SHIFT) + (wc & (Cc2wc_ROW_LEN - 1))]; + if (*dst) { + return 1; + } + } +#endif + + return -1; +} + +#endif +/**********************************************************************/ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/locale/localeconv.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/locale/localeconv.c new file mode 100644 index 00000000..7e67fb24 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/locale/localeconv.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_localeconv +#include "locale.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/locale/newlocale.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/locale/newlocale.c new file mode 100644 index 00000000..a9868849 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/locale/newlocale.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_newlocale +#include "locale.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/locale/nl_langinfo.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/locale/nl_langinfo.c new file mode 100644 index 00000000..0bc0a002 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/locale/nl_langinfo.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_nl_langinfo +#include "locale.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/locale/nl_langinfo_l.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/locale/nl_langinfo_l.c new file mode 100644 index 00000000..7205ccab --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/locale/nl_langinfo_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_nl_langinfo_l +#define __UCLIBC_DO_XLOCALE +#include "locale.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/locale/setlocale.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/locale/setlocale.c new file mode 100644 index 00000000..1eae88ac --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/locale/setlocale.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_setlocale +#include "locale.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/locale/uselocale.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/locale/uselocale.c new file mode 100644 index 00000000..2aecc549 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/locale/uselocale.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_uselocale +#define __UCLIBC_DO_XLOCALE +#include "locale.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/mntent/.indent.pro b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/mntent/.indent.pro new file mode 100644 index 00000000..492ecf1c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/mntent/.indent.pro @@ -0,0 +1,33 @@ +--blank-lines-after-declarations +--blank-lines-after-procedures +--break-before-boolean-operator +--no-blank-lines-after-commas +--braces-on-if-line +--braces-on-struct-decl-line +--comment-indentation25 +--declaration-comment-column25 +--no-comment-delimiters-on-blank-lines +--cuddle-else +--continuation-indentation4 +--case-indentation0 +--else-endif-column33 +--space-after-cast +--line-comments-indentation0 +--declaration-indentation1 +--dont-format-first-column-comments +--dont-format-comments +--honour-newlines +--indent-level4 +/* changed from 0 to 4 */ +--parameter-indentation4 +--line-length78 /* changed from 75 */ +--continue-at-parentheses +--no-space-after-function-call-names +--dont-break-procedure-type +--dont-star-comments +--leave-optional-blank-lines +--dont-space-special-semicolon +--tab-size4 +/* additions by Mark */ +--case-brace-indentation0 +--leave-preprocessor-space diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/mntent/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/mntent/Makefile new file mode 100644 index 00000000..4a8f4a07 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/mntent/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../ +top_builddir=../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/mntent/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/mntent/Makefile.in new file mode 100644 index 00000000..daa888da --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/mntent/Makefile.in @@ -0,0 +1,23 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +subdirs += libc/misc/mntent + +CSRC := mntent.c + +MISC_MNTENT_DIR := $(top_srcdir)libc/misc/mntent +MISC_MNTENT_OUT := $(top_builddir)libc/misc/mntent + +MISC_MNTENT_SRC := $(MISC_MNTENT_DIR)/mntent.c +MISC_MNTENT_OBJ := $(MISC_MNTENT_OUT)/mntent.o + +libc-y += $(MISC_MNTENT_OBJ) + +objclean-y += CLEAN_libc/misc/mntent + +CLEAN_libc/misc/mntent: + $(do_rm) $(addprefix $(MISC_MNTENT_OUT)/*., o os) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/mntent/mntent.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/mntent/mntent.c new file mode 100644 index 00000000..608f84c1 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/mntent/mntent.c @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include +#include + +__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_MUTEX_INITIALIZER); + + + +/* Reentrant version of getmntent. */ +struct mntent *getmntent_r (FILE *filep, + struct mntent *mnt, char *buff, int bufsize) +{ + static const char sep[] = " \t\n"; + + char *cp, *ptrptr; + + if (!filep || !mnt || !buff) + return NULL; + + /* Loop on the file, skipping comment lines. - FvK 03/07/93 */ + while ((cp = fgets(buff, bufsize, filep)) != NULL) { + if (buff[0] == '#' || buff[0] == '\n') + continue; + break; + } + + /* At the EOF, the buffer should be unchanged. We should + * check the return value from fgets (). + */ + if (cp == NULL) + return NULL; + + ptrptr = 0; + mnt->mnt_fsname = strtok_r(buff, sep, &ptrptr); + if (mnt->mnt_fsname == NULL) + return NULL; + + mnt->mnt_dir = strtok_r(NULL, sep, &ptrptr); + if (mnt->mnt_dir == NULL) + return NULL; + + mnt->mnt_type = strtok_r(NULL, sep, &ptrptr); + if (mnt->mnt_type == NULL) + return NULL; + + mnt->mnt_opts = strtok_r(NULL, sep, &ptrptr); + if (mnt->mnt_opts == NULL) + mnt->mnt_opts = ""; + + cp = strtok_r(NULL, sep, &ptrptr); + mnt->mnt_freq = (cp != NULL) ? atoi(cp) : 0; + + cp = strtok_r(NULL, sep, &ptrptr); + mnt->mnt_passno = (cp != NULL) ? atoi(cp) : 0; + + return mnt; +} +libc_hidden_def(getmntent_r) + +struct mntent *getmntent(FILE * filep) +{ + struct mntent *tmp; + static char *buff = NULL; + static struct mntent mnt; + __UCLIBC_MUTEX_LOCK(mylock); + + if (!buff) { + buff = malloc(BUFSIZ); + if (!buff) + abort(); + } + + tmp = getmntent_r(filep, &mnt, buff, BUFSIZ); + __UCLIBC_MUTEX_UNLOCK(mylock); + return(tmp); +} + +int addmntent(FILE * filep, const struct mntent *mnt) +{ + if (fseek(filep, 0, SEEK_END) < 0) + return 1; + + return (fprintf (filep, "%s %s %s %s %d %d\n", mnt->mnt_fsname, mnt->mnt_dir, + mnt->mnt_type, mnt->mnt_opts, mnt->mnt_freq, mnt->mnt_passno) < 0 ? 1 : 0); +} + +char *hasmntopt(const struct mntent *mnt, const char *opt) +{ + return strstr(mnt->mnt_opts, opt); +} + +FILE *setmntent(const char *name, const char *mode) +{ + return fopen(name, mode); +} +libc_hidden_def(setmntent) + +int endmntent(FILE * filep) +{ + if (filep != NULL) + fclose(filep); + return 1; +} +libc_hidden_def(endmntent) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/pthread/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/pthread/Makefile new file mode 100644 index 00000000..4a8f4a07 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/pthread/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../ +top_builddir=../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/pthread/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/pthread/Makefile.in new file mode 100644 index 00000000..2f436ac1 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/pthread/Makefile.in @@ -0,0 +1,18 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +subdirs += libc/misc/pthread + +MISC_PTHREAD_DIR := $(top_srcdir)libc/misc/pthread +MISC_PTHREAD_OUT := $(top_builddir)libc/misc/pthread + +libc-shared-$(UCLIBC_HAS_TLS) += $(MISC_PTHREAD_OUT)/tsd.os + +objclean-y += CLEAN_libc/misc/pthread + +CLEAN_libc/misc/pthread: + $(do_rm) $(addprefix $(MISC_PTHREAD_OUT)/*., o os oS) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/pthread/tsd.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/pthread/tsd.c new file mode 100644 index 00000000..835ee22c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/pthread/tsd.c @@ -0,0 +1,10 @@ +/* libpthread sets _dl_error_catch_tsd to point to this function. + We define it here instead of in libpthread so t here instead of in libpthread so that it doesn't + need to have a TLS segment of its own just for this one pointer. */ + +void ** __attribute__ ((const)) +__libc_dl_error_tsd (void) +{ + static __thread void *data __attribute__ ((tls_model ("initial-exec"))); + return &data; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/regex/.indent.pro b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/regex/.indent.pro new file mode 100644 index 00000000..492ecf1c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/regex/.indent.pro @@ -0,0 +1,33 @@ +--blank-lines-after-declarations +--blank-lines-after-procedures +--break-before-boolean-operator +--no-blank-lines-after-commas +--braces-on-if-line +--braces-on-struct-decl-line +--comment-indentation25 +--declaration-comment-column25 +--no-comment-delimiters-on-blank-lines +--cuddle-else +--continuation-indentation4 +--case-indentation0 +--else-endif-column33 +--space-after-cast +--line-comments-indentation0 +--declaration-indentation1 +--dont-format-first-column-comments +--dont-format-comments +--honour-newlines +--indent-level4 +/* changed from 0 to 4 */ +--parameter-indentation4 +--line-length78 /* changed from 75 */ +--continue-at-parentheses +--no-space-after-function-call-names +--dont-break-procedure-type +--dont-star-comments +--leave-optional-blank-lines +--dont-space-special-semicolon +--tab-size4 +/* additions by Mark */ +--case-brace-indentation0 +--leave-preprocessor-space diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/regex/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/regex/Makefile new file mode 100644 index 00000000..4a8f4a07 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/regex/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../ +top_builddir=../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/regex/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/regex/Makefile.in new file mode 100644 index 00000000..94710238 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/regex/Makefile.in @@ -0,0 +1,27 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +subdirs += libc/misc/regex + +ifeq ($(UCLIBC_HAS_REGEX_OLD),y) +CSRC := regex_old.c +else +CSRC := regex.c +endif + +MISC_REGEX_DIR := $(top_srcdir)libc/misc/regex +MISC_REGEX_OUT := $(top_builddir)libc/misc/regex + +MISC_REGEX_SRC := $(patsubst %.c,$(MISC_REGEX_DIR)/%.c,$(CSRC)) +MISC_REGEX_OBJ := $(patsubst %.c,$(MISC_REGEX_OUT)/%.o,$(CSRC)) + +libc-$(UCLIBC_HAS_REGEX) += $(MISC_REGEX_OBJ) + +objclean-y += CLEAN_libc/misc/regex + +CLEAN_libc/misc/regex: + $(do_rm) $(addprefix $(MISC_REGEX_OUT)/*., o os) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/regex/regcomp.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/regex/regcomp.c new file mode 100644 index 00000000..8f2e18ce --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/regex/regcomp.c @@ -0,0 +1,3783 @@ +/* Extended regular expression matching and search library. + Copyright (C) 2002,2003,2004,2005,2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Isamu Hasegawa . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +static reg_errcode_t re_compile_internal (regex_t *preg, const char * pattern, + size_t length, reg_syntax_t syntax); +static void re_compile_fastmap_iter (regex_t *bufp, + const re_dfastate_t *init_state, + char *fastmap); +static reg_errcode_t init_dfa (re_dfa_t *dfa, size_t pat_len); +#ifdef RE_ENABLE_I18N +static void free_charset (re_charset_t *cset); +#endif +static void free_workarea_compile (regex_t *preg); +static reg_errcode_t create_initial_state (re_dfa_t *dfa); +#ifdef RE_ENABLE_I18N +static void optimize_utf8 (re_dfa_t *dfa); +#endif +static reg_errcode_t analyze (regex_t *preg); +static reg_errcode_t preorder (bin_tree_t *root, + reg_errcode_t (fn (void *, bin_tree_t *)), + void *extra); +static reg_errcode_t postorder (bin_tree_t *root, + reg_errcode_t (fn (void *, bin_tree_t *)), + void *extra); +static reg_errcode_t optimize_subexps (void *extra, bin_tree_t *node); +static reg_errcode_t lower_subexps (void *extra, bin_tree_t *node); +static bin_tree_t *lower_subexp (reg_errcode_t *err, regex_t *preg, + bin_tree_t *node); +static reg_errcode_t calc_first (void *extra, bin_tree_t *node); +static reg_errcode_t calc_next (void *extra, bin_tree_t *node); +static reg_errcode_t link_nfa_nodes (void *extra, bin_tree_t *node); +static int duplicate_node (re_dfa_t *dfa, int org_idx, unsigned int constraint); +static int search_duplicated_node (const re_dfa_t *dfa, int org_node, + unsigned int constraint); +static reg_errcode_t calc_eclosure (re_dfa_t *dfa); +static reg_errcode_t calc_eclosure_iter (re_node_set *new_set, re_dfa_t *dfa, + int node, int root); +static reg_errcode_t calc_inveclosure (re_dfa_t *dfa); +static int fetch_number (re_string_t *input, re_token_t *token, + reg_syntax_t syntax); +static int peek_token (re_token_t *token, re_string_t *input, + reg_syntax_t syntax) internal_function; +static bin_tree_t *parse (re_string_t *regexp, regex_t *preg, + reg_syntax_t syntax, reg_errcode_t *err); +static bin_tree_t *parse_reg_exp (re_string_t *regexp, regex_t *preg, + re_token_t *token, reg_syntax_t syntax, + int nest, reg_errcode_t *err); +static bin_tree_t *parse_branch (re_string_t *regexp, regex_t *preg, + re_token_t *token, reg_syntax_t syntax, + int nest, reg_errcode_t *err); +static bin_tree_t *parse_expression (re_string_t *regexp, regex_t *preg, + re_token_t *token, reg_syntax_t syntax, + int nest, reg_errcode_t *err); +static bin_tree_t *parse_sub_exp (re_string_t *regexp, regex_t *preg, + re_token_t *token, reg_syntax_t syntax, + int nest, reg_errcode_t *err); +static bin_tree_t *parse_dup_op (bin_tree_t *dup_elem, re_string_t *regexp, + re_dfa_t *dfa, re_token_t *token, + reg_syntax_t syntax, reg_errcode_t *err); +static bin_tree_t *parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, + re_token_t *token, reg_syntax_t syntax, + reg_errcode_t *err); +static reg_errcode_t parse_bracket_element (bracket_elem_t *elem, + re_string_t *regexp, + re_token_t *token, int token_len, + re_dfa_t *dfa, + reg_syntax_t syntax, + int accept_hyphen); +static reg_errcode_t parse_bracket_symbol (bracket_elem_t *elem, + re_string_t *regexp, + re_token_t *token); +#ifdef RE_ENABLE_I18N +static reg_errcode_t build_equiv_class (bitset_t sbcset, + re_charset_t *mbcset, + int *equiv_class_alloc, + const unsigned char *name); +static reg_errcode_t build_charclass (RE_TRANSLATE_TYPE trans, + bitset_t sbcset, + re_charset_t *mbcset, + int *char_class_alloc, + const unsigned char *class_name, + reg_syntax_t syntax); +#else /* not RE_ENABLE_I18N */ +static reg_errcode_t build_equiv_class (bitset_t sbcset, + const unsigned char *name); +static reg_errcode_t build_charclass (RE_TRANSLATE_TYPE trans, + bitset_t sbcset, + const unsigned char *class_name, + reg_syntax_t syntax); +#endif /* not RE_ENABLE_I18N */ +static bin_tree_t *build_charclass_op (re_dfa_t *dfa, + RE_TRANSLATE_TYPE trans, + const unsigned char *class_name, + const unsigned char *extra, + int non_match, reg_errcode_t *err); +static bin_tree_t *create_tree (re_dfa_t *dfa, + bin_tree_t *left, bin_tree_t *right, + re_token_type_t type); +static bin_tree_t *create_token_tree (re_dfa_t *dfa, + bin_tree_t *left, bin_tree_t *right, + const re_token_t *token); +static bin_tree_t *duplicate_tree (const bin_tree_t *src, re_dfa_t *dfa); +static void free_token (re_token_t *node); +static reg_errcode_t free_tree (void *extra, bin_tree_t *node); +static reg_errcode_t mark_opt_subexp (void *extra, bin_tree_t *node); + +/* This table gives an error message for each of the error codes listed + in regex.h. Obviously the order here has to be same as there. + POSIX doesn't require that we do anything for REG_NOERROR, + but why not be nice? */ + +static const char __re_error_msgid[] = + { +#define REG_NOERROR_IDX 0 + gettext_noop ("Success") /* REG_NOERROR */ + "\0" +#define REG_NOMATCH_IDX (REG_NOERROR_IDX + sizeof "Success") + gettext_noop ("No match") /* REG_NOMATCH */ + "\0" +#define REG_BADPAT_IDX (REG_NOMATCH_IDX + sizeof "No match") + gettext_noop ("Invalid regular expression") /* REG_BADPAT */ + "\0" +#define REG_ECOLLATE_IDX (REG_BADPAT_IDX + sizeof "Invalid regular expression") + gettext_noop ("Invalid collation character") /* REG_ECOLLATE */ + "\0" +#define REG_ECTYPE_IDX (REG_ECOLLATE_IDX + sizeof "Invalid collation character") + gettext_noop ("Invalid character class name") /* REG_ECTYPE */ + "\0" +#define REG_EESCAPE_IDX (REG_ECTYPE_IDX + sizeof "Invalid character class name") + gettext_noop ("Trailing backslash") /* REG_EESCAPE */ + "\0" +#define REG_ESUBREG_IDX (REG_EESCAPE_IDX + sizeof "Trailing backslash") + gettext_noop ("Invalid back reference") /* REG_ESUBREG */ + "\0" +#define REG_EBRACK_IDX (REG_ESUBREG_IDX + sizeof "Invalid back reference") + gettext_noop ("Unmatched [ or [^") /* REG_EBRACK */ + "\0" +#define REG_EPAREN_IDX (REG_EBRACK_IDX + sizeof "Unmatched [ or [^") + gettext_noop ("Unmatched ( or \\(") /* REG_EPAREN */ + "\0" +#define REG_EBRACE_IDX (REG_EPAREN_IDX + sizeof "Unmatched ( or \\(") + gettext_noop ("Unmatched \\{") /* REG_EBRACE */ + "\0" +#define REG_BADBR_IDX (REG_EBRACE_IDX + sizeof "Unmatched \\{") + gettext_noop ("Invalid content of \\{\\}") /* REG_BADBR */ + "\0" +#define REG_ERANGE_IDX (REG_BADBR_IDX + sizeof "Invalid content of \\{\\}") + gettext_noop ("Invalid range end") /* REG_ERANGE */ + "\0" +#define REG_ESPACE_IDX (REG_ERANGE_IDX + sizeof "Invalid range end") + gettext_noop ("Memory exhausted") /* REG_ESPACE */ + "\0" +#define REG_BADRPT_IDX (REG_ESPACE_IDX + sizeof "Memory exhausted") + gettext_noop ("Invalid preceding regular expression") /* REG_BADRPT */ + "\0" +#define REG_EEND_IDX (REG_BADRPT_IDX + sizeof "Invalid preceding regular expression") + gettext_noop ("Premature end of regular expression") /* REG_EEND */ + "\0" +#define REG_ESIZE_IDX (REG_EEND_IDX + sizeof "Premature end of regular expression") + gettext_noop ("Regular expression too big") /* REG_ESIZE */ + "\0" +#define REG_ERPAREN_IDX (REG_ESIZE_IDX + sizeof "Regular expression too big") + gettext_noop ("Unmatched ) or \\)") /* REG_ERPAREN */ + }; + +static const uint16_t __re_error_msgid_idx[] = + { + REG_NOERROR_IDX, + REG_NOMATCH_IDX, + REG_BADPAT_IDX, + REG_ECOLLATE_IDX, + REG_ECTYPE_IDX, + REG_EESCAPE_IDX, + REG_ESUBREG_IDX, + REG_EBRACK_IDX, + REG_EPAREN_IDX, + REG_EBRACE_IDX, + REG_BADBR_IDX, + REG_ERANGE_IDX, + REG_ESPACE_IDX, + REG_BADRPT_IDX, + REG_EEND_IDX, + REG_ESIZE_IDX, + REG_ERPAREN_IDX + }; + +/* Entry points for GNU code. */ + +/* re_compile_pattern is the GNU regular expression compiler: it + compiles PATTERN (of length LENGTH) and puts the result in BUFP. + Returns 0 if the pattern was valid, otherwise an error string. + + Assumes the `allocated' (and perhaps `buffer') and `translate' fields + are set in BUFP on entry. */ + +const char * +re_compile_pattern (const char *pattern, + size_t length, + struct re_pattern_buffer *bufp) +{ + reg_errcode_t ret; + + /* And GNU code determines whether or not to get register information + by passing null for the REGS argument to re_match, etc., not by + setting no_sub, unless RE_NO_SUB is set. */ + bufp->no_sub = !!(re_syntax_options & RE_NO_SUB); + + /* Match anchors at newline. */ + bufp->newline_anchor = 1; + + ret = re_compile_internal (bufp, pattern, length, re_syntax_options); + + if (!ret) + return NULL; + return gettext (__re_error_msgid + __re_error_msgid_idx[(int) ret]); +} + +/* Set by `re_set_syntax' to the current regexp syntax to recognize. Can + also be assigned to arbitrarily: each pattern buffer stores its own + syntax, so it can be changed between regex compilations. */ +/* This has no initializer because initialized variables in Emacs + become read-only after dumping. */ +reg_syntax_t re_syntax_options; + + +/* Specify the precise syntax of regexps for compilation. This provides + for compatibility for various utilities which historically have + different, incompatible syntaxes. + + The argument SYNTAX is a bit mask comprised of the various bits + defined in regex.h. We return the old syntax. */ + +reg_syntax_t +re_set_syntax (reg_syntax_t syntax) +{ + reg_syntax_t ret = re_syntax_options; + + re_syntax_options = syntax; + return ret; +} + +int +re_compile_fastmap (struct re_pattern_buffer *bufp) +{ + re_dfa_t *dfa = (re_dfa_t *) bufp->buffer; + char *fastmap = bufp->fastmap; + + memset (fastmap, '\0', sizeof (char) * SBC_MAX); + re_compile_fastmap_iter (bufp, dfa->init_state, fastmap); + if (dfa->init_state != dfa->init_state_word) + re_compile_fastmap_iter (bufp, dfa->init_state_word, fastmap); + if (dfa->init_state != dfa->init_state_nl) + re_compile_fastmap_iter (bufp, dfa->init_state_nl, fastmap); + if (dfa->init_state != dfa->init_state_begbuf) + re_compile_fastmap_iter (bufp, dfa->init_state_begbuf, fastmap); + bufp->fastmap_accurate = 1; + return 0; +} +libc_hidden_def(re_compile_fastmap) + +static __inline__ void +__attribute ((always_inline)) +re_set_fastmap (char *fastmap, int icase, int ch) +{ + fastmap[ch] = 1; + if (icase) + fastmap[tolower (ch)] = 1; +} + +/* Helper function for re_compile_fastmap. + Compile fastmap for the initial_state INIT_STATE. */ + +static void +re_compile_fastmap_iter (regex_t *bufp, const re_dfastate_t *init_state, + char *fastmap) +{ + re_dfa_t *dfa = (re_dfa_t *) bufp->buffer; + int node_cnt; + int icase = (dfa->mb_cur_max == 1 && (bufp->syntax & RE_ICASE)); + for (node_cnt = 0; node_cnt < init_state->nodes.nelem; ++node_cnt) + { + int node = init_state->nodes.elems[node_cnt]; + re_token_type_t type = dfa->nodes[node].type; + + if (type == CHARACTER) + { + re_set_fastmap (fastmap, icase, dfa->nodes[node].opr.c); +#ifdef RE_ENABLE_I18N + if ((bufp->syntax & RE_ICASE) && dfa->mb_cur_max > 1) + { + unsigned char *buf = alloca (dfa->mb_cur_max), *p; + wchar_t wc; + mbstate_t state; + + p = buf; + *p++ = dfa->nodes[node].opr.c; + while (++node < dfa->nodes_len + && dfa->nodes[node].type == CHARACTER + && dfa->nodes[node].mb_partial) + *p++ = dfa->nodes[node].opr.c; + memset (&state, '\0', sizeof (state)); + if (mbrtowc (&wc, (const char *) buf, p - buf, + &state) == p - buf + && (__wcrtomb ((char *) buf, towlower (wc), &state) + != (size_t) -1)) + re_set_fastmap (fastmap, 0, buf[0]); + } +#endif + } + else if (type == SIMPLE_BRACKET) + { + int i, ch; + for (i = 0, ch = 0; i < BITSET_WORDS; ++i) + { + int j; + bitset_word_t w = dfa->nodes[node].opr.sbcset[i]; + for (j = 0; j < BITSET_WORD_BITS; ++j, ++ch) + if (w & ((bitset_word_t) 1 << j)) + re_set_fastmap (fastmap, icase, ch); + } + } +#ifdef RE_ENABLE_I18N + else if (type == COMPLEX_BRACKET) + { + int i; + re_charset_t *cset = dfa->nodes[node].opr.mbcset; + if (cset->non_match || cset->ncoll_syms || cset->nequiv_classes + || cset->nranges || cset->nchar_classes) + { +# if 0 + if (_NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES) != 0) + { + /* In this case we want to catch the bytes which are + the first byte of any collation elements. + e.g. In da_DK, we want to catch 'a' since "aa" + is a valid collation element, and don't catch + 'b' since 'b' is the only collation element + which starts from 'b'. */ + const int32_t *table = (const int32_t *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB); + for (i = 0; i < SBC_MAX; ++i) + if (table[i] < 0) + re_set_fastmap (fastmap, icase, i); + } +# else + if (dfa->mb_cur_max > 1) + for (i = 0; i < SBC_MAX; ++i) + if (__btowc (i) == WEOF) + re_set_fastmap (fastmap, icase, i); +# endif + } + for (i = 0; i < cset->nmbchars; ++i) + { + char buf[256]; + mbstate_t state; + memset (&state, '\0', sizeof (state)); + if (__wcrtomb (buf, cset->mbchars[i], &state) != (size_t) -1) + re_set_fastmap (fastmap, icase, *(unsigned char *) buf); + if ((bufp->syntax & RE_ICASE) && dfa->mb_cur_max > 1) + { + if (__wcrtomb (buf, towlower (cset->mbchars[i]), &state) + != (size_t) -1) + re_set_fastmap (fastmap, 0, *(unsigned char *) buf); + } + } + } +#endif /* RE_ENABLE_I18N */ + else if (type == OP_PERIOD +#ifdef RE_ENABLE_I18N + || type == OP_UTF8_PERIOD +#endif + || type == END_OF_RE) + { + memset (fastmap, '\1', sizeof (char) * SBC_MAX); + if (type == END_OF_RE) + bufp->can_be_null = 1; + return; + } + } +} + +/* Entry point for POSIX code. */ +/* regcomp takes a regular expression as a string and compiles it. + + PREG is a regex_t *. We do not expect any fields to be initialized, + since POSIX says we shouldn't. Thus, we set + + `buffer' to the compiled pattern; + `used' to the length of the compiled pattern; + `syntax' to RE_SYNTAX_POSIX_EXTENDED if the + REG_EXTENDED bit in CFLAGS is set; otherwise, to + RE_SYNTAX_POSIX_BASIC; + `newline_anchor' to REG_NEWLINE being set in CFLAGS; + `fastmap' to an allocated space for the fastmap; + `fastmap_accurate' to zero; + `re_nsub' to the number of subexpressions in PATTERN. + + PATTERN is the address of the pattern string. + + CFLAGS is a series of bits which affect compilation. + + If REG_EXTENDED is set, we use POSIX extended syntax; otherwise, we + use POSIX basic syntax. + + If REG_NEWLINE is set, then . and [^...] don't match newline. + Also, regexec will try a match beginning after every newline. + + If REG_ICASE is set, then we considers upper- and lowercase + versions of letters to be equivalent when matching. + + If REG_NOSUB is set, then when PREG is passed to regexec, that + routine will report only success or failure, and nothing about the + registers. + + It returns 0 if it succeeds, nonzero if it doesn't. (See regex.h for + the return codes and their meanings.) */ + +int +regcomp (regex_t *__restrict preg, + const char *__restrict pattern, + int cflags) +{ + reg_errcode_t ret; + reg_syntax_t syntax = ((cflags & REG_EXTENDED) ? RE_SYNTAX_POSIX_EXTENDED + : RE_SYNTAX_POSIX_BASIC); + + preg->buffer = NULL; + preg->allocated = 0; + preg->used = 0; + + /* Try to allocate space for the fastmap. */ + preg->fastmap = re_malloc (char, SBC_MAX); + if (BE (preg->fastmap == NULL, 0)) + return REG_ESPACE; + + syntax |= (cflags & REG_ICASE) ? RE_ICASE : 0; + + /* If REG_NEWLINE is set, newlines are treated differently. */ + if (cflags & REG_NEWLINE) + { /* REG_NEWLINE implies neither . nor [^...] match newline. */ + syntax &= ~RE_DOT_NEWLINE; + syntax |= RE_HAT_LISTS_NOT_NEWLINE; + /* It also changes the matching behavior. */ + preg->newline_anchor = 1; + } + else + preg->newline_anchor = 0; + preg->no_sub = !!(cflags & REG_NOSUB); + preg->translate = NULL; + + ret = re_compile_internal (preg, pattern, strlen (pattern), syntax); + + /* POSIX doesn't distinguish between an unmatched open-group and an + unmatched close-group: both are REG_EPAREN. */ + if (ret == REG_ERPAREN) + ret = REG_EPAREN; + + /* We have already checked preg->fastmap != NULL. */ + if (BE (ret == REG_NOERROR, 1)) + /* Compute the fastmap now, since regexec cannot modify the pattern + buffer. This function never fails in this implementation. */ + (void) re_compile_fastmap (preg); + else + { + /* Some error occurred while compiling the expression. */ + re_free (preg->fastmap); + preg->fastmap = NULL; + } + + return (int) ret; +} + +/* Returns a message corresponding to an error code, ERRCODE, returned + from either regcomp or regexec. We don't use PREG here. */ + +size_t +regerror (int errcode, + const regex_t *__restrict preg, + char *__restrict errbuf, + size_t errbuf_size) +{ + const char *msg; + size_t msg_size; + + if (BE (errcode < 0 + || errcode >= (int) (sizeof (__re_error_msgid_idx) + / sizeof (__re_error_msgid_idx[0])), 0)) + /* Only error codes returned by the rest of the code should be passed + to this routine. If we are given anything else, or if other regex + code generates an invalid error code, then the program has a bug. + Dump core so we can fix it. */ + abort (); + + msg = gettext (__re_error_msgid + __re_error_msgid_idx[errcode]); + + msg_size = strlen (msg) + 1; /* Includes the null. */ + + if (BE (errbuf_size != 0, 1)) + { + if (BE (msg_size > errbuf_size, 0)) + { + memcpy (errbuf, msg, errbuf_size - 1); + errbuf[errbuf_size - 1] = 0; + } + else + memcpy (errbuf, msg, msg_size); + } + + return msg_size; +} + + +#ifdef RE_ENABLE_I18N +/* This static array is used for the map to single-byte characters when + UTF-8 is used. Otherwise we would allocate memory just to initialize + it the same all the time. UTF-8 is the preferred encoding so this is + a worthwhile optimization. */ +static const bitset_t utf8_sb_map = +{ + /* Set the first 128 bits. */ + [0 ... 0x80 / BITSET_WORD_BITS - 1] = BITSET_WORD_MAX +}; +#endif + + +static void +free_dfa_content (re_dfa_t *dfa) +{ + int i, j; + + if (dfa->nodes) + for (i = 0; i < dfa->nodes_len; ++i) + free_token (dfa->nodes + i); + re_free (dfa->nexts); + for (i = 0; i < dfa->nodes_len; ++i) + { + if (dfa->eclosures != NULL) + re_node_set_free (dfa->eclosures + i); + if (dfa->inveclosures != NULL) + re_node_set_free (dfa->inveclosures + i); + if (dfa->edests != NULL) + re_node_set_free (dfa->edests + i); + } + re_free (dfa->edests); + re_free (dfa->eclosures); + re_free (dfa->inveclosures); + re_free (dfa->nodes); + + if (dfa->state_table) + for (i = 0; i <= dfa->state_hash_mask; ++i) + { + struct re_state_table_entry *entry = dfa->state_table + i; + for (j = 0; j < entry->num; ++j) + { + re_dfastate_t *state = entry->array[j]; + free_state (state); + } + re_free (entry->array); + } + re_free (dfa->state_table); +#ifdef RE_ENABLE_I18N + if (dfa->sb_char != utf8_sb_map) + re_free (dfa->sb_char); +#endif + re_free (dfa->subexp_map); +#ifdef DEBUG + re_free (dfa->re_str); +#endif + + re_free (dfa); +} + + +/* Free dynamically allocated space used by PREG. */ + +void +regfree (regex_t *preg) +{ + re_dfa_t *dfa = (re_dfa_t *) preg->buffer; + if (BE (dfa != NULL, 1)) + free_dfa_content (dfa); + preg->buffer = NULL; + preg->allocated = 0; + + re_free (preg->fastmap); + preg->fastmap = NULL; + + re_free (preg->translate); + preg->translate = NULL; +} +libc_hidden_def(regfree) + +/* Entry points compatible with 4.2 BSD regex library. We don't define + them unless specifically requested. */ + +#if defined _REGEX_RE_COMP || defined __UCLIBC__ + +/* BSD has one and only one pattern buffer. */ +static struct re_pattern_buffer *re_comp_buf; + +char * +/* Make BCD definitions weak in libc, so POSIX programs can redefine + these names if they don't use our functions, and still use + regcomp/regexec above without link errors. */ +weak_function +re_comp (const char *s) +{ + reg_errcode_t ret; + + /* "If re_comp() is passed NULL or a null string, it returns + * without changing the currently compiled regular expression." */ + if (!s || !s[0]) + { + if (!re_comp_buf) + return gettext ("No previous regular expression"); + return NULL; + } + + if (!re_comp_buf) + { + re_comp_buf = calloc (1, sizeof(*re_comp_buf)); + if (!re_comp_buf) + { + ret = REG_ESPACE; + goto err; + } + } + + if (re_comp_buf->buffer) + { + regfree (re_comp_buf); + memset (re_comp_buf, '\0', sizeof(*re_comp_buf)); + } + + if (re_comp_buf->fastmap == NULL) + { + re_comp_buf->fastmap = malloc (SBC_MAX); + if (re_comp_buf->fastmap == NULL) + { + ret = REG_ESPACE; + goto err; + } + } + + /* Since `re_exec' always passes NULL for the `regs' argument, we + don't need to initialize the pattern buffer fields which affect it. */ + + /* Match anchors at newlines. */ + re_comp_buf->newline_anchor = 1; + + ret = re_compile_internal (re_comp_buf, s, strlen (s), re_syntax_options); + + if (!ret) + return NULL; + free (re_comp_buf); + re_comp_buf = NULL; + + err: + /* Yes, we're discarding `const' here if !HAVE_LIBINTL. */ + return (char *) gettext (__re_error_msgid + __re_error_msgid_idx[(int) ret]); +} + +#if 0 +libc_freeres_fn (free_mem) +{ + regfree (re_comp_buf); + free (re_comp_buf); + re_comp_buf = NULL; +} +#endif + +#endif /* _REGEX_RE_COMP */ + +/* Internal entry point. + Compile the regular expression PATTERN, whose length is LENGTH. + SYNTAX indicate regular expression's syntax. */ + +static reg_errcode_t +re_compile_internal (regex_t *preg, const char * pattern, size_t length, + reg_syntax_t syntax) +{ + reg_errcode_t err = REG_NOERROR; + re_dfa_t *dfa; + re_string_t regexp; + + /* Initialize the pattern buffer. */ + preg->fastmap_accurate = 0; + preg->syntax = syntax; + preg->not_bol = preg->not_eol = 0; + preg->used = 0; + preg->re_nsub = 0; + preg->can_be_null = 0; + preg->regs_allocated = REGS_UNALLOCATED; + + /* Initialize the dfa. */ + dfa = (re_dfa_t *) preg->buffer; + if (BE (preg->allocated < sizeof (re_dfa_t), 0)) + { + /* If zero allocated, but buffer is non-null, try to realloc + enough space. This loses if buffer's address is bogus, but + that is the user's responsibility. If ->buffer is NULL this + is a simple allocation. */ + dfa = re_realloc (preg->buffer, re_dfa_t, 1); + if (dfa == NULL) + return REG_ESPACE; + preg->allocated = sizeof (re_dfa_t); + preg->buffer = (unsigned char *) dfa; + } + preg->used = sizeof (re_dfa_t); + + err = init_dfa (dfa, length); + if (BE (err != REG_NOERROR, 0)) + { + free_dfa_content (dfa); + preg->buffer = NULL; + preg->allocated = 0; + return err; + } +#ifdef DEBUG + /* Note: length+1 will not overflow since it is checked in init_dfa. */ + dfa->re_str = re_malloc (char, length + 1); + strncpy (dfa->re_str, pattern, length + 1); +#endif + + __libc_lock_init (dfa->lock); + + err = re_string_construct (®exp, pattern, length, preg->translate, + syntax & RE_ICASE, dfa); + if (BE (err != REG_NOERROR, 0)) + { + re_compile_internal_free_return: + free_workarea_compile (preg); + re_string_destruct (®exp); + free_dfa_content (dfa); + preg->buffer = NULL; + preg->allocated = 0; + return err; + } + + /* Parse the regular expression, and build a structure tree. */ + preg->re_nsub = 0; + dfa->str_tree = parse (®exp, preg, syntax, &err); + if (BE (dfa->str_tree == NULL, 0)) + goto re_compile_internal_free_return; + + /* Analyze the tree and create the nfa. */ + err = analyze (preg); + if (BE (err != REG_NOERROR, 0)) + goto re_compile_internal_free_return; + +#ifdef RE_ENABLE_I18N + /* If possible, do searching in single byte encoding to speed things up. */ + if (dfa->is_utf8 && !(syntax & RE_ICASE) && preg->translate == NULL) + optimize_utf8 (dfa); +#endif + + /* Then create the initial state of the dfa. */ + err = create_initial_state (dfa); + + /* Release work areas. */ + free_workarea_compile (preg); + re_string_destruct (®exp); + + if (BE (err != REG_NOERROR, 0)) + { + free_dfa_content (dfa); + preg->buffer = NULL; + preg->allocated = 0; + } + + return err; +} + +/* Initialize DFA. We use the length of the regular expression PAT_LEN + as the initial length of some arrays. */ + +static reg_errcode_t +init_dfa (re_dfa_t *dfa, size_t pat_len) +{ + unsigned int table_size; +#if 1 + char *codeset_name; +#endif + + memset (dfa, '\0', sizeof (re_dfa_t)); + + /* Force allocation of str_tree_storage the first time. */ + dfa->str_tree_storage_idx = BIN_TREE_STORAGE_SIZE; + + /* Avoid overflows. */ + if (pat_len == SIZE_MAX) + return REG_ESPACE; + + dfa->nodes_alloc = pat_len + 1; + dfa->nodes = re_malloc (re_token_t, dfa->nodes_alloc); + + /* table_size = 2 ^ ceil(log pat_len) */ + for (table_size = 1; ; table_size <<= 1) + if (table_size > pat_len) + break; + + dfa->state_table = calloc (sizeof (struct re_state_table_entry), table_size); + dfa->state_hash_mask = table_size - 1; + +#ifdef __UCLIBC_HAS_WCHAR__ + dfa->mb_cur_max = MB_CUR_MAX; +#else + dfa->mb_cur_max = 1; +#endif +#if 0 + if (dfa->mb_cur_max == 6 + && strcmp (_NL_CURRENT (LC_CTYPE, _NL_CTYPE_CODESET_NAME), "UTF-8") == 0) + dfa->is_utf8 = 1; + dfa->map_notascii = (_NL_CURRENT_WORD (LC_CTYPE, _NL_CTYPE_MAP_TO_NONASCII) + != 0); +#else +# ifdef HAVE_LANGINFO_CODESET + codeset_name = nl_langinfo (CODESET); +# else + codeset_name = getenv ("LC_ALL"); + if (codeset_name == NULL || codeset_name[0] == '\0') + codeset_name = getenv ("LC_CTYPE"); + if (codeset_name == NULL || codeset_name[0] == '\0') + codeset_name = getenv ("LANG"); + if (codeset_name == NULL) + codeset_name = ""; + else if (strchr (codeset_name, '.') != NULL) + codeset_name = strchr (codeset_name, '.') + 1; +# endif + + if (strcasecmp (codeset_name, "UTF-8") == 0 + || strcasecmp (codeset_name, "UTF8") == 0) + dfa->is_utf8 = 1; + + /* We check exhaustively in the loop below if this charset is a + superset of ASCII. */ + dfa->map_notascii = 0; +#endif + +#ifdef RE_ENABLE_I18N + if (dfa->mb_cur_max > 1) + { + if (dfa->is_utf8) + dfa->sb_char = (re_bitset_ptr_t) utf8_sb_map; + else + { + int i, j, ch; + + dfa->sb_char = calloc (sizeof (bitset_t), 1); + if (BE (dfa->sb_char == NULL, 0)) + return REG_ESPACE; + + /* Set the bits corresponding to single byte chars. */ + for (i = 0, ch = 0; i < BITSET_WORDS; ++i) + for (j = 0; j < BITSET_WORD_BITS; ++j, ++ch) + { + wint_t wch = __btowc (ch); + if (wch != WEOF) + dfa->sb_char[i] |= (bitset_word_t) 1 << j; +# if 1 + if (isascii (ch) && wch != ch) + dfa->map_notascii = 1; +# endif + } + } + } +#endif + + if (BE (dfa->nodes == NULL || dfa->state_table == NULL, 0)) + return REG_ESPACE; + return REG_NOERROR; +} + +/* Initialize WORD_CHAR table, which indicate which character is + "word". In this case "word" means that it is the word construction + character used by some operators like "\<", "\>", etc. */ + +static void +internal_function +init_word_char (re_dfa_t *dfa) +{ + int i, j, ch; + dfa->word_ops_used = 1; + for (i = 0, ch = 0; i < BITSET_WORDS; ++i) + for (j = 0; j < BITSET_WORD_BITS; ++j, ++ch) + if (isalnum (ch) || ch == '_') + dfa->word_char[i] |= (bitset_word_t) 1 << j; +} + +/* Free the work area which are only used while compiling. */ + +static void +free_workarea_compile (regex_t *preg) +{ + re_dfa_t *dfa = (re_dfa_t *) preg->buffer; + bin_tree_storage_t *storage, *next; + for (storage = dfa->str_tree_storage; storage; storage = next) + { + next = storage->next; + re_free (storage); + } + dfa->str_tree_storage = NULL; + dfa->str_tree_storage_idx = BIN_TREE_STORAGE_SIZE; + dfa->str_tree = NULL; + re_free (dfa->org_indices); + dfa->org_indices = NULL; +} + +/* Create initial states for all contexts. */ + +static reg_errcode_t +create_initial_state (re_dfa_t *dfa) +{ + int first, i; + reg_errcode_t err; + re_node_set init_nodes; + + /* Initial states have the epsilon closure of the node which is + the first node of the regular expression. */ + first = dfa->str_tree->first->node_idx; + dfa->init_node = first; + err = re_node_set_init_copy (&init_nodes, dfa->eclosures + first); + if (BE (err != REG_NOERROR, 0)) + return err; + + /* The back-references which are in initial states can epsilon transit, + since in this case all of the subexpressions can be null. + Then we add epsilon closures of the nodes which are the next nodes of + the back-references. */ + if (dfa->nbackref > 0) + for (i = 0; i < init_nodes.nelem; ++i) + { + int node_idx = init_nodes.elems[i]; + re_token_type_t type = dfa->nodes[node_idx].type; + + int clexp_idx; + if (type != OP_BACK_REF) + continue; + for (clexp_idx = 0; clexp_idx < init_nodes.nelem; ++clexp_idx) + { + re_token_t *clexp_node; + clexp_node = dfa->nodes + init_nodes.elems[clexp_idx]; + if (clexp_node->type == OP_CLOSE_SUBEXP + && clexp_node->opr.idx == dfa->nodes[node_idx].opr.idx) + break; + } + if (clexp_idx == init_nodes.nelem) + continue; + + if (type == OP_BACK_REF) + { + int dest_idx = dfa->edests[node_idx].elems[0]; + if (!re_node_set_contains (&init_nodes, dest_idx)) + { + re_node_set_merge (&init_nodes, dfa->eclosures + dest_idx); + i = 0; + } + } + } + + /* It must be the first time to invoke acquire_state. */ + dfa->init_state = re_acquire_state_context (&err, dfa, &init_nodes, 0); + /* We don't check ERR here, since the initial state must not be NULL. */ + if (BE (dfa->init_state == NULL, 0)) + return err; + if (dfa->init_state->has_constraint) + { + dfa->init_state_word = re_acquire_state_context (&err, dfa, &init_nodes, + CONTEXT_WORD); + dfa->init_state_nl = re_acquire_state_context (&err, dfa, &init_nodes, + CONTEXT_NEWLINE); + dfa->init_state_begbuf = re_acquire_state_context (&err, dfa, + &init_nodes, + CONTEXT_NEWLINE + | CONTEXT_BEGBUF); + if (BE (dfa->init_state_word == NULL || dfa->init_state_nl == NULL + || dfa->init_state_begbuf == NULL, 0)) + return err; + } + else + dfa->init_state_word = dfa->init_state_nl + = dfa->init_state_begbuf = dfa->init_state; + + re_node_set_free (&init_nodes); + return REG_NOERROR; +} + +#ifdef RE_ENABLE_I18N +/* If it is possible to do searching in single byte encoding instead of UTF-8 + to speed things up, set dfa->mb_cur_max to 1, clear is_utf8 and change + DFA nodes where needed. */ + +static void +optimize_utf8 (re_dfa_t *dfa) +{ + int node, i, mb_chars = 0, has_period = 0; + + for (node = 0; node < dfa->nodes_len; ++node) + switch (dfa->nodes[node].type) + { + case CHARACTER: + if (dfa->nodes[node].opr.c >= 0x80) + mb_chars = 1; + break; + case ANCHOR: + switch (dfa->nodes[node].opr.idx) + { + case LINE_FIRST: + case LINE_LAST: + case BUF_FIRST: + case BUF_LAST: + break; + default: + /* Word anchors etc. cannot be handled. */ + return; + } + break; + case OP_PERIOD: + has_period = 1; + break; + case OP_BACK_REF: + case OP_ALT: + case END_OF_RE: + case OP_DUP_ASTERISK: + case OP_OPEN_SUBEXP: + case OP_CLOSE_SUBEXP: + break; + case COMPLEX_BRACKET: + return; + case SIMPLE_BRACKET: + /* Just double check. The non-ASCII range starts at 0x80. */ + assert (0x80 % BITSET_WORD_BITS == 0); + for (i = 0x80 / BITSET_WORD_BITS; i < BITSET_WORDS; ++i) + if (dfa->nodes[node].opr.sbcset[i]) + return; + break; + default: + abort (); + } + + if (mb_chars || has_period) + for (node = 0; node < dfa->nodes_len; ++node) + { + if (dfa->nodes[node].type == CHARACTER + && dfa->nodes[node].opr.c >= 0x80) + dfa->nodes[node].mb_partial = 0; + else if (dfa->nodes[node].type == OP_PERIOD) + dfa->nodes[node].type = OP_UTF8_PERIOD; + } + + /* The search can be in single byte locale. */ + dfa->mb_cur_max = 1; + dfa->is_utf8 = 0; + dfa->has_mb_node = dfa->nbackref > 0 || has_period; +} +#endif + +/* Analyze the structure tree, and calculate "first", "next", "edest", + "eclosure", and "inveclosure". */ + +static reg_errcode_t +analyze (regex_t *preg) +{ + re_dfa_t *dfa = (re_dfa_t *) preg->buffer; + reg_errcode_t ret; + + /* Allocate arrays. */ + dfa->nexts = re_malloc (int, dfa->nodes_alloc); + dfa->org_indices = re_malloc (int, dfa->nodes_alloc); + dfa->edests = re_malloc (re_node_set, dfa->nodes_alloc); + dfa->eclosures = re_malloc (re_node_set, dfa->nodes_alloc); + if (BE (dfa->nexts == NULL || dfa->org_indices == NULL || dfa->edests == NULL + || dfa->eclosures == NULL, 0)) + return REG_ESPACE; + + dfa->subexp_map = re_malloc (int, preg->re_nsub); + if (dfa->subexp_map != NULL) + { + int i; + for (i = 0; i < preg->re_nsub; i++) + dfa->subexp_map[i] = i; + preorder (dfa->str_tree, optimize_subexps, dfa); + for (i = 0; i < preg->re_nsub; i++) + if (dfa->subexp_map[i] != i) + break; + if (i == preg->re_nsub) + { + free (dfa->subexp_map); + dfa->subexp_map = NULL; + } + } + + ret = postorder (dfa->str_tree, lower_subexps, preg); + if (BE (ret != REG_NOERROR, 0)) + return ret; + ret = postorder (dfa->str_tree, calc_first, dfa); + if (BE (ret != REG_NOERROR, 0)) + return ret; + preorder (dfa->str_tree, calc_next, dfa); + ret = preorder (dfa->str_tree, link_nfa_nodes, dfa); + if (BE (ret != REG_NOERROR, 0)) + return ret; + ret = calc_eclosure (dfa); + if (BE (ret != REG_NOERROR, 0)) + return ret; + + /* We only need this during the prune_impossible_nodes pass in regexec.c; + skip it if p_i_n will not run, as calc_inveclosure can be quadratic. */ + if ((!preg->no_sub && preg->re_nsub > 0 && dfa->has_plural_match) + || dfa->nbackref) + { + dfa->inveclosures = re_malloc (re_node_set, dfa->nodes_len); + if (BE (dfa->inveclosures == NULL, 0)) + return REG_ESPACE; + ret = calc_inveclosure (dfa); + } + + return ret; +} + +/* Our parse trees are very unbalanced, so we cannot use a stack to + implement parse tree visits. Instead, we use parent pointers and + some hairy code in these two functions. */ +static reg_errcode_t +postorder (bin_tree_t *root, reg_errcode_t (fn (void *, bin_tree_t *)), + void *extra) +{ + bin_tree_t *node, *prev; + + for (node = root; ; ) + { + /* Descend down the tree, preferably to the left (or to the right + if that's the only child). */ + while (node->left || node->right) + if (node->left) + node = node->left; + else + node = node->right; + + do + { + reg_errcode_t err = fn (extra, node); + if (BE (err != REG_NOERROR, 0)) + return err; + if (node->parent == NULL) + return REG_NOERROR; + prev = node; + node = node->parent; + } + /* Go up while we have a node that is reached from the right. */ + while (node->right == prev || node->right == NULL); + node = node->right; + } +} + +static reg_errcode_t +preorder (bin_tree_t *root, reg_errcode_t (fn (void *, bin_tree_t *)), + void *extra) +{ + bin_tree_t *node; + + for (node = root; ; ) + { + reg_errcode_t err = fn (extra, node); + if (BE (err != REG_NOERROR, 0)) + return err; + + /* Go to the left node, or up and to the right. */ + if (node->left) + node = node->left; + else + { + bin_tree_t *prev = NULL; + while (node->right == prev || node->right == NULL) + { + prev = node; + node = node->parent; + if (!node) + return REG_NOERROR; + } + node = node->right; + } + } +} + +/* Optimization pass: if a SUBEXP is entirely contained, strip it and tell + re_search_internal to map the inner one's opr.idx to this one's. Adjust + backreferences as well. Requires a preorder visit. */ +static reg_errcode_t +optimize_subexps (void *extra, bin_tree_t *node) +{ + re_dfa_t *dfa = (re_dfa_t *) extra; + + if (node->token.type == OP_BACK_REF && dfa->subexp_map) + { + int idx = node->token.opr.idx; + node->token.opr.idx = dfa->subexp_map[idx]; + dfa->used_bkref_map |= 1 << node->token.opr.idx; + } + + else if (node->token.type == SUBEXP + && node->left && node->left->token.type == SUBEXP) + { + int other_idx = node->left->token.opr.idx; + + node->left = node->left->left; + if (node->left) + node->left->parent = node; + + dfa->subexp_map[other_idx] = dfa->subexp_map[node->token.opr.idx]; + if (other_idx < BITSET_WORD_BITS) + dfa->used_bkref_map &= ~((bitset_word_t) 1 << other_idx); + } + + return REG_NOERROR; +} + +/* Lowering pass: Turn each SUBEXP node into the appropriate concatenation + of OP_OPEN_SUBEXP, the body of the SUBEXP (if any) and OP_CLOSE_SUBEXP. */ +static reg_errcode_t +lower_subexps (void *extra, bin_tree_t *node) +{ + regex_t *preg = (regex_t *) extra; + reg_errcode_t err = REG_NOERROR; + + if (node->left && node->left->token.type == SUBEXP) + { + node->left = lower_subexp (&err, preg, node->left); + if (node->left) + node->left->parent = node; + } + if (node->right && node->right->token.type == SUBEXP) + { + node->right = lower_subexp (&err, preg, node->right); + if (node->right) + node->right->parent = node; + } + + return err; +} + +static bin_tree_t * +lower_subexp (reg_errcode_t *err, regex_t *preg, bin_tree_t *node) +{ + re_dfa_t *dfa = (re_dfa_t *) preg->buffer; + bin_tree_t *body = node->left; + bin_tree_t *op, *cls, *tree1, *tree; + + if (preg->no_sub + /* We do not optimize empty subexpressions, because otherwise we may + have bad CONCAT nodes with NULL children. This is obviously not + very common, so we do not lose much. An example that triggers + this case is the sed "script" /\(\)/x. */ + && node->left != NULL + && (node->token.opr.idx >= BITSET_WORD_BITS + || !(dfa->used_bkref_map + & ((bitset_word_t) 1 << node->token.opr.idx)))) + return node->left; + + /* Convert the SUBEXP node to the concatenation of an + OP_OPEN_SUBEXP, the contents, and an OP_CLOSE_SUBEXP. */ + op = create_tree (dfa, NULL, NULL, OP_OPEN_SUBEXP); + cls = create_tree (dfa, NULL, NULL, OP_CLOSE_SUBEXP); + tree1 = body ? create_tree (dfa, body, cls, CONCAT) : cls; + tree = create_tree (dfa, op, tree1, CONCAT); + if (BE (tree == NULL || tree1 == NULL || op == NULL || cls == NULL, 0)) + { + *err = REG_ESPACE; + return NULL; + } + + op->token.opr.idx = cls->token.opr.idx = node->token.opr.idx; + op->token.opt_subexp = cls->token.opt_subexp = node->token.opt_subexp; + return tree; +} + +/* Pass 1 in building the NFA: compute FIRST and create unlinked automaton + nodes. Requires a postorder visit. */ +static reg_errcode_t +calc_first (void *extra, bin_tree_t *node) +{ + re_dfa_t *dfa = (re_dfa_t *) extra; + if (node->token.type == CONCAT) + { + node->first = node->left->first; + node->node_idx = node->left->node_idx; + } + else + { + node->first = node; + node->node_idx = re_dfa_add_node (dfa, node->token); + if (BE (node->node_idx == -1, 0)) + return REG_ESPACE; + } + return REG_NOERROR; +} + +/* Pass 2: compute NEXT on the tree. Preorder visit. */ +static reg_errcode_t +calc_next (void *extra, bin_tree_t *node) +{ + switch (node->token.type) + { + case OP_DUP_ASTERISK: + node->left->next = node; + break; + case CONCAT: + node->left->next = node->right->first; + node->right->next = node->next; + break; + default: + if (node->left) + node->left->next = node->next; + if (node->right) + node->right->next = node->next; + break; + } + return REG_NOERROR; +} + +/* Pass 3: link all DFA nodes to their NEXT node (any order will do). */ +static reg_errcode_t +link_nfa_nodes (void *extra, bin_tree_t *node) +{ + re_dfa_t *dfa = (re_dfa_t *) extra; + int idx = node->node_idx; + reg_errcode_t err = REG_NOERROR; + + switch (node->token.type) + { + case CONCAT: + break; + + case END_OF_RE: + assert (node->next == NULL); + break; + + case OP_DUP_ASTERISK: + case OP_ALT: + { + int left, right; + dfa->has_plural_match = 1; + if (node->left != NULL) + left = node->left->first->node_idx; + else + left = node->next->node_idx; + if (node->right != NULL) + right = node->right->first->node_idx; + else + right = node->next->node_idx; + assert (left > -1); + assert (right > -1); + err = re_node_set_init_2 (dfa->edests + idx, left, right); + } + break; + + case ANCHOR: + case OP_OPEN_SUBEXP: + case OP_CLOSE_SUBEXP: + err = re_node_set_init_1 (dfa->edests + idx, node->next->node_idx); + break; + + case OP_BACK_REF: + dfa->nexts[idx] = node->next->node_idx; + if (node->token.type == OP_BACK_REF) + re_node_set_init_1 (dfa->edests + idx, dfa->nexts[idx]); + break; + + default: + assert (!IS_EPSILON_NODE (node->token.type)); + dfa->nexts[idx] = node->next->node_idx; + break; + } + + return err; +} + +/* Duplicate the epsilon closure of the node ROOT_NODE. + Note that duplicated nodes have constraint INIT_CONSTRAINT in addition + to their own constraint. */ + +static reg_errcode_t +internal_function +duplicate_node_closure (re_dfa_t *dfa, int top_org_node, int top_clone_node, + int root_node, unsigned int init_constraint) +{ + int org_node, clone_node, ret; + unsigned int constraint = init_constraint; + for (org_node = top_org_node, clone_node = top_clone_node;;) + { + int org_dest, clone_dest; + if (dfa->nodes[org_node].type == OP_BACK_REF) + { + /* If the back reference epsilon-transit, its destination must + also have the constraint. Then duplicate the epsilon closure + of the destination of the back reference, and store it in + edests of the back reference. */ + org_dest = dfa->nexts[org_node]; + re_node_set_empty (dfa->edests + clone_node); + clone_dest = duplicate_node (dfa, org_dest, constraint); + if (BE (clone_dest == -1, 0)) + return REG_ESPACE; + dfa->nexts[clone_node] = dfa->nexts[org_node]; + ret = re_node_set_insert (dfa->edests + clone_node, clone_dest); + if (BE (ret < 0, 0)) + return REG_ESPACE; + } + else if (dfa->edests[org_node].nelem == 0) + { + /* In case of the node can't epsilon-transit, don't duplicate the + destination and store the original destination as the + destination of the node. */ + dfa->nexts[clone_node] = dfa->nexts[org_node]; + break; + } + else if (dfa->edests[org_node].nelem == 1) + { + /* In case of the node can epsilon-transit, and it has only one + destination. */ + org_dest = dfa->edests[org_node].elems[0]; + re_node_set_empty (dfa->edests + clone_node); + if (dfa->nodes[org_node].type == ANCHOR) + { + /* In case of the node has another constraint, append it. */ + if (org_node == root_node && clone_node != org_node) + { + /* ...but if the node is root_node itself, it means the + epsilon closure have a loop, then tie it to the + destination of the root_node. */ + ret = re_node_set_insert (dfa->edests + clone_node, + org_dest); + if (BE (ret < 0, 0)) + return REG_ESPACE; + break; + } + constraint |= dfa->nodes[org_node].opr.ctx_type; + } + clone_dest = duplicate_node (dfa, org_dest, constraint); + if (BE (clone_dest == -1, 0)) + return REG_ESPACE; + ret = re_node_set_insert (dfa->edests + clone_node, clone_dest); + if (BE (ret < 0, 0)) + return REG_ESPACE; + } + else /* dfa->edests[org_node].nelem == 2 */ + { + /* In case of the node can epsilon-transit, and it has two + destinations. In the bin_tree_t and DFA, that's '|' and '*'. */ + org_dest = dfa->edests[org_node].elems[0]; + re_node_set_empty (dfa->edests + clone_node); + /* Search for a duplicated node which satisfies the constraint. */ + clone_dest = search_duplicated_node (dfa, org_dest, constraint); + if (clone_dest == -1) + { + /* There are no such a duplicated node, create a new one. */ + reg_errcode_t err; + clone_dest = duplicate_node (dfa, org_dest, constraint); + if (BE (clone_dest == -1, 0)) + return REG_ESPACE; + ret = re_node_set_insert (dfa->edests + clone_node, clone_dest); + if (BE (ret < 0, 0)) + return REG_ESPACE; + err = duplicate_node_closure (dfa, org_dest, clone_dest, + root_node, constraint); + if (BE (err != REG_NOERROR, 0)) + return err; + } + else + { + /* There are a duplicated node which satisfy the constraint, + use it to avoid infinite loop. */ + ret = re_node_set_insert (dfa->edests + clone_node, clone_dest); + if (BE (ret < 0, 0)) + return REG_ESPACE; + } + + org_dest = dfa->edests[org_node].elems[1]; + clone_dest = duplicate_node (dfa, org_dest, constraint); + if (BE (clone_dest == -1, 0)) + return REG_ESPACE; + ret = re_node_set_insert (dfa->edests + clone_node, clone_dest); + if (BE (ret < 0, 0)) + return REG_ESPACE; + } + org_node = org_dest; + clone_node = clone_dest; + } + return REG_NOERROR; +} + +/* Search for a node which is duplicated from the node ORG_NODE, and + satisfies the constraint CONSTRAINT. */ + +static int +search_duplicated_node (const re_dfa_t *dfa, int org_node, + unsigned int constraint) +{ + int idx; + for (idx = dfa->nodes_len - 1; dfa->nodes[idx].duplicated && idx > 0; --idx) + { + if (org_node == dfa->org_indices[idx] + && constraint == dfa->nodes[idx].constraint) + return idx; /* Found. */ + } + return -1; /* Not found. */ +} + +/* Duplicate the node whose index is ORG_IDX and set the constraint CONSTRAINT. + Return the index of the new node, or -1 if insufficient storage is + available. */ + +static int +duplicate_node (re_dfa_t *dfa, int org_idx, unsigned int constraint) +{ + int dup_idx = re_dfa_add_node (dfa, dfa->nodes[org_idx]); + if (BE (dup_idx != -1, 1)) + { + dfa->nodes[dup_idx].constraint = constraint; + if (dfa->nodes[org_idx].type == ANCHOR) + dfa->nodes[dup_idx].constraint |= dfa->nodes[org_idx].opr.ctx_type; + dfa->nodes[dup_idx].duplicated = 1; + + /* Store the index of the original node. */ + dfa->org_indices[dup_idx] = org_idx; + } + return dup_idx; +} + +static reg_errcode_t +calc_inveclosure (re_dfa_t *dfa) +{ + int src, idx, ret; + for (idx = 0; idx < dfa->nodes_len; ++idx) + re_node_set_init_empty (dfa->inveclosures + idx); + + for (src = 0; src < dfa->nodes_len; ++src) + { + int *elems = dfa->eclosures[src].elems; + for (idx = 0; idx < dfa->eclosures[src].nelem; ++idx) + { + ret = re_node_set_insert_last (dfa->inveclosures + elems[idx], src); + if (BE (ret == -1, 0)) + return REG_ESPACE; + } + } + + return REG_NOERROR; +} + +/* Calculate "eclosure" for all the node in DFA. */ + +static reg_errcode_t +calc_eclosure (re_dfa_t *dfa) +{ + int node_idx, incomplete; +#ifdef DEBUG + assert (dfa->nodes_len > 0); +#endif + incomplete = 0; + /* For each nodes, calculate epsilon closure. */ + for (node_idx = 0; ; ++node_idx) + { + reg_errcode_t err; + re_node_set eclosure_elem; + if (node_idx == dfa->nodes_len) + { + if (!incomplete) + break; + incomplete = 0; + node_idx = 0; + } + +#ifdef DEBUG + assert (dfa->eclosures[node_idx].nelem != -1); +#endif + + /* If we have already calculated, skip it. */ + if (dfa->eclosures[node_idx].nelem != 0) + continue; + /* Calculate epsilon closure of `node_idx'. */ + err = calc_eclosure_iter (&eclosure_elem, dfa, node_idx, 1); + if (BE (err != REG_NOERROR, 0)) + return err; + + if (dfa->eclosures[node_idx].nelem == 0) + { + incomplete = 1; + re_node_set_free (&eclosure_elem); + } + } + return REG_NOERROR; +} + +/* Calculate epsilon closure of NODE. */ + +static reg_errcode_t +calc_eclosure_iter (re_node_set *new_set, re_dfa_t *dfa, int node, int root) +{ + reg_errcode_t err; + unsigned int constraint; + int i, incomplete; + re_node_set eclosure; + incomplete = 0; + err = re_node_set_alloc (&eclosure, dfa->edests[node].nelem + 1); + if (BE (err != REG_NOERROR, 0)) + return err; + + /* This indicates that we are calculating this node now. + We reference this value to avoid infinite loop. */ + dfa->eclosures[node].nelem = -1; + + constraint = ((dfa->nodes[node].type == ANCHOR) + ? dfa->nodes[node].opr.ctx_type : 0); + /* If the current node has constraints, duplicate all nodes. + Since they must inherit the constraints. */ + if (constraint + && dfa->edests[node].nelem + && !dfa->nodes[dfa->edests[node].elems[0]].duplicated) + { + err = duplicate_node_closure (dfa, node, node, node, constraint); + if (BE (err != REG_NOERROR, 0)) + return err; + } + + /* Expand each epsilon destination nodes. */ + if (IS_EPSILON_NODE(dfa->nodes[node].type)) + for (i = 0; i < dfa->edests[node].nelem; ++i) + { + re_node_set eclosure_elem; + int edest = dfa->edests[node].elems[i]; + /* If calculating the epsilon closure of `edest' is in progress, + return intermediate result. */ + if (dfa->eclosures[edest].nelem == -1) + { + incomplete = 1; + continue; + } + /* If we haven't calculated the epsilon closure of `edest' yet, + calculate now. Otherwise use calculated epsilon closure. */ + if (dfa->eclosures[edest].nelem == 0) + { + err = calc_eclosure_iter (&eclosure_elem, dfa, edest, 0); + if (BE (err != REG_NOERROR, 0)) + return err; + } + else + eclosure_elem = dfa->eclosures[edest]; + /* Merge the epsilon closure of `edest'. */ + re_node_set_merge (&eclosure, &eclosure_elem); + /* If the epsilon closure of `edest' is incomplete, + the epsilon closure of this node is also incomplete. */ + if (dfa->eclosures[edest].nelem == 0) + { + incomplete = 1; + re_node_set_free (&eclosure_elem); + } + } + + /* Epsilon closures include itself. */ + re_node_set_insert (&eclosure, node); + if (incomplete && !root) + dfa->eclosures[node].nelem = 0; + else + dfa->eclosures[node] = eclosure; + *new_set = eclosure; + return REG_NOERROR; +} + +/* Functions for token which are used in the parser. */ + +/* Fetch a token from INPUT. + We must not use this function inside bracket expressions. */ + +static void +internal_function +fetch_token (re_token_t *result, re_string_t *input, reg_syntax_t syntax) +{ + re_string_skip_bytes (input, peek_token (result, input, syntax)); +} + +/* Peek a token from INPUT, and return the length of the token. + We must not use this function inside bracket expressions. */ + +static int +internal_function +peek_token (re_token_t *token, re_string_t *input, reg_syntax_t syntax) +{ + unsigned char c; + + if (re_string_eoi (input)) + { + token->type = END_OF_RE; + return 0; + } + + c = re_string_peek_byte (input, 0); + token->opr.c = c; + + token->word_char = 0; +#ifdef RE_ENABLE_I18N + token->mb_partial = 0; + if (input->mb_cur_max > 1 && + !re_string_first_byte (input, re_string_cur_idx (input))) + { + token->type = CHARACTER; + token->mb_partial = 1; + return 1; + } +#endif + if (c == '\\') + { + unsigned char c2; + if (re_string_cur_idx (input) + 1 >= re_string_length (input)) + { + token->type = BACK_SLASH; + return 1; + } + + c2 = re_string_peek_byte_case (input, 1); + token->opr.c = c2; + token->type = CHARACTER; +#ifdef RE_ENABLE_I18N + if (input->mb_cur_max > 1) + { + wint_t wc = re_string_wchar_at (input, + re_string_cur_idx (input) + 1); + token->word_char = IS_WIDE_WORD_CHAR (wc) != 0; + } + else +#endif + token->word_char = IS_WORD_CHAR (c2) != 0; + + switch (c2) + { + case '|': + if (!(syntax & RE_LIMITED_OPS) && !(syntax & RE_NO_BK_VBAR)) + token->type = OP_ALT; + break; + case '1': case '2': case '3': case '4': case '5': + case '6': case '7': case '8': case '9': + if (!(syntax & RE_NO_BK_REFS)) + { + token->type = OP_BACK_REF; + token->opr.idx = c2 - '1'; + } + break; + case '<': + if (!(syntax & RE_NO_GNU_OPS)) + { + token->type = ANCHOR; + token->opr.ctx_type = WORD_FIRST; + } + break; + case '>': + if (!(syntax & RE_NO_GNU_OPS)) + { + token->type = ANCHOR; + token->opr.ctx_type = WORD_LAST; + } + break; + case 'b': + if (!(syntax & RE_NO_GNU_OPS)) + { + token->type = ANCHOR; + token->opr.ctx_type = WORD_DELIM; + } + break; + case 'B': + if (!(syntax & RE_NO_GNU_OPS)) + { + token->type = ANCHOR; + token->opr.ctx_type = NOT_WORD_DELIM; + } + break; + case 'w': + if (!(syntax & RE_NO_GNU_OPS)) + token->type = OP_WORD; + break; + case 'W': + if (!(syntax & RE_NO_GNU_OPS)) + token->type = OP_NOTWORD; + break; + case 's': + if (!(syntax & RE_NO_GNU_OPS)) + token->type = OP_SPACE; + break; + case 'S': + if (!(syntax & RE_NO_GNU_OPS)) + token->type = OP_NOTSPACE; + break; + case '`': + if (!(syntax & RE_NO_GNU_OPS)) + { + token->type = ANCHOR; + token->opr.ctx_type = BUF_FIRST; + } + break; + case '\'': + if (!(syntax & RE_NO_GNU_OPS)) + { + token->type = ANCHOR; + token->opr.ctx_type = BUF_LAST; + } + break; + case '(': + if (!(syntax & RE_NO_BK_PARENS)) + token->type = OP_OPEN_SUBEXP; + break; + case ')': + if (!(syntax & RE_NO_BK_PARENS)) + token->type = OP_CLOSE_SUBEXP; + break; + case '+': + if (!(syntax & RE_LIMITED_OPS) && (syntax & RE_BK_PLUS_QM)) + token->type = OP_DUP_PLUS; + break; + case '?': + if (!(syntax & RE_LIMITED_OPS) && (syntax & RE_BK_PLUS_QM)) + token->type = OP_DUP_QUESTION; + break; + case '{': + if ((syntax & RE_INTERVALS) && (!(syntax & RE_NO_BK_BRACES))) + token->type = OP_OPEN_DUP_NUM; + break; + case '}': + if ((syntax & RE_INTERVALS) && (!(syntax & RE_NO_BK_BRACES))) + token->type = OP_CLOSE_DUP_NUM; + break; + default: + break; + } + return 2; + } + + token->type = CHARACTER; +#ifdef RE_ENABLE_I18N + if (input->mb_cur_max > 1) + { + wint_t wc = re_string_wchar_at (input, re_string_cur_idx (input)); + token->word_char = IS_WIDE_WORD_CHAR (wc) != 0; + } + else +#endif + token->word_char = IS_WORD_CHAR (token->opr.c); + + switch (c) + { + case '\n': + if (syntax & RE_NEWLINE_ALT) + token->type = OP_ALT; + break; + case '|': + if (!(syntax & RE_LIMITED_OPS) && (syntax & RE_NO_BK_VBAR)) + token->type = OP_ALT; + break; + case '*': + token->type = OP_DUP_ASTERISK; + break; + case '+': + if (!(syntax & RE_LIMITED_OPS) && !(syntax & RE_BK_PLUS_QM)) + token->type = OP_DUP_PLUS; + break; + case '?': + if (!(syntax & RE_LIMITED_OPS) && !(syntax & RE_BK_PLUS_QM)) + token->type = OP_DUP_QUESTION; + break; + case '{': + if ((syntax & RE_INTERVALS) && (syntax & RE_NO_BK_BRACES)) + token->type = OP_OPEN_DUP_NUM; + break; + case '}': + if ((syntax & RE_INTERVALS) && (syntax & RE_NO_BK_BRACES)) + token->type = OP_CLOSE_DUP_NUM; + break; + case '(': + if (syntax & RE_NO_BK_PARENS) + token->type = OP_OPEN_SUBEXP; + break; + case ')': + if (syntax & RE_NO_BK_PARENS) + token->type = OP_CLOSE_SUBEXP; + break; + case '[': + token->type = OP_OPEN_BRACKET; + break; + case '.': + token->type = OP_PERIOD; + break; + case '^': + if (!(syntax & (RE_CONTEXT_INDEP_ANCHORS | RE_CARET_ANCHORS_HERE)) && + re_string_cur_idx (input) != 0) + { + char prev = re_string_peek_byte (input, -1); + if (!(syntax & RE_NEWLINE_ALT) || prev != '\n') + break; + } + token->type = ANCHOR; + token->opr.ctx_type = LINE_FIRST; + break; + case '$': + if (!(syntax & RE_CONTEXT_INDEP_ANCHORS) && + re_string_cur_idx (input) + 1 != re_string_length (input)) + { + re_token_t next; + re_string_skip_bytes (input, 1); + peek_token (&next, input, syntax); + re_string_skip_bytes (input, -1); + if (next.type != OP_ALT && next.type != OP_CLOSE_SUBEXP) + break; + } + token->type = ANCHOR; + token->opr.ctx_type = LINE_LAST; + break; + default: + break; + } + return 1; +} + +/* Peek a token from INPUT, and return the length of the token. + We must not use this function out of bracket expressions. */ + +static int +internal_function +peek_token_bracket (re_token_t *token, re_string_t *input, reg_syntax_t syntax) +{ + unsigned char c; + if (re_string_eoi (input)) + { + token->type = END_OF_RE; + return 0; + } + c = re_string_peek_byte (input, 0); + token->opr.c = c; + +#ifdef RE_ENABLE_I18N + if (input->mb_cur_max > 1 && + !re_string_first_byte (input, re_string_cur_idx (input))) + { + token->type = CHARACTER; + return 1; + } +#endif + + if (c == '\\' && (syntax & RE_BACKSLASH_ESCAPE_IN_LISTS) + && re_string_cur_idx (input) + 1 < re_string_length (input)) + { + /* In this case, '\' escape a character. */ + unsigned char c2; + re_string_skip_bytes (input, 1); + c2 = re_string_peek_byte (input, 0); + token->opr.c = c2; + token->type = CHARACTER; + return 1; + } + if (c == '[') /* '[' is a special char in a bracket exps. */ + { + unsigned char c2; + int token_len; + if (re_string_cur_idx (input) + 1 < re_string_length (input)) + c2 = re_string_peek_byte (input, 1); + else + c2 = 0; + token->opr.c = c2; + token_len = 2; + switch (c2) + { + case '.': + token->type = OP_OPEN_COLL_ELEM; + break; + case '=': + token->type = OP_OPEN_EQUIV_CLASS; + break; + case ':': + if (syntax & RE_CHAR_CLASSES) + { + token->type = OP_OPEN_CHAR_CLASS; + break; + } + /* else fall through. */ + default: + token->type = CHARACTER; + token->opr.c = c; + token_len = 1; + break; + } + return token_len; + } + switch (c) + { + case '-': + token->type = OP_CHARSET_RANGE; + break; + case ']': + token->type = OP_CLOSE_BRACKET; + break; + case '^': + token->type = OP_NON_MATCH_LIST; + break; + default: + token->type = CHARACTER; + } + return 1; +} + +/* Functions for parser. */ + +/* Entry point of the parser. + Parse the regular expression REGEXP and return the structure tree. + If an error is occured, ERR is set by error code, and return NULL. + This function build the following tree, from regular expression : + CAT + / \ + / \ + EOR + + CAT means concatenation. + EOR means end of regular expression. */ + +static bin_tree_t * +parse (re_string_t *regexp, regex_t *preg, reg_syntax_t syntax, + reg_errcode_t *err) +{ + re_dfa_t *dfa = (re_dfa_t *) preg->buffer; + bin_tree_t *tree, *eor, *root; + re_token_t current_token; + dfa->syntax = syntax; + fetch_token (¤t_token, regexp, syntax | RE_CARET_ANCHORS_HERE); + tree = parse_reg_exp (regexp, preg, ¤t_token, syntax, 0, err); + if (BE (*err != REG_NOERROR && tree == NULL, 0)) + return NULL; + eor = create_tree (dfa, NULL, NULL, END_OF_RE); + if (tree != NULL) + root = create_tree (dfa, tree, eor, CONCAT); + else + root = eor; + if (BE (eor == NULL || root == NULL, 0)) + { + *err = REG_ESPACE; + return NULL; + } + return root; +} + +/* This function build the following tree, from regular expression + |: + ALT + / \ + / \ + + + ALT means alternative, which represents the operator `|'. */ + +static bin_tree_t * +parse_reg_exp (re_string_t *regexp, regex_t *preg, re_token_t *token, + reg_syntax_t syntax, int nest, reg_errcode_t *err) +{ + re_dfa_t *dfa = (re_dfa_t *) preg->buffer; + bin_tree_t *tree, *branch = NULL; + tree = parse_branch (regexp, preg, token, syntax, nest, err); + if (BE (*err != REG_NOERROR && tree == NULL, 0)) + return NULL; + + while (token->type == OP_ALT) + { + fetch_token (token, regexp, syntax | RE_CARET_ANCHORS_HERE); + if (token->type != OP_ALT && token->type != END_OF_RE + && (nest == 0 || token->type != OP_CLOSE_SUBEXP)) + { + branch = parse_branch (regexp, preg, token, syntax, nest, err); + if (BE (*err != REG_NOERROR && branch == NULL, 0)) + return NULL; + } + else + branch = NULL; + tree = create_tree (dfa, tree, branch, OP_ALT); + if (BE (tree == NULL, 0)) + { + *err = REG_ESPACE; + return NULL; + } + } + return tree; +} + +/* This function build the following tree, from regular expression + : + CAT + / \ + / \ + + + CAT means concatenation. */ + +static bin_tree_t * +parse_branch (re_string_t *regexp, regex_t *preg, re_token_t *token, + reg_syntax_t syntax, int nest, reg_errcode_t *err) +{ + bin_tree_t *tree, *exp; + re_dfa_t *dfa = (re_dfa_t *) preg->buffer; + tree = parse_expression (regexp, preg, token, syntax, nest, err); + if (BE (*err != REG_NOERROR && tree == NULL, 0)) + return NULL; + + while (token->type != OP_ALT && token->type != END_OF_RE + && (nest == 0 || token->type != OP_CLOSE_SUBEXP)) + { + exp = parse_expression (regexp, preg, token, syntax, nest, err); + if (BE (*err != REG_NOERROR && exp == NULL, 0)) + { + return NULL; + } + if (tree != NULL && exp != NULL) + { + tree = create_tree (dfa, tree, exp, CONCAT); + if (tree == NULL) + { + *err = REG_ESPACE; + return NULL; + } + } + else if (tree == NULL) + tree = exp; + /* Otherwise exp == NULL, we don't need to create new tree. */ + } + return tree; +} + +/* This function build the following tree, from regular expression a*: + * + | + a +*/ + +static bin_tree_t * +parse_expression (re_string_t *regexp, regex_t *preg, re_token_t *token, + reg_syntax_t syntax, int nest, reg_errcode_t *err) +{ + re_dfa_t *dfa = (re_dfa_t *) preg->buffer; + bin_tree_t *tree; + switch (token->type) + { + case CHARACTER: + tree = create_token_tree (dfa, NULL, NULL, token); + if (BE (tree == NULL, 0)) + { + *err = REG_ESPACE; + return NULL; + } +#ifdef RE_ENABLE_I18N + if (dfa->mb_cur_max > 1) + { + while (!re_string_eoi (regexp) + && !re_string_first_byte (regexp, re_string_cur_idx (regexp))) + { + bin_tree_t *mbc_remain; + fetch_token (token, regexp, syntax); + mbc_remain = create_token_tree (dfa, NULL, NULL, token); + tree = create_tree (dfa, tree, mbc_remain, CONCAT); + if (BE (mbc_remain == NULL || tree == NULL, 0)) + { + *err = REG_ESPACE; + return NULL; + } + } + } +#endif + break; + case OP_OPEN_SUBEXP: + tree = parse_sub_exp (regexp, preg, token, syntax, nest + 1, err); + if (BE (*err != REG_NOERROR && tree == NULL, 0)) + return NULL; + break; + case OP_OPEN_BRACKET: + tree = parse_bracket_exp (regexp, dfa, token, syntax, err); + if (BE (*err != REG_NOERROR && tree == NULL, 0)) + return NULL; + break; + case OP_BACK_REF: + if (!BE (dfa->completed_bkref_map & (1 << token->opr.idx), 1)) + { + *err = REG_ESUBREG; + return NULL; + } + dfa->used_bkref_map |= 1 << token->opr.idx; + tree = create_token_tree (dfa, NULL, NULL, token); + if (BE (tree == NULL, 0)) + { + *err = REG_ESPACE; + return NULL; + } + ++dfa->nbackref; + dfa->has_mb_node = 1; + break; + case OP_OPEN_DUP_NUM: + if (syntax & RE_CONTEXT_INVALID_DUP) + { + *err = REG_BADRPT; + return NULL; + } + /* FALLTHROUGH */ + case OP_DUP_ASTERISK: + case OP_DUP_PLUS: + case OP_DUP_QUESTION: + if (syntax & RE_CONTEXT_INVALID_OPS) + { + *err = REG_BADRPT; + return NULL; + } + else if (syntax & RE_CONTEXT_INDEP_OPS) + { + fetch_token (token, regexp, syntax); + return parse_expression (regexp, preg, token, syntax, nest, err); + } + /* else fall through */ + case OP_CLOSE_SUBEXP: + if ((token->type == OP_CLOSE_SUBEXP) && + !(syntax & RE_UNMATCHED_RIGHT_PAREN_ORD)) + { + *err = REG_ERPAREN; + return NULL; + } + /* else fall through */ + case OP_CLOSE_DUP_NUM: + /* We treat it as a normal character. */ + + /* Then we can these characters as normal characters. */ + token->type = CHARACTER; + /* mb_partial and word_char bits should be initialized already + by peek_token. */ + tree = create_token_tree (dfa, NULL, NULL, token); + if (BE (tree == NULL, 0)) + { + *err = REG_ESPACE; + return NULL; + } + break; + case ANCHOR: + if ((token->opr.ctx_type + & (WORD_DELIM | NOT_WORD_DELIM | WORD_FIRST | WORD_LAST)) + && dfa->word_ops_used == 0) + init_word_char (dfa); + if (token->opr.ctx_type == WORD_DELIM + || token->opr.ctx_type == NOT_WORD_DELIM) + { + bin_tree_t *tree_first, *tree_last; + if (token->opr.ctx_type == WORD_DELIM) + { + token->opr.ctx_type = WORD_FIRST; + tree_first = create_token_tree (dfa, NULL, NULL, token); + token->opr.ctx_type = WORD_LAST; + } + else + { + token->opr.ctx_type = INSIDE_WORD; + tree_first = create_token_tree (dfa, NULL, NULL, token); + token->opr.ctx_type = INSIDE_NOTWORD; + } + tree_last = create_token_tree (dfa, NULL, NULL, token); + tree = create_tree (dfa, tree_first, tree_last, OP_ALT); + if (BE (tree_first == NULL || tree_last == NULL || tree == NULL, 0)) + { + *err = REG_ESPACE; + return NULL; + } + } + else + { + tree = create_token_tree (dfa, NULL, NULL, token); + if (BE (tree == NULL, 0)) + { + *err = REG_ESPACE; + return NULL; + } + } + /* We must return here, since ANCHORs can't be followed + by repetition operators. + eg. RE"^*" is invalid or "", + it must not be "". */ + fetch_token (token, regexp, syntax); + return tree; + case OP_PERIOD: + tree = create_token_tree (dfa, NULL, NULL, token); + if (BE (tree == NULL, 0)) + { + *err = REG_ESPACE; + return NULL; + } + if (dfa->mb_cur_max > 1) + dfa->has_mb_node = 1; + break; + case OP_WORD: + case OP_NOTWORD: + tree = build_charclass_op (dfa, regexp->trans, + (const unsigned char *) "alnum", + (const unsigned char *) "_", + token->type == OP_NOTWORD, err); + if (BE (*err != REG_NOERROR && tree == NULL, 0)) + return NULL; + break; + case OP_SPACE: + case OP_NOTSPACE: + tree = build_charclass_op (dfa, regexp->trans, + (const unsigned char *) "space", + (const unsigned char *) "", + token->type == OP_NOTSPACE, err); + if (BE (*err != REG_NOERROR && tree == NULL, 0)) + return NULL; + break; + case OP_ALT: + case END_OF_RE: + return NULL; + case BACK_SLASH: + *err = REG_EESCAPE; + return NULL; + default: + /* Must not happen? */ +#ifdef DEBUG + assert (0); +#endif + return NULL; + } + fetch_token (token, regexp, syntax); + + while (token->type == OP_DUP_ASTERISK || token->type == OP_DUP_PLUS + || token->type == OP_DUP_QUESTION || token->type == OP_OPEN_DUP_NUM) + { + tree = parse_dup_op (tree, regexp, dfa, token, syntax, err); + if (BE (*err != REG_NOERROR && tree == NULL, 0)) + return NULL; + /* In BRE consecutive duplications are not allowed. */ + if ((syntax & RE_CONTEXT_INVALID_DUP) + && (token->type == OP_DUP_ASTERISK + || token->type == OP_OPEN_DUP_NUM)) + { + *err = REG_BADRPT; + return NULL; + } + } + + return tree; +} + +/* This function build the following tree, from regular expression + (): + SUBEXP + | + +*/ + +static bin_tree_t * +parse_sub_exp (re_string_t *regexp, regex_t *preg, re_token_t *token, + reg_syntax_t syntax, int nest, reg_errcode_t *err) +{ + re_dfa_t *dfa = (re_dfa_t *) preg->buffer; + bin_tree_t *tree; + size_t cur_nsub; + cur_nsub = preg->re_nsub++; + + fetch_token (token, regexp, syntax | RE_CARET_ANCHORS_HERE); + + /* The subexpression may be a null string. */ + if (token->type == OP_CLOSE_SUBEXP) + tree = NULL; + else + { + tree = parse_reg_exp (regexp, preg, token, syntax, nest, err); + if (BE (*err == REG_NOERROR && token->type != OP_CLOSE_SUBEXP, 0)) + *err = REG_EPAREN; + if (BE (*err != REG_NOERROR, 0)) + return NULL; + } + + if (cur_nsub <= '9' - '1') + dfa->completed_bkref_map |= 1 << cur_nsub; + + tree = create_tree (dfa, tree, NULL, SUBEXP); + if (BE (tree == NULL, 0)) + { + *err = REG_ESPACE; + return NULL; + } + tree->token.opr.idx = cur_nsub; + return tree; +} + +/* This function parse repetition operators like "*", "+", "{1,3}" etc. */ + +static bin_tree_t * +parse_dup_op (bin_tree_t *elem, re_string_t *regexp, re_dfa_t *dfa, + re_token_t *token, reg_syntax_t syntax, reg_errcode_t *err) +{ + bin_tree_t *tree = NULL, *old_tree = NULL; + int i, start, end, start_idx = re_string_cur_idx (regexp); + re_token_t start_token = *token; + + if (token->type == OP_OPEN_DUP_NUM) + { + end = 0; + start = fetch_number (regexp, token, syntax); + if (start == -1) + { + if (token->type == CHARACTER && token->opr.c == ',') + start = 0; /* We treat "{,m}" as "{0,m}". */ + else + { + *err = REG_BADBR; /* {} is invalid. */ + return NULL; + } + } + if (BE (start != -2, 1)) + { + /* We treat "{n}" as "{n,n}". */ + end = ((token->type == OP_CLOSE_DUP_NUM) ? start + : ((token->type == CHARACTER && token->opr.c == ',') + ? fetch_number (regexp, token, syntax) : -2)); + } + if (BE (start == -2 || end == -2, 0)) + { + /* Invalid sequence. */ + if (BE (!(syntax & RE_INVALID_INTERVAL_ORD), 0)) + { + if (token->type == END_OF_RE) + *err = REG_EBRACE; + else + *err = REG_BADBR; + + return NULL; + } + + /* If the syntax bit is set, rollback. */ + re_string_set_index (regexp, start_idx); + *token = start_token; + token->type = CHARACTER; + /* mb_partial and word_char bits should be already initialized by + peek_token. */ + return elem; + } + + if (BE (end != -1 && start > end, 0)) + { + /* First number greater than second. */ + *err = REG_BADBR; + return NULL; + } + } + else + { + start = (token->type == OP_DUP_PLUS) ? 1 : 0; + end = (token->type == OP_DUP_QUESTION) ? 1 : -1; + } + + fetch_token (token, regexp, syntax); + + if (BE (elem == NULL, 0)) + return NULL; + if (BE (start == 0 && end == 0, 0)) + { + postorder (elem, free_tree, NULL); + return NULL; + } + + /* Extract "{n,m}" to "...{0,}". */ + if (BE (start > 0, 0)) + { + tree = elem; + for (i = 2; i <= start; ++i) + { + elem = duplicate_tree (elem, dfa); + tree = create_tree (dfa, tree, elem, CONCAT); + if (BE (elem == NULL || tree == NULL, 0)) + goto parse_dup_op_espace; + } + + if (start == end) + return tree; + + /* Duplicate ELEM before it is marked optional. */ + elem = duplicate_tree (elem, dfa); + old_tree = tree; + } + else + old_tree = NULL; + + if (elem->token.type == SUBEXP) + postorder (elem, mark_opt_subexp, (void *) (long) elem->token.opr.idx); + + tree = create_tree (dfa, elem, NULL, (end == -1 ? OP_DUP_ASTERISK : OP_ALT)); + if (BE (tree == NULL, 0)) + goto parse_dup_op_espace; + + /* This loop is actually executed only when end != -1, + to rewrite {0,n} as ((...?)?)?... We have + already created the start+1-th copy. */ + for (i = start + 2; i <= end; ++i) + { + elem = duplicate_tree (elem, dfa); + tree = create_tree (dfa, tree, elem, CONCAT); + if (BE (elem == NULL || tree == NULL, 0)) + goto parse_dup_op_espace; + + tree = create_tree (dfa, tree, NULL, OP_ALT); + if (BE (tree == NULL, 0)) + goto parse_dup_op_espace; + } + + if (old_tree) + tree = create_tree (dfa, old_tree, tree, CONCAT); + + return tree; + + parse_dup_op_espace: + *err = REG_ESPACE; + return NULL; +} + +/* Size of the names for collating symbol/equivalence_class/character_class. + I'm not sure, but maybe enough. */ +#define BRACKET_NAME_BUF_SIZE 32 + +#if 1 + /* Local function for parse_bracket_exp only used in case of NOT glibc. + Build the range expression which starts from START_ELEM, and ends + at END_ELEM. The result are written to MBCSET and SBCSET. + RANGE_ALLOC is the allocated size of mbcset->range_starts, and + mbcset->range_ends, is a pointer argument sinse we may + update it. */ + +static reg_errcode_t +internal_function +# ifdef RE_ENABLE_I18N +build_range_exp (bitset_t sbcset, re_charset_t *mbcset, int *range_alloc, + bracket_elem_t *start_elem, bracket_elem_t *end_elem) +# else +build_range_exp (bitset_t sbcset, bracket_elem_t *start_elem, + bracket_elem_t *end_elem) +# endif +{ + unsigned int start_ch, end_ch; + /* Equivalence Classes and Character Classes can't be a range start/end. */ + if (BE (start_elem->type == EQUIV_CLASS || start_elem->type == CHAR_CLASS + || end_elem->type == EQUIV_CLASS || end_elem->type == CHAR_CLASS, + 0)) + return REG_ERANGE; + + /* We can handle no multi character collating elements without libc + support. */ + if (BE ((start_elem->type == COLL_SYM + && strlen ((char *) start_elem->opr.name) > 1) + || (end_elem->type == COLL_SYM + && strlen ((char *) end_elem->opr.name) > 1), 0)) + return REG_ECOLLATE; + +# ifdef RE_ENABLE_I18N + { + wchar_t wc; + wint_t start_wc; + wint_t end_wc; + wchar_t cmp_buf[6] = {L'\0', L'\0', L'\0', L'\0', L'\0', L'\0'}; + + start_ch = ((start_elem->type == SB_CHAR) ? start_elem->opr.ch + : ((start_elem->type == COLL_SYM) ? start_elem->opr.name[0] + : 0)); + end_ch = ((end_elem->type == SB_CHAR) ? end_elem->opr.ch + : ((end_elem->type == COLL_SYM) ? end_elem->opr.name[0] + : 0)); + start_wc = ((start_elem->type == SB_CHAR || start_elem->type == COLL_SYM) + ? __btowc (start_ch) : start_elem->opr.wch); + end_wc = ((end_elem->type == SB_CHAR || end_elem->type == COLL_SYM) + ? __btowc (end_ch) : end_elem->opr.wch); + if (start_wc == WEOF || end_wc == WEOF) + return REG_ECOLLATE; + cmp_buf[0] = start_wc; + cmp_buf[4] = end_wc; + if (wcscoll (cmp_buf, cmp_buf + 4) > 0) + return REG_ERANGE; + + /* Got valid collation sequence values, add them as a new entry. + However, for !glibc we have no collation elements: if the + character set is single byte, the single byte character set + that we build below suffices. parse_bracket_exp passes + no MBCSET if dfa->mb_cur_max == 1. */ + if (mbcset) + { + /* Check the space of the arrays. */ + if (BE (*range_alloc == mbcset->nranges, 0)) + { + /* There is not enough space, need realloc. */ + wchar_t *new_array_start, *new_array_end; + int new_nranges; + + /* +1 in case of mbcset->nranges is 0. */ + new_nranges = 2 * mbcset->nranges + 1; + /* Use realloc since mbcset->range_starts and mbcset->range_ends + are NULL if *range_alloc == 0. */ + new_array_start = re_realloc (mbcset->range_starts, wchar_t, + new_nranges); + new_array_end = re_realloc (mbcset->range_ends, wchar_t, + new_nranges); + + if (BE (new_array_start == NULL || new_array_end == NULL, 0)) + return REG_ESPACE; + + mbcset->range_starts = new_array_start; + mbcset->range_ends = new_array_end; + *range_alloc = new_nranges; + } + + mbcset->range_starts[mbcset->nranges] = start_wc; + mbcset->range_ends[mbcset->nranges++] = end_wc; + } + + /* Build the table for single byte characters. */ + for (wc = 0; wc < SBC_MAX; ++wc) + { + cmp_buf[2] = wc; + if (wcscoll (cmp_buf, cmp_buf + 2) <= 0 + && wcscoll (cmp_buf + 2, cmp_buf + 4) <= 0) + bitset_set (sbcset, wc); + } + } +# else /* not RE_ENABLE_I18N */ + { + unsigned int ch; + start_ch = ((start_elem->type == SB_CHAR ) ? start_elem->opr.ch + : ((start_elem->type == COLL_SYM) ? start_elem->opr.name[0] + : 0)); + end_ch = ((end_elem->type == SB_CHAR ) ? end_elem->opr.ch + : ((end_elem->type == COLL_SYM) ? end_elem->opr.name[0] + : 0)); + if (start_ch > end_ch) + return REG_ERANGE; + /* Build the table for single byte characters. */ + for (ch = 0; ch < SBC_MAX; ++ch) + if (start_ch <= ch && ch <= end_ch) + bitset_set (sbcset, ch); + } +# endif /* not RE_ENABLE_I18N */ + return REG_NOERROR; +} +#endif + +#if 1 +/* Helper function for parse_bracket_exp only used in case of NOT glibc. + Build the collating element which is represented by NAME. + The result are written to MBCSET and SBCSET. + COLL_SYM_ALLOC is the allocated size of mbcset->coll_sym, is a + pointer argument since we may update it. */ + +static reg_errcode_t +internal_function +# ifdef RE_ENABLE_I18N +build_collating_symbol (bitset_t sbcset, re_charset_t *mbcset, + int *coll_sym_alloc, const unsigned char *name) +# else +build_collating_symbol (bitset_t sbcset, const unsigned char *name) +# endif +{ + size_t name_len = strlen ((const char *) name); + if (BE (name_len != 1, 0)) + return REG_ECOLLATE; + bitset_set (sbcset, name[0]); + return REG_NOERROR; +} +#endif + +/* This function parse bracket expression like "[abc]", "[a-c]", + "[[.a-a.]]" etc. */ + +static bin_tree_t * +parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token, + reg_syntax_t syntax, reg_errcode_t *err) +{ +#if 0 + const unsigned char *collseqmb; + const char *collseqwc; + uint32_t nrules; + int32_t table_size; + const int32_t *symb_table; + const unsigned char *extra; + + /* Local function for parse_bracket_exp used in glibc. + Seek the collating symbol entry correspondings to NAME. + Return the index of the symbol in the SYMB_TABLE. */ + + auto __inline__ int32_t + __attribute ((always_inline)) + seek_collating_symbol_entry (const unsigned char *name, size_t name_len) + { + int32_t hash = elem_hash ((const char *) name, name_len); + int32_t elem = hash % table_size; + if (symb_table[2 * elem] != 0) + { + int32_t second = hash % (table_size - 2) + 1; + + do + { + /* First compare the hashing value. */ + if (symb_table[2 * elem] == hash + /* Compare the length of the name. */ + && name_len == extra[symb_table[2 * elem + 1]] + /* Compare the name. */ + && memcmp (name, &extra[symb_table[2 * elem + 1] + 1], + name_len) == 0) + { + /* Yep, this is the entry. */ + break; + } + + /* Next entry. */ + elem += second; + } + while (symb_table[2 * elem] != 0); + } + return elem; + } + + /* Local function for parse_bracket_exp used in glibc. + Look up the collation sequence value of BR_ELEM. + Return the value if succeeded, UINT_MAX otherwise. */ + + auto __inline__ unsigned int + __attribute ((always_inline)) + lookup_collation_sequence_value (bracket_elem_t *br_elem) + { + if (br_elem->type == SB_CHAR) + { + /* + if (MB_CUR_MAX == 1) + */ + if (nrules == 0) + return collseqmb[br_elem->opr.ch]; + else + { + wint_t wc = __btowc (br_elem->opr.ch); + return __collseq_table_lookup (collseqwc, wc); + } + } + else if (br_elem->type == MB_CHAR) + { + return __collseq_table_lookup (collseqwc, br_elem->opr.wch); + } + else if (br_elem->type == COLL_SYM) + { + size_t sym_name_len = strlen ((char *) br_elem->opr.name); + if (nrules != 0) + { + int32_t elem, idx; + elem = seek_collating_symbol_entry (br_elem->opr.name, + sym_name_len); + if (symb_table[2 * elem] != 0) + { + /* We found the entry. */ + idx = symb_table[2 * elem + 1]; + /* Skip the name of collating element name. */ + idx += 1 + extra[idx]; + /* Skip the byte sequence of the collating element. */ + idx += 1 + extra[idx]; + /* Adjust for the alignment. */ + idx = (idx + 3) & ~3; + /* Skip the multibyte collation sequence value. */ + idx += sizeof (unsigned int); + /* Skip the wide char sequence of the collating element. */ + idx += sizeof (unsigned int) * + (1 + *(unsigned int *) (extra + idx)); + /* Return the collation sequence value. */ + return *(unsigned int *) (extra + idx); + } + else if (symb_table[2 * elem] == 0 && sym_name_len == 1) + { + /* No valid character. Match it as a single byte + character. */ + return collseqmb[br_elem->opr.name[0]]; + } + } + else if (sym_name_len == 1) + return collseqmb[br_elem->opr.name[0]]; + } + return UINT_MAX; + } + + /* Local function for parse_bracket_exp used in glibc. + Build the range expression which starts from START_ELEM, and ends + at END_ELEM. The result are written to MBCSET and SBCSET. + RANGE_ALLOC is the allocated size of mbcset->range_starts, and + mbcset->range_ends, is a pointer argument sinse we may + update it. */ + + auto __inline__ reg_errcode_t + __attribute ((always_inline)) + build_range_exp (re_charset_t *mbcset, + int *range_alloc, + bitset_t sbcset, + bracket_elem_t *start_elem, + bracket_elem_t *end_elem) + { + unsigned int ch; + uint32_t start_collseq; + uint32_t end_collseq; + + /* Equivalence Classes and Character Classes can't be a range + start/end. */ + if (BE (start_elem->type == EQUIV_CLASS || start_elem->type == CHAR_CLASS + || end_elem->type == EQUIV_CLASS || end_elem->type == CHAR_CLASS, + 0)) + return REG_ERANGE; + + start_collseq = lookup_collation_sequence_value (start_elem); + end_collseq = lookup_collation_sequence_value (end_elem); + /* Check start/end collation sequence values. */ + if (BE (start_collseq == UINT_MAX || end_collseq == UINT_MAX, 0)) + return REG_ECOLLATE; + if (BE ((syntax & RE_NO_EMPTY_RANGES) && start_collseq > end_collseq, 0)) + return REG_ERANGE; + + /* Got valid collation sequence values, add them as a new entry. + However, if we have no collation elements, and the character set + is single byte, the single byte character set that we + build below suffices. */ + if (nrules > 0 || dfa->mb_cur_max > 1) + { + /* Check the space of the arrays. */ + if (BE (*range_alloc == mbcset->nranges, 0)) + { + /* There is not enough space, need realloc. */ + uint32_t *new_array_start; + uint32_t *new_array_end; + int new_nranges; + + /* +1 in case of mbcset->nranges is 0. */ + new_nranges = 2 * mbcset->nranges + 1; + new_array_start = re_realloc (mbcset->range_starts, uint32_t, + new_nranges); + new_array_end = re_realloc (mbcset->range_ends, uint32_t, + new_nranges); + + if (BE (new_array_start == NULL || new_array_end == NULL, 0)) + return REG_ESPACE; + + mbcset->range_starts = new_array_start; + mbcset->range_ends = new_array_end; + *range_alloc = new_nranges; + } + + mbcset->range_starts[mbcset->nranges] = start_collseq; + mbcset->range_ends[mbcset->nranges++] = end_collseq; + } + + /* Build the table for single byte characters. */ + for (ch = 0; ch < SBC_MAX; ch++) + { + uint32_t ch_collseq; + /* + if (MB_CUR_MAX == 1) + */ + if (nrules == 0) + ch_collseq = collseqmb[ch]; + else + ch_collseq = __collseq_table_lookup (collseqwc, __btowc (ch)); + if (start_collseq <= ch_collseq && ch_collseq <= end_collseq) + bitset_set (sbcset, ch); + } + return REG_NOERROR; + } + + /* Local function for parse_bracket_exp used in glibc. + Build the collating element which is represented by NAME. + The result are written to MBCSET and SBCSET. + COLL_SYM_ALLOC is the allocated size of mbcset->coll_sym, is a + pointer argument sinse we may update it. */ + + auto __inline__ reg_errcode_t + __attribute ((always_inline)) + build_collating_symbol (re_charset_t *mbcset, + int *coll_sym_alloc, + bitset_t sbcset, + const unsigned char *name) + { + int32_t elem, idx; + size_t name_len = strlen ((const char *) name); + if (nrules != 0) + { + elem = seek_collating_symbol_entry (name, name_len); + if (symb_table[2 * elem] != 0) + { + /* We found the entry. */ + idx = symb_table[2 * elem + 1]; + /* Skip the name of collating element name. */ + idx += 1 + extra[idx]; + } + else if (symb_table[2 * elem] == 0 && name_len == 1) + { + /* No valid character, treat it as a normal + character. */ + bitset_set (sbcset, name[0]); + return REG_NOERROR; + } + else + return REG_ECOLLATE; + + /* Got valid collation sequence, add it as a new entry. */ + /* Check the space of the arrays. */ + if (BE (*coll_sym_alloc == mbcset->ncoll_syms, 0)) + { + /* Not enough, realloc it. */ + /* +1 in case of mbcset->ncoll_syms is 0. */ + int new_coll_sym_alloc = 2 * mbcset->ncoll_syms + 1; + /* Use realloc since mbcset->coll_syms is NULL + if *alloc == 0. */ + int32_t *new_coll_syms = re_realloc (mbcset->coll_syms, int32_t, + new_coll_sym_alloc); + if (BE (new_coll_syms == NULL, 0)) + return REG_ESPACE; + mbcset->coll_syms = new_coll_syms; + *coll_sym_alloc = new_coll_sym_alloc; + } + mbcset->coll_syms[mbcset->ncoll_syms++] = idx; + return REG_NOERROR; + } + else + { + if (BE (name_len != 1, 0)) + return REG_ECOLLATE; + else + { + bitset_set (sbcset, name[0]); + return REG_NOERROR; + } + } + } +#endif + + re_token_t br_token; + re_bitset_ptr_t sbcset; +#ifdef RE_ENABLE_I18N + re_charset_t *mbcset; + int coll_sym_alloc = 0, range_alloc = 0, mbchar_alloc = 0; + int equiv_class_alloc = 0, char_class_alloc = 0; +#endif + int non_match = 0; + bin_tree_t *work_tree; + int token_len; + int first_round = 1; +#if 0 + collseqmb = (const unsigned char *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQMB); + nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); + if (nrules) + { + /* + if (MB_CUR_MAX > 1) + */ + collseqwc = _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQWC); + table_size = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_SYMB_HASH_SIZEMB); + symb_table = (const int32_t *) _NL_CURRENT (LC_COLLATE, + _NL_COLLATE_SYMB_TABLEMB); + extra = (const unsigned char *) _NL_CURRENT (LC_COLLATE, + _NL_COLLATE_SYMB_EXTRAMB); + } +#endif + sbcset = calloc (sizeof (bitset_t), 1); +#ifdef RE_ENABLE_I18N + mbcset = calloc (sizeof (re_charset_t), 1); +#endif +#ifdef RE_ENABLE_I18N + if (BE (sbcset == NULL || mbcset == NULL, 0)) +#else + if (BE (sbcset == NULL, 0)) +#endif + { + *err = REG_ESPACE; + return NULL; + } + + token_len = peek_token_bracket (token, regexp, syntax); + if (BE (token->type == END_OF_RE, 0)) + { + *err = REG_BADPAT; + goto parse_bracket_exp_free_return; + } + if (token->type == OP_NON_MATCH_LIST) + { +#ifdef RE_ENABLE_I18N + mbcset->non_match = 1; +#endif + non_match = 1; + if (syntax & RE_HAT_LISTS_NOT_NEWLINE) + bitset_set (sbcset, '\0'); + re_string_skip_bytes (regexp, token_len); /* Skip a token. */ + token_len = peek_token_bracket (token, regexp, syntax); + if (BE (token->type == END_OF_RE, 0)) + { + *err = REG_BADPAT; + goto parse_bracket_exp_free_return; + } + } + + /* We treat the first ']' as a normal character. */ + if (token->type == OP_CLOSE_BRACKET) + token->type = CHARACTER; + + while (1) + { + bracket_elem_t start_elem, end_elem; + unsigned char start_name_buf[BRACKET_NAME_BUF_SIZE]; + unsigned char end_name_buf[BRACKET_NAME_BUF_SIZE]; + reg_errcode_t ret; + int token_len2 = 0, is_range_exp = 0; + re_token_t token2; + + start_elem.opr.name = start_name_buf; + ret = parse_bracket_element (&start_elem, regexp, token, token_len, dfa, + syntax, first_round); + if (BE (ret != REG_NOERROR, 0)) + { + *err = ret; + goto parse_bracket_exp_free_return; + } + first_round = 0; + + /* Get information about the next token. We need it in any case. */ + token_len = peek_token_bracket (token, regexp, syntax); + + /* Do not check for ranges if we know they are not allowed. */ + if (start_elem.type != CHAR_CLASS && start_elem.type != EQUIV_CLASS) + { + if (BE (token->type == END_OF_RE, 0)) + { + *err = REG_EBRACK; + goto parse_bracket_exp_free_return; + } + if (token->type == OP_CHARSET_RANGE) + { + re_string_skip_bytes (regexp, token_len); /* Skip '-'. */ + token_len2 = peek_token_bracket (&token2, regexp, syntax); + if (BE (token2.type == END_OF_RE, 0)) + { + *err = REG_EBRACK; + goto parse_bracket_exp_free_return; + } + if (token2.type == OP_CLOSE_BRACKET) + { + /* We treat the last '-' as a normal character. */ + re_string_skip_bytes (regexp, -token_len); + token->type = CHARACTER; + } + else + is_range_exp = 1; + } + } + + if (is_range_exp == 1) + { + end_elem.opr.name = end_name_buf; + ret = parse_bracket_element (&end_elem, regexp, &token2, token_len2, + dfa, syntax, 1); + if (BE (ret != REG_NOERROR, 0)) + { + *err = ret; + goto parse_bracket_exp_free_return; + } + + token_len = peek_token_bracket (token, regexp, syntax); + +#if 0 + *err = build_range_exp (sbcset, mbcset, &range_alloc, + &start_elem, &end_elem); +#else +# ifdef RE_ENABLE_I18N + *err = build_range_exp (sbcset, + dfa->mb_cur_max > 1 ? mbcset : NULL, + &range_alloc, &start_elem, &end_elem); +# else + *err = build_range_exp (sbcset, &start_elem, &end_elem); +# endif +#endif + if (BE (*err != REG_NOERROR, 0)) + goto parse_bracket_exp_free_return; + } + else + { + switch (start_elem.type) + { + case SB_CHAR: + bitset_set (sbcset, start_elem.opr.ch); + break; +#ifdef RE_ENABLE_I18N + case MB_CHAR: + /* Check whether the array has enough space. */ + if (BE (mbchar_alloc == mbcset->nmbchars, 0)) + { + wchar_t *new_mbchars; + /* Not enough, realloc it. */ + /* +1 in case of mbcset->nmbchars is 0. */ + mbchar_alloc = 2 * mbcset->nmbchars + 1; + /* Use realloc since array is NULL if *alloc == 0. */ + new_mbchars = re_realloc (mbcset->mbchars, wchar_t, + mbchar_alloc); + if (BE (new_mbchars == NULL, 0)) + goto parse_bracket_exp_espace; + mbcset->mbchars = new_mbchars; + } + mbcset->mbchars[mbcset->nmbchars++] = start_elem.opr.wch; + break; +#endif /* RE_ENABLE_I18N */ + case EQUIV_CLASS: + *err = build_equiv_class (sbcset, +#ifdef RE_ENABLE_I18N + mbcset, &equiv_class_alloc, +#endif + start_elem.opr.name); + if (BE (*err != REG_NOERROR, 0)) + goto parse_bracket_exp_free_return; + break; + case COLL_SYM: + *err = build_collating_symbol (sbcset, +#ifdef RE_ENABLE_I18N + mbcset, &coll_sym_alloc, +#endif + start_elem.opr.name); + if (BE (*err != REG_NOERROR, 0)) + goto parse_bracket_exp_free_return; + break; + case CHAR_CLASS: + *err = build_charclass (regexp->trans, sbcset, +#ifdef RE_ENABLE_I18N + mbcset, &char_class_alloc, +#endif + start_elem.opr.name, syntax); + if (BE (*err != REG_NOERROR, 0)) + goto parse_bracket_exp_free_return; + break; + default: + assert (0); + break; + } + } + if (BE (token->type == END_OF_RE, 0)) + { + *err = REG_EBRACK; + goto parse_bracket_exp_free_return; + } + if (token->type == OP_CLOSE_BRACKET) + break; + } + + re_string_skip_bytes (regexp, token_len); /* Skip a token. */ + + /* If it is non-matching list. */ + if (non_match) + bitset_not (sbcset); + +#ifdef RE_ENABLE_I18N + /* Ensure only single byte characters are set. */ + if (dfa->mb_cur_max > 1) + bitset_mask (sbcset, dfa->sb_char); + + if (mbcset->nmbchars || mbcset->ncoll_syms || mbcset->nequiv_classes + || mbcset->nranges || (dfa->mb_cur_max > 1 && (mbcset->nchar_classes + || mbcset->non_match))) + { + bin_tree_t *mbc_tree; + int sbc_idx; + /* Build a tree for complex bracket. */ + dfa->has_mb_node = 1; + br_token.type = COMPLEX_BRACKET; + br_token.opr.mbcset = mbcset; + mbc_tree = create_token_tree (dfa, NULL, NULL, &br_token); + if (BE (mbc_tree == NULL, 0)) + goto parse_bracket_exp_espace; + for (sbc_idx = 0; sbc_idx < BITSET_WORDS; ++sbc_idx) + if (sbcset[sbc_idx]) + break; + /* If there are no bits set in sbcset, there is no point + of having both SIMPLE_BRACKET and COMPLEX_BRACKET. */ + if (sbc_idx < BITSET_WORDS) + { + /* Build a tree for simple bracket. */ + br_token.type = SIMPLE_BRACKET; + br_token.opr.sbcset = sbcset; + work_tree = create_token_tree (dfa, NULL, NULL, &br_token); + if (BE (work_tree == NULL, 0)) + goto parse_bracket_exp_espace; + + /* Then join them by ALT node. */ + work_tree = create_tree (dfa, work_tree, mbc_tree, OP_ALT); + if (BE (work_tree == NULL, 0)) + goto parse_bracket_exp_espace; + } + else + { + re_free (sbcset); + work_tree = mbc_tree; + } + } + else +#endif /* not RE_ENABLE_I18N */ + { +#ifdef RE_ENABLE_I18N + free_charset (mbcset); +#endif + /* Build a tree for simple bracket. */ + br_token.type = SIMPLE_BRACKET; + br_token.opr.sbcset = sbcset; + work_tree = create_token_tree (dfa, NULL, NULL, &br_token); + if (BE (work_tree == NULL, 0)) + goto parse_bracket_exp_espace; + } + return work_tree; + + parse_bracket_exp_espace: + *err = REG_ESPACE; + parse_bracket_exp_free_return: + re_free (sbcset); +#ifdef RE_ENABLE_I18N + free_charset (mbcset); +#endif + return NULL; +} + +/* Parse an element in the bracket expression. */ + +static reg_errcode_t +parse_bracket_element (bracket_elem_t *elem, re_string_t *regexp, + re_token_t *token, int token_len, re_dfa_t *dfa, + reg_syntax_t syntax, int accept_hyphen) +{ +#ifdef RE_ENABLE_I18N + int cur_char_size; + cur_char_size = re_string_char_size_at (regexp, re_string_cur_idx (regexp)); + if (cur_char_size > 1) + { + elem->type = MB_CHAR; + elem->opr.wch = re_string_wchar_at (regexp, re_string_cur_idx (regexp)); + re_string_skip_bytes (regexp, cur_char_size); + return REG_NOERROR; + } +#endif /* RE_ENABLE_I18N */ + re_string_skip_bytes (regexp, token_len); /* Skip a token. */ + if (token->type == OP_OPEN_COLL_ELEM || token->type == OP_OPEN_CHAR_CLASS + || token->type == OP_OPEN_EQUIV_CLASS) + return parse_bracket_symbol (elem, regexp, token); + if (BE (token->type == OP_CHARSET_RANGE, 0) && !accept_hyphen) + { + /* A '-' must only appear as anything but a range indicator before + the closing bracket. Everything else is an error. */ + re_token_t token2; + (void) peek_token_bracket (&token2, regexp, syntax); + if (token2.type != OP_CLOSE_BRACKET) + /* The actual error value is not standardized since this whole + case is undefined. But ERANGE makes good sense. */ + return REG_ERANGE; + } + elem->type = SB_CHAR; + elem->opr.ch = token->opr.c; + return REG_NOERROR; +} + +/* Parse a bracket symbol in the bracket expression. Bracket symbols are + such as [::], [..], and + [==]. */ + +static reg_errcode_t +parse_bracket_symbol (bracket_elem_t *elem, re_string_t *regexp, + re_token_t *token) +{ + unsigned char ch, delim = token->opr.c; + int i = 0; + if (re_string_eoi(regexp)) + return REG_EBRACK; + for (;; ++i) + { + if (i >= BRACKET_NAME_BUF_SIZE) + return REG_EBRACK; + if (token->type == OP_OPEN_CHAR_CLASS) + ch = re_string_fetch_byte_case (regexp); + else + ch = re_string_fetch_byte (regexp); + if (re_string_eoi(regexp)) + return REG_EBRACK; + if (ch == delim && re_string_peek_byte (regexp, 0) == ']') + break; + elem->opr.name[i] = ch; + } + re_string_skip_bytes (regexp, 1); + elem->opr.name[i] = '\0'; + switch (token->type) + { + case OP_OPEN_COLL_ELEM: + elem->type = COLL_SYM; + break; + case OP_OPEN_EQUIV_CLASS: + elem->type = EQUIV_CLASS; + break; + case OP_OPEN_CHAR_CLASS: + elem->type = CHAR_CLASS; + break; + default: + break; + } + return REG_NOERROR; +} + + /* Helper function for parse_bracket_exp. + Build the equivalence class which is represented by NAME. + The result are written to MBCSET and SBCSET. + EQUIV_CLASS_ALLOC is the allocated size of mbcset->equiv_classes, + is a pointer argument sinse we may update it. */ + +static reg_errcode_t +#ifdef RE_ENABLE_I18N +build_equiv_class (bitset_t sbcset, re_charset_t *mbcset, + int *equiv_class_alloc, const unsigned char *name) +#else +build_equiv_class (bitset_t sbcset, const unsigned char *name) +#endif +{ +#if 0 + uint32_t nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); + if (nrules != 0) + { + const int32_t *table, *indirect; + const unsigned char *weights, *extra, *cp; + unsigned char char_buf[2]; + int32_t idx1, idx2; + unsigned int ch; + size_t len; + /* This #include defines a local function! */ +# include + /* Calculate the index for equivalence class. */ + cp = name; + table = (const int32_t *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB); + weights = (const unsigned char *) _NL_CURRENT (LC_COLLATE, + _NL_COLLATE_WEIGHTMB); + extra = (const unsigned char *) _NL_CURRENT (LC_COLLATE, + _NL_COLLATE_EXTRAMB); + indirect = (const int32_t *) _NL_CURRENT (LC_COLLATE, + _NL_COLLATE_INDIRECTMB); + idx1 = findidx (&cp); + if (BE (idx1 == 0 || cp < name + strlen ((const char *) name), 0)) + /* This isn't a valid character. */ + return REG_ECOLLATE; + + /* Build single byte matcing table for this equivalence class. */ + char_buf[1] = (unsigned char) '\0'; + len = weights[idx1]; + for (ch = 0; ch < SBC_MAX; ++ch) + { + char_buf[0] = ch; + cp = char_buf; + idx2 = findidx (&cp); +/* + idx2 = table[ch]; +*/ + if (idx2 == 0) + /* This isn't a valid character. */ + continue; + if (len == weights[idx2]) + { + int cnt = 0; + while (cnt <= len && + weights[idx1 + 1 + cnt] == weights[idx2 + 1 + cnt]) + ++cnt; + + if (cnt > len) + bitset_set (sbcset, ch); + } + } + /* Check whether the array has enough space. */ + if (BE (*equiv_class_alloc == mbcset->nequiv_classes, 0)) + { + /* Not enough, realloc it. */ + /* +1 in case of mbcset->nequiv_classes is 0. */ + int new_equiv_class_alloc = 2 * mbcset->nequiv_classes + 1; + /* Use realloc since the array is NULL if *alloc == 0. */ + int32_t *new_equiv_classes = re_realloc (mbcset->equiv_classes, + int32_t, + new_equiv_class_alloc); + if (BE (new_equiv_classes == NULL, 0)) + return REG_ESPACE; + mbcset->equiv_classes = new_equiv_classes; + *equiv_class_alloc = new_equiv_class_alloc; + } + mbcset->equiv_classes[mbcset->nequiv_classes++] = idx1; + } + else +#endif + { + if (BE (strlen ((const char *) name) != 1, 0)) + return REG_ECOLLATE; + bitset_set (sbcset, *name); + } + return REG_NOERROR; +} + + /* Helper function for parse_bracket_exp. + Build the character class which is represented by NAME. + The result are written to MBCSET and SBCSET. + CHAR_CLASS_ALLOC is the allocated size of mbcset->char_classes, + is a pointer argument sinse we may update it. */ + +static reg_errcode_t +#ifdef RE_ENABLE_I18N +build_charclass (RE_TRANSLATE_TYPE trans, bitset_t sbcset, + re_charset_t *mbcset, int *char_class_alloc, + const unsigned char *class_name, reg_syntax_t syntax) +#else +build_charclass (RE_TRANSLATE_TYPE trans, bitset_t sbcset, + const unsigned char *class_name, reg_syntax_t syntax) +#endif +{ + int i; + const char *name = (const char *) class_name; + + /* In case of REG_ICASE "upper" and "lower" match the both of + upper and lower cases. */ + if ((syntax & RE_ICASE) + && (strcmp (name, "upper") == 0 || strcmp (name, "lower") == 0)) + name = "alpha"; + +#ifdef RE_ENABLE_I18N + /* Check the space of the arrays. */ + if (BE (*char_class_alloc == mbcset->nchar_classes, 0)) + { + /* Not enough, realloc it. */ + /* +1 in case of mbcset->nchar_classes is 0. */ + int new_char_class_alloc = 2 * mbcset->nchar_classes + 1; + /* Use realloc since array is NULL if *alloc == 0. */ + wctype_t *new_char_classes = re_realloc (mbcset->char_classes, wctype_t, + new_char_class_alloc); + if (BE (new_char_classes == NULL, 0)) + return REG_ESPACE; + mbcset->char_classes = new_char_classes; + *char_class_alloc = new_char_class_alloc; + } + mbcset->char_classes[mbcset->nchar_classes++] = __wctype (name); +#endif /* RE_ENABLE_I18N */ + +#define BUILD_CHARCLASS_LOOP(ctype_func) \ + do { \ + if (BE (trans != NULL, 0)) \ + { \ + for (i = 0; i < SBC_MAX; ++i) \ + if (ctype_func (i)) \ + bitset_set (sbcset, trans[i]); \ + } \ + else \ + { \ + for (i = 0; i < SBC_MAX; ++i) \ + if (ctype_func (i)) \ + bitset_set (sbcset, i); \ + } \ + } while (0) + + if (strcmp (name, "alnum") == 0) + BUILD_CHARCLASS_LOOP (isalnum); + else if (strcmp (name, "cntrl") == 0) + BUILD_CHARCLASS_LOOP (iscntrl); + else if (strcmp (name, "lower") == 0) + BUILD_CHARCLASS_LOOP (islower); + else if (strcmp (name, "space") == 0) + BUILD_CHARCLASS_LOOP (isspace); + else if (strcmp (name, "alpha") == 0) + BUILD_CHARCLASS_LOOP (isalpha); + else if (strcmp (name, "digit") == 0) + BUILD_CHARCLASS_LOOP (isdigit); + else if (strcmp (name, "print") == 0) + BUILD_CHARCLASS_LOOP (isprint); + else if (strcmp (name, "upper") == 0) + BUILD_CHARCLASS_LOOP (isupper); + else if (strcmp (name, "blank") == 0) + BUILD_CHARCLASS_LOOP (isblank); + else if (strcmp (name, "graph") == 0) + BUILD_CHARCLASS_LOOP (isgraph); + else if (strcmp (name, "punct") == 0) + BUILD_CHARCLASS_LOOP (ispunct); + else if (strcmp (name, "xdigit") == 0) + BUILD_CHARCLASS_LOOP (isxdigit); + else + return REG_ECTYPE; + + return REG_NOERROR; +} + +static bin_tree_t * +build_charclass_op (re_dfa_t *dfa, RE_TRANSLATE_TYPE trans, + const unsigned char *class_name, + const unsigned char *extra, int non_match, + reg_errcode_t *err) +{ + re_bitset_ptr_t sbcset; +#ifdef RE_ENABLE_I18N + re_charset_t *mbcset; + int alloc = 0; +#endif + reg_errcode_t ret; + re_token_t br_token; + bin_tree_t *tree; + + sbcset = calloc (sizeof (bitset_t), 1); +#ifdef RE_ENABLE_I18N + mbcset = calloc (sizeof (re_charset_t), 1); +#endif + +#ifdef RE_ENABLE_I18N + if (BE (sbcset == NULL || mbcset == NULL, 0)) +#else + if (BE (sbcset == NULL, 0)) +#endif + { + *err = REG_ESPACE; + return NULL; + } + + if (non_match) + { +#ifdef RE_ENABLE_I18N + /* + if (syntax & RE_HAT_LISTS_NOT_NEWLINE) + bitset_set(cset->sbcset, '\0'); + */ + mbcset->non_match = 1; +#endif + } + + /* We don't care the syntax in this case. */ + ret = build_charclass (trans, sbcset, +#ifdef RE_ENABLE_I18N + mbcset, &alloc, +#endif + class_name, 0); + + if (BE (ret != REG_NOERROR, 0)) + { + re_free (sbcset); +#ifdef RE_ENABLE_I18N + free_charset (mbcset); +#endif + *err = ret; + return NULL; + } + /* \w match '_' also. */ + for (; *extra; extra++) + bitset_set (sbcset, *extra); + + /* If it is non-matching list. */ + if (non_match) + bitset_not (sbcset); + +#ifdef RE_ENABLE_I18N + /* Ensure only single byte characters are set. */ + if (dfa->mb_cur_max > 1) + bitset_mask (sbcset, dfa->sb_char); +#endif + + /* Build a tree for simple bracket. */ + br_token.type = SIMPLE_BRACKET; + br_token.opr.sbcset = sbcset; + tree = create_token_tree (dfa, NULL, NULL, &br_token); + if (BE (tree == NULL, 0)) + goto build_word_op_espace; + +#ifdef RE_ENABLE_I18N + if (dfa->mb_cur_max > 1) + { + bin_tree_t *mbc_tree; + /* Build a tree for complex bracket. */ + br_token.type = COMPLEX_BRACKET; + br_token.opr.mbcset = mbcset; + dfa->has_mb_node = 1; + mbc_tree = create_token_tree (dfa, NULL, NULL, &br_token); + if (BE (mbc_tree == NULL, 0)) + goto build_word_op_espace; + /* Then join them by ALT node. */ + tree = create_tree (dfa, tree, mbc_tree, OP_ALT); + if (BE (mbc_tree != NULL, 1)) + return tree; + } + else + { + free_charset (mbcset); + return tree; + } +#else /* not RE_ENABLE_I18N */ + return tree; +#endif + + build_word_op_espace: + re_free (sbcset); +#ifdef RE_ENABLE_I18N + free_charset (mbcset); +#endif + *err = REG_ESPACE; + return NULL; +} + +/* This is intended for the expressions like "a{1,3}". + Fetch a number from `input', and return the number. + Return -1, if the number field is empty like "{,1}". + Return -2, If an error is occured. */ + +static int +fetch_number (re_string_t *input, re_token_t *token, reg_syntax_t syntax) +{ + int num = -1; + unsigned char c; + while (1) + { + fetch_token (token, input, syntax); + c = token->opr.c; + if (BE (token->type == END_OF_RE, 0)) + return -2; + if (token->type == OP_CLOSE_DUP_NUM || c == ',') + break; + num = ((token->type != CHARACTER || c < '0' || '9' < c || num == -2) + ? -2 : ((num == -1) ? c - '0' : num * 10 + c - '0')); + num = (num > RE_DUP_MAX) ? -2 : num; + } + return num; +} + +#ifdef RE_ENABLE_I18N +static void +free_charset (re_charset_t *cset) +{ + re_free (cset->mbchars); +# if 0 + re_free (cset->coll_syms); + re_free (cset->equiv_classes); + re_free (cset->range_starts); + re_free (cset->range_ends); +# endif + re_free (cset->char_classes); + re_free (cset); +} +#endif /* RE_ENABLE_I18N */ + +/* Functions for binary tree operation. */ + +/* Create a tree node. */ + +static bin_tree_t * +create_tree (re_dfa_t *dfa, bin_tree_t *left, bin_tree_t *right, + re_token_type_t type) +{ + re_token_t t; + t.type = type; + return create_token_tree (dfa, left, right, &t); +} + +static bin_tree_t * +create_token_tree (re_dfa_t *dfa, bin_tree_t *left, bin_tree_t *right, + const re_token_t *token) +{ + bin_tree_t *tree; + if (BE (dfa->str_tree_storage_idx == BIN_TREE_STORAGE_SIZE, 0)) + { + bin_tree_storage_t *storage = re_malloc (bin_tree_storage_t, 1); + + if (storage == NULL) + return NULL; + storage->next = dfa->str_tree_storage; + dfa->str_tree_storage = storage; + dfa->str_tree_storage_idx = 0; + } + tree = &dfa->str_tree_storage->data[dfa->str_tree_storage_idx++]; + + tree->parent = NULL; + tree->left = left; + tree->right = right; + tree->token = *token; + tree->token.duplicated = 0; + tree->token.opt_subexp = 0; + tree->first = NULL; + tree->next = NULL; + tree->node_idx = -1; + + if (left != NULL) + left->parent = tree; + if (right != NULL) + right->parent = tree; + return tree; +} + +/* Mark the tree SRC as an optional subexpression. + To be called from preorder or postorder. */ + +static reg_errcode_t +mark_opt_subexp (void *extra, bin_tree_t *node) +{ + int idx = (int) (long) extra; + if (node->token.type == SUBEXP && node->token.opr.idx == idx) + node->token.opt_subexp = 1; + + return REG_NOERROR; +} + +/* Free the allocated memory inside NODE. */ + +static void +free_token (re_token_t *node) +{ +#ifdef RE_ENABLE_I18N + if (node->type == COMPLEX_BRACKET && node->duplicated == 0) + free_charset (node->opr.mbcset); + else +#endif + if (node->type == SIMPLE_BRACKET && node->duplicated == 0) + re_free (node->opr.sbcset); +} + +/* Worker function for tree walking. Free the allocated memory inside NODE + and its children. */ + +static reg_errcode_t +free_tree (void *extra, bin_tree_t *node) +{ + free_token (&node->token); + return REG_NOERROR; +} + + +/* Duplicate the node SRC, and return new node. This is a preorder + visit similar to the one implemented by the generic visitor, but + we need more infrastructure to maintain two parallel trees --- so, + it's easier to duplicate. */ + +static bin_tree_t * +duplicate_tree (const bin_tree_t *root, re_dfa_t *dfa) +{ + const bin_tree_t *node; + bin_tree_t *dup_root; + bin_tree_t **p_new = &dup_root, *dup_node = root->parent; + + for (node = root; ; ) + { + /* Create a new tree and link it back to the current parent. */ + *p_new = create_token_tree (dfa, NULL, NULL, &node->token); + if (*p_new == NULL) + return NULL; + (*p_new)->parent = dup_node; + (*p_new)->token.duplicated = 1; + dup_node = *p_new; + + /* Go to the left node, or up and to the right. */ + if (node->left) + { + node = node->left; + p_new = &dup_node->left; + } + else + { + const bin_tree_t *prev = NULL; + while (node->right == prev || node->right == NULL) + { + prev = node; + node = node->parent; + dup_node = dup_node->parent; + if (!node) + return dup_root; + } + node = node->right; + p_new = &dup_node->right; + } + } +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/regex/regex.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/regex/regex.c new file mode 100644 index 00000000..fa46f635 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/regex/regex.c @@ -0,0 +1,58 @@ +/* Extended regular expression matching and search library. + Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Isamu Hasegawa . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#ifdef __UCLIBC__ +# define _REGEX_RE_COMP +# define HAVE_LANGINFO +# define HAVE_LANGINFO_CODESET +# include +# include +# include +# include +# ifdef __UCLIBC_HAS_WCHAR__ +# define RE_ENABLE_I18N +# include +# include +# define __iswctype iswctype +# define __wcrtomb wcrtomb +# define __btowc btowc +# define __wctype wctype +# endif +# include +#endif + +/* Make sure noone compiles this code with a C++ compiler. */ +#ifdef __cplusplus +# error "This is C code, use a C compiler" +#endif + +/* On some systems, limits.h sets RE_DUP_MAX to a lower value than + GNU regex allows. Include it before , which correctly + #undefs RE_DUP_MAX and sets it to the right value. */ +#include + +#include + +#include "regex_internal.h" +#include "regex_internal.c" +#include "regcomp.c" +#include "regexec.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/regex/regex_internal.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/regex/regex_internal.c new file mode 100644 index 00000000..de640e08 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/regex/regex_internal.c @@ -0,0 +1,1642 @@ +/* Extended regular expression matching and search library. + Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Isamu Hasegawa . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +static void re_string_construct_common (const char *str, int len, + re_string_t *pstr, + RE_TRANSLATE_TYPE trans, int icase, + const re_dfa_t *dfa) internal_function; +static re_dfastate_t *create_ci_newstate (const re_dfa_t *dfa, + const re_node_set *nodes, + unsigned int hash) internal_function; +static re_dfastate_t *create_cd_newstate (const re_dfa_t *dfa, + const re_node_set *nodes, + unsigned int context, + unsigned int hash) internal_function; + +/* Functions for string operation. */ + +/* This function allocate the buffers. It is necessary to call + re_string_reconstruct before using the object. */ + +static reg_errcode_t +internal_function +re_string_allocate (re_string_t *pstr, const char *str, int len, int init_len, + RE_TRANSLATE_TYPE trans, int icase, const re_dfa_t *dfa) +{ + reg_errcode_t ret; + int init_buf_len; + + /* Ensure at least one character fits into the buffers. */ + if (init_len < dfa->mb_cur_max) + init_len = dfa->mb_cur_max; + init_buf_len = (len + 1 < init_len) ? len + 1: init_len; + re_string_construct_common (str, len, pstr, trans, icase, dfa); + + ret = re_string_realloc_buffers (pstr, init_buf_len); + if (BE (ret != REG_NOERROR, 0)) + return ret; + + pstr->word_char = dfa->word_char; + pstr->word_ops_used = dfa->word_ops_used; + pstr->mbs = pstr->mbs_allocated ? pstr->mbs : (unsigned char *) str; + pstr->valid_len = (pstr->mbs_allocated || dfa->mb_cur_max > 1) ? 0 : len; + pstr->valid_raw_len = pstr->valid_len; + return REG_NOERROR; +} + +/* This function allocate the buffers, and initialize them. */ + +static reg_errcode_t +internal_function +re_string_construct (re_string_t *pstr, const char *str, int len, + RE_TRANSLATE_TYPE trans, int icase, const re_dfa_t *dfa) +{ + reg_errcode_t ret; + memset (pstr, '\0', sizeof (re_string_t)); + re_string_construct_common (str, len, pstr, trans, icase, dfa); + + if (len > 0) + { + ret = re_string_realloc_buffers (pstr, len + 1); + if (BE (ret != REG_NOERROR, 0)) + return ret; + } + pstr->mbs = pstr->mbs_allocated ? pstr->mbs : (unsigned char *) str; + + if (icase) + { +#ifdef RE_ENABLE_I18N + if (dfa->mb_cur_max > 1) + { + while (1) + { + ret = build_wcs_upper_buffer (pstr); + if (BE (ret != REG_NOERROR, 0)) + return ret; + if (pstr->valid_raw_len >= len) + break; + if (pstr->bufs_len > pstr->valid_len + dfa->mb_cur_max) + break; + ret = re_string_realloc_buffers (pstr, pstr->bufs_len * 2); + if (BE (ret != REG_NOERROR, 0)) + return ret; + } + } + else +#endif /* RE_ENABLE_I18N */ + build_upper_buffer (pstr); + } + else + { +#ifdef RE_ENABLE_I18N + if (dfa->mb_cur_max > 1) + build_wcs_buffer (pstr); + else +#endif + { + if (trans != NULL) + re_string_translate_buffer (pstr); + else + { + pstr->valid_len = pstr->bufs_len; + pstr->valid_raw_len = pstr->bufs_len; + } + } + } + + return REG_NOERROR; +} + +/* Helper functions for re_string_allocate, and re_string_construct. */ + +static reg_errcode_t +internal_function +re_string_realloc_buffers (re_string_t *pstr, int new_buf_len) +{ +#ifdef RE_ENABLE_I18N + if (pstr->mb_cur_max > 1) + { + wint_t *new_wcs = re_realloc (pstr->wcs, wint_t, new_buf_len); + if (BE (new_wcs == NULL, 0)) + return REG_ESPACE; + pstr->wcs = new_wcs; + if (pstr->offsets != NULL) + { + int *new_offsets = re_realloc (pstr->offsets, int, new_buf_len); + if (BE (new_offsets == NULL, 0)) + return REG_ESPACE; + pstr->offsets = new_offsets; + } + } +#endif /* RE_ENABLE_I18N */ + if (pstr->mbs_allocated) + { + unsigned char *new_mbs = re_realloc (pstr->mbs, unsigned char, + new_buf_len); + if (BE (new_mbs == NULL, 0)) + return REG_ESPACE; + pstr->mbs = new_mbs; + } + pstr->bufs_len = new_buf_len; + return REG_NOERROR; +} + + +static void +internal_function +re_string_construct_common (const char *str, int len, re_string_t *pstr, + RE_TRANSLATE_TYPE trans, int icase, + const re_dfa_t *dfa) +{ + pstr->raw_mbs = (const unsigned char *) str; + pstr->len = len; + pstr->raw_len = len; + pstr->trans = trans; + pstr->icase = icase ? 1 : 0; + pstr->mbs_allocated = (trans != NULL || icase); + pstr->mb_cur_max = dfa->mb_cur_max; + pstr->is_utf8 = dfa->is_utf8; + pstr->map_notascii = dfa->map_notascii; + pstr->stop = pstr->len; + pstr->raw_stop = pstr->stop; +} + +#ifdef RE_ENABLE_I18N + +/* Build wide character buffer PSTR->WCS. + If the byte sequence of the string are: + (0), (1), (0), (1), + Then wide character buffer will be: + , WEOF , , WEOF , + We use WEOF for padding, they indicate that the position isn't + a first byte of a multibyte character. + + Note that this function assumes PSTR->VALID_LEN elements are already + built and starts from PSTR->VALID_LEN. */ + +static void +internal_function +build_wcs_buffer (re_string_t *pstr) +{ +#if defined __UCLIBC__ + unsigned char buf[MB_LEN_MAX]; + assert (MB_LEN_MAX >= pstr->mb_cur_max); +#else + unsigned char buf[64]; +#endif + mbstate_t prev_st; + int byte_idx, end_idx, remain_len; + size_t mbclen; + + /* Build the buffers from pstr->valid_len to either pstr->len or + pstr->bufs_len. */ + end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len; + for (byte_idx = pstr->valid_len; byte_idx < end_idx;) + { + wchar_t wc; + const char *p; + + remain_len = end_idx - byte_idx; + prev_st = pstr->cur_state; + /* Apply the translation if we need. */ + if (BE (pstr->trans != NULL, 0)) + { + int i, ch; + + for (i = 0; i < pstr->mb_cur_max && i < remain_len; ++i) + { + ch = pstr->raw_mbs [pstr->raw_mbs_idx + byte_idx + i]; + buf[i] = pstr->mbs[byte_idx + i] = pstr->trans[ch]; + } + p = (const char *) buf; + } + else + p = (const char *) pstr->raw_mbs + pstr->raw_mbs_idx + byte_idx; + mbclen = mbrtowc (&wc, p, remain_len, &pstr->cur_state); + if (BE (mbclen == (size_t) -2, 0)) + { + /* The buffer doesn't have enough space, finish to build. */ + pstr->cur_state = prev_st; + break; + } + else if (BE (mbclen == (size_t) -1 || mbclen == 0, 0)) + { + /* We treat these cases as a singlebyte character. */ + mbclen = 1; + wc = (wchar_t) pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx]; + if (BE (pstr->trans != NULL, 0)) + wc = pstr->trans[wc]; + pstr->cur_state = prev_st; + } + + /* Write wide character and padding. */ + pstr->wcs[byte_idx++] = wc; + /* Write paddings. */ + for (remain_len = byte_idx + mbclen - 1; byte_idx < remain_len ;) + pstr->wcs[byte_idx++] = WEOF; + } + pstr->valid_len = byte_idx; + pstr->valid_raw_len = byte_idx; +} + +/* Build wide character buffer PSTR->WCS like build_wcs_buffer, + but for REG_ICASE. */ + +static reg_errcode_t +internal_function +build_wcs_upper_buffer (re_string_t *pstr) +{ + mbstate_t prev_st; + int src_idx, byte_idx, end_idx, remain_len; + size_t mbclen; +#if defined __UCLIBC__ + char buf[MB_LEN_MAX]; + assert (MB_LEN_MAX >= pstr->mb_cur_max); +#else + char buf[64]; +#endif + + byte_idx = pstr->valid_len; + end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len; + + /* The following optimization assumes that ASCII characters can be + mapped to wide characters with a simple cast. */ + if (! pstr->map_notascii && pstr->trans == NULL && !pstr->offsets_needed) + { + while (byte_idx < end_idx) + { + wchar_t wc; + + if (isascii (pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx]) + && mbsinit (&pstr->cur_state)) + { + /* In case of a singlebyte character. */ + pstr->mbs[byte_idx] + = toupper (pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx]); + /* The next step uses the assumption that wchar_t is encoded + ASCII-safe: all ASCII values can be converted like this. */ + pstr->wcs[byte_idx] = (wchar_t) pstr->mbs[byte_idx]; + ++byte_idx; + continue; + } + + remain_len = end_idx - byte_idx; + prev_st = pstr->cur_state; + mbclen = mbrtowc (&wc, + ((const char *) pstr->raw_mbs + pstr->raw_mbs_idx + + byte_idx), remain_len, &pstr->cur_state); + if (BE (mbclen + 2 > 2, 1)) + { + wchar_t wcu = wc; + if (iswlower (wc)) + { + size_t mbcdlen; + + wcu = towupper (wc); + mbcdlen = wcrtomb (buf, wcu, &prev_st); + if (BE (mbclen == mbcdlen, 1)) + memcpy (pstr->mbs + byte_idx, buf, mbclen); + else + { + src_idx = byte_idx; + goto offsets_needed; + } + } + else + memcpy (pstr->mbs + byte_idx, + pstr->raw_mbs + pstr->raw_mbs_idx + byte_idx, mbclen); + pstr->wcs[byte_idx++] = wcu; + /* Write paddings. */ + for (remain_len = byte_idx + mbclen - 1; byte_idx < remain_len ;) + pstr->wcs[byte_idx++] = WEOF; + } + else if (mbclen == (size_t) -1 || mbclen == 0) + { + /* It is an invalid character or '\0'. Just use the byte. */ + int ch = pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx]; + pstr->mbs[byte_idx] = ch; + /* And also cast it to wide char. */ + pstr->wcs[byte_idx++] = (wchar_t) ch; + if (BE (mbclen == (size_t) -1, 0)) + pstr->cur_state = prev_st; + } + else + { + /* The buffer doesn't have enough space, finish to build. */ + pstr->cur_state = prev_st; + break; + } + } + pstr->valid_len = byte_idx; + pstr->valid_raw_len = byte_idx; + return REG_NOERROR; + } + else + for (src_idx = pstr->valid_raw_len; byte_idx < end_idx;) + { + wchar_t wc; + const char *p; + offsets_needed: + remain_len = end_idx - byte_idx; + prev_st = pstr->cur_state; + if (BE (pstr->trans != NULL, 0)) + { + int i, ch; + + for (i = 0; i < pstr->mb_cur_max && i < remain_len; ++i) + { + ch = pstr->raw_mbs [pstr->raw_mbs_idx + src_idx + i]; + buf[i] = pstr->trans[ch]; + } + p = (const char *) buf; + } + else + p = (const char *) pstr->raw_mbs + pstr->raw_mbs_idx + src_idx; + mbclen = mbrtowc (&wc, p, remain_len, &pstr->cur_state); + if (BE (mbclen + 2 > 2, 1)) + { + wchar_t wcu = wc; + if (iswlower (wc)) + { + size_t mbcdlen; + + wcu = towupper (wc); + mbcdlen = wcrtomb ((char *) buf, wcu, &prev_st); + if (BE (mbclen == mbcdlen, 1)) + memcpy (pstr->mbs + byte_idx, buf, mbclen); + else if (mbcdlen != (size_t) -1) + { + size_t i; + + if (byte_idx + mbcdlen > pstr->bufs_len) + { + pstr->cur_state = prev_st; + break; + } + + if (pstr->offsets == NULL) + { + pstr->offsets = re_malloc (int, pstr->bufs_len); + + if (pstr->offsets == NULL) + return REG_ESPACE; + } + if (!pstr->offsets_needed) + { + for (i = 0; i < (size_t) byte_idx; ++i) + pstr->offsets[i] = i; + pstr->offsets_needed = 1; + } + + memcpy (pstr->mbs + byte_idx, buf, mbcdlen); + pstr->wcs[byte_idx] = wcu; + pstr->offsets[byte_idx] = src_idx; + for (i = 1; i < mbcdlen; ++i) + { + pstr->offsets[byte_idx + i] + = src_idx + (i < mbclen ? i : mbclen - 1); + pstr->wcs[byte_idx + i] = WEOF; + } + pstr->len += mbcdlen - mbclen; + if (pstr->raw_stop > src_idx) + pstr->stop += mbcdlen - mbclen; + end_idx = (pstr->bufs_len > pstr->len) + ? pstr->len : pstr->bufs_len; + byte_idx += mbcdlen; + src_idx += mbclen; + continue; + } + else + memcpy (pstr->mbs + byte_idx, p, mbclen); + } + else + memcpy (pstr->mbs + byte_idx, p, mbclen); + + if (BE (pstr->offsets_needed != 0, 0)) + { + size_t i; + for (i = 0; i < mbclen; ++i) + pstr->offsets[byte_idx + i] = src_idx + i; + } + src_idx += mbclen; + + pstr->wcs[byte_idx++] = wcu; + /* Write paddings. */ + for (remain_len = byte_idx + mbclen - 1; byte_idx < remain_len ;) + pstr->wcs[byte_idx++] = WEOF; + } + else if (mbclen == (size_t) -1 || mbclen == 0) + { + /* It is an invalid character or '\0'. Just use the byte. */ + int ch = pstr->raw_mbs[pstr->raw_mbs_idx + src_idx]; + + if (BE (pstr->trans != NULL, 0)) + ch = pstr->trans [ch]; + pstr->mbs[byte_idx] = ch; + + if (BE (pstr->offsets_needed != 0, 0)) + pstr->offsets[byte_idx] = src_idx; + ++src_idx; + + /* And also cast it to wide char. */ + pstr->wcs[byte_idx++] = (wchar_t) ch; + if (BE (mbclen == (size_t) -1, 0)) + pstr->cur_state = prev_st; + } + else + { + /* The buffer doesn't have enough space, finish to build. */ + pstr->cur_state = prev_st; + break; + } + } + pstr->valid_len = byte_idx; + pstr->valid_raw_len = src_idx; + return REG_NOERROR; +} + +/* Skip characters until the index becomes greater than NEW_RAW_IDX. + Return the index. */ + +static int +internal_function +re_string_skip_chars (re_string_t *pstr, int new_raw_idx, wint_t *last_wc) +{ + mbstate_t prev_st; + int rawbuf_idx; + size_t mbclen; + wchar_t wc = 0; + + /* Skip the characters which are not necessary to check. */ + for (rawbuf_idx = pstr->raw_mbs_idx + pstr->valid_raw_len; + rawbuf_idx < new_raw_idx;) + { + int remain_len; + remain_len = pstr->len - rawbuf_idx; + prev_st = pstr->cur_state; + mbclen = mbrtowc (&wc, (const char *) pstr->raw_mbs + rawbuf_idx, + remain_len, &pstr->cur_state); + if (BE (mbclen == (size_t) -2 || mbclen == (size_t) -1 || mbclen == 0, 0)) + { + /* We treat these cases as a singlebyte character. */ + mbclen = 1; + pstr->cur_state = prev_st; + } + /* Then proceed the next character. */ + rawbuf_idx += mbclen; + } + *last_wc = (wint_t) wc; + return rawbuf_idx; +} +#endif /* RE_ENABLE_I18N */ + +/* Build the buffer PSTR->MBS, and apply the translation if we need. + This function is used in case of REG_ICASE. */ + +static void +internal_function +build_upper_buffer (re_string_t *pstr) +{ + int char_idx, end_idx; + end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len; + + for (char_idx = pstr->valid_len; char_idx < end_idx; ++char_idx) + { + int ch = pstr->raw_mbs[pstr->raw_mbs_idx + char_idx]; + if (BE (pstr->trans != NULL, 0)) + ch = pstr->trans[ch]; + if (islower (ch)) + pstr->mbs[char_idx] = toupper (ch); + else + pstr->mbs[char_idx] = ch; + } + pstr->valid_len = char_idx; + pstr->valid_raw_len = char_idx; +} + +/* Apply TRANS to the buffer in PSTR. */ + +static void +internal_function +re_string_translate_buffer (re_string_t *pstr) +{ + int buf_idx, end_idx; + end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len; + + for (buf_idx = pstr->valid_len; buf_idx < end_idx; ++buf_idx) + { + int ch = pstr->raw_mbs[pstr->raw_mbs_idx + buf_idx]; + pstr->mbs[buf_idx] = pstr->trans[ch]; + } + + pstr->valid_len = buf_idx; + pstr->valid_raw_len = buf_idx; +} + +/* This function re-construct the buffers. + Concretely, convert to wide character in case of pstr->mb_cur_max > 1, + convert to upper case in case of REG_ICASE, apply translation. */ + +static reg_errcode_t +internal_function +re_string_reconstruct (re_string_t *pstr, int idx, int eflags) +{ + int offset = idx - pstr->raw_mbs_idx; + if (BE (offset < 0, 0)) + { + /* Reset buffer. */ +#ifdef RE_ENABLE_I18N + if (pstr->mb_cur_max > 1) + memset (&pstr->cur_state, '\0', sizeof (mbstate_t)); +#endif + pstr->len = pstr->raw_len; + pstr->stop = pstr->raw_stop; + pstr->valid_len = 0; + pstr->raw_mbs_idx = 0; + pstr->valid_raw_len = 0; + pstr->offsets_needed = 0; + pstr->tip_context = ((eflags & REG_NOTBOL) ? CONTEXT_BEGBUF + : CONTEXT_NEWLINE | CONTEXT_BEGBUF); + if (!pstr->mbs_allocated) + pstr->mbs = (unsigned char *) pstr->raw_mbs; + offset = idx; + } + + if (BE (offset != 0, 1)) + { + /* Are the characters which are already checked remain? */ + if (BE (offset < pstr->valid_raw_len, 1) +#ifdef RE_ENABLE_I18N + /* Handling this would enlarge the code too much. + Accept a slowdown in that case. */ + && pstr->offsets_needed == 0 +#endif + ) + { + /* Yes, move them to the front of the buffer. */ + pstr->tip_context = re_string_context_at (pstr, offset - 1, eflags); +#ifdef RE_ENABLE_I18N + if (pstr->mb_cur_max > 1) + memmove (pstr->wcs, pstr->wcs + offset, + (pstr->valid_len - offset) * sizeof (wint_t)); +#endif + if (BE (pstr->mbs_allocated, 0)) + memmove (pstr->mbs, pstr->mbs + offset, + pstr->valid_len - offset); + pstr->valid_len -= offset; + pstr->valid_raw_len -= offset; +#ifdef DEBUG + assert (pstr->valid_len > 0); +#endif + } + else + { + /* No, skip all characters until IDX. */ +#ifdef RE_ENABLE_I18N + if (BE (pstr->offsets_needed, 0)) + { + pstr->len = pstr->raw_len - idx + offset; + pstr->stop = pstr->raw_stop - idx + offset; + pstr->offsets_needed = 0; + } +#endif + pstr->valid_len = 0; + pstr->valid_raw_len = 0; +#ifdef RE_ENABLE_I18N + if (pstr->mb_cur_max > 1) + { + int wcs_idx; + wint_t wc = WEOF; + + if (pstr->is_utf8) + { + const unsigned char *raw, *p, *q, *end; + + /* Special case UTF-8. Multi-byte chars start with any + byte other than 0x80 - 0xbf. */ + raw = pstr->raw_mbs + pstr->raw_mbs_idx; + end = raw + (offset - pstr->mb_cur_max); + p = raw + offset - 1; +#if 0 + /* We know the wchar_t encoding is UCS4, so for the simple + case, ASCII characters, skip the conversion step. */ + if (isascii (*p) && BE (pstr->trans == NULL, 1)) + { + memset (&pstr->cur_state, '\0', sizeof (mbstate_t)); + pstr->valid_len = 0; + wc = (wchar_t) *p; + } + else +#endif + for (; p >= end; --p) + if ((*p & 0xc0) != 0x80) + { + mbstate_t cur_state; + wchar_t wc2; + int mlen = raw + pstr->len - p; + unsigned char buf[6]; + size_t mbclen; + + q = p; + if (BE (pstr->trans != NULL, 0)) + { + int i = mlen < 6 ? mlen : 6; + while (--i >= 0) + buf[i] = pstr->trans[p[i]]; + q = buf; + } + /* XXX Don't use mbrtowc, we know which conversion + to use (UTF-8 -> UCS4). */ + memset (&cur_state, 0, sizeof (cur_state)); + mbclen = mbrtowc (&wc2, (const char *) p, mlen, + &cur_state); + if (raw + offset - p <= mbclen + && mbclen < (size_t) -2) + { + memset (&pstr->cur_state, '\0', + sizeof (mbstate_t)); + pstr->valid_len = mbclen - (raw + offset - p); + wc = wc2; + } + break; + } + } + + if (wc == WEOF) + pstr->valid_len = re_string_skip_chars (pstr, idx, &wc) - idx; + if (BE (pstr->valid_len, 0)) + { + for (wcs_idx = 0; wcs_idx < pstr->valid_len; ++wcs_idx) + pstr->wcs[wcs_idx] = WEOF; + if (pstr->mbs_allocated) + memset (pstr->mbs, 255, pstr->valid_len); + } + pstr->valid_raw_len = pstr->valid_len; + pstr->tip_context = ((BE (pstr->word_ops_used != 0, 0) + && IS_WIDE_WORD_CHAR (wc)) + ? CONTEXT_WORD + : ((IS_WIDE_NEWLINE (wc) + && pstr->newline_anchor) + ? CONTEXT_NEWLINE : 0)); + } + else +#endif /* RE_ENABLE_I18N */ + { + int c = pstr->raw_mbs[pstr->raw_mbs_idx + offset - 1]; + if (pstr->trans) + c = pstr->trans[c]; + pstr->tip_context = (bitset_contain (pstr->word_char, c) + ? CONTEXT_WORD + : ((IS_NEWLINE (c) && pstr->newline_anchor) + ? CONTEXT_NEWLINE : 0)); + } + } + if (!BE (pstr->mbs_allocated, 0)) + pstr->mbs += offset; + } + pstr->raw_mbs_idx = idx; + pstr->len -= offset; + pstr->stop -= offset; + + /* Then build the buffers. */ +#ifdef RE_ENABLE_I18N + if (pstr->mb_cur_max > 1) + { + if (pstr->icase) + { + reg_errcode_t ret = build_wcs_upper_buffer (pstr); + if (BE (ret != REG_NOERROR, 0)) + return ret; + } + else + build_wcs_buffer (pstr); + } + else +#endif + if (BE (pstr->mbs_allocated, 0)) + { + if (pstr->icase) + build_upper_buffer (pstr); + else if (pstr->trans != NULL) + re_string_translate_buffer (pstr); + } + else + pstr->valid_len = pstr->len; + + pstr->cur_idx = 0; + return REG_NOERROR; +} + +static unsigned char +internal_function __attribute ((pure)) +re_string_peek_byte_case (const re_string_t *pstr, int idx) +{ + int ch, off; + + /* Handle the common (easiest) cases first. */ + if (BE (!pstr->mbs_allocated, 1)) + return re_string_peek_byte (pstr, idx); + +#ifdef RE_ENABLE_I18N + if (pstr->mb_cur_max > 1 + && ! re_string_is_single_byte_char (pstr, pstr->cur_idx + idx)) + return re_string_peek_byte (pstr, idx); +#endif + + off = pstr->cur_idx + idx; +#ifdef RE_ENABLE_I18N + if (pstr->offsets_needed) + off = pstr->offsets[off]; +#endif + + ch = pstr->raw_mbs[pstr->raw_mbs_idx + off]; + +#ifdef RE_ENABLE_I18N + /* Ensure that e.g. for tr_TR.UTF-8 BACKSLASH DOTLESS SMALL LETTER I + this function returns CAPITAL LETTER I instead of first byte of + DOTLESS SMALL LETTER I. The latter would confuse the parser, + since peek_byte_case doesn't advance cur_idx in any way. */ + if (pstr->offsets_needed && !isascii (ch)) + return re_string_peek_byte (pstr, idx); +#endif + + return ch; +} + +static unsigned char +internal_function __attribute ((pure)) +re_string_fetch_byte_case (re_string_t *pstr) +{ + if (BE (!pstr->mbs_allocated, 1)) + return re_string_fetch_byte (pstr); + +#ifdef RE_ENABLE_I18N + if (pstr->offsets_needed) + { + int off, ch; + + /* For tr_TR.UTF-8 [[:islower:]] there is + [[: CAPITAL LETTER I WITH DOT lower:]] in mbs. Skip + in that case the whole multi-byte character and return + the original letter. On the other side, with + [[: DOTLESS SMALL LETTER I return [[:I, as doing + anything else would complicate things too much. */ + + if (!re_string_first_byte (pstr, pstr->cur_idx)) + return re_string_fetch_byte (pstr); + + off = pstr->offsets[pstr->cur_idx]; + ch = pstr->raw_mbs[pstr->raw_mbs_idx + off]; + + if (! isascii (ch)) + return re_string_fetch_byte (pstr); + + re_string_skip_bytes (pstr, + re_string_char_size_at (pstr, pstr->cur_idx)); + return ch; + } +#endif + + return pstr->raw_mbs[pstr->raw_mbs_idx + pstr->cur_idx++]; +} + +static void +internal_function +re_string_destruct (re_string_t *pstr) +{ +#ifdef RE_ENABLE_I18N + re_free (pstr->wcs); + re_free (pstr->offsets); +#endif /* RE_ENABLE_I18N */ + if (pstr->mbs_allocated) + re_free (pstr->mbs); +} + +/* Return the context at IDX in INPUT. */ + +static unsigned int +internal_function +re_string_context_at (const re_string_t *input, int idx, int eflags) +{ + int c; + if (BE (idx < 0, 0)) + /* In this case, we use the value stored in input->tip_context, + since we can't know the character in input->mbs[-1] here. */ + return input->tip_context; + if (BE (idx == input->len, 0)) + return ((eflags & REG_NOTEOL) ? CONTEXT_ENDBUF + : CONTEXT_NEWLINE | CONTEXT_ENDBUF); +#ifdef RE_ENABLE_I18N + if (input->mb_cur_max > 1) + { + wint_t wc; + int wc_idx = idx; + while(input->wcs[wc_idx] == WEOF) + { +#ifdef DEBUG + /* It must not happen. */ + assert (wc_idx >= 0); +#endif + --wc_idx; + if (wc_idx < 0) + return input->tip_context; + } + wc = input->wcs[wc_idx]; + if (BE (input->word_ops_used != 0, 0) && IS_WIDE_WORD_CHAR (wc)) + return CONTEXT_WORD; + return (IS_WIDE_NEWLINE (wc) && input->newline_anchor + ? CONTEXT_NEWLINE : 0); + } +#endif + c = re_string_byte_at (input, idx); + if (bitset_contain (input->word_char, c)) + return CONTEXT_WORD; + return IS_NEWLINE (c) && input->newline_anchor ? CONTEXT_NEWLINE : 0; +} + +/* Functions for set operation. */ + +static reg_errcode_t +internal_function +re_node_set_alloc (re_node_set *set, int size) +{ + set->alloc = size; + set->nelem = 0; + set->elems = re_malloc (int, size); /* can be NULL if size == 0 + (see re_node_set_init_empty(set)) */ + if (BE (set->elems == NULL && size != 0, 0)) + return REG_ESPACE; + return REG_NOERROR; +} + +static reg_errcode_t +internal_function +re_node_set_init_1 (re_node_set *set, int elem) +{ + set->alloc = 1; + set->nelem = 1; + set->elems = re_malloc (int, 1); + if (BE (set->elems == NULL, 0)) + { + set->alloc = set->nelem = 0; + return REG_ESPACE; + } + set->elems[0] = elem; + return REG_NOERROR; +} + +static reg_errcode_t +internal_function +re_node_set_init_2 (re_node_set *set, int elem1, int elem2) +{ + set->alloc = 2; + set->elems = re_malloc (int, 2); + if (BE (set->elems == NULL, 0)) + return REG_ESPACE; + if (elem1 == elem2) + { + set->nelem = 1; + set->elems[0] = elem1; + } + else + { + set->nelem = 2; + if (elem1 < elem2) + { + set->elems[0] = elem1; + set->elems[1] = elem2; + } + else + { + set->elems[0] = elem2; + set->elems[1] = elem1; + } + } + return REG_NOERROR; +} + +static reg_errcode_t +internal_function +re_node_set_init_copy (re_node_set *dest, const re_node_set *src) +{ + dest->nelem = src->nelem; + if (src->nelem > 0) + { + dest->alloc = dest->nelem; + dest->elems = re_malloc (int, dest->alloc); + if (BE (dest->elems == NULL, 0)) + { + dest->alloc = dest->nelem = 0; + return REG_ESPACE; + } + memcpy (dest->elems, src->elems, src->nelem * sizeof (int)); + } + else + re_node_set_init_empty (dest); + return REG_NOERROR; +} + +/* Calculate the intersection of the sets SRC1 and SRC2. And merge it to + DEST. Return value indicate the error code or REG_NOERROR if succeeded. + Note: We assume dest->elems is NULL, when dest->alloc is 0. */ + +static reg_errcode_t +internal_function +re_node_set_add_intersect (re_node_set *dest, const re_node_set *src1, + const re_node_set *src2) +{ + int i1, i2, is, id, delta, sbase; + if (src1->nelem == 0 || src2->nelem == 0) + return REG_NOERROR; + + /* We need dest->nelem + 2 * elems_in_intersection; this is a + conservative estimate. */ + if (src1->nelem + src2->nelem + dest->nelem > dest->alloc) + { + int new_alloc = src1->nelem + src2->nelem + dest->alloc; + int *new_elems = re_realloc (dest->elems, int, new_alloc); + if (BE (new_elems == NULL, 0)) + return REG_ESPACE; + dest->elems = new_elems; + dest->alloc = new_alloc; + } + + /* Find the items in the intersection of SRC1 and SRC2, and copy + into the top of DEST those that are not already in DEST itself. */ + sbase = dest->nelem + src1->nelem + src2->nelem; + i1 = src1->nelem - 1; + i2 = src2->nelem - 1; + id = dest->nelem - 1; + for (;;) + { + if (src1->elems[i1] == src2->elems[i2]) + { + /* Try to find the item in DEST. Maybe we could binary search? */ + while (id >= 0 && dest->elems[id] > src1->elems[i1]) + --id; + + if (id < 0 || dest->elems[id] != src1->elems[i1]) + dest->elems[--sbase] = src1->elems[i1]; + + if (--i1 < 0 || --i2 < 0) + break; + } + + /* Lower the highest of the two items. */ + else if (src1->elems[i1] < src2->elems[i2]) + { + if (--i2 < 0) + break; + } + else + { + if (--i1 < 0) + break; + } + } + + id = dest->nelem - 1; + is = dest->nelem + src1->nelem + src2->nelem - 1; + delta = is - sbase + 1; + + /* Now copy. When DELTA becomes zero, the remaining + DEST elements are already in place; this is more or + less the same loop that is in re_node_set_merge. */ + dest->nelem += delta; + if (delta > 0 && id >= 0) + for (;;) + { + if (dest->elems[is] > dest->elems[id]) + { + /* Copy from the top. */ + dest->elems[id + delta--] = dest->elems[is--]; + if (delta == 0) + break; + } + else + { + /* Slide from the bottom. */ + dest->elems[id + delta] = dest->elems[id]; + if (--id < 0) + break; + } + } + + /* Copy remaining SRC elements. */ + memcpy (dest->elems, dest->elems + sbase, delta * sizeof (int)); + + return REG_NOERROR; +} + +/* Calculate the union set of the sets SRC1 and SRC2. And store it to + DEST. Return value indicate the error code or REG_NOERROR if succeeded. */ + +static reg_errcode_t +internal_function +re_node_set_init_union (re_node_set *dest, const re_node_set *src1, + const re_node_set *src2) +{ + int i1, i2, id; + if (src1 != NULL && src1->nelem > 0 && src2 != NULL && src2->nelem > 0) + { + dest->alloc = src1->nelem + src2->nelem; + dest->elems = re_malloc (int, dest->alloc); + if (BE (dest->elems == NULL, 0)) + return REG_ESPACE; + } + else + { + if (src1 != NULL && src1->nelem > 0) + return re_node_set_init_copy (dest, src1); + if (src2 != NULL && src2->nelem > 0) + return re_node_set_init_copy (dest, src2); + re_node_set_init_empty (dest); + return REG_NOERROR; + } + for (i1 = i2 = id = 0 ; i1 < src1->nelem && i2 < src2->nelem ;) + { + if (src1->elems[i1] > src2->elems[i2]) + { + dest->elems[id++] = src2->elems[i2++]; + continue; + } + if (src1->elems[i1] == src2->elems[i2]) + ++i2; + dest->elems[id++] = src1->elems[i1++]; + } + if (i1 < src1->nelem) + { + memcpy (dest->elems + id, src1->elems + i1, + (src1->nelem - i1) * sizeof (int)); + id += src1->nelem - i1; + } + else if (i2 < src2->nelem) + { + memcpy (dest->elems + id, src2->elems + i2, + (src2->nelem - i2) * sizeof (int)); + id += src2->nelem - i2; + } + dest->nelem = id; + return REG_NOERROR; +} + +/* Calculate the union set of the sets DEST and SRC. And store it to + DEST. Return value indicate the error code or REG_NOERROR if succeeded. */ + +static reg_errcode_t +internal_function +re_node_set_merge (re_node_set *dest, const re_node_set *src) +{ + int is, id, sbase, delta; + if (src == NULL || src->nelem == 0) + return REG_NOERROR; + if (dest->alloc < 2 * src->nelem + dest->nelem) + { + int new_alloc = 2 * (src->nelem + dest->alloc); + int *new_buffer = re_realloc (dest->elems, int, new_alloc); + if (BE (new_buffer == NULL, 0)) + return REG_ESPACE; + dest->elems = new_buffer; + dest->alloc = new_alloc; + } + + if (BE (dest->nelem == 0, 0)) + { + dest->nelem = src->nelem; + memcpy (dest->elems, src->elems, src->nelem * sizeof (int)); + return REG_NOERROR; + } + + /* Copy into the top of DEST the items of SRC that are not + found in DEST. Maybe we could binary search in DEST? */ + for (sbase = dest->nelem + 2 * src->nelem, + is = src->nelem - 1, id = dest->nelem - 1; is >= 0 && id >= 0; ) + { + if (dest->elems[id] == src->elems[is]) + is--, id--; + else if (dest->elems[id] < src->elems[is]) + dest->elems[--sbase] = src->elems[is--]; + else /* if (dest->elems[id] > src->elems[is]) */ + --id; + } + + if (is >= 0) + { + /* If DEST is exhausted, the remaining items of SRC must be unique. */ + sbase -= is + 1; + memcpy (dest->elems + sbase, src->elems, (is + 1) * sizeof (int)); + } + + id = dest->nelem - 1; + is = dest->nelem + 2 * src->nelem - 1; + delta = is - sbase + 1; + if (delta == 0) + return REG_NOERROR; + + /* Now copy. When DELTA becomes zero, the remaining + DEST elements are already in place. */ + dest->nelem += delta; + for (;;) + { + if (dest->elems[is] > dest->elems[id]) + { + /* Copy from the top. */ + dest->elems[id + delta--] = dest->elems[is--]; + if (delta == 0) + break; + } + else + { + /* Slide from the bottom. */ + dest->elems[id + delta] = dest->elems[id]; + if (--id < 0) + { + /* Copy remaining SRC elements. */ + memcpy (dest->elems, dest->elems + sbase, + delta * sizeof (int)); + break; + } + } + } + + return REG_NOERROR; +} + +/* Insert the new element ELEM to the re_node_set* SET. + SET should not already have ELEM. + return -1 if an error is occured, return 1 otherwise. */ + +static int +internal_function +re_node_set_insert (re_node_set *set, int elem) +{ + int idx; + /* In case the set is empty. */ + if (set->alloc == 0) + { + if (BE (re_node_set_init_1 (set, elem) == REG_NOERROR, 1)) + return 1; + return -1; + } + + if (BE (set->nelem, 0) == 0) + { + /* We already guaranteed above that set->alloc != 0. */ + set->elems[0] = elem; + ++set->nelem; + return 1; + } + + /* Realloc if we need. */ + if (set->alloc == set->nelem) + { + int *new_elems; + set->alloc = set->alloc * 2; + new_elems = re_realloc (set->elems, int, set->alloc); + if (BE (new_elems == NULL, 0)) + return -1; + set->elems = new_elems; + } + + /* Move the elements which follows the new element. Test the + first element separately to skip a check in the inner loop. */ + if (elem < set->elems[0]) + { + idx = 0; + for (idx = set->nelem; idx > 0; idx--) + set->elems[idx] = set->elems[idx - 1]; + } + else + { + for (idx = set->nelem; set->elems[idx - 1] > elem; idx--) + set->elems[idx] = set->elems[idx - 1]; + } + + /* Insert the new element. */ + set->elems[idx] = elem; + ++set->nelem; + return 1; +} + +/* Insert the new element ELEM to the re_node_set* SET. + SET should not already have any element greater than or equal to ELEM. + Return -1 if an error is occured, return 1 otherwise. */ + +static int +internal_function +re_node_set_insert_last (re_node_set *set, int elem) +{ + /* Realloc if we need. */ + if (set->alloc == set->nelem) + { + int *new_elems; + set->alloc = (set->alloc + 1) * 2; + new_elems = re_realloc (set->elems, int, set->alloc); + if (BE (new_elems == NULL, 0)) + return -1; + set->elems = new_elems; + } + + /* Insert the new element. */ + set->elems[set->nelem++] = elem; + return 1; +} + +/* Compare two node sets SET1 and SET2. + return 1 if SET1 and SET2 are equivalent, return 0 otherwise. */ + +static int +internal_function __attribute ((pure)) +re_node_set_compare (const re_node_set *set1, const re_node_set *set2) +{ + int i; + if (set1 == NULL || set2 == NULL || set1->nelem != set2->nelem) + return 0; + for (i = set1->nelem ; --i >= 0 ; ) + if (set1->elems[i] != set2->elems[i]) + return 0; + return 1; +} + +/* Return (idx + 1) if SET contains the element ELEM, return 0 otherwise. */ + +static int +internal_function __attribute ((pure)) +re_node_set_contains (const re_node_set *set, int elem) +{ + unsigned int idx, right, mid; + if (set->nelem <= 0) + return 0; + + /* Binary search the element. */ + idx = 0; + right = set->nelem - 1; + while (idx < right) + { + mid = (idx + right) / 2; + if (set->elems[mid] < elem) + idx = mid + 1; + else + right = mid; + } + return set->elems[idx] == elem ? idx + 1 : 0; +} + +static void +internal_function +re_node_set_remove_at (re_node_set *set, int idx) +{ + if (idx < 0 || idx >= set->nelem) + return; + --set->nelem; + for (; idx < set->nelem; idx++) + set->elems[idx] = set->elems[idx + 1]; +} + + +/* Add the token TOKEN to dfa->nodes, and return the index of the token. + Or return -1, if an error will be occured. */ + +static int +internal_function +re_dfa_add_node (re_dfa_t *dfa, re_token_t token) +{ +#ifdef RE_ENABLE_I18N + int type = token.type; +#endif + if (BE (dfa->nodes_len >= dfa->nodes_alloc, 0)) + { + size_t new_nodes_alloc = dfa->nodes_alloc * 2; + int *new_nexts, *new_indices; + re_node_set *new_edests, *new_eclosures; + re_token_t *new_nodes; + + /* Avoid overflows. */ + if (BE (new_nodes_alloc < dfa->nodes_alloc, 0)) + return -1; + + new_nodes = re_realloc (dfa->nodes, re_token_t, new_nodes_alloc); + if (BE (new_nodes == NULL, 0)) + return -1; + dfa->nodes = new_nodes; + new_nexts = re_realloc (dfa->nexts, int, new_nodes_alloc); + new_indices = re_realloc (dfa->org_indices, int, new_nodes_alloc); + new_edests = re_realloc (dfa->edests, re_node_set, new_nodes_alloc); + new_eclosures = re_realloc (dfa->eclosures, re_node_set, new_nodes_alloc); + if (BE (new_nexts == NULL || new_indices == NULL + || new_edests == NULL || new_eclosures == NULL, 0)) + return -1; + dfa->nexts = new_nexts; + dfa->org_indices = new_indices; + dfa->edests = new_edests; + dfa->eclosures = new_eclosures; + dfa->nodes_alloc = new_nodes_alloc; + } + dfa->nodes[dfa->nodes_len] = token; + dfa->nodes[dfa->nodes_len].constraint = 0; +#ifdef RE_ENABLE_I18N + dfa->nodes[dfa->nodes_len].accept_mb = + (type == OP_PERIOD && dfa->mb_cur_max > 1) || type == COMPLEX_BRACKET; +#endif + dfa->nexts[dfa->nodes_len] = -1; + re_node_set_init_empty (dfa->edests + dfa->nodes_len); + re_node_set_init_empty (dfa->eclosures + dfa->nodes_len); + return dfa->nodes_len++; +} + +static __inline__ unsigned int +internal_function +calc_state_hash (const re_node_set *nodes, unsigned int context) +{ + unsigned int hash = nodes->nelem + context; + int i; + for (i = 0 ; i < nodes->nelem ; i++) + hash += nodes->elems[i]; + return hash; +} + +/* Search for the state whose node_set is equivalent to NODES. + Return the pointer to the state, if we found it in the DFA. + Otherwise create the new one and return it. In case of an error + return NULL and set the error code in ERR. + Note: - We assume NULL as the invalid state, then it is possible that + return value is NULL and ERR is REG_NOERROR. + - We never return non-NULL value in case of any errors, it is for + optimization. */ + +static re_dfastate_t * +internal_function +re_acquire_state (reg_errcode_t *err, const re_dfa_t *dfa, + const re_node_set *nodes) +{ + unsigned int hash; + re_dfastate_t *new_state; + struct re_state_table_entry *spot; + int i; + if (BE (nodes->nelem == 0, 0)) + { + *err = REG_NOERROR; + return NULL; + } + hash = calc_state_hash (nodes, 0); + spot = dfa->state_table + (hash & dfa->state_hash_mask); + + for (i = 0 ; i < spot->num ; i++) + { + re_dfastate_t *state = spot->array[i]; + if (hash != state->hash) + continue; + if (re_node_set_compare (&state->nodes, nodes)) + return state; + } + + /* There are no appropriate state in the dfa, create the new one. */ + new_state = create_ci_newstate (dfa, nodes, hash); + if (BE (new_state == NULL, 0)) + *err = REG_ESPACE; + + return new_state; +} + +/* Search for the state whose node_set is equivalent to NODES and + whose context is equivalent to CONTEXT. + Return the pointer to the state, if we found it in the DFA. + Otherwise create the new one and return it. In case of an error + return NULL and set the error code in ERR. + Note: - We assume NULL as the invalid state, then it is possible that + return value is NULL and ERR is REG_NOERROR. + - We never return non-NULL value in case of any errors, it is for + optimization. */ + +static re_dfastate_t * +internal_function +re_acquire_state_context (reg_errcode_t *err, const re_dfa_t *dfa, + const re_node_set *nodes, unsigned int context) +{ + unsigned int hash; + re_dfastate_t *new_state; + struct re_state_table_entry *spot; + int i; + if (nodes->nelem == 0) + { + *err = REG_NOERROR; + return NULL; + } + hash = calc_state_hash (nodes, context); + spot = dfa->state_table + (hash & dfa->state_hash_mask); + + for (i = 0 ; i < spot->num ; i++) + { + re_dfastate_t *state = spot->array[i]; + if (state->hash == hash + && state->context == context + && re_node_set_compare (state->entrance_nodes, nodes)) + return state; + } + /* There are no appropriate state in `dfa', create the new one. */ + new_state = create_cd_newstate (dfa, nodes, context, hash); + if (BE (new_state == NULL, 0)) + *err = REG_ESPACE; + + return new_state; +} + +/* Finish initialization of the new state NEWSTATE, and using its hash value + HASH put in the appropriate bucket of DFA's state table. Return value + indicates the error code if failed. */ + +static reg_errcode_t +register_state (const re_dfa_t *dfa, re_dfastate_t *newstate, + unsigned int hash) +{ + struct re_state_table_entry *spot; + reg_errcode_t err; + int i; + + newstate->hash = hash; + err = re_node_set_alloc (&newstate->non_eps_nodes, newstate->nodes.nelem); + if (BE (err != REG_NOERROR, 0)) + return REG_ESPACE; + for (i = 0; i < newstate->nodes.nelem; i++) + { + int elem = newstate->nodes.elems[i]; + if (!IS_EPSILON_NODE (dfa->nodes[elem].type)) + re_node_set_insert_last (&newstate->non_eps_nodes, elem); + } + + spot = dfa->state_table + (hash & dfa->state_hash_mask); + if (BE (spot->alloc <= spot->num, 0)) + { + int new_alloc = 2 * spot->num + 2; + re_dfastate_t **new_array = re_realloc (spot->array, re_dfastate_t *, + new_alloc); + if (BE (new_array == NULL, 0)) + return REG_ESPACE; + spot->array = new_array; + spot->alloc = new_alloc; + } + spot->array[spot->num++] = newstate; + return REG_NOERROR; +} + +static void +free_state (re_dfastate_t *state) +{ + re_node_set_free (&state->non_eps_nodes); + re_node_set_free (&state->inveclosure); + if (state->entrance_nodes != &state->nodes) + { + re_node_set_free (state->entrance_nodes); + re_free (state->entrance_nodes); + } + re_node_set_free (&state->nodes); + re_free (state->word_trtable); + re_free (state->trtable); + re_free (state); +} + +/* Create the new state which is independ of contexts. + Return the new state if succeeded, otherwise return NULL. */ + +static re_dfastate_t * +internal_function +create_ci_newstate (const re_dfa_t *dfa, const re_node_set *nodes, + unsigned int hash) +{ + int i; + reg_errcode_t err; + re_dfastate_t *newstate; + + newstate = calloc (sizeof (re_dfastate_t), 1); + if (BE (newstate == NULL, 0)) + return NULL; + err = re_node_set_init_copy (&newstate->nodes, nodes); + if (BE (err != REG_NOERROR, 0)) + { + re_free (newstate); + return NULL; + } + + newstate->entrance_nodes = &newstate->nodes; + for (i = 0 ; i < nodes->nelem ; i++) + { + re_token_t *node = dfa->nodes + nodes->elems[i]; + re_token_type_t type = node->type; + + if (type == CHARACTER && !node->constraint) + continue; +#ifdef RE_ENABLE_I18N + newstate->accept_mb |= node->accept_mb; +#endif + + /* If the state has the halt node, the state is a halt state. */ + if (type == END_OF_RE) + newstate->halt = 1; + else if (type == OP_BACK_REF) + newstate->has_backref = 1; + else if (type == ANCHOR || node->constraint) + newstate->has_constraint = 1; + } + err = register_state (dfa, newstate, hash); + if (BE (err != REG_NOERROR, 0)) + { + free_state (newstate); + newstate = NULL; + } + return newstate; +} + +/* Create the new state which is depend on the context CONTEXT. + Return the new state if succeeded, otherwise return NULL. */ + +static re_dfastate_t * +internal_function +create_cd_newstate (const re_dfa_t *dfa, const re_node_set *nodes, + unsigned int context, unsigned int hash) +{ + int i, nctx_nodes = 0; + reg_errcode_t err; + re_dfastate_t *newstate; + + newstate = calloc (sizeof (re_dfastate_t), 1); + if (BE (newstate == NULL, 0)) + return NULL; + err = re_node_set_init_copy (&newstate->nodes, nodes); + if (BE (err != REG_NOERROR, 0)) + { + re_free (newstate); + return NULL; + } + + newstate->context = context; + newstate->entrance_nodes = &newstate->nodes; + + for (i = 0 ; i < nodes->nelem ; i++) + { + unsigned int constraint = 0; + re_token_t *node = dfa->nodes + nodes->elems[i]; + re_token_type_t type = node->type; + if (node->constraint) + constraint = node->constraint; + + if (type == CHARACTER && !constraint) + continue; +#ifdef RE_ENABLE_I18N + newstate->accept_mb |= node->accept_mb; +#endif /* RE_ENABLE_I18N */ + + /* If the state has the halt node, the state is a halt state. */ + if (type == END_OF_RE) + newstate->halt = 1; + else if (type == OP_BACK_REF) + newstate->has_backref = 1; + else if (type == ANCHOR) + constraint = node->opr.ctx_type; + + if (constraint) + { + if (newstate->entrance_nodes == &newstate->nodes) + { + newstate->entrance_nodes = re_malloc (re_node_set, 1); + if (BE (newstate->entrance_nodes == NULL, 0)) + { + free_state (newstate); + return NULL; + } + re_node_set_init_copy (newstate->entrance_nodes, nodes); + nctx_nodes = 0; + newstate->has_constraint = 1; + } + + if (NOT_SATISFY_PREV_CONSTRAINT (constraint,context)) + { + re_node_set_remove_at (&newstate->nodes, i - nctx_nodes); + ++nctx_nodes; + } + } + } + err = register_state (dfa, newstate, hash); + if (BE (err != REG_NOERROR, 0)) + { + free_state (newstate); + newstate = NULL; + } + return newstate; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/regex/regex_internal.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/regex/regex_internal.h new file mode 100644 index 00000000..0a255e37 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/regex/regex_internal.h @@ -0,0 +1,708 @@ +/* Extended regular expression matching and search library. + Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Isamu Hasegawa . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _REGEX_INTERNAL_H +#define _REGEX_INTERNAL_H 1 + +#include +#include +#include +#include +#include + +#if defined HAVE_LANGINFO_H || defined HAVE_LANGINFO_CODESET +# include +#endif +#if defined HAVE_LOCALE_H +# include +#endif +#if defined HAVE_WCHAR_H +# include +#endif +#if defined HAVE_WCTYPE_H +# include +#endif +#if defined HAVE_STDBOOL_H +# include +#endif +#if defined HAVE_STDINT_H +# include +#endif + +#ifdef __UCLIBC_HAS_THREADS__ +#include +#else +#define __libc_lock_define(CLASS, NAME) +#define __libc_lock_init(NAME) do { } while (0) +#define __libc_lock_lock(NAME) do { } while (0) +#define __libc_lock_unlock(NAME) do { } while (0) +#endif + +#undef gettext +#undef gettext_noop +#define gettext(msgid) (msgid) +#define gettext_noop(String) String + +#if (defined MB_CUR_MAX && HAVE_LOCALE_H && HAVE_WCTYPE_H && HAVE_WCHAR_H && HAVE_WCRTOMB && HAVE_MBRTOWC && HAVE_WCSCOLL) +# define RE_ENABLE_I18N +#endif + +#if __GNUC__ >= 3 +/* uclibc: lean towards smaller size a bit: + * OFF: # define BE(expr, val) __builtin_expect (expr, val) */ +# define BE(expr, val) (expr) +#else +# define BE(expr, val) (expr) +# define inline +#endif + +/* Number of single byte character. */ +#define SBC_MAX 256 + +#define COLL_ELEM_LEN_MAX 8 + +/* The character which represents newline. */ +#define NEWLINE_CHAR '\n' +#define WIDE_NEWLINE_CHAR L'\n' + +#ifdef __GNUC__ +# define __attribute(arg) __attribute__ (arg) +#else +# define __attribute(arg) +#endif + +/* An integer used to represent a set of bits. It must be unsigned, + and must be at least as wide as unsigned int. */ +typedef unsigned long int bitset_word_t; +/* All bits set in a bitset_word_t. */ +#define BITSET_WORD_MAX ULONG_MAX +/* Number of bits in a bitset_word_t. */ +#define BITSET_WORD_BITS (sizeof (bitset_word_t) * CHAR_BIT) +/* Number of bitset_word_t in a bit_set. */ +#define BITSET_WORDS (SBC_MAX / BITSET_WORD_BITS) +typedef bitset_word_t bitset_t[BITSET_WORDS]; +typedef bitset_word_t *re_bitset_ptr_t; +typedef const bitset_word_t *re_const_bitset_ptr_t; + +#define bitset_set(set,i) \ + (set[i / BITSET_WORD_BITS] |= (bitset_word_t) 1 << i % BITSET_WORD_BITS) +#define bitset_clear(set,i) \ + (set[i / BITSET_WORD_BITS] &= ~((bitset_word_t) 1 << i % BITSET_WORD_BITS)) +#define bitset_contain(set,i) \ + (set[i / BITSET_WORD_BITS] & ((bitset_word_t) 1 << i % BITSET_WORD_BITS)) +#define bitset_empty(set) memset (set, '\0', sizeof (bitset_t)) +#define bitset_set_all(set) memset (set, '\xff', sizeof (bitset_t)) +#define bitset_copy(dest,src) memcpy (dest, src, sizeof (bitset_t)) + +#define PREV_WORD_CONSTRAINT 0x0001 +#define PREV_NOTWORD_CONSTRAINT 0x0002 +#define NEXT_WORD_CONSTRAINT 0x0004 +#define NEXT_NOTWORD_CONSTRAINT 0x0008 +#define PREV_NEWLINE_CONSTRAINT 0x0010 +#define NEXT_NEWLINE_CONSTRAINT 0x0020 +#define PREV_BEGBUF_CONSTRAINT 0x0040 +#define NEXT_ENDBUF_CONSTRAINT 0x0080 +#define WORD_DELIM_CONSTRAINT 0x0100 +#define NOT_WORD_DELIM_CONSTRAINT 0x0200 + +typedef enum +{ + INSIDE_WORD = PREV_WORD_CONSTRAINT | NEXT_WORD_CONSTRAINT, + WORD_FIRST = PREV_NOTWORD_CONSTRAINT | NEXT_WORD_CONSTRAINT, + WORD_LAST = PREV_WORD_CONSTRAINT | NEXT_NOTWORD_CONSTRAINT, + INSIDE_NOTWORD = PREV_NOTWORD_CONSTRAINT | NEXT_NOTWORD_CONSTRAINT, + LINE_FIRST = PREV_NEWLINE_CONSTRAINT, + LINE_LAST = NEXT_NEWLINE_CONSTRAINT, + BUF_FIRST = PREV_BEGBUF_CONSTRAINT, + BUF_LAST = NEXT_ENDBUF_CONSTRAINT, + WORD_DELIM = WORD_DELIM_CONSTRAINT, + NOT_WORD_DELIM = NOT_WORD_DELIM_CONSTRAINT +} re_context_type; + +typedef struct +{ + int alloc; + int nelem; + int *elems; +} re_node_set; + +typedef enum +{ + NON_TYPE = 0, + + /* Node type, These are used by token, node, tree. */ + CHARACTER = 1, + END_OF_RE = 2, + SIMPLE_BRACKET = 3, + OP_BACK_REF = 4, + OP_PERIOD = 5, +#ifdef RE_ENABLE_I18N + COMPLEX_BRACKET = 6, + OP_UTF8_PERIOD = 7, +#endif /* RE_ENABLE_I18N */ + + /* We define EPSILON_BIT as a macro so that OP_OPEN_SUBEXP is used + when the debugger shows values of this enum type. */ +#define EPSILON_BIT 8 + OP_OPEN_SUBEXP = EPSILON_BIT | 0, + OP_CLOSE_SUBEXP = EPSILON_BIT | 1, + OP_ALT = EPSILON_BIT | 2, + OP_DUP_ASTERISK = EPSILON_BIT | 3, + ANCHOR = EPSILON_BIT | 4, + + /* Tree type, these are used only by tree. */ + CONCAT = 16, + SUBEXP = 17, + + /* Token type, these are used only by token. */ + OP_DUP_PLUS = 18, + OP_DUP_QUESTION, + OP_OPEN_BRACKET, + OP_CLOSE_BRACKET, + OP_CHARSET_RANGE, + OP_OPEN_DUP_NUM, + OP_CLOSE_DUP_NUM, + OP_NON_MATCH_LIST, + OP_OPEN_COLL_ELEM, + OP_CLOSE_COLL_ELEM, + OP_OPEN_EQUIV_CLASS, + OP_CLOSE_EQUIV_CLASS, + OP_OPEN_CHAR_CLASS, + OP_CLOSE_CHAR_CLASS, + OP_WORD, + OP_NOTWORD, + OP_SPACE, + OP_NOTSPACE, + BACK_SLASH + +} re_token_type_t; + +#ifdef RE_ENABLE_I18N +typedef struct +{ + /* Multibyte characters. */ + wchar_t *mbchars; + + /* Collating symbols. */ +# if 0 + int32_t *coll_syms; +# endif + + /* Equivalence classes. */ +# if 0 + int32_t *equiv_classes; +# endif + + /* Range expressions. */ +# if 0 + uint32_t *range_starts; + uint32_t *range_ends; +# else + wchar_t *range_starts; + wchar_t *range_ends; +# endif + + /* Character classes. */ + wctype_t *char_classes; + + /* If this character set is the non-matching list. */ + unsigned int non_match : 1; + + /* # of multibyte characters. */ + int nmbchars; + + /* # of collating symbols. */ + int ncoll_syms; + + /* # of equivalence classes. */ + int nequiv_classes; + + /* # of range expressions. */ + int nranges; + + /* # of character classes. */ + int nchar_classes; +} re_charset_t; +#endif /* RE_ENABLE_I18N */ + +typedef struct +{ + union + { + unsigned char c; /* for CHARACTER */ + re_bitset_ptr_t sbcset; /* for SIMPLE_BRACKET */ +#ifdef RE_ENABLE_I18N + re_charset_t *mbcset; /* for COMPLEX_BRACKET */ +#endif /* RE_ENABLE_I18N */ + int idx; /* for BACK_REF */ + re_context_type ctx_type; /* for ANCHOR */ + } opr; +#if __GNUC__ >= 2 + re_token_type_t type : 8; +#else + re_token_type_t type; +#endif + unsigned int constraint : 10; /* context constraint */ + unsigned int duplicated : 1; + unsigned int opt_subexp : 1; +#ifdef RE_ENABLE_I18N + unsigned int accept_mb : 1; + /* These 2 bits can be moved into the union if needed (e.g. if running out + of bits; move opr.c to opr.c.c and move the flags to opr.c.flags). */ + unsigned int mb_partial : 1; +#endif + unsigned int word_char : 1; +} re_token_t; + +#define IS_EPSILON_NODE(type) ((type) & EPSILON_BIT) + +struct re_string_t +{ + /* Indicate the raw buffer which is the original string passed as an + argument of regexec(), re_search(), etc.. */ + const unsigned char *raw_mbs; + /* Store the multibyte string. In case of "case insensitive mode" like + REG_ICASE, upper cases of the string are stored, otherwise MBS points + the same address that RAW_MBS points. */ + unsigned char *mbs; +#ifdef RE_ENABLE_I18N + /* Store the wide character string which is corresponding to MBS. */ + wint_t *wcs; + int *offsets; + mbstate_t cur_state; +#endif + /* Index in RAW_MBS. Each character mbs[i] corresponds to + raw_mbs[raw_mbs_idx + i]. */ + int raw_mbs_idx; + /* The length of the valid characters in the buffers. */ + int valid_len; + /* The corresponding number of bytes in raw_mbs array. */ + int valid_raw_len; + /* The length of the buffers MBS and WCS. */ + int bufs_len; + /* The index in MBS, which is updated by re_string_fetch_byte. */ + int cur_idx; + /* length of RAW_MBS array. */ + int raw_len; + /* This is RAW_LEN - RAW_MBS_IDX + VALID_LEN - VALID_RAW_LEN. */ + int len; + /* End of the buffer may be shorter than its length in the cases such + as re_match_2, re_search_2. Then, we use STOP for end of the buffer + instead of LEN. */ + int raw_stop; + /* This is RAW_STOP - RAW_MBS_IDX adjusted through OFFSETS. */ + int stop; + + /* The context of mbs[0]. We store the context independently, since + the context of mbs[0] may be different from raw_mbs[0], which is + the beginning of the input string. */ + unsigned int tip_context; + /* The translation passed as a part of an argument of re_compile_pattern. */ + RE_TRANSLATE_TYPE trans; + /* Copy of re_dfa_t's word_char. */ + re_const_bitset_ptr_t word_char; + /* 1 if REG_ICASE. */ + unsigned char icase; + unsigned char is_utf8; + unsigned char map_notascii; + unsigned char mbs_allocated; + unsigned char offsets_needed; + unsigned char newline_anchor; + unsigned char word_ops_used; + int mb_cur_max; +}; +typedef struct re_string_t re_string_t; + +struct re_dfa_t; +typedef struct re_dfa_t re_dfa_t; + +static reg_errcode_t re_string_realloc_buffers (re_string_t *pstr, + int new_buf_len) + internal_function; +#ifdef RE_ENABLE_I18N +static void build_wcs_buffer (re_string_t *pstr) internal_function; +static reg_errcode_t build_wcs_upper_buffer (re_string_t *pstr) internal_function; +#endif /* RE_ENABLE_I18N */ +static void build_upper_buffer (re_string_t *pstr) internal_function; +static void re_string_translate_buffer (re_string_t *pstr) internal_function; +static unsigned int re_string_context_at (const re_string_t *input, int idx, + int eflags) + internal_function __attribute ((pure)); +#define re_string_peek_byte(pstr, offset) \ + ((pstr)->mbs[(pstr)->cur_idx + offset]) +#define re_string_fetch_byte(pstr) \ + ((pstr)->mbs[(pstr)->cur_idx++]) +#define re_string_first_byte(pstr, idx) \ + ((idx) == (pstr)->valid_len || (pstr)->wcs[idx] != WEOF) +#define re_string_is_single_byte_char(pstr, idx) \ + ((pstr)->wcs[idx] != WEOF && ((pstr)->valid_len == (idx) + 1 \ + || (pstr)->wcs[(idx) + 1] != WEOF)) +#define re_string_eoi(pstr) ((pstr)->stop <= (pstr)->cur_idx) +#define re_string_cur_idx(pstr) ((pstr)->cur_idx) +#define re_string_get_buffer(pstr) ((pstr)->mbs) +#define re_string_length(pstr) ((pstr)->len) +#define re_string_byte_at(pstr,idx) ((pstr)->mbs[idx]) +#define re_string_skip_bytes(pstr,idx) ((pstr)->cur_idx += (idx)) +#define re_string_set_index(pstr,idx) ((pstr)->cur_idx = (idx)) + +#include + +#if 1 +# ifdef HAVE_ALLOCA +/* The OS usually guarantees only one guard page at the bottom of the stack, + and a page size can be as small as 4096 bytes. So we cannot safely + allocate anything larger than 4096 bytes. Also care for the possibility + of a few compiler-allocated temporary stack slots. */ +# define __libc_use_alloca(n) ((n) < 4032) +# else +/* alloca is implemented with malloc, so just use malloc. */ +# define __libc_use_alloca(n) 0 +# endif +#endif + +#define re_malloc(t,n) ((t *) malloc ((n) * sizeof (t))) +#define re_realloc(p,t,n) ((t *) realloc (p, (n) * sizeof (t))) +#define re_free(p) free (p) + +struct bin_tree_t +{ + struct bin_tree_t *parent; + struct bin_tree_t *left; + struct bin_tree_t *right; + struct bin_tree_t *first; + struct bin_tree_t *next; + + re_token_t token; + + /* `node_idx' is the index in dfa->nodes, if `type' == 0. + Otherwise `type' indicate the type of this node. */ + int node_idx; +}; +typedef struct bin_tree_t bin_tree_t; + +#define BIN_TREE_STORAGE_SIZE \ + ((1024 - sizeof (void *)) / sizeof (bin_tree_t)) + +struct bin_tree_storage_t +{ + struct bin_tree_storage_t *next; + bin_tree_t data[BIN_TREE_STORAGE_SIZE]; +}; +typedef struct bin_tree_storage_t bin_tree_storage_t; + +#define CONTEXT_WORD 1 +#define CONTEXT_NEWLINE (CONTEXT_WORD << 1) +#define CONTEXT_BEGBUF (CONTEXT_NEWLINE << 1) +#define CONTEXT_ENDBUF (CONTEXT_BEGBUF << 1) + +#define IS_WORD_CONTEXT(c) ((c) & CONTEXT_WORD) +#define IS_NEWLINE_CONTEXT(c) ((c) & CONTEXT_NEWLINE) +#define IS_BEGBUF_CONTEXT(c) ((c) & CONTEXT_BEGBUF) +#define IS_ENDBUF_CONTEXT(c) ((c) & CONTEXT_ENDBUF) +#define IS_ORDINARY_CONTEXT(c) ((c) == 0) + +#define IS_WORD_CHAR(ch) (isalnum (ch) || (ch) == '_') +#define IS_NEWLINE(ch) ((ch) == NEWLINE_CHAR) +#define IS_WIDE_WORD_CHAR(ch) (iswalnum (ch) || (ch) == L'_') +#define IS_WIDE_NEWLINE(ch) ((ch) == WIDE_NEWLINE_CHAR) + +#define NOT_SATISFY_PREV_CONSTRAINT(constraint,context) \ + ((((constraint) & PREV_WORD_CONSTRAINT) && !IS_WORD_CONTEXT (context)) \ + || ((constraint & PREV_NOTWORD_CONSTRAINT) && IS_WORD_CONTEXT (context)) \ + || ((constraint & PREV_NEWLINE_CONSTRAINT) && !IS_NEWLINE_CONTEXT (context))\ + || ((constraint & PREV_BEGBUF_CONSTRAINT) && !IS_BEGBUF_CONTEXT (context))) + +#define NOT_SATISFY_NEXT_CONSTRAINT(constraint,context) \ + ((((constraint) & NEXT_WORD_CONSTRAINT) && !IS_WORD_CONTEXT (context)) \ + || (((constraint) & NEXT_NOTWORD_CONSTRAINT) && IS_WORD_CONTEXT (context)) \ + || (((constraint) & NEXT_NEWLINE_CONSTRAINT) && !IS_NEWLINE_CONTEXT (context)) \ + || (((constraint) & NEXT_ENDBUF_CONSTRAINT) && !IS_ENDBUF_CONTEXT (context))) + +struct re_dfastate_t +{ + unsigned int hash; + re_node_set nodes; + re_node_set non_eps_nodes; + re_node_set inveclosure; + re_node_set *entrance_nodes; + struct re_dfastate_t **trtable, **word_trtable; + unsigned int context : 4; + unsigned int halt : 1; + /* If this state can accept `multi byte'. + Note that we refer to multibyte characters, and multi character + collating elements as `multi byte'. */ + unsigned int accept_mb : 1; + /* If this state has backreference node(s). */ + unsigned int has_backref : 1; + unsigned int has_constraint : 1; +}; +typedef struct re_dfastate_t re_dfastate_t; + +struct re_state_table_entry +{ + int num; + int alloc; + re_dfastate_t **array; +}; + +/* Array type used in re_sub_match_last_t and re_sub_match_top_t. */ + +typedef struct +{ + int next_idx; + int alloc; + re_dfastate_t **array; +} state_array_t; + +/* Store information about the node NODE whose type is OP_CLOSE_SUBEXP. */ + +typedef struct +{ + int node; + int str_idx; /* The position NODE match at. */ + state_array_t path; +} re_sub_match_last_t; + +/* Store information about the node NODE whose type is OP_OPEN_SUBEXP. + And information about the node, whose type is OP_CLOSE_SUBEXP, + corresponding to NODE is stored in LASTS. */ + +typedef struct +{ + int str_idx; + int node; + state_array_t *path; + int alasts; /* Allocation size of LASTS. */ + int nlasts; /* The number of LASTS. */ + re_sub_match_last_t **lasts; +} re_sub_match_top_t; + +struct re_backref_cache_entry +{ + int node; + int str_idx; + int subexp_from; + int subexp_to; + char more; + char unused; + unsigned short int eps_reachable_subexps_map; +}; + +typedef struct +{ + /* The string object corresponding to the input string. */ + re_string_t input; + const re_dfa_t *dfa; + /* EFLAGS of the argument of regexec. */ + int eflags; + /* Where the matching ends. */ + int match_last; + int last_node; + /* The state log used by the matcher. */ + re_dfastate_t **state_log; + int state_log_top; + /* Back reference cache. */ + int nbkref_ents; + int abkref_ents; + struct re_backref_cache_entry *bkref_ents; + int max_mb_elem_len; + int nsub_tops; + int asub_tops; + re_sub_match_top_t **sub_tops; +} re_match_context_t; + +typedef struct +{ + re_dfastate_t **sifted_states; + re_dfastate_t **limited_states; + int last_node; + int last_str_idx; + re_node_set limits; +} re_sift_context_t; + +struct re_fail_stack_ent_t +{ + int idx; + int node; + regmatch_t *regs; + re_node_set eps_via_nodes; +}; + +struct re_fail_stack_t +{ + int num; + int alloc; + struct re_fail_stack_ent_t *stack; +}; + +struct re_dfa_t +{ + re_token_t *nodes; + size_t nodes_alloc; + size_t nodes_len; + int *nexts; + int *org_indices; + re_node_set *edests; + re_node_set *eclosures; + re_node_set *inveclosures; + struct re_state_table_entry *state_table; + re_dfastate_t *init_state; + re_dfastate_t *init_state_word; + re_dfastate_t *init_state_nl; + re_dfastate_t *init_state_begbuf; + bin_tree_t *str_tree; + bin_tree_storage_t *str_tree_storage; + re_bitset_ptr_t sb_char; + int str_tree_storage_idx; + + /* number of subexpressions `re_nsub' is in regex_t. */ + unsigned int state_hash_mask; + int init_node; + int nbackref; /* The number of backreference in this dfa. */ + + /* Bitmap expressing which backreference is used. */ + bitset_word_t used_bkref_map; + bitset_word_t completed_bkref_map; + + unsigned int has_plural_match : 1; + /* If this dfa has "multibyte node", which is a backreference or + a node which can accept multibyte character or multi character + collating element. */ + unsigned int has_mb_node : 1; + unsigned int is_utf8 : 1; + unsigned int map_notascii : 1; + unsigned int word_ops_used : 1; + int mb_cur_max; + bitset_t word_char; + reg_syntax_t syntax; + int *subexp_map; +#ifdef DEBUG + char* re_str; +#endif + __libc_lock_define (, lock) +}; + +#define re_node_set_init_empty(set) memset (set, '\0', sizeof (re_node_set)) +#define re_node_set_remove(set,id) \ + (re_node_set_remove_at (set, re_node_set_contains (set, id) - 1)) +#define re_node_set_empty(p) ((p)->nelem = 0) +#define re_node_set_free(set) re_free ((set)->elems) + + +typedef enum +{ + SB_CHAR, + MB_CHAR, + EQUIV_CLASS, + COLL_SYM, + CHAR_CLASS +} bracket_elem_type; + +typedef struct +{ + bracket_elem_type type; + union + { + unsigned char ch; + unsigned char *name; +#ifdef __UCLIBC_HAS_WCHAR__ + wchar_t wch; +#endif + } opr; +} bracket_elem_t; + + +/* Inline functions for bitset operation. */ +static __inline__ void +bitset_not (bitset_t set) +{ + int bitset_i; + for (bitset_i = 0; bitset_i < BITSET_WORDS; ++bitset_i) + set[bitset_i] = ~set[bitset_i]; +} + +static __inline__ void +bitset_merge (bitset_t dest, const bitset_t src) +{ + int bitset_i; + for (bitset_i = 0; bitset_i < BITSET_WORDS; ++bitset_i) + dest[bitset_i] |= src[bitset_i]; +} + +static __inline__ void +bitset_mask (bitset_t dest, const bitset_t src) +{ + int bitset_i; + for (bitset_i = 0; bitset_i < BITSET_WORDS; ++bitset_i) + dest[bitset_i] &= src[bitset_i]; +} + +#ifdef RE_ENABLE_I18N +/* Inline functions for re_string. */ +static __inline__ int +internal_function __attribute ((pure)) +re_string_char_size_at (const re_string_t *pstr, int idx) +{ + int byte_idx; + if (pstr->mb_cur_max == 1) + return 1; + for (byte_idx = 1; idx + byte_idx < pstr->valid_len; ++byte_idx) + if (pstr->wcs[idx + byte_idx] != WEOF) + break; + return byte_idx; +} + +static __inline__ wint_t +internal_function __attribute ((pure)) +re_string_wchar_at (const re_string_t *pstr, int idx) +{ + if (pstr->mb_cur_max == 1) + return (wint_t) pstr->mbs[idx]; + return (wint_t) pstr->wcs[idx]; +} + +static int +internal_function __attribute ((pure)) +re_string_elem_size_at (const re_string_t *pstr, int idx) +{ +# if 0 + const unsigned char *p, *extra; + const int32_t *table, *indirect; + int32_t tmp; +# include + uint_fast32_t nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); + + if (nrules != 0) + { + table = (const int32_t *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB); + extra = (const unsigned char *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAMB); + indirect = (const int32_t *) _NL_CURRENT (LC_COLLATE, + _NL_COLLATE_INDIRECTMB); + p = pstr->mbs + idx; + tmp = findidx (&p); + return p - pstr->mbs - idx; + } +# endif + return 1; +} +#endif /* RE_ENABLE_I18N */ + +#endif /* _REGEX_INTERNAL_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/regex/regex_old.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/regex/regex_old.c new file mode 100644 index 00000000..a3c30b51 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/regex/regex_old.c @@ -0,0 +1,8269 @@ +/* Extended regular expression matching and search library, + version 0.12. + (Implements POSIX draft P1003.2/D11.2, except for some of the + internationalization features.) + Copyright (C) 1993-1999, 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* To exclude some unwanted junk.... */ +#undef emacs +#include +/* unistd.h must be included with _LIBC defined: we need smallint */ +#include +#ifdef __UCLIBC__ +# undef _LIBC +# define _REGEX_RE_COMP +# define STDC_HEADERS +# define RE_TRANSLATE_TYPE char * +#endif +#include +#include +#include +#include + +/* AIX requires this to be the first thing in the file. */ +#if defined _AIX && !defined REGEX_MALLOC +# pragma alloca +#endif + +#ifdef HAVE_CONFIG_H +# include +#endif + +#ifndef INSIDE_RECURSION + +# if defined STDC_HEADERS && !defined emacs +# include +# else +/* We need this for `regex.h', and perhaps for the Emacs include files. */ +# include +# endif + + +/* For platform which support the ISO C amendement 1 functionality we + support user defined character classes. */ +# if defined __UCLIBC_HAS_WCHAR__ +# define WIDE_CHAR_SUPPORT 1 +/* Solaris 2.5 has a bug: must be included before . */ +# include +# include +# endif + +# if defined _LIBC || defined __UCLIBC__ +/* We have to keep the namespace clean. */ + +# ifndef __UCLIBC__ +# define btowc __btowc + +/* We are also using some library internals. */ +# include +# include +# include +# include +# endif +# endif + +/* This is for other GNU distributions with internationalized messages. */ +# if defined HAVE_LIBINTL_H || defined _LIBC +# include +# ifdef _LIBC +# undef gettext +# define gettext(msgid) __dcgettext ("libc", msgid, LC_MESSAGES) +# endif +# else +# define gettext(msgid) (msgid) +# endif + +# ifndef gettext_noop +/* This define is so xgettext can find the internationalizable + strings. */ +# define gettext_noop(String) String +# endif + +/* The `emacs' switch turns on certain matching commands + that make sense only in Emacs. */ +# ifdef emacs + +# include "lisp.h" +# include "buffer.h" +# include "syntax.h" + +# else /* not emacs */ + +/* If we are not linking with Emacs proper, + we can't use the relocating allocator + even if config.h says that we can. */ +# undef REL_ALLOC + +# if defined STDC_HEADERS || defined _LIBC +# include +# else +char *malloc (); +char *realloc (); +# endif + +/* When used in Emacs's lib-src, we need to get bzero and bcopy somehow. + If nothing else has been done, use the method below. */ +# ifdef INHIBIT_STRING_HEADER +# if !(defined HAVE_BZERO && defined HAVE_BCOPY) +# if !defined bzero && !defined bcopy +# undef INHIBIT_STRING_HEADER +# endif +# endif +# endif + +/* This is the normal way of making sure we have a bcopy and a bzero. + This is used in most programs--a few other programs avoid this + by defining INHIBIT_STRING_HEADER. */ +# ifndef INHIBIT_STRING_HEADER +# if defined HAVE_STRING_H || defined STDC_HEADERS || defined _LIBC +# include +# ifndef bzero +# ifndef _LIBC +# define bzero(s, n) (memset (s, '\0', n), (s)) +# else +# define bzero(s, n) __bzero (s, n) +# endif +# endif +# else +# include +# ifndef memcmp +# define memcmp(s1, s2, n) bcmp (s1, s2, n) +# endif +# ifndef memcpy +# define memcpy(d, s, n) (bcopy (s, d, n), (d)) +# endif +# endif +# endif + +/* Define the syntax stuff for \<, \>, etc. */ + +/* This must be nonzero for the wordchar and notwordchar pattern + commands in re_match_2. */ +# ifndef Sword +# define Sword 1 +# endif + +# ifdef SWITCH_ENUM_BUG +# define SWITCH_ENUM_CAST(x) ((int)(x)) +# else +# define SWITCH_ENUM_CAST(x) (x) +# endif + +# endif /* not emacs */ + +# if defined _LIBC || defined HAVE_LIMITS_H +# include +# endif + +# ifndef MB_LEN_MAX +# define MB_LEN_MAX 1 +# endif + +/* Get the interface, including the syntax bits. */ +# include + +/* isalpha etc. are used for the character classes. */ +# include + +/* Jim Meyering writes: + + "... Some ctype macros are valid only for character codes that + isascii says are ASCII (SGI's IRIX-4.0.5 is one such system --when + using /bin/cc or gcc but without giving an ansi option). So, all + ctype uses should be through macros like ISPRINT... If + STDC_HEADERS is defined, then autoconf has verified that the ctype + macros don't need to be guarded with references to isascii. ... + Defining isascii to 1 should let any compiler worth its salt + eliminate the && through constant folding." + Solaris defines some of these symbols so we must undefine them first. */ + +# undef ISASCII +# if defined STDC_HEADERS || (!defined isascii && !defined HAVE_ISASCII) +# define ISASCII(c) 1 +# else +# define ISASCII(c) isascii(c) +# endif + +# ifdef isblank +# define ISBLANK(c) (ISASCII (c) && isblank (c)) +# else +# define ISBLANK(c) ((c) == ' ' || (c) == '\t') +# endif +# ifdef isgraph +# define ISGRAPH(c) (ISASCII (c) && isgraph (c)) +# else +# define ISGRAPH(c) (ISASCII (c) && isprint (c) && !isspace (c)) +# endif + +# undef ISPRINT +# define ISPRINT(c) (ISASCII (c) && isprint (c)) +# define ISDIGIT(c) (ISASCII (c) && isdigit (c)) +# define ISALNUM(c) (ISASCII (c) && isalnum (c)) +# define ISALPHA(c) (ISASCII (c) && isalpha (c)) +# define ISCNTRL(c) (ISASCII (c) && iscntrl (c)) +# define ISLOWER(c) (ISASCII (c) && islower (c)) +# define ISPUNCT(c) (ISASCII (c) && ispunct (c)) +# define ISSPACE(c) (ISASCII (c) && isspace (c)) +# define ISUPPER(c) (ISASCII (c) && isupper (c)) +# define ISXDIGIT(c) (ISASCII (c) && isxdigit (c)) + +# ifdef _tolower +# define TOLOWER(c) _tolower(c) +# else +# define TOLOWER(c) tolower(c) +# endif + +# ifndef NULL +# define NULL (void *)0 +# endif + +/* We remove any previous definition of `SIGN_EXTEND_CHAR', + since ours (we hope) works properly with all combinations of + machines, compilers, `char' and `unsigned char' argument types. + (Per Bothner suggested the basic approach.) */ +# undef SIGN_EXTEND_CHAR +# if __STDC__ +# define SIGN_EXTEND_CHAR(c) ((signed char) (c)) +# else /* not __STDC__ */ +/* As in Harbison and Steele. */ +# define SIGN_EXTEND_CHAR(c) ((((unsigned char) (c)) ^ 128) - 128) +# endif + +# ifndef emacs +/* How many characters in the character set. */ +# define CHAR_SET_SIZE 256 + +# ifdef SYNTAX_TABLE + +extern char *re_syntax_table; + +# else /* not SYNTAX_TABLE */ + +static char re_syntax_table[CHAR_SET_SIZE]; + +static void init_syntax_once (void); + +static void +init_syntax_once (void) +{ + register int c; + static smallint done = 0; + + if (done) + return; + bzero (re_syntax_table, sizeof re_syntax_table); + + for (c = 0; c < CHAR_SET_SIZE; ++c) + if (ISALNUM (c)) + re_syntax_table[c] = Sword; + + re_syntax_table['_'] = Sword; + + done = 1; +} + +# endif /* not SYNTAX_TABLE */ + +# define SYNTAX(c) re_syntax_table[(unsigned char) (c)] + +# endif /* emacs */ + +/* Integer type for pointers. */ +# if !defined _LIBC && !defined __intptr_t_defined +typedef unsigned long int uintptr_t; +# endif + +/* Should we use malloc or alloca? If REGEX_MALLOC is not defined, we + use `alloca' instead of `malloc'. This is because using malloc in + re_search* or re_match* could cause memory leaks when C-g is used in + Emacs; also, malloc is slower and causes storage fragmentation. On + the other hand, malloc is more portable, and easier to debug. + + Because we sometimes use alloca, some routines have to be macros, + not functions -- `alloca'-allocated space disappears at the end of the + function it is called in. */ + +# ifdef REGEX_MALLOC + +# define REGEX_ALLOCATE malloc +# define REGEX_REALLOCATE(source, osize, nsize) realloc (source, nsize) +# define REGEX_FREE free + +# else /* not REGEX_MALLOC */ + +/* Emacs already defines alloca, sometimes. */ +# ifndef alloca + +/* Make alloca work the best possible way. */ +# ifdef __GNUC__ +# define alloca __builtin_alloca +# else /* not __GNUC__ */ +# if HAVE_ALLOCA_H +# include +# endif /* HAVE_ALLOCA_H */ +# endif /* not __GNUC__ */ + +# endif /* not alloca */ + +# define REGEX_ALLOCATE alloca + +/* Assumes a `char *destination' variable. */ +# define REGEX_REALLOCATE(source, osize, nsize) \ + (destination = (char *) alloca (nsize), \ + memcpy (destination, source, osize)) + +/* No need to do anything to free, after alloca. */ +# define REGEX_FREE(arg) ((void)0) /* Do nothing! But inhibit gcc warning. */ + +# endif /* not REGEX_MALLOC */ + +/* Define how to allocate the failure stack. */ + +# if defined REL_ALLOC && defined REGEX_MALLOC + +# define REGEX_ALLOCATE_STACK(size) \ + r_alloc (&failure_stack_ptr, (size)) +# define REGEX_REALLOCATE_STACK(source, osize, nsize) \ + r_re_alloc (&failure_stack_ptr, (nsize)) +# define REGEX_FREE_STACK(ptr) \ + r_alloc_free (&failure_stack_ptr) + +# else /* not using relocating allocator */ + +# ifdef REGEX_MALLOC + +# define REGEX_ALLOCATE_STACK malloc +# define REGEX_REALLOCATE_STACK(source, osize, nsize) realloc (source, nsize) +# define REGEX_FREE_STACK free + +# else /* not REGEX_MALLOC */ + +# define REGEX_ALLOCATE_STACK alloca + +# define REGEX_REALLOCATE_STACK(source, osize, nsize) \ + REGEX_REALLOCATE (source, osize, nsize) +/* No need to explicitly free anything. */ +# define REGEX_FREE_STACK(arg) + +# endif /* not REGEX_MALLOC */ +# endif /* not using relocating allocator */ + + +/* True if `size1' is non-NULL and PTR is pointing anywhere inside + `string1' or just past its end. This works if PTR is NULL, which is + a good thing. */ +# define FIRST_STRING_P(ptr) \ + (size1 && string1 <= (ptr) && (ptr) <= string1 + size1) + +/* (Re)Allocate N items of type T using malloc, or fail. */ +# define TALLOC(n, t) ((t *) malloc ((n) * sizeof (t))) +# define RETALLOC(addr, n, t) ((addr) = (t *) realloc (addr, (n) * sizeof (t))) +# define RETALLOC_IF(addr, n, t) \ + if (addr) RETALLOC((addr), (n), t); else (addr) = TALLOC ((n), t) +# define REGEX_TALLOC(n, t) ((t *) REGEX_ALLOCATE ((n) * sizeof (t))) + +# define BYTEWIDTH 8 /* In bits. */ + +# define STREQ(s1, s2) ((strcmp (s1, s2) == 0)) + +# undef MAX +# undef MIN +# define MAX(a, b) ((a) > (b) ? (a) : (b)) +# define MIN(a, b) ((a) < (b) ? (a) : (b)) + +typedef char boolean; +# define false 0 +# define true 1 + +static reg_errcode_t byte_regex_compile (const char *pattern, size_t size, + reg_syntax_t syntax, + struct re_pattern_buffer *bufp); + +static int byte_re_match_2_internal (struct re_pattern_buffer *bufp, + const char *string1, int size1, + const char *string2, int size2, + int pos, + struct re_registers *regs, + int stop); +static int byte_re_search_2 (struct re_pattern_buffer *bufp, + const char *string1, int size1, + const char *string2, int size2, + int startpos, int range, + struct re_registers *regs, int stop); +static int byte_re_compile_fastmap (struct re_pattern_buffer *bufp); + +#ifdef MBS_SUPPORT +static reg_errcode_t wcs_regex_compile (const char *pattern, size_t size, + reg_syntax_t syntax, + struct re_pattern_buffer *bufp); + + +static int wcs_re_match_2_internal (struct re_pattern_buffer *bufp, + const char *cstring1, int csize1, + const char *cstring2, int csize2, + int pos, + struct re_registers *regs, + int stop, + wchar_t *string1, int size1, + wchar_t *string2, int size2, + int *mbs_offset1, int *mbs_offset2); +static int wcs_re_search_2 (struct re_pattern_buffer *bufp, + const char *string1, int size1, + const char *string2, int size2, + int startpos, int range, + struct re_registers *regs, int stop); +static int wcs_re_compile_fastmap (struct re_pattern_buffer *bufp); +#endif + +/* These are the command codes that appear in compiled regular + expressions. Some opcodes are followed by argument bytes. A + command code can specify any interpretation whatsoever for its + arguments. Zero bytes may appear in the compiled regular expression. */ + +typedef enum +{ + no_op = 0, + + /* Succeed right away--no more backtracking. */ + succeed, + + /* Followed by one byte giving n, then by n literal bytes. */ + exactn, + +# ifdef MBS_SUPPORT + /* Same as exactn, but contains binary data. */ + exactn_bin, +# endif + + /* Matches any (more or less) character. */ + anychar, + + /* Matches any one char belonging to specified set. First + following byte is number of bitmap bytes. Then come bytes + for a bitmap saying which chars are in. Bits in each byte + are ordered low-bit-first. A character is in the set if its + bit is 1. A character too large to have a bit in the map is + automatically not in the set. */ + /* ifdef MBS_SUPPORT, following element is length of character + classes, length of collating symbols, length of equivalence + classes, length of character ranges, and length of characters. + Next, character class element, collating symbols elements, + equivalence class elements, range elements, and character + elements follow. + See regex_compile function. */ + charset, + + /* Same parameters as charset, but match any character that is + not one of those specified. */ + charset_not, + + /* Start remembering the text that is matched, for storing in a + register. Followed by one byte with the register number, in + the range 0 to one less than the pattern buffer's re_nsub + field. Then followed by one byte with the number of groups + inner to this one. (This last has to be part of the + start_memory only because we need it in the on_failure_jump + of re_match_2.) */ + start_memory, + + /* Stop remembering the text that is matched and store it in a + memory register. Followed by one byte with the register + number, in the range 0 to one less than `re_nsub' in the + pattern buffer, and one byte with the number of inner groups, + just like `start_memory'. (We need the number of inner + groups here because we don't have any easy way of finding the + corresponding start_memory when we're at a stop_memory.) */ + stop_memory, + + /* Match a duplicate of something remembered. Followed by one + byte containing the register number. */ + duplicate, + + /* Fail unless at beginning of line. */ + begline, + + /* Fail unless at end of line. */ + endline, + + /* Succeeds if at beginning of buffer (if emacs) or at beginning + of string to be matched (if not). */ + begbuf, + + /* Analogously, for end of buffer/string. */ + endbuf, + + /* Followed by two byte relative address to which to jump. */ + jump, + + /* Same as jump, but marks the end of an alternative. */ + jump_past_alt, + + /* Followed by two-byte relative address of place to resume at + in case of failure. */ + /* ifdef MBS_SUPPORT, the size of address is 1. */ + on_failure_jump, + + /* Like on_failure_jump, but pushes a placeholder instead of the + current string position when executed. */ + on_failure_keep_string_jump, + + /* Throw away latest failure point and then jump to following + two-byte relative address. */ + /* ifdef MBS_SUPPORT, the size of address is 1. */ + pop_failure_jump, + + /* Change to pop_failure_jump if know won't have to backtrack to + match; otherwise change to jump. This is used to jump + back to the beginning of a repeat. If what follows this jump + clearly won't match what the repeat does, such that we can be + sure that there is no use backtracking out of repetitions + already matched, then we change it to a pop_failure_jump. + Followed by two-byte address. */ + /* ifdef MBS_SUPPORT, the size of address is 1. */ + maybe_pop_jump, + + /* Jump to following two-byte address, and push a dummy failure + point. This failure point will be thrown away if an attempt + is made to use it for a failure. A `+' construct makes this + before the first repeat. Also used as an intermediary kind + of jump when compiling an alternative. */ + /* ifdef MBS_SUPPORT, the size of address is 1. */ + dummy_failure_jump, + + /* Push a dummy failure point and continue. Used at the end of + alternatives. */ + push_dummy_failure, + + /* Followed by two-byte relative address and two-byte number n. + After matching N times, jump to the address upon failure. */ + /* ifdef MBS_SUPPORT, the size of address is 1. */ + succeed_n, + + /* Followed by two-byte relative address, and two-byte number n. + Jump to the address N times, then fail. */ + /* ifdef MBS_SUPPORT, the size of address is 1. */ + jump_n, + + /* Set the following two-byte relative address to the + subsequent two-byte number. The address *includes* the two + bytes of number. */ + /* ifdef MBS_SUPPORT, the size of address is 1. */ + set_number_at, + + wordchar, /* Matches any word-constituent character. */ + notwordchar, /* Matches any char that is not a word-constituent. */ + + wordbeg, /* Succeeds if at word beginning. */ + wordend, /* Succeeds if at word end. */ + + wordbound, /* Succeeds if at a word boundary. */ + notwordbound /* Succeeds if not at a word boundary. */ + +# ifdef emacs + ,before_dot, /* Succeeds if before point. */ + at_dot, /* Succeeds if at point. */ + after_dot, /* Succeeds if after point. */ + + /* Matches any character whose syntax is specified. Followed by + a byte which contains a syntax code, e.g., Sword. */ + syntaxspec, + + /* Matches any character whose syntax is not that specified. */ + notsyntaxspec +# endif /* emacs */ +} re_opcode_t; +#endif /* not INSIDE_RECURSION */ + + +#ifdef BYTE +# define CHAR_T char +# define UCHAR_T unsigned char +# define COMPILED_BUFFER_VAR bufp->buffer +# define OFFSET_ADDRESS_SIZE 2 +# define PREFIX(name) byte_##name +# define ARG_PREFIX(name) name +# define PUT_CHAR(c) putchar (c) +#else +# ifdef WCHAR +# define CHAR_T wchar_t +# define UCHAR_T wchar_t +# define COMPILED_BUFFER_VAR wc_buffer +# define OFFSET_ADDRESS_SIZE 1 /* the size which STORE_NUMBER macro use */ +# define CHAR_CLASS_SIZE ((__alignof__(wctype_t)+sizeof(wctype_t))/sizeof(CHAR_T)+1) +# define PREFIX(name) wcs_##name +# define ARG_PREFIX(name) c##name +/* Should we use wide stream?? */ +# define PUT_CHAR(c) printf ("%C", c); +# define TRUE 1 +# define FALSE 0 +# else +# ifdef MBS_SUPPORT +# define WCHAR +# define INSIDE_RECURSION +# include "regex_old.c" +# undef INSIDE_RECURSION +# endif +# define BYTE +# define INSIDE_RECURSION +# include "regex_old.c" +# undef INSIDE_RECURSION +# endif +#endif + +#ifdef INSIDE_RECURSION +/* Common operations on the compiled pattern. */ + +/* Store NUMBER in two contiguous bytes starting at DESTINATION. */ +/* ifdef MBS_SUPPORT, we store NUMBER in 1 element. */ + +# ifdef WCHAR +# define STORE_NUMBER(destination, number) \ + do { \ + *(destination) = (UCHAR_T)(number); \ + } while (0) +# else /* BYTE */ +# define STORE_NUMBER(destination, number) \ + do { \ + (destination)[0] = (number) & 0377; \ + (destination)[1] = (number) >> 8; \ + } while (0) +# endif /* WCHAR */ + +/* Same as STORE_NUMBER, except increment DESTINATION to + the byte after where the number is stored. Therefore, DESTINATION + must be an lvalue. */ +/* ifdef MBS_SUPPORT, we store NUMBER in 1 element. */ + +# define STORE_NUMBER_AND_INCR(destination, number) \ + do { \ + STORE_NUMBER (destination, number); \ + (destination) += OFFSET_ADDRESS_SIZE; \ + } while (0) + +/* Put into DESTINATION a number stored in two contiguous bytes starting + at SOURCE. */ +/* ifdef MBS_SUPPORT, we store NUMBER in 1 element. */ + +# ifdef WCHAR +# define EXTRACT_NUMBER(destination, source) \ + do { \ + (destination) = *(source); \ + } while (0) +# else /* BYTE */ +# define EXTRACT_NUMBER(destination, source) \ + do { \ + (destination) = *(source) & 0377; \ + (destination) += SIGN_EXTEND_CHAR (*((source) + 1)) << 8; \ + } while (0) +# endif + +# ifdef DEBUG +static void PREFIX(extract_number) (int *dest, UCHAR_T *source) +{ +# ifdef WCHAR + *dest = *source; +# else /* BYTE */ + int temp = SIGN_EXTEND_CHAR (*(source + 1)); + *dest = *source & 0377; + *dest += temp << 8; +# endif +} + +# ifndef EXTRACT_MACROS /* To debug the macros. */ +# undef EXTRACT_NUMBER +# define EXTRACT_NUMBER(dest, src) PREFIX(extract_number) (&dest, src) +# endif /* not EXTRACT_MACROS */ + +# endif /* DEBUG */ + +/* Same as EXTRACT_NUMBER, except increment SOURCE to after the number. + SOURCE must be an lvalue. */ + +# define EXTRACT_NUMBER_AND_INCR(destination, source) \ + do { \ + EXTRACT_NUMBER (destination, source); \ + (source) += OFFSET_ADDRESS_SIZE; \ + } while (0) + +# ifdef DEBUG +static void PREFIX(extract_number_and_incr) (int *destination, + UCHAR_T **source) +{ + PREFIX(extract_number) (destination, *source); + *source += OFFSET_ADDRESS_SIZE; +} + +# ifndef EXTRACT_MACROS +# undef EXTRACT_NUMBER_AND_INCR +# define EXTRACT_NUMBER_AND_INCR(dest, src) \ + PREFIX(extract_number_and_incr) (&dest, &src) +# endif /* not EXTRACT_MACROS */ + +# endif /* DEBUG */ + + + +/* If DEBUG is defined, Regex prints many voluminous messages about what + it is doing (if the variable `debug' is nonzero). If linked with the + main program in `iregex.c', you can enter patterns and strings + interactively. And if linked with the main program in `main.c' and + the other test files, you can run the already-written tests. */ + +# ifdef DEBUG + +# ifndef DEFINED_ONCE + +/* We use standard I/O for debugging. */ +# include + +/* It is useful to test things that ``must'' be true when debugging. */ +# include + +static smallint debug; + +# define DEBUG_STATEMENT(e) e +# define DEBUG_PRINT1(x) if (debug) printf (x) +# define DEBUG_PRINT2(x1, x2) if (debug) printf (x1, x2) +# define DEBUG_PRINT3(x1, x2, x3) if (debug) printf (x1, x2, x3) +# define DEBUG_PRINT4(x1, x2, x3, x4) if (debug) printf (x1, x2, x3, x4) +# endif /* not DEFINED_ONCE */ + +# define DEBUG_PRINT_COMPILED_PATTERN(p, s, e) \ + if (debug) PREFIX(print_partial_compiled_pattern) (s, e) +# define DEBUG_PRINT_DOUBLE_STRING(w, s1, sz1, s2, sz2) \ + if (debug) PREFIX(print_double_string) (w, s1, sz1, s2, sz2) + + +/* Print the fastmap in human-readable form. */ + +# ifndef DEFINED_ONCE +void +print_fastmap (char *fastmap) +{ + unsigned was_a_range = 0; + unsigned i = 0; + + while (i < (1 << BYTEWIDTH)) + { + if (fastmap[i++]) + { + was_a_range = 0; + putchar (i - 1); + while (i < (1 << BYTEWIDTH) && fastmap[i]) + { + was_a_range = 1; + i++; + } + if (was_a_range) + { + printf ("-"); + putchar (i - 1); + } + } + } + putchar ('\n'); +} +# endif /* not DEFINED_ONCE */ + + +/* Print a compiled pattern string in human-readable form, starting at + the START pointer into it and ending just before the pointer END. */ + +void +PREFIX(print_partial_compiled_pattern) (UCHAR_T *start, UCHAR_T *end) +{ + int mcnt, mcnt2; + UCHAR_T *p1; + UCHAR_T *p = start; + UCHAR_T *pend = end; + + if (start == NULL) + { + printf ("(null)\n"); + return; + } + + /* Loop over pattern commands. */ + while (p < pend) + { +# ifdef _LIBC + printf ("%td:\t", p - start); +# else + printf ("%ld:\t", (long int) (p - start)); +# endif + + switch ((re_opcode_t) *p++) + { + case no_op: + printf ("/no_op"); + break; + + case exactn: + mcnt = *p++; + printf ("/exactn/%d", mcnt); + do + { + putchar ('/'); + PUT_CHAR (*p++); + } + while (--mcnt); + break; + +# ifdef MBS_SUPPORT + case exactn_bin: + mcnt = *p++; + printf ("/exactn_bin/%d", mcnt); + do + { + printf("/%lx", (long int) *p++); + } + while (--mcnt); + break; +# endif /* MBS_SUPPORT */ + + case start_memory: + mcnt = *p++; + printf ("/start_memory/%d/%ld", mcnt, (long int) *p++); + break; + + case stop_memory: + mcnt = *p++; + printf ("/stop_memory/%d/%ld", mcnt, (long int) *p++); + break; + + case duplicate: + printf ("/duplicate/%ld", (long int) *p++); + break; + + case anychar: + printf ("/anychar"); + break; + + case charset: + case charset_not: + { +# ifdef WCHAR + int i, length; + wchar_t *workp = p; + printf ("/charset [%s", + (re_opcode_t) *(workp - 1) == charset_not ? "^" : ""); + p += 5; + length = *workp++; /* the length of char_classes */ + for (i=0 ; ibuffer; + + PREFIX(print_partial_compiled_pattern) (buffer, buffer + + bufp->used / sizeof(UCHAR_T)); + printf ("%ld bytes used/%ld bytes allocated.\n", + bufp->used, bufp->allocated); + + if (bufp->fastmap_accurate && bufp->fastmap) + { + printf ("fastmap: "); + print_fastmap (bufp->fastmap); + } + +# ifdef _LIBC + printf ("re_nsub: %Zd\t", bufp->re_nsub); +# else + printf ("re_nsub: %ld\t", (long int) bufp->re_nsub); +# endif + printf ("regs_alloc: %d\t", bufp->regs_allocated); + printf ("can_be_null: %d\t", bufp->can_be_null); + printf ("newline_anchor: %d\n", bufp->newline_anchor); + printf ("no_sub: %d\t", bufp->no_sub); + printf ("not_bol: %d\t", bufp->not_bol); + printf ("not_eol: %d\t", bufp->not_eol); + printf ("syntax: %lx\n", bufp->syntax); + /* Perhaps we should print the translate table? */ +} + + +void +PREFIX(print_double_string) ( + const CHAR_T *where, + const CHAR_T *string1, + int size1, + const CHAR_T *string2, + int size2) +{ + int this_char; + + if (where == NULL) + printf ("(null)"); + else + { + int cnt; + + if (FIRST_STRING_P (where)) + { + for (this_char = where - string1; this_char < size1; this_char++) + PUT_CHAR (string1[this_char]); + + where = string2; + } + + cnt = 0; + for (this_char = where - string2; this_char < size2; this_char++) + { + PUT_CHAR (string2[this_char]); + if (++cnt > 100) + { + fputs ("...", stdout); + break; + } + } + } +} + +# ifndef DEFINED_ONCE +void +printchar (int c) +{ + putc (c, stderr); +} +# endif + +# else /* not DEBUG */ + +# ifndef DEFINED_ONCE +# undef assert +# define assert(e) + +# define DEBUG_STATEMENT(e) +# define DEBUG_PRINT1(x) +# define DEBUG_PRINT2(x1, x2) +# define DEBUG_PRINT3(x1, x2, x3) +# define DEBUG_PRINT4(x1, x2, x3, x4) +# endif /* not DEFINED_ONCE */ +# define DEBUG_PRINT_COMPILED_PATTERN(p, s, e) +# define DEBUG_PRINT_DOUBLE_STRING(w, s1, sz1, s2, sz2) + +# endif /* not DEBUG */ + + + +# ifdef WCHAR +/* This convert a multibyte string to a wide character string. + And write their correspondances to offset_buffer(see below) + and write whether each wchar_t is binary data to is_binary. + This assume invalid multibyte sequences as binary data. + We assume offset_buffer and is_binary is already allocated + enough space. */ + +static size_t +convert_mbs_to_wcs ( + CHAR_T *dest, + const unsigned char* src, + size_t len, /* the length of multibyte string. */ + + /* It hold correspondances between src(char string) and + dest(wchar_t string) for optimization. + e.g. src = "xxxyzz" + dest = {'X', 'Y', 'Z'} + (each "xxx", "y" and "zz" represent one multibyte character + corresponding to 'X', 'Y' and 'Z'.) + offset_buffer = {0, 0+3("xxx"), 0+3+1("y"), 0+3+1+2("zz")} + = {0, 3, 4, 6} + */ + int *offset_buffer, + char *is_binary) +{ + wchar_t *pdest = dest; + const unsigned char *psrc = src; + size_t wc_count = 0; + + mbstate_t mbs; + int i, consumed; + size_t mb_remain = len; + size_t mb_count = 0; + + /* Initialize the conversion state. */ + memset (&mbs, 0, sizeof (mbstate_t)); + + offset_buffer[0] = 0; + for( ; mb_remain > 0 ; ++wc_count, ++pdest, mb_remain -= consumed, + psrc += consumed) + { +#ifdef _LIBC + consumed = __mbrtowc (pdest, psrc, mb_remain, &mbs); +#else + consumed = mbrtowc (pdest, psrc, mb_remain, &mbs); +#endif + + if (consumed <= 0) + /* failed to convert. maybe src contains binary data. + So we consume 1 byte manualy. */ + { + *pdest = *psrc; + consumed = 1; + is_binary[wc_count] = TRUE; + } + else + is_binary[wc_count] = FALSE; + /* In sjis encoding, we use yen sign as escape character in + place of reverse solidus. So we convert 0x5c(yen sign in + sjis) to not 0xa5(yen sign in UCS2) but 0x5c(reverse + solidus in UCS2). */ + if (consumed == 1 && (int) *psrc == 0x5c && (int) *pdest == 0xa5) + *pdest = (wchar_t) *psrc; + + offset_buffer[wc_count + 1] = mb_count += consumed; + } + + /* Fill remain of the buffer with sentinel. */ + for (i = wc_count + 1 ; i <= len ; i++) + offset_buffer[i] = mb_count + 1; + + return wc_count; +} + +# endif /* WCHAR */ + +#else /* not INSIDE_RECURSION */ + +/* Set by `re_set_syntax' to the current regexp syntax to recognize. Can + also be assigned to arbitrarily: each pattern buffer stores its own + syntax, so it can be changed between regex compilations. */ +/* This has no initializer because initialized variables in Emacs + become read-only after dumping. */ +reg_syntax_t re_syntax_options; + + +/* Specify the precise syntax of regexps for compilation. This provides + for compatibility for various utilities which historically have + different, incompatible syntaxes. + + The argument SYNTAX is a bit mask comprised of the various bits + defined in regex.h. We return the old syntax. */ + +reg_syntax_t +re_set_syntax (reg_syntax_t syntax) +{ + reg_syntax_t ret = re_syntax_options; + + re_syntax_options = syntax; +# ifdef DEBUG + if (syntax & RE_DEBUG) + debug = 1; + else if (debug) /* was on but now is not */ + debug = 0; +# endif /* DEBUG */ + return ret; +} + +/* This table gives an error message for each of the error codes listed + in regex.h. Obviously the order here has to be same as there. + POSIX doesn't require that we do anything for REG_NOERROR, + but why not be nice? */ + +static const char re_error_msgid[] = + { +# define REG_NOERROR_IDX 0 + gettext_noop ("Success") /* REG_NOERROR */ + "\0" +# define REG_NOMATCH_IDX (REG_NOERROR_IDX + sizeof "Success") + gettext_noop ("No match") /* REG_NOMATCH */ + "\0" +# define REG_BADPAT_IDX (REG_NOMATCH_IDX + sizeof "No match") + gettext_noop ("Invalid regular expression") /* REG_BADPAT */ + "\0" +# define REG_ECOLLATE_IDX (REG_BADPAT_IDX + sizeof "Invalid regular expression") + gettext_noop ("Invalid collation character") /* REG_ECOLLATE */ + "\0" +# define REG_ECTYPE_IDX (REG_ECOLLATE_IDX + sizeof "Invalid collation character") + gettext_noop ("Invalid character class name") /* REG_ECTYPE */ + "\0" +# define REG_EESCAPE_IDX (REG_ECTYPE_IDX + sizeof "Invalid character class name") + gettext_noop ("Trailing backslash") /* REG_EESCAPE */ + "\0" +# define REG_ESUBREG_IDX (REG_EESCAPE_IDX + sizeof "Trailing backslash") + gettext_noop ("Invalid back reference") /* REG_ESUBREG */ + "\0" +# define REG_EBRACK_IDX (REG_ESUBREG_IDX + sizeof "Invalid back reference") + gettext_noop ("Unmatched [ or [^") /* REG_EBRACK */ + "\0" +# define REG_EPAREN_IDX (REG_EBRACK_IDX + sizeof "Unmatched [ or [^") + gettext_noop ("Unmatched ( or \\(") /* REG_EPAREN */ + "\0" +# define REG_EBRACE_IDX (REG_EPAREN_IDX + sizeof "Unmatched ( or \\(") + gettext_noop ("Unmatched \\{") /* REG_EBRACE */ + "\0" +# define REG_BADBR_IDX (REG_EBRACE_IDX + sizeof "Unmatched \\{") + gettext_noop ("Invalid content of \\{\\}") /* REG_BADBR */ + "\0" +# define REG_ERANGE_IDX (REG_BADBR_IDX + sizeof "Invalid content of \\{\\}") + gettext_noop ("Invalid range end") /* REG_ERANGE */ + "\0" +# define REG_ESPACE_IDX (REG_ERANGE_IDX + sizeof "Invalid range end") + gettext_noop ("Memory exhausted") /* REG_ESPACE */ + "\0" +# define REG_BADRPT_IDX (REG_ESPACE_IDX + sizeof "Memory exhausted") + gettext_noop ("Invalid preceding regular expression") /* REG_BADRPT */ + "\0" +# define REG_EEND_IDX (REG_BADRPT_IDX + sizeof "Invalid preceding regular expression") + gettext_noop ("Premature end of regular expression") /* REG_EEND */ + "\0" +# define REG_ESIZE_IDX (REG_EEND_IDX + sizeof "Premature end of regular expression") + gettext_noop ("Regular expression too big") /* REG_ESIZE */ + "\0" +# define REG_ERPAREN_IDX (REG_ESIZE_IDX + sizeof "Regular expression too big") + gettext_noop ("Unmatched ) or \\)") /* REG_ERPAREN */ + }; + +static const uint16_t re_error_msgid_idx[] = + { + REG_NOERROR_IDX, + REG_NOMATCH_IDX, + REG_BADPAT_IDX, + REG_ECOLLATE_IDX, + REG_ECTYPE_IDX, + REG_EESCAPE_IDX, + REG_ESUBREG_IDX, + REG_EBRACK_IDX, + REG_EPAREN_IDX, + REG_EBRACE_IDX, + REG_BADBR_IDX, + REG_ERANGE_IDX, + REG_ESPACE_IDX, + REG_BADRPT_IDX, + REG_EEND_IDX, + REG_ESIZE_IDX, + REG_ERPAREN_IDX + }; + +#endif /* INSIDE_RECURSION */ + +#ifndef DEFINED_ONCE +/* Avoiding alloca during matching, to placate r_alloc. */ + +/* Define MATCH_MAY_ALLOCATE unless we need to make sure that the + searching and matching functions should not call alloca. On some + systems, alloca is implemented in terms of malloc, and if we're + using the relocating allocator routines, then malloc could cause a + relocation, which might (if the strings being searched are in the + ralloc heap) shift the data out from underneath the regexp + routines. + + Here's another reason to avoid allocation: Emacs + processes input from X in a signal handler; processing X input may + call malloc; if input arrives while a matching routine is calling + malloc, then we're scrod. But Emacs can't just block input while + calling matching routines; then we don't notice interrupts when + they come in. So, Emacs blocks input around all regexp calls + except the matching calls, which it leaves unprotected, in the + faith that they will not malloc. */ + +/* Normally, this is fine. */ +# define MATCH_MAY_ALLOCATE + +/* When using GNU C, we are not REALLY using the C alloca, no matter + what config.h may say. So don't take precautions for it. */ +# ifdef __GNUC__ +# undef C_ALLOCA +# endif + +/* The match routines may not allocate if (1) they would do it with malloc + and (2) it's not safe for them to use malloc. + Note that if REL_ALLOC is defined, matching would not use malloc for the + failure stack, but we would still use it for the register vectors; + so REL_ALLOC should not affect this. */ +# if (defined C_ALLOCA || defined REGEX_MALLOC) && defined emacs +# undef MATCH_MAY_ALLOCATE +# endif +#endif /* not DEFINED_ONCE */ + +#ifdef INSIDE_RECURSION +/* Failure stack declarations and macros; both re_compile_fastmap and + re_match_2 use a failure stack. These have to be macros because of + REGEX_ALLOCATE_STACK. */ + + +/* Number of failure points for which to initially allocate space + when matching. If this number is exceeded, we allocate more + space, so it is not a hard limit. */ +# ifndef INIT_FAILURE_ALLOC +# define INIT_FAILURE_ALLOC 5 +# endif + +/* Roughly the maximum number of failure points on the stack. Would be + exactly that if always used MAX_FAILURE_ITEMS items each time we failed. + This is a variable only so users of regex can assign to it; we never + change it ourselves. */ + +# ifdef INT_IS_16BIT + +# ifndef DEFINED_ONCE +# if defined MATCH_MAY_ALLOCATE +/* 4400 was enough to cause a crash on Alpha OSF/1, + whose default stack limit is 2mb. */ +long int re_max_failures = 4000; +# else +long int re_max_failures = 2000; +# endif +# endif + +union PREFIX(fail_stack_elt) +{ + UCHAR_T *pointer; + long int integer; +}; + +typedef union PREFIX(fail_stack_elt) PREFIX(fail_stack_elt_t); + +typedef struct +{ + PREFIX(fail_stack_elt_t) *stack; + unsigned long int size; + unsigned long int avail; /* Offset of next open position. */ +} PREFIX(fail_stack_type); + +# else /* not INT_IS_16BIT */ + +# ifndef DEFINED_ONCE +# if defined MATCH_MAY_ALLOCATE +/* 4400 was enough to cause a crash on Alpha OSF/1, + whose default stack limit is 2mb. */ +int re_max_failures = 4000; +# else +int re_max_failures = 2000; +# endif +# endif + +union PREFIX(fail_stack_elt) +{ + UCHAR_T *pointer; + int integer; +}; + +typedef union PREFIX(fail_stack_elt) PREFIX(fail_stack_elt_t); + +typedef struct +{ + PREFIX(fail_stack_elt_t) *stack; + unsigned size; + unsigned avail; /* Offset of next open position. */ +} PREFIX(fail_stack_type); + +# endif /* INT_IS_16BIT */ + +# ifndef DEFINED_ONCE +# define FAIL_STACK_EMPTY() (fail_stack.avail == 0) +# define FAIL_STACK_PTR_EMPTY() (fail_stack_ptr->avail == 0) +# define FAIL_STACK_FULL() (fail_stack.avail == fail_stack.size) +# endif + + +/* Define macros to initialize and free the failure stack. + Do `return -2' if the alloc fails. */ + +# ifdef MATCH_MAY_ALLOCATE +# define INIT_FAIL_STACK() \ + do { \ + fail_stack.stack = (PREFIX(fail_stack_elt_t) *) \ + REGEX_ALLOCATE_STACK (INIT_FAILURE_ALLOC * sizeof (PREFIX(fail_stack_elt_t))); \ + \ + if (fail_stack.stack == NULL) \ + return -2; \ + \ + fail_stack.size = INIT_FAILURE_ALLOC; \ + fail_stack.avail = 0; \ + } while (0) + +# define RESET_FAIL_STACK() REGEX_FREE_STACK (fail_stack.stack) +# else +# define INIT_FAIL_STACK() \ + do { \ + fail_stack.avail = 0; \ + } while (0) + +# define RESET_FAIL_STACK() +# endif + + +/* Double the size of FAIL_STACK, up to approximately `re_max_failures' items. + + Return 1 if succeeds, and 0 if either ran out of memory + allocating space for it or it was already too large. + + REGEX_REALLOCATE_STACK requires `destination' be declared. */ + +# define DOUBLE_FAIL_STACK(fail_stack) \ + ((fail_stack).size > (unsigned) (re_max_failures * MAX_FAILURE_ITEMS) \ + ? 0 \ + : ((fail_stack).stack = (PREFIX(fail_stack_elt_t) *) \ + REGEX_REALLOCATE_STACK ((fail_stack).stack, \ + (fail_stack).size * sizeof (PREFIX(fail_stack_elt_t)), \ + ((fail_stack).size << 1) * sizeof (PREFIX(fail_stack_elt_t))),\ + \ + (fail_stack).stack == NULL \ + ? 0 \ + : ((fail_stack).size <<= 1, \ + 1))) + + +/* Push pointer POINTER on FAIL_STACK. + Return 1 if was able to do so and 0 if ran out of memory allocating + space to do so. */ +# define PUSH_PATTERN_OP(POINTER, FAIL_STACK) \ + ((FAIL_STACK_FULL () \ + && !DOUBLE_FAIL_STACK (FAIL_STACK)) \ + ? 0 \ + : ((FAIL_STACK).stack[(FAIL_STACK).avail++].pointer = POINTER, \ + 1)) + +/* Push a pointer value onto the failure stack. + Assumes the variable `fail_stack'. Probably should only + be called from within `PUSH_FAILURE_POINT'. */ +# define PUSH_FAILURE_POINTER(item) \ + fail_stack.stack[fail_stack.avail++].pointer = (UCHAR_T *) (item) + +/* This pushes an integer-valued item onto the failure stack. + Assumes the variable `fail_stack'. Probably should only + be called from within `PUSH_FAILURE_POINT'. */ +# define PUSH_FAILURE_INT(item) \ + fail_stack.stack[fail_stack.avail++].integer = (item) + +/* Push a fail_stack_elt_t value onto the failure stack. + Assumes the variable `fail_stack'. Probably should only + be called from within `PUSH_FAILURE_POINT'. */ +# define PUSH_FAILURE_ELT(item) \ + fail_stack.stack[fail_stack.avail++] = (item) + +/* These three POP... operations complement the three PUSH... operations. + All assume that `fail_stack' is nonempty. */ +# define POP_FAILURE_POINTER() fail_stack.stack[--fail_stack.avail].pointer +# define POP_FAILURE_INT() fail_stack.stack[--fail_stack.avail].integer +# define POP_FAILURE_ELT() fail_stack.stack[--fail_stack.avail] + +/* Used to omit pushing failure point id's when we're not debugging. */ +# ifdef DEBUG +# define DEBUG_PUSH PUSH_FAILURE_INT +# define DEBUG_POP(item_addr) *(item_addr) = POP_FAILURE_INT () +# else +# define DEBUG_PUSH(item) +# define DEBUG_POP(item_addr) +# endif + + +/* Push the information about the state we will need + if we ever fail back to it. + + Requires variables fail_stack, regstart, regend, reg_info, and + num_regs_pushed be declared. DOUBLE_FAIL_STACK requires `destination' + be declared. + + Does `return FAILURE_CODE' if runs out of memory. */ + +# define PUSH_FAILURE_POINT(pattern_place, string_place, failure_code) \ + do { \ + char *destination; \ + /* Must be int, so when we don't save any registers, the arithmetic \ + of 0 + -1 isn't done as unsigned. */ \ + /* Can't be int, since there is not a shred of a guarantee that int \ + is wide enough to hold a value of something to which pointer can \ + be assigned */ \ + active_reg_t this_reg; \ + \ + DEBUG_STATEMENT (failure_id++); \ + DEBUG_STATEMENT (nfailure_points_pushed++); \ + DEBUG_PRINT2 ("\nPUSH_FAILURE_POINT #%u:\n", failure_id); \ + DEBUG_PRINT2 (" Before push, next avail: %d\n", (fail_stack).avail);\ + DEBUG_PRINT2 (" size: %d\n", (fail_stack).size);\ + \ + DEBUG_PRINT2 (" slots needed: %ld\n", NUM_FAILURE_ITEMS); \ + DEBUG_PRINT2 (" available: %d\n", REMAINING_AVAIL_SLOTS); \ + \ + /* Ensure we have enough space allocated for what we will push. */ \ + while (REMAINING_AVAIL_SLOTS < NUM_FAILURE_ITEMS) \ + { \ + if (!DOUBLE_FAIL_STACK (fail_stack)) \ + return failure_code; \ + \ + DEBUG_PRINT2 ("\n Doubled stack; size now: %d\n", \ + (fail_stack).size); \ + DEBUG_PRINT2 (" slots available: %d\n", REMAINING_AVAIL_SLOTS);\ + } \ + \ + /* Push the info, starting with the registers. */ \ + DEBUG_PRINT1 ("\n"); \ + \ + if (1) \ + for (this_reg = lowest_active_reg; this_reg <= highest_active_reg; \ + this_reg++) \ + { \ + DEBUG_PRINT2 (" Pushing reg: %lu\n", this_reg); \ + DEBUG_STATEMENT (num_regs_pushed++); \ + \ + DEBUG_PRINT2 (" start: %p\n", regstart[this_reg]); \ + PUSH_FAILURE_POINTER (regstart[this_reg]); \ + \ + DEBUG_PRINT2 (" end: %p\n", regend[this_reg]); \ + PUSH_FAILURE_POINTER (regend[this_reg]); \ + \ + DEBUG_PRINT2 (" info: %p\n ", \ + reg_info[this_reg].word.pointer); \ + DEBUG_PRINT2 (" match_null=%d", \ + REG_MATCH_NULL_STRING_P (reg_info[this_reg])); \ + DEBUG_PRINT2 (" active=%d", IS_ACTIVE (reg_info[this_reg])); \ + DEBUG_PRINT2 (" matched_something=%d", \ + MATCHED_SOMETHING (reg_info[this_reg])); \ + DEBUG_PRINT2 (" ever_matched=%d", \ + EVER_MATCHED_SOMETHING (reg_info[this_reg])); \ + DEBUG_PRINT1 ("\n"); \ + PUSH_FAILURE_ELT (reg_info[this_reg].word); \ + } \ + \ + DEBUG_PRINT2 (" Pushing low active reg: %ld\n", lowest_active_reg);\ + PUSH_FAILURE_INT (lowest_active_reg); \ + \ + DEBUG_PRINT2 (" Pushing high active reg: %ld\n", highest_active_reg);\ + PUSH_FAILURE_INT (highest_active_reg); \ + \ + DEBUG_PRINT2 (" Pushing pattern %p:\n", pattern_place); \ + DEBUG_PRINT_COMPILED_PATTERN (bufp, pattern_place, pend); \ + PUSH_FAILURE_POINTER (pattern_place); \ + \ + DEBUG_PRINT2 (" Pushing string %p: `", string_place); \ + DEBUG_PRINT_DOUBLE_STRING (string_place, string1, size1, string2, \ + size2); \ + DEBUG_PRINT1 ("'\n"); \ + PUSH_FAILURE_POINTER (string_place); \ + \ + DEBUG_PRINT2 (" Pushing failure id: %u\n", failure_id); \ + DEBUG_PUSH (failure_id); \ + } while (0) + +# ifndef DEFINED_ONCE +/* This is the number of items that are pushed and popped on the stack + for each register. */ +# define NUM_REG_ITEMS 3 + +/* Individual items aside from the registers. */ +# ifdef DEBUG +# define NUM_NONREG_ITEMS 5 /* Includes failure point id. */ +# else +# define NUM_NONREG_ITEMS 4 +# endif + +/* We push at most this many items on the stack. */ +/* We used to use (num_regs - 1), which is the number of registers + this regexp will save; but that was changed to 5 + to avoid stack overflow for a regexp with lots of parens. */ +# define MAX_FAILURE_ITEMS (5 * NUM_REG_ITEMS + NUM_NONREG_ITEMS) + +/* We actually push this many items. */ +# define NUM_FAILURE_ITEMS \ + (((0 \ + ? 0 : highest_active_reg - lowest_active_reg + 1) \ + * NUM_REG_ITEMS) \ + + NUM_NONREG_ITEMS) + +/* How many items can still be added to the stack without overflowing it. */ +# define REMAINING_AVAIL_SLOTS ((fail_stack).size - (fail_stack).avail) +# endif /* not DEFINED_ONCE */ + + +/* Pops what PUSH_FAIL_STACK pushes. + + We restore into the parameters, all of which should be lvalues: + STR -- the saved data position. + PAT -- the saved pattern position. + LOW_REG, HIGH_REG -- the highest and lowest active registers. + REGSTART, REGEND -- arrays of string positions. + REG_INFO -- array of information about each subexpression. + + Also assumes the variables `fail_stack' and (if debugging), `bufp', + `pend', `string1', `size1', `string2', and `size2'. */ +# define POP_FAILURE_POINT(str, pat, low_reg, high_reg, regstart, regend, reg_info)\ +{ \ + DEBUG_STATEMENT (unsigned failure_id;) \ + active_reg_t this_reg; \ + const UCHAR_T *string_temp; \ + \ + assert (!FAIL_STACK_EMPTY ()); \ + \ + /* Remove failure points and point to how many regs pushed. */ \ + DEBUG_PRINT1 ("POP_FAILURE_POINT:\n"); \ + DEBUG_PRINT2 (" Before pop, next avail: %d\n", fail_stack.avail); \ + DEBUG_PRINT2 (" size: %d\n", fail_stack.size); \ + \ + assert (fail_stack.avail >= NUM_NONREG_ITEMS); \ + \ + DEBUG_POP (&failure_id); \ + DEBUG_PRINT2 (" Popping failure id: %u\n", failure_id); \ + \ + /* If the saved string location is NULL, it came from an \ + on_failure_keep_string_jump opcode, and we want to throw away the \ + saved NULL, thus retaining our current position in the string. */ \ + string_temp = POP_FAILURE_POINTER (); \ + if (string_temp != NULL) \ + str = (const CHAR_T *) string_temp; \ + \ + DEBUG_PRINT2 (" Popping string %p: `", str); \ + DEBUG_PRINT_DOUBLE_STRING (str, string1, size1, string2, size2); \ + DEBUG_PRINT1 ("'\n"); \ + \ + pat = (UCHAR_T *) POP_FAILURE_POINTER (); \ + DEBUG_PRINT2 (" Popping pattern %p:\n", pat); \ + DEBUG_PRINT_COMPILED_PATTERN (bufp, pat, pend); \ + \ + /* Restore register info. */ \ + high_reg = (active_reg_t) POP_FAILURE_INT (); \ + DEBUG_PRINT2 (" Popping high active reg: %ld\n", high_reg); \ + \ + low_reg = (active_reg_t) POP_FAILURE_INT (); \ + DEBUG_PRINT2 (" Popping low active reg: %ld\n", low_reg); \ + \ + if (1) \ + for (this_reg = high_reg; this_reg >= low_reg; this_reg--) \ + { \ + DEBUG_PRINT2 (" Popping reg: %ld\n", this_reg); \ + \ + reg_info[this_reg].word = POP_FAILURE_ELT (); \ + DEBUG_PRINT2 (" info: %p\n", \ + reg_info[this_reg].word.pointer); \ + \ + regend[this_reg] = (const CHAR_T *) POP_FAILURE_POINTER (); \ + DEBUG_PRINT2 (" end: %p\n", regend[this_reg]); \ + \ + regstart[this_reg] = (const CHAR_T *) POP_FAILURE_POINTER (); \ + DEBUG_PRINT2 (" start: %p\n", regstart[this_reg]); \ + } \ + else \ + { \ + for (this_reg = highest_active_reg; this_reg > high_reg; this_reg--) \ + { \ + reg_info[this_reg].word.integer = 0; \ + regend[this_reg] = 0; \ + regstart[this_reg] = 0; \ + } \ + highest_active_reg = high_reg; \ + } \ + \ + set_regs_matched_done = 0; \ + DEBUG_STATEMENT (nfailure_points_popped++); \ +} /* POP_FAILURE_POINT */ + +/* Structure for per-register (a.k.a. per-group) information. + Other register information, such as the + starting and ending positions (which are addresses), and the list of + inner groups (which is a bits list) are maintained in separate + variables. + + We are making a (strictly speaking) nonportable assumption here: that + the compiler will pack our bit fields into something that fits into + the type of `word', i.e., is something that fits into one item on the + failure stack. */ + + +/* Declarations and macros for re_match_2. */ + +typedef union +{ + PREFIX(fail_stack_elt_t) word; + struct + { + /* This field is one if this group can match the empty string, + zero if not. If not yet determined, `MATCH_NULL_UNSET_VALUE'. */ +# define MATCH_NULL_UNSET_VALUE 3 + unsigned match_null_string_p : 2; + unsigned is_active : 1; + unsigned matched_something : 1; + unsigned ever_matched_something : 1; + } bits; +} PREFIX(register_info_type); + +# ifndef DEFINED_ONCE +# define REG_MATCH_NULL_STRING_P(R) ((R).bits.match_null_string_p) +# define IS_ACTIVE(R) ((R).bits.is_active) +# define MATCHED_SOMETHING(R) ((R).bits.matched_something) +# define EVER_MATCHED_SOMETHING(R) ((R).bits.ever_matched_something) + + +/* Call this when have matched a real character; it sets `matched' flags + for the subexpressions which we are currently inside. Also records + that those subexprs have matched. */ +# define SET_REGS_MATCHED() \ + do \ + { \ + if (!set_regs_matched_done) \ + { \ + active_reg_t r; \ + set_regs_matched_done = 1; \ + for (r = lowest_active_reg; r <= highest_active_reg; r++) \ + { \ + MATCHED_SOMETHING (reg_info[r]) \ + = EVER_MATCHED_SOMETHING (reg_info[r]) \ + = 1; \ + } \ + } \ + } \ + while (0) +# endif /* not DEFINED_ONCE */ + +/* Registers are set to a sentinel when they haven't yet matched. */ +static CHAR_T PREFIX(reg_unset_dummy); +# define REG_UNSET_VALUE (&PREFIX(reg_unset_dummy)) +# define REG_UNSET(e) ((e) == REG_UNSET_VALUE) + +/* Subroutine declarations and macros for regex_compile. */ +static void PREFIX(store_op1) (re_opcode_t op, UCHAR_T *loc, int arg); +static void PREFIX(store_op2) (re_opcode_t op, UCHAR_T *loc, + int arg1, int arg2); +static void PREFIX(insert_op1) (re_opcode_t op, UCHAR_T *loc, + int arg, UCHAR_T *end); +static void PREFIX(insert_op2) (re_opcode_t op, UCHAR_T *loc, + int arg1, int arg2, UCHAR_T *end); +static boolean PREFIX(at_begline_loc_p) (const CHAR_T *pattern, + const CHAR_T *p, + reg_syntax_t syntax); +static boolean PREFIX(at_endline_loc_p) (const CHAR_T *p, + const CHAR_T *pend, + reg_syntax_t syntax); +# ifdef WCHAR +static reg_errcode_t wcs_compile_range (CHAR_T range_start, + const CHAR_T **p_ptr, + const CHAR_T *pend, + char *translate, + reg_syntax_t syntax, + UCHAR_T *b, + CHAR_T *char_set); +static void insert_space (int num, CHAR_T *loc, CHAR_T *end); +# else /* BYTE */ +static reg_errcode_t byte_compile_range (unsigned int range_start, + const char **p_ptr, + const char *pend, + char *translate, + reg_syntax_t syntax, + unsigned char *b); +# endif /* WCHAR */ + +/* Fetch the next character in the uncompiled pattern---translating it + if necessary. Also cast from a signed character in the constant + string passed to us by the user to an unsigned char that we can use + as an array index (in, e.g., `translate'). */ +/* ifdef MBS_SUPPORT, we translate only if character <= 0xff, + because it is impossible to allocate 4GB array for some encodings + which have 4 byte character_set like UCS4. */ +# ifndef PATFETCH +# ifdef WCHAR +# define PATFETCH(c) \ + do {if (p == pend) return REG_EEND; \ + c = (UCHAR_T) *p++; \ + if (translate && (c <= 0xff)) c = (UCHAR_T) translate[c]; \ + } while (0) +# else /* BYTE */ +# define PATFETCH(c) \ + do {if (p == pend) return REG_EEND; \ + c = (unsigned char) *p++; \ + if (translate) c = (unsigned char) translate[c]; \ + } while (0) +# endif /* WCHAR */ +# endif + +/* Fetch the next character in the uncompiled pattern, with no + translation. */ +# define PATFETCH_RAW(c) \ + do {if (p == pend) return REG_EEND; \ + c = (UCHAR_T) *p++; \ + } while (0) + +/* Go backwards one character in the pattern. */ +# define PATUNFETCH p-- + + +/* If `translate' is non-null, return translate[D], else just D. We + cast the subscript to translate because some data is declared as + `char *', to avoid warnings when a string constant is passed. But + when we use a character as a subscript we must make it unsigned. */ +/* ifdef MBS_SUPPORT, we translate only if character <= 0xff, + because it is impossible to allocate 4GB array for some encodings + which have 4 byte character_set like UCS4. */ + +# ifndef TRANSLATE +# ifdef WCHAR +# define TRANSLATE(d) \ + ((translate && ((UCHAR_T) (d)) <= 0xff) \ + ? (char) translate[(unsigned char) (d)] : (d)) +# else /* BYTE */ +# define TRANSLATE(d) \ + (translate ? (char) translate[(unsigned char) (d)] : (d)) +# endif /* WCHAR */ +# endif + + +/* Macros for outputting the compiled pattern into `buffer'. */ + +/* If the buffer isn't allocated when it comes in, use this. */ +# define INIT_BUF_SIZE (32 * sizeof(UCHAR_T)) + +/* Make sure we have at least N more bytes of space in buffer. */ +# ifdef WCHAR +# define GET_BUFFER_SPACE(n) \ + while (((unsigned long)b - (unsigned long)COMPILED_BUFFER_VAR \ + + (n)*sizeof(CHAR_T)) > bufp->allocated) \ + EXTEND_BUFFER () +# else /* BYTE */ +# define GET_BUFFER_SPACE(n) \ + while ((unsigned long) (b - bufp->buffer + (n)) > bufp->allocated) \ + EXTEND_BUFFER () +# endif /* WCHAR */ + +/* Make sure we have one more byte of buffer space and then add C to it. */ +# define BUF_PUSH(c) \ + do { \ + GET_BUFFER_SPACE (1); \ + *b++ = (UCHAR_T) (c); \ + } while (0) + + +/* Ensure we have two more bytes of buffer space and then append C1 and C2. */ +# define BUF_PUSH_2(c1, c2) \ + do { \ + GET_BUFFER_SPACE (2); \ + *b++ = (UCHAR_T) (c1); \ + *b++ = (UCHAR_T) (c2); \ + } while (0) + + +/* As with BUF_PUSH_2, except for three bytes. */ +# define BUF_PUSH_3(c1, c2, c3) \ + do { \ + GET_BUFFER_SPACE (3); \ + *b++ = (UCHAR_T) (c1); \ + *b++ = (UCHAR_T) (c2); \ + *b++ = (UCHAR_T) (c3); \ + } while (0) + +/* Store a jump with opcode OP at LOC to location TO. We store a + relative address offset by the three bytes the jump itself occupies. */ +# define STORE_JUMP(op, loc, to) \ + PREFIX(store_op1) (op, loc, (int) ((to) - (loc) - (1 + OFFSET_ADDRESS_SIZE))) + +/* Likewise, for a two-argument jump. */ +# define STORE_JUMP2(op, loc, to, arg) \ + PREFIX(store_op2) (op, loc, (int) ((to) - (loc) - (1 + OFFSET_ADDRESS_SIZE)), arg) + +/* Like `STORE_JUMP', but for inserting. Assume `b' is the buffer end. */ +# define INSERT_JUMP(op, loc, to) \ + PREFIX(insert_op1) (op, loc, (int) ((to) - (loc) - (1 + OFFSET_ADDRESS_SIZE)), b) + +/* Like `STORE_JUMP2', but for inserting. Assume `b' is the buffer end. */ +# define INSERT_JUMP2(op, loc, to, arg) \ + PREFIX(insert_op2) (op, loc, (int) ((to) - (loc) - (1 + OFFSET_ADDRESS_SIZE)),\ + arg, b) + +/* This is not an arbitrary limit: the arguments which represent offsets + into the pattern are two bytes long. So if 2^16 bytes turns out to + be too small, many things would have to change. */ +/* Any other compiler which, like MSC, has allocation limit below 2^16 + bytes will have to use approach similar to what was done below for + MSC and drop MAX_BUF_SIZE a bit. Otherwise you may end up + reallocating to 0 bytes. Such thing is not going to work too well. + You have been warned!! */ +# ifndef DEFINED_ONCE +# if defined _MSC_VER && !defined WIN32 +/* Microsoft C 16-bit versions limit malloc to approx 65512 bytes. + The REALLOC define eliminates a flurry of conversion warnings, + but is not required. */ +# define MAX_BUF_SIZE 65500L +# define REALLOC(p,s) realloc ((p), (size_t) (s)) +# else +# define MAX_BUF_SIZE (1L << 16) +# define REALLOC(p,s) realloc ((p), (s)) +# endif +# endif /* not DEFINED_ONCE */ + +/* Extend the buffer by twice its current size via realloc and + reset the pointers that pointed into the old block to point to the + correct places in the new one. If extending the buffer results in it + being larger than MAX_BUF_SIZE, then flag memory exhausted. */ +# ifdef WCHAR +# define EXTEND_BUFFER() \ + do { \ + UCHAR_T *old_buffer = COMPILED_BUFFER_VAR; \ + int wchar_count; \ + if (bufp->allocated + sizeof(UCHAR_T) > MAX_BUF_SIZE) \ + return REG_ESIZE; \ + bufp->allocated <<= 1; \ + if (bufp->allocated > MAX_BUF_SIZE) \ + bufp->allocated = MAX_BUF_SIZE; \ + /* How many characters the new buffer can have? */ \ + wchar_count = bufp->allocated / sizeof(UCHAR_T); \ + if (wchar_count == 0) wchar_count = 1; \ + /* Truncate the buffer to CHAR_T align. */ \ + bufp->allocated = wchar_count * sizeof(UCHAR_T); \ + RETALLOC (COMPILED_BUFFER_VAR, wchar_count, UCHAR_T); \ + bufp->buffer = (char*)COMPILED_BUFFER_VAR; \ + if (COMPILED_BUFFER_VAR == NULL) \ + return REG_ESPACE; \ + /* If the buffer moved, move all the pointers into it. */ \ + if (old_buffer != COMPILED_BUFFER_VAR) \ + { \ + int incr = COMPILED_BUFFER_VAR - old_buffer; \ + b += incr; \ + begalt += incr; \ + if (fixup_alt_jump) \ + fixup_alt_jump += incr; \ + if (laststart) \ + laststart += incr; \ + if (pending_exact) \ + pending_exact += incr; \ + } \ + } while (0) +# else /* BYTE */ +# define EXTEND_BUFFER() \ + do { \ + UCHAR_T *old_buffer = COMPILED_BUFFER_VAR; \ + if (bufp->allocated == MAX_BUF_SIZE) \ + return REG_ESIZE; \ + bufp->allocated <<= 1; \ + if (bufp->allocated > MAX_BUF_SIZE) \ + bufp->allocated = MAX_BUF_SIZE; \ + bufp->buffer = (UCHAR_T *) REALLOC (COMPILED_BUFFER_VAR, \ + bufp->allocated); \ + if (COMPILED_BUFFER_VAR == NULL) \ + return REG_ESPACE; \ + /* If the buffer moved, move all the pointers into it. */ \ + if (old_buffer != COMPILED_BUFFER_VAR) \ + { \ + int incr = COMPILED_BUFFER_VAR - old_buffer; \ + b += incr; \ + begalt += incr; \ + if (fixup_alt_jump) \ + fixup_alt_jump += incr; \ + if (laststart) \ + laststart += incr; \ + if (pending_exact) \ + pending_exact += incr; \ + } \ + } while (0) +# endif /* WCHAR */ + +# ifndef DEFINED_ONCE +/* Since we have one byte reserved for the register number argument to + {start,stop}_memory, the maximum number of groups we can report + things about is what fits in that byte. */ +# define MAX_REGNUM 255 + +/* But patterns can have more than `MAX_REGNUM' registers. We just + ignore the excess. */ +typedef unsigned regnum_t; + + +/* Macros for the compile stack. */ + +/* Since offsets can go either forwards or backwards, this type needs to + be able to hold values from -(MAX_BUF_SIZE - 1) to MAX_BUF_SIZE - 1. */ +/* int may be not enough when sizeof(int) == 2. */ +typedef long pattern_offset_t; + +typedef struct +{ + pattern_offset_t begalt_offset; + pattern_offset_t fixup_alt_jump; + pattern_offset_t inner_group_offset; + pattern_offset_t laststart_offset; + regnum_t regnum; +} compile_stack_elt_t; + + +typedef struct +{ + compile_stack_elt_t *stack; + unsigned size; + unsigned avail; /* Offset of next open position. */ +} compile_stack_type; + + +# define INIT_COMPILE_STACK_SIZE 32 + +# define COMPILE_STACK_EMPTY (compile_stack.avail == 0) +# define COMPILE_STACK_FULL (compile_stack.avail == compile_stack.size) + +/* The next available element. */ +# define COMPILE_STACK_TOP (compile_stack.stack[compile_stack.avail]) + +# endif /* not DEFINED_ONCE */ + +/* Set the bit for character C in a list. */ +# ifndef DEFINED_ONCE +# define SET_LIST_BIT(c) \ + (b[((unsigned char) (c)) / BYTEWIDTH] \ + |= 1 << (((unsigned char) c) % BYTEWIDTH)) +# endif /* DEFINED_ONCE */ + +/* Get the next unsigned number in the uncompiled pattern. */ +# define GET_UNSIGNED_NUMBER(num) \ + { \ + while (p != pend) \ + { \ + PATFETCH (c); \ + if (c < '0' || c > '9') \ + break; \ + if (num <= RE_DUP_MAX) \ + { \ + if (num < 0) \ + num = 0; \ + num = num * 10 + c - '0'; \ + } \ + } \ + } + +# ifndef DEFINED_ONCE +# if defined _LIBC || defined WIDE_CHAR_SUPPORT +/* The GNU C library provides support for user-defined character classes + and the functions from ISO C amendement 1. */ +# ifdef CHARCLASS_NAME_MAX +# define CHAR_CLASS_MAX_LENGTH CHARCLASS_NAME_MAX +# else +/* This shouldn't happen but some implementation might still have this + problem. Use a reasonable default value. */ +# define CHAR_CLASS_MAX_LENGTH 256 +# endif + +# ifdef _LIBC +# define IS_CHAR_CLASS(string) __wctype (string) +# else +# define IS_CHAR_CLASS(string) wctype (string) +# endif +# else +# define CHAR_CLASS_MAX_LENGTH 6 /* Namely, `xdigit'. */ + +# define IS_CHAR_CLASS(string) \ + (STREQ (string, "alpha") || STREQ (string, "upper") \ + || STREQ (string, "lower") || STREQ (string, "digit") \ + || STREQ (string, "alnum") || STREQ (string, "xdigit") \ + || STREQ (string, "space") || STREQ (string, "print") \ + || STREQ (string, "punct") || STREQ (string, "graph") \ + || STREQ (string, "cntrl") || STREQ (string, "blank")) +# endif +# endif /* DEFINED_ONCE */ + +# ifndef MATCH_MAY_ALLOCATE + +/* If we cannot allocate large objects within re_match_2_internal, + we make the fail stack and register vectors global. + The fail stack, we grow to the maximum size when a regexp + is compiled. + The register vectors, we adjust in size each time we + compile a regexp, according to the number of registers it needs. */ + +static PREFIX(fail_stack_type) fail_stack; + +/* Size with which the following vectors are currently allocated. + That is so we can make them bigger as needed, + but never make them smaller. */ +# ifdef DEFINED_ONCE +static int regs_allocated_size; + +static const char ** regstart, ** regend; +static const char ** old_regstart, ** old_regend; +static const char **best_regstart, **best_regend; +static const char **reg_dummy; +# endif /* DEFINED_ONCE */ + +static PREFIX(register_info_type) *PREFIX(reg_info); +static PREFIX(register_info_type) *PREFIX(reg_info_dummy); + +/* Make the register vectors big enough for NUM_REGS registers, + but don't make them smaller. */ + +static void +PREFIX(regex_grow_registers) (int num_regs) +{ + if (num_regs > regs_allocated_size) + { + RETALLOC_IF (regstart, num_regs, const char *); + RETALLOC_IF (regend, num_regs, const char *); + RETALLOC_IF (old_regstart, num_regs, const char *); + RETALLOC_IF (old_regend, num_regs, const char *); + RETALLOC_IF (best_regstart, num_regs, const char *); + RETALLOC_IF (best_regend, num_regs, const char *); + RETALLOC_IF (PREFIX(reg_info), num_regs, PREFIX(register_info_type)); + RETALLOC_IF (reg_dummy, num_regs, const char *); + RETALLOC_IF (PREFIX(reg_info_dummy), num_regs, PREFIX(register_info_type)); + + regs_allocated_size = num_regs; + } +} + +# endif /* not MATCH_MAY_ALLOCATE */ + +# ifndef DEFINED_ONCE +static boolean group_in_compile_stack (compile_stack_type + compile_stack, + regnum_t regnum); +# endif /* not DEFINED_ONCE */ + +/* `regex_compile' compiles PATTERN (of length SIZE) according to SYNTAX. + Returns one of error codes defined in `regex.h', or zero for success. + + Assumes the `allocated' (and perhaps `buffer') and `translate' + fields are set in BUFP on entry. + + If it succeeds, results are put in BUFP (if it returns an error, the + contents of BUFP are undefined): + `buffer' is the compiled pattern; + `syntax' is set to SYNTAX; + `used' is set to the length of the compiled pattern; + `fastmap_accurate' is zero; + `re_nsub' is the number of subexpressions in PATTERN; + `not_bol' and `not_eol' are zero; + + The `fastmap' and `newline_anchor' fields are neither + examined nor set. */ + +/* Return, freeing storage we allocated. */ +# ifdef WCHAR +# define FREE_STACK_RETURN(value) \ + return (free(pattern), free(mbs_offset), free(is_binary), free (compile_stack.stack), value) +# else +# define FREE_STACK_RETURN(value) \ + return (free (compile_stack.stack), value) +# endif /* WCHAR */ + +static reg_errcode_t +PREFIX(regex_compile) ( + const char *ARG_PREFIX(pattern), + size_t ARG_PREFIX(size), + reg_syntax_t syntax, + struct re_pattern_buffer *bufp) +{ + /* We fetch characters from PATTERN here. Even though PATTERN is + `char *' (i.e., signed), we declare these variables as unsigned, so + they can be reliably used as array indices. */ + register UCHAR_T c, c1; + +#ifdef WCHAR + /* A temporary space to keep wchar_t pattern and compiled pattern. */ + CHAR_T *pattern, *COMPILED_BUFFER_VAR; + size_t size; + /* offset buffer for optimization. See convert_mbs_to_wc. */ + int *mbs_offset = NULL; + /* It hold whether each wchar_t is binary data or not. */ + char *is_binary = NULL; + /* A flag whether exactn is handling binary data or not. */ + char is_exactn_bin = FALSE; +#endif /* WCHAR */ + + /* A random temporary spot in PATTERN. */ + const CHAR_T *p1; + + /* Points to the end of the buffer, where we should append. */ + register UCHAR_T *b; + + /* Keeps track of unclosed groups. */ + compile_stack_type compile_stack; + + /* Points to the current (ending) position in the pattern. */ +#ifdef WCHAR + const CHAR_T *p; + const CHAR_T *pend; +#else /* BYTE */ + const CHAR_T *p = pattern; + const CHAR_T *pend = pattern + size; +#endif /* WCHAR */ + + /* How to translate the characters in the pattern. */ + RE_TRANSLATE_TYPE translate = bufp->translate; + + /* Address of the count-byte of the most recently inserted `exactn' + command. This makes it possible to tell if a new exact-match + character can be added to that command or if the character requires + a new `exactn' command. */ + UCHAR_T *pending_exact = 0; + + /* Address of start of the most recently finished expression. + This tells, e.g., postfix * where to find the start of its + operand. Reset at the beginning of groups and alternatives. */ + UCHAR_T *laststart = 0; + + /* Address of beginning of regexp, or inside of last group. */ + UCHAR_T *begalt; + + /* Address of the place where a forward jump should go to the end of + the containing expression. Each alternative of an `or' -- except the + last -- ends with a forward jump of this sort. */ + UCHAR_T *fixup_alt_jump = 0; + + /* Counts open-groups as they are encountered. Remembered for the + matching close-group on the compile stack, so the same register + number is put in the stop_memory as the start_memory. */ + regnum_t regnum = 0; + +#ifdef WCHAR + /* Initialize the wchar_t PATTERN and offset_buffer. */ + p = pend = pattern = TALLOC(csize + 1, CHAR_T); + mbs_offset = TALLOC(csize + 1, int); + is_binary = TALLOC(csize + 1, char); + if (pattern == NULL || mbs_offset == NULL || is_binary == NULL) + { + free(pattern); + free(mbs_offset); + free(is_binary); + return REG_ESPACE; + } + pattern[csize] = L'\0'; /* sentinel */ + size = convert_mbs_to_wcs(pattern, cpattern, csize, mbs_offset, is_binary); + pend = p + size; + if (size < 0) + { + free(pattern); + free(mbs_offset); + free(is_binary); + return REG_BADPAT; + } +#endif + +#ifdef DEBUG + DEBUG_PRINT1 ("\nCompiling pattern: "); + if (debug) + { + unsigned debug_count; + + for (debug_count = 0; debug_count < size; debug_count++) + PUT_CHAR (pattern[debug_count]); + putchar ('\n'); + } +#endif /* DEBUG */ + + /* Initialize the compile stack. */ + compile_stack.stack = TALLOC (INIT_COMPILE_STACK_SIZE, compile_stack_elt_t); + if (compile_stack.stack == NULL) + { +#ifdef WCHAR + free(pattern); + free(mbs_offset); + free(is_binary); +#endif + return REG_ESPACE; + } + + compile_stack.size = INIT_COMPILE_STACK_SIZE; + compile_stack.avail = 0; + + /* Initialize the pattern buffer. */ + bufp->syntax = syntax; + bufp->fastmap_accurate = 0; + bufp->not_bol = bufp->not_eol = 0; + + /* Set `used' to zero, so that if we return an error, the pattern + printer (for debugging) will think there's no pattern. We reset it + at the end. */ + bufp->used = 0; + + /* Always count groups, whether or not bufp->no_sub is set. */ + bufp->re_nsub = 0; + +#if !defined emacs && !defined SYNTAX_TABLE + /* Initialize the syntax table. */ + init_syntax_once (); +#endif + + if (bufp->allocated == 0) + { + if (bufp->buffer) + { /* If zero allocated, but buffer is non-null, try to realloc + enough space. This loses if buffer's address is bogus, but + that is the user's responsibility. */ +#ifdef WCHAR + /* Free bufp->buffer and allocate an array for wchar_t pattern + buffer. */ + free(bufp->buffer); + COMPILED_BUFFER_VAR = TALLOC (INIT_BUF_SIZE/sizeof(UCHAR_T), + UCHAR_T); +#else + RETALLOC (COMPILED_BUFFER_VAR, INIT_BUF_SIZE, UCHAR_T); +#endif /* WCHAR */ + } + else + { /* Caller did not allocate a buffer. Do it for them. */ + COMPILED_BUFFER_VAR = TALLOC (INIT_BUF_SIZE / sizeof(UCHAR_T), + UCHAR_T); + } + + if (!COMPILED_BUFFER_VAR) FREE_STACK_RETURN (REG_ESPACE); +#ifdef WCHAR + bufp->buffer = (char*)COMPILED_BUFFER_VAR; +#endif /* WCHAR */ + bufp->allocated = INIT_BUF_SIZE; + } +#ifdef WCHAR + else + COMPILED_BUFFER_VAR = (UCHAR_T*) bufp->buffer; +#endif + + begalt = b = COMPILED_BUFFER_VAR; + + /* Loop through the uncompiled pattern until we're at the end. */ + while (p != pend) + { + PATFETCH (c); + + switch (c) + { + case '^': + { + if ( /* If at start of pattern, it's an operator. */ + p == pattern + 1 + /* If context independent, it's an operator. */ + || syntax & RE_CONTEXT_INDEP_ANCHORS + /* Otherwise, depends on what's come before. */ + || PREFIX(at_begline_loc_p) (pattern, p, syntax)) + BUF_PUSH (begline); + else + goto normal_char; + } + break; + + + case '$': + { + if ( /* If at end of pattern, it's an operator. */ + p == pend + /* If context independent, it's an operator. */ + || syntax & RE_CONTEXT_INDEP_ANCHORS + /* Otherwise, depends on what's next. */ + || PREFIX(at_endline_loc_p) (p, pend, syntax)) + BUF_PUSH (endline); + else + goto normal_char; + } + break; + + + case '+': + case '?': + if ((syntax & RE_BK_PLUS_QM) + || (syntax & RE_LIMITED_OPS)) + goto normal_char; + handle_plus: + case '*': + /* If there is no previous pattern... */ + if (!laststart) + { + if (syntax & RE_CONTEXT_INVALID_OPS) + FREE_STACK_RETURN (REG_BADRPT); + else if (!(syntax & RE_CONTEXT_INDEP_OPS)) + goto normal_char; + } + + { + /* Are we optimizing this jump? */ + boolean keep_string_p = false; + + /* 1 means zero (many) matches is allowed. */ + char zero_times_ok = 0, many_times_ok = 0; + + /* If there is a sequence of repetition chars, collapse it + down to just one (the right one). We can't combine + interval operators with these because of, e.g., `a{2}*', + which should only match an even number of `a's. */ + + for (;;) + { + zero_times_ok |= c != '+'; + many_times_ok |= c != '?'; + + if (p == pend) + break; + + PATFETCH (c); + + if (c == '*' + || (!(syntax & RE_BK_PLUS_QM) && (c == '+' || c == '?'))) + ; + + else if (syntax & RE_BK_PLUS_QM && c == '\\') + { + if (p == pend) FREE_STACK_RETURN (REG_EESCAPE); + + PATFETCH (c1); + if (!(c1 == '+' || c1 == '?')) + { + PATUNFETCH; + PATUNFETCH; + break; + } + + c = c1; + } + else + { + PATUNFETCH; + break; + } + + /* If we get here, we found another repeat character. */ + } + + /* Star, etc. applied to an empty pattern is equivalent + to an empty pattern. */ + if (!laststart) + break; + + /* Now we know whether or not zero matches is allowed + and also whether or not two or more matches is allowed. */ + if (many_times_ok) + { /* More than one repetition is allowed, so put in at the + end a backward relative jump from `b' to before the next + jump we're going to put in below (which jumps from + laststart to after this jump). + + But if we are at the `*' in the exact sequence `.*\n', + insert an unconditional jump backwards to the ., + instead of the beginning of the loop. This way we only + push a failure point once, instead of every time + through the loop. */ + assert (p - 1 > pattern); + + /* Allocate the space for the jump. */ + GET_BUFFER_SPACE (1 + OFFSET_ADDRESS_SIZE); + + /* We know we are not at the first character of the pattern, + because laststart was nonzero. And we've already + incremented `p', by the way, to be the character after + the `*'. Do we have to do something analogous here + for null bytes, because of RE_DOT_NOT_NULL? */ + if (TRANSLATE (*(p - 2)) == TRANSLATE ('.') + && zero_times_ok + && p < pend && TRANSLATE (*p) == TRANSLATE ('\n') + && !(syntax & RE_DOT_NEWLINE)) + { /* We have .*\n. */ + STORE_JUMP (jump, b, laststart); + keep_string_p = true; + } + else + /* Anything else. */ + STORE_JUMP (maybe_pop_jump, b, laststart - + (1 + OFFSET_ADDRESS_SIZE)); + + /* We've added more stuff to the buffer. */ + b += 1 + OFFSET_ADDRESS_SIZE; + } + + /* On failure, jump from laststart to b + 3, which will be the + end of the buffer after this jump is inserted. */ + /* ifdef WCHAR, 'b + 1 + OFFSET_ADDRESS_SIZE' instead of + 'b + 3'. */ + GET_BUFFER_SPACE (1 + OFFSET_ADDRESS_SIZE); + INSERT_JUMP (keep_string_p ? on_failure_keep_string_jump + : on_failure_jump, + laststart, b + 1 + OFFSET_ADDRESS_SIZE); + pending_exact = 0; + b += 1 + OFFSET_ADDRESS_SIZE; + + if (!zero_times_ok) + { + /* At least one repetition is required, so insert a + `dummy_failure_jump' before the initial + `on_failure_jump' instruction of the loop. This + effects a skip over that instruction the first time + we hit that loop. */ + GET_BUFFER_SPACE (1 + OFFSET_ADDRESS_SIZE); + INSERT_JUMP (dummy_failure_jump, laststart, laststart + + 2 + 2 * OFFSET_ADDRESS_SIZE); + b += 1 + OFFSET_ADDRESS_SIZE; + } + } + break; + + + case '.': + laststart = b; + BUF_PUSH (anychar); + break; + + + case '[': + { + boolean had_char_class = false; +#ifdef WCHAR + CHAR_T range_start = 0xffffffff; +#else + unsigned int range_start = 0xffffffff; +#endif + if (p == pend) FREE_STACK_RETURN (REG_EBRACK); + +#ifdef WCHAR + /* We assume a charset(_not) structure as a wchar_t array. + charset[0] = (re_opcode_t) charset(_not) + charset[1] = l (= length of char_classes) + charset[2] = m (= length of collating_symbols) + charset[3] = n (= length of equivalence_classes) + charset[4] = o (= length of char_ranges) + charset[5] = p (= length of chars) + + charset[6] = char_class (wctype_t) + charset[6+CHAR_CLASS_SIZE] = char_class (wctype_t) + ... + charset[l+5] = char_class (wctype_t) + + charset[l+6] = collating_symbol (wchar_t) + ... + charset[l+m+5] = collating_symbol (wchar_t) + ifdef _LIBC we use the index if + _NL_COLLATE_SYMB_EXTRAMB instead of + wchar_t string. + + charset[l+m+6] = equivalence_classes (wchar_t) + ... + charset[l+m+n+5] = equivalence_classes (wchar_t) + ifdef _LIBC we use the index in + _NL_COLLATE_WEIGHT instead of + wchar_t string. + + charset[l+m+n+6] = range_start + charset[l+m+n+7] = range_end + ... + charset[l+m+n+2o+4] = range_start + charset[l+m+n+2o+5] = range_end + ifdef _LIBC we use the value looked up + in _NL_COLLATE_COLLSEQ instead of + wchar_t character. + + charset[l+m+n+2o+6] = char + ... + charset[l+m+n+2o+p+5] = char + + */ + + /* We need at least 6 spaces: the opcode, the length of + char_classes, the length of collating_symbols, the length of + equivalence_classes, the length of char_ranges, the length of + chars. */ + GET_BUFFER_SPACE (6); + + /* Save b as laststart. And We use laststart as the pointer + to the first element of the charset here. + In other words, laststart[i] indicates charset[i]. */ + laststart = b; + + /* We test `*p == '^' twice, instead of using an if + statement, so we only need one BUF_PUSH. */ + BUF_PUSH (*p == '^' ? charset_not : charset); + if (*p == '^') + p++; + + /* Push the length of char_classes, the length of + collating_symbols, the length of equivalence_classes, the + length of char_ranges and the length of chars. */ + BUF_PUSH_3 (0, 0, 0); + BUF_PUSH_2 (0, 0); + + /* Remember the first position in the bracket expression. */ + p1 = p; + + /* charset_not matches newline according to a syntax bit. */ + if ((re_opcode_t) b[-6] == charset_not + && (syntax & RE_HAT_LISTS_NOT_NEWLINE)) + { + BUF_PUSH('\n'); + laststart[5]++; /* Update the length of characters */ + } + + /* Read in characters and ranges, setting map bits. */ + for (;;) + { + if (p == pend) FREE_STACK_RETURN (REG_EBRACK); + + PATFETCH (c); + + /* \ might escape characters inside [...] and [^...]. */ + if ((syntax & RE_BACKSLASH_ESCAPE_IN_LISTS) && c == '\\') + { + if (p == pend) FREE_STACK_RETURN (REG_EESCAPE); + + PATFETCH (c1); + BUF_PUSH(c1); + laststart[5]++; /* Update the length of chars */ + range_start = c1; + continue; + } + + /* Could be the end of the bracket expression. If it's + not (i.e., when the bracket expression is `[]' so + far), the ']' character bit gets set way below. */ + if (c == ']' && p != p1 + 1) + break; + + /* Look ahead to see if it's a range when the last thing + was a character class. */ + if (had_char_class && c == '-' && *p != ']') + FREE_STACK_RETURN (REG_ERANGE); + + /* Look ahead to see if it's a range when the last thing + was a character: if this is a hyphen not at the + beginning or the end of a list, then it's the range + operator. */ + if (c == '-' + && !(p - 2 >= pattern && p[-2] == '[') + && !(p - 3 >= pattern && p[-3] == '[' && p[-2] == '^') + && *p != ']') + { + reg_errcode_t ret; + /* Allocate the space for range_start and range_end. */ + GET_BUFFER_SPACE (2); + /* Update the pointer to indicate end of buffer. */ + b += 2; + ret = wcs_compile_range (range_start, &p, pend, translate, + syntax, b, laststart); + if (ret != REG_NOERROR) FREE_STACK_RETURN (ret); + range_start = 0xffffffff; + } + else if (p[0] == '-' && p[1] != ']') + { /* This handles ranges made up of characters only. */ + reg_errcode_t ret; + + /* Move past the `-'. */ + PATFETCH (c1); + /* Allocate the space for range_start and range_end. */ + GET_BUFFER_SPACE (2); + /* Update the pointer to indicate end of buffer. */ + b += 2; + ret = wcs_compile_range (c, &p, pend, translate, syntax, b, + laststart); + if (ret != REG_NOERROR) FREE_STACK_RETURN (ret); + range_start = 0xffffffff; + } + + /* See if we're at the beginning of a possible character + class. */ + else if (syntax & RE_CHAR_CLASSES && c == '[' && *p == ':') + { /* Leave room for the null. */ + char str[CHAR_CLASS_MAX_LENGTH + 1]; + + PATFETCH (c); + c1 = 0; + + /* If pattern is `[[:'. */ + if (p == pend) FREE_STACK_RETURN (REG_EBRACK); + + for (;;) + { + PATFETCH (c); + if ((c == ':' && *p == ']') || p == pend) + break; + if (c1 < CHAR_CLASS_MAX_LENGTH) + str[c1++] = c; + else + /* This is in any case an invalid class name. */ + str[0] = '\0'; + } + str[c1] = '\0'; + + /* If isn't a word bracketed by `[:' and `:]': + undo the ending character, the letters, and leave + the leading `:' and `[' (but store them as character). */ + if (c == ':' && *p == ']') + { + wctype_t wt; + uintptr_t alignedp; + + /* Query the character class as wctype_t. */ + wt = IS_CHAR_CLASS (str); + if (wt == 0) + FREE_STACK_RETURN (REG_ECTYPE); + + /* Throw away the ] at the end of the character + class. */ + PATFETCH (c); + + if (p == pend) FREE_STACK_RETURN (REG_EBRACK); + + /* Allocate the space for character class. */ + GET_BUFFER_SPACE(CHAR_CLASS_SIZE); + /* Update the pointer to indicate end of buffer. */ + b += CHAR_CLASS_SIZE; + /* Move data which follow character classes + not to violate the data. */ + insert_space(CHAR_CLASS_SIZE, + laststart + 6 + laststart[1], + b - 1); + alignedp = ((uintptr_t)(laststart + 6 + laststart[1]) + + __alignof__(wctype_t) - 1) + & ~(uintptr_t)(__alignof__(wctype_t) - 1); + /* Store the character class. */ + *((wctype_t*)alignedp) = wt; + /* Update length of char_classes */ + laststart[1] += CHAR_CLASS_SIZE; + + had_char_class = true; + } + else + { + c1++; + while (c1--) + PATUNFETCH; + BUF_PUSH ('['); + BUF_PUSH (':'); + laststart[5] += 2; /* Update the length of characters */ + range_start = ':'; + had_char_class = false; + } + } + else if (syntax & RE_CHAR_CLASSES && c == '[' && (*p == '=' + || *p == '.')) + { + CHAR_T str[128]; /* Should be large enough. */ + CHAR_T delim = *p; /* '=' or '.' */ +# ifdef _LIBC + uint32_t nrules = + _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); +# endif + PATFETCH (c); + c1 = 0; + + /* If pattern is `[[=' or '[[.'. */ + if (p == pend) FREE_STACK_RETURN (REG_EBRACK); + + for (;;) + { + PATFETCH (c); + if ((c == delim && *p == ']') || p == pend) + break; + if (c1 < sizeof (str) - 1) + str[c1++] = c; + else + /* This is in any case an invalid class name. */ + str[0] = '\0'; + } + str[c1] = '\0'; + + if (c == delim && *p == ']' && str[0] != '\0') + { + unsigned int i, offset; + /* If we have no collation data we use the default + collation in which each character is in a class + by itself. It also means that ASCII is the + character set and therefore we cannot have character + with more than one byte in the multibyte + representation. */ + + /* If not defined _LIBC, we push the name and + `\0' for the sake of matching performance. */ + int datasize = c1 + 1; + +# ifdef _LIBC + int32_t idx = 0; + if (nrules == 0) +# endif + { + if (c1 != 1) + FREE_STACK_RETURN (REG_ECOLLATE); + } +# ifdef _LIBC + else + { + const int32_t *table; + const int32_t *weights; + const int32_t *extra; + const int32_t *indirect; + wint_t *cp; + + /* This #include defines a local function! */ +# include + + if(delim == '=') + { + /* We push the index for equivalence class. */ + cp = (wint_t*)str; + + table = (const int32_t *) + _NL_CURRENT (LC_COLLATE, + _NL_COLLATE_TABLEWC); + weights = (const int32_t *) + _NL_CURRENT (LC_COLLATE, + _NL_COLLATE_WEIGHTWC); + extra = (const int32_t *) + _NL_CURRENT (LC_COLLATE, + _NL_COLLATE_EXTRAWC); + indirect = (const int32_t *) + _NL_CURRENT (LC_COLLATE, + _NL_COLLATE_INDIRECTWC); + + idx = findidx ((const wint_t**)&cp); + if (idx == 0 || cp < (wint_t*) str + c1) + /* This is no valid character. */ + FREE_STACK_RETURN (REG_ECOLLATE); + + str[0] = (wchar_t)idx; + } + else /* delim == '.' */ + { + /* We push collation sequence value + for collating symbol. */ + int32_t table_size; + const int32_t *symb_table; + const unsigned char *extra; + int32_t idx; + int32_t elem; + int32_t second; + int32_t hash; + char char_str[c1]; + + /* We have to convert the name to a single-byte + string. This is possible since the names + consist of ASCII characters and the internal + representation is UCS4. */ + for (i = 0; i < c1; ++i) + char_str[i] = str[i]; + + table_size = + _NL_CURRENT_WORD (LC_COLLATE, + _NL_COLLATE_SYMB_HASH_SIZEMB); + symb_table = (const int32_t *) + _NL_CURRENT (LC_COLLATE, + _NL_COLLATE_SYMB_TABLEMB); + extra = (const unsigned char *) + _NL_CURRENT (LC_COLLATE, + _NL_COLLATE_SYMB_EXTRAMB); + + /* Locate the character in the hashing table. */ + hash = elem_hash (char_str, c1); + + idx = 0; + elem = hash % table_size; + second = hash % (table_size - 2); + while (symb_table[2 * elem] != 0) + { + /* First compare the hashing value. */ + if (symb_table[2 * elem] == hash + && c1 == extra[symb_table[2 * elem + 1]] + && memcmp (char_str, + &extra[symb_table[2 * elem + 1] + + 1], c1) == 0) + { + /* Yep, this is the entry. */ + idx = symb_table[2 * elem + 1]; + idx += 1 + extra[idx]; + break; + } + + /* Next entry. */ + elem += second; + } + + if (symb_table[2 * elem] != 0) + { + /* Compute the index of the byte sequence + in the table. */ + idx += 1 + extra[idx]; + /* Adjust for the alignment. */ + idx = (idx + 3) & ~3; + + str[0] = (wchar_t) idx + 4; + } + else if (symb_table[2 * elem] == 0 && c1 == 1) + { + /* No valid character. Match it as a + single byte character. */ + had_char_class = false; + BUF_PUSH(str[0]); + /* Update the length of characters */ + laststart[5]++; + range_start = str[0]; + + /* Throw away the ] at the end of the + collating symbol. */ + PATFETCH (c); + /* exit from the switch block. */ + continue; + } + else + FREE_STACK_RETURN (REG_ECOLLATE); + } + datasize = 1; + } +# endif + /* Throw away the ] at the end of the equivalence + class (or collating symbol). */ + PATFETCH (c); + + /* Allocate the space for the equivalence class + (or collating symbol) (and '\0' if needed). */ + GET_BUFFER_SPACE(datasize); + /* Update the pointer to indicate end of buffer. */ + b += datasize; + + if (delim == '=') + { /* equivalence class */ + /* Calculate the offset of char_ranges, + which is next to equivalence_classes. */ + offset = laststart[1] + laststart[2] + + laststart[3] +6; + /* Insert space. */ + insert_space(datasize, laststart + offset, b - 1); + + /* Write the equivalence_class and \0. */ + for (i = 0 ; i < datasize ; i++) + laststart[offset + i] = str[i]; + + /* Update the length of equivalence_classes. */ + laststart[3] += datasize; + had_char_class = true; + } + else /* delim == '.' */ + { /* collating symbol */ + /* Calculate the offset of the equivalence_classes, + which is next to collating_symbols. */ + offset = laststart[1] + laststart[2] + 6; + /* Insert space and write the collationg_symbol + and \0. */ + insert_space(datasize, laststart + offset, b-1); + for (i = 0 ; i < datasize ; i++) + laststart[offset + i] = str[i]; + + /* In re_match_2_internal if range_start < -1, we + assume -range_start is the offset of the + collating symbol which is specified as + the character of the range start. So we assign + -(laststart[1] + laststart[2] + 6) to + range_start. */ + range_start = -(laststart[1] + laststart[2] + 6); + /* Update the length of collating_symbol. */ + laststart[2] += datasize; + had_char_class = false; + } + } + else + { + c1++; + while (c1--) + PATUNFETCH; + BUF_PUSH ('['); + BUF_PUSH (delim); + laststart[5] += 2; /* Update the length of characters */ + range_start = delim; + had_char_class = false; + } + } + else + { + had_char_class = false; + BUF_PUSH(c); + laststart[5]++; /* Update the length of characters */ + range_start = c; + } + } + +#else /* BYTE */ + /* Ensure that we have enough space to push a charset: the + opcode, the length count, and the bitset; 34 bytes in all. */ + GET_BUFFER_SPACE (34); + + laststart = b; + + /* We test `*p == '^' twice, instead of using an if + statement, so we only need one BUF_PUSH. */ + BUF_PUSH (*p == '^' ? charset_not : charset); + if (*p == '^') + p++; + + /* Remember the first position in the bracket expression. */ + p1 = p; + + /* Push the number of bytes in the bitmap. */ + BUF_PUSH ((1 << BYTEWIDTH) / BYTEWIDTH); + + /* Clear the whole map. */ + bzero (b, (1 << BYTEWIDTH) / BYTEWIDTH); + + /* charset_not matches newline according to a syntax bit. */ + if ((re_opcode_t) b[-2] == charset_not + && (syntax & RE_HAT_LISTS_NOT_NEWLINE)) + SET_LIST_BIT ('\n'); + + /* Read in characters and ranges, setting map bits. */ + for (;;) + { + if (p == pend) FREE_STACK_RETURN (REG_EBRACK); + + PATFETCH (c); + + /* \ might escape characters inside [...] and [^...]. */ + if ((syntax & RE_BACKSLASH_ESCAPE_IN_LISTS) && c == '\\') + { + if (p == pend) FREE_STACK_RETURN (REG_EESCAPE); + + PATFETCH (c1); + SET_LIST_BIT (c1); + range_start = c1; + continue; + } + + /* Could be the end of the bracket expression. If it's + not (i.e., when the bracket expression is `[]' so + far), the ']' character bit gets set way below. */ + if (c == ']' && p != p1 + 1) + break; + + /* Look ahead to see if it's a range when the last thing + was a character class. */ + if (had_char_class && c == '-' && *p != ']') + FREE_STACK_RETURN (REG_ERANGE); + + /* Look ahead to see if it's a range when the last thing + was a character: if this is a hyphen not at the + beginning or the end of a list, then it's the range + operator. */ + if (c == '-' + && !(p - 2 >= pattern && p[-2] == '[') + && !(p - 3 >= pattern && p[-3] == '[' && p[-2] == '^') + && *p != ']') + { + reg_errcode_t ret + = byte_compile_range (range_start, &p, pend, translate, + syntax, b); + if (ret != REG_NOERROR) FREE_STACK_RETURN (ret); + range_start = 0xffffffff; + } + + else if (p[0] == '-' && p[1] != ']') + { /* This handles ranges made up of characters only. */ + reg_errcode_t ret; + + /* Move past the `-'. */ + PATFETCH (c1); + + ret = byte_compile_range (c, &p, pend, translate, syntax, b); + if (ret != REG_NOERROR) FREE_STACK_RETURN (ret); + range_start = 0xffffffff; + } + + /* See if we're at the beginning of a possible character + class. */ + + else if (syntax & RE_CHAR_CLASSES && c == '[' && *p == ':') + { /* Leave room for the null. */ + char str[CHAR_CLASS_MAX_LENGTH + 1]; + + PATFETCH (c); + c1 = 0; + + /* If pattern is `[[:'. */ + if (p == pend) FREE_STACK_RETURN (REG_EBRACK); + + for (;;) + { + PATFETCH (c); + if ((c == ':' && *p == ']') || p == pend) + break; +#if CHAR_CLASS_MAX_LENGTH != 256 + if (c1 < CHAR_CLASS_MAX_LENGTH) + str[c1++] = c; + else + /* This is in any case an invalid class name. */ + str[0] = '\0'; +#else + str[c1++] = c; +#endif + } + str[c1] = '\0'; + + /* If isn't a word bracketed by `[:' and `:]': + undo the ending character, the letters, and leave + the leading `:' and `[' (but set bits for them). */ + if (c == ':' && *p == ']') + { +# if defined _LIBC || defined WIDE_CHAR_SUPPORT + boolean is_lower = STREQ (str, "lower"); + boolean is_upper = STREQ (str, "upper"); + wctype_t wt; + int ch; + + wt = IS_CHAR_CLASS (str); + if (wt == 0) + FREE_STACK_RETURN (REG_ECTYPE); + + /* Throw away the ] at the end of the character + class. */ + PATFETCH (c); + + if (p == pend) FREE_STACK_RETURN (REG_EBRACK); + + for (ch = 0; ch < 1 << BYTEWIDTH; ++ch) + { +# ifdef _LIBC + if (__iswctype (__btowc (ch), wt)) + SET_LIST_BIT (ch); +# else + if (iswctype (btowc (ch), wt)) + SET_LIST_BIT (ch); +# endif + + if (translate && (is_upper || is_lower) + && (ISUPPER (ch) || ISLOWER (ch))) + SET_LIST_BIT (ch); + } + + had_char_class = true; +# else + int ch; + boolean is_alnum = STREQ (str, "alnum"); + boolean is_alpha = STREQ (str, "alpha"); + boolean is_blank = STREQ (str, "blank"); + boolean is_cntrl = STREQ (str, "cntrl"); + boolean is_digit = STREQ (str, "digit"); + boolean is_graph = STREQ (str, "graph"); + boolean is_lower = STREQ (str, "lower"); + boolean is_print = STREQ (str, "print"); + boolean is_punct = STREQ (str, "punct"); + boolean is_space = STREQ (str, "space"); + boolean is_upper = STREQ (str, "upper"); + boolean is_xdigit = STREQ (str, "xdigit"); + + if (!IS_CHAR_CLASS (str)) + FREE_STACK_RETURN (REG_ECTYPE); + + /* Throw away the ] at the end of the character + class. */ + PATFETCH (c); + + if (p == pend) FREE_STACK_RETURN (REG_EBRACK); + + for (ch = 0; ch < 1 << BYTEWIDTH; ch++) + { + /* This was split into 3 if's to + avoid an arbitrary limit in some compiler. */ + if ( (is_alnum && ISALNUM (ch)) + || (is_alpha && ISALPHA (ch)) + || (is_blank && ISBLANK (ch)) + || (is_cntrl && ISCNTRL (ch))) + SET_LIST_BIT (ch); + if ( (is_digit && ISDIGIT (ch)) + || (is_graph && ISGRAPH (ch)) + || (is_lower && ISLOWER (ch)) + || (is_print && ISPRINT (ch))) + SET_LIST_BIT (ch); + if ( (is_punct && ISPUNCT (ch)) + || (is_space && ISSPACE (ch)) + || (is_upper && ISUPPER (ch)) + || (is_xdigit && ISXDIGIT (ch))) + SET_LIST_BIT (ch); + if ( translate && (is_upper || is_lower) + && (ISUPPER (ch) || ISLOWER (ch))) + SET_LIST_BIT (ch); + } + had_char_class = true; +# endif /* libc || wctype.h */ + } + else + { + c1++; + while (c1--) + PATUNFETCH; + SET_LIST_BIT ('['); + SET_LIST_BIT (':'); + range_start = ':'; + had_char_class = false; + } + } + else if (syntax & RE_CHAR_CLASSES && c == '[' && *p == '=') + { + unsigned char str[MB_LEN_MAX + 1]; +# ifdef _LIBC + uint32_t nrules = + _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); +# endif + + PATFETCH (c); + c1 = 0; + + /* If pattern is `[[='. */ + if (p == pend) FREE_STACK_RETURN (REG_EBRACK); + + for (;;) + { + PATFETCH (c); + if ((c == '=' && *p == ']') || p == pend) + break; + if (c1 < MB_LEN_MAX) + str[c1++] = c; + else + /* This is in any case an invalid class name. */ + str[0] = '\0'; + } + str[c1] = '\0'; + + if (c == '=' && *p == ']' && str[0] != '\0') + { + /* If we have no collation data we use the default + collation in which each character is in a class + by itself. It also means that ASCII is the + character set and therefore we cannot have character + with more than one byte in the multibyte + representation. */ +# ifdef _LIBC + if (nrules == 0) +# endif + { + if (c1 != 1) + FREE_STACK_RETURN (REG_ECOLLATE); + + /* Throw away the ] at the end of the equivalence + class. */ + PATFETCH (c); + + /* Set the bit for the character. */ + SET_LIST_BIT (str[0]); + } +# ifdef _LIBC + else + { + /* Try to match the byte sequence in `str' against + those known to the collate implementation. + First find out whether the bytes in `str' are + actually from exactly one character. */ + const int32_t *table; + const unsigned char *weights; + const unsigned char *extra; + const int32_t *indirect; + int32_t idx; + const unsigned char *cp = str; + int ch; + + /* This #include defines a local function! */ +# include + + table = (const int32_t *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB); + weights = (const unsigned char *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_WEIGHTMB); + extra = (const unsigned char *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAMB); + indirect = (const int32_t *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTMB); + + idx = findidx (&cp); + if (idx == 0 || cp < str + c1) + /* This is no valid character. */ + FREE_STACK_RETURN (REG_ECOLLATE); + + /* Throw away the ] at the end of the equivalence + class. */ + PATFETCH (c); + + /* Now we have to go throught the whole table + and find all characters which have the same + first level weight. + + XXX Note that this is not entirely correct. + we would have to match multibyte sequences + but this is not possible with the current + implementation. */ + for (ch = 1; ch < 256; ++ch) + /* XXX This test would have to be changed if we + would allow matching multibyte sequences. */ + if (table[ch] > 0) + { + int32_t idx2 = table[ch]; + size_t len = weights[idx2]; + + /* Test whether the lenghts match. */ + if (weights[idx] == len) + { + /* They do. New compare the bytes of + the weight. */ + size_t cnt = 0; + + while (cnt < len + && (weights[idx + 1 + cnt] + == weights[idx2 + 1 + cnt])) + ++cnt; + + if (cnt == len) + /* They match. Mark the character as + acceptable. */ + SET_LIST_BIT (ch); + } + } + } +# endif + had_char_class = true; + } + else + { + c1++; + while (c1--) + PATUNFETCH; + SET_LIST_BIT ('['); + SET_LIST_BIT ('='); + range_start = '='; + had_char_class = false; + } + } + else if (syntax & RE_CHAR_CLASSES && c == '[' && *p == '.') + { + unsigned char str[128]; /* Should be large enough. */ +# ifdef _LIBC + uint32_t nrules = + _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); +# endif + + PATFETCH (c); + c1 = 0; + + /* If pattern is `[[.'. */ + if (p == pend) FREE_STACK_RETURN (REG_EBRACK); + + for (;;) + { + PATFETCH (c); + if ((c == '.' && *p == ']') || p == pend) + break; + if (c1 < sizeof (str)) + str[c1++] = c; + else + /* This is in any case an invalid class name. */ + str[0] = '\0'; + } + str[c1] = '\0'; + + if (c == '.' && *p == ']' && str[0] != '\0') + { + /* If we have no collation data we use the default + collation in which each character is the name + for its own class which contains only the one + character. It also means that ASCII is the + character set and therefore we cannot have character + with more than one byte in the multibyte + representation. */ +# ifdef _LIBC + if (nrules == 0) +# endif + { + if (c1 != 1) + FREE_STACK_RETURN (REG_ECOLLATE); + + /* Throw away the ] at the end of the equivalence + class. */ + PATFETCH (c); + + /* Set the bit for the character. */ + SET_LIST_BIT (str[0]); + range_start = ((const unsigned char *) str)[0]; + } +# ifdef _LIBC + else + { + /* Try to match the byte sequence in `str' against + those known to the collate implementation. + First find out whether the bytes in `str' are + actually from exactly one character. */ + int32_t table_size; + const int32_t *symb_table; + const unsigned char *extra; + int32_t idx; + int32_t elem; + int32_t second; + int32_t hash; + + table_size = + _NL_CURRENT_WORD (LC_COLLATE, + _NL_COLLATE_SYMB_HASH_SIZEMB); + symb_table = (const int32_t *) + _NL_CURRENT (LC_COLLATE, + _NL_COLLATE_SYMB_TABLEMB); + extra = (const unsigned char *) + _NL_CURRENT (LC_COLLATE, + _NL_COLLATE_SYMB_EXTRAMB); + + /* Locate the character in the hashing table. */ + hash = elem_hash (str, c1); + + idx = 0; + elem = hash % table_size; + second = hash % (table_size - 2); + while (symb_table[2 * elem] != 0) + { + /* First compare the hashing value. */ + if (symb_table[2 * elem] == hash + && c1 == extra[symb_table[2 * elem + 1]] + && memcmp (str, + &extra[symb_table[2 * elem + 1] + + 1], + c1) == 0) + { + /* Yep, this is the entry. */ + idx = symb_table[2 * elem + 1]; + idx += 1 + extra[idx]; + break; + } + + /* Next entry. */ + elem += second; + } + + if (symb_table[2 * elem] == 0) + /* This is no valid character. */ + FREE_STACK_RETURN (REG_ECOLLATE); + + /* Throw away the ] at the end of the equivalence + class. */ + PATFETCH (c); + + /* Now add the multibyte character(s) we found + to the accept list. + + XXX Note that this is not entirely correct. + we would have to match multibyte sequences + but this is not possible with the current + implementation. Also, we have to match + collating symbols, which expand to more than + one file, as a whole and not allow the + individual bytes. */ + c1 = extra[idx++]; + if (c1 == 1) + range_start = extra[idx]; + while (c1-- > 0) + { + SET_LIST_BIT (extra[idx]); + ++idx; + } + } +# endif + had_char_class = false; + } + else + { + c1++; + while (c1--) + PATUNFETCH; + SET_LIST_BIT ('['); + SET_LIST_BIT ('.'); + range_start = '.'; + had_char_class = false; + } + } + else + { + had_char_class = false; + SET_LIST_BIT (c); + range_start = c; + } + } + + /* Discard any (non)matching list bytes that are all 0 at the + end of the map. Decrease the map-length byte too. */ + while ((int) b[-1] > 0 && b[b[-1] - 1] == 0) + b[-1]--; + b += b[-1]; +#endif /* WCHAR */ + } + break; + + + case '(': + if (syntax & RE_NO_BK_PARENS) + goto handle_open; + else + goto normal_char; + + + case ')': + if (syntax & RE_NO_BK_PARENS) + goto handle_close; + else + goto normal_char; + + + case '\n': + if (syntax & RE_NEWLINE_ALT) + goto handle_alt; + else + goto normal_char; + + + case '|': + if (syntax & RE_NO_BK_VBAR) + goto handle_alt; + else + goto normal_char; + + + case '{': + if (syntax & RE_INTERVALS && syntax & RE_NO_BK_BRACES) + goto handle_interval; + else + goto normal_char; + + + case '\\': + if (p == pend) FREE_STACK_RETURN (REG_EESCAPE); + + /* Do not translate the character after the \, so that we can + distinguish, e.g., \B from \b, even if we normally would + translate, e.g., B to b. */ + PATFETCH_RAW (c); + + switch (c) + { + case '(': + if (syntax & RE_NO_BK_PARENS) + goto normal_backslash; + + handle_open: + bufp->re_nsub++; + regnum++; + + if (COMPILE_STACK_FULL) + { + RETALLOC (compile_stack.stack, compile_stack.size << 1, + compile_stack_elt_t); + if (compile_stack.stack == NULL) return REG_ESPACE; + + compile_stack.size <<= 1; + } + + /* These are the values to restore when we hit end of this + group. They are all relative offsets, so that if the + whole pattern moves because of realloc, they will still + be valid. */ + COMPILE_STACK_TOP.begalt_offset = begalt - COMPILED_BUFFER_VAR; + COMPILE_STACK_TOP.fixup_alt_jump + = fixup_alt_jump ? fixup_alt_jump - COMPILED_BUFFER_VAR + 1 : 0; + COMPILE_STACK_TOP.laststart_offset = b - COMPILED_BUFFER_VAR; + COMPILE_STACK_TOP.regnum = regnum; + + /* We will eventually replace the 0 with the number of + groups inner to this one. But do not push a + start_memory for groups beyond the last one we can + represent in the compiled pattern. */ + if (regnum <= MAX_REGNUM) + { + COMPILE_STACK_TOP.inner_group_offset = b + - COMPILED_BUFFER_VAR + 2; + BUF_PUSH_3 (start_memory, regnum, 0); + } + + compile_stack.avail++; + + fixup_alt_jump = 0; + laststart = 0; + begalt = b; + /* If we've reached MAX_REGNUM groups, then this open + won't actually generate any code, so we'll have to + clear pending_exact explicitly. */ + pending_exact = 0; + break; + + + case ')': + if (syntax & RE_NO_BK_PARENS) goto normal_backslash; + + if (COMPILE_STACK_EMPTY) + { + if (syntax & RE_UNMATCHED_RIGHT_PAREN_ORD) + goto normal_backslash; + else + FREE_STACK_RETURN (REG_ERPAREN); + } + + handle_close: + if (fixup_alt_jump) + { /* Push a dummy failure point at the end of the + alternative for a possible future + `pop_failure_jump' to pop. See comments at + `push_dummy_failure' in `re_match_2'. */ + BUF_PUSH (push_dummy_failure); + + /* We allocated space for this jump when we assigned + to `fixup_alt_jump', in the `handle_alt' case below. */ + STORE_JUMP (jump_past_alt, fixup_alt_jump, b - 1); + } + + /* See similar code for backslashed left paren above. */ + if (COMPILE_STACK_EMPTY) + { + if (syntax & RE_UNMATCHED_RIGHT_PAREN_ORD) + goto normal_char; + else + FREE_STACK_RETURN (REG_ERPAREN); + } + + /* Since we just checked for an empty stack above, this + ``can't happen''. */ + assert (compile_stack.avail != 0); + { + /* We don't just want to restore into `regnum', because + later groups should continue to be numbered higher, + as in `(ab)c(de)' -- the second group is #2. */ + regnum_t this_group_regnum; + + compile_stack.avail--; + begalt = COMPILED_BUFFER_VAR + COMPILE_STACK_TOP.begalt_offset; + fixup_alt_jump + = COMPILE_STACK_TOP.fixup_alt_jump + ? COMPILED_BUFFER_VAR + COMPILE_STACK_TOP.fixup_alt_jump - 1 + : 0; + laststart = COMPILED_BUFFER_VAR + COMPILE_STACK_TOP.laststart_offset; + this_group_regnum = COMPILE_STACK_TOP.regnum; + /* If we've reached MAX_REGNUM groups, then this open + won't actually generate any code, so we'll have to + clear pending_exact explicitly. */ + pending_exact = 0; + + /* We're at the end of the group, so now we know how many + groups were inside this one. */ + if (this_group_regnum <= MAX_REGNUM) + { + UCHAR_T *inner_group_loc + = COMPILED_BUFFER_VAR + COMPILE_STACK_TOP.inner_group_offset; + + *inner_group_loc = regnum - this_group_regnum; + BUF_PUSH_3 (stop_memory, this_group_regnum, + regnum - this_group_regnum); + } + } + break; + + + case '|': /* `\|'. */ + if (syntax & RE_LIMITED_OPS || syntax & RE_NO_BK_VBAR) + goto normal_backslash; + handle_alt: + if (syntax & RE_LIMITED_OPS) + goto normal_char; + + /* Insert before the previous alternative a jump which + jumps to this alternative if the former fails. */ + GET_BUFFER_SPACE (1 + OFFSET_ADDRESS_SIZE); + INSERT_JUMP (on_failure_jump, begalt, + b + 2 + 2 * OFFSET_ADDRESS_SIZE); + pending_exact = 0; + b += 1 + OFFSET_ADDRESS_SIZE; + + /* The alternative before this one has a jump after it + which gets executed if it gets matched. Adjust that + jump so it will jump to this alternative's analogous + jump (put in below, which in turn will jump to the next + (if any) alternative's such jump, etc.). The last such + jump jumps to the correct final destination. A picture: + _____ _____ + | | | | + | v | v + a | b | c + + If we are at `b', then fixup_alt_jump right now points to a + three-byte space after `a'. We'll put in the jump, set + fixup_alt_jump to right after `b', and leave behind three + bytes which we'll fill in when we get to after `c'. */ + + if (fixup_alt_jump) + STORE_JUMP (jump_past_alt, fixup_alt_jump, b); + + /* Mark and leave space for a jump after this alternative, + to be filled in later either by next alternative or + when know we're at the end of a series of alternatives. */ + fixup_alt_jump = b; + GET_BUFFER_SPACE (1 + OFFSET_ADDRESS_SIZE); + b += 1 + OFFSET_ADDRESS_SIZE; + + laststart = 0; + begalt = b; + break; + + + case '{': + /* If \{ is a literal. */ + if (!(syntax & RE_INTERVALS) + /* If we're at `\{' and it's not the open-interval + operator. */ + || (syntax & RE_NO_BK_BRACES)) + goto normal_backslash; + + handle_interval: + { + /* If got here, then the syntax allows intervals. */ + + /* At least (most) this many matches must be made. */ + int lower_bound = -1, upper_bound = -1; + + /* Place in the uncompiled pattern (i.e., just after + the '{') to go back to if the interval is invalid. */ + const CHAR_T *beg_interval = p; + + if (p == pend) + goto invalid_interval; + + GET_UNSIGNED_NUMBER (lower_bound); + + if (c == ',') + { + GET_UNSIGNED_NUMBER (upper_bound); + if (upper_bound < 0) + upper_bound = RE_DUP_MAX; + } + else + /* Interval such as `{1}' => match exactly once. */ + upper_bound = lower_bound; + + if (! (0 <= lower_bound && lower_bound <= upper_bound)) + goto invalid_interval; + + if (!(syntax & RE_NO_BK_BRACES)) + { + if (c != '\\' || p == pend) + goto invalid_interval; + PATFETCH (c); + } + + if (c != '}') + goto invalid_interval; + + /* If it's invalid to have no preceding re. */ + if (!laststart) + { + if (syntax & RE_CONTEXT_INVALID_OPS + && !(syntax & RE_INVALID_INTERVAL_ORD)) + FREE_STACK_RETURN (REG_BADRPT); + else if (syntax & RE_CONTEXT_INDEP_OPS) + laststart = b; + else + goto unfetch_interval; + } + + /* We just parsed a valid interval. */ + + if (RE_DUP_MAX < upper_bound) + FREE_STACK_RETURN (REG_BADBR); + + /* If the upper bound is zero, don't want to succeed at + all; jump from `laststart' to `b + 3', which will be + the end of the buffer after we insert the jump. */ + /* ifdef WCHAR, 'b + 1 + OFFSET_ADDRESS_SIZE' + instead of 'b + 3'. */ + if (upper_bound == 0) + { + GET_BUFFER_SPACE (1 + OFFSET_ADDRESS_SIZE); + INSERT_JUMP (jump, laststart, b + 1 + + OFFSET_ADDRESS_SIZE); + b += 1 + OFFSET_ADDRESS_SIZE; + } + + /* Otherwise, we have a nontrivial interval. When + we're all done, the pattern will look like: + set_number_at + set_number_at + succeed_n + + jump_n + (The upper bound and `jump_n' are omitted if + `upper_bound' is 1, though.) */ + else + { /* If the upper bound is > 1, we need to insert + more at the end of the loop. */ + unsigned nbytes = 2 + 4 * OFFSET_ADDRESS_SIZE + + (upper_bound > 1) * (2 + 4 * OFFSET_ADDRESS_SIZE); + + GET_BUFFER_SPACE (nbytes); + + /* Initialize lower bound of the `succeed_n', even + though it will be set during matching by its + attendant `set_number_at' (inserted next), + because `re_compile_fastmap' needs to know. + Jump to the `jump_n' we might insert below. */ + INSERT_JUMP2 (succeed_n, laststart, + b + 1 + 2 * OFFSET_ADDRESS_SIZE + + (upper_bound > 1) * (1 + 2 * OFFSET_ADDRESS_SIZE) + , lower_bound); + b += 1 + 2 * OFFSET_ADDRESS_SIZE; + + /* Code to initialize the lower bound. Insert + before the `succeed_n'. The `5' is the last two + bytes of this `set_number_at', plus 3 bytes of + the following `succeed_n'. */ + /* ifdef WCHAR, The '1+2*OFFSET_ADDRESS_SIZE' + is the 'set_number_at', plus '1+OFFSET_ADDRESS_SIZE' + of the following `succeed_n'. */ + PREFIX(insert_op2) (set_number_at, laststart, 1 + + 2 * OFFSET_ADDRESS_SIZE, lower_bound, b); + b += 1 + 2 * OFFSET_ADDRESS_SIZE; + + if (upper_bound > 1) + { /* More than one repetition is allowed, so + append a backward jump to the `succeed_n' + that starts this interval. + + When we've reached this during matching, + we'll have matched the interval once, so + jump back only `upper_bound - 1' times. */ + STORE_JUMP2 (jump_n, b, laststart + + 2 * OFFSET_ADDRESS_SIZE + 1, + upper_bound - 1); + b += 1 + 2 * OFFSET_ADDRESS_SIZE; + + /* The location we want to set is the second + parameter of the `jump_n'; that is `b-2' as + an absolute address. `laststart' will be + the `set_number_at' we're about to insert; + `laststart+3' the number to set, the source + for the relative address. But we are + inserting into the middle of the pattern -- + so everything is getting moved up by 5. + Conclusion: (b - 2) - (laststart + 3) + 5, + i.e., b - laststart. + + We insert this at the beginning of the loop + so that if we fail during matching, we'll + reinitialize the bounds. */ + PREFIX(insert_op2) (set_number_at, laststart, + b - laststart, + upper_bound - 1, b); + b += 1 + 2 * OFFSET_ADDRESS_SIZE; + } + } + pending_exact = 0; + break; + + invalid_interval: + if (!(syntax & RE_INVALID_INTERVAL_ORD)) + FREE_STACK_RETURN (p == pend ? REG_EBRACE : REG_BADBR); + unfetch_interval: + /* Match the characters as literals. */ + p = beg_interval; + c = '{'; + if (syntax & RE_NO_BK_BRACES) + goto normal_char; + else + goto normal_backslash; + } + +#ifdef emacs + /* There is no way to specify the before_dot and after_dot + operators. rms says this is ok. --karl */ + case '=': + BUF_PUSH (at_dot); + break; + + case 's': + laststart = b; + PATFETCH (c); + BUF_PUSH_2 (syntaxspec, syntax_spec_code[c]); + break; + + case 'S': + laststart = b; + PATFETCH (c); + BUF_PUSH_2 (notsyntaxspec, syntax_spec_code[c]); + break; +#endif /* emacs */ + + + case 'w': + if (syntax & RE_NO_GNU_OPS) + goto normal_char; + laststart = b; + BUF_PUSH (wordchar); + break; + + + case 'W': + if (syntax & RE_NO_GNU_OPS) + goto normal_char; + laststart = b; + BUF_PUSH (notwordchar); + break; + + + case '<': + if (syntax & RE_NO_GNU_OPS) + goto normal_char; + BUF_PUSH (wordbeg); + break; + + case '>': + if (syntax & RE_NO_GNU_OPS) + goto normal_char; + BUF_PUSH (wordend); + break; + + case 'b': + if (syntax & RE_NO_GNU_OPS) + goto normal_char; + BUF_PUSH (wordbound); + break; + + case 'B': + if (syntax & RE_NO_GNU_OPS) + goto normal_char; + BUF_PUSH (notwordbound); + break; + + case '`': + if (syntax & RE_NO_GNU_OPS) + goto normal_char; + BUF_PUSH (begbuf); + break; + + case '\'': + if (syntax & RE_NO_GNU_OPS) + goto normal_char; + BUF_PUSH (endbuf); + break; + + case '1': case '2': case '3': case '4': case '5': + case '6': case '7': case '8': case '9': + if (syntax & RE_NO_BK_REFS) + goto normal_char; + + c1 = c - '0'; + + if (c1 > regnum) + FREE_STACK_RETURN (REG_ESUBREG); + + /* Can't back reference to a subexpression if inside of it. */ + if (group_in_compile_stack (compile_stack, (regnum_t) c1)) + goto normal_char; + + laststart = b; + BUF_PUSH_2 (duplicate, c1); + break; + + + case '+': + case '?': + if (syntax & RE_BK_PLUS_QM) + goto handle_plus; + else + goto normal_backslash; + + default: + normal_backslash: + /* You might think it would be useful for \ to mean + not to translate; but if we don't translate it + it will never match anything. */ + c = TRANSLATE (c); + goto normal_char; + } + break; + + + default: + /* Expects the character in `c'. */ + normal_char: + /* If no exactn currently being built. */ + if (!pending_exact +#ifdef WCHAR + /* If last exactn handle binary(or character) and + new exactn handle character(or binary). */ + || is_exactn_bin != is_binary[p - 1 - pattern] +#endif /* WCHAR */ + + /* If last exactn not at current position. */ + || pending_exact + *pending_exact + 1 != b + + /* We have only one byte following the exactn for the count. */ + || *pending_exact == (1 << BYTEWIDTH) - 1 + + /* If followed by a repetition operator. */ + || *p == '*' || *p == '^' + || ((syntax & RE_BK_PLUS_QM) + ? *p == '\\' && (p[1] == '+' || p[1] == '?') + : (*p == '+' || *p == '?')) + || ((syntax & RE_INTERVALS) + && ((syntax & RE_NO_BK_BRACES) + ? *p == '{' + : (p[0] == '\\' && p[1] == '{')))) + { + /* Start building a new exactn. */ + + laststart = b; + +#ifdef WCHAR + /* Is this exactn binary data or character? */ + is_exactn_bin = is_binary[p - 1 - pattern]; + if (is_exactn_bin) + BUF_PUSH_2 (exactn_bin, 0); + else + BUF_PUSH_2 (exactn, 0); +#else + BUF_PUSH_2 (exactn, 0); +#endif /* WCHAR */ + pending_exact = b - 1; + } + + BUF_PUSH (c); + (*pending_exact)++; + break; + } /* switch (c) */ + } /* while p != pend */ + + + /* Through the pattern now. */ + + if (fixup_alt_jump) + STORE_JUMP (jump_past_alt, fixup_alt_jump, b); + + if (!COMPILE_STACK_EMPTY) + FREE_STACK_RETURN (REG_EPAREN); + + /* If we don't want backtracking, force success + the first time we reach the end of the compiled pattern. */ + if (syntax & RE_NO_POSIX_BACKTRACKING) + BUF_PUSH (succeed); + +#ifdef WCHAR + free (pattern); + free (mbs_offset); + free (is_binary); +#endif + free (compile_stack.stack); + + /* We have succeeded; set the length of the buffer. */ +#ifdef WCHAR + bufp->used = (uintptr_t) b - (uintptr_t) COMPILED_BUFFER_VAR; +#else + bufp->used = b - bufp->buffer; +#endif + +#ifdef DEBUG + if (debug) + { + DEBUG_PRINT1 ("\nCompiled pattern: \n"); + PREFIX(print_compiled_pattern) (bufp); + } +#endif /* DEBUG */ + +#ifndef MATCH_MAY_ALLOCATE + /* Initialize the failure stack to the largest possible stack. This + isn't necessary unless we're trying to avoid calling alloca in + the search and match routines. */ + { + int num_regs = bufp->re_nsub + 1; + + /* Since DOUBLE_FAIL_STACK refuses to double only if the current size + is strictly greater than re_max_failures, the largest possible stack + is 2 * re_max_failures failure points. */ + if (fail_stack.size < (2 * re_max_failures * MAX_FAILURE_ITEMS)) + { + fail_stack.size = (2 * re_max_failures * MAX_FAILURE_ITEMS); + +# ifdef emacs + if (! fail_stack.stack) + fail_stack.stack + = (PREFIX(fail_stack_elt_t) *) xmalloc (fail_stack.size + * sizeof (PREFIX(fail_stack_elt_t))); + else + fail_stack.stack + = (PREFIX(fail_stack_elt_t) *) xrealloc (fail_stack.stack, + (fail_stack.size + * sizeof (PREFIX(fail_stack_elt_t)))); +# else /* not emacs */ + if (! fail_stack.stack) + fail_stack.stack + = (PREFIX(fail_stack_elt_t) *) malloc (fail_stack.size + * sizeof (PREFIX(fail_stack_elt_t))); + else + fail_stack.stack + = (PREFIX(fail_stack_elt_t) *) realloc (fail_stack.stack, + (fail_stack.size + * sizeof (PREFIX(fail_stack_elt_t)))); +# endif /* not emacs */ + } + + PREFIX(regex_grow_registers) (num_regs); + } +#endif /* not MATCH_MAY_ALLOCATE */ + + return REG_NOERROR; +} /* regex_compile */ + +/* Subroutines for `regex_compile'. */ + +/* Store OP at LOC followed by two-byte integer parameter ARG. */ +/* ifdef WCHAR, integer parameter is 1 wchar_t. */ + +static void +PREFIX(store_op1) ( + re_opcode_t op, + UCHAR_T *loc, + int arg) +{ + *loc = (UCHAR_T) op; + STORE_NUMBER (loc + 1, arg); +} + + +/* Like `store_op1', but for two two-byte parameters ARG1 and ARG2. */ +/* ifdef WCHAR, integer parameter is 1 wchar_t. */ + +static void +PREFIX(store_op2) ( + re_opcode_t op, + UCHAR_T *loc, + int arg1, int arg2) +{ + *loc = (UCHAR_T) op; + STORE_NUMBER (loc + 1, arg1); + STORE_NUMBER (loc + 1 + OFFSET_ADDRESS_SIZE, arg2); +} + + +/* Copy the bytes from LOC to END to open up three bytes of space at LOC + for OP followed by two-byte integer parameter ARG. */ +/* ifdef WCHAR, integer parameter is 1 wchar_t. */ + +static void +PREFIX(insert_op1) ( + re_opcode_t op, + UCHAR_T *loc, + int arg, + UCHAR_T *end) +{ + register UCHAR_T *pfrom = end; + register UCHAR_T *pto = end + 1 + OFFSET_ADDRESS_SIZE; + + while (pfrom != loc) + *--pto = *--pfrom; + + PREFIX(store_op1) (op, loc, arg); +} + + +/* Like `insert_op1', but for two two-byte parameters ARG1 and ARG2. */ +/* ifdef WCHAR, integer parameter is 1 wchar_t. */ + +static void +PREFIX(insert_op2) ( + re_opcode_t op, + UCHAR_T *loc, + int arg1, int arg2, + UCHAR_T *end) +{ + register UCHAR_T *pfrom = end; + register UCHAR_T *pto = end + 1 + 2 * OFFSET_ADDRESS_SIZE; + + while (pfrom != loc) + *--pto = *--pfrom; + + PREFIX(store_op2) (op, loc, arg1, arg2); +} + + +/* P points to just after a ^ in PATTERN. Return true if that ^ comes + after an alternative or a begin-subexpression. We assume there is at + least one character before the ^. */ + +static boolean +PREFIX(at_begline_loc_p) ( + const CHAR_T *pattern, const CHAR_T *p, + reg_syntax_t syntax) +{ + const CHAR_T *prev = p - 2; + boolean prev_prev_backslash = prev > pattern && prev[-1] == '\\'; + + return + /* After a subexpression? */ + (*prev == '(' && (syntax & RE_NO_BK_PARENS || prev_prev_backslash)) + /* After an alternative? */ + || (*prev == '|' && (syntax & RE_NO_BK_VBAR || prev_prev_backslash)); +} + + +/* The dual of at_begline_loc_p. This one is for $. We assume there is + at least one character after the $, i.e., `P < PEND'. */ + +static boolean +PREFIX(at_endline_loc_p) ( + const CHAR_T *p, const CHAR_T *pend, + reg_syntax_t syntax) +{ + const CHAR_T *next = p; + boolean next_backslash = *next == '\\'; + const CHAR_T *next_next = p + 1 < pend ? p + 1 : 0; + + return + /* Before a subexpression? */ + (syntax & RE_NO_BK_PARENS ? *next == ')' + : next_backslash && next_next && *next_next == ')') + /* Before an alternative? */ + || (syntax & RE_NO_BK_VBAR ? *next == '|' + : next_backslash && next_next && *next_next == '|'); +} + +#else /* not INSIDE_RECURSION */ + +/* Returns true if REGNUM is in one of COMPILE_STACK's elements and + false if it's not. */ + +static boolean +group_in_compile_stack ( + compile_stack_type compile_stack, + regnum_t regnum) +{ + int this_element; + + for (this_element = compile_stack.avail - 1; + this_element >= 0; + this_element--) + if (compile_stack.stack[this_element].regnum == regnum) + return true; + + return false; +} +#endif /* not INSIDE_RECURSION */ + +#ifdef INSIDE_RECURSION + +#ifdef WCHAR +/* This insert space, which size is "num", into the pattern at "loc". + "end" must point the end of the allocated buffer. */ +static void +insert_space ( + int num, + CHAR_T *loc, + CHAR_T *end) +{ + register CHAR_T *pto = end; + register CHAR_T *pfrom = end - num; + + while (pfrom >= loc) + *pto-- = *pfrom--; +} +#endif /* WCHAR */ + +#ifdef WCHAR +static reg_errcode_t +wcs_compile_range ( + CHAR_T range_start_char, + const CHAR_T **p_ptr, const CHAR_T *pend, + RE_TRANSLATE_TYPE translate, + reg_syntax_t syntax, + CHAR_T *b, CHAR_T *char_set) +{ + const CHAR_T *p = *p_ptr; + CHAR_T range_start, range_end; + reg_errcode_t ret; +# ifdef _LIBC + uint32_t nrules; + uint32_t start_val, end_val; +# endif + if (p == pend) + return REG_ERANGE; + +# ifdef _LIBC + nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); + if (nrules != 0) + { + const char *collseq = (const char *) _NL_CURRENT(LC_COLLATE, + _NL_COLLATE_COLLSEQWC); + const unsigned char *extra = (const unsigned char *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_EXTRAMB); + + if (range_start_char < -1) + { + /* range_start is a collating symbol. */ + int32_t *wextra; + /* Retreive the index and get collation sequence value. */ + wextra = (int32_t*)(extra + char_set[-range_start_char]); + start_val = wextra[1 + *wextra]; + } + else + start_val = collseq_table_lookup(collseq, TRANSLATE(range_start_char)); + + end_val = collseq_table_lookup (collseq, TRANSLATE (p[0])); + + /* Report an error if the range is empty and the syntax prohibits + this. */ + ret = ((syntax & RE_NO_EMPTY_RANGES) + && (start_val > end_val))? REG_ERANGE : REG_NOERROR; + + /* Insert space to the end of the char_ranges. */ + insert_space(2, b - char_set[5] - 2, b - 1); + *(b - char_set[5] - 2) = (wchar_t)start_val; + *(b - char_set[5] - 1) = (wchar_t)end_val; + char_set[4]++; /* ranges_index */ + } + else +# endif + { + range_start = (range_start_char >= 0)? TRANSLATE (range_start_char): + range_start_char; + range_end = TRANSLATE (p[0]); + /* Report an error if the range is empty and the syntax prohibits + this. */ + ret = ((syntax & RE_NO_EMPTY_RANGES) + && (range_start > range_end))? REG_ERANGE : REG_NOERROR; + + /* Insert space to the end of the char_ranges. */ + insert_space(2, b - char_set[5] - 2, b - 1); + *(b - char_set[5] - 2) = range_start; + *(b - char_set[5] - 1) = range_end; + char_set[4]++; /* ranges_index */ + } + /* Have to increment the pointer into the pattern string, so the + caller isn't still at the ending character. */ + (*p_ptr)++; + + return ret; +} +#else /* BYTE */ +/* Read the ending character of a range (in a bracket expression) from the + uncompiled pattern *P_PTR (which ends at PEND). We assume the + starting character is in `P[-2]'. (`P[-1]' is the character `-'.) + Then we set the translation of all bits between the starting and + ending characters (inclusive) in the compiled pattern B. + + Return an error code. + + We use these short variable names so we can use the same macros as + `regex_compile' itself. */ + +static reg_errcode_t +byte_compile_range ( + unsigned int range_start_char, + const char **p_ptr, const char *pend, + RE_TRANSLATE_TYPE translate, + reg_syntax_t syntax, + unsigned char *b) +{ + unsigned this_char; + const char *p = *p_ptr; + reg_errcode_t ret; +# ifdef _LIBC + const unsigned char *collseq; + unsigned int start_colseq; + unsigned int end_colseq; +# else + unsigned end_char; +# endif + + if (p == pend) + return REG_ERANGE; + + /* Have to increment the pointer into the pattern string, so the + caller isn't still at the ending character. */ + (*p_ptr)++; + + /* Report an error if the range is empty and the syntax prohibits this. */ + ret = syntax & RE_NO_EMPTY_RANGES ? REG_ERANGE : REG_NOERROR; + +# ifdef _LIBC + collseq = (const unsigned char *) _NL_CURRENT (LC_COLLATE, + _NL_COLLATE_COLLSEQMB); + + start_colseq = collseq[(unsigned char) TRANSLATE (range_start_char)]; + end_colseq = collseq[(unsigned char) TRANSLATE (p[0])]; + for (this_char = 0; this_char <= (unsigned char) -1; ++this_char) + { + unsigned int this_colseq = collseq[(unsigned char) TRANSLATE (this_char)]; + + if (start_colseq <= this_colseq && this_colseq <= end_colseq) + { + SET_LIST_BIT (TRANSLATE (this_char)); + ret = REG_NOERROR; + } + } +# else + /* Here we see why `this_char' has to be larger than an `unsigned + char' -- we would otherwise go into an infinite loop, since all + characters <= 0xff. */ + range_start_char = TRANSLATE (range_start_char); + /* TRANSLATE(p[0]) is casted to char (not unsigned char) in TRANSLATE, + and some compilers cast it to int implicitly, so following for_loop + may fall to (almost) infinite loop. + e.g. If translate[p[0]] = 0xff, end_char may equals to 0xffffffff. + To avoid this, we cast p[0] to unsigned int and truncate it. */ + end_char = ((unsigned)TRANSLATE(p[0]) & ((1 << BYTEWIDTH) - 1)); + + for (this_char = range_start_char; this_char <= end_char; ++this_char) + { + SET_LIST_BIT (TRANSLATE (this_char)); + ret = REG_NOERROR; + } +# endif + + return ret; +} +#endif /* WCHAR */ + +/* re_compile_fastmap computes a ``fastmap'' for the compiled pattern in + BUFP. A fastmap records which of the (1 << BYTEWIDTH) possible + characters can start a string that matches the pattern. This fastmap + is used by re_search to skip quickly over impossible starting points. + + The caller must supply the address of a (1 << BYTEWIDTH)-byte data + area as BUFP->fastmap. + + We set the `fastmap', `fastmap_accurate', and `can_be_null' fields in + the pattern buffer. + + Returns 0 if we succeed, -2 if an internal error. */ + +#ifdef WCHAR +/* local function for re_compile_fastmap. + truncate wchar_t character to char. */ +static unsigned char truncate_wchar (CHAR_T c) +{ + unsigned char buf[MB_CUR_MAX]; + mbstate_t state; + int retval; + memset (&state, '\0', sizeof (state)); +# ifdef _LIBC + retval = __wcrtomb (buf, c, &state); +# else + retval = wcrtomb (buf, c, &state); +# endif + return retval > 0 ? buf[0] : (unsigned char) c; +} +#endif /* WCHAR */ + +static int +PREFIX(re_compile_fastmap) (struct re_pattern_buffer *bufp) +{ + int j, k; +#ifdef MATCH_MAY_ALLOCATE + PREFIX(fail_stack_type) fail_stack; +#endif +#ifndef REGEX_MALLOC + char *destination; +#endif + + register char *fastmap = bufp->fastmap; + +#ifdef WCHAR + /* We need to cast pattern to (wchar_t*), because we casted this compiled + pattern to (char*) in regex_compile. */ + UCHAR_T *pattern = (UCHAR_T*)bufp->buffer; + register UCHAR_T *pend = (UCHAR_T*) (bufp->buffer + bufp->used); +#else /* BYTE */ + UCHAR_T *pattern = bufp->buffer; + register UCHAR_T *pend = pattern + bufp->used; +#endif /* WCHAR */ + UCHAR_T *p = pattern; + +#ifdef REL_ALLOC + /* This holds the pointer to the failure stack, when + it is allocated relocatably. */ + fail_stack_elt_t *failure_stack_ptr; +#endif + + /* Assume that each path through the pattern can be null until + proven otherwise. We set this false at the bottom of switch + statement, to which we get only if a particular path doesn't + match the empty string. */ + boolean path_can_be_null = true; + + /* We aren't doing a `succeed_n' to begin with. */ + boolean succeed_n_p = false; + + assert (fastmap != NULL && p != NULL); + + INIT_FAIL_STACK (); + bzero (fastmap, 1 << BYTEWIDTH); /* Assume nothing's valid. */ + bufp->fastmap_accurate = 1; /* It will be when we're done. */ + bufp->can_be_null = 0; + + while (1) + { + if (p == pend || *p == succeed) + { + /* We have reached the (effective) end of pattern. */ + if (!FAIL_STACK_EMPTY ()) + { + bufp->can_be_null |= path_can_be_null; + + /* Reset for next path. */ + path_can_be_null = true; + + p = fail_stack.stack[--fail_stack.avail].pointer; + + continue; + } + else + break; + } + + /* We should never be about to go beyond the end of the pattern. */ + assert (p < pend); + + switch (SWITCH_ENUM_CAST ((re_opcode_t) *p++)) + { + + /* I guess the idea here is to simply not bother with a fastmap + if a backreference is used, since it's too hard to figure out + the fastmap for the corresponding group. Setting + `can_be_null' stops `re_search_2' from using the fastmap, so + that is all we do. */ + case duplicate: + bufp->can_be_null = 1; + goto done; + + + /* Following are the cases which match a character. These end + with `break'. */ + +#ifdef WCHAR + case exactn: + fastmap[truncate_wchar(p[1])] = 1; + break; +#else /* BYTE */ + case exactn: + fastmap[p[1]] = 1; + break; +#endif /* WCHAR */ +#ifdef MBS_SUPPORT + case exactn_bin: + fastmap[p[1]] = 1; + break; +#endif + +#ifdef WCHAR + /* It is hard to distinguish fastmap from (multi byte) characters + which depends on current locale. */ + case charset: + case charset_not: + case wordchar: + case notwordchar: + bufp->can_be_null = 1; + goto done; +#else /* BYTE */ + case charset: + for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--) + if (p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH))) + fastmap[j] = 1; + break; + + + case charset_not: + /* Chars beyond end of map must be allowed. */ + for (j = *p * BYTEWIDTH; j < (1 << BYTEWIDTH); j++) + fastmap[j] = 1; + + for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--) + if (!(p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH)))) + fastmap[j] = 1; + break; + + + case wordchar: + for (j = 0; j < (1 << BYTEWIDTH); j++) + if (SYNTAX (j) == Sword) + fastmap[j] = 1; + break; + + + case notwordchar: + for (j = 0; j < (1 << BYTEWIDTH); j++) + if (SYNTAX (j) != Sword) + fastmap[j] = 1; + break; +#endif /* WCHAR */ + + case anychar: + { + int fastmap_newline = fastmap['\n']; + + /* `.' matches anything ... */ + for (j = 0; j < (1 << BYTEWIDTH); j++) + fastmap[j] = 1; + + /* ... except perhaps newline. */ + if (!(bufp->syntax & RE_DOT_NEWLINE)) + fastmap['\n'] = fastmap_newline; + + /* Return if we have already set `can_be_null'; if we have, + then the fastmap is irrelevant. Something's wrong here. */ + else if (bufp->can_be_null) + goto done; + + /* Otherwise, have to check alternative paths. */ + break; + } + +#ifdef emacs + case syntaxspec: + k = *p++; + for (j = 0; j < (1 << BYTEWIDTH); j++) + if (SYNTAX (j) == (enum syntaxcode) k) + fastmap[j] = 1; + break; + + + case notsyntaxspec: + k = *p++; + for (j = 0; j < (1 << BYTEWIDTH); j++) + if (SYNTAX (j) != (enum syntaxcode) k) + fastmap[j] = 1; + break; + + + /* All cases after this match the empty string. These end with + `continue'. */ + + + case before_dot: + case at_dot: + case after_dot: + continue; +#endif /* emacs */ + + + case no_op: + case begline: + case endline: + case begbuf: + case endbuf: + case wordbound: + case notwordbound: + case wordbeg: + case wordend: + case push_dummy_failure: + continue; + + + case jump_n: + case pop_failure_jump: + case maybe_pop_jump: + case jump: + case jump_past_alt: + case dummy_failure_jump: + EXTRACT_NUMBER_AND_INCR (j, p); + p += j; + if (j > 0) + continue; + + /* Jump backward implies we just went through the body of a + loop and matched nothing. Opcode jumped to should be + `on_failure_jump' or `succeed_n'. Just treat it like an + ordinary jump. For a * loop, it has pushed its failure + point already; if so, discard that as redundant. */ + if ((re_opcode_t) *p != on_failure_jump + && (re_opcode_t) *p != succeed_n) + continue; + + p++; + EXTRACT_NUMBER_AND_INCR (j, p); + p += j; + + /* If what's on the stack is where we are now, pop it. */ + if (!FAIL_STACK_EMPTY () + && fail_stack.stack[fail_stack.avail - 1].pointer == p) + fail_stack.avail--; + + continue; + + + case on_failure_jump: + case on_failure_keep_string_jump: + handle_on_failure_jump: + EXTRACT_NUMBER_AND_INCR (j, p); + + /* For some patterns, e.g., `(a?)?', `p+j' here points to the + end of the pattern. We don't want to push such a point, + since when we restore it above, entering the switch will + increment `p' past the end of the pattern. We don't need + to push such a point since we obviously won't find any more + fastmap entries beyond `pend'. Such a pattern can match + the null string, though. */ + if (p + j < pend) + { + if (!PUSH_PATTERN_OP (p + j, fail_stack)) + { + RESET_FAIL_STACK (); + return -2; + } + } + else + bufp->can_be_null = 1; + + if (succeed_n_p) + { + EXTRACT_NUMBER_AND_INCR (k, p); /* Skip the n. */ + succeed_n_p = false; + } + + continue; + + + case succeed_n: + /* Get to the number of times to succeed. */ + p += OFFSET_ADDRESS_SIZE; + + /* Increment p past the n for when k != 0. */ + EXTRACT_NUMBER_AND_INCR (k, p); + if (k == 0) + { + p -= 2 * OFFSET_ADDRESS_SIZE; + succeed_n_p = true; /* Spaghetti code alert. */ + goto handle_on_failure_jump; + } + continue; + + + case set_number_at: + p += 2 * OFFSET_ADDRESS_SIZE; + continue; + + + case start_memory: + case stop_memory: + p += 2; + continue; + + + default: + abort (); /* We have listed all the cases. */ + } /* switch *p++ */ + + /* Getting here means we have found the possible starting + characters for one path of the pattern -- and that the empty + string does not match. We need not follow this path further. + Instead, look at the next alternative (remembered on the + stack), or quit if no more. The test at the top of the loop + does these things. */ + path_can_be_null = false; + p = pend; + } /* while p */ + + /* Set `can_be_null' for the last path (also the first path, if the + pattern is empty). */ + bufp->can_be_null |= path_can_be_null; + + done: + RESET_FAIL_STACK (); + return 0; +} + +#else /* not INSIDE_RECURSION */ + +int +re_compile_fastmap (struct re_pattern_buffer *bufp) +{ +# ifdef MBS_SUPPORT + if (MB_CUR_MAX != 1) + return wcs_re_compile_fastmap(bufp); +# endif + return byte_re_compile_fastmap(bufp); +} +libc_hidden_def(re_compile_fastmap) + + +/* Set REGS to hold NUM_REGS registers, storing them in STARTS and + ENDS. Subsequent matches using PATTERN_BUFFER and REGS will use + this memory for recording register information. STARTS and ENDS + must be allocated using the malloc library routine, and must each + be at least NUM_REGS * sizeof (regoff_t) bytes long. + + If NUM_REGS == 0, then subsequent matches should allocate their own + register data. + + Unless this function is called, the first search or match using + PATTERN_BUFFER will allocate its own register data, without + freeing the old data. */ + +void +re_set_registers ( + struct re_pattern_buffer *bufp, + struct re_registers *regs, + unsigned num_regs, + regoff_t *starts, regoff_t *ends) +{ + if (num_regs) + { + bufp->regs_allocated = REGS_REALLOCATE; + regs->num_regs = num_regs; + regs->start = starts; + regs->end = ends; + } + else + { + bufp->regs_allocated = REGS_UNALLOCATED; + regs->num_regs = 0; + regs->start = regs->end = (regoff_t *) 0; + } +} + +/* Searching routines. */ + +/* Like re_search_2, below, but only one string is specified, and + doesn't let you say where to stop matching. */ + +int +re_search ( + struct re_pattern_buffer *bufp, + const char *string, + int size, int startpos, int range, + struct re_registers *regs) +{ + return re_search_2 (bufp, NULL, 0, string, size, startpos, range, + regs, size); +} +libc_hidden_def(re_search) + + +/* Using the compiled pattern in BUFP->buffer, first tries to match the + virtual concatenation of STRING1 and STRING2, starting first at index + STARTPOS, then at STARTPOS + 1, and so on. + + STRING1 and STRING2 have length SIZE1 and SIZE2, respectively. + + RANGE is how far to scan while trying to match. RANGE = 0 means try + only at STARTPOS; in general, the last start tried is STARTPOS + + RANGE. + + In REGS, return the indices of the virtual concatenation of STRING1 + and STRING2 that matched the entire BUFP->buffer and its contained + subexpressions. + + Do not consider matching one past the index STOP in the virtual + concatenation of STRING1 and STRING2. + + We return either the position in the strings at which the match was + found, -1 if no match, or -2 if error (such as failure + stack overflow). */ + +int +re_search_2 ( + struct re_pattern_buffer *bufp, + const char *string1, int size1, + const char *string2, int size2, + int startpos, + int range, + struct re_registers *regs, + int stop) +{ +# ifdef MBS_SUPPORT + if (MB_CUR_MAX != 1) + return wcs_re_search_2 (bufp, string1, size1, string2, size2, startpos, + range, regs, stop); +# endif + return byte_re_search_2 (bufp, string1, size1, string2, size2, startpos, + range, regs, stop); +} +libc_hidden_def(re_search_2) + +#endif /* not INSIDE_RECURSION */ + +#ifdef INSIDE_RECURSION + +#ifdef MATCH_MAY_ALLOCATE +# define FREE_VAR(var) if (var) REGEX_FREE (var); var = NULL +#else +# define FREE_VAR(var) free (var); var = NULL +#endif + +#ifdef WCHAR +# define MAX_ALLOCA_SIZE 2000 + +# define FREE_WCS_BUFFERS() \ + do { \ + if (size1 > MAX_ALLOCA_SIZE) \ + { \ + free (wcs_string1); \ + free (mbs_offset1); \ + } \ + else \ + { \ + FREE_VAR (wcs_string1); \ + FREE_VAR (mbs_offset1); \ + } \ + if (size2 > MAX_ALLOCA_SIZE) \ + { \ + free (wcs_string2); \ + free (mbs_offset2); \ + } \ + else \ + { \ + FREE_VAR (wcs_string2); \ + FREE_VAR (mbs_offset2); \ + } \ + } while (0) + +#endif + + +static int +PREFIX(re_search_2) ( + struct re_pattern_buffer *bufp, + const char *string1, int size1, + const char *string2, int size2, + int startpos, + int range, + struct re_registers *regs, + int stop) +{ + int val; + register char *fastmap = bufp->fastmap; + register RE_TRANSLATE_TYPE translate = bufp->translate; + int total_size = size1 + size2; + int endpos = startpos + range; +#ifdef WCHAR + /* We need wchar_t* buffers correspond to cstring1, cstring2. */ + wchar_t *wcs_string1 = NULL, *wcs_string2 = NULL; + /* We need the size of wchar_t buffers correspond to csize1, csize2. */ + int wcs_size1 = 0, wcs_size2 = 0; + /* offset buffer for optimization. See convert_mbs_to_wc. */ + int *mbs_offset1 = NULL, *mbs_offset2 = NULL; + /* They hold whether each wchar_t is binary data or not. */ + char *is_binary = NULL; +#endif /* WCHAR */ + + /* Check for out-of-range STARTPOS. */ + if (startpos < 0 || startpos > total_size) + return -1; + + /* Fix up RANGE if it might eventually take us outside + the virtual concatenation of STRING1 and STRING2. + Make sure we won't move STARTPOS below 0 or above TOTAL_SIZE. */ + if (endpos < 0) + range = 0 - startpos; + else if (endpos > total_size) + range = total_size - startpos; + + /* If the search isn't to be a backwards one, don't waste time in a + search for a pattern that must be anchored. */ + if (bufp->used > 0 && range > 0 + && ((re_opcode_t) bufp->buffer[0] == begbuf + /* `begline' is like `begbuf' if it cannot match at newlines. */ + || ((re_opcode_t) bufp->buffer[0] == begline + && !bufp->newline_anchor))) + { + if (startpos > 0) + return -1; + else + range = 1; + } + +#ifdef emacs + /* In a forward search for something that starts with \=. + don't keep searching past point. */ + if (bufp->used > 0 && (re_opcode_t) bufp->buffer[0] == at_dot && range > 0) + { + range = PT - startpos; + if (range <= 0) + return -1; + } +#endif /* emacs */ + + /* Update the fastmap now if not correct already. */ + if (fastmap && !bufp->fastmap_accurate) + if (re_compile_fastmap (bufp) == -2) + return -2; + +#ifdef WCHAR + /* Allocate wchar_t array for wcs_string1 and wcs_string2 and + fill them with converted string. */ + if (size1 != 0) + { + if (size1 > MAX_ALLOCA_SIZE) + { + wcs_string1 = TALLOC (size1 + 1, CHAR_T); + mbs_offset1 = TALLOC (size1 + 1, int); + is_binary = TALLOC (size1 + 1, char); + } + else + { + wcs_string1 = REGEX_TALLOC (size1 + 1, CHAR_T); + mbs_offset1 = REGEX_TALLOC (size1 + 1, int); + is_binary = REGEX_TALLOC (size1 + 1, char); + } + if (!wcs_string1 || !mbs_offset1 || !is_binary) + { + if (size1 > MAX_ALLOCA_SIZE) + { + free (wcs_string1); + free (mbs_offset1); + free (is_binary); + } + else + { + FREE_VAR (wcs_string1); + FREE_VAR (mbs_offset1); + FREE_VAR (is_binary); + } + return -2; + } + wcs_size1 = convert_mbs_to_wcs(wcs_string1, string1, size1, + mbs_offset1, is_binary); + wcs_string1[wcs_size1] = L'\0'; /* for a sentinel */ + if (size1 > MAX_ALLOCA_SIZE) + free (is_binary); + else + FREE_VAR (is_binary); + } + if (size2 != 0) + { + if (size2 > MAX_ALLOCA_SIZE) + { + wcs_string2 = TALLOC (size2 + 1, CHAR_T); + mbs_offset2 = TALLOC (size2 + 1, int); + is_binary = TALLOC (size2 + 1, char); + } + else + { + wcs_string2 = REGEX_TALLOC (size2 + 1, CHAR_T); + mbs_offset2 = REGEX_TALLOC (size2 + 1, int); + is_binary = REGEX_TALLOC (size2 + 1, char); + } + if (!wcs_string2 || !mbs_offset2 || !is_binary) + { + FREE_WCS_BUFFERS (); + if (size2 > MAX_ALLOCA_SIZE) + free (is_binary); + else + FREE_VAR (is_binary); + return -2; + } + wcs_size2 = convert_mbs_to_wcs(wcs_string2, string2, size2, + mbs_offset2, is_binary); + wcs_string2[wcs_size2] = L'\0'; /* for a sentinel */ + if (size2 > MAX_ALLOCA_SIZE) + free (is_binary); + else + FREE_VAR (is_binary); + } +#endif /* WCHAR */ + + + /* Loop through the string, looking for a place to start matching. */ + for (;;) + { + /* If a fastmap is supplied, skip quickly over characters that + cannot be the start of a match. If the pattern can match the + null string, however, we don't need to skip characters; we want + the first null string. */ + if (fastmap && startpos < total_size && !bufp->can_be_null) + { + if (range > 0) /* Searching forwards. */ + { + register const char *d; + register int lim = 0; + int irange = range; + + if (startpos < size1 && startpos + range >= size1) + lim = range - (size1 - startpos); + + d = (startpos >= size1 ? string2 - size1 : string1) + startpos; + + /* Written out as an if-else to avoid testing `translate' + inside the loop. */ + if (translate) + while (range > lim + && !fastmap[(unsigned char) + translate[(unsigned char) *d++]]) + range--; + else + while (range > lim && !fastmap[(unsigned char) *d++]) + range--; + + startpos += irange - range; + } + else /* Searching backwards. */ + { + register CHAR_T c = (size1 == 0 || startpos >= size1 + ? string2[startpos - size1] + : string1[startpos]); + + if (!fastmap[(unsigned char) TRANSLATE (c)]) + goto advance; + } + } + + /* If can't match the null string, and that's all we have left, fail. */ + if (range >= 0 && startpos == total_size && fastmap + && !bufp->can_be_null) + { +#ifdef WCHAR + FREE_WCS_BUFFERS (); +#endif + return -1; + } + +#ifdef WCHAR + val = wcs_re_match_2_internal (bufp, string1, size1, string2, + size2, startpos, regs, stop, + wcs_string1, wcs_size1, + wcs_string2, wcs_size2, + mbs_offset1, mbs_offset2); +#else /* BYTE */ + val = byte_re_match_2_internal (bufp, string1, size1, string2, + size2, startpos, regs, stop); +#endif /* BYTE */ + +#ifndef REGEX_MALLOC +# ifdef C_ALLOCA + alloca (0); +# endif +#endif + + if (val >= 0) + { +#ifdef WCHAR + FREE_WCS_BUFFERS (); +#endif + return startpos; + } + + if (val == -2) + { +#ifdef WCHAR + FREE_WCS_BUFFERS (); +#endif + return -2; + } + + advance: + if (!range) + break; + else if (range > 0) + { + range--; + startpos++; + } + else + { + range++; + startpos--; + } + } +#ifdef WCHAR + FREE_WCS_BUFFERS (); +#endif + return -1; +} + +#ifdef WCHAR +/* This converts PTR, a pointer into one of the search wchar_t strings + `string1' and `string2' into an multibyte string offset from the + beginning of that string. We use mbs_offset to optimize. + See convert_mbs_to_wcs. */ +# define POINTER_TO_OFFSET(ptr) \ + (FIRST_STRING_P (ptr) \ + ? ((regoff_t)(mbs_offset1 != NULL? mbs_offset1[(ptr)-string1] : 0)) \ + : ((regoff_t)((mbs_offset2 != NULL? mbs_offset2[(ptr)-string2] : 0) \ + + csize1))) +#else /* BYTE */ +/* This converts PTR, a pointer into one of the search strings `string1' + and `string2' into an offset from the beginning of that string. */ +# define POINTER_TO_OFFSET(ptr) \ + (FIRST_STRING_P (ptr) \ + ? ((regoff_t) ((ptr) - string1)) \ + : ((regoff_t) ((ptr) - string2 + size1))) +#endif /* WCHAR */ + +/* Macros for dealing with the split strings in re_match_2. */ + +#define MATCHING_IN_FIRST_STRING (dend == end_match_1) + +/* Call before fetching a character with *d. This switches over to + string2 if necessary. */ +#define PREFETCH() \ + while (d == dend) \ + { \ + /* End of string2 => fail. */ \ + if (dend == end_match_2) \ + goto fail; \ + /* End of string1 => advance to string2. */ \ + d = string2; \ + dend = end_match_2; \ + } + +/* Test if at very beginning or at very end of the virtual concatenation + of `string1' and `string2'. If only one string, it's `string2'. */ +#define AT_STRINGS_BEG(d) ((d) == (size1 ? string1 : string2) || !size2) +#define AT_STRINGS_END(d) ((d) == end2) + + +/* Test if D points to a character which is word-constituent. We have + two special cases to check for: if past the end of string1, look at + the first character in string2; and if before the beginning of + string2, look at the last character in string1. */ +#ifdef WCHAR +/* Use internationalized API instead of SYNTAX. */ +# define WORDCHAR_P(d) \ + (iswalnum ((wint_t)((d) == end1 ? *string2 \ + : (d) == string2 - 1 ? *(end1 - 1) : *(d))) != 0 \ + || ((d) == end1 ? *string2 \ + : (d) == string2 - 1 ? *(end1 - 1) : *(d)) == L'_') +#else /* BYTE */ +# define WORDCHAR_P(d) \ + (SYNTAX ((d) == end1 ? *string2 \ + : (d) == string2 - 1 ? *(end1 - 1) : *(d)) \ + == Sword) +#endif /* WCHAR */ + +/* Disabled due to a compiler bug -- see comment at case wordbound */ +#if 0 +/* Test if the character before D and the one at D differ with respect + to being word-constituent. */ +#define AT_WORD_BOUNDARY(d) \ + (AT_STRINGS_BEG (d) || AT_STRINGS_END (d) \ + || WORDCHAR_P (d - 1) != WORDCHAR_P (d)) +#endif + +/* Free everything we malloc. */ +#ifdef MATCH_MAY_ALLOCATE +# ifdef WCHAR +# define FREE_VARIABLES() \ + do { \ + REGEX_FREE_STACK (fail_stack.stack); \ + FREE_VAR (regstart); \ + FREE_VAR (regend); \ + FREE_VAR (old_regstart); \ + FREE_VAR (old_regend); \ + FREE_VAR (best_regstart); \ + FREE_VAR (best_regend); \ + FREE_VAR (reg_info); \ + FREE_VAR (reg_dummy); \ + FREE_VAR (reg_info_dummy); \ + if (!cant_free_wcs_buf) \ + { \ + FREE_VAR (string1); \ + FREE_VAR (string2); \ + FREE_VAR (mbs_offset1); \ + FREE_VAR (mbs_offset2); \ + } \ + } while (0) +# else /* BYTE */ +# define FREE_VARIABLES() \ + do { \ + REGEX_FREE_STACK (fail_stack.stack); \ + FREE_VAR (regstart); \ + FREE_VAR (regend); \ + FREE_VAR (old_regstart); \ + FREE_VAR (old_regend); \ + FREE_VAR (best_regstart); \ + FREE_VAR (best_regend); \ + FREE_VAR (reg_info); \ + FREE_VAR (reg_dummy); \ + FREE_VAR (reg_info_dummy); \ + } while (0) +# endif /* WCHAR */ +#else +# ifdef WCHAR +# define FREE_VARIABLES() \ + do { \ + if (!cant_free_wcs_buf) \ + { \ + FREE_VAR (string1); \ + FREE_VAR (string2); \ + FREE_VAR (mbs_offset1); \ + FREE_VAR (mbs_offset2); \ + } \ + } while (0) +# else /* BYTE */ +# define FREE_VARIABLES() ((void)0) /* Do nothing! But inhibit gcc warning. */ +# endif /* WCHAR */ +#endif /* not MATCH_MAY_ALLOCATE */ + +/* These values must meet several constraints. They must not be valid + register values; since we have a limit of 255 registers (because + we use only one byte in the pattern for the register number), we can + use numbers larger than 255. They must differ by 1, because of + NUM_FAILURE_ITEMS above. And the value for the lowest register must + be larger than the value for the highest register, so we do not try + to actually save any registers when none are active. */ +#define NO_HIGHEST_ACTIVE_REG (1 << BYTEWIDTH) +#define NO_LOWEST_ACTIVE_REG (NO_HIGHEST_ACTIVE_REG + 1) + +#else /* not INSIDE_RECURSION */ +/* Matching routines. */ + +#ifndef emacs /* Emacs never uses this. */ +/* re_match is like re_match_2 except it takes only a single string. */ + +int +re_match ( + struct re_pattern_buffer *bufp, + const char *string, + int size, int pos, + struct re_registers *regs) +{ + int result; +# ifdef MBS_SUPPORT + if (MB_CUR_MAX != 1) + result = wcs_re_match_2_internal (bufp, NULL, 0, string, size, + pos, regs, size, + NULL, 0, NULL, 0, NULL, NULL); + else +# endif + result = byte_re_match_2_internal (bufp, NULL, 0, string, size, + pos, regs, size); +# ifndef REGEX_MALLOC +# ifdef C_ALLOCA + alloca (0); +# endif +# endif + return result; +} +#endif /* not emacs */ + +#endif /* not INSIDE_RECURSION */ + +#ifdef INSIDE_RECURSION +static boolean PREFIX(group_match_null_string_p) (UCHAR_T **p, + UCHAR_T *end, + PREFIX(register_info_type) *reg_info); +static boolean PREFIX(alt_match_null_string_p) (UCHAR_T *p, + UCHAR_T *end, + PREFIX(register_info_type) *reg_info); +static boolean PREFIX(common_op_match_null_string_p) (UCHAR_T **p, + UCHAR_T *end, + PREFIX(register_info_type) *reg_info); +static int PREFIX(bcmp_translate) (const CHAR_T *s1, const CHAR_T *s2, + int len, char *translate); +#else /* not INSIDE_RECURSION */ + +/* re_match_2 matches the compiled pattern in BUFP against the + the (virtual) concatenation of STRING1 and STRING2 (of length SIZE1 + and SIZE2, respectively). We start matching at POS, and stop + matching at STOP. + + If REGS is non-null and the `no_sub' field of BUFP is nonzero, we + store offsets for the substring each group matched in REGS. See the + documentation for exactly how many groups we fill. + + We return -1 if no match, -2 if an internal error (such as the + failure stack overflowing). Otherwise, we return the length of the + matched substring. */ + +int +re_match_2 ( + struct re_pattern_buffer *bufp, + const char *string1, int size1, + const char *string2, int size2, + int pos, + struct re_registers *regs, + int stop) +{ + int result; +# ifdef MBS_SUPPORT + if (MB_CUR_MAX != 1) + result = wcs_re_match_2_internal (bufp, string1, size1, string2, size2, + pos, regs, stop, + NULL, 0, NULL, 0, NULL, NULL); + else +# endif + result = byte_re_match_2_internal (bufp, string1, size1, string2, size2, + pos, regs, stop); + +#ifndef REGEX_MALLOC +# ifdef C_ALLOCA + alloca (0); +# endif +#endif + return result; +} + +#endif /* not INSIDE_RECURSION */ + +#ifdef INSIDE_RECURSION + +#ifdef WCHAR +static int count_mbs_length (int *, int); + +/* This check the substring (from 0, to length) of the multibyte string, + to which offset_buffer correspond. And count how many wchar_t_characters + the substring occupy. We use offset_buffer to optimization. + See convert_mbs_to_wcs. */ + +static int +count_mbs_length( + int *offset_buffer, + int length) +{ + int upper, lower; + + /* Check whether the size is valid. */ + if (length < 0) + return -1; + + if (offset_buffer == NULL) + return 0; + + /* If there are no multibyte character, offset_buffer[i] == i. + Optmize for this case. */ + if (offset_buffer[length] == length) + return length; + + /* Set up upper with length. (because for all i, offset_buffer[i] >= i) */ + upper = length; + lower = 0; + + while (true) + { + int middle = (lower + upper) / 2; + if (middle == lower || middle == upper) + break; + if (offset_buffer[middle] > length) + upper = middle; + else if (offset_buffer[middle] < length) + lower = middle; + else + return middle; + } + + return -1; +} +#endif /* WCHAR */ + +/* This is a separate function so that we can force an alloca cleanup + afterwards. */ +#ifdef WCHAR +static int +wcs_re_match_2_internal ( + struct re_pattern_buffer *bufp, + const char *cstring1, int csize1, + const char *cstring2, int csize2, + int pos, + struct re_registers *regs, + int stop, + /* string1 == string2 == NULL means string1/2, size1/2 and + mbs_offset1/2 need seting up in this function. */ + /* We need wchar_t* buffers correspond to cstring1, cstring2. */ + /* We need the size of wchar_t buffers correspond to csize1, csize2. */ + wchar_t *string1, int size1, + wchar_t *string2, int size2, + /* offset buffer for optimization. See convert_mbs_to_wc. */ + int *mbs_offset1, int *mbs_offset2) +#else /* BYTE */ +static int +byte_re_match_2_internal ( + struct re_pattern_buffer *bufp, + const char *string1, int size1, + const char *string2, int size2, + int pos, + struct re_registers *regs, + int stop) +#endif /* BYTE */ +{ + /* General temporaries. */ + int mcnt; + UCHAR_T *p1; +#ifdef WCHAR + /* They hold whether each wchar_t is binary data or not. */ + char *is_binary = NULL; + /* If true, we can't free string1/2, mbs_offset1/2. */ + int cant_free_wcs_buf = 1; +#endif /* WCHAR */ + + /* Just past the end of the corresponding string. */ + const CHAR_T *end1, *end2; + + /* Pointers into string1 and string2, just past the last characters in + each to consider matching. */ + const CHAR_T *end_match_1, *end_match_2; + + /* Where we are in the data, and the end of the current string. */ + const CHAR_T *d, *dend; + + /* Where we are in the pattern, and the end of the pattern. */ +#ifdef WCHAR + UCHAR_T *pattern, *p; + register UCHAR_T *pend; +#else /* BYTE */ + UCHAR_T *p = bufp->buffer; + register UCHAR_T *pend = p + bufp->used; +#endif /* WCHAR */ + + /* Mark the opcode just after a start_memory, so we can test for an + empty subpattern when we get to the stop_memory. */ + UCHAR_T *just_past_start_mem = 0; + + /* We use this to map every character in the string. */ + RE_TRANSLATE_TYPE translate = bufp->translate; + + /* Failure point stack. Each place that can handle a failure further + down the line pushes a failure point on this stack. It consists of + restart, regend, and reg_info for all registers corresponding to + the subexpressions we're currently inside, plus the number of such + registers, and, finally, two char *'s. The first char * is where + to resume scanning the pattern; the second one is where to resume + scanning the strings. If the latter is zero, the failure point is + a ``dummy''; if a failure happens and the failure point is a dummy, + it gets discarded and the next next one is tried. */ +#ifdef MATCH_MAY_ALLOCATE /* otherwise, this is global. */ + PREFIX(fail_stack_type) fail_stack; +#endif +#ifdef DEBUG + static unsigned failure_id; + unsigned nfailure_points_pushed = 0, nfailure_points_popped = 0; +#endif + +#ifdef REL_ALLOC + /* This holds the pointer to the failure stack, when + it is allocated relocatably. */ + fail_stack_elt_t *failure_stack_ptr; +#endif + + /* We fill all the registers internally, independent of what we + return, for use in backreferences. The number here includes + an element for register zero. */ + size_t num_regs = bufp->re_nsub + 1; + + /* The currently active registers. */ + active_reg_t lowest_active_reg = NO_LOWEST_ACTIVE_REG; + active_reg_t highest_active_reg = NO_HIGHEST_ACTIVE_REG; + + /* Information on the contents of registers. These are pointers into + the input strings; they record just what was matched (on this + attempt) by a subexpression part of the pattern, that is, the + regnum-th regstart pointer points to where in the pattern we began + matching and the regnum-th regend points to right after where we + stopped matching the regnum-th subexpression. (The zeroth register + keeps track of what the whole pattern matches.) */ +#ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global. */ + const CHAR_T **regstart, **regend; +#endif + + /* If a group that's operated upon by a repetition operator fails to + match anything, then the register for its start will need to be + restored because it will have been set to wherever in the string we + are when we last see its open-group operator. Similarly for a + register's end. */ +#ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global. */ + const CHAR_T **old_regstart, **old_regend; +#endif + + /* The is_active field of reg_info helps us keep track of which (possibly + nested) subexpressions we are currently in. The matched_something + field of reg_info[reg_num] helps us tell whether or not we have + matched any of the pattern so far this time through the reg_num-th + subexpression. These two fields get reset each time through any + loop their register is in. */ +#ifdef MATCH_MAY_ALLOCATE /* otherwise, this is global. */ + PREFIX(register_info_type) *reg_info; +#endif + + /* The following record the register info as found in the above + variables when we find a match better than any we've seen before. + This happens as we backtrack through the failure points, which in + turn happens only if we have not yet matched the entire string. */ + unsigned best_regs_set = false; +#ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global. */ + const CHAR_T **best_regstart, **best_regend; +#endif + + /* Logically, this is `best_regend[0]'. But we don't want to have to + allocate space for that if we're not allocating space for anything + else (see below). Also, we never need info about register 0 for + any of the other register vectors, and it seems rather a kludge to + treat `best_regend' differently than the rest. So we keep track of + the end of the best match so far in a separate variable. We + initialize this to NULL so that when we backtrack the first time + and need to test it, it's not garbage. */ + const CHAR_T *match_end = NULL; + + /* This helps SET_REGS_MATCHED avoid doing redundant work. */ + int set_regs_matched_done = 0; + + /* Used when we pop values we don't care about. */ +#ifdef MATCH_MAY_ALLOCATE /* otherwise, these are global. */ + const CHAR_T **reg_dummy; + PREFIX(register_info_type) *reg_info_dummy; +#endif + +#ifdef DEBUG + /* Counts the total number of registers pushed. */ + unsigned num_regs_pushed = 0; +#endif + + DEBUG_PRINT1 ("\n\nEntering re_match_2.\n"); + + INIT_FAIL_STACK (); + +#ifdef MATCH_MAY_ALLOCATE + /* Do not bother to initialize all the register variables if there are + no groups in the pattern, as it takes a fair amount of time. If + there are groups, we include space for register 0 (the whole + pattern), even though we never use it, since it simplifies the + array indexing. We should fix this. */ + if (bufp->re_nsub) + { + regstart = REGEX_TALLOC (num_regs, const CHAR_T *); + regend = REGEX_TALLOC (num_regs, const CHAR_T *); + old_regstart = REGEX_TALLOC (num_regs, const CHAR_T *); + old_regend = REGEX_TALLOC (num_regs, const CHAR_T *); + best_regstart = REGEX_TALLOC (num_regs, const CHAR_T *); + best_regend = REGEX_TALLOC (num_regs, const CHAR_T *); + reg_info = REGEX_TALLOC (num_regs, PREFIX(register_info_type)); + reg_dummy = REGEX_TALLOC (num_regs, const CHAR_T *); + reg_info_dummy = REGEX_TALLOC (num_regs, PREFIX(register_info_type)); + + if (!(regstart && regend && old_regstart && old_regend && reg_info + && best_regstart && best_regend && reg_dummy && reg_info_dummy)) + { + FREE_VARIABLES (); + return -2; + } + } + else + { + /* We must initialize all our variables to NULL, so that + `FREE_VARIABLES' doesn't try to free them. */ + regstart = regend = old_regstart = old_regend = best_regstart + = best_regend = reg_dummy = NULL; + reg_info = reg_info_dummy = (PREFIX(register_info_type) *) NULL; + } +#endif /* MATCH_MAY_ALLOCATE */ + + /* The starting position is bogus. */ +#ifdef WCHAR + if (pos < 0 || pos > csize1 + csize2) +#else /* BYTE */ + if (pos < 0 || pos > size1 + size2) +#endif + { + FREE_VARIABLES (); + return -1; + } + +#ifdef WCHAR + /* Allocate wchar_t array for string1 and string2 and + fill them with converted string. */ + if (string1 == NULL && string2 == NULL) + { + /* We need seting up buffers here. */ + + /* We must free wcs buffers in this function. */ + cant_free_wcs_buf = 0; + + if (csize1 != 0) + { + string1 = REGEX_TALLOC (csize1 + 1, CHAR_T); + mbs_offset1 = REGEX_TALLOC (csize1 + 1, int); + is_binary = REGEX_TALLOC (csize1 + 1, char); + if (!string1 || !mbs_offset1 || !is_binary) + { + FREE_VAR (string1); + FREE_VAR (mbs_offset1); + FREE_VAR (is_binary); + return -2; + } + } + if (csize2 != 0) + { + string2 = REGEX_TALLOC (csize2 + 1, CHAR_T); + mbs_offset2 = REGEX_TALLOC (csize2 + 1, int); + is_binary = REGEX_TALLOC (csize2 + 1, char); + if (!string2 || !mbs_offset2 || !is_binary) + { + FREE_VAR (string1); + FREE_VAR (mbs_offset1); + FREE_VAR (string2); + FREE_VAR (mbs_offset2); + FREE_VAR (is_binary); + return -2; + } + size2 = convert_mbs_to_wcs(string2, cstring2, csize2, + mbs_offset2, is_binary); + string2[size2] = L'\0'; /* for a sentinel */ + FREE_VAR (is_binary); + } + } + + /* We need to cast pattern to (wchar_t*), because we casted this compiled + pattern to (char*) in regex_compile. */ + p = pattern = (CHAR_T*)bufp->buffer; + pend = (CHAR_T*)(bufp->buffer + bufp->used); + +#endif /* WCHAR */ + + /* Initialize subexpression text positions to -1 to mark ones that no + start_memory/stop_memory has been seen for. Also initialize the + register information struct. */ + for (mcnt = 1; (unsigned) mcnt < num_regs; mcnt++) + { + regstart[mcnt] = regend[mcnt] + = old_regstart[mcnt] = old_regend[mcnt] = REG_UNSET_VALUE; + + REG_MATCH_NULL_STRING_P (reg_info[mcnt]) = MATCH_NULL_UNSET_VALUE; + IS_ACTIVE (reg_info[mcnt]) = 0; + MATCHED_SOMETHING (reg_info[mcnt]) = 0; + EVER_MATCHED_SOMETHING (reg_info[mcnt]) = 0; + } + + /* We move `string1' into `string2' if the latter's empty -- but not if + `string1' is null. */ + if (size2 == 0 && string1 != NULL) + { + string2 = string1; + size2 = size1; + string1 = 0; + size1 = 0; +#ifdef WCHAR + mbs_offset2 = mbs_offset1; + csize2 = csize1; + mbs_offset1 = NULL; + csize1 = 0; +#endif + } + end1 = string1 + size1; + end2 = string2 + size2; + + /* Compute where to stop matching, within the two strings. */ +#ifdef WCHAR + if (stop <= csize1) + { + mcnt = count_mbs_length(mbs_offset1, stop); + end_match_1 = string1 + mcnt; + end_match_2 = string2; + } + else + { + if (stop > csize1 + csize2) + stop = csize1 + csize2; + end_match_1 = end1; + mcnt = count_mbs_length(mbs_offset2, stop-csize1); + end_match_2 = string2 + mcnt; + } + if (mcnt < 0) + { /* count_mbs_length return error. */ + FREE_VARIABLES (); + return -1; + } +#else + if (stop <= size1) + { + end_match_1 = string1 + stop; + end_match_2 = string2; + } + else + { + end_match_1 = end1; + end_match_2 = string2 + stop - size1; + } +#endif /* WCHAR */ + + /* `p' scans through the pattern as `d' scans through the data. + `dend' is the end of the input string that `d' points within. `d' + is advanced into the following input string whenever necessary, but + this happens before fetching; therefore, at the beginning of the + loop, `d' can be pointing at the end of a string, but it cannot + equal `string2'. */ +#ifdef WCHAR + if (size1 > 0 && pos <= csize1) + { + mcnt = count_mbs_length(mbs_offset1, pos); + d = string1 + mcnt; + dend = end_match_1; + } + else + { + mcnt = count_mbs_length(mbs_offset2, pos-csize1); + d = string2 + mcnt; + dend = end_match_2; + } + + if (mcnt < 0) + { /* count_mbs_length return error. */ + FREE_VARIABLES (); + return -1; + } +#else + if (size1 > 0 && pos <= size1) + { + d = string1 + pos; + dend = end_match_1; + } + else + { + d = string2 + pos - size1; + dend = end_match_2; + } +#endif /* WCHAR */ + + DEBUG_PRINT1 ("The compiled pattern is:\n"); + DEBUG_PRINT_COMPILED_PATTERN (bufp, p, pend); + DEBUG_PRINT1 ("The string to match is: `"); + DEBUG_PRINT_DOUBLE_STRING (d, string1, size1, string2, size2); + DEBUG_PRINT1 ("'\n"); + + /* This loops over pattern commands. It exits by returning from the + function if the match is complete, or it drops through if the match + fails at this starting point in the input data. */ + for (;;) + { +#ifdef _LIBC + DEBUG_PRINT2 ("\n%p: ", p); +#else + DEBUG_PRINT2 ("\n0x%x: ", p); +#endif + + if (p == pend) + { /* End of pattern means we might have succeeded. */ + DEBUG_PRINT1 ("end of pattern ... "); + + /* If we haven't matched the entire string, and we want the + longest match, try backtracking. */ + if (d != end_match_2) + { + /* 1 if this match ends in the same string (string1 or string2) + as the best previous match. */ + boolean same_str_p = (FIRST_STRING_P (match_end) + == MATCHING_IN_FIRST_STRING); + /* 1 if this match is the best seen so far. */ + boolean best_match_p; + + /* AIX compiler got confused when this was combined + with the previous declaration. */ + if (same_str_p) + best_match_p = d > match_end; + else + best_match_p = !MATCHING_IN_FIRST_STRING; + + DEBUG_PRINT1 ("backtracking.\n"); + + if (!FAIL_STACK_EMPTY ()) + { /* More failure points to try. */ + + /* If exceeds best match so far, save it. */ + if (!best_regs_set || best_match_p) + { + best_regs_set = true; + match_end = d; + + DEBUG_PRINT1 ("\nSAVING match as best so far.\n"); + + for (mcnt = 1; (unsigned) mcnt < num_regs; mcnt++) + { + best_regstart[mcnt] = regstart[mcnt]; + best_regend[mcnt] = regend[mcnt]; + } + } + goto fail; + } + + /* If no failure points, don't restore garbage. And if + last match is real best match, don't restore second + best one. */ + else if (best_regs_set && !best_match_p) + { + restore_best_regs: + /* Restore best match. It may happen that `dend == + end_match_1' while the restored d is in string2. + For example, the pattern `x.*y.*z' against the + strings `x-' and `y-z-', if the two strings are + not consecutive in memory. */ + DEBUG_PRINT1 ("Restoring best registers.\n"); + + d = match_end; + dend = ((d >= string1 && d <= end1) + ? end_match_1 : end_match_2); + + for (mcnt = 1; (unsigned) mcnt < num_regs; mcnt++) + { + regstart[mcnt] = best_regstart[mcnt]; + regend[mcnt] = best_regend[mcnt]; + } + } + } /* d != end_match_2 */ + + succeed_label: + DEBUG_PRINT1 ("Accepting match.\n"); + /* If caller wants register contents data back, do it. */ + if (regs && !bufp->no_sub) + { + /* Have the register data arrays been allocated? */ + if (bufp->regs_allocated == REGS_UNALLOCATED) + { /* No. So allocate them with malloc. We need one + extra element beyond `num_regs' for the `-1' marker + GNU code uses. */ +/* regex specs say: + * "If REGS_UNALLOCATED, allocate space in the regs structure + * for max(RE_NREGS, re_nsub + 1) groups" + * but real-world testsuites fail with contrived examples + * with lots of groups. + * I don't see why we can't just allocate exact needed number. + * Incidentally, it makes RE_NREGS unused. + * + * regs->num_regs = MAX (RE_NREGS, num_regs + 1); - VERY WRONG + * regs->num_regs = MIN (RE_NREGS, num_regs + 1); - slightly less wrong + * good one which passes uclibc test/regex/tst-regex2.c: + */ + regs->num_regs = num_regs + 1; + regs->start = TALLOC (regs->num_regs, regoff_t); + regs->end = TALLOC (regs->num_regs, regoff_t); + if (regs->start == NULL || regs->end == NULL) + { + FREE_VARIABLES (); + return -2; + } + bufp->regs_allocated = REGS_REALLOCATE; + } + else if (bufp->regs_allocated == REGS_REALLOCATE) + { /* Yes. If we need more elements than were already + allocated, reallocate them. If we need fewer, just + leave it alone. */ + if (regs->num_regs < num_regs + 1) + { + regs->num_regs = num_regs + 1; + RETALLOC (regs->start, regs->num_regs, regoff_t); + RETALLOC (regs->end, regs->num_regs, regoff_t); + if (regs->start == NULL || regs->end == NULL) + { + FREE_VARIABLES (); + return -2; + } + } + } + else + { + /* These braces fend off a "empty body in an else-statement" + warning under GCC when assert expands to nothing. */ + assert (bufp->regs_allocated == REGS_FIXED); + } + + /* Convert the pointer data in `regstart' and `regend' to + indices. Register zero has to be set differently, + since we haven't kept track of any info for it. */ + if (regs->num_regs > 0) + { + regs->start[0] = pos; +#ifdef WCHAR + if (MATCHING_IN_FIRST_STRING) + regs->end[0] = mbs_offset1 != NULL ? + mbs_offset1[d-string1] : 0; + else + regs->end[0] = csize1 + (mbs_offset2 != NULL ? + mbs_offset2[d-string2] : 0); +#else + regs->end[0] = (MATCHING_IN_FIRST_STRING + ? ((regoff_t) (d - string1)) + : ((regoff_t) (d - string2 + size1))); +#endif /* WCHAR */ + } + + /* Go through the first `min (num_regs, regs->num_regs)' + registers, since that is all we initialized. */ + for (mcnt = 1; (unsigned) mcnt < MIN (num_regs, regs->num_regs); + mcnt++) + { + if (REG_UNSET (regstart[mcnt]) || REG_UNSET (regend[mcnt])) + regs->start[mcnt] = regs->end[mcnt] = -1; + else + { + regs->start[mcnt] + = (regoff_t) POINTER_TO_OFFSET (regstart[mcnt]); + regs->end[mcnt] + = (regoff_t) POINTER_TO_OFFSET (regend[mcnt]); + } + } + + /* If the regs structure we return has more elements than + were in the pattern, set the extra elements to -1. If + we (re)allocated the registers, this is the case, + because we always allocate enough to have at least one + -1 at the end. */ + for (mcnt = num_regs; (unsigned) mcnt < regs->num_regs; mcnt++) + regs->start[mcnt] = regs->end[mcnt] = -1; + } /* regs && !bufp->no_sub */ + + DEBUG_PRINT4 ("%u failure points pushed, %u popped (%u remain).\n", + nfailure_points_pushed, nfailure_points_popped, + nfailure_points_pushed - nfailure_points_popped); + DEBUG_PRINT2 ("%u registers pushed.\n", num_regs_pushed); + +#ifdef WCHAR + if (MATCHING_IN_FIRST_STRING) + mcnt = mbs_offset1 != NULL ? mbs_offset1[d-string1] : 0; + else + mcnt = (mbs_offset2 != NULL ? mbs_offset2[d-string2] : 0) + + csize1; + mcnt -= pos; +#else + mcnt = d - pos - (MATCHING_IN_FIRST_STRING + ? string1 + : string2 - size1); +#endif /* WCHAR */ + + DEBUG_PRINT2 ("Returning %d from re_match_2.\n", mcnt); + + FREE_VARIABLES (); + return mcnt; + } + + /* Otherwise match next pattern command. */ + switch (SWITCH_ENUM_CAST ((re_opcode_t) *p++)) + { + /* Ignore these. Used to ignore the n of succeed_n's which + currently have n == 0. */ + case no_op: + DEBUG_PRINT1 ("EXECUTING no_op.\n"); + break; + + case succeed: + DEBUG_PRINT1 ("EXECUTING succeed.\n"); + goto succeed_label; + + /* Match the next n pattern characters exactly. The following + byte in the pattern defines n, and the n bytes after that + are the characters to match. */ + case exactn: +#ifdef MBS_SUPPORT + case exactn_bin: +#endif + mcnt = *p++; + DEBUG_PRINT2 ("EXECUTING exactn %d.\n", mcnt); + + /* This is written out as an if-else so we don't waste time + testing `translate' inside the loop. */ + if (translate) + { + do + { + PREFETCH (); +#ifdef WCHAR + if (*d <= 0xff) + { + if ((UCHAR_T) translate[(unsigned char) *d++] + != (UCHAR_T) *p++) + goto fail; + } + else + { + if (*d++ != (CHAR_T) *p++) + goto fail; + } +#else + if ((UCHAR_T) translate[(unsigned char) *d++] + != (UCHAR_T) *p++) + goto fail; +#endif /* WCHAR */ + } + while (--mcnt); + } + else + { + do + { + PREFETCH (); + if (*d++ != (CHAR_T) *p++) goto fail; + } + while (--mcnt); + } + SET_REGS_MATCHED (); + break; + + + /* Match any character except possibly a newline or a null. */ + case anychar: + DEBUG_PRINT1 ("EXECUTING anychar.\n"); + + PREFETCH (); + + if ((!(bufp->syntax & RE_DOT_NEWLINE) && TRANSLATE (*d) == '\n') + || (bufp->syntax & RE_DOT_NOT_NULL && TRANSLATE (*d) == '\000')) + goto fail; + + SET_REGS_MATCHED (); + DEBUG_PRINT2 (" Matched `%ld'.\n", (long int) *d); + d++; + break; + + + case charset: + case charset_not: + { + register UCHAR_T c; +#ifdef WCHAR + unsigned int i, char_class_length, coll_symbol_length, + equiv_class_length, ranges_length, chars_length, length; + CHAR_T *workp, *workp2, *charset_top; +#define WORK_BUFFER_SIZE 128 + CHAR_T str_buf[WORK_BUFFER_SIZE]; +# ifdef _LIBC + uint32_t nrules; +# endif /* _LIBC */ +#endif /* WCHAR */ + boolean not = (re_opcode_t) *(p - 1) == charset_not; + + DEBUG_PRINT2 ("EXECUTING charset%s.\n", not ? "_not" : ""); + PREFETCH (); + c = TRANSLATE (*d); /* The character to match. */ +#ifdef WCHAR +# ifdef _LIBC + nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); +# endif /* _LIBC */ + charset_top = p - 1; + char_class_length = *p++; + coll_symbol_length = *p++; + equiv_class_length = *p++; + ranges_length = *p++; + chars_length = *p++; + /* p points charset[6], so the address of the next instruction + (charset[l+m+n+2o+k+p']) equals p[l+m+n+2*o+p'], + where l=length of char_classes, m=length of collating_symbol, + n=equivalence_class, o=length of char_range, + p'=length of character. */ + workp = p; + /* Update p to indicate the next instruction. */ + p += char_class_length + coll_symbol_length+ equiv_class_length + + 2*ranges_length + chars_length; + + /* match with char_class? */ + for (i = 0; i < char_class_length ; i += CHAR_CLASS_SIZE) + { + wctype_t wctype; + uintptr_t alignedp = ((uintptr_t)workp + + __alignof__(wctype_t) - 1) + & ~(uintptr_t)(__alignof__(wctype_t) - 1); + wctype = *((wctype_t*)alignedp); + workp += CHAR_CLASS_SIZE; +# ifdef _LIBC + if (__iswctype((wint_t)c, wctype)) + goto char_set_matched; +# else + if (iswctype((wint_t)c, wctype)) + goto char_set_matched; +# endif + } + + /* match with collating_symbol? */ +# ifdef _LIBC + if (nrules != 0) + { + const unsigned char *extra = (const unsigned char *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_EXTRAMB); + + for (workp2 = workp + coll_symbol_length ; workp < workp2 ; + workp++) + { + int32_t *wextra; + wextra = (int32_t*)(extra + *workp++); + for (i = 0; i < *wextra; ++i) + if (TRANSLATE(d[i]) != wextra[1 + i]) + break; + + if (i == *wextra) + { + /* Update d, however d will be incremented at + char_set_matched:, we decrement d here. */ + d += i - 1; + goto char_set_matched; + } + } + } + else /* (nrules == 0) */ +# endif + /* If we can't look up collation data, we use wcscoll + instead. */ + { + for (workp2 = workp + coll_symbol_length ; workp < workp2 ;) + { + const CHAR_T *backup_d = d, *backup_dend = dend; +# ifdef _LIBC + length = __wcslen (workp); +# else + length = wcslen (workp); +# endif + + /* If wcscoll(the collating symbol, whole string) > 0, + any substring of the string never match with the + collating symbol. */ +# ifdef _LIBC + if (__wcscoll (workp, d) > 0) +# else + if (wcscoll (workp, d) > 0) +# endif + { + workp += length + 1; + continue; + } + + /* First, we compare the collating symbol with + the first character of the string. + If it don't match, we add the next character to + the compare buffer in turn. */ + for (i = 0 ; i < WORK_BUFFER_SIZE-1 ; i++, d++) + { + int match; + if (d == dend) + { + if (dend == end_match_2) + break; + d = string2; + dend = end_match_2; + } + + /* add next character to the compare buffer. */ + str_buf[i] = TRANSLATE(*d); + str_buf[i+1] = '\0'; + +# ifdef _LIBC + match = __wcscoll (workp, str_buf); +# else + match = wcscoll (workp, str_buf); +# endif + if (match == 0) + goto char_set_matched; + + if (match < 0) + /* (str_buf > workp) indicate (str_buf + X > workp), + because for all X (str_buf + X > str_buf). + So we don't need continue this loop. */ + break; + + /* Otherwise(str_buf < workp), + (str_buf+next_character) may equals (workp). + So we continue this loop. */ + } + /* not matched */ + d = backup_d; + dend = backup_dend; + workp += length + 1; + } + } + /* match with equivalence_class? */ +# ifdef _LIBC + if (nrules != 0) + { + const CHAR_T *backup_d = d, *backup_dend = dend; + /* Try to match the equivalence class against + those known to the collate implementation. */ + const int32_t *table; + const int32_t *weights; + const int32_t *extra; + const int32_t *indirect; + int32_t idx, idx2; + wint_t *cp; + size_t len; + + /* This #include defines a local function! */ +# include + + table = (const int32_t *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEWC); + weights = (const wint_t *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_WEIGHTWC); + extra = (const wint_t *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAWC); + indirect = (const int32_t *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTWC); + + /* Write 1 collating element to str_buf, and + get its index. */ + idx2 = 0; + + for (i = 0 ; idx2 == 0 && i < WORK_BUFFER_SIZE - 1; i++) + { + cp = (wint_t*)str_buf; + if (d == dend) + { + if (dend == end_match_2) + break; + d = string2; + dend = end_match_2; + } + str_buf[i] = TRANSLATE(*(d+i)); + str_buf[i+1] = '\0'; /* sentinel */ + idx2 = findidx ((const wint_t**)&cp); + } + + /* Update d, however d will be incremented at + char_set_matched:, we decrement d here. */ + d = backup_d + ((wchar_t*)cp - (wchar_t*)str_buf - 1); + if (d >= dend) + { + if (dend == end_match_2) + d = dend; + else + { + d = string2; + dend = end_match_2; + } + } + + len = weights[idx2]; + + for (workp2 = workp + equiv_class_length ; workp < workp2 ; + workp++) + { + idx = (int32_t)*workp; + /* We already checked idx != 0 in regex_compile. */ + + if (idx2 != 0 && len == weights[idx]) + { + int cnt = 0; + while (cnt < len && (weights[idx + 1 + cnt] + == weights[idx2 + 1 + cnt])) + ++cnt; + + if (cnt == len) + goto char_set_matched; + } + } + /* not matched */ + d = backup_d; + dend = backup_dend; + } + else /* (nrules == 0) */ +# endif + /* If we can't look up collation data, we use wcscoll + instead. */ + { + for (workp2 = workp + equiv_class_length ; workp < workp2 ;) + { + const CHAR_T *backup_d = d, *backup_dend = dend; +# ifdef _LIBC + length = __wcslen (workp); +# else + length = wcslen (workp); +# endif + + /* If wcscoll(the collating symbol, whole string) > 0, + any substring of the string never match with the + collating symbol. */ +# ifdef _LIBC + if (__wcscoll (workp, d) > 0) +# else + if (wcscoll (workp, d) > 0) +# endif + { + workp += length + 1; + break; + } + + /* First, we compare the equivalence class with + the first character of the string. + If it don't match, we add the next character to + the compare buffer in turn. */ + for (i = 0 ; i < WORK_BUFFER_SIZE - 1 ; i++, d++) + { + int match; + if (d == dend) + { + if (dend == end_match_2) + break; + d = string2; + dend = end_match_2; + } + + /* add next character to the compare buffer. */ + str_buf[i] = TRANSLATE(*d); + str_buf[i+1] = '\0'; + +# ifdef _LIBC + match = __wcscoll (workp, str_buf); +# else + match = wcscoll (workp, str_buf); +# endif + + if (match == 0) + goto char_set_matched; + + if (match < 0) + /* (str_buf > workp) indicate (str_buf + X > workp), + because for all X (str_buf + X > str_buf). + So we don't need continue this loop. */ + break; + + /* Otherwise(str_buf < workp), + (str_buf+next_character) may equals (workp). + So we continue this loop. */ + } + /* not matched */ + d = backup_d; + dend = backup_dend; + workp += length + 1; + } + } + + /* match with char_range? */ +# ifdef _LIBC + if (nrules != 0) + { + uint32_t collseqval; + const char *collseq = (const char *) + _NL_CURRENT(LC_COLLATE, _NL_COLLATE_COLLSEQWC); + + collseqval = collseq_table_lookup (collseq, c); + + for (; workp < p - chars_length ;) + { + uint32_t start_val, end_val; + + /* We already compute the collation sequence value + of the characters (or collating symbols). */ + start_val = (uint32_t) *workp++; /* range_start */ + end_val = (uint32_t) *workp++; /* range_end */ + + if (start_val <= collseqval && collseqval <= end_val) + goto char_set_matched; + } + } + else +# endif + { + /* We set range_start_char at str_buf[0], range_end_char + at str_buf[4], and compared char at str_buf[2]. */ + str_buf[1] = 0; + str_buf[2] = c; + str_buf[3] = 0; + str_buf[5] = 0; + for (; workp < p - chars_length ;) + { + wchar_t *range_start_char, *range_end_char; + + /* match if (range_start_char <= c <= range_end_char). */ + + /* If range_start(or end) < 0, we assume -range_start(end) + is the offset of the collating symbol which is specified + as the character of the range start(end). */ + + /* range_start */ + if (*workp < 0) + range_start_char = charset_top - (*workp++); + else + { + str_buf[0] = *workp++; + range_start_char = str_buf; + } + + /* range_end */ + if (*workp < 0) + range_end_char = charset_top - (*workp++); + else + { + str_buf[4] = *workp++; + range_end_char = str_buf + 4; + } + +# ifdef _LIBC + if (__wcscoll (range_start_char, str_buf+2) <= 0 + && __wcscoll (str_buf+2, range_end_char) <= 0) +# else + if (wcscoll (range_start_char, str_buf+2) <= 0 + && wcscoll (str_buf+2, range_end_char) <= 0) +# endif + goto char_set_matched; + } + } + + /* match with char? */ + for (; workp < p ; workp++) + if (c == *workp) + goto char_set_matched; + + not = !not; + + char_set_matched: + if (not) goto fail; +#else + /* Cast to `unsigned' instead of `unsigned char' in case the + bit list is a full 32 bytes long. */ + if (c < (unsigned) (*p * BYTEWIDTH) + && p[1 + c / BYTEWIDTH] & (1 << (c % BYTEWIDTH))) + not = !not; + + p += 1 + *p; + + if (!not) goto fail; +#undef WORK_BUFFER_SIZE +#endif /* WCHAR */ + SET_REGS_MATCHED (); + d++; + break; + } + + + /* The beginning of a group is represented by start_memory. + The arguments are the register number in the next byte, and the + number of groups inner to this one in the next. The text + matched within the group is recorded (in the internal + registers data structure) under the register number. */ + case start_memory: + DEBUG_PRINT3 ("EXECUTING start_memory %ld (%ld):\n", + (long int) *p, (long int) p[1]); + + /* Find out if this group can match the empty string. */ + p1 = p; /* To send to group_match_null_string_p. */ + + if (REG_MATCH_NULL_STRING_P (reg_info[*p]) == MATCH_NULL_UNSET_VALUE) + REG_MATCH_NULL_STRING_P (reg_info[*p]) + = PREFIX(group_match_null_string_p) (&p1, pend, reg_info); + + /* Save the position in the string where we were the last time + we were at this open-group operator in case the group is + operated upon by a repetition operator, e.g., with `(a*)*b' + against `ab'; then we want to ignore where we are now in + the string in case this attempt to match fails. */ + old_regstart[*p] = REG_MATCH_NULL_STRING_P (reg_info[*p]) + ? REG_UNSET (regstart[*p]) ? d : regstart[*p] + : regstart[*p]; + DEBUG_PRINT2 (" old_regstart: %d\n", + POINTER_TO_OFFSET (old_regstart[*p])); + + regstart[*p] = d; + DEBUG_PRINT2 (" regstart: %d\n", POINTER_TO_OFFSET (regstart[*p])); + + IS_ACTIVE (reg_info[*p]) = 1; + MATCHED_SOMETHING (reg_info[*p]) = 0; + + /* Clear this whenever we change the register activity status. */ + set_regs_matched_done = 0; + + /* This is the new highest active register. */ + highest_active_reg = *p; + + /* If nothing was active before, this is the new lowest active + register. */ + if (lowest_active_reg == NO_LOWEST_ACTIVE_REG) + lowest_active_reg = *p; + + /* Move past the register number and inner group count. */ + p += 2; + just_past_start_mem = p; + + break; + + + /* The stop_memory opcode represents the end of a group. Its + arguments are the same as start_memory's: the register + number, and the number of inner groups. */ + case stop_memory: + DEBUG_PRINT3 ("EXECUTING stop_memory %ld (%ld):\n", + (long int) *p, (long int) p[1]); + + /* We need to save the string position the last time we were at + this close-group operator in case the group is operated + upon by a repetition operator, e.g., with `((a*)*(b*)*)*' + against `aba'; then we want to ignore where we are now in + the string in case this attempt to match fails. */ + old_regend[*p] = REG_MATCH_NULL_STRING_P (reg_info[*p]) + ? REG_UNSET (regend[*p]) ? d : regend[*p] + : regend[*p]; + DEBUG_PRINT2 (" old_regend: %d\n", + POINTER_TO_OFFSET (old_regend[*p])); + + regend[*p] = d; + DEBUG_PRINT2 (" regend: %d\n", POINTER_TO_OFFSET (regend[*p])); + + /* This register isn't active anymore. */ + IS_ACTIVE (reg_info[*p]) = 0; + + /* Clear this whenever we change the register activity status. */ + set_regs_matched_done = 0; + + /* If this was the only register active, nothing is active + anymore. */ + if (lowest_active_reg == highest_active_reg) + { + lowest_active_reg = NO_LOWEST_ACTIVE_REG; + highest_active_reg = NO_HIGHEST_ACTIVE_REG; + } + else + { /* We must scan for the new highest active register, since + it isn't necessarily one less than now: consider + (a(b)c(d(e)f)g). When group 3 ends, after the f), the + new highest active register is 1. */ + UCHAR_T r = *p - 1; + while (r > 0 && !IS_ACTIVE (reg_info[r])) + r--; + + /* If we end up at register zero, that means that we saved + the registers as the result of an `on_failure_jump', not + a `start_memory', and we jumped to past the innermost + `stop_memory'. For example, in ((.)*) we save + registers 1 and 2 as a result of the *, but when we pop + back to the second ), we are at the stop_memory 1. + Thus, nothing is active. */ + if (r == 0) + { + lowest_active_reg = NO_LOWEST_ACTIVE_REG; + highest_active_reg = NO_HIGHEST_ACTIVE_REG; + } + else + highest_active_reg = r; + } + + /* If just failed to match something this time around with a + group that's operated on by a repetition operator, try to + force exit from the ``loop'', and restore the register + information for this group that we had before trying this + last match. */ + if ((!MATCHED_SOMETHING (reg_info[*p]) + || just_past_start_mem == p - 1) + && (p + 2) < pend) + { + boolean is_a_jump_n = false; + + p1 = p + 2; + mcnt = 0; + switch ((re_opcode_t) *p1++) + { + case jump_n: + is_a_jump_n = true; + case pop_failure_jump: + case maybe_pop_jump: + case jump: + case dummy_failure_jump: + EXTRACT_NUMBER_AND_INCR (mcnt, p1); + if (is_a_jump_n) + p1 += OFFSET_ADDRESS_SIZE; + break; + + default: + /* do nothing */ ; + } + p1 += mcnt; + + /* If the next operation is a jump backwards in the pattern + to an on_failure_jump right before the start_memory + corresponding to this stop_memory, exit from the loop + by forcing a failure after pushing on the stack the + on_failure_jump's jump in the pattern, and d. */ + if (mcnt < 0 && (re_opcode_t) *p1 == on_failure_jump + && (re_opcode_t) p1[1+OFFSET_ADDRESS_SIZE] == start_memory + && p1[2+OFFSET_ADDRESS_SIZE] == *p) + { + /* If this group ever matched anything, then restore + what its registers were before trying this last + failed match, e.g., with `(a*)*b' against `ab' for + regstart[1], and, e.g., with `((a*)*(b*)*)*' + against `aba' for regend[3]. + + Also restore the registers for inner groups for, + e.g., `((a*)(b*))*' against `aba' (register 3 would + otherwise get trashed). */ + + if (EVER_MATCHED_SOMETHING (reg_info[*p])) + { + unsigned r; + + EVER_MATCHED_SOMETHING (reg_info[*p]) = 0; + + /* Restore this and inner groups' (if any) registers. */ + for (r = *p; r < (unsigned) *p + (unsigned) *(p + 1); + r++) + { + regstart[r] = old_regstart[r]; + + /* xx why this test? */ + if (old_regend[r] >= regstart[r]) + regend[r] = old_regend[r]; + } + } + p1++; + EXTRACT_NUMBER_AND_INCR (mcnt, p1); + PUSH_FAILURE_POINT (p1 + mcnt, d, -2); + + goto fail; + } + } + + /* Move past the register number and the inner group count. */ + p += 2; + break; + + + /* \ has been turned into a `duplicate' command which is + followed by the numeric value of as the register number. */ + case duplicate: + { + register const CHAR_T *d2, *dend2; + int regno = *p++; /* Get which register to match against. */ + DEBUG_PRINT2 ("EXECUTING duplicate %d.\n", regno); + + /* Can't back reference a group which we've never matched. */ + if (REG_UNSET (regstart[regno]) || REG_UNSET (regend[regno])) + goto fail; + + /* Where in input to try to start matching. */ + d2 = regstart[regno]; + + /* Where to stop matching; if both the place to start and + the place to stop matching are in the same string, then + set to the place to stop, otherwise, for now have to use + the end of the first string. */ + + dend2 = ((FIRST_STRING_P (regstart[regno]) + == FIRST_STRING_P (regend[regno])) + ? regend[regno] : end_match_1); + for (;;) + { + /* If necessary, advance to next segment in register + contents. */ + while (d2 == dend2) + { + if (dend2 == end_match_2) break; + if (dend2 == regend[regno]) break; + + /* End of string1 => advance to string2. */ + d2 = string2; + dend2 = regend[regno]; + } + /* At end of register contents => success */ + if (d2 == dend2) break; + + /* If necessary, advance to next segment in data. */ + PREFETCH (); + + /* How many characters left in this segment to match. */ + mcnt = dend - d; + + /* Want how many consecutive characters we can match in + one shot, so, if necessary, adjust the count. */ + if (mcnt > dend2 - d2) + mcnt = dend2 - d2; + + /* Compare that many; failure if mismatch, else move + past them. */ + if (translate + ? PREFIX(bcmp_translate) (d, d2, mcnt, translate) + : memcmp (d, d2, mcnt*sizeof(UCHAR_T))) + goto fail; + d += mcnt, d2 += mcnt; + + /* Do this because we've match some characters. */ + SET_REGS_MATCHED (); + } + } + break; + + + /* begline matches the empty string at the beginning of the string + (unless `not_bol' is set in `bufp'), and, if + `newline_anchor' is set, after newlines. */ + case begline: + DEBUG_PRINT1 ("EXECUTING begline.\n"); + + if (AT_STRINGS_BEG (d)) + { + if (!bufp->not_bol) break; + } + else if (d[-1] == '\n' && bufp->newline_anchor) + { + break; + } + /* In all other cases, we fail. */ + goto fail; + + + /* endline is the dual of begline. */ + case endline: + DEBUG_PRINT1 ("EXECUTING endline.\n"); + + if (AT_STRINGS_END (d)) + { + if (!bufp->not_eol) break; + } + + /* We have to ``prefetch'' the next character. */ + else if ((d == end1 ? *string2 : *d) == '\n' + && bufp->newline_anchor) + { + break; + } + goto fail; + + + /* Match at the very beginning of the data. */ + case begbuf: + DEBUG_PRINT1 ("EXECUTING begbuf.\n"); + if (AT_STRINGS_BEG (d)) + break; + goto fail; + + + /* Match at the very end of the data. */ + case endbuf: + DEBUG_PRINT1 ("EXECUTING endbuf.\n"); + if (AT_STRINGS_END (d)) + break; + goto fail; + + + /* on_failure_keep_string_jump is used to optimize `.*\n'. It + pushes NULL as the value for the string on the stack. Then + `pop_failure_point' will keep the current value for the + string, instead of restoring it. To see why, consider + matching `foo\nbar' against `.*\n'. The .* matches the foo; + then the . fails against the \n. But the next thing we want + to do is match the \n against the \n; if we restored the + string value, we would be back at the foo. + + Because this is used only in specific cases, we don't need to + check all the things that `on_failure_jump' does, to make + sure the right things get saved on the stack. Hence we don't + share its code. The only reason to push anything on the + stack at all is that otherwise we would have to change + `anychar's code to do something besides goto fail in this + case; that seems worse than this. */ + case on_failure_keep_string_jump: + DEBUG_PRINT1 ("EXECUTING on_failure_keep_string_jump"); + + EXTRACT_NUMBER_AND_INCR (mcnt, p); +#ifdef _LIBC + DEBUG_PRINT3 (" %d (to %p):\n", mcnt, p + mcnt); +#else + DEBUG_PRINT3 (" %d (to 0x%x):\n", mcnt, p + mcnt); +#endif + + PUSH_FAILURE_POINT (p + mcnt, NULL, -2); + break; + + + /* Uses of on_failure_jump: + + Each alternative starts with an on_failure_jump that points + to the beginning of the next alternative. Each alternative + except the last ends with a jump that in effect jumps past + the rest of the alternatives. (They really jump to the + ending jump of the following alternative, because tensioning + these jumps is a hassle.) + + Repeats start with an on_failure_jump that points past both + the repetition text and either the following jump or + pop_failure_jump back to this on_failure_jump. */ + case on_failure_jump: + on_failure: + DEBUG_PRINT1 ("EXECUTING on_failure_jump"); + + EXTRACT_NUMBER_AND_INCR (mcnt, p); +#ifdef _LIBC + DEBUG_PRINT3 (" %d (to %p)", mcnt, p + mcnt); +#else + DEBUG_PRINT3 (" %d (to 0x%x)", mcnt, p + mcnt); +#endif + + /* If this on_failure_jump comes right before a group (i.e., + the original * applied to a group), save the information + for that group and all inner ones, so that if we fail back + to this point, the group's information will be correct. + For example, in \(a*\)*\1, we need the preceding group, + and in \(zz\(a*\)b*\)\2, we need the inner group. */ + + /* We can't use `p' to check ahead because we push + a failure point to `p + mcnt' after we do this. */ + p1 = p; + + /* We need to skip no_op's before we look for the + start_memory in case this on_failure_jump is happening as + the result of a completed succeed_n, as in \(a\)\{1,3\}b\1 + against aba. */ + while (p1 < pend && (re_opcode_t) *p1 == no_op) + p1++; + + if (p1 < pend && (re_opcode_t) *p1 == start_memory) + { + /* We have a new highest active register now. This will + get reset at the start_memory we are about to get to, + but we will have saved all the registers relevant to + this repetition op, as described above. */ + highest_active_reg = *(p1 + 1) + *(p1 + 2); + if (lowest_active_reg == NO_LOWEST_ACTIVE_REG) + lowest_active_reg = *(p1 + 1); + } + + DEBUG_PRINT1 (":\n"); + PUSH_FAILURE_POINT (p + mcnt, d, -2); + break; + + + /* A smart repeat ends with `maybe_pop_jump'. + We change it to either `pop_failure_jump' or `jump'. */ + case maybe_pop_jump: + EXTRACT_NUMBER_AND_INCR (mcnt, p); + DEBUG_PRINT2 ("EXECUTING maybe_pop_jump %d.\n", mcnt); + { + register UCHAR_T *p2 = p; + + /* Compare the beginning of the repeat with what in the + pattern follows its end. If we can establish that there + is nothing that they would both match, i.e., that we + would have to backtrack because of (as in, e.g., `a*a') + then we can change to pop_failure_jump, because we'll + never have to backtrack. + + This is not true in the case of alternatives: in + `(a|ab)*' we do need to backtrack to the `ab' alternative + (e.g., if the string was `ab'). But instead of trying to + detect that here, the alternative has put on a dummy + failure point which is what we will end up popping. */ + + /* Skip over open/close-group commands. + If what follows this loop is a ...+ construct, + look at what begins its body, since we will have to + match at least one of that. */ + while (1) + { + if (p2 + 2 < pend + && ((re_opcode_t) *p2 == stop_memory + || (re_opcode_t) *p2 == start_memory)) + p2 += 3; + else if (p2 + 2 + 2 * OFFSET_ADDRESS_SIZE < pend + && (re_opcode_t) *p2 == dummy_failure_jump) + p2 += 2 + 2 * OFFSET_ADDRESS_SIZE; + else + break; + } + + p1 = p + mcnt; + /* p1[0] ... p1[2] are the `on_failure_jump' corresponding + to the `maybe_finalize_jump' of this case. Examine what + follows. */ + + /* If we're at the end of the pattern, we can change. */ + if (p2 == pend) + { + /* Consider what happens when matching ":\(.*\)" + against ":/". I don't really understand this code + yet. */ + p[-(1+OFFSET_ADDRESS_SIZE)] = (UCHAR_T) + pop_failure_jump; + DEBUG_PRINT1 + (" End of pattern: change to `pop_failure_jump'.\n"); + } + + else if ((re_opcode_t) *p2 == exactn +#ifdef MBS_SUPPORT + || (re_opcode_t) *p2 == exactn_bin +#endif + || (bufp->newline_anchor && (re_opcode_t) *p2 == endline)) + { + register UCHAR_T c + = *p2 == (UCHAR_T) endline ? '\n' : p2[2]; + + if (((re_opcode_t) p1[1+OFFSET_ADDRESS_SIZE] == exactn +#ifdef MBS_SUPPORT + || (re_opcode_t) p1[1+OFFSET_ADDRESS_SIZE] == exactn_bin +#endif + ) && p1[3+OFFSET_ADDRESS_SIZE] != c) + { + p[-(1+OFFSET_ADDRESS_SIZE)] = (UCHAR_T) + pop_failure_jump; +#ifdef WCHAR + DEBUG_PRINT3 (" %C != %C => pop_failure_jump.\n", + (wint_t) c, + (wint_t) p1[3+OFFSET_ADDRESS_SIZE]); +#else + DEBUG_PRINT3 (" %c != %c => pop_failure_jump.\n", + (char) c, + (char) p1[3+OFFSET_ADDRESS_SIZE]); +#endif + } + +#ifndef WCHAR + else if ((re_opcode_t) p1[3] == charset + || (re_opcode_t) p1[3] == charset_not) + { + int not = (re_opcode_t) p1[3] == charset_not; + + if (c < (unsigned) (p1[4] * BYTEWIDTH) + && p1[5 + c / BYTEWIDTH] & (1 << (c % BYTEWIDTH))) + not = !not; + + /* `not' is equal to 1 if c would match, which means + that we can't change to pop_failure_jump. */ + if (!not) + { + p[-3] = (unsigned char) pop_failure_jump; + DEBUG_PRINT1 (" No match => pop_failure_jump.\n"); + } + } +#endif /* not WCHAR */ + } +#ifndef WCHAR + else if ((re_opcode_t) *p2 == charset) + { + /* We win if the first character of the loop is not part + of the charset. */ + if ((re_opcode_t) p1[3] == exactn + && ! ((int) p2[1] * BYTEWIDTH > (int) p1[5] + && (p2[2 + p1[5] / BYTEWIDTH] + & (1 << (p1[5] % BYTEWIDTH))))) + { + p[-3] = (unsigned char) pop_failure_jump; + DEBUG_PRINT1 (" No match => pop_failure_jump.\n"); + } + + else if ((re_opcode_t) p1[3] == charset_not) + { + int idx; + /* We win if the charset_not inside the loop + lists every character listed in the charset after. */ + for (idx = 0; idx < (int) p2[1]; idx++) + if (! (p2[2 + idx] == 0 + || (idx < (int) p1[4] + && ((p2[2 + idx] & ~ p1[5 + idx]) == 0)))) + break; + + if (idx == p2[1]) + { + p[-3] = (unsigned char) pop_failure_jump; + DEBUG_PRINT1 (" No match => pop_failure_jump.\n"); + } + } + else if ((re_opcode_t) p1[3] == charset) + { + int idx; + /* We win if the charset inside the loop + has no overlap with the one after the loop. */ + for (idx = 0; + idx < (int) p2[1] && idx < (int) p1[4]; + idx++) + if ((p2[2 + idx] & p1[5 + idx]) != 0) + break; + + if (idx == p2[1] || idx == p1[4]) + { + p[-3] = (unsigned char) pop_failure_jump; + DEBUG_PRINT1 (" No match => pop_failure_jump.\n"); + } + } + } +#endif /* not WCHAR */ + } + p -= OFFSET_ADDRESS_SIZE; /* Point at relative address again. */ + if ((re_opcode_t) p[-1] != pop_failure_jump) + { + p[-1] = (UCHAR_T) jump; + DEBUG_PRINT1 (" Match => jump.\n"); + goto unconditional_jump; + } + /* Note fall through. */ + + + /* The end of a simple repeat has a pop_failure_jump back to + its matching on_failure_jump, where the latter will push a + failure point. The pop_failure_jump takes off failure + points put on by this pop_failure_jump's matching + on_failure_jump; we got through the pattern to here from the + matching on_failure_jump, so didn't fail. */ + case pop_failure_jump: + { + /* We need to pass separate storage for the lowest and + highest registers, even though we don't care about the + actual values. Otherwise, we will restore only one + register from the stack, since lowest will == highest in + `pop_failure_point'. */ + active_reg_t dummy_low_reg, dummy_high_reg; + UCHAR_T *pdummy = NULL; + const CHAR_T *sdummy = NULL; + + DEBUG_PRINT1 ("EXECUTING pop_failure_jump.\n"); + POP_FAILURE_POINT (sdummy, pdummy, + dummy_low_reg, dummy_high_reg, + reg_dummy, reg_dummy, reg_info_dummy); + } + /* Note fall through. */ + + unconditional_jump: +#ifdef _LIBC + DEBUG_PRINT2 ("\n%p: ", p); +#else + DEBUG_PRINT2 ("\n0x%x: ", p); +#endif + /* Note fall through. */ + + /* Unconditionally jump (without popping any failure points). */ + case jump: + EXTRACT_NUMBER_AND_INCR (mcnt, p); /* Get the amount to jump. */ + DEBUG_PRINT2 ("EXECUTING jump %d ", mcnt); + p += mcnt; /* Do the jump. */ +#ifdef _LIBC + DEBUG_PRINT2 ("(to %p).\n", p); +#else + DEBUG_PRINT2 ("(to 0x%x).\n", p); +#endif + break; + + + /* We need this opcode so we can detect where alternatives end + in `group_match_null_string_p' et al. */ + case jump_past_alt: + DEBUG_PRINT1 ("EXECUTING jump_past_alt.\n"); + goto unconditional_jump; + + + /* Normally, the on_failure_jump pushes a failure point, which + then gets popped at pop_failure_jump. We will end up at + pop_failure_jump, also, and with a pattern of, say, `a+', we + are skipping over the on_failure_jump, so we have to push + something meaningless for pop_failure_jump to pop. */ + case dummy_failure_jump: + DEBUG_PRINT1 ("EXECUTING dummy_failure_jump.\n"); + /* It doesn't matter what we push for the string here. What + the code at `fail' tests is the value for the pattern. */ + PUSH_FAILURE_POINT (NULL, NULL, -2); + goto unconditional_jump; + + + /* At the end of an alternative, we need to push a dummy failure + point in case we are followed by a `pop_failure_jump', because + we don't want the failure point for the alternative to be + popped. For example, matching `(a|ab)*' against `aab' + requires that we match the `ab' alternative. */ + case push_dummy_failure: + DEBUG_PRINT1 ("EXECUTING push_dummy_failure.\n"); + /* See comments just above at `dummy_failure_jump' about the + two zeroes. */ + PUSH_FAILURE_POINT (NULL, NULL, -2); + break; + + /* Have to succeed matching what follows at least n times. + After that, handle like `on_failure_jump'. */ + case succeed_n: + EXTRACT_NUMBER (mcnt, p + OFFSET_ADDRESS_SIZE); + DEBUG_PRINT2 ("EXECUTING succeed_n %d.\n", mcnt); + + assert (mcnt >= 0); + /* Originally, this is how many times we HAVE to succeed. */ + if (mcnt > 0) + { + mcnt--; + p += OFFSET_ADDRESS_SIZE; + STORE_NUMBER_AND_INCR (p, mcnt); +#ifdef _LIBC + DEBUG_PRINT3 (" Setting %p to %d.\n", p - OFFSET_ADDRESS_SIZE + , mcnt); +#else + DEBUG_PRINT3 (" Setting 0x%x to %d.\n", p - OFFSET_ADDRESS_SIZE + , mcnt); +#endif + } + else if (mcnt == 0) + { +#ifdef _LIBC + DEBUG_PRINT2 (" Setting two bytes from %p to no_op.\n", + p + OFFSET_ADDRESS_SIZE); +#else + DEBUG_PRINT2 (" Setting two bytes from 0x%x to no_op.\n", + p + OFFSET_ADDRESS_SIZE); +#endif /* _LIBC */ + +#ifdef WCHAR + p[1] = (UCHAR_T) no_op; +#else + p[2] = (UCHAR_T) no_op; + p[3] = (UCHAR_T) no_op; +#endif /* WCHAR */ + goto on_failure; + } + break; + + case jump_n: + EXTRACT_NUMBER (mcnt, p + OFFSET_ADDRESS_SIZE); + DEBUG_PRINT2 ("EXECUTING jump_n %d.\n", mcnt); + + /* Originally, this is how many times we CAN jump. */ + if (mcnt) + { + mcnt--; + STORE_NUMBER (p + OFFSET_ADDRESS_SIZE, mcnt); + +#ifdef _LIBC + DEBUG_PRINT3 (" Setting %p to %d.\n", p + OFFSET_ADDRESS_SIZE, + mcnt); +#else + DEBUG_PRINT3 (" Setting 0x%x to %d.\n", p + OFFSET_ADDRESS_SIZE, + mcnt); +#endif /* _LIBC */ + goto unconditional_jump; + } + /* If don't have to jump any more, skip over the rest of command. */ + else + p += 2 * OFFSET_ADDRESS_SIZE; + break; + + case set_number_at: + { + DEBUG_PRINT1 ("EXECUTING set_number_at.\n"); + + EXTRACT_NUMBER_AND_INCR (mcnt, p); + p1 = p + mcnt; + EXTRACT_NUMBER_AND_INCR (mcnt, p); +#ifdef _LIBC + DEBUG_PRINT3 (" Setting %p to %d.\n", p1, mcnt); +#else + DEBUG_PRINT3 (" Setting 0x%x to %d.\n", p1, mcnt); +#endif + STORE_NUMBER (p1, mcnt); + break; + } + +#if 0 + /* The DEC Alpha C compiler 3.x generates incorrect code for the + test WORDCHAR_P (d - 1) != WORDCHAR_P (d) in the expansion of + AT_WORD_BOUNDARY, so this code is disabled. Expanding the + macro and introducing temporary variables works around the bug. */ + + case wordbound: + DEBUG_PRINT1 ("EXECUTING wordbound.\n"); + if (AT_WORD_BOUNDARY (d)) + break; + goto fail; + + case notwordbound: + DEBUG_PRINT1 ("EXECUTING notwordbound.\n"); + if (AT_WORD_BOUNDARY (d)) + goto fail; + break; +#else + case wordbound: + { + boolean prevchar, thischar; + + DEBUG_PRINT1 ("EXECUTING wordbound.\n"); + if (AT_STRINGS_BEG (d) || AT_STRINGS_END (d)) + break; + + prevchar = WORDCHAR_P (d - 1); + thischar = WORDCHAR_P (d); + if (prevchar != thischar) + break; + goto fail; + } + + case notwordbound: + { + boolean prevchar, thischar; + + DEBUG_PRINT1 ("EXECUTING notwordbound.\n"); + if (AT_STRINGS_BEG (d) || AT_STRINGS_END (d)) + goto fail; + + prevchar = WORDCHAR_P (d - 1); + thischar = WORDCHAR_P (d); + if (prevchar != thischar) + goto fail; + break; + } +#endif + + case wordbeg: + DEBUG_PRINT1 ("EXECUTING wordbeg.\n"); + if (!AT_STRINGS_END (d) && WORDCHAR_P (d) + && (AT_STRINGS_BEG (d) || !WORDCHAR_P (d - 1))) + break; + goto fail; + + case wordend: + DEBUG_PRINT1 ("EXECUTING wordend.\n"); + if (!AT_STRINGS_BEG (d) && WORDCHAR_P (d - 1) + && (AT_STRINGS_END (d) || !WORDCHAR_P (d))) + break; + goto fail; + +#ifdef emacs + case before_dot: + DEBUG_PRINT1 ("EXECUTING before_dot.\n"); + if (PTR_CHAR_POS ((unsigned char *) d) >= point) + goto fail; + break; + + case at_dot: + DEBUG_PRINT1 ("EXECUTING at_dot.\n"); + if (PTR_CHAR_POS ((unsigned char *) d) != point) + goto fail; + break; + + case after_dot: + DEBUG_PRINT1 ("EXECUTING after_dot.\n"); + if (PTR_CHAR_POS ((unsigned char *) d) <= point) + goto fail; + break; + + case syntaxspec: + DEBUG_PRINT2 ("EXECUTING syntaxspec %d.\n", mcnt); + mcnt = *p++; + goto matchsyntax; + + case wordchar: + DEBUG_PRINT1 ("EXECUTING Emacs wordchar.\n"); + mcnt = (int) Sword; + matchsyntax: + PREFETCH (); + /* Can't use *d++ here; SYNTAX may be an unsafe macro. */ + d++; + if (SYNTAX (d[-1]) != (enum syntaxcode) mcnt) + goto fail; + SET_REGS_MATCHED (); + break; + + case notsyntaxspec: + DEBUG_PRINT2 ("EXECUTING notsyntaxspec %d.\n", mcnt); + mcnt = *p++; + goto matchnotsyntax; + + case notwordchar: + DEBUG_PRINT1 ("EXECUTING Emacs notwordchar.\n"); + mcnt = (int) Sword; + matchnotsyntax: + PREFETCH (); + /* Can't use *d++ here; SYNTAX may be an unsafe macro. */ + d++; + if (SYNTAX (d[-1]) == (enum syntaxcode) mcnt) + goto fail; + SET_REGS_MATCHED (); + break; + +#else /* not emacs */ + case wordchar: + DEBUG_PRINT1 ("EXECUTING non-Emacs wordchar.\n"); + PREFETCH (); + if (!WORDCHAR_P (d)) + goto fail; + SET_REGS_MATCHED (); + d++; + break; + + case notwordchar: + DEBUG_PRINT1 ("EXECUTING non-Emacs notwordchar.\n"); + PREFETCH (); + if (WORDCHAR_P (d)) + goto fail; + SET_REGS_MATCHED (); + d++; + break; +#endif /* not emacs */ + + default: + abort (); + } + continue; /* Successfully executed one pattern command; keep going. */ + + + /* We goto here if a matching operation fails. */ + fail: + if (!FAIL_STACK_EMPTY ()) + { /* A restart point is known. Restore to that state. */ + DEBUG_PRINT1 ("\nFAIL:\n"); + POP_FAILURE_POINT (d, p, + lowest_active_reg, highest_active_reg, + regstart, regend, reg_info); + + /* If this failure point is a dummy, try the next one. */ + if (!p) + goto fail; + + /* If we failed to the end of the pattern, don't examine *p. */ + assert (p <= pend); + if (p < pend) + { + boolean is_a_jump_n = false; + + /* If failed to a backwards jump that's part of a repetition + loop, need to pop this failure point and use the next one. */ + switch ((re_opcode_t) *p) + { + case jump_n: + is_a_jump_n = true; + case maybe_pop_jump: + case pop_failure_jump: + case jump: + p1 = p + 1; + EXTRACT_NUMBER_AND_INCR (mcnt, p1); + p1 += mcnt; + + if ((is_a_jump_n && (re_opcode_t) *p1 == succeed_n) + || (!is_a_jump_n + && (re_opcode_t) *p1 == on_failure_jump)) + goto fail; + break; + default: + /* do nothing */ ; + } + } + + if (d >= string1 && d <= end1) + dend = end_match_1; + } + else + break; /* Matching at this starting point really fails. */ + } /* for (;;) */ + + if (best_regs_set) + goto restore_best_regs; + + FREE_VARIABLES (); + + return -1; /* Failure to match. */ +} /* re_match_2 */ + +/* Subroutine definitions for re_match_2. */ + + +/* We are passed P pointing to a register number after a start_memory. + + Return true if the pattern up to the corresponding stop_memory can + match the empty string, and false otherwise. + + If we find the matching stop_memory, sets P to point to one past its number. + Otherwise, sets P to an undefined byte less than or equal to END. + + We don't handle duplicates properly (yet). */ + +static boolean +PREFIX(group_match_null_string_p) ( + UCHAR_T **p, UCHAR_T *end, + PREFIX(register_info_type) *reg_info) +{ + int mcnt; + /* Point to after the args to the start_memory. */ + UCHAR_T *p1 = *p + 2; + + while (p1 < end) + { + /* Skip over opcodes that can match nothing, and return true or + false, as appropriate, when we get to one that can't, or to the + matching stop_memory. */ + + switch ((re_opcode_t) *p1) + { + /* Could be either a loop or a series of alternatives. */ + case on_failure_jump: + p1++; + EXTRACT_NUMBER_AND_INCR (mcnt, p1); + + /* If the next operation is not a jump backwards in the + pattern. */ + + if (mcnt >= 0) + { + /* Go through the on_failure_jumps of the alternatives, + seeing if any of the alternatives cannot match nothing. + The last alternative starts with only a jump, + whereas the rest start with on_failure_jump and end + with a jump, e.g., here is the pattern for `a|b|c': + + /on_failure_jump/0/6/exactn/1/a/jump_past_alt/0/6 + /on_failure_jump/0/6/exactn/1/b/jump_past_alt/0/3 + /exactn/1/c + + So, we have to first go through the first (n-1) + alternatives and then deal with the last one separately. */ + + + /* Deal with the first (n-1) alternatives, which start + with an on_failure_jump (see above) that jumps to right + past a jump_past_alt. */ + + while ((re_opcode_t) p1[mcnt-(1+OFFSET_ADDRESS_SIZE)] == + jump_past_alt) + { + /* `mcnt' holds how many bytes long the alternative + is, including the ending `jump_past_alt' and + its number. */ + + if (!PREFIX(alt_match_null_string_p) (p1, p1 + mcnt - + (1 + OFFSET_ADDRESS_SIZE), + reg_info)) + return false; + + /* Move to right after this alternative, including the + jump_past_alt. */ + p1 += mcnt; + + /* Break if it's the beginning of an n-th alternative + that doesn't begin with an on_failure_jump. */ + if ((re_opcode_t) *p1 != on_failure_jump) + break; + + /* Still have to check that it's not an n-th + alternative that starts with an on_failure_jump. */ + p1++; + EXTRACT_NUMBER_AND_INCR (mcnt, p1); + if ((re_opcode_t) p1[mcnt-(1+OFFSET_ADDRESS_SIZE)] != + jump_past_alt) + { + /* Get to the beginning of the n-th alternative. */ + p1 -= 1 + OFFSET_ADDRESS_SIZE; + break; + } + } + + /* Deal with the last alternative: go back and get number + of the `jump_past_alt' just before it. `mcnt' contains + the length of the alternative. */ + EXTRACT_NUMBER (mcnt, p1 - OFFSET_ADDRESS_SIZE); + + if (!PREFIX(alt_match_null_string_p) (p1, p1 + mcnt, reg_info)) + return false; + + p1 += mcnt; /* Get past the n-th alternative. */ + } /* if mcnt > 0 */ + break; + + + case stop_memory: + assert (p1[1] == **p); + *p = p1 + 2; + return true; + + + default: + if (!PREFIX(common_op_match_null_string_p) (&p1, end, reg_info)) + return false; + } + } /* while p1 < end */ + + return false; +} /* group_match_null_string_p */ + + +/* Similar to group_match_null_string_p, but doesn't deal with alternatives: + It expects P to be the first byte of a single alternative and END one + byte past the last. The alternative can contain groups. */ + +static boolean +PREFIX(alt_match_null_string_p) ( + UCHAR_T *p, UCHAR_T *end, + PREFIX(register_info_type) *reg_info) +{ + int mcnt; + UCHAR_T *p1 = p; + + while (p1 < end) + { + /* Skip over opcodes that can match nothing, and break when we get + to one that can't. */ + + switch ((re_opcode_t) *p1) + { + /* It's a loop. */ + case on_failure_jump: + p1++; + EXTRACT_NUMBER_AND_INCR (mcnt, p1); + p1 += mcnt; + break; + + default: + if (!PREFIX(common_op_match_null_string_p) (&p1, end, reg_info)) + return false; + } + } /* while p1 < end */ + + return true; +} /* alt_match_null_string_p */ + + +/* Deals with the ops common to group_match_null_string_p and + alt_match_null_string_p. + + Sets P to one after the op and its arguments, if any. */ + +static boolean +PREFIX(common_op_match_null_string_p) ( + UCHAR_T **p, UCHAR_T *end, + PREFIX(register_info_type) *reg_info) +{ + int mcnt; + boolean ret; + int reg_no; + UCHAR_T *p1 = *p; + + switch ((re_opcode_t) *p1++) + { + case no_op: + case begline: + case endline: + case begbuf: + case endbuf: + case wordbeg: + case wordend: + case wordbound: + case notwordbound: +#ifdef emacs + case before_dot: + case at_dot: + case after_dot: +#endif + break; + + case start_memory: + reg_no = *p1; + assert (reg_no > 0 && reg_no <= MAX_REGNUM); + ret = PREFIX(group_match_null_string_p) (&p1, end, reg_info); + + /* Have to set this here in case we're checking a group which + contains a group and a back reference to it. */ + + if (REG_MATCH_NULL_STRING_P (reg_info[reg_no]) == MATCH_NULL_UNSET_VALUE) + REG_MATCH_NULL_STRING_P (reg_info[reg_no]) = ret; + + if (!ret) + return false; + break; + + /* If this is an optimized succeed_n for zero times, make the jump. */ + case jump: + EXTRACT_NUMBER_AND_INCR (mcnt, p1); + if (mcnt >= 0) + p1 += mcnt; + else + return false; + break; + + case succeed_n: + /* Get to the number of times to succeed. */ + p1 += OFFSET_ADDRESS_SIZE; + EXTRACT_NUMBER_AND_INCR (mcnt, p1); + + if (mcnt == 0) + { + p1 -= 2 * OFFSET_ADDRESS_SIZE; + EXTRACT_NUMBER_AND_INCR (mcnt, p1); + p1 += mcnt; + } + else + return false; + break; + + case duplicate: + if (!REG_MATCH_NULL_STRING_P (reg_info[*p1])) + return false; + break; + + case set_number_at: + p1 += 2 * OFFSET_ADDRESS_SIZE; + + default: + /* All other opcodes mean we cannot match the empty string. */ + return false; + } + + *p = p1; + return true; +} /* common_op_match_null_string_p */ + + +/* Return zero if TRANSLATE[S1] and TRANSLATE[S2] are identical for LEN + bytes; nonzero otherwise. */ + +static int +PREFIX(bcmp_translate) ( + const CHAR_T *s1, const CHAR_T *s2, + register int len, + RE_TRANSLATE_TYPE translate) +{ + register const UCHAR_T *p1 = (const UCHAR_T *) s1; + register const UCHAR_T *p2 = (const UCHAR_T *) s2; + while (len) + { +#ifdef WCHAR + if (((*p1<=0xff)?translate[*p1++]:*p1++) + != ((*p2<=0xff)?translate[*p2++]:*p2++)) + return 1; +#else /* BYTE */ + if (translate[*p1++] != translate[*p2++]) return 1; +#endif /* WCHAR */ + len--; + } + return 0; +} + + +#else /* not INSIDE_RECURSION */ + +/* Entry points for GNU code. */ + +/* re_compile_pattern is the GNU regular expression compiler: it + compiles PATTERN (of length SIZE) and puts the result in BUFP. + Returns 0 if the pattern was valid, otherwise an error string. + + Assumes the `allocated' (and perhaps `buffer') and `translate' fields + are set in BUFP on entry. + + We call regex_compile to do the actual compilation. */ + +const char * +re_compile_pattern (const char *pattern, + size_t length, + struct re_pattern_buffer *bufp) +{ + reg_errcode_t ret; + + /* GNU code is written to assume at least RE_NREGS registers will be set + (and at least one extra will be -1). */ + bufp->regs_allocated = REGS_UNALLOCATED; + + /* And GNU code determines whether or not to get register information + by passing null for the REGS argument to re_match, etc., not by + setting no_sub. */ + bufp->no_sub = 0; + + /* Match anchors at newline. */ + bufp->newline_anchor = 1; + +# ifdef MBS_SUPPORT + if (MB_CUR_MAX != 1) + ret = wcs_regex_compile (pattern, length, re_syntax_options, bufp); + else +# endif + ret = byte_regex_compile (pattern, length, re_syntax_options, bufp); + + if (!ret) + return NULL; + return gettext (re_error_msgid + re_error_msgid_idx[(int) ret]); +} + +/* Entry points compatible with 4.2 BSD regex library. We don't define + them unless specifically requested. */ + +#if defined _REGEX_RE_COMP || defined _LIBC + +/* BSD has one and only one pattern buffer. */ +static struct re_pattern_buffer re_comp_buf; + +char * +#ifdef _LIBC +/* Make these definitions weak in libc, so POSIX programs can redefine + these names if they don't use our functions, and still use + regcomp/regexec below without link errors. */ +weak_function +#endif +re_comp (const char *s) +{ + reg_errcode_t ret; + + if (!s) + { + if (!re_comp_buf.buffer) + return gettext ("No previous regular expression"); + return 0; + } + + if (!re_comp_buf.buffer) + { + re_comp_buf.buffer = (unsigned char *) malloc (200); + if (re_comp_buf.buffer == NULL) + return (char *) gettext (re_error_msgid + + re_error_msgid_idx[(int) REG_ESPACE]); + re_comp_buf.allocated = 200; + + re_comp_buf.fastmap = (char *) malloc (1 << BYTEWIDTH); + if (re_comp_buf.fastmap == NULL) + return (char *) gettext (re_error_msgid + + re_error_msgid_idx[(int) REG_ESPACE]); + } + + /* Since `re_exec' always passes NULL for the `regs' argument, we + don't need to initialize the pattern buffer fields which affect it. */ + + /* Match anchors at newlines. */ + re_comp_buf.newline_anchor = 1; + +# ifdef MBS_SUPPORT + if (MB_CUR_MAX != 1) + ret = wcs_regex_compile (s, strlen (s), re_syntax_options, &re_comp_buf); + else +# endif + ret = byte_regex_compile (s, strlen (s), re_syntax_options, &re_comp_buf); + + if (!ret) + return NULL; + + /* Yes, we're discarding `const' here if !HAVE_LIBINTL. */ + return (char *) gettext (re_error_msgid + re_error_msgid_idx[(int) ret]); +} + + +int +#if defined _LIBC || defined __UCLIBC__ +weak_function +#endif +re_exec (const char *s) +{ + const int len = strlen (s); + return + 0 <= re_search (&re_comp_buf, s, len, 0, len, (struct re_registers *) 0); +} + +#endif /* _REGEX_RE_COMP */ + +/* POSIX.2 functions. Don't define these for Emacs. */ + +#ifndef emacs + +/* regcomp takes a regular expression as a string and compiles it. + + PREG is a regex_t *. We do not expect any fields to be initialized, + since POSIX says we shouldn't. Thus, we set + + `buffer' to the compiled pattern; + `used' to the length of the compiled pattern; + `syntax' to RE_SYNTAX_POSIX_EXTENDED if the + REG_EXTENDED bit in CFLAGS is set; otherwise, to + RE_SYNTAX_POSIX_BASIC; + `newline_anchor' to REG_NEWLINE being set in CFLAGS; + `fastmap' to an allocated space for the fastmap; + `fastmap_accurate' to zero; + `re_nsub' to the number of subexpressions in PATTERN. + + PATTERN is the address of the pattern string. + + CFLAGS is a series of bits which affect compilation. + + If REG_EXTENDED is set, we use POSIX extended syntax; otherwise, we + use POSIX basic syntax. + + If REG_NEWLINE is set, then . and [^...] don't match newline. + Also, regexec will try a match beginning after every newline. + + If REG_ICASE is set, then we considers upper- and lowercase + versions of letters to be equivalent when matching. + + If REG_NOSUB is set, then when PREG is passed to regexec, that + routine will report only success or failure, and nothing about the + registers. + + It returns 0 if it succeeds, nonzero if it doesn't. (See regex.h for + the return codes and their meanings.) */ + +int +regcomp ( + regex_t *preg, + const char *pattern, + int cflags) +{ + reg_errcode_t ret; + reg_syntax_t syntax + = (cflags & REG_EXTENDED) ? + RE_SYNTAX_POSIX_EXTENDED : RE_SYNTAX_POSIX_BASIC; + + /* regex_compile will allocate the space for the compiled pattern. */ + preg->buffer = 0; + preg->allocated = 0; + preg->used = 0; + + /* Try to allocate space for the fastmap. */ + preg->fastmap = (char *) malloc (1 << BYTEWIDTH); + + if (cflags & REG_ICASE) + { + unsigned i; + + preg->translate + = (RE_TRANSLATE_TYPE) malloc (CHAR_SET_SIZE + * sizeof (*(RE_TRANSLATE_TYPE)0)); + if (preg->translate == NULL) + return (int) REG_ESPACE; + + /* Map uppercase characters to corresponding lowercase ones. */ + for (i = 0; i < CHAR_SET_SIZE; i++) + preg->translate[i] = ISUPPER (i) ? TOLOWER (i) : i; + } + else + preg->translate = NULL; + + /* If REG_NEWLINE is set, newlines are treated differently. */ + if (cflags & REG_NEWLINE) + { /* REG_NEWLINE implies neither . nor [^...] match newline. */ + syntax &= ~RE_DOT_NEWLINE; + syntax |= RE_HAT_LISTS_NOT_NEWLINE; + /* It also changes the matching behavior. */ + preg->newline_anchor = 1; + } + else + preg->newline_anchor = 0; + + preg->no_sub = !!(cflags & REG_NOSUB); + + /* POSIX says a null character in the pattern terminates it, so we + can use strlen here in compiling the pattern. */ +# ifdef MBS_SUPPORT + if (MB_CUR_MAX != 1) + ret = wcs_regex_compile (pattern, strlen (pattern), syntax, preg); + else +# endif + ret = byte_regex_compile (pattern, strlen (pattern), syntax, preg); + + /* POSIX doesn't distinguish between an unmatched open-group and an + unmatched close-group: both are REG_EPAREN. */ + if (ret == REG_ERPAREN) ret = REG_EPAREN; + + if (ret == REG_NOERROR && preg->fastmap) + { + /* Compute the fastmap now, since regexec cannot modify the pattern + buffer. */ + if (re_compile_fastmap (preg) == -2) + { + /* Some error occurred while computing the fastmap, just forget + about it. */ + free (preg->fastmap); + preg->fastmap = NULL; + } + } + + return (int) ret; +} + + +/* regexec searches for a given pattern, specified by PREG, in the + string STRING. + + If NMATCH is zero or REG_NOSUB was set in the cflags argument to + `regcomp', we ignore PMATCH. Otherwise, we assume PMATCH has at + least NMATCH elements, and we set them to the offsets of the + corresponding matched substrings. + + EFLAGS specifies `execution flags' which affect matching: if + REG_NOTBOL is set, then ^ does not match at the beginning of the + string; if REG_NOTEOL is set, then $ does not match at the end. + + We return 0 if we find a match and REG_NOMATCH if not. */ + +int +regexec ( + const regex_t *preg, + const char *string, + size_t nmatch, + regmatch_t pmatch[], + int eflags) +{ + int ret; + struct re_registers regs; + regex_t private_preg; + int len = strlen (string); + boolean want_reg_info = !preg->no_sub && nmatch > 0; + + /* use hidden memcpy() ourselves rather than gcc calling public memcpy() */ + memcpy(&private_preg, preg, sizeof(*preg)); + + private_preg.not_bol = !!(eflags & REG_NOTBOL); + private_preg.not_eol = !!(eflags & REG_NOTEOL); + + /* The user has told us exactly how many registers to return + information about, via `nmatch'. We have to pass that on to the + matching routines. */ + private_preg.regs_allocated = REGS_FIXED; + + if (want_reg_info) + { + regs.num_regs = nmatch; + regs.start = TALLOC (nmatch * 2, regoff_t); + if (regs.start == NULL) + return (int) REG_NOMATCH; + regs.end = regs.start + nmatch; + } + + /* Perform the searching operation. */ + ret = re_search (&private_preg, string, len, + /* start: */ 0, /* range: */ len, + want_reg_info ? ®s : (struct re_registers *) 0); + + /* Copy the register information to the POSIX structure. */ + if (want_reg_info) + { + if (ret >= 0) + { + unsigned r; + + for (r = 0; r < nmatch; r++) + { + pmatch[r].rm_so = regs.start[r]; + pmatch[r].rm_eo = regs.end[r]; + } + } + + /* If we needed the temporary register info, free the space now. */ + free (regs.start); + } + + /* We want zero return to mean success, unlike `re_search'. */ + return ret >= 0 ? (int) REG_NOERROR : (int) REG_NOMATCH; +} +libc_hidden_def(regexec) + + +/* Returns a message corresponding to an error code, ERRCODE, returned + from either regcomp or regexec. We don't use PREG here. */ + +size_t +regerror ( + int errcode, + const regex_t * preg attribute_unused, + char *errbuf, + size_t errbuf_size) +{ + const char *msg; + size_t msg_size; + + if (errcode < 0 + || errcode >= (int) (sizeof (re_error_msgid_idx) + / sizeof (re_error_msgid_idx[0]))) + /* Only error codes returned by the rest of the code should be passed + to this routine. If we are given anything else, or if other regex + code generates an invalid error code, then the program has a bug. + Dump core so we can fix it. */ + abort (); + + msg = gettext (re_error_msgid + re_error_msgid_idx[errcode]); + + msg_size = strlen (msg) + 1; /* Includes the null. */ + + if (errbuf_size != 0) + { + if (msg_size > errbuf_size) + { + memcpy (errbuf, msg, errbuf_size - 1); + errbuf[errbuf_size - 1] = 0; + } + else + memcpy (errbuf, msg, msg_size); + } + + return msg_size; +} + + +/* Free dynamically allocated space used by PREG. */ + +void +regfree (regex_t *preg) +{ + free (preg->buffer); + preg->buffer = NULL; + + preg->allocated = 0; + preg->used = 0; + + free (preg->fastmap); + preg->fastmap = NULL; + preg->fastmap_accurate = 0; + + free (preg->translate); + preg->translate = NULL; +} +libc_hidden_def(regfree) + +#endif /* not emacs */ + +#endif /* not INSIDE_RECURSION */ + + +#undef STORE_NUMBER +#undef STORE_NUMBER_AND_INCR +#undef EXTRACT_NUMBER +#undef EXTRACT_NUMBER_AND_INCR + +#undef DEBUG_PRINT_COMPILED_PATTERN +#undef DEBUG_PRINT_DOUBLE_STRING + +#undef INIT_FAIL_STACK +#undef RESET_FAIL_STACK +#undef DOUBLE_FAIL_STACK +#undef PUSH_PATTERN_OP +#undef PUSH_FAILURE_POINTER +#undef PUSH_FAILURE_INT +#undef PUSH_FAILURE_ELT +#undef POP_FAILURE_POINTER +#undef POP_FAILURE_INT +#undef POP_FAILURE_ELT +#undef DEBUG_PUSH +#undef DEBUG_POP +#undef PUSH_FAILURE_POINT +#undef POP_FAILURE_POINT + +#undef REG_UNSET_VALUE +#undef REG_UNSET + +#undef PATFETCH +#undef PATFETCH_RAW +#undef PATUNFETCH +#undef TRANSLATE + +#undef INIT_BUF_SIZE +#undef GET_BUFFER_SPACE +#undef BUF_PUSH +#undef BUF_PUSH_2 +#undef BUF_PUSH_3 +#undef STORE_JUMP +#undef STORE_JUMP2 +#undef INSERT_JUMP +#undef INSERT_JUMP2 +#undef EXTEND_BUFFER +#undef GET_UNSIGNED_NUMBER +#undef FREE_STACK_RETURN + +# undef POINTER_TO_OFFSET +# undef MATCHING_IN_FRST_STRING +# undef PREFETCH +# undef AT_STRINGS_BEG +# undef AT_STRINGS_END +# undef WORDCHAR_P +# undef FREE_VAR +# undef FREE_VARIABLES +# undef NO_HIGHEST_ACTIVE_REG +# undef NO_LOWEST_ACTIVE_REG + +# undef CHAR_T +# undef UCHAR_T +# undef COMPILED_BUFFER_VAR +# undef OFFSET_ADDRESS_SIZE +# undef CHAR_CLASS_SIZE +# undef PREFIX +# undef ARG_PREFIX +# undef PUT_CHAR +# undef BYTE +# undef WCHAR + +# define DEFINED_ONCE diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/regex/regexec.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/regex/regexec.c new file mode 100644 index 00000000..c13c64ef --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/regex/regexec.c @@ -0,0 +1,4247 @@ +/* Extended regular expression matching and search library. + Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Isamu Hasegawa . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +static reg_errcode_t match_ctx_init (re_match_context_t *cache, int eflags, + int n) internal_function; +static void match_ctx_clean (re_match_context_t *mctx) internal_function; +static void match_ctx_free (re_match_context_t *cache) internal_function; +static reg_errcode_t match_ctx_add_entry (re_match_context_t *cache, int node, + int str_idx, int from, int to) + internal_function; +static int search_cur_bkref_entry (const re_match_context_t *mctx, int str_idx) + internal_function; +static reg_errcode_t match_ctx_add_subtop (re_match_context_t *mctx, int node, + int str_idx) internal_function; +static re_sub_match_last_t * match_ctx_add_sublast (re_sub_match_top_t *subtop, + int node, int str_idx) + internal_function; +static void sift_ctx_init (re_sift_context_t *sctx, re_dfastate_t **sifted_sts, + re_dfastate_t **limited_sts, int last_node, + int last_str_idx) + internal_function; +static reg_errcode_t re_search_internal (const regex_t *preg, + const char *string, int length, + int start, int range, int stop, + size_t nmatch, regmatch_t pmatch[], + int eflags) internal_function; +static int re_search_2_stub (struct re_pattern_buffer *bufp, + const char *string1, int length1, + const char *string2, int length2, + int start, int range, struct re_registers *regs, + int stop, int ret_len) internal_function; +static int re_search_stub (struct re_pattern_buffer *bufp, + const char *string, int length, int start, + int range, int stop, struct re_registers *regs, + int ret_len) internal_function; +static unsigned re_copy_regs (struct re_registers *regs, regmatch_t *pmatch, + int nregs, int regs_allocated) internal_function; +static reg_errcode_t prune_impossible_nodes (re_match_context_t *mctx) + internal_function; +static int check_matching (re_match_context_t *mctx, int fl_longest_match, + int *p_match_first) internal_function; +static int check_halt_state_context (const re_match_context_t *mctx, + const re_dfastate_t *state, int idx) + internal_function; +static void update_regs (const re_dfa_t *dfa, regmatch_t *pmatch, + regmatch_t *prev_idx_match, int cur_node, + int cur_idx, int nmatch) internal_function; +static reg_errcode_t push_fail_stack (struct re_fail_stack_t *fs, + int str_idx, int dest_node, int nregs, + regmatch_t *regs, + re_node_set *eps_via_nodes) + internal_function; +static reg_errcode_t set_regs (const regex_t *preg, + const re_match_context_t *mctx, + size_t nmatch, regmatch_t *pmatch, + int fl_backtrack) internal_function; +static reg_errcode_t free_fail_stack_return (struct re_fail_stack_t *fs) + internal_function; + +#ifdef RE_ENABLE_I18N +static int sift_states_iter_mb (const re_match_context_t *mctx, + re_sift_context_t *sctx, + int node_idx, int str_idx, int max_str_idx) + internal_function; +#endif +static reg_errcode_t sift_states_backward (const re_match_context_t *mctx, + re_sift_context_t *sctx) + internal_function; +static reg_errcode_t build_sifted_states (const re_match_context_t *mctx, + re_sift_context_t *sctx, int str_idx, + re_node_set *cur_dest) + internal_function; +static reg_errcode_t update_cur_sifted_state (const re_match_context_t *mctx, + re_sift_context_t *sctx, + int str_idx, + re_node_set *dest_nodes) + internal_function; +static reg_errcode_t add_epsilon_src_nodes (const re_dfa_t *dfa, + re_node_set *dest_nodes, + const re_node_set *candidates) + internal_function; +static int check_dst_limits (const re_match_context_t *mctx, + re_node_set *limits, + int dst_node, int dst_idx, int src_node, + int src_idx) internal_function; +static int check_dst_limits_calc_pos_1 (const re_match_context_t *mctx, + int boundaries, int subexp_idx, + int from_node, int bkref_idx) + internal_function; +static int check_dst_limits_calc_pos (const re_match_context_t *mctx, + int limit, int subexp_idx, + int node, int str_idx, + int bkref_idx) internal_function; +static reg_errcode_t check_subexp_limits (const re_dfa_t *dfa, + re_node_set *dest_nodes, + const re_node_set *candidates, + re_node_set *limits, + struct re_backref_cache_entry *bkref_ents, + int str_idx) internal_function; +static reg_errcode_t sift_states_bkref (const re_match_context_t *mctx, + re_sift_context_t *sctx, + int str_idx, const re_node_set *candidates) + internal_function; +static reg_errcode_t merge_state_array (const re_dfa_t *dfa, + re_dfastate_t **dst, + re_dfastate_t **src, int num) + internal_function; +static re_dfastate_t *find_recover_state (reg_errcode_t *err, + re_match_context_t *mctx) internal_function; +static re_dfastate_t *transit_state (reg_errcode_t *err, + re_match_context_t *mctx, + re_dfastate_t *state) internal_function; +static re_dfastate_t *merge_state_with_log (reg_errcode_t *err, + re_match_context_t *mctx, + re_dfastate_t *next_state) + internal_function; +static reg_errcode_t check_subexp_matching_top (re_match_context_t *mctx, + re_node_set *cur_nodes, + int str_idx) internal_function; +#if 0 +static re_dfastate_t *transit_state_sb (reg_errcode_t *err, + re_match_context_t *mctx, + re_dfastate_t *pstate) + internal_function; +#endif +#ifdef RE_ENABLE_I18N +static reg_errcode_t transit_state_mb (re_match_context_t *mctx, + re_dfastate_t *pstate) + internal_function; +#endif +static reg_errcode_t transit_state_bkref (re_match_context_t *mctx, + const re_node_set *nodes) + internal_function; +static reg_errcode_t get_subexp (re_match_context_t *mctx, + int bkref_node, int bkref_str_idx) + internal_function; +static reg_errcode_t get_subexp_sub (re_match_context_t *mctx, + const re_sub_match_top_t *sub_top, + re_sub_match_last_t *sub_last, + int bkref_node, int bkref_str) + internal_function; +static int find_subexp_node (const re_dfa_t *dfa, const re_node_set *nodes, + int subexp_idx, int type) internal_function; +static reg_errcode_t check_arrival (re_match_context_t *mctx, + state_array_t *path, int top_node, + int top_str, int last_node, int last_str, + int type) internal_function; +static reg_errcode_t check_arrival_add_next_nodes (re_match_context_t *mctx, + int str_idx, + re_node_set *cur_nodes, + re_node_set *next_nodes) + internal_function; +static reg_errcode_t check_arrival_expand_ecl (const re_dfa_t *dfa, + re_node_set *cur_nodes, + int ex_subexp, int type) + internal_function; +static reg_errcode_t check_arrival_expand_ecl_sub (const re_dfa_t *dfa, + re_node_set *dst_nodes, + int target, int ex_subexp, + int type) internal_function; +static reg_errcode_t expand_bkref_cache (re_match_context_t *mctx, + re_node_set *cur_nodes, int cur_str, + int subexp_num, int type) + internal_function; +static int build_trtable (const re_dfa_t *dfa, + re_dfastate_t *state) internal_function; +#ifdef RE_ENABLE_I18N +static int check_node_accept_bytes (const re_dfa_t *dfa, int node_idx, + const re_string_t *input, int idx) + internal_function; +#endif +static int group_nodes_into_DFAstates (const re_dfa_t *dfa, + const re_dfastate_t *state, + re_node_set *states_node, + bitset_t *states_ch) internal_function; +static int check_node_accept (const re_match_context_t *mctx, + const re_token_t *node, int idx) + internal_function; +static reg_errcode_t extend_buffers (re_match_context_t *mctx) + internal_function; + +/* Entry point for POSIX code. */ + +/* regexec searches for a given pattern, specified by PREG, in the + string STRING. + + If NMATCH is zero or REG_NOSUB was set in the cflags argument to + `regcomp', we ignore PMATCH. Otherwise, we assume PMATCH has at + least NMATCH elements, and we set them to the offsets of the + corresponding matched substrings. + + EFLAGS specifies `execution flags' which affect matching: if + REG_NOTBOL is set, then ^ does not match at the beginning of the + string; if REG_NOTEOL is set, then $ does not match at the end. + + We return 0 if we find a match and REG_NOMATCH if not. */ + +int +regexec (const regex_t *__restrict preg, const char *__restrict string, + size_t nmatch, regmatch_t pmatch[], int eflags) +{ + reg_errcode_t err; + int start, length; +#ifdef __UCLIBC_HAS_THREADS__ + re_dfa_t *dfa = (re_dfa_t *) preg->buffer; +#endif + + if (eflags & ~(REG_NOTBOL | REG_NOTEOL | REG_STARTEND)) + return REG_BADPAT; + + if (eflags & REG_STARTEND) + { + start = pmatch[0].rm_so; + length = pmatch[0].rm_eo; + } + else + { + start = 0; + length = strlen (string); + } + + __libc_lock_lock (dfa->lock); + if (preg->no_sub) + err = re_search_internal (preg, string, length, start, length - start, + length, 0, NULL, eflags); + else + err = re_search_internal (preg, string, length, start, length - start, + length, nmatch, pmatch, eflags); + __libc_lock_unlock (dfa->lock); + return err != REG_NOERROR; +} +libc_hidden_def(regexec) + +/* Entry points for GNU code. */ + +/* re_match, re_search, re_match_2, re_search_2 + + The former two functions operate on STRING with length LENGTH, + while the later two operate on concatenation of STRING1 and STRING2 + with lengths LENGTH1 and LENGTH2, respectively. + + re_match() matches the compiled pattern in BUFP against the string, + starting at index START. + + re_search() first tries matching at index START, then it tries to match + starting from index START + 1, and so on. The last start position tried + is START + RANGE. (Thus RANGE = 0 forces re_search to operate the same + way as re_match().) + + The parameter STOP of re_{match,search}_2 specifies that no match exceeding + the first STOP characters of the concatenation of the strings should be + concerned. + + If REGS is not NULL, and BUFP->no_sub is not set, the offsets of the match + and all groups is stroed in REGS. (For the "_2" variants, the offsets are + computed relative to the concatenation, not relative to the individual + strings.) + + On success, re_match* functions return the length of the match, re_search* + return the position of the start of the match. Return value -1 means no + match was found and -2 indicates an internal error. */ + +int +re_match (struct re_pattern_buffer *bufp, const char *string, int length, + int start, struct re_registers *regs) +{ + return re_search_stub (bufp, string, length, start, 0, length, regs, 1); +} + +int +re_search (struct re_pattern_buffer *bufp, const char *string, int length, + int start, int range, struct re_registers *regs) +{ + return re_search_stub (bufp, string, length, start, range, length, regs, 0); +} +libc_hidden_def(re_search) + +int +re_match_2 (struct re_pattern_buffer *bufp, const char *string1, int length1, + const char *string2, int length2, int start, + struct re_registers *regs, int stop) +{ + return re_search_2_stub (bufp, string1, length1, string2, length2, + start, 0, regs, stop, 1); +} + +int +re_search_2 (struct re_pattern_buffer *bufp, const char *string1, int lenght1, + const char *string2, int length2, int start, int range, + struct re_registers *regs, int stop) +{ + return re_search_2_stub (bufp, string1, lenght1, string2, length2, + start, range, regs, stop, 0); +} +libc_hidden_def(re_search_2) + +static int internal_function +re_search_2_stub (struct re_pattern_buffer *bufp, const char *string1, + int length1, const char *string2, int length2, int start, + int range, struct re_registers *regs, int stop, int ret_len) +{ + const char *str; + int rval; + int len = length1 + length2; + int free_str = 0; + + if (BE (length1 < 0 || length2 < 0 || stop < 0, 0)) + return -2; + + /* Concatenate the strings. */ + if (length2 > 0) + if (length1 > 0) + { + char *s = re_malloc (char, len); + + if (BE (s == NULL, 0)) + return -2; + memcpy (s, string1, length1); + memcpy (s + length1, string2, length2); + str = s; + free_str = 1; + } + else + str = string2; + else + str = string1; + + rval = re_search_stub (bufp, str, len, start, range, stop, regs, + ret_len); + if (free_str) + re_free ((char *) str); + return rval; +} + +/* The parameters have the same meaning as those of re_search. + Additional parameters: + If RET_LEN is nonzero the length of the match is returned (re_match style); + otherwise the position of the match is returned. */ + +static int internal_function +re_search_stub (struct re_pattern_buffer *bufp, const char *string, int length, + int start, int range, int stop, struct re_registers *regs, + int ret_len) +{ + reg_errcode_t result; + regmatch_t *pmatch; + int nregs, rval; + int eflags = 0; +#ifdef __UCLIBC_HAS_THREADS__ + re_dfa_t *dfa = (re_dfa_t *) bufp->buffer; +#endif + /* Check for out-of-range. */ + if (BE (start < 0 || start > length, 0)) + return -1; + if (BE (start + range > length, 0)) + range = length - start; + else if (BE (start + range < 0, 0)) + range = -start; + + __libc_lock_lock (dfa->lock); + + eflags |= (bufp->not_bol) ? REG_NOTBOL : 0; + eflags |= (bufp->not_eol) ? REG_NOTEOL : 0; + + /* Compile fastmap if we haven't yet. */ + if (range > 0 && bufp->fastmap != NULL && !bufp->fastmap_accurate) + re_compile_fastmap (bufp); + + if (BE (bufp->no_sub, 0)) + regs = NULL; + + /* We need at least 1 register. */ + if (regs == NULL) + nregs = 1; + else if (BE (bufp->regs_allocated == REGS_FIXED && + regs->num_regs < bufp->re_nsub + 1, 0)) + { + nregs = regs->num_regs; + if (BE (nregs < 1, 0)) + { + /* Nothing can be copied to regs. */ + regs = NULL; + nregs = 1; + } + } + else + nregs = bufp->re_nsub + 1; + pmatch = re_malloc (regmatch_t, nregs); + if (BE (pmatch == NULL, 0)) + { + rval = -2; + goto out; + } + + result = re_search_internal (bufp, string, length, start, range, stop, + nregs, pmatch, eflags); + + rval = 0; + + /* I hope we needn't fill ther regs with -1's when no match was found. */ + if (result != REG_NOERROR) + rval = -1; + else if (regs != NULL) + { + /* If caller wants register contents data back, copy them. */ + bufp->regs_allocated = re_copy_regs (regs, pmatch, nregs, + bufp->regs_allocated); + if (BE (bufp->regs_allocated == REGS_UNALLOCATED, 0)) + rval = -2; + } + + if (BE (rval == 0, 1)) + { + if (ret_len) + { + assert (pmatch[0].rm_so == start); + rval = pmatch[0].rm_eo - start; + } + else + rval = pmatch[0].rm_so; + } + re_free (pmatch); + out: + __libc_lock_unlock (dfa->lock); + return rval; +} + +static unsigned internal_function +re_copy_regs (struct re_registers *regs, regmatch_t *pmatch, int nregs, + int regs_allocated) +{ + int rval = REGS_REALLOCATE; + int i; + int need_regs = nregs + 1; + /* We need one extra element beyond `num_regs' for the `-1' marker GNU code + uses. */ + + /* Have the register data arrays been allocated? */ + if (regs_allocated == REGS_UNALLOCATED) + { /* No. So allocate them with malloc. */ + regs->start = re_malloc (regoff_t, need_regs); + regs->end = re_malloc (regoff_t, need_regs); + if (BE (regs->start == NULL, 0) || BE (regs->end == NULL, 0)) + return REGS_UNALLOCATED; + regs->num_regs = need_regs; + } + else if (regs_allocated == REGS_REALLOCATE) + { /* Yes. If we need more elements than were already + allocated, reallocate them. If we need fewer, just + leave it alone. */ + if (BE (need_regs > regs->num_regs, 0)) + { + regoff_t *new_start = re_realloc (regs->start, regoff_t, need_regs); + regoff_t *new_end = re_realloc (regs->end, regoff_t, need_regs); + if (BE (new_start == NULL, 0) || BE (new_end == NULL, 0)) + return REGS_UNALLOCATED; + regs->start = new_start; + regs->end = new_end; + regs->num_regs = need_regs; + } + } + else + { + assert (regs_allocated == REGS_FIXED); + /* This function may not be called with REGS_FIXED and nregs too big. */ + assert (regs->num_regs >= nregs); + rval = REGS_FIXED; + } + + /* Copy the regs. */ + for (i = 0; i < nregs; ++i) + { + regs->start[i] = pmatch[i].rm_so; + regs->end[i] = pmatch[i].rm_eo; + } + for ( ; i < regs->num_regs; ++i) + regs->start[i] = regs->end[i] = -1; + + return rval; +} + +/* Set REGS to hold NUM_REGS registers, storing them in STARTS and + ENDS. Subsequent matches using PATTERN_BUFFER and REGS will use + this memory for recording register information. STARTS and ENDS + must be allocated using the malloc library routine, and must each + be at least NUM_REGS * sizeof (regoff_t) bytes long. + + If NUM_REGS == 0, then subsequent matches should allocate their own + register data. + + Unless this function is called, the first search or match using + PATTERN_BUFFER will allocate its own register data, without + freeing the old data. */ + +void +re_set_registers (struct re_pattern_buffer *bufp, struct re_registers *regs, + unsigned num_regs, regoff_t *starts, regoff_t *ends) +{ + if (num_regs) + { + bufp->regs_allocated = REGS_REALLOCATE; + regs->num_regs = num_regs; + regs->start = starts; + regs->end = ends; + } + else + { + bufp->regs_allocated = REGS_UNALLOCATED; + regs->num_regs = 0; + regs->start = regs->end = (regoff_t *) 0; + } +} + +/* Entry points compatible with 4.2 BSD regex library. We don't define + them unless specifically requested. */ + +#if defined _REGEX_RE_COMP || defined __UCLIBC__ +int +weak_function +re_exec (const char *s) +{ + return 0 == regexec (re_comp_buf, s, 0, NULL, 0); +} +#endif + +/* Internal entry point. */ + +/* Searches for a compiled pattern PREG in the string STRING, whose + length is LENGTH. NMATCH, PMATCH, and EFLAGS have the same + mingings with regexec. START, and RANGE have the same meanings + with re_search. + Return REG_NOERROR if we find a match, and REG_NOMATCH if not, + otherwise return the error code. + Note: We assume front end functions already check ranges. + (START + RANGE >= 0 && START + RANGE <= LENGTH) */ +static reg_errcode_t internal_function +re_search_internal (const regex_t *preg, const char *string, int length, + int start, int range, int stop, size_t nmatch, + regmatch_t pmatch[], int eflags) +{ + reg_errcode_t err; + const re_dfa_t *dfa = (const re_dfa_t *) preg->buffer; + int left_lim, right_lim, incr; + int fl_longest_match, match_first, match_kind, match_last = -1; + int extra_nmatch; + int sb, ch; + re_match_context_t mctx; + char *fastmap = (preg->fastmap != NULL && preg->fastmap_accurate + && range && !preg->can_be_null) ? preg->fastmap : NULL; + RE_TRANSLATE_TYPE t = preg->translate; + + memset (&mctx, '\0', sizeof (re_match_context_t)); + mctx.dfa = dfa; + + extra_nmatch = (nmatch > preg->re_nsub) ? nmatch - (preg->re_nsub + 1) : 0; + nmatch -= extra_nmatch; + + /* Check if the DFA haven't been compiled. */ + if (BE (preg->used == 0 || dfa->init_state == NULL + || dfa->init_state_word == NULL || dfa->init_state_nl == NULL + || dfa->init_state_begbuf == NULL, 0)) + return REG_NOMATCH; + +#ifdef DEBUG + /* We assume front-end functions already check them. */ + assert (start + range >= 0 && start + range <= length); +#endif + + /* If initial states with non-begbuf contexts have no elements, + the regex must be anchored. If preg->newline_anchor is set, + we'll never use init_state_nl, so do not check it. */ + if (dfa->init_state->nodes.nelem == 0 + && dfa->init_state_word->nodes.nelem == 0 + && (dfa->init_state_nl->nodes.nelem == 0 + || !preg->newline_anchor)) + { + if (start != 0 && start + range != 0) + return REG_NOMATCH; + start = range = 0; + } + + /* We must check the longest matching, if nmatch > 0. */ + fl_longest_match = (nmatch != 0 || dfa->nbackref); + + err = re_string_allocate (&mctx.input, string, length, dfa->nodes_len + 1, + preg->translate, preg->syntax & RE_ICASE, dfa); + if (BE (err != REG_NOERROR, 0)) + goto free_return; + mctx.input.stop = stop; + mctx.input.raw_stop = stop; + mctx.input.newline_anchor = preg->newline_anchor; + + err = match_ctx_init (&mctx, eflags, dfa->nbackref * 2); + if (BE (err != REG_NOERROR, 0)) + goto free_return; + + /* We will log all the DFA states through which the dfa pass, + if nmatch > 1, or this dfa has "multibyte node", which is a + back-reference or a node which can accept multibyte character or + multi character collating element. */ + if (nmatch > 1 || dfa->has_mb_node) + { + mctx.state_log = re_malloc (re_dfastate_t *, mctx.input.bufs_len + 1); + if (BE (mctx.state_log == NULL, 0)) + { + err = REG_ESPACE; + goto free_return; + } + } + else + mctx.state_log = NULL; + + match_first = start; + mctx.input.tip_context = (eflags & REG_NOTBOL) ? CONTEXT_BEGBUF + : CONTEXT_NEWLINE | CONTEXT_BEGBUF; + + /* Check incrementally whether of not the input string match. */ + incr = (range < 0) ? -1 : 1; + left_lim = (range < 0) ? start + range : start; + right_lim = (range < 0) ? start : start + range; + sb = dfa->mb_cur_max == 1; + match_kind = + (fastmap + ? ((sb || !(preg->syntax & RE_ICASE || t) ? 4 : 0) + | (range >= 0 ? 2 : 0) + | (t != NULL ? 1 : 0)) + : 8); + + for (;; match_first += incr) + { + err = REG_NOMATCH; + if (match_first < left_lim || right_lim < match_first) + goto free_return; + + /* Advance as rapidly as possible through the string, until we + find a plausible place to start matching. This may be done + with varying efficiency, so there are various possibilities: + only the most common of them are specialized, in order to + save on code size. We use a switch statement for speed. */ + switch (match_kind) + { + case 8: + /* No fastmap. */ + break; + + case 7: + /* Fastmap with single-byte translation, match forward. */ + while (BE (match_first < right_lim, 1) + && !fastmap[t[(unsigned char) string[match_first]]]) + ++match_first; + goto forward_match_found_start_or_reached_end; + + case 6: + /* Fastmap without translation, match forward. */ + while (BE (match_first < right_lim, 1) + && !fastmap[(unsigned char) string[match_first]]) + ++match_first; + + forward_match_found_start_or_reached_end: + if (BE (match_first == right_lim, 0)) + { + ch = match_first >= length + ? 0 : (unsigned char) string[match_first]; + if (!fastmap[t ? t[ch] : ch]) + goto free_return; + } + break; + + case 4: + case 5: + /* Fastmap without multi-byte translation, match backwards. */ + while (match_first >= left_lim) + { + ch = match_first >= length + ? 0 : (unsigned char) string[match_first]; + if (fastmap[t ? t[ch] : ch]) + break; + --match_first; + } + if (match_first < left_lim) + goto free_return; + break; + + default: + /* In this case, we can't determine easily the current byte, + since it might be a component byte of a multibyte + character. Then we use the constructed buffer instead. */ + for (;;) + { + /* If MATCH_FIRST is out of the valid range, reconstruct the + buffers. */ + unsigned int offset = match_first - mctx.input.raw_mbs_idx; + if (BE (offset >= (unsigned int) mctx.input.valid_raw_len, 0)) + { + err = re_string_reconstruct (&mctx.input, match_first, + eflags); + if (BE (err != REG_NOERROR, 0)) + goto free_return; + + offset = match_first - mctx.input.raw_mbs_idx; + } + /* If MATCH_FIRST is out of the buffer, leave it as '\0'. + Note that MATCH_FIRST must not be smaller than 0. */ + ch = (match_first >= length + ? 0 : re_string_byte_at (&mctx.input, offset)); + if (fastmap[ch]) + break; + match_first += incr; + if (match_first < left_lim || match_first > right_lim) + { + err = REG_NOMATCH; + goto free_return; + } + } + break; + } + + /* Reconstruct the buffers so that the matcher can assume that + the matching starts from the beginning of the buffer. */ + err = re_string_reconstruct (&mctx.input, match_first, eflags); + if (BE (err != REG_NOERROR, 0)) + goto free_return; + +#ifdef RE_ENABLE_I18N + /* Don't consider this char as a possible match start if it part, + yet isn't the head, of a multibyte character. */ + if (!sb && !re_string_first_byte (&mctx.input, 0)) + continue; +#endif + + /* It seems to be appropriate one, then use the matcher. */ + /* We assume that the matching starts from 0. */ + mctx.state_log_top = mctx.nbkref_ents = mctx.max_mb_elem_len = 0; + match_last = check_matching (&mctx, fl_longest_match, + range >= 0 ? &match_first : NULL); + if (match_last != -1) + { + if (BE (match_last == -2, 0)) + { + err = REG_ESPACE; + goto free_return; + } + else + { + mctx.match_last = match_last; + if ((!preg->no_sub && nmatch > 1) || dfa->nbackref) + { + re_dfastate_t *pstate = mctx.state_log[match_last]; + mctx.last_node = check_halt_state_context (&mctx, pstate, + match_last); + } + if ((!preg->no_sub && nmatch > 1 && dfa->has_plural_match) + || dfa->nbackref) + { + err = prune_impossible_nodes (&mctx); + if (err == REG_NOERROR) + break; + if (BE (err != REG_NOMATCH, 0)) + goto free_return; + match_last = -1; + } + else + break; /* We found a match. */ + } + } + + match_ctx_clean (&mctx); + } + +#ifdef DEBUG + assert (match_last != -1); + assert (err == REG_NOERROR); +#endif + + /* Set pmatch[] if we need. */ + if (nmatch > 0) + { + int reg_idx; + + /* Initialize registers. */ + for (reg_idx = 1; reg_idx < nmatch; ++reg_idx) + pmatch[reg_idx].rm_so = pmatch[reg_idx].rm_eo = -1; + + /* Set the points where matching start/end. */ + pmatch[0].rm_so = 0; + pmatch[0].rm_eo = mctx.match_last; + + if (!preg->no_sub && nmatch > 1) + { + err = set_regs (preg, &mctx, nmatch, pmatch, + dfa->has_plural_match && dfa->nbackref > 0); + if (BE (err != REG_NOERROR, 0)) + goto free_return; + } + + /* At last, add the offset to the each registers, since we slided + the buffers so that we could assume that the matching starts + from 0. */ + for (reg_idx = 0; reg_idx < nmatch; ++reg_idx) + if (pmatch[reg_idx].rm_so != -1) + { +#ifdef RE_ENABLE_I18N + if (BE (mctx.input.offsets_needed != 0, 0)) + { + pmatch[reg_idx].rm_so = + (pmatch[reg_idx].rm_so == mctx.input.valid_len + ? mctx.input.valid_raw_len + : mctx.input.offsets[pmatch[reg_idx].rm_so]); + pmatch[reg_idx].rm_eo = + (pmatch[reg_idx].rm_eo == mctx.input.valid_len + ? mctx.input.valid_raw_len + : mctx.input.offsets[pmatch[reg_idx].rm_eo]); + } +#else + assert (mctx.input.offsets_needed == 0); +#endif + pmatch[reg_idx].rm_so += match_first; + pmatch[reg_idx].rm_eo += match_first; + } + for (reg_idx = 0; reg_idx < extra_nmatch; ++reg_idx) + { + pmatch[nmatch + reg_idx].rm_so = -1; + pmatch[nmatch + reg_idx].rm_eo = -1; + } + + if (dfa->subexp_map) + for (reg_idx = 0; reg_idx + 1 < nmatch; reg_idx++) + if (dfa->subexp_map[reg_idx] != reg_idx) + { + pmatch[reg_idx + 1].rm_so + = pmatch[dfa->subexp_map[reg_idx] + 1].rm_so; + pmatch[reg_idx + 1].rm_eo + = pmatch[dfa->subexp_map[reg_idx] + 1].rm_eo; + } + } + + free_return: + re_free (mctx.state_log); + if (dfa->nbackref) + match_ctx_free (&mctx); + re_string_destruct (&mctx.input); + return err; +} + +static reg_errcode_t internal_function +prune_impossible_nodes (re_match_context_t *mctx) +{ + const re_dfa_t *const dfa = mctx->dfa; + int halt_node, match_last; + reg_errcode_t ret; + re_dfastate_t **sifted_states; + re_dfastate_t **lim_states = NULL; + re_sift_context_t sctx; +#ifdef DEBUG + assert (mctx->state_log != NULL); +#endif + match_last = mctx->match_last; + halt_node = mctx->last_node; + sifted_states = re_malloc (re_dfastate_t *, match_last + 1); + if (BE (sifted_states == NULL, 0)) + { + ret = REG_ESPACE; + goto free_return; + } + if (dfa->nbackref) + { + lim_states = re_malloc (re_dfastate_t *, match_last + 1); + if (BE (lim_states == NULL, 0)) + { + ret = REG_ESPACE; + goto free_return; + } + while (1) + { + memset (lim_states, '\0', + sizeof (re_dfastate_t *) * (match_last + 1)); + sift_ctx_init (&sctx, sifted_states, lim_states, halt_node, + match_last); + ret = sift_states_backward (mctx, &sctx); + re_node_set_free (&sctx.limits); + if (BE (ret != REG_NOERROR, 0)) + goto free_return; + if (sifted_states[0] != NULL || lim_states[0] != NULL) + break; + do + { + --match_last; + if (match_last < 0) + { + ret = REG_NOMATCH; + goto free_return; + } + } while (mctx->state_log[match_last] == NULL + || !mctx->state_log[match_last]->halt); + halt_node = check_halt_state_context (mctx, + mctx->state_log[match_last], + match_last); + } + ret = merge_state_array (dfa, sifted_states, lim_states, + match_last + 1); + re_free (lim_states); + lim_states = NULL; + if (BE (ret != REG_NOERROR, 0)) + goto free_return; + } + else + { + sift_ctx_init (&sctx, sifted_states, lim_states, halt_node, match_last); + ret = sift_states_backward (mctx, &sctx); + re_node_set_free (&sctx.limits); + if (BE (ret != REG_NOERROR, 0)) + goto free_return; + } + re_free (mctx->state_log); + mctx->state_log = sifted_states; + sifted_states = NULL; + mctx->last_node = halt_node; + mctx->match_last = match_last; + ret = REG_NOERROR; + free_return: + re_free (sifted_states); + re_free (lim_states); + return ret; +} + +/* Acquire an initial state and return it. + We must select appropriate initial state depending on the context, + since initial states may have constraints like "\<", "^", etc.. */ + +static __inline__ re_dfastate_t * +__attribute ((always_inline)) internal_function +acquire_init_state_context (reg_errcode_t *err, const re_match_context_t *mctx, + int idx) +{ + const re_dfa_t *const dfa = mctx->dfa; + if (dfa->init_state->has_constraint) + { + unsigned int context; + context = re_string_context_at (&mctx->input, idx - 1, mctx->eflags); + if (IS_WORD_CONTEXT (context)) + return dfa->init_state_word; + else if (IS_ORDINARY_CONTEXT (context)) + return dfa->init_state; + else if (IS_BEGBUF_CONTEXT (context) && IS_NEWLINE_CONTEXT (context)) + return dfa->init_state_begbuf; + else if (IS_NEWLINE_CONTEXT (context)) + return dfa->init_state_nl; + else if (IS_BEGBUF_CONTEXT (context)) + { + /* It is relatively rare case, then calculate on demand. */ + return re_acquire_state_context (err, dfa, + dfa->init_state->entrance_nodes, + context); + } + else + /* Must not happen? */ + return dfa->init_state; + } + else + return dfa->init_state; +} + +/* Check whether the regular expression match input string INPUT or not, + and return the index where the matching end, return -1 if not match, + or return -2 in case of an error. + FL_LONGEST_MATCH means we want the POSIX longest matching. + If P_MATCH_FIRST is not NULL, and the match fails, it is set to the + next place where we may want to try matching. + Note that the matcher assume that the maching starts from the current + index of the buffer. */ + +static int +internal_function +check_matching (re_match_context_t *mctx, int fl_longest_match, + int *p_match_first) +{ + const re_dfa_t *const dfa = mctx->dfa; + reg_errcode_t err; + int match = 0; + int match_last = -1; + int cur_str_idx = re_string_cur_idx (&mctx->input); + re_dfastate_t *cur_state; + int at_init_state = p_match_first != NULL; + int next_start_idx = cur_str_idx; + + err = REG_NOERROR; + cur_state = acquire_init_state_context (&err, mctx, cur_str_idx); + /* An initial state must not be NULL (invalid). */ + if (BE (cur_state == NULL, 0)) + { + assert (err == REG_ESPACE); + return -2; + } + + if (mctx->state_log != NULL) + { + mctx->state_log[cur_str_idx] = cur_state; + + /* Check OP_OPEN_SUBEXP in the initial state in case that we use them + later. E.g. Processing back references. */ + if (BE (dfa->nbackref, 0)) + { + at_init_state = 0; + err = check_subexp_matching_top (mctx, &cur_state->nodes, 0); + if (BE (err != REG_NOERROR, 0)) + return err; + + if (cur_state->has_backref) + { + err = transit_state_bkref (mctx, &cur_state->nodes); + if (BE (err != REG_NOERROR, 0)) + return err; + } + } + } + + /* If the RE accepts NULL string. */ + if (BE (cur_state->halt, 0)) + { + if (!cur_state->has_constraint + || check_halt_state_context (mctx, cur_state, cur_str_idx)) + { + if (!fl_longest_match) + return cur_str_idx; + else + { + match_last = cur_str_idx; + match = 1; + } + } + } + + while (!re_string_eoi (&mctx->input)) + { + re_dfastate_t *old_state = cur_state; + int next_char_idx = re_string_cur_idx (&mctx->input) + 1; + + if (BE (next_char_idx >= mctx->input.bufs_len, 0) + || (BE (next_char_idx >= mctx->input.valid_len, 0) + && mctx->input.valid_len < mctx->input.len)) + { + err = extend_buffers (mctx); + if (BE (err != REG_NOERROR, 0)) + { + assert (err == REG_ESPACE); + return -2; + } + } + + cur_state = transit_state (&err, mctx, cur_state); + if (mctx->state_log != NULL) + cur_state = merge_state_with_log (&err, mctx, cur_state); + + if (cur_state == NULL) + { + /* Reached the invalid state or an error. Try to recover a valid + state using the state log, if available and if we have not + already found a valid (even if not the longest) match. */ + if (BE (err != REG_NOERROR, 0)) + return -2; + + if (mctx->state_log == NULL + || (match && !fl_longest_match) + || (cur_state = find_recover_state (&err, mctx)) == NULL) + break; + } + + if (BE (at_init_state, 0)) + { + if (old_state == cur_state) + next_start_idx = next_char_idx; + else + at_init_state = 0; + } + + if (cur_state->halt) + { + /* Reached a halt state. + Check the halt state can satisfy the current context. */ + if (!cur_state->has_constraint + || check_halt_state_context (mctx, cur_state, + re_string_cur_idx (&mctx->input))) + { + /* We found an appropriate halt state. */ + match_last = re_string_cur_idx (&mctx->input); + match = 1; + + /* We found a match, do not modify match_first below. */ + p_match_first = NULL; + if (!fl_longest_match) + break; + } + } + } + + if (p_match_first) + *p_match_first += next_start_idx; + + return match_last; +} + +/* Check NODE match the current context. */ + +static int +internal_function +check_halt_node_context (const re_dfa_t *dfa, int node, unsigned int context) +{ + re_token_type_t type = dfa->nodes[node].type; + unsigned int constraint = dfa->nodes[node].constraint; + if (type != END_OF_RE) + return 0; + if (!constraint) + return 1; + if (NOT_SATISFY_NEXT_CONSTRAINT (constraint, context)) + return 0; + return 1; +} + +/* Check the halt state STATE match the current context. + Return 0 if not match, if the node, STATE has, is a halt node and + match the context, return the node. */ + +static int +internal_function +check_halt_state_context (const re_match_context_t *mctx, + const re_dfastate_t *state, int idx) +{ + int i; + unsigned int context; +#ifdef DEBUG + assert (state->halt); +#endif + context = re_string_context_at (&mctx->input, idx, mctx->eflags); + for (i = 0; i < state->nodes.nelem; ++i) + if (check_halt_node_context (mctx->dfa, state->nodes.elems[i], context)) + return state->nodes.elems[i]; + return 0; +} + +/* Compute the next node to which "NFA" transit from NODE("NFA" is a NFA + corresponding to the DFA). + Return the destination node, and update EPS_VIA_NODES, return -1 in case + of errors. */ + +static int +internal_function +proceed_next_node (const re_match_context_t *mctx, int nregs, regmatch_t *regs, + int *pidx, int node, re_node_set *eps_via_nodes, + struct re_fail_stack_t *fs) +{ + const re_dfa_t *const dfa = mctx->dfa; + int i, err; + if (IS_EPSILON_NODE (dfa->nodes[node].type)) + { + re_node_set *cur_nodes = &mctx->state_log[*pidx]->nodes; + re_node_set *edests = &dfa->edests[node]; + int dest_node; + err = re_node_set_insert (eps_via_nodes, node); + if (BE (err < 0, 0)) + return -2; + /* Pick up a valid destination, or return -1 if none is found. */ + for (dest_node = -1, i = 0; i < edests->nelem; ++i) + { + int candidate = edests->elems[i]; + if (!re_node_set_contains (cur_nodes, candidate)) + continue; + if (dest_node == -1) + dest_node = candidate; + + else + { + /* In order to avoid infinite loop like "(a*)*", return the second + epsilon-transition if the first was already considered. */ + if (re_node_set_contains (eps_via_nodes, dest_node)) + return candidate; + + /* Otherwise, push the second epsilon-transition on the fail stack. */ + else if (fs != NULL + && push_fail_stack (fs, *pidx, candidate, nregs, regs, + eps_via_nodes)) + return -2; + + /* We know we are going to exit. */ + break; + } + } + return dest_node; + } + else + { + int naccepted = 0; + re_token_type_t type = dfa->nodes[node].type; + +#ifdef RE_ENABLE_I18N + if (dfa->nodes[node].accept_mb) + naccepted = check_node_accept_bytes (dfa, node, &mctx->input, *pidx); + else +#endif /* RE_ENABLE_I18N */ + if (type == OP_BACK_REF) + { + int subexp_idx = dfa->nodes[node].opr.idx + 1; + naccepted = regs[subexp_idx].rm_eo - regs[subexp_idx].rm_so; + if (fs != NULL) + { + if (regs[subexp_idx].rm_so == -1 || regs[subexp_idx].rm_eo == -1) + return -1; + else if (naccepted) + { + char *buf = (char *) re_string_get_buffer (&mctx->input); + if (memcmp (buf + regs[subexp_idx].rm_so, buf + *pidx, + naccepted) != 0) + return -1; + } + } + + if (naccepted == 0) + { + int dest_node; + err = re_node_set_insert (eps_via_nodes, node); + if (BE (err < 0, 0)) + return -2; + dest_node = dfa->edests[node].elems[0]; + if (re_node_set_contains (&mctx->state_log[*pidx]->nodes, + dest_node)) + return dest_node; + } + } + + if (naccepted != 0 + || check_node_accept (mctx, dfa->nodes + node, *pidx)) + { + int dest_node = dfa->nexts[node]; + *pidx = (naccepted == 0) ? *pidx + 1 : *pidx + naccepted; + if (fs && (*pidx > mctx->match_last || mctx->state_log[*pidx] == NULL + || !re_node_set_contains (&mctx->state_log[*pidx]->nodes, + dest_node))) + return -1; + re_node_set_empty (eps_via_nodes); + return dest_node; + } + } + return -1; +} + +static reg_errcode_t +internal_function +push_fail_stack (struct re_fail_stack_t *fs, int str_idx, int dest_node, + int nregs, regmatch_t *regs, re_node_set *eps_via_nodes) +{ + reg_errcode_t err; + int num = fs->num++; + if (fs->num == fs->alloc) + { + struct re_fail_stack_ent_t *new_array; + new_array = realloc (fs->stack, (sizeof (struct re_fail_stack_ent_t) + * fs->alloc * 2)); + if (new_array == NULL) + return REG_ESPACE; + fs->alloc *= 2; + fs->stack = new_array; + } + fs->stack[num].idx = str_idx; + fs->stack[num].node = dest_node; + fs->stack[num].regs = re_malloc (regmatch_t, nregs); + if (fs->stack[num].regs == NULL) + return REG_ESPACE; + memcpy (fs->stack[num].regs, regs, sizeof (regmatch_t) * nregs); + err = re_node_set_init_copy (&fs->stack[num].eps_via_nodes, eps_via_nodes); + return err; +} + +static int +internal_function +pop_fail_stack (struct re_fail_stack_t *fs, int *pidx, int nregs, + regmatch_t *regs, re_node_set *eps_via_nodes) +{ + int num = --fs->num; + assert (num >= 0); + *pidx = fs->stack[num].idx; + memcpy (regs, fs->stack[num].regs, sizeof (regmatch_t) * nregs); + re_node_set_free (eps_via_nodes); + re_free (fs->stack[num].regs); + *eps_via_nodes = fs->stack[num].eps_via_nodes; + return fs->stack[num].node; +} + +/* Set the positions where the subexpressions are starts/ends to registers + PMATCH. + Note: We assume that pmatch[0] is already set, and + pmatch[i].rm_so == pmatch[i].rm_eo == -1 for 0 < i < nmatch. */ + +static reg_errcode_t +internal_function +set_regs (const regex_t *preg, const re_match_context_t *mctx, size_t nmatch, + regmatch_t *pmatch, int fl_backtrack) +{ + const re_dfa_t *dfa = (const re_dfa_t *) preg->buffer; + int idx, cur_node; + re_node_set eps_via_nodes; + struct re_fail_stack_t *fs; + struct re_fail_stack_t fs_body = { 0, 2, NULL }; + regmatch_t *prev_idx_match; + int prev_idx_match_malloced = 0; + +#ifdef DEBUG + assert (nmatch > 1); + assert (mctx->state_log != NULL); +#endif + if (fl_backtrack) + { + fs = &fs_body; + fs->stack = re_malloc (struct re_fail_stack_ent_t, fs->alloc); + if (fs->stack == NULL) + return REG_ESPACE; + } + else + fs = NULL; + + cur_node = dfa->init_node; + re_node_set_init_empty (&eps_via_nodes); + + if (__libc_use_alloca (nmatch * sizeof (regmatch_t))) + prev_idx_match = (regmatch_t *) alloca (nmatch * sizeof (regmatch_t)); + else + { + prev_idx_match = re_malloc (regmatch_t, nmatch); + if (prev_idx_match == NULL) + { + free_fail_stack_return (fs); + return REG_ESPACE; + } + prev_idx_match_malloced = 1; + } + memcpy (prev_idx_match, pmatch, sizeof (regmatch_t) * nmatch); + + for (idx = pmatch[0].rm_so; idx <= pmatch[0].rm_eo ;) + { + update_regs (dfa, pmatch, prev_idx_match, cur_node, idx, nmatch); + + if (idx == pmatch[0].rm_eo && cur_node == mctx->last_node) + { + int reg_idx; + if (fs) + { + for (reg_idx = 0; reg_idx < nmatch; ++reg_idx) + if (pmatch[reg_idx].rm_so > -1 && pmatch[reg_idx].rm_eo == -1) + break; + if (reg_idx == nmatch) + { + re_node_set_free (&eps_via_nodes); + if (prev_idx_match_malloced) + re_free (prev_idx_match); + return free_fail_stack_return (fs); + } + cur_node = pop_fail_stack (fs, &idx, nmatch, pmatch, + &eps_via_nodes); + } + else + { + re_node_set_free (&eps_via_nodes); + if (prev_idx_match_malloced) + re_free (prev_idx_match); + return REG_NOERROR; + } + } + + /* Proceed to next node. */ + cur_node = proceed_next_node (mctx, nmatch, pmatch, &idx, cur_node, + &eps_via_nodes, fs); + + if (BE (cur_node < 0, 0)) + { + if (BE (cur_node == -2, 0)) + { + re_node_set_free (&eps_via_nodes); + if (prev_idx_match_malloced) + re_free (prev_idx_match); + free_fail_stack_return (fs); + return REG_ESPACE; + } + if (fs) + cur_node = pop_fail_stack (fs, &idx, nmatch, pmatch, + &eps_via_nodes); + else + { + re_node_set_free (&eps_via_nodes); + if (prev_idx_match_malloced) + re_free (prev_idx_match); + return REG_NOMATCH; + } + } + } + re_node_set_free (&eps_via_nodes); + if (prev_idx_match_malloced) + re_free (prev_idx_match); + return free_fail_stack_return (fs); +} + +static reg_errcode_t +internal_function +free_fail_stack_return (struct re_fail_stack_t *fs) +{ + if (fs) + { + int fs_idx; + for (fs_idx = 0; fs_idx < fs->num; ++fs_idx) + { + re_node_set_free (&fs->stack[fs_idx].eps_via_nodes); + re_free (fs->stack[fs_idx].regs); + } + re_free (fs->stack); + } + return REG_NOERROR; +} + +static void +internal_function +update_regs (const re_dfa_t *dfa, regmatch_t *pmatch, + regmatch_t *prev_idx_match, int cur_node, int cur_idx, int nmatch) +{ + int type = dfa->nodes[cur_node].type; + if (type == OP_OPEN_SUBEXP) + { + int reg_num = dfa->nodes[cur_node].opr.idx + 1; + + /* We are at the first node of this sub expression. */ + if (reg_num < nmatch) + { + pmatch[reg_num].rm_so = cur_idx; + pmatch[reg_num].rm_eo = -1; + } + } + else if (type == OP_CLOSE_SUBEXP) + { + int reg_num = dfa->nodes[cur_node].opr.idx + 1; + if (reg_num < nmatch) + { + /* We are at the last node of this sub expression. */ + if (pmatch[reg_num].rm_so < cur_idx) + { + pmatch[reg_num].rm_eo = cur_idx; + /* This is a non-empty match or we are not inside an optional + subexpression. Accept this right away. */ + memcpy (prev_idx_match, pmatch, sizeof (regmatch_t) * nmatch); + } + else + { + if (dfa->nodes[cur_node].opt_subexp + && prev_idx_match[reg_num].rm_so != -1) + /* We transited through an empty match for an optional + subexpression, like (a?)*, and this is not the subexp's + first match. Copy back the old content of the registers + so that matches of an inner subexpression are undone as + well, like in ((a?))*. */ + memcpy (pmatch, prev_idx_match, sizeof (regmatch_t) * nmatch); + else + /* We completed a subexpression, but it may be part of + an optional one, so do not update PREV_IDX_MATCH. */ + pmatch[reg_num].rm_eo = cur_idx; + } + } + } +} + +/* This function checks the STATE_LOG from the SCTX->last_str_idx to 0 + and sift the nodes in each states according to the following rules. + Updated state_log will be wrote to STATE_LOG. + + Rules: We throw away the Node `a' in the STATE_LOG[STR_IDX] if... + 1. When STR_IDX == MATCH_LAST(the last index in the state_log): + If `a' isn't the LAST_NODE and `a' can't epsilon transit to + the LAST_NODE, we throw away the node `a'. + 2. When 0 <= STR_IDX < MATCH_LAST and `a' accepts + string `s' and transit to `b': + i. If 'b' isn't in the STATE_LOG[STR_IDX+strlen('s')], we throw + away the node `a'. + ii. If 'b' is in the STATE_LOG[STR_IDX+strlen('s')] but 'b' is + thrown away, we throw away the node `a'. + 3. When 0 <= STR_IDX < MATCH_LAST and 'a' epsilon transit to 'b': + i. If 'b' isn't in the STATE_LOG[STR_IDX], we throw away the + node `a'. + ii. If 'b' is in the STATE_LOG[STR_IDX] but 'b' is thrown away, + we throw away the node `a'. */ + +#define STATE_NODE_CONTAINS(state,node) \ + ((state) != NULL && re_node_set_contains (&(state)->nodes, node)) + +static reg_errcode_t +internal_function +sift_states_backward (const re_match_context_t *mctx, re_sift_context_t *sctx) +{ + reg_errcode_t err; + int null_cnt = 0; + int str_idx = sctx->last_str_idx; + re_node_set cur_dest; + +#ifdef DEBUG + assert (mctx->state_log != NULL && mctx->state_log[str_idx] != NULL); +#endif + + /* Build sifted state_log[str_idx]. It has the nodes which can epsilon + transit to the last_node and the last_node itself. */ + err = re_node_set_init_1 (&cur_dest, sctx->last_node); + if (BE (err != REG_NOERROR, 0)) + return err; + err = update_cur_sifted_state (mctx, sctx, str_idx, &cur_dest); + if (BE (err != REG_NOERROR, 0)) + goto free_return; + + /* Then check each states in the state_log. */ + while (str_idx > 0) + { + /* Update counters. */ + null_cnt = (sctx->sifted_states[str_idx] == NULL) ? null_cnt + 1 : 0; + if (null_cnt > mctx->max_mb_elem_len) + { + memset (sctx->sifted_states, '\0', + sizeof (re_dfastate_t *) * str_idx); + re_node_set_free (&cur_dest); + return REG_NOERROR; + } + re_node_set_empty (&cur_dest); + --str_idx; + + if (mctx->state_log[str_idx]) + { + err = build_sifted_states (mctx, sctx, str_idx, &cur_dest); + if (BE (err != REG_NOERROR, 0)) + goto free_return; + } + + /* Add all the nodes which satisfy the following conditions: + - It can epsilon transit to a node in CUR_DEST. + - It is in CUR_SRC. + And update state_log. */ + err = update_cur_sifted_state (mctx, sctx, str_idx, &cur_dest); + if (BE (err != REG_NOERROR, 0)) + goto free_return; + } + err = REG_NOERROR; + free_return: + re_node_set_free (&cur_dest); + return err; +} + +static reg_errcode_t +internal_function +build_sifted_states (const re_match_context_t *mctx, re_sift_context_t *sctx, + int str_idx, re_node_set *cur_dest) +{ + const re_dfa_t *const dfa = mctx->dfa; + const re_node_set *cur_src = &mctx->state_log[str_idx]->non_eps_nodes; + int i; + + /* Then build the next sifted state. + We build the next sifted state on `cur_dest', and update + `sifted_states[str_idx]' with `cur_dest'. + Note: + `cur_dest' is the sifted state from `state_log[str_idx + 1]'. + `cur_src' points the node_set of the old `state_log[str_idx]' + (with the epsilon nodes pre-filtered out). */ + for (i = 0; i < cur_src->nelem; i++) + { + int prev_node = cur_src->elems[i]; + int naccepted = 0; + int ret; + +#ifdef DEBUG + re_token_type_t type = dfa->nodes[prev_node].type; + assert (!IS_EPSILON_NODE (type)); +#endif +#ifdef RE_ENABLE_I18N + /* If the node may accept `multi byte'. */ + if (dfa->nodes[prev_node].accept_mb) + naccepted = sift_states_iter_mb (mctx, sctx, prev_node, + str_idx, sctx->last_str_idx); +#endif /* RE_ENABLE_I18N */ + + /* We don't check backreferences here. + See update_cur_sifted_state(). */ + if (!naccepted + && check_node_accept (mctx, dfa->nodes + prev_node, str_idx) + && STATE_NODE_CONTAINS (sctx->sifted_states[str_idx + 1], + dfa->nexts[prev_node])) + naccepted = 1; + + if (naccepted == 0) + continue; + + if (sctx->limits.nelem) + { + int to_idx = str_idx + naccepted; + if (check_dst_limits (mctx, &sctx->limits, + dfa->nexts[prev_node], to_idx, + prev_node, str_idx)) + continue; + } + ret = re_node_set_insert (cur_dest, prev_node); + if (BE (ret == -1, 0)) + return REG_ESPACE; + } + + return REG_NOERROR; +} + +/* Helper functions. */ + +static reg_errcode_t +internal_function +clean_state_log_if_needed (re_match_context_t *mctx, int next_state_log_idx) +{ + int top = mctx->state_log_top; + + if (next_state_log_idx >= mctx->input.bufs_len + || (next_state_log_idx >= mctx->input.valid_len + && mctx->input.valid_len < mctx->input.len)) + { + reg_errcode_t err; + err = extend_buffers (mctx); + if (BE (err != REG_NOERROR, 0)) + return err; + } + + if (top < next_state_log_idx) + { + memset (mctx->state_log + top + 1, '\0', + sizeof (re_dfastate_t *) * (next_state_log_idx - top)); + mctx->state_log_top = next_state_log_idx; + } + return REG_NOERROR; +} + +static reg_errcode_t +internal_function +merge_state_array (const re_dfa_t *dfa, re_dfastate_t **dst, + re_dfastate_t **src, int num) +{ + int st_idx; + reg_errcode_t err; + for (st_idx = 0; st_idx < num; ++st_idx) + { + if (dst[st_idx] == NULL) + dst[st_idx] = src[st_idx]; + else if (src[st_idx] != NULL) + { + re_node_set merged_set; + err = re_node_set_init_union (&merged_set, &dst[st_idx]->nodes, + &src[st_idx]->nodes); + if (BE (err != REG_NOERROR, 0)) + return err; + dst[st_idx] = re_acquire_state (&err, dfa, &merged_set); + re_node_set_free (&merged_set); + if (BE (err != REG_NOERROR, 0)) + return err; + } + } + return REG_NOERROR; +} + +static reg_errcode_t +internal_function +update_cur_sifted_state (const re_match_context_t *mctx, + re_sift_context_t *sctx, int str_idx, + re_node_set *dest_nodes) +{ + const re_dfa_t *const dfa = mctx->dfa; + reg_errcode_t err = REG_NOERROR; + const re_node_set *candidates; + candidates = ((mctx->state_log[str_idx] == NULL) ? NULL + : &mctx->state_log[str_idx]->nodes); + + if (dest_nodes->nelem == 0) + sctx->sifted_states[str_idx] = NULL; + else + { + if (candidates) + { + /* At first, add the nodes which can epsilon transit to a node in + DEST_NODE. */ + err = add_epsilon_src_nodes (dfa, dest_nodes, candidates); + if (BE (err != REG_NOERROR, 0)) + return err; + + /* Then, check the limitations in the current sift_context. */ + if (sctx->limits.nelem) + { + err = check_subexp_limits (dfa, dest_nodes, candidates, &sctx->limits, + mctx->bkref_ents, str_idx); + if (BE (err != REG_NOERROR, 0)) + return err; + } + } + + sctx->sifted_states[str_idx] = re_acquire_state (&err, dfa, dest_nodes); + if (BE (err != REG_NOERROR, 0)) + return err; + } + + if (candidates && mctx->state_log[str_idx]->has_backref) + { + err = sift_states_bkref (mctx, sctx, str_idx, candidates); + if (BE (err != REG_NOERROR, 0)) + return err; + } + return REG_NOERROR; +} + +static reg_errcode_t +internal_function +add_epsilon_src_nodes (const re_dfa_t *dfa, re_node_set *dest_nodes, + const re_node_set *candidates) +{ + reg_errcode_t err = REG_NOERROR; + int i; + + re_dfastate_t *state = re_acquire_state (&err, dfa, dest_nodes); + if (BE (err != REG_NOERROR, 0)) + return err; + + if (!state->inveclosure.alloc) + { + err = re_node_set_alloc (&state->inveclosure, dest_nodes->nelem); + if (BE (err != REG_NOERROR, 0)) + return REG_ESPACE; + for (i = 0; i < dest_nodes->nelem; i++) + re_node_set_merge (&state->inveclosure, + dfa->inveclosures + dest_nodes->elems[i]); + } + return re_node_set_add_intersect (dest_nodes, candidates, + &state->inveclosure); +} + +static reg_errcode_t +internal_function +sub_epsilon_src_nodes (const re_dfa_t *dfa, int node, re_node_set *dest_nodes, + const re_node_set *candidates) +{ + int ecl_idx; + reg_errcode_t err; + re_node_set *inv_eclosure = dfa->inveclosures + node; + re_node_set except_nodes; + re_node_set_init_empty (&except_nodes); + for (ecl_idx = 0; ecl_idx < inv_eclosure->nelem; ++ecl_idx) + { + int cur_node = inv_eclosure->elems[ecl_idx]; + if (cur_node == node) + continue; + if (IS_EPSILON_NODE (dfa->nodes[cur_node].type)) + { + int edst1 = dfa->edests[cur_node].elems[0]; + int edst2 = ((dfa->edests[cur_node].nelem > 1) + ? dfa->edests[cur_node].elems[1] : -1); + if ((!re_node_set_contains (inv_eclosure, edst1) + && re_node_set_contains (dest_nodes, edst1)) + || (edst2 > 0 + && !re_node_set_contains (inv_eclosure, edst2) + && re_node_set_contains (dest_nodes, edst2))) + { + err = re_node_set_add_intersect (&except_nodes, candidates, + dfa->inveclosures + cur_node); + if (BE (err != REG_NOERROR, 0)) + { + re_node_set_free (&except_nodes); + return err; + } + } + } + } + for (ecl_idx = 0; ecl_idx < inv_eclosure->nelem; ++ecl_idx) + { + int cur_node = inv_eclosure->elems[ecl_idx]; + if (!re_node_set_contains (&except_nodes, cur_node)) + { + int idx = re_node_set_contains (dest_nodes, cur_node) - 1; + re_node_set_remove_at (dest_nodes, idx); + } + } + re_node_set_free (&except_nodes); + return REG_NOERROR; +} + +static int +internal_function +check_dst_limits (const re_match_context_t *mctx, re_node_set *limits, + int dst_node, int dst_idx, int src_node, int src_idx) +{ + const re_dfa_t *const dfa = mctx->dfa; + int lim_idx, src_pos, dst_pos; + + int dst_bkref_idx = search_cur_bkref_entry (mctx, dst_idx); + int src_bkref_idx = search_cur_bkref_entry (mctx, src_idx); + for (lim_idx = 0; lim_idx < limits->nelem; ++lim_idx) + { + int subexp_idx; + struct re_backref_cache_entry *ent; + ent = mctx->bkref_ents + limits->elems[lim_idx]; + subexp_idx = dfa->nodes[ent->node].opr.idx; + + dst_pos = check_dst_limits_calc_pos (mctx, limits->elems[lim_idx], + subexp_idx, dst_node, dst_idx, + dst_bkref_idx); + src_pos = check_dst_limits_calc_pos (mctx, limits->elems[lim_idx], + subexp_idx, src_node, src_idx, + src_bkref_idx); + + /* In case of: + ( ) + ( ) + ( ) */ + if (src_pos == dst_pos) + continue; /* This is unrelated limitation. */ + else + return 1; + } + return 0; +} + +static int +internal_function +check_dst_limits_calc_pos_1 (const re_match_context_t *mctx, int boundaries, + int subexp_idx, int from_node, int bkref_idx) +{ + const re_dfa_t *const dfa = mctx->dfa; + const re_node_set *eclosures = dfa->eclosures + from_node; + int node_idx; + + /* Else, we are on the boundary: examine the nodes on the epsilon + closure. */ + for (node_idx = 0; node_idx < eclosures->nelem; ++node_idx) + { + int node = eclosures->elems[node_idx]; + switch (dfa->nodes[node].type) + { + case OP_BACK_REF: + if (bkref_idx != -1) + { + struct re_backref_cache_entry *ent = mctx->bkref_ents + bkref_idx; + do + { + int dst, cpos; + + if (ent->node != node) + continue; + + if (subexp_idx < BITSET_WORD_BITS + && !(ent->eps_reachable_subexps_map + & ((bitset_word_t) 1 << subexp_idx))) + continue; + + /* Recurse trying to reach the OP_OPEN_SUBEXP and + OP_CLOSE_SUBEXP cases below. But, if the + destination node is the same node as the source + node, don't recurse because it would cause an + infinite loop: a regex that exhibits this behavior + is ()\1*\1* */ + dst = dfa->edests[node].elems[0]; + if (dst == from_node) + { + if (boundaries & 1) + return -1; + else /* if (boundaries & 2) */ + return 0; + } + + cpos = + check_dst_limits_calc_pos_1 (mctx, boundaries, subexp_idx, + dst, bkref_idx); + if (cpos == -1 /* && (boundaries & 1) */) + return -1; + if (cpos == 0 && (boundaries & 2)) + return 0; + + if (subexp_idx < BITSET_WORD_BITS) + ent->eps_reachable_subexps_map + &= ~((bitset_word_t) 1 << subexp_idx); + } + while (ent++->more); + } + break; + + case OP_OPEN_SUBEXP: + if ((boundaries & 1) && subexp_idx == dfa->nodes[node].opr.idx) + return -1; + break; + + case OP_CLOSE_SUBEXP: + if ((boundaries & 2) && subexp_idx == dfa->nodes[node].opr.idx) + return 0; + break; + + default: + break; + } + } + + return (boundaries & 2) ? 1 : 0; +} + +static int +internal_function +check_dst_limits_calc_pos (const re_match_context_t *mctx, int limit, + int subexp_idx, int from_node, int str_idx, + int bkref_idx) +{ + struct re_backref_cache_entry *lim = mctx->bkref_ents + limit; + int boundaries; + + /* If we are outside the range of the subexpression, return -1 or 1. */ + if (str_idx < lim->subexp_from) + return -1; + + if (lim->subexp_to < str_idx) + return 1; + + /* If we are within the subexpression, return 0. */ + boundaries = (str_idx == lim->subexp_from); + boundaries |= (str_idx == lim->subexp_to) << 1; + if (boundaries == 0) + return 0; + + /* Else, examine epsilon closure. */ + return check_dst_limits_calc_pos_1 (mctx, boundaries, subexp_idx, + from_node, bkref_idx); +} + +/* Check the limitations of sub expressions LIMITS, and remove the nodes + which are against limitations from DEST_NODES. */ + +static reg_errcode_t +internal_function +check_subexp_limits (const re_dfa_t *dfa, re_node_set *dest_nodes, + const re_node_set *candidates, re_node_set *limits, + struct re_backref_cache_entry *bkref_ents, int str_idx) +{ + reg_errcode_t err; + int node_idx, lim_idx; + + for (lim_idx = 0; lim_idx < limits->nelem; ++lim_idx) + { + int subexp_idx; + struct re_backref_cache_entry *ent; + ent = bkref_ents + limits->elems[lim_idx]; + + if (str_idx <= ent->subexp_from || ent->str_idx < str_idx) + continue; /* This is unrelated limitation. */ + + subexp_idx = dfa->nodes[ent->node].opr.idx; + if (ent->subexp_to == str_idx) + { + int ops_node = -1; + int cls_node = -1; + for (node_idx = 0; node_idx < dest_nodes->nelem; ++node_idx) + { + int node = dest_nodes->elems[node_idx]; + re_token_type_t type = dfa->nodes[node].type; + if (type == OP_OPEN_SUBEXP + && subexp_idx == dfa->nodes[node].opr.idx) + ops_node = node; + else if (type == OP_CLOSE_SUBEXP + && subexp_idx == dfa->nodes[node].opr.idx) + cls_node = node; + } + + /* Check the limitation of the open subexpression. */ + /* Note that (ent->subexp_to = str_idx != ent->subexp_from). */ + if (ops_node >= 0) + { + err = sub_epsilon_src_nodes (dfa, ops_node, dest_nodes, + candidates); + if (BE (err != REG_NOERROR, 0)) + return err; + } + + /* Check the limitation of the close subexpression. */ + if (cls_node >= 0) + for (node_idx = 0; node_idx < dest_nodes->nelem; ++node_idx) + { + int node = dest_nodes->elems[node_idx]; + if (!re_node_set_contains (dfa->inveclosures + node, + cls_node) + && !re_node_set_contains (dfa->eclosures + node, + cls_node)) + { + /* It is against this limitation. + Remove it form the current sifted state. */ + err = sub_epsilon_src_nodes (dfa, node, dest_nodes, + candidates); + if (BE (err != REG_NOERROR, 0)) + return err; + --node_idx; + } + } + } + else /* (ent->subexp_to != str_idx) */ + { + for (node_idx = 0; node_idx < dest_nodes->nelem; ++node_idx) + { + int node = dest_nodes->elems[node_idx]; + re_token_type_t type = dfa->nodes[node].type; + if (type == OP_CLOSE_SUBEXP || type == OP_OPEN_SUBEXP) + { + if (subexp_idx != dfa->nodes[node].opr.idx) + continue; + /* It is against this limitation. + Remove it form the current sifted state. */ + err = sub_epsilon_src_nodes (dfa, node, dest_nodes, + candidates); + if (BE (err != REG_NOERROR, 0)) + return err; + } + } + } + } + return REG_NOERROR; +} + +static reg_errcode_t +internal_function +sift_states_bkref (const re_match_context_t *mctx, re_sift_context_t *sctx, + int str_idx, const re_node_set *candidates) +{ + const re_dfa_t *const dfa = mctx->dfa; + reg_errcode_t err; + int node_idx, node; + re_sift_context_t local_sctx; + int first_idx = search_cur_bkref_entry (mctx, str_idx); + + if (first_idx == -1) + return REG_NOERROR; + + local_sctx.sifted_states = NULL; /* Mark that it hasn't been initialized. */ + + for (node_idx = 0; node_idx < candidates->nelem; ++node_idx) + { + int enabled_idx; + re_token_type_t type; + struct re_backref_cache_entry *entry; + node = candidates->elems[node_idx]; + type = dfa->nodes[node].type; + /* Avoid infinite loop for the REs like "()\1+". */ + if (node == sctx->last_node && str_idx == sctx->last_str_idx) + continue; + if (type != OP_BACK_REF) + continue; + + entry = mctx->bkref_ents + first_idx; + enabled_idx = first_idx; + do + { + int subexp_len; + int to_idx; + int dst_node; + int ret; + re_dfastate_t *cur_state; + + if (entry->node != node) + continue; + subexp_len = entry->subexp_to - entry->subexp_from; + to_idx = str_idx + subexp_len; + dst_node = (subexp_len ? dfa->nexts[node] + : dfa->edests[node].elems[0]); + + if (to_idx > sctx->last_str_idx + || sctx->sifted_states[to_idx] == NULL + || !STATE_NODE_CONTAINS (sctx->sifted_states[to_idx], dst_node) + || check_dst_limits (mctx, &sctx->limits, node, + str_idx, dst_node, to_idx)) + continue; + + if (local_sctx.sifted_states == NULL) + { + local_sctx = *sctx; + err = re_node_set_init_copy (&local_sctx.limits, &sctx->limits); + if (BE (err != REG_NOERROR, 0)) + goto free_return; + } + local_sctx.last_node = node; + local_sctx.last_str_idx = str_idx; + ret = re_node_set_insert (&local_sctx.limits, enabled_idx); + if (BE (ret < 0, 0)) + { + err = REG_ESPACE; + goto free_return; + } + cur_state = local_sctx.sifted_states[str_idx]; + err = sift_states_backward (mctx, &local_sctx); + if (BE (err != REG_NOERROR, 0)) + goto free_return; + if (sctx->limited_states != NULL) + { + err = merge_state_array (dfa, sctx->limited_states, + local_sctx.sifted_states, + str_idx + 1); + if (BE (err != REG_NOERROR, 0)) + goto free_return; + } + local_sctx.sifted_states[str_idx] = cur_state; + re_node_set_remove (&local_sctx.limits, enabled_idx); + + /* mctx->bkref_ents may have changed, reload the pointer. */ + entry = mctx->bkref_ents + enabled_idx; + } + while (enabled_idx++, entry++->more); + } + err = REG_NOERROR; + free_return: + if (local_sctx.sifted_states != NULL) + { + re_node_set_free (&local_sctx.limits); + } + + return err; +} + + +#ifdef RE_ENABLE_I18N +static int +internal_function +sift_states_iter_mb (const re_match_context_t *mctx, re_sift_context_t *sctx, + int node_idx, int str_idx, int max_str_idx) +{ + const re_dfa_t *const dfa = mctx->dfa; + int naccepted; + /* Check the node can accept `multi byte'. */ + naccepted = check_node_accept_bytes (dfa, node_idx, &mctx->input, str_idx); + if (naccepted > 0 && str_idx + naccepted <= max_str_idx && + !STATE_NODE_CONTAINS (sctx->sifted_states[str_idx + naccepted], + dfa->nexts[node_idx])) + /* The node can't accept the `multi byte', or the + destination was already thrown away, then the node + could't accept the current input `multi byte'. */ + naccepted = 0; + /* Otherwise, it is sure that the node could accept + `naccepted' bytes input. */ + return naccepted; +} +#endif /* RE_ENABLE_I18N */ + + +/* Functions for state transition. */ + +/* Return the next state to which the current state STATE will transit by + accepting the current input byte, and update STATE_LOG if necessary. + If STATE can accept a multibyte char/collating element/back reference + update the destination of STATE_LOG. */ + +static re_dfastate_t * +internal_function +transit_state (reg_errcode_t *err, re_match_context_t *mctx, + re_dfastate_t *state) +{ + re_dfastate_t **trtable; + unsigned char ch; + +#ifdef RE_ENABLE_I18N + /* If the current state can accept multibyte. */ + if (BE (state->accept_mb, 0)) + { + *err = transit_state_mb (mctx, state); + if (BE (*err != REG_NOERROR, 0)) + return NULL; + } +#endif /* RE_ENABLE_I18N */ + + /* Then decide the next state with the single byte. */ +#if 0 + if (0) + /* don't use transition table */ + return transit_state_sb (err, mctx, state); +#endif + + /* Use transition table */ + ch = re_string_fetch_byte (&mctx->input); + for (;;) + { + trtable = state->trtable; + if (BE (trtable != NULL, 1)) + return trtable[ch]; + + trtable = state->word_trtable; + if (BE (trtable != NULL, 1)) + { + unsigned int context; + context + = re_string_context_at (&mctx->input, + re_string_cur_idx (&mctx->input) - 1, + mctx->eflags); + if (IS_WORD_CONTEXT (context)) + return trtable[ch + SBC_MAX]; + else + return trtable[ch]; + } + + if (!build_trtable (mctx->dfa, state)) + { + *err = REG_ESPACE; + return NULL; + } + + /* Retry, we now have a transition table. */ + } +} + +/* Update the state_log if we need */ +re_dfastate_t * +internal_function +merge_state_with_log (reg_errcode_t *err, re_match_context_t *mctx, + re_dfastate_t *next_state) +{ + const re_dfa_t *const dfa = mctx->dfa; + int cur_idx = re_string_cur_idx (&mctx->input); + + if (cur_idx > mctx->state_log_top) + { + mctx->state_log[cur_idx] = next_state; + mctx->state_log_top = cur_idx; + } + else if (mctx->state_log[cur_idx] == 0) + { + mctx->state_log[cur_idx] = next_state; + } + else + { + re_dfastate_t *pstate; + unsigned int context; + re_node_set next_nodes, *log_nodes, *table_nodes = NULL; + /* If (state_log[cur_idx] != 0), it implies that cur_idx is + the destination of a multibyte char/collating element/ + back reference. Then the next state is the union set of + these destinations and the results of the transition table. */ + pstate = mctx->state_log[cur_idx]; + log_nodes = pstate->entrance_nodes; + if (next_state != NULL) + { + table_nodes = next_state->entrance_nodes; + *err = re_node_set_init_union (&next_nodes, table_nodes, + log_nodes); + if (BE (*err != REG_NOERROR, 0)) + return NULL; + } + else + next_nodes = *log_nodes; + /* Note: We already add the nodes of the initial state, + then we don't need to add them here. */ + + context = re_string_context_at (&mctx->input, + re_string_cur_idx (&mctx->input) - 1, + mctx->eflags); + next_state = mctx->state_log[cur_idx] + = re_acquire_state_context (err, dfa, &next_nodes, context); + /* We don't need to check errors here, since the return value of + this function is next_state and ERR is already set. */ + + if (table_nodes != NULL) + re_node_set_free (&next_nodes); + } + + if (BE (dfa->nbackref, 0) && next_state != NULL) + { + /* Check OP_OPEN_SUBEXP in the current state in case that we use them + later. We must check them here, since the back references in the + next state might use them. */ + *err = check_subexp_matching_top (mctx, &next_state->nodes, + cur_idx); + if (BE (*err != REG_NOERROR, 0)) + return NULL; + + /* If the next state has back references. */ + if (next_state->has_backref) + { + *err = transit_state_bkref (mctx, &next_state->nodes); + if (BE (*err != REG_NOERROR, 0)) + return NULL; + next_state = mctx->state_log[cur_idx]; + } + } + + return next_state; +} + +/* Skip bytes in the input that correspond to part of a + multi-byte match, then look in the log for a state + from which to restart matching. */ +re_dfastate_t * +internal_function +find_recover_state (reg_errcode_t *err, re_match_context_t *mctx) +{ + re_dfastate_t *cur_state; + do + { + int max = mctx->state_log_top; + int cur_str_idx = re_string_cur_idx (&mctx->input); + + do + { + if (++cur_str_idx > max) + return NULL; + re_string_skip_bytes (&mctx->input, 1); + } + while (mctx->state_log[cur_str_idx] == NULL); + + cur_state = merge_state_with_log (err, mctx, NULL); + } + while (*err == REG_NOERROR && cur_state == NULL); + return cur_state; +} + +/* Helper functions for transit_state. */ + +/* From the node set CUR_NODES, pick up the nodes whose types are + OP_OPEN_SUBEXP and which have corresponding back references in the regular + expression. And register them to use them later for evaluating the + correspoding back references. */ + +static reg_errcode_t +internal_function +check_subexp_matching_top (re_match_context_t *mctx, re_node_set *cur_nodes, + int str_idx) +{ + const re_dfa_t *const dfa = mctx->dfa; + int node_idx; + reg_errcode_t err; + + /* TODO: This isn't efficient. + Because there might be more than one nodes whose types are + OP_OPEN_SUBEXP and whose index is SUBEXP_IDX, we must check all + nodes. + E.g. RE: (a){2} */ + for (node_idx = 0; node_idx < cur_nodes->nelem; ++node_idx) + { + int node = cur_nodes->elems[node_idx]; + if (dfa->nodes[node].type == OP_OPEN_SUBEXP + && dfa->nodes[node].opr.idx < BITSET_WORD_BITS + && (dfa->used_bkref_map + & ((bitset_word_t) 1 << dfa->nodes[node].opr.idx))) + { + err = match_ctx_add_subtop (mctx, node, str_idx); + if (BE (err != REG_NOERROR, 0)) + return err; + } + } + return REG_NOERROR; +} + +#if 0 +/* Return the next state to which the current state STATE will transit by + accepting the current input byte. */ + +static re_dfastate_t * +transit_state_sb (reg_errcode_t *err, re_match_context_t *mctx, + re_dfastate_t *state) +{ + const re_dfa_t *const dfa = mctx->dfa; + re_node_set next_nodes; + re_dfastate_t *next_state; + int node_cnt, cur_str_idx = re_string_cur_idx (&mctx->input); + unsigned int context; + + *err = re_node_set_alloc (&next_nodes, state->nodes.nelem + 1); + if (BE (*err != REG_NOERROR, 0)) + return NULL; + for (node_cnt = 0; node_cnt < state->nodes.nelem; ++node_cnt) + { + int cur_node = state->nodes.elems[node_cnt]; + if (check_node_accept (mctx, dfa->nodes + cur_node, cur_str_idx)) + { + *err = re_node_set_merge (&next_nodes, + dfa->eclosures + dfa->nexts[cur_node]); + if (BE (*err != REG_NOERROR, 0)) + { + re_node_set_free (&next_nodes); + return NULL; + } + } + } + context = re_string_context_at (&mctx->input, cur_str_idx, mctx->eflags); + next_state = re_acquire_state_context (err, dfa, &next_nodes, context); + /* We don't need to check errors here, since the return value of + this function is next_state and ERR is already set. */ + + re_node_set_free (&next_nodes); + re_string_skip_bytes (&mctx->input, 1); + return next_state; +} +#endif + +#ifdef RE_ENABLE_I18N +static reg_errcode_t +internal_function +transit_state_mb (re_match_context_t *mctx, re_dfastate_t *pstate) +{ + const re_dfa_t *const dfa = mctx->dfa; + reg_errcode_t err; + int i; + + for (i = 0; i < pstate->nodes.nelem; ++i) + { + re_node_set dest_nodes, *new_nodes; + int cur_node_idx = pstate->nodes.elems[i]; + int naccepted, dest_idx; + unsigned int context; + re_dfastate_t *dest_state; + + if (!dfa->nodes[cur_node_idx].accept_mb) + continue; + + if (dfa->nodes[cur_node_idx].constraint) + { + context = re_string_context_at (&mctx->input, + re_string_cur_idx (&mctx->input), + mctx->eflags); + if (NOT_SATISFY_NEXT_CONSTRAINT (dfa->nodes[cur_node_idx].constraint, + context)) + continue; + } + + /* How many bytes the node can accept? */ + naccepted = check_node_accept_bytes (dfa, cur_node_idx, &mctx->input, + re_string_cur_idx (&mctx->input)); + if (naccepted == 0) + continue; + + /* The node can accepts `naccepted' bytes. */ + dest_idx = re_string_cur_idx (&mctx->input) + naccepted; + mctx->max_mb_elem_len = ((mctx->max_mb_elem_len < naccepted) ? naccepted + : mctx->max_mb_elem_len); + err = clean_state_log_if_needed (mctx, dest_idx); + if (BE (err != REG_NOERROR, 0)) + return err; +#ifdef DEBUG + assert (dfa->nexts[cur_node_idx] != -1); +#endif + new_nodes = dfa->eclosures + dfa->nexts[cur_node_idx]; + + dest_state = mctx->state_log[dest_idx]; + if (dest_state == NULL) + dest_nodes = *new_nodes; + else + { + err = re_node_set_init_union (&dest_nodes, + dest_state->entrance_nodes, new_nodes); + if (BE (err != REG_NOERROR, 0)) + return err; + } + context = re_string_context_at (&mctx->input, dest_idx - 1, + mctx->eflags); + mctx->state_log[dest_idx] + = re_acquire_state_context (&err, dfa, &dest_nodes, context); + if (dest_state != NULL) + re_node_set_free (&dest_nodes); + if (BE (mctx->state_log[dest_idx] == NULL && err != REG_NOERROR, 0)) + return err; + } + return REG_NOERROR; +} +#endif /* RE_ENABLE_I18N */ + +static reg_errcode_t +internal_function +transit_state_bkref (re_match_context_t *mctx, const re_node_set *nodes) +{ + const re_dfa_t *const dfa = mctx->dfa; + reg_errcode_t err; + int i; + int cur_str_idx = re_string_cur_idx (&mctx->input); + + for (i = 0; i < nodes->nelem; ++i) + { + int dest_str_idx, prev_nelem, bkc_idx; + int node_idx = nodes->elems[i]; + unsigned int context; + const re_token_t *node = dfa->nodes + node_idx; + re_node_set *new_dest_nodes; + + /* Check whether `node' is a backreference or not. */ + if (node->type != OP_BACK_REF) + continue; + + if (node->constraint) + { + context = re_string_context_at (&mctx->input, cur_str_idx, + mctx->eflags); + if (NOT_SATISFY_NEXT_CONSTRAINT (node->constraint, context)) + continue; + } + + /* `node' is a backreference. + Check the substring which the substring matched. */ + bkc_idx = mctx->nbkref_ents; + err = get_subexp (mctx, node_idx, cur_str_idx); + if (BE (err != REG_NOERROR, 0)) + goto free_return; + + /* And add the epsilon closures (which is `new_dest_nodes') of + the backreference to appropriate state_log. */ +#ifdef DEBUG + assert (dfa->nexts[node_idx] != -1); +#endif + for (; bkc_idx < mctx->nbkref_ents; ++bkc_idx) + { + int subexp_len; + re_dfastate_t *dest_state; + struct re_backref_cache_entry *bkref_ent; + bkref_ent = mctx->bkref_ents + bkc_idx; + if (bkref_ent->node != node_idx || bkref_ent->str_idx != cur_str_idx) + continue; + subexp_len = bkref_ent->subexp_to - bkref_ent->subexp_from; + new_dest_nodes = (subexp_len == 0 + ? dfa->eclosures + dfa->edests[node_idx].elems[0] + : dfa->eclosures + dfa->nexts[node_idx]); + dest_str_idx = (cur_str_idx + bkref_ent->subexp_to + - bkref_ent->subexp_from); + context = re_string_context_at (&mctx->input, dest_str_idx - 1, + mctx->eflags); + dest_state = mctx->state_log[dest_str_idx]; + prev_nelem = ((mctx->state_log[cur_str_idx] == NULL) ? 0 + : mctx->state_log[cur_str_idx]->nodes.nelem); + /* Add `new_dest_node' to state_log. */ + if (dest_state == NULL) + { + mctx->state_log[dest_str_idx] + = re_acquire_state_context (&err, dfa, new_dest_nodes, + context); + if (BE (mctx->state_log[dest_str_idx] == NULL + && err != REG_NOERROR, 0)) + goto free_return; + } + else + { + re_node_set dest_nodes; + err = re_node_set_init_union (&dest_nodes, + dest_state->entrance_nodes, + new_dest_nodes); + if (BE (err != REG_NOERROR, 0)) + { + re_node_set_free (&dest_nodes); + goto free_return; + } + mctx->state_log[dest_str_idx] + = re_acquire_state_context (&err, dfa, &dest_nodes, context); + re_node_set_free (&dest_nodes); + if (BE (mctx->state_log[dest_str_idx] == NULL + && err != REG_NOERROR, 0)) + goto free_return; + } + /* We need to check recursively if the backreference can epsilon + transit. */ + if (subexp_len == 0 + && mctx->state_log[cur_str_idx]->nodes.nelem > prev_nelem) + { + err = check_subexp_matching_top (mctx, new_dest_nodes, + cur_str_idx); + if (BE (err != REG_NOERROR, 0)) + goto free_return; + err = transit_state_bkref (mctx, new_dest_nodes); + if (BE (err != REG_NOERROR, 0)) + goto free_return; + } + } + } + err = REG_NOERROR; + free_return: + return err; +} + +/* Enumerate all the candidates which the backreference BKREF_NODE can match + at BKREF_STR_IDX, and register them by match_ctx_add_entry(). + Note that we might collect inappropriate candidates here. + However, the cost of checking them strictly here is too high, then we + delay these checking for prune_impossible_nodes(). */ + +static reg_errcode_t +internal_function +get_subexp (re_match_context_t *mctx, int bkref_node, int bkref_str_idx) +{ + const re_dfa_t *const dfa = mctx->dfa; + int subexp_num, sub_top_idx; + const char *buf = (const char *) re_string_get_buffer (&mctx->input); + /* Return if we have already checked BKREF_NODE at BKREF_STR_IDX. */ + int cache_idx = search_cur_bkref_entry (mctx, bkref_str_idx); + if (cache_idx != -1) + { + const struct re_backref_cache_entry *entry + = mctx->bkref_ents + cache_idx; + do + if (entry->node == bkref_node) + return REG_NOERROR; /* We already checked it. */ + while (entry++->more); + } + + subexp_num = dfa->nodes[bkref_node].opr.idx; + + /* For each sub expression */ + for (sub_top_idx = 0; sub_top_idx < mctx->nsub_tops; ++sub_top_idx) + { + reg_errcode_t err; + re_sub_match_top_t *sub_top = mctx->sub_tops[sub_top_idx]; + re_sub_match_last_t *sub_last; + int sub_last_idx, sl_str, bkref_str_off; + + if (dfa->nodes[sub_top->node].opr.idx != subexp_num) + continue; /* It isn't related. */ + + sl_str = sub_top->str_idx; + bkref_str_off = bkref_str_idx; + /* At first, check the last node of sub expressions we already + evaluated. */ + for (sub_last_idx = 0; sub_last_idx < sub_top->nlasts; ++sub_last_idx) + { + int sl_str_diff; + sub_last = sub_top->lasts[sub_last_idx]; + sl_str_diff = sub_last->str_idx - sl_str; + /* The matched string by the sub expression match with the substring + at the back reference? */ + if (sl_str_diff > 0) + { + if (BE (bkref_str_off + sl_str_diff > mctx->input.valid_len, 0)) + { + /* Not enough chars for a successful match. */ + if (bkref_str_off + sl_str_diff > mctx->input.len) + break; + + err = clean_state_log_if_needed (mctx, + bkref_str_off + + sl_str_diff); + if (BE (err != REG_NOERROR, 0)) + return err; + buf = (const char *) re_string_get_buffer (&mctx->input); + } + if (memcmp (buf + bkref_str_off, buf + sl_str, sl_str_diff) != 0) + /* We don't need to search this sub expression any more. */ + break; + } + bkref_str_off += sl_str_diff; + sl_str += sl_str_diff; + err = get_subexp_sub (mctx, sub_top, sub_last, bkref_node, + bkref_str_idx); + + /* Reload buf, since the preceding call might have reallocated + the buffer. */ + buf = (const char *) re_string_get_buffer (&mctx->input); + + if (err == REG_NOMATCH) + continue; + if (BE (err != REG_NOERROR, 0)) + return err; + } + + if (sub_last_idx < sub_top->nlasts) + continue; + if (sub_last_idx > 0) + ++sl_str; + /* Then, search for the other last nodes of the sub expression. */ + for (; sl_str <= bkref_str_idx; ++sl_str) + { + int cls_node, sl_str_off; + const re_node_set *nodes; + sl_str_off = sl_str - sub_top->str_idx; + /* The matched string by the sub expression match with the substring + at the back reference? */ + if (sl_str_off > 0) + { + if (BE (bkref_str_off >= mctx->input.valid_len, 0)) + { + /* If we are at the end of the input, we cannot match. */ + if (bkref_str_off >= mctx->input.len) + break; + + err = extend_buffers (mctx); + if (BE (err != REG_NOERROR, 0)) + return err; + + buf = (const char *) re_string_get_buffer (&mctx->input); + } + if (buf [bkref_str_off++] != buf[sl_str - 1]) + break; /* We don't need to search this sub expression + any more. */ + } + if (mctx->state_log[sl_str] == NULL) + continue; + /* Does this state have a ')' of the sub expression? */ + nodes = &mctx->state_log[sl_str]->nodes; + cls_node = find_subexp_node (dfa, nodes, subexp_num, + OP_CLOSE_SUBEXP); + if (cls_node == -1) + continue; /* No. */ + if (sub_top->path == NULL) + { + sub_top->path = calloc (sizeof (state_array_t), + sl_str - sub_top->str_idx + 1); + if (sub_top->path == NULL) + return REG_ESPACE; + } + /* Can the OP_OPEN_SUBEXP node arrive the OP_CLOSE_SUBEXP node + in the current context? */ + err = check_arrival (mctx, sub_top->path, sub_top->node, + sub_top->str_idx, cls_node, sl_str, + OP_CLOSE_SUBEXP); + if (err == REG_NOMATCH) + continue; + if (BE (err != REG_NOERROR, 0)) + return err; + sub_last = match_ctx_add_sublast (sub_top, cls_node, sl_str); + if (BE (sub_last == NULL, 0)) + return REG_ESPACE; + err = get_subexp_sub (mctx, sub_top, sub_last, bkref_node, + bkref_str_idx); + if (err == REG_NOMATCH) + continue; + } + } + return REG_NOERROR; +} + +/* Helper functions for get_subexp(). */ + +/* Check SUB_LAST can arrive to the back reference BKREF_NODE at BKREF_STR. + If it can arrive, register the sub expression expressed with SUB_TOP + and SUB_LAST. */ + +static reg_errcode_t +internal_function +get_subexp_sub (re_match_context_t *mctx, const re_sub_match_top_t *sub_top, + re_sub_match_last_t *sub_last, int bkref_node, int bkref_str) +{ + reg_errcode_t err; + int to_idx; + /* Can the subexpression arrive the back reference? */ + err = check_arrival (mctx, &sub_last->path, sub_last->node, + sub_last->str_idx, bkref_node, bkref_str, + OP_OPEN_SUBEXP); + if (err != REG_NOERROR) + return err; + err = match_ctx_add_entry (mctx, bkref_node, bkref_str, sub_top->str_idx, + sub_last->str_idx); + if (BE (err != REG_NOERROR, 0)) + return err; + to_idx = bkref_str + sub_last->str_idx - sub_top->str_idx; + return clean_state_log_if_needed (mctx, to_idx); +} + +/* Find the first node which is '(' or ')' and whose index is SUBEXP_IDX. + Search '(' if FL_OPEN, or search ')' otherwise. + TODO: This function isn't efficient... + Because there might be more than one nodes whose types are + OP_OPEN_SUBEXP and whose index is SUBEXP_IDX, we must check all + nodes. + E.g. RE: (a){2} */ + +static int +internal_function +find_subexp_node (const re_dfa_t *dfa, const re_node_set *nodes, + int subexp_idx, int type) +{ + int cls_idx; + for (cls_idx = 0; cls_idx < nodes->nelem; ++cls_idx) + { + int cls_node = nodes->elems[cls_idx]; + const re_token_t *node = dfa->nodes + cls_node; + if (node->type == type + && node->opr.idx == subexp_idx) + return cls_node; + } + return -1; +} + +/* Check whether the node TOP_NODE at TOP_STR can arrive to the node + LAST_NODE at LAST_STR. We record the path onto PATH since it will be + heavily reused. + Return REG_NOERROR if it can arrive, or REG_NOMATCH otherwise. */ + +static reg_errcode_t +internal_function +check_arrival (re_match_context_t *mctx, state_array_t *path, int top_node, + int top_str, int last_node, int last_str, int type) +{ + const re_dfa_t *const dfa = mctx->dfa; + reg_errcode_t err = REG_NOERROR; + int subexp_num, backup_cur_idx, str_idx, null_cnt; + re_dfastate_t *cur_state = NULL; + re_node_set *cur_nodes, next_nodes; + re_dfastate_t **backup_state_log; + unsigned int context; + + subexp_num = dfa->nodes[top_node].opr.idx; + /* Extend the buffer if we need. */ + if (BE (path->alloc < last_str + mctx->max_mb_elem_len + 1, 0)) + { + re_dfastate_t **new_array; + int old_alloc = path->alloc; + path->alloc += last_str + mctx->max_mb_elem_len + 1; + new_array = re_realloc (path->array, re_dfastate_t *, path->alloc); + if (BE (new_array == NULL, 0)) + { + path->alloc = old_alloc; + return REG_ESPACE; + } + path->array = new_array; + memset (new_array + old_alloc, '\0', + sizeof (re_dfastate_t *) * (path->alloc - old_alloc)); + } + + str_idx = path->next_idx ?: top_str; + + /* Temporary modify MCTX. */ + backup_state_log = mctx->state_log; + backup_cur_idx = mctx->input.cur_idx; + mctx->state_log = path->array; + mctx->input.cur_idx = str_idx; + + /* Setup initial node set. */ + context = re_string_context_at (&mctx->input, str_idx - 1, mctx->eflags); + if (str_idx == top_str) + { + err = re_node_set_init_1 (&next_nodes, top_node); + if (BE (err != REG_NOERROR, 0)) + return err; + err = check_arrival_expand_ecl (dfa, &next_nodes, subexp_num, type); + if (BE (err != REG_NOERROR, 0)) + { + re_node_set_free (&next_nodes); + return err; + } + } + else + { + cur_state = mctx->state_log[str_idx]; + if (cur_state && cur_state->has_backref) + { + err = re_node_set_init_copy (&next_nodes, &cur_state->nodes); + if (BE (err != REG_NOERROR, 0)) + return err; + } + else + re_node_set_init_empty (&next_nodes); + } + if (str_idx == top_str || (cur_state && cur_state->has_backref)) + { + if (next_nodes.nelem) + { + err = expand_bkref_cache (mctx, &next_nodes, str_idx, + subexp_num, type); + if (BE (err != REG_NOERROR, 0)) + { + re_node_set_free (&next_nodes); + return err; + } + } + cur_state = re_acquire_state_context (&err, dfa, &next_nodes, context); + if (BE (cur_state == NULL && err != REG_NOERROR, 0)) + { + re_node_set_free (&next_nodes); + return err; + } + mctx->state_log[str_idx] = cur_state; + } + + for (null_cnt = 0; str_idx < last_str && null_cnt <= mctx->max_mb_elem_len;) + { + re_node_set_empty (&next_nodes); + if (mctx->state_log[str_idx + 1]) + { + err = re_node_set_merge (&next_nodes, + &mctx->state_log[str_idx + 1]->nodes); + if (BE (err != REG_NOERROR, 0)) + { + re_node_set_free (&next_nodes); + return err; + } + } + if (cur_state) + { + err = check_arrival_add_next_nodes (mctx, str_idx, + &cur_state->non_eps_nodes, + &next_nodes); + if (BE (err != REG_NOERROR, 0)) + { + re_node_set_free (&next_nodes); + return err; + } + } + ++str_idx; + if (next_nodes.nelem) + { + err = check_arrival_expand_ecl (dfa, &next_nodes, subexp_num, type); + if (BE (err != REG_NOERROR, 0)) + { + re_node_set_free (&next_nodes); + return err; + } + err = expand_bkref_cache (mctx, &next_nodes, str_idx, + subexp_num, type); + if (BE (err != REG_NOERROR, 0)) + { + re_node_set_free (&next_nodes); + return err; + } + } + context = re_string_context_at (&mctx->input, str_idx - 1, mctx->eflags); + cur_state = re_acquire_state_context (&err, dfa, &next_nodes, context); + if (BE (cur_state == NULL && err != REG_NOERROR, 0)) + { + re_node_set_free (&next_nodes); + return err; + } + mctx->state_log[str_idx] = cur_state; + null_cnt = cur_state == NULL ? null_cnt + 1 : 0; + } + re_node_set_free (&next_nodes); + cur_nodes = (mctx->state_log[last_str] == NULL ? NULL + : &mctx->state_log[last_str]->nodes); + path->next_idx = str_idx; + + /* Fix MCTX. */ + mctx->state_log = backup_state_log; + mctx->input.cur_idx = backup_cur_idx; + + /* Then check the current node set has the node LAST_NODE. */ + if (cur_nodes != NULL && re_node_set_contains (cur_nodes, last_node)) + return REG_NOERROR; + + return REG_NOMATCH; +} + +/* Helper functions for check_arrival. */ + +/* Calculate the destination nodes of CUR_NODES at STR_IDX, and append them + to NEXT_NODES. + TODO: This function is similar to the functions transit_state*(), + however this function has many additional works. + Can't we unify them? */ + +static reg_errcode_t +internal_function +check_arrival_add_next_nodes (re_match_context_t *mctx, int str_idx, + re_node_set *cur_nodes, re_node_set *next_nodes) +{ + const re_dfa_t *const dfa = mctx->dfa; + int result; + int cur_idx; +#ifdef RE_ENABLE_I18N + reg_errcode_t err = REG_NOERROR; +#endif + re_node_set union_set; + re_node_set_init_empty (&union_set); + for (cur_idx = 0; cur_idx < cur_nodes->nelem; ++cur_idx) + { + int naccepted = 0; + int cur_node = cur_nodes->elems[cur_idx]; +#ifdef DEBUG + re_token_type_t type = dfa->nodes[cur_node].type; + assert (!IS_EPSILON_NODE (type)); +#endif +#ifdef RE_ENABLE_I18N + /* If the node may accept `multi byte'. */ + if (dfa->nodes[cur_node].accept_mb) + { + naccepted = check_node_accept_bytes (dfa, cur_node, &mctx->input, + str_idx); + if (naccepted > 1) + { + re_dfastate_t *dest_state; + int next_node = dfa->nexts[cur_node]; + int next_idx = str_idx + naccepted; + dest_state = mctx->state_log[next_idx]; + re_node_set_empty (&union_set); + if (dest_state) + { + err = re_node_set_merge (&union_set, &dest_state->nodes); + if (BE (err != REG_NOERROR, 0)) + { + re_node_set_free (&union_set); + return err; + } + } + result = re_node_set_insert (&union_set, next_node); + if (BE (result < 0, 0)) + { + re_node_set_free (&union_set); + return REG_ESPACE; + } + mctx->state_log[next_idx] = re_acquire_state (&err, dfa, + &union_set); + if (BE (mctx->state_log[next_idx] == NULL + && err != REG_NOERROR, 0)) + { + re_node_set_free (&union_set); + return err; + } + } + } +#endif /* RE_ENABLE_I18N */ + if (naccepted + || check_node_accept (mctx, dfa->nodes + cur_node, str_idx)) + { + result = re_node_set_insert (next_nodes, dfa->nexts[cur_node]); + if (BE (result < 0, 0)) + { + re_node_set_free (&union_set); + return REG_ESPACE; + } + } + } + re_node_set_free (&union_set); + return REG_NOERROR; +} + +/* For all the nodes in CUR_NODES, add the epsilon closures of them to + CUR_NODES, however exclude the nodes which are: + - inside the sub expression whose number is EX_SUBEXP, if FL_OPEN. + - out of the sub expression whose number is EX_SUBEXP, if !FL_OPEN. +*/ + +static reg_errcode_t +internal_function +check_arrival_expand_ecl (const re_dfa_t *dfa, re_node_set *cur_nodes, + int ex_subexp, int type) +{ + reg_errcode_t err; + int idx, outside_node; + re_node_set new_nodes; +#ifdef DEBUG + assert (cur_nodes->nelem); +#endif + err = re_node_set_alloc (&new_nodes, cur_nodes->nelem); + if (BE (err != REG_NOERROR, 0)) + return err; + /* Create a new node set NEW_NODES with the nodes which are epsilon + closures of the node in CUR_NODES. */ + + for (idx = 0; idx < cur_nodes->nelem; ++idx) + { + int cur_node = cur_nodes->elems[idx]; + const re_node_set *eclosure = dfa->eclosures + cur_node; + outside_node = find_subexp_node (dfa, eclosure, ex_subexp, type); + if (outside_node == -1) + { + /* There are no problematic nodes, just merge them. */ + err = re_node_set_merge (&new_nodes, eclosure); + if (BE (err != REG_NOERROR, 0)) + { + re_node_set_free (&new_nodes); + return err; + } + } + else + { + /* There are problematic nodes, re-calculate incrementally. */ + err = check_arrival_expand_ecl_sub (dfa, &new_nodes, cur_node, + ex_subexp, type); + if (BE (err != REG_NOERROR, 0)) + { + re_node_set_free (&new_nodes); + return err; + } + } + } + re_node_set_free (cur_nodes); + *cur_nodes = new_nodes; + return REG_NOERROR; +} + +/* Helper function for check_arrival_expand_ecl. + Check incrementally the epsilon closure of TARGET, and if it isn't + problematic append it to DST_NODES. */ + +static reg_errcode_t +internal_function +check_arrival_expand_ecl_sub (const re_dfa_t *dfa, re_node_set *dst_nodes, + int target, int ex_subexp, int type) +{ + int cur_node; + for (cur_node = target; !re_node_set_contains (dst_nodes, cur_node);) + { + int err; + + if (dfa->nodes[cur_node].type == type + && dfa->nodes[cur_node].opr.idx == ex_subexp) + { + if (type == OP_CLOSE_SUBEXP) + { + err = re_node_set_insert (dst_nodes, cur_node); + if (BE (err == -1, 0)) + return REG_ESPACE; + } + break; + } + err = re_node_set_insert (dst_nodes, cur_node); + if (BE (err == -1, 0)) + return REG_ESPACE; + if (dfa->edests[cur_node].nelem == 0) + break; + if (dfa->edests[cur_node].nelem == 2) + { + err = check_arrival_expand_ecl_sub (dfa, dst_nodes, + dfa->edests[cur_node].elems[1], + ex_subexp, type); + if (BE (err != REG_NOERROR, 0)) + return err; + } + cur_node = dfa->edests[cur_node].elems[0]; + } + return REG_NOERROR; +} + + +/* For all the back references in the current state, calculate the + destination of the back references by the appropriate entry + in MCTX->BKREF_ENTS. */ + +static reg_errcode_t +internal_function +expand_bkref_cache (re_match_context_t *mctx, re_node_set *cur_nodes, + int cur_str, int subexp_num, int type) +{ + const re_dfa_t *const dfa = mctx->dfa; + reg_errcode_t err; + int cache_idx_start = search_cur_bkref_entry (mctx, cur_str); + struct re_backref_cache_entry *ent; + + if (cache_idx_start == -1) + return REG_NOERROR; + + restart: + ent = mctx->bkref_ents + cache_idx_start; + do + { + int to_idx, next_node; + + /* Is this entry ENT is appropriate? */ + if (!re_node_set_contains (cur_nodes, ent->node)) + continue; /* No. */ + + to_idx = cur_str + ent->subexp_to - ent->subexp_from; + /* Calculate the destination of the back reference, and append it + to MCTX->STATE_LOG. */ + if (to_idx == cur_str) + { + /* The backreference did epsilon transit, we must re-check all the + node in the current state. */ + re_node_set new_dests; + reg_errcode_t err2, err3; + next_node = dfa->edests[ent->node].elems[0]; + if (re_node_set_contains (cur_nodes, next_node)) + continue; + err = re_node_set_init_1 (&new_dests, next_node); + err2 = check_arrival_expand_ecl (dfa, &new_dests, subexp_num, type); + err3 = re_node_set_merge (cur_nodes, &new_dests); + re_node_set_free (&new_dests); + if (BE (err != REG_NOERROR || err2 != REG_NOERROR + || err3 != REG_NOERROR, 0)) + { + err = (err != REG_NOERROR ? err + : (err2 != REG_NOERROR ? err2 : err3)); + return err; + } + /* TODO: It is still inefficient... */ + goto restart; + } + else + { + re_node_set union_set; + next_node = dfa->nexts[ent->node]; + if (mctx->state_log[to_idx]) + { + int ret; + if (re_node_set_contains (&mctx->state_log[to_idx]->nodes, + next_node)) + continue; + err = re_node_set_init_copy (&union_set, + &mctx->state_log[to_idx]->nodes); + ret = re_node_set_insert (&union_set, next_node); + if (BE (err != REG_NOERROR || ret < 0, 0)) + { + re_node_set_free (&union_set); + err = err != REG_NOERROR ? err : REG_ESPACE; + return err; + } + } + else + { + err = re_node_set_init_1 (&union_set, next_node); + if (BE (err != REG_NOERROR, 0)) + return err; + } + mctx->state_log[to_idx] = re_acquire_state (&err, dfa, &union_set); + re_node_set_free (&union_set); + if (BE (mctx->state_log[to_idx] == NULL + && err != REG_NOERROR, 0)) + return err; + } + } + while (ent++->more); + return REG_NOERROR; +} + +/* Build transition table for the state. + Return 1 if succeeded, otherwise return NULL. */ + +static int +internal_function +build_trtable (const re_dfa_t *dfa, re_dfastate_t *state) +{ + reg_errcode_t err; + int i, j, ch, need_word_trtable = 0; + bitset_word_t elem, mask; + bool dests_node_malloced = false; + bool dest_states_malloced = false; + int ndests; /* Number of the destination states from `state'. */ + re_dfastate_t **trtable; + re_dfastate_t **dest_states = NULL, **dest_states_word, **dest_states_nl; + re_node_set follows, *dests_node; + bitset_t *dests_ch; + bitset_t acceptable; + + struct dests_alloc + { + re_node_set dests_node[SBC_MAX]; + bitset_t dests_ch[SBC_MAX]; + } *dests_alloc; + + /* We build DFA states which corresponds to the destination nodes + from `state'. `dests_node[i]' represents the nodes which i-th + destination state contains, and `dests_ch[i]' represents the + characters which i-th destination state accepts. */ + if (__libc_use_alloca (sizeof (struct dests_alloc))) + dests_alloc = (struct dests_alloc *) alloca (sizeof (struct dests_alloc)); + else + { + dests_alloc = re_malloc (struct dests_alloc, 1); + if (BE (dests_alloc == NULL, 0)) + return 0; + dests_node_malloced = true; + } + dests_node = dests_alloc->dests_node; + dests_ch = dests_alloc->dests_ch; + + /* Initialize transiton table. */ + state->word_trtable = state->trtable = NULL; + + /* At first, group all nodes belonging to `state' into several + destinations. */ + ndests = group_nodes_into_DFAstates (dfa, state, dests_node, dests_ch); + if (BE (ndests <= 0, 0)) + { + if (dests_node_malloced) + free (dests_alloc); + /* Return 0 in case of an error, 1 otherwise. */ + if (ndests == 0) + { + state->trtable = (re_dfastate_t **) + calloc (sizeof (re_dfastate_t *), SBC_MAX); + return 1; + } + return 0; + } + + err = re_node_set_alloc (&follows, ndests + 1); + if (BE (err != REG_NOERROR, 0)) + goto out_free; + + if (__libc_use_alloca ((sizeof (re_node_set) + sizeof (bitset_t)) * SBC_MAX + + ndests * 3 * sizeof (re_dfastate_t *))) + dest_states = (re_dfastate_t **) + alloca (ndests * 3 * sizeof (re_dfastate_t *)); + else + { + dest_states = (re_dfastate_t **) + malloc (ndests * 3 * sizeof (re_dfastate_t *)); + if (BE (dest_states == NULL, 0)) + { +out_free: + if (dest_states_malloced) + free (dest_states); + re_node_set_free (&follows); + for (i = 0; i < ndests; ++i) + re_node_set_free (dests_node + i); + if (dests_node_malloced) + free (dests_alloc); + return 0; + } + dest_states_malloced = true; + } + dest_states_word = dest_states + ndests; + dest_states_nl = dest_states_word + ndests; + bitset_empty (acceptable); + + /* Then build the states for all destinations. */ + for (i = 0; i < ndests; ++i) + { + int next_node; + re_node_set_empty (&follows); + /* Merge the follows of this destination states. */ + for (j = 0; j < dests_node[i].nelem; ++j) + { + next_node = dfa->nexts[dests_node[i].elems[j]]; + if (next_node != -1) + { + err = re_node_set_merge (&follows, dfa->eclosures + next_node); + if (BE (err != REG_NOERROR, 0)) + goto out_free; + } + } + dest_states[i] = re_acquire_state_context (&err, dfa, &follows, 0); + if (BE (dest_states[i] == NULL && err != REG_NOERROR, 0)) + goto out_free; + /* If the new state has context constraint, + build appropriate states for these contexts. */ + if (dest_states[i]->has_constraint) + { + dest_states_word[i] = re_acquire_state_context (&err, dfa, &follows, + CONTEXT_WORD); + if (BE (dest_states_word[i] == NULL && err != REG_NOERROR, 0)) + goto out_free; + + if (dest_states[i] != dest_states_word[i] && dfa->mb_cur_max > 1) + need_word_trtable = 1; + + dest_states_nl[i] = re_acquire_state_context (&err, dfa, &follows, + CONTEXT_NEWLINE); + if (BE (dest_states_nl[i] == NULL && err != REG_NOERROR, 0)) + goto out_free; + } + else + { + dest_states_word[i] = dest_states[i]; + dest_states_nl[i] = dest_states[i]; + } + bitset_merge (acceptable, dests_ch[i]); + } + + if (!BE (need_word_trtable, 0)) + { + /* We don't care about whether the following character is a word + character, or we are in a single-byte character set so we can + discern by looking at the character code: allocate a + 256-entry transition table. */ + trtable = state->trtable = calloc (sizeof (re_dfastate_t *), SBC_MAX); + if (BE (trtable == NULL, 0)) + goto out_free; + + /* For all characters ch...: */ + for (i = 0; i < BITSET_WORDS; ++i) + for (ch = i * BITSET_WORD_BITS, elem = acceptable[i], mask = 1; + elem; + mask <<= 1, elem >>= 1, ++ch) + if (BE (elem & 1, 0)) + { + /* There must be exactly one destination which accepts + character ch. See group_nodes_into_DFAstates. */ + for (j = 0; (dests_ch[j][i] & mask) == 0; ++j) + ; + + /* j-th destination accepts the word character ch. */ + if (dfa->word_char[i] & mask) + trtable[ch] = dest_states_word[j]; + else + trtable[ch] = dest_states[j]; + } + } + else + { + /* We care about whether the following character is a word + character, and we are in a multi-byte character set: discern + by looking at the character code: build two 256-entry + transition tables, one starting at trtable[0] and one + starting at trtable[SBC_MAX]. */ + trtable = state->word_trtable = calloc (sizeof (re_dfastate_t *), 2 * SBC_MAX); + if (BE (trtable == NULL, 0)) + goto out_free; + + /* For all characters ch...: */ + for (i = 0; i < BITSET_WORDS; ++i) + for (ch = i * BITSET_WORD_BITS, elem = acceptable[i], mask = 1; + elem; + mask <<= 1, elem >>= 1, ++ch) + if (BE (elem & 1, 0)) + { + /* There must be exactly one destination which accepts + character ch. See group_nodes_into_DFAstates. */ + for (j = 0; (dests_ch[j][i] & mask) == 0; ++j) + ; + + /* j-th destination accepts the word character ch. */ + trtable[ch] = dest_states[j]; + trtable[ch + SBC_MAX] = dest_states_word[j]; + } + } + + /* new line */ + if (bitset_contain (acceptable, NEWLINE_CHAR)) + { + /* The current state accepts newline character. */ + for (j = 0; j < ndests; ++j) + if (bitset_contain (dests_ch[j], NEWLINE_CHAR)) + { + /* k-th destination accepts newline character. */ + trtable[NEWLINE_CHAR] = dest_states_nl[j]; + if (need_word_trtable) + trtable[NEWLINE_CHAR + SBC_MAX] = dest_states_nl[j]; + /* There must be only one destination which accepts + newline. See group_nodes_into_DFAstates. */ + break; + } + } + + if (dest_states_malloced) + free (dest_states); + + re_node_set_free (&follows); + for (i = 0; i < ndests; ++i) + re_node_set_free (dests_node + i); + + if (dests_node_malloced) + free (dests_alloc); + + return 1; +} + +/* Group all nodes belonging to STATE into several destinations. + Then for all destinations, set the nodes belonging to the destination + to DESTS_NODE[i] and set the characters accepted by the destination + to DEST_CH[i]. This function return the number of destinations. */ + +static int +internal_function +group_nodes_into_DFAstates (const re_dfa_t *dfa, const re_dfastate_t *state, + re_node_set *dests_node, bitset_t *dests_ch) +{ + reg_errcode_t err; + int result; + int i, j, k; + int ndests; /* Number of the destinations from `state'. */ + bitset_t accepts; /* Characters a node can accept. */ + const re_node_set *cur_nodes = &state->nodes; + bitset_empty (accepts); + ndests = 0; + + /* For all the nodes belonging to `state', */ + for (i = 0; i < cur_nodes->nelem; ++i) + { + re_token_t *node = &dfa->nodes[cur_nodes->elems[i]]; + re_token_type_t type = node->type; + unsigned int constraint = node->constraint; + + /* Enumerate all single byte character this node can accept. */ + if (type == CHARACTER) + bitset_set (accepts, node->opr.c); + else if (type == SIMPLE_BRACKET) + { + bitset_merge (accepts, node->opr.sbcset); + } + else if (type == OP_PERIOD) + { +#ifdef RE_ENABLE_I18N + if (dfa->mb_cur_max > 1) + bitset_merge (accepts, dfa->sb_char); + else +#endif + bitset_set_all (accepts); + if (!(dfa->syntax & RE_DOT_NEWLINE)) + bitset_clear (accepts, '\n'); + if (dfa->syntax & RE_DOT_NOT_NULL) + bitset_clear (accepts, '\0'); + } +#ifdef RE_ENABLE_I18N + else if (type == OP_UTF8_PERIOD) + { + memset (accepts, '\xff', sizeof (bitset_t) / 2); + if (!(dfa->syntax & RE_DOT_NEWLINE)) + bitset_clear (accepts, '\n'); + if (dfa->syntax & RE_DOT_NOT_NULL) + bitset_clear (accepts, '\0'); + } +#endif + else + continue; + + /* Check the `accepts' and sift the characters which are not + match it the context. */ + if (constraint) + { + if (constraint & NEXT_NEWLINE_CONSTRAINT) + { + bool accepts_newline = bitset_contain (accepts, NEWLINE_CHAR); + bitset_empty (accepts); + if (accepts_newline) + bitset_set (accepts, NEWLINE_CHAR); + else + continue; + } + if (constraint & NEXT_ENDBUF_CONSTRAINT) + { + bitset_empty (accepts); + continue; + } + + if (constraint & NEXT_WORD_CONSTRAINT) + { + bitset_word_t any_set = 0; + if (type == CHARACTER && !node->word_char) + { + bitset_empty (accepts); + continue; + } +#ifdef RE_ENABLE_I18N + if (dfa->mb_cur_max > 1) + for (j = 0; j < BITSET_WORDS; ++j) + any_set |= (accepts[j] &= (dfa->word_char[j] | ~dfa->sb_char[j])); + else +#endif + for (j = 0; j < BITSET_WORDS; ++j) + any_set |= (accepts[j] &= dfa->word_char[j]); + if (!any_set) + continue; + } + if (constraint & NEXT_NOTWORD_CONSTRAINT) + { + bitset_word_t any_set = 0; + if (type == CHARACTER && node->word_char) + { + bitset_empty (accepts); + continue; + } +#ifdef RE_ENABLE_I18N + if (dfa->mb_cur_max > 1) + for (j = 0; j < BITSET_WORDS; ++j) + any_set |= (accepts[j] &= ~(dfa->word_char[j] & dfa->sb_char[j])); + else +#endif + for (j = 0; j < BITSET_WORDS; ++j) + any_set |= (accepts[j] &= ~dfa->word_char[j]); + if (!any_set) + continue; + } + } + + /* Then divide `accepts' into DFA states, or create a new + state. Above, we make sure that accepts is not empty. */ + for (j = 0; j < ndests; ++j) + { + bitset_t intersec; /* Intersection sets, see below. */ + bitset_t remains; + /* Flags, see below. */ + bitset_word_t has_intersec, not_subset, not_consumed; + + /* Optimization, skip if this state doesn't accept the character. */ + if (type == CHARACTER && !bitset_contain (dests_ch[j], node->opr.c)) + continue; + + /* Enumerate the intersection set of this state and `accepts'. */ + has_intersec = 0; + for (k = 0; k < BITSET_WORDS; ++k) + has_intersec |= intersec[k] = accepts[k] & dests_ch[j][k]; + /* And skip if the intersection set is empty. */ + if (!has_intersec) + continue; + + /* Then check if this state is a subset of `accepts'. */ + not_subset = not_consumed = 0; + for (k = 0; k < BITSET_WORDS; ++k) + { + not_subset |= remains[k] = ~accepts[k] & dests_ch[j][k]; + not_consumed |= accepts[k] = accepts[k] & ~dests_ch[j][k]; + } + + /* If this state isn't a subset of `accepts', create a + new group state, which has the `remains'. */ + if (not_subset) + { + bitset_copy (dests_ch[ndests], remains); + bitset_copy (dests_ch[j], intersec); + err = re_node_set_init_copy (dests_node + ndests, &dests_node[j]); + if (BE (err != REG_NOERROR, 0)) + goto error_return; + ++ndests; + } + + /* Put the position in the current group. */ + result = re_node_set_insert (&dests_node[j], cur_nodes->elems[i]); + if (BE (result < 0, 0)) + goto error_return; + + /* If all characters are consumed, go to next node. */ + if (!not_consumed) + break; + } + /* Some characters remain, create a new group. */ + if (j == ndests) + { + bitset_copy (dests_ch[ndests], accepts); + err = re_node_set_init_1 (dests_node + ndests, cur_nodes->elems[i]); + if (BE (err != REG_NOERROR, 0)) + goto error_return; + ++ndests; + bitset_empty (accepts); + } + } + return ndests; + error_return: + for (j = 0; j < ndests; ++j) + re_node_set_free (dests_node + j); + return -1; +} + +#ifdef RE_ENABLE_I18N +/* Check how many bytes the node `dfa->nodes[node_idx]' accepts. + Return the number of the bytes the node accepts. + STR_IDX is the current index of the input string. + + This function handles the nodes which can accept one character, or + one collating element like '.', '[a-z]', opposite to the other nodes + can only accept one byte. */ + +static int +internal_function +check_node_accept_bytes (const re_dfa_t *dfa, int node_idx, + const re_string_t *input, int str_idx) +{ + const re_token_t *node = dfa->nodes + node_idx; + int char_len, elem_len; + int i; + + if (BE (node->type == OP_UTF8_PERIOD, 0)) + { + unsigned char c = re_string_byte_at (input, str_idx), d; + if (BE (c < 0xc2, 1)) + return 0; + + if (str_idx + 2 > input->len) + return 0; + + d = re_string_byte_at (input, str_idx + 1); + if (c < 0xe0) + return (d < 0x80 || d > 0xbf) ? 0 : 2; + else if (c < 0xf0) + { + char_len = 3; + if (c == 0xe0 && d < 0xa0) + return 0; + } + else if (c < 0xf8) + { + char_len = 4; + if (c == 0xf0 && d < 0x90) + return 0; + } + else if (c < 0xfc) + { + char_len = 5; + if (c == 0xf8 && d < 0x88) + return 0; + } + else if (c < 0xfe) + { + char_len = 6; + if (c == 0xfc && d < 0x84) + return 0; + } + else + return 0; + + if (str_idx + char_len > input->len) + return 0; + + for (i = 1; i < char_len; ++i) + { + d = re_string_byte_at (input, str_idx + i); + if (d < 0x80 || d > 0xbf) + return 0; + } + return char_len; + } + + char_len = re_string_char_size_at (input, str_idx); + if (node->type == OP_PERIOD) + { + if (char_len <= 1) + return 0; + /* FIXME: I don't think this if is needed, as both '\n' + and '\0' are char_len == 1. */ + /* '.' accepts any one character except the following two cases. */ + if ((!(dfa->syntax & RE_DOT_NEWLINE) && + re_string_byte_at (input, str_idx) == '\n') || + ((dfa->syntax & RE_DOT_NOT_NULL) && + re_string_byte_at (input, str_idx) == '\0')) + return 0; + return char_len; + } + + elem_len = re_string_elem_size_at (input, str_idx); + if ((elem_len <= 1 && char_len <= 1) || char_len == 0) + return 0; + + if (node->type == COMPLEX_BRACKET) + { + const re_charset_t *cset = node->opr.mbcset; +# if 0 + const unsigned char *pin + = ((const unsigned char *) re_string_get_buffer (input) + str_idx); + int j; + uint32_t nrules; +# endif + int match_len = 0; + wchar_t wc = ((cset->nranges || cset->nchar_classes || cset->nmbchars) + ? re_string_wchar_at (input, str_idx) : 0); + + /* match with multibyte character? */ + for (i = 0; i < cset->nmbchars; ++i) + if (wc == cset->mbchars[i]) + { + match_len = char_len; + goto check_node_accept_bytes_match; + } + /* match with character_class? */ + for (i = 0; i < cset->nchar_classes; ++i) + { + wctype_t wt = cset->char_classes[i]; + if (__iswctype (wc, wt)) + { + match_len = char_len; + goto check_node_accept_bytes_match; + } + } + +# if 0 + nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); + if (nrules != 0) + { + unsigned int in_collseq = 0; + const int32_t *table, *indirect; + const unsigned char *weights, *extra; + const char *collseqwc; + int32_t idx; + /* This #include defines a local function! */ +# include + + /* match with collating_symbol? */ + if (cset->ncoll_syms) + extra = (const unsigned char *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_EXTRAMB); + for (i = 0; i < cset->ncoll_syms; ++i) + { + const unsigned char *coll_sym = extra + cset->coll_syms[i]; + /* Compare the length of input collating element and + the length of current collating element. */ + if (*coll_sym != elem_len) + continue; + /* Compare each bytes. */ + for (j = 0; j < *coll_sym; j++) + if (pin[j] != coll_sym[1 + j]) + break; + if (j == *coll_sym) + { + /* Match if every bytes is equal. */ + match_len = j; + goto check_node_accept_bytes_match; + } + } + + if (cset->nranges) + { + if (elem_len <= char_len) + { + collseqwc = _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQWC); + in_collseq = __collseq_table_lookup (collseqwc, wc); + } + else + in_collseq = find_collation_sequence_value (pin, elem_len); + } + /* match with range expression? */ + for (i = 0; i < cset->nranges; ++i) + if (cset->range_starts[i] <= in_collseq + && in_collseq <= cset->range_ends[i]) + { + match_len = elem_len; + goto check_node_accept_bytes_match; + } + + /* match with equivalence_class? */ + if (cset->nequiv_classes) + { + const unsigned char *cp = pin; + table = (const int32_t *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB); + weights = (const unsigned char *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_WEIGHTMB); + extra = (const unsigned char *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAMB); + indirect = (const int32_t *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTMB); + idx = findidx (&cp); + if (idx > 0) + for (i = 0; i < cset->nequiv_classes; ++i) + { + int32_t equiv_class_idx = cset->equiv_classes[i]; + size_t weight_len = weights[idx]; + if (weight_len == weights[equiv_class_idx]) + { + int cnt = 0; + while (cnt <= weight_len + && (weights[equiv_class_idx + 1 + cnt] + == weights[idx + 1 + cnt])) + ++cnt; + if (cnt > weight_len) + { + match_len = elem_len; + goto check_node_accept_bytes_match; + } + } + } + } + } + else +# endif + { + /* match with range expression? */ + wchar_t cmp_buf[6]; + + memset (cmp_buf, 0, sizeof(cmp_buf)); + cmp_buf[2] = wc; + for (i = 0; i < cset->nranges; ++i) + { + cmp_buf[0] = cset->range_starts[i]; + cmp_buf[4] = cset->range_ends[i]; + if (wcscoll (cmp_buf, cmp_buf + 2) <= 0 + && wcscoll (cmp_buf + 2, cmp_buf + 4) <= 0) + { + match_len = char_len; + goto check_node_accept_bytes_match; + } + } + } + + check_node_accept_bytes_match: + if (!cset->non_match) + return match_len; + if (match_len > 0) + return 0; + return (elem_len > char_len) ? elem_len : char_len; + } + return 0; +} + +# if 0 +static unsigned int +internal_function +find_collation_sequence_value (const unsigned char *mbs, size_t mbs_len) +{ + uint32_t nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); + if (nrules == 0) + { + if (mbs_len == 1) + { + /* No valid character. Match it as a single byte character. */ + const unsigned char *collseq = (const unsigned char *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQMB); + return collseq[mbs[0]]; + } + return UINT_MAX; + } + else + { + int32_t idx; + const unsigned char *extra = (const unsigned char *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_EXTRAMB); + int32_t extrasize = (const unsigned char *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_EXTRAMB + 1) - extra; + + for (idx = 0; idx < extrasize;) + { + int mbs_cnt, found = 0; + int32_t elem_mbs_len; + /* Skip the name of collating element name. */ + idx = idx + extra[idx] + 1; + elem_mbs_len = extra[idx++]; + if (mbs_len == elem_mbs_len) + { + for (mbs_cnt = 0; mbs_cnt < elem_mbs_len; ++mbs_cnt) + if (extra[idx + mbs_cnt] != mbs[mbs_cnt]) + break; + if (mbs_cnt == elem_mbs_len) + /* Found the entry. */ + found = 1; + } + /* Skip the byte sequence of the collating element. */ + idx += elem_mbs_len; + /* Adjust for the alignment. */ + idx = (idx + 3) & ~3; + /* Skip the collation sequence value. */ + idx += sizeof (uint32_t); + /* Skip the wide char sequence of the collating element. */ + idx = idx + sizeof (uint32_t) * (extra[idx] + 1); + /* If we found the entry, return the sequence value. */ + if (found) + return *(uint32_t *) (extra + idx); + /* Skip the collation sequence value. */ + idx += sizeof (uint32_t); + } + return UINT_MAX; + } +} +# endif +#endif /* RE_ENABLE_I18N */ + +/* Check whether the node accepts the byte which is IDX-th + byte of the INPUT. */ + +static int +internal_function +check_node_accept (const re_match_context_t *mctx, const re_token_t *node, + int idx) +{ + unsigned char ch; + ch = re_string_byte_at (&mctx->input, idx); + switch (node->type) + { + case CHARACTER: + if (node->opr.c != ch) + return 0; + break; + + case SIMPLE_BRACKET: + if (!bitset_contain (node->opr.sbcset, ch)) + return 0; + break; + +#ifdef RE_ENABLE_I18N + case OP_UTF8_PERIOD: + if (ch >= 0x80) + return 0; + /* FALLTHROUGH */ +#endif + case OP_PERIOD: + if ((ch == '\n' && !(mctx->dfa->syntax & RE_DOT_NEWLINE)) + || (ch == '\0' && (mctx->dfa->syntax & RE_DOT_NOT_NULL))) + return 0; + break; + + default: + return 0; + } + + if (node->constraint) + { + /* The node has constraints. Check whether the current context + satisfies the constraints. */ + unsigned int context = re_string_context_at (&mctx->input, idx, + mctx->eflags); + if (NOT_SATISFY_NEXT_CONSTRAINT (node->constraint, context)) + return 0; + } + + return 1; +} + +/* Extend the buffers, if the buffers have run out. */ + +static reg_errcode_t +internal_function +extend_buffers (re_match_context_t *mctx) +{ + reg_errcode_t ret; + re_string_t *pstr = &mctx->input; + + /* Double the lengthes of the buffers. */ + ret = re_string_realloc_buffers (pstr, pstr->bufs_len * 2); + if (BE (ret != REG_NOERROR, 0)) + return ret; + + if (mctx->state_log != NULL) + { + /* And double the length of state_log. */ + /* XXX We have no indication of the size of this buffer. If this + allocation fail we have no indication that the state_log array + does not have the right size. */ + re_dfastate_t **new_array = re_realloc (mctx->state_log, re_dfastate_t *, + pstr->bufs_len + 1); + if (BE (new_array == NULL, 0)) + return REG_ESPACE; + mctx->state_log = new_array; + } + + /* Then reconstruct the buffers. */ + if (pstr->icase) + { +#ifdef RE_ENABLE_I18N + if (pstr->mb_cur_max > 1) + { + ret = build_wcs_upper_buffer (pstr); + if (BE (ret != REG_NOERROR, 0)) + return ret; + } + else +#endif /* RE_ENABLE_I18N */ + build_upper_buffer (pstr); + } + else + { +#ifdef RE_ENABLE_I18N + if (pstr->mb_cur_max > 1) + build_wcs_buffer (pstr); + else +#endif /* RE_ENABLE_I18N */ + { + if (pstr->trans != NULL) + re_string_translate_buffer (pstr); + } + } + return REG_NOERROR; +} + + +/* Functions for matching context. */ + +/* Initialize MCTX. */ + +static reg_errcode_t +internal_function +match_ctx_init (re_match_context_t *mctx, int eflags, int n) +{ + mctx->eflags = eflags; + mctx->match_last = -1; + if (n > 0) + { + mctx->bkref_ents = re_malloc (struct re_backref_cache_entry, n); + mctx->sub_tops = re_malloc (re_sub_match_top_t *, n); + if (BE (mctx->bkref_ents == NULL || mctx->sub_tops == NULL, 0)) + return REG_ESPACE; + } + /* Already zero-ed by the caller. + else + mctx->bkref_ents = NULL; + mctx->nbkref_ents = 0; + mctx->nsub_tops = 0; */ + mctx->abkref_ents = n; + mctx->max_mb_elem_len = 1; + mctx->asub_tops = n; + return REG_NOERROR; +} + +/* Clean the entries which depend on the current input in MCTX. + This function must be invoked when the matcher changes the start index + of the input, or changes the input string. */ + +static void +internal_function +match_ctx_clean (re_match_context_t *mctx) +{ + int st_idx; + for (st_idx = 0; st_idx < mctx->nsub_tops; ++st_idx) + { + int sl_idx; + re_sub_match_top_t *top = mctx->sub_tops[st_idx]; + for (sl_idx = 0; sl_idx < top->nlasts; ++sl_idx) + { + re_sub_match_last_t *last = top->lasts[sl_idx]; + re_free (last->path.array); + re_free (last); + } + re_free (top->lasts); + if (top->path) + { + re_free (top->path->array); + re_free (top->path); + } + free (top); + } + + mctx->nsub_tops = 0; + mctx->nbkref_ents = 0; +} + +/* Free all the memory associated with MCTX. */ + +static void +internal_function +match_ctx_free (re_match_context_t *mctx) +{ + /* First, free all the memory associated with MCTX->SUB_TOPS. */ + match_ctx_clean (mctx); + re_free (mctx->sub_tops); + re_free (mctx->bkref_ents); +} + +/* Add a new backreference entry to MCTX. + Note that we assume that caller never call this function with duplicate + entry, and call with STR_IDX which isn't smaller than any existing entry. +*/ + +static reg_errcode_t +internal_function +match_ctx_add_entry (re_match_context_t *mctx, int node, int str_idx, int from, + int to) +{ + if (mctx->nbkref_ents >= mctx->abkref_ents) + { + struct re_backref_cache_entry* new_entry; + new_entry = re_realloc (mctx->bkref_ents, struct re_backref_cache_entry, + mctx->abkref_ents * 2); + if (BE (new_entry == NULL, 0)) + { + re_free (mctx->bkref_ents); + return REG_ESPACE; + } + mctx->bkref_ents = new_entry; + memset (mctx->bkref_ents + mctx->nbkref_ents, '\0', + sizeof (struct re_backref_cache_entry) * mctx->abkref_ents); + mctx->abkref_ents *= 2; + } + if (mctx->nbkref_ents > 0 + && mctx->bkref_ents[mctx->nbkref_ents - 1].str_idx == str_idx) + mctx->bkref_ents[mctx->nbkref_ents - 1].more = 1; + + mctx->bkref_ents[mctx->nbkref_ents].node = node; + mctx->bkref_ents[mctx->nbkref_ents].str_idx = str_idx; + mctx->bkref_ents[mctx->nbkref_ents].subexp_from = from; + mctx->bkref_ents[mctx->nbkref_ents].subexp_to = to; + + /* This is a cache that saves negative results of check_dst_limits_calc_pos. + If bit N is clear, means that this entry won't epsilon-transition to + an OP_OPEN_SUBEXP or OP_CLOSE_SUBEXP for the N+1-th subexpression. If + it is set, check_dst_limits_calc_pos_1 will recurse and try to find one + such node. + + A backreference does not epsilon-transition unless it is empty, so set + to all zeros if FROM != TO. */ + mctx->bkref_ents[mctx->nbkref_ents].eps_reachable_subexps_map + = (from == to ? ~0 : 0); + + mctx->bkref_ents[mctx->nbkref_ents++].more = 0; + if (mctx->max_mb_elem_len < to - from) + mctx->max_mb_elem_len = to - from; + return REG_NOERROR; +} + +/* Search for the first entry which has the same str_idx, or -1 if none is + found. Note that MCTX->BKREF_ENTS is already sorted by MCTX->STR_IDX. */ + +static int +internal_function +search_cur_bkref_entry (const re_match_context_t *mctx, int str_idx) +{ + int left, right, mid, last; + last = right = mctx->nbkref_ents; + for (left = 0; left < right;) + { + mid = (left + right) / 2; + if (mctx->bkref_ents[mid].str_idx < str_idx) + left = mid + 1; + else + right = mid; + } + if (left < last && mctx->bkref_ents[left].str_idx == str_idx) + return left; + else + return -1; +} + +/* Register the node NODE, whose type is OP_OPEN_SUBEXP, and which matches + at STR_IDX. */ + +static reg_errcode_t +internal_function +match_ctx_add_subtop (re_match_context_t *mctx, int node, int str_idx) +{ +#ifdef DEBUG + assert (mctx->sub_tops != NULL); + assert (mctx->asub_tops > 0); +#endif + if (BE (mctx->nsub_tops == mctx->asub_tops, 0)) + { + int new_asub_tops = mctx->asub_tops * 2; + re_sub_match_top_t **new_array = re_realloc (mctx->sub_tops, + re_sub_match_top_t *, + new_asub_tops); + if (BE (new_array == NULL, 0)) + return REG_ESPACE; + mctx->sub_tops = new_array; + mctx->asub_tops = new_asub_tops; + } + mctx->sub_tops[mctx->nsub_tops] = calloc (1, sizeof (re_sub_match_top_t)); + if (BE (mctx->sub_tops[mctx->nsub_tops] == NULL, 0)) + return REG_ESPACE; + mctx->sub_tops[mctx->nsub_tops]->node = node; + mctx->sub_tops[mctx->nsub_tops++]->str_idx = str_idx; + return REG_NOERROR; +} + +/* Register the node NODE, whose type is OP_CLOSE_SUBEXP, and which matches + at STR_IDX, whose corresponding OP_OPEN_SUBEXP is SUB_TOP. */ + +static re_sub_match_last_t * +internal_function +match_ctx_add_sublast (re_sub_match_top_t *subtop, int node, int str_idx) +{ + re_sub_match_last_t *new_entry; + if (BE (subtop->nlasts == subtop->alasts, 0)) + { + int new_alasts = 2 * subtop->alasts + 1; + re_sub_match_last_t **new_array = re_realloc (subtop->lasts, + re_sub_match_last_t *, + new_alasts); + if (BE (new_array == NULL, 0)) + return NULL; + subtop->lasts = new_array; + subtop->alasts = new_alasts; + } + new_entry = calloc (1, sizeof (re_sub_match_last_t)); + if (BE (new_entry != NULL, 1)) + { + subtop->lasts[subtop->nlasts] = new_entry; + new_entry->node = node; + new_entry->str_idx = str_idx; + ++subtop->nlasts; + } + return new_entry; +} + +static void +internal_function +sift_ctx_init (re_sift_context_t *sctx, re_dfastate_t **sifted_sts, + re_dfastate_t **limited_sts, int last_node, int last_str_idx) +{ + sctx->sifted_states = sifted_sts; + sctx->limited_states = limited_sts; + sctx->last_node = last_node; + sctx->last_str_idx = last_str_idx; + re_node_set_init_empty (&sctx->limits); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/search/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/search/Makefile new file mode 100644 index 00000000..4a8f4a07 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/search/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../ +top_builddir=../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/search/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/search/Makefile.in new file mode 100644 index 00000000..35dacb49 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/search/Makefile.in @@ -0,0 +1,35 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +subdirs += libc/misc/search + +CSRC := hsearch.c + +# multi source _tsearch.c +CSRC += tsearch.c tfind.c tdelete.c twalk.c tdestroy.c + +# multi source _lsearch.c +CSRC += lfind.c lsearch.c + +# multi source insremque.c +CSRC += insque.c remque.c + +# multi source _hsearch_r.c +CSRC += hcreate_r.c hdestroy_r.c hsearch_r.c + +MISC_SEARCH_DIR := $(top_srcdir)libc/misc/search +MISC_SEARCH_OUT := $(top_builddir)libc/misc/search + +MISC_SEARCH_SRC := $(patsubst %.c,$(MISC_SEARCH_DIR)/%.c,$(CSRC)) +MISC_SEARCH_OBJ := $(patsubst %.c,$(MISC_SEARCH_OUT)/%.o,$(CSRC)) + +libc-y += $(MISC_SEARCH_OBJ) + +objclean-y += CLEAN_libc/misc/search + +CLEAN_libc/misc/search: + $(do_rm) $(addprefix $(MISC_SEARCH_OUT)/*., o os) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/search/_hsearch_r.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/search/_hsearch_r.c new file mode 100644 index 00000000..bfe3efed --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/search/_hsearch_r.c @@ -0,0 +1,226 @@ +/* Copyright (C) 1993, 1995, 1996, 1997, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1993. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +#include + + +/* [Aho,Sethi,Ullman] Compilers: Principles, Techniques and Tools, 1986 + [Knuth] The Art of Computer Programming, part 3 (6.4) */ + + +/* The reentrant version has no static variables to maintain the state. + Instead the interface of all functions is extended to take an argument + which describes the current status. */ +typedef struct _ENTRY +{ + unsigned int used; + ENTRY entry; +} +_ENTRY; + + +#ifdef L_hcreate_r + +/* For the used double hash method the table size has to be a prime. To + correct the user given table size we need a prime test. This trivial + algorithm is adequate because + a) the code is (most probably) called a few times per program run and + b) the number is small because the table must fit in the core */ +static int isprime (unsigned int number) +{ + /* no even number will be passed */ + unsigned int divisor = 3; + + while (divisor * divisor < number && number % divisor != 0) + divisor += 2; + + return number % divisor != 0; +} + + +/* Before using the hash table we must allocate memory for it. + Test for an existing table are done. We allocate one element + more as the found prime number says. This is done for more effective + indexing as explained in the comment for the hsearch function. + The contents of the table is zeroed, especially the field used + becomes zero. */ +int hcreate_r (size_t nel, struct hsearch_data *htab) +{ + /* Test for correct arguments. */ + if (htab == NULL) + { + __set_errno (EINVAL); + return 0; + } + + /* There is still another table active. Return with error. */ + if (htab->table != NULL) + return 0; + + /* Change nel to the first prime number not smaller as nel. */ + nel |= 1; /* make odd */ + while (!isprime (nel)) + nel += 2; + + htab->size = nel; + htab->filled = 0; + + /* allocate memory and zero out */ + htab->table = (_ENTRY *) calloc (htab->size + 1, sizeof (_ENTRY)); + if (htab->table == NULL) + return 0; + + /* everything went alright */ + return 1; +} +libc_hidden_def(hcreate_r) +#endif + +#ifdef L_hdestroy_r +/* After using the hash table it has to be destroyed. The used memory can + be freed and the local static variable can be marked as not used. */ +void hdestroy_r (struct hsearch_data *htab) +{ + /* Test for correct arguments. */ + if (htab == NULL) + { + __set_errno (EINVAL); + return; + } + + /* free used memory */ + free (htab->table); + + /* the sign for an existing table is an value != NULL in htable */ + htab->table = NULL; +} +libc_hidden_def(hdestroy_r) +#endif + +#ifdef L_hsearch_r +/* This is the search function. It uses double hashing with open addressing. + The argument item.key has to be a pointer to an zero terminated, most + probably strings of chars. The function for generating a number of the + strings is simple but fast. It can be replaced by a more complex function + like ajw (see [Aho,Sethi,Ullman]) if the needs are shown. + + We use an trick to speed up the lookup. The table is created by hcreate + with one more element available. This enables us to use the index zero + special. This index will never be used because we store the first hash + index in the field used where zero means not used. Every other value + means used. The used field can be used as a first fast comparison for + equality of the stored and the parameter value. This helps to prevent + unnecessary expensive calls of strcmp. */ + + +int hsearch_r (ENTRY item, ACTION action, ENTRY **retval, + struct hsearch_data *htab) +{ + unsigned int hval; + unsigned int count; + unsigned int len = strlen (item.key); + unsigned int idx; + + /* Compute an value for the given string. Perhaps use a better method. */ + hval = len; + count = len; + while (count-- > 0) + { + hval <<= 4; + hval += item.key[count]; + } + + /* First hash function: simply take the modul but prevent zero. */ + hval %= htab->size; + if (hval == 0) + ++hval; + + /* The first index tried. */ + idx = hval; + + if (htab->table[idx].used) + { + /* Further action might be required according to the action value. */ + unsigned hval2; + + if (htab->table[idx].used == hval + && strcmp (item.key, htab->table[idx].entry.key) == 0) + { + *retval = &htab->table[idx].entry; + return 1; + } + + /* Second hash function, as suggested in [Knuth] */ + hval2 = 1 + hval % (htab->size - 2); + + do + { + /* Because SIZE is prime this guarantees to step through all + available indeces. */ + if (idx <= hval2) + idx = htab->size + idx - hval2; + else + idx -= hval2; + + /* If we visited all entries leave the loop unsuccessfully. */ + if (idx == hval) + break; + + /* If entry is found use it. */ + if (htab->table[idx].used == hval + && strcmp (item.key, htab->table[idx].entry.key) == 0) + { + *retval = &htab->table[idx].entry; + return 1; + } + } + while (htab->table[idx].used); + } + + /* An empty bucket has been found. */ + if (action == ENTER) + { + /* If table is full and another entry should be entered return + with error. */ + if (htab->filled == htab->size) + { + __set_errno (ENOMEM); + *retval = NULL; + return 0; + } + + htab->table[idx].used = hval; + htab->table[idx].entry = item; + + ++htab->filled; + + *retval = &htab->table[idx].entry; + return 1; + } + + __set_errno (ESRCH); + *retval = NULL; + return 0; +} +libc_hidden_def(hsearch_r) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/search/_lsearch.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/search/_lsearch.c new file mode 100644 index 00000000..0cf496e2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/search/_lsearch.c @@ -0,0 +1,49 @@ +/* + * This file lifted in toto from 'Dlibs' on the atari ST (RdeBath) + * + * + * Dale Schumacher 399 Beacon Ave. + * (alias: Dalnefre') St. Paul, MN 55104 + * dal@syntel.UUCP United States of America + * "It's not reality that's important, but how you perceive things." + */ + +#include +#include +#include + + +#ifdef L_lfind + +void *lfind(const void *key, const void *base, size_t *nmemb, + size_t size, int (*compar)(const void *, const void *)) +{ + register int n = *nmemb; + + while (n--) { + if ((*compar) (key, base) == 0) + return ((void*)base); + base += size; + } + return (NULL); +} +libc_hidden_def(lfind) + +#endif + +#ifdef L_lsearch + + +void *lsearch(const void *key, void *base, size_t *nmemb, + size_t size, int (*compar)(const void *, const void *)) +{ + register char *p; + + if ((p = lfind(key, base, nmemb, size, compar)) == NULL) { + p = memcpy((base + (size * (*nmemb))), key, size); + ++(*nmemb); + } + return (p); +} + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/search/_tsearch.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/search/_tsearch.c new file mode 100644 index 00000000..20b04af7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/search/_tsearch.c @@ -0,0 +1,220 @@ +/* Copyright (C) 1994 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +/* + * Tree search generalized from Knuth (6.2.2) Algorithm T just like + * the AT&T man page says. + * + * The node_t structure is for internal use only, lint doesn't grok it. + * + * Written by reading the System V Interface Definition, not the code. + * + * Totally public domain. + */ +/*LINTLIBRARY*/ + +#include +#include + +/* This routine is not very bad. It makes many assumptions about + * the compiler. It assumpts that the first field in node must be + * the "key" field, which points to the datum. It is a very trick + * stuff. H.J. + */ + +typedef struct node_t +{ + void *key; + struct node_t *left, *right; +} node; + +#ifdef L_tsearch +/* find or insert datum into search tree. +char *key; key to be located +register node **rootp; address of tree root +int (*compar)(); ordering function +*/ + +void *tsearch(__const void *key, void **vrootp, __compar_fn_t compar) +{ + register node *q; + register node **rootp = (node **) vrootp; + + if (rootp == (struct node_t **)0) + return ((struct node_t *)0); + while (*rootp != (struct node_t *)0) /* Knuth's T1: */ + { + int r; + + if ((r = (*compar)(key, (*rootp)->key)) == 0) /* T2: */ + return (*rootp); /* we found it! */ + rootp = (r < 0) ? + &(*rootp)->left : /* T3: follow left branch */ + &(*rootp)->right; /* T4: follow right branch */ + } + q = (node *) malloc(sizeof(node)); /* T5: key not found */ + if (q != (struct node_t *)0) /* make new node */ + { + *rootp = q; /* link new node to old */ + q->key = (void *)key; /* initialize new node */ + q->left = q->right = (struct node_t *)0; + } + return (q); +} +libc_hidden_def(tsearch) +#endif + +#ifdef L_tfind +void *tfind(__const void *key, void * __const *vrootp, __compar_fn_t compar) +{ + register node **rootp = (node **) vrootp; + + if (rootp == (struct node_t **)0) + return ((struct node_t *)0); + while (*rootp != (struct node_t *)0) /* Knuth's T1: */ + { + int r; + + if ((r = (*compar)(key, (*rootp)->key)) == 0) /* T2: */ + return (*rootp); /* we found it! */ + rootp = (r < 0) ? + &(*rootp)->left : /* T3: follow left branch */ + &(*rootp)->right; /* T4: follow right branch */ + } + return NULL; +} +libc_hidden_def(tfind) +#endif + +#ifdef L_tdelete +/* delete node with given key +char *key; key to be deleted +register node **rootp; address of the root of tree +int (*compar)(); comparison function +*/ +void *tdelete(__const void *key, void ** vrootp, __compar_fn_t compar) +{ + node *p; + register node *q; + register node *r; + int cmp; + register node **rootp = (node **) vrootp; + + if (rootp == (struct node_t **)0 || (p = *rootp) == (struct node_t *)0) + return ((struct node_t *)0); + while ((cmp = (*compar)(key, (*rootp)->key)) != 0) + { + p = *rootp; + rootp = (cmp < 0) ? + &(*rootp)->left : /* follow left branch */ + &(*rootp)->right; /* follow right branch */ + if (*rootp == (struct node_t *)0) + return ((struct node_t *)0); /* key not found */ + } + r = (*rootp)->right; /* D1: */ + if ((q = (*rootp)->left) == (struct node_t *)0) /* Left (struct node_t *)0? */ + q = r; + else if (r != (struct node_t *)0) /* Right link is null? */ + { + if (r->left == (struct node_t *)0) /* D2: Find successor */ + { + r->left = q; + q = r; + } + else + { /* D3: Find (struct node_t *)0 link */ + for (q = r->left; q->left != (struct node_t *)0; q = r->left) + r = q; + r->left = q->right; + q->left = (*rootp)->left; + q->right = (*rootp)->right; + } + } + free((struct node_t *) *rootp); /* D4: Free node */ + *rootp = q; /* link parent to new node */ + return(p); +} +#endif + +#ifdef L_twalk +/* Walk the nodes of a tree +register node *root; Root of the tree to be walked +register void (*action)(); Function to be called at each node +register int level; +*/ +static void trecurse(__const void *vroot, __action_fn_t action, int level) +{ + register node *root = (node *) vroot; + + if (root->left == (struct node_t *)0 && root->right == (struct node_t *)0) + (*action)(root, leaf, level); + else + { + (*action)(root, preorder, level); + if (root->left != (struct node_t *)0) + trecurse(root->left, action, level + 1); + (*action)(root, postorder, level); + if (root->right != (struct node_t *)0) + trecurse(root->right, action, level + 1); + (*action)(root, endorder, level); + } +} + +/* void twalk(root, action) Walk the nodes of a tree +node *root; Root of the tree to be walked +void (*action)(); Function to be called at each node +PTR +*/ +void twalk(__const void *vroot, __action_fn_t action) +{ + register __const node *root = (node *) vroot; + + if (root != (node *)0 && action != (__action_fn_t) 0) + trecurse(root, action, 0); +} +#endif + +#ifdef __USE_GNU +#ifdef L_tdestroy +/* The standardized functions miss an important functionality: the + tree cannot be removed easily. We provide a function to do this. */ +static void +internal_function +tdestroy_recurse (node *root, __free_fn_t freefct) +{ + if (root->left != NULL) + tdestroy_recurse (root->left, freefct); + if (root->right != NULL) + tdestroy_recurse (root->right, freefct); + (*freefct) ((void *) root->key); + /* Free the node itself. */ + free (root); +} + +void tdestroy (void *vroot, __free_fn_t freefct) +{ + node *root = (node *) vroot; + if (root != NULL) { + tdestroy_recurse (root, freefct); + } +} +libc_hidden_def(tdestroy) +#endif +#endif + +/* tsearch.c ends here */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/search/hcreate_r.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/search/hcreate_r.c new file mode 100644 index 00000000..b62991e4 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/search/hcreate_r.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_hcreate_r +#include "_hsearch_r.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/search/hdestroy_r.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/search/hdestroy_r.c new file mode 100644 index 00000000..98e1ddbe --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/search/hdestroy_r.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_hdestroy_r +#include "_hsearch_r.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/search/hsearch.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/search/hsearch.c new file mode 100644 index 00000000..d011997b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/search/hsearch.c @@ -0,0 +1,52 @@ +/* Copyright (C) 1993, 1995, 1996, 1997, 1998 Free Software Foundation, Inc. + Contributed by Ulrich Drepper + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + + +/* The non-reentrant version use a global space for storing the table. */ +static struct hsearch_data htab; + + +/* Define the non-reentrant function using the reentrant counterparts. */ +ENTRY *hsearch (ENTRY item, ACTION action) +{ + ENTRY *result; + + (void) hsearch_r (item, action, &result, &htab); + + return result; +} + + +int hcreate (size_t nel) +{ + return hcreate_r (nel, &htab); +} + + +/* void __hdestroy (void) */ +void hdestroy (void) +{ + hdestroy_r (&htab); +} + +/* Make sure the table is freed if we want to free everything before + exiting. */ +/* text_set_element (__libc_subfreeres, __hdestroy); */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/search/hsearch_r.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/search/hsearch_r.c new file mode 100644 index 00000000..48bdf2d6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/search/hsearch_r.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_hsearch_r +#include "_hsearch_r.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/search/insque.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/search/insque.c new file mode 100644 index 00000000..fc5bf807 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/search/insque.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_insque +#include "insremque.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/search/insremque.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/search/insremque.c new file mode 100644 index 00000000..32edf7a4 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/search/insremque.c @@ -0,0 +1,54 @@ +/* Copyright (C) 1992, 1995, 1996 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include + +#ifdef L_insque + +/* Insert ELEM into a doubly-linked list, after PREV. */ + +void +insque (void *elem, void *prev) +{ + struct qelem *next = ((struct qelem *) prev)->q_forw; + ((struct qelem *) prev)->q_forw = (struct qelem *) elem; + if (next != NULL) + next->q_back = (struct qelem *) elem; + ((struct qelem *) elem)->q_forw = next; + ((struct qelem *) elem)->q_back = (struct qelem *) prev; +} + +#endif + +#ifdef L_remque +/* Unlink ELEM from the doubly-linked list that it is in. */ + +void +remque (void *elem) +{ + struct qelem *next = ((struct qelem *) elem)->q_forw; + struct qelem *prev = ((struct qelem *) elem)->q_back; + if (next != NULL) + next->q_back = prev; + if (prev != NULL) + prev->q_forw = (struct qelem *) next; +} + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/search/lfind.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/search/lfind.c new file mode 100644 index 00000000..66111c5a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/search/lfind.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_lfind +#include "_lsearch.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/search/lsearch.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/search/lsearch.c new file mode 100644 index 00000000..1e632975 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/search/lsearch.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_lsearch +#include "_lsearch.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/search/remque.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/search/remque.c new file mode 100644 index 00000000..bab69850 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/search/remque.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_remque +#include "insremque.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/search/tdelete.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/search/tdelete.c new file mode 100644 index 00000000..33d9fe8a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/search/tdelete.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_tdelete +#include "_tsearch.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/search/tdestroy.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/search/tdestroy.c new file mode 100644 index 00000000..3e397ea8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/search/tdestroy.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_tdestroy +#include "_tsearch.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/search/tfind.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/search/tfind.c new file mode 100644 index 00000000..e5a31617 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/search/tfind.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_tfind +#include "_tsearch.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/search/tsearch.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/search/tsearch.c new file mode 100644 index 00000000..8984fc1d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/search/tsearch.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_tsearch +#include "_tsearch.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/search/twalk.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/search/twalk.c new file mode 100644 index 00000000..f36d341f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/search/twalk.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_twalk +#include "_tsearch.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/statfs/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/statfs/Makefile new file mode 100644 index 00000000..4a8f4a07 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/statfs/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../ +top_builddir=../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/statfs/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/statfs/Makefile.in new file mode 100644 index 00000000..aa92d1f7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/statfs/Makefile.in @@ -0,0 +1,31 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +subdirs += libc/misc/statfs + +CSRC := statvfs.c fstatvfs.c +ifeq ($(UCLIBC_HAS_LFS),y) +ifeq ($(UCLIBC_LINUX_SPECIFIC),y) +CSRC += fstatfs64.c statfs64.c +endif +CSRC += statvfs64.c fstatvfs64.c +endif + +MISC_STATFS_DIR := $(top_srcdir)libc/misc/statfs +MISC_STATFS_OUT := $(top_builddir)libc/misc/statfs + +MISC_STATFS_SRC := $(patsubst %.c,$(MISC_STATFS_DIR)/%.c,$(CSRC)) +MISC_STATFS_OBJ := $(patsubst %.c,$(MISC_STATFS_OUT)/%.o,$(CSRC)) + +libc-y += $(MISC_STATFS_OBJ) + +libc-nomulti-$(UCLIBC_HAS_LFS) += $(MISC_STATFS_OUT)/statvfs64.o $(MISC_STATFS_OUT)/fstatvfs64.o + +objclean-y += CLEAN_libc/misc/statfs + +CLEAN_libc/misc/statfs: + $(do_rm) $(addprefix $(MISC_STATFS_OUT)/*., o os oS) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/statfs/fstatfs64.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/statfs/fstatfs64.c new file mode 100644 index 00000000..27bb8d60 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/statfs/fstatfs64.c @@ -0,0 +1,51 @@ +/* Return information about the filesystem on which FD resides. + Copyright (C) 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <_lfs_64.h> + +#include +#include +#include +#include +#include + +extern __typeof(fstatfs) __libc_fstatfs; + +/* Return information about the filesystem on which FD resides. */ +int fstatfs64 (int fd, struct statfs64 *buf) +{ + struct statfs buf32; + + if (__libc_fstatfs (fd, &buf32) < 0) + return -1; + + buf->f_type = buf32.f_type; + buf->f_bsize = buf32.f_bsize; + buf->f_blocks = buf32.f_blocks; + buf->f_bfree = buf32.f_bfree; + buf->f_bavail = buf32.f_bavail; + buf->f_files = buf32.f_files; + buf->f_ffree = buf32.f_ffree; + buf->f_fsid = buf32.f_fsid; + buf->f_namelen = buf32.f_namelen; + memcpy (buf->f_spare, buf32.f_spare, sizeof (buf32.f_spare)); + + return 0; +} +libc_hidden_def(fstatfs64) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/statfs/fstatvfs.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/statfs/fstatvfs.c new file mode 100644 index 00000000..63fce0fa --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/statfs/fstatvfs.c @@ -0,0 +1,60 @@ +/* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#ifndef __USE_FILE_OFFSET64 +extern int fstatfs (int __fildes, struct statfs *__buf) + __THROW __nonnull ((2)); +#else +# ifdef __REDIRECT_NTH +extern int __REDIRECT_NTH (fstatfs, (int __fildes, struct statfs *__buf), + fstatfs64) __nonnull ((2)); +# else +# define fstatfs fstatfs64 +# endif +#endif + +extern __typeof(fstatfs) __libc_fstatfs; + +int fstatvfs (int fd, struct statvfs *buf) +{ + struct statfs fsbuf; + struct stat st; + + /* Get as much information as possible from the system. */ + if (__libc_fstatfs (fd, &fsbuf) < 0) + return -1; + +#define STAT(st) fstat (fd, st) +#include "internal_statvfs.c" + + /* We signal success if the statfs call succeeded. */ + return 0; +} +libc_hidden_def(fstatvfs) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/statfs/fstatvfs64.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/statfs/fstatvfs64.c new file mode 100644 index 00000000..f57e9d9b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/statfs/fstatvfs64.c @@ -0,0 +1,68 @@ +/* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <_lfs_64.h> + +#include +#include +#include +#include +#include +#include +#include +#include + + +#undef stat +#define stat stat64 + +int fstatvfs64 (int fd, struct statvfs64 *buf) +{ + struct statfs64 fsbuf; + struct stat64 st; +#if !defined __UCLIBC_LINUX_SPECIFIC__ + int ret; + struct statvfs buf32; + + ret = fstatvfs (fd, &buf32); + if (ret == 0) { + fsbuf.f_bsize = buf32.f_bsize; + fsbuf.f_frsize = buf32.f_frsize; + fsbuf.f_blocks = buf32.f_blocks; + fsbuf.f_bfree = buf32.f_bfree; + fsbuf.f_bavail = buf32.f_bavail; + fsbuf.f_files = buf32.f_files; + fsbuf.f_ffree = buf32.f_ffree; + if (sizeof (fsbuf.f_fsid) == sizeof(buf32.f_fsid)) + memcpy (&fsbuf.f_fsid, &buf32.f_fsid, sizeof(fsbuf.f_fsid)); + /* and if not, then you could approximate or whatever.. */ + fsbuf.f_namelen = buf32.f_namemax; + } else + return ret; +#else + /* Get as much information as possible from the system. */ + if (fstatfs64 (fd, &fsbuf) < 0) + return -1; +#endif +#define STAT(st) fstat64 (fd, st) +#include "internal_statvfs.c" + + /* We signal success if the statfs call succeeded. */ + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/statfs/internal_statvfs.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/statfs/internal_statvfs.c new file mode 100644 index 00000000..6075e9cf --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/statfs/internal_statvfs.c @@ -0,0 +1,111 @@ +/* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + + /* Now fill in the fields we have information for. */ + buf->f_bsize = fsbuf.f_bsize; + /* Linux does not support f_frsize, so set it to the full block size. */ + buf->f_frsize = fsbuf.f_bsize; + buf->f_blocks = fsbuf.f_blocks; + buf->f_bfree = fsbuf.f_bfree; + buf->f_bavail = fsbuf.f_bavail; + buf->f_files = fsbuf.f_files; + buf->f_ffree = fsbuf.f_ffree; + if (sizeof (buf->f_fsid) == sizeof (fsbuf.f_fsid)) + buf->f_fsid = (fsbuf.f_fsid.__val[0] + | ((unsigned long int) fsbuf.f_fsid.__val[1] + << (8 * (sizeof (buf->f_fsid) + - sizeof (fsbuf.f_fsid.__val[0]))))); + else + /* We cannot help here. The statvfs element is not large enough to + contain both words of the statfs f_fsid field. */ + buf->f_fsid = fsbuf.f_fsid.__val[0]; +#ifdef _STATVFSBUF_F_UNUSED + buf->__f_unused = 0; +#endif + buf->f_namemax = fsbuf.f_namelen; + memset (buf->__f_spare, '\0', 6 * sizeof (int)); + + /* What remains to do is to fill the fields f_favail and f_flag. */ + + /* XXX I have no idea how to compute f_favail. Any idea??? */ + buf->f_favail = buf->f_ffree; + + /* Determining the flags is tricky. We have to read /proc/mounts or + the /etc/mtab file and search for the entry which matches the given + file. The way we can test for matching filesystem is using the + device number. */ + buf->f_flag = 0; + if (STAT (&st) >= 0) + { + int save_errno = errno; + struct mntent mntbuf; + FILE *mtab; + + mtab = setmntent ("/proc/mounts", "r"); + if (mtab == NULL) + mtab = setmntent (_PATH_MOUNTED, "r"); + + if (mtab != NULL) + { + char tmpbuf[1024]; + + while (getmntent_r (mtab, &mntbuf, tmpbuf, sizeof (tmpbuf))) + { + struct stat fsst; + + /* Find out about the device the current entry is for. */ + if (stat (mntbuf.mnt_dir, &fsst) >= 0 + && st.st_dev == fsst.st_dev) + { + /* Bingo, we found the entry for the device FD is on. + Now interpret the option string. */ + char *cp = mntbuf.mnt_opts; + char *opt; + + while ((opt = strsep (&cp, ",")) != NULL) + if (strcmp (opt, "ro") == 0) + buf->f_flag |= ST_RDONLY; + else if (strcmp (opt, "nosuid") == 0) + buf->f_flag |= ST_NOSUID; +#ifdef __USE_GNU + else if (strcmp (opt, "noexec") == 0) + buf->f_flag |= ST_NOEXEC; + else if (strcmp (opt, "nodev") == 0) + buf->f_flag |= ST_NODEV; + else if (strcmp (opt, "sync") == 0) + buf->f_flag |= ST_SYNCHRONOUS; + else if (strcmp (opt, "mand") == 0) + buf->f_flag |= ST_MANDLOCK; + else if (strcmp (opt, "noatime") == 0) + buf->f_flag |= ST_NOATIME; + else if (strcmp (opt, "nodiratime") == 0) + buf->f_flag |= ST_NODIRATIME; +#endif + + /* We can stop looking for more entries. */ + break; + } + } + + /* Close the file. */ + endmntent (mtab); + } + + __set_errno (save_errno); + } diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/statfs/statfs64.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/statfs/statfs64.c new file mode 100644 index 00000000..0cc8595d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/statfs/statfs64.c @@ -0,0 +1,49 @@ +/* Return information about the filesystem on which FILE resides. + Copyright (C) 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <_lfs_64.h> + +#include +#include +#include + +extern __typeof(statfs) __libc_statfs; + +/* Return information about the filesystem on which FILE resides. */ +int statfs64 (const char *file, struct statfs64 *buf) +{ + struct statfs buf32; + + if (__libc_statfs (file, &buf32) < 0) + return -1; + + buf->f_type = buf32.f_type; + buf->f_bsize = buf32.f_bsize; + buf->f_blocks = buf32.f_blocks; + buf->f_bfree = buf32.f_bfree; + buf->f_bavail = buf32.f_bavail; + buf->f_files = buf32.f_files; + buf->f_ffree = buf32.f_ffree; + buf->f_fsid = buf32.f_fsid; + buf->f_namelen = buf32.f_namelen; + memcpy (buf->f_spare, buf32.f_spare, sizeof (buf32.f_spare)); + + return 0; +} +libc_hidden_def(statfs64) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/statfs/statvfs.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/statfs/statvfs.c new file mode 100644 index 00000000..5ac38ed5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/statfs/statvfs.c @@ -0,0 +1,48 @@ +/* Copyright (C) 1998, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +extern __typeof(statfs) __libc_statfs; + +int statvfs (const char *file, struct statvfs *buf) +{ + struct statfs fsbuf; + struct stat st; + + /* Get as much information as possible from the system. */ + if (__libc_statfs (file, &fsbuf) < 0) + return -1; + +#define STAT(st) stat (file, st) +#include "internal_statvfs.c" + + /* We signal success if the statfs call succeeded. */ + return 0; +} +libc_hidden_def(statvfs) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/statfs/statvfs64.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/statfs/statvfs64.c new file mode 100644 index 00000000..9923e66a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/statfs/statvfs64.c @@ -0,0 +1,68 @@ +/* Copyright (C) 1998, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <_lfs_64.h> + +#include +#include +#include +#include +#include +#include +#include +#include + + +#undef stat +#define stat stat64 + +int statvfs64 (const char *file, struct statvfs64 *buf) +{ + struct statfs64 fsbuf; + struct stat64 st; +#if !defined __UCLIBC_LINUX_SPECIFIC__ + int ret; + struct statvfs buf32; + + ret = statvfs (file, &buf32); + if (ret == 0) { + fsbuf.f_bsize = buf32.f_bsize; + fsbuf.f_frsize = buf32.f_frsize; + fsbuf.f_blocks = buf32.f_blocks; + fsbuf.f_bfree = buf32.f_bfree; + fsbuf.f_bavail = buf32.f_bavail; + fsbuf.f_files = buf32.f_files; + fsbuf.f_ffree = buf32.f_ffree; + if (sizeof (fsbuf.f_fsid) == sizeof(buf32.f_fsid)) + memcpy (&fsbuf.f_fsid, &buf32.f_fsid, sizeof(fsbuf.f_fsid)); + /* and if not, then you could approximate or whatever.. */ + fsbuf.f_namelen = buf32.f_namemax; + } else + return ret; +#else + /* Get as much information as possible from the system. */ + if (statfs64 (file, &fsbuf) < 0) + return -1; +#endif +#define STAT(st) stat (file, st) +#include "internal_statvfs.c" + + /* We signal success if the statfs call succeeded. */ + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/syslog/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/syslog/Makefile new file mode 100644 index 00000000..4a8f4a07 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/syslog/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../ +top_builddir=../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/syslog/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/syslog/Makefile.in new file mode 100644 index 00000000..5cc4f523 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/syslog/Makefile.in @@ -0,0 +1,25 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +subdirs += libc/misc/syslog + +CSRC := syslog.c + +MISC_SYSLOG_DIR := $(top_srcdir)libc/misc/syslog +MISC_SYSLOG_OUT := $(top_builddir)libc/misc/syslog + +MISC_SYSLOG_SRC := $(patsubst %.c,$(MISC_SYSLOG_DIR)/%.c,$(CSRC)) +MISC_SYSLOG_OBJ := $(patsubst %.c,$(MISC_SYSLOG_OUT)/%.o,$(CSRC)) + +ifeq ($(UCLIBC_HAS_SYSLOG),y) +libc-y += $(MISC_SYSLOG_OBJ) +endif + +objclean-y += CLEAN_libc/misc/syslog + +CLEAN_libc/misc/syslog: + $(do_rm) $(addprefix $(MISC_SYSLOG_OUT)/*., o os) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/syslog/syslog.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/syslog/syslog.c new file mode 100644 index 00000000..b10a5561 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/syslog/syslog.c @@ -0,0 +1,343 @@ +/* + * Copyright (c) 1983, 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * SYSLOG -- print message on log file + * + * This routine looks a lot like printf, except that it outputs to the + * log file instead of the standard output. Also: + * adds a timestamp, + * prints the module name in front of the message, + * has some other formatting types (or will sometime), + * adds a newline on the end of the message. + * + * The output of this routine is intended to be read by syslogd(8). + * + * Author: Eric Allman + * Modified to use UNIX domain IPC by Ralph Campbell + * Patched March 12, 1996 by A. Ian Vogelesang + * - to correct the handling of message & format string truncation, + * - to visibly tag truncated records to facilitate + * investigation of such Bad Things with grep, and, + * - to correct the handling of case where "write" + * returns after writing only part of the message. + * Rewritten by Martin Mares on May 14, 1997 + * - better buffer overrun checks. + * - special handling of "%m" removed as we use GNU sprintf which handles + * it automatically. + * - Major code cleanup. + */ + +#define __FORCE_GLIBC +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include + +__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_MUTEX_INITIALIZER); + + +/* !glibc_compat: glibc uses argv[0] by default + * (default: if there was no openlog or if openlog passed NULL), + * not string "syslog" + */ +static const char *LogTag = "syslog"; /* string to tag the entry with */ +static int LogFile = -1; /* fd for log */ +static smalluint connected; /* have done connect */ +/* all bits in option argument for openlog fit in 8 bits */ +static smalluint LogStat = 0; /* status bits, set by openlog */ +/* default facility code if openlog is not called */ +/* (this fits in 8 bits even without >> 3 shift, but playing extra safe) */ +static smalluint LogFacility = LOG_USER >> 3; +/* bits mask of priorities to be logged (eight prios - 8 bits is enough) */ +static smalluint LogMask = 0xff; +/* AF_UNIX address of local logger (we use struct sockaddr + * instead of struct sockaddr_un since "/dev/log" is small enough) */ +static const struct sockaddr SyslogAddr = { + .sa_family = AF_UNIX, /* sa_family_t (usually a short) */ + .sa_data = _PATH_LOG /* char [14] */ +}; + +static void +closelog_intern(int sig) +{ + /* mylock must be held by the caller */ + if (LogFile != -1) { + (void) close(LogFile); + } + LogFile = -1; + connected = 0; + if (sig == 0) { /* called from closelog()? - reset to defaults */ + LogStat = 0; + LogTag = "syslog"; + LogFacility = LOG_USER >> 3; + LogMask = 0xff; + } +} + +static void +openlog_intern(const char *ident, int logstat, int logfac) +{ + int fd; + int logType = SOCK_DGRAM; + + if (ident != NULL) + LogTag = ident; + LogStat = logstat; + /* (we were checking also for logfac != 0, but it breaks + * openlog(xx, LOG_KERN) since LOG_KERN == 0) */ + if ((logfac & ~LOG_FACMASK) == 0) /* if we don't have invalid bits */ + LogFacility = (unsigned)logfac >> 3; + + fd = LogFile; + if (fd == -1) { + retry: + if (logstat & LOG_NDELAY) { + LogFile = fd = socket(AF_UNIX, logType, 0); + if (fd == -1) { + return; + } + fcntl(fd, F_SETFD, FD_CLOEXEC); + /* We don't want to block if e.g. syslogd is SIGSTOPed */ + fcntl(fd, F_SETFL, O_NONBLOCK | fcntl(fd, F_GETFL)); + } + } + + if (fd != -1 && !connected) { + if (connect(fd, &SyslogAddr, sizeof(SyslogAddr)) != -1) { + connected = 1; + } else { + if (fd != -1) { + close(fd); + LogFile = fd = -1; + } + if (logType == SOCK_DGRAM) { + logType = SOCK_STREAM; + goto retry; + } + } + } +} + +/* + * OPENLOG -- open system log + */ +void +openlog(const char *ident, int logstat, int logfac) +{ + __UCLIBC_MUTEX_LOCK(mylock); + openlog_intern(ident, logstat, logfac); + __UCLIBC_MUTEX_UNLOCK(mylock); +} +libc_hidden_def(openlog) + +/* + * syslog, vsyslog -- + * print message on log file; output is intended for syslogd(8). + */ +void +vsyslog(int pri, const char *fmt, va_list ap) +{ + register char *p; + char *last_chr, *head_end, *end, *stdp; + time_t now; + int fd, saved_errno; + int rc; + char tbuf[1024]; /* syslogd is unable to handle longer messages */ + + /* Just throw out this message if pri has bad bits. */ + if ((pri & ~(LOG_PRIMASK|LOG_FACMASK)) != 0) + return; + + saved_errno = errno; + + __UCLIBC_MUTEX_LOCK(mylock); + + /* See if we should just throw out this message according to LogMask. */ + if ((LogMask & LOG_MASK(LOG_PRI(pri))) == 0) + goto getout; + if (LogFile < 0 || !connected) + openlog_intern(NULL, LogStat | LOG_NDELAY, LOG_USER); + + /* Set default facility if none specified. */ + if ((pri & LOG_FACMASK) == 0) + pri |= ((int)LogFacility << 3); + + /* Build the message. We know the starting part of the message can take + * no longer than 64 characters plus length of the LogTag. So it's + * safe to test only LogTag and use normal sprintf everywhere else. + */ + (void)time(&now); + stdp = p = tbuf + sprintf(tbuf, "<%d>%.15s ", pri, ctime(&now) + 4); + /*if (LogTag) - always true */ { + if (strlen(LogTag) < sizeof(tbuf) - 64) + p += sprintf(p, "%s", LogTag); + else + p += sprintf(p, ""); + } + if (LogStat & LOG_PID) + p += sprintf(p, "[%d]", getpid()); + /*if (LogTag) - always true */ { + *p++ = ':'; + *p++ = ' '; + } + head_end = p; + + /* We format the rest of the message. If the buffer becomes full, we mark + * the message as truncated. Note that we require at least 2 free bytes + * in the buffer as we might want to add "\r\n" there. + */ + + end = tbuf + sizeof(tbuf) - 1; + __set_errno(saved_errno); + p += vsnprintf(p, end - p, fmt, ap); + if (p >= end || p < head_end) { /* Returned -1 in case of error... */ + static const char truncate_msg[12] = "[truncated] "; /* no NUL! */ + memmove(head_end + sizeof(truncate_msg), head_end, + end - head_end - sizeof(truncate_msg)); + memcpy(head_end, truncate_msg, sizeof(truncate_msg)); + if (p < head_end) { + while (p < end && *p) { + p++; + } + } + else { + p = end - 1; + } + + } + last_chr = p; + + /* Output to stderr if requested. */ + if (LogStat & LOG_PERROR) { + *last_chr = '\n'; + (void)write(STDERR_FILENO, stdp, last_chr - stdp + 1); + } + + /* Output the message to the local logger using NUL as a message delimiter. */ + p = tbuf; + *last_chr = '\0'; + if (LogFile >= 0) { + do { + /* can't just use write, it can result in SIGPIPE */ + rc = send(LogFile, p, last_chr + 1 - p, MSG_NOSIGNAL); + if (rc < 0) { + /* I don't think looping forever on EAGAIN is a good idea. + * Imagine that syslogd is SIGSTOPed... */ + if (/* (errno != EAGAIN) && */ (errno != EINTR)) { + closelog_intern(1); /* 1: do not reset LogXXX globals to default */ + goto write_err; + } + rc = 0; + } + p += rc; + } while (p <= last_chr); + goto getout; + } + + write_err: + /* + * Output the message to the console; don't worry about blocking, + * if console blocks everything will. Make sure the error reported + * is the one from the syslogd failure. + */ + /* should mode be O_WRONLY | O_NOCTTY? -- Uli */ + /* yes, but in Linux "/dev/console" never becomes ctty anyway -- vda */ + if ((LogStat & LOG_CONS) && + (fd = open(_PATH_CONSOLE, O_WRONLY | O_NOCTTY)) >= 0) { + p = strchr(tbuf, '>') + 1; + last_chr[0] = '\r'; + last_chr[1] = '\n'; + (void)write(fd, p, last_chr - p + 2); + (void)close(fd); + } + + getout: + __UCLIBC_MUTEX_UNLOCK(mylock); +} +libc_hidden_def(vsyslog) + +void +syslog(int pri, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + vsyslog(pri, fmt, ap); + va_end(ap); +} +libc_hidden_def(syslog) + +/* + * CLOSELOG -- close the system log + */ +void +closelog(void) +{ + __UCLIBC_MUTEX_LOCK(mylock); + closelog_intern(0); /* 0: reset LogXXX globals to default */ + __UCLIBC_MUTEX_UNLOCK(mylock); +} +libc_hidden_def(closelog) + +/* setlogmask -- set the log mask level */ +int setlogmask(int pmask) +{ + int omask; + + omask = LogMask; + if (pmask != 0) { + __UCLIBC_MUTEX_LOCK(mylock); + LogMask = pmask; + __UCLIBC_MUTEX_UNLOCK(mylock); + } + return omask; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/sysvipc/.indent.pro b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/sysvipc/.indent.pro new file mode 100644 index 00000000..492ecf1c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/sysvipc/.indent.pro @@ -0,0 +1,33 @@ +--blank-lines-after-declarations +--blank-lines-after-procedures +--break-before-boolean-operator +--no-blank-lines-after-commas +--braces-on-if-line +--braces-on-struct-decl-line +--comment-indentation25 +--declaration-comment-column25 +--no-comment-delimiters-on-blank-lines +--cuddle-else +--continuation-indentation4 +--case-indentation0 +--else-endif-column33 +--space-after-cast +--line-comments-indentation0 +--declaration-indentation1 +--dont-format-first-column-comments +--dont-format-comments +--honour-newlines +--indent-level4 +/* changed from 0 to 4 */ +--parameter-indentation4 +--line-length78 /* changed from 75 */ +--continue-at-parentheses +--no-space-after-function-call-names +--dont-break-procedure-type +--dont-star-comments +--leave-optional-blank-lines +--dont-space-special-semicolon +--tab-size4 +/* additions by Mark */ +--case-brace-indentation0 +--leave-preprocessor-space diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/sysvipc/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/sysvipc/Makefile new file mode 100644 index 00000000..4a8f4a07 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/sysvipc/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../ +top_builddir=../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/sysvipc/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/sysvipc/Makefile.in new file mode 100644 index 00000000..115cfc67 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/sysvipc/Makefile.in @@ -0,0 +1,32 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +subdirs += libc/misc/sysvipc + +CSRC := ftok.c __syscall_ipc.c + +# multi source sem.c +CSRC += semget.c semctl.c semop.c semtimedop.c + +# multi source shm.c +CSRC += shmat.c shmctl.c shmdt.c shmget.c + +# multi source msgq.c +CSRC += msgctl.c msgget.c msgrcv.c msgsnd.c + +MISC_SYSVIPC_DIR := $(top_srcdir)libc/misc/sysvipc +MISC_SYSVIPC_OUT := $(top_builddir)libc/misc/sysvipc + +MISC_SYSVIPC_SRC := $(patsubst %.c,$(MISC_SYSVIPC_DIR)/%.c,$(CSRC)) +MISC_SYSVIPC_OBJ := $(patsubst %.c,$(MISC_SYSVIPC_OUT)/%.o,$(CSRC)) + +libc-y += $(MISC_SYSVIPC_OBJ) + +objclean-y += CLEAN_libc/misc/sysvipc + +CLEAN_libc/misc/sysvipc: + $(do_rm) $(addprefix $(MISC_SYSVIPC_OUT)/*., o os) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/sysvipc/__syscall_ipc.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/sysvipc/__syscall_ipc.c new file mode 100644 index 00000000..304a42c2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/sysvipc/__syscall_ipc.c @@ -0,0 +1,17 @@ +/* vi: set sw=4 ts=4: */ +/* + * __syscall_ipc() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +#ifdef __NR_ipc +#define __NR___syscall_ipc __NR_ipc +#include "ipc.h" +_syscall6(int, __syscall_ipc, unsigned int, call, long, first, long, second, long, + third, void *, ptr, void *, fifth) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/sysvipc/ftok.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/sysvipc/ftok.c new file mode 100644 index 00000000..d855e3d2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/sysvipc/ftok.c @@ -0,0 +1,36 @@ +/* Copyright (C) 1995, 1996 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , August 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + + +key_t ftok (const char *pathname, int proj_id) +{ + struct stat st; + key_t key; + + if (stat(pathname, &st) < 0) + return (key_t) -1; + + key = ((st.st_ino & 0xffff) | ((st.st_dev & 0xff) << 16) + | ((proj_id & 0xff) << 24)); + + return key; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/sysvipc/ipc.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/sysvipc/ipc.h new file mode 100644 index 00000000..339d1364 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/sysvipc/ipc.h @@ -0,0 +1,35 @@ +#ifndef IPC_H +#define IPC_H +#include +#include + +#if __WORDSIZE == 32 || defined __alpha__ || defined __mips__ +# define __IPC_64 0x100 +#else +# define __IPC_64 0x0 +#endif + +#ifdef __NR_ipc + +/* The actual system call: all functions are multiplexed by this. */ +extern int __syscall_ipc (unsigned int __call, long __first, long __second, + long __third, void *__ptr, void *__fifth) attribute_hidden; + + +/* The codes for the functions to use the multiplexer `__syscall_ipc'. */ +#define IPCOP_semop 1 +#define IPCOP_semget 2 +#define IPCOP_semctl 3 +#define IPCOP_semtimedop 4 +#define IPCOP_msgsnd 11 +#define IPCOP_msgrcv 12 +#define IPCOP_msgget 13 +#define IPCOP_msgctl 14 +#define IPCOP_shmat 21 +#define IPCOP_shmdt 22 +#define IPCOP_shmget 23 +#define IPCOP_shmctl 24 + +#endif + +#endif /* IPC_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/sysvipc/msgctl.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/sysvipc/msgctl.c new file mode 100644 index 00000000..480a54cb --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/sysvipc/msgctl.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_msgctl +#include "msgq.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/sysvipc/msgget.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/sysvipc/msgget.c new file mode 100644 index 00000000..f7e54d5c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/sysvipc/msgget.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_msgget +#include "msgq.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/sysvipc/msgq.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/sysvipc/msgq.c new file mode 100644 index 00000000..27eb1ff9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/sysvipc/msgq.c @@ -0,0 +1,112 @@ +#include +#include +#include "ipc.h" +#ifdef __UCLIBC_HAS_THREADS_NATIVE__ +#include "sysdep-cancel.h" +#else +#define SINGLE_THREAD_P 1 +#endif + + +#ifdef L_msgctl + +#ifdef __NR_msgctl +#define __NR___libc_msgctl __NR_msgctl +static __inline__ _syscall3(int, __libc_msgctl, int, msqid, int, cmd, struct msqid_ds *, buf); +#endif +/* Message queue control operation. */ +int msgctl(int msqid, int cmd, struct msqid_ds *buf) +{ +#ifdef __NR_msgctl + return __libc_msgctl(msqid, cmd | __IPC_64, buf); +#else + return __syscall_ipc(IPCOP_msgctl, msqid, cmd | __IPC_64, 0, buf, 0); +#endif +} +#endif + + +#ifdef L_msgget +#ifdef __NR_msgget +_syscall2(int, msgget, key_t, key, int, msgflg) +#else +/* Get messages queue. */ +int msgget (key_t key, int msgflg) +{ + return __syscall_ipc(IPCOP_msgget ,key ,msgflg ,0 ,0, 0); +} +#endif +#endif + + +struct new_msg_buf{ + struct msgbuf * oldmsg; + long int r_msgtyp; /* the fifth arg of __syscall_ipc */ +}; +/* Receive message from message queue. */ + + +#ifdef L_msgrcv +#ifdef __NR_msgrcv +#define __NR___syscall_msgrcv __NR_msgrcv +static inline _syscall5(ssize_t, __syscall_msgrcv, int, msqid, void *, msgp, + size_t, msgsz, long int, msgtyp, int, msgflg) +#endif +static inline ssize_t do_msgrcv (int msqid, void *msgp, size_t msgsz, + long int msgtyp, int msgflg) +{ +#ifdef __NR_msgrcv + return __syscall_msgrcv(msqid, msgp, msgsz, msgtyp, msgflg); +#else + struct new_msg_buf temp; + + temp.r_msgtyp = msgtyp; + temp.oldmsg = msgp; + return __syscall_ipc(IPCOP_msgrcv ,msqid ,msgsz ,msgflg ,&temp, 0); +#endif +} +ssize_t msgrcv (int msqid, void *msgp, size_t msgsz, + long int msgtyp, int msgflg) +{ + if (SINGLE_THREAD_P) + return do_msgrcv(msqid, msgp, msgsz, msgtyp, msgflg); +#ifdef __UCLIBC_HAS_THREADS_NATIVE__ + int oldtype = LIBC_CANCEL_ASYNC (); + int result = do_msgrcv(msqid, msgp, msgsz, msgtyp, msgflg); + LIBC_CANCEL_RESET (oldtype); + return result; +#endif +} +#endif + + + +#ifdef L_msgsnd +#ifdef __NR_msgsnd +#define __NR___syscall_msgsnd __NR_msgsnd +static inline _syscall4(int, __syscall_msgsnd, int, msqid, const void *, msgp, + size_t, msgsz, int, msgflg) +#endif +/* Send message to message queue. */ +static inline int do_msgsnd (int msqid, const void *msgp, size_t msgsz, + int msgflg) +{ +#ifdef __NR_msgsnd + return __syscall_msgsnd(msqid, msgp, msgsz, msgflg); +#else + return __syscall_ipc(IPCOP_msgsnd, msqid, msgsz, msgflg, (void *)msgp, 0); +#endif +} +int msgsnd (int msqid, const void *msgp, size_t msgsz, int msgflg) +{ + if (SINGLE_THREAD_P) + return do_msgsnd(msqid, msgp, msgsz, msgflg); +#ifdef __UCLIBC_HAS_THREADS_NATIVE__ + int oldtype = LIBC_CANCEL_ASYNC (); + int result = do_msgsnd(msqid, msgp, msgsz, msgflg); + LIBC_CANCEL_RESET (oldtype); + return result; +#endif +} +#endif + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/sysvipc/msgrcv.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/sysvipc/msgrcv.c new file mode 100644 index 00000000..a85e52a9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/sysvipc/msgrcv.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_msgrcv +#include "msgq.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/sysvipc/msgsnd.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/sysvipc/msgsnd.c new file mode 100644 index 00000000..9f09d1fd --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/sysvipc/msgsnd.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_msgsnd +#include "msgq.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/sysvipc/sem.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/sysvipc/sem.c new file mode 100644 index 00000000..e340216e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/sysvipc/sem.c @@ -0,0 +1,105 @@ +/* Copyright (C) 1995, 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , August 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include /* for NULL */ + +#include "ipc.h" + + +#ifdef L_semctl +/* Return identifier for array of NSEMS semaphores associated with + KEY. */ +#include +/* arg for semctl system calls. */ +union semun { + int val; /* value for SETVAL */ + struct semid_ds *buf; /* buffer for IPC_STAT & IPC_SET */ + unsigned short *array; /* array for GETALL & SETALL */ + struct seminfo *__buf; /* buffer for IPC_INFO */ + void *__pad; +}; + + +#ifdef __NR_semctl +#define __NR___semctl __NR_semctl +static __inline__ _syscall4(int, __semctl, int, semid, int, semnum, int, cmd, void *, arg); +#endif + +int semctl(int semid, int semnum, int cmd, ...) +{ + union semun arg; + va_list ap; + + /* Get the argument. */ + va_start (ap, cmd); + arg = va_arg (ap, union semun); + va_end (ap); +#ifdef __NR_semctl + return __semctl(semid, semnum, cmd | __IPC_64, arg.__pad); +#else + return __syscall_ipc(IPCOP_semctl, semid, semnum, cmd|__IPC_64, &arg, NULL); +#endif +} +#endif + +#ifdef L_semget +#ifdef __NR_semget +_syscall3(int, semget, key_t, key, int, nsems, int, semflg) + +#else +/* Return identifier for array of NSEMS semaphores associated + * with KEY. */ +int semget (key_t key, int nsems, int semflg) +{ + return __syscall_ipc(IPCOP_semget, key, nsems, semflg, NULL, 0); +} +#endif +#endif + +#ifdef L_semop + +#ifdef __NR_semop +_syscall3(int, semop, int, semid, struct sembuf *, sops, size_t, nsops) + +#else +/* Perform user-defined atomical operation of array of semaphores. */ +int semop (int semid, struct sembuf *sops, size_t nsops) +{ + return __syscall_ipc(IPCOP_semop, semid, (int) nsops, 0, sops, NULL); +} +#endif +#endif + +#ifdef L_semtimedop + +#ifdef __NR_semtimedop +_syscall4(int, semtimedop, int, semid, struct sembuf *, sops, size_t, nsops, const struct timespec *, timeout) + +#else + +int semtimedop(int semid, struct sembuf *sops, size_t nsops, + const struct timespec *timeout) +{ + return __syscall_ipc(IPCOP_semtimedop, semid, nsops, 0, sops, (void *) timeout); +} +#endif +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/sysvipc/semctl.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/sysvipc/semctl.c new file mode 100644 index 00000000..df62a76e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/sysvipc/semctl.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_semctl +#include "sem.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/sysvipc/semget.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/sysvipc/semget.c new file mode 100644 index 00000000..94d0b5da --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/sysvipc/semget.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_semget +#include "sem.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/sysvipc/semop.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/sysvipc/semop.c new file mode 100644 index 00000000..0c67f62f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/sysvipc/semop.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_semop +#include "sem.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/sysvipc/semtimedop.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/sysvipc/semtimedop.c new file mode 100644 index 00000000..ecd0438f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/sysvipc/semtimedop.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_semtimedop +#include "sem.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/sysvipc/shm.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/sysvipc/shm.c new file mode 100644 index 00000000..4b7ea075 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/sysvipc/shm.c @@ -0,0 +1,95 @@ +/* Copyright (C) 1995, 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , August 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* SHMLBA uses it on most of the archs (not mips) */ +#define __getpagesize getpagesize + +#include +#include +#include +#include +#include "ipc.h" + +#ifdef L_shmat +/* Attach the shared memory segment associated with SHMID to the data + segment of the calling process. SHMADDR and SHMFLG determine how + and where the segment is attached. */ +#if defined(__NR_osf_shmat) +# define __NR_shmat __NR_osf_shmat +#endif +#ifdef __NR_shmat +_syscall3(void *, shmat, int, shmid, const void *,shmaddr, int, shmflg) +#else +/* psm: don't remove this, else mips will fail */ +#include + +void * shmat (int shmid, const void *shmaddr, int shmflg) +{ + int retval; + unsigned long raddr; + + retval = __syscall_ipc(IPCOP_shmat, shmid, shmflg, (int) &raddr, (void *) shmaddr, 0); + return ((unsigned long int) retval > -(unsigned long int) SHMLBA + ? (void *) retval : (void *) raddr); +} +#endif +#endif + +#ifdef L_shmctl +/* Provide operations to control over shared memory segments. */ +#ifdef __NR_shmctl +#define __NR___libc_shmctl __NR_shmctl +static __inline__ _syscall3(int, __libc_shmctl, int, shmid, int, cmd, struct shmid_ds *, buf); +#endif +int shmctl(int shmid, int cmd, struct shmid_ds *buf) +{ +#ifdef __NR_shmctl + return __libc_shmctl(shmid, cmd | __IPC_64, buf); +#else + return __syscall_ipc(IPCOP_shmctl, shmid, cmd | __IPC_64, 0, buf, 0); +#endif +} +#endif + + +#ifdef L_shmdt +/* Detach shared memory segment starting at address specified by SHMADDR + from the caller's data segment. */ +#ifdef __NR_shmdt +_syscall1(int, shmdt, const void *, shmaddr) +#else +int shmdt (const void *shmaddr) +{ + return __syscall_ipc(IPCOP_shmdt, 0, 0, 0, (void *) shmaddr, 0); +} +#endif +#endif + +#ifdef L_shmget +/* Return an identifier for an shared memory segment of at least size SIZE + which is associated with KEY. */ +#ifdef __NR_shmget +_syscall3(int, shmget, key_t, key, size_t, size, int, shmflg) +#else +int shmget (key_t key, size_t size, int shmflg) +{ + return __syscall_ipc(IPCOP_shmget, key, size, shmflg, NULL, 0); +} +#endif +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/sysvipc/shmat.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/sysvipc/shmat.c new file mode 100644 index 00000000..d6cd22a5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/sysvipc/shmat.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_shmat +#include "shm.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/sysvipc/shmctl.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/sysvipc/shmctl.c new file mode 100644 index 00000000..90fab5a2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/sysvipc/shmctl.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_shmctl +#include "shm.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/sysvipc/shmdt.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/sysvipc/shmdt.c new file mode 100644 index 00000000..07833413 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/sysvipc/shmdt.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_shmdt +#include "shm.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/sysvipc/shmget.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/sysvipc/shmget.c new file mode 100644 index 00000000..4778e361 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/sysvipc/shmget.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_shmget +#include "shm.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/.indent.pro b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/.indent.pro new file mode 100644 index 00000000..492ecf1c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/.indent.pro @@ -0,0 +1,33 @@ +--blank-lines-after-declarations +--blank-lines-after-procedures +--break-before-boolean-operator +--no-blank-lines-after-commas +--braces-on-if-line +--braces-on-struct-decl-line +--comment-indentation25 +--declaration-comment-column25 +--no-comment-delimiters-on-blank-lines +--cuddle-else +--continuation-indentation4 +--case-indentation0 +--else-endif-column33 +--space-after-cast +--line-comments-indentation0 +--declaration-indentation1 +--dont-format-first-column-comments +--dont-format-comments +--honour-newlines +--indent-level4 +/* changed from 0 to 4 */ +--parameter-indentation4 +--line-length78 /* changed from 75 */ +--continue-at-parentheses +--no-space-after-function-call-names +--dont-break-procedure-type +--dont-star-comments +--leave-optional-blank-lines +--dont-space-special-semicolon +--tab-size4 +/* additions by Mark */ +--case-brace-indentation0 +--leave-preprocessor-space diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/Makefile new file mode 100644 index 00000000..4a8f4a07 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../ +top_builddir=../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/Makefile.in new file mode 100644 index 00000000..78f01ad8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/Makefile.in @@ -0,0 +1,43 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +subdirs += libc/misc/time + +CSRC := adjtime.c +ifeq ($(UCLIBC_SUSV3_LEGACY),y) +CSRC += ftime.c +endif +# multi source time.c +CSRC += asctime.c asctime_r.c clock.c ctime.c ctime_r.c gmtime.c gmtime_r.c \ + localtime.c localtime_r.c mktime.c strftime.c strptime.c tzset.c \ + _time_t2tm.c __time_tm.c _time_mktime.c dysize.c timegm.c \ + _time_mktime_tzi.c _time_localtime_tzi.c +ifeq ($(UCLIBC_HAS_FLOATS),y) +CSRC += difftime.c +endif +ifeq ($(UCLIBC_HAS_XLOCALE),y) +CSRC += strftime_l.c strptime_l.c +endif +ifeq ($(UCLIBC_HAS_WCHAR),y) +CSRC += wcsftime.c +ifeq ($(UCLIBC_HAS_XLOCALE),y) +CSRC += wcsftime_l.c +endif +endif + +MISC_TIME_DIR := $(top_srcdir)libc/misc/time +MISC_TIME_OUT := $(top_builddir)libc/misc/time + +MISC_TIME_SRC := $(patsubst %.c,$(MISC_TIME_DIR)/%.c,$(CSRC)) +MISC_TIME_OBJ := $(patsubst %.c,$(MISC_TIME_OUT)/%.o,$(CSRC)) + +libc-y += $(MISC_TIME_OBJ) + +objclean-y += CLEAN_libc/misc/time + +CLEAN_libc/misc/time: + $(do_rm) $(addprefix $(MISC_TIME_OUT)/*., o os) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/__time_tm.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/__time_tm.c new file mode 100644 index 00000000..59b7d8aa --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/__time_tm.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L___time_tm +#include "time.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/_time_localtime_tzi.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/_time_localtime_tzi.c new file mode 100644 index 00000000..32728a49 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/_time_localtime_tzi.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L__time_localtime_tzi +#include "time.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/_time_mktime.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/_time_mktime.c new file mode 100644 index 00000000..1fd92002 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/_time_mktime.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L__time_mktime +#include "time.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/_time_mktime_tzi.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/_time_mktime_tzi.c new file mode 100644 index 00000000..543893e6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/_time_mktime_tzi.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L__time_mktime_tzi +#include "time.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/_time_t2tm.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/_time_t2tm.c new file mode 100644 index 00000000..903651ff --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/_time_t2tm.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L__time_t2tm +#include "time.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/adjtime.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/adjtime.c new file mode 100644 index 00000000..1e808710 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/adjtime.c @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include + + +#define MAX_SEC (LONG_MAX / 1000000L - 2) +#define MIN_SEC (LONG_MIN / 1000000L + 2) + +#ifndef MOD_OFFSET +#define modes mode +#endif + +int +adjtime(const struct timeval * itv, struct timeval * otv) +{ + struct timex tntx; + + if (itv) + { + struct timeval tmp; + + /* We will do some check here. */ + tmp.tv_sec = itv->tv_sec + itv->tv_usec / 1000000L; + tmp.tv_usec = itv->tv_usec % 1000000L; + if (tmp.tv_sec > MAX_SEC || tmp.tv_sec < MIN_SEC) + { + __set_errno(EINVAL); + return -1; + } + tntx.offset = tmp.tv_usec + tmp.tv_sec * 1000000L; + tntx.modes = ADJ_OFFSET_SINGLESHOT; + } + else + { + tntx.modes = 0; + } + if (adjtimex(&tntx) < 0) return -1; + if (otv) { + if (tntx.offset < 0) + { + otv->tv_usec = -(-tntx.offset % 1000000); + otv->tv_sec = -(-tntx.offset / 1000000); + } + else + { + otv->tv_usec = tntx.offset % 1000000; + otv->tv_sec = tntx.offset / 1000000; + } + } + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/asctime.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/asctime.c new file mode 100644 index 00000000..d80c017a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/asctime.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_asctime +#include "time.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/asctime_r.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/asctime_r.c new file mode 100644 index 00000000..aec38b13 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/asctime_r.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_asctime_r +#include "time.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/clock.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/clock.c new file mode 100644 index 00000000..9cc42541 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/clock.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_clock +#include "time.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/ctime.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/ctime.c new file mode 100644 index 00000000..4bd09a8a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/ctime.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_ctime +#include "time.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/ctime_r.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/ctime_r.c new file mode 100644 index 00000000..c03f5c95 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/ctime_r.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_ctime_r +#include "time.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/difftime.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/difftime.c new file mode 100644 index 00000000..4bcec2c0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/difftime.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_difftime +#include "time.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/dysize.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/dysize.c new file mode 100644 index 00000000..b1bf84b6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/dysize.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_dysize +#include "time.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/ftime.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/ftime.c new file mode 100644 index 00000000..ff78d418 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/ftime.c @@ -0,0 +1,38 @@ +/* Copyright (C) 1994, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + + +int ftime(struct timeb *timebuf) +{ + struct timeval tv; + struct timezone tz; + + /* In Linux, gettimeofday fails only on bad parameter. + * We know that here parameters aren't bad. + */ + gettimeofday (&tv, &tz); + + timebuf->time = tv.tv_sec; + timebuf->millitm = (tv.tv_usec + 999) / 1000; + timebuf->timezone = tz.tz_minuteswest; + timebuf->dstflag = tz.tz_dsttime; + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/gmtime.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/gmtime.c new file mode 100644 index 00000000..24a512c0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/gmtime.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_gmtime +#include "time.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/gmtime_r.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/gmtime_r.c new file mode 100644 index 00000000..8677dd2d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/gmtime_r.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_gmtime_r +#include "time.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/localtime.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/localtime.c new file mode 100644 index 00000000..e4bffbd2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/localtime.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_localtime +#include "time.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/localtime_r.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/localtime_r.c new file mode 100644 index 00000000..5351834b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/localtime_r.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_localtime_r +#include "time.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/mktime.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/mktime.c new file mode 100644 index 00000000..2b2c8e45 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/mktime.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_mktime +#include "time.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/strftime.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/strftime.c new file mode 100644 index 00000000..2eb827da --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/strftime.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_strftime +#include "time.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/strftime_l.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/strftime_l.c new file mode 100644 index 00000000..e1d34ad4 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/strftime_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_strftime_l +#define __UCLIBC_DO_XLOCALE +#include "time.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/strptime.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/strptime.c new file mode 100644 index 00000000..771633fb --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/strptime.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_strptime +#include "time.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/strptime_l.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/strptime_l.c new file mode 100644 index 00000000..16ee7e1b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/strptime_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_strptime_l +#define __UCLIBC_DO_XLOCALE +#include "time.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/time.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/time.c new file mode 100644 index 00000000..ff44892a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/time.c @@ -0,0 +1,2485 @@ +/* Copyright (C) 2002-2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +/* June 15, 2002 Initial Notes: + * + * Note: It is assumed throught that time_t is either long or unsigned long. + * Similarly, clock_t is assumed to be long int. + * + * Warning: Assumptions are made about the layout of struct tm! It is + * assumed that the initial fields of struct tm are (in order): + * tm_sec, tm_min, tm_hour, tm_mday, tm_mon, tm_year, tm_wday, tm_yday + * + * Reached the inital goal of supporting the ANSI/ISO C99 time functions + * as well as SUSv3's strptime. All timezone info is obtained from the + * TZ env variable. + * + * Differences from glibc worth noting: + * + * Leap seconds are not considered here. + * + * glibc stores additional timezone info the struct tm, whereas we don't. + * + * Alternate digits and era handling are not currently implemented. + * The modifiers are accepted, and tested for validity with the following + * specifier, but are ignored otherwise. + * + * strftime does not implement glibc extension modifiers or widths for + * conversion specifiers. However it does implement the glibc + * extension specifiers %l, %k, and %s. It also recognizes %P, but + * treats it as a synonym for %p; i.e. doesn't convert to lower case. + * + * strptime implements the glibc extension specifiers. However, it follows + * SUSv3 in requiring at least one non-alphanumeric char between + * conversion specifiers. Also, strptime only sets struct tm fields + * for which format specifiers appear and does not try to infer other + * fields (such as wday) as glibc's version does. + * + * TODO - Since glibc's %l and %k can space-pad their output in strftime, + * it might be reasonable to eat whitespace first for those specifiers. + * This could be done by pushing " %I" and " %H" respectively so that + * leading whitespace is consumed. This is really only an issue if %l + * or %k occurs at the start of the format string. + * + * TODO - Implement getdate? tzfile? struct tm extensions? + * + * TODO - Rework _time_mktime to remove the dependency on long long. + */ + +/* Oct 28, 2002 + * + * Fixed allowed char check for std and dst TZ fields. + * + * Added several options concerned with timezone support. The names will + * probably change once Erik gets the new config system in place. + * + * Defining __TIME_TZ_FILE causes tzset() to attempt to read the TZ value + * from the file /etc/TZ if the TZ env variable isn't set. The file contents + * must be the intended value of TZ, followed by a newline. No other chars, + * spacing, etc is allowed. As an example, an easy way for me to init + * /etc/TZ appropriately would be: echo CST6CDT > /etc/TZ + * + * Defining __TIME_TZ_FILE_ONCE will cause all further accesses of /etc/TZ + * to be skipped once a legal value has been read. + * + * Defining __TIME_TZ_OPT_SPEED will cause a tzset() to keep a copy of the + * last TZ setting string and do a "fast out" if the current string is the + * same. + * + * Nov 21, 2002 Fix an error return case in _time_mktime. + * + * Nov 26, 2002 Fix bug in setting daylight and timezone when no (valid) TZ. + * Bug reported by Arne Bernin in regards to freeswan. + * + * July 27, 2003 Adjust the struct tm extension field support. + * Change __tm_zone back to a ptr and add the __tm_tzname[] buffer for + * __tm_zone to point to. This gets around complaints from g++. + * Who knows... it might even fix the PPC timezone init problem. + * + * July 29, 2003 Fix a bug in mktime behavior when tm_isdst was -1. + * Bug reported by "Sid Wade" in regards to busybox. + * + * NOTE: uClibc mktime behavior is different than glibc's when + * the struct tm has tm_isdst == -1 and also had fields outside of + * the normal ranges. + * + * Apparently, glibc examines (at least) tm_sec and guesses the app's + * intention of assuming increasing or decreasing time when entering an + * ambiguous time period at the dst<->st boundaries. + * + * The uClibc behavior is to always normalize the struct tm and then + * try to determing the dst setting. + * + * As long as tm_isdst != -1 or the time specifiec by struct tm is + * unambiguous (not falling in the dst<->st transition region) both + * uClibc and glibc should produce the same result for mktime. + * + * Oct 31, 2003 Kill the seperate __tm_zone and __tm_tzname[] and which + * doesn't work if you want the memcpy the struct. Sigh... I didn't + * think about that. So now, when the extensions are enabled, we + * malloc space when necessary and keep the timezone names in a linked + * list. + * + * Fix a dst-related bug which resulted in use of uninitialized data. + * + * Nov 15, 2003 I forgot to update the thread locking in the last dst fix. + * + * Dec 14, 2003 Fix some dst issues in _time_mktime(). + * Normalize the tm_isdst value to -1, 0, or 1. + * If no dst for this timezone, then reset tm_isdst to 0. + * + * May 7, 2004 + * Change clock() to allow wrapping. + * Add timegm() function. + * Make lookup_tzname() static (as it should have been). + * Have strftime() get timezone information from the passed struct + * for the %z and %Z conversions when using struct tm extensions. + * + * Jul 24, 2004 + * Fix 2 bugs in strftime related to glibc struct tm extensions. + * 1) Need to negate tm_gmtoff field value when used. (bug 336). + * 2) Deal with NULL ptr case for tm_zone field, which was causing + * segfaults in both the NIST/PCTS tests and the Python 2.4.1 + * self-test suite. + * NOTE: We set uninitialized timezone names to "???", and this + * differs (intentionally) from glibc's behavior. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __UCLIBC_HAS_WCHAR__ +#include +#endif +#ifdef __UCLIBC_HAS_XLOCALE__ +#include +#endif + + +#ifndef __isleap +#define __isleap(y) ( !((y) % 4) && ( ((y) % 100) || !((y) % 400) ) ) +#endif + +#ifndef TZNAME_MAX +#define TZNAME_MAX _POSIX_TZNAME_MAX +#endif + +#if defined (L_tzset) || defined (L_localtime_r) || defined(L_strftime) || \ + defined(L__time_mktime) || defined(L__time_mktime_tzi) || \ + ((defined(L_strftime) || defined(L_strftime_l)) && \ + defined(__UCLIBC_HAS_XLOCALE__)) + +void _time_tzset(int use_old_rules) attribute_hidden; + +#ifndef L__time_mktime + + /* Jan 1, 2007 Z - tm = 0,0,0,1,0,107,1,0,0 */ + +static const time_t new_rule_starts = 1167609600; + +#endif +#endif + +/**********************************************************************/ +/* The era code is currently unfinished. */ +/* #define ENABLE_ERA_CODE */ + +#define TZ_BUFLEN (2*TZNAME_MAX + 56) + +#ifdef __UCLIBC_HAS_TZ_FILE__ + +#include +#include "paths.h" +/* ":+hh:mm:ss+hh:mm:ss,Mmm.w.d/hh:mm:ss,Mmm.w.d/hh:mm:ss" + nul */ +/* 1 + 2*(1+TZNAME_MAX+1 + 9 + 7 + 9) + 1 = 2*TZNAME_MAX + 56 */ + +#else /* __UCLIBC_HAS_TZ_FILE__ */ + +/* Probably no longer needed. */ +#undef __UCLIBC_HAS_TZ_FILE_READ_MANY__ + +#endif /* __UCLIBC_HAS_TZ_FILE__ */ + +/**********************************************************************/ + +extern struct tm __time_tm attribute_hidden; + +typedef struct { + long gmt_offset; + long dst_offset; + short day; /* for J or normal */ + short week; + short month; + short rule_type; /* J, M, \0 */ + char tzname[TZNAME_MAX+1]; +} rule_struct; + +__UCLIBC_MUTEX_EXTERN(_time_tzlock); + +extern rule_struct _time_tzinfo[2] attribute_hidden; + +extern struct tm *_time_t2tm(const time_t *__restrict timer, + int offset, struct tm *__restrict result) attribute_hidden; + +extern time_t _time_mktime(struct tm *timeptr, int store_on_success) attribute_hidden; + +extern struct tm *__time_localtime_tzi(const time_t *__restrict timer, + struct tm *__restrict result, + rule_struct *tzi) attribute_hidden; + +extern time_t _time_mktime_tzi(struct tm *timeptr, int store_on_success, + rule_struct *tzi) attribute_hidden; + +/**********************************************************************/ +#ifdef L_asctime + +static char __time_str[26]; + +char *asctime(const struct tm *ptm) +{ + return asctime_r(ptm, __time_str); +} +libc_hidden_def(asctime) + +#endif +/**********************************************************************/ +#ifdef L_asctime_r + +/* Strictly speaking, this implementation isn't correct. ANSI/ISO specifies + * that the implementation of asctime() be equivalent to + * + * char *asctime(const struct tm *timeptr) + * { + * static char wday_name[7][3] = { + * "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" + * }; + * static char mon_name[12][3] = { + * "Jan", "Feb", "Mar", "Apr", "May", "Jun", + * "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" + * }; + * static char result[26]; + * + * sprintf(result, "%.3s %.3s%3d %.2d:%.2d:%.2d %d\n", + * wday_name[timeptr->tm_wday], + * mon_name[timeptr->tm_mon], + * timeptr->tm_mday, timeptr->tm_hour, + * timeptr->tm_min, timeptr->tm_sec, + * 1900 + timeptr->tm_year); + * return result; + * } + * + * but the above is either inherently unsafe, or carries with it the implicit + * assumption that all fields of timeptr fall within their usual ranges, and + * that the tm_year value falls in the range [-2899,8099] to avoid overflowing + * the static buffer. + * + * If we take the implicit assumption as given, then the implementation below + * is still incorrect for tm_year values < -900, as there will be either + * 0-padding and/or a missing negative sign for the year conversion . But given + * the usual use of asctime(), I think it isn't unreasonable to restrict correct + * operation to the domain of years between 1000 and 9999. + */ + +/* This is generally a good thing, but if you're _sure_ any data passed will be + * in range, you can #undef this. */ +#define SAFE_ASCTIME_R 1 + +static const unsigned char at_data[] = { + 'S', 'u', 'n', 'M', 'o', 'n', 'T', 'u', 'e', 'W', 'e', 'd', + 'T', 'h', 'u', 'F', 'r', 'i', 'S', 'a', 't', + + 'J', 'a', 'n', 'F', 'e', 'b', 'M', 'a', 'r', 'A', 'p', 'r', + 'M', 'a', 'y', 'J', 'u', 'n', 'J', 'u', 'l', 'A', 'u', 'g', + 'S', 'e', 'p', 'O', 'c', 't', 'N', 'o', 'v', 'D', 'e', 'c', + +#ifdef SAFE_ASCTIME_R + '?', '?', '?', +#endif + ' ', '?', '?', '?', + ' ', '0', + offsetof(struct tm, tm_mday), + ' ', '0', + offsetof(struct tm, tm_hour), + ':', '0', + offsetof(struct tm, tm_min), + ':', '0', + offsetof(struct tm, tm_sec), + ' ', '?', '?', '?', '?', '\n', 0 +}; + +char *asctime_r(register const struct tm *__restrict ptm, + register char *__restrict buffer) +{ + int tmp; + + assert(ptm); + assert(buffer); + +#ifdef SAFE_ASCTIME_R + memcpy(buffer, at_data + 3*(7 + 12), sizeof(at_data) - 3*(7 + 12)); + + if (((unsigned int)(ptm->tm_wday)) <= 6) { + memcpy(buffer, at_data + 3 * ptm->tm_wday, 3); + } + + if (((unsigned int)(ptm->tm_mon)) <= 11) { + memcpy(buffer + 4, at_data + 3*7 + 3 * ptm->tm_mon, 3); + } +#else + assert(((unsigned int)(ptm->tm_wday)) <= 6); + assert(((unsigned int)(ptm->tm_mon)) <= 11); + + memcpy(buffer, at_data + 3*(7 + 12) - 3, sizeof(at_data) + 3 - 3*(7 + 12)); + + memcpy(buffer, at_data + 3 * ptm->tm_wday, 3); + memcpy(buffer + 4, at_data + 3*7 + 3 * ptm->tm_mon, 3); +#endif + +#ifdef SAFE_ASCTIME_R + buffer += 19; + tmp = ptm->tm_year + 1900; + if (((unsigned int) tmp) < 10000) { + buffer += 4; + do { + *buffer = '0' + (tmp % 10); + tmp /= 10; + } while (*--buffer == '?'); + } +/* Not sure if we should even bother ... + } else { + __set_errno(EOVERFLOW); + return NULL; + } +*/ +#else /* SAFE_ASCTIME_R */ + buffer += 23; + tmp = ptm->tm_year + 1900; + assert( ((unsigned int) tmp) < 10000 ); +/* Not sure if we should even bother ... + if ( ((unsigned int) tmp) >= 10000 ) { + __set_errno(EOVERFLOW); + return NULL; + } +*/ + do { + *buffer = '0' + (tmp % 10); + tmp /= 10; + } while (*--buffer == '?'); +#endif /* SAFE_ASCTIME_R */ + + do { + --buffer; + tmp = *((int *)(((const char *) ptm) + (int) *buffer)); +#ifdef SAFE_ASCTIME_R + if (((unsigned int) tmp) >= 100) { /* Just check 2 digit non-neg. */ + buffer[-1] = *buffer = '?'; + } else +#else + assert(((unsigned int) tmp) < 100); /* Just check 2 digit non-neg. */ +#endif + { + *buffer = '0' + (tmp % 10); +#ifdef __BCC__ + buffer[-1] = '0' + (tmp/10); +#else + buffer[-1] += (tmp/10); +#endif + } + } while ((buffer -= 2)[-2] == '0'); + + if (*++buffer == '0') { /* Space-pad day of month. */ + *buffer = ' '; + } + + return buffer - 8; +} +libc_hidden_def(asctime_r) + +#endif +/**********************************************************************/ +#ifdef L_clock + +#include + +#ifndef __BCC__ +#if CLOCKS_PER_SEC != 1000000L +#error unexpected value for CLOCKS_PER_SEC! +#endif +#endif + +#ifdef __UCLIBC_CLK_TCK_CONST +# if __UCLIBC_CLK_TCK_CONST > CLOCKS_PER_SEC +# error __UCLIBC_CLK_TCK_CONST > CLOCKS_PER_SEC! +# elif __UCLIBC_CLK_TCK_CONST < 1 +# error __UCLIBC_CLK_TCK_CONST < 1! +# endif +#endif + +/* Note: SUSv3 notes + * + * On XSI-conformant systems, CLOCKS_PER_SEC is defined to be one million. + * + * The value returned by clock() may wrap around on some implementations. + * For example, on a machine with 32-bit values for clock_t, it wraps + * after 2147 seconds. + * + * This implies that we should bitwise and with LONG_MAX. + */ + +clock_t clock(void) +{ + struct tms xtms; + unsigned long t; + + times(&xtms); + + t = ((unsigned long) xtms.tms_utime) + xtms.tms_stime; + +#ifndef __UCLIBC_CLK_TCK_CONST + +# error __UCLIBC_CLK_TCK_CONST not defined! + +#elif ((CLOCKS_PER_SEC % __UCLIBC_CLK_TCK_CONST) == 0) + + /* CLOCKS_PER_SEC == k * __UCLIBC_CLK_TCK_CONST for some integer k >= 1. */ + return ((t * (CLOCKS_PER_SEC/__UCLIBC_CLK_TCK_CONST)) & LONG_MAX); + +#else + + /* Unlike the previous case, the scaling factor is not an integer. + * So when tms_utime, tms_stime, or their sum wraps, some of the + * "visible" bits in the return value are affected. Nothing we + * can really do about this though other than handle tms_utime and + * tms_stime seperately and then sum. But since that doesn't really + * buy us much, we don't bother. */ + + return ((((t / __UCLIBC_CLK_TCK_CONST) * CLOCKS_PER_SEC) + + ((((t % __UCLIBC_CLK_TCK_CONST) * CLOCKS_PER_SEC) + / __UCLIBC_CLK_TCK_CONST)) + ) & LONG_MAX); + +#endif +} + +#endif +/**********************************************************************/ +#ifdef L_ctime + +char *ctime(const time_t *t) +{ + /* ANSI/ISO/SUSv3 say that ctime is equivalent to the following: + * return asctime(localtime(t)); + * I don't think "equivalent" means "it uses the same internal buffer", + * it means "gives the same resultant string". + * + * I doubt anyone ever uses weird code like: + * struct tm *ptm = localtime(t1); ...; ctime(t2); use(ptm); + * which relies on the assumption that ctime's and localtime's + * internal static struct tm is the same. + * + * Using localtime_r instead of localtime avoids linking in + * localtime's static buffer: + */ + struct tm xtm; + memset(&xtm, 0, sizeof(xtm)); + + return asctime(localtime_r(t, &xtm)); +} +libc_hidden_def(ctime) +#endif +/**********************************************************************/ +#ifdef L_ctime_r + +char *ctime_r(const time_t *t, char *buf) +{ + struct tm xtm; + + return asctime_r(localtime_r(t, &xtm), buf); +} + +#endif +/**********************************************************************/ +#ifdef L_difftime + +#include + +#if FLT_RADIX != 2 +#error difftime implementation assumptions violated for you arch! +#endif + +double difftime(time_t time1, time_t time0) +{ +#if (LONG_MAX >> DBL_MANT_DIG) == 0 + + /* time_t fits in the mantissa of a double. */ + return (double)time1 - (double)time0; + +#elif ((LONG_MAX >> DBL_MANT_DIG) >> DBL_MANT_DIG) == 0 + + /* time_t can overflow the mantissa of a double. */ + time_t t1, t0, d; + + d = ((time_t) 1) << DBL_MANT_DIG; + t1 = time1 / d; + time1 -= (t1 * d); + t0 = time0 / d; + time0 -= (t0*d); + + /* Since FLT_RADIX==2 and d is a power of 2, the only possible + * rounding error in the expression below would occur from the + * addition. */ + return (((double) t1) - t0) * d + (((double) time1) - time0); + +#else +#error difftime needs special implementation on your arch. +#endif +} + +#endif +/**********************************************************************/ +#ifdef L_gmtime + +struct tm *gmtime(const time_t *timer) +{ + register struct tm *ptm = &__time_tm; + + _time_t2tm(timer, 0, ptm); /* Can return NULL... */ + + return ptm; +} + +#endif +/**********************************************************************/ +#ifdef L_gmtime_r + +struct tm *gmtime_r(const time_t *__restrict timer, + struct tm *__restrict result) +{ + return _time_t2tm(timer, 0, result); +} + +#endif +/**********************************************************************/ +#ifdef L_localtime + +struct tm *localtime(const time_t *timer) +{ + register struct tm *ptm = &__time_tm; + + /* In this implementation, tzset() is called by localtime_r(). */ + + localtime_r(timer, ptm); /* Can return NULL... */ + + return ptm; +} +libc_hidden_def(localtime) + +#endif +/**********************************************************************/ +#ifdef L_localtime_r + +struct tm *localtime_r(register const time_t *__restrict timer, + register struct tm *__restrict result) +{ + __UCLIBC_MUTEX_LOCK(_time_tzlock); + + _time_tzset(*timer < new_rule_starts); + + __time_localtime_tzi(timer, result, _time_tzinfo); + + __UCLIBC_MUTEX_UNLOCK(_time_tzlock); + + return result; +} +libc_hidden_def(localtime_r) + +#endif +/**********************************************************************/ +#ifdef L__time_localtime_tzi + +#ifdef __UCLIBC_HAS_TM_EXTENSIONS__ + +struct ll_tzname_item; + +typedef struct ll_tzname_item { + struct ll_tzname_item *next; + char tzname[1]; +} ll_tzname_item_t; + +/* Structures form a list "UTC" -> "???" -> "tzname1" -> "tzname2"... */ +struct { + struct ll_tzname_item *next; + char tzname[4]; +} ll_tzname_UNKNOWN = { NULL, "???" }; +const struct { + struct ll_tzname_item *next; + char tzname[4]; +} ll_tzname_UTC = { (void*)&ll_tzname_UNKNOWN, "UTC" }; + +static const char *lookup_tzname(const char *key) +{ + int len; + ll_tzname_item_t *p = (void*) &ll_tzname_UTC; + + do { + if (strcmp(p->tzname, key) == 0) + return p->tzname; + p = p->next; + } while (p != NULL); + + /* Hmm... a new name. */ + len = strnlen(key, TZNAME_MAX+1); + if (len < TZNAME_MAX+1) { /* Verify legal length */ + p = malloc(sizeof(ll_tzname_item_t) + len); + if (p != NULL) { + /* Insert as 3rd item in the list. */ + p->next = ll_tzname_UNKNOWN.next; + ll_tzname_UNKNOWN.next = p; + return strcpy(p->tzname, key); + } + } + + /* Either invalid or couldn't alloc. */ + return ll_tzname_UNKNOWN.tzname; +} + +#endif /* __UCLIBC_HAS_TM_EXTENSIONS__ */ + +static const unsigned char day_cor[] = { /* non-leap */ + 31, 31, 34, 34, 35, 35, 36, 36, 36, 37, 37, 38, 38 +/* 0, 0, 3, 3, 4, 4, 5, 5, 5, 6, 6, 7, 7 */ +/* 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 */ +}; + +/* Note: timezone locking is done by localtime_r. */ + +static int tm_isdst(register const struct tm *__restrict ptm, + register rule_struct *r) +{ + long sec; + int i, isdst, isleap, day, day0, monlen, mday; + int oday = oday; /* ok to be uninitialized, shutting up compiler warning */ + + isdst = 0; + if (r[1].tzname[0] != 0) { + /* First, get the current seconds offset from the start of the year. + * Fields of ptm are assumed to be in their normal ranges. */ + sec = ptm->tm_sec + + 60 * (ptm->tm_min + + 60 * (long)(ptm->tm_hour + + 24 * ptm->tm_yday)); + /* Do some prep work. */ + i = (ptm->tm_year % 400) + 1900; /* Make sure we don't overflow. */ + isleap = __isleap(i); + --i; + day0 = (1 + + i /* Normal years increment 1 wday. */ + + (i/4) + - (i/100) + + (i/400) ) % 7; + i = 0; + do { + day = r->day; /* Common for 'J' and # case. */ + if (r->rule_type == 'J') { + if (!isleap || (day < (31+29))) { + --day; + } + } else if (r->rule_type == 'M') { + /* Find 0-based day number for 1st of the month. */ + day = 31*r->month - day_cor[r->month -1]; + if (isleap && (day >= 59)) { + ++day; + } + monlen = 31 + day_cor[r->month -1] - day_cor[r->month]; + if (isleap && (r->month > 1)) { + ++monlen; + } + /* Wweekday (0 is Sunday) of 1st of the month + * is (day0 + day) % 7. */ + if ((mday = r->day - ((day0 + day) % 7)) >= 0) { + mday -= 7; /* Back up into prev month since r->week>0. */ + } + if ((mday += 7 * r->week) >= monlen) { + mday -= 7; + } + /* So, 0-based day number is... */ + day += mday; + } + + if (i != 0) { + /* Adjust sec since dst->std change time is in dst. */ + sec += (r[-1].gmt_offset - r->gmt_offset); + if (oday > day) { + ++isdst; /* Year starts in dst. */ + } + } + oday = day; + + /* Now convert day to seconds and add offset and compare. */ + if (sec >= (day * 86400L) + r->dst_offset) { + ++isdst; + } + ++r; + } while (++i < 2); + } + + return (isdst & 1); +} + +struct tm attribute_hidden *__time_localtime_tzi(register const time_t *__restrict timer, + register struct tm *__restrict result, + rule_struct *tzi) +{ + time_t x[1]; + long offset; + int days, dst; + + dst = 0; + do { + days = -7; + offset = 604800L - tzi[dst].gmt_offset; + if (*timer > (LONG_MAX - 604800L)) { + days = -days; + offset = -offset; + } + *x = *timer + offset; + + _time_t2tm(x, days, result); + result->tm_isdst = dst; +#ifdef __UCLIBC_HAS_TM_EXTENSIONS__ +# ifdef __USE_BSD + result->tm_gmtoff = - tzi[dst].gmt_offset; + result->tm_zone = lookup_tzname(tzi[dst].tzname); +# else + result->__tm_gmtoff = - tzi[dst].gmt_offset; + result->__tm_zone = lookup_tzname(tzi[dst].tzname); +# endif +#endif /* __UCLIBC_HAS_TM_EXTENSIONS__ */ + } while ((++dst < 2) + && ((result->tm_isdst = tm_isdst(result, tzi)) != 0)); + + return result; +} + +#endif +/**********************************************************************/ +#ifdef L_mktime + +time_t mktime(struct tm *timeptr) +{ + return _time_mktime(timeptr, 1); +} + +/* Another name for `mktime'. */ +/* time_t timelocal(struct tm *tp) */ +strong_alias(mktime,timelocal) + +#endif +/**********************************************************************/ +#ifdef L_timegm +/* Like `mktime' but timeptr represents Universal Time, not local time. */ + +time_t timegm(struct tm *timeptr) +{ + rule_struct gmt_tzinfo[2]; + + memset(gmt_tzinfo, 0, sizeof(gmt_tzinfo)); + strcpy(gmt_tzinfo[0].tzname, "GMT"); /* Match glibc behavior here. */ + + return _time_mktime_tzi(timeptr, 1, gmt_tzinfo); +} + +#endif +/**********************************************************************/ +#if defined(L_strftime) || defined(L_strftime_l) + +#if defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) + +size_t strftime(char *__restrict s, size_t maxsize, + const char *__restrict format, + const struct tm *__restrict timeptr) +{ + return strftime_l(s, maxsize, format, timeptr, __UCLIBC_CURLOCALE); +} +libc_hidden_def(strftime) + +#else /* defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) */ + +#define NO_E_MOD 0x80 +#define NO_O_MOD 0x40 + +#define ILLEGAL_SPEC 0x3f + +#define INT_SPEC 0x00 /* must be 0x00!! */ +#define STRING_SPEC 0x10 /* must be 0x10!! */ +#define CALC_SPEC 0x20 +#define STACKED_SPEC 0x30 + +#define MASK_SPEC 0x30 + +/* Compatibility: + * + * No alternate digit (%O?) handling. Always uses 0-9. + * Alternate locale format (%E?) handling is broken for nontrivial ERAs. + * glibc's %P is currently faked by %p. This means it doesn't do lower case. + * glibc's %k, %l, and %s are handled. + * glibc apparently allows (and ignores) extraneous 'E' and 'O' modifiers, + * while they are flagged as illegal conversions here. + */ + +/* Warning: Assumes ASCII values! (as do lots of other things in the lib...) */ +static const unsigned char spec[] = { + /* A */ 0x03 | STRING_SPEC | NO_E_MOD | NO_O_MOD, + /* B */ 0x04 | STRING_SPEC | NO_E_MOD | NO_O_MOD, + /* C */ 0x0a | INT_SPEC | NO_O_MOD, + /* D */ 0x02 | STACKED_SPEC | NO_E_MOD | NO_O_MOD, + /* E */ ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD, + /* F */ 0x03 | STACKED_SPEC | NO_E_MOD | NO_O_MOD, + /* G */ 0x03 | CALC_SPEC | NO_E_MOD | NO_O_MOD, + /* H */ 0x0b | INT_SPEC | NO_E_MOD, + /* I */ 0x0c | INT_SPEC | NO_E_MOD, + /* J */ ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD, + /* K */ ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD, + /* L */ ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD, + /* M */ 0x0d | INT_SPEC | NO_E_MOD, + /* N */ ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD, + /* O */ ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD, + /* P */ 0x05 | STRING_SPEC | NO_E_MOD | NO_O_MOD, /* glibc ; use %p */ + /* Q */ ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD, + /* R */ 0x04 | STACKED_SPEC | NO_E_MOD | NO_O_MOD, + /* S */ 0x0e | INT_SPEC | NO_E_MOD, + /* T */ 0x05 | STACKED_SPEC | NO_E_MOD | NO_O_MOD, + /* U */ 0x04 | CALC_SPEC | NO_E_MOD, + /* V */ 0x05 | CALC_SPEC | NO_E_MOD, + /* W */ 0x06 | CALC_SPEC | NO_E_MOD, + /* X */ 0x0a | STACKED_SPEC | NO_O_MOD, + /* Y */ 0x0f | INT_SPEC | NO_O_MOD, + /* Z */ 0x01 | CALC_SPEC | NO_E_MOD | NO_O_MOD, + '?', /* 26 */ + '?', /* 27 */ + '?', /* 28 */ + '?', /* 29 */ + 0, /* 30 */ + 0, /* 31 */ + /* a */ 0x00 | STRING_SPEC | NO_E_MOD | NO_O_MOD, + /* b */ 0x01 | STRING_SPEC | NO_E_MOD | NO_O_MOD, + /* c */ 0x08 | STACKED_SPEC | NO_O_MOD, + /* d */ 0x00 | INT_SPEC | NO_E_MOD, + /* e */ 0x01 | INT_SPEC | NO_E_MOD, + /* f */ ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD, + /* g */ 0x02 | CALC_SPEC | NO_E_MOD | NO_O_MOD, + /* h */ 0x01 | STRING_SPEC | NO_E_MOD | NO_O_MOD, /* same as b */ + /* i */ ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD, + /* j */ 0x08 | INT_SPEC | NO_E_MOD | NO_O_MOD, + /* k */ 0x03 | INT_SPEC | NO_E_MOD | NO_O_MOD, /* glibc */ + /* l */ 0x04 | INT_SPEC | NO_E_MOD | NO_O_MOD, /* glibc */ + /* m */ 0x05 | INT_SPEC | NO_E_MOD, + /* n */ 0x00 | STACKED_SPEC | NO_E_MOD | NO_O_MOD, + /* o */ ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD, + /* p */ 0x02 | STRING_SPEC | NO_E_MOD | NO_O_MOD, + /* q */ ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD, + /* r */ 0x0b | STACKED_SPEC | NO_E_MOD | NO_O_MOD, + /* s */ 0x07 | CALC_SPEC | NO_E_MOD | NO_O_MOD, /* glibc */ + /* t */ 0x01 | STACKED_SPEC | NO_E_MOD | NO_O_MOD, + /* u */ 0x07 | INT_SPEC | NO_E_MOD, + /* v */ ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD, + /* w */ 0x02 | INT_SPEC | NO_E_MOD, + /* x */ 0x09 | STACKED_SPEC | NO_O_MOD, + /* y */ 0x09 | INT_SPEC, + /* z */ 0x00 | CALC_SPEC | NO_E_MOD | NO_O_MOD, + + + /* WARNING!!! These are dependent on the layout of struct tm!!! */ +#define FIELD_MAX (26+6+26) + 60 /* 61? */, 59, 23, 31, 11, 0 /* 9999 */, 6, 0 /* 365 */, + +#define TP_OFFSETS (FIELD_MAX+8) + 3, /* d */ + 3, /* e */ + 6, /* w */ + 2, /* k */ + 2, /* l */ + 4, /* m */ + 0, /* CURRENTLY UNUSED */ + /* NOTE: u,j,y order must be preserved as 6,7,5 seq is used in the code! */ +#define CALC_OFFSETS (TP_OFFSETS + 7) + 6, /* u */ + 7, /* j */ + 5, /* y */ + 5, /* C */ + 2, /* H */ + 2, /* I */ + 1, /* M */ + 0, /* S */ + 5, /* Y */ + 6, /* a */ + 4, /* b, h */ + 2, /* p */ + 6, /* A */ + 4, /* B */ + 2, /* P */ + +#define TP_CODES (TP_OFFSETS + 16 + 6) + 2 | 16, /* d */ + 2, /* e */ + 0 | 16, /* w */ + 2, /* k */ + 2 | 32 | 0, /* l */ + 2 | 16 | 1, /* m */ + 0, /* CURRENTLY UNUSED */ + 0 | 16 | 8 , /* u */ + 4 | 16 | 1, /* j */ + 2 | 128 | 32 | 16 , /* y */ + 2 | 128 | 64 | 32 | 16 , /* C */ + 2 | 16, /* H */ + 2 | 32 | 16 | 0, /* I */ + 2 | 16, /* M */ + 2 | 16, /* S */ + 6 | 16, /* Y */ + 2, /* a */ + 2, /* b, h */ + 2 | 64, /* p */ + 2, /* A */ + 2, /* B */ + 2 | 64, /* P */ + +#define STRINGS_NL_ITEM_START (TP_CODES + 16 + 6) + _NL_ITEM_INDEX(ABDAY_1), /* a */ + _NL_ITEM_INDEX(ABMON_1), /* b, h */ + _NL_ITEM_INDEX(AM_STR), /* p */ + _NL_ITEM_INDEX(DAY_1), /* A */ + _NL_ITEM_INDEX(MON_1), /* B */ + _NL_ITEM_INDEX(AM_STR), /* P -- wrong! need lower case */ + +#define STACKED_STRINGS_START (STRINGS_NL_ITEM_START+6) + 6, 7, 8, 16, 24, 29, /* 6 - offsets from offset-count to strings */ + '\n', 0, /* 2 */ + '\t', 0, /* 2 */ + '%', 'm', '/', '%', 'd', '/', '%', 'y', 0, /* 9 - %D */ + '%', 'Y', '-', '%', 'm', '-', '%', 'd', 0, /* 9 - %F (glibc extension) */ + '%', 'H', ':', '%', 'M', 0, /* 6 - %R*/ + '%', 'H', ':', '%', 'M', ':', '%', 'S', 0, /* 9 - %T */ + +#define STACKED_STRINGS_NL_ITEM_START (STACKED_STRINGS_START + 43) + _NL_ITEM_INDEX(D_T_FMT), /* c */ + _NL_ITEM_INDEX(D_FMT), /* x */ + _NL_ITEM_INDEX(T_FMT), /* X */ + _NL_ITEM_INDEX(T_FMT_AMPM), /* r */ +#ifdef ENABLE_ERA_CODE + _NL_ITEM_INDEX(ERA_D_T_FMT), /* Ec */ + _NL_ITEM_INDEX(ERA_D_FMT), /* Ex */ + _NL_ITEM_INDEX(ERA_T_FMT), /* EX */ +#endif +}; + +static int load_field(int k, const struct tm *__restrict timeptr) +{ + int r; + int r_max; + + r = ((int *) timeptr)[k]; + + r_max = spec[FIELD_MAX + k]; + + if (k == 7) { + r_max = 365; + } else if (k == 5) { + r += 1900; + r_max = 9999; + } + + if ((((unsigned int) r) > r_max) || ((k == 3) && !r)) { + r = -1; + } + + return r; +} + +#define MAX_PUSH 4 + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning TODO: Check multibyte format string validity. +#endif + +libc_hidden_proto(__XL_NPP(strftime)) +size_t __XL_NPP(strftime)(char *__restrict s, size_t maxsize, + const char *__restrict format, + const struct tm *__restrict timeptr __LOCALE_PARAM ) +{ + long tzo; + register const char *p; + register const char *o; +#ifndef __UCLIBC_HAS_TM_EXTENSIONS__ + const rule_struct *rsp; +#endif + const char *stack[MAX_PUSH]; + size_t count; + size_t o_count; + int field_val, i, j, lvl; + int x[3]; /* wday, yday, year */ + int isofm, days; + char buf[__UIM_BUFLEN_LONG]; + unsigned char mod; + unsigned char code; + + /* We'll, let's get this out of the way. */ + _time_tzset(_time_mktime((struct tm *) timeptr, 0) < new_rule_starts); + + lvl = 0; + p = format; + count = maxsize; + +LOOP: + if (!count) { + return 0; + } + if (!*p) { + if (lvl == 0) { + *s = 0; /* nul-terminate */ + return maxsize - count; + } + p = stack[--lvl]; + goto LOOP; + } + + o_count = 1; + if ((*(o = p) == '%') && (*++p != '%')) { + o_count = 2; + mod = ILLEGAL_SPEC; + if ((*p == 'O') || (*p == 'E')) { /* modifier */ + mod |= ((*p == 'O') ? NO_O_MOD : NO_E_MOD); + ++o_count; + ++p; + } + if ((((unsigned char)(((*p) | 0x20) - 'a')) >= 26) + || (((code = spec[(int)(*p - 'A')]) & mod) >= ILLEGAL_SPEC) + ) { + if (!*p) { + --p; + --o_count; + } + goto OUTPUT; + } + code &= ILLEGAL_SPEC; /* modifiers are preserved in mod var. */ + + if ((code & MASK_SPEC) == STACKED_SPEC) { + if (lvl == MAX_PUSH) { + goto OUTPUT; /* Stack full so treat as illegal spec. */ + } + stack[lvl++] = ++p; + if ((code &= 0xf) < 8) { + p = ((const char *) spec) + STACKED_STRINGS_START + code; + p += *((unsigned char *)p); + goto LOOP; + } + p = ((const char *) spec) + STACKED_STRINGS_NL_ITEM_START + + (code & 7); +#ifdef ENABLE_ERA_CODE + if ((mod & NO_E_MOD) /* Actually, this means E modifier present. */ + && (*(o = __XL_NPP(nl_langinfo)(_NL_ITEM(LC_TIME, + (int)(((unsigned char *)p)[4])) + __LOCALE_ARG + ))) + ) { + p = o; + goto LOOP; + } +#endif + p = __XL_NPP(nl_langinfo)(_NL_ITEM(LC_TIME, + (int)(*((unsigned char *)p))) + __LOCALE_ARG + ); + goto LOOP; + } + + o = ((const char *) spec) + 26; /* set to "????" */ + if ((code & MASK_SPEC) == CALC_SPEC) { + + if (*p == 's') { + time_t t; + + /* Use a cast to silence the warning since *timeptr won't + * be changed. */ + if ((t = _time_mktime((struct tm *) timeptr, 0)) + == ((time_t) -1) + ) { + o_count = 1; + goto OUTPUT; + } +#ifdef TIME_T_IS_UNSIGNED + o = _uintmaxtostr(buf + sizeof(buf) - 1, + (uintmax_t) t, + 10, __UIM_DECIMAL); +#else + o = _uintmaxtostr(buf + sizeof(buf) - 1, + (uintmax_t) t, + -10, __UIM_DECIMAL); +#endif + o_count = sizeof(buf); + goto OUTPUT; + } else if (((*p) | 0x20) == 'z') { /* 'z' or 'Z' */ + + if (timeptr->tm_isdst < 0) { + /* SUSv3 specifies this behavior for 'z', but we'll also + * treat it as "no timezone info" for 'Z' too. */ + o_count = 0; + goto OUTPUT; + } + +#ifdef __UCLIBC_HAS_TM_EXTENSIONS__ + +# ifdef __USE_BSD +# define RSP_TZNAME timeptr->tm_zone +# define RSP_GMT_OFFSET (-timeptr->tm_gmtoff) +# else +# define RSP_TZNAME timeptr->__tm_zone +# define RSP_GMT_OFFSET (-timeptr->__tm_gmtoff) +# endif + +#else + +#define RSP_TZNAME rsp->tzname +#define RSP_GMT_OFFSET rsp->gmt_offset + + __UCLIBC_MUTEX_LOCK(_time_tzlock); + + rsp = _time_tzinfo; + if (timeptr->tm_isdst > 0) { + ++rsp; + } +#endif + + if (*p == 'Z') { + o = RSP_TZNAME; +#ifdef __UCLIBC_HAS_TM_EXTENSIONS__ + /* Sigh... blasted glibc extensions. Of course we can't + * count on the pointer being valid. Best we can do is + * handle NULL, which looks to be all that glibc does. + * At least that catches the memset() with 0 case. + * NOTE: We handle this case differently than glibc! + * It uses system timezone name (based on tm_isdst) in this + * case... although it always seems to use the embedded + * tm_gmtoff value. What we'll do instead is treat the + * timezone name as unknown/invalid and return "???". */ + if (!o) { + o = "???"; + } +#endif + assert(o != NULL); +#if 0 + if (!o) { /* PARANOIA */ + o = spec+30; /* empty string */ + } +#endif + o_count = SIZE_MAX; +#ifdef __UCLIBC_HAS_TM_EXTENSIONS__ + goto OUTPUT; +#endif + } else { /* z */ + *s = '+'; + if ((tzo = -RSP_GMT_OFFSET) < 0) { + tzo = -tzo; + *s = '-'; + } + ++s; + --count; + + i = tzo / 60; + field_val = ((i / 60) * 100) + (i % 60); + + i = 16 + 6; /* 0-fill, width = 4 */ + } +#ifndef __UCLIBC_HAS_TM_EXTENSIONS__ + __UCLIBC_MUTEX_UNLOCK(_time_tzlock); + if (*p == 'Z') { + goto OUTPUT; + } +#endif + } else { + /* TODO: don't need year for U, W */ + for (i=0 ; i < 3 ; i++) { + if ((x[i] = load_field(spec[CALC_OFFSETS+i],timeptr)) < 0) { + goto OUTPUT; + } + } + + i = 16 + 2; /* 0-fill, width = 2 */ + + if ((*p == 'U') || (*p == 'W')) { + field_val = ((x[1] - x[0]) + 7); + if (*p == 'W') { + ++field_val; + } + field_val /= 7; + if ((*p == 'W') && !x[0]) { + --field_val; + } + } else { /* ((*p == 'g') || (*p == 'G') || (*p == 'V')) */ +ISO_LOOP: + isofm = (((x[1] - x[0]) + 11) % 7) - 3; /* [-3,3] */ + + if (x[1] < isofm) { /* belongs to previous year */ + --x[2]; + x[1] += 365 + __isleap(x[2]); + goto ISO_LOOP; + } + + field_val = ((x[1] - isofm) / 7) + 1; /* week # */ + days = 365 + __isleap(x[2]); + isofm = ((isofm + 7*53 + 3 - days)) % 7 + days - 3; /* next year */ + if (x[1] >= isofm) { /* next year */ + x[1] -= days; + ++x[2]; + goto ISO_LOOP; + } + + if (*p != 'V') { /* need year */ + field_val = x[2]; /* TODO: what if x[2] now 10000 ?? */ + if (*p == 'g') { + field_val %= 100; + } else { + i = 16 + 6; /* 0-fill, width = 4 */ + } + } + } + } + } else { + i = TP_OFFSETS + (code & 0x1f); + if ((field_val = load_field(spec[i], timeptr)) < 0) { + goto OUTPUT; + } + + i = spec[i+(TP_CODES - TP_OFFSETS)]; + + j = (i & 128) ? 100: 12; + if (i & 64) { + field_val /= j;; + } + if (i & 32) { + field_val %= j; + if (((i & 128) + field_val) == 0) { /* mod 12? == 0 */ + field_val = j; /* set to 12 */ + } + } + field_val += (i & 1); + if ((i & 8) && !field_val) { + field_val += 7; + } + } + + if ((code & MASK_SPEC) == STRING_SPEC) { + o_count = SIZE_MAX; + field_val += spec[STRINGS_NL_ITEM_START + (code & 0xf)]; + o = __XL_NPP(nl_langinfo)(_NL_ITEM(LC_TIME, field_val) __LOCALE_ARG); + } else { + o_count = ((i >> 1) & 3) + 1; + o = buf + o_count; + do { + *(char *)(--o) = '0' + (field_val % 10); + field_val /= 10; + } while (o > buf); + if (*buf == '0') { + *buf = ' ' + (i & 16); + } + } + } + +OUTPUT: + ++p; + while (o_count && count && *o) { + *s++ = *o++; + --o_count; + --count; + } + goto LOOP; +} +libc_hidden_def(__XL_NPP(strftime)) + +#endif /* defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) */ + +#endif +/**********************************************************************/ +#if defined(L_strptime) || defined(L_strptime_l) + +#define ISDIGIT(C) __isdigit_char((C)) + +#ifdef __UCLIBC_DO_XLOCALE +#define ISSPACE(C) isspace_l((C), locale_arg) +#else +#define ISSPACE(C) isspace((C)) +#endif + +#if defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) + +char *strptime(const char *__restrict buf, const char *__restrict format, + struct tm *__restrict tm) +{ + return strptime_l(buf, format, tm, __UCLIBC_CURLOCALE); +} +libc_hidden_def(strptime) + +#else /* defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) */ + +/* TODO: + * 1) %l and %k are space-padded, so "%l" by itself fails while " %l" succeeds. + * Both work for glibc. So, should we always strip spaces? + * 2) %Z + */ + +/* Notes: + * There are several differences between this strptime and glibc's strptime. + * 1) glibc strips leading space before numeric conversions. + * 2) glibc will read fields without whitespace in between. SUSv3 states + * that you must have whitespace between conversion operators. Besides, + * how do you know how long a number should be if there are leading 0s? + * 3) glibc attempts to compute some the struct tm fields based on the + * data retrieved; tm_wday in particular. I don't as I consider it + * another glibc attempt at mind-reading... + */ + +#define NO_E_MOD 0x80 +#define NO_O_MOD 0x40 + +#define ILLEGAL_SPEC 0x3f + +#define INT_SPEC 0x00 /* must be 0x00!! */ +#define STRING_SPEC 0x10 /* must be 0x10!! */ +#define CALC_SPEC 0x20 +#define STACKED_SPEC 0x30 + +#define MASK_SPEC 0x30 + +/* Warning: Assumes ASCII values! (as do lots of other things in the lib...) */ +static const unsigned char spec[] = { + /* A */ 0x02 | STRING_SPEC | NO_E_MOD | NO_O_MOD, + /* B */ 0x01 | STRING_SPEC | NO_E_MOD | NO_O_MOD, + /* C */ 0x08 | INT_SPEC | NO_O_MOD, + /* D */ 0x01 | STACKED_SPEC | NO_E_MOD | NO_O_MOD, + /* E */ ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD, + /* F */ 0x02 | STACKED_SPEC | NO_E_MOD | NO_O_MOD, /* glibc */ + /* G */ 0x0f | INT_SPEC | NO_E_MOD | NO_O_MOD, /* glibc */ + /* H */ 0x06 | INT_SPEC | NO_E_MOD, + /* I */ 0x07 | INT_SPEC | NO_E_MOD, + /* J */ ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD, + /* K */ ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD, + /* L */ ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD, + /* M */ 0x04 | INT_SPEC | NO_E_MOD, + /* N */ ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD, + /* O */ ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD, + /* P */ 0x00 | STRING_SPEC | NO_E_MOD | NO_O_MOD, /* glibc */ + /* Q */ ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD, + /* R */ 0x03 | STACKED_SPEC | NO_E_MOD | NO_O_MOD, + /* S */ 0x05 | INT_SPEC | NO_E_MOD, + /* T */ 0x04 | STACKED_SPEC | NO_E_MOD | NO_O_MOD, + /* U */ 0x0c | INT_SPEC | NO_E_MOD, + /* V */ 0x0d | INT_SPEC | NO_E_MOD | NO_O_MOD, /* glibc */ + /* W */ 0x0c | INT_SPEC | NO_E_MOD, + /* X */ 0x0a | STACKED_SPEC | NO_O_MOD, + /* Y */ 0x0a | INT_SPEC | NO_O_MOD, + /* Z */ 0x02 | CALC_SPEC | NO_E_MOD | NO_O_MOD, /* glibc */ + + /* WARNING! This assumes orderings: + * AM,PM + * ABDAY_1-ABDAY-7,DAY_1-DAY_7 + * ABMON_1-ABMON_12,MON_1-MON12 + * Also, there are exactly 6 bytes between 'Z' and 'a'. + */ +#define STRINGS_NL_ITEM_START (26) + _NL_ITEM_INDEX(AM_STR), /* p (P) */ + _NL_ITEM_INDEX(ABMON_1), /* B, b */ + _NL_ITEM_INDEX(ABDAY_1), /* A, a */ + 2, + 24, + 14, + + /* a */ 0x02 | STRING_SPEC | NO_E_MOD | NO_O_MOD, + /* b */ 0x01 | STRING_SPEC | NO_E_MOD | NO_O_MOD, + /* c */ 0x08 | STACKED_SPEC | NO_O_MOD, + /* d */ 0x00 | INT_SPEC | NO_E_MOD, + /* e */ 0x00 | INT_SPEC | NO_E_MOD, + /* f */ ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD, + /* g */ 0x0e | INT_SPEC | NO_E_MOD | NO_O_MOD, /* glibc */ + /* h */ 0x01 | STRING_SPEC | NO_E_MOD | NO_O_MOD, + /* i */ ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD, + /* j */ 0x01 | INT_SPEC | NO_E_MOD | NO_O_MOD, + /* k */ 0x06 | INT_SPEC | NO_E_MOD, /* glibc */ + /* l */ 0x07 | INT_SPEC | NO_E_MOD, /* glibc */ + /* m */ 0x02 | INT_SPEC | NO_E_MOD, + /* n */ 0x00 | STACKED_SPEC | NO_E_MOD | NO_O_MOD, + /* o */ ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD, + /* p */ 0x00 | STRING_SPEC | NO_E_MOD | NO_O_MOD, + /* q */ ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD, + /* r */ 0x0b | STACKED_SPEC | NO_E_MOD | NO_O_MOD, + /* s */ 0x00 | CALC_SPEC | NO_E_MOD | NO_O_MOD, /* glibc */ + /* t */ 0x00 | STACKED_SPEC | NO_E_MOD | NO_O_MOD, + /* u */ 0x0b | INT_SPEC | NO_E_MOD | NO_O_MOD, /* glibc */ + /* v */ ILLEGAL_SPEC | NO_E_MOD | NO_O_MOD, + /* w */ 0x03 | INT_SPEC | NO_E_MOD, + /* x */ 0x09 | STACKED_SPEC | NO_O_MOD, + /* y */ 0x09 | INT_SPEC, + /* z */ 0x01 | CALC_SPEC | NO_E_MOD | NO_O_MOD, /* glibc */ + +#define INT_FIELD_START (26+6+26) + /* (field #) << 3 + lower bound (0|1) + correction 0:none, 2:-1, 4:-1900 + * followed by upper bound prior to correction with 1=>366 and 2=>9999. */ + /* d, e */ (3 << 3) + 1 + 0, 31, + /* j */ (7 << 3) + 1 + 2, /* 366 */ 1, + /* m */ (4 << 3) + 1 + 2, 12, + /* w */ (6 << 3) + 0 + 0, 6, + /* M */ (1 << 3) + 0 + 0, 59, + /* S */ 0 + 0 + 0, 60, + /* H (k) */ (2 << 3) + 0 + 0, 23, + /* I (l) */ (9 << 3) + 1 + 0, 12, /* goes with 8 -- am/pm */ + /* C */ (10<< 3) + 0 + 0, 99, + /* y */ (11<< 3) + 0 + 0, 99, + /* Y */ (5 << 3) + 0 + 4, /* 9999 */ 2, + /* u */ (6 << 3) + 1 + 0, 7, + /* The following are processed and range-checked, but ignored otherwise. */ + /* U, W */ (12<< 3) + 0 + 0, 53, + /* V */ (12<< 3) + 1 + 0, 53, + /* g */ (12<< 3) + 0 + 0, 99, + /* G */ (12<< 3) + 0 /*+ 4*/, /* 9999 */ 2, /* Note: -1 or 10000? */ + +#define STACKED_STRINGS_START (INT_FIELD_START+32) + 5, 6, 14, 22, 27, /* 5 - offsets from offset-count to strings */ + ' ', 0, /* 2 - %n or %t */ + '%', 'm', '/', '%', 'd', '/', '%', 'y', 0, /* 9 - %D */ + '%', 'Y', '-', '%', 'm', '-', '%', 'd', 0, /* 9 - %F (glibc extension) */ + '%', 'H', ':', '%', 'M', 0, /* 6 - %R*/ + '%', 'H', ':', '%', 'M', ':', '%', 'S', 0, /* 9 - %T */ + +#define STACKED_STRINGS_NL_ITEM_START (STACKED_STRINGS_START + 40) + _NL_ITEM_INDEX(D_T_FMT), /* c */ + _NL_ITEM_INDEX(D_FMT), /* x */ + _NL_ITEM_INDEX(T_FMT), /* X */ + _NL_ITEM_INDEX(T_FMT_AMPM), /* r */ +#ifdef ENABLE_ERA_CODE + _NL_ITEM_INDEX(ERA_D_T_FMT), /* Ec */ + _NL_ITEM_INDEX(ERA_D_FMT), /* Ex */ + _NL_ITEM_INDEX(ERA_T_FMT), /* EX */ +#endif +}; + +#define MAX_PUSH 4 + +libc_hidden_proto(__XL_NPP(strptime)) +char *__XL_NPP(strptime)(const char *__restrict buf, const char *__restrict format, + struct tm *__restrict tm __LOCALE_PARAM) +{ + register const char *p; + char *o; + const char *stack[MAX_PUSH]; + int i, j, lvl; + int fields[13]; + unsigned char mod; + unsigned char code; + + i = 0; + do { + fields[i] = INT_MIN; + } while (++i < 13); + + lvl = 0; + p = format; + +LOOP: + if (!*p) { + if (lvl == 0) { /* Done. */ + if (fields[6] == 7) { /* Cleanup for %u here since just once. */ + fields[6] = 0; /* Don't use mod in case unset. */ + } + + i = 0; + do { /* Store the values into tm. */ + if (fields[i] != INT_MIN) { + ((int *) tm)[i] = fields[i]; + } + } while (++i < 8); + + return (char *) buf; /* Success. */ + } + p = stack[--lvl]; + goto LOOP; + } + + if ((*p == '%') && (*++p != '%')) { + mod = ILLEGAL_SPEC; + if ((*p == 'O') || (*p == 'E')) { /* Modifier? */ + mod |= ((*p == 'O') ? NO_O_MOD : NO_E_MOD); + ++p; + } + + if (!*p + || (((unsigned char)(((*p) | 0x20) - 'a')) >= 26) + || (((code = spec[(int)(*p - 'A')]) & mod) >= ILLEGAL_SPEC) + ) { + return NULL; /* Illegal spec. */ + } + + if ((code & MASK_SPEC) == STACKED_SPEC) { + if (lvl == MAX_PUSH) { + return NULL; /* Stack full so treat as illegal spec. */ + } + stack[lvl++] = ++p; + if ((code &= 0xf) < 8) { + p = ((const char *) spec) + STACKED_STRINGS_START + code; + p += *((unsigned char *)p); + goto LOOP; + } + + p = ((const char *) spec) + STACKED_STRINGS_NL_ITEM_START + + (code & 7); +#ifdef ENABLE_ERA_CODE + if ((mod & NO_E_MOD) /* Actually, this means E modifier present. */ + && (*(o = __XL_NPP(nl_langinfo)(_NL_ITEM(LC_TIME, + (int)(((unsigned char *)p)[4])) + __LOCALE_ARG + ))) + ) { + p = o; + goto LOOP; + } +#endif + p = __XL_NPP(nl_langinfo)(_NL_ITEM(LC_TIME, + (int)(*((unsigned char *)p))) + __LOCALE_ARG + ); + goto LOOP; + } + + ++p; + + if ((code & MASK_SPEC) == STRING_SPEC) { + code &= 0xf; + j = spec[STRINGS_NL_ITEM_START + 3 + code]; + i = _NL_ITEM(LC_TIME, spec[STRINGS_NL_ITEM_START + code]); + /* Go backwards to check full names before abreviations. */ + do { + --j; + o = __XL_NPP(nl_langinfo)(i+j __LOCALE_ARG); + if (!__XL_NPP(strncasecmp)(buf, o, strlen(o) __LOCALE_ARG) && *o) { + do { /* Found a match. */ + ++buf; + } while (*++o); + if (!code) { /* am/pm */ + fields[8] = j * 12; + if (fields[9] >= 0) { /* We have a previous %I or %l. */ + fields[2] = fields[9] + fields[8]; + } + } else { /* day (4) or month (6) */ + fields[2 + (code << 1)] + = j % (spec[STRINGS_NL_ITEM_START + 3 + code] >> 1); + } + goto LOOP; + } + } while (j); + return NULL; /* Failed to match. */ + } + + if ((code & MASK_SPEC) == CALC_SPEC) { + if ((code &= 0xf) < 1) { /* s or z*/ + time_t t; + + o = (char *) buf; + i = errno; + __set_errno(0); + if (!ISSPACE(*buf)) { /* Signal an error if whitespace. */ +#ifdef TIME_T_IS_UNSIGNED + t = __XL_NPP(strtoul)(buf, &o, 10 __LOCALE_ARG); +#else + t = __XL_NPP(strtol)(buf, &o, 10 __LOCALE_ARG); +#endif + } + if ((o == buf) || errno) { /* Not a number or overflow. */ + return NULL; + } + __set_errno(i); /* Restore errno. */ + buf = o; + + if (!code) { /* s */ + localtime_r(&t, tm); /* TODO: check for failure? */ + i = 0; + do { /* Now copy values from tm to fields. */ + fields[i] = ((int *) tm)[i]; + } while (++i < 8); + } + } + /* TODO: glibc treats %Z as a nop. For now, do the same. */ + goto LOOP; + } + + assert((code & MASK_SPEC) == INT_SPEC); + { + register const unsigned char *x; + code &= 0xf; + x = spec + INT_FIELD_START + (code << 1); + if ((j = x[1]) < 3) { /* upper bound (inclusive) */ + j = ((j==1) ? 366 : 9999); + } + i = -1; + while (ISDIGIT(*buf)) { + if (i < 0) { + i = 0; + } + if ((i = 10*i + (*buf - '0')) > j) { /* Overflow. */ + return NULL; + } + ++buf; + } + if (i < (*x & 1)) { /* This catches no-digit case too. */ + return NULL; + } + if (*x & 2) { + --i; + } + if (*x & 4) { + i -= 1900; + } + + if (*x == (9 << 3) + 1 + 0) { /* %I or %l */ + if (i == 12) { + i = 0; + } + if (fields[8] >= 0) { /* We have a previous %p or %P. */ + fields[2] = i + fields[8]; + } + } + + fields[(*x) >> 3] = i; + + if (((unsigned char)(*x - (10 << 3) + 0 + 0)) <= 8) { /* %C or %y */ + if ((j = fields[10]) < 0) { /* No %C, so i must be %y data. */ + if (i <= 68) { /* Map [0-68] to 2000+i */ + i += 100; + } + } else { /* Have %C data, but what about %y? */ + if ((i = fields[11]) < 0) { /* No %y data. */ + i = 0; /* Treat %y val as 0 following glibc's example. */ + } + i += 100*(j - 19); + } + fields[5] = i; + } + } + goto LOOP; + } else if (ISSPACE(*p)) { + ++p; + while (ISSPACE(*buf)) { + ++buf; + } + goto LOOP; + } else if (*buf++ == *p++) { + goto LOOP; + } + return NULL; +} +libc_hidden_def(__XL_NPP(strptime)) + +#endif /* defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) */ + +#endif +/**********************************************************************/ +#ifdef L_time + +#ifndef __BCC__ +#error The uClibc version of time is in sysdeps/linux/common. +#endif + +time_t time(register time_t *tloc) +{ + struct timeval tv; + register struct timeval *p = &tv; + + gettimeofday(p, NULL); /* This should never fail... */ + + if (tloc) { + *tloc = p->tv_sec; + } + + return p->tv_sec; +} + +#endif +/**********************************************************************/ +#ifdef L_tzset + +static const char vals[] = { + 'T', 'Z', 0, /* 3 */ + 'U', 'T', 'C', 0, /* 4 */ + 25, 60, 60, 1, /* 4 */ + '.', 1, /* M */ + 5, '.', 1, + 6, 0, 0, /* Note: overloaded for non-M non-J case... */ + 0, 1, 0, /* J */ + ',', 'M', '4', '.', '1', '.', '0', + ',', 'M', '1', '0', '.', '5', '.', '0', 0, + ',', 'M', '3', '.', '2', '.', '0', + ',', 'M', '1', '1', '.', '1', '.', '0', 0 +}; + +#define TZ vals +#define UTC (vals + 3) +#define RANGE (vals + 7) +#define RULE (vals + 11 - 1) +#define DEFAULT_RULES (vals + 22) +#define DEFAULT_2007_RULES (vals + 38) + +/* Initialize to UTC. */ +int daylight = 0; +long timezone = 0; +char *tzname[2] = { (char *) UTC, (char *) (UTC-1) }; + +__UCLIBC_MUTEX_INIT(_time_tzlock, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP); + +rule_struct _time_tzinfo[2]; + +static const char *getoffset(register const char *e, long *pn) +{ + register const char *s = RANGE-1; + long n; + int f; + + n = 0; + f = -1; + do { + ++s; + if (__isdigit_char(*e)) { + f = *e++ - '0'; + } + if (__isdigit_char(*e)) { + f = 10 * f + (*e++ - '0'); + } + if (((unsigned int)f) >= *s) { + return NULL; + } + n = (*s) * n + f; + f = 0; + if (*e == ':') { + ++e; + --f; + } + } while (*s > 1); + + *pn = n; + return e; +} + +static const char *getnumber(register const char *e, int *pn) +{ +#ifdef __BCC__ + /* bcc can optimize the counter if it thinks it is a pointer... */ + register const char *n = (const char *) 3; + int f; + + f = 0; + while (n && __isdigit_char(*e)) { + f = 10 * f + (*e++ - '0'); + --n; + } + + *pn = f; + return (n == (const char *) 3) ? NULL : e; +#else /* __BCC__ */ + int n, f; + + n = 3; + f = 0; + while (n && __isdigit_char(*e)) { + f = 10 * f + (*e++ - '0'); + --n; + } + + *pn = f; + return (n == 3) ? NULL : e; +#endif /* __BCC__ */ +} + + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning CONSIDER: Should we preserve errno from open/read/close errors re TZ file? +#endif + +#ifdef __UCLIBC_HAS_TZ_FILE__ + +#ifndef __UCLIBC_HAS_TZ_FILE_READ_MANY__ +static smallint TZ_file_read; /* Let BSS initialization set this to 0. */ +#endif + +static char *read_TZ_file(char *buf) +{ + int r; + int fd; + char *p = NULL; + + fd = open(__UCLIBC_TZ_FILE_PATH__, O_RDONLY); + if (fd >= 0) { +#if 0 + /* TZ are small *files*. On files, short reads + * only occur on EOF (unlike, say, pipes). + * The code below is pedanticallly more correct, + * but this way we always read at least twice: + * 1st read is short, 2nd one is zero bytes. + */ + size_t todo = TZ_BUFLEN; + p = buf; + do { + r = read(fd, p, todo); + if (r < 0) + goto ERROR; + if (r == 0) + break; + p += r; + todo -= r; + } while (todo); +#else + /* Shorter, and does one fewer read syscall */ + r = read(fd, buf, TZ_BUFLEN); + if (r < 0) + goto ERROR; + p = buf + r; +#endif + if ((p > buf) && (p[-1] == '\n')) { /* Must end with newline */ + p[-1] = 0; + p = buf; +#ifndef __UCLIBC_HAS_TZ_FILE_READ_MANY__ + TZ_file_read = 1; +#endif + } else { +ERROR: + p = NULL; + } + close(fd); + } +#ifdef __UCLIBC_FALLBACK_TO_ETC_LOCALTIME__ + else { + fd = open("/etc/localtime", O_RDONLY); + if (fd >= 0) { + r = read(fd, buf, TZ_BUFLEN); + if (r != TZ_BUFLEN + || strncmp(buf, "TZif", 4) != 0 + || (unsigned char)buf[4] < 2 + || lseek(fd, -TZ_BUFLEN, SEEK_END) < 0 + ) { + goto ERROR; + } + /* tzfile.h from tzcode database says about TZif2+ files: + ** + ** If tzh_version is '2' or greater, the above is followed by a second instance + ** of tzhead and a second instance of the data in which each coded transition + ** time uses 8 rather than 4 chars, + ** then a POSIX-TZ-environment-variable-style string for use in handling + ** instants after the last transition time stored in the file + ** (with nothing between the newlines if there is no POSIX representation for + ** such instants). + */ + r = read(fd, buf, TZ_BUFLEN); + if (r <= 0 || buf[--r] != '\n') + goto ERROR; + buf[r] = 0; + while (r != 0) { + if (buf[--r] == '\n') { + p = buf + r + 1; +#ifndef __UCLIBC_HAS_TZ_FILE_READ_MANY__ + TZ_file_read = 1; +#endif + break; + } + } /* else ('\n' not found): p remains NULL */ + close(fd); + } + } +#endif /* __UCLIBC_FALLBACK_TO_ETC_LOCALTIME__ */ + return p; +} + +#endif /* __UCLIBC_HAS_TZ_FILE__ */ + +void tzset(void) +{ + _time_tzset((time(NULL)) < new_rule_starts); +} + +void _time_tzset(int use_old_rules) +{ + register const char *e; + register char *s; + long off = 0; + short *p; + rule_struct new_rules[2]; + int n, count, f; + char c; +#ifdef __UCLIBC_HAS_TZ_FILE__ + char buf[TZ_BUFLEN]; +#endif +#ifdef __UCLIBC_HAS_TZ_CACHING__ + static char oldval[TZ_BUFLEN]; /* BSS-zero'd. */ +#endif + + /* Put this inside the lock to prevent the possibility of two different + * timezones being used in a threaded app. */ + __UCLIBC_MUTEX_LOCK(_time_tzlock); + + e = getenv(TZ); /* TZ env var always takes precedence. */ + +#if defined(__UCLIBC_HAS_TZ_FILE__) && !defined(__UCLIBC_HAS_TZ_FILE_READ_MANY__) + if (e) { + /* Never use TZfile if TZ env var is set. */ + TZ_file_read = 0; + } + if (TZ_file_read) { + /* We already parsed TZfile before, skip everything. */ + goto FAST_DONE; + } +#endif + + /* Warning!!! Since uClibc doesn't do lib locking, the following is + * potentially unsafe in a multi-threaded program since it is remotely + * possible that another thread could call setenv() for TZ and overwrite + * the string being parsed. So, don't do that... */ + +#ifdef __UCLIBC_HAS_TZ_FILE__ + if (!e) + e = read_TZ_file(buf); +#endif + if (!e /* TZ env var not set and no TZfile (or bad TZfile) */ + || !*e /* or set to empty string. */ + ) { + goto ILLEGAL; + } + + if (*e == ':') { /* Ignore leading ':'. */ + ++e; + } + +#ifdef __UCLIBC_HAS_TZ_CACHING__ + if (strcmp(e, oldval) == 0) { + /* Same string as last time... nothing to do. */ + goto FAST_DONE; + } + /* Make a copy of the TZ env string. It won't be nul-terminated if + * it is too long, but it that case it will be illegal and will be reset + * to the empty string anyway. */ + strncpy(oldval, e, TZ_BUFLEN); +#endif + + count = 0; + new_rules[1].tzname[0] = 0; +LOOP: + /* Get std or dst name. */ + c = 0; + if (*e == '<') { + ++e; + c = '>'; + } + + s = new_rules[count].tzname; + n = 0; + while (*e + && isascii(*e) /* SUSv3 requires char in portable char set. */ + && (isalpha(*e) + || (c && (isalnum(*e) || (*e == '+') || (*e == '-'))) + ) + ) { + *s++ = *e++; + if (++n > TZNAME_MAX) { + goto ILLEGAL; + } + } + *s = 0; + + if ((n < 3) /* Check for minimum length. */ + || (c && (*e++ != c)) /* Match any quoting '<'. */ + ) { + goto ILLEGAL; + } + + /* Get offset */ + s = (char *) e; + if ((*e != '-') && (*e != '+')) { + if (count && !__isdigit_char(*e)) { + off -= 3600; /* Default to 1 hour ahead of std. */ + goto SKIP_OFFSET; + } + --e; + } + + ++e; + e = getoffset(e, &off); + if (!e) { + goto ILLEGAL; + } + + if (*s == '-') { + off = -off; /* Save off in case needed for dst default. */ + } +SKIP_OFFSET: + new_rules[count].gmt_offset = off; + + if (!count) { + new_rules[1].gmt_offset = off; /* Shouldn't be needed... */ + if (*e) { + ++count; + goto LOOP; + } + } else { /* OK, we have dst, so get some rules. */ + count = 0; + if (!*e) { /* No rules so default to US rules. */ + e = use_old_rules ? DEFAULT_RULES : DEFAULT_2007_RULES; +#ifdef DEBUG_TZSET + if (e == DEFAULT_RULES) + printf("tzset: Using old rules.\n"); + else if (e == DEFAULT_2007_RULES) + printf("tzset: Using new rules\n"); + else + printf("tzset: Using undefined rules\n"); +#endif + } + + do { + if (*e++ != ',') { + goto ILLEGAL; + } + + n = 365; + s = (char *) RULE; + c = *e++; + if (c == 'M') { + n = 12; + } else if (c == 'J') { + s += 8; + } else { + --e; + c = 0; + s += 6; + } + + p = &new_rules[count].rule_type; + *p = c; + if (c != 'M') { + p -= 2; + } + + do { + ++s; + e = getnumber(e, &f); + if (!e + || ((unsigned int)(f - s[1]) > n) + || (*s && (*e++ != *s)) + ) { + goto ILLEGAL; + } + *--p = f; + s += 2; + n = *s; + } while (n > 0); + + off = 2 * 60 * 60; /* Default to 2:00:00 */ + if (*e == '/') { + ++e; + e = getoffset(e, &off); + if (!e) { + goto ILLEGAL; + } + } + new_rules[count].dst_offset = off; + } while (++count < 2); + + if (*e) { +ILLEGAL: +#ifdef __UCLIBC_HAS_TZ_CACHING__ + oldval[0] = 0; /* oldval = "" */ +#endif + memset(_time_tzinfo, 0, sizeof(_time_tzinfo)); + strcpy(_time_tzinfo[0].tzname, UTC); + goto DONE; + } + } + + memcpy(_time_tzinfo, new_rules, sizeof(new_rules)); +DONE: + tzname[0] = _time_tzinfo[0].tzname; + tzname[1] = _time_tzinfo[1].tzname; + daylight = !!_time_tzinfo[1].tzname[0]; + timezone = _time_tzinfo[0].gmt_offset; + +#if defined(__UCLIBC_HAS_TZ_FILE__) || defined(__UCLIBC_HAS_TZ_CACHING__) +FAST_DONE: +#endif + __UCLIBC_MUTEX_UNLOCK(_time_tzlock); +} +libc_hidden_def(tzset) +#endif +/**********************************************************************/ +/* #ifdef L_utime */ + +/* utime is a syscall in both linux and elks. */ +/* int utime(const char *path, const struct utimbuf *times) */ + +/* #endif */ +/**********************************************************************/ +/* Non-SUSv3 */ +/**********************************************************************/ +#ifdef L_utimes + +#ifndef __BCC__ +#error The uClibc version of utimes is in sysdeps/linux/common. +#endif + +#include + +int utimes(const char *filename, register const struct timeval *tvp) +{ + register struct utimbuf *p = NULL; + struct utimbuf utb; + + if (tvp) { + p = &utb; + p->actime = tvp[0].tv_sec; + p->modtime = tvp[1].tv_sec; + } + return utime(filename, p); +} + +#endif +/**********************************************************************/ +#ifdef L__time_t2tm + +static const uint16_t _vals[] = { + 60, 60, 24, 7 /* special */, 36524, 1461, 365, 0 +}; + +static const unsigned char days[] = { + 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, /* non-leap */ + 29, +}; + +#ifdef __UCLIBC_HAS_TM_EXTENSIONS__ +static const char utc_string[] = "UTC"; +#endif + +/* Notes: + * If time_t is 32 bits, then no overflow is possible. + * It time_t is > 32 bits, this needs to be adjusted to deal with overflow. + */ + +/* Note: offset is the correction in _days_ to *timer! */ + +struct tm attribute_hidden *_time_t2tm(const time_t *__restrict timer, + int offset, struct tm *__restrict result) +{ + register int *p; + time_t t1, t, v; + int wday = wday; /* ok to be uninitialized, shutting up warning */ + + { + register const uint16_t *vp; + t = *timer; + p = (int *) result; + p[7] = 0; + vp = _vals; + do { + if ((v = *vp) == 7) { + /* Overflow checking, assuming time_t is long int... */ +#if (LONG_MAX > INT_MAX) && (LONG_MAX > 2147483647L) +#if (INT_MAX == 2147483647L) && (LONG_MAX == 9223372036854775807L) + /* Valid range for t is [-784223472856L, 784223421720L]. + * Outside of this range, the tm_year field will overflow. */ + if (((unsigned long)(t + offset- -784223472856L)) + > (784223421720L - -784223472856L) + ) { + return NULL; + } +#else +#error overflow conditions unknown +#endif +#endif + + /* We have days since the epoch, so caluclate the weekday. */ +#if defined(__BCC__) && TIME_T_IS_UNSIGNED + wday = (t + 4) % (*vp); /* t is unsigned */ +#else + wday = ((int)((t % (*vp)) + 11)) % ((int)(*vp)); /* help bcc */ +#endif + /* Set divisor to days in 400 years. Be kind to bcc... */ + v = ((time_t)(vp[1])) << 2; + ++v; + /* Change to days since 1/1/1601 so that for 32 bit time_t + * values, we'll have t >= 0. This should be changed for + * archs with larger time_t types. + * Also, correct for offset since a multiple of 7. */ + + /* TODO: Does this still work on archs with time_t > 32 bits? */ + t += (135140L - 366) + offset; /* 146097 - (365*30 + 7) -366 */ + } +#if defined(__BCC__) && TIME_T_IS_UNSIGNED + t -= ((t1 = t / v) * v); +#else + if ((t -= ((t1 = t / v) * v)) < 0) { + t += v; + --t1; + } +#endif + + if ((*vp == 7) && (t == v-1)) { + --t; /* Correct for 400th year leap case */ + ++p[4]; /* Stash the extra day... */ + } + +#if defined(__BCC__) && 0 + *p = t1; + if (v <= 60) { + *p = t; + t = t1; + } + ++p; +#else + if (v <= 60) { + *p++ = t; + t = t1; + } else { + *p++ = t1; + } +#endif + } while (*++vp); + } + + if (p[-1] == 4) { + --p[-1]; + t = 365; + } + + *p += ((int) t); /* result[7] .. tm_yday */ + + p -= 2; /* at result[5] */ + +#if (LONG_MAX > INT_MAX) && (LONG_MAX > 2147483647L) + /* Protect against overflow. TODO: Unecessary if int arith wraps? */ + *p = ((((p[-2]<<2) + p[-1])*25 + p[0])<< 2) + (p[1] - 299); /* tm_year */ +#else + *p = ((((p[-2]<<2) + p[-1])*25 + p[0])<< 2) + p[1] - 299; /* tm_year */ +#endif + + p[1] = wday; /* result[6] .. tm_wday */ + + { + register const unsigned char *d = days; + + wday = 1900 + *p; + if (__isleap(wday)) { + d += 11; + } + + wday = p[2] + 1; /* result[7] .. tm_yday */ + *--p = 0; /* at result[4] .. tm_mon */ + while (wday > *d) { + wday -= *d; + if (*d == 29) { + d -= 11; /* Backup to non-leap Feb. */ + } + ++d; + ++*p; /* Increment tm_mon. */ + } + p[-1] = wday; /* result[3] .. tm_mday */ + } + /* TODO -- should this be 0? */ + p[4] = 0; /* result[8] .. tm_isdst */ +#ifdef __UCLIBC_HAS_TM_EXTENSIONS__ +# ifdef __USE_BSD + result->tm_gmtoff = 0; + result->tm_zone = utc_string; +# else + result->__tm_gmtoff = 0; + result->__tm_zone = utc_string; +# endif +#endif /* __UCLIBC_HAS_TM_EXTENSIONS__ */ + + return result; +} + +#endif +/**********************************************************************/ +#ifdef L___time_tm + +struct tm __time_tm; /* Global shared by gmtime() and localtime(). */ + +#endif +/**********************************************************************/ +#ifdef L__time_mktime + +time_t attribute_hidden _time_mktime(struct tm *timeptr, int store_on_success) +{ + time_t t; + + __UCLIBC_MUTEX_LOCK(_time_tzlock); + + tzset(); + + t = _time_mktime_tzi(timeptr, store_on_success, _time_tzinfo); + + __UCLIBC_MUTEX_UNLOCK(_time_tzlock); + + return t; +} + +#endif +/**********************************************************************/ +#ifdef L__time_mktime_tzi + +static const unsigned char __vals[] = { + 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, /* non-leap */ + 29, +}; + +time_t attribute_hidden _time_mktime_tzi(struct tm *timeptr, int store_on_success, + rule_struct *tzi) +{ +#ifdef __BCC__ + long days, secs; +#else + long long secs; +#endif + time_t t; + struct tm x; + /* 0:sec 1:min 2:hour 3:mday 4:mon 5:year 6:wday 7:yday 8:isdst */ + register int *p = (int *) &x; + register const unsigned char *s; + int d, default_dst; + + memcpy(p, timeptr, sizeof(struct tm)); + + if (!tzi[1].tzname[0]) { /* No dst in this timezone, */ + p[8] = 0; /* so set tm_isdst to 0. */ + } + + default_dst = 0; + if (p[8]) { /* Either dst or unknown? */ + default_dst = 1; /* Assume advancing (even if unknown). */ + p[8] = ((p[8] > 0) ? 1 : -1); /* Normalize so abs() <= 1. */ + } + + d = 400; + p[5] = (p[5] - ((p[6] = p[5]/d) * d)) + (p[7] = p[4]/12); + if ((p[4] -= 12 * p[7]) < 0) { + p[4] += 12; + --p[5]; + } + + s = __vals; + d = (p[5] += 1900); /* Correct year. Now between 1900 and 2300. */ + if (__isleap(d)) { + s += 11; + } + + p[7] = 0; + d = p[4]; + while (d) { + p[7] += *s; + if (*s == 29) { + s -= 11; /* Backup to non-leap Feb. */ + } + ++s; + --d; + } + + _time_tzset (x.tm_year < 2007); /* tm_year was expanded above */ + +#ifdef __BCC__ + d = p[5] - 1; + days = -719163L + ((long)d)*365 + ((d/4) - (d/100) + (d/400) + p[3] + p[7]); + secs = p[0] + 60*( p[1] + 60*((long)(p[2])) ) + + tzi[default_dst].gmt_offset; +DST_CORRECT: + if (secs < 0) { + secs += 120009600L; + days -= 1389; + } + if ( ((unsigned long)(days + secs/86400L)) > 49710L) { + t = ((time_t)(-1)); + goto DONE; + } + secs += (days * 86400L); +#else + d = p[5] - 1; + d = -719163L + d*365 + (d/4) - (d/100) + (d/400); + secs = p[0] + + tzi[default_dst].gmt_offset + + 60*( p[1] + + 60*(p[2] + + 24*(((146073L * ((long long)(p[6])) + d) + + p[3]) + p[7]))); + +DST_CORRECT: + if (((unsigned long long)(secs - LONG_MIN)) + > (((unsigned long long)LONG_MAX) - LONG_MIN) + ) { + t = ((time_t)(-1)); + goto DONE; + } +#endif + + d = ((struct tm *)p)->tm_isdst; + t = secs; + + __time_localtime_tzi(&t, (struct tm *)p, tzi); + + if (t == ((time_t)(-1))) { /* Remember, time_t can be unsigned. */ + goto DONE; + } + + if ((d < 0) && (((struct tm *)p)->tm_isdst != default_dst)) { +#ifdef __BCC__ + secs -= (days * 86400L); +#endif + secs += (tzi[1-default_dst].gmt_offset + - tzi[default_dst].gmt_offset); + goto DST_CORRECT; + } + + + if (store_on_success) { + memcpy(timeptr, p, sizeof(struct tm)); + } + + +DONE: + return t; +} + +#endif +/**********************************************************************/ +#if defined(L_wcsftime) || defined(L_wcsftime_l) + +#if defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) + +size_t wcsftime(wchar_t *__restrict s, size_t maxsize, + const wchar_t *__restrict format, + const struct tm *__restrict timeptr) +{ + return wcsftime_l(s, maxsize, format, timeptr, __UCLIBC_CURLOCALE); +} +libc_hidden_def(wcsftime) + +#else /* defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) */ + +libc_hidden_proto(__XL_NPP(wcsftime)) +size_t __XL_NPP(wcsftime)(wchar_t *__restrict s, size_t maxsize, + const wchar_t *__restrict format, + const struct tm *__restrict timeptr __LOCALE_PARAM ) +{ +#warning wcsftime always fails + return 0; /* always fail */ +} +libc_hidden_def(__XL_NPP(wcsftime)) + +#endif /* defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) */ + +#endif +/**********************************************************************/ +#ifdef L_dysize +/* Return the number of days in YEAR. */ + +int dysize(int year) +{ + return __isleap(year) ? 366 : 365; +} + +#endif +/**********************************************************************/ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/timegm.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/timegm.c new file mode 100644 index 00000000..ae2fc7df --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/timegm.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_timegm +#include "time.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/tzset.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/tzset.c new file mode 100644 index 00000000..e5607a51 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/tzset.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_tzset +#include "time.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/wcsftime.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/wcsftime.c new file mode 100644 index 00000000..e4b25c0d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/wcsftime.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_wcsftime +#include "time.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/wcsftime_l.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/wcsftime_l.c new file mode 100644 index 00000000..68c29545 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/time/wcsftime_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_wcsftime_l +#define __UCLIBC_DO_XLOCALE +#include "time.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ttyent/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ttyent/Makefile new file mode 100644 index 00000000..4a8f4a07 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ttyent/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../ +top_builddir=../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ttyent/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ttyent/Makefile.in new file mode 100644 index 00000000..bfa80bec --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ttyent/Makefile.in @@ -0,0 +1,23 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +subdirs += libc/misc/ttyent + +CSRC := getttyent.c + +MISC_TTYENT_DIR := $(top_srcdir)libc/misc/ttyent +MISC_TTYENT_OUT := $(top_builddir)libc/misc/ttyent + +MISC_TTYENT_SRC := $(patsubst %.c,$(MISC_TTYENT_DIR)/%.c,$(CSRC)) +MISC_TTYENT_OBJ := $(patsubst %.c,$(MISC_TTYENT_OUT)/%.o,$(CSRC)) + +libc-y += $(MISC_TTYENT_OBJ) + +objclean-y += CLEAN_libc/misc/ttyent + +CLEAN_libc/misc/ttyent: + $(do_rm) $(addprefix $(MISC_TTYENT_OUT)/*., o os) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ttyent/getttyent.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ttyent/getttyent.c new file mode 100644 index 00000000..474f7f09 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/ttyent/getttyent.c @@ -0,0 +1,208 @@ +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#ifdef __UCLIBC_HAS_THREADS__ +# include +#endif + +static char zapchar; +static FILE *tf; +static struct ttyent tty; + + +/* Skip over the current field, removing quotes, and return + * a pointer to the next field. + */ +#define QUOTED 1 +static char * skip(register char *p) +{ + register char *t; + register int c, q; + + for (q = 0, t = p; (c = *p) != '\0'; p++) { + if (c == '"') { + q ^= QUOTED; /* obscure, but nice */ + continue; + } + if (q == QUOTED && *p == '\\' && *(p+1) == '"') + p++; + *t++ = *p; + if (q == QUOTED) + continue; + if (c == '#') { + zapchar = c; + *p = 0; + break; + } + if (c == '\t' || c == ' ' || c == '\n') { + zapchar = c; + *p++ = 0; + while ((c = *p) == '\t' || c == ' ' || c == '\n') + p++; + break; + } + } + *--t = '\0'; + return (p); +} + +static char * value(register char *p) +{ + + return ((p = strchr(p, '=')) ? ++p : NULL); +} + +int setttyent(void) +{ + + if (tf) { + rewind(tf); + return (1); + } else if ((tf = fopen(_PATH_TTYS, "r"))) { + /* We do the locking ourselves. */ +#ifdef __UCLIBC_HAS_THREADS__ + __fsetlocking (tf, FSETLOCKING_BYCALLER); +#endif + return (1); + } + return (0); +} +libc_hidden_def(setttyent) + +struct ttyent * getttyent(void) +{ + register int c; + register char *p; + static char *line = NULL; + struct ttyent *retval = NULL; + + if (!tf && !setttyent()) + return (NULL); + + if (!line) { + line = malloc(BUFSIZ); + if (!line) + abort(); + } + + __STDIO_ALWAYS_THREADLOCK(tf); + + for (;;) { + if (!fgets_unlocked(p = line, BUFSIZ, tf)) { + goto DONE; + } + /* skip lines that are too big */ + if (!strchr(p, '\n')) { + while ((c = getc_unlocked(tf)) != '\n' && c != EOF) + ; + continue; + } + while (isspace(*p)) + ++p; + if (*p && *p != '#') + break; + } + + zapchar = 0; + tty.ty_name = p; + p = skip(p); + if (!*(tty.ty_getty = p)) + tty.ty_getty = tty.ty_type = NULL; + else { + p = skip(p); + if (!*(tty.ty_type = p)) + tty.ty_type = NULL; + else + p = skip(p); + } + tty.ty_status = 0; + tty.ty_window = NULL; + +#define scmp(e) !strncmp(p, e, sizeof(e) - 1) && isspace(p[sizeof(e) - 1]) +#define vcmp(e) !strncmp(p, e, sizeof(e) - 1) && p[sizeof(e) - 1] == '=' + for (; *p; p = skip(p)) { + if (scmp(_TTYS_OFF)) + tty.ty_status &= ~TTY_ON; + else if (scmp(_TTYS_ON)) + tty.ty_status |= TTY_ON; + else if (scmp(_TTYS_SECURE)) + tty.ty_status |= TTY_SECURE; + else if (vcmp(_TTYS_WINDOW)) + tty.ty_window = value(p); + else + break; + } + + if (zapchar == '#' || *p == '#') + while ((c = *++p) == ' ' || c == '\t') + ; + tty.ty_comment = p; + if (*p == 0) + tty.ty_comment = 0; + if ((p = strchr(p, '\n'))) + *p = '\0'; + retval = &tty; + + DONE: + __STDIO_ALWAYS_THREADUNLOCK(tf); + return retval; +} +libc_hidden_def(getttyent) + +int endttyent(void) +{ + int rval; + + if (tf) { + rval = !(fclose(tf) == EOF); + tf = NULL; + return (rval); + } + return (1); +} +libc_hidden_def(endttyent) + +struct ttyent * getttynam(const char *_tty) +{ + register struct ttyent *t; + + setttyent(); + while ((t = getttyent())) + if (!strcmp(_tty, t->ty_name)) + break; + endttyent(); + return (t); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/utmp/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/utmp/Makefile new file mode 100644 index 00000000..4a8f4a07 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/utmp/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../ +top_builddir=../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/utmp/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/utmp/Makefile.in new file mode 100644 index 00000000..49ae5a50 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/utmp/Makefile.in @@ -0,0 +1,27 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +subdirs += libc/misc/utmp + +CSRC := utent.c wtent.c + +ifeq ($(UCLIBC_HAS_UTMPX),y) +CSRC += utxent.c +endif + +MISC_UTMP_DIR := $(top_srcdir)libc/misc/utmp +MISC_UTMP_OUT := $(top_builddir)libc/misc/utmp + +MISC_UTMP_SRC := $(patsubst %.c,$(MISC_UTMP_DIR)/%.c,$(CSRC)) +MISC_UTMP_OBJ := $(patsubst %.c,$(MISC_UTMP_OUT)/%.o,$(CSRC)) + +libc-y += $(MISC_UTMP_OBJ) + +objclean-y += CLEAN_libc/misc/utmp + +CLEAN_libc/misc/utmp: + $(do_rm) $(addprefix $(MISC_UTMP_OUT)/*., o os) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/utmp/utent.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/utmp/utent.c new file mode 100644 index 00000000..bf265c2a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/utmp/utent.c @@ -0,0 +1,207 @@ +/* utent.c */ +/* Let it be known that this is very possibly the worst standard ever. HP-UX + does one thing, someone else does another, linux another... If anyone + actually has the standard, please send it to me. + + Note that because of the way this stupid stupid standard works, you + have to call endutent() to close the file even if you've not called + setutent -- getutid and family use the same file descriptor. + + Modified by Erik Andersen for uClibc... +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +__UCLIBC_MUTEX_STATIC(utmplock, PTHREAD_MUTEX_INITIALIZER); + + +/* Do not create extra unlocked functions if no locking is needed */ +#if defined __UCLIBC_HAS_THREADS__ +# define static_if_threaded static +#else +# define static_if_threaded /* nothing */ +# define __setutent setutent +# define __getutent getutent +# define __getutid getutid +#endif + + +/* Some global crap */ +static int static_fd = -1; +static struct utmp static_utmp; +static const char default_file_name[] = _PATH_UTMP; +static const char *static_ut_name = default_file_name; + + +/* This function must be called with the LOCK held */ +static_if_threaded void __setutent(void) +{ + if (static_fd < 0) { + static_fd = open_not_cancel_2(static_ut_name, O_RDWR | O_CLOEXEC); + if (static_fd < 0) { + static_fd = open_not_cancel_2(static_ut_name, O_RDONLY | O_CLOEXEC); + if (static_fd < 0) { + return; /* static_fd remains < 0 */ + } + } +#ifndef __ASSUME_O_CLOEXEC + /* Make sure the file will be closed on exec() */ + fcntl_not_cancel(static_fd, F_SETFD, FD_CLOEXEC); +#endif + return; + } + lseek(static_fd, 0, SEEK_SET); +} +#if defined __UCLIBC_HAS_THREADS__ +void setutent(void) +{ + __UCLIBC_MUTEX_LOCK(utmplock); + __setutent(); + __UCLIBC_MUTEX_UNLOCK(utmplock); +} +#endif +libc_hidden_def(setutent) + +/* This function must be called with the LOCK held */ +static_if_threaded struct utmp *__getutent(void) +{ + if (static_fd < 0) { + __setutent(); + if (static_fd < 0) { + return NULL; + } + } + + if (read_not_cancel(static_fd, &static_utmp, sizeof(static_utmp)) == sizeof(static_utmp)) { + return &static_utmp; + } + + return NULL; +} +#if defined __UCLIBC_HAS_THREADS__ +struct utmp *getutent(void) +{ + struct utmp *ret; + + __UCLIBC_MUTEX_LOCK(utmplock); + ret = __getutent(); + __UCLIBC_MUTEX_UNLOCK(utmplock); + return ret; +} +libc_hidden_def(getutent) +#endif + +void endutent(void) +{ + __UCLIBC_MUTEX_LOCK(utmplock); + if (static_fd >= 0) + close_not_cancel_no_status(static_fd); + static_fd = -1; + __UCLIBC_MUTEX_UNLOCK(utmplock); +} +libc_hidden_def(endutent) + +/* This function must be called with the LOCK held */ +static_if_threaded struct utmp *__getutid(const struct utmp *utmp_entry) +{ + struct utmp *lutmp; + unsigned type; + + /* We use the fact that constants we are interested in are: */ + /* RUN_LVL=1, ... OLD_TIME=4; INIT_PROCESS=5, ... USER_PROCESS=8 */ + type = utmp_entry->ut_type - 1; + type /= 4; + + while ((lutmp = __getutent()) != NULL) { + if (type == 0 && lutmp->ut_type == utmp_entry->ut_type) { + /* one of RUN_LVL, BOOT_TIME, NEW_TIME, OLD_TIME */ + return lutmp; + } + if (type == 1 && strncmp(lutmp->ut_id, utmp_entry->ut_id, sizeof(lutmp->ut_id)) == 0) { + /* INIT_PROCESS, LOGIN_PROCESS, USER_PROCESS, DEAD_PROCESS */ + return lutmp; + } + } + + return NULL; +} +#if defined __UCLIBC_HAS_THREADS__ +struct utmp *getutid(const struct utmp *utmp_entry) +{ + struct utmp *ret; + + __UCLIBC_MUTEX_LOCK(utmplock); + ret = __getutid(utmp_entry); + __UCLIBC_MUTEX_UNLOCK(utmplock); + return ret; +} +#endif + +struct utmp *getutline(const struct utmp *utmp_entry) +{ + struct utmp *lutmp; + + __UCLIBC_MUTEX_LOCK(utmplock); + while ((lutmp = __getutent()) != NULL) { + if (lutmp->ut_type == USER_PROCESS || lutmp->ut_type == LOGIN_PROCESS) { + if (strncmp(lutmp->ut_line, utmp_entry->ut_line, sizeof(lutmp->ut_line)) == 0) { + break; + } + } + } + __UCLIBC_MUTEX_UNLOCK(utmplock); + return lutmp; +} +libc_hidden_def(getutline) + +struct utmp *pututline(const struct utmp *utmp_entry) +{ + __UCLIBC_MUTEX_LOCK(utmplock); + /* Ignore the return value. That way, if they've already positioned + the file pointer where they want it, everything will work out. */ + lseek(static_fd, (off_t) - sizeof(struct utmp), SEEK_CUR); + + if (__getutid(utmp_entry) != NULL) + lseek(static_fd, (off_t) - sizeof(struct utmp), SEEK_CUR); + else + lseek(static_fd, (off_t) 0, SEEK_END); + if (write(static_fd, utmp_entry, sizeof(struct utmp)) != sizeof(struct utmp)) + utmp_entry = NULL; + + __UCLIBC_MUTEX_UNLOCK(utmplock); + return (struct utmp *)utmp_entry; +} +libc_hidden_def(pututline) + +int utmpname(const char *new_ut_name) +{ + __UCLIBC_MUTEX_LOCK(utmplock); + if (new_ut_name != NULL) { + if (static_ut_name != default_file_name) + free((char *)static_ut_name); + static_ut_name = strdup(new_ut_name); + if (static_ut_name == NULL) { + /* We should probably whine about out-of-memory + * errors here... Instead just reset to the default */ + static_ut_name = default_file_name; + } + } + + if (static_fd >= 0) { + close_not_cancel_no_status(static_fd); + static_fd = -1; + } + __UCLIBC_MUTEX_UNLOCK(utmplock); + return 0; /* or maybe return -(static_ut_name != new_ut_name)? */ +} +libc_hidden_def(utmpname) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/utmp/utxent.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/utmp/utxent.c new file mode 100644 index 00000000..a0e80a66 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/utmp/utxent.c @@ -0,0 +1,107 @@ +/* + * utexent.c : Support for accessing user accounting database. + * Copyright (C) 2010 STMicroelectronics Ltd. + * + * Author: Salvatore Cro + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + */ + +#include +#include +#include +#include + +void setutxent(void) +{ + setutent (); +} + +void endutxent(void) +{ + endutent (); +} + +struct utmpx *getutxent(void) +{ + return (struct utmpx *) getutent (); +} + +struct utmpx *getutxid(const struct utmpx *utmp_entry) +{ + return (struct utmpx *) getutid ((const struct utmp *) utmp_entry); +} + +struct utmpx *getutxline(const struct utmpx *utmp_entry) +{ + return (struct utmpx *) getutline ((const struct utmp *) utmp_entry); +} + +struct utmpx *pututxline (const struct utmpx *utmp_entry) +{ + return (struct utmpx *) pututline ((const struct utmp *) utmp_entry); +} + +int utmpxname (const char *new_ut_name) +{ + return utmpname (new_ut_name); +} + +void updwtmpx (const char *wtmpx_file, const struct utmpx *utmpx) +{ + updwtmp (wtmpx_file, (const struct utmp *) utmpx); +} + +/* Copy the information in UTMPX to UTMP. */ +void getutmp (const struct utmpx *utmpx, struct utmp *utmp) +{ +#if _HAVE_UT_TYPE - 0 + utmp->ut_type = utmpx->ut_type; +#endif +#if _HAVE_UT_PID - 0 + utmp->ut_pid = utmpx->ut_pid; +#endif + memcpy (utmp->ut_line, utmpx->ut_line, sizeof (utmp->ut_line)); + memcpy (utmp->ut_user, utmpx->ut_user, sizeof (utmp->ut_user)); +#if _HAVE_UT_ID - 0 + memcpy (utmp->ut_id, utmpx->ut_id, sizeof (utmp->ut_id)); +#endif +#if _HAVE_UT_HOST - 0 + memcpy (utmp->ut_host, utmpx->ut_host, sizeof (utmp->ut_host)); +#endif +#if _HAVE_UT_TV - 0 + utmp->ut_tv.tv_sec = utmpx->ut_tv.tv_sec; + utmp->ut_tv.tv_usec = utmpx->ut_tv.tv_usec; +#else + utmp->ut_time = utmpx->ut_time; +#endif +} + +/* Copy the information in UTMP to UTMPX. */ +void getutmpx (const struct utmp *utmp, struct utmpx *utmpx) +{ + memset (utmpx, 0, sizeof (struct utmpx)); + +#if _HAVE_UT_TYPE - 0 + utmpx->ut_type = utmp->ut_type; +#endif +#if _HAVE_UT_PID - 0 + utmpx->ut_pid = utmp->ut_pid; +#endif + memcpy (utmpx->ut_line, utmp->ut_line, sizeof (utmp->ut_line)); + memcpy (utmpx->ut_user, utmp->ut_user, sizeof (utmp->ut_user)); +#if _HAVE_UT_ID - 0 + memcpy (utmpx->ut_id, utmp->ut_id, sizeof (utmp->ut_id)); +#endif +#if _HAVE_UT_HOST - 0 + memcpy (utmpx->ut_host, utmp->ut_host, sizeof (utmp->ut_host)); +#endif +#if _HAVE_UT_TV - 0 + utmpx->ut_tv.tv_sec = utmp->ut_tv.tv_sec; + utmpx->ut_tv.tv_usec = utmp->ut_tv.tv_usec; +#else + utmpx->ut_time = utmp->ut_time; +#endif +} + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/utmp/wtent.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/utmp/wtent.c new file mode 100644 index 00000000..c97f89cf --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/utmp/wtent.c @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* wtmp support rubbish (i.e. complete crap) */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#if 0 +/* This is enabled in uClibc/libutil/logwtmp.c */ +void logwtmp (const char *line, const char *name, const char *host) +{ + struct utmp lutmp; + memset(&lutmp, 0, sizeof(lutmp)); + + lutmp.ut_type = (name && *name) ? USER_PROCESS : DEAD_PROCESS; + lutmp.ut_pid = getpid(); + strncpy(lutmp.ut_line, line, sizeof(lutmp.ut_line)-1); + strncpy(lutmp.ut_name, name, sizeof(lutmp.ut_name)-1); + strncpy(lutmp.ut_host, host, sizeof(lutmp.ut_host)-1); + gettimeofday(&(lutmp.ut_tv), NULL); + + updwtmp(_PATH_WTMP, &lutmp); +} +#endif + +void updwtmp(const char *wtmp_file, const struct utmp *lutmp) +{ + int fd; + + fd = open_not_cancel(wtmp_file, O_APPEND | O_WRONLY, 0); + if (fd >= 0) { + if (lockf(fd, F_LOCK, 0) == 0) { + write_not_cancel(fd, lutmp, sizeof(struct utmp)); + lockf(fd, F_ULOCK, 0); + close_not_cancel_no_status(fd); + } + } +} +libc_hidden_def(updwtmp) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wchar/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wchar/Makefile new file mode 100644 index 00000000..4a8f4a07 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wchar/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../ +top_builddir=../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wchar/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wchar/Makefile.in new file mode 100644 index 00000000..be95a186 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wchar/Makefile.in @@ -0,0 +1,41 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +# The stdio and time related wide functions are now built in the normal +# directories. +# +# stdio: +# fwide fgetwc getwchar fgetws fputwc putwchar fputws ungetwc +# getwc (fgetwc alias) getwc_unlocked (fgetwc_unlocked alias) +# putwc (fputwc alias) putwc_unlocked (fputwc_unlocked alias) +# time: +# wcsftime +# + +subdirs += libc/misc/wchar + +# multi source wchar.c +CSRC := btowc.c wctob.c mbsinit.c mbrlen.c mbrtowc.c wcrtomb.c mbsrtowcs.c \ + wcsrtombs.c _wchar_utf8sntowcs.c _wchar_wcsntoutf8s.c \ + mbsnrtowcs.c wcsnrtombs.c wcwidth.c wcswidth.c + +ifeq ($(UCLIBC_HAS_LOCALE),y) +CSRC += iconv.c +endif + +MISC_WCHAR_DIR := $(top_srcdir)libc/misc/wchar +MISC_WCHAR_OUT := $(top_builddir)libc/misc/wchar + +MISC_WCHAR_SRC := $(patsubst %.c,$(MISC_WCHAR_DIR)/%.c,$(CSRC)) +MISC_WCHAR_OBJ := $(patsubst %.c,$(MISC_WCHAR_OUT)/%.o,$(CSRC)) + +libc-$(UCLIBC_HAS_WCHAR) += $(MISC_WCHAR_OBJ) + +objclean-y += CLEAN_libc/misc/wchar + +CLEAN_libc/misc/wchar: + $(do_rm) $(addprefix $(MISC_WCHAR_OUT)/*., o os) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wchar/_wchar_utf8sntowcs.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wchar/_wchar_utf8sntowcs.c new file mode 100644 index 00000000..a01990eb --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wchar/_wchar_utf8sntowcs.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L__wchar_utf8sntowcs +#include "wchar.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wchar/_wchar_wcsntoutf8s.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wchar/_wchar_wcsntoutf8s.c new file mode 100644 index 00000000..a63aa911 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wchar/_wchar_wcsntoutf8s.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L__wchar_wcsntoutf8s +#include "wchar.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wchar/btowc.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wchar/btowc.c new file mode 100644 index 00000000..d5e60ce6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wchar/btowc.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_btowc +#include "wchar.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wchar/iconv.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wchar/iconv.c new file mode 100644 index 00000000..e6e8ea88 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wchar/iconv.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_iconv +#include "wchar.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wchar/mbrlen.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wchar/mbrlen.c new file mode 100644 index 00000000..01bd31eb --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wchar/mbrlen.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_mbrlen +#include "wchar.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wchar/mbrtowc.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wchar/mbrtowc.c new file mode 100644 index 00000000..76ce28a7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wchar/mbrtowc.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_mbrtowc +#include "wchar.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wchar/mbsinit.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wchar/mbsinit.c new file mode 100644 index 00000000..23aaac50 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wchar/mbsinit.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_mbsinit +#include "wchar.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wchar/mbsnrtowcs.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wchar/mbsnrtowcs.c new file mode 100644 index 00000000..9b407c1d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wchar/mbsnrtowcs.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_mbsnrtowcs +#include "wchar.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wchar/mbsrtowcs.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wchar/mbsrtowcs.c new file mode 100644 index 00000000..dd47a91a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wchar/mbsrtowcs.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_mbsrtowcs +#include "wchar.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wchar/wchar.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wchar/wchar.c new file mode 100644 index 00000000..ab6c617e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wchar/wchar.c @@ -0,0 +1,1565 @@ + +/* Copyright (C) 2002, 2003, 2004 Manuel Novoa III + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION! + * + * Besides uClibc, I'm using this code in my libc for elks, which is + * a 16-bit environment with a fairly limited compiler. It would make + * things much easier for me if this file isn't modified unnecessarily. + * In particular, please put any new or replacement functions somewhere + * else, and modify the makefile to use your version instead. + * Thanks. Manuel + * + * ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION! */ + + +/* May 23, 2002 Initial Notes: + * + * I'm still tweaking this stuff, but it passes the tests I've thrown + * at it, and Erik needs it for the gcc port. The glibc extension + * __wcsnrtombs() hasn't been tested, as I didn't find a test for it + * in the glibc source. I also need to fix the behavior of + * _wchar_utf8sntowcs() if the max number of wchars to convert is 0. + * + * UTF-8 -> wchar -> UTF-8 conversion tests on Markus Kuhn's UTF-8-demo.txt + * file on my platform (x86) show about 5-10% faster conversion speed than + * glibc with mbsrtowcs()/wcsrtombs() and almost twice as fast as glibc with + * individual mbrtowc()/wcrtomb() calls. + * + * If 'DECODER' is defined, then _wchar_utf8sntowcs() will be compiled + * as a fail-safe UTF-8 decoder appropriate for a terminal, etc. which + * needs to deal gracefully with whatever is sent to it. In that mode, + * it passes Markus Kuhn's UTF-8-test.txt stress test. I plan to add + * an arg to force that behavior, so the interface will be changing. + * + * I need to fix the error checking for 16-bit wide chars. This isn't + * an issue for uClibc, but may be for ELKS. I'm currently not sure + * if I'll use 16-bit, 32-bit, or configureable wchars in ELKS. + * + * July 1, 2002 + * + * Fixed _wchar_utf8sntowcs() for the max number of wchars == 0 case. + * Fixed nul-char bug in btowc(), and another in __mbsnrtowcs() for 8-bit + * locales. + * Enabled building of a C/POSIX-locale-only version, so full locale support + * no longer needs to be enabled. + * + * Nov 4, 2002 + * + * Fixed a bug in _wchar_wcsntoutf8s(). Don't store wcs position if dst is NULL. + * Also, introduce an awful hack into _wchar_wcsntoutf8s() and wcsrtombs() in + * order to support %ls in printf. See comments below for details. + * Change behaviour of wc<->mb functions when in the C locale. Now they do + * a 1-1 map for the range 0x80-UCHAR_MAX. This is for backwards compatibility + * and consistency with the stds requirements that a printf format string by + * a valid multibyte string beginning and ending in it's initial shift state. + * + * Nov 5, 2002 + * + * Forgot to change btowc and wctob when I changed the wc<->mb functions yesterday. + * + * Nov 7, 2002 + * + * Add wcwidth and wcswidth, based on Markus Kuhn's wcwidth of 2002-05-08. + * Added some size/speed optimizations and integrated it into my locale + * framework. Minimally tested at the moment, but the stub C-locale + * version (which most people would probably be using) should be fine. + * + * Nov 21, 2002 + * + * Revert the wc<->mb changes from earlier this month involving the C-locale. + * Add a couple of ugly hacks to support *wprintf. + * Add a mini iconv() and iconv implementation (requires locale support). + * + * Aug 1, 2003 + * Bug fix for mbrtowc. + * + * Aug 18, 2003 + * Bug fix: _wchar_utf8sntowcs and _wchar_wcsntoutf8s now set errno if EILSEQ. + * + * Feb 11, 2004 + * Bug fix: Fix size check for remaining output space in iconv(). + * + * Manuel + */ +#ifdef _LIBC +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/**********************************************************************/ +#ifdef __UCLIBC_HAS_LOCALE__ +#ifdef __UCLIBC_MJN3_ONLY__ +#ifdef L_iswspace +/* generates one warning */ +#warning TODO: Fix Cc2wc* and Cwc2c* defines! +#endif +#endif /* __UCLIBC_MJN3_ONLY__ */ + +#define ENCODING (__UCLIBC_CURLOCALE->encoding) + +#define Cc2wc_IDX_SHIFT __LOCALE_DATA_Cc2wc_IDX_SHIFT +#define Cc2wc_ROW_LEN __LOCALE_DATA_Cc2wc_ROW_LEN +#define Cwc2c_DOMAIN_MAX __LOCALE_DATA_Cwc2c_DOMAIN_MAX +#define Cwc2c_TI_SHIFT __LOCALE_DATA_Cwc2c_TI_SHIFT +#define Cwc2c_TT_SHIFT __LOCALE_DATA_Cwc2c_TT_SHIFT +#define Cwc2c_TI_LEN __LOCALE_DATA_Cwc2c_TI_LEN + +#ifndef __CTYPE_HAS_UTF_8_LOCALES +#warning __CTYPE_HAS_UTF_8_LOCALES not set! +#endif + +#else /* __UCLIBC_HAS_LOCALE__ */ + +#ifdef __UCLIBC_MJN3_ONLY__ +#ifdef L_btowc +/* emit only once */ +#warning fix preprocessor logic testing locale settings +#endif +#endif + +#define ENCODING (__ctype_encoding_7_bit) +#ifdef __CTYPE_HAS_8_BIT_LOCALES +#error __CTYPE_HAS_8_BIT_LOCALES is defined! +#endif +#ifdef __CTYPE_HAS_UTF_8_LOCALES +#error __CTYPE_HAS_UTF_8_LOCALES is defined! +#endif +#undef L__wchar_utf8sntowcs +#undef L__wchar_wcsntoutf8s + +#endif /* __UCLIBC_HAS_LOCALE__ */ +/**********************************************************************/ + +#if WCHAR_MAX > 0xffffUL +#define UTF_8_MAX_LEN 6 +#else +#define UTF_8_MAX_LEN 3 +#endif + +#define KUHN 1 + +/* Implementation-specific work functions. */ + +extern size_t _wchar_utf8sntowcs(wchar_t *__restrict pwc, size_t wn, + const char **__restrict src, size_t n, + mbstate_t *ps, int allow_continuation) attribute_hidden; + +extern size_t _wchar_wcsntoutf8s(char *__restrict s, size_t n, + const wchar_t **__restrict src, size_t wn) attribute_hidden; +#endif +/**********************************************************************/ +#ifdef L_btowc + + +wint_t btowc(int c) +{ +#ifdef __CTYPE_HAS_8_BIT_LOCALES + + wchar_t wc; + unsigned char buf[1]; + mbstate_t mbstate; + + if (c != EOF) { + *buf = (unsigned char) c; + mbstate.__mask = 0; /* Initialize the mbstate. */ + if (mbrtowc(&wc, (char*) buf, 1, &mbstate) <= 1) { + return wc; + } + } + return WEOF; + +#else /* !__CTYPE_HAS_8_BIT_LOCALES */ + +#ifdef __UCLIBC_HAS_LOCALE__ + assert((ENCODING == __ctype_encoding_7_bit) + || (ENCODING == __ctype_encoding_utf8)); +#endif + + /* If we don't have 8-bit locale support, then this is trivial since + * anything outside of 0-0x7f is illegal in C/POSIX and UTF-8 locales. */ + return (((unsigned int)c) < 0x80) ? c : WEOF; + +#endif /* !__CTYPE_HAS_8_BIT_LOCALES */ +} +libc_hidden_def(btowc) + +#endif +/**********************************************************************/ +#ifdef L_wctob + +/* Note: We completely ignore ps in all currently supported conversions. */ + + +int wctob(wint_t c) +{ +#ifdef __CTYPE_HAS_8_BIT_LOCALES + + unsigned char buf[MB_LEN_MAX]; + + return (wcrtomb((char*) buf, c, NULL) == 1) ? *buf : EOF; + +#else /* __CTYPE_HAS_8_BIT_LOCALES */ + +#ifdef __UCLIBC_HAS_LOCALE__ + assert((ENCODING == __ctype_encoding_7_bit) + || (ENCODING == __ctype_encoding_utf8)); +#endif /* __UCLIBC_HAS_LOCALE__ */ + + /* If we don't have 8-bit locale support, then this is trivial since + * anything outside of 0-0x7f is illegal in C/POSIX and UTF-8 locales. */ + + /* TODO: need unsigned version of wint_t... */ +/* return (((unsigned int)c) < 0x80) ? c : WEOF; */ + return ((c >= 0) && (c < 0x80)) ? c : EOF; + +#endif /* __CTYPE_HAS_8_BIT_LOCALES */ +} + +#endif +/**********************************************************************/ +#ifdef L_mbsinit + +int mbsinit(const mbstate_t *ps) +{ + return !ps || !ps->__mask; +} +libc_hidden_def(mbsinit) + +#endif +/**********************************************************************/ +#ifdef L_mbrlen + + +size_t mbrlen(const char *__restrict s, size_t n, mbstate_t *__restrict ps) +{ + static mbstate_t mbstate; /* Rely on bss 0-init. */ + + return mbrtowc(NULL, s, n, (ps != NULL) ? ps : &mbstate); +} +libc_hidden_def(mbrlen) + +#endif +/**********************************************************************/ +#ifdef L_mbrtowc + + +size_t mbrtowc(wchar_t *__restrict pwc, const char *__restrict s, + size_t n, mbstate_t *__restrict ps) +{ + static mbstate_t mbstate; /* Rely on bss 0-init. */ + wchar_t wcbuf[1]; + const char *p; + size_t r; + char empty_string[1]; /* Avoid static to be fPIC friendly. */ + + if (!ps) { + ps = &mbstate; + } + + if (!s) { + pwc = (wchar_t *) s; /* NULL */ + empty_string[0] = 0; /* Init the empty string when necessary. */ + s = empty_string; + n = 1; + } else if (*s == '\0') { + if (pwc) + *pwc = '\0'; + /* According to the ISO C 89 standard this is the expected behaviour. */ + return 0; + } else if (!n) { + /* TODO: change error code? */ +#if 0 + return (ps->__mask && (ps->__wc == 0xffffU)) + ? ((size_t) -1) : ((size_t) -2); +#else + return 0; +#endif + } + + p = s; + +#ifdef __CTYPE_HAS_UTF_8_LOCALES + /* Need to do this here since mbsrtowcs doesn't allow incompletes. */ + if (ENCODING == __ctype_encoding_utf8) { + if (!pwc) { + pwc = wcbuf; + } + r = _wchar_utf8sntowcs(pwc, 1, &p, n, ps, 1); + return (r == 1) ? (p-s) : r; /* Need to return 0 if nul char. */ + } +#endif + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning TODO: This adds a trailing nul! +#endif /* __UCLIBC_MJN3_ONLY__ */ + + r = mbsnrtowcs(wcbuf, &p, SIZE_MAX, 1, ps); + + if (((ssize_t) r) >= 0) { + if (pwc) { + *pwc = *wcbuf; + } + } + return (size_t) r; +} +libc_hidden_def(mbrtowc) + +#endif +/**********************************************************************/ +#ifdef L_wcrtomb + + +/* Note: We completely ignore ps in all currently supported conversions. */ +/* TODO: Check for valid state anyway? */ + +size_t wcrtomb(register char *__restrict s, wchar_t wc, + mbstate_t *__restrict ps) +{ +#ifdef __UCLIBC_MJN3_ONLY__ +#warning TODO: Should wcsnrtombs nul-terminate unconditionally? Check glibc. +#endif /* __UCLIBC_MJN3_ONLY__ */ + wchar_t wcbuf[1]; + const wchar_t *pwc; + size_t r; + char buf[MB_LEN_MAX]; + + if (!s) { + s = buf; + wc = 0; + } + + pwc = wcbuf; + wcbuf[0] = wc; + + r = wcsnrtombs(s, &pwc, 1, MB_LEN_MAX, ps); + return (r != 0) ? r : 1; +} +libc_hidden_def(wcrtomb) + +#endif +/**********************************************************************/ +#ifdef L_mbsrtowcs + + +size_t mbsrtowcs(wchar_t *__restrict dst, const char **__restrict src, + size_t len, mbstate_t *__restrict ps) +{ + static mbstate_t mbstate; /* Rely on bss 0-init. */ + + return mbsnrtowcs(dst, src, SIZE_MAX, len, + ((ps != NULL) ? ps : &mbstate)); +} +libc_hidden_def(mbsrtowcs) + +#endif +/**********************************************************************/ +#ifdef L_wcsrtombs + +/* Note: We completely ignore ps in all currently supported conversions. + + * TODO: Check for valid state anyway? */ + + +size_t wcsrtombs(char *__restrict dst, const wchar_t **__restrict src, + size_t len, mbstate_t *__restrict ps) +{ + return wcsnrtombs(dst, src, SIZE_MAX, len, ps); +} +libc_hidden_def(wcsrtombs) + +#endif +/**********************************************************************/ +#ifdef L__wchar_utf8sntowcs + +/* Define DECODER to generate a UTF-8 decoder which passes Markus Kuhn's + * UTF-8-test.txt strss test. + */ +/* #define DECODER */ + +#ifdef DECODER +#ifndef KUHN +#define KUHN +#endif +#endif + +size_t attribute_hidden _wchar_utf8sntowcs(wchar_t *__restrict pwc, size_t wn, + const char **__restrict src, size_t n, + mbstate_t *ps, int allow_continuation) +{ + register const char *s; + __uwchar_t mask; + __uwchar_t wc; + wchar_t wcbuf[1]; + size_t count; + int incr; + + s = *src; + + assert(s != NULL); + assert(ps != NULL); + + incr = 1; + /* NOTE: The following is an AWFUL HACK! In order to support %s in + * wprintf, we need to be able to compute the number of wchars needed + * for the mbs conversion, not to exceed the precision specified. + * But if dst is NULL, the return value is the length assuming a + * sufficiently sized buffer. So, we allow passing of (wchar_t *) ps + * as pwc in order to flag that we really want the length, subject + * to the restricted buffer size and no partial conversions. + * See mbsnrtowcs() as well. */ + if (!pwc || (pwc == ((wchar_t *)ps))) { + if (!pwc) { + wn = SIZE_MAX; + } + pwc = wcbuf; + incr = 0; + } + + /* This is really here only to support the glibc extension function + * __mbsnrtowcs which apparently returns 0 if wn == 0 without any + * check on the validity of the mbstate. */ + if (!(count = wn)) { + return 0; + } + + if ((mask = (__uwchar_t) ps->__mask) != 0) { /* A continuation... */ +#ifdef DECODER + wc = (__uwchar_t) ps->__wc; + if (n) { + goto CONTINUE; + } + goto DONE; +#else + if ((wc = (__uwchar_t) ps->__wc) != 0xffffU) { + /* TODO: change error code here and below? */ + if (n) { + goto CONTINUE; + } + goto DONE; + } + __set_errno(EILSEQ); + return (size_t) -1; /* We're in an error state. */ +#endif + } + + do { + if (!n) { + goto DONE; + } + --n; + if ((wc = ((unsigned char) *s++)) >= 0x80) { /* Not ASCII... */ + mask = 0x40; +#ifdef __UCLIBC_MJN3_ONLY__ +#warning TODO: Fix range for 16 bit wchar_t case. +#endif + if (( ((unsigned char)(s[-1] - 0xc0)) < (0xfe - 0xc0) ) && + (((unsigned char)s[-1] != 0xc0 ) && ((unsigned char)s[-1] != 0xc1 ))) { + goto START; + } + BAD: +#ifdef DECODER + wc = 0xfffdU; + goto COMPLETE; +#else + ps->__mask = mask; + ps->__wc = 0xffffU; + __set_errno(EILSEQ); + return (size_t) -1; /* Illegal start byte! */ +#endif + + CONTINUE: + while (n) { + --n; + if ((*s & 0xc0) != 0x80) { + goto BAD; + } + mask <<= 5; + wc <<= 6; + wc += (*s & 0x3f); /* keep seperate for bcc (smaller code) */ + ++s; + START: + wc &= ~(mask << 1); + + if ((wc & mask) == 0) { /* Character completed. */ + if ((mask >>= 5) == 0x40) { + mask += mask; + } + /* Check for invalid sequences (longer than necessary) + * and invalid chars. */ + if ( (wc < mask) /* Sequence not minimal length. */ +#ifdef KUHN +#if UTF_8_MAX_LEN == 3 +#error broken since mask can overflow!! + /* For plane 0, these are the only defined values.*/ + || (wc > 0xfffdU) +#else + /* Note that we don't need to worry about exceeding */ + /* 31 bits as that is the most that UTF-8 provides. */ + || ( ((__uwchar_t)(wc - 0xfffeU)) < 2) +#endif + || ( ((__uwchar_t)(wc - 0xd800U)) < (0xe000U - 0xd800U) ) +#endif /* KUHN */ + ) { + goto BAD; + } + goto COMPLETE; + } + } + /* Character potentially valid but incomplete. */ + if (!allow_continuation) { + if (count != wn) { + return 0; + } + /* NOTE: The following can fail if you allow and then disallow + * continuation!!! */ +#if UTF_8_MAX_LEN == 3 +#error broken since mask can overflow!! +#endif + /* Need to back up... */ + do { + --s; + } while ((mask >>= 5) >= 0x40); + goto DONE; + } + ps->__mask = (wchar_t) mask; + ps->__wc = (wchar_t) wc; + *src = s; + return (size_t) -2; + } + COMPLETE: + *pwc = wc; + pwc += incr; + } +#ifdef DECODER + while (--count); +#else + while (wc && --count); + + if (!wc) { + s = NULL; + } +#endif + + DONE: + /* ps->__wc is irrelavent here. */ + ps->__mask = 0; + if (pwc != wcbuf) { + *src = s; + } + + return wn - count; +} + +#endif +/**********************************************************************/ +#ifdef L__wchar_wcsntoutf8s + +size_t attribute_hidden _wchar_wcsntoutf8s(char *__restrict s, size_t n, + const wchar_t **__restrict src, size_t wn) +{ + register char *p; + size_t len, t; + __uwchar_t wc; + const __uwchar_t *swc; + int store; + char buf[MB_LEN_MAX]; + char m; + + store = 1; + /* NOTE: The following is an AWFUL HACK! In order to support %ls in + * printf, we need to be able to compute the number of bytes needed + * for the mbs conversion, not to exceed the precision specified. + * But if dst is NULL, the return value is the length assuming a + * sufficiently sized buffer. So, we allow passing of (char *) src + * as dst in order to flag that we really want the length, subject + * to the restricted buffer size and no partial conversions. + * See wcsnrtombs() as well. */ + if (!s || (s == ((char *) src))) { + if (!s) { + n = SIZE_MAX; + } + s = buf; + store = 0; + } + + t = n; + swc = (const __uwchar_t *) *src; + + assert(swc != NULL); + + while (wn && t) { + wc = *swc; + + *s = wc; + len = 1; + + if (wc >= 0x80) { +#ifdef KUHN + if ( +#if UTF_8_MAX_LEN == 3 + /* For plane 0, these are the only defined values.*/ + /* Note that we don't need to worry about exceeding */ + /* 31 bits as that is the most that UTF-8 provides. */ + (wc > 0xfffdU) +#else + /* UTF_8_MAX_LEN == 6 */ + (wc > 0x7fffffffUL) + || ( ((__uwchar_t)(wc - 0xfffeU)) < 2) +#endif + || ( ((__uwchar_t)(wc - 0xd800U)) < (0xe000U - 0xd800U) ) + ) { + __set_errno(EILSEQ); + return (size_t) -1; + } +#else /* KUHN */ +#if UTF_8_MAX_LEN != 3 + if (wc > 0x7fffffffUL) { /* Value too large. */ + __set_errno(EILSEQ); + return (size_t) -1; + } +#endif +#endif /* KUHN */ + + wc >>= 1; + p = s; + do { + ++p; + } while (wc >>= 5); + wc = *swc; + if ((len = p - s) > t) { /* Not enough space. */ + break; + } + + m = 0x80; + while( p>s ) { + m = (m >> 1) | 0x80; + *--p = (wc & 0x3f) | 0x80; + wc >>= 6; + } + *s |= (m << 1); + } else if (wc == 0) { /* End of string. */ + swc = NULL; + break; + } + + ++swc; + --wn; + t -= len; + if (store) { + s += len; + } + } + + if (store) { + *src = (const wchar_t *) swc; + } + + return n - t; +} + + +#endif +/**********************************************************************/ +#ifdef L_mbsnrtowcs + +/* WARNING: We treat len as SIZE_MAX when dst is NULL! */ + +size_t mbsnrtowcs(wchar_t *__restrict dst, const char **__restrict src, + size_t NMC, size_t len, mbstate_t *__restrict ps) +{ + static mbstate_t mbstate; /* Rely on bss 0-init. */ + wchar_t wcbuf[1]; + const char *s; + size_t count; + int incr; + + if (!ps) { + ps = &mbstate; + } + +#ifdef __CTYPE_HAS_UTF_8_LOCALES + if (ENCODING == __ctype_encoding_utf8) { + size_t r; + return ((r = _wchar_utf8sntowcs(dst, len, src, NMC, ps, 1)) + != (size_t) -2) ? r : 0; + } +#endif + incr = 1; + /* NOTE: The following is an AWFUL HACK! In order to support %s in + * wprintf, we need to be able to compute the number of wchars needed + * for the mbs conversion, not to exceed the precision specified. + * But if dst is NULL, the return value is the length assuming a + * sufficiently sized buffer. So, we allow passing of ((wchar_t *)ps) + * as dst in order to flag that we really want the length, subject + * to the restricted buffer size and no partial conversions. + * See _wchar_utf8sntowcs() as well. */ + if (!dst || (dst == ((wchar_t *)ps))) { + if (!dst) { + len = SIZE_MAX; + } + dst = wcbuf; + incr = 0; + } + + /* Since all the following encodings are single-byte encodings... */ + if (len > NMC) { + len = NMC; + } + + count = len; + s = *src; + +#ifdef __CTYPE_HAS_8_BIT_LOCALES + if (ENCODING == __ctype_encoding_8_bit) { + wchar_t wc; + while (count) { + if ((wc = ((unsigned char)(*s))) >= 0x80) { /* Non-ASCII... */ + wc -= 0x80; + wc = __UCLIBC_CURLOCALE->tbl8c2wc[ + (__UCLIBC_CURLOCALE->idx8c2wc[wc >> Cc2wc_IDX_SHIFT] + << Cc2wc_IDX_SHIFT) + (wc & (Cc2wc_ROW_LEN - 1))]; + if (!wc) { + goto BAD; + } + } + if (!(*dst = wc)) { + s = NULL; + break; + } + dst += incr; + ++s; + --count; + } + if (dst != wcbuf) { + *src = s; + } + return len - count; + } +#endif + +#ifdef __UCLIBC_HAS_LOCALE__ + assert(ENCODING == __ctype_encoding_7_bit); +#endif + + while (count) { + if ((*dst = (unsigned char) *s) == 0) { + s = NULL; + break; + } + if (*dst >= 0x80) { +#ifdef __CTYPE_HAS_8_BIT_LOCALES + BAD: +#endif + __set_errno(EILSEQ); + return (size_t) -1; + } + ++s; + dst += incr; + --count; + } + if (dst != wcbuf) { + *src = s; + } + return len - count; +} +libc_hidden_def(mbsnrtowcs) + +#endif +/**********************************************************************/ +#ifdef L_wcsnrtombs + +/* WARNING: We treat len as SIZE_MAX when dst is NULL! */ + +/* Note: We completely ignore ps in all currently supported conversions. + * TODO: Check for valid state anyway? */ + +size_t wcsnrtombs(char *__restrict dst, const wchar_t **__restrict src, + size_t NWC, size_t len, mbstate_t *__restrict ps) +{ + const __uwchar_t *s; + size_t count; + int incr; + char buf[MB_LEN_MAX]; + +#ifdef __CTYPE_HAS_UTF_8_LOCALES + if (ENCODING == __ctype_encoding_utf8) { + return _wchar_wcsntoutf8s(dst, len, src, NWC); + } +#endif /* __CTYPE_HAS_UTF_8_LOCALES */ + + incr = 1; + /* NOTE: The following is an AWFUL HACK! In order to support %ls in + * printf, we need to be able to compute the number of bytes needed + * for the mbs conversion, not to exceed the precision specified. + * But if dst is NULL, the return value is the length assuming a + * sufficiently sized buffer. So, we allow passing of (char *) src + * as dst in order to flag that we really want the length, subject + * to the restricted buffer size and no partial conversions. + * See _wchar_wcsntoutf8s() as well. */ + if (!dst || (dst == ((char *) src))) { + if (!dst) { + len = SIZE_MAX; + } + dst = buf; + incr = 0; + } + + /* Since all the following encodings are single-byte encodings... */ + if (len > NWC) { + len = NWC; + } + + count = len; + s = (const __uwchar_t *) *src; + +#ifdef __CTYPE_HAS_8_BIT_LOCALES + if (ENCODING == __ctype_encoding_8_bit) { + __uwchar_t wc; + __uwchar_t u; + while (count) { + if ((wc = *s) <= 0x7f) { + if (!(*dst = (unsigned char) wc)) { + s = NULL; + break; + } + } else { + u = 0; + if (wc <= Cwc2c_DOMAIN_MAX) { + u = __UCLIBC_CURLOCALE->idx8wc2c[wc >> (Cwc2c_TI_SHIFT + + Cwc2c_TT_SHIFT)]; + u = __UCLIBC_CURLOCALE->tbl8wc2c[(u << Cwc2c_TI_SHIFT) + + ((wc >> Cwc2c_TT_SHIFT) + & ((1 << Cwc2c_TI_SHIFT)-1))]; + u = __UCLIBC_CURLOCALE->tbl8wc2c[Cwc2c_TI_LEN + + (u << Cwc2c_TT_SHIFT) + + (wc & ((1 << Cwc2c_TT_SHIFT)-1))]; + } + +#ifdef __WCHAR_REPLACEMENT_CHAR + *dst = (unsigned char) ( u ? u : __WCHAR_REPLACEMENT_CHAR ); +#else /* __WCHAR_REPLACEMENT_CHAR */ + if (!u) { + goto BAD; + } + *dst = (unsigned char) u; +#endif /* __WCHAR_REPLACEMENT_CHAR */ + } + ++s; + dst += incr; + --count; + } + if (dst != buf) { + *src = (const wchar_t *) s; + } + return len - count; + } +#endif /* __CTYPE_HAS_8_BIT_LOCALES */ + +#ifdef __UCLIBC_HAS_LOCALE__ + assert(ENCODING == __ctype_encoding_7_bit); +#endif + + while (count) { + if (*s >= 0x80) { +#if defined(__CTYPE_HAS_8_BIT_LOCALES) && !defined(__WCHAR_REPLACEMENT_CHAR) + BAD: +#endif + __set_errno(EILSEQ); + return (size_t) -1; + } + if ((*dst = (unsigned char) *s) == 0) { + s = NULL; + break; + } + ++s; + dst += incr; + --count; + } + if (dst != buf) { + *src = (const wchar_t *) s; + } + return len - count; +} +libc_hidden_def(wcsnrtombs) + +#endif +/**********************************************************************/ +#ifdef L_wcswidth + + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning REMINDER: If we start doing translit, wcwidth and wcswidth will need updating. +#warning TODO: Update wcwidth to match latest by Kuhn. +#endif + +#if defined(__UCLIBC_HAS_LOCALE__) && \ +( defined(__CTYPE_HAS_8_BIT_LOCALES) || defined(__CTYPE_HAS_UTF_8_LOCALES) ) + +static const unsigned char new_idx[] = { + 0, 5, 5, 6, 10, 15, 28, 39, + 48, 48, 71, 94, 113, 128, 139, 154, + 175, 186, 188, 188, 188, 188, 188, 188, + 203, 208, 208, 208, 208, 208, 208, 208, + 208, 219, 219, 219, 222, 222, 222, 222, + 222, 222, 222, 222, 222, 222, 222, 224, + 224, 231, 231, 231, 231, 231, 231, 231, + 231, 231, 231, 231, 231, 231, 231, 231, + 231, 231, 231, 231, 231, 231, 231, 231, + 231, 231, 231, 231, 231, 231, 231, 231, + 231, 231, 231, 231, 231, 231, 231, 231, + 231, 231, 231, 231, 231, 231, 231, 231, + 231, 231, 231, 231, 231, 231, 231, 231, + 231, 231, 231, 231, 231, 231, 231, 231, + 231, 231, 231, 231, 231, 231, 231, 231, + 231, 231, 231, 231, 231, 231, 231, 231, + 231, 231, 231, 231, 231, 231, 231, 231, + 231, 231, 231, 231, 231, 231, 231, 231, + 231, 231, 231, 231, 231, 231, 231, 231, + 231, 231, 231, 231, 231, 231, 231, 231, + 231, 231, 231, 231, 231, 233, 233, 233, + 233, 233, 233, 233, 234, 234, 234, 234, + 234, 234, 234, 234, 234, 234, 234, 234, + 234, 234, 234, 234, 234, 234, 234, 234, + 234, 234, 234, 234, 234, 234, 234, 234, + 234, 234, 234, 234, 234, 234, 234, 234, + 234, 234, 234, 234, 234, 234, 234, 234, + 236, 236, 236, 236, 236, 236, 236, 236, + 236, 236, 236, 236, 236, 236, 236, 236, + 236, 236, 236, 236, 236, 236, 236, 236, + 236, 236, 236, 236, 236, 236, 236, 236, + 236, 237, 237, 238, 241, 241, 242, 249, + 255, +}; + +static const unsigned char new_tbl[] = { + 0x00, 0x01, 0x20, 0x7f, 0xa0, 0x00, 0x00, 0x50, + 0x60, 0x70, 0x00, 0x83, 0x87, 0x88, 0x8a, 0x00, + 0x91, 0xa2, 0xa3, 0xba, 0xbb, 0xbe, 0xbf, 0xc0, + 0xc1, 0xc3, 0xc4, 0xc5, 0x00, 0x4b, 0x56, 0x70, + 0x71, 0xd6, 0xe5, 0xe7, 0xe9, 0xea, 0xee, 0x00, + 0x0f, 0x10, 0x11, 0x12, 0x30, 0x4b, 0xa6, 0xb1, + 0x00, 0x01, 0x03, 0x3c, 0x3d, 0x41, 0x49, 0x4d, + 0x4e, 0x51, 0x55, 0x62, 0x64, 0x81, 0x82, 0xbc, + 0xbd, 0xc1, 0xc5, 0xcd, 0xce, 0xe2, 0xe4, 0x00, + 0x02, 0x03, 0x3c, 0x3d, 0x41, 0x43, 0x47, 0x49, + 0x4b, 0x4e, 0x70, 0x72, 0x81, 0x83, 0xbc, 0xbd, + 0xc1, 0xc6, 0xc7, 0xc9, 0xcd, 0xce, 0x00, 0x01, + 0x02, 0x3c, 0x3d, 0x3f, 0x40, 0x41, 0x44, 0x4d, + 0x4e, 0x56, 0x57, 0x82, 0x83, 0xc0, 0xc1, 0xcd, + 0xce, 0x00, 0x3e, 0x41, 0x46, 0x49, 0x4a, 0x4e, + 0x55, 0x57, 0xbf, 0xc0, 0xc6, 0xc7, 0xcc, 0xce, + 0x00, 0x41, 0x44, 0x4d, 0x4e, 0xca, 0xcb, 0xd2, + 0xd5, 0xd6, 0xd7, 0x00, 0x31, 0x32, 0x34, 0x3b, + 0x47, 0x4f, 0xb1, 0xb2, 0xb4, 0xba, 0xbb, 0xbd, + 0xc8, 0xce, 0x00, 0x18, 0x1a, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3a, 0x71, 0x7f, 0x80, 0x85, 0x86, + 0x88, 0x90, 0x98, 0x99, 0xbd, 0xc6, 0xc7, 0x00, + 0x2d, 0x31, 0x32, 0x33, 0x36, 0x38, 0x39, 0x3a, + 0x58, 0x5a, 0x00, 0x60, 0x00, 0x12, 0x15, 0x32, + 0x35, 0x52, 0x54, 0x72, 0x74, 0xb7, 0xbe, 0xc6, + 0xc7, 0xc9, 0xd4, 0x00, 0x0b, 0x0f, 0xa9, 0xaa, + 0x00, 0x0b, 0x10, 0x2a, 0x2f, 0x60, 0x64, 0x6a, + 0x70, 0xd0, 0xeb, 0x00, 0x29, 0x2b, 0x00, 0x80, + 0x00, 0x2a, 0x30, 0x3f, 0x40, 0x99, 0x9b, 0x00, + 0xd0, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x00, 0x1e, + 0x1f, 0x00, 0x00, 0x10, 0x20, 0x24, 0x30, 0x70, + 0xff, 0x00, 0x61, 0xe0, 0xe7, 0xf9, 0xfc, +}; + +static const signed char new_wtbl[] = { + 0, -1, 1, -1, 1, 1, 0, 1, + 0, 1, 1, 0, 1, 0, 1, 1, + 0, 1, 0, 1, 0, 1, 0, 1, + 0, 1, 0, 1, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 1, + 0, 1, 0, 1, 0, 1, 0, 1, + 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 1, + 0, 1, 0, 1, 0, 1, 0, 1, + 0, 1, 0, 1, 0, 1, 0, 1, + 0, 1, 0, 1, 0, 1, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, + 1, 1, 0, 1, 0, 1, 0, 1, + 0, 1, 0, 1, 0, 1, 0, 1, + 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 1, 0, 1, 0, 1, + 0, 1, 0, 1, 0, 1, 0, 1, + 0, 1, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 1, + 0, 1, 0, 1, 0, 1, 0, 1, + 0, 1, 2, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 1, 0, 1, 0, 1, + 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 1, 2, 1, 1, 2, + 2, 0, 2, 1, 2, 0, 2, 2, + 1, 1, 2, 1, 1, 2, 1, 0, + 1, 1, 0, 1, 0, 1, 2, 1, + 0, 2, 1, 2, 1, 0, 1, +}; + + +int wcswidth(const wchar_t *pwcs, size_t n) +{ + int h, l, m, count; + wchar_t wc; + unsigned char b; + + if (ENCODING == __ctype_encoding_7_bit) { + size_t i; + + for (i = 0 ; (i < n) && pwcs[i] ; i++) { + if (pwcs[i] != (pwcs[i] & 0x7f)) { + return -1; + } + } + } +#ifdef __CTYPE_HAS_8_BIT_LOCALES + else if (ENCODING == __ctype_encoding_8_bit) { + mbstate_t mbstate; + + mbstate.__mask = 0; /* Initialize the mbstate. */ + if (wcsnrtombs(NULL, &pwcs, n, SIZE_MAX, &mbstate) == ((size_t) - 1)) { + return -1; + } + } +#endif /* __CTYPE_HAS_8_BIT_LOCALES */ +#if defined(__CTYPE_HAS_UTF_8_LOCALES) && defined(KUHN) + /* For stricter handling of allowed unicode values... see comments above. */ + else if (ENCODING == __ctype_encoding_utf8) { + size_t i; + + for (i = 0 ; (i < n) && pwcs[i] ; i++) { + if ( (((__uwchar_t)((pwcs[i]) - 0xfffeU)) < 2) + || (((__uwchar_t)((pwcs[i]) - 0xd800U)) < (0xe000U - 0xd800U)) + ) { + return -1; + } + } + } +#endif /* __CTYPE_HAS_UTF_8_LOCALES */ + + for (count = 0 ; n && (wc = *pwcs++) ; n--) { + if (wc <= 0xff) { + /* If we're here, wc != 0. */ + if ((wc < 32) || ((wc >= 0x7f) && (wc < 0xa0))) { + return -1; + } + ++count; + continue; + } + if (((unsigned int) wc) <= 0xffff) { + b = wc & 0xff; + h = (wc >> 8); + l = new_idx[h]; + h = new_idx[h+1]; + while ((m = (l+h) >> 1) != l) { + if (b >= new_tbl[m]) { + l = m; + } else { /* wc < tbl[m] */ + h = m; + } + } + count += new_wtbl[l]; /* none should be -1. */ + continue; + } + + /* Redo this to minimize average number of compares?*/ + if (wc >= 0x1d167) { + if (wc <= 0x1d1ad) { + if ((wc <= 0x1d169 + || (wc >= 0x1d173 + && (wc <= 0x1d182 + || (wc >= 0x1d185 + && (wc <= 0x1d18b + || (wc >= 0x1d1aa)))))) + ) { + continue; + } + } else if (((wc >= 0xe0020) && (wc <= 0xe007f)) || (wc == 0xe0001)) { + continue; + } else if ((wc >= 0x20000) && (wc <= 0x2ffff)) { + ++count; /* need 2.. add one here */ + } +#if (WCHAR_MAX > 0x7fffffffL) + else if (wc > 0x7fffffffL) { + return -1; + } +#endif /* (WCHAR_MAX > 0x7fffffffL) */ + } + + ++count; + } + + return count; +} + +#else /* __UCLIBC_HAS_LOCALE__ */ + +int wcswidth(const wchar_t *pwcs, size_t n) +{ + int count; + wchar_t wc; + size_t i; + + for (i = 0 ; (i < n) && pwcs[i] ; i++) { + if (pwcs[i] != (pwcs[i] & 0x7f)) { + return -1; + } + } + + for (count = 0 ; n && (wc = *pwcs++) ; n--) { + if (wc <= 0xff) { + /* If we're here, wc != 0. */ + if ((wc < 32) || ((wc >= 0x7f) && (wc < 0xa0))) { + return -1; + } + ++count; + continue; + } else { + return -1; + } + } + + return count; +} + +#endif /* __UCLIBC_HAS_LOCALE__ */ + +libc_hidden_def(wcswidth) + +#endif +/**********************************************************************/ +#ifdef L_wcwidth + + +int wcwidth(wchar_t wc) +{ + return wcswidth(&wc, 1); +} + +#endif +/**********************************************************************/ + + +typedef struct { + mbstate_t tostate; + mbstate_t fromstate; + int tocodeset; + int fromcodeset; + int frombom; + int tobom; + int fromcodeset0; + int frombom0; + int tobom0; + int skip_invalid_input; /* To support iconv -c option. */ +} _UC_iconv_t; + +/* For the multibyte + * bit 0 means swap endian + * bit 1 means 2 byte + * bit 2 means 4 byte + * + */ + +#if defined L_iconv && defined _LIBC +/* Used externally only by iconv utility */ +extern const unsigned char __iconv_codesets[]; +libc_hidden_proto(__iconv_codesets) +#endif + +#if defined L_iconv || defined L_iconv_main +const unsigned char __iconv_codesets[] = + "\x0a\xe0""WCHAR_T\x00" /* superset of UCS-4 but platform-endian */ +#if __BYTE_ORDER == __BIG_ENDIAN + "\x08\xec""UCS-4\x00" /* always BE */ + "\x0a\xec""UCS-4BE\x00" + "\x0a\xed""UCS-4LE\x00" + "\x09\xe4""UTF-32\x00" /* platform endian with BOM */ + "\x0b\xe4""UTF-32BE\x00" + "\x0b\xe5""UTF-32LE\x00" + "\x08\xe2""UCS-2\x00" /* always BE */ + "\x0a\xe2""UCS-2BE\x00" + "\x0a\xe3""UCS-2LE\x00" + "\x09\xea""UTF-16\x00" /* platform endian with BOM */ + "\x0b\xea""UTF-16BE\x00" + "\x0b\xeb""UTF-16LE\x00" +#elif __BYTE_ORDER == __LITTLE_ENDIAN + "\x08\xed""UCS-4\x00" /* always BE */ + "\x0a\xed""UCS-4BE\x00" + "\x0a\xec""UCS-4LE\x00" + "\x09\xf4""UTF-32\x00" /* platform endian with BOM */ + "\x0b\xe5""UTF-32BE\x00" + "\x0b\xe4""UTF-32LE\x00" + "\x08\xe3""UCS-2\x00" /* always BE */ + "\x0a\xe3""UCS-2BE\x00" + "\x0a\xe2""UCS-2LE\x00" + "\x09\xfa""UTF-16\x00" /* platform endian with BOM */ + "\x0b\xeb""UTF-16BE\x00" + "\x0b\xea""UTF-16LE\x00" +#endif + "\x08\x02""UTF-8\x00" + "\x0b\x01""US-ASCII\x00" + "\x07\x01""ASCII"; /* Must be last! (special case to save a nul) */ +#endif +#if defined L_iconv && defined _LIBC +libc_hidden_data_def(__iconv_codesets) +#endif + + +#ifdef L_iconv + +#include +#include +#include +#include + +#if (__BYTE_ORDER != __BIG_ENDIAN) && (__BYTE_ORDER != __LITTLE_ENDIAN) +#error unsupported endianness for iconv +#endif + +#ifndef __CTYPE_HAS_8_BIT_LOCALES +#error currently iconv requires 8 bit locales +#endif +#ifndef __CTYPE_HAS_UTF_8_LOCALES +#error currently iconv requires UTF-8 locales +#endif + + +enum { + IC_WCHAR_T = 0xe0, + IC_MULTIBYTE = 0xe0, +#if __BYTE_ORDER == __BIG_ENDIAN + IC_UCS_4 = 0xec, + IC_UTF_32 = 0xe4, + IC_UCS_2 = 0xe2, + IC_UTF_16 = 0xea, +#else + IC_UCS_4 = 0xed, + IC_UTF_32 = 0xe5, + IC_UCS_2 = 0xe3, + IC_UTF_16 = 0xeb, +#endif + IC_UTF_8 = 2, + IC_ASCII = 1 +}; + + +static int find_codeset(const char *name) +{ + const unsigned char *s; + int codeset; + + for (s = __iconv_codesets; *s; s += *s) { + if (!strcasecmp((char*) (s + 2), name)) { + return s[1]; + } + } + + /* The following is ripped from find_locale in locale.c. */ + + /* TODO: maybe CODESET_LIST + *s ??? */ + /* 7bit is 1, UTF-8 is 2, 8-bit is >= 3 */ + codeset = 2; + s = (const unsigned char *) __LOCALE_DATA_CODESET_LIST; + do { + ++codeset; /* Increment codeset first. */ + if (!strcasecmp(__LOCALE_DATA_CODESET_LIST+*s, name)) { + return codeset; + } + } while (*++s); + + return 0; /* No matching codeset! */ +} + +iconv_t weak_function iconv_open(const char *tocode, const char *fromcode) +{ + register _UC_iconv_t *px; + int tocodeset, fromcodeset; + + if (((tocodeset = find_codeset(tocode)) != 0) + && ((fromcodeset = find_codeset(fromcode)) != 0)) { + if ((px = malloc(sizeof(_UC_iconv_t))) != NULL) { + px->tocodeset = tocodeset; + px->tobom0 = px->tobom = (tocodeset & 0x10) >> 4; + px->fromcodeset0 = px->fromcodeset = fromcodeset; + px->frombom0 = px->frombom = (fromcodeset & 0x10) >> 4; + px->skip_invalid_input = px->tostate.__mask + = px->fromstate.__mask = 0; + return (iconv_t) px; + } + } else { + __set_errno(EINVAL); + } + return (iconv_t)(-1); +} + +int weak_function iconv_close(iconv_t cd) +{ + free(cd); + + return 0; +} + +size_t weak_function iconv(iconv_t cd, char **__restrict inbuf, + size_t *__restrict inbytesleft, + char **__restrict outbuf, + size_t *__restrict outbytesleft) +{ + _UC_iconv_t *px = (_UC_iconv_t *) cd; + size_t nrcount, r; + wchar_t wc, wc2; + int inci, inco; + + assert(px != (_UC_iconv_t *)(-1)); + assert(sizeof(wchar_t) == 4); + + if (!inbuf || !*inbuf) { /* Need to reinitialze conversion state. */ + /* Note: For shift-state encodings we possibly need to output the + * shift sequence to return to initial state! */ + if ((px->fromcodeset & 0xf0) == 0xe0) { + } + px->tostate.__mask = px->fromstate.__mask = 0; + px->fromcodeset = px->fromcodeset0; + px->tobom = px->tobom0; + px->frombom = px->frombom0; + return 0; + } + + nrcount = 0; + while (*inbytesleft) { + if (!*outbytesleft) { + TOO_BIG: + __set_errno(E2BIG); + return (size_t) -1; + } + + inci = inco = 1; + if (px->fromcodeset >= IC_MULTIBYTE) { + inci = (px->fromcodeset == IC_WCHAR_T) ? 4: (px->fromcodeset & 6); + if (*inbytesleft < inci) goto INVALID; + wc = (((unsigned int)((unsigned char)((*inbuf)[0]))) << 8) + + ((unsigned char)((*inbuf)[1])); + if (inci == 4) { + wc = (((unsigned int)((unsigned char)((*inbuf)[2]))) << 8) + + ((unsigned char)((*inbuf)[3])) + (wc << 16); + if (!(px->fromcodeset & 1)) wc = bswap_32(wc); + } else { + if (!(px->fromcodeset & 1)) wc = bswap_16(wc); + if (((px->fromcodeset & IC_UTF_16) == IC_UTF_16) + && (((__uwchar_t)(wc - 0xd800U)) < (0xdc00U - 0xd800U)) + ) { /* surrogate */ + wc =- 0xd800U; + if (*inbytesleft < 4) goto INVALID; + wc2 = (((unsigned int)((unsigned char)((*inbuf)[2]))) << 8) + + ((unsigned char)((*inbuf)[3])); + if (!(px->fromcodeset & 1)) wc = bswap_16(wc2); + if (((__uwchar_t)(wc2 -= 0xdc00U)) < (0xe0000U - 0xdc00U)) { + goto ILLEGAL; + } + inci = 4; /* Change inci here in case skipping illegals. */ + wc = 0x10000UL + (wc << 10) + wc2; + } + } + + if (px->frombom) { + px->frombom = 0; + if ((wc == 0xfeffU) + || (wc == ((inci == 4) + ? (((wchar_t) 0xfffe0000UL)) + : ((wchar_t)(0xfffeUL)))) + ) { + if (wc != 0xfeffU) { + px->fromcodeset ^= 1; /* toggle endianness */ + wc = 0xfeffU; + } + if (!px->frombom) { + goto BOM_SKIP_OUTPUT; + } + goto GOT_BOM; + } + } + + if (px->fromcodeset != IC_WCHAR_T) { + if (((__uwchar_t) wc) > (((px->fromcodeset & IC_UCS_4) == IC_UCS_4) + ? 0x7fffffffUL : 0x10ffffUL) +#ifdef KUHN + || (((__uwchar_t)(wc - 0xfffeU)) < 2) + || (((__uwchar_t)(wc - 0xd800U)) < (0xe000U - 0xd800U)) +#endif + ) { + goto ILLEGAL; + } + } + } else if (px->fromcodeset == IC_UTF_8) { + const char *p = *inbuf; + r = _wchar_utf8sntowcs(&wc, 1, &p, *inbytesleft, &px->fromstate, 0); + if (((ssize_t) r) <= 0) { /* either EILSEQ or incomplete or nul */ + if (((ssize_t) r) < 0) { /* either EILSEQ or incomplete or nul */ + assert((r == (size_t)(-1)) || (r == (size_t)(-2))); + if (r == (size_t)(-2)) { + INVALID: + __set_errno(EINVAL); + } else { + px->fromstate.__mask = 0; + inci = 1; + ILLEGAL: + if (px->skip_invalid_input) { + px->skip_invalid_input = 2; /* flag for iconv utility */ + goto BOM_SKIP_OUTPUT; + } + __set_errno(EILSEQ); + } + return (size_t)(-1); + } +#ifdef __UCLIBC_MJN3_ONLY__ +#warning TODO: optimize this. +#endif + if (p != NULL) { /* incomplete char case */ + goto INVALID; + } + p = *inbuf + 1; /* nul */ + } + inci = p - *inbuf; + } else if ((wc = ((unsigned char)(**inbuf))) >= 0x80) { /* Non-ASCII... */ + if (px->fromcodeset == IC_ASCII) { /* US-ASCII codeset */ + goto ILLEGAL; + } else { /* some other 8-bit ascii-extension codeset */ + const __codeset_8_bit_t *c8b + = __locale_mmap->codeset_8_bit + px->fromcodeset - 3; + wc -= 0x80; + wc = __UCLIBC_CURLOCALE->tbl8c2wc[ + (c8b->idx8c2wc[wc >> Cc2wc_IDX_SHIFT] + << Cc2wc_IDX_SHIFT) + (wc & (Cc2wc_ROW_LEN - 1))]; + if (!wc) { + goto ILLEGAL; + } + } + } + + + if (px->tobom) { + inci = 0; + wc = 0xfeffU; + GOT_BOM: + px->tobom = 0; + } + + if (px->tocodeset >= IC_MULTIBYTE) { + inco = (px->tocodeset == IC_WCHAR_T) ? 4: (px->tocodeset & 6); + if (*outbytesleft < inco) goto TOO_BIG; + if (px->tocodeset != IC_WCHAR_T) { + if (((__uwchar_t) wc) > (((px->tocodeset & IC_UCS_4) == IC_UCS_4) + ? 0x7fffffffUL : 0x10ffffUL) +#ifdef KUHN + || (((__uwchar_t)(wc - 0xfffeU)) < 2) + || (((__uwchar_t)(wc - 0xd800U)) < (0xe000U - 0xd800U)) +#endif + ) { + REPLACE_32: + wc = 0xfffd; + ++nrcount; + } + } + if (inco == 4) { + if (px->tocodeset & 1) wc = bswap_32(wc); + } else { + if (((__uwchar_t)wc ) > 0xffffU) { + if ((px->tocodeset & IC_UTF_16) != IC_UTF_16) { + goto REPLACE_32; + } + if (*outbytesleft < (inco = 4)) goto TOO_BIG; + wc2 = 0xdc00U + (wc & 0x3ff); + wc = 0xd800U + ((wc >> 10) & 0x3ff); + if (px->tocodeset & 1) { + wc = bswap_16(wc); + wc2 = bswap_16(wc2); + } + wc += (wc2 << 16); + } else if (px->tocodeset & 1) wc = bswap_16(wc); + } + (*outbuf)[0] = (char)((unsigned char)(wc)); + (*outbuf)[1] = (char)((unsigned char)(wc >> 8)); + if (inco == 4) { + (*outbuf)[2] = (char)((unsigned char)(wc >> 16)); + (*outbuf)[3] = (char)((unsigned char)(wc >> 24)); + } + } else if (px->tocodeset == IC_UTF_8) { + const wchar_t *pw = &wc; + do { + r = _wchar_wcsntoutf8s(*outbuf, *outbytesleft, &pw, 1); + if (r != (size_t)(-1)) { +#ifdef __UCLIBC_MJN3_ONLY__ +#warning TODO: What happens for a nul? +#endif + if (r == 0) { + if (wc != 0) { + goto TOO_BIG; + } + ++r; + } + break; + } + wc = 0xfffdU; + ++nrcount; + } while (1); + inco = r; + } else if (((__uwchar_t)(wc)) < 0x80) { + CHAR_GOOD: + **outbuf = wc; + } else { + if ((px->tocodeset != 0x01) && (wc <= Cwc2c_DOMAIN_MAX)) { + const __codeset_8_bit_t *c8b + = __locale_mmap->codeset_8_bit + px->tocodeset - 3; + __uwchar_t u; + u = c8b->idx8wc2c[wc >> (Cwc2c_TI_SHIFT + Cwc2c_TT_SHIFT)]; + u = __UCLIBC_CURLOCALE->tbl8wc2c[(u << Cwc2c_TI_SHIFT) + + ((wc >> Cwc2c_TT_SHIFT) + & ((1 << Cwc2c_TI_SHIFT)-1))]; + wc = __UCLIBC_CURLOCALE->tbl8wc2c[Cwc2c_TI_LEN + + (u << Cwc2c_TT_SHIFT) + + (wc & ((1 << Cwc2c_TT_SHIFT)-1))]; + if (wc) { + goto CHAR_GOOD; + } + } + **outbuf = '?'; + ++nrcount; + } + + *outbuf += inco; + *outbytesleft -= inco; + BOM_SKIP_OUTPUT: + *inbuf += inci; + *inbytesleft -= inci; + } + return nrcount; +} +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wchar/wcrtomb.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wchar/wcrtomb.c new file mode 100644 index 00000000..91eb3062 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wchar/wcrtomb.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_wcrtomb +#include "wchar.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wchar/wcsnrtombs.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wchar/wcsnrtombs.c new file mode 100644 index 00000000..af9d6c33 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wchar/wcsnrtombs.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_wcsnrtombs +#include "wchar.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wchar/wcsrtombs.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wchar/wcsrtombs.c new file mode 100644 index 00000000..e5b6c0b3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wchar/wcsrtombs.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_wcsrtombs +#include "wchar.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wchar/wcswidth.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wchar/wcswidth.c new file mode 100644 index 00000000..3d955a21 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wchar/wcswidth.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_wcswidth +#include "wchar.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wchar/wctob.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wchar/wctob.c new file mode 100644 index 00000000..88d31f5a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wchar/wctob.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_wctob +#include "wchar.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wchar/wcwidth.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wchar/wcwidth.c new file mode 100644 index 00000000..6c4a3447 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wchar/wcwidth.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_wcwidth +#include "wchar.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/Makefile new file mode 100644 index 00000000..4a8f4a07 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../ +top_builddir=../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/Makefile.in new file mode 100644 index 00000000..4eacc118 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/Makefile.in @@ -0,0 +1,36 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +subdirs += libc/misc/wctype + +# multi source _wctype.c +COM_SRC := \ + iswalnum.c iswalpha.c iswcntrl.c iswdigit.c iswgraph.c \ + iswlower.c iswprint.c iswpunct.c iswspace.c iswupper.c \ + iswxdigit.c iswblank.c wctrans.c towctrans.c \ + wctype.c iswctype.c towlower.c towupper.c + +CSRC := +ifeq ($(UCLIBC_HAS_WCHAR),y) +CSRC += $(COM_SRC) +endif +ifeq ($(UCLIBC_HAS_XLOCALE),y) +CSRC += $(patsubst %.c,%_l.c,$(COM_SRC)) +endif + +MISC_WCTYPE_DIR := $(top_srcdir)libc/misc/wctype +MISC_WCTYPE_OUT := $(top_builddir)libc/misc/wctype + +MISC_WCTYPE_SRC := $(patsubst %.c,$(MISC_WCTYPE_DIR)/%.c,$(CSRC)) +MISC_WCTYPE_OBJ := $(patsubst %.c,$(MISC_WCTYPE_OUT)/%.o,$(CSRC)) + +libc-y += $(MISC_WCTYPE_OBJ) + +objclean-y += CLEAN_libc/misc/wctype + +CLEAN_libc/misc/wctype: + $(do_rm) $(addprefix $(MISC_WCTYPE_OUT)/*., o os) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/_wctype.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/_wctype.c new file mode 100644 index 00000000..296293ff --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/_wctype.c @@ -0,0 +1,851 @@ +/* Copyright (C) 2002, 2003 Manuel Novoa III + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION! + * + * Besides uClibc, I'm using this code in my libc for elks, which is + * a 16-bit environment with a fairly limited compiler. It would make + * things much easier for me if this file isn't modified unnecessarily. + * In particular, please put any new or replacement functions somewhere + * else, and modify the makefile to use your version instead. + * Thanks. Manuel + * + * ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION! */ + +#define __NO_CTYPE + +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(__LOCALE_C_ONLY) && defined(__UCLIBC_DO_XLOCALE) +# error xlocale functionality is not supported in stub locale mode. +#endif + +#ifdef __UCLIBC_HAS_XLOCALE__ +# include +#endif + +/* We know wide char support is enabled. We wouldn't be here otherwise. */ + +/* Define this if you want to unify the towupper and towlower code in the + * towctrans function. */ +/* #define SMALL_UPLOW */ + + +/* Pull in __CTYPE_xxx constants */ +#include + + +/* The following is used to implement wctype(), but it is defined + * here because the ordering must agree with that of the enumeration + * below (ignoring unclassified). */ +#define __CTYPE_TYPESTRING \ + "\6alnum\0\6alpha\0\6blank\0\6cntrl\0\6digit\0\6graph\0\6lower\0" \ + "\6print\0\6punct\0\6space\0\6upper\0\7xdigit\0\0" + + +/* The values for wctype_t. */ +enum { + _CTYPE_unclassified = 0, + _CTYPE_isalnum, + _CTYPE_isalpha, + _CTYPE_isblank, + _CTYPE_iscntrl, + _CTYPE_isdigit, + _CTYPE_isgraph, + _CTYPE_islower, + _CTYPE_isprint, + _CTYPE_ispunct, + _CTYPE_isspace, + _CTYPE_isupper, + _CTYPE_isxdigit /* _MUST_ be last of the standard classes! */ +}; + +/* The following is used to implement wctrans(). */ + +#define __CTYPE_TRANSTRING "\10tolower\0\10toupper\0\10totitle\0\0" + +enum { + _CTYPE_tolower = 1, + _CTYPE_toupper, + _CTYPE_totitle +}; + +/*--------------------------------------------------------------------*/ + +#define _CTYPE_iswxdigit (_CTYPE_isxdigit) + +/*--------------------------------------------------------------------*/ + +#ifdef __UCLIBC_MJN3_ONLY__ +# ifdef L_iswspace +/* generates one warning */ +# warning TODO: Fix WC* defines! +# endif +#endif + +#define ENCODING (__UCLIBC_CURLOCALE->encoding) + +#define WCctype (__UCLIBC_CURLOCALE->tblwctype) +#define WCuplow (__UCLIBC_CURLOCALE->tblwuplow) +#define WCcmob (__UCLIBC_CURLOCALE->tblwcomb) +#define WCuplow_diff (__UCLIBC_CURLOCALE->tblwuplow_diff) + + +#define WC_TABLE_DOMAIN_MAX __LOCALE_DATA_WC_TABLE_DOMAIN_MAX + +#define WCctype_II_LEN __LOCALE_DATA_WCctype_II_LEN +#define WCctype_TI_LEN __LOCALE_DATA_WCctype_TI_LEN +#define WCctype_UT_LEN __LOCALE_DATA_WCctype_UT_LEN +#define WCctype_II_SHIFT __LOCALE_DATA_WCctype_II_SHIFT +#define WCctype_TI_SHIFT __LOCALE_DATA_WCctype_TI_SHIFT + +#define WCuplow_II_LEN __LOCALE_DATA_WCuplow_II_LEN +#define WCuplow_TI_LEN __LOCALE_DATA_WCuplow_TI_LEN +#define WCuplow_UT_LEN __LOCALE_DATA_WCuplow_UT_LEN +#define WCuplow_II_SHIFT __LOCALE_DATA_WCuplow_II_SHIFT +#define WCuplow_TI_SHIFT __LOCALE_DATA_WCuplow_TI_SHIFT + + +#define WCctype_TI_MASK ((1 << (WCctype_TI_SHIFT)) - 1) +#define WCctype_II_MASK ((1 << (WCctype_II_SHIFT)) - 1) + +/**********************************************************************/ + +#undef __PASTE2 +#undef __PASTE3 +#define __PASTE2(X,Y) X ## Y +#define __PASTE3(X,Y,Z) X ## Y ## Z + +#ifdef __UCLIBC_DO_XLOCALE + +#define ISW_FUNC_BODY(NAME) \ +libc_hidden_proto(__PASTE3(isw,NAME,_l)) \ +int __PASTE3(isw,NAME,_l) (wint_t wc, __locale_t l) \ +{ \ + return iswctype_l(wc, __PASTE2(_CTYPE_is,NAME), l); \ +} \ +libc_hidden_def(__PASTE3(isw,NAME,_l)) + +#else /* __UCLIBC_DO_XLOCALE */ + +#define ISW_FUNC_BODY(NAME) \ +libc_hidden_proto(__PASTE2(isw,NAME)) \ +int __PASTE2(isw,NAME) (wint_t wc) \ +{ \ + return iswctype(wc, __PASTE2(_CTYPE_is,NAME)); \ +} \ +libc_hidden_def(__PASTE2(isw,NAME)) + +#endif /* __UCLIBC_DO_XLOCALE */ +/**********************************************************************/ +#if defined(L_iswalnum) || defined(L_iswalnum_l) + +ISW_FUNC_BODY(alnum); + +#endif +/**********************************************************************/ +#if defined(L_iswalpha) || defined(L_iswalpha_l) + +ISW_FUNC_BODY(alpha); + +#endif +/**********************************************************************/ +#if defined(L_iswblank) || defined(L_iswblank_l) + +ISW_FUNC_BODY(blank); + +#endif +/**********************************************************************/ +#if defined(L_iswcntrl) || defined(L_iswcntrl_l) + +ISW_FUNC_BODY(cntrl); + +#endif +/**********************************************************************/ +#if defined(L_iswdigit) || defined(L_iswdigit_l) + +ISW_FUNC_BODY(digit); + +#endif +/**********************************************************************/ +#if defined(L_iswgraph) || defined(L_iswgraph_l) + +ISW_FUNC_BODY(graph); + +#endif +/**********************************************************************/ +#if defined(L_iswlower) || defined(L_iswlower_l) + +ISW_FUNC_BODY(lower); + +#endif +/**********************************************************************/ +#if defined(L_iswprint) || defined(L_iswprint_l) + +ISW_FUNC_BODY(print); + +#endif +/**********************************************************************/ +#if defined(L_iswpunct) || defined(L_iswpunct_l) + +ISW_FUNC_BODY(punct); + +#endif +/**********************************************************************/ +#if defined(L_iswspace) || defined(L_iswspace_l) + +ISW_FUNC_BODY(space); + +#endif +/**********************************************************************/ +#if defined(L_iswupper) || defined(L_iswupper_l) + +ISW_FUNC_BODY(upper); + +#endif +/**********************************************************************/ +#if defined(L_iswxdigit) || defined(L_iswxdigit_l) + +ISW_FUNC_BODY(xdigit); + +#endif +/**********************************************************************/ +#if defined(L_towlower) || defined(L_towlower_l) + +# ifdef L_towlower +# define TOWLOWER(w) towlower(w) +# else +# define TOWLOWER(w) towlower_l(w, __locale_t locale) +# undef __UCLIBC_CURLOCALE +# define __UCLIBC_CURLOCALE (locale) +# endif + +# ifdef __UCLIBC_HAS_XLOCALE__ +# define TOWCTRANS(w,d) towctrans_l(w,d, __UCLIBC_CURLOCALE) +# else +# define TOWCTRANS(w,d) towctrans(w,d) +# endif + +# define __C_towlower(wc) \ + (((__uwchar_t)(wc) <= 0x7f) ? (__C_ctype_tolower)[(wc)] : (wc)) + +# ifdef __LOCALE_C_ONLY + +wint_t towlower(wint_t wc) +{ +# ifdef __UCLIBC_HAS_CTYPE_TABLES__ + return __C_towlower(wc); +# else + return (wc == (unsigned)wc) + ? __C_tolower((unsigned)wc) + : 0; +# endif +} + +# else /* __LOCALE_C_ONLY */ + +# ifdef SMALL_UPLOW + +# if defined(L_towlower) && defined(__UCLIBC_HAS_XLOCALE__) +wint_t towlower(wint_t wc) +{ + return towctrans_l(wc, _CTYPE_tolower, __UCLIBC_CURLOCALE); +} +# else /* defined(L_towlower) && defined(__UCLIBC_HAS_XLOCALE__) */ +wint_t TOWLOWER(wint_t wc) +{ + return TOWCTRANS(wc, _CTYPE_tolower); +} +# endif /* defined(L_towlower) && defined(__UCLIBC_HAS_XLOCALE__) */ + +# else /* SMALL_UPLOW */ + +# if defined(L_towlower) && defined(__UCLIBC_HAS_XLOCALE__) + +wint_t towlower(wint_t wc) +{ + return towlower_l(wc, __UCLIBC_CURLOCALE); +} + +# else /* defined(L_towlower) && defined(__UCLIBC_HAS_XLOCALE__) */ + +wint_t TOWLOWER(wint_t wc) +{ + unsigned sc, n, i; + __uwchar_t u = wc; + + if (ENCODING == __ctype_encoding_7_bit) { + /* We're in the C/POSIX locale, so ignore the tables. */ + return __C_towlower(wc); + } + + if (u <= WC_TABLE_DOMAIN_MAX) { + sc = u & ((1 << WCuplow_TI_SHIFT) - 1); + u >>= WCuplow_TI_SHIFT; + n = u & ((1 << WCuplow_II_SHIFT) - 1); + u >>= WCuplow_II_SHIFT; + + i = ((unsigned) WCuplow[u]) << WCuplow_II_SHIFT; + i = ((unsigned) WCuplow[WCuplow_II_LEN + i + n]) << WCuplow_TI_SHIFT; + i = ((unsigned) WCuplow[WCuplow_II_LEN + WCuplow_TI_LEN + i + sc]) << 1; + wc += WCuplow_diff[i + 1]; + } + return wc; +} + +# endif /* defined(L_towlower) && defined(__UCLIBC_HAS_XLOCALE__) */ + +# endif /* SMALL_UPLOW */ + +# ifdef L_towlower_l +libc_hidden_def(towlower_l) +# endif + +# endif /* __LOCALE_C_ONLY */ + +# ifndef L_towlower_l +libc_hidden_def(towlower) +# endif + +#endif +/**********************************************************************/ +#if defined(L_towupper) || defined(L_towupper_l) + +# ifdef L_towupper +# define TOWUPPER(w) towupper(w) +# else +# define TOWUPPER(w) towupper_l(w, __locale_t locale) +# undef __UCLIBC_CURLOCALE +# define __UCLIBC_CURLOCALE (locale) +# endif + +# ifdef __UCLIBC_HAS_XLOCALE__ +# define TOWCTRANS(w,d) towctrans_l(w,d, __UCLIBC_CURLOCALE) +# else +# define TOWCTRANS(w,d) towctrans(w,d) +# endif + +# define __C_towupper(wc) \ + (((__uwchar_t)(wc) <= 0x7f) ? (__C_ctype_toupper)[(wc)] : (wc)) + +# ifdef __LOCALE_C_ONLY + +wint_t towupper(wint_t wc) +{ +# ifdef __UCLIBC_HAS_CTYPE_TABLES__ + return __C_towupper(wc); +# else + return (wc == (unsigned)wc) + ? __C_toupper((unsigned)wc) + : 0; +# endif +} + +# else /* __LOCALE_C_ONLY */ + +# ifdef SMALL_UPLOW + +# if defined(L_towupper) && defined(__UCLIBC_HAS_XLOCALE__) +wint_t towupper(wint_t wc) +{ + return towctrans_l(wc, _CTYPE_toupper, __UCLIBC_CURLOCALE); +} +# else +wint_t TOWUPPER(wint_t wc) +{ + return TOWCTRANS(wc, _CTYPE_toupper); +} +# endif + +# else /* SMALL_UPLOW */ + +# if defined(L_towupper) && defined(__UCLIBC_HAS_XLOCALE__) +wint_t towupper(wint_t wc) +{ + return towupper_l(wc, __UCLIBC_CURLOCALE); +} +# else /* defined(L_towupper) && defined(__UCLIBC_HAS_XLOCALE__) */ +wint_t TOWUPPER(wint_t wc) +{ + unsigned sc, n, i; + __uwchar_t u = wc; + + if (ENCODING == __ctype_encoding_7_bit) { + /* We're in the C/POSIX locale, so ignore the tables. */ + return __C_towupper(wc); + } + + if (u <= WC_TABLE_DOMAIN_MAX) { + sc = u & ((1 << WCuplow_TI_SHIFT) - 1); + u >>= WCuplow_TI_SHIFT; + n = u & ((1 << WCuplow_II_SHIFT) - 1); + u >>= WCuplow_II_SHIFT; + + i = ((unsigned) WCuplow[u]) << WCuplow_II_SHIFT; + i = ((unsigned) WCuplow[WCuplow_II_LEN + i + n]) << WCuplow_TI_SHIFT; + i = ((unsigned) WCuplow[WCuplow_II_LEN + WCuplow_TI_LEN + i + sc]) << 1; + wc += WCuplow_diff[i]; + } + return wc; +} +# endif /* defined(L_towupper) && defined(__UCLIBC_HAS_XLOCALE__) */ + +# endif /* SMALL_UPLOW */ + +# ifdef L_towupper_l +libc_hidden_def(towupper_l) +# endif + +# endif /* __LOCALE_C_ONLY */ + +# ifndef L_towupper_l +libc_hidden_def(towupper) +# endif + +#endif +/**********************************************************************/ +#ifdef L_wctype + +static const unsigned char typestring[] = __CTYPE_TYPESTRING; + +wctype_t wctype(const char *property) +{ + const unsigned char *p; + int i; + + p = typestring; + i = 1; + do { + if (!strcmp(property, (const char *) ++p)) { + return i; + } + ++i; + p += p[-1]; + } while (*p); + + /* TODO - Add locale-specific classifications. */ + return 0; +} +libc_hidden_def(wctype) + +#endif +/**********************************************************************/ +#ifdef L_wctype_l + +#ifdef __UCLIBC_MJN3_ONLY__ +# warning REMINDER: Currently wctype_l simply calls wctype. +#endif + +wctype_t wctype_l (const char *property, __locale_t locale) +{ + return wctype(property); +} +libc_hidden_def(wctype_l) + +#endif +/**********************************************************************/ +#if defined(L_iswctype) || defined(L_iswctype_l) + +#define __C_iswdigit(c) \ + ((sizeof(c) == sizeof(char)) \ + ? ((unsigned char)((c) - '0') < 10) \ + : ((__uwchar_t)((c) - '0') < 10) \ + ) +#define __C_iswxdigit(c) \ + (__C_iswdigit(c) \ + || ((sizeof(c) == sizeof(char)) \ + ? ((unsigned char)(((c) | 0x20) - 'a') < 6) \ + : ((__uwchar_t)(((c) | 0x20) - 'a') < 6) \ + ) \ + ) + +#ifdef __UCLIBC_MJN3_ONLY__ +# ifdef L_iswctype +# warning CONSIDER: Change to bit shift? would need to sync with wctype.h +# endif +#endif + +#ifdef __UCLIBC_HAS_CTYPE_TABLES__ +# if !defined(__UCLIBC_HAS_XLOCALE__) || defined(L_iswctype_l) +static const unsigned short int desc2flag[] = { + [_CTYPE_unclassified] = 0, + [_CTYPE_isalnum] = (unsigned short int) _ISwalnum, + [_CTYPE_isalpha] = (unsigned short int) _ISwalpha, + [_CTYPE_isblank] = (unsigned short int) _ISwblank, + [_CTYPE_iscntrl] = (unsigned short int) _ISwcntrl, + [_CTYPE_isdigit] = (unsigned short int) _ISwdigit, + [_CTYPE_isgraph] = (unsigned short int) _ISwgraph, + [_CTYPE_islower] = (unsigned short int) _ISwlower, + [_CTYPE_isprint] = (unsigned short int) _ISwprint, + [_CTYPE_ispunct] = (unsigned short int) _ISwpunct, + [_CTYPE_isspace] = (unsigned short int) _ISwspace, + [_CTYPE_isupper] = (unsigned short int) _ISwupper, + [_CTYPE_isxdigit] = (unsigned short int) _ISwxdigit, +}; +# endif +#endif + +#ifdef __LOCALE_C_ONLY + +#ifdef __UCLIBC_HAS_CTYPE_TABLES__ + +int iswctype(wint_t wc, wctype_t desc) +{ + /* Note... wctype_t is unsigned. */ + + if ((__uwchar_t) wc <= 0x7f + && desc < (sizeof(desc2flag) / sizeof(desc2flag[0])) + ) { + return __isctype(wc, desc2flag[desc]); + } + return 0; +} + +#else /* __UCLIBC_HAS_CTYPE_TABLES__ */ + +int iswctype(wint_t wc, wctype_t desc) +{ + /* This is lame, but it is here just to get it working for now. */ + + if (wc == (unsigned)wc) { + switch (desc) { + case _CTYPE_isupper: + return __C_isupper((unsigned)wc); + case _CTYPE_islower: + return __C_islower((unsigned)wc); + case _CTYPE_isalpha: + return __C_isalpha((unsigned)wc); + case _CTYPE_isdigit: + return __C_isdigit((unsigned)wc); + case _CTYPE_isxdigit: + return __C_isxdigit((unsigned)wc); + case _CTYPE_isspace: + return __C_isspace((unsigned)wc); + case _CTYPE_isprint: + return __C_isprint((unsigned)wc); + case _CTYPE_isgraph: + return __C_isgraph((unsigned)wc); + case _CTYPE_isblank: + return __C_isblank((unsigned)wc); + case _CTYPE_iscntrl: + return __C_iscntrl((unsigned)wc); + case _CTYPE_ispunct: + return __C_ispunct((unsigned)wc); + case _CTYPE_isalnum: + return __C_isalnum((unsigned)wc); + default: + break; + } + } + return 0; +} + +#endif /* __UCLIBC_HAS_CTYPE_TABLES__ */ + +#else /* __LOCALE_C_ONLY */ + +#ifdef __UCLIBC_MJN3_ONLY__ +# ifdef L_iswctype +# warning CONSIDER: Handle combining class? +# endif +#endif + +#ifdef L_iswctype +# define ISWCTYPE(w,d) iswctype(w,d) +#else +# define ISWCTYPE(w,d) iswctype_l(w,d, __locale_t locale) +# undef __UCLIBC_CURLOCALE +# define __UCLIBC_CURLOCALE (locale) +#endif + +#if defined(L_iswctype) && defined(__UCLIBC_HAS_XLOCALE__) + +int iswctype(wint_t wc, wctype_t desc) +{ + return iswctype_l(wc, desc, __UCLIBC_CURLOCALE); +} + +#else /* defined(L_iswctype) && defined(__UCLIBC_HAS_XLOCALE__) */ + +int ISWCTYPE(wint_t wc, wctype_t desc) +{ + unsigned sc, n, i0, i1; + unsigned char d = __CTYPE_unclassified; + + if ((ENCODING != __ctype_encoding_7_bit) || ((__uwchar_t)wc <= 0x7f)) { + if (desc < _CTYPE_iswxdigit) { + if ((__uwchar_t)wc <= WC_TABLE_DOMAIN_MAX) { + /* From here on, we know wc > 0. */ + sc = wc & WCctype_TI_MASK; + wc >>= WCctype_TI_SHIFT; + n = wc & WCctype_II_MASK; + wc >>= WCctype_II_SHIFT; + + i0 = WCctype[wc]; + i0 <<= WCctype_II_SHIFT; + i1 = WCctype[WCctype_II_LEN + i0 + n]; + i1 <<= (WCctype_TI_SHIFT-1); + d = WCctype[WCctype_II_LEN + WCctype_TI_LEN + i1 + (sc >> 1)]; + + d = (sc & 1) ? (d >> 4) : (d & 0xf); + } else if ((__uwchar_t)(wc - 0xe0020UL) <= 0x5f + || wc == 0xe0001UL + || (((__uwchar_t)(wc - 0xf0000UL) < 0x20000UL) && ((wc & 0xffffU) <= 0xfffdU)) + ) { + d = __CTYPE_punct; + } + +#if 0 + return ((unsigned char)(d - ctype_range[2*desc]) <= ctype_range[2*desc + 1]) + && ((desc != _CTYPE_iswblank) || (d & 1)); +#else + return __UCLIBC_CURLOCALE->code2flag[d] & desc2flag[desc]; +#endif + } + +#ifdef __UCLIBC_MJN3_ONLY__ +# warning TODO: xdigit really needs to be handled better. Remember only for ascii! +#endif + /* TODO - Add locale-specific classifications. */ + return (desc == _CTYPE_iswxdigit) ? __C_iswxdigit(wc) : 0; + } + return 0; +} + +#endif /* defined(L_iswctype) && defined(__UCLIBC_HAS_XLOCALE__) */ + +#ifdef L_iswctype_l +libc_hidden_def(iswctype_l) +#endif + +#endif /* __LOCALE_C_ONLY */ + +#ifdef L_iswctype +libc_hidden_def(iswctype) +#endif + +#endif +/**********************************************************************/ +#if defined(L_towctrans) || defined(L_towctrans_l) + +#ifdef __LOCALE_C_ONLY + +/* Minimal support for C/POSIX locale. */ + +wint_t towctrans(wint_t wc, wctrans_t desc) +{ + if ((unsigned)(desc - _CTYPE_tolower) <= (_CTYPE_toupper - _CTYPE_tolower)) { + /* Transliteration is either tolower or toupper. */ +#if 0 +/* I think it's wrong: _toupper(c) assumes that c is a *lowercase* *letter* - + * it is defined as ((c) ^ 0x20)! */ + if ((__uwchar_t) wc <= 0x7f) { + return (desc == _CTYPE_tolower) ? _tolower(wc) : _toupper(wc); + } +#endif + __uwchar_t c = wc | 0x20; /* lowercase if it's a letter */ + if (c >= 'a' && c <= 'z') { + if (desc == _CTYPE_toupper) + c &= ~0x20; /* uppercase */ + return c; + } + } else { + __set_errno(EINVAL); /* Invalid transliteration. */ + } + return wc; +} + +#else /* __LOCALE_C_ONLY */ + +#ifdef L_towctrans +# define TOWCTRANS(w,d) towctrans(w,d) +#else +# define TOWCTRANS(w,d) towctrans_l(w,d, __locale_t locale) +# undef __UCLIBC_CURLOCALE +# define __UCLIBC_CURLOCALE (locale) +#endif + +#ifdef __UCLIBC_HAS_XLOCALE__ +# define TOWLOWER(w,l) towlower_l(w,l) +# define TOWUPPER(w,l) towupper_l(w,l) +#else +# define TOWLOWER(w,l) towlower(w) +# define TOWUPPER(w,l) towupper(w) +#endif + +#if defined(L_towctrans) && defined(__UCLIBC_HAS_XLOCALE__) + +wint_t towctrans(wint_t wc, wctrans_t desc) +{ + return towctrans_l(wc, desc, __UCLIBC_CURLOCALE); +} + +#else /* defined(L_towctrans) && defined(__UCLIBC_HAS_XLOCALE__) */ + +#ifdef SMALL_UPLOW + +wint_t TOWCTRANS(wint_t wc, wctrans_t desc) +{ + unsigned sc, n, i; + __uwchar_t u = wc; + + /* TODO - clean up */ + if (ENCODING == __ctype_encoding_7_bit) { + if ((__uwchar_t)wc > 0x7f + || (unsigned)(desc - _CTYPE_tolower) > (_CTYPE_toupper - _CTYPE_tolower) + ) { + /* We're in the C/POSIX locale, so ignore non-ASCII values + * as well an any mappings other than toupper or tolower. */ + return wc; + } + } + + if ((unsigned)(desc - _CTYPE_tolower) <= (_CTYPE_totitle - _CTYPE_tolower)) { + if (u <= WC_TABLE_DOMAIN_MAX) { + sc = u & ((1 << WCuplow_TI_SHIFT) - 1); + u >>= WCuplow_TI_SHIFT; + n = u & ((1 << WCuplow_II_SHIFT) - 1); + u >>= WCuplow_II_SHIFT; + + i = ((unsigned) WCuplow[u]) << WCuplow_II_SHIFT; + i = ((unsigned) WCuplow[WCuplow_II_LEN + i + n]) << WCuplow_TI_SHIFT; + i = ((unsigned) WCuplow[WCuplow_II_LEN + WCuplow_TI_LEN + i + sc]) << 1; + if (desc == _CTYPE_tolower) { + ++i; + } + wc += WCuplow_diff[i]; + if (desc == _CTYPE_totitle) { +#ifdef __UCLIBC_MJN3_ONLY__ +# warning TODO: Verify totitle special cases! +#endif + /* WARNING! These special cases work for glibc 2.2.4. Changes + * may be needed if the glibc locale tables are updated. */ + if ((__uwchar_t)(wc - 0x1c4) <= (0x1cc - 0x1c4) + || wc == 0x1f1 + ) { + ++wc; + } + } + } + } else { + /* TODO - Deal with other transliterations. */ + __set_errno(EINVAL); + } + + return wc; +} + +#else /* SMALL_UPLOW */ + +wint_t TOWCTRANS(wint_t wc, wctrans_t desc) +{ + if (ENCODING == __ctype_encoding_7_bit) { + if ((__uwchar_t)wc > 0x7f + || (unsigned)(desc - _CTYPE_tolower) > (_CTYPE_toupper - _CTYPE_tolower) + ) { + /* We're in the C/POSIX locale, so ignore non-ASCII values + * as well an any mappings other than toupper or tolower. */ + return wc; + } + } + + if (desc == _CTYPE_tolower) { + return TOWLOWER(wc, __UCLIBC_CURLOCALE); + } + if ((unsigned)(desc - _CTYPE_toupper) <= (_CTYPE_totitle - _CTYPE_toupper)) { + wc = TOWUPPER(wc, __UCLIBC_CURLOCALE); + if (desc == _CTYPE_totitle) { +#ifdef __UCLIBC_MJN3_ONLY__ +# warning TODO: Verify totitle special cases! +#endif + /* WARNING! These special cases work for glibc 2.2.4. Changes + * may be needed if the glibc locale tables are updated. */ + if ((__uwchar_t)(wc - 0x1c4) <= (0x1cc - 0x1c4) + || wc == 0x1f1 + ) { + ++wc; + } + } + } else { + /* TODO - Deal with other transliterations. */ + __set_errno(EINVAL); + } + return wc; +} + +#endif /* SMALL_UPLOW */ + +#endif /* defined(L_towctrans) && defined(__UCLIBC_HAS_XLOCALE__) */ + +#ifdef L_towctrans_l +libc_hidden_def(towctrans_l) +#endif + +#endif /* __LOCALE_C_ONLY */ + +#ifndef L_towctrans_l +libc_hidden_def(towctrans) +#endif + +#endif +/**********************************************************************/ +#ifdef L_wctrans + +static const char transstring[] = __CTYPE_TRANSTRING; + +wctrans_t wctrans(const char *property) +{ + const unsigned char *p; + int i; + + p = (const unsigned char *) transstring; + i = 1; + do { + if (!strcmp(property, (const char*) ++p)) { + return i; + } + ++i; + p += p[-1]; + } while (*p); + + /* TODO - Add locale-specific translations. */ + return 0; +} +libc_hidden_def(wctrans) + +#endif +/**********************************************************************/ +#ifdef L_wctrans_l + +# ifdef __UCLIBC_MJN3_ONLY__ +# warning REMINDER: Currently wctrans_l simply calls wctrans. +# endif + +wctrans_t wctrans_l(const char *property, __locale_t locale) +{ + return wctrans(property); +} + +#endif +/**********************************************************************/ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswalnum.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswalnum.c new file mode 100644 index 00000000..a85a03dc --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswalnum.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2002-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_iswalnum +#include "_wctype.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswalnum_l.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswalnum_l.c new file mode 100644 index 00000000..6e3cd777 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswalnum_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2002-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_iswalnum_l +#define __UCLIBC_DO_XLOCALE +#include "_wctype.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswalpha.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswalpha.c new file mode 100644 index 00000000..6b829eb8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswalpha.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2002-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_iswalpha +#include "_wctype.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswalpha_l.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswalpha_l.c new file mode 100644 index 00000000..79b11cf7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswalpha_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2002-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_iswalpha_l +#define __UCLIBC_DO_XLOCALE +#include "_wctype.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswblank.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswblank.c new file mode 100644 index 00000000..67862d59 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswblank.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2002-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_iswblank +#include "_wctype.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswblank_l.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswblank_l.c new file mode 100644 index 00000000..4c5709cf --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswblank_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2002-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_iswblank_l +#define __UCLIBC_DO_XLOCALE +#include "_wctype.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswcntrl.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswcntrl.c new file mode 100644 index 00000000..50d72b46 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswcntrl.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2002-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_iswcntrl +#include "_wctype.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswcntrl_l.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswcntrl_l.c new file mode 100644 index 00000000..2fe64d74 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswcntrl_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2002-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_iswcntrl_l +#define __UCLIBC_DO_XLOCALE +#include "_wctype.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswctype.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswctype.c new file mode 100644 index 00000000..777d4104 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswctype.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2002-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_iswctype +#include "_wctype.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswctype_l.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswctype_l.c new file mode 100644 index 00000000..71bce184 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswctype_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2002-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_iswctype_l +#define __UCLIBC_DO_XLOCALE +#include "_wctype.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswdigit.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswdigit.c new file mode 100644 index 00000000..b2aa5d00 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswdigit.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2002-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_iswdigit +#include "_wctype.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswdigit_l.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswdigit_l.c new file mode 100644 index 00000000..4832c9c8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswdigit_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2002-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_iswdigit_l +#define __UCLIBC_DO_XLOCALE +#include "_wctype.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswgraph.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswgraph.c new file mode 100644 index 00000000..8113054f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswgraph.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2002-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_iswgraph +#include "_wctype.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswgraph_l.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswgraph_l.c new file mode 100644 index 00000000..db683156 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswgraph_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2002-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_iswgraph_l +#define __UCLIBC_DO_XLOCALE +#include "_wctype.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswlower.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswlower.c new file mode 100644 index 00000000..016d8cc8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswlower.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2002-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_iswlower +#include "_wctype.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswlower_l.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswlower_l.c new file mode 100644 index 00000000..5b9f8212 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswlower_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2002-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_iswlower_l +#define __UCLIBC_DO_XLOCALE +#include "_wctype.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswprint.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswprint.c new file mode 100644 index 00000000..8e47e88c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswprint.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2002-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_iswprint +#include "_wctype.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswprint_l.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswprint_l.c new file mode 100644 index 00000000..148414c4 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswprint_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2002-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_iswprint_l +#define __UCLIBC_DO_XLOCALE +#include "_wctype.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswpunct.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswpunct.c new file mode 100644 index 00000000..1175e1ad --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswpunct.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2002-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_iswpunct +#include "_wctype.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswpunct_l.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswpunct_l.c new file mode 100644 index 00000000..a6d36165 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswpunct_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2002-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_iswpunct_l +#define __UCLIBC_DO_XLOCALE +#include "_wctype.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswspace.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswspace.c new file mode 100644 index 00000000..603f5cf4 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswspace.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2002-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_iswspace +#include "_wctype.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswspace_l.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswspace_l.c new file mode 100644 index 00000000..e389f891 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswspace_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2002-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_iswspace_l +#define __UCLIBC_DO_XLOCALE +#include "_wctype.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswupper.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswupper.c new file mode 100644 index 00000000..4cfdebb1 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswupper.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2002-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_iswupper +#include "_wctype.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswupper_l.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswupper_l.c new file mode 100644 index 00000000..359aef98 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswupper_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2002-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_iswupper_l +#define __UCLIBC_DO_XLOCALE +#include "_wctype.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswxdigit.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswxdigit.c new file mode 100644 index 00000000..568f253f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswxdigit.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2002-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_iswxdigit +#include "_wctype.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswxdigit_l.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswxdigit_l.c new file mode 100644 index 00000000..1d543abb --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/iswxdigit_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2002-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_iswxdigit_l +#define __UCLIBC_DO_XLOCALE +#include "_wctype.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/towctrans.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/towctrans.c new file mode 100644 index 00000000..9ad0468f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/towctrans.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2002-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_towctrans +#include "_wctype.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/towctrans_l.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/towctrans_l.c new file mode 100644 index 00000000..e179b50f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/towctrans_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2002-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_towctrans_l +#define __UCLIBC_DO_XLOCALE +#include "_wctype.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/towlower.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/towlower.c new file mode 100644 index 00000000..dffbff3d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/towlower.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2002-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_towlower +#include "_wctype.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/towlower_l.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/towlower_l.c new file mode 100644 index 00000000..f1aa7e6e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/towlower_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2002-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_towlower_l +#define __UCLIBC_DO_XLOCALE +#include "_wctype.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/towupper.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/towupper.c new file mode 100644 index 00000000..1dab8fed --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/towupper.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2002-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_towupper +#include "_wctype.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/towupper_l.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/towupper_l.c new file mode 100644 index 00000000..cf05d5c8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/towupper_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2002-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_towupper_l +#define __UCLIBC_DO_XLOCALE +#include "_wctype.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/wctrans.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/wctrans.c new file mode 100644 index 00000000..f99d9cd9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/wctrans.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2002-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_wctrans +#include "_wctype.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/wctrans_l.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/wctrans_l.c new file mode 100644 index 00000000..79854c2d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/wctrans_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2002-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_wctrans_l +#define __UCLIBC_DO_XLOCALE +#include "_wctype.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/wctype.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/wctype.c new file mode 100644 index 00000000..0dc1e6d7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/wctype.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2002-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_wctype +#include "_wctype.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/wctype_l.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/wctype_l.c new file mode 100644 index 00000000..65f82e2b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wctype/wctype_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2002-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_wctype_l +#define __UCLIBC_DO_XLOCALE +#include "_wctype.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wordexp/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wordexp/Makefile new file mode 100644 index 00000000..4a8f4a07 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wordexp/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../ +top_builddir=../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wordexp/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wordexp/Makefile.in new file mode 100644 index 00000000..981db643 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wordexp/Makefile.in @@ -0,0 +1,23 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +subdirs += libc/misc/wordexp + +CSRC := wordexp.c + +MISC_WORDEXP_DIR := $(top_srcdir)libc/misc/wordexp +MISC_WORDEXP_OUT := $(top_builddir)libc/misc/wordexp + +MISC_WORDEXP_SRC := $(patsubst %.c,$(MISC_WORDEXP_DIR)/%.c,$(CSRC)) +MISC_WORDEXP_OBJ := $(patsubst %.c,$(MISC_WORDEXP_OUT)/%.o,$(CSRC)) + +libc-$(UCLIBC_HAS_WORDEXP) += $(MISC_WORDEXP_OBJ) + +objclean-y += CLEAN_libc/misc/wordexp + +CLEAN_libc/misc/wordexp: + $(do_rm) $(addprefix $(MISC_WORDEXP_OUT)/*., o os) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wordexp/wordexp.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wordexp/wordexp.c new file mode 100644 index 00000000..4c25d286 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/misc/wordexp/wordexp.c @@ -0,0 +1,2239 @@ +/* vi: set sw=4 ts=4: */ +/* POSIX.2 wordexp implementation. + Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Tim Waugh . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define __WORDEXP_FULL + +/* + * This is a recursive-descent-style word expansion routine. + */ + +/* These variables are defined and initialized in the startup code. */ +/*extern int __libc_argc;*/ +/*extern char **__libc_argv;*/ + +/* FIXME!!!! */ +int attribute_hidden __libc_argc; +char attribute_hidden **__libc_argv; + +/* Some forward declarations */ +static int parse_dollars(char **word, size_t * word_length, + size_t * max_length, const char *words, + size_t * offset, int flags, wordexp_t * pwordexp, + const char *ifs, const char *ifs_white, + int quoted); +static int parse_backtick(char **word, size_t * word_length, + size_t * max_length, const char *words, + size_t * offset, int flags, wordexp_t * pwordexp, + const char *ifs, const char *ifs_white); +static int parse_dquote(char **word, size_t * word_length, + size_t * max_length, const char *words, + size_t * offset, int flags, wordexp_t * pwordexp, + const char *ifs, const char *ifs_white); + + + +/* The w_*() functions manipulate word lists. */ +#define W_CHUNK (100) + +/* Result of w_newword will be ignored if it's the last word. */ +static __inline__ char *w_newword(size_t * actlen, size_t * maxlen) +{ + *actlen = *maxlen = 0; + return NULL; +} + +/* Add a character to the buffer, allocating room for it if needed. */ +static __inline__ char *w_addchar(char *buffer, size_t * actlen, + size_t * maxlen, char ch) + /* (lengths exclude trailing zero) */ +{ + + if (*actlen == *maxlen) { + char *old_buffer = buffer; + assert(buffer == NULL || *maxlen != 0); + *maxlen += W_CHUNK; + buffer = realloc(buffer, 1 + *maxlen); + if (buffer == NULL) + free(old_buffer); + } + + if (buffer != NULL) { + buffer[*actlen] = ch; + buffer[++(*actlen)] = '\0'; + } + + return buffer; +} +#ifndef MAX +#define MAX( a, b ) ( ( ( a ) > ( b ) ) ? ( a ) : ( b ) ) +#endif +static char *w_addmem(char *buffer, size_t * actlen, size_t * maxlen, + const char *str, size_t len) +{ + /* Add a string to the buffer, allocating room for it if needed. + */ + if (*actlen + len > *maxlen) { + char *old_buffer = buffer; + assert(buffer == NULL || *maxlen != 0); + *maxlen += MAX(2 * len, W_CHUNK); + buffer = realloc(old_buffer, 1 + *maxlen); + if (buffer == NULL) + free(old_buffer); + } + + if (buffer != NULL) { + *((char *) mempcpy(&buffer[*actlen], str, len)) = '\0'; + *actlen += len; + } + return buffer; +} + +/* Add a string to the buffer, allocating room for it if needed. */ +static char *w_addstr(char *buffer, size_t * actlen, size_t * maxlen, + const char *str) + /* (lengths exclude trailing zero) */ +{ + size_t len; + assert(str != NULL); /* w_addstr only called from this file */ + len = strlen(str); + + return w_addmem(buffer, actlen, maxlen, str, len); +} + +/* Add a word to the wordlist */ +static int w_addword(wordexp_t * pwordexp, char *word) +{ + size_t num_p; + char **new_wordv; + + /* Internally, NULL acts like "". Convert NULLs to "" before + * the caller sees them. + */ + if (word == NULL) { + word = strdup(""); + if (word == NULL) + goto no_space; + } + + num_p = 2 + pwordexp->we_wordc + pwordexp->we_offs; + new_wordv = realloc(pwordexp->we_wordv, sizeof(char *) * num_p); + if (new_wordv != NULL) { + pwordexp->we_wordv = new_wordv; + pwordexp->we_wordv[pwordexp->we_offs + pwordexp->we_wordc++] = word; + pwordexp->we_wordv[pwordexp->we_offs + pwordexp->we_wordc] = NULL; + return 0; + } + + no_space: + return WRDE_NOSPACE; +} + +/* The parse_*() functions should leave *offset being the offset in 'words' + * to the last character processed. + */ +static int +parse_backslash(char **word, size_t * word_length, size_t * max_length, + const char *words, size_t * offset) +{ + /* We are poised _at_ a backslash, not in quotes */ + + switch (words[1 + *offset]) { + case 0: + /* Backslash is last character of input words */ + return WRDE_SYNTAX; + + case '\n': + ++(*offset); + break; + + default: + *word = w_addchar(*word, word_length, max_length, words[1 + *offset]); + if (*word == NULL) + return WRDE_NOSPACE; + + ++(*offset); + break; + } + + return 0; +} + +static int +parse_qtd_backslash(char **word, size_t * word_length, size_t * max_length, + const char *words, size_t * offset) +{ + /* We are poised _at_ a backslash, inside quotes */ + + switch (words[1 + *offset]) { + case 0: + /* Backslash is last character of input words */ + return WRDE_SYNTAX; + + case '\n': + ++(*offset); + break; + + case '$': + case '`': + case '"': + case '\\': + *word = + w_addchar(*word, word_length, max_length, words[1 + *offset]); + if (*word == NULL) + return WRDE_NOSPACE; + + ++(*offset); + break; + + default: + *word = w_addchar(*word, word_length, max_length, words[*offset]); + if (*word != NULL) + *word = + w_addchar(*word, word_length, max_length, + words[1 + *offset]); + + if (*word == NULL) + return WRDE_NOSPACE; + + ++(*offset); + break; + } + + return 0; +} + +static int +parse_tilde(char **word, size_t * word_length, size_t * max_length, + const char *words, size_t * offset, size_t wordc) +{ + /* We are poised _at_ a tilde */ + size_t i; + + if (*word_length != 0) { + if (!((*word)[*word_length - 1] == '=' && wordc == 0)) { + if (!((*word)[*word_length - 1] == ':' + && strchr(*word, '=') && wordc == 0)) { + *word = w_addchar(*word, word_length, max_length, '~'); + return *word ? 0 : WRDE_NOSPACE; + } + } + } + + for (i = 1 + *offset; words[i]; i++) { + if (words[i] == ':' || words[i] == '/' || words[i] == ' ' || + words[i] == '\t' || words[i] == 0) + break; + + if (words[i] == '\\') { + *word = w_addchar(*word, word_length, max_length, '~'); + return *word ? 0 : WRDE_NOSPACE; + } + } + + if (i == 1 + *offset) { + /* Tilde appears on its own */ + uid_t uid; + struct passwd pwd, *tpwd; + int buflen = 1000; + char *home; + char *buffer; + int result; + + /* POSIX.2 says ~ expands to $HOME and if HOME is unset the + results are unspecified. We do a lookup on the uid if + HOME is unset. */ + + home = getenv("HOME"); + if (home != NULL) { + *word = w_addstr(*word, word_length, max_length, home); + if (*word == NULL) + return WRDE_NOSPACE; + } else { + uid = getuid(); + buffer = alloca(buflen); + + while ((result = getpwuid_r(uid, &pwd, buffer, buflen, &tpwd)) + != 0 && errno == ERANGE) + { + buflen += 1000; + buffer = alloca(buflen); + } + + if (result == 0 && tpwd != NULL && pwd.pw_dir != NULL) { + *word = w_addstr(*word, word_length, max_length, pwd.pw_dir); + if (*word == NULL) + return WRDE_NOSPACE; + } else { + *word = w_addchar(*word, word_length, max_length, '~'); + if (*word == NULL) + return WRDE_NOSPACE; + } + } + } else { + /* Look up user name in database to get home directory */ + char *user = strndup(&words[1 + *offset], i - (1 + *offset)); + struct passwd pwd, *tpwd; + int buflen = 1000; + char *buffer = alloca(buflen); + int result; + + while ((result = getpwnam_r(user, &pwd, buffer, buflen, &tpwd)) != 0 + && errno == ERANGE) { + buflen += 1000; + buffer = alloca(buflen); + } + + if (result == 0 && tpwd != NULL && pwd.pw_dir) + *word = w_addstr(*word, word_length, max_length, pwd.pw_dir); + else { + /* (invalid login name) */ + *word = w_addchar(*word, word_length, max_length, '~'); + if (*word != NULL) + *word = w_addstr(*word, word_length, max_length, user); + } + + *offset = i - 1; + } + return *word ? 0 : WRDE_NOSPACE; +} + + +static int +do_parse_glob(const char *glob_word, char **word, size_t * word_length, + size_t * max_length, wordexp_t * pwordexp, const char *ifs + /*, const char *ifs_white*/) +{ + int error; + int match; + glob_t globbuf; + + error = glob(glob_word, GLOB_NOCHECK, NULL, &globbuf); + + if (error != 0) { + /* We can only run into memory problems. */ + assert(error == GLOB_NOSPACE); + return WRDE_NOSPACE; + } + + if (ifs && !*ifs) { + /* No field splitting allowed. */ + assert(globbuf.gl_pathv[0] != NULL); + *word = w_addstr(*word, word_length, max_length, globbuf.gl_pathv[0]); + for (match = 1; match < globbuf.gl_pathc && *word != NULL; ++match) { + *word = w_addchar(*word, word_length, max_length, ' '); + if (*word != NULL) + *word = w_addstr(*word, word_length, max_length, + globbuf.gl_pathv[match]); + } + + globfree(&globbuf); + return *word ? 0 : WRDE_NOSPACE; + } + + assert(ifs == NULL || *ifs != '\0'); + if (*word != NULL) { + free(*word); + *word = w_newword(word_length, max_length); + } + + for (match = 0; match < globbuf.gl_pathc; ++match) { + char *matching_word = strdup(globbuf.gl_pathv[match]); + + if (matching_word == NULL || w_addword(pwordexp, matching_word)) { + globfree(&globbuf); + return WRDE_NOSPACE; + } + } + + globfree(&globbuf); + return 0; +} + +static int +parse_glob(char **word, size_t * word_length, size_t * max_length, + const char *words, size_t * offset, int flags, + wordexp_t * pwordexp, const char *ifs, const char *ifs_white) +{ + /* We are poised just after a '*', a '[' or a '?'. */ + int error = WRDE_NOSPACE; + int quoted = 0; /* 1 if singly-quoted, 2 if doubly */ + int i; + wordexp_t glob_list; /* List of words to glob */ + + glob_list.we_wordc = 0; + glob_list.we_wordv = NULL; + glob_list.we_offs = 0; + for (; words[*offset] != '\0'; ++*offset) { + if ((ifs && strchr(ifs, words[*offset])) || + (!ifs && strchr(" \t\n", words[*offset]))) + /* Reached IFS */ + break; + + /* Sort out quoting */ + if (words[*offset] == '\'') { + if (quoted == 0) { + quoted = 1; + continue; + } else if (quoted == 1) { + quoted = 0; + continue; + } + } else if (words[*offset] == '"') { + if (quoted == 0) { + quoted = 2; + continue; + } else if (quoted == 2) { + quoted = 0; + continue; + } + } + + /* Sort out other special characters */ + if (quoted != 1 && words[*offset] == '$') { + error = parse_dollars(word, word_length, max_length, words, + offset, flags, &glob_list, ifs, + ifs_white, quoted == 2); + if (error) + goto tidy_up; + + continue; + } else if (words[*offset] == '\\') { + if (quoted) + error = parse_qtd_backslash(word, word_length, max_length, + words, offset); + else + error = parse_backslash(word, word_length, max_length, + words, offset); + + if (error) + goto tidy_up; + + continue; + } + + *word = w_addchar(*word, word_length, max_length, words[*offset]); + if (*word == NULL) + goto tidy_up; + } + + /* Don't forget to re-parse the character we stopped at. */ + --*offset; + + /* Glob the words */ + error = w_addword(&glob_list, *word); + *word = w_newword(word_length, max_length); + for (i = 0; error == 0 && i < glob_list.we_wordc; i++) + error = do_parse_glob(glob_list.we_wordv[i], word, word_length, + max_length, pwordexp, ifs /*, ifs_white*/); + + /* Now tidy up */ + tidy_up: + wordfree(&glob_list); + return error; +} + +static int +parse_squote(char **word, size_t * word_length, size_t * max_length, + const char *words, size_t * offset) +{ + /* We are poised just after a single quote */ + for (; words[*offset]; ++(*offset)) { + if (words[*offset] != '\'') { + *word = w_addchar(*word, word_length, max_length, words[*offset]); + if (*word == NULL) + return WRDE_NOSPACE; + } else + return 0; + } + + /* Unterminated string */ + return WRDE_SYNTAX; +} + +#ifdef __WORDEXP_FULL +static int eval_expr(char *expr, long int *result); + +static char *_itoa(unsigned long long int value, char *buflim) +{ + sprintf(buflim, "%llu", value); + return buflim; +} + +/* Functions to evaluate an arithmetic expression */ +static int eval_expr_val(char **expr, long int *result) +{ + int sgn = +1; + char *digit; + + /* Skip white space */ + for (digit = *expr; digit && *digit && isspace(*digit); ++digit); + + switch (*digit) { + case '(': + + /* Scan for closing paren */ + for (++digit; **expr && **expr != ')'; ++(*expr)); + + /* Is there one? */ + if (!**expr) + return WRDE_SYNTAX; + + *(*expr)++ = 0; + + if (eval_expr(digit, result)) + return WRDE_SYNTAX; + + return 0; + + case '+': /* Positive value */ + ++digit; + break; + + case '-': /* Negative value */ + ++digit; + sgn = -1; + break; + + default: + if (!isdigit(*digit)) + return WRDE_SYNTAX; + } + + *result = 0; + for (; *digit && isdigit(*digit); ++digit) + *result = (*result * 10) + (*digit - '0'); + + *expr = digit; + *result *= sgn; + return 0; +} + +static int eval_expr_multdiv(char **expr, long int *result) +{ + long int arg; + + /* Read a Value */ + if (eval_expr_val(expr, result) != 0) + return WRDE_SYNTAX; + + while (**expr) { + /* Skip white space */ + for (; *expr && **expr && isspace(**expr); ++(*expr)); + + if (**expr == '*') { + ++(*expr); + if (eval_expr_val(expr, &arg) != 0) + return WRDE_SYNTAX; + + *result *= arg; + } else if (**expr == '/') { + ++(*expr); + if (eval_expr_val(expr, &arg) != 0) + return WRDE_SYNTAX; + + *result /= arg; + } else + break; + } + + return 0; +} + +static int eval_expr(char *expr, long int *result) +{ + long int arg; + + /* Read a Multdiv */ + if (eval_expr_multdiv(&expr, result) != 0) + return WRDE_SYNTAX; + + while (*expr) { + /* Skip white space */ + for (; expr && *expr && isspace(*expr); ++expr); + + if (*expr == '+') { + ++expr; + if (eval_expr_multdiv(&expr, &arg) != 0) + return WRDE_SYNTAX; + + *result += arg; + } else if (*expr == '-') { + ++expr; + if (eval_expr_multdiv(&expr, &arg) != 0) + return WRDE_SYNTAX; + + *result -= arg; + } else + break; + } + + return 0; +} + +static int +parse_arith(char **word, size_t * word_length, size_t * max_length, + const char *words, size_t * offset, int flags, int bracket) +{ + /* We are poised just after "$((" or "$[" */ + int error; + int paren_depth = 1; + size_t expr_length; + size_t expr_maxlen; + char *expr; + + expr = w_newword(&expr_length, &expr_maxlen); + for (; words[*offset]; ++(*offset)) { + switch (words[*offset]) { + case '$': + error = parse_dollars(&expr, &expr_length, &expr_maxlen, + words, offset, flags, NULL, NULL, NULL, + 1); + /* The ``1'' here is to tell parse_dollars not to + * split the fields. + */ + if (error) { + free(expr); + return error; + } + break; + + case '`': + (*offset)++; + error = parse_backtick(&expr, &expr_length, &expr_maxlen, + words, offset, flags, NULL, NULL, NULL); + /* The first NULL here is to tell parse_backtick not to + * split the fields. + */ + if (error) { + free(expr); + return error; + } + break; + + case '\\': + error = parse_qtd_backslash(&expr, &expr_length, &expr_maxlen, + words, offset); + if (error) { + free(expr); + return error; + } + /* I think that a backslash within an + * arithmetic expansion is bound to + * cause an error sooner or later anyway though. + */ + break; + + case ')': + if (--paren_depth == 0) { + char result[21]; /* 21 = ceil(log10(2^64)) + 1 */ + long int numresult = 0; + long long int convertme; + + if (bracket || words[1 + *offset] != ')') { + free(expr); + return WRDE_SYNTAX; + } + + ++(*offset); + + /* Go - evaluate. */ + if (*expr && eval_expr(expr, &numresult) != 0) { + free(expr); + return WRDE_SYNTAX; + } + + if (numresult < 0) { + convertme = -numresult; + *word = w_addchar(*word, word_length, max_length, '-'); + if (!*word) { + free(expr); + return WRDE_NOSPACE; + } + } else + convertme = numresult; + + result[20] = '\0'; + *word = w_addstr(*word, word_length, max_length, + _itoa(convertme, &result[20])); + free(expr); + return *word ? 0 : WRDE_NOSPACE; + } + expr = + w_addchar(expr, &expr_length, &expr_maxlen, + words[*offset]); + if (expr == NULL) + return WRDE_NOSPACE; + + break; + + case ']': + if (bracket && paren_depth == 1) { + char result[21]; /* 21 = ceil(log10(2^64)) + 1 */ + long int numresult = 0; + + /* Go - evaluate. */ + if (*expr && eval_expr(expr, &numresult) != 0) { + free(expr); + return WRDE_SYNTAX; + } + + result[20] = '\0'; + *word = w_addstr(*word, word_length, max_length, + _itoa(numresult, &result[20])); + free(expr); + return *word ? 0 : WRDE_NOSPACE; + } + + free(expr); + return WRDE_SYNTAX; + + case '\n': + case ';': + case '{': + case '}': + free(expr); + return WRDE_BADCHAR; + + case '(': + ++paren_depth; + default: + expr = + w_addchar(expr, &expr_length, &expr_maxlen, + words[*offset]); + if (expr == NULL) + return WRDE_NOSPACE; + } + } + + /* Premature end */ + free(expr); + return WRDE_SYNTAX; +} + +/* Function called by child process in exec_comm() */ +static void attribute_noreturn +exec_comm_child(char *comm, int *fildes, int showerr, int noexec) +{ + int fd; + const char *args[4] = { _PATH_BSHELL, "-c", comm, NULL }; + + /* Execute the command, or just check syntax? */ + if (noexec) + args[1] = "-nc"; + + /* Redirect output. */ + fd = fildes[1]; + if (fd != 1) { + dup2(fd, 1); + close(fd); + } + + /* Redirect stderr to /dev/null if we have to. */ + if (showerr == 0) { + close(2); + fd = open(_PATH_DEVNULL, O_WRONLY); + if (fd >= 0 && fd != 2) { + dup2(fd, 2); + close(fd); + } + } + + /* Make sure the subshell doesn't field-split on our behalf. */ + unsetenv("IFS"); + + if (fildes[0] != 1) + close(fildes[0]); + execve(_PATH_BSHELL, (char *const *) args, __environ); + + /* Bad. What now? */ + abort(); +} + +/* Function to execute a command and retrieve the results */ +/* pwordexp contains NULL if field-splitting is forbidden */ +static int +exec_comm(char *comm, char **word, size_t * word_length, + size_t * max_length, int flags, wordexp_t * pwordexp, + const char *ifs, const char *ifs_white) +{ + int fildes[2]; + int bufsize = 128; + int buflen; + int i; + int status = 0; + size_t maxnewlines = 0; + char *buffer; + pid_t pid; + + /* Don't fork() unless necessary */ + if (!comm || !*comm) + return 0; + + if (pipe(fildes)) + /* Bad */ + return WRDE_NOSPACE; + + if ((pid = fork()) < 0) { + /* Bad */ + close(fildes[0]); + close(fildes[1]); + return WRDE_NOSPACE; + } + + if (pid == 0) + exec_comm_child(comm, fildes, (flags & WRDE_SHOWERR), 0); + + /* Parent */ + + close(fildes[1]); + buffer = alloca(bufsize); + + if (!pwordexp) + /* Quoted - no field splitting */ + { + while (1) { + if ((buflen = read(fildes[0], buffer, bufsize)) < 1) { + if (waitpid(pid, &status, WNOHANG) == 0) + continue; + if ((buflen = read(fildes[0], buffer, bufsize)) < 1) + break; + } + + maxnewlines += buflen; + + *word = w_addmem(*word, word_length, max_length, buffer, buflen); + if (*word == NULL) + goto no_space; + } + } else + /* Not quoted - split fields */ + { + int copying = 0; + + /* 'copying' is: + * 0 when searching for first character in a field not IFS white space + * 1 when copying the text of a field + * 2 when searching for possible non-whitespace IFS + * 3 when searching for non-newline after copying field + */ + + while (1) { + if ((buflen = read(fildes[0], buffer, bufsize)) < 1) { + if (waitpid(pid, &status, WNOHANG) == 0) + continue; + if ((buflen = read(fildes[0], buffer, bufsize)) < 1) + break; + } + + for (i = 0; i < buflen; ++i) { + if (strchr(ifs, buffer[i]) != NULL) { + /* Current character is IFS */ + if (strchr(ifs_white, buffer[i]) == NULL) { + /* Current character is IFS but not whitespace */ + if (copying == 2) { + /* current character + * | + * V + * eg: textmoretext + * + * So, strip whitespace IFS (like at the start) + */ + copying = 0; + continue; + } + + copying = 0; + /* fall through and delimit field.. */ + } else { + if (buffer[i] == '\n') { + /* Current character is (IFS) newline */ + + /* If copying a field, this is the end of it, + but maybe all that's left is trailing newlines. + So start searching for a non-newline. */ + if (copying == 1) + copying = 3; + + continue; + } else { + /* Current character is IFS white space, but + not a newline */ + + /* If not either copying a field or searching + for non-newline after a field, ignore it */ + if (copying != 1 && copying != 3) + continue; + + /* End of field (search for non-ws IFS afterwards) */ + copying = 2; + } + } + + /* First IFS white space (non-newline), or IFS non-whitespace. + * Delimit the field. Nulls are converted by w_addword. */ + if (w_addword(pwordexp, *word) == WRDE_NOSPACE) + goto no_space; + + *word = w_newword(word_length, max_length); + + maxnewlines = 0; + /* fall back round the loop.. */ + } else { + /* Not IFS character */ + + if (copying == 3) { + /* Nothing but (IFS) newlines since the last field, + so delimit it here before starting new word */ + if (w_addword(pwordexp, *word) == WRDE_NOSPACE) + goto no_space; + + *word = w_newword(word_length, max_length); + } + + copying = 1; + + if (buffer[i] == '\n') /* happens if newline not in IFS */ + maxnewlines++; + else + maxnewlines = 0; + + *word = w_addchar(*word, word_length, max_length, + buffer[i]); + if (*word == NULL) + goto no_space; + } + } + } + } + + /* Chop off trailing newlines (required by POSIX.2) */ + /* Ensure we don't go back further than the beginning of the + substitution (i.e. remove maxnewlines bytes at most) */ + while (maxnewlines-- != 0 && + *word_length > 0 && (*word)[*word_length - 1] == '\n') { + (*word)[--*word_length] = '\0'; + + /* If the last word was entirely newlines, turn it into a new word + * which can be ignored if there's nothing following it. */ + if (*word_length == 0) { + free(*word); + *word = w_newword(word_length, max_length); + break; + } + } + + close(fildes[0]); + + /* Check for syntax error (re-execute but with "-n" flag) */ + if (buflen < 1 && status != 0) { + if ((pid = fork()) < 0) { + /* Bad */ + return WRDE_NOSPACE; + } + + if (pid == 0) { + fildes[0] = fildes[1] = -1; + exec_comm_child(comm, fildes, 0, 1); + } + + if (waitpid(pid, &status, 0) == pid && status != 0) + return WRDE_SYNTAX; + } + + return 0; + + no_space: + kill(pid, SIGKILL); + waitpid(pid, NULL, 0); + close(fildes[0]); + return WRDE_NOSPACE; +} + +static int +parse_comm(char **word, size_t * word_length, size_t * max_length, + const char *words, size_t * offset, int flags, + wordexp_t * pwordexp, const char *ifs, const char *ifs_white) +{ + /* We are poised just after "$(" */ + int paren_depth = 1; + int error = 0; + int quoted = 0; /* 1 for singly-quoted, 2 for doubly-quoted */ + size_t comm_length; + size_t comm_maxlen; + char *comm = w_newword(&comm_length, &comm_maxlen); + + for (; words[*offset]; ++(*offset)) { + switch (words[*offset]) { + case '\'': + if (quoted == 0) + quoted = 1; + else if (quoted == 1) + quoted = 0; + + break; + + case '"': + if (quoted == 0) + quoted = 2; + else if (quoted == 2) + quoted = 0; + + break; + + case ')': + if (!quoted && --paren_depth == 0) { + /* Go -- give script to the shell */ + if (comm) { + error = exec_comm(comm, word, word_length, max_length, + flags, pwordexp, ifs, ifs_white); + free(comm); + } + + return error; + } + + /* This is just part of the script */ + break; + + case '(': + if (!quoted) + ++paren_depth; + } + + comm = w_addchar(comm, &comm_length, &comm_maxlen, words[*offset]); + if (comm == NULL) + return WRDE_NOSPACE; + } + + /* Premature end */ + free(comm); + + return WRDE_SYNTAX; +} + +static int +parse_backtick(char **word, size_t * word_length, size_t * max_length, + const char *words, size_t * offset, int flags, + wordexp_t * pwordexp, const char *ifs, + const char *ifs_white) +{ + /* We are poised just after "`" */ + int error; + int squoting = 0; + size_t comm_length; + size_t comm_maxlen; + char *comm = w_newword(&comm_length, &comm_maxlen); + + for (; words[*offset]; ++(*offset)) { + switch (words[*offset]) { + case '`': + /* Go -- give the script to the shell */ + error = exec_comm(comm, word, word_length, max_length, flags, + pwordexp, ifs, ifs_white); + free(comm); + return error; + + case '\\': + if (squoting) { + error = parse_qtd_backslash(&comm, &comm_length, &comm_maxlen, + words, offset); + + if (error) { + free(comm); + return error; + } + + break; + } + + ++(*offset); + error = parse_backslash(&comm, &comm_length, &comm_maxlen, words, + offset); + + if (error) { + free(comm); + return error; + } + + break; + + case '\'': + squoting = 1 - squoting; + default: + comm = w_addchar(comm, &comm_length, &comm_maxlen, + words[*offset]); + if (comm == NULL) + return WRDE_NOSPACE; + } + } + + /* Premature end */ + free(comm); + return WRDE_SYNTAX; +} + +static int +parse_param(char **word, size_t * word_length, size_t * max_length, + const char *words, size_t * offset, int flags, + wordexp_t * pwordexp, const char *ifs, const char *ifs_white, + int quoted) +{ + /* We are poised just after "$" */ + enum action { + ACT_NONE, + ACT_RP_SHORT_LEFT = '#', + ACT_RP_LONG_LEFT = 'L', + ACT_RP_SHORT_RIGHT = '%', + ACT_RP_LONG_RIGHT = 'R', + ACT_NULL_ERROR = '?', + ACT_NULL_SUBST = '-', + ACT_NONNULL_SUBST = '+', + ACT_NULL_ASSIGN = '=' + }; + size_t env_length; + size_t env_maxlen; + size_t pat_length; + size_t pat_maxlen; + size_t start = *offset; + char *env; + char *pattern; + char *value = NULL; + enum action action = ACT_NONE; + int depth = 0; + int colon_seen = 0; + int seen_hash = 0; + int free_value = 0; + int pattern_is_quoted = 0; /* 1 for singly-quoted, 2 for doubly-quoted */ + int error; + int special = 0; + char buffer[21]; + int brace = words[*offset] == '{'; + + env = w_newword(&env_length, &env_maxlen); + pattern = w_newword(&pat_length, &pat_maxlen); + + if (brace) + ++ * offset; + + /* First collect the parameter name. */ + + if (words[*offset] == '#') { + seen_hash = 1; + if (!brace) + goto envsubst; + ++*offset; + } + + if (isalpha(words[*offset]) || words[*offset] == '_') { + /* Normal parameter name. */ + do { + env = w_addchar(env, &env_length, &env_maxlen, words[*offset]); + if (env == NULL) + goto no_space; + } + while (isalnum(words[++*offset]) || words[*offset] == '_'); + } else if (isdigit(words[*offset])) { + /* Numeric parameter name. */ + special = 1; + do { + env = w_addchar(env, &env_length, &env_maxlen, words[*offset]); + if (env == NULL) + goto no_space; + if (!brace) + goto envsubst; + } + while (isdigit(words[++*offset])); + } else if (strchr("*@$", words[*offset]) != NULL) { + /* Special parameter. */ + special = 1; + env = w_addchar(env, &env_length, &env_maxlen, words[*offset]); + if (env == NULL) + goto no_space; + ++*offset; + } else { + if (brace) + goto syntax; + } + + if (brace) { + /* Check for special action to be applied to the value. */ + switch (words[*offset]) { + case '}': + /* Evaluate. */ + goto envsubst; + + case '#': + action = ACT_RP_SHORT_LEFT; + if (words[1 + *offset] == '#') { + ++*offset; + action = ACT_RP_LONG_LEFT; + } + break; + + case '%': + action = ACT_RP_SHORT_RIGHT; + if (words[1 + *offset] == '%') { + ++*offset; + action = ACT_RP_LONG_RIGHT; + } + break; + + case ':': + if (strchr("-=?+", words[1 + *offset]) == NULL) + goto syntax; + + colon_seen = 1; + action = words[++*offset]; + break; + + case '-': + case '=': + case '?': + case '+': + action = words[*offset]; + break; + + default: + goto syntax; + } + + /* Now collect the pattern, but don't expand it yet. */ + ++*offset; + for (; words[*offset]; ++(*offset)) { + switch (words[*offset]) { + case '{': + if (!pattern_is_quoted) + ++depth; + break; + + case '}': + if (!pattern_is_quoted) { + if (depth == 0) + goto envsubst; + --depth; + } + break; + + case '\\': + if (pattern_is_quoted) + /* Quoted; treat as normal character. */ + break; + + /* Otherwise, it's an escape: next character is literal. */ + if (words[++*offset] == '\0') + goto syntax; + + pattern = w_addchar(pattern, &pat_length, &pat_maxlen, '\\'); + if (pattern == NULL) + goto no_space; + + break; + + case '\'': + if (pattern_is_quoted == 0) + pattern_is_quoted = 1; + else if (pattern_is_quoted == 1) + pattern_is_quoted = 0; + + break; + + case '"': + if (pattern_is_quoted == 0) + pattern_is_quoted = 2; + else if (pattern_is_quoted == 2) + pattern_is_quoted = 0; + + break; + } + + pattern = w_addchar(pattern, &pat_length, &pat_maxlen, + words[*offset]); + if (pattern == NULL) + goto no_space; + } + } + + /* End of input string -- remember to reparse the character that we + * stopped at. */ + --(*offset); + + envsubst: + if (words[start] == '{' && words[*offset] != '}') + goto syntax; + + if (env == NULL) { + if (seen_hash) { + /* $# expands to the number of positional parameters */ + buffer[20] = '\0'; + value = _itoa(__libc_argc - 1, &buffer[20]); + seen_hash = 0; + } else { + /* Just $ on its own */ + *offset = start - 1; + *word = w_addchar(*word, word_length, max_length, '$'); + return *word ? 0 : WRDE_NOSPACE; + } + } + /* Is it a numeric parameter? */ + else if (isdigit(env[0])) { + int n = atoi(env); + + if (n >= __libc_argc) + /* Substitute NULL. */ + value = NULL; + else + /* Replace with appropriate positional parameter. */ + value = __libc_argv[n]; + } + /* Is it a special parameter? */ + else if (special) { + /* Is it `$$'? */ + if (*env == '$') { + buffer[20] = '\0'; + value = _itoa(getpid(), &buffer[20]); + } + /* Is it `${#*}' or `${#@}'? */ + else if ((*env == '*' || *env == '@') && seen_hash) { + buffer[20] = '\0'; + value = _itoa(__libc_argc > 0 ? __libc_argc - 1 : 0, + &buffer[20]); + *word = w_addstr(*word, word_length, max_length, value); + free(env); + free(pattern); + return *word ? 0 : WRDE_NOSPACE; + } + /* Is it `$*' or `$@' (unquoted) ? */ + else if (*env == '*' || (*env == '@' && !quoted)) { + size_t plist_len = 0; + int p; + char *end; + + /* Build up value parameter by parameter (copy them) */ + for (p = 1; __libc_argv[p]; ++p) + plist_len += strlen(__libc_argv[p]) + 1; /* for space */ + value = malloc(plist_len); + if (value == NULL) + goto no_space; + end = value; + *end = 0; + for (p = 1; __libc_argv[p]; ++p) { + if (p > 1) + *end++ = ' '; + end = stpcpy(end, __libc_argv[p]); + } + + free_value = 1; + } else { + /* Must be a quoted `$@' */ + assert(*env == '@' && quoted); + + /* Each parameter is a separate word ("$@") */ + if (__libc_argc == 2) + value = __libc_argv[1]; + else if (__libc_argc > 2) { + int p; + + /* Append first parameter to current word. */ + value = w_addstr(*word, word_length, max_length, + __libc_argv[1]); + if (value == NULL || w_addword(pwordexp, value)) + goto no_space; + + for (p = 2; __libc_argv[p + 1]; p++) { + char *newword = strdup(__libc_argv[p]); + + if (newword == NULL || w_addword(pwordexp, newword)) + goto no_space; + } + + /* Start a new word with the last parameter. */ + *word = w_newword(word_length, max_length); + value = __libc_argv[p]; + } else { + free(env); + free(pattern); + return 0; + } + } + } else + value = getenv(env); + + if (value == NULL && (flags & WRDE_UNDEF)) { + /* Variable not defined. */ + error = WRDE_BADVAL; + goto do_error; + } + + if (action != ACT_NONE) { + int expand_pattern = 0; + + /* First, find out if we need to expand pattern (i.e. if we will + * use it). */ + switch (action) { + case ACT_RP_SHORT_LEFT: + case ACT_RP_LONG_LEFT: + case ACT_RP_SHORT_RIGHT: + case ACT_RP_LONG_RIGHT: + /* Always expand for these. */ + expand_pattern = 1; + break; + + case ACT_NULL_ERROR: + case ACT_NULL_SUBST: + case ACT_NULL_ASSIGN: + if (!value || (!*value && colon_seen)) + /* If param is unset, or set but null and a colon has been seen, + the expansion of the pattern will be needed. */ + expand_pattern = 1; + + break; + + case ACT_NONNULL_SUBST: + /* Expansion of word will be needed if parameter is set and not null, + or set null but no colon has been seen. */ + if (value && (*value || !colon_seen)) + expand_pattern = 1; + + break; + + default: + assert(!"Unrecognised action!"); + } + + if (expand_pattern) { + /* We need to perform tilde expansion, parameter expansion, + command substitution, and arithmetic expansion. We also + have to be a bit careful with wildcard characters, as + pattern might be given to fnmatch soon. To do this, we + convert quotes to escapes. */ + + char *expanded; + size_t exp_len; + size_t exp_maxl; + char *p; + int quotes = 0; /* 1: single quotes; 2: double */ + + expanded = w_newword(&exp_len, &exp_maxl); + for (p = pattern; p && *p; p++) { + size_t _offset; + + switch (*p) { + case '"': + if (quotes == 2) + quotes = 0; + else if (quotes == 0) + quotes = 2; + else + break; + + continue; + + case '\'': + if (quotes == 1) + quotes = 0; + else if (quotes == 0) + quotes = 1; + else + break; + + continue; + + case '*': + case '?': + if (quotes) { + /* Convert quoted wildchar to escaped wildchar. */ + expanded = w_addchar(expanded, &exp_len, + &exp_maxl, '\\'); + + if (expanded == NULL) + goto no_space; + } + break; + + case '$': + _offset = 0; + error = parse_dollars(&expanded, &exp_len, &exp_maxl, p, + &_offset, flags, NULL, NULL, NULL, 1); + if (error) { + if (free_value) + free(value); + + free(expanded); + + goto do_error; + } + + p += _offset; + continue; + + case '~': + if (quotes || exp_len) + break; + + _offset = 0; + error = parse_tilde(&expanded, &exp_len, &exp_maxl, p, + &_offset, 0); + if (error) { + if (free_value) + free(value); + + free(expanded); + + goto do_error; + } + + p += _offset; + continue; + + case '\\': + expanded = w_addchar(expanded, &exp_len, &exp_maxl, '\\'); + ++p; + assert(*p); /* checked when extracted initially */ + if (expanded == NULL) + goto no_space; + } + + expanded = w_addchar(expanded, &exp_len, &exp_maxl, *p); + + if (expanded == NULL) + goto no_space; + } + + free(pattern); + + pattern = expanded; + } + + switch (action) { + case ACT_RP_SHORT_LEFT: + case ACT_RP_LONG_LEFT: + case ACT_RP_SHORT_RIGHT: + case ACT_RP_LONG_RIGHT: + { + char *p; + char c; + char *end; + + if (value == NULL || pattern == NULL || *pattern == '\0') + break; + + end = value + strlen(value); + + switch (action) { + case ACT_RP_SHORT_LEFT: + for (p = value; p <= end; ++p) { + c = *p; + *p = '\0'; + if (fnmatch(pattern, value, 0) != FNM_NOMATCH) { + *p = c; + if (free_value) { + char *newval = strdup(p); + + if (newval == NULL) { + free(value); + goto no_space; + } + free(value); + value = newval; + } else + value = p; + break; + } + *p = c; + } + + break; + + case ACT_RP_LONG_LEFT: + for (p = end; p >= value; --p) { + c = *p; + *p = '\0'; + if (fnmatch(pattern, value, 0) != FNM_NOMATCH) { + *p = c; + if (free_value) { + char *newval = strdup(p); + + if (newval == NULL) { + free(value); + goto no_space; + } + free(value); + value = newval; + } else + value = p; + break; + } + *p = c; + } + + break; + + case ACT_RP_SHORT_RIGHT: + for (p = end; p >= value; --p) { + if (fnmatch(pattern, p, 0) != FNM_NOMATCH) { + char *newval; + + newval = malloc(p - value + 1); + + if (newval == NULL) { + if (free_value) + free(value); + goto no_space; + } + + *(char *) mempcpy(newval, value, p - value) = '\0'; + if (free_value) + free(value); + value = newval; + free_value = 1; + break; + } + } + + break; + + case ACT_RP_LONG_RIGHT: + for (p = value; p <= end; ++p) { + if (fnmatch(pattern, p, 0) != FNM_NOMATCH) { + char *newval; + + newval = malloc(p - value + 1); + + if (newval == NULL) { + if (free_value) + free(value); + goto no_space; + } + + *(char *) mempcpy(newval, value, p - value) = '\0'; + if (free_value) + free(value); + value = newval; + free_value = 1; + break; + } + } + + break; + + default: + break; + } + + break; + } + + case ACT_NULL_ERROR: + if (value && *value) + /* Substitute parameter */ + break; + + error = 0; + if (!colon_seen && value) + /* Substitute NULL */ + ; + else if (*pattern) + fprintf(stderr, "%s: %s\n", env, pattern); + else { + fprintf(stderr, "%s: parameter null or not set\n", env); + error = WRDE_BADVAL; + } + + if (free_value) + free(value); + goto do_error; + + case ACT_NULL_SUBST: + if (value && *value) + /* Substitute parameter */ + break; + + if (free_value) + free(value); + + if (!colon_seen && value) + /* Substitute NULL */ + goto success; + + value = pattern ? strdup(pattern) : pattern; + free_value = 1; + + if (pattern && !value) + goto no_space; + + break; + + case ACT_NONNULL_SUBST: + if (value && (*value || !colon_seen)) { + if (free_value) + free(value); + + value = pattern ? strdup(pattern) : pattern; + free_value = 1; + + if (pattern && !value) + goto no_space; + + break; + } + + /* Substitute NULL */ + if (free_value) + free(value); + goto success; + + case ACT_NULL_ASSIGN: + if (value && *value) + /* Substitute parameter */ + break; + + if (!colon_seen && value) { + /* Substitute NULL */ + if (free_value) + free(value); + goto success; + } + + if (free_value) + free(value); + + value = pattern ? strdup(pattern) : pattern; + free_value = 1; + + if (pattern && !value) + goto no_space; + + setenv(env, value, 1); + break; + + default: + assert(!"Unrecognised action!"); + } + } + + free(env); + env = NULL; + free(pattern); + pattern = NULL; + + if (seen_hash) { + char param_length[21]; + + param_length[20] = '\0'; + *word = w_addstr(*word, word_length, max_length, + _itoa(value ? strlen(value) : 0, + ¶m_length[20])); + if (free_value) { + assert(value != NULL); + free(value); + } + + return *word ? 0 : WRDE_NOSPACE; + } + + if (value == NULL) + return 0; + + if (quoted || !pwordexp) { + /* Quoted - no field split */ + *word = w_addstr(*word, word_length, max_length, value); + if (free_value) + free(value); + + return *word ? 0 : WRDE_NOSPACE; + } else { + /* Need to field-split */ + char *value_copy = strdup(value); /* Don't modify value */ + char *field_begin = value_copy; + int seen_nonws_ifs = 0; + + if (free_value) + free(value); + + if (value_copy == NULL) + goto no_space; + + do { + char *field_end = field_begin; + char *next_field; + + /* If this isn't the first field, start a new word */ + if (field_begin != value_copy) { + if (w_addword(pwordexp, *word) == WRDE_NOSPACE) { + free(value_copy); + goto no_space; + } + + *word = w_newword(word_length, max_length); + } + + /* Skip IFS whitespace before the field */ + field_begin += strspn(field_begin, ifs_white); + + if (!seen_nonws_ifs && *field_begin == 0) + /* Nothing but whitespace */ + break; + + /* Search for the end of the field */ + field_end = field_begin + strcspn(field_begin, ifs); + + /* Set up pointer to the character after end of field and + skip whitespace IFS after it. */ + next_field = field_end + strspn(field_end, ifs_white); + + /* Skip at most one non-whitespace IFS character after the field */ + seen_nonws_ifs = 0; + if (*next_field && strchr(ifs, *next_field)) { + seen_nonws_ifs = 1; + next_field++; + } + + /* Null-terminate it */ + *field_end = 0; + + /* Tag a copy onto the current word */ + *word = w_addstr(*word, word_length, max_length, field_begin); + + if (*word == NULL && *field_begin != '\0') { + free(value_copy); + goto no_space; + } + + field_begin = next_field; + } + while (seen_nonws_ifs || *field_begin); + + free(value_copy); + } + + return 0; + + success: + error = 0; + goto do_error; + + no_space: + error = WRDE_NOSPACE; + goto do_error; + + syntax: + error = WRDE_SYNTAX; + + do_error: + free(env); + + free(pattern); + + return error; +} +#else +static __inline__ int +parse_backtick(char **word, size_t * word_length, size_t * max_length, + const char *words, size_t * offset, int flags, + wordexp_t * pwordexp, const char *ifs, + const char *ifs_white) +{ + return 0; +} +#endif + +static int +parse_dollars(char **word, size_t * word_length, size_t * max_length, + const char *words, size_t * offset, int flags, + wordexp_t * pwordexp, const char *ifs, const char *ifs_white, + int quoted) +{ + /* We are poised _at_ "$" */ + switch (words[1 + *offset]) { + case '"': + case '\'': + case 0: + *word = w_addchar(*word, word_length, max_length, '$'); + return *word ? 0 : WRDE_NOSPACE; + +#ifdef __WORDEXP_FULL + case '(': + if (words[2 + *offset] == '(') { + /* Differentiate between $((1+3)) and $((echo);(ls)) */ + int i = 3 + *offset; + int depth = 0; + + while (words[i] && !(depth == 0 && words[i] == ')')) { + if (words[i] == '(') + ++depth; + else if (words[i] == ')') + --depth; + + ++i; + } + + if (words[i] == ')' && words[i + 1] == ')') { + (*offset) += 3; + /* Call parse_arith -- 0 is for "no brackets" */ + return parse_arith(word, word_length, max_length, words, + offset, flags, 0); + } + } + + if (flags & WRDE_NOCMD) + return WRDE_CMDSUB; + + (*offset) += 2; + return parse_comm(word, word_length, max_length, words, offset, + flags, quoted ? NULL : pwordexp, ifs, ifs_white); + + case '[': + (*offset) += 2; + /* Call parse_arith -- 1 is for "brackets" */ + return parse_arith(word, word_length, max_length, words, offset, + flags, 1); + + case '{': + default: + ++(*offset); /* parse_param needs to know if "{" is there */ + return parse_param(word, word_length, max_length, words, offset, + flags, pwordexp, ifs, ifs_white, quoted); +#else + default: + ++(*offset); /* parse_param needs to know if "{" is there */ + return 0; +#endif + } +} + +static int +parse_dquote(char **word, size_t * word_length, size_t * max_length, + const char *words, size_t * offset, int flags, + wordexp_t * pwordexp, const char *ifs, const char *ifs_white) +{ + /* We are poised just after a double-quote */ + int error; + + for (; words[*offset]; ++(*offset)) { + switch (words[*offset]) { + case '"': + return 0; + + case '$': + error = parse_dollars(word, word_length, max_length, words, offset, + flags, pwordexp, ifs, ifs_white, 1); + /* The ``1'' here is to tell parse_dollars not to + * split the fields. It may need to, however ("$@"). + */ + if (error) + return error; + + break; + + case '`': + if (flags & WRDE_NOCMD) + return WRDE_CMDSUB; + + ++(*offset); + error = parse_backtick(word, word_length, max_length, words, + offset, flags, NULL, NULL, NULL); + /* The first NULL here is to tell parse_backtick not to + * split the fields. + */ + if (error) + return error; + + break; + + case '\\': + error = parse_qtd_backslash(word, word_length, max_length, words, + offset); + + if (error) + return error; + + break; + + default: + *word = w_addchar(*word, word_length, max_length, words[*offset]); + if (*word == NULL) + return WRDE_NOSPACE; + } + } + + /* Unterminated string */ + return WRDE_SYNTAX; +} + +/* + * wordfree() is to be called after pwordexp is finished with. + */ + +void wordfree(wordexp_t * pwordexp) +{ + + /* wordexp can set pwordexp to NULL */ + if (pwordexp && pwordexp->we_wordv) { + char **wordv = pwordexp->we_wordv; + + for (wordv += pwordexp->we_offs; *wordv; ++wordv) + free(*wordv); + + free(pwordexp->we_wordv); + pwordexp->we_wordv = NULL; + } +} +libc_hidden_def(wordfree) + +/* + * wordexp() + */ + +int wordexp(const char *words, wordexp_t * we, int flags) +{ + size_t words_offset; + size_t word_length; + size_t max_length; + char *word = w_newword(&word_length, &max_length); + int error; + char *ifs; + char ifs_white[4]; + wordexp_t old_word = *we; + + if (flags & WRDE_REUSE) { + /* Minimal implementation of WRDE_REUSE for now */ + wordfree(we); + old_word.we_wordv = NULL; + } + + if ((flags & WRDE_APPEND) == 0) { + we->we_wordc = 0; + + if (flags & WRDE_DOOFFS) { + we->we_wordv = calloc(1 + we->we_offs, sizeof(char *)); + if (we->we_wordv == NULL) { + error = WRDE_NOSPACE; + goto do_error; + } + } else { + we->we_wordv = calloc(1, sizeof(char *)); + if (we->we_wordv == NULL) { + error = WRDE_NOSPACE; + goto do_error; + } + + we->we_offs = 0; + } + } + + /* Find out what the field separators are. + * There are two types: whitespace and non-whitespace. + */ + ifs = getenv("IFS"); + + if (!ifs) + /* IFS unset - use . */ + ifs = strcpy(ifs_white, " \t\n"); + else { + char *ifsch = ifs; + char *whch = ifs_white; + + /* Start off with no whitespace IFS characters */ + ifs_white[0] = '\0'; + + while (*ifsch != '\0') { + if ((*ifsch == ' ') || (*ifsch == '\t') || (*ifsch == '\n')) { + /* Whitespace IFS. See first whether it is already in our + collection. */ + char *runp = ifs_white; + + while (runp < whch && *runp != '\0' && *runp != *ifsch) + ++runp; + + if (runp == whch) + *whch++ = *ifsch; + } + + ++ifsch; + } + *whch = '\0'; + } + + for (words_offset = 0; words[words_offset]; ++words_offset) + switch (words[words_offset]) { + case '\\': + error = parse_backslash(&word, &word_length, &max_length, words, + &words_offset); + + if (error) + goto do_error; + + break; + + case '$': + error = parse_dollars(&word, &word_length, &max_length, words, + &words_offset, flags, we, ifs, ifs_white, + 0); + + if (error) + goto do_error; + + break; + + case '`': + if (flags & WRDE_NOCMD) { + error = WRDE_CMDSUB; + goto do_error; + } + + ++words_offset; + error = parse_backtick(&word, &word_length, &max_length, words, + &words_offset, flags, we, ifs, + ifs_white); + + if (error) + goto do_error; + + break; + + case '"': + ++words_offset; + error = parse_dquote(&word, &word_length, &max_length, words, + &words_offset, flags, we, ifs, ifs_white); + + if (error) + goto do_error; + + if (!word_length) { + error = w_addword(we, NULL); + + if (error) + return error; + } + + break; + + case '\'': + ++words_offset; + error = parse_squote(&word, &word_length, &max_length, words, + &words_offset); + + if (error) + goto do_error; + + if (!word_length) { + error = w_addword(we, NULL); + + if (error) + return error; + } + + break; + + case '~': + error = parse_tilde(&word, &word_length, &max_length, words, + &words_offset, we->we_wordc); + + if (error) + goto do_error; + + break; + + case '*': + case '[': + case '?': + error = parse_glob(&word, &word_length, &max_length, words, + &words_offset, flags, we, ifs, ifs_white); + + if (error) + goto do_error; + + break; + + default: + /* Is it a word separator? */ + if (strchr(" \t", words[words_offset]) == NULL) { + char ch = words[words_offset]; + + /* Not a word separator -- but is it a valid word char? */ + if (strchr("\n|&;<>(){}", ch)) { + /* Fail */ + error = WRDE_BADCHAR; + goto do_error; + } + + /* "Ordinary" character -- add it to word */ + word = w_addchar(word, &word_length, &max_length, ch); + if (word == NULL) { + error = WRDE_NOSPACE; + goto do_error; + } + + break; + } + + /* If a word has been delimited, add it to the list. */ + if (word != NULL) { + error = w_addword(we, word); + if (error) + goto do_error; + } + + word = w_newword(&word_length, &max_length); + } + + /* End of string */ + + /* There was a word separator at the end */ + if (word == NULL) /* i.e. w_newword */ + return 0; + + /* There was no field separator at the end */ + return w_addword(we, word); + + do_error: + /* Error: + * free memory used (unless error is WRDE_NOSPACE), and + * set we members back to what they were. + */ + + free(word); + + if (error == WRDE_NOSPACE) + return WRDE_NOSPACE; + + if ((flags & WRDE_APPEND) == 0) + wordfree(we); + + *we = old_word; + return error; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/.indent.pro b/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/.indent.pro new file mode 100644 index 00000000..492ecf1c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/.indent.pro @@ -0,0 +1,33 @@ +--blank-lines-after-declarations +--blank-lines-after-procedures +--break-before-boolean-operator +--no-blank-lines-after-commas +--braces-on-if-line +--braces-on-struct-decl-line +--comment-indentation25 +--declaration-comment-column25 +--no-comment-delimiters-on-blank-lines +--cuddle-else +--continuation-indentation4 +--case-indentation0 +--else-endif-column33 +--space-after-cast +--line-comments-indentation0 +--declaration-indentation1 +--dont-format-first-column-comments +--dont-format-comments +--honour-newlines +--indent-level4 +/* changed from 0 to 4 */ +--parameter-indentation4 +--line-length78 /* changed from 75 */ +--continue-at-parentheses +--no-space-after-function-call-names +--dont-break-procedure-type +--dont-star-comments +--leave-optional-blank-lines +--dont-space-special-semicolon +--tab-size4 +/* additions by Mark */ +--case-brace-indentation0 +--leave-preprocessor-space diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/Makefile new file mode 100644 index 00000000..11f362a5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../ +top_builddir=../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/Makefile.in new file mode 100644 index 00000000..757adc85 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/Makefile.in @@ -0,0 +1,33 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +subdirs += libc/pwd_grp + +PWDGRP_DIR := $(top_srcdir)libc/pwd_grp +PWDGRP_OUT := $(top_builddir)libc/pwd_grp + +CSRC := $(notdir $(wildcard $(PWDGRP_DIR)/*.c)) +CSRC := $(filter-out pwd_grp.c pwd_grp_internal.c,$(CSRC)) + +ifneq ($(UCLIBC_HAS_SHADOW),y) +SHADOW_CSRC := \ + fgetspent_r.c fgetspent.c getspent_r.c getspent.c \ + getspnam_r.c getspnam.c lckpwdf.c putspent.c \ + sgetspent_r.c sgetspent.c __parsespent.c +# getspuid_r.c getspuid.c +CSRC := $(filter-out $(SHADOW_CSRC),$(CSRC)) +endif + +PWDGRP_SRC := $(patsubst %.c,$(PWDGRP_DIR)/%.c,$(CSRC)) +PWDGRP_OBJ := $(patsubst %.c,$(PWDGRP_OUT)/%.o,$(CSRC)) + +libc-y += $(PWDGRP_OBJ) + +objclean-y += CLEAN_libc/pwd_grp + +CLEAN_libc/pwd_grp: + $(do_rm) $(addprefix $(PWDGRP_OUT)/*., o os) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/__getgrouplist_internal.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/__getgrouplist_internal.c new file mode 100644 index 00000000..c2edc99c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/__getgrouplist_internal.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L___getgrouplist_internal +#include "pwd_grp.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/__parsegrent.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/__parsegrent.c new file mode 100644 index 00000000..e3ac4ad7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/__parsegrent.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L___parsegrent +#include "pwd_grp.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/__parsepwent.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/__parsepwent.c new file mode 100644 index 00000000..2804a0a2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/__parsepwent.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L___parsepwent +#include "pwd_grp.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/__parsespent.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/__parsespent.c new file mode 100644 index 00000000..08321d07 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/__parsespent.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L___parsespent +#include "pwd_grp.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/__pgsreader.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/__pgsreader.c new file mode 100644 index 00000000..ac39ce94 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/__pgsreader.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L___pgsreader +#include "pwd_grp.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/fgetgrent.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/fgetgrent.c new file mode 100644 index 00000000..695aee11 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/fgetgrent.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_fgetgrent +#include "pwd_grp.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/fgetgrent_r.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/fgetgrent_r.c new file mode 100644 index 00000000..ea97af72 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/fgetgrent_r.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_fgetgrent_r +#include "pwd_grp.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/fgetpwent.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/fgetpwent.c new file mode 100644 index 00000000..ddcc7ffb --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/fgetpwent.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_fgetpwent +#include "pwd_grp.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/fgetpwent_r.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/fgetpwent_r.c new file mode 100644 index 00000000..8b935034 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/fgetpwent_r.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_fgetpwent_r +#include "pwd_grp.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/fgetspent.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/fgetspent.c new file mode 100644 index 00000000..b7c1ef24 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/fgetspent.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_fgetspent +#include "pwd_grp.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/fgetspent_r.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/fgetspent_r.c new file mode 100644 index 00000000..7196d80e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/fgetspent_r.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_fgetspent_r +#include "pwd_grp.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/getgrent.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/getgrent.c new file mode 100644 index 00000000..808e4e81 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/getgrent.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_getgrent +#include "pwd_grp.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/getgrent_r.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/getgrent_r.c new file mode 100644 index 00000000..5f0b7c29 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/getgrent_r.c @@ -0,0 +1,12 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +#ifdef __USE_GNU +# define L_getgrent_r +# include "pwd_grp.c" +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/getgrgid.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/getgrgid.c new file mode 100644 index 00000000..96ce9039 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/getgrgid.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_getgrgid +#include "pwd_grp.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/getgrgid_r.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/getgrgid_r.c new file mode 100644 index 00000000..a962f4ce --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/getgrgid_r.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_getgrgid_r +#include "pwd_grp.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/getgrnam.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/getgrnam.c new file mode 100644 index 00000000..3b47d9a9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/getgrnam.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_getgrnam +#include "pwd_grp.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/getgrnam_r.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/getgrnam_r.c new file mode 100644 index 00000000..592a66c4 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/getgrnam_r.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_getgrnam_r +#include "pwd_grp.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/getgrouplist.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/getgrouplist.c new file mode 100644 index 00000000..a4eba7db --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/getgrouplist.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_getgrouplist +#include "pwd_grp.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/getpw.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/getpw.c new file mode 100644 index 00000000..943da3f2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/getpw.c @@ -0,0 +1,12 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +#ifdef __USE_GNU +# define L_getpw +# include "pwd_grp.c" +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/getpwent.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/getpwent.c new file mode 100644 index 00000000..a617bc8b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/getpwent.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_getpwent +#include "pwd_grp.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/getpwent_r.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/getpwent_r.c new file mode 100644 index 00000000..9f00b05f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/getpwent_r.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_getpwent_r +#include "pwd_grp.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/getpwnam.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/getpwnam.c new file mode 100644 index 00000000..d00640b5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/getpwnam.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_getpwnam +#include "pwd_grp.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/getpwnam_r.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/getpwnam_r.c new file mode 100644 index 00000000..a4440e75 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/getpwnam_r.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_getpwnam_r +#include "pwd_grp.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/getpwuid.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/getpwuid.c new file mode 100644 index 00000000..16ac50f7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/getpwuid.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_getpwuid +#include "pwd_grp.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/getpwuid_r.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/getpwuid_r.c new file mode 100644 index 00000000..21d39ed7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/getpwuid_r.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_getpwuid_r +#include "pwd_grp.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/getspent.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/getspent.c new file mode 100644 index 00000000..5699b67d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/getspent.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_getspent +#include "pwd_grp.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/getspent_r.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/getspent_r.c new file mode 100644 index 00000000..da147a52 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/getspent_r.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_getspent_r +#include "pwd_grp.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/getspnam.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/getspnam.c new file mode 100644 index 00000000..19e40c73 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/getspnam.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_getspnam +#include "pwd_grp.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/getspnam_r.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/getspnam_r.c new file mode 100644 index 00000000..053b697e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/getspnam_r.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_getspnam_r +#include "pwd_grp.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/initgroups.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/initgroups.c new file mode 100644 index 00000000..d02be5e0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/initgroups.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_initgroups +#include "pwd_grp.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/lckpwdf.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/lckpwdf.c new file mode 100644 index 00000000..adbc616a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/lckpwdf.c @@ -0,0 +1,152 @@ +/* vi: set sw=4 ts=4: */ +/* Handle locking of password file. + Copyright (C) 1996,98,2000,02 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1996. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* How long to wait for getting the lock before returning with an error. */ +#define TIMEOUT 15 /* sec */ + +/* File descriptor for lock file. */ +static int lock_fd = -1; + +/* Prevent problems in multithreaded program by using mutex. */ +#include +__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_MUTEX_INITIALIZER); + +/* Prototypes for local functions. */ +static void noop_handler (int __sig); + + +int +lckpwdf (void) +{ + sigset_t saved_set; /* Saved set of caught signals. */ + struct sigaction saved_act; /* Saved signal action. */ + sigset_t new_set; /* New set of caught signals. */ + struct sigaction new_act; /* New signal action. */ + struct flock fl; /* Information struct for locking. */ + int result; + + if (lock_fd != -1) + /* Still locked by own process. */ + return -1; + + /* Prevent problems caused by multiple threads. */ + __UCLIBC_MUTEX_LOCK(mylock); + + lock_fd = open (_PATH_PASSWD, O_WRONLY | O_CLOEXEC); + if (lock_fd == -1) { + goto DONE; + } +#ifndef __ASSUME_O_CLOEXEC + /* Make sure file gets correctly closed when process finished. */ + fcntl (lock_fd, F_SETFD, FD_CLOEXEC); +#endif + + /* Now we have to get exclusive write access. Since multiple + process could try this we won't stop when it first fails. + Instead we set a timeout for the system call. Once the timer + expires it is likely that there are some problems which cannot be + resolved by waiting. (sa_flags have no SA_RESTART. Thus SIGALRM + will EINTR fcntl(F_SETLKW) + + It is important that we don't change the signal state. We must + restore the old signal behaviour. */ + memset (&new_act, '\0', sizeof (new_act)); + new_act.sa_handler = noop_handler; + __sigfillset (&new_act.sa_mask); + + /* Install new action handler for alarm and save old. + * This never fails in Linux. */ + sigaction (SIGALRM, &new_act, &saved_act); + + /* Now make sure the alarm signal is not blocked. */ + __sigemptyset (&new_set); + __sigaddset (&new_set, SIGALRM); + sigprocmask (SIG_UNBLOCK, &new_set, &saved_set); + + /* Start timer. If we cannot get the lock in the specified time we + get a signal. */ + alarm (TIMEOUT); + + /* Try to get the lock. */ + memset (&fl, '\0', sizeof (fl)); + if (F_WRLCK) + fl.l_type = F_WRLCK; + if (SEEK_SET) + fl.l_whence = SEEK_SET; + result = fcntl (lock_fd, F_SETLKW, &fl); + + /* Clear alarm. */ + alarm (0); + + sigprocmask (SIG_SETMASK, &saved_set, NULL); + sigaction (SIGALRM, &saved_act, NULL); + + if (result < 0) { + close(lock_fd); + lock_fd = -1; + } + +DONE: + __UCLIBC_MUTEX_UNLOCK(mylock); + return 0; /* TODO: return result? */ +} + + +int +ulckpwdf (void) +{ + int result; + + if (lock_fd == -1) + /* There is no lock set. */ + result = -1; + else + { + /* Prevent problems caused by multiple threads. */ + __UCLIBC_MUTEX_LOCK(mylock); + + result = close (lock_fd); + + /* Mark descriptor as unused. */ + lock_fd = -1; + + /* Clear mutex. */ + __UCLIBC_MUTEX_UNLOCK(mylock); + } + + return result; +} + + +static void +noop_handler (int sig attribute_unused) { + + /* We simply return which makes the `fcntl' call return with an error. */ +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/putgrent.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/putgrent.c new file mode 100644 index 00000000..20a6faf9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/putgrent.c @@ -0,0 +1,12 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +#ifdef __USE_GNU +# define L_putgrent +# include "pwd_grp.c" +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/putpwent.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/putpwent.c new file mode 100644 index 00000000..045462e9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/putpwent.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_putpwent +#include "pwd_grp.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/putspent.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/putspent.c new file mode 100644 index 00000000..d6b5b289 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/putspent.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_putspent +#include "pwd_grp.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/pwd_grp.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/pwd_grp.c new file mode 100644 index 00000000..f5c22f88 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/pwd_grp.c @@ -0,0 +1,1185 @@ +/* + * Copyright (C) 2003 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* Nov 6, 2003 Initial version. + * + * NOTE: This implementation is quite strict about requiring all + * field seperators. It also does not allow leading whitespace + * except when processing the numeric fields. glibc is more + * lenient. See the various glibc difference comments below. + * + * TODO: + * Move to dynamic allocation of (currently statically allocated) + * buffers; especially for the group-related functions since + * large group member lists will cause error returns. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef __UCLIBC_HAS_SHADOW__ +# include +#endif +#include + +/**********************************************************************/ +/* Prototypes for internal functions. */ + +extern int __parsepwent(void *pw, char *line) attribute_hidden; +extern int __parsegrent(void *gr, char *line) attribute_hidden; +extern int __parsespent(void *sp, char *line) attribute_hidden; + +extern int __pgsreader(int (*__parserfunc)(void *d, char *line), void *data, + char *__restrict line_buff, size_t buflen, FILE *f) attribute_hidden; + +extern gid_t* __getgrouplist_internal(const char *user, gid_t gid, int *ngroups) attribute_hidden; + +/**********************************************************************/ +/* For the various fget??ent_r funcs, return + * + * 0: success + * ENOENT: end-of-file encountered + * ERANGE: buflen too small + * other error values possible. See __pgsreader. + * + * Also, *result == resultbuf on success and NULL on failure. + * + * NOTE: glibc difference - For the ENOENT case, glibc also sets errno. + * We do not, as it really isn't an error if we reach the end-of-file. + * Doing so is analogous to having fgetc() set errno on EOF. + */ +/**********************************************************************/ +#ifdef L_fgetpwent_r + +#ifdef __USE_SVID +int fgetpwent_r(FILE *__restrict stream, struct passwd *__restrict resultbuf, + char *__restrict buffer, size_t buflen, + struct passwd **__restrict result) +{ + int rv; + + *result = NULL; + + if (!(rv = __pgsreader(__parsepwent, resultbuf, buffer, buflen, stream))) { + *result = resultbuf; + } + + return rv; +} +libc_hidden_def(fgetpwent_r) +#endif + +#endif +/**********************************************************************/ +#ifdef L_fgetgrent_r + +#ifdef __USE_SVID +int fgetgrent_r(FILE *__restrict stream, struct group *__restrict resultbuf, + char *__restrict buffer, size_t buflen, + struct group **__restrict result) +{ + int rv; + + *result = NULL; + + if (!(rv = __pgsreader(__parsegrent, resultbuf, buffer, buflen, stream))) { + *result = resultbuf; + } + + return rv; +} +libc_hidden_def(fgetgrent_r) +#endif + +#endif +/**********************************************************************/ +#ifdef L_fgetspent_r + +int fgetspent_r(FILE *__restrict stream, struct spwd *__restrict resultbuf, + char *__restrict buffer, size_t buflen, + struct spwd **__restrict result) +{ + int rv; + + *result = NULL; + + if (!(rv = __pgsreader(__parsespent, resultbuf, buffer, buflen, stream))) { + *result = resultbuf; + } + + return rv; +} +libc_hidden_def(fgetspent_r) + +#endif +/**********************************************************************/ +/* For the various fget??ent funcs, return NULL on failure and a + * pointer to the appropriate struct (statically allocated) on success. + */ +/**********************************************************************/ +#ifdef L_fgetpwent + +#ifdef __USE_SVID + +struct passwd *fgetpwent(FILE *stream) +{ + static char buffer[__UCLIBC_PWD_BUFFER_SIZE__]; + static struct passwd resultbuf; + struct passwd *result; + + fgetpwent_r(stream, &resultbuf, buffer, sizeof(buffer), &result); + return result; +} +#endif + +#endif +/**********************************************************************/ +#ifdef L_fgetgrent + +#ifdef __USE_SVID + +struct group *fgetgrent(FILE *stream) +{ + static char buffer[__UCLIBC_GRP_BUFFER_SIZE__]; + static struct group resultbuf; + struct group *result; + + fgetgrent_r(stream, &resultbuf, buffer, sizeof(buffer), &result); + return result; +} +#endif + +#endif +/**********************************************************************/ +#ifdef L_fgetspent + + +struct spwd *fgetspent(FILE *stream) +{ + static char buffer[__UCLIBC_PWD_BUFFER_SIZE__]; + static struct spwd resultbuf; + struct spwd *result; + + fgetspent_r(stream, &resultbuf, buffer, sizeof(buffer), &result); + return result; +} + +#endif +/**********************************************************************/ +#ifdef L_sgetspent_r + +int sgetspent_r(const char *string, struct spwd *result_buf, + char *buffer, size_t buflen, struct spwd **result) +{ + int rv = ERANGE; + + *result = NULL; + + if (buflen < __UCLIBC_PWD_BUFFER_SIZE__) { + DO_ERANGE: + __set_errno(rv); + goto DONE; + } + + if (string != buffer) { + if (strlen(string) >= buflen) { + goto DO_ERANGE; + } + strcpy(buffer, string); + } + + if (!(rv = __parsespent(result_buf, buffer))) { + *result = result_buf; + } + + DONE: + return rv; +} +libc_hidden_def(sgetspent_r) + +#endif +/**********************************************************************/ + +#ifdef GETXXKEY_R_FUNC +#error GETXXKEY_R_FUNC is already defined! +#endif + +#ifdef L_getpwnam_r +#define GETXXKEY_R_FUNC getpwnam_r +#define GETXXKEY_R_PARSER __parsepwent +#define GETXXKEY_R_ENTTYPE struct passwd +#define GETXXKEY_R_TEST(ENT) (!strcmp((ENT)->pw_name, key)) +#define DO_GETXXKEY_R_KEYTYPE const char *__restrict +#define DO_GETXXKEY_R_PATHNAME _PATH_PASSWD +#include "pwd_grp_internal.c" +#endif + +#ifdef L_getgrnam_r +#define GETXXKEY_R_FUNC getgrnam_r +#define GETXXKEY_R_PARSER __parsegrent +#define GETXXKEY_R_ENTTYPE struct group +#define GETXXKEY_R_TEST(ENT) (!strcmp((ENT)->gr_name, key)) +#define DO_GETXXKEY_R_KEYTYPE const char *__restrict +#define DO_GETXXKEY_R_PATHNAME _PATH_GROUP +#include "pwd_grp_internal.c" +#endif + +#ifdef L_getspnam_r +#define GETXXKEY_R_FUNC getspnam_r +#define GETXXKEY_R_PARSER __parsespent +#define GETXXKEY_R_ENTTYPE struct spwd +#define GETXXKEY_R_TEST(ENT) (!strcmp((ENT)->sp_namp, key)) +#define DO_GETXXKEY_R_KEYTYPE const char *__restrict +#define DO_GETXXKEY_R_PATHNAME _PATH_SHADOW +#include "pwd_grp_internal.c" +#endif + +#ifdef L_getpwuid_r +#define GETXXKEY_R_FUNC getpwuid_r +#define GETXXKEY_R_PARSER __parsepwent +#define GETXXKEY_R_ENTTYPE struct passwd +#define GETXXKEY_R_TEST(ENT) ((ENT)->pw_uid == key) +#define DO_GETXXKEY_R_KEYTYPE uid_t +#define DO_GETXXKEY_R_PATHNAME _PATH_PASSWD +#include "pwd_grp_internal.c" +#endif + +#ifdef L_getgrgid_r +#define GETXXKEY_R_FUNC getgrgid_r +#define GETXXKEY_R_PARSER __parsegrent +#define GETXXKEY_R_ENTTYPE struct group +#define GETXXKEY_R_TEST(ENT) ((ENT)->gr_gid == key) +#define DO_GETXXKEY_R_KEYTYPE gid_t +#define DO_GETXXKEY_R_PATHNAME _PATH_GROUP +#include "pwd_grp_internal.c" +#endif + +/**********************************************************************/ +#ifdef L_getpwuid + + +struct passwd *getpwuid(uid_t uid) +{ + static char buffer[__UCLIBC_PWD_BUFFER_SIZE__]; + static struct passwd resultbuf; + struct passwd *result; + + getpwuid_r(uid, &resultbuf, buffer, sizeof(buffer), &result); + return result; +} + +#endif +/**********************************************************************/ +#ifdef L_getgrgid + + +struct group *getgrgid(gid_t gid) +{ + static char buffer[__UCLIBC_GRP_BUFFER_SIZE__]; + static struct group resultbuf; + struct group *result; + + getgrgid_r(gid, &resultbuf, buffer, sizeof(buffer), &result); + return result; +} + +#endif +/**********************************************************************/ +#ifdef L_getspuid_r + +/* This function is non-standard and is currently not built. It seems + * to have been created as a reentrant version of the non-standard + * functions getspuid. Why getspuid was added, I do not know. */ + + +int getspuid_r(uid_t uid, struct spwd *__restrict resultbuf, + char *__restrict buffer, size_t buflen, + struct spwd **__restrict result) +{ + int rv; + struct passwd *pp; + struct passwd password; + char pwd_buff[__UCLIBC_PWD_BUFFER_SIZE__]; + + *result = NULL; + if (!(rv = getpwuid_r(uid, &password, pwd_buff, sizeof(pwd_buff), &pp))) { + rv = getspnam_r(password.pw_name, resultbuf, buffer, buflen, result); + } + + return rv; +} + +#endif +/**********************************************************************/ +#ifdef L_getspuid + +/* This function is non-standard and is currently not built. + * Why it was added, I do not know. */ + +struct spwd *getspuid(uid_t uid) +{ + static char buffer[__UCLIBC_PWD_BUFFER_SIZE__]; + static struct spwd resultbuf; + struct spwd *result; + + getspuid_r(uid, &resultbuf, buffer, sizeof(buffer), &result); + return result; +} + +#endif +/**********************************************************************/ +#ifdef L_getpwnam + + +struct passwd *getpwnam(const char *name) +{ + static char buffer[__UCLIBC_PWD_BUFFER_SIZE__]; + static struct passwd resultbuf; + struct passwd *result; + + getpwnam_r(name, &resultbuf, buffer, sizeof(buffer), &result); + return result; +} + +#endif +/**********************************************************************/ +#ifdef L_getgrnam + + +struct group *getgrnam(const char *name) +{ + static char buffer[__UCLIBC_GRP_BUFFER_SIZE__]; + static struct group resultbuf; + struct group *result; + + getgrnam_r(name, &resultbuf, buffer, sizeof(buffer), &result); + return result; +} + +#endif +/**********************************************************************/ +#ifdef L_getspnam + + +struct spwd *getspnam(const char *name) +{ + static char buffer[__UCLIBC_PWD_BUFFER_SIZE__]; + static struct spwd resultbuf; + struct spwd *result; + + getspnam_r(name, &resultbuf, buffer, sizeof(buffer), &result); + return result; +} + +#endif +/**********************************************************************/ +#ifdef L_getpw + + +int getpw(uid_t uid, char *buf) +{ + struct passwd resultbuf; + struct passwd *result; + char buffer[__UCLIBC_PWD_BUFFER_SIZE__]; + + if (!buf) { + __set_errno(EINVAL); + } else if (!getpwuid_r(uid, &resultbuf, buffer, sizeof(buffer), &result)) { + if (sprintf(buf, "%s:%s:%lu:%lu:%s:%s:%s\n", + resultbuf.pw_name, resultbuf.pw_passwd, + (unsigned long)(resultbuf.pw_uid), + (unsigned long)(resultbuf.pw_gid), + resultbuf.pw_gecos, resultbuf.pw_dir, + resultbuf.pw_shell) >= 0 + ) { + return 0; + } + } + + return -1; +} + +#endif +/**********************************************************************/ + +#ifdef L_getpwent_r +__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_MUTEX_INITIALIZER); + +static FILE *pwf /*= NULL*/; + +void setpwent(void) +{ + __UCLIBC_MUTEX_LOCK(mylock); + if (pwf) { + rewind(pwf); + } + __UCLIBC_MUTEX_UNLOCK(mylock); +} + +void endpwent(void) +{ + __UCLIBC_MUTEX_LOCK(mylock); + if (pwf) { + fclose(pwf); + pwf = NULL; + } + __UCLIBC_MUTEX_UNLOCK(mylock); +} + + +int getpwent_r(struct passwd *__restrict resultbuf, + char *__restrict buffer, size_t buflen, + struct passwd **__restrict result) +{ + int rv; + + __UCLIBC_MUTEX_LOCK(mylock); + + *result = NULL; /* In case of error... */ + + if (!pwf) { + if (!(pwf = fopen(_PATH_PASSWD, "r"))) { + rv = errno; + goto ERR; + } + __STDIO_SET_USER_LOCKING(pwf); + } + + if (!(rv = __pgsreader(__parsepwent, resultbuf, + buffer, buflen, pwf))) { + *result = resultbuf; + } + + ERR: + __UCLIBC_MUTEX_UNLOCK(mylock); + + return rv; +} +libc_hidden_def(getpwent_r) + +#endif +/**********************************************************************/ +#ifdef L_getgrent_r +__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_MUTEX_INITIALIZER); + +static FILE *grf /*= NULL*/; + +void setgrent(void) +{ + __UCLIBC_MUTEX_LOCK(mylock); + if (grf) { + rewind(grf); + } + __UCLIBC_MUTEX_UNLOCK(mylock); +} + +void endgrent(void) +{ + __UCLIBC_MUTEX_LOCK(mylock); + if (grf) { + fclose(grf); + grf = NULL; + } + __UCLIBC_MUTEX_UNLOCK(mylock); +} + +int getgrent_r(struct group *__restrict resultbuf, + char *__restrict buffer, size_t buflen, + struct group **__restrict result) +{ + int rv; + + __UCLIBC_MUTEX_LOCK(mylock); + + *result = NULL; /* In case of error... */ + + if (!grf) { + if (!(grf = fopen(_PATH_GROUP, "r"))) { + rv = errno; + goto ERR; + } + __STDIO_SET_USER_LOCKING(grf); + } + + if (!(rv = __pgsreader(__parsegrent, resultbuf, + buffer, buflen, grf))) { + *result = resultbuf; + } + + ERR: + __UCLIBC_MUTEX_UNLOCK(mylock); + + return rv; +} +libc_hidden_def(getgrent_r) + +#endif +/**********************************************************************/ +#ifdef L_getspent_r +__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_MUTEX_INITIALIZER); + +static FILE *spf /*= NULL*/; + +void setspent(void) +{ + __UCLIBC_MUTEX_LOCK(mylock); + if (spf) { + rewind(spf); + } + __UCLIBC_MUTEX_UNLOCK(mylock); +} + +void endspent(void) +{ + __UCLIBC_MUTEX_LOCK(mylock); + if (spf) { + fclose(spf); + spf = NULL; + } + __UCLIBC_MUTEX_UNLOCK(mylock); +} + +int getspent_r(struct spwd *resultbuf, char *buffer, + size_t buflen, struct spwd **result) +{ + int rv; + + __UCLIBC_MUTEX_LOCK(mylock); + + *result = NULL; /* In case of error... */ + + if (!spf) { + if (!(spf = fopen(_PATH_SHADOW, "r"))) { + rv = errno; + goto ERR; + } + __STDIO_SET_USER_LOCKING(spf); + } + + if (!(rv = __pgsreader(__parsespent, resultbuf, + buffer, buflen, spf))) { + *result = resultbuf; + } + + ERR: + __UCLIBC_MUTEX_UNLOCK(mylock); + + return rv; +} +libc_hidden_def(getspent_r) + +#endif +/**********************************************************************/ +#ifdef L_getpwent + + +struct passwd *getpwent(void) +{ + static char line_buff[__UCLIBC_PWD_BUFFER_SIZE__]; + static struct passwd pwd; + struct passwd *result; + + getpwent_r(&pwd, line_buff, sizeof(line_buff), &result); + return result; +} + +#endif +/**********************************************************************/ +#ifdef L_getgrent + + +struct group *getgrent(void) +{ + static char line_buff[__UCLIBC_GRP_BUFFER_SIZE__]; + static struct group gr; + struct group *result; + + getgrent_r(&gr, line_buff, sizeof(line_buff), &result); + return result; +} + +#endif +/**********************************************************************/ +#ifdef L_getspent + + +struct spwd *getspent(void) +{ + static char line_buff[__UCLIBC_PWD_BUFFER_SIZE__]; + static struct spwd spwd; + struct spwd *result; + + getspent_r(&spwd, line_buff, sizeof(line_buff), &result); + return result; +} + +#endif +/**********************************************************************/ +#ifdef L_sgetspent + + +struct spwd *sgetspent(const char *string) +{ + static char line_buff[__UCLIBC_PWD_BUFFER_SIZE__]; + static struct spwd spwd; + struct spwd *result; + + sgetspent_r(string, &spwd, line_buff, sizeof(line_buff), &result); + return result; +} + +#endif +/**********************************************************************/ +#ifdef L___getgrouplist_internal + +gid_t attribute_hidden *__getgrouplist_internal(const char *user, gid_t gid, int *ngroups) +{ + FILE *grfile; + gid_t *group_list; + int num_groups; + struct group group; + char buff[__UCLIBC_PWD_BUFFER_SIZE__]; + + *ngroups = num_groups = 1; + + /* We alloc space for 8 gids at a time. */ + group_list = malloc(8 * sizeof(group_list[0])); + if (!group_list) + return NULL; + + group_list[0] = gid; + grfile = fopen(_PATH_GROUP, "r"); + /* If /etc/group doesn't exist, we still return 1-element vector */ + if (!grfile) + return group_list; + + __STDIO_SET_USER_LOCKING(grfile); + + while (!__pgsreader(__parsegrent, &group, buff, sizeof(buff), grfile)) { + char **m; + + assert(group.gr_mem); /* Must have at least a NULL terminator. */ + if (group.gr_gid == gid) + continue; + for (m = group.gr_mem; *m; m++) { + if (strcmp(*m, user) != 0) + continue; + if (!(num_groups & 7)) { + gid_t *tmp = realloc(group_list, (num_groups+8) * sizeof(group_list[0])); + if (!tmp) + goto DO_CLOSE; + group_list = tmp; + } + group_list[num_groups++] = group.gr_gid; + break; + } + } + + DO_CLOSE: + fclose(grfile); + *ngroups = num_groups; + return group_list; +} + +#endif +/**********************************************************************/ +#ifdef L_getgrouplist + +#if defined __USE_BSD || defined __USE_GNU +int getgrouplist(const char *user, gid_t gid, gid_t *groups, int *ngroups) +{ + int sz = *ngroups; + gid_t *group_list = __getgrouplist_internal(user, gid, ngroups); + + if (!group_list) { + /* malloc failure - what shall we do? + * fail with ENOMEM? I bet users never check for that */ + /* *ngroups = 1; - already done by __getgrouplist_internal */ + if (sz) { + groups[0] = gid; + return 1; + } + return -1; + } + /* *ngroups is non-zero here */ + + if (sz > *ngroups) + sz = *ngroups; + if (sz) + memcpy(groups, group_list, sz * sizeof(group_list[0])); + free(group_list); + if (sz < *ngroups) + return -1; + return sz; +} +#endif + +#endif +/**********************************************************************/ +#ifdef L_initgroups + +#ifdef __USE_BSD + +int initgroups(const char *user, gid_t gid) +{ + int rv; + int num_groups = ((unsigned)~0) >> 1; /* INT_MAX */ + gid_t *group_list = __getgrouplist_internal(user, gid, &num_groups); + if (!group_list) + return -1; + rv = setgroups(num_groups, group_list); + free(group_list); + return rv; +} +#endif + +#endif +/**********************************************************************/ +#ifdef L_putpwent + +#ifdef __USE_SVID +int putpwent(const struct passwd *__restrict p, FILE *__restrict f) +{ + int rv = -1; + + if (!p || !f) { + __set_errno(EINVAL); + } else { + /* No extra thread locking is needed above what fprintf does. */ + if (fprintf(f, "%s:%s:%lu:%lu:%s:%s:%s\n", + p->pw_name, p->pw_passwd, + (unsigned long)(p->pw_uid), + (unsigned long)(p->pw_gid), + p->pw_gecos, p->pw_dir, p->pw_shell) >= 0 + ) { + rv = 0; + } + } + + return rv; +} +#endif + +#endif +/**********************************************************************/ +#ifdef L_putgrent + +int putgrent(const struct group *__restrict p, FILE *__restrict f) +{ + static const char format[] = ",%s"; + char **m; + const char *fmt; + int rv = -1; + __STDIO_AUTO_THREADLOCK_VAR; + + if (!p || !f) { /* Sigh... glibc checks. */ + __set_errno(EINVAL); + } else { + __STDIO_AUTO_THREADLOCK(f); + + if (fprintf(f, "%s:%s:%lu:", + p->gr_name, p->gr_passwd, + (unsigned long)(p->gr_gid)) >= 0 + ) { + + fmt = format + 1; + + assert(p->gr_mem); + m = p->gr_mem; + + do { + if (!*m) { + if (__fputc_unlocked('\n', f) >= 0) { + rv = 0; + } + break; + } + if (fprintf(f, fmt, *m) < 0) { + break; + } + ++m; + fmt = format; + } while (1); + + } + + __STDIO_AUTO_THREADUNLOCK(f); + } + + return rv; +} + +#endif +/**********************************************************************/ +#ifdef L_putspent + +static const unsigned char _sp_off[] = { + offsetof(struct spwd, sp_lstchg), /* 2 - not a char ptr */ + offsetof(struct spwd, sp_min), /* 3 - not a char ptr */ + offsetof(struct spwd, sp_max), /* 4 - not a char ptr */ + offsetof(struct spwd, sp_warn), /* 5 - not a char ptr */ + offsetof(struct spwd, sp_inact), /* 6 - not a char ptr */ + offsetof(struct spwd, sp_expire), /* 7 - not a char ptr */ +}; + +int putspent(const struct spwd *p, FILE *stream) +{ + static const char ld_format[] = "%ld:"; + const char *f; + long int x; + size_t i; + int rv = -1; + __STDIO_AUTO_THREADLOCK_VAR; + + /* Unlike putpwent and putgrent, glibc does not check the args. */ + + __STDIO_AUTO_THREADLOCK(stream); + + if (fprintf(stream, "%s:%s:", p->sp_namp, + (p->sp_pwdp ? p->sp_pwdp : "")) < 0 + ) { + goto DO_UNLOCK; + } + + for (i=0 ; i < sizeof(_sp_off) ; i++) { + f = ld_format; + if ((x = *(const long int *)(((const char *) p) + _sp_off[i])) == -1) { + f += 3; + } + if (fprintf(stream, f, x) < 0) { + goto DO_UNLOCK; + } + } + + if ((p->sp_flag != ~0UL) && (fprintf(stream, "%lu", p->sp_flag) < 0)) { + goto DO_UNLOCK; + } + + if (__fputc_unlocked('\n', stream) > 0) { + rv = 0; + } + + DO_UNLOCK: + __STDIO_AUTO_THREADUNLOCK(stream); + + return rv; +} + +#endif +/**********************************************************************/ +/* Internal uClibc functions. */ +/**********************************************************************/ +#ifdef L___parsepwent + +static const unsigned char pw_off[] = { + offsetof(struct passwd, pw_name), /* 0 */ + offsetof(struct passwd, pw_passwd), /* 1 */ + offsetof(struct passwd, pw_uid), /* 2 - not a char ptr */ + offsetof(struct passwd, pw_gid), /* 3 - not a char ptr */ + offsetof(struct passwd, pw_gecos), /* 4 */ + offsetof(struct passwd, pw_dir), /* 5 */ + offsetof(struct passwd, pw_shell) /* 6 */ +}; + +int attribute_hidden __parsepwent(void *data, char *line) +{ + char *endptr; + char *p; + int i; + + i = 0; + do { + p = ((char *) ((struct passwd *) data)) + pw_off[i]; + + if ((i & 6) ^ 2) { /* i!=2 and i!=3 */ + *((char **) p) = line; + if (i==6) { + return 0; + } + /* NOTE: glibc difference - glibc allows omission of + * ':' seperators after the gid field if all remaining + * entries are empty. We require all separators. */ + if (!(line = strchr(line, ':'))) { + break; + } + } else { + unsigned long t = strtoul(line, &endptr, 10); + /* Make sure we had at least one digit, and that the + * failing char is the next field seperator ':'. See + * glibc difference note above. */ + /* TODO: Also check for leading whitespace? */ + if ((endptr == line) || (*endptr != ':')) { + break; + } + line = endptr; + if (i & 1) { /* i == 3 -- gid */ + *((gid_t *) p) = t; + } else { /* i == 2 -- uid */ + *((uid_t *) p) = t; + } + } + + *line++ = 0; + ++i; + } while (1); + + return -1; +} + +#endif +/**********************************************************************/ +#ifdef L___parsegrent + +static const unsigned char gr_off[] = { + offsetof(struct group, gr_name), /* 0 */ + offsetof(struct group, gr_passwd), /* 1 */ + offsetof(struct group, gr_gid) /* 2 - not a char ptr */ +}; + +int attribute_hidden __parsegrent(void *data, char *line) +{ + char *endptr; + char *p; + int i; + char **members; + char *end_of_buf; + + end_of_buf = ((struct group *) data)->gr_name; /* Evil hack! */ + i = 0; + do { + p = ((char *) ((struct group *) data)) + gr_off[i]; + + if (i < 2) { + *((char **) p) = line; + if (!(line = strchr(line, ':'))) { + break; + } + *line++ = 0; + ++i; + } else { + *((gid_t *) p) = strtoul(line, &endptr, 10); + + /* NOTE: glibc difference - glibc allows omission of the + * trailing colon when there is no member list. We treat + * this as an error. */ + + /* Make sure we had at least one digit, and that the + * failing char is the next field seperator ':'. See + * glibc difference note above. */ + if ((endptr == line) || (*endptr != ':')) { + break; + } + + i = 1; /* Count terminating NULL ptr. */ + p = endptr; + + if (p[1]) { /* We have a member list to process. */ + /* Overwrite the last ':' with a ',' before counting. + * This allows us to test for initial ',' and adds + * one ',' so that the ',' count equals the member + * count. */ + *p = ','; + do { + /* NOTE: glibc difference - glibc allows and trims leading + * (but not trailing) space. We treat this as an error. */ + /* NOTE: glibc difference - glibc allows consecutive and + * trailing commas, and ignores "empty string" users. We + * treat this as an error. */ + if (*p == ',') { + ++i; + *p = 0; /* nul-terminate each member string. */ + if (!*++p || (*p == ',') || isspace(*p)) { + goto ERR; + } + } + } while (*++p); + } + + /* Now align (p+1), rounding up. */ + /* Assumes sizeof(char **) is a power of 2. */ + members = (char **)( (((intptr_t) p) + sizeof(char **)) + & ~((intptr_t)(sizeof(char **) - 1)) ); + + if (((char *)(members + i)) > end_of_buf) { /* No space. */ + break; + } + + ((struct group *) data)->gr_mem = members; + + if (--i) { + p = endptr; /* Pointing to char prior to first member. */ + do { + *members++ = ++p; + if (!--i) break; + while (*++p) {} + } while (1); + } + *members = NULL; + + return 0; + } + } while (1); + + ERR: + return -1; +} + +#endif +/**********************************************************************/ +#ifdef L___parsespent + +static const unsigned char sp_off[] = { + offsetof(struct spwd, sp_namp), /* 0 */ + offsetof(struct spwd, sp_pwdp), /* 1 */ + offsetof(struct spwd, sp_lstchg), /* 2 - not a char ptr */ + offsetof(struct spwd, sp_min), /* 3 - not a char ptr */ + offsetof(struct spwd, sp_max), /* 4 - not a char ptr */ + offsetof(struct spwd, sp_warn), /* 5 - not a char ptr */ + offsetof(struct spwd, sp_inact), /* 6 - not a char ptr */ + offsetof(struct spwd, sp_expire), /* 7 - not a char ptr */ + offsetof(struct spwd, sp_flag) /* 8 - not a char ptr */ +}; + +int attribute_hidden __parsespent(void *data, char * line) +{ + char *endptr; + char *p; + int i; + + i = 0; + do { + p = ((char *) ((struct spwd *) data)) + sp_off[i]; + if (i < 2) { + *((char **) p) = line; + if (!(line = strchr(line, ':'))) { + break; + } + } else { +#if 0 + if (i==5) { /* Support for old format. */ + while (isspace(*line)) ++line; /* glibc eats space here. */ + if (!*line) { + ((struct spwd *) data)->sp_warn = -1; + ((struct spwd *) data)->sp_inact = -1; + ((struct spwd *) data)->sp_expire = -1; + ((struct spwd *) data)->sp_flag = ~0UL; + return 0; + } + } +#endif + + *((long *) p) = (long) strtoul(line, &endptr, 10); + + if (endptr == line) { + *((long *) p) = ((i != 8) ? -1L : ((long)(~0UL))); + } + + line = endptr; + + if (i == 8) { + if (!*endptr) { + return 0; + } + break; + } + + if (*endptr != ':') { + break; + } + + } + + *line++ = 0; + ++i; + } while (1); + + return EINVAL; +} + +#endif +/**********************************************************************/ +#ifdef L___pgsreader + +/* Reads until if EOF, or until if finds a line which fits in the buffer + * and for which the parser function succeeds. + * + * Returns 0 on success and ENOENT for end-of-file (glibc concession). + */ + +int attribute_hidden __pgsreader(int (*__parserfunc)(void *d, char *line), void *data, + char *__restrict line_buff, size_t buflen, FILE *f) +{ + size_t line_len; + int skip; + int rv = ERANGE; + __STDIO_AUTO_THREADLOCK_VAR; + + if (buflen < __UCLIBC_PWD_BUFFER_SIZE__) { + __set_errno(rv); + } else { + __STDIO_AUTO_THREADLOCK(f); + + skip = 0; + do { + if (!fgets_unlocked(line_buff, buflen, f)) { + if (feof_unlocked(f)) { + rv = ENOENT; + } + break; + } + + line_len = strlen(line_buff) - 1; /* strlen() must be > 0. */ + if (line_buff[line_len] == '\n') { + line_buff[line_len] = 0; + } else if (line_len + 2 == buflen) { /* line too long */ + ++skip; + continue; + } + + if (skip) { + --skip; + continue; + } + + /* NOTE: glibc difference - glibc strips leading whitespace from + * records. We do not allow leading whitespace. */ + + /* Skip empty lines, comment lines, and lines with leading + * whitespace. */ + if (*line_buff && (*line_buff != '#') && !isspace(*line_buff)) { + if (__parserfunc == __parsegrent) { /* Do evil group hack. */ + /* The group entry parsing function needs to know where + * the end of the buffer is so that it can construct the + * group member ptr table. */ + ((struct group *) data)->gr_name = line_buff + buflen; + } + + if (!__parserfunc(data, line_buff)) { + rv = 0; + break; + } + } + } while (1); + + __STDIO_AUTO_THREADUNLOCK(f); + } + + return rv; +} + +#endif +/**********************************************************************/ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/pwd_grp_internal.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/pwd_grp_internal.c new file mode 100644 index 00000000..c8974789 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/pwd_grp_internal.c @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2003 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* Nov 6, 2003 Initial version. + * + * NOTE: This implementation is quite strict about requiring all + * field seperators. It also does not allow leading whitespace + * except when processing the numeric fields. glibc is more + * lenient. See the various glibc difference comments below. + * + * TODO: + * Move to dynamic allocation of (currently statically allocated) + * buffers; especially for the group-related functions since + * large group member lists will cause error returns. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef __UCLIBC_HAS_SHADOW__ +#include +#endif +#ifdef __UCLIBC_HAS_THREADS__ +#include +#endif + +/**********************************************************************/ +/* Sizes for statically allocated buffers. */ + +/* If you change these values, also change _SC_GETPW_R_SIZE_MAX and + * _SC_GETGR_R_SIZE_MAX in libc/unistd/sysconf.c to match */ +#define PWD_BUFFER_SIZE 256 +#define GRP_BUFFER_SIZE 256 + +/**********************************************************************/ +/* Prototypes for internal functions. */ + +#ifndef GETXXKEY_R_FUNC +#error GETXXKEY_R_FUNC is not defined! +#endif +/**********************************************************************/ +#ifdef GETXXKEY_R_FUNC + +libc_hidden_proto(GETXXKEY_R_FUNC) +int GETXXKEY_R_FUNC(DO_GETXXKEY_R_KEYTYPE key, + GETXXKEY_R_ENTTYPE *__restrict resultbuf, + char *__restrict buffer, size_t buflen, + GETXXKEY_R_ENTTYPE **__restrict result) +{ + FILE *stream; + int rv; + + *result = NULL; + + if (!(stream = fopen(DO_GETXXKEY_R_PATHNAME, "r"))) { + rv = errno; + } else { + __STDIO_SET_USER_LOCKING(stream); + do { + if (!(rv = __pgsreader(GETXXKEY_R_PARSER, resultbuf, + buffer, buflen, stream)) + ) { + if (GETXXKEY_R_TEST(resultbuf)) { /* Found key? */ + *result = resultbuf; + break; + } + } else { + if (rv == ENOENT) { /* end-of-file encountered. */ + rv = 0; + } + break; + } + } while (1); + fclose(stream); + } + + return rv; +} +libc_hidden_def(GETXXKEY_R_FUNC) + +#endif +/**********************************************************************/ +#undef GETXXKEY_R_FUNC_HIDDEN +#undef GETXXKEY_R_FUNC +#undef GETXXKEY_R_PARSER +#undef GETXXKEY_R_ENTTYPE +#undef GETXXKEY_R_TEST +#undef DO_GETXXKEY_R_KEYTYPE +#undef DO_GETXXKEY_R_PATHNAME diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/sgetspent.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/sgetspent.c new file mode 100644 index 00000000..877a2478 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/sgetspent.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_sgetspent +#include "pwd_grp.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/sgetspent_r.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/sgetspent_r.c new file mode 100644 index 00000000..131e0bd3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/pwd_grp/sgetspent_r.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_sgetspent_r +#include "pwd_grp.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/Makefile new file mode 100644 index 00000000..11f362a5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../ +top_builddir=../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/Makefile.in new file mode 100644 index 00000000..a7e30787 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/Makefile.in @@ -0,0 +1,38 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +subdirs += libc/signal + +CSRC-y := allocrtsig.c killpg.c raise.c sigaction.c sigaddset.c sigandset.c \ + sigblock.c sigdelset.c sigempty.c sigfillset.c siggetmask.c \ + sigisempty.c sigismem.c sigjmp.c signal.c \ + sigorset.c sigpause.c sigsetmask.c sigsetops.c sigwait.c +CSRC-$(UCLIBC_HAS_OBSOLETE_BSD_SIGNAL) += \ + sighold.c sigignore.c sigrelse.c sigset.c +CSRC-$(UCLIBC_HAS_OBSOLETE_SYSV_SIGNAL) += sysv_signal.c +CSRC-$(UCLIBC_SUSV4_LEGACY) += sigintr.c + +ifeq ($(UCLIBC_HAS_THREADS_NATIVE),y) +CSRC-y:=$(filter-out raise.c sigaction.c,$(CSRC-y)) +endif + +ifneq ($(strip $(ARCH_OBJS)),) +CSRC-y := $(filter-out $(notdir $(ARCH_OBJS:.o=.c)),$(CSRC-y)) +endif + +SIGNAL_DIR := $(top_srcdir)libc/signal +SIGNAL_OUT := $(top_builddir)libc/signal + +SIGNAL_SRC := $(patsubst %.c,$(SIGNAL_DIR)/%.c,$(CSRC-y)) +SIGNAL_OBJ := $(patsubst %.c,$(SIGNAL_OUT)/%.o,$(CSRC-y)) + +libc-y += $(SIGNAL_OBJ) + +objclean-y += CLEAN_libc/signal + +CLEAN_libc/signal: + $(do_rm) $(addprefix $(SIGNAL_OUT)/*., o os) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/allocrtsig.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/allocrtsig.c new file mode 100644 index 00000000..3c7d6211 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/allocrtsig.c @@ -0,0 +1,66 @@ +/* Handle real-time signal allocation. + Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + +/* Only enable rt signals when it is supported at compile time */ +#ifndef __NR_rt_sigaction +/* In these variables we keep track of the used variables. If the + platform does not support any real-time signals we will define the + values to some unreasonable value which will signal failing of all + the functions below. */ +static int current_rtmin = -1; +static int current_rtmax = -1; +#else +# ifdef __UCLIBC_HAS_THREADS_NATIVE__ +static int current_rtmin = __SIGRTMIN + 2; +# else +static int current_rtmin = __SIGRTMIN; +# endif +static int current_rtmax = __SIGRTMAX; +#endif + +/* Return number of available real-time signal with highest priority. */ +int __libc_current_sigrtmin (void) +{ + return current_rtmin; +} + +/* Return number of available real-time signal with lowest priority. */ +int __libc_current_sigrtmax (void) +{ + return current_rtmax; +} + +/* Allocate real-time signal with highest/lowest available + priority. Please note that we don't use a lock since we assume + this function to be called at program start. */ +int __libc_allocate_rtsig (int high); +int __libc_allocate_rtsig (int high) +{ + if (current_rtmin == -1 || current_rtmin > current_rtmax) + /* We don't have anymore signal available. */ + return -1; + + return high ? current_rtmin++ : current_rtmax--; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/killpg.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/killpg.c new file mode 100644 index 00000000..c2dc713d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/killpg.c @@ -0,0 +1,36 @@ +/* Copyright (C) 1991, 1993, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + + +/* Send SIG to all processes in process group PGRP. + If PGRP is zero, send SIG to all processes in + the current process's process group. */ +int +killpg (__pid_t pgrp, int sig) +{ + if (pgrp < 0) + { + __set_errno (EINVAL); + return -1; + } + + return kill (- pgrp, sig); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/raise.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/raise.c new file mode 100644 index 00000000..aed9b46d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/raise.c @@ -0,0 +1,14 @@ +/* Copyright (C) 1995,1996 Robert de Bath + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include + +int raise(int signo) +{ + return kill(getpid(), signo); +} +libc_hidden_def(raise) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sigaction.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sigaction.c new file mode 100644 index 00000000..ae2e4b91 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sigaction.c @@ -0,0 +1,87 @@ +/* Copyright (C) 1997-2000,2002,2003,2005,2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include + +#include + +#ifndef LIBC_SIGACTION +extern __typeof(sigaction) __libc_sigaction; +#endif + + +#if defined __NR_rt_sigaction + +/* If ACT is not NULL, change the action for SIG to *ACT. + If OACT is not NULL, put the old action for SIG in *OACT. */ +int +__libc_sigaction(int sig, const struct sigaction *act, struct sigaction *oact) +{ + /* NB: kernel (as of 2.6.25) will return EINVAL + * if sizeof(act->sa_mask) does not match kernel's sizeof(sigset_t). + * Try to catch this problem at uclibc build time: */ + struct BUG_sigset_size { + int BUG_sigset_size + [sizeof(act->sa_mask) == _NSIG / 8 ? 1 : -1]; + }; + return __syscall_rt_sigaction(sig, act, oact, sizeof(act->sa_mask)); +} + +#else + +/* If ACT is not NULL, change the action for SIG to *ACT. + If OACT is not NULL, put the old action for SIG in *OACT. */ +int +__libc_sigaction(int sig, const struct sigaction *act, struct sigaction *oact) +{ + int result; + struct old_kernel_sigaction kact, koact; + + if (act) { + kact.k_sa_handler = act->sa_handler; + kact.sa_mask = act->sa_mask.__val[0]; + kact.sa_flags = act->sa_flags; +# ifdef HAVE_SA_RESTORER + kact.sa_restorer = act->sa_restorer; +# endif + } + result = __syscall_sigaction(sig, + act ? &kact : NULL, + oact ? &koact : NULL); + if (oact && result >= 0) { + oact->sa_handler = koact.k_sa_handler; + oact->sa_mask.__val[0] = koact.sa_mask; + oact->sa_flags = koact.sa_flags; +# ifdef HAVE_SA_RESTORER + oact->sa_restorer = koact.sa_restorer; +# endif + } + return result; +} + +#endif + + +#ifndef LIBC_SIGACTION +weak_alias(__libc_sigaction,sigaction) +libc_hidden_weak(sigaction) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sigaddset.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sigaddset.c new file mode 100644 index 00000000..7577d37c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sigaddset.c @@ -0,0 +1,33 @@ +/* Copyright (C) 1991, 1996, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "sigsetops.h" + +/* Add SIGNO to SET. */ +int +sigaddset (sigset_t *set, int signo) +{ + if (set == NULL || signo <= 0 || signo >= NSIG) + { + __set_errno (EINVAL); + return -1; + } + + return __sigaddset (set, signo); +} +libc_hidden_def(sigaddset) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sigandset.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sigandset.c new file mode 100644 index 00000000..dcc37dab --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sigandset.c @@ -0,0 +1,34 @@ +/* Copyright (C) 1991, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#define __need_NULL +#include + +/* Combine sets LEFT and RIGHT by logical AND and place result in DEST. */ +int sigandset (sigset_t *dest, const sigset_t *left, const sigset_t *right) +{ + if (dest == NULL || left == NULL || right == NULL) + { + __set_errno (EINVAL); + return -1; + } + + return __sigandset (dest, left, right); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sigblock.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sigblock.c new file mode 100644 index 00000000..ad3acb0b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sigblock.c @@ -0,0 +1,34 @@ +/* Copyright (C) 1991, 1994-1998, 2001-2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define __UCLIBC_HIDE_DEPRECATED__ +#include +#include + +#include "sigset-cvt-mask.h" + +/* Block signals in MASK, returning the old mask. */ +int sigblock (int mask) +{ + sigset_t set, oset; + + sigset_set_old_mask (&set, mask); + sigprocmask (SIG_BLOCK, &set, &oset); /* can't fail */ + return sigset_get_old_mask (&oset); +} +libc_hidden_def(sigblock) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sigdelset.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sigdelset.c new file mode 100644 index 00000000..ff30303e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sigdelset.c @@ -0,0 +1,32 @@ +/* Copyright (C) 1991, 1996, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "sigsetops.h" + +/* Add SIGNO to SET. */ +int sigdelset (sigset_t *set, int signo) +{ + if (set == NULL || signo <= 0 || signo >= NSIG) + { + __set_errno (EINVAL); + return -1; + } + + return __sigdelset (set, signo); +} +libc_hidden_def(sigdelset) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sigempty.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sigempty.c new file mode 100644 index 00000000..b4f180bb --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sigempty.c @@ -0,0 +1,39 @@ +/* Copyright (C) 1991,96,97,2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + + +/* Clear all signals from SET. */ +int sigemptyset (sigset_t *set) +{ +#if 0 /* is it really required by standards?! */ + if (set == NULL) + { + __set_errno (EINVAL); + return -1; + } +#endif + + __sigemptyset (set); + + return 0; +} +libc_hidden_def(sigemptyset) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sigfillset.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sigfillset.c new file mode 100644 index 00000000..951e76b7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sigfillset.c @@ -0,0 +1,49 @@ +/* Copyright (C) 1991,96,97,2002,2003,2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + + +/* Set all signals in SET. */ +int +sigfillset (sigset_t *set) +{ +#if 0 /* is it really required by standards?! */ + if (set == NULL) + { + __set_errno (EINVAL); + return -1; + } +#endif + + __sigfillset (set); + + /* If the implementation uses a cancellation signal don't set the bit. */ +#ifdef SIGCANCEL + __sigdelset (set, SIGCANCEL); +#endif + /* Likewise for the signal to implement setxid. */ +#ifdef SIGSETXID + __sigdelset (set, SIGSETXID); +#endif + + return 0; +} +libc_hidden_def(sigfillset) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/siggetmask.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/siggetmask.c new file mode 100644 index 00000000..3992a7a0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/siggetmask.c @@ -0,0 +1,31 @@ +/* siggetmask -- useless alias for `sigblock (0)' for old Linux compatibility. + Copyright (C) 1996 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define __UCLIBC_HIDE_DEPRECATED__ +#include + + +int +siggetmask (void) +{ + return sigblock (0); +} + +link_warning (siggetmask, + "warning: `siggetmask' is obsolete; `sigprocmask' is best") diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sighold.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sighold.c new file mode 100644 index 00000000..6a2e718c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sighold.c @@ -0,0 +1,39 @@ +/* Add SIG to the calling process' signal mask. + Copyright (C) 1998, 2000, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define __need_NULL +#include +#include + + +int sighold (int sig) +{ + sigset_t set; + + /* Retrieve current signal set. */ + sigprocmask (SIG_SETMASK, NULL, &set); /* can't fail */ + + /* Bound-check sig, add it to the set. */ + if (sigaddset (&set, sig) < 0) + return -1; + + /* Set the new mask. */ + return sigprocmask (SIG_SETMASK, &set, NULL); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sigignore.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sigignore.c new file mode 100644 index 00000000..a74c1052 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sigignore.c @@ -0,0 +1,36 @@ +/* Set the disposition of SIG to SIG_IGN. + Copyright (C) 1998, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#define __need_NULL +#include +#include +#include /* For the real memset prototype. */ + + +int sigignore (int sig) +{ + struct sigaction act; + + memset(&act, 0, sizeof(act)); + act.sa_handler = SIG_IGN; + + return sigaction (sig, &act, NULL); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sigintr.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sigintr.c new file mode 100644 index 00000000..10567e93 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sigintr.c @@ -0,0 +1,56 @@ +/* Copyright (C) 1992, 1994, 1996, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + + +/* If INTERRUPT is nonzero, make signal SIG interrupt system calls + (causing them to fail with EINTR); if INTERRUPT is zero, make system + calls be restarted after signal SIG. */ +#ifdef SA_RESTART +extern sigset_t _sigintr attribute_hidden; /* Defined in signal.c. */ +#endif + +int siginterrupt (int sig, int interrupt) +{ +#ifdef SA_RESTART + struct sigaction action; + + /* Fails if sig is bad. */ + if (sigaction (sig, NULL, &action) < 0) + return -1; + + if (interrupt) + { + __sigaddset (&_sigintr, sig); + action.sa_flags &= ~SA_RESTART; + } + else + { + __sigdelset (&_sigintr, sig); + action.sa_flags |= SA_RESTART; + } + + return sigaction (sig, &action, NULL); +#else + __set_errno (ENOSYS); + return -1; +#endif +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sigisempty.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sigisempty.c new file mode 100644 index 00000000..a25bb473 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sigisempty.c @@ -0,0 +1,34 @@ +/* Copyright (C) 1991, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#define __need_NULL +#include + +/* Test whether SET is empty. */ +int sigisemptyset (const sigset_t *set) +{ + if (set == NULL) + { + __set_errno (EINVAL); + return -1; + } + + return __sigisemptyset (set); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sigismem.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sigismem.c new file mode 100644 index 00000000..b546f626 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sigismem.c @@ -0,0 +1,31 @@ +/* Copyright (C) 1991,96,2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "sigsetops.h" + +/* Return 1 if SIGNO is in SET, 0 if not. */ +int sigismember (const sigset_t *set, int signo) +{ + if (set == NULL || signo <= 0 || signo >= NSIG) + { + __set_errno (EINVAL); + return -1; + } + + return __sigismember (set, signo); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sigjmp.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sigjmp.c new file mode 100644 index 00000000..0dcbc8b0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sigjmp.c @@ -0,0 +1,36 @@ +/* Copyright (C) 1992, 1994, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + + +/* This function is called by the `sigsetjmp' macro + before doing a `__setjmp' on ENV[0].__jmpbuf. + Always return zero. */ + +int __sigjmp_save (sigjmp_buf env, int savemask) attribute_hidden; +int __sigjmp_save (sigjmp_buf env, int savemask) +{ + env[0].__mask_was_saved = (savemask && + sigprocmask (SIG_BLOCK, NULL, &env[0].__saved_mask) == 0); + + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/signal.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/signal.c new file mode 100644 index 00000000..644617c1 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/signal.c @@ -0,0 +1,54 @@ +/* BSD-like signal function. + Copyright (C) 1991,1992,1996,1997,2000,2002,2005 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include /* For the real memset prototype. */ + +sigset_t _sigintr attribute_hidden; /* Set by siginterrupt. */ + +/* Set the handler for the signal SIG to HANDLER, + returning the old handler, or SIG_ERR on error. */ +__sighandler_t +signal (int sig, __sighandler_t handler) +{ + struct sigaction act, oact; + + /* Check signal extents to protect __sigismember. */ + if (handler == SIG_ERR || sig < 1 || sig >= NSIG) + { + __set_errno (EINVAL); + return SIG_ERR; + } + + act.sa_handler = handler; + __sigemptyset (&act.sa_mask); + __sigaddset (&act.sa_mask, sig); + act.sa_flags = __sigismember (&_sigintr, sig) ? 0 : SA_RESTART; + /* In Linux (as of 2.6.25), fails only if sig is SIGKILL or SIGSTOP */ + if (sigaction (sig, &act, &oact) < 0) + return SIG_ERR; + + return oact.sa_handler; +} +libc_hidden_def(signal) +#ifdef __UCLIBC_SUSV3_LEGACY__ +strong_alias(signal,bsd_signal) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sigorset.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sigorset.c new file mode 100644 index 00000000..3588cc48 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sigorset.c @@ -0,0 +1,34 @@ +/* Copyright (C) 1991, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#define __need_NULL +#include + +/* Combine sets LEFT and RIGHT by logical OR and place result in DEST. */ +int sigorset (sigset_t *dest, const sigset_t *left, const sigset_t *right) +{ + if (dest == NULL || left == NULL || right == NULL) + { + __set_errno (EINVAL); + return -1; + } + + return __sigorset (dest, left, right); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sigpause.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sigpause.c new file mode 100644 index 00000000..0856ba2e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sigpause.c @@ -0,0 +1,77 @@ +/* Copyright (C) 1991,92,94-98,2000,2002,2003,2004 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define __UCLIBC_HIDE_DEPRECATED__ +/* psm: need the BSD version of sigpause here */ +#include +#define __FAVOR_BSD +#include +#include /* For NULL. */ +#ifdef __UCLIBC_HAS_THREADS_NATIVE__ +#include +#endif + +#include "sigset-cvt-mask.h" + +/* Set the mask of blocked signals to MASK, + wait for a signal to arrive, and then restore the mask. */ +int __sigpause (int sig_or_mask, int is_sig) +{ + sigset_t set; + + if (is_sig) + { + /* The modern X/Open implementation is requested. */ + sigprocmask (SIG_BLOCK, NULL, &set); + /* Bound-check sig_or_mask, remove it from the set. */ + if (sigdelset (&set, sig_or_mask) < 0) + return -1; + } + else + sigset_set_old_mask (&set, sig_or_mask); + + /* Note the sigpause() is a cancellation point. But since we call + sigsuspend() which itself is a cancellation point we do not have + to do anything here. */ + return sigsuspend (&set); +} +libc_hidden_def(__sigpause) + +#undef sigpause + +/* We have to provide a default version of this function since the + standards demand it. The version which is a bit more reasonable is + the BSD version. So make this the default. */ +int sigpause (int mask) +{ +#ifdef __UCLIBC_HAS_THREADS_NATIVE__ + if (SINGLE_THREAD_P) + return __sigpause (mask, 0); + + int oldtype = LIBC_CANCEL_ASYNC (); + + int result = __sigpause (mask, 0); + + LIBC_CANCEL_RESET (oldtype); + + return result; +#else + return __sigpause (mask, 0); +#endif +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sigrelse.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sigrelse.c new file mode 100644 index 00000000..07e7fddf --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sigrelse.c @@ -0,0 +1,39 @@ +/* Remove SIG from the calling process' signal mask. + Copyright (C) 1998, 2000, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define __need_NULL +#include +#include + + +int sigrelse (int sig) +{ + sigset_t set; + + /* Retrieve current signal set. */ + sigprocmask (SIG_SETMASK, NULL, &set); /* can't fail */ + + /* Bound-check sig, remove it from the set. */ + if (sigdelset (&set, sig) < 0) + return -1; + + /* Set the new mask. */ + return sigprocmask (SIG_SETMASK, &set, NULL); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sigset-cvt-mask.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sigset-cvt-mask.h new file mode 100644 index 00000000..d4c2dc7c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sigset-cvt-mask.h @@ -0,0 +1,38 @@ +/* Convert between lowlevel sigmask and libc representation of sigset_t. + Linux version. + Copyright (C) 1998, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Joe Keane . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +static __inline__ void __attribute__ ((unused)) +sigset_set_old_mask (sigset_t *set, int mask) +{ + if (_SIGSET_NWORDS == 2) /* typical */ + set->__val[1] = 0; + if (_SIGSET_NWORDS > 2) + memset(set, 0, sizeof(*set)); + set->__val[0] = (unsigned int) mask; +} + +static __inline__ int __attribute__ ((unused)) +sigset_get_old_mask (const sigset_t *set) +{ + return (unsigned int) set->__val[0]; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sigset.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sigset.c new file mode 100644 index 00000000..b91ce808 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sigset.c @@ -0,0 +1,67 @@ +/* Copyright (C) 1998, 2000, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#define __need_NULL +#include +#include +#include /* For the real memset prototype. */ + + +/* Set the disposition for SIG. */ +__sighandler_t sigset (int sig, __sighandler_t disp) +{ + struct sigaction act, oact; + sigset_t set; + + /* Check signal extents to protect __sigismember. */ + if (disp == SIG_ERR || sig < 1 || sig >= NSIG) + { + __set_errno (EINVAL); + return SIG_ERR; + } + +#ifdef SIG_HOLD + /* Handle SIG_HOLD first. */ + if (disp == SIG_HOLD) + { + __sigemptyset (&set); + __sigaddset (&set, sig); + + /* Add the signal set to the current signal mask. */ + sigprocmask (SIG_BLOCK, &set, NULL); /* can't fail */ + + return SIG_HOLD; + } +#endif /* SIG_HOLD */ + + memset(&act, 0, sizeof(act)); + act.sa_handler = disp; + /* In Linux (as of 2.6.25), fails only if sig is SIGKILL or SIGSTOP */ + if (sigaction (sig, &act, &oact) < 0) + return SIG_ERR; + + /* Create an empty signal set. Add the specified signal. */ + __sigemptyset (&set); + __sigaddset (&set, sig); + + /* Remove the signal set from the current signal mask. */ + sigprocmask (SIG_UNBLOCK, &set, NULL); /* can't fail */ + + return oact.sa_handler; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sigsetmask.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sigsetmask.c new file mode 100644 index 00000000..64c8ad68 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sigsetmask.c @@ -0,0 +1,35 @@ +/* Copyright (C) 1991,1994-1997,2001-2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define __UCLIBC_HIDE_DEPRECATED__ +#include +#include + +#include "sigset-cvt-mask.h" + +/* Set the mask of blocked signals to MASK, returning the old mask. */ +int +sigsetmask (int mask) +{ + sigset_t set, oset; + + sigset_set_old_mask (&set, mask); + sigprocmask (SIG_SETMASK, &set, &oset); /* can't fail */ + return sigset_get_old_mask (&oset); +} +libc_hidden_def(sigsetmask) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sigsetops.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sigsetops.c new file mode 100644 index 00000000..fa5fe6ac --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sigsetops.c @@ -0,0 +1,20 @@ +/* Define the real-function versions of all inline functions + defined in signal.h (or bits/sigset.h). */ + +#include + +#define __PROVIDE_OUT_OF_LINE_SIGSETFN +#ifndef __USE_EXTERN_INLINES +# define __USE_EXTERN_INLINES 1 +#endif + +#include + +/* Since we massaged signal.h into emitting non-inline function + * definitions, we need to finish PLT avoidance trick: */ +#undef __sigismember +#undef __sigaddset +#undef __sigdelset +libc_hidden_def(__sigismember) +libc_hidden_def(__sigaddset) +libc_hidden_def(__sigdelset) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sigsetops.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sigsetops.h new file mode 100644 index 00000000..52081c2b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sigsetops.h @@ -0,0 +1,33 @@ +/* Copyright (C) 1991, 1995, 1996 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Definitions relevant to functions that operate on `sigset_t's. */ + +#include +#include +#include + +#define BITS (_NSIG - 1) +#define ELT(signo) (((signo) - 1) / BITS) +#define MASK(signo) (1 << (((signo) - 1) % BITS)) + +#undef sigemptyset +#undef sigfillset +#undef sigaddset +#undef sigdelset +#undef sigismember diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sigwait.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sigwait.c new file mode 100644 index 00000000..8fd7ea81 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sigwait.c @@ -0,0 +1,167 @@ +/* vi: set sw=4 ts=4: */ +/* sigwait + * + * Copyright (C) 2006 by Steven J. Hill + * Copyright (C) 2003-2005 by Erik Andersen + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * The GNU C Library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the GNU C Library; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 USA. */ + +#include +#include +#include +#include + +#ifdef __UCLIBC_HAS_THREADS_NATIVE__ +# include + +# ifdef __NR_rt_sigtimedwait + +/* Return any pending signal or wait for one for the given time. */ +static int do_sigwait(const sigset_t *set, int *sig) +{ + int ret; + +# ifdef SIGCANCEL + sigset_t tmpset; + if (set != NULL + && (__builtin_expect (__sigismember (set, SIGCANCEL), 0) +# ifdef SIGSETXID + || __builtin_expect (__sigismember (set, SIGSETXID), 0) +# endif + )) + { + /* Create a temporary mask without the bit for SIGCANCEL set. */ + // We are not copying more than we have to. + memcpy(&tmpset, set, _NSIG / 8); + __sigdelset(&tmpset, SIGCANCEL); +# ifdef SIGSETXID + __sigdelset(&tmpset, SIGSETXID); +# endif + set = &tmpset; + } +# endif + + /* XXX The size argument hopefully will have to be changed to the + real size of the user-level sigset_t. */ + INTERNAL_SYSCALL_DECL(err); + do + ret = INTERNAL_SYSCALL (rt_sigtimedwait, err, 4, set, NULL, + NULL, _NSIG / 8); + while (INTERNAL_SYSCALL_ERROR_P (ret, err) + && INTERNAL_SYSCALL_ERRNO (ret, err) == EINTR); + if (! INTERNAL_SYSCALL_ERROR_P (ret, err)) + { + *sig = ret; + ret = 0; + } +else + ret = INTERNAL_SYSCALL_ERRNO (ret, err); + + return ret; +} + +int sigwait (const sigset_t *set, int *sig) +{ + if(SINGLE_THREAD_P) + return do_sigwait(set, sig); + + int oldtype = LIBC_CANCEL_ASYNC(); + + int result = do_sigwait(set, sig); + + LIBC_CANCEL_RESET(oldtype); + + return result; +} +# else /* __NR_rt_sigtimedwait */ +# error We must have rt_sigtimedwait defined!!! +# endif +#else /* __UCLIBC_HAS_THREADS_NATIVE__ */ + +# if defined __UCLIBC_HAS_REALTIME__ + +int sigwait (const sigset_t *set, int *sig) +{ + int ret = 1; + if ((ret = sigwaitinfo(set, NULL)) != -1) { + *sig = ret; + return 0; + } + return 1; +} + +# else /* __UCLIBC_HAS_REALTIME__ */ +/* variant without REALTIME extensions */ + +static smallint was_sig; /* obviously not thread-safe */ + +static void ignore_signal(int sig) +{ + was_sig = sig; +} + +int sigwait (const sigset_t *set, int *sig) +{ + sigset_t tmp_mask; + struct sigaction saved[NSIG]; + struct sigaction action; + int save_errno; + int this; + + /* Prepare set. */ + __sigfillset (&tmp_mask); + + /* Unblock all signals in the SET and register our nice handler. */ + action.sa_handler = ignore_signal; + action.sa_flags = 0; + __sigfillset (&action.sa_mask); /* Block all signals for handler. */ + + /* Make sure we recognize error conditions by setting WAS_SIG to a + value which does not describe a legal signal number. */ + was_sig = -1; + + for (this = 1; this < NSIG; ++this) + if (__sigismember (set, this)) + { + /* Unblock this signal. */ + __sigdelset (&tmp_mask, this); + + /* Register temporary action handler. */ + /* In Linux (as of 2.6.25), fails only if sig is SIGKILL or SIGSTOP */ + /* (so, will it work correctly if set has, say, SIGSTOP?) */ + if (sigaction (this, &action, &saved[this]) != 0) + goto restore_handler; + } + + /* Now we can wait for signals. */ + sigsuspend (&tmp_mask); + + restore_handler: + save_errno = errno; + + while (--this >= 1) + if (__sigismember (set, this)) + /* We ignore errors here since we must restore all handlers. */ + sigaction (this, &saved[this], NULL); + + __set_errno (save_errno); + + /* Store the result and return. */ + *sig = was_sig; + return was_sig == -1 ? -1 : 0; +} +# endif /* __UCLIBC_HAS_REALTIME__ */ +#endif /* __UCLIBC_HAS_THREADS_NATIVE__ */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sysv_signal.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sysv_signal.c new file mode 100644 index 00000000..a696a542 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/signal/sysv_signal.c @@ -0,0 +1,57 @@ +/* Copyright (C) 1991, 1992, 1996, 1997, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include /* For the real memset prototype. */ + + +/* Tolerate non-threads versions of Posix */ +#ifndef SA_ONESHOT +#define SA_ONESHOT 0 +#endif +#ifndef SA_NOMASK +#define SA_NOMASK 0 +#endif +#ifndef SA_INTERRUPT +#define SA_INTERRUPT 0 +#endif + +/* Set the handler for the signal SIG to HANDLER, + returning the old handler, or SIG_ERR on error. */ +__sighandler_t __sysv_signal (int sig, __sighandler_t handler) +{ + struct sigaction act, oact; + + /* Check signal extents to protect __sigismember. */ + if (handler == SIG_ERR || sig < 1 || sig >= NSIG) + { + __set_errno (EINVAL); + return SIG_ERR; + } + + act.sa_handler = handler; + __sigemptyset (&act.sa_mask); + act.sa_flags = (SA_ONESHOT | SA_NOMASK | SA_INTERRUPT) & ~SA_RESTART; + /* In Linux (as of 2.6.25), fails only if sig is SIGKILL or SIGSTOP */ + if (sigaction (sig, &act, &oact) < 0) + return SIG_ERR; + + return oact.sa_handler; +} +strong_alias(__sysv_signal,sysv_signal) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/.indent.pro b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/.indent.pro new file mode 100644 index 00000000..492ecf1c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/.indent.pro @@ -0,0 +1,33 @@ +--blank-lines-after-declarations +--blank-lines-after-procedures +--break-before-boolean-operator +--no-blank-lines-after-commas +--braces-on-if-line +--braces-on-struct-decl-line +--comment-indentation25 +--declaration-comment-column25 +--no-comment-delimiters-on-blank-lines +--cuddle-else +--continuation-indentation4 +--case-indentation0 +--else-endif-column33 +--space-after-cast +--line-comments-indentation0 +--declaration-indentation1 +--dont-format-first-column-comments +--dont-format-comments +--honour-newlines +--indent-level4 +/* changed from 0 to 4 */ +--parameter-indentation4 +--line-length78 /* changed from 75 */ +--continue-at-parentheses +--no-space-after-function-call-names +--dont-break-procedure-type +--dont-star-comments +--leave-optional-blank-lines +--dont-space-special-semicolon +--tab-size4 +/* additions by Mark */ +--case-brace-indentation0 +--leave-preprocessor-space diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/Makefile new file mode 100644 index 00000000..11f362a5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../ +top_builddir=../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/Makefile.in new file mode 100644 index 00000000..1ca2dcff --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/Makefile.in @@ -0,0 +1,109 @@ +# Makefile for uClibc +# +# Copyright (C) 2004 Manuel Novoa III +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# +# Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. +# + +subdirs += libc/stdio + +# SUSv3 functions +CSRC := \ + fclose.c fcloseall.c fdopen.c fgetpos.c fopen.c freopen.c \ + fseeko.c fsetpos.c ftello.c getdelim.c getline.c gets.c getw.c \ + perror.c puts.c putw.c remove.c rewind.c setbuf.c setbuffer.c \ + setlinebuf.c setvbuf.c ungetc.c \ + printf.c vprintf.c vsprintf.c fprintf.c snprintf.c dprintf.c \ + asprintf.c sprintf.c vasprintf.c vdprintf.c vsnprintf.c \ + tmpfile.c tmpnam.c tmpnam_r.c popen.c tempnam.c ctermid.c + +ifeq ($(UCLIBC_HAS_LFS),y) +CSRC += fgetpos64.c fopen64.c freopen64.c fseeko64.c fsetpos64.c ftello64.c +endif + +# getc -> alias for fgetc +# putc -> alias for fputc +# rename is a syscall + +# Implementation support functions +CSRC += \ + _READ.c _WRITE.c _adjust_pos.c _fopen.c _fwrite.c \ + _rfill.c _stdio.c _trans2r.c _trans2w.c _wcommit.c \ + _cs_funcs.c _load_inttype.c _store_inttype.c _uintmaxtostr.c +ifeq ($(UCLIBC_HAS_FLOATS),y) +CSRC += _fpmaxtostr.c +endif + +# stdio_ext.h functions +CSRC += \ + __fbufsize.c __flbf.c __fpending.c __fpurge.c __freadable.c \ + __freading.c __fsetlocking.c __fwritable.c __fwriting.c _flushlbf.c + +# Other glibc extensions +ifeq ($(UCLIBC_HAS_GLIBC_CUSTOM_STREAMS),y) +CSRC += fopencookie.c fmemopen.c open_memstream.c +endif + +# pthread functions +CSRC += flockfile.c ftrylockfile.c funlockfile.c + +# Functions with unlocked versions +CUSRC := \ + clearerr.c feof.c ferror.c fflush.c fgetc.c fgets.c fileno.c \ + fputc.c fputs.c fread.c fwrite.c getchar.c putchar.c +# getc_unlocked -> alias for fgetc_unlocked +# putc_unlocked -> alias for fputc_unlocked + +# vfprintf and support functions +ifneq ($(USE_OLD_VFPRINTF),y) +VF_CSRC := \ + vfprintf.c \ + _vfprintf_internal.c \ + _ppfs_init.c _ppfs_prepargs.c _ppfs_setargs.c _ppfs_parsespec.c \ + register_printf_function.c parse_printf_format.c +CSRC += $(VF_CSRC) +else +CSRC += old_vfprintf.c +endif + +# vfscanf and support functions plus other *scanf funcs +CSRC += \ + vfscanf.c __scan_cookie.c __psfs_parse_spec.c __psfs_do_numeric.c \ + scanf.c sscanf.c fscanf.c vscanf.c vsscanf.c + +ifeq ($(UCLIBC_HAS_WCHAR),y) +CSRC += _wfwrite.c fwprintf.c swprintf.c vswprintf.c vwprintf.c wprintf.c \ + fwide.c ungetwc.c +CUSRC += fgetwc.c getwchar.c fgetws.c fputwc.c putwchar.c fputws.c +# getwc (fgetwc alias) getwc_unlocked (fgetwc_unlocked alias) +# putwc (fputwc alias) putwc_unlocked (fputwc_unlocked alias) +CSRC += vfwprintf.c _vfwprintf_internal.c +CSRC += wscanf.c swscanf.c fwscanf.c vwscanf.c vswscanf.c vfwscanf.c +endif + +CUSRC_UNLOCKED := $(patsubst %.c,%_unlocked.c,$(CUSRC)) + +CSRC += $(CUSRC) $(CUSRC_UNLOCKED) + +STDIO_DIR := $(top_srcdir)libc/stdio +STDIO_OUT := $(top_builddir)libc/stdio + +STDIO_SRC := $(patsubst %.c,$(STDIO_DIR)/%.c,$(CSRC)) +STDIO_OBJ := $(patsubst %.c,$(STDIO_OUT)/%.o,$(CSRC)) + +libc-y += $(STDIO_OBJ) + +ifneq ($(USE_OLD_VFPRINTF),y) +libc-nomulti-y += $(patsubst %.c,$(STDIO_OUT)/%.o,$(VF_CSRC)) +endif +ifeq ($(UCLIBC_HAS_WCHAR),y) +libc-nomulti-y += $(STDIO_OUT)/vfwprintf.o $(STDIO_OUT)/vfwscanf.o +endif + +objclean-y += CLEAN_libc/stdio + +CLEAN_libc/stdio: + $(do_rm) $(addprefix $(STDIO_OUT)/*., o os oS) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_READ.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_READ.c new file mode 100644 index 00000000..02601c09 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_READ.c @@ -0,0 +1,67 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + + +/* Given a reading stream without its end-of-file indicator set and + * with no buffered input or ungots, read at most 'bufsize' bytes + * into 'buf' (which may be the stream's __bufstart). + * If a read error occurs, set the stream's error indicator. + * If EOF is encountered, set the stream's end-of-file indicator. + * + * Returns the number of bytes read, even in EOF and error cases. + * + * Notes: + * Calling with bufsize == 0 is NOT permitted (unlike __stdio_WRITE). + * NOT THREADSAFE! Assumes stream already locked if necessary. + */ + +size_t attribute_hidden __stdio_READ(register FILE *stream, + unsigned char *buf, size_t bufsize) +{ + ssize_t rv = 0; + + __STDIO_STREAM_VALIDATE(stream); + assert(stream->__filedes >= -1); + assert(__STDIO_STREAM_IS_READING(stream)); + assert(!__STDIO_STREAM_BUFFER_RAVAIL(stream)); /* Buffer must be empty. */ + assert(!(stream->__modeflags & __FLAG_UNGOT)); + assert(bufsize); + + if (!__FEOF_UNLOCKED(stream)) { + if (bufsize > SSIZE_MAX) { + bufsize = SSIZE_MAX; + } + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning EINTR? +#endif +/* RETRY: */ + if ((rv = __READ(stream, (char *) buf, bufsize)) <= 0) { + if (rv == 0) { + __STDIO_STREAM_SET_EOF(stream); + } else { +/* if (errno == EINTR) goto RETRY; */ + __STDIO_STREAM_SET_ERROR(stream); + rv = 0; + } +#ifdef __UCLIBC_MJN3_ONLY__ +#warning TODO: Make custom stream read return check optional. +#endif +#ifdef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ + } else { + assert(rv <= bufsize); + if (rv > bufsize) { /* Read more than bufsize! */ + abort(); + } +#endif + } + } + + return rv; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_WRITE.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_WRITE.c new file mode 100644 index 00000000..10b3b958 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_WRITE.c @@ -0,0 +1,101 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + + +/* Given a writing stream with no buffered output, write the + * data in 'buf' (which may be the stream's bufstart) of size + * 'bufsize' to the stream. If a write error occurs, set the + * stream's error indicator and (if buffering) buffer as much + * data as possible (FBF) or only up to '\n' (LBF) to implement + * "as if fputc()" clause in the standard. + * + * Returns the number of bytes written and/or buffered. + * + * Notes: + * Calling with bufsize == 0 is permitted, and buf is ignored in + * that case. + * We implement fflush() by setting bufpos to bufstart and passing + * bufstart as the buf arg. If there is a write error, the + * unwritten buffered data will simply be moved to the beginning + * of the buffer. Since the data obviously fits in the buffer + * and since there will be no '\n' chars in the buffer in the LBF + * case, no data will be lost. + * NOT THREADSAFE! Assumes stream already locked if necessary. + */ + +size_t attribute_hidden __stdio_WRITE(register FILE *stream, + register const unsigned char *buf, size_t bufsize) +{ + size_t todo; + ssize_t rv, stodo; + + __STDIO_STREAM_VALIDATE(stream); + assert(stream->__filedes >= -1); + assert(__STDIO_STREAM_IS_WRITING(stream)); + assert(!__STDIO_STREAM_BUFFER_WUSED(stream)); /* Buffer must be empty. */ + + todo = bufsize; + + do { + if (todo == 0) { /* Done? */ + __STDIO_STREAM_VALIDATE(stream); + return bufsize; + } + stodo = (todo <= SSIZE_MAX) ? todo : SSIZE_MAX; + if ((rv = __WRITE(stream, (char *) buf, stodo)) >= 0) { +#ifdef __UCLIBC_MJN3_ONLY__ +#warning TODO: Make custom stream write return check optional. +#endif +#ifdef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ + assert(rv <= stodo); + if (rv > stodo) { /* Wrote more than stodo! */ +/* abort(); */ + } +#endif + todo -= rv; + buf += rv; + } else +#ifdef __UCLIBC_MJN3_ONLY__ +#warning EINTR? +#endif +/* if (errno != EINTR) */ + { + __STDIO_STREAM_SET_ERROR(stream); + +#ifdef __STDIO_BUFFERS + if ((stodo = __STDIO_STREAM_BUFFER_SIZE(stream)) != 0) { + unsigned char *s; + + if (stodo > todo) { + stodo = todo; + } + + s = stream->__bufstart; + + do { + if (((*s = *buf) == '\n') + && __STDIO_STREAM_IS_LBF(stream) + ) { + break; + } + ++s; + ++buf; + } while (--stodo); + + stream->__bufpos = s; + + todo -= (s - stream->__bufstart); + } +#endif /* __STDIO_BUFFERS */ + + __STDIO_STREAM_VALIDATE(stream); + return bufsize - todo; + } + } while (1); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/__fbufsize.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/__fbufsize.c new file mode 100644 index 00000000..09ade15a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/__fbufsize.c @@ -0,0 +1,20 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" +#include + +/* Solaris function -- + * Returns the size of the buffer in bytes.. + */ + +size_t __fbufsize(register FILE * __restrict stream) +{ + __STDIO_STREAM_VALIDATE(stream); + + return __STDIO_STREAM_BUFFER_SIZE(stream); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/__flbf.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/__flbf.c new file mode 100644 index 00000000..13d8cea9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/__flbf.c @@ -0,0 +1,20 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" +#include + +/* Solaris function -- + * Returns nonzero if the stream is line buffered, and 0 otherwise. + */ + +int __flbf(FILE * __restrict stream) +{ + __STDIO_STREAM_VALIDATE(stream); + + return __STDIO_STREAM_IS_LBF(stream); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/__fpending.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/__fpending.c new file mode 100644 index 00000000..a7fe0546 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/__fpending.c @@ -0,0 +1,35 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" +#include + +/* Solaris function -- + * Returns the number of bytes in the buffer for a writing stream. + * + * NOTE: GLIBC DIFFERENCE!!! + * + * glibc will return the number of wide chars pending for wide oriented + * streams. We always return the number of bytes in the buffer, as we + * convert wide chars to their multibyte encodings and buffer _those_. + */ + +#ifdef __UCLIBC_HAS_WCHAR__ +#warning Note: Unlike the glibc version, this __fpending returns bytes in buffer for wide streams too! + +link_warning(__fpending, "This version of __fpending returns bytes remaining in buffer for both narrow and wide streams. glibc's version returns wide chars in buffer for the wide stream case.") + +#endif + +size_t __fpending(register FILE * __restrict stream) +{ + __STDIO_STREAM_VALIDATE(stream); + + return (__STDIO_STREAM_IS_WRITING(stream)) + ? __STDIO_STREAM_BUFFER_WUSED(stream) + : 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/__fpurge.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/__fpurge.c new file mode 100644 index 00000000..c17ecf4c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/__fpurge.c @@ -0,0 +1,34 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" +#include + +/* Solaris function -- + * Discard all buffered data whether reading or writing. + */ + +void __fpurge(register FILE * __restrict stream) +{ + __STDIO_STREAM_VALIDATE(stream); + + __STDIO_STREAM_DISABLE_GETC(stream); + __STDIO_STREAM_DISABLE_PUTC(stream); + __STDIO_STREAM_INIT_BUFREAD_BUFPOS(stream); + stream->__ungot[1] = 0; + +#ifdef __STDIO_MBSTATE + __INIT_MBSTATE(&(stream->__state)); +#endif +#ifdef __UCLIBC_HAS_WCHAR__ + stream->__ungot_width[0] = 0; +#endif + + stream->__modeflags &= ~(__MASK_READING|__FLAG_WRITING); + + __STDIO_STREAM_VALIDATE(stream); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/__freadable.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/__freadable.c new file mode 100644 index 00000000..006a66fc --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/__freadable.c @@ -0,0 +1,20 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" +#include + +/* Solaris function -- + * Return nonzero if readable, and 0 if write-only. + */ + +int __freadable(FILE * __restrict stream) +{ + __STDIO_STREAM_VALIDATE(stream); + + return !__STDIO_STREAM_IS_WRITEONLY(stream); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/__freading.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/__freading.c new file mode 100644 index 00000000..aab91b23 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/__freading.c @@ -0,0 +1,20 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" +#include + +/* Solaris function -- + * Return nonzero if read-only or was last read from, and 0 otherwise. + */ + +int __freading(FILE * __restrict stream) +{ + __STDIO_STREAM_VALIDATE(stream); + + return __STDIO_STREAM_IS_READING_OR_READONLY(stream); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/__fsetlocking.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/__fsetlocking.c new file mode 100644 index 00000000..6d4fc18b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/__fsetlocking.c @@ -0,0 +1,47 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" +#include + + +/* Not threadsafe. */ + +/* Notes: + * When setting the locking mode, glibc returns the previous setting. + * glibc treats invalid locking_mode args as FSETLOCKING_INTERNAL. + */ + +int __fsetlocking(FILE *stream, int locking_mode) +{ +#ifdef __UCLIBC_HAS_THREADS__ + int current = 1 + (stream->__user_locking & 1); + + /* Check constant assumptions. We can't test at build time + * since these are enums. */ + assert((FSETLOCKING_QUERY == 0) && (FSETLOCKING_INTERNAL == 1) + && (FSETLOCKING_BYCALLER == 2)); + + __STDIO_STREAM_VALIDATE(stream); + assert(((unsigned int) locking_mode) <= 2); + + if (locking_mode != FSETLOCKING_QUERY) { + stream->__user_locking = ((locking_mode == FSETLOCKING_BYCALLER) + ? 1 + : _stdio_user_locking); /* 0 or 2 */ + __STDIO_STREAM_VALIDATE(stream); + } + + return current; +#else + __STDIO_STREAM_VALIDATE(stream); + assert(((unsigned int) locking_mode) <= 2); + + return FSETLOCKING_INTERNAL; +#endif +} +libc_hidden_def(__fsetlocking) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/__fwritable.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/__fwritable.c new file mode 100644 index 00000000..59c70a64 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/__fwritable.c @@ -0,0 +1,20 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" +#include + +/* Solaris function -- + * Return nonzero if writable, and 0 if read-only. + */ + +int __fwritable(FILE * __restrict stream) +{ + __STDIO_STREAM_VALIDATE(stream); + + return !__STDIO_STREAM_IS_READONLY(stream); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/__fwriting.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/__fwriting.c new file mode 100644 index 00000000..926eaa95 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/__fwriting.c @@ -0,0 +1,20 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" +#include + +/* Solaris function -- + * Return nonzero if write-only or was last written to, and 0 otherwise. + */ + +int __fwriting(FILE * __restrict stream) +{ + __STDIO_STREAM_VALIDATE(stream); + + return __STDIO_STREAM_IS_WRITING_OR_WRITEONLY(stream); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/__psfs_do_numeric.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/__psfs_do_numeric.c new file mode 100644 index 00000000..e3714776 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/__psfs_do_numeric.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define L___psfs_do_numeric +#include "_scanf.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/__psfs_parse_spec.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/__psfs_parse_spec.c new file mode 100644 index 00000000..cac9cda4 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/__psfs_parse_spec.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define L___psfs_parse_spec +#include "_scanf.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/__scan_cookie.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/__scan_cookie.c new file mode 100644 index 00000000..d5d53c4c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/__scan_cookie.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define L___scan_cookie +#include "_scanf.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_adjust_pos.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_adjust_pos.c new file mode 100644 index 00000000..bc6e9055 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_adjust_pos.c @@ -0,0 +1,68 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +/* Both ftell() and fseek() (for SEEK_CUR) need to correct the stream's + * position to take into account buffered data and ungotten chars. + * + * If successful, store corrected position in *pos and return >= 0. + * Otherwise return < 0. + * + * If position is unrepresentable, set errno to EOVERFLOW. + */ + +int attribute_hidden __stdio_adjust_position(register FILE * __restrict stream, + register __offmax_t *pos) +{ + __offmax_t oldpos; + int corr; + + if ((corr = stream->__modeflags & __MASK_READING) != 0) { + --corr; /* Correct for ungots. Assume narrow, and fix below. */ + } + +#ifdef __UCLIBC_HAS_WCHAR__ + if (corr && __STDIO_STREAM_IS_WIDE(stream)) { + /* A wide stream and we have at least one ungotten wchar. + * If it is a user ungot, we need to fail since position + * is unspecified as per C99. */ + if ((corr > 1) || stream->__ungot[1]) { /* User ungetwc, */ + return -1; /* so position is undefined. */ + } + corr -= (1 + stream->__ungot_width[1]); + if (stream->__state.__mask > 0) { /* Incomplete (bad?) mb char. */ + corr -= stream->__ungot_width[0]; + } + } +#endif + +#ifdef __STDIO_BUFFERS + corr += (((__STDIO_STREAM_IS_WRITING(stream)) + ? stream->__bufstart : stream->__bufread) + - stream->__bufpos); +#endif + + oldpos = *pos; + + /* Range checking cases: + * (pos - corr > pos) && (corr > 0) : underflow? return -corr < 0 + * (pos - corr > pos) && (corr < 0) : ok .. return -corr > 0 + * (pos - corr <= pos) && (corr >= 0) : ok .. return corr > 0 + * (pos - corr <= pos) && (corr < 0) : overflow .. return corr < 0 + */ + + if ((*pos -= corr) > oldpos) { + corr = -corr; + } + + if (corr < 0) { + __set_errno(EOVERFLOW); + } + + return corr; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_cs_funcs.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_cs_funcs.c new file mode 100644 index 00000000..9df93f22 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_cs_funcs.c @@ -0,0 +1,67 @@ +/* Copyright (C) 2004-2005 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +/**********************************************************************/ +#ifdef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ +/**********************************************************************/ + +ssize_t attribute_hidden _cs_read(void *cookie, char *buf, size_t bufsize) +{ + return read(*((int *) cookie), buf, bufsize); +} + +/**********************************************************************/ + +ssize_t attribute_hidden _cs_write(void *cookie, const char *buf, size_t bufsize) +{ + return write(*((int *) cookie), (char *) buf, bufsize); +} + +/**********************************************************************/ + +int attribute_hidden _cs_seek(void *cookie, register __offmax_t *pos, int whence) +{ + __offmax_t res; + +#ifdef __UCLIBC_HAS_LFS__ + res = lseek64(*((int *) cookie), *pos, whence); +#else + res = lseek(*((int *) cookie), *pos, whence); +#endif + + return (res >= 0) ? ((*pos = res), 0) : ((int) res); +} + +/**********************************************************************/ + +int attribute_hidden _cs_close(void *cookie) +{ + return close(*((int *) cookie)); +} + +/**********************************************************************/ +#else +/**********************************************************************/ + +int attribute_hidden __stdio_seek(FILE *stream, register __offmax_t *pos, int whence) +{ + __offmax_t res; + +#ifdef __UCLIBC_HAS_LFS__ + res = lseek64(stream->__filedes, *pos, whence); +#else + res = lseek(stream->__filedes, *pos, whence); +#endif + + return (res >= 0) ? ((*pos = res), 0) : ((int) res); +} + +/**********************************************************************/ +#endif +/**********************************************************************/ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_flushlbf.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_flushlbf.c new file mode 100644 index 00000000..c322c3e3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_flushlbf.c @@ -0,0 +1,19 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" +#include + + +/* Solaris function -- + * Flush all line buffered (writing) streams. + */ + +void _flushlbf(void) +{ + __STDIO_FLUSH_LBF_STREAMS; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_fopen.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_fopen.c new file mode 100644 index 00000000..2db27a89 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_fopen.c @@ -0,0 +1,226 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + + +/* + * Cases: + * fopen64 : filename != NULL, stream == NULL, filedes == -2 + * fopen : filename != NULL, stream == NULL, filedes == -1 + * freopen : filename != NULL, stream != NULL, filedes == -1 + * fdopen : filename == NULL, stream == NULL, filedes valid + * + * fsfopen : filename != NULL, stream != NULL, filedes == -1 + */ + +#if (O_ACCMODE != 3) || (O_RDONLY != 0) || (O_WRONLY != 1) || (O_RDWR != 2) +#error Assumption violated - mode constants +#endif + +#ifndef O_LARGEFILE +#define O_LARGEFILE 0 +#endif + +/* Internal function -- reentrant (locks open file list) */ + +FILE attribute_hidden *_stdio_fopen(intptr_t fname_or_mode, + register const char * __restrict mode, + register FILE * __restrict stream, int filedes) +{ + __mode_t open_mode; + int i; + + /* Parse the specified mode. */ + open_mode = O_RDONLY; + if (*mode != 'r') { /* Not read... */ + open_mode = (O_WRONLY | O_CREAT | O_TRUNC); + if (*mode != 'w') { /* Not write (create or truncate)... */ + open_mode = (O_WRONLY | O_CREAT | O_APPEND); + if (*mode != 'a') { /* Not write (create or append)... */ + DO_EINVAL: + __set_errno(EINVAL); /* So illegal mode. */ + if (stream) { + FREE_STREAM: + assert(!(stream->__modeflags & __FLAG_FREEBUF)); + __STDIO_STREAM_FREE_FILE(stream); + } + return NULL; + } + } + } + + if ((mode[1] == 'b')) { /* Binary mode (NO-OP currently). */ + ++mode; + } + + if (mode[1] == '+') { /* Read and Write. */ + ++mode; + open_mode |= (O_RDONLY | O_WRONLY); + open_mode += (O_RDWR - (O_RDONLY | O_WRONLY)); + } + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning CONSIDER: Implement glibc ccs option to bind a codeset? +#warning CONSIDER: Implement glibc mmap option for readonly files? +#warning CONSIDER: Implement a text mode using custom read/write funcs? +#endif +#if defined(__UCLIBC_HAS_FOPEN_EXCLUSIVE_MODE__) || defined(__UCLIBC_HAS_FOPEN_LARGEFILE_MODE__) + + while (*++mode) { +# ifdef __UCLIBC_HAS_FOPEN_EXCLUSIVE_MODE__ + if (*mode == 'x') { /* Open exclusive (a glibc extension). */ + open_mode |= O_EXCL; + continue; + } +# endif +# ifdef __UCLIBC_HAS_FOPEN_LARGEFILE_MODE__ + if (*mode == 'F') { /* Open as large file (uClibc extension). */ + open_mode |= O_LARGEFILE; + continue; + } +# endif + } + +#endif + + if (!stream) { /* Need to allocate a FILE (not freopen). */ + if ((stream = malloc(sizeof(FILE))) == NULL) { + return stream; + } + stream->__modeflags = __FLAG_FREEFILE; +#ifdef __STDIO_BUFFERS + stream->__bufstart = NULL; /* We allocate a buffer below. */ +#endif +#ifdef __UCLIBC_HAS_THREADS__ + /* We only initialize the mutex in the non-freopen case. */ + /* stream->__user_locking = _stdio_user_locking; */ + STDIO_INIT_MUTEX(stream->__lock); +#endif + } + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning TODO: Verify fdopen append behavior of glibc. +#endif + + if (filedes >= 0) { /* Handle fdopen trickery. */ + stream->__filedes = filedes; + /* NOTE: it is insufficient to just check R/W/RW agreement. + * We must also check largefile compatibility if applicable. + * Also, if append mode is desired for fdopen but O_APPEND isn't + * currently set, then set it as recommended by SUSv3. However, + * if append mode is not specified for fdopen but O_APPEND is set, + * leave it set (glibc compat). */ + i = (open_mode & (O_ACCMODE|O_LARGEFILE)) + 1; + + /* NOTE: fopencookie needs changing if the basic check changes! */ + if ((i & ((int)fname_or_mode + 1)) != i) /* Basic agreement? */ + goto DO_EINVAL; + if ((open_mode & ~(__mode_t)fname_or_mode) & O_APPEND) { + if (fcntl(filedes, F_SETFL, O_APPEND)) /* Need O_APPEND. */ + goto DO_EINVAL; + } + /* For later... to reflect largefile setting in stream flags. */ + __STDIO_WHEN_LFS( open_mode |= (((__mode_t) fname_or_mode) + & O_LARGEFILE) ); + } else { + __STDIO_WHEN_LFS( if (filedes < -1) open_mode |= O_LARGEFILE ); + if ((stream->__filedes = open(((const char *) fname_or_mode), + open_mode, 0666)) < 0) { + goto FREE_STREAM; + } + } + + stream->__modeflags &= __FLAG_FREEFILE; +/* stream->__modeflags &= ~(__FLAG_READONLY|__FLAG_WRITEONLY); */ + + stream->__modeflags |= /* Note: Makes assumptions about flag vals! */ +#if (O_APPEND != __FLAG_APPEND) || ((O_LARGEFILE != __FLAG_LARGEFILE) && (O_LARGEFILE != 0)) +# if (O_APPEND != __FLAG_APPEND) + ((open_mode & O_APPEND) ? __FLAG_APPEND : 0) | +# else + (open_mode & O_APPEND) | +# endif +# if (O_LARGEFILE != __FLAG_LARGEFILE) && (O_LARGEFILE != 0) + ((open_mode & O_LARGEFILE) ? __FLAG_LARGEFILE : 0) | +# else + (open_mode & O_LARGEFILE) | +# endif +#else + (open_mode & (O_APPEND|O_LARGEFILE)) | /* i386 linux and elks */ +#endif + ((((open_mode & O_ACCMODE) + 1) ^ 0x03) * __FLAG_WRITEONLY); + +#ifdef __STDIO_BUFFERS + if (stream->__filedes != INT_MAX) { + /* NB: fopencookie uses bogus filedes == INT_MAX, + * avoiding isatty() in that case. + */ + i = errno; /* preserve errno against isatty call. */ + if (isatty(stream->__filedes)) + stream->__modeflags |= __FLAG_LBF; + __set_errno(i); + } + + if (!stream->__bufstart) { + if ((stream->__bufstart = malloc(BUFSIZ)) != NULL) { + stream->__bufend = stream->__bufstart + BUFSIZ; + stream->__modeflags |= __FLAG_FREEBUF; + } else { +# if __STDIO_BUILTIN_BUF_SIZE > 0 + stream->__bufstart = stream->__builtinbuf; + stream->__bufend = stream->__builtinbuf + sizeof(stream->__builtinbuf); +# else /* __STDIO_BUILTIN_BUF_SIZE > 0 */ + stream->__bufend = stream->__bufstart; +# endif /* __STDIO_BUILTIN_BUF_SIZE > 0 */ + } + } + + __STDIO_STREAM_DISABLE_GETC(stream); + __STDIO_STREAM_DISABLE_PUTC(stream); + __STDIO_STREAM_INIT_BUFREAD_BUFPOS(stream); +#endif + + __STDIO_STREAM_RESET_GCS(stream); + +#ifdef __UCLIBC_HAS_WCHAR__ + stream->__ungot_width[0] = 0; +#endif +#ifdef __STDIO_MBSTATE + __INIT_MBSTATE(&(stream->__state)); +#endif + +#ifdef __UCLIBC_HAS_THREADS__ + /* Even in the freopen case, we reset the user locking flag. */ + stream->__user_locking = _stdio_user_locking; + /* STDIO_INIT_MUTEX(stream->__lock); */ +#endif + +#ifdef __STDIO_HAS_OPENLIST +#if defined(__UCLIBC_HAS_THREADS__) && defined(__STDIO_BUFFERS) + if (!(stream->__modeflags & __FLAG_FREEFILE)) + { + /* An freopen call so the file was never removed from the list. */ + } + else +#endif + { + /* We have to lock the del mutex in case another thread wants to fclose() + * the last file. */ + __STDIO_THREADLOCK_OPENLIST_DEL; + __STDIO_THREADLOCK_OPENLIST_ADD; + stream->__nextopen = _stdio_openlist; /* New files are inserted at */ + _stdio_openlist = stream; /* the head of the list. */ + __STDIO_THREADUNLOCK_OPENLIST_ADD; + __STDIO_THREADUNLOCK_OPENLIST_DEL; + } +#endif + + __STDIO_STREAM_VALIDATE(stream); + + return stream; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_fpmaxtostr.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_fpmaxtostr.c new file mode 100644 index 00000000..1332a20e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_fpmaxtostr.c @@ -0,0 +1,765 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" +#include +#include +#include +#include + + +typedef size_t (__fp_outfunc_t)(FILE *fp, intptr_t type, intptr_t len, + intptr_t buf); + + +/* Copyright (C) 2000, 2001, 2003 Manuel Novoa III + * + * Function: + * + * ssize_t _fpmaxtostr(FILE * fp, __fpmax_t x, struct printf_info *info, + * __fp_outfunc_t fp_outfunc); + * + * This is derived from the old _dtostr, whic I wrote for uClibc to provide + * floating point support for the printf functions. It handles +/- infinity, + * nan, and signed 0 assuming you have ieee arithmetic. It also now handles + * digit grouping (for the uClibc supported locales) and hexadecimal float + * notation. Finally, via the fp_outfunc parameter, it now supports wide + * output. + * + * Notes: + * + * At most DECIMAL_DIG significant digits are kept. Any trailing digits + * are treated as 0 as they are really just the results of rounding noise + * anyway. If you want to do better, use an arbitary precision arithmetic + * package. ;-) + * + * It should also be fairly portable, as no assumptions are made about the + * bit-layout of doubles. Of course, that does make it less efficient than + * it could be. + * + */ + +/*****************************************************************************/ +/* Don't change anything that follows unless you know what you're doing. */ +/*****************************************************************************/ +/* Fairly portable nan check. Bitwise for i386 generated larger code. + * If you have a better version, comment this out. + */ +#define isnan(x) ((x) != (x)) + +/* Without seminumerical functions to examine the sign bit, this is + * about the best we can do to test for '-0'. + */ +#define zeroisnegative(x) ((1./(x)) < 0) + +/*****************************************************************************/ +/* Don't change anything that follows peroid!!! ;-) */ +/*****************************************************************************/ +#ifdef __UCLIBC_HAS_HEXADECIMAL_FLOATS__ +#if FLT_RADIX != 2 +#error FLT_RADIX != 2 is not currently supported +#endif +#endif /* __UCLIBC_HAS_HEXADECIMAL_FLOATS__ */ + +#define NUM_HEX_DIGITS ((FPMAX_MANT_DIG + 3)/ 4) + +/* WARNING: Adjust _fp_out_wide() below if this changes! */ +/* With 32 bit ints, we can get 9 decimal digits per block. */ +#define DIGITS_PER_BLOCK 9 +#define HEX_DIGITS_PER_BLOCK 8 + +/* Maximum number of subcases to output double is... + * 0 - sign + * 1 - padding and initial digit + * 2 - digits left of the radix + * 3 - 0s left of the radix or radix + * 4 - radix or digits right of the radix + * 5 - 0s right of the radix + * 6 - exponent + * 7 - trailing space padding + * although not all cases may occur. + */ +#define MAX_CALLS 8 + +/*****************************************************************************/ + +#define NUM_DIGIT_BLOCKS ((DECIMAL_DIG+DIGITS_PER_BLOCK-1)/DIGITS_PER_BLOCK) +#define NUM_HEX_DIGIT_BLOCKS \ + ((NUM_HEX_DIGITS+HEX_DIGITS_PER_BLOCK-1)/HEX_DIGITS_PER_BLOCK) + +/* WARNING: Adjust _fp_out_wide() below if this changes! */ + +/* extra space for '-', '.', 'e+###', and nul */ +#define BUF_SIZE ( 3 + NUM_DIGIT_BLOCKS * DIGITS_PER_BLOCK ) + +/*****************************************************************************/ + +static const char fmt[] = "inf\0INF\0nan\0NAN\0.\0,"; + +#define INF_OFFSET 0 /* must be 1st */ +#define NAN_OFFSET 8 /* must be 2nd.. see hex sign handling */ +#define DECPT_OFFSET 16 +#define THOUSEP_OFFSET 18 + +#define EMPTY_STRING_OFFSET 3 + +/*****************************************************************************/ +#if FPMAX_MAX_10_EXP < -FPMAX_MIN_10_EXP +#error scaling code can not handle FPMAX_MAX_10_EXP < -FPMAX_MIN_10_EXP +#endif + +static const __fpmax_t exp10_table[] = +{ + 1e1L, 1e2L, 1e4L, 1e8L, 1e16L, 1e32L, /* floats */ +#if FPMAX_MAX_10_EXP < 32 +#error unsupported FPMAX_MAX_10_EXP (< 32). ANSI/ISO C requires >= 37. +#endif +#if FPMAX_MAX_10_EXP >= 64 + 1e64L, +#endif +#if FPMAX_MAX_10_EXP >= 128 + 1e128L, +#endif +#if FPMAX_MAX_10_EXP >= 256 + 1e256L, +#endif +#if FPMAX_MAX_10_EXP >= 512 + 1e512L, +#endif +#if FPMAX_MAX_10_EXP >= 1024 + 1e1024L, +#endif +#if FPMAX_MAX_10_EXP >= 2048 + 1e2048L, +#endif +#if FPMAX_MAX_10_EXP >= 4096 + 1e4096L +#endif +#if FPMAX_MAX_10_EXP >= 8192 +#error unsupported FPMAX_MAX_10_EXP. please increase table +#endif +}; + +#define EXP10_TABLE_SIZE (sizeof(exp10_table)/sizeof(exp10_table[0])) +#define EXP10_TABLE_MAX (1U<<(EXP10_TABLE_SIZE-1)) + +/*****************************************************************************/ +#ifdef __UCLIBC_HAS_HEXADECIMAL_FLOATS__ + +#if FLT_RADIX != 2 +#error FLT_RADIX != 2 is not currently supported +#endif + +#if FPMAX_MAX_EXP < -FPMAX_MIN_EXP +#error scaling code can not handle FPMAX_MAX_EXP < -FPMAX_MIN_EXP +#endif + +static const __fpmax_t exp16_table[] = { + 0x1.0p4L, 0x1.0p8L, 0x1.0p16L, 0x1.0p32L, 0x1.0p64L, +#if FPMAX_MAX_EXP >= 128 + 0x1.0p128L, +#endif +#if FPMAX_MAX_EXP >= 256 + 0x1.0p256L, +#endif +#if FPMAX_MAX_EXP >= 512 + 0x1.0p512L, +#endif +#if FPMAX_MAX_EXP >= 1024 + 0x1.0p1024L, +#endif +#if FPMAX_MAX_EXP >= 2048 + 0x1.0p2048L, +#endif +#if FPMAX_MAX_EXP >= 4096 + 0x1.0p4096L, +#endif +#if FPMAX_MAX_EXP >= 8192 + 0x1.0p8192L, +#endif +#if FPMAX_MAX_EXP >= 16384 + 0x1.0p16384L +#endif +#if FPMAX_MAX_EXP >= 32768 +#error unsupported FPMAX_MAX_EXP. please increase table +#endif +}; + +#define EXP16_TABLE_SIZE (sizeof(exp16_table)/sizeof(exp16_table[0])) +#define EXP16_TABLE_MAX (1U<<(EXP16_TABLE_SIZE-1)) + +#endif /* __UCLIBC_HAS_HEXADECIMAL_FLOATS__ */ +/*****************************************************************************/ + +#define FPO_ZERO_PAD (0x80 | '0') +#define FPO_STR_WIDTH (0x80 | ' '); +#define FPO_STR_PREC 'p' + +ssize_t _fpmaxtostr(FILE * fp, __fpmax_t x, struct printf_info *info, + __fp_outfunc_t fp_outfunc) attribute_hidden; +ssize_t _fpmaxtostr(FILE * fp, __fpmax_t x, struct printf_info *info, + __fp_outfunc_t fp_outfunc) +{ +#ifdef __UCLIBC_HAS_HEXADECIMAL_FLOATS__ + __fpmax_t lower_bnd; + __fpmax_t upper_bnd = 1e9; +#endif /* __UCLIBC_HAS_HEXADECIMAL_FLOATS__ */ +#ifdef __UCLIBC_HAS_HEXADECIMAL_FLOATS__ + uint_fast32_t base = 10; + const __fpmax_t *power_table; + int dpb = DIGITS_PER_BLOCK; + int ndb = NUM_DIGIT_BLOCKS; + int nd = DECIMAL_DIG; + int sufficient_precision = 0; +#endif /* __UCLIBC_HAS_HEXADECIMAL_FLOATS__ */ +#ifdef __UCLIBC_HAS_GLIBC_DIGIT_GROUPING__ + int num_groups = 0; + int initial_group; /* This does not need to be initialized. */ + int tslen; /* This does not need to be initialized. */ + int nblk2; /* This does not need to be initialized. */ + const char *ts; /* This does not need to be initialized. */ +#endif /* __UCLIBC_HAS_GLIBC_DIGIT_GROUPING__ */ + int round, o_exp; + int exp; + int width, preci; + int cnt; + char *s; + char *e; + intptr_t pc_fwi[3*MAX_CALLS]; + intptr_t *ppc; + intptr_t *ppc_last; +#ifdef __UCLIBC_MJN3_ONLY__ +#warning TODO: The size of exp_buf[] should really be determined by the float constants. +#endif /* __UCLIBC_MJN3_ONLY__ */ + char exp_buf[16]; + char buf[BUF_SIZE]; + char sign_str[6]; /* Last 2 are for 1st digit + nul. */ + char o_mode; + char mode; + + + width = info->width; + preci = info->prec; + mode = info->spec; + + *exp_buf = 'e'; + if ((mode|0x20) == 'a') { +#ifdef __UCLIBC_HAS_HEXADECIMAL_FLOATS__ + *exp_buf = 'p'; + if (preci < 0) { + preci = NUM_HEX_DIGITS; + sufficient_precision = 1; + } +#else + mode += ('g' - 'a'); +#endif + } + + if (preci < 0) { + preci = 6; + } + + *sign_str = '\0'; + if (PRINT_INFO_FLAG_VAL(info,showsign)) { + *sign_str = '+'; + } else if (PRINT_INFO_FLAG_VAL(info,space)) { + *sign_str = ' '; + } + + *(sign_str+1) = 0; + pc_fwi[5] = INF_OFFSET; + if (isnan(x)) { /* First, check for nan. */ + pc_fwi[5] = NAN_OFFSET; + goto INF_NAN; + } + + if (x == 0) { /* Handle 0 now to avoid false positive. */ +#ifdef __UCLIBC_HAVE_SIGNED_ZERO__ + if (zeroisnegative(x)) { /* Handle 'signed' zero. */ + *sign_str = '-'; + } +#endif /* __UCLIBC_HAVE_SIGNED_ZERO__ */ + exp = -1; + goto GENERATE_DIGITS; + } + + if (x < 0) { /* Convert negatives to positives. */ + *sign_str = '-'; + x = -x; + } + + if (__FPMAX_ZERO_OR_INF_CHECK(x)) { /* Inf since zero handled above. */ + INF_NAN: + info->pad = ' '; + ppc = pc_fwi + 6; + pc_fwi[3] = FPO_STR_PREC; + pc_fwi[4] = 3; + if (mode < 'a') { + pc_fwi[5] += 4; + } + pc_fwi[5] = (intptr_t)(fmt + pc_fwi[5]); + goto EXIT_SPECIAL; + } + + { + int i, j; +#ifdef __UCLIBC_MJN3_ONLY__ +#warning TODO: Clean up defines when hexadecimal float notation is unsupported. +#endif /* __UCLIBC_MJN3_ONLY__ */ + +#ifdef __UCLIBC_HAS_HEXADECIMAL_FLOATS__ + + if ((mode|0x20) == 'a') { + lower_bnd = 0x1.0p31L; + upper_bnd = 0x1.0p32L; + power_table = exp16_table; + exp = HEX_DIGITS_PER_BLOCK - 1; + i = EXP16_TABLE_SIZE; + j = EXP16_TABLE_MAX; + dpb = HEX_DIGITS_PER_BLOCK; + ndb = NUM_HEX_DIGIT_BLOCKS; + nd = NUM_HEX_DIGITS; + base = 16; + } else { + lower_bnd = 1e8; + /* upper_bnd = 1e9; */ + power_table = exp10_table; + exp = DIGITS_PER_BLOCK - 1; + i = EXP10_TABLE_SIZE; + j = EXP10_TABLE_MAX; + /* dpb = DIGITS_PER_BLOCK; */ + /* ndb = NUM_DIGIT_BLOCKS; */ + /* base = 10; */ + } + + + +#else /* __UCLIBC_HAS_HEXADECIMAL_FLOATS__ */ + +#define lower_bnd 1e8 +#define upper_bnd 1e9 +#define power_table exp10_table +#define dpb DIGITS_PER_BLOCK +#define base 10 +#define ndb NUM_DIGIT_BLOCKS +#define nd DECIMAL_DIG + + exp = DIGITS_PER_BLOCK - 1; + i = EXP10_TABLE_SIZE; + j = EXP10_TABLE_MAX; + +#endif /* __UCLIBC_HAS_HEXADECIMAL_FLOATS__ */ + + { + int exp_neg = 0; + if (x < lower_bnd) { /* Do we need to scale up or down? */ + exp_neg = 1; + } + + do { + --i; + if (exp_neg) { + if (x * power_table[i] < upper_bnd) { + x *= power_table[i]; + exp -= j; + } + } else { + if (x / power_table[i] >= lower_bnd) { + x /= power_table[i]; + exp += j; + } + } + j >>= 1; + } while (i); + } + } + if (x >= upper_bnd) { /* Handle bad rounding case. */ + x /= power_table[0]; + ++exp; + } + assert(x < upper_bnd); + + GENERATE_DIGITS: + { + int i, j; + s = buf + 2; /* Leave space for '\0' and '0'. */ + i = 0; + do { + uint_fast32_t digit_block = (uint_fast32_t) x; + assert(digit_block < upper_bnd); +#ifdef __UCLIBC_MJN3_ONLY__ +#warning CONSIDER: Can rounding be a problem? +#endif /* __UCLIBC_MJN3_ONLY__ */ + x = (x - digit_block) * upper_bnd; + s += dpb; + j = 0; + do { + s[- ++j] = '0' + (digit_block % base); + digit_block /= base; + } while (j < dpb); + } while (++i < ndb); + } + + /*************************************************************************/ + + if (mode < 'a') { + *exp_buf -= ('a' - 'A'); /* e->E and p->P */ + mode += ('a' - 'A'); + } + + o_mode = mode; + if ((mode == 'g') && (preci > 0)){ + --preci; + } + round = preci; + + if (mode == 'f') { + round += exp; + if (round < -1) { + memset(buf, '0', DECIMAL_DIG); /* OK, since 'f' -> decimal case. */ + exp = -1; + round = -1; + } + } + + s = buf; + *s++ = 0; /* Terminator for rounding and 0-triming. */ + *s = '0'; /* Space to round. */ + + { + int i; + i = 0; + e = s + nd + 1; + if (round < nd) { + e = s + round + 2; + if (*e >= '0' + (base/2)) { /* NOTE: We always round away from 0! */ + i = 1; + } + } + + do { /* Handle rounding and trim trailing 0s. */ + *--e += i; /* Add the carry. */ + } while ((*e == '0') || (*e > '0' - 1 + base)); + } + +#ifdef __UCLIBC_HAS_HEXADECIMAL_FLOATS__ + if ((mode|0x20) == 'a') { + char *q; + + for (q = e ; *q ; --q) { + if (*q > '9') { + *q += (*exp_buf - ('p' - 'a') - '9' - 1); + } + } + + if (e > s) { + exp *= 4; /* Change from base 16 to base 2. */ + } + } +#endif /* __UCLIBC_HAS_HEXADECIMAL_FLOATS__ */ + + o_exp = exp; + if (e <= s) { /* We carried into an extra digit. */ + ++o_exp; + e = s; /* Needed if all 0s. */ + } else { + ++s; + } + *++e = 0; /* Terminating nul char. */ + + if ((mode == 'g') && ((o_exp >= -4) && (o_exp <= round))) { + mode = 'f'; + preci = round - o_exp; + } + + exp = o_exp; + if (mode != 'f') { + o_exp = 0; + } + + if (o_exp < 0) { /* Exponent is < 0, so */ + *--s = '0'; /* fake the first 0 digit. */ + } + + pc_fwi[3] = FPO_ZERO_PAD; + pc_fwi[4] = 1; + pc_fwi[5] = (intptr_t)(sign_str + 4); + sign_str[4] = *s++; + sign_str[5] = 0; + ppc = pc_fwi + 6; + + { + int i = e - s; /* Total digits is 'i'. */ + if (o_exp >= 0) { +#ifdef __UCLIBC_HAS_GLIBC_DIGIT_GROUPING__ + + const char *p; + + if (PRINT_INFO_FLAG_VAL(info,group) + && *(p = __UCLIBC_CURLOCALE->grouping) + ) { + int nblk1; + + nblk2 = nblk1 = *p; + if (*++p) { + nblk2 = *p; + assert(!*++p); + } + + if (o_exp >= nblk1) { + num_groups = (o_exp - nblk1) / nblk2 + 1; + initial_group = (o_exp - nblk1) % nblk2; + +#ifdef __UCLIBC_HAS_WCHAR__ + if (PRINT_INFO_FLAG_VAL(info,wide)) { + /* _fp_out_wide() will fix this up. */ + ts = fmt + THOUSEP_OFFSET; + tslen = 1; + } else { +#endif /* __UCLIBC_HAS_WCHAR__ */ + ts = __UCLIBC_CURLOCALE->thousands_sep; + tslen = __UCLIBC_CURLOCALE->thousands_sep_len; +#ifdef __UCLIBC_HAS_WCHAR__ + } +#endif /* __UCLIBC_HAS_WCHAR__ */ + + width -= num_groups * tslen; + } + } + + +#endif /* __UCLIBC_HAS_GLIBC_DIGIT_GROUPING__ */ + ppc[0] = FPO_STR_PREC; + ppc[2] = (intptr_t)(s); + if (o_exp >= i) { /* all digit(s) left of decimal */ + ppc[1] = i; + ppc += 3; + o_exp -= i; + i = 0; + if (o_exp>0) { /* have 0s left of decimal */ + ppc[0] = FPO_ZERO_PAD; + ppc[1] = o_exp; + ppc[2] = (intptr_t)(fmt + EMPTY_STRING_OFFSET); + ppc += 3; + } + } else if (o_exp > 0) { /* decimal between digits */ + ppc[1] = o_exp; + ppc += 3; + s += o_exp; + i -= o_exp; + } + o_exp = -1; + } + + if (PRINT_INFO_FLAG_VAL(info,alt) + || (i) + || ((o_mode != 'g') +#ifdef __UCLIBC_HAS_HEXADECIMAL_FLOATS__ + && (o_mode != 'a') +#endif /* __UCLIBC_HAS_HEXADECIMAL_FLOATS__ */ + && (preci > 0)) + ) { + ppc[0] = FPO_STR_PREC; +#ifdef __LOCALE_C_ONLY + ppc[1] = 1; + ppc[2] = (intptr_t)(fmt + DECPT_OFFSET); +#else /* __LOCALE_C_ONLY */ +#ifdef __UCLIBC_HAS_WCHAR__ + if (PRINT_INFO_FLAG_VAL(info,wide)) { + /* _fp_out_wide() will fix this up. */ + ppc[1] = 1; + ppc[2] = (intptr_t)(fmt + DECPT_OFFSET); + } else { +#endif /* __UCLIBC_HAS_WCHAR__ */ + ppc[1] = __UCLIBC_CURLOCALE->decimal_point_len; + ppc[2] = (intptr_t)(__UCLIBC_CURLOCALE->decimal_point); +#ifdef __UCLIBC_HAS_WCHAR__ + } +#endif /* __UCLIBC_HAS_WCHAR__ */ +#endif /* __LOCALE_C_ONLY */ + ppc += 3; + } + + if (++o_exp < 0) { /* Have 0s right of decimal. */ + ppc[0] = FPO_ZERO_PAD; + ppc[1] = -o_exp; + ppc[2] = (intptr_t)(fmt + EMPTY_STRING_OFFSET); + ppc += 3; + } + if (i) { /* Have digit(s) right of decimal. */ + ppc[0] = FPO_STR_PREC; + ppc[1] = i; + ppc[2] = (intptr_t)(s); + ppc += 3; + } + + if (((o_mode != 'g') || PRINT_INFO_FLAG_VAL(info,alt)) +#ifdef __UCLIBC_HAS_HEXADECIMAL_FLOATS__ + && !sufficient_precision +#endif /* __UCLIBC_HAS_HEXADECIMAL_FLOATS__ */ + ) { + i -= o_exp; + if (i < preci) { /* Have 0s right of digits. */ + i = preci - i; + ppc[0] = FPO_ZERO_PAD; + ppc[1] = i; + ppc[2] = (intptr_t)(fmt + EMPTY_STRING_OFFSET); + ppc += 3; + } + } + } + + /* Build exponent string. */ + if (mode != 'f') { + char *p = exp_buf + sizeof(exp_buf); + int j; + char exp_char = *exp_buf; + char exp_sign = '+'; +#ifdef __UCLIBC_HAS_HEXADECIMAL_FLOATS__ + int min_exp_dig_plus_2 = ((o_mode != 'a') ? (2+2) : (2+1)); +#else /* __UCLIBC_HAS_HEXADECIMAL_FLOATS__ */ +#define min_exp_dig_plus_2 (2+2) +#endif /* __UCLIBC_HAS_HEXADECIMAL_FLOATS__ */ + + if (exp < 0) { + exp_sign = '-'; + exp = -exp; + } + + *--p = 0; /* nul-terminate */ + j = 2; /* Count exp_char and exp_sign. */ + do { + *--p = '0' + (exp % 10); + exp /= 10; + } while ((++j < min_exp_dig_plus_2) || exp); /* char+sign+mindigits */ + *--p = exp_sign; + *--p = exp_char; + + ppc[0] = FPO_STR_PREC; + ppc[1] = j; + ppc[2] = (intptr_t)(p); + ppc += 3; + } + + EXIT_SPECIAL: + { + int i; + ppc_last = ppc; + ppc = pc_fwi + 4; /* Need width fields starting with second. */ + do { + width -= *ppc; + ppc += 3; + } while (ppc < ppc_last); + + ppc = pc_fwi; + ppc[0] = FPO_STR_WIDTH; + ppc[1] = i = ((*sign_str) != 0); + ppc[2] = (intptr_t) sign_str; + +#ifdef __UCLIBC_HAS_HEXADECIMAL_FLOATS__ + if (((mode|0x20) == 'a') && (pc_fwi[3] >= 16)) { /* Hex sign handling. */ + /* Hex and not inf or nan, so prefix with 0x. */ + char *h = sign_str + i; + *h = '0'; + *++h = 'x' - 'p' + *exp_buf; + *++h = 0; + ppc[1] = (i += 2); + } +#endif /* __UCLIBC_HAS_HEXADECIMAL_FLOATS__ */ + + if ((width -= i) > 0) { + if (PRINT_INFO_FLAG_VAL(info,left)) { /* Left-justified. */ + ppc_last[0] = FPO_STR_WIDTH; + ppc_last[1] = width; + ppc_last[2] = (intptr_t)(fmt + EMPTY_STRING_OFFSET); + ppc_last += 3; + } else if (info->pad == '0') { /* 0 padding */ + ppc[4] += width; /* Pad second field. */ + } else { + ppc[1] += width; /* Pad first (sign) field. */ + } + } + + cnt = 0; + } + + do { +#ifdef __UCLIBC_HAS_GLIBC_DIGIT_GROUPING__ + + if ((ppc == pc_fwi + 6) && num_groups) { + const char *gp = (const char *) ppc[2]; + int len = ppc[1]; + int blk = initial_group; + + cnt += num_groups * tslen; /* Adjust count now for sep chars. */ + +/* __printf("\n"); */ + do { + if (!blk) { /* Initial group could be 0 digits long! */ + blk = nblk2; + } else if (len >= blk) { /* Enough digits for a group. */ +/* __printf("norm: len=%d blk=%d \"%.*s\"\n", len, blk, blk, gp); */ + if (fp_outfunc(fp, *ppc, blk, (intptr_t) gp) != blk) { + return -1; + } + assert(gp); + if (*gp) { + gp += blk; + } + len -= blk; + } else { /* Transition to 0s. */ +/* __printf("trans: len=%d blk=%d \"%.*s\"\n", len, blk, len, gp); */ + if (len) { +/* __printf("len\n"); */ + if (fp_outfunc(fp, *ppc, len, (intptr_t) gp) != len) { + return -1; + } + gp += len; + } + + if (ppc[3] == FPO_ZERO_PAD) { /* Need to group 0s */ +/* __printf("zeropad\n"); */ + cnt += ppc[1]; + ppc += 3; + gp = (const char *) ppc[2]; + blk -= len; /* blk > len, so blk still > 0. */ + len = ppc[1]; + continue; /* Don't decrement num_groups here. */ + } else { + assert(num_groups == 0); + break; + } + } + + if (num_groups <= 0) { + break; + } + --num_groups; + + if (fp_outfunc(fp, FPO_STR_PREC, tslen, (intptr_t) ts) != tslen) { + return -1; + } + blk = nblk2; + +/* __printf("num_groups=%d blk=%d\n", num_groups, blk); */ + + } while (1); + } else + +#endif /* __UCLIBC_HAS_GLIBC_DIGIT_GROUPING__ */ + { /* NOTE: Remember 'else' above! */ + if (fp_outfunc(fp, *ppc, ppc[1], ppc[2]) != ppc[1]) { + return -1; + } + } + + cnt += ppc[1]; + ppc += 3; + } while (ppc < ppc_last); + + return cnt; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_fwrite.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_fwrite.c new file mode 100644 index 00000000..47860afb --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_fwrite.c @@ -0,0 +1,79 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + + +#ifdef __STDIO_BUFFERS + +/* Either buffer data or (commit buffer if necessary and) write. */ + +size_t attribute_hidden __stdio_fwrite(const unsigned char * __restrict buffer, + size_t bytes, + register FILE * __restrict stream) +{ + size_t pending; + const unsigned char *p; + + __STDIO_STREAM_VALIDATE(stream); + assert(__STDIO_STREAM_IS_WRITING(stream)); + assert(buffer); + assert(bytes); + + if (!__STDIO_STREAM_IS_NBF(stream)) { /* FBF or LBF. */ +#ifdef __UCLIBC_MJN3_ONLY__ +#warning CONSIDER: Try to consolidate some of the code? +#endif + if (__STDIO_STREAM_IS_FAKE_VSNPRINTF(stream)) { + pending = __STDIO_STREAM_BUFFER_WAVAIL(stream); + if (pending > bytes) { + pending = bytes; + } + memcpy(stream->__bufpos, buffer, pending); + stream->__bufpos += pending; + __STDIO_STREAM_VALIDATE(stream); + return bytes; + } + +/* RETRY: */ + if (bytes <= __STDIO_STREAM_BUFFER_WAVAIL(stream)) { + memcpy(stream->__bufpos, buffer, bytes); + stream->__bufpos += bytes; + if (__STDIO_STREAM_IS_LBF(stream) + && memrchr(buffer, '\n', bytes) /* Search backwards. */ + ) { + if ((pending = __STDIO_COMMIT_WRITE_BUFFER(stream)) > 0) { + if (pending > bytes) { + pending = bytes; + } + buffer += (bytes - pending); + if ((p = memchr(buffer, '\n', pending)) != NULL) { + pending = (buffer + pending) - p; + bytes -= pending; + stream->__bufpos -= pending; + } + } + } + __STDIO_STREAM_VALIDATE(stream); + return bytes; + } + /* FBF or LBF and not enough space in buffer. */ + if (__STDIO_STREAM_BUFFER_WUSED(stream)) { /* Buffered data. */ + if (__STDIO_COMMIT_WRITE_BUFFER(stream)) { /* Commit failed! */ + return 0; + } +#ifdef __UCLIBC_MJN3_ONLY__ +#warning CONSIDER: Do we want to try again if data now fits in buffer? +#endif +/* goto RETRY; */ + } + } + + return __stdio_WRITE(stream, buffer, bytes); +} + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_load_inttype.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_load_inttype.c new file mode 100644 index 00000000..057f5f25 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_load_inttype.c @@ -0,0 +1,67 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" +#include + +uintmax_t _load_inttype(int desttype, register const void *src, int uflag) attribute_hidden; +uintmax_t _load_inttype(int desttype, register const void *src, int uflag) +{ + if (uflag >= 0) { /* unsigned */ +#if LONG_MAX != INT_MAX + if (desttype & (PA_FLAG_LONG|PA_FLAG_LONG_LONG)) { +#ifdef LLONG_MAX + if (desttype == PA_FLAG_LONG_LONG) { + return *((unsigned long long int *) src); + } +#endif + return *((unsigned long int *) src); + } +#else /* LONG_MAX != INT_MAX */ +#ifdef LLONG_MAX + if (desttype & PA_FLAG_LONG_LONG) { + return *((unsigned long long int *) src); + } +#endif +#endif /* LONG_MAX != INT_MAX */ + { + unsigned int x; + x = *((unsigned int *) src); + if (desttype == __PA_FLAG_CHAR) x = (unsigned char) x; +#if SHRT_MAX != INT_MAX + if (desttype == PA_FLAG_SHORT) x = (unsigned short int) x; +#endif + return x; + } + } else { /* signed */ +#if LONG_MAX != INT_MAX + if (desttype & (PA_FLAG_LONG|PA_FLAG_LONG_LONG)) { +#ifdef LLONG_MAX + if (desttype == PA_FLAG_LONG_LONG) { + return *((long long int *) src); + } +#endif + return *((long int *) src); + } +#else /* LONG_MAX != INT_MAX */ +#ifdef LLONG_MAX + if (desttype & PA_FLAG_LONG_LONG) { + return *((long long int *) src); + } +#endif +#endif /* LONG_MAX != INT_MAX */ + { + int x; + x = *((int *) src); + if (desttype == __PA_FLAG_CHAR) x = (char) x; +#if SHRT_MAX != INT_MAX + if (desttype == PA_FLAG_SHORT) x = (short int) x; +#endif + return x; + } + } +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_ppfs_init.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_ppfs_init.c new file mode 100644 index 00000000..80d8aeb9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_ppfs_init.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define L__ppfs_init +#include "_vfprintf.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_ppfs_parsespec.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_ppfs_parsespec.c new file mode 100644 index 00000000..a3e29880 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_ppfs_parsespec.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define L__ppfs_parsespec +#include "_vfprintf.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_ppfs_prepargs.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_ppfs_prepargs.c new file mode 100644 index 00000000..a6efbf46 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_ppfs_prepargs.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define L__ppfs_prepargs +#include "_vfprintf.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_ppfs_setargs.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_ppfs_setargs.c new file mode 100644 index 00000000..41214d99 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_ppfs_setargs.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define L__ppfs_setargs +#include "_vfprintf.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_rfill.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_rfill.c new file mode 100644 index 00000000..d61b1a9f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_rfill.c @@ -0,0 +1,45 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning CONSIDER: Do we really need a seperate rfill function? +#endif + +#ifdef __STDIO_BUFFERS + +/* Read some data into the buffer. + * Returns number of bytes read into the buffer. + * If 0 is returned, then either EOF or ERROR. + * Side effects are those of _stdio_READ. + */ + +size_t attribute_hidden __stdio_rfill(register FILE *__restrict stream) +{ + size_t rv; + + __STDIO_STREAM_VALIDATE(stream); + assert(stream->__filedes >= -1); + assert(__STDIO_STREAM_IS_READING(stream)); + assert(!__STDIO_STREAM_BUFFER_RAVAIL(stream)); /* Buffer must be empty. */ + assert(__STDIO_STREAM_BUFFER_SIZE(stream)); /* Must have a buffer. */ + assert(!(stream->__modeflags & __FLAG_UNGOT)); +#ifdef __UCLIBC_HAS_STDIO_GETC_MACRO__ + assert(stream->__bufgetc_u == stream->__bufstart); +#endif + + rv = __stdio_READ(stream, stream->__bufstart, + stream->__bufend - stream->__bufstart); + stream->__bufpos = stream->__bufstart; + stream->__bufread = stream->__bufstart + rv; + + __STDIO_STREAM_VALIDATE(stream); + return rv; +} + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_scanf.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_scanf.c new file mode 100644 index 00000000..34c1c9ab --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_scanf.c @@ -0,0 +1,2221 @@ +/* Copyright (C) 2002-2004 Manuel Novoa III + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* Aug 1, 2003 + * New *scanf implementation with lots of bug fixes and *wscanf support. + * Also now optionally supports hexadecimal float notation, positional + * args, and glibc locale-specific digit grouping. Should now be + * standards compliant. + * + * Aug 18, 2003 + * Bug fix: scanf %lc,%ls,%l[ would always set mb_fail on eof or error, + * even when just starting a new mb char. + * Bug fix: wscanf would incorrectly unget in certain situations. + * + * Sep 5, 2003 + * Bug fix: store flag wasn't respected if no positional args. + * Implement vs{n}scanf for the non-buffered stdio no-wchar case. + * + * Sep 13, 2003 + * Bug fix: Fix a problem reported by Atsushi Nemoto + * for environments where long and long long are the same. + * + * Sep 21, 2003 + * Ugh... EOF handling by scanf was completely broken. :-( Regretably, + * I got my mind fixed in one mode and didn't comply with the standards. + * Things should be fixed now, but comparision testing is difficult when + * glibc's scanf is broken and they stubbornly refuse to even acknowledge + * that it is... even when confronted by specific examples from the C99 + * standards and from an official C standard defect report. + */ + +#define _ISOC99_SOURCE /* for LLONG_MAX primarily... */ +#include +#include "_stdio.h" +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __UCLIBC_HAS_WCHAR__ +#include +#include +#include +#endif /* __UCLIBC_HAS_WCHAR__ */ + +#include +#include + +#include +#include + +#ifdef __UCLIBC_HAS_THREADS__ +#include +#include +#endif /* __UCLIBC_HAS_THREADS__ */ + +#ifdef __UCLIBC_HAS_FLOATS__ +#include +#include +#endif /* __UCLIBC_HAS_FLOATS__ */ + +#ifdef __UCLIBC_HAS_SCANF_GLIBC_A_FLAG__ +#ifdef L_vfscanf +/* only emit this once */ +#warning Forcing undef of __UCLIBC_HAS_SCANF_GLIBC_A_FLAG__ until implemented! +#endif +#undef __UCLIBC_HAS_SCANF_GLIBC_A_FLAG__ +#endif + +#undef __STDIO_HAS_VSSCANF +#if defined(__STDIO_BUFFERS) || !defined(__UCLIBC_HAS_WCHAR__) || defined(__UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__) +#define __STDIO_HAS_VSSCANF 1 + +#if !defined(__STDIO_BUFFERS) && !defined(__UCLIBC_HAS_WCHAR__) +typedef struct { + FILE f; + unsigned char *bufread; /* pointer to 1 past end of buffer */ + unsigned char *bufpos; +} __FILE_vsscanf; +#endif + +#endif + +extern void _store_inttype(void *dest, int desttype, uintmax_t val); + +#if defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX) + +extern unsigned long long +_stdlib_strto_ll(register const char * __restrict str, + char ** __restrict endptr, int base, int sflag); +#if (ULLONG_MAX == UINTMAX_MAX) +#define STRTOUIM(s,e,b,sf) _stdlib_strto_ll(s,e,b,sf) +#endif + +#else /* defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX) */ + +extern unsigned long +_stdlib_strto_l(register const char * __restrict str, + char ** __restrict endptr, int base, int sflag); + +#if (ULONG_MAX == UINTMAX_MAX) +#define STRTOUIM(s,e,b,sf) _stdlib_strto_l(s,e,b,sf) +#endif + +#endif /* defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX) */ + +#ifndef STRTOUIM +#error STRTOUIM conversion function is undefined! +#endif + +/**********************************************************************/ + +/* The standards require EOF < 0. */ +#if EOF >= CHAR_MIN +#define __isdigit_char_or_EOF(C) __isdigit_char((C)) +#else +#define __isdigit_char_or_EOF(C) __isdigit_int((C)) +#endif + +/**********************************************************************/ +#ifdef L_fscanf + +int fscanf(FILE * __restrict stream, const char * __restrict format, ...) +{ + va_list arg; + int rv; + + va_start(arg, format); + rv = vfscanf(stream, format, arg); + va_end(arg); + + return rv; +} +libc_hidden_def(fscanf) + +#endif +/**********************************************************************/ +#ifdef L_scanf + +int scanf(const char * __restrict format, ...) +{ + va_list arg; + int rv; + + va_start(arg, format); + rv = vfscanf(stdin, format, arg); + va_end(arg); + + return rv; +} + +#endif +/**********************************************************************/ +#ifdef L_sscanf + +#ifdef __STDIO_HAS_VSSCANF + +int sscanf(const char * __restrict str, const char * __restrict format, ...) +{ + va_list arg; + int rv; + + va_start(arg, format); + rv = vsscanf(str, format, arg); + va_end(arg); + + return rv; +} +libc_hidden_def(sscanf) + +#else /* __STDIO_HAS_VSSCANF */ +#warning Skipping sscanf since no vsscanf! +#endif /* __STDIO_HAS_VSSCANF */ + +#endif +/**********************************************************************/ +#ifdef L_vscanf + +int vscanf(const char * __restrict format, va_list arg) +{ + return vfscanf(stdin, format, arg); +} +libc_hidden_def(vscanf) + +#endif +/**********************************************************************/ +#ifdef L_vsscanf + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning WISHLIST: Implement vsscanf for non-buf and no custom stream case. +#endif /* __UCLIBC_MJN3_ONLY__ */ + +#ifdef __STDIO_BUFFERS + +int vsscanf(__const char *sp, __const char *fmt, va_list ap) +{ + FILE f; + +/* __STDIO_STREAM_RESET_GCS(&f); */ +#ifdef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ + f.__cookie = &(f.__filedes); + f.__gcs.read = NULL; + f.__gcs.write = NULL; + f.__gcs.seek = NULL; + f.__gcs.close = NULL; +#endif + + f.__filedes = __STDIO_STREAM_FAKE_VSSCANF_FILEDES; + f.__modeflags = (__FLAG_NARROW|__FLAG_READONLY|__FLAG_READING); + +#ifdef __UCLIBC_HAS_WCHAR__ + f.__ungot_width[0] = 0; +#endif +#ifdef __STDIO_MBSTATE + __INIT_MBSTATE(&(f.__state)); +#endif + +#ifdef __UCLIBC_HAS_THREADS__ + f.__user_locking = 1; /* Set user locking. */ + STDIO_INIT_MUTEX(f.__lock); +#endif + f.__nextopen = NULL; + + /* Set these last since __bufgetc initialization depends on + * __user_locking and only gets set if user locking is on. */ + f.__bufstart = + f.__bufpos = (unsigned char *) ((void *) sp); + f.__bufread = + f.__bufend = f.__bufstart + strlen(sp); + __STDIO_STREAM_ENABLE_GETC(&f); + __STDIO_STREAM_DISABLE_PUTC(&f); + + return vfscanf(&f, fmt, ap); +} +libc_hidden_def(vsscanf) + +#elif !defined(__UCLIBC_HAS_WCHAR__) + +int vsscanf(__const char *sp, __const char *fmt, va_list ap) +{ + __FILE_vsscanf f; + + f.bufpos = (unsigned char *) ((void *) sp); + f.bufread = f.bufpos + strlen(sp); + +/* __STDIO_STREAM_RESET_GCS(&f.f); */ +#ifdef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ + f.f.__cookie = &(f.f.__filedes); + f.f.__gcs.read = NULL; + f.f.__gcs.write = NULL; + f.f.__gcs.seek = NULL; + f.f.__gcs.close = NULL; +#endif + + f.f.__filedes = __STDIO_STREAM_FAKE_VSSCANF_FILEDES_NB; + f.f.__modeflags = (__FLAG_NARROW|__FLAG_READONLY|__FLAG_READING); + +/* #ifdef __UCLIBC_HAS_WCHAR__ */ +/* f.f.__ungot_width[0] = 0; */ +/* #endif */ +#ifdef __STDIO_MBSTATE +#error __STDIO_MBSTATE is defined! +/* __INIT_MBSTATE(&(f.f.__state)); */ +#endif + +#ifdef __UCLIBC_HAS_THREADS__ + f.f.__user_locking = 1; /* Set user locking. */ + STDIO_INIT_MUTEX(f.f.__lock); +#endif + f.f.__nextopen = NULL; + + return vfscanf(&f.f, fmt, ap); +} +libc_hidden_def(vsscanf) + +#elif defined(__UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__) + +int vsscanf(__const char *sp, __const char *fmt, va_list ap) +{ + FILE *f; + int rv = EOF; + + if ((f = fmemopen((char *)sp, strlen(sp), "r")) != NULL) { + rv = vfscanf(f, fmt, ap); + fclose(f); + } + + return rv; +} +libc_hidden_def(vsscanf) + +#else +#warning Skipping vsscanf since no buffering, no custom streams, and wchar enabled! +#ifdef __STDIO_HAS_VSSCANF +#error WHOA! __STDIO_HAS_VSSCANF is defined! +#endif +#endif + +#endif +/**********************************************************************/ +#ifdef L_fwscanf + +int fwscanf(FILE * __restrict stream, const wchar_t * __restrict format, ...) +{ + va_list arg; + int rv; + + va_start(arg, format); + rv = vfwscanf(stream, format, arg); + va_end(arg); + + return rv; +} + +#endif +/**********************************************************************/ +#ifdef L_wscanf + +int wscanf(const wchar_t * __restrict format, ...) +{ + va_list arg; + int rv; + + va_start(arg, format); + rv = vfwscanf(stdin, format, arg); + va_end(arg); + + return rv; +} + +#endif +/**********************************************************************/ +#ifdef L_swscanf + +#ifdef __STDIO_BUFFERS + +int swscanf(const wchar_t * __restrict str, const wchar_t * __restrict format, + ...) +{ + va_list arg; + int rv; + + va_start(arg, format); + rv = vswscanf(str, format, arg); + va_end(arg); + + return rv; +} +#else /* __STDIO_BUFFERS */ +#warning Skipping swscanf since no buffering! +#endif /* __STDIO_BUFFERS */ + +#endif +/**********************************************************************/ +#ifdef L_vwscanf + +int vwscanf(const wchar_t * __restrict format, va_list arg) +{ + return vfwscanf(stdin, format, arg); +} + +#endif +/**********************************************************************/ +#ifdef L_vswscanf + +#ifdef __STDIO_BUFFERS + +int vswscanf(const wchar_t * __restrict str, const wchar_t * __restrict format, + va_list arg) +{ + FILE f; + + f.__bufstart = + f.__bufpos = (char *) str; + f.__bufread = + f.__bufend = (char *)(str + wcslen(str)); + __STDIO_STREAM_DISABLE_GETC(&f); + __STDIO_STREAM_DISABLE_PUTC(&f); + +/* __STDIO_STREAM_RESET_GCS(&f); */ +#ifdef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ + f.__cookie = &(f.__filedes); + f.__gcs.read = NULL; + f.__gcs.write = NULL; + f.__gcs.seek = NULL; + f.__gcs.close = NULL; +#endif + + f.__filedes = __STDIO_STREAM_FAKE_VSWSCANF_FILEDES; + f.__modeflags = (__FLAG_WIDE|__FLAG_READONLY|__FLAG_READING); + +#ifdef __UCLIBC_HAS_WCHAR__ + f.__ungot_width[0] = 0; +#endif /* __UCLIBC_HAS_WCHAR__ */ +#ifdef __STDIO_MBSTATE + __INIT_MBSTATE(&(f.__state)); +#endif /* __STDIO_MBSTATE */ + +#ifdef __UCLIBC_HAS_THREADS__ + f.__user_locking = 1; /* Set user locking. */ + STDIO_INIT_MUTEX(f.__lock); +#endif + f.__nextopen = NULL; + + return vfwscanf(&f, format, arg); +} +libc_hidden_def(vswscanf) +#else /* __STDIO_BUFFERS */ +#warning Skipping vswscanf since no buffering! +#endif /* __STDIO_BUFFERS */ + +#endif +/**********************************************************************/ +/**********************************************************************/ + + + +/* float layout 0123456789012345678901 repeat n for "l[" */ +#define SPEC_CHARS "npxXoudifFeEgGaACSncs[" +/* npxXoudif eEgG CS cs[ */ + +/* NOTE: Ordering is important! In particular, CONV_LEFTBRACKET + * must immediately precede CONV_c. */ + +enum { + CONV_n = 0, + CONV_p, + CONV_x, CONV_X, CONV_o, CONV_u, CONV_d, CONV_i, + CONV_f, CONV_F, CONV_e, CONV_E, CONV_g, CONV_G, CONV_a, CONV_A, + CONV_C, CONV_S, CONV_LEFTBRACKET, CONV_c, CONV_s, CONV_leftbracket, + CONV_percent, CONV_whitespace /* not in SPEC_* and no flags */ +}; + +#ifdef __UCLIBC_HAS_FLOATS__ +#ifdef __UCLIBC_HAS_HEXADECIMAL_FLOATS__ +/* p x X o u d i f F e E g G a A */ +#define SPEC_BASE { 16, 16, 16, 8, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0 } +#else +/* p x X o u d i f F e E g G a A */ +#define SPEC_BASE { 16, 16, 16, 8, 10, 10, 0, 10, 10, 10, 10, 10, 10, 10, 10 } +#endif +#else /* __UCLIBC_HAS_FLOATS__ */ +/* p x X o u d i f F e E g G a A */ +#define SPEC_BASE { 16, 16, 16, 8, 10, 10, 0 } +#endif /* __UCLIBC_HAS_FLOATS__ */ + +#ifdef __UCLIBC_MJN3_ONLY__ +#ifdef L_vfscanf +/* emit once */ +#warning CONSIDER: Add a '0' flag to eat 0 padding when grouping? +#endif +#endif /* __UCLIBC_MJN3_ONLY__ */ + +#define SPEC_FLAGS "*'I" + +enum { + FLAG_SURPRESS = 0x10, /* MUST BE 1ST!! See DO_FLAGS. */ + FLAG_THOUSANDS = 0x20, + FLAG_I18N = 0x40, /* only works for d, i, u */ + FLAG_MALLOC = 0x80, /* only works for s, S, and [ (and l[)*/ +}; + + +#define SPEC_RANGES { CONV_n, CONV_p, CONV_i, CONV_A, \ + CONV_C, CONV_LEFTBRACKET, \ + CONV_c, CONV_leftbracket } + +/* Note: We treat L and ll as synonymous... for ints and floats. */ + +#define SPEC_ALLOWED_FLAGS { \ + /* n */ (0x0f|FLAG_SURPRESS), \ + /* p */ ( 0|FLAG_SURPRESS), \ + /* oxXudi */ (0x0f|FLAG_SURPRESS|FLAG_THOUSANDS|FLAG_I18N), \ + /* fFeEgGaA */ (0x0c|FLAG_SURPRESS|FLAG_THOUSANDS|FLAG_I18N), \ + /* C */ ( 0|FLAG_SURPRESS), \ + /* S and l[ */ ( 0|FLAG_SURPRESS|FLAG_MALLOC), \ + /* c */ (0x04|FLAG_SURPRESS), \ + /* s and [ */ (0x04|FLAG_SURPRESS|FLAG_MALLOC), \ +} + + +/**********************************************************************/ +/* + * In order to ease translation to what arginfo and _print_info._flags expect, + * we map: 0:int 1:char 2:longlong 4:long 8:short + * and then _flags |= (((q << 7) + q) & 0x701) and argtype |= (_flags & 0x701) + */ + +/* TODO -- Fix the table below to take into account stdint.h. */ +/* #ifndef LLONG_MAX */ +/* #error fix QUAL_CHARS for no long long! Affects 'L', 'j', 'q', 'll'. */ +/* #else */ +/* #if LLONG_MAX != INTMAX_MAX */ +/* #error fix QUAL_CHARS intmax_t entry 'j'! */ +/* #endif */ +/* #endif */ + +#ifdef PDS +#error PDS already defined! +#endif +#ifdef SS +#error SS already defined! +#endif +#ifdef IMS +#error IMS already defined! +#endif + +#if PTRDIFF_MAX == INT_MAX +#define PDS 0 +#elif PTRDIFF_MAX == LONG_MAX +#define PDS 4 +#elif defined(LLONG_MAX) && (PTRDIFF_MAX == LLONG_MAX) +#define PDS 8 +#else +#error fix QUAL_CHARS ptrdiff_t entry 't'! +#endif + +#if SIZE_MAX == UINT_MAX +#define SS 0 +#elif SIZE_MAX == ULONG_MAX +#define SS 4 +#elif defined(LLONG_MAX) && (SIZE_MAX == ULLONG_MAX) +#define SS 8 +#else +#error fix QUAL_CHARS size_t entries 'z', 'Z'! +#endif + +#if INTMAX_MAX == INT_MAX +#define IMS 0 +#elif INTMAX_MAX == LONG_MAX +#define IMS 4 +#elif defined(LLONG_MAX) && (INTMAX_MAX == LLONG_MAX) +#define IMS 8 +#else +#error fix QUAL_CHARS ptrdiff_t entry 't'! +#endif + +#define QUAL_CHARS { \ + /* j:(u)intmax_t z:(s)size_t t:ptrdiff_t \0:int q:long_long */ \ + 'h', 'l', 'L', 'j', 'z', 't', 'q', 0, \ + 2, 4, 8, IMS, SS, PDS, 8, 0, /* TODO -- fix!!! */ \ + 1, 8 \ +} + + +/**********************************************************************/ + +#ifdef L_vfwscanf +/* FIXME: "warning: the right operand of ">" changes sign when promoted" */ +#if WINT_MIN > EOF +#error Unfortunately, we currently need wint_t to be able to store EOF. Sorry. +#endif +#define W_EOF WEOF +#define Wint wint_t +#define Wchar wchar_t +#define Wuchar __uwchar_t +#define ISSPACE(C) iswspace((C)) +#define VFSCANF vfwscanf +#define GETC(SC) (SC)->sc_getc((SC)) +#else +typedef unsigned char __uchar_t; +#define W_EOF EOF +#define Wint int +#define Wchar char +#define Wuchar __uchar_t +#define ISSPACE(C) isspace((C)) +#define VFSCANF vfscanf +#ifdef __UCLIBC_HAS_WCHAR__ +#define GETC(SC) (SC)->sc_getc((SC)) +#else /* __UCLIBC_HAS_WCHAR__ */ +#define GETC(SC) getc_unlocked((SC)->fp) +#endif /* __UCLIBC_HAS_WCHAR__ */ +#endif + +struct scan_cookie { + Wint cc; + Wint ungot_char; + FILE *fp; + int nread; + int width; + +#ifdef __UCLIBC_HAS_WCHAR__ + wchar_t app_ungot; /* Match FILE struct member type. */ + unsigned char ungot_wchar_width; +#else /* __UCLIBC_HAS_WCHAR__ */ + unsigned char app_ungot; /* Match FILE struct member type. */ +#endif /* __UCLIBC_HAS_WCHAR__ */ + + char ungot_flag; + +#ifdef __UCLIBC_HAS_WCHAR__ + char ungot_wflag; /* vfwscanf */ + char mb_fail; /* vfscanf */ + mbstate_t mbstate; /* vfscanf */ + wint_t wc; + wint_t ungot_wchar; /* to support __scan_getc */ + int (*sc_getc)(struct scan_cookie *); +#endif /* __UCLIBC_HAS_WCHAR__ */ + +#ifdef __UCLIBC_HAS_GLIBC_DIGIT_GROUPING__ + const char *grouping; + const unsigned char *thousands_sep; + int tslen; +#ifdef __UCLIBC_HAS_WCHAR__ + wchar_t thousands_sep_wc; +#endif /* __UCLIBC_HAS_WCHAR__ */ +#endif /* __UCLIBC_HAS_GLIBC_DIGIT_GROUPING__ */ + +#ifdef __UCLIBC_HAS_FLOATS__ + const unsigned char *decpt; + int decpt_len; +#ifdef __UCLIBC_HAS_WCHAR__ + wchar_t decpt_wc; +#endif /* __UCLIBC_HAS_WCHAR__ */ + const unsigned char *fake_decpt; +#endif /* __UCLIBC_HAS_FLOATS__ */ + +}; + +typedef struct { +#if defined(NL_ARGMAX) && (NL_ARGMAX > 0) +#if NL_ARGMAX > 10 +#warning NL_ARGMAX > 10, and space is allocated on the stack for positional args. +#endif + void *pos_args[NL_ARGMAX]; + int num_pos_args; /* Must start at -1. */ + int cur_pos_arg; +#endif /* defined(NL_ARGMAX) && (NL_ARGMAX > 0) */ + void *cur_ptr; + const unsigned char *fmt; + int cnt, dataargtype, conv_num, max_width; + unsigned char store, flags; +} psfs_t; /* parse scanf format state */ + + +/**********************************************************************/ +/**********************************************************************/ + +extern void __init_scan_cookie(register struct scan_cookie *sc, + register FILE *fp) attribute_hidden; +extern int __scan_getc(register struct scan_cookie *sc) attribute_hidden; +extern void __scan_ungetc(register struct scan_cookie *sc) attribute_hidden; + +#ifdef __UCLIBC_HAS_FLOATS__ +extern int __scan_strtold(long double *ld, struct scan_cookie *sc); +#endif /* __UCLIBC_HAS_FLOATS__ */ + +extern int __psfs_parse_spec(psfs_t *psfs) attribute_hidden; +extern int __psfs_do_numeric(psfs_t *psfs, struct scan_cookie *sc) attribute_hidden; + +/**********************************************************************/ +#ifdef L___scan_cookie + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning TODO: Remove dependence on decpt_str and fake_decpt in stub locale mode. +#endif +#ifndef __UCLIBC_HAS_LOCALE__ +static const char decpt_str[] = "."; +#endif + +void attribute_hidden __init_scan_cookie(register struct scan_cookie *sc, + register FILE *fp) +{ + sc->fp = fp; + sc->nread = 0; + sc->ungot_flag = 0; + sc->app_ungot = ((fp->__modeflags & __FLAG_UNGOT) ? fp->__ungot[1] : 0); +#ifdef __UCLIBC_HAS_WCHAR__ + sc->ungot_wflag = 0; /* vfwscanf */ + sc->mb_fail = 0; +#endif /* __UCLIBC_HAS_WCHAR__ */ + +#ifdef __UCLIBC_HAS_GLIBC_DIGIT_GROUPING__ + if (*(sc->grouping = __UCLIBC_CURLOCALE->grouping)) { + sc->thousands_sep = (const unsigned char *) __UCLIBC_CURLOCALE->thousands_sep; + sc->tslen = __UCLIBC_CURLOCALE->thousands_sep_len; +#ifdef __UCLIBC_HAS_WCHAR__ + sc->thousands_sep_wc = __UCLIBC_CURLOCALE->thousands_sep_wc; +#endif /* __UCLIBC_HAS_WCHAR__ */ + } +#endif /* __UCLIBC_HAS_GLIBC_DIGIT_GROUPING__ */ + +#ifdef __UCLIBC_HAS_FLOATS__ +#ifdef __UCLIBC_HAS_LOCALE__ + sc->decpt = (const unsigned char *) __UCLIBC_CURLOCALE->decimal_point; + sc->decpt_len = __UCLIBC_CURLOCALE->decimal_point_len; +#else /* __UCLIBC_HAS_LOCALE__ */ + sc->fake_decpt = sc->decpt = (unsigned char *) decpt_str; + sc->decpt_len = 1; +#endif /* __UCLIBC_HAS_LOCALE__ */ +#ifdef __UCLIBC_HAS_WCHAR__ +#ifdef __UCLIBC_HAS_LOCALE__ + sc->decpt_wc = __UCLIBC_CURLOCALE->decimal_point_wc; +#else + sc->decpt_wc = '.'; +#endif +#endif /* __UCLIBC_HAS_WCHAR__ */ +#endif /* __UCLIBC_HAS_FLOATS__ */ + +} + +int attribute_hidden __scan_getc(register struct scan_cookie *sc) +{ + int c; + +#ifdef __UCLIBC_HAS_WCHAR__ + assert(!sc->mb_fail); +#endif /* __UCLIBC_HAS_WCHAR__ */ + + sc->cc = EOF; + + if (--sc->width < 0) { + sc->ungot_flag |= 2; + return -1; + } + + if (sc->ungot_flag == 0) { +#if !defined(__STDIO_BUFFERS) && !defined(__UCLIBC_HAS_WCHAR__) + if (!__STDIO_STREAM_IS_FAKE_VSSCANF_NB(sc->fp)) { + c = GETC(sc); + } else { + __FILE_vsscanf *fv = (__FILE_vsscanf *)(sc->fp); + if (fv->bufpos < fv->bufread) { + c = *fv->bufpos++; + } else { + c = EOF; + sc->fp->__modeflags |= __FLAG_EOF; + } + } + if (c == EOF) { + sc->ungot_flag |= 2; + return -1; + } +#else + if ((c = GETC(sc)) == EOF) { + sc->ungot_flag |= 2; + return -1; + } +#endif + sc->ungot_char = c; + } else { + assert(sc->ungot_flag == 1); + sc->ungot_flag = 0; + } + + ++sc->nread; + return sc->cc = sc->ungot_char; +} + +void attribute_hidden __scan_ungetc(register struct scan_cookie *sc) +{ + ++sc->width; + if (sc->ungot_flag == 2) { /* last was EOF */ + sc->ungot_flag = 0; + sc->cc = sc->ungot_char; + } else if (sc->ungot_flag == 0) { + sc->ungot_flag = 1; + --sc->nread; + } else { + assert(0); + } +} + +#endif +/**********************************************************************/ +#ifdef L___psfs_parse_spec + +#ifdef SPEC_FLAGS +static const unsigned char spec_flags[] = SPEC_FLAGS; +#endif /* SPEC_FLAGS */ +static const unsigned char spec_chars[] = SPEC_CHARS; +static const unsigned char qual_chars[] = QUAL_CHARS; +static const unsigned char spec_ranges[] = SPEC_RANGES; +static const unsigned short spec_allowed[] = SPEC_ALLOWED_FLAGS; + +int attribute_hidden __psfs_parse_spec(register psfs_t *psfs) +{ + const unsigned char *p; + const unsigned char *fmt0 = psfs->fmt; + int i; +#ifdef SPEC_FLAGS + int j; +#endif +#if defined(NL_ARGMAX) && (NL_ARGMAX > 0) + unsigned char fail = 0; + + i = 0; /* Do this here to avoid a warning. */ + + if (!__isdigit_char(*psfs->fmt)) { /* Not a positional arg. */ + fail = 1; + goto DO_FLAGS; + } + + /* parse the positional arg (or width) value */ + do { + if (i <= ((INT_MAX - 9)/10)) { + i = (i * 10) + (*psfs->fmt++ - '0'); + } + } while (__isdigit_char(*psfs->fmt)); + + if (*psfs->fmt != '$') { /* This is a max field width. */ + if (psfs->num_pos_args >= 0) { /* Already saw a pos arg! */ + goto ERROR_EINVAL; + } + psfs->max_width = i; + psfs->num_pos_args = -2; + goto DO_QUALIFIER; + } + ++psfs->fmt; /* Advance past '$'. */ +#endif /* defined(NL_ARGMAX) && (NL_ARGMAX > 0) */ + +#if defined(SPEC_FLAGS) || (defined(NL_ARGMAX) && (NL_ARGMAX > 0)) + DO_FLAGS: +#endif /* defined(SPEC_FLAGS) || (defined(NL_ARGMAX) && (NL_ARGMAX > 0)) */ +#ifdef SPEC_FLAGS + p = spec_flags; + j = FLAG_SURPRESS; + do { + if (*p == *psfs->fmt) { + ++psfs->fmt; + psfs->flags |= j; + goto DO_FLAGS; + } + j += j; + } while (*++p); + + if (psfs->flags & FLAG_SURPRESS) { /* Suppress assignment. */ + psfs->store = 0; + goto DO_WIDTH; + } +#else /* SPEC_FLAGS */ + if (*psfs->fmt == '*') { /* Suppress assignment. */ + ++psfs->fmt; + psfs->store = 0; + goto DO_WIDTH; + } +#endif /* SPEC_FLAGS */ + + +#if defined(NL_ARGMAX) && (NL_ARGMAX > 0) + if (fail) { + /* Must be a non-positional arg */ + if (psfs->num_pos_args >= 0) { /* Already saw a pos arg! */ + goto ERROR_EINVAL; + } + psfs->num_pos_args = -2; + } else { + if ((psfs->num_pos_args == -2) || (((unsigned int)(--i)) >= NL_ARGMAX)) { + /* Already saw a non-pos arg or (0-based) num too large. */ + goto ERROR_EINVAL; + } + psfs->cur_pos_arg = i; + } +#endif /* defined(NL_ARGMAX) && (NL_ARGMAX > 0) */ + + DO_WIDTH: + for (i = 0 ; __isdigit_char(*psfs->fmt) ; ) { + if (i <= ((INT_MAX - 9)/10)) { + i = (i * 10) + (*psfs->fmt++ - '0'); + psfs->max_width = i; + } + } + +#if defined(NL_ARGMAX) && (NL_ARGMAX > 0) + DO_QUALIFIER: +#endif /* defined(NL_ARGMAX) && (NL_ARGMAX > 0) */ + p = qual_chars; + do { + if (*psfs->fmt == *p) { + ++psfs->fmt; + break; + } + } while (*++p); + if ((p - qual_chars < 2) && (*psfs->fmt == *p)) { + p += ((sizeof(qual_chars)-2) / 2); + ++psfs->fmt; + } + psfs->dataargtype = ((int)(p[(sizeof(qual_chars)-2) / 2])) << 8; + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning CONSIDER: Should we validate that psfs->max_width > 0 in __psfs_parse_spec()? It would avoid whitespace consumption... +#warning CONSIDER: Should INT_MAX be a valid width (%c/%C)? See __psfs_parse_spec(). +#endif /* __UCLIBC_MJN3_ONLY__ */ + + p = spec_chars; + do { + if (*psfs->fmt == *p) { + int p_m_spec_chars = p - spec_chars; + +#ifdef __UCLIBC_HAS_SCANF_GLIBC_A_FLAG__ +#error implement gnu a flag + if ((*p == 'a') + && ((psfs->fmt[1] == '[') || ((psfs->fmt[1]|0x20) == 's')) + ) { /* Assumes ascii for 's' and 'S' test. */ + psfs->flags |= FLAG_MALLOC; + ++psfs->fmt; + ++p; + continue; /* The related conversions follow 'a'. */ + } +#endif /* __UCLIBC_HAS_SCANF_GLIBC_A_FLAG__ */ + + for (p = spec_ranges; p_m_spec_chars > *p ; ++p) {} + if (((psfs->dataargtype >> 8) | psfs->flags) + & ~spec_allowed[(int)(p - spec_ranges)] + ) { + goto ERROR_EINVAL; + } + + if ((p_m_spec_chars >= CONV_c) + && (psfs->dataargtype & PA_FLAG_LONG)) { + p_m_spec_chars -= 3; /* lc -> C, ls -> S, l[ -> ?? */ + } + + psfs->conv_num = p_m_spec_chars; + return psfs->fmt - fmt0; + } + if (!*++p) { + ERROR_EINVAL: + __set_errno(EINVAL); + return -1; + } + } while(1); + + assert(0); +} + +#endif +/**********************************************************************/ +#if defined(L_vfscanf) || defined(L_vfwscanf) + +#ifdef __UCLIBC_HAS_WCHAR__ +#ifdef L_vfscanf +static int sc_getc(register struct scan_cookie *sc) +{ + return (getc_unlocked)(sc->fp); /* Disable the macro. */ +} + +static int scan_getwc(register struct scan_cookie *sc) +{ + size_t r; + int width; + wchar_t wc[1]; + char b[1]; + + if (--sc->width < 0) { + sc->ungot_flag |= 2; + return -1; + } + + width = sc->width; /* Preserve width. */ + sc->width = INT_MAX; /* MB_CUR_MAX can invoke a function. */ + + assert(!sc->mb_fail); + + r = (size_t)(-3); + while (__scan_getc(sc) >= 0) { + *b = sc->cc; + + r = mbrtowc(wc, b, 1, &sc->mbstate); + if (((ssize_t) r) >= 0) { /* Successful completion of a wc. */ + sc->wc = *wc; + goto SUCCESS; + } else if (r == ((size_t) -2)) { + /* Potentially valid but incomplete. */ + continue; + } + break; + } + + if (r == ((size_t)(-3))) { /* EOF or ERROR on first read */ + sc->wc = WEOF; + r = (size_t)(-1); + } else { + /* If we reach here, either r == ((size_t)-1) and + * mbrtowc set errno to EILSEQ, or r == ((size_t)-2) + * and stream is in an error state or at EOF with a + * partially complete wchar. */ + __set_errno(EILSEQ); /* In case of incomplete conversion. */ + sc->mb_fail = 1; + } + + SUCCESS: + sc->width = width; /* Restore width. */ + + return (int)((ssize_t) r); +} + +#endif /* L_vfscanf */ + +#ifdef L_vfwscanf + +/* This gets called by __scan_getc. __scan_getc is called by vfwscanf + * when the next wide char is expected to be valid ascii (digits). + */ +static int sc_getc(register struct scan_cookie *sc) +{ + wint_t wc; + + if (__STDIO_STREAM_IS_FAKE_VSWSCANF(sc->fp)) { + if (sc->fp->__bufpos < sc->fp->__bufend) { + wc = *((wchar_t *)(sc->fp->__bufpos)); + sc->fp->__bufpos += sizeof(wchar_t); + } else { + sc->fp->__modeflags |= __FLAG_EOF; + return EOF; + } + } else if ((wc = fgetwc_unlocked(sc->fp)) == WEOF) { + return EOF; + } + + sc->ungot_wflag = 1; + sc->ungot_wchar = wc; + sc->ungot_wchar_width = sc->fp->__ungot_width[0]; + +#ifdef __UCLIBC_HAS_GLIBC_DIGIT_GROUPING__ + if (wc == sc->thousands_sep_wc) { + wc = ','; + } else +#endif /* __UCLIBC_HAS_GLIBC_DIGIT_GROUPING__ */ +#ifdef __UCLIBC_HAS_FLOATS__ + if (wc == sc->decpt_wc) { + wc = '.'; + } else +#endif /* __UCLIBC_HAS_FLOATS__ */ + sc->wc = sc->ungot_char = wc; + + return (int) wc; +} + +static int scan_getwc(register struct scan_cookie *sc) +{ + wint_t wc; + + sc->wc = WEOF; + + if (--sc->width < 0) { + sc->ungot_flag |= 2; + return -1; + } + + if (sc->ungot_flag == 0) { + if (__STDIO_STREAM_IS_FAKE_VSWSCANF(sc->fp)) { + if (sc->fp->__bufpos < sc->fp->__bufend) { + wc = *((wchar_t *)(sc->fp->__bufpos)); + sc->fp->__bufpos += sizeof(wchar_t); + } else { + sc->ungot_flag |= 2; + return -1; + } + } else if ((wc = fgetwc_unlocked(sc->fp)) == WEOF) { + sc->ungot_flag |= 2; + return -1; + } + sc->ungot_wflag = 1; + sc->ungot_char = wc; + sc->ungot_wchar_width = sc->fp->__ungot_width[0]; + } else { + assert(sc->ungot_flag == 1); + sc->ungot_flag = 0; + } + + ++sc->nread; + sc->wc = sc->ungot_char; + + return 0; +} + + +#endif /* L_vfwscanf */ +#endif /* __UCLIBC_HAS_WCHAR__ */ + +static __inline void kill_scan_cookie(register struct scan_cookie *sc) +{ +#ifdef L_vfscanf + + if (sc->ungot_flag & 1) { +#if !defined(__STDIO_BUFFERS) && !defined(__UCLIBC_HAS_WCHAR__) + if (!__STDIO_STREAM_IS_FAKE_VSSCANF_NB(sc->fp)) { + ungetc(sc->ungot_char, sc->fp); + } +#else + ungetc(sc->ungot_char, sc->fp); +#endif + /* Deal with distiction between user and scanf ungots. */ + if (sc->nread == 0) { /* Only one char was read... app ungot? */ + sc->fp->__ungot[1] = sc->app_ungot; /* restore ungot state. */ + } else { + sc->fp->__ungot[1] = 0; + } + } + +#else + + if ((sc->ungot_flag & 1) && (sc->ungot_wflag & 1) + && !__STDIO_STREAM_IS_FAKE_VSWSCANF(sc->fp) + && (sc->fp->__state.__mask == 0) + ) { + ungetwc(sc->ungot_char, sc->fp); + /* Deal with distiction between user and scanf ungots. */ + if (sc->nread == 0) { /* Only one char was read... app ungot? */ + sc->fp->__ungot[1] = sc->app_ungot; /* restore ungot state. */ + } else { + sc->fp->__ungot[1] = 0; + } + sc->fp->__ungot_width[1] = sc->ungot_wchar_width; + } + +#endif +} + + +int VFSCANF (FILE *__restrict fp, const Wchar *__restrict format, va_list arg) +{ + const Wuchar *fmt; + unsigned char *b; + +#ifdef L_vfwscanf + wchar_t wbuf[1]; + wchar_t *wb; +#endif /* L_vfwscanf */ + +#if defined(__UCLIBC_HAS_LOCALE__) && !defined(L_vfwscanf) || !defined(L_vfscanf) + mbstate_t mbstate; +#endif + + struct scan_cookie sc; + psfs_t psfs; + int i; + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning TODO: Fix MAX_DIGITS. We do not do binary, so...! +#endif +#define MAX_DIGITS 65 /* Allow one leading 0. */ + unsigned char buf[MAX_DIGITS+2]; +#ifdef L_vfscanf + unsigned char scanset[UCHAR_MAX + 1]; + unsigned char invert; /* Careful! Meaning changes. */ +#endif /* L_vfscanf */ + unsigned char fail; + unsigned char zero_conversions = 1; + __STDIO_AUTO_THREADLOCK_VAR; + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning TODO: Make checking of the format string in C locale an option. +#endif + /* To support old programs, don't check mb validity if in C locale. */ +#if defined(__UCLIBC_HAS_LOCALE__) && !defined(L_vfwscanf) + /* ANSI/ISO C99 requires format string to be a valid multibyte string + * beginning and ending in its initial shift state. */ + if (__UCLIBC_CURLOCALE->encoding != __ctype_encoding_7_bit) { + const char *p = format; + mbstate.__mask = 0; /* Initialize the mbstate. */ + if (mbsrtowcs(NULL, &p, SIZE_MAX, &mbstate) == ((size_t)(-1))) { + __set_errno(EINVAL); /* Format string is invalid. */ + return 0; + } + } +#endif /* defined(__UCLIBC_HAS_LOCALE__) && !defined(L_vfwscanf) */ + +#if defined(NL_ARGMAX) && (NL_ARGMAX > 0) + psfs.num_pos_args = -1; /* Must start at -1. */ + /* Initialize positional arg ptrs to NULL. */ + memset(psfs.pos_args, 0, sizeof(psfs.pos_args)); +#endif /* defined(NL_ARGMAX) && (NL_ARGMAX > 0) */ + + __STDIO_AUTO_THREADLOCK(fp); + + __STDIO_STREAM_VALIDATE(fp); + + __init_scan_cookie(&sc,fp); +#ifdef __UCLIBC_HAS_WCHAR__ + sc.sc_getc = sc_getc; + sc.ungot_wchar_width = sc.fp->__ungot_width[1]; + +#ifdef L_vfwscanf + +#ifdef __UCLIBC_HAS_GLIBC_DIGIT_GROUPING__ + if (*sc.grouping) { + sc.thousands_sep = (const unsigned char *) ","; + sc.tslen = 1; + } +#endif /* __UCLIBC_HAS_GLIBC_DIGIT_GROUPING__ */ + +#ifdef __UCLIBC_HAS_FLOATS__ + sc.fake_decpt = (const unsigned char *) "."; +#endif /* __UCLIBC_HAS_FLOATS__ */ + +#else /* L_vfwscanf */ + +#ifdef __UCLIBC_HAS_FLOATS__ + sc.fake_decpt = sc.decpt; +#endif /* __UCLIBC_HAS_FLOATS__ */ + +#endif /* L_vfwscanf */ + +#endif /* __UCLIBC_HAS_WCHAR__ */ + psfs.cnt = 0; + + /* Note: If we ever wanted to support non-nice codesets, we + * would really need to do a mb->wc conversion here in the + * vfscanf case. Related changes would have to be made in + * the code that follows... basicly wherever fmt appears. */ + for (fmt = (const Wuchar *) format ; *fmt ; /* ++fmt */) { + + psfs.store = 1; + psfs.flags = 0; +#ifndef NDEBUG + psfs.cur_ptr = NULL; /* Debugging aid. */ +#endif /* NDEBUG */ + + + sc.ungot_flag &= 1; /* Clear (possible fake) EOF. */ + sc.width = psfs.max_width = INT_MAX; + + /* Note: According to the standards, vfscanf does use isspace + * here. So, if we did a mb->wc conversion, we would have to do + * something like + * ((((__uwchar_t)wc) < UCHAR_MAX) && isspace(wc)) + * because wc might not be in the allowed domain. */ + if (ISSPACE(*fmt)) { + do { + ++fmt; + } while (ISSPACE(*fmt)); + --fmt; + psfs.conv_num = CONV_whitespace; + goto DO_WHITESPACE; + } + + if (*fmt == '%') { /* Conversion specification. */ + if (*++fmt == '%') { /* Remember, '%' eats whitespace too. */ + /* Note: The standard says no conversion occurs. + * So do not reset zero_conversions flag. */ + psfs.conv_num = CONV_percent; + goto DO_CONVERSION; + } + + +#ifdef L_vfscanf + psfs.fmt = fmt; +#else /* L_vfscanf */ + { + const __uwchar_t *wf = fmt; + psfs.fmt = b = buf; + + while (*wf && __isascii(*wf) && (b < buf + sizeof(buf) - 1)) { + *b++ = *wf++; + } +#ifdef __UCLIBC_HAS_SCANF_GLIBC_A_FLAG__ +#error this is wrong... we need to ched in __psfs_parse_spec instead since this checks last char in buffer and conversion my have stopped before it. + if ((*b == 'a') && ((*wf == '[') || ((*wf|0x20) == 's'))) { + goto DONE; /* Spec was excessively long. */ + } +#endif /* __UCLIBC_HAS_SCANF_GLIBC_A_FLAG__ */ + *b = 0; + if (b == buf) { /* Bad conversion specifier! */ + goto DONE; + } + } +#endif /* L_vfscanf */ + if ((i = __psfs_parse_spec(&psfs)) < 0) { /* Bad conversion specifier! */ + goto DONE; + } + fmt += i; + + if (psfs.store) { +#if defined(NL_ARGMAX) && (NL_ARGMAX > 0) + if (psfs.num_pos_args == -2) { + psfs.cur_ptr = va_arg(arg, void *); + } else { + while (psfs.cur_pos_arg > psfs.num_pos_args) { + psfs.pos_args[++psfs.num_pos_args] = va_arg(arg, void *); + } + psfs.cur_ptr = psfs.pos_args[psfs.cur_pos_arg]; + } +#else /* defined(NL_ARGMAX) && (NL_ARGMAX > 0) */ + psfs.cur_ptr = va_arg(arg, void *); +#endif /* defined(NL_ARGMAX) && (NL_ARGMAX > 0) */ + } + + DO_CONVERSION: + /* First, consume white-space if not n, c, [, C, or l[. */ + if ((((1L << CONV_n)|(1L << CONV_C)|(1L << CONV_c) + |(1L << CONV_LEFTBRACKET)|(1L << CONV_leftbracket)) + & (1L << psfs.conv_num)) == 0 + ) { + DO_WHITESPACE: + while ((__scan_getc(&sc) >= 0) +#ifdef L_vfscanf + && isspace(sc.cc) +#else /* L_vfscanf */ + && iswspace(sc.wc) +#endif /* L_vfscanf */ + ) {} + __scan_ungetc(&sc); + if (psfs.conv_num == CONV_whitespace) { + goto NEXT_FMT; + } + } + + sc.width = psfs.max_width; /* Now limit the max width. */ + + if (sc.width == 0) { /* 0 width is forbidden. */ + goto DONE; + } + + + if (psfs.conv_num == CONV_percent) { + goto MATCH_CHAR; + } + + if (psfs.conv_num == CONV_n) { +#ifdef __UCLIBC_MJN3_ONLY__ +#warning CONSIDER: Should %n count as a conversion as far as EOF return value? +#endif +/* zero_conversions = 0; */ + if (psfs.store) { + _store_inttype(psfs.cur_ptr, psfs.dataargtype, + (uintmax_t) sc.nread); + } + goto NEXT_FMT; + } + + if (psfs.conv_num <= CONV_A) { /* pointer, integer, or float spec */ + int r = __psfs_do_numeric(&psfs, &sc); +#ifndef L_vfscanf + if (sc.ungot_wflag == 1) { /* fix up '?', '.', and ',' hacks */ + sc.cc = sc.ungot_char = sc.ungot_wchar; + } +#endif + if (r != -1) { /* Either success or a matching failure. */ + zero_conversions = 0; + } + if (r < 0) { + goto DONE; + } + goto NEXT_FMT; + } + + /* Do string conversions here since they are not common code. */ + + +#ifdef L_vfscanf + + if +#ifdef __UCLIBC_HAS_WCHAR__ + (psfs.conv_num >= CONV_LEFTBRACKET) +#else /* __UCLIBC_HAS_WCHAR__ */ + (psfs.conv_num >= CONV_c) +#endif /* __UCLIBC_HAS_WCHAR__ */ + { + b = (psfs.store ? ((unsigned char *) psfs.cur_ptr) : buf); + fail = 1; + + if (psfs.conv_num == CONV_c) { + if (sc.width == INT_MAX) { + sc.width = 1; + } + + while (__scan_getc(&sc) >= 0) { + zero_conversions = 0; + *b = sc.cc; + b += psfs.store; + } + __scan_ungetc(&sc); + if (sc.width > 0) { /* Failed to read all required. */ + goto DONE; + } + psfs.cnt += psfs.store; + goto NEXT_FMT; + } + + if (psfs.conv_num == CONV_s) { + /* Yes, believe it or not, a %s conversion can store nuls. */ + while ((__scan_getc(&sc) >= 0) && !isspace(sc.cc)) { + zero_conversions = 0; + *b = sc.cc; + b += psfs.store; + fail = 0; + } + } else { +#ifdef __UCLIBC_HAS_WCHAR__ + assert((psfs.conv_num == CONV_LEFTBRACKET) || \ + (psfs.conv_num == CONV_leftbracket)); +#else /* __UCLIBC_HAS_WCHAR__ */ + assert((psfs.conv_num == CONV_leftbracket)); +#endif /* __UCLIBC_HAS_WCHAR__ */ + + invert = 0; + + if (*++fmt == '^') { + ++fmt; + invert = 1; + } + memset(scanset, invert, sizeof(scanset)); + invert = 1-invert; + + if (*fmt == ']') { + scanset[(int)(']')] = invert; + ++fmt; + } + + while (*fmt != ']') { + if (!*fmt) { /* No closing ']'. */ + goto DONE; + } + if ((*fmt == '-') && (fmt[1] != ']') + && (fmt[-1] < fmt[1]) /* sorted? */ + ) { /* range */ + ++fmt; + i = fmt[-2]; + /* Note: scanset[i] should already have been done + * in the previous iteration. */ + do { + scanset[++i] = invert; + } while (i < *fmt); + /* Safe to fall through, and a bit smaller. */ + } + /* literal char */ + scanset[(int) *fmt] = invert; + ++fmt; + } + +#ifdef __UCLIBC_HAS_WCHAR__ + if (psfs.conv_num == CONV_LEFTBRACKET) { + goto DO_LEFTBRACKET; + } +#endif /* __UCLIBC_HAS_WCHAR__ */ + + + while (__scan_getc(&sc) >= 0) { + zero_conversions = 0; + if (!scanset[sc.cc]) { + break; + } + *b = sc.cc; + b += psfs.store; + fail = 0; + } + } + /* Common tail for processing of %s and %[. */ + + __scan_ungetc(&sc); + if (fail) { /* nothing stored! */ + goto DONE; + } + *b = 0; /* Nul-terminate string. */ + psfs.cnt += psfs.store; + goto NEXT_FMT; + } + +#ifdef __UCLIBC_HAS_WCHAR__ + DO_LEFTBRACKET: /* Need to do common wide init. */ + if (psfs.conv_num >= CONV_C) { + wchar_t wbuf[1]; + wchar_t *wb; + + sc.mbstate.__mask = 0; + + wb = (psfs.store ? ((wchar_t *) psfs.cur_ptr) : wbuf); + fail = 1; + + if (psfs.conv_num == CONV_C) { + if (sc.width == INT_MAX) { + sc.width = 1; + } + + while (scan_getwc(&sc) >= 0) { + zero_conversions = 0; + assert(sc.width >= 0); + *wb = sc.wc; + wb += psfs.store; + } + + __scan_ungetc(&sc); + if (sc.width > 0) { /* Failed to read all required. */ + goto DONE; + } + psfs.cnt += psfs.store; + goto NEXT_FMT; + } + + + if (psfs.conv_num == CONV_S) { + /* Yes, believe it or not, a %s conversion can store nuls. */ + while (scan_getwc(&sc) >= 0) { + zero_conversions = 0; + if ((((__uwchar_t)(sc.wc)) <= UCHAR_MAX) && isspace(sc.wc)) { + break; + } + *wb = sc.wc; + wb += psfs.store; + fail = 0; + } + } else { + assert(psfs.conv_num == CONV_LEFTBRACKET); + + while (scan_getwc(&sc) >= 0) { + zero_conversions = 0; + if (((__uwchar_t) sc.wc) <= UCHAR_MAX) { + if (!scanset[sc.wc]) { + break; + } + } else if (invert) { + break; + } + *wb = sc.wc; + wb += psfs.store; + fail = 0; + } + } + /* Common tail for processing of %ls and %l[. */ + + __scan_ungetc(&sc); + if (fail || sc.mb_fail) { /* Nothing stored or mb error. */ + goto DONE; + } + *wb = 0; /* Nul-terminate string. */ + psfs.cnt += psfs.store; + goto NEXT_FMT; + + } + +#endif /* __UCLIBC_HAS_WCHAR__ */ +#else /* L_vfscanf */ + + if (psfs.conv_num >= CONV_C) { + b = buf; + wb = wbuf; + if (psfs.conv_num >= CONV_c) { + mbstate.__mask = 0; /* Initialize the mbstate. */ + if (psfs.store) { + b = (unsigned char *) psfs.cur_ptr; + } + } else { + if (psfs.store) { + wb = (wchar_t *) psfs.cur_ptr; + } + } + fail = 1; + + + if ((psfs.conv_num == CONV_C) || (psfs.conv_num == CONV_c)) { + if (sc.width == INT_MAX) { + sc.width = 1; + } + + while (scan_getwc(&sc) >= 0) { + zero_conversions = 0; + if (psfs.conv_num == CONV_C) { + *wb = sc.wc; + wb += psfs.store; + } else { + i = wcrtomb((char*) b, sc.wc, &mbstate); + if (i < 0) { /* Conversion failure. */ + goto DONE_DO_UNGET; + } + if (psfs.store) { + b += i; + } + } + } + __scan_ungetc(&sc); + if (sc.width > 0) { /* Failed to read all required. */ + goto DONE; + } + psfs.cnt += psfs.store; + goto NEXT_FMT; + } + + if ((psfs.conv_num == CONV_S) || (psfs.conv_num == CONV_s)) { + /* Yes, believe it or not, a %s conversion can store nuls. */ + while (scan_getwc(&sc) >= 0) { + zero_conversions = 0; + if (iswspace(sc.wc)) { + break; + } + if (psfs.conv_num == CONV_S) { + *wb = sc.wc; + wb += psfs.store; + } else { + i = wcrtomb((char*) b, sc.wc, &mbstate); + if (i < 0) { /* Conversion failure. */ + goto DONE_DO_UNGET; + } + if (psfs.store) { + b += i; + } + } + fail = 0; + } + } else { + const wchar_t *sss; + const wchar_t *ssp; + unsigned char invert = 0; + + assert((psfs.conv_num == CONV_LEFTBRACKET) + || (psfs.conv_num == CONV_leftbracket)); + + if (*++fmt == '^') { + ++fmt; + invert = 1; + } + sss = (const wchar_t *) fmt; + if (*fmt == ']') { + ++fmt; + } + while (*fmt != ']') { + if (!*fmt) { /* No closing ']'. */ + goto DONE; + } + if ((*fmt == '-') && (fmt[1] != ']') + && (fmt[-1] < fmt[1]) /* sorted? */ + ) { /* range */ + ++fmt; + } + ++fmt; + } + /* Ok... a valid scanset spec. */ + + while (scan_getwc(&sc) >= 0) { + zero_conversions = 0; + ssp = sss; + do { /* We know sss < fmt. */ + if (*ssp == '-') { /* possible range... */ + /* Note: We accept a-c-e (ordered) as + * equivalent to a-e. */ + if (ssp > sss) { + if ((++ssp < (const wchar_t *) fmt) + && (ssp[-2] < *ssp) /* sorted? */ + ) { /* yes */ + if ((sc.wc >= ssp[-2]) + && (sc.wc <= *ssp)) { + break; + } + continue; /* not in range */ + } + --ssp; /* oops... '-' at end, so back up */ + } + /* false alarm... a literal '-' */ + } + if (sc.wc == *ssp) { /* Matched literal char. */ + break; + } + } while (++ssp < (const wchar_t *) fmt); + + if ((ssp == (const wchar_t *) fmt) ^ invert) { + /* no match and not inverting + * or match and inverting */ + break; + } + if (psfs.conv_num == CONV_LEFTBRACKET) { + *wb = sc.wc; + wb += psfs.store; + } else { + i = wcrtomb((char*) b, sc.wc, &mbstate); + if (i < 0) { /* Conversion failure. */ + goto DONE_DO_UNGET; + } + if (psfs.store) { + b += i; + } + } + fail = 0; + } + } + /* Common tail for processing of %s and %[. */ + + __scan_ungetc(&sc); + if (fail) { /* nothing stored! */ + goto DONE; + } + *wb = 0; /* Nul-terminate string. */ + *b = 0; + psfs.cnt += psfs.store; + goto NEXT_FMT; + } + +#endif /* L_vfscanf */ + + assert(0); + goto DONE; + } /* conversion specification */ + + MATCH_CHAR: + if (__scan_getc(&sc) != *fmt) { +#ifdef L_vfwscanf + DONE_DO_UNGET: +#endif /* L_vfwscanf */ + __scan_ungetc(&sc); + goto DONE; + } + + NEXT_FMT: + ++fmt; + if (__FERROR_UNLOCKED(fp)) { + break; + } + } + + DONE: + if (__FERROR_UNLOCKED(fp) || (*fmt && zero_conversions && __FEOF_UNLOCKED(fp))) { + psfs.cnt = EOF; /* Yes, vfwscanf also returns EOF. */ + } + + kill_scan_cookie(&sc); + + __STDIO_STREAM_VALIDATE(fp); + + __STDIO_AUTO_THREADUNLOCK(fp); + + return psfs.cnt; +} +libc_hidden_def(VFSCANF) +#endif +/**********************************************************************/ +#ifdef L___psfs_do_numeric + +static const unsigned char spec_base[] = SPEC_BASE; +static const unsigned char nil_string[] = "(nil)"; + +int attribute_hidden __psfs_do_numeric(psfs_t *psfs, struct scan_cookie *sc) +{ + unsigned char *b; + const unsigned char *p; + +#ifdef __UCLIBC_HAS_FLOATS__ + int exp_adjust = 0; +#endif +#ifdef __UCLIBC_MJN3_ONLY__ +#warning TODO: Fix MAX_DIGITS. We do not do binary, so...! +#warning TODO: Fix buf! +#endif +#define MAX_DIGITS 65 /* Allow one leading 0. */ + unsigned char buf[MAX_DIGITS+2+ 100]; + unsigned char usflag, base; + unsigned char nonzero = 0; + unsigned char seendigit = 0; + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning CONSIDER: What should be returned for an invalid conversion specifier? +#endif +#ifndef __UCLIBC_HAS_FLOATS__ + if (psfs->conv_num > CONV_i) { /* floating point */ + goto DONE; + } +#endif + + base = spec_base[psfs->conv_num - CONV_p]; + usflag = (psfs->conv_num <= CONV_u); /* (1)0 if (un)signed */ + b = buf; + + + if (psfs->conv_num == CONV_p) { /* Pointer */ + p = nil_string; + do { + if ((__scan_getc(sc) < 0) || (*p != sc->cc)) { + __scan_ungetc(sc); + if (p > nil_string) { + /* We matched at least the '(' so even if we + * are at eof, we can not match a pointer. */ + return -2; /* Matching failure */ + } + break; + } + if (!*++p) { /* Matched (nil), so no unget necessary. */ + if (psfs->store) { + ++psfs->cnt; + _store_inttype(psfs->cur_ptr, psfs->dataargtype, + (uintmax_t)0); + } + return 0; + } + } while (1); + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning CONSIDER: Should we require a 0x prefix and disallow +/- for pointer %p? +#endif /* __UCLIBC_MJN3_ONLY__ */ + } + + __scan_getc(sc); + if (sc->cc < 0) { + return -1; /* Input failure (nothing read yet). */ + } + + if ((sc->cc == '+') || (sc->cc == '-')) { /* Handle leading sign.*/ + *b++ = sc->cc; + __scan_getc(sc); + } + + if ((base & 0xef) == 0) { /* 0xef is ~16, so 16 or 0. */ + if (sc->cc == '0') { /* Possibly set base and handle prefix. */ + __scan_getc(sc); + if ((sc->cc|0x20) == 'x') { /* Assumes ascii.. x or X. */ + if (__scan_getc(sc) < 0) { + /* Either EOF or error (including wc outside char range). + * If EOF or error, this is a matching failure (we read 0x). + * If wc outside char range, this is also a matching failure. + * Hence, we do an unget (although not really necessary here + * and fail. */ + goto DONE_DO_UNGET; /* matching failure */ + } + base = 16; /* Base 16 for sure now. */ +#ifdef __UCLIBC_HAS_HEXADECIMAL_FLOATS__ + /* The prefix is required for hexadecimal floats. */ + *b++ = '0'; + *b++ = 'x'; +#endif /* __UCLIBC_HAS_HEXADECIMAL_FLOATS__ */ + } else { /* oops... back up */ + __scan_ungetc(sc); + sc->cc = '0'; /* NASTY HACK! */ + + base = (base >> 1) + 8; /* 0->8, 16->16. no 'if' */ +#ifdef __UCLIBC_HAS_FLOATS__ + if (psfs->conv_num > CONV_i) { /* floating point */ + base = 10; + } +#endif + } + } else if (!base) { + base = 10; + } + } + + /***************** digit grouping **********************/ +#ifdef __UCLIBC_HAS_GLIBC_DIGIT_GROUPING__ + + if ((psfs->flags & FLAG_THOUSANDS) && (base == 10) + && *(p = (const unsigned char *) sc->grouping) + ) { + + int nblk1, nblk2, nbmax, lastblock, pass, i; + + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning CONSIDER: Should we initalize the grouping blocks in __init_scan_cookie()? +#endif /* __UCLIBC_MJN3_ONLY__ */ + nbmax = nblk2 = nblk1 = *p; + if (*++p) { + nblk2 = *p; + if (nbmax < nblk2) { + nbmax = nblk2; + } + assert(!p[1]); + } + + /* Note: for printf, if 0 and \' flags appear then + * grouping is done before 0-padding. Should we + * strip leading 0's first? Or add a 0 flag? */ + + /* For vfwscanf, sc_getc translates, so the value of sc->cc is + * either EOF or a char. */ + + if (!__isdigit_char_or_EOF(sc->cc)) { /* No starting digit! */ +#ifdef __UCLIBC_HAS_FLOATS__ + if (psfs->conv_num > CONV_i) { /* floating point */ + goto NO_STARTING_DIGIT; + } +#endif + goto DONE_DO_UNGET; + } + + if (sc->cc == '0') { + seendigit = 1; + *b++ = '0'; /* Store the first 0. */ +#ifdef __UCLIBC_MJN3_ONLY__ +#warning CONSIDER: Should leading 0s be skipped before digit grouping? (printf 0 pad) +#endif /* __UCLIBC_MJN3_ONLY__ */ +#if 0 + do { /* But ignore all subsequent 0s. */ + __scan_getc(sc); + } while (sc->cc == '0'); +#endif + } + pass = 0; + lastblock = 0; + do { + i = 0; + while (__isdigit_char_or_EOF(sc->cc)) { + seendigit = 1; + if (i == nbmax) { /* too many digits for a block */ +#ifdef __UCLIBC_HAS_SCANF_LENIENT_DIGIT_GROUPING__ + if (!pass) { /* treat as nongrouped */ + if (nonzero) { + goto DO_NO_GROUP; + } + goto DO_TRIM_LEADING_ZEROS; + } +#endif + if (nbmax > nblk1) { + goto DONE_DO_UNGET; /* matching failure */ + } + goto DONE_GROUPING_DO_UNGET; /* nbmax == nblk1 */ + } + ++i; + + if (nonzero || (sc->cc != '0')) { + if (b < buf + MAX_DIGITS) { + *b++ = sc->cc; + nonzero = 1; +#ifdef __UCLIBC_HAS_FLOATS__ + } else { + ++exp_adjust; +#endif + } + } + + __scan_getc(sc); + } + + if (i) { /* we saw digits digits */ + if ((i == nblk2) || ((i < nblk2) && !pass)) { + /* (possible) outer grp */ + p = sc->thousands_sep; + if (*p == sc->cc) { /* first byte matches... */ + /* so check if grouping mb char */ + /* Since 1st matched, either match or fail now + * unless EOF (yuk) */ + __scan_getc(sc); + MBG_LOOP: + if (!*++p) { /* is a grouping mb char */ + lastblock = i; + ++pass; + continue; + } + if (*p == sc->cc) { + __scan_getc(sc); + goto MBG_LOOP; + } + /* bad grouping mb char! */ + __scan_ungetc(sc); + if ((sc->cc >= 0) || (p > sc->thousands_sep + 1)) { +#ifdef __UCLIBC_HAS_FLOATS__ + /* We failed to match a thousep mb char, and + * we've read too much to recover. But if + * this is a floating point conversion and + * the initial portion of the decpt mb char + * matches, then we may still be able to + * recover. */ + int k = p - sc->thousands_sep - 1; + + if ((psfs->conv_num > CONV_i) /* float conversion */ + && (!pass || (i == nblk1)) /* possible last */ + && !memcmp(sc->thousands_sep, sc->fake_decpt, k) + /* and prefix matched, so could be decpt */ + ) { + __scan_getc(sc); + p = sc->fake_decpt + k; + do { + if (!*++p) { + strcpy((char*) b, (char*) sc->decpt); + b += sc->decpt_len; + goto GOT_DECPT; + } + if (*p != sc->cc) { + __scan_ungetc(sc); + break; /* failed */ + } + __scan_getc(sc); + } while (1); + } +#endif /* __UCLIBC_HAS_FLOATS__ */ + goto DONE; + } + /* was EOF and 1st, so recoverable. */ + } + } + if ((i == nblk1) || ((i < nblk1) && !pass)) { + /* got an inner group */ + goto DONE_GROUPING_DO_UNGET; + } + goto DONE_DO_UNGET; /* Matching failure. */ + } /* i != 0 */ + + assert(pass); + + goto DONE_DO_UNGET; + } while (1); + + assert(0); /* Should never get here. */ + } + +#endif /***************** digit grouping **********************/ + + /* Not grouping so first trim all but one leading 0. */ +#ifdef __UCLIBC_HAS_SCANF_LENIENT_DIGIT_GROUPING__ + DO_TRIM_LEADING_ZEROS: +#endif /* __UCLIBC_HAS_SCANF_LENIENT_DIGIT_GROUPING__ */ + if (sc->cc == '0') { + seendigit = 1; + *b++ = '0'; /* Store the first 0. */ + do { /* But ignore all subsequent 0s. */ + __scan_getc(sc); + } while (sc->cc == '0'); + } + +#ifdef __UCLIBC_HAS_SCANF_LENIENT_DIGIT_GROUPING__ + DO_NO_GROUP: +#endif /* __UCLIBC_HAS_SCANF_LENIENT_DIGIT_GROUPING__ */ + /* At this point, we're ready to start reading digits. */ + +#define valid_digit(cc,base) (isxdigit(cc) && ((base == 16) || (cc - '0' < base))) + + while (valid_digit(sc->cc,base)) { /* Now for significant digits.*/ + if (b - buf < MAX_DIGITS) { + nonzero = seendigit = 1; /* Set nonzero too 0s trimmed above. */ + *b++ = sc->cc; +#ifdef __UCLIBC_HAS_FLOATS__ + } else { + ++exp_adjust; +#endif + } + __scan_getc(sc); + } + +#ifdef __UCLIBC_HAS_GLIBC_DIGIT_GROUPING__ + DONE_GROUPING_DO_UNGET: +#endif /* __UCLIBC_HAS_GLIBC_DIGIT_GROUPING__ */ + if (psfs->conv_num <= CONV_i) { /* integer conversion */ + __scan_ungetc(sc); + *b = 0; /* null-terminate */ + if (!seendigit) { + goto DONE; /* No digits! */ + } + if (psfs->store) { + if (*buf == '-') { + usflag = 0; + } + ++psfs->cnt; + _store_inttype(psfs->cur_ptr, psfs->dataargtype, + (uintmax_t) STRTOUIM((char *) buf, NULL, base, 1-usflag)); + } + return 0; + } + +#ifdef __UCLIBC_HAS_FLOATS__ + + /* At this point, we have everything left of the decimal point or exponent. */ +#ifdef __UCLIBC_HAS_GLIBC_DIGIT_GROUPING__ + NO_STARTING_DIGIT: +#endif + p = sc->fake_decpt; + do { + if (!*p) { + strcpy((char *) b, (char *) sc->decpt); + b += sc->decpt_len; + break; + } + if (*p != sc->cc) { + if (p > sc->fake_decpt) { + goto DONE_DO_UNGET; /* matching failure (read some of decpt) */ + } + goto DO_DIGIT_CHECK; + } + ++p; + __scan_getc(sc); + } while (1); + +#ifdef __UCLIBC_HAS_GLIBC_DIGIT_GROUPING__ + GOT_DECPT: +#endif + if (!nonzero) { + if (sc->cc == '0') { + assert(exp_adjust == 0); + *b++ = '0'; + ++exp_adjust; + seendigit = 1; + do { + --exp_adjust; + __scan_getc(sc); + } while (sc->cc == '0'); + } + } + + while (valid_digit(sc->cc,base)) { /* Process fractional digits.*/ + if (b - buf < MAX_DIGITS) { + seendigit = 1; + *b++ = sc->cc; + } + __scan_getc(sc); + } + + DO_DIGIT_CHECK: + /* Hmm... no decimal point. */ + if (!seendigit) { + static const unsigned char nan_inf_str[] = "an\0nfinity"; + + if (base == 16) { /* We had a prefix, but no digits! */ + goto DONE_DO_UNGET; /* matching failure */ + } + + /* Avoid tolower problems for INFINITY in the tr_TR locale. (yuk)*/ +#undef TOLOWER +#define TOLOWER(C) ((C)|0x20) + + switch (TOLOWER(sc->cc)) { + case 'i': + p = nan_inf_str + 3; + break; + case 'n': + p = nan_inf_str; + break; + default: + /* No digits and not inf or nan. */ + goto DONE_DO_UNGET; + } + + *b++ = sc->cc; + + do { + __scan_getc(sc); + if (TOLOWER(sc->cc) == *p) { + *b++ = sc->cc; + ++p; + continue; + } + if (!*p || (p == nan_inf_str + 5)) { /* match nan/infinity or inf */ + goto GOT_FLOAT; + } + /* Unrecoverable. Even if on 1st char, we had no digits. */ + goto DONE_DO_UNGET; + } while (1); + } + + /* If we get here, we had some digits. */ + + if ( +#ifdef __UCLIBC_HAS_HEXADECIMAL_FLOATS__ + ((base == 16) && (((sc->cc)|0x20) == 'p')) || +#endif + (((sc->cc)|0x20) == 'e') + ) { /* Process an exponent. */ + *b++ = sc->cc; + + __scan_getc(sc); + if (sc->cc < 0) { + goto DONE_DO_UNGET; /* matching failure.. no exponent digits */ + } + + if ((sc->cc == '+') || (sc->cc == '-')) { /* Signed exponent? */ + *b++ = sc->cc; + __scan_getc(sc); + } + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning TODO: Fix MAX_EXP_DIGITS! +#endif +#define MAX_EXP_DIGITS 20 + assert(seendigit); + seendigit = 0; + nonzero = 0; + + if (sc->cc == '0') { + seendigit = 1; + *b++ = '0'; + do { + __scan_getc(sc); + } while (sc->cc == '0'); + } + + while (__isdigit_char_or_EOF(sc->cc)) { /* Exponent digits (base 10).*/ + if (seendigit < MAX_EXP_DIGITS) { + ++seendigit; + *b++ = sc->cc; + } + __scan_getc(sc); + } + + if (!seendigit) { /* No digits. Unrecoverable. */ + goto DONE_DO_UNGET; + } + } + + + GOT_FLOAT: + *b = 0; + { + __fpmax_t x; + char *e; + x = __strtofpmax((char *) buf, &e, exp_adjust); + assert(!*e); + if (psfs->store) { + if (psfs->dataargtype & PA_FLAG_LONG_LONG) { + *((long double *)psfs->cur_ptr) = (long double) x; + } else if (psfs->dataargtype & PA_FLAG_LONG) { + *((double *)psfs->cur_ptr) = (double) x; + } else { + *((float *)psfs->cur_ptr) = (float) x; + } + ++psfs->cnt; + } + __scan_ungetc(sc); + return 0; + } +#endif /* __UCLIBC_HAS_FLOATS__ */ + + DONE_DO_UNGET: + __scan_ungetc(sc); + DONE: + return -2; /* Matching failure. */ + +} +#endif +/**********************************************************************/ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_stdio.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_stdio.c new file mode 100644 index 00000000..bf2057b4 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_stdio.c @@ -0,0 +1,465 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + + +/* This is pretty much straight from uClibc, but with one important + * difference. + * + * We now initialize the locking flag to user locking instead of + * auto locking (i.e. FSETLOCKING_BYCALLER vs FSETLOCKING_INTERNAL). + * This greatly benefits non-threading applications linked to a + * shared thread-enabled library. In threading applications, we + * walk the stdio open file list and reset the locking mode + * appropriately when the thread subsystem is initialized. + */ + +/**********************************************************************/ + +#ifdef __UCLIBC_HAS_WCHAR__ +#define __STDIO_FILE_INIT_WUNGOT { 0, 0 }, +#else +#define __STDIO_FILE_INIT_WUNGOT +#endif + +#ifdef __STDIO_GETC_MACRO +# define __STDIO_FILE_INIT_BUFGETC(x) x, +#else +# define __STDIO_FILE_INIT_BUFGETC(x) +#endif + +#ifdef __STDIO_PUTC_MACRO +# define __STDIO_FILE_INIT_BUFPUTC(x) x, +#else +# define __STDIO_FILE_INIT_BUFPUTC(x) +#endif + +#ifdef __STDIO_HAS_OPENLIST +#define __STDIO_FILE_INIT_NEXT(next) (next), +#else +#define __STDIO_FILE_INIT_NEXT(next) +#endif + +#ifdef __STDIO_BUFFERS +#define __STDIO_FILE_INIT_BUFFERS(buf,bufsize) \ + (buf), (buf)+(bufsize), (buf), (buf), +#else +#define __STDIO_FILE_INIT_BUFFERS(buf,bufsize) +#endif + +#ifdef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ +#define __STDIO_FILE_INIT_CUSTOM_STREAM(stream) \ + &((stream).__filedes), { _cs_read, _cs_write, _cs_seek, _cs_close }, +#else +#define __STDIO_FILE_INIT_CUSTOM_STREAM(stream) +#endif + +#ifdef __STDIO_MBSTATE +#define __STDIO_FILE_INIT_MBSTATE \ + { 0, 0 }, +#else +#define __STDIO_FILE_INIT_MBSTATE +#endif + +#ifdef __UCLIBC_HAS_XLOCALE__ +#define __STDIO_FILE_INIT_UNUSED \ + NULL, +#else +#define __STDIO_FILE_INIT_UNUSED +#endif + +#ifdef __UCLIBC_HAS_THREADS__ +#ifdef __USE_STDIO_FUTEXES__ +#define __STDIO_FILE_INIT_THREADSAFE \ + 2, _LIBC_LOCK_RECURSIVE_INITIALIZER, +#else +#define __STDIO_FILE_INIT_THREADSAFE \ + 2, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP, +#endif +#else +#define __STDIO_FILE_INIT_THREADSAFE +#endif + +#define __STDIO_INIT_FILE_STRUCT(stream, flags, filedes, next, buf, bufsize) \ + { (flags), \ + { 0, 0 }, /* ungot[2] (no wchar) or ungot_width[2] (wchar)*/ \ + (filedes), \ + __STDIO_FILE_INIT_BUFFERS(buf,bufsize) \ + __STDIO_FILE_INIT_BUFGETC((buf)) \ + __STDIO_FILE_INIT_BUFPUTC((buf)) \ + __STDIO_FILE_INIT_NEXT(next) \ + __STDIO_FILE_INIT_CUSTOM_STREAM(stream) \ + __STDIO_FILE_INIT_WUNGOT \ + __STDIO_FILE_INIT_MBSTATE \ + __STDIO_FILE_INIT_UNUSED \ + __STDIO_FILE_INIT_THREADSAFE \ +} /* TODO: builtin buf */ + +/**********************************************************************/ +/* First we need the standard files. */ + +#ifdef __STDIO_BUFFERS +static unsigned char _fixed_buffers[2 * BUFSIZ]; +#endif + +static FILE _stdio_streams[] = { + __STDIO_INIT_FILE_STRUCT(_stdio_streams[0], \ + __FLAG_LBF|__FLAG_READONLY, \ + 0, \ + _stdio_streams + 1, \ + _fixed_buffers, \ + BUFSIZ ), + __STDIO_INIT_FILE_STRUCT(_stdio_streams[1], \ + __FLAG_LBF|__FLAG_WRITEONLY, \ + 1, \ + _stdio_streams + 2, \ + _fixed_buffers + BUFSIZ, \ + BUFSIZ ), + __STDIO_INIT_FILE_STRUCT(_stdio_streams[2], \ + __FLAG_NBF|__FLAG_WRITEONLY, \ + 2, \ + NULL, \ + NULL, \ + 0 ) +}; + +FILE *stdin = _stdio_streams; +FILE *stdout = _stdio_streams + 1; +FILE *stderr = _stdio_streams + 2; + +#ifdef __STDIO_GETC_MACRO +FILE *__stdin = _stdio_streams; /* For getchar() macro. */ +#endif +#ifdef __STDIO_PUTC_MACRO +FILE *__stdout = _stdio_streams + 1; /* For putchar() macro. */ +/* FILE *__stderr = _stdio_streams + 2; */ +#endif + +/**********************************************************************/ +#ifdef __STDIO_HAS_OPENLIST + +/* In certain configurations, we need to keep a list of open files. + * 1) buffering enabled - We need to initialize the buffering mode + * (full or line buffering) of stdin and stdout. We also + * need to flush all write buffers prior to normal termination. + * 2) custom streams - Even if we aren't buffering in the library + * itself, we need to fclose() all custom streams when terminating + * so that any special cleanup is done. + * 3) threads enabled - We need to be able to reset the locking mode + * of all open streams when the threading system is initialized. + */ + +FILE *_stdio_openlist = _stdio_streams; + +# ifdef __UCLIBC_HAS_THREADS__ +__UCLIBC_IO_MUTEX_INIT(_stdio_openlist_add_lock); +# ifdef __STDIO_BUFFERS +__UCLIBC_IO_MUTEX_INIT(_stdio_openlist_del_lock); +volatile int _stdio_openlist_use_count = 0; +int _stdio_openlist_del_count = 0; +# endif +# endif +#endif +/**********************************************************************/ +#ifdef __UCLIBC_HAS_THREADS__ + +/* 2 if threading not initialized and 0 otherwise; */ +int _stdio_user_locking = 2; + +#ifndef __USE_STDIO_FUTEXES__ +void attribute_hidden __stdio_init_mutex(__UCLIBC_MUTEX_TYPE *m) +{ + const __UCLIBC_MUTEX_STATIC(__stdio_mutex_initializer, + PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP); + + memcpy(m, &__stdio_mutex_initializer, sizeof(__stdio_mutex_initializer)); +} +#endif + +#endif +/**********************************************************************/ + +/* We assume here that we are the only remaining thread. */ +void attribute_hidden _stdio_term(void) +{ +#if defined(__STDIO_BUFFERS) || defined(__UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__) + register FILE *ptr; + +#ifdef __UCLIBC_HAS_THREADS__ + /* First, make sure the open file list is unlocked. If it was + * locked, then I suppose there is a chance that a pointer in the + * chain might be corrupt due to a partial store. + */ + STDIO_INIT_MUTEX(_stdio_openlist_add_lock); +#warning check +#ifdef __STDIO_BUFFERS + STDIO_INIT_MUTEX(_stdio_openlist_del_lock); +#endif + + /* Next we need to worry about the streams themselves. If a stream + * is currently locked, then it may be in an invalid state. So we + * 'disable' it in case a custom stream is stacked on top of it. + * Then we reinitialize the locks. + */ + for (ptr = _stdio_openlist ; ptr ; ptr = ptr->__nextopen ) { + if (__STDIO_ALWAYS_THREADTRYLOCK_CANCEL_UNSAFE(ptr)) { + /* The stream is already locked, so we don't want to touch it. + * However, if we have custom streams, we can't just close it + * or leave it locked since a custom stream may be stacked + * on top of it. So we do unlock it, while also disabling it. + */ + ptr->__modeflags = (__FLAG_READONLY|__FLAG_WRITEONLY); + __STDIO_STREAM_DISABLE_GETC(ptr); + __STDIO_STREAM_DISABLE_PUTC(ptr); + __STDIO_STREAM_INIT_BUFREAD_BUFPOS(ptr); + } + + ptr->__user_locking = 1; /* Set locking mode to "by caller". */ + STDIO_INIT_MUTEX(ptr->__lock); /* Shouldn't be necessary, but... */ + } +#endif + + /* Finally, flush all writing streams and shut down all custom streams. + * NOTE: We assume that any stacking by custom streams is done on top + * of streams previously allocated, and hence further down the + * list. Otherwise we have no way of knowing the order in which + * to shut them down. + * Remember that freopen() counts as a new allocation here, even + * though the stream is reused. That's because it moves the + * stream to the head of the list. + */ + for (ptr = _stdio_openlist ; ptr ; ptr = ptr->__nextopen ) { +#ifdef __STDIO_BUFFERS + /* Write any pending buffered chars. */ + if (__STDIO_STREAM_IS_WRITING(ptr)) { + __STDIO_COMMIT_WRITE_BUFFER(ptr); + } +#endif +#ifdef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ + /* Actually close all custom streams to perform any special cleanup. */ + if (ptr->__cookie != &ptr->__filedes) { + __CLOSE(ptr); + } +#endif + } + +#endif +} + +#if defined __STDIO_BUFFERS || !defined __UCLIBC__ +void attribute_hidden _stdio_init(void) +{ +#ifdef __NOT_FOR_L4__ +#ifdef __STDIO_BUFFERS + int old_errno = errno; + /* stdin and stdout uses line buffering when connected to a tty. */ + if (!isatty(0)) + _stdio_streams[0].__modeflags ^= __FLAG_LBF; + if (!isatty(1)) + _stdio_streams[1].__modeflags ^= __FLAG_LBF; + __set_errno(old_errno); +#endif +#else +# if defined(__STDIO_BUFFERS) && defined(__UCLIBC_HAS_THREADS__) + register FILE *ptr; + _stdio_user_locking = 0; + for (ptr = _stdio_openlist ; ptr ; ptr = ptr->__nextopen ) { + if (ptr->__user_locking != 1) { + ptr->__user_locking = 0; + } + } +# endif + +#endif + +#ifndef __UCLIBC__ + /* _stdio_term is done automatically when exiting if stdio is used. + * See misc/internals/__uClibc_main.c and and stdlib/atexit.c. */ + atexit(_stdio_term); +#endif +} +#endif + +/**********************************************************************/ + +#if !(__MASK_READING & __FLAG_UNGOT) +#error Assumption violated about __MASK_READING and __FLAG_UNGOT +#endif + +#ifdef __UCLIBC_HAS_THREADS__ +#include +#endif + +#ifndef NDEBUG + +void _stdio_validate_FILE(const FILE *stream) +{ +#ifdef __UCLIBC_HAS_THREADS__ + assert(((unsigned int)(stream->__user_locking)) <= 2); +#endif + +#warning Define a constant for minimum possible valid __filedes? + assert(stream->__filedes >= -3); + + if (stream->__filedes < 0) { +/* assert((stream->__filedes != -1) */ +/* #ifdef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ */ +/* || (stream->__cookie == &stream->__filedes) /\* custom *\/ */ +/* #endif */ +/* ); */ +/* assert((stream->__filedes == -1) || __STDIO_STREAM_IS_FBF(stream)); */ + + assert(!__STDIO_STREAM_IS_FAKE_VSNPRINTF(stream) + || __STDIO_STREAM_IS_NARROW(stream)); + assert(!__STDIO_STREAM_IS_FAKE_VSSCANF(stream) + || __STDIO_STREAM_IS_NARROW(stream)); +#ifdef __STDIO_STREAM_IS_FAKE_VSWPRINTF + assert(!__STDIO_STREAM_IS_FAKE_VSWPRINTF(stream) + || __STDIO_STREAM_IS_WIDE(stream)); +#endif +#ifdef __STDIO_STREAM_IS_FAKE_VSWSCANF + assert(!__STDIO_STREAM_IS_FAKE_VSWSCANF(stream) + || __STDIO_STREAM_IS_WIDE(stream)); +#endif + } + +#ifdef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ + if (stream->__cookie != &stream->__filedes) { /* custom */ + assert(stream->__filedes == -1); + } +#endif + + /* Can not be both narrow and wide oriented at the same time. */ + assert(!(__STDIO_STREAM_IS_NARROW(stream) + && __STDIO_STREAM_IS_WIDE(stream))); + + + /* The following impossible case is used to disable a stream. */ + if ((stream->__modeflags & (__FLAG_READONLY|__FLAG_WRITEONLY)) + == (__FLAG_READONLY|__FLAG_WRITEONLY) + ) { + assert(stream->__modeflags == (__FLAG_READONLY|__FLAG_WRITEONLY)); + assert(stream->__filedes == -1); +#ifdef __STDIO_BUFFERS + assert(stream->__bufpos == stream->__bufstart); + assert(stream->__bufread == stream->__bufstart); +# ifdef __UCLIBC_HAS_STDIO_PUTC_MACRO__ + assert(stream->__bufputc_u == stream->__bufstart); +# endif +# ifdef __UCLIBC_HAS_STDIO_GETC_MACRO__ + assert(stream->__bufgetc_u == stream->__bufstart); +# endif +#endif + } + + if (__STDIO_STREAM_IS_READONLY(stream)) { +/* assert(!__STDIO_STREAM_IS_WRITEONLY(stream)); */ + assert(!__STDIO_STREAM_IS_WRITING(stream)); + if (stream->__modeflags & __FLAG_UNGOT) { + assert(((unsigned)(stream->__ungot[1])) <= 1); + assert(!__FEOF_UNLOCKED(stream)); + } + } + + if (__STDIO_STREAM_IS_WRITEONLY(stream)) { +/* assert(!__STDIO_STREAM_IS_READONLY(stream)); */ + assert(!__STDIO_STREAM_IS_READING(stream)); + assert(!(stream->__modeflags & __FLAG_UNGOT)); + } + + if (__STDIO_STREAM_IS_NBF(stream)) { + /* We require that all non buffered streams have no buffer. */ + assert(!__STDIO_STREAM_BUFFER_SIZE(stream)); + } + + assert((stream->__modeflags & __MASK_BUFMODE) <= __FLAG_NBF); + +#ifdef __STDIO_BUFFERS + /* Ensure __bufstart <= __bufpos <= __bufend. */ + assert(stream->__bufpos >= stream->__bufstart); + assert(stream->__bufpos <= stream->__bufend); + /* Ensure __bufstart <= __bufread <= __bufend. */ + assert(stream->__bufread >= stream->__bufstart); + assert(stream->__bufread <= stream->__bufend); +#endif + + /* If EOF, then we must have no buffered readable or ungots. */ + if (__FEOF_UNLOCKED(stream)) { +#ifdef __STDIO_BUFFERS + assert(stream->__bufpos == stream->__bufread); +#endif + assert(!(stream->__modeflags & __FLAG_UNGOT)); + } + + + if (!__STDIO_STREAM_IS_WRITING(stream)) { +#ifdef __STDIO_BUFFERS + /* If not writing, then putc macro must be disabled. */ +# ifdef __UCLIBC_HAS_STDIO_PUTC_MACRO__ + assert(stream->__bufputc_u == stream->__bufstart); +# endif +#endif + } + + if (!__STDIO_STREAM_IS_READING(stream)) { + /* If not reading, then can not have ungots. */ + assert(!(stream->__modeflags & __FLAG_UNGOT)); +#ifdef __STDIO_BUFFERS + /* Ensure __bufread == __bufstart. */ + assert(stream->__bufread == stream->__bufstart); + /* If not reading, then getc macro must be disabled. */ +# ifdef __UCLIBC_HAS_STDIO_GETC_MACRO__ + assert(stream->__bufgetc_u == stream->__bufstart); +# endif +#endif + } + + if (__STDIO_STREAM_IS_READING(stream)) { + assert(!__STDIO_STREAM_IS_WRITING(stream)); +#ifdef __STDIO_BUFFERS + /* Ensure __bufpos <= __bufread. */ + assert(stream->__bufpos <= stream->__bufread); + + /* Ensure __bufgetc_u is valid. */ +# ifdef __UCLIBC_HAS_STDIO_GETC_MACRO__ + assert(stream->__bufgetc_u >= stream->__bufstart); + assert(stream->__bufgetc_u <= stream->__bufread); +# endif + +#endif + } + + if (__STDIO_STREAM_IS_WRITING(stream)) { + assert(!__STDIO_STREAM_IS_READING(stream)); +#ifdef __STDIO_BUFFERS +# ifdef __UCLIBC_HAS_STDIO_PUTC_MACRO__ + assert(stream->__bufputc_u >= stream->__bufstart); + assert(stream->__bufputc_u <= stream->__bufend); +# endif +#endif + } + + /* If have an ungotten char, then getc (and putc) must be disabled. */ + /* Also, wide streams must have the getc/putc macros disabled. */ + if ((stream->__modeflags & __FLAG_UNGOT) + || __STDIO_STREAM_IS_WIDE(stream) + ) { +#ifdef __STDIO_BUFFERS +# ifdef __UCLIBC_HAS_STDIO_PUTC_MACRO__ + assert(stream->__bufputc_u == stream->__bufstart); +# endif +# ifdef __UCLIBC_HAS_STDIO_GETC_MACRO__ + assert(stream->__bufgetc_u == stream->__bufstart); +# endif +#endif + } + + /* TODO -- filepos? ungot_width? filedes? nextopen? */ +} + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_stdio.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_stdio.h new file mode 100644 index 00000000..ec98f9e0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_stdio.h @@ -0,0 +1,456 @@ +/* Copyright (C) 2004-2005 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef __UCLIBC_HAS_WCHAR__ +#include +#endif + +#include + +#define __STDIO_THREADLOCK_OPENLIST_ADD \ + __UCLIBC_IO_MUTEX_LOCK(_stdio_openlist_add_lock) + +#define __STDIO_THREADUNLOCK_OPENLIST_ADD \ + __UCLIBC_IO_MUTEX_UNLOCK(_stdio_openlist_add_lock) + +#ifdef __STDIO_BUFFERS + +#define __STDIO_THREADLOCK_OPENLIST_DEL \ + __UCLIBC_IO_MUTEX_LOCK(_stdio_openlist_del_lock) + +#define __STDIO_THREADUNLOCK_OPENLIST_DEL \ + __UCLIBC_IO_MUTEX_UNLOCK(_stdio_openlist_del_lock) + + +#ifdef __UCLIBC_HAS_THREADS__ +#define __STDIO_OPENLIST_INC_USE \ +do { \ + __STDIO_THREADLOCK_OPENLIST_DEL; \ + ++_stdio_openlist_use_count; \ + __STDIO_THREADUNLOCK_OPENLIST_DEL; \ +} while (0) + +extern void _stdio_openlist_dec_use(void) attribute_hidden; + +#define __STDIO_OPENLIST_DEC_USE \ + _stdio_openlist_dec_use() + +#define __STDIO_OPENLIST_INC_DEL_CNT \ +do { \ + __STDIO_THREADLOCK_OPENLIST_DEL; \ + ++_stdio_openlist_del_count; \ + __STDIO_THREADUNLOCK_OPENLIST_DEL; \ +} while (0) + +#define __STDIO_OPENLIST_DEC_DEL_CNT \ +do { \ + __STDIO_THREADLOCK_OPENLIST_DEL; \ + --_stdio_openlist_del_count; \ + __STDIO_THREADUNLOCK_OPENLIST_DEL; \ +} while (0) + +#endif /* __UCLIBC_HAS_THREADS__ */ +#endif /* __STDIO_BUFFERS */ + +#ifndef __STDIO_THREADLOCK_OPENLIST_DEL +#define __STDIO_THREADLOCK_OPENLIST_DEL ((void)0) +#endif +#ifndef __STDIO_THREADUNLOCK_OPENLIST_DEL +#define __STDIO_THREADUNLOCK_OPENLIST_DEL ((void)0) +#endif +#ifndef __STDIO_OPENLIST_INC_USE +#define __STDIO_OPENLIST_INC_USE ((void)0) +#endif +#ifndef __STDIO_OPENLIST_DEC_USE +#define __STDIO_OPENLIST_DEC_USE ((void)0) +#endif +#ifndef __STDIO_OPENLIST_INC_DEL_CNT +#define __STDIO_OPENLIST_INC_DEL_CNT ((void)0) +#endif +#ifndef __STDIO_OPENLIST_DEC_DEL_CNT +#define __STDIO_OPENLIST_DEC_DEL_CNT ((void)0) +#endif + +#define __UNDEFINED_OR_NONPORTABLE ((void)0) + +/**********************************************************************/ +#ifdef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ + +extern __ssize_t _cs_read(void *cookie, char *buf, size_t bufsize) attribute_hidden; +extern __ssize_t _cs_write(void *cookie, const char *buf, size_t bufsize) attribute_hidden; +extern int _cs_seek(void *cookie, __offmax_t *pos, int whence) attribute_hidden; +extern int _cs_close(void *cookie) attribute_hidden; + +#define __STDIO_STREAM_RESET_GCS(S) \ + (S)->__cookie = &((S)->__filedes); \ + (S)->__gcs.read = _cs_read; \ + (S)->__gcs.write = _cs_write; \ + (S)->__gcs.seek = _cs_seek; \ + (S)->__gcs.close = _cs_close + + +#define __READ(STREAMPTR,BUF,SIZE) \ + ((((STREAMPTR)->__gcs.read) == NULL) ? -1 : \ + (((STREAMPTR)->__gcs.read)((STREAMPTR)->__cookie,(BUF),(SIZE)))) +#define __WRITE(STREAMPTR,BUF,SIZE) \ + ((((STREAMPTR)->__gcs.write) == NULL) ? -1 : \ + (((STREAMPTR)->__gcs.write)((STREAMPTR)->__cookie,(BUF),(SIZE)))) +#define __SEEK(STREAMPTR,PPOS,WHENCE) \ + ((((STREAMPTR)->__gcs.seek) == NULL) ? -1 : \ + (((STREAMPTR)->__gcs.seek)((STREAMPTR)->__cookie,(PPOS),(WHENCE)))) +#define __CLOSE(STREAMPTR) \ + ((((STREAMPTR)->__gcs.close) == NULL) ? 0 : \ + (((STREAMPTR)->__gcs.close)((STREAMPTR)->__cookie))) + +#else /* __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ */ + +extern int __stdio_seek(FILE *stream, register __offmax_t *pos, int whence) attribute_hidden; + +#define __STDIO_STREAM_RESET_GCS(S) ((void)0) + +#define __READ(STREAMPTR,BUF,SIZE) \ + (read((STREAMPTR)->__filedes,(BUF),(SIZE))) +#define __WRITE(STREAMPTR,BUF,SIZE) \ + (write((STREAMPTR)->__filedes,(BUF),(SIZE))) +#define __SEEK(STREAMPTR,PPOS,WHENCE) \ + (__stdio_seek((STREAMPTR),(PPOS),(WHENCE))) +#define __CLOSE(STREAMPTR) \ + (close((STREAMPTR)->__filedes)) + +#endif /* __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ */ + +/**********************************************************************/ +#ifdef __UCLIBC_HAS_WCHAR__ + +#define __STDIO_STREAM_TRANS_TO_WRITE(S,O) __stdio_trans2w_o((S), (O)) +#define __STDIO_STREAM_TRANS_TO_READ(S,O) __stdio_trans2r_o((S), (O)) + +#else + +#define __STDIO_STREAM_TRANS_TO_WRITE(S,O) __stdio_trans2w((S)) +#define __STDIO_STREAM_TRANS_TO_READ(S,O) __stdio_trans2r((S)) + +#endif +/**********************************************************************/ + +#define __STDIO_STREAM_IS_READING(S) ((S)->__modeflags & __MASK_READING) +#define __STDIO_STREAM_IS_WRITING(S) ((S)->__modeflags & __FLAG_WRITING) + +#define __STDIO_STREAM_SET_READING(S) ((S)->__modeflags |= __FLAG_READING) +#define __STDIO_STREAM_SET_WRITING(S) ((S)->__modeflags |= __FLAG_WRITING) + +#define __STDIO_STREAM_IS_READING_OR_READONLY(S) \ + ((S)->__modeflags & (__MASK_READING|__FLAG_READONLY)) + +#define __STDIO_STREAM_IS_WRITING_OR_WRITEONLY(S) \ + ((S)->__modeflags & (__FLAG_WRITING|__FLAG_WRITEONLY)) + +#define __STDIO_STREAM_IS_READONLY(S) ((S)->__modeflags & __FLAG_READONLY) +#define __STDIO_STREAM_IS_WRITEONLY(S) ((S)->__modeflags & __FLAG_WRITEONLY) + + +/**********************************************************************/ +#ifdef __UCLIBC_HAS_WCHAR__ + +#define __STDIO_STREAM_IS_NARROW_WRITING(S) \ + (((S)->__modeflags & (__FLAG_WRITING|__FLAG_NARROW)) \ + == (__FLAG_WRITING|__FLAG_NARROW)) + +#define __STDIO_STREAM_IS_WIDE_WRITING(S) \ + (((S)->__modeflags & (__FLAG_WRITING|__FLAG_WIDE)) \ + == (__FLAG_WRITING|__FLAG_WIDE)) + +#if (__FLAG_NARROW <= __MASK_READING) +#error assumption violated regarding __FLAG_NARROW +#endif + +#define __STDIO_STREAM_IS_NARROW_READING(S) \ + (((S)->__modeflags & (__MASK_READING|__FLAG_NARROW)) > __FLAG_NARROW) + +#define __STDIO_STREAM_IS_WIDE_READING(S) \ + (((S)->__modeflags & (__MASK_READING|__FLAG_WIDE)) > __FLAG_WIDE) + +#define __STDIO_STREAM_IS_NARROW(S) ((S)->__modeflags & __FLAG_NARROW) +#define __STDIO_STREAM_IS_WIDE(S) ((S)->__modeflags & __FLAG_WIDE) + +#define __STDIO_STREAM_SET_NARROW(S) \ + ((void)((S)->__modeflags |= __FLAG_NARROW)) +#define __STDIO_STREAM_SET_WIDE(S) \ + ((void)((S)->__modeflags |= __FLAG_WIDE)) + +#else + +#define __STDIO_STREAM_IS_NARROW_WRITING(S) __STDIO_STREAM_IS_WRITING(S) + +#define __STDIO_STREAM_IS_NARROW_READING(S) __STDIO_STREAM_IS_READING(S) + +#define __STDIO_STREAM_IS_NARROW(S) (1) +#define __STDIO_STREAM_IS_WIDE(S) (0) + +#define __STDIO_STREAM_SET_NARROW(S) ((void)0) +#define __STDIO_STREAM_SET_WIDE(S) ((void)0) + +#endif +/**********************************************************************/ + +#define __STDIO_STREAM_SET_EOF(S) \ + ((void)((S)->__modeflags |= __FLAG_EOF)) +#define __STDIO_STREAM_SET_ERROR(S) \ + ((void)((S)->__modeflags |= __FLAG_ERROR)) + +#define __STDIO_STREAM_CLEAR_EOF(S) \ + ((void)((S)->__modeflags &= ~__FLAG_EOF)) +#define __STDIO_STREAM_CLEAR_ERROR(S) \ + ((void)((S)->__modeflags &= ~__FLAG_ERROR)) + +#define __STDIO_STREAM_CLEAR_READING_AND_UNGOTS(S) \ + ((void)((S)->__modeflags &= ~__MASK_READING)) +#define __STDIO_STREAM_CLEAR_WRITING(S) \ + ((void)((S)->__modeflags &= ~__FLAG_WRITING)) + +#ifdef __UCLIBC_HAS_STDIO_GETC_MACRO__ +# define __STDIO_STREAM_DISABLE_GETC(S) \ + ((void)((S)->__bufgetc_u = (S)->__bufstart)) +# define __STDIO_STREAM_ENABLE_GETC(S) \ + ((void)((S)->__bufgetc_u = (S)->__bufread)) +# define __STDIO_STREAM_CAN_USE_BUFFER_GET(S) \ + ((S)->__bufpos < (S)->__bufgetc_u) +#else +# define __STDIO_STREAM_DISABLE_GETC(S) ((void)0) +# define __STDIO_STREAM_ENABLE_GETC(S) ((void)0) +# define __STDIO_STREAM_CAN_USE_BUFFER_GET(S) (0) +#endif + +#ifdef __UCLIBC_HAS_STDIO_PUTC_MACRO__ +# define __STDIO_STREAM_DISABLE_PUTC(S) \ + ((void)((S)->__bufputc_u = (S)->__bufstart)) +# define __STDIO_STREAM_ENABLE_PUTC(S) \ + ((void)((S)->__bufputc_u = (S)->__bufend)) +# define __STDIO_STREAM_CAN_USE_BUFFER_ADD(S) \ + ((S)->__bufpos < (S)->__bufputc_u) +#else +# define __STDIO_STREAM_DISABLE_PUTC(S) ((void)0) +# define __STDIO_STREAM_ENABLE_PUTC(S) ((void)0) +# define __STDIO_STREAM_CAN_USE_BUFFER_ADD(S) (0) +#endif + +#ifdef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ +#define __STDIO_STREAM_IS_CUSTOM(S) ((S)->__cookie != &((S)->__filedes)) +#else +#define __STDIO_STREAM_IS_CUSTOM(S) (0) +#endif + +/**********************************************************************/ + +#ifdef __STDIO_BUFFERS +#define __STDIO_STREAM_FREE_BUFFER(S) \ + do { if ((S)->__modeflags & __FLAG_FREEBUF) \ + free((S)->__bufstart); } while (0) +#else +#define __STDIO_STREAM_FREE_BUFFER(S) ((void)0) +#endif + +#define __STDIO_STREAM_FREE_FILE(S) \ + do { if ((S)->__modeflags & __FLAG_FREEFILE) \ + free((S)); } while (0) + + +#ifdef __UCLIBC_HAS_LFS__ +#define __STDIO_WHEN_LFS(E) E +#else +#define __STDIO_WHEN_LFS(E) ((void)0) +#endif + +/**********************************************************************/ +/* The following return 0 on success. */ + +#ifdef __STDIO_BUFFERS +/* Assume stream in valid writing state. Do not reset writing flag + * or disble putc macro unless error. */ +/* Should we assume that buffer is not empty to avoid a check? */ +extern size_t __stdio_wcommit(FILE *__restrict stream) attribute_hidden; + +/* Remember to fail if at EOF! */ +extern size_t __stdio_rfill(FILE *__restrict stream) attribute_hidden; + +extern size_t __stdio_fwrite(const unsigned char *__restrict buffer, + size_t bytes, FILE *__restrict stream) attribute_hidden; +#else + +#define __stdio_fwrite(B,N,S) __stdio_WRITE((S),(B),(N)) + +#endif + +extern size_t __stdio_WRITE(FILE *stream, const unsigned char *buf, + size_t bufsize) attribute_hidden; +extern size_t __stdio_READ(FILE *stream, unsigned char *buf, + size_t bufsize) attribute_hidden; + +extern int __stdio_trans2r(FILE *__restrict stream) attribute_hidden; +extern int __stdio_trans2w(FILE *__restrict stream) attribute_hidden; + +extern int __stdio_trans2r_o(FILE *__restrict stream, int oflag) attribute_hidden; +extern int __stdio_trans2w_o(FILE *__restrict stream, int oflag) attribute_hidden; + +/**********************************************************************/ +#ifdef __STDIO_BUFFERS + +#define __STDIO_STREAM_IS_FBF(S) (!((S)->__modeflags & __MASK_BUFMODE)) +#define __STDIO_STREAM_IS_LBF(S) ((S)->__modeflags & __FLAG_LBF) +#define __STDIO_STREAM_IS_NBF(S) ((S)->__modeflags & __FLAG_NBF) + +#define __STDIO_STREAM_BUFFER_SIZE(S) ((S)->__bufend - (S)->__bufstart) + +/* Valid when writing... */ +#define __STDIO_STREAM_BUFFER_ADD(S,C) (*(S)->__bufpos++ = (C)) +#define __STDIO_STREAM_BUFFER_UNADD(S) (--(S)->__bufpos) +#define __STDIO_STREAM_BUFFER_WAVAIL(S) ((S)->__bufend - (S)->__bufpos) +#define __STDIO_STREAM_BUFFER_WUSED(S) ((S)->__bufpos - (S)->__bufstart) +#define __STDIO_COMMIT_WRITE_BUFFER(S) __stdio_wcommit((S)) +#ifdef __UCLIBC_HAS_WCHAR__ +#define __STDIO_STREAM_IS_NARROW_FBF(S) \ + (!((S)->__modeflags & (__MASK_BUFMODE|__FLAG_WIDE))) +#else +#define __STDIO_STREAM_IS_NARROW_FBF(S) __STDIO_STREAM_IS_FBF((S)) +#endif + +/* Valid when reading... */ +#define __STDIO_STREAM_BUFFER_RAVAIL(S) ((S)->__bufread - (S)->__bufpos) +#define __STDIO_STREAM_BUFFER_GET(S) (*(S)->__bufpos++) +#define __STDIO_FILL_READ_BUFFER(S) __stdio_rfill((S)) + +#define __STDIO_STREAM_INIT_BUFREAD_BUFPOS(S) \ + (S)->__bufread = (S)->__bufpos = (S)->__bufstart + + +#define __STDIO_STREAM_FAKE_VSNPRINTF_FILEDES (-2) +#define __STDIO_STREAM_FAKE_VSSCANF_FILEDES (-2) +#define __STDIO_STREAM_FAKE_VSWPRINTF_FILEDES (-3) +#define __STDIO_STREAM_FAKE_VSWSCANF_FILEDES (-3) + +#define __STDIO_STREAM_IS_FAKE_VSNPRINTF(S) \ + ((S)->__filedes == __STDIO_STREAM_FAKE_VSNPRINTF_FILEDES) +#define __STDIO_STREAM_IS_FAKE_VSSCANF(S) \ + ((S)->__filedes == __STDIO_STREAM_FAKE_VSSCANF_FILEDES) +#define __STDIO_STREAM_IS_FAKE_VSWPRINTF(S) \ + ((S)->__filedes == __STDIO_STREAM_FAKE_VSWPRINTF_FILEDES) +#define __STDIO_STREAM_IS_FAKE_VSWSCANF(S) \ + ((S)->__filedes == __STDIO_STREAM_FAKE_VSWSCANF_FILEDES) + +#else /* __STDIO_BUFFERS */ + +#define __STDIO_STREAM_IS_FBF(S) (0) +#define __STDIO_STREAM_IS_LBF(S) (0) +#define __STDIO_STREAM_IS_NBF(S) (1) + +#define __STDIO_STREAM_BUFFER_SIZE(S) (0) +#define __STDIO_STREAM_BUFFER_ADD(S,C) ((void)0) +#define __STDIO_STREAM_BUFFER_UNADD(S) ((void)0) +#define __STDIO_STREAM_BUFFER_WAVAIL(S) (0) +#define __STDIO_STREAM_BUFFER_WUSED(S) (0) +#define __STDIO_COMMIT_WRITE_BUFFER(S) (0) +#define __STDIO_STREAM_IS_NARROW_FBF(S) (0) + +#define __STDIO_STREAM_BUFFER_RAVAIL(S) (0) +#define __STDIO_STREAM_BUFFER_GET(S) (EOF) +#define __STDIO_FILL_READ_BUFFER(S) (0) +#define __STDIO_STREAM_INIT_BUFREAD_BUFPOS(S) ((void)0) + +#undef __STDIO_STREAM_FAKE_VSNPRINTF_FILEDES +#undef __STDIO_STREAM_FAKE_VSSCANF_FILEDES +#undef __STDIO_STREAM_FAKE_VSWPRINTF_FILEDES + +#define __STDIO_STREAM_IS_FAKE_VSNPRINTF(S) (0) +#define __STDIO_STREAM_IS_FAKE_VSSCANF(S) (0) +#undef __STDIO_STREAM_IS_FAKE_VSWPRINTF + +# ifdef __USE_OLD_VFPRINTF__ +# define __STDIO_STREAM_FAKE_VSNPRINTF_FILEDES_NB (-2) +# define __STDIO_STREAM_IS_FAKE_VSNPRINTF_NB(S) \ + ((S)->__filedes == __STDIO_STREAM_FAKE_VSNPRINTF_FILEDES_NB) +# endif + +# ifndef __UCLIBC_HAS_WCHAR__ +# define __STDIO_STREAM_FAKE_VSSCANF_FILEDES_NB (-2) +# define __STDIO_STREAM_IS_FAKE_VSSCANF_NB(S) \ + ((S)->__filedes == __STDIO_STREAM_FAKE_VSSCANF_FILEDES_NB) +# endif + +#endif /* __STDIO_BUFFERS */ +/**********************************************************************/ + +extern int __stdio_adjust_position(FILE *__restrict stream, __offmax_t *pos) attribute_hidden; + +#ifdef __STDIO_HAS_OPENLIST + /* Uses an implementation hack!!! */ +#define __STDIO_FLUSH_LBF_STREAMS \ + fflush_unlocked((FILE *) &_stdio_openlist) +#else +#define __STDIO_FLUSH_LBF_STREAMS ((void)0) +#endif + +#ifdef NDEBUG +#define __STDIO_STREAM_VALIDATE(S) ((void)0) +#else +extern void _stdio_validate_FILE(const FILE *stream); +#define __STDIO_STREAM_VALIDATE(S) _stdio_validate_FILE((S)) +#endif + +#ifdef __STDIO_MBSTATE +#define __COPY_MBSTATE(dest,src) \ + ((void)((dest)->__mask = (src)->__mask, (dest)->__wc = (src)->__wc)) +#define __INIT_MBSTATE(dest) ((void)((dest)->__mask = 0)) +#else +#define __COPY_MBSTATE(dest,src) ((void)0) +#define __INIT_MBSTATE(dest) ((void)0) +#endif + +/**********************************************************************/ + +extern FILE *_stdio_fopen(intptr_t fname_or_mode, const char *__restrict mode, + FILE *__restrict stream, int filedes) attribute_hidden; + +#ifdef __UCLIBC_HAS_WCHAR__ +extern size_t _wstdio_fwrite(const wchar_t *__restrict ws, + size_t n, FILE *__restrict stream) attribute_hidden; +#endif + +/**********************************************************************/ + +extern int _vfprintf_internal (FILE * __restrict stream, + const char * __restrict format, + va_list arg) attribute_hidden; + +#ifdef __UCLIBC_HAS_WCHAR__ +extern int _vfwprintf_internal (FILE * __restrict stream, + const wchar_t * __restrict format, + va_list arg) attribute_hidden; +#endif + +/**********************************************************************/ +/* Only use the macro below if you know fp is a valid FILE for a valid fd. + * This is _not_ true for custom streams! */ +#define __FILENO_UNLOCKED(fp) ((fp)->__filedes) + +#define __FEOF_OR_FERROR_UNLOCKED(stream) \ + ((stream)->__modeflags & (__FLAG_EOF|__FLAG_ERROR)) + +#if defined(__STDIO_BUFFERS) || defined(__USE_OLD_VFPRINTF__) || defined(__UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__) +#define __STDIO_HAS_VSNPRINTF 1 +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_store_inttype.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_store_inttype.c new file mode 100644 index 00000000..fdd4dce0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_store_inttype.c @@ -0,0 +1,58 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" +#include + +/* Right now, we assume intmax_t is either long or long long */ + +#ifdef INTMAX_MAX + +#ifdef LLONG_MAX + +#if INTMAX_MAX > LLONG_MAX +#error INTMAX_MAX > LLONG_MAX! The printf code needs to be updated! +#endif + +#elif INTMAX_MAX > LONG_MAX + +#error No LLONG_MAX and INTMAX_MAX > LONG_MAX! The printf code needs to be updated! + +#endif /* LLONG_MAX */ + +#endif /* INTMAX_MAX */ + +/* We assume int may be short or long, but short and long are different. */ + +void _store_inttype(register void *dest, int desttype, uintmax_t val) attribute_hidden; +void _store_inttype(register void *dest, int desttype, uintmax_t val) +{ + if (desttype == __PA_FLAG_CHAR) { /* assume char not int */ + *((unsigned char *) dest) = val; + return; + } +#if defined(LLONG_MAX) && (INT_MAX != LLONG_MAX) + if (desttype == PA_FLAG_LONG_LONG) { + *((unsigned long long int *) dest) = val; + return; + } +#endif /* LLONG_MAX */ +#if SHRT_MAX != INT_MAX + if (desttype == PA_FLAG_SHORT) { + *((unsigned short int *) dest) = val; + return; + } +#endif /* SHRT_MAX */ +#if LONG_MAX != INT_MAX + if (desttype == PA_FLAG_LONG) { + *((unsigned long int *) dest) = val; + return; + } +#endif /* LONG_MAX */ + + *((unsigned int *) dest) = val; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_trans2r.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_trans2r.c new file mode 100644 index 00000000..1f393007 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_trans2r.c @@ -0,0 +1,79 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +/* Function to handle transition to reading. + * Initialize or verify the stream's orientation (even if writeonly). + * Check that the stream is readable. + * If currently reading, check that we can transition to writing. + * C99 requires that we not be reading, but attempting to + * auto-transition by commiting the write buffer is a configurable + * option. + * Returns 0 on success and EOF otherwise. + * + * Notes: + * There are two function signatures, depending on wchar support, + * since with no wchar support the orientation is narrow by default. + */ + +#ifdef __UCLIBC_HAS_WCHAR__ +int attribute_hidden __stdio_trans2r_o(FILE * __restrict stream, int oflag) +#else +int attribute_hidden __stdio_trans2r(FILE * __restrict stream) +#endif +{ + __STDIO_STREAM_VALIDATE(stream); + assert(!__STDIO_STREAM_IS_READING(stream)); + +#ifdef __UCLIBC_HAS_WCHAR__ + if (!(stream->__modeflags & oflag)) { + if (stream->__modeflags & (__FLAG_NARROW|__FLAG_WIDE)) { + __UNDEFINED_OR_NONPORTABLE; + goto DO_EBADF; + } + stream->__modeflags |= oflag; + } +#endif + + if (stream->__modeflags & __FLAG_WRITEONLY) { +#if defined(__UCLIBC_HAS_WCHAR__) || !defined(__UCLIBC_HAS_STDIO_AUTO_RW_TRANSITION__) + DO_EBADF: +#endif + __set_errno(EBADF); +#ifdef __UCLIBC_HAS_STDIO_AUTO_RW_TRANSITION__ + ERROR: +#endif + __STDIO_STREAM_SET_ERROR(stream); + __STDIO_STREAM_VALIDATE(stream); + return EOF; + } + + if (__STDIO_STREAM_IS_WRITING(stream)) { +#ifdef __UCLIBC_HAS_STDIO_AUTO_RW_TRANSITION__ + if (__STDIO_COMMIT_WRITE_BUFFER(stream)) { /* commit failed! */ + goto ERROR; + } + assert(!__STDIO_STREAM_BUFFER_WUSED(stream)); + + __STDIO_STREAM_DISABLE_PUTC(stream); + __STDIO_STREAM_CLEAR_WRITING(stream); +#else + /* C99: Output shall not be directly followed by input without an + intervening call to the fflush function or to a file positioning + function (fseek, fsetpos, or rewind). */ + __UNDEFINED_OR_NONPORTABLE; + goto DO_EBADF; +#endif + } + + __STDIO_STREAM_SET_READING(stream); + /* getc macro is enabled when data is read into buffer. */ + + __STDIO_STREAM_VALIDATE(stream); + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_trans2w.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_trans2w.c new file mode 100644 index 00000000..c7223793 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_trans2w.c @@ -0,0 +1,94 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + + +/* Function to handle transition to writing. + * Initialize or verify the stream's orientation (even if readonly). + * Check that the stream is writable. + * If currently reading, check that we can transition to writing. + * C99 requires that the stream is at EOF, but attempting to + * auto-transition via fseek() is a configurable option. + * Returns 0 on success and EOF otherwise. + * + * Notes: + * There are two function signatures, depending on wchar support, + * since with no wchar support the orientation is narrow by default. + */ + +#ifdef __UCLIBC_HAS_WCHAR__ +int attribute_hidden __stdio_trans2w_o(FILE * __restrict stream, int oflag) +#else +int attribute_hidden __stdio_trans2w(FILE * __restrict stream) +#endif +{ + __STDIO_STREAM_VALIDATE(stream); + assert(!__STDIO_STREAM_IS_WRITING(stream)); + +#ifdef __UCLIBC_HAS_WCHAR__ + if (!(stream->__modeflags & oflag)) { + if (stream->__modeflags & (__FLAG_NARROW|__FLAG_WIDE)) { + __UNDEFINED_OR_NONPORTABLE; + goto DO_EBADF; + } + stream->__modeflags |= oflag; + } +#endif + + if (stream->__modeflags & __FLAG_READONLY) { +#if defined(__UCLIBC_HAS_WCHAR__) || !defined(__UCLIBC_HAS_STDIO_AUTO_RW_TRANSITION__) + DO_EBADF: +#endif + __set_errno(EBADF); +#ifdef __UCLIBC_HAS_STDIO_AUTO_RW_TRANSITION__ + ERROR: +#endif + __STDIO_STREAM_SET_ERROR(stream); + __STDIO_STREAM_VALIDATE(stream); + return EOF; + } + + if (__STDIO_STREAM_IS_READING(stream)) { + if (!__FEOF_UNLOCKED(stream)) { +#ifdef __UCLIBC_HAS_STDIO_AUTO_RW_TRANSITION__ + /* Need to seek to correct position if we have buffered + * read data or ungots. If appending, we might as well + * seek to the end. + * + * NOTE: If the OS does not handle append files correctly, + * this is insufficient since we would need to seek to + * the end even if not reading.*/ + if (((__STDIO_STREAM_BUFFER_RAVAIL(stream)) + || (stream->__modeflags & __FLAG_UNGOT)) + && fseek(stream, 0L, + ((stream->__modeflags & __FLAG_APPEND) + ? SEEK_END : SEEK_CUR)) + ) { + /* fseek() only sets error indicator on read/write error. */ + goto ERROR; + } +#else + /* C99 requires either at EOF or currently not reading. */ + __UNDEFINED_OR_NONPORTABLE; + goto DO_EBADF; +#endif + } + __STDIO_STREAM_CLEAR_READING_AND_UNGOTS(stream); + __STDIO_STREAM_DISABLE_GETC(stream); + /* Reaching EOF does not reset buffer pointers... */ + __STDIO_STREAM_INIT_BUFREAD_BUFPOS(stream); + } + + __STDIO_STREAM_SET_WRITING(stream); + if (__STDIO_STREAM_IS_NARROW_FBF(stream)) { + __STDIO_STREAM_ENABLE_PUTC(stream); + } + + __STDIO_STREAM_VALIDATE(stream); + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_uintmaxtostr.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_uintmaxtostr.c new file mode 100644 index 00000000..e501165a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_uintmaxtostr.c @@ -0,0 +1,152 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#define _ISOC99_SOURCE /* for ULLONG primarily... */ +#include "_stdio.h" +#include +#include +#include + + +/* Avoid using long long / and % operations to cut down dependencies on + * libgcc.a. Definitely helps on i386 at least. */ +#if (INTMAX_MAX > INT_MAX) && (((INTMAX_MAX/INT_MAX)/2) - 2 <= INT_MAX) +#define INTERNAL_DIV_MOD +#endif + +char attribute_hidden *_uintmaxtostr(register char * __restrict bufend, uintmax_t uval, + int base, __UIM_CASE alphacase) +{ + int negative; + unsigned int digit; +#ifdef INTERNAL_DIV_MOD + unsigned int H, L, high, low, rh; +#endif +#ifndef __LOCALE_C_ONLY + int grouping, outdigit; + const char *g; /* This does not need to be initialized. */ +#endif /* __LOCALE_C_ONLY */ + + negative = 0; + if (base < 0) { /* signed value */ + base = -base; + if (uval > INTMAX_MAX) { + uval = -uval; + negative = 1; + } + } + + /* this is an internal routine -- we shouldn't need to check this */ + assert(!((base < 2) || (base > 36))); + +#ifndef __LOCALE_C_ONLY + grouping = -1; + outdigit = 0x80 & alphacase; + alphacase ^= outdigit; + if (alphacase == __UIM_GROUP) { + assert(base == 10); + if (*(g = __UCLIBC_CURLOCALE->grouping)) { + grouping = *g; + } + } +#endif /* __LOCALE_C_ONLY */ + + *bufend = '\0'; + +#ifndef INTERNAL_DIV_MOD + do { +#ifndef __LOCALE_C_ONLY + if (!grouping) { /* Finished a group. */ + bufend -= __UCLIBC_CURLOCALE->thousands_sep_len; + memcpy(bufend, __UCLIBC_CURLOCALE->thousands_sep, + __UCLIBC_CURLOCALE->thousands_sep_len); + if (g[1] != 0) { /* g[1] == 0 means repeat last grouping. */ + /* Note: g[1] == -1 means no further grouping. But since + * we'll never wrap around, we can set grouping to -1 without + * fear of */ + ++g; + } + grouping = *g; + } + --grouping; +#endif /* __LOCALE_C_ONLY */ + digit = uval % base; + uval /= base; + +#ifndef __LOCALE_C_ONLY + if (unlikely(outdigit)) { + bufend -= __UCLIBC_CURLOCALE->outdigit_length[digit]; + memcpy(bufend, + (&__UCLIBC_CURLOCALE->outdigit0_mb)[digit], + __UCLIBC_CURLOCALE->outdigit_length[digit]); + } else +#endif + { + *--bufend = ( (digit < 10) ? digit + '0' : digit + alphacase ); + } + } while (uval); + +#else /* ************************************************** */ + + H = (UINT_MAX / base); + L = UINT_MAX % base + 1; + if (L == base) { + ++H; + L = 0; + } + low = (unsigned int) uval; + high = (unsigned int) (uval >> (sizeof(unsigned int) * CHAR_BIT)); + + do { +#ifndef __LOCALE_C_ONLY + if (!grouping) { /* Finished a group. */ + bufend -= __UCLIBC_CURLOCALE->thousands_sep_len; + memcpy(bufend, __UCLIBC_CURLOCALE->thousands_sep, + __UCLIBC_CURLOCALE->thousands_sep_len); + if (g[1] != 0) { /* g[1] == 0 means repeat last grouping. */ + /* Note: g[1] == -1 means no further grouping. But since + * we'll never wrap around, we can set grouping to -1 without + * fear of */ + ++g; + } + grouping = *g; + } + --grouping; +#endif /* __LOCALE_C_ONLY */ + + if (unlikely(high)) { + rh = high % base; + high /= base; + digit = (low % base) + (L * rh); + low = (low / base) + (H * rh) + (digit / base); + digit %= base; + } else { + digit = low % base; + low /= base; + } + +#ifndef __LOCALE_C_ONLY + if (unlikely(outdigit)) { + bufend -= __UCLIBC_CURLOCALE->outdigit_length[digit]; + memcpy(bufend, + (&__UCLIBC_CURLOCALE->outdigit0_mb)[digit], + __UCLIBC_CURLOCALE->outdigit_length[digit]); + } else +#endif + { + *--bufend = ( (digit < 10) ? digit + '0' : digit + alphacase ); + } + } while (low | high); + +#endif /******************************************************/ + + if (negative) { + *--bufend = '-'; + } + + return bufend; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_vfprintf.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_vfprintf.c new file mode 100644 index 00000000..3b007084 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_vfprintf.c @@ -0,0 +1,1969 @@ +/* Copyright (C) 2002-2004 Manuel Novoa III + * My stdio library for linux and (soon) elks. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* This code needs a lot of clean up. Some of that is on hold until uClibc + * gets a better configuration system (on Erik's todo list). + * The other cleanup will take place during the implementation/integration of + * the wide char (un)formatted i/o functions which I'm currently working on. + */ + +/* ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION! + * + * This code is currently under development. Also, I plan to port + * it to elks which is a 16-bit environment with a fairly limited + * compiler. Therefore, please refrain from modifying this code + * and, instead, pass any bug-fixes, etc. to me. Thanks. Manuel + * + * ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION! */ + + +/* April 1, 2002 + * Initialize thread locks for fake files in vsnprintf and vdprintf. + * reported by Erik Andersen (andersen@codepoet.com) + * Fix an arg promotion handling bug in _do_one_spec for %c. + * reported by Ilguiz Latypov + * + * May 10, 2002 + * Remove __isdigit and use new ctype.h version. + * Add conditional setting of QUAL_CHARS for size_t and ptrdiff_t. + * + * Aug 16, 2002 + * Fix two problems that showed up with the python 2.2.1 tests; one + * involving %o and one involving %f. + * + * Oct 28, 2002 + * Fix a problem in vasprintf (reported by vodz a while back) when built + * without custom stream support. In that case, it is necessary to do + * a va_copy. + * Make sure each va_copy has a matching va_end, as required by C99. + * + * Nov 4, 2002 + * Add locale-specific grouping support for integer decimal conversion. + * Add locale-specific decimal point support for floating point conversion. + * Note: grouping will have to wait for _dtostr() rewrite. + * Add printf wchar support for %lc (%C) and %ls (%S). + * Require printf format strings to be valid multibyte strings beginning and + * ending in their initial shift state, as per the stds. + * + * Nov 21, 2002 + * Add *wprintf functions. Currently they don't support floating point + * conversions. That will wait until the rewrite of _dtostr. + * + * Aug 1, 2003 + * Optional hexadecimal float notation support for %a/%A. + * Floating point output now works for *wprintf. + * Support for glibc locale-specific digit grouping for floats. + * Misc bug fixes. + * + * Aug 31, 2003 + * Fix precision bug for %g conversion specifier when using %f style. + * + * Sep 5, 2003 + * Implement *s*scanf for the non-buffered stdio case with old_vfprintf. + * + * Sep 23, 2003 + * vfprintf was not always checking for narrow stream orientation. + */ + +/* TODO: + * + * Should we validate that *printf format strings are valid multibyte + * strings in the current locale? ANSI/ISO C99 seems to imply this + * and Plauger's printf implementation in his Standard C Library book + * treats this as an error. + */ + +#define _ISOC99_SOURCE /* for ULLONG primarily... */ +#include +#include "_stdio.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __UCLIBC_HAS_THREADS__ +# include +# include +#endif + +#ifdef __UCLIBC_HAS_WCHAR__ +# include +#endif + +#include +#include + +/* Some older or broken gcc toolchains define LONG_LONG_MAX but not + * LLONG_MAX. Since LLONG_MAX is part of the standard, that's what + * we use. So complain if we do not have it but should. + */ +#if !defined(LLONG_MAX) && defined(LONG_LONG_MAX) +#error Apparently, LONG_LONG_MAX is defined but LLONG_MAX is not. You need to fix your toolchain headers to support the standard macros for (unsigned) long long. +#endif + +/**********************************************************************/ +/* These provide some control over printf's feature set */ + +/* This is undefined below depeding on uClibc's configuration. */ +#define __STDIO_PRINTF_FLOAT 1 + +/* Now controlled by uClibc_stdio.h. */ +/* #define __UCLIBC_HAS_PRINTF_M_SPEC__ */ + + +/**********************************************************************/ + +#if defined(__UCLIBC__) && !defined(__UCLIBC_HAS_FLOATS__) +# undef __STDIO_PRINTF_FLOAT +#endif + +#ifdef __BCC__ +# undef __STDIO_PRINTF_FLOAT +#endif + +#ifdef __STDIO_PRINTF_FLOAT +# include +# include +#else +# undef L__fpmaxtostr +#endif + + +#undef __STDIO_HAS_VSNPRINTF +#if defined(__STDIO_BUFFERS) || defined(__USE_OLD_VFPRINTF__) || defined(__UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__) +# define __STDIO_HAS_VSNPRINTF 1 +#endif + +/**********************************************************************/ + +/* Now controlled by uClibc_stdio.h. */ +/* #define __UCLIBC_HAS_GLIBC_CUSTOM_PRINTF__ */ + +#ifdef __UCLIBC_MJN3_ONLY__ +# ifdef L_register_printf_function +/* emit only once */ +# warning WISHLIST: Make MAX_USER_SPEC configurable? +# warning WISHLIST: Make MAX_ARGS_PER_SPEC configurable? +# endif +#endif + +#ifdef __UCLIBC_HAS_GLIBC_CUSTOM_PRINTF__ +# define MAX_USER_SPEC 10 +# define MAX_ARGS_PER_SPEC 5 +#else +# undef MAX_USER_SPEC +# define MAX_ARGS_PER_SPEC 1 +#endif + +#if MAX_ARGS_PER_SPEC < 1 +# error MAX_ARGS_PER_SPEC < 1! +# undef MAX_ARGS_PER_SPEC +# define MAX_ARGS_PER_SPEC 1 +#endif + +#if defined(NL_ARGMAX) && (NL_ARGMAX < 9) +# error NL_ARGMAX < 9! +#endif + +#if defined(NL_ARGMAX) && (NL_ARGMAX >= (MAX_ARGS_PER_SPEC + 2)) +# define MAX_ARGS NL_ARGMAX +#else +/* N for spec itself, plus 1 each for width and precision */ +# define MAX_ARGS (MAX_ARGS_PER_SPEC + 2) +#endif + +/**********************************************************************/ + +#define __PA_FLAG_INTMASK \ + (__PA_FLAG_CHAR|PA_FLAG_SHORT|__PA_FLAG_INT|PA_FLAG_LONG|PA_FLAG_LONG_LONG) + +#ifdef __UCLIBC_HAS_GLIBC_CUSTOM_PRINTF__ +extern printf_function _custom_printf_handler[MAX_USER_SPEC] attribute_hidden; +extern printf_arginfo_function *_custom_printf_arginfo[MAX_USER_SPEC] attribute_hidden; +extern char *_custom_printf_spec attribute_hidden; +#endif + +/**********************************************************************/ + +#define SPEC_FLAGS " +0-#'I" +enum { + FLAG_SPACE = 0x01, + FLAG_PLUS = 0x02, /* must be 2 * FLAG_SPACE */ + FLAG_ZERO = 0x04, + FLAG_MINUS = 0x08, /* must be 2 * FLAG_ZERO */ + FLAG_HASH = 0x10, + FLAG_THOUSANDS = 0x20, + FLAG_I18N = 0x40, /* only works for d, i, u */ + FLAG_WIDESTREAM = 0x80 +}; + +/**********************************************************************/ + +/* float layout 01234567890123456789 TODO: B?*/ +#define SPEC_CHARS "npxXoudifFeEgGaACScs" +enum { + CONV_n = 0, + CONV_p, + CONV_x, CONV_X, CONV_o, CONV_u, CONV_d, CONV_i, + CONV_f, CONV_F, CONV_e, CONV_E, CONV_g, CONV_G, CONV_a, CONV_A, + CONV_C, CONV_S, CONV_c, CONV_s, +#ifdef __UCLIBC_HAS_PRINTF_M_SPEC__ + CONV_m, +#endif + CONV_custom0 /* must be last */ +}; + +/* p x X o u d i */ +#define SPEC_BASE { 16, 16, 16, 8, 10, 10, 10 } + +#define SPEC_RANGES { CONV_n, CONV_p, CONV_i, CONV_A, \ + CONV_C, CONV_S, CONV_c, CONV_s, CONV_custom0 } + +#define SPEC_OR_MASK { \ + /* n */ (PA_FLAG_PTR|PA_INT), \ + /* p */ PA_POINTER, \ + /* oxXudi */ PA_INT, \ + /* fFeEgGaA */ PA_DOUBLE, \ + /* C */ PA_WCHAR, \ + /* S */ PA_WSTRING, \ + /* c */ PA_CHAR, \ + /* s */ PA_STRING, \ +} + +#define SPEC_AND_MASK { \ + /* n */ (PA_FLAG_PTR|__PA_INTMASK), \ + /* p */ PA_POINTER, \ + /* oxXudi */ (__PA_INTMASK), \ + /* fFeEgGaA */ (PA_FLAG_LONG_DOUBLE|PA_DOUBLE), \ + /* C */ (PA_WCHAR), \ + /* S */ (PA_WSTRING), \ + /* c */ (PA_CHAR), \ + /* s */ (PA_STRING), \ +} + +/**********************************************************************/ +/* + * In order to ease translation to what arginfo and _print_info._flags expect, + * we map: 0:int 1:char 2:longlong 4:long 8:short + * and then _flags |= (((q << 7) + q) & 0x701) and argtype |= (_flags & 0x701) + */ + +/* TODO -- Fix the table below to take into account stdint.h. */ +/* #ifndef LLONG_MAX */ +/* #error fix QUAL_CHARS for no long long! Affects 'L', 'j', 'q', 'll'. */ +/* #else */ +/* #if LLONG_MAX != INTMAX_MAX */ +/* #error fix QUAL_CHARS intmax_t entry 'j'! */ +/* #endif */ +/* #endif */ + +#ifdef PDS +# error PDS already defined! +#endif +#ifdef SS +# error SS already defined! +#endif +#ifdef IMS +# error IMS already defined! +#endif + +#if PTRDIFF_MAX == INT_MAX +# define PDS 0 +#elif PTRDIFF_MAX == LONG_MAX +# define PDS 4 +#elif defined(LLONG_MAX) && (PTRDIFF_MAX == LLONG_MAX) +# define PDS 8 +#else +# error fix QUAL_CHARS ptrdiff_t entry 't'! +#endif + +#if SIZE_MAX == UINT_MAX +# define SS 0 +#elif SIZE_MAX == ULONG_MAX +# define SS 4 +#elif defined(LLONG_MAX) && (SIZE_MAX == ULLONG_MAX) +# define SS 8 +#else +# error fix QUAL_CHARS size_t entries 'z', 'Z'! +#endif + +#if INTMAX_MAX == INT_MAX +# define IMS 0 +#elif INTMAX_MAX == LONG_MAX +# define IMS 4 +#elif defined(LLONG_MAX) && (INTMAX_MAX == LLONG_MAX) +# define IMS 8 +#else +# error fix QUAL_CHARS intmax_t entry 'j'! +#endif + +#define QUAL_CHARS { \ + /* j:(u)intmax_t z:(s)size_t t:ptrdiff_t \0:int */ \ + /* q:long_long Z:(s)size_t */ \ + 'h', 'l', 'L', 'j', 'z', 't', 'q', 'Z', 0, \ + 2, 4, 8, IMS, SS, PDS, 8, SS, 0, /* TODO -- fix!!! */\ + 1, 8 \ +} + +/**********************************************************************/ + +#ifdef __STDIO_VA_ARG_PTR +# ifdef __BCC__ +# define __va_arg_ptr(ap,type) (((type *)(ap += sizeof(type))) - 1) +# endif + +# if 1 +# ifdef __GNUC__ +/* TODO -- need other than for 386 as well! */ + +# ifndef __va_rounded_size +# define __va_rounded_size(TYPE) \ + (((sizeof (TYPE) + sizeof (int) - 1) / sizeof (int)) * sizeof (int)) +# endif +# define __va_arg_ptr(AP, TYPE) \ + (AP = (va_list) ((char *) (AP) + __va_rounded_size (TYPE)), \ + ((void *) ((char *) (AP) - __va_rounded_size (TYPE))) \ + ) +# endif +# endif +#endif /* __STDIO_VA_ARG_PTR */ + +#ifdef __va_arg_ptr +# define GET_VA_ARG(AP,F,TYPE,ARGS) (*(AP) = __va_arg_ptr(ARGS,TYPE)) +# define GET_ARG_VALUE(AP,F,TYPE) (*((TYPE *)(*(AP)))) +#else +typedef union { + wchar_t wc; + unsigned int u; + unsigned long ul; +# ifdef ULLONG_MAX + unsigned long long ull; +# endif +# ifdef __STDIO_PRINTF_FLOAT + double d; + long double ld; +# endif + void *p; +} argvalue_t; + +# define GET_VA_ARG(AU,F,TYPE,ARGS) (AU->F = va_arg(ARGS,TYPE)) +# define GET_ARG_VALUE(AU,F,TYPE) ((TYPE)((AU)->F)) +#endif + +typedef struct { + const char *fmtpos; /* TODO: move below struct?? */ + struct printf_info info; +#ifdef NL_ARGMAX + int maxposarg; /* > 0 if args are positional, 0 if not, -1 if unknown */ +#endif + int num_data_args; /* TODO: use sentinal??? */ + unsigned int conv_num; + unsigned char argnumber[4]; /* width | prec | 1st data | unused */ + int argtype[MAX_ARGS]; + va_list arg; +#ifdef __va_arg_ptr + void *argptr[MAX_ARGS]; +#else +/* if defined(NL_ARGMAX) || defined(__UCLIBC_HAS_GLIBC_CUSTOM_PRINTF__) */ + /* While this is wasteful of space in the case where pos args aren't + * enabled, it is also needed to support custom printf handlers. */ + argvalue_t argvalue[MAX_ARGS]; +#endif +} ppfs_t; /* parse printf format state */ + +/**********************************************************************/ + +/* TODO: fix printf to return 0 and set errno if format error. Standard says + only returns -1 if sets error indicator for the stream. */ + +#ifdef __STDIO_PRINTF_FLOAT +typedef size_t (__fp_outfunc_t)(FILE *fp, intptr_t type, intptr_t len, + intptr_t buf); + +extern ssize_t _fpmaxtostr(FILE * fp, __fpmax_t x, struct printf_info *info, + __fp_outfunc_t fp_outfunc) attribute_hidden; +#endif + +extern int _ppfs_init(ppfs_t *ppfs, const char *fmt0) attribute_hidden; /* validates */ +extern void _ppfs_prepargs(ppfs_t *ppfs, va_list arg) attribute_hidden; /* sets posargptrs */ +extern void _ppfs_setargs(ppfs_t *ppfs) attribute_hidden; /* sets argptrs for current spec */ +extern int _ppfs_parsespec(ppfs_t *ppfs) attribute_hidden; /* parses specifier */ + +extern void _store_inttype(void *dest, int desttype, uintmax_t val) attribute_hidden; +extern uintmax_t _load_inttype(int desttype, const void *src, int uflag) attribute_hidden; + +/**********************************************************************/ +#ifdef L_parse_printf_format + +/* NOTE: This function differs from the glibc version in that parsing stops + * upon encountering an invalid conversion specifier. Since this is the way + * my printf functions work, I think it makes sense to do it that way here. + * Unfortunately, since glibc sets the return type as size_t, we have no way + * of returning that the template is illegal, other than returning 0. + */ + +size_t parse_printf_format(register const char *template, + size_t n, register int *argtypes) +{ + ppfs_t ppfs; + size_t i; + size_t count = 0; + + if (_ppfs_init(&ppfs, template) >= 0) { +#ifdef NL_ARGMAX + if (ppfs.maxposarg > 0) { + /* Using positional args. */ + count = ppfs.maxposarg; + if (n > count) { + n = count; + } + for (i = 0 ; i < n ; i++) { + *argtypes++ = ppfs.argtype[i]; + } + } else +#endif + { + /* Not using positional args. */ + while (*template) { + if ((*template == '%') && (*++template != '%')) { + ppfs.fmtpos = template; + _ppfs_parsespec(&ppfs); /* Can't fail. */ + template = ppfs.fmtpos; /* Update to one past spec end. */ + if (ppfs.info.width == INT_MIN) { + ++count; + if (n > 0) { + *argtypes++ = PA_INT; + --n; + } + } + if (ppfs.info.prec == INT_MIN) { + ++count; + if (n > 0) { + *argtypes++ = PA_INT; + --n; + } + } + for (i = 0 ; i < ppfs.num_data_args ; i++) { + if ((ppfs.argtype[i]) != __PA_NOARG) { + ++count; + if (n > 0) { + *argtypes++ = ppfs.argtype[i]; + --n; + } + } + } + } else { + ++template; + } + } + } + } + + return count; +} + +#endif +/**********************************************************************/ +#ifdef L__ppfs_init + +int attribute_hidden _ppfs_init(register ppfs_t *ppfs, const char *fmt0) +{ + int r; + + /* First, zero out everything... argnumber[], argtype[], argptr[] */ + memset(ppfs, 0, sizeof(ppfs_t)); /* TODO: nonportable???? */ +#ifdef NL_ARGMAX + --ppfs->maxposarg; /* set to -1 */ +#endif + ppfs->fmtpos = fmt0; +#ifdef __UCLIBC_MJN3_ONLY__ +# warning TODO: Make checking of the format string in C locale an option. +#endif +#ifdef __UCLIBC_HAS_LOCALE__ + /* To support old programs, don't check mb validity if in C locale. */ + if (__UCLIBC_CURLOCALE->encoding != __ctype_encoding_7_bit) { + /* ANSI/ISO C99 requires format string to be a valid multibyte string + * beginning and ending in its initial shift state. */ + static const char invalid_mbs[] = "Invalid multibyte format string."; + mbstate_t mbstate; + const char *p; + mbstate.__mask = 0; /* Initialize the mbstate. */ + p = fmt0; + if (mbsrtowcs(NULL, &p, SIZE_MAX, &mbstate) == ((size_t)(-1))) { + ppfs->fmtpos = invalid_mbs; + return -1; + } + } +#endif /* __UCLIBC_HAS_LOCALE__ */ + /* now set all argtypes to no-arg */ + { +#if 1 + /* TODO - use memset here since already "paid for"? */ + register int *p = ppfs->argtype; + + r = MAX_ARGS; + do { + *p++ = __PA_NOARG; + } while (--r); +#else + /* TODO -- get rid of this?? */ + register char *p = (char *) ((MAX_ARGS-1) * sizeof(int)); + + do { + *((int *)(((char *)ppfs) + ((int)p) + offsetof(ppfs_t,argtype))) = __PA_NOARG; + p -= sizeof(int); + } while (p); +#endif + } + + /* + * Run through the entire format string to validate it and initialize + * the positional arg numbers (if any). + */ + { + register const char *fmt = fmt0; + + while (*fmt) { + if ((*fmt == '%') && (*++fmt != '%')) { + ppfs->fmtpos = fmt; /* back up to the '%' */ + r = _ppfs_parsespec(ppfs); + if (r < 0) { + return -1; + } + fmt = ppfs->fmtpos; /* update to one past end of spec */ + } else { + ++fmt; + } + } + ppfs->fmtpos = fmt0; /* rewind */ + } + +#ifdef NL_MAX_ARG + /* If we have positional args, make sure we know all the types. */ + { + register int *p = ppfs->argtype; + r = ppfs->maxposarg; + while (--r >= 0) { + if ( *p == __PA_NOARG ) { /* missing arg type!!! */ + return -1; + } + ++p; + } + } +#endif /* NL_MAX_ARG */ + + return 0; +} +#endif +/**********************************************************************/ +#ifdef L__ppfs_prepargs +void attribute_hidden _ppfs_prepargs(register ppfs_t *ppfs, va_list arg) +{ + int i; + + va_copy(ppfs->arg, arg); + +#ifdef NL_ARGMAX + i = ppfs->maxposarg; /* init for positional args */ + if (i > 0) { + ppfs->num_data_args = i; + ppfs->info.width = ppfs->info.prec = ppfs->maxposarg = 0; + _ppfs_setargs(ppfs); + ppfs->maxposarg = i; + } +#endif +} +#endif +/**********************************************************************/ +#ifdef L__ppfs_setargs + +void attribute_hidden _ppfs_setargs(register ppfs_t *ppfs) +{ +#ifdef __va_arg_ptr + register void **p = ppfs->argptr; +#else + register argvalue_t *p = ppfs->argvalue; +#endif + int i; + +#ifdef NL_ARGMAX + if (ppfs->maxposarg == 0) { /* initing for or no pos args */ +#endif + if (ppfs->info.width == INT_MIN) { + ppfs->info.width = +#ifdef __va_arg_ptr + *(int *) +#endif + GET_VA_ARG(p,u,unsigned int,ppfs->arg); + } + if (ppfs->info.prec == INT_MIN) { + ppfs->info.prec = +#ifdef __va_arg_ptr + *(int *) +#endif + GET_VA_ARG(p,u,unsigned int,ppfs->arg); + } + i = 0; + while (i < ppfs->num_data_args) { + switch(ppfs->argtype[i++]) { + case (PA_INT|PA_FLAG_LONG_LONG): +#ifdef ULLONG_MAX + GET_VA_ARG(p,ull,unsigned long long,ppfs->arg); + break; +#endif + case (PA_INT|PA_FLAG_LONG): +#if ULONG_MAX != UINT_MAX + GET_VA_ARG(p,ul,unsigned long,ppfs->arg); + break; +#endif + case PA_CHAR: /* TODO - be careful */ + /* ... users could use above and really want below!! */ + case (PA_INT|__PA_FLAG_CHAR):/* TODO -- translate this!!! */ + case (PA_INT|PA_FLAG_SHORT): + case PA_INT: + GET_VA_ARG(p,u,unsigned int,ppfs->arg); + break; + case PA_WCHAR: /* TODO -- assume int? */ + /* we're assuming wchar_t is at least an int */ + GET_VA_ARG(p,wc,wchar_t,ppfs->arg); + break; +#ifdef __STDIO_PRINTF_FLOAT + /* PA_FLOAT */ + case PA_DOUBLE: + GET_VA_ARG(p,d,double,ppfs->arg); + break; + case (PA_DOUBLE|PA_FLAG_LONG_DOUBLE): + GET_VA_ARG(p,ld,long double,ppfs->arg); + break; +#else /* __STDIO_PRINTF_FLOAT */ + case PA_DOUBLE: + case (PA_DOUBLE|PA_FLAG_LONG_DOUBLE): + assert(0); + continue; +#endif /* __STDIO_PRINTF_FLOAT */ + default: + /* TODO -- really need to ensure this can't happen */ + assert(ppfs->argtype[i-1] & PA_FLAG_PTR); + case PA_POINTER: + case PA_STRING: + case PA_WSTRING: + GET_VA_ARG(p,p,void *,ppfs->arg); + break; + case __PA_NOARG: + continue; + } + ++p; + } +#ifdef NL_ARGMAX + } else { + if (ppfs->info.width == INT_MIN) { + ppfs->info.width + = (int) GET_ARG_VALUE(p + ppfs->argnumber[0] - 1,u,unsigned int); + } + if (ppfs->info.prec == INT_MIN) { + ppfs->info.prec + = (int) GET_ARG_VALUE(p + ppfs->argnumber[1] - 1,u,unsigned int); + } + } +#endif /* NL_ARGMAX */ + + /* Now we know the width and precision. */ + if (ppfs->info.width < 0) { + ppfs->info.width = -ppfs->info.width; + PRINT_INFO_SET_FLAG(&(ppfs->info),left); + PRINT_INFO_CLR_FLAG(&(ppfs->info),space); + ppfs->info.pad = ' '; + } +#if 0 + /* NOTE -- keep neg for now so float knows! */ + if (ppfs->info.prec < 0) { /* spec says treat as omitted. */ + /* so use default prec... 1 for everything but floats and strings. */ + ppfs->info.prec = 1; + } +#endif +} +#endif +/**********************************************************************/ +#ifdef L__ppfs_parsespec + +/* Notes: argtype differs from glibc for the following: + * mine glibc + * lc PA_WCHAR PA_CHAR the standard says %lc means %C + * ls PA_WSTRING PA_STRING the standard says %ls means %S + * {*}n {*}|PA_FLAG_PTR PA_FLAG_PTR size of n can be qualified + */ + +/* TODO: store positions of positional args */ + +/* TODO -- WARNING -- assumes aligned on integer boundaries!!! */ + +/* TODO -- disable if not using positional args!!! */ +#define _OVERLAPPING_DIFFERENT_ARGS + +/* TODO -- rethink this -- perhaps we should set to largest type??? */ + +#ifdef _OVERLAPPING_DIFFERENT_ARGS + +#define PROMOTED_SIZE_OF(X) ((sizeof(X) + sizeof(int) - 1) / sizeof(X)) + +static const short int type_codes[] = { + __PA_NOARG, /* must be first entry */ + PA_POINTER, + PA_STRING, + PA_WSTRING, + PA_CHAR, + PA_INT|PA_FLAG_SHORT, + PA_INT, + PA_INT|PA_FLAG_LONG, + PA_INT|PA_FLAG_LONG_LONG, + PA_WCHAR, +#ifdef __STDIO_PRINTF_FLOAT + /* PA_FLOAT, */ + PA_DOUBLE, + PA_DOUBLE|PA_FLAG_LONG_DOUBLE, +#endif +}; + +static const unsigned char type_sizes[] = { + /* unknown type consumes no arg */ + 0, /* must be first entry */ + PROMOTED_SIZE_OF(void *), + PROMOTED_SIZE_OF(char *), + PROMOTED_SIZE_OF(wchar_t *), + PROMOTED_SIZE_OF(char), + PROMOTED_SIZE_OF(short), + PROMOTED_SIZE_OF(int), + PROMOTED_SIZE_OF(long), +#ifdef ULLONG_MAX + PROMOTED_SIZE_OF(long long), +#else + PROMOTED_SIZE_OF(long), /* TODO -- is this correct? (above too) */ +#endif + PROMOTED_SIZE_OF(wchar_t), +#ifdef __STDIO_PRINTF_FLOAT + /* PROMOTED_SIZE_OF(float), */ + PROMOTED_SIZE_OF(double), + PROMOTED_SIZE_OF(long double), +#endif +}; + +static int _promoted_size(int argtype) +{ + register const short int *p; + + /* note -- since any unrecognized type is treated as a pointer */ + p = type_codes + sizeof(type_codes)/sizeof(type_codes[0]); + do { + if (*--p == argtype) { + break; + } + } while (p > type_codes); + + return type_sizes[(int)(p - type_codes)]; +} + +static int _is_equal_or_bigger_arg(int curtype, int newtype) +{ + /* Quick test */ + if (newtype == __PA_NOARG) { + return 0; + } + if ((curtype == __PA_NOARG) || (curtype == newtype)) { + return 1; + } + /* Ok... slot is already filled and types are different in name. */ + /* So, compare promoted sizes of curtype and newtype args. */ + return _promoted_size(curtype) <= _promoted_size(newtype); +} + +#else + +#define _is_equal_or_bigger_arg(C,N) (((C) == __PA_NOARG) || ((C) == (N))) + +#endif + +#ifdef __UCLIBC_HAS_GLIBC_CUSTOM_PRINTF__ +/* TODO - do this differently? */ +static char _bss_custom_printf_spec[MAX_USER_SPEC]; /* 0-init'd for us. */ + +attribute_hidden char *_custom_printf_spec = _bss_custom_printf_spec; +attribute_hidden printf_arginfo_function *_custom_printf_arginfo[MAX_USER_SPEC]; +attribute_hidden printf_function _custom_printf_handler[MAX_USER_SPEC]; +#endif /* __UCLIBC_HAS_GLIBC_CUSTOM_PRINTF__ */ + +int attribute_hidden _ppfs_parsespec(ppfs_t *ppfs) +{ + register const char *fmt; + register const char *p; + int preci; + int width; + int flags; + int dataargtype; + int i; + int dpoint; +#ifdef NL_ARGMAX + int maxposarg; +#endif + int p_m_spec_chars; + int n; + int argtype[MAX_ARGS_PER_SPEC+2]; + int argnumber[3]; /* width, precision, 1st data arg */ + static const char spec_flags[] = SPEC_FLAGS; + static const char spec_chars[] = SPEC_CHARS;/* TODO: b? */ + static const char spec_ranges[] = SPEC_RANGES; + static const short spec_or_mask[] = SPEC_OR_MASK; + static const short spec_and_mask[] = SPEC_AND_MASK; + static const char qual_chars[] = QUAL_CHARS; +#ifdef __UCLIBC_HAS_WCHAR__ + char buf[32]; +#endif + + /* WIDE note: we can test against '%' here since we don't allow */ + /* WIDE note: other mappings of '%' in the wide char set. */ + preci = -1; + argnumber[0] = 0; + argnumber[1] = 0; + argtype[0] = __PA_NOARG; + argtype[1] = __PA_NOARG; +#ifdef NL_ARGMAX + maxposarg = ppfs->maxposarg; +#endif + +#ifdef __UCLIBC_HAS_WCHAR__ + /* This is somewhat lame, but saves a lot of code. If we're dealing with + * a wide stream, that means the format is a wchar string. So, copy it + * char-by-char into a normal char buffer for processing. Make the buffer + * (buf) big enough so that any reasonable format specifier will fit. + * While there a legal specifiers that won't, the all involve duplicate + * flags or outrageous field widths/precisions. */ + width = dpoint = 0; + flags = ppfs->info._flags & FLAG_WIDESTREAM; + if (flags == 0) { + fmt = ppfs->fmtpos; + } else { + fmt = buf + 1; + i = 0; + do { + buf[i] = (char) (((wchar_t *) ppfs->fmtpos)[i-1]); + if (buf[i] != (((wchar_t *) ppfs->fmtpos)[i-1])) { + return -1; + } + } while (buf[i++] && (i < sizeof(buf))); + buf[sizeof(buf)-1] = 0; + } +#else /* __UCLIBC_HAS_WCHAR__ */ + width = flags = dpoint = 0; + fmt = ppfs->fmtpos; +#endif + + assert(fmt[-1] == '%'); + assert(fmt[0] != '%'); + + /* Process arg pos and/or flags and/or width and/or precision. */ + width_precision: + p = fmt; + if (*fmt == '*') { + argtype[-dpoint] = PA_INT; + ++fmt; + } + i = 0; + while (isdigit(*fmt)) { + if (i < INT_MAX / 10 + || (i == INT_MAX / 10 && (*fmt - '0') <= INT_MAX % 10)) { + i = (i * 10) + (*fmt - '0'); + } else { + i = INT_MAX; /* best we can do... */ + } + ++fmt; + } + if (p[-1] == '%') { /* Check for a position. */ + + /* TODO: if val not in range, then error */ + +#ifdef NL_ARGMAX + if ((*fmt == '$') && (i > 0)) {/* Positional spec. */ + ++fmt; + if (maxposarg == 0) { + return -1; + } + argnumber[2] = i; + if (argnumber[2] > maxposarg) { + maxposarg = i; + } + /* Now fall through to check flags. */ + } else { + if (maxposarg > 0) { +# ifdef __UCLIBC_HAS_PRINTF_M_SPEC__ +# ifdef __UCLIBC_MJN3_ONLY__ +# warning TODO: Support prec and width for %m when positional args used + /* Actually, positional arg processing will fail in general + * for specifiers that don't require an arg. */ +# endif + if (*fmt == 'm') { + goto PREC_WIDTH; + } +# endif /* __UCLIBC_HAS_PRINTF_M_SPEC__ */ + return -1; + } + maxposarg = 0; /* Possible redundant store, but cuts size. */ + + if ((fmt > p) && (*p != '0')) { + goto PREC_WIDTH; + } + + fmt = p; /* Back up for possible '0's flag. */ + /* Now fall through to check flags. */ + } +#else /* NL_ARGMAX */ + if (*fmt == '$') { /* Positional spec. */ + return -1; + } + + if ((fmt > p) && (*p != '0')) { + goto PREC_WIDTH; + } + + fmt = p; /* Back up for possible '0's flag. */ + /* Now fall through to check flags. */ +#endif /* NL_ARGMAX */ + + restart_flags: /* Process flags. */ + i = 1; + p = spec_flags; + + do { + if (*fmt == *p++) { + ++fmt; + flags |= i; + goto restart_flags; + } + i += i; /* Better than i <<= 1 for bcc */ + } while (*p); + i = 0; + + /* If '+' then ignore ' ', and if '-' then ignore '0'. */ + /* Note: Need to ignore '0' when prec is an arg with val < 0, */ + /* but that test needs to wait until the arg is retrieved. */ + flags &= ~((flags & (FLAG_PLUS|FLAG_MINUS)) >> 1); + /* Note: Ignore '0' when prec is specified < 0 too (in printf). */ + + if (fmt[-1] != '%') { /* If we've done anything, loop for width. */ + goto width_precision; + } + } + PREC_WIDTH: + if (*p == '*') { /* Prec or width takes an arg. */ +#ifdef NL_ARGMAX + if (maxposarg) { + if ((*fmt++ != '$') || (i <= 0)) { + /* Using pos args and no $ or invalid arg number. */ + return -1; + } + argnumber[-dpoint] = i; + } else +#endif + if (++p != fmt) { + /* Not using pos args but digits followed *. */ + return -1; + } + i = INT_MIN; + } + + if (!dpoint) { + width = i; + if (*fmt == '.') { + ++fmt; + dpoint = -1; /* To use as default precison. */ + goto width_precision; + } + } else { + preci = i; + } + + /* Process qualifier. */ + p = qual_chars; + do { + if (*fmt == *p) { + ++fmt; + break; + } + } while (*++p); + if ((p - qual_chars < 2) && (*fmt == *p)) { + p += ((sizeof(qual_chars)-2) / 2); + ++fmt; + } + dataargtype = ((int)(p[(sizeof(qual_chars)-2) / 2])) << 8; + + /* Process conversion specifier. */ + if (!*fmt) { + return -1; + } + + p = spec_chars; + + do { + if (*fmt == *p) { + p_m_spec_chars = p - spec_chars; + + if ((p_m_spec_chars >= CONV_c) + && (dataargtype & PA_FLAG_LONG)) { + p_m_spec_chars -= 2; /* lc -> C and ls -> S */ + } + + ppfs->conv_num = p_m_spec_chars; + p = spec_ranges-1; + while (p_m_spec_chars > *++p) {} + + i = p - spec_ranges; + argtype[2] = (dataargtype | spec_or_mask[i]) & spec_and_mask[i]; + p = spec_chars; + break; + } + } while(*++p); + + ppfs->info.spec = *fmt; + ppfs->info.prec = preci; + ppfs->info.width = width; + ppfs->info.pad = ((flags & FLAG_ZERO) ? '0' : ' '); + ppfs->info._flags = (flags & ~FLAG_ZERO) | (dataargtype & __PA_INTMASK); + ppfs->num_data_args = 1; + + if (!*p) { +#ifdef __UCLIBC_HAS_PRINTF_M_SPEC__ + if (*fmt == 'm') { + ppfs->conv_num = CONV_m; + ppfs->num_data_args = 0; + } else +#endif + { +#ifndef __UCLIBC_HAS_GLIBC_CUSTOM_PRINTF__ + return -1; /* Error */ +#else + /* Handle custom arg -- WARNING -- overwrites p!!! */ + ppfs->conv_num = CONV_custom0; + p = _custom_printf_spec; + while (1) { + if (*p == *fmt) { + printf_arginfo_function *fp = _custom_printf_arginfo[(int)(p - _custom_printf_spec)]; + ppfs->num_data_args = fp(&(ppfs->info), MAX_ARGS_PER_SPEC, argtype + 2); + if (ppfs->num_data_args > MAX_ARGS_PER_SPEC) { + return -1; /* Error -- too many args! */ + } + break; + } + if (++p >= (_custom_printf_spec + MAX_USER_SPEC)) + return -1; /* Error */ + } +#endif + } + } + +#ifdef NL_ARGMAX + if (maxposarg > 0) { + i = 0; + do { + /* Update maxposarg and check that NL_ARGMAX is not exceeded. */ + n = ((i <= 2) + ? (ppfs->argnumber[i] = argnumber[i]) + : argnumber[2] + (i-2)); + if (n > maxposarg) { + maxposarg = n; + if (maxposarg > NL_ARGMAX) { + return -1; + } + } + --n; + /* Record argtype with largest size (current, new). */ + if (_is_equal_or_bigger_arg(ppfs->argtype[n], argtype[i])) { + ppfs->argtype[n] = argtype[i]; + } + } while (++i < ppfs->num_data_args + 2); + } else +#endif /* NL_ARGMAX */ + { + ppfs->argnumber[2] = 1; + memcpy(ppfs->argtype, argtype + 2, ppfs->num_data_args * sizeof(int)); + } + +#ifdef NL_ARGMAX + ppfs->maxposarg = maxposarg; +#endif + +#ifdef __UCLIBC_HAS_WCHAR__ + flags = ppfs->info._flags & FLAG_WIDESTREAM; + if (flags == 0) { + ppfs->fmtpos = ++fmt; + } else { + ppfs->fmtpos = (const char *) (((const wchar_t *)(ppfs->fmtpos)) + + (fmt - buf) ); + } +#else /* __UCLIBC_HAS_WCHAR__ */ + ppfs->fmtpos = ++fmt; +#endif + + return ppfs->num_data_args + 2; +} + +#endif +/**********************************************************************/ +#ifdef L_register_printf_function + +#ifdef __UCLIBC_HAS_GLIBC_CUSTOM_PRINTF__ + +int register_printf_function(int spec, printf_function handler, + printf_arginfo_function arginfo) +{ + register char *r; + register char *p; + + if (spec && (arginfo != NULL)) { /* TODO -- check if spec is valid char */ + r = NULL; + p = _custom_printf_spec + MAX_USER_SPEC; + do { + --p; + if (!*p) { + r = p; + } +#ifdef __BCC__ + else /* bcc generates less code with fall-through */ +#endif + if (*p == spec) { + r = p; + p = _custom_printf_spec; + } + } while (p > _custom_printf_spec); + + if (r) { + if (handler) { + *r = spec; + _custom_printf_handler[(int)(r - p)] = handler; + _custom_printf_arginfo[(int)(r - p)] = arginfo; + } else { + *r = 0; + } + return 0; + } + /* TODO -- if asked to unregister a non-existent spec, return what? */ + } + return -1; +} + +#endif + +#endif +/**********************************************************************/ +#if defined(L__vfprintf_internal) || defined(L__vfwprintf_internal) + +/* We only support ascii digits (or their USC equivalent codes) in + * precision and width settings in *printf (wide) format strings. + * In other words, we don't currently support glibc's 'I' flag. + * We do accept it, but it is currently ignored. */ + +static size_t _charpad(FILE * __restrict stream, int padchar, size_t numpad); + +#ifdef L__vfprintf_internal + +#define VFPRINTF_internal _vfprintf_internal +#define FMT_TYPE char +#define OUTNSTR _outnstr +#define STRLEN strlen +#define _PPFS_init _ppfs_init +#define OUTPUT(F,S) fputs_unlocked(S,F) +/* #define _outnstr(stream, string, len) __stdio_fwrite(string, len, stream) */ +#define _outnstr(stream, string, len) ((len > 0) ? __stdio_fwrite((const unsigned char *)(string), len, stream) : 0) +#define FP_OUT _fp_out_narrow + +#ifdef __STDIO_PRINTF_FLOAT + +static size_t _fp_out_narrow(FILE *fp, intptr_t type, intptr_t len, intptr_t buf) +{ + size_t r = 0; + + if (type & 0x80) { /* Some type of padding needed. */ + int buflen = strlen((const char *) buf); + len -= buflen; + if (len > 0) { + r = _charpad(fp, (type & 0x7f), len); + if (r != len) { + return r; + } + } + len = buflen; + } + return r + OUTNSTR(fp, (const char *) buf, len); +} + +#endif /* __STDIO_PRINTF_FLOAT */ + +#else /* L__vfprintf_internal */ + +#define VFPRINTF_internal _vfwprintf_internal +#define FMT_TYPE wchar_t +#define OUTNSTR _outnwcs +#define STRLEN wcslen +#define _PPFS_init _ppwfs_init +/* Pulls in fseek: */ +#define OUTPUT(F,S) fputws(S,F) +/* TODO: #define OUTPUT(F,S) _wstdio_fwrite((S),wcslen(S),(F)) */ +#define _outnwcs(stream, wstring, len) _wstdio_fwrite((const wchar_t *)(wstring), len, stream) +#define FP_OUT _fp_out_wide + +static size_t _outnstr(FILE *stream, const char *s, size_t wclen) +{ + /* NOTE!!! len here is the number of wchars we want to generate!!! */ + wchar_t wbuf[64]; + mbstate_t mbstate; + size_t todo, r, n; + + mbstate.__mask = 0; + todo = wclen; + + while (todo) { + r = mbsrtowcs(wbuf, &s, + ((todo <= sizeof(wbuf)/sizeof(wbuf[0])) + ? todo + : sizeof(wbuf)/sizeof(wbuf[0])), + &mbstate); + assert(((ssize_t)r) > 0); + n = _outnwcs(stream, wbuf, r); + todo -= n; + if (n != r) { + break; + } + } + + return wclen - todo; +} + +#ifdef __STDIO_PRINTF_FLOAT + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning TODO: Move defines from _fpmaxtostr. Put them in a common header. +#endif + +/* The following defines are from _fpmaxtostr.*/ +#define DIGITS_PER_BLOCK 9 +#define NUM_DIGIT_BLOCKS ((DECIMAL_DIG+DIGITS_PER_BLOCK-1)/DIGITS_PER_BLOCK) +#define BUF_SIZE ( 3 + NUM_DIGIT_BLOCKS * DIGITS_PER_BLOCK ) + +static size_t _fp_out_wide(FILE *fp, intptr_t type, intptr_t len, intptr_t buf) +{ + wchar_t wbuf[BUF_SIZE]; + const char *s = (const char *) buf; + size_t r = 0; + int i; + + if (type & 0x80) { /* Some type of padding needed */ + int buflen = strlen(s); + len -= buflen; + if (len > 0) { + r = _charpad(fp, (type & 0x7f), len); + if (r != len) { + return r; + } + } + len = buflen; + } + + if (len > 0) { + i = 0; + do { +#ifdef __LOCALE_C_ONLY + wbuf[i] = s[i]; +#else + +# ifdef __UCLIBC_HAS_GLIBC_DIGIT_GROUPING__ + if (s[i] == ',') { + wbuf[i] = __UCLIBC_CURLOCALE->thousands_sep_wc; + } else +# endif + if (s[i] == '.') { + wbuf[i] = __UCLIBC_CURLOCALE->decimal_point_wc; + } else { + wbuf[i] = s[i]; + } +#endif /* __LOCALE_C_ONLY */ + + } while (++i < len); + + r += OUTNSTR(fp, wbuf, len); + } + + return r; +} + +#endif /* __STDIO_PRINTF_FLOAT */ + +static int _ppwfs_init(register ppfs_t *ppfs, const wchar_t *fmt0) +{ + static const wchar_t invalid_wcs[] = L"Invalid wide format string."; + int r; + + /* First, zero out everything... argnumber[], argtype[], argptr[] */ + memset(ppfs, 0, sizeof(ppfs_t)); /* TODO: nonportable???? */ +#ifdef NL_ARGMAX + --ppfs->maxposarg; /* set to -1 */ +#endif + ppfs->fmtpos = (const char *) fmt0; + ppfs->info._flags = FLAG_WIDESTREAM; + + { + mbstate_t mbstate; + const wchar_t *p; + mbstate.__mask = 0; /* Initialize the mbstate. */ + p = fmt0; + if (wcsrtombs(NULL, &p, SIZE_MAX, &mbstate) == ((size_t)(-1))) { + ppfs->fmtpos = (const char *) invalid_wcs; + return -1; + } + } + + /* now set all argtypes to no-arg */ + { +#if 1 + /* TODO - use memset here since already "paid for"? */ + register int *p = ppfs->argtype; + + r = MAX_ARGS; + do { + *p++ = __PA_NOARG; + } while (--r); +#else + /* TODO -- get rid of this?? */ + register char *p = (char *) ((MAX_ARGS-1) * sizeof(int)); + + do { + *((int *)(((char *)ppfs) + ((int)p) + offsetof(ppfs_t,argtype))) = __PA_NOARG; + p -= sizeof(int); + } while (p); +#endif + } + + /* + * Run through the entire format string to validate it and initialize + * the positional arg numbers (if any). + */ + { + register const wchar_t *fmt = fmt0; + + while (*fmt) { + if ((*fmt == '%') && (*++fmt != '%')) { + ppfs->fmtpos = (const char *) fmt; /* back up to the '%' */ + r = _ppfs_parsespec(ppfs); + if (r < 0) { + return -1; + } + fmt = (const wchar_t *) ppfs->fmtpos; /* update to one past end of spec */ + } else { + ++fmt; + } + } + ppfs->fmtpos = (const char *) fmt0; /* rewind */ + } + +#ifdef NL_ARGMAX + /* If we have positional args, make sure we know all the types. */ + { + register int *p = ppfs->argtype; + r = ppfs->maxposarg; + while (--r >= 0) { + if ( *p == __PA_NOARG ) { /* missing arg type!!! */ + return -1; + } + ++p; + } + } +#endif /* NL_ARGMAX */ + + return 0; +} + +#endif /* L__vfprintf_internal */ + + +static size_t _charpad(FILE * __restrict stream, int padchar, size_t numpad) +{ + size_t todo = numpad; + + /* TODO -- Use a buffer to cut down on function calls... */ + FMT_TYPE pad[1]; + + *pad = padchar; + while (todo && (OUTNSTR(stream, (const char *) pad, 1) == 1)) { + --todo; + } + + return numpad - todo; +} + +/* TODO -- Dynamically allocate work space to accomodate stack-poor archs? */ +static int _do_one_spec(FILE * __restrict stream, + register ppfs_t *ppfs, int *count) +{ + static const char spec_base[] = SPEC_BASE; +#ifdef L__vfprintf_internal + static const char prefix[] = "+\0-\0 \0000x\0000X"; + /* 0 2 4 6 9 11*/ +#else + static const wchar_t prefix[] = L"+\0-\0 \0000x\0000X"; +#endif + enum { + PREFIX_PLUS = 0, + PREFIX_MINUS = 2, + PREFIX_SPACE = 4, + PREFIX_LWR_X = 6, + PREFIX_UPR_X = 9, + PREFIX_NONE = 11 + }; + +#ifdef __va_arg_ptr + const void * const *argptr; +#else + const void * argptr[MAX_ARGS_PER_SPEC]; +#endif + int *argtype; +#ifdef __UCLIBC_HAS_WCHAR__ + const wchar_t *ws = NULL; + mbstate_t mbstate; +#endif + size_t slen; +#ifdef L__vfprintf_internal +#define SLEN slen +#else + size_t SLEN; + wchar_t wbuf[2]; +#endif + int base; + int numpad; + int alphacase; + int numfill = 0; /* TODO: fix */ + int prefix_num = PREFIX_NONE; + char padchar = ' '; +#ifdef __UCLIBC_MJN3_ONLY__ +#warning TODO: Determine appropriate buf size. +#endif + /* TODO: buf needs to be big enough for any possible error return strings + * and also for any locale-grouped long long integer strings generated. + * This should be large enough for any of the current archs/locales, but + * eventually this should be handled robustly. */ + char buf[128]; + +#ifdef NDEBUG + _ppfs_parsespec(ppfs); +#else + if (_ppfs_parsespec(ppfs) < 0) { /* TODO: just for debugging */ + abort(); + } +#endif + _ppfs_setargs(ppfs); + + argtype = ppfs->argtype + ppfs->argnumber[2] - 1; + /* Deal with the argptr vs argvalue issue. */ +#ifdef __va_arg_ptr + argptr = (const void * const *) ppfs->argptr; +# ifdef NL_ARGMAX + if (ppfs->maxposarg > 0) { /* Using positional args... */ + argptr += ppfs->argnumber[2] - 1; + } +# endif +#else + /* Need to build a local copy... */ + { + register argvalue_t *p = ppfs->argvalue; + int i; +# ifdef NL_ARGMAX + if (ppfs->maxposarg > 0) { /* Using positional args... */ + p += ppfs->argnumber[2] - 1; + } +# endif + for (i = 0 ; i < ppfs->num_data_args ; i++ ) { + argptr[i] = (void *) p++; + } + } +#endif + { + register char *s = NULL; /* TODO: Should s be unsigned char * ? */ + + if (ppfs->conv_num == CONV_n) { + _store_inttype(*(void **)*argptr, + ppfs->info._flags & __PA_INTMASK, + (intmax_t) (*count)); + return 0; + } + if (ppfs->conv_num <= CONV_i) { /* pointer or (un)signed int */ + alphacase = __UIM_LOWER; + +#ifdef __UCLIBC_MJN3_ONLY__ +#ifdef L__vfprintf_internal +#warning CONSIDER: Should we ignore these flags if stub locale? What about custom specs? +#endif +#endif + base = spec_base[(int)(ppfs->conv_num - CONV_p)]; + if (base == 10) { + if (PRINT_INFO_FLAG_VAL(&(ppfs->info),group)) { + alphacase = __UIM_GROUP; + } + if (PRINT_INFO_FLAG_VAL(&(ppfs->info),i18n)) { + alphacase |= 0x80; + } + } + + if (ppfs->conv_num <= CONV_u) { /* pointer or unsigned int */ + if (ppfs->conv_num == CONV_X) { + alphacase = __UIM_UPPER; + } + if (ppfs->conv_num == CONV_p) { /* pointer */ + prefix_num = PREFIX_LWR_X; + } else { /* unsigned int */ + } + } else { /* signed int */ + base = -base; + } + if (ppfs->info.prec < 0) { /* Ignore '0' flag if prec specified. */ + padchar = ppfs->info.pad; + } +#ifdef __UCLIBC_MJN3_ONLY__ +#ifdef L__vfprintf_internal +#warning CONSIDER: If using outdigits and/or grouping, how should we interpret precision? +#endif +#endif + s = _uintmaxtostr(buf + sizeof(buf) - 1, + (uintmax_t) + _load_inttype(ppfs->conv_num == CONV_p ? PA_FLAG_LONG : *argtype & __PA_INTMASK, + *argptr, base), base, alphacase); + if (ppfs->conv_num > CONV_u) { /* signed int */ + if (*s == '-') { + PRINT_INFO_SET_FLAG(&(ppfs->info),showsign); + ++s; /* handle '-' in the prefix string */ + prefix_num = PREFIX_MINUS; + } else if (PRINT_INFO_FLAG_VAL(&(ppfs->info),showsign)) { + prefix_num = PREFIX_PLUS; + } else if (PRINT_INFO_FLAG_VAL(&(ppfs->info),space)) { + prefix_num = PREFIX_SPACE; + } + } + slen = (char *)(buf + sizeof(buf) - 1) - s; +#ifdef L__vfwprintf_internal + { + const char *q = s; + mbstate.__mask = 0; /* Initialize the mbstate. */ + SLEN = mbsrtowcs(NULL, &q, 0, &mbstate); + } +#endif + numfill = ((ppfs->info.prec < 0) ? 1 : ppfs->info.prec); + if (PRINT_INFO_FLAG_VAL(&(ppfs->info),alt)) { + if (ppfs->conv_num <= CONV_x) { /* x or p */ + prefix_num = PREFIX_LWR_X; + } + if (ppfs->conv_num == CONV_X) { + prefix_num = PREFIX_UPR_X; + } + if ((ppfs->conv_num == CONV_o) && (numfill <= SLEN)) { + numfill = ((*s == '0') ? 1 : SLEN + 1); + } + } + if (*s == '0') { + if (prefix_num >= PREFIX_LWR_X) { + prefix_num = PREFIX_NONE; + } + if (ppfs->conv_num == CONV_p) {/* null pointer */ + s = "(nil)"; +#ifdef L__vfwprintf_internal + SLEN = +#endif + slen = 5; + numfill = 0; + } else if (numfill == 0) { /* if precision 0, no output */ +#ifdef L__vfwprintf_internal + SLEN = +#endif + slen = 0; + } + } + numfill = ((numfill > SLEN) ? numfill - SLEN : 0); + } else if (ppfs->conv_num <= CONV_A) { /* floating point */ +#ifdef __STDIO_PRINTF_FLOAT + ssize_t nf; + nf = _fpmaxtostr(stream, + (__fpmax_t) + (PRINT_INFO_FLAG_VAL(&(ppfs->info),is_long_double) + ? *(long double *) *argptr + : (long double) (* (double *) *argptr)), + &ppfs->info, FP_OUT ); + if (nf < 0) { + return -1; + } + *count += nf; + + return 0; +#else /* __STDIO_PRINTF_FLOAT */ + return -1; /* TODO -- try to continue? */ +#endif + } else if (ppfs->conv_num <= CONV_S) { /* wide char or string */ +#ifdef L__vfprintf_internal + +#ifdef __UCLIBC_HAS_WCHAR__ + mbstate.__mask = 0; /* Initialize the mbstate. */ + if (ppfs->conv_num == CONV_S) { /* wide string */ + ws = *((const wchar_t **) *argptr); + if (!ws) { + goto NULL_STRING; + } + /* We use an awful uClibc-specific hack here, passing + * (char*) &ws as the conversion destination. This signals + * uClibc's wcsrtombs that we want a "restricted" length + * such that the mbs fits in a buffer of the specified + * size with no partial conversions. */ + slen = wcsrtombs((char *) &ws, &ws, /* Use awful hack! */ + ((ppfs->info.prec >= 0) + ? ppfs->info.prec + : SIZE_MAX), + &mbstate); + if (slen == ((size_t)-1)) { + return -1; /* EILSEQ */ + } + } else { /* wide char */ + s = buf; + slen = wcrtomb(s, (*((const wchar_t *) *argptr)), &mbstate); + if (slen == ((size_t)-1)) { + return -1; /* EILSEQ */ + } + s[slen] = 0; /* TODO - Is this necessary? */ + } +#else /* __UCLIBC_HAS_WCHAR__ */ + return -1; +#endif + } else if (ppfs->conv_num <= CONV_s) { /* char or string */ + if (ppfs->conv_num == CONV_s) { /* string */ + s = *((char **) (*argptr)); + if (s) { +#ifdef __UCLIBC_HAS_PRINTF_M_SPEC__ + SET_STRING_LEN: +#endif + slen = strnlen(s, ((ppfs->info.prec >= 0) + ? ppfs->info.prec : SIZE_MAX)); + } else { +#ifdef __UCLIBC_HAS_WCHAR__ + NULL_STRING: +#endif + s = "(null)"; + slen = 6; + } + } else { /* char */ + s = buf; + *s = (unsigned char)(*((const int *) *argptr)); + s[1] = 0; + slen = 1; + } + +#else /* L__vfprintf_internal */ + + if (ppfs->conv_num == CONV_S) { /* wide string */ + ws = *((wchar_t **) (*argptr)); + if (!ws) { + goto NULL_STRING; + } + SLEN = wcsnlen(ws, ((ppfs->info.prec >= 0) + ? ppfs->info.prec : SIZE_MAX)); + } else { /* wide char */ + *wbuf = (wchar_t)(*((const wint_t *) *argptr)); + CHAR_CASE: + ws = wbuf; + wbuf[1] = 0; + SLEN = 1; + } + + } else if (ppfs->conv_num <= CONV_s) { /* char or string */ + + if (ppfs->conv_num == CONV_s) { /* string */ +#ifdef __UCLIBC_MJN3_ONLY__ +#warning TODO: Fix %s for _vfwprintf_internal... output upto illegal sequence? +#endif + s = *((char **) (*argptr)); + if (s) { +#ifdef __UCLIBC_HAS_PRINTF_M_SPEC__ + SET_STRING_LEN: +#endif + /* We use an awful uClibc-specific hack here, passing + * (wchar_t*) &mbstate as the conversion destination. + * This signals uClibc's mbsrtowcs that we want a + * "restricted" length such that the mbs fits in a buffer + * of the specified size with no partial conversions. */ + { + const char *q = s; + mbstate.__mask = 0; /* Initialize the mbstate. */ + SLEN = mbsrtowcs((wchar_t *) &mbstate, &q, + ((ppfs->info.prec >= 0) + ? ppfs->info.prec : SIZE_MAX), + &mbstate); + } + if (SLEN == ((size_t)(-1))) { + return -1; /* EILSEQ */ + } + } else { + NULL_STRING: + s = "(null)"; + SLEN = slen = 6; + } + } else { /* char */ + *wbuf = btowc( (unsigned char)(*((const int *) *argptr)) ); + goto CHAR_CASE; + } + +#endif /* L__vfprintf_internal */ + +#ifdef __UCLIBC_HAS_PRINTF_M_SPEC__ + } else if (ppfs->conv_num == CONV_m) { + s = __glibc_strerror_r(errno, buf, sizeof(buf)); + goto SET_STRING_LEN; +#endif + } else { +#ifdef __UCLIBC_HAS_GLIBC_CUSTOM_PRINTF__ + assert(ppfs->conv_num == CONV_custom0); + + s = _custom_printf_spec; + do { + if (*s == ppfs->info.spec) { + int rv; + /* TODO -- check return value for sanity? */ + rv = (*_custom_printf_handler + [(int)(s-_custom_printf_spec)]) + (stream, &ppfs->info, argptr); + if (rv < 0) { + return -1; + } + *count += rv; + return 0; + } + } while (++s < (_custom_printf_spec + MAX_USER_SPEC)); +#endif /* __UCLIBC_HAS_GLIBC_CUSTOM_PRINTF__ */ + assert(0); + return -1; + } + +#ifdef __UCLIBC_MJN3_ONLY__ +#ifdef L__vfprintf_internal +#warning CONSIDER: If using outdigits and/or grouping, how should we pad? +#endif +#endif + { + size_t t; + + t = SLEN + numfill; + if (prefix_num != PREFIX_NONE) { + t += ((prefix_num < PREFIX_LWR_X) ? 1 : 2); + } + numpad = ((ppfs->info.width > t) ? (ppfs->info.width - t) : 0); + *count += t + numpad; + } + if (padchar == '0') { /* TODO: check this */ + numfill += numpad; + numpad = 0; + } + + /* Now handle the output itself. */ + if (!PRINT_INFO_FLAG_VAL(&(ppfs->info),left)) { + if (_charpad(stream, ' ', numpad) != numpad) { + return -1; + } + numpad = 0; + } + OUTPUT(stream, prefix + prefix_num); + + if (_charpad(stream, '0', numfill) != numfill) { + return -1; + } + +#ifdef L__vfprintf_internal + +# ifdef __UCLIBC_HAS_WCHAR__ + if (!ws) { + assert(s); + if (_outnstr(stream, s, slen) != slen) { + return -1; + } + } else { /* wide string */ + size_t t; + mbstate.__mask = 0; /* Initialize the mbstate. */ + while (slen) { + t = (slen <= sizeof(buf)) ? slen : sizeof(buf); + t = wcsrtombs(buf, &ws, t, &mbstate); + assert(t != ((size_t)(-1))); + if (_outnstr(stream, buf, t) != t) { + return -1; + } + slen -= t; + } + } +# else /* __UCLIBC_HAS_WCHAR__ */ + if (_outnstr(stream, (const unsigned char *) s, slen) != slen) { + return -1; + } +# endif + +#else /* L__vfprintf_internal */ + + if (!ws) { + assert(s); + if (_outnstr(stream, s, SLEN) != SLEN) { + return -1; + } + } else { + if (_outnwcs(stream, ws, SLEN) != SLEN) { + return -1; + } + } + +#endif /* L__vfprintf_internal */ + if (_charpad(stream, ' ', numpad) != numpad) { + return -1; + } + } + + return 0; +} + + +int VFPRINTF_internal (FILE * __restrict stream, + const FMT_TYPE * __restrict format, + va_list arg) +{ + ppfs_t ppfs; + int count, r; + register const FMT_TYPE *s; + + count = 0; + s = format; + + if (_PPFS_init(&ppfs, format) < 0) { /* Bad format string. */ + OUTNSTR(stream, (const char *) ppfs.fmtpos, + STRLEN((const FMT_TYPE *)(ppfs.fmtpos))); +#if defined(L__vfprintf_internal) && !defined(NDEBUG) + fprintf(stderr,"\nIMbS: \"%s\"\n\n", format); +#endif + count = -1; + } else { + _ppfs_prepargs(&ppfs, arg); /* This did a va_copy!!! */ + + do { + while (*format && (*format != '%')) { + ++format; + } + + if (format - s) { /* output any literal text in format string */ + r = OUTNSTR(stream, (const char *) s, format - s); + if (r != (format - s)) { + count = -1; + break; + } + count += r; + } + + if (!*format) { /* we're done */ + break; + } + + if (format[1] != '%') { /* if we get here, *format == '%' */ + /* TODO: _do_one_spec needs to know what the output funcs are!!! */ + ppfs.fmtpos = (const char *)(++format); + /* TODO: check -- should only fail on stream error */ + r = _do_one_spec(stream, &ppfs, &count); + if (r < 0) { + count = -1; + break; + } + s = format = (const FMT_TYPE *) ppfs.fmtpos; + } else { /* %% means literal %, so start new string */ + s = ++format; + ++format; + } + } while (1); + + va_end(ppfs.arg); /* Need to clean up after va_copy! */ + } + +/* #if defined(L__vfprintf_internal) && defined(__UCLIBC_HAS_WCHAR__) */ +/* DONE: */ +/* #endif */ + + return count; +} +#endif /* defined(L__vfprintf_internal) || defined(L__vfwprintf_internal) */ + + +/**********************************************************************/ +#if defined(L_vfprintf) || defined(L_vfwprintf) + +/* This is just a wrapper around VFPRINTF_internal. + * Factoring out vfprintf internals allows: + * (1) vdprintf and vsnprintf don't need to setup fake locking, + * (2) __STDIO_STREAM_TRANS_TO_WRITE is not used in vfprintf internals, + * and thus fseek etc is not pulled in by vdprintf and vsnprintf. + * + * In order to not pull in fseek through fputs, OUTPUT() macro + * is using __stdio_fwrite (TODO: do the same for wide functions). + */ +#ifdef L_vfprintf +# define VFPRINTF vfprintf +# define VFPRINTF_internal _vfprintf_internal +# define FMT_TYPE char +#else +# define VFPRINTF vfwprintf +# define VFPRINTF_internal _vfwprintf_internal +# define FMT_TYPE wchar_t +#endif + +libc_hidden_proto(VFPRINTF) +int VFPRINTF (FILE * __restrict stream, + const FMT_TYPE * __restrict format, + va_list arg) +{ + int count; + __STDIO_AUTO_THREADLOCK_VAR; + + __STDIO_AUTO_THREADLOCK(stream); + + if +#ifdef L_vfprintf + (!__STDIO_STREAM_IS_NARROW_WRITING(stream) + && __STDIO_STREAM_TRANS_TO_WRITE(stream, __FLAG_NARROW)) +#else + (!__STDIO_STREAM_IS_WIDE_WRITING(stream) + && __STDIO_STREAM_TRANS_TO_WRITE(stream, __FLAG_WIDE)) +#endif + { + count = -1; + } else { + count = VFPRINTF_internal(stream, format, arg); + } + + __STDIO_AUTO_THREADUNLOCK(stream); + + return count; +} +libc_hidden_def(VFPRINTF) +#endif /* defined(L_vfprintf) || defined(L_vfwprintf) */ + +/**********************************************************************/ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_vfprintf_internal.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_vfprintf_internal.c new file mode 100644 index 00000000..40bf39e2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_vfprintf_internal.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define L__vfprintf_internal +#include "_vfprintf.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_vfwprintf_internal.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_vfwprintf_internal.c new file mode 100644 index 00000000..8584cf4a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_vfwprintf_internal.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define L__vfwprintf_internal +#include "_vfprintf.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_wcommit.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_wcommit.c new file mode 100644 index 00000000..a0b3219b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_wcommit.c @@ -0,0 +1,31 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +#ifdef __STDIO_BUFFERS + +/* Commit the data in the write buffer. + * Returns 0 on success, >0 (pending) on failure. + * Side effects are those of _stdio_WRITE + */ + +size_t attribute_hidden __stdio_wcommit(register FILE * __restrict stream) +{ + size_t bufsize; + + __STDIO_STREAM_VALIDATE(stream); + + if ((bufsize = __STDIO_STREAM_BUFFER_WUSED(stream)) != 0) { + stream->__bufpos = stream->__bufstart; + __stdio_WRITE(stream, stream->__bufstart, bufsize); + } + + return __STDIO_STREAM_BUFFER_WUSED(stream); +} + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_wfwrite.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_wfwrite.c new file mode 100644 index 00000000..517e3a7a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/_wfwrite.c @@ -0,0 +1,73 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" +#include + +#ifndef __UCLIBC_HAS_WCHAR__ +#error wide function when no wide support! +#endif + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning TODO: Fix prototype. +#endif + + +size_t attribute_hidden _wstdio_fwrite(const wchar_t *__restrict ws, size_t n, + register FILE *__restrict stream) +{ + size_t r, count; + char buf[64]; + const wchar_t *pw; + + __STDIO_STREAM_VALIDATE(stream); + +#ifdef __STDIO_BUFFERS + if (__STDIO_STREAM_IS_FAKE_VSWPRINTF(stream)) { + /* We know buffer is wchar aligned for fake streams. */ + count = (((wchar_t *)(stream->__bufend)) + - ((wchar_t *)(stream->__bufpos))); + if (count > n) { + count = n; + } + if (count) { + wmemcpy((wchar_t *)(stream->__bufpos), ws, count); + stream->__bufpos = (unsigned char *)(((wchar_t *)(stream->__bufpos)) + count); + } + __STDIO_STREAM_VALIDATE(stream); + return n; + } +#endif + + count = 0; + + if (__STDIO_STREAM_IS_WIDE_WRITING(stream) + || !__STDIO_STREAM_TRANS_TO_WRITE(stream, __FLAG_WIDE) + ) { + + pw = ws; + while (n > count) { + r = wcsnrtombs(buf, &pw, n-count, sizeof(buf), &stream->__state); + if (r != ((size_t) -1)) { /* No encoding errors */ + if (!r) { + ++r; /* 0 is returned when nul is reached. */ + pw = ws + count + r; /* pw was set to NULL, so correct. */ + } + if (__stdio_fwrite((const unsigned char *)buf, r, stream) == r) { + count = pw - ws; + continue; + } + } + break; + } + + /* Note: The count is incorrect if 0 < __stdio_fwrite return < r!!! */ + } + + __STDIO_STREAM_VALIDATE(stream); + return count; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/asprintf.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/asprintf.c new file mode 100644 index 00000000..6334cc72 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/asprintf.c @@ -0,0 +1,34 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include + +#ifdef __USE_GNU +#include "_stdio.h" +#include + + + +#ifndef __STDIO_HAS_VSNPRINTF +#warning Skipping asprintf and __asprintf since no vsnprintf! +#else + +int asprintf(char **__restrict buf, const char * __restrict format, ...) +{ + va_list arg; + int rv; + + va_start(arg, format); + rv = vasprintf(buf, format, arg); + va_end(arg); + + return rv; +} +libc_hidden_def(asprintf) + +#endif +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/clearerr.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/clearerr.c new file mode 100644 index 00000000..a96ecaa8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/clearerr.c @@ -0,0 +1,40 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +#undef clearerr +#ifdef __DO_UNLOCKED + +#undef clearerr_unlocked +void clearerr_unlocked(register FILE *stream) +{ + __STDIO_STREAM_VALIDATE(stream); + + __CLEARERR_UNLOCKED(stream); +} + +#ifndef __UCLIBC_HAS_THREADS__ +strong_alias(clearerr_unlocked,clearerr) +#endif + +#elif defined __UCLIBC_HAS_THREADS__ + +void clearerr(register FILE *stream) +{ + __STDIO_AUTO_THREADLOCK_VAR; + + __STDIO_AUTO_THREADLOCK(stream); + + __STDIO_STREAM_VALIDATE(stream); + + __CLEARERR_UNLOCKED(stream); + + __STDIO_AUTO_THREADUNLOCK(stream); +} + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/clearerr_unlocked.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/clearerr_unlocked.c new file mode 100644 index 00000000..1728d037 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/clearerr_unlocked.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define __DO_UNLOCKED +#include "clearerr.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/ctermid.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/ctermid.c new file mode 100644 index 00000000..854c526e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/ctermid.c @@ -0,0 +1,27 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + + +char *ctermid(register char *s) +{ + static char sbuf[L_ctermid]; + +#ifdef __BCC__ + /* Currently elks doesn't support /dev/tty. */ + if (!s) { + s = sbuf; + } + *s = 0; + + return s; +#else + /* glibc always returns /dev/tty for linux. */ + return strcpy((s ? s : sbuf), "/dev/tty"); +#endif +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/dprintf.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/dprintf.c new file mode 100644 index 00000000..3fab1273 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/dprintf.c @@ -0,0 +1,26 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include + +#ifdef __USE_GNU +#include "_stdio.h" +#include + + +int dprintf(int filedes, const char * __restrict format, ...) +{ + va_list arg; + int rv; + + va_start(arg, format); + rv = vdprintf(filedes, format, arg); + va_end(arg); + + return rv; +} +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fclose.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fclose.c new file mode 100644 index 00000000..3417b267 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fclose.c @@ -0,0 +1,103 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + + +int fclose(register FILE *stream) +{ + int rv = 0; + __STDIO_AUTO_THREADLOCK_VAR; + +#ifdef __STDIO_HAS_OPENLIST +#if !defined(__UCLIBC_HAS_THREADS__) || !defined(__STDIO_BUFFERS) + /* First, remove the file from the open file list. */ + { + FILE *ptr; + + __STDIO_THREADLOCK_OPENLIST_DEL; + __STDIO_THREADLOCK_OPENLIST_ADD; + ptr = _stdio_openlist; + if ((ptr = _stdio_openlist) == stream) { + _stdio_openlist = stream->__nextopen; + } else { + while (ptr) { + if (ptr->__nextopen == stream) { + ptr->__nextopen = stream->__nextopen; + break; + } + ptr = ptr->__nextopen; + } + } + __STDIO_THREADUNLOCK_OPENLIST_ADD; + __STDIO_THREADUNLOCK_OPENLIST_DEL; + } +#endif +#endif + + __STDIO_AUTO_THREADLOCK(stream); + + __STDIO_STREAM_VALIDATE(stream); + +#ifdef __STDIO_BUFFERS + /* Write any pending buffered chars. */ + if (__STDIO_STREAM_IS_WRITING(stream)) { + rv = fflush_unlocked(stream); + } +#endif + + if (__CLOSE(stream) < 0) { /* Must close even if fflush failed. */ + rv = EOF; + } + + stream->__filedes = -1; + + /* We need a way for freopen to know that a file has been closed. + * Since a file can't be both readonly and writeonly, that makes + * an effective signal. It also has the benefit of disabling + * transitions to either reading or writing. */ +#if defined(__UCLIBC_HAS_THREADS__) && defined(__STDIO_BUFFERS) + /* Before we mark the file as closed, make sure we increment the openlist use count + * so it isn't freed under us while still cleaning up. */ + __STDIO_OPENLIST_INC_USE; +#endif + stream->__modeflags &= (__FLAG_FREEBUF|__FLAG_FREEFILE); + stream->__modeflags |= (__FLAG_READONLY|__FLAG_WRITEONLY); + +#ifndef NDEBUG + __STDIO_STREAM_RESET_GCS(stream); + + /* Reinitialize everything (including putc since fflush could fail). */ + __STDIO_STREAM_DISABLE_GETC(stream); + __STDIO_STREAM_DISABLE_PUTC(stream); + __STDIO_STREAM_INIT_BUFREAD_BUFPOS(stream); + +# ifdef __UCLIBC_HAS_WCHAR__ + stream->__ungot_width[0] = 0; +# endif +# ifdef __STDIO_MBSTATE + __INIT_MBSTATE(&(stream->__state)); +# endif +#endif + + __STDIO_AUTO_THREADUNLOCK(stream); + + __STDIO_STREAM_FREE_BUFFER(stream); +#ifdef __UCLIBC_MJN3_ONLY__ +#warning REMINDER: inefficient - locks and unlocks twice and walks whole list +#endif +#if defined(__UCLIBC_HAS_THREADS__) && defined(__STDIO_BUFFERS) + /* inefficient - locks/unlocks twice and walks whole list */ + __STDIO_OPENLIST_INC_DEL_CNT; + __STDIO_OPENLIST_DEC_USE; /* This with free the file if necessary. */ +#else + __STDIO_STREAM_FREE_FILE(stream); +#endif + + return rv; +} +libc_hidden_def(fclose) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fcloseall.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fcloseall.c new file mode 100644 index 00000000..4d78b37d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fcloseall.c @@ -0,0 +1,70 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include + +#ifdef __USE_GNU +#include "_stdio.h" + + +/* NOTE: GLIBC difference!!! -- fcloseall + * According to the info pages, glibc actually fclose()s all open files. + * Apparently, glibc's new version only fflush()s and unbuffers all + * writing streams to cope with unordered destruction of c++ static + * objects. + */ + +int fcloseall (void) +{ +#ifdef __STDIO_HAS_OPENLIST + + int retval = 0; + FILE *f; + + __STDIO_OPENLIST_INC_USE; + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning REMINDER: should probably have a get_head() operation +#endif + __STDIO_THREADLOCK_OPENLIST_ADD; + f = _stdio_openlist; + __STDIO_THREADUNLOCK_OPENLIST_ADD; + + while (f) { +#ifdef __UCLIBC_MJN3_ONLY__ +#warning REMINDER: should probably have a get_next() operation +#endif + FILE *n = f->__nextopen; + __STDIO_AUTO_THREADLOCK_VAR; + + __STDIO_AUTO_THREADLOCK(f); + /* Only call fclose on the stream if it is not already closed. */ + if ((f->__modeflags & (__FLAG_READONLY|__FLAG_WRITEONLY)) + != (__FLAG_READONLY|__FLAG_WRITEONLY) + ) { + if (fclose(f)) { + retval = EOF; + } + } + __STDIO_AUTO_THREADUNLOCK(f); + + f = n; + } + + __STDIO_OPENLIST_DEC_USE; + + return retval; + +#else + +#warning Always fails in this configuration because no open file list. + + return EOF; + +#endif +} +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fdopen.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fdopen.c new file mode 100644 index 00000000..76c239f4 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fdopen.c @@ -0,0 +1,20 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + + +FILE *fdopen(int filedes, const char *mode) +{ + intptr_t cur_mode; + + cur_mode = fcntl(filedes, F_GETFL); + if (cur_mode != -1) + return _stdio_fopen(cur_mode, mode, NULL, filedes); + return NULL; +} +libc_hidden_def(fdopen) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/feof.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/feof.c new file mode 100644 index 00000000..e5f03b72 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/feof.c @@ -0,0 +1,43 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +#undef feof +#ifdef __DO_UNLOCKED + +#undef feof_unlocked +int feof_unlocked(register FILE *stream) +{ + __STDIO_STREAM_VALIDATE(stream); + + return __FEOF_UNLOCKED(stream); +} + +#ifndef __UCLIBC_HAS_THREADS__ +strong_alias(feof_unlocked,feof) +#endif + +#elif defined __UCLIBC_HAS_THREADS__ + +int feof(register FILE *stream) +{ + int retval; + __STDIO_AUTO_THREADLOCK_VAR; + + __STDIO_AUTO_THREADLOCK(stream); + + __STDIO_STREAM_VALIDATE(stream); + + retval = __FEOF_UNLOCKED(stream); + + __STDIO_AUTO_THREADUNLOCK(stream); + + return retval; +} + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/feof_unlocked.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/feof_unlocked.c new file mode 100644 index 00000000..4553f306 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/feof_unlocked.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define __DO_UNLOCKED +#include "feof.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/ferror.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/ferror.c new file mode 100644 index 00000000..947b89ed --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/ferror.c @@ -0,0 +1,43 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +#undef ferror +#ifdef __DO_UNLOCKED + +#undef ferror_unlocked +int ferror_unlocked(register FILE *stream) +{ + __STDIO_STREAM_VALIDATE(stream); + + return __FERROR_UNLOCKED(stream); +} + +#ifndef __UCLIBC_HAS_THREADS__ +strong_alias(ferror_unlocked,ferror) +#endif + +#elif defined __UCLIBC_HAS_THREADS__ + +int ferror(register FILE *stream) +{ + int retval; + __STDIO_AUTO_THREADLOCK_VAR; + + __STDIO_AUTO_THREADLOCK(stream); + + __STDIO_STREAM_VALIDATE(stream); + + retval = __FERROR_UNLOCKED(stream); + + __STDIO_AUTO_THREADUNLOCK(stream); + + return retval; +} + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/ferror_unlocked.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/ferror_unlocked.c new file mode 100644 index 00000000..19722b8b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/ferror_unlocked.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define __DO_UNLOCKED +#include "ferror.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fflush.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fflush.c new file mode 100644 index 00000000..d9104a42 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fflush.c @@ -0,0 +1,211 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + + +#ifdef __DO_UNLOCKED + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning WISHLIST: Add option to test for undefined behavior of fflush. +#endif /* __UCLIBC_MJN3_ONLY__ */ + +/* Even if the stream is set to user-locking, we still need to lock + * when all (lbf) writing streams are flushed. */ + +#define __MY_STDIO_THREADLOCK(__stream) \ + __UCLIBC_IO_MUTEX_CONDITIONAL_LOCK((__stream)->__lock, \ + (_stdio_user_locking != 2)) + +#define __MY_STDIO_THREADUNLOCK(__stream) \ + __UCLIBC_IO_MUTEX_CONDITIONAL_UNLOCK((__stream)->__lock, \ + (_stdio_user_locking != 2)) + +#if defined(__UCLIBC_HAS_THREADS__) && defined(__STDIO_BUFFERS) +void attribute_hidden _stdio_openlist_dec_use(void) +{ + __STDIO_THREADLOCK_OPENLIST_DEL; + if ((_stdio_openlist_use_count == 1) && (_stdio_openlist_del_count > 0)) { + FILE *p = NULL; + FILE *n; + FILE *stream; + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning REMINDER: As an optimization, we could unlock after we move past the head. +#endif + /* Grab the openlist add lock since we might change the head of the list. */ + __STDIO_THREADLOCK_OPENLIST_ADD; + for (stream = _stdio_openlist; stream; stream = n) { + n = stream->__nextopen; +#ifdef __UCLIBC_MJN3_ONLY__ +#warning REMINDER: fix for nonatomic +#endif + if ((stream->__modeflags & (__FLAG_READONLY|__FLAG_WRITEONLY|__FLAG_FAILED_FREOPEN)) + == (__FLAG_READONLY|__FLAG_WRITEONLY) + ) { /* The file was closed and should be removed from the list. */ + if (!p) { + _stdio_openlist = n; + } else { + p->__nextopen = n; + } + __STDIO_STREAM_FREE_FILE(stream); + } else { + p = stream; + } + } + __STDIO_THREADUNLOCK_OPENLIST_ADD; + _stdio_openlist_del_count = 0; /* Should be clean now. */ + } + --_stdio_openlist_use_count; + __STDIO_THREADUNLOCK_OPENLIST_DEL; +} +#endif + +int fflush_unlocked(register FILE *stream) +{ +#ifdef __STDIO_BUFFERS + + int retval = 0; +#ifdef __UCLIBC_MJN3_ONLY__ +#warning REMINDER: should probably define a modeflags type +#endif + unsigned short bufmask = __FLAG_LBF; + +#ifndef NDEBUG + if ((stream != NULL) && (stream != (FILE *) &_stdio_openlist)) { + __STDIO_STREAM_VALIDATE(stream); /* debugging only */ + } +#endif + + if (stream == (FILE *) &_stdio_openlist) { /* Flush all lbf streams. */ + stream = NULL; + bufmask = 0; + } + + if (!stream) { /* Flush all (lbf) writing streams. */ + + __STDIO_OPENLIST_INC_USE; + + __STDIO_THREADLOCK_OPENLIST_ADD; + stream = _stdio_openlist; + __STDIO_THREADUNLOCK_OPENLIST_ADD; + + while(stream) { + /* We only care about currently writing streams and do not want to + * block trying to obtain mutexes on non-writing streams. */ +#warning fix for nonatomic +#warning unnecessary check if no threads + if (__STDIO_STREAM_IS_WRITING(stream)) { /* ONLY IF ATOMIC!!! */ + __MY_STDIO_THREADLOCK(stream); + /* Need to check again once we have the lock. */ + if (!(((stream->__modeflags | bufmask) + ^ (__FLAG_WRITING|__FLAG_LBF) + ) & (__FLAG_WRITING|__MASK_BUFMODE)) + ) { + if (!__STDIO_COMMIT_WRITE_BUFFER(stream)) { + __STDIO_STREAM_DISABLE_PUTC(stream); + __STDIO_STREAM_CLEAR_WRITING(stream); + } else { + retval = EOF; + } + } + __MY_STDIO_THREADUNLOCK(stream); + } + stream = stream->__nextopen; + } + + __STDIO_OPENLIST_DEC_USE; + + } else if (__STDIO_STREAM_IS_WRITING(stream)) { + if (!__STDIO_COMMIT_WRITE_BUFFER(stream)) { + __STDIO_STREAM_DISABLE_PUTC(stream); + __STDIO_STREAM_CLEAR_WRITING(stream); + } else { + retval = EOF; + } + } +#if 0 + else if (stream->__modeflags & (__MASK_READING|__FLAG_READONLY)) { + /* ANSI/ISO says behavior in this case is undefined but also says you + * shouldn't flush a stream you were reading from. As usual, glibc + * caters to broken programs and simply ignores this. */ + __UNDEFINED_OR_NONPORTABLE; + __STDIO_STREAM_SET_ERROR(stream); + __set_errno(EBADF); + retval = EOF; + } +#endif + +#ifndef NDEBUG + if ((stream != NULL) && (stream != (FILE *) &_stdio_openlist)) { + __STDIO_STREAM_VALIDATE(stream); /* debugging only */ + } +#endif + + return retval; + +#else /* __STDIO_BUFFERS --------------------------------------- */ + +#ifndef NDEBUG + if ((stream != NULL) +#ifdef __STDIO_HAS_OPENLIST + && (stream != (FILE *) &_stdio_openlist) +#endif + ) { + __STDIO_STREAM_VALIDATE(stream); /* debugging only */ + } +#endif + +#if 0 + if (stream && (stream->__modeflags & (__MASK_READING|__FLAG_READONLY))) { + /* ANSI/ISO says behavior in this case is undefined but also says you + * shouldn't flush a stream you were reading from. As usual, glibc + * caters to broken programs and simply ignores this. */ + __UNDEFINED_OR_NONPORTABLE; + __STDIO_STREAM_SET_ERROR(stream); + __set_errno(EBADF); + return EOF; + } +#endif + + return 0; +#endif /* __STDIO_BUFFERS */ +} +libc_hidden_def(fflush_unlocked) + +#ifndef __UCLIBC_HAS_THREADS__ +strong_alias(fflush_unlocked,fflush) +libc_hidden_def(fflush) +#endif + +#elif defined __UCLIBC_HAS_THREADS__ + +int fflush(register FILE *stream) +{ + int retval; + __STDIO_AUTO_THREADLOCK_VAR; + + if (stream +#ifdef __STDIO_HAS_OPENLIST + && (stream != (FILE *) &_stdio_openlist) +#endif + ) { + + __STDIO_AUTO_THREADLOCK(stream); + + retval = fflush_unlocked(stream); + + __STDIO_AUTO_THREADUNLOCK(stream); + } else { + retval = fflush_unlocked(stream); + } + + return retval; +} +libc_hidden_def(fflush) + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fflush_unlocked.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fflush_unlocked.c new file mode 100644 index 00000000..a6adb59c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fflush_unlocked.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define __DO_UNLOCKED +#include "fflush.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fgetc.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fgetc.c new file mode 100644 index 00000000..56a284c0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fgetc.c @@ -0,0 +1,107 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +#undef fgetc +#undef fgetc_unlocked +#undef getc +#undef getc_unlocked + + +#ifdef __DO_UNLOCKED + + +int __fgetc_unlocked(FILE *stream) +{ + __STDIO_STREAM_VALIDATE(stream); + + /* First the fast path. We're good to go if getc macro enabled. */ + if (__STDIO_STREAM_CAN_USE_BUFFER_GET(stream)) { + return __STDIO_STREAM_BUFFER_GET(stream); + } + + /* Next quickest... reading and narrow oriented, but macro + * disabled and/or buffer is exhausted. */ + if (__STDIO_STREAM_IS_NARROW_READING(stream) + || !__STDIO_STREAM_TRANS_TO_READ(stream, __FLAG_NARROW) + ) { + if (stream->__modeflags & __FLAG_UNGOT) { /* Use ungots first. */ + unsigned char uc = stream->__ungot[(stream->__modeflags--) & 1]; + stream->__ungot[1] = 0; + __STDIO_STREAM_VALIDATE(stream); + return uc; + } + + if (__STDIO_STREAM_BUFFER_RAVAIL(stream)) { /* Have buffered? */ + return __STDIO_STREAM_BUFFER_GET(stream); + } + + /* Is this a fake stream for *sscanf? */ + if (__STDIO_STREAM_IS_FAKE_VSSCANF(stream)) { + __STDIO_STREAM_SET_EOF(stream); + return EOF; + } + + /* We need to read from the host environment, so we must + * flush all line buffered streams if the stream is not + * fully buffered. */ + if (!__STDIO_STREAM_IS_FBF(stream)) { + __STDIO_FLUSH_LBF_STREAMS; + } + + if (__STDIO_STREAM_BUFFER_SIZE(stream)) { /* Do we have a buffer? */ + __STDIO_STREAM_DISABLE_GETC(stream); + if(__STDIO_FILL_READ_BUFFER(stream)) { /* Refill succeeded? */ + __STDIO_STREAM_ENABLE_GETC(stream); /* FBF or LBF */ + return __STDIO_STREAM_BUFFER_GET(stream); + } + } else { + unsigned char uc; + if (__stdio_READ(stream, &uc, 1)) { + return uc; + } + } + } + + return EOF; +} +libc_hidden_def(__fgetc_unlocked) + +strong_alias(__fgetc_unlocked,fgetc_unlocked) +libc_hidden_def(fgetc_unlocked) + +strong_alias(__fgetc_unlocked,getc_unlocked) +libc_hidden_def(getc_unlocked) + +#ifndef __UCLIBC_HAS_THREADS__ +strong_alias(__fgetc_unlocked,fgetc) +libc_hidden_def(fgetc) + +strong_alias(__fgetc_unlocked,getc) +#endif + +#elif defined __UCLIBC_HAS_THREADS__ + +int fgetc(register FILE *stream) +{ + if (stream->__user_locking != 0) { + return __GETC_UNLOCKED_MACRO(stream); + } else { + int retval; + __STDIO_ALWAYS_THREADLOCK(stream); + retval = __GETC_UNLOCKED_MACRO(stream); + __STDIO_ALWAYS_THREADUNLOCK(stream); + return retval; + } +} +libc_hidden_def(fgetc) + +strong_alias(fgetc,getc) + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fgetc_unlocked.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fgetc_unlocked.c new file mode 100644 index 00000000..a20c7eef --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fgetc_unlocked.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define __DO_UNLOCKED +#include "fgetc.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fgetpos.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fgetpos.c new file mode 100644 index 00000000..610737d3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fgetpos.c @@ -0,0 +1,40 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +#ifndef __DO_LARGEFILE +#define FTELL ftell +#endif + +libc_hidden_proto(FTELL) + +int fgetpos(FILE * __restrict stream, register fpos_t * __restrict pos) +{ +#ifdef __STDIO_MBSTATE + + int retval = -1; + __STDIO_AUTO_THREADLOCK_VAR; + + __STDIO_AUTO_THREADLOCK(stream); + + if ((pos->__pos = FTELL(stream)) >= 0) { + __COPY_MBSTATE(&(pos->__mbstate), &(stream->__state)); + pos->__mblen_pending = stream->__ungot_width[0]; + retval = 0; + } + + __STDIO_AUTO_THREADUNLOCK(stream); + + return retval; + +#else + + return ((pos->__pos = FTELL(stream)) >= 0) ? 0 : -1; + +#endif +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fgetpos64.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fgetpos64.c new file mode 100644 index 00000000..32b7120a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fgetpos64.c @@ -0,0 +1,14 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +#define __DO_LARGEFILE +#define fgetpos fgetpos64 +#define fpos_t fpos64_t +#define FTELL ftello64 +#include "fgetpos.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fgets.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fgets.c new file mode 100644 index 00000000..bc710c76 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fgets.c @@ -0,0 +1,87 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + + +#ifdef __DO_UNLOCKED + + +char *fgets_unlocked(char *__restrict s, int n, + register FILE * __restrict stream) +{ + register char *p; + int c; + + __STDIO_STREAM_VALIDATE(stream); + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning CONSIDER: What should fgets do if n <= 0? +#endif /* __UCLIBC_MJN3_ONLY__ */ + /* Should we assert here? Or set errno? Or just fail... */ + if (n <= 0) { +/* __set_errno(EINVAL); */ + goto ERROR; + } + + p = s; + + while (--n) { + if (__STDIO_STREAM_CAN_USE_BUFFER_GET(stream)) { + if ((*p++ = __STDIO_STREAM_BUFFER_GET(stream)) == '\n') { + break; + } + } else { + if ((c = __fgetc_unlocked(stream)) == EOF) { + if (__FERROR_UNLOCKED(stream)) { + goto ERROR; + } + break; + } + if ((*p++ = c) == '\n') { + break; + } + } + } + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning CONSIDER: If n==1 and not at EOF, should fgets return an empty string? +#endif /* __UCLIBC_MJN3_ONLY__ */ + if (p > s) { + *p = 0; + return s; + } + + ERROR: + return NULL; +} +libc_hidden_def(fgets_unlocked) + +#ifndef __UCLIBC_HAS_THREADS__ +strong_alias(fgets_unlocked,fgets) +libc_hidden_def(fgets) +#endif + +#elif defined __UCLIBC_HAS_THREADS__ + +char *fgets(char *__restrict s, int n, + register FILE * __restrict stream) +{ + char *retval; + __STDIO_AUTO_THREADLOCK_VAR; + + __STDIO_AUTO_THREADLOCK(stream); + + retval = fgets_unlocked(s, n, stream); + + __STDIO_AUTO_THREADUNLOCK(stream); + + return retval; +} +libc_hidden_def(fgets) + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fgets_unlocked.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fgets_unlocked.c new file mode 100644 index 00000000..db019130 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fgets_unlocked.c @@ -0,0 +1,14 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include + +#ifdef __USE_GNU +# define __DO_UNLOCKED +# include "fgets.c" +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fgetwc.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fgetwc.c new file mode 100644 index 00000000..32d9e0ea --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fgetwc.c @@ -0,0 +1,138 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + + + +#ifdef __DO_UNLOCKED + +static void munge_stream(register FILE *stream, unsigned char *buf) +{ + stream->__bufend = stream->__bufstart = buf; + __STDIO_STREAM_INIT_BUFREAD_BUFPOS(stream); + __STDIO_STREAM_DISABLE_GETC(stream); + __STDIO_STREAM_DISABLE_PUTC(stream); +} + +wint_t fgetwc_unlocked(register FILE *stream) +{ + wint_t wi; + wchar_t wc[1]; + int n; + size_t r; + unsigned char sbuf[1]; + + __STDIO_STREAM_VALIDATE(stream); + + wi = WEOF; /* Prepare for failure. */ + + if (__STDIO_STREAM_IS_WIDE_READING(stream) + || !__STDIO_STREAM_TRANS_TO_READ(stream, __FLAG_WIDE) + ) { + if (stream->__modeflags & __FLAG_UNGOT) { /* Any ungetwc()s? */ + if (((stream->__modeflags & 1) || stream->__ungot[1])) { + stream->__ungot_width[0] = 0; /* Application ungot... */ + } else { /* scanf ungot */ + stream->__ungot_width[0] = stream->__ungot_width[1]; + } + + wi = stream->__ungot[(stream->__modeflags--) & 1]; + stream->__ungot[1] = 0; + goto DONE; + } + + if (!stream->__bufstart) { /* Ugh... stream isn't buffered! */ + /* Munge the stream temporarily to use a 1-byte buffer. */ + munge_stream(stream, sbuf); + ++stream->__bufend; + } + + if (stream->__state.__mask == 0) { /* If last was a complete char */ + stream->__ungot_width[0] = 0; /* then reset the width. */ + } + + LOOP: + if ((n = __STDIO_STREAM_BUFFER_RAVAIL(stream)) == 0) { + goto FILL_BUFFER; + } + + r = mbrtowc(wc, (const char*) stream->__bufpos, n, &stream->__state); + if (((ssize_t) r) >= 0) { /* Success... */ + if (r == 0) { /* Nul wide char... means 0 byte for us so */ + ++r; /* increment r and handle below as single. */ + } + stream->__bufpos += r; + stream->__ungot_width[0] += r; + wi = *wc; + goto DONE; + } + + if (r == ((size_t) -2)) { + /* Potentially valid but incomplete and no more buffered. */ + stream->__bufpos += n; /* Update bufpos for stream. */ + stream->__ungot_width[0] += n; + FILL_BUFFER: + if(__STDIO_FILL_READ_BUFFER(stream)) { /* Refill succeeded? */ + goto LOOP; + } + if (!__FERROR_UNLOCKED(stream)) { /* EOF with no error. */ + if (!stream->__state.__mask) { /* No partial wchar. */ + goto DONE; + } + /* EOF but partially complete wchar. */ + /* TODO: should EILSEQ be set? */ + __set_errno(EILSEQ); + } + } + + /* If we reach here, either r == ((size_t)-1) and mbrtowc set errno + * to EILSEQ, or r == ((size_t)-2) and stream is in an error state + * or at EOF with a partially complete wchar. Make sure stream's + * error indicator is set. */ + stream->__modeflags |= __FLAG_ERROR; + + DONE: + if (stream->__bufstart == sbuf) { /* Need to un-munge the stream. */ + munge_stream(stream, NULL); + } + + } + + __STDIO_STREAM_VALIDATE(stream); + + return wi; +} +libc_hidden_def(fgetwc_unlocked) + +strong_alias(fgetwc_unlocked,getwc_unlocked) +#ifndef __UCLIBC_HAS_THREADS__ +strong_alias(fgetwc_unlocked,fgetwc) +libc_hidden_def(fgetwc) + +strong_alias(fgetwc_unlocked,getwc) +#endif + +#elif defined __UCLIBC_HAS_THREADS__ + +wint_t fgetwc(register FILE *stream) +{ + wint_t retval; + __STDIO_AUTO_THREADLOCK_VAR; + + __STDIO_AUTO_THREADLOCK(stream); + + retval = fgetwc_unlocked(stream); + + __STDIO_AUTO_THREADUNLOCK(stream); + + return retval; +} +libc_hidden_def(fgetwc) + +strong_alias(fgetwc,getwc) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fgetwc_unlocked.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fgetwc_unlocked.c new file mode 100644 index 00000000..8eab8439 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fgetwc_unlocked.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define __DO_UNLOCKED +#include "fgetwc.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fgetws.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fgetws.c new file mode 100644 index 00000000..b59d74b1 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fgetws.c @@ -0,0 +1,60 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + + + +#ifdef __DO_UNLOCKED + +wchar_t *fgetws_unlocked(wchar_t *__restrict ws, int n, + FILE *__restrict stream) +{ + register wchar_t *p = ws; + wint_t wi; + + __STDIO_STREAM_VALIDATE(stream); + + while ((n > 1) + && ((wi = fgetwc_unlocked(stream)) != WEOF) + && ((*p++ = wi) != '\n') + ) { + --n; + } + if (p == ws) { + /* TODO -- should we set errno? */ +/* if (n <= 0) { */ +/* errno = EINVAL; */ +/* } */ + return NULL; + } + *p = 0; + return ws; +} +libc_hidden_def(fgetws_unlocked) + +#ifndef __UCLIBC_HAS_THREADS__ +strong_alias(fgetws_unlocked,fgetws) +#endif + +#elif defined __UCLIBC_HAS_THREADS__ + +wchar_t *fgetws(wchar_t *__restrict ws, int n, FILE *__restrict stream) +{ + wchar_t *retval; + __STDIO_AUTO_THREADLOCK_VAR; + + __STDIO_AUTO_THREADLOCK(stream); + + retval = fgetws_unlocked(ws, n, stream); + + __STDIO_AUTO_THREADUNLOCK(stream); + + return retval; +} + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fgetws_unlocked.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fgetws_unlocked.c new file mode 100644 index 00000000..6dd58f20 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fgetws_unlocked.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define __DO_UNLOCKED +#include "fgetws.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fileno.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fileno.c new file mode 100644 index 00000000..452572ba --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fileno.c @@ -0,0 +1,48 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + + +#ifdef __DO_UNLOCKED + +int fileno_unlocked(register FILE *stream) +{ + __STDIO_STREAM_VALIDATE(stream); + + if ((!__STDIO_STREAM_IS_CUSTOM(stream)) && (stream->__filedes >= 0)) { + return stream->__filedes; + } + + __set_errno(EBADF); + return -1; +} +libc_hidden_def(fileno_unlocked) + +#ifndef __UCLIBC_HAS_THREADS__ +strong_alias(fileno_unlocked,fileno) +libc_hidden_def(fileno) +#endif + +#elif defined __UCLIBC_HAS_THREADS__ + +int fileno(register FILE *stream) +{ + int retval; + __STDIO_AUTO_THREADLOCK_VAR; + + __STDIO_AUTO_THREADLOCK(stream); + + retval = fileno_unlocked(stream); + + __STDIO_AUTO_THREADUNLOCK(stream); + + return retval; +} +libc_hidden_def(fileno) + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fileno_unlocked.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fileno_unlocked.c new file mode 100644 index 00000000..e5005929 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fileno_unlocked.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define __DO_UNLOCKED +#include "fileno.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/flockfile.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/flockfile.c new file mode 100644 index 00000000..3fad7118 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/flockfile.c @@ -0,0 +1,16 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +void flockfile(FILE *stream) +{ + __STDIO_STREAM_VALIDATE(stream); + + __STDIO_ALWAYS_THREADLOCK_CANCEL_UNSAFE(stream); +} + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fmemopen.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fmemopen.c new file mode 100644 index 00000000..4a67376f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fmemopen.c @@ -0,0 +1,181 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include + +#ifdef __USE_GNU +#include "_stdio.h" + + +#ifndef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ +#error no custom streams! +#endif + +typedef struct { + size_t pos; + size_t len; + size_t eof; + int dynbuf; + unsigned char *buf; + FILE *fp; +} __fmo_cookie; + +#define COOKIE ((__fmo_cookie *) cookie) + +static ssize_t fmo_read(register void *cookie, char *buf, size_t bufsize) +{ + size_t count = COOKIE->len - COOKIE->pos; + + /* Note: 0 < bufsize < SSIZE_MAX because of _stdio_READ. */ + if (!count) { /* EOF! */ + return 0; + } + + if (bufsize > count) { + bufsize = count; + } + + memcpy(buf, COOKIE->buf + COOKIE->pos, bufsize); + COOKIE->pos += bufsize; + + return bufsize; +} + +static ssize_t fmo_write(register void *cookie, const char *buf, size_t bufsize) +{ + size_t count; + + /* Note: bufsize < SSIZE_MAX because of _stdio_WRITE. */ + + /* If appending, need to seek to end of file!!!! */ + if (COOKIE->fp->__modeflags & __FLAG_APPEND) { + COOKIE->pos = COOKIE->eof; + } + + count = COOKIE->len - COOKIE->pos; + + if (bufsize > count) { + bufsize = count; + if (count == 0) { /* We're at the end of the buffer... */ + __set_errno(EFBIG); + return -1; + } + } + + memcpy(COOKIE->buf + COOKIE->pos, buf, bufsize); + COOKIE->pos += bufsize; + + if (COOKIE->pos > COOKIE->eof) { + COOKIE->eof = COOKIE->pos; + if (bufsize < count) { /* New eof and still room in buffer? */ + *(COOKIE->buf + COOKIE->pos) = 0; + } + } + + return bufsize; +} + +/* glibc doesn't allow seeking, but it has in-buffer seeks... we don't. */ +static int fmo_seek(register void *cookie, __offmax_t *pos, int whence) +{ + __offmax_t p = *pos; + + /* Note: fseek already checks that whence is legal, so don't check here + * unless debugging. */ + assert(((unsigned int) whence) <= 2); + + if (whence != SEEK_SET) { + p += (whence == SEEK_CUR) ? COOKIE->pos : /* SEEK_END */ COOKIE->eof; + } + + /* Note: glibc only allows seeking in the buffer. We'll actually restrict + * to the data. */ + /* Check for offset < 0, offset > eof, or offset overflow... */ + if (((uintmax_t) p) > COOKIE->eof) { + return -1; + } + + COOKIE->pos = *pos = p; + return 0; +} + +static int fmo_close(register void *cookie) +{ + if (COOKIE->dynbuf) { + free(COOKIE->buf); + } + free(cookie); + return 0; +} + +#undef COOKIE + +static const cookie_io_functions_t _fmo_io_funcs = { + fmo_read, fmo_write, fmo_seek, fmo_close +}; + +/* TODO: If we have buffers enabled, it might be worthwile to add a pointer + * to the FILE in the cookie and have read, write, and seek operate directly + * on the buffer itself (ie replace the FILE buffer with the cookie buffer + * and update FILE bufstart, etc. whenever we seek). */ + +FILE *fmemopen(void *s, size_t len, const char *modes) +{ + FILE *fp; + register __fmo_cookie *cookie; + size_t i; + + if ((cookie = malloc(sizeof(__fmo_cookie))) != NULL) { + cookie->len = len; + cookie->eof = cookie->pos = 0; /* pos and eof adjusted below. */ + cookie->dynbuf = 0; + if (((cookie->buf = s) == NULL) && (len > 0)) { + if ((cookie->buf = malloc(len)) == NULL) { + goto EXIT_cookie; + } + cookie->dynbuf = 1; + *cookie->buf = 0; /* If we're appending, treat as empty file. */ + } + +#ifndef __BCC__ + fp = fopencookie(cookie, modes, _fmo_io_funcs); +#else + fp = fopencookie(cookie, modes, &_fmo_io_funcs); +#endif + /* Note: We don't need to worry about locking fp in the thread case + * as the only possible access would be a close or flush with + * nothing currently in the FILE's write buffer. */ + + if (fp != NULL) { + cookie->fp = fp; + if (fp->__modeflags & __FLAG_READONLY) { + cookie->eof = len; + } + if ((fp->__modeflags & __FLAG_APPEND) && (len > 0)) { + for (i = 0 ; i < len ; i++) { + if (cookie->buf[i] == 0) { + break; + } + } + cookie->eof = cookie->pos = i; /* Adjust eof and pos. */ + } + + __STDIO_STREAM_VALIDATE(fp); + + return fp; + } + } + + if (!s) { + free(cookie->buf); + } + EXIT_cookie: + free(cookie); + + return NULL; +} +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fopen.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fopen.c new file mode 100644 index 00000000..a2d6617e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fopen.c @@ -0,0 +1,21 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +#ifndef __DO_LARGEFILE +# define FILEDES_ARG (-1) +# undef fopen +#else +# undef fopen64 +#endif + +FILE *fopen(const char * __restrict filename, const char * __restrict mode) +{ + return _stdio_fopen(((intptr_t) filename), mode, NULL, FILEDES_ARG); +} +libc_hidden_def(fopen) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fopen64.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fopen64.c new file mode 100644 index 00000000..cbdb03d6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fopen64.c @@ -0,0 +1,14 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +#define __DO_LARGEFILE +#undef fopen +#define fopen fopen64 +#define FILEDES_ARG (-2) +#include "fopen.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fopencookie.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fopencookie.c new file mode 100644 index 00000000..c4927e0b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fopencookie.c @@ -0,0 +1,66 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include + +#ifdef __USE_GNU +#include "_stdio.h" + +#ifndef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ +#error no custom streams! +#endif + +/* NOTE: GLIBC difference!!! -- fopencookie + * According to the info pages, glibc allows seeking within buffers even if + * no seek function is supplied. We don't. */ + +/* NOTE: GLIBC difference!!! -- fopencookie + * When compiled without large file support, the offset pointer for the + * cookie_seek function is off_t * and not off64_t * as for glibc. */ + +/* NOTE: GLIBC difference!!! -- fopencookie (bcc only) + * Since bcc doesn't support passing of structs, we define fopencookie as a + * macro in terms of _fopencookie which takes a struct * for the io functions + * instead. + */ + +/* Currently no real reentrancy issues other than a possible double close(). */ + +#ifndef __BCC__ +FILE *fopencookie(void * __restrict cookie, const char * __restrict mode, + cookie_io_functions_t io_functions) +#else +FILE *_fopencookie(void * __restrict cookie, const char * __restrict mode, + register cookie_io_functions_t *io_functions) +#endif +{ + FILE *stream; + + /* Fake an fdopen guaranteed to pass the _stdio_fopen basic agreement + * check without an fcntl call. */ + stream = _stdio_fopen(((intptr_t)(INT_MAX-1)), mode, NULL, INT_MAX); + if (stream) { + stream->__filedes = -1; +#ifndef __BCC__ + stream->__gcs = io_functions; +#else + stream->__gcs.read = io_functions->read; + stream->__gcs.write = io_functions->write; + stream->__gcs.seek = io_functions->seek; + stream->__gcs.close = io_functions->close; +#endif + stream->__cookie = cookie; + + __STDIO_STREAM_VALIDATE(stream); + } + + return stream; +} +#ifndef __BCC__ +libc_hidden_def(fopencookie) +#endif +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fprintf.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fprintf.c new file mode 100644 index 00000000..fb754956 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fprintf.c @@ -0,0 +1,23 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" +#include + + +int fprintf(FILE * __restrict stream, const char * __restrict format, ...) +{ + va_list arg; + int rv; + + va_start(arg, format); + rv = vfprintf(stream, format, arg); + va_end(arg); + + return rv; +} +libc_hidden_def(fprintf) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fputc.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fputc.c new file mode 100644 index 00000000..b49f868f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fputc.c @@ -0,0 +1,106 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +#undef fputc +#undef fputc_unlocked +#undef putc +#undef putc_unlocked + + +#ifdef __DO_UNLOCKED + +int __fputc_unlocked(int c, register FILE *stream) +{ + __STDIO_STREAM_VALIDATE(stream); + + /* First the fast path. We're good to go if putc macro enabled. */ + if (__STDIO_STREAM_CAN_USE_BUFFER_ADD(stream)) { + __STDIO_STREAM_BUFFER_ADD(stream, ((unsigned char) c)); + return (unsigned char) c; + } + + /* Next quickest... writing and narrow oriented, but macro + * disabled and/or buffer is full. */ + if (__STDIO_STREAM_IS_NARROW_WRITING(stream) + || !__STDIO_STREAM_TRANS_TO_WRITE(stream, __FLAG_NARROW) + ) { + if (__STDIO_STREAM_IS_FAKE_VSNPRINTF(stream)) { + return (unsigned char) c; + } + + if (__STDIO_STREAM_BUFFER_SIZE(stream)) { /* Do we have a buffer? */ + /* The buffer is full and/or the stream is line buffered. */ + if (!__STDIO_STREAM_BUFFER_WAVAIL(stream) /* Buffer full? */ + && __STDIO_COMMIT_WRITE_BUFFER(stream) /* Commit failed! */ + ) { + goto BAD; + } +#ifdef __UCLIBC_MJN3_ONLY__ +#warning CONSIDER: Should we fail if the commit fails but we now have room? +#endif + + __STDIO_STREAM_BUFFER_ADD(stream, ((unsigned char) c)); + + if (__STDIO_STREAM_IS_LBF(stream)) { + if ((((unsigned char) c) == '\n') + && __STDIO_COMMIT_WRITE_BUFFER(stream)) { + /* Commit failed! */ + __STDIO_STREAM_BUFFER_UNADD(stream); /* Undo the write! */ + goto BAD; + } + } + } else { + /* NOTE: Do not try to save space by moving uc to the top of + * the file, as that dramaticly increases runtime. */ + unsigned char uc = (unsigned char) c; + if (! __stdio_WRITE(stream, &uc, 1)) { + goto BAD; + } + } + return (unsigned char) c; + } + + BAD: + return EOF; +} +libc_hidden_def(__fputc_unlocked) + +strong_alias(__fputc_unlocked,fputc_unlocked) +libc_hidden_def(fputc_unlocked) + +strong_alias(__fputc_unlocked,putc_unlocked) +libc_hidden_def(putc_unlocked) +#ifndef __UCLIBC_HAS_THREADS__ +strong_alias(__fputc_unlocked,fputc) +libc_hidden_def(fputc) + +strong_alias(__fputc_unlocked,putc) +libc_hidden_def(putc) +#endif + +#elif defined __UCLIBC_HAS_THREADS__ + +int fputc(int c, register FILE *stream) +{ + if (stream->__user_locking != 0) { + return __PUTC_UNLOCKED_MACRO(c, stream); + } else { + int retval; + __STDIO_ALWAYS_THREADLOCK(stream); + retval = __PUTC_UNLOCKED_MACRO(c, stream); + __STDIO_ALWAYS_THREADUNLOCK(stream); + return retval; + } +} +libc_hidden_def(fputc) + +strong_alias(fputc,putc) +libc_hidden_def(putc) + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fputc_unlocked.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fputc_unlocked.c new file mode 100644 index 00000000..dc4c77a5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fputc_unlocked.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define __DO_UNLOCKED +#include "fputc.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fputs.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fputs.c new file mode 100644 index 00000000..b3ede687 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fputs.c @@ -0,0 +1,50 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + + + +/* Note: The standard says fputs returns a nonnegative number on + * success. In this implementation, we return the length of the + * string written on success. + */ + +#ifdef __DO_UNLOCKED + +int fputs_unlocked(register const char * __restrict s, + FILE * __restrict stream) +{ + size_t n = strlen(s); + + return ((fwrite_unlocked(s, 1, n, stream) == n) ? n : EOF); +} +libc_hidden_def(fputs_unlocked) + +#ifndef __UCLIBC_HAS_THREADS__ +strong_alias(fputs_unlocked,fputs) +libc_hidden_def(fputs) +#endif + +#elif defined __UCLIBC_HAS_THREADS__ + +int fputs(const char * __restrict s, register FILE * __restrict stream) +{ + int retval; + __STDIO_AUTO_THREADLOCK_VAR; + + __STDIO_AUTO_THREADLOCK(stream); + + retval = fputs_unlocked(s, stream); + + __STDIO_AUTO_THREADUNLOCK(stream); + + return retval; +} +libc_hidden_def(fputs) + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fputs_unlocked.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fputs_unlocked.c new file mode 100644 index 00000000..c7ff3f59 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fputs_unlocked.c @@ -0,0 +1,14 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include + +#ifdef __USE_GNU +# define __DO_UNLOCKED +# include "fputs.c" +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fputwc.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fputwc.c new file mode 100644 index 00000000..7f46f48b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fputwc.c @@ -0,0 +1,43 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + + +#ifdef __DO_UNLOCKED + +wint_t fputwc_unlocked(wchar_t wc, FILE *stream) +{ + return _wstdio_fwrite(&wc, 1, stream) ? wc : WEOF; +} +libc_hidden_def(fputwc_unlocked) + +strong_alias(fputwc_unlocked,putwc_unlocked) +#ifndef __UCLIBC_HAS_THREADS__ +strong_alias(fputwc_unlocked,fputwc) +strong_alias(fputwc_unlocked,putwc) +#endif + +#elif defined __UCLIBC_HAS_THREADS__ + +wint_t fputwc(wchar_t wc, register FILE *stream) +{ + wint_t retval; + __STDIO_AUTO_THREADLOCK_VAR; + + __STDIO_AUTO_THREADLOCK(stream); + + retval = fputwc_unlocked(wc, stream); + + __STDIO_AUTO_THREADUNLOCK(stream); + + return retval; +} + +strong_alias(fputwc,putwc) + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fputwc_unlocked.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fputwc_unlocked.c new file mode 100644 index 00000000..757cbd0d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fputwc_unlocked.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define __DO_UNLOCKED +#include "fputwc.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fputws.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fputws.c new file mode 100644 index 00000000..7a189218 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fputws.c @@ -0,0 +1,45 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + + + +#ifdef __DO_UNLOCKED + +int fputws_unlocked(const wchar_t *__restrict ws, + register FILE *__restrict stream) +{ + size_t n = wcslen(ws); + + return (_wstdio_fwrite(ws, n, stream) == n) ? 0 : -1; +} +libc_hidden_def(fputws_unlocked) + +#ifndef __UCLIBC_HAS_THREADS__ +strong_alias(fputws_unlocked,fputws) +libc_hidden_def(fputws) +#endif + +#elif defined __UCLIBC_HAS_THREADS__ + +int fputws(const wchar_t *__restrict ws, register FILE *__restrict stream) +{ + int retval; + __STDIO_AUTO_THREADLOCK_VAR; + + __STDIO_AUTO_THREADLOCK(stream); + + retval = fputws_unlocked(ws, stream); + + __STDIO_AUTO_THREADUNLOCK(stream); + + return retval; +} +libc_hidden_def(fputws) + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fputws_unlocked.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fputws_unlocked.c new file mode 100644 index 00000000..b3a03777 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fputws_unlocked.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define __DO_UNLOCKED +#include "fputws.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fread.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fread.c new file mode 100644 index 00000000..d2fcc70d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fread.c @@ -0,0 +1,112 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + + +#ifdef __DO_UNLOCKED + + +size_t fread_unlocked(void * __restrict ptr, size_t size, size_t nmemb, + FILE * __restrict stream) +{ + __STDIO_STREAM_VALIDATE(stream); + assert(stream->__filedes >= -1); + + /* Note: If nmbem * size > SIZE_MAX then there is an application + * bug since no array can be larger than SIZE_MAX in size. */ + + if ((__STDIO_STREAM_IS_NARROW_READING(stream) + || !__STDIO_STREAM_TRANS_TO_READ(stream, __FLAG_NARROW)) + && size && nmemb + ) { + + if (nmemb <= (SIZE_MAX / size)) { + unsigned char *buffer = (unsigned char *) ptr; + size_t todo, bytes, avail; + + todo = bytes = size * nmemb; + + /* Check for ungots... */ + while (stream->__modeflags & __FLAG_UNGOT) { + *buffer++ = stream->__ungot[(stream->__modeflags--) & 1]; + stream->__ungot[1] = 0; + if (!--todo) { + goto DONE; + } + } + +#ifdef __STDIO_BUFFERS + /* Next check for available buffered... */ + if ((avail = stream->__bufread - stream->__bufpos) > 0) { + if (avail > todo) { + avail = todo; + } + memcpy(buffer, stream->__bufpos, avail); + buffer += avail; + stream->__bufpos += avail; + if (!(todo -= avail)) { + goto DONE; + } + } + + /* We need to read from the host environment, so we must + * flush all line buffered streams if the stream is not + * fully buffered. */ + if (!__STDIO_STREAM_IS_FBF(stream)) { + __STDIO_FLUSH_LBF_STREAMS; + } +#endif + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning CONSIDER: should we refill and read from the buffer sometimes? +#endif + while ((avail = __stdio_READ(stream, buffer, todo)) > 0) { + buffer += avail; + if (!(todo -= avail)) { + break; + } + } + + DONE: + __STDIO_STREAM_VALIDATE(stream); + return (bytes - todo) / size; + } + + __STDIO_STREAM_SET_ERROR(stream); + __set_errno(EINVAL); + } + + __STDIO_STREAM_VALIDATE(stream); + return 0; +} +libc_hidden_def(fread_unlocked) + +#ifndef __UCLIBC_HAS_THREADS__ +strong_alias(fread_unlocked,fread) +libc_hidden_def(fread) +#endif + +#elif defined __UCLIBC_HAS_THREADS__ + +size_t fread(void * __restrict ptr, size_t size, size_t nmemb, + register FILE * __restrict stream) +{ + size_t retval; + __STDIO_AUTO_THREADLOCK_VAR; + + __STDIO_AUTO_THREADLOCK(stream); + + retval = fread_unlocked(ptr, size, nmemb, stream); + + __STDIO_AUTO_THREADUNLOCK(stream); + + return retval; +} +libc_hidden_def(fread) + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fread_unlocked.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fread_unlocked.c new file mode 100644 index 00000000..441edbb6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fread_unlocked.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define __DO_UNLOCKED +#include "fread.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/freopen.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/freopen.c new file mode 100644 index 00000000..f48a43b7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/freopen.c @@ -0,0 +1,75 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + + +#ifndef __DO_LARGEFILE +# define FILEDES_ARG (-1) +#endif + +FILE *freopen(const char * __restrict filename, const char * __restrict mode, + register FILE * __restrict stream) +{ + /* + * ANSI/ISO allow (implementation-defined) change of mode for an + * existing file if filename is NULL. It doesn't look like Linux + * supports this, so we don't here. + * + * NOTE: Whether or not the stream is free'd on failure is unclear + * w.r.t. ANSI/ISO. This implementation chooses to NOT free + * the stream and associated buffer if they were dynamically + * allocated. + * NOTE: Previous versions of uClibc did free dynamic storage. + * + * TODO: Apparently linux allows setting append mode. Implement? + */ + unsigned short dynmode; + register FILE *fp; + __STDIO_AUTO_THREADLOCK_VAR; + + __STDIO_AUTO_THREADLOCK(stream); + + __STDIO_STREAM_VALIDATE(stream); + + __STDIO_OPENLIST_INC_USE; /* Do not remove the file from the list. */ + + /* First, flush and close, but don't deallocate, the stream. */ + /* This also removes the stream for the open file list. */ + dynmode = (stream->__modeflags & (__FLAG_FREEBUF|__FLAG_FREEFILE)); + + stream->__modeflags &= ~(__FLAG_FREEBUF|__FLAG_FREEFILE); + + /* Only call fclose on the stream if it is not already closed. */ + if ((stream->__modeflags & (__FLAG_READONLY|__FLAG_WRITEONLY)) + != (__FLAG_READONLY|__FLAG_WRITEONLY) + ) { + fclose(stream); /* Failures are ignored. */ + /* NOTE: fclose always does __STDIO_OPENLIST_INC_DEL_CNT. But we don't + * want to remove this FILE from the open list, even if the freopen fails. + * Consider the case of a failed freopen() on stdin. You probably still + * want to be able to call freopen() again. Similarly for other "malloc'd" + * streams. */ + __STDIO_OPENLIST_DEC_DEL_CNT; + } + + fp = _stdio_fopen(((intptr_t) filename), mode, stream, FILEDES_ARG); + if (!fp) { + /* Don't remove stream from the open file list and (potentially) free it. + * See _stdio_openlist_dec_use() in fflush.c. */ + stream->__modeflags = __FLAG_READONLY|__FLAG_WRITEONLY|__FLAG_FAILED_FREOPEN; + } + + /* Reset the allocation flags. */ + stream->__modeflags |= dynmode; + + __STDIO_OPENLIST_DEC_USE; + + __STDIO_AUTO_THREADUNLOCK(stream); + + return fp; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/freopen64.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/freopen64.c new file mode 100644 index 00000000..e44c972f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/freopen64.c @@ -0,0 +1,13 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +#define __DO_LARGEFILE +#define freopen freopen64 +#define FILEDES_ARG (-2) +#include "freopen.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fscanf.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fscanf.c new file mode 100644 index 00000000..102cb8d5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fscanf.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define L_fscanf +#include "_scanf.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fseeko.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fseeko.c new file mode 100644 index 00000000..3caf1ac7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fseeko.c @@ -0,0 +1,81 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +#if SEEK_SET != 0 || SEEK_CUR != 1 || SEEK_END != 2 +# error Assumption violated -- values of SEEK_SET, SEEK_CUR, SEEK_END +#endif + +#ifndef __DO_LARGEFILE +# define FSEEK fseek +# define OFFSET_TYPE long int +#endif + +int FSEEK(register FILE *stream, OFFSET_TYPE offset, int whence) +{ +#if defined(__UCLIBC_HAS_LFS__) && !defined(__DO_LARGEFILE) + + return fseeko64(stream, offset, whence); + +#else + + __offmax_t pos = offset; + int retval = -1; + __STDIO_AUTO_THREADLOCK_VAR; + + if (((unsigned int) whence) > 2) { + __set_errno(EINVAL); + } else { + __STDIO_AUTO_THREADLOCK(stream); + + __STDIO_STREAM_VALIDATE(stream); + + if ((!__STDIO_STREAM_IS_WRITING(stream) + || !__STDIO_COMMIT_WRITE_BUFFER(stream)) + && ((whence != SEEK_CUR) + || (__stdio_adjust_position(stream, &pos) >= 0)) + && (__SEEK(stream, &pos, whence) >= 0) + ) { + + /* Clear reading/writing modes, EOF, and ungots. */ + stream->__modeflags &= + ~(__MASK_READING|__FLAG_WRITING|__FLAG_EOF); + + /* Make sure all pointers are reset. */ + __STDIO_STREAM_INIT_BUFREAD_BUFPOS(stream); + __STDIO_STREAM_DISABLE_GETC(stream); + __STDIO_STREAM_DISABLE_PUTC(stream); + + /* We reinitialize the mbstate object. Doing so is + * implementation defined behavior. */ +#ifdef __STDIO_MBSTATE + __INIT_MBSTATE(&(stream->__state)); +#endif +#ifdef __UCLIBC_HAS_WCHAR__ + stream->__ungot_width[0] = 0; +#endif + + retval = 0; + } + + __STDIO_STREAM_VALIDATE(stream); + + __STDIO_AUTO_THREADUNLOCK(stream); + } + + return retval; + +#endif +} + +#ifdef __DO_LARGEFILE +libc_hidden_def(fseeko64) +#else +libc_hidden_def(fseek) +strong_alias(fseek,fseeko) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fseeko64.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fseeko64.c new file mode 100644 index 00000000..78cab1b5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fseeko64.c @@ -0,0 +1,13 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +#define __DO_LARGEFILE +#define FSEEK fseeko64 +#define OFFSET_TYPE __off64_t +#include "fseeko.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fsetpos.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fsetpos.c new file mode 100644 index 00000000..d63adc02 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fsetpos.c @@ -0,0 +1,39 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +#ifndef __DO_LARGEFILE +#define FSEEK fseek +#endif + +libc_hidden_proto(FSEEK) + +int fsetpos(FILE *stream, register const fpos_t *pos) +{ +#ifdef __STDIO_MBSTATE + + int retval = -1; + __STDIO_AUTO_THREADLOCK_VAR; + + __STDIO_AUTO_THREADLOCK(stream); + + if ((retval = FSEEK(stream, pos->__pos, SEEK_SET)) == 0) { + __COPY_MBSTATE(&(stream->__state), &(pos->__mbstate)); + stream->__ungot_width[0]= pos->__mblen_pending; + } + + __STDIO_AUTO_THREADUNLOCK(stream); + + return retval; + +#else + + return FSEEK(stream, pos->__pos, SEEK_SET); + +#endif +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fsetpos64.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fsetpos64.c new file mode 100644 index 00000000..82819a4f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fsetpos64.c @@ -0,0 +1,14 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +#define __DO_LARGEFILE +#define fsetpos fsetpos64 +#define fpos_t fpos64_t +#define FSEEK fseeko64 +#include "fsetpos.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/ftello.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/ftello.c new file mode 100644 index 00000000..e8ff3653 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/ftello.c @@ -0,0 +1,57 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +#ifndef __DO_LARGEFILE +# define FTELL ftell +# define OFFSET_TYPE long int +#endif + +OFFSET_TYPE FTELL(register FILE *stream) +{ +#if defined(__UCLIBC_HAS_LFS__) && !defined(__DO_LARGEFILE) + + __offmax_t pos = ftello64(stream); + + if ((sizeof(long) >= sizeof(__offmax_t)) || (((long) pos) == pos)) { + return ((long) pos); + } else { + __set_errno(EOVERFLOW); + return -1; + } + +#else + + __offmax_t pos = 0; + __STDIO_AUTO_THREADLOCK_VAR; + + __STDIO_AUTO_THREADLOCK(stream); + + __STDIO_STREAM_VALIDATE(stream); + + if ((__SEEK(stream, &pos, + ((__STDIO_STREAM_IS_WRITING(stream) + && (stream->__modeflags & __FLAG_APPEND)) + ? SEEK_END : SEEK_CUR)) < 0) + || (__stdio_adjust_position(stream, &pos) < 0)) { + pos = -1; + } + + __STDIO_AUTO_THREADUNLOCK(stream); + + return pos; + +#endif +} + +#ifdef __DO_LARGEFILE +libc_hidden_def(ftello64) +#else +libc_hidden_def(ftell) +strong_alias(ftell,ftello) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/ftello64.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/ftello64.c new file mode 100644 index 00000000..905834f3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/ftello64.c @@ -0,0 +1,13 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +#define __DO_LARGEFILE +#define FTELL ftello64 +#define OFFSET_TYPE __off64_t +#include "ftello.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/ftrylockfile.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/ftrylockfile.c new file mode 100644 index 00000000..0d2e156a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/ftrylockfile.c @@ -0,0 +1,19 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning CONSIDER: What should this return when not threading? +#endif + +int ftrylockfile(FILE *stream) +{ + __STDIO_STREAM_VALIDATE(stream); + + return __STDIO_ALWAYS_THREADTRYLOCK_CANCEL_UNSAFE(stream); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/funlockfile.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/funlockfile.c new file mode 100644 index 00000000..2ddf0979 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/funlockfile.c @@ -0,0 +1,15 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +void funlockfile(FILE *stream) +{ + __STDIO_STREAM_VALIDATE(stream); + + __STDIO_ALWAYS_THREADUNLOCK_CANCEL_UNSAFE(stream); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fwide.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fwide.c new file mode 100644 index 00000000..422d789f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fwide.c @@ -0,0 +1,32 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +/* TODO: According to SUSv3 should return EBADF if invalid stream. */ + +int fwide(register FILE *stream, int mode) +{ + __STDIO_AUTO_THREADLOCK_VAR; + + __STDIO_AUTO_THREADLOCK(stream); + + __STDIO_STREAM_VALIDATE(stream); + + if (mode && !(stream->__modeflags & (__FLAG_WIDE|__FLAG_NARROW))) { + stream->__modeflags |= ((mode > 0) ? __FLAG_WIDE : __FLAG_NARROW); + } + + mode = (stream->__modeflags & __FLAG_WIDE) + - (stream->__modeflags & __FLAG_NARROW); + + assert((stream->__modeflags & (__FLAG_WIDE|__FLAG_NARROW)) + != (__FLAG_WIDE|__FLAG_NARROW)); + __STDIO_AUTO_THREADUNLOCK(stream); + + return mode; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fwprintf.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fwprintf.c new file mode 100644 index 00000000..2f2dddc1 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fwprintf.c @@ -0,0 +1,24 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" +#include +#include + + +int fwprintf(FILE * __restrict stream, const wchar_t * __restrict format, ...) +{ + va_list arg; + int rv; + + va_start(arg, format); + rv = vfwprintf(stream, format, arg); + va_end(arg); + + return rv; +} +libc_hidden_def(fwprintf) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fwrite.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fwrite.c new file mode 100644 index 00000000..71793ff2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fwrite.c @@ -0,0 +1,62 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + + +#ifdef __DO_UNLOCKED + +size_t fwrite_unlocked(const void * __restrict ptr, size_t size, + size_t nmemb, register FILE * __restrict stream) +{ + __STDIO_STREAM_VALIDATE(stream); + + /* Note: If nmbem * size > SIZE_MAX then there is an application + * bug since no array can be larger than SIZE_MAX in size. */ + + if ((__STDIO_STREAM_IS_NARROW_WRITING(stream) + || !__STDIO_STREAM_TRANS_TO_WRITE(stream, __FLAG_NARROW)) + && size && nmemb + ) { + + if (nmemb <= (SIZE_MAX / size)) { + return __stdio_fwrite((const unsigned char *) ptr, + size*nmemb, stream) / size; + } + + __STDIO_STREAM_SET_ERROR(stream); + __set_errno(EINVAL); + } + + return 0; +} +libc_hidden_def(fwrite_unlocked) + +#ifndef __UCLIBC_HAS_THREADS__ +strong_alias(fwrite_unlocked,fwrite) +libc_hidden_def(fwrite) +#endif + +#elif defined __UCLIBC_HAS_THREADS__ + +size_t fwrite(const void * __restrict ptr, size_t size, + size_t nmemb, register FILE * __restrict stream) +{ + size_t retval; + __STDIO_AUTO_THREADLOCK_VAR; + + __STDIO_AUTO_THREADLOCK(stream); + + retval = fwrite_unlocked(ptr, size, nmemb, stream); + + __STDIO_AUTO_THREADUNLOCK(stream); + + return retval; +} +libc_hidden_def(fwrite) + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fwrite_unlocked.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fwrite_unlocked.c new file mode 100644 index 00000000..0f9e026c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fwrite_unlocked.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define __DO_UNLOCKED +#include "fwrite.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fwscanf.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fwscanf.c new file mode 100644 index 00000000..3409d00a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/fwscanf.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define L_fwscanf +#include "_scanf.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/getchar.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/getchar.c new file mode 100644 index 00000000..b6c650c9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/getchar.c @@ -0,0 +1,45 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + + +#undef getchar +#ifdef __DO_UNLOCKED + +/* the only use of the hidden getchar_unlocked is in gets.c */ +#undef getchar_unlocked +int getchar_unlocked(void) +{ + register FILE *stream = stdin; + + return __GETC_UNLOCKED_MACRO(stream); +} +libc_hidden_def(getchar_unlocked) + +#ifndef __UCLIBC_HAS_THREADS__ +strong_alias(getchar_unlocked,getchar) +#endif + +#elif defined __UCLIBC_HAS_THREADS__ + +int getchar(void) +{ + register FILE *stream = stdin; + + if (stream->__user_locking != 0) { + return __GETC_UNLOCKED_MACRO(stream); + } else { + int retval; + __STDIO_ALWAYS_THREADLOCK(stream); + retval = __GETC_UNLOCKED_MACRO(stream); + __STDIO_ALWAYS_THREADUNLOCK(stream); + return retval; + } +} + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/getchar_unlocked.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/getchar_unlocked.c new file mode 100644 index 00000000..60ea2512 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/getchar_unlocked.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define __DO_UNLOCKED +#include "getchar.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/getdelim.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/getdelim.c new file mode 100644 index 00000000..987e32a1 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/getdelim.c @@ -0,0 +1,82 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include + +#ifdef __USE_GNU +#include "_stdio.h" + + + +/* Note: There is a defect in this function. (size_t vs ssize_t). */ + +/* glibc function -- + * Return -1 if error or EOF prior to any chars read. + * Return number of chars read (including possible delimiter but not + * the terminating nul) otherwise. + * + * NOTE: If we need to allocate a buffer, we do so prior to attempting + * a reading. So space may be allocated even if initially at EOF. + */ + +#define GETDELIM_GROWBY 64 + +ssize_t getdelim(char **__restrict lineptr, size_t *__restrict n, + int delimiter, register FILE *__restrict stream) +{ + register char *buf; + ssize_t pos = -1; + int c; + __STDIO_AUTO_THREADLOCK_VAR; + + if (!lineptr || !n || !stream) { /* Be compatable with glibc... even */ + __set_errno(EINVAL); /* though I think we should assert here */ + } else { + __STDIO_AUTO_THREADLOCK(stream); + + if (!(buf = *lineptr)) { /* If passed NULL for buffer, */ + *n = 0; /* ignore value passed and treat size as 0. */ + } + + /* Within the loop, pos is actually the current buffer index + 2, + * because we want to make sure we have enough space to store + * an additional char plus a nul terminator. + */ + pos = 1; + + do { + if (pos >= *n) { + if (!(buf = realloc(buf, *n + GETDELIM_GROWBY))) { + pos = -1; + break; + } + *n += GETDELIM_GROWBY; + *lineptr = buf; + } + + if ((c = __GETC_UNLOCKED(stream)) != EOF) { + buf[++pos - 2] = c; + if (c != delimiter) { + continue; + } + } + + /* We're done, so correct pos back to being the current index. */ + if ((pos -= 2) >= 0) { + buf[++pos] = 0; + } + break; + + } while (1); + + __STDIO_AUTO_THREADUNLOCK(stream); + } + + return pos; +} +libc_hidden_def(getdelim) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/getline.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/getline.c new file mode 100644 index 00000000..98ce8d10 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/getline.c @@ -0,0 +1,21 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include + +#ifdef __USE_GNU +#include "_stdio.h" + + + +ssize_t getline(char **__restrict lineptr, size_t *__restrict n, + FILE *__restrict stream) +{ + return getdelim(lineptr, n, '\n', stream); +} +libc_hidden_def(getline) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/gets.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/gets.c new file mode 100644 index 00000000..515e966d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/gets.c @@ -0,0 +1,39 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +link_warning(gets, "the 'gets' function is dangerous and should not be used.") + +/* UNSAFE FUNCTION -- do not bother optimizing */ + +/* disable macro, force actual function call */ +#undef getchar_unlocked + +char *gets(char *s) +{ + register char *p = s; + int c; + __STDIO_AUTO_THREADLOCK_VAR; + + __STDIO_AUTO_THREADLOCK(stdin); + + /* Note: don't worry about performance here... this shouldn't be used! + * Therefore, force actual function call. */ + while (((c = getchar_unlocked()) != EOF) && ((*p = c) != '\n')) { + ++p; + } + if ((c == EOF) || (s == p)) { + s = NULL; + } else { + *p = 0; + } + + __STDIO_AUTO_THREADUNLOCK(stdin); + + return s; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/getw.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/getw.c new file mode 100644 index 00000000..625f17f3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/getw.c @@ -0,0 +1,19 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + + +/* SUSv2 Legacy function -- need not be reentrant. */ + +int getw(FILE *stream) +{ + int aw; + + return (fread_unlocked((void *) &aw, sizeof(int), 1, stream) != 0) + ? aw : EOF; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/getwchar.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/getwchar.c new file mode 100644 index 00000000..75266de3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/getwchar.c @@ -0,0 +1,30 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +#ifdef __DO_UNLOCKED + + +wint_t getwchar_unlocked(void) +{ + return fgetwc_unlocked(stdin); +} + +#ifndef __UCLIBC_HAS_THREADS__ +strong_alias(getwchar_unlocked,getwchar) +#endif + +#elif defined __UCLIBC_HAS_THREADS__ + + +wint_t getwchar(void) +{ + return fgetwc(stdin); +} + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/getwchar_unlocked.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/getwchar_unlocked.c new file mode 100644 index 00000000..af4a9e88 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/getwchar_unlocked.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define __DO_UNLOCKED +#include "getwchar.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/old_vfprintf.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/old_vfprintf.c new file mode 100644 index 00000000..7d4bfea6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/old_vfprintf.c @@ -0,0 +1,710 @@ +/* + * This file based on printf.c from 'Dlibs' on the atari ST (RdeBath) + * + * + * Dale Schumacher 399 Beacon Ave. + * (alias: Dalnefre') St. Paul, MN 55104 + * dal@syntel.UUCP United States of America + * "It's not reality that's important, but how you perceive things." + */ + +/* Altered to use stdarg, made the core function vfnprintf. + * Hooked into the stdio package using 'inside information' + * Altered sizeof() assumptions, now assumes all integers except chars + * will be either + * sizeof(xxx) == sizeof(long) or sizeof(xxx) == sizeof(short) + * + * -RDB + */ + +/* + * Manuel Novoa III Dec 2000 + * + * The previous vfnprintf routine was almost completely rewritten with the + * goal of fixing some shortcomings and reducing object size. + * + * The summary of changes: + * + * Converted print conversion specification parsing from one big switch + * to a method using string tables. This new method verifies that the + * conversion flags, field width, precision, qualifier, and specifier + * appear in the correct order. Many questionable specifications were + * accepted by the previous code. This new method also resulted in a + * substantial reduction in object size of about 330 bytes (20%) from + * the old version (1627 bytes) on i386, even with the following + * improvements. + * + * Implemented %n specifier as required by the standards. + * Implemented proper handling of precision for int types. + * Implemented # for hex and pointer, fixed error for octal rep of 0. + * Implemented return of -1 on stream error. + * + * Added optional support for the GNU extension %m which prints the string + * corresponding the errno. + * + * Added optional support for long long ints and unsigned long long ints + * using the conversion qualifiers "ll", "L", or "q" (like glibc). + * + * Added optional support for doubles in a very limited form. None of + * the formating options are obeyed. The string returned by __dtostr + * is printed directly. + * + * Converted to use my (un)signed long (long) to string routines, which are + * smaller than the previous functions and don't require static buffers. + * + * Other Modifications: + * Modified sprintf, snprintf, vsprintf, vsnprintf to share on fake-file. + */ + +/* + * Manuel Novoa III Jan 2001 + * + * Removed fake file from *s*printf functions because of possible problems + * if called recursively. Instead, have sprintf, snprintf, and vsprintf + * call vsnprintf which allocates a fake file on the stack. + * Removed WANT_FPUTC option. Always use standard putc macro to avoid + * problems with the fake file used by the *s*printf functions. + * Fixed bug parsing flags -- did not restart scan. + * Added function asprintf. + * Fixed 0-pad prefixing bug. + * Converted sizeof(int) == sizeof(long) tests to compile time vs run time. + * This saves 112 bytes of code on i386. + * Fixed precision bug -- when negative set to default. + * Added function fnprintf to support __dtostr. + * Added floating point support for doubles. Yeah! + * + * + * May 2001 Fixes from Johan Adolfsson (johan.adolfsson@axis.com) + * 1) printf("%c",0) returned 0 instead of 1. + * 2) unrolled loop in asprintf to reduce size and remove compile warning. + * + * + * June 2001 + * 1) fix %p so that "0x" is prepended to outputed hex val + * 2) fix %p so that "(nil)" is output for (void *)0 to match glibc + * + * Sep 5, 2003 + * Convert to new floating point conversion routine. + * Fix qualifier handling on integer and %n conversions. + * Add support for vsnprintf when in non-buffered/no-wchar configuration. + * + */ + +/*****************************************************************************/ +/* OPTIONS */ +/*****************************************************************************/ +/* The optional support for long longs and doubles comes in two forms. + * + * 1) Normal (or partial for doubles) output support. Set to 1 to turn on. + * Adds about 130 bytes for doubles, about 220 bytes for long longs, + * and about 275 for both to the base code size of 1163 on i386. + */ + +/* These are now set in uClibc_config.h based on Config. */ +/* +#define __UCLIBC_HAS_FLOATS__ 1 +*/ + +/* 2) An error message is inserted into the stream, an arg of the + * appropriate size is removed from the arglist, and processing + * continues. This is adds less code and may be useful in some + * cases. Set to 1 to turn on. Adds about 50 bytes for doubles, + * about 140 bytes for long longs, and about 175 bytes for both + * to the base code size of 1163 on i386. + */ + +#define WANT_FLOAT_ERROR 0 + +/* + * Set to support GNU extension of %m to print string corresponding to errno. + * + * Warning: This adds about 50 bytes (i386) to the code but it also pulls in + * strerror and the corresponding string table which together are about 3.8k. + */ + +/* Now controlled by uClibc_stdio.h and set below. */ +/* #define WANT_GNU_ERRNO 0 */ + +/**************************************************************************/ + +#define _ISOC99_SOURCE /* for ULLONG primarily... */ +#include "_stdio.h" +/* #include */ +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __UCLIBC_HAS_THREADS__ +#include +#endif /* __UCLIBC_HAS_THREADS__ */ + + +/* #undef __UCLIBC_HAS_FLOATS__ */ +/* #undef WANT_FLOAT_ERROR */ +/* #define WANT_FLOAT_ERROR 1 */ + +/* #define __isdigit(c) (((unsigned int)(c - '0')) < 10) */ + +#ifdef __UCLIBC_HAS_PRINTF_M_SPEC__ +#define WANT_GNU_ERRNO 1 +#else +#define WANT_GNU_ERRNO 0 +#endif + +#undef PUTC +#undef OUTNSTR +#undef _outnstr + +#ifdef __STDIO_BUFFERS + +#define PUTC(C,F) putc_unlocked((C),(F)) +#define OUTNSTR _outnstr +#define _outnstr(stream, string, len) __stdio_fwrite(string, len, stream) + +#else /* __STDIO_BUFFERS */ + +typedef struct { + FILE f; + unsigned char *bufend; /* pointer to 1 past end of buffer */ + unsigned char *bufpos; +} __FILE_vsnprintf; + +#ifdef __UCLIBC_HAS_FLOATS__ +static void _outnstr(FILE *stream, const unsigned char *s, size_t n) +{ + __FILE_vsnprintf *f = (__FILE_vsnprintf *) stream; + + if (!__STDIO_STREAM_IS_FAKE_VSNPRINTF_NB(&f->f)) { + __stdio_fwrite(s, n, &f->f); + } else if (f->bufend > f->bufpos) { + size_t r = f->bufend - f->bufpos; + if (r > n) { + r = n; + } + memcpy(f->bufpos, s, r); + f->bufpos += r; + } +} +#endif + +static void putc_unlocked_sprintf(int c, __FILE_vsnprintf *f) +{ + if (!__STDIO_STREAM_IS_FAKE_VSNPRINTF_NB(&f->f)) { + putc_unlocked(c, &f->f); + } else if (f->bufpos < f->bufend) { + *f->bufpos++ = c; + } +} + + +#define PUTC(C,F) putc_unlocked_sprintf((C),(__FILE_vsnprintf *)(F)) +#define OUTNSTR _outnstr + +#endif /* __STDIO_BUFFERS */ + +#ifdef __UCLIBC_HAS_FLOATS__ +#include +#include + +typedef void (__fp_outfunc_t)(FILE *fp, intptr_t type, intptr_t len, + intptr_t buf); + +extern size_t _fpmaxtostr(FILE * fp, __fpmax_t x, struct printf_info *info, + __fp_outfunc_t fp_outfunc) attribute_hidden; + +static void _charpad(FILE * __restrict stream, int padchar, size_t numpad) +{ + /* TODO -- Use a buffer to cut down on function calls... */ + char pad[1]; + + *pad = padchar; + while (numpad) { + OUTNSTR(stream, pad, 1); + --numpad; + } +} + +static void _fp_out_narrow(FILE *fp, intptr_t type, intptr_t len, intptr_t buf) +{ + if (type & 0x80) { /* Some type of padding needed. */ + int buflen = strlen((const char *) buf); + if ((len -= buflen) > 0) { + _charpad(fp, (type & 0x7f), len); + } + len = buflen; + } + if (len) { + OUTNSTR(fp, (const char *) buf, len); + } +} + +#endif + + +enum { + FLAG_PLUS = 0, + FLAG_MINUS_LJUSTIFY, + FLAG_HASH, + FLAG_0_PAD, + FLAG_SPACE, +}; + +/* layout 01234 */ +static const char spec[] = "+-#0 "; + +/**********************************************************************/ + +extern void _store_inttype(void *dest, int desttype, uintmax_t val) attribute_hidden; +extern uintmax_t _load_inttype(int desttype, const void *src, int uflag) attribute_hidden; + +/* + * In order to ease translation to what arginfo and _print_info._flags expect, + * we map: 0:int 1:char 2:longlong 4:long 8:short + * and then _flags |= (((q << 7) + q) & 0x701) and argtype |= (_flags & 0x701) + */ + +#ifdef PDS +#error PDS already defined! +#endif +#ifdef SS +#error SS already defined! +#endif +#ifdef IMS +#error IMS already defined! +#endif + +#if PTRDIFF_MAX == INT_MAX +#define PDS 0 +#elif PTRDIFF_MAX == LONG_MAX +#define PDS 4 +#elif defined(LLONG_MAX) && (PTRDIFF_MAX == LLONG_MAX) +#define PDS 8 +#else +#error fix QUAL_CHARS ptrdiff_t entry 't'! +#endif + +#if SIZE_MAX == UINT_MAX +#define SS 0 +#elif SIZE_MAX == ULONG_MAX +#define SS 4 +#elif defined(LLONG_MAX) && (SIZE_MAX == ULLONG_MAX) +#define SS 8 +#else +#error fix QUAL_CHARS size_t entries 'z', 'Z'! +#endif + +#if INTMAX_MAX == INT_MAX +#define IMS 0 +#elif INTMAX_MAX == LONG_MAX +#define IMS 4 +#elif defined(LLONG_MAX) && (INTMAX_MAX == LLONG_MAX) +#define IMS 8 +#else +#error fix QUAL_CHARS intmax_t entry 'j'! +#endif + +#define QUAL_CHARS { \ + /* j:(u)intmax_t z:(s)size_t t:ptrdiff_t \0:int */ \ + /* q:long_long Z:(s)size_t */ \ + 'h', 'l', 'L', 'j', 'z', 't', 'q', 'Z', 0, \ + 2, 4, 8, IMS, SS, PDS, 8, SS, 0, /* TODO -- fix!!! */\ + 1, 8 \ +} + +static const char qual_chars[] = QUAL_CHARS; + +/* static const char qual[] = "hlLq"; */ +/**********************************************************************/ + +#if !defined(__UCLIBC_HAS_FLOATS__) && WANT_FLOAT_ERROR +static const char dbl_err[] = ""; +#endif + +#if defined(__UCLIBC_HAS_FLOATS__) || WANT_FLOAT_ERROR +/* layout 012345678901234567 */ +static const char u_spec[] = "%nbopxXudicsfgGeEaA"; +#else +/* layout 0123456789012 */ +static const char u_spec[] = "%nbopxXudics"; +#endif + +/* WARNING: u_spec and u_radix need to stay in agreement!!! */ +/* u_radix[i] <-> u_spec[i+2] for unsigned entries only */ +static const char u_radix[] = "\x02\x08\x10\x10\x10\x0a"; + +int vfprintf(FILE * __restrict op, register const char * __restrict fmt, + va_list ap) +{ + union { +#ifdef LLONG_MAX + long long ll; +#endif +#if LONG_MAX != INT_MAX + long l; +#endif + int i; + } intarg; + int i, cnt, dataargtype, len; + const void *argptr = argptr; /* ok to be initialized. */ + register char *p; + const char *fmt0; + int preci, width; +#define upcase i + int radix, dpoint /*, upcase*/; + char tmp[65]; /* TODO - determine needed size from headers */ + char flag[sizeof(spec)]; + __STDIO_AUTO_THREADLOCK_VAR; + + __STDIO_AUTO_THREADLOCK(op); + + __STDIO_STREAM_VALIDATE(op); + + cnt = 0; + + if (__STDIO_STREAM_IS_NARROW_WRITING(op) + || !__STDIO_STREAM_TRANS_TO_WRITE(op, __FLAG_NARROW) + ) { + + while (*fmt) { + if (*fmt == '%') { + fmt0 = fmt; /* save our position in case of bad format */ + ++fmt; + width = -1; /* min field width */ + preci = -5; /* max string width or mininum digits */ + radix = 10; /* number base */ + dpoint = 0; /* found decimal point */ + + /* init flags */ + for (p =(char *) spec ; *p ; p++) { + flag[p-spec] = '\0'; + } + flag[FLAG_0_PAD] = ' '; + + /* process optional flags */ + for (p = (char *)spec ; *p ; ) { + if (*fmt == *p) { + flag[p-spec] = *fmt++; + p = (char *)spec; /* restart scan */ + } else { + p++; + } + } + + if (!flag[FLAG_PLUS]) { + flag[FLAG_PLUS] = flag[FLAG_SPACE]; + } + + /* process optional width and precision */ + do { + if (*fmt == '.') { + ++fmt; + dpoint = 1; + } + if (*fmt == '*') { /* parameter width value */ + ++fmt; + i = va_arg(ap, int); + } else { + for ( i = 0 ; (*fmt >= '0') && (*fmt <= '9') ; ++fmt ) { + i = (i * 10) + (*fmt - '0'); + } + } + + if (dpoint) { + preci = i; + if (i<0) { + preci = -5; + } + } else { + width = i; + if (i<0) { + width = -i; + flag[FLAG_MINUS_LJUSTIFY] = 1; + } + } + } while ((*fmt == '.') && !dpoint ); + + /* process optional qualifier */ + p = (char *) qual_chars; + do { + if (*fmt == *p) { + ++fmt; + break; + } + } while (*++p); + if ((p - qual_chars < 2) && (*fmt == *p)) { + p += ((sizeof(qual_chars)-2) / 2); + ++fmt; + } + dataargtype = ((int)(p[(sizeof(qual_chars)-2) / 2])) << 8; + +#if WANT_GNU_ERRNO + if (*fmt == 'm') { + flag[FLAG_PLUS] = '\0'; + flag[FLAG_0_PAD] = ' '; + p = __glibc_strerror_r(errno, tmp, sizeof(tmp)); + goto print; + } +#endif + + /* process format specifier */ + for (p = (char *) u_spec ; *p ; p++) { + if (*fmt != *p) continue; + if (p-u_spec < 1) { /* print a % */ + goto charout; + } + if (p-u_spec < 2) { /* store output count in int ptr */ + _store_inttype(va_arg(ap, void *), + dataargtype, + (intmax_t) (cnt)); + goto nextfmt; + } + + if (p-u_spec < 10) { + if (*p == 'p') { +#if INTPTR_MAX == INT_MAX + dataargtype = 0; +#else +#error Fix dataargtype for pointers! +#endif + } + + switch(dataargtype) { + case (PA_INT|PA_FLAG_LONG_LONG): +#ifdef LLONG_MAX + intarg.ll = va_arg(ap, long long); + argptr = &intarg.ll; + break; +#endif + case (PA_INT|PA_FLAG_LONG): +#if LONG_MAX != INT_MAX + intarg.l = va_arg(ap, long); + argptr = &intarg.l; + break; +#endif + default: + intarg.i = va_arg(ap, int); + argptr = &intarg.i; + break; + } + } + + if (p-u_spec < 8) { /* unsigned conversion */ + radix = u_radix[p-u_spec-2]; + upcase = ((*p == 'x') ? __UIM_LOWER : __UIM_UPPER); + if (*p == 'p') { + upcase = __UIM_LOWER; + flag[FLAG_HASH] = 'p'; + } + p = _uintmaxtostr(tmp + sizeof(tmp) - 1, + (uintmax_t) + _load_inttype(dataargtype, argptr, radix), + radix, upcase); + + flag[FLAG_PLUS] = '\0'; /* meaningless for unsigned */ + if (*p != '0') { /* non-zero */ + if (flag[FLAG_HASH]) { + if (radix == 8) { + *--p = '0'; /* add leadding zero */ + } else if (radix != 10) { /* either 2 or 16 */ + flag[FLAG_PLUS] = '0'; + *--p = 'b'; + if (radix == 16) { + *p = 'x'; + if (*fmt == 'X') { + *p = 'X'; + } + } + } + } + } else if (flag[FLAG_HASH] == 'p') { /* null pointer */ + p = "(nil)"; + } + } else if (p-u_spec < 10) { /* signed conversion */ + p = _uintmaxtostr(tmp + sizeof(tmp) - 1, + (uintmax_t) + _load_inttype(dataargtype, argptr, -radix), + -radix, upcase); + + } else if (p-u_spec < 12) { /* character or string */ + flag[FLAG_PLUS] = '\0'; + flag[FLAG_0_PAD] = ' '; + if (*p == 'c') { /* character */ + p = tmp; + *p = va_arg(ap, int); + /* This takes care of the "%c",0 case */ + len = 1; + goto print_len_set; + } else { /* string */ + p = va_arg(ap, char *); + if (!p) { + p = "(null)"; + preci = 6; + } else { + if (preci < 0) { + preci = INT_MAX; + } + } + len = strnlen(p, preci); + goto print_len_set; + } +#if defined(__UCLIBC_HAS_FLOATS__) || WANT_FLOAT_ERROR + } else if (p-u_spec < 27) { /* floating point */ +#endif /* defined(__UCLIBC_HAS_FLOATS__) || WANT_FLOAT_ERROR */ +#if defined(__UCLIBC_HAS_FLOATS__) + struct printf_info info; + if (preci < 0) { + preci = 6; + } + info.width = width; + info.prec = preci; + info.spec = *fmt; + info.pad = flag[FLAG_0_PAD]; + info._flags = 0; + if (flag[FLAG_PLUS] == '+') { + PRINT_INFO_SET_FLAG(&info,showsign); + } else if (flag[FLAG_PLUS] == ' ') { + PRINT_INFO_SET_FLAG(&info,space); + } + if (flag[FLAG_HASH]) { + PRINT_INFO_SET_FLAG(&info,alt); + } + if (flag[FLAG_MINUS_LJUSTIFY]) { + PRINT_INFO_SET_FLAG(&info,left); + } +#if 1 + cnt += _fpmaxtostr(op, + (__fpmax_t) + ((dataargtype == (8 << 8)) + ? va_arg(ap, long double) + : (long double) va_arg(ap, double)), + &info, _fp_out_narrow); +#else + cnt += _fpmaxtostr(op, + (__fpmax_t) + ((lval > 1) + ? va_arg(ap, long double) + : (long double) va_arg(ap, double)), + &info, _fp_out_narrow); +#endif + goto nextfmt; +#elif WANT_FLOAT_ERROR + (void) ((lval > 1) ? va_arg(ap, long double) + : va_arg(ap, double)); /* carry on */ + p = (char *) dbl_err; +#endif /* defined(__UCLIBC_HAS_FLOATS__) */ + } + +#if WANT_GNU_ERRNO + print: +#endif + { /* this used to be printfield */ + /* cheaper than strlen call */ +/* for ( len = 0 ; p[len] ; len++ ) { } */ + len = strnlen(p, SIZE_MAX); + print_len_set: + if ((*p == '-') +#if WANT_GNU_ERRNO + && (*fmt != 'm') +#endif + && (*fmt != 's')) { + flag[FLAG_PLUS] = *p++; + --len; + } + if (flag[FLAG_PLUS]) { + ++len; + ++preci; + if (flag[FLAG_PLUS] == '0') { /* base 16 */ + ++preci; /* account for x or X */ + } + } + + if (preci >= 0) { + if ((*fmt == 's') +#if WANT_GNU_ERRNO + || (*fmt == 'm') +#endif + ) { + if (len > preci) { + len = preci; + } else { + preci = len; + } + } + preci -= len; + if (preci < 0) { + preci = 0; + } + width -= preci; + } + + width -= len; + if (width < 0) { + width = 0; + } + + if (preci < 0) { + preci = 0; + if (!flag[FLAG_MINUS_LJUSTIFY] + /* && flag[FLAG_PLUS] */ + && (flag[FLAG_0_PAD] == '0')) { + preci = width; + width = 0; + } + } + + while (width + len + preci) { + unsigned char ch; + /* right padding || left padding */ + if ((!len && !preci) + || (width && !flag[FLAG_MINUS_LJUSTIFY])) { + ch = ' '; + --width; + } else if (flag[FLAG_PLUS]) { + ch = flag[FLAG_PLUS]; /* sign */ + if (flag[FLAG_PLUS]=='0') { /* base 16 case */ + flag[FLAG_PLUS] = *p++; /* get the x|X */ + } else { + flag[FLAG_PLUS] = '\0'; + } + --len; + } else if (preci) { + ch = '0'; + --preci; + } else { + ch = *p++; /* main field */ + --len; + } + ++cnt; + PUTC(ch, op); + } + } + goto nextfmt; + } + + fmt = fmt0; /* this was an illegal format */ + } + + charout: + ++cnt; + PUTC(*fmt, op); /* normal char out */ + + nextfmt: + ++fmt; + } + + } + + i = (__FERROR_UNLOCKED(op)) ? -1 : cnt; + + __STDIO_STREAM_VALIDATE(op); + + __STDIO_AUTO_THREADUNLOCK(op); + + return i; +} +libc_hidden_def(vfprintf) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/open_memstream.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/open_memstream.c new file mode 100644 index 00000000..8b552c79 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/open_memstream.c @@ -0,0 +1,166 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include + +#ifdef __USE_GNU +#include "_stdio.h" + + +#ifndef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ +#error no custom streams! +#endif + +#define COOKIE ((__oms_cookie *) cookie) + +typedef struct { + char *buf; + size_t len; + size_t pos; + size_t eof; + char **bufloc; + size_t *sizeloc; +} __oms_cookie; + +/* Nothing to do here, as memstreams are write-only. */ +/* static ssize_t oms_read(void *cookie, char *buf, size_t bufsize) */ +/* { */ +/* } */ + +static ssize_t oms_write(register void *cookie, const char *buf, size_t bufsize) +{ + register char *newbuf; + size_t count; + + /* Note: we already know bufsize < SSIZE_MAX... */ + + count = COOKIE->len - COOKIE->pos - 1; + assert(COOKIE->pos < COOKIE->len); /* Always nul-terminate! */ + + if (bufsize > count) { + newbuf = realloc(COOKIE->buf, COOKIE->len + bufsize - count); + if (newbuf) { + *COOKIE->bufloc = COOKIE->buf = newbuf; + COOKIE->len += (bufsize - count); + } else { + bufsize = count; + if (count == 0) { + __set_errno(EFBIG); /* TODO: check glibc errno setting... */ + return -1; + } + } + } + + memcpy(COOKIE->buf + COOKIE->pos, buf, bufsize); + COOKIE->pos += bufsize; + + if (COOKIE->pos > COOKIE->eof) { + *COOKIE->sizeloc = COOKIE->eof = COOKIE->pos; + COOKIE->buf[COOKIE->eof] = 0; /* Need to nul-terminate. */ + } + + return bufsize; +} + +static int oms_seek(register void *cookie, __offmax_t *pos, int whence) +{ + __offmax_t p = *pos; + register char *buf; + size_t leastlen; + + /* Note: fseek already checks that whence is legal, so don't check here + * unless debugging. */ + assert(((unsigned int) whence) <= 2); + + if (whence != SEEK_SET) { + p += (whence == SEEK_CUR) ? COOKIE->pos : /* SEEK_END */ COOKIE->eof; + } + + /* Note: glibc only allows seeking in the buffer. We'll actually restrict + * to the data. */ + /* Check for offset < 0, offset >= too big (need nul), or overflow... */ + if (((uintmax_t) p) >= SIZE_MAX - 1) { + return -1; + } + + leastlen = ((size_t) p) + 1; /* New pos + 1 for nul if necessary. */ + + if (leastlen >= COOKIE->len) { /* Need to grow buffer... */ + buf = realloc(COOKIE->buf, leastlen); + if (buf) { + *COOKIE->bufloc = COOKIE->buf = buf; + COOKIE->len = leastlen; + memset(buf + COOKIE->eof, 0, leastlen - COOKIE->eof); /* 0-fill */ + } else { + /* TODO: check glibc errno setting... */ + return -1; + } + } + + *pos = COOKIE->pos = --leastlen; + + if (leastlen > COOKIE->eof) { + memset(COOKIE->buf + COOKIE->eof, 0, leastlen - COOKIE->eof); + *COOKIE->sizeloc = COOKIE->eof; + } + + return 0; +} + +static int oms_close(void *cookie) +{ + free(cookie); + return 0; +} + +#undef COOKIE + +static const cookie_io_functions_t _oms_io_funcs = { + NULL, oms_write, oms_seek, oms_close +}; + +/* TODO: If we have buffers enabled, it might be worthwile to add a pointer + * to the FILE in the cookie and operate directly on the buffer itself + * (ie replace the FILE buffer with the cookie buffer and update FILE bufstart, + * etc. whenever we seek). */ + +FILE *open_memstream(char **__restrict bufloc, size_t *__restrict sizeloc) +{ + register __oms_cookie *cookie; + register FILE *fp; + + if ((cookie = malloc(sizeof(__oms_cookie))) != NULL) { + if ((cookie->buf = malloc(cookie->len = BUFSIZ)) == NULL) { + goto EXIT_cookie; + } + *cookie->buf = 0; /* Set nul terminator for buffer. */ + *(cookie->bufloc = bufloc) = cookie->buf; + *(cookie->sizeloc = sizeloc) = cookie->eof = cookie->pos = 0; + +#ifndef __BCC__ + fp = fopencookie(cookie, "w", _oms_io_funcs); +#else + fp = fopencookie(cookie, "w", &_oms_io_funcs); +#endif + /* Note: We don't need to worry about locking fp in the thread case + * as the only possible access would be a close or flush with + * nothing currently in the FILE's write buffer. */ + + if (fp != NULL) { + __STDIO_STREAM_VALIDATE(fp); + return fp; + } + } + + free(cookie->buf); + EXIT_cookie: + free(cookie); + + return NULL; +} +libc_hidden_def(open_memstream) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/parse_printf_format.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/parse_printf_format.c new file mode 100644 index 00000000..38266b3d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/parse_printf_format.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define L_parse_printf_format +#include "_vfprintf.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/perror.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/perror.c new file mode 100644 index 00000000..8b943e46 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/perror.c @@ -0,0 +1,38 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning CONSIDER: Increase buffer size for error message (non-%m case)? +#endif + +void perror(register const char *s) +{ + /* If the program is calling perror, it's a safe bet that printf and + * friends are used as well. It is also possible that the calling + * program could buffer stderr, or reassign it. */ + + register const char *sep; + + sep = ": "; + if (!(s && *s)) { /* Caller did not supply a prefix message */ + s = (sep += 2); /* or passed an empty string. */ + } + +#ifdef __UCLIBC_HAS_PRINTF_M_SPEC__ + fprintf(stderr, "%s%s%m\n", s, sep); /* Use the gnu %m feature. */ +#else + { + char buf[64]; + fprintf(stderr, "%s%s%s\n", s, sep, + __glibc_strerror_r(errno, buf, sizeof(buf))); + } +#endif +} +libc_hidden_def(perror) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/popen.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/popen.c new file mode 100644 index 00000000..d5c60cf2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/popen.c @@ -0,0 +1,186 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +/* Jan 1, 2004 + * + * Rewrite popen for SUSv3 compliance. + * Added a list of popen()'d to store pids and use waitpid() in pclose(). + * Loop on waitpid() failure due to EINTR as required. + * Close parent's popen()'d FILEs in the {v}fork()'d child. + * Fix failure exit code for failed execve(). + */ + +#include +#include +#include +#include +#include +#include + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning "hmm... susv3 says Pipe streams are byte-oriented." +#endif /* __UCLIBC_MJN3_ONLY__ */ + + +/* uClinux-2.0 has vfork, but Linux 2.0 doesn't */ +#include +#if ! defined __NR_vfork +# define vfork fork +# define VFORK_LOCK ((void) 0) +# define VFORK_UNLOCK ((void) 0) +#endif + +#ifndef VFORK_LOCK +__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_MUTEX_INITIALIZER); +# define VFORK_LOCK __UCLIBC_MUTEX_LOCK(mylock) +# define VFORK_UNLOCK __UCLIBC_MUTEX_UNLOCK(mylock) +#endif + +struct popen_list_item { + struct popen_list_item *next; + FILE *f; + pid_t pid; +}; + +static struct popen_list_item *popen_list /* = NULL (bss initialized) */; + +FILE *popen(const char *command, const char *modes) +{ + FILE *fp; + struct popen_list_item *pi; + struct popen_list_item *po; + int pipe_fd[2]; + int parent_fd; + int child_fd; + int child_writing; /* Doubles as the desired child fildes. */ + pid_t pid; + + child_writing = 0; /* Assume child is writing. */ + if (modes[0] != 'w') { /* Parent not writing... */ + ++child_writing; /* so child must be writing. */ + if (modes[0] != 'r') { /* Oops! Parent not reading either! */ + __set_errno(EINVAL); + goto RET_NULL; + } + } + + if (!(pi = malloc(sizeof(struct popen_list_item)))) { + goto RET_NULL; + } + + if (pipe(pipe_fd)) { + goto FREE_PI; + } + + child_fd = pipe_fd[child_writing]; + parent_fd = pipe_fd[1-child_writing]; + + if (!(fp = fdopen(parent_fd, modes))) { + close(parent_fd); + close(child_fd); + goto FREE_PI; + } + + VFORK_LOCK; + if ((pid = vfork()) == 0) { /* Child of vfork... */ + close(parent_fd); + if (child_fd != child_writing) { + dup2(child_fd, child_writing); + close(child_fd); + } + + /* SUSv3 requires that any previously popen()'d streams in the + * parent shall be closed in the child. */ + for (po = popen_list ; po ; po = po->next) { + close(po->f->__filedes); + } + + execl("/bin/sh", "sh", "-c", command, (char *)0); + + /* SUSv3 mandates an exit code of 127 for the child if the + * command interpreter can not be invoked. */ + _exit(127); + } + VFORK_UNLOCK; + + /* We need to close the child filedes whether vfork failed or + * it succeeded and we're in the parent. */ + close(child_fd); + + if (pid > 0) { /* Parent of vfork... */ + pi->pid = pid; + pi->f = fp; + VFORK_LOCK; + pi->next = popen_list; + popen_list = pi; + VFORK_UNLOCK; + + return fp; + } + + /* If we get here, vfork failed. */ + fclose(fp); /* Will close parent_fd. */ + + FREE_PI: + free(pi); + + RET_NULL: + return NULL; +} + +#warning is pclose correct wrt the new mutex semantics? + +int pclose(FILE *stream) +{ + struct popen_list_item *p; + int stat; + pid_t pid; + + /* First, find the list entry corresponding to stream and remove it + * from the list. Set p to the list item (NULL if not found). */ + VFORK_LOCK; + if ((p = popen_list) != NULL) { + if (p->f == stream) { + popen_list = p->next; + } else { + struct popen_list_item *t; + do { + t = p; + if (!(p = t->next)) { + __set_errno(EINVAL); /* Not required by SUSv3. */ + break; + } + if (p->f == stream) { + t->next = p->next; + break; + } + } while (1); + } + } + VFORK_UNLOCK; + + if (p) { + pid = p->pid; /* Save the pid we need */ + free(p); /* and free the list item. */ + + fclose(stream); /* The SUSv3 example code ignores the return. */ + + /* SUSv3 specificly requires that pclose not return before the child + * terminates, in order to disallow pclose from returning on EINTR. */ + do { + if (waitpid(pid, &stat, 0) >= 0) { + return stat; + } + if (errno != EINTR) { + break; + } + } while (1); + } + + return -1; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/printf.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/printf.c new file mode 100644 index 00000000..8cd3db9f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/printf.c @@ -0,0 +1,23 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" +#include + + +int printf(const char * __restrict format, ...) +{ + va_list arg; + int rv; + + va_start(arg, format); + rv = vfprintf(stdout, format, arg); + va_end(arg); + + return rv; +} +libc_hidden_def(printf) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/putchar.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/putchar.c new file mode 100644 index 00000000..583e90f4 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/putchar.c @@ -0,0 +1,43 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + + +#undef putchar +#ifdef __DO_UNLOCKED + +#undef putchar_unlocked +int putchar_unlocked(int c) +{ + register FILE *stream = stdout; + + return __PUTC_UNLOCKED_MACRO(c, stream); +} + +#ifndef __UCLIBC_HAS_THREADS__ +strong_alias(putchar_unlocked,putchar) +#endif + +#elif defined __UCLIBC_HAS_THREADS__ + +int putchar(int c) +{ + register FILE *stream = stdout; + + if (stream->__user_locking != 0) { + return __PUTC_UNLOCKED_MACRO(c, stream); + } else { + int retval; + __STDIO_ALWAYS_THREADLOCK(stream); + retval = __PUTC_UNLOCKED_MACRO(c, stream); + __STDIO_ALWAYS_THREADUNLOCK(stream); + return retval; + } +} + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/putchar_unlocked.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/putchar_unlocked.c new file mode 100644 index 00000000..6d6ec471 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/putchar_unlocked.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define __DO_UNLOCKED +#include "putchar.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/puts.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/puts.c new file mode 100644 index 00000000..67775ff7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/puts.c @@ -0,0 +1,34 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + + +int puts(register const char * __restrict s) +{ + register FILE *stream = stdout; /* This helps bcc optimize. */ + int n; + __STDIO_AUTO_THREADLOCK_VAR; + + __STDIO_AUTO_THREADLOCK(stream); + + /* Note: Don't try to optimize by switching to FBF until the newline. + * If the string itself contained a newline a write error occurred, + * then we could have a newline in the buffer of an LBF stream. */ + + /* Note: Nonportable as fputs need only return nonnegative on success. */ + if ((n = fputs_unlocked(s, stream)) != EOF) { + ++n; + if (__fputc_unlocked('\n', stream) == EOF) { + n = EOF; + } + } + + __STDIO_AUTO_THREADUNLOCK(stream); + + return n; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/putw.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/putw.c new file mode 100644 index 00000000..ffdb1147 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/putw.c @@ -0,0 +1,29 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + + +/* SUSv2 Legacy function -- need not be reentrant. */ + +int putw(int w, FILE *stream) +{ +#define PW &w + /* If w is passed in a register, enable the following. */ +#if 0 +#undef PW + int PW[1]; + PW[0] = w; +#endif + +#if EOF == -1 + return fwrite_unlocked((void *) PW, sizeof(int), 1, stream) - 1; +#else + return (fwrite_unlocked((void *) PW, sizeof(int), 1, stream) != 0) + ? 0 : EOF; +#endif +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/putwchar.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/putwchar.c new file mode 100644 index 00000000..3fadb61d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/putwchar.c @@ -0,0 +1,31 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +#ifdef __DO_UNLOCKED + + +wint_t putwchar_unlocked(wchar_t wc) +{ + return fputwc_unlocked(wc, stdout); +} + +#ifndef __UCLIBC_HAS_THREADS__ +strong_alias(putwchar_unlocked,putwchar) +#endif + +#elif defined __UCLIBC_HAS_THREADS__ + +/* psm: should this be fputwc? */ + +wint_t putwchar(wchar_t wc) +{ + return fputc(wc, stdout); +} + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/putwchar_unlocked.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/putwchar_unlocked.c new file mode 100644 index 00000000..5b0c6000 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/putwchar_unlocked.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define __DO_UNLOCKED +#include "putwchar.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/register_printf_function.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/register_printf_function.c new file mode 100644 index 00000000..c6b3240a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/register_printf_function.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define L_register_printf_function +#include "_vfprintf.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/remove.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/remove.c new file mode 100644 index 00000000..af285073 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/remove.c @@ -0,0 +1,31 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +#include +#include + +/* SUSv3 states: + * If path does not name a directory, remove(path) shall be equivalent + * to unlink(path). If path names a directory, remove(path) shall be + * equivalent to rmdir(path). + */ + +int remove(register const char *filename) +{ + int saved_errno = errno; + int rv; + + rv = rmdir(filename); + if ((rv < 0) && (errno == ENOTDIR)) { + __set_errno(saved_errno); /* Need to restore errno. */ + rv = unlink(filename); + } + return rv; +} +libc_hidden_def(remove) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/rewind.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/rewind.c new file mode 100644 index 00000000..1b170443 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/rewind.c @@ -0,0 +1,22 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + + +void rewind(register FILE *stream) +{ + __STDIO_AUTO_THREADLOCK_VAR; + + __STDIO_AUTO_THREADLOCK(stream); + + __STDIO_STREAM_CLEAR_ERROR(stream); /* Clear the error indicator */ + fseek(stream, 0L, SEEK_SET); /* first since fseek could set it. */ + + __STDIO_AUTO_THREADUNLOCK(stream); +} +libc_hidden_def(rewind) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/scanf.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/scanf.c new file mode 100644 index 00000000..4943c88d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/scanf.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define L_scanf +#include "_scanf.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/setbuf.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/setbuf.c new file mode 100644 index 00000000..e6080a52 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/setbuf.c @@ -0,0 +1,16 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + + +void setbuf(FILE * __restrict stream, register char * __restrict buf) +{ +#ifdef __STDIO_BUFFERS + setvbuf(stream, buf, ((buf != NULL) ? _IOFBF : _IONBF), BUFSIZ); +#endif +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/setbuffer.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/setbuffer.c new file mode 100644 index 00000000..b566bfc3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/setbuffer.c @@ -0,0 +1,25 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +#ifdef __USE_BSD + + +/* A BSD function. The implementation matches the linux man page, + * except that we do not bother calling setvbuf if not configured + * for stream buffering. + */ + +void setbuffer(FILE * __restrict stream, register char * __restrict buf, + size_t size) +{ +#ifdef __STDIO_BUFFERS + setvbuf(stream, buf, (buf ? _IOFBF : _IONBF), size); +#endif +} +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/setlinebuf.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/setlinebuf.c new file mode 100644 index 00000000..93233888 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/setlinebuf.c @@ -0,0 +1,24 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +#ifdef __USE_BSD + + +/* A BSD function. The implementation matches the linux man page, + * except that we do not bother calling setvbuf if not configured + * for stream buffering. + */ + +void setlinebuf(FILE * __restrict stream) +{ +#ifdef __STDIO_BUFFERS + setvbuf(stream, NULL, _IOLBF, (size_t) 0); +#endif +} +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/setvbuf.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/setvbuf.c new file mode 100644 index 00000000..0b0ea0dd --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/setvbuf.c @@ -0,0 +1,107 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +#if (_IOFBF != 0) || (_IOLBF != 1) || (_IONBF != 2) +#error Assumption violated -- values of _IOFBF, _IOLBF, _IONBF +#endif +#if (__FLAG_FBF != 0) || (__FLAG_NBF != (2*__FLAG_LBF)) +#error Assumption violated for buffering mode flags +#endif + +int setvbuf(register FILE * __restrict stream, register char * __restrict buf, + int mode, size_t size) +{ +#ifdef __STDIO_BUFFERS + + int retval = EOF; + int alloc_flag = 0; + __STDIO_AUTO_THREADLOCK_VAR; + + __STDIO_AUTO_THREADLOCK(stream); + __STDIO_STREAM_VALIDATE(stream); + + if (((unsigned int) mode) > 2) { + __set_errno(EINVAL); + goto ERROR; + } + + /* C99 states that setvbuf may only be used between a successful + * open of the stream and before any other operation other than + * an unsuccessful call to setvbuf. */ + +#ifdef __STDIO_FLEXIBLE_SETVBUF + /* If we aren't currently reading (including ungots) or writing, + * then allow the request to proceed. */ + + if (stream->__modeflags & (__MASK_READING|__FLAG_WRITING)) { + goto ERROR; + } +#else + /* The following test isn't quite as strict as C99, as it will + * not detect file positioning operations. */ + + if (stream->__modeflags & (__MASK_READING|__FLAG_WRITING + |__FLAG_NARROW|__FLAG_WIDE + |__FLAG_ERROR|__FLAG_EOF) + ) { + goto ERROR; + } +#endif + + stream->__modeflags &= ~(__MASK_BUFMODE); /* Clear current mode */ + stream->__modeflags |= mode * __FLAG_LBF; /* and set new one. */ + + if ((mode == _IONBF) || !size) { + size = 0; + buf = NULL; + } else if (!buf) { + if ((__STDIO_STREAM_BUFFER_SIZE(stream) == size) /* Same size or */ + || !(buf = malloc(size)) /* malloc failed, so don't change. */ + ) { + goto DONE; + } + alloc_flag = __FLAG_FREEBUF; + } + + if (stream->__modeflags & __FLAG_FREEBUF) { + stream->__modeflags &= ~(__FLAG_FREEBUF); + free(stream->__bufstart); + } + + stream->__modeflags |= alloc_flag; + stream->__bufstart = (unsigned char *) buf; + stream->__bufend = (unsigned char *) buf + size; + __STDIO_STREAM_INIT_BUFREAD_BUFPOS(stream); + __STDIO_STREAM_DISABLE_GETC(stream); + __STDIO_STREAM_DISABLE_PUTC(stream); + + DONE: + retval = 0; + + ERROR: + __STDIO_STREAM_VALIDATE(stream); + __STDIO_AUTO_THREADUNLOCK(stream); + + return retval; + +#else /* __STDIO_BUFFERS */ + + if (mode == _IONBF) { + return 0; + } + + if (((unsigned int) mode) > 2) { + __set_errno(EINVAL); + } + + return EOF; + +#endif +} +libc_hidden_def(setvbuf) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/snprintf.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/snprintf.c new file mode 100644 index 00000000..e0902ac7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/snprintf.c @@ -0,0 +1,29 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" +#include + +#ifndef __STDIO_HAS_VSNPRINTF +#warning Skipping snprintf since no vsnprintf! +#else + + +int snprintf(char *__restrict buf, size_t size, + const char * __restrict format, ...) +{ + va_list arg; + int rv; + + va_start(arg, format); + rv = vsnprintf(buf, size, format, arg); + va_end(arg); + return rv; +} +libc_hidden_def(snprintf) + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/sprintf.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/sprintf.c new file mode 100644 index 00000000..44304b5d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/sprintf.c @@ -0,0 +1,29 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" +#include + +#ifndef __STDIO_HAS_VSNPRINTF +#warning Skipping sprintf since no vsnprintf! +#else + + +int sprintf(char *__restrict buf, const char * __restrict format, ...) +{ + va_list arg; + int rv; + + va_start(arg, format); + rv = vsnprintf(buf, SIZE_MAX, format, arg); + va_end(arg); + + return rv; +} +libc_hidden_def(sprintf) + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/sscanf.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/sscanf.c new file mode 100644 index 00000000..f53c0654 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/sscanf.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define L_sscanf +#include "_scanf.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/swprintf.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/swprintf.c new file mode 100644 index 00000000..8e037d20 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/swprintf.c @@ -0,0 +1,30 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" +#include +#include + + +#ifndef __STDIO_BUFFERS +#warning Skipping swprintf since no buffering! +#else /* __STDIO_BUFFERS */ + +int swprintf(wchar_t *__restrict buf, size_t size, + const wchar_t * __restrict format, ...) +{ + va_list arg; + int rv; + + va_start(arg, format); + rv = vswprintf(buf, size, format, arg); + va_end(arg); + + return rv; +} + +#endif /* __STDIO_BUFFERS */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/swscanf.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/swscanf.c new file mode 100644 index 00000000..06f8cb75 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/swscanf.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define L_swscanf +#include "_scanf.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/tempnam.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/tempnam.c new file mode 100644 index 00000000..66c905db --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/tempnam.c @@ -0,0 +1,44 @@ +/* Copyright (C) 1991,1993,1996-1999,2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include "../misc/internals/tempname.h" + + +/* Generate a unique temporary filename using up to five characters of PFX + if it is not NULL. The directory to put this file in is searched for + as follows: First the environment variable "TMPDIR" is checked. + If it contains the name of a writable directory, that directory is used. + If not and if DIR is not NULL, that value is checked. If that fails, + P_tmpdir is tried and finally "/tmp". The storage for the filename + is allocated by `malloc'. */ +char * +tempnam (const char *dir, const char *pfx) +{ + char buf[FILENAME_MAX]; + + if (__path_search (buf, FILENAME_MAX, dir, pfx, 1)) + return NULL; + + if (__gen_tempname (buf, __GT_NOCREATE, 0)) + return NULL; + + return strdup (buf); +} + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/tmpfile.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/tmpfile.c new file mode 100644 index 00000000..c6b2dc8a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/tmpfile.c @@ -0,0 +1,54 @@ +/* Copyright (C) 1991, 1993, 1996, 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include +#include "../misc/internals/tempname.h" +#include + + +/* This returns a new stream opened on a temporary file (generated + by tmpnam). The file is opened with mode "w+b" (binary read/write). + If we couldn't generate a unique filename or the file couldn't + be opened, NULL is returned. */ +FILE * tmpfile (void) +{ + char buf[FILENAME_MAX]; + int fd; + FILE *f; + + if (__path_search (buf, FILENAME_MAX, NULL, "tmpf", 0)) + return NULL; + fd = __gen_tempname (buf, __GT_FILE, S_IRUSR | S_IWUSR); + if (fd < 0) + return NULL; + + /* Note that this relies on the Unix semantics that + a file is not really removed until it is closed. */ + (void) remove (buf); + + if ((f = fdopen (fd, "w+b")) == NULL) + close_not_cancel (fd); + + return f; +} +#ifdef __UCLIBC_HAS_LFS__ +strong_alias(tmpfile,tmpfile64) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/tmpnam.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/tmpnam.c new file mode 100644 index 00000000..323105ba --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/tmpnam.c @@ -0,0 +1,54 @@ +/* Copyright (C) 1991,1993,1996-1999,2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include "../misc/internals/tempname.h" + + +static char tmpnam_buffer[L_tmpnam]; + +/* Generate a unique filename in P_tmpdir. + + This function is *not* thread safe! */ +char * +tmpnam (char *s) +{ + /* By using two buffers we manage to be thread safe in the case + where S != NULL. */ + char tmpbufmem[L_tmpnam]; + char *tmpbuf = s ?: tmpbufmem; + + /* In the following call we use the buffer pointed to by S if + non-NULL although we don't know the size. But we limit the size + to L_tmpnam characters in any case. */ + if (__builtin_expect (__path_search (tmpbuf, L_tmpnam, NULL, NULL, 0), + 0)) + return NULL; + + if (__builtin_expect (__gen_tempname (tmpbuf, __GT_NOCREATE, 0), 0)) + return NULL; + + if (s == NULL) + return (char *) memcpy (tmpnam_buffer, tmpbuf, L_tmpnam); + + return s; +} + +link_warning (tmpnam, + "the use of `tmpnam' is dangerous, better use `mkstemp'") diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/tmpnam_r.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/tmpnam_r.c new file mode 100644 index 00000000..8f616b27 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/tmpnam_r.c @@ -0,0 +1,35 @@ +/* Copyright (C) 1991, 1993, 1996, 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include "../misc/internals/tempname.h" + +/* Generate a unique filename in P_tmpdir. If S is NULL return NULL. + This makes this function thread safe. */ +char * tmpnam_r (char *s) +{ + if (s == NULL) + return NULL; + + if (__path_search (s, L_tmpnam, NULL, NULL, 0)) + return NULL; + if (__gen_tempname (s, __GT_NOCREATE, 0)) + return NULL; + + return s; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/ungetc.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/ungetc.c new file mode 100644 index 00000000..ea4edd22 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/ungetc.c @@ -0,0 +1,78 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +/* Having ungotten characters implies the stream is reading. + * The scheme used here treats the least significant 2 bits of + * the stream's modeflags member as follows: + * 0 0 Not currently reading. + * 0 1 Reading, but no ungetc() or scanf() push back chars. + * 1 0 Reading with one ungetc() char (ungot[1] is 1) + * or one scanf() pushed back char (ungot[1] is 0). + * 1 1 Reading with both an ungetc() char and a scanf() + * pushed back char. Note that this must be the result + * of a scanf() push back (in ungot[0]) _followed_ by + * an ungetc() call (in ungot[1]). + * + * Notes: + * scanf() can NOT use ungetc() to push back characters. + * (See section 7.19.6.2 of the C9X rationale -- WG14/N897.) + */ + +int ungetc(int c, register FILE *stream) +{ + __STDIO_AUTO_THREADLOCK_VAR; + + __STDIO_AUTO_THREADLOCK(stream); + __STDIO_STREAM_VALIDATE(stream); + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning CONSIDER: Make fast ungetc an option? +#endif +#ifdef __UCLIBC_HAS_STDIO_GETC_MACRO__ + /* If buffered narrow reading with no ungot slots filled, and if not + * ungetting a different char than the one last read from the buffer, + * we can simply decrement the position and not worry about disabling + * the getc macros. This will cut down on overhead in applications + * that use getc/ungetc extensively (like gcc). */ + /* NOTE: If we can use getc, then we are buffered narrow reading with + * no ungot slots filled. */ + if (__STDIO_STREAM_CAN_USE_BUFFER_GET(stream) + && (c != EOF) + && (stream->__bufpos > stream->__bufstart) + && (stream->__bufpos[-1] == ((unsigned char)c)) + ) { + --stream->__bufpos; + __STDIO_STREAM_CLEAR_EOF(stream); /* Must clear end-of-file flag. */ + } else +#endif + /* Note: Even if c == EOF, we need to initialize/verify the + * stream's orientation and ensure the stream is in reading + * mode (if readable and properly oriented). */ + if ((!__STDIO_STREAM_IS_NARROW_READING(stream) + && __STDIO_STREAM_TRANS_TO_READ(stream, __FLAG_NARROW)) + || ((stream->__modeflags & __FLAG_UNGOT) + && ((stream->__modeflags & 1) || stream->__ungot[1])) + ) { + c = EOF; + } else if (c != EOF) { + __STDIO_STREAM_DISABLE_GETC(stream); + + /* Flag this as a user ungot, as scanf does the necessary fixup. */ + stream->__ungot[1] = 1; + stream->__ungot[(++stream->__modeflags) & 1] = c; + + __STDIO_STREAM_CLEAR_EOF(stream); /* Must clear end-of-file flag. */ + } + + __STDIO_STREAM_VALIDATE(stream); + __STDIO_AUTO_THREADUNLOCK(stream); + + return c; +} +libc_hidden_def(ungetc) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/ungetwc.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/ungetwc.c new file mode 100644 index 00000000..25b12b88 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/ungetwc.c @@ -0,0 +1,49 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" + +/* Note: This is the application-callable ungetwc. If wscanf calls this, it + * should also set stream->__ungot[1] to 0 if this is the only ungot, as well + * as reset stream->__ungot_width[1] for use by _stdio_adjpos(). + */ + +wint_t ungetwc(wint_t c, register FILE *stream) +{ + __STDIO_AUTO_THREADLOCK_VAR; + + __STDIO_AUTO_THREADLOCK(stream); + __STDIO_STREAM_VALIDATE(stream); /* debugging only */ + + /* Note: Even if c == WEOF, we need to initialize/verify the + * stream's orientation and ensure the stream is in reading + * mode (if readable and properly oriented). */ + if ((!__STDIO_STREAM_IS_WIDE_READING(stream) + && __STDIO_STREAM_TRANS_TO_READ(stream, __FLAG_WIDE)) + || ((stream->__modeflags & __FLAG_UNGOT) + && ((stream->__modeflags & 1) || stream->__ungot[1])) + || (c == WEOF) + ) { + c = WEOF; + } else { + /* In the wide case, getc macros should already be disabled. */ + /* __STDIO_STREAM_DISABLE_GETC(stream); */ + + /* Flag this as a user ungot, as scanf does the necessary fixup. */ + stream->__ungot[1] = 1; + stream->__ungot[(++stream->__modeflags) & 1] = c; + /* Note: ungot_width is handled by fgetwc. */ + + __STDIO_STREAM_CLEAR_EOF(stream); /* Must clear end-of-file flag. */ + } + + __STDIO_STREAM_VALIDATE(stream); + __STDIO_AUTO_THREADUNLOCK(stream); + + return c; +} +libc_hidden_def(ungetwc) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/vasprintf.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/vasprintf.c new file mode 100644 index 00000000..a901ee81 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/vasprintf.c @@ -0,0 +1,82 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include + +#ifdef __USE_GNU +#include "_stdio.h" +#include +#include + + +#ifdef __UCLIBC_MJN3_ONLY__ +/* Do the memstream stuff inline to avoid fclose and the openlist? */ +#warning CONSIDER: avoid open_memstream call? +#endif + +#ifndef __STDIO_HAS_VSNPRINTF +#warning Skipping vasprintf since no vsnprintf! +#else + +int vasprintf(char **__restrict buf, const char * __restrict format, + va_list arg) +{ +#ifdef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ + + FILE *f; + size_t size; + int rv = -1; + + *buf = NULL; + + if ((f = open_memstream(buf, &size)) != NULL) { + rv = vfprintf(f, format, arg); + fclose(f); + if (rv < 0) { + free(*buf); + *buf = NULL; + } + } + + assert(rv >= -1); + + return rv; + +#else /* __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ */ + + /* This implementation actually calls the printf machinery twice, but + * only does one malloc. This can be a problem though when custom printf + * specs or the %m specifier are involved because the results of the + * second call might be different from the first. */ + va_list arg2; + int rv; + + va_copy(arg2, arg); + rv = vsnprintf(NULL, 0, format, arg2); + va_end(arg2); + + *buf = NULL; + + if (rv >= 0) { + if ((*buf = malloc(++rv)) != NULL) { + if ((rv = vsnprintf(*buf, rv, format, arg)) < 0) { + free(*buf); + *buf = NULL; + } + } + } + + assert(rv >= -1); + + return rv; + +#endif /* __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ */ +} +libc_hidden_def(vasprintf) + +#endif +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/vdprintf.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/vdprintf.c new file mode 100644 index 00000000..457018bc --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/vdprintf.c @@ -0,0 +1,74 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include + +#ifdef __USE_GNU +#include "_stdio.h" +#include + + +int vdprintf(int filedes, const char * __restrict format, va_list arg) +{ + FILE f; + int rv; +#ifdef __STDIO_BUFFERS + char buf[64]; /* TODO: provide _optional_ buffering? */ + + f.__bufend = (unsigned char *) buf + sizeof(buf); + f.__bufstart = (unsigned char *) buf; + __STDIO_STREAM_DISABLE_GETC(&f); + __STDIO_STREAM_DISABLE_PUTC(&f); + __STDIO_STREAM_INIT_BUFREAD_BUFPOS(&f); +#endif + +/* __STDIO_STREAM_RESET_GCS(&f); */ +#ifdef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ + f.__cookie = &(f.__filedes); + f.__gcs.read = NULL; + f.__gcs.write = _cs_write; + f.__gcs.seek = NULL; + f.__gcs.close = NULL; +#endif + + f.__filedes = filedes; + f.__modeflags = (__FLAG_NARROW|__FLAG_WRITEONLY|__FLAG_WRITING); + +#ifdef __UCLIBC_HAS_WCHAR__ + f.__ungot_width[0] = 0; +#endif +#ifdef __STDIO_MBSTATE + __INIT_MBSTATE(&(f.__state)); +#endif + +/* _vfprintf_internal doesn't do any locking, locking init is here + * only because of fflush_unlocked. TODO? */ +#if (defined(__STDIO_BUFFERS) || defined(__USE_OLD_VFPRINTF__)) && defined(__UCLIBC_HAS_THREADS__) + f.__user_locking = 1; /* Set user locking. */ + STDIO_INIT_MUTEX(f.__lock); +#endif + f.__nextopen = NULL; + +#ifdef __USE_OLD_VFPRINTF__ + rv = vfprintf(&f, format, arg); +#else + rv = _vfprintf_internal(&f, format, arg); +#endif + +#ifdef __STDIO_BUFFERS + /* If not buffering, then fflush is unnecessary. */ + if ((rv > 0) && fflush_unlocked(&f)) { + rv = -1; + } +#endif + + assert(rv >= -1); + + return rv; +} +libc_hidden_def(vdprintf) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/vfprintf.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/vfprintf.c new file mode 100644 index 00000000..78b725fd --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/vfprintf.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define L_vfprintf +#include "_vfprintf.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/vfscanf.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/vfscanf.c new file mode 100644 index 00000000..b13ff8db --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/vfscanf.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define L_vfscanf +#include "_scanf.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/vfwprintf.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/vfwprintf.c new file mode 100644 index 00000000..323b9001 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/vfwprintf.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define L_vfwprintf +#include "_vfprintf.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/vfwscanf.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/vfwscanf.c new file mode 100644 index 00000000..ac982b4f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/vfwscanf.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define L_vfwscanf +#include "_scanf.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/vprintf.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/vprintf.c new file mode 100644 index 00000000..853f340c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/vprintf.c @@ -0,0 +1,15 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" +#include + + +int vprintf(const char * __restrict format, va_list arg) +{ + return vfprintf(stdout, format, arg); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/vscanf.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/vscanf.c new file mode 100644 index 00000000..834fe92e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/vscanf.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define L_vscanf +#include "_scanf.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/vsnprintf.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/vsnprintf.c new file mode 100644 index 00000000..31adc52b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/vsnprintf.c @@ -0,0 +1,216 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" +#include + + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning WISHLIST: Implement vsnprintf for non-buffered and no custom stream case. +#endif /* __UCLIBC_MJN3_ONLY__ */ + +#ifdef __STDIO_BUFFERS +/* NB: we can still have __USE_OLD_VFPRINTF__ defined in this case! */ + +int vsnprintf(char *__restrict buf, size_t size, + const char * __restrict format, va_list arg) +{ + FILE f; + int rv; + +/* __STDIO_STREAM_RESET_GCS(&f); */ +#ifdef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ + f.__cookie = &(f.__filedes); + f.__gcs.read = NULL; + f.__gcs.write = NULL; + f.__gcs.seek = NULL; + f.__gcs.close = NULL; +#endif + + f.__filedes = __STDIO_STREAM_FAKE_VSNPRINTF_FILEDES; + f.__modeflags = (__FLAG_NARROW|__FLAG_WRITEONLY|__FLAG_WRITING); + +#ifdef __UCLIBC_HAS_WCHAR__ + f.__ungot_width[0] = 0; +#endif /* __UCLIBC_HAS_WCHAR__ */ +#ifdef __STDIO_MBSTATE + __INIT_MBSTATE(&(f.__state)); +#endif /* __STDIO_MBSTATE */ + +#if (defined(__STDIO_BUFFERS) || defined(__USE_OLD_VFPRINTF__)) && defined(__UCLIBC_HAS_THREADS__) + f.__user_locking = 1; /* Set user locking. */ + STDIO_INIT_MUTEX(f.__lock); +#endif + f.__nextopen = NULL; + + if (size > SIZE_MAX - (size_t) buf) { + size = SIZE_MAX - (size_t) buf; + } + +/* TODO: this comment seems to be wrong */ + /* Set these last since __bufputc initialization depends on + * __user_locking and only gets set if user locking is on. */ + f.__bufstart = (unsigned char *) buf; + f.__bufend = (unsigned char *) buf + size; + __STDIO_STREAM_INIT_BUFREAD_BUFPOS(&f); + __STDIO_STREAM_DISABLE_GETC(&f); + __STDIO_STREAM_ENABLE_PUTC(&f); + +#ifdef __USE_OLD_VFPRINTF__ + rv = vfprintf(&f, format, arg); +#else + rv = _vfprintf_internal(&f, format, arg); +#endif + if (size) { + if (f.__bufpos == f.__bufend) { + --f.__bufpos; + } + *f.__bufpos = 0; + } + return rv; +} +libc_hidden_def(vsnprintf) + +#elif defined(__USE_OLD_VFPRINTF__) + +typedef struct { + FILE f; + unsigned char *bufend; /* pointer to 1 past end of buffer */ + unsigned char *bufpos; +} __FILE_vsnprintf; + +int vsnprintf(char *__restrict buf, size_t size, + const char * __restrict format, va_list arg) +{ + __FILE_vsnprintf f; + int rv; + + f.bufpos = buf; + + if (size > SIZE_MAX - (size_t) buf) { + size = SIZE_MAX - (size_t) buf; + } + f.bufend = buf + size; + +/* __STDIO_STREAM_RESET_GCS(&f.f); */ +#ifdef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ + f.f.__cookie = &(f.f.__filedes); + f.f.__gcs.read = NULL; + f.f.__gcs.write = NULL; + f.f.__gcs.seek = NULL; + f.f.__gcs.close = NULL; +#endif + + f.f.__filedes = __STDIO_STREAM_FAKE_VSNPRINTF_FILEDES_NB; + f.f.__modeflags = (__FLAG_NARROW|__FLAG_WRITEONLY|__FLAG_WRITING); + +#ifdef __UCLIBC_HAS_WCHAR__ + f.f.__ungot_width[0] = 0; +#endif /* __UCLIBC_HAS_WCHAR__ */ +#ifdef __STDIO_MBSTATE + __INIT_MBSTATE(&(f.f.__state)); +#endif /* __STDIO_MBSTATE */ + +#ifdef __UCLIBC_HAS_THREADS__ + f.f.__user_locking = 1; /* Set user locking. */ + STDIO_INIT_MUTEX(f.f.__lock); +#endif + f.f.__nextopen = NULL; + + rv = vfprintf((FILE *) &f, format, arg); + if (size) { + if (f.bufpos == f.bufend) { + --f.bufpos; + } + *f.bufpos = 0; + } + return rv; +} +libc_hidden_def(vsnprintf) + +#elif defined(__UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__) + +typedef struct { + size_t pos; + size_t len; + unsigned char *buf; + FILE *fp; +} __snpf_cookie; + +#define COOKIE ((__snpf_cookie *) cookie) + +static ssize_t snpf_write(register void *cookie, const char *buf, + size_t bufsize) +{ + size_t count; + register char *p; + + /* Note: bufsize < SSIZE_MAX because of _stdio_WRITE. */ + + if (COOKIE->len > COOKIE->pos) { + count = COOKIE->len - COOKIE->pos - 1; /* Leave space for nul. */ + if (count > bufsize) { + count = bufsize; + } + + p = COOKIE->buf + COOKIE->pos; + while (count) { + *p++ = *buf++; + --count; + } + *p = 0; + } + + COOKIE->pos += bufsize; + + return bufsize; +} + +#undef COOKIE + +int vsnprintf(char *__restrict buf, size_t size, + const char * __restrict format, va_list arg) +{ + FILE f; + __snpf_cookie cookie; + int rv; + + cookie.buf = buf; + cookie.len = size; + cookie.pos = 0; + cookie.fp = &f; + + f.__cookie = &cookie; + f.__gcs.write = snpf_write; + f.__gcs.read = NULL; + f.__gcs.seek = NULL; + f.__gcs.close = NULL; + + f.__filedes = -1; /* For debugging. */ + f.__modeflags = (__FLAG_NARROW|__FLAG_WRITEONLY|__FLAG_WRITING); + +#ifdef __UCLIBC_HAS_WCHAR__ + f.__ungot_width[0] = 0; +#endif /* __UCLIBC_HAS_WCHAR__ */ +#ifdef __STDIO_MBSTATE + __INIT_MBSTATE(&(f.__state)); +#endif /* __STDIO_MBSTATE */ + + f.__nextopen = NULL; + + rv = _vfprintf_internal(&f, format, arg); + + return rv; +} +libc_hidden_def(vsnprintf) + +#else +#warning Skipping vsnprintf since no buffering, no custom streams, and not old vfprintf! +#ifdef __STDIO_HAS_VSNPRINTF +#error WHOA! __STDIO_HAS_VSNPRINTF is defined! +#endif +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/vsprintf.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/vsprintf.c new file mode 100644 index 00000000..d8709014 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/vsprintf.c @@ -0,0 +1,22 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" +#include + +#ifndef __STDIO_HAS_VSNPRINTF +#warning Skipping vsprintf since no vsnprintf! +#else + + +int vsprintf(char *__restrict buf, const char * __restrict format, + va_list arg) +{ + return vsnprintf(buf, SIZE_MAX, format, arg); +} + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/vsscanf.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/vsscanf.c new file mode 100644 index 00000000..882c2713 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/vsscanf.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define L_vsscanf +#include "_scanf.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/vswprintf.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/vswprintf.c new file mode 100644 index 00000000..e509216e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/vswprintf.c @@ -0,0 +1,70 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" +#include +#include + + +/* NB: this file is not used if __USE_OLD_VFPRINTF__ */ + +#ifndef __STDIO_BUFFERS +#warning Skipping vswprintf since no buffering! +#else /* __STDIO_BUFFERS */ + +int vswprintf(wchar_t *__restrict buf, size_t size, + const wchar_t * __restrict format, va_list arg) +{ + FILE f; + int rv; + +/* __STDIO_STREAM_RESET_GCS(&f); */ +#ifdef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ + f.__cookie = &(f.__filedes); + f.__gcs.read = NULL; + f.__gcs.write = NULL; + f.__gcs.seek = NULL; + f.__gcs.close = NULL; +#endif + + f.__filedes = __STDIO_STREAM_FAKE_VSWPRINTF_FILEDES; + f.__modeflags = (__FLAG_WIDE|__FLAG_WRITEONLY|__FLAG_WRITING); + + f.__ungot_width[0] = 0; +#ifdef __STDIO_MBSTATE + __INIT_MBSTATE(&(f.__state)); +#endif /* __STDIO_MBSTATE */ + + f.__nextopen = NULL; + + if (size > ((SIZE_MAX - (size_t) buf)/sizeof(wchar_t))) { + size = ((SIZE_MAX - (size_t) buf)/sizeof(wchar_t)); + } + + f.__bufstart = (unsigned char *) buf; + f.__bufend = (unsigned char *) (buf + size); + __STDIO_STREAM_INIT_BUFREAD_BUFPOS(&f); + __STDIO_STREAM_DISABLE_GETC(&f); + __STDIO_STREAM_DISABLE_PUTC(&f); + + rv = _vfwprintf_internal(&f, format, arg); + + /* NOTE: Return behaviour differs from snprintf... */ + if (f.__bufpos == f.__bufend) { + rv = -1; + if (size) { + f.__bufpos = (unsigned char *) (((wchar_t *) f.__bufpos) - 1); + } + } + if (size) { + *((wchar_t *) f.__bufpos) = 0; + } + return rv; +} +libc_hidden_def(vswprintf) + +#endif /* __STDIO_BUFFERS */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/vswscanf.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/vswscanf.c new file mode 100644 index 00000000..fddb6020 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/vswscanf.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define L_vswscanf +#include "_scanf.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/vwprintf.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/vwprintf.c new file mode 100644 index 00000000..25dd5b3f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/vwprintf.c @@ -0,0 +1,16 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" +#include +#include + + +int vwprintf(const wchar_t * __restrict format, va_list arg) +{ + return vfwprintf(stdout, format, arg); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/vwscanf.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/vwscanf.c new file mode 100644 index 00000000..9e21a271 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/vwscanf.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define L_vwscanf +#include "_scanf.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/wprintf.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/wprintf.c new file mode 100644 index 00000000..b3a6318a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/wprintf.c @@ -0,0 +1,24 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#include "_stdio.h" +#include +#include + + +int wprintf(const wchar_t * __restrict format, ...) +{ + va_list arg; + int rv; + + va_start(arg, format); + rv = vfwprintf(stdout, format, arg); + va_end(arg); + + return rv; +} + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/wscanf.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/wscanf.c new file mode 100644 index 00000000..d354d527 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdio/wscanf.c @@ -0,0 +1,9 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ +#define L_wscanf +#include "_scanf.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/.indent.pro b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/.indent.pro new file mode 100644 index 00000000..492ecf1c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/.indent.pro @@ -0,0 +1,33 @@ +--blank-lines-after-declarations +--blank-lines-after-procedures +--break-before-boolean-operator +--no-blank-lines-after-commas +--braces-on-if-line +--braces-on-struct-decl-line +--comment-indentation25 +--declaration-comment-column25 +--no-comment-delimiters-on-blank-lines +--cuddle-else +--continuation-indentation4 +--case-indentation0 +--else-endif-column33 +--space-after-cast +--line-comments-indentation0 +--declaration-indentation1 +--dont-format-first-column-comments +--dont-format-comments +--honour-newlines +--indent-level4 +/* changed from 0 to 4 */ +--parameter-indentation4 +--line-length78 /* changed from 75 */ +--continue-at-parentheses +--no-space-after-function-call-names +--dont-break-procedure-type +--dont-star-comments +--leave-optional-blank-lines +--dont-space-special-semicolon +--tab-size4 +/* additions by Mark */ +--case-brace-indentation0 +--leave-preprocessor-space diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/Makefile new file mode 100644 index 00000000..11f362a5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../ +top_builddir=../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/Makefile.in new file mode 100644 index 00000000..760ccf7e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/Makefile.in @@ -0,0 +1,80 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +subdirs += libc/stdlib + +include $(top_srcdir)libc/stdlib/malloc/Makefile.in +include $(top_srcdir)libc/stdlib/malloc-simple/Makefile.in +include $(top_srcdir)libc/stdlib/malloc-standard/Makefile.in + +CSRC-y := \ + abort.c getenv.c mkdtemp.c realpath.c canonicalize.c mkstemp.c \ + rand.c random.c random_r.c setenv.c div.c ldiv.c lldiv.c \ + getpt.c drand48-iter.c jrand48.c \ + jrand48_r.c lrand48.c lrand48_r.c mrand48.c mrand48_r.c nrand48.c \ + nrand48_r.c rand_r.c srand48.c srand48_r.c seed48.c seed48_r.c \ + valloc.c a64l.c l64a.c __uc_malloc.c +CSRC-$(UCLIBC_HAS_ADVANCED_REALTIME) += posix_memalign.c +CSRC-$(UCLIBC_HAS_PTY) += grantpt.c unlockpt.c ptsname.c +CSRC-$(UCLIBC_HAS_ARC4RANDOM) += arc4random.c +CSRC-$(UCLIBC_HAS_LFS) += mkstemp64.c +CSRC-$(UCLIBC_HAS_FLOATS) += drand48.c drand48_r.c erand48.c erand48_r.c +CSRC-$(if $(findstring yy,$(UCLIBC_HAS_FLOATS)$(UCLIBC_SUSV3_LEGACY)),y) += \ + gcvt.c +CSRC-$(UCLIBC_SUSV3_LEGACY) += mktemp.c + +# multi source stdlib.c +CSRC-y += abs.c labs.c atoi.c atol.c strtol.c strtoul.c _stdlib_strto_l.c \ + qsort.c bsearch.c \ + llabs.c atoll.c strtoll.c strtoull.c _stdlib_strto_ll.c +# (aliases) strtoq.o strtouq.o +CSRC-$(UCLIBC_HAS_FLOATS) += atof.c +CSRC-$(UCLIBC_HAS_XLOCALE) += strtol_l.c strtoul_l.c _stdlib_strto_l_l.c \ + strtoll_l.c strtoull_l.c _stdlib_strto_ll_l.c + +CSRC-$(UCLIBC_HAS_WCHAR) += mblen.c mbtowc.c wctomb.c mbstowcs.c wcstombs.c \ + _stdlib_mb_cur_max.c _stdlib_wcsto_l.c _stdlib_wcsto_ll.c \ + wcstol.c wcstoul.c wcstoll.c wcstoull.c +CSRC-$(if $(findstring yy,$(UCLIBC_HAS_WCHAR)$(UCLIBC_HAS_XLOCALE)),y) += \ + _stdlib_wcsto_l_l.c _stdlib_wcsto_ll_l.c \ + wcstol_l.c wcstoul_l.c wcstoll_l.c wcstoull_l.c + +# multi source _strtod.c +CSRC-$(UCLIBC_HAS_FLOATS) += strtod.c strtof.c strtold.c __strtofpmax.c __fp_range_check.c +CSRC-$(if $(findstring yy,$(UCLIBC_HAS_FLOATS)$(UCLIBC_HAS_XLOCALE)),y) += \ + strtod_l.c strtof_l.c strtold_l.c __strtofpmax_l.c +CSRC-$(if $(findstring yy,$(UCLIBC_HAS_FLOATS)$(UCLIBC_HAS_WCHAR)),y) += \ + wcstod.c wcstof.c wcstold.c __wcstofpmax.c +CSRC-$(if $(findstring yyy,$(UCLIBC_HAS_FLOATS)$(UCLIBC_HAS_WCHAR)$(UCLIBC_HAS_XLOCALE)),y) += \ + wcstod_l.c wcstof_l.c wcstold_l.c __wcstofpmax_l.c +# (aliases) wcstoq.o wcstouq.o +# wcstod wcstof wcstold + +# multi source _atexit.c +CSRC-y += __cxa_atexit.c __cxa_finalize.c __exit_handler.c exit.c on_exit.c +CSRC-$(COMPAT_ATEXIT) += old_atexit.c + +STDLIB_DIR := $(top_srcdir)libc/stdlib +STDLIB_OUT := $(top_builddir)libc/stdlib + +STDLIB_SRC := $(patsubst %.c,$(STDLIB_DIR)/%.c,$(CSRC-y)) +STDLIB_OBJ := $(patsubst %.c,$(STDLIB_OUT)/%.o,$(CSRC-y)) + +libc-y += $(STDLIB_OBJ) +libc-static-y += $(STDLIB_OUT)/atexit.o $(STDLIB_OUT)/system.o +libc-shared-y += $(STDLIB_OUT)/system.oS + +# this should always be the PIC version, because it could be used in shared libs +libc-nonshared-y += $(STDLIB_OUT)/atexit.os + +libc-nomulti-y += $(STDLIB_OUT)/labs.o $(STDLIB_OUT)/atol.o $(STDLIB_OUT)/_stdlib_strto_l.o $(STDLIB_OUT)/_stdlib_strto_ll.o +libc-nomulti-$(UCLIBC_HAS_XLOCALE) += $(STDLIB_OUT)/_stdlib_strto_l_l.o $(STDLIB_OUT)/_stdlib_strto_ll_l.o + +objclean-y += CLEAN_libc/stdlib + +CLEAN_libc/stdlib: + $(do_rm) $(addprefix $(STDLIB_OUT)/*., o os oS) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/__cxa_atexit.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/__cxa_atexit.c new file mode 100644 index 00000000..fbf06e5a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/__cxa_atexit.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L___cxa_atexit +#include "_atexit.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/__cxa_finalize.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/__cxa_finalize.c new file mode 100644 index 00000000..4a91626b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/__cxa_finalize.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L___cxa_finalize +#include "_atexit.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/__exit_handler.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/__exit_handler.c new file mode 100644 index 00000000..ae4ff84b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/__exit_handler.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L___exit_handler +#include "_atexit.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/__fp_range_check.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/__fp_range_check.c new file mode 100644 index 00000000..9c60972a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/__fp_range_check.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L___fp_range_check +#include "_strtod.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/__strtofpmax.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/__strtofpmax.c new file mode 100644 index 00000000..6b01aca0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/__strtofpmax.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L___strtofpmax +#include "_strtod.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/__strtofpmax_l.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/__strtofpmax_l.c new file mode 100644 index 00000000..a6141323 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/__strtofpmax_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2000-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L___strtofpmax_l +#define __UCLIBC_DO_XLOCALE +#include "_strtod.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/__uc_malloc.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/__uc_malloc.c new file mode 100644 index 00000000..2a2e223e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/__uc_malloc.c @@ -0,0 +1,45 @@ +/* vi: set sw=4 ts=4: */ +/* uClibc internal malloc. + Copyright (C) 2007 Denys Vlasenko + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License +version 2 as published by the Free Software Foundation. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. + +*/ + +#include +#include +#include + + +void (*__uc_malloc_failed)(size_t size) = NULL; +/* Seemingly superfluous assigment of NULL above prevents gas error + * ("__uc_malloc_failed can't be equated to common symbol + * __GI___uc_malloc_failed") in libc_hidden_data_def: */ +libc_hidden_data_def(__uc_malloc_failed) + +void *__uc_malloc(size_t size) +{ + void *p; + + while (1) { + p = malloc(size); + if (!size || p) + return p; + if (!__uc_malloc_failed) + _exit(1); + __uc_malloc_failed(size); + } +} +libc_hidden_def(__uc_malloc) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/__wcstofpmax.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/__wcstofpmax.c new file mode 100644 index 00000000..3c3fdcce --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/__wcstofpmax.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L___wcstofpmax +#include "_strtod.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/__wcstofpmax_l.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/__wcstofpmax_l.c new file mode 100644 index 00000000..909b7204 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/__wcstofpmax_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2000-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L___wcstofpmax_l +#define __UCLIBC_DO_XLOCALE +#include "_strtod.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/_atexit.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/_atexit.c new file mode 100644 index 00000000..0d420d3c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/_atexit.c @@ -0,0 +1,337 @@ +/* Copyright (C) 1995,1996 Robert de Bath + * This file is part of the Linux-8086 C library and is distributed + * under the GNU Library General Public License. + */ + +/* + * Dec 2000 Manuel Novoa III + * + * Made atexit handling conform to standards... i.e. no args. + * Removed on_exit since it did not match gnu libc definition. + * Combined atexit and __do_exit into one object file. + * + * Feb 2001 Manuel Novoa III + * + * Reworked file after addition of __uClibc_main. + * Changed name of __do_exit to atexit_handler. + * Changed name of __cleanup to __uClibc_cleanup. + * Moved declaration of __uClibc_cleanup to __uClibc_main + * where it is initialized with (possibly weak alias) + * _stdio_term. + * + * Jul 2001 Steve Thayer + * + * Added an on_exit implementation (that now matches gnu libc definition.) + * Pulled atexit_handler out of the atexit object since it is now required by + * on_exit as well. Renamed it to __exit_handler. + * Fixed a problem where exit functions stop getting called if one of + * them calls exit(). + * As a side effect of these changes, abort() no longer calls the exit + * functions (it now matches the gnu libc definition). + * + * August 2002 Erik Andersen + * Added locking so atexit and friends can be thread safe + * + * August 2005 Stephen Warren + * Added __cxa_atexit and __cxa_finalize support + * + */ + +#include +#include +#include +#include +#include + +#include +__UCLIBC_MUTEX_EXTERN(__atexit_lock); + + + +typedef void (*aefuncp) (void); /* atexit function pointer */ +typedef void (*oefuncp) (int, void *); /* on_exit function pointer */ +typedef void (*cxaefuncp) (void *); /* __cxa_atexit function pointer */ +typedef enum { + ef_free, + ef_in_use, + ef_on_exit, + ef_cxa_atexit +} ef_type; /* exit function types */ + +/* this is in the L_exit object */ +extern void (*__exit_cleanup) (int) attribute_hidden; + +/* these are in the L___do_exit object */ +extern int __exit_slots attribute_hidden; +extern int __exit_count attribute_hidden; +extern void __exit_handler(int) attribute_hidden; +struct exit_function { + /* + * 'type' should be of type of the 'enum ef_type' above but since we + * need this element in an atomic operation we have to use 'long int'. + */ + long int type; /* enum ef_type */ + union { + struct { + oefuncp func; + void *arg; + } on_exit; + struct { + cxaefuncp func; + void *arg; + void* dso_handle; + } cxa_atexit; + } funcs; +}; +#ifdef __UCLIBC_DYNAMIC_ATEXIT__ +extern struct exit_function *__exit_function_table attribute_hidden; +#else +extern struct exit_function __exit_function_table[__UCLIBC_MAX_ATEXIT] attribute_hidden; +#endif +extern struct exit_function *__new_exitfn (void) attribute_hidden; + +/* this is in the L___cxa_atexit object */ +extern int __cxa_atexit (cxaefuncp, void *arg, void *dso_handle); + + +/* remove old_atexit after 0.9.29 */ +#if defined(L_atexit) || defined(L_old_atexit) +extern void *__dso_handle __attribute__ ((__weak__)); + +/* + * register a function to be called at normal program termination + * (the registered function takes no arguments) + */ +#ifdef L_atexit +int attribute_hidden atexit(aefuncp func) +#else +int old_atexit(aefuncp func); +int old_atexit(aefuncp func) +#endif +{ + /* + * glibc casts aefuncp to cxaefuncp. + * This seems dodgy, but I guess calling a function with more + * parameters than it needs will work everywhere? + */ + return __cxa_atexit((cxaefuncp)func, NULL, + &__dso_handle == NULL ? NULL : __dso_handle); +} +#ifndef L_atexit +weak_alias(old_atexit,atexit) +#endif +#endif + +#ifdef L_on_exit +/* + * register a function to be called at normal program termination + * the registered function takes two arguments: + * status - the exit status that was passed to the exit() function + * arg - generic argument + */ +int on_exit(oefuncp func, void *arg) +{ + struct exit_function *efp; + + if (func == NULL) { + return 0; + } + + efp = __new_exitfn(); + if (efp == NULL) { + return -1; + } + + efp->funcs.on_exit.func = func; + efp->funcs.on_exit.arg = arg; + /* assign last for thread safety, since we're now unlocked */ + efp->type = ef_on_exit; + + return 0; +} +#endif + +#ifdef L___cxa_atexit +libc_hidden_proto(__cxa_atexit) +int __cxa_atexit (cxaefuncp func, void *arg, void *dso_handle) +{ + struct exit_function *efp; + + if (func == NULL) { + return 0; + } + + efp = __new_exitfn(); + if (efp == NULL) { + return -1; + } + + efp->funcs.cxa_atexit.func = func; + efp->funcs.cxa_atexit.arg = arg; + efp->funcs.cxa_atexit.dso_handle = dso_handle; + /* assign last for thread safety, since we're now unlocked */ + efp->type = ef_cxa_atexit; + + return 0; +} +libc_hidden_def(__cxa_atexit) +#endif + +#ifdef L___cxa_finalize +/* + * If D is non-NULL, call all functions registered with `__cxa_atexit' + * with the same dso handle. Otherwise, if D is NULL, call all of the + * registered handlers. + */ +void __cxa_finalize (void *dso_handle); +void __cxa_finalize (void *dso_handle) +{ + struct exit_function *efp; + int exit_count_snapshot = __exit_count; + + /* In reverse order */ + while (exit_count_snapshot) { + efp = &__exit_function_table[--exit_count_snapshot]; + + /* + * We check dso_handle match before we verify the type of the union entry. + * However, the atomic_exchange will validate that we were really "allowed" + * to read dso_handle... + */ + if ((dso_handle == NULL || dso_handle == efp->funcs.cxa_atexit.dso_handle) + /* We don't want to run this cleanup more than once. */ + && !atomic_compare_and_exchange_bool_acq(&efp->type, ef_free, ef_cxa_atexit) + ) { + /* glibc passes status (0) too, but that's not in the prototype */ + (*efp->funcs.cxa_atexit.func)(efp->funcs.cxa_atexit.arg); + } + } + +#if 0 /* haven't looked into this yet... */ + /* + * Remove the registered fork handlers. We do not have to + * unregister anything if the program is going to terminate anyway. + */ +#ifdef UNREGISTER_ATFORK + if (d != NULL) { + UNREGISTER_ATFORK (d); + } +#endif +#endif +} +#endif + +#ifdef L___exit_handler +int __exit_count = 0; /* Number of registered exit functions */ +#ifdef __UCLIBC_DYNAMIC_ATEXIT__ +struct exit_function *__exit_function_table = NULL; +int __exit_slots = 0; /* Size of __exit_function_table */ +#else +struct exit_function __exit_function_table[__UCLIBC_MAX_ATEXIT]; +#endif + +/* + * Find and return a new exit_function pointer, for atexit, + * onexit and __cxa_atexit to initialize + */ +struct exit_function attribute_hidden *__new_exitfn(void) +{ + struct exit_function *efp; + + __UCLIBC_MUTEX_LOCK(__atexit_lock); + +#ifdef __UCLIBC_DYNAMIC_ATEXIT__ + /* If we are out of function table slots, make some more */ + if (__exit_slots < __exit_count+1) { + efp=realloc(__exit_function_table, + (__exit_slots+20)*sizeof(struct exit_function)); + if (efp == NULL) { + __set_errno(ENOMEM); + goto DONE; + } + __exit_function_table = efp; + __exit_slots += 20; + } +#else + if (__exit_count >= __UCLIBC_MAX_ATEXIT) { + __set_errno(ENOMEM); + efp = NULL; + goto DONE; + } +#endif + + __exit_cleanup = __exit_handler; /* enable cleanup */ + efp = &__exit_function_table[__exit_count++]; + efp->type = ef_in_use; + +DONE: + __UCLIBC_MUTEX_UNLOCK(__atexit_lock); + return efp; +} + +/* + * Handle the work of executing the registered exit functions + * This is called while we are locked, so no additional locking + * is needed... + */ +void __exit_handler(int status) +{ + struct exit_function *efp; + + /* In reverse order */ + while ( __exit_count ) { + efp = &__exit_function_table[--__exit_count]; + switch (efp->type) { + case ef_on_exit: + if (efp->funcs.on_exit.func) { + (efp->funcs.on_exit.func) (status, efp->funcs.on_exit.arg); + } + break; + case ef_cxa_atexit: + if (efp->funcs.cxa_atexit.func) { + /* glibc passes status too, but that's not in the prototype */ + (efp->funcs.cxa_atexit.func) (efp->funcs.cxa_atexit.arg); + } + break; + } + } +#ifdef __UCLIBC_DYNAMIC_ATEXIT__ + /* Free up memory used by the __exit_function_table structure */ + free(__exit_function_table); +#endif +} +#endif + +#ifdef L_exit +extern void weak_function _stdio_term(void) attribute_hidden; +attribute_hidden void (*__exit_cleanup) (int) = 0; +__UCLIBC_MUTEX_INIT(__atexit_lock, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP); + +extern void __uClibc_fini(void); +libc_hidden_proto(__uClibc_fini) + +/* + * Normal program termination + */ +void exit(int rv) +{ + /* Perform exit-specific cleanup (atexit and on_exit) */ + __UCLIBC_MUTEX_LOCK(__atexit_lock); + if (__exit_cleanup) { + __exit_cleanup(rv); + } + __UCLIBC_MUTEX_UNLOCK(__atexit_lock); + + __uClibc_fini(); + + /* If we are using stdio, try to shut it down. At the very least, + * this will attempt to commit all buffered writes. It may also + * unbuffer all writable files, or close them outright. + * Check the stdio routines for details. */ + if (_stdio_term) + _stdio_term(); + + _exit(rv); +} +libc_hidden_def(exit) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/_stdlib_mb_cur_max.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/_stdlib_mb_cur_max.c new file mode 100644 index 00000000..b87f6094 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/_stdlib_mb_cur_max.c @@ -0,0 +1,7 @@ +/* Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L__stdlib_mb_cur_max +#include "stdlib.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/_stdlib_strto_l.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/_stdlib_strto_l.c new file mode 100644 index 00000000..4dfa0378 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/_stdlib_strto_l.c @@ -0,0 +1,7 @@ +/* Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L__stdlib_strto_l +#include "stdlib.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/_stdlib_strto_l_l.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/_stdlib_strto_l_l.c new file mode 100644 index 00000000..1692f0cf --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/_stdlib_strto_l_l.c @@ -0,0 +1,8 @@ +/* Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L__stdlib_strto_l_l +#define __UCLIBC_DO_XLOCALE +#include "stdlib.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/_stdlib_strto_ll.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/_stdlib_strto_ll.c new file mode 100644 index 00000000..ce79598b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/_stdlib_strto_ll.c @@ -0,0 +1,7 @@ +/* Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L__stdlib_strto_ll +#include "stdlib.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/_stdlib_strto_ll_l.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/_stdlib_strto_ll_l.c new file mode 100644 index 00000000..b5fb1117 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/_stdlib_strto_ll_l.c @@ -0,0 +1,8 @@ +/* Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L__stdlib_strto_ll_l +#define __UCLIBC_DO_XLOCALE +#include "stdlib.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/_stdlib_wcsto_l.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/_stdlib_wcsto_l.c new file mode 100644 index 00000000..d05a2078 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/_stdlib_wcsto_l.c @@ -0,0 +1,7 @@ +/* Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L__stdlib_wcsto_l +#include "stdlib.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/_stdlib_wcsto_l_l.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/_stdlib_wcsto_l_l.c new file mode 100644 index 00000000..26ea5a70 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/_stdlib_wcsto_l_l.c @@ -0,0 +1,8 @@ +/* Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L__stdlib_wcsto_l_l +#define __UCLIBC_DO_XLOCALE +#include "stdlib.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/_stdlib_wcsto_ll.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/_stdlib_wcsto_ll.c new file mode 100644 index 00000000..e67a5773 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/_stdlib_wcsto_ll.c @@ -0,0 +1,7 @@ +/* Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L__stdlib_wcsto_ll +#include "stdlib.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/_stdlib_wcsto_ll_l.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/_stdlib_wcsto_ll_l.c new file mode 100644 index 00000000..9d647128 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/_stdlib_wcsto_ll_l.c @@ -0,0 +1,8 @@ +/* Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L__stdlib_wcsto_ll_l +#define __UCLIBC_DO_XLOCALE +#include "stdlib.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/_strtod.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/_strtod.c new file mode 100644 index 00000000..dc5d5574 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/_strtod.c @@ -0,0 +1,604 @@ +/* + * Copyright (C) 2000-2005 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* Notes: + * + * The primary objective of this implementation was minimal size and + * portablility, while providing robustness and resonable accuracy. + * + * This implementation depends on IEEE floating point behavior and expects + * to be able to generate +/- infinity as a result. + * + * There are a number of compile-time options below. + */ + +/* July 27, 2003 + * + * General cleanup and some minor size optimizations. + * Change implementation to support __strtofpmax() rather than strtod(). + * Now all the strto{floating pt}() funcs are implemented in terms of + * of the internal __strtofpmax() function. + * Support "nan", "inf", and "infinity" strings (case-insensitive). + * Support hexadecimal floating point notation. + * Support wchar variants. + * Support xlocale variants. + * + * TODO: + * + * Consider accumulating blocks of digits in longs to save floating pt mults. + * This would likely be much better on anything that only supported floats + * where DECIMAL_DIG == 9. Actually, if floats have FLT_MAX_10_EXP == 38, + * we could calculate almost all the exponent multipliers (p_base) in + * long arithmetic as well. + */ + +/**********************************************************************/ +/* OPTIONS */ +/**********************************************************************/ + +/* Defined if we want to recognize "nan", "inf", and "infinity". (C99) */ +#define _STRTOD_NAN_INF_STRINGS 1 + +/* Defined if we want support hexadecimal floating point notation. (C99) */ +/* Note! Now controlled by uClibc configuration. See below. */ +#define _STRTOD_HEXADECIMAL_FLOATS 1 + +/* Defined if we want to scale with a O(log2(exp)) multiplications. + * This is generally a good thing to do unless you are really tight + * on space and do not expect to convert values of large magnitude. */ + +#define _STRTOD_LOG_SCALING 1 + +/* WARNING!!! WARNING!!! WARNING!!! WARNING!!! WARNING!!! + * + * Clearing any of the options below this point is not advised (or tested). + * + * WARNING!!! WARNING!!! WARNING!!! WARNING!!! WARNING!!! */ + +/* Defined if we want strtod to set errno appropriately. */ +/* NOTE: Implies all options below. */ +#define _STRTOD_ERRNO 1 + +/* Defined if we want support for the endptr arg. */ +/* Implied by _STRTOD_ERRNO. */ +#define _STRTOD_ENDPTR 1 + +/* Defined if we want to prevent overflow in accumulating the exponent. */ +/* Implied by _STRTOD_ERRNO. */ +#define _STRTOD_RESTRICT_EXP 1 + +/* Defined if we want to process mantissa digits more intelligently. */ +/* Implied by _STRTOD_ERRNO. */ +#define _STRTOD_RESTRICT_DIGITS 1 + +/* Defined if we want to skip scaling 0 for the exponent. */ +/* Implied by _STRTOD_ERRNO. */ +#define _STRTOD_ZERO_CHECK 1 + +/**********************************************************************/ +/* Don't change anything that follows. */ +/**********************************************************************/ + +#ifdef _STRTOD_ERRNO +#undef _STRTOD_ENDPTR +#undef _STRTOD_RESTRICT_EXP +#undef _STRTOD_RESTRICT_DIGITS +#undef _STRTOD_ZERO_CHECK +#define _STRTOD_ENDPTR 1 +#define _STRTOD_RESTRICT_EXP 1 +#define _STRTOD_RESTRICT_DIGITS 1 +#define _STRTOD_ZERO_CHECK 1 +#endif + +/**********************************************************************/ + +#define _ISOC99_SOURCE 1 +#include +#include +#include +#include +#include +#include +#include + +#include + +#ifdef __UCLIBC_HAS_WCHAR__ +# include +# include +# include +#endif + +#ifdef __UCLIBC_HAS_XLOCALE__ +# include +#endif + +/* Handle _STRTOD_HEXADECIMAL_FLOATS via uClibc config now. */ +#undef _STRTOD_HEXADECIMAL_FLOATS +#ifdef __UCLIBC_HAS_HEXADECIMAL_FLOATS__ +# define _STRTOD_HEXADECIMAL_FLOATS 1 +#endif + +/**********************************************************************/ + +#undef _STRTOD_FPMAX + +#if FPMAX_TYPE == 3 + +#define NEED_STRTOLD_WRAPPER +#define NEED_STRTOD_WRAPPER +#define NEED_STRTOF_WRAPPER + +#elif FPMAX_TYPE == 2 + +#define NEED_STRTOD_WRAPPER +#define NEED_STRTOF_WRAPPER + +#elif FPMAX_TYPE == 1 + +#define NEED_STRTOF_WRAPPER + +#else + +#error unknown FPMAX_TYPE! + +#endif + +extern void __fp_range_check(__fpmax_t y, __fpmax_t x) attribute_hidden; + +/**********************************************************************/ + +#ifdef _STRTOD_RESTRICT_DIGITS +#define EXP_DENORM_ADJUST DECIMAL_DIG +#define MAX_ALLOWED_EXP (DECIMAL_DIG + EXP_DENORM_ADJUST - FPMAX_MIN_10_EXP) + +#if MAX_ALLOWED_EXP > INT_MAX +#error size assumption violated for MAX_ALLOWED_EXP +#endif +#else +/* We want some excess if we're not restricting mantissa digits. */ +#define MAX_ALLOWED_EXP ((20 - FPMAX_MIN_10_EXP) * 2) +#endif + + +#if defined(_STRTOD_RESTRICT_DIGITS) || defined(_STRTOD_ENDPTR) || defined(_STRTOD_HEXADECIMAL_FLOATS) +#undef _STRTOD_NEED_NUM_DIGITS +#define _STRTOD_NEED_NUM_DIGITS 1 +#endif + +/**********************************************************************/ +#if defined(L___strtofpmax) || defined(L___strtofpmax_l) || defined(L___wcstofpmax) || defined(L___wcstofpmax_l) + +#if defined(L___wcstofpmax) || defined(L___wcstofpmax_l) + +#define __strtofpmax __wcstofpmax +#define __strtofpmax_l __wcstofpmax_l + +#define Wchar wchar_t +#ifdef __UCLIBC_DO_XLOCALE +#define ISSPACE(C) iswspace_l((C), locale_arg) +#else +#define ISSPACE(C) iswspace((C)) +#endif + +#else /* defined(L___wcstofpmax) || defined(L___wcstofpmax_l) */ + +#define Wchar char +#ifdef __UCLIBC_DO_XLOCALE +#define ISSPACE(C) isspace_l((C), locale_arg) +#else +#define ISSPACE(C) isspace((C)) +#endif + +#endif /* defined(L___wcstofpmax) || defined(L___wcstofpmax_l) */ + + +#if defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) + +__fpmax_t attribute_hidden __strtofpmax(const Wchar *str, Wchar **endptr, int exponent_power) +{ + return __strtofpmax_l(str, endptr, exponent_power, __UCLIBC_CURLOCALE); +} + +#else /* defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) */ + + +__fpmax_t attribute_hidden __XL_NPP(__strtofpmax)(const Wchar *str, Wchar **endptr, int exponent_power + __LOCALE_PARAM ) +{ + __fpmax_t number; + __fpmax_t p_base = 10; /* Adjusted to 16 in the hex case. */ + Wchar *pos0; +#ifdef _STRTOD_ENDPTR + Wchar *pos1; +#endif + Wchar *pos = (Wchar *) str; + int exponent_temp; + int negative; /* A flag for the number, a multiplier for the exponent. */ +#ifdef _STRTOD_NEED_NUM_DIGITS + int num_digits; +#endif +#ifdef __UCLIBC_HAS_LOCALE__ +#if defined(L___wcstofpmax) || defined(L___wcstofpmax_l) + wchar_t decpt_wc = __LOCALE_PTR->decimal_point_wc; +#else + const char *decpt = __LOCALE_PTR->decimal_point; + int decpt_len = __LOCALE_PTR->decimal_point_len; +#endif +#endif + +#ifdef _STRTOD_HEXADECIMAL_FLOATS + Wchar expchar = 'e'; + Wchar *poshex = NULL; + __uint16_t is_mask = _ISdigit; +#define EXPCHAR expchar +#define IS_X_DIGIT(C) __isctype((C), is_mask) +#else /* _STRTOD_HEXADECIMAL_FLOATS */ +#define EXPCHAR 'e' +#define IS_X_DIGIT(C) isdigit((C)) +#endif /* _STRTOD_HEXADECIMAL_FLOATS */ + + while (ISSPACE(*pos)) { /* Skip leading whitespace. */ + ++pos; + } + + negative = 0; + switch(*pos) { /* Handle optional sign. */ + case '-': negative = 1; /* Fall through to increment position. */ + case '+': ++pos; + } + +#ifdef _STRTOD_HEXADECIMAL_FLOATS + if ((*pos == '0') && (((pos[1])|0x20) == 'x')) { + poshex = ++pos; /* Save position of 'x' in case no digits */ + ++pos; /* and advance past it. */ + is_mask = _ISxdigit; /* Used by IS_X_DIGIT. */ + expchar = 'p'; /* Adjust exponent char. */ + p_base = 16; /* Adjust base multiplier. */ + } +#endif + + number = 0.; +#ifdef _STRTOD_NEED_NUM_DIGITS + num_digits = -1; +#endif +/* exponent_power = 0; */ + pos0 = NULL; + + LOOP: + while (IS_X_DIGIT(*pos)) { /* Process string of (hex) digits. */ +#ifdef _STRTOD_RESTRICT_DIGITS + if (num_digits < 0) { /* First time through? */ + ++num_digits; /* We've now seen a digit. */ + } + if (num_digits || (*pos != '0')) { /* Had/have nonzero. */ + ++num_digits; + if (num_digits <= DECIMAL_DIG) { /* Is digit significant? */ +#ifdef _STRTOD_HEXADECIMAL_FLOATS + number = number * p_base + + (isdigit(*pos) + ? (*pos - '0') + : (((*pos)|0x20) - ('a' - 10))); +#else /* _STRTOD_HEXADECIMAL_FLOATS */ + number = number * p_base + (*pos - '0'); +#endif /* _STRTOD_HEXADECIMAL_FLOATS */ + } + } +#else /* _STRTOD_RESTRICT_DIGITS */ +#ifdef _STRTOD_NEED_NUM_DIGITS + ++num_digits; +#endif +#ifdef _STRTOD_HEXADECIMAL_FLOATS + number = number * p_base + + (isdigit(*pos) + ? (*pos - '0') + : (((*pos)|0x20) - ('a' - 10))); +#else /* _STRTOD_HEXADECIMAL_FLOATS */ + number = number * p_base + (*pos - '0'); +#endif /* _STRTOD_HEXADECIMAL_FLOATS */ +#endif /* _STRTOD_RESTRICT_DIGITS */ + ++pos; + } + +#ifdef __UCLIBC_HAS_LOCALE__ +#if defined(L___wcstofpmax) || defined(L___wcstofpmax_l) + if (!pos0 && (*pos == decpt_wc)) { /* First decimal point? */ + pos0 = ++pos; + goto LOOP; + } +#else + if (!pos0 && !memcmp(pos, decpt, decpt_len)) { /* First decimal point? */ + pos0 = (pos += decpt_len); + goto LOOP; + } +#endif +#else /* __UCLIBC_HAS_LOCALE__ */ + if ((*pos == '.') && !pos0) { /* First decimal point? */ + pos0 = ++pos; /* Save position of decimal point */ + goto LOOP; /* and process rest of digits. */ + } +#endif /* __UCLIBC_HAS_LOCALE__ */ + +#ifdef _STRTOD_NEED_NUM_DIGITS + if (num_digits<0) { /* Must have at least one digit. */ +#ifdef _STRTOD_HEXADECIMAL_FLOATS + if (poshex) { /* Back up to '0' in '0x' prefix. */ + pos = poshex; + goto DONE; + } +#endif /* _STRTOD_HEXADECIMAL_FLOATS */ + +#ifdef _STRTOD_NAN_INF_STRINGS + if (!pos0) { /* No decimal point, so check for inf/nan. */ + /* Note: nan is the first string so 'number = i/0.;' works. */ + static const char nan_inf_str[] = "\05nan\0\012infinity\0\05inf\0"; + int i = 0; + + do { + /* Unfortunately, we have no memcasecmp(). */ + int j = 0; + /* | 0x20 is a cheap lowercasing (valid for ASCII letters and numbers only) */ + while ((pos[j] | 0x20) == nan_inf_str[i+1+j]) { + ++j; + if (!nan_inf_str[i+1+j]) { + number = i / 0.; + if (negative) { /* Correct for sign. */ + number = -number; + } + pos += nan_inf_str[i] - 2; + goto DONE; + } + } + i += nan_inf_str[i]; + } while (nan_inf_str[i]); + } + +#endif /* STRTOD_NAN_INF_STRINGS */ +#ifdef _STRTOD_ENDPTR + pos = (Wchar *) str; +#endif + goto DONE; + } +#endif /* _STRTOD_NEED_NUM_DIGITS */ + +#ifdef _STRTOD_RESTRICT_DIGITS + if (num_digits > DECIMAL_DIG) { /* Adjust exponent for skipped digits. */ + exponent_power += num_digits - DECIMAL_DIG; + } +#endif + + if (pos0) { + exponent_power += pos0 - pos; /* Adjust exponent for decimal point. */ + } + +#ifdef _STRTOD_HEXADECIMAL_FLOATS + if (poshex) { + exponent_power *= 4; /* Above is 2**4, but below is 2. */ + p_base = 2; + } +#endif /* _STRTOD_HEXADECIMAL_FLOATS */ + + if (negative) { /* Correct for sign. */ + number = -number; + } + + /* process an exponent string */ + if (((*pos)|0x20) == EXPCHAR) { +#ifdef _STRTOD_ENDPTR + pos1 = pos; +#endif + negative = 1; + switch(*++pos) { /* Handle optional sign. */ + case '-': negative = -1; /* Fall through to increment pos. */ + case '+': ++pos; + } + + pos0 = pos; + exponent_temp = 0; + while (isdigit(*pos)) { /* Process string of digits. */ +#ifdef _STRTOD_RESTRICT_EXP + if (exponent_temp < MAX_ALLOWED_EXP) { /* Avoid overflow. */ + exponent_temp = exponent_temp * 10 + (*pos - '0'); + } +#else + exponent_temp = exponent_temp * 10 + (*pos - '0'); +#endif + ++pos; + } + +#ifdef _STRTOD_ENDPTR + if (pos == pos0) { /* No digits? */ + pos = pos1; /* Back up to {e|E}/{p|P}. */ + } /* else */ +#endif + + exponent_power += negative * exponent_temp; + } + +#ifdef _STRTOD_ZERO_CHECK + if (number == 0.) { + goto DONE; + } +#endif + + /* scale the result */ +#ifdef _STRTOD_LOG_SCALING + exponent_temp = exponent_power; + + if (exponent_temp < 0) { + exponent_temp = -exponent_temp; + } + + while (exponent_temp) { + if (exponent_temp & 1) { + if (exponent_power < 0) { + /* Warning... caluclating a factor for the exponent and + * then dividing could easily be faster. But doing so + * might cause problems when dealing with denormals. */ + number /= p_base; + } else { + number *= p_base; + } + } + exponent_temp >>= 1; + p_base *= p_base; + } + +#else /* _STRTOD_LOG_SCALING */ + while (exponent_power) { + if (exponent_power < 0) { + number /= p_base; + exponent_power++; + } else { + number *= p_base; + exponent_power--; + } + } +#endif /* _STRTOD_LOG_SCALING */ + +#ifdef _STRTOD_ERRNO + if (__FPMAX_ZERO_OR_INF_CHECK(number)) { + __set_errno(ERANGE); + } +#endif + + DONE: +#ifdef _STRTOD_ENDPTR + if (endptr) { + *endptr = pos; + } +#endif + + return number; +} + +#endif /* defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) */ + +#endif +/**********************************************************************/ +#ifdef L___fp_range_check +#if defined(NEED_STRTOF_WRAPPER) || defined(NEED_STRTOD_WRAPPER) + +void attribute_hidden __fp_range_check(__fpmax_t y, __fpmax_t x) +{ + if (__FPMAX_ZERO_OR_INF_CHECK(y) /* y is 0 or +/- infinity */ + && (y != 0) /* y is not 0 (could have x>0, y==0 if underflow) */ + && !__FPMAX_ZERO_OR_INF_CHECK(x) /* x is not 0 or +/- infinity */ + ) { + __set_errno(ERANGE); /* Then x is not in y's range. */ + } +} + +#endif +#endif +/**********************************************************************/ +#if defined(L_strtof) || defined(L_strtof_l) || defined(L_wcstof) || defined(L_wcstof_l) +#if defined(NEED_STRTOF_WRAPPER) + +#if defined(L_wcstof) || defined(L_wcstof_l) +#define strtof wcstof +#define strtof_l wcstof_l +#define __strtofpmax __wcstofpmax +#define __strtofpmax_l __wcstofpmax_l +#define Wchar wchar_t +#else +#define Wchar char +#endif + + +libc_hidden_proto(__XL_NPP(strtof)) +float __XL_NPP(strtof)(const Wchar *str, Wchar **endptr __LOCALE_PARAM ) +{ +#if FPMAX_TYPE == 1 + return __XL_NPP(__strtofpmax)(str, endptr, 0 __LOCALE_ARG ); +#else + __fpmax_t x; + float y; + + x = __XL_NPP(__strtofpmax)(str, endptr, 0 __LOCALE_ARG ); + y = (float) x; + + __fp_range_check(y, x); + + return y; +#endif +} +libc_hidden_def(__XL_NPP(strtof)) + +#endif +#endif +/**********************************************************************/ +#if defined(L_strtod) || defined(L_strtod_l) || defined(L_wcstod) || defined(L_wcstod_l) +#if defined(NEED_STRTOD_WRAPPER) + +#if defined(L_wcstod) || defined(L_wcstod_l) +#define strtod wcstod +#define strtod_l wcstod_l +#define __strtofpmax __wcstofpmax +#define __strtofpmax_l __wcstofpmax_l +#define Wchar wchar_t +#else +#define Wchar char +#endif + +libc_hidden_proto(__XL_NPP(strtod)) +double __XL_NPP(strtod)(const Wchar *__restrict str, + Wchar **__restrict endptr __LOCALE_PARAM ) +{ +#if FPMAX_TYPE == 2 + return __XL_NPP(__strtofpmax)(str, endptr, 0 __LOCALE_ARG ); +#else + __fpmax_t x; + double y; + + x = __XL_NPP(__strtofpmax)(str, endptr, 0 __LOCALE_ARG ); + y = (double) x; + + __fp_range_check(y, x); + + return y; +#endif +} +libc_hidden_def(__XL_NPP(strtod)) + +#endif +#endif +/**********************************************************************/ +#if defined(L_strtold) || defined(L_strtold_l) || defined(L_wcstold) || defined(L_wcstold_l) +#if defined(NEED_STRTOLD_WRAPPER) + +#if defined(L_wcstold) || defined(L_wcstold_l) +#define strtold wcstold +#define strtold_l wcstold_l +#define __strtofpmax __wcstofpmax +#define __strtofpmax_l __wcstofpmax_l +#define Wchar wchar_t +#else +#define Wchar char +#endif + +libc_hidden_proto(__XL_NPP(strtold)) +long double __XL_NPP(strtold) (const Wchar *str, Wchar **endptr __LOCALE_PARAM ) +{ +#if FPMAX_TYPE == 3 + return __XL_NPP(__strtofpmax)(str, endptr, 0 __LOCALE_ARG ); +#else + __fpmax_t x; + long double y; + + x = __XL_NPP(__strtofpmax)(str, endptr, 0 __LOCALE_ARG ); + y = (long double) x; + + __fp_range_check(y, x); + + return y; +#endif +} +libc_hidden_def(__XL_NPP(strtold)) + +#endif +#endif +/**********************************************************************/ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/a64l.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/a64l.c new file mode 100644 index 00000000..d09dbf46 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/a64l.c @@ -0,0 +1,64 @@ +/* Copyright (C) 1995, 1997, 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , August 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#define TABLE_BASE 0x2e +#define TABLE_SIZE 0x4d + +#define XX ((char)0x40) + + +static const char a64l_table[TABLE_SIZE] = +{ + /* 0x2e */ 0, 1, + /* 0x30 */ 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, XX, XX, XX, XX, XX, XX, + /* 0x40 */ XX, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, + /* 0x50 */ 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, XX, XX, XX, XX, XX, + /* 0x60 */ XX, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, + /* 0x70 */ 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63 +}; + + +long int a64l (const char *string) +{ + const char *ptr = string; + unsigned long int result = 0ul; + const char *end = ptr + 6; + int shift = 0; + + do + { + unsigned index; + unsigned value; + + index = *ptr - TABLE_BASE; + if ((unsigned int) index >= TABLE_SIZE) + break; + value = (int) a64l_table[index]; + if (value == (int) XX) + break; + ++ptr; + result |= value << shift; + shift += 6; + } + while (ptr != end); + + return (long int) result; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/abort.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/abort.c new file mode 100644 index 00000000..3cc79637 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/abort.c @@ -0,0 +1,114 @@ +/* Copyright (C) 1991 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +/* Hacked up for uClibc by Erik Andersen */ + +#include +#include +#include +#include +#include +#include +#include + + + +/* Our last ditch effort to commit suicide */ +#ifdef __UCLIBC_ABORT_INSTRUCTION__ +# define ABORT_INSTRUCTION __asm__(__UCLIBC_ABORT_INSTRUCTION__) +#else +# define ABORT_INSTRUCTION +# warning "no abort instruction defined for your arch" +#endif + +#ifdef __UCLIBC_HAS_STDIO_SHUTDOWN_ON_ABORT__ +extern void weak_function _stdio_term(void) attribute_hidden; +#endif +static smallint been_there_done_that = 0; + +/* Be prepared in case multiple threads try to abort() */ +#include +__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP); + +/* Cause an abnormal program termination with core-dump */ +void abort(void) +{ + sigset_t sigs; + + /* Make sure we acquire the lock before proceeding */ + __UCLIBC_MUTEX_LOCK_CANCEL_UNSAFE(mylock); + + /* Unmask SIGABRT to be sure we can get it */ + __sigemptyset(&sigs); + __sigaddset(&sigs, SIGABRT); + sigprocmask(SIG_UNBLOCK, &sigs, NULL); + + while (1) { + /* Try to suicide with a SIGABRT */ + if (been_there_done_that == 0) { + been_there_done_that++; + +#ifdef __UCLIBC_HAS_STDIO_SHUTDOWN_ON_ABORT__ + /* If we are using stdio, try to shut it down. At the very least, + * this will attempt to commit all buffered writes. It may also + * unbuffer all writable files, or close them outright. + * Check the stdio routines for details. */ + if (_stdio_term) { + _stdio_term(); + } +#endif + +abort_it: + __UCLIBC_MUTEX_UNLOCK_CANCEL_UNSAFE(mylock); + raise(SIGABRT); + __UCLIBC_MUTEX_LOCK_CANCEL_UNSAFE(mylock); + } + + /* Still here? Try to remove any signal handlers */ + if (been_there_done_that == 1) { + struct sigaction act; + + been_there_done_that++; + memset(&act, '\0', sizeof(struct sigaction)); + if (SIG_DFL) /* if it's constant zero, already done */ + act.sa_handler = SIG_DFL; + __sigfillset(&act.sa_mask); + sigaction(SIGABRT, &act, NULL); + + goto abort_it; + } + + /* Still here? Try to suicide with an illegal instruction */ + if (been_there_done_that == 2) { + been_there_done_that++; + ABORT_INSTRUCTION; + } + + /* Still here? Try to at least exit */ + if (been_there_done_that == 3) { + been_there_done_that++; + _exit(127); + } + + /* Still here? We're screwed. Sleepy time. Good night. */ + while (1) + /* Try for ever and ever */ + ABORT_INSTRUCTION; + } +} +libc_hidden_def(abort) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/abs.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/abs.c new file mode 100644 index 00000000..540c020e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/abs.c @@ -0,0 +1,7 @@ +/* Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_abs +#include "stdlib.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/arc4random.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/arc4random.c new file mode 100644 index 00000000..97f318a5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/arc4random.c @@ -0,0 +1,204 @@ +/* $$$: arc4random.c 2005/02/08 robert */ +/* $NetBSD: arc4random.c,v 1.5.2.1 2004/03/26 22:52:50 jmc Exp $ */ +/* $OpenBSD: arc4random.c,v 1.6 2001/06/05 05:05:38 pvalchev Exp $ */ + +/* + * Arc4 random number generator for OpenBSD. + * Copyright 1996 David Mazieres . + * + * Modification and redistribution in source and binary forms is + * permitted provided that due credit is given to the author and the + * OpenBSD project by leaving this copyright notice intact. + */ + +/* + * This code is derived from section 17.1 of Applied Cryptography, + * second edition, which describes a stream cipher allegedly + * compatible with RSA Labs "RC4" cipher (the actual description of + * which is a trade secret). The same algorithm is used as a stream + * cipher called "arcfour" in Tatu Ylonen's ssh package. + * + * Here the stream cipher has been modified always to include the time + * when initializing the state. That makes it impossible to + * regenerate the same random sequence twice, so this can't be used + * for encryption, but will generate good random numbers. + * + * RC4 is a registered trademark of RSA Laboratories. + */ + +#include +#include +#include +#include +#include +#include +#include +#ifdef __ARC4RANDOM_USE_ERANDOM__ +#include +#endif + + +struct arc4_stream { + uint8_t i; + uint8_t j; + uint8_t s[256]; +}; + +static int rs_initialized; +static struct arc4_stream rs; + +static __inline__ void arc4_init(struct arc4_stream *); +static __inline__ void arc4_addrandom(struct arc4_stream *, u_char *, int); +static void arc4_stir(struct arc4_stream *); +static __inline__ uint8_t arc4_getbyte(struct arc4_stream *); +static __inline__ uint32_t arc4_getword(struct arc4_stream *); + +static __inline__ void +arc4_init(as) + struct arc4_stream *as; +{ + int n; + + for (n = 0; n < 256; n++) + as->s[n] = n; + as->i = 0; + as->j = 0; +} + +static __inline__ void +arc4_addrandom(as, dat, datlen) + struct arc4_stream *as; + u_char *dat; + int datlen; +{ + int n; + uint8_t si; + + as->i--; + for (n = 0; n < 256; n++) { + as->i = (as->i + 1); + si = as->s[as->i]; + as->j = (as->j + si + dat[n % datlen]); + as->s[as->i] = as->s[as->j]; + as->s[as->j] = si; + } + as->j = as->i; +} + +static void +arc4_stir(as) + struct arc4_stream *as; +{ + int fd; + struct { + struct timeval tv; + uint rnd[(128 - sizeof(struct timeval)) / sizeof(uint)]; + } rdat; + int n; + + gettimeofday(&rdat.tv, NULL); + fd = open("/dev/urandom", O_RDONLY); + if (fd != -1) { + read(fd, rdat.rnd, sizeof(rdat.rnd)); + close(fd); + } +#ifdef __ARC4RANDOM_USE_ERANDOM__ + else { + int mib[3]; + uint i; + size_t len; + + /* Device could not be opened, we might be chrooted, take + * randomness from sysctl. */ + + mib[0] = CTL_KERN; + mib[1] = KERN_RANDOM; + mib[2] = RANDOM_ERANDOM; + + for (i = 0; i < sizeof(rdat.rnd) / sizeof(uint); i++) { + len = sizeof(uint); + if (sysctl(mib, 3, &rdat.rnd[i], &len, NULL, 0) == -1) + break; + } + } +#endif + + arc4_addrandom(as, (void *) &rdat, sizeof(rdat)); + + /* + * Throw away the first N words of output, as suggested in the + * paper "Weaknesses in the Key Scheduling Algorithm of RC4" + * by Fluher, Mantin, and Shamir. + * http://www.wisdom.weizmann.ac.il/~itsik/RC4/Papers/Rc4_ksa.ps + * N = 256 in our case. + */ + for (n = 0; n < 256 * 4; n++) + arc4_getbyte(as); +} + +static __inline__ uint8_t +arc4_getbyte(as) + struct arc4_stream *as; +{ + uint8_t si, sj; + + as->i = (as->i + 1); + si = as->s[as->i]; + as->j = (as->j + si); + sj = as->s[as->j]; + as->s[as->i] = sj; + as->s[as->j] = si; + return (as->s[(si + sj) & 0xff]); +} + +static __inline__ uint32_t +arc4_getword(as) + struct arc4_stream *as; +{ + uint32_t val; + val = arc4_getbyte(as) << 24; + val |= arc4_getbyte(as) << 16; + val |= arc4_getbyte(as) << 8; + val |= arc4_getbyte(as); + return val; +} + +void +arc4random_stir(void) +{ + if (!rs_initialized) { + arc4_init(&rs); + rs_initialized = 1; + } + arc4_stir(&rs); +} +libc_hidden_def(arc4random_stir) + +void +arc4random_addrandom(u_char *dat, int datlen) +{ + if (!rs_initialized) + arc4random_stir(); + arc4_addrandom(&rs, dat, datlen); +} + +uint32_t +arc4random(void) +{ + if (!rs_initialized) + arc4random_stir(); + return arc4_getword(&rs); +} + +#if 0 +/*-------- Test code --------*/ +#include +#include + +int main(void) { + int random_number; + random_number = arc4random() % 65536; + printf("%d\n", random_number); + return 0; +} +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/atexit.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/atexit.c new file mode 100644 index 00000000..158869e7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/atexit.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_atexit +#include "_atexit.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/atof.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/atof.c new file mode 100644 index 00000000..2fdd75cd --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/atof.c @@ -0,0 +1,7 @@ +/* Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_atof +#include "stdlib.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/atoi.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/atoi.c new file mode 100644 index 00000000..61562bbb --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/atoi.c @@ -0,0 +1,7 @@ +/* Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_atoi +#include "stdlib.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/atol.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/atol.c new file mode 100644 index 00000000..3e577208 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/atol.c @@ -0,0 +1,7 @@ +/* Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_atol +#include "stdlib.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/atoll.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/atoll.c new file mode 100644 index 00000000..f6b04a66 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/atoll.c @@ -0,0 +1,7 @@ +/* Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_atoll +#include "stdlib.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/bsd_getpt.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/bsd_getpt.c new file mode 100644 index 00000000..e704e235 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/bsd_getpt.c @@ -0,0 +1,76 @@ +/* Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Zack Weinberg , 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + +#if defined __USE_BSD + +/* Prefix for master pseudo terminal nodes. */ +#define _PATH_PTY "/dev/pty" + +/* Letters indicating a series of pseudo terminals. */ +#ifndef PTYNAME1 +#define PTYNAME1 "pqrsPQRS" +#endif +const char __libc_ptyname1[] attribute_hidden = PTYNAME1; + +/* Letters indicating the position within a series. */ +#ifndef PTYNAME2 +#define PTYNAME2 "0123456789abcdefghijklmnopqrstuv"; +#endif +const char __libc_ptyname2[] attribute_hidden = PTYNAME2; + +/* Open a master pseudo terminal and return its file descriptor. */ +int +__getpt (void) +{ + char buf[sizeof (_PATH_PTY) + 2]; + const char *p, *q; + char *s; + + s = mempcpy (buf, _PATH_PTY, sizeof (_PATH_PTY) - 1); + /* s[0] and s[1] will be filled in the loop. */ + s[2] = '\0'; + + for (p = __libc_ptyname1; *p != '\0'; ++p) + { + s[0] = *p; + + for (q = __libc_ptyname2; *q != '\0'; ++q) + { + int fd; + + s[1] = *q; + + fd = open (buf, O_RDWR); + if (fd != -1) + return fd; + + if (errno == ENOENT) + return -1; + } + } + + __set_errno (ENOENT); + return -1; +} +#endif /* __USE_BSD */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/bsearch.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/bsearch.c new file mode 100644 index 00000000..4feceefd --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/bsearch.c @@ -0,0 +1,7 @@ +/* Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_bsearch +#include "stdlib.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/canonicalize.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/canonicalize.c new file mode 100644 index 00000000..06e710ab --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/canonicalize.c @@ -0,0 +1,38 @@ +/* + * canonicalize.c -- Return a malloc'd string containing the canonical + * absolute name of the named file. The last file name component need + * not exist, and may be a symlink to a nonexistent file. + * Copyright (C) 2009 STMicroelectronics + * Author: Salvatore Cro + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +#ifdef __USE_GNU + +#ifndef PATH_MAX +# ifdef _POSIX_VERSION +# define PATH_MAX _POSIX_PATH_MAX +# else +# ifdef MAXPATHLEN +# define PATH_MAX MAXPATHLEN +# else +# define PATH_MAX 1024 +# endif +# endif +#endif + +char * canonicalize_file_name (const char *name) +{ + char *buf = (char *) malloc(PATH_MAX); + + if(unlikely(buf == NULL)) + return NULL; + + *buf='\0'; + return realpath (name, buf); +} +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/div.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/div.c new file mode 100644 index 00000000..6c595959 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/div.c @@ -0,0 +1,17 @@ +/* vi: set sw=4 ts=4: */ +/* + * div for uClibc + * Copyright (C) 2000-2006 by Erik Andersen + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +div_t div(int numer, int denom) +{ + div_t result; + result.quot = numer / denom; + result.rem = numer - (result.quot * denom); + return(result); +} + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/drand48-iter.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/drand48-iter.c new file mode 100644 index 00000000..221cbe08 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/drand48-iter.c @@ -0,0 +1,59 @@ +/* Copyright (C) 1995, 1996, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , August 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include + +/* Global state for non-reentrant functions. */ +struct drand48_data __libc_drand48_data attribute_hidden; + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning turn int __drand48_iterate into void +#endif /* __UCLIBC_MJN3_ONLY__ */ +int __drand48_iterate (unsigned short int xsubi[3], struct drand48_data *buffer) attribute_hidden; +int __drand48_iterate (unsigned short int xsubi[3], struct drand48_data *buffer) +{ + uint64_t X; + uint64_t result; + + /* Initialize buffer, if not yet done. */ + if (unlikely(!buffer->__init)) + { + buffer->__a = 0x5deece66dull; + buffer->__c = 0xb; + buffer->__init = 1; + } + + /* Do the real work. We choose a data type which contains at least + 48 bits. Because we compute the modulus it does not care how + many bits really are computed. */ + + X = (uint64_t) xsubi[2] << 32 | (uint32_t) xsubi[1] << 16 | xsubi[0]; + + result = X * buffer->__a + buffer->__c; + + xsubi[0] = result & 0xffff; + xsubi[1] = (result >> 16) & 0xffff; + xsubi[2] = (result >> 32) & 0xffff; + + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/drand48.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/drand48.c new file mode 100644 index 00000000..8c9017b1 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/drand48.c @@ -0,0 +1,33 @@ +/* Copyright (C) 1995,1996,1997,1998,2001,2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , August 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + + +/* Global state for non-reentrant functions. Defined in drand48-iter.c. */ +extern struct drand48_data __libc_drand48_data attribute_hidden; + +double drand48 (void) +{ + double result; + + (void) erand48_r (__libc_drand48_data.__x, &__libc_drand48_data, &result); + + return result; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/drand48_r.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/drand48_r.c new file mode 100644 index 00000000..df07b075 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/drand48_r.c @@ -0,0 +1,28 @@ +/* Copyright (C) 1995, 1996, 1997, 1998, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , August 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + + +int drand48_r (struct drand48_data *buffer, double *result) +{ + return erand48_r (buffer->__x, buffer, result); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/erand48.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/erand48.c new file mode 100644 index 00000000..ee28d963 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/erand48.c @@ -0,0 +1,33 @@ +/* Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper >, August 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + + +/* Global state for non-reentrant functions. Defined in drand48-iter.c. */ +extern struct drand48_data __libc_drand48_data attribute_hidden; + +double erand48 (unsigned short int xsubi[3]) +{ + double result; + + (void) erand48_r (xsubi, &__libc_drand48_data, &result); + + return result; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/erand48_r.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/erand48_r.c new file mode 100644 index 00000000..e36e73eb --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/erand48_r.c @@ -0,0 +1,48 @@ +/* Copyright (C) 1995, 1997, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper >, August 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +extern int __drand48_iterate(unsigned short xsubi[3], + struct drand48_data *buffer) attribute_hidden; + +int erand48_r (unsigned short int xsubi[3], struct drand48_data *buffer, double *result) +{ + union ieee754_double temp; + + /* Compute next state. */ + if (__drand48_iterate (xsubi, buffer) < 0) + return -1; + + /* Construct a positive double with the 48 random bits distributed over + its fractional part so the resulting FP number is [0.0,1.0). */ + + temp.ieee.negative = 0; + temp.ieee.exponent = IEEE754_DOUBLE_BIAS; + temp.ieee.mantissa0 = (xsubi[2] << 4) | (xsubi[1] >> 12); + temp.ieee.mantissa1 = ((xsubi[1] & 0xfff) << 20) | (xsubi[0] << 4); + + /* Please note the lower 4 bits of mantissa1 are always 0. */ + *result = temp.d - 1.0; + + return 0; +} +libc_hidden_def(erand48_r) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/exit.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/exit.c new file mode 100644 index 00000000..a2255d2b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/exit.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_exit +#include "_atexit.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/gcvt.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/gcvt.c new file mode 100644 index 00000000..3c27b62c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/gcvt.c @@ -0,0 +1,12 @@ +#include +#include + + +#ifdef __UCLIBC_HAS_FLOATS__ +#define MAX_NDIGIT 17 +char *gcvt (double number, int ndigit, char *buf) +{ + sprintf(buf, "%.*g", (ndigit > MAX_NDIGIT)? MAX_NDIGIT : ndigit, number); + return buf; +} +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/getenv.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/getenv.c new file mode 100644 index 00000000..d5db1785 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/getenv.c @@ -0,0 +1,30 @@ +/* getenv.c for uClibc + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include + + +/* IEEE Std 1003.1-2001 says getenv need not be thread safe, so + * don't bother locking access to __environ */ +char *getenv(const char *var) +{ + int len; + char **ep; + + if (!(ep=__environ)) + return NULL; + len = strlen(var); + while(*ep) { + if (memcmp(var, *ep, len) == 0 && (*ep)[len] == '=') { + return *ep + len + 1; + } + ep++; + } + return NULL; +} +libc_hidden_def(getenv) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/getpt.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/getpt.c new file mode 100644 index 00000000..2d8b207d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/getpt.c @@ -0,0 +1,132 @@ +/* Copyright (C) 1998, 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Zack Weinberg , 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include +#include + +extern __typeof(statfs) __libc_statfs; + + +#if !defined __ASSUME_DEVPTS__ + +/* Constant that identifies the `devpts' filesystem. */ +# define DEVPTS_SUPER_MAGIC 0x1cd1 +/* Constant that identifies the `devfs' filesystem. */ +# define DEVFS_SUPER_MAGIC 0x1373 +#endif + +/* Path to the master pseudo terminal cloning device. */ +#define _PATH_DEVPTMX _PATH_DEV "ptmx" +/* Directory containing the UNIX98 pseudo terminals. */ +#define _PATH_DEVPTS _PATH_DEV "pts" + +#if !defined __UNIX98PTY_ONLY__ && defined __UCLIBC_HAS_GETPT__ +/* Prototype for function that opens BSD-style master pseudo-terminals. */ +extern int __bsd_getpt (void) attribute_hidden; +#endif + +/* Open a master pseudo terminal and return its file descriptor. */ +int +posix_openpt (int flags) +{ +#define have_no_dev_ptmx (1<<0) +#define devpts_mounted (1<<1) +#if !defined __UNIX98PTY_ONLY__ + static smallint _state; +#endif + int fd; + +#if !defined __UNIX98PTY_ONLY__ + if (!(_state & have_no_dev_ptmx)) +#endif + { + fd = open (_PATH_DEVPTMX, flags); + if (fd != -1) + { +#if defined __ASSUME_DEVPTS__ + return fd; +#else + struct statfs fsbuf; + + /* Check that the /dev/pts filesystem is mounted + or if /dev is a devfs filesystem (this implies /dev/pts). */ + if ( +#if !defined __UNIX98PTY_ONLY__ + (_state & devpts_mounted) || +#endif + (__libc_statfs (_PATH_DEVPTS, &fsbuf) == 0 + && fsbuf.f_type == DEVPTS_SUPER_MAGIC) + || (__libc_statfs (_PATH_DEV, &fsbuf) == 0 + && fsbuf.f_type == DEVFS_SUPER_MAGIC)) + { + /* Everything is ok. */ +#if !defined __UNIX98PTY_ONLY__ + _state |= devpts_mounted; +#endif + return fd; + } + + /* If /dev/pts is not mounted then the UNIX98 pseudo terminals + are not usable. */ + close (fd); +#if !defined __UNIX98PTY_ONLY__ + _state |= have_no_dev_ptmx; +#endif +#endif + } + else + { +#if !defined __UNIX98PTY_ONLY__ + if (errno == ENOENT || errno == ENODEV) + _state |= have_no_dev_ptmx; + else +#endif + return -1; + } + } +#if !defined __UNIX98PTY_ONLY__ && defined __UCLIBC_HAS_GETPT__ + /* If we have no ptmx then ignore flags and use the fallback. */ + if (_state & have_no_dev_ptmx) + return __bsd_getpt(); +#endif + return -1; +} +libc_hidden_def(posix_openpt) +#undef have_no_dev_ptmx +#undef devpts_mounted + +#if defined __USE_GNU && defined __UCLIBC_HAS_GETPT__ +int getpt (void) +{ + return posix_openpt(O_RDWR); +} + +#if !defined __UNIX98PTY_ONLY__ && defined __UCLIBC_HAS_GETPT__ +# define PTYNAME1 "pqrstuvwxyzabcde"; +# define PTYNAME2 "0123456789abcdef"; + +# define __getpt __bsd_getpt +# include "bsd_getpt.c" +#endif +#endif /* GNU && __UCLIBC_HAS_GETPT__ */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/grantpt.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/grantpt.c new file mode 100644 index 00000000..42a64b37 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/grantpt.c @@ -0,0 +1,76 @@ +/* Copyright (C) 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +/* If __ASSUME_DEVPTS__ is defined, grantpt() reduces to a stub since we + assume that the devfs/devpts filesystem automatically manages the + permissions. */ +#if !defined __ASSUME_DEVPTS__ +#include + +/* Constant that identifies the `devpts' filesystem. */ +#define DEVPTS_SUPER_MAGIC 0x1cd1 +/* Constant that identifies the `devfs' filesystem. */ +#define DEVFS_SUPER_MAGIC 0x1373 + +/* Prototype for function that changes ownership and access permission + for slave pseudo terminals that do not live on a `devpts' + filesystem. */ +int __unix_grantpt (int fd); + +/* Prototype for private function that gets the name of the slave + pseudo terminal in a safe way. */ +static int pts_name (int fd, char **pts, size_t buf_len); +extern __typeof(statfs) __libc_statfs; +#endif + +/* Change the ownership and access permission of the slave pseudo + terminal associated with the master pseudo terminal specified + by FD. */ +int +#if !defined __ASSUME_DEVPTS__ +grantpt (int fd) +#else +grantpt (attribute_unused int fd) +#endif +{ +#if !defined __ASSUME_DEVPTS__ + struct statfs fsbuf; + char _buf[PATH_MAX]; + char *buf = _buf; + + if (pts_name (fd, &buf, sizeof (_buf))) + return -1; + + if (__libc_statfs (buf, &fsbuf) < 0) + return -1; + + /* If the slave pseudo terminal lives on a `devpts' filesystem, the + ownership and access permission are already set. */ + if (fsbuf.f_type != DEVPTS_SUPER_MAGIC && fsbuf.f_type != DEVFS_SUPER_MAGIC) + return __unix_grantpt (fd); +#endif + return 0; +} + +#if !defined __ASSUME_DEVPTS__ +# define grantpt __unix_grantpt +# include "unix_grantpt.c" +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/jrand48.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/jrand48.c new file mode 100644 index 00000000..163c5408 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/jrand48.c @@ -0,0 +1,33 @@ +/* Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper >, August 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + + +/* Global state for non-reentrant functions. Defined in drand48-iter.c. */ +extern struct drand48_data __libc_drand48_data attribute_hidden; + +long int jrand48 (unsigned short int xsubi[3]) +{ + long int result; + + (void) jrand48_r (xsubi, &__libc_drand48_data, &result); + + return result; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/jrand48_r.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/jrand48_r.c new file mode 100644 index 00000000..24f7075f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/jrand48_r.c @@ -0,0 +1,36 @@ +/* Copyright (C) 1995, 1997, 1998, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper >, August 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +extern int __drand48_iterate(unsigned short xsubi[3], + struct drand48_data *buffer) attribute_hidden; + +int jrand48_r (unsigned short int xsubi[3], struct drand48_data *buffer, long int *result) +{ + /* Compute next state. */ + if (__drand48_iterate (xsubi, buffer) < 0) + return -1; + + /* Store the result. */ + *result = ((xsubi[2] << 16) | xsubi[1]) & 0xffffffffl; + + return 0; +} +libc_hidden_def(jrand48_r) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/l64a.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/l64a.c new file mode 100644 index 00000000..1f0dfb7a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/l64a.c @@ -0,0 +1,56 @@ +/* Copyright (C) 1995, 1996, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , August 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +/* Conversion table. */ +static const char conv_table[64] = +{ + '.', '/', '0', '1', '2', '3', '4', '5', + '6', '7', '8', '9', 'A', 'B', 'C', 'D', + 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', + 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', + 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', + 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', + 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', + 's', 't', 'u', 'v', 'w', 'x', 'y', 'z' +}; + +char * l64a (long int n) +{ + unsigned long int m = (unsigned long int) n; + static char result[7]; + char *p; + + /* The standard says that only 32 bits are used. */ + if (sizeof(m) != 4) + m &= 0xffffffff; + + /* The value for N == 0 is defined to be the empty string, + * this code provides that as well. */ + p = result; + while (m) + { + *p++ = conv_table[m & 0x3f]; + m >>= 6; + } + *p = '\0'; + + return result; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/labs.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/labs.c new file mode 100644 index 00000000..95196af9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/labs.c @@ -0,0 +1,7 @@ +/* Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_labs +#include "stdlib.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/ldiv.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/ldiv.c new file mode 100644 index 00000000..88a87711 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/ldiv.c @@ -0,0 +1,61 @@ + +/* Copyright (C) 1992, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + + +/* Return the `ldiv_t' representation of NUMER over DENOM. */ +ldiv_t +ldiv (long int numer, long int denom) +{ + ldiv_t result; + + result.quot = numer / denom; + result.rem = numer % denom; + + /* The ANSI standard says that |QUOT| <= |NUMER / DENOM|, where + NUMER / DENOM is to be computed in infinite precision. In + other words, we should always truncate the quotient towards + zero, never -infinity. Machine division and remainer may + work either way when one or both of NUMER or DENOM is + negative. If only one is negative and QUOT has been + truncated towards -infinity, REM will have the same sign as + DENOM and the opposite sign of NUMER; if both are negative + and QUOT has been truncated towards -infinity, REM will be + positive (will have the opposite sign of NUMER). These are + considered `wrong'. If both are NUM and DENOM are positive, + RESULT will always be positive. This all boils down to: if + NUMER >= 0, but REM < 0, we got the wrong answer. In that + case, to get the right answer, add 1 to QUOT and subtract + DENOM from REM. */ + + if (numer >= 0 && result.rem < 0) + { + ++result.quot; + result.rem -= denom; + } + + return result; +} + +#if __WORDSIZE == 64 +#undef imaxdiv +strong_alias(ldiv,imaxdiv) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/llabs.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/llabs.c new file mode 100644 index 00000000..17ec30a6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/llabs.c @@ -0,0 +1,7 @@ +/* Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_llabs +#include "stdlib.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/lldiv.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/lldiv.c new file mode 100644 index 00000000..ff670174 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/lldiv.c @@ -0,0 +1,61 @@ +/* `long long int' divison with remainder. + Copyright (C) 1992, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + + +/* Return the `lldiv_t' representation of NUMER over DENOM. */ +lldiv_t +lldiv (long long int numer, long long int denom) +{ + lldiv_t result; + + result.quot = numer / denom; + result.rem = numer % denom; + + /* The ANSI standard says that |QUOT| <= |NUMER / DENOM|, where + NUMER / DENOM is to be computed in infinite precision. In + other words, we should always truncate the quotient towards + zero, never -infinity. Machine division and remainer may + work either way when one or both of NUMER or DENOM is + negative. If only one is negative and QUOT has been + truncated towards -infinity, REM will have the same sign as + DENOM and the opposite sign of NUMER; if both are negative + and QUOT has been truncated towards -infinity, REM will be + positive (will have the opposite sign of NUMER). These are + considered `wrong'. If both are NUM and DENOM are positive, + RESULT will always be positive. This all boils down to: if + NUMER >= 0, but REM < 0, we got the wrong answer. In that + case, to get the right answer, add 1 to QUOT and subtract + DENOM from REM. */ + + if (numer >= 0 && result.rem < 0) + { + ++result.quot; + result.rem -= denom; + } + + return result; +} + +#if __WORDSIZE != 64 +#undef imaxdiv +strong_alias(lldiv,imaxdiv) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/lrand48.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/lrand48.c new file mode 100644 index 00000000..a0b15caf --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/lrand48.c @@ -0,0 +1,33 @@ +/* Copyright (C) 1995, 1996, 1997, 1998, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper >, August 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + + +/* Global state for non-reentrant functions. Defined in drand48-iter.c. */ +extern struct drand48_data __libc_drand48_data attribute_hidden; + +long int lrand48 (void) +{ + long int result; + + nrand48_r (__libc_drand48_data.__x, &__libc_drand48_data, &result); + + return result; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/lrand48_r.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/lrand48_r.c new file mode 100644 index 00000000..5a425d1e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/lrand48_r.c @@ -0,0 +1,31 @@ +/* Copyright (C) 1995, 1997, 1998, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper >, August 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + + +int lrand48_r (struct drand48_data *buffer, long int *result) +{ + /* Be generous for the arguments, detect some errors. */ + if (buffer == NULL) + return -1; + + return nrand48_r (buffer->__x, buffer, result); +} +libc_hidden_def(lrand48_r) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc-simple/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc-simple/Makefile new file mode 100644 index 00000000..4a8f4a07 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc-simple/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../ +top_builddir=../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc-simple/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc-simple/Makefile.in new file mode 100644 index 00000000..351504bd --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc-simple/Makefile.in @@ -0,0 +1,24 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +subdirs += libc/stdlib/malloc-simple + +STDLIB_MALLOC_SIMPLE_DIR := $(top_srcdir)libc/stdlib/malloc-simple +STDLIB_MALLOC_SIMPLE_OUT := $(top_builddir)libc/stdlib/malloc-simple + +CSRC := $(notdir $(wildcard $(STDLIB_MALLOC_SIMPLE_DIR)/*.c)) +CSRC := $(filter-out alloc.c,$(CSRC)) + +STDLIB_MALLOC_SIMPLE_SRC := $(patsubst %.c,$(STDLIB_MALLOC_SIMPLE_DIR)/%.c,$(CSRC)) +STDLIB_MALLOC_SIMPLE_OBJ := $(patsubst %.c,$(STDLIB_MALLOC_SIMPLE_OUT)/%.o,$(CSRC)) + +libc-$(MALLOC_SIMPLE) += $(STDLIB_MALLOC_SIMPLE_OBJ) + +objclean-y += CLEAN_libc/stdlib/malloc-simple + +CLEAN_libc/stdlib/malloc-simple: + $(do_rm) $(addprefix $(STDLIB_MALLOC_SIMPLE_OUT)/*., o os) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc-simple/alloc.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc-simple/alloc.c new file mode 100644 index 00000000..914c89dc --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc-simple/alloc.c @@ -0,0 +1,185 @@ +/* alloc.c + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ +/* + * Parts of the memalign code were stolen from malloc-930716. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + + +#ifdef L_malloc +void *malloc(size_t size) +{ + void *result; + + if (unlikely(size == 0)) { +#if defined(__MALLOC_GLIBC_COMPAT__) + size++; +#else + /* Some programs will call malloc (0). Lets be strict and return NULL */ + __set_errno(ENOMEM); + return NULL; +#endif + } + +#ifdef __ARCH_USE_MMU__ +# define MMAP_FLAGS MAP_PRIVATE | MAP_ANONYMOUS +#else +# define MMAP_FLAGS MAP_SHARED | MAP_ANONYMOUS | MAP_UNINITIALIZE +#endif + + result = mmap((void *) 0, size + sizeof(size_t), PROT_READ | PROT_WRITE, + MMAP_FLAGS, 0, 0); + if (result == MAP_FAILED) + return 0; + * (size_t *) result = size; + return(result + sizeof(size_t)); +} +#endif + +#ifdef L_calloc +void * calloc(size_t nmemb, size_t lsize) +{ + void *result; + size_t size=lsize * nmemb; + + /* guard vs integer overflow, but allow nmemb + * to fall through and call malloc(0) */ + if (nmemb && lsize != (size / nmemb)) { + __set_errno(ENOMEM); + return NULL; + } + result = malloc(size); + +#ifndef __ARCH_USE_MMU__ + /* mmap'd with MAP_UNINITIALIZE, we have to blank memory ourselves */ + if (result != NULL) { + memset(result, 0, size); + } +#endif + return result; +} +#endif + +#ifdef L_realloc +void *realloc(void *ptr, size_t size) +{ + void *newptr = NULL; + + if (!ptr) + return malloc(size); + if (!size) { + free(ptr); + return malloc(0); + } + + newptr = malloc(size); + if (newptr) { + size_t old_size = *((size_t *) (ptr - sizeof(size_t))); + memcpy(newptr, ptr, (old_size < size ? old_size : size)); + free(ptr); + } + return newptr; +} +#endif + +#ifdef L_free +extern int weak_function __libc_free_aligned(void *ptr); +void free(void *ptr) +{ + if (unlikely(ptr == NULL)) + return; + if (unlikely(__libc_free_aligned != NULL)) { + if (__libc_free_aligned(ptr)) + return; + } + ptr -= sizeof(size_t); + munmap(ptr, * (size_t *) ptr + sizeof(size_t)); +} +#endif + +#ifdef L_memalign + +#include +__UCLIBC_MUTEX_INIT(__malloc_lock, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP); +#define __MALLOC_LOCK __UCLIBC_MUTEX_LOCK(__malloc_lock) +#define __MALLOC_UNLOCK __UCLIBC_MUTEX_UNLOCK(__malloc_lock) + +/* List of blocks allocated with memalign or valloc */ +struct alignlist +{ + struct alignlist *next; + __ptr_t aligned; /* The address that memaligned returned. */ + __ptr_t exact; /* The address that malloc returned. */ +}; +struct alignlist *_aligned_blocks; + +/* Return memory to the heap. */ +int __libc_free_aligned(void *ptr) +{ + struct alignlist *l; + + if (ptr == NULL) + return 0; + + __MALLOC_LOCK; + for (l = _aligned_blocks; l != NULL; l = l->next) { + if (l->aligned == ptr) { + /* Mark the block as free */ + l->aligned = NULL; + ptr = l->exact; + ptr -= sizeof(size_t); + munmap(ptr, * (size_t *) ptr + sizeof(size_t)); + return 1; + } + } + __MALLOC_UNLOCK; + return 0; +} +void * memalign (size_t alignment, size_t size) +{ + void * result; + unsigned long int adj; + + result = malloc (size + alignment - 1); + if (result == NULL) + return NULL; + + adj = (unsigned long int) ((unsigned long int) ((char *) result - (char *) NULL)) % alignment; + if (adj != 0) { + struct alignlist *l; + __MALLOC_LOCK; + for (l = _aligned_blocks; l != NULL; l = l->next) + if (l->aligned == NULL) + /* This slot is free. Use it. */ + break; + if (l == NULL) { + l = (struct alignlist *) malloc (sizeof (struct alignlist)); + if (l == NULL) { + free(result); + result = NULL; + goto DONE; + } + l->next = _aligned_blocks; + _aligned_blocks = l; + } + l->exact = result; + result = l->aligned = (char *) result + alignment - adj; +DONE: + __MALLOC_UNLOCK; + } + + return result; +} +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc-simple/calloc.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc-simple/calloc.c new file mode 100644 index 00000000..b4048964 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc-simple/calloc.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_calloc +#include "alloc.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc-simple/free.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc-simple/free.c new file mode 100644 index 00000000..3fc7a969 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc-simple/free.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_free +#include "alloc.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc-simple/malloc.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc-simple/malloc.c new file mode 100644 index 00000000..1ad8ca2f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc-simple/malloc.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_malloc +#include "alloc.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc-simple/memalign.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc-simple/memalign.c new file mode 100644 index 00000000..d7ee3529 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc-simple/memalign.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_memalign +#include "alloc.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc-simple/realloc.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc-simple/realloc.c new file mode 100644 index 00000000..b116ab11 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc-simple/realloc.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_realloc +#include "alloc.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc-standard/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc-standard/Makefile new file mode 100644 index 00000000..4a8f4a07 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc-standard/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../ +top_builddir=../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc-standard/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc-standard/Makefile.in new file mode 100644 index 00000000..7da7fe1d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc-standard/Makefile.in @@ -0,0 +1,25 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +subdirs += libc/stdlib/malloc-standard + +# calloc.c can be found at uClibc/libc/stdlib/calloc.c +# valloc.c can be found at uClibc/libc/stdlib/valloc.c +CSRC := malloc.c calloc.c realloc.c free.c memalign.c mallopt.c mallinfo.c + +STDLIB_MALLOC_STANDARD_DIR := $(top_srcdir)libc/stdlib/malloc-standard +STDLIB_MALLOC_STANDARD_OUT := $(top_builddir)libc/stdlib/malloc-standard + +STDLIB_MALLOC_STANDARD_SRC := $(patsubst %.c,$(STDLIB_MALLOC_STANDARD_DIR)/%.c,$(CSRC)) +STDLIB_MALLOC_STANDARD_OBJ := $(patsubst %.c,$(STDLIB_MALLOC_STANDARD_OUT)/%.o,$(CSRC)) + +libc-$(MALLOC_STANDARD) += $(STDLIB_MALLOC_STANDARD_OBJ) + +objclean-y += CLEAN_libc/stdlib/malloc-standard + +CLEAN_libc/stdlib/malloc-standard: + $(do_rm) $(addprefix $(STDLIB_MALLOC_STANDARD_OUT)/*., o os) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc-standard/calloc.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc-standard/calloc.c new file mode 100644 index 00000000..a70516f0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc-standard/calloc.c @@ -0,0 +1,93 @@ +/* + This is a version (aka dlmalloc) of malloc/free/realloc written by + Doug Lea and released to the public domain. Use, modify, and + redistribute this code without permission or acknowledgement in any + way you wish. Send questions, comments, complaints, performance + data, etc to dl@cs.oswego.edu + + VERSION 2.7.2 Sat Aug 17 09:07:30 2002 Doug Lea (dl at gee) + + Note: There may be an updated version of this malloc obtainable at + ftp://gee.cs.oswego.edu/pub/misc/malloc.c + Check before installing! + + Hacked up for uClibc by Erik Andersen +*/ + +#include "malloc.h" + + +/* ------------------------------ calloc ------------------------------ */ +void* calloc(size_t n_elements, size_t elem_size) +{ + mchunkptr p; + unsigned long clearsize; + unsigned long nclears; + size_t size, *d; + void* mem; + + + /* guard vs integer overflow, but allow nmemb + * to fall through and call malloc(0) */ + size = n_elements * elem_size; + if (n_elements && elem_size != (size / n_elements)) { + __set_errno(ENOMEM); + return NULL; + } + + __MALLOC_LOCK; + mem = malloc(size); + if (mem != 0) { + p = mem2chunk(mem); + + if (!chunk_is_mmapped(p)) + { + /* + Unroll clear of <= 36 bytes (72 if 8byte sizes) + We know that contents have an odd number of + size_t-sized words; minimally 3. + */ + + d = (size_t*)mem; + clearsize = chunksize(p) - (sizeof(size_t)); + nclears = clearsize / sizeof(size_t); + assert(nclears >= 3); + + if (nclears > 9) + memset(d, 0, clearsize); + + else { + *(d+0) = 0; + *(d+1) = 0; + *(d+2) = 0; + if (nclears > 4) { + *(d+3) = 0; + *(d+4) = 0; + if (nclears > 6) { + *(d+5) = 0; + *(d+6) = 0; + if (nclears > 8) { + *(d+7) = 0; + *(d+8) = 0; + } + } + } + } + } +#if 0 + else + { + /* Standard unix mmap using /dev/zero clears memory so calloc + * doesn't need to actually zero anything.... + */ + d = (size_t*)mem; + /* Note the additional (sizeof(size_t)) */ + clearsize = chunksize(p) - 2*(sizeof(size_t)); + memset(d, 0, clearsize); + } +#endif + } + __MALLOC_UNLOCK; + return mem; +} + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc-standard/free.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc-standard/free.c new file mode 100644 index 00000000..39e54d63 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc-standard/free.c @@ -0,0 +1,410 @@ +/* + This is a version (aka dlmalloc) of malloc/free/realloc written by + Doug Lea and released to the public domain. Use, modify, and + redistribute this code without permission or acknowledgement in any + way you wish. Send questions, comments, complaints, performance + data, etc to dl@cs.oswego.edu + + VERSION 2.7.2 Sat Aug 17 09:07:30 2002 Doug Lea (dl at gee) + + Note: There may be an updated version of this malloc obtainable at + ftp://gee.cs.oswego.edu/pub/misc/malloc.c + Check before installing! + + Hacked up for uClibc by Erik Andersen +*/ + +#include "malloc.h" + + +/* ------------------------- __malloc_trim ------------------------- + __malloc_trim is an inverse of sorts to __malloc_alloc. It gives memory + back to the system (via negative arguments to sbrk) if there is unused + memory at the `high' end of the malloc pool. It is called automatically by + free() when top space exceeds the trim threshold. It is also called by the + public malloc_trim routine. It returns 1 if it actually released any + memory, else 0. +*/ +static int __malloc_trim(size_t pad, mstate av) +{ + long top_size; /* Amount of top-most memory */ + long extra; /* Amount to release */ + long released; /* Amount actually released */ + char* current_brk; /* address returned by pre-check sbrk call */ + char* new_brk; /* address returned by post-check sbrk call */ + size_t pagesz; + + pagesz = av->pagesize; + top_size = chunksize(av->top); + + /* Release in pagesize units, keeping at least one page */ + extra = ((top_size - pad - MINSIZE + (pagesz-1)) / pagesz - 1) * pagesz; + + if (extra > 0) { + + /* + Only proceed if end of memory is where we last set it. + This avoids problems if there were foreign sbrk calls. + */ + current_brk = (char*)(MORECORE(0)); + if (current_brk == (char*)(av->top) + top_size) { + + /* + Attempt to release memory. We ignore MORECORE return value, + and instead call again to find out where new end of memory is. + This avoids problems if first call releases less than we asked, + of if failure somehow altered brk value. (We could still + encounter problems if it altered brk in some very bad way, + but the only thing we can do is adjust anyway, which will cause + some downstream failure.) + */ + + MORECORE(-extra); + new_brk = (char*)(MORECORE(0)); + + if (new_brk != (char*)MORECORE_FAILURE) { + released = (long)(current_brk - new_brk); + + if (released != 0) { + /* Success. Adjust top. */ + av->sbrked_mem -= released; + set_head(av->top, (top_size - released) | PREV_INUSE); + check_malloc_state(); + return 1; + } + } + } + } + return 0; +} + +/* ------------------------- malloc_trim ------------------------- + malloc_trim(size_t pad); + + If possible, gives memory back to the system (via negative + arguments to sbrk) if there is unused memory at the `high' end of + the malloc pool. You can call this after freeing large blocks of + memory to potentially reduce the system-level memory requirements + of a program. However, it cannot guarantee to reduce memory. Under + some allocation patterns, some large free blocks of memory will be + locked between two used chunks, so they cannot be given back to + the system. + + The `pad' argument to malloc_trim represents the amount of free + trailing space to leave untrimmed. If this argument is zero, + only the minimum amount of memory to maintain internal data + structures will be left (one page or less). Non-zero arguments + can be supplied to maintain enough trailing space to service + future expected allocations without having to re-obtain memory + from the system. + + Malloc_trim returns 1 if it actually released any memory, else 0. + On systems that do not support "negative sbrks", it will always + return 0. +*/ +int malloc_trim(size_t pad) +{ + mstate av = get_malloc_state(); + __malloc_consolidate(av); + return __malloc_trim(pad, av); +} + +/* + Initialize a malloc_state struct. + + This is called only from within __malloc_consolidate, which needs + be called in the same contexts anyway. It is never called directly + outside of __malloc_consolidate because some optimizing compilers try + to inline it at all call points, which turns out not to be an + optimization at all. (Inlining it in __malloc_consolidate is fine though.) +*/ +static void malloc_init_state(mstate av) +{ + int i; + mbinptr bin; + + /* Establish circular links for normal bins */ + for (i = 1; i < NBINS; ++i) { + bin = bin_at(av,i); + bin->fd = bin->bk = bin; + } + + av->top_pad = DEFAULT_TOP_PAD; + av->n_mmaps_max = DEFAULT_MMAP_MAX; + av->mmap_threshold = DEFAULT_MMAP_THRESHOLD; + av->trim_threshold = DEFAULT_TRIM_THRESHOLD; + +#if MORECORE_CONTIGUOUS + set_contiguous(av); +#else + set_noncontiguous(av); +#endif + + + set_max_fast(av, DEFAULT_MXFAST); + + av->top = initial_top(av); + av->pagesize = malloc_getpagesize; +} + + +/* ---------------------------------------------------------------------- + * + * PUBLIC STUFF + * + * ----------------------------------------------------------------------*/ + + +/* ------------------------- __malloc_consolidate ------------------------- + + __malloc_consolidate is a specialized version of free() that tears + down chunks held in fastbins. Free itself cannot be used for this + purpose since, among other things, it might place chunks back onto + fastbins. So, instead, we need to use a minor variant of the same + code. + + Also, because this routine needs to be called the first time through + malloc anyway, it turns out to be the perfect place to trigger + initialization code. +*/ +void attribute_hidden __malloc_consolidate(mstate av) +{ + mfastbinptr* fb; /* current fastbin being consolidated */ + mfastbinptr* maxfb; /* last fastbin (for loop control) */ + mchunkptr p; /* current chunk being consolidated */ + mchunkptr nextp; /* next chunk to consolidate */ + mchunkptr unsorted_bin; /* bin header */ + mchunkptr first_unsorted; /* chunk to link to */ + + /* These have same use as in free() */ + mchunkptr nextchunk; + size_t size; + size_t nextsize; + size_t prevsize; + int nextinuse; + mchunkptr bck; + mchunkptr fwd; + + /* + If max_fast is 0, we know that av hasn't + yet been initialized, in which case do so below + */ + + if (av->max_fast != 0) { + clear_fastchunks(av); + + unsorted_bin = unsorted_chunks(av); + + /* + Remove each chunk from fast bin and consolidate it, placing it + then in unsorted bin. Among other reasons for doing this, + placing in unsorted bin avoids needing to calculate actual bins + until malloc is sure that chunks aren't immediately going to be + reused anyway. + */ + + maxfb = &(av->fastbins[fastbin_index(av->max_fast)]); + fb = &(av->fastbins[0]); + do { + if ( (p = *fb) != 0) { + *fb = 0; + + do { + check_inuse_chunk(p); + nextp = p->fd; + + /* Slightly streamlined version of consolidation code in free() */ + size = p->size & ~PREV_INUSE; + nextchunk = chunk_at_offset(p, size); + nextsize = chunksize(nextchunk); + + if (!prev_inuse(p)) { + prevsize = p->prev_size; + size += prevsize; + p = chunk_at_offset(p, -((long) prevsize)); + unlink(p, bck, fwd); + } + + if (nextchunk != av->top) { + nextinuse = inuse_bit_at_offset(nextchunk, nextsize); + set_head(nextchunk, nextsize); + + if (!nextinuse) { + size += nextsize; + unlink(nextchunk, bck, fwd); + } + + first_unsorted = unsorted_bin->fd; + unsorted_bin->fd = p; + first_unsorted->bk = p; + + set_head(p, size | PREV_INUSE); + p->bk = unsorted_bin; + p->fd = first_unsorted; + set_foot(p, size); + } + + else { + size += nextsize; + set_head(p, size | PREV_INUSE); + av->top = p; + } + + } while ( (p = nextp) != 0); + + } + } while (fb++ != maxfb); + } + else { + malloc_init_state(av); + check_malloc_state(); + } +} + + +/* ------------------------------ free ------------------------------ */ +void free(void* mem) +{ + mstate av; + + mchunkptr p; /* chunk corresponding to mem */ + size_t size; /* its size */ + mfastbinptr* fb; /* associated fastbin */ + mchunkptr nextchunk; /* next contiguous chunk */ + size_t nextsize; /* its size */ + int nextinuse; /* true if nextchunk is used */ + size_t prevsize; /* size of previous contiguous chunk */ + mchunkptr bck; /* misc temp for linking */ + mchunkptr fwd; /* misc temp for linking */ + + /* free(0) has no effect */ + if (mem == NULL) + return; + + __MALLOC_LOCK; + av = get_malloc_state(); + p = mem2chunk(mem); + size = chunksize(p); + + check_inuse_chunk(p); + + /* + If eligible, place chunk on a fastbin so it can be found + and used quickly in malloc. + */ + + if ((unsigned long)(size) <= (unsigned long)(av->max_fast) + +#if TRIM_FASTBINS + /* If TRIM_FASTBINS set, don't place chunks + bordering top into fastbins */ + && (chunk_at_offset(p, size) != av->top) +#endif + ) { + + set_fastchunks(av); + fb = &(av->fastbins[fastbin_index(size)]); + p->fd = *fb; + *fb = p; + } + + /* + Consolidate other non-mmapped chunks as they arrive. + */ + + else if (!chunk_is_mmapped(p)) { + set_anychunks(av); + + nextchunk = chunk_at_offset(p, size); + nextsize = chunksize(nextchunk); + + /* consolidate backward */ + if (!prev_inuse(p)) { + prevsize = p->prev_size; + size += prevsize; + p = chunk_at_offset(p, -((long) prevsize)); + unlink(p, bck, fwd); + } + + if (nextchunk != av->top) { + /* get and clear inuse bit */ + nextinuse = inuse_bit_at_offset(nextchunk, nextsize); + set_head(nextchunk, nextsize); + + /* consolidate forward */ + if (!nextinuse) { + unlink(nextchunk, bck, fwd); + size += nextsize; + } + + /* + Place the chunk in unsorted chunk list. Chunks are + not placed into regular bins until after they have + been given one chance to be used in malloc. + */ + + bck = unsorted_chunks(av); + fwd = bck->fd; + p->bk = bck; + p->fd = fwd; + bck->fd = p; + fwd->bk = p; + + set_head(p, size | PREV_INUSE); + set_foot(p, size); + + check_free_chunk(p); + } + + /* + If the chunk borders the current high end of memory, + consolidate into top + */ + + else { + size += nextsize; + set_head(p, size | PREV_INUSE); + av->top = p; + check_chunk(p); + } + + /* + If freeing a large space, consolidate possibly-surrounding + chunks. Then, if the total unused topmost memory exceeds trim + threshold, ask malloc_trim to reduce top. + + Unless max_fast is 0, we don't know if there are fastbins + bordering top, so we cannot tell for sure whether threshold + has been reached unless fastbins are consolidated. But we + don't want to consolidate on each free. As a compromise, + consolidation is performed if FASTBIN_CONSOLIDATION_THRESHOLD + is reached. + */ + + if ((unsigned long)(size) >= FASTBIN_CONSOLIDATION_THRESHOLD) { + if (have_fastchunks(av)) + __malloc_consolidate(av); + + if ((unsigned long)(chunksize(av->top)) >= + (unsigned long)(av->trim_threshold)) + __malloc_trim(av->top_pad, av); + } + + } + /* + If the chunk was allocated via mmap, release via munmap() + Note that if HAVE_MMAP is false but chunk_is_mmapped is + true, then user must have overwritten memory. There's nothing + we can do to catch this error unless DEBUG is set, in which case + check_inuse_chunk (above) will have triggered error. + */ + + else { + size_t offset = p->prev_size; + av->n_mmaps--; + av->mmapped_mem -= (size + offset); + munmap((char*)p - offset, size + offset); + } + __MALLOC_UNLOCK; +} + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc-standard/mallinfo.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc-standard/mallinfo.c new file mode 100644 index 00000000..d60d6d9b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc-standard/mallinfo.c @@ -0,0 +1,124 @@ +/* + This is a version (aka dlmalloc) of malloc/free/realloc written by + Doug Lea and released to the public domain. Use, modify, and + redistribute this code without permission or acknowledgement in any + way you wish. Send questions, comments, complaints, performance + data, etc to dl@cs.oswego.edu + + VERSION 2.7.2 Sat Aug 17 09:07:30 2002 Doug Lea (dl at gee) + + Note: There may be an updated version of this malloc obtainable at + ftp://gee.cs.oswego.edu/pub/misc/malloc.c + Check before installing! + + Hacked up for uClibc by Erik Andersen +*/ + +#include "malloc.h" + + +/* ------------------------------ mallinfo ------------------------------ */ +struct mallinfo mallinfo(void) +{ + mstate av; + struct mallinfo mi; + unsigned int i; + mbinptr b; + mchunkptr p; + size_t avail; + size_t fastavail; + int nblocks; + int nfastblocks; + + __MALLOC_LOCK; + av = get_malloc_state(); + /* Ensure initialization */ + if (av->top == 0) { + __malloc_consolidate(av); + } + + check_malloc_state(); + + /* Account for top */ + avail = chunksize(av->top); + nblocks = 1; /* top always exists */ + + /* traverse fastbins */ + nfastblocks = 0; + fastavail = 0; + + for (i = 0; i < NFASTBINS; ++i) { + for (p = av->fastbins[i]; p != 0; p = p->fd) { + ++nfastblocks; + fastavail += chunksize(p); + } + } + + avail += fastavail; + + /* traverse regular bins */ + for (i = 1; i < NBINS; ++i) { + b = bin_at(av, i); + for (p = last(b); p != b; p = p->bk) { + ++nblocks; + avail += chunksize(p); + } + } + + mi.smblks = nfastblocks; + mi.ordblks = nblocks; + mi.fordblks = avail; + mi.uordblks = av->sbrked_mem - avail; + mi.arena = av->sbrked_mem; + mi.hblks = av->n_mmaps; + mi.hblkhd = av->mmapped_mem; + mi.fsmblks = fastavail; + mi.keepcost = chunksize(av->top); + mi.usmblks = av->max_total_mem; + __MALLOC_UNLOCK; + return mi; +} +libc_hidden_def(mallinfo) + +void malloc_stats(FILE *file) +{ + struct mallinfo mi; + + if (file==NULL) { + file = stderr; + } + + mi = mallinfo(); + fprintf(file, + "total bytes allocated = %10u\n" + "total bytes in use bytes = %10u\n" + "total non-mmapped bytes allocated = %10d\n" + "number of mmapped regions = %10d\n" + "total allocated mmap space = %10d\n" + "total allocated sbrk space = %10d\n" +#if 0 + "number of free chunks = %10d\n" + "number of fastbin blocks = %10d\n" + "space in freed fastbin blocks = %10d\n" +#endif + "maximum total allocated space = %10d\n" + "total free space = %10d\n" + "memory releasable via malloc_trim = %10d\n", + + (unsigned int)(mi.arena + mi.hblkhd), + (unsigned int)(mi.uordblks + mi.hblkhd), + mi.arena, + mi.hblks, + mi.hblkhd, + mi.uordblks, +#if 0 + mi.ordblks, + mi.smblks, + mi.fsmblks, +#endif + mi.usmblks, + mi.fordblks, + mi.keepcost + ); +} + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc-standard/malloc.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc-standard/malloc.c new file mode 100644 index 00000000..3253ebda --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc-standard/malloc.c @@ -0,0 +1,1167 @@ +/* + This is a version (aka dlmalloc) of malloc/free/realloc written by + Doug Lea and released to the public domain. Use, modify, and + redistribute this code without permission or acknowledgement in any + way you wish. Send questions, comments, complaints, performance + data, etc to dl@cs.oswego.edu + + VERSION 2.7.2 Sat Aug 17 09:07:30 2002 Doug Lea (dl at gee) + + Note: There may be an updated version of this malloc obtainable at + ftp://gee.cs.oswego.edu/pub/misc/malloc.c + Check before installing! + + Hacked up for uClibc by Erik Andersen +*/ + +#include "malloc.h" + + +__UCLIBC_MUTEX_INIT(__malloc_lock, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP); + +/* + There is exactly one instance of this struct in this malloc. + If you are adapting this malloc in a way that does NOT use a static + malloc_state, you MUST explicitly zero-fill it before using. This + malloc relies on the property that malloc_state is initialized to + all zeroes (as is true of C statics). +*/ +struct malloc_state __malloc_state; /* never directly referenced */ + +/* forward declaration */ +static int __malloc_largebin_index(unsigned int sz); + +#ifdef __UCLIBC_MALLOC_DEBUGGING__ + +/* + Debugging support + + Because freed chunks may be overwritten with bookkeeping fields, this + malloc will often die when freed memory is overwritten by user + programs. This can be very effective (albeit in an annoying way) + in helping track down dangling pointers. + + If you compile with __UCLIBC_MALLOC_DEBUGGING__, a number of assertion checks are + enabled that will catch more memory errors. You probably won't be + able to make much sense of the actual assertion errors, but they + should help you locate incorrectly overwritten memory. The + checking is fairly extensive, and will slow down execution + noticeably. Calling malloc_stats or mallinfo with __UCLIBC_MALLOC_DEBUGGING__ set will + attempt to check every non-mmapped allocated and free chunk in the + course of computing the summmaries. (By nature, mmapped regions + cannot be checked very much automatically.) + + Setting __UCLIBC_MALLOC_DEBUGGING__ may also be helpful if you are trying to modify + this code. The assertions in the check routines spell out in more + detail the assumptions and invariants underlying the algorithms. + + Setting __UCLIBC_MALLOC_DEBUGGING__ does NOT provide an automated mechanism for checking + that all accesses to malloced memory stay within their + bounds. However, there are several add-ons and adaptations of this + or other mallocs available that do this. +*/ + +/* Properties of all chunks */ +void __do_check_chunk(mchunkptr p) +{ + mstate av = get_malloc_state(); +#ifdef __DOASSERTS__ + /* min and max possible addresses assuming contiguous allocation */ + char* max_address = (char*)(av->top) + chunksize(av->top); + char* min_address = max_address - av->sbrked_mem; + unsigned long sz = chunksize(p); +#endif + + if (!chunk_is_mmapped(p)) { + + /* Has legal address ... */ + if (p != av->top) { + if (contiguous(av)) { + assert(((char*)p) >= min_address); + assert(((char*)p + sz) <= ((char*)(av->top))); + } + } + else { + /* top size is always at least MINSIZE */ + assert((unsigned long)(sz) >= MINSIZE); + /* top predecessor always marked inuse */ + assert(prev_inuse(p)); + } + + } + else { + /* address is outside main heap */ + if (contiguous(av) && av->top != initial_top(av)) { + assert(((char*)p) < min_address || ((char*)p) > max_address); + } + /* chunk is page-aligned */ + assert(((p->prev_size + sz) & (av->pagesize-1)) == 0); + /* mem is aligned */ + assert(aligned_OK(chunk2mem(p))); + } +} + +/* Properties of free chunks */ +void __do_check_free_chunk(mchunkptr p) +{ + size_t sz = p->size & ~PREV_INUSE; +#ifdef __DOASSERTS__ + mstate av = get_malloc_state(); + mchunkptr next = chunk_at_offset(p, sz); +#endif + + __do_check_chunk(p); + + /* Chunk must claim to be free ... */ + assert(!inuse(p)); + assert (!chunk_is_mmapped(p)); + + /* Unless a special marker, must have OK fields */ + if ((unsigned long)(sz) >= MINSIZE) + { + assert((sz & MALLOC_ALIGN_MASK) == 0); + assert(aligned_OK(chunk2mem(p))); + /* ... matching footer field */ + assert(next->prev_size == sz); + /* ... and is fully consolidated */ + assert(prev_inuse(p)); + assert (next == av->top || inuse(next)); + + /* ... and has minimally sane links */ + assert(p->fd->bk == p); + assert(p->bk->fd == p); + } + else /* markers are always of size (sizeof(size_t)) */ + assert(sz == (sizeof(size_t))); +} + +/* Properties of inuse chunks */ +void __do_check_inuse_chunk(mchunkptr p) +{ + mstate av = get_malloc_state(); + mchunkptr next; + __do_check_chunk(p); + + if (chunk_is_mmapped(p)) + return; /* mmapped chunks have no next/prev */ + + /* Check whether it claims to be in use ... */ + assert(inuse(p)); + + next = next_chunk(p); + + /* ... and is surrounded by OK chunks. + Since more things can be checked with free chunks than inuse ones, + if an inuse chunk borders them and debug is on, it's worth doing them. + */ + if (!prev_inuse(p)) { + /* Note that we cannot even look at prev unless it is not inuse */ + mchunkptr prv = prev_chunk(p); + assert(next_chunk(prv) == p); + __do_check_free_chunk(prv); + } + + if (next == av->top) { + assert(prev_inuse(next)); + assert(chunksize(next) >= MINSIZE); + } + else if (!inuse(next)) + __do_check_free_chunk(next); +} + +/* Properties of chunks recycled from fastbins */ +void __do_check_remalloced_chunk(mchunkptr p, size_t s) +{ +#ifdef __DOASSERTS__ + size_t sz = p->size & ~PREV_INUSE; +#endif + + __do_check_inuse_chunk(p); + + /* Legal size ... */ + assert((sz & MALLOC_ALIGN_MASK) == 0); + assert((unsigned long)(sz) >= MINSIZE); + /* ... and alignment */ + assert(aligned_OK(chunk2mem(p))); + /* chunk is less than MINSIZE more than request */ + assert((long)(sz) - (long)(s) >= 0); + assert((long)(sz) - (long)(s + MINSIZE) < 0); +} + +/* Properties of nonrecycled chunks at the point they are malloced */ +void __do_check_malloced_chunk(mchunkptr p, size_t s) +{ + /* same as recycled case ... */ + __do_check_remalloced_chunk(p, s); + + /* + ... plus, must obey implementation invariant that prev_inuse is + always true of any allocated chunk; i.e., that each allocated + chunk borders either a previously allocated and still in-use + chunk, or the base of its memory arena. This is ensured + by making all allocations from the the `lowest' part of any found + chunk. This does not necessarily hold however for chunks + recycled via fastbins. + */ + + assert(prev_inuse(p)); +} + + +/* + Properties of malloc_state. + + This may be useful for debugging malloc, as well as detecting user + programmer errors that somehow write into malloc_state. + + If you are extending or experimenting with this malloc, you can + probably figure out how to hack this routine to print out or + display chunk addresses, sizes, bins, and other instrumentation. +*/ +void __do_check_malloc_state(void) +{ + mstate av = get_malloc_state(); + int i; + mchunkptr p; + mchunkptr q; + mbinptr b; + unsigned int binbit; + int empty; + unsigned int idx; + size_t size; + unsigned long total = 0; + int max_fast_bin; + + /* internal size_t must be no wider than pointer type */ + assert(sizeof(size_t) <= sizeof(char*)); + + /* alignment is a power of 2 */ + assert((MALLOC_ALIGNMENT & (MALLOC_ALIGNMENT-1)) == 0); + + /* cannot run remaining checks until fully initialized */ + if (av->top == 0 || av->top == initial_top(av)) + return; + + /* pagesize is a power of 2 */ + assert((av->pagesize & (av->pagesize-1)) == 0); + + /* properties of fastbins */ + + /* max_fast is in allowed range */ + assert(get_max_fast(av) <= request2size(MAX_FAST_SIZE)); + + max_fast_bin = fastbin_index(av->max_fast); + + for (i = 0; i < NFASTBINS; ++i) { + p = av->fastbins[i]; + + /* all bins past max_fast are empty */ + if (i > max_fast_bin) + assert(p == 0); + + while (p != 0) { + /* each chunk claims to be inuse */ + __do_check_inuse_chunk(p); + total += chunksize(p); + /* chunk belongs in this bin */ + assert(fastbin_index(chunksize(p)) == i); + p = p->fd; + } + } + + if (total != 0) + assert(have_fastchunks(av)); + else if (!have_fastchunks(av)) + assert(total == 0); + + /* check normal bins */ + for (i = 1; i < NBINS; ++i) { + b = bin_at(av,i); + + /* binmap is accurate (except for bin 1 == unsorted_chunks) */ + if (i >= 2) { + binbit = get_binmap(av,i); + empty = last(b) == b; + if (!binbit) + assert(empty); + else if (!empty) + assert(binbit); + } + + for (p = last(b); p != b; p = p->bk) { + /* each chunk claims to be free */ + __do_check_free_chunk(p); + size = chunksize(p); + total += size; + if (i >= 2) { + /* chunk belongs in bin */ + idx = bin_index(size); + assert(idx == i); + /* lists are sorted */ + if ((unsigned long) size >= (unsigned long)(FIRST_SORTED_BIN_SIZE)) { + assert(p->bk == b || + (unsigned long)chunksize(p->bk) >= + (unsigned long)chunksize(p)); + } + } + /* chunk is followed by a legal chain of inuse chunks */ + for (q = next_chunk(p); + (q != av->top && inuse(q) && + (unsigned long)(chunksize(q)) >= MINSIZE); + q = next_chunk(q)) + __do_check_inuse_chunk(q); + } + } + + /* top chunk is OK */ + __do_check_chunk(av->top); + + /* sanity checks for statistics */ + + assert(total <= (unsigned long)(av->max_total_mem)); + assert(av->n_mmaps >= 0); + assert(av->n_mmaps <= av->max_n_mmaps); + + assert((unsigned long)(av->sbrked_mem) <= + (unsigned long)(av->max_sbrked_mem)); + + assert((unsigned long)(av->mmapped_mem) <= + (unsigned long)(av->max_mmapped_mem)); + + assert((unsigned long)(av->max_total_mem) >= + (unsigned long)(av->mmapped_mem) + (unsigned long)(av->sbrked_mem)); +} +#endif + + +/* ----------- Routines dealing with system allocation -------------- */ + +/* + sysmalloc handles malloc cases requiring more memory from the system. + On entry, it is assumed that av->top does not have enough + space to service request for nb bytes, thus requiring that av->top + be extended or replaced. +*/ +static void* __malloc_alloc(size_t nb, mstate av) +{ + mchunkptr old_top; /* incoming value of av->top */ + size_t old_size; /* its size */ + char* old_end; /* its end address */ + + long size; /* arg to first MORECORE or mmap call */ + char* fst_brk; /* return value from MORECORE */ + + long correction; /* arg to 2nd MORECORE call */ + char* snd_brk; /* 2nd return val */ + + size_t front_misalign; /* unusable bytes at front of new space */ + size_t end_misalign; /* partial page left at end of new space */ + char* aligned_brk; /* aligned offset into brk */ + + mchunkptr p; /* the allocated/returned chunk */ + mchunkptr remainder; /* remainder from allocation */ + unsigned long remainder_size; /* its size */ + + unsigned long sum; /* for updating stats */ + + size_t pagemask = av->pagesize - 1; + + /* + If there is space available in fastbins, consolidate and retry + malloc from scratch rather than getting memory from system. This + can occur only if nb is in smallbin range so we didn't consolidate + upon entry to malloc. It is much easier to handle this case here + than in malloc proper. + */ + + if (have_fastchunks(av)) { + assert(in_smallbin_range(nb)); + __malloc_consolidate(av); + return malloc(nb - MALLOC_ALIGN_MASK); + } + + + /* + If have mmap, and the request size meets the mmap threshold, and + the system supports mmap, and there are few enough currently + allocated mmapped regions, try to directly map this request + rather than expanding top. + */ + + if ((unsigned long)(nb) >= (unsigned long)(av->mmap_threshold) && + (av->n_mmaps < av->n_mmaps_max)) { + + char* mm; /* return value from mmap call*/ + + /* + Round up size to nearest page. For mmapped chunks, the overhead + is one (sizeof(size_t)) unit larger than for normal chunks, because there + is no following chunk whose prev_size field could be used. + */ + size = (nb + (sizeof(size_t)) + MALLOC_ALIGN_MASK + pagemask) & ~pagemask; + + /* Don't try if size wraps around 0 */ + if ((unsigned long)(size) > (unsigned long)(nb)) { + + mm = (char*)(MMAP(0, size, PROT_READ|PROT_WRITE)); + + if (mm != (char*)(MORECORE_FAILURE)) { + + /* + The offset to the start of the mmapped region is stored + in the prev_size field of the chunk. This allows us to adjust + returned start address to meet alignment requirements here + and in memalign(), and still be able to compute proper + address argument for later munmap in free() and realloc(). + */ + + front_misalign = (size_t)chunk2mem(mm) & MALLOC_ALIGN_MASK; + if (front_misalign > 0) { + correction = MALLOC_ALIGNMENT - front_misalign; + p = (mchunkptr)(mm + correction); + p->prev_size = correction; + set_head(p, (size - correction) |IS_MMAPPED); + } + else { + p = (mchunkptr)mm; + p->prev_size = 0; + set_head(p, size|IS_MMAPPED); + } + + /* update statistics */ + + if (++av->n_mmaps > av->max_n_mmaps) + av->max_n_mmaps = av->n_mmaps; + + sum = av->mmapped_mem += size; + if (sum > (unsigned long)(av->max_mmapped_mem)) + av->max_mmapped_mem = sum; + sum += av->sbrked_mem; + if (sum > (unsigned long)(av->max_total_mem)) + av->max_total_mem = sum; + + check_chunk(p); + + return chunk2mem(p); + } + } + } + + /* Record incoming configuration of top */ + + old_top = av->top; + old_size = chunksize(old_top); + old_end = (char*)(chunk_at_offset(old_top, old_size)); + + fst_brk = snd_brk = (char*)(MORECORE_FAILURE); + + /* If not the first time through, we require old_size to + * be at least MINSIZE and to have prev_inuse set. */ + + assert((old_top == initial_top(av) && old_size == 0) || + ((unsigned long) (old_size) >= MINSIZE && + prev_inuse(old_top))); + + /* Precondition: not enough current space to satisfy nb request */ + assert((unsigned long)(old_size) < (unsigned long)(nb + MINSIZE)); + + /* Precondition: all fastbins are consolidated */ + assert(!have_fastchunks(av)); + + + /* Request enough space for nb + pad + overhead */ + + size = nb + av->top_pad + MINSIZE; + + /* + If contiguous, we can subtract out existing space that we hope to + combine with new space. We add it back later only if + we don't actually get contiguous space. + */ + + if (contiguous(av)) + size -= old_size; + + /* + Round to a multiple of page size. + If MORECORE is not contiguous, this ensures that we only call it + with whole-page arguments. And if MORECORE is contiguous and + this is not first time through, this preserves page-alignment of + previous calls. Otherwise, we correct to page-align below. + */ + + size = (size + pagemask) & ~pagemask; + + /* + Don't try to call MORECORE if argument is so big as to appear + negative. Note that since mmap takes size_t arg, it may succeed + below even if we cannot call MORECORE. + */ + + if (size > 0) + fst_brk = (char*)(MORECORE(size)); + + /* + If have mmap, try using it as a backup when MORECORE fails or + cannot be used. This is worth doing on systems that have "holes" in + address space, so sbrk cannot extend to give contiguous space, but + space is available elsewhere. Note that we ignore mmap max count + and threshold limits, since the space will not be used as a + segregated mmap region. + */ + + if (fst_brk == (char*)(MORECORE_FAILURE)) { + + /* Cannot merge with old top, so add its size back in */ + if (contiguous(av)) + size = (size + old_size + pagemask) & ~pagemask; + + /* If we are relying on mmap as backup, then use larger units */ + if ((unsigned long)(size) < (unsigned long)(MMAP_AS_MORECORE_SIZE)) + size = MMAP_AS_MORECORE_SIZE; + + /* Don't try if size wraps around 0 */ + if ((unsigned long)(size) > (unsigned long)(nb)) { + + fst_brk = (char*)(MMAP(0, size, PROT_READ|PROT_WRITE)); + + if (fst_brk != (char*)(MORECORE_FAILURE)) { + + /* We do not need, and cannot use, another sbrk call to find end */ + snd_brk = fst_brk + size; + + /* Record that we no longer have a contiguous sbrk region. + After the first time mmap is used as backup, we do not + ever rely on contiguous space since this could incorrectly + bridge regions. + */ + set_noncontiguous(av); + } + } + } + + if (fst_brk != (char*)(MORECORE_FAILURE)) { + av->sbrked_mem += size; + + /* + If MORECORE extends previous space, we can likewise extend top size. + */ + + if (fst_brk == old_end && snd_brk == (char*)(MORECORE_FAILURE)) { + set_head(old_top, (size + old_size) | PREV_INUSE); + } + + /* + Otherwise, make adjustments: + + * If the first time through or noncontiguous, we need to call sbrk + just to find out where the end of memory lies. + + * We need to ensure that all returned chunks from malloc will meet + MALLOC_ALIGNMENT + + * If there was an intervening foreign sbrk, we need to adjust sbrk + request size to account for fact that we will not be able to + combine new space with existing space in old_top. + + * Almost all systems internally allocate whole pages at a time, in + which case we might as well use the whole last page of request. + So we allocate enough more memory to hit a page boundary now, + which in turn causes future contiguous calls to page-align. + */ + + else { + front_misalign = 0; + end_misalign = 0; + correction = 0; + aligned_brk = fst_brk; + + /* + If MORECORE returns an address lower than we have seen before, + we know it isn't really contiguous. This and some subsequent + checks help cope with non-conforming MORECORE functions and + the presence of "foreign" calls to MORECORE from outside of + malloc or by other threads. We cannot guarantee to detect + these in all cases, but cope with the ones we do detect. + */ + if (contiguous(av) && old_size != 0 && fst_brk < old_end) { + set_noncontiguous(av); + } + + /* handle contiguous cases */ + if (contiguous(av)) { + + /* We can tolerate forward non-contiguities here (usually due + to foreign calls) but treat them as part of our space for + stats reporting. */ + if (old_size != 0) + av->sbrked_mem += fst_brk - old_end; + + /* Guarantee alignment of first new chunk made from this space */ + + front_misalign = (size_t)chunk2mem(fst_brk) & MALLOC_ALIGN_MASK; + if (front_misalign > 0) { + + /* + Skip over some bytes to arrive at an aligned position. + We don't need to specially mark these wasted front bytes. + They will never be accessed anyway because + prev_inuse of av->top (and any chunk created from its start) + is always true after initialization. + */ + + correction = MALLOC_ALIGNMENT - front_misalign; + aligned_brk += correction; + } + + /* + If this isn't adjacent to existing space, then we will not + be able to merge with old_top space, so must add to 2nd request. + */ + + correction += old_size; + + /* Extend the end address to hit a page boundary */ + end_misalign = (size_t)(fst_brk + size + correction); + correction += ((end_misalign + pagemask) & ~pagemask) - end_misalign; + + assert(correction >= 0); + snd_brk = (char*)(MORECORE(correction)); + + if (snd_brk == (char*)(MORECORE_FAILURE)) { + /* + If can't allocate correction, try to at least find out current + brk. It might be enough to proceed without failing. + */ + correction = 0; + snd_brk = (char*)(MORECORE(0)); + } + else if (snd_brk < fst_brk) { + /* + If the second call gives noncontiguous space even though + it says it won't, the only course of action is to ignore + results of second call, and conservatively estimate where + the first call left us. Also set noncontiguous, so this + won't happen again, leaving at most one hole. + + Note that this check is intrinsically incomplete. Because + MORECORE is allowed to give more space than we ask for, + there is no reliable way to detect a noncontiguity + producing a forward gap for the second call. + */ + snd_brk = fst_brk + size; + correction = 0; + set_noncontiguous(av); + } + + } + + /* handle non-contiguous cases */ + else { + /* MORECORE/mmap must correctly align */ + assert(aligned_OK(chunk2mem(fst_brk))); + + /* Find out current end of memory */ + if (snd_brk == (char*)(MORECORE_FAILURE)) { + snd_brk = (char*)(MORECORE(0)); + av->sbrked_mem += snd_brk - fst_brk - size; + } + } + + /* Adjust top based on results of second sbrk */ + if (snd_brk != (char*)(MORECORE_FAILURE)) { + av->top = (mchunkptr)aligned_brk; + set_head(av->top, (snd_brk - aligned_brk + correction) | PREV_INUSE); + av->sbrked_mem += correction; + + /* + If not the first time through, we either have a + gap due to foreign sbrk or a non-contiguous region. Insert a + double fencepost at old_top to prevent consolidation with space + we don't own. These fenceposts are artificial chunks that are + marked as inuse and are in any case too small to use. We need + two to make sizes and alignments work out. + */ + + if (old_size != 0) { + /* Shrink old_top to insert fenceposts, keeping size a + multiple of MALLOC_ALIGNMENT. We know there is at least + enough space in old_top to do this. + */ + old_size = (old_size - 3*(sizeof(size_t))) & ~MALLOC_ALIGN_MASK; + set_head(old_top, old_size | PREV_INUSE); + + /* + Note that the following assignments completely overwrite + old_top when old_size was previously MINSIZE. This is + intentional. We need the fencepost, even if old_top otherwise gets + lost. + */ + chunk_at_offset(old_top, old_size )->size = + (sizeof(size_t))|PREV_INUSE; + + chunk_at_offset(old_top, old_size + (sizeof(size_t)))->size = + (sizeof(size_t))|PREV_INUSE; + + /* If possible, release the rest, suppressing trimming. */ + if (old_size >= MINSIZE) { + size_t tt = av->trim_threshold; + av->trim_threshold = (size_t)(-1); + free(chunk2mem(old_top)); + av->trim_threshold = tt; + } + } + } + } + + /* Update statistics */ + sum = av->sbrked_mem; + if (sum > (unsigned long)(av->max_sbrked_mem)) + av->max_sbrked_mem = sum; + + sum += av->mmapped_mem; + if (sum > (unsigned long)(av->max_total_mem)) + av->max_total_mem = sum; + + check_malloc_state(); + + /* finally, do the allocation */ + + p = av->top; + size = chunksize(p); + + /* check that one of the above allocation paths succeeded */ + if ((unsigned long)(size) >= (unsigned long)(nb + MINSIZE)) { + remainder_size = size - nb; + remainder = chunk_at_offset(p, nb); + av->top = remainder; + set_head(p, nb | PREV_INUSE); + set_head(remainder, remainder_size | PREV_INUSE); + check_malloced_chunk(p, nb); + return chunk2mem(p); + } + + } + + /* catch all failure paths */ + errno = ENOMEM; + return 0; +} + + +/* + Compute index for size. We expect this to be inlined when + compiled with optimization, else not, which works out well. +*/ +static int __malloc_largebin_index(unsigned int sz) +{ + unsigned int x = sz >> SMALLBIN_WIDTH; + unsigned int m; /* bit position of highest set bit of m */ + + if (x >= 0x10000) return NBINS-1; + + /* On intel, use BSRL instruction to find highest bit */ +#if defined(__GNUC__) && defined(i386) + + __asm__("bsrl %1,%0\n\t" + : "=r" (m) + : "g" (x)); + +#else + { + /* + Based on branch-free nlz algorithm in chapter 5 of Henry + S. Warren Jr's book "Hacker's Delight". + */ + + unsigned int n = ((x - 0x100) >> 16) & 8; + x <<= n; + m = ((x - 0x1000) >> 16) & 4; + n += m; + x <<= m; + m = ((x - 0x4000) >> 16) & 2; + n += m; + x = (x << m) >> 14; + m = 13 - n + (x & ~(x>>1)); + } +#endif + + /* Use next 2 bits to create finer-granularity bins */ + return NSMALLBINS + (m << 2) + ((sz >> (m + 6)) & 3); +} + + + +/* ---------------------------------------------------------------------- + * + * PUBLIC STUFF + * + * ----------------------------------------------------------------------*/ + + +/* ------------------------------ malloc ------------------------------ */ +void* malloc(size_t bytes) +{ + mstate av; + + size_t nb; /* normalized request size */ + unsigned int idx; /* associated bin index */ + mbinptr bin; /* associated bin */ + mfastbinptr* fb; /* associated fastbin */ + + mchunkptr victim; /* inspected/selected chunk */ + size_t size; /* its size */ + int victim_index; /* its bin index */ + + mchunkptr remainder; /* remainder from a split */ + unsigned long remainder_size; /* its size */ + + unsigned int block; /* bit map traverser */ + unsigned int bit; /* bit map traverser */ + unsigned int map; /* current word of binmap */ + + mchunkptr fwd; /* misc temp for linking */ + mchunkptr bck; /* misc temp for linking */ + void * sysmem; + void * retval; + +#if !defined(__MALLOC_GLIBC_COMPAT__) + if (!bytes) { + __set_errno(ENOMEM); + return NULL; + } +#endif + + __MALLOC_LOCK; + av = get_malloc_state(); + /* + Convert request size to internal form by adding (sizeof(size_t)) bytes + overhead plus possibly more to obtain necessary alignment and/or + to obtain a size of at least MINSIZE, the smallest allocatable + size. Also, checked_request2size traps (returning 0) request sizes + that are so large that they wrap around zero when padded and + aligned. + */ + + checked_request2size(bytes, nb); + + /* + Bypass search if no frees yet + */ + if (!have_anychunks(av)) { + if (av->max_fast == 0) /* initialization check */ + __malloc_consolidate(av); + goto use_top; + } + + /* + If the size qualifies as a fastbin, first check corresponding bin. + */ + + if ((unsigned long)(nb) <= (unsigned long)(av->max_fast)) { + fb = &(av->fastbins[(fastbin_index(nb))]); + if ( (victim = *fb) != 0) { + *fb = victim->fd; + check_remalloced_chunk(victim, nb); + retval = chunk2mem(victim); + goto DONE; + } + } + + /* + If a small request, check regular bin. Since these "smallbins" + hold one size each, no searching within bins is necessary. + (For a large request, we need to wait until unsorted chunks are + processed to find best fit. But for small ones, fits are exact + anyway, so we can check now, which is faster.) + */ + + if (in_smallbin_range(nb)) { + idx = smallbin_index(nb); + bin = bin_at(av,idx); + + if ( (victim = last(bin)) != bin) { + bck = victim->bk; + set_inuse_bit_at_offset(victim, nb); + bin->bk = bck; + bck->fd = bin; + + check_malloced_chunk(victim, nb); + retval = chunk2mem(victim); + goto DONE; + } + } + + /* If this is a large request, consolidate fastbins before continuing. + While it might look excessive to kill all fastbins before + even seeing if there is space available, this avoids + fragmentation problems normally associated with fastbins. + Also, in practice, programs tend to have runs of either small or + large requests, but less often mixtures, so consolidation is not + invoked all that often in most programs. And the programs that + it is called frequently in otherwise tend to fragment. + */ + + else { + idx = __malloc_largebin_index(nb); + if (have_fastchunks(av)) + __malloc_consolidate(av); + } + + /* + Process recently freed or remaindered chunks, taking one only if + it is exact fit, or, if this a small request, the chunk is remainder from + the most recent non-exact fit. Place other traversed chunks in + bins. Note that this step is the only place in any routine where + chunks are placed in bins. + */ + + while ( (victim = unsorted_chunks(av)->bk) != unsorted_chunks(av)) { + bck = victim->bk; + size = chunksize(victim); + + /* If a small request, try to use last remainder if it is the + only chunk in unsorted bin. This helps promote locality for + runs of consecutive small requests. This is the only + exception to best-fit, and applies only when there is + no exact fit for a small chunk. + */ + + if (in_smallbin_range(nb) && + bck == unsorted_chunks(av) && + victim == av->last_remainder && + (unsigned long)(size) > (unsigned long)(nb + MINSIZE)) { + + /* split and reattach remainder */ + remainder_size = size - nb; + remainder = chunk_at_offset(victim, nb); + unsorted_chunks(av)->bk = unsorted_chunks(av)->fd = remainder; + av->last_remainder = remainder; + remainder->bk = remainder->fd = unsorted_chunks(av); + + set_head(victim, nb | PREV_INUSE); + set_head(remainder, remainder_size | PREV_INUSE); + set_foot(remainder, remainder_size); + + check_malloced_chunk(victim, nb); + retval = chunk2mem(victim); + goto DONE; + } + + /* remove from unsorted list */ + unsorted_chunks(av)->bk = bck; + bck->fd = unsorted_chunks(av); + + /* Take now instead of binning if exact fit */ + + if (size == nb) { + set_inuse_bit_at_offset(victim, size); + check_malloced_chunk(victim, nb); + retval = chunk2mem(victim); + goto DONE; + } + + /* place chunk in bin */ + + if (in_smallbin_range(size)) { + victim_index = smallbin_index(size); + bck = bin_at(av, victim_index); + fwd = bck->fd; + } + else { + victim_index = __malloc_largebin_index(size); + bck = bin_at(av, victim_index); + fwd = bck->fd; + + if (fwd != bck) { + /* if smaller than smallest, place first */ + if ((unsigned long)(size) < (unsigned long)(bck->bk->size)) { + fwd = bck; + bck = bck->bk; + } + else if ((unsigned long)(size) >= + (unsigned long)(FIRST_SORTED_BIN_SIZE)) { + + /* maintain large bins in sorted order */ + size |= PREV_INUSE; /* Or with inuse bit to speed comparisons */ + while ((unsigned long)(size) < (unsigned long)(fwd->size)) + fwd = fwd->fd; + bck = fwd->bk; + } + } + } + + mark_bin(av, victim_index); + victim->bk = bck; + victim->fd = fwd; + fwd->bk = victim; + bck->fd = victim; + } + + /* + If a large request, scan through the chunks of current bin to + find one that fits. (This will be the smallest that fits unless + FIRST_SORTED_BIN_SIZE has been changed from default.) This is + the only step where an unbounded number of chunks might be + scanned without doing anything useful with them. However the + lists tend to be short. + */ + + if (!in_smallbin_range(nb)) { + bin = bin_at(av, idx); + + for (victim = last(bin); victim != bin; victim = victim->bk) { + size = chunksize(victim); + + if ((unsigned long)(size) >= (unsigned long)(nb)) { + remainder_size = size - nb; + unlink(victim, bck, fwd); + + /* Exhaust */ + if (remainder_size < MINSIZE) { + set_inuse_bit_at_offset(victim, size); + check_malloced_chunk(victim, nb); + retval = chunk2mem(victim); + goto DONE; + } + /* Split */ + else { + remainder = chunk_at_offset(victim, nb); + unsorted_chunks(av)->bk = unsorted_chunks(av)->fd = remainder; + remainder->bk = remainder->fd = unsorted_chunks(av); + set_head(victim, nb | PREV_INUSE); + set_head(remainder, remainder_size | PREV_INUSE); + set_foot(remainder, remainder_size); + check_malloced_chunk(victim, nb); + retval = chunk2mem(victim); + goto DONE; + } + } + } + } + + /* + Search for a chunk by scanning bins, starting with next largest + bin. This search is strictly by best-fit; i.e., the smallest + (with ties going to approximately the least recently used) chunk + that fits is selected. + + The bitmap avoids needing to check that most blocks are nonempty. + */ + + ++idx; + bin = bin_at(av,idx); + block = idx2block(idx); + map = av->binmap[block]; + bit = idx2bit(idx); + + for (;;) { + + /* Skip rest of block if there are no more set bits in this block. */ + if (bit > map || bit == 0) { + do { + if (++block >= BINMAPSIZE) /* out of bins */ + goto use_top; + } while ( (map = av->binmap[block]) == 0); + + bin = bin_at(av, (block << BINMAPSHIFT)); + bit = 1; + } + + /* Advance to bin with set bit. There must be one. */ + while ((bit & map) == 0) { + bin = next_bin(bin); + bit <<= 1; + assert(bit != 0); + } + + /* Inspect the bin. It is likely to be non-empty */ + victim = last(bin); + + /* If a false alarm (empty bin), clear the bit. */ + if (victim == bin) { + av->binmap[block] = map &= ~bit; /* Write through */ + bin = next_bin(bin); + bit <<= 1; + } + + else { + size = chunksize(victim); + + /* We know the first chunk in this bin is big enough to use. */ + assert((unsigned long)(size) >= (unsigned long)(nb)); + + remainder_size = size - nb; + + /* unlink */ + bck = victim->bk; + bin->bk = bck; + bck->fd = bin; + + /* Exhaust */ + if (remainder_size < MINSIZE) { + set_inuse_bit_at_offset(victim, size); + check_malloced_chunk(victim, nb); + retval = chunk2mem(victim); + goto DONE; + } + + /* Split */ + else { + remainder = chunk_at_offset(victim, nb); + + unsorted_chunks(av)->bk = unsorted_chunks(av)->fd = remainder; + remainder->bk = remainder->fd = unsorted_chunks(av); + /* advertise as last remainder */ + if (in_smallbin_range(nb)) + av->last_remainder = remainder; + + set_head(victim, nb | PREV_INUSE); + set_head(remainder, remainder_size | PREV_INUSE); + set_foot(remainder, remainder_size); + check_malloced_chunk(victim, nb); + retval = chunk2mem(victim); + goto DONE; + } + } + } + +use_top: + /* + If large enough, split off the chunk bordering the end of memory + (held in av->top). Note that this is in accord with the best-fit + search rule. In effect, av->top is treated as larger (and thus + less well fitting) than any other available chunk since it can + be extended to be as large as necessary (up to system + limitations). + + We require that av->top always exists (i.e., has size >= + MINSIZE) after initialization, so if it would otherwise be + exhuasted by current request, it is replenished. (The main + reason for ensuring it exists is that we may need MINSIZE space + to put in fenceposts in sysmalloc.) + */ + + victim = av->top; + size = chunksize(victim); + + if ((unsigned long)(size) >= (unsigned long)(nb + MINSIZE)) { + remainder_size = size - nb; + remainder = chunk_at_offset(victim, nb); + av->top = remainder; + set_head(victim, nb | PREV_INUSE); + set_head(remainder, remainder_size | PREV_INUSE); + + check_malloced_chunk(victim, nb); + retval = chunk2mem(victim); + goto DONE; + } + + /* If no space in top, relay to handle system-dependent cases */ + sysmem = __malloc_alloc(nb, av); + retval = sysmem; +DONE: + __MALLOC_UNLOCK; + return retval; +} + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc-standard/malloc.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc-standard/malloc.h new file mode 100644 index 00000000..73d4b124 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc-standard/malloc.h @@ -0,0 +1,959 @@ +/* + This is a version (aka dlmalloc) of malloc/free/realloc written by + Doug Lea and released to the public domain. Use, modify, and + redistribute this code without permission or acknowledgement in any + way you wish. Send questions, comments, complaints, performance + data, etc to dl@cs.oswego.edu + + VERSION 2.7.2 Sat Aug 17 09:07:30 2002 Doug Lea (dl at gee) + + Note: There may be an updated version of this malloc obtainable at + ftp://gee.cs.oswego.edu/pub/misc/malloc.c + Check before installing! + + Hacked up for uClibc by Erik Andersen +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + + +__UCLIBC_MUTEX_EXTERN(__malloc_lock); +#define __MALLOC_LOCK __UCLIBC_MUTEX_LOCK(__malloc_lock) +#define __MALLOC_UNLOCK __UCLIBC_MUTEX_UNLOCK(__malloc_lock) + + + +/* + MALLOC_ALIGNMENT is the minimum alignment for malloc'ed chunks. + It must be a power of two at least 2 * (sizeof(size_t)), even on machines + for which smaller alignments would suffice. It may be defined as + larger than this though. Note however that code and data structures + are optimized for the case of 8-byte alignment. +*/ +#ifndef MALLOC_ALIGNMENT +#define MALLOC_ALIGNMENT (2 * (sizeof(size_t))) +#endif + +/* The corresponding bit mask value */ +#define MALLOC_ALIGN_MASK (MALLOC_ALIGNMENT - 1) + +/* + TRIM_FASTBINS controls whether free() of a very small chunk can + immediately lead to trimming. Setting to true (1) can reduce memory + footprint, but will almost always slow down programs that use a lot + of small chunks. + + Define this only if you are willing to give up some speed to more + aggressively reduce system-level memory footprint when releasing + memory in programs that use many small chunks. You can get + essentially the same effect by setting MXFAST to 0, but this can + lead to even greater slowdowns in programs using many small chunks. + TRIM_FASTBINS is an in-between compile-time option, that disables + only those chunks bordering topmost memory from being placed in + fastbins. +*/ +#ifndef TRIM_FASTBINS +#define TRIM_FASTBINS 0 +#endif + + +/* + MORECORE-related declarations. By default, rely on sbrk +*/ + + +/* + MORECORE is the name of the routine to call to obtain more memory + from the system. See below for general guidance on writing + alternative MORECORE functions, as well as a version for WIN32 and a + sample version for pre-OSX macos. +*/ +#ifndef MORECORE +#define MORECORE sbrk +#endif + +/* + MORECORE_FAILURE is the value returned upon failure of MORECORE + as well as mmap. Since it cannot be an otherwise valid memory address, + and must reflect values of standard sys calls, you probably ought not + try to redefine it. +*/ +#ifndef MORECORE_FAILURE +#define MORECORE_FAILURE (-1) +#endif + +/* + If MORECORE_CONTIGUOUS is true, take advantage of fact that + consecutive calls to MORECORE with positive arguments always return + contiguous increasing addresses. This is true of unix sbrk. Even + if not defined, when regions happen to be contiguous, malloc will + permit allocations spanning regions obtained from different + calls. But defining this when applicable enables some stronger + consistency checks and space efficiencies. +*/ +#ifndef MORECORE_CONTIGUOUS +#define MORECORE_CONTIGUOUS 1 +#endif + +/* + MMAP_AS_MORECORE_SIZE is the minimum mmap size argument to use if + sbrk fails, and mmap is used as a backup (which is done only if + HAVE_MMAP). The value must be a multiple of page size. This + backup strategy generally applies only when systems have "holes" in + address space, so sbrk cannot perform contiguous expansion, but + there is still space available on system. On systems for which + this is known to be useful (i.e. most linux kernels), this occurs + only when programs allocate huge amounts of memory. Between this, + and the fact that mmap regions tend to be limited, the size should + be large, to avoid too many mmap calls and thus avoid running out + of kernel resources. +*/ +#ifndef MMAP_AS_MORECORE_SIZE +#define MMAP_AS_MORECORE_SIZE (1024 * 1024) +#endif + +/* + The system page size. To the extent possible, this malloc manages + memory from the system in page-size units. Note that this value is + cached during initialization into a field of malloc_state. So even + if malloc_getpagesize is a function, it is only called once. + + The following mechanics for getpagesize were adapted from bsd/gnu + getpagesize.h. If none of the system-probes here apply, a value of + 4096 is used, which should be OK: If they don't apply, then using + the actual value probably doesn't impact performance. +*/ +#ifndef malloc_getpagesize +# include +# define malloc_getpagesize sysconf(_SC_PAGESIZE) +#else /* just guess */ +# define malloc_getpagesize (4096) +#endif + + +/* mallopt tuning options */ + +/* + M_MXFAST is the maximum request size used for "fastbins", special bins + that hold returned chunks without consolidating their spaces. This + enables future requests for chunks of the same size to be handled + very quickly, but can increase fragmentation, and thus increase the + overall memory footprint of a program. + + This malloc manages fastbins very conservatively yet still + efficiently, so fragmentation is rarely a problem for values less + than or equal to the default. The maximum supported value of MXFAST + is 80. You wouldn't want it any higher than this anyway. Fastbins + are designed especially for use with many small structs, objects or + strings -- the default handles structs/objects/arrays with sizes up + to 16 4byte fields, or small strings representing words, tokens, + etc. Using fastbins for larger objects normally worsens + fragmentation without improving speed. + + M_MXFAST is set in REQUEST size units. It is internally used in + chunksize units, which adds padding and alignment. You can reduce + M_MXFAST to 0 to disable all use of fastbins. This causes the malloc + algorithm to be a closer approximation of fifo-best-fit in all cases, + not just for larger requests, but will generally cause it to be + slower. +*/ + + +/* M_MXFAST is a standard SVID/XPG tuning option, usually listed in malloc.h */ +#ifndef M_MXFAST +#define M_MXFAST 1 +#endif + +#ifndef DEFAULT_MXFAST +#define DEFAULT_MXFAST 64 +#endif + + +/* + M_TRIM_THRESHOLD is the maximum amount of unused top-most memory + to keep before releasing via malloc_trim in free(). + + Automatic trimming is mainly useful in long-lived programs. + Because trimming via sbrk can be slow on some systems, and can + sometimes be wasteful (in cases where programs immediately + afterward allocate more large chunks) the value should be high + enough so that your overall system performance would improve by + releasing this much memory. + + The trim threshold and the mmap control parameters (see below) + can be traded off with one another. Trimming and mmapping are + two different ways of releasing unused memory back to the + system. Between these two, it is often possible to keep + system-level demands of a long-lived program down to a bare + minimum. For example, in one test suite of sessions measuring + the XF86 X server on Linux, using a trim threshold of 128K and a + mmap threshold of 192K led to near-minimal long term resource + consumption. + + If you are using this malloc in a long-lived program, it should + pay to experiment with these values. As a rough guide, you + might set to a value close to the average size of a process + (program) running on your system. Releasing this much memory + would allow such a process to run in memory. Generally, it's + worth it to tune for trimming rather tham memory mapping when a + program undergoes phases where several large chunks are + allocated and released in ways that can reuse each other's + storage, perhaps mixed with phases where there are no such + chunks at all. And in well-behaved long-lived programs, + controlling release of large blocks via trimming versus mapping + is usually faster. + + However, in most programs, these parameters serve mainly as + protection against the system-level effects of carrying around + massive amounts of unneeded memory. Since frequent calls to + sbrk, mmap, and munmap otherwise degrade performance, the default + parameters are set to relatively high values that serve only as + safeguards. + + The trim value must be greater than page size to have any useful + effect. To disable trimming completely, you can set to + (unsigned long)(-1) + + Trim settings interact with fastbin (MXFAST) settings: Unless + TRIM_FASTBINS is defined, automatic trimming never takes place upon + freeing a chunk with size less than or equal to MXFAST. Trimming is + instead delayed until subsequent freeing of larger chunks. However, + you can still force an attempted trim by calling malloc_trim. + + Also, trimming is not generally possible in cases where + the main arena is obtained via mmap. + + Note that the trick some people use of mallocing a huge space and + then freeing it at program startup, in an attempt to reserve system + memory, doesn't have the intended effect under automatic trimming, + since that memory will immediately be returned to the system. +*/ +#define M_TRIM_THRESHOLD -1 + +#ifndef DEFAULT_TRIM_THRESHOLD +#define DEFAULT_TRIM_THRESHOLD (256 * 1024) +#endif + +/* + M_TOP_PAD is the amount of extra `padding' space to allocate or + retain whenever sbrk is called. It is used in two ways internally: + + * When sbrk is called to extend the top of the arena to satisfy + a new malloc request, this much padding is added to the sbrk + request. + + * When malloc_trim is called automatically from free(), + it is used as the `pad' argument. + + In both cases, the actual amount of padding is rounded + so that the end of the arena is always a system page boundary. + + The main reason for using padding is to avoid calling sbrk so + often. Having even a small pad greatly reduces the likelihood + that nearly every malloc request during program start-up (or + after trimming) will invoke sbrk, which needlessly wastes + time. + + Automatic rounding-up to page-size units is normally sufficient + to avoid measurable overhead, so the default is 0. However, in + systems where sbrk is relatively slow, it can pay to increase + this value, at the expense of carrying around more memory than + the program needs. +*/ +#define M_TOP_PAD -2 + +#ifndef DEFAULT_TOP_PAD +#define DEFAULT_TOP_PAD (0) +#endif + +/* + M_MMAP_THRESHOLD is the request size threshold for using mmap() + to service a request. Requests of at least this size that cannot + be allocated using already-existing space will be serviced via mmap. + (If enough normal freed space already exists it is used instead.) + + Using mmap segregates relatively large chunks of memory so that + they can be individually obtained and released from the host + system. A request serviced through mmap is never reused by any + other request (at least not directly; the system may just so + happen to remap successive requests to the same locations). + + Segregating space in this way has the benefits that: + + 1. Mmapped space can ALWAYS be individually released back + to the system, which helps keep the system level memory + demands of a long-lived program low. + 2. Mapped memory can never become `locked' between + other chunks, as can happen with normally allocated chunks, which + means that even trimming via malloc_trim would not release them. + 3. On some systems with "holes" in address spaces, mmap can obtain + memory that sbrk cannot. + + However, it has the disadvantages that: + + 1. The space cannot be reclaimed, consolidated, and then + used to service later requests, as happens with normal chunks. + 2. It can lead to more wastage because of mmap page alignment + requirements + 3. It causes malloc performance to be more dependent on host + system memory management support routines which may vary in + implementation quality and may impose arbitrary + limitations. Generally, servicing a request via normal + malloc steps is faster than going through a system's mmap. + + The advantages of mmap nearly always outweigh disadvantages for + "large" chunks, but the value of "large" varies across systems. The + default is an empirically derived value that works well in most + systems. +*/ +#define M_MMAP_THRESHOLD -3 + +#ifndef DEFAULT_MMAP_THRESHOLD +#define DEFAULT_MMAP_THRESHOLD (256 * 1024) +#endif + +/* + M_MMAP_MAX is the maximum number of requests to simultaneously + service using mmap. This parameter exists because +. Some systems have a limited number of internal tables for + use by mmap, and using more than a few of them may degrade + performance. + + The default is set to a value that serves only as a safeguard. + Setting to 0 disables use of mmap for servicing large requests. If + HAVE_MMAP is not set, the default value is 0, and attempts to set it + to non-zero values in mallopt will fail. +*/ +#define M_MMAP_MAX -4 + +#ifndef DEFAULT_MMAP_MAX +#define DEFAULT_MMAP_MAX (65536) +#endif + + +/* ------------------ MMAP support ------------------ */ +#include +#include + +#if !defined(MAP_ANONYMOUS) && defined(MAP_ANON) +#define MAP_ANONYMOUS MAP_ANON +#endif + +#ifdef __ARCH_USE_MMU__ +# define _MAP_UNINITIALIZE 0 +#else +# define _MAP_UNINITIALIZE MAP_UNINITIALIZE +#endif + +#define MMAP(addr, size, prot) \ + (mmap((addr), (size), (prot), MAP_PRIVATE|MAP_ANONYMOUS|_MAP_UNINITIALIZE, 0, 0)) + + +/* ----------------------- Chunk representations ----------------------- */ + + +/* + This struct declaration is misleading (but accurate and necessary). + It declares a "view" into memory allowing access to necessary + fields at known offsets from a given base. See explanation below. +*/ + +struct malloc_chunk { + + size_t prev_size; /* Size of previous chunk (if free). */ + size_t size; /* Size in bytes, including overhead. */ + + struct malloc_chunk* fd; /* double links -- used only if free. */ + struct malloc_chunk* bk; +}; + + +typedef struct malloc_chunk* mchunkptr; + +/* + malloc_chunk details: + + (The following includes lightly edited explanations by Colin Plumb.) + + Chunks of memory are maintained using a `boundary tag' method as + described in e.g., Knuth or Standish. (See the paper by Paul + Wilson ftp://ftp.cs.utexas.edu/pub/garbage/allocsrv.ps for a + survey of such techniques.) Sizes of free chunks are stored both + in the front of each chunk and at the end. This makes + consolidating fragmented chunks into bigger chunks very fast. The + size fields also hold bits representing whether chunks are free or + in use. + + An allocated chunk looks like this: + + + chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Size of previous chunk, if allocated | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Size of chunk, in bytes |P| + mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | User data starts here... . + . . + . (malloc_usable_space() bytes) . + . | +nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Size of chunk | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + + Where "chunk" is the front of the chunk for the purpose of most of + the malloc code, but "mem" is the pointer that is returned to the + user. "Nextchunk" is the beginning of the next contiguous chunk. + + Chunks always begin on even word boundries, so the mem portion + (which is returned to the user) is also on an even word boundary, and + thus at least double-word aligned. + + Free chunks are stored in circular doubly-linked lists, and look like this: + + chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Size of previous chunk | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + `head:' | Size of chunk, in bytes |P| + mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Forward pointer to next chunk in list | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Back pointer to previous chunk in list | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Unused space (may be 0 bytes long) . + . . + . | +nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + `foot:' | Size of chunk, in bytes | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + The P (PREV_INUSE) bit, stored in the unused low-order bit of the + chunk size (which is always a multiple of two words), is an in-use + bit for the *previous* chunk. If that bit is *clear*, then the + word before the current chunk size contains the previous chunk + size, and can be used to find the front of the previous chunk. + The very first chunk allocated always has this bit set, + preventing access to non-existent (or non-owned) memory. If + prev_inuse is set for any given chunk, then you CANNOT determine + the size of the previous chunk, and might even get a memory + addressing fault when trying to do so. + + Note that the `foot' of the current chunk is actually represented + as the prev_size of the NEXT chunk. This makes it easier to + deal with alignments etc but can be very confusing when trying + to extend or adapt this code. + + The two exceptions to all this are + + 1. The special chunk `top' doesn't bother using the + trailing size field since there is no next contiguous chunk + that would have to index off it. After initialization, `top' + is forced to always exist. If it would become less than + MINSIZE bytes long, it is replenished. + + 2. Chunks allocated via mmap, which have the second-lowest-order + bit (IS_MMAPPED) set in their size fields. Because they are + allocated one-by-one, each must contain its own trailing size field. + +*/ + +/* + ---------- Size and alignment checks and conversions ---------- +*/ + +/* conversion from malloc headers to user pointers, and back */ + +#define chunk2mem(p) ((void*)((char*)(p) + 2*(sizeof(size_t)))) +#define mem2chunk(mem) ((mchunkptr)((char*)(mem) - 2*(sizeof(size_t)))) + +/* The smallest possible chunk */ +#define MIN_CHUNK_SIZE (sizeof(struct malloc_chunk)) + +/* The smallest size we can malloc is an aligned minimal chunk */ + +#define MINSIZE \ + (unsigned long)(((MIN_CHUNK_SIZE+MALLOC_ALIGN_MASK) & ~MALLOC_ALIGN_MASK)) + +/* Check if m has acceptable alignment */ + +#define aligned_OK(m) (((unsigned long)((m)) & (MALLOC_ALIGN_MASK)) == 0) + + +/* Check if a request is so large that it would wrap around zero when + padded and aligned. To simplify some other code, the bound is made + low enough so that adding MINSIZE will also not wrap around sero. +*/ + +#define REQUEST_OUT_OF_RANGE(req) \ + ((unsigned long)(req) >= \ + (unsigned long)(size_t)(-2 * MINSIZE)) + +/* pad request bytes into a usable size -- internal version */ + +#define request2size(req) \ + (((req) + (sizeof(size_t)) + MALLOC_ALIGN_MASK < MINSIZE) ? \ + MINSIZE : \ + ((req) + (sizeof(size_t)) + MALLOC_ALIGN_MASK) & ~MALLOC_ALIGN_MASK) + +/* Same, except also perform argument check */ + +#define checked_request2size(req, sz) \ + if (REQUEST_OUT_OF_RANGE(req)) { \ + errno = ENOMEM; \ + return 0; \ + } \ + (sz) = request2size(req); + +/* + --------------- Physical chunk operations --------------- +*/ + + +/* size field is or'ed with PREV_INUSE when previous adjacent chunk in use */ +#define PREV_INUSE 0x1 + +/* extract inuse bit of previous chunk */ +#define prev_inuse(p) ((p)->size & PREV_INUSE) + + +/* size field is or'ed with IS_MMAPPED if the chunk was obtained with mmap() */ +#define IS_MMAPPED 0x2 + +/* check for mmap()'ed chunk */ +#define chunk_is_mmapped(p) ((p)->size & IS_MMAPPED) + +/* Bits to mask off when extracting size + + Note: IS_MMAPPED is intentionally not masked off from size field in + macros for which mmapped chunks should never be seen. This should + cause helpful core dumps to occur if it is tried by accident by + people extending or adapting this malloc. +*/ +#define SIZE_BITS (PREV_INUSE|IS_MMAPPED) + +/* Get size, ignoring use bits */ +#define chunksize(p) ((p)->size & ~(SIZE_BITS)) + + +/* Ptr to next physical malloc_chunk. */ +#define next_chunk(p) ((mchunkptr)( ((char*)(p)) + ((p)->size & ~PREV_INUSE) )) + +/* Ptr to previous physical malloc_chunk */ +#define prev_chunk(p) ((mchunkptr)( ((char*)(p)) - ((p)->prev_size) )) + +/* Treat space at ptr + offset as a chunk */ +#define chunk_at_offset(p, s) ((mchunkptr)(((char*)(p)) + (s))) + +/* extract p's inuse bit */ +#define inuse(p)\ +((((mchunkptr)(((char*)(p))+((p)->size & ~PREV_INUSE)))->size) & PREV_INUSE) + +/* set/clear chunk as being inuse without otherwise disturbing */ +#define set_inuse(p)\ +((mchunkptr)(((char*)(p)) + ((p)->size & ~PREV_INUSE)))->size |= PREV_INUSE + +#define clear_inuse(p)\ +((mchunkptr)(((char*)(p)) + ((p)->size & ~PREV_INUSE)))->size &= ~(PREV_INUSE) + + +/* check/set/clear inuse bits in known places */ +#define inuse_bit_at_offset(p, s)\ + (((mchunkptr)(((char*)(p)) + (s)))->size & PREV_INUSE) + +#define set_inuse_bit_at_offset(p, s)\ + (((mchunkptr)(((char*)(p)) + (s)))->size |= PREV_INUSE) + +#define clear_inuse_bit_at_offset(p, s)\ + (((mchunkptr)(((char*)(p)) + (s)))->size &= ~(PREV_INUSE)) + + +/* Set size at head, without disturbing its use bit */ +#define set_head_size(p, s) ((p)->size = (((p)->size & PREV_INUSE) | (s))) + +/* Set size/use field */ +#define set_head(p, s) ((p)->size = (s)) + +/* Set size at footer (only when chunk is not in use) */ +#define set_foot(p, s) (((mchunkptr)((char*)(p) + (s)))->prev_size = (s)) + + +/* -------------------- Internal data structures -------------------- */ + +/* + Bins + + An array of bin headers for free chunks. Each bin is doubly + linked. The bins are approximately proportionally (log) spaced. + There are a lot of these bins (128). This may look excessive, but + works very well in practice. Most bins hold sizes that are + unusual as malloc request sizes, but are more usual for fragments + and consolidated sets of chunks, which is what these bins hold, so + they can be found quickly. All procedures maintain the invariant + that no consolidated chunk physically borders another one, so each + chunk in a list is known to be preceeded and followed by either + inuse chunks or the ends of memory. + + Chunks in bins are kept in size order, with ties going to the + approximately least recently used chunk. Ordering isn't needed + for the small bins, which all contain the same-sized chunks, but + facilitates best-fit allocation for larger chunks. These lists + are just sequential. Keeping them in order almost never requires + enough traversal to warrant using fancier ordered data + structures. + + Chunks of the same size are linked with the most + recently freed at the front, and allocations are taken from the + back. This results in LRU (FIFO) allocation order, which tends + to give each chunk an equal opportunity to be consolidated with + adjacent freed chunks, resulting in larger free chunks and less + fragmentation. + + To simplify use in double-linked lists, each bin header acts + as a malloc_chunk. This avoids special-casing for headers. + But to conserve space and improve locality, we allocate + only the fd/bk pointers of bins, and then use repositioning tricks + to treat these as the fields of a malloc_chunk*. +*/ + +typedef struct malloc_chunk* mbinptr; + +/* addressing -- note that bin_at(0) does not exist */ +#define bin_at(m, i) ((mbinptr)((char*)&((m)->bins[(i)<<1]) - ((sizeof(size_t))<<1))) + +/* analog of ++bin */ +#define next_bin(b) ((mbinptr)((char*)(b) + (sizeof(mchunkptr)<<1))) + +/* Reminders about list directionality within bins */ +#define first(b) ((b)->fd) +#define last(b) ((b)->bk) + +/* Take a chunk off a bin list */ +#define unlink(P, BK, FD) { \ + FD = P->fd; \ + BK = P->bk; \ + if (FD->bk != P || BK->fd != P) \ + abort(); \ + FD->bk = BK; \ + BK->fd = FD; \ +} + +/* + Indexing + + Bins for sizes < 512 bytes contain chunks of all the same size, spaced + 8 bytes apart. Larger bins are approximately logarithmically spaced: + + 64 bins of size 8 + 32 bins of size 64 + 16 bins of size 512 + 8 bins of size 4096 + 4 bins of size 32768 + 2 bins of size 262144 + 1 bin of size what's left + + The bins top out around 1MB because we expect to service large + requests via mmap. +*/ + +#define NBINS 96 +#define NSMALLBINS 32 +#define SMALLBIN_WIDTH 8 +#define MIN_LARGE_SIZE 256 + +#define in_smallbin_range(sz) \ + ((unsigned long)(sz) < (unsigned long)MIN_LARGE_SIZE) + +#define smallbin_index(sz) (((unsigned)(sz)) >> 3) + +#define bin_index(sz) \ + ((in_smallbin_range(sz)) ? smallbin_index(sz) : __malloc_largebin_index(sz)) + +/* + FIRST_SORTED_BIN_SIZE is the chunk size corresponding to the + first bin that is maintained in sorted order. This must + be the smallest size corresponding to a given bin. + + Normally, this should be MIN_LARGE_SIZE. But you can weaken + best fit guarantees to sometimes speed up malloc by increasing value. + Doing this means that malloc may choose a chunk that is + non-best-fitting by up to the width of the bin. + + Some useful cutoff values: + 512 - all bins sorted + 2560 - leaves bins <= 64 bytes wide unsorted + 12288 - leaves bins <= 512 bytes wide unsorted + 65536 - leaves bins <= 4096 bytes wide unsorted + 262144 - leaves bins <= 32768 bytes wide unsorted + -1 - no bins sorted (not recommended!) +*/ + +#define FIRST_SORTED_BIN_SIZE MIN_LARGE_SIZE +/* #define FIRST_SORTED_BIN_SIZE 65536 */ + +/* + Unsorted chunks + + All remainders from chunk splits, as well as all returned chunks, + are first placed in the "unsorted" bin. They are then placed + in regular bins after malloc gives them ONE chance to be used before + binning. So, basically, the unsorted_chunks list acts as a queue, + with chunks being placed on it in free (and __malloc_consolidate), + and taken off (to be either used or placed in bins) in malloc. +*/ + +/* The otherwise unindexable 1-bin is used to hold unsorted chunks. */ +#define unsorted_chunks(M) (bin_at(M, 1)) + +/* + Top + + The top-most available chunk (i.e., the one bordering the end of + available memory) is treated specially. It is never included in + any bin, is used only if no other chunk is available, and is + released back to the system if it is very large (see + M_TRIM_THRESHOLD). Because top initially + points to its own bin with initial zero size, thus forcing + extension on the first malloc request, we avoid having any special + code in malloc to check whether it even exists yet. But we still + need to do so when getting memory from system, so we make + initial_top treat the bin as a legal but unusable chunk during the + interval between initialization and the first call to + __malloc_alloc. (This is somewhat delicate, since it relies on + the 2 preceding words to be zero during this interval as well.) +*/ + +/* Conveniently, the unsorted bin can be used as dummy top on first call */ +#define initial_top(M) (unsorted_chunks(M)) + +/* + Binmap + + To help compensate for the large number of bins, a one-level index + structure is used for bin-by-bin searching. `binmap' is a + bitvector recording whether bins are definitely empty so they can + be skipped over during during traversals. The bits are NOT always + cleared as soon as bins are empty, but instead only + when they are noticed to be empty during traversal in malloc. +*/ + +/* Conservatively use 32 bits per map word, even if on 64bit system */ +#define BINMAPSHIFT 5 +#define BITSPERMAP (1U << BINMAPSHIFT) +#define BINMAPSIZE (NBINS / BITSPERMAP) + +#define idx2block(i) ((i) >> BINMAPSHIFT) +#define idx2bit(i) ((1U << ((i) & ((1U << BINMAPSHIFT)-1)))) + +#define mark_bin(m,i) ((m)->binmap[idx2block(i)] |= idx2bit(i)) +#define unmark_bin(m,i) ((m)->binmap[idx2block(i)] &= ~(idx2bit(i))) +#define get_binmap(m,i) ((m)->binmap[idx2block(i)] & idx2bit(i)) + +/* + Fastbins + + An array of lists holding recently freed small chunks. Fastbins + are not doubly linked. It is faster to single-link them, and + since chunks are never removed from the middles of these lists, + double linking is not necessary. Also, unlike regular bins, they + are not even processed in FIFO order (they use faster LIFO) since + ordering doesn't much matter in the transient contexts in which + fastbins are normally used. + + Chunks in fastbins keep their inuse bit set, so they cannot + be consolidated with other free chunks. __malloc_consolidate + releases all chunks in fastbins and consolidates them with + other free chunks. +*/ + +typedef struct malloc_chunk* mfastbinptr; + +/* offset 2 to use otherwise unindexable first 2 bins */ +#define fastbin_index(sz) ((((unsigned int)(sz)) >> 3) - 2) + +/* The maximum fastbin request size we support */ +#define MAX_FAST_SIZE 80 + +#define NFASTBINS (fastbin_index(request2size(MAX_FAST_SIZE))+1) + +/* + FASTBIN_CONSOLIDATION_THRESHOLD is the size of a chunk in free() + that triggers automatic consolidation of possibly-surrounding + fastbin chunks. This is a heuristic, so the exact value should not + matter too much. It is defined at half the default trim threshold as a + compromise heuristic to only attempt consolidation if it is likely + to lead to trimming. However, it is not dynamically tunable, since + consolidation reduces fragmentation surrounding loarge chunks even + if trimming is not used. +*/ + +#define FASTBIN_CONSOLIDATION_THRESHOLD \ + ((unsigned long)(DEFAULT_TRIM_THRESHOLD) >> 1) + +/* + Since the lowest 2 bits in max_fast don't matter in size comparisons, + they are used as flags. +*/ + +/* + ANYCHUNKS_BIT held in max_fast indicates that there may be any + freed chunks at all. It is set true when entering a chunk into any + bin. +*/ + +#define ANYCHUNKS_BIT (1U) + +#define have_anychunks(M) (((M)->max_fast & ANYCHUNKS_BIT)) +#define set_anychunks(M) ((M)->max_fast |= ANYCHUNKS_BIT) +#define clear_anychunks(M) ((M)->max_fast &= ~ANYCHUNKS_BIT) + +/* + FASTCHUNKS_BIT held in max_fast indicates that there are probably + some fastbin chunks. It is set true on entering a chunk into any + fastbin, and cleared only in __malloc_consolidate. +*/ + +#define FASTCHUNKS_BIT (2U) + +#define have_fastchunks(M) (((M)->max_fast & FASTCHUNKS_BIT)) +#define set_fastchunks(M) ((M)->max_fast |= (FASTCHUNKS_BIT|ANYCHUNKS_BIT)) +#define clear_fastchunks(M) ((M)->max_fast &= ~(FASTCHUNKS_BIT)) + +/* Set value of max_fast. Use impossibly small value if 0. */ +#define set_max_fast(M, s) \ + (M)->max_fast = (((s) == 0)? SMALLBIN_WIDTH: request2size(s)) | \ + ((M)->max_fast & (FASTCHUNKS_BIT|ANYCHUNKS_BIT)) + +#define get_max_fast(M) \ + ((M)->max_fast & ~(FASTCHUNKS_BIT | ANYCHUNKS_BIT)) + + +/* + morecore_properties is a status word holding dynamically discovered + or controlled properties of the morecore function +*/ + +#define MORECORE_CONTIGUOUS_BIT (1U) + +#define contiguous(M) \ + (((M)->morecore_properties & MORECORE_CONTIGUOUS_BIT)) +#define noncontiguous(M) \ + (((M)->morecore_properties & MORECORE_CONTIGUOUS_BIT) == 0) +#define set_contiguous(M) \ + ((M)->morecore_properties |= MORECORE_CONTIGUOUS_BIT) +#define set_noncontiguous(M) \ + ((M)->morecore_properties &= ~MORECORE_CONTIGUOUS_BIT) + + +/* + ----------- Internal state representation and initialization ----------- +*/ + +struct malloc_state { + + /* The maximum chunk size to be eligible for fastbin */ + size_t max_fast; /* low 2 bits used as flags */ + + /* Fastbins */ + mfastbinptr fastbins[NFASTBINS]; + + /* Base of the topmost chunk -- not otherwise kept in a bin */ + mchunkptr top; + + /* The remainder from the most recent split of a small request */ + mchunkptr last_remainder; + + /* Normal bins packed as described above */ + mchunkptr bins[NBINS * 2]; + + /* Bitmap of bins. Trailing zero map handles cases of largest binned size */ + unsigned int binmap[BINMAPSIZE+1]; + + /* Tunable parameters */ + unsigned long trim_threshold; + size_t top_pad; + size_t mmap_threshold; + + /* Memory map support */ + int n_mmaps; + int n_mmaps_max; + int max_n_mmaps; + + /* Cache malloc_getpagesize */ + unsigned int pagesize; + + /* Track properties of MORECORE */ + unsigned int morecore_properties; + + /* Statistics */ + size_t mmapped_mem; + size_t sbrked_mem; + size_t max_sbrked_mem; + size_t max_mmapped_mem; + size_t max_total_mem; +}; + +typedef struct malloc_state *mstate; + +/* + There is exactly one instance of this struct in this malloc. + If you are adapting this malloc in a way that does NOT use a static + malloc_state, you MUST explicitly zero-fill it before using. This + malloc relies on the property that malloc_state is initialized to + all zeroes (as is true of C statics). +*/ +extern struct malloc_state __malloc_state; /* never directly referenced */ + +/* + All uses of av_ are via get_malloc_state(). + At most one "call" to get_malloc_state is made per invocation of + the public versions of malloc and free, but other routines + that in turn invoke malloc and/or free may call more then once. + Also, it is called in check* routines if __UCLIBC_MALLOC_DEBUGGING__ is set. +*/ + +#define get_malloc_state() (&(__malloc_state)) + +/* External internal utilities operating on mstates */ +void __malloc_consolidate(mstate) attribute_hidden; + + +/* Debugging support */ +#ifndef __UCLIBC_MALLOC_DEBUGGING__ + +#define check_chunk(P) +#define check_free_chunk(P) +#define check_inuse_chunk(P) +#define check_remalloced_chunk(P,N) +#define check_malloced_chunk(P,N) +#define check_malloc_state() +#define assert(x) ((void)0) + + +#else + +#define check_chunk(P) __do_check_chunk(P) +#define check_free_chunk(P) __do_check_free_chunk(P) +#define check_inuse_chunk(P) __do_check_inuse_chunk(P) +#define check_remalloced_chunk(P,N) __do_check_remalloced_chunk(P,N) +#define check_malloced_chunk(P,N) __do_check_malloced_chunk(P,N) +#define check_malloc_state() __do_check_malloc_state() + +extern void __do_check_chunk(mchunkptr p); +extern void __do_check_free_chunk(mchunkptr p); +extern void __do_check_inuse_chunk(mchunkptr p); +extern void __do_check_remalloced_chunk(mchunkptr p, size_t s); +extern void __do_check_malloced_chunk(mchunkptr p, size_t s); +extern void __do_check_malloc_state(void); + +#include + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc-standard/mallopt.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc-standard/mallopt.c new file mode 100644 index 00000000..053242db --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc-standard/mallopt.c @@ -0,0 +1,64 @@ +/* + This is a version (aka dlmalloc) of malloc/free/realloc written by + Doug Lea and released to the public domain. Use, modify, and + redistribute this code without permission or acknowledgement in any + way you wish. Send questions, comments, complaints, performance + data, etc to dl@cs.oswego.edu + + VERSION 2.7.2 Sat Aug 17 09:07:30 2002 Doug Lea (dl at gee) + + Note: There may be an updated version of this malloc obtainable at + ftp://gee.cs.oswego.edu/pub/misc/malloc.c + Check before installing! + + Hacked up for uClibc by Erik Andersen +*/ + +#include "malloc.h" + + +/* ------------------------------ mallopt ------------------------------ */ +int mallopt(int param_number, int value) +{ + int ret; + mstate av; + + ret = 0; + + __MALLOC_LOCK; + av = get_malloc_state(); + /* Ensure initialization/consolidation */ + __malloc_consolidate(av); + + switch(param_number) { + case M_MXFAST: + if (value >= 0 && value <= MAX_FAST_SIZE) { + set_max_fast(av, value); + ret = 1; + } + break; + + case M_TRIM_THRESHOLD: + av->trim_threshold = value; + ret = 1; + break; + + case M_TOP_PAD: + av->top_pad = value; + ret = 1; + break; + + case M_MMAP_THRESHOLD: + av->mmap_threshold = value; + ret = 1; + break; + + case M_MMAP_MAX: + av->n_mmaps_max = value; + ret = 1; + break; + } + __MALLOC_UNLOCK; + return ret; +} + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc-standard/memalign.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc-standard/memalign.c new file mode 100644 index 00000000..7e0674be --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc-standard/memalign.c @@ -0,0 +1,130 @@ +/* + This is a version (aka dlmalloc) of malloc/free/realloc written by + Doug Lea and released to the public domain. Use, modify, and + redistribute this code without permission or acknowledgement in any + way you wish. Send questions, comments, complaints, performance + data, etc to dl@cs.oswego.edu + + VERSION 2.7.2 Sat Aug 17 09:07:30 2002 Doug Lea (dl at gee) + + Note: There may be an updated version of this malloc obtainable at + ftp://gee.cs.oswego.edu/pub/misc/malloc.c + Check before installing! + + Hacked up for uClibc by Erik Andersen +*/ + +#include +#include +#include +#include +#include +#include "malloc.h" + + +/* ------------------------------ memalign ------------------------------ */ +void* memalign(size_t alignment, size_t bytes) +{ + size_t nb; /* padded request size */ + char* m; /* memory returned by malloc call */ + mchunkptr p; /* corresponding chunk */ + char* _brk; /* alignment point within p */ + mchunkptr newp; /* chunk to return */ + size_t newsize; /* its size */ + size_t leadsize; /* leading space before alignment point */ + mchunkptr remainder; /* spare room at end to split off */ + unsigned long remainder_size; /* its size */ + size_t size; + void *retval; + + /* If need less alignment than we give anyway, just relay to malloc */ + + if (alignment <= MALLOC_ALIGNMENT) return malloc(bytes); + + /* Otherwise, ensure that it is at least a minimum chunk size */ + + if (alignment < MINSIZE) alignment = MINSIZE; + + /* Make sure alignment is power of 2 (in case MINSIZE is not). */ + if ((alignment & (alignment - 1)) != 0) { + size_t a = MALLOC_ALIGNMENT * 2; + while ((unsigned long)a < (unsigned long)alignment) a <<= 1; + alignment = a; + } + + __MALLOC_LOCK; + checked_request2size(bytes, nb); + + /* Strategy: find a spot within that chunk that meets the alignment + * request, and then possibly free the leading and trailing space. */ + + + /* Call malloc with worst case padding to hit alignment. */ + + m = (char*)(malloc(nb + alignment + MINSIZE)); + + if (m == 0) { + retval = 0; /* propagate failure */ + goto DONE; + } + + p = mem2chunk(m); + + if ((((unsigned long)(m)) % alignment) != 0) { /* misaligned */ + + /* + Find an aligned spot inside chunk. Since we need to give back + leading space in a chunk of at least MINSIZE, if the first + calculation places us at a spot with less than MINSIZE leader, + we can move to the next aligned spot -- we've allocated enough + total room so that this is always possible. + */ + + _brk = (char*)mem2chunk((unsigned long)(((unsigned long)(m + alignment - 1)) & + -((signed long) alignment))); + if ((unsigned long)(_brk - (char*)(p)) < MINSIZE) + _brk += alignment; + + newp = (mchunkptr)_brk; + leadsize = _brk - (char*)(p); + newsize = chunksize(p) - leadsize; + + /* For mmapped chunks, just adjust offset */ + if (chunk_is_mmapped(p)) { + newp->prev_size = p->prev_size + leadsize; + set_head(newp, newsize|IS_MMAPPED); + retval = chunk2mem(newp); + goto DONE; + } + + /* Otherwise, give back leader, use the rest */ + set_head(newp, newsize | PREV_INUSE); + set_inuse_bit_at_offset(newp, newsize); + set_head_size(p, leadsize); + free(chunk2mem(p)); + p = newp; + + assert (newsize >= nb && + (((unsigned long)(chunk2mem(p))) % alignment) == 0); + } + + /* Also give back spare room at the end */ + if (!chunk_is_mmapped(p)) { + size = chunksize(p); + if ((unsigned long)(size) > (unsigned long)(nb + MINSIZE)) { + remainder_size = size - nb; + remainder = chunk_at_offset(p, nb); + set_head(remainder, remainder_size | PREV_INUSE); + set_head_size(p, nb); + free(chunk2mem(remainder)); + } + } + + check_inuse_chunk(p); + retval = chunk2mem(p); + + DONE: + __MALLOC_UNLOCK; + return retval; +} + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc-standard/realloc.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc-standard/realloc.c new file mode 100644 index 00000000..e060b70e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc-standard/realloc.c @@ -0,0 +1,240 @@ +/* + This is a version (aka dlmalloc) of malloc/free/realloc written by + Doug Lea and released to the public domain. Use, modify, and + redistribute this code without permission or acknowledgement in any + way you wish. Send questions, comments, complaints, performance + data, etc to dl@cs.oswego.edu + + VERSION 2.7.2 Sat Aug 17 09:07:30 2002 Doug Lea (dl at gee) + + Note: There may be an updated version of this malloc obtainable at + ftp://gee.cs.oswego.edu/pub/misc/malloc.c + Check before installing! + + Hacked up for uClibc by Erik Andersen +*/ + +#include "malloc.h" + + +/* ------------------------------ realloc ------------------------------ */ +void* realloc(void* oldmem, size_t bytes) +{ + mstate av; + + size_t nb; /* padded request size */ + + mchunkptr oldp; /* chunk corresponding to oldmem */ + size_t oldsize; /* its size */ + + mchunkptr newp; /* chunk to return */ + size_t newsize; /* its size */ + void* newmem; /* corresponding user mem */ + + mchunkptr next; /* next contiguous chunk after oldp */ + + mchunkptr remainder; /* extra space at end of newp */ + unsigned long remainder_size; /* its size */ + + mchunkptr bck; /* misc temp for linking */ + mchunkptr fwd; /* misc temp for linking */ + + unsigned long copysize; /* bytes to copy */ + unsigned int ncopies; /* size_t words to copy */ + size_t* s; /* copy source */ + size_t* d; /* copy destination */ + + void *retval; + + /* Check for special cases. */ + if (! oldmem) + return malloc(bytes); + if (! bytes) { + free (oldmem); + return NULL; + } + + __MALLOC_LOCK; + av = get_malloc_state(); + checked_request2size(bytes, nb); + + oldp = mem2chunk(oldmem); + oldsize = chunksize(oldp); + + check_inuse_chunk(oldp); + + if (!chunk_is_mmapped(oldp)) { + + if ((unsigned long)(oldsize) >= (unsigned long)(nb)) { + /* already big enough; split below */ + newp = oldp; + newsize = oldsize; + } + + else { + next = chunk_at_offset(oldp, oldsize); + + /* Try to expand forward into top */ + if (next == av->top && + (unsigned long)(newsize = oldsize + chunksize(next)) >= + (unsigned long)(nb + MINSIZE)) { + set_head_size(oldp, nb); + av->top = chunk_at_offset(oldp, nb); + set_head(av->top, (newsize - nb) | PREV_INUSE); + retval = chunk2mem(oldp); + goto DONE; + } + + /* Try to expand forward into next chunk; split off remainder below */ + else if (next != av->top && + !inuse(next) && + (unsigned long)(newsize = oldsize + chunksize(next)) >= + (unsigned long)(nb)) { + newp = oldp; + unlink(next, bck, fwd); + } + + /* allocate, copy, free */ + else { + newmem = malloc(nb - MALLOC_ALIGN_MASK); + if (newmem == 0) { + retval = 0; /* propagate failure */ + goto DONE; + } + + newp = mem2chunk(newmem); + newsize = chunksize(newp); + + /* + Avoid copy if newp is next chunk after oldp. + */ + if (newp == next) { + newsize += oldsize; + newp = oldp; + } + else { + /* + Unroll copy of <= 36 bytes (72 if 8byte sizes) + We know that contents have an odd number of + size_t-sized words; minimally 3. + */ + + copysize = oldsize - (sizeof(size_t)); + s = (size_t*)(oldmem); + d = (size_t*)(newmem); + ncopies = copysize / sizeof(size_t); + assert(ncopies >= 3); + + if (ncopies > 9) + memcpy(d, s, copysize); + + else { + *(d+0) = *(s+0); + *(d+1) = *(s+1); + *(d+2) = *(s+2); + if (ncopies > 4) { + *(d+3) = *(s+3); + *(d+4) = *(s+4); + if (ncopies > 6) { + *(d+5) = *(s+5); + *(d+6) = *(s+6); + if (ncopies > 8) { + *(d+7) = *(s+7); + *(d+8) = *(s+8); + } + } + } + } + + free(oldmem); + check_inuse_chunk(newp); + retval = chunk2mem(newp); + goto DONE; + } + } + } + + /* If possible, free extra space in old or extended chunk */ + + assert((unsigned long)(newsize) >= (unsigned long)(nb)); + + remainder_size = newsize - nb; + + if (remainder_size < MINSIZE) { /* not enough extra to split off */ + set_head_size(newp, newsize); + set_inuse_bit_at_offset(newp, newsize); + } + else { /* split remainder */ + remainder = chunk_at_offset(newp, nb); + set_head_size(newp, nb); + set_head(remainder, remainder_size | PREV_INUSE); + /* Mark remainder as inuse so free() won't complain */ + set_inuse_bit_at_offset(remainder, remainder_size); + free(chunk2mem(remainder)); + } + + check_inuse_chunk(newp); + retval = chunk2mem(newp); + goto DONE; + } + + /* + Handle mmap cases + */ + + else { + size_t offset = oldp->prev_size; + size_t pagemask = av->pagesize - 1; + char *cp; + unsigned long sum; + + /* Note the extra (sizeof(size_t)) overhead */ + newsize = (nb + offset + (sizeof(size_t)) + pagemask) & ~pagemask; + + /* don't need to remap if still within same page */ + if (oldsize == newsize - offset) { + retval = oldmem; + goto DONE; + } + + cp = (char*)mremap((char*)oldp - offset, oldsize + offset, newsize, 1); + + if (cp != (char*)MORECORE_FAILURE) { + + newp = (mchunkptr)(cp + offset); + set_head(newp, (newsize - offset)|IS_MMAPPED); + + assert(aligned_OK(chunk2mem(newp))); + assert((newp->prev_size == offset)); + + /* update statistics */ + sum = av->mmapped_mem += newsize - oldsize; + if (sum > (unsigned long)(av->max_mmapped_mem)) + av->max_mmapped_mem = sum; + sum += av->sbrked_mem; + if (sum > (unsigned long)(av->max_total_mem)) + av->max_total_mem = sum; + + retval = chunk2mem(newp); + goto DONE; + } + + /* Note the extra (sizeof(size_t)) overhead. */ + if ((unsigned long)(oldsize) >= (unsigned long)(nb + (sizeof(size_t)))) + newmem = oldmem; /* do nothing */ + else { + /* Must alloc, copy, free. */ + newmem = malloc(nb - MALLOC_ALIGN_MASK); + if (newmem != 0) { + memcpy(newmem, oldmem, oldsize - 2*(sizeof(size_t))); + free(oldmem); + } + } + retval = newmem; + } + + DONE: + __MALLOC_UNLOCK; + return retval; +} + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc/Makefile new file mode 100644 index 00000000..4a8f4a07 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../ +top_builddir=../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc/Makefile.in new file mode 100644 index 00000000..642570c9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc/Makefile.in @@ -0,0 +1,39 @@ +# Makefile for uClibc +# +# Copyright (C) 2002-2003 NEC Electronics Corporation +# Copyright (C) 2002-2003 Miles Bader +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +subdirs += libc/stdlib/malloc + +CSRC := malloc.c calloc.c free.c realloc.c memalign.c \ + heap_alloc.c heap_alloc_at.c heap_free.c + +# Turn on malloc debugging if requested +ifeq ($(UCLIBC_MALLOC_DEBUGGING),y) +CSRC += malloc_debug.c heap_debug.c +CFLAGS += -DMALLOC_DEBUGGING -DHEAP_DEBUGGING +ifeq ($(UCLIBC_UCLINUX_BROKEN_MUNMAP),y) +CFLAGS += -DMALLOC_MMB_DEBUGGING +endif +endif + +STDLIB_MALLOC_DIR := $(top_srcdir)libc/stdlib/malloc +STDLIB_MALLOC_OUT := $(top_builddir)libc/stdlib/malloc + +STDLIB_MALLOC_SRC := $(patsubst %.c,$(STDLIB_MALLOC_DIR)/%.c,$(CSRC)) +STDLIB_MALLOC_OBJ := $(patsubst %.c,$(STDLIB_MALLOC_OUT)/%.o,$(CSRC)) + +libc-$(MALLOC) += $(STDLIB_MALLOC_OBJ) + +objclean-y += CLEAN_libc/stdlib/malloc + +CLEAN_libc/stdlib/malloc: + $(do_rm) $(addprefix $(STDLIB_MALLOC_OUT)/*., o os) + +malloc.o free.o realloc.o memalign.o: malloc.h +# Depend on uClinux_config.h to cache changes in __UCLIBC_MALLOC_DEBUGGING__ +$(STDLIB_MALLOC_OBJ): $(STDLIB_MALLOC_DIR)/heap.h $(top_builddir)include/bits/uClibc_config.h diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc/calloc.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc/calloc.c new file mode 100644 index 00000000..7ac94b83 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc/calloc.c @@ -0,0 +1,42 @@ +/* vi: set sw=4 ts=4: */ +/* calloc for uClibc + * + * Copyright (C) 2002 by Erik Andersen + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License + * for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include + + +void * calloc(size_t nmemb, size_t lsize) +{ + void *result; + size_t size=lsize * nmemb; + + /* guard vs integer overflow, but allow nmemb + * to fall through and call malloc(0) */ + if (nmemb && lsize != (size / nmemb)) { + __set_errno(ENOMEM); + return NULL; + } + if ((result=malloc(size)) != NULL) { + memset(result, 0, size); + } + return result; +} + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc/free.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc/free.c new file mode 100644 index 00000000..e7b6a290 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc/free.c @@ -0,0 +1,272 @@ +/* + * libc/stdlib/malloc/free.c -- free function + * + * Copyright (C) 2002,03 NEC Electronics Corporation + * Copyright (C) 2002,03 Miles Bader + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + * + * Written by Miles Bader + */ + +#include +#include +#include + + +#include "malloc.h" +#include "heap.h" + +#ifdef HEAP_USE_LOCKING +#define free_to_heap(mem, heap, lck) __free_to_heap(mem, heap, lck) +#else +#define free_to_heap(mem, heap, lck) __free_to_heap(mem, heap) +#endif + +static void +__free_to_heap (void *mem, struct heap_free_area **heap +#ifdef HEAP_USE_LOCKING + , malloc_mutex_t *heap_lock +#endif + ) +{ + size_t size; + struct heap_free_area *fa; + + /* Check for special cases. */ + if (unlikely (! mem)) + return; + + /* Normal free. */ + + MALLOC_DEBUG (1, "free: 0x%lx (base = 0x%lx, total_size = %d)", + (long)mem, (long)MALLOC_BASE (mem), MALLOC_SIZE (mem)); + + size = MALLOC_SIZE (mem); + mem = MALLOC_BASE (mem); + + __heap_lock (heap_lock); + + /* Put MEM back in the heap, and get the free-area it was placed in. */ + fa = __heap_free (heap, mem, size); + + /* See if the free-area FA has grown big enough that it should be + unmapped. */ + if (HEAP_FREE_AREA_SIZE (fa) < MALLOC_UNMAP_THRESHOLD) + /* Nope, nothing left to do, just release the lock. */ + __heap_unlock (heap_lock); + else + /* Yup, try to unmap FA. */ + { + unsigned long start = (unsigned long)HEAP_FREE_AREA_START (fa); + unsigned long end = (unsigned long)HEAP_FREE_AREA_END (fa); +#ifndef MALLOC_USE_SBRK +# ifdef __UCLIBC_UCLINUX_BROKEN_MUNMAP__ + struct malloc_mmb *mmb, *prev_mmb; + unsigned long mmb_start, mmb_end; +# else /* !__UCLIBC_UCLINUX_BROKEN_MUNMAP__ */ + unsigned long unmap_start, unmap_end; +# endif /* __UCLIBC_UCLINUX_BROKEN_MUNMAP__ */ +#endif /* !MALLOC_USE_SBRK */ + +#ifdef MALLOC_USE_SBRK + /* Get the sbrk lock so that the two possible calls to sbrk below + are guaranteed to be contiguous. */ + __malloc_lock_sbrk (); + /* When using sbrk, we only shrink the heap from the end. It would + be possible to allow _both_ -- shrinking via sbrk when possible, + and otherwise shrinking via munmap, but this results in holes in + memory that prevent the brk from every growing back down; since + we only ever grow the heap via sbrk, this tends to produce a + continuously growing brk (though the actual memory is unmapped), + which could eventually run out of address space. Note that + `sbrk(0)' shouldn't normally do a system call, so this test is + reasonably cheap. */ + if ((void *)end != sbrk (0)) + { + MALLOC_DEBUG (-1, "not unmapping: 0x%lx - 0x%lx (%ld bytes)", + start, end, end - start); + __malloc_unlock_sbrk (); + __heap_unlock (heap_lock); + return; + } +#endif + + MALLOC_DEBUG (0, "unmapping: 0x%lx - 0x%lx (%ld bytes)", + start, end, end - start); + + /* Remove FA from the heap. */ + __heap_delete (heap, fa); + + if (__heap_is_empty (heap)) + /* We want to avoid the heap from losing all memory, so reserve + a bit. This test is only a heuristic -- the existance of + another free area, even if it's smaller than + MALLOC_MIN_SIZE, will cause us not to reserve anything. */ + { + /* Put the reserved memory back in the heap; we assume that + MALLOC_UNMAP_THRESHOLD is greater than MALLOC_MIN_SIZE, so + we use the latter unconditionally here. */ + __heap_free (heap, (void *)start, MALLOC_MIN_SIZE); + start += MALLOC_MIN_SIZE; + } + +#ifdef MALLOC_USE_SBRK + + /* Release the heap lock; we're still holding the sbrk lock. */ + __heap_unlock (heap_lock); + /* Lower the brk. */ + sbrk (start - end); + /* Release the sbrk lock too; now we hold no locks. */ + __malloc_unlock_sbrk (); + +#else /* !MALLOC_USE_SBRK */ + +# ifdef __UCLIBC_UCLINUX_BROKEN_MUNMAP__ + /* Using the uClinux broken munmap, we have to only munmap blocks + exactly as we got them from mmap, so scan through our list of + mmapped blocks, and return them in order. */ + + MALLOC_MMB_DEBUG (1, "walking mmb list for region 0x%x[%d]...", + start, end - start); + + prev_mmb = 0; + mmb = __malloc_mmapped_blocks; + while (mmb + && ((mmb_end = (mmb_start = (unsigned long)mmb->mem) + mmb->size) + <= end)) + { + MALLOC_MMB_DEBUG (1, "considering mmb at 0x%x: 0x%x[%d]", + (unsigned)mmb, mmb_start, mmb_end - mmb_start); + + if (mmb_start >= start + /* If the space between START and MMB_START is non-zero, but + too small to return to the heap, we can't unmap MMB. */ + && (start == mmb_start + || mmb_start - start > HEAP_MIN_FREE_AREA_SIZE)) + { + struct malloc_mmb *next_mmb = mmb->next; + + if (mmb_end != end && mmb_end + HEAP_MIN_FREE_AREA_SIZE > end) + /* There's too little space left at the end to deallocate + this block, so give up. */ + break; + + MALLOC_MMB_DEBUG (1, "unmapping mmb at 0x%x: 0x%x[%d]", + (unsigned)mmb, mmb_start, mmb_end - mmb_start); + + if (mmb_start != start) + /* We're going to unmap a part of the heap that begins after + start, so put the intervening region back into the heap. */ + { + MALLOC_MMB_DEBUG (0, "putting intervening region back into heap: 0x%x[%d]", + start, mmb_start - start); + __heap_free (heap, (void *)start, mmb_start - start); + } + + MALLOC_MMB_DEBUG_INDENT (-1); + + /* Unlink MMB from the list. */ + if (prev_mmb) + prev_mmb->next = next_mmb; + else + __malloc_mmapped_blocks = next_mmb; + + /* Start searching again from the end of this block. */ + start = mmb_end; + + /* Release the descriptor block we used. */ + free_to_heap (mmb, &__malloc_mmb_heap, &__malloc_mmb_heap_lock); + + /* We have to unlock the heap before we recurse to free the mmb + descriptor, because we might be unmapping from the mmb + heap. */ + __heap_unlock (heap_lock); + + /* Do the actual munmap. */ + munmap ((void *)mmb_start, mmb_end - mmb_start); + + __heap_lock (heap_lock); + +# ifdef __UCLIBC_HAS_THREADS__ + /* In a multi-threaded program, it's possible that PREV_MMB has + been invalidated by another thread when we released the + heap lock to do the munmap system call, so just start over + from the beginning of the list. It sucks, but oh well; + it's probably not worth the bother to do better. */ + prev_mmb = 0; + mmb = __malloc_mmapped_blocks; +# else + mmb = next_mmb; +# endif + } + else + { + prev_mmb = mmb; + mmb = mmb->next; + } + + MALLOC_MMB_DEBUG_INDENT (-1); + } + + if (start != end) + /* Hmm, well there's something we couldn't unmap, so put it back + into the heap. */ + { + MALLOC_MMB_DEBUG (0, "putting tail region back into heap: 0x%x[%d]", + start, end - start); + __heap_free (heap, (void *)start, end - start); + } + + /* Finally release the lock for good. */ + __heap_unlock (heap_lock); + + MALLOC_MMB_DEBUG_INDENT (-1); + +# else /* !__UCLIBC_UCLINUX_BROKEN_MUNMAP__ */ + + /* MEM/LEN may not be page-aligned, so we have to page-align them, + and return any left-over bits on the end to the heap. */ + unmap_start = MALLOC_ROUND_UP_TO_PAGE_SIZE (start); + unmap_end = MALLOC_ROUND_DOWN_TO_PAGE_SIZE (end); + + /* We have to be careful that any left-over bits are large enough to + return. Note that we _don't check_ to make sure there's room to + grow/shrink the start/end by another page, we just assume that + the unmap threshold is high enough so that this is always safe + (i.e., it should probably be at least 3 pages). */ + if (unmap_start > start) + { + if (unmap_start - start < HEAP_MIN_FREE_AREA_SIZE) + unmap_start += MALLOC_PAGE_SIZE; + __heap_free (heap, (void *)start, unmap_start - start); + } + if (end > unmap_end) + { + if (end - unmap_end < HEAP_MIN_FREE_AREA_SIZE) + unmap_end -= MALLOC_PAGE_SIZE; + __heap_free (heap, (void *)unmap_end, end - unmap_end); + } + + /* Release the heap lock before we do the system call. */ + __heap_unlock (heap_lock); + + if (unmap_end > unmap_start) + /* Finally, actually unmap the memory. */ + munmap ((void *)unmap_start, unmap_end - unmap_start); + +# endif /* __UCLIBC_UCLINUX_BROKEN_MUNMAP__ */ + +#endif /* MALLOC_USE_SBRK */ + } + + MALLOC_DEBUG_INDENT (-1); +} + +void +free (void *mem) +{ + free_to_heap (mem, &__malloc_heap, &__malloc_heap_lock); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc/heap.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc/heap.h new file mode 100644 index 00000000..30380791 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc/heap.h @@ -0,0 +1,229 @@ +/* + * libc/stdlib/malloc/heap.h -- heap allocator used for malloc + * + * Copyright (C) 2002,03 NEC Electronics Corporation + * Copyright (C) 2002,03 Miles Bader + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + * + * Written by Miles Bader + */ + +#include + + +/* On multi-threaded systems, the heap includes a lock. */ +#ifdef __UCLIBC_HAS_THREADS__ +# include +# define HEAP_USE_LOCKING +# define __heap_lock(heap_lock) __UCLIBC_MUTEX_LOCK_CANCEL_UNSAFE(*(heap_lock)) +# define __heap_unlock(heap_lock) __UCLIBC_MUTEX_UNLOCK_CANCEL_UNSAFE(*(heap_lock)) +#else +# define __heap_lock(heap_lock) +# define __heap_unlock(heap_lock) +#endif + + +/* The heap allocates in multiples of, and aligned to, HEAP_GRANULARITY. + HEAP_GRANULARITY must be a power of 2. Malloc depends on this being the + same as MALLOC_ALIGNMENT. */ +#define HEAP_GRANULARITY_TYPE double __attribute_aligned__ (sizeof (size_t)) +#define HEAP_GRANULARITY (__alignof__ (HEAP_GRANULARITY_TYPE)) + + +/* The HEAP_INIT macro can be used as a static initializer for a heap + variable. The HEAP_INIT_WITH_FA variant is used to initialize a heap + with an initial static free-area; its argument FA should be declared + using HEAP_DECLARE_STATIC_FREE_AREA. */ +# define HEAP_INIT 0 +# define HEAP_INIT_WITH_FA(fa) &fa._fa + +/* A free-list area `header'. These are actually stored at the _ends_ of + free areas (to make allocating from the beginning of the area simpler), + so one might call it a `footer'. */ +struct heap_free_area +{ + size_t size; + struct heap_free_area *next, *prev; +}; + +/* Return the address of the end of the frea area FA. */ +#define HEAP_FREE_AREA_END(fa) ((void *)(fa + 1)) +/* Return the address of the beginning of the frea area FA. FA is + evaulated multiple times. */ +#define HEAP_FREE_AREA_START(fa) ((void *)((char *)(fa + 1) - (fa)->size)) +/* Return the size of the frea area FA. */ +#define HEAP_FREE_AREA_SIZE(fa) ((fa)->size) + +/* This rather clumsy macro allows one to declare a static free-area for + passing to HEAP_INIT_WITH_FA initializer macro. This is only use for + which NAME is allowed. */ +#define HEAP_DECLARE_STATIC_FREE_AREA(name, size) \ + static struct \ + { \ + HEAP_GRANULARITY_TYPE aligned_space; \ + char space[HEAP_ADJUST_SIZE(size) \ + - sizeof (struct heap_free_area) \ + - HEAP_GRANULARITY]; \ + struct heap_free_area _fa; \ + } name = { (HEAP_GRANULARITY_TYPE)0, "", { HEAP_ADJUST_SIZE(size), 0, 0 } } + + +/* Rounds SZ up to be a multiple of HEAP_GRANULARITY. */ +#define HEAP_ADJUST_SIZE(sz) \ + (((sz) + HEAP_GRANULARITY - 1) & ~(HEAP_GRANULARITY - 1)) + + +/* The minimum allocatable size. */ +#define HEAP_MIN_SIZE HEAP_ADJUST_SIZE (sizeof (struct heap_free_area)) + +/* The minimum size of a free area; if allocating memory from a free-area + would make the free-area smaller than this, the allocation is simply + given the whole free-area instead. It must include at least enough room + to hold a struct heap_free_area, plus some extra to avoid excessive heap + fragmentation (thus increasing speed). This is only a heuristic -- it's + possible for smaller free-areas than this to exist (say, by realloc + returning the tail-end of a previous allocation), but __heap_alloc will + try to get rid of them when possible. */ +#define HEAP_MIN_FREE_AREA_SIZE \ + HEAP_ADJUST_SIZE (sizeof (struct heap_free_area) + 32) + + +/* branch-prediction macros; they may already be defined by libc. */ +#ifndef likely +#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96) +#define likely(cond) __builtin_expect(!!(int)(cond), 1) +#define unlikely(cond) __builtin_expect((int)(cond), 0) +#else +#define likely(cond) (cond) +#define unlikely(cond) (cond) +#endif +#endif /* !likely */ + + +/* Define HEAP_DEBUGGING to cause the heap routines to emit debugging info + to stderr when the variable __heap_debug is set to true. */ +#ifdef HEAP_DEBUGGING +extern int __heap_debug; +#define HEAP_DEBUG(heap, str) (__heap_debug ? __heap_dump (heap, str) : 0) +#else +#define HEAP_DEBUG(heap, str) (void)0 +#endif + +/* Output a text representation of HEAP to stderr, labelling it with STR. */ +extern void __heap_dump (struct heap_free_area *heap, const char *str); + +/* Do some consistency checks on HEAP. If they fail, output an error + message to stderr, and exit. STR is printed with the failure message. */ +extern void __heap_check (struct heap_free_area *heap, const char *str); + + +/* Delete the free-area FA from HEAP. */ +static __inline__ void +__heap_delete (struct heap_free_area **heap, struct heap_free_area *fa) +{ + if (fa->next) + fa->next->prev = fa->prev; + if (fa->prev) + fa->prev->next = fa->next; + else + *heap = fa->next; +} + + +/* Link the free-area FA between the existing free-area's PREV and NEXT in + HEAP. PREV and NEXT may be 0; if PREV is 0, FA is installed as the + first free-area. */ +static __inline__ void +__heap_link_free_area (struct heap_free_area **heap, struct heap_free_area *fa, + struct heap_free_area *prev, + struct heap_free_area *next) +{ + fa->next = next; + fa->prev = prev; + + if (prev) + prev->next = fa; + else + *heap = fa; + if (next) + next->prev = fa; +} + +/* Update the mutual links between the free-areas PREV and FA in HEAP. + PREV may be 0, in which case FA is installed as the first free-area (but + FA may not be 0). */ +static __inline__ void +__heap_link_free_area_after (struct heap_free_area **heap, + struct heap_free_area *fa, + struct heap_free_area *prev) +{ + if (prev) + prev->next = fa; + else + *heap = fa; + fa->prev = prev; +} + +/* Add a new free-area MEM, of length SIZE, in between the existing + free-area's PREV and NEXT in HEAP, and return a pointer to its header. + PREV and NEXT may be 0; if PREV is 0, MEM is installed as the first + free-area. */ +static __inline__ struct heap_free_area * +__heap_add_free_area (struct heap_free_area **heap, void *mem, size_t size, + struct heap_free_area *prev, + struct heap_free_area *next) +{ + struct heap_free_area *fa = (struct heap_free_area *) + ((char *)mem + size - sizeof (struct heap_free_area)); + + fa->size = size; + + __heap_link_free_area (heap, fa, prev, next); + + return fa; +} + + +/* Allocate SIZE bytes from the front of the free-area FA in HEAP, and + return the amount actually allocated (which may be more than SIZE). */ +static __inline__ size_t +__heap_free_area_alloc (struct heap_free_area **heap, + struct heap_free_area *fa, size_t size) +{ + size_t fa_size = fa->size; + + if (fa_size < size + HEAP_MIN_FREE_AREA_SIZE) + /* There's not enough room left over in FA after allocating the block, so + just use the whole thing, removing it from the list of free areas. */ + { + __heap_delete (heap, fa); + /* Remember that we've alloced the whole area. */ + size = fa_size; + } + else + /* Reduce size of FA to account for this allocation. */ + fa->size = fa_size - size; + + return size; +} + + +/* Allocate and return a block at least *SIZE bytes long from HEAP. + *SIZE is adjusted to reflect the actual amount allocated (which may be + greater than requested). */ +extern void *__heap_alloc (struct heap_free_area **heap, size_t *size); + +/* Allocate SIZE bytes at address MEM in HEAP. Return the actual size + allocated, or 0 if we failed. */ +extern size_t __heap_alloc_at (struct heap_free_area **heap, void *mem, size_t size); + +/* Return the memory area MEM of size SIZE to HEAP. + Returns the heap free area into which the memory was placed. */ +extern struct heap_free_area *__heap_free (struct heap_free_area **heap, + void *mem, size_t size); + +/* Return true if HEAP contains absolutely no memory. */ +#define __heap_is_empty(heap) (! (heap)) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc/heap_alloc.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc/heap_alloc.c new file mode 100644 index 00000000..77b7d856 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc/heap_alloc.c @@ -0,0 +1,51 @@ +/* + * libc/stdlib/malloc/heap_alloc.c -- allocate memory from a heap + * + * Copyright (C) 2002 NEC Corporation + * Copyright (C) 2002 Miles Bader + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + * + * Written by Miles Bader + */ + +#include + +#include "heap.h" + + +/* Allocate and return a block at least *SIZE bytes long from HEAP. + *SIZE is adjusted to reflect the actual amount allocated (which may be + greater than requested). */ +void * +__heap_alloc (struct heap_free_area **heap, size_t *size) +{ + struct heap_free_area *fa; + size_t _size = *size; + void *mem = 0; + + _size = HEAP_ADJUST_SIZE (_size); + + if (_size < sizeof (struct heap_free_area)) + /* Because we sometimes must use a freed block to hold a free-area node, + we must make sure that every allocated block can hold one. */ + _size = HEAP_ADJUST_SIZE (sizeof (struct heap_free_area)); + + HEAP_DEBUG (*heap, "before __heap_alloc"); + + /* Look for a free area that can contain _SIZE bytes. */ + for (fa = *heap; fa; fa = fa->next) + if (fa->size >= _size) + { + /* Found one! */ + mem = HEAP_FREE_AREA_START (fa); + *size = __heap_free_area_alloc (heap, fa, _size); + break; + } + + HEAP_DEBUG (*heap, "after __heap_alloc"); + + return mem; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc/heap_alloc_at.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc/heap_alloc_at.c new file mode 100644 index 00000000..45d68598 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc/heap_alloc_at.c @@ -0,0 +1,47 @@ +/* + * libc/stdlib/malloc/heap_alloc_at.c -- allocate at a specific address + * + * Copyright (C) 2002 NEC Corporation + * Copyright (C) 2002 Miles Bader + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + * + * Written by Miles Bader + */ + +#include + +#include "heap.h" + + +/* Allocate SIZE bytes at address MEM in HEAP. Return the actual size + allocated, or 0 if we failed. */ +size_t +__heap_alloc_at (struct heap_free_area **heap, void *mem, size_t size) +{ + struct heap_free_area *fa; + size_t alloced = 0; + + size = HEAP_ADJUST_SIZE (size); + + HEAP_DEBUG (*heap, "before __heap_alloc_at"); + + /* Look for a free area that can contain SIZE bytes. */ + for (fa = *heap; fa; fa = fa->next) + { + void *fa_mem = HEAP_FREE_AREA_START (fa); + if (fa_mem <= mem) + { + if (fa_mem == mem && fa->size >= size) + /* FA has the right addr, and is big enough! */ + alloced = __heap_free_area_alloc (heap, fa, size); + break; + } + } + + HEAP_DEBUG (*heap, "after __heap_alloc_at"); + + return alloced; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc/heap_debug.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc/heap_debug.c new file mode 100644 index 00000000..5f17aae0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc/heap_debug.c @@ -0,0 +1,144 @@ +/* + * libc/stdlib/malloc/heap_debug.c -- optional heap debugging routines + * + * Copyright (C) 2002 NEC Corporation + * Copyright (C) 2002 Miles Bader + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + * + * Written by Miles Bader + */ + +#include +#include +#include +#include +#include + + +#include "malloc.h" +#include "heap.h" + + +#ifdef HEAP_DEBUGGING +int __heap_debug = 0; +#endif + + +static void +__heap_dump_freelist (struct heap_free_area *heap) +{ + struct heap_free_area *fa; + for (fa = heap; fa; fa = fa->next) + __malloc_debug_printf (0, + "0x%lx: 0x%lx - 0x%lx (%d)\tP=0x%lx, N=0x%lx", + (long)fa, + (long)HEAP_FREE_AREA_START (fa), + (long)HEAP_FREE_AREA_END (fa), + fa->size, + (long)fa->prev, + (long)fa->next); +} + +/* Output a text representation of HEAP to stderr, labelling it with STR. */ +void +__heap_dump (struct heap_free_area *heap, const char *str) +{ + static smallint recursed; + + if (! recursed) + { + __heap_check (heap, str); + + recursed = 1; + + __malloc_debug_printf (1, "%s: heap @0x%lx:", str, (long)heap); + __heap_dump_freelist (heap); + __malloc_debug_indent (-1); + + recursed = 0; + } +} + + +/* Output an error message to stderr, and exit. STR is printed with the + failure message. */ +static void attribute_noreturn +__heap_check_failure (struct heap_free_area *heap, struct heap_free_area *fa, + const char *str, char *fmt, ...) +{ + va_list val; + + if (str) + fprintf (stderr, "\nHEAP CHECK FAILURE %s: ", str); + else + fprintf (stderr, "\nHEAP CHECK FAILURE: "); + + va_start (val, fmt); + vfprintf (stderr, fmt, val); + va_end (val); + + fprintf (stderr, "\n"); + + __malloc_debug_set_indent (0); + __malloc_debug_printf (1, "heap dump:"); + __heap_dump_freelist (heap); + + _exit (22); +} + +/* Do some consistency checks on HEAP. If they fail, output an error + message to stderr, and exit. STR is printed with the failure message. */ +void +__heap_check (struct heap_free_area *heap, const char *str) +{ + typedef unsigned long ul_t; + struct heap_free_area *fa, *prev; + struct heap_free_area *first_fa = heap; + + if (first_fa && first_fa->prev) + __heap_check_failure (heap, first_fa, str, +"first free-area has non-zero prev pointer:\n\ + first free-area = 0x%lx\n\ + (0x%lx)->prev = 0x%lx\n", + (ul_t)first_fa, + (ul_t)first_fa, (ul_t)first_fa->prev); + + for (prev = 0, fa = first_fa; fa; prev = fa, fa = fa->next) + { + if (((ul_t)HEAP_FREE_AREA_END (fa) & (HEAP_GRANULARITY - 1)) + || (fa->size & (HEAP_GRANULARITY - 1))) + __heap_check_failure (heap, fa, str, "alignment error:\n\ + (0x%lx)->start = 0x%lx\n\ + (0x%lx)->size = 0x%lx\n", + (ul_t)fa, + (ul_t)HEAP_FREE_AREA_START (fa), + (ul_t)fa, fa->size); + + if (fa->prev != prev) + __heap_check_failure (heap, fa, str, "prev pointer corrupted:\n\ + (0x%lx)->next = 0x%lx\n\ + (0x%lx)->prev = 0x%lx\n", + (ul_t)prev, (ul_t)prev->next, + (ul_t)fa, (ul_t)fa->prev); + + if (prev) + { + ul_t start = (ul_t)HEAP_FREE_AREA_START (fa); + ul_t prev_end = (ul_t)HEAP_FREE_AREA_END (prev); + + if (prev_end >= start) + __heap_check_failure (heap, fa, str, + "start %s with prev free-area end:\n\ + (0x%lx)->prev = 0x%lx\n\ + (0x%lx)->start = 0x%lx\n\ + (0x%lx)->end = 0x%lx\n", + (prev_end == start ? "unmerged" : "overlaps"), + (ul_t)fa, (ul_t)prev, + (ul_t)fa, start, + (ul_t)prev, prev_end); + } + } +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc/heap_free.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc/heap_free.c new file mode 100644 index 00000000..15343c05 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc/heap_free.c @@ -0,0 +1,89 @@ +/* + * libc/stdlib/malloc/heap_free.c -- return memory to a heap + * + * Copyright (C) 2002 NEC Corporation + * Copyright (C) 2002 Miles Bader + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + * + * Written by Miles Bader + */ + +#include + +#include "heap.h" + + +/* Return the block of memory at MEM, of size SIZE, to HEAP. */ +struct heap_free_area * +__heap_free (struct heap_free_area **heap, void *mem, size_t size) +{ + struct heap_free_area *fa, *prev_fa; + void *end = (char *)mem + size; + + HEAP_DEBUG (*heap, "before __heap_free"); + + /* Find the right position in the free-list entry to place the new block. + This is the most speed critical loop in this malloc implementation: + since we use a simple linked-list for the free-list, and we keep it in + address-sorted order, it can become very expensive to insert something + in the free-list when it becomes fragmented and long. [A better + implemention would use a balanced tree or something for the free-list, + though that bloats the code-size and complexity quite a bit.] */ + for (prev_fa = 0, fa = *heap; fa; prev_fa = fa, fa = fa->next) + if (unlikely (HEAP_FREE_AREA_END (fa) >= mem)) + break; + + if (fa && HEAP_FREE_AREA_START (fa) <= end) + /* The free-area FA is adjacent to the new block, merge them. */ + { + size_t fa_size = fa->size + size; + + if (HEAP_FREE_AREA_START (fa) == end) + /* FA is just after the new block, grow down to encompass it. */ + { + /* See if FA can now be merged with its predecessor. */ + if (prev_fa && mem == HEAP_FREE_AREA_END (prev_fa)) + /* Yup; merge PREV_FA's info into FA. */ + { + fa_size += prev_fa->size; + __heap_link_free_area_after (heap, fa, prev_fa->prev); + } + } + else + /* FA is just before the new block, expand to encompass it. */ + { + struct heap_free_area *next_fa = fa->next; + + /* See if FA can now be merged with its successor. */ + if (next_fa && end == HEAP_FREE_AREA_START (next_fa)) + /* Yup; merge FA's info into NEXT_FA. */ + { + fa_size += next_fa->size; + __heap_link_free_area_after (heap, next_fa, prev_fa); + fa = next_fa; + } + else + /* FA can't be merged; move the descriptor for it to the tail-end + of the memory block. */ + { + /* The new descriptor is at the end of the extended block, + SIZE bytes later than the old descriptor. */ + fa = (struct heap_free_area *)((char *)fa + size); + /* Update links with the neighbors in the list. */ + __heap_link_free_area (heap, fa, prev_fa, next_fa); + } + } + + fa->size = fa_size; + } + else + /* Make the new block into a separate free-list entry. */ + fa = __heap_add_free_area (heap, mem, size, prev_fa, fa); + + HEAP_DEBUG (*heap, "after __heap_free"); + + return fa; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc/malloc.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc/malloc.c new file mode 100644 index 00000000..d58a7d0e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc/malloc.c @@ -0,0 +1,233 @@ +/* + * libc/stdlib/malloc/malloc.c -- malloc function + * + * Copyright (C) 2002,03 NEC Electronics Corporation + * Copyright (C) 2002,03 Miles Bader + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + * + * Written by Miles Bader + */ + +#include +#include +#include +#include + + +#include "malloc.h" +#include "heap.h" + + +/* The malloc heap. We provide a bit of initial static space so that + programs can do a little mallocing without mmaping in more space. */ +HEAP_DECLARE_STATIC_FREE_AREA (initial_fa, 256); +struct heap_free_area *__malloc_heap = HEAP_INIT_WITH_FA (initial_fa); +#ifdef HEAP_USE_LOCKING +malloc_mutex_t __malloc_heap_lock = PTHREAD_MUTEX_INITIALIZER; +#endif + +#if defined(MALLOC_USE_LOCKING) && defined(MALLOC_USE_SBRK) +/* A lock protecting our use of sbrk. */ +malloc_mutex_t __malloc_sbrk_lock; +#endif /* MALLOC_USE_LOCKING && MALLOC_USE_SBRK */ + + +#ifdef __UCLIBC_UCLINUX_BROKEN_MUNMAP__ +/* A list of all malloc_mmb structures describing blocks that + malloc has mmapped, ordered by the block address. */ +struct malloc_mmb *__malloc_mmapped_blocks = 0; + +/* A heap used for allocating malloc_mmb structures. We could allocate + them from the main heap, but that tends to cause heap fragmentation in + annoying ways. */ +HEAP_DECLARE_STATIC_FREE_AREA (initial_mmb_fa, 48); /* enough for 3 mmbs */ +struct heap_free_area *__malloc_mmb_heap = HEAP_INIT_WITH_FA (initial_mmb_fa); +#ifdef HEAP_USE_LOCKING +malloc_mutex_t __malloc_mmb_heap_lock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; +#endif +#endif /* __UCLIBC_UCLINUX_BROKEN_MUNMAP__ */ + + +#ifdef HEAP_USE_LOCKING +#define malloc_from_heap(size, heap, lck) __malloc_from_heap(size, heap, lck) +#else +#define malloc_from_heap(size, heap, lck) __malloc_from_heap(size, heap) +#endif +static void * +__malloc_from_heap (size_t size, struct heap_free_area **heap +#ifdef HEAP_USE_LOCKING + , malloc_mutex_t *heap_lock +#endif + ) +{ + void *mem; + + MALLOC_DEBUG (1, "malloc: %d bytes", size); + + /* Include extra space to record the size of the allocated block. */ + size += MALLOC_HEADER_SIZE; + + __heap_lock (heap_lock); + + /* First try to get memory that's already in our heap. */ + mem = __heap_alloc (heap, &size); + + __heap_unlock (heap_lock); + + if (unlikely (! mem)) + /* We couldn't allocate from the heap, so grab some more + from the system, add it to the heap, and try again. */ + { + /* If we're trying to allocate a block bigger than the default + MALLOC_HEAP_EXTEND_SIZE, make sure we get enough to hold it. */ + void *block; + size_t block_size + = (size < MALLOC_HEAP_EXTEND_SIZE + ? MALLOC_HEAP_EXTEND_SIZE + : MALLOC_ROUND_UP_TO_PAGE_SIZE (size)); + + /* Allocate the new heap block. */ +#ifdef MALLOC_USE_SBRK + + __malloc_lock_sbrk (); + + /* Use sbrk we can, as it's faster than mmap, and guarantees + contiguous allocation. */ + block = sbrk (block_size); + if (likely (block != (void *)-1)) + { + /* Because sbrk can return results of arbitrary + alignment, align the result to a MALLOC_ALIGNMENT boundary. */ + long aligned_block = MALLOC_ROUND_UP ((long)block, MALLOC_ALIGNMENT); + if (block != (void *)aligned_block) + /* Have to adjust. We should only have to actually do this + the first time (after which we will have aligned the brk + correctly). */ + { + /* Move the brk to reflect the alignment; our next allocation + should start on exactly the right alignment. */ + sbrk (aligned_block - (long)block); + block = (void *)aligned_block; + } + } + + __malloc_unlock_sbrk (); + +#else /* !MALLOC_USE_SBRK */ + + /* Otherwise, use mmap. */ +#ifdef __ARCH_USE_MMU__ + block = mmap ((void *)0, block_size, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, 0, 0); +#else + block = mmap ((void *)0, block_size, PROT_READ | PROT_WRITE, + MAP_SHARED | MAP_ANONYMOUS | MAP_UNINITIALIZE, 0, 0); +#endif + +#endif /* MALLOC_USE_SBRK */ + + if (likely (block != (void *)-1)) + { +#if !defined(MALLOC_USE_SBRK) && defined(__UCLIBC_UCLINUX_BROKEN_MUNMAP__) + struct malloc_mmb *mmb, *prev_mmb, *new_mmb; +#endif + + MALLOC_DEBUG (1, "adding system memory to heap: 0x%lx - 0x%lx (%d bytes)", + (long)block, (long)block + block_size, block_size); + + /* Get back the heap lock. */ + __heap_lock (heap_lock); + + /* Put BLOCK into the heap. */ + __heap_free (heap, block, block_size); + + MALLOC_DEBUG_INDENT (-1); + + /* Try again to allocate. */ + mem = __heap_alloc (heap, &size); + + +#if !defined(MALLOC_USE_SBRK) && defined(__UCLIBC_UCLINUX_BROKEN_MUNMAP__) + /* Insert a record of BLOCK in sorted order into the + __malloc_mmapped_blocks list. */ + + new_mmb = malloc_from_heap (sizeof *new_mmb, &__malloc_mmb_heap, &__malloc_mmb_heap_lock); + + for (prev_mmb = 0, mmb = __malloc_mmapped_blocks; + mmb; + prev_mmb = mmb, mmb = mmb->next) + if (block < mmb->mem) + break; + + new_mmb->next = mmb; + new_mmb->mem = block; + new_mmb->size = block_size; + + if (prev_mmb) + prev_mmb->next = new_mmb; + else + __malloc_mmapped_blocks = new_mmb; + + MALLOC_MMB_DEBUG (0, "new mmb at 0x%x: 0x%x[%d]", + (unsigned)new_mmb, + (unsigned)new_mmb->mem, block_size); +#endif /* !MALLOC_USE_SBRK && __UCLIBC_UCLINUX_BROKEN_MUNMAP__ */ + __heap_unlock (heap_lock); + } + } + + if (likely (mem)) + /* Record the size of the block and get the user address. */ + { + mem = MALLOC_SETUP (mem, size); + + MALLOC_DEBUG (-1, "malloc: returning 0x%lx (base:0x%lx, total_size:%ld)", + (long)mem, (long)MALLOC_BASE(mem), (long)MALLOC_SIZE(mem)); + } + else + MALLOC_DEBUG (-1, "malloc: returning 0"); + + return mem; +} + +void * +malloc (size_t size) +{ + void *mem; +#ifdef MALLOC_DEBUGGING + static smallint debugging_initialized; + if (! debugging_initialized) + { + debugging_initialized = 1; + __malloc_debug_init (); + } + if (__malloc_check) + __heap_check (__malloc_heap, "malloc"); +#endif + +#ifdef __MALLOC_GLIBC_COMPAT__ + if (unlikely (size == 0)) + size++; +#else + /* Some programs will call malloc (0). Lets be strict and return NULL */ + if (unlikely (size == 0)) + goto oom; +#endif + + /* Check if they are doing something dumb like malloc(-1) */ + if (unlikely(((unsigned long)size > (unsigned long)(MALLOC_HEADER_SIZE*-2)))) + goto oom; + + mem = malloc_from_heap (size, &__malloc_heap, &__malloc_heap_lock); + if (unlikely (!mem)) + { + oom: + __set_errno (ENOMEM); + return 0; + } + + return mem; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc/malloc.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc/malloc.h new file mode 100644 index 00000000..0a4b43b8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc/malloc.h @@ -0,0 +1,229 @@ +/* + * libc/stdlib/malloc/malloc.h -- small malloc implementation + * + * Copyright (C) 2002 NEC Corporation + * Copyright (C) 2002 Miles Bader + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + * + * Written by Miles Bader + */ + +/* The alignment we guarantee for malloc return values. We prefer this + to be at least sizeof (size_t) bytes because (a) we have to allocate + that many bytes for the header anyway and (b) guaranteeing word + alignment can be a significant win on targets like m68k and Coldfire, + where __alignof__(double) == 2. */ +#define MALLOC_ALIGNMENT \ + __alignof__ (double __attribute_aligned__ (sizeof (size_t))) + +/* The system pagesize... */ +extern size_t __pagesize; +#define MALLOC_PAGE_SIZE __pagesize + +/* The minimum size of block we request from the the system to extend the + heap for small allocations (we may request a bigger block if necessary to + satisfy a particularly big request). */ +#define MALLOC_HEAP_EXTEND_SIZE MALLOC_PAGE_SIZE + +/* When a heap free-area grows above this size, try to unmap it, releasing + the memory back to the system. */ +#define MALLOC_UNMAP_THRESHOLD (8*MALLOC_PAGE_SIZE) +/* When unmapping a free-area, retain this many bytes if it's the only one, + to avoid completely emptying the heap. This is only a heuristic -- the + existance of another free area, even if it's smaller than + MALLOC_MIN_SIZE, will cause us not to reserve anything. */ +#define MALLOC_MIN_SIZE (2*MALLOC_PAGE_SIZE) + +/* When realloc shrinks an allocation, it only does so if more than this + many bytes will be freed; it must at at least HEAP_MIN_SIZE. Larger + values increase speed (by reducing heap fragmentation) at the expense of + space. */ +#define MALLOC_REALLOC_MIN_FREE_SIZE (HEAP_MIN_SIZE + 16) + + +/* For systems with an MMU, use sbrk to map/unmap memory for the malloc + heap, instead of mmap/munmap. This is a tradeoff -- sbrk is faster than + mmap/munmap, and guarantees contiguous allocation, but is also less + flexible, and causes the heap to only be shrinkable from the end. */ +#ifdef __ARCH_USE_MMU__ +# define MALLOC_USE_SBRK +#endif + + +/* The current implementation of munmap in uClinux doesn't work correctly: + it requires that ever call to munmap exactly match a corresponding call + to mmap (that is, it doesn't allow you to unmap only part of a + previously allocated block, or to unmap two contiguous blocks with a + single call to munmap). This behavior is broken, and uClinux should be + fixed; however, until it is, we add code to work around the problem in + malloc. */ +#ifdef __UCLIBC_UCLINUX_BROKEN_MUNMAP__ + +/* A structure recording a block of memory mmapped by malloc. */ +struct malloc_mmb +{ + void *mem; /* the mmapped block */ + size_t size; /* its size */ + struct malloc_mmb *next; +}; + +/* A list of all malloc_mmb structures describing blocks that malloc has + mmapped, ordered by the block address. */ +extern struct malloc_mmb *__malloc_mmapped_blocks; + +/* A heap used for allocating malloc_mmb structures. We could allocate + them from the main heap, but that tends to cause heap fragmentation in + annoying ways. */ +extern struct heap_free_area *__malloc_mmb_heap; + +/* Define MALLOC_MMB_DEBUGGING to cause malloc to emit debugging info about + about mmap block allocation/freeing by the `uclinux broken munmap' code + to stderr, when the variable __malloc_mmb_debug is set to true. */ +#ifdef MALLOC_MMB_DEBUGGING +# include + +extern int __malloc_mmb_debug; +# define MALLOC_MMB_DEBUG(indent, fmt, args...) \ + (__malloc_mmb_debug ? __malloc_debug_printf (indent, fmt , ##args) : 0) +# define MALLOC_MMB_DEBUG_INDENT(indent) \ + (__malloc_mmb_debug ? __malloc_debug_indent (indent) : 0) +# ifndef MALLOC_DEBUGGING +# define MALLOC_DEBUGGING +# endif +#else /* !MALLOC_MMB_DEBUGGING */ +# define MALLOC_MMB_DEBUG(fmt, args...) (void)0 +# define MALLOC_MMB_DEBUG_INDENT(indent) (void)0 +#endif /* MALLOC_MMB_DEBUGGING */ + +#endif /* __UCLIBC_UCLINUX_BROKEN_MUNMAP__ */ + + +/* The size of a malloc allocation is stored in a size_t word + MALLOC_HEADER_SIZE bytes prior to the start address of the allocation: + + +--------+---------+-------------------+ + | SIZE |(unused) | allocation ... | + +--------+---------+-------------------+ + ^ BASE ^ ADDR + ^ ADDR - MALLOC_HEADER_SIZE +*/ + +/* The amount of extra space used by the malloc header. */ +#define MALLOC_HEADER_SIZE \ + (MALLOC_ALIGNMENT < sizeof (size_t) \ + ? sizeof (size_t) \ + : MALLOC_ALIGNMENT) + +/* Set up the malloc header, and return the user address of a malloc block. */ +#define MALLOC_SETUP(base, size) \ + (MALLOC_SET_SIZE (base, size), (void *)((char *)base + MALLOC_HEADER_SIZE)) +/* Set the size of a malloc allocation, given the base address. */ +#define MALLOC_SET_SIZE(base, size) (*(size_t *)(base) = (size)) + +/* Return base-address of a malloc allocation, given the user address. */ +#define MALLOC_BASE(addr) ((void *)((char *)addr - MALLOC_HEADER_SIZE)) +/* Return the size of a malloc allocation, given the user address. */ +#define MALLOC_SIZE(addr) (*(size_t *)MALLOC_BASE(addr)) + + +/* Locking for multithreaded apps. */ +#ifdef __UCLIBC_HAS_THREADS__ + +# include + +# define MALLOC_USE_LOCKING + +typedef __UCLIBC_MUTEX_TYPE malloc_mutex_t; +# define MALLOC_MUTEX_INIT __UCLIBC_MUTEX_INITIALIZER + +# ifdef MALLOC_USE_SBRK +/* This lock is used to serialize uses of the `sbrk' function (in both + malloc and free, sbrk may be used several times in succession, and + things will break if these multiple calls are interleaved with another + thread's use of sbrk!). */ +extern malloc_mutex_t __malloc_sbrk_lock; +# define __malloc_lock_sbrk() __UCLIBC_MUTEX_LOCK_CANCEL_UNSAFE (__malloc_sbrk_lock) +# define __malloc_unlock_sbrk() __UCLIBC_MUTEX_UNLOCK_CANCEL_UNSAFE (__malloc_sbrk_lock) +# endif /* MALLOC_USE_SBRK */ + +#else /* !__UCLIBC_HAS_THREADS__ */ + +/* Without threads, mutex operations are a nop. */ +# define __malloc_lock_sbrk() (void)0 +# define __malloc_unlock_sbrk() (void)0 + +#endif /* __UCLIBC_HAS_THREADS__ */ + + +/* branch-prediction macros; they may already be defined by libc. */ +#ifndef likely +#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96) +#define likely(cond) __builtin_expect(!!(int)(cond), 1) +#define unlikely(cond) __builtin_expect((int)(cond), 0) +#else +#define likely(cond) (cond) +#define unlikely(cond) (cond) +#endif +#endif /* !likely */ + + +/* Define MALLOC_DEBUGGING to cause malloc to emit debugging info to stderr + when the variable __malloc_debug is set to true. */ +#ifdef MALLOC_DEBUGGING + +extern void __malloc_debug_init (void); + +/* The number of spaces in a malloc debug indent level. */ +#define MALLOC_DEBUG_INDENT_SIZE 3 + +extern int __malloc_debug, __malloc_check; + +# define MALLOC_DEBUG(indent, fmt, args...) \ + (__malloc_debug ? __malloc_debug_printf (indent, fmt , ##args) : 0) +# define MALLOC_DEBUG_INDENT(indent) \ + (__malloc_debug ? __malloc_debug_indent (indent) : 0) + +extern int __malloc_debug_cur_indent; + +/* Print FMT and args indented at the current debug print level, followed + by a newline, and change the level by INDENT. */ +extern void __malloc_debug_printf (int indent, const char *fmt, ...); + +/* Change the current debug print level by INDENT, and return the value. */ +#define __malloc_debug_indent(indent) (__malloc_debug_cur_indent += indent) + +/* Set the current debug print level to LEVEL. */ +#define __malloc_debug_set_indent(level) (__malloc_debug_cur_indent = level) + +#else /* !MALLOC_DEBUGGING */ +# define MALLOC_DEBUG(fmt, args...) (void)0 +# define MALLOC_DEBUG_INDENT(indent) (void)0 +#endif /* MALLOC_DEBUGGING */ + + +/* Return SZ rounded down to POWER_OF_2_SIZE (which must be power of 2). */ +#define MALLOC_ROUND_DOWN(sz, power_of_2_size) \ + ((sz) & ~(power_of_2_size - 1)) +/* Return SZ rounded to POWER_OF_2_SIZE (which must be power of 2). */ +#define MALLOC_ROUND_UP(sz, power_of_2_size) \ + MALLOC_ROUND_DOWN ((sz) + (power_of_2_size - 1), (power_of_2_size)) + +/* Return SZ rounded down to a multiple MALLOC_PAGE_SIZE. */ +#define MALLOC_ROUND_DOWN_TO_PAGE_SIZE(sz) \ + MALLOC_ROUND_DOWN (sz, MALLOC_PAGE_SIZE) +/* Return SZ rounded up to a multiple MALLOC_PAGE_SIZE. */ +#define MALLOC_ROUND_UP_TO_PAGE_SIZE(sz) \ + MALLOC_ROUND_UP (sz, MALLOC_PAGE_SIZE) + + +/* The malloc heap. */ +extern struct heap_free_area *__malloc_heap; +#ifdef __UCLIBC_HAS_THREADS__ +extern malloc_mutex_t __malloc_heap_lock; +#ifdef __UCLIBC_UCLINUX_BROKEN_MUNMAP__ +extern malloc_mutex_t __malloc_mmb_heap_lock; +#endif +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc/malloc_debug.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc/malloc_debug.c new file mode 100644 index 00000000..1a5374fa --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc/malloc_debug.c @@ -0,0 +1,87 @@ +/* + * libc/stdlib/malloc/malloc_debug.c -- malloc debugging support + * + * Copyright (C) 2002 NEC Corporation + * Copyright (C) 2002 Miles Bader + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + * + * Written by Miles Bader + */ + +#include +#include +#include +#include + + +#include "malloc.h" +#include "heap.h" + +int __malloc_debug = 0, __malloc_check = 0; + +#ifdef MALLOC_MMB_DEBUGGING +int __malloc_mmb_debug = 0; +#endif + +/* Debugging output is indented this may levels. */ +int __malloc_debug_cur_indent = 0; + + +/* Print FMT and args indented at the current debug print level, followed + by a newline, and change the level by INDENT. */ +void +__malloc_debug_printf (int indent, const char *fmt, ...) +{ + unsigned spaces = __malloc_debug_cur_indent * MALLOC_DEBUG_INDENT_SIZE; + va_list val; + + while (spaces > 0) + { + putc (' ', stderr); + spaces--; + } + + va_start (val, fmt); + vfprintf (stderr, fmt, val); + va_end (val); + + putc ('\n', stderr); + + __malloc_debug_indent (indent); +} + +void +__malloc_debug_init (void) +{ + char *ev = getenv ("MALLOC_DEBUG"); + if (ev) + { + int val = atoi (ev); + + if (val & 1) + __malloc_check = 1; + + if (val & 2) + __malloc_debug = 1; + +#ifdef MALLOC_MMB_DEBUGGING + if (val & 4) + __malloc_mmb_debug = 1; +#endif + +#ifdef HEAP_DEBUGGING + if (val & 8) + __heap_debug = 1; +#endif + + if (val) + __malloc_debug_printf + (0, "malloc_debug: initialized to %d (check = %d, dump = %d, dump_mmb = %d, dump_heap = %d)", + val, + !!(val & 1), !!(val & 2), + !!(val & 4), !!(val & 8)); + } +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc/memalign.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc/memalign.c new file mode 100644 index 00000000..6826d623 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc/memalign.c @@ -0,0 +1,95 @@ +/* + * libc/stdlib/malloc/memalign.c -- memalign (`aligned malloc') function + * + * Copyright (C) 2002 NEC Corporation + * Copyright (C) 2002 Miles Bader + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + * + * Written by Miles Bader + */ + +#include +#include +#include + +#include "malloc.h" +#include "heap.h" + + +#define MAX(x,y) ((x) > (y) ? (x) : (y)) + +/* + ______________________ TOTAL _________________________ + / \ + +---------------+-------------------------+--------------+ + | | | | + +---------------+-------------------------+--------------+ + \____ INIT ____/ \______ RETURNED _______/ \____ END ___/ +*/ + +void *memalign (size_t alignment, size_t size); +void * +memalign (size_t alignment, size_t size) +{ + void *mem, *base; + unsigned long tot_addr, tot_end_addr, addr, end_addr; + struct heap_free_area **heap = &__malloc_heap; + + /* Make SIZE something we like. */ + size = HEAP_ADJUST_SIZE (size); + + /* Use malloc to do the initial allocation, since it deals with getting + system memory. We over-allocate enough to be sure that we'll get + enough memory to hold a properly aligned block of size SIZE, + _somewhere_ in the result. */ + mem = malloc (size + 2 * alignment); + if (! mem) + /* Allocation failed, we can't do anything. */ + return 0; + if (alignment < MALLOC_ALIGNMENT) + return mem; + + /* Remember the base-address, of the allocation, although we normally + use the user-address for calculations, since that's where the + alignment matters. */ + base = MALLOC_BASE (mem); + + /* The bounds of the initial allocation. */ + tot_addr = (unsigned long)mem; + tot_end_addr = (unsigned long)base + MALLOC_SIZE (mem); + + /* Find a likely place inside MEM with the right alignment. */ + addr = MALLOC_ROUND_UP (tot_addr, alignment); + + /* Unless TOT_ADDR was already aligned correctly, we need to return the + initial part of MEM to the heap. */ + if (addr != tot_addr) + { + size_t init_size = addr - tot_addr; + + /* Ensure that memory returned to the heap is large enough. */ + if (init_size < HEAP_MIN_SIZE) + { + addr = MALLOC_ROUND_UP (tot_addr + HEAP_MIN_SIZE, alignment); + init_size = addr - tot_addr; + } + + __heap_free (heap, base, init_size); + + /* Remember that we've freed the initial part of MEM. */ + base += init_size; + } + + /* Return the end part of MEM to the heap, unless it's too small. */ + end_addr = addr + size; + if (end_addr + MALLOC_REALLOC_MIN_FREE_SIZE < tot_end_addr) + __heap_free (heap, (void *)end_addr, tot_end_addr - end_addr); + else + /* We didn't free the end, so include it in the size. */ + end_addr = tot_end_addr; + + return MALLOC_SETUP (base, end_addr - (unsigned long)base); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc/realloc.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc/realloc.c new file mode 100644 index 00000000..8de00665 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/malloc/realloc.c @@ -0,0 +1,100 @@ +/* + * libc/stdlib/malloc/realloc.c -- realloc function + * + * Copyright (C) 2002 NEC Corporation + * Copyright (C) 2002 Miles Bader + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + * + * Written by Miles Bader + */ + +#include +#include +#include + + +#include "malloc.h" +#include "heap.h" + + +void * +realloc (void *mem, size_t new_size) +{ + size_t size; + char *base_mem; + + /* Check for special cases. */ + if (! new_size) + { + free (mem); + return malloc (new_size); + } + if (! mem) + return malloc (new_size); + /* This matches the check in malloc() */ + if (unlikely(((unsigned long)new_size > (unsigned long)(MALLOC_HEADER_SIZE*-2)))) + return NULL; + + /* Normal realloc. */ + + base_mem = MALLOC_BASE (mem); + size = MALLOC_SIZE (mem); + + /* Include extra space to record the size of the allocated block. + Also make sure that we're dealing in a multiple of the heap + allocation unit (SIZE is already guaranteed to be so).*/ + new_size = HEAP_ADJUST_SIZE (new_size + MALLOC_HEADER_SIZE); + + if (new_size < sizeof (struct heap_free_area)) + /* Because we sometimes must use a freed block to hold a free-area node, + we must make sure that every allocated block can hold one. */ + new_size = HEAP_ADJUST_SIZE (sizeof (struct heap_free_area)); + + MALLOC_DEBUG (1, "realloc: 0x%lx, %d (base = 0x%lx, total_size = %d)", + (long)mem, new_size, (long)base_mem, size); + + if (new_size > size) + /* Grow the block. */ + { + size_t extra = new_size - size; + + __heap_lock (&__malloc_heap_lock); + extra = __heap_alloc_at (&__malloc_heap, base_mem + size, extra); + __heap_unlock (&__malloc_heap_lock); + + if (extra) + /* Record the changed size. */ + MALLOC_SET_SIZE (base_mem, size + extra); + else + /* Our attempts to extend MEM in place failed, just + allocate-and-copy. */ + { + void *new_mem = malloc (new_size - MALLOC_HEADER_SIZE); + if (new_mem) + { + memcpy (new_mem, mem, size - MALLOC_HEADER_SIZE); + free (mem); + } + mem = new_mem; + } + } + else if (new_size + MALLOC_REALLOC_MIN_FREE_SIZE <= size) + /* Shrink the block. */ + { + __heap_lock (&__malloc_heap_lock); + __heap_free (&__malloc_heap, base_mem + new_size, size - new_size); + __heap_unlock (&__malloc_heap_lock); + MALLOC_SET_SIZE (base_mem, new_size); + } + + if (mem) + MALLOC_DEBUG (-1, "realloc: returning 0x%lx (base:0x%lx, total_size:%d)", + (long)mem, (long)MALLOC_BASE(mem), (long)MALLOC_SIZE(mem)); + else + MALLOC_DEBUG (-1, "realloc: returning 0"); + + return mem; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/mblen.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/mblen.c new file mode 100644 index 00000000..c7a0ccb6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/mblen.c @@ -0,0 +1,7 @@ +/* Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_mblen +#include "stdlib.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/mbstowcs.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/mbstowcs.c new file mode 100644 index 00000000..f6180037 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/mbstowcs.c @@ -0,0 +1,7 @@ +/* Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_mbstowcs +#include "stdlib.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/mbtowc.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/mbtowc.c new file mode 100644 index 00000000..5d888d16 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/mbtowc.c @@ -0,0 +1,7 @@ +/* Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_mbtowc +#include "stdlib.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/mkdtemp.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/mkdtemp.c new file mode 100644 index 00000000..2bf15ae0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/mkdtemp.c @@ -0,0 +1,38 @@ +/* vi: set sw=4 ts=4: */ +/* Copyright (C) 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include "../misc/internals/tempname.h" + +#ifdef __USE_BSD +/* Generate a unique temporary directory name from TEMPLATE. + The last six characters of TEMPLATE must be "XXXXXX"; + they are replaced with a string that makes the filename unique. + The directory is created, mode 700, and its name is returned. + (This function comes from OpenBSD.) */ +char * mkdtemp (char *template) +{ + if (__gen_tempname (template, __GT_DIR, S_IRUSR | S_IWUSR | S_IXUSR)) + return NULL; + else + return template; +} +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/mkstemp.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/mkstemp.c new file mode 100644 index 00000000..ce7d7dba --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/mkstemp.c @@ -0,0 +1,31 @@ +/* Copyright (C) 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include "../misc/internals/tempname.h" + +/* Generate a unique temporary file name from TEMPLATE. + The last six characters of TEMPLATE must be "XXXXXX"; + they are replaced with a string that makes the filename unique. + Then open the file and return a fd. */ +int mkstemp (char *template) +{ + return __gen_tempname (template, __GT_FILE, S_IRUSR | S_IWUSR); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/mkstemp64.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/mkstemp64.c new file mode 100644 index 00000000..2cdee70a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/mkstemp64.c @@ -0,0 +1,31 @@ +/* Copyright (C) 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include "../misc/internals/tempname.h" + +/* Generate a unique temporary file name from TEMPLATE. + The last six characters of TEMPLATE must be "XXXXXX"; + they are replaced with a string that makes the filename unique. + Then open the file and return a fd. */ +int mkstemp64 (char *template) +{ + return __gen_tempname (template, __GT_BIGFILE, S_IRUSR | S_IWUSR); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/mktemp.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/mktemp.c new file mode 100644 index 00000000..3c922e32 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/mktemp.c @@ -0,0 +1,35 @@ +/* Copyright (C) 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include "../misc/internals/tempname.h" + +/* Generate a unique temporary file name from TEMPLATE. + * The last six characters of TEMPLATE must be "XXXXXX"; + * they are replaced with a string that makes the filename unique. */ +char *mktemp(char *template) +{ + if (__gen_tempname (template, __GT_NOCREATE, 0) < 0) + /* We return the null string if we can't find a unique file name. */ + template[0] = '\0'; + + return template; +} + +link_warning(mktemp, "the use of `mktemp' is dangerous, better use `mkstemp'") diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/mrand48.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/mrand48.c new file mode 100644 index 00000000..b209acd5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/mrand48.c @@ -0,0 +1,33 @@ +/* Copyright (C) 1995, 1996, 1997, 1998, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper >, August 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + + +/* Global state for non-reentrant functions. Defined in drand48-iter.c. */ +extern struct drand48_data __libc_drand48_data attribute_hidden; + +long int mrand48 (void) +{ + long int result; + + jrand48_r (__libc_drand48_data.__x, &__libc_drand48_data, &result); + + return result; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/mrand48_r.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/mrand48_r.c new file mode 100644 index 00000000..86fd6a2b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/mrand48_r.c @@ -0,0 +1,30 @@ +/* Copyright (C) 1995, 1997, 1998, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper >, August 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + + +int mrand48_r (struct drand48_data *buffer, long int *result) +{ + /* Be generous for the arguments, detect some errors. */ + if (buffer == NULL) + return -1; + + return jrand48_r (buffer->__x, buffer, result); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/nrand48.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/nrand48.c new file mode 100644 index 00000000..97c197ca --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/nrand48.c @@ -0,0 +1,33 @@ +/* Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper >, August 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + + +/* Global state for non-reentrant functions. Defined in drand48-iter.c. */ +extern struct drand48_data __libc_drand48_data attribute_hidden; + +long int nrand48 (unsigned short int xsubi[3]) +{ + long int result; + + nrand48_r (xsubi, &__libc_drand48_data, &result); + + return result; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/nrand48_r.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/nrand48_r.c new file mode 100644 index 00000000..0710e90e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/nrand48_r.c @@ -0,0 +1,39 @@ +/* Copyright (C) 1995, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper >, August 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +extern int __drand48_iterate(unsigned short xsubi[3], + struct drand48_data *buffer) attribute_hidden; + +int nrand48_r (unsigned short int xsubi[3], struct drand48_data *buffer, long int *result) +{ + /* Compute next state. */ + if (__drand48_iterate (xsubi, buffer) < 0) + return -1; + + /* Store the result. */ + if (sizeof (unsigned short int) == 2) + *result = xsubi[2] << 15 | xsubi[1] >> 1; + else + *result = xsubi[2] >> 1; + + return 0; +} +libc_hidden_def(nrand48_r) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/old_atexit.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/old_atexit.c new file mode 100644 index 00000000..b15fd0aa --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/old_atexit.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_old_atexit +#include "_atexit.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/on_exit.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/on_exit.c new file mode 100644 index 00000000..cb943aca --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/on_exit.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_on_exit +#include "_atexit.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/posix_memalign.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/posix_memalign.c new file mode 100644 index 00000000..115fb899 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/posix_memalign.c @@ -0,0 +1,42 @@ +/* vi: set sw=4 ts=4: */ +/* posix_memalign for uClibc + * + * Copyright (C) 1996-2002, 2003, 2004, 2005 Free Software Foundation, Inc. + * Copyright (C) 2005 by Erik Andersen + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License + * for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include +#include +#include +#include +#include + +int posix_memalign(void **memptr, size_t alignment, size_t size) +{ + /* Make sure alignment is correct. */ + if (alignment % sizeof(void *) != 0) + /* Skip these checks because the memalign() func does them for us + || !powerof2(alignment / sizeof(void *)) != 0 + || alignment == 0 + */ + return EINVAL; + + *memptr = memalign(alignment, size); + + return (*memptr != NULL ? 0 : ENOMEM); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/ptsname.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/ptsname.c new file mode 100644 index 00000000..ff382330 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/ptsname.c @@ -0,0 +1,192 @@ +/* Copyright (C) 1998, 2000, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Zack Weinberg , 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#if !defined __UNIX98PTY_ONLY__ + +/* Check if DEV corresponds to a master pseudo terminal device. */ +#define MASTER_P(Dev) \ + (major ((Dev)) == 2 \ + || (major ((Dev)) == 4 && minor ((Dev)) >= 128 && minor ((Dev)) < 192) \ + || (major ((Dev)) >= 128 && major ((Dev)) < 136)) + +/* Check if DEV corresponds to a slave pseudo terminal device. */ +#define SLAVE_P(Dev) \ + (major ((Dev)) == 3 \ + || (major ((Dev)) == 4 && minor ((Dev)) >= 192 && minor ((Dev)) < 256) \ + || (major ((Dev)) >= 136 && major ((Dev)) < 144)) + +/* Note that major number 4 corresponds to the old BSD style pseudo + terminal devices. As of Linux 2.1.115 these are no longer + supported. They have been replaced by major numbers 2 (masters) + and 3 (slaves). */ + +/* The are declared in getpt.c. */ +extern const char __libc_ptyname1[] attribute_hidden; +extern const char __libc_ptyname2[] attribute_hidden; + +#endif + +/* Directory where we can find the slave pty nodes. */ +#define _PATH_DEVPTS "/dev/pts/" + +/* Store at most BUFLEN characters of the pathname of the slave pseudo + terminal associated with the master FD is open on in BUF. + Return 0 on success, otherwise an error number. */ +int ptsname_r (int fd, char *buf, size_t buflen) +{ + int save_errno = errno; +#if !defined __UNIX98PTY_ONLY__ + struct stat st; +#endif + int ptyno; + + if (buf == NULL) + { + errno = EINVAL; + return EINVAL; + } + +#if !defined __UNIX98PTY_ONLY__ + if (!isatty (fd)) + { + errno = ENOTTY; + return ENOTTY; + } +#elif !defined TIOCGPTN +# error "__UNIX98PTY_ONLY__ enabled but TIOCGPTN ioctl not supported by your kernel." +#endif +#ifdef TIOCGPTN + if (ioctl (fd, TIOCGPTN, &ptyno) == 0) + { + /* Buffer we use to print the number in. */ + char numbuf[__BUFLEN_INT10TOSTR]; + static const char devpts[] = _PATH_DEVPTS; + char *p; + + p = _int10tostr(&numbuf[sizeof numbuf - 1], ptyno); + + if (buflen < sizeof(devpts) + (size_t)(&numbuf[sizeof(numbuf) - 1] - p)) + { + errno = ERANGE; + return ERANGE; + } + + strcpy (buf, devpts); + strcat (buf, p); + /* Note: Don't bother with stat on the slave name and checking the + driver's major device number - the ioctl above succeeded so + we know the fd was a Unix'98 master and the /dev/pts/ prefix + is set by definition. If the name isn't really a slave PTY, + the system is misconfigured anyway - something else will fail + later. + */ + errno = save_errno; + return 0; + } +#endif +#if defined __UNIX98PTY_ONLY__ + else + { + /* If the ioctl fails it wasn't a Unix 98 master PTY */ + errno = ENOTTY; + return ENOTTY; + } +#else +# if defined TIOCGPTN + else if (errno == EINVAL) +# endif + { + char *p; + + if (buflen < strlen (_PATH_TTY) + 3) + { + errno = ERANGE; + return ERANGE; + } + + if (fstat (fd, &st) < 0) + return errno; + + /* Check if FD really is a master pseudo terminal. */ + if (! MASTER_P (st.st_rdev)) + { + errno = ENOTTY; + return ENOTTY; + } + + ptyno = minor (st.st_rdev); + /* This is for the old BSD pseudo terminals. As of Linux + 2.1.115 these are no longer supported. */ + if (major (st.st_rdev) == 4) + ptyno -= 128; + + if (ptyno / 16 >= strlen (__libc_ptyname1)) + { + errno = ENOTTY; + return ENOTTY; + } + + strcpy (buf, _PATH_TTY); + p = buf + strlen (buf); + p[0] = __libc_ptyname1[ptyno / 16]; + p[1] = __libc_ptyname2[ptyno % 16]; + p[2] = '\0'; + } + + if (stat(buf, &st) < 0) + return errno; + + /* Check if the name we're about to return really corresponds to a + slave pseudo terminal. */ + if (! S_ISCHR (st.st_mode) || ! SLAVE_P (st.st_rdev)) + { + /* This really is a configuration problem. */ + errno = ENOTTY; + return ENOTTY; + } +#endif + + errno = save_errno; + return 0; +} +libc_hidden_def(ptsname_r) + +/* Return the pathname of the pseudo terminal slave assoicated with + the master FD is open on, or NULL on errors. + The returned storage is good until the next call to this function. */ +char * +ptsname (int fd) +{ + static char buffer[sizeof (_PATH_DEVPTS) + 20]; + + return ptsname_r (fd, buffer, sizeof (buffer)) != 0 ? NULL : buffer; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/pty-private.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/pty-private.h new file mode 100644 index 00000000..621dbfd6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/pty-private.h @@ -0,0 +1,42 @@ +/* Internal defenitions and declarations for pseudo terminal functions. + Copyright (C) 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Zack Weinberg , 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _PTY_PRIVATE_H +#define _PTY_PRIVATE_H 1 + +/* The group slave pseudo terminals belong to. */ +#define TTY_GROUP "tty" + +/* The file descriptor connected to the master pseudo terminal. */ +#define PTY_FILENO 3 + +/* Path to the helper program that implements `grantpt' in user space. */ +#define _PATH_PT_CHOWN "/sbin/pt_chown" + +/* Exit codes for the helper program. */ +enum /* failure modes */ +{ + FAIL_EBADF = 1, + FAIL_EINVAL, + FAIL_EACCES, + FAIL_EXEC +}; + +#endif /* pty-private.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/qsort.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/qsort.c new file mode 100644 index 00000000..31fc2eaf --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/qsort.c @@ -0,0 +1,7 @@ +/* Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_qsort +#include "stdlib.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/rand.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/rand.c new file mode 100644 index 00000000..4b899c0f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/rand.c @@ -0,0 +1,14 @@ +/* vi: set sw=4 ts=4: */ +/* + * rand for uClibc + * Copyright (C) 2000-2006 by Erik Andersen + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + + +int rand(void) +{ + return (int)random(); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/rand_r.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/rand_r.c new file mode 100644 index 00000000..61004408 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/rand_r.c @@ -0,0 +1,48 @@ +/* Reentrant random function frm POSIX.1c. + Copyright (C) 1996, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper >, 1996. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + + +/* This algorithm is mentioned in the ISO C standard, here extended + for 32 bits. */ +int rand_r (unsigned int *seed) +{ + unsigned int next = *seed; + int result; + + next *= 1103515245; + next += 12345; + result = (unsigned int) (next / 65536) % 2048; + + next *= 1103515245; + next += 12345; + result <<= 10; + result ^= (unsigned int) (next / 65536) % 1024; + + next *= 1103515245; + next += 12345; + result <<= 10; + result ^= (unsigned int) (next / 65536) % 1024; + + *seed = next; + + return result; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/random.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/random.c new file mode 100644 index 00000000..b009c431 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/random.c @@ -0,0 +1,243 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +/* + * This is derived from the Berkeley source: + * @(#)random.c 5.5 (Berkeley) 7/6/88 + * It was reworked for the GNU C Library by Roland McGrath. + * Rewritten to use reentrant functions by Ulrich Drepper, 1995. + */ + +#include +#include +#include +#include + + +/* POSIX.1c requires that there is mutual exclusion for the `rand' and + `srand' functions to prevent concurrent calls from modifying common + data. */ +#include +__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP); + + +/* An improved random number generation package. In addition to the standard + rand()/srand() like interface, this package also has a special state info + interface. The initstate() routine is called with a seed, an array of + bytes, and a count of how many bytes are being passed in; this array is + then initialized to contain information for random number generation with + that much state information. Good sizes for the amount of state + information are 32, 64, 128, and 256 bytes. The state can be switched by + calling the setstate() function with the same array as was initialized + with initstate(). By default, the package runs with 128 bytes of state + information and generates far better random numbers than a linear + congruential generator. If the amount of state information is less than + 32 bytes, a simple linear congruential R.N.G. is used. Internally, the + state information is treated as an array of longs; the zeroth element of + the array is the type of R.N.G. being used (small integer); the remainder + of the array is the state information for the R.N.G. Thus, 32 bytes of + state information will give 7 longs worth of state information, which will + allow a degree seven polynomial. (Note: The zeroth word of state + information also has some other information stored in it; see setstate + for details). The random number generation technique is a linear feedback + shift register approach, employing trinomials (since there are fewer terms + to sum up that way). In this approach, the least significant bit of all + the numbers in the state table will act as a linear feedback shift register, + and will have period 2^deg - 1 (where deg is the degree of the polynomial + being used, assuming that the polynomial is irreducible and primitive). + The higher order bits will have longer periods, since their values are + also influenced by pseudo-random carries out of the lower bits. The + total period of the generator is approximately deg*(2**deg - 1); thus + doubling the amount of state information has a vast influence on the + period of the generator. Note: The deg*(2**deg - 1) is an approximation + only good for large deg, when the period of the shift register is the + dominant factor. With deg equal to seven, the period is actually much + longer than the 7*(2**7 - 1) predicted by this formula. */ + + + +/* Keep constants in sync with random_r.c */ + +/* Linear congruential. */ +#define TYPE_0 0 +#define BREAK_0 8 +#define DEG_0 0 +#define SEP_0 0 + +/* x**7 + x**3 + 1. */ +#define TYPE_1 1 +#define BREAK_1 32 +#define DEG_1 7 +#define SEP_1 3 + +/* x**15 + x + 1. */ +#define TYPE_2 2 +#define BREAK_2 64 +#define DEG_2 15 +#define SEP_2 1 + +/* x**31 + x**3 + 1. */ +#define TYPE_3 3 +#define BREAK_3 128 +#define DEG_3 31 +#define SEP_3 3 + +/* x**63 + x + 1. */ +#define TYPE_4 4 +#define BREAK_4 256 +#define DEG_4 63 +#define SEP_4 1 + +#define MAX_TYPES 5 /* Max number of types above. */ + +/* Initially, everything is set up as if from: + initstate(1, randtbl, 128); + Note that this initialization takes advantage of the fact that srandom + advances the front and rear pointers 10*rand_deg times, and hence the + rear pointer which starts at 0 will also end up at zero; thus the zeroth + element of the state information, which contains info about the current + position of the rear pointer is just + (MAX_TYPES * (rptr - state)) + TYPE_3 == TYPE_3. */ + +static int32_t randtbl[DEG_3 + 1] = +{ + TYPE_3, + + -1726662223, 379960547, 1735697613, 1040273694, 1313901226, + 1627687941, -179304937, -2073333483, 1780058412, -1989503057, + -615974602, 344556628, 939512070, -1249116260, 1507946756, + -812545463, 154635395, 1388815473, -1926676823, 525320961, + -1009028674, 968117788, -123449607, 1284210865, 435012392, + -2017506339, -911064859, -370259173, 1132637927, 1398500161, + -205601318, +}; + + +static struct random_data unsafe_state = +{ + /* FPTR and RPTR are two pointers into the state info, a front and a rear + pointer. These two pointers are always rand_sep places aparts, as they + cycle through the state information. (Yes, this does mean we could get + away with just one pointer, but the code for random is more efficient + this way). The pointers are left positioned as they would be from the call: + initstate(1, randtbl, 128); + (The position of the rear pointer, rptr, is really 0 (as explained above + in the initialization of randtbl) because the state table pointer is set + to point to randtbl[1] (as explained below).) */ + + fptr : &randtbl[SEP_3 + 1], + rptr : &randtbl[1], + + /* The following things are the pointer to the state information table, + the type of the current generator, the degree of the current polynomial + being used, and the separation between the two pointers. + Note that for efficiency of random, we remember the first location of + the state information, not the zeroth. Hence it is valid to access + state[-1], which is used to store the type of the R.N.G. + Also, we remember the last location, since this is more efficient than + indexing every time to find the address of the last element to see if + the front and rear pointers have wrapped. */ + + state : &randtbl[1], + + rand_type : TYPE_3, + rand_deg : DEG_3, + rand_sep : SEP_3, + + end_ptr : &randtbl[sizeof (randtbl) / sizeof (randtbl[0])] +}; + + +/* Initialize the random number generator based on the given seed. If the + type is the trivial no-state-information type, just remember the seed. + Otherwise, initializes state[] based on the given "seed" via a linear + congruential generator. Then, the pointers are set to known locations + that are exactly rand_sep places apart. Lastly, it cycles the state + information a given number of times to get rid of any initial dependencies + introduced by the L.C.R.N.G. Note that the initialization of randtbl[] + for default usage relies on values produced by this routine. */ +void srandom (unsigned int x) +{ + __UCLIBC_MUTEX_LOCK(mylock); + srandom_r (x, &unsafe_state); + __UCLIBC_MUTEX_UNLOCK(mylock); +} +strong_alias(srandom,srand) + +/* Initialize the state information in the given array of N bytes for + future random number generation. Based on the number of bytes we + are given, and the break values for the different R.N.G.'s, we choose + the best (largest) one we can and set things up for it. srandom is + then called to initialize the state information. Note that on return + from srandom, we set state[-1] to be the type multiplexed with the current + value of the rear pointer; this is so successive calls to initstate won't + lose this information and will be able to restart with setstate. + Note: The first thing we do is save the current state, if any, just like + setstate so that it doesn't matter when initstate is called. + Returns a pointer to the old state. */ +char * initstate (unsigned int seed, char *arg_state, size_t n) +{ + int32_t *ostate; + + __UCLIBC_MUTEX_LOCK(mylock); + ostate = &unsafe_state.state[-1]; + initstate_r (seed, arg_state, n, &unsafe_state); + __UCLIBC_MUTEX_UNLOCK(mylock); + return (char *) ostate; +} + +/* Restore the state from the given state array. + Note: It is important that we also remember the locations of the pointers + in the current state information, and restore the locations of the pointers + from the old state information. This is done by multiplexing the pointer + location into the zeroth word of the state information. Note that due + to the order in which things are done, it is OK to call setstate with the + same state as the current state + Returns a pointer to the old state information. */ +char * setstate (char *arg_state) +{ + int32_t *ostate; + + __UCLIBC_MUTEX_LOCK(mylock); + ostate = &unsafe_state.state[-1]; + if (setstate_r (arg_state, &unsafe_state) < 0) + ostate = NULL; + __UCLIBC_MUTEX_UNLOCK(mylock); + return (char *) ostate; +} + +/* If we are using the trivial TYPE_0 R.N.G., just do the old linear + congruential bit. Otherwise, we do our fancy trinomial stuff, which is the + same in all the other cases due to all the global variables that have been + set up. The basic operation is to add the number at the rear pointer into + the one at the front pointer. Then both pointers are advanced to the next + location cyclically in the table. The value returned is the sum generated, + reduced to 31 bits by throwing away the "least random" low bit. + Note: The code takes advantage of the fact that both the front and + rear pointers can't wrap on the same call by not testing the rear + pointer if the front one has wrapped. Returns a 31-bit random number. */ + +long int random (void) +{ + int32_t retval; + + __UCLIBC_MUTEX_LOCK(mylock); + random_r (&unsafe_state, &retval); + __UCLIBC_MUTEX_UNLOCK(mylock); + return retval; +} +libc_hidden_def(random) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/random_r.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/random_r.c new file mode 100644 index 00000000..4b2b3f85 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/random_r.c @@ -0,0 +1,359 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +/* + * This is derived from the Berkeley source: + * @(#)random.c 5.5 (Berkeley) 7/6/88 + * It was reworked for the GNU C Library by Roland McGrath. + * Rewritten to be reentrant by Ulrich Drepper, 1995 + */ + +#include +#include +#include +#include +#include +#include + +/* An improved random number generation package. In addition to the standard + rand()/srand() like interface, this package also has a special state info + interface. The initstate() routine is called with a seed, an array of + bytes, and a count of how many bytes are being passed in; this array is + then initialized to contain information for random number generation with + that much state information. Good sizes for the amount of state + information are 32, 64, 128, and 256 bytes. The state can be switched by + calling the setstate() function with the same array as was initialized + with initstate(). By default, the package runs with 128 bytes of state + information and generates far better random numbers than a linear + congruential generator. If the amount of state information is less than + 32 bytes, a simple linear congruential R.N.G. is used. Internally, the + state information is treated as an array of longs; the zeroth element of + the array is the type of R.N.G. being used (small integer); the remainder + of the array is the state information for the R.N.G. Thus, 32 bytes of + state information will give 7 longs worth of state information, which will + allow a degree seven polynomial. (Note: The zeroth word of state + information also has some other information stored in it; see setstate + for details). The random number generation technique is a linear feedback + shift register approach, employing trinomials (since there are fewer terms + to sum up that way). In this approach, the least significant bit of all + the numbers in the state table will act as a linear feedback shift register, + and will have period 2^deg - 1 (where deg is the degree of the polynomial + being used, assuming that the polynomial is irreducible and primitive). + The higher order bits will have longer periods, since their values are + also influenced by pseudo-random carries out of the lower bits. The + total period of the generator is approximately deg*(2**deg - 1); thus + doubling the amount of state information has a vast influence on the + period of the generator. Note: The deg*(2**deg - 1) is an approximation + only good for large deg, when the period of the shift register is the + dominant factor. With deg equal to seven, the period is actually much + longer than the 7*(2**7 - 1) predicted by this formula. */ + + + +/* For each of the currently supported random number generators, we have a + break value on the amount of state information (you need at least this many + bytes of state info to support this random number generator), a degree for + the polynomial (actually a trinomial) that the R.N.G. is based on, and + separation between the two lower order coefficients of the trinomial. */ + +/* Linear congruential. */ +#define TYPE_0 0 +#define BREAK_0 8 +#define DEG_0 0 +#define SEP_0 0 + +/* x**7 + x**3 + 1. */ +#define TYPE_1 1 +#define BREAK_1 32 +#define DEG_1 7 +#define SEP_1 3 + +/* x**15 + x + 1. */ +#define TYPE_2 2 +#define BREAK_2 64 +#define DEG_2 15 +#define SEP_2 1 + +/* x**31 + x**3 + 1. */ +#define TYPE_3 3 +#define BREAK_3 128 +#define DEG_3 31 +#define SEP_3 3 + +/* x**63 + x + 1. */ +#define TYPE_4 4 +#define BREAK_4 256 +#define DEG_4 63 +#define SEP_4 1 + + +/* Array versions of the above information to make code run faster. + Relies on fact that TYPE_i == i. */ + +#define MAX_TYPES 5 /* Max number of types above. */ + +struct random_poly_info +{ + smallint seps[MAX_TYPES]; + smallint degrees[MAX_TYPES]; +}; + +static const struct random_poly_info random_poly_info = +{ + { SEP_0, SEP_1, SEP_2, SEP_3, SEP_4 }, + { DEG_0, DEG_1, DEG_2, DEG_3, DEG_4 } +}; + + + +/* If we are using the trivial TYPE_0 R.N.G., just do the old linear + congruential bit. Otherwise, we do our fancy trinomial stuff, which is the + same in all the other cases due to all the global variables that have been + set up. The basic operation is to add the number at the rear pointer into + the one at the front pointer. Then both pointers are advanced to the next + location cyclically in the table. The value returned is the sum generated, + reduced to 31 bits by throwing away the "least random" low bit. + Note: The code takes advantage of the fact that both the front and + rear pointers can't wrap on the same call by not testing the rear + pointer if the front one has wrapped. Returns a 31-bit random number. */ + +int random_r(struct random_data *buf, int32_t *result) +{ + int32_t *state; + + if (buf == NULL || result == NULL) + goto fail; + + state = buf->state; + + if (buf->rand_type == TYPE_0) + { + int32_t val = state[0]; + val = ((state[0] * 1103515245) + 12345) & 0x7fffffff; + state[0] = val; + *result = val; + } + else + { + int32_t *fptr = buf->fptr; + int32_t *rptr = buf->rptr; + int32_t *end_ptr = buf->end_ptr; + int32_t val; + + val = *fptr += *rptr; + /* Chucking least random bit. */ + *result = (val >> 1) & 0x7fffffff; + ++fptr; + if (fptr >= end_ptr) + { + fptr = state; + ++rptr; + } + else + { + ++rptr; + if (rptr >= end_ptr) + rptr = state; + } + buf->fptr = fptr; + buf->rptr = rptr; + } + return 0; + +fail: + __set_errno (EINVAL); + return -1; +} +libc_hidden_def(random_r) + +/* Initialize the random number generator based on the given seed. If the + type is the trivial no-state-information type, just remember the seed. + Otherwise, initializes state[] based on the given "seed" via a linear + congruential generator. Then, the pointers are set to known locations + that are exactly rand_sep places apart. Lastly, it cycles the state + information a given number of times to get rid of any initial dependencies + introduced by the L.C.R.N.G. Note that the initialization of randtbl[] + for default usage relies on values produced by this routine. */ +int srandom_r (unsigned int seed, struct random_data *buf) +{ + int type; + int32_t *state; + long int i; + long int word; + int32_t *dst; + int kc; + + if (buf == NULL) + goto fail; + type = buf->rand_type; + if ((unsigned int) type >= MAX_TYPES) + goto fail; + + state = buf->state; + /* We must make sure the seed is not 0. Take arbitrarily 1 in this case. */ + if (seed == 0) + seed = 1; + state[0] = seed; + if (type == TYPE_0) + goto done; + + dst = state; + word = seed; + kc = buf->rand_deg; + for (i = 1; i < kc; ++i) + { + /* This does: + state[i] = (16807 * state[i - 1]) % 2147483647; + but avoids overflowing 31 bits. */ + long int hi = word / 127773; + long int lo = word % 127773; + word = 16807 * lo - 2836 * hi; + if (word < 0) + word += 2147483647; + *++dst = word; + } + + buf->fptr = &state[buf->rand_sep]; + buf->rptr = &state[0]; + kc *= 10; + while (--kc >= 0) + { + int32_t discard; + (void) random_r (buf, &discard); + } + +done: + return 0; + +fail: + return -1; +} +libc_hidden_def(srandom_r) + +/* Initialize the state information in the given array of N bytes for + future random number generation. Based on the number of bytes we + are given, and the break values for the different R.N.G.'s, we choose + the best (largest) one we can and set things up for it. srandom is + then called to initialize the state information. Note that on return + from srandom, we set state[-1] to be the type multiplexed with the current + value of the rear pointer; this is so successive calls to initstate won't + lose this information and will be able to restart with setstate. + Note: The first thing we do is save the current state, if any, just like + setstate so that it doesn't matter when initstate is called. + Returns a pointer to the old state. */ +int initstate_r (unsigned int seed, char *arg_state, size_t n, struct random_data *buf) +{ + int type; + int degree; + int separation; + int32_t *state; + + if (buf == NULL) + goto fail; + + if (n >= BREAK_3) + type = n < BREAK_4 ? TYPE_3 : TYPE_4; + else if (n < BREAK_1) + { + if (n < BREAK_0) + { + __set_errno (EINVAL); + goto fail; + } + type = TYPE_0; + } + else + type = n < BREAK_2 ? TYPE_1 : TYPE_2; + + degree = random_poly_info.degrees[type]; + separation = random_poly_info.seps[type]; + + buf->rand_type = type; + buf->rand_sep = separation; + buf->rand_deg = degree; + state = &((int32_t *) arg_state)[1]; /* First location. */ + /* Must set END_PTR before srandom. */ + buf->end_ptr = &state[degree]; + + buf->state = state; + + srandom_r (seed, buf); + + state[-1] = TYPE_0; + if (type != TYPE_0) + state[-1] = (buf->rptr - state) * MAX_TYPES + type; + + return 0; + +fail: + __set_errno (EINVAL); + return -1; +} +libc_hidden_def(initstate_r) + +/* Restore the state from the given state array. + Note: It is important that we also remember the locations of the pointers + in the current state information, and restore the locations of the pointers + from the old state information. This is done by multiplexing the pointer + location into the zeroth word of the state information. Note that due + to the order in which things are done, it is OK to call setstate with the + same state as the current state + Returns a pointer to the old state information. */ +int setstate_r (char *arg_state, struct random_data *buf) +{ + int32_t *new_state = 1 + (int32_t *) arg_state; + int type; + int old_type; + int32_t *old_state; + int degree; + int separation; + + if (arg_state == NULL || buf == NULL) + goto fail; + + old_type = buf->rand_type; + old_state = buf->state; + if (old_type == TYPE_0) + old_state[-1] = TYPE_0; + else + old_state[-1] = (MAX_TYPES * (buf->rptr - old_state)) + old_type; + + type = new_state[-1] % MAX_TYPES; + if (type < TYPE_0 || type > TYPE_4) + goto fail; + + buf->rand_deg = degree = random_poly_info.degrees[type]; + buf->rand_sep = separation = random_poly_info.seps[type]; + buf->rand_type = type; + + if (type != TYPE_0) + { + int rear = new_state[-1] / MAX_TYPES; + buf->rptr = &new_state[rear]; + buf->fptr = &new_state[(rear + separation) % degree]; + } + buf->state = new_state; + /* Set end_ptr too. */ + buf->end_ptr = &new_state[degree]; + + return 0; + +fail: + __set_errno (EINVAL); + return -1; +} +libc_hidden_def(setstate_r) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/realpath.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/realpath.c new file mode 100644 index 00000000..cf9d45fa --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/realpath.c @@ -0,0 +1,162 @@ +/* + * realpath.c -- canonicalize pathname by removing symlinks + * Copyright (C) 1993 Rick Sladkey + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include /* for PATH_MAX */ +#include /* for MAXPATHLEN */ +#include +#include + +#include /* for S_IFLNK */ + + +#ifndef PATH_MAX +#ifdef _POSIX_VERSION +#define PATH_MAX _POSIX_PATH_MAX +#else +#ifdef MAXPATHLEN +#define PATH_MAX MAXPATHLEN +#else +#define PATH_MAX 1024 +#endif +#endif +#endif + +#define MAX_READLINKS 32 + +char *realpath(const char *path, char got_path[]) +{ + char copy_path[PATH_MAX]; + char *max_path, *new_path, *allocated_path; + size_t path_len; + int readlinks = 0; +#ifdef S_IFLNK + int link_len; +#endif + + if (path == NULL) { + __set_errno(EINVAL); + return NULL; + } + if (*path == '\0') { + __set_errno(ENOENT); + return NULL; + } + /* Make a copy of the source path since we may need to modify it. */ + path_len = strlen(path); + if (path_len >= PATH_MAX - 2) { + __set_errno(ENAMETOOLONG); + return NULL; + } + /* Copy so that path is at the end of copy_path[] */ + strcpy(copy_path + (PATH_MAX-1) - path_len, path); + path = copy_path + (PATH_MAX-1) - path_len; + allocated_path = got_path ? NULL : (got_path = malloc(PATH_MAX)); + max_path = got_path + PATH_MAX - 2; /* points to last non-NUL char */ + new_path = got_path; + if (*path != '/') { + /* If it's a relative pathname use getcwd for starters. */ + if (!getcwd(new_path, PATH_MAX - 1)) + goto err; + new_path += strlen(new_path); + if (new_path[-1] != '/') + *new_path++ = '/'; + } else { + *new_path++ = '/'; + path++; + } + /* Expand each slash-separated pathname component. */ + while (*path != '\0') { + /* Ignore stray "/". */ + if (*path == '/') { + path++; + continue; + } + if (*path == '.') { + /* Ignore ".". */ + if (path[1] == '\0' || path[1] == '/') { + path++; + continue; + } + if (path[1] == '.') { + if (path[2] == '\0' || path[2] == '/') { + path += 2; + /* Ignore ".." at root. */ + if (new_path == got_path + 1) + continue; + /* Handle ".." by backing up. */ + while ((--new_path)[-1] != '/'); + continue; + } + } + } + /* Safely copy the next pathname component. */ + while (*path != '\0' && *path != '/') { + if (new_path > max_path) { + __set_errno(ENAMETOOLONG); + err: + free(allocated_path); + return NULL; + } + *new_path++ = *path++; + } +#ifdef S_IFLNK + /* Protect against infinite loops. */ + if (readlinks++ > MAX_READLINKS) { + __set_errno(ELOOP); + goto err; + } + path_len = strlen(path); + /* See if last (so far) pathname component is a symlink. */ + *new_path = '\0'; + { + int sv_errno = errno; + link_len = readlink(got_path, copy_path, PATH_MAX - 1); + if (link_len < 0) { + /* EINVAL means the file exists but isn't a symlink. */ + if (errno != EINVAL) { + goto err; + } + } else { + /* Safe sex check. */ + if (path_len + link_len >= PATH_MAX - 2) { + __set_errno(ENAMETOOLONG); + goto err; + } + /* Note: readlink doesn't add the null byte. */ + /* copy_path[link_len] = '\0'; - we don't need it too */ + if (*copy_path == '/') + /* Start over for an absolute symlink. */ + new_path = got_path; + else + /* Otherwise back up over this component. */ + while (*(--new_path) != '/'); + /* Prepend symlink contents to path. */ + memmove(copy_path + (PATH_MAX-1) - link_len - path_len, copy_path, link_len); + path = copy_path + (PATH_MAX-1) - link_len - path_len; + } + __set_errno(sv_errno); + } +#endif /* S_IFLNK */ + *new_path++ = '/'; + } + /* Delete trailing slash but don't whomp a lone slash. */ + if (new_path != got_path + 1 && new_path[-1] == '/') + new_path--; + /* Make sure it's null terminated. */ + *new_path = '\0'; + return got_path; +} +libc_hidden_def(realpath) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/seed48.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/seed48.c new file mode 100644 index 00000000..9ff8a480 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/seed48.c @@ -0,0 +1,31 @@ +/* Copyright (C) 1995,1996,1997,1998,2001,2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , August 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + + +/* Global state for non-reentrant functions. Defined in drand48-iter.c. */ +extern struct drand48_data __libc_drand48_data attribute_hidden; + +unsigned short int * +seed48 (unsigned short int seed16v[3]) +{ + (void) seed48_r (seed16v, &__libc_drand48_data); + return __libc_drand48_data.__old_x; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/seed48_r.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/seed48_r.c new file mode 100644 index 00000000..0d587223 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/seed48_r.c @@ -0,0 +1,40 @@ +/* Copyright (C) 1995, 1997, 1998, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , August 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + + +int seed48_r (unsigned short int seed16v[3], struct drand48_data *buffer) +{ + /* Save old value at a private place to be used as return value. */ + memcpy (buffer->__old_x, buffer->__x, sizeof (buffer->__x)); + + /* Install new state. */ + buffer->__x[2] = seed16v[2]; + buffer->__x[1] = seed16v[1]; + buffer->__x[0] = seed16v[0]; + buffer->__a = 0x5deece66dull; + buffer->__c = 0xb; + buffer->__init = 1; + + return 0; +} +libc_hidden_def(seed48_r) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/setenv.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/setenv.c new file mode 100644 index 00000000..8da2fae5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/setenv.c @@ -0,0 +1,183 @@ +/* Copyright (C) 1992,95,96,97,98,99,2000,2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. + + modified for uClibc by Erik Andersen +*/ + +#include +#include +#include +#include +#include + + +#include +__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_MUTEX_INITIALIZER); + + +/* If this variable is not a null pointer we allocated the current + environment. */ +static char **last_environ; + + +/* This function is used by `setenv' and `putenv'. The difference between + the two functions is that for the former must create a new string which + is then placed in the environment, while the argument of `putenv' + must be used directly. This is all complicated by the fact that we try + to reuse values once generated for a `setenv' call since we can never + free the strings. [in uclibc, we do not] */ +static int __add_to_environ(const char *name, const char *value, + int replace) +{ + register char **ep; + register size_t size; + char *var_val; + char **new_environ; + /* name may come from putenv() and thus may contain "=VAL" part */ + const size_t namelen = strchrnul(name, '=') - name; + int rv = -1; + + __UCLIBC_MUTEX_LOCK(mylock); + + /* We have to get the pointer now that we have the lock and not earlier + since another thread might have created a new environment. */ + ep = __environ; + + size = 0; + if (ep != NULL) { + while (*ep != NULL) { + if (!strncmp(*ep, name, namelen) && (*ep)[namelen] == '=') { + /* Found */ + if (!replace) + goto DONE_OK; + goto REPLACE; + } + ++size; + ++ep; + } + } + + /* Not found, add at the end */ + + /* We allocated this space; we can extend it. */ + new_environ = realloc(last_environ, (size + 2) * sizeof(char *)); + if (new_environ == NULL) { + __set_errno(ENOMEM); + goto DONE; + } + if (__environ != last_environ) { + memcpy(new_environ, __environ, size * sizeof(char *)); + } + last_environ = __environ = new_environ; + + ep = &new_environ[size]; + /* Ensure env is NULL terminated in case malloc below fails */ + ep[0] = NULL; + ep[1] = NULL; + + REPLACE: + var_val = (char*) name; + /* Build VAR=VAL if we called by setenv, not putenv. */ + if (value != NULL) { + const size_t vallen = strlen(value) + 1; + + var_val = malloc(namelen + 1 + vallen); + if (var_val == NULL) { + __set_errno(ENOMEM); + goto DONE; + } + memcpy(var_val, name, namelen); + var_val[namelen] = '='; + memcpy(&var_val[namelen + 1], value, vallen); + } + *ep = var_val; + + DONE_OK: + rv = 0; + + DONE: + __UCLIBC_MUTEX_UNLOCK(mylock); + return rv; +} + +int setenv(const char *name, const char *value, int replace) +{ + /* NB: setenv("VAR", NULL, 1) inserts "VAR=" string */ + return __add_to_environ(name, value ? value : "", replace); +} +libc_hidden_def(setenv) + +int unsetenv(const char *name) +{ + const char *eq; + size_t len; + char **ep; + + if (name == NULL || *name == '\0' + || *(eq = strchrnul(name, '=')) == '=' + ) { + __set_errno(EINVAL); + return -1; + } + len = eq - name; /* avoiding strlen this way */ + + __UCLIBC_MUTEX_LOCK(mylock); + ep = __environ; + /* NB: clearenv(); unsetenv("foo"); should not segfault */ + if (ep) while (*ep != NULL) { + if (!strncmp(*ep, name, len) && (*ep)[len] == '=') { + /* Found it. Remove this pointer by moving later ones back. */ + char **dp = ep; + do { + dp[0] = dp[1]; + } while (*dp++); + /* Continue the loop in case NAME appears again. */ + } else { + ++ep; + } + } + __UCLIBC_MUTEX_UNLOCK(mylock); + return 0; +} +libc_hidden_def(unsetenv) + +/* The `clearenv' was planned to be added to POSIX.1 but probably + never made it. Nevertheless the POSIX.9 standard (POSIX bindings + for Fortran 77) requires this function. */ +int clearenv(void) +{ + __UCLIBC_MUTEX_LOCK(mylock); + /* If we allocated this environment we can free it. + * If we did not allocate this environment, it's NULL already + * and is safe to free(). */ + free(last_environ); + last_environ = NULL; + /* Clearing environ removes the whole environment. */ + __environ = NULL; + __UCLIBC_MUTEX_UNLOCK(mylock); + return 0; +} + +/* Put STRING, which is of the form "NAME=VALUE", in the environment. */ +int putenv(char *string) +{ + if (strchr(string, '=') != NULL) { + return __add_to_environ(string, NULL, 1); + } + return unsetenv(string); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/srand48.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/srand48.c new file mode 100644 index 00000000..817d068c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/srand48.c @@ -0,0 +1,29 @@ +/* Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper >, August 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + + +/* Global state for non-reentrant functions. Defined in drand48-iter.c. */ +extern struct drand48_data __libc_drand48_data attribute_hidden; + +void srand48 (long seedval) +{ + srand48_r (seedval, &__libc_drand48_data); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/srand48_r.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/srand48_r.c new file mode 100644 index 00000000..4347fef6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/srand48_r.c @@ -0,0 +1,39 @@ +/* Copyright (C) 1995, 1996, 1997, 1998, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper >, August 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +int srand48_r (long int seedval, struct drand48_data *buffer) +{ + /* The standards say we only have 32 bits. */ + if (sizeof (long int) > 4) + seedval &= 0xffffffffl; + + buffer->__x[2] = seedval >> 16; + buffer->__x[1] = seedval & 0xffffl; + buffer->__x[0] = 0x330e; + + buffer->__a = 0x5deece66dull; + buffer->__c = 0xb; + buffer->__init = 1; + + return 0; +} +libc_hidden_def(srand48_r) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/stdlib.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/stdlib.c new file mode 100644 index 00000000..4d608eea --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/stdlib.c @@ -0,0 +1,1152 @@ +/* Copyright (C) 2002 Manuel Novoa III + * From my (incomplete) stdlib library for linux and (soon) elks. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION! + * + * This code is currently under development. Also, I plan to port + * it to elks which is a 16-bit environment with a fairly limited + * compiler. Therefore, please refrain from modifying this code + * and, instead, pass any bug-fixes, etc. to me. Thanks. Manuel + * + * ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION! */ + +/* Oct 29, 2002 + * Fix a couple of 'restrict' bugs in mbstowcs and wcstombs. + * + * Nov 21, 2002 + * Add wscto{inttype} functions. + */ + +#define _ISOC99_SOURCE /* for ULLONG primarily... */ +#include +#include +/* Work around gcc's refusal to create aliases. + * TODO: Add in a define to disable the aliases? */ + +#if UINT_MAX == ULONG_MAX +#ifdef L_labs +#define abs __ignore_abs +#endif +#ifdef L_atol +#define atoi __ignore_atoi +#endif +#endif +#if defined(ULLONG_MAX) && (ULLONG_MAX == ULONG_MAX) +#ifdef L_labs +#define llabs __ignore_llabs +#endif +#ifdef L_atol +#define atoll __ignore_atoll +#endif +#ifdef L_strtol +#define strtoll __ignore_strtoll +#endif +#ifdef L_strtoul +#define strtoull __ignore_strtoull +#endif +#ifdef L_wcstol +#define wcstoll __ignore_wcstoll +#endif +#ifdef L_wcstoul +#define wcstoull __ignore_wcstoull +#endif +#ifdef L_strtol_l +#define strtoll_l __ignore_strtoll_l +#endif +#ifdef L_strtoul_l +#define strtoull_l __ignore_strtoull_l +#endif +#ifdef L_wcstol_l +#define wcstoll_l __ignore_wcstoll_l +#endif +#ifdef L_wcstoul_l +#define wcstoull_l __ignore_wcstoull_l +#endif +#endif +#if defined(ULLONG_MAX) && (ULLONG_MAX == UINTMAX_MAX) +#if defined L_labs || defined L_llabs +#define imaxabs __ignore_imaxabs +#endif +#endif + +#include +#include +#include +#include +#include +#include + +#include +#include + +#ifdef __UCLIBC_HAS_WCHAR__ + +#include +#include +#include + +#ifdef __UCLIBC_HAS_XLOCALE__ +#include +#endif /* __UCLIBC_HAS_XLOCALE__ */ + +/* TODO: clean up the following... */ + +#if WCHAR_MAX > 0xffffUL +#define UTF_8_MAX_LEN 6 +#else +#define UTF_8_MAX_LEN 3 +#endif + +#ifdef __UCLIBC_HAS_LOCALE__ + +#define ENCODING (__UCLIBC_CURLOCALE->encoding) +#ifndef __CTYPE_HAS_UTF_8_LOCALES +#ifdef L_mblen +/* emit only once */ +#warning __CTYPE_HAS_UTF_8_LOCALES not set! +#endif +#endif + +#else /* __UCLIBC_HAS_LOCALE__ */ + +#ifdef __UCLIBC_MJN3_ONLY__ +#ifdef L_mblen +/* emit only once */ +#warning devel checks +#endif +#endif +#ifdef __CTYPE_HAS_8_BIT_LOCALES +#error __CTYPE_HAS_8_BIT_LOCALES is defined! +#endif +#ifdef __CTYPE_HAS_UTF_8_LOCALES +#error __CTYPE_HAS_UTF_8_LOCALES is defined! +#endif +#endif + +#endif /* __UCLIBC_HAS_LOCALE__ */ + +/**********************************************************************/ +#ifdef __UCLIBC_HAS_XLOCALE__ + +extern unsigned long +_stdlib_strto_l_l(register const char * __restrict str, + char ** __restrict endptr, int base, int sflag, + __locale_t locale_arg) attribute_hidden; + +#if defined(ULLONG_MAX) +extern unsigned long long +_stdlib_strto_ll_l(register const char * __restrict str, + char ** __restrict endptr, int base, int sflag, + __locale_t locale_arg) attribute_hidden; +#endif + +#ifdef __UCLIBC_HAS_WCHAR__ +extern unsigned long +_stdlib_wcsto_l_l(register const wchar_t * __restrict str, + wchar_t ** __restrict endptr, int base, int sflag, + __locale_t locale_arg) attribute_hidden; + +#if defined(ULLONG_MAX) +extern unsigned long long +_stdlib_wcsto_ll_l(register const wchar_t * __restrict str, + wchar_t ** __restrict endptr, int base, int sflag, + __locale_t locale_arg) attribute_hidden; +#endif +#endif /* __UCLIBC_HAS_WCHAR__ */ + +#endif /* __UCLIBC_HAS_XLOCALE__ */ + + + +extern unsigned long +_stdlib_strto_l(register const char * __restrict str, + char ** __restrict endptr, int base, int sflag) attribute_hidden; + +#if defined(ULLONG_MAX) +extern unsigned long long +_stdlib_strto_ll(register const char * __restrict str, + char ** __restrict endptr, int base, int sflag) attribute_hidden; +#endif + +#ifdef __UCLIBC_HAS_WCHAR__ +extern unsigned long +_stdlib_wcsto_l(register const wchar_t * __restrict str, + wchar_t ** __restrict endptr, int base, int sflag) attribute_hidden; + +#if defined(ULLONG_MAX) +extern unsigned long long +_stdlib_wcsto_ll(register const wchar_t * __restrict str, + wchar_t ** __restrict endptr, int base, int sflag) attribute_hidden; +#endif +#endif /* __UCLIBC_HAS_WCHAR__ */ +/**********************************************************************/ +#ifdef L_atof + + +double atof(const char *nptr) +{ + return strtod(nptr, (char **) NULL); +} + +#endif +/**********************************************************************/ +#ifdef L_abs + +#if INT_MAX < LONG_MAX + +int abs(int j) +{ + return (j >= 0) ? j : -j; +} + +#endif /* INT_MAX < LONG_MAX */ + +#endif +/**********************************************************************/ +#ifdef L_labs + +long int labs(long int j) +{ + return (j >= 0) ? j : -j; +} + +#if UINT_MAX == ULONG_MAX +#undef abs +extern __typeof(labs) abs; +strong_alias(labs,abs) +#endif + +#if defined(ULLONG_MAX) && (ULLONG_MAX == ULONG_MAX) +#undef llabs +extern __typeof(labs) llabs; +strong_alias(labs,llabs) +#endif + +#if ULONG_MAX == UINTMAX_MAX +#undef imaxabs +extern __typeof(labs) imaxabs; +strong_alias(labs,imaxabs) +#endif + +#endif +/**********************************************************************/ +#ifdef L_llabs + +#if defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX) + +long long int llabs(long long int j) +{ + return (j >= 0) ? j : -j; +} + +#if (ULLONG_MAX == UINTMAX_MAX) +#undef imaxabs +extern __typeof(llabs) imaxabs; +strong_alias(llabs,imaxabs) +#endif + +#endif /* defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX) */ + +#endif +/**********************************************************************/ +#ifdef L_atoi + +#if INT_MAX < LONG_MAX + + +int atoi(const char *nptr) +{ + return (int) strtol(nptr, (char **) NULL, 10); +} +libc_hidden_def(atoi) + +#endif /* INT_MAX < LONG_MAX */ + +#endif +/**********************************************************************/ +#ifdef L_atol + + +long atol(const char *nptr) +{ + return strtol(nptr, (char **) NULL, 10); +} +libc_hidden_def(atol) + +#if UINT_MAX == ULONG_MAX +#undef atoi +extern __typeof(atol) atoi; +libc_hidden_proto(atoi) +strong_alias(atol,atoi) +libc_hidden_def(atoi) +#endif + +#if defined(ULLONG_MAX) && (ULLONG_MAX == ULONG_MAX) +#undef atoll +extern __typeof(atol) atoll; +strong_alias(atol,atoll) +#endif + +#endif +/**********************************************************************/ +#ifdef L_atoll + +#if defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX) + + +long long atoll(const char *nptr) +{ + return strtoll(nptr, (char **) NULL, 10); +} + +#endif /* defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX) */ + +#endif +/**********************************************************************/ +#if defined(L_strtol) || defined(L_strtol_l) + +libc_hidden_proto(__XL_NPP(strtol)) +long __XL_NPP(strtol)(const char * __restrict str, char ** __restrict endptr, + int base __LOCALE_PARAM) +{ + return __XL_NPP(_stdlib_strto_l)(str, endptr, base, 1 __LOCALE_ARG); +} +libc_hidden_def(__XL_NPP(strtol)) + +#if (ULONG_MAX == UINTMAX_MAX) && !defined(L_strtol_l) +strong_alias(strtol,strtoimax) +#endif + +#if defined(ULLONG_MAX) && (ULLONG_MAX == ULONG_MAX) +#ifdef L_strtol_l +#undef strtoll_l +#else +#undef strtoll +#endif +extern __typeof(__XL_NPP(strtol)) __XL_NPP(strtoll); +libc_hidden_proto(__XL_NPP(strtoll)) +strong_alias(__XL_NPP(strtol),__XL_NPP(strtoll)) +libc_hidden_def(__XL_NPP(strtoll)) +#if !defined(L_strtol_l) +strong_alias(strtol,strtoq) +#endif +#endif + +#endif +/**********************************************************************/ +#if defined(L_strtoll) || defined(L_strtoll_l) + +#if defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX) + +libc_hidden_proto(__XL_NPP(strtoll)) +long long __XL_NPP(strtoll)(const char * __restrict str, + char ** __restrict endptr, int base + __LOCALE_PARAM) +{ + return (long long) __XL_NPP(_stdlib_strto_ll)(str, endptr, base, 1 __LOCALE_ARG); +} +libc_hidden_def(__XL_NPP(strtoll)) + +#if !defined(L_strtoll_l) +#if (ULLONG_MAX == UINTMAX_MAX) +strong_alias(strtoll,strtoimax) +#endif +strong_alias(strtoll,strtoq) +#endif + +#endif /* defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX) */ + +#endif +/**********************************************************************/ +#if defined(L_strtoul) || defined(L_strtoul_l) + +libc_hidden_proto(__XL_NPP(strtoul)) +unsigned long __XL_NPP(strtoul)(const char * __restrict str, + char ** __restrict endptr, int base + __LOCALE_PARAM) +{ + return __XL_NPP(_stdlib_strto_l)(str, endptr, base, 0 __LOCALE_ARG); +} +libc_hidden_def(__XL_NPP(strtoul)) + +#if (ULONG_MAX == UINTMAX_MAX) && !defined(L_strtoul_l) +strong_alias(strtoul,strtoumax) +#endif + +#if defined(ULLONG_MAX) && (ULLONG_MAX == ULONG_MAX) +#ifdef L_strtoul_l +#undef strtoull_l +#else +#undef strtoull +#endif +extern __typeof(__XL_NPP(strtoul)) __XL_NPP(strtoull); +libc_hidden_proto(__XL_NPP(strtoull)) +strong_alias(__XL_NPP(strtoul),__XL_NPP(strtoull)) +libc_hidden_def(__XL_NPP(strtoull)) +#if !defined(L_strtoul_l) +strong_alias(strtoul,strtouq) +#endif +#endif + + +#endif +/**********************************************************************/ +#if defined(L_strtoull) || defined(L_strtoull_l) + +#if defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX) + +libc_hidden_proto(__XL_NPP(strtoull)) +unsigned long long __XL_NPP(strtoull)(const char * __restrict str, + char ** __restrict endptr, int base + __LOCALE_PARAM) +{ + return __XL_NPP(_stdlib_strto_ll)(str, endptr, base, 0 __LOCALE_ARG); +} +libc_hidden_def(__XL_NPP(strtoull)) + +#if !defined(L_strtoull_l) +#if (ULLONG_MAX == UINTMAX_MAX) +strong_alias(strtoull,strtoumax) +#endif +strong_alias(strtoull,strtouq) +#endif + +#endif /* defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX) */ + +#endif +/**********************************************************************/ +/* Support routines follow */ +/**********************************************************************/ +/* Set if we want errno set appropriately. */ +/* NOTE: Implies _STRTO_ENDPTR below */ +#define _STRTO_ERRNO 1 + +/* Set if we want support for the endptr arg. */ +/* Implied by _STRTO_ERRNO. */ +#define _STRTO_ENDPTR 1 + +#if _STRTO_ERRNO +#undef _STRTO_ENDPTR +#define _STRTO_ENDPTR 1 +#define SET_ERRNO(X) __set_errno(X) +#else +#define SET_ERRNO(X) ((void)(X)) /* keep side effects */ +#endif + +/**********************************************************************/ +#if defined(L__stdlib_wcsto_l) || defined(L__stdlib_wcsto_l_l) +#ifndef L__stdlib_strto_l +#define L__stdlib_strto_l +#endif +#endif + +#if defined(L__stdlib_strto_l) || defined(L__stdlib_strto_l_l) + +#if defined(L__stdlib_wcsto_l) || defined(L__stdlib_wcsto_l_l) + +#define _stdlib_strto_l _stdlib_wcsto_l +#define _stdlib_strto_l_l _stdlib_wcsto_l_l +#define Wchar wchar_t +#define Wuchar __uwchar_t +#ifdef __UCLIBC_DO_XLOCALE +#define ISSPACE(C) iswspace_l((C), locale_arg) +#else +#define ISSPACE(C) iswspace((C)) +#endif + +#else /* defined(L__stdlib_wcsto_l) || defined(L__stdlib_wcsto_l_l) */ + +#define Wchar char +#define Wuchar unsigned char +#ifdef __UCLIBC_DO_XLOCALE +#define ISSPACE(C) isspace_l((C), locale_arg) +#else +#define ISSPACE(C) isspace((C)) +#endif + +#endif /* defined(L__stdlib_wcsto_l) || defined(L__stdlib_wcsto_l_l) */ + +#if defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) + +unsigned long attribute_hidden _stdlib_strto_l(register const Wchar * __restrict str, + Wchar ** __restrict endptr, int base, + int sflag) +{ + return _stdlib_strto_l_l(str, endptr, base, sflag, __UCLIBC_CURLOCALE); +} + + +#else /* defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) */ + +/* This is the main work fuction which handles both strtol (sflag = 1) and + * strtoul (sflag = 0). */ + +unsigned long attribute_hidden __XL_NPP(_stdlib_strto_l)(register const Wchar * __restrict str, + Wchar ** __restrict endptr, int base, + int sflag __LOCALE_PARAM) +{ + unsigned long number, cutoff; +#if _STRTO_ENDPTR + const Wchar *fail_char; +#define SET_FAIL(X) fail_char = (X) +#else +#define SET_FAIL(X) ((void)(X)) /* Keep side effects. */ +#endif + unsigned char negative, digit, cutoff_digit; + + assert(((unsigned int)sflag) <= 1); + + SET_FAIL(str); + + while (ISSPACE(*str)) { /* Skip leading whitespace. */ + ++str; + } + + /* Handle optional sign. */ + negative = 0; + switch (*str) { + case '-': negative = 1; /* Fall through to increment str. */ + case '+': ++str; + } + + if (!(base & ~0x10)) { /* Either dynamic (base = 0) or base 16. */ + base += 10; /* Default is 10 (26). */ + if (*str == '0') { + SET_FAIL(++str); + base -= 2; /* Now base is 8 or 16 (24). */ + if ((0x20|(*str)) == 'x') { /* WARNING: assumes ascii. */ + ++str; + base += base; /* Base is 16 (16 or 48). */ + } + } + + if (base > 16) { /* Adjust in case base wasn't dynamic. */ + base = 16; + } + } + + number = 0; + + if (((unsigned)(base - 2)) < 35) { /* Legal base. */ + cutoff_digit = ULONG_MAX % base; + cutoff = ULONG_MAX / base; + do { + digit = ((Wuchar)(*str - '0') <= 9) + ? /* 0..9 */ (*str - '0') + : /* else */ (((Wuchar)(0x20 | *str) >= 'a') /* WARNING: assumes ascii. */ + ? /* >= A/a */ ((Wuchar)(0x20 | *str) - ('a' - 10)) + : /* else */ 40 /* bad value */); + + if (digit >= base) { + break; + } + + SET_FAIL(++str); + + if ((number > cutoff) + || ((number == cutoff) && (digit > cutoff_digit))) { + number = ULONG_MAX; + negative &= sflag; + SET_ERRNO(ERANGE); + } else { + number = number * base + digit; + } + } while (1); + } + +#if _STRTO_ENDPTR + if (endptr) { + *endptr = (Wchar *) fail_char; + } +#endif + + { + unsigned long tmp = (negative + ? ((unsigned long)(-(1+LONG_MIN)))+1 + : LONG_MAX); + if (sflag && (number > tmp)) { + number = tmp; + SET_ERRNO(ERANGE); + } + } + + return negative ? (unsigned long)(-((long)number)) : number; +} + +#endif /* defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) */ + + +#endif +/**********************************************************************/ +#if defined(L__stdlib_wcsto_ll) || defined(L__stdlib_wcsto_ll_l) +#ifndef L__stdlib_strto_ll +#define L__stdlib_strto_ll +#endif +#endif + +#if defined(L__stdlib_strto_ll) || defined(L__stdlib_strto_ll_l) + +#if defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX) + +#if defined(L__stdlib_wcsto_ll) || defined(L__stdlib_wcsto_ll_l) +#define _stdlib_strto_ll _stdlib_wcsto_ll +#define _stdlib_strto_ll_l _stdlib_wcsto_ll_l +#define Wchar wchar_t +#define Wuchar __uwchar_t +#ifdef __UCLIBC_DO_XLOCALE +#define ISSPACE(C) iswspace_l((C), locale_arg) +#else +#define ISSPACE(C) iswspace((C)) +#endif + +#else /* defined(L__stdlib_wcsto_ll) || defined(L__stdlib_wcsto_ll_l) */ + +#define Wchar char +#define Wuchar unsigned char +#ifdef __UCLIBC_DO_XLOCALE +#define ISSPACE(C) isspace_l((C), locale_arg) +#else +#define ISSPACE(C) isspace((C)) +#endif + +#endif /* defined(L__stdlib_wcsto_ll) || defined(L__stdlib_wcsto_ll_l) */ + +#if defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) + +unsigned long long attribute_hidden _stdlib_strto_ll(register const Wchar * __restrict str, + Wchar ** __restrict endptr, int base, + int sflag) +{ + return _stdlib_strto_ll_l(str, endptr, base, sflag, __UCLIBC_CURLOCALE); +} + + +#else /* defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) */ + +/* This is the main work fuction which handles both strtoll (sflag = 1) and + * strtoull (sflag = 0). */ + +unsigned long long attribute_hidden __XL_NPP(_stdlib_strto_ll)(register const Wchar * __restrict str, + Wchar ** __restrict endptr, int base, + int sflag __LOCALE_PARAM) +{ + unsigned long long number; +#if _STRTO_ENDPTR + const Wchar *fail_char; +#define SET_FAIL(X) fail_char = (X) +#else +#define SET_FAIL(X) ((void)(X)) /* Keep side effects. */ +#endif + unsigned int n1; + unsigned char negative, digit; + + assert(((unsigned int)sflag) <= 1); + + SET_FAIL(str); + + while (ISSPACE(*str)) { /* Skip leading whitespace. */ + ++str; + } + + /* Handle optional sign. */ + negative = 0; + switch (*str) { + case '-': negative = 1; /* Fall through to increment str. */ + case '+': ++str; + } + + if (!(base & ~0x10)) { /* Either dynamic (base = 0) or base 16. */ + base += 10; /* Default is 10 (26). */ + if (*str == '0') { + SET_FAIL(++str); + base -= 2; /* Now base is 8 or 16 (24). */ + if ((0x20|(*str)) == 'x') { /* WARNING: assumes ascii. */ + ++str; + base += base; /* Base is 16 (16 or 48). */ + } + } + + if (base > 16) { /* Adjust in case base wasn't dynamic. */ + base = 16; + } + } + + number = 0; + + if (((unsigned)(base - 2)) < 35) { /* Legal base. */ + do { + digit = ((Wuchar)(*str - '0') <= 9) + ? /* 0..9 */ (*str - '0') + : /* else */ (((Wuchar)(0x20 | *str) >= 'a') /* WARNING: assumes ascii. */ + ? /* >= A/a */ ((Wuchar)(0x20 | *str) - ('a' - 10)) + : /* else */ 40 /* bad value */); + + if (digit >= base) { + break; + } + + SET_FAIL(++str); + +#if 1 + /* Optional, but speeds things up in the usual case. */ + if (number <= (ULLONG_MAX >> 6)) { + number = number * base + digit; + } else +#endif + { + n1 = ((unsigned char) number) * base + digit; + number = (number >> CHAR_BIT) * base; + + if (number + (n1 >> CHAR_BIT) <= (ULLONG_MAX >> CHAR_BIT)) { + number = (number << CHAR_BIT) + n1; + } else { /* Overflow. */ + number = ULLONG_MAX; + negative &= sflag; + SET_ERRNO(ERANGE); + } + } + + } while (1); + } + +#if _STRTO_ENDPTR + if (endptr) { + *endptr = (Wchar *) fail_char; + } +#endif + + { + unsigned long long tmp = ((negative) + ? ((unsigned long long)(-(1+LLONG_MIN)))+1 + : LLONG_MAX); + if (sflag && (number > tmp)) { + number = tmp; + SET_ERRNO(ERANGE); + } + } + + return negative ? (unsigned long long)(-((long long)number)) : number; +} + +#endif /* defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) */ + +#endif /* defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX) */ + +#endif +/**********************************************************************/ +/* Made _Exit() an alias for _exit(), as per C99. */ +/* #ifdef L__Exit */ +/* void _Exit(int status) */ +/* { */ +/* _exit(status); */ +/* } */ + +/* #endif */ +/**********************************************************************/ +#ifdef L_bsearch + +void *bsearch(const void *key, const void *base, size_t /* nmemb */ high, + size_t size, int (*compar)(const void *, const void *)) +{ + register char *p; + size_t low; + size_t mid; + int r; + + if (size > 0) { /* TODO: change this to an assert?? */ + low = 0; + while (low < high) { + mid = low + ((high - low) >> 1); /* Avoid possible overflow here. */ + p = ((char *)base) + mid * size; /* Could overflow here... */ + r = (*compar)(key, p); /* but that's an application problem! */ + if (r > 0) { + low = mid + 1; + } else if (r < 0) { + high = mid; + } else { + return p; + } + } + } + return NULL; +} + +#endif +/**********************************************************************/ +#ifdef L_qsort + +/* This code is derived from a public domain shell sort routine by + * Ray Gardner and found in Bob Stout's snippets collection. The + * original code is included below in an #if 0/#endif block. + * + * I modified it to avoid the possibility of overflow in the wgap + * calculation, as well as to reduce the generated code size with + * bcc and gcc. */ + +void qsort(void *base, + size_t nel, + size_t width, + int (*comp)(const void *, const void *)) +{ + size_t wgap, i, j, k; + char tmp; + + if ((nel > 1) && (width > 0)) { + assert(nel <= ((size_t)(-1)) / width); /* check for overflow */ + wgap = 0; + do { + wgap = 3 * wgap + 1; + } while (wgap < (nel-1)/3); + /* From the above, we know that either wgap == 1 < nel or */ + /* ((wgap-1)/3 < (int) ((nel-1)/3) <= (nel-1)/3 ==> wgap < nel. */ + wgap *= width; /* So this can not overflow if wnel doesn't. */ + nel *= width; /* Convert nel to 'wnel' */ + do { + i = wgap; + do { + j = i; + do { + register char *a; + register char *b; + + j -= wgap; + a = j + ((char *)base); + b = a + wgap; + if ((*comp)(a, b) <= 0) { + break; + } + k = width; + do { + tmp = *a; + *a++ = *b; + *b++ = tmp; + } while (--k); + } while (j >= wgap); + i += width; + } while (i < nel); + wgap = (wgap - width)/3; + } while (wgap); + } +} +libc_hidden_def(qsort) + +/* ---------- original snippets version below ---------- */ + +#if 0 +/* +** ssort() -- Fast, small, qsort()-compatible Shell sort +** +** by Ray Gardner, public domain 5/90 +*/ + +#include + +void ssort(void *base, + size_t nel, + size_t width, + int (*comp)(const void *, const void *)) +{ + size_t wnel, gap, wgap, i, j, k; + char *a, *b, tmp; + + wnel = width * nel; + for (gap = 0; ++gap < nel;) + gap *= 3; + while ((gap /= 3) != 0) { + wgap = width * gap; + for (i = wgap; i < wnel; i += width) { + for (j = i - wgap; ;j -= wgap) { + a = j + (char *)base; + b = a + wgap; + if ((*comp)(a, b) <= 0) + break; + k = width; + do { + tmp = *a; + *a++ = *b; + *b++ = tmp; + } while (--k); + if (j < wgap) + break; + } + } + } +} +#endif + +#endif +/**********************************************************************/ +#ifdef L__stdlib_mb_cur_max + +size_t _stdlib_mb_cur_max(void) +{ +#ifdef __CTYPE_HAS_UTF_8_LOCALES + return __UCLIBC_CURLOCALE->mb_cur_max; +#else +#ifdef __CTYPE_HAS_8_BIT_LOCALES +#ifdef __UCLIBC_MJN3_ONLY__ +#warning need to change this when/if transliteration is implemented +#endif +#endif + return 1; +#endif +} +libc_hidden_def(_stdlib_mb_cur_max) + +#endif + +#ifdef __UCLIBC_HAS_LOCALE__ +/* + * The following function return 1 if the encoding is stateful, 0 if stateless. + * To note, until now all the supported encoding are stateless. + */ + +static __always_inline int is_stateful(unsigned char encoding) +{ + switch (encoding) + { + case __ctype_encoding_7_bit: + case __ctype_encoding_utf8: + case __ctype_encoding_8_bit: + return 0; + default: + assert(0); + return -1; + } +} +#else +#define is_stateful(encoding) 0 +#endif + +/**********************************************************************/ +#ifdef L_mblen + + +int mblen(register const char *s, size_t n) +{ + static mbstate_t state; + size_t r; + + if (!s) { + state.__mask = 0; + /* + In this case we have to return 0 because the only multibyte supported encoding + is utf-8, that is a stateless encoding. See mblen() documentation. + */ + return is_stateful(ENCODING); + } + + if (*s == '\0') + /* According to the ISO C 89 standard this is the expected behaviour. */ + return 0; + + if ((r = mbrlen(s, n, &state)) == (size_t) -2) { + /* TODO: Should we set an error state? */ + state.__wc = 0xffffU; /* Make sure we're in an error state. */ + return -1; /* TODO: Change error code above? */ + } + return r; +} + +#endif +/**********************************************************************/ +#ifdef L_mbtowc + + +int mbtowc(wchar_t *__restrict pwc, register const char *__restrict s, size_t n) +{ + static mbstate_t state; + size_t r; + + if (!s) { + state.__mask = 0; + /* + In this case we have to return 0 because the only multibyte supported encoding + is utf-8, that is a stateless encoding. See mbtowc() documentation. + */ + + return is_stateful(ENCODING); + } + + if (*s == '\0') + /* According to the ISO C 89 standard this is the expected behaviour. */ + return 0; + + if ((r = mbrtowc(pwc, s, n, &state)) == (size_t) -2) { + /* TODO: Should we set an error state? */ + state.__wc = 0xffffU; /* Make sure we're in an error state. */ + return -1; /* TODO: Change error code above? */ + } + return r; +} + +#endif +/**********************************************************************/ +#ifdef L_wctomb + +/* Note: We completely ignore state in all currently supported conversions. */ + + +int wctomb(register char *__restrict s, wchar_t swc) +{ + return (!s) + ? + /* + In this case we have to return 0 because the only multibyte supported encoding + is utf-8, that is a stateless encoding. See wctomb() documentation. + */ + + is_stateful(ENCODING) + : ((ssize_t) wcrtomb(s, swc, NULL)); +} + +#endif +/**********************************************************************/ +#ifdef L_mbstowcs + + +size_t mbstowcs(wchar_t * __restrict pwcs, const char * __restrict s, size_t n) +{ + mbstate_t state; + const char *e = s; /* Needed because of restrict. */ + + state.__mask = 0; /* Always start in initial shift state. */ + return mbsrtowcs(pwcs, &e, n, &state); +} + +#endif +/**********************************************************************/ +#ifdef L_wcstombs + +/* Note: We completely ignore state in all currently supported conversions. */ + + +size_t wcstombs(char * __restrict s, const wchar_t * __restrict pwcs, size_t n) +{ + const wchar_t *e = pwcs; /* Needed because of restrict. */ + + return wcsrtombs(s, &e, n, NULL); +} + +#endif +/**********************************************************************/ +#if defined(L_wcstol) || defined(L_wcstol_l) + +libc_hidden_proto(__XL_NPP(wcstol)) +long __XL_NPP(wcstol)(const wchar_t * __restrict str, + wchar_t ** __restrict endptr, int base __LOCALE_PARAM) +{ + return __XL_NPP(_stdlib_wcsto_l)(str, endptr, base, 1 __LOCALE_ARG); +} +libc_hidden_def(__XL_NPP(wcstol)) + +#if (ULONG_MAX == UINTMAX_MAX) && !defined(L_wcstol_l) +strong_alias(wcstol,wcstoimax) +#endif + +#if defined(ULLONG_MAX) && (ULLONG_MAX == ULONG_MAX) +#ifdef L_wcstol_l +#undef wcstoll_l +#else +#undef wcstoll +#endif +extern __typeof(__XL_NPP(wcstol)) __XL_NPP(wcstoll); +libc_hidden_proto(__XL_NPP(wcstoll)) +strong_alias(__XL_NPP(wcstol),__XL_NPP(wcstoll)) +libc_hidden_def(__XL_NPP(wcstoll)) +#endif + +#endif +/**********************************************************************/ +#if defined(L_wcstoll) || defined(L_wcstoll_l) + +#if defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX) + +libc_hidden_proto(__XL_NPP(wcstoll)) +long long __XL_NPP(wcstoll)(const wchar_t * __restrict str, + wchar_t ** __restrict endptr, int base + __LOCALE_PARAM) +{ + return (long long) __XL_NPP(_stdlib_wcsto_ll)(str, endptr, base, 1 __LOCALE_ARG); +} +libc_hidden_def(__XL_NPP(wcstoll)) + +#if !defined(L_wcstoll_l) +#if (ULLONG_MAX == UINTMAX_MAX) +strong_alias(wcstoll,wcstoimax) +#endif +strong_alias(wcstoll,wcstoq) +#endif + +#endif /* defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX) */ + +#endif +/**********************************************************************/ +#if defined(L_wcstoul) || defined(L_wcstoul_l) + +libc_hidden_proto(__XL_NPP(wcstoul)) +unsigned long __XL_NPP(wcstoul)(const wchar_t * __restrict str, + wchar_t ** __restrict endptr, int base + __LOCALE_PARAM) +{ + return __XL_NPP(_stdlib_wcsto_l)(str, endptr, base, 0 __LOCALE_ARG); +} +libc_hidden_def(__XL_NPP(wcstoul)) + +#if (ULONG_MAX == UINTMAX_MAX) && !defined(L_wcstoul_l) +strong_alias(wcstoul,wcstoumax) +#endif + +#if defined(ULLONG_MAX) && (ULLONG_MAX == ULONG_MAX) +#ifdef L_wcstoul_l +#undef wcstoull_l +#else +#undef wcstoull +#endif +extern __typeof(__XL_NPP(wcstoul)) __XL_NPP(wcstoull); +libc_hidden_proto(__XL_NPP(wcstoull)) +strong_alias(__XL_NPP(wcstoul),__XL_NPP(wcstoull)) +libc_hidden_def(__XL_NPP(wcstoull)) +#endif + +#endif +/**********************************************************************/ +#if defined(L_wcstoull) || defined(L_wcstoull_l) + +#if defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX) + +libc_hidden_proto(__XL_NPP(wcstoull)) +unsigned long long __XL_NPP(wcstoull)(const wchar_t * __restrict str, + wchar_t ** __restrict endptr, int base + __LOCALE_PARAM) +{ + return __XL_NPP(_stdlib_wcsto_ll)(str, endptr, base, 0 __LOCALE_ARG); +} +libc_hidden_def(__XL_NPP(wcstoull)) + +#if !defined(L_wcstoull_l) +#if (ULLONG_MAX == UINTMAX_MAX) +strong_alias(wcstoull,wcstoumax) +#endif +strong_alias(wcstoull,wcstouq) +#endif + +#endif /* defined(ULLONG_MAX) && (LLONG_MAX > LONG_MAX) */ + +#endif +/**********************************************************************/ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/strtod.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/strtod.c new file mode 100644 index 00000000..7f59aef4 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/strtod.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_strtod +#include "_strtod.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/strtod_l.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/strtod_l.c new file mode 100644 index 00000000..41312423 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/strtod_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2000-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_strtod_l +#define __UCLIBC_DO_XLOCALE +#include "_strtod.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/strtof.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/strtof.c new file mode 100644 index 00000000..35e89771 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/strtof.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_strtof +#include "_strtod.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/strtof_l.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/strtof_l.c new file mode 100644 index 00000000..7b44d1b0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/strtof_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2000-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_strtof_l +#define __UCLIBC_DO_XLOCALE +#include "_strtod.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/strtol.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/strtol.c new file mode 100644 index 00000000..cee4e134 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/strtol.c @@ -0,0 +1,7 @@ +/* Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_strtol +#include "stdlib.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/strtol_l.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/strtol_l.c new file mode 100644 index 00000000..d59c1e50 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/strtol_l.c @@ -0,0 +1,8 @@ +/* Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_strtol_l +#define __UCLIBC_DO_XLOCALE +#include "stdlib.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/strtold.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/strtold.c new file mode 100644 index 00000000..91a3ba79 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/strtold.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_strtold +#include "_strtod.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/strtold_l.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/strtold_l.c new file mode 100644 index 00000000..7eccd00b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/strtold_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2000-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_strtold_l +#define __UCLIBC_DO_XLOCALE +#include "_strtod.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/strtoll.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/strtoll.c new file mode 100644 index 00000000..a9c7c83e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/strtoll.c @@ -0,0 +1,7 @@ +/* Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_strtoll +#include "stdlib.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/strtoll_l.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/strtoll_l.c new file mode 100644 index 00000000..9fa46bdd --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/strtoll_l.c @@ -0,0 +1,8 @@ +/* Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_strtoll_l +#define __UCLIBC_DO_XLOCALE +#include "stdlib.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/strtoul.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/strtoul.c new file mode 100644 index 00000000..e92d2464 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/strtoul.c @@ -0,0 +1,7 @@ +/* Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_strtoul +#include "stdlib.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/strtoul_l.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/strtoul_l.c new file mode 100644 index 00000000..2aef138a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/strtoul_l.c @@ -0,0 +1,8 @@ +/* Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_strtoul_l +#define __UCLIBC_DO_XLOCALE +#include "stdlib.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/strtoull.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/strtoull.c new file mode 100644 index 00000000..60b626fe --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/strtoull.c @@ -0,0 +1,7 @@ +/* Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_strtoull +#include "stdlib.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/strtoull_l.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/strtoull_l.c new file mode 100644 index 00000000..81e045a4 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/strtoull_l.c @@ -0,0 +1,8 @@ +/* Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_strtoull_l +#define __UCLIBC_DO_XLOCALE +#include "stdlib.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/system.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/system.c new file mode 100644 index 00000000..a0ff726a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/system.c @@ -0,0 +1,270 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include +#include +#include +#include +#ifdef __UCLIBC_HAS_THREADS_NATIVE__ +#include +#include +#include +#include +#endif + +extern __typeof(system) __libc_system; + +/* TODO: the cancellable version breaks on sparc currently, + * need to figure out why still + */ +#if !defined __UCLIBC_HAS_THREADS_NATIVE__ || defined __sparc__ +/* uClinux-2.0 has vfork, but Linux 2.0 doesn't */ +#include +#ifndef __NR_vfork +# define vfork fork +#endif + +int __libc_system(const char *command) +{ + int wait_val, pid; + __sighandler_t save_quit, save_int, save_chld; + + if (command == 0) + return 1; + + save_quit = signal(SIGQUIT, SIG_IGN); + save_int = signal(SIGINT, SIG_IGN); + save_chld = signal(SIGCHLD, SIG_DFL); + + if ((pid = vfork()) < 0) { + signal(SIGQUIT, save_quit); + signal(SIGINT, save_int); + signal(SIGCHLD, save_chld); + return -1; + } + if (pid == 0) { + signal(SIGQUIT, SIG_DFL); + signal(SIGINT, SIG_DFL); + signal(SIGCHLD, SIG_DFL); + + execl("/bin/sh", "sh", "-c", command, (char *) 0); + _exit(127); + } + /* Signals are not absolutly guarenteed with vfork */ + signal(SIGQUIT, SIG_IGN); + signal(SIGINT, SIG_IGN); + +#if 0 + __printf("Waiting for child %d\n", pid); +#endif + + if (wait4(pid, &wait_val, 0, 0) == -1) + wait_val = -1; + + signal(SIGQUIT, save_quit); + signal(SIGINT, save_int); + signal(SIGCHLD, save_chld); + return wait_val; +} +#else +/* We have to and actually can handle cancelable system(). The big + problem: we have to kill the child process if necessary. To do + this a cleanup handler has to be registered and is has to be able + to find the PID of the child. The main problem is to reliable have + the PID when needed. It is not necessary for the parent thread to + return. It might still be in the kernel when the cancellation + request comes. Therefore we have to use the clone() calls ability + to have the kernel write the PID into the user-level variable. */ + +libc_hidden_proto(sigaction) +libc_hidden_proto(waitpid) + +#if defined __ia64__ +# define FORK() \ + INLINE_SYSCALL (clone2, 6, CLONE_PARENT_SETTID | SIGCHLD, NULL, 0, \ + &pid, NULL, NULL) +#elif defined __sparc__ +# define FORK() \ + INLINE_CLONE_SYSCALL (CLONE_PARENT_SETTID | SIGCHLD, 0, &pid, NULL, NULL) +#elif defined __s390__ +# define FORK() \ + INLINE_SYSCALL (clone, 3, 0, CLONE_PARENT_SETTID | SIGCHLD, &pid) +#else +# define FORK() \ + INLINE_SYSCALL (clone, 3, CLONE_PARENT_SETTID | SIGCHLD, 0, &pid) +#endif + +static void cancel_handler (void *arg); + +# define CLEANUP_HANDLER \ + __libc_cleanup_region_start (1, cancel_handler, &pid) + +# define CLEANUP_RESET \ + __libc_cleanup_region_end (0) + +static struct sigaction intr, quit; +static int sa_refcntr; +__libc_lock_define_initialized (static, lock); + +# define DO_LOCK() __libc_lock_lock (lock) +# define DO_UNLOCK() __libc_lock_unlock (lock) +# define INIT_LOCK() ({ __libc_lock_init (lock); sa_refcntr = 0; }) +# define ADD_REF() sa_refcntr++ +# define SUB_REF() --sa_refcntr + +/* Execute LINE as a shell command, returning its status. */ +static int +do_system (const char *line) +{ + int status, save; + pid_t pid; + struct sigaction sa; + sigset_t omask; + + memset(&sa, 0, sizeof(sa)); + sa.sa_handler = SIG_IGN; + /*sa.sa_flags = 0; - done by memset */ + /*__sigemptyset (&sa.sa_mask); - done by memset */ + + DO_LOCK (); + if (ADD_REF () == 0) + { + if (sigaction (SIGINT, &sa, &intr) < 0) + { + SUB_REF (); + goto out; + } + if (sigaction (SIGQUIT, &sa, &quit) < 0) + { + save = errno; + SUB_REF (); + goto out_restore_sigint; + } + } + DO_UNLOCK (); + + /* We reuse the bitmap in the 'sa' structure. */ + __sigaddset (&sa.sa_mask, SIGCHLD); + save = errno; + if (sigprocmask (SIG_BLOCK, &sa.sa_mask, &omask) < 0) + { + { + DO_LOCK (); + if (SUB_REF () == 0) + { + save = errno; + (void) sigaction (SIGQUIT, &quit, (struct sigaction *) NULL); + out_restore_sigint: + (void) sigaction (SIGINT, &intr, (struct sigaction *) NULL); + __set_errno (save); + } + out: + DO_UNLOCK (); + return -1; + } + } + + CLEANUP_HANDLER; + + pid = FORK (); + if (pid == (pid_t) 0) + { + /* Child side. */ + const char *new_argv[4]; + new_argv[0] = "/bin/sh"; + new_argv[1] = "-c"; + new_argv[2] = line; + new_argv[3] = NULL; + + /* Restore the signals. */ + (void) sigaction (SIGINT, &intr, (struct sigaction *) NULL); + (void) sigaction (SIGQUIT, &quit, (struct sigaction *) NULL); + (void) sigprocmask (SIG_SETMASK, &omask, (sigset_t *) NULL); + INIT_LOCK (); + + /* Exec the shell. */ + (void) execve ("/bin/sh", (char *const *) new_argv, __environ); + _exit (127); + } + else if (pid < (pid_t) 0) + /* The fork failed. */ + status = -1; + else + /* Parent side. */ + { + /* Note the system() is a cancellation point. But since we call + waitpid() which itself is a cancellation point we do not + have to do anything here. */ + if (TEMP_FAILURE_RETRY (waitpid (pid, &status, 0)) != pid) + status = -1; + } + + CLEANUP_RESET; + + save = errno; + DO_LOCK (); + if ((SUB_REF () == 0 + && (sigaction (SIGINT, &intr, (struct sigaction *) NULL) + | sigaction (SIGQUIT, &quit, (struct sigaction *) NULL)) != 0) + || sigprocmask (SIG_SETMASK, &omask, (sigset_t *) NULL) != 0) + { + status = -1; + } + DO_UNLOCK (); + + return status; +} + + +int +__libc_system (const char *line) +{ + if (line == NULL) + /* Check that we have a command processor available. It might + not be available after a chroot(), for example. */ + return do_system ("exit 0") == 0; + + if (SINGLE_THREAD_P) + return do_system (line); + + int oldtype = LIBC_CANCEL_ASYNC (); + + int result = do_system (line); + + LIBC_CANCEL_RESET (oldtype); + + return result; +} + + +/* The cancellation handler. */ +static void +cancel_handler (void *arg) +{ + pid_t child = *(pid_t *) arg; + + INTERNAL_SYSCALL_DECL (err); + INTERNAL_SYSCALL (kill, err, 2, child, SIGKILL); + + TEMP_FAILURE_RETRY (waitpid (child, NULL, 0)); + + DO_LOCK (); + + if (SUB_REF () == 0) + { + (void) sigaction (SIGQUIT, &quit, (struct sigaction *) NULL); + (void) sigaction (SIGINT, &intr, (struct sigaction *) NULL); + } + + DO_UNLOCK (); +} +#endif +#ifdef IS_IN_libc +weak_alias(__libc_system,system) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/unix_grantpt.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/unix_grantpt.c new file mode 100644 index 00000000..1be0a7dd --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/unix_grantpt.c @@ -0,0 +1,201 @@ +/* Copyright (C) 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Zack Weinberg , 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "pty-private.h" + + +/* uClinux-2.0 has vfork, but Linux 2.0 doesn't */ +#include +#if ! defined __NR_vfork +#define vfork fork +#endif + +/* Return the result of ptsname_r in the buffer pointed to by PTS, + which should be of length BUF_LEN. If it is too long to fit in + this buffer, a sufficiently long buffer is allocated using malloc, + and returned in PTS. 0 is returned upon success, -1 otherwise. */ +static int +pts_name (int fd, char **pts, size_t buf_len) +{ + int rv; + char *buf = *pts; + + for (;;) + { + char *new_buf; + + if (buf_len) + { + rv = ptsname_r (fd, buf, buf_len); + + if (rv != 0 || memchr (buf, '\0', buf_len)) + /* We either got an error, or we succeeded and the + returned name fit in the buffer. */ + break; + + /* Try again with a longer buffer. */ + buf_len += buf_len; /* Double it */ + } + else + /* No initial buffer; start out by mallocing one. */ + buf_len = 128; /* First time guess. */ + + if (buf != *pts) + /* We've already malloced another buffer at least once. */ + new_buf = realloc (buf, buf_len); + else + new_buf = malloc (buf_len); + if (! new_buf) + { + rv = -1; + errno = ENOMEM; + break; + } + buf = new_buf; + } + + if (rv == 0) + *pts = buf; /* Return buffer to the user. */ + else if (buf != *pts) + free (buf); /* Free what we malloced when returning an error. */ + + return rv; +} + +/* Change the ownership and access permission of the slave pseudo + terminal associated with the master pseudo terminal specified + by FD. */ +int +grantpt (int fd) +{ + int retval = -1; +#ifdef PATH_MAX + char _buf[PATH_MAX]; +#else + char _buf[512]; +#endif + char *buf = _buf; + struct stat st; + uid_t uid; + gid_t gid; + pid_t pid; + + if (pts_name (fd, &buf, sizeof (_buf))) + return -1; + + if (stat(buf, &st) < 0) + goto cleanup; + + /* Make sure that we own the device. */ + uid = getuid (); + if (st.st_uid != uid) + { + if (chown (buf, uid, st.st_gid) < 0) + goto helper; + } + + gid = getgid (); + + /* Make sure the group of the device is that special group. */ + if (st.st_gid != gid) + { + if (chown (buf, uid, gid) < 0) + goto helper; + } + + /* Make sure the permission mode is set to readable and writable by + the owner, and writable by the group. */ + if ((st.st_mode & ACCESSPERMS) != (S_IRUSR|S_IWUSR|S_IWGRP)) + { + if (chmod (buf, S_IRUSR|S_IWUSR|S_IWGRP) < 0) + goto helper; + } + + retval = 0; + goto cleanup; + + /* We have to use the helper program. */ + helper: + + pid = vfork (); + if (pid == -1) + goto cleanup; + else if (pid == 0) + { + /* Disable core dumps. */ + struct rlimit rl = { 0, 0 }; + setrlimit (RLIMIT_CORE, &rl); + + /* We pase the master pseudo terminal as file descriptor PTY_FILENO. */ + if (fd != PTY_FILENO) + if (dup2 (fd, PTY_FILENO) < 0) + _exit (FAIL_EBADF); + + execle (_PATH_PT_CHOWN, _PATH_PT_CHOWN, NULL, NULL); + _exit (FAIL_EXEC); + } + else + { + int w; + + if (waitpid (pid, &w, 0) == -1) + goto cleanup; + if (!WIFEXITED (w)) + errno = ENOEXEC; + else + switch (WEXITSTATUS(w)) + { + case 0: + retval = 0; + break; + case FAIL_EBADF: + errno = EBADF; + break; + case FAIL_EINVAL: + errno = EINVAL; + break; + case FAIL_EACCES: + errno = EACCES; + break; + case FAIL_EXEC: + errno = ENOEXEC; + break; + + default: + assert(! "getpt: internal error: invalid exit code from pt_chown"); + } + } + + cleanup: + if (buf != _buf) + free (buf); + + return retval; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/unlockpt.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/unlockpt.c new file mode 100644 index 00000000..5dfea15d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/unlockpt.c @@ -0,0 +1,49 @@ +/* Copyright (C) 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Zack Weinberg , 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include + + +/* Unlock the slave pseudo terminal associated with the master pseudo + terminal specified by FD. */ +int +unlockpt (int fd) +{ +#ifdef TIOCSPTLCK + int save_errno = errno; + int unlock = 0; + + if (ioctl (fd, TIOCSPTLCK, &unlock)) + { + if (errno == EINVAL) + { + errno = save_errno; + return 0; + } + else + return -1; + } +#endif + /* If we have no TIOCSPTLCK ioctl, all slave pseudo terminals are + unlocked by default. */ + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/valloc.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/valloc.c new file mode 100644 index 00000000..c5197b2b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/valloc.c @@ -0,0 +1,36 @@ +/* vi: set sw=4 ts=4: */ +/* Allocate memory on a page boundary. + Copyright (C) 1991, 1992 Free Software Foundation, Inc. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with this library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. + + The author may be reached (Email) at the address mike@@ai.mit.edu, + or (US mail) as Mike Haertel c/o Free Software Foundation. */ + +#include +#include +#include + + +static size_t pagesize; + +__ptr_t valloc (size_t size) +{ + if (pagesize == 0) + pagesize = getpagesize (); + + return memalign(pagesize, size); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/wcstod.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/wcstod.c new file mode 100644 index 00000000..08f80211 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/wcstod.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_wcstod +#include "_strtod.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/wcstod_l.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/wcstod_l.c new file mode 100644 index 00000000..be0e58e5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/wcstod_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2000-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_wcstod_l +#define __UCLIBC_DO_XLOCALE +#include "_strtod.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/wcstof.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/wcstof.c new file mode 100644 index 00000000..27ad22f6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/wcstof.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_wcstof +#include "_strtod.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/wcstof_l.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/wcstof_l.c new file mode 100644 index 00000000..953ebe04 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/wcstof_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2000-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_wcstof_l +#define __UCLIBC_DO_XLOCALE +#include "_strtod.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/wcstol.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/wcstol.c new file mode 100644 index 00000000..74462e1a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/wcstol.c @@ -0,0 +1,7 @@ +/* Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_wcstol +#include "stdlib.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/wcstol_l.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/wcstol_l.c new file mode 100644 index 00000000..4282987d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/wcstol_l.c @@ -0,0 +1,8 @@ +/* Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_wcstol_l +#define __UCLIBC_DO_XLOCALE +#include "stdlib.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/wcstold.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/wcstold.c new file mode 100644 index 00000000..cd879c11 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/wcstold.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_wcstold +#include "_strtod.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/wcstold_l.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/wcstold_l.c new file mode 100644 index 00000000..2ea23b0d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/wcstold_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2000-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_wcstold_l +#define __UCLIBC_DO_XLOCALE +#include "_strtod.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/wcstoll.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/wcstoll.c new file mode 100644 index 00000000..4cc9b05f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/wcstoll.c @@ -0,0 +1,7 @@ +/* Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_wcstoll +#include "stdlib.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/wcstoll_l.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/wcstoll_l.c new file mode 100644 index 00000000..66c23c29 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/wcstoll_l.c @@ -0,0 +1,8 @@ +/* Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_wcstoll_l +#define __UCLIBC_DO_XLOCALE +#include "stdlib.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/wcstombs.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/wcstombs.c new file mode 100644 index 00000000..c3d08d8d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/wcstombs.c @@ -0,0 +1,7 @@ +/* Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_wcstombs +#include "stdlib.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/wcstoul.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/wcstoul.c new file mode 100644 index 00000000..55427447 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/wcstoul.c @@ -0,0 +1,7 @@ +/* Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_wcstoul +#include "stdlib.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/wcstoul_l.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/wcstoul_l.c new file mode 100644 index 00000000..529e8e40 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/wcstoul_l.c @@ -0,0 +1,8 @@ +/* Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_wcstoul_l +#define __UCLIBC_DO_XLOCALE +#include "stdlib.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/wcstoull.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/wcstoull.c new file mode 100644 index 00000000..ea884ef0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/wcstoull.c @@ -0,0 +1,7 @@ +/* Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_wcstoull +#include "stdlib.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/wcstoull_l.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/wcstoull_l.c new file mode 100644 index 00000000..976d103e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/wcstoull_l.c @@ -0,0 +1,8 @@ +/* Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_wcstoull_l +#define __UCLIBC_DO_XLOCALE +#include "stdlib.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/wctomb.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/wctomb.c new file mode 100644 index 00000000..3f612be2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/stdlib/wctomb.c @@ -0,0 +1,7 @@ +/* Copyright (C) 2004-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_wctomb +#include "stdlib.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/.indent.pro b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/.indent.pro new file mode 100644 index 00000000..492ecf1c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/.indent.pro @@ -0,0 +1,33 @@ +--blank-lines-after-declarations +--blank-lines-after-procedures +--break-before-boolean-operator +--no-blank-lines-after-commas +--braces-on-if-line +--braces-on-struct-decl-line +--comment-indentation25 +--declaration-comment-column25 +--no-comment-delimiters-on-blank-lines +--cuddle-else +--continuation-indentation4 +--case-indentation0 +--else-endif-column33 +--space-after-cast +--line-comments-indentation0 +--declaration-indentation1 +--dont-format-first-column-comments +--dont-format-comments +--honour-newlines +--indent-level4 +/* changed from 0 to 4 */ +--parameter-indentation4 +--line-length78 /* changed from 75 */ +--continue-at-parentheses +--no-space-after-function-call-names +--dont-break-procedure-type +--dont-star-comments +--leave-optional-blank-lines +--dont-space-special-semicolon +--tab-size4 +/* additions by Mark */ +--case-brace-indentation0 +--leave-preprocessor-space diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/Makefile new file mode 100644 index 00000000..11f362a5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../ +top_builddir=../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/Makefile.in new file mode 100644 index 00000000..e7f2ccde --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/Makefile.in @@ -0,0 +1,144 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +subdirs += libc/string/$(TARGET_ARCH) libc/string/generic + +# +# Arch specific fun +# +# Collect the subarch specific implementation (asm files) +ifneq ($(strip $(TARGET_SUBARCH)),) +STRING_SUBARCH_DIR := $(top_srcdir)libc/string/$(TARGET_ARCH)/$(TARGET_SUBARCH) +STRING_SUBARCH_OUT := $(top_builddir)libc/string/$(TARGET_ARCH)/$(TARGET_SUBARCH) + +STRING_SUBARCH_SSRC := $(wildcard $(STRING_SUBARCH_OUT)/*.S) +STRING_SUBARCH_SOBJ := $(patsubst $(STRING_SUBARCH_DIR)/%.S,$(STRING_SUBARCH_OUT)/%.o,$(STRING_SUBARCH_SSRC)) + +STRING_SUBARCH_CSRC := $(wildcard $(STRING_SUBARCH_OUT)/*.c) +STRING_SUBARCH_COBJ := $(patsubst $(STRING_SUBARCH_DIR)/%.c,$(STRING_SUBARCH_OUT)/%.o,$(STRING_SUBARCH_CSRC)) + +STRING_SUBARCH_OBJS := $(STRING_SUBARCH_SOBJ) $(STRING_SUBARCH_COBJ) +endif + +# Collect the arch specific implementation (asm, c files) +STRING_ARCH_DIR := $(top_srcdir)libc/string/$(TARGET_ARCH) +STRING_ARCH_OUT := $(top_builddir)libc/string/$(TARGET_ARCH) + +STRING_ARCH_SRC := $(wildcard $(STRING_ARCH_DIR)/*.c) +STRING_ARCH_OBJ := $(patsubst $(STRING_ARCH_DIR)/%.c,$(STRING_ARCH_OUT)/%.o,$(STRING_ARCH_SRC)) + +STRING_ARCH_SSRC := $(wildcard $(STRING_ARCH_DIR)/*.S) + +# Exclude the subarch implementation from the arch ones +ifneq ($(strip $(STRING_SUBARCH_OBJS)),) +STRING_ARCH_SSRC := $(filter-out $(patsubst %.o,$(STRING_ARCH_DIR)/%.S,$(notdir $(STRING_SUBARCH_OBJS))),$(STRING_ARCH_SSRC)) +endif + +STRING_ARCH_SOBJ := $(patsubst $(STRING_ARCH_DIR)/%.S,$(STRING_ARCH_OUT)/%.o,$(STRING_ARCH_SSRC)) + +STRING_ARCH_OBJS := $(STRING_ARCH_OBJ) $(STRING_ARCH_SOBJ) + +libc-$(UCLIBC_HAS_STRING_ARCH_OPT) += $(STRING_ARCH_OBJS) $(STRING_SUBARCH_OBJS) + +libc-nomulti-$(UCLIBC_HAS_STRING_ARCH_OPT) += $(STRING_ARCH_SOBJ) $(STRING_SUBARCH_OBJS) + +# +# Generic stuff +# +STRING_GENERIC_DIR := $(top_srcdir)libc/string/generic +STRING_GENERIC_OUT := $(top_builddir)libc/string/generic + +STRING_GENERIC_SRC := $(wildcard $(STRING_GENERIC_DIR)/*.c) +STRING_GENERIC_SRC := $(filter-out $(STRING_GENERIC_DIR)/_memcpy_fwd.c, $(STRING_GENERIC_SRC)) + +ifeq ($(UCLIBC_HAS_STRING_ARCH_OPT),y) +ifneq ($(strip $(STRING_ARCH_OBJS)),) +STRING_GENERIC_SRC := $(filter-out $(patsubst %.o,$(STRING_GENERIC_DIR)/%.c,$(notdir $(STRING_ARCH_OBJS))),$(STRING_GENERIC_SRC)) +endif +ifneq ($(strip $(STRING_SUBARCH_OBJS)),) +STRING_GENERIC_SRC := $(filter-out $(patsubst %.o,$(STRING_GENERIC_DIR)/%.c,$(notdir $(STRING_SUBARCH_OBJS))),$(STRING_GENERIC_SRC)) +endif +endif + +STRING_GENERIC_OBJS := $(patsubst $(STRING_GENERIC_DIR)/%.c,$(STRING_GENERIC_OUT)/%.o,$(STRING_GENERIC_SRC)) + +libc-$(UCLIBC_HAS_STRING_GENERIC_OPT) += $(STRING_GENERIC_OBJS) + +# +# Top level string +# +STRING_DIR := $(top_srcdir)libc/string +STRING_OUT := $(top_builddir)libc/string + +STRING_ALL_WXSRC := $(wildcard $(STRING_DIR)/w*_l.c) +ifeq ($(UCLIBC_HAS_LOCALE),y) +STRING_WXSRC := $(STRING_ALL_WXSRC) +else +# wcscoll_l +STRING_WXSRC := $(filter-out $(STRING_DIR)/wcsxfrm_l.c,$(STRING_ALL_WXSRC)) +endif + +STRING_ALL_XLSRC := $(filter-out $(STRING_ALL_WXSRC),$(wildcard $(STRING_DIR)/*_l.c)) +ifeq ($(UCLIBC_HAS_LOCALE),y) +STRING_XLSRC := $(STRING_ALL_XLSRC) +else +# strcoll_l +STRING_XLSRC := $(filter-out $(STRING_DIR)/strxfrm_l.c,$(STRING_ALL_XLSRC)) +endif + +STRING_ALL_WSRC := $(filter-out $(STRING_ALL_WXSRC),$(wildcard $(STRING_DIR)/w*.c)) +ifeq ($(UCLIBC_HAS_LOCALE),y) +STRING_WSRC := $(STRING_ALL_WSRC) +else +# wcscoll +STRING_WSRC := $(filter-out $(STRING_DIR)/wcsxfrm.c,$(STRING_ALL_WSRC)) +endif + +STRING_ALL_CSRC := $(filter-out $(STRING_ALL_WXSRC) $(STRING_ALL_XLSRC) $(STRING_ALL_WSRC) $(STRING_DIR)/_collate.c,$(wildcard $(STRING_DIR)/*.c)) +ifeq ($(UCLIBC_HAS_LOCALE),y) +STRING_CSRC := $(STRING_ALL_CSRC) +else +# strcoll +STRING_CSRC := $(filter-out $(STRING_DIR)/strxfrm.c,$(STRING_ALL_CSRC)) +endif + +ifeq ($(UCLIBC_HAS_WCHAR),y) +STRING_CSRC += $(STRING_WSRC) +endif +ifeq ($(UCLIBC_HAS_XLOCALE),y) +STRING_CSRC += $(STRING_XLSRC) +ifeq ($(UCLIBC_HAS_WCHAR),y) +STRING_CSRC += $(STRING_WXSRC) +endif +endif + +ifeq ($(UCLIBC_HAS_STRING_ARCH_OPT),y) +ifneq ($(strip $(STRING_ARCH_OBJS)),) +STRING_CSRC := $(filter-out $(patsubst %.o,$(STRING_DIR)/%.c,$(notdir $(STRING_ARCH_OBJS))),$(STRING_CSRC)) +endif +ifneq ($(strip $(STRING_SUBARCH_OBJS)),) +STRING_CSRC := $(filter-out $(patsubst %.o,$(STRING_DIR)/%.c,$(notdir $(STRING_SUBARCH_OBJS))),$(STRING_CSRC)) +endif +endif + +ifeq ($(UCLIBC_HAS_STRING_GENERIC_OPT),y) +ifneq ($(strip $(STRING_GENERIC_OBJS)),) +STRING_CSRC := $(filter-out $(patsubst %.o,$(STRING_DIR)/%.c,$(notdir $(STRING_GENERIC_OBJS))),$(STRING_CSRC)) +endif +endif + +STRING_COBJ := $(patsubst $(STRING_DIR)/%.c,$(STRING_OUT)/%.o,$(STRING_CSRC)) + +libc-y += $(STRING_COBJ) + +libc-nomulti-$(UCLIBC_HAS_XLOCALE) += $(STRING_OUT)/wcsxfrm_l.o +libc-nomulti-y += $(STRING_OUT)/__xpg_strerror_r.o + +objclean-y += CLEAN_libc/string + +CLEAN_libc/string: + $(do_rm) $(addprefix $(STRING_OUT)/,$(addprefix *., o os oS) $(addprefix */*., o os oS) $(addprefix */*/*., o os oS)) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/__glibc_strerror_r.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/__glibc_strerror_r.c new file mode 100644 index 00000000..e97e5523 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/__glibc_strerror_r.c @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + + +char *__glibc_strerror_r(int errnum, char *strerrbuf, size_t buflen) +{ + __xpg_strerror_r(errnum, strerrbuf, buflen); + + return strerrbuf; +} +libc_hidden_def(__glibc_strerror_r) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/__xpg_basename.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/__xpg_basename.c new file mode 100644 index 00000000..2449d1d4 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/__xpg_basename.c @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include "_string.h" +#include + +char *__xpg_basename(register char *path) +{ + static const char null_or_empty[] = "."; + char *first; + register char *last; + + first = (char *) null_or_empty; + + if (path && *path) { + first = path; + last = path - 1; + + do { + if ((*path != '/') && (path > ++last)) { + last = first = path; + } + } while (*++path); + + if (*first == '/') { + last = first; + } + last[1] = 0; + } + + return first; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/__xpg_strerror_r.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/__xpg_strerror_r.c new file mode 100644 index 00000000..fb4d4400 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/__xpg_strerror_r.c @@ -0,0 +1,276 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* Make sure we get proper strerror_r() prototype */ +#define strerror_r _hidestrerror_r + +#include +#include +#include +#include "_syserrmsg.h" + +#undef strerror_r + + +#ifdef __UCLIBC_HAS_ERRNO_MESSAGES__ + +extern const char _string_syserrmsgs[] attribute_hidden; + +#if defined(__alpha__) || defined(__mips__) || defined(__sparc__) + +static const unsigned char estridx[] = { + 0, /* success is always 0 */ + EPERM, + ENOENT, + ESRCH, + EINTR, + EIO, + ENXIO, + E2BIG, + ENOEXEC, + EBADF, + ECHILD, + EAGAIN, + ENOMEM, + EACCES, + EFAULT, + ENOTBLK, + EBUSY, + EEXIST, + EXDEV, + ENODEV, + ENOTDIR, + EISDIR, + EINVAL, + ENFILE, + EMFILE, + ENOTTY, + ETXTBSY, + EFBIG, + ENOSPC, + ESPIPE, + EROFS, + EMLINK, + EPIPE, + EDOM, + ERANGE, + EDEADLK, + ENAMETOOLONG, + ENOLCK, + ENOSYS, + ENOTEMPTY, + ELOOP, + 0, + ENOMSG, + EIDRM, + ECHRNG, + EL2NSYNC, + EL3HLT, + EL3RST, + ELNRNG, + EUNATCH, + ENOCSI, + EL2HLT, + EBADE, + EBADR, + EXFULL, + ENOANO, + EBADRQC, + EBADSLT, + 0, + EBFONT, + ENOSTR, + ENODATA, + ETIME, + ENOSR, + ENONET, + ENOPKG, + EREMOTE, + ENOLINK, + EADV, + ESRMNT, + ECOMM, + EPROTO, + EMULTIHOP, + EDOTDOT, + EBADMSG, + EOVERFLOW, + ENOTUNIQ, + EBADFD, + EREMCHG, + ELIBACC, + ELIBBAD, + ELIBSCN, + ELIBMAX, + ELIBEXEC, + EILSEQ, + ERESTART, + ESTRPIPE, + EUSERS, + ENOTSOCK, + EDESTADDRREQ, + EMSGSIZE, + EPROTOTYPE, + ENOPROTOOPT, + EPROTONOSUPPORT, + ESOCKTNOSUPPORT, + EOPNOTSUPP, + EPFNOSUPPORT, + EAFNOSUPPORT, + EADDRINUSE, + EADDRNOTAVAIL, + ENETDOWN, + ENETUNREACH, + ENETRESET, + ECONNABORTED, + ECONNRESET, + ENOBUFS, + EISCONN, + ENOTCONN, + ESHUTDOWN, + ETOOMANYREFS, + ETIMEDOUT, + ECONNREFUSED, + EHOSTDOWN, + EHOSTUNREACH, + EALREADY, + EINPROGRESS, + ESTALE, + EUCLEAN, + ENOTNAM, + ENAVAIL, + EISNAM, + EREMOTEIO, +#if EDQUOT > 200 /* mips has an outrageous value for this... */ + 0, +#else + EDQUOT, +#endif + ENOMEDIUM, + EMEDIUMTYPE, +#if EDEADLOCK != EDEADLK + EDEADLOCK, +#endif +}; + +#endif + +int __xpg_strerror_r(int errnum, char *strerrbuf, size_t buflen) +{ + register char *s; + int i, retval; + char buf[_STRERROR_BUFSIZE]; + static const char unknown[] = { + 'U', 'n', 'k', 'n', 'o', 'w', 'n', ' ', 'e', 'r', 'r', 'o', 'r', ' ' + }; + + retval = EINVAL; + + +#ifdef __UCLIBC_HAS_ERRNO_MESSAGES__ + +#if defined(__alpha__) || defined(__mips__) || defined(__sparc__) + /* Need to translate errno to string index. */ + for (i = 0 ; i < sizeof(estridx)/sizeof(estridx[0]) ; i++) { + if (estridx[i] == errnum) { + goto GOT_ESTRIDX; + } + } + i = INT_MAX; /* Failed, but may need to check mips special case. */ +#if EDQUOT > 200 /* Deal with large EDQUOT value on mips */ + if (errnum == EDQUOT) + i = 122; +#endif + GOT_ESTRIDX: +#else + /* No errno to string index translation needed. */ + i = errnum; +#endif + + if (((unsigned int) i) < _SYS_NERR) { + /* Trade time for space. This function should rarely be called + * so rather than keeping an array of pointers for the different + * messages, just run through the buffer until we find the + * correct string. */ + for (s = (char *) _string_syserrmsgs ; i ; ++s) { + if (!*s) { + --i; + } + } + if (*s) { /* Make sure we have an actual message. */ + retval = 0; + goto GOT_MESG; + } + } + +#endif /* __UCLIBC_HAS_ERRNO_MESSAGES__ */ + + s = _int10tostr(buf+sizeof(buf)-1, errnum) - sizeof(unknown); + memcpy(s, unknown, sizeof(unknown)); + + GOT_MESG: + if (!strerrbuf) { /* SUSv3 */ + buflen = 0; + } + i = strlen(s) + 1; + if (i > buflen) { + i = buflen; + retval = ERANGE; + } + + if (i) { + memcpy(strerrbuf, s, i); + strerrbuf[i-1] = 0; /* In case buf was too small. */ + } + + if (retval) { + __set_errno(retval); + } + + return retval; +} + +#else /* __UCLIBC_HAS_ERRNO_MESSAGES__ */ + +int __xpg_strerror_r(int errnum, char *strerrbuf, size_t buflen) +{ + register char *s; + int i, retval; + char buf[_STRERROR_BUFSIZE]; + static const char unknown[] = { + 'U', 'n', 'k', 'n', 'o', 'w', 'n', ' ', 'e', 'r', 'r', 'o', 'r', ' ' + }; + + s = _int10tostr(buf+sizeof(buf)-1, errnum) - sizeof(unknown); + memcpy(s, unknown, sizeof(unknown)); + + if (!strerrbuf) { /* SUSv3 */ + buflen = 0; + } + + retval = EINVAL; + + i = buf + sizeof(buf) - s; + + if (i > buflen) { + i = buflen; + retval = ERANGE; + } + + if (i) { + memcpy(strerrbuf, s, i); + strerrbuf[i-1] = 0; /* In case buf was too small. */ + } + + __set_errno(retval); + + return retval; +} + +#endif /* __UCLIBC_HAS_ERRNO_MESSAGES__ */ +libc_hidden_def(__xpg_strerror_r) +weak_alias(__xpg_strerror_r, strerror_r) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/_collate.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/_collate.c new file mode 100644 index 00000000..77d9eb62 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/_collate.c @@ -0,0 +1,673 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* Dec 20, 2002 + * Initial test implementation of strcoll, strxfrm, wcscoll, and wcsxfrm. + * The code needs to be cleaned up a good bit, but I'd like to see people + * test it out. + * + */ + +#include "_string.h" +#include +#include +#include +#include +#include + +#ifdef __UCLIBC_HAS_LOCALE__ +#if defined(L_strxfrm) || defined(L_strxfrm_l) || defined(L_wcsxfrm) || defined(L_wcsxfrm_l) + +#ifdef L_strxfrm +#ifndef WANT_WIDE +#error WANT_WIDE should be defined for L_strxfrm +#endif +#ifdef L_wcsxfrm +#error L_wcsxfrm already defined for L_strxfrm +#endif +#endif /* L_strxfrm */ + +#if defined(L_strxfrm) || defined(L_strxfrm_l) + +#define wcscoll strcoll +#define wcscoll_l strcoll_l +#define wcsxfrm strxfrm +#define wcsxfrm_l strxfrm_l + +#undef WANT_WIDE +#undef Wvoid +#undef Wchar +#undef Wuchar +#undef Wint + +#define Wchar char + +#endif /* defined(L_strxfrm) || defined(L_strxfrm_l) */ + +#if defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) + + +int wcscoll (const Wchar *s0, const Wchar *s1) +{ + return wcscoll_l(s0, s1, __UCLIBC_CURLOCALE ); +} +libc_hidden_def(wcscoll) + + +size_t wcsxfrm(Wchar *__restrict ws1, const Wchar *__restrict ws2, size_t n) +{ + return wcsxfrm_l(ws1, ws2, n, __UCLIBC_CURLOCALE ); +} +libc_hidden_def(wcsxfrm) + +#else /* defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) */ + + +#if 0 +#define CUR_COLLATE (&__UCLIBC_CURLOCALE->collate) +#else +#define CUR_COLLATE (& __LOCALE_PTR->collate) +#endif + +#define MAX_PENDING 8 + +typedef struct { + const Wchar *s; + const Wchar *eob; /* end of backward */ + + __uwchar_t weight; + __uwchar_t ui_weight; /* undefined or invalid */ + int colitem; + int weightidx; + int rule; + size_t position; + /* should be wchar_t. if wchar < 0 do EILSEQ? */ + __uwchar_t *cip; + __uwchar_t ci_pending[MAX_PENDING]; /* nul-terminated */ + + char *back_buf; + char *bbe; /* end of back_buf (actual last... not 1 past end) */ + char *bp; /* ptr into backbuf, NULL if not in backward mode */ + char ibb[128]; + size_t bb_size; + + int ru_pushed; +} col_state_t; + + +#define WEIGHT_MASK 0x3fffU +#define RULE_MASK 0xc000U + +#define RULE_FORWARD (1 << 14) +#define RULE_POSITION (1 << 15) + +#define UI_IDX (WEIGHT_MASK-6) +#define POSIT_IDX (WEIGHT_MASK-5) +#define RANGE_IDX (WEIGHT_MASK-4) +#define UNDEF_IDX (WEIGHT_MASK-3) +#define INVAL_IDX (WEIGHT_MASK-2) +#define DITTO_IDX (WEIGHT_MASK-1) + + +#undef TRACE +#if 0 +#define TRACE(X) printf X +#else +#define TRACE(X) ((void)0) +#endif + +static int lookup(wchar_t wc __LOCALE_PARAM ) +{ + unsigned int sc, n, i0, i1; + + if (((__uwchar_t) wc) > 0xffffU) { + return 0; + } + + sc = wc & CUR_COLLATE->ti_mask; + wc >>= CUR_COLLATE->ti_shift; + n = wc & CUR_COLLATE->ii_mask; + wc >>= CUR_COLLATE->ii_shift; + + i0 = CUR_COLLATE->wcs2colidt_tbl[wc]; + i0 <<= CUR_COLLATE->ii_shift; + i1 = CUR_COLLATE->wcs2colidt_tbl[CUR_COLLATE->ii_len + i0 + n]; + i1 <<= CUR_COLLATE->ti_shift; + return CUR_COLLATE->wcs2colidt_tbl[CUR_COLLATE->ii_len + CUR_COLLATE->ti_len + i1 + sc]; + +} + +static void init_col_state(col_state_t *cs, const Wchar *wcs) +{ + memset(cs, 0, sizeof(col_state_t)); + cs->s = wcs; + cs->bp = cs->back_buf = cs->ibb; + cs->bb_size = 128; + cs->bbe = cs->back_buf + (cs->bb_size -1); +} + +static void next_weight(col_state_t *cs, int pass __LOCALE_PARAM ) +{ + int r, w, ru, ri, popping_backup_stack; + ssize_t n; + const uint16_t *p; +#ifdef WANT_WIDE +#define WC (*cs->s) +#define N (1) +#else /* WANT_WIDE */ + wchar_t WC; + size_t n0, nx; +#define N n0 + +#endif /* WANT_WIDE */ + + do { + + if (cs->ru_pushed) { + ru = cs->ru_pushed; + TRACE(("ru_pushed = %d\n", ru)); + cs->ru_pushed = 0; + goto POSITION_SKIP; + } + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning should we walk pendings backwards? +#endif + if (cs->cip) { /* possible pending weight */ + if ((r = *(cs->cip++)) == 0) { + cs->cip = NULL; + continue; + } + cs->weightidx = r & WEIGHT_MASK; + assert(cs->weightidx); +/* assert(cs->weightidx != WEIGHT_MASK); */ + } else { /* get the next collation item from the string */ + TRACE(("clearing popping flag\n")); + popping_backup_stack = 0; + + IGNORE_LOOP: + /* keep first pos as 0 for a sentinal */ + if (*cs->bp) { /* pending backward chars */ + POP_BACKUP: + popping_backup_stack = 1; + TRACE(("setting popping flag\n")); + n = 0; + if (*cs->bp > 0) { /* singles pending */ + cs->s -= 1; + if ((*cs->bp -= 1) == 0) { + cs->bp -= 1; + } + } else { /* last was a multi */ + cs->s += *cs->bp; + cs->bp -= 1; + } + } else if (!*cs->s) { /* not in backward mode and end of string */ + cs->weight = 0; + return; + } else { + cs->position += 1; + } + + BACK_LOOP: +#ifdef WANT_WIDE + n = 1; + cs->colitem = r = lookup(*cs->s __LOCALE_ARG ); +#else /* WANT_WIDE */ + n = n0 = __locale_mbrtowc_l(&WC, cs->s, __LOCALE_PTR); + if (n < 0) { + __set_errno(EILSEQ); + cs->weight = 0; + return; + } + cs->colitem = r = lookup(WC __LOCALE_ARG ); +#endif /* WANT_WIDE */ + + TRACE((" r=%d WC=%#lx\n", r, (unsigned long)(WC))); + + if (r > CUR_COLLATE->max_col_index) { /* starting char for one or more sequences */ + p = CUR_COLLATE->multistart_tbl; + p += p[r-CUR_COLLATE->max_col_index -1]; + do { + n = N; + r = *p++; + do { + if (!*p) { /* found it */ + cs->colitem = r; + TRACE((" found multi %d\n", n)); + goto FOUND; + } +#ifdef WANT_WIDE + /* the lookup check here is safe since we're assured that *p is a valid colidx */ + if (!cs->s[n] || (lookup(cs->s[n] __LOCALE_ARG ) != *p)) { + do {} while (*p++); + break; + } + ++p; + ++n; +#else /* WANT_WIDE */ + if (cs->s[n]) { + nx = __locale_mbrtowc_l(&WC, cs->s + n, __LOCALE_PTR); + if (nx < 0) { + __set_errno(EILSEQ); + cs->weight = 0; + return; + } + } + if (!cs->s[n] || (lookup(WC __LOCALE_ARG ) != *p)) { + do {} while (*p++); + break; + } + ++p; + n += nx; /* Only gets here if cs->s[n] != 0, so nx is set. */ +#endif /* WANT_WIDE */ + } while (1); + } while (1); + } else if (r == 0) { /* illegal, undefined, or part of a range */ + if ((CUR_COLLATE->range_count) +#ifdef __UCLIBC_MJN3_ONLY__ +#warning .. need to introduce range as a collating item? +#endif + && (((__uwchar_t)(WC - CUR_COLLATE->range_low)) <= CUR_COLLATE->range_count) + ) { /* part of a range */ + /* Note: cs->colitem = 0 already. */ + TRACE((" found range\n")); + ru = CUR_COLLATE->ruletable[CUR_COLLATE->range_rule_offset*CUR_COLLATE->MAX_WEIGHTS + pass]; + assert((ru & WEIGHT_MASK) != DITTO_IDX); + if ((ru & WEIGHT_MASK) == WEIGHT_MASK) { + ru = (ru & RULE_MASK) | RANGE_IDX; + cs->weight = CUR_COLLATE->range_base_weight + (WC - CUR_COLLATE->range_low); + } + goto RANGE_SKIP_TO; + } else if (((__uwchar_t)(WC)) <= 0x7fffffffUL) { /* legal but undefined */ + UNDEFINED: + /* Note: cs->colitem = 0 already. */ + ri = CUR_COLLATE->undefined_idx; + assert(ri != 0); /* implicit undefined isn't supported */ + + TRACE((" found explicit UNDEFINED\n")); +#ifdef __UCLIBC_MJN3_ONLY__ +#warning right now single weight locales do not support .. +#endif + if (CUR_COLLATE->num_weights == 1) { + TRACE((" single weight UNDEFINED\n")); + cs->weightidx = RANGE_IDX; + cs->weight = ri; + cs->s += n; + goto PROCESS_WEIGHT; + } + + ri = CUR_COLLATE->index2ruleidx[ri - 1]; + ru = CUR_COLLATE->ruletable[ri * CUR_COLLATE->MAX_WEIGHTS + pass]; + assert((ru & WEIGHT_MASK) != WEIGHT_MASK); /* TODO: handle ".." */ + if ((ru & WEIGHT_MASK) == DITTO_IDX) { + cs->colitem = CUR_COLLATE->undefined_idx; + } + goto RANGE_SKIP_TO; + } else { /* illegal */ + TRACE((" found illegal\n")); + __set_errno(EINVAL); + /* We put all illegals in the same equiv class with maximal weight, + * and ignore them after the first pass. */ + if (pass > 0) { + cs->s += n; + goto IGNORE_LOOP; + } + ru = (RULE_FORWARD | RANGE_IDX); + cs->weight = 0xffffU; + goto RANGE_SKIP_TO; + } + } else if (CUR_COLLATE->num_weights == 1) { + TRACE((" single weight\n")); + cs->weightidx = RANGE_IDX; + cs->weight = cs->colitem; + cs->s += n; + goto PROCESS_WEIGHT; + } else { + TRACE((" normal\n")); + } + + /* if we get here, it is a normal char either singlely weighted, undefined, or in a range */ + FOUND: + ri = CUR_COLLATE->index2ruleidx[cs->colitem - 1]; + TRACE((" ri=%d ", ri)); +#ifdef __UCLIBC_MJN3_ONLY__ +#warning make sure this is correct +#endif + if (!ri) { + TRACE(("NOT IN THIS LOCALE\n")); + goto UNDEFINED; + } + ru = CUR_COLLATE->ruletable[ri * CUR_COLLATE->MAX_WEIGHTS + pass]; + + RANGE_SKIP_TO: + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning ignoreables probably should not interrupt backwards processing, but this is wrong +#endif +/* if (!(ru & WEIGHT_MASK)) { */ +/* TRACE(("IGNORE\n")); */ +/* cs->s += n; */ +/* continue; */ +/* } */ + + + TRACE((" rule = %#x weight = %#x popping = %d s = %p eob = %p\n", + ru & RULE_MASK, ru & WEIGHT_MASK, popping_backup_stack, + cs->s, cs->eob)); + /* now we need to check if we're going backwards... */ + + if (!popping_backup_stack) { + if (!(ru & RULE_MASK)) { /* backward */ + TRACE(("backwards\n")); + assert(cs->bp <= cs->bbe); + if (cs->bp == cs->bbe) { + if (cs->back_buf == cs->ibb) { /* was using internal buffer */ + cs->bp = malloc(cs->bb_size + 128); + if (!cs->bp) { + __set_errno(ENOMEM); +#ifdef __UCLIBC_MJN3_ONLY__ +#warning what to do here? +#endif + cs->weight = 0; + return; + } + memcpy(cs->bp, cs->back_buf, cs->bb_size); + + } else { + cs->bp = realloc(cs->back_buf, cs->bb_size + 128); + if (!cs->bp) { + __set_errno(ENOMEM); +#ifdef __UCLIBC_MJN3_ONLY__ +#warning what to do here? +#endif + cs->weight = 0; + return; + } + } + cs->bb_size += 128; + cs->bbe = cs->bp + (cs->bbe - cs->back_buf); + cs->back_buf = cs->bp; + cs->bp = cs->bbe; + + } + if (n==1) { /* single char */ + if (*cs->bp && (((unsigned char)(*cs->bp)) < CHAR_MAX)) { + *cs->bp += 1; /* increment last single's count */ + } else { /* last was a multi, or just starting */ + if (!cs->bp) { + cs->bp = cs->back_buf; + } else { + assert(cs->bp < cs->bbe); + ++cs->bp; + } + *cs->bp = 1; + } + } else { /* multichar */ + assert(n>1); + assert(cs->bp < cs->bbe); + *++cs->bp = -n; + } + cs->s += n; + if (*cs->s) { + goto BACK_LOOP; + } + /* end-of-string so start popping */ + cs->eob = cs->s; + TRACE(("popping\n")); + goto POP_BACKUP; + } else if (*cs->bp) { /* was going backward but this element isn't */ + /* discard current and use previous backward element */ + assert(!cs->cip); + cs->eob = cs->s; + TRACE(("popping\n")); + goto POP_BACKUP; + } else { /* was and still going forward */ + TRACE(("forwards\n")); + if ((ru & (RULE_POSITION|WEIGHT_MASK)) > RULE_POSITION) { + assert(ru & WEIGHT_MASK); + cs->ru_pushed = ru; + cs->weight = cs->position; +#ifdef __UCLIBC_MJN3_ONLY__ +#warning devel code +#endif + cs->position = 0; /* reset to reduce size for strcoll? */ + cs->s += n; + cs->weightidx = RANGE_IDX; + goto PROCESS_WEIGHT; + } + } + } else { /* popping backwards stack */ + TRACE(("popping (continued)\n")); + if (!*cs->bp) { + cs->s = cs->eob; + } + cs->s -= n; + } + + cs->s += n; + POSITION_SKIP: + cs->weightidx = ru & WEIGHT_MASK; + cs->rule = ru & RULE_MASK; + } + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning for pending we only want the weight... _not_ the rule +#endif + if (!cs->weightidx) { /* ignore */ + continue; + } + + PROCESS_WEIGHT: + assert(cs->weightidx); + + + if (((unsigned int)(cs->weightidx - UI_IDX)) <= (INVAL_IDX-UI_IDX)) { + if (cs->weightidx == UI_IDX) { + cs->weight = cs->ui_weight; + } + return; + } + + assert(cs->weightidx != WEIGHT_MASK); + if (cs->weightidx == DITTO_IDX) { /* want the weight of the current collating item */ + TRACE(("doing ditto\n")); + w = CUR_COLLATE->index2weight[cs->colitem -1]; + } else if (cs->weightidx <= CUR_COLLATE->max_col_index) { /* normal */ + TRACE(("doing normal\n")); + w = CUR_COLLATE->index2weight[cs->weightidx -1]; + } else { /* a string */ + TRACE(("doing string\n")); + assert(!(cs->weightidx & RULE_MASK)); + /* note: iso14561 allows null string here */ + p = CUR_COLLATE->weightstr + (cs->weightidx - (CUR_COLLATE->max_col_index + 2)); + if (*p & WEIGHT_MASK) { + r = 0; + do { + assert(r < MAX_PENDING); + cs->ci_pending[r++] = *p++; + } while (*p & WEIGHT_MASK); + cs->cip = cs->ci_pending; + } + continue; + } + + cs->weight = w; + return; + } while (1); +} + +libc_hidden_proto(__XL_NPP(wcscoll)) +int __XL_NPP(wcscoll) (const Wchar *s0, const Wchar *s1 __LOCALE_PARAM ) +{ + col_state_t ws[2]; + int pass; + + if (!CUR_COLLATE->num_weights) { /* C locale */ +#ifdef WANT_WIDE + return wcscmp(s0, s1); +#else + return strcmp(s0, s1); +#endif + } + + pass = 0; + do { /* loop through the weights levels */ + init_col_state(ws, s0); + init_col_state(ws+1, s1); + do { /* loop through the strings */ + /* for each string, get the next weight */ + next_weight(ws, pass __LOCALE_ARG ); + next_weight(ws+1, pass __LOCALE_ARG ); + TRACE(("w0=%lu w1=%lu\n", + (unsigned long) ws[0].weight, + (unsigned long) ws[1].weight)); + + if (ws[0].weight != ws[1].weight) { + return ws[0].weight - ws[1].weight; + } + } while (ws[0].weight); + } while (++pass < CUR_COLLATE->num_weights); + + return 0; +} +libc_hidden_def(__XL_NPP(wcscoll)) + +#ifdef WANT_WIDE + +extern size_t __wcslcpy(wchar_t *__restrict dst, + const wchar_t *__restrict src, size_t n); + +libc_hidden_proto(__XL_NPP(wcsxfrm)) +size_t __XL_NPP(wcsxfrm)(wchar_t *__restrict ws1, const wchar_t *__restrict ws2, + size_t n __LOCALE_PARAM ) +{ + col_state_t cs; + size_t count; + int pass; + + if (!CUR_COLLATE->num_weights) { /* C locale */ + return __wcslcpy(ws1, ws2, n); + } + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning handle empty string as a special case +#endif + + count = pass = 0; + do { /* loop through the weights levels */ + init_col_state(&cs, ws2); + do { /* loop through the string */ + next_weight(&cs, pass __LOCALE_ARG ); + TRACE(("weight=%lu (%#lx)\n", (unsigned long) cs.weight, (unsigned long) cs.weight)); + if (count < n) { + ws1[count] = cs.weight +1; + } + ++count; + TRACE(("--------------------------------------------\n")); + } while (cs.weight); + if (count <= n) { /* overwrite the trailing 0 end-of-pass marker */ + ws1[count-1] = 1; + } + TRACE(("-------------------- pass %d --------------------\n", pass)); + } while (++pass < CUR_COLLATE->num_weights); + if (count <= n) { /* oops... change it back */ + ws1[count-1] = 0; + } + return count-1; +} +libc_hidden_def(__XL_NPP(wcsxfrm)) + +#else /* WANT_WIDE */ + +static const unsigned long bound[] = { + 1UL << 7, + 1UL << 11, + 1UL << 16, + 1UL << 21, + 1UL << 26, +}; + +static unsigned char first[] = { + 0x0, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc +}; + +/* Use an extension of UTF-8 to store a 32 bit val in max 6 bytes. */ + +static size_t store(unsigned char *s, size_t count, size_t n, __uwchar_t weight) +{ + int i, r; + + i = 0; + do { + if (weight < bound[i]) { + break; + } + } while (++i < sizeof(bound)/sizeof(bound[0])); + + r = i+1; + if (i + count < n) { + s += count; + s[0] = first[i]; + while (i) { + s[i] = 0x80 | (weight & 0x3f); + weight >>= 6; + --i; + } + s[0] |= weight; + } + + return r; +} + +libc_hidden_proto(__XL_NPP(strxfrm)) +size_t __XL_NPP(strxfrm)(char *__restrict ws1, const char *__restrict ws2, size_t n + __LOCALE_PARAM ) +{ + col_state_t cs; + size_t count, inc; + int pass; + + if (!CUR_COLLATE->num_weights) { /* C locale */ + return strlcpy(ws1, ws2, n); + } + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning handle empty string as a special case +#endif + + inc = count = pass = 0; + do { /* loop through the weights levels */ + init_col_state(&cs, ws2); + do { /* loop through the string */ + next_weight(&cs, pass __LOCALE_ARG ); + TRACE(("weight=%lu (%#lx)\n", (unsigned long) cs.weight, (unsigned long) cs.weight)); + inc = store((unsigned char *)ws1, count, n, cs.weight + 1); + count += inc; + TRACE(("--------------------------------------------\n")); + } while (cs.weight); + /* overwrite the trailing 0 end-of-pass marker */ + assert(inc == 1); + if (count <= n) { + ws1[count-1] = 1; + } + TRACE(("-------------------- pass %d --------------------\n", pass)); + } while (++pass < CUR_COLLATE->num_weights); + if (count <= n) { /* oops... change it back */ + ws1[count-1] = 0; + } + return count-1; +} +libc_hidden_def(__XL_NPP(strxfrm)) + +#endif /* WANT_WIDE */ + +#endif /* defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) */ + +#endif /* defined(L_strxfrm) || defined(L_strxfrm_l) || defined(L_wcsxfrm) || defined(L_wcsxfrm_l) */ + +#endif /* __UCLIBC_HAS_LOCALE__ */ +/**********************************************************************/ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/_string.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/_string.h new file mode 100644 index 00000000..67f17b1f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/_string.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#ifndef __STRING_H +#define __STRING_H + +#include +#include +#include +#include + +#ifdef WANT_WIDE +# include +# include +# include +# define Wvoid wchar_t +# define Wchar wchar_t +# define Wuchar __uwchar_t +# define Wint wchar_t +#else +# define Wvoid void +# define Wchar char +typedef unsigned char __string_uchar_t; +# define Wuchar __string_uchar_t +# define Wint int +#endif + +#endif /* __STRING_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/_string_syserrmsgs.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/_string_syserrmsgs.c new file mode 100644 index 00000000..893af5cc --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/_string_syserrmsgs.c @@ -0,0 +1,147 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +#ifdef __UCLIBC_HAS_ERRNO_MESSAGES__ + +attribute_hidden +const char _string_syserrmsgs[] = { + /* 0: 0, 8 */ "Success\0" + /* 1: 8, 24 */ "Operation not permitted\0" + /* 2: 32, 26 */ "No such file or directory\0" + /* 3: 58, 16 */ "No such process\0" + /* 4: 74, 24 */ "Interrupted system call\0" + /* 5: 98, 19 */ "Input/output error\0" + /* 6: 117, 26 */ "No such device or address\0" + /* 7: 143, 23 */ "Argument list too long\0" + /* 8: 166, 18 */ "Exec format error\0" + /* 9: 184, 20 */ "Bad file descriptor\0" + /* 10: 204, 19 */ "No child processes\0" + /* 11: 223, 33 */ "Resource temporarily unavailable\0" + /* 12: 256, 23 */ "Cannot allocate memory\0" + /* 13: 279, 18 */ "Permission denied\0" + /* 14: 297, 12 */ "Bad address\0" + /* 15: 309, 22 */ "Block device required\0" + /* 16: 331, 24 */ "Device or resource busy\0" + /* 17: 355, 12 */ "File exists\0" + /* 18: 367, 26 */ "Invalid cross-device link\0" + /* 19: 393, 15 */ "No such device\0" + /* 20: 408, 16 */ "Not a directory\0" + /* 21: 424, 15 */ "Is a directory\0" + /* 22: 439, 17 */ "Invalid argument\0" + /* 23: 456, 30 */ "Too many open files in system\0" + /* 24: 486, 20 */ "Too many open files\0" + /* 25: 506, 31 */ "Inappropriate ioctl for device\0" + /* 26: 537, 15 */ "Text file busy\0" + /* 27: 552, 15 */ "File too large\0" + /* 28: 567, 24 */ "No space left on device\0" + /* 29: 591, 13 */ "Illegal seek\0" + /* 30: 604, 22 */ "Read-only file system\0" + /* 31: 626, 15 */ "Too many links\0" + /* 32: 641, 12 */ "Broken pipe\0" + /* 33: 653, 33 */ "Numerical argument out of domain\0" + /* 34: 686, 30 */ "Numerical result out of range\0" + /* 35: 716, 26 */ "Resource deadlock avoided\0" + /* 36: 742, 19 */ "File name too long\0" + /* 37: 761, 19 */ "No locks available\0" + /* 38: 780, 25 */ "Function not implemented\0" + /* 39: 805, 20 */ "Directory not empty\0" + /* 40: 825, 34 */ "Too many levels of symbolic links\0" + /* 41: 859, 1 */ "\0" + /* 42: 860, 27 */ "No message of desired type\0" + /* 43: 887, 19 */ "Identifier removed\0" + /* 44: 906, 28 */ "Channel number out of range\0" + /* 45: 934, 25 */ "Level 2 not synchronized\0" + /* 46: 959, 15 */ "Level 3 halted\0" + /* 47: 974, 14 */ "Level 3 reset\0" + /* 48: 988, 25 */ "Link number out of range\0" + /* 49: 1013, 29 */ "Protocol driver not attached\0" + /* 50: 1042, 27 */ "No CSI structure available\0" + /* 51: 1069, 15 */ "Level 2 halted\0" + /* 52: 1084, 17 */ "Invalid exchange\0" + /* 53: 1101, 27 */ "Invalid request descriptor\0" + /* 54: 1128, 14 */ "Exchange full\0" + /* 55: 1142, 9 */ "No anode\0" + /* 56: 1151, 21 */ "Invalid request code\0" + /* 57: 1172, 13 */ "Invalid slot\0" + /* 58: 1185, 1 */ "\0" + /* 59: 1186, 21 */ "Bad font file format\0" + /* 60: 1207, 20 */ "Device not a stream\0" + /* 61: 1227, 18 */ "No data available\0" + /* 62: 1245, 14 */ "Timer expired\0" + /* 63: 1259, 25 */ "Out of streams resources\0" + /* 64: 1284, 30 */ "Machine is not on the network\0" + /* 65: 1314, 22 */ "Package not installed\0" + /* 66: 1336, 17 */ "Object is remote\0" + /* 67: 1353, 22 */ "Link has been severed\0" + /* 68: 1375, 16 */ "Advertise error\0" + /* 69: 1391, 14 */ "Srmount error\0" + /* 70: 1405, 28 */ "Communication error on send\0" + /* 71: 1433, 15 */ "Protocol error\0" + /* 72: 1448, 19 */ "Multihop attempted\0" + /* 73: 1467, 19 */ "RFS specific error\0" + /* 74: 1486, 12 */ "Bad message\0" + /* 75: 1498, 38 */ "Value too large for defined data type\0" + /* 76: 1536, 27 */ "Name not unique on network\0" + /* 77: 1563, 29 */ "File descriptor in bad state\0" + /* 78: 1592, 23 */ "Remote address changed\0" + /* 79: 1615, 39 */ "Can not access a needed shared library\0" + /* 80: 1654, 37 */ "Accessing a corrupted shared library\0" + /* 81: 1691, 32 */ ".lib section in a.out corrupted\0" + /* 82: 1723, 48 */ "Attempting to link in too many shared libraries\0" + /* 83: 1771, 38 */ "Cannot exec a shared library directly\0" + /* 84: 1809, 50 */ "Invalid or incomplete multibyte or wide character\0" + /* 85: 1859, 44 */ "Interrupted system call should be restarted\0" + /* 86: 1903, 19 */ "Streams pipe error\0" + /* 87: 1922, 15 */ "Too many users\0" + /* 88: 1937, 31 */ "Socket operation on non-socket\0" + /* 89: 1968, 29 */ "Destination address required\0" + /* 90: 1997, 17 */ "Message too long\0" + /* 91: 2014, 31 */ "Protocol wrong type for socket\0" + /* 92: 2045, 23 */ "Protocol not available\0" + /* 93: 2068, 23 */ "Protocol not supported\0" + /* 94: 2091, 26 */ "Socket type not supported\0" + /* 95: 2117, 24 */ "Operation not supported\0" + /* 96: 2141, 30 */ "Protocol family not supported\0" + /* 97: 2171, 41 */ "Address family not supported by protocol\0" + /* 98: 2212, 23 */ "Address already in use\0" + /* 99: 2235, 32 */ "Cannot assign requested address\0" + /* 100: 2267, 16 */ "Network is down\0" + /* 101: 2283, 23 */ "Network is unreachable\0" + /* 102: 2306, 36 */ "Network dropped connection on reset\0" + /* 103: 2342, 33 */ "Software caused connection abort\0" + /* 104: 2375, 25 */ "Connection reset by peer\0" + /* 105: 2400, 26 */ "No buffer space available\0" + /* 106: 2426, 40 */ "Transport endpoint is already connected\0" + /* 107: 2466, 36 */ "Transport endpoint is not connected\0" + /* 108: 2502, 46 */ "Cannot send after transport endpoint shutdown\0" + /* 109: 2548, 35 */ "Too many references: cannot splice\0" + /* 110: 2583, 21 */ "Connection timed out\0" + /* 111: 2604, 19 */ "Connection refused\0" + /* 112: 2623, 13 */ "Host is down\0" + /* 113: 2636, 17 */ "No route to host\0" + /* 114: 2653, 30 */ "Operation already in progress\0" + /* 115: 2683, 26 */ "Operation now in progress\0" + /* 116: 2709, 22 */ "Stale NFS file handle\0" + /* 117: 2731, 25 */ "Structure needs cleaning\0" + /* 118: 2756, 28 */ "Not a XENIX named type file\0" + /* 119: 2784, 30 */ "No XENIX semaphores available\0" + /* 120: 2814, 21 */ "Is a named type file\0" + /* 121: 2835, 17 */ "Remote I/O error\0" + /* 122: 2852, 20 */ "Disk quota exceeded\0" + /* 123: 2872, 16 */ "No medium found\0" + /* 124: 2888, 18 */ "Wrong medium type" +#if defined(__mips__) || defined(__sparc__) + "\0" + /* 125: 2906, 28 */ "File locking deadlock error" +#endif + /* Note: for mips we are ignoring ECANCELED since glibc doesn't have a + * corresponsding message.*/ +}; + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/_string_syssigmsgs.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/_string_syssigmsgs.c new file mode 100644 index 00000000..26c0948f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/_string_syssigmsgs.c @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +#ifdef __UCLIBC_HAS_SIGNUM_MESSAGES__ + +attribute_hidden +const char _string_syssigmsgs[] = { + /* 0: 0, 1 */ "\0" + /* 1: 1, 7 */ "Hangup\0" + /* 2: 8, 10 */ "Interrupt\0" + /* 3: 18, 5 */ "Quit\0" + /* 4: 23, 20 */ "Illegal instruction\0" + /* 5: 43, 22 */ "Trace/breakpoint trap\0" + /* 6: 65, 8 */ "Aborted\0" + /* 7: 73, 10 */ "Bus error\0" + /* 8: 83, 25 */ "Floating point exception\0" + /* 9: 108, 7 */ "Killed\0" + /* 10: 115, 22 */ "User defined signal 1\0" + /* 11: 137, 19 */ "Segmentation fault\0" + /* 12: 156, 22 */ "User defined signal 2\0" + /* 13: 178, 12 */ "Broken pipe\0" + /* 14: 190, 12 */ "Alarm clock\0" + /* 15: 202, 11 */ "Terminated\0" + /* 16: 213, 12 */ "Stack fault\0" + /* 17: 225, 13 */ "Child exited\0" + /* 18: 238, 10 */ "Continued\0" + /* 19: 248, 17 */ "Stopped (signal)\0" + /* 20: 265, 8 */ "Stopped\0" + /* 21: 273, 20 */ "Stopped (tty input)\0" + /* 22: 293, 21 */ "Stopped (tty output)\0" + /* 23: 314, 21 */ "Urgent I/O condition\0" + /* 24: 335, 24 */ "CPU time limit exceeded\0" + /* 25: 359, 25 */ "File size limit exceeded\0" + /* 26: 384, 22 */ "Virtual timer expired\0" + /* 27: 406, 24 */ "Profiling timer expired\0" + /* 28: 430, 15 */ "Window changed\0" + /* 29: 445, 13 */ "I/O possible\0" + /* 30: 458, 14 */ "Power failure\0" + /* 31: 472, 16 */ "Bad system call" +#if defined SIGEMT + /* 32: 488, 9 */ "\0EMT trap" +#endif +}; + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/_syserrmsg.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/_syserrmsg.h new file mode 100644 index 00000000..8bd742e7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/_syserrmsg.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#ifndef __SYSERRMSG_H +#define __SYSERRMSG_H 1 + +#include + +/**********************************************************************/ +/* NOTE: If we ever do internationalized syserr messages, this will + * have to be changed! */ + +#if defined(__mips__) || defined(__sparc__) +/* sparce and mips have an extra error entry, as EDEADLK and EDEADLOCK have + * different meanings on those platforms. */ +# define _SYS_NERR 126 +#else +# define _SYS_NERR 125 +#endif + +#ifdef __UCLIBC_HAS_ERRNO_MESSAGES__ +# define _SYS_ERRMSG_MAXLEN 50 +#else /* __UCLIBC_HAS_ERRNO_MESSAGES__ */ +# define _SYS_ERRMSG_MAXLEN 0 +#endif /* __UCLIBC_HAS_ERRNO_MESSAGES__ */ + +#if _SYS_ERRMSG_MAXLEN < __UIM_BUFLEN_INT + 14 +# define _STRERROR_BUFSIZE (__UIM_BUFLEN_INT + 14) +#else +# define _STRERROR_BUFSIZE _SYS_ERRMSG_MAXLEN +#endif + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/arm/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/arm/Makefile new file mode 100644 index 00000000..0a95346f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/arm/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir:=../../../ +top_builddir:=../../../ +all: objs +include $(top_builddir)Rules.mak +include ../Makefile.in +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/arm/_memcpy.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/arm/_memcpy.S new file mode 100644 index 00000000..b26080d0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/arm/_memcpy.S @@ -0,0 +1,747 @@ +/*- + * Copyright (c) 1997 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Neil A. Carson and Mark Brinicombe + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * Adapted for uClibc from NetBSD _memcpy.S,v 1.6 2003/10/09 + * by Erik Andersen + */ + +#include +#include +#include + +#if !defined(THUMB1_ONLY) +/* + * This is one fun bit of code ... + * Some easy listening music is suggested while trying to understand this + * code e.g. Iron Maiden + * + * For anyone attempting to understand it : + * + * The core code is implemented here with simple stubs for memcpy() + * memmove() and bcopy(). + * + * All local labels are prefixed with Lmemcpy_ + * Following the prefix a label starting f is used in the forward copy code + * while a label using b is used in the backwards copy code + * The source and destination addresses determine whether a forward or + * backward copy is performed. + * Separate bits of code are used to deal with the following situations + * for both the forward and backwards copy. + * unaligned source address + * unaligned destination address + * Separate copy routines are used to produce an optimised result for each + * of these cases. + * The copy code will use LDM/STM instructions to copy up to 32 bytes at + * a time where possible. + * + * Note: r12 (aka ip) can be trashed during the function along with + * r0-r3 although r0-r2 have defined uses i.e. dest, src, len throughout. + * Additional registers are preserved prior to use i.e. r4, r5 & lr + * The return value in r0 must be the destination address. + * + * Apologies for the state of the comments ;-) + */ + +.text +.global _memcpy +.hidden _memcpy +.type _memcpy,%function +.align 4 + +/* XXX: The Thumb-2 conditionals can be removed if/when we require an + assembler that supports unified syntax. */ +.macro copy regs +#if defined(__thumb2__) + ittt ge + ldmiage r1!, \regs + stmiage r0!, \regs +#else + ldmgeia r1!, \regs + stmgeia r0!, \regs +#endif +.endm + +.macro copydb regs +#if defined(__thumb2__) + ittt ge + ldmdbge r1!, \regs + stmdbge r0!, \regs +#else + ldmgedb r1!, \regs + stmgedb r0!, \regs +#endif +.endm + +_memcpy: + /* Determine copy direction */ + cmp r1, r0 + bcc .Lmemcpy_backwards + + IT(t, eq) /* Quick abort for src=dst */ +#if defined(__USE_BX__) + bxeq lr +#else + moveq pc, lr +#endif + stmdb sp!, {r0, lr} /* memcpy() returns dest addr */ + subs r2, r2, #4 + blt .Lmemcpy_fl4 /* less than 4 bytes */ + ands r12, r0, #3 + bne .Lmemcpy_fdestul /* oh unaligned destination addr */ + ands r12, r1, #3 + bne .Lmemcpy_fsrcul /* oh unaligned source addr */ + +.Lmemcpy_ft8: + /* We have aligned source and destination */ + subs r2, r2, #8 + blt .Lmemcpy_fl12 /* less than 12 bytes (4 from above) */ + subs r2, r2, #0x14 + blt .Lmemcpy_fl32 /* less than 32 bytes (12 from above) */ + str r4, [sp, #-4]! /* borrow r4 */ + + /* blat 32 bytes at a time */ + /* XXX for really big copies perhaps we should use more registers */ +.Lmemcpy_floop32: + ldmia r1!, {r3, r4, r12, lr} + stmia r0!, {r3, r4, r12, lr} + ldmia r1!, {r3, r4, r12, lr} + stmia r0!, {r3, r4, r12, lr} + subs r2, r2, #0x20 + bge .Lmemcpy_floop32 + + cmn r2, #0x10 + /* blat a remaining 16 bytes */ + copy "{r3, r4, r12, lr}" + subge r2, r2, #0x10 + ldr r4, [sp], #4 /* restore r4 */ + +.Lmemcpy_fl32: + adds r2, r2, #0x14 + + /* blat 12 bytes at a time */ +.Lmemcpy_floop12: + copy "{r3, r12, lr}" +#if defined(__thumb2__) + subsge r2, r2, #0x0c +#else + subges r2, r2, #0x0c +#endif + bge .Lmemcpy_floop12 + +.Lmemcpy_fl12: + adds r2, r2, #8 + blt .Lmemcpy_fl4 + + subs r2, r2, #4 + IT(tt, lt) + ldrlt r3, [r1], #4 + strlt r3, [r0], #4 + copy "{r3, r12}" + subge r2, r2, #4 + +.Lmemcpy_fl4: + /* less than 4 bytes to go */ + adds r2, r2, #4 +#if defined(__thumb2__) + it eq + popeq {r0, pc} /* done */ +#elif defined(__ARM_ARCH_4T__) + ldmeqia sp!, {r0, r3} /* done */ + bxeq r3 +#else + ldmeqia sp!, {r0, pc} /* done */ +#endif + + /* copy the crud byte at a time */ + cmp r2, #2 + ldrb r3, [r1], #1 + strb r3, [r0], #1 +#if defined(__thumb2__) + itt ge + ldrbge r3, [r1], #1 + strbge r3, [r0], #1 + itt gt + ldrbgt r3, [r1], #1 + strbgt r3, [r0], #1 +#else + ldrgeb r3, [r1], #1 + strgeb r3, [r0], #1 + ldrgtb r3, [r1], #1 + strgtb r3, [r0], #1 +#endif +#if defined(__ARM_ARCH_4T__) + ldmia sp!, {r0, r3} + bx r3 +#else + ldmia sp!, {r0, pc} +#endif + + /* erg - unaligned destination */ +.Lmemcpy_fdestul: + rsb r12, r12, #4 + cmp r12, #2 + + /* align destination with byte copies */ + ldrb r3, [r1], #1 + strb r3, [r0], #1 +#if defined(__thumb2__) + itt ge + ldrbge r3, [r1], #1 + strbge r3, [r0], #1 + itt gt + ldrbgt r3, [r1], #1 + strbgt r3, [r0], #1 +#else + ldrgeb r3, [r1], #1 + strgeb r3, [r0], #1 + ldrgtb r3, [r1], #1 + strgtb r3, [r0], #1 +#endif + subs r2, r2, r12 + blt .Lmemcpy_fl4 /* less the 4 bytes */ + + ands r12, r1, #3 + beq .Lmemcpy_ft8 /* we have an aligned source */ + + /* erg - unaligned source */ + /* This is where it gets nasty ... */ +.Lmemcpy_fsrcul: + bic r1, r1, #3 + ldr lr, [r1], #4 + cmp r12, #2 + bgt .Lmemcpy_fsrcul3 + beq .Lmemcpy_fsrcul2 + cmp r2, #0x0c + blt .Lmemcpy_fsrcul1loop4 + sub r2, r2, #0x0c + stmdb sp!, {r4, r5} + +.Lmemcpy_fsrcul1loop16: +#if __BYTE_ORDER == __BIG_ENDIAN + mov r3, lr, lsl #8 + ldmia r1!, {r4, r5, r12, lr} + orr r3, r3, r4, lsr #24 + mov r4, r4, lsl #8 + orr r4, r4, r5, lsr #24 + mov r5, r5, lsl #8 + orr r5, r5, r12, lsr #24 + mov r12, r12, lsl #8 + orr r12, r12, lr, lsr #24 +#else + mov r3, lr, lsr #8 + ldmia r1!, {r4, r5, r12, lr} + orr r3, r3, r4, lsl #24 + mov r4, r4, lsr #8 + orr r4, r4, r5, lsl #24 + mov r5, r5, lsr #8 + orr r5, r5, r12, lsl #24 + mov r12, r12, lsr #8 + orr r12, r12, lr, lsl #24 +#endif + stmia r0!, {r3-r5, r12} + subs r2, r2, #0x10 + bge .Lmemcpy_fsrcul1loop16 + ldmia sp!, {r4, r5} + adds r2, r2, #0x0c + blt .Lmemcpy_fsrcul1l4 + +.Lmemcpy_fsrcul1loop4: +#if __BYTE_ORDER == __BIG_ENDIAN + mov r12, lr, lsl #8 + ldr lr, [r1], #4 + orr r12, r12, lr, lsr #24 +#else + mov r12, lr, lsr #8 + ldr lr, [r1], #4 + orr r12, r12, lr, lsl #24 +#endif + str r12, [r0], #4 + subs r2, r2, #4 + bge .Lmemcpy_fsrcul1loop4 + +.Lmemcpy_fsrcul1l4: + sub r1, r1, #3 + b .Lmemcpy_fl4 + +.Lmemcpy_fsrcul2: + cmp r2, #0x0c + blt .Lmemcpy_fsrcul2loop4 + sub r2, r2, #0x0c + stmdb sp!, {r4, r5} + +.Lmemcpy_fsrcul2loop16: +#if __BYTE_ORDER == __BIG_ENDIAN + mov r3, lr, lsl #16 + ldmia r1!, {r4, r5, r12, lr} + orr r3, r3, r4, lsr #16 + mov r4, r4, lsl #16 + orr r4, r4, r5, lsr #16 + mov r5, r5, lsl #16 + orr r5, r5, r12, lsr #16 + mov r12, r12, lsl #16 + orr r12, r12, lr, lsr #16 +#else + mov r3, lr, lsr #16 + ldmia r1!, {r4, r5, r12, lr} + orr r3, r3, r4, lsl #16 + mov r4, r4, lsr #16 + orr r4, r4, r5, lsl #16 + mov r5, r5, lsr #16 + orr r5, r5, r12, lsl #16 + mov r12, r12, lsr #16 + orr r12, r12, lr, lsl #16 +#endif + stmia r0!, {r3-r5, r12} + subs r2, r2, #0x10 + bge .Lmemcpy_fsrcul2loop16 + ldmia sp!, {r4, r5} + adds r2, r2, #0x0c + blt .Lmemcpy_fsrcul2l4 + +.Lmemcpy_fsrcul2loop4: +#if __BYTE_ORDER == __BIG_ENDIAN + mov r12, lr, lsl #16 + ldr lr, [r1], #4 + orr r12, r12, lr, lsr #16 +#else + mov r12, lr, lsr #16 + ldr lr, [r1], #4 + orr r12, r12, lr, lsl #16 +#endif + str r12, [r0], #4 + subs r2, r2, #4 + bge .Lmemcpy_fsrcul2loop4 + +.Lmemcpy_fsrcul2l4: + sub r1, r1, #2 + b .Lmemcpy_fl4 + +.Lmemcpy_fsrcul3: + cmp r2, #0x0c + blt .Lmemcpy_fsrcul3loop4 + sub r2, r2, #0x0c + stmdb sp!, {r4, r5} + +.Lmemcpy_fsrcul3loop16: +#if __BYTE_ORDER == __BIG_ENDIAN + mov r3, lr, lsl #24 + ldmia r1!, {r4, r5, r12, lr} + orr r3, r3, r4, lsr #8 + mov r4, r4, lsl #24 + orr r4, r4, r5, lsr #8 + mov r5, r5, lsl #24 + orr r5, r5, r12, lsr #8 + mov r12, r12, lsl #24 + orr r12, r12, lr, lsr #8 +#else + mov r3, lr, lsr #24 + ldmia r1!, {r4, r5, r12, lr} + orr r3, r3, r4, lsl #8 + mov r4, r4, lsr #24 + orr r4, r4, r5, lsl #8 + mov r5, r5, lsr #24 + orr r5, r5, r12, lsl #8 + mov r12, r12, lsr #24 + orr r12, r12, lr, lsl #8 +#endif + stmia r0!, {r3-r5, r12} + subs r2, r2, #0x10 + bge .Lmemcpy_fsrcul3loop16 + ldmia sp!, {r4, r5} + adds r2, r2, #0x0c + blt .Lmemcpy_fsrcul3l4 + +.Lmemcpy_fsrcul3loop4: +#if __BYTE_ORDER == __BIG_ENDIAN + mov r12, lr, lsl #24 + ldr lr, [r1], #4 + orr r12, r12, lr, lsr #8 +#else + mov r12, lr, lsr #24 + ldr lr, [r1], #4 + orr r12, r12, lr, lsl #8 +#endif + str r12, [r0], #4 + subs r2, r2, #4 + bge .Lmemcpy_fsrcul3loop4 + +.Lmemcpy_fsrcul3l4: + sub r1, r1, #1 + b .Lmemcpy_fl4 + +.Lmemcpy_backwards: + add r1, r1, r2 + add r0, r0, r2 + subs r2, r2, #4 + blt .Lmemcpy_bl4 /* less than 4 bytes */ + ands r12, r0, #3 + bne .Lmemcpy_bdestul /* oh unaligned destination addr */ + ands r12, r1, #3 + bne .Lmemcpy_bsrcul /* oh unaligned source addr */ + +.Lmemcpy_bt8: + /* We have aligned source and destination */ + subs r2, r2, #8 + blt .Lmemcpy_bl12 /* less than 12 bytes (4 from above) */ + stmdb sp!, {r4, lr} + subs r2, r2, #0x14 /* less than 32 bytes (12 from above) */ + blt .Lmemcpy_bl32 + + /* blat 32 bytes at a time */ + /* XXX for really big copies perhaps we should use more registers */ +.Lmemcpy_bloop32: + ldmdb r1!, {r3, r4, r12, lr} + stmdb r0!, {r3, r4, r12, lr} + ldmdb r1!, {r3, r4, r12, lr} + stmdb r0!, {r3, r4, r12, lr} + subs r2, r2, #0x20 + bge .Lmemcpy_bloop32 + +.Lmemcpy_bl32: + cmn r2, #0x10 + /* blat a remaining 16 bytes */ + copydb "{r3, r4, r12, lr}" + subge r2, r2, #0x10 + adds r2, r2, #0x14 + /* blat a remaining 12 bytes */ + copydb "{r3, r12, lr}" + subge r2, r2, #0x0c + ldmia sp!, {r4, lr} + +.Lmemcpy_bl12: + adds r2, r2, #8 + blt .Lmemcpy_bl4 + subs r2, r2, #4 + IT(tt, lt) + ldrlt r3, [r1, #-4]! + strlt r3, [r0, #-4]! + copydb "{r3, r12}" + subge r2, r2, #4 + +.Lmemcpy_bl4: + /* less than 4 bytes to go */ + adds r2, r2, #4 + IT(t, eq) +#if defined(__USE_BX__) + bxeq lr +#else + moveq pc, lr /* done */ +#endif + /* copy the crud byte at a time */ + cmp r2, #2 + ldrb r3, [r1, #-1]! + strb r3, [r0, #-1]! +#ifdef __thumb2__ + itt ge + ldrbge r3, [r1, #-1]! + strbge r3, [r0, #-1]! + itt gt + ldrbgt r3, [r1, #-1]! + strbgt r3, [r0, #-1]! +#else + ldrgeb r3, [r1, #-1]! + strgeb r3, [r0, #-1]! + ldrgtb r3, [r1, #-1]! + strgtb r3, [r0, #-1]! +#endif +#if defined(__USE_BX__) + bx lr +#else + mov pc, lr +#endif + /* erg - unaligned destination */ +.Lmemcpy_bdestul: + cmp r12, #2 + + /* align destination with byte copies */ + ldrb r3, [r1, #-1]! + strb r3, [r0, #-1]! +#ifdef __thumb2__ + itt ge + ldrbge r3, [r1, #-1]! + strbge r3, [r0, #-1]! + itt gt + ldrbgt r3, [r1, #-1]! + strbgt r3, [r0, #-1]! +#else + ldrgeb r3, [r1, #-1]! + strgeb r3, [r0, #-1]! + ldrgtb r3, [r1, #-1]! + strgtb r3, [r0, #-1]! +#endif + subs r2, r2, r12 + blt .Lmemcpy_bl4 /* less than 4 bytes to go */ + ands r12, r1, #3 + beq .Lmemcpy_bt8 /* we have an aligned source */ + + /* erg - unaligned source */ + /* This is where it gets nasty ... */ +.Lmemcpy_bsrcul: + bic r1, r1, #3 + ldr r3, [r1, #0] + cmp r12, #2 + blt .Lmemcpy_bsrcul1 + beq .Lmemcpy_bsrcul2 + cmp r2, #0x0c + blt .Lmemcpy_bsrcul3loop4 + sub r2, r2, #0x0c + stmdb sp!, {r4, r5, lr} + +.Lmemcpy_bsrcul3loop16: +#if __BYTE_ORDER == __BIG_ENDIAN + mov lr, r3, lsr #8 + ldmdb r1!, {r3-r5, r12} + orr lr, lr, r12, lsl #24 + mov r12, r12, lsr #8 + orr r12, r12, r5, lsl #24 + mov r5, r5, lsr #8 + orr r5, r5, r4, lsl #24 + mov r4, r4, lsr #8 + orr r4, r4, r3, lsl #24 +#else + mov lr, r3, lsl #8 + ldmdb r1!, {r3-r5, r12} + orr lr, lr, r12, lsr #24 + mov r12, r12, lsl #8 + orr r12, r12, r5, lsr #24 + mov r5, r5, lsl #8 + orr r5, r5, r4, lsr #24 + mov r4, r4, lsl #8 + orr r4, r4, r3, lsr #24 +#endif + stmdb r0!, {r4, r5, r12, lr} + subs r2, r2, #0x10 + bge .Lmemcpy_bsrcul3loop16 + ldmia sp!, {r4, r5, lr} + adds r2, r2, #0x0c + blt .Lmemcpy_bsrcul3l4 + +.Lmemcpy_bsrcul3loop4: +#if __BYTE_ORDER == __BIG_ENDIAN + mov r12, r3, lsr #8 + ldr r3, [r1, #-4]! + orr r12, r12, r3, lsl #24 +#else + mov r12, r3, lsl #8 + ldr r3, [r1, #-4]! + orr r12, r12, r3, lsr #24 +#endif + str r12, [r0, #-4]! + subs r2, r2, #4 + bge .Lmemcpy_bsrcul3loop4 + +.Lmemcpy_bsrcul3l4: + add r1, r1, #3 + b .Lmemcpy_bl4 + +.Lmemcpy_bsrcul2: + cmp r2, #0x0c + blt .Lmemcpy_bsrcul2loop4 + sub r2, r2, #0x0c + stmdb sp!, {r4, r5, lr} + +.Lmemcpy_bsrcul2loop16: +#if __BYTE_ORDER == __BIG_ENDIAN + mov lr, r3, lsr #16 + ldmdb r1!, {r3-r5, r12} + orr lr, lr, r12, lsl #16 + mov r12, r12, lsr #16 + orr r12, r12, r5, lsl #16 + mov r5, r5, lsr #16 + orr r5, r5, r4, lsl #16 + mov r4, r4, lsr #16 + orr r4, r4, r3, lsl #16 +#else + mov lr, r3, lsl #16 + ldmdb r1!, {r3-r5, r12} + orr lr, lr, r12, lsr #16 + mov r12, r12, lsl #16 + orr r12, r12, r5, lsr #16 + mov r5, r5, lsl #16 + orr r5, r5, r4, lsr #16 + mov r4, r4, lsl #16 + orr r4, r4, r3, lsr #16 +#endif + stmdb r0!, {r4, r5, r12, lr} + subs r2, r2, #0x10 + bge .Lmemcpy_bsrcul2loop16 + ldmia sp!, {r4, r5, lr} + adds r2, r2, #0x0c + blt .Lmemcpy_bsrcul2l4 + +.Lmemcpy_bsrcul2loop4: +#if __BYTE_ORDER == __BIG_ENDIAN + mov r12, r3, lsr #16 + ldr r3, [r1, #-4]! + orr r12, r12, r3, lsl #16 +#else + mov r12, r3, lsl #16 + ldr r3, [r1, #-4]! + orr r12, r12, r3, lsr #16 +#endif + str r12, [r0, #-4]! + subs r2, r2, #4 + bge .Lmemcpy_bsrcul2loop4 + +.Lmemcpy_bsrcul2l4: + add r1, r1, #2 + b .Lmemcpy_bl4 + +.Lmemcpy_bsrcul1: + cmp r2, #0x0c + blt .Lmemcpy_bsrcul1loop4 + sub r2, r2, #0x0c + stmdb sp!, {r4, r5, lr} + +.Lmemcpy_bsrcul1loop32: +#if __BYTE_ORDER == __BIG_ENDIAN + mov lr, r3, lsr #24 + ldmdb r1!, {r3-r5, r12} + orr lr, lr, r12, lsl #8 + mov r12, r12, lsr #24 + orr r12, r12, r5, lsl #8 + mov r5, r5, lsr #24 + orr r5, r5, r4, lsl #8 + mov r4, r4, lsr #24 + orr r4, r4, r3, lsl #8 +#else + mov lr, r3, lsl #24 + ldmdb r1!, {r3-r5, r12} + orr lr, lr, r12, lsr #8 + mov r12, r12, lsl #24 + orr r12, r12, r5, lsr #8 + mov r5, r5, lsl #24 + orr r5, r5, r4, lsr #8 + mov r4, r4, lsl #24 + orr r4, r4, r3, lsr #8 +#endif + stmdb r0!, {r4, r5, r12, lr} + subs r2, r2, #0x10 + bge .Lmemcpy_bsrcul1loop32 + ldmia sp!, {r4, r5, lr} + adds r2, r2, #0x0c + blt .Lmemcpy_bsrcul1l4 + +.Lmemcpy_bsrcul1loop4: +#if __BYTE_ORDER == __BIG_ENDIAN + mov r12, r3, lsr #24 + ldr r3, [r1, #-4]! + orr r12, r12, r3, lsl #8 +#else + mov r12, r3, lsl #24 + ldr r3, [r1, #-4]! + orr r12, r12, r3, lsr #8 +#endif + str r12, [r0, #-4]! + subs r2, r2, #4 + bge .Lmemcpy_bsrcul1loop4 + +.Lmemcpy_bsrcul1l4: + add r1, r1, #1 + b .Lmemcpy_bl4 + +#else /* THUMB1_ONLY */ + +/* This is a fairly dumb implementation for when we can't use the 32-bit code + above. */ +.text +.global _memcpy +.hidden _memcpy +.type _memcpy,%function +.align 4 +.thumb +_memcpy: + push {r0, r4} + cmp r2, #0 + beq .Lmemcpy_exit + @ See if we have overlapping regions, and need to reverse the + @ direction of the copy + cmp r0, r1 + bls .Lmemcpy_forwards + add r4, r1, r2 + cmp r0, r4 + bcc .Lmemcpy_backwards +.Lmemcpy_forwards: + /* Forwards. */ + mov r3, r0 + eor r3, r1 + mov r4, #3 + tst r3, r4 + bne .Lmemcpy_funaligned + cmp r2, #8 + bcc .Lmemcpy_funaligned +1: @ copy up to the first word boundary. + tst r0, r4 + beq 1f + ldrb r3, [r1] + add r1, r1, #1 + strb r3, [r0] + add r0, r0, #1 + sub r2, r2, #1 + b 1b +1: @ Copy aligned words + ldr r3, [r1] + add r1, r1, #4 + str r3, [r0] + add r0, r0, #4 + sub r2, r2, #4 + cmp r2, #4 + bcs 1b + cmp r2, #0 + beq .Lmemcpy_exit +.Lmemcpy_funaligned: +1: + ldrb r3, [r1] + add r1, r1, #1 + strb r3, [r0] + add r0, r0, #1 + sub r2, r2, #1 + bne 1b +.Lmemcpy_exit: + pop {r0, r4} + bx lr + +.Lmemcpy_backwards: + add r0, r0, r2 + add r1, r1, r2 +1: + sub r0, r0, #1 + sub r1, r1, #1 + ldrb r3, [r1] + strb r3, [r0] + sub r2, r2, #1 + bne 1b + b .Lmemcpy_exit +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/arm/bcopy.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/arm/bcopy.S new file mode 100644 index 00000000..2d6e90d1 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/arm/bcopy.S @@ -0,0 +1,72 @@ +/*- + * Copyright (c) 1997 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Neil A. Carson and Mark Brinicombe + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * Adapted for uClibc from NetBSD bcopy.S,v 1.2 1997/10/09 + * by Erik Andersen + */ + +/* bcopy = memcpy/memmove with arguments reversed. */ + +#include +#include + +#ifdef __UCLIBC_SUSV3_LEGACY__ + +.text +.global bcopy +.type bcopy,%function +.align 4 + +#if defined(__thumb__) && !defined(__thumb2__) +.thumb_func +bcopy: + push {r2, lr} + mov ip, r0 + mov r0, r1 + mov r1, ip + bl _memcpy + POP_RET +#else +bcopy: + /* switch the source and destination registers */ + eor r0, r1, r0 + eor r1, r0, r1 + eor r0, r1, r0 + b _memcpy /* (PLT) */ +#endif + +.size bcopy,.-bcopy + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/arm/bzero.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/arm/bzero.S new file mode 100644 index 00000000..e576a12e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/arm/bzero.S @@ -0,0 +1,68 @@ +/*- + * Copyright (c) 1997 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Neil A. Carson and Mark Brinicombe + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * Adapted for uClibc from NetBSD bzero.S,v 1.2 1997/10/09 + * by Erik Andersen + */ + +#include +#include + +#ifdef __UCLIBC_SUSV3_LEGACY__ + +.text +.global bzero +.type bzero,%function +.align 4 + +#if defined(__thumb__) && !defined(__thumb2__) +.thumb_func +bzero: + push {r2, lr} + mov r2, r1 + mov r1, #0 + bl HIDDEN_JUMPTARGET(memset) + POP_RET +#else + +bzero: + mov r2, r1 + mov r1, #0 + b HIDDEN_JUMPTARGET(memset) +#endif + +.size bzero,.-bzero + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/arm/memcmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/arm/memcmp.S new file mode 100644 index 00000000..65409f43 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/arm/memcmp.S @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2002 ARM Ltd + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the company may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY ARM LTD ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ARM LTD BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Adapted for uClibc from NetBSD memcmp.S, version 1.2 2003/04/05 + * by Erik Andersen + */ + +#include +#include + +.text +.global memcmp +.type memcmp,%function +.align 4 + +#if defined(THUMB1_ONLY) +.thumb_func +memcmp: + cmp r2, #0 + bne 1f + mov r0, #0 + bx lr +1: + push {r4} + add r4, r0, r2 +2: + ldrb r2, [r0] + add r0, r0, #1 + ldrb r3, [r1] + add r1, r1, #1 + cmp r4, r0 + beq 3f + cmp r2, r3 + beq 2b +3: + sub r0, r2, r3 + pop {r4} + bx lr +#else +memcmp: + /* if ((len - 1) < 0) return 0 */ + subs r2, r2, #1 + IT(tt, mi) + movmi r0, #0 +#if defined(__USE_BX__) + bxmi lr +#else + movmi pc, lr +#endif + /* ip == last src address to compare */ + add ip, r0, r2 +1: + ldrb r2, [r0], #1 + ldrb r3, [r1], #1 + cmp ip, r0 + IT(t, cs) + cmpcs r2, r3 + beq 1b + sub r0, r2, r3 +#if defined(__USE_BX__) + bx lr +#else + mov pc, lr +#endif +#endif + +.size memcmp,.-memcmp + +libc_hidden_def(memcmp) +#ifdef __UCLIBC_SUSV3_LEGACY__ +strong_alias(memcmp,bcmp) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/arm/memcpy.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/arm/memcpy.S new file mode 100644 index 00000000..d2013d21 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/arm/memcpy.S @@ -0,0 +1,61 @@ +/*- + * Copyright (c) 1997 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Neil A. Carson and Mark Brinicombe + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * Adapted for uClibc from NetBSD memcpy.S,v 1.3 2003/04/05 + * by Erik Andersen + */ + +#include +#include + +.text +.global memcpy +.type memcpy,%function +.align 4 + +#if defined(__thumb__) && !defined(__thumb2__) +.thumb_func +memcpy: + push {r0, lr} + bl _memcpy + POP_RET +#else +memcpy: + b _memcpy +#endif + +.size memcpy,.-memcpy + +libc_hidden_def(memcpy) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/arm/memmove.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/arm/memmove.S new file mode 100644 index 00000000..c11b98dd --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/arm/memmove.S @@ -0,0 +1,61 @@ +/*- + * Copyright (c) 1997 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Neil A. Carson and Mark Brinicombe + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * Adapted for uClibc from NetBSD memmove.S,v 1.3 2003/04/05 + * by Erik Andersen + */ + +#include +#include + +.text +.global memmove +.type memmove,%function +.align 4 + +#if defined(__thumb__) && !defined(__thumb2__) +.thumb_func +memmove: + push {r2, lr} + bl _memcpy + POP_RET +#else +memmove: + b _memcpy +#endif + +.size memmove,.-memmove + +libc_hidden_def(memmove) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/arm/memset.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/arm/memset.S new file mode 100644 index 00000000..66aa6039 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/arm/memset.S @@ -0,0 +1,144 @@ +/* Copyright (C) 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Philip Blundell + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +.text +.global memset +.type memset,%function +.align 4 + +#if defined(THUMB1_ONLY) +.thumb_func +memset: + mov ip, r0 + cmp r2, #8 @ at least 8 bytes to do? + bcc 2f + + lsl r3, r1, #8 + orr r1, r3 + lsl r3, r1, #16 + orr r1, r3 + + mov r3, #3 +1: @ Fill up to the first word boundary + tst r0, r3 + beq 1f + strb r1, [r0] + add r0, r0, #1 + sub r2, r2, #1 + b 1b +1: @ Fill aligned words + str r1, [r0] + add r0, r0, #4 + sub r2, r2, #4 + cmp r2, #4 + bcs 1b + +2: @ Fill the remaining bytes + cmp r2, #0 + beq 2f +1: + strb r1, [r0] + add r0, r0, #1 + sub r2, r2, #1 + bne 1b +2: + mov r0, ip + bx lr +#else +memset: + mov a4, a1 + cmp a3, $8 @ at least 8 bytes to do? + blt 2f + orr a2, a2, a2, lsl $8 + orr a2, a2, a2, lsl $16 +1: + tst a4, $3 @ aligned yet? +#if defined(__thumb2__) + itt ne + strbne a2, [a4], $1 + subne a3, a3, $1 +#else + strneb a2, [a4], $1 + subne a3, a3, $1 +#endif + bne 1b + mov ip, a2 +1: + cmp a3, $8 @ 8 bytes still to do? + blt 2f + stmia a4!, {a2, ip} + sub a3, a3, $8 + cmp a3, $8 @ 8 bytes still to do? + blt 2f + stmia a4!, {a2, ip} + sub a3, a3, $8 + cmp a3, $8 @ 8 bytes still to do? + blt 2f + stmia a4!, {a2, ip} + sub a3, a3, $8 + cmp a3, $8 @ 8 bytes still to do? +#if defined(__thumb2__) + itt ge + stmiage a4!, {a2, ip} + subge a3, a3, $8 +#else + stmgeia a4!, {a2, ip} + subge a3, a3, $8 +#endif + bge 1b +2: + movs a3, a3 @ anything left? + IT(t, eq) +#if defined(__USE_BX__) + bxeq lr +#else + moveq pc, lr @ nope +#endif +#if defined (__thumb2__) +1: + strb a2, [a4], #1 + subs a3, a3, #1 + bne 1b + bx lr +#else + rsb a3, a3, $7 + add pc, pc, a3, lsl $2 + mov r0, r0 + strb a2, [a4], $1 + strb a2, [a4], $1 + strb a2, [a4], $1 + strb a2, [a4], $1 + strb a2, [a4], $1 + strb a2, [a4], $1 + strb a2, [a4], $1 +#if defined(__USE_BX__) + bx lr +#else + mov pc, lr +#endif +#endif +#endif + +.size memset,.-memset + +libc_hidden_def(memset) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/arm/strcmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/arm/strcmp.S new file mode 100644 index 00000000..97363c1c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/arm/strcmp.S @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2002 ARM Ltd + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the company may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY ARM LTD ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ARM LTD BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Adapted for uClibc from NetBSD strcmp.S, version 1.3 2003/04/05 + * by Erik Andersen + */ + +#include +#include + +.text +.global strcmp +.type strcmp,%function +.align 4 + +#if defined(__thumb__) && !defined(__thumb2__) +.thumb_func +strcmp: +1: + ldrb r2, [r0] + add r0, r0, #1 + ldrb r3, [r1] + add r1, r1, #1 + cmp r2, #0 + beq 2f + cmp r2, r3 + beq 1b +2: + sub r0, r2, r3 + bx lr +#else +strcmp: +1: + ldrb r2, [r0], #1 + ldrb r3, [r1], #1 + cmp r2, #1 + IT(t, cs) + cmpcs r2, r3 + beq 1b + sub r0, r2, r3 +#if defined(__USE_BX__) + bx lr +#else + mov pc, lr +#endif +#endif + +.size strcmp,.-strcmp + +libc_hidden_def(strcmp) +#ifndef __UCLIBC_HAS_LOCALE__ +strong_alias(strcmp,strcoll) +libc_hidden_def(strcoll) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/arm/strlen.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/arm/strlen.S new file mode 100644 index 00000000..949e918f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/arm/strlen.S @@ -0,0 +1,111 @@ +/* Copyright (C) 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Code contributed by Matthew Wilcox + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + +/* size_t strlen(const char *S) + * entry: r0 -> string + * exit: r0 = len + */ + +.text +.global strlen +.type strlen,%function +.align 4 + +#if defined(THUMB1_ONLY) +/* A simple implementation for when the ARM implementation can't be used. */ +.thumb_func +strlen: + mov r2, #0 +1: + ldrb r1, [r0, r2] + add r2, r2, #1 + cmp r1, #0 + bne 1b + sub r0, r2, #1 + bx lr +#else +strlen: + bic r1, r0, $3 @ addr of word containing first byte + ldr r2, [r1], $4 @ get the first word + ands r3, r0, $3 @ how many bytes are duff? + rsb r0, r3, $0 @ get - that number into counter. + beq Laligned @ skip into main check routine if no + @ more +#if __BYTE_ORDER == __BIG_ENDIAN + orr r2, r2, $0xff000000 @ set this byte to non-zero + subs r3, r3, $1 @ any more to do? + IT(t, gt) + orrgt r2, r2, $0x00ff0000 @ if so, set this byte + subs r3, r3, $1 @ more? + IT(t, gt) + orrgt r2, r2, $0x0000ff00 @ then set. +#else + orr r2, r2, $0x000000ff @ set this byte to non-zero + subs r3, r3, $1 @ any more to do? + IT(t, gt) + orrgt r2, r2, $0x0000ff00 @ if so, set this byte + subs r3, r3, $1 @ more? + IT(t, gt) + orrgt r2, r2, $0x00ff0000 @ then set. +#endif +Laligned: @ here, we have a word in r2. Does it + tst r2, $0x000000ff @ contain any zeroes? + IT(tttt, ne) + tstne r2, $0x0000ff00 @ + tstne r2, $0x00ff0000 @ + tstne r2, $0xff000000 @ + addne r0, r0, $4 @ if not, the string is 4 bytes longer + IT(t, ne) + ldrne r2, [r1], $4 @ and we continue to the next word + bne Laligned @ +Llastword: @ drop through to here once we find a +#if __BYTE_ORDER == __BIG_ENDIAN + tst r2, $0xff000000 @ word that has a zero byte in it + IT(tttt, ne) + addne r0, r0, $1 @ + tstne r2, $0x00ff0000 @ and add up to 3 bytes on to it + addne r0, r0, $1 @ + tstne r2, $0x0000ff00 @ (if first three all non-zero, 4th + IT(t, ne) + addne r0, r0, $1 @ must be zero) +#else + tst r2, $0x000000ff @ + IT(tttt, ne) + addne r0, r0, $1 @ + tstne r2, $0x0000ff00 @ and add up to 3 bytes on to it + addne r0, r0, $1 @ + tstne r2, $0x00ff0000 @ (if first three all non-zero, 4th + IT(t, ne) + addne r0, r0, $1 @ must be zero) +#endif +#if defined(__USE_BX__) + bx lr +#else + mov pc,lr +#endif +#endif + +.size strlen,.-strlen + +libc_hidden_def(strlen) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/avr32/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/avr32/Makefile new file mode 100644 index 00000000..e19e9d9e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/avr32/Makefile @@ -0,0 +1,26 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2003 Erik Andersen +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU Library General Public License as published by the Free +# Software Foundation; either version 2 of the License, or (at your option) any +# later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more +# details. +# +# You should have received a copy of the GNU Library General Public License +# along with this program; if not, write to the Free Software Foundation, Inc., +# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +top_srcdir := ../../../ +top_builddir := ../../../ + +all: objs + +include $(top_builddir)Rules.mak +include ../Makefile.in +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/avr32/bcopy.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/avr32/bcopy.S new file mode 100644 index 00000000..bdd52181 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/avr32/bcopy.S @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2004-2007 Atmel Corporation + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License. See the file "COPYING.LIB" in the main directory of this + * archive for more details. + */ + +#include + +#ifdef __UCLIBC_SUSV3_LEGACY__ + + .text + .global bcopy + .type bcopy, @function + .align 1 +bcopy: + /* Swap the first two arguments */ + eor r11, r12 + eor r12, r11 + eor r11, r12 + rjmp HIDDEN_JUMPTARGET(memmove) + + .size bcopy, . - bcopy + +#endif /* __UCLIBC_SUSV3_LEGACY__ */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/avr32/bzero.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/avr32/bzero.S new file mode 100644 index 00000000..ca1bd2dd --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/avr32/bzero.S @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2004-2007 Atmel Corporation + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License. See the file "COPYING.LIB" in the main directory of this + * archive for more details. + */ + +#include + +#ifdef __UCLIBC_SUSV3_LEGACY__ + + .text + .global bzero + .type bzero, @function + .align 1 +bzero: + mov r10, r11 + mov r11, 0 + rjmp HIDDEN_JUMPTARGET(memset) + + .size bzero, . - bzero + +#endif /* __UCLIBC_SUSV3_LEGACY__ */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/avr32/memcmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/avr32/memcmp.S new file mode 100644 index 00000000..ae6cc918 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/avr32/memcmp.S @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2004-2007 Atmel Corporation + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License. See the file "COPYING.LIB" in the main directory of this + * archive for more details. + */ + +#include + +#define s1 r12 +#define s2 r11 +#define len r10 + + .text + .global memcmp + .type memcmp, @function + .align 1 +memcmp: + sub len, 4 + brlt .Lless_than_4 + +1: ld.w r8, s1++ + ld.w r9, s2++ + cp.w r8, r9 + brne .Lfound_word + sub len, 4 + brge 1b + +.Lless_than_4: + sub len, -4 + reteq 0 + +1: ld.ub r8, s1++ + ld.ub r9, s2++ + sub r8, r9 + retne r8 + sub len, 1 + brgt 1b + + retal 0 + +.Lfound_word: + mov len, 4 + +2: bfextu r11, r9, 24, 8 + bfextu r12, r8, 24, 8 + sub r12, r11 + retne r12 + lsl r8, 8 + lsl r9, 8 + sub len, 1 + brne 2b + retal r12 + + .size memcmp, . - memcmp + +libc_hidden_def(memcmp) +#ifdef __UCLIBC_SUSV3_LEGACY__ +strong_alias(memcmp,bcmp) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/avr32/memcpy.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/avr32/memcpy.S new file mode 100644 index 00000000..bf091abf --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/avr32/memcpy.S @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2004-2007 Atmel Corporation + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License. See the file "COPYING.LIB" in the main directory of this + * archive for more details. + */ + +/* Don't use r12 as dst since we must return it unmodified */ +#define dst r9 +#define src r11 +#define len r10 + + .text + .global memcpy + .type memcpy, @function +memcpy: + pref src[0] + mov dst, r12 + + /* If we have less than 32 bytes, don't do anything fancy */ + cp.w len, 32 + brge .Lmore_than_31 + + sub len, 1 + retlt r12 +1: ld.ub r8, src++ + st.b dst++, r8 + sub len, 1 + brge 1b + retal r12 + +.Lmore_than_31: + pushm r0-r7, lr + + /* Check alignment */ + mov r8, src + andl r8, 31, COH + brne .Lunaligned_src + mov r8, dst + andl r8, 3, COH + brne .Lunaligned_dst + +.Laligned_copy: + sub len, 32 + brlt .Lless_than_32 + +1: /* Copy 32 bytes at a time */ + ldm src, r0-r7 + sub src, -32 + stm dst, r0-r7 + sub dst, -32 + sub len, 32 + brge 1b + +.Lless_than_32: + /* Copy 16 more bytes if possible */ + sub len, -16 + brlt .Lless_than_16 + ldm src, r0-r3 + sub src, -16 + sub len, 16 + stm dst, r0-r3 + sub dst, -16 + +.Lless_than_16: + /* Do the remaining as byte copies */ + neg len + add pc, pc, len << 2 + .rept 15 + ld.ub r0, src++ + st.b dst++, r0 + .endr + + popm r0-r7, pc + +.Lunaligned_src: + /* Make src cacheline-aligned. r8 = (src & 31) */ + rsub r8, r8, 32 + sub len, r8 +1: ld.ub r0, src++ + st.b dst++, r0 + sub r8, 1 + brne 1b + + /* If dst is word-aligned, we're ready to go */ + pref src[0] + mov r8, 3 + tst dst, r8 + breq .Laligned_copy + +.Lunaligned_dst: + /* src is aligned, but dst is not. Expect bad performance */ + sub len, 4 + brlt 2f +1: ld.w r0, src++ + st.w dst++, r0 + sub len, 4 + brge 1b + +2: neg len + add pc, pc, len << 2 + .rept 3 + ld.ub r0, src++ + st.b dst++, r0 + .endr + + popm r0-r7, pc + .size memcpy, . - memcpy + +libc_hidden_def(memcpy) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/avr32/memmove.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/avr32/memmove.S new file mode 100644 index 00000000..535f4a25 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/avr32/memmove.S @@ -0,0 +1,116 @@ +/* + * Copyright (C) 2004-2007 Atmel Corporation + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License. See the file "COPYING.LIB" in the main directory of this + * archive for more details. + */ + +#define dst r12 +#define src r11 +#define len r10 + + .text + .global memmove + .type memmove, @function +memmove: + cp.w src, dst + brge HIDDEN_JUMPTARGET(memcpy) + + add dst, len + add src, len + pref src[-1] + + /* + * The rest is basically the same as in memcpy.S except that + * the direction is reversed. + */ + cp.w len, 32 + brge .Lmore_than_31 + + sub len, 1 + retlt r12 +1: ld.ub r8, --src + st.b --dst, r8 + sub len, 1 + brge 1b + retal r12 + +.Lmore_than_31: + pushm r0-r7, lr + + /* Check alignment */ + mov r8, src + andl r8, 31, COH + brne .Lunaligned_src + mov r8, r12 + andl r8, 3, COH + brne .Lunaligned_dst + +.Laligned_copy: + sub len, 32 + brlt .Lless_than_32 + +1: /* Copy 32 bytes at a time */ + sub src, 32 + ldm src, r0-r7 + sub dst, 32 + sub len, 32 + stm dst, r0-r7 + brge 1b + +.Lless_than_32: + /* Copy 16 more bytes if possible */ + sub len, -16 + brlt .Lless_than_16 + sub src, 16 + ldm src, r0-r3 + sub dst, 16 + sub len, 16 + stm dst, r0-r3 + +.Lless_than_16: + /* Do the remaining as byte copies */ + sub len, -16 + breq 2f +1: ld.ub r0, --src + st.b --dst, r0 + sub len, 1 + brne 1b + +2: popm r0-r7, pc + +.Lunaligned_src: + /* Make src cacheline-aligned. r8 = (src & 31) */ + sub len, r8 +1: ld.ub r0, --src + st.b --dst, r0 + sub r8, 1 + brne 1b + + /* If dst is word-aligned, we're ready to go */ + pref src[-4] + mov r8, 3 + tst dst, r8 + breq .Laligned_copy + +.Lunaligned_dst: + /* src is aligned, but dst is not. Expect bad performance */ + sub len, 4 + brlt 2f +1: ld.w r0, --src + st.w --dst, r0 + sub len, 4 + brge 1b + +2: neg len + add pc, pc, len << 2 + .rept 3 + ld.ub r0, --src + st.b --dst, r0 + .endr + + popm r0-r7, pc + .size memmove, . - memmove + +libc_hidden_def(memmove) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/avr32/memset.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/avr32/memset.S new file mode 100644 index 00000000..472b2be3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/avr32/memset.S @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2004-2007 Atmel Corporation + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License. See the file "COPYING.LIB" in the main directory of this + * archive for more details. + */ + +#include + +#define s r12 +#define c r11 +#define n r10 + + .text + .global memset + .type memset, @function + + .align 1 +memset: + cp.w n, 32 + mov r9, s + brge .Llarge_memset + + sub n, 1 + retlt s +1: st.b s++, c + sub n, 1 + brge 1b + + retal r9 + +.Llarge_memset: + mov r8, r11 + mov r11, 3 + bfins r8, r8, 8, 8 + bfins r8, r8, 16, 16 + tst s, r11 + breq 2f + +1: st.b s++, r8 + sub n, 1 + tst s, r11 + brne 1b + +2: mov r11, r9 + mov r9, r8 + sub n, 8 + +3: st.d s++, r8 + sub n, 8 + brge 3b + + /* If we are done, n == -8 and we'll skip all st.b insns below */ + neg n + lsl n, 1 + add pc, n + .rept 7 + st.b s++, r8 + .endr + retal r11 + + .size memset, . - memset + +libc_hidden_def(memset) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/avr32/strcmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/avr32/strcmp.S new file mode 100644 index 00000000..f73bd43e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/avr32/strcmp.S @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2004-2007 Atmel Corporation + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License. See the file "COPYING.LIB" in the main directory of this + * archive for more details. + */ + +#include + +#define s1 r12 +#define s2 r11 +#define len r10 + + .text + .global strcmp + .type strcmp, @function + .align 1 +strcmp: + mov r8, 3 + tst s1, r8 + brne .Lunaligned_s1 + tst s2, r8 + brne .Lunaligned_s2 + +1: ld.w r8, s1++ + ld.w r9, s2++ + cp.w r8, r9 + brne 2f + tnbz r8 + brne 1b + retal 0 + +2: bfextu r12, r8, 24, 8 + bfextu r11, r9, 24, 8 + sub r12, r11 + retne r12 + cp.w r11, 0 + reteq 0 + bfextu r12, r8, 16, 8 + bfextu r11, r9, 16, 8 + sub r12, r11 + retne r12 + cp.w r11, 0 + reteq 0 + bfextu r12, r8, 8, 8 + bfextu r11, r9, 8, 8 + sub r12, r11 + retne r12 + cp.w r11, 0 + reteq 0 + bfextu r12, r8, 0, 8 + bfextu r11, r9, 0, 8 + sub r12, r11 + retal r12 + +.Lunaligned_s1: +3: tst s1, r8 + breq 4f + ld.ub r10, s1++ + ld.ub r9, s2++ + sub r10, r9 + retne r10 + cp.w r9, 0 + brne 3b + retal r10 + +4: tst s2, r8 + breq 1b + +.Lunaligned_s2: + /* + * s1 and s2 can't both be aligned, and unaligned word loads + * can trigger spurious exceptions if we cross a page boundary. + * Do it the slow way... + */ +1: ld.ub r8, s1++ + ld.ub r9, s2++ + sub r8, r9 + retne r8 + cp.w r9, 0 + brne 1b + retal 0 + + .size strcmp, . - strcmp + +libc_hidden_def(strcmp) +#ifndef __UCLIBC_HAS_LOCALE__ +strong_alias(strcmp, strcoll) +libc_hidden_def(strcoll) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/avr32/strlen.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/avr32/strlen.S new file mode 100644 index 00000000..5223e536 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/avr32/strlen.S @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2004-2007 Atmel Corporation + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License. See the file "COPYING.LIB" in the main directory of this + * archive for more details. + */ + +#include + +#define str r12 + + .text + .global strlen + .type strlen, @function +strlen: + mov r11, r12 + + mov r9, str + andl r9, 3, COH + brne .Lunaligned_str + +1: ld.w r8, str++ + tnbz r8 + brne 1b + + sub r12, r11 + bfextu r9, r8, 24, 8 + cp.w r9, 0 + subeq r12, 4 + reteq r12 + bfextu r9, r8, 16, 8 + cp.w r9, 0 + subeq r12, 3 + reteq r12 + bfextu r9, r8, 8, 8 + cp.w r9, 0 + subeq r12, 2 + reteq r12 + sub r12, 1 + retal r12 + +.Lunaligned_str: + add pc, pc, r9 << 3 + sub r0, r0, 0 /* 4-byte nop */ + ld.ub r8, str++ + sub r8, r8, 0 + breq 1f + ld.ub r8, str++ + sub r8, r8, 0 + breq 1f + ld.ub r8, str++ + sub r8, r8, 0 + brne 1b + +1: sub r12, 1 + sub r12, r11 + retal r12 + + .size strlen, . - strlen + +libc_hidden_def(strlen) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/basename.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/basename.c new file mode 100644 index 00000000..29e7a2a8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/basename.c @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include "_string.h" + +#ifdef __USE_GNU + +char *basename(const char *path) +{ + register const char *s; + register const char *p; + + p = s = path; + + while (*s) { + if (*s++ == '/') { + p = s; + } + } + + return (char *) p; +} +libc_hidden_def(basename) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/bcopy.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/bcopy.c new file mode 100644 index 00000000..6234fd80 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/bcopy.c @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include "_string.h" + +#ifdef __UCLIBC_SUSV3_LEGACY__ + + +void bcopy(const void *s2, void *s1, size_t n) +{ +#if 1 + memmove(s1, s2, n); +#else + register char *s; + register const char *p; + + s = s1; + p = s2; + if (p >= s) { + while (n) { + *s++ = *p++; + --n; + } + } else { + while (n) { + --n; + s[n] = p[n]; + } + } +#endif +} +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/bfin/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/bfin/Makefile new file mode 100644 index 00000000..0a95346f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/bfin/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir:=../../../ +top_builddir:=../../../ +all: objs +include $(top_builddir)Rules.mak +include ../Makefile.in +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/bfin/memchr.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/bfin/memchr.S new file mode 100644 index 00000000..26d419f7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/bfin/memchr.S @@ -0,0 +1,55 @@ +/* memchr.S + * Copyright (C) 2003-2007 Analog Devices Inc., All Rights Reserved. + * + * This file is subject to the terms and conditions of the GNU Library General + * Public License. See the file "COPYING.LIB" in the main directory of this + * archive for more details. + * + * Non-LGPL License also available as part of VisualDSP++ + * http://www.analog.com/processors/resources/crosscore/visualDspDevSoftware.html + */ + +#include + +/* void *memchr(const void *s, int c, size_t n); + * R0 = address (s) + * R1 = sought byte (c) + * R2 = count (n) + * + * Returns pointer to located character. + */ + +.text + +.align 2 + +.weak _memchr +ENTRY(_memchr) + P0 = R0; /* P0 = address */ + P2 = R2; /* P2 = count */ + R1 = R1.B(Z); + CC = R2 == 0; + IF CC JUMP .Lfailed; + +.Lbytes: + LSETUP (.Lbyte_loop_s, .Lbyte_loop_e) LC0=P2; + +.Lbyte_loop_s: + R3 = B[P0++](Z); + CC = R3 == R1; + IF CC JUMP .Lfound; +.Lbyte_loop_e: + NOP; + +.Lfailed: + R0=0; + RTS; + +.Lfound: + R0 = P0; + R0 += -1; + RTS; + +.size _memchr,.-_memchr + +libc_hidden_def (memchr) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/bfin/memcmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/bfin/memcmp.S new file mode 100644 index 00000000..7cc76ad9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/bfin/memcmp.S @@ -0,0 +1,104 @@ +/* memcmp.S + * Copyright (C) 2003-2007 Analog Devices Inc., All Rights Reserved. + * + * This file is subject to the terms and conditions of the GNU Library General + * Public License. See the file "COPYING.LIB" in the main directory of this + * archive for more details. + * + * Non-LGPL License also available as part of VisualDSP++ + * http://www.analog.com/processors/resources/crosscore/visualDspDevSoftware.html + */ + +#include + +/* int memcmp(const void *s1, const void *s2, size_t n); + * R0 = First Address (s1) + * R1 = Second Address (s2) + * R2 = count (n) + * + * Favours word aligned data. + */ + +.text + +.align 2 + +.weak _memcmp +ENTRY(_memcmp) + I1 = P3; + P0 = R0; /* P0 = s1 address */ + P3 = R1; /* P3 = s2 Address */ + P2 = R2 ; /* P2 = count */ + CC = R2 <= 7(IU); + IF CC JUMP .Ltoo_small; + I0 = R1; /* s2 */ + R1 = R1 | R0; /* OR addresses together */ + R1 <<= 30; /* check bottom two bits */ + CC = AZ; /* AZ set if zero. */ + IF !CC JUMP .Lbytes ; /* Jump if addrs not aligned. */ + + P1 = P2 >> 2; /* count = n/4 */ + R3 = 3; + R2 = R2 & R3; /* remainder */ + P2 = R2; /* set remainder */ + + LSETUP (.Lquad_loop_s, .Lquad_loop_e) LC0=P1; +.Lquad_loop_s: +#if !defined(__WORKAROUND_AVOID_DAG1) + MNOP || R0 = [P0++] || R1 = [I0++]; +#else + R0 = [P0++]; + R1 = [I0++]; +#endif + CC = R0 == R1; + IF !CC JUMP .Lquad_different; +.Lquad_loop_e: + NOP; + + P3 = I0; /* s2 */ +.Ltoo_small: + CC = P2 == 0; /* Check zero count*/ + IF CC JUMP .Lfinished; /* very unlikely*/ + +.Lbytes: + LSETUP (.Lbyte_loop_s, .Lbyte_loop_e) LC0=P2; +.Lbyte_loop_s: + R1 = B[P3++](Z); /* *s2 */ + R0 = B[P0++](Z); /* *s1 */ + CC = R0 == R1; + IF !CC JUMP .Ldifferent; +.Lbyte_loop_e: + NOP; + +.Ldifferent: + R0 = R0 - R1; + P3 = I1; + RTS; + +.Lquad_different: + /* We've read two quads which don't match. + * Can't just compare them, because we're + * a little-endian machine, so the MSBs of + * the regs occur at later addresses in the + * string. + * Arrange to re-read those two quads again, + * byte-by-byte. + */ + P0 += -4; /* back up to the start of the */ + P3 = I0; /* quads, and increase the*/ + P2 += 4; /* remainder count*/ + P3 += -4; + JUMP .Lbytes; + +.Lfinished: + R0 = 0; + P3 = I1; + RTS; + +.size _memcmp,.-_memcmp + +libc_hidden_def (memcmp) + +#ifdef __UCLIBC_SUSV3_LEGACY__ +weak_alias (memcmp,bcmp) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/bfin/memcpy.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/bfin/memcpy.S new file mode 100644 index 00000000..bdd76069 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/bfin/memcpy.S @@ -0,0 +1,77 @@ +/* memcpy.S + * Copyright (C) 2003-2007 Analog Devices Inc., All Rights Reserved. + * + * This file is subject to the terms and conditions of the GNU Library General + * Public License. See the file "COPYING.LIB" in the main directory of this + * archive for more details. + * + * Non-LGPL License also available as part of VisualDSP++ + * http://www.analog.com/processors/resources/crosscore/visualDspDevSoftware.html + */ + +#include + +/* void *memcpy(void *dest, const void *src, size_t n); + * R0 = To Address (dest) (leave unchanged to form result) + * R1 = From Address (src) + * R2 = count + * + * Note: Favours word alignment + */ + +.text + +.align 2 + +.weak _memcpy +ENTRY(_memcpy) + [--SP] = P3; + P0 = R0; /* P0 = To address */ + P3 = R1; /* P3 = From Address */ + P2 = R2; /* P2 = count */ + CC = R2 <= 7(IU); + IF CC JUMP .Ltoo_small; + I0 = R1; + R3 = R1 | R0; /* OR addresses together */ + R3 <<= 30; /* check bottom two bits */ + CC = AZ; /* AZ set if zero. */ + IF !CC JUMP .Lbytes; /* Jump if addrs not aligned. */ + P1 = P2 >> 2; /* count = n/4 */ + P1 += -1; + R3 = 3; + R2 = R2 & R3; /* remainder */ + P2 = R2; /* set remainder */ + R1 = [I0++]; +#if !defined(__WORKAROUND_AVOID_DAG1) + LSETUP (.Lquad_loop, .Lquad_loop) LC0=P1; +.Lquad_loop: MNOP || [P0++] = R1 || R1 = [I0++]; +#else + LSETUP (.Lquad_loop_s, .Lquad_loop_e) LC0=P1; +.Lquad_loop_s: [P0++] = R1; +.Lquad_loop_e: R1 = [I0++]; +#endif + [P0++] = R1; + + CC = P2 == 0; /* any remaining bytes? */ + P3 = I0; /* Ammend P3 for remaining copy */ + IF !CC JUMP .Lbytes; + P3 = [SP++]; + RTS; + +.Ltoo_small: + CC = P2 == 0; /* Check zero count */ + IF CC JUMP .Lfinished; /* very unlikely */ + +.Lbytes: + LSETUP (.Lbyte_loop_s, .Lbyte_loop_e) LC0=P2; +.Lbyte_loop_s: R1 = B[P3++](Z); +.Lbyte_loop_e: B[P0++] = R1; + +.Lfinished: + P3 = [SP++]; + + RTS; + +.size _memcpy,.-_memcpy + +libc_hidden_def (memcpy) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/bfin/memmove.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/bfin/memmove.S new file mode 100644 index 00000000..73e36382 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/bfin/memmove.S @@ -0,0 +1,100 @@ +/* memmove.S + * Copyright (C) 2003-2007 Analog Devices Inc., All Rights Reserved. + * + * This file is subject to the terms and conditions of the GNU Library General + * Public License. See the file "COPYING.LIB" in the main directory of this + * archive for more details. + * + * Non-LGPL License also available as part of VisualDSP++ + * http://www.analog.com/processors/resources/crosscore/visualDspDevSoftware.html + */ + +#include + +/* void *memmove(void *dest, const void *src, size_t n); + * R0 = To Address (dest) (leave unchanged to form result) + * R1 = From Address (src) + * R2 = count (n) + * + * Note: Data may overlap + */ + +.text + +.align 2 + +.weak _memmove +ENTRY(_memmove) + I1 = P3; + P0 = R0; /* P0 = To address */ + P3 = R1; /* P3 = From Address */ + P2 = R2; /* P2 = count */ + CC = P2 == 0; /* Check zero count*/ + IF CC JUMP .Lfinished; /* very unlikely */ + + CC = R1 < R0 (IU); /* From < To */ + IF !CC JUMP .Lno_overlap; + R3 = R1 + R2; + CC = R0 <= R3 (IU); /* (From+len) >= To */ + IF CC JUMP .Loverlap; +.Lno_overlap: + R3 = 11; + CC = R2 <= R3; + IF CC JUMP .Lbytes; + R3 = R1 | R0; /* OR addresses together */ + R3 <<= 30; /* check bottom two bits */ + CC = AZ; /* AZ set if zero.*/ + IF !CC JUMP .Lbytes; /* Jump if addrs not aligned.*/ + + I0 = P3; + P1 = P2 >> 2; /* count = n/4 */ + P1 += -1; + R3 = 3; + R2 = R2 & R3; /* remainder */ + P2 = R2; /* set remainder */ + R1 = [I0++]; + +#if !defined(__WORKAROUND_AVOID_DAG1) + LSETUP (.Lquad_loop, .Lquad_loop) LC0=P1; +.Lquad_loop: MNOP || [P0++] = R1 || R1 = [I0++]; +#else + LSETUP (.Lquad_loop_s, .Lquad_loop_e) LC0=P1; +.Lquad_loop_s: [P0++] = R1; +.Lquad_loop_e: R1 = [I0++]; +#endif + [P0++] = R1; + + CC = P2 == 0; /* any remaining bytes? */ + P3 = I0; /* Ammend P3 to updated ptr. */ + IF !CC JUMP .Lbytes; + P3 = I1; + RTS; + +.Lbytes: LSETUP (.Lbyte2_s, .Lbyte2_e) LC0=P2; +.Lbyte2_s: R1 = B[P3++](Z); +.Lbyte2_e: B[P0++] = R1; + +.Lfinished: P3 = I1; + RTS; + +.Loverlap: + P2 += -1; + P0 = P0 + P2; + P3 = P3 + P2; + R1 = B[P3--] (Z); + CC = P2 == 0; + IF CC JUMP .Lno_loop; +#if defined(__WORKAROUND_SPECULATIVE_LOADS) + NOP; + NOP; +#endif + LSETUP (.Lol_s, .Lol_e) LC0 = P2; +.Lol_s: B[P0--] = R1; +.Lol_e: R1 = B[P3--] (Z); +.Lno_loop: B[P0] = R1; + P3 = I1; + RTS; + +.size _memmove,.-_memmove + +libc_hidden_def (memmove) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/bfin/memset.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/bfin/memset.S new file mode 100644 index 00000000..64012f78 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/bfin/memset.S @@ -0,0 +1,90 @@ +/* memset.S + * Copyright (C) 2003-2007 Analog Devices Inc., All Rights Reserved. + * + * This file is subject to the terms and conditions of the GNU Library General + * Public License. See the file "COPYING.LIB" in the main directory of this + * archive for more details. + * + * Non-LGPL License also available as part of VisualDSP++ + * http://www.analog.com/processors/resources/crosscore/visualDspDevSoftware.html + */ + +#include + +/* void *memset(void *s, int c, size_t n); + * R0 = address (s) (leave unchanged to form result) + * R1 = filler byte (c) + * R2 = count (n) + * + * Note: Favours word aligned data. + */ + +.text + +.align 2 + +.weak _memset +ENTRY(_memset) + P0 = R0 ; /* P0 = address */ + P2 = R2 ; /* P2 = count */ + R3 = R0 + R2; /* end */ + CC = R2 <= 7(IU); + IF CC JUMP .Ltoo_small; + R1 = R1.B (Z); /* R1 = fill char */ + R2 = 3; + R2 = R0 & R2; /* addr bottom two bits */ + CC = R2 == 0; /* AZ set if zero. */ + IF !CC JUMP .Lforce_align ; /* Jump if addr not aligned. */ + +.Laligned: + P1 = P2 >> 2; /* count = n/4 */ + R2 = R1 << 8; /* create quad filler */ + R2.L = R2.L + R1.L(NS); + R2.H = R2.L + R1.H(NS); + P2 = R3; + + LSETUP (.Lquad_loop , .Lquad_loop) LC0=P1; +.Lquad_loop: + [P0++] = R2; + + CC = P0 == P2; + IF !CC JUMP .Lbytes_left; + RTS; + +.Lbytes_left: + R2 = R3; /* end point */ + R3 = P0; /* current position */ + R2 = R2 - R3; /* bytes left */ + P2 = R2; + +.Ltoo_small: + CC = P2 == 0; /* Check zero count */ + IF CC JUMP .Lfinished; /* Unusual */ + +.Lbytes: + LSETUP (.Lbyte_loop , .Lbyte_loop) LC0=P2; +.Lbyte_loop: + B[P0++] = R1; + +.Lfinished: + RTS; + +.Lforce_align: + CC = BITTST (R0, 0); /* odd byte */ + R0 = 4; + R0 = R0 - R2; + P1 = R0; + R0 = P0; /* Recover return address */ + IF !CC JUMP .Lskip1; + B[P0++] = R1; +.Lskip1: + CC = R2 <= 2; /* 2 bytes */ + P2 -= P1; /* reduce count */ + IF !CC JUMP .Laligned; + B[P0++] = R1; + B[P0++] = R1; + JUMP .Laligned; + +.size _memset,.-_memset + +libc_hidden_def (memset) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/bfin/strcmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/bfin/strcmp.S new file mode 100644 index 00000000..ef23aa9a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/bfin/strcmp.S @@ -0,0 +1,122 @@ +/* strcmp.S + * Copyright (C) 2003-2007 Analog Devices Inc., All Rights Reserved. + * + * This file is subject to the terms and conditions of the GNU Library General + * Public License. See the file "COPYING.LIB" in the main directory of this + * archive for more details. + * + * Non-LGPL License also available as part of VisualDSP++ + * http://www.analog.com/processors/resources/crosscore/visualDspDevSoftware.html + */ + +#include + +/* Fast strcmp() for Blackfin. + * When both strings are aligned, this processes four characters at + * a time. Uses a hw loop with "very big" count to loop "forever", + * until difference or a terminating zero is found. + * Once the end-case word has been identified, breaks out of the + * loop to check more carefully (same as the unaligned case). + */ + +.text + +.align 2 + +.weak _strcmp +ENTRY(_strcmp) + [--sp] = (R7:4); + p1 = r0; + p2 = r1; + + p0 = -1; /* (need for loop counter init) */ + + /* check if byte aligned */ + r0 = r0 | r1; /* check both pointers at same time */ + r0 <<= 30; /* dump all but last 2 bits */ + cc = az; /* are they zero? */ + if !cc jump .Lunaligned; /* no; use unaligned code. */ + /* fall-thru for aligned case.. */ + + /* note that r0 is zero from the previous... */ + /* p0 set to -1 */ + + LSETUP (.Lbeginloop, .Lendloop) lc0=p0; + /* pick up first words */ + r1 = [p1++]; + r2 = [p2++]; + /* make up mask: 0FF0FF */ + r7 = 0xFF; + r7.h = 0xFF; + /* loop : 9 cycles to check 4 characters */ + cc = r1 == r2; +.Lbeginloop: + if !cc jump .Lnotequal4; /* compare failure, exit loop */ + + /* starting with 44332211 */ + /* see if char 3 or char 1 is 0 */ + r3 = r1 & r7; /* form 00330011 */ + /* add to zero, and (r2 is free, reload) */ + r6 = r3 +|+ r0 || r2 = [p2++] || nop; + cc = az; /* true if either is zero */ + r3 = r1 ^ r3; /* form 44002200 (4321^0301 => 4020) */ + /* (trick, saves having another mask) */ + /* add to zero, and (r1 is free, reload) */ + r6 = r3 +|+ r0 || r1 = [p1++] || nop; + cc |= az; /* true if either is zero */ + if cc jump .Lzero4; /* leave if a zero somewhere */ +.Lendloop: + cc = r1 == r2; + + /* loop exits */ +.Lnotequal4: /* compare failure on 4-char compare */ + /* address pointers are one word ahead; */ + /* faster to use zero4 exit code */ + p1 += 4; + p2 += 4; + +.Lzero4: /* one of the bytes in word 1 is zero */ + /* but we've already fetched the next word; so */ + /* backup two to look at failing word again */ + p1 += -8; + p2 += -8; + + + + /* here when pointers are unaligned: checks one */ + /* character at a time. Also use at the end of */ + /* the word-check algorithm to figure out what happened */ +.Lunaligned: + /* R0 is non-zero from before. */ + /* p0 set to -1 */ + + r0 = 0 (Z); + r1 = B[p1++] (Z); + r2 = B[p2++] (Z); + LSETUP (.Lbeginloop1, .Lendloop1) lc0=p0; + +.Lbeginloop1: + cc = r1; /* first char must be non-zero */ + /* chars must be the same */ + r3 = r2 - r1 (NS) || r1 = B[p1++] (Z) || nop; + cc &= az; + r3 = r0 - r2; /* second char must be non-zero */ + cc &= an; + if !cc jump .Lexitloop1; +.Lendloop1: + r2 = B[p2++] (Z); + +.Lexitloop1: /* here means we found a zero or a difference. */ + /* we have r2(N), p2(N), r1(N+1), p1(N+2) */ + r1=B[p1+ -2] (Z); + r0 = r1 - r2; + (r7:4) = [sp++]; + rts; +.size _strcmp,.-_strcmp + +libc_hidden_def (strcmp) + +#ifndef __UCLIBC_HAS_LOCALE__ +weak_alias (strcmp,strcoll) +libc_hidden_def (strcoll) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/bzero.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/bzero.c new file mode 100644 index 00000000..a541f369 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/bzero.c @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include "_string.h" + +#ifdef __UCLIBC_SUSV3_LEGACY__ +void bzero(void *s, size_t n) +{ +#if 1 + (void)memset(s, 0, n); +#else + register unsigned char *p = s; + + while (n) { + *p++ = 0; + --n; + } +#endif +} +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/cris/memcopy.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/cris/memcopy.h new file mode 100644 index 00000000..449c7564 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/cris/memcopy.h @@ -0,0 +1,62 @@ +/* Copyright (C) 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + Modified for use in uClibc (C) 2007 Axis Communications AB. + Minimal modifications: include path name and #undef of WORD_COPY_FWD/BWD + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include "../generic/memcopy.h" + +/* We override the word-copying macros, partly because misalignment in one + pointer isn't cause for a special function, partly because we want to + get rid of all the static functions in generic/memcopy.c; these macros + are only used in memmove.c since we have arch-specific mempcpy, memcpy and + memset. */ + +#undef OP_T_THRES +#define OP_T_THRES OPSIZ + +#undef WORD_COPY_FWD +#define WORD_COPY_FWD(dst_bp, src_bp, nbytes_left, nbytes) \ + do \ + { \ + unsigned long enddst_bp = dst_bp + nbytes - (nbytes % OPSIZ); \ + nbytes_left = (nbytes % OPSIZ); \ + while (dst_bp < (unsigned long) enddst_bp) \ + { \ + op_t x = *(op_t *) src_bp; \ + src_bp += sizeof x; \ + *(op_t *) dst_bp = x; \ + dst_bp += sizeof x; \ + } \ + } while (0) + +#undef WORD_COPY_BWD +#define WORD_COPY_BWD(dst_bp, src_bp, nbytes_left, nbytes) \ + do \ + { \ + unsigned long enddst_bp = dst_bp - nbytes + (nbytes % OPSIZ); \ + nbytes_left = (nbytes % OPSIZ); \ + while (dst_bp > enddst_bp) \ + { \ + op_t x; \ + src_bp -= sizeof x; \ + x = *(op_t *) src_bp; \ + dst_bp -= sizeof x; \ + *(op_t *) dst_bp = x; \ + } \ + } while (0) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/cris/memcpy.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/cris/memcpy.c new file mode 100644 index 00000000..94e576f4 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/cris/memcpy.c @@ -0,0 +1,242 @@ +/* A memcpy for CRIS. + Copyright (C) 1994-2008 Axis Communications. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Neither the name of Axis Communications nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY AXIS COMMUNICATIONS AND ITS CONTRIBUTORS + ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL AXIS + COMMUNICATIONS OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. */ + +/* FIXME: This file should really only be used for reference, as the + result is somewhat depending on gcc generating what we expect rather + than what we describe. An assembly file should be used instead. */ + +#include + +#ifdef __arch_v32 +/* For CRISv32, movem is very cheap. */ +#define MEMCPY_BY_BLOCK_THRESHOLD (44) +#else +/* Break even between movem and move16 is really at 38.7 * 2, but + modulo 44, so up to the next multiple of 44, we use ordinary code. */ +#define MEMCPY_BY_BLOCK_THRESHOLD (44 * 2) +#endif + +/* No name ambiguities in this file. */ +__asm__ (".syntax no_register_prefix"); + +void * +memcpy(void *pdst, const void *psrc, size_t pn) +{ + /* Now we want the parameters put in special registers. + Make sure the compiler is able to make something useful of this. + As it is now: r10 -> r13; r11 -> r11 (nop); r12 -> r12 (nop). + + If gcc was allright, it really would need no temporaries, and no + stack space to save stuff on. */ + + register void *return_dst __asm__ ("r10") = pdst; + register unsigned char *dst __asm__ ("r13") = pdst; + register unsigned const char *src __asm__ ("r11") = psrc; + register int n __asm__ ("r12") = pn; + + /* When src is aligned but not dst, this makes a few extra needless + cycles. I believe it would take as many to check that the + re-alignment was unnecessary. */ + if (((unsigned long) dst & 3) != 0 + /* Don't align if we wouldn't copy more than a few bytes; so we + don't have to check further for overflows. */ + && n >= 3) + { + if ((unsigned long) dst & 1) + { + n--; + *dst = *src; + src++; + dst++; + } + + if ((unsigned long) dst & 2) + { + n -= 2; + *(short *) dst = *(short *) src; + src += 2; + dst += 2; + } + } + + /* Decide which copying method to use. */ + if (n >= MEMCPY_BY_BLOCK_THRESHOLD) + { + /* It is not optimal to tell the compiler about clobbering any + registers; that will move the saving/restoring of those registers + to the function prologue/epilogue, and make non-movem sizes + suboptimal. */ + __asm__ __volatile__ + ("\ + ;; GCC does promise correct register allocations, but let's \n\ + ;; make sure it keeps its promises. \n\ + .ifnc %0-%1-%2,$r13-$r11-$r12 \n\ + .error \"GCC reg alloc bug: %0-%1-%4 != $r13-$r12-$r11\" \n\ + .endif \n\ + \n\ + ;; Save the registers we'll use in the movem process \n\ + ;; on the stack. \n\ + subq 11*4,sp \n\ + movem r10,[sp] \n\ + \n\ + ;; Now we've got this: \n\ + ;; r11 - src \n\ + ;; r13 - dst \n\ + ;; r12 - n \n\ + \n\ + ;; Update n for the first loop. \n\ + subq 44,r12 \n\ +0: \n\ +" +#ifdef __arch_common_v10_v32 + /* Cater to branch offset difference between v32 and v10. We + assume the branch below has an 8-bit offset. */ +" setf\n" +#endif +" movem [r11+],r10 \n\ + subq 44,r12 \n\ + bge 0b \n\ + movem r10,[r13+] \n\ + \n\ + ;; Compensate for last loop underflowing n. \n\ + addq 44,r12 \n\ + \n\ + ;; Restore registers from stack. \n\ + movem [sp+],r10" + + /* Outputs. */ + : "=r" (dst), "=r" (src), "=r" (n) + + /* Inputs. */ + : "0" (dst), "1" (src), "2" (n)); + } + + while (n >= 16) + { + *(long *) dst = *(long *) src; dst += 4; src += 4; + *(long *) dst = *(long *) src; dst += 4; src += 4; + *(long *) dst = *(long *) src; dst += 4; src += 4; + *(long *) dst = *(long *) src; dst += 4; src += 4; + + n -= 16; + } + + switch (n) + { + case 0: + break; + + case 1: + *dst = *src; + break; + + case 2: + *(short *) dst = *(short *) src; + break; + + case 3: + *(short *) dst = *(short *) src; dst += 2; src += 2; + *dst = *src; + break; + + case 4: + *(long *) dst = *(long *) src; + break; + + case 5: + *(long *) dst = *(long *) src; dst += 4; src += 4; + *dst = *src; + break; + + case 6: + *(long *) dst = *(long *) src; dst += 4; src += 4; + *(short *) dst = *(short *) src; + break; + + case 7: + *(long *) dst = *(long *) src; dst += 4; src += 4; + *(short *) dst = *(short *) src; dst += 2; src += 2; + *dst = *src; + break; + + case 8: + *(long *) dst = *(long *) src; dst += 4; src += 4; + *(long *) dst = *(long *) src; + break; + + case 9: + *(long *) dst = *(long *) src; dst += 4; src += 4; + *(long *) dst = *(long *) src; dst += 4; src += 4; + *dst = *src; + break; + + case 10: + *(long *) dst = *(long *) src; dst += 4; src += 4; + *(long *) dst = *(long *) src; dst += 4; src += 4; + *(short *) dst = *(short *) src; + break; + + case 11: + *(long *) dst = *(long *) src; dst += 4; src += 4; + *(long *) dst = *(long *) src; dst += 4; src += 4; + *(short *) dst = *(short *) src; dst += 2; src += 2; + *dst = *src; + break; + + case 12: + *(long *) dst = *(long *) src; dst += 4; src += 4; + *(long *) dst = *(long *) src; dst += 4; src += 4; + *(long *) dst = *(long *) src; + break; + + case 13: + *(long *) dst = *(long *) src; dst += 4; src += 4; + *(long *) dst = *(long *) src; dst += 4; src += 4; + *(long *) dst = *(long *) src; dst += 4; src += 4; + *dst = *src; + break; + + case 14: + *(long *) dst = *(long *) src; dst += 4; src += 4; + *(long *) dst = *(long *) src; dst += 4; src += 4; + *(long *) dst = *(long *) src; dst += 4; src += 4; + *(short *) dst = *(short *) src; + break; + + case 15: + *(long *) dst = *(long *) src; dst += 4; src += 4; + *(long *) dst = *(long *) src; dst += 4; src += 4; + *(long *) dst = *(long *) src; dst += 4; src += 4; + *(short *) dst = *(short *) src; dst += 2; src += 2; + *dst = *src; + break; + } + + return return_dst; +} +libc_hidden_def(memcpy) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/cris/memmove.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/cris/memmove.c new file mode 100644 index 00000000..4184fc96 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/cris/memmove.c @@ -0,0 +1,100 @@ +/* Taken from generic/memmove.c; trivially modified to work with + arch-specific memcopy.h for Cris. + + Copy memory to memory until the specified number of bytes + has been copied. Overlap is handled correctly. + Copyright (C) 1991, 1995, 1996, 1997, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Torbjorn Granlund (tege@sics.se). + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#include "memcopy.h" +#include "../generic/pagecopy.h" + +void *memmove (void *dest, const void *src, size_t len) +{ + unsigned long int dstp = (long int) dest; + unsigned long int srcp = (long int) src; + + /* This test makes the forward copying code be used whenever possible. + Reduces the working set. */ + if (dstp - srcp >= len) /* *Unsigned* compare! */ + { +#if 1 +#warning REMINDER: Cris arch-opt memmove assumes memcpy does forward copying! + memcpy(dest, src, len); +#else + /* Copy from the beginning to the end. */ + + /* If there not too few bytes to copy, use word copy. */ + if (len >= OP_T_THRES) + { + /* Copy just a few bytes to make DSTP aligned. */ + len -= (-dstp) % OPSIZ; + BYTE_COPY_FWD (dstp, srcp, (-dstp) % OPSIZ); + + /* Copy whole pages from SRCP to DSTP by virtual address + manipulation, as much as possible. */ + + PAGE_COPY_FWD_MAYBE (dstp, srcp, len, len); + + /* Copy from SRCP to DSTP taking advantage of the known + alignment of DSTP. Number of bytes remaining is put + in the third argument, i.e. in LEN. This number may + vary from machine to machine. */ + + WORD_COPY_FWD (dstp, srcp, len, len); + + /* Fall out and copy the tail. */ + } + + /* There are just a few bytes to copy. Use byte memory operations. */ + BYTE_COPY_FWD (dstp, srcp, len); +#endif + } + else + { + /* Copy from the end to the beginning. */ + srcp += len; + dstp += len; + + /* If there not too few bytes to copy, use word copy. */ + if (len >= OP_T_THRES) + { + /* Copy just a few bytes to make DSTP aligned. */ + len -= dstp % OPSIZ; + BYTE_COPY_BWD (dstp, srcp, dstp % OPSIZ); + + /* Copy from SRCP to DSTP taking advantage of the known + alignment of DSTP. Number of bytes remaining is put + in the third argument, i.e. in LEN. This number may + vary from machine to machine. */ + + WORD_COPY_BWD (dstp, srcp, len, len); + + /* Fall out and copy the tail. */ + } + + /* There are just a few bytes to copy. Use byte memory operations. */ + BYTE_COPY_BWD (dstp, srcp, len); + } + + return (dest); +} +libc_hidden_def(memmove) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/cris/memset.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/cris/memset.c new file mode 100644 index 00000000..fab4e8b6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/cris/memset.c @@ -0,0 +1,262 @@ +/* A memset for CRIS. + Copyright (C) 1999-2008 Axis Communications. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Neither the name of Axis Communications nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY AXIS COMMUNICATIONS AND ITS CONTRIBUTORS + ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL AXIS + COMMUNICATIONS OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. */ + +/* FIXME: This file should really only be used for reference, as the + result is somewhat depending on gcc generating what we expect rather + than what we describe. An assembly file should be used instead. */ + +#include + +/* Note the multiple occurrence of the expression "12*4", including the + asm. It is hard to get it into the asm in a good way. Thus better to + expose the problem everywhere: no macro. */ + +/* Assuming one cycle per dword written or read (ok, not really true; the + world is not ideal), and one cycle per instruction, then 43+3*(n/48-1) + <= 24+24*(n/48-1) so n >= 45.7; n >= 0.9; we win on the first full + 48-byte block to set. */ + +#define MEMSET_BY_BLOCK_THRESHOLD (1 * 48) + +/* No name ambiguities in this file. */ +__asm__ (".syntax no_register_prefix"); + +void *memset(void *pdst, int c, unsigned int plen) +{ + /* Now we want the parameters in special registers. Make sure the + compiler does something usable with this. */ + + register char *return_dst __asm__ ("r10") = pdst; + register int n __asm__ ("r12") = plen; + register int lc __asm__ ("r11") = c; + + /* Most apps use memset sanely. Memsetting about 3..4 bytes or less get + penalized here compared to the generic implementation. */ + + /* This is fragile performancewise at best. Check with newer GCC + releases, if they compile cascaded "x |= x << 8" to sane code. */ + __asm__("movu.b %0,r13 \n\ + lslq 8,r13 \n\ + move.b %0,r13 \n\ + move.d r13,%0 \n\ + lslq 16,r13 \n\ + or.d r13,%0" + : "=r" (lc) /* Inputs. */ + : "0" (lc) /* Outputs. */ + : "r13"); /* Trash. */ + + { + register char *dst __asm__ ("r13") = pdst; + + if (((unsigned long) pdst & 3) != 0 + /* Oops! n = 0 must be a valid call, regardless of alignment. */ + && n >= 3) + { + if ((unsigned long) dst & 1) + { + *dst = (char) lc; + n--; + dst++; + } + + if ((unsigned long) dst & 2) + { + *(short *) dst = lc; + n -= 2; + dst += 2; + } + } + + /* Decide which setting method to use. */ + if (n >= MEMSET_BY_BLOCK_THRESHOLD) + { + /* It is not optimal to tell the compiler about clobbering any + registers; that will move the saving/restoring of those registers + to the function prologue/epilogue, and make non-block sizes + suboptimal. */ + __asm__ __volatile__ + ("\ + ;; GCC does promise correct register allocations, but let's \n\ + ;; make sure it keeps its promises. \n\ + .ifnc %0-%1-%4,$r13-$r12-$r11 \n\ + .error \"GCC reg alloc bug: %0-%1-%4 != $r13-$r12-$r11\" \n\ + .endif \n\ + \n\ + ;; Save the registers we'll clobber in the movem process \n\ + ;; on the stack. Don't mention them to gcc, it will only be \n\ + ;; upset. \n\ + subq 11*4,sp \n\ + movem r10,[sp] \n\ + \n\ + move.d r11,r0 \n\ + move.d r11,r1 \n\ + move.d r11,r2 \n\ + move.d r11,r3 \n\ + move.d r11,r4 \n\ + move.d r11,r5 \n\ + move.d r11,r6 \n\ + move.d r11,r7 \n\ + move.d r11,r8 \n\ + move.d r11,r9 \n\ + move.d r11,r10 \n\ + \n\ + ;; Now we've got this: \n\ + ;; r13 - dst \n\ + ;; r12 - n \n\ + \n\ + ;; Update n for the first loop \n\ + subq 12*4,r12 \n\ +0: \n\ +" +#ifdef __arch_common_v10_v32 + /* Cater to branch offset difference between v32 and v10. We + assume the branch below has an 8-bit offset. */ +" setf\n" +#endif +" subq 12*4,r12 \n\ + bge 0b \n\ + movem r11,[r13+] \n\ + \n\ + ;; Compensate for last loop underflowing n. \n\ + addq 12*4,r12 \n\ + \n\ + ;; Restore registers from stack. \n\ + movem [sp+],r10" + + /* Outputs. */ + : "=r" (dst), "=r" (n) + + /* Inputs. */ + : "0" (dst), "1" (n), "r" (lc)); + } + + /* An ad-hoc unroll, used for 4*12-1..16 bytes. */ + while (n >= 16) + { + *(long *) dst = lc; dst += 4; + *(long *) dst = lc; dst += 4; + *(long *) dst = lc; dst += 4; + *(long *) dst = lc; dst += 4; + n -= 16; + } + + switch (n) + { + case 0: + break; + + case 1: + *dst = (char) lc; + break; + + case 2: + *(short *) dst = (short) lc; + break; + + case 3: + *(short *) dst = (short) lc; dst += 2; + *dst = (char) lc; + break; + + case 4: + *(long *) dst = lc; + break; + + case 5: + *(long *) dst = lc; dst += 4; + *dst = (char) lc; + break; + + case 6: + *(long *) dst = lc; dst += 4; + *(short *) dst = (short) lc; + break; + + case 7: + *(long *) dst = lc; dst += 4; + *(short *) dst = (short) lc; dst += 2; + *dst = (char) lc; + break; + + case 8: + *(long *) dst = lc; dst += 4; + *(long *) dst = lc; + break; + + case 9: + *(long *) dst = lc; dst += 4; + *(long *) dst = lc; dst += 4; + *dst = (char) lc; + break; + + case 10: + *(long *) dst = lc; dst += 4; + *(long *) dst = lc; dst += 4; + *(short *) dst = (short) lc; + break; + + case 11: + *(long *) dst = lc; dst += 4; + *(long *) dst = lc; dst += 4; + *(short *) dst = (short) lc; dst += 2; + *dst = (char) lc; + break; + + case 12: + *(long *) dst = lc; dst += 4; + *(long *) dst = lc; dst += 4; + *(long *) dst = lc; + break; + + case 13: + *(long *) dst = lc; dst += 4; + *(long *) dst = lc; dst += 4; + *(long *) dst = lc; dst += 4; + *dst = (char) lc; + break; + + case 14: + *(long *) dst = lc; dst += 4; + *(long *) dst = lc; dst += 4; + *(long *) dst = lc; dst += 4; + *(short *) dst = (short) lc; + break; + + case 15: + *(long *) dst = lc; dst += 4; + *(long *) dst = lc; dst += 4; + *(long *) dst = lc; dst += 4; + *(short *) dst = (short) lc; dst += 2; + *dst = (char) lc; + break; + } + } + + return return_dst; +} +libc_hidden_def(memset) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/cris/strcpy.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/cris/strcpy.c new file mode 100644 index 00000000..40e6389b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/cris/strcpy.c @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2006-2007 Axis Communications AB + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +char *strcpy(char *dest, const char *src) +{ + char *ret = dest; + unsigned long himagic = 0x80808080L; + unsigned long lomagic = 0x01010101L; + + while ((unsigned long)src & (sizeof src - 1)) + { + if (!(*dest++ = *src++)) + { + return ret; + } + } + + while (1) + { + unsigned long value = *(unsigned long*)src; + unsigned long magic; + + src += sizeof (unsigned long); + + if ((magic = (value - lomagic) & himagic)) + { + if (magic & ~value) + { + break; + } + } + + *(unsigned long*)dest = value; + dest += sizeof (unsigned long); + } + + src -= sizeof (unsigned long); + + while ((*dest++ = *src++)) + { + } + + return ret; +} +libc_hidden_def(strcpy) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/cris/strncpy.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/cris/strncpy.c new file mode 100644 index 00000000..8d074071 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/cris/strncpy.c @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2006-2007 Axis Communications AB + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + + +char *strncpy(char *dest, const char *src, size_t count) +{ + char *ret = dest; + unsigned long himagic = 0x80808080L; + unsigned long lomagic = 0x01010101L; + + while (count && (unsigned long)src & (sizeof src - 1)) + { + count--; + if (!(*dest++ = *src++)) + { + goto finalize; + } + } + + while (count >= sizeof (unsigned long)) + { + unsigned long value = *(unsigned long*)src; + unsigned long magic; + + if ((magic = (value - lomagic) & himagic)) + { + if (magic & ~value) + { + break; + } + } + + *(unsigned long*)dest = value; + dest += sizeof (unsigned long); + src += sizeof (unsigned long); + count -= sizeof (unsigned long); + } + + while (count) + { + count--; + if (!(*dest++ = *src++)) + break; + } + +finalize: + if (count) + { + memset(dest, '\0', count); + } + + return ret; +} +libc_hidden_def(strncpy) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/dirname.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/dirname.c new file mode 100644 index 00000000..6265e562 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/dirname.c @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include "_string.h" +#include + +char *dirname(char *path) +{ + static const char null_or_empty_or_noslash[] = "."; + register char *s; + register char *last; + char *first; + + last = s = path; + + if (s != NULL) { + + LOOP: + while (*s && (*s != '/')) ++s; + first = s; + while (*s == '/') ++s; + if (*s) { + last = first; + goto LOOP; + } + + if (last == path) { + if (*last != '/') { + goto DOT; + } + if ((*++last == '/') && (last[1] == 0)) { + ++last; + } + } + *last = 0; + return path; + } + DOT: + return (char *) null_or_empty_or_noslash; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/ffs.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/ffs.c new file mode 100644 index 00000000..22efe4a1 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/ffs.c @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* ffsl,ffsll */ + +#include "_string.h" + + +int ffs(int i) +{ +#if 1 + /* inlined binary search method */ + char n = 1; +#if UINT_MAX == 0xffffU + /* nothing to do here -- just trying to avoiding possible problems */ +#elif UINT_MAX == 0xffffffffU + if (!(i & 0xffff)) { + n += 16; + i >>= 16; + } +#else +#error ffs needs rewriting! +#endif + + if (!(i & 0xff)) { + n += 8; + i >>= 8; + } + if (!(i & 0x0f)) { + n += 4; + i >>= 4; + } + if (!(i & 0x03)) { + n += 2; + i >>= 2; + } + return (i) ? (n + ((i+1) & 0x01)) : 0; + +#else + /* linear search -- slow, but small */ + int n; + + for (n = 0 ; i ; ++n) { + i >>= 1; + } + + return n; +#endif +} +libc_hidden_def(ffs) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/frv/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/frv/Makefile new file mode 100644 index 00000000..0a95346f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/frv/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir:=../../../ +top_builddir:=../../../ +all: objs +include $(top_builddir)Rules.mak +include ../Makefile.in +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/frv/memcpy.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/frv/memcpy.S new file mode 100644 index 00000000..ae843797 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/frv/memcpy.S @@ -0,0 +1,127 @@ +/* memcpy.S: optimised assembly memcpy + * + * Copyright (C) 2003, 2004 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include + + .text + .p2align 4 + +############################################################################### +# +# void *memcpy(void *to, const char *from, size_t count) +# +# - NOTE: must not use any stack. exception detection performs function return +# to caller's fixup routine, aborting the remainder of the copy +# +############################################################################### + .globl memcpy + .type memcpy,@function +memcpy: + or.p gr8,gr9,gr4 + orcc gr10,gr0,gr0,icc3 + or.p gr10,gr4,gr4 + beqlr icc3,#0 + + # optimise based on best common alignment for to, from & count + andicc.p gr4,#0x1f,gr0,icc0 + setlos #8,gr11 + andicc.p gr4,#0x0f,gr0,icc1 + beq icc0,#0,memcpy_32 + andicc.p gr4,#0x07,gr0,icc0 + beq icc1,#0,memcpy_16 + andicc.p gr4,#0x03,gr0,icc1 + beq icc0,#0,memcpy_8 + andicc.p gr4,#0x01,gr0,icc0 + beq icc1,#0,memcpy_4 + setlos.p #1,gr11 + beq icc0,#0,memcpy_2 + + # do byte by byte copy + sub.p gr8,gr11,gr3 + sub gr9,gr11,gr9 +0: ldubu.p @(gr9,gr11),gr4 + subicc gr10,#1,gr10,icc0 + stbu.p gr4,@(gr3,gr11) + bne icc0,#2,0b + bralr + + # do halfword by halfword copy +memcpy_2: + setlos #2,gr11 + sub.p gr8,gr11,gr3 + sub gr9,gr11,gr9 +0: lduhu.p @(gr9,gr11),gr4 + subicc gr10,#2,gr10,icc0 + sthu.p gr4,@(gr3,gr11) + bne icc0,#2,0b + bralr + + # do word by word copy +memcpy_4: + setlos #4,gr11 + sub.p gr8,gr11,gr3 + sub gr9,gr11,gr9 +0: ldu.p @(gr9,gr11),gr4 + subicc gr10,#4,gr10,icc0 + stu.p gr4,@(gr3,gr11) + bne icc0,#2,0b + bralr + + # do double-word by double-word copy +memcpy_8: + sub.p gr8,gr11,gr3 + sub gr9,gr11,gr9 +0: lddu.p @(gr9,gr11),gr4 + subicc gr10,#8,gr10,icc0 + stdu.p gr4,@(gr3,gr11) + bne icc0,#2,0b + bralr + + # do quad-word by quad-word copy +memcpy_16: + sub.p gr8,gr11,gr3 + sub gr9,gr11,gr9 +0: lddu @(gr9,gr11),gr4 + lddu.p @(gr9,gr11),gr6 + subicc gr10,#16,gr10,icc0 + stdu gr4,@(gr3,gr11) + stdu.p gr6,@(gr3,gr11) + bne icc0,#2,0b + bralr + + # do eight-word by eight-word copy +memcpy_32: + sub.p gr8,gr11,gr3 + sub gr9,gr11,gr9 +0: lddu @(gr9,gr11),gr4 + lddu @(gr9,gr11),gr6 + lddu @(gr9,gr11),gr12 + lddu.p @(gr9,gr11),gr14 + subicc gr10,#32,gr10,icc0 + stdu gr4,@(gr3,gr11) + stdu gr6,@(gr3,gr11) + stdu gr12,@(gr3,gr11) + stdu.p gr14,@(gr3,gr11) + bne icc0,#2,0b + bralr + + .size memcpy, .-memcpy + +libc_hidden_def(memcpy) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/frv/memset.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/frv/memset.S new file mode 100644 index 00000000..a3e76c49 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/frv/memset.S @@ -0,0 +1,157 @@ +/* memset.S: optimised assembly memset + * + * Copyright (C) 2003, 2004 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include + + .text + .p2align 4 + +############################################################################### +# +# void *memset(void *p, char ch, size_t count) +# +# - NOTE: must not use any stack. exception detection performs function return +# to caller's fixup routine, aborting the remainder of the set +# GR4, GR7, GR8, and GR11 must be managed +# +############################################################################### + .globl memset + .type memset,@function +memset: + orcc.p gr10,gr0,gr5,icc3 ; GR5 = count + andi gr9,#0xff,gr9 + or.p gr8,gr0,gr4 ; GR4 = address + beqlr icc3,#0 + + # conditionally write a byte to 2b-align the address + setlos.p #1,gr6 + andicc gr4,#1,gr0,icc0 + ckne icc0,cc7 + cstb.p gr9,@(gr4,gr0) ,cc7,#1 + csubcc gr5,gr6,gr5 ,cc7,#1 ; also set ICC3 + cadd.p gr4,gr6,gr4 ,cc7,#1 + beqlr icc3,#0 + + # conditionally write a word to 4b-align the address + andicc.p gr4,#2,gr0,icc0 + subicc gr5,#2,gr0,icc1 + setlos.p #2,gr6 + ckne icc0,cc7 + slli.p gr9,#8,gr12 ; need to double up the pattern + cknc icc1,cc5 + or.p gr9,gr12,gr12 + andcr cc7,cc5,cc7 + + csth.p gr12,@(gr4,gr0) ,cc7,#1 + csubcc gr5,gr6,gr5 ,cc7,#1 ; also set ICC3 + cadd.p gr4,gr6,gr4 ,cc7,#1 + beqlr icc3,#0 + + # conditionally write a dword to 8b-align the address + andicc.p gr4,#4,gr0,icc0 + subicc gr5,#4,gr0,icc1 + setlos.p #4,gr6 + ckne icc0,cc7 + slli.p gr12,#16,gr13 ; need to quadruple-up the pattern + cknc icc1,cc5 + or.p gr13,gr12,gr12 + andcr cc7,cc5,cc7 + + cst.p gr12,@(gr4,gr0) ,cc7,#1 + csubcc gr5,gr6,gr5 ,cc7,#1 ; also set ICC3 + cadd.p gr4,gr6,gr4 ,cc7,#1 + beqlr icc3,#0 + + or.p gr12,gr12,gr13 ; need to octuple-up the pattern + + # the address is now 8b-aligned - loop around writing 64b chunks + setlos #8,gr7 + subi.p gr4,#8,gr4 ; store with update index does weird stuff + setlos #64,gr6 + + subicc gr5,#64,gr0,icc0 +0: cknc icc0,cc7 + cstdu gr12,@(gr4,gr7) ,cc7,#1 + cstdu gr12,@(gr4,gr7) ,cc7,#1 + cstdu gr12,@(gr4,gr7) ,cc7,#1 + cstdu gr12,@(gr4,gr7) ,cc7,#1 + cstdu gr12,@(gr4,gr7) ,cc7,#1 + cstdu.p gr12,@(gr4,gr7) ,cc7,#1 + csubcc gr5,gr6,gr5 ,cc7,#1 ; also set ICC3 + cstdu.p gr12,@(gr4,gr7) ,cc7,#1 + subicc gr5,#64,gr0,icc0 + cstdu.p gr12,@(gr4,gr7) ,cc7,#1 + beqlr icc3,#0 + bnc icc0,#2,0b + + # now do 32-byte remnant + subicc.p gr5,#32,gr0,icc0 + setlos #32,gr6 + cknc icc0,cc7 + cstdu.p gr12,@(gr4,gr7) ,cc7,#1 + csubcc gr5,gr6,gr5 ,cc7,#1 ; also set ICC3 + cstdu.p gr12,@(gr4,gr7) ,cc7,#1 + setlos #16,gr6 + cstdu.p gr12,@(gr4,gr7) ,cc7,#1 + subicc gr5,#16,gr0,icc0 + cstdu.p gr12,@(gr4,gr7) ,cc7,#1 + beqlr icc3,#0 + + # now do 16-byte remnant + cknc icc0,cc7 + cstdu.p gr12,@(gr4,gr7) ,cc7,#1 + csubcc gr5,gr6,gr5 ,cc7,#1 ; also set ICC3 + cstdu.p gr12,@(gr4,gr7) ,cc7,#1 + beqlr icc3,#0 + + # now do 8-byte remnant + subicc gr5,#8,gr0,icc1 + cknc icc1,cc7 + cstdu.p gr12,@(gr4,gr7) ,cc7,#1 + csubcc gr5,gr7,gr5 ,cc7,#1 ; also set ICC3 + setlos.p #4,gr7 + beqlr icc3,#0 + + # now do 4-byte remnant + subicc gr5,#4,gr0,icc0 + addi.p gr4,#4,gr4 + cknc icc0,cc7 + cstu.p gr12,@(gr4,gr7) ,cc7,#1 + csubcc gr5,gr7,gr5 ,cc7,#1 ; also set ICC3 + subicc.p gr5,#2,gr0,icc1 + beqlr icc3,#0 + + # now do 2-byte remnant + setlos #2,gr7 + addi.p gr4,#2,gr4 + cknc icc1,cc7 + csthu.p gr12,@(gr4,gr7) ,cc7,#1 + csubcc gr5,gr7,gr5 ,cc7,#1 ; also set ICC3 + subicc.p gr5,#1,gr0,icc0 + beqlr icc3,#0 + + # now do 1-byte remnant + setlos #0,gr7 + addi.p gr4,#2,gr4 + cknc icc0,cc7 + cstb.p gr12,@(gr4,gr0) ,cc7,#1 + bralr + .size memset, .-memset + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/Makefile new file mode 100644 index 00000000..0a95346f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir:=../../../ +top_builddir:=../../../ +all: objs +include $(top_builddir)Rules.mak +include ../Makefile.in +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/_memcpy_fwd.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/_memcpy_fwd.c new file mode 100644 index 00000000..470165a5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/_memcpy_fwd.c @@ -0,0 +1,185 @@ +/* _wordcopy_fwd_aligned -- Copy block beginning at SRCP to + block beginning at DSTP with LEN `op_t' words (not LEN bytes!). + Both SRCP and DSTP should be aligned for memory operations on `op_t's. */ + +static void _wordcopy_fwd_aligned (long int dstp, long int srcp, size_t len) +{ + op_t a0, a1; + + switch (len % 8) + { + case 2: + a0 = ((op_t *) srcp)[0]; + srcp -= 6 * OPSIZ; + dstp -= 7 * OPSIZ; + len += 6; + goto do1; + case 3: + a1 = ((op_t *) srcp)[0]; + srcp -= 5 * OPSIZ; + dstp -= 6 * OPSIZ; + len += 5; + goto do2; + case 4: + a0 = ((op_t *) srcp)[0]; + srcp -= 4 * OPSIZ; + dstp -= 5 * OPSIZ; + len += 4; + goto do3; + case 5: + a1 = ((op_t *) srcp)[0]; + srcp -= 3 * OPSIZ; + dstp -= 4 * OPSIZ; + len += 3; + goto do4; + case 6: + a0 = ((op_t *) srcp)[0]; + srcp -= 2 * OPSIZ; + dstp -= 3 * OPSIZ; + len += 2; + goto do5; + case 7: + a1 = ((op_t *) srcp)[0]; + srcp -= 1 * OPSIZ; + dstp -= 2 * OPSIZ; + len += 1; + goto do6; + + case 0: + if (OP_T_THRES <= 3 * OPSIZ && len == 0) + return; + a0 = ((op_t *) srcp)[0]; + srcp -= 0 * OPSIZ; + dstp -= 1 * OPSIZ; + goto do7; + case 1: + a1 = ((op_t *) srcp)[0]; + srcp -=-1 * OPSIZ; + dstp -= 0 * OPSIZ; + len -= 1; + if (OP_T_THRES <= 3 * OPSIZ && len == 0) + goto do0; + goto do8; /* No-op. */ + } + + do + { + do8: + a0 = ((op_t *) srcp)[0]; + ((op_t *) dstp)[0] = a1; + do7: + a1 = ((op_t *) srcp)[1]; + ((op_t *) dstp)[1] = a0; + do6: + a0 = ((op_t *) srcp)[2]; + ((op_t *) dstp)[2] = a1; + do5: + a1 = ((op_t *) srcp)[3]; + ((op_t *) dstp)[3] = a0; + do4: + a0 = ((op_t *) srcp)[4]; + ((op_t *) dstp)[4] = a1; + do3: + a1 = ((op_t *) srcp)[5]; + ((op_t *) dstp)[5] = a0; + do2: + a0 = ((op_t *) srcp)[6]; + ((op_t *) dstp)[6] = a1; + do1: + a1 = ((op_t *) srcp)[7]; + ((op_t *) dstp)[7] = a0; + + srcp += 8 * OPSIZ; + dstp += 8 * OPSIZ; + len -= 8; + } + while (len != 0); + + /* This is the right position for do0. Please don't move + it into the loop. */ + do0: + ((op_t *) dstp)[0] = a1; +} + +/* _wordcopy_fwd_dest_aligned -- Copy block beginning at SRCP to + block beginning at DSTP with LEN `op_t' words (not LEN bytes!). + DSTP should be aligned for memory operations on `op_t's, but SRCP must + *not* be aligned. */ + +static void _wordcopy_fwd_dest_aligned (long int dstp, long int srcp, size_t len) +{ + op_t a0, a1, a2, a3; + int sh_1, sh_2; + + /* Calculate how to shift a word read at the memory operation + aligned srcp to make it aligned for copy. */ + + sh_1 = 8 * (srcp % OPSIZ); + sh_2 = 8 * OPSIZ - sh_1; + + /* Make SRCP aligned by rounding it down to the beginning of the `op_t' + it points in the middle of. */ + srcp &= -OPSIZ; + + switch (len % 4) + { + case 2: + a1 = ((op_t *) srcp)[0]; + a2 = ((op_t *) srcp)[1]; + srcp -= 1 * OPSIZ; + dstp -= 3 * OPSIZ; + len += 2; + goto do1; + case 3: + a0 = ((op_t *) srcp)[0]; + a1 = ((op_t *) srcp)[1]; + srcp -= 0 * OPSIZ; + dstp -= 2 * OPSIZ; + len += 1; + goto do2; + case 0: + if (OP_T_THRES <= 3 * OPSIZ && len == 0) + return; + a3 = ((op_t *) srcp)[0]; + a0 = ((op_t *) srcp)[1]; + srcp -=-1 * OPSIZ; + dstp -= 1 * OPSIZ; + len += 0; + goto do3; + case 1: + a2 = ((op_t *) srcp)[0]; + a3 = ((op_t *) srcp)[1]; + srcp -=-2 * OPSIZ; + dstp -= 0 * OPSIZ; + len -= 1; + if (OP_T_THRES <= 3 * OPSIZ && len == 0) + goto do0; + goto do4; /* No-op. */ + } + + do + { + do4: + a0 = ((op_t *) srcp)[0]; + ((op_t *) dstp)[0] = MERGE (a2, sh_1, a3, sh_2); + do3: + a1 = ((op_t *) srcp)[1]; + ((op_t *) dstp)[1] = MERGE (a3, sh_1, a0, sh_2); + do2: + a2 = ((op_t *) srcp)[2]; + ((op_t *) dstp)[2] = MERGE (a0, sh_1, a1, sh_2); + do1: + a3 = ((op_t *) srcp)[3]; + ((op_t *) dstp)[3] = MERGE (a1, sh_1, a2, sh_2); + + srcp += 4 * OPSIZ; + dstp += 4 * OPSIZ; + len -= 4; + } + while (len != 0); + + /* This is the right position for do0. Please don't move + it into the loop. */ + do0: + ((op_t *) dstp)[0] = MERGE (a2, sh_1, a3, sh_2); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/memchr.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/memchr.c new file mode 100644 index 00000000..d5cd0005 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/memchr.c @@ -0,0 +1,175 @@ +/* Copyright (C) 1991,93,96,97,99,2000,2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Based on strlen implementation by Torbjorn Granlund (tege@sics.se), + with help from Dan Sahlin (dan@sics.se) and + commentary by Jim Blandy (jimb@ai.mit.edu); + adaptation to memchr suggested by Dick Karpinski (dick@cca.ucsf.edu), + and implemented by Roland McGrath (roland@ai.mit.edu). + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +#include "memcopy.h" + +#define LONG_MAX_32_BITS 2147483647 + +/* Search no more than N bytes of S for C. */ +#undef memchr +void *memchr (const void * s, int c_in, size_t n) +{ + const unsigned char *char_ptr; + const unsigned long int *longword_ptr; + unsigned long int longword, magic_bits, charmask; + unsigned reg_char c; + + c = (unsigned char) c_in; + + /* Handle the first few characters by reading one character at a time. + Do this until CHAR_PTR is aligned on a longword boundary. */ + for (char_ptr = (const unsigned char *) s; + n > 0 && ((unsigned long int) char_ptr + & (sizeof (longword) - 1)) != 0; + --n, ++char_ptr) + if (*char_ptr == c) + return (void *) char_ptr; + + /* All these elucidatory comments refer to 4-byte longwords, + but the theory applies equally well to 8-byte longwords. */ + + longword_ptr = (unsigned long int *) char_ptr; + + /* Bits 31, 24, 16, and 8 of this number are zero. Call these bits + the "holes." Note that there is a hole just to the left of + each byte, with an extra at the end: + + bits: 01111110 11111110 11111110 11111111 + bytes: AAAAAAAA BBBBBBBB CCCCCCCC DDDDDDDD + + The 1-bits make sure that carries propagate to the next 0-bit. + The 0-bits provide holes for carries to fall into. */ + + if (sizeof (longword) != 4 && sizeof (longword) != 8) + abort (); + +#if LONG_MAX <= LONG_MAX_32_BITS + magic_bits = 0x7efefeff; +#else + magic_bits = ((unsigned long int) 0x7efefefe << 32) | 0xfefefeff; +#endif + + /* Set up a longword, each of whose bytes is C. */ + charmask = c | (c << 8); + charmask |= charmask << 16; +#if LONG_MAX > LONG_MAX_32_BITS + charmask |= charmask << 32; +#endif + + /* Instead of the traditional loop which tests each character, + we will test a longword at a time. The tricky part is testing + if *any of the four* bytes in the longword in question are zero. */ + while (n >= sizeof (longword)) + { + /* We tentatively exit the loop if adding MAGIC_BITS to + LONGWORD fails to change any of the hole bits of LONGWORD. + + 1) Is this safe? Will it catch all the zero bytes? + Suppose there is a byte with all zeros. Any carry bits + propagating from its left will fall into the hole at its + least significant bit and stop. Since there will be no + carry from its most significant bit, the LSB of the + byte to the left will be unchanged, and the zero will be + detected. + + 2) Is this worthwhile? Will it ignore everything except + zero bytes? Suppose every byte of LONGWORD has a bit set + somewhere. There will be a carry into bit 8. If bit 8 + is set, this will carry into bit 16. If bit 8 is clear, + one of bits 9-15 must be set, so there will be a carry + into bit 16. Similarly, there will be a carry into bit + 24. If one of bits 24-30 is set, there will be a carry + into bit 31, so all of the hole bits will be changed. + + The one misfire occurs when bits 24-30 are clear and bit + 31 is set; in this case, the hole at bit 31 is not + changed. If we had access to the processor carry flag, + we could close this loophole by putting the fourth hole + at bit 32! + + So it ignores everything except 128's, when they're aligned + properly. + + 3) But wait! Aren't we looking for C, not zero? + Good point. So what we do is XOR LONGWORD with a longword, + each of whose bytes is C. This turns each byte that is C + into a zero. */ + + longword = *longword_ptr++ ^ charmask; + + /* Add MAGIC_BITS to LONGWORD. */ + if ((((longword + magic_bits) + + /* Set those bits that were unchanged by the addition. */ + ^ ~longword) + + /* Look at only the hole bits. If any of the hole bits + are unchanged, most likely one of the bytes was a + zero. */ + & ~magic_bits) != 0) + { + /* Which of the bytes was C? If none of them were, it was + a misfire; continue the search. */ + + const unsigned char *cp = (const unsigned char *) (longword_ptr - 1); + + if (cp[0] == c) + return (void *) cp; + if (cp[1] == c) + return (void *) &cp[1]; + if (cp[2] == c) + return (void *) &cp[2]; + if (cp[3] == c) + return (void *) &cp[3]; +#if LONG_MAX > 2147483647 + if (cp[4] == c) + return (void *) &cp[4]; + if (cp[5] == c) + return (void *) &cp[5]; + if (cp[6] == c) + return (void *) &cp[6]; + if (cp[7] == c) + return (void *) &cp[7]; +#endif + } + + n -= sizeof (longword); + } + + char_ptr = (const unsigned char *) longword_ptr; + + while (n-- > 0) + { + if (*char_ptr == c) + return (void *) char_ptr; + else + ++char_ptr; + } + + return 0; +} +libc_hidden_weak(memchr) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/memcmp.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/memcmp.c new file mode 100644 index 00000000..62600cd0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/memcmp.c @@ -0,0 +1,315 @@ +/* Copyright (C) 1991,1993,1995,1997,1998,2003,2004 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Torbjorn Granlund (tege@sics.se). + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include "memcopy.h" + + +#include + +#if __BYTE_ORDER == __BIG_ENDIAN +# define CMP_LT_OR_GT(a, b) ((a) > (b) ? 1 : -1) +#else +# define CMP_LT_OR_GT(a, b) memcmp_bytes ((a), (b)) +#endif + +/* BE VERY CAREFUL IF YOU CHANGE THIS CODE! */ + +/* The strategy of this memcmp is: + + 1. Compare bytes until one of the block pointers is aligned. + + 2. Compare using memcmp_common_alignment or + memcmp_not_common_alignment, regarding the alignment of the other + block after the initial byte operations. The maximum number of + full words (of type op_t) are compared in this way. + + 3. Compare the few remaining bytes. */ + +#if __BYTE_ORDER != __BIG_ENDIAN +/* memcmp_bytes -- Compare A and B bytewise in the byte order of the machine. + A and B are known to be different. + This is needed only on little-endian machines. */ + +static __inline__ int +memcmp_bytes (op_t a, op_t b) +{ + long int srcp1 = (long int) &a; + long int srcp2 = (long int) &b; + op_t a0, b0; + + do + { + a0 = ((byte *) srcp1)[0]; + b0 = ((byte *) srcp2)[0]; + srcp1 += 1; + srcp2 += 1; + } + while (a0 == b0); + return a0 - b0; +} +#endif + +/* memcmp_common_alignment -- Compare blocks at SRCP1 and SRCP2 with LEN `op_t' + objects (not LEN bytes!). Both SRCP1 and SRCP2 should be aligned for + memory operations on `op_t's. */ +static int +memcmp_common_alignment (long int srcp1, long int srcp2, size_t len) +{ + op_t a0, a1; + op_t b0, b1; + + switch (len % 4) + { + default: /* Avoid warning about uninitialized local variables. */ + case 2: + a0 = ((op_t *) srcp1)[0]; + b0 = ((op_t *) srcp2)[0]; + srcp1 -= 2 * OPSIZ; + srcp2 -= 2 * OPSIZ; + len += 2; + goto do1; + case 3: + a1 = ((op_t *) srcp1)[0]; + b1 = ((op_t *) srcp2)[0]; + srcp1 -= OPSIZ; + srcp2 -= OPSIZ; + len += 1; + goto do2; + case 0: + if (OP_T_THRES <= 3 * OPSIZ && len == 0) + return 0; + a0 = ((op_t *) srcp1)[0]; + b0 = ((op_t *) srcp2)[0]; + goto do3; + case 1: + a1 = ((op_t *) srcp1)[0]; + b1 = ((op_t *) srcp2)[0]; + srcp1 += OPSIZ; + srcp2 += OPSIZ; + len -= 1; + if (OP_T_THRES <= 3 * OPSIZ && len == 0) + goto do0; + /* Fall through. */ + } + + do + { + a0 = ((op_t *) srcp1)[0]; + b0 = ((op_t *) srcp2)[0]; + if (a1 != b1) + return CMP_LT_OR_GT (a1, b1); + + do3: + a1 = ((op_t *) srcp1)[1]; + b1 = ((op_t *) srcp2)[1]; + if (a0 != b0) + return CMP_LT_OR_GT (a0, b0); + + do2: + a0 = ((op_t *) srcp1)[2]; + b0 = ((op_t *) srcp2)[2]; + if (a1 != b1) + return CMP_LT_OR_GT (a1, b1); + + do1: + a1 = ((op_t *) srcp1)[3]; + b1 = ((op_t *) srcp2)[3]; + if (a0 != b0) + return CMP_LT_OR_GT (a0, b0); + + srcp1 += 4 * OPSIZ; + srcp2 += 4 * OPSIZ; + len -= 4; + } + while (len != 0); + + /* This is the right position for do0. Please don't move + it into the loop. */ + do0: + if (a1 != b1) + return CMP_LT_OR_GT (a1, b1); + return 0; +} + +/* memcmp_not_common_alignment -- Compare blocks at SRCP1 and SRCP2 with LEN + `op_t' objects (not LEN bytes!). SRCP2 should be aligned for memory + operations on `op_t', but SRCP1 *should be unaligned*. */ +static int +memcmp_not_common_alignment (long int srcp1, long int srcp2, size_t len) +{ + op_t a0, a1, a2, a3; + op_t b0, b1, b2, b3; + op_t x; + int shl, shr; + + /* Calculate how to shift a word read at the memory operation + aligned srcp1 to make it aligned for comparison. */ + + shl = 8 * (srcp1 % OPSIZ); + shr = 8 * OPSIZ - shl; + + /* Make SRCP1 aligned by rounding it down to the beginning of the `op_t' + it points in the middle of. */ + srcp1 &= -OPSIZ; + + switch (len % 4) + { + default: /* Avoid warning about uninitialized local variables. */ + case 2: + a1 = ((op_t *) srcp1)[0]; + a2 = ((op_t *) srcp1)[1]; + b2 = ((op_t *) srcp2)[0]; + srcp1 -= 1 * OPSIZ; + srcp2 -= 2 * OPSIZ; + len += 2; + goto do1; + case 3: + a0 = ((op_t *) srcp1)[0]; + a1 = ((op_t *) srcp1)[1]; + b1 = ((op_t *) srcp2)[0]; + srcp2 -= 1 * OPSIZ; + len += 1; + goto do2; + case 0: + if (OP_T_THRES <= 3 * OPSIZ && len == 0) + return 0; + a3 = ((op_t *) srcp1)[0]; + a0 = ((op_t *) srcp1)[1]; + b0 = ((op_t *) srcp2)[0]; + srcp1 += 1 * OPSIZ; + goto do3; + case 1: + a2 = ((op_t *) srcp1)[0]; + a3 = ((op_t *) srcp1)[1]; + b3 = ((op_t *) srcp2)[0]; + srcp1 += 2 * OPSIZ; + srcp2 += 1 * OPSIZ; + len -= 1; + if (OP_T_THRES <= 3 * OPSIZ && len == 0) + goto do0; + /* Fall through. */ + } + + do + { + a0 = ((op_t *) srcp1)[0]; + b0 = ((op_t *) srcp2)[0]; + x = MERGE(a2, shl, a3, shr); + if (x != b3) + return CMP_LT_OR_GT (x, b3); + + do3: + a1 = ((op_t *) srcp1)[1]; + b1 = ((op_t *) srcp2)[1]; + x = MERGE(a3, shl, a0, shr); + if (x != b0) + return CMP_LT_OR_GT (x, b0); + + do2: + a2 = ((op_t *) srcp1)[2]; + b2 = ((op_t *) srcp2)[2]; + x = MERGE(a0, shl, a1, shr); + if (x != b1) + return CMP_LT_OR_GT (x, b1); + + do1: + a3 = ((op_t *) srcp1)[3]; + b3 = ((op_t *) srcp2)[3]; + x = MERGE(a1, shl, a2, shr); + if (x != b2) + return CMP_LT_OR_GT (x, b2); + + srcp1 += 4 * OPSIZ; + srcp2 += 4 * OPSIZ; + len -= 4; + } + while (len != 0); + + /* This is the right position for do0. Please don't move + it into the loop. */ + do0: + x = MERGE(a2, shl, a3, shr); + if (x != b3) + return CMP_LT_OR_GT (x, b3); + return 0; +} + +int +memcmp (const __ptr_t s1, const __ptr_t s2, size_t len) +{ + op_t a0; + op_t b0; + long int srcp1 = (long int) s1; + long int srcp2 = (long int) s2; + op_t res; + + if (len >= OP_T_THRES) + { + /* There are at least some bytes to compare. No need to test + for LEN == 0 in this alignment loop. */ + while (srcp2 % OPSIZ != 0) + { + a0 = ((byte *) srcp1)[0]; + b0 = ((byte *) srcp2)[0]; + srcp1 += 1; + srcp2 += 1; + res = a0 - b0; + if (res != 0) + return res; + len -= 1; + } + + /* SRCP2 is now aligned for memory operations on `op_t'. + SRCP1 alignment determines if we can do a simple, + aligned compare or need to shuffle bits. */ + + if (srcp1 % OPSIZ == 0) + res = memcmp_common_alignment (srcp1, srcp2, len / OPSIZ); + else + res = memcmp_not_common_alignment (srcp1, srcp2, len / OPSIZ); + if (res != 0) + return res; + + /* Number of bytes remaining in the interval [0..OPSIZ-1]. */ + srcp1 += len & -OPSIZ; + srcp2 += len & -OPSIZ; + len %= OPSIZ; + } + + /* There are just a few bytes to compare. Use byte memory operations. */ + while (len != 0) + { + a0 = ((byte *) srcp1)[0]; + b0 = ((byte *) srcp2)[0]; + srcp1 += 1; + srcp2 += 1; + res = a0 - b0; + if (res != 0) + return res; + len -= 1; + } + + return 0; +} +libc_hidden_weak(memcmp) +#ifdef __UCLIBC_SUSV3_LEGACY__ +strong_alias(memcmp,bcmp) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/memcopy.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/memcopy.h new file mode 100644 index 00000000..df1ba9a9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/memcopy.h @@ -0,0 +1,150 @@ +/* memcopy.h -- definitions for memory copy functions. Generic C version. + Copyright (C) 1991, 1992, 1993, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Torbjorn Granlund (tege@sics.se). + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* The strategy of the memory functions is: + + 1. Copy bytes until the destination pointer is aligned. + + 2. Copy words in unrolled loops. If the source and destination + are not aligned in the same way, use word memory operations, + but shift and merge two read words before writing. + + 3. Copy the few remaining bytes. + + This is fast on processors that have at least 10 registers for + allocation by GCC, and that can access memory at reg+const in one + instruction. + + I made an "exhaustive" test of this memmove when I wrote it, + exhaustive in the sense that I tried all alignment and length + combinations, with and without overlap. */ + +#include +#include + +/* The macros defined in this file are: + + BYTE_COPY_FWD(dst_beg_ptr, src_beg_ptr, nbytes_to_copy) + + BYTE_COPY_BWD(dst_end_ptr, src_end_ptr, nbytes_to_copy) + + WORD_COPY_FWD(dst_beg_ptr, src_beg_ptr, nbytes_remaining, nbytes_to_copy) + + WORD_COPY_BWD(dst_end_ptr, src_end_ptr, nbytes_remaining, nbytes_to_copy) + + MERGE(old_word, sh_1, new_word, sh_2) + [I fail to understand. I feel stupid. --roland] +*/ + +/* Type to use for aligned memory operations. + This should normally be the biggest type supported by a single load + and store. */ +#define op_t unsigned long int +#define OPSIZ (sizeof(op_t)) + +/* Type to use for unaligned operations. */ +typedef unsigned char byte; + +/* Optimal type for storing bytes in registers. */ +#define reg_char char + +#if __BYTE_ORDER == __LITTLE_ENDIAN +#define MERGE(w0, sh_1, w1, sh_2) (((w0) >> (sh_1)) | ((w1) << (sh_2))) +#endif +#if __BYTE_ORDER == __BIG_ENDIAN +#define MERGE(w0, sh_1, w1, sh_2) (((w0) << (sh_1)) | ((w1) >> (sh_2))) +#endif + +/* Copy exactly NBYTES bytes from SRC_BP to DST_BP, + without any assumptions about alignment of the pointers. */ +#define BYTE_COPY_FWD(dst_bp, src_bp, nbytes) \ + do \ + { \ + size_t __nbytes = (nbytes); \ + while (__nbytes > 0) \ + { \ + byte __x = ((byte *) src_bp)[0]; \ + src_bp += 1; \ + __nbytes -= 1; \ + ((byte *) dst_bp)[0] = __x; \ + dst_bp += 1; \ + } \ + } while (0) + +/* Copy exactly NBYTES_TO_COPY bytes from SRC_END_PTR to DST_END_PTR, + beginning at the bytes right before the pointers and continuing towards + smaller addresses. Don't assume anything about alignment of the + pointers. */ +#define BYTE_COPY_BWD(dst_ep, src_ep, nbytes) \ + do \ + { \ + size_t __nbytes = (nbytes); \ + while (__nbytes > 0) \ + { \ + byte __x; \ + src_ep -= 1; \ + __x = ((byte *) src_ep)[0]; \ + dst_ep -= 1; \ + __nbytes -= 1; \ + ((byte *) dst_ep)[0] = __x; \ + } \ + } while (0) + +/* Copy *up to* NBYTES bytes from SRC_BP to DST_BP, with + the assumption that DST_BP is aligned on an OPSIZ multiple. If + not all bytes could be easily copied, store remaining number of bytes + in NBYTES_LEFT, otherwise store 0. */ +/* extern void _wordcopy_fwd_aligned __P ((long int, long int, size_t)); */ +/* extern void _wordcopy_fwd_dest_aligned __P ((long int, long int, size_t)); */ +#define WORD_COPY_FWD(dst_bp, src_bp, nbytes_left, nbytes) \ + do \ + { \ + if (src_bp % OPSIZ == 0) \ + _wordcopy_fwd_aligned (dst_bp, src_bp, (nbytes) / OPSIZ); \ + else \ + _wordcopy_fwd_dest_aligned (dst_bp, src_bp, (nbytes) / OPSIZ); \ + src_bp += (nbytes) & -OPSIZ; \ + dst_bp += (nbytes) & -OPSIZ; \ + (nbytes_left) = (nbytes) % OPSIZ; \ + } while (0) + +/* Copy *up to* NBYTES_TO_COPY bytes from SRC_END_PTR to DST_END_PTR, + beginning at the words (of type op_t) right before the pointers and + continuing towards smaller addresses. May take advantage of that + DST_END_PTR is aligned on an OPSIZ multiple. If not all bytes could be + easily copied, store remaining number of bytes in NBYTES_REMAINING, + otherwise store 0. */ +/* extern void _wordcopy_bwd_aligned __P ((long int, long int, size_t)); */ +/* extern void _wordcopy_bwd_dest_aligned __P ((long int, long int, size_t)); */ +#define WORD_COPY_BWD(dst_ep, src_ep, nbytes_left, nbytes) \ + do \ + { \ + if (src_ep % OPSIZ == 0) \ + _wordcopy_bwd_aligned (dst_ep, src_ep, (nbytes) / OPSIZ); \ + else \ + _wordcopy_bwd_dest_aligned (dst_ep, src_ep, (nbytes) / OPSIZ); \ + src_ep -= (nbytes) & -OPSIZ; \ + dst_ep -= (nbytes) & -OPSIZ; \ + (nbytes_left) = (nbytes) % OPSIZ; \ + } while (0) + + +/* Threshold value for when to enter the unrolled loops. */ +#define OP_T_THRES 16 diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/memcpy.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/memcpy.c new file mode 100644 index 00000000..7dd7118f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/memcpy.c @@ -0,0 +1,61 @@ +/* Copy memory to memory until the specified number of bytes + has been copied. Overlap is NOT handled correctly. + Copyright (C) 1991, 1997, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Torbjorn Granlund (tege@sics.se). + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include "memcopy.h" +#include "pagecopy.h" +#include "_memcpy_fwd.c" + + +void *memcpy (void *dstpp, const void *srcpp, size_t len) +{ + unsigned long int dstp = (long int) dstpp; + unsigned long int srcp = (long int) srcpp; + + /* Copy from the beginning to the end. */ + + /* If there not too few bytes to copy, use word copy. */ + if (len >= OP_T_THRES) + { + /* Copy just a few bytes to make DSTP aligned. */ + len -= (-dstp) % OPSIZ; + BYTE_COPY_FWD (dstp, srcp, (-dstp) % OPSIZ); + + /* Copy whole pages from SRCP to DSTP by virtual address manipulation, + as much as possible. */ + + PAGE_COPY_FWD_MAYBE (dstp, srcp, len, len); + + /* Copy from SRCP to DSTP taking advantage of the known alignment of + DSTP. Number of bytes remaining is put in the third argument, + i.e. in LEN. This number may vary from machine to machine. */ + + WORD_COPY_FWD (dstp, srcp, len, len); + + /* Fall out and copy the tail. */ + } + + /* There are just a few bytes to copy. Use byte memory operations. */ + BYTE_COPY_FWD (dstp, srcp, len); + + return dstpp; +} +libc_hidden_weak(memcpy) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/memmem.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/memmem.c new file mode 100644 index 00000000..0fccac77 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/memmem.c @@ -0,0 +1,52 @@ +/* Copyright (C) 1991,92,93,94,96,97,98,2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +#ifdef __USE_GNU + +/* Return the first occurrence of NEEDLE in HAYSTACK. */ +void *memmem (const void *haystack, size_t haystack_len, + const void *needle, size_t needle_len) +{ + const char *begin; + const char *const last_possible + = (const char *) haystack + haystack_len - needle_len; + + if (needle_len == 0) + /* The first occurrence of the empty string is deemed to occur at + the beginning of the string. */ + return (void *) haystack; + + /* Sanity check, otherwise the loop might search through the whole + memory. */ + if (__builtin_expect (haystack_len < needle_len, 0)) + return NULL; + + for (begin = (const char *) haystack; begin <= last_possible; ++begin) + if (begin[0] == ((const char *) needle)[0] && + !memcmp ((const void *) &begin[1], + (const void *) ((const char *) needle + 1), + needle_len - 1)) + return (void *) begin; + + return NULL; +} +libc_hidden_def(memmem) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/memmove.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/memmove.c new file mode 100644 index 00000000..b564a7d1 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/memmove.c @@ -0,0 +1,289 @@ +/* Copy memory to memory until the specified number of bytes + has been copied. Overlap is handled correctly. + Copyright (C) 1991, 1995, 1996, 1997, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Torbjorn Granlund (tege@sics.se). + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#include "memcopy.h" +#include "pagecopy.h" + +#ifdef __ARCH_HAS_BWD_MEMCPY__ +/* generic-opt memmove assumes memcpy does forward copying! */ +#include "_memcpy_fwd.c" +#endif + + +static void _wordcopy_bwd_aligned (long int dstp, long int srcp, size_t len) +{ + op_t a0 = 0; + op_t a1 = 0; + + switch (len % 8) + { + case 2: + srcp -= 2 * OPSIZ; + dstp -= 1 * OPSIZ; + a0 = ((op_t *) srcp)[1]; + len += 6; + goto do1; + case 3: + srcp -= 3 * OPSIZ; + dstp -= 2 * OPSIZ; + a1 = ((op_t *) srcp)[2]; + len += 5; + goto do2; + case 4: + srcp -= 4 * OPSIZ; + dstp -= 3 * OPSIZ; + a0 = ((op_t *) srcp)[3]; + len += 4; + goto do3; + case 5: + srcp -= 5 * OPSIZ; + dstp -= 4 * OPSIZ; + a1 = ((op_t *) srcp)[4]; + len += 3; + goto do4; + case 6: + srcp -= 6 * OPSIZ; + dstp -= 5 * OPSIZ; + a0 = ((op_t *) srcp)[5]; + len += 2; + goto do5; + case 7: + srcp -= 7 * OPSIZ; + dstp -= 6 * OPSIZ; + a1 = ((op_t *) srcp)[6]; + len += 1; + goto do6; + + case 0: + if (OP_T_THRES <= 3 * OPSIZ && len == 0) + return; + srcp -= 8 * OPSIZ; + dstp -= 7 * OPSIZ; + a0 = ((op_t *) srcp)[7]; + goto do7; + case 1: + srcp -= 9 * OPSIZ; + dstp -= 8 * OPSIZ; + a1 = ((op_t *) srcp)[8]; + len -= 1; + if (OP_T_THRES <= 3 * OPSIZ && len == 0) + goto do0; + goto do8; /* No-op. */ + } + + do + { + do8: + a0 = ((op_t *) srcp)[7]; + ((op_t *) dstp)[7] = a1; + do7: + a1 = ((op_t *) srcp)[6]; + ((op_t *) dstp)[6] = a0; + do6: + a0 = ((op_t *) srcp)[5]; + ((op_t *) dstp)[5] = a1; + do5: + a1 = ((op_t *) srcp)[4]; + ((op_t *) dstp)[4] = a0; + do4: + a0 = ((op_t *) srcp)[3]; + ((op_t *) dstp)[3] = a1; + do3: + a1 = ((op_t *) srcp)[2]; + ((op_t *) dstp)[2] = a0; + do2: + a0 = ((op_t *) srcp)[1]; + ((op_t *) dstp)[1] = a1; + do1: + a1 = ((op_t *) srcp)[0]; + ((op_t *) dstp)[0] = a0; + + srcp -= 8 * OPSIZ; + dstp -= 8 * OPSIZ; + len -= 8; + } + while (len != 0); + + /* This is the right position for do0. Please don't move + it into the loop. */ + do0: + ((op_t *) dstp)[7] = a1; +} + +/* _wordcopy_bwd_dest_aligned -- Copy block finishing right + before SRCP to block finishing right before DSTP with LEN `op_t' + words (not LEN bytes!). DSTP should be aligned for memory + operations on `op_t', but SRCP must *not* be aligned. */ + +static void _wordcopy_bwd_dest_aligned (long int dstp, long int srcp, size_t len) +{ + op_t a0 = 0; + op_t a1 = 0; + op_t a2 = 0; + op_t a3 = 0; + int sh_1, sh_2; + + /* Calculate how to shift a word read at the memory operation + aligned srcp to make it aligned for copy. */ + + sh_1 = 8 * (srcp % OPSIZ); + sh_2 = 8 * OPSIZ - sh_1; + + /* Make srcp aligned by rounding it down to the beginning of the op_t + it points in the middle of. */ + srcp &= -OPSIZ; + srcp += OPSIZ; + + switch (len % 4) + { + case 2: + srcp -= 3 * OPSIZ; + dstp -= 1 * OPSIZ; + a2 = ((op_t *) srcp)[2]; + a1 = ((op_t *) srcp)[1]; + len += 2; + goto do1; + case 3: + srcp -= 4 * OPSIZ; + dstp -= 2 * OPSIZ; + a3 = ((op_t *) srcp)[3]; + a2 = ((op_t *) srcp)[2]; + len += 1; + goto do2; + case 0: + if (OP_T_THRES <= 3 * OPSIZ && len == 0) + return; + srcp -= 5 * OPSIZ; + dstp -= 3 * OPSIZ; + a0 = ((op_t *) srcp)[4]; + a3 = ((op_t *) srcp)[3]; + goto do3; + case 1: + srcp -= 6 * OPSIZ; + dstp -= 4 * OPSIZ; + a1 = ((op_t *) srcp)[5]; + a0 = ((op_t *) srcp)[4]; + len -= 1; + if (OP_T_THRES <= 3 * OPSIZ && len == 0) + goto do0; + goto do4; /* No-op. */ + } + + do + { + do4: + a3 = ((op_t *) srcp)[3]; + ((op_t *) dstp)[3] = MERGE (a0, sh_1, a1, sh_2); + do3: + a2 = ((op_t *) srcp)[2]; + ((op_t *) dstp)[2] = MERGE (a3, sh_1, a0, sh_2); + do2: + a1 = ((op_t *) srcp)[1]; + ((op_t *) dstp)[1] = MERGE (a2, sh_1, a3, sh_2); + do1: + a0 = ((op_t *) srcp)[0]; + ((op_t *) dstp)[0] = MERGE (a1, sh_1, a2, sh_2); + + srcp -= 4 * OPSIZ; + dstp -= 4 * OPSIZ; + len -= 4; + } + while (len != 0); + + /* This is the right position for do0. Please don't move + it into the loop. */ + do0: + ((op_t *) dstp)[3] = MERGE (a0, sh_1, a1, sh_2); +} + +void *memmove (void *dest, const void *src, size_t len) +{ + unsigned long int dstp = (long int) dest; + unsigned long int srcp = (long int) src; + + /* This test makes the forward copying code be used whenever possible. + Reduces the working set. */ + if (dstp - srcp >= len) /* *Unsigned* compare! */ + { +#ifndef __ARCH_HAS_BWD_MEMCPY__ + /* Backward memcpy implementation cannot be used */ + memcpy(dest, src, len); +#else + /* Copy from the beginning to the end. */ + + /* If there not too few bytes to copy, use word copy. */ + if (len >= OP_T_THRES) + { + /* Copy just a few bytes to make DSTP aligned. */ + len -= (-dstp) % OPSIZ; + BYTE_COPY_FWD (dstp, srcp, (-dstp) % OPSIZ); + + /* Copy whole pages from SRCP to DSTP by virtual address + manipulation, as much as possible. */ + + PAGE_COPY_FWD_MAYBE (dstp, srcp, len, len); + + /* Copy from SRCP to DSTP taking advantage of the known + alignment of DSTP. Number of bytes remaining is put + in the third argument, i.e. in LEN. This number may + vary from machine to machine. */ + + WORD_COPY_FWD (dstp, srcp, len, len); + + /* Fall out and copy the tail. */ + } + + /* There are just a few bytes to copy. Use byte memory operations. */ + BYTE_COPY_FWD (dstp, srcp, len); +#endif + } + else + { + /* Copy from the end to the beginning. */ + srcp += len; + dstp += len; + + /* If there not too few bytes to copy, use word copy. */ + if (len >= OP_T_THRES) + { + /* Copy just a few bytes to make DSTP aligned. */ + len -= dstp % OPSIZ; + BYTE_COPY_BWD (dstp, srcp, dstp % OPSIZ); + + /* Copy from SRCP to DSTP taking advantage of the known + alignment of DSTP. Number of bytes remaining is put + in the third argument, i.e. in LEN. This number may + vary from machine to machine. */ + + WORD_COPY_BWD (dstp, srcp, len, len); + + /* Fall out and copy the tail. */ + } + + /* There are just a few bytes to copy. Use byte memory operations. */ + BYTE_COPY_BWD (dstp, srcp, len); + } + + return (dest); +} +libc_hidden_weak(memmove) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/mempcpy.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/mempcpy.c new file mode 100644 index 00000000..d7fa79ef --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/mempcpy.c @@ -0,0 +1,19 @@ +/* Copy memory to memory until the specified number of bytes + has been copied, return pointer to following byte. + Overlap is NOT handled correctly. +*/ + +/* Ditch the glibc version and just wrap memcpy. */ + +#include + +#ifdef __USE_GNU + +# undef mempcpy +void *mempcpy (void *dstpp, const void *srcpp, size_t len) +{ + memcpy(dstpp, srcpp, len); + return (void *)(((char *)dstpp) + len); +} +libc_hidden_weak(mempcpy) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/memrchr.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/memrchr.c new file mode 100644 index 00000000..c03a7703 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/memrchr.c @@ -0,0 +1,176 @@ +/* memrchr -- find the last occurrence of a byte in a memory block + Copyright (C) 1991, 93, 96, 97, 99, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Based on strlen implementation by Torbjorn Granlund (tege@sics.se), + with help from Dan Sahlin (dan@sics.se) and + commentary by Jim Blandy (jimb@ai.mit.edu); + adaptation to memchr suggested by Dick Karpinski (dick@cca.ucsf.edu), + and implemented by Roland McGrath (roland@ai.mit.edu). + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +#ifdef __USE_GNU + +#include "memcopy.h" + +#define LONG_MAX_32_BITS 2147483647 + +/* Search no more than N bytes of S for C. */ +void *memrchr (const void * s, int c_in, size_t n) +{ + const unsigned char *char_ptr; + const unsigned long int *longword_ptr; + unsigned long int longword, magic_bits, charmask; + unsigned reg_char c; + + c = (unsigned char) c_in; + + /* Handle the last few characters by reading one character at a time. + Do this until CHAR_PTR is aligned on a longword boundary. */ + for (char_ptr = (const unsigned char *) s + n; + n > 0 && ((unsigned long int) char_ptr + & (sizeof (longword) - 1)) != 0; + --n) + if (*--char_ptr == c) + return (void *) char_ptr; + + /* All these elucidatory comments refer to 4-byte longwords, + but the theory applies equally well to 8-byte longwords. */ + + longword_ptr = (const unsigned long int *) char_ptr; + + /* Bits 31, 24, 16, and 8 of this number are zero. Call these bits + the "holes." Note that there is a hole just to the left of + each byte, with an extra at the end: + + bits: 01111110 11111110 11111110 11111111 + bytes: AAAAAAAA BBBBBBBB CCCCCCCC DDDDDDDD + + The 1-bits make sure that carries propagate to the next 0-bit. + The 0-bits provide holes for carries to fall into. */ + + if (sizeof (longword) != 4 && sizeof (longword) != 8) + abort (); + +#if LONG_MAX <= LONG_MAX_32_BITS + magic_bits = 0x7efefeff; +#else + magic_bits = ((unsigned long int) 0x7efefefe << 32) | 0xfefefeff; +#endif + + /* Set up a longword, each of whose bytes is C. */ + charmask = c | (c << 8); + charmask |= charmask << 16; +#if LONG_MAX > LONG_MAX_32_BITS + charmask |= charmask << 32; +#endif + + /* Instead of the traditional loop which tests each character, + we will test a longword at a time. The tricky part is testing + if *any of the four* bytes in the longword in question are zero. */ + while (n >= sizeof (longword)) + { + /* We tentatively exit the loop if adding MAGIC_BITS to + LONGWORD fails to change any of the hole bits of LONGWORD. + + 1) Is this safe? Will it catch all the zero bytes? + Suppose there is a byte with all zeros. Any carry bits + propagating from its left will fall into the hole at its + least significant bit and stop. Since there will be no + carry from its most significant bit, the LSB of the + byte to the left will be unchanged, and the zero will be + detected. + + 2) Is this worthwhile? Will it ignore everything except + zero bytes? Suppose every byte of LONGWORD has a bit set + somewhere. There will be a carry into bit 8. If bit 8 + is set, this will carry into bit 16. If bit 8 is clear, + one of bits 9-15 must be set, so there will be a carry + into bit 16. Similarly, there will be a carry into bit + 24. If one of bits 24-30 is set, there will be a carry + into bit 31, so all of the hole bits will be changed. + + The one misfire occurs when bits 24-30 are clear and bit + 31 is set; in this case, the hole at bit 31 is not + changed. If we had access to the processor carry flag, + we could close this loophole by putting the fourth hole + at bit 32! + + So it ignores everything except 128's, when they're aligned + properly. + + 3) But wait! Aren't we looking for C, not zero? + Good point. So what we do is XOR LONGWORD with a longword, + each of whose bytes is C. This turns each byte that is C + into a zero. */ + + longword = *--longword_ptr ^ charmask; + + /* Add MAGIC_BITS to LONGWORD. */ + if ((((longword + magic_bits) + + /* Set those bits that were unchanged by the addition. */ + ^ ~longword) + + /* Look at only the hole bits. If any of the hole bits + are unchanged, most likely one of the bytes was a + zero. */ + & ~magic_bits) != 0) + { + /* Which of the bytes was C? If none of them were, it was + a misfire; continue the search. */ + + const unsigned char *cp = (const unsigned char *) longword_ptr; + +#if LONG_MAX > 2147483647 + if (cp[7] == c) + return (void *) &cp[7]; + if (cp[6] == c) + return (void *) &cp[6]; + if (cp[5] == c) + return (void *) &cp[5]; + if (cp[4] == c) + return (void *) &cp[4]; +#endif + if (cp[3] == c) + return (void *) &cp[3]; + if (cp[2] == c) + return (void *) &cp[2]; + if (cp[1] == c) + return (void *) &cp[1]; + if (cp[0] == c) + return (void *) cp; + } + + n -= sizeof (longword); + } + + char_ptr = (const unsigned char *) longword_ptr; + + while (n-- > 0) + { + if (*--char_ptr == c) + return (void *) char_ptr; + } + + return 0; +} +libc_hidden_def(memrchr) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/memset.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/memset.c new file mode 100644 index 00000000..7be57276 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/memset.c @@ -0,0 +1,85 @@ +/* Copyright (C) 1991, 1997, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include "memcopy.h" + +void *memset (void *dstpp, int c, size_t len) +{ + long int dstp = (long int) dstpp; + + if (len >= 8) + { + size_t xlen; + op_t cccc; + + cccc = (unsigned char) c; + cccc |= cccc << 8; + cccc |= cccc << 16; + if (OPSIZ > 4) + /* Do the shift in two steps to avoid warning if long has 32 bits. */ + cccc |= (cccc << 16) << 16; + + /* There are at least some bytes to set. + No need to test for LEN == 0 in this alignment loop. */ + while (dstp % OPSIZ != 0) + { + ((byte *) dstp)[0] = c; + dstp += 1; + len -= 1; + } + + /* Write 8 `op_t' per iteration until less than 8 `op_t' remain. */ + xlen = len / (OPSIZ * 8); + while (xlen > 0) + { + ((op_t *) dstp)[0] = cccc; + ((op_t *) dstp)[1] = cccc; + ((op_t *) dstp)[2] = cccc; + ((op_t *) dstp)[3] = cccc; + ((op_t *) dstp)[4] = cccc; + ((op_t *) dstp)[5] = cccc; + ((op_t *) dstp)[6] = cccc; + ((op_t *) dstp)[7] = cccc; + dstp += 8 * OPSIZ; + xlen -= 1; + } + len %= OPSIZ * 8; + + /* Write 1 `op_t' per iteration until less than OPSIZ bytes remain. */ + xlen = len / OPSIZ; + while (xlen > 0) + { + ((op_t *) dstp)[0] = cccc; + dstp += OPSIZ; + xlen -= 1; + } + len %= OPSIZ; + } + + /* Write the last few bytes. */ + while (len > 0) + { + ((byte *) dstp)[0] = c; + dstp += 1; + len -= 1; + } + + return dstpp; +} +libc_hidden_weak(memset) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/pagecopy.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/pagecopy.h new file mode 100644 index 00000000..b00db493 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/pagecopy.h @@ -0,0 +1,75 @@ +/* Macros for copying by pages; used in memcpy, memmove. Generic macros. + Copyright (C) 1995, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This file defines the macro: + + PAGE_COPY_FWD_MAYBE (dstp, srcp, nbytes_left, nbytes) + + which is invoked like WORD_COPY_FWD et al. The pointers should be at + least word aligned. This will check if virtual copying by pages can and + should be done and do it if so. + + System-specific pagecopy.h files should define these macros and then + #include this file: + + PAGE_COPY_THRESHOLD + -- Minimum size for which virtual copying by pages is worthwhile. + + PAGE_SIZE + -- Size of a page. + + PAGE_COPY_FWD (dstp, srcp, nbytes_left, nbytes) + -- Macro to perform the virtual copy operation. + The pointers will be aligned to PAGE_SIZE bytes. +*/ + + +#if defined PAGE_COPY_THRESHOLD && PAGE_COPY_THRESHOLD + +#include + +#define PAGE_COPY_FWD_MAYBE(dstp, srcp, nbytes_left, nbytes) \ + do \ + { \ + if ((nbytes) >= PAGE_COPY_THRESHOLD && \ + PAGE_OFFSET ((dstp) - (srcp)) == 0) \ + { \ + /* The amount to copy is past the threshold for copying \ + pages virtually with kernel VM operations, and the \ + source and destination addresses have the same alignment. */ \ + size_t nbytes_before = PAGE_OFFSET (-(dstp)); \ + if (nbytes_before != 0) \ + { \ + /* First copy the words before the first page boundary. */ \ + WORD_COPY_FWD (dstp, srcp, nbytes_left, nbytes_before); \ + assert (nbytes_left == 0); \ + nbytes -= nbytes_before; \ + } \ + PAGE_COPY_FWD (dstp, srcp, nbytes_left, nbytes); \ + } \ + } while (0) + +/* The page size is always a power of two, so we can avoid modulo division. */ +#define PAGE_OFFSET(n) ((n) & (PAGE_SIZE - 1)) + +#else + +#define PAGE_COPY_FWD_MAYBE(dstp, srcp, nbytes_left, nbytes) /* nada */ + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/rawmemchr.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/rawmemchr.c new file mode 100644 index 00000000..ddefb099 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/rawmemchr.c @@ -0,0 +1,162 @@ +/* Copyright (C) 1991,93,96,97,99,2000,2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Based on strlen implementation by Torbjorn Granlund (tege@sics.se), + with help from Dan Sahlin (dan@sics.se) and + commentary by Jim Blandy (jimb@ai.mit.edu); + adaptation to memchr suggested by Dick Karpinski (dick@cca.ucsf.edu), + and implemented by Roland McGrath (roland@ai.mit.edu). + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +#ifdef __USE_GNU + +#include "memcopy.h" + +#define LONG_MAX_32_BITS 2147483647 + +/* Find the first occurrence of C in S. */ +void *rawmemchr (const void * s, int c_in) +{ + const unsigned char *char_ptr; + const unsigned long int *longword_ptr; + unsigned long int longword, magic_bits, charmask; + unsigned reg_char c; + + c = (unsigned char) c_in; + + /* Handle the first few characters by reading one character at a time. + Do this until CHAR_PTR is aligned on a longword boundary. */ + for (char_ptr = (const unsigned char *) s; + ((unsigned long int) char_ptr & (sizeof (longword) - 1)) != 0; + ++char_ptr) + if (*char_ptr == c) + return (void *) char_ptr; + + /* All these elucidatory comments refer to 4-byte longwords, + but the theory applies equally well to 8-byte longwords. */ + + longword_ptr = (unsigned long int *) char_ptr; + + /* Bits 31, 24, 16, and 8 of this number are zero. Call these bits + the "holes." Note that there is a hole just to the left of + each byte, with an extra at the end: + + bits: 01111110 11111110 11111110 11111111 + bytes: AAAAAAAA BBBBBBBB CCCCCCCC DDDDDDDD + + The 1-bits make sure that carries propagate to the next 0-bit. + The 0-bits provide holes for carries to fall into. */ + + if (sizeof (longword) != 4 && sizeof (longword) != 8) + abort (); + +#if LONG_MAX <= LONG_MAX_32_BITS + magic_bits = 0x7efefeff; +#else + magic_bits = ((unsigned long int) 0x7efefefe << 32) | 0xfefefeff; +#endif + + /* Set up a longword, each of whose bytes is C. */ + charmask = c | (c << 8); + charmask |= charmask << 16; +#if LONG_MAX > LONG_MAX_32_BITS + charmask |= charmask << 32; +#endif + + /* Instead of the traditional loop which tests each character, + we will test a longword at a time. The tricky part is testing + if *any of the four* bytes in the longword in question are zero. */ + while (1) + { + /* We tentatively exit the loop if adding MAGIC_BITS to + LONGWORD fails to change any of the hole bits of LONGWORD. + + 1) Is this safe? Will it catch all the zero bytes? + Suppose there is a byte with all zeros. Any carry bits + propagating from its left will fall into the hole at its + least significant bit and stop. Since there will be no + carry from its most significant bit, the LSB of the + byte to the left will be unchanged, and the zero will be + detected. + + 2) Is this worthwhile? Will it ignore everything except + zero bytes? Suppose every byte of LONGWORD has a bit set + somewhere. There will be a carry into bit 8. If bit 8 + is set, this will carry into bit 16. If bit 8 is clear, + one of bits 9-15 must be set, so there will be a carry + into bit 16. Similarly, there will be a carry into bit + 24. If one of bits 24-30 is set, there will be a carry + into bit 31, so all of the hole bits will be changed. + + The one misfire occurs when bits 24-30 are clear and bit + 31 is set; in this case, the hole at bit 31 is not + changed. If we had access to the processor carry flag, + we could close this loophole by putting the fourth hole + at bit 32! + + So it ignores everything except 128's, when they're aligned + properly. + + 3) But wait! Aren't we looking for C, not zero? + Good point. So what we do is XOR LONGWORD with a longword, + each of whose bytes is C. This turns each byte that is C + into a zero. */ + + longword = *longword_ptr++ ^ charmask; + + /* Add MAGIC_BITS to LONGWORD. */ + if ((((longword + magic_bits) + + /* Set those bits that were unchanged by the addition. */ + ^ ~longword) + + /* Look at only the hole bits. If any of the hole bits + are unchanged, most likely one of the bytes was a + zero. */ + & ~magic_bits) != 0) + { + /* Which of the bytes was C? If none of them were, it was + a misfire; continue the search. */ + + const unsigned char *cp = (const unsigned char *) (longword_ptr - 1); + + if (cp[0] == c) + return (void *) cp; + if (cp[1] == c) + return (void *) &cp[1]; + if (cp[2] == c) + return (void *) &cp[2]; + if (cp[3] == c) + return (void *) &cp[3]; +#if LONG_MAX > 2147483647 + if (cp[4] == c) + return (void *) &cp[4]; + if (cp[5] == c) + return (void *) &cp[5]; + if (cp[6] == c) + return (void *) &cp[6]; + if (cp[7] == c) + return (void *) &cp[7]; +#endif + } + } +} +libc_hidden_def(rawmemchr) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/strcat.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/strcat.c new file mode 100644 index 00000000..b19a0dbd --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/strcat.c @@ -0,0 +1,47 @@ +/* Copyright (C) 1991, 1997, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include "memcopy.h" + +/* Append SRC on the end of DEST. */ +char *strcat (char *dest, const char *src) +{ + char *s1 = dest; + const char *s2 = src; + reg_char c; + + /* Find the end of the string. */ + do + c = *s1++; + while (c != '\0'); + + /* Make S1 point before the next character, so we can increment + it while memory is read (wins on pipelined cpus). */ + s1 -= 2; + + do + { + c = *s2++; + *++s1 = c; + } + while (c != '\0'); + + return dest; +} +libc_hidden_def(strcat) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/strchr.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/strchr.c new file mode 100644 index 00000000..836ccddb --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/strchr.c @@ -0,0 +1,185 @@ +/* Copyright (C) 1991,93,94,95,96,97,99,2000,03 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Based on strlen implementation by Torbjorn Granlund (tege@sics.se), + with help from Dan Sahlin (dan@sics.se) and + bug fix and commentary by Jim Blandy (jimb@ai.mit.edu); + adaptation to strchr suggested by Dick Karpinski (dick@cca.ucsf.edu), + and implemented by Roland McGrath (roland@ai.mit.edu). + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + + +#include "memcopy.h" + +/* Find the first occurrence of C in S. */ +char *strchr (const char *s, int c_in) +{ + const unsigned char *char_ptr; + const unsigned long int *longword_ptr; + unsigned long int longword, magic_bits, charmask; + unsigned reg_char c; + + c = (unsigned char) c_in; + + /* Handle the first few characters by reading one character at a time. + Do this until CHAR_PTR is aligned on a longword boundary. */ + for (char_ptr = (const unsigned char *) s; + ((unsigned long int) char_ptr & (sizeof (longword) - 1)) != 0; + ++char_ptr) + if (*char_ptr == c) + return (void *) char_ptr; + else if (*char_ptr == '\0') + return NULL; + + /* All these elucidatory comments refer to 4-byte longwords, + but the theory applies equally well to 8-byte longwords. */ + + longword_ptr = (unsigned long int *) char_ptr; + + /* Bits 31, 24, 16, and 8 of this number are zero. Call these bits + the "holes." Note that there is a hole just to the left of + each byte, with an extra at the end: + + bits: 01111110 11111110 11111110 11111111 + bytes: AAAAAAAA BBBBBBBB CCCCCCCC DDDDDDDD + + The 1-bits make sure that carries propagate to the next 0-bit. + The 0-bits provide holes for carries to fall into. */ + switch (sizeof (longword)) + { + case 4: magic_bits = 0x7efefeffL; break; + case 8: magic_bits = ((0x7efefefeL << 16) << 16) | 0xfefefeffL; break; + default: + abort (); + } + + /* Set up a longword, each of whose bytes is C. */ + charmask = c | (c << 8); + charmask |= charmask << 16; + if (sizeof (longword) > 4) + /* Do the shift in two steps to avoid a warning if long has 32 bits. */ + charmask |= (charmask << 16) << 16; + if (sizeof (longword) > 8) + abort (); + + /* Instead of the traditional loop which tests each character, + we will test a longword at a time. The tricky part is testing + if *any of the four* bytes in the longword in question are zero. */ + for (;;) + { + /* We tentatively exit the loop if adding MAGIC_BITS to + LONGWORD fails to change any of the hole bits of LONGWORD. + + 1) Is this safe? Will it catch all the zero bytes? + Suppose there is a byte with all zeros. Any carry bits + propagating from its left will fall into the hole at its + least significant bit and stop. Since there will be no + carry from its most significant bit, the LSB of the + byte to the left will be unchanged, and the zero will be + detected. + + 2) Is this worthwhile? Will it ignore everything except + zero bytes? Suppose every byte of LONGWORD has a bit set + somewhere. There will be a carry into bit 8. If bit 8 + is set, this will carry into bit 16. If bit 8 is clear, + one of bits 9-15 must be set, so there will be a carry + into bit 16. Similarly, there will be a carry into bit + 24. If one of bits 24-30 is set, there will be a carry + into bit 31, so all of the hole bits will be changed. + + The one misfire occurs when bits 24-30 are clear and bit + 31 is set; in this case, the hole at bit 31 is not + changed. If we had access to the processor carry flag, + we could close this loophole by putting the fourth hole + at bit 32! + + So it ignores everything except 128's, when they're aligned + properly. + + 3) But wait! Aren't we looking for C as well as zero? + Good point. So what we do is XOR LONGWORD with a longword, + each of whose bytes is C. This turns each byte that is C + into a zero. */ + + longword = *longword_ptr++; + + /* Add MAGIC_BITS to LONGWORD. */ + if ((((longword + magic_bits) + + /* Set those bits that were unchanged by the addition. */ + ^ ~longword) + + /* Look at only the hole bits. If any of the hole bits + are unchanged, most likely one of the bytes was a + zero. */ + & ~magic_bits) != 0 || + + /* That caught zeroes. Now test for C. */ + ((((longword ^ charmask) + magic_bits) ^ ~(longword ^ charmask)) + & ~magic_bits) != 0) + { + /* Which of the bytes was C or zero? + If none of them were, it was a misfire; continue the search. */ + + const unsigned char *cp = (const unsigned char *) (longword_ptr - 1); + + if (*cp == c) + return (char *) cp; + else if (*cp == '\0') + return NULL; + if (*++cp == c) + return (char *) cp; + else if (*cp == '\0') + return NULL; + if (*++cp == c) + return (char *) cp; + else if (*cp == '\0') + return NULL; + if (*++cp == c) + return (char *) cp; + else if (*cp == '\0') + return NULL; + if (sizeof (longword) > 4) + { + if (*++cp == c) + return (char *) cp; + else if (*cp == '\0') + return NULL; + if (*++cp == c) + return (char *) cp; + else if (*cp == '\0') + return NULL; + if (*++cp == c) + return (char *) cp; + else if (*cp == '\0') + return NULL; + if (*++cp == c) + return (char *) cp; + else if (*cp == '\0') + return NULL; + } + } + } + + return NULL; +} +libc_hidden_weak(strchr) +#ifdef __UCLIBC_SUSV3_LEGACY__ +weak_alias(strchr,index) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/strchrnul.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/strchrnul.c new file mode 100644 index 00000000..9984d616 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/strchrnul.c @@ -0,0 +1,167 @@ +/* Copyright (C) 1991,93,94,95,96,97,99,2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Based on strlen implementation by Torbjorn Granlund (tege@sics.se), + with help from Dan Sahlin (dan@sics.se) and + bug fix and commentary by Jim Blandy (jimb@ai.mit.edu); + adaptation to strchr suggested by Dick Karpinski (dick@cca.ucsf.edu), + and implemented by Roland McGrath (roland@ai.mit.edu). + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +#ifdef __USE_GNU + +#include "memcopy.h" + +/* Find the first occurrence of C in S or the final NUL byte. */ +char *strchrnul (const char *s, int c_in) +{ + const unsigned char *char_ptr; + const unsigned long int *longword_ptr; + unsigned long int longword, magic_bits, charmask; + unsigned reg_char c; + + c = (unsigned char) c_in; + + /* Handle the first few characters by reading one character at a time. + Do this until CHAR_PTR is aligned on a longword boundary. */ + for (char_ptr = (const unsigned char *) s; + ((unsigned long int) char_ptr & (sizeof (longword) - 1)) != 0; + ++char_ptr) + if (*char_ptr == c || *char_ptr == '\0') + return (void *) char_ptr; + + /* All these elucidatory comments refer to 4-byte longwords, + but the theory applies equally well to 8-byte longwords. */ + + longword_ptr = (unsigned long int *) char_ptr; + + /* Bits 31, 24, 16, and 8 of this number are zero. Call these bits + the "holes." Note that there is a hole just to the left of + each byte, with an extra at the end: + + bits: 01111110 11111110 11111110 11111111 + bytes: AAAAAAAA BBBBBBBB CCCCCCCC DDDDDDDD + + The 1-bits make sure that carries propagate to the next 0-bit. + The 0-bits provide holes for carries to fall into. */ + switch (sizeof (longword)) + { + case 4: magic_bits = 0x7efefeffL; break; + case 8: magic_bits = ((0x7efefefeL << 16) << 16) | 0xfefefeffL; break; + default: + abort (); + } + + /* Set up a longword, each of whose bytes is C. */ + charmask = c | (c << 8); + charmask |= charmask << 16; + if (sizeof (longword) > 4) + /* Do the shift in two steps to avoid a warning if long has 32 bits. */ + charmask |= (charmask << 16) << 16; + if (sizeof (longword) > 8) + abort (); + + /* Instead of the traditional loop which tests each character, + we will test a longword at a time. The tricky part is testing + if *any of the four* bytes in the longword in question are zero. */ + for (;;) + { + /* We tentatively exit the loop if adding MAGIC_BITS to + LONGWORD fails to change any of the hole bits of LONGWORD. + + 1) Is this safe? Will it catch all the zero bytes? + Suppose there is a byte with all zeros. Any carry bits + propagating from its left will fall into the hole at its + least significant bit and stop. Since there will be no + carry from its most significant bit, the LSB of the + byte to the left will be unchanged, and the zero will be + detected. + + 2) Is this worthwhile? Will it ignore everything except + zero bytes? Suppose every byte of LONGWORD has a bit set + somewhere. There will be a carry into bit 8. If bit 8 + is set, this will carry into bit 16. If bit 8 is clear, + one of bits 9-15 must be set, so there will be a carry + into bit 16. Similarly, there will be a carry into bit + 24. If one of bits 24-30 is set, there will be a carry + into bit 31, so all of the hole bits will be changed. + + The one misfire occurs when bits 24-30 are clear and bit + 31 is set; in this case, the hole at bit 31 is not + changed. If we had access to the processor carry flag, + we could close this loophole by putting the fourth hole + at bit 32! + + So it ignores everything except 128's, when they're aligned + properly. + + 3) But wait! Aren't we looking for C as well as zero? + Good point. So what we do is XOR LONGWORD with a longword, + each of whose bytes is C. This turns each byte that is C + into a zero. */ + + longword = *longword_ptr++; + + /* Add MAGIC_BITS to LONGWORD. */ + if ((((longword + magic_bits) + + /* Set those bits that were unchanged by the addition. */ + ^ ~longword) + + /* Look at only the hole bits. If any of the hole bits + are unchanged, most likely one of the bytes was a + zero. */ + & ~magic_bits) != 0 || + + /* That caught zeroes. Now test for C. */ + ((((longword ^ charmask) + magic_bits) ^ ~(longword ^ charmask)) + & ~magic_bits) != 0) + { + /* Which of the bytes was C or zero? + If none of them were, it was a misfire; continue the search. */ + + const unsigned char *cp = (const unsigned char *) (longword_ptr - 1); + + if (*cp == c || *cp == '\0') + return (char *) cp; + if (*++cp == c || *cp == '\0') + return (char *) cp; + if (*++cp == c || *cp == '\0') + return (char *) cp; + if (*++cp == c || *cp == '\0') + return (char *) cp; + if (sizeof (longword) > 4) + { + if (*++cp == c || *cp == '\0') + return (char *) cp; + if (*++cp == c || *cp == '\0') + return (char *) cp; + if (*++cp == c || *cp == '\0') + return (char *) cp; + if (*++cp == c || *cp == '\0') + return (char *) cp; + } + } + } + + /* This should never happen. */ + return NULL; +} +libc_hidden_def(strchrnul) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/strcmp.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/strcmp.c new file mode 100644 index 00000000..502b80fb --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/strcmp.c @@ -0,0 +1,48 @@ +/* Copyright (C) 1991, 1996, 1997, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#include "memcopy.h" + +/* Compare S1 and S2, returning less than, equal to or + greater than zero if S1 is lexicographically less than, + equal to or greater than S2. */ +int strcmp (const char *p1, const char *p2) +{ + register const unsigned char *s1 = (const unsigned char *) p1; + register const unsigned char *s2 = (const unsigned char *) p2; + unsigned reg_char c1, c2; + + do + { + c1 = (unsigned char) *s1++; + c2 = (unsigned char) *s2++; + if (c1 == '\0') + return c1 - c2; + } + while (c1 == c2); + + return c1 - c2; +} +libc_hidden_weak(strcmp) + +#ifndef __UCLIBC_HAS_LOCALE__ +strong_alias(strcmp,strcoll) +libc_hidden_def(strcoll) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/strcpy.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/strcpy.c new file mode 100644 index 00000000..4d070531 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/strcpy.c @@ -0,0 +1,36 @@ +/* Copyright (C) 1991, 1997, 2000, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +#include "memcopy.h" + +/* Copy SRC to DEST. */ +char *strcpy(char *dest, const char *src) +{ + char *dst = dest; + + while ((*dst = *src) != '\0') { + src++; + dst++; + } + + return dest; +} +libc_hidden_def(strcpy) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/strcspn.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/strcspn.c new file mode 100644 index 00000000..f1f39df8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/strcspn.c @@ -0,0 +1,36 @@ +/* Copyright (C) 1991, 1994, 1996, 1997, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + + +/* Return the length of the maximum initial segment of S + which contains no characters from REJECT. */ +size_t strcspn (const char *s, const char *reject) +{ + size_t count = 0; + + while (*s != '\0') + if (strchr (reject, *s++) == NULL) + ++count; + else + return count; + + return count; +} +libc_hidden_def(strcspn) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/strlen.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/strlen.c new file mode 100644 index 00000000..9b6d81df --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/strlen.c @@ -0,0 +1,150 @@ +/* Copyright (C) 1991, 1993, 1997, 2000, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Written by Torbjorn Granlund (tege@sics.se), + with help from Dan Sahlin (dan@sics.se); + commentary by Jim Blandy (jimb@ai.mit.edu). + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + + +/* Return the length of the null-terminated string STR. Scan for + the null terminator quickly by testing four bytes at a time. */ +size_t strlen (const char *str) +{ + const char *char_ptr; + const unsigned long int *longword_ptr; + unsigned long int longword, magic_bits, himagic, lomagic; + + /* Handle the first few characters by reading one character at a time. + Do this until CHAR_PTR is aligned on a longword boundary. */ + for (char_ptr = str; ((unsigned long int) char_ptr + & (sizeof (longword) - 1)) != 0; + ++char_ptr) + if (*char_ptr == '\0') + return char_ptr - str; + + /* All these elucidatory comments refer to 4-byte longwords, + but the theory applies equally well to 8-byte longwords. */ + + longword_ptr = (unsigned long int *) char_ptr; + + /* Bits 31, 24, 16, and 8 of this number are zero. Call these bits + the "holes." Note that there is a hole just to the left of + each byte, with an extra at the end: + + bits: 01111110 11111110 11111110 11111111 + bytes: AAAAAAAA BBBBBBBB CCCCCCCC DDDDDDDD + + The 1-bits make sure that carries propagate to the next 0-bit. + The 0-bits provide holes for carries to fall into. */ + magic_bits = 0x7efefeffL; + himagic = 0x80808080L; + lomagic = 0x01010101L; + if (sizeof (longword) > 4) + { + /* 64-bit version of the magic. */ + /* Do the shift in two steps to avoid a warning if long has 32 bits. */ + magic_bits = ((0x7efefefeL << 16) << 16) | 0xfefefeffL; + himagic = ((himagic << 16) << 16) | himagic; + lomagic = ((lomagic << 16) << 16) | lomagic; + } + if (sizeof (longword) > 8) + abort (); + + /* Instead of the traditional loop which tests each character, + we will test a longword at a time. The tricky part is testing + if *any of the four* bytes in the longword in question are zero. */ + for (;;) + { + /* We tentatively exit the loop if adding MAGIC_BITS to + LONGWORD fails to change any of the hole bits of LONGWORD. + + 1) Is this safe? Will it catch all the zero bytes? + Suppose there is a byte with all zeros. Any carry bits + propagating from its left will fall into the hole at its + least significant bit and stop. Since there will be no + carry from its most significant bit, the LSB of the + byte to the left will be unchanged, and the zero will be + detected. + + 2) Is this worthwhile? Will it ignore everything except + zero bytes? Suppose every byte of LONGWORD has a bit set + somewhere. There will be a carry into bit 8. If bit 8 + is set, this will carry into bit 16. If bit 8 is clear, + one of bits 9-15 must be set, so there will be a carry + into bit 16. Similarly, there will be a carry into bit + 24. If one of bits 24-30 is set, there will be a carry + into bit 31, so all of the hole bits will be changed. + + The one misfire occurs when bits 24-30 are clear and bit + 31 is set; in this case, the hole at bit 31 is not + changed. If we had access to the processor carry flag, + we could close this loophole by putting the fourth hole + at bit 32! + + So it ignores everything except 128's, when they're aligned + properly. */ + + longword = *longword_ptr++; + + if ( +#if 0 + /* Add MAGIC_BITS to LONGWORD. */ + (((longword + magic_bits) + + /* Set those bits that were unchanged by the addition. */ + ^ ~longword) + + /* Look at only the hole bits. If any of the hole bits + are unchanged, most likely one of the bytes was a + zero. */ + & ~magic_bits) +#else + ((longword - lomagic) & himagic) +#endif + != 0) + { + /* Which of the bytes was the zero? If none of them were, it was + a misfire; continue the search. */ + + const char *cp = (const char *) (longword_ptr - 1); + + if (cp[0] == 0) + return cp - str; + if (cp[1] == 0) + return cp - str + 1; + if (cp[2] == 0) + return cp - str + 2; + if (cp[3] == 0) + return cp - str + 3; + if (sizeof (longword) > 4) + { + if (cp[4] == 0) + return cp - str + 4; + if (cp[5] == 0) + return cp - str + 5; + if (cp[6] == 0) + return cp - str + 6; + if (cp[7] == 0) + return cp - str + 7; + } + } + } +} +libc_hidden_weak(strlen) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/strncat.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/strncat.c new file mode 100644 index 00000000..0863d366 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/strncat.c @@ -0,0 +1,76 @@ +/* Copyright (C) 1991, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#include "memcopy.h" + +char *strncat (char *s1, const char *s2, size_t n) +{ + reg_char c; + char *s = s1; + + /* Find the end of S1. */ + do + c = *s1++; + while (c != '\0'); + + /* Make S1 point before next character, so we can increment + it while memory is read (wins on pipelined cpus). */ + s1 -= 2; + + if (n >= 4) + { + size_t n4 = n >> 2; + do + { + c = *s2++; + *++s1 = c; + if (c == '\0') + return s; + c = *s2++; + *++s1 = c; + if (c == '\0') + return s; + c = *s2++; + *++s1 = c; + if (c == '\0') + return s; + c = *s2++; + *++s1 = c; + if (c == '\0') + return s; + } while (--n4 > 0); + n &= 3; + } + + while (n > 0) + { + c = *s2++; + *++s1 = c; + if (c == '\0') + return s; + n--; + } + + if (c != '\0') + *++s1 = '\0'; + + return s; +} +libc_hidden_def(strncat) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/strncmp.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/strncmp.c new file mode 100644 index 00000000..04d6cf2a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/strncmp.c @@ -0,0 +1,67 @@ +/* Copyright (C) 1991, 1996, 1997, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include "memcopy.h" + +/* Compare no more than N characters of S1 and S2, + returning less than, equal to or greater than zero + if S1 is lexicographically less than, equal to or + greater than S2. */ +int strncmp (const char *s1, const char *s2, size_t n) +{ + unsigned reg_char c1 = '\0'; + unsigned reg_char c2 = '\0'; + + if (n >= 4) + { + size_t n4 = n >> 2; + do + { + c1 = (unsigned char) *s1++; + c2 = (unsigned char) *s2++; + if (c1 == '\0' || c1 != c2) + return c1 - c2; + c1 = (unsigned char) *s1++; + c2 = (unsigned char) *s2++; + if (c1 == '\0' || c1 != c2) + return c1 - c2; + c1 = (unsigned char) *s1++; + c2 = (unsigned char) *s2++; + if (c1 == '\0' || c1 != c2) + return c1 - c2; + c1 = (unsigned char) *s1++; + c2 = (unsigned char) *s2++; + if (c1 == '\0' || c1 != c2) + return c1 - c2; + } while (--n4 > 0); + n &= 3; + } + + while (n > 0) + { + c1 = (unsigned char) *s1++; + c2 = (unsigned char) *s2++; + if (c1 == '\0' || c1 != c2) + return c1 - c2; + n--; + } + + return c1 - c2; +} +libc_hidden_weak(strncmp) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/strncpy.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/strncpy.c new file mode 100644 index 00000000..26b45bb8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/strncpy.c @@ -0,0 +1,81 @@ +/* Copyright (C) 1991, 1997, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include "memcopy.h" + +char *strncpy (char *s1, const char *s2, size_t n) +{ + reg_char c; + char *s = s1; + + --s1; + + if (n >= 4) + { + size_t n4 = n >> 2; + + for (;;) + { + c = *s2++; + *++s1 = c; + if (c == '\0') + break; + c = *s2++; + *++s1 = c; + if (c == '\0') + break; + c = *s2++; + *++s1 = c; + if (c == '\0') + break; + c = *s2++; + *++s1 = c; + if (c == '\0') + break; + if (--n4 == 0) + goto last_chars; + } + n = n - (s1 - s) - 1; + if (n == 0) + return s; + goto zero_fill; + } + + last_chars: + n &= 3; + if (n == 0) + return s; + + do + { + c = *s2++; + *++s1 = c; + if (--n == 0) + return s; + } + while (c != '\0'); + + zero_fill: + do + *++s1 = '\0'; + while (--n > 0); + + return s; +} +libc_hidden_def(strncpy) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/strnlen.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/strnlen.c new file mode 100644 index 00000000..85819aaa --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/strnlen.c @@ -0,0 +1,162 @@ +/* Find the length of STRING, but scan at most MAXLEN characters. + Copyright (C) 1991, 1993, 1997, 2000, 2001 Free Software Foundation, Inc. + Contributed by Jakub Jelinek . + + Based on strlen written by Torbjorn Granlund (tege@sics.se), + with help from Dan Sahlin (dan@sics.se); + commentary by Jim Blandy (jimb@ai.mit.edu). + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +#ifdef __USE_GNU + +/* Find the length of S, but scan at most MAXLEN characters. If no + '\0' terminator is found in that many characters, return MAXLEN. */ +size_t strnlen (const char *str, size_t maxlen) +{ + const char *char_ptr, *end_ptr = str + maxlen; + const unsigned long int *longword_ptr; + unsigned long int longword, magic_bits, himagic, lomagic; + + if (maxlen == 0) + return 0; + + if (__builtin_expect (end_ptr < str, 0)) + end_ptr = (const char *) ~0UL; + + /* Handle the first few characters by reading one character at a time. + Do this until CHAR_PTR is aligned on a longword boundary. */ + for (char_ptr = str; ((unsigned long int) char_ptr + & (sizeof (longword) - 1)) != 0; + ++char_ptr) + if (*char_ptr == '\0') + { + if (char_ptr > end_ptr) + char_ptr = end_ptr; + return char_ptr - str; + } + + /* All these elucidatory comments refer to 4-byte longwords, + but the theory applies equally well to 8-byte longwords. */ + + longword_ptr = (unsigned long int *) char_ptr; + + /* Bits 31, 24, 16, and 8 of this number are zero. Call these bits + the "holes." Note that there is a hole just to the left of + each byte, with an extra at the end: + + bits: 01111110 11111110 11111110 11111111 + bytes: AAAAAAAA BBBBBBBB CCCCCCCC DDDDDDDD + + The 1-bits make sure that carries propagate to the next 0-bit. + The 0-bits provide holes for carries to fall into. */ + magic_bits = 0x7efefeffL; + himagic = 0x80808080L; + lomagic = 0x01010101L; + if (sizeof (longword) > 4) + { + /* 64-bit version of the magic. */ + /* Do the shift in two steps to avoid a warning if long has 32 bits. */ + magic_bits = ((0x7efefefeL << 16) << 16) | 0xfefefeffL; + himagic = ((himagic << 16) << 16) | himagic; + lomagic = ((lomagic << 16) << 16) | lomagic; + } + if (sizeof (longword) > 8) + abort (); + + /* Instead of the traditional loop which tests each character, + we will test a longword at a time. The tricky part is testing + if *any of the four* bytes in the longword in question are zero. */ + while (longword_ptr < (unsigned long int *) end_ptr) + { + /* We tentatively exit the loop if adding MAGIC_BITS to + LONGWORD fails to change any of the hole bits of LONGWORD. + + 1) Is this safe? Will it catch all the zero bytes? + Suppose there is a byte with all zeros. Any carry bits + propagating from its left will fall into the hole at its + least significant bit and stop. Since there will be no + carry from its most significant bit, the LSB of the + byte to the left will be unchanged, and the zero will be + detected. + + 2) Is this worthwhile? Will it ignore everything except + zero bytes? Suppose every byte of LONGWORD has a bit set + somewhere. There will be a carry into bit 8. If bit 8 + is set, this will carry into bit 16. If bit 8 is clear, + one of bits 9-15 must be set, so there will be a carry + into bit 16. Similarly, there will be a carry into bit + 24. If one of bits 24-30 is set, there will be a carry + into bit 31, so all of the hole bits will be changed. + + The one misfire occurs when bits 24-30 are clear and bit + 31 is set; in this case, the hole at bit 31 is not + changed. If we had access to the processor carry flag, + we could close this loophole by putting the fourth hole + at bit 32! + + So it ignores everything except 128's, when they're aligned + properly. */ + + longword = *longword_ptr++; + + if ((longword - lomagic) & himagic) + { + /* Which of the bytes was the zero? If none of them were, it was + a misfire; continue the search. */ + + const char *cp = (const char *) (longword_ptr - 1); + + char_ptr = cp; + if (cp[0] == 0) + break; + char_ptr = cp + 1; + if (cp[1] == 0) + break; + char_ptr = cp + 2; + if (cp[2] == 0) + break; + char_ptr = cp + 3; + if (cp[3] == 0) + break; + if (sizeof (longword) > 4) + { + char_ptr = cp + 4; + if (cp[4] == 0) + break; + char_ptr = cp + 5; + if (cp[5] == 0) + break; + char_ptr = cp + 6; + if (cp[6] == 0) + break; + char_ptr = cp + 7; + if (cp[7] == 0) + break; + } + } + char_ptr = end_ptr; + } + + if (char_ptr > end_ptr) + char_ptr = end_ptr; + return char_ptr - str; +} +libc_hidden_def(strnlen) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/strrchr.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/strrchr.c new file mode 100644 index 00000000..7d169260 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/strrchr.c @@ -0,0 +1,46 @@ +/* Copyright (C) 1991, 1995, 1996, 1997, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + + +/* Find the last occurrence of C in S. */ +char *strrchr (const char *s, int c) +{ + register const char *found, *p; + + c = (unsigned char) c; + + /* Since strchr is fast, we use it rather than the obvious loop. */ + + if (c == '\0') + return strchr (s, '\0'); + + found = NULL; + while ((p = strchr (s, c)) != NULL) + { + found = p; + s = p + 1; + } + + return (char *) found; +} +libc_hidden_weak(strrchr) +#ifdef __UCLIBC_SUSV3_LEGACY__ +weak_alias(strrchr,rindex) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/strsep.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/strsep.c new file mode 100644 index 00000000..91dfade8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/strsep.c @@ -0,0 +1,68 @@ +/* Copyright (C) 1992, 93, 96, 97, 98, 99, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#ifdef __USE_BSD + + +char *strsep (char **stringp, const char *delim) +{ + char *begin, *end; + + begin = *stringp; + if (begin == NULL) + return NULL; + + /* A frequent case is when the delimiter string contains only one + character. Here we don't need to call the expensive `strpbrk' + function and instead work using `strchr'. */ + if (delim[0] == '\0' || delim[1] == '\0') + { + char ch = delim[0]; + + if (ch == '\0') + end = NULL; + else + { + if (*begin == ch) + end = begin; + else if (*begin == '\0') + end = NULL; + else + end = strchr (begin + 1, ch); + } + } + else + /* Find the end of the token. */ + end = strpbrk (begin, delim); + + if (end) + { + /* Terminate the token and set *STRINGP past NUL character. */ + *end++ = '\0'; + *stringp = end; + } + else + /* No more delimiters; this is the last token. */ + *stringp = NULL; + + return begin; +} +libc_hidden_def(strsep) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/strspn.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/strspn.c new file mode 100644 index 00000000..1d9ec402 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/strspn.c @@ -0,0 +1,42 @@ +/* Copyright (C) 1991, 1997, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +/* Return the length of the maximum initial segment + of S which contains only characters in ACCEPT. */ +size_t strspn (const char *s, const char *accept) +{ + const char *p; + const char *a; + size_t count = 0; + + for (p = s; *p != '\0'; ++p) + { + for (a = accept; *a != '\0'; ++a) + if (*p == *a) + break; + if (*a == '\0') + return count; + else + ++count; + } + + return count; +} +libc_hidden_def(strspn) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/strstr.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/strstr.c new file mode 100644 index 00000000..c3b886a0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/strstr.c @@ -0,0 +1,113 @@ +/* Return the offset of one string within another. + Copyright (C) 1994,1996,1997,2000,2001,2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * My personal strstr() implementation that beats most other algorithms. + * Until someone tells me otherwise, I assume that this is the + * fastest implementation of strstr() in C. + * I deliberately chose not to comment it. You should have at least + * as much fun trying to understand it, as I had to write it :-). + * + * Stephen R. van den Berg, berg@pool.informatik.rwth-aachen.de */ + +#include + + +typedef unsigned chartype; + +char *strstr (const char *phaystack, const char *pneedle) +{ + const unsigned char *haystack, *needle; + chartype b; + const unsigned char *rneedle; + + haystack = (const unsigned char *) phaystack; + + if ((b = *(needle = (const unsigned char *) pneedle))) + { + chartype c; + haystack--; /* possible ANSI violation */ + + { + chartype a; + do + if (!(a = *++haystack)) + goto ret0; + while (a != b); + } + + if (!(c = *++needle)) + goto foundneedle; + ++needle; + goto jin; + + for (;;) + { + { + chartype a; + if (0) + jin:{ + if ((a = *++haystack) == c) + goto crest; + } + else + a = *++haystack; + do + { + for (; a != b; a = *++haystack) + { + if (!a) + goto ret0; + if ((a = *++haystack) == b) + break; + if (!a) + goto ret0; + } + } + while ((a = *++haystack) != c); + } + crest: + { + chartype a; + { + const unsigned char *rhaystack; + if (*(rhaystack = haystack-- + 1) == (a = *(rneedle = needle))) + do + { + if (!a) + goto foundneedle; + if (*++rhaystack != (a = *++needle)) + break; + if (!a) + goto foundneedle; + } + while (*++rhaystack == (a = *++needle)); + needle = rneedle; /* took the register-poor aproach */ + } + if (!a) + break; + } + } + } +foundneedle: + return (char *) haystack; +ret0: + return 0; +} +libc_hidden_def(strstr) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/strtok_r.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/strtok_r.c new file mode 100644 index 00000000..75ce5be2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/generic/strtok_r.c @@ -0,0 +1,67 @@ +/* Reentrant string tokenizer. Generic version. + Copyright (C) 1991,1996-1999,2001,2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#ifdef __USE_GNU +# define __rawmemchr rawmemchr +#else +# define __rawmemchr strchr +#endif +#if 0 + Parse S into tokens separated by characters in DELIM. + If S is NULL, the saved pointer in SAVE_PTR is used as + the next starting point. For example: + char s[] = "-abc-=-def"; + char *sp; + x = strtok_r(s, "-", &sp); /* x = "abc", sp = "=-def" */ + x = strtok_r(NULL, "-=", &sp); /* x = "def", sp = NULL */ + x = strtok_r(NULL, "=", &sp); /* x = NULL */ + /* s = "abc\0-def\0" */ +#endif +char *strtok_r (char *s, const char *delim, char **save_ptr) +{ + char *token; + + if (s == NULL) + s = *save_ptr; + + /* Scan leading delimiters. */ + s += strspn (s, delim); + if (*s == '\0') + { + *save_ptr = s; + return NULL; + } + + /* Find the end of the token. */ + token = s; + s = strpbrk (token, delim); + if (s == NULL) + /* This token finishes the string. */ + *save_ptr = __rawmemchr (token, '\0'); + else + { + /* Terminate the token and make *SAVE_PTR point past it. */ + *s = '\0'; + *save_ptr = s + 1; + } + return token; +} +libc_hidden_def(strtok_r) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/i386/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/i386/Makefile new file mode 100644 index 00000000..0a95346f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/i386/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir:=../../../ +top_builddir:=../../../ +all: objs +include $(top_builddir)Rules.mak +include ../Makefile.in +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/i386/memchr.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/i386/memchr.c new file mode 100644 index 00000000..1960f6ba --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/i386/memchr.c @@ -0,0 +1,75 @@ +/* + * This string-include defines all string functions as inline + * functions. Use gcc. It also assumes ds=es=data space, this should be + * normal. Most of the string-functions are rather heavily hand-optimized, + * see especially strtok,strstr,str[c]spn. They should work, but are not + * very easy to understand. Everything is done entirely within the register + * set, making the functions fast and clean. String instructions have been + * used through-out, making for "slightly" unclear code :-) + * + * NO Copyright (C) 1991, 1992 Linus Torvalds, + * consider these trivial functions to be PD. + */ + +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* + * Modified for uClibc by Erik Andersen + * These make no attempt to use nifty things like mmx/3dnow/etc. + * These are not inline, and will therefore not be as fast as + * modifying the headers to use inlines (and cannot therefore + * do tricky things when dealing with const memory). But they + * should (I hope!) be faster than their generic equivalents.... + * + * More importantly, these should provide a good example for + * others to follow when adding arch specific optimizations. + * -Erik + */ + +#include + +#undef memchr +/*#define memchr TESTING*/ +void *memchr(const void *s, int c, size_t count) +{ + void *edi; + int ecx; + __asm__ __volatile__( + " jecxz 1f\n" + " repne; scasb\n" + " leal -1(%%edi), %%edi\n" + " je 2f\n" + "1:\n" + " xorl %%edi, %%edi\n" /* NULL */ + "2:\n" + : "=&D" (edi), "=&c" (ecx) + : "a" (c), "0" (s), "1" (count) + /* : no clobbers */ + ); + return edi; +} +#ifndef memchr +libc_hidden_def(memchr) +#else +/* Uncomment TESTING, gcc -D_GNU_SOURCE -m32 -Os memchr.c -o memchr + * and run ./memchr + */ +int main() +{ + static const char str[] = "abc.def"; + printf((char*)memchr(str, '.',-2) - str == 3 ? "ok\n" : "BAD!\n"); + printf((char*)memchr(str, '.',-1) - str == 3 ? "ok\n" : "BAD!\n"); + printf((char*)memchr(str, '.', 0) == NULL ? "ok\n" : "BAD!\n"); + printf((char*)memchr(str, '.', 1) == NULL ? "ok\n" : "BAD!\n"); + printf((char*)memchr(str, '.', 2) == NULL ? "ok\n" : "BAD!\n"); + printf((char*)memchr(str, '.', 3) == NULL ? "ok\n" : "BAD!\n"); + printf((char*)memchr(str, '.', 4) - str == 3 ? "ok\n" : "BAD!\n"); + printf((char*)memchr(str, '.', 5) - str == 3 ? "ok\n" : "BAD!\n"); + printf((char*)memchr(str+3, '.', 0) == NULL ? "ok\n" : "BAD!\n"); + printf((char*)memchr(str+3, '.', 5) - str == 3 ? "ok\n" : "BAD!\n"); +} +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/i386/memcpy.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/i386/memcpy.c new file mode 100644 index 00000000..697d0bdc --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/i386/memcpy.c @@ -0,0 +1,54 @@ +/* + * This string-include defines all string functions as inline + * functions. Use gcc. It also assumes ds=es=data space, this should be + * normal. Most of the string-functions are rather heavily hand-optimized, + * see especially strtok,strstr,str[c]spn. They should work, but are not + * very easy to understand. Everything is done entirely within the register + * set, making the functions fast and clean. String instructions have been + * used through-out, making for "slightly" unclear code :-) + * + * NO Copyright (C) 1991, 1992 Linus Torvalds, + * consider these trivial functions to be PD. + */ + +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* + * Modified for uClibc by Erik Andersen + * These make no attempt to use nifty things like mmx/3dnow/etc. + * These are not inline, and will therefore not be as fast as + * modifying the headers to use inlines (and cannot therefore + * do tricky things when dealing with const memory). But they + * should (I hope!) be faster than their generic equivalents.... + * + * More importantly, these should provide a good example for + * others to follow when adding arch specific optimizations. + * -Erik + */ + +#include + +#undef memcpy +void *memcpy(void * to, const void * from, size_t n) +{ + int d0, d1, d2; + __asm__ __volatile__( + " rep; movsl\n" + " movl %4, %%ecx\n" + " andl $3, %%ecx\n" + /* jz is optional. avoids "rep; movsb" with ecx == 0, + * but adds a branch, which is currently (2008) faster */ + " jz 1f\n" + " rep; movsb\n" + "1:\n" + : "=&c" (d0), "=&D" (d1), "=&S" (d2) + : "0" (n / 4), "g" (n), "1" ((long)to), "2" ((long)from) + : "memory" + ); + return to; +} +libc_hidden_def(memcpy) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/i386/memmove.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/i386/memmove.c new file mode 100644 index 00000000..0ec8016a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/i386/memmove.c @@ -0,0 +1,71 @@ +/* + * This string-include defines all string functions as inline + * functions. Use gcc. It also assumes ds=es=data space, this should be + * normal. Most of the string-functions are rather heavily hand-optimized, + * see especially strtok,strstr,str[c]spn. They should work, but are not + * very easy to understand. Everything is done entirely within the register + * set, making the functions fast and clean. String instructions have been + * used through-out, making for "slightly" unclear code :-) + * + * NO Copyright (C) 1991, 1992 Linus Torvalds, + * consider these trivial functions to be PD. + */ + +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* + * Modified for uClibc by Erik Andersen + * These make no attempt to use nifty things like mmx/3dnow/etc. + * These are not inline, and will therefore not be as fast as + * modifying the headers to use inlines (and cannot therefore + * do tricky things when dealing with const memory). But they + * should (I hope!) be faster than their generic equivalents.... + * + * More importantly, these should provide a good example for + * others to follow when adding arch specific optimizations. + * -Erik + */ + +#include + +#undef memmove +/*#define memmove TESTING*/ +void *memmove(void *dest, const void *src, size_t n) +{ + int eax, ecx, esi, edi; + __asm__ __volatile__( + " movl %%eax, %%edi\n" + " cmpl %%esi, %%eax\n" + " je 2f\n" /* (optional) src == dest -> NOP */ + " jb 1f\n" /* src > dest -> simple copy */ + " leal -1(%%esi,%%ecx), %%esi\n" + " leal -1(%%eax,%%ecx), %%edi\n" + " std\n" + "1: rep; movsb\n" + " cld\n" + "2:\n" + : "=&c" (ecx), "=&S" (esi), "=&a" (eax), "=&D" (edi) + : "0" (n), "1" (src), "2" (dest) + : "memory" + ); + return (void*)eax; +} +#ifndef memmove +libc_hidden_def(memmove) +#else +/* Uncomment TESTING, gcc -D_GNU_SOURCE -m32 -Os memmove.c -o memmove + * and run ./memmove + */ +int main() +{ + static char str[] = "abcdef.123"; + memmove(str + 1, str, 5); + printf(strcmp(str, "aabcde.123") == 0 ? "ok\n" : "BAD!\n"); + memmove(str, str + 1, 5); + printf(strcmp(str, "abcdee.123") == 0 ? "ok\n" : "BAD!\n"); +} +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/i386/memset.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/i386/memset.c new file mode 100644 index 00000000..9f51f3c6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/i386/memset.c @@ -0,0 +1,95 @@ +/* + * This string-include defines all string functions as inline + * functions. Use gcc. It also assumes ds=es=data space, this should be + * normal. Most of the string-functions are rather heavily hand-optimized, + * see especially strtok,strstr,str[c]spn. They should work, but are not + * very easy to understand. Everything is done entirely within the register + * set, making the functions fast and clean. String instructions have been + * used through-out, making for "slightly" unclear code :-) + * + * NO Copyright (C) 1991, 1992 Linus Torvalds, + * consider these trivial functions to be PD. + */ + +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* + * Modified for uClibc by Erik Andersen + * These make no attempt to use nifty things like mmx/3dnow/etc. + * These are not inline, and will therefore not be as fast as + * modifying the headers to use inlines (and cannot therefore + * do tricky things when dealing with const memory). But they + * should (I hope!) be faster than their generic equivalents.... + * + * More importantly, these should provide a good example for + * others to follow when adding arch specific optimizations. + * -Erik + * + * 2009-04: modified by Denys Vlasenko + * Fill byte-by-byte is a bit too slow. I prefer 46 byte function + * which fills x4 faster than 21 bytes one. + */ + +#include + +#undef memset +void *memset(void *s, int c, size_t count) +{ + int reg, edi; + __asm__ __volatile__( + + /* Most of the time, count is divisible by 4 and nonzero */ + /* It's better to make this case faster */ + /* " jecxz 9f\n" - (optional) count == 0: goto ret */ + " mov %%ecx, %1\n" + " shr $2, %%ecx\n" + " jz 1f\n" /* zero words: goto fill_bytes */ + /* extend 8-bit fill to 32 bits */ + " movzx %%al, %%eax\n" /* 3 bytes */ + /* or: " and $0xff, %%eax\n" - 5 bytes */ + " imul $0x01010101, %%eax\n" /* 6 bytes */ + /* fill full words */ + " rep; stosl\n" + /* fill 0-3 bytes */ + "1: and $3, %1\n" + " jz 9f\n" /* (count & 3) == 0: goto end */ + "2: stosb\n" + " dec %1\n" + " jnz 2b\n" + /* end */ + "9:\n" + + : "=&D" (edi), "=&r" (reg) + : "0" (s), "a" (c), "c" (count) + : "memory" + ); + return s; +} +libc_hidden_def(memset) + +/* +gcc 4.3.1 +========= +57 push %edi +8b 7c 24 08 mov 0x8(%esp),%edi +8b 4c 24 10 mov 0x10(%esp),%ecx +8b 44 24 0c mov 0xc(%esp),%eax +89 ca mov %ecx,%edx +c1 e9 02 shr $0x2,%ecx +74 0b je 1f <__GI_memset+0x1f> +0f b6 c0 movzbl %al,%eax +69 c0 01 01 01 01 imul $0x1010101,%eax,%eax +f3 ab rep stos %eax,%es:(%edi) +83 e2 03 and $0x3,%edx +74 04 je 28 <__GI_memset+0x28> +aa stos %al,%es:(%edi) +4a dec %edx +75 fc jne 24 <__GI_memset+0x24> +8b 44 24 08 mov 0x8(%esp),%eax +5f pop %edi +c3 ret +*/ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/i386/rawmemchr.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/i386/rawmemchr.c new file mode 100644 index 00000000..be0b142c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/i386/rawmemchr.c @@ -0,0 +1,24 @@ +/* + * Adapted from strlen.c code + * + * Copyright (C) 2008 Denys Vlasenko + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +#undef rawmemchr +void *rawmemchr(const void *s, int c) +{ + void *eax; + int ecx, edi; + __asm__ __volatile__( + " repne; scasb\n" + " leal -1(%%edi), %%eax\n" + : "=&c" (ecx), "=&D" (edi), "=&a" (eax) + : "0" (0xffffffff), "1" (s), "2" (c) + ); + return eax; +} +libc_hidden_def(rawmemchr) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/i386/strcat.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/i386/strcat.c new file mode 100644 index 00000000..e71aad4f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/i386/strcat.c @@ -0,0 +1,50 @@ +/* + * This string-include defines all string functions as inline + * functions. Use gcc. It also assumes ds=es=data space, this should be + * normal. Most of the string-functions are rather heavily hand-optimized, + * see especially strtok,strstr,str[c]spn. They should work, but are not + * very easy to understand. Everything is done entirely within the register + * set, making the functions fast and clean. String instructions have been + * used through-out, making for "slightly" unclear code :-) + * + * NO Copyright (C) 1991, 1992 Linus Torvalds, + * consider these trivial functions to be PD. + */ + +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* + * Modified for uClibc by Erik Andersen + * These make no attempt to use nifty things like mmx/3dnow/etc. + * These are not inline, and will therefore not be as fast as + * modifying the headers to use inlines (and cannot therefore + * do tricky things when dealing with const memory). But they + * should (I hope!) be faster than their generic equivalents.... + * + * More importantly, these should provide a good example for + * others to follow when adding arch specific optimizations. + * -Erik + */ + +#include + +char *strcat(char * dest, const char * src) +{ + int d0, d1, d2, d3; + __asm__ __volatile__( + "repne\n\t" + "scasb\n\t" + "decl %1\n" + "1:\tlodsb\n\t" + "stosb\n\t" + "testb %%al,%%al\n\t" + "jne 1b" + : "=&S" (d0), "=&D" (d1), "=&a" (d2), "=&c" (d3) + : "0" (src), "1" (dest), "2" (0), "3" (0xffffffff):"memory"); + return dest; +} +libc_hidden_def(strcat) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/i386/strchr.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/i386/strchr.c new file mode 100644 index 00000000..93cc9583 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/i386/strchr.c @@ -0,0 +1,58 @@ +/* + * This string-include defines all string functions as inline + * functions. Use gcc. It also assumes ds=es=data space, this should be + * normal. Most of the string-functions are rather heavily hand-optimized, + * see especially strtok,strstr,str[c]spn. They should work, but are not + * very easy to understand. Everything is done entirely within the register + * set, making the functions fast and clean. String instructions have been + * used through-out, making for "slightly" unclear code :-) + * + * NO Copyright (C) 1991, 1992 Linus Torvalds, + * consider these trivial functions to be PD. + */ + +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* + * Modified for uClibc by Erik Andersen + * These make no attempt to use nifty things like mmx/3dnow/etc. + * These are not inline, and will therefore not be as fast as + * modifying the headers to use inlines (and cannot therefore + * do tricky things when dealing with const memory). But they + * should (I hope!) be faster than their generic equivalents.... + * + * More importantly, these should provide a good example for + * others to follow when adding arch specific optimizations. + * -Erik + */ + +#include + +#undef strchr +char *strchr(const char *s, int c) +{ + int esi; + register char * eax; + __asm__ __volatile__( + " movb %%al, %%ah\n" + "1: lodsb\n" + " cmpb %%ah, %%al\n" + " je 2f\n" + " testb %%al, %%al\n" + " jnz 1b\n" + " movl $1, %%esi\n" /* can use shorter xor + inc */ + "2: leal -1(%%esi), %%eax\n" + : "=a" (eax), "=&S" (esi) + : "0" (c), "1" (s) + /* no clobbers */ + ); + return eax; +} +libc_hidden_def(strchr) +#ifdef __UCLIBC_SUSV3_LEGACY__ +strong_alias(strchr,index) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/i386/strchrnul.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/i386/strchrnul.c new file mode 100644 index 00000000..d4842721 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/i386/strchrnul.c @@ -0,0 +1,47 @@ +/* + * Adapted from strchr.c code + * + * Copyright (C) 2008 Denys Vlasenko + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +#undef strchrnul +/*#define strchrnul TESTING*/ +char *strchrnul(const char *s, int c) +{ + int esi; + char *eax; + __asm__ __volatile__( + " movb %%al, %%ah\n" + "1: lodsb\n" + " cmpb %%ah, %%al\n" + " je 2f\n" + " testb %%al, %%al\n" + " jnz 1b\n" + /* with this, we'd get strchr(): */ + /* " movl $1, %%esi\n" */ + "2: leal -1(%%esi), %%eax\n" + : "=a" (eax), "=&S" (esi) + : "0" (c), "1" (s) + /* no clobbers */ + ); + return eax; +} +#ifndef strchrnul +libc_hidden_def(strchrnul) +#else +/* Uncomment TESTING, gcc -D_GNU_SOURCE -m32 -Os strchrnul.c -o strchrnul + * and run ./strchrnul + */ +int main() +{ + static const char str[] = "abc.def"; + printf((char*)strchrnul(str, '.') - str == 3 ? "ok\n" : "BAD!\n"); + printf((char*)strchrnul(str, '*') - str == 7 ? "ok\n" : "BAD!\n"); + printf((char*)strchrnul(str, 0) - str == 7 ? "ok\n" : "BAD!\n"); + printf((char*)strchrnul(str+3, '.') - str == 3 ? "ok\n" : "BAD!\n"); +} +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/i386/strcmp.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/i386/strcmp.c new file mode 100644 index 00000000..9621f66f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/i386/strcmp.c @@ -0,0 +1,59 @@ +/* + * This string-include defines all string functions as inline + * functions. Use gcc. It also assumes ds=es=data space, this should be + * normal. Most of the string-functions are rather heavily hand-optimized, + * see especially strtok,strstr,str[c]spn. They should work, but are not + * very easy to understand. Everything is done entirely within the register + * set, making the functions fast and clean. String instructions have been + * used through-out, making for "slightly" unclear code :-) + * + * NO Copyright (C) 1991, 1992 Linus Torvalds, + * consider these trivial functions to be PD. + */ + +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* + * Modified for uClibc by Erik Andersen + * These make no attempt to use nifty things like mmx/3dnow/etc. + * These are not inline, and will therefore not be as fast as + * modifying the headers to use inlines (and cannot therefore + * do tricky things when dealing with const memory). But they + * should (I hope!) be faster than their generic equivalents.... + * + * More importantly, these should provide a good example for + * others to follow when adding arch specific optimizations. + * -Erik + */ + +#include + +int strcmp(const char *cs, const char *ct) +{ + int d0, d1; + register int __res; + __asm__ __volatile__( + "1:\tlodsb\n\t" + "scasb\n\t" + "jne 2f\n\t" + "testb %%al,%%al\n\t" + "jne 1b\n\t" + "xorl %%eax,%%eax\n\t" + "jmp 3f\n" + "2:\tsbbl %%eax,%%eax\n\t" + "orb $1,%%al\n" + "3:" + :"=a" (__res), "=&S" (d0), "=&D" (d1) + :"1" (cs),"2" (ct)); + return __res; +} +libc_hidden_def(strcmp) + +#ifndef __UCLIBC_HAS_LOCALE__ +strong_alias(strcmp,strcoll) +libc_hidden_def(strcoll) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/i386/strcpy.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/i386/strcpy.c new file mode 100644 index 00000000..fff1bd00 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/i386/strcpy.c @@ -0,0 +1,48 @@ +/* + * This string-include defines all string functions as inline + * functions. Use gcc. It also assumes ds=es=data space, this should be + * normal. Most of the string-functions are rather heavily hand-optimized, + * see especially strtok,strstr,str[c]spn. They should work, but are not + * very easy to understand. Everything is done entirely within the register + * set, making the functions fast and clean. String instructions have been + * used through-out, making for "slightly" unclear code :-) + * + * NO Copyright (C) 1991, 1992 Linus Torvalds, + * consider these trivial functions to be PD. + */ + +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* + * Modified for uClibc by Erik Andersen + * These make no attempt to use nifty things like mmx/3dnow/etc. + * These are not inline, and will therefore not be as fast as + * modifying the headers to use inlines (and cannot therefore + * do tricky things when dealing with const memory). But they + * should (I hope!) be faster than their generic equivalents.... + * + * More importantly, these should provide a good example for + * others to follow when adding arch specific optimizations. + * -Erik + */ + +#include + +#undef strcpy +char *strcpy(char * dest, const char * src) +{ + int d0, d1, d2; + __asm__ __volatile__( + "1:\tlodsb\n\t" + "stosb\n\t" + "testb %%al,%%al\n\t" + "jne 1b" + : "=&S" (d0), "=&D" (d1), "=&a" (d2) + :"0" (src),"1" (dest) : "memory"); + return dest; +} +libc_hidden_def(strcpy) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/i386/string.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/i386/string.h new file mode 100644 index 00000000..352a3dcd --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/i386/string.h @@ -0,0 +1,338 @@ +/* + * Copyright (C) 2008 Denys Vlasenko + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball + */ + +#if !defined _STRING_H +#error "Never use directly; include instead" +#endif + +#ifndef _LIBC_STRING_i386_H +#define _LIBC_STRING_i386_H 1 + +static __always_inline +void *inlined_memset_const_c_count4(void *s, unsigned eax, unsigned count) +{ + int ecx, edi; + + if (count == 0) + return s; + + /* Very small (2 stores or less) are best done with direct + * mov , instructions (they do not clobber registers) */ + if (count == 1) { + *(char *)((char *)s + 0) = eax; + return s; + } + + /* You wonder why & 0xff is needed? Try memset(p, '\xff', size). + * If char is signed, '\xff' == -1! */ + eax = (eax & 0xff) * 0x01010101; /* done at compile time */ + + if (count == 2) { + *(short *)((char *)s + 0) = eax; + return s; + } + if (count == 3) { + *(short *)((char *)s + 0) = eax; + *(char *) ((char *)s + 2) = eax; + return s; + } + if (count == 1*4 + 0) { + *(int *)((char *)s + 0) = eax; + return s; + } + if (count == 1*4 + 1) { + *(int *) ((char *)s + 0) = eax; + *(char *)((char *)s + 4) = eax; + return s; + } + if (count == 1*4 + 2) { + *(int *) ((char *)s + 0) = eax; + *(short *)((char *)s + 4) = eax; + return s; + } + + /* Small string stores: don't clobber ecx + * (clobbers only eax and edi) */ +#define small_store(arg) { \ + __asm__ __volatile__( \ + arg \ + : "=&D" (edi) \ + : "a" (eax), "0" (s) \ + : "memory" \ + ); \ + return s; \ +} + if (count == 1*4 + 3) small_store("stosl; stosw; stosb"); + if (count == 2*4 + 0) { + ((int *)s)[0] = eax; + ((int *)s)[1] = eax; + return s; + } + if (count == 2*4 + 1) small_store("stosl; stosl; stosb"); + if (count == 2*4 + 2) small_store("stosl; stosl; stosw"); + if (count == 2*4 + 3) small_store("stosl; stosl; stosw; stosb"); + if (count == 3*4 + 0) small_store("stosl; stosl; stosl"); + if (count == 3*4 + 1) small_store("stosl; stosl; stosl; stosb"); + if (count == 3*4 + 2) small_store("stosl; stosl; stosl; stosw"); + if (count == 3*4 + 3) small_store("stosl; stosl; stosl; stosw; stosb"); + if (count == 4*4 + 0) small_store("stosl; stosl; stosl; stosl"); + if (count == 4*4 + 1) small_store("stosl; stosl; stosl; stosl; stosb"); + /* going over 7 bytes is suboptimal */ + /* stosw is 2-byte insn, so this one takes 6 bytes: */ + if (count == 4*4 + 2) small_store("stosl; stosl; stosl; stosl; stosw"); + /* 7 bytes */ + if (count == 4*4 + 3) small_store("stosl; stosl; stosl; stosl; stosw; stosb"); + /* 5 bytes */ + if (count == 5*4 + 0) small_store("stosl; stosl; stosl; stosl; stosl"); + /* 6 bytes */ + if (count == 5*4 + 1) small_store("stosl; stosl; stosl; stosl; stosl; stosb"); + /* 7 bytes */ + if (count == 5*4 + 2) small_store("stosl; stosl; stosl; stosl; stosl; stosw"); + /* 8 bytes, but oh well... */ + if (count == 5*4 + 3) small_store("stosl; stosl; stosl; stosl; stosl; stosw; stosb"); + /* 6 bytes */ + if (count == 6*4 + 0) small_store("stosl; stosl; stosl; stosl; stosl; stosl"); + /* the rest would be 7+ bytes and is handled below instead */ +#undef small_store + + /* Not small, but multiple-of-4 store. + * "mov ,%ecx; rep; stosl" sequence is 7 bytes */ + __asm__ __volatile__( + " rep; stosl\n" + : "=&c" (ecx), "=&D" (edi) + : "a" (eax), "0" (count / 4), "1" (s) + : "memory" + ); + return s; +} +#if 1 /* -51 bytes on shared i386 build with gcc 4.3.0 */ +#define memset(s, c, count) ( \ + ( !(__builtin_constant_p(c) && __builtin_constant_p(count)) \ + || ((count) > (6*4 + 0) && ((count) % 4) != 0) \ + ) \ + ? memset((s), (c), (count)) \ + : inlined_memset_const_c_count4((s), (c), (count)) \ + ) +#endif + + +static __always_inline +void *inlined_mempcpy_const_count4(void *d, const void *s, unsigned count) +{ + int ecx; + char *esi, *edi; + + if (count == 0) + return d; + + if (count == 1) { + *(char *)d = *(char *)s; + return (char *)d + 1; + } + if (count == 2) { + *(short *)d = *(short *)s; + return (char *)d + 2; + } + /* Small string moves: don't clobber ecx + * (clobbers only esi and edi) */ +#define small_move(arg) { \ + __asm__ __volatile__( \ + arg \ + : "=&S" (esi), "=&D" (edi) \ + : "0" (s), "1" (d) \ + : "memory" \ + ); \ + return edi; \ +} + if (count == 3) small_move("movsw; movsb"); + if (count == 1*4 + 0) { + *(int *)d = *(int *)s; + return (char *)d + 4; + } + if (count == 1*4 + 1) small_move("movsl; movsb"); + if (count == 1*4 + 2) small_move("movsl; movsw"); + if (count == 1*4 + 3) small_move("movsl; movsw; movsb"); + if (count == 2*4 + 0) small_move("movsl; movsl"); + if (count == 2*4 + 1) small_move("movsl; movsl; movsb"); + if (count == 2*4 + 2) small_move("movsl; movsl; movsw"); + if (count == 2*4 + 3) small_move("movsl; movsl; movsw; movsb"); + if (count == 3*4 + 0) small_move("movsl; movsl; movsl"); + if (count == 3*4 + 1) small_move("movsl; movsl; movsl; movsb"); + if (count == 3*4 + 2) small_move("movsl; movsl; movsl; movsw"); + if (count == 3*4 + 3) small_move("movsl; movsl; movsl; movsw; movsb"); + if (count == 4*4 + 0) small_move("movsl; movsl; movsl; movsl"); + if (count == 4*4 + 1) small_move("movsl; movsl; movsl; movsl; movsb"); + /* going over 7 bytes is suboptimal */ + /* movsw is 2-byte insn, so this one takes 6 bytes: */ + if (count == 4*4 + 2) small_move("movsl; movsl; movsl; movsl; movsw"); + /* 7 bytes */ + if (count == 4*4 + 3) small_move("movsl; movsl; movsl; movsl; movsw; movsb"); + /* 5 bytes */ + if (count == 5*4 + 0) small_move("movsl; movsl; movsl; movsl; movsl"); + /* 6 bytes */ + if (count == 5*4 + 1) small_move("movsl; movsl; movsl; movsl; movsl; movsb"); + /* 7 bytes */ + if (count == 5*4 + 2) small_move("movsl; movsl; movsl; movsl; movsl; movsw"); + /* 8 bytes, but oh well... */ + if (count == 5*4 + 3) small_move("movsl; movsl; movsl; movsl; movsl; movsw; movsb"); + /* 6 bytes */ + if (count == 6*4 + 0) small_move("movsl; movsl; movsl; movsl; movsl; movsl"); + /* the rest would be 7+ bytes and is handled below instead */ +#undef small_move + + /* Not small, but multiple-of-4 move. + * "mov ,%ecx; rep; movsl" sequence is 7 bytes */ + __asm__ __volatile__( + " rep; movsl\n" + : "=&c" (ecx), "=&S" (esi), "=&D" (edi) + : "0" (count / 4), "1" (s), "2" (d) + : "memory" + ); + return edi; +} +static __always_inline +void *inlined_memcpy_const_count4(void *d, const void *s, unsigned count) +{ + inlined_mempcpy_const_count4(d, s, count); + return d; +} +#if 1 /* +34 bytes on shared i386 build with gcc 4.3.0 */ +#define mempcpy(d, s, count) ( \ + ( !(__builtin_constant_p(count)) \ + || ((count) > (6*4 + 0) && ((count) % 4) != 0) \ + ) \ + ? mempcpy((d), (s), (count)) \ + : inlined_mempcpy_const_count4((d), (s), (count)) \ + ) +#define memcpy(d, s, count) ( \ + ( !(__builtin_constant_p(count)) \ + || ((count) > (6*4 + 0) && ((count) % 4) != 0) \ + ) \ + ? memcpy((d), (s), (count)) \ + : inlined_memcpy_const_count4((d), (s), (count)) \ + ) +#endif + + +static __always_inline +size_t inlined_strlen(const char *s) +{ + int edi; + int ecx; + __asm__ __volatile__( + " repne; scasb\n" + /* " notl %0\n" */ + /* " decl %0\n" */ + : "=c" (ecx), "=&D" (edi) + : "1" (s), "a" (0), "0" (0xffffffffu) + /* : no clobbers */ + ); + return -ecx - 1; +} +#if 0 /* +1108 bytes on shared i386 build with gcc 4.3.0 */ +#define strlen(s) inlined_strlen(s) +#endif + + +static __always_inline +char *inlined_stpcpy(char *dest, const char *src) +{ + char *esi, *edi; + int eax; + __asm__ __volatile__( + "1: lodsb\n" + " stosb\n" + " testb %%al, %%al\n" + " jnz 1b\n" + : "=&S" (esi), "=&D" (edi), "=&a" (eax) + : "0" (src), "1" (dest) + : "memory" + ); + return edi - 1; +} +static __always_inline +char *inlined_strcpy(char *dest, const char *src) +{ + inlined_stpcpy(dest, src); + return dest; +} +#if 0 /* +562 bytes on shared i386 build with gcc 4.3.0 */ +#define stpcpy(dest, src) inlined_stpcpy(dest, src) +#define strcpy(dest, src) inlined_strcpy(dest, src) +#endif + + +static __always_inline +void *inlined_memchr(const void *s, int c, size_t count) +{ + void *edi; + int ecx; + /* Unfortunately, c gets loaded to %eax (wide insn), not %al */ + __asm__ __volatile__( + " jecxz 1f\n" + " repne; scasb\n" + " leal -1(%%edi), %%edi\n" + " je 2f\n" + "1:\n" + " xorl %%edi, %%edi\n" + "2:\n" + : "=&D" (edi), "=&c" (ecx) + : "a" (c), "0" (s), "1" (count) + /* : no clobbers */ + ); + return edi; +} +static __always_inline +void *inlined_memchr_const_c(const void *s, int c, size_t count) +{ +#if defined __OPTIMIZE__ + void *edi; + int ecx, eax; + __asm__ __volatile__( + " jecxz 1f\n" + " movb %4, %%al\n" /* const c to %%al */ + " repne; scasb\n" + " leal -1(%%edi), %%edi\n" + " je 2f\n" + "1:\n" + " xorl %%edi, %%edi\n" + "2:\n" + : "=&D" (edi), "=&c" (ecx), "=&a" (eax) + : "0" (s), "i" (c), "1" (count) + /* : no clobbers */ + ); + return edi; +#else + /* With -O0, gcc can't figure out how to encode CONST c + * as an immediate operand. Generating slightly bigger code + * (usually "movl CONST,%eax", 3 bytes bigger than needed): + */ + void *edi; + int ecx, eax; + __asm__ __volatile__( + " jecxz 1f\n" + " repne; scasb\n" + " leal -1(%%edi), %%edi\n" + " je 2f\n" + "1:\n" + " xorl %%edi, %%edi\n" + "2:\n" + : "=&D" (edi), "=&c" (ecx), "=&a" (eax) + : "0" (s), "2" (c), "1" (count) + /* : no clobbers */ + ); + return edi; +#endif +} +#if 1 /* +2 bytes on shared i386 build with gcc 4.3.0 */ +#define memchr(s, c, count) ( \ + __builtin_constant_p(c) \ + ? inlined_memchr_const_c(s, (c) & 0xff, count) \ + : inlined_memchr(s, c, count) \ + ) +#endif + +#endif /* _LIBC_STRING_i386_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/i386/strlen.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/i386/strlen.c new file mode 100644 index 00000000..ff2baeb3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/i386/strlen.c @@ -0,0 +1,48 @@ +/* + * This string-include defines all string functions as inline + * functions. Use gcc. It also assumes ds=es=data space, this should be + * normal. Most of the string-functions are rather heavily hand-optimized, + * see especially strtok,strstr,str[c]spn. They should work, but are not + * very easy to understand. Everything is done entirely within the register + * set, making the functions fast and clean. String instructions have been + * used through-out, making for "slightly" unclear code :-) + * + * NO Copyright (C) 1991, 1992 Linus Torvalds, + * consider these trivial functions to be PD. + */ + +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* + * Modified for uClibc by Erik Andersen + * These make no attempt to use nifty things like mmx/3dnow/etc. + * These are not inline, and will therefore not be as fast as + * modifying the headers to use inlines (and cannot therefore + * do tricky things when dealing with const memory). But they + * should (I hope!) be faster than their generic equivalents.... + * + * More importantly, these should provide a good example for + * others to follow when adding arch specific optimizations. + * -Erik + */ + +#include + +#undef strlen +size_t strlen(const char *s) +{ + int eax, ecx, edi; + __asm__ __volatile__( + " repne; scasb\n" + " notl %%ecx\n" + " leal -1(%%ecx), %%eax\n" + : "=&c" (ecx), "=&D" (edi), "=&a" (eax) + : "0" (0xffffffff), "1" (s), "2" (0) + ); + return eax; +} +libc_hidden_def(strlen) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/i386/strncat.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/i386/strncat.c new file mode 100644 index 00000000..12f0a302 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/i386/strncat.c @@ -0,0 +1,86 @@ +/* + * This string-include defines all string functions as inline + * functions. Use gcc. It also assumes ds=es=data space, this should be + * normal. Most of the string-functions are rather heavily hand-optimized, + * see especially strtok,strstr,str[c]spn. They should work, but are not + * very easy to understand. Everything is done entirely within the register + * set, making the functions fast and clean. String instructions have been + * used through-out, making for "slightly" unclear code :-) + * + * NO Copyright (C) 1991, 1992 Linus Torvalds, + * consider these trivial functions to be PD. + */ + +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* + * Modified for uClibc by Erik Andersen + * These make no attempt to use nifty things like mmx/3dnow/etc. + * These are not inline, and will therefore not be as fast as + * modifying the headers to use inlines (and cannot therefore + * do tricky things when dealing with const memory). But they + * should (I hope!) be faster than their generic equivalents.... + * + * More importantly, these should provide a good example for + * others to follow when adding arch specific optimizations. + * -Erik + */ + +#include + +#undef strncat +/*#define strncat TESTING*/ +char *strncat(char * dest, const char * src, size_t count) +{ + int esi, edi, eax, ecx, edx; + __asm__ __volatile__( + " xorl %%eax, %%eax\n" + " incl %%edx\n" + " pushl %%edi\n" /* save dest */ + " repne; scasb\n" + " decl %%edi\n" /* edi => NUL in dest */ + /* count-- */ + "1: decl %%edx\n" + /* if count reached 0, store NUL and bail out */ + " movl %%edx, %%eax\n" + " jz 2f\n" + /* else copy a char */ + " lodsb\n" + "2: stosb\n" + " testb %%al, %%al\n" + " jnz 1b\n" + /* end of loop */ + " popl %%eax\n" /* restore dest into eax */ + : "=&S" (esi), "=&D" (edi), "=&a" (eax), "=&c" (ecx), "=&d" (edx) + : "0" (src), "1" (dest), "3" (0xffffffff), "4" (count) + : "memory" + ); + return (char *)eax; +} +#ifndef strncat +libc_hidden_def(strncat) +#else +/* Uncomment TESTING, gcc -m32 -Os strncat.c -o strncat + * and run ./strncat + */ +int main() +{ + char buf[99]; + + strcpy(buf, "abc"); buf[4] = '*'; strncat(buf, "def", 0); + printf(strcmp(buf, "abc") == 0 && buf[4] == '*' ? "ok\n" : "BAD!\n"); + + strcpy(buf, "abc"); buf[6] = 1; buf[7] = '*'; strncat(buf, "def", 50); + printf(strcmp(buf, "abcdef") == 0 && buf[7] == '*' ? "ok\n" : "BAD!\n"); + + strcpy(buf, "abc"); buf[6] = 1; buf[7] = '*'; strncat(buf, "def", -1); + printf(strcmp(buf, "abcdef") == 0 && buf[7] == '*' ? "ok\n" : "BAD!\n"); + + strcpy(buf, "abc"); buf[6] = 1; buf[7] = '*'; strncat(buf, "def123", 3); + printf(strcmp(buf, "abcdef") == 0 && buf[7] == '*' ? "ok\n" : "BAD!\n"); +} +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/i386/strncmp.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/i386/strncmp.c new file mode 100644 index 00000000..bfb20c30 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/i386/strncmp.c @@ -0,0 +1,59 @@ +/* + * This string-include defines all string functions as inline + * functions. Use gcc. It also assumes ds=es=data space, this should be + * normal. Most of the string-functions are rather heavily hand-optimized, + * see especially strtok,strstr,str[c]spn. They should work, but are not + * very easy to understand. Everything is done entirely within the register + * set, making the functions fast and clean. String instructions have been + * used through-out, making for "slightly" unclear code :-) + * + * NO Copyright (C) 1991, 1992 Linus Torvalds, + * consider these trivial functions to be PD. + */ + +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* + * Modified for uClibc by Erik Andersen + * These make no attempt to use nifty things like mmx/3dnow/etc. + * These are not inline, and will therefore not be as fast as + * modifying the headers to use inlines (and cannot therefore + * do tricky things when dealing with const memory). But they + * should (I hope!) be faster than their generic equivalents.... + * + * More importantly, these should provide a good example for + * others to follow when adding arch specific optimizations. + * -Erik + */ + +#include + +#undef strncmp +int strncmp(const char *cs, const char *ct, size_t count) +{ + int eax; + int esi, edi, ecx; + __asm__ __volatile__( + " incl %%ecx\n" + "1: decl %%ecx\n" + " jz 2f\n" + " lodsb\n" + " scasb\n" + " jne 3f\n" + " testb %%al, %%al\n" + " jnz 1b\n" + "2: xorl %%eax, %%eax\n" + " jmp 4f\n" + "3: sbbl %%eax, %%eax\n" + " orb $1, %%al\n" + "4:\n" + : "=a" (eax), "=&S" (esi), "=&D" (edi), "=&c" (ecx) + : "1" (cs), "2" (ct), "3" (count) + ); + return eax; +} +libc_hidden_weak(strncmp) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/i386/strncpy.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/i386/strncpy.c new file mode 100644 index 00000000..99d104b0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/i386/strncpy.c @@ -0,0 +1,75 @@ +/* + * This string-include defines all string functions as inline + * functions. Use gcc. It also assumes ds=es=data space, this should be + * normal. Most of the string-functions are rather heavily hand-optimized, + * see especially strtok,strstr,str[c]spn. They should work, but are not + * very easy to understand. Everything is done entirely within the register + * set, making the functions fast and clean. String instructions have been + * used through-out, making for "slightly" unclear code :-) + * + * NO Copyright (C) 1991, 1992 Linus Torvalds, + * consider these trivial functions to be PD. + */ + +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* + * Modified for uClibc by Erik Andersen + * These make no attempt to use nifty things like mmx/3dnow/etc. + * These are not inline, and will therefore not be as fast as + * modifying the headers to use inlines (and cannot therefore + * do tricky things when dealing with const memory). But they + * should (I hope!) be faster than their generic equivalents.... + * + * More importantly, these should provide a good example for + * others to follow when adding arch specific optimizations. + * -Erik + */ + +#include + +#undef strncpy +/*#define strncpy TESTING*/ +char *strncpy(char * dest, const char * src, size_t count) +{ + int esi, edi, ecx, eax; + __asm__ __volatile__( + "1: subl $1, %%ecx\n" /* not dec! it doesnt set CF */ + " jc 2f\n" + " lodsb\n" + " stosb\n" + " testb %%al, %%al\n" + " jnz 1b\n" + " rep; stosb\n" + "2:\n" + : "=&S" (esi), "=&D" (edi), "=&c" (ecx), "=&a" (eax) + : "0" (src), "1" (dest), "2" (count) + : "memory" + ); + return dest; +} +#ifndef strncpy +libc_hidden_def(strncpy) +#else +/* Uncomment TESTING, gcc -D_GNU_SOURCE -m32 -Os strncpy.c -o strncpy + * and run ./strncpy + */ +int main() +{ + static char str[99]; + + str[3] = '*'; str[4] = 0; strncpy(str, "abc", 3); + printf(strcmp(str, "abc*") == 0 ? "ok\n" : "BAD!\n"); + + str[4] = '*'; str[5] = '+'; strncpy(str, "abc", 5); + printf(strcmp(str, "abc") == 0 && str[4] == 0 && str[5] == '+' ? + "ok\n" : "BAD!\n"); + strncpy(str, "def", 0); /* should do nothing */ + printf(strcmp(str, "abc") == 0 && str[4] == 0 && str[5] == '+' ? + "ok\n" : "BAD!\n"); +} +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/i386/strnlen.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/i386/strnlen.c new file mode 100644 index 00000000..f58f698d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/i386/strnlen.c @@ -0,0 +1,75 @@ +/* + * This string-include defines all string functions as inline + * functions. Use gcc. It also assumes ds=es=data space, this should be + * normal. Most of the string-functions are rather heavily hand-optimized, + * see especially strtok,strstr,str[c]spn. They should work, but are not + * very easy to understand. Everything is done entirely within the register + * set, making the functions fast and clean. String instructions have been + * used through-out, making for "slightly" unclear code :-) + * + * NO Copyright (C) 1991, 1992 Linus Torvalds, + * consider these trivial functions to be PD. + */ + +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* + * Modified for uClibc by Erik Andersen + * These make no attempt to use nifty things like mmx/3dnow/etc. + * These are not inline, and will therefore not be as fast as + * modifying the headers to use inlines (and cannot therefore + * do tricky things when dealing with const memory). But they + * should (I hope!) be faster than their generic equivalents.... + * + * More importantly, these should provide a good example for + * others to follow when adding arch specific optimizations. + * -Erik + */ + +#include + +#ifdef __USE_GNU + +#undef strnlen +/*#define strnlen TESTING*/ +size_t strnlen(const char *s, size_t count) +{ + int edx; + int eax; + __asm__ __volatile__( + " leal -1(%%ecx), %%eax\n" + "1: incl %%eax\n" + " decl %%edx\n" + " jz 3f\n" + " cmpb $0, (%%eax)\n" + " jnz 1b\n" + "3: subl %%ecx, %%eax" + : "=a" (eax), "=&d" (edx) + : "c" (s), "1" (count + 1) + ); + return eax; +} +#ifndef strnlen +libc_hidden_def(strnlen) +#else +/* Uncomment TESTING, gcc -D_GNU_SOURCE -m32 -Os strnlen.c -o strnlen + * and run ./strnlen + */ +int main() +{ + printf(strnlen("abc\0def", -2) == 3 ? "ok\n" : "BAD!\n"); + printf(strnlen("abc\0def", -1) == 3 ? "ok\n" : "BAD!\n"); + printf(strnlen("abc\0def", 0) == 0 ? "ok\n" : "BAD!\n"); + printf(strnlen("abc\0def", 1) == 1 ? "ok\n" : "BAD!\n"); + printf(strnlen("abc\0def", 2) == 2 ? "ok\n" : "BAD!\n"); + printf(strnlen("abc\0def", 3) == 3 ? "ok\n" : "BAD!\n"); + printf(strnlen("abc\0def", 4) == 3 ? "ok\n" : "BAD!\n"); + printf(strnlen("abc\0def", 5) == 3 ? "ok\n" : "BAD!\n"); +} +#endif + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/i386/strrchr.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/i386/strrchr.c new file mode 100644 index 00000000..5c349f68 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/i386/strrchr.c @@ -0,0 +1,58 @@ +/* + * This string-include defines all string functions as inline + * functions. Use gcc. It also assumes ds=es=data space, this should be + * normal. Most of the string-functions are rather heavily hand-optimized, + * see especially strtok,strstr,str[c]spn. They should work, but are not + * very easy to understand. Everything is done entirely within the register + * set, making the functions fast and clean. String instructions have been + * used through-out, making for "slightly" unclear code :-) + * + * NO Copyright (C) 1991, 1992 Linus Torvalds, + * consider these trivial functions to be PD. + */ + +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* + * Modified for uClibc by Erik Andersen + * These make no attempt to use nifty things like mmx/3dnow/etc. + * These are not inline, and will therefore not be as fast as + * modifying the headers to use inlines (and cannot therefore + * do tricky things when dealing with const memory). But they + * should (I hope!) be faster than their generic equivalents.... + * + * More importantly, these should provide a good example for + * others to follow when adding arch specific optimizations. + * -Erik + */ + +#include + +char *strrchr(const char *s, int c) +{ + char *eax; + + __asm__ __volatile__( + " movb %%cl, %%ch\n" + "1: movb (%1), %%cl\n" /* load char */ + " cmpb %%cl, %%ch\n" /* char == c? */ + " jne 2f\n" + " movl %1, %%eax\n" + "2: incl %1\n" + " testb %%cl, %%cl\n" /* char == NUL? */ + " jnz 1b\n" + /* "=c": use ecx, not ebx (-fpic uses it). */ + : "=a" (eax), "=r" (s), "=c" (c) + : "0" (0), "1" (s), "2" (c) + /* : no clobbers */ + ); + return eax; +} +libc_hidden_def(strrchr) +#ifdef __UCLIBC_SUSV3_LEGACY__ +strong_alias(strrchr,rindex) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/ia64/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/ia64/Makefile new file mode 100644 index 00000000..0a95346f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/ia64/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir:=../../../ +top_builddir:=../../../ +all: objs +include $(top_builddir)Rules.mak +include ../Makefile.in +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/ia64/bcopy.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/ia64/bcopy.S new file mode 100644 index 00000000..c5637c36 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/ia64/bcopy.S @@ -0,0 +1,14 @@ +#include "sysdep.h" + +#ifdef __UCLIBC_SUSV3_LEGACY__ + +ENTRY(bcopy) + .regstk 3, 0, 0, 0 + mov r8 = in0 + mov in0 = in1 + ;; + mov in1 = r8 + br.cond.sptk.many HIDDEN_JUMPTARGET(memmove) +END(bcopy) + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/ia64/bzero.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/ia64/bzero.S new file mode 100644 index 00000000..1f0f8b7a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/ia64/bzero.S @@ -0,0 +1,320 @@ +/* Optimized version of the standard bzero() function. + This file is part of the GNU C Library. + Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc. + Contributed by Dan Pop for Itanium . + Rewritten for McKinley by Sverre Jarp, HP Labs/CERN + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Return: dest + + Inputs: + in0: dest + in1: count + + The algorithm is fairly straightforward: set byte by byte until we + we get to a 16B-aligned address, then loop on 128 B chunks using an + early store as prefetching, then loop on 32B chucks, then clear remaining + words, finally clear remaining bytes. + Since a stf.spill f0 can store 16B in one go, we use this instruction + to get peak speed. */ + +#include "sysdep.h" + +#ifdef __UCLIBC_SUSV3_LEGACY__ + +#undef ret + +#define dest in0 +#define cnt in1 + +#define tmp r31 +#define save_lc r30 +#define ptr0 r29 +#define ptr1 r28 +#define ptr2 r27 +#define ptr3 r26 +#define ptr9 r24 +#define loopcnt r23 +#define linecnt r22 +#define bytecnt r21 + +/* This routine uses only scratch predicate registers (p6 - p15) */ +#define p_scr p6 /* default register for same-cycle branches */ +#define p_unalgn p9 +#define p_y p11 +#define p_n p12 +#define p_yy p13 +#define p_nn p14 + +#define movi0 mov + +#define MIN1 15 +#define MIN1P1HALF 8 +#define LINE_SIZE 128 +#define LSIZE_SH 7 /* shift amount */ +#define PREF_AHEAD 8 + +#define USE_FLP +#if defined(USE_INT) +#define store st8 +#define myval r0 +#elif defined(USE_FLP) +#define store stf8 +#define myval f0 +#endif + +.align 64 +ENTRY(bzero) +{ .mmi + .prologue + alloc tmp = ar.pfs, 2, 0, 0, 0 + lfetch.nt1 [dest] + .save ar.lc, save_lc + movi0 save_lc = ar.lc +} { .mmi + .body + mov ret0 = dest /* return value */ + nop.m 0 + cmp.eq p_scr, p0 = cnt, r0 +;; } +{ .mmi + and ptr2 = -(MIN1+1), dest /* aligned address */ + and tmp = MIN1, dest /* prepare to check for alignment */ + tbit.nz p_y, p_n = dest, 0 /* Do we have an odd address? (M_B_U) */ +} { .mib + mov ptr1 = dest + nop.i 0 +(p_scr) br.ret.dpnt.many rp /* return immediately if count = 0 */ +;; } +{ .mib + cmp.ne p_unalgn, p0 = tmp, r0 +} { .mib /* NB: # of bytes to move is 1 */ + sub bytecnt = (MIN1+1), tmp /* higher than loopcnt */ + cmp.gt p_scr, p0 = 16, cnt /* is it a minimalistic task? */ +(p_scr) br.cond.dptk.many .move_bytes_unaligned /* go move just a few (M_B_U) */ +;; } +{ .mmi +(p_unalgn) add ptr1 = (MIN1+1), ptr2 /* after alignment */ +(p_unalgn) add ptr2 = MIN1P1HALF, ptr2 /* after alignment */ +(p_unalgn) tbit.nz.unc p_y, p_n = bytecnt, 3 /* should we do a st8 ? */ +;; } +{ .mib +(p_y) add cnt = -8, cnt +(p_unalgn) tbit.nz.unc p_yy, p_nn = bytecnt, 2 /* should we do a st4 ? */ +} { .mib +(p_y) st8 [ptr2] = r0,-4 +(p_n) add ptr2 = 4, ptr2 +;; } +{ .mib +(p_yy) add cnt = -4, cnt +(p_unalgn) tbit.nz.unc p_y, p_n = bytecnt, 1 /* should we do a st2 ? */ +} { .mib +(p_yy) st4 [ptr2] = r0,-2 +(p_nn) add ptr2 = 2, ptr2 +;; } +{ .mmi + mov tmp = LINE_SIZE+1 /* for compare */ +(p_y) add cnt = -2, cnt +(p_unalgn) tbit.nz.unc p_yy, p_nn = bytecnt, 0 /* should we do a st1 ? */ +} { .mmi + nop.m 0 +(p_y) st2 [ptr2] = r0,-1 +(p_n) add ptr2 = 1, ptr2 +;; } + +{ .mmi +(p_yy) st1 [ptr2] = r0 + cmp.gt p_scr, p0 = tmp, cnt /* is it a minimalistic task? */ +} { .mbb +(p_yy) add cnt = -1, cnt +(p_scr) br.cond.dpnt.many .fraction_of_line /* go move just a few */ +;; } +{ .mib + nop.m 0 + shr.u linecnt = cnt, LSIZE_SH + nop.b 0 +;; } + + .align 32 +.l1b: /* ------------------ L1B: store ahead into cache lines; fill later */ +{ .mmi + and tmp = -(LINE_SIZE), cnt /* compute end of range */ + mov ptr9 = ptr1 /* used for prefetching */ + and cnt = (LINE_SIZE-1), cnt /* remainder */ +} { .mmi + mov loopcnt = PREF_AHEAD-1 /* default prefetch loop */ + cmp.gt p_scr, p0 = PREF_AHEAD, linecnt /* check against actual value */ +;; } +{ .mmi +(p_scr) add loopcnt = -1, linecnt + add ptr2 = 16, ptr1 /* start of stores (beyond prefetch stores) */ + add ptr1 = tmp, ptr1 /* first address beyond total range */ +;; } +{ .mmi + add tmp = -1, linecnt /* next loop count */ + movi0 ar.lc = loopcnt +;; } +.pref_l1b: +{ .mib + stf.spill [ptr9] = f0, 128 /* Do stores one cache line apart */ + nop.i 0 + br.cloop.dptk.few .pref_l1b +;; } +{ .mmi + add ptr0 = 16, ptr2 /* Two stores in parallel */ + movi0 ar.lc = tmp +;; } +.l1bx: + { .mmi + stf.spill [ptr2] = f0, 32 + stf.spill [ptr0] = f0, 32 + ;; } + { .mmi + stf.spill [ptr2] = f0, 32 + stf.spill [ptr0] = f0, 32 + ;; } + { .mmi + stf.spill [ptr2] = f0, 32 + stf.spill [ptr0] = f0, 64 + cmp.lt p_scr, p0 = ptr9, ptr1 /* do we need more prefetching? */ + ;; } +{ .mmb + stf.spill [ptr2] = f0, 32 +(p_scr) stf.spill [ptr9] = f0, 128 + br.cloop.dptk.few .l1bx +;; } +{ .mib + cmp.gt p_scr, p0 = 8, cnt /* just a few bytes left ? */ +(p_scr) br.cond.dpnt.many .move_bytes_from_alignment +;; } + +.fraction_of_line: +{ .mib + add ptr2 = 16, ptr1 + shr.u loopcnt = cnt, 5 /* loopcnt = cnt / 32 */ +;; } +{ .mib + cmp.eq p_scr, p0 = loopcnt, r0 + add loopcnt = -1, loopcnt +(p_scr) br.cond.dpnt.many .store_words +;; } +{ .mib + and cnt = 0x1f, cnt /* compute the remaining cnt */ + movi0 ar.lc = loopcnt +;; } + .align 32 +.l2: /* ----------------------------- L2A: store 32B in 2 cycles */ +{ .mmb + store [ptr1] = myval, 8 + store [ptr2] = myval, 8 +;; } { .mmb + store [ptr1] = myval, 24 + store [ptr2] = myval, 24 + br.cloop.dptk.many .l2 +;; } +.store_words: +{ .mib + cmp.gt p_scr, p0 = 8, cnt /* just a few bytes left ? */ +(p_scr) br.cond.dpnt.many .move_bytes_from_alignment /* Branch */ +;; } + +{ .mmi + store [ptr1] = myval, 8 /* store */ + cmp.le p_y, p_n = 16, cnt /* */ + add cnt = -8, cnt /* subtract */ +;; } +{ .mmi +(p_y) store [ptr1] = myval, 8 /* store */ +(p_y) cmp.le.unc p_yy, p_nn = 16, cnt +(p_y) add cnt = -8, cnt /* subtract */ +;; } +{ .mmi /* store */ +(p_yy) store [ptr1] = myval, 8 +(p_yy) add cnt = -8, cnt /* subtract */ +;; } + +.move_bytes_from_alignment: +{ .mib + cmp.eq p_scr, p0 = cnt, r0 + tbit.nz.unc p_y, p0 = cnt, 2 /* should we terminate with a st4 ? */ +(p_scr) br.cond.dpnt.few .restore_and_exit +;; } +{ .mib +(p_y) st4 [ptr1] = r0,4 + tbit.nz.unc p_yy, p0 = cnt, 1 /* should we terminate with a st2 ? */ +;; } +{ .mib +(p_yy) st2 [ptr1] = r0,2 + tbit.nz.unc p_y, p0 = cnt, 0 /* should we terminate with a st1 ? */ +;; } + +{ .mib +(p_y) st1 [ptr1] = r0 +;; } +.restore_and_exit: +{ .mib + nop.m 0 + movi0 ar.lc = save_lc + br.ret.sptk.many rp +;; } + +.move_bytes_unaligned: +{ .mmi + .pred.rel "mutex",p_y, p_n + .pred.rel "mutex",p_yy, p_nn +(p_n) cmp.le p_yy, p_nn = 4, cnt +(p_y) cmp.le p_yy, p_nn = 5, cnt +(p_n) add ptr2 = 2, ptr1 +} { .mmi +(p_y) add ptr2 = 3, ptr1 +(p_y) st1 [ptr1] = r0, 1 /* fill 1 (odd-aligned) byte */ +(p_y) add cnt = -1, cnt /* [15, 14 (or less) left] */ +;; } +{ .mmi +(p_yy) cmp.le.unc p_y, p0 = 8, cnt + add ptr3 = ptr1, cnt /* prepare last store */ + movi0 ar.lc = save_lc +} { .mmi +(p_yy) st2 [ptr1] = r0, 4 /* fill 2 (aligned) bytes */ +(p_yy) st2 [ptr2] = r0, 4 /* fill 2 (aligned) bytes */ +(p_yy) add cnt = -4, cnt /* [11, 10 (o less) left] */ +;; } +{ .mmi +(p_y) cmp.le.unc p_yy, p0 = 8, cnt + add ptr3 = -1, ptr3 /* last store */ + tbit.nz p_scr, p0 = cnt, 1 /* will there be a st2 at the end ? */ +} { .mmi +(p_y) st2 [ptr1] = r0, 4 /* fill 2 (aligned) bytes */ +(p_y) st2 [ptr2] = r0, 4 /* fill 2 (aligned) bytes */ +(p_y) add cnt = -4, cnt /* [7, 6 (or less) left] */ +;; } +{ .mmi +(p_yy) st2 [ptr1] = r0, 4 /* fill 2 (aligned) bytes */ +(p_yy) st2 [ptr2] = r0, 4 /* fill 2 (aligned) bytes */ + /* [3, 2 (or less) left] */ + tbit.nz p_y, p0 = cnt, 0 /* will there be a st1 at the end ? */ +} { .mmi +(p_yy) add cnt = -4, cnt +;; } +{ .mmb +(p_scr) st2 [ptr1] = r0 /* fill 2 (aligned) bytes */ +(p_y) st1 [ptr3] = r0 /* fill last byte (using ptr3) */ + br.ret.sptk.many rp +;; } +END(bzero) + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/ia64/memccpy.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/ia64/memccpy.S new file mode 100644 index 00000000..259d680b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/ia64/memccpy.S @@ -0,0 +1,213 @@ +/* Optimized version of the memccpy() function. + This file is part of the GNU C Library. + Copyright (C) 2000, 2001, 2003 Free Software Foundation, Inc. + Contributed by Dan Pop . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Return: a pointer to the next byte after char in dest or NULL + + Inputs: + in0: dest + in1: src + in2: char + in3: byte count + + This implementation assumes little endian mode (UM.be = 0). + + This implementation assumes that it is safe to do read ahead + in the src block, without getting beyond its limit. */ + +#include "sysdep.h" +#undef ret + +#define OP_T_THRES 16 +#define OPSIZ 8 + +#define saved_pr r17 +#define saved_lc r18 +#define dest r19 +#define src r20 +#define len r21 +#define asrc r22 +#define tmp r23 +#define char r24 +#define charx8 r25 +#define saved_ec r26 +#define sh2 r28 +#define sh1 r29 +#define loopcnt r30 +#define value r31 + +#ifdef GAS_ALIGN_BREAKS_UNWIND_INFO +/* Manually force proper loop-alignment. Note: be sure to + double-check the code-layout after making any changes to + this routine! */ +# define ALIGN(n) { nop 0 } +#else +# define ALIGN(n) .align n +#endif + +ENTRY(memccpy) + .prologue + alloc r2 = ar.pfs, 4, 40 - 4, 0, 40 + +#include "softpipe.h" + .rotr r[MEMLAT + 7], tmp1[4], tmp2[4], val[4], tmp3[2], pos0[2] + .rotp p[MEMLAT + 6 + 1] + + mov ret0 = r0 /* return NULL if no match */ + .save pr, saved_pr + mov saved_pr = pr /* save the predicate registers */ + mov dest = in0 /* dest */ + .save ar.lc, saved_lc + mov saved_lc = ar.lc /* save the loop counter */ + mov saved_ec = ar.ec /* save the loop counter */ + .body + mov src = in1 /* src */ + extr.u char = in2, 0, 8 /* char */ + mov len = in3 /* len */ + sub tmp = r0, in0 /* tmp = -dest */ + cmp.ne p7, p0 = r0, r0 /* clear p7 */ + ;; + and loopcnt = 7, tmp /* loopcnt = -dest % 8 */ + cmp.ge p6, p0 = OP_T_THRES, len /* is len <= OP_T_THRES */ + mov ar.ec = 0 /* ec not guaranteed zero on entry */ +(p6) br.cond.spnt .cpyfew /* copy byte by byte */ + ;; + cmp.eq p6, p0 = loopcnt, r0 + mux1 charx8 = char, @brcst +(p6) br.cond.sptk .dest_aligned + sub len = len, loopcnt /* len -= -dest % 8 */ + adds loopcnt = -1, loopcnt /* --loopcnt */ + ;; + mov ar.lc = loopcnt +.l1: /* copy -dest % 8 bytes */ + ld1 value = [src], 1 /* value = *src++ */ + ;; + st1 [dest] = value, 1 /* *dest++ = value */ + cmp.eq p6, p0 = value, char +(p6) br.cond.spnt .foundit + br.cloop.dptk .l1 +.dest_aligned: + and sh1 = 7, src /* sh1 = src % 8 */ + and tmp = -8, len /* tmp = len & -OPSIZ */ + and asrc = -8, src /* asrc = src & -OPSIZ -- align src */ + shr.u loopcnt = len, 3 /* loopcnt = len / 8 */ + and len = 7, len ;; /* len = len % 8 */ + shl sh1 = sh1, 3 /* sh1 = 8 * (src % 8) */ + adds loopcnt = -1, loopcnt /* --loopcnt */ + mov pr.rot = 1 << 16 ;; /* set rotating predicates */ + sub sh2 = 64, sh1 /* sh2 = 64 - sh1 */ + mov ar.lc = loopcnt /* set LC */ + cmp.eq p6, p0 = sh1, r0 /* is the src aligned? */ +(p6) br.cond.sptk .src_aligned ;; + add src = src, tmp /* src += len & -OPSIZ */ + mov ar.ec = MEMLAT + 6 + 1 /* six more passes needed */ + ld8 r[1] = [asrc], 8 /* r[1] = w0 */ + cmp.ne p6, p0 = r0, r0 ;; /* clear p6 */ + ALIGN(32) +.l2: +(p[0]) ld8.s r[0] = [asrc], 8 /* r[0] = w1 */ +(p[MEMLAT]) shr.u tmp1[0] = r[1 + MEMLAT], sh1 /* tmp1 = w0 >> sh1 */ +(p[MEMLAT]) shl tmp2[0] = r[0 + MEMLAT], sh2 /* tmp2 = w1 << sh2 */ +(p[MEMLAT+4]) xor tmp3[0] = val[1], charx8 +(p[MEMLAT+5]) czx1.r pos0[0] = tmp3[1] +(p[MEMLAT+6]) chk.s r[6 + MEMLAT], .recovery1 /* our data isn't */ + /* valid - rollback! */ +(p[MEMLAT+6]) cmp.ne p6, p0 = 8, pos0[1] +(p6) br.cond.spnt .gotit +(p[MEMLAT+6]) st8 [dest] = val[3], 8 /* store val to dest */ +(p[MEMLAT+3]) or val[0] = tmp1[3], tmp2[3] /* val = tmp1 | tmp2 */ + br.ctop.sptk .l2 + br.cond.sptk .cpyfew + +.src_aligned: + cmp.ne p6, p0 = r0, r0 /* clear p6 */ + mov ar.ec = MEMLAT + 2 + 1 ;; /* set EC */ +.l3: +(p[0]) ld8.s r[0] = [src], 8 +(p[MEMLAT]) xor tmp3[0] = r[MEMLAT], charx8 +(p[MEMLAT+1]) czx1.r pos0[0] = tmp3[1] +(p[MEMLAT+2]) cmp.ne p7, p0 = 8, pos0[1] +(p[MEMLAT+2]) chk.s r[MEMLAT+2], .recovery2 +(p7) br.cond.spnt .gotit +.back2: +(p[MEMLAT+2]) st8 [dest] = r[MEMLAT+2], 8 + br.ctop.dptk .l3 +.cpyfew: + cmp.eq p6, p0 = len, r0 /* is len == 0 ? */ + adds len = -1, len /* --len; */ +(p6) br.cond.spnt .restore_and_exit ;; + mov ar.lc = len +.l4: + ld1 value = [src], 1 + ;; + st1 [dest] = value, 1 + cmp.eq p6, p0 = value, char +(p6) br.cond.spnt .foundit + br.cloop.dptk .l4 ;; +.foundit: +(p6) mov ret0 = dest +.restore_and_exit: + mov pr = saved_pr, -1 /* restore the predicate registers */ + mov ar.lc = saved_lc /* restore the loop counter */ + mov ar.ec = saved_ec ;; /* restore the epilog counter */ + br.ret.sptk.many b0 +.gotit: + .pred.rel "mutex" p6, p7 +(p6) mov value = val[3] /* if coming from l2 */ +(p7) mov value = r[MEMLAT+2] /* if coming from l3 */ + mov ar.lc = pos0[1] ;; +.l5: + extr.u tmp = value, 0, 8 ;; + st1 [dest] = tmp, 1 + shr.u value = value, 8 + br.cloop.sptk .l5 ;; + mov ret0 = dest + mov pr = saved_pr, -1 + mov ar.lc = saved_lc + br.ret.sptk.many b0 + +.recovery1: + adds src = -(MEMLAT + 6 + 1) * 8, asrc + mov loopcnt = ar.lc + mov tmp = ar.ec ;; + sub sh1 = (MEMLAT + 6 + 1), tmp + shr.u sh2 = sh2, 3 + ;; + shl loopcnt = loopcnt, 3 + sub src = src, sh2 + shl sh1 = sh1, 3 + shl tmp = tmp, 3 + ;; + add len = len, loopcnt + add src = sh1, src ;; + add len = tmp, len +.back1: + br.cond.sptk .cpyfew + +.recovery2: + add tmp = -(MEMLAT + 3) * 8, src +(p7) br.cond.spnt .gotit + ;; + ld8 r[MEMLAT+2] = [tmp] ;; + xor pos0[1] = r[MEMLAT+2], charx8 ;; + czx1.r pos0[1] = pos0[1] ;; + cmp.ne p7, p6 = 8, pos0[1] +(p7) br.cond.spnt .gotit + br.cond.sptk .back2 +END(memccpy) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/ia64/memchr.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/ia64/memchr.S new file mode 100644 index 00000000..f25e8030 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/ia64/memchr.S @@ -0,0 +1,131 @@ +/* Optimized version of the standard memchr() function. + This file is part of the GNU C Library. + Copyright (C) 2000, 2001, 2003 Free Software Foundation, Inc. + Contributed by Dan Pop . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Return: the address of the first occurence of chr in str or NULL + + Inputs: + in0: str + in1: chr + in2: byte count + + This implementation assumes little endian mode. For big endian mode, + the instruction czx1.r should be replaced by czx1.l. + + The algorithm is fairly straightforward: search byte by byte until we + we get to a word aligned address, then search word by word as much as + possible; the remaining few bytes are searched one at a time. + + The word by word search is performed by xor-ing the word with a word + containing chr in every byte. If there is a hit, the result will + contain a zero byte in the corresponding position. The presence and + position of that zero byte is detected with a czx instruction. + + All the loops in this function could have had the internal branch removed + if br.ctop and br.cloop could be predicated :-(. */ + +#include "sysdep.h" +#undef ret + +#define saved_pr r15 +#define saved_lc r16 +#define chr r17 +#define len r18 +#define pos0 r20 +#define val r21 +#define tmp r24 +#define chrx8 r25 +#define loopcnt r30 + +#define str in0 + +ENTRY(__memchr) + .prologue + alloc r2 = ar.pfs, 3, 0, 29, 32 +#include "softpipe.h" + .rotr value[MEMLAT+1], addr[MEMLAT+3], aux[2], poschr[2] + .rotp p[MEMLAT+3] + .save ar.lc, saved_lc + mov saved_lc = ar.lc /* save the loop counter */ + .save pr, saved_pr + mov saved_pr = pr /* save the predicates */ + .body + mov ret0 = str + and tmp = 7, str /* tmp = str % 8 */ + cmp.ne p7, p0 = r0, r0 /* clear p7 */ + extr.u chr = in1, 0, 8 /* chr = (unsigned char) in1 */ + mov len = in2 + cmp.gtu p6, p0 = 16, in2 /* use a simple loop for short */ +(p6) br.cond.spnt .srchfew ;; /* searches */ + sub loopcnt = 8, tmp /* loopcnt = 8 - tmp */ + cmp.eq p6, p0 = tmp, r0 +(p6) br.cond.sptk .str_aligned;; + sub len = len, loopcnt + adds loopcnt = -1, loopcnt;; + mov ar.lc = loopcnt +.l1: + ld1 val = [ret0], 1 + ;; + cmp.eq p6, p0 = val, chr +(p6) br.cond.spnt .foundit + br.cloop.sptk .l1 ;; +.str_aligned: + cmp.ne p6, p0 = r0, r0 /* clear p6 */ + shr.u loopcnt = len, 3 /* loopcnt = len / 8 */ + and len = 7, len ;; /* remaining len = len & 7 */ + adds loopcnt = -1, loopcnt + mov ar.ec = MEMLAT + 3 + mux1 chrx8 = chr, @brcst ;; /* get a word full of chr */ + mov ar.lc = loopcnt + mov pr.rot = 1 << 16 ;; +.l2: +(p[0]) mov addr[0] = ret0 +(p[0]) ld8 value[0] = [ret0], 8 +(p[MEMLAT]) xor aux[0] = value[MEMLAT], chrx8 +(p[MEMLAT+1]) czx1.r poschr[0] = aux[1] +(p[MEMLAT+2]) cmp.ne p7, p0 = 8, poschr[1] +(p7) br.cond.dpnt .foundit + br.ctop.dptk .l2 +.srchfew: + adds loopcnt = -1, len + cmp.eq p6, p0 = len, r0 +(p6) br.cond.spnt .notfound ;; + mov ar.lc = loopcnt +.l3: + ld1 val = [ret0], 1 + ;; + cmp.eq p6, p0 = val, chr +(p6) br.cond.dpnt .foundit + br.cloop.sptk .l3 ;; +.notfound: + cmp.ne p6, p0 = r0, r0 /* clear p6 (p7 was already 0 when we got here) */ + mov ret0 = r0 ;; /* return NULL */ +.foundit: + .pred.rel "mutex" p6, p7 +(p6) adds ret0 = -1, ret0 /* if we got here from l1 or l3 */ +(p7) add ret0 = addr[MEMLAT+2], poschr[1] /* if we got here from l2 */ + mov pr = saved_pr, -1 + mov ar.lc = saved_lc + br.ret.sptk.many b0 + +END(__memchr) + +weak_alias(__memchr, memchr) +weak_alias(__memchr, __ubp_memchr) +libc_hidden_def(memchr) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/ia64/memcmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/ia64/memcmp.S new file mode 100644 index 00000000..adb1a20d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/ia64/memcmp.S @@ -0,0 +1,166 @@ +/* Optimized version of the standard memcmp() function. + This file is part of the GNU C Library. + Copyright (C) 2000, 2001, 2004 Free Software Foundation, Inc. + Contributed by Dan Pop . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Return: the result of the comparison + + Inputs: + in0: dest (aka s1) + in1: src (aka s2) + in2: byte count + + In this form, it assumes little endian mode. For big endian mode, the + the two shifts in .l2 must be inverted: + + shl tmp1[0] = r[1 + MEMLAT], sh1 // tmp1 = w0 << sh1 + shr.u tmp2[0] = r[0 + MEMLAT], sh2 // tmp2 = w1 >> sh2 + + and all the mux1 instructions should be replaced by plain mov's. */ + +#include "sysdep.h" +#undef ret + +#define OP_T_THRES 16 +#define OPSIZ 8 +#define MEMLAT 2 + +#define start r15 +#define saved_pr r17 +#define saved_lc r18 +#define dest r19 +#define src r20 +#define len r21 +#define asrc r22 +#define tmp r23 +#define value1 r24 +#define value2 r25 +#define sh2 r28 +#define sh1 r29 +#define loopcnt r30 + +ENTRY(memcmp) + .prologue + alloc r2 = ar.pfs, 3, 37, 0, 40 + + .rotr r[MEMLAT + 2], q[MEMLAT + 5], tmp1[4], tmp2[4], val[2] + .rotp p[MEMLAT + 4 + 1] + + mov ret0 = r0 /* by default return value = 0 */ + .save pr, saved_pr + mov saved_pr = pr /* save the predicate registers */ + .save ar.lc, saved_lc + mov saved_lc = ar.lc /* save the loop counter */ + .body + mov dest = in0 /* dest */ + mov src = in1 /* src */ + mov len = in2 /* len */ + sub tmp = r0, in0 /* tmp = -dest */ + ;; + and loopcnt = 7, tmp /* loopcnt = -dest % 8 */ + cmp.ge p6, p0 = OP_T_THRES, len /* is len <= OP_T_THRES */ +(p6) br.cond.spnt .cmpfew /* compare byte by byte */ + ;; + cmp.eq p6, p0 = loopcnt, r0 +(p6) br.cond.sptk .dest_aligned + sub len = len, loopcnt /* len -= -dest % 8 */ + adds loopcnt = -1, loopcnt /* --loopcnt */ + ;; + mov ar.lc = loopcnt +.l1: /* copy -dest % 8 bytes */ + ld1 value1 = [src], 1 /* value = *src++ */ + ld1 value2 = [dest], 1 + ;; + cmp.ne p6, p0 = value1, value2 +(p6) br.cond.spnt .done + br.cloop.dptk .l1 +.dest_aligned: + and sh1 = 7, src /* sh1 = src % 8 */ + and tmp = -8, len /* tmp = len & -OPSIZ */ + and asrc = -8, src /* asrc = src & -OPSIZ -- align src */ + shr.u loopcnt = len, 3 /* loopcnt = len / 8 */ + and len = 7, len ;; /* len = len % 8 */ + shl sh1 = sh1, 3 /* sh1 = 8 * (src % 8) */ + adds loopcnt = -1, loopcnt /* --loopcnt */ + mov pr.rot = 1 << 16 ;; /* set rotating predicates */ + sub sh2 = 64, sh1 /* sh2 = 64 - sh1 */ + mov ar.lc = loopcnt /* set LC */ + cmp.eq p6, p0 = sh1, r0 /* is the src aligned? */ +(p6) br.cond.sptk .src_aligned + add src = src, tmp /* src += len & -OPSIZ */ + mov ar.ec = MEMLAT + 4 + 1 /* four more passes needed */ + ld8 r[1] = [asrc], 8 ;; /* r[1] = w0 */ + .align 32 + +/* We enter this loop with p6 cleared by the above comparison */ + +.l2: +(p[0]) ld8 r[0] = [asrc], 8 /* r[0] = w1 */ +(p[0]) ld8 q[0] = [dest], 8 +(p[MEMLAT]) shr.u tmp1[0] = r[1 + MEMLAT], sh1 /* tmp1 = w0 >> sh1 */ +(p[MEMLAT]) shl tmp2[0] = r[0 + MEMLAT], sh2 /* tmp2 = w1 << sh2 */ +(p[MEMLAT+4]) cmp.ne p6, p0 = q[MEMLAT + 4], val[1] +(p[MEMLAT+3]) or val[0] = tmp1[3], tmp2[3] /* val = tmp1 | tmp2 */ +(p6) br.cond.spnt .l2exit + br.ctop.sptk .l2 + br.cond.sptk .cmpfew +.l3exit: + mux1 value1 = r[MEMLAT], @rev + mux1 value2 = q[MEMLAT], @rev + cmp.ne p6, p0 = r0, r0 ;; /* clear p6 */ +.l2exit: +(p6) mux1 value1 = val[1], @rev +(p6) mux1 value2 = q[MEMLAT + 4], @rev ;; + cmp.ltu p6, p7 = value2, value1 ;; +(p6) mov ret0 = -1 +(p7) mov ret0 = 1 + mov pr = saved_pr, -1 /* restore the predicate registers */ + mov ar.lc = saved_lc /* restore the loop counter */ + br.ret.sptk.many b0 +.src_aligned: + cmp.ne p6, p0 = r0, r0 /* clear p6 */ + mov ar.ec = MEMLAT + 1 ;; /* set EC */ +.l3: +(p[0]) ld8 r[0] = [src], 8 +(p[0]) ld8 q[0] = [dest], 8 +(p[MEMLAT]) cmp.ne p6, p0 = r[MEMLAT], q[MEMLAT] +(p6) br.cond.spnt .l3exit + br.ctop.dptk .l3 ;; +.cmpfew: + cmp.eq p6, p0 = len, r0 /* is len == 0 ? */ + adds len = -1, len /* --len; */ +(p6) br.cond.spnt .restore_and_exit ;; + mov ar.lc = len +.l4: + ld1 value1 = [src], 1 + ld1 value2 = [dest], 1 + ;; + cmp.ne p6, p0 = value1, value2 +(p6) br.cond.spnt .done + br.cloop.dptk .l4 ;; +.done: +(p6) sub ret0 = value2, value1 /* don't execute it if falling thru */ +.restore_and_exit: + mov pr = saved_pr, -1 /* restore the predicate registers */ + mov ar.lc = saved_lc /* restore the loop counter */ + br.ret.sptk.many b0 +END(memcmp) +libc_hidden_def (memcmp) +#ifdef __UCLIBC_SUSV3_LEGACY__ +strong_alias (memcmp, bcmp) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/ia64/memcpy.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/ia64/memcpy.S new file mode 100644 index 00000000..6c48a72d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/ia64/memcpy.S @@ -0,0 +1,436 @@ +/* Optimized version of the standard memcpy() function. + This file is part of the GNU C Library. + Copyright (C) 2000, 2001, 2003 Free Software Foundation, Inc. + Contributed by Dan Pop for Itanium . + Rewritten for McKinley by Sverre Jarp, HP Labs/CERN + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Return: dest + + Inputs: + in0: dest + in1: src + in2: byte count + + An assembly implementation of the algorithm used by the generic C + version from glibc. The case when source and sest are aligned is + treated separately, for extra performance. + + In this form, memcpy assumes little endian mode. For big endian mode, + sh1 must be computed using an extra instruction: sub sh1 = 64, sh1 + and the order of r[MEMLAT] and r[MEMLAT+1] must be reverted in the + shrp instruction. */ + +#define USE_LFETCH +#define USE_FLP +#include "sysdep.h" +#undef ret + +#define LFETCH_DIST 500 + +#define ALIGN_UNROLL_no 4 /* no. of elements */ +#define ALIGN_UNROLL_sh 2 /* (shift amount) */ + +#define MEMLAT 8 +#define Nrot ((4*(MEMLAT+2) + 7) & ~7) + +#define OP_T_THRES 16 +#define OPSIZ 8 + +#define loopcnt r14 +#define elemcnt r15 +#define saved_pr r16 +#define saved_lc r17 +#define adest r18 +#define dest r19 +#define asrc r20 +#define src r21 +#define len r22 +#define tmp2 r23 +#define tmp3 r24 +#define tmp4 r25 +#define ptable r26 +#define ploop56 r27 +#define loopaddr r28 +#define sh1 r29 +#define ptr1 r30 +#define ptr2 r31 + +#define movi0 mov + +#define p_scr p6 +#define p_xtr p7 +#define p_nxtr p8 +#define p_few p9 + +#if defined(USE_FLP) +#define load ldf8 +#define store stf8 +#define tempreg f6 +#define the_r fr +#define the_s fs +#define the_t ft +#define the_q fq +#define the_w fw +#define the_x fx +#define the_y fy +#define the_z fz +#elif defined(USE_INT) +#define load ld8 +#define store st8 +#define tempreg tmp2 +#define the_r r +#define the_s s +#define the_t t +#define the_q q +#define the_w w +#define the_x x +#define the_y y +#define the_z z +#endif + +#ifdef GAS_ALIGN_BREAKS_UNWIND_INFO +/* Manually force proper loop-alignment. Note: be sure to + double-check the code-layout after making any changes to + this routine! */ +# define ALIGN(n) { nop 0 } +#else +# define ALIGN(n) .align n +#endif + +#if defined(USE_LFETCH) +#define LOOP(shift) \ + ALIGN(32); \ +.loop##shift : \ +{ .mmb \ +(p[0]) ld8.nt1 r[0] = [asrc], 8 ; \ +(p[0]) lfetch.nt1 [ptr1], 16 ; \ + nop.b 0 ; \ +} { .mib \ +(p[MEMLAT+1]) st8 [dest] = tmp3, 8 ; \ +(p[MEMLAT]) shrp tmp3 = r[MEMLAT], s[MEMLAT+1], shift ; \ + nop.b 0 ;; \ + } { .mmb \ +(p[0]) ld8.nt1 s[0] = [asrc], 8 ; \ +(p[0]) lfetch.nt1 [ptr2], 16 ; \ + nop.b 0 ; \ +} { .mib \ +(p[MEMLAT+1]) st8 [dest] = tmp4, 8 ; \ +(p[MEMLAT]) shrp tmp4 = s[MEMLAT], r[MEMLAT], shift ; \ + br.ctop.sptk.many .loop##shift \ +;; } \ +{ .mib \ + br.cond.sptk.many .copy_bytes ; /* deal with the remaining bytes */ \ +} +#else +#define LOOP(shift) \ + ALIGN(32); \ +.loop##shift : \ +{ .mmb \ +(p[0]) ld8.nt1 r[0] = [asrc], 8 ; \ + nop.b 0 ; \ +} { .mib \ +(p[MEMLAT+1]) st8 [dest] = tmp3, 8 ; \ +(p[MEMLAT]) shrp tmp3 = r[MEMLAT], s[MEMLAT+1], shift ; \ + nop.b 0 ;; \ + } { .mmb \ +(p[0]) ld8.nt1 s[0] = [asrc], 8 ; \ + nop.b 0 ; \ +} { .mib \ +(p[MEMLAT+1]) st8 [dest] = tmp4, 8 ; \ +(p[MEMLAT]) shrp tmp4 = s[MEMLAT], r[MEMLAT], shift ; \ + br.ctop.sptk.many .loop##shift \ +;; } \ +{ .mib \ + br.cond.sptk.many .copy_bytes ; /* deal with the remaining bytes */ \ +} +#endif + + +ENTRY(memcpy) +{ .mmi + .prologue + alloc r2 = ar.pfs, 3, Nrot - 3, 0, Nrot + .rotr r[MEMLAT+1], s[MEMLAT+2], q[MEMLAT+1], t[MEMLAT+1] + .rotp p[MEMLAT+2] + .rotf fr[MEMLAT+1], fq[MEMLAT+1], fs[MEMLAT+1], ft[MEMLAT+1] + mov ret0 = in0 /* return tmp2 = dest */ + .save pr, saved_pr + movi0 saved_pr = pr /* save the predicate registers */ +} { .mmi + and tmp4 = 7, in0 /* check if destination is aligned */ + mov dest = in0 /* dest */ + mov src = in1 /* src */ +;; } +{ .mii + cmp.eq p_scr, p0 = in2, r0 /* if (len == 0) */ + .save ar.lc, saved_lc + movi0 saved_lc = ar.lc /* save the loop counter */ + .body + cmp.ge p_few, p0 = OP_T_THRES, in2 /* is len <= OP_T_THRESH */ +} { .mbb + mov len = in2 /* len */ +(p_scr) br.cond.dpnt.few .restore_and_exit /* Branch no. 1: return dest */ +(p_few) br.cond.dpnt.many .copy_bytes /* Branch no. 2: copy byte by byte */ +;; } +{ .mmi +#if defined(USE_LFETCH) + lfetch.nt1 [dest] /* */ + lfetch.nt1 [src] /* */ +#endif + shr.u elemcnt = len, 3 /* elemcnt = len / 8 */ +} { .mib + cmp.eq p_scr, p0 = tmp4, r0 /* is destination aligned? */ + sub loopcnt = 7, tmp4 /* */ +(p_scr) br.cond.dptk.many .dest_aligned +;; } +{ .mmi + ld1 tmp2 = [src], 1 /* */ + sub len = len, loopcnt, 1 /* reduce len */ + movi0 ar.lc = loopcnt /* */ +} { .mib + cmp.ne p_scr, p0 = 0, loopcnt /* avoid loading beyond end-point */ +;; } + +.l0: /* ---------------------------- L0: Align src on 8-byte boundary */ +{ .mmi + st1 [dest] = tmp2, 1 /* */ +(p_scr) ld1 tmp2 = [src], 1 /* */ +} { .mib + cmp.lt p_scr, p0 = 1, loopcnt /* avoid load beyond end-point */ + add loopcnt = -1, loopcnt + br.cloop.dptk.few .l0 /* */ +;; } + +.dest_aligned: +{ .mmi + and tmp4 = 7, src /* ready for alignment check */ + shr.u elemcnt = len, 3 /* elemcnt = len / 8 */ +;; } +{ .mib + cmp.ne p_scr, p0 = tmp4, r0 /* is source also aligned */ + tbit.nz p_xtr, p_nxtr = src, 3 /* prepare a separate move if src */ +} { .mib /* is not 16B aligned */ + add ptr2 = LFETCH_DIST, dest /* prefetch address */ + add ptr1 = LFETCH_DIST, src +(p_scr) br.cond.dptk.many .src_not_aligned +;; } + +/* The optimal case, when dest, and src are aligned */ + +.both_aligned: +{ .mmi + .pred.rel "mutex",p_xtr,p_nxtr +(p_xtr) cmp.gt p_scr, p0 = ALIGN_UNROLL_no+1, elemcnt /* Need N + 1 to qualify */ +(p_nxtr) cmp.gt p_scr, p0 = ALIGN_UNROLL_no, elemcnt /* Need only N to qualify */ + movi0 pr.rot = 1 << 16 /* set rotating predicates */ +} { .mib +(p_scr) br.cond.dpnt.many .copy_full_words +;; } + +{ .mmi +(p_xtr) load tempreg = [src], 8 +(p_xtr) add elemcnt = -1, elemcnt + movi0 ar.ec = MEMLAT + 1 /* set the epilog counter */ +;; } +{ .mmi +(p_xtr) add len = -8, len /* */ + add asrc = 16, src /* one bank apart (for USE_INT) */ + shr.u loopcnt = elemcnt, ALIGN_UNROLL_sh /* cater for unrolling */ +;;} +{ .mmi + add loopcnt = -1, loopcnt +(p_xtr) store [dest] = tempreg, 8 /* copy the "extra" word */ + nop.i 0 +;; } +{ .mib + add adest = 16, dest + movi0 ar.lc = loopcnt /* set the loop counter */ +;; } + +#ifdef GAS_ALIGN_BREAKS_UNWIND_INFO + { nop 0 } +#else + .align 32 +#endif +#if defined(USE_FLP) +.l1: /* ------------------------------- L1: Everything a multiple of 8 */ +{ .mmi +#if defined(USE_LFETCH) +(p[0]) lfetch.nt1 [ptr2],32 +#endif +(p[0]) ldfp8 the_r[0],the_q[0] = [src], 16 +(p[0]) add len = -32, len +} {.mmb +(p[MEMLAT]) store [dest] = the_r[MEMLAT], 8 +(p[MEMLAT]) store [adest] = the_s[MEMLAT], 8 +;; } +{ .mmi +#if defined(USE_LFETCH) +(p[0]) lfetch.nt1 [ptr1],32 +#endif +(p[0]) ldfp8 the_s[0], the_t[0] = [src], 16 +} {.mmb +(p[MEMLAT]) store [dest] = the_q[MEMLAT], 24 +(p[MEMLAT]) store [adest] = the_t[MEMLAT], 24 + br.ctop.dptk.many .l1 +;; } +#elif defined(USE_INT) +.l1: /* ------------------------------- L1: Everything a multiple of 8 */ +{ .mmi +(p[0]) load the_r[0] = [src], 8 +(p[0]) load the_q[0] = [asrc], 8 +(p[0]) add len = -32, len +} {.mmb +(p[MEMLAT]) store [dest] = the_r[MEMLAT], 8 +(p[MEMLAT]) store [adest] = the_q[MEMLAT], 8 +;; } +{ .mmi +(p[0]) load the_s[0] = [src], 24 +(p[0]) load the_t[0] = [asrc], 24 +} {.mmb +(p[MEMLAT]) store [dest] = the_s[MEMLAT], 24 +(p[MEMLAT]) store [adest] = the_t[MEMLAT], 24 +#if defined(USE_LFETCH) +;; } +{ .mmb +(p[0]) lfetch.nt1 [ptr2],32 +(p[0]) lfetch.nt1 [ptr1],32 +#endif + br.ctop.dptk.many .l1 +;; } +#endif + +.copy_full_words: +{ .mib + cmp.gt p_scr, p0 = 8, len /* */ + shr.u elemcnt = len, 3 /* */ +(p_scr) br.cond.dpnt.many .copy_bytes +;; } +{ .mii + load tempreg = [src], 8 + add loopcnt = -1, elemcnt /* */ +;; } +{ .mii + cmp.ne p_scr, p0 = 0, loopcnt /* */ + mov ar.lc = loopcnt /* */ +;; } + +.l2: /* ------------------------------- L2: Max 4 words copied separately */ +{ .mmi + store [dest] = tempreg, 8 +(p_scr) load tempreg = [src], 8 /* */ + add len = -8, len +} { .mib + cmp.lt p_scr, p0 = 1, loopcnt /* avoid load beyond end-point */ + add loopcnt = -1, loopcnt + br.cloop.dptk.few .l2 +;; } + +.copy_bytes: +{ .mib + cmp.eq p_scr, p0 = len, r0 /* is len == 0 ? */ + add loopcnt = -1, len /* len--; */ +(p_scr) br.cond.spnt .restore_and_exit +;; } +{ .mii + ld1 tmp2 = [src], 1 + movi0 ar.lc = loopcnt + cmp.ne p_scr, p0 = 0, loopcnt /* avoid load beyond end-point */ +;; } + +.l3: /* ------------------------------- L3: Final byte move */ +{ .mmi + st1 [dest] = tmp2, 1 +(p_scr) ld1 tmp2 = [src], 1 +} { .mib + cmp.lt p_scr, p0 = 1, loopcnt /* avoid load beyond end-point */ + add loopcnt = -1, loopcnt + br.cloop.dptk.few .l3 +;; } + +.restore_and_exit: +{ .mmi + movi0 pr = saved_pr, -1 /* restore the predicate registers */ +;; } +{ .mib + movi0 ar.lc = saved_lc /* restore the loop counter */ + br.ret.sptk.many b0 +;; } + + +.src_not_aligned: +{ .mmi + cmp.gt p_scr, p0 = 16, len + and sh1 = 7, src /* sh1 = src % 8 */ + shr.u loopcnt = len, 4 /* element-cnt = len / 16 */ +} { .mib + add tmp4 = @ltoff(.table), gp + add tmp3 = @ltoff(.loop56), gp +(p_scr) br.cond.dpnt.many .copy_bytes /* do byte by byte if too few */ +;; } +{ .mmi + and asrc = -8, src /* asrc = (-8) -- align src for loop */ + add loopcnt = -1, loopcnt /* loopcnt-- */ + shl sh1 = sh1, 3 /* sh1 = 8 * (src % 8) */ +} { .mmi + ld8 ptable = [tmp4] /* ptable = &table */ + ld8 ploop56 = [tmp3] /* ploop56 = &loop56 */ + and tmp2 = -16, len /* tmp2 = len & -OPSIZ */ +;; } +{ .mmi + add tmp3 = ptable, sh1 /* tmp3 = &table + sh1 */ + add src = src, tmp2 /* src += len & (-16) */ + movi0 ar.lc = loopcnt /* set LC */ +;; } +{ .mmi + ld8 tmp4 = [tmp3] /* tmp4 = loop offset */ + sub len = len, tmp2 /* len -= len & (-16) */ + movi0 ar.ec = MEMLAT + 2 /* one more pass needed */ +;; } +{ .mmi + ld8 s[1] = [asrc], 8 /* preload */ + sub loopaddr = ploop56,tmp4 /* loopadd = &loop56 - loop offset */ + movi0 pr.rot = 1 << 16 /* set rotating predicates */ +;; } +{ .mib + nop.m 0 + movi0 b6 = loopaddr + br b6 /* jump to the appropriate loop */ +;; } + + LOOP(8) + LOOP(16) + LOOP(24) + LOOP(32) + LOOP(40) + LOOP(48) + LOOP(56) +END(memcpy) +libc_hidden_def (memcpy) + + .rodata + .align 8 +.table: + data8 0 /* dummy entry */ + data8 .loop56 - .loop8 + data8 .loop56 - .loop16 + data8 .loop56 - .loop24 + data8 .loop56 - .loop32 + data8 .loop56 - .loop40 + data8 .loop56 - .loop48 + data8 .loop56 - .loop56 diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/ia64/memmove.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/ia64/memmove.S new file mode 100644 index 00000000..beaada6f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/ia64/memmove.S @@ -0,0 +1,251 @@ +/* Optimized version of the standard memmove() function. + This file is part of the GNU C Library. + Copyright (C) 2000, 2001, 2003 Free Software Foundation, Inc. + Contributed by Dan Pop . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Return: dest + + Inputs: + in0: dest + in1: src + in2: byte count + + The core of the function is the memcpy implementation used in memcpy.S. + When bytes have to be copied backwards, only the easy case, when + all arguments are multiples of 8, is optimised. + + In this form, it assumes little endian mode. For big endian mode, + sh1 must be computed using an extra instruction: sub sh1 = 64, sh1 + or the UM.be bit should be cleared at the beginning and set at the end. */ + +#include "sysdep.h" +#undef ret + +#define OP_T_THRES 16 +#define OPSIZ 8 + +#define adest r15 +#define saved_pr r17 +#define saved_lc r18 +#define dest r19 +#define src r20 +#define len r21 +#define asrc r22 +#define tmp2 r23 +#define tmp3 r24 +#define tmp4 r25 +#define ptable r26 +#define ploop56 r27 +#define loopaddr r28 +#define sh1 r29 +#define loopcnt r30 +#define value r31 + +#ifdef GAS_ALIGN_BREAKS_UNWIND_INFO +# define ALIGN(n) { nop 0 } +#else +# define ALIGN(n) .align n +#endif + +#define LOOP(shift) \ + ALIGN(32); \ +.loop##shift : \ +(p[0]) ld8 r[0] = [asrc], 8 ; /* w1 */ \ +(p[MEMLAT+1]) st8 [dest] = value, 8 ; \ +(p[MEMLAT]) shrp value = r[MEMLAT], r[MEMLAT+1], shift ; \ + nop.b 0 ; \ + nop.b 0 ; \ + br.ctop.sptk .loop##shift ; \ + br.cond.sptk .cpyfew ; /* deal with the remaining bytes */ + +#define MEMLAT 21 +#define Nrot (((2*MEMLAT+3) + 7) & ~7) + +ENTRY(memmove) + .prologue + alloc r2 = ar.pfs, 3, Nrot - 3, 0, Nrot + .rotr r[MEMLAT + 2], q[MEMLAT + 1] + .rotp p[MEMLAT + 2] + mov ret0 = in0 /* return value = dest */ + .save pr, saved_pr + mov saved_pr = pr /* save the predicate registers */ + .save ar.lc, saved_lc + mov saved_lc = ar.lc /* save the loop counter */ + .body + or tmp3 = in0, in1 ;; /* tmp3 = dest | src */ + or tmp3 = tmp3, in2 /* tmp3 = dest | src | len */ + mov dest = in0 /* dest */ + mov src = in1 /* src */ + mov len = in2 /* len */ + sub tmp2 = r0, in0 /* tmp2 = -dest */ + cmp.eq p6, p0 = in2, r0 /* if (len == 0) */ +(p6) br.cond.spnt .restore_and_exit;;/* return dest; */ + and tmp4 = 7, tmp3 /* tmp4 = (dest | src | len) & 7 */ + cmp.le p6, p0 = dest, src /* if dest <= src it's always safe */ +(p6) br.cond.spnt .forward /* to copy forward */ + add tmp3 = src, len;; + cmp.lt p6, p0 = dest, tmp3 /* if dest > src && dest < src + len */ +(p6) br.cond.spnt .backward /* we have to copy backward */ + +.forward: + shr.u loopcnt = len, 4 ;; /* loopcnt = len / 16 */ + cmp.ne p6, p0 = tmp4, r0 /* if ((dest | src | len) & 7 != 0) */ +(p6) br.cond.sptk .next /* goto next; */ + +/* The optimal case, when dest, src and len are all multiples of 8 */ + + and tmp3 = 0xf, len + mov pr.rot = 1 << 16 /* set rotating predicates */ + mov ar.ec = MEMLAT + 1 ;; /* set the epilog counter */ + cmp.ne p6, p0 = tmp3, r0 /* do we have to copy an extra word? */ + adds loopcnt = -1, loopcnt;; /* --loopcnt */ +(p6) ld8 value = [src], 8;; +(p6) st8 [dest] = value, 8 /* copy the "odd" word */ + mov ar.lc = loopcnt /* set the loop counter */ + cmp.eq p6, p0 = 8, len +(p6) br.cond.spnt .restore_and_exit;;/* the one-word special case */ + adds adest = 8, dest /* set adest one word ahead of dest */ + adds asrc = 8, src ;; /* set asrc one word ahead of src */ + nop.b 0 /* get the "golden" alignment for */ + nop.b 0 /* the next loop */ +.l0: +(p[0]) ld8 r[0] = [src], 16 +(p[0]) ld8 q[0] = [asrc], 16 +(p[MEMLAT]) st8 [dest] = r[MEMLAT], 16 +(p[MEMLAT]) st8 [adest] = q[MEMLAT], 16 + br.ctop.dptk .l0 ;; + + mov pr = saved_pr, -1 /* restore the predicate registers */ + mov ar.lc = saved_lc /* restore the loop counter */ + br.ret.sptk.many b0 +.next: + cmp.ge p6, p0 = OP_T_THRES, len /* is len <= OP_T_THRES */ + and loopcnt = 7, tmp2 /* loopcnt = -dest % 8 */ +(p6) br.cond.spnt .cpyfew /* copy byte by byte */ + ;; + cmp.eq p6, p0 = loopcnt, r0 +(p6) br.cond.sptk .dest_aligned + sub len = len, loopcnt /* len -= -dest % 8 */ + adds loopcnt = -1, loopcnt /* --loopcnt */ + ;; + mov ar.lc = loopcnt +.l1: /* copy -dest % 8 bytes */ + ld1 value = [src], 1 /* value = *src++ */ + ;; + st1 [dest] = value, 1 /* *dest++ = value */ + br.cloop.dptk .l1 +.dest_aligned: + and sh1 = 7, src /* sh1 = src % 8 */ + and tmp2 = -8, len /* tmp2 = len & -OPSIZ */ + and asrc = -8, src /* asrc = src & -OPSIZ -- align src */ + shr.u loopcnt = len, 3 /* loopcnt = len / 8 */ + and len = 7, len;; /* len = len % 8 */ + adds loopcnt = -1, loopcnt /* --loopcnt */ + addl tmp4 = @ltoff(.table), gp + addl tmp3 = @ltoff(.loop56), gp + mov ar.ec = MEMLAT + 1 /* set EC */ + mov pr.rot = 1 << 16;; /* set rotating predicates */ + mov ar.lc = loopcnt /* set LC */ + cmp.eq p6, p0 = sh1, r0 /* is the src aligned? */ +(p6) br.cond.sptk .src_aligned + add src = src, tmp2 /* src += len & -OPSIZ */ + shl sh1 = sh1, 3 /* sh1 = 8 * (src % 8) */ + ld8 ploop56 = [tmp3] /* ploop56 = &loop56 */ + ld8 ptable = [tmp4];; /* ptable = &table */ + add tmp3 = ptable, sh1;; /* tmp3 = &table + sh1 */ + mov ar.ec = MEMLAT + 1 + 1 /* one more pass needed */ + ld8 tmp4 = [tmp3];; /* tmp4 = loop offset */ + sub loopaddr = ploop56,tmp4 /* loopadd = &loop56 - loop offset */ + ld8 r[1] = [asrc], 8;; /* w0 */ + mov b6 = loopaddr;; + br b6 /* jump to the appropriate loop */ + + LOOP(8) + LOOP(16) + LOOP(24) + LOOP(32) + LOOP(40) + LOOP(48) + LOOP(56) + +.src_aligned: +.l3: +(p[0]) ld8 r[0] = [src], 8 +(p[MEMLAT]) st8 [dest] = r[MEMLAT], 8 + br.ctop.dptk .l3 +.cpyfew: + cmp.eq p6, p0 = len, r0 /* is len == 0 ? */ + adds len = -1, len /* --len; */ +(p6) br.cond.spnt .restore_and_exit ;; + mov ar.lc = len +.l4: + ld1 value = [src], 1 + ;; + st1 [dest] = value, 1 + br.cloop.dptk .l4 ;; +.restore_and_exit: + mov pr = saved_pr, -1 /* restore the predicate registers */ + mov ar.lc = saved_lc /* restore the loop counter */ + br.ret.sptk.many b0 + +/* In the case of a backward copy, optimise only the case when everything + is a multiple of 8, otherwise copy byte by byte. The backward copy is + used only when the blocks are overlapping and dest > src. +*/ +.backward: + shr.u loopcnt = len, 3 /* loopcnt = len / 8 */ + add src = src, len /* src points one byte past the end */ + add dest = dest, len ;; /* dest points one byte past the end */ + mov ar.ec = MEMLAT + 1 /* set the epilog counter */ + mov pr.rot = 1 << 16 /* set rotating predicates */ + adds loopcnt = -1, loopcnt /* --loopcnt */ + cmp.ne p6, p0 = tmp4, r0 /* if ((dest | src | len) & 7 != 0) */ +(p6) br.cond.sptk .bytecopy ;; /* copy byte by byte backward */ + adds src = -8, src /* src points to the last word */ + adds dest = -8, dest /* dest points to the last word */ + mov ar.lc = loopcnt;; /* set the loop counter */ +.l5: +(p[0]) ld8 r[0] = [src], -8 +(p[MEMLAT]) st8 [dest] = r[MEMLAT], -8 + br.ctop.dptk .l5 + br.cond.sptk .restore_and_exit +.bytecopy: + adds src = -1, src /* src points to the last byte */ + adds dest = -1, dest /* dest points to the last byte */ + adds loopcnt = -1, len;; /* loopcnt = len - 1 */ + mov ar.lc = loopcnt;; /* set the loop counter */ +.l6: +(p[0]) ld1 r[0] = [src], -1 +(p[MEMLAT]) st1 [dest] = r[MEMLAT], -1 + br.ctop.dptk .l6 + br.cond.sptk .restore_and_exit +END(memmove) + + .rodata + .align 8 +.table: + data8 0 /* dummy entry */ + data8 .loop56 - .loop8 + data8 .loop56 - .loop16 + data8 .loop56 - .loop24 + data8 .loop56 - .loop32 + data8 .loop56 - .loop40 + data8 .loop56 - .loop48 + data8 .loop56 - .loop56 + +libc_hidden_def (memmove) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/ia64/memset.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/ia64/memset.S new file mode 100644 index 00000000..45df5838 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/ia64/memset.S @@ -0,0 +1,400 @@ +/* Optimized version of the standard memset() function. + This file is part of the GNU C Library. + Copyright (C) 2000, 2001, 2002, 2003 Free Software Foundation, Inc. + Contributed by Dan Pop for Itanium . + Rewritten for McKinley by Sverre Jarp, HP Labs/CERN + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Return: dest + + Inputs: + in0: dest + in1: value + in2: count + + The algorithm is fairly straightforward: set byte by byte until we + we get to a 16B-aligned address, then loop on 128 B chunks using an + early store as prefetching, then loop on 32B chucks, then clear remaining + words, finally clear remaining bytes. + Since a stf.spill f0 can store 16B in one go, we use this instruction + to get peak speed when value = 0. */ + +#include "sysdep.h" +#undef ret + +#define dest in0 +#define value in1 +#define cnt in2 + +#define tmp r31 +#define save_lc r30 +#define ptr0 r29 +#define ptr1 r28 +#define ptr2 r27 +#define ptr3 r26 +#define ptr9 r24 +#define loopcnt r23 +#define linecnt r22 +#define bytecnt r21 + +#define fvalue f6 + +/* This routine uses only scratch predicate registers (p6 - p15) */ +#define p_scr p6 /* default register for same-cycle branches */ +#define p_nz p7 +#define p_zr p8 +#define p_unalgn p9 +#define p_y p11 +#define p_n p12 +#define p_yy p13 +#define p_nn p14 + +#define movi0 mov + +#define MIN1 15 +#define MIN1P1HALF 8 +#define LINE_SIZE 128 +#define LSIZE_SH 7 /* shift amount */ +#define PREF_AHEAD 8 + +#define USE_FLP +#if defined(USE_INT) +#define store st8 +#define myval value +#elif defined(USE_FLP) +#define store stf8 +#define myval fvalue +#endif + +.align 64 +ENTRY(memset) +{ .mmi + .prologue + alloc tmp = ar.pfs, 3, 0, 0, 0 + lfetch.nt1 [dest] + .save ar.lc, save_lc + movi0 save_lc = ar.lc +} { .mmi + .body + mov ret0 = dest /* return value */ + cmp.ne p_nz, p_zr = value, r0 /* use stf.spill if value is zero */ + cmp.eq p_scr, p0 = cnt, r0 +;; } +{ .mmi + and ptr2 = -(MIN1+1), dest /* aligned address */ + and tmp = MIN1, dest /* prepare to check for alignment */ + tbit.nz p_y, p_n = dest, 0 /* Do we have an odd address? (M_B_U) */ +} { .mib + mov ptr1 = dest + mux1 value = value, @brcst /* create 8 identical bytes in word */ +(p_scr) br.ret.dpnt.many rp /* return immediately if count = 0 */ +;; } +{ .mib + cmp.ne p_unalgn, p0 = tmp, r0 +} { .mib /* NB: # of bytes to move is 1 higher */ + sub bytecnt = (MIN1+1), tmp /* than loopcnt */ + cmp.gt p_scr, p0 = 16, cnt /* is it a minimalistic task? */ +(p_scr) br.cond.dptk.many .move_bytes_unaligned /* go move just a few (M_B_U) */ +;; } +{ .mmi +(p_unalgn) add ptr1 = (MIN1+1), ptr2 /* after alignment */ +(p_unalgn) add ptr2 = MIN1P1HALF, ptr2 /* after alignment */ +(p_unalgn) tbit.nz.unc p_y, p_n = bytecnt, 3 /* should we do a st8 ? */ +;; } +{ .mib +(p_y) add cnt = -8, cnt +(p_unalgn) tbit.nz.unc p_yy, p_nn = bytecnt, 2 /* should we do a st4 ? */ +} { .mib +(p_y) st8 [ptr2] = value, -4 +(p_n) add ptr2 = 4, ptr2 +;; } +{ .mib +(p_yy) add cnt = -4, cnt +(p_unalgn) tbit.nz.unc p_y, p_n = bytecnt, 1 /* should we do a st2 ? */ +} { .mib +(p_yy) st4 [ptr2] = value, -2 +(p_nn) add ptr2 = 2, ptr2 +;; } +{ .mmi + mov tmp = LINE_SIZE+1 /* for compare */ +(p_y) add cnt = -2, cnt +(p_unalgn) tbit.nz.unc p_yy, p_nn = bytecnt, 0 /* should we do a st1 ? */ +} { .mmi + setf.sig fvalue=value /* transfer value to FLP side */ +(p_y) st2 [ptr2] = value, -1 +(p_n) add ptr2 = 1, ptr2 +;; } + +{ .mmi +(p_yy) st1 [ptr2] = value + cmp.gt p_scr, p0 = tmp, cnt /* is it a minimalistic task? */ +} { .mbb +(p_yy) add cnt = -1, cnt +(p_scr) br.cond.dpnt.many .fraction_of_line /* go move just a few */ +;; } + +{ .mib + nop.m 0 + shr.u linecnt = cnt, LSIZE_SH +(p_zr) br.cond.dptk.many .l1b /* Jump to use stf.spill */ +;; } + +#ifndef GAS_ALIGN_BREAKS_UNWIND_INFO + .align 32 /* -------- L1A: store ahead into cache lines; fill later */ +#endif +{ .mmi + and tmp = -(LINE_SIZE), cnt /* compute end of range */ + mov ptr9 = ptr1 /* used for prefetching */ + and cnt = (LINE_SIZE-1), cnt /* remainder */ +} { .mmi + mov loopcnt = PREF_AHEAD-1 /* default prefetch loop */ + cmp.gt p_scr, p0 = PREF_AHEAD, linecnt /* check against actual value */ +;; } +{ .mmi +(p_scr) add loopcnt = -1, linecnt /* start of stores */ + add ptr2 = 8, ptr1 /* (beyond prefetch stores) */ + add ptr1 = tmp, ptr1 /* first address beyond total */ +;; } /* range */ +{ .mmi + add tmp = -1, linecnt /* next loop count */ + movi0 ar.lc = loopcnt +;; } +.pref_l1a: +{ .mib + store [ptr9] = myval, 128 /* Do stores one cache line apart */ + nop.i 0 + br.cloop.dptk.few .pref_l1a +;; } +{ .mmi + add ptr0 = 16, ptr2 /* Two stores in parallel */ + movi0 ar.lc = tmp +;; } +.l1ax: + { .mmi + store [ptr2] = myval, 8 + store [ptr0] = myval, 8 + ;; } + { .mmi + store [ptr2] = myval, 24 + store [ptr0] = myval, 24 + ;; } + { .mmi + store [ptr2] = myval, 8 + store [ptr0] = myval, 8 + ;; } + { .mmi + store [ptr2] = myval, 24 + store [ptr0] = myval, 24 + ;; } + { .mmi + store [ptr2] = myval, 8 + store [ptr0] = myval, 8 + ;; } + { .mmi + store [ptr2] = myval, 24 + store [ptr0] = myval, 24 + ;; } + { .mmi + store [ptr2] = myval, 8 + store [ptr0] = myval, 32 + cmp.lt p_scr, p0 = ptr9, ptr1 /* do we need more prefetching? */ + ;; } +{ .mmb + store [ptr2] = myval, 24 +(p_scr) store [ptr9] = myval, 128 + br.cloop.dptk.few .l1ax +;; } +{ .mbb + cmp.le p_scr, p0 = 8, cnt /* just a few bytes left ? */ +(p_scr) br.cond.dpnt.many .fraction_of_line /* Branch no. 2 */ + br.cond.dpnt.many .move_bytes_from_alignment /* Branch no. 3 */ +;; } + +#ifdef GAS_ALIGN_BREAKS_UNWIND_INFO + { nop 0 } +#else + .align 32 +#endif +.l1b: /* ------------------ L1B: store ahead into cache lines; fill later */ +{ .mmi + and tmp = -(LINE_SIZE), cnt /* compute end of range */ + mov ptr9 = ptr1 /* used for prefetching */ + and cnt = (LINE_SIZE-1), cnt /* remainder */ +} { .mmi + mov loopcnt = PREF_AHEAD-1 /* default prefetch loop */ + cmp.gt p_scr, p0 = PREF_AHEAD, linecnt /* check against actual value */ +;; } +{ .mmi +(p_scr) add loopcnt = -1, linecnt + add ptr2 = 16, ptr1 /* start of stores (beyond prefetch stores) */ + add ptr1 = tmp, ptr1 /* first address beyond total range */ +;; } +{ .mmi + add tmp = -1, linecnt /* next loop count */ + movi0 ar.lc = loopcnt +;; } +.pref_l1b: +{ .mib + stf.spill [ptr9] = f0, 128 /* Do stores one cache line apart */ + nop.i 0 + br.cloop.dptk.few .pref_l1b +;; } +{ .mmi + add ptr0 = 16, ptr2 /* Two stores in parallel */ + movi0 ar.lc = tmp +;; } +.l1bx: + { .mmi + stf.spill [ptr2] = f0, 32 + stf.spill [ptr0] = f0, 32 + ;; } + { .mmi + stf.spill [ptr2] = f0, 32 + stf.spill [ptr0] = f0, 32 + ;; } + { .mmi + stf.spill [ptr2] = f0, 32 + stf.spill [ptr0] = f0, 64 + cmp.lt p_scr, p0 = ptr9, ptr1 /* do we need more prefetching? */ + ;; } +{ .mmb + stf.spill [ptr2] = f0, 32 +(p_scr) stf.spill [ptr9] = f0, 128 + br.cloop.dptk.few .l1bx +;; } +{ .mib + cmp.gt p_scr, p0 = 8, cnt /* just a few bytes left ? */ +(p_scr) br.cond.dpnt.many .move_bytes_from_alignment +;; } + +.fraction_of_line: +{ .mib + add ptr2 = 16, ptr1 + shr.u loopcnt = cnt, 5 /* loopcnt = cnt / 32 */ +;; } +{ .mib + cmp.eq p_scr, p0 = loopcnt, r0 + add loopcnt = -1, loopcnt +(p_scr) br.cond.dpnt.many store_words +;; } +{ .mib + and cnt = 0x1f, cnt /* compute the remaining cnt */ + movi0 ar.lc = loopcnt +;; } +#ifndef GAS_ALIGN_BREAKS_UNWIND_INFO + .align 32 +#endif +.l2: /* ---------------------------- L2A: store 32B in 2 cycles */ +{ .mmb + store [ptr1] = myval, 8 + store [ptr2] = myval, 8 +;; } { .mmb + store [ptr1] = myval, 24 + store [ptr2] = myval, 24 + br.cloop.dptk.many .l2 +;; } +store_words: +{ .mib + cmp.gt p_scr, p0 = 8, cnt /* just a few bytes left ? */ +(p_scr) br.cond.dpnt.many .move_bytes_from_alignment /* Branch */ +;; } + +{ .mmi + store [ptr1] = myval, 8 /* store */ + cmp.le p_y, p_n = 16, cnt /* */ + add cnt = -8, cnt /* subtract */ +;; } +{ .mmi +(p_y) store [ptr1] = myval, 8 /* store */ +(p_y) cmp.le.unc p_yy, p_nn = 16, cnt /* */ +(p_y) add cnt = -8, cnt /* subtract */ +;; } +{ .mmi /* store */ +(p_yy) store [ptr1] = myval, 8 /* */ +(p_yy) add cnt = -8, cnt /* subtract */ +;; } + +.move_bytes_from_alignment: +{ .mib + cmp.eq p_scr, p0 = cnt, r0 + tbit.nz.unc p_y, p0 = cnt, 2 /* should we terminate with a st4 ? */ +(p_scr) br.cond.dpnt.few .restore_and_exit +;; } +{ .mib +(p_y) st4 [ptr1] = value, 4 + tbit.nz.unc p_yy, p0 = cnt, 1 /* should we terminate with a st2 ? */ +;; } +{ .mib +(p_yy) st2 [ptr1] = value, 2 + tbit.nz.unc p_y, p0 = cnt, 0 +;; } + +{ .mib +(p_y) st1 [ptr1] = value +;; } +.restore_and_exit: +{ .mib + nop.m 0 + movi0 ar.lc = save_lc + br.ret.sptk.many rp +;; } + +.move_bytes_unaligned: +{ .mmi + .pred.rel "mutex",p_y, p_n + .pred.rel "mutex",p_yy, p_nn +(p_n) cmp.le p_yy, p_nn = 4, cnt +(p_y) cmp.le p_yy, p_nn = 5, cnt +(p_n) add ptr2 = 2, ptr1 +} { .mmi +(p_y) add ptr2 = 3, ptr1 +(p_y) st1 [ptr1] = value, 1 /* fill 1 (odd-aligned) byte */ +(p_y) add cnt = -1, cnt /* [15, 14 (or less) left] */ +;; } +{ .mmi +(p_yy) cmp.le.unc p_y, p0 = 8, cnt + add ptr3 = ptr1, cnt /* prepare last store */ + movi0 ar.lc = save_lc +} { .mmi +(p_yy) st2 [ptr1] = value, 4 /* fill 2 (aligned) bytes */ +(p_yy) st2 [ptr2] = value, 4 /* fill 2 (aligned) bytes */ +(p_yy) add cnt = -4, cnt /* [11, 10 (o less) left] */ +;; } +{ .mmi +(p_y) cmp.le.unc p_yy, p0 = 8, cnt + add ptr3 = -1, ptr3 /* last store */ + tbit.nz p_scr, p0 = cnt, 1 /* will there be a st2 at the end ? */ +} { .mmi +(p_y) st2 [ptr1] = value, 4 /* fill 2 (aligned) bytes */ +(p_y) st2 [ptr2] = value, 4 /* fill 2 (aligned) bytes */ +(p_y) add cnt = -4, cnt /* [7, 6 (or less) left] */ +;; } +{ .mmi +(p_yy) st2 [ptr1] = value, 4 /* fill 2 (aligned) bytes */ +(p_yy) st2 [ptr2] = value, 4 /* fill 2 (aligned) bytes */ + /* [3, 2 (or less) left] */ + tbit.nz p_y, p0 = cnt, 0 /* will there be a st1 at the end ? */ +} { .mmi +(p_yy) add cnt = -4, cnt +;; } +{ .mmb +(p_scr) st2 [ptr1] = value /* fill 2 (aligned) bytes */ +(p_y) st1 [ptr3] = value /* fill last byte (using ptr3) */ + br.ret.sptk.many rp +;; } +END(memset) +libc_hidden_def (memset) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/ia64/softpipe.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/ia64/softpipe.h new file mode 100644 index 00000000..d71af735 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/ia64/softpipe.h @@ -0,0 +1,29 @@ +/* This file is part of the GNU C Library. + Copyright (C) 2000 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* The latency of a memory load assumed by the assembly implementation + of the mem and str functions. Since we don't have any clue about + where the data might be, let's assume it's in the L2 cache. + Assuming L3 would be too pessimistic :-) + + Some functions define MEMLAT as 2, because they expect their data + to be in the L1D cache. */ + +#ifndef MEMLAT +# define MEMLAT 6 +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/ia64/strchr.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/ia64/strchr.S new file mode 100644 index 00000000..66703f26 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/ia64/strchr.S @@ -0,0 +1,113 @@ +/* Optimized version of the standard strchr() function. + This file is part of the GNU C Library. + Copyright (C) 2000, 2001, 2003 Free Software Foundation, Inc. + Contributed by Dan Pop . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Return: the address of the first occurence of chr in str or NULL + + Inputs: + in0: str + in1: chr + + A modified version of memchr.S, the search ends when the character is + found or the terminating null character is encountered. + + This implementation assumes little endian mode. For big endian mode, + the instruction czx1.r should be replaced by czx1.l. */ + +#include "sysdep.h" +#undef ret + +#define saved_lc r18 +#define poschr r19 +#define pos0 r20 +#define val1 r21 +#define val2 r22 +#define tmp r24 +#define chrx8 r25 +#define loopcnt r30 + +#define str in0 +#define chr in1 + +ENTRY(strchr) + .prologue + alloc r2 = ar.pfs, 2, 0, 0, 0 + .save ar.lc, saved_lc + mov saved_lc = ar.lc /* save the loop counter */ + .body + mov ret0 = str + and tmp = 7, str /* tmp = str % 8 */ + mux1 chrx8 = chr, @brcst + extr.u chr = chr, 0, 8 /* retain only the last byte */ + cmp.ne p8, p0 = r0, r0 /* clear p8 */ + ;; + sub loopcnt = 8, tmp /* loopcnt = 8 - tmp */ + cmp.eq p6, p0 = tmp, r0 +(p6) br.cond.sptk .str_aligned;; + adds loopcnt = -1, loopcnt;; + mov ar.lc = loopcnt +.l1: + ld1 val2 = [ret0], 1 + ;; + cmp.eq p6, p0 = val2, chr + cmp.eq p7, p0 = val2, r0 +(p6) br.cond.spnt .restore_and_exit +(p7) br.cond.spnt .notfound + br.cloop.sptk .l1 +.str_aligned: + ld8 val1 = [ret0], 8;; + nop.b 0 + nop.b 0 +.l2: + ld8.s val2 = [ret0], 8 /* don't bomb out here */ + czx1.r pos0 = val1 + xor tmp = val1, chrx8 /* if val1 contains chr, tmp will */ + ;; /* contain a zero in its position */ + czx1.r poschr = tmp + cmp.ne p6, p0 = 8, pos0 + ;; + cmp.ne p7, p0 = 8, poschr +(p7) br.cond.spnt .foundit +(p6) br.cond.spnt .notfound + chk.s val2, .recovery +.back: + mov val1 = val2 + br.cond.dptk .l2 +.foundit: +(p6) cmp.lt p8, p0 = pos0, poschr /* we found chr and null in the word */ +(p8) br.cond.spnt .notfound /* null was found before chr */ + add ret0 = ret0, poschr ;; + adds ret0 = -15, ret0 ;; /* should be -16, but we decrement */ +.restore_and_exit: /* ret0 in the next instruction */ + adds ret0 = -1, ret0 /* ret0 was pointing 1 char too far */ + mov ar.lc = saved_lc /* restore the loop counter */ + br.ret.sptk.many b0 +.notfound: + mov ret0 = r0 /* return NULL if null was found */ + mov ar.lc = saved_lc + br.ret.sptk.many b0 +.recovery: + adds ret0 = -8, ret0;; + ld8 val2 = [ret0], 8 /* bomb out here */ + br.cond.sptk .back +END(strchr) +libc_hidden_def (strchr) +#ifdef __UCLIBC_SUSV3_LEGACY__ +strong_alias (strchr, index) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/ia64/strcmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/ia64/strcmp.S new file mode 100644 index 00000000..4da72fa1 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/ia64/strcmp.S @@ -0,0 +1,59 @@ +/* Optimized version of the standard strcmp() function. + This file is part of the GNU C Library. + Copyright (C) 2000, 2001, 2003 Free Software Foundation, Inc. + Contributed by Dan Pop . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Return: the result of the comparison + + Inputs: + in0: s1 + in1: s2 + + Unlike memcmp(), this function is optimized for mismatches within the + first few characters. */ + +#include "sysdep.h" +#undef ret + +#define s1 in0 +#define s2 in1 + +#define val1 r15 +#define val2 r16 + + +ENTRY(strcmp) + alloc r2 = ar.pfs, 2, 0, 0, 0 +.loop: + ld1 val1 = [s1], 1 + ld1 val2 = [s2], 1 + cmp.eq p6, p0 = r0, r0 /* set p6 */ + ;; + cmp.ne.and p6, p0 = val1, r0 + cmp.ne.and p6, p0 = val2, r0 + cmp.eq.and p6, p0 = val1, val2 +(p6) br.cond.sptk .loop + sub ret0 = val1, val2 + br.ret.sptk.many b0 +END(strcmp) +libc_hidden_def (strcmp) + +#ifndef __UCLIBC_HAS_LOCALE__ +strong_alias(strcmp,strcoll) +libc_hidden_def(strcoll) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/ia64/strcpy.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/ia64/strcpy.S new file mode 100644 index 00000000..7b002f66 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/ia64/strcpy.S @@ -0,0 +1,145 @@ +/* Optimized version of the standard strcpy() function. + This file is part of the GNU C Library. + Copyright (C) 2000, 2001, 2003 Free Software Foundation, Inc. + Contributed by Dan Pop . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Return: dest + + Inputs: + in0: dest + in1: src + + In this form, it assumes little endian mode. For big endian mode, the + the two shifts in .l2 must be inverted: + + shl value = r[1], sh1 // value = w0 << sh1 + shr.u tmp = r[0], sh2 // tmp = w1 >> sh2 + */ + +#include "sysdep.h" +#undef ret + +#define saved_lc r15 +#define saved_pr r16 +#define thresh r17 +#define dest r19 +#define src r20 +#define len r21 +#define asrc r22 +#define tmp r23 +#define pos r24 +#define w0 r25 +#define w1 r26 +#define c r27 +#define sh2 r28 +#define sh1 r29 +#define loopcnt r30 +#define value r31 + +ENTRY(strcpy) + .prologue + alloc r2 = ar.pfs, 2, 0, 30, 32 + +#define MEMLAT 2 + .rotr r[MEMLAT + 2] + .rotp p[MEMLAT + 1] + + mov ret0 = in0 /* return value = dest */ + .save pr, saved_pr + mov saved_pr = pr /* save the predicate registers */ + .save ar.lc, saved_lc + mov saved_lc = ar.lc /* save the loop counter */ + .body + sub tmp = r0, in0 ;; /* tmp = -dest */ + mov dest = in0 /* dest */ + mov src = in1 /* src */ + and loopcnt = 7, tmp ;; /* loopcnt = -dest % 8 */ + cmp.eq p6, p0 = loopcnt, r0 + adds loopcnt = -1, loopcnt /* --loopcnt */ +(p6) br.cond.sptk .dest_aligned ;; + mov ar.lc = loopcnt +.l1: /* copy -dest % 8 bytes */ + ld1 c = [src], 1 /* c = *src++ */ + ;; + st1 [dest] = c, 1 /* *dest++ = c */ + cmp.eq p6, p0 = c, r0 +(p6) br.cond.dpnt .restore_and_exit + br.cloop.dptk .l1 ;; +.dest_aligned: + and sh1 = 7, src /* sh1 = src % 8 */ + mov ar.lc = -1 /* "infinite" loop */ + and asrc = -8, src ;; /* asrc = src & -OPSIZ -- align src */ + sub thresh = 8, sh1 + mov pr.rot = 1 << 16 /* set rotating predicates */ + cmp.ne p7, p0 = r0, r0 /* clear p7 */ + shl sh1 = sh1, 3 ;; /* sh1 = 8 * (src % 8) */ + sub sh2 = 64, sh1 /* sh2 = 64 - sh1 */ + cmp.eq p6, p0 = sh1, r0 /* is the src aligned? */ +(p6) br.cond.sptk .src_aligned ;; + ld8 r[1] = [asrc],8 ;; + + .align 32 +.l2: + ld8.s r[0] = [asrc], 8 + shr.u value = r[1], sh1 ;; /* value = w0 >> sh1 */ + czx1.r pos = value ;; /* do we have an "early" zero */ + cmp.lt p7, p0 = pos, thresh /* in w0 >> sh1? */ +(p7) br.cond.dpnt .found0 + chk.s r[0], .recovery2 /* it is safe to do that only */ +.back2: /* after the previous test */ + shl tmp = r[0], sh2 /* tmp = w1 << sh2 */ + ;; + or value = value, tmp ;; /* value |= tmp */ + czx1.r pos = value ;; + cmp.ne p7, p0 = 8, pos +(p7) br.cond.dpnt .found0 + st8 [dest] = value, 8 /* store val to dest */ + br.ctop.dptk .l2 ;; +.src_aligned: +.l3: +(p[0]) ld8.s r[0] = [src], 8 +(p[MEMLAT]) chk.s r[MEMLAT], .recovery3 +.back3: +(p[MEMLAT]) mov value = r[MEMLAT] +(p[MEMLAT]) czx1.r pos = r[MEMLAT] ;; +(p[MEMLAT]) cmp.ne p7, p0 = 8, pos +(p7) br.cond.dpnt .found0 +(p[MEMLAT]) st8 [dest] = r[MEMLAT], 8 + br.ctop.dptk .l3 ;; +.found0: + mov ar.lc = pos +.l4: + extr.u c = value, 0, 8 /* c = value & 0xff */ + shr.u value = value, 8 + ;; + st1 [dest] = c, 1 + br.cloop.dptk .l4 ;; +.restore_and_exit: + mov ar.lc = saved_lc /* restore the loop counter */ + mov pr = saved_pr, -1 /* restore the predicate registers */ + br.ret.sptk.many b0 +.recovery2: + add tmp = -8, asrc ;; + ld8 r[0] = [tmp] + br.cond.sptk .back2 +.recovery3: + add tmp = -(MEMLAT + 1) * 8, src ;; + ld8 r[MEMLAT] = [tmp] + br.cond.sptk .back3 +END(strcpy) +libc_hidden_def (strcpy) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/ia64/strlen.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/ia64/strlen.S new file mode 100644 index 00000000..edbe8435 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/ia64/strlen.S @@ -0,0 +1,98 @@ +/* Optimized version of the standard strlen() function. + This file is part of the GNU C Library. + Copyright (C) 2000, 2001, 2003, 2005 Free Software Foundation, Inc. + Contributed by Dan Pop . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Return: the length of the input string + + Input: + in0: str + + Look for the null character byte by byte, until we reach a word aligned + address, then search word by word, using the czx instruction. We're + also doing one word of read ahead, which could cause problems if the + null character is on the last word of a page and the next page is not + mapped in the process address space. Hence the use of the speculative + load. + + This implementation assumes little endian mode. For big endian mode, + the instruction czx1.r should be replaced by czx1.l. */ + +#include "sysdep.h" +#undef ret + +#define saved_lc r18 +#define str r19 +#define pos0 r20 +#define val1 r21 +#define val2 r22 +#define origadd r23 +#define tmp r24 +#define loopcnt r30 +#define len ret0 + +ENTRY(strlen) + .prologue + alloc r2 = ar.pfs, 1, 0, 0, 0 + .save ar.lc, saved_lc + mov saved_lc = ar.lc /* save the loop counter */ + .body + mov str = in0 + mov len = r0 /* len = 0 */ + and tmp = 7, in0 /* tmp = str % 8 */ + ;; + sub loopcnt = 8, tmp /* loopcnt = 8 - tmp */ + cmp.eq p6, p0 = tmp, r0 +(p6) br.cond.sptk .str_aligned;; + adds loopcnt = -1, loopcnt;; + mov ar.lc = loopcnt +.l1: + ld1 val2 = [str], 1 + ;; + cmp.eq p6, p0 = val2, r0 +(p6) br.cond.spnt .restore_and_exit + adds len = 1, len + br.cloop.dptk .l1 +.str_aligned: + mov origadd = str /* origadd = orig */ + ld8 val1 = [str], 8;; + nop.b 0 + nop.b 0 +.l2: ld8.s val2 = [str], 8 /* don't bomb out here */ + czx1.r pos0 = val1 + ;; + cmp.ne p6, p0 = 8, pos0 +(p6) br.cond.spnt .foundit + chk.s val2, .recovery +.back: + mov val1 = val2 + br.cond.dptk .l2 +.foundit: + sub tmp = str, origadd /* tmp = crt address - orig */ + add len = len, pos0;; + add len = len, tmp;; + adds len = -16, len +.restore_and_exit: + mov ar.lc = saved_lc /* restore the loop counter */ + br.ret.sptk.many b0 +.recovery: + adds str = -8, str;; + ld8 val2 = [str], 8 /* bomb out here */ + br.cond.sptk .back +END(strlen) +libc_hidden_def (strlen) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/ia64/strncmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/ia64/strncmp.S new file mode 100644 index 00000000..e31f8fbd --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/ia64/strncmp.S @@ -0,0 +1,62 @@ +/* Optimized version of the standard strncmp() function. + This file is part of the GNU C Library. + Copyright (C) 2000, 2001, 2003 Free Software Foundation, Inc. + Contributed by Dan Pop . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Return: the result of the comparison + + Inputs: + in0: s1 + in1: s2 + in2: n + + Unlike memcmp(), this function is optimized for mismatches within the + first few characters. */ + +#include "sysdep.h" +#undef ret + +#define s1 in0 +#define s2 in1 +#define n in2 + +#define val1 r15 +#define val2 r16 + + +ENTRY(strncmp) + alloc r2 = ar.pfs, 3, 0, 0, 0 + mov ret0 = r0 + cmp.eq p6, p0 = r0, r0 /* set p6 */ + cmp.eq p7, p0 = n, r0 /* return immediately if n == 0 */ +(p7) br.cond.spnt .restore_and_exit ;; +.loop: + ld1 val1 = [s1], 1 + ld1 val2 = [s2], 1 + adds n = -1, n /* n-- */ + ;; + cmp.ne.and p6, p0 = val1, r0 + cmp.ne.and p6, p0 = val2, r0 + cmp.ne.and p6, p0 = n, r0 + cmp.eq.and p6, p0 = val1, val2 +(p6) br.cond.sptk .loop + sub ret0 = val1, val2 +.restore_and_exit: + br.ret.sptk.many b0 +END(strncmp) +libc_hidden_weak (strncmp) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/ia64/strncpy.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/ia64/strncpy.S new file mode 100644 index 00000000..3f29bbd5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/ia64/strncpy.S @@ -0,0 +1,232 @@ +/* Optimized version of the standard strncpy() function. + This file is part of the GNU C Library. + Copyright (C) 2000, 2001, 2002, 2003 Free Software Foundation, Inc. + Contributed by Dan Pop + and Jakub Jelinek . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Return: dest + + Inputs: + in0: dest + in1: src + in2: len + + In this form, it assumes little endian mode. + */ + +#include "sysdep.h" +#undef ret + +#define saved_lc r15 +#define saved_pr r16 +#define thresh r17 +#define dest r18 +#define dest2 r19 +#define src r20 +#define len r21 +#define asrc r22 +#define tmp r23 +#define pos r24 +#define w0 r25 +#define w1 r26 +#define c r27 +#define sh2 r28 +#define sh1 r29 +#define loopcnt r30 +#define value r31 + +ENTRY(strncpy) + .prologue + alloc r2 = ar.pfs, 3, 0, 29, 32 + +#define MEMLAT 2 + .rotr r[MEMLAT + 2] + .rotp p[MEMLAT + 1] + + mov ret0 = in0 /* return value = dest */ + .save pr, saved_pr + mov saved_pr = pr /* save the predicate registers */ + .save ar.lc, saved_lc + mov saved_lc = ar.lc /* save the loop counter */ + mov ar.ec = 0 /* ec is not guaranteed to */ + /* be zero upon function entry */ + .body + cmp.geu p6, p5 = 24, in2 +(p6) br.cond.spnt .short_len + sub tmp = r0, in0 ;; /* tmp = -dest */ + mov len = in2 /* len */ + mov dest = in0 /* dest */ + mov src = in1 /* src */ + and tmp = 7, tmp ;; /* loopcnt = -dest % 8 */ + cmp.eq p6, p7 = tmp, r0 + adds loopcnt = -1, tmp /* --loopcnt */ +(p6) br.cond.sptk .dest_aligned ;; + sub len = len, tmp /* len -= -dest % 8 */ + mov ar.lc = loopcnt +.l1: /* copy -dest % 8 bytes */ +(p5) ld1 c = [src], 1 /* c = *src++ */ + ;; + st1 [dest] = c, 1 /* *dest++ = c */ + cmp.ne p5, p7 = c, r0 + br.cloop.dptk .l1 ;; +(p7) br.cond.dpnt .found0_align + +.dest_aligned: /* p7 should be cleared here */ + shr.u c = len, 3 /* c = len / 8 */ + and sh1 = 7, src /* sh1 = src % 8 */ + and asrc = -8, src ;; /* asrc = src & -OPSIZ -- align src */ + adds c = (MEMLAT-1), c /* c = (len / 8) + MEMLAT - 1 */ + sub thresh = 8, sh1 + mov pr.rot = 1 << 16 /* set rotating predicates */ + shl sh1 = sh1, 3 ;; /* sh1 = 8 * (src % 8) */ + mov ar.lc = c /* "infinite" loop */ + sub sh2 = 64, sh1 /* sh2 = 64 - sh1 */ + cmp.eq p6, p0 = sh1, r0 /* is the src aligned? */ +(p6) br.cond.sptk .src_aligned + adds c = -(MEMLAT-1), c ;; /* c = (len / 8) */ + ld8 r[1] = [asrc],8 + mov ar.lc = c ;; + + .align 32 +.l2: +(p6) st8 [dest] = value, 8 /* store val to dest */ + ld8.s r[0] = [asrc], 8 + shr.u value = r[1], sh1 ;; /* value = w0 >> sh1 */ + czx1.r pos = value ;; /* do we have an "early" zero */ + cmp.lt p7, p0 = pos, thresh /* in w0 >> sh1? */ + adds len = -8, len /* len -= 8 */ +(p7) br.cond.dpnt .nonalign_found0 + chk.s r[0], .recovery2 /* it is safe to do that only */ +.back2: /* after the previous test */ + shl tmp = r[0], sh2 /* tmp = w1 << sh2 */ + ;; + or value = value, tmp ;; /* value |= tmp */ + czx1.r pos = value ;; + cmp.ne p7, p6 = 8, pos +(p7) br.cond.dpnt .nonalign_found0 + br.ctop.dptk .l2 ;; + adds len = 8, len + br.cond.sptk .not_found0 ;; +.nonalign_found0: + cmp.gtu p6, p0 = -8, len +(p6) br.cond.dptk .found0 + adds len = 8, len + br.cond.sptk .not_found0 ;; + + .align 32 +.src_aligned: +.l3: +(p[0]) ld8.s r[0] = [src], 8 +(p[MEMLAT]) chk.s r[MEMLAT], .recovery3 +.back3: +(p[MEMLAT]) mov value = r[MEMLAT] +(p[MEMLAT]) czx1.r pos = r[MEMLAT] ;; +(p[MEMLAT]) cmp.ne p7, p0 = 8, pos +(p[MEMLAT]) adds len = -8, len /* len -= 8 */ +(p7) br.cond.dpnt .found0 +(p[MEMLAT]) st8 [dest] = r[MEMLAT], 8 + br.ctop.dptk .l3 ;; + + chk.s r[MEMLAT-1], .recovery4 +.back4: + mov value = r[MEMLAT-1] + +.not_found0: + cmp.eq p5, p6 = len, r0 + adds len = -1, len +(p5) br.cond.dptk .restore_and_exit ;; + mov ar.lc = len +.l4: +(p6) extr.u c = value, 0, 8 /* c = value & 0xff */ +(p6) shr.u value = value, 8 ;; + st1 [dest] = c, 1 + cmp.ne p6, p0 = c, r0 + br.cloop.dptk .l4 + br.cond.sptk .restore_and_exit + +.found0_align: + mov pos = 0 + adds len = -8, len + mov value = 0 ;; +.found0: + shl tmp = pos, 3 + shr.u loopcnt = len, 4 /* loopcnt = len / 16 */ + mov c = -1 ;; + cmp.eq p6, p0 = loopcnt, r0 + adds loopcnt = -1, loopcnt + shl c = c, tmp ;; + and len = 0xf, len + andcm value = value, c + mov ar.lc = loopcnt ;; + cmp.le p7, p0 = 8, len + adds dest2 = 16, dest + st8 [dest] = value, 8 + and len = 0x7, len +(p6) br.cond.dpnt .l6 ;; +.l5: + st8 [dest] = r0, 16 + st8 [dest2] = r0, 16 + br.cloop.dptk .l5 ;; +.l6: +(p7) st8 [dest] = r0, 8 + cmp.eq p5, p0 = len, r0 + adds len = -1, len +(p5) br.cond.dptk .restore_and_exit ;; + mov ar.lc = len ;; +.l7: + st1 [dest] = r0, 1 + br.cloop.dptk .l7 ;; +.restore_and_exit: + mov ar.lc = saved_lc /* restore the loop counter */ + mov pr = saved_pr, -1 /* restore the predicate registers */ + br.ret.sptk.many b0 + +.short_len: + cmp.eq p5, p0 = in2, r0 + adds loopcnt = -1, in2 +(p5) br.cond.spnt .restore_and_exit ;; + mov ar.lc = loopcnt /* p6 should be set when we get here */ +.l8: +(p6) ld1 c = [in1], 1 /* c = *src++ */ + ;; + st1 [in0] = c, 1 /* *dest++ = c */ +(p6) cmp.ne p6, p0 = c, r0 + br.cloop.dptk .l8 + ;; + mov ar.lc = saved_lc /* restore the loop counter */ + mov pr = saved_pr, -1 /* restore the predicate registers */ + br.ret.sptk.many b0 +.recovery2: + add c = 8, len + add tmp = -8, asrc ;; + cmp.gtu p8, p5 = c, thresh ;; +(p8) ld8 r[0] = [tmp] +(p5) mov r[0] = r0 + br.cond.sptk .back2 +.recovery3: + add tmp = -(MEMLAT + 1) * 8, src ;; + ld8 r[MEMLAT] = [tmp] + br.cond.sptk .back3 +.recovery4: + cmp.eq p5, p6 = len, r0 + add tmp = -MEMLAT * 8, src ;; +(p6) ld8 r[MEMLAT - 1] = [tmp] +(p5) mov r[MEMLAT - 1] = r0 + br.cond.sptk .back4 +END(strncpy) +libc_hidden_def (strncpy) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/ia64/sysdep.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/ia64/sysdep.h new file mode 100644 index 00000000..d10020ac --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/ia64/sysdep.h @@ -0,0 +1,168 @@ +/* Copyright (C) 1999, 2000, 2002, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Written by Jes Sorensen, , April 1999. + Based on code originally written by David Mosberger-Tang + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _LINUX_IA64_SYSDEP_H +#define _LINUX_IA64_SYSDEP_H 1 + +#include +#include + +#ifdef __ASSEMBLER__ + +/* Macros to help writing .prologue directives in assembly code. */ +#define ASM_UNW_PRLG_RP 0x8 +#define ASM_UNW_PRLG_PFS 0x4 +#define ASM_UNW_PRLG_PSP 0x2 +#define ASM_UNW_PRLG_PR 0x1 +#define ASM_UNW_PRLG_GRSAVE(ninputs) (32+(ninputs)) + +#ifdef __STDC__ +#define C_LABEL(name) name : +#else +#define C_LABEL(name) name/**/: +#endif + +#define CALL_MCOUNT + +#define ENTRY(name) \ + .text; \ + .align 32; \ + .proc C_SYMBOL_NAME(name); \ + .global C_SYMBOL_NAME(name); \ + C_LABEL(name) \ + CALL_MCOUNT + +#define LEAF(name) \ + .text; \ + .align 32; \ + .proc C_SYMBOL_NAME(name); \ + .global name; \ + C_LABEL(name) + +/* Mark the end of function SYM. */ +#undef END +#define END(sym) .endp C_SYMBOL_NAME(sym) + +/* For Linux we can use the system call table in the header file + /usr/include/asm/unistd.h + of the kernel. But these symbols do not follow the SYS_* syntax + so we have to redefine the `SYS_ify' macro here. */ +#undef SYS_ify +#ifdef __STDC__ +# define SYS_ify(syscall_name) __NR_##syscall_name +#else +# define SYS_ify(syscall_name) __NR_/**/syscall_name +#endif + +/* Linux uses a negative return value to indicate syscall errors, unlike + most Unices, which use the condition codes' carry flag. + + Since version 2.1 the return value of a system call might be negative + even if the call succeeded. E.g., the `lseek' system call might return + a large offset. Therefore we must not anymore test for < 0, but test + for a real error by making sure the value in %d0 is a real error + number. Linus said he will make sure the no syscall returns a value + in -1 .. -4095 as a valid result so we can savely test with -4095. */ + +/* We don't want the label for the error handler to be visible in the symbol + table when we define it here. */ +#define SYSCALL_ERROR_LABEL __syscall_error + +#undef PSEUDO +#define PSEUDO(name, syscall_name, args) \ + ENTRY(name) \ + DO_CALL (SYS_ify(syscall_name)); \ + cmp.eq p6,p0=-1,r10; \ +(p6) br.cond.spnt.few __syscall_error; + +#define DO_CALL_VIA_BREAK(num) \ + mov r15=num; \ + break __BREAK_SYSCALL + +#ifdef IA64_USE_NEW_STUB +# ifdef SHARED +# define DO_CALL(num) \ + .prologue; \ + adds r2 = SYSINFO_OFFSET, r13;; \ + ld8 r2 = [r2]; \ + .save ar.pfs, r11; \ + mov r11 = ar.pfs;; \ + .body; \ + mov r15 = num; \ + mov b7 = r2; \ + br.call.sptk.many b6 = b7;; \ + .restore sp; \ + mov ar.pfs = r11; \ + .prologue; \ + .body +# else /* !SHARED */ +# define DO_CALL(num) \ + .prologue; \ + mov r15 = num; \ + movl r2 = _dl_sysinfo;; \ + ld8 r2 = [r2]; \ + .save ar.pfs, r11; \ + mov r11 = ar.pfs;; \ + .body; \ + mov b7 = r2; \ + br.call.sptk.many b6 = b7;; \ + .restore sp; \ + mov ar.pfs = r11; \ + .prologue; \ + .body +# endif +#else +# define DO_CALL(num) DO_CALL_VIA_BREAK(num) +#endif + +#undef PSEUDO_END +#define PSEUDO_END(name) .endp C_SYMBOL_NAME(name); + +#undef PSEUDO_NOERRNO +#define PSEUDO_NOERRNO(name, syscall_name, args) \ + ENTRY(name) \ + DO_CALL (SYS_ify(syscall_name)); + +#undef PSEUDO_END_NOERRNO +#define PSEUDO_END_NOERRNO(name) .endp C_SYMBOL_NAME(name); + +#undef PSEUDO_ERRVAL +#define PSEUDO_ERRVAL(name, syscall_name, args) \ + ENTRY(name) \ + DO_CALL (SYS_ify(syscall_name)); \ + cmp.eq p6,p0=-1,r10; \ +(p6) mov r10=r8; + + +#undef PSEUDO_END_ERRVAL +#define PSEUDO_END_ERRVAL(name) .endp C_SYMBOL_NAME(name); + +#undef END +#define END(name) \ + .size C_SYMBOL_NAME(name), . - C_SYMBOL_NAME(name) ; \ + .endp C_SYMBOL_NAME(name) + +#define ret br.ret.sptk.few b0 +#define ret_NOERRNO ret +#define ret_ERRVAL ret + +#endif /* not __ASSEMBLER__ */ + +#endif /* linux/ia64/sysdep.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/memccpy.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/memccpy.c new file mode 100644 index 00000000..076bdac7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/memccpy.c @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* No wide analog. */ + +#include "_string.h" + +void *memccpy(void * __restrict s1, const void * __restrict s2, int c, size_t n) +{ + register char *r1 = s1; + register const char *r2 = s2; + + while (n-- && (((unsigned char)(*r1++ = *r2++)) != ((unsigned char) c))); + + return (n == (size_t) -1) ? NULL : r1; +} +libc_hidden_def(memccpy) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/memchr.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/memchr.c new file mode 100644 index 00000000..99e13a2f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/memchr.c @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include "_string.h" + +#ifdef WANT_WIDE +# define Wmemchr wmemchr +#else +# undef memchr +# define Wmemchr memchr +#endif + +Wvoid *Wmemchr(const Wvoid *s, Wint c, size_t n) +{ + register const Wuchar *r = (const Wuchar *) s; + + while (n) { + if (*r == ((Wuchar)c)) { + return (Wvoid *) r; /* silence the warning */ + } + ++r; + --n; + } + + return NULL; +} + +libc_hidden_def(Wmemchr) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/memcmp.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/memcmp.c new file mode 100644 index 00000000..6cb37f41 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/memcmp.c @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include "_string.h" + +#ifdef WANT_WIDE +# define Wmemcmp wmemcmp +#else +# define Wmemcmp memcmp +#endif + +int Wmemcmp(const Wvoid *s1, const Wvoid *s2, size_t n) +{ + register const Wuchar *r1 = (const Wuchar *) s1; + register const Wuchar *r2 = (const Wuchar *) s2; + +#ifdef WANT_WIDE + while (n && (*r1 == *r2)) { + ++r1; + ++r2; + --n; + } + + return (n == 0) ? 0 : ((*r1 < *r2) ? -1 : 1); +#else + int r = 0; + + while (n-- && ((r = ((int)(*r1++)) - *r2++) == 0)); + + return r; +#endif +} + +#ifndef WANT_WIDE +libc_hidden_def(memcmp) +# ifdef __UCLIBC_SUSV3_LEGACY__ +strong_alias(memcmp,bcmp) +# endif +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/memcpy.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/memcpy.c new file mode 100644 index 00000000..42436e0b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/memcpy.c @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include "_string.h" + +#ifdef WANT_WIDE +# define Wmemcpy wmemcpy +#else +# undef memcpy +# define Wmemcpy memcpy +#endif + +Wvoid *Wmemcpy(Wvoid * __restrict s1, const Wvoid * __restrict s2, size_t n) +{ + register Wchar *r1 = s1; + register const Wchar *r2 = s2; + + while (n) { + *r1++ = *r2++; + --n; + } + + return s1; +} +libc_hidden_def(Wmemcpy) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/memmem.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/memmem.c new file mode 100644 index 00000000..f568a426 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/memmem.c @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include "_string.h" + +#ifdef __USE_GNU +void *memmem(const void *haystack, size_t haystacklen, + const void *needle, size_t needlelen) +{ + register const char *ph; + register const char *pn; + const char *plast; + size_t n; + + if (needlelen == 0) { + return (void *) haystack; + } + + if (haystacklen >= needlelen) { + ph = (const char *) haystack; + pn = (const char *) needle; + plast = ph + (haystacklen - needlelen); + + do { + n = 0; + while (ph[n] == pn[n]) { + if (++n == needlelen) { + return (void *) ph; + } + } + } while (++ph <= plast); + } + + return NULL; +} +libc_hidden_def(memmem) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/memmove.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/memmove.c new file mode 100644 index 00000000..9fb0efee --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/memmove.c @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include "_string.h" + +#ifdef WANT_WIDE +# define Wmemmove wmemmove +#else +# define Wmemmove memmove +#endif + +Wvoid *Wmemmove(Wvoid *s1, const Wvoid *s2, size_t n) +{ + register Wchar *s = (Wchar *) s1; + register const Wchar *p = (const Wchar *) s2; + + if (p >= s) { + while (n) { + *s++ = *p++; + --n; + } + } else { + while (n) { + --n; + s[n] = p[n]; + } + } + + return s1; +} + +#ifndef WANT_WIDE +libc_hidden_def(Wmemmove) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/mempcpy.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/mempcpy.c new file mode 100644 index 00000000..d1d752b5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/mempcpy.c @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include "_string.h" + +#ifdef __USE_GNU + +#ifdef WANT_WIDE +# define Wmempcpy wmempcpy +#else +# undef mempcpy +# define Wmempcpy mempcpy +#endif + +Wvoid *Wmempcpy(Wvoid * __restrict s1, const Wvoid * __restrict s2, size_t n) +{ + register Wchar *r1 = s1; + register const Wchar *r2 = s2; + + while (n) { + *r1++ = *r2++; + --n; + } + + return r1; +} + +libc_hidden_weak(Wmempcpy) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/memrchr.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/memrchr.c new file mode 100644 index 00000000..60211f80 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/memrchr.c @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include "_string.h" + +#ifdef __USE_GNU +void *memrchr(const void *s, int c, size_t n) +{ + register const unsigned char *r; + + r = ((unsigned char *)s) + ((size_t) n); + + while (n) { + if (*--r == ((unsigned char)c)) { + return (void *) r; /* silence the warning */ + } + --n; + } + + return NULL; +} + +libc_hidden_def(memrchr) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/memset.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/memset.c new file mode 100644 index 00000000..2a7c19de --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/memset.c @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include "_string.h" + +#ifdef WANT_WIDE +# define Wmemset wmemset +#else +# undef memset +# define Wmemset memset +#endif + +Wvoid *Wmemset(Wvoid *s, Wint c, size_t n) +{ + register Wuchar *p = (Wuchar *) s; + + while (n) { + *p++ = (Wuchar) c; + --n; + } + + return s; +} + +#ifndef WANT_WIDE +libc_hidden_def(memset) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/microblaze/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/microblaze/Makefile new file mode 100644 index 00000000..5bdfef2f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/microblaze/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir := ../../../ +top_builddir := ../../../ +all: objs +include $(top_builddir)Rules.mak +include ../Makefile.in +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/microblaze/memcpy.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/microblaze/memcpy.S new file mode 100644 index 00000000..7cf081e8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/microblaze/memcpy.S @@ -0,0 +1,326 @@ +/* + * Copyright (C) 2008-2009 Michal Simek + * Copyright (C) 2008-2009 PetaLogix + * Copyright (C) 2008 Jim Law - Iris LP All rights reserved. + * + * This file is subject to the terms and conditions of the GNU General + * Public License. See the file COPYING in the main directory of this + * archive for more details. + * + * Written by Jim Law + * + * intended to replace: + * memcpy in memcpy.c and + * memmove in memmove.c + * ... in arch/microblaze/lib + * + * + * assly_fastcopy.S + * + * Attempt at quicker memcpy and memmove for MicroBlaze + * Input : Operand1 in Reg r5 - destination address + * Operand2 in Reg r6 - source address + * Operand3 in Reg r7 - number of bytes to transfer + * Output: Result in Reg r3 - starting destinaition address + * + * + * Explanation: + * Perform (possibly unaligned) copy of a block of memory + * between mem locations with size of xfer spec'd in bytes + */ + + .text + .globl memcpy + .type memcpy, @function + .ent memcpy + +memcpy: +fast_memcpy_ascending: + /* move d to return register as value of function */ + addi r3, r5, 0 + + addi r4, r0, 4 /* n = 4 */ + cmpu r4, r4, r7 /* n = c - n (unsigned) */ + blti r4, a_xfer_end /* if n < 0, less than one word to transfer */ + + /* transfer first 0~3 bytes to get aligned dest address */ + andi r4, r5, 3 /* n = d & 3 */ + /* if zero, destination already aligned */ + beqi r4, a_dalign_done + /* n = 4 - n (yields 3, 2, 1 transfers for 1, 2, 3 addr offset) */ + rsubi r4, r4, 4 + rsub r7, r4, r7 /* c = c - n adjust c */ + +a_xfer_first_loop: + /* if no bytes left to transfer, transfer the bulk */ + beqi r4, a_dalign_done + lbui r11, r6, 0 /* h = *s */ + sbi r11, r5, 0 /* *d = h */ + addi r6, r6, 1 /* s++ */ + addi r5, r5, 1 /* d++ */ + brid a_xfer_first_loop /* loop */ + addi r4, r4, -1 /* n-- (IN DELAY SLOT) */ + +a_dalign_done: + addi r4, r0, 32 /* n = 32 */ + cmpu r4, r4, r7 /* n = c - n (unsigned) */ + /* if n < 0, less than one block to transfer */ + blti r4, a_block_done + +a_block_xfer: + andi r9, r6, 3 /* t1 = s & 3 */ + /* if temp == 0, everything is word-aligned */ + beqi r9, a_word_xfer + +a_block_unaligned: + andi r4, r7, 0xffffffe0 /* n = c & ~31 */ + rsub r7, r4, r7 /* c = c - n */ + andi r8, r6, 0xfffffffc /* as = s & ~3 */ + add r6, r6, r4 /* s = s + n */ + lwi r11, r8, 0 /* h = *(as + 0) */ + + addi r9, r9, -1 + beqi r9, a_block_u1 /* t1 was 1 => 1 byte offset */ + addi r9, r9, -1 + beqi r9, a_block_u2 /* t1 was 2 => 2 byte offset */ + +a_block_u3: + bslli r11, r11, 24 /* h = h << 24 */ +a_bu3_loop: + lwi r12, r8, 4 /* v = *(as + 4) */ + bsrli r9, r12, 8 /* t1 = v >> 8 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 0 /* *(d + 0) = t1 */ + bslli r11, r12, 24 /* h = v << 24 */ + lwi r12, r8, 8 /* v = *(as + 8) */ + bsrli r9, r12, 8 /* t1 = v >> 8 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 4 /* *(d + 4) = t1 */ + bslli r11, r12, 24 /* h = v << 24 */ + lwi r12, r8, 12 /* v = *(as + 12) */ + bsrli r9, r12, 8 /* t1 = v >> 8 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 8 /* *(d + 8) = t1 */ + bslli r11, r12, 24 /* h = v << 24 */ + lwi r12, r8, 16 /* v = *(as + 16) */ + bsrli r9, r12, 8 /* t1 = v >> 8 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 12 /* *(d + 12) = t1 */ + bslli r11, r12, 24 /* h = v << 24 */ + lwi r12, r8, 20 /* v = *(as + 20) */ + bsrli r9, r12, 8 /* t1 = v >> 8 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 16 /* *(d + 16) = t1 */ + bslli r11, r12, 24 /* h = v << 24 */ + lwi r12, r8, 24 /* v = *(as + 24) */ + bsrli r9, r12, 8 /* t1 = v >> 8 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 20 /* *(d + 20) = t1 */ + bslli r11, r12, 24 /* h = v << 24 */ + lwi r12, r8, 28 /* v = *(as + 28) */ + bsrli r9, r12, 8 /* t1 = v >> 8 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 24 /* *(d + 24) = t1 */ + bslli r11, r12, 24 /* h = v << 24 */ + lwi r12, r8, 32 /* v = *(as + 32) */ + bsrli r9, r12, 8 /* t1 = v >> 8 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 28 /* *(d + 28) = t1 */ + bslli r11, r12, 24 /* h = v << 24 */ + addi r8, r8, 32 /* as = as + 32 */ + addi r4, r4, -32 /* n = n - 32 */ + bneid r4, a_bu3_loop /* while (n) loop */ + addi r5, r5, 32 /* d = d + 32 (IN DELAY SLOT) */ + bri a_block_done + +a_block_u1: + bslli r11, r11, 8 /* h = h << 8 */ +a_bu1_loop: + lwi r12, r8, 4 /* v = *(as + 4) */ + bsrli r9, r12, 24 /* t1 = v >> 24 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 0 /* *(d + 0) = t1 */ + bslli r11, r12, 8 /* h = v << 8 */ + lwi r12, r8, 8 /* v = *(as + 8) */ + bsrli r9, r12, 24 /* t1 = v >> 24 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 4 /* *(d + 4) = t1 */ + bslli r11, r12, 8 /* h = v << 8 */ + lwi r12, r8, 12 /* v = *(as + 12) */ + bsrli r9, r12, 24 /* t1 = v >> 24 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 8 /* *(d + 8) = t1 */ + bslli r11, r12, 8 /* h = v << 8 */ + lwi r12, r8, 16 /* v = *(as + 16) */ + bsrli r9, r12, 24 /* t1 = v >> 24 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 12 /* *(d + 12) = t1 */ + bslli r11, r12, 8 /* h = v << 8 */ + lwi r12, r8, 20 /* v = *(as + 20) */ + bsrli r9, r12, 24 /* t1 = v >> 24 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 16 /* *(d + 16) = t1 */ + bslli r11, r12, 8 /* h = v << 8 */ + lwi r12, r8, 24 /* v = *(as + 24) */ + bsrli r9, r12, 24 /* t1 = v >> 24 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 20 /* *(d + 20) = t1 */ + bslli r11, r12, 8 /* h = v << 8 */ + lwi r12, r8, 28 /* v = *(as + 28) */ + bsrli r9, r12, 24 /* t1 = v >> 24 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 24 /* *(d + 24) = t1 */ + bslli r11, r12, 8 /* h = v << 8 */ + lwi r12, r8, 32 /* v = *(as + 32) */ + bsrli r9, r12, 24 /* t1 = v >> 24 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 28 /* *(d + 28) = t1 */ + bslli r11, r12, 8 /* h = v << 8 */ + addi r8, r8, 32 /* as = as + 32 */ + addi r4, r4, -32 /* n = n - 32 */ + bneid r4, a_bu1_loop /* while (n) loop */ + addi r5, r5, 32 /* d = d + 32 (IN DELAY SLOT) */ + bri a_block_done + +a_block_u2: + bslli r11, r11, 16 /* h = h << 16 */ +a_bu2_loop: + lwi r12, r8, 4 /* v = *(as + 4) */ + bsrli r9, r12, 16 /* t1 = v >> 16 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 0 /* *(d + 0) = t1 */ + bslli r11, r12, 16 /* h = v << 16 */ + lwi r12, r8, 8 /* v = *(as + 8) */ + bsrli r9, r12, 16 /* t1 = v >> 16 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 4 /* *(d + 4) = t1 */ + bslli r11, r12, 16 /* h = v << 16 */ + lwi r12, r8, 12 /* v = *(as + 12) */ + bsrli r9, r12, 16 /* t1 = v >> 16 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 8 /* *(d + 8) = t1 */ + bslli r11, r12, 16 /* h = v << 16 */ + lwi r12, r8, 16 /* v = *(as + 16) */ + bsrli r9, r12, 16 /* t1 = v >> 16 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 12 /* *(d + 12) = t1 */ + bslli r11, r12, 16 /* h = v << 16 */ + lwi r12, r8, 20 /* v = *(as + 20) */ + bsrli r9, r12, 16 /* t1 = v >> 16 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 16 /* *(d + 16) = t1 */ + bslli r11, r12, 16 /* h = v << 16 */ + lwi r12, r8, 24 /* v = *(as + 24) */ + bsrli r9, r12, 16 /* t1 = v >> 16 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 20 /* *(d + 20) = t1 */ + bslli r11, r12, 16 /* h = v << 16 */ + lwi r12, r8, 28 /* v = *(as + 28) */ + bsrli r9, r12, 16 /* t1 = v >> 16 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 24 /* *(d + 24) = t1 */ + bslli r11, r12, 16 /* h = v << 16 */ + lwi r12, r8, 32 /* v = *(as + 32) */ + bsrli r9, r12, 16 /* t1 = v >> 16 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 28 /* *(d + 28) = t1 */ + bslli r11, r12, 16 /* h = v << 16 */ + addi r8, r8, 32 /* as = as + 32 */ + addi r4, r4, -32 /* n = n - 32 */ + bneid r4, a_bu2_loop /* while (n) loop */ + addi r5, r5, 32 /* d = d + 32 (IN DELAY SLOT) */ + +a_block_done: + addi r4, r0, 4 /* n = 4 */ + cmpu r4, r4, r7 /* n = c - n (unsigned) */ + blti r4, a_xfer_end /* if n < 0, less than one word to transfer */ + +a_word_xfer: + andi r4, r7, 0xfffffffc /* n = c & ~3 */ + addi r10, r0, 0 /* offset = 0 */ + + andi r9, r6, 3 /* t1 = s & 3 */ + /* if temp != 0, unaligned transfers needed */ + bnei r9, a_word_unaligned + +a_word_aligned: + lw r9, r6, r10 /* t1 = *(s+offset) */ + sw r9, r5, r10 /* *(d+offset) = t1 */ + addi r4, r4,-4 /* n-- */ + bneid r4, a_word_aligned /* loop */ + addi r10, r10, 4 /* offset++ (IN DELAY SLOT) */ + + bri a_word_done + +a_word_unaligned: + andi r8, r6, 0xfffffffc /* as = s & ~3 */ + lwi r11, r8, 0 /* h = *(as + 0) */ + addi r8, r8, 4 /* as = as + 4 */ + + addi r9, r9, -1 + beqi r9, a_word_u1 /* t1 was 1 => 1 byte offset */ + addi r9, r9, -1 + beqi r9, a_word_u2 /* t1 was 2 => 2 byte offset */ + +a_word_u3: + bslli r11, r11, 24 /* h = h << 24 */ +a_wu3_loop: + lw r12, r8, r10 /* v = *(as + offset) */ + bsrli r9, r12, 8 /* t1 = v >> 8 */ + or r9, r11, r9 /* t1 = h | t1 */ + sw r9, r5, r10 /* *(d + offset) = t1 */ + bslli r11, r12, 24 /* h = v << 24 */ + addi r4, r4,-4 /* n = n - 4 */ + bneid r4, a_wu3_loop /* while (n) loop */ + addi r10, r10, 4 /* offset = ofset + 4 (IN DELAY SLOT) */ + + bri a_word_done + +a_word_u1: + bslli r11, r11, 8 /* h = h << 8 */ +a_wu1_loop: + lw r12, r8, r10 /* v = *(as + offset) */ + bsrli r9, r12, 24 /* t1 = v >> 24 */ + or r9, r11, r9 /* t1 = h | t1 */ + sw r9, r5, r10 /* *(d + offset) = t1 */ + bslli r11, r12, 8 /* h = v << 8 */ + addi r4, r4,-4 /* n = n - 4 */ + bneid r4, a_wu1_loop /* while (n) loop */ + addi r10, r10, 4 /* offset = ofset + 4 (IN DELAY SLOT) */ + + bri a_word_done + +a_word_u2: + bslli r11, r11, 16 /* h = h << 16 */ +a_wu2_loop: + lw r12, r8, r10 /* v = *(as + offset) */ + bsrli r9, r12, 16 /* t1 = v >> 16 */ + or r9, r11, r9 /* t1 = h | t1 */ + sw r9, r5, r10 /* *(d + offset) = t1 */ + bslli r11, r12, 16 /* h = v << 16 */ + addi r4, r4,-4 /* n = n - 4 */ + bneid r4, a_wu2_loop /* while (n) loop */ + addi r10, r10, 4 /* offset = ofset + 4 (IN DELAY SLOT) */ + +a_word_done: + add r5, r5, r10 /* d = d + offset */ + add r6, r6, r10 /* s = s + offset */ + rsub r7, r10, r7 /* c = c - offset */ + +a_xfer_end: +a_xfer_end_loop: + beqi r7, a_done /* while (c) */ + lbui r9, r6, 0 /* t1 = *s */ + addi r6, r6, 1 /* s++ */ + sbi r9, r5, 0 /* *d = t1 */ + addi r7, r7, -1 /* c-- */ + brid a_xfer_end_loop /* loop */ + addi r5, r5, 1 /* d++ (IN DELAY SLOT) */ + +a_done: + rtsd r15, 8 + nop + +.size memcpy, . - memcpy +.end memcpy +libc_hidden_def(memcpy) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/microblaze/memmove.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/microblaze/memmove.S new file mode 100644 index 00000000..29233f56 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/microblaze/memmove.S @@ -0,0 +1,348 @@ +/* + * Copyright (C) 2008-2009 Michal Simek + * Copyright (C) 2008-2009 PetaLogix + * Copyright (C) 2008 Jim Law - Iris LP All rights reserved. + * + * This file is subject to the terms and conditions of the GNU General + * Public License. See the file COPYING in the main directory of this + * archive for more details. + * + * Written by Jim Law + * + * intended to replace: + * memcpy in memcpy.c and + * memmove in memmove.c + * ... in arch/microblaze/lib + * + * + * assly_fastcopy.S + * + * Attempt at quicker memcpy and memmove for MicroBlaze + * Input : Operand1 in Reg r5 - destination address + * Operand2 in Reg r6 - source address + * Operand3 in Reg r7 - number of bytes to transfer + * Output: Result in Reg r3 - starting destinaition address + * + * + * Explanation: + * Perform (possibly unaligned) copy of a block of memory + * between mem locations with size of xfer spec'd in bytes + */ + + .globl memmove + .type memmove, @function + .ent memmove + +memmove: + cmpu r4, r5, r6 /* n = s - d */ + bgei r4, HIDDEN_JUMPTARGET(memcpy) + +fast_memcpy_descending: + /* move d to return register as value of function */ + addi r3, r5, 0 + + add r5, r5, r7 /* d = d + c */ + add r6, r6, r7 /* s = s + c */ + + addi r4, r0, 4 /* n = 4 */ + cmpu r4, r4, r7 /* n = c - n (unsigned) */ + blti r4,d_xfer_end /* if n < 0, less than one word to transfer */ + + /* transfer first 0~3 bytes to get aligned dest address */ + andi r4, r5, 3 /* n = d & 3 */ + /* if zero, destination already aligned */ + beqi r4,d_dalign_done + rsub r7, r4, r7 /* c = c - n adjust c */ + +d_xfer_first_loop: + /* if no bytes left to transfer, transfer the bulk */ + beqi r4,d_dalign_done + addi r6, r6, -1 /* s-- */ + addi r5, r5, -1 /* d-- */ + lbui r11, r6, 0 /* h = *s */ + sbi r11, r5, 0 /* *d = h */ + brid d_xfer_first_loop /* loop */ + addi r4, r4, -1 /* n-- (IN DELAY SLOT) */ + +d_dalign_done: + addi r4, r0, 32 /* n = 32 */ + cmpu r4, r4, r7 /* n = c - n (unsigned) */ + /* if n < 0, less than one block to transfer */ + blti r4, d_block_done + +d_block_xfer: + andi r4, r7, 0xffffffe0 /* n = c & ~31 */ + rsub r7, r4, r7 /* c = c - n */ + + andi r9, r6, 3 /* t1 = s & 3 */ + /* if temp != 0, unaligned transfers needed */ + bnei r9, d_block_unaligned + +d_block_aligned: + addi r6, r6, -32 /* s = s - 32 */ + addi r5, r5, -32 /* d = d - 32 */ + lwi r9, r6, 28 /* t1 = *(s + 28) */ + lwi r10, r6, 24 /* t2 = *(s + 24) */ + lwi r11, r6, 20 /* t3 = *(s + 20) */ + lwi r12, r6, 16 /* t4 = *(s + 16) */ + swi r9, r5, 28 /* *(d + 28) = t1 */ + swi r10, r5, 24 /* *(d + 24) = t2 */ + swi r11, r5, 20 /* *(d + 20) = t3 */ + swi r12, r5, 16 /* *(d + 16) = t4 */ + lwi r9, r6, 12 /* t1 = *(s + 12) */ + lwi r10, r6, 8 /* t2 = *(s + 8) */ + lwi r11, r6, 4 /* t3 = *(s + 4) */ + lwi r12, r6, 0 /* t4 = *(s + 0) */ + swi r9, r5, 12 /* *(d + 12) = t1 */ + swi r10, r5, 8 /* *(d + 8) = t2 */ + swi r11, r5, 4 /* *(d + 4) = t3 */ + addi r4, r4, -32 /* n = n - 32 */ + bneid r4, d_block_aligned /* while (n) loop */ + swi r12, r5, 0 /* *(d + 0) = t4 (IN DELAY SLOT) */ + bri d_block_done + +d_block_unaligned: + andi r8, r6, 0xfffffffc /* as = s & ~3 */ + rsub r6, r4, r6 /* s = s - n */ + lwi r11, r8, 0 /* h = *(as + 0) */ + + addi r9, r9, -1 + beqi r9,d_block_u1 /* t1 was 1 => 1 byte offset */ + addi r9, r9, -1 + beqi r9,d_block_u2 /* t1 was 2 => 2 byte offset */ + +d_block_u3: + bsrli r11, r11, 8 /* h = h >> 8 */ +d_bu3_loop: + addi r8, r8, -32 /* as = as - 32 */ + addi r5, r5, -32 /* d = d - 32 */ + lwi r12, r8, 28 /* v = *(as + 28) */ + bslli r9, r12, 24 /* t1 = v << 24 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 28 /* *(d + 28) = t1 */ + bsrli r11, r12, 8 /* h = v >> 8 */ + lwi r12, r8, 24 /* v = *(as + 24) */ + bslli r9, r12, 24 /* t1 = v << 24 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 24 /* *(d + 24) = t1 */ + bsrli r11, r12, 8 /* h = v >> 8 */ + lwi r12, r8, 20 /* v = *(as + 20) */ + bslli r9, r12, 24 /* t1 = v << 24 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 20 /* *(d + 20) = t1 */ + bsrli r11, r12, 8 /* h = v >> 8 */ + lwi r12, r8, 16 /* v = *(as + 16) */ + bslli r9, r12, 24 /* t1 = v << 24 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 16 /* *(d + 16) = t1 */ + bsrli r11, r12, 8 /* h = v >> 8 */ + lwi r12, r8, 12 /* v = *(as + 12) */ + bslli r9, r12, 24 /* t1 = v << 24 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 12 /* *(d + 112) = t1 */ + bsrli r11, r12, 8 /* h = v >> 8 */ + lwi r12, r8, 8 /* v = *(as + 8) */ + bslli r9, r12, 24 /* t1 = v << 24 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 8 /* *(d + 8) = t1 */ + bsrli r11, r12, 8 /* h = v >> 8 */ + lwi r12, r8, 4 /* v = *(as + 4) */ + bslli r9, r12, 24 /* t1 = v << 24 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 4 /* *(d + 4) = t1 */ + bsrli r11, r12, 8 /* h = v >> 8 */ + lwi r12, r8, 0 /* v = *(as + 0) */ + bslli r9, r12, 24 /* t1 = v << 24 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 0 /* *(d + 0) = t1 */ + addi r4, r4, -32 /* n = n - 32 */ + bneid r4, d_bu3_loop /* while (n) loop */ + bsrli r11, r12, 8 /* h = v >> 8 (IN DELAY SLOT) */ + bri d_block_done + +d_block_u1: + bsrli r11, r11, 24 /* h = h >> 24 */ +d_bu1_loop: + addi r8, r8, -32 /* as = as - 32 */ + addi r5, r5, -32 /* d = d - 32 */ + lwi r12, r8, 28 /* v = *(as + 28) */ + bslli r9, r12, 8 /* t1 = v << 8 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 28 /* *(d + 28) = t1 */ + bsrli r11, r12, 24 /* h = v >> 24 */ + lwi r12, r8, 24 /* v = *(as + 24) */ + bslli r9, r12, 8 /* t1 = v << 8 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 24 /* *(d + 24) = t1 */ + bsrli r11, r12, 24 /* h = v >> 24 */ + lwi r12, r8, 20 /* v = *(as + 20) */ + bslli r9, r12, 8 /* t1 = v << 8 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 20 /* *(d + 20) = t1 */ + bsrli r11, r12, 24 /* h = v >> 24 */ + lwi r12, r8, 16 /* v = *(as + 16) */ + bslli r9, r12, 8 /* t1 = v << 8 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 16 /* *(d + 16) = t1 */ + bsrli r11, r12, 24 /* h = v >> 24 */ + lwi r12, r8, 12 /* v = *(as + 12) */ + bslli r9, r12, 8 /* t1 = v << 8 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 12 /* *(d + 112) = t1 */ + bsrli r11, r12, 24 /* h = v >> 24 */ + lwi r12, r8, 8 /* v = *(as + 8) */ + bslli r9, r12, 8 /* t1 = v << 8 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 8 /* *(d + 8) = t1 */ + bsrli r11, r12, 24 /* h = v >> 24 */ + lwi r12, r8, 4 /* v = *(as + 4) */ + bslli r9, r12, 8 /* t1 = v << 8 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 4 /* *(d + 4) = t1 */ + bsrli r11, r12, 24 /* h = v >> 24 */ + lwi r12, r8, 0 /* v = *(as + 0) */ + bslli r9, r12, 8 /* t1 = v << 8 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 0 /* *(d + 0) = t1 */ + addi r4, r4, -32 /* n = n - 32 */ + bneid r4, d_bu1_loop /* while (n) loop */ + bsrli r11, r12, 24 /* h = v >> 24 (IN DELAY SLOT) */ + bri d_block_done + +d_block_u2: + bsrli r11, r11, 16 /* h = h >> 16 */ +d_bu2_loop: + addi r8, r8, -32 /* as = as - 32 */ + addi r5, r5, -32 /* d = d - 32 */ + lwi r12, r8, 28 /* v = *(as + 28) */ + bslli r9, r12, 16 /* t1 = v << 16 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 28 /* *(d + 28) = t1 */ + bsrli r11, r12, 16 /* h = v >> 16 */ + lwi r12, r8, 24 /* v = *(as + 24) */ + bslli r9, r12, 16 /* t1 = v << 16 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 24 /* *(d + 24) = t1 */ + bsrli r11, r12, 16 /* h = v >> 16 */ + lwi r12, r8, 20 /* v = *(as + 20) */ + bslli r9, r12, 16 /* t1 = v << 16 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 20 /* *(d + 20) = t1 */ + bsrli r11, r12, 16 /* h = v >> 16 */ + lwi r12, r8, 16 /* v = *(as + 16) */ + bslli r9, r12, 16 /* t1 = v << 16 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 16 /* *(d + 16) = t1 */ + bsrli r11, r12, 16 /* h = v >> 16 */ + lwi r12, r8, 12 /* v = *(as + 12) */ + bslli r9, r12, 16 /* t1 = v << 16 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 12 /* *(d + 112) = t1 */ + bsrli r11, r12, 16 /* h = v >> 16 */ + lwi r12, r8, 8 /* v = *(as + 8) */ + bslli r9, r12, 16 /* t1 = v << 16 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 8 /* *(d + 8) = t1 */ + bsrli r11, r12, 16 /* h = v >> 16 */ + lwi r12, r8, 4 /* v = *(as + 4) */ + bslli r9, r12, 16 /* t1 = v << 16 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 4 /* *(d + 4) = t1 */ + bsrli r11, r12, 16 /* h = v >> 16 */ + lwi r12, r8, 0 /* v = *(as + 0) */ + bslli r9, r12, 16 /* t1 = v << 16 */ + or r9, r11, r9 /* t1 = h | t1 */ + swi r9, r5, 0 /* *(d + 0) = t1 */ + addi r4, r4, -32 /* n = n - 32 */ + bneid r4, d_bu2_loop /* while (n) loop */ + bsrli r11, r12, 16 /* h = v >> 16 (IN DELAY SLOT) */ + +d_block_done: + addi r4, r0, 4 /* n = 4 */ + cmpu r4, r4, r7 /* n = c - n (unsigned) */ + blti r4,d_xfer_end /* if n < 0, less than one word to transfer */ + +d_word_xfer: + andi r4, r7, 0xfffffffc /* n = c & ~3 */ + rsub r5, r4, r5 /* d = d - n */ + rsub r6, r4, r6 /* s = s - n */ + rsub r7, r4, r7 /* c = c - n */ + + andi r9, r6, 3 /* t1 = s & 3 */ + /* if temp != 0, unaligned transfers needed */ + bnei r9, d_word_unaligned + +d_word_aligned: + addi r4, r4,-4 /* n-- */ + lw r9, r6, r4 /* t1 = *(s+n) */ + bneid r4, d_word_aligned /* loop */ + sw r9, r5, r4 /* *(d+n) = t1 (IN DELAY SLOT) */ + + bri d_word_done + +d_word_unaligned: + andi r8, r6, 0xfffffffc /* as = s & ~3 */ + lw r11, r8, r4 /* h = *(as + n) */ + + addi r9, r9, -1 + beqi r9,d_word_u1 /* t1 was 1 => 1 byte offset */ + addi r9, r9, -1 + beqi r9,d_word_u2 /* t1 was 2 => 2 byte offset */ + +d_word_u3: + bsrli r11, r11, 8 /* h = h >> 8 */ +d_wu3_loop: + addi r4, r4,-4 /* n = n - 4 */ + lw r12, r8, r4 /* v = *(as + n) */ + bslli r9, r12, 24 /* t1 = v << 24 */ + or r9, r11, r9 /* t1 = h | t1 */ + sw r9, r5, r4 /* *(d + n) = t1 */ + bneid r4, d_wu3_loop /* while (n) loop */ + bsrli r11, r12, 8 /* h = v >> 8 (IN DELAY SLOT) */ + + bri d_word_done + +d_word_u1: + bsrli r11, r11, 24 /* h = h >> 24 */ +d_wu1_loop: + addi r4, r4,-4 /* n = n - 4 */ + lw r12, r8, r4 /* v = *(as + n) */ + bslli r9, r12, 8 /* t1 = v << 8 */ + or r9, r11, r9 /* t1 = h | t1 */ + sw r9, r5, r4 /* *(d + n) = t1 */ + bneid r4, d_wu1_loop /* while (n) loop */ + bsrli r11, r12, 24 /* h = v >> 24 (IN DELAY SLOT) */ + + bri d_word_done + +d_word_u2: + bsrli r11, r11, 16 /* h = h >> 16 */ +d_wu2_loop: + addi r4, r4,-4 /* n = n - 4 */ + lw r12, r8, r4 /* v = *(as + n) */ + bslli r9, r12, 16 /* t1 = v << 16 */ + or r9, r11, r9 /* t1 = h | t1 */ + sw r9, r5, r4 /* *(d + n) = t1 */ + bneid r4, d_wu2_loop /* while (n) loop */ + bsrli r11, r12, 16 /* h = v >> 16 (IN DELAY SLOT) */ + +d_word_done: + +d_xfer_end: +d_xfer_end_loop: + beqi r7, a_done /* while (c) */ + addi r6, r6, -1 /* s-- */ + lbui r9, r6, 0 /* t1 = *s */ + addi r5, r5, -1 /* d-- */ + sbi r9, r5, 0 /* *d = t1 */ + brid d_xfer_end_loop /* loop */ + addi r7, r7, -1 /* c-- (IN DELAY SLOT) */ + +a_done: +d_done: + rtsd r15, 8 + nop + +.size memmove, . - memmove +.end memmove +libc_hidden_def(memmove) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/mips/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/mips/Makefile new file mode 100644 index 00000000..0a95346f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/mips/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir:=../../../ +top_builddir:=../../../ +all: objs +include $(top_builddir)Rules.mak +include ../Makefile.in +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/mips/memcpy.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/mips/memcpy.S new file mode 100644 index 00000000..9b05ee6d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/mips/memcpy.S @@ -0,0 +1,257 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Hartvig Ekner , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +/*#include */ +#include +#include "sysdep.h" + +/* void *memcpy(void *s1, const void *s2, size_t n); */ + +#ifdef __mips64 + +#include + +#if __BYTE_ORDER == __BIG_ENDIAN +# define LDHI ldl /* high part is left in big-endian */ +# define SDHI sdl /* high part is left in big-endian */ +# define LDLO ldr /* low part is right in big-endian */ +# define SDLO sdr /* low part is right in big-endian */ +#else +# define LDHI ldr /* high part is right in little-endian */ +# define SDHI sdr /* high part is right in little-endian */ +# define LDLO ldl /* low part is left in little-endian */ +# define SDLO sdl /* low part is left in little-endian */ +#endif + +ENTRY (memcpy) + .set noreorder + + slti t0, a2, 16 # Less than 16? + bne t0, zero, L(last16) + move v0, a0 # Setup exit value before too late + + xor t0, a1, a0 # Find a0/a1 displacement + andi t0, 0x7 + bne t0, zero, L(shift) # Go handle the unaligned case + PTR_SUBU t1, zero, a1 + andi t1, 0x7 # a0/a1 are aligned, but are we + beq t1, zero, L(chk8w) # starting in the middle of a word? + PTR_SUBU a2, t1 + LDHI t0, 0(a1) # Yes we are... take care of that + PTR_ADDU a1, t1 + SDHI t0, 0(a0) + PTR_ADDU a0, t1 + +L(chk8w): + andi t0, a2, 0x3f # 64 or more bytes left? + beq t0, a2, L(chk1w) + PTR_SUBU a3, a2, t0 # Yes + PTR_ADDU a3, a1 # a3 = end address of loop + move a2, t0 # a2 = what will be left after loop +L(lop8w): + ld t0, 0(a1) # Loop taking 8 words at a time + ld t1, 8(a1) + ld t2, 16(a1) + ld t3, 24(a1) + ld ta0, 32(a1) + ld ta1, 40(a1) + ld ta2, 48(a1) + ld ta3, 56(a1) + PTR_ADDIU a0, 64 + PTR_ADDIU a1, 64 + sd t0, -64(a0) + sd t1, -56(a0) + sd t2, -48(a0) + sd t3, -40(a0) + sd ta0, -32(a0) + sd ta1, -24(a0) + sd ta2, -16(a0) + bne a1, a3, L(lop8w) + sd ta3, -8(a0) + +L(chk1w): + andi t0, a2, 0x7 # 8 or more bytes left? + beq t0, a2, L(last16) + PTR_SUBU a3, a2, t0 # Yes, handle them one dword at a time + PTR_ADDU a3, a1 # a3 again end address + move a2, t0 +L(lop1w): + ld t0, 0(a1) + PTR_ADDIU a0, 8 + PTR_ADDIU a1, 8 + bne a1, a3, L(lop1w) + sd t0, -8(a0) + +L(last16): + blez a2, L(lst16e) # Handle last 16 bytes, one at a time + PTR_ADDU a3, a2, a1 +L(lst16l): + lb t0, 0(a1) + PTR_ADDIU a0, 1 + PTR_ADDIU a1, 1 + bne a1, a3, L(lst16l) + sb t0, -1(a0) +L(lst16e): + jr ra # Bye, bye + nop + +L(shift): + PTR_SUBU a3, zero, a0 # Src and Dest unaligned + andi a3, 0x7 # (unoptimized case...) + beq a3, zero, L(shft1) + PTR_SUBU a2, a3 # a2 = bytes left + LDHI t0, 0(a1) # Take care of first odd part + LDLO t0, 7(a1) + PTR_ADDU a1, a3 + SDHI t0, 0(a0) + PTR_ADDU a0, a3 +L(shft1): + andi t0, a2, 0x7 + PTR_SUBU a3, a2, t0 + PTR_ADDU a3, a1 +L(shfth): + LDHI t1, 0(a1) # Limp through, dword by dword + LDLO t1, 7(a1) + PTR_ADDIU a0, 8 + PTR_ADDIU a1, 8 + bne a1, a3, L(shfth) + sd t1, -8(a0) + b L(last16) # Handle anything which may be left + move a2, t0 + + .set reorder +END (memcpy) + +#else /* !__mips64 */ + +#if __BYTE_ORDER == __BIG_ENDIAN +# define LWHI lwl /* high part is left in big-endian */ +# define SWHI swl /* high part is left in big-endian */ +# define LWLO lwr /* low part is right in big-endian */ +# define SWLO swr /* low part is right in big-endian */ +#else +# define LWHI lwr /* high part is right in little-endian */ +# define SWHI swr /* high part is right in little-endian */ +# define LWLO lwl /* low part is left in little-endian */ +# define SWLO swl /* low part is left in little-endian */ +#endif + +ENTRY (memcpy) + .set noreorder + + slti t0, a2, 8 # Less than 8? + bne t0, zero, L(last8) + move v0, a0 # Setup exit value before too late + + xor t0, a1, a0 # Find a0/a1 displacement + andi t0, 0x3 + bne t0, zero, L(shift) # Go handle the unaligned case + subu t1, zero, a1 + andi t1, 0x3 # a0/a1 are aligned, but are we + beq t1, zero, L(chk8w) # starting in the middle of a word? + subu a2, t1 + LWHI t0, 0(a1) # Yes we are... take care of that + addu a1, t1 + SWHI t0, 0(a0) + addu a0, t1 + +L(chk8w): + andi t0, a2, 0x1f # 32 or more bytes left? + beq t0, a2, L(chk1w) + subu a3, a2, t0 # Yes + addu a3, a1 # a3 = end address of loop + move a2, t0 # a2 = what will be left after loop +L(lop8w): + lw t0, 0(a1) # Loop taking 8 words at a time + lw t1, 4(a1) + lw t2, 8(a1) + lw t3, 12(a1) + lw t4, 16(a1) + lw t5, 20(a1) + lw t6, 24(a1) + lw t7, 28(a1) + addiu a0, 32 + addiu a1, 32 + sw t0, -32(a0) + sw t1, -28(a0) + sw t2, -24(a0) + sw t3, -20(a0) + sw t4, -16(a0) + sw t5, -12(a0) + sw t6, -8(a0) + bne a1, a3, L(lop8w) + sw t7, -4(a0) + +L(chk1w): + andi t0, a2, 0x3 # 4 or more bytes left? + beq t0, a2, L(last8) + subu a3, a2, t0 # Yes, handle them one word at a time + addu a3, a1 # a3 again end address + move a2, t0 +L(lop1w): + lw t0, 0(a1) + addiu a0, 4 + addiu a1, 4 + bne a1, a3, L(lop1w) + sw t0, -4(a0) + +L(last8): + blez a2, L(lst8e) # Handle last 8 bytes, one at a time + addu a3, a2, a1 +L(lst8l): + lb t0, 0(a1) + addiu a0, 1 + addiu a1, 1 + bne a1, a3, L(lst8l) + sb t0, -1(a0) +L(lst8e): + jr ra # Bye, bye + nop + +L(shift): + subu a3, zero, a0 # Src and Dest unaligned + andi a3, 0x3 # (unoptimized case...) + beq a3, zero, L(shft1) + subu a2, a3 # a2 = bytes left + LWHI t0, 0(a1) # Take care of first odd part + LWLO t0, 3(a1) + addu a1, a3 + SWHI t0, 0(a0) + addu a0, a3 +L(shft1): + andi t0, a2, 0x3 + subu a3, a2, t0 + addu a3, a1 +L(shfth): + LWHI t1, 0(a1) # Limp through, word by word + LWLO t1, 3(a1) + addiu a0, 4 + addiu a1, 4 + bne a1, a3, L(shfth) + sw t1, -4(a0) + b L(last8) # Handle anything which may be left + move a2, t0 + + .set reorder +END (memcpy) + +#endif /* !__mips64 */ + +libc_hidden_def(memcpy) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/mips/memset.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/mips/memset.S new file mode 100644 index 00000000..ff0554ff --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/mips/memset.S @@ -0,0 +1,159 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Hartvig Ekner , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +/*#include */ +#include +#include "sysdep.h" + +/* void *memset(void *s, int c, size_t n). */ + +#ifdef __mips64 + +#include + +#if __BYTE_ORDER == __BIG_ENDIAN +# define SDHI sdl /* high part is left in big-endian */ +#else +# define SDHI sdr /* high part is right in little-endian */ +#endif + +ENTRY (memset) + .set noreorder + + slti ta1, a2, 16 # Less than 16? + bne ta1, zero, L(last16) + move v0, a0 # Setup exit value before too late + + beq a1, zero, L(ueven) # If zero pattern, no need to extend + andi a1, 0xff # Avoid problems with bogus arguments + dsll ta0, a1, 8 + or a1, ta0 + dsll ta0, a1, 16 + or a1, ta0 # a1 is now pattern in full word + dsll ta0, a1, 32 + or a1, ta0 # a1 is now pattern in double word + +L(ueven): + PTR_SUBU ta0, zero, a0 # Unaligned address? + andi ta0, 0x7 + beq ta0, zero, L(chkw) + PTR_SUBU a2, ta0 + SDHI a1, 0(a0) # Yes, handle first unaligned part + PTR_ADDU a0, ta0 # Now both a0 and a2 are updated + +L(chkw): + andi ta0, a2, 0xf # Enough left for one loop iteration? + beq ta0, a2, L(chkl) + PTR_SUBU a3, a2, ta0 + PTR_ADDU a3, a0 # a3 is last loop address +1 + move a2, ta0 # a2 is now # of bytes left after loop +L(loopw): + PTR_ADDIU a0, 16 # Handle 2 dwords pr. iteration + sd a1, -16(a0) + bne a0, a3, L(loopw) + sd a1, -8(a0) + +L(chkl): + andi ta0, a2, 0x8 # Check if there is at least a double + beq ta0, zero, L(last16) # word remaining after the loop + PTR_SUBU a2, ta0 + sd a1, 0(a0) # Yes... + PTR_ADDIU a0, 8 + +L(last16): + blez a2, L(exit) # Handle last 16 bytes (if cnt>0) + PTR_ADDU a3, a2, a0 # a3 is last address +1 +L(lst16l): + PTR_ADDIU a0, 1 + bne a0, a3, L(lst16l) + sb a1, -1(a0) +L(exit): + j ra # Bye, bye + nop + + .set reorder +END (memset) + +#else /* !__mips64 */ + +#if __BYTE_ORDER == __BIG_ENDIAN +# define SWHI swl /* high part is left in big-endian */ +#else +# define SWHI swr /* high part is right in little-endian */ +#endif + +ENTRY (memset) + .set noreorder + + slti t1, a2, 8 # Less than 8? + bne t1, zero, L(last8) + move v0, a0 # Setup exit value before too late + + beq a1, zero, L(ueven) # If zero pattern, no need to extend + andi a1, 0xff # Avoid problems with bogus arguments + sll t0, a1, 8 + or a1, t0 + sll t0, a1, 16 + or a1, t0 # a1 is now pattern in full word + +L(ueven): + subu t0, zero, a0 # Unaligned address? + andi t0, 0x3 + beq t0, zero, L(chkw) + subu a2, t0 + SWHI a1, 0(a0) # Yes, handle first unaligned part + addu a0, t0 # Now both a0 and a2 are updated + +L(chkw): + andi t0, a2, 0x7 # Enough left for one loop iteration? + beq t0, a2, L(chkl) + subu a3, a2, t0 + addu a3, a0 # a3 is last loop address +1 + move a2, t0 # a2 is now # of bytes left after loop +L(loopw): + addiu a0, 8 # Handle 2 words pr. iteration + sw a1, -8(a0) + bne a0, a3, L(loopw) + sw a1, -4(a0) + +L(chkl): + andi t0, a2, 0x4 # Check if there is at least a full + beq t0, zero, L(last8) # word remaining after the loop + subu a2, t0 + sw a1, 0(a0) # Yes... + addiu a0, 4 + +L(last8): + blez a2, L(exit) # Handle last 8 bytes (if cnt>0) + addu a3, a2, a0 # a3 is last address +1 +L(lst8l): + addiu a0, 1 + bne a0, a3, L(lst8l) + sb a1, -1(a0) +L(exit): + j ra # Bye, bye + nop + + .set reorder +END (memset) + +#endif /* !__mips64 */ + +libc_hidden_def(memset) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/mips/sysdep.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/mips/sysdep.h new file mode 100644 index 00000000..5dad8342 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/mips/sysdep.h @@ -0,0 +1,45 @@ +/* Adapted from glibc's sysdeps/unix/mips/sysdep.h */ + +/* Copyright (C) 1992, 1995, 1997, 1999, 2000, 2002, 2003 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Brendan Kehoe (brendan@zen.org). + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifdef __ASSEMBLER__ + +#include +#include + +#define ENTRY(name) \ + .globl name; \ + .align 2; \ + .ent name,0; \ + name/* use a comment rather than ## to workaround bug in gcc-3.4.x */: + +#undef END +#define END(function) \ + .end function; \ + .size function,.-function + +#if _MIPS_SIM == _MIPS_SIM_ABI32 || _MIPS_SIM == _MIPS_SIM_ABIO64 +# define L(label) $L ## label +#else +# define L(label) .L ## label +#endif + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/powerpc/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/powerpc/Makefile new file mode 100644 index 00000000..0a95346f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/powerpc/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir:=../../../ +top_builddir:=../../../ +all: objs +include $(top_builddir)Rules.mak +include ../Makefile.in +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/powerpc/memcpy.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/powerpc/memcpy.c new file mode 100644 index 00000000..22794ec3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/powerpc/memcpy.c @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2004 Joakim Tjernlund + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* These are carefully optimized mem*() functions for PPC written in C. + * Don't muck around with these function without checking the generated + * assembler code. + * It is possible to optimize these significantly more by using specific + * data cache instructions(mainly dcbz). However that requires knownledge + * about the CPU's cache line size. + * + * BUG ALERT! + * The cache instructions on MPC8xx CPU's are buggy(they don't update + * the DAR register when causing a DTLB Miss/Error) and cannot be + * used on 8xx CPU's without a kernel patch to work around this + * problem. + */ + +#include + +/* PPC can do pre increment and load/store, but not post increment and + load/store. Therefore use *++ptr instead of *ptr++. */ +void *memcpy(void *to, const void *from, size_t len) +{ + unsigned long rem, chunks, tmp1, tmp2; + unsigned char *tmp_to; + unsigned char *tmp_from = (unsigned char *)from; + + chunks = len / 8; + tmp_from -= 4; + tmp_to = to - 4; + if (!chunks) + goto lessthan8; + rem = (unsigned long )tmp_to % 4; + if (rem) + goto align; + copy_chunks: + do { + /* make gcc to load all data, then store it */ + tmp1 = *(unsigned long *)(tmp_from+4); + tmp_from += 8; + tmp2 = *(unsigned long *)tmp_from; + *(unsigned long *)(tmp_to+4) = tmp1; + tmp_to += 8; + *(unsigned long *)tmp_to = tmp2; + } while (--chunks); + lessthan8: + len = len % 8; + if (len >= 4) { + tmp_from += 4; + tmp_to += 4; + *(unsigned long *)(tmp_to) = *(unsigned long *)(tmp_from); + len -= 4; + } + if (!len) + return to; + tmp_from += 3; + tmp_to += 3; + do { + *++tmp_to = *++tmp_from; + } while (--len); + + return to; + align: + /* ???: Do we really need to generate the carry flag here? If not, then: + rem -= 4; */ + rem = 4 - rem; + len -= rem; + do { + *(tmp_to+4) = *(tmp_from+4); + ++tmp_from; + ++tmp_to; + } while (--rem); + chunks = len / 8; + if (chunks) + goto copy_chunks; + goto lessthan8; +} +libc_hidden_def(memcpy) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/powerpc/memmove.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/powerpc/memmove.c new file mode 100644 index 00000000..6bd79915 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/powerpc/memmove.c @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2004 Joakim Tjernlund + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* These are carefully optimized mem*() functions for PPC written in C. + * Don't muck around with these function without checking the generated + * assembler code. + * It is possible to optimize these significantly more by using specific + * data cache instructions(mainly dcbz). However that requires knownledge + * about the CPU's cache line size. + * + * BUG ALERT! + * The cache instructions on MPC8xx CPU's are buggy(they don't update + * the DAR register when causing a DTLB Miss/Error) and cannot be + * used on 8xx CPU's without a kernel patch to work around this + * problem. + */ + +#include + + +void *memmove(void *to, const void *from, size_t n) +{ + unsigned long rem, chunks, tmp1, tmp2; + unsigned char *tmp_to; + unsigned char *tmp_from = (unsigned char *)from; + + if (tmp_from >= (unsigned char *)to) + return memcpy(to, from, n); + chunks = n / 8; + tmp_from += n; + tmp_to = to + n; + if (!chunks) + goto lessthan8; + rem = (unsigned long )tmp_to % 4; + if (rem) + goto align; + copy_chunks: + do { + /* make gcc to load all data, then store it */ + tmp1 = *(unsigned long *)(tmp_from-4); + tmp_from -= 8; + tmp2 = *(unsigned long *)tmp_from; + *(unsigned long *)(tmp_to-4) = tmp1; + tmp_to -= 8; + *(unsigned long *)tmp_to = tmp2; + } while (--chunks); + lessthan8: + n = n % 8; + if (n >= 4) { + *(unsigned long *)(tmp_to-4) = *(unsigned long *)(tmp_from-4); + tmp_from -= 4; + tmp_to -= 4; + n = n-4; + } + if (!n ) return to; + do { + *--tmp_to = *--tmp_from; + } while (--n); + + return to; + align: + rem = 4 - rem; + n = n - rem; + do { + *--tmp_to = *--tmp_from; + } while (--rem); + chunks = n / 8; + if (chunks) + goto copy_chunks; + goto lessthan8; +} +libc_hidden_def(memmove) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/powerpc/memset.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/powerpc/memset.c new file mode 100644 index 00000000..a900b92c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/powerpc/memset.c @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2004 Joakim Tjernlund + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* These are carefully optimized mem*() functions for PPC written in C. + * Don't muck around with these function without checking the generated + * assembler code. + * It is possible to optimize these significantly more by using specific + * data cache instructions(mainly dcbz). However that requires knownledge + * about the CPU's cache line size. + * + * BUG ALERT! + * The cache instructions on MPC8xx CPU's are buggy(they don't update + * the DAR register when causing a DTLB Miss/Error) and cannot be + * used on 8xx CPU's without a kernel patch to work around this + * problem. + */ + +#include + + +static __inline__ int expand_byte_word(int c){ + /* this does: + c = c << 8 | c; + c = c << 16 | c ; + */ + __asm__("rlwimi %0,%0,8,16,23\n" + "\trlwimi %0,%0,16,0,15\n" + : "=r" (c) : "0" (c)); + return c; +} + +void *memset(void *to, int c, size_t n) +{ + unsigned long rem, chunks; + unsigned char *tmp_to; + + chunks = n / 8; + tmp_to = to - 4; + c = expand_byte_word(c); + if (!chunks) + goto lessthan8; + rem = (unsigned long )tmp_to % 4; + if (rem) + goto align; + copy_chunks: + do { + *(unsigned long *)(tmp_to+4) = c; + tmp_to += 4; + *(unsigned long *)(tmp_to+4) = c; + tmp_to += 4; + } while (--chunks); + lessthan8: + n = n % 8; + if (n >= 4) { + *(unsigned long *)(tmp_to+4) = c; + tmp_to += 4; + n = n-4; + } + if (!n ) return to; + tmp_to += 3; + do { + *++tmp_to = c; + } while (--n); + + return to; + align: + rem = 4 - rem; + n = n-rem; + do { + *(tmp_to+4) = c; + ++tmp_to; + } while (--rem); + chunks = n / 8; + if (chunks) + goto copy_chunks; + goto lessthan8; +} +libc_hidden_def(memset) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/psignal.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/psignal.c new file mode 100644 index 00000000..3e1f68b9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/psignal.c @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include + + +/* TODO: make this threadsafe with a reentrant version of strsignal? */ + +void psignal(int signum, register const char *message) +{ + /* If the program is calling psignal, it's a safe bet that printf and + * friends are used as well. It is also possible that the calling + * program could buffer stderr, or reassign it. */ + + register const char *sep; + + sep = ": "; + if (!(message && *message)) { /* Caller did not supply a prefix message */ + message = (sep += 2); /* or passed an empty string. */ + } + + fprintf(stderr, "%s%s%s\n", message, sep, strsignal(signum)); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/rawmemchr.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/rawmemchr.c new file mode 100644 index 00000000..f0cb7ee4 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/rawmemchr.c @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include "_string.h" + +#ifdef __USE_GNU +void *rawmemchr(const void *s, int c) +{ + register const unsigned char *r = s; + + while (*r != ((unsigned char)c)) ++r; + + return (void *) r; /* silence the warning */ +} +libc_hidden_def(rawmemchr) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sh/memchr.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sh/memchr.S new file mode 100644 index 00000000..6b7142f6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sh/memchr.S @@ -0,0 +1,30 @@ +/* $Id: memchr.S,v 1.1 2000/04/14 16:49:01 mjd Exp $ + * + * "memchr" implementation of SuperH + * + * Copyright (C) 1999 Niibe Yutaka + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* + * void *memchr(const void *s, int c, size_t n); + */ + +#include + +ENTRY(memchr) + tst r6,r6 + bt/s 2f + exts.b r5,r5 +1: mov.b @r4,r1 + cmp/eq r1,r5 + bt/s 3f + dt r6 + bf/s 1b + add #1,r4 +2: mov #0,r4 +3: rts + mov r4,r0 +END(memchr) +libc_hidden_def (memchr) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sh/sh4/memcpy.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sh/sh4/memcpy.S new file mode 100644 index 00000000..6a229a06 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sh/sh4/memcpy.S @@ -0,0 +1,1006 @@ +/* + * "memcpy" implementation of SuperH + * + * Copyright (C) 1999 Niibe Yutaka + * Copyright (c) 2002 STMicroelectronics Ltd + * Modified from memcpy.S and micro-optimised for SH4 + * Stuart Menefy (stuart.menefy@st.com) + * + * Copyright (c) 2009 STMicroelectronics Ltd + * Optimised using prefetching and 64bit data transfer via FPU + * Author: Giuseppe Cavallaro + */ + +/* + * void *memcpy(void *dst, const void *src, size_t n); + * + * It is assumed that there is no overlap between src and dst. + * If there is an overlap, then the results are undefined. + */ + +#include +#include + +#if defined (__LITTLE_ENDIAN__) && defined (__SH_FPU_ANY__) +#define MEMCPY_USES_FPU +/* Use paired single precision load or store mode for 64-bit tranfering. + * FPSCR.SZ=1,FPSCR.SZ=0 is well defined on both SH4-200 and SH4-300. + * Currenlty it has been only implemented and tested for little endian mode. */ +.macro FPU_SET_PAIRED_PREC + sts fpscr, r7 + mov #0x10, r0 ! PR=0 SZ=1 + shll16 r0 + lds r0, fpscr +.endm +.macro RESTORE_FPSCR + lds r7, fpscr +.endm +.macro DALLOC + ! Cache allocate + store on dst-32. + add #-32, r1 + movca.l r0, @r1 + add #32, r1 +.endm + +#endif + + ! + ! GHIJ KLMN OPQR --> ...G HIJK LMNO PQR. + ! + + ! Size is 16 or greater, and may have trailing bytes + + .balign 32 +.Lcase1: + ! Read a long word and write a long word at once + ! At the start of each iteration, r7 contains last long load + add #-1,r5 ! 79 EX + mov r4,r2 ! 5 MT (0 cycles latency) + + mov.l @(r0,r5),r7 ! 21 LS (2 cycles latency) + add #-4,r5 ! 50 EX + + add #7,r2 ! 79 EX + ! +#ifdef __LITTLE_ENDIAN__ + ! 6 cycles, 4 bytes per iteration +3: mov.l @(r0,r5),r1 ! 21 LS (latency=2) ! NMLK + mov r7, r3 ! 5 MT (latency=0) ! RQPO + + cmp/hi r2,r0 ! 57 MT + shll16 r3 ! 103 EX + + mov r1,r6 ! 5 MT (latency=0) + shll8 r3 ! 102 EX ! Oxxx + + shlr8 r6 ! 106 EX ! xNML + mov r1, r7 ! 5 MT (latency=0) + + or r6,r3 ! 82 EX ! ONML + bt/s 3b ! 109 BR + + mov.l r3,@-r0 ! 30 LS +#else +3: mov.l @(r0,r5),r1 ! 21 LS (latency=2) ! KLMN + mov r7,r3 ! 5 MT (latency=0) ! OPQR + + cmp/hi r2,r0 ! 57 MT + shlr16 r3 ! 107 EX + + shlr8 r3 ! 106 EX ! xxxO + mov r1,r6 ! 5 MT (latency=0) + + shll8 r6 ! 102 EX ! LMNx + mov r1,r7 ! 5 MT (latency=0) + + or r6,r3 ! 82 EX ! LMNO + bt/s 3b ! 109 BR + + mov.l r3,@-r0 ! 30 LS +#endif + ! Finally, copy a byte at once, if necessary + + add #4,r5 ! 50 EX + cmp/eq r4,r0 ! 54 MT + + add #-6,r2 ! 50 EX + bt 9f ! 109 BR + +8: cmp/hi r2,r0 ! 57 MT + mov.b @(r0,r5),r1 ! 20 LS (latency=2) + + bt/s 8b ! 109 BR + + mov.b r1,@-r0 ! 29 LS + +9: rts + nop + + + ! + ! GHIJ KLMN OPQR --> .GHI JKLM NOPQ R... + ! + + ! Size is 16 or greater, and may have trailing bytes + + .balign 32 +.Lcase3: + ! Read a long word and write a long word at once + ! At the start of each iteration, r7 contains last long load + add #-3,r5 ! 79 EX + mov r4,r2 ! 5 MT (0 cycles latency) + + mov.l @(r0,r5),r7 ! 21 LS (2 cycles latency) + add #-4,r5 ! 50 EX + + add #7,r2 ! 79 EX + ! +#ifdef __LITTLE_ENDIAN__ + ! 6 cycles, 4 bytes per iteration +3: mov.l @(r0,r5),r1 ! 21 LS (latency=2) ! NMLK + mov r7, r3 ! 5 MT (latency=0) ! RQPO + + cmp/hi r2,r0 ! 57 MT + shll8 r3 ! 102 EX ! QPOx + + mov r1,r6 ! 5 MT (latency=0) + shlr16 r6 ! 107 EX + + shlr8 r6 ! 106 EX ! xxxN + mov r1, r7 ! 5 MT (latency=0) + + or r6,r3 ! 82 EX ! QPON + bt/s 3b ! 109 BR + + mov.l r3,@-r0 ! 30 LS +#else +3: mov r7,r3 ! OPQR + shlr8 r3 ! xOPQ + mov.l @(r0,r5),r7 ! KLMN + mov r7,r6 + shll16 r6 + shll8 r6 ! Nxxx + or r6,r3 ! NOPQ + cmp/hi r2,r0 + bt/s 3b + mov.l r3,@-r0 +#endif + + ! Finally, copy a byte at once, if necessary + + add #6,r5 ! 50 EX + cmp/eq r4,r0 ! 54 MT + + add #-6,r2 ! 50 EX + bt 9f ! 109 BR + +8: cmp/hi r2,r0 ! 57 MT + mov.b @(r0,r5),r1 ! 20 LS (latency=2) + + bt/s 8b ! 109 BR + + mov.b r1,@-r0 ! 29 LS + +9: rts + nop + +ENTRY(memcpy) + + ! Calculate the invariants which will be used in the remainder + ! of the code: + ! + ! r4 --> [ ... ] DST [ ... ] SRC + ! [ ... ] [ ... ] + ! : : + ! r0 --> [ ... ] r0+r5 --> [ ... ] + ! + ! + + ! Short circuit the common case of src, dst and len being 32 bit aligned + ! and test for zero length move + + mov r6, r0 ! 5 MT (0 cycle latency) + or r4, r0 ! 82 EX + + or r5, r0 ! 82 EX + tst r6, r6 ! 86 MT + + bt/s 99f ! 111 BR (zero len) + tst #3, r0 ! 87 MT + + mov r4, r0 ! 5 MT (0 cycle latency) + add r6, r0 ! 49 EX + + bt/s .Lcase00 ! 111 BR (aligned) + sub r4, r5 ! 75 EX + + ! Arguments are not nicely long word aligned or zero len. + ! Check for small copies, and if so do a simple byte at a time copy. + ! + ! Deciding on an exact value of 'small' is not easy, as the point at which + ! using the optimised routines become worthwhile varies (these are the + ! cycle counts for differnet sizes using byte-at-a-time vs. optimised): + ! size byte-at-time long word byte + ! 16 42 39-40 46-50 50-55 + ! 24 58 43-44 54-58 62-67 + ! 36 82 49-50 66-70 80-85 + ! However the penalty for getting it 'wrong' is much higher for long word + ! aligned data (and this is more common), so use a value of 16. + + mov #16, r1 ! 6 EX + cmp/gt r6,r1 ! 56 MT + + add #-1,r5 ! 50 EX + bf/s 6f ! 108 BR (not small) + + mov r5, r3 ! 5 MT (latency=0) + shlr r6 ! 104 EX + + mov.b @(r0,r5),r1 ! 20 LS (latency=2) + bf/s 4f ! 111 BR + + add #-1,r3 ! 50 EX + tst r6, r6 ! 86 MT + + bt/s 98f ! 110 BR + mov.b r1,@-r0 ! 29 LS + + ! 4 cycles, 2 bytes per iteration +3: mov.b @(r0,r5),r1 ! 20 LS (latency=2) + +4: mov.b @(r0,r3),r2 ! 20 LS (latency=2) + dt r6 ! 67 EX + + mov.b r1,@-r0 ! 29 LS + bf/s 3b ! 111 BR + + mov.b r2,@-r0 ! 29 LS +98: + rts + nop + +99: rts + mov r4, r0 + + ! Size is not small, so its worthwhile looking for optimisations. + ! First align destination to a long word boundary. + ! + ! r5 = normal value -1 + +6: tst #3, r0 ! 87 MT + mov #3, r3 ! 6 EX + + bt/s 2f ! 111 BR + and r0,r3 ! 78 EX + + ! 3 cycles, 1 byte per iteration +1: dt r3 ! 67 EX + mov.b @(r0,r5),r1 ! 19 LS (latency=2) + + add #-1, r6 ! 79 EX + bf/s 1b ! 109 BR + + mov.b r1,@-r0 ! 28 LS + +2: add #1, r5 ! 79 EX + + ! Now select the appropriate bulk transfer code based on relative + ! alignment of src and dst. + + mov r0, r3 ! 5 MT (latency=0) + + mov r5, r0 ! 5 MT (latency=0) + tst #1, r0 ! 87 MT + + bf/s 1f ! 111 BR + mov #64, r7 ! 6 EX + + ! bit 0 clear + + cmp/ge r7, r6 ! 55 MT + + bt/s 2f ! 111 BR + tst #2, r0 ! 87 MT + + ! small + bt/s .Lcase0 + mov r3, r0 + + bra .Lcase2 + nop + + ! big +2: bt/s .Lcase0b + mov r3, r0 + + bra .Lcase2b + nop + + ! bit 0 set +1: tst #2, r0 ! 87 MT + + bt/s .Lcase1 + mov r3, r0 + + bra .Lcase3 + nop + + + ! + ! GHIJ KLMN OPQR --> GHIJ KLMN OPQR + ! + + ! src, dst and size are all long word aligned + ! size is non-zero + + .balign 32 +.Lcase00: + mov #64, r1 ! 6 EX + mov r5, r3 ! 5 MT (latency=0) + + cmp/gt r6, r1 ! 56 MT + add #-4, r5 ! 50 EX + + bf .Lcase00b ! 108 BR (big loop) + shlr2 r6 ! 105 EX + + shlr r6 ! 104 EX + mov.l @(r0, r5), r1 ! 21 LS (latency=2) + + bf/s 4f ! 111 BR + add #-8, r3 ! 50 EX + + tst r6, r6 ! 86 MT + bt/s 5f ! 110 BR + + mov.l r1,@-r0 ! 30 LS + + ! 4 cycles, 2 long words per iteration +3: mov.l @(r0, r5), r1 ! 21 LS (latency=2) + +4: mov.l @(r0, r3), r2 ! 21 LS (latency=2) + dt r6 ! 67 EX + + mov.l r1, @-r0 ! 30 LS + bf/s 3b ! 109 BR + + mov.l r2, @-r0 ! 30 LS + +5: rts + nop + + + ! Size is 16 or greater and less than 64, but may have trailing bytes + + .balign 32 +.Lcase0: + add #-4, r5 ! 50 EX + mov r4, r7 ! 5 MT (latency=0) + + mov.l @(r0, r5), r1 ! 21 LS (latency=2) + mov #4, r2 ! 6 EX + + add #11, r7 ! 50 EX + tst r2, r6 ! 86 MT + + mov r5, r3 ! 5 MT (latency=0) + bt/s 4f ! 111 BR + + add #-4, r3 ! 50 EX + mov.l r1,@-r0 ! 30 LS + + ! 4 cycles, 2 long words per iteration +3: mov.l @(r0, r5), r1 ! 21 LS (latency=2) + +4: mov.l @(r0, r3), r2 ! 21 LS (latency=2) + cmp/hi r7, r0 + + mov.l r1, @-r0 ! 30 LS + bt/s 3b ! 109 BR + + mov.l r2, @-r0 ! 30 LS + + ! Copy the final 0-3 bytes + + add #3,r5 ! 50 EX + + cmp/eq r0, r4 ! 54 MT + add #-10, r7 ! 50 EX + + bt 9f ! 110 BR + + ! 3 cycles, 1 byte per iteration +1: mov.b @(r0,r5),r1 ! 19 LS + cmp/hi r7,r0 ! 57 MT + + bt/s 1b ! 111 BR + mov.b r1,@-r0 ! 28 LS + +9: rts + nop + + ! Size is at least 64 bytes, so will be going round the big loop at least once. + ! + ! r2 = rounded up r4 + ! r3 = rounded down r0 + + .balign 32 +.Lcase0b: + add #-4, r5 ! 50 EX + +.Lcase00b: + mov r0, r3 ! 5 MT (latency=0) + mov #(~0x1f), r1 ! 6 EX + + and r1, r3 ! 78 EX + mov r4, r2 ! 5 MT (latency=0) + + cmp/eq r3, r0 ! 54 MT + add #0x1f, r2 ! 50 EX + + bt/s 1f ! 110 BR + and r1, r2 ! 78 EX + + ! copy initial words until cache line aligned + + mov.l @(r0, r5), r1 ! 21 LS (latency=2) + tst #4, r0 ! 87 MT + + mov r5, r6 ! 5 MT (latency=0) + add #-4, r6 ! 50 EX + + bt/s 4f ! 111 BR + add #8, r3 ! 50 EX + + tst #0x18, r0 ! 87 MT + + bt/s 1f ! 109 BR + mov.l r1,@-r0 ! 30 LS + + ! 4 cycles, 2 long words per iteration +3: mov.l @(r0, r5), r1 ! 21 LS (latency=2) + +4: mov.l @(r0, r6), r7 ! 21 LS (latency=2) + cmp/eq r3, r0 ! 54 MT + + mov.l r1, @-r0 ! 30 LS + bf/s 3b ! 109 BR + + mov.l r7, @-r0 ! 30 LS + +#ifdef MEMCPY_USES_FPU + ! Copy the cache line aligned blocks by using the FPU registers. + ! If src and dst are well aligned adopt 64-bit data transfer. + ! We also need r0 as a temporary (for movca), so 'undo' the invariant: + ! r5: src (was r0+r5) + ! r1: dest (was r0) +1: + add r0, r5 + mov r0, r1 + + mov r1, r3 ! MT + sub r2, r3 ! EX (r3 - r2 -> r3) + mov #-5, r0 + shld r0, r3 ! number of the cache lines + + mov #8, r0 + cmp/ge r0, r3 ! Check if there are many cache lines to copy. + bf 45f ! Copy cache line aligned blocks without pref. + mov r5, r0 + add #-0x7c, r0 + tst #7, r0 ! src is 8byte aligned + bf 45f + + ! Many cache lines have to be copied and the buffers are well aligned. + ! Aggressive prefetching and FPU in single paired precision. + mov r0, r5 + mov r5, r6 + add #-0x80, r6 ! prefetch head + + ! store FPU (in single precision mode, do not check R15 align). + fmov fr12, @-r15 + fmov fr13, @-r15 + fmov fr14, @-r15 + fmov fr15, @-r15 + + FPU_SET_PAIRED_PREC + + mov #4, r0 +67: + add #-0x20, r6 + pref @r6 + add #-0x20, r6 + pref @r6 + + fmov @r5+, dr0 + fmov @r5+, dr2 + fmov @r5+, dr4 + fmov @r5+, dr6 + fmov @r5+, dr8 + fmov @r5+, dr10 + fmov @r5+, dr12 + fmov @r5+, dr14 + fmov @r5+, xd0 + fmov @r5+, xd2 + fmov @r5+, xd4 + fmov @r5+, xd6 + fmov @r5+, xd8 + fmov @r5+, xd10 + fmov @r5+, xd12 + fmov @r5+, xd14 + + DALLOC + fmov xd14, @-r1 + fmov xd12, @-r1 + fmov xd10, @-r1 + fmov xd8, @-r1 + DALLOC + fmov xd6, @-r1 + fmov xd4, @-r1 + fmov xd2, @-r1 + fmov xd0, @-r1 + DALLOC + fmov dr14, @-r1 + fmov dr12, @-r1 + fmov dr10, @-r1 + fmov dr8, @-r1 + DALLOC + fmov dr6, @-r1 + add #-0x80, r5 + fmov dr4, @-r1 + add #-0x80, r5 + fmov dr2, @-r1 + add #-0x20, r6 + fmov dr0, @-r1 + add #-4, r3 + pref @r6 + add #-0x20, r6 + cmp/ge r0, r3 + bt/s 67b + pref @r6 + + RESTORE_FPSCR + + ! Restore FPU callee save registers + fmov @r15+, fr15 + fmov @r15+, fr14 + fmov @r15+, fr13 + fmov @r15+, fr12 + + ! Other cache lines could be copied: so use the FPU in single paired + ! precision without prefetching. No check for alignment is necessary. + + mov #1, r0 + cmp/ge r0, r3 + bt/s 3f + add #0x60, r5 + + bra 5f + nop + + ! No prefetch and FPU in single precision. +45: + add #-0x1c, r5 + mov r5, r0 + tst #7, r0 + bt 3f + +2: fmov.s @r5+, fr0 + fmov.s @r5+, fr1 + fmov.s @r5+, fr2 + fmov.s @r5+, fr3 + fmov.s @r5+, fr4 + fmov.s @r5+, fr5 + fmov.s @r5+, fr6 + fmov.s @r5+, fr7 + + DALLOC + + fmov.s fr7, @-r1 + fmov.s fr6, @-r1 + fmov.s fr5, @-r1 + fmov.s fr4, @-r1 + fmov.s fr3, @-r1 + fmov.s fr2, @-r1 + fmov.s fr1, @-r1 + fmov.s fr0, @-r1 + + cmp/eq r2,r1 + + bf/s 2b + add #-0x40, r5 + + bra 5f + nop + + ! No prefetch and FPU in single paired precision. + +3: FPU_SET_PAIRED_PREC + +4: fmov @r5+, dr0 + fmov @r5+, dr2 + fmov @r5+, dr4 + fmov @r5+, dr6 + + DALLOC + + fmov dr6, @-r1 + fmov dr4, @-r1 + fmov dr2, @-r1 + fmov dr0, @-r1 + cmp/eq r2,r1 + + bf/s 4b + add #-0x40, r5 + + RESTORE_FPSCR + +5: mov r1, r0 + + cmp/eq r4, r0 ! 54 MT + bf/s 1f ! 109 BR + sub r1, r5 ! 75 EX + + rts + nop +1: +#else + ! Copy the cache line aligned blocks + ! + ! In use: r0, r2, r4, r5 + ! Scratch: r1, r3, r6, r7 + ! + ! We could do this with the four scratch registers, but if src + ! and dest hit the same cache line, this will thrash, so make + ! use of additional registers. + ! + ! We also need r0 as a temporary (for movca), so 'undo' the invariant: + ! r5: src (was r0+r5) + ! r1: dest (was r0) + ! this can be reversed at the end, so we don't need to save any extra + ! state. + ! +1: mov.l r8, @-r15 ! 30 LS + add r0, r5 ! 49 EX + + mov.l r9, @-r15 ! 30 LS + mov r0, r1 ! 5 MT (latency=0) + + mov.l r10, @-r15 ! 30 LS + add #-0x1c, r5 ! 50 EX + + mov.l r11, @-r15 ! 30 LS + + ! 16 cycles, 32 bytes per iteration +2: mov.l @(0x00,r5),r0 ! 18 LS (latency=2) + add #-0x20, r1 ! 50 EX + mov.l @(0x04,r5),r3 ! 18 LS (latency=2) + mov.l @(0x08,r5),r6 ! 18 LS (latency=2) + mov.l @(0x0c,r5),r7 ! 18 LS (latency=2) + mov.l @(0x10,r5),r8 ! 18 LS (latency=2) + mov.l @(0x14,r5),r9 ! 18 LS (latency=2) + mov.l @(0x18,r5),r10 ! 18 LS (latency=2) + mov.l @(0x1c,r5),r11 ! 18 LS (latency=2) + movca.l r0,@r1 ! 40 LS (latency=3-7) + mov.l r3,@(0x04,r1) ! 33 LS + mov.l r6,@(0x08,r1) ! 33 LS + mov.l r7,@(0x0c,r1) ! 33 LS + + mov.l r8,@(0x10,r1) ! 33 LS + add #-0x20, r5 ! 50 EX + + mov.l r9,@(0x14,r1) ! 33 LS + cmp/eq r2,r1 ! 54 MT + + mov.l r10,@(0x18,r1) ! 33 LS + bf/s 2b ! 109 BR + + mov.l r11,@(0x1c,r1) ! 33 LS + + mov r1, r0 ! 5 MT (latency=0) + + mov.l @r15+, r11 ! 15 LS + sub r1, r5 ! 75 EX + + mov.l @r15+, r10 ! 15 LS + cmp/eq r4, r0 ! 54 MT + + bf/s 1f ! 109 BR + mov.l @r15+, r9 ! 15 LS + + rts +1: mov.l @r15+, r8 ! 15 LS +#endif + sub r4, r1 ! 75 EX (len remaining) + + ! number of trailing bytes is non-zero + ! + ! invariants restored (r5 already decremented by 4) + ! also r1=num bytes remaining + + mov #4, r2 ! 6 EX + mov r4, r7 ! 5 MT (latency=0) + + add #0x1c, r5 ! 50 EX (back to -4) + cmp/hs r2, r1 ! 58 MT + + bf/s 5f ! 108 BR + add #11, r7 ! 50 EX + + mov.l @(r0, r5), r6 ! 21 LS (latency=2) + tst r2, r1 ! 86 MT + + mov r5, r3 ! 5 MT (latency=0) + bt/s 4f ! 111 BR + + add #-4, r3 ! 50 EX + cmp/hs r2, r1 ! 58 MT + + bt/s 5f ! 111 BR + mov.l r6,@-r0 ! 30 LS + + ! 4 cycles, 2 long words per iteration +3: mov.l @(r0, r5), r6 ! 21 LS (latency=2) + +4: mov.l @(r0, r3), r2 ! 21 LS (latency=2) + cmp/hi r7, r0 + + mov.l r6, @-r0 ! 30 LS + bt/s 3b ! 109 BR + + mov.l r2, @-r0 ! 30 LS + + ! Copy the final 0-3 bytes + +5: cmp/eq r0, r4 ! 54 MT + add #-10, r7 ! 50 EX + + bt 9f ! 110 BR + add #3,r5 ! 50 EX + + ! 3 cycles, 1 byte per iteration +1: mov.b @(r0,r5),r1 ! 19 LS + cmp/hi r7,r0 ! 57 MT + + bt/s 1b ! 111 BR + mov.b r1,@-r0 ! 28 LS + +9: rts + nop + + ! + ! GHIJ KLMN OPQR --> ..GH IJKL MNOP QR.. + ! + + .balign 32 +.Lcase2: + ! Size is 16 or greater and less then 64, but may have trailing bytes + +2: mov r5, r6 ! 5 MT (latency=0) + add #-2,r5 ! 50 EX + + mov r4,r2 ! 5 MT (latency=0) + add #-4,r6 ! 50 EX + + add #7,r2 ! 50 EX +3: mov.w @(r0,r5),r1 ! 20 LS (latency=2) + + mov.w @(r0,r6),r3 ! 20 LS (latency=2) + cmp/hi r2,r0 ! 57 MT + + mov.w r1,@-r0 ! 29 LS + bt/s 3b ! 111 BR + + mov.w r3,@-r0 ! 29 LS + + bra 10f + nop + + + .balign 32 +.Lcase2b: + ! Size is at least 64 bytes, so will be going round the big loop at least once. + ! + ! r2 = rounded up r4 + ! r3 = rounded down r0 + + mov r0, r3 ! 5 MT (latency=0) + mov #(~0x1f), r1 ! 6 EX + + and r1, r3 ! 78 EX + mov r4, r2 ! 5 MT (latency=0) + + cmp/eq r3, r0 ! 54 MT + add #0x1f, r2 ! 50 EX + + add #-2, r5 ! 50 EX + bt/s 1f ! 110 BR + and r1, r2 ! 78 EX + + ! Copy a short word one at a time until we are cache line aligned + ! Normal values: r0, r2, r3, r4 + ! Unused: r1, r6, r7 + ! Mod: r5 (=r5-2) + ! + add #2, r3 ! 50 EX + +2: mov.w @(r0,r5),r1 ! 20 LS (latency=2) + cmp/eq r3,r0 ! 54 MT + + bf/s 2b ! 111 BR + + mov.w r1,@-r0 ! 29 LS + + ! Copy the cache line aligned blocks + ! + ! In use: r0, r2, r4, r5 (=r5-2) + ! Scratch: r1, r3, r6, r7 + ! + ! We could do this with the four scratch registers, but if src + ! and dest hit the same cache line, this will thrash, so make + ! use of additional registers. + ! + ! We also need r0 as a temporary (for movca), so 'undo' the invariant: + ! r5: src (was r0+r5) + ! r1: dest (was r0) + ! this can be reversed at the end, so we don't need to save any extra + ! state. + ! +1: mov.l r8, @-r15 ! 30 LS + add r0, r5 ! 49 EX + + mov.l r9, @-r15 ! 30 LS + mov r0, r1 ! 5 MT (latency=0) + + mov.l r10, @-r15 ! 30 LS + add #-0x1e, r5 ! 50 EX + + mov.l r11, @-r15 ! 30 LS + + mov.l r12, @-r15 ! 30 LS + + ! 17 cycles, 32 bytes per iteration +#ifdef __LITTLE_ENDIAN__ +2: mov.w @r5+, r0 ! 14 LS (latency=2) ..JI + add #-0x20, r1 ! 50 EX + + mov.l @r5+, r3 ! 15 LS (latency=2) NMLK + + mov.l @r5+, r6 ! 15 LS (latency=2) RQPO + shll16 r0 ! 103 EX JI.. + + mov.l @r5+, r7 ! 15 LS (latency=2) + xtrct r3, r0 ! 48 EX LKJI + + mov.l @r5+, r8 ! 15 LS (latency=2) + xtrct r6, r3 ! 48 EX PONM + + mov.l @r5+, r9 ! 15 LS (latency=2) + xtrct r7, r6 ! 48 EX + + mov.l @r5+, r10 ! 15 LS (latency=2) + xtrct r8, r7 ! 48 EX + + mov.l @r5+, r11 ! 15 LS (latency=2) + xtrct r9, r8 ! 48 EX + + mov.w @r5+, r12 ! 15 LS (latency=2) + xtrct r10, r9 ! 48 EX + + movca.l r0,@r1 ! 40 LS (latency=3-7) + xtrct r11, r10 ! 48 EX + + mov.l r3, @(0x04,r1) ! 33 LS + xtrct r12, r11 ! 48 EX + + mov.l r6, @(0x08,r1) ! 33 LS + + mov.l r7, @(0x0c,r1) ! 33 LS + + mov.l r8, @(0x10,r1) ! 33 LS + add #-0x40, r5 ! 50 EX + + mov.l r9, @(0x14,r1) ! 33 LS + cmp/eq r2,r1 ! 54 MT + + mov.l r10, @(0x18,r1) ! 33 LS + bf/s 2b ! 109 BR + + mov.l r11, @(0x1c,r1) ! 33 LS +#else +2: mov.w @(0x1e,r5), r0 ! 17 LS (latency=2) + add #-2, r5 ! 50 EX + + mov.l @(0x1c,r5), r3 ! 18 LS (latency=2) + add #-4, r1 ! 50 EX + + mov.l @(0x18,r5), r6 ! 18 LS (latency=2) + shll16 r0 ! 103 EX + + mov.l @(0x14,r5), r7 ! 18 LS (latency=2) + xtrct r3, r0 ! 48 EX + + mov.l @(0x10,r5), r8 ! 18 LS (latency=2) + xtrct r6, r3 ! 48 EX + + mov.l @(0x0c,r5), r9 ! 18 LS (latency=2) + xtrct r7, r6 ! 48 EX + + mov.l @(0x08,r5), r10 ! 18 LS (latency=2) + xtrct r8, r7 ! 48 EX + + mov.l @(0x04,r5), r11 ! 18 LS (latency=2) + xtrct r9, r8 ! 48 EX + + mov.l @(0x00,r5), r12 ! 18 LS (latency=2) + xtrct r10, r9 ! 48 EX + + movca.l r0,@r1 ! 40 LS (latency=3-7) + add #-0x1c, r1 ! 50 EX + + mov.l r3, @(0x18,r1) ! 33 LS + xtrct r11, r10 ! 48 EX + + mov.l r6, @(0x14,r1) ! 33 LS + xtrct r12, r11 ! 48 EX + + mov.l r7, @(0x10,r1) ! 33 LS + + mov.l r8, @(0x0c,r1) ! 33 LS + add #-0x1e, r5 ! 50 EX + + mov.l r9, @(0x08,r1) ! 33 LS + cmp/eq r2,r1 ! 54 MT + + mov.l r10, @(0x04,r1) ! 33 LS + bf/s 2b ! 109 BR + + mov.l r11, @(0x00,r1) ! 33 LS +#endif + + mov.l @r15+, r12 + mov r1, r0 ! 5 MT (latency=0) + + mov.l @r15+, r11 ! 15 LS + sub r1, r5 ! 75 EX + + mov.l @r15+, r10 ! 15 LS + cmp/eq r4, r0 ! 54 MT + + bf/s 1f ! 109 BR + mov.l @r15+, r9 ! 15 LS + + rts +1: mov.l @r15+, r8 ! 15 LS + + add #0x1e, r5 ! 50 EX + + ! Finish off a short word at a time + ! r5 must be invariant - 2 +10: mov r4,r2 ! 5 MT (latency=0) + add #1,r2 ! 50 EX + + cmp/hi r2, r0 ! 57 MT + bf/s 1f ! 109 BR + + add #2, r2 ! 50 EX + +3: mov.w @(r0,r5),r1 ! 20 LS + cmp/hi r2,r0 ! 57 MT + + bt/s 3b ! 109 BR + + mov.w r1,@-r0 ! 29 LS +1: + + ! + ! Finally, copy the last byte if necessary + cmp/eq r4,r0 ! 54 MT + bt/s 9b + add #1,r5 + mov.b @(r0,r5),r1 + rts + mov.b r1,@-r0 + +END(memcpy) +libc_hidden_def (memcpy) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sh/sh4/memmove.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sh/sh4/memmove.c new file mode 100644 index 00000000..8059bd4c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sh/sh4/memmove.c @@ -0,0 +1,121 @@ +/* memmove implementation for SH4 + * + * Copyright (C) 2009 STMicroelectronics Ltd. + * + * Author: Giuseppe Cavallaro + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#ifndef __SH_FPU_ANY__ +#include "../../generic/memmove.c" +#else + +#include + +#define FPSCR_SR (1 << 20) +#define STORE_FPSCR(x) __asm__ __volatile__("sts fpscr, %0" : "=r"(x)) +#define LOAD_FPSCR(x) __asm__ __volatile__("lds %0, fpscr" : : "r"(x)) + +static void fpu_optimised_copy_fwd(void *dest, const void *src, size_t len) +{ + char *d = (char *)dest; + char *s = (char *)src; + + if (len >= 64) { + unsigned long fpscr; + int *s1; + int *d1; + + /* Align the dest to 4 byte boundary. */ + while ((unsigned)d & 0x7) { + *d++ = *s++; + len--; + } + + s1 = (int *)s; + d1 = (int *)d; + + /* check if s is well aligned to use FPU */ + if (!((unsigned)s1 & 0x7)) { + + /* Align the dest to cache-line boundary */ + while ((unsigned)d1 & 0x1c) { + *d1++ = *s1++; + len -= 4; + } + + /* Use paired single precision load or store mode for + * 64-bit tranfering.*/ + STORE_FPSCR(fpscr); + LOAD_FPSCR(FPSCR_SR); + + while (len >= 32) { + __asm__ __volatile__ ("fmov @%0+,dr0":"+r" (s1)); + __asm__ __volatile__ ("fmov @%0+,dr2":"+r" (s1)); + __asm__ __volatile__ ("fmov @%0+,dr4":"+r" (s1)); + __asm__ __volatile__ ("fmov @%0+,dr6":"+r" (s1)); + __asm__ + __volatile__ ("fmov dr0,@%0"::"r" + (d1):"memory"); + d1 += 2; + __asm__ + __volatile__ ("fmov dr2,@%0"::"r" + (d1):"memory"); + d1 += 2; + __asm__ + __volatile__ ("fmov dr4,@%0"::"r" + (d1):"memory"); + d1 += 2; + __asm__ + __volatile__ ("fmov dr6,@%0"::"r" + (d1):"memory"); + d1 += 2; + len -= 32; + } + LOAD_FPSCR(fpscr); + } + s = (char *)s1; + d = (char *)d1; + /*TODO: other subcases could be covered here?!?*/ + } + /* Go to per-byte copy */ + while (len > 0) { + *d++ = *s++; + len--; + } + return; +} + +void *memmove(void *dest, const void *src, size_t len) +{ + unsigned long int d = (long int)dest; + unsigned long int s = (long int)src; + unsigned long int res; + + if (d >= s) + res = d - s; + else + res = s - d; + /* + * 1) dest and src are not overlap ==> memcpy (BWD/FDW) + * 2) dest and src are 100% overlap ==> memcpy (BWD/FDW) + * 3) left-to-right overlap ==> Copy from the beginning to the end + * 4) right-to-left overlap ==> Copy from the end to the beginning + */ + + if (res == 0) /* 100% overlap */ + memcpy(dest, src, len); /* No overlap */ + else if (res >= len) + memcpy(dest, src, len); + else { + if (d > s) /* right-to-left overlap */ + memcpy(dest, src, len); /* memcpy is BWD */ + else /* cannot use SH4 memcpy for this case */ + fpu_optimised_copy_fwd(dest, src, len); + } + return (dest); +} + +libc_hidden_def(memmove) +#endif /*__SH_FPU_ANY__ */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sh/sh4/memset.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sh/sh4/memset.S new file mode 100644 index 00000000..eb83355c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sh/sh4/memset.S @@ -0,0 +1,152 @@ +/* $Id: memset.S,v 1.1 2000/04/14 16:49:01 mjd Exp $ + * + * "memset" implementation of SuperH + * + * Copyright (C) 1999 Niibe Yutaka + * + * Copyright (c) 2009 STMicroelectronics Ltd + * Optimised using 64bit data transfer (via FPU) and the movca.l inst. + * Author: Giuseppe Cavallaro + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* + * void *memset(void *s, int c, size_t n); + */ + +#include + +#if defined (__LITTLE_ENDIAN__) && defined (__SH_FPU_ANY__) +#define MEMSET_USES_FPU +/* Use paired single precision load or store mode for 64-bit tranfering. + * FPSCR.SZ=1,FPSCR.SZ=0 is well defined on both SH4-200 and SH4-300. + * Currenlty it has been only implemented and tested for little endian mode. */ +.macro FPU_SET_PAIRED_PREC + sts fpscr, r3 + mov #0x10, r1 ! PR=0 SZ=1 + shll16 r1 + lds r1, fpscr +.endm +.macro RESTORE_FPSCR + lds r3, fpscr +.endm +#endif + +ENTRY(memset) + mov #12,r0 + add r6,r4 + cmp/gt r6,r0 + bt/s 40f ! if it's too small, set a byte at once + mov r4,r0 + and #3,r0 + cmp/eq #0,r0 + bt/s 2f ! It's aligned + sub r0,r6 +1: + dt r0 + bf/s 1b + mov.b r5,@-r4 +2: ! make VVVV + extu.b r5,r5 + swap.b r5,r0 ! V0 + or r0,r5 ! VV + swap.w r5,r0 ! VV00 + or r0,r5 ! VVVV + + ! Check if enough bytes need to be copied to be worth the big loop + mov #0x40, r0 ! (MT) + cmp/gt r6,r0 ! (MT) 64 > len => slow loop + + bt/s 22f + mov r6,r0 + + ! align the dst to the cache block size if necessary + mov r4, r3 + mov #~(0x1f), r1 + + and r3, r1 + cmp/eq r3, r1 + + bt/s 11f ! dst is already aligned + sub r1, r3 ! r3-r1 -> r3 + shlr2 r3 ! number of loops + +10: mov.l r5,@-r4 + dt r3 + bf/s 10b + add #-4, r6 + +11: ! dst is 32byte aligned + mov r6,r2 + mov #-5,r0 + shld r0,r2 ! number of loops + + add #-32, r4 + mov r5, r0 + +#ifdef MEMSET_USES_FPU + lds r5, fpul ! (CO) + fsts fpul, fr0 ! Dr0 will be 'VVVVVVVV' + fsts fpul, fr1 + + FPU_SET_PAIRED_PREC +12: + movca.l r0, @r4 + mov.l r5, @(4, r4) + add #32, r4 + fmov dr0, @-r4 + fmov dr0, @-r4 + add #-0x20, r6 + fmov dr0, @-r4 + dt r2 + bf/s 12b + add #-40, r4 + + RESTORE_FPSCR +#else +12: + movca.l r0,@r4 + mov.l r5,@(4, r4) + mov.l r5,@(8, r4) + mov.l r5,@(12,r4) + mov.l r5,@(16,r4) + mov.l r5,@(20,r4) + add #-0x20, r6 + mov.l r5,@(24,r4) + dt r2 + mov.l r5,@(28,r4) + bf/s 12b + add #-32, r4 + +#endif + add #32, r4 + mov #8, r0 + cmp/ge r0, r6 + bf 40f + + mov r6,r0 +22: + shlr2 r0 + shlr r0 ! r0 = r6 >> 3 +3: + dt r0 + mov.l r5,@-r4 ! set 8-byte at once + bf/s 3b + mov.l r5,@-r4 + ! + mov #7,r0 + and r0,r6 + + ! fill bytes (length may be zero) +40: tst r6,r6 + bt 5f +4: + dt r6 + bf/s 4b + mov.b r5,@-r4 +5: + rts + mov r4,r0 +END(memset) +libc_hidden_def (memset) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sh/sh4/strcpy.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sh/sh4/strcpy.S new file mode 100644 index 00000000..0f827801 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sh/sh4/strcpy.S @@ -0,0 +1,28 @@ +/* strcpy implementation for SUPERH + * + * Copyright (C) 2009 STMicroelectronics Ltd. + * + * Author: Giuseppe Cavallaro + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* + char *strcpy(char *dest, const char *src); + */ + +#include + +ENTRY(strcpy) + mov r4,r2 +1: + mov.b @r5+,r1 + tst r1,r1 + mov.b r1,@r2 + bf/s 1b + add #1,r2 + + rts + mov r4,r0 +END(strcpy) +libc_hidden_def (strcpy) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sh/sh4/strncpy.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sh/sh4/strncpy.S new file mode 100644 index 00000000..8a16f39d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sh/sh4/strncpy.S @@ -0,0 +1,43 @@ +/* strncpy implementation for SUPERH + * + * Copyright (C) 2009 STMicroelectronics Ltd. + * + * Author: Giuseppe Cavallaro + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* + char *strncpy(char *dest, const char *src, size_t n); + */ + +#include + +ENTRY(strncpy) + mov #0,r0 + bra 2f + mov r4,r2 +1: + mov.b r1,@(r0,r2) + add #1,r0 +2: + cmp/hs r6,r0 + bt 5f + mov.b @(r0,r5),r1 + tst r1,r1 + bf/s 1b + cmp/hs r6,r0 + bra 4f + nop +3: + mov.b r1,@(r0,r2) + add #1,r0 + cmp/hs r6,r0 +4: + bf/s 3b + mov #0,r1 +5: + rts + mov r2,r0 +END(strncpy) +libc_hidden_def(strncpy) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sh/strlen.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sh/strlen.S new file mode 100644 index 00000000..1ccecc17 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sh/strlen.S @@ -0,0 +1,75 @@ +/* $Id: strlen.S,v 1.2 2001/06/29 14:07:15 gniibe Exp $ + * + * "strlen" implementation of SuperH + * + * Copyright (C) 1999 Kaz Kojima + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* size_t strlen (const char *s) */ + +#include +#include + +ENTRY(strlen) + mov r4,r0 + and #3,r0 + tst r0,r0 + bt/s 1f + mov #0,r2 + + add #-1,r0 + shll2 r0 + shll r0 + braf r0 + nop + + mov.b @r4+,r1 + tst r1,r1 + bt 8f + add #1,r2 + + mov.b @r4+,r1 + tst r1,r1 + bt 8f + add #1,r2 + + mov.b @r4+,r1 + tst r1,r1 + bt 8f + add #1,r2 + +1: + mov #0,r3 +2: + mov.l @r4+,r1 + cmp/str r3,r1 + bf/s 2b + add #4,r2 + + add #-4,r2 +#ifndef __LITTLE_ENDIAN__ + swap.b r1,r1 + swap.w r1,r1 + swap.b r1,r1 +#endif + extu.b r1,r0 + tst r0,r0 + bt/s 8f + shlr8 r1 + add #1,r2 + extu.b r1,r0 + tst r0,r0 + bt/s 8f + shlr8 r1 + add #1,r2 + extu.b r1,r0 + tst r0,r0 + bt 8f + add #1,r2 +8: + rts + mov r2,r0 +END(strlen) +libc_hidden_def (strlen) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sh64/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sh64/Makefile new file mode 100644 index 00000000..0a95346f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sh64/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir:=../../../ +top_builddir:=../../../ +all: objs +include $(top_builddir)Rules.mak +include ../Makefile.in +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sh64/memcpy.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sh64/memcpy.S new file mode 100644 index 00000000..470784ec --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sh64/memcpy.S @@ -0,0 +1,205 @@ +/* Cloned and hacked for uClibc by Paul Mundt, December 2003 */ +/* Modified by SuperH, Inc. September 2003 */ +! +! Fast SH memcpy +! +! by Toshiyasu Morita (tm@netcom.com) +! hacked by J"orn Rernnecke (joern.rennecke@superh.com) ("o for o-umlaut) +! SH5 code Copyright 2002 SuperH Ltd. +! +! Entry: ARG0: destination pointer +! ARG1: source pointer +! ARG2: byte count +! +! Exit: RESULT: destination pointer +! any other registers in the range r0-r7: trashed +! +! Notes: Usually one wants to do small reads and write a longword, but +! unfortunately it is difficult in some cases to concatanate bytes +! into a longword on the SH, so this does a longword read and small +! writes. +! +! This implementation makes two assumptions about how it is called: +! +! 1.: If the byte count is nonzero, the address of the last byte to be +! copied is unsigned greater than the address of the first byte to +! be copied. This could be easily swapped for a signed comparison, +! but the algorithm used needs some comparison. +! +! 2.: When there are two or three bytes in the last word of an 11-or-more +! bytes memory chunk to b copied, the rest of the word can be read +! without side effects. +! This could be easily changed by increasing the minumum size of +! a fast memcpy and the amount subtracted from r7 before L_2l_loop be 2, +! however, this would cost a few extra cyles on average. +! For SHmedia, the assumption is that any quadword can be read in its +! enirety if at least one byte is included in the copy. +! + +#include + + .section .text..SHmedia32,"ax" + .globl memcpy + .type memcpy, @function + .align 5 + +memcpy: + +#define LDUAQ(P,O,D0,D1) ldlo.q P,O,D0; ldhi.q P,O+7,D1 +#define STUAQ(P,O,D0,D1) stlo.q P,O,D0; sthi.q P,O+7,D1 +#define LDUAL(P,O,D0,D1) ldlo.l P,O,D0; ldhi.l P,O+3,D1 +#define STUAL(P,O,D0,D1) stlo.l P,O,D0; sthi.l P,O+3,D1 + + ld.b r3,0,r63 + pta/l Large,tr0 + movi 25,r0 + bgeu/u r4,r0,tr0 + nsb r4,r0 + shlli r0,5,r0 + movi (L1-L0+63*32 + 1) & 0xffff,r1 + sub r1, r0, r0 +L0: ptrel r0,tr0 + add r2,r4,r5 + ptabs r18,tr1 + add r3,r4,r6 + blink tr0,r63 + +/* Rearranged to make cut2 safe */ + .balign 8 +L4_7: /* 4..7 byte memcpy cntd. */ + stlo.l r2, 0, r0 + or r6, r7, r6 + sthi.l r5, -1, r6 + stlo.l r5, -4, r6 + blink tr1,r63 + + .balign 8 +L1: /* 0 byte memcpy */ + nop + blink tr1,r63 + nop + nop + nop + nop + +L2_3: /* 2 or 3 byte memcpy cntd. */ + st.b r5,-1,r6 + blink tr1,r63 + + /* 1 byte memcpy */ + ld.b r3,0,r0 + st.b r2,0,r0 + blink tr1,r63 + +L8_15: /* 8..15 byte memcpy cntd. */ + stlo.q r2, 0, r0 + or r6, r7, r6 + sthi.q r5, -1, r6 + stlo.q r5, -8, r6 + blink tr1,r63 + + /* 2 or 3 byte memcpy */ + ld.b r3,0,r0 + ld.b r2,0,r63 + ld.b r3,1,r1 + st.b r2,0,r0 + pta/l L2_3,tr0 + ld.b r6,-1,r6 + st.b r2,1,r1 + blink tr0, r63 + + /* 4 .. 7 byte memcpy */ + LDUAL (r3, 0, r0, r1) + pta L4_7, tr0 + ldlo.l r6, -4, r7 + or r0, r1, r0 + sthi.l r2, 3, r0 + ldhi.l r6, -1, r6 + blink tr0, r63 + + /* 8 .. 15 byte memcpy */ + LDUAQ (r3, 0, r0, r1) + pta L8_15, tr0 + ldlo.q r6, -8, r7 + or r0, r1, r0 + sthi.q r2, 7, r0 + ldhi.q r6, -1, r6 + blink tr0, r63 + + /* 16 .. 24 byte memcpy */ + LDUAQ (r3, 0, r0, r1) + LDUAQ (r3, 8, r8, r9) + or r0, r1, r0 + sthi.q r2, 7, r0 + or r8, r9, r8 + sthi.q r2, 15, r8 + ldlo.q r6, -8, r7 + ldhi.q r6, -1, r6 + stlo.q r2, 8, r8 + stlo.q r2, 0, r0 + or r6, r7, r6 + sthi.q r5, -1, r6 + stlo.q r5, -8, r6 + blink tr1,r63 + +Large: + ld.b r2, 0, r63 + pta/l Loop_ua, tr1 + ori r3, -8, r7 + sub r2, r7, r22 + sub r3, r2, r6 + add r2, r4, r5 + ldlo.q r3, 0, r0 + addi r5, -16, r5 + movi 64+8, r27 /* could subtract r7 from that. */ + stlo.q r2, 0, r0 + sthi.q r2, 7, r0 + ldx.q r22, r6, r0 + bgtu/l r27, r4, tr1 + + addi r5, -48, r27 + pta/l Loop_line, tr0 + addi r6, 64, r36 + addi r6, -24, r19 + addi r6, -16, r20 + addi r6, -8, r21 + +Loop_line: + ldx.q r22, r36, r63 + alloco r22, 32 + addi r22, 32, r22 + ldx.q r22, r19, r23 + sthi.q r22, -25, r0 + ldx.q r22, r20, r24 + ldx.q r22, r21, r25 + stlo.q r22, -32, r0 + ldx.q r22, r6, r0 + sthi.q r22, -17, r23 + sthi.q r22, -9, r24 + sthi.q r22, -1, r25 + stlo.q r22, -24, r23 + stlo.q r22, -16, r24 + stlo.q r22, -8, r25 + bgeu r27, r22, tr0 + +Loop_ua: + addi r22, 8, r22 + sthi.q r22, -1, r0 + stlo.q r22, -8, r0 + ldx.q r22, r6, r0 + bgtu/l r5, r22, tr1 + + add r3, r4, r7 + ldlo.q r7, -8, r1 + sthi.q r22, 7, r0 + ldhi.q r7, -1, r7 + ptabs r18,tr1 + stlo.q r22, 0, r0 + or r1, r7, r1 + sthi.q r5, 15, r1 + stlo.q r5, 8, r1 + blink tr1, r63 + + .size memcpy,.-memcpy + +libc_hidden_def(memcpy) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sh64/memset.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sh64/memset.S new file mode 100644 index 00000000..1b8812cd --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sh64/memset.S @@ -0,0 +1,97 @@ +/* Cloned and hacked for uClibc by Paul Mundt, December 2003 */ +/* Modified by SuperH, Inc. September 2003 */ +! +! Fast SH memset +! +! by Toshiyasu Morita (tm@netcom.com) +! +! SH5 code by J"orn Rennecke (joern.rennecke@superh.com) +! Copyright 2002 SuperH Ltd. +! + +#include +#include + +#if __BYTE_ORDER == __LITTLE_ENDIAN +#define SHHI shlld +#define SHLO shlrd +#else +#define SHHI shlrd +#define SHLO shlld +#endif + + .section .text..SHmedia32,"ax" + .globl memset + .type memset, @function + + .align 5 + +memset: + pta/l multiquad, tr0 + andi r2, 7, r22 + ptabs r18, tr2 + mshflo.b r3,r3,r3 + add r4, r22, r23 + mperm.w r3, r63, r3 /* Fill pattern now in every byte of r3 */ + + movi 8, r9 + bgtu/u r23, r9, tr0 /* multiquad */ + + beqi/u r4, 0, tr2 /* Return with size 0 - ensures no mem accesses */ + ldlo.q r2, 0, r7 + shlli r4, 2, r4 + movi -1, r8 + SHHI r8, r4, r8 + SHHI r8, r4, r8 + mcmv r7, r8, r3 + stlo.q r2, 0, r3 + blink tr2, r63 + +multiquad: + pta/l lastquad, tr0 + stlo.q r2, 0, r3 + shlri r23, 3, r24 + add r2, r4, r5 + beqi/u r24, 1, tr0 /* lastquad */ + pta/l loop, tr1 + sub r2, r22, r25 + andi r5, -8, r20 /* calculate end address and */ + addi r20, -7*8, r8 /* loop end address; This might overflow, so we need + to use a different test before we start the loop + */ + bge/u r24, r9, tr1 /* loop */ + st.q r25, 8, r3 + st.q r20, -8, r3 + shlri r24, 1, r24 + beqi/u r24, 1, tr0 /* lastquad */ + st.q r25, 16, r3 + st.q r20, -16, r3 + beqi/u r24, 2, tr0 /* lastquad */ + st.q r25, 24, r3 + st.q r20, -24, r3 +lastquad: + sthi.q r5, -1, r3 + blink tr2,r63 + +loop: +!!! alloco r25, 32 /* QQQ comment out for short-term fix to SHUK #3895. + QQQ commenting out is locically correct, but sub-optimal + QQQ Sean McGoogan - 4th April 2003. */ + st.q r25, 8, r3 + st.q r25, 16, r3 + st.q r25, 24, r3 + st.q r25, 32, r3 + addi r25, 32, r25 + bgeu/l r8, r25, tr1 /* loop */ + + st.q r20, -40, r3 + st.q r20, -32, r3 + st.q r20, -24, r3 + st.q r20, -16, r3 + st.q r20, -8, r3 + sthi.q r5, -1, r3 + blink tr2,r63 + + .size memset,.-memset + +libc_hidden_def(memset) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sh64/strcpy.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sh64/strcpy.S new file mode 100644 index 00000000..f317707b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sh64/strcpy.S @@ -0,0 +1,102 @@ +/* Cloned and hacked for uClibc by Paul Mundt, December 2003 */ +/* Modified by SuperH, Inc. September 2003 */ +! Entry: arg0: destination +! arg1: source +! Exit: result: destination +! +! SH5 code Copyright 2002 SuperH Ltd. + +#include +#include + +#if __BYTE_ORDER == __LITTLE_ENDIAN +#define SHHI shlld +#define SHLO shlrd +#else +#define SHHI shlrd +#define SHLO shlld +#endif + + .section .text..SHmedia32,"ax" + .globl strcpy + .type strcpy, @function + .align 5 + +strcpy: + + pta/l shortstring,tr1 + ldlo.q r3,0,r4 + ptabs r18,tr4 + shlli r3,3,r7 + addi r2, 8, r0 + mcmpeq.b r4,r63,r6 + SHHI r6,r7,r6 + bnei/u r6,0,tr1 /* shortstring */ + pta/l no_lddst, tr2 + ori r3,-8,r23 + sub r2, r23, r0 + sub r3, r2, r21 + addi r21, 8, r20 + ldx.q r0, r21, r5 + pta/l loop, tr0 + ori r2,-8,r22 + mcmpeq.b r5, r63, r6 + bgt/u r22, r23, tr2 /* no_lddst */ + + /* r22 < r23 : Need to do a load from the destination. */ + /* r22 == r23 : Doesn't actually need to load from destination, */ + /* but still can be handled here. */ + ldlo.q r2, 0, r9 + movi -1, r8 + SHLO r8, r7, r8 + mcmv r4, r8, r9 + stlo.q r2, 0, r9 + beqi/l r6, 0, tr0 /* loop */ + + add r5, r63, r4 + addi r0, 8, r0 + blink tr1, r63 /* shortstring */ +no_lddst: + /* r22 > r23: note that for r22 == r23 the sthi.q would clobber */ + /* bytes before the destination region. */ + stlo.q r2, 0, r4 + SHHI r4, r7, r4 + sthi.q r0, -1, r4 + beqi/l r6, 0, tr0 /* loop */ + + add r5, r63, r4 + addi r0, 8, r0 +shortstring: +#if __BYTE_ORDER != __LITTLE_ENDIAN + pta/l shortstring2,tr1 + byterev r4,r4 +#endif +shortstring2: + st.b r0,-8,r4 + andi r4,0xff,r5 + shlri r4,8,r4 + addi r0,1,r0 + bnei/l r5,0,tr1 + blink tr4,r63 /* return */ + + .balign 8 +loop: + stlo.q r0, 0, r5 + ldx.q r0, r20, r4 + addi r0, 16, r0 + sthi.q r0, -9, r5 + mcmpeq.b r4, r63, r6 + bnei/u r6, 0, tr1 /* shortstring */ + ldx.q r0, r21, r5 + stlo.q r0, -8, r4 + sthi.q r0, -1, r4 + mcmpeq.b r5, r63, r6 + beqi/l r6, 0, tr0 /* loop */ + + add r5, r63, r4 + addi r0, 8, r0 + blink tr1, r63 /* shortstring */ + + .size strcpy,.-strcpy + +libc_hidden_def(strcpy) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sh64/strlen.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sh64/strlen.S new file mode 100644 index 00000000..18f4164f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sh64/strlen.S @@ -0,0 +1,63 @@ +/* vi: set sw=8 ts=8: */ +/* + * libc/string/sh64/strlen.S + * + * Simplistic strlen() implementation for SHmedia. + * + * Copyright (C) 2003 Paul Mundt + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. The name of the above contributors may not be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + + .section .text..SHmedia32,"ax" + .globl strlen + .type strlen,@function + + .balign 16 +strlen: + ptabs r18, tr4 + + /* + * Note: We could easily deal with the NULL case here with a simple + * sanity check, though it seems that the behavior we want is to fault + * in the event that r2 == NULL, so we don't bother. + */ +/* beqi r2, 0, tr4 */ ! Sanity check + + movi -1, r0 + pta/l loop, tr0 +loop: + ld.b r2, 0, r1 + addi r2, 1, r2 + addi r0, 1, r0 + bnei/l r1, 0, tr0 + + or r0, r63, r2 + blink tr4, r63 + + .size strlen,.-strlen + +libc_hidden_def(strlen) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/Makefile new file mode 100644 index 00000000..0a95346f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir:=../../../ +top_builddir:=../../../ +all: objs +include $(top_builddir)Rules.mak +include ../Makefile.in +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/_glibc_inc.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/_glibc_inc.h new file mode 100644 index 00000000..e0aef52c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/_glibc_inc.h @@ -0,0 +1,27 @@ +/* + * Setup some glibc defines so we can just drop in the + * asm files from glibc without any modification. + */ + +#include +#include + +/* Is alignment really needed? */ + +#if __WORDSIZE == 32 +# define ENTRY_ALIGN 4 +#else +# define ENTRY_ALIGN 2 +#endif + +#define ENTRY(sym) \ + .global sym; \ + .align ENTRY_ALIGN; \ + .type sym,%function; \ + sym: + +#define LOC(sym) \ + .L ## sym + +#define END(sym) \ + .size sym,.-sym; diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/bcopy.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/bcopy.c new file mode 100644 index 00000000..9a455f33 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/bcopy.c @@ -0,0 +1 @@ +/* bcopy is in memcpy.S */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/bzero.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/bzero.c new file mode 100644 index 00000000..37f0f6f9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/bzero.c @@ -0,0 +1 @@ +/* bzero is in memset.S */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/memchr.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/memchr.S new file mode 100644 index 00000000..73e5101f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/memchr.S @@ -0,0 +1,13 @@ +#include "_glibc_inc.h" + +#if __WORDSIZE == 32 + +# if defined(__CONFIG_SPARC_V9B__) +# include "sparc32/sparcv9b/memchr.S" +# else +# include "sparc32/memchr.S" +# endif + +#else +# include "sparc64/memchr.S" +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/memcpy.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/memcpy.S new file mode 100644 index 00000000..478cb106 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/memcpy.S @@ -0,0 +1,19 @@ +#include "_glibc_inc.h" + +#if __WORDSIZE == 32 + +# if defined(__CONFIG_SPARC_V9B__) +# include "sparc32/sparcv9b/memcpy.S" +# else +# include "sparc32/memcpy.S" +# endif + +#else + +# if defined(__CONFIG_SPARC_V9B__) +# include "sparc64/sparcv9b/memcpy.S" +# else +# include "sparc64/memcpy.S" +#endif + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/memmove.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/memmove.c new file mode 100644 index 00000000..a8d2d499 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/memmove.c @@ -0,0 +1 @@ +/* memmove is in memcpy.S */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/memset.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/memset.S new file mode 100644 index 00000000..4aed7742 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/memset.S @@ -0,0 +1,13 @@ +#include "_glibc_inc.h" + +#if __WORDSIZE == 32 + +# if defined(__CONFIG_SPARC_V9B__) +# include "sparc32/sparcv9b/memset.S" +# else +# include "sparc32/memset.S" +# endif + +#else +# include "sparc64/memset.S" +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc32/memchr.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc32/memchr.S new file mode 100644 index 00000000..d926e978 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc32/memchr.S @@ -0,0 +1,142 @@ +/* memchr (str, ch, n) -- Return pointer to first occurrence of CH in STR less + than N. + For SPARC v7. + Copyright (C) 1996, 1999, 2000, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek and + David S. Miller . + This version is developed using the same algorithm as the fast C + version which carries the following introduction: + Based on strlen implementation by Torbjorn Granlund (tege@sics.se), + with help from Dan Sahlin (dan@sics.se) and + commentary by Jim Blandy (jimb@ai.mit.edu); + adaptation to memchr suggested by Dick Karpinski (dick@cca.ucsf.edu), + and implemented by Roland McGrath (roland@ai.mit.edu). + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + + .text + .align 4 +0: cmp %o2, 0 + be 9f + sethi %hi(0x80808080), %o4 + ldub [%o0], %g4 + cmp %g4, %o1 + be 1f + add %o0, 1, %o0 + subcc %o2, 1, %o2 + be 9f + andcc %o0, 3, %g0 + be 4f + or %o4, %lo(0x80808080), %o3 + ldub [%o0], %g4 + cmp %g4, %o1 + be 1f + add %o0, 1, %o0 + subcc %o2, 1, %o2 + be 9f + andcc %o0, 3, %g0 + be 5f + sethi %hi(0x01010101), %o5 + ldub [%o0], %g4 + cmp %g4, %o1 + be 1f + add %o0, 1, %o0 + subcc %o2, 1, %o2 + bne,a 7f + and %o2, 3, %g1 + retl + clr %o0 +1: retl + sub %o0, 1, %o0 + +ENTRY(memchr) + andcc %o1, 0xff, %o1 + sll %o1, 8, %g6 + andcc %o0, 3, %g0 + or %o1, %g6, %g6 + sll %g6, 16, %o3 + bne 0b + or %o3, %g6, %g2 + sethi %hi(0x80808080), %o4 + or %o4, %lo(0x80808080), %o3 +4: sethi %hi(0x01010101), %o5 +5: and %o2, 3, %g1 +7: andcc %o2, 0xfffffffc, %o2 + be 0f + or %o5, %lo(0x01010101), %g6 + ld [%o0], %g4 +6: xor %g4, %g2, %g5 + add %o0, 4, %o0 + sub %g5, %g6, %g5 + andcc %g5, %o3, %g0 + bne 8f + subcc %o2, 4, %o2 + bne,a 6b + ld [%o0], %g4 +0: cmp %g1, 0 +1: be 9f + add %o0, 4, %o0 + ldub [%o0 - 4], %g4 + cmp %g4, %o1 + be 4f + cmp %g1, 1 + be 9f + ldub [%o0 - 3], %g4 + cmp %g4, %o1 + be 3f + cmp %g1, 2 + be 9f + ldub [%o0 - 2], %g4 + cmp %g4, %o1 + be 2f + nop +9: retl + clr %o0 + + /* Check every byte. */ +8: srl %g4, 24, %g5 + and %g5, 0xff, %g5 + cmp %g5, %o1 + be 4f + srl %g4, 16, %g5 + and %g5, 0xff, %g5 + cmp %g5, %o1 + be 3f + srl %g4, 8, %g5 + and %g5, 0xff, %g5 + cmp %g5, %o1 + be 2f + and %g4, 0xff, %g5 + cmp %g5, %o1 + be 1f + cmp %o2, 0 + bne,a 6b + ld [%o0], %g4 + b 1b + cmp %g1, 0 +1: retl + sub %o0, 1, %o0 +2: retl + sub %o0, 2, %o0 +3: retl + sub %o0, 3, %o0 +4: retl + sub %o0, 4, %o0 +END(memchr) +libc_hidden_def(memchr) + +weak_alias(memchr,__ubp_memchr) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc32/memcpy.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc32/memcpy.S new file mode 100644 index 00000000..25a48844 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc32/memcpy.S @@ -0,0 +1,973 @@ +/* Copy SIZE bytes from SRC to DEST. + For SPARC v7. + Copyright (C) 1996, 1999, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by David S. Miller , + Eddie C. Dost and + Jakub Jelinek . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +/* Both these macros have to start with exactly the same insn */ +#define MOVE_BIGCHUNK(src, dst, offset, t0, t1, t2, t3, t4, t5, t6, t7) \ + ldd [%src + offset + 0x00], %t0; \ + ldd [%src + offset + 0x08], %t2; \ + ldd [%src + offset + 0x10], %t4; \ + ldd [%src + offset + 0x18], %t6; \ + st %t0, [%dst + offset + 0x00]; \ + st %t1, [%dst + offset + 0x04]; \ + st %t2, [%dst + offset + 0x08]; \ + st %t3, [%dst + offset + 0x0c]; \ + st %t4, [%dst + offset + 0x10]; \ + st %t5, [%dst + offset + 0x14]; \ + st %t6, [%dst + offset + 0x18]; \ + st %t7, [%dst + offset + 0x1c]; + +#define MOVE_BIGALIGNCHUNK(src, dst, offset, t0, t1, t2, t3, t4, t5, t6, t7) \ + ldd [%src + offset + 0x00], %t0; \ + ldd [%src + offset + 0x08], %t2; \ + ldd [%src + offset + 0x10], %t4; \ + ldd [%src + offset + 0x18], %t6; \ + std %t0, [%dst + offset + 0x00]; \ + std %t2, [%dst + offset + 0x08]; \ + std %t4, [%dst + offset + 0x10]; \ + std %t6, [%dst + offset + 0x18]; + +#define MOVE_LASTCHUNK(src, dst, offset, t0, t1, t2, t3) \ + ldd [%src - offset - 0x10], %t0; \ + ldd [%src - offset - 0x08], %t2; \ + st %t0, [%dst - offset - 0x10]; \ + st %t1, [%dst - offset - 0x0c]; \ + st %t2, [%dst - offset - 0x08]; \ + st %t3, [%dst - offset - 0x04]; + +#define MOVE_LASTALIGNCHUNK(src, dst, offset, t0, t1, t2, t3) \ + ldd [%src - offset - 0x10], %t0; \ + ldd [%src - offset - 0x08], %t2; \ + std %t0, [%dst - offset - 0x10]; \ + std %t2, [%dst - offset - 0x08]; + +#define MOVE_SHORTCHUNK(src, dst, offset, t0, t1) \ + ldub [%src - offset - 0x02], %t0; \ + ldub [%src - offset - 0x01], %t1; \ + stb %t0, [%dst - offset - 0x02]; \ + stb %t1, [%dst - offset - 0x01]; + +/* Both these macros have to start with exactly the same insn */ +#define RMOVE_BIGCHUNK(src, dst, offset, t0, t1, t2, t3, t4, t5, t6, t7) \ + ldd [%src - offset - 0x20], %t0; \ + ldd [%src - offset - 0x18], %t2; \ + ldd [%src - offset - 0x10], %t4; \ + ldd [%src - offset - 0x08], %t6; \ + st %t0, [%dst - offset - 0x20]; \ + st %t1, [%dst - offset - 0x1c]; \ + st %t2, [%dst - offset - 0x18]; \ + st %t3, [%dst - offset - 0x14]; \ + st %t4, [%dst - offset - 0x10]; \ + st %t5, [%dst - offset - 0x0c]; \ + st %t6, [%dst - offset - 0x08]; \ + st %t7, [%dst - offset - 0x04]; + +#define RMOVE_BIGALIGNCHUNK(src, dst, offset, t0, t1, t2, t3, t4, t5, t6, t7) \ + ldd [%src - offset - 0x20], %t0; \ + ldd [%src - offset - 0x18], %t2; \ + ldd [%src - offset - 0x10], %t4; \ + ldd [%src - offset - 0x08], %t6; \ + std %t0, [%dst - offset - 0x20]; \ + std %t2, [%dst - offset - 0x18]; \ + std %t4, [%dst - offset - 0x10]; \ + std %t6, [%dst - offset - 0x08]; + +#define RMOVE_LASTCHUNK(src, dst, offset, t0, t1, t2, t3) \ + ldd [%src + offset + 0x00], %t0; \ + ldd [%src + offset + 0x08], %t2; \ + st %t0, [%dst + offset + 0x00]; \ + st %t1, [%dst + offset + 0x04]; \ + st %t2, [%dst + offset + 0x08]; \ + st %t3, [%dst + offset + 0x0c]; + +#define RMOVE_SHORTCHUNK(src, dst, offset, t0, t1) \ + ldub [%src + offset + 0x00], %t0; \ + ldub [%src + offset + 0x01], %t1; \ + stb %t0, [%dst + offset + 0x00]; \ + stb %t1, [%dst + offset + 0x01]; + +#define SMOVE_CHUNK(src, dst, offset, t0, t1, t2, t3, t4, t5, t6, prev, shil, shir, offset2) \ + ldd [%src + offset + 0x00], %t0; \ + ldd [%src + offset + 0x08], %t2; \ + srl %t0, shir, %t5; \ + srl %t1, shir, %t6; \ + sll %t0, shil, %t0; \ + or %t5, %prev, %t5; \ + sll %t1, shil, %prev; \ + or %t6, %t0, %t0; \ + srl %t2, shir, %t1; \ + srl %t3, shir, %t6; \ + sll %t2, shil, %t2; \ + or %t1, %prev, %t1; \ + std %t4, [%dst + offset + offset2 - 0x04]; \ + std %t0, [%dst + offset + offset2 + 0x04]; \ + sll %t3, shil, %prev; \ + or %t6, %t2, %t4; + +#define SMOVE_ALIGNCHUNK(src, dst, offset, t0, t1, t2, t3, t4, t5, t6, prev, shil, shir, offset2) \ + ldd [%src + offset + 0x00], %t0; \ + ldd [%src + offset + 0x08], %t2; \ + srl %t0, shir, %t4; \ + srl %t1, shir, %t5; \ + sll %t0, shil, %t6; \ + or %t4, %prev, %t0; \ + sll %t1, shil, %prev; \ + or %t5, %t6, %t1; \ + srl %t2, shir, %t4; \ + srl %t3, shir, %t5; \ + sll %t2, shil, %t6; \ + or %t4, %prev, %t2; \ + sll %t3, shil, %prev; \ + or %t5, %t6, %t3; \ + std %t0, [%dst + offset + offset2 + 0x00]; \ + std %t2, [%dst + offset + offset2 + 0x08]; + + .text + .align 4 + +70: andcc %o1, 1, %g0 + be 4f + andcc %o1, 2, %g0 + + ldub [%o1 - 1], %g2 + sub %o1, 1, %o1 + stb %g2, [%o0 - 1] + sub %o2, 1, %o2 + be 3f + sub %o0, 1, %o0 +4: lduh [%o1 - 2], %g2 + sub %o1, 2, %o1 + sth %g2, [%o0 - 2] + sub %o2, 2, %o2 + b 3f + sub %o0, 2, %o0 + +#ifdef __UCLIBC_SUSV3_LEGACY__ +ENTRY(bcopy) + mov %o0, %o3 + mov %o1, %o0 + mov %o3, %o1 +END(bcopy) +#endif + +ENTRY(memmove) + cmp %o0, %o1 + st %o0, [%sp + 64] + bleu 9f + sub %o0, %o1, %o4 + + add %o1, %o2, %o3 + cmp %o3, %o0 + bleu 0f + andcc %o4, 3, %o5 + + add %o1, %o2, %o1 + add %o0, %o2, %o0 + bne 77f + cmp %o2, 15 + bleu 91f + andcc %o1, 3, %g0 + bne 70b +3: andcc %o1, 4, %g0 + + be 2f + mov %o2, %g1 + + ld [%o1 - 4], %o4 + sub %g1, 4, %g1 + st %o4, [%o0 - 4] + sub %o1, 4, %o1 + sub %o0, 4, %o0 +2: andcc %g1, 0xffffff80, %g6 + be 3f + andcc %o0, 4, %g0 + + be 74f + 4 +5: RMOVE_BIGCHUNK(o1, o0, 0x00, o2, o3, o4, o5, g2, g3, g4, g5) + RMOVE_BIGCHUNK(o1, o0, 0x20, o2, o3, o4, o5, g2, g3, g4, g5) + RMOVE_BIGCHUNK(o1, o0, 0x40, o2, o3, o4, o5, g2, g3, g4, g5) + RMOVE_BIGCHUNK(o1, o0, 0x60, o2, o3, o4, o5, g2, g3, g4, g5) + subcc %g6, 128, %g6 + sub %o1, 128, %o1 + bne 5b + sub %o0, 128, %o0 + +3: andcc %g1, 0x70, %g6 + be 72f + andcc %g1, 8, %g0 + + srl %g6, 1, %o4 + mov %o7, %g2 + add %g6, %o4, %o4 +101: call 100f + sub %o1, %g6, %o1 + mov %g2, %o7 + jmpl %o5 + (72f - 101b), %g0 + sub %o0, %g6, %o0 + +71: RMOVE_LASTCHUNK(o1, o0, 0x60, g2, g3, g4, g5) + RMOVE_LASTCHUNK(o1, o0, 0x50, g2, g3, g4, g5) + RMOVE_LASTCHUNK(o1, o0, 0x40, g2, g3, g4, g5) + RMOVE_LASTCHUNK(o1, o0, 0x30, g2, g3, g4, g5) + RMOVE_LASTCHUNK(o1, o0, 0x20, g2, g3, g4, g5) + RMOVE_LASTCHUNK(o1, o0, 0x10, g2, g3, g4, g5) + RMOVE_LASTCHUNK(o1, o0, 0x00, g2, g3, g4, g5) +72: be 73f + andcc %g1, 4, %g0 + + ldd [%o1 - 0x08], %g2 + sub %o0, 8, %o0 + sub %o1, 8, %o1 + st %g2, [%o0] + st %g3, [%o0 + 0x04] +73: be 1f + andcc %g1, 2, %g0 + + ld [%o1 - 4], %g2 + sub %o1, 4, %o1 + st %g2, [%o0 - 4] + sub %o0, 4, %o0 +1: be 1f + andcc %g1, 1, %g0 + + lduh [%o1 - 2], %g2 + sub %o1, 2, %o1 + sth %g2, [%o0 - 2] + sub %o0, 2, %o0 +1: be 1f + nop + + ldub [%o1 - 1], %g2 + stb %g2, [%o0 - 1] +1: retl + ld [%sp + 64], %o0 + +74: RMOVE_BIGALIGNCHUNK(o1, o0, 0x00, o2, o3, o4, o5, g2, g3, g4, g5) + RMOVE_BIGALIGNCHUNK(o1, o0, 0x20, o2, o3, o4, o5, g2, g3, g4, g5) + RMOVE_BIGALIGNCHUNK(o1, o0, 0x40, o2, o3, o4, o5, g2, g3, g4, g5) + RMOVE_BIGALIGNCHUNK(o1, o0, 0x60, o2, o3, o4, o5, g2, g3, g4, g5) + subcc %g6, 128, %g6 + sub %o1, 128, %o1 + bne 74b + sub %o0, 128, %o0 + + andcc %g1, 0x70, %g6 + be 72b + andcc %g1, 8, %g0 + + srl %g6, 1, %o4 + mov %o7, %g2 + add %g6, %o4, %o4 +102: call 100f + sub %o1, %g6, %o1 + mov %g2, %o7 + jmpl %o5 + (72b - 102b), %g0 + sub %o0, %g6, %o0 + +75: and %o2, 0xe, %o3 + mov %o7, %g2 + sll %o3, 3, %o4 + sub %o0, %o3, %o0 +103: call 100f + sub %o1, %o3, %o1 + mov %g2, %o7 + jmpl %o5 + (76f - 103b), %g0 + andcc %o2, 1, %g0 + + RMOVE_SHORTCHUNK(o1, o0, 0x0c, g2, g3) + RMOVE_SHORTCHUNK(o1, o0, 0x0a, g2, g3) + RMOVE_SHORTCHUNK(o1, o0, 0x08, g2, g3) + RMOVE_SHORTCHUNK(o1, o0, 0x06, g2, g3) + RMOVE_SHORTCHUNK(o1, o0, 0x04, g2, g3) + RMOVE_SHORTCHUNK(o1, o0, 0x02, g2, g3) + RMOVE_SHORTCHUNK(o1, o0, 0x00, g2, g3) + +76: be 1f + nop + ldub [%o1 - 1], %g2 + stb %g2, [%o0 - 1] +1: retl + ld [%sp + 64], %o0 + +91: bne 75b + andcc %o2, 8, %g0 + + be 1f + andcc %o2, 4, %g0 + + ld [%o1 - 0x08], %g2 + ld [%o1 - 0x04], %g3 + sub %o1, 8, %o1 + st %g2, [%o0 - 0x08] + st %g3, [%o0 - 0x04] + sub %o0, 8, %o0 +1: b 73b + mov %o2, %g1 + +77: cmp %o2, 15 + bleu 75b + andcc %o0, 3, %g0 + be 64f + andcc %o0, 1, %g0 + be 63f + andcc %o0, 2, %g0 + ldub [%o1 - 1], %g5 + sub %o1, 1, %o1 + stb %g5, [%o0 - 1] + sub %o0, 1, %o0 + be 64f + sub %o2, 1, %o2 + +63: ldub [%o1 - 1], %g5 + sub %o1, 2, %o1 + stb %g5, [%o0 - 1] + sub %o0, 2, %o0 + ldub [%o1], %g5 + sub %o2, 2, %o2 + stb %g5, [%o0] +64: and %o1, 3, %g2 + and %o1, -4, %o1 + and %o2, 0xc, %g3 + add %o1, 4, %o1 + cmp %g3, 4 + sll %g2, 3, %g4 + mov 32, %g2 + be 4f + sub %g2, %g4, %g6 + + blu 3f + cmp %g3, 8 + + be 2f + srl %o2, 2, %g3 + + ld [%o1 - 4], %o3 + add %o0, -8, %o0 + ld [%o1 - 8], %o4 + add %o1, -16, %o1 + b 7f + add %g3, 1, %g3 +2: ld [%o1 - 4], %o4 + add %o0, -4, %o0 + ld [%o1 - 8], %g1 + add %o1, -12, %o1 + b 8f + add %g3, 2, %g3 +3: ld [%o1 - 4], %o5 + add %o0, -12, %o0 + ld [%o1 - 8], %o3 + add %o1, -20, %o1 + b 6f + srl %o2, 2, %g3 +4: ld [%o1 - 4], %g1 + srl %o2, 2, %g3 + ld [%o1 - 8], %o5 + add %o1, -24, %o1 + add %o0, -16, %o0 + add %g3, -1, %g3 + + ld [%o1 + 12], %o3 +5: sll %o5, %g4, %g2 + srl %g1, %g6, %g5 + or %g2, %g5, %g2 + st %g2, [%o0 + 12] +6: ld [%o1 + 8], %o4 + sll %o3, %g4, %g2 + srl %o5, %g6, %g5 + or %g2, %g5, %g2 + st %g2, [%o0 + 8] +7: ld [%o1 + 4], %g1 + sll %o4, %g4, %g2 + srl %o3, %g6, %g5 + or %g2, %g5, %g2 + st %g2, [%o0 + 4] +8: ld [%o1], %o5 + sll %g1, %g4, %g2 + srl %o4, %g6, %g5 + addcc %g3, -4, %g3 + or %g2, %g5, %g2 + add %o1, -16, %o1 + st %g2, [%o0] + add %o0, -16, %o0 + bne,a 5b + ld [%o1 + 12], %o3 + sll %o5, %g4, %g2 + srl %g1, %g6, %g5 + srl %g4, 3, %g3 + or %g2, %g5, %g2 + add %o1, %g3, %o1 + andcc %o2, 2, %g0 + st %g2, [%o0 + 12] + be 1f + andcc %o2, 1, %g0 + + ldub [%o1 + 15], %g5 + add %o1, -2, %o1 + stb %g5, [%o0 + 11] + add %o0, -2, %o0 + ldub [%o1 + 16], %g5 + stb %g5, [%o0 + 12] +1: be 1f + nop + ldub [%o1 + 15], %g5 + stb %g5, [%o0 + 11] +1: retl + ld [%sp + 64], %o0 + +78: andcc %o1, 1, %g0 + be 4f + andcc %o1, 2, %g0 + + ldub [%o1], %g2 + add %o1, 1, %o1 + stb %g2, [%o0] + sub %o2, 1, %o2 + bne 3f + add %o0, 1, %o0 +4: lduh [%o1], %g2 + add %o1, 2, %o1 + sth %g2, [%o0] + sub %o2, 2, %o2 + b 3f + add %o0, 2, %o0 +END(memmove) +libc_hidden_def(memmove) + +ENTRY(memcpy) /* %o0=dst %o1=src %o2=len */ + sub %o0, %o1, %o4 + st %o0, [%sp + 64] +9: andcc %o4, 3, %o5 +0: bne 86f + cmp %o2, 15 + + bleu 90f + andcc %o1, 3, %g0 + + bne 78b +3: andcc %o1, 4, %g0 + + be 2f + mov %o2, %g1 + + ld [%o1], %o4 + sub %g1, 4, %g1 + st %o4, [%o0] + add %o1, 4, %o1 + add %o0, 4, %o0 +2: andcc %g1, 0xffffff80, %g6 + be 3f + andcc %o0, 4, %g0 + + be 82f + 4 +5: MOVE_BIGCHUNK(o1, o0, 0x00, o2, o3, o4, o5, g2, g3, g4, g5) + MOVE_BIGCHUNK(o1, o0, 0x20, o2, o3, o4, o5, g2, g3, g4, g5) + MOVE_BIGCHUNK(o1, o0, 0x40, o2, o3, o4, o5, g2, g3, g4, g5) + MOVE_BIGCHUNK(o1, o0, 0x60, o2, o3, o4, o5, g2, g3, g4, g5) + subcc %g6, 128, %g6 + add %o1, 128, %o1 + bne 5b + add %o0, 128, %o0 +3: andcc %g1, 0x70, %g6 + be 80f + andcc %g1, 8, %g0 + + srl %g6, 1, %o4 + mov %o7, %g2 + add %g6, %o4, %o4 + add %o1, %g6, %o1 +104: call 100f + add %o0, %g6, %o0 + jmpl %o5 + (80f - 104b), %g0 + mov %g2, %o7 + +79: MOVE_LASTCHUNK(o1, o0, 0x60, g2, g3, g4, g5) + MOVE_LASTCHUNK(o1, o0, 0x50, g2, g3, g4, g5) + MOVE_LASTCHUNK(o1, o0, 0x40, g2, g3, g4, g5) + MOVE_LASTCHUNK(o1, o0, 0x30, g2, g3, g4, g5) + MOVE_LASTCHUNK(o1, o0, 0x20, g2, g3, g4, g5) + MOVE_LASTCHUNK(o1, o0, 0x10, g2, g3, g4, g5) + MOVE_LASTCHUNK(o1, o0, 0x00, g2, g3, g4, g5) + +80: be 81f + andcc %g1, 4, %g0 + + ldd [%o1], %g2 + add %o0, 8, %o0 + st %g2, [%o0 - 0x08] + add %o1, 8, %o1 + st %g3, [%o0 - 0x04] + +81: be 1f + andcc %g1, 2, %g0 + + ld [%o1], %g2 + add %o1, 4, %o1 + st %g2, [%o0] + add %o0, 4, %o0 +1: be 1f + andcc %g1, 1, %g0 + + lduh [%o1], %g2 + add %o1, 2, %o1 + sth %g2, [%o0] + add %o0, 2, %o0 +1: be 1f + nop + + ldub [%o1], %g2 + stb %g2, [%o0] +1: retl + ld [%sp + 64], %o0 + +82: /* ldd_std */ + MOVE_BIGALIGNCHUNK(o1, o0, 0x00, o2, o3, o4, o5, g2, g3, g4, g5) + MOVE_BIGALIGNCHUNK(o1, o0, 0x20, o2, o3, o4, o5, g2, g3, g4, g5) + MOVE_BIGALIGNCHUNK(o1, o0, 0x40, o2, o3, o4, o5, g2, g3, g4, g5) + MOVE_BIGALIGNCHUNK(o1, o0, 0x60, o2, o3, o4, o5, g2, g3, g4, g5) + subcc %g6, 128, %g6 + add %o1, 128, %o1 + bne 82b + add %o0, 128, %o0 + + andcc %g1, 0x70, %g6 + be 84f + andcc %g1, 8, %g0 + + mov %o7, %g2 +111: call 110f + add %o1, %g6, %o1 + mov %g2, %o7 + jmpl %o5 + (84f - 111b), %g0 + add %o0, %g6, %o0 + +83: MOVE_LASTALIGNCHUNK(o1, o0, 0x60, g2, g3, g4, g5) + MOVE_LASTALIGNCHUNK(o1, o0, 0x50, g2, g3, g4, g5) + MOVE_LASTALIGNCHUNK(o1, o0, 0x40, g2, g3, g4, g5) + MOVE_LASTALIGNCHUNK(o1, o0, 0x30, g2, g3, g4, g5) + MOVE_LASTALIGNCHUNK(o1, o0, 0x20, g2, g3, g4, g5) + MOVE_LASTALIGNCHUNK(o1, o0, 0x10, g2, g3, g4, g5) + MOVE_LASTALIGNCHUNK(o1, o0, 0x00, g2, g3, g4, g5) + +84: be 85f + andcc %g1, 4, %g0 + + ldd [%o1], %g2 + add %o0, 8, %o0 + std %g2, [%o0 - 0x08] + add %o1, 8, %o1 +85: be 1f + andcc %g1, 2, %g0 + + ld [%o1], %g2 + add %o1, 4, %o1 + st %g2, [%o0] + add %o0, 4, %o0 +1: be 1f + andcc %g1, 1, %g0 + + lduh [%o1], %g2 + add %o1, 2, %o1 + sth %g2, [%o0] + add %o0, 2, %o0 +1: be 1f + nop + + ldub [%o1], %g2 + stb %g2, [%o0] +1: retl + ld [%sp + 64], %o0 + +86: cmp %o2, 6 + bleu 88f + + cmp %o2, 256 + bcc 87f + + andcc %o0, 3, %g0 + be 61f + andcc %o0, 1, %g0 + be 60f + andcc %o0, 2, %g0 + + ldub [%o1], %g5 + add %o1, 1, %o1 + stb %g5, [%o0] + sub %o2, 1, %o2 + bne 61f + add %o0, 1, %o0 +60: ldub [%o1], %g3 + add %o1, 2, %o1 + stb %g3, [%o0] + sub %o2, 2, %o2 + ldub [%o1 - 1], %g3 + add %o0, 2, %o0 + stb %g3, [%o0 - 1] +61: and %o1, 3, %g2 + and %o2, 0xc, %g3 + and %o1, -4, %o1 + cmp %g3, 4 + sll %g2, 3, %g4 + mov 32, %g2 + be 4f + sub %g2, %g4, %g6 + + blu 3f + cmp %g3, 0x8 + + be 2f + srl %o2, 2, %g3 + + ld [%o1], %o3 + add %o0, -8, %o0 + ld [%o1 + 4], %o4 + b 8f + add %g3, 1, %g3 +2: ld [%o1], %o4 + add %o0, -12, %o0 + ld [%o1 + 4], %o5 + add %g3, 2, %g3 + b 9f + add %o1, -4, %o1 +3: ld [%o1], %g1 + add %o0, -4, %o0 + ld [%o1 + 4], %o3 + srl %o2, 2, %g3 + b 7f + add %o1, 4, %o1 +4: ld [%o1], %o5 + cmp %o2, 7 + ld [%o1 + 4], %g1 + srl %o2, 2, %g3 + bleu 10f + add %o1, 8, %o1 + + ld [%o1], %o3 + add %g3, -1, %g3 +5: sll %o5, %g4, %g2 + srl %g1, %g6, %g5 + or %g2, %g5, %g2 + st %g2, [%o0] +7: ld [%o1 + 4], %o4 + sll %g1, %g4, %g2 + srl %o3, %g6, %g5 + or %g2, %g5, %g2 + st %g2, [%o0 + 4] +8: ld [%o1 + 8], %o5 + sll %o3, %g4, %g2 + srl %o4, %g6, %g5 + or %g2, %g5, %g2 + st %g2, [%o0 + 8] +9: ld [%o1 + 12], %g1 + sll %o4, %g4, %g2 + srl %o5, %g6, %g5 + addcc %g3, -4, %g3 + or %g2, %g5, %g2 + add %o1, 16, %o1 + st %g2, [%o0 + 12] + add %o0, 16, %o0 + bne,a 5b + ld [%o1], %o3 +10: sll %o5, %g4, %g2 + srl %g1, %g6, %g5 + srl %g6, 3, %g3 + or %g2, %g5, %g2 + sub %o1, %g3, %o1 + andcc %o2, 2, %g0 + st %g2, [%o0] + be 1f + andcc %o2, 1, %g0 + + ldub [%o1], %g2 + add %o1, 2, %o1 + stb %g2, [%o0 + 4] + add %o0, 2, %o0 + ldub [%o1 - 1], %g2 + stb %g2, [%o0 + 3] +1: be 1f + nop + ldub [%o1], %g2 + stb %g2, [%o0 + 4] +1: retl + ld [%sp + 64], %o0 + +87: andcc %o1, 3, %g0 + be 3f + andcc %o1, 1, %g0 + + be 4f + andcc %o1, 2, %g0 + + ldub [%o1], %g2 + add %o1, 1, %o1 + stb %g2, [%o0] + sub %o2, 1, %o2 + bne 3f + add %o0, 1, %o0 +4: lduh [%o1], %g2 + add %o1, 2, %o1 + srl %g2, 8, %g3 + sub %o2, 2, %o2 + stb %g3, [%o0] + add %o0, 2, %o0 + stb %g2, [%o0 - 1] +3: andcc %o1, 4, %g0 + + bne 2f + cmp %o5, 1 + + ld [%o1], %o4 + srl %o4, 24, %g2 + stb %g2, [%o0] + srl %o4, 16, %g3 + stb %g3, [%o0 + 1] + srl %o4, 8, %g2 + stb %g2, [%o0 + 2] + sub %o2, 4, %o2 + stb %o4, [%o0 + 3] + add %o1, 4, %o1 + add %o0, 4, %o0 +2: be 33f + cmp %o5, 2 + be 32f + sub %o2, 4, %o2 +31: ld [%o1], %g2 + add %o1, 4, %o1 + srl %g2, 24, %g3 + and %o0, 7, %g5 + stb %g3, [%o0] + cmp %g5, 7 + sll %g2, 8, %g1 + add %o0, 4, %o0 + be 41f + and %o2, 0xffffffc0, %o3 + ld [%o0 - 7], %o4 +4: SMOVE_CHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g6, g1, 8, 24, -3) + SMOVE_CHUNK(o1, o0, 0x10, g2, g3, g4, g5, o4, o5, g6, g1, 8, 24, -3) + SMOVE_CHUNK(o1, o0, 0x20, g2, g3, g4, g5, o4, o5, g6, g1, 8, 24, -3) + SMOVE_CHUNK(o1, o0, 0x30, g2, g3, g4, g5, o4, o5, g6, g1, 8, 24, -3) + subcc %o3, 64, %o3 + add %o1, 64, %o1 + bne 4b + add %o0, 64, %o0 + + andcc %o2, 0x30, %o3 + be,a 1f + srl %g1, 16, %g2 +4: SMOVE_CHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g6, g1, 8, 24, -3) + subcc %o3, 16, %o3 + add %o1, 16, %o1 + bne 4b + add %o0, 16, %o0 + + srl %g1, 16, %g2 +1: st %o4, [%o0 - 7] + sth %g2, [%o0 - 3] + srl %g1, 8, %g4 + b 88f + stb %g4, [%o0 - 1] +32: ld [%o1], %g2 + add %o1, 4, %o1 + srl %g2, 16, %g3 + and %o0, 7, %g5 + sth %g3, [%o0] + cmp %g5, 6 + sll %g2, 16, %g1 + add %o0, 4, %o0 + be 42f + and %o2, 0xffffffc0, %o3 + ld [%o0 - 6], %o4 +4: SMOVE_CHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g6, g1, 16, 16, -2) + SMOVE_CHUNK(o1, o0, 0x10, g2, g3, g4, g5, o4, o5, g6, g1, 16, 16, -2) + SMOVE_CHUNK(o1, o0, 0x20, g2, g3, g4, g5, o4, o5, g6, g1, 16, 16, -2) + SMOVE_CHUNK(o1, o0, 0x30, g2, g3, g4, g5, o4, o5, g6, g1, 16, 16, -2) + subcc %o3, 64, %o3 + add %o1, 64, %o1 + bne 4b + add %o0, 64, %o0 + + andcc %o2, 0x30, %o3 + be,a 1f + srl %g1, 16, %g2 +4: SMOVE_CHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g6, g1, 16, 16, -2) + subcc %o3, 16, %o3 + add %o1, 16, %o1 + bne 4b + add %o0, 16, %o0 + + srl %g1, 16, %g2 +1: st %o4, [%o0 - 6] + b 88f + sth %g2, [%o0 - 2] +33: ld [%o1], %g2 + sub %o2, 4, %o2 + srl %g2, 24, %g3 + and %o0, 7, %g5 + stb %g3, [%o0] + cmp %g5, 5 + srl %g2, 8, %g4 + sll %g2, 24, %g1 + sth %g4, [%o0 + 1] + add %o1, 4, %o1 + be 43f + and %o2, 0xffffffc0, %o3 + + ld [%o0 - 1], %o4 + add %o0, 4, %o0 +4: SMOVE_CHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g6, g1, 24, 8, -1) + SMOVE_CHUNK(o1, o0, 0x10, g2, g3, g4, g5, o4, o5, g6, g1, 24, 8, -1) + SMOVE_CHUNK(o1, o0, 0x20, g2, g3, g4, g5, o4, o5, g6, g1, 24, 8, -1) + SMOVE_CHUNK(o1, o0, 0x30, g2, g3, g4, g5, o4, o5, g6, g1, 24, 8, -1) + subcc %o3, 64, %o3 + add %o1, 64, %o1 + bne 4b + add %o0, 64, %o0 + + andcc %o2, 0x30, %o3 + be,a 1f + srl %g1, 24, %g2 +4: SMOVE_CHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g6, g1, 24, 8, -1) + subcc %o3, 16, %o3 + add %o1, 16, %o1 + bne 4b + add %o0, 16, %o0 + + srl %g1, 24, %g2 +1: st %o4, [%o0 - 5] + b 88f + stb %g2, [%o0 - 1] +41: SMOVE_ALIGNCHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g6, g1, 8, 24, -3) + SMOVE_ALIGNCHUNK(o1, o0, 0x10, g2, g3, g4, g5, o4, o5, g6, g1, 8, 24, -3) + SMOVE_ALIGNCHUNK(o1, o0, 0x20, g2, g3, g4, g5, o4, o5, g6, g1, 8, 24, -3) + SMOVE_ALIGNCHUNK(o1, o0, 0x30, g2, g3, g4, g5, o4, o5, g6, g1, 8, 24, -3) + subcc %o3, 64, %o3 + add %o1, 64, %o1 + bne 41b + add %o0, 64, %o0 + + andcc %o2, 0x30, %o3 + be,a 1f + srl %g1, 16, %g2 +4: SMOVE_ALIGNCHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g6, g1, 8, 24, -3) + subcc %o3, 16, %o3 + add %o1, 16, %o1 + bne 4b + add %o0, 16, %o0 + + srl %g1, 16, %g2 +1: sth %g2, [%o0 - 3] + srl %g1, 8, %g4 + b 88f + stb %g4, [%o0 - 1] +43: SMOVE_ALIGNCHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g6, g1, 24, 8, 3) + SMOVE_ALIGNCHUNK(o1, o0, 0x10, g2, g3, g4, g5, o4, o5, g6, g1, 24, 8, 3) + SMOVE_ALIGNCHUNK(o1, o0, 0x20, g2, g3, g4, g5, o4, o5, g6, g1, 24, 8, 3) + SMOVE_ALIGNCHUNK(o1, o0, 0x30, g2, g3, g4, g5, o4, o5, g6, g1, 24, 8, 3) + subcc %o3, 64, %o3 + add %o1, 64, %o1 + bne 43b + add %o0, 64, %o0 + + andcc %o2, 0x30, %o3 + be,a 1f + srl %g1, 24, %g2 +4: SMOVE_ALIGNCHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g6, g1, 24, 8, 3) + subcc %o3, 16, %o3 + add %o1, 16, %o1 + bne 4b + add %o0, 16, %o0 + + srl %g1, 24, %g2 +1: stb %g2, [%o0 + 3] + b 88f + add %o0, 4, %o0 +42: SMOVE_ALIGNCHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g6, g1, 16, 16, -2) + SMOVE_ALIGNCHUNK(o1, o0, 0x10, g2, g3, g4, g5, o4, o5, g6, g1, 16, 16, -2) + SMOVE_ALIGNCHUNK(o1, o0, 0x20, g2, g3, g4, g5, o4, o5, g6, g1, 16, 16, -2) + SMOVE_ALIGNCHUNK(o1, o0, 0x30, g2, g3, g4, g5, o4, o5, g6, g1, 16, 16, -2) + subcc %o3, 64, %o3 + add %o1, 64, %o1 + bne 42b + add %o0, 64, %o0 + + andcc %o2, 0x30, %o3 + be,a 1f + srl %g1, 16, %g2 +4: SMOVE_ALIGNCHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g6, g1, 16, 16, -2) + subcc %o3, 16, %o3 + add %o1, 16, %o1 + bne 4b + add %o0, 16, %o0 + + srl %g1, 16, %g2 +1: sth %g2, [%o0 - 2] + + /* Fall through */ + +88: and %o2, 0xe, %o3 + mov %o7, %g2 + sll %o3, 3, %o4 + add %o0, %o3, %o0 +106: call 100f + add %o1, %o3, %o1 + mov %g2, %o7 + jmpl %o5 + (89f - 106b), %g0 + andcc %o2, 1, %g0 + + MOVE_SHORTCHUNK(o1, o0, 0x0c, g2, g3) + MOVE_SHORTCHUNK(o1, o0, 0x0a, g2, g3) + MOVE_SHORTCHUNK(o1, o0, 0x08, g2, g3) + MOVE_SHORTCHUNK(o1, o0, 0x06, g2, g3) + MOVE_SHORTCHUNK(o1, o0, 0x04, g2, g3) + MOVE_SHORTCHUNK(o1, o0, 0x02, g2, g3) + MOVE_SHORTCHUNK(o1, o0, 0x00, g2, g3) + +89: be 1f + nop + + ldub [%o1], %g2 + stb %g2, [%o0] +1: retl + ld [%sp + 64], %o0 + +90: bne 88b + andcc %o2, 8, %g0 + + be 1f + andcc %o2, 4, %g0 + + ld [%o1 + 0x00], %g2 + ld [%o1 + 0x04], %g3 + add %o1, 8, %o1 + st %g2, [%o0 + 0x00] + st %g3, [%o0 + 0x04] + add %o0, 8, %o0 +1: b 81b + mov %o2, %g1 + +100: retl + sub %o7, %o4, %o5 +110: retl + sub %o7, %g6, %o5 +END(memcpy) +libc_hidden_def(memcpy) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc32/memset.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc32/memset.S new file mode 100644 index 00000000..6c6424cf --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc32/memset.S @@ -0,0 +1,157 @@ +/* Set a block of memory to some byte value. + For SPARC v7. + Copyright (C) 1996, 1999, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by David S. Miller and + Jakub Jelinek . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + + /* Store 64 bytes at (BASE + OFFSET) using value SOURCE. */ +#define ZERO_BIG_BLOCK(base, offset, source) \ + std source, [base + offset + 0x00]; \ + std source, [base + offset + 0x08]; \ + std source, [base + offset + 0x10]; \ + std source, [base + offset + 0x18]; \ + std source, [base + offset + 0x20]; \ + std source, [base + offset + 0x28]; \ + std source, [base + offset + 0x30]; \ + std source, [base + offset + 0x38]; + +#define ZERO_LAST_BLOCKS(base, offset, source) \ + std source, [base - offset - 0x38]; \ + std source, [base - offset - 0x30]; \ + std source, [base - offset - 0x28]; \ + std source, [base - offset - 0x20]; \ + std source, [base - offset - 0x18]; \ + std source, [base - offset - 0x10]; \ + std source, [base - offset - 0x08]; \ + std source, [base - offset - 0x00]; + + .text + .align 4 +#ifdef __UCLIBC_SUSV3_LEGACY__ +ENTRY(bzero) + b 1f + mov %g0, %g3 +#endif + +3: cmp %o2, 3 + be 2f + stb %g3, [%o0] + + cmp %o2, 2 + be 2f + stb %g3, [%o0 + 0x01] + + stb %g3, [%o0 + 0x02] +2: sub %o2, 4, %o2 + add %o1, %o2, %o1 + b 4f + sub %o0, %o2, %o0 +#ifdef __UCLIBC_SUSV3_LEGACY__ +END(bzero) +#endif + +ENTRY(memset) + and %o1, 0xff, %g3 + sll %g3, 8, %g2 + or %g3, %g2, %g3 + sll %g3, 16, %g2 + or %g3, %g2, %g3 + orcc %o2, %g0, %o1 +1: cmp %o1, 7 + bleu 7f + mov %o0, %g1 + + andcc %o0, 3, %o2 + bne 3b +4: andcc %o0, 4, %g0 + + be 2f + mov %g3, %g2 + + st %g3, [%o0] + sub %o1, 4, %o1 + add %o0, 4, %o0 +2: andcc %o1, 0xffffff80, %o3 + be 9f + andcc %o1, 0x78, %o2 +4: ZERO_BIG_BLOCK (%o0, 0x00, %g2) + subcc %o3, 128, %o3 + ZERO_BIG_BLOCK (%o0, 0x40, %g2) + bne 4b + add %o0, 128, %o0 + + orcc %o2, %g0, %g0 +9: be 6f + andcc %o1, 7, %o1 + + mov %o7, %g4 +101: call 100f + srl %o2, 1, %o3 + mov %g4, %o7 + jmpl %o4 + (20f + 64 - 101b), %g0 + add %o0, %o2, %o0 + +100: retl + sub %o7, %o3, %o4 + +20: ZERO_LAST_BLOCKS(%o0, 0x48, %g2) + ZERO_LAST_BLOCKS(%o0, 0x08, %g2) + +6: be 8f + andcc %o1, 4, %g0 + be 1f + andcc %o1, 2, %g0 + st %g3, [%o0] + add %o0, 4, %o0 +1: be 1f + andcc %o1, 1, %g0 + sth %g3, [%o0] + add %o0, 2, %o0 +1: bne,a 8f + stb %g3, [%o0] +8: retl + mov %g1, %o0 +7: orcc %o1, 0, %g0 + be 0f + subcc %o1, 1, %o1 + stb %g3, [%o0] + be 0f + subcc %o1, 1, %o1 + stb %g3, [%o0 + 1] + be 0f + subcc %o1, 1, %o1 + stb %g3, [%o0 + 2] + be 0f + subcc %o1, 1, %o1 + stb %g3, [%o0 + 3] + be 0f + subcc %o1, 1, %o1 + stb %g3, [%o0 + 4] + be 0f + subcc %o1, 1, %o1 + stb %g3, [%o0 + 5] + be 0f + subcc %o1, 1, %o1 + stb %g3, [%o0 + 6] +0: retl + nop +END(memset) +libc_hidden_def(memset) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc32/sparcv9b/memchr.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc32/sparcv9b/memchr.S new file mode 100644 index 00000000..43a16ff1 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc32/sparcv9b/memchr.S @@ -0,0 +1,4 @@ +#define ASI_PNF 0x82 +#define ASI_BLK_P 0xf0 +#define XCC icc +#include "../../sparc64/memchr.S" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc32/sparcv9b/memcpy.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc32/sparcv9b/memcpy.S new file mode 100644 index 00000000..2024869d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc32/sparcv9b/memcpy.S @@ -0,0 +1,4 @@ +#define ASI_PNF 0x82 +#define ASI_BLK_P 0xf0 +#define XCC icc +#include "../../sparc64/sparcv9b/memcpy.S" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc32/sparcv9b/memset.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc32/sparcv9b/memset.S new file mode 100644 index 00000000..e4917317 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc32/sparcv9b/memset.S @@ -0,0 +1,4 @@ +#define ASI_PNF 0x82 +#define ASI_BLK_P 0xf0 +#define XCC icc +#include "../../sparc64/memset.S" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc32/sparcv9b/stpcpy.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc32/sparcv9b/stpcpy.S new file mode 100644 index 00000000..17ffa5e4 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc32/sparcv9b/stpcpy.S @@ -0,0 +1,4 @@ +#define ASI_PNF 0x82 +#define ASI_BLK_P 0xf0 +#define XCC icc +#include "../../sparc64/stpcpy.S" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc32/sparcv9b/strcat.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc32/sparcv9b/strcat.S new file mode 100644 index 00000000..9ed125a4 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc32/sparcv9b/strcat.S @@ -0,0 +1,4 @@ +#define ASI_PNF 0x82 +#define ASI_BLK_P 0xf0 +#define XCC icc +#include "../../sparc64/strcat.S" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc32/sparcv9b/strchr.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc32/sparcv9b/strchr.S new file mode 100644 index 00000000..6b2727a1 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc32/sparcv9b/strchr.S @@ -0,0 +1,4 @@ +#define ASI_PNF 0x82 +#define ASI_BLK_P 0xf0 +#define XCC icc +#include "../../sparc64/strchr.S" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc32/sparcv9b/strcmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc32/sparcv9b/strcmp.S new file mode 100644 index 00000000..854403ff --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc32/sparcv9b/strcmp.S @@ -0,0 +1,4 @@ +#define ASI_PNF 0x82 +#define ASI_BLK_P 0xf0 +#define XCC icc +#include "../../sparc64/strcmp.S" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc32/sparcv9b/strcpy.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc32/sparcv9b/strcpy.S new file mode 100644 index 00000000..e8102bde --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc32/sparcv9b/strcpy.S @@ -0,0 +1,4 @@ +#define ASI_PNF 0x82 +#define ASI_BLK_P 0xf0 +#define XCC icc +#include "../../sparc64/strcpy.S" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc32/sparcv9b/strlen.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc32/sparcv9b/strlen.S new file mode 100644 index 00000000..8673333a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc32/sparcv9b/strlen.S @@ -0,0 +1,4 @@ +#define ASI_PNF 0x82 +#define ASI_BLK_P 0xf0 +#define XCC icc +#include "../../sparc64/strlen.S" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc32/stpcpy.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc32/stpcpy.S new file mode 100644 index 00000000..daf116eb --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc32/stpcpy.S @@ -0,0 +1,161 @@ +/* Copy SRC to DEST returning the address of the terminating '\0' in DEST. + For SPARC v7. + Copyright (C) 1996, 1999, 2002, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + + /* Normally, this uses ((xword - 0x01010101) & 0x80808080) test + to find out if any byte in xword could be zero. This is fast, but + also gives false alarm for any byte in range 0x81-0xff. It does + not matter for correctness, as if this test tells us there could + be some zero byte, we check it byte by byte, but if bytes with + high bits set are common in the strings, then this will give poor + performance. You can #define EIGHTBIT_NOT_RARE and the algorithm + will use one tick slower, but more precise test + ((xword - 0x01010101) & (~xword) & 0x80808080), + which does not give any false alarms (but if some bits are set, + one cannot assume from it which bytes are zero and which are not). + It is yet to be measured, what is the correct default for glibc + in these days for an average user. + */ + + .text + .align 4 +10: ldub [%o1], %o5 + stb %o5, [%o0] + cmp %o5, 0 + add %o0, 1, %o0 + be 1f + add %o1, 1, %o1 + andcc %o1, 3, %g0 + be 4f + or %o4, %lo(0x80808080), %o3 + ldub [%o1], %o5 + stb %o5, [%o0] + cmp %o5, 0 + add %o0, 1, %o0 + be 1f + add %o1, 1, %o1 + andcc %o1, 3, %g0 + be 5f + sethi %hi(0x01010101), %o4 + ldub [%o1], %o5 + stb %o5, [%o0] + cmp %o5, 0 + add %o0, 1, %o0 + be 1f + add %o1, 1, %o1 + b 6f + or %o4, %lo(0x01010101), %o2 +1: retl + add %o0, -1, %o0 + +ENTRY(stpcpy) + andcc %o1, 3, %g0 + bne 10b + sethi %hi(0x80808080), %o4 + or %o4, %lo(0x80808080), %o3 +4: sethi %hi(0x01010101), %o4 +5: or %o4, %lo(0x01010101), %o2 +6: andcc %o0, 3, %g0 + bne 16f + sub %g0, 4, %g1 + +11: add %g1, 4, %g1 + ld [%o1 + %g1], %o5 + sub %o5, %o2, %o4 +#ifdef EIGHTBIT_NOT_RARE + andn %o4, %o5, %o4 +#endif + andcc %o4, %o3, %g0 + be,a 11b + st %o5, [%o0 + %g1] + + /* Check every byte. */ + srl %o5, 24, %g5 + andcc %g5, 0xff, %g0 + be 14f + srl %o5, 16, %g5 + andcc %g5, 0xff, %g0 + be 13f + srl %o5, 8, %g5 + andcc %g5, 0xff, %g0 + be 12f + andcc %o5, 0xff, %g0 + bne 11b + st %o5, [%o0 + %g1] + add %o0, %g1, %o0 + retl + add %o0, 3, %o0 +12: srl %o5, 16, %o5 + sth %o5, [%o0 + %g1] + add %g1, 2, %g1 + stb %g0, [%o0 + %g1] + retl + add %o0, %g1, %o0 +13: srl %o5, 16, %o5 + sth %o5, [%o0 + %g1] + add %g1, 1, %g1 + retl + add %o0, %g1, %o0 +14: stb %g0, [%o0 + %g1] + retl + add %o0, %g1, %o0 + +15: srl %o5, 24, %o4 + srl %o5, 16, %g1 + stb %o4, [%o0] + srl %o5, 8, %g4 + stb %g1, [%o0 + 1] + stb %g4, [%o0 + 2] + stb %o5, [%o0 + 3] + add %o0, 4, %o0 +16: ld [%o1], %o5 + sub %o5, %o2, %o4 + andcc %o4, %o3, %g0 + be 15b + add %o1, 4, %o1 + + /* Check every byte. */ + srl %o5, 24, %g5 + andcc %g5, 0xff, %g4 + be 19f + stb %g4, [%o0] + srl %o5, 16, %g5 + andcc %g5, 0xff, %g4 + be 18f + stb %g4, [%o0 + 1] + srl %o5, 8, %g5 + andcc %g5, 0xff, %g4 + be 17f + stb %g4, [%o0 + 2] + andcc %o5, 0xff, %g4 + stb %g4, [%o0 + 3] + bne 16b + add %o0, 4, %o0 + retl + sub %o0, 1, %o0 +17: retl + add %o0, 2, %o0 +18: retl + add %o0, 1, %o0 +19: retl + nop +END(stpcpy) + +libc_hidden_def(stpcpy) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc32/strcat.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc32/strcat.S new file mode 100644 index 00000000..eda029a1 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc32/strcat.S @@ -0,0 +1,348 @@ +/* strcat (dest, src) -- Append SRC on the end of DEST. + For SPARC v7. + Copyright (C) 1996, 1999, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + + /* Normally, this uses ((xword - 0x01010101) & 0x80808080) test + to find out if any byte in xword could be zero. This is fast, but + also gives false alarm for any byte in range 0x81-0xff. It does + not matter for correctness, as if this test tells us there could + be some zero byte, we check it byte by byte, but if bytes with + high bits set are common in the strings, then this will give poor + performance. You can #define EIGHTBIT_NOT_RARE and the algorithm + will use one tick slower, but more precise test + ((xword - 0x01010101) & (~xword) & 0x80808080), + which does not give any false alarms (but if some bits are set, + one cannot assume from it which bytes are zero and which are not). + It is yet to be measured, what is the correct default for glibc + in these days for an average user. + */ + + .text + .align 4 +10: cmp %o4, 2 + be 1f + cmp %o4, 3 + ldub [%o1], %o5 + add %o1, 1, %o1 + stb %o5, [%o0] + be 3f + cmp %o5, 0 + be 0f + add %o0, 1, %o0 +1: lduh [%o1], %o5 + add %o1, 2, %o1 + srl %o5, 8, %o4 + cmp %o4, 0 + stb %o4, [%o0] + bne,a 2f + stb %o5, [%o0 + 1] + retl + mov %g2, %o0 +2: andcc %o5, 0xff, %o5 + bne 4f + add %o0, 2, %o0 + retl + mov %g2, %o0 +3: bne 4f + add %o0, 1, %o0 + retl + mov %g2, %o0 + +11: ldub [%o0], %o5 + cmp %o5, 0 + be 1f + add %o0, 1, %o0 + andcc %o0, 3, %g0 + be 7f + or %o4, %lo(0x80808080), %o3 + ldub [%o0], %o5 + cmp %o5, 0 + be 2f + add %o0, 1, %o0 + andcc %o0, 3, %g0 + be 8f + sethi %hi(0x01010101), %o4 + ldub [%o0], %o5 + cmp %o5, 0 + be 3f + add %o0, 1, %o0 + b 9f + or %o4, %lo(0x01010101), %o2 +1: or %o4, %lo(0x80808080), %o3 +2: sethi %hi(0x01010101), %o4 +3: or %o4, %lo(0x01010101), %o2 + b 3f + sub %o0, 1, %o0 + +ENTRY(strcat) + mov %o0, %g2 + andcc %o0, 3, %g0 + bne 11b + sethi %hi(0x80808080), %o4 + or %o4, %lo(0x80808080), %o3 +7: sethi %hi(0x01010101), %o4 +8: or %o4, %lo(0x01010101), %o2 +9: ld [%o0], %o5 +7: sub %o5, %o2, %o4 +#ifdef EIGHTBIT_NOT_RARE + andn %o4, %o5, %o4 +#endif + andcc %o4, %o3, %g0 + be 9b + add %o0, 4, %o0 + + srl %o5, 24, %g5 + andcc %g5, 0xff, %g0 + be 3f + add %o0, -4, %o0 + srl %o5, 16, %g5 + andcc %g5, 0xff, %g0 + be 3f + add %o0, 1, %o0 + srl %o5, 8, %g5 + andcc %g5, 0xff, %g0 + be 3f + add %o0, 1, %o0 + andcc %o5, 0xff, %g0 + add %o0, 2, %o0 + bne,a 7b + ld [%o0], %o5 + sub %o0, 1, %o0 +3: andcc %o1, 3, %o4 + bne 10b +4: andcc %o0, 3, %g3 + bne 12f +1: ld [%o1], %o5 + add %o1, 4, %o1 + sub %o5, %o2, %o4 +#ifdef EIGHTBIT_NOT_RARE + andn %o4, %o5, %o4 +#endif + add %o0, 4, %o0 + andcc %o4, %o3, %g0 + be,a 1b + st %o5, [%o0 - 4] + + srl %o5, 24, %g5 + andcc %g5, 0xff, %g0 + be 1f + srl %o5, 16, %g5 + andcc %g5, 0xff, %g0 + be 2f + srl %o5, 8, %g5 + andcc %g5, 0xff, %g0 + be 3f + andcc %o5, 0xff, %g0 + bne 1b + st %o5, [%o0 - 4] + retl + mov %g2, %o0 +3: srl %o5, 16, %o5 + sth %o5, [%o0 - 4] + stb %g0, [%o0 - 2] + retl + mov %g2, %o0 +2: srl %o5, 16, %o5 + sth %o5, [%o0 - 4] + retl + mov %g2, %o0 +1: stb %g0, [%o0 - 4] + retl + mov %g2, %o0 + +12: add %o1, 4, %o1 + sub %o5, %o2, %o4 + cmp %g3, 2 + be 2f + cmp %g3, 3 + be 3f + andcc %o4, %o3, %g0 + bne 5f + srl %o5, 24, %g5 + stb %g5, [%o0] + sub %o0, 1, %o0 + srl %o5, 8, %g5 + sth %g5, [%o0 + 2] +1: add %o0, 4, %o0 +4: sll %o5, 24, %g6 + ld [%o1], %o5 + add %o1, 4, %o1 + srl %o5, 8, %g5 + sub %o5, %o2, %o4 +#ifdef EIGHTBIT_NOT_RARE + andn %o4, %o5, %o4 +#endif + or %g5, %g6, %g5 + andcc %o4, %o3, %g0 + be,a 1b + st %g5, [%o0] + srl %o5, 24, %o4 + andcc %o4, 0xff, %g0 + be 6f + srl %o5, 16, %o4 + andcc %o4, 0xff, %g0 + be 7f + srl %o5, 8, %o4 + st %g5, [%o0] + andcc %o4, 0xff, %g0 + be 0f + andcc %o5, 0xff, %g0 +1: bne 4b + add %o0, 4, %o0 +9: stb %g0, [%o0] +0: retl + mov %g2, %o0 + +6: srl %g5, 16, %g5 + sth %g5, [%o0] + retl + mov %g2, %o0 + +7: srl %g5, 16, %g5 + sth %g5, [%o0] + stb %g0, [%o0 + 2] + retl + mov %g2, %o0 + +5: andcc %g5, 0xff, %g4 + be 9b + srl %o5, 16, %g5 + andcc %g5, 0xff, %g0 + be 7f + srl %o5, 8, %g5 + andcc %g5, 0xff, %g0 + stb %g4, [%o0] + sth %g5, [%o0 + 1] + sub %o0, 1, %o0 + bne 1b + andcc %o5, 0xff, %g0 + retl + mov %g2, %o0 + +7: stb %g4, [%o0] + stb %g0, [%o0 + 1] + retl + mov %g2, %o0 + +2: andcc %o4, %o3, %g0 + bne 5f + srl %o5, 16, %g5 + sth %g5, [%o0] + sub %o0, 2, %o0 +1: add %o0, 4, %o0 +4: sll %o5, 16, %g6 + ld [%o1], %o5 + add %o1, 4, %o1 + srl %o5, 16, %g5 + sub %o5, %o2, %o4 +#ifdef EIGHTBIT_NOT_RARE + andn %o4, %o5, %o4 +#endif + or %g5, %g6, %g5 + andcc %o4, %o3, %g0 + be,a 1b + st %g5, [%o0] + srl %o5, 24, %o4 + andcc %o4, 0xff, %g0 + be 7f + srl %o5, 16, %o4 + st %g5, [%o0] + andcc %o4, 0xff, %g0 + be 0b + srl %o5, 8, %o4 +1: andcc %o4, 0xff, %g0 + be 8f + andcc %o5, 0xff, %g0 + bne 4b + add %o0, 4, %o0 + sth %o5, [%o0] + retl + mov %g2, %o0 + +7: srl %g5, 16, %g5 + sth %g5, [%o0] + stb %g0, [%o0 + 2] + retl + mov %g2, %o0 + +8: stb %g0, [%o0 + 4] + retl + mov %g2, %o0 + +5: srl %o5, 24, %g5 + andcc %g5, 0xff, %g0 + be 9b + srl %o5, 16, %g5 + andcc %g5, 0xff, %g0 + sth %g5, [%o0] + sub %o0, 2, %o0 + bne 1b + srl %o5, 8, %o4 + retl + mov %g2, %o0 + +3: bne 5f + srl %o5, 24, %g5 + stb %g5, [%o0] + sub %o0, 3, %o0 +1: add %o0, 4, %o0 +4: sll %o5, 8, %g6 + ld [%o1], %o5 + add %o1, 4, %o1 + srl %o5, 24, %g5 + sub %o5, %o2, %o4 +#ifdef EIGHTBIT_NOT_RARE + andn %o4, %o5, %o4 +#endif + or %g5, %g6, %g5 + andcc %o4, %o3, %g0 + be 1b + st %g5, [%o0] + srl %o5, 24, %o4 + andcc %o4, 0xff, %g0 + be 0b + srl %o5, 16, %o4 +1: andcc %o4, 0xff, %g0 + be 8b + srl %o5, 8, %o4 + andcc %o4, 0xff, %g0 + be 9f + andcc %o5, 0xff, %g0 + bne 4b + add %o0, 4, %o0 + srl %o5, 8, %o5 + sth %o5, [%o0] + stb %g0, [%o0 + 2] + retl + mov %g2, %o0 +9: srl %o5, 8, %o5 + sth %o5, [%o0 + 4] + retl + mov %g2, %o0 +5: andcc %g5, 0xff, %g0 + stb %g5, [%o0] + sub %o0, 3, %o0 + bne 1b + srl %o5, 16, %o4 + retl + mov %g2, %o0 +END(strcat) + +libc_hidden_def(strcat) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc32/strchr.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc32/strchr.S new file mode 100644 index 00000000..16710d4e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc32/strchr.S @@ -0,0 +1,287 @@ +/* strchr (str, ch) -- Return pointer to first occurrence of CH in STR. + For SPARC v7. + Copyright (C) 1996, 1999, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek and + David S. Miller . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + + /* Normally, this uses ((xword - 0x01010101) & 0x80808080) test + to find out if any byte in xword could be zero. This is fast, but + also gives false alarm for any byte in range 0x81-0xff. It does + not matter for correctness, as if this test tells us there could + be some zero byte, we check it byte by byte, but if bytes with + high bits set are common in the strings, then this will give poor + performance. You can #define EIGHTBIT_NOT_RARE and the algorithm + will use one tick slower, but more precise test + ((xword - 0x01010101) & (~xword) & 0x80808080), + which does not give any false alarms (but if some bits are set, + one cannot assume from it which bytes are zero and which are not). + It is yet to be measured, what is the correct default for glibc + in these days for an average user. + */ + +#include + + .text + .align 4 +10: ldub [%o0], %g4 + cmp %g4, %o1 + be 1f + add %o0, 1, %o0 + cmp %g4, 0 + be 9f + andcc %o0, 3, %g0 + be 4f + or %o4, %lo(0x80808080), %o3 + ldub [%o0], %g4 + cmp %g4, %o1 + be 1f + add %o0, 1, %o0 + cmp %g4, 0 + be 9f + andcc %o0, 3, %g0 + be 5f + sethi %hi(0x01010101), %o5 + ldub [%o0], %g4 + cmp %g4, %o1 + be 1f + add %o0, 1, %o0 + cmp %g4, 0 + be 9f + or %o5, %lo(0x01010101), %o2 + b 6f + ld [%o0], %g4 +1: retl + sub %o0, 1, %o0 + +ENTRY(strchr) + andcc %o1, 0xff, %o1 + be 12f + sll %o1, 8, %o2 + andcc %o0, 3, %g0 + or %o1, %o2, %o2 + sethi %hi(0x80808080), %o4 + sll %o2, 16, %o3 + bne 10b + or %o3, %o2, %g2 + or %o4, %lo(0x80808080), %o3 +4: sethi %hi(0x01010101), %o5 +5: or %o5, %lo(0x01010101), %o2 +7: ld [%o0], %g4 +6: xor %g4, %g2, %g5 + sub %g4, %o2, %o4 +#ifdef EIGHTBIT_NOT_RARE + sub %g5, %o2, %g6 + andn %o4, %g4, %o4 + andn %g6, %g5, %g5 +#else + sub %g5, %o2, %g5 +#endif + or %g5, %o4, %o4 + andcc %o4, %o3, %g0 + be 7b + add %o0, 4, %o0 + + /* Check every byte. */ +8: srl %g4, 24, %g5 +7: andcc %g5, 0xff, %g5 + be 9f + cmp %g5, %o1 + be 4f + srl %g4, 16, %g5 + andcc %g5, 0xff, %g5 + be 9f + cmp %g5, %o1 + be 3f + srl %g4, 8, %g5 + andcc %g5, 0xff, %g5 + be 9f + cmp %g5, %o1 + be 2f + andcc %g4, 0xff, %g5 + be 9f + cmp %g5, %o1 + bne,a 6b + ld [%o0], %g4 + retl + sub %o0, 1, %o0 +2: retl + sub %o0, 2, %o0 +3: retl + sub %o0, 3, %o0 +4: retl + sub %o0, 4, %o0 +9: retl + clr %o0 + +11: ldub [%o0], %o5 + cmp %o5, 0 + be 1f + add %o0, 1, %o0 + andcc %o0, 3, %g0 + be 4f + or %o4, %lo(0x80808080), %o3 + ldub [%o0], %o5 + cmp %o5, 0 + be 1f + add %o0, 1, %o0 + andcc %o0, 3, %g0 + be 5f + sethi %hi(0x01010101), %o4 + ldub [%o0], %o5 + cmp %o5, 0 + be 1f + add %o0, 1, %o0 + b 6f + or %o4, %lo(0x01010101), %o2 +1: retl + sub %o0, 1, %o0 + +12: andcc %o0, 3, %g0 + bne 11b + sethi %hi(0x80808080), %o4 + or %o4, %lo(0x80808080), %o3 +4: sethi %hi(0x01010101), %o4 +5: or %o4, %lo(0x01010101), %o2 +6: ld [%o0], %o5 +7: sub %o5, %o2, %o4 +#ifdef EIGHTBIT_NOT_RARE + andn %o4, %o5, %o4 +#endif + andcc %o4, %o3, %g0 + be 6b + add %o0, 4, %o0 + + /* Check every byte. */ + srl %o5, 24, %g5 + andcc %g5, 0xff, %g0 + be 8f + add %o0, -4, %o4 + srl %o5, 16, %g5 + andcc %g5, 0xff, %g0 + be 8f + add %o4, 1, %o4 + srl %o5, 8, %g5 + andcc %g5, 0xff, %g0 + be 8f + add %o4, 1, %o4 + andcc %o5, 0xff, %g0 + bne,a 7b + ld [%o0], %o5 + add %o4, 1, %o4 +8: retl + mov %o4, %o0 + +13: ldub [%o0], %g4 + cmp %g4, %o1 + add %o0, 1, %o0 + be,a 1f + sub %o0, 1, %o5 + cmp %g4, 0 + be 9f +1: andcc %o0, 3, %g0 + be 4f + or %o4, %lo(0x80808080), %o3 + ldub [%o0], %g4 + cmp %g4, %o1 + add %o0, 1, %o0 + be,a 1f + sub %o0, 1, %o5 + cmp %g4, 0 + be 9f +1: andcc %o0, 3, %g0 + be 5f + sethi %hi(0x01010101), %o4 + ldub [%o0], %g4 + cmp %g4, %o1 + add %o0, 1, %o0 + be,a 1f + sub %o0, 1, %o5 + cmp %g4, 0 + be 9f +1: or %o4, %lo(0x01010101), %o2 + b 7f + ld [%o0], %g4 +END(strchr) +libc_hidden_def(strchr) +#ifdef __UCLIBC_SUSV3_LEGACY__ +strong_alias(strchr,index) +#endif + +ENTRY(strrchr) + andcc %o1, 0xff, %o1 + clr %o5 + be 12b + sll %o1, 8, %o2 + andcc %o0, 3, %g0 + or %o1, %o2, %o2 + sethi %hi(0x80808080), %o4 + sll %o2, 16, %o3 + bne 13b + or %o3, %o2, %g2 + or %o4, %lo(0x80808080), %o3 +4: sethi %hi(0x01010101), %o4 +5: or %o4, %lo(0x01010101), %o2 +6: ld [%o0], %g4 +7: xor %g4, %g2, %g5 + sub %g4, %o2, %o4 +#ifdef EIGHTBIT_NOT_RARE + sub %g5, %o2, %g6 + andn %o4, %g4, %o4 + andn %g6, %g5, %g5 +#else + sub %g5, %o2, %g5 +#endif + or %g5, %o4, %o4 + andcc %o4, %o3, %g0 + be 6b + add %o0, 4, %o0 + + /* Check every byte. */ +3: srl %g4, 24, %g5 +8: andcc %g5, 0xff, %g5 + be 9f + cmp %g5, %o1 + be,a 1f + sub %o0, 4, %o5 +1: srl %g4, 16, %g5 + andcc %g5, 0xff, %g5 + be 9f + cmp %g5, %o1 + be,a 1f + sub %o0, 3, %o5 +1: srl %g4, 8, %g5 + andcc %g5, 0xff, %g5 + be 9f + cmp %g5, %o1 + be,a 1f + sub %o0, 2, %o5 +1: andcc %g4, 0xff, %g5 + be 9f + cmp %g5, %o1 + be,a 1f + sub %o0, 1, %o5 +1: b 7b + ld [%o0], %g4 +9: retl + mov %o5, %o0 +END(strrchr) +libc_hidden_def(strrchr) +#ifdef __UCLIBC_SUSV3_LEGACY__ +strong_alias(strrchr,rindex) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc32/strcmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc32/strcmp.S new file mode 100644 index 00000000..d43883de --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc32/strcmp.S @@ -0,0 +1,256 @@ +/* Compare two strings for differences. + For SPARC v7. + Copyright (C) 1996, 97, 99, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + + /* Normally, this uses ((xword - 0x01010101) & 0x80808080) test + to find out if any byte in xword could be zero. This is fast, but + also gives false alarm for any byte in range 0x81-0xff. It does + not matter for correctness, as if this test tells us there could + be some zero byte, we check it byte by byte, but if bytes with + high bits set are common in the strings, then this will give poor + performance. You can #define EIGHTBIT_NOT_RARE and the algorithm + will use one tick slower, but more precise test + ((xword - 0x01010101) & (~xword) & 0x80808080), + which does not give any false alarms (but if some bits are set, + one cannot assume from it which bytes are zero and which are not). + It is yet to be measured, what is the correct default for glibc + in these days for an average user. + */ + + .text + .align 4 +10: ldub [%o0], %o4 + add %o0, 1, %o0 + ldub [%o1], %o5 + cmp %o4, 0 + add %o1, 1, %o1 + be 2f + subcc %o4, %o5, %o4 + bne 2f + andcc %o0, 3, %g0 + be 4f + or %g1, %lo(0x80808080), %o3 + ldub [%o0], %o4 + add %o0, 1, %o0 + ldub [%o1], %o5 + cmp %o4, 0 + add %o1, 1, %o1 + be 2f + subcc %o4, %o5, %o4 + bne 2f + andcc %o0, 3, %g0 + be 5f + sethi %hi(0x01010101), %g1 + ldub [%o0], %o4 + add %o0, 1, %o0 + ldub [%o1], %o5 + cmp %o4, 0 + add %o1, 1, %o1 + be 2f + subcc %o4, %o5, %o4 + bne 2f + andcc %o1, 3, %g2 + bne 12f + or %g1, %lo(0x01010101), %o2 + b 1f + ld [%o0], %o4 +2: retl + mov %o4, %o0 + +ENTRY(strcmp) + andcc %o0, 3, %g0 + bne 10b + sethi %hi(0x80808080), %g1 + or %g1, %lo(0x80808080), %o3 +4: sethi %hi(0x01010101), %g1 +5: andcc %o1, 3, %g2 + bne 12f + or %g1, %lo(0x01010101), %o2 + +0: ld [%o0], %o4 +1: ld [%o1], %o5 + sub %o4, %o2, %g1 + add %o0, 4, %o0 + cmp %o4, %o5 +#ifdef EIGHTBIT_NOT_RARE + andn %g1, %o4, %g1 +#endif + bne 11f + andcc %g1, %o3, %g0 + be 0b + add %o1, 4, %o1 + + srl %o4, 24, %g4 + andcc %g4, 0xff, %g0 + be 2f + srl %o4, 16, %g4 + andcc %g4, 0xff, %g0 + be 2f + srl %o4, 8, %g4 + andcc %g4, 0xff, %g0 + be 2f + andcc %o4, 0xff, %g0 + bne,a 1b + ld [%o0], %o4 +2: retl + clr %o0 + +11: srl %o4, 24, %g4 + srl %o5, 24, %g5 + andcc %g4, 0xff, %g0 + be 3f + subcc %g4, %g5, %g4 + bne 3f + srl %o5, 16, %g5 + srl %o4, 16, %g4 + andcc %g4, 0xff, %g0 + be 3f + subcc %g4, %g5, %g4 + bne 3f + srl %o5, 8, %g5 + srl %o4, 8, %g4 + andcc %g4, 0xff, %g0 + be 3f + subcc %g4, %g5, %g4 + bne 3f + subcc %o4, %o5, %o4 + retl + mov %o4, %o0 +3: retl + mov %g4, %o0 + +12: save %sp, -64, %sp + ld [%i0], %i4 + sll %g2, 3, %g3 + andn %i1, 3, %i1 + mov 32, %l1 + ld [%i1], %l2 + mov -1, %g6 + add %i1, 4, %i1 + sub %l1, %g3, %l1 + sll %g6, %g3, %g6 + +1: sll %l2, %g3, %g5 + and %i4, %g6, %l3 + sub %i4, %i2, %g1 +#ifdef EIGHTBIT_NOT_RARE + andn %g1, %i4, %g1 +#endif + andcc %g1, %i3, %g1 + bne 3f + cmp %g5, %l3 + bne 2f + add %i0, 4, %i0 + ld [%i1], %l2 + add %i1, 4, %i1 + srl %l2, %l1, %l4 + or %l4, %g5, %l4 + cmp %l4, %i4 + be,a 1b + ld [%i0], %i4 + restore %l4, %g0, %o3 + retl + sub %o4, %o3, %o0 + +2: sll %l2, %g3, %i2 + srl %i4, %g3, %i3 + srl %i2, %g3, %i2 + restore + retl + sub %o3, %o2, %o0 + +3: srl %i4, 24, %g4 + srl %g5, 24, %l6 + andcc %g4, 0xff, %g0 + be 4f + subcc %g4, %l6, %g4 + bne 4f + cmp %g2, 3 + be 6f + srl %i4, 16, %g4 + srl %g5, 16, %l6 + andcc %g4, 0xff, %g0 + be 4f + subcc %g4, %l6, %g4 + bne 4f + cmp %g2, 2 + be 5f + srl %i4, 8, %g4 + srl %g5, 8, %l6 + andcc %g4, 0xff, %g0 + be 4f + subcc %g4, %l6, %g4 + bne 4f + add %i0, 4, %i0 + ld [%i1], %l2 + add %i1, 4, %i1 + srl %l2, 24, %g5 + andcc %i4, 0xff, %g4 + be 4f + subcc %g4, %g5, %g4 + be,a 1b + ld [%i0], %i4 +4: jmpl %i7 + 8, %g0 + restore %g4, %g0, %o0 + +5: ld [%i1], %l2 + add %i1, 4, %i1 + add %i0, 4, %i0 + srl %l2, 24, %l6 + andcc %g4, 0xff, %g4 + be 4b + subcc %g4, %l6, %g4 + bne 4b + srl %l2, 16, %l6 + andcc %i4, 0xff, %g4 + and %l6, 0xff, %l6 + be 4b + subcc %g4, %l6, %g4 + be,a 1b + ld [%i0], %i4 + jmpl %i7 + 8, %g0 + restore %g4, %g0, %o0 + +6: ld [%i1], %l2 + add %i1, 4, %i1 + add %i0, 4, %i0 + srl %l2, 24, %l6 + andcc %g4, 0xff, %g4 + be 4b + subcc %g4, %l6, %g4 + bne 4b + srl %l2, 16, %l6 + srl %i4, 8, %g4 + and %l6, 0xff, %l6 + andcc %g4, 0xff, %g4 + be 4b + subcc %g4, %l6, %g4 + bne 4b + srl %l2, 8, %l6 + andcc %i4, 0xff, %g4 + and %l6, 0xff, %l6 + be 4b + subcc %g4, %l6, %g4 + be,a 1b + ld [%i0], %i4 + jmpl %i7 + 8, %g0 + restore %g4, %g0, %o0 +END(strcmp) +libc_hidden_def(strcmp) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc32/strcpy.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc32/strcpy.S new file mode 100644 index 00000000..4d7742eb --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc32/strcpy.S @@ -0,0 +1,273 @@ +/* Copy SRC to DEST returning DEST. + For SPARC v7. + Copyright (C) 1996, 1999, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + + /* Normally, this uses ((xword - 0x01010101) & 0x80808080) test + to find out if any byte in xword could be zero. This is fast, but + also gives false alarm for any byte in range 0x81-0xff. It does + not matter for correctness, as if this test tells us there could + be some zero byte, we check it byte by byte, but if bytes with + high bits set are common in the strings, then this will give poor + performance. You can #define EIGHTBIT_NOT_RARE and the algorithm + will use one tick slower, but more precise test + ((xword - 0x01010101) & (~xword) & 0x80808080), + which does not give any false alarms (but if some bits are set, + one cannot assume from it which bytes are zero and which are not). + It is yet to be measured, what is the correct default for glibc + in these days for an average user. + */ + + .text + .align 4 +1: ldub [%o1], %o5 + stb %o5, [%o0] + cmp %o5, 0 + add %o0, 1, %o0 + be 0f + add %o1, 1, %o1 + andcc %o1, 3, %g0 + be 4f + or %o4, %lo(0x80808080), %o3 + ldub [%o1], %o5 + stb %o5, [%o0] + cmp %o5, 0 + add %o0, 1, %o0 + be 0f + add %o1, 1, %o1 + andcc %o1, 3, %g0 + be 5f + sethi %hi(0x01010101), %o4 + ldub [%o1], %o5 + stb %o5, [%o0] + cmp %o5, 0 + add %o0, 1, %o0 + be 0f + add %o1, 1, %o1 + b 6f + andcc %o0, 3, %g3 + +ENTRY(strcpy) + mov %o0, %g2 + andcc %o1, 3, %g0 + bne 1b + sethi %hi(0x80808080), %o4 + or %o4, %lo(0x80808080), %o3 +4: sethi %hi(0x01010101), %o4 +5: andcc %o0, 3, %g3 +6: bne 10f + or %o4, %lo(0x01010101), %o2 +1: ld [%o1], %o5 + add %o1, 4, %o1 + sub %o5, %o2, %o4 + add %o0, 4, %o0 + andcc %o4, %o3, %g0 + be,a 1b + st %o5, [%o0 - 4] + + srl %o5, 24, %g5 + andcc %g5, 0xff, %g0 + be 1f + srl %o5, 16, %g5 + andcc %g5, 0xff, %g0 + be 2f + srl %o5, 8, %g5 + andcc %g5, 0xff, %g0 + be 3f + andcc %o5, 0xff, %g0 + bne 1b + st %o5, [%o0 - 4] + retl + mov %g2, %o0 +3: srl %o5, 16, %o5 + sth %o5, [%o0 - 4] + stb %g0, [%o0 - 2] + retl + mov %g2, %o0 +2: srl %o5, 16, %o5 + sth %o5, [%o0 - 4] + retl + mov %g2, %o0 +1: stb %g0, [%o0 - 4] + retl + mov %g2, %o0 + +10: ld [%o1], %o5 + add %o1, 4, %o1 + sub %o5, %o2, %o4 + cmp %g3, 2 + be 2f + cmp %g3, 3 + be 3f + andcc %o4, %o3, %g0 + bne 5f + srl %o5, 24, %g5 + stb %g5, [%o0] + sub %o0, 1, %o0 + srl %o5, 8, %g5 + sth %g5, [%o0 + 2] +1: add %o0, 4, %o0 +4: sll %o5, 24, %g6 + ld [%o1], %o5 + add %o1, 4, %o1 + srl %o5, 8, %g5 + sub %o5, %o2, %o4 + or %g5, %g6, %g5 + andcc %o4, %o3, %g0 + be,a 1b + st %g5, [%o0] + srl %o5, 24, %o4 + andcc %o4, 0xff, %g0 + be 6f + srl %o5, 16, %o4 + andcc %o4, 0xff, %g0 + be 7f + srl %o5, 8, %o4 + st %g5, [%o0] + andcc %o4, 0xff, %g0 + be 0f + andcc %o5, 0xff, %g0 +1: bne 4b + add %o0, 4, %o0 +9: stb %g0, [%o0] +0: retl + mov %g2, %o0 +6: srl %g5, 16, %g5 + sth %g5, [%o0] + retl + mov %g2, %o0 +7: srl %g5, 16, %g5 + sth %g5, [%o0] + stb %g0, [%o0 + 2] + retl + mov %g2, %o0 +5: andcc %g5, 0xff, %g4 + be 9b + srl %o5, 16, %g5 + andcc %g5, 0xff, %g0 + be 7f + srl %o5, 8, %g5 + andcc %g5, 0xff, %g0 + stb %g4, [%o0] + sth %g5, [%o0 + 1] + sub %o0, 1, %o0 + bne 1b + andcc %o5, 0xff, %g0 + retl + mov %g2, %o0 +7: stb %g4, [%o0] + stb %g0, [%o0 + 1] + retl + mov %g2, %o0 + +2: andcc %o4, %o3, %g0 + bne 5f + srl %o5, 16, %g5 + sth %g5, [%o0] + sub %o0, 2, %o0 +1: add %o0, 4, %o0 +4: sll %o5, 16, %g6 + ld [%o1], %o5 + add %o1, 4, %o1 + srl %o5, 16, %g5 + sub %o5, %o2, %o4 + or %g5, %g6, %g5 + andcc %o4, %o3, %g0 + be,a 1b + st %g5, [%o0] + srl %o5, 24, %o4 + andcc %o4, 0xff, %g0 + be 7f + srl %o5, 16, %o4 + st %g5, [%o0] + andcc %o4, 0xff, %g0 + be 0b + srl %o5, 8, %o4 +1: andcc %o4, 0xff, %g0 + be 8f + andcc %o5, 0xff, %g0 + bne 4b + add %o0, 4, %o0 + sth %o5, [%o0] + retl + mov %g2, %o0 +7: srl %g5, 16, %g5 + sth %g5, [%o0] + stb %g0, [%o0 + 2] + retl + mov %g2, %o0 +8: stb %g0, [%o0 + 4] + retl + mov %g2, %o0 +5: srl %o5, 24, %g5 + andcc %g5, 0xff, %g0 + be 9b + srl %o5, 16, %g5 + andcc %g5, 0xff, %g0 + sth %g5, [%o0] + sub %o0, 2, %o0 + bne 1b + srl %o5, 8, %o4 + retl + mov %g2, %o0 + +3: bne 5f + srl %o5, 24, %g5 + stb %g5, [%o0] + sub %o0, 3, %o0 +1: add %o0, 4, %o0 +4: sll %o5, 8, %g6 + ld [%o1], %o5 + add %o1, 4, %o1 + srl %o5, 24, %g5 + sub %o5, %o2, %o4 + or %g5, %g6, %g5 + andcc %o4, %o3, %g0 + be 1b + st %g5, [%o0] + srl %o5, 24, %o4 + andcc %o4, 0xff, %g0 + be 0b + srl %o5, 16, %o4 +1: andcc %o4, 0xff, %g0 + be 8b + srl %o5, 8, %o4 + andcc %o4, 0xff, %g0 + be 9f + andcc %o5, 0xff, %g0 + bne 4b + add %o0, 4, %o0 + srl %o5, 8, %o5 + sth %o5, [%o0] + stb %g0, [%o0 + 2] + retl + mov %g2, %o0 +9: srl %o5, 8, %o5 + sth %o5, [%o0 + 4] + retl + mov %g2, %o0 +5: andcc %g5, 0xff, %g0 + stb %g5, [%o0] + sub %o0, 3, %o0 + bne 1b + srl %o5, 16, %o4 + retl + mov %g2, %o0 +END(strcpy) +libc_hidden_def(strcpy) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc32/strlen.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc32/strlen.S new file mode 100644 index 00000000..4edfe7e7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc32/strlen.S @@ -0,0 +1,102 @@ +/* Determine the length of a string. + For SPARC v7. + Copyright (C) 1996, 1999, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + + /* Normally, this uses ((xword - 0x01010101) & 0x80808080) test + to find out if any byte in xword could be zero. This is fast, but + also gives false alarm for any byte in range 0x81-0xff. It does + not matter for correctness, as if this test tells us there could + be some zero byte, we check it byte by byte, but if bytes with + high bits set are common in the strings, then this will give poor + performance. You can #define EIGHTBIT_NOT_RARE and the algorithm + will use one tick slower, but more precise test + ((xword - 0x01010101) & (~xword) & 0x80808080), + which does not give any false alarms (but if some bits are set, + one cannot assume from it which bytes are zero and which are not). + It is yet to be measured, what is the correct default for glibc + in these days for an average user. + */ + + .text + .align 4 +10: ldub [%o0], %o5 + cmp %o5, 0 + be 1f + add %o0, 1, %o0 + andcc %o0, 3, %g0 + be 4f + or %o4, %lo(0x80808080), %o3 + ldub [%o0], %o5 + cmp %o5, 0 + be 2f + add %o0, 1, %o0 + andcc %o0, 3, %g0 + be 5f + sethi %hi(0x01010101), %o4 + ldub [%o0], %o5 + cmp %o5, 0 + be 3f + add %o0, 1, %o0 + b 11f + or %o4, %lo(0x01010101), %o2 +1: retl + mov 0, %o0 +2: retl + mov 1, %o0 +3: retl + mov 2, %o0 + +ENTRY(strlen) + mov %o0, %o1 + andcc %o0, 3, %g0 + bne 10b + sethi %hi(0x80808080), %o4 + or %o4, %lo(0x80808080), %o3 +4: sethi %hi(0x01010101), %o4 +5: or %o4, %lo(0x01010101), %o2 +11: ld [%o0], %o5 +12: sub %o5, %o2, %o4 +#ifdef EIGHTBIT_NOT_RARE + andn %o4, %o5, %o4 +#endif + andcc %o4, %o3, %g0 + be 11b + add %o0, 4, %o0 + + srl %o5, 24, %g5 + andcc %g5, 0xff, %g0 + be 13f + add %o0, -4, %o4 + srl %o5, 16, %g5 + andcc %g5, 0xff, %g0 + be 13f + add %o4, 1, %o4 + srl %o5, 8, %g5 + andcc %g5, 0xff, %g0 + be 13f + add %o4, 1, %o4 + andcc %o5, 0xff, %g0 + bne,a 12b + ld [%o0], %o5 + add %o4, 1, %o4 +13: retl + sub %o4, %o1, %o0 +END(strlen) +libc_hidden_def(strlen) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc64/memchr.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc64/memchr.S new file mode 100644 index 00000000..f44850b0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc64/memchr.S @@ -0,0 +1,259 @@ +/* memchr (str, ch, n) -- Return pointer to first occurrence of CH in STR less + than N. + For SPARC v9. + Copyright (C) 1998, 1999, 2000, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jan Vondrak and + Jakub Jelinek . + This version is developed using the same algorithm as the fast C + version which carries the following introduction: + Based on strlen implementation by Torbjorn Granlund (tege@sics.se), + with help from Dan Sahlin (dan@sics.se) and + commentary by Jim Blandy (jimb@ai.mit.edu); + adaptation to memchr suggested by Dick Karpinski (dick@cca.ucsf.edu), + and implemented by Roland McGrath (roland@ai.mit.edu). + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#ifndef XCC +#define XCC xcc +#define USE_BPR + .register %g2, #scratch + .register %g3, #scratch +#endif + + /* Normally, this uses + ((xword - 0x0101010101010101) & 0x8080808080808080) test + to find out if any byte in xword could be zero. This is fast, but + also gives false alarm for any byte in range 0x81-0xff. It does + not matter for correctness, as if this test tells us there could + be some zero byte, we check it byte by byte, but if bytes with + high bits set are common in the strings, then this will give poor + performance. You can #define EIGHTBIT_NOT_RARE and the algorithm + will use one tick slower, but more precise test + ((xword - 0x0101010101010101) & (~xword) & 0x8080808080808080), + which does not give any false alarms (but if some bits are set, + one cannot assume from it which bytes are zero and which are not). + It is yet to be measured, what is the correct default for glibc + in these days for an average user. + */ + + .text + .align 32 +ENTRY(memchr) + and %o1, 0xff, %o1 /* IEU0 Group */ +#ifdef USE_BPR + brz,pn %o2, 12f /* CTI+IEU1 */ +#else + tst %o2 /* IEU1 */ + be,pn %XCC, 12f /* CTI */ +#endif + sll %o1, 8, %g3 /* IEU0 Group */ + add %o0, %o2, %o2 /* IEU1 */ + + sethi %hi(0x01010101), %g1 /* IEU0 Group */ + or %g3, %o1, %g3 /* IEU1 */ + ldub [%o0], %o3 /* Load */ + sllx %g3, 16, %g5 /* IEU0 Group */ + + or %g1, %lo(0x01010101), %g1 /* IEU1 */ + sllx %g1, 32, %g2 /* IEU0 Group */ + or %g3, %g5, %g3 /* IEU1 */ + sllx %g3, 32, %g5 /* IEU0 Group */ + + cmp %o3, %o1 /* IEU1 */ + be,pn %xcc, 13f /* CTI */ + or %g1, %g2, %g1 /* IEU0 Group */ + andcc %o0, 7, %g0 /* IEU1 */ + + bne,a,pn %icc, 21f /* CTI */ + add %o0, 1, %o0 /* IEU0 Group */ + ldx [%o0], %o3 /* Load Group */ + sllx %g1, 7, %g2 /* IEU0 */ + + or %g3, %g5, %g3 /* IEU1 */ +1: add %o0, 8, %o0 /* IEU0 Group */ + xor %o3, %g3, %o4 /* IEU1 */ + /* %g1 = 0101010101010101 * + * %g2 = 8080088080808080 * + * %g3 = c c c c c c c c * + * %o3 = value * + * %o4 = value XOR c */ +2: cmp %o0, %o2 /* IEU1 Group */ + + bg,pn %XCC, 11f /* CTI */ + ldxa [%o0] ASI_PNF, %o3 /* Load */ + sub %o4, %g1, %o5 /* IEU0 Group */ + add %o0, 8, %o0 /* IEU1 */ +#ifdef EIGHTBIT_NOT_RARE + andn %o5, %o4, %o5 /* IEU0 Group */ +#endif + + andcc %o5, %g2, %g0 /* IEU1 Group */ + be,a,pt %xcc, 2b /* CTI */ + xor %o3, %g3, %o4 /* IEU0 */ + srlx %o4, 56, %g5 /* IEU0 */ + + andcc %g5, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 3f /* CTI */ + srlx %o4, 48, %g5 /* IEU0 */ + andcc %g5, 0xff, %g0 /* IEU1 Group */ + + be,pn %icc, 4f /* CTI */ + srlx %o4, 40, %g5 /* IEU0 */ + andcc %g5, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 5f /* CTI */ + + srlx %o4, 32, %g5 /* IEU0 */ + andcc %g5, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 6f /* CTI */ + srlx %o4, 24, %g5 /* IEU0 */ + + andcc %g5, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 7f /* CTI */ + srlx %o4, 16, %g5 /* IEU0 */ + andcc %g5, 0xff, %g0 /* IEU1 Group */ + + be,pn %icc, 8f /* CTI */ + srlx %o4, 8, %g5 /* IEU0 */ + andcc %g5, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 9f /* CTI */ + + andcc %o4, 0xff, %g0 /* IEU1 Group */ + bne,pt %icc, 2b /* CTI */ + xor %o3, %g3, %o4 /* IEU0 */ + retl /* CTI+IEU1 Group */ + + add %o0, -9, %o0 /* IEU0 */ + + .align 16 +3: retl /* CTI+IEU1 Group */ + add %o0, -16, %o0 /* IEU0 */ +4: retl /* CTI+IEU1 Group */ + add %o0, -15, %o0 /* IEU0 */ + +5: retl /* CTI+IEU1 Group */ + add %o0, -14, %o0 /* IEU0 */ +6: retl /* CTI+IEU1 Group */ + add %o0, -13, %o0 /* IEU0 */ + +7: retl /* CTI+IEU1 Group */ + add %o0, -12, %o0 /* IEU0 */ +8: retl /* CTI+IEU1 Group */ + add %o0, -11, %o0 /* IEU0 */ + +9: retl /* CTI+IEU1 Group */ + add %o0, -10, %o0 /* IEU0 */ +11: sub %o4, %g1, %o5 /* IEU0 Group */ + sub %o0, 8, %o0 /* IEU1 */ + + andcc %o5, %g2, %g0 /* IEU1 Group */ + be,pt %xcc, 12f /* CTI */ + sub %o2, %o0, %o2 /* IEU0 */ + tst %o2 /* IEU1 Group */ + + be,pn %XCC, 12f /* CTI */ + srlx %o4, 56, %g5 /* IEU0 */ + andcc %g5, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 13f /* CTI */ + + cmp %o2, 1 /* IEU0 */ + be,pn %XCC, 12f /* CTI Group */ + srlx %o4, 48, %g5 /* IEU0 */ + andcc %g5, 0xff, %g0 /* IEU1 Group */ + + be,pn %icc, 14f /* CTI */ + cmp %o2, 2 /* IEU1 Group */ + be,pn %XCC, 12f /* CTI */ + srlx %o4, 40, %g5 /* IEU0 */ + + andcc %g5, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 15f /* CTI */ + cmp %o2, 3 /* IEU1 Group */ + be,pn %XCC, 12f /* CTI */ + + srlx %o4, 32, %g5 /* IEU0 */ + andcc %g5, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 16f /* CTI */ + cmp %o2, 4 /* IEU1 Group */ + + be,pn %XCC, 12f /* CTI */ + srlx %o4, 24, %g5 /* IEU0 */ + andcc %g5, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 17f /* CTI */ + + cmp %o2, 5 /* IEU1 Group */ + be,pn %XCC, 12f /* CTI */ + srlx %o4, 16, %g5 /* IEU0 */ + andcc %g5, 0xff, %g0 /* IEU1 Group */ + + be,pn %icc, 18f /* CTI */ + cmp %o2, 6 /* IEU1 Group */ + be,pn %XCC, 12f /* CTI */ + srlx %o4, 8, %g5 /* IEU0 */ + + andcc %g5, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 19f /* CTI */ + nop /* IEU0 */ +12: retl /* CTI+IEU1 Group */ + + clr %o0 /* IEU0 */ + nop /* Stub */ +13: retl /* CTI+IEU1 Group */ + nop /* IEU0 */ + +14: retl /* CTI+IEU1 Group */ + add %o0, 1, %o0 /* IEU0 */ +15: retl /* CTI+IEU1 Group */ + add %o0, 2, %o0 /* IEU0 */ + +16: retl /* CTI+IEU1 Group */ + add %o0, 3, %o0 /* IEU0 */ +17: retl /* CTI+IEU1 Group */ + add %o0, 4, %o0 /* IEU0 */ + +18: retl /* CTI+IEU1 Group */ + add %o0, 5, %o0 /* IEU0 */ +19: retl /* CTI+IEU1 Group */ + add %o0, 6, %o0 /* IEU0 */ + +21: cmp %o0, %o2 /* IEU1 */ + be,pn %XCC, 12b /* CTI */ + sllx %g1, 7, %g2 /* IEU0 Group */ + ldub [%o0], %o3 /* Load */ + + or %g3, %g5, %g3 /* IEU1 */ +22: andcc %o0, 7, %g0 /* IEU1 Group */ + be,a,pn %icc, 1b /* CTI */ + ldx [%o0], %o3 /* Load */ + + cmp %o3, %o1 /* IEU1 Group */ + be,pn %xcc, 23f /* CTI */ + add %o0, 1, %o0 /* IEU0 */ + cmp %o0, %o2 /* IEU1 Group */ + + bne,a,pt %XCC, 22b /* CTI */ + ldub [%o0], %o3 /* Load */ + retl /* CTI+IEU1 Group */ + clr %o0 /* IEU0 */ + +23: retl /* CTI+IEU1 Group */ + add %o0, -1, %o0 /* IEU0 */ +END(memchr) + +libc_hidden_def(memchr) +weak_alias(memchr,__ubp_memchr) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc64/memcpy.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc64/memcpy.S new file mode 100644 index 00000000..db63d1da --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc64/memcpy.S @@ -0,0 +1,923 @@ +/* Copy SIZE bytes from SRC to DEST. + For UltraSPARC. + Copyright (C) 1996, 97, 98, 99, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by David S. Miller (davem@caip.rutgers.edu) and + Jakub Jelinek (jakub@redhat.com). + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#ifndef XCC +#define USE_BPR + .register %g2, #scratch + .register %g3, #scratch + .register %g6, #scratch +#define XCC xcc +#endif +#define FPRS_FEF 4 + +#define FREG_FROB(f1, f2, f3, f4, f5, f6, f7, f8, f9) \ + faligndata %f1, %f2, %f48; \ + faligndata %f2, %f3, %f50; \ + faligndata %f3, %f4, %f52; \ + faligndata %f4, %f5, %f54; \ + faligndata %f5, %f6, %f56; \ + faligndata %f6, %f7, %f58; \ + faligndata %f7, %f8, %f60; \ + faligndata %f8, %f9, %f62; + +#define MAIN_LOOP_CHUNK(src, dest, fdest, fsrc, len, jmptgt) \ + ldda [%src] %asi, %fdest; \ + add %src, 0x40, %src; \ + add %dest, 0x40, %dest; \ + subcc %len, 0x40, %len; \ + be,pn %xcc, jmptgt; \ + stda %fsrc, [%dest - 0x40] %asi; + +#define LOOP_CHUNK1(src, dest, len, branch_dest) \ + MAIN_LOOP_CHUNK(src, dest, f0, f48, len, branch_dest) +#define LOOP_CHUNK2(src, dest, len, branch_dest) \ + MAIN_LOOP_CHUNK(src, dest, f16, f48, len, branch_dest) +#define LOOP_CHUNK3(src, dest, len, branch_dest) \ + MAIN_LOOP_CHUNK(src, dest, f32, f48, len, branch_dest) + +#define STORE_SYNC(dest, fsrc) \ + stda %fsrc, [%dest] %asi; \ + add %dest, 0x40, %dest; + +#define STORE_JUMP(dest, fsrc, target) \ + stda %fsrc, [%dest] %asi; \ + add %dest, 0x40, %dest; \ + ba,pt %xcc, target; + +#define VISLOOP_PAD nop; nop; nop; nop; \ + nop; nop; nop; nop; \ + nop; nop; nop; nop; \ + nop; nop; nop; + +#define FINISH_VISCHUNK(dest, f0, f1, left) \ + subcc %left, 8, %left; \ + bl,pn %xcc, 205f; \ + faligndata %f0, %f1, %f48; \ + std %f48, [%dest]; \ + add %dest, 8, %dest; + +#define UNEVEN_VISCHUNK(dest, f0, f1, left) \ + subcc %left, 8, %left; \ + bl,pn %xcc, 205f; \ + fsrc1 %f0, %f1; \ + ba,a,pt %xcc, 204f; + + /* Macros for non-VIS memcpy code. */ +#define MOVE_BIGCHUNK(src, dst, offset, t0, t1, t2, t3) \ + ldx [%src + offset + 0x00], %t0; \ + ldx [%src + offset + 0x08], %t1; \ + ldx [%src + offset + 0x10], %t2; \ + ldx [%src + offset + 0x18], %t3; \ + stw %t0, [%dst + offset + 0x04]; \ + srlx %t0, 32, %t0; \ + stw %t0, [%dst + offset + 0x00]; \ + stw %t1, [%dst + offset + 0x0c]; \ + srlx %t1, 32, %t1; \ + stw %t1, [%dst + offset + 0x08]; \ + stw %t2, [%dst + offset + 0x14]; \ + srlx %t2, 32, %t2; \ + stw %t2, [%dst + offset + 0x10]; \ + stw %t3, [%dst + offset + 0x1c]; \ + srlx %t3, 32, %t3; \ + stw %t3, [%dst + offset + 0x18]; + +#define MOVE_BIGALIGNCHUNK(src, dst, offset, t0, t1, t2, t3) \ + ldx [%src + offset + 0x00], %t0; \ + ldx [%src + offset + 0x08], %t1; \ + ldx [%src + offset + 0x10], %t2; \ + ldx [%src + offset + 0x18], %t3; \ + stx %t0, [%dst + offset + 0x00]; \ + stx %t1, [%dst + offset + 0x08]; \ + stx %t2, [%dst + offset + 0x10]; \ + stx %t3, [%dst + offset + 0x18]; \ + ldx [%src + offset + 0x20], %t0; \ + ldx [%src + offset + 0x28], %t1; \ + ldx [%src + offset + 0x30], %t2; \ + ldx [%src + offset + 0x38], %t3; \ + stx %t0, [%dst + offset + 0x20]; \ + stx %t1, [%dst + offset + 0x28]; \ + stx %t2, [%dst + offset + 0x30]; \ + stx %t3, [%dst + offset + 0x38]; + +#define MOVE_LASTCHUNK(src, dst, offset, t0, t1, t2, t3) \ + ldx [%src - offset - 0x10], %t0; \ + ldx [%src - offset - 0x08], %t1; \ + stw %t0, [%dst - offset - 0x0c]; \ + srlx %t0, 32, %t2; \ + stw %t2, [%dst - offset - 0x10]; \ + stw %t1, [%dst - offset - 0x04]; \ + srlx %t1, 32, %t3; \ + stw %t3, [%dst - offset - 0x08]; + +#define MOVE_LASTALIGNCHUNK(src, dst, offset, t0, t1) \ + ldx [%src - offset - 0x10], %t0; \ + ldx [%src - offset - 0x08], %t1; \ + stx %t0, [%dst - offset - 0x10]; \ + stx %t1, [%dst - offset - 0x08]; + + /* Macros for non-VIS memmove code. */ +#define RMOVE_BIGCHUNK(src, dst, offset, t0, t1, t2, t3) \ + ldx [%src - offset - 0x20], %t0; \ + ldx [%src - offset - 0x18], %t1; \ + ldx [%src - offset - 0x10], %t2; \ + ldx [%src - offset - 0x08], %t3; \ + stw %t0, [%dst - offset - 0x1c]; \ + srlx %t0, 32, %t0; \ + stw %t0, [%dst - offset - 0x20]; \ + stw %t1, [%dst - offset - 0x14]; \ + srlx %t1, 32, %t1; \ + stw %t1, [%dst - offset - 0x18]; \ + stw %t2, [%dst - offset - 0x0c]; \ + srlx %t2, 32, %t2; \ + stw %t2, [%dst - offset - 0x10]; \ + stw %t3, [%dst - offset - 0x04]; \ + srlx %t3, 32, %t3; \ + stw %t3, [%dst - offset - 0x08]; + +#define RMOVE_BIGALIGNCHUNK(src, dst, offset, t0, t1, t2, t3) \ + ldx [%src - offset - 0x20], %t0; \ + ldx [%src - offset - 0x18], %t1; \ + ldx [%src - offset - 0x10], %t2; \ + ldx [%src - offset - 0x08], %t3; \ + stx %t0, [%dst - offset - 0x20]; \ + stx %t1, [%dst - offset - 0x18]; \ + stx %t2, [%dst - offset - 0x10]; \ + stx %t3, [%dst - offset - 0x08]; \ + ldx [%src - offset - 0x40], %t0; \ + ldx [%src - offset - 0x38], %t1; \ + ldx [%src - offset - 0x30], %t2; \ + ldx [%src - offset - 0x28], %t3; \ + stx %t0, [%dst - offset - 0x40]; \ + stx %t1, [%dst - offset - 0x38]; \ + stx %t2, [%dst - offset - 0x30]; \ + stx %t3, [%dst - offset - 0x28]; + +#define RMOVE_LASTCHUNK(src, dst, offset, t0, t1, t2, t3) \ + ldx [%src + offset + 0x00], %t0; \ + ldx [%src + offset + 0x08], %t1; \ + stw %t0, [%dst + offset + 0x04]; \ + srlx %t0, 32, %t2; \ + stw %t2, [%dst + offset + 0x00]; \ + stw %t1, [%dst + offset + 0x0c]; \ + srlx %t1, 32, %t3; \ + stw %t3, [%dst + offset + 0x08]; + +#define RMOVE_LASTALIGNCHUNK(src, dst, offset, t0, t1) \ + ldx [%src + offset + 0x00], %t0; \ + ldx [%src + offset + 0x08], %t1; \ + stx %t0, [%dst + offset + 0x00]; \ + stx %t1, [%dst + offset + 0x08]; + + .text + .align 32 + +#ifdef __UCLIBC_SUSV3_LEGACY__ +ENTRY(bcopy) + sub %o1, %o0, %o4 /* IEU0 Group */ + mov %o0, %g3 /* IEU1 */ + cmp %o4, %o2 /* IEU1 Group */ + mov %o1, %o0 /* IEU0 */ + bgeu,pt %XCC, 210f /* CTI */ + mov %g3, %o1 /* IEU0 Group */ +#ifndef USE_BPR + srl %o2, 0, %o2 /* IEU1 */ +#endif + brnz,pn %o2, 220f /* CTI Group */ + add %o0, %o2, %o0 /* IEU0 */ + retl + nop +END(bcopy) +#endif + + .align 32 +200: be,pt %xcc, 201f /* CTI */ + andcc %o0, 0x38, %g5 /* IEU1 Group */ + mov 8, %g1 /* IEU0 */ + sub %g1, %g2, %g2 /* IEU0 Group */ + andcc %o0, 1, %g0 /* IEU1 */ + be,pt %icc, 2f /* CTI */ + sub %o2, %g2, %o2 /* IEU0 Group */ +1: ldub [%o1], %o5 /* Load Group */ + add %o1, 1, %o1 /* IEU0 */ + add %o0, 1, %o0 /* IEU1 */ + subcc %g2, 1, %g2 /* IEU1 Group */ + be,pn %xcc, 3f /* CTI */ + stb %o5, [%o0 - 1] /* Store */ +2: ldub [%o1], %o5 /* Load Group */ + add %o0, 2, %o0 /* IEU0 */ + ldub [%o1 + 1], %g3 /* Load Group */ + subcc %g2, 2, %g2 /* IEU1 Group */ + stb %o5, [%o0 - 2] /* Store */ + add %o1, 2, %o1 /* IEU0 */ + bne,pt %xcc, 2b /* CTI Group */ + stb %g3, [%o0 - 1] /* Store */ +3: andcc %o0, 0x38, %g5 /* IEU1 Group */ +201: be,pt %icc, 202f /* CTI */ + mov 64, %g1 /* IEU0 */ + fmovd %f0, %f2 /* FPU */ + sub %g1, %g5, %g5 /* IEU0 Group */ + alignaddr %o1, %g0, %g1 /* GRU Group */ + ldd [%g1], %f4 /* Load Group */ + sub %o2, %g5, %o2 /* IEU0 */ +1: ldd [%g1 + 0x8], %f6 /* Load Group */ + add %g1, 0x8, %g1 /* IEU0 Group */ + subcc %g5, 8, %g5 /* IEU1 */ + faligndata %f4, %f6, %f0 /* GRU Group */ + std %f0, [%o0] /* Store */ + add %o1, 8, %o1 /* IEU0 Group */ + be,pn %xcc, 202f /* CTI */ + add %o0, 8, %o0 /* IEU1 */ + ldd [%g1 + 0x8], %f4 /* Load Group */ + add %g1, 8, %g1 /* IEU0 */ + subcc %g5, 8, %g5 /* IEU1 */ + faligndata %f6, %f4, %f0 /* GRU Group */ + std %f0, [%o0] /* Store */ + add %o1, 8, %o1 /* IEU0 */ + bne,pt %xcc, 1b /* CTI Group */ + add %o0, 8, %o0 /* IEU0 */ +202: membar #LoadStore | #StoreStore | #StoreLoad /* LSU Group */ + wr %g0, ASI_BLK_P, %asi /* LSU Group */ + subcc %o2, 0x40, %g6 /* IEU1 Group */ + mov %o1, %g1 /* IEU0 */ + andncc %g6, (0x40 - 1), %g6 /* IEU1 Group */ + srl %g1, 3, %g2 /* IEU0 */ + sub %o2, %g6, %g3 /* IEU0 Group */ + andn %o1, (0x40 - 1), %o1 /* IEU1 */ + and %g2, 7, %g2 /* IEU0 Group */ + andncc %g3, 0x7, %g3 /* IEU1 */ + fmovd %f0, %f2 /* FPU */ + sub %g3, 0x10, %g3 /* IEU0 Group */ + sub %o2, %g6, %o2 /* IEU1 */ + alignaddr %g1, %g0, %g0 /* GRU Group */ + add %g1, %g6, %g1 /* IEU0 Group */ + subcc %o2, %g3, %o2 /* IEU1 */ + ldda [%o1 + 0x00] %asi, %f0 /* LSU Group */ + add %g1, %g3, %g1 /* IEU0 */ + ldda [%o1 + 0x40] %asi, %f16 /* LSU Group */ + sub %g6, 0x80, %g6 /* IEU0 */ + ldda [%o1 + 0x80] %asi, %f32 /* LSU Group */ + /* Clk1 Group 8-( */ + /* Clk2 Group 8-( */ + /* Clk3 Group 8-( */ + /* Clk4 Group 8-( */ +203: rd %pc, %g5 /* PDU Group 8-( */ + addcc %g5, %lo(300f - 203b), %g5 /* IEU1 Group */ + sll %g2, 9, %g2 /* IEU0 */ + jmpl %g5 + %g2, %g0 /* CTI Group brk forced*/ + addcc %o1, 0xc0, %o1 /* IEU1 Group */ + + .align 512 /* OK, here comes the fun part... */ +300: FREG_FROB(f0, f2, f4, f6, f8, f10,f12,f14,f16) LOOP_CHUNK1(o1, o0, g6, 301f) + FREG_FROB(f16,f18,f20,f22,f24,f26,f28,f30,f32) LOOP_CHUNK2(o1, o0, g6, 302f) + FREG_FROB(f32,f34,f36,f38,f40,f42,f44,f46,f0) LOOP_CHUNK3(o1, o0, g6, 303f) + b,pt %xcc, 300b+4; faligndata %f0, %f2, %f48 +301: FREG_FROB(f16,f18,f20,f22,f24,f26,f28,f30,f32) STORE_SYNC(o0, f48) membar #Sync + FREG_FROB(f32,f34,f36,f38,f40,f42,f44,f46,f0) STORE_JUMP(o0, f48, 400f) membar #Sync +302: FREG_FROB(f32,f34,f36,f38,f40,f42,f44,f46,f0) STORE_SYNC(o0, f48) membar #Sync + FREG_FROB(f0, f2, f4, f6, f8, f10,f12,f14,f16) STORE_JUMP(o0, f48, 416f) membar #Sync +303: FREG_FROB(f0, f2, f4, f6, f8, f10,f12,f14,f16) STORE_SYNC(o0, f48) membar #Sync + FREG_FROB(f16,f18,f20,f22,f24,f26,f28,f30,f32) STORE_JUMP(o0, f48, 432f) membar #Sync + VISLOOP_PAD +310: FREG_FROB(f2, f4, f6, f8, f10,f12,f14,f16,f18) LOOP_CHUNK1(o1, o0, g6, 311f) + FREG_FROB(f18,f20,f22,f24,f26,f28,f30,f32,f34) LOOP_CHUNK2(o1, o0, g6, 312f) + FREG_FROB(f34,f36,f38,f40,f42,f44,f46,f0, f2) LOOP_CHUNK3(o1, o0, g6, 313f) + b,pt %xcc, 310b+4; faligndata %f2, %f4, %f48 +311: FREG_FROB(f18,f20,f22,f24,f26,f28,f30,f32,f34) STORE_SYNC(o0, f48) membar #Sync + FREG_FROB(f34,f36,f38,f40,f42,f44,f46,f0, f2) STORE_JUMP(o0, f48, 402f) membar #Sync +312: FREG_FROB(f34,f36,f38,f40,f42,f44,f46,f0, f2) STORE_SYNC(o0, f48) membar #Sync + FREG_FROB(f2, f4, f6, f8, f10,f12,f14,f16,f18) STORE_JUMP(o0, f48, 418f) membar #Sync +313: FREG_FROB(f2, f4, f6, f8, f10,f12,f14,f16,f18) STORE_SYNC(o0, f48) membar #Sync + FREG_FROB(f18,f20,f22,f24,f26,f28,f30,f32,f34) STORE_JUMP(o0, f48, 434f) membar #Sync + VISLOOP_PAD +320: FREG_FROB(f4, f6, f8, f10,f12,f14,f16,f18,f20) LOOP_CHUNK1(o1, o0, g6, 321f) + FREG_FROB(f20,f22,f24,f26,f28,f30,f32,f34,f36) LOOP_CHUNK2(o1, o0, g6, 322f) + FREG_FROB(f36,f38,f40,f42,f44,f46,f0, f2, f4) LOOP_CHUNK3(o1, o0, g6, 323f) + b,pt %xcc, 320b+4; faligndata %f4, %f6, %f48 +321: FREG_FROB(f20,f22,f24,f26,f28,f30,f32,f34,f36) STORE_SYNC(o0, f48) membar #Sync + FREG_FROB(f36,f38,f40,f42,f44,f46,f0, f2, f4) STORE_JUMP(o0, f48, 404f) membar #Sync +322: FREG_FROB(f36,f38,f40,f42,f44,f46,f0, f2, f4) STORE_SYNC(o0, f48) membar #Sync + FREG_FROB(f4, f6, f8, f10,f12,f14,f16,f18,f20) STORE_JUMP(o0, f48, 420f) membar #Sync +323: FREG_FROB(f4, f6, f8, f10,f12,f14,f16,f18,f20) STORE_SYNC(o0, f48) membar #Sync + FREG_FROB(f20,f22,f24,f26,f28,f30,f32,f34,f36) STORE_JUMP(o0, f48, 436f) membar #Sync + VISLOOP_PAD +330: FREG_FROB(f6, f8, f10,f12,f14,f16,f18,f20,f22) LOOP_CHUNK1(o1, o0, g6, 331f) + FREG_FROB(f22,f24,f26,f28,f30,f32,f34,f36,f38) LOOP_CHUNK2(o1, o0, g6, 332f) + FREG_FROB(f38,f40,f42,f44,f46,f0, f2, f4, f6) LOOP_CHUNK3(o1, o0, g6, 333f) + b,pt %xcc, 330b+4; faligndata %f6, %f8, %f48 +331: FREG_FROB(f22,f24,f26,f28,f30,f32,f34,f36,f38) STORE_SYNC(o0, f48) membar #Sync + FREG_FROB(f38,f40,f42,f44,f46,f0, f2, f4, f6) STORE_JUMP(o0, f48, 406f) membar #Sync +332: FREG_FROB(f38,f40,f42,f44,f46,f0, f2, f4, f6) STORE_SYNC(o0, f48) membar #Sync + FREG_FROB(f6, f8, f10,f12,f14,f16,f18,f20,f22) STORE_JUMP(o0, f48, 422f) membar #Sync +333: FREG_FROB(f6, f8, f10,f12,f14,f16,f18,f20,f22) STORE_SYNC(o0, f48) membar #Sync + FREG_FROB(f22,f24,f26,f28,f30,f32,f34,f36,f38) STORE_JUMP(o0, f48, 438f) membar #Sync + VISLOOP_PAD +340: FREG_FROB(f8, f10,f12,f14,f16,f18,f20,f22,f24) LOOP_CHUNK1(o1, o0, g6, 341f) + FREG_FROB(f24,f26,f28,f30,f32,f34,f36,f38,f40) LOOP_CHUNK2(o1, o0, g6, 342f) + FREG_FROB(f40,f42,f44,f46,f0, f2, f4, f6, f8) LOOP_CHUNK3(o1, o0, g6, 343f) + b,pt %xcc, 340b+4; faligndata %f8, %f10, %f48 +341: FREG_FROB(f24,f26,f28,f30,f32,f34,f36,f38,f40) STORE_SYNC(o0, f48) membar #Sync + FREG_FROB(f40,f42,f44,f46,f0, f2, f4, f6, f8) STORE_JUMP(o0, f48, 408f) membar #Sync +342: FREG_FROB(f40,f42,f44,f46,f0, f2, f4, f6, f8) STORE_SYNC(o0, f48) membar #Sync + FREG_FROB(f8, f10,f12,f14,f16,f18,f20,f22,f24) STORE_JUMP(o0, f48, 424f) membar #Sync +343: FREG_FROB(f8, f10,f12,f14,f16,f18,f20,f22,f24) STORE_SYNC(o0, f48) membar #Sync + FREG_FROB(f24,f26,f28,f30,f32,f34,f36,f38,f40) STORE_JUMP(o0, f48, 440f) membar #Sync + VISLOOP_PAD +350: FREG_FROB(f10,f12,f14,f16,f18,f20,f22,f24,f26) LOOP_CHUNK1(o1, o0, g6, 351f) + FREG_FROB(f26,f28,f30,f32,f34,f36,f38,f40,f42) LOOP_CHUNK2(o1, o0, g6, 352f) + FREG_FROB(f42,f44,f46,f0, f2, f4, f6, f8, f10) LOOP_CHUNK3(o1, o0, g6, 353f) + b,pt %xcc, 350b+4; faligndata %f10, %f12, %f48 +351: FREG_FROB(f26,f28,f30,f32,f34,f36,f38,f40,f42) STORE_SYNC(o0, f48) membar #Sync + FREG_FROB(f42,f44,f46,f0, f2, f4, f6, f8, f10) STORE_JUMP(o0, f48, 410f) membar #Sync +352: FREG_FROB(f42,f44,f46,f0, f2, f4, f6, f8, f10) STORE_SYNC(o0, f48) membar #Sync + FREG_FROB(f10,f12,f14,f16,f18,f20,f22,f24,f26) STORE_JUMP(o0, f48, 426f) membar #Sync +353: FREG_FROB(f10,f12,f14,f16,f18,f20,f22,f24,f26) STORE_SYNC(o0, f48) membar #Sync + FREG_FROB(f26,f28,f30,f32,f34,f36,f38,f40,f42) STORE_JUMP(o0, f48, 442f) membar #Sync + VISLOOP_PAD +360: FREG_FROB(f12,f14,f16,f18,f20,f22,f24,f26,f28) LOOP_CHUNK1(o1, o0, g6, 361f) + FREG_FROB(f28,f30,f32,f34,f36,f38,f40,f42,f44) LOOP_CHUNK2(o1, o0, g6, 362f) + FREG_FROB(f44,f46,f0, f2, f4, f6, f8, f10,f12) LOOP_CHUNK3(o1, o0, g6, 363f) + b,pt %xcc, 360b+4; faligndata %f12, %f14, %f48 +361: FREG_FROB(f28,f30,f32,f34,f36,f38,f40,f42,f44) STORE_SYNC(o0, f48) membar #Sync + FREG_FROB(f44,f46,f0, f2, f4, f6, f8, f10,f12) STORE_JUMP(o0, f48, 412f) membar #Sync +362: FREG_FROB(f44,f46,f0, f2, f4, f6, f8, f10,f12) STORE_SYNC(o0, f48) membar #Sync + FREG_FROB(f12,f14,f16,f18,f20,f22,f24,f26,f28) STORE_JUMP(o0, f48, 428f) membar #Sync +363: FREG_FROB(f12,f14,f16,f18,f20,f22,f24,f26,f28) STORE_SYNC(o0, f48) membar #Sync + FREG_FROB(f28,f30,f32,f34,f36,f38,f40,f42,f44) STORE_JUMP(o0, f48, 444f) membar #Sync + VISLOOP_PAD +370: FREG_FROB(f14,f16,f18,f20,f22,f24,f26,f28,f30) LOOP_CHUNK1(o1, o0, g6, 371f) + FREG_FROB(f30,f32,f34,f36,f38,f40,f42,f44,f46) LOOP_CHUNK2(o1, o0, g6, 372f) + FREG_FROB(f46,f0, f2, f4, f6, f8, f10,f12,f14) LOOP_CHUNK3(o1, o0, g6, 373f) + b,pt %xcc, 370b+4; faligndata %f14, %f16, %f48 +371: FREG_FROB(f30,f32,f34,f36,f38,f40,f42,f44,f46) STORE_SYNC(o0, f48) membar #Sync + FREG_FROB(f46,f0, f2, f4, f6, f8, f10,f12,f14) STORE_JUMP(o0, f48, 414f) membar #Sync +372: FREG_FROB(f46,f0, f2, f4, f6, f8, f10,f12,f14) STORE_SYNC(o0, f48) membar #Sync + FREG_FROB(f14,f16,f18,f20,f22,f24,f26,f28,f30) STORE_JUMP(o0, f48, 430f) membar #Sync +373: FREG_FROB(f14,f16,f18,f20,f22,f24,f26,f28,f30) STORE_SYNC(o0, f48) membar #Sync + FREG_FROB(f30,f32,f34,f36,f38,f40,f42,f44,f46) STORE_JUMP(o0, f48, 446f) membar #Sync + VISLOOP_PAD +400: FINISH_VISCHUNK(o0, f0, f2, g3) +402: FINISH_VISCHUNK(o0, f2, f4, g3) +404: FINISH_VISCHUNK(o0, f4, f6, g3) +406: FINISH_VISCHUNK(o0, f6, f8, g3) +408: FINISH_VISCHUNK(o0, f8, f10, g3) +410: FINISH_VISCHUNK(o0, f10, f12, g3) +412: FINISH_VISCHUNK(o0, f12, f14, g3) +414: UNEVEN_VISCHUNK(o0, f14, f0, g3) +416: FINISH_VISCHUNK(o0, f16, f18, g3) +418: FINISH_VISCHUNK(o0, f18, f20, g3) +420: FINISH_VISCHUNK(o0, f20, f22, g3) +422: FINISH_VISCHUNK(o0, f22, f24, g3) +424: FINISH_VISCHUNK(o0, f24, f26, g3) +426: FINISH_VISCHUNK(o0, f26, f28, g3) +428: FINISH_VISCHUNK(o0, f28, f30, g3) +430: UNEVEN_VISCHUNK(o0, f30, f0, g3) +432: FINISH_VISCHUNK(o0, f32, f34, g3) +434: FINISH_VISCHUNK(o0, f34, f36, g3) +436: FINISH_VISCHUNK(o0, f36, f38, g3) +438: FINISH_VISCHUNK(o0, f38, f40, g3) +440: FINISH_VISCHUNK(o0, f40, f42, g3) +442: FINISH_VISCHUNK(o0, f42, f44, g3) +444: FINISH_VISCHUNK(o0, f44, f46, g3) +446: UNEVEN_VISCHUNK(o0, f46, f0, g3) +204: ldd [%o1], %f2 /* Load Group */ + add %o1, 8, %o1 /* IEU0 */ + subcc %g3, 8, %g3 /* IEU1 */ + faligndata %f0, %f2, %f8 /* GRU Group */ + std %f8, [%o0] /* Store */ + bl,pn %xcc, 205f /* CTI */ + add %o0, 8, %o0 /* IEU0 Group */ + ldd [%o1], %f0 /* Load Group */ + add %o1, 8, %o1 /* IEU0 */ + subcc %g3, 8, %g3 /* IEU1 */ + faligndata %f2, %f0, %f8 /* GRU Group */ + std %f8, [%o0] /* Store */ + bge,pt %xcc, 204b /* CTI */ + add %o0, 8, %o0 /* IEU0 Group */ +205: brz,pt %o2, 207f /* CTI Group */ + mov %g1, %o1 /* IEU0 */ +206: ldub [%o1], %g5 /* LOAD */ + add %o1, 1, %o1 /* IEU0 */ + add %o0, 1, %o0 /* IEU1 */ + subcc %o2, 1, %o2 /* IEU1 */ + bne,pt %xcc, 206b /* CTI */ + stb %g5, [%o0 - 1] /* Store Group */ +207: membar #StoreLoad | #StoreStore /* LSU Group */ + wr %g0, FPRS_FEF, %fprs + retl + mov %g4, %o0 + +208: andcc %o2, 1, %g0 /* IEU1 Group */ + be,pt %icc, 2f+4 /* CTI */ +1: ldub [%o1], %g5 /* LOAD Group */ + add %o1, 1, %o1 /* IEU0 */ + add %o0, 1, %o0 /* IEU1 */ + subcc %o2, 1, %o2 /* IEU1 Group */ + be,pn %xcc, 209f /* CTI */ + stb %g5, [%o0 - 1] /* Store */ +2: ldub [%o1], %g5 /* LOAD Group */ + add %o0, 2, %o0 /* IEU0 */ + ldub [%o1 + 1], %o5 /* LOAD Group */ + add %o1, 2, %o1 /* IEU0 */ + subcc %o2, 2, %o2 /* IEU1 Group */ + stb %g5, [%o0 - 2] /* Store */ + bne,pt %xcc, 2b /* CTI */ + stb %o5, [%o0 - 1] /* Store */ +209: retl + mov %g4, %o0 + +#ifdef USE_BPR + + /* void *__align_cpy_4(void *dest, void *src, size_t n) + * SPARC v9 SYSV ABI + * Like memcpy, but results are undefined if (!n || ((dest | src | n) & 3)) + */ + + .align 32 +ENTRY(__align_cpy_4) + mov %o0, %g4 /* IEU0 Group */ + cmp %o2, 15 /* IEU1 */ + bleu,pn %xcc, 208b /* CTI */ + cmp %o2, (64 * 6) /* IEU1 Group */ + bgeu,pn %xcc, 200b /* CTI */ + andcc %o0, 7, %g2 /* IEU1 Group */ + ba,pt %xcc, 216f /* CTI */ + andcc %o1, 4, %g0 /* IEU1 Group */ +END(__align_cpy_4) + + /* void *__align_cpy_8(void *dest, void *src, size_t n) + * SPARC v9 SYSV ABI + * Like memcpy, but results are undefined if (!n || ((dest | src | n) & 7)) + */ + + .align 32 +ENTRY(__align_cpy_8) + mov %o0, %g4 /* IEU0 Group */ + cmp %o2, 15 /* IEU1 */ + bleu,pn %xcc, 208b /* CTI */ + cmp %o2, (64 * 6) /* IEU1 Group */ + bgeu,pn %xcc, 201b /* CTI */ + andcc %o0, 0x38, %g5 /* IEU1 Group */ + andcc %o2, -128, %g6 /* IEU1 Group */ + bne,a,pt %xcc, 82f + 4 /* CTI */ + ldx [%o1], %g1 /* Load */ + ba,pt %xcc, 41f /* CTI Group */ + andcc %o2, 0x70, %g6 /* IEU1 */ +END(__align_cpy_8) + + /* void *__align_cpy_16(void *dest, void *src, size_t n) + * SPARC v9 SYSV ABI + * Like memcpy, but results are undefined if (!n || ((dest | src | n) & 15)) + */ + + .align 32 +ENTRY(__align_cpy_16) + mov %o0, %g4 /* IEU0 Group */ + cmp %o2, (64 * 6) /* IEU1 */ + bgeu,pn %xcc, 201b /* CTI */ + andcc %o0, 0x38, %g5 /* IEU1 Group */ + andcc %o2, -128, %g6 /* IEU1 Group */ + bne,a,pt %xcc, 82f + 4 /* CTI */ + ldx [%o1], %g1 /* Load */ + ba,pt %xcc, 41f /* CTI Group */ + andcc %o2, 0x70, %g6 /* IEU1 */ +END(__align_cpy_16) + +#endif + + .align 32 +ENTRY(memcpy) +210: +#ifndef USE_BPR + srl %o2, 0, %o2 /* IEU1 Group */ +#endif + brz,pn %o2, 209b /* CTI Group */ + mov %o0, %g4 /* IEU0 */ +218: cmp %o2, 15 /* IEU1 Group */ + bleu,pn %xcc, 208b /* CTI */ + cmp %o2, (64 * 6) /* IEU1 Group */ + bgeu,pn %xcc, 200b /* CTI */ + andcc %o0, 7, %g2 /* IEU1 Group */ + sub %o0, %o1, %g5 /* IEU0 */ + andcc %g5, 3, %o5 /* IEU1 Group */ + bne,pn %xcc, 212f /* CTI */ + andcc %o1, 3, %g0 /* IEU1 Group */ + be,a,pt %xcc, 216f /* CTI */ + andcc %o1, 4, %g0 /* IEU1 Group */ + andcc %o1, 1, %g0 /* IEU1 Group */ + be,pn %xcc, 4f /* CTI */ + andcc %o1, 2, %g0 /* IEU1 Group */ + ldub [%o1], %g2 /* Load Group */ + add %o1, 1, %o1 /* IEU0 */ + add %o0, 1, %o0 /* IEU1 */ + sub %o2, 1, %o2 /* IEU0 Group */ + bne,pn %xcc, 5f /* CTI Group */ + stb %g2, [%o0 - 1] /* Store */ +4: lduh [%o1], %g2 /* Load Group */ + add %o1, 2, %o1 /* IEU0 */ + add %o0, 2, %o0 /* IEU1 */ + sub %o2, 2, %o2 /* IEU0 */ + sth %g2, [%o0 - 2] /* Store Group + bubble */ +5: andcc %o1, 4, %g0 /* IEU1 */ +216: be,a,pn %xcc, 2f /* CTI */ + andcc %o2, -128, %g6 /* IEU1 Group */ + lduw [%o1], %g5 /* Load Group */ + add %o1, 4, %o1 /* IEU0 */ + add %o0, 4, %o0 /* IEU1 */ + sub %o2, 4, %o2 /* IEU0 Group */ + stw %g5, [%o0 - 4] /* Store */ + andcc %o2, -128, %g6 /* IEU1 Group */ +2: be,pn %xcc, 215f /* CTI */ + andcc %o0, 4, %g0 /* IEU1 Group */ + be,pn %xcc, 82f + 4 /* CTI Group */ +5: MOVE_BIGCHUNK(o1, o0, 0x00, g1, g3, g5, o5) + MOVE_BIGCHUNK(o1, o0, 0x20, g1, g3, g5, o5) + MOVE_BIGCHUNK(o1, o0, 0x40, g1, g3, g5, o5) + MOVE_BIGCHUNK(o1, o0, 0x60, g1, g3, g5, o5) +35: subcc %g6, 128, %g6 /* IEU1 Group */ + add %o1, 128, %o1 /* IEU0 */ + bne,pt %xcc, 5b /* CTI */ + add %o0, 128, %o0 /* IEU0 Group */ +215: andcc %o2, 0x70, %g6 /* IEU1 Group */ +41: be,pn %xcc, 80f /* CTI */ + andcc %o2, 8, %g0 /* IEU1 Group */ + /* Clk1 8-( */ + /* Clk2 8-( */ + /* Clk3 8-( */ + /* Clk4 8-( */ +79: rd %pc, %o5 /* PDU Group */ + sll %g6, 1, %g5 /* IEU0 Group */ + add %o1, %g6, %o1 /* IEU1 */ + sub %o5, %g5, %o5 /* IEU0 Group */ + jmpl %o5 + %lo(80f - 79b), %g0 /* CTI Group brk forced*/ + add %o0, %g6, %o0 /* IEU0 Group */ +36: MOVE_LASTCHUNK(o1, o0, 0x60, g2, g3, g5, o5) + MOVE_LASTCHUNK(o1, o0, 0x50, g2, g3, g5, o5) + MOVE_LASTCHUNK(o1, o0, 0x40, g2, g3, g5, o5) + MOVE_LASTCHUNK(o1, o0, 0x30, g2, g3, g5, o5) + MOVE_LASTCHUNK(o1, o0, 0x20, g2, g3, g5, o5) + MOVE_LASTCHUNK(o1, o0, 0x10, g2, g3, g5, o5) + MOVE_LASTCHUNK(o1, o0, 0x00, g2, g3, g5, o5) +80: be,pt %xcc, 81f /* CTI */ + andcc %o2, 4, %g0 /* IEU1 */ + ldx [%o1], %g2 /* Load Group */ + add %o0, 8, %o0 /* IEU0 */ + stw %g2, [%o0 - 0x4] /* Store Group */ + add %o1, 8, %o1 /* IEU1 */ + srlx %g2, 32, %g2 /* IEU0 Group */ + stw %g2, [%o0 - 0x8] /* Store */ +81: be,pt %xcc, 1f /* CTI */ + andcc %o2, 2, %g0 /* IEU1 Group */ + lduw [%o1], %g2 /* Load Group */ + add %o1, 4, %o1 /* IEU0 */ + stw %g2, [%o0] /* Store Group */ + add %o0, 4, %o0 /* IEU0 */ +1: be,pt %xcc, 1f /* CTI */ + andcc %o2, 1, %g0 /* IEU1 Group */ + lduh [%o1], %g2 /* Load Group */ + add %o1, 2, %o1 /* IEU0 */ + sth %g2, [%o0] /* Store Group */ + add %o0, 2, %o0 /* IEU0 */ +1: be,pt %xcc, 211f /* CTI */ + nop /* IEU1 */ + ldub [%o1], %g2 /* Load Group */ + stb %g2, [%o0] /* Store Group + bubble */ +211: retl + mov %g4, %o0 + +82: MOVE_BIGALIGNCHUNK(o1, o0, 0x00, g1, g3, g5, o5) + MOVE_BIGALIGNCHUNK(o1, o0, 0x40, g1, g3, g5, o5) +37: subcc %g6, 128, %g6 /* IEU1 Group */ + add %o1, 128, %o1 /* IEU0 */ + bne,pt %xcc, 82b /* CTI */ + add %o0, 128, %o0 /* IEU0 Group */ + andcc %o2, 0x70, %g6 /* IEU1 */ + be,pn %xcc, 84f /* CTI */ + andcc %o2, 8, %g0 /* IEU1 Group */ + /* Clk1 8-( */ + /* Clk2 8-( */ + /* Clk3 8-( */ + /* Clk4 8-( */ +83: rd %pc, %o5 /* PDU Group */ + add %o1, %g6, %o1 /* IEU0 Group */ + sub %o5, %g6, %o5 /* IEU1 */ + jmpl %o5 + %lo(84f - 83b), %g0 /* CTI Group brk forced*/ + add %o0, %g6, %o0 /* IEU0 Group */ +38: MOVE_LASTALIGNCHUNK(o1, o0, 0x60, g2, g3) + MOVE_LASTALIGNCHUNK(o1, o0, 0x50, g2, g3) + MOVE_LASTALIGNCHUNK(o1, o0, 0x40, g2, g3) + MOVE_LASTALIGNCHUNK(o1, o0, 0x30, g2, g3) + MOVE_LASTALIGNCHUNK(o1, o0, 0x20, g2, g3) + MOVE_LASTALIGNCHUNK(o1, o0, 0x10, g2, g3) + MOVE_LASTALIGNCHUNK(o1, o0, 0x00, g2, g3) +84: be,pt %xcc, 85f /* CTI Group */ + andcc %o2, 4, %g0 /* IEU1 */ + ldx [%o1], %g2 /* Load Group */ + add %o0, 8, %o0 /* IEU0 */ + add %o1, 8, %o1 /* IEU0 Group */ + stx %g2, [%o0 - 0x8] /* Store */ +85: be,pt %xcc, 1f /* CTI */ + andcc %o2, 2, %g0 /* IEU1 Group */ + lduw [%o1], %g2 /* Load Group */ + add %o0, 4, %o0 /* IEU0 */ + add %o1, 4, %o1 /* IEU0 Group */ + stw %g2, [%o0 - 0x4] /* Store */ +1: be,pt %xcc, 1f /* CTI */ + andcc %o2, 1, %g0 /* IEU1 Group */ + lduh [%o1], %g2 /* Load Group */ + add %o0, 2, %o0 /* IEU0 */ + add %o1, 2, %o1 /* IEU0 Group */ + sth %g2, [%o0 - 0x2] /* Store */ +1: be,pt %xcc, 1f /* CTI */ + nop /* IEU0 Group */ + ldub [%o1], %g2 /* Load Group */ + stb %g2, [%o0] /* Store Group + bubble */ +1: retl + mov %g4, %o0 + +212: brz,pt %g2, 2f /* CTI Group */ + mov 8, %g1 /* IEU0 */ + sub %g1, %g2, %g2 /* IEU0 Group */ + sub %o2, %g2, %o2 /* IEU0 Group */ +1: ldub [%o1], %g5 /* Load Group */ + add %o1, 1, %o1 /* IEU0 */ + add %o0, 1, %o0 /* IEU1 */ + subcc %g2, 1, %g2 /* IEU1 Group */ + bne,pt %xcc, 1b /* CTI */ + stb %g5, [%o0 - 1] /* Store */ +2: andn %o2, 7, %g5 /* IEU0 Group */ + and %o2, 7, %o2 /* IEU1 */ + fmovd %f0, %f2 /* FPU */ + alignaddr %o1, %g0, %g1 /* GRU Group */ + ldd [%g1], %f4 /* Load Group */ +1: ldd [%g1 + 0x8], %f6 /* Load Group */ + add %g1, 0x8, %g1 /* IEU0 Group */ + subcc %g5, 8, %g5 /* IEU1 */ + faligndata %f4, %f6, %f0 /* GRU Group */ + std %f0, [%o0] /* Store */ + add %o1, 8, %o1 /* IEU0 Group */ + be,pn %xcc, 213f /* CTI */ + add %o0, 8, %o0 /* IEU1 */ + ldd [%g1 + 0x8], %f4 /* Load Group */ + add %g1, 8, %g1 /* IEU0 */ + subcc %g5, 8, %g5 /* IEU1 */ + faligndata %f6, %f4, %f0 /* GRU Group */ + std %f0, [%o0] /* Store */ + add %o1, 8, %o1 /* IEU0 */ + bne,pn %xcc, 1b /* CTI Group */ + add %o0, 8, %o0 /* IEU0 */ +213: brz,pn %o2, 214f /* CTI Group */ + nop /* IEU0 */ + ldub [%o1], %g5 /* LOAD */ + add %o1, 1, %o1 /* IEU0 */ + add %o0, 1, %o0 /* IEU1 */ + subcc %o2, 1, %o2 /* IEU1 */ + bne,pt %xcc, 206b /* CTI */ + stb %g5, [%o0 - 1] /* Store Group */ +214: wr %g0, FPRS_FEF, %fprs + retl + mov %g4, %o0 +END(memcpy) +libc_hidden_def(memcpy) + + .align 32 +228: andcc %o2, 1, %g0 /* IEU1 Group */ + be,pt %icc, 2f+4 /* CTI */ +1: ldub [%o1 - 1], %o5 /* LOAD Group */ + sub %o1, 1, %o1 /* IEU0 */ + sub %o0, 1, %o0 /* IEU1 */ + subcc %o2, 1, %o2 /* IEU1 Group */ + be,pn %xcc, 229f /* CTI */ + stb %o5, [%o0] /* Store */ +2: ldub [%o1 - 1], %o5 /* LOAD Group */ + sub %o0, 2, %o0 /* IEU0 */ + ldub [%o1 - 2], %g5 /* LOAD Group */ + sub %o1, 2, %o1 /* IEU0 */ + subcc %o2, 2, %o2 /* IEU1 Group */ + stb %o5, [%o0 + 1] /* Store */ + bne,pt %xcc, 2b /* CTI */ + stb %g5, [%o0] /* Store */ +229: retl + mov %g4, %o0 +219: retl + nop + + .align 32 +ENTRY(memmove) +#ifndef USE_BPR + srl %o2, 0, %o2 /* IEU1 Group */ +#endif + brz,pn %o2, 219b /* CTI Group */ + sub %o0, %o1, %o4 /* IEU0 */ + cmp %o4, %o2 /* IEU1 Group */ + bgeu,pt %XCC, 218b /* CTI */ + mov %o0, %g4 /* IEU0 */ + add %o0, %o2, %o0 /* IEU0 Group */ +220: add %o1, %o2, %o1 /* IEU1 */ + cmp %o2, 15 /* IEU1 Group */ + bleu,pn %xcc, 228b /* CTI */ + andcc %o0, 7, %g2 /* IEU1 Group */ + sub %o0, %o1, %g5 /* IEU0 */ + andcc %g5, 3, %o5 /* IEU1 Group */ + bne,pn %xcc, 232f /* CTI */ + andcc %o1, 3, %g0 /* IEU1 Group */ + be,a,pt %xcc, 236f /* CTI */ + andcc %o1, 4, %g0 /* IEU1 Group */ + andcc %o1, 1, %g0 /* IEU1 Group */ + be,pn %xcc, 4f /* CTI */ + andcc %o1, 2, %g0 /* IEU1 Group */ + ldub [%o1 - 1], %g2 /* Load Group */ + sub %o1, 1, %o1 /* IEU0 */ + sub %o0, 1, %o0 /* IEU1 */ + sub %o2, 1, %o2 /* IEU0 Group */ + be,pn %xcc, 5f /* CTI Group */ + stb %g2, [%o0] /* Store */ +4: lduh [%o1 - 2], %g2 /* Load Group */ + sub %o1, 2, %o1 /* IEU0 */ + sub %o0, 2, %o0 /* IEU1 */ + sub %o2, 2, %o2 /* IEU0 */ + sth %g2, [%o0] /* Store Group + bubble */ +5: andcc %o1, 4, %g0 /* IEU1 */ +236: be,a,pn %xcc, 2f /* CTI */ + andcc %o2, -128, %g6 /* IEU1 Group */ + lduw [%o1 - 4], %g5 /* Load Group */ + sub %o1, 4, %o1 /* IEU0 */ + sub %o0, 4, %o0 /* IEU1 */ + sub %o2, 4, %o2 /* IEU0 Group */ + stw %g5, [%o0] /* Store */ + andcc %o2, -128, %g6 /* IEU1 Group */ +2: be,pn %xcc, 235f /* CTI */ + andcc %o0, 4, %g0 /* IEU1 Group */ + be,pn %xcc, 282f + 4 /* CTI Group */ +5: RMOVE_BIGCHUNK(o1, o0, 0x00, g1, g3, g5, o5) + RMOVE_BIGCHUNK(o1, o0, 0x20, g1, g3, g5, o5) + RMOVE_BIGCHUNK(o1, o0, 0x40, g1, g3, g5, o5) + RMOVE_BIGCHUNK(o1, o0, 0x60, g1, g3, g5, o5) + subcc %g6, 128, %g6 /* IEU1 Group */ + sub %o1, 128, %o1 /* IEU0 */ + bne,pt %xcc, 5b /* CTI */ + sub %o0, 128, %o0 /* IEU0 Group */ +235: andcc %o2, 0x70, %g6 /* IEU1 Group */ +41: be,pn %xcc, 280f /* CTI */ + andcc %o2, 8, %g0 /* IEU1 Group */ + /* Clk1 8-( */ + /* Clk2 8-( */ + /* Clk3 8-( */ + /* Clk4 8-( */ +279: rd %pc, %o5 /* PDU Group */ + sll %g6, 1, %g5 /* IEU0 Group */ + sub %o1, %g6, %o1 /* IEU1 */ + sub %o5, %g5, %o5 /* IEU0 Group */ + jmpl %o5 + %lo(280f - 279b), %g0 /* CTI Group brk forced*/ + sub %o0, %g6, %o0 /* IEU0 Group */ + RMOVE_LASTCHUNK(o1, o0, 0x60, g2, g3, g5, o5) + RMOVE_LASTCHUNK(o1, o0, 0x50, g2, g3, g5, o5) + RMOVE_LASTCHUNK(o1, o0, 0x40, g2, g3, g5, o5) + RMOVE_LASTCHUNK(o1, o0, 0x30, g2, g3, g5, o5) + RMOVE_LASTCHUNK(o1, o0, 0x20, g2, g3, g5, o5) + RMOVE_LASTCHUNK(o1, o0, 0x10, g2, g3, g5, o5) + RMOVE_LASTCHUNK(o1, o0, 0x00, g2, g3, g5, o5) +280: be,pt %xcc, 281f /* CTI */ + andcc %o2, 4, %g0 /* IEU1 */ + ldx [%o1 - 8], %g2 /* Load Group */ + sub %o0, 8, %o0 /* IEU0 */ + stw %g2, [%o0 + 4] /* Store Group */ + sub %o1, 8, %o1 /* IEU1 */ + srlx %g2, 32, %g2 /* IEU0 Group */ + stw %g2, [%o0] /* Store */ +281: be,pt %xcc, 1f /* CTI */ + andcc %o2, 2, %g0 /* IEU1 Group */ + lduw [%o1 - 4], %g2 /* Load Group */ + sub %o1, 4, %o1 /* IEU0 */ + stw %g2, [%o0 - 4] /* Store Group */ + sub %o0, 4, %o0 /* IEU0 */ +1: be,pt %xcc, 1f /* CTI */ + andcc %o2, 1, %g0 /* IEU1 Group */ + lduh [%o1 - 2], %g2 /* Load Group */ + sub %o1, 2, %o1 /* IEU0 */ + sth %g2, [%o0 - 2] /* Store Group */ + sub %o0, 2, %o0 /* IEU0 */ +1: be,pt %xcc, 211f /* CTI */ + nop /* IEU1 */ + ldub [%o1 - 1], %g2 /* Load Group */ + stb %g2, [%o0 - 1] /* Store Group + bubble */ +211: retl + mov %g4, %o0 + +282: RMOVE_BIGALIGNCHUNK(o1, o0, 0x00, g1, g3, g5, o5) + RMOVE_BIGALIGNCHUNK(o1, o0, 0x40, g1, g3, g5, o5) + subcc %g6, 128, %g6 /* IEU1 Group */ + sub %o1, 128, %o1 /* IEU0 */ + bne,pt %xcc, 282b /* CTI */ + sub %o0, 128, %o0 /* IEU0 Group */ + andcc %o2, 0x70, %g6 /* IEU1 */ + be,pn %xcc, 284f /* CTI */ + andcc %o2, 8, %g0 /* IEU1 Group */ + /* Clk1 8-( */ + /* Clk2 8-( */ + /* Clk3 8-( */ + /* Clk4 8-( */ +283: rd %pc, %o5 /* PDU Group */ + sub %o1, %g6, %o1 /* IEU0 Group */ + sub %o5, %g6, %o5 /* IEU1 */ + jmpl %o5 + %lo(284f - 283b), %g0 /* CTI Group brk forced*/ + sub %o0, %g6, %o0 /* IEU0 Group */ + RMOVE_LASTALIGNCHUNK(o1, o0, 0x60, g2, g3) + RMOVE_LASTALIGNCHUNK(o1, o0, 0x50, g2, g3) + RMOVE_LASTALIGNCHUNK(o1, o0, 0x40, g2, g3) + RMOVE_LASTALIGNCHUNK(o1, o0, 0x30, g2, g3) + RMOVE_LASTALIGNCHUNK(o1, o0, 0x20, g2, g3) + RMOVE_LASTALIGNCHUNK(o1, o0, 0x10, g2, g3) + RMOVE_LASTALIGNCHUNK(o1, o0, 0x00, g2, g3) +284: be,pt %xcc, 285f /* CTI Group */ + andcc %o2, 4, %g0 /* IEU1 */ + ldx [%o1 - 8], %g2 /* Load Group */ + sub %o0, 8, %o0 /* IEU0 */ + sub %o1, 8, %o1 /* IEU0 Group */ + stx %g2, [%o0] /* Store */ +285: be,pt %xcc, 1f /* CTI */ + andcc %o2, 2, %g0 /* IEU1 Group */ + lduw [%o1 - 4], %g2 /* Load Group */ + sub %o0, 4, %o0 /* IEU0 */ + sub %o1, 4, %o1 /* IEU0 Group */ + stw %g2, [%o0] /* Store */ +1: be,pt %xcc, 1f /* CTI */ + andcc %o2, 1, %g0 /* IEU1 Group */ + lduh [%o1 - 2], %g2 /* Load Group */ + sub %o0, 2, %o0 /* IEU0 */ + sub %o1, 2, %o1 /* IEU0 Group */ + sth %g2, [%o0] /* Store */ +1: be,pt %xcc, 1f /* CTI */ + nop /* IEU0 Group */ + ldub [%o1 - 1], %g2 /* Load Group */ + stb %g2, [%o0 - 1] /* Store Group + bubble */ +1: retl + mov %g4, %o0 + +232: brz,pt %g2, 2f /* CTI Group */ + sub %o2, %g2, %o2 /* IEU0 Group */ +1: ldub [%o1 - 1], %g5 /* Load Group */ + sub %o1, 1, %o1 /* IEU0 */ + sub %o0, 1, %o0 /* IEU1 */ + subcc %g2, 1, %g2 /* IEU1 Group */ + bne,pt %xcc, 1b /* CTI */ + stb %g5, [%o0] /* Store */ +2: andn %o2, 7, %g5 /* IEU0 Group */ + and %o2, 7, %o2 /* IEU1 */ + fmovd %f0, %f2 /* FPU */ + alignaddr %o1, %g0, %g1 /* GRU Group */ + ldd [%g1], %f4 /* Load Group */ +1: ldd [%g1 - 8], %f6 /* Load Group */ + sub %g1, 8, %g1 /* IEU0 Group */ + subcc %g5, 8, %g5 /* IEU1 */ + faligndata %f6, %f4, %f0 /* GRU Group */ + std %f0, [%o0 - 8] /* Store */ + sub %o1, 8, %o1 /* IEU0 Group */ + be,pn %xcc, 233f /* CTI */ + sub %o0, 8, %o0 /* IEU1 */ + ldd [%g1 - 8], %f4 /* Load Group */ + sub %g1, 8, %g1 /* IEU0 */ + subcc %g5, 8, %g5 /* IEU1 */ + faligndata %f4, %f6, %f0 /* GRU Group */ + std %f0, [%o0 - 8] /* Store */ + sub %o1, 8, %o1 /* IEU0 */ + bne,pn %xcc, 1b /* CTI Group */ + sub %o0, 8, %o0 /* IEU0 */ +233: brz,pn %o2, 234f /* CTI Group */ + nop /* IEU0 */ +237: ldub [%o1 - 1], %g5 /* LOAD */ + sub %o1, 1, %o1 /* IEU0 */ + sub %o0, 1, %o0 /* IEU1 */ + subcc %o2, 1, %o2 /* IEU1 */ + bne,pt %xcc, 237b /* CTI */ + stb %g5, [%o0] /* Store Group */ +234: wr %g0, FPRS_FEF, %fprs + retl + mov %g4, %o0 +END(memmove) +libc_hidden_def(memmove) + +#ifdef USE_BPR +weak_alias(memcpy,__align_cpy_1) +weak_alias(memcpy,__align_cpy_2) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc64/memset.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc64/memset.S new file mode 100644 index 00000000..50e404bc --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc64/memset.S @@ -0,0 +1,317 @@ +/* Set a block of memory to some byte value. + For UltraSPARC. + Copyright (C) 1996, 97, 98, 99, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by David S. Miller (davem@caip.rutgers.edu) and + Jakub Jelinek (jj@ultra.linux.cz). + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#ifndef XCC +#define XCC xcc +#define USE_BPR +#endif +#define FPRS_FEF 4 + +#define SET_BLOCKS(base, offset, source) \ + stx source, [base - offset - 0x18]; \ + stx source, [base - offset - 0x10]; \ + stx source, [base - offset - 0x08]; \ + stx source, [base - offset - 0x00]; + + /* Well, memset is a lot easier to get right than bcopy... */ + .text + .align 32 +ENTRY(memset) + andcc %o1, 0xff, %o1 + mov %o0, %o5 + be,a,pt %icc, 50f +#ifndef USE_BPR + srl %o2, 0, %o1 +#else + mov %o2, %o1 +#endif + cmp %o2, 7 +#ifndef USE_BPR + srl %o2, 0, %o2 +#endif + bleu,pn %XCC, 17f + andcc %o0, 3, %g5 + be,pt %xcc, 4f + and %o1, 0xff, %o1 + cmp %g5, 3 + be,pn %xcc, 2f + stb %o1, [%o0 + 0x00] + cmp %g5, 2 + be,pt %xcc, 2f + stb %o1, [%o0 + 0x01] + stb %o1, [%o0 + 0x02] +2: sub %g5, 4, %g5 + sub %o0, %g5, %o0 + add %o2, %g5, %o2 +4: sllx %o1, 8, %g1 + andcc %o0, 4, %g0 + or %o1, %g1, %o1 + sllx %o1, 16, %g1 + or %o1, %g1, %o1 + be,pt %xcc, 2f + sllx %o1, 32, %g1 + stw %o1, [%o0] + sub %o2, 4, %o2 + add %o0, 4, %o0 +2: cmp %o2, 128 + or %o1, %g1, %o1 + blu,pn %xcc, 9f + andcc %o0, 0x38, %g5 + be,pn %icc, 6f + mov 64, %o4 + andcc %o0, 8, %g0 + be,pn %icc, 1f + sub %o4, %g5, %o4 + stx %o1, [%o0] + add %o0, 8, %o0 +1: andcc %o4, 16, %g0 + be,pn %icc, 1f + sub %o2, %o4, %o2 + stx %o1, [%o0] + stx %o1, [%o0 + 8] + add %o0, 16, %o0 +1: andcc %o4, 32, %g0 + be,pn %icc, 7f + andncc %o2, 0x3f, %o3 + stw %o1, [%o0] + stw %o1, [%o0 + 4] + stw %o1, [%o0 + 8] + stw %o1, [%o0 + 12] + stw %o1, [%o0 + 16] + stw %o1, [%o0 + 20] + stw %o1, [%o0 + 24] + stw %o1, [%o0 + 28] + add %o0, 32, %o0 +7: be,pn %xcc, 9f + nop + ldd [%o0 - 8], %f0 +18: wr %g0, ASI_BLK_P, %asi + membar #StoreStore | #LoadStore + andcc %o3, 0xc0, %g5 + and %o2, 0x3f, %o2 + fmovd %f0, %f2 + fmovd %f0, %f4 + andn %o3, 0xff, %o3 + fmovd %f0, %f6 + cmp %g5, 64 + fmovd %f0, %f8 + fmovd %f0, %f10 + fmovd %f0, %f12 + brz,pn %g5, 10f + fmovd %f0, %f14 + be,pn %icc, 2f + stda %f0, [%o0 + 0x00] %asi + cmp %g5, 128 + be,pn %icc, 2f + stda %f0, [%o0 + 0x40] %asi + stda %f0, [%o0 + 0x80] %asi +2: brz,pn %o3, 12f + add %o0, %g5, %o0 +10: stda %f0, [%o0 + 0x00] %asi + stda %f0, [%o0 + 0x40] %asi + stda %f0, [%o0 + 0x80] %asi + stda %f0, [%o0 + 0xc0] %asi +11: subcc %o3, 256, %o3 + bne,pt %xcc, 10b + add %o0, 256, %o0 +12: wr %g0, FPRS_FEF, %fprs + membar #StoreLoad | #StoreStore +9: andcc %o2, 0x78, %g5 + be,pn %xcc, 13f + andcc %o2, 7, %o2 +14: rd %pc, %o4 + srl %g5, 1, %o3 + sub %o4, %o3, %o4 + jmpl %o4 + (13f - 14b), %g0 + add %o0, %g5, %o0 +12: SET_BLOCKS (%o0, 0x68, %o1) + SET_BLOCKS (%o0, 0x48, %o1) + SET_BLOCKS (%o0, 0x28, %o1) + SET_BLOCKS (%o0, 0x08, %o1) +13: be,pn %xcc, 8f + andcc %o2, 4, %g0 + be,pn %xcc, 1f + andcc %o2, 2, %g0 + stw %o1, [%o0] + add %o0, 4, %o0 +1: be,pn %xcc, 1f + andcc %o2, 1, %g0 + sth %o1, [%o0] + add %o0, 2, %o0 +1: bne,a,pn %xcc, 8f + stb %o1, [%o0] +8: retl + mov %o5, %o0 +17: brz,pn %o2, 0f +8: add %o0, 1, %o0 + subcc %o2, 1, %o2 + bne,pt %xcc, 8b + stb %o1, [%o0 - 1] +0: retl + mov %o5, %o0 + +6: stx %o1, [%o0] + andncc %o2, 0x3f, %o3 + be,pn %xcc, 9b + nop + ba,pt %xcc, 18b + ldd [%o0], %f0 +END(memset) +libc_hidden_def(memset) + +#define ZERO_BLOCKS(base, offset, source) \ + stx source, [base - offset - 0x38]; \ + stx source, [base - offset - 0x30]; \ + stx source, [base - offset - 0x28]; \ + stx source, [base - offset - 0x20]; \ + stx source, [base - offset - 0x18]; \ + stx source, [base - offset - 0x10]; \ + stx source, [base - offset - 0x08]; \ + stx source, [base - offset - 0x00]; + + .text + .align 32 +#ifdef __UCLIBC_SUSV3_LEGACY__ +ENTRY(bzero) +#ifndef USE_BPR + srl %o1, 0, %o1 +#endif + mov %o0, %o5 +#endif +50: cmp %o1, 7 + bleu,pn %xcc, 17f + andcc %o0, 3, %o2 + be,a,pt %xcc, 4f + andcc %o0, 4, %g0 + cmp %o2, 3 + be,pn %xcc, 2f + stb %g0, [%o0 + 0x00] + cmp %o2, 2 + be,pt %xcc, 2f + stb %g0, [%o0 + 0x01] + stb %g0, [%o0 + 0x02] +2: sub %o2, 4, %o2 + sub %o0, %o2, %o0 + add %o1, %o2, %o1 + andcc %o0, 4, %g0 +4: be,pt %xcc, 2f + cmp %o1, 128 + stw %g0, [%o0] + sub %o1, 4, %o1 + add %o0, 4, %o0 +2: blu,pn %xcc, 9f + andcc %o0, 0x38, %o2 + be,pn %icc, 6f + mov 64, %o4 + andcc %o0, 8, %g0 + be,pn %icc, 1f + sub %o4, %o2, %o4 + stx %g0, [%o0] + add %o0, 8, %o0 +1: andcc %o4, 16, %g0 + be,pn %icc, 1f + sub %o1, %o4, %o1 + stx %g0, [%o0] + stx %g0, [%o0 + 8] + add %o0, 16, %o0 +1: andcc %o4, 32, %g0 + be,pn %icc, 7f + andncc %o1, 0x3f, %o3 + stx %g0, [%o0] + stx %g0, [%o0 + 8] + stx %g0, [%o0 + 16] + stx %g0, [%o0 + 24] + add %o0, 32, %o0 +6: andncc %o1, 0x3f, %o3 +7: be,pn %xcc, 9f + wr %g0, ASI_BLK_P, %asi + membar #StoreLoad | #StoreStore | #LoadStore + fzero %f0 + andcc %o3, 0xc0, %o2 + and %o1, 0x3f, %o1 + fzero %f2 + andn %o3, 0xff, %o3 + faddd %f0, %f2, %f4 + fmuld %f0, %f2, %f6 + cmp %o2, 64 + faddd %f0, %f2, %f8 + fmuld %f0, %f2, %f10 + faddd %f0, %f2, %f12 + brz,pn %o2, 10f + fmuld %f0, %f2, %f14 + be,pn %icc, 2f + stda %f0, [%o0 + 0x00] %asi + cmp %o2, 128 + be,pn %icc, 2f + stda %f0, [%o0 + 0x40] %asi + stda %f0, [%o0 + 0x80] %asi +2: brz,pn %o3, 12f + add %o0, %o2, %o0 +10: stda %f0, [%o0 + 0x00] %asi + stda %f0, [%o0 + 0x40] %asi + stda %f0, [%o0 + 0x80] %asi + stda %f0, [%o0 + 0xc0] %asi +11: subcc %o3, 256, %o3 + bne,pt %xcc, 10b + add %o0, 256, %o0 +12: wr %g0, FPRS_FEF, %fprs + membar #StoreLoad | #StoreStore +9: andcc %o1, 0xf8, %o2 + be,pn %xcc, 13f + andcc %o1, 7, %o1 +14: rd %pc, %o4 + srl %o2, 1, %o3 + sub %o4, %o3, %o4 + jmpl %o4 + (13f - 14b), %g0 + add %o0, %o2, %o0 +12: ZERO_BLOCKS (%o0, 0xc8, %g0) + ZERO_BLOCKS (%o0, 0x88, %g0) + ZERO_BLOCKS (%o0, 0x48, %g0) + ZERO_BLOCKS (%o0, 0x08, %g0) +13: be,pn %xcc, 8f + andcc %o1, 4, %g0 + be,pn %xcc, 1f + andcc %o1, 2, %g0 + stw %g0, [%o0] + add %o0, 4, %o0 +1: be,pn %xcc, 1f + andcc %o1, 1, %g0 + sth %g0, [%o0] + add %o0, 2, %o0 +1: bne,a,pn %xcc, 8f + stb %g0, [%o0] +8: retl + mov %o5, %o0 +17: be,pn %xcc, 13b + orcc %o1, 0, %g0 + be,pn %xcc, 0f +8: add %o0, 1, %o0 + subcc %o1, 1, %o1 + bne,pt %xcc, 8b + stb %g0, [%o0 - 1] +0: retl + mov %o5, %o0 +#ifdef __UCLIBC_SUSV3_LEGACY__ +END(bzero) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc64/sparcv9b/memcpy.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc64/sparcv9b/memcpy.S new file mode 100644 index 00000000..64f6a92e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc64/sparcv9b/memcpy.S @@ -0,0 +1,612 @@ +/* Copy SIZE bytes from SRC to DEST. + For UltraSPARC-III. + Copyright (C) 2001, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by David S. Miller (davem@redhat.com) + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#define ASI_BLK_P 0xf0 +#define FPRS_FEF 0x04 +#define VISEntryHalf rd %fprs, %o5; wr %g0, FPRS_FEF, %fprs +#define VISExitHalf and %o5, FPRS_FEF, %o5; wr %o5, 0x0, %fprs + +#ifndef XCC +#define USE_BPR +#define XCC xcc +#endif + + .register %g2,#scratch + .register %g3,#scratch + .register %g6,#scratch + + .text + .align 32 + +#ifdef __UCLIBC_SUSV3_LEGACY__ +ENTRY(bcopy) + sub %o1, %o0, %o4 + mov %o0, %g4 + cmp %o4, %o2 + mov %o1, %o0 + bgeu,pt %XCC, 100f + mov %g4, %o1 +#ifndef USE_BPR + srl %o2, 0, %o2 +#endif + brnz,pn %o2, 220f + add %o0, %o2, %o0 + retl + nop +END(bcopy) +#endif + + /* Special/non-trivial issues of this code: + * + * 1) %o5 is preserved from VISEntryHalf to VISExitHalf + * 2) Only low 32 FPU registers are used so that only the + * lower half of the FPU register set is dirtied by this + * code. This is especially important in the kernel. + * 3) This code never prefetches cachelines past the end + * of the source buffer. + * + * The cheetah's flexible spine, oversized liver, enlarged heart, + * slender muscular body, and claws make it the swiftest hunter + * in Africa and the fastest animal on land. Can reach speeds + * of up to 2.4GB per second. + */ + .align 32 +ENTRY(memcpy) + +100: /* %o0=dst, %o1=src, %o2=len */ + mov %o0, %g5 + cmp %o2, 0 + be,pn %XCC, out +218: or %o0, %o1, %o3 + cmp %o2, 16 + bleu,a,pn %XCC, small_copy + or %o3, %o2, %o3 + + cmp %o2, 256 + blu,pt %XCC, medium_copy + andcc %o3, 0x7, %g0 + + ba,pt %xcc, enter + andcc %o0, 0x3f, %g2 + + /* Here len >= 256 and condition codes reflect execution + * of "andcc %o0, 0x7, %g2", done by caller. + */ + .align 64 +enter: + /* Is 'dst' already aligned on an 64-byte boundary? */ + be,pt %XCC, 2f + + /* Compute abs((dst & 0x3f) - 0x40) into %g2. This is the number + * of bytes to copy to make 'dst' 64-byte aligned. We pre- + * subtract this from 'len'. + */ + sub %g2, 0x40, %g2 + sub %g0, %g2, %g2 + sub %o2, %g2, %o2 + + /* Copy %g2 bytes from src to dst, one byte at a time. */ +1: ldub [%o1 + 0x00], %o3 + add %o1, 0x1, %o1 + add %o0, 0x1, %o0 + subcc %g2, 0x1, %g2 + + bg,pt %XCC, 1b + stb %o3, [%o0 + -1] + +2: VISEntryHalf + and %o1, 0x7, %g1 + ba,pt %xcc, begin + alignaddr %o1, %g0, %o1 + + .align 64 +begin: + prefetch [%o1 + 0x000], #one_read + prefetch [%o1 + 0x040], #one_read + andn %o2, (0x40 - 1), %o4 + prefetch [%o1 + 0x080], #one_read + prefetch [%o1 + 0x0c0], #one_read + ldd [%o1 + 0x000], %f0 + prefetch [%o1 + 0x100], #one_read + ldd [%o1 + 0x008], %f2 + prefetch [%o1 + 0x140], #one_read + ldd [%o1 + 0x010], %f4 + prefetch [%o1 + 0x180], #one_read + faligndata %f0, %f2, %f16 + ldd [%o1 + 0x018], %f6 + faligndata %f2, %f4, %f18 + ldd [%o1 + 0x020], %f8 + faligndata %f4, %f6, %f20 + ldd [%o1 + 0x028], %f10 + faligndata %f6, %f8, %f22 + + ldd [%o1 + 0x030], %f12 + faligndata %f8, %f10, %f24 + ldd [%o1 + 0x038], %f14 + faligndata %f10, %f12, %f26 + ldd [%o1 + 0x040], %f0 + + sub %o4, 0x80, %o4 + add %o1, 0x40, %o1 + ba,pt %xcc, loop + srl %o4, 6, %o3 + + .align 64 +loop: + ldd [%o1 + 0x008], %f2 + faligndata %f12, %f14, %f28 + ldd [%o1 + 0x010], %f4 + faligndata %f14, %f0, %f30 + stda %f16, [%o0] ASI_BLK_P + ldd [%o1 + 0x018], %f6 + faligndata %f0, %f2, %f16 + + ldd [%o1 + 0x020], %f8 + faligndata %f2, %f4, %f18 + ldd [%o1 + 0x028], %f10 + faligndata %f4, %f6, %f20 + ldd [%o1 + 0x030], %f12 + faligndata %f6, %f8, %f22 + ldd [%o1 + 0x038], %f14 + faligndata %f8, %f10, %f24 + + ldd [%o1 + 0x040], %f0 + prefetch [%o1 + 0x180], #one_read + faligndata %f10, %f12, %f26 + subcc %o3, 0x01, %o3 + add %o1, 0x40, %o1 + bg,pt %XCC, loop + add %o0, 0x40, %o0 + + /* Finally we copy the last full 64-byte block. */ +loopfini: + ldd [%o1 + 0x008], %f2 + faligndata %f12, %f14, %f28 + ldd [%o1 + 0x010], %f4 + faligndata %f14, %f0, %f30 + stda %f16, [%o0] ASI_BLK_P + ldd [%o1 + 0x018], %f6 + faligndata %f0, %f2, %f16 + ldd [%o1 + 0x020], %f8 + faligndata %f2, %f4, %f18 + ldd [%o1 + 0x028], %f10 + faligndata %f4, %f6, %f20 + ldd [%o1 + 0x030], %f12 + faligndata %f6, %f8, %f22 + ldd [%o1 + 0x038], %f14 + faligndata %f8, %f10, %f24 + cmp %g1, 0 + be,pt %XCC, 1f + add %o0, 0x40, %o0 + ldd [%o1 + 0x040], %f0 +1: faligndata %f10, %f12, %f26 + faligndata %f12, %f14, %f28 + faligndata %f14, %f0, %f30 + stda %f16, [%o0] ASI_BLK_P + add %o0, 0x40, %o0 + add %o1, 0x40, %o1 + membar #Sync + + /* Now we copy the (len modulo 64) bytes at the end. + * Note how we borrow the %f0 loaded above. + * + * Also notice how this code is careful not to perform a + * load past the end of the src buffer. + */ +loopend: + and %o2, 0x3f, %o2 + andcc %o2, 0x38, %g2 + be,pn %XCC, endcruft + subcc %g2, 0x8, %g2 + be,pn %XCC, endcruft + cmp %g1, 0 + + be,a,pt %XCC, 1f + ldd [%o1 + 0x00], %f0 + +1: ldd [%o1 + 0x08], %f2 + add %o1, 0x8, %o1 + sub %o2, 0x8, %o2 + subcc %g2, 0x8, %g2 + faligndata %f0, %f2, %f8 + std %f8, [%o0 + 0x00] + be,pn %XCC, endcruft + add %o0, 0x8, %o0 + ldd [%o1 + 0x08], %f0 + add %o1, 0x8, %o1 + sub %o2, 0x8, %o2 + subcc %g2, 0x8, %g2 + faligndata %f2, %f0, %f8 + std %f8, [%o0 + 0x00] + bne,pn %XCC, 1b + add %o0, 0x8, %o0 + + /* If anything is left, we copy it one byte at a time. + * Note that %g1 is (src & 0x3) saved above before the + * alignaddr was performed. + */ +endcruft: + cmp %o2, 0 + add %o1, %g1, %o1 + VISExitHalf + be,pn %XCC, out + sub %o0, %o1, %o3 + + andcc %g1, 0x7, %g0 + bne,pn %icc, small_copy_unaligned + andcc %o2, 0x8, %g0 + be,pt %icc, 1f + nop + ldx [%o1], %o5 + stx %o5, [%o1 + %o3] + add %o1, 0x8, %o1 + +1: andcc %o2, 0x4, %g0 + be,pt %icc, 1f + nop + lduw [%o1], %o5 + stw %o5, [%o1 + %o3] + add %o1, 0x4, %o1 + +1: andcc %o2, 0x2, %g0 + be,pt %icc, 1f + nop + lduh [%o1], %o5 + sth %o5, [%o1 + %o3] + add %o1, 0x2, %o1 + +1: andcc %o2, 0x1, %g0 + be,pt %icc, out + nop + ldub [%o1], %o5 + ba,pt %xcc, out + stb %o5, [%o1 + %o3] + +medium_copy: /* 16 < len <= 64 */ + bne,pn %XCC, small_copy_unaligned + sub %o0, %o1, %o3 + +medium_copy_aligned: + andn %o2, 0x7, %o4 + and %o2, 0x7, %o2 +1: subcc %o4, 0x8, %o4 + ldx [%o1], %o5 + stx %o5, [%o1 + %o3] + bgu,pt %XCC, 1b + add %o1, 0x8, %o1 + andcc %o2, 0x4, %g0 + be,pt %XCC, 1f + nop + sub %o2, 0x4, %o2 + lduw [%o1], %o5 + stw %o5, [%o1 + %o3] + add %o1, 0x4, %o1 +1: cmp %o2, 0 + be,pt %XCC, out + nop + ba,pt %xcc, small_copy_unaligned + nop + +small_copy: /* 0 < len <= 16 */ + andcc %o3, 0x3, %g0 + bne,pn %XCC, small_copy_unaligned + sub %o0, %o1, %o3 + +small_copy_aligned: + subcc %o2, 4, %o2 + lduw [%o1], %g1 + stw %g1, [%o1 + %o3] + bgu,pt %XCC, small_copy_aligned + add %o1, 4, %o1 + +out: retl + mov %g5, %o0 + + .align 32 +small_copy_unaligned: + subcc %o2, 1, %o2 + ldub [%o1], %g1 + stb %g1, [%o1 + %o3] + bgu,pt %XCC, small_copy_unaligned + add %o1, 1, %o1 + retl + mov %g5, %o0 + +END(memcpy) +libc_hidden_def(memcpy) + +#define RMOVE_BIGCHUNK(src, dst, offset, t0, t1, t2, t3) \ + ldx [%src - offset - 0x20], %t0; \ + ldx [%src - offset - 0x18], %t1; \ + ldx [%src - offset - 0x10], %t2; \ + ldx [%src - offset - 0x08], %t3; \ + stw %t0, [%dst - offset - 0x1c]; \ + srlx %t0, 32, %t0; \ + stw %t0, [%dst - offset - 0x20]; \ + stw %t1, [%dst - offset - 0x14]; \ + srlx %t1, 32, %t1; \ + stw %t1, [%dst - offset - 0x18]; \ + stw %t2, [%dst - offset - 0x0c]; \ + srlx %t2, 32, %t2; \ + stw %t2, [%dst - offset - 0x10]; \ + stw %t3, [%dst - offset - 0x04]; \ + srlx %t3, 32, %t3; \ + stw %t3, [%dst - offset - 0x08]; + +#define RMOVE_BIGALIGNCHUNK(src, dst, offset, t0, t1, t2, t3) \ + ldx [%src - offset - 0x20], %t0; \ + ldx [%src - offset - 0x18], %t1; \ + ldx [%src - offset - 0x10], %t2; \ + ldx [%src - offset - 0x08], %t3; \ + stx %t0, [%dst - offset - 0x20]; \ + stx %t1, [%dst - offset - 0x18]; \ + stx %t2, [%dst - offset - 0x10]; \ + stx %t3, [%dst - offset - 0x08]; \ + ldx [%src - offset - 0x40], %t0; \ + ldx [%src - offset - 0x38], %t1; \ + ldx [%src - offset - 0x30], %t2; \ + ldx [%src - offset - 0x28], %t3; \ + stx %t0, [%dst - offset - 0x40]; \ + stx %t1, [%dst - offset - 0x38]; \ + stx %t2, [%dst - offset - 0x30]; \ + stx %t3, [%dst - offset - 0x28]; + +#define RMOVE_LASTCHUNK(src, dst, offset, t0, t1, t2, t3) \ + ldx [%src + offset + 0x00], %t0; \ + ldx [%src + offset + 0x08], %t1; \ + stw %t0, [%dst + offset + 0x04]; \ + srlx %t0, 32, %t2; \ + stw %t2, [%dst + offset + 0x00]; \ + stw %t1, [%dst + offset + 0x0c]; \ + srlx %t1, 32, %t3; \ + stw %t3, [%dst + offset + 0x08]; + +#define RMOVE_LASTALIGNCHUNK(src, dst, offset, t0, t1) \ + ldx [%src + offset + 0x00], %t0; \ + ldx [%src + offset + 0x08], %t1; \ + stx %t0, [%dst + offset + 0x00]; \ + stx %t1, [%dst + offset + 0x08]; + + .align 32 +228: andcc %o2, 1, %g0 /* IEU1 Group */ + be,pt %icc, 2f+4 /* CTI */ +1: ldub [%o1 - 1], %o5 /* LOAD Group */ + sub %o1, 1, %o1 /* IEU0 */ + sub %o0, 1, %o0 /* IEU1 */ + subcc %o2, 1, %o2 /* IEU1 Group */ + be,pn %xcc, 229f /* CTI */ + stb %o5, [%o0] /* Store */ +2: ldub [%o1 - 1], %o5 /* LOAD Group */ + sub %o0, 2, %o0 /* IEU0 */ + ldub [%o1 - 2], %g5 /* LOAD Group */ + sub %o1, 2, %o1 /* IEU0 */ + subcc %o2, 2, %o2 /* IEU1 Group */ + stb %o5, [%o0 + 1] /* Store */ + bne,pt %xcc, 2b /* CTI */ + stb %g5, [%o0] /* Store */ +229: retl + mov %g4, %o0 + + .align 32 +ENTRY(memmove) + mov %o0, %g5 +#ifndef USE_BPR + srl %o2, 0, %o2 /* IEU1 Group */ +#endif + brz,pn %o2, out /* CTI Group */ + sub %o0, %o1, %o4 /* IEU0 */ + cmp %o4, %o2 /* IEU1 Group */ + bgeu,pt %XCC, 218b /* CTI */ + mov %o0, %g4 /* IEU0 */ + add %o0, %o2, %o0 /* IEU0 Group */ +220: add %o1, %o2, %o1 /* IEU1 */ + cmp %o2, 15 /* IEU1 Group */ + bleu,pn %xcc, 228b /* CTI */ + andcc %o0, 7, %g2 /* IEU1 Group */ + sub %o0, %o1, %g5 /* IEU0 */ + andcc %g5, 3, %o5 /* IEU1 Group */ + bne,pn %xcc, 232f /* CTI */ + andcc %o1, 3, %g0 /* IEU1 Group */ + be,a,pt %xcc, 236f /* CTI */ + andcc %o1, 4, %g0 /* IEU1 Group */ + andcc %o1, 1, %g0 /* IEU1 Group */ + be,pn %xcc, 4f /* CTI */ + andcc %o1, 2, %g0 /* IEU1 Group */ + ldub [%o1 - 1], %g2 /* Load Group */ + sub %o1, 1, %o1 /* IEU0 */ + sub %o0, 1, %o0 /* IEU1 */ + sub %o2, 1, %o2 /* IEU0 Group */ + be,pn %xcc, 5f /* CTI Group */ + stb %g2, [%o0] /* Store */ +4: lduh [%o1 - 2], %g2 /* Load Group */ + sub %o1, 2, %o1 /* IEU0 */ + sub %o0, 2, %o0 /* IEU1 */ + sub %o2, 2, %o2 /* IEU0 */ + sth %g2, [%o0] /* Store Group + bubble */ +5: andcc %o1, 4, %g0 /* IEU1 */ +236: be,a,pn %xcc, 2f /* CTI */ + andcc %o2, -128, %g6 /* IEU1 Group */ + lduw [%o1 - 4], %g5 /* Load Group */ + sub %o1, 4, %o1 /* IEU0 */ + sub %o0, 4, %o0 /* IEU1 */ + sub %o2, 4, %o2 /* IEU0 Group */ + stw %g5, [%o0] /* Store */ + andcc %o2, -128, %g6 /* IEU1 Group */ +2: be,pn %xcc, 235f /* CTI */ + andcc %o0, 4, %g0 /* IEU1 Group */ + be,pn %xcc, 282f + 4 /* CTI Group */ +5: RMOVE_BIGCHUNK(o1, o0, 0x00, g1, g3, g5, o5) + RMOVE_BIGCHUNK(o1, o0, 0x20, g1, g3, g5, o5) + RMOVE_BIGCHUNK(o1, o0, 0x40, g1, g3, g5, o5) + RMOVE_BIGCHUNK(o1, o0, 0x60, g1, g3, g5, o5) + subcc %g6, 128, %g6 /* IEU1 Group */ + sub %o1, 128, %o1 /* IEU0 */ + bne,pt %xcc, 5b /* CTI */ + sub %o0, 128, %o0 /* IEU0 Group */ +235: andcc %o2, 0x70, %g6 /* IEU1 Group */ +41: be,pn %xcc, 280f /* CTI */ + andcc %o2, 8, %g0 /* IEU1 Group */ + /* Clk1 8-( */ + /* Clk2 8-( */ + /* Clk3 8-( */ + /* Clk4 8-( */ +279: rd %pc, %o5 /* PDU Group */ + sll %g6, 1, %g5 /* IEU0 Group */ + sub %o1, %g6, %o1 /* IEU1 */ + sub %o5, %g5, %o5 /* IEU0 Group */ + jmpl %o5 + %lo(280f - 279b), %g0 /* CTI Group brk forced*/ + sub %o0, %g6, %o0 /* IEU0 Group */ + RMOVE_LASTCHUNK(o1, o0, 0x60, g2, g3, g5, o5) + RMOVE_LASTCHUNK(o1, o0, 0x50, g2, g3, g5, o5) + RMOVE_LASTCHUNK(o1, o0, 0x40, g2, g3, g5, o5) + RMOVE_LASTCHUNK(o1, o0, 0x30, g2, g3, g5, o5) + RMOVE_LASTCHUNK(o1, o0, 0x20, g2, g3, g5, o5) + RMOVE_LASTCHUNK(o1, o0, 0x10, g2, g3, g5, o5) + RMOVE_LASTCHUNK(o1, o0, 0x00, g2, g3, g5, o5) +280: be,pt %xcc, 281f /* CTI */ + andcc %o2, 4, %g0 /* IEU1 */ + ldx [%o1 - 8], %g2 /* Load Group */ + sub %o0, 8, %o0 /* IEU0 */ + stw %g2, [%o0 + 4] /* Store Group */ + sub %o1, 8, %o1 /* IEU1 */ + srlx %g2, 32, %g2 /* IEU0 Group */ + stw %g2, [%o0] /* Store */ +281: be,pt %xcc, 1f /* CTI */ + andcc %o2, 2, %g0 /* IEU1 Group */ + lduw [%o1 - 4], %g2 /* Load Group */ + sub %o1, 4, %o1 /* IEU0 */ + stw %g2, [%o0 - 4] /* Store Group */ + sub %o0, 4, %o0 /* IEU0 */ +1: be,pt %xcc, 1f /* CTI */ + andcc %o2, 1, %g0 /* IEU1 Group */ + lduh [%o1 - 2], %g2 /* Load Group */ + sub %o1, 2, %o1 /* IEU0 */ + sth %g2, [%o0 - 2] /* Store Group */ + sub %o0, 2, %o0 /* IEU0 */ +1: be,pt %xcc, 211f /* CTI */ + nop /* IEU1 */ + ldub [%o1 - 1], %g2 /* Load Group */ + stb %g2, [%o0 - 1] /* Store Group + bubble */ +211: retl + mov %g4, %o0 + +282: RMOVE_BIGALIGNCHUNK(o1, o0, 0x00, g1, g3, g5, o5) + RMOVE_BIGALIGNCHUNK(o1, o0, 0x40, g1, g3, g5, o5) + subcc %g6, 128, %g6 /* IEU1 Group */ + sub %o1, 128, %o1 /* IEU0 */ + bne,pt %xcc, 282b /* CTI */ + sub %o0, 128, %o0 /* IEU0 Group */ + andcc %o2, 0x70, %g6 /* IEU1 */ + be,pn %xcc, 284f /* CTI */ + andcc %o2, 8, %g0 /* IEU1 Group */ + /* Clk1 8-( */ + /* Clk2 8-( */ + /* Clk3 8-( */ + /* Clk4 8-( */ +283: rd %pc, %o5 /* PDU Group */ + sub %o1, %g6, %o1 /* IEU0 Group */ + sub %o5, %g6, %o5 /* IEU1 */ + jmpl %o5 + %lo(284f - 283b), %g0 /* CTI Group brk forced*/ + sub %o0, %g6, %o0 /* IEU0 Group */ + RMOVE_LASTALIGNCHUNK(o1, o0, 0x60, g2, g3) + RMOVE_LASTALIGNCHUNK(o1, o0, 0x50, g2, g3) + RMOVE_LASTALIGNCHUNK(o1, o0, 0x40, g2, g3) + RMOVE_LASTALIGNCHUNK(o1, o0, 0x30, g2, g3) + RMOVE_LASTALIGNCHUNK(o1, o0, 0x20, g2, g3) + RMOVE_LASTALIGNCHUNK(o1, o0, 0x10, g2, g3) + RMOVE_LASTALIGNCHUNK(o1, o0, 0x00, g2, g3) +284: be,pt %xcc, 285f /* CTI Group */ + andcc %o2, 4, %g0 /* IEU1 */ + ldx [%o1 - 8], %g2 /* Load Group */ + sub %o0, 8, %o0 /* IEU0 */ + sub %o1, 8, %o1 /* IEU0 Group */ + stx %g2, [%o0] /* Store */ +285: be,pt %xcc, 1f /* CTI */ + andcc %o2, 2, %g0 /* IEU1 Group */ + lduw [%o1 - 4], %g2 /* Load Group */ + sub %o0, 4, %o0 /* IEU0 */ + sub %o1, 4, %o1 /* IEU0 Group */ + stw %g2, [%o0] /* Store */ +1: be,pt %xcc, 1f /* CTI */ + andcc %o2, 1, %g0 /* IEU1 Group */ + lduh [%o1 - 2], %g2 /* Load Group */ + sub %o0, 2, %o0 /* IEU0 */ + sub %o1, 2, %o1 /* IEU0 Group */ + sth %g2, [%o0] /* Store */ +1: be,pt %xcc, 1f /* CTI */ + nop /* IEU0 Group */ + ldub [%o1 - 1], %g2 /* Load Group */ + stb %g2, [%o0 - 1] /* Store Group + bubble */ +1: retl + mov %g4, %o0 + +232: brz,pt %g2, 2f /* CTI Group */ + sub %o2, %g2, %o2 /* IEU0 Group */ +1: ldub [%o1 - 1], %g5 /* Load Group */ + sub %o1, 1, %o1 /* IEU0 */ + sub %o0, 1, %o0 /* IEU1 */ + subcc %g2, 1, %g2 /* IEU1 Group */ + bne,pt %xcc, 1b /* CTI */ + stb %g5, [%o0] /* Store */ +2: andn %o2, 7, %g5 /* IEU0 Group */ + and %o2, 7, %o2 /* IEU1 */ + fmovd %f0, %f2 /* FPU */ + alignaddr %o1, %g0, %g1 /* GRU Group */ + ldd [%g1], %f4 /* Load Group */ +1: ldd [%g1 - 8], %f6 /* Load Group */ + sub %g1, 8, %g1 /* IEU0 Group */ + subcc %g5, 8, %g5 /* IEU1 */ + faligndata %f6, %f4, %f0 /* GRU Group */ + std %f0, [%o0 - 8] /* Store */ + sub %o1, 8, %o1 /* IEU0 Group */ + be,pn %xcc, 233f /* CTI */ + sub %o0, 8, %o0 /* IEU1 */ + ldd [%g1 - 8], %f4 /* Load Group */ + sub %g1, 8, %g1 /* IEU0 */ + subcc %g5, 8, %g5 /* IEU1 */ + faligndata %f4, %f6, %f0 /* GRU Group */ + std %f0, [%o0 - 8] /* Store */ + sub %o1, 8, %o1 /* IEU0 */ + bne,pn %xcc, 1b /* CTI Group */ + sub %o0, 8, %o0 /* IEU0 */ +233: brz,pn %o2, 234f /* CTI Group */ + nop /* IEU0 */ +237: ldub [%o1 - 1], %g5 /* LOAD */ + sub %o1, 1, %o1 /* IEU0 */ + sub %o0, 1, %o0 /* IEU1 */ + subcc %o2, 1, %o2 /* IEU1 */ + bne,pt %xcc, 237b /* CTI */ + stb %g5, [%o0] /* Store Group */ +234: wr %g0, FPRS_FEF, %fprs + retl + mov %g4, %o0 +END(memmove) +libc_hidden_def(memmove) + +#ifdef USE_BPR +weak_alias(memcpy,__align_cpy_1) +weak_alias(memcpy,__align_cpy_2) +weak_alias(memcpy,__align_cpy_4) +weak_alias(memcpy,__align_cpy_8) +weak_alias(memcpy,__align_cpy_16) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc64/stpcpy.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc64/stpcpy.S new file mode 100644 index 00000000..8c26c6be --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc64/stpcpy.S @@ -0,0 +1,271 @@ +/* Copy SRC to DEST returning the address of the terminating '\0' in DEST. + For SPARC v9. + Copyright (C) 1998, 1999, 2002, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jan Vondrak and + Jakub Jelinek . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#ifndef XCC + .register %g2, #scratch + .register %g3, #scratch + .register %g6, #scratch +#endif + + /* Normally, this uses + ((xword - 0x0101010101010101) & 0x8080808080808080) test + to find out if any byte in xword could be zero. This is fast, but + also gives false alarm for any byte in range 0x81-0xff. It does + not matter for correctness, as if this test tells us there could + be some zero byte, we check it byte by byte, but if bytes with + high bits set are common in the strings, then this will give poor + performance. You can #define EIGHTBIT_NOT_RARE and the algorithm + will use one tick slower, but more precise test + ((xword - 0x0101010101010101) & (~xword) & 0x8080808080808080), + which does not give any false alarms (but if some bits are set, + one cannot assume from it which bytes are zero and which are not). + It is yet to be measured, what is the correct default for glibc + in these days for an average user. + */ + + .text + .align 32 +ENTRY(stpcpy) + sethi %hi(0x01010101), %g1 /* IEU0 Group */ + or %g1, %lo(0x01010101), %g1 /* IEU0 Group */ + andcc %o0, 7, %g0 /* IEU1 */ + sllx %g1, 32, %g2 /* IEU0 Group */ + + bne,pn %icc, 12f /* CTI */ + andcc %o1, 7, %g3 /* IEU1 */ + or %g1, %g2, %g1 /* IEU0 Group */ + bne,pn %icc, 14f /* CTI */ + + sllx %g1, 7, %g2 /* IEU0 Group */ +1: ldx [%o1], %o3 /* Load */ + add %o1, 8, %o1 /* IEU1 */ +2: mov %o3, %g3 /* IEU0 Group */ + + sub %o3, %g1, %o2 /* IEU1 */ +3: ldxa [%o1] ASI_PNF, %o3 /* Load */ +#ifdef EIGHTBIT_NOT_RARE + andn %o2, %g3, %o2 /* IEU0 Group */ +#endif + add %o0, 8, %o0 /* IEU0 Group */ + andcc %o2, %g2, %g0 /* IEU1 */ + + add %o1, 8, %o1 /* IEU0 Group */ + be,a,pt %xcc, 2b /* CTI */ + stx %g3, [%o0 - 8] /* Store */ + srlx %g3, 56, %g5 /* IEU0 Group */ + + andcc %g5, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 11f /* CTI */ + srlx %g3, 48, %g4 /* IEU0 */ + andcc %g4, 0xff, %g0 /* IEU1 Group */ + + be,pn %icc, 10f /* CTI */ + srlx %g3, 40, %g5 /* IEU0 */ + andcc %g5, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 9f /* CTI */ + + srlx %g3, 32, %g4 /* IEU0 */ + andcc %g4, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 8f /* CTI */ + srlx %g3, 24, %g5 /* IEU0 */ + + andcc %g5, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 7f /* CTI */ + srlx %g3, 16, %g4 /* IEU0 */ + andcc %g4, 0xff, %g0 /* IEU1 Group */ + + be,pn %icc, 6f /* CTI */ + srlx %g3, 8, %g5 /* IEU0 */ + andcc %g5, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 5f /* CTI */ + + sub %o3, %g1, %o2 /* IEU0 */ + stx %g3, [%o0 - 8] /* Store Group */ + andcc %g3, 0xff, %g0 /* IEU1 */ + bne,pt %icc, 3b /* CTI */ + + mov %o3, %g3 /* IEU0 Group */ +4: retl /* CTI+IEU1 Group */ + sub %o0, 1, %o0 /* IEU0 */ + + .align 16 +6: ba,pt %xcc, 23f /* CTI Group */ + sub %o0, 3, %g6 /* IEU0 */ +5: sub %o0, 2, %g6 /* IEU0 Group */ + stb %g5, [%o0 - 2] /* Store */ + + srlx %g3, 16, %g4 /* IEU0 Group */ +23: sth %g4, [%o0 - 4] /* Store */ + srlx %g3, 32, %g4 /* IEU0 Group */ + stw %g4, [%o0 - 8] /* Store */ + + retl /* CTI+IEU1 Group */ + mov %g6, %o0 /* IEU0 */ +8: ba,pt %xcc, 24f /* CTI Group */ + sub %o0, 5, %g6 /* IEU0 */ + +7: sub %o0, 4, %g6 /* IEU0 Group */ + stb %g5, [%o0 - 4] /* Store */ + srlx %g3, 32, %g4 /* IEU0 Group */ +24: stw %g4, [%o0 - 8] /* Store */ + + retl /* CTI+IEU1 Group */ + mov %g6, %o0 /* IEU0 */ +10: ba,pt %xcc, 25f /* CTI Group */ + sub %o0, 7, %g6 /* IEU0 */ + +9: sub %o0, 6, %g6 /* IEU0 Group */ + stb %g5, [%o0 - 6] /* Store */ + srlx %g3, 48, %g4 /* IEU0 */ +25: sth %g4, [%o0 - 8] /* Store Group */ + + retl /* CTI+IEU1 Group */ + mov %g6, %o0 /* IEU0 */ +11: stb %g5, [%o0 - 8] /* Store Group */ + retl /* CTI+IEU1 Group */ + + sub %o0, 8, %o0 /* IEU0 */ + + .align 16 +12: or %g1, %g2, %g1 /* IEU0 Group */ + ldub [%o1], %o3 /* Load */ + sllx %g1, 7, %g2 /* IEU0 Group */ + stb %o3, [%o0] /* Store Group */ + +13: add %o0, 1, %o0 /* IEU0 */ + add %o1, 1, %o1 /* IEU1 */ + andcc %o3, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 4b /* CTI */ + + lduba [%o1] ASI_PNF, %o3 /* Load */ + andcc %o0, 7, %g0 /* IEU1 Group */ + bne,a,pt %icc, 13b /* CTI */ + stb %o3, [%o0] /* Store */ + + andcc %o1, 7, %g3 /* IEU1 Group */ + be,a,pt %icc, 1b /* CTI */ + ldx [%o1], %o3 /* Load */ +14: orcc %g0, 64, %g4 /* IEU1 Group */ + + sllx %g3, 3, %g5 /* IEU0 */ + sub %o1, %g3, %o1 /* IEU0 Group */ + sub %g4, %g5, %g4 /* IEU1 */ + /* %g1 = 0101010101010101 * + * %g2 = 8080808080808080 * + * %g3 = source alignment * + * %g5 = number of bits to shift left * + * %g4 = number of bits to shift right */ + ldxa [%o1] ASI_PNF, %o5 /* Load Group */ + + addcc %o1, 8, %o1 /* IEU1 */ +15: sllx %o5, %g5, %o3 /* IEU0 Group */ + ldxa [%o1] ASI_PNF, %o5 /* Load */ + srlx %o5, %g4, %o4 /* IEU0 Group */ + + add %o0, 8, %o0 /* IEU1 */ + or %o3, %o4, %o3 /* IEU0 Group */ + add %o1, 8, %o1 /* IEU1 */ + sub %o3, %g1, %o4 /* IEU0 Group */ + +#ifdef EIGHTBIT_NOT_RARE + andn %o4, %o3, %o4 /* IEU0 Group */ +#endif + andcc %o4, %g2, %g0 /* IEU1 Group */ + be,a,pt %xcc, 15b /* CTI */ + stx %o3, [%o0 - 8] /* Store */ + srlx %o3, 56, %o4 /* IEU0 Group */ + + andcc %o4, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 22f /* CTI */ + srlx %o3, 48, %o4 /* IEU0 */ + andcc %o4, 0xff, %g0 /* IEU1 Group */ + + be,pn %icc, 21f /* CTI */ + srlx %o3, 40, %o4 /* IEU0 */ + andcc %o4, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 20f /* CTI */ + + srlx %o3, 32, %o4 /* IEU0 */ + andcc %o4, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 19f /* CTI */ + srlx %o3, 24, %o4 /* IEU0 */ + + andcc %o4, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 18f /* CTI */ + srlx %o3, 16, %o4 /* IEU0 */ + andcc %o4, 0xff, %g0 /* IEU1 Group */ + + be,pn %icc, 17f /* CTI */ + srlx %o3, 8, %o4 /* IEU0 */ + andcc %o4, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 16f /* CTI */ + + andcc %o3, 0xff, %g0 /* IEU1 Group */ + bne,pn %icc, 15b /* CTI */ + stx %o3, [%o0 - 8] /* Store */ + retl /* CTI+IEU1 Group */ + + sub %o0, 1, %o0 /* IEU0 */ + + .align 16 +17: ba,pt %xcc, 26f /* CTI Group */ + subcc %o0, 3, %g6 /* IEU1 */ +18: ba,pt %xcc, 27f /* CTI Group */ + subcc %o0, 4, %g6 /* IEU1 */ + +19: ba,pt %xcc, 28f /* CTI Group */ + subcc %o0, 5, %g6 /* IEU1 */ +16: subcc %o0, 2, %g6 /* IEU1 Group */ + srlx %o3, 8, %o4 /* IEU0 */ + + stb %o4, [%o0 - 2] /* Store */ +26: srlx %o3, 16, %o4 /* IEU0 Group */ + stb %o4, [%o0 - 3] /* Store */ +27: srlx %o3, 24, %o4 /* IEU0 Group */ + + stb %o4, [%o0 - 4] /* Store */ +28: srlx %o3, 32, %o4 /* IEU0 Group */ + stw %o4, [%o0 - 8] /* Store */ + retl /* CTI+IEU1 Group */ + + mov %g6, %o0 /* IEU0 */ + + .align 16 +21: ba,pt %xcc, 29f /* CTI Group */ + subcc %o0, 7, %g6 /* IEU1 */ +22: ba,pt %xcc, 30f /* CTI Group */ + subcc %o0, 8, %g6 /* IEU1 */ + +20: subcc %o0, 6, %g6 /* IEU1 Group */ + srlx %o3, 40, %o4 /* IEU0 */ + stb %o4, [%o0 - 6] /* Store */ +29: srlx %o3, 48, %o4 /* IEU0 Group */ + + stb %o4, [%o0 - 7] /* Store */ +30: srlx %o3, 56, %o4 /* IEU0 Group */ + stb %o4, [%o0 - 8] /* Store */ + retl /* CTI+IEU1 Group */ + + mov %g6, %o0 /* IEU0 */ +END(stpcpy) +libc_hidden_def(stpcpy) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc64/strcat.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc64/strcat.S new file mode 100644 index 00000000..fcc4ba59 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc64/strcat.S @@ -0,0 +1,339 @@ +/* strcat (dest, src) -- Append SRC on the end of DEST. + For SPARC v9. + Copyright (C) 1998, 1999, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek and + Jan Vondrak . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#ifndef XCC +#define XCC xcc +#define USE_BPR + .register %g2, #scratch + .register %g3, #scratch + .register %g6, #scratch +#endif + + /* Normally, this uses + ((xword - 0x0101010101010101) & 0x8080808080808080) test + to find out if any byte in xword could be zero. This is fast, but + also gives false alarm for any byte in range 0x81-0xff. It does + not matter for correctness, as if this test tells us there could + be some zero byte, we check it byte by byte, but if bytes with + high bits set are common in the strings, then this will give poor + performance. You can #define EIGHTBIT_NOT_RARE and the algorithm + will use one tick slower, but more precise test + ((xword - 0x0101010101010101) & (~xword) & 0x8080808080808080), + which does not give any false alarms (but if some bits are set, + one cannot assume from it which bytes are zero and which are not). + It is yet to be measured, what is the correct default for glibc + in these days for an average user. + */ + + .text + .align 32 +ENTRY(strcat) + sethi %hi(0x01010101), %g1 /* IEU0 Group */ + ldub [%o0], %o3 /* Load */ + or %g1, %lo(0x01010101), %g1 /* IEU0 Group */ + mov %o0, %g6 /* IEU1 */ + + sllx %g1, 32, %g2 /* IEU0 Group */ + andcc %o0, 7, %g0 /* IEU1 */ + or %g1, %g2, %g1 /* IEU0 Group */ + bne,pn %icc, 32f /* CTI */ + + sllx %g1, 7, %g2 /* IEU0 Group */ + brz,pn %o3, 30f /* CTI+IEU1 */ + ldx [%o0], %o3 /* Load */ +48: add %o0, 8, %o0 /* IEU0 Group */ + +49: sub %o3, %g1, %o2 /* IEU0 Group */ +#ifdef EIGHTBIT_NOT_RARE + andn %o2, %o3, %g5 /* IEU0 Group */ + ldxa [%o0] ASI_PNF, %o3 /* Load */ + andcc %g5, %g2, %g0 /* IEU1 Group */ +#else + ldxa [%o0] ASI_PNF, %o3 /* Load */ + andcc %o2, %g2, %g0 /* IEU1 Group */ +#endif + be,pt %xcc, 49b /* CTI */ + + add %o0, 8, %o0 /* IEU0 */ + addcc %o2, %g1, %g3 /* IEU1 Group */ + srlx %o2, 32, %o2 /* IEU0 */ +50: andcc %o2, %g2, %g0 /* IEU1 Group */ + + be,pn %xcc, 51f /* CTI */ + srlx %g3, 56, %o2 /* IEU0 */ + andcc %o2, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 29f /* CTI */ + + srlx %g3, 48, %o2 /* IEU0 */ + andcc %o2, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 28f /* CTI */ + srlx %g3, 40, %o2 /* IEU0 */ + + andcc %o2, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 27f /* CTI */ + srlx %g3, 32, %o2 /* IEU0 */ + andcc %o2, 0xff, %g0 /* IEU1 Group */ + + be,pn %icc, 26f /* CTI */ +51: srlx %g3, 24, %o2 /* IEU0 */ + andcc %o2, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 25f /* CTI */ + + srlx %g3, 16, %o2 /* IEU0 */ + andcc %o2, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 24f /* CTI */ + srlx %g3, 8, %o2 /* IEU0 */ + + andcc %o2, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 23f /* CTI */ + sub %o3, %g1, %o2 /* IEU0 */ + andcc %g3, 0xff, %g0 /* IEU1 Group */ + + be,pn %icc, 52f /* CTI */ + ldxa [%o0] ASI_PNF, %o3 /* Load */ + andcc %o2, %g2, %g0 /* IEU1 Group */ + be,pt %xcc, 49b /* CTI */ + + add %o0, 8, %o0 /* IEU0 */ + addcc %o2, %g1, %g3 /* IEU1 Group */ + ba,pt %xcc, 50b /* CTI */ + srlx %o2, 32, %o2 /* IEU0 */ + + .align 16 +52: ba,pt %xcc, 12f /* CTI Group */ + add %o0, -9, %o0 /* IEU0 */ +23: ba,pt %xcc, 12f /* CTI Group */ + add %o0, -10, %o0 /* IEU0 */ + +24: ba,pt %xcc, 12f /* CTI Group */ + add %o0, -11, %o0 /* IEU0 */ +25: ba,pt %xcc, 12f /* CTI Group */ + add %o0, -12, %o0 /* IEU0 */ + +26: ba,pt %xcc, 12f /* CTI Group */ + add %o0, -13, %o0 /* IEU0 */ +27: ba,pt %xcc, 12f /* CTI Group */ + add %o0, -14, %o0 /* IEU0 */ + +28: ba,pt %xcc, 12f /* CTI Group */ + add %o0, -15, %o0 /* IEU0 */ +29: add %o0, -16, %o0 /* IEU0 Group */ +30: andcc %o1, 7, %g3 /* IEU1 */ + +31: bne,pn %icc, 14f /* CTI */ + orcc %g0, 64, %g4 /* IEU1 Group */ +1: ldx [%o1], %o3 /* Load */ + add %o1, 8, %o1 /* IEU1 */ + +2: mov %o3, %g3 /* IEU0 Group */ +3: sub %o3, %g1, %o2 /* IEU1 */ + ldxa [%o1] ASI_PNF, %o3 /* Load */ +#ifdef EIGHTBIT_NOT_RARE + andn %o2, %g3, %o2 /* IEU0 Group */ +#endif + add %o0, 8, %o0 /* IEU0 Group */ + + andcc %o2, %g2, %g0 /* IEU1 */ + add %o1, 8, %o1 /* IEU0 Group */ + be,a,pt %xcc, 2b /* CTI */ + stx %g3, [%o0 - 8] /* Store */ + + srlx %g3, 56, %g5 /* IEU0 Group */ + andcc %g5, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 11f /* CTI */ + srlx %g3, 48, %g4 /* IEU0 */ + + andcc %g4, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 10f /* CTI */ + srlx %g3, 40, %g5 /* IEU0 */ + andcc %g5, 0xff, %g0 /* IEU1 Group */ + + be,pn %icc, 9f /* CTI */ + srlx %g3, 32, %g4 /* IEU0 */ + andcc %g4, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 8f /* CTI */ + + srlx %g3, 24, %g5 /* IEU0 */ + andcc %g5, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 7f /* CTI */ + srlx %g3, 16, %g4 /* IEU0 */ + + andcc %g4, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 6f /* CTI */ + srlx %g3, 8, %g5 /* IEU0 */ + andcc %g5, 0xff, %g0 /* IEU1 Group */ + + be,pn %icc, 5f /* CTI */ + sub %o3, %g1, %o2 /* IEU0 */ + stx %g3, [%o0 - 8] /* Store Group */ + andcc %g3, 0xff, %g0 /* IEU1 */ + + bne,pt %icc, 3b /* CTI */ + mov %o3, %g3 /* IEU0 Group */ +4: retl /* CTI+IEU1 Group */ + mov %g6, %o0 /* IEU0 */ + + .align 16 +5: stb %g5, [%o0 - 2] /* Store Group */ + srlx %g3, 16, %g4 /* IEU0 */ +6: sth %g4, [%o0 - 4] /* Store Group */ + srlx %g3, 32, %g4 /* IEU0 */ + + stw %g4, [%o0 - 8] /* Store Group */ + retl /* CTI+IEU1 Group */ + mov %g6, %o0 /* IEU0 */ +7: stb %g5, [%o0 - 4] /* Store Group */ + + srlx %g3, 32, %g4 /* IEU0 */ +8: stw %g4, [%o0 - 8] /* Store Group */ + retl /* CTI+IEU1 Group */ + mov %g6, %o0 /* IEU0 */ + +9: stb %g5, [%o0 - 6] /* Store Group */ + srlx %g3, 48, %g4 /* IEU0 */ +10: sth %g4, [%o0 - 8] /* Store Group */ + retl /* CTI+IEU1 Group */ + + mov %g6, %o0 /* IEU0 */ +11: stb %g5, [%o0 - 8] /* Store Group */ + retl /* CTI+IEU1 Group */ + mov %g6, %o0 /* IEU0 */ + + .align 16 +32: andcc %o0, 7, %g0 /* IEU1 Group */ + be,a,pn %icc, 48b /* CTI */ + ldx [%o0], %o3 /* Load */ + add %o0, 1, %o0 /* IEU0 Group */ + + brnz,a,pt %o3, 32b /* CTI+IEU1 */ + lduba [%o0] ASI_PNF, %o3 /* Load */ + add %o0, -1, %o0 /* IEU0 Group */ + andcc %o0, 7, %g0 /* IEU1 Group */ + + be,a,pn %icc, 31b /* CTI */ + andcc %o1, 7, %g3 /* IEU1 Group */ +12: ldub [%o1], %o3 /* Load */ + stb %o3, [%o0] /* Store Group */ + +13: add %o0, 1, %o0 /* IEU0 */ + add %o1, 1, %o1 /* IEU1 */ + andcc %o3, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 4b /* CTI */ + + lduba [%o1] ASI_PNF, %o3 /* Load */ + andcc %o0, 7, %g0 /* IEU1 Group */ + bne,a,pt %icc, 13b /* CTI */ + stb %o3, [%o0] /* Store */ + + andcc %o1, 7, %g3 /* IEU1 Group */ + be,a,pt %icc, 1b /* CTI */ + ldx [%o1], %o3 /* Load */ + orcc %g0, 64, %g4 /* IEU1 Group */ + +14: sllx %g3, 3, %g5 /* IEU0 */ + sub %o1, %g3, %o1 /* IEU0 Group */ + sub %g4, %g5, %g4 /* IEU1 */ + /* %g1 = 0101010101010101 * + * %g2 = 8080808080808080 * + * %g3 = source alignment * + * %g5 = number of bits to shift left * + * %g4 = number of bits to shift right */ + ldxa [%o1] ASI_PNF, %o5 /* Load Group */ + + addcc %o1, 8, %o1 /* IEU1 */ +15: sllx %o5, %g5, %o3 /* IEU0 Group */ + ldxa [%o1] ASI_PNF, %o5 /* Load */ + srlx %o5, %g4, %o4 /* IEU0 Group */ + + add %o0, 8, %o0 /* IEU1 */ + or %o3, %o4, %o3 /* IEU0 Group */ + add %o1, 8, %o1 /* IEU1 */ + sub %o3, %g1, %o4 /* IEU0 Group */ + +#ifdef EIGHTBIT_NOT_RARE + andn %o4, %o3, %o4 /* IEU0 Group */ +#endif + andcc %o4, %g2, %g0 /* IEU1 Group */ + be,a,pt %xcc, 15b /* CTI */ + stx %o3, [%o0 - 8] /* Store */ + srlx %o3, 56, %o4 /* IEU0 Group */ + + andcc %o4, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 22f /* CTI */ + srlx %o3, 48, %o4 /* IEU0 */ + andcc %o4, 0xff, %g0 /* IEU1 Group */ + + be,pn %icc, 21f /* CTI */ + srlx %o3, 40, %o4 /* IEU0 */ + andcc %o4, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 20f /* CTI */ + + srlx %o3, 32, %o4 /* IEU0 */ + andcc %o4, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 19f /* CTI */ + srlx %o3, 24, %o4 /* IEU0 */ + + andcc %o4, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 18f /* CTI */ + srlx %o3, 16, %o4 /* IEU0 */ + andcc %o4, 0xff, %g0 /* IEU1 Group */ + + be,pn %icc, 17f /* CTI */ + srlx %o3, 8, %o4 /* IEU0 */ + andcc %o4, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 16f /* CTI */ + + andcc %o3, 0xff, %g0 /* IEU1 Group */ + bne,pn %icc, 15b /* CTI */ + stx %o3, [%o0 - 8] /* Store */ + retl /* CTI+IEU1 Group */ + + mov %g6, %o0 /* IEU0 */ + + .align 16 +16: srlx %o3, 8, %o4 /* IEU0 Group */ + stb %o4, [%o0 - 2] /* Store */ +17: srlx %o3, 16, %o4 /* IEU0 Group */ + stb %o4, [%o0 - 3] /* Store */ + +18: srlx %o3, 24, %o4 /* IEU0 Group */ + stb %o4, [%o0 - 4] /* Store */ +19: srlx %o3, 32, %o4 /* IEU0 Group */ + stw %o4, [%o0 - 8] /* Store */ + + retl /* CTI+IEU1 Group */ + mov %g6, %o0 /* IEU0 */ + nop + nop + +20: srlx %o3, 40, %o4 /* IEU0 Group */ + stb %o4, [%o0 - 6] /* Store */ +21: srlx %o3, 48, %o4 /* IEU0 Group */ + stb %o4, [%o0 - 7] /* Store */ + +22: srlx %o3, 56, %o4 /* IEU0 Group */ + stb %o4, [%o0 - 8] /* Store */ + retl /* CTI+IEU1 Group */ + mov %g6, %o0 /* IEU0 */ +END(strcat) +libc_hidden_def(strcat) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc64/strchr.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc64/strchr.S new file mode 100644 index 00000000..da26d1f9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc64/strchr.S @@ -0,0 +1,486 @@ +/* strchr (str, ch) -- Return pointer to first occurrence of CH in STR. + For SPARC v9. + Copyright (C) 1998, 1999, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jan Vondrak and + Jakub Jelinek . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#ifndef XCC +#define XCC xcc +#define USE_BPR + .register %g2, #scratch + .register %g3, #scratch + .register %g6, #scratch +#endif + + /* Normally, this uses + ((xword - 0x0101010101010101) & 0x8080808080808080) test + to find out if any byte in xword could be zero. This is fast, but + also gives false alarm for any byte in range 0x81-0xff. It does + not matter for correctness, as if this test tells us there could + be some zero byte, we check it byte by byte, but if bytes with + high bits set are common in the strings, then this will give poor + performance. You can #define EIGHTBIT_NOT_RARE and the algorithm + will use one tick slower, but more precise test + ((xword - 0x0101010101010101) & (~xword) & 0x8080808080808080), + which does not give any false alarms (but if some bits are set, + one cannot assume from it which bytes are zero and which are not). + It is yet to be measured, what is the correct default for glibc + in these days for an average user. + */ + + .text + .align 32 +ENTRY(strchr) + andcc %o1, 0xff, %o1 /* IEU1 Group */ + be,pn %icc, 17f /* CTI */ + sllx %o1, 8, %g3 /* IEU0 Group */ + sethi %hi(0x01010101), %g1 /* IEU1 */ + + or %g3, %o1, %g3 /* IEU0 Group */ + ldub [%o0], %o3 /* Load */ + sllx %g3, 16, %g5 /* IEU0 Group */ + or %g1, %lo(0x01010101), %g1 /* IEU1 */ + + sllx %g1, 32, %g2 /* IEU0 Group */ + brz,pn %o3, 5f /* CTI+IEU1 */ + orcc %g3, %g5, %g3 /* IEU1 Group */ + sllx %g3, 32, %g5 /* IEU0 */ + + cmp %o3, %o1 /* IEU1 Group */ + be,pn %xcc, 14f /* CTI */ + or %g1, %g2, %g1 /* IEU0 */ + andcc %o0, 7, %g0 /* IEU1 Group */ + + bne,a,pn %icc, 15f /* CTI */ + add %o0, 1, %o0 /* IEU0 */ + ldx [%o0], %o3 /* Load Group */ +1: sllx %g1, 7, %g2 /* IEU0 */ + + or %g3, %g5, %g3 /* IEU1 */ + add %o0, 8, %o0 /* IEU0 Group */ + xor %o3, %g3, %o4 /* IEU1 */ + /* %g1 = 0101010101010101 * + * %g2 = 8080088080808080 * + * %g3 = c c c c c c c c * + * %o3 = value * + * %o4 = value XOR c */ +2: sub %o3, %g1, %o2 /* IEU0 Group */ + + sub %o4, %g1, %o5 /* IEU1 */ +#ifdef EIGHTBIT_NOT_RARE + andn %o2, %o3, %g6 /* IEU0 Group */ + andn %o5, %o4, %o5 /* IEU1 */ + ldxa [%o0] ASI_PNF, %o3 /* Load */ + or %o5, %g6, %o5 /* IEU0 Group */ +#else + ldxa [%o0] ASI_PNF, %o3 /* Load */ + or %o5, %o2, %o5 /* IEU0 Group */ +#endif + add %o0, 8, %o0 /* IEU1 */ + + andcc %o5, %g2, %g0 /* IEU1 Group */ + be,a,pt %xcc, 2b /* CTI */ + xor %o3, %g3, %o4 /* IEU0 */ + srlx %o5, 32, %g5 /* IEU0 Group */ + + add %o2, %g1, %o2 /* IEU1 */ +3: andcc %g5, %g2, %g0 /* IEU1 Group */ + be,pn %xcc, 4f /* CTI */ + srlx %o2, 56, %g5 /* IEU0 */ + + andcc %g5, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 5f /* CTI */ + srlx %o4, 56, %g5 /* IEU0 */ + andcc %g5, 0xff, %g0 /* IEU1 Group */ + + be,pn %icc, 6f /* CTI */ + srlx %o2, 48, %g5 /* IEU0 */ + andcc %g5, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 5f /* CTI */ + + srlx %o4, 48, %g5 /* IEU0 */ + andcc %g5, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 7f /* CTI */ + srlx %o2, 40, %g5 /* IEU0 */ + + andcc %g5, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 5f /* CTI */ + srlx %o4, 40, %g5 /* IEU0 */ + andcc %g5, 0xff, %g0 /* IEU1 Group */ + + be,pn %icc, 8f /* CTI */ + srlx %o2, 32, %g5 /* IEU0 */ + andcc %g5, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 5f /* CTI */ + + srlx %o4, 32, %g5 /* IEU0 */ + andcc %g5, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 9f /* CTI */ +4: srlx %o2, 24, %g5 /* IEU0 */ + + andcc %g5, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 5f /* CTI */ + srlx %o4, 24, %g5 /* IEU0 */ + andcc %g5, 0xff, %g0 /* IEU1 Group */ + + be,pn %icc, 10f /* CTI */ + srlx %o2, 16, %g5 /* IEU0 */ + andcc %g5, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 5f /* CTI */ + + srlx %o4, 16, %g5 /* IEU0 */ + andcc %g5, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 11f /* CTI */ + srlx %o2, 8, %g5 /* IEU0 */ + + andcc %g5, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 5f /* CTI */ + srlx %o4, 8, %g5 /* IEU0 */ + andcc %g5, 0xff, %g0 /* IEU1 Group */ + + be,pn %icc, 12f /* CTI */ + andcc %o2, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 5f /* CTI */ + sub %o3, %g1, %o2 /* IEU0 */ + + andcc %o4, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 13f /* CTI */ + xor %o3, %g3, %o4 /* IEU0 */ + ldxa [%o0] ASI_PNF, %o3 /* Load Group */ + + sub %o4, %g1, %o5 /* IEU0 */ + or %o5, %o2, %o5 /* IEU1 */ + add %o0, 8, %o0 /* IEU0 Group */ + andcc %o5, %g2, %g0 /* IEU1 */ + + be,a,pt %xcc, 2b /* CTI */ + xor %o3, %g3, %o4 /* IEU0 Group */ + srlx %o5, 32, %g5 /* IEU0 Group */ + ba,pt %xcc, 3b /* CTI */ + + add %o2, %g1, %o2 /* IEU1 */ + + .align 16 +5: retl /* CTI+IEU1 Group */ + clr %o0 /* IEU0 */ +6: retl /* CTI+IEU1 Group */ + add %o0, -16, %o0 /* IEU0 */ + +7: retl /* CTI+IEU1 Group */ + add %o0, -15, %o0 /* IEU0 */ +8: retl /* CTI+IEU1 Group */ + add %o0, -14, %o0 /* IEU0 */ + +9: retl /* CTI+IEU1 Group */ + add %o0, -13, %o0 /* IEU0 */ +10: retl /* CTI+IEU1 Group */ + add %o0, -12, %o0 /* IEU0 */ + +11: retl /* CTI+IEU1 Group */ + add %o0, -11, %o0 /* IEU0 */ +12: retl /* CTI+IEU1 Group */ + add %o0, -10, %o0 /* IEU0 */ + +13: retl /* CTI+IEU1 Group */ + add %o0, -9, %o0 /* IEU0 */ +14: retl /* CTI+IEU1 Group */ + nop /* IEU0 */ + + .align 16 +15: ldub [%o0], %o3 /* Load Group */ +16: andcc %o0, 7, %g0 /* IEU1 */ + be,a,pn %icc, 1b /* CTI */ + ldx [%o0], %o3 /* Load Group */ + + andcc %o3, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 5b /* CTI */ + add %o0, 1, %o0 /* IEU0 */ + cmp %o3, %o1 /* IEU1 Group */ + + bne,a,pn %icc, 16b /* CTI */ + ldub [%o0], %o3 /* Load */ + retl /* CTI+IEU1 Group */ + add %o0, -1, %o0 /* IEU0 */ + + /* strchr (str, 0) */ + .align 32 + nop + .align 16 +17: sethi %hi(0x01010101), %g1 /* IEU0 Group */ + ldub [%o0], %o3 /* Load */ + or %g1, %lo(0x01010101), %g1 /* IEU0 Group */ + sllx %g1, 32, %g2 /* IEU0 Group */ + + andcc %o0, 7, %g0 /* IEU1 */ + or %g1, %g2, %g1 /* IEU0 Group */ + bne,pn %icc, 32f /* CTI */ + sllx %g1, 7, %g2 /* IEU0 Group */ + + brz,pn %o3, 30f /* CTI+IEU1 */ + ldx [%o0], %o3 /* Load */ +18: add %o0, 8, %o0 /* IEU0 Group */ +19: sub %o3, %g1, %o2 /* IEU0 Group */ + +#ifdef EIGHTBIT_NOT_RARE + andn %o2, %o3, %g6 /* IEU0 Group */ + ldxa [%o0] ASI_PNF, %o3 /* Load */ + andcc %g6, %g2, %g0 /* IEU1 Group */ +#else + ldxa [%o0] ASI_PNF, %o3 /* Load */ + andcc %o2, %g2, %g0 /* IEU1 Group */ +#endif + be,pt %xcc, 19b /* CTI */ + add %o0, 8, %o0 /* IEU0 */ + + addcc %o2, %g1, %g3 /* IEU1 Group */ + srlx %o2, 32, %o2 /* IEU0 */ +20: andcc %o2, %g2, %g0 /* IEU1 Group */ + be,pn %xcc, 21f /* CTI */ + + srlx %g3, 56, %o2 /* IEU0 */ + andcc %o2, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 29f /* CTI */ + srlx %g3, 48, %o2 /* IEU0 */ + + andcc %o2, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 28f /* CTI */ + srlx %g3, 40, %o2 /* IEU0 */ + andcc %o2, 0xff, %g0 /* IEU1 Group */ + + be,pn %icc, 27f /* CTI */ + srlx %g3, 32, %o2 /* IEU0 */ + andcc %o2, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 26f /* CTI */ + +21: srlx %g3, 24, %o2 /* IEU0 */ + andcc %o2, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 25f /* CTI */ + srlx %g3, 16, %o2 /* IEU0 */ + + andcc %o2, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 24f /* CTI */ + srlx %g3, 8, %o2 /* IEU0 */ + andcc %o2, 0xff, %g0 /* IEU1 Group */ + + be,pn %icc, 23f /* CTI */ + sub %o3, %g1, %o2 /* IEU0 */ + andcc %g3, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 22f /* CTI */ + + ldxa [%o0] ASI_PNF, %o3 /* Load */ + andcc %o2, %g2, %g0 /* IEU1 Group */ + be,pt %xcc, 19b /* CTI */ + add %o0, 8, %o0 /* IEU0 */ + + addcc %o2, %g1, %g3 /* IEU1 Group */ + ba,pt %xcc, 20b /* CTI */ + srlx %o2, 32, %o2 /* IEU0 */ + + .align 16 +22: retl /* CTI+IEU1 Group */ + add %o0, -9, %o0 /* IEU0 */ +23: retl /* CTI+IEU1 Group */ + add %o0, -10, %o0 /* IEU0 */ + +24: retl /* CTI+IEU1 Group */ + add %o0, -11, %o0 /* IEU0 */ +25: retl /* CTI+IEU1 Group */ + add %o0, -12, %o0 /* IEU0 */ + +26: retl /* CTI+IEU1 Group */ + add %o0, -13, %o0 /* IEU0 */ +27: retl /* CTI+IEU1 Group */ + add %o0, -14, %o0 /* IEU0 */ + +28: retl /* CTI+IEU1 Group */ + add %o0, -15, %o0 /* IEU0 */ +29: retl /* CTI+IEU1 Group */ + add %o0, -16, %o0 /* IEU0 */ + +30: retl /* CTI+IEU1 Group */ + nop /* IEU0 */ + + .align 16 +32: andcc %o0, 7, %g0 /* IEU1 Group */ + be,a,pn %icc, 18b /* CTI */ + ldx [%o0], %o3 /* Load */ + add %o0, 1, %o0 /* IEU0 Group */ + + brnz,a,pt %o3, 32b /* CTI+IEU1 */ + lduba [%o0] ASI_PNF, %o3 /* Load */ + retl /* CTI+IEU1 Group */ + add %o0, -1, %o0 /* IEU0 */ +END(strchr) +libc_hidden_def(strchr) +#ifdef __UCLIBC_SUSV3_LEGACY__ +strong_alias(strchr,index) +#endif + + .align 32 +ENTRY(strrchr) + andcc %o1, 0xff, %o1 /* IEU1 Group */ + be,pn %icc, 17b /* CTI */ + clr %g4 /* IEU0 */ + andcc %o0, 7, %g0 /* IEU1 Group */ + + bne,pn %icc, 13f /* CTI */ + sllx %o1, 8, %g3 /* IEU0 */ + ldx [%o0], %o3 /* Load Group */ +1: sethi %hi(0x01010101), %g1 /* IEU0 */ + + or %g3, %o1, %g3 /* IEU1 */ + sllx %g3, 16, %g5 /* IEU0 Group */ + or %g1, %lo(0x01010101), %g1 /* IEU1 */ + sllx %g1, 32, %g2 /* IEU0 Group */ + + or %g3, %g5, %g3 /* IEU1 */ + sllx %g3, 32, %g5 /* IEU0 Group */ + or %g1, %g2, %g1 /* IEU1 */ + sllx %g1, 7, %g2 /* IEU0 Group */ + + or %g3, %g5, %g3 /* IEU1 */ + add %o0, 8, %o0 /* IEU0 Group */ + xor %o3, %g3, %o4 /* IEU1 */ + /* %g1 = 0101010101010101 * + * %g2 = 8080088080808080 * + * %g3 = c c c c c c c c * + * %o3 = value * + * %o4 = value XOR c */ +2: sub %o3, %g1, %o2 /* IEU0 Group */ + +3: sub %o4, %g1, %o5 /* IEU1 */ +#ifdef EIGHTBIT_NOT_RARE + andn %o2, %o3, %g6 /* IEU0 Group */ + andn %o5, %o4, %o5 /* IEU1 */ + ldxa [%o0] ASI_PNF, %o3 /* Load */ + + or %o5, %g6, %o5 /* IEU0 Group */ +#else + ldxa [%o0] ASI_PNF, %o3 /* Load */ + + or %o5, %o2, %o5 /* IEU0 Group */ +#endif + add %o0, 8, %o0 /* IEU1 */ + andcc %o5, %g2, %g0 /* IEU1 Group */ + be,a,pt %xcc, 2b /* CTI */ + + xor %o3, %g3, %o4 /* IEU0 */ + srlx %o5, 32, %g5 /* IEU0 Group */ + add %o2, %g1, %o2 /* IEU1 */ + andcc %g5, %g2, %g0 /* IEU1 Group */ + + be,pn %xcc, 7f /* CTI */ + srlx %o2, 56, %g5 /* IEU0 */ + andcc %g5, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 12f /* CTI */ + + srlx %o4, 56, %g5 /* IEU0 */ + andcc %g5, 0xff, %g0 /* IEU1 Group */ + srlx %o2, 48, %g5 /* IEU0 */ + be,a,pn %icc, 4f /* CTI */ + + add %o0, -16, %g4 /* IEU0 Group */ +4: andcc %g5, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 12f /* CTI */ + srlx %o4, 48, %g5 /* IEU0 */ + + andcc %g5, 0xff, %g0 /* IEU1 Group */ + srlx %o2, 40, %g5 /* IEU0 */ + be,a,pn %icc, 5f /* CTI */ + add %o0, -15, %g4 /* IEU0 Group */ + +5: andcc %g5, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 12f /* CTI */ + srlx %o4, 40, %g5 /* IEU0 */ + andcc %g5, 0xff, %g0 /* IEU1 Group */ + + srlx %o2, 32, %g5 /* IEU0 */ + be,a,pn %icc, 6f /* CTI */ + add %o0, -14, %g4 /* IEU0 Group */ +6: andcc %g5, 0xff, %g0 /* IEU1 Group */ + + be,pn %icc, 12f /* CTI */ + srlx %o4, 32, %g5 /* IEU0 */ + andcc %g5, 0xff, %g0 /* IEU1 Group */ + be,a,pn %icc, 7f /* CTI */ + + add %o0, -13, %g4 /* IEU0 */ +7: srlx %o2, 24, %g5 /* IEU0 */ + andcc %g5, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 12f /* CTI */ + + srlx %o4, 24, %g5 /* IEU0 */ + andcc %g5, 0xff, %g0 /* IEU1 Group */ + srlx %o2, 16, %g5 /* IEU0 */ + be,a,pn %icc, 8f /* CTI */ + + add %o0, -12, %g4 /* IEU0 Group */ +8: andcc %g5, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 12f /* CTI */ + srlx %o4, 16, %g5 /* IEU0 */ + + andcc %g5, 0xff, %g0 /* IEU1 Group */ + srlx %o2, 8, %g5 /* IEU0 */ + be,a,pn %icc, 9f /* CTI */ + add %o0, -11, %g4 /* IEU0 Group */ + +9: andcc %g5, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 12f /* CTI */ + srlx %o4, 8, %g5 /* IEU0 */ + andcc %g5, 0xff, %g0 /* IEU1 Group */ + + be,a,pn %icc, 10f /* CTI */ + add %o0, -10, %g4 /* IEU0 */ +10: andcc %o2, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 12f /* CTI */ + + sub %o3, %g1, %o2 /* IEU0 */ + andcc %o4, 0xff, %g0 /* IEU1 Group */ + be,a,pn %icc, 11f /* CTI */ + add %o0, -9, %g4 /* IEU0 */ + +11: ba,pt %xcc, 3b /* CTI Group */ + xor %o3, %g3, %o4 /* IEU0 Group */ +12: retl /* CTI+IEU1 Group */ + mov %g4, %o0 /* IEU0 */ + + .align 16 +13: ldub [%o0], %o3 /* Load Group */ + add %o0, 1, %o0 /* IEU0 */ +14: andcc %o3, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 12b /* CTI */ + + cmp %o3, %o1 /* IEU1 Group */ + ldub [%o0], %o3 /* Load */ + be,a,pn %icc, 15f /* CTI */ + add %o0, -1, %g4 /* IEU0 Group */ + +15: andcc %o0, 7, %g0 /* IEU1 Group */ + bne,a,pt %icc, 14b /* CTI */ + add %o0, 1, %o0 /* IEU0 */ + ba,pt %xcc, 1b /* CTI Group */ + + ldx [%o0], %o3 /* Load */ +END(strrchr) +libc_hidden_def(strrchr) +#ifdef __UCLIBC_SUSV3_LEGACY__ +strong_alias(strrchr,rindex) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc64/strcmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc64/strcmp.S new file mode 100644 index 00000000..df9e6917 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc64/strcmp.S @@ -0,0 +1,279 @@ +/* Compare two strings for differences. + For SPARC v9. + Copyright (C) 1997, 1999, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jan Vondrak and + Jakub Jelinek . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#ifndef XCC + .register %g2, #scratch + .register %g3, #scratch + .register %g6, #scratch +#endif + + /* Normally, this uses + ((xword - 0x0101010101010101) & 0x8080808080808080) test + to find out if any byte in xword could be zero. This is fast, but + also gives false alarm for any byte in range 0x81-0xff. It does + not matter for correctness, as if this test tells us there could + be some zero byte, we check it byte by byte, but if bytes with + high bits set are common in the strings, then this will give poor + performance. You can #define EIGHTBIT_NOT_RARE and the algorithm + will use one tick slower, but more precise test + ((xword - 0x0101010101010101) & (~xword) & 0x8080808080808080), + which does not give any false alarms (but if some bits are set, + one cannot assume from it which bytes are zero and which are not). + It is yet to be measured, what is the correct default for glibc + in these days for an average user. + */ + + .text + .align 32 +ENTRY(strcmp) + sethi %hi(0x01010101), %g1 /* IEU0 Group */ + andcc %o0, 7, %g0 /* IEU1 */ + bne,pn %icc, 7f /* CTI */ + or %g1, %lo(0x01010101), %g1 /* IEU0 Group */ + + andcc %o1, 7, %g3 /* IEU1 */ + bne,pn %icc, 9f /* CTI */ + sllx %g1, 32, %g2 /* IEU0 Group */ + ldx [%o0], %o2 /* Load */ + + or %g1, %g2, %g1 /* IEU0 Group */ +1: ldx [%o1], %o3 /* Load */ + sub %o1, %o0, %o1 /* IEU1 */ + sllx %g1, 7, %g2 /* IEU0 Group */ + +2: add %o0, 8, %o0 /* IEU1 */ + sub %o2, %g1, %g3 /* IEU0 Group */ + subcc %o2, %o3, %g0 /* IEU1 */ + bne,pn %xcc, 13f /* CTI */ + +#ifdef EIGHTBIT_NOT_RARE + andn %g3, %o2, %g4 /* IEU0 Group */ + ldxa [%o0] ASI_PNF, %o2 /* Load */ + andcc %g4, %g2, %g0 /* IEU1 Group */ +#else + ldxa [%o0] ASI_PNF, %o2 /* Load Group */ + andcc %g3, %g2, %g0 /* IEU1 */ +#endif + be,a,pt %xcc, 2b /* CTI */ + ldxa [%o1 + %o0] ASI_PNF, %o3 /* Load Group */ + + addcc %g3, %g1, %o4 /* IEU1 */ + srlx %g3, 32, %g3 /* IEU0 */ + andcc %g3, %g2, %g0 /* IEU1 Group */ + be,pt %xcc, 3f /* CTI */ + + srlx %o4, 56, %o5 /* IEU0 */ + andcc %o5, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 4f /* CTI */ + srlx %o4, 48, %o5 /* IEU0 */ + + andcc %o5, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 4f /* CTI */ + srlx %o4, 40, %o5 /* IEU0 */ + andcc %o5, 0xff, %g0 /* IEU1 Group */ + + be,pn %icc, 4f /* CTI */ + srlx %o4, 32, %o5 /* IEU0 */ + andcc %o5, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 4f /* CTI */ + +3: srlx %o4, 24, %o5 /* IEU0 */ + andcc %o5, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 4f /* CTI */ + srlx %o4, 16, %o5 /* IEU0 */ + + andcc %o5, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 4f /* CTI */ + srlx %o4, 8, %o5 /* IEU0 */ + andcc %o5, 0xff, %g0 /* IEU1 Group */ + + be,pn %icc, 4f /* CTI */ + andcc %o4, 0xff, %g0 /* IEU1 Group */ + bne,a,pn %icc, 2b /* CTI */ + ldxa [%o1 + %o0] ASI_PNF, %o3 /* Load */ + +4: retl /* CTI+IEU1 Group */ + clr %o0 /* IEU0 */ + + .align 32 +13: mov 0xff, %g6 /* IEU0 Group */ +#ifdef EIGHTBIT_NOT_RARE + andcc %g4, %g2, %g0 /* IEU1 */ +#else + andcc %g3, %g2, %g0 /* IEU1 */ +#endif + be,pt %xcc, 25f /* CTI */ + addcc %g3, %g1, %o4 /* IEU1 Group */ + + srlx %g3, 32, %g3 /* IEU0 */ + andcc %g3, %g2, %g0 /* IEU1 Group */ + be,pt %xcc, 23f /* CTI */ + sllx %g6, 56, %o5 /* IEU0 */ + + andcc %o4, %o5, %g0 /* IEU1 Group */ + be,pn %xcc, 24f /* CTI */ + sllx %g6, 48, %o5 /* IEU0 */ + andcc %o4, %o5, %g0 /* IEU1 Group */ + + be,pn %xcc, 24f /* CTI */ + sllx %g6, 40, %o5 /* IEU0 */ + andcc %o4, %o5, %g0 /* IEU1 Group */ + be,pn %xcc, 24f /* CTI */ + + sllx %g6, 32, %o5 /* IEU0 */ + andcc %o4, %o5, %g0 /* IEU1 Group */ + be,pn %xcc, 24f /* CTI */ +23: sllx %g6, 24, %o5 /* IEU0 */ + + andcc %o4, %o5, %g0 /* IEU1 Group */ + be,pn %icc, 24f /* CTI */ + sllx %g6, 16, %o5 /* IEU0 */ + andcc %o4, %o5, %g0 /* IEU1 Group */ + + be,pn %icc, 24f /* CTI */ + sllx %g6, 8, %o5 /* IEU0 */ + andcc %o4, %o5, %g0 /* IEU1 Group */ + be,pn %icc, 24f /* CTI */ + + mov %g6, %o5 /* IEU0 */ +25: cmp %o4, %o3 /* IEU1 Group */ +5: mov -1, %o0 /* IEU0 */ + retl /* CTI+IEU1 Group */ + + movgu %xcc, 1, %o0 /* Single Group */ + + .align 16 +24: sub %o5, 1, %g6 /* IEU0 Group */ + clr %o0 /* IEU1 */ + or %o5, %g6, %o5 /* IEU0 Group */ + andn %o4, %o5, %o4 /* IEU0 Group */ + + andn %o3, %o5, %o3 /* IEU1 */ + cmp %o4, %o3 /* IEU1 Group */ + movgu %xcc, 1, %o0 /* Single Group */ + retl /* CTI+IEU1 Group */ + + movlu %xcc, -1, %o0 /* Single Group */ +6: retl /* CTI+IEU1 Group */ + mov %o4, %o0 /* IEU0 */ + + .align 16 +7: ldub [%o0], %o2 /* Load */ + add %o0, 1, %o0 /* IEU1 */ + ldub [%o1], %o3 /* Load Group */ + sllx %g1, 32, %g2 /* IEU0 */ + +8: add %o1, 1, %o1 /* IEU1 */ + subcc %o2, %o3, %o4 /* IEU1 Group */ + bne,pn %xcc, 6b /* CTI */ + lduba [%o0] ASI_PNF, %o2 /* Load */ + + brz,pn %o3, 4b /* CTI+IEU1 Group */ + lduba [%o1] ASI_PNF, %o3 /* Load */ + andcc %o0, 7, %g0 /* IEU1 Group */ + bne,a,pn %icc, 8b /* CTI */ + + add %o0, 1, %o0 /* IEU0 */ + or %g1, %g2, %g1 /* IEU0 Group */ + andcc %o1, 7, %g3 /* IEU1 */ + be,a,pn %icc, 1b /* CTI */ + + ldxa [%o0] ASI_PNF, %o2 /* Load Group */ +9: sllx %g3, 3, %g5 /* IEU0 */ + mov 64, %o5 /* IEU1 */ + sub %o1, %g3, %o1 /* IEU0 Group */ + + sub %o5, %g5, %o5 /* IEU1 */ + ldxa [%o1] ASI_PNF, %g6 /* Load Group */ + or %g1, %g2, %g1 /* IEU0 */ + sub %o1, %o0, %o1 /* IEU1 */ + + sllx %g1, 7, %g2 /* IEU0 Group */ + add %o1, 8, %o1 /* IEU1 */ + /* %g1 = 0101010101010101 + * %g2 = 8080808080800880 + * %g5 = number of bits to shift left + * %o5 = number of bits to shift right */ +10: sllx %g6, %g5, %o3 /* IEU0 Group */ + ldxa [%o1 + %o0] ASI_PNF, %g6 /* Load */ + +11: srlx %g6, %o5, %o4 /* IEU0 Group */ + ldxa [%o0] ASI_PNF, %o2 /* Load */ + or %o3, %o4, %o3 /* IEU1 */ + add %o0, 8, %o0 /* IEU0 Group */ + + subcc %o2, %o3, %g0 /* IEU1 */ +#ifdef EIGHTBIT_NOT_RARE + sub %o2, %g1, %g3 /* IEU0 Group */ + bne,pn %xcc, 13b /* CTI */ + andn %g3, %o2, %g4 /* IEU0 Group */ + + andcc %g4, %g2, %g0 /* IEU1 Group */ + be,pt %xcc, 10b /* CTI */ + srlx %g4, 32, %g4 /* IEU0 */ + andcc %g4, %g2, %g0 /* IEU1 Group */ +#else + bne,pn %xcc, 13b /* CTI */ + sub %o2, %g1, %g3 /* IEU0 Group */ + andcc %g3, %g2, %g0 /* IEU1 Group */ + + be,pt %xcc, 10b /* CTI */ + srlx %g3, 32, %g3 /* IEU0 */ + andcc %g3, %g2, %g0 /* IEU1 Group */ +#endif + be,pt %xcc, 12f /* CTI */ + + srlx %o2, 56, %g3 /* IEU0 */ + andcc %g3, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 4b /* CTI */ + srlx %o2, 48, %g3 /* IEU0 */ + + andcc %g3, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 4b /* CTI */ + srlx %o2, 40, %g3 /* IEU0 */ + andcc %g3, 0xff, %g0 /* IEU1 Group */ + + be,pn %icc, 4b /* CTI */ + srlx %o2, 32, %g3 /* IEU0 */ + andcc %g3, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 4b /* CTI */ + +12: srlx %o2, 24, %g3 /* IEU0 */ + andcc %g3, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 4b /* CTI */ + srlx %o2, 16, %g3 /* IEU0 */ + + andcc %g3, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 4b /* CTI */ + srlx %o2, 8, %g3 /* IEU0 */ + andcc %g3, 0xff, %g0 /* IEU1 Group */ + + be,pn %icc, 4b /* CTI */ + andcc %o2, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 4b /* CTI */ + sllx %g6, %g5, %o3 /* IEU0 */ + + ba,pt %xcc, 11b /* CTI Group */ + ldxa [%o1 + %o0] ASI_PNF, %g6 /* Load */ +END(strcmp) +libc_hidden_def(strcmp) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc64/strcpy.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc64/strcpy.S new file mode 100644 index 00000000..1317d548 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc64/strcpy.S @@ -0,0 +1,245 @@ +/* Copy SRC to DEST returning DEST. + For SPARC v9. + Copyright (C) 1998, 1999, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jan Vondrak and + Jakub Jelinek . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#ifndef XCC + .register %g2, #scratch + .register %g3, #scratch + .register %g6, #scratch +#endif + + /* Normally, this uses + ((xword - 0x0101010101010101) & 0x8080808080808080) test + to find out if any byte in xword could be zero. This is fast, but + also gives false alarm for any byte in range 0x81-0xff. It does + not matter for correctness, as if this test tells us there could + be some zero byte, we check it byte by byte, but if bytes with + high bits set are common in the strings, then this will give poor + performance. You can #define EIGHTBIT_NOT_RARE and the algorithm + will use one tick slower, but more precise test + ((xword - 0x0101010101010101) & (~xword) & 0x8080808080808080), + which does not give any false alarms (but if some bits are set, + one cannot assume from it which bytes are zero and which are not). + It is yet to be measured, what is the correct default for glibc + in these days for an average user. + */ + + .text + .align 32 +ENTRY(strcpy) + sethi %hi(0x01010101), %g1 /* IEU0 Group */ + mov %o0, %g6 /* IEU1 */ + or %g1, %lo(0x01010101), %g1 /* IEU0 Group */ + andcc %o0, 7, %g0 /* IEU1 */ + + sllx %g1, 32, %g2 /* IEU0 Group */ + bne,pn %icc, 12f /* CTI */ + andcc %o1, 7, %g3 /* IEU1 */ + or %g1, %g2, %g1 /* IEU0 Group */ + + bne,pn %icc, 14f /* CTI */ + sllx %g1, 7, %g2 /* IEU0 Group */ +1: ldx [%o1], %o3 /* Load */ + add %o1, 8, %o1 /* IEU1 */ + +2: mov %o3, %g3 /* IEU0 Group */ +3: sub %o3, %g1, %o2 /* IEU1 */ + ldxa [%o1] ASI_PNF, %o3 /* Load */ +#ifdef EIGHTBIT_NOT_RARE + andn %o2, %g3, %o2 /* IEU0 Group */ +#endif + add %o0, 8, %o0 /* IEU0 Group */ + + andcc %o2, %g2, %g0 /* IEU1 */ + add %o1, 8, %o1 /* IEU0 Group */ + be,a,pt %xcc, 2b /* CTI */ + stx %g3, [%o0 - 8] /* Store */ + + srlx %g3, 56, %g5 /* IEU0 Group */ + andcc %g5, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 11f /* CTI */ + srlx %g3, 48, %g4 /* IEU0 */ + + andcc %g4, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 10f /* CTI */ + srlx %g3, 40, %g5 /* IEU0 */ + andcc %g5, 0xff, %g0 /* IEU1 Group */ + + be,pn %icc, 9f /* CTI */ + srlx %g3, 32, %g4 /* IEU0 */ + andcc %g4, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 8f /* CTI */ + + srlx %g3, 24, %g5 /* IEU0 */ + andcc %g5, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 7f /* CTI */ + srlx %g3, 16, %g4 /* IEU0 */ + + andcc %g4, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 6f /* CTI */ + srlx %g3, 8, %g5 /* IEU0 */ + andcc %g5, 0xff, %g0 /* IEU1 Group */ + + be,pn %icc, 5f /* CTI */ + sub %o3, %g1, %o2 /* IEU0 */ + stx %g3, [%o0 - 8] /* Store Group */ + andcc %g3, 0xff, %g0 /* IEU1 */ + + bne,pt %icc, 3b /* CTI */ + mov %o3, %g3 /* IEU0 Group */ +4: retl /* CTI+IEU1 Group */ + mov %g6, %o0 /* IEU0 */ + + .align 16 +5: stb %g5, [%o0 - 2] /* Store Group */ + srlx %g3, 16, %g4 /* IEU0 */ +6: sth %g4, [%o0 - 4] /* Store Group */ + srlx %g3, 32, %g4 /* IEU0 */ + + stw %g4, [%o0 - 8] /* Store Group */ + retl /* CTI+IEU1 Group */ + mov %g6, %o0 /* IEU0 */ +7: stb %g5, [%o0 - 4] /* Store Group */ + + srlx %g3, 32, %g4 /* IEU0 */ +8: stw %g4, [%o0 - 8] /* Store Group */ + retl /* CTI+IEU1 Group */ + mov %g6, %o0 /* IEU0 */ + +9: stb %g5, [%o0 - 6] /* Store Group */ + srlx %g3, 48, %g4 /* IEU0 */ +10: sth %g4, [%o0 - 8] /* Store Group */ + retl /* CTI+IEU1 Group */ + + mov %g6, %o0 /* IEU0 */ +11: stb %g5, [%o0 - 8] /* Store Group */ + retl /* CTI+IEU1 Group */ + mov %g6, %o0 /* IEU0 */ + +12: or %g1, %g2, %g1 /* IEU0 Group */ + ldub [%o1], %o3 /* Load */ + sllx %g1, 7, %g2 /* IEU0 Group */ + stb %o3, [%o0] /* Store Group */ + +13: add %o0, 1, %o0 /* IEU0 */ + add %o1, 1, %o1 /* IEU1 */ + andcc %o3, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 4b /* CTI */ + + lduba [%o1] ASI_PNF, %o3 /* Load */ + andcc %o0, 7, %g0 /* IEU1 Group */ + bne,a,pt %icc, 13b /* CTI */ + stb %o3, [%o0] /* Store */ + + andcc %o1, 7, %g3 /* IEU1 Group */ + be,a,pt %icc, 1b /* CTI */ + ldx [%o1], %o3 /* Load */ +14: orcc %g0, 64, %g4 /* IEU1 Group */ + + sllx %g3, 3, %g5 /* IEU0 */ + sub %o1, %g3, %o1 /* IEU0 Group */ + sub %g4, %g5, %g4 /* IEU1 */ + /* %g1 = 0101010101010101 * + * %g2 = 8080808080808080 * + * %g3 = source alignment * + * %g5 = number of bits to shift left * + * %g4 = number of bits to shift right */ + ldxa [%o1] ASI_PNF, %o5 /* Load Group */ + + addcc %o1, 8, %o1 /* IEU1 */ +15: sllx %o5, %g5, %o3 /* IEU0 Group */ + ldxa [%o1] ASI_PNF, %o5 /* Load */ + srlx %o5, %g4, %o4 /* IEU0 Group */ + + add %o0, 8, %o0 /* IEU1 */ + or %o3, %o4, %o3 /* IEU0 Group */ + add %o1, 8, %o1 /* IEU1 */ + sub %o3, %g1, %o4 /* IEU0 Group */ + +#ifdef EIGHTBIT_NOT_RARE + andn %o4, %o3, %o4 /* IEU0 Group */ +#endif + andcc %o4, %g2, %g0 /* IEU1 Group */ + be,a,pt %xcc, 15b /* CTI */ + stx %o3, [%o0 - 8] /* Store */ + srlx %o3, 56, %o4 /* IEU0 Group */ + + andcc %o4, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 22f /* CTI */ + srlx %o3, 48, %o4 /* IEU0 */ + andcc %o4, 0xff, %g0 /* IEU1 Group */ + + be,pn %icc, 21f /* CTI */ + srlx %o3, 40, %o4 /* IEU0 */ + andcc %o4, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 20f /* CTI */ + + srlx %o3, 32, %o4 /* IEU0 */ + andcc %o4, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 19f /* CTI */ + srlx %o3, 24, %o4 /* IEU0 */ + + andcc %o4, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 18f /* CTI */ + srlx %o3, 16, %o4 /* IEU0 */ + andcc %o4, 0xff, %g0 /* IEU1 Group */ + + be,pn %icc, 17f /* CTI */ + srlx %o3, 8, %o4 /* IEU0 */ + andcc %o4, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 16f /* CTI */ + + andcc %o3, 0xff, %g0 /* IEU1 Group */ + bne,pn %icc, 15b /* CTI */ + stx %o3, [%o0 - 8] /* Store */ + retl /* CTI+IEU1 Group */ + + mov %g6, %o0 /* IEU0 */ + + .align 16 +16: srlx %o3, 8, %o4 /* IEU0 Group */ + stb %o4, [%o0 - 2] /* Store */ +17: srlx %o3, 16, %o4 /* IEU0 Group */ + stb %o4, [%o0 - 3] /* Store */ + +18: srlx %o3, 24, %o4 /* IEU0 Group */ + stb %o4, [%o0 - 4] /* Store */ +19: srlx %o3, 32, %o4 /* IEU0 Group */ + stw %o4, [%o0 - 8] /* Store */ + + retl /* CTI+IEU1 Group */ + mov %g6, %o0 /* IEU0 */ + nop + nop + +20: srlx %o3, 40, %o4 /* IEU0 Group */ + stb %o4, [%o0 - 6] /* Store */ +21: srlx %o3, 48, %o4 /* IEU0 Group */ + stb %o4, [%o0 - 7] /* Store */ + +22: srlx %o3, 56, %o4 /* IEU0 Group */ + stb %o4, [%o0 - 8] /* Store */ + retl /* CTI+IEU1 Group */ + mov %g6, %o0 /* IEU0 */ +END(strcpy) + +libc_hidden_def(strcpy) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc64/strlen.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc64/strlen.S new file mode 100644 index 00000000..1fe85496 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/sparc64/strlen.S @@ -0,0 +1,173 @@ +/* Determine the length of a string. For SPARC v9. + Copyright (C) 1998, 1999, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jan Vondrak and + Jakub Jelinek . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + + /* Normally, this uses + ((xword - 0x0101010101010101) & 0x8080808080808080) test + to find out if any byte in xword could be zero. This is fast, but + also gives false alarm for any byte in range 0x81-0xff. It does + not matter for correctness, as if this test tells us there could + be some zero byte, we check it byte by byte, but if bytes with + high bits set are common in the strings, then this will give poor + performance. You can #define EIGHTBIT_NOT_RARE and the algorithm + will use one tick slower, but more precise test + ((xword - 0x0101010101010101) & (~xword) & 0x8080808080808080), + which does not give any false alarms (but if some bits are set, + one cannot assume from it which bytes are zero and which are not). + It is yet to be measured, what is the correct default for glibc + in these days for an average user. + */ + + .text + .align 32 +ENTRY(strlen) + sethi %hi(0x01010101), %g1 /* IEU0 Group */ + ldub [%o0], %o3 /* Load */ + or %g1, %lo(0x01010101), %g1 /* IEU0 Group */ + mov %o0, %o1 /* IEU1 */ + + sllx %g1, 32, %g4 /* IEU0 Group */ + andcc %o0, 7, %g0 /* IEU1 */ + or %g1, %g4, %g1 /* IEU0 Group */ + brz,pn %o3, 13f /* CTI+IEU1 */ + + sllx %g1, 7, %g4 /* IEU0 Group */ + bne,a,pn %icc, 15f /* CTI */ + add %o0, 1, %o0 /* IEU1 */ + /* %g1 = 0x0101010101010101 * + * %g4 = 0x8080808080808080 * + * %o0 = string pointer * + * %o1 = start of string */ +1: ldx [%o0], %o3 /* Load Group */ + + add %o0, 8, %o0 /* IEU1 */ +2: sub %o3, %g1, %o2 /* IEU0 Group */ +#ifdef EIGHTBIT_NOT_RARE + andn %o2, %o3, %o5 /* IEU0 Group */ + ldxa [%o0] ASI_PNF, %o3 /* Load */ + andcc %o5, %g4, %g0 /* IEU1 Group */ +#else + ldxa [%o0] ASI_PNF, %o3 /* Load */ + andcc %o2, %g4, %g0 /* IEU1 Group */ +#endif + + be,pt %xcc, 2b /* CTI */ + add %o0, 8, %o0 /* IEU0 */ + addcc %o2, %g1, %g5 /* IEU1 Group */ +#ifdef EIGHTBIT_NOT_RARE + srlx %o5, 32, %o5 /* IEU0 */ + +3: andcc %o5, %g4, %g0 /* IEU1 Group */ +#else + srlx %o2, 32, %o2 /* IEU0 */ + +3: andcc %o2, %g4, %g0 /* IEU1 Group */ +#endif + be,pn %xcc, 4f /* CTI */ + srlx %g5, 56, %o2 /* IEU0 */ + andcc %o2, 0xff, %g0 /* IEU1 Group */ + + be,pn %icc, 12f /* CTI */ + srlx %g5, 48, %o2 /* IEU0 */ + andcc %o2, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 11f /* CTI */ + + srlx %g5, 40, %o2 /* IEU0 */ + andcc %o2, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 10f /* CTI */ + srlx %g5, 32, %o2 /* IEU0 */ + + andcc %o2, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 9f /* CTI */ +4: srlx %g5, 24, %o2 /* IEU0 */ + andcc %o2, 0xff, %g0 /* IEU1 Group */ + + be,pn %icc, 8f /* CTI */ + srlx %g5, 16, %o2 /* IEU0 */ + andcc %o2, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 7f /* CTI */ + + srlx %g5, 8, %o2 /* IEU0 */ + andcc %o2, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 6f /* CTI */ + sub %o3, %g1, %o2 /* IEU0 */ + + andcc %g5, 0xff, %g0 /* IEU1 Group */ + be,pn %icc, 5f /* CTI */ + ldxa [%o0] ASI_PNF, %o3 /* Load */ + andcc %o2, %g4, %g0 /* IEU1 Group */ + + be,pt %xcc, 2b /* CTI */ + add %o0, 8, %o0 /* IEU0 */ + addcc %o2, %g1, %g5 /* IEU1 Group */ + ba,pt %xcc, 3b /* CTI */ + + srlx %o2, 32, %o2 /* IEU0 */ +5: add %o0, -9, %o0 /* IEU0 Group */ + retl /* CTI+IEU1 Group */ + sub %o0, %o1, %o0 /* IEU0 */ + +6: add %o0, -10, %o0 /* IEU0 Group */ + retl /* CTI+IEU1 Group */ + sub %o0, %o1, %o0 /* IEU0 */ +7: add %o0, -11, %o0 /* IEU0 Group */ + + retl /* CTI+IEU1 Group */ + sub %o0, %o1, %o0 /* IEU0 */ +8: add %o0, -12, %o0 /* IEU0 Group */ + retl /* CTI+IEU1 Group */ + + sub %o0, %o1, %o0 /* IEU0 */ +9: add %o0, -13, %o0 /* IEU0 Group */ + retl /* CTI+IEU1 Group */ + sub %o0, %o1, %o0 /* IEU0 */ + +10: add %o0, -14, %o0 /* IEU0 Group */ + retl /* CTI+IEU1 Group */ + sub %o0, %o1, %o0 /* IEU0 */ +11: add %o0, -15, %o0 /* IEU0 Group */ + + retl /* CTI+IEU1 Group */ + sub %o0, %o1, %o0 /* IEU0 */ +12: add %o0, -16, %o0 /* IEU0 Group */ + retl /* CTI+IEU1 Group */ + + sub %o0, %o1, %o0 /* IEU0 */ +13: retl /* CTI+IEU1 Group */ + mov 0, %o0 /* IEU0 */ + nop + +15: ldub [%o0], %o3 /* Load Group */ +16: andcc %o0, 7, %g0 /* IEU1 */ + be,pn %icc, 1b /* CTI */ + nop /* IEU0 Group */ + + add %o0, 1, %o0 /* IEU1 */ + andcc %o3, 0xff, %g0 /* IEU1 Group */ + bne,a,pt %icc, 16b /* CTI */ + lduba [%o0] ASI_PNF, %o3 /* Load */ + + add %o0, -1, %o0 /* IEU0 Group */ + retl /* CTI+IEU1 Group */ + sub %o0, %o1, %o0 /* IEU0 */ +END(strlen) +libc_hidden_def(strlen) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/stpcpy.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/stpcpy.S new file mode 100644 index 00000000..2d27393e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/stpcpy.S @@ -0,0 +1,13 @@ +#include "_glibc_inc.h" + +#if __WORDSIZE == 32 + +# if defined(__CONFIG_SPARC_V9B__) +# include "sparc32/sparcv9b/stpcpy.S" +# else +# include "sparc32/stpcpy.S" +# endif + +#else +# include "sparc64/stpcpy.S" +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/strcat.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/strcat.S new file mode 100644 index 00000000..ae18e4e9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/strcat.S @@ -0,0 +1,13 @@ +#include "_glibc_inc.h" + +#if __WORDSIZE == 32 + +# if defined(__CONFIG_SPARC_V9B__) +# include "sparc32/sparcv9b/strcat.S" +# else +# include "sparc32/strcat.S" +# endif + +#else +# include "sparc64/strcat.S" +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/strchr.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/strchr.S new file mode 100644 index 00000000..99b51199 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/strchr.S @@ -0,0 +1,13 @@ +#include "_glibc_inc.h" + +#if __WORDSIZE == 32 + +# if defined(__CONFIG_SPARC_V9B__) +# include "sparc32/sparcv9b/strchr.S" +# else +# include "sparc32/strchr.S" +# endif + +#else +# include "sparc64/strchr.S" +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/strcmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/strcmp.S new file mode 100644 index 00000000..556537ce --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/strcmp.S @@ -0,0 +1,18 @@ +#include "_glibc_inc.h" + +#if __WORDSIZE == 32 + +# if defined(__CONFIG_SPARC_V9B__) +# include "sparc32/sparcv9b/strcmp.S" +# else +# include "sparc32/strcmp.S" +# endif + +#else +# include "sparc64/strcmp.S" +#endif + +#ifndef __UCLIBC_HAS_LOCALE__ +strong_alias(strcmp,strcoll) +libc_hidden_def(strcoll) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/strcpy.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/strcpy.S new file mode 100644 index 00000000..6dbbf5a3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/strcpy.S @@ -0,0 +1,13 @@ +#include "_glibc_inc.h" + +#if __WORDSIZE == 32 + +# if defined(__CONFIG_SPARC_V9B__) +# include "sparc32/sparcv9b/strcpy.S" +# else +# include "sparc32/strcpy.S" +# endif + +#else +# include "sparc64/strcpy.S" +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/strlen.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/strlen.S new file mode 100644 index 00000000..0bfa3f58 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/strlen.S @@ -0,0 +1,13 @@ +#include "_glibc_inc.h" + +#if __WORDSIZE == 32 + +# if defined(__CONFIG_SPARC_V9B__) +# include "sparc32/sparcv9b/strlen.S" +# else +# include "sparc32/strlen.S" +# endif + +#else +# include "sparc64/strlen.S" +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/strrchr.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/strrchr.c new file mode 100644 index 00000000..ec608d6a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sparc/strrchr.c @@ -0,0 +1 @@ +/* strrchr is in strchr.S */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/stpcpy.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/stpcpy.c new file mode 100644 index 00000000..2fd2c064 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/stpcpy.c @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include "_string.h" + +#ifdef WANT_WIDE +# define Wstpcpy wcpcpy +#else +# undef stpcpy +# define Wstpcpy stpcpy +#endif + +Wchar *Wstpcpy(register Wchar * __restrict s1, const Wchar * __restrict s2) +{ + while ( (*s1++ = *s2++) != 0 ); + + return s1 - 1; +} + +#ifndef WANT_WIDE +libc_hidden_def(stpcpy) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/stpncpy.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/stpncpy.c new file mode 100644 index 00000000..088145de --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/stpncpy.c @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include "_string.h" + +#ifdef WANT_WIDE +# define Wstpncpy wcpncpy +#else +# define Wstpncpy stpncpy +#endif + +Wchar *Wstpncpy(register Wchar * __restrict s1, + register const Wchar * __restrict s2, + size_t n) +{ + Wchar *s = s1; + const Wchar *p = s2; + + while (n) { + if ((*s = *s2) != 0) s2++; /* Need to fill tail with 0s. */ + ++s; + --n; + } + return s1 + (s2 - p); +} + +#ifndef WANT_WIDE +libc_hidden_def(stpncpy) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strcasecmp.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strcasecmp.c new file mode 100644 index 00000000..33e48fa2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strcasecmp.c @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include "_string.h" +#include +#include + +#ifdef WANT_WIDE +# define strcasecmp wcscasecmp +# define strcasecmp_l wcscasecmp_l +# ifdef __UCLIBC_DO_XLOCALE +# define TOLOWER(C) towlower_l((C), locale_arg) +# else +# define TOLOWER(C) towlower((C)) +# endif +#else +# ifdef __UCLIBC_DO_XLOCALE +# define TOLOWER(C) tolower_l((C), locale_arg) +# else +# define TOLOWER(C) tolower((C)) +# endif +#endif + +#if defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) + +int strcasecmp(register const Wchar *s1, register const Wchar *s2) +{ + return strcasecmp_l(s1, s2, __UCLIBC_CURLOCALE); +} +libc_hidden_def(strcasecmp) + +#else /* defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) */ + +int __XL_NPP(strcasecmp)(register const Wchar *s1, register const Wchar *s2 + __LOCALE_PARAM ) +{ +#ifdef WANT_WIDE + while ((*s1 == *s2) || (TOLOWER(*s1) == TOLOWER(*s2))) { + if (!*s1++) { + return 0; + } + ++s2; + } + + return (((Wuchar)TOLOWER(*s1)) < ((Wuchar)TOLOWER(*s2))) ? -1 : 1; + /* TODO -- should wide cmp funcs do wchar or Wuchar compares? */ +#else + int r = 0; + + while ( ((s1 == s2) || + !(r = ((int)( TOLOWER(*((Wuchar *)s1)))) + - TOLOWER(*((Wuchar *)s2)))) + && (++s2, *s1++)); + + return r; +#endif +} +libc_hidden_def(__XL_NPP(strcasecmp)) + +#endif /* defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strcasecmp_l.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strcasecmp_l.c new file mode 100644 index 00000000..a3f74c4f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strcasecmp_l.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define __UCLIBC_DO_XLOCALE +#include "strcasecmp.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strcasestr.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strcasestr.c new file mode 100644 index 00000000..3334086b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strcasestr.c @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include "_string.h" +#include + +char *strcasestr(const char *s1, const char *s2) +{ + register const char *s = s1; + register const char *p = s2; + +#if 1 + do { + if (!*p) { + return (char *) s1;; + } + if ((*p == *s) + || (tolower(*((unsigned char *)p)) == tolower(*((unsigned char *)s))) + ) { + ++p; + ++s; + } else { + p = s2; + if (!*s) { + return NULL; + } + s = ++s1; + } + } while (1); +#else + while (*p && *s) { + if ((*p == *s) + || (tolower(*((unsigned char *)p)) == tolower(*((unsigned char *)s))) + ) { + ++p; + ++s; + } else { + p = s2; + s = ++s1; + } + } + + return (*p) ? NULL : (char *) s1; +#endif +} +libc_hidden_def(strcasestr) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strcat.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strcat.c new file mode 100644 index 00000000..63619bcc --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strcat.c @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include "_string.h" + +#ifdef WANT_WIDE +# define Wstrcat wcscat +#else +# define Wstrcat strcat +#endif + +Wchar *Wstrcat(Wchar * __restrict s1, register const Wchar * __restrict s2) +{ + register Wchar *s = s1; + + while (*s++); + --s; + while ((*s++ = *s2++) != 0); + + return s1; +} +libc_hidden_def(Wstrcat) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strchr.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strchr.c new file mode 100644 index 00000000..462b7b1f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strchr.c @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include "_string.h" + +#ifdef WANT_WIDE +# define Wstrchr wcschr +#else +# define Wstrchr strchr +#endif + +Wchar *Wstrchr(register const Wchar *s, Wint c) +{ + do { + if (*s == ((Wchar)c)) { + return (Wchar *) s; /* silence the warning */ + } + } while (*s++); + + return NULL; +} +libc_hidden_def(Wstrchr) + +#if !defined WANT_WIDE && defined __UCLIBC_SUSV3_LEGACY__ +weak_alias(strchr,index) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strchrnul.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strchrnul.c new file mode 100644 index 00000000..d2d7df30 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strchrnul.c @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include "_string.h" + +#ifdef __USE_GNU + +#ifdef WANT_WIDE +# define Wstrchrnul wcschrnul +#else +# define Wstrchrnul strchrnul +#endif + +Wchar *Wstrchrnul(register const Wchar *s, Wint c) +{ + --s; + while (*++s && (*s != ((Wchar)c))); + return (Wchar *) s; +} +libc_hidden_def(Wstrchrnul) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strcmp.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strcmp.c new file mode 100644 index 00000000..abae6181 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strcmp.c @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include "_string.h" + +#ifdef WANT_WIDE +# define Wstrcmp wcscmp +# define Wstrcoll wcscoll +#else +# define Wstrcmp strcmp +# define Wstrcoll strcoll +#endif + +int Wstrcmp(register const Wchar *s1, register const Wchar *s2) +{ +#ifdef WANT_WIDE + while (*((Wuchar *)s1) == *((Wuchar *)s2)) { + if (!*s1++) { + return 0; + } + ++s2; + } + + return (*((Wuchar *)s1) < *((Wuchar *)s2)) ? -1 : 1; +#else + int r; + + while (((r = ((int)(*((Wuchar *)s1))) - *((Wuchar *)s2++)) + == 0) && *s1++); + + return r; +#endif +} +libc_hidden_def(Wstrcmp) + +#ifndef __UCLIBC_HAS_LOCALE__ +strong_alias(Wstrcmp,Wstrcoll) +libc_hidden_def(Wstrcoll) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strcpy.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strcpy.c new file mode 100644 index 00000000..bb5a1687 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strcpy.c @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include "_string.h" + +#ifdef WANT_WIDE +# define Wstrcpy wcscpy +#else +# define Wstrcpy strcpy +#endif + +Wchar *Wstrcpy(Wchar * __restrict s1, const Wchar * __restrict s2) +{ + register Wchar *s = s1; + + while ( (*s++ = *s2++) != 0 ); + + return s1; +} + +#ifdef WANT_WIDE +/* wcscpy does not need libc_hidden_def */ +#else +libc_hidden_def(strcpy) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strcspn.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strcspn.c new file mode 100644 index 00000000..0466af99 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strcspn.c @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include "_string.h" + +#ifdef WANT_WIDE +# define Wstrcspn wcscspn +#else +# define Wstrcspn strcspn +#endif + +size_t Wstrcspn(const Wchar *s1, const Wchar *s2) +{ + register const Wchar *s; + register const Wchar *p; + + for ( s=s1 ; *s ; s++ ) { + for ( p=s2 ; *p ; p++ ) { + if (*p == *s) goto done; + } + } + done: + return s - s1; +} + +#ifndef WANT_WIDE +libc_hidden_def(strcspn) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strdup.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strdup.c new file mode 100644 index 00000000..049a23f6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strdup.c @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include "_string.h" +#include + +#ifdef WANT_WIDE +# define Wstrdup wcsdup +# define Wstrlen wcslen +#else +# define Wstrdup strdup +# define Wstrlen strlen +#endif + +Wchar *Wstrdup(register const Wchar *s1) +{ + register Wchar *s; + register size_t l = (Wstrlen(s1) + 1) * sizeof(Wchar); + + if ((s = malloc(l)) != NULL) { + memcpy(s, s1, l); + } + + return s; +} + +#ifndef WANT_WIDE +libc_hidden_weak(strdup) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strerror.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strerror.c new file mode 100644 index 00000000..7250da07 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strerror.c @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include "_syserrmsg.h" + + +char *strerror(int errnum) +{ + static char buf[_STRERROR_BUFSIZE]; + + __xpg_strerror_r(errnum, buf, sizeof(buf)); + + return buf; +} +libc_hidden_def(strerror) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strlcat.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strlcat.c new file mode 100644 index 00000000..d55761d4 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strlcat.c @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* OpenBSD function: + * Append at most n-1-strlen(dst) chars from src to dst and nul-terminate dst. + * Returns strlen(src) + strlen({original} dst), so truncation occurred if the + * return val is >= n. + * Note: If dst doesn't contain a nul in the first n chars, strlen(dst) is + * taken as n. */ + +#include "_string.h" + +size_t strlcat(register char *__restrict dst, + register const char *__restrict src, + size_t n) +{ + size_t len; + char dummy[1]; + + len = 0; + + while (1) { + if (len >= n) { + dst = dummy; + break; + } + if (!*dst) { + break; + } + ++dst; + ++len; + } + + while ((*dst = *src) != 0) { + if (++len < n) { + ++dst; + } + ++src; + } + + return len; +} +libc_hidden_def(strlcat) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strlcpy.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strlcpy.c new file mode 100644 index 00000000..0ccfc0e8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strlcpy.c @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include "_string.h" + +#ifdef WANT_WIDE +# define Wstrlcpy __wcslcpy +#else +# define Wstrlcpy strlcpy +#endif + +/* OpenBSD function: + * Copy at most n-1 chars from src to dst and nul-terminate dst. + * Returns strlen(src), so truncation occurred if the return value is >= n. */ + +#ifdef WANT_WIDE +size_t Wstrlcpy(register Wchar *__restrict dst, + register const Wchar *__restrict src, + size_t n) attribute_hidden; +#endif +size_t Wstrlcpy(register Wchar *__restrict dst, + register const Wchar *__restrict src, + size_t n) +{ + const Wchar *src0 = src; + Wchar dummy[1]; + + if (!n) { + dst = dummy; + } else { + --n; + } + + while ((*dst = *src) != 0) { + if (n) { + --n; + ++dst; + } + ++src; + } + + return src - src0; +} +#ifdef WANT_WIDE + +#ifndef __UCLIBC_HAS_LOCALE__ +strong_alias(__wcslcpy,wcsxfrm) +libc_hidden_def(wcsxfrm) +#endif + +#else + +libc_hidden_def(strlcpy) +#ifndef __UCLIBC_HAS_LOCALE__ +strong_alias(strlcpy,strxfrm) +libc_hidden_def(strxfrm) +#endif + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strlen.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strlen.c new file mode 100644 index 00000000..021a8cab --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strlen.c @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include "_string.h" + +#ifdef WANT_WIDE +# define Wstrlen wcslen +#else +# define Wstrlen strlen +#endif + +size_t Wstrlen(const Wchar *s) +{ + register const Wchar *p; + + for (p=s ; *p ; p++); + + return p - s; +} +libc_hidden_weak(Wstrlen) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strncasecmp.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strncasecmp.c new file mode 100644 index 00000000..2af305e1 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strncasecmp.c @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include "_string.h" +#include +#include + +#ifdef WANT_WIDE +# define strncasecmp wcsncasecmp +# define strncasecmp_l wcsncasecmp_l +# ifdef __UCLIBC_DO_XLOCALE +# define TOLOWER(C) towlower_l((C), locale_arg) +# else +# define TOLOWER(C) towlower((C)) +# endif +#else +# ifdef __UCLIBC_DO_XLOCALE +# define TOLOWER(C) tolower_l((C), locale_arg) +# else +# define TOLOWER(C) tolower((C)) +# endif +#endif + +#if defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) + +int strncasecmp(register const Wchar *s1, register const Wchar *s2, size_t n) +{ + return strncasecmp_l(s1, s2, n, __UCLIBC_CURLOCALE); +} +libc_hidden_def(strncasecmp) + +#else /* defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) */ + +int __XL_NPP(strncasecmp)(register const Wchar *s1, register const Wchar *s2, + size_t n __LOCALE_PARAM ) +{ +#ifdef WANT_WIDE + while (n && ((*s1 == *s2) || (TOLOWER(*s1) == TOLOWER(*s2)))) { + if (!*s1++) { + return 0; + } + ++s2; + --n; + } + + return (n == 0) + ? 0 + : ((((Wuchar)TOLOWER(*s1)) < ((Wuchar)TOLOWER(*s2))) ? -1 : 1); + /* TODO -- should wide cmp funcs do wchar or Wuchar compares? */ +#else + int r = 0; + + while ( n + && ((s1 == s2) || + !(r = ((int)( TOLOWER(*((unsigned char *)s1)))) + - TOLOWER(*((unsigned char *)s2)))) + && (--n, ++s2, *s1++)); + return r; +#endif +} +libc_hidden_def(__XL_NPP(strncasecmp)) + +#endif /* defined(__UCLIBC_HAS_XLOCALE__) && !defined(__UCLIBC_DO_XLOCALE) */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strncasecmp_l.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strncasecmp_l.c new file mode 100644 index 00000000..7f251bae --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strncasecmp_l.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define __UCLIBC_DO_XLOCALE +#include "strncasecmp.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strncat.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strncat.c new file mode 100644 index 00000000..0fa9b4ae --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strncat.c @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include "_string.h" + +#ifdef WANT_WIDE +# define Wstrncat wcsncat +#else +# define Wstrncat strncat +#endif + +Wchar *Wstrncat(Wchar * __restrict s1, register const Wchar * __restrict s2, + size_t n) +{ + register Wchar *s = s1; + + while (*s++); + --s; + while (n && ((*s = *s2++) != 0)) { + --n; + ++s; + } + *s = 0; + + return s1; +} + +#ifndef WANT_WIDE +libc_hidden_def(strncat) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strncmp.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strncmp.c new file mode 100644 index 00000000..2da61771 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strncmp.c @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include "_string.h" + +#ifdef WANT_WIDE +# define Wstrncmp wcsncmp +#else +# define Wstrncmp strncmp +#endif + +int Wstrncmp(register const Wchar *s1, register const Wchar *s2, size_t n) +{ +#ifdef WANT_WIDE + while (n && (*((Wuchar *)s1) == *((Wuchar *)s2))) { + if (!*s1++) { + return 0; + } + ++s2; + --n; + } + + return (n == 0) ? 0 : (*((Wuchar *)s1) - *((Wuchar *)s2)); +#else + int r = 0; + + while (n-- + && ((r = ((int)(*((unsigned char *)s1))) - *((unsigned char *)s2++)) + == 0) + && *s1++); + + return r; +#endif +} +#ifndef WANT_WIDE +libc_hidden_weak(strncmp) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strncpy.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strncpy.c new file mode 100644 index 00000000..4a44e1f0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strncpy.c @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include "_string.h" + +#ifdef WANT_WIDE +# define Wstrncpy wcsncpy +#else +# define Wstrncpy strncpy +#endif + +Wchar *Wstrncpy(Wchar * __restrict s1, register const Wchar * __restrict s2, + size_t n) +{ + register Wchar *s = s1; + + while (n) { + if ((*s = *s2) != 0) s2++; /* Need to fill tail with 0s. */ + ++s; + --n; + } + + return s1; +} +#ifndef WANT_WIDE +libc_hidden_def(strncpy) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strndup.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strndup.c new file mode 100644 index 00000000..8e608669 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strndup.c @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include "_string.h" +#include + + +char *strndup(register const char *s1, size_t n) +{ + register char *s; + + n = strnlen(s1,n); /* Avoid problems if s1 not nul-terminated. */ + + if ((s = malloc(n + 1)) != NULL) { + memcpy(s, s1, n); + s[n] = 0; + } + + return s; +} +libc_hidden_def(strndup) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strnlen.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strnlen.c new file mode 100644 index 00000000..08de0887 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strnlen.c @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include "_string.h" + +#ifdef __USE_GNU + +#ifdef WANT_WIDE +# define Wstrnlen wcsnlen +#else +# define Wstrnlen strnlen +#endif + +size_t Wstrnlen(const Wchar *s, size_t max) +{ + register const Wchar *p = s; + + while (max && *p) { + ++p; + --max; + } + + return p - s; +} + +libc_hidden_def(Wstrnlen) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strpbrk.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strpbrk.c new file mode 100644 index 00000000..ddfc7517 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strpbrk.c @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include "_string.h" + +#ifdef WANT_WIDE +# define Wstrpbrk wcspbrk +#else +# define Wstrpbrk strpbrk +#endif + +Wchar *Wstrpbrk(const Wchar *s1, const Wchar *s2) +{ + register const Wchar *s; + register const Wchar *p; + + for ( s=s1 ; *s ; s++ ) { + for ( p=s2 ; *p ; p++ ) { + if (*p == *s) return (Wchar *) s; /* silence the warning */ + } + } + return NULL; +} +libc_hidden_def(Wstrpbrk) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strrchr.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strrchr.c new file mode 100644 index 00000000..db12bbc7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strrchr.c @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include "_string.h" + +#ifdef WANT_WIDE +# define Wstrrchr wcsrchr +#else +# define Wstrrchr strrchr +#endif + +Wchar *Wstrrchr(register const Wchar *s, Wint c) +{ + register const Wchar *p; + + p = NULL; + do { + if (*s == (Wchar) c) { + p = s; + } + } while (*s++); + + return (Wchar *) p; /* silence the warning */ +} +#ifndef WANT_WIDE +libc_hidden_weak(strrchr) +# ifdef __UCLIBC_SUSV3_LEGACY__ +weak_alias(strrchr,rindex) +# endif +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strsep.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strsep.c new file mode 100644 index 00000000..ce17dcf8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strsep.c @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include "_string.h" + +#ifdef __USE_BSD + + +char *strsep(char ** __restrict s1, const char * __restrict s2) +{ + register char *s = *s1; + register char *p; + +#if 1 + p = NULL; + if (s && *s && (p = strpbrk(s, s2))) { + *p++ = 0; + } +#else + if (s && *s && *(p = s + strcspn(s, s2))) { + *p++ = 0; + } else { + p = NULL; + } +#endif + *s1 = p; + return s; +} +libc_hidden_def(strsep) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strsignal.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strsignal.c new file mode 100644 index 00000000..0fbbf850 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strsignal.c @@ -0,0 +1,143 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* + * Sep 11, 2003 + * Patch by Atsushi Nemoto to do arch-required + * mapping of signal strings (alpha, mips, hppa, sparc). + */ + +/* TODO: make a threadsafe version? */ + +#include +#include +#include +#include + +#define _SYS_NSIG 32 + +#ifdef __UCLIBC_HAS_SIGNUM_MESSAGES__ +# define _SYS_SIGMSG_MAXLEN 25 +#else +# define _SYS_SIGMSG_MAXLEN 0 +#endif + +#if _SYS_SIGMSG_MAXLEN < __UIM_BUFLEN_INT + 15 +# define _STRSIGNAL_BUFSIZE (__UIM_BUFLEN_INT + 15) +#else +# define _STRSIGNAL_BUFSIZE _SYS_SIGMSG_MAXLEN +#endif + +#ifdef __UCLIBC_HAS_SIGNUM_MESSAGES__ + +extern const char _string_syssigmsgs[] attribute_hidden; + +#if defined(__alpha__) || defined(__mips__) || defined(__hppa__) || defined(__sparc__) +static const unsigned char sstridx[] = { + 0, + SIGHUP, + SIGINT, + SIGQUIT, + SIGILL, + SIGTRAP, + SIGIOT, + SIGBUS, + SIGFPE, + SIGKILL, + SIGUSR1, + SIGSEGV, + SIGUSR2, + SIGPIPE, + SIGALRM, + SIGTERM, +#if defined SIGSTKFLT + SIGSTKFLT, +#else + 0, +#endif + SIGCHLD, + SIGCONT, + SIGSTOP, + SIGTSTP, + SIGTTIN, + SIGTTOU, + SIGURG, + SIGXCPU, + SIGXFSZ, + SIGVTALRM, + SIGPROF, + SIGWINCH, + SIGIO, + SIGPWR, + SIGSYS, +#if defined SIGEMT + SIGEMT, +#endif +}; +#endif + +char *strsignal(int signum) +{ + register char *s; + int i; + static char buf[_STRSIGNAL_BUFSIZE]; + static const char unknown[] = { + 'U', 'n', 'k', 'n', 'o', 'w', 'n', ' ', 's', 'i', 'g', 'n', 'a', 'l', ' ' + }; + +#if defined(__alpha__) || defined(__mips__) || defined(__hppa__) || defined(__sparc__) + /* Need to translate signum to string index. */ + for (i = 0; i < sizeof(sstridx)/sizeof(sstridx[0]); i++) { + if (sstridx[i] == signum) { + goto GOT_SSTRIDX; + } + } + i = INT_MAX; /* Failed. */ + GOT_SSTRIDX: +#else + /* No signum to string index translation needed. */ + i = signum; +#endif + + if (((unsigned int) signum) < _SYS_NSIG) { + /* Trade time for space. This function should rarely be called + * so rather than keeping an array of pointers for the different + * messages, just run through the buffer until we find the + * correct string. */ + for (s = (char *) _string_syssigmsgs; i; ++s) { + if (!*s) { + --i; + } + } + if (*s) { /* Make sure we have an actual message. */ + goto DONE; + } + } + + s = _int10tostr(buf + sizeof(buf)-1, signum) - sizeof(unknown); + memcpy(s, unknown, sizeof(unknown)); + + DONE: + return s; +} + +#else /* __UCLIBC_HAS_SIGNUM_MESSAGES__ */ + +char *strsignal(int signum) +{ + static char buf[_STRSIGNAL_BUFSIZE]; + static const char unknown[] = { + 'U', 'n', 'k', 'n', 'o', 'w', 'n', ' ', 's', 'i', 'g', 'n', 'a', 'l', ' ' + }; + + return memcpy(_int10tostr(buf + sizeof(buf)-1, signum) - sizeof(unknown), + unknown, sizeof(unknown)); +} + +#endif /* __UCLIBC_HAS_SIGNUM_MESSAGES__ */ + +libc_hidden_def(strsignal) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strspn.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strspn.c new file mode 100644 index 00000000..942b6f30 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strspn.c @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include "_string.h" + +#ifdef WANT_WIDE +# define Wstrspn wcsspn +#else +# define Wstrspn strspn +#endif + +size_t Wstrspn(const Wchar *s1, const Wchar *s2) +{ + register const Wchar *s = s1; + register const Wchar *p = s2; + + while (*p) { + if (*p++ == *s) { + ++s; + p = s2; + } + } + return s - s1; +} +libc_hidden_def(Wstrspn) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strstr.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strstr.c new file mode 100644 index 00000000..7e2a64e7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strstr.c @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include "_string.h" + +#ifdef WANT_WIDE +# define Wstrstr wcsstr +#else +# define Wstrstr strstr +#endif + +/* NOTE: This is the simple-minded O(len(s1) * len(s2)) worst-case approach. */ + +Wchar *Wstrstr(const Wchar *s1, const Wchar *s2) +{ + register const Wchar *s = s1; + register const Wchar *p = s2; + + do { + if (!*p) { + return (Wchar *) s1;; + } + if (*p == *s) { + ++p; + ++s; + } else { + p = s2; + if (!*s) { + return NULL; + } + s = ++s1; + } + } while (1); +} +#ifndef WANT_WIDE +libc_hidden_def(strstr) +#elif defined __UCLIBC_SUSV3_LEGACY__ +strong_alias(wcsstr,wcswcs) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strtok.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strtok.c new file mode 100644 index 00000000..c337d81a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strtok.c @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include "_string.h" + +#if 0 /*def WANT_WIDE*/ +# define Wstrtok wcstok +# define Wstrtok_r wcstok_r +#else +# define Wstrtok strtok +# define Wstrtok_r strtok_r +#endif + + +Wchar *Wstrtok(Wchar * __restrict s1, const Wchar * __restrict s2) +{ + static Wchar *next_start; /* Initialized to 0 since in bss. */ + return Wstrtok_r(s1, s2, &next_start); +} +libc_hidden_def(Wstrtok) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strtok_r.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strtok_r.c new file mode 100644 index 00000000..2026888f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strtok_r.c @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include "_string.h" + +#ifdef WANT_WIDE +# define Wstrtok_r wcstok +# define Wstrspn wcsspn +# define Wstrpbrk wcspbrk +#else +# define Wstrtok_r strtok_r +# define Wstrspn strspn +# define Wstrpbrk strpbrk +#endif + +Wchar *Wstrtok_r(Wchar * __restrict s1, const Wchar * __restrict s2, + Wchar ** __restrict next_start) +{ + register Wchar *s; + register Wchar *p; + +#if 1 + if (((s = s1) != NULL) || ((s = *next_start) != NULL)) { + if (*(s += Wstrspn(s, s2))) { + if ((p = Wstrpbrk(s, s2)) != NULL) { + *p++ = 0; + } + } else { + p = s = NULL; + } + *next_start = p; + } + return s; +#else + if (!(s = s1)) { + s = *next_start; + } + if (s && *(s += Wstrspn(s, s2))) { + if (*(p = s + Wstrcspn(s, s2))) { + *p++ = 0; + } + *next_start = p; + return s; + } + return NULL; /* TODO: set *next_start = NULL for safety? */ +#endif +} + +#ifndef WANT_WIDE +libc_hidden_def(strtok_r) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strverscmp.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strverscmp.c new file mode 100644 index 00000000..b19e8f0b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strverscmp.c @@ -0,0 +1,118 @@ +/* GNU's strverscmp() function, taken from glibc 2.3.2 sources + */ + +/* Compare strings while treating digits characters numerically. + Copyright (C) 1997, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jean-François Bignolles , 1997. + + Derived work for uClibc by Hai Zaar, Codefidence Ltd + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + + +/* states: S_N: normal, S_I: comparing integral part, S_F: comparing + fractional parts, S_Z: idem but with leading Zeroes only */ +#define S_N 0x0 +#define S_I 0x4 +#define S_F 0x8 +#define S_Z 0xC + +/* result_type: CMP: return diff; LEN: compare using len_diff/diff */ +#define CMP 2 +#define LEN 3 + +/* using more efficient isdigit() */ +#undef isdigit +#define isdigit(a) ((unsigned)((a) - '0') <= 9) + +/* Compare S1 and S2 as strings holding indices/version numbers, + returning less than, equal to or greater than zero if S1 is less than, + equal to or greater than S2 (for more info, see the texinfo doc). +*/ +int strverscmp (const char *s1, const char *s2) +{ + const unsigned char *p1 = (const unsigned char *) s1; + const unsigned char *p2 = (const unsigned char *) s2; + unsigned char c1, c2; + int state; + int diff; + + /* Symbol(s) 0 [1-9] others (padding) + Transition (10) 0 (01) d (00) x (11) - */ + static const uint8_t next_state[] = + { + /* state x d 0 - */ + /* S_N */ S_N, S_I, S_Z, S_N, + /* S_I */ S_N, S_I, S_I, S_I, + /* S_F */ S_N, S_F, S_F, S_F, + /* S_Z */ S_N, S_F, S_Z, S_Z + }; + + static const int8_t result_type[] = + { + /* state x/x x/d x/0 x/- d/x d/d d/0 d/- + 0/x 0/d 0/0 0/- -/x -/d -/0 -/- */ + + /* S_N */ CMP, CMP, CMP, CMP, CMP, LEN, CMP, CMP, + CMP, CMP, CMP, CMP, CMP, CMP, CMP, CMP, + /* S_I */ CMP, -1, -1, CMP, +1, LEN, LEN, CMP, + +1, LEN, LEN, CMP, CMP, CMP, CMP, CMP, + /* S_F */ CMP, CMP, CMP, CMP, CMP, LEN, CMP, CMP, + CMP, CMP, CMP, CMP, CMP, CMP, CMP, CMP, + /* S_Z */ CMP, +1, +1, CMP, -1, CMP, CMP, CMP, + -1, CMP, CMP, CMP + }; + + if (p1 == p2) + return 0; + + c1 = *p1++; + c2 = *p2++; + /* Hint: '0' is a digit too. */ + state = S_N | ((c1 == '0') + (isdigit (c1) != 0)); + + while ((diff = c1 - c2) == 0 && c1 != '\0') + { + state = next_state[state]; + c1 = *p1++; + c2 = *p2++; + state |= (c1 == '0') + (isdigit (c1) != 0); + } + + state = result_type[state << 2 | (((c2 == '0') + (isdigit (c2) != 0)))]; + + switch (state) + { + case CMP: + return diff; + + case LEN: + while (isdigit (*p1++)) + if (!isdigit (*p2++)) + return 1; + + return isdigit (*p2) ? -1 : diff; + + default: + return state; + } +} +libc_hidden_def(strverscmp) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strxfrm.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strxfrm.c new file mode 100644 index 00000000..037d47bd --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strxfrm.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define WANT_WIDE +#define L_strxfrm +#include "_collate.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strxfrm_l.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strxfrm_l.c new file mode 100644 index 00000000..85e1cdfd --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/strxfrm_l.c @@ -0,0 +1,10 @@ +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define WANT_WIDE +#define __UCLIBC_DO_XLOCALE +#define L_strxfrm_l +#include "_collate.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sys_errlist.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sys_errlist.c new file mode 100644 index 00000000..17ed4d62 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sys_errlist.c @@ -0,0 +1,171 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +extern const char _string_syserrmsgs[] attribute_hidden; + +#ifdef __UCLIBC_HAS_SYS_ERRLIST__ + +link_warning(_sys_errlist, "sys_nerr and sys_errlist are obsolete and uClibc support for them (in at least some configurations) will probably be unavailable in the near future.") + +const char *const sys_errlist[] = { + [0] = _string_syserrmsgs + 0, + [EPERM] = _string_syserrmsgs + 8, + [ENOENT] = _string_syserrmsgs + 32, + [ESRCH] = _string_syserrmsgs + 58, + [EINTR] = _string_syserrmsgs + 74, + [EIO] = _string_syserrmsgs + 98, + [ENXIO] = _string_syserrmsgs + 117, + [E2BIG] = _string_syserrmsgs + 143, + [ENOEXEC] = _string_syserrmsgs + 166, + [EBADF] = _string_syserrmsgs + 184, + [ECHILD] = _string_syserrmsgs + 204, + [EAGAIN] = _string_syserrmsgs + 223, + [ENOMEM] = _string_syserrmsgs + 256, + [EACCES] = _string_syserrmsgs + 279, + [EFAULT] = _string_syserrmsgs + 297, + [ENOTBLK] = _string_syserrmsgs + 309, + [EBUSY] = _string_syserrmsgs + 331, + [EEXIST] = _string_syserrmsgs + 355, + [EXDEV] = _string_syserrmsgs + 367, + [ENODEV] = _string_syserrmsgs + 393, + [ENOTDIR] = _string_syserrmsgs + 408, + [EISDIR] = _string_syserrmsgs + 424, + [EINVAL] = _string_syserrmsgs + 439, + [ENFILE] = _string_syserrmsgs + 456, + [EMFILE] = _string_syserrmsgs + 486, + [ENOTTY] = _string_syserrmsgs + 506, + [ETXTBSY] = _string_syserrmsgs + 537, + [EFBIG] = _string_syserrmsgs + 552, + [ENOSPC] = _string_syserrmsgs + 567, + [ESPIPE] = _string_syserrmsgs + 591, + [EROFS] = _string_syserrmsgs + 604, + [EMLINK] = _string_syserrmsgs + 626, + [EPIPE] = _string_syserrmsgs + 641, + [EDOM] = _string_syserrmsgs + 653, + [ERANGE] = _string_syserrmsgs + 686, + [EDEADLK] = _string_syserrmsgs + 716, + [ENAMETOOLONG] = _string_syserrmsgs + 742, + [ENOLCK] = _string_syserrmsgs + 761, + [ENOSYS] = _string_syserrmsgs + 780, + [ENOTEMPTY] = _string_syserrmsgs + 805, + [ELOOP] = _string_syserrmsgs + 825, + /* _string_syserrmsgs + 859, */ + [ENOMSG] = _string_syserrmsgs + 860, + [EIDRM] = _string_syserrmsgs + 887, + [ECHRNG] = _string_syserrmsgs + 906, + [EL2NSYNC] = _string_syserrmsgs + 934, + [EL3HLT] = _string_syserrmsgs + 959, + [EL3RST] = _string_syserrmsgs + 974, + [ELNRNG] = _string_syserrmsgs + 988, + [EUNATCH] = _string_syserrmsgs + 1013, + [ENOCSI] = _string_syserrmsgs + 1042, + [EL2HLT] = _string_syserrmsgs + 1069, + [EBADE] = _string_syserrmsgs + 1084, + [EBADR] = _string_syserrmsgs + 1101, + [EXFULL] = _string_syserrmsgs + 1128, + [ENOANO] = _string_syserrmsgs + 1142, + [EBADRQC] = _string_syserrmsgs + 1151, + [EBADSLT] = _string_syserrmsgs + 1172, + /* _string_syserrmsgs + 1185, */ + [EBFONT] = _string_syserrmsgs + 1186, + [ENOSTR] = _string_syserrmsgs + 1207, + [ENODATA] = _string_syserrmsgs + 1227, + [ETIME] = _string_syserrmsgs + 1245, + [ENOSR] = _string_syserrmsgs + 1259, + [ENONET] = _string_syserrmsgs + 1284, + [ENOPKG] = _string_syserrmsgs + 1314, + [EREMOTE] = _string_syserrmsgs + 1336, + [ENOLINK] = _string_syserrmsgs + 1353, + [EADV] = _string_syserrmsgs + 1375, + [ESRMNT] = _string_syserrmsgs + 1391, + [ECOMM] = _string_syserrmsgs + 1405, + [EPROTO] = _string_syserrmsgs + 1433, + [EMULTIHOP] = _string_syserrmsgs + 1448, + [EDOTDOT] = _string_syserrmsgs + 1467, + [EBADMSG] = _string_syserrmsgs + 1486, + [EOVERFLOW] = _string_syserrmsgs + 1498, + [ENOTUNIQ] = _string_syserrmsgs + 1536, + [EBADFD] = _string_syserrmsgs + 1563, + [EREMCHG] = _string_syserrmsgs + 1592, + [ELIBACC] = _string_syserrmsgs + 1615, + [ELIBBAD] = _string_syserrmsgs + 1654, + [ELIBSCN] = _string_syserrmsgs + 1691, + [ELIBMAX] = _string_syserrmsgs + 1723, + [ELIBEXEC] = _string_syserrmsgs + 1771, + [EILSEQ] = _string_syserrmsgs + 1809, + [ERESTART] = _string_syserrmsgs + 1859, + [ESTRPIPE] = _string_syserrmsgs + 1903, + [EUSERS] = _string_syserrmsgs + 1922, + [ENOTSOCK] = _string_syserrmsgs + 1937, + [EDESTADDRREQ] = _string_syserrmsgs + 1968, + [EMSGSIZE] = _string_syserrmsgs + 1997, + [EPROTOTYPE] = _string_syserrmsgs + 2014, + [ENOPROTOOPT] = _string_syserrmsgs + 2045, + [EPROTONOSUPPORT] = _string_syserrmsgs + 2068, + [ESOCKTNOSUPPORT] = _string_syserrmsgs + 2091, + [EOPNOTSUPP] = _string_syserrmsgs + 2117, + [EPFNOSUPPORT] = _string_syserrmsgs + 2141, + [EAFNOSUPPORT] = _string_syserrmsgs + 2171, + [EADDRINUSE] = _string_syserrmsgs + 2212, + [EADDRNOTAVAIL] = _string_syserrmsgs + 2235, + [ENETDOWN] = _string_syserrmsgs + 2267, + [ENETUNREACH] = _string_syserrmsgs + 2283, + [ENETRESET] = _string_syserrmsgs + 2306, + [ECONNABORTED] = _string_syserrmsgs + 2342, + [ECONNRESET] = _string_syserrmsgs + 2375, + [ENOBUFS] = _string_syserrmsgs + 2400, + [EISCONN] = _string_syserrmsgs + 2426, + [ENOTCONN] = _string_syserrmsgs + 2466, + [ESHUTDOWN] = _string_syserrmsgs + 2502, + [ETOOMANYREFS] = _string_syserrmsgs + 2548, + [ETIMEDOUT] = _string_syserrmsgs + 2583, + [ECONNREFUSED] = _string_syserrmsgs + 2604, + [EHOSTDOWN] = _string_syserrmsgs + 2623, + [EHOSTUNREACH] = _string_syserrmsgs + 2636, + [EALREADY] = _string_syserrmsgs + 2653, + [EINPROGRESS] = _string_syserrmsgs + 2683, + [ESTALE] = _string_syserrmsgs + 2709, + [EUCLEAN] = _string_syserrmsgs + 2731, + [ENOTNAM] = _string_syserrmsgs + 2756, + [ENAVAIL] = _string_syserrmsgs + 2784, + [EISNAM] = _string_syserrmsgs + 2814, + [EREMOTEIO] = _string_syserrmsgs + 2835, + [EDQUOT] = _string_syserrmsgs + 2852, + [ENOMEDIUM] = _string_syserrmsgs + 2872, + [EMEDIUMTYPE] = _string_syserrmsgs + 2888, + +#if EDEADLOCK != EDEADLK + [EDEADLOCK] = _string_syserrmsgs + 2906, +#endif + +#if EWOULDBLOCK != EAGAIN +#error EWOULDBLOCK does not equal EAGAIN +#endif + + /* For now, ignore the other arch-specific errors. glibc only maps EPROCLIM. */ + + /* some other mips errors */ +#ifdef ECANCELED +#endif +#ifdef EINIT +#endif +#ifdef EREMDEV +#endif + + /* some other sparc errors */ +#ifdef EPROCLIM +#endif +#ifdef ERREMOTE +#endif +}; + +int sys_nerr = sizeof(sys_errlist)/sizeof(sys_errlist[0]); + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sys_siglist.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sys_siglist.c new file mode 100644 index 00000000..84433753 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/sys_siglist.c @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2002 Manuel Novoa III + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#define __need_NULL +#include +#include + +extern const char _string_syssigmsgs[] attribute_hidden; + +#ifdef __UCLIBC_HAS_SYS_SIGLIST__ + +const char *const sys_siglist[_NSIG] = { + [0] = NULL, + [SIGHUP] = _string_syssigmsgs + 1, + [SIGINT] = _string_syssigmsgs + 8, + [SIGQUIT] = _string_syssigmsgs + 18, + [SIGILL] = _string_syssigmsgs + 23, + [SIGTRAP] = _string_syssigmsgs + 43, + [SIGABRT] = _string_syssigmsgs + 65, + [SIGBUS] = _string_syssigmsgs + 73, + [SIGFPE] = _string_syssigmsgs + 83, + [SIGKILL] = _string_syssigmsgs + 108, + [SIGUSR1] = _string_syssigmsgs + 115, + [SIGSEGV] = _string_syssigmsgs + 137, + [SIGUSR2] = _string_syssigmsgs + 156, + [SIGPIPE] = _string_syssigmsgs + 178, + [SIGALRM] = _string_syssigmsgs + 190, + [SIGTERM] = _string_syssigmsgs + 202, +#if defined SIGSTKFLT /* not all arches define this, yeah ! */ + [SIGSTKFLT] = _string_syssigmsgs + 213, +#endif + [SIGCHLD] = _string_syssigmsgs + 225, + [SIGCONT] = _string_syssigmsgs + 238, + [SIGSTOP] = _string_syssigmsgs + 248, + [SIGTSTP] = _string_syssigmsgs + 265, + [SIGTTIN] = _string_syssigmsgs + 273, + [SIGTTOU] = _string_syssigmsgs + 293, + [SIGURG] = _string_syssigmsgs + 314, + [SIGXCPU] = _string_syssigmsgs + 335, + [SIGXFSZ] = _string_syssigmsgs + 359, + [SIGVTALRM] = _string_syssigmsgs + 384, + [SIGPROF] = _string_syssigmsgs + 406, + [SIGWINCH] = _string_syssigmsgs + 430, + [SIGIO] = _string_syssigmsgs + 445, + [SIGPWR] = _string_syssigmsgs + 458, + [SIGSYS] = _string_syssigmsgs + 472, +#if defined SIGEMT /* only some arches define this, yeah ! */ + [SIGEMT] = _string_syssigmsgs + 488, +#endif +}; + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcpcpy.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcpcpy.c new file mode 100644 index 00000000..b4fc8e61 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcpcpy.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define WANT_WIDE +#include "stpcpy.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcpncpy.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcpncpy.c new file mode 100644 index 00000000..c5e5a761 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcpncpy.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define WANT_WIDE +#include "stpncpy.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcscasecmp.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcscasecmp.c new file mode 100644 index 00000000..95291b15 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcscasecmp.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define WANT_WIDE +#include "strcasecmp.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcscasecmp_l.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcscasecmp_l.c new file mode 100644 index 00000000..99e5723a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcscasecmp_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define WANT_WIDE +#define __UCLIBC_DO_XLOCALE +#include "strcasecmp.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcscat.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcscat.c new file mode 100644 index 00000000..36b4b638 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcscat.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define WANT_WIDE +#include "strcat.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcschr.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcschr.c new file mode 100644 index 00000000..d16650ac --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcschr.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define WANT_WIDE +#include "strchr.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcschrnul.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcschrnul.c new file mode 100644 index 00000000..dc1b1bcd --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcschrnul.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define WANT_WIDE +#include "strchrnul.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcscmp.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcscmp.c new file mode 100644 index 00000000..a33ed835 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcscmp.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define WANT_WIDE +#include "strcmp.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcscpy.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcscpy.c new file mode 100644 index 00000000..34799842 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcscpy.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define WANT_WIDE +#include "strcpy.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcscspn.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcscspn.c new file mode 100644 index 00000000..945ecef6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcscspn.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define WANT_WIDE +#include "strcspn.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcsdup.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcsdup.c new file mode 100644 index 00000000..8885a2ba --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcsdup.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define WANT_WIDE +#include "strdup.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcslcpy.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcslcpy.c new file mode 100644 index 00000000..f62ea14e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcslcpy.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define WANT_WIDE +#include "strlcpy.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcslen.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcslen.c new file mode 100644 index 00000000..ac4637e8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcslen.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define WANT_WIDE +#include "strlen.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcsncasecmp.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcsncasecmp.c new file mode 100644 index 00000000..230efdad --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcsncasecmp.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define WANT_WIDE +#include "strncasecmp.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcsncasecmp_l.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcsncasecmp_l.c new file mode 100644 index 00000000..acdb26b1 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcsncasecmp_l.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define WANT_WIDE +#define __UCLIBC_DO_XLOCALE +#include "strncasecmp.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcsncat.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcsncat.c new file mode 100644 index 00000000..776f1b7b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcsncat.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define WANT_WIDE +#include "strncat.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcsncmp.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcsncmp.c new file mode 100644 index 00000000..224844fd --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcsncmp.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define WANT_WIDE +#include "strncmp.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcsncpy.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcsncpy.c new file mode 100644 index 00000000..ac267e81 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcsncpy.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define WANT_WIDE +#include "strncpy.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcsnlen.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcsnlen.c new file mode 100644 index 00000000..917a2c9f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcsnlen.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define WANT_WIDE +#include "strnlen.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcspbrk.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcspbrk.c new file mode 100644 index 00000000..b416f7c2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcspbrk.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define WANT_WIDE +#include "strpbrk.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcsrchr.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcsrchr.c new file mode 100644 index 00000000..3290820d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcsrchr.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define WANT_WIDE +#include "strrchr.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcsspn.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcsspn.c new file mode 100644 index 00000000..9716315a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcsspn.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define WANT_WIDE +#include "strspn.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcsstr.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcsstr.c new file mode 100644 index 00000000..69a94e58 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcsstr.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define WANT_WIDE +#include "strstr.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcstok.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcstok.c new file mode 100644 index 00000000..591c214a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcstok.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define WANT_WIDE +#include "strtok_r.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcsxfrm.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcsxfrm.c new file mode 100644 index 00000000..8b37495a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcsxfrm.c @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define WANT_WIDE +#define L_wcsxfrm +#include "_collate.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcsxfrm_l.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcsxfrm_l.c new file mode 100644 index 00000000..67e2f170 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wcsxfrm_l.c @@ -0,0 +1,10 @@ +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define WANT_WIDE +#define __UCLIBC_DO_XLOCALE +#define L_wcsxfrm_l +#include "_collate.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wmemchr.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wmemchr.c new file mode 100644 index 00000000..f4069e40 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wmemchr.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define WANT_WIDE +#include "memchr.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wmemcmp.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wmemcmp.c new file mode 100644 index 00000000..9168705c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wmemcmp.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define WANT_WIDE +#include "memcmp.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wmemcpy.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wmemcpy.c new file mode 100644 index 00000000..6991ece7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wmemcpy.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define WANT_WIDE +#include "memcpy.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wmemmove.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wmemmove.c new file mode 100644 index 00000000..17270491 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wmemmove.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define WANT_WIDE +#include "memmove.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wmempcpy.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wmempcpy.c new file mode 100644 index 00000000..d995a809 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wmempcpy.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define WANT_WIDE +#include "mempcpy.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wmemset.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wmemset.c new file mode 100644 index 00000000..0efe1783 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/wmemset.c @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define WANT_WIDE +#include "memset.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/x86_64/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/x86_64/Makefile new file mode 100644 index 00000000..0a95346f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/x86_64/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir:=../../../ +top_builddir:=../../../ +all: objs +include $(top_builddir)Rules.mak +include ../Makefile.in +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/x86_64/_glibc_inc.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/x86_64/_glibc_inc.h new file mode 100644 index 00000000..415ce90a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/x86_64/_glibc_inc.h @@ -0,0 +1,21 @@ +/* + * Setup some glibc defines so we can just drop in the + * asm files from glibc without any modification. + */ + +#include +#include + +#define ENTRY(sym) \ + .global sym; \ + .type sym,%function; \ + sym: + +#define BP_SYM(sym) sym + +#define L(sym) LOC(sym) +#define LOC(sym) \ + .L ## sym + +#define END(sym) \ + .size sym,.-sym; diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/x86_64/bzero.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/x86_64/bzero.S new file mode 100644 index 00000000..231d7cb4 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/x86_64/bzero.S @@ -0,0 +1,6 @@ +#include +#ifdef __UCLIBC_SUSV3_LEGACY__ +# define memset bzero +# define __memset_chk __bzero_chk +# include "memset.S" +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/x86_64/memcpy.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/x86_64/memcpy.S new file mode 100644 index 00000000..6d941e0f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/x86_64/memcpy.S @@ -0,0 +1,100 @@ +/* Highly optimized version for x86-64. + Copyright (C) 1997, 2000, 2002, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Based on i586 version contributed by Ulrich Drepper , 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "_glibc_inc.h" + +/* BEWARE: `#ifdef memcpy' means that memcpy is redefined as `mempcpy', + and the return value is the byte after the last one copied in + the destination. */ +#define MEMPCPY_P (defined memcpy) + + .text +#if defined __PIC__ && !defined NOT_IN_libc +ENTRY (__memcpy_chk) + cmpq %rdx, %rcx +#if defined __UCLIBC_HAS_SSP__ + jb HIDDEN_JUMPTARGET (__chk_fail) +#endif +END (__memcpy_chk) +#endif +ENTRY (BP_SYM (memcpy)) + /* Cutoff for the big loop is a size of 32 bytes since otherwise + the loop will never be entered. */ + cmpq $32, %rdx + movq %rdx, %rcx +#if !MEMPCPY_P + movq %rdi, %r10 /* Save value. */ +#endif + + /* We need this in any case. */ + cld + + jbe 1f + + /* Align destination. */ + movq %rdi, %rax + negq %rax + andq $7, %rax + subq %rax, %rcx + xchgq %rax, %rcx + + rep; movsb + + movq %rax, %rcx + subq $32, %rcx + js 2f + + /* Next 3 insns are 11 bytes total, make sure we decode them in one go */ + .p2align 4,,11 +3: + /* Now correct the loop counter. Please note that in the following + code the flags are not changed anymore. */ + subq $32, %rcx + + movq (%rsi), %rax + movq 8(%rsi), %rdx + movq 16(%rsi), %r8 + movq 24(%rsi), %r9 + movq %rax, (%rdi) + movq %rdx, 8(%rdi) + movq %r8, 16(%rdi) + movq %r9, 24(%rdi) + + leaq 32(%rsi), %rsi + leaq 32(%rdi), %rdi + + jns 3b + + /* Correct extra loop counter modification. */ +2: addq $32, %rcx +1: rep; movsb + +#if MEMPCPY_P + movq %rdi, %rax /* Set return value. */ +#else + movq %r10, %rax /* Set return value. */ + +#endif + ret + +END (BP_SYM (memcpy)) +#if !MEMPCPY_P +libc_hidden_def(memcpy) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/x86_64/mempcpy.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/x86_64/mempcpy.S new file mode 100644 index 00000000..b0607aa5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/x86_64/mempcpy.S @@ -0,0 +1,4 @@ +#define memcpy mempcpy +#define __memcpy_chk __mempcpy_chk +#include "memcpy.S" +libc_hidden_def(mempcpy) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/x86_64/memset.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/x86_64/memset.S new file mode 100644 index 00000000..df265f39 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/x86_64/memset.S @@ -0,0 +1,149 @@ +/* memset/bzero -- set memory area to CH/0 + Optimized version for x86-64. + Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Andreas Jaeger . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "_glibc_inc.h" + +/* BEWARE: `#ifdef memset' means that memset is redefined as `bzero' */ +#define BZERO_P (defined memset) + +/* This is somehow experimental and could made dependend on the cache + size. */ +#define LARGE $120000 + + .text +#if defined __PIC__ && !defined NOT_IN_libc +ENTRY (__memset_chk) + cmpq %rdx, %rcx +#if defined __UCLIBC_HAS_SSP__ + jb HIDDEN_JUMPTARGET (__chk_fail) +#endif +END (__memset_chk) +#endif +ENTRY (memset) +#if BZERO_P + mov %rsi,%rdx /* Adjust parameter. */ + xorl %esi,%esi /* Fill with 0s. */ +#endif + cmp $0x7,%rdx /* Check for small length. */ + mov %rdi,%rcx /* Save ptr as return value. */ + jbe 7f + +#if BZERO_P + mov %rsi,%r8 /* Just copy 0. */ +#else + /* Populate 8 bit data to full 64-bit. */ + movabs $0x0101010101010101,%r8 + movzbl %sil,%eax + imul %rax,%r8 +#endif + test $0x7,%edi /* Check for alignment. */ + jz 2f + + /* Next 3 insns are 9 bytes total, make sure we decode them in one go */ + .p2align 4,,9 +1: + /* Align ptr to 8 byte. */ + mov %sil,(%rcx) + dec %rdx + inc %rcx + test $0x7,%cl + jnz 1b + +2: /* Check for really large regions. */ + mov %rdx,%rax + shr $0x6,%rax + je 4f + cmp LARGE, %rdx + jae 11f + + /* Next 3 insns are 11 bytes total, make sure we decode them in one go */ + .p2align 4,,11 +3: + /* Fill 64 bytes. */ + mov %r8,(%rcx) + mov %r8,0x8(%rcx) + mov %r8,0x10(%rcx) + mov %r8,0x18(%rcx) + mov %r8,0x20(%rcx) + mov %r8,0x28(%rcx) + mov %r8,0x30(%rcx) + mov %r8,0x38(%rcx) + add $0x40,%rcx + dec %rax + jne 3b + +4: /* Fill final bytes. */ + and $0x3f,%edx + mov %rdx,%rax + shr $0x3,%rax + je 6f + +5: /* First in chunks of 8 bytes. */ + mov %r8,(%rcx) + add $0x8,%rcx + dec %rax + jne 5b +6: + and $0x7,%edx +7: + test %rdx,%rdx + je 9f +8: /* And finally as bytes (up to 7). */ + mov %sil,(%rcx) + inc %rcx + dec %rdx + jne 8b +9: +#if BZERO_P + /* nothing */ +#else + /* Load result (only if used as memset). */ + mov %rdi,%rax /* start address of destination is result */ +#endif + retq + + /* Next 3 insns are 14 bytes total, make sure we decode them in one go */ + .p2align 4,,14 +11: + /* Fill 64 bytes without polluting the cache. */ + /* We could use movntdq %xmm0,(%rcx) here to further + speed up for large cases but let's not use XMM registers. */ + movnti %r8,(%rcx) + movnti %r8,0x8(%rcx) + movnti %r8,0x10(%rcx) + movnti %r8,0x18(%rcx) + movnti %r8,0x20(%rcx) + movnti %r8,0x28(%rcx) + movnti %r8,0x30(%rcx) + movnti %r8,0x38(%rcx) + add $0x40,%rcx + dec %rax + jne 11b + jmp 4b + +END (memset) +#if !BZERO_P +libc_hidden_def(memset) +#endif + +#if !BZERO_P && defined __PIC__ && !defined NOT_IN_libc +strong_alias (__memset_chk, __memset_zero_constant_len_parameter) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/x86_64/stpcpy.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/x86_64/stpcpy.S new file mode 100644 index 00000000..138d0fb1 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/x86_64/stpcpy.S @@ -0,0 +1,4 @@ +#define USE_AS_STPCPY +#define STRCPY stpcpy +#include "strcpy.S" +libc_hidden_def(stpcpy) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/x86_64/strcat.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/x86_64/strcat.S new file mode 100644 index 00000000..23d068fe --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/x86_64/strcat.S @@ -0,0 +1,268 @@ +/* strcat(dest, src) -- Append SRC on the end of DEST. + Optimized for x86-64. + Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Andreas Jaeger , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "_glibc_inc.h" + +/* Seems to be unrolled too much */ + + .text +ENTRY (BP_SYM (strcat)) + movq %rdi, %rcx /* Dest. register. */ + andl $7, %ecx /* mask alignment bits */ + movq %rdi, %rax /* Duplicate destination pointer. */ + movq $0xfefefefefefefeff,%r8 + + /* First step: Find end of destination. */ + jz 4f /* aligned => start loop */ + + neg %ecx /* We need to align to 8 bytes. */ + addl $8,%ecx + /* Search the first bytes directly. */ +0: cmpb $0x0,(%rax) /* is byte NUL? */ + je 2f /* yes => start copy */ + incq %rax /* increment pointer */ + decl %ecx + jnz 0b + + + + /* Now the source is aligned. Scan for NUL byte. */ + + /* Next 3 insns are 10 bytes total, make sure we decode them in one go */ + .p2align 4,,10 +4: + /* First unroll. */ + movq (%rax), %rcx /* get double word (= 8 bytes) in question */ + addq $8,%rax /* adjust pointer for next word */ + movq %r8, %rdx /* magic value */ + addq %rcx, %rdx /* add the magic value to the word. We get + carry bits reported for each byte which + is *not* 0 */ + jnc 3f /* highest byte is NUL => return pointer */ + xorq %rcx, %rdx /* (word+magic)^word */ + orq %r8, %rdx /* set all non-carry bits */ + incq %rdx /* add 1: if one carry bit was *not* set + the addition will not result in 0. */ + jnz 3f /* found NUL => return pointer */ + + /* Second unroll. */ + movq (%rax), %rcx /* get double word (= 8 bytes) in question */ + addq $8,%rax /* adjust pointer for next word */ + movq %r8, %rdx /* magic value */ + addq %rcx, %rdx /* add the magic value to the word. We get + carry bits reported for each byte which + is *not* 0 */ + jnc 3f /* highest byte is NUL => return pointer */ + xorq %rcx, %rdx /* (word+magic)^word */ + orq %r8, %rdx /* set all non-carry bits */ + incq %rdx /* add 1: if one carry bit was *not* set + the addition will not result in 0. */ + jnz 3f /* found NUL => return pointer */ + + /* Third unroll. */ + movq (%rax), %rcx /* get double word (= 8 bytes) in question */ + addq $8,%rax /* adjust pointer for next word */ + movq %r8, %rdx /* magic value */ + addq %rcx, %rdx /* add the magic value to the word. We get + carry bits reported for each byte which + is *not* 0 */ + jnc 3f /* highest byte is NUL => return pointer */ + xorq %rcx, %rdx /* (word+magic)^word */ + orq %r8, %rdx /* set all non-carry bits */ + incq %rdx /* add 1: if one carry bit was *not* set + the addition will not result in 0. */ + jnz 3f /* found NUL => return pointer */ + + /* Fourth unroll. */ + movq (%rax), %rcx /* get double word (= 8 bytes) in question */ + addq $8,%rax /* adjust pointer for next word */ + movq %r8, %rdx /* magic value */ + addq %rcx, %rdx /* add the magic value to the word. We get + carry bits reported for each byte which + is *not* 0 */ + jnc 3f /* highest byte is NUL => return pointer */ + xorq %rcx, %rdx /* (word+magic)^word */ + orq %r8, %rdx /* set all non-carry bits */ + incq %rdx /* add 1: if one carry bit was *not* set + the addition will not result in 0. */ + jz 4b /* no NUL found => continue loop */ + + /* Align, it is a jump target. */ + /* Next 3 insns are 8 bytes total, make sure we decode them in one go */ + .p2align 3,,8 +3: + subq $8,%rax /* correct pointer increment. */ + + testb %cl, %cl /* is first byte NUL? */ + jz 2f /* yes => return */ + incq %rax /* increment pointer */ + + testb %ch, %ch /* is second byte NUL? */ + jz 2f /* yes => return */ + incq %rax /* increment pointer */ + + testl $0x00ff0000, %ecx /* is third byte NUL? */ + jz 2f /* yes => return pointer */ + incq %rax /* increment pointer */ + + testl $0xff000000, %ecx /* is fourth byte NUL? */ + jz 2f /* yes => return pointer */ + incq %rax /* increment pointer */ + + shrq $32, %rcx /* look at other half. */ + + testb %cl, %cl /* is first byte NUL? */ + jz 2f /* yes => return */ + incq %rax /* increment pointer */ + + testb %ch, %ch /* is second byte NUL? */ + jz 2f /* yes => return */ + incq %rax /* increment pointer */ + + testl $0xff0000, %ecx /* is third byte NUL? */ + jz 2f /* yes => return pointer */ + incq %rax /* increment pointer */ + +2: + /* Second step: Copy source to destination. */ + + movq %rsi, %rcx /* duplicate */ + andl $7,%ecx /* mask alignment bits */ + movq %rax, %rdx /* move around */ + jz 22f /* aligned => start loop */ + + neg %ecx /* align to 8 bytes. */ + addl $8, %ecx + /* Align the source pointer. */ +21: + movb (%rsi), %al /* Fetch a byte */ + testb %al, %al /* Is it NUL? */ + movb %al, (%rdx) /* Store it */ + jz 24f /* If it was NUL, done! */ + incq %rsi + incq %rdx + decl %ecx + jnz 21b + + /* Now the sources is aligned. Unfortunatly we cannot force + to have both source and destination aligned, so ignore the + alignment of the destination. */ + + /* Next 3 insns are 10 bytes total, make sure we decode them in one go */ + .p2align 4,,10 +22: + /* 1st unroll. */ + movq (%rsi), %rax /* Read double word (8 bytes). */ + addq $8, %rsi /* Adjust pointer for next word. */ + movq %rax, %r9 /* Save a copy for NUL finding. */ + addq %r8, %r9 /* add the magic value to the word. We get + carry bits reported for each byte which + is *not* 0 */ + jnc 23f /* highest byte is NUL => return pointer */ + xorq %rax, %r9 /* (word+magic)^word */ + orq %r8, %r9 /* set all non-carry bits */ + incq %r9 /* add 1: if one carry bit was *not* set + the addition will not result in 0. */ + + jnz 23f /* found NUL => return pointer */ + + movq %rax, (%rdx) /* Write value to destination. */ + addq $8, %rdx /* Adjust pointer. */ + + /* 2nd unroll. */ + movq (%rsi), %rax /* Read double word (8 bytes). */ + addq $8, %rsi /* Adjust pointer for next word. */ + movq %rax, %r9 /* Save a copy for NUL finding. */ + addq %r8, %r9 /* add the magic value to the word. We get + carry bits reported for each byte which + is *not* 0 */ + jnc 23f /* highest byte is NUL => return pointer */ + xorq %rax, %r9 /* (word+magic)^word */ + orq %r8, %r9 /* set all non-carry bits */ + incq %r9 /* add 1: if one carry bit was *not* set + the addition will not result in 0. */ + + jnz 23f /* found NUL => return pointer */ + + movq %rax, (%rdx) /* Write value to destination. */ + addq $8, %rdx /* Adjust pointer. */ + + /* 3rd unroll. */ + movq (%rsi), %rax /* Read double word (8 bytes). */ + addq $8, %rsi /* Adjust pointer for next word. */ + movq %rax, %r9 /* Save a copy for NUL finding. */ + addq %r8, %r9 /* add the magic value to the word. We get + carry bits reported for each byte which + is *not* 0 */ + jnc 23f /* highest byte is NUL => return pointer */ + xorq %rax, %r9 /* (word+magic)^word */ + orq %r8, %r9 /* set all non-carry bits */ + incq %r9 /* add 1: if one carry bit was *not* set + the addition will not result in 0. */ + + jnz 23f /* found NUL => return pointer */ + + movq %rax, (%rdx) /* Write value to destination. */ + addq $8, %rdx /* Adjust pointer. */ + + /* 4th unroll. */ + movq (%rsi), %rax /* Read double word (8 bytes). */ + addq $8, %rsi /* Adjust pointer for next word. */ + movq %rax, %r9 /* Save a copy for NUL finding. */ + addq %r8, %r9 /* add the magic value to the word. We get + carry bits reported for each byte which + is *not* 0 */ + jnc 23f /* highest byte is NUL => return pointer */ + xorq %rax, %r9 /* (word+magic)^word */ + orq %r8, %r9 /* set all non-carry bits */ + incq %r9 /* add 1: if one carry bit was *not* set + the addition will not result in 0. */ + + jnz 23f /* found NUL => return pointer */ + + movq %rax, (%rdx) /* Write value to destination. */ + addq $8, %rdx /* Adjust pointer. */ + jmp 22b /* Next iteration. */ + + /* Do the last few bytes. %rax contains the value to write. + The loop is unrolled twice. */ + + /* Next 3 insns are 6 bytes total, make sure we decode them in one go */ + .p2align 3,,6 +23: + movb %al, (%rdx) /* 1st byte. */ + testb %al, %al /* Is it NUL. */ + jz 24f /* yes, finish. */ + incq %rdx /* Increment destination. */ + movb %ah, (%rdx) /* 2nd byte. */ + testb %ah, %ah /* Is it NUL?. */ + jz 24f /* yes, finish. */ + incq %rdx /* Increment destination. */ + shrq $16, %rax /* Shift... */ + jmp 23b /* and look at next two bytes in %rax. */ + + +24: + movq %rdi, %rax /* Source is return value. */ + retq +END (BP_SYM (strcat)) + +libc_hidden_def(strcat) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/x86_64/strchr.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/x86_64/strchr.S new file mode 100644 index 00000000..9ef46b7f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/x86_64/strchr.S @@ -0,0 +1,295 @@ +/* strchr (str, ch) -- Return pointer to first occurrence of CH in STR. + For AMD x86-64. + Copyright (C) 2002, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "_glibc_inc.h" + +/* Seems to be unrolled too much */ + + .text +ENTRY (BP_SYM (strchr)) + + /* Before we start with the main loop we process single bytes + until the source pointer is aligned. This has two reasons: + 1. aligned 64-bit memory access is faster + and (more important) + 2. we process in the main loop 64 bit in one step although + we don't know the end of the string. But accessing at + 8-byte alignment guarantees that we never access illegal + memory if this would not also be done by the trivial + implementation (this is because all processor inherent + boundaries are multiples of 8). */ + + movq %rdi, %rdx + andl $7, %edx /* Mask alignment bits */ + movq %rdi, %rax /* duplicate destination. */ + jz 1f /* aligned => start loop */ + neg %edx + addl $8, %edx /* Align to 8 bytes. */ + + /* Search the first bytes directly. */ +0: movb (%rax), %cl /* load byte */ + cmpb %cl,%sil /* compare byte. */ + je 6f /* target found */ + testb %cl,%cl /* is byte NUL? */ + je 7f /* yes => return NULL */ + incq %rax /* increment pointer */ + decl %edx + jnz 0b + + +1: + /* At the moment %rsi contains C. What we need for the + algorithm is C in all bytes of the register. Avoid + operations on 16 bit words because these require an + prefix byte (and one more cycle). */ + /* Populate 8 bit data to full 64-bit. */ + movabs $0x0101010101010101,%r9 + movzbl %sil,%edx + imul %rdx,%r9 + + movq $0xfefefefefefefeff, %r8 /* Save magic. */ + + /* We exit the loop if adding MAGIC_BITS to LONGWORD fails to + change any of the hole bits of LONGWORD. + + 1) Is this safe? Will it catch all the zero bytes? + Suppose there is a byte with all zeros. Any carry bits + propagating from its left will fall into the hole at its + least significant bit and stop. Since there will be no + carry from its most significant bit, the LSB of the + byte to the left will be unchanged, and the zero will be + detected. + + 2) Is this worthwhile? Will it ignore everything except + zero bytes? Suppose every byte of QUARDWORD has a bit set + somewhere. There will be a carry into bit 8. If bit 8 + is set, this will carry into bit 16. If bit 8 is clear, + one of bits 9-15 must be set, so there will be a carry + into bit 16. Similarly, there will be a carry into bit + 24 tec.. If one of bits 54-63 is set, there will be a carry + into bit 64 (=carry flag), so all of the hole bits will + be changed. + + 3) But wait! Aren't we looking for C, not zero? + Good point. So what we do is XOR LONGWORD with a longword, + each of whose bytes is C. This turns each byte that is C + into a zero. */ + + /* Next 3 insns are 10 bytes total, make sure we decode them in one go */ + .p2align 4,,10 +4: + /* Main Loop is unrolled 4 times. */ + /* First unroll. */ + movq (%rax), %rcx /* get double word (= 8 bytes) in question */ + addq $8,%rax /* adjust pointer for next word */ + movq %r8, %rdx /* magic value */ + xorq %r9, %rcx /* XOR with qword c|...|c => bytes of str == c + are now 0 */ + addq %rcx, %rdx /* add the magic value to the word. We get + carry bits reported for each byte which + is *not* 0 */ + jnc 3f /* highest byte is NUL => return pointer */ + xorq %rcx, %rdx /* (word+magic)^word */ + orq %r8, %rdx /* set all non-carry bits */ + incq %rdx /* add 1: if one carry bit was *not* set + the addition will not result in 0. */ + jnz 3f /* found c => return pointer */ + + /* The quadword we looked at does not contain the value we're looking + for. Let's search now whether we have reached the end of the + string. */ + xorq %r9, %rcx /* restore original dword without reload */ + movq %r8, %rdx /* magic value */ + addq %rcx, %rdx /* add the magic value to the word. We get + carry bits reported for each byte which + is *not* 0 */ + jnc 7f /* highest byte is NUL => return NULL */ + xorq %rcx, %rdx /* (word+magic)^word */ + orq %r8, %rdx /* set all non-carry bits */ + incq %rdx /* add 1: if one carry bit was *not* set + the addition will not result in 0. */ + jnz 7f /* found NUL => return NULL */ + + /* Second unroll. */ + movq (%rax), %rcx /* get double word (= 8 bytes) in question */ + addq $8,%rax /* adjust pointer for next word */ + movq %r8, %rdx /* magic value */ + xorq %r9, %rcx /* XOR with qword c|...|c => bytes of str == c + are now 0 */ + addq %rcx, %rdx /* add the magic value to the word. We get + carry bits reported for each byte which + is *not* 0 */ + jnc 3f /* highest byte is NUL => return pointer */ + xorq %rcx, %rdx /* (word+magic)^word */ + orq %r8, %rdx /* set all non-carry bits */ + incq %rdx /* add 1: if one carry bit was *not* set + the addition will not result in 0. */ + jnz 3f /* found c => return pointer */ + + /* The quadword we looked at does not contain the value we're looking + for. Let's search now whether we have reached the end of the + string. */ + xorq %r9, %rcx /* restore original dword without reload */ + movq %r8, %rdx /* magic value */ + addq %rcx, %rdx /* add the magic value to the word. We get + carry bits reported for each byte which + is *not* 0 */ + jnc 7f /* highest byte is NUL => return NULL */ + xorq %rcx, %rdx /* (word+magic)^word */ + orq %r8, %rdx /* set all non-carry bits */ + incq %rdx /* add 1: if one carry bit was *not* set + the addition will not result in 0. */ + jnz 7f /* found NUL => return NULL */ + /* Third unroll. */ + movq (%rax), %rcx /* get double word (= 8 bytes) in question */ + addq $8,%rax /* adjust pointer for next word */ + movq %r8, %rdx /* magic value */ + xorq %r9, %rcx /* XOR with qword c|...|c => bytes of str == c + are now 0 */ + addq %rcx, %rdx /* add the magic value to the word. We get + carry bits reported for each byte which + is *not* 0 */ + jnc 3f /* highest byte is NUL => return pointer */ + xorq %rcx, %rdx /* (word+magic)^word */ + orq %r8, %rdx /* set all non-carry bits */ + incq %rdx /* add 1: if one carry bit was *not* set + the addition will not result in 0. */ + jnz 3f /* found c => return pointer */ + + /* The quadword we looked at does not contain the value we're looking + for. Let's search now whether we have reached the end of the + string. */ + xorq %r9, %rcx /* restore original dword without reload */ + movq %r8, %rdx /* magic value */ + addq %rcx, %rdx /* add the magic value to the word. We get + carry bits reported for each byte which + is *not* 0 */ + jnc 7f /* highest byte is NUL => return NULL */ + xorq %rcx, %rdx /* (word+magic)^word */ + orq %r8, %rdx /* set all non-carry bits */ + incq %rdx /* add 1: if one carry bit was *not* set + the addition will not result in 0. */ + jnz 7f /* found NUL => return NULL */ + /* Fourth unroll. */ + movq (%rax), %rcx /* get double word (= 8 bytes) in question */ + addq $8,%rax /* adjust pointer for next word */ + movq %r8, %rdx /* magic value */ + xorq %r9, %rcx /* XOR with qword c|...|c => bytes of str == c + are now 0 */ + addq %rcx, %rdx /* add the magic value to the word. We get + carry bits reported for each byte which + is *not* 0 */ + jnc 3f /* highest byte is NUL => return pointer */ + xorq %rcx, %rdx /* (word+magic)^word */ + orq %r8, %rdx /* set all non-carry bits */ + incq %rdx /* add 1: if one carry bit was *not* set + the addition will not result in 0. */ + jnz 3f /* found c => return pointer */ + + /* The quadword we looked at does not contain the value we're looking + for. Let's search now whether we have reached the end of the + string. */ + xorq %r9, %rcx /* restore original dword without reload */ + movq %r8, %rdx /* magic value */ + addq %rcx, %rdx /* add the magic value to the word. We get + carry bits reported for each byte which + is *not* 0 */ + jnc 7f /* highest byte is NUL => return NULL */ + xorq %rcx, %rdx /* (word+magic)^word */ + orq %r8, %rdx /* set all non-carry bits */ + incq %rdx /* add 1: if one carry bit was *not* set + the addition will not result in 0. */ + jz 4b /* no NUL found => restart loop */ + + +7: /* Return NULL. */ + xorl %eax, %eax + retq + + + /* We now scan for the byte in which the character was matched. + But we have to take care of the case that a NUL char is + found before this in the dword. Note that we XORed %rcx + with the byte we're looking for, therefore the tests below look + reversed. */ + + + /* Align, it's a jump target. */ + /* Next 3 insns are 9 bytes total, make sure we decode them in one go */ + .p2align 4,,9 +3: + movq %r9,%rdx /* move to %rdx so that we can access bytes */ + subq $8,%rax /* correct pointer increment. */ + testb %cl, %cl /* is first byte C? */ + jz 6f /* yes => return pointer */ + cmpb %dl, %cl /* is first byte NUL? */ + je 7b /* yes => return NULL */ + incq %rax /* increment pointer */ + + testb %ch, %ch /* is second byte C? */ + jz 6f /* yes => return pointer */ + cmpb %dl, %ch /* is second byte NUL? */ + je 7b /* yes => return NULL? */ + incq %rax /* increment pointer */ + + shrq $16, %rcx /* make upper bytes accessible */ + testb %cl, %cl /* is third byte C? */ + jz 6f /* yes => return pointer */ + cmpb %dl, %cl /* is third byte NUL? */ + je 7b /* yes => return NULL */ + incq %rax /* increment pointer */ + + testb %ch, %ch /* is fourth byte C? */ + jz 6f /* yes => return pointer */ + cmpb %dl, %ch /* is fourth byte NUL? */ + je 7b /* yes => return NULL? */ + incq %rax /* increment pointer */ + + shrq $16, %rcx /* make upper bytes accessible */ + testb %cl, %cl /* is fifth byte C? */ + jz 6f /* yes => return pointer */ + cmpb %dl, %cl /* is fifth byte NUL? */ + je 7b /* yes => return NULL */ + incq %rax /* increment pointer */ + + testb %ch, %ch /* is sixth byte C? */ + jz 6f /* yes => return pointer */ + cmpb %dl, %ch /* is sixth byte NUL? */ + je 7b /* yes => return NULL? */ + incq %rax /* increment pointer */ + + shrq $16, %rcx /* make upper bytes accessible */ + testb %cl, %cl /* is seventh byte C? */ + jz 6f /* yes => return pointer */ + cmpb %dl, %cl /* is seventh byte NUL? */ + je 7b /* yes => return NULL */ + + /* It must be in the eigth byte and it cannot be NUL. */ + incq %rax + +6: + /* nop - huh?? */ + retq +END (BP_SYM (strchr)) + +libc_hidden_def(strchr) +#ifdef __UCLIBC_SUSV3_LEGACY__ +strong_alias (BP_SYM (strchr), BP_SYM (index)) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/x86_64/strcmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/x86_64/strcmp.S new file mode 100644 index 00000000..437e145b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/x86_64/strcmp.S @@ -0,0 +1,47 @@ +/* Highly optimized version for x86-64. + Copyright (C) 1999, 2000, 2002, 2003, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Based on i686 version contributed by Ulrich Drepper + , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "_glibc_inc.h" + + .text +ENTRY (BP_SYM (strcmp)) +L(oop): movb (%rdi), %al + cmpb (%rsi), %al + jne L(neq) + incq %rdi + incq %rsi + testb %al, %al + jnz L(oop) + + xorl %eax, %eax + ret + +L(neq): movl $1, %eax + movl $-1, %ecx + cmovbl %ecx, %eax + ret +END (BP_SYM (strcmp)) + +libc_hidden_def(strcmp) +#ifndef __UCLIBC_HAS_LOCALE__ +strong_alias(strcmp,strcoll) +libc_hidden_def(strcoll) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/x86_64/strcpy.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/x86_64/strcpy.S new file mode 100644 index 00000000..612a30d1 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/x86_64/strcpy.S @@ -0,0 +1,162 @@ +/* strcpy/stpcpy implementation for x86-64. + Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Andreas Jaeger , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "_glibc_inc.h" + +/* Seems to be unrolled too much */ + +#ifndef USE_AS_STPCPY +# define STRCPY strcpy +#endif + + .text +ENTRY (BP_SYM (STRCPY)) + movq %rsi, %rcx /* Source register. */ + andl $7, %ecx /* mask alignment bits */ + movq %rdi, %rdx /* Duplicate destination pointer. */ + + jz 5f /* aligned => start loop */ + + neg %ecx /* We need to align to 8 bytes. */ + addl $8,%ecx + /* Search the first bytes directly. */ +0: + movb (%rsi), %al /* Fetch a byte */ + testb %al, %al /* Is it NUL? */ + movb %al, (%rdx) /* Store it */ + jz 4f /* If it was NUL, done! */ + incq %rsi + incq %rdx + decl %ecx + jnz 0b + +5: + movq $0xfefefefefefefeff,%r8 + + /* Now the sources is aligned. Unfortunatly we cannot force + to have both source and destination aligned, so ignore the + alignment of the destination. */ + + /* Next 3 insns are 10 bytes total, make sure we decode them in one go */ + .p2align 4,,10 +1: + /* 1st unroll. */ + movq (%rsi), %rax /* Read double word (8 bytes). */ + addq $8, %rsi /* Adjust pointer for next word. */ + movq %rax, %r9 /* Save a copy for NUL finding. */ + addq %r8, %r9 /* add the magic value to the word. We get + carry bits reported for each byte which + is *not* 0 */ + jnc 3f /* highest byte is NUL => return pointer */ + xorq %rax, %r9 /* (word+magic)^word */ + orq %r8, %r9 /* set all non-carry bits */ + incq %r9 /* add 1: if one carry bit was *not* set + the addition will not result in 0. */ + + jnz 3f /* found NUL => return pointer */ + + movq %rax, (%rdx) /* Write value to destination. */ + addq $8, %rdx /* Adjust pointer. */ + + /* 2nd unroll. */ + movq (%rsi), %rax /* Read double word (8 bytes). */ + addq $8, %rsi /* Adjust pointer for next word. */ + movq %rax, %r9 /* Save a copy for NUL finding. */ + addq %r8, %r9 /* add the magic value to the word. We get + carry bits reported for each byte which + is *not* 0 */ + jnc 3f /* highest byte is NUL => return pointer */ + xorq %rax, %r9 /* (word+magic)^word */ + orq %r8, %r9 /* set all non-carry bits */ + incq %r9 /* add 1: if one carry bit was *not* set + the addition will not result in 0. */ + + jnz 3f /* found NUL => return pointer */ + + movq %rax, (%rdx) /* Write value to destination. */ + addq $8, %rdx /* Adjust pointer. */ + + /* 3rd unroll. */ + movq (%rsi), %rax /* Read double word (8 bytes). */ + addq $8, %rsi /* Adjust pointer for next word. */ + movq %rax, %r9 /* Save a copy for NUL finding. */ + addq %r8, %r9 /* add the magic value to the word. We get + carry bits reported for each byte which + is *not* 0 */ + jnc 3f /* highest byte is NUL => return pointer */ + xorq %rax, %r9 /* (word+magic)^word */ + orq %r8, %r9 /* set all non-carry bits */ + incq %r9 /* add 1: if one carry bit was *not* set + the addition will not result in 0. */ + + jnz 3f /* found NUL => return pointer */ + + movq %rax, (%rdx) /* Write value to destination. */ + addq $8, %rdx /* Adjust pointer. */ + + /* 4th unroll. */ + movq (%rsi), %rax /* Read double word (8 bytes). */ + addq $8, %rsi /* Adjust pointer for next word. */ + movq %rax, %r9 /* Save a copy for NUL finding. */ + addq %r8, %r9 /* add the magic value to the word. We get + carry bits reported for each byte which + is *not* 0 */ + jnc 3f /* highest byte is NUL => return pointer */ + xorq %rax, %r9 /* (word+magic)^word */ + orq %r8, %r9 /* set all non-carry bits */ + incq %r9 /* add 1: if one carry bit was *not* set + the addition will not result in 0. */ + + jnz 3f /* found NUL => return pointer */ + + movq %rax, (%rdx) /* Write value to destination. */ + addq $8, %rdx /* Adjust pointer. */ + jmp 1b /* Next iteration. */ + + /* Do the last few bytes. %rax contains the value to write. + The loop is unrolled twice. */ + + /* Next 3 insns are 6 bytes total, make sure we decode them in one go */ + .p2align 3,,6 +3: + /* Note that stpcpy needs to return with the value of the NUL + byte. */ + movb %al, (%rdx) /* 1st byte. */ + testb %al, %al /* Is it NUL. */ + jz 4f /* yes, finish. */ + incq %rdx /* Increment destination. */ + movb %ah, (%rdx) /* 2nd byte. */ + testb %ah, %ah /* Is it NUL?. */ + jz 4f /* yes, finish. */ + incq %rdx /* Increment destination. */ + shrq $16, %rax /* Shift... */ + jmp 3b /* and look at next two bytes in %rax. */ + +4: +#ifdef USE_AS_STPCPY + movq %rdx, %rax /* Destination is return value. */ +#else + movq %rdi, %rax /* Source is return value. */ +#endif + retq +END (BP_SYM (STRCPY)) +#ifndef USE_AS_STPCPY +libc_hidden_def(strcpy) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/x86_64/strcspn.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/x86_64/strcspn.S new file mode 100644 index 00000000..fd9b09c4 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/x86_64/strcspn.S @@ -0,0 +1,137 @@ +/* strcspn (str, ss) -- Return the length of the initial segment of STR + which contains no characters from SS. + For AMD x86-64. + Copyright (C) 1994-1997, 2000, 2002, 2003, 2004, 2005 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper . + Bug fixes by Alan Modra . + Adopted for x86-64 by Andreas Jaeger . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "_glibc_inc.h" + +/* Seems to be unrolled too much */ + +/* BEWARE: `#ifdef strcspn' means that strcspn is redefined as `strpbrk' */ +#define STRPBRK_P (defined strcspn) + + .text +ENTRY (strcspn) + + movq %rdi, %rdx /* Save SRC. */ + + /* First we create a table with flags for all possible characters. + For the ASCII (7bit/8bit) or ISO-8859-X character sets which are + supported by the C string functions we have 256 characters. + Before inserting marks for the stop characters we clear the whole + table. */ + movq %rdi, %r8 /* Save value. */ + subq $256, %rsp /* Make space for 256 bytes. */ + movl $32, %ecx /* 32*8 bytes = 256 bytes. */ + movq %rsp, %rdi + xorl %eax, %eax /* We store 0s. */ + cld + rep + stosq + + movq %rsi, %rax /* Setup skipset. */ + +/* For understanding the following code remember that %rcx == 0 now. + Although all the following instruction only modify %cl we always + have a correct zero-extended 64-bit value in %rcx. */ + + /* Next 3 insns are 6 bytes total, make sure we decode them in one go */ + .p2align 3,,6 + +L(2): movb (%rax), %cl /* get byte from skipset */ + testb %cl, %cl /* is NUL char? */ + jz L(1) /* yes => start compare loop */ + movb %cl, (%rsp,%rcx) /* set corresponding byte in skipset table */ + + movb 1(%rax), %cl /* get byte from skipset */ + testb %cl, %cl /* is NUL char? */ + jz L(1) /* yes => start compare loop */ + movb %cl, (%rsp,%rcx) /* set corresponding byte in skipset table */ + + movb 2(%rax), %cl /* get byte from skipset */ + testb %cl, %cl /* is NUL char? */ + jz L(1) /* yes => start compare loop */ + movb %cl, (%rsp,%rcx) /* set corresponding byte in skipset table */ + + movb 3(%rax), %cl /* get byte from skipset */ + addq $4, %rax /* increment skipset pointer */ + movb %cl, (%rsp,%rcx) /* set corresponding byte in skipset table */ + testb %cl, %cl /* is NUL char? */ + jnz L(2) /* no => process next dword from skipset */ + +L(1): leaq -4(%rdx), %rax /* prepare loop */ + + /* We use a neat trick for the following loop. Normally we would + have to test for two termination conditions + 1. a character in the skipset was found + and + 2. the end of the string was found + But as a sign that the character is in the skipset we store its + value in the table. But the value of NUL is NUL so the loop + terminates for NUL in every case. */ + + /* Next 3 insns are 9 bytes total. */ + /* .p2align 4,,9 would make sure we decode them in one go, */ + /* but it will also align entire function to 16 bytes, */ + /* potentially creating largish padding at link time. */ + /* We are aligning to 8 bytes instead: */ + .p2align 3,,8 + +L(3): addq $4, %rax /* adjust pointer for full loop round */ + + movb (%rax), %cl /* get byte from string */ + cmpb %cl, (%rsp,%rcx) /* is it contained in skipset? */ + je L(4) /* yes => return */ + + movb 1(%rax), %cl /* get byte from string */ + cmpb %cl, (%rsp,%rcx) /* is it contained in skipset? */ + je L(5) /* yes => return */ + + movb 2(%rax), %cl /* get byte from string */ + cmpb %cl, (%rsp,%rcx) /* is it contained in skipset? */ + jz L(6) /* yes => return */ + + movb 3(%rax), %cl /* get byte from string */ + cmpb %cl, (%rsp,%rcx) /* is it contained in skipset? */ + jne L(3) /* no => start loop again */ + + incq %rax /* adjust pointer */ +L(6): incq %rax +L(5): incq %rax + +L(4): addq $256, %rsp /* remove skipset */ +#if STRPBRK_P + xorl %edx,%edx + orb %cl, %cl /* was last character NUL? */ + cmovzq %rdx, %rax /* Yes: return NULL */ +#else + subq %rdx, %rax /* we have to return the number of valid + characters, so compute distance to first + non-valid character */ +#endif + ret +END (strcspn) + +#if !STRPBRK_P +libc_hidden_def(strcspn) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/x86_64/strlen.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/x86_64/strlen.S new file mode 100644 index 00000000..4213f0ab --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/x86_64/strlen.S @@ -0,0 +1,144 @@ +/* strlen(str) -- determine the length of the string STR. + Copyright (C) 2002, 2003 Free Software Foundation, Inc. + Based on i486 version contributed by Ulrich Drepper . + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "_glibc_inc.h" + +/* Seems to be unrolled too much */ + + .text +ENTRY (strlen) + movq %rdi, %rcx /* Duplicate source pointer. */ + andl $7, %ecx /* mask alignment bits */ + movq %rdi, %rax /* duplicate destination. */ + jz 1f /* aligned => start loop */ + + neg %ecx /* We need to align to 8 bytes. */ + addl $8,%ecx + /* Search the first bytes directly. */ +0: cmpb $0x0,(%rax) /* is byte NUL? */ + je 2f /* yes => return */ + incq %rax /* increment pointer */ + decl %ecx + jnz 0b + +1: movq $0xfefefefefefefeff,%r8 /* Save magic. */ + + /* Align loop. */ + /* Next 3 insns are 10 bytes total, make sure we decode them in one go */ + .p2align 4,,10 +4: + /* Main Loop is unrolled 4 times. */ + /* First unroll. */ + movq (%rax), %rcx /* get double word (= 8 bytes) in question */ + addq $8,%rax /* adjust pointer for next word */ + movq %r8, %rdx /* magic value */ + addq %rcx, %rdx /* add the magic value to the word. We get + carry bits reported for each byte which + is *not* 0 */ + jnc 3f /* highest byte is NUL => return pointer */ + xorq %rcx, %rdx /* (word+magic)^word */ + orq %r8, %rdx /* set all non-carry bits */ + incq %rdx /* add 1: if one carry bit was *not* set + the addition will not result in 0. */ + jnz 3f /* found NUL => return pointer */ + + /* Second unroll. */ + movq (%rax), %rcx /* get double word (= 8 bytes) in question */ + addq $8,%rax /* adjust pointer for next word */ + movq %r8, %rdx /* magic value */ + addq %rcx, %rdx /* add the magic value to the word. We get + carry bits reported for each byte which + is *not* 0 */ + jnc 3f /* highest byte is NUL => return pointer */ + xorq %rcx, %rdx /* (word+magic)^word */ + orq %r8, %rdx /* set all non-carry bits */ + incq %rdx /* add 1: if one carry bit was *not* set + the addition will not result in 0. */ + jnz 3f /* found NUL => return pointer */ + + /* Third unroll. */ + movq (%rax), %rcx /* get double word (= 8 bytes) in question */ + addq $8,%rax /* adjust pointer for next word */ + movq %r8, %rdx /* magic value */ + addq %rcx, %rdx /* add the magic value to the word. We get + carry bits reported for each byte which + is *not* 0 */ + jnc 3f /* highest byte is NUL => return pointer */ + xorq %rcx, %rdx /* (word+magic)^word */ + orq %r8, %rdx /* set all non-carry bits */ + incq %rdx /* add 1: if one carry bit was *not* set + the addition will not result in 0. */ + jnz 3f /* found NUL => return pointer */ + + /* Fourth unroll. */ + movq (%rax), %rcx /* get double word (= 8 bytes) in question */ + addq $8,%rax /* adjust pointer for next word */ + movq %r8, %rdx /* magic value */ + addq %rcx, %rdx /* add the magic value to the word. We get + carry bits reported for each byte which + is *not* 0 */ + jnc 3f /* highest byte is NUL => return pointer */ + xorq %rcx, %rdx /* (word+magic)^word */ + orq %r8, %rdx /* set all non-carry bits */ + incq %rdx /* add 1: if one carry bit was *not* set + the addition will not result in 0. */ + jz 4b /* no NUL found => continue loop */ + + /* Align, it is a jump target. */ + /* Next 3 insns are 8 bytes total, make sure we decode them in one go */ + .p2align 3,,8 +3: + subq $8,%rax /* correct pointer increment. */ + + testb %cl, %cl /* is first byte NUL? */ + jz 2f /* yes => return */ + incq %rax /* increment pointer */ + + testb %ch, %ch /* is second byte NUL? */ + jz 2f /* yes => return */ + incq %rax /* increment pointer */ + + testl $0x00ff0000, %ecx /* is third byte NUL? */ + jz 2f /* yes => return pointer */ + incq %rax /* increment pointer */ + + testl $0xff000000, %ecx /* is fourth byte NUL? */ + jz 2f /* yes => return pointer */ + incq %rax /* increment pointer */ + + shrq $32, %rcx /* look at other half. */ + + testb %cl, %cl /* is first byte NUL? */ + jz 2f /* yes => return */ + incq %rax /* increment pointer */ + + testb %ch, %ch /* is second byte NUL? */ + jz 2f /* yes => return */ + incq %rax /* increment pointer */ + + testl $0xff0000, %ecx /* is third byte NUL? */ + jz 2f /* yes => return pointer */ + incq %rax /* increment pointer */ +2: + subq %rdi, %rax /* compute difference to string start */ + ret +END (strlen) + +libc_hidden_def(strlen) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/x86_64/strpbrk.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/x86_64/strpbrk.S new file mode 100644 index 00000000..db6cc24c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/x86_64/strpbrk.S @@ -0,0 +1,3 @@ +#define strcspn strpbrk +#include "strcspn.S" +libc_hidden_def(strpbrk) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/x86_64/strspn.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/x86_64/strspn.S new file mode 100644 index 00000000..41cff049 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/x86_64/strspn.S @@ -0,0 +1,124 @@ +/* strspn (str, ss) -- Return the length of the initial segment of STR + which contains only characters from SS. + For AMD x86-64. + Copyright (C) 1994-1997, 2000, 2002, 2003, 2004, 2005 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper . + Bug fixes by Alan Modra . + Adopted for x86-64 by Andreas Jaeger . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "_glibc_inc.h" + + .text +ENTRY (strspn) + + movq %rdi, %rdx /* Save SRC. */ + + /* First we create a table with flags for all possible characters. + For the ASCII (7bit/8bit) or ISO-8859-X character sets which are + supported by the C string functions we have 256 characters. + Before inserting marks for the stop characters we clear the whole + table. */ + movq %rdi, %r8 /* Save value. */ + subq $256, %rsp /* Make space for 256 bytes. */ + movl $32, %ecx /* 32*8 bytes = 256 bytes. */ + movq %rsp, %rdi + xorl %eax, %eax /* We store 0s. */ + cld + rep + stosq + + movq %rsi, %rax /* Setup stopset. */ + +/* For understanding the following code remember that %rcx == 0 now. + Although all the following instruction only modify %cl we always + have a correct zero-extended 64-bit value in %rcx. */ + + /* Next 3 insns are 6 bytes total, make sure we decode them in one go */ + .p2align 3,,6 +L(2): + movb (%rax), %cl /* get byte from stopset */ + testb %cl, %cl /* is NUL char? */ + jz L(1) /* yes => start compare loop */ + movb %cl, (%rsp,%rcx) /* set corresponding byte in stopset table */ + + movb 1(%rax), %cl /* get byte from stopset */ + testb %cl, %cl /* is NUL char? */ + jz L(1) /* yes => start compare loop */ + movb %cl, (%rsp,%rcx) /* set corresponding byte in stopset table */ + + movb 2(%rax), %cl /* get byte from stopset */ + testb %cl, %cl /* is NUL char? */ + jz L(1) /* yes => start compare loop */ + movb %cl, (%rsp,%rcx) /* set corresponding byte in stopset table */ + + movb 3(%rax), %cl /* get byte from stopset */ + addq $4, %rax /* increment stopset pointer */ + movb %cl, (%rsp,%rcx) /* set corresponding byte in stopset table */ + testb %cl, %cl /* is NUL char? */ + jnz L(2) /* no => process next dword from stopset */ + +L(1): leaq -4(%rdx), %rax /* prepare loop */ + + /* We use a neat trick for the following loop. Normally we would + have to test for two termination conditions + 1. a character in the stopset was found + and + 2. the end of the string was found + But as a sign that the character is in the stopset we store its + value in the table. But the value of NUL is NUL so the loop + terminates for NUL in every case. */ + + /* Next 3 insns are 9 bytes total. */ + /* .p2align 4,,9 would make sure we decode them in one go, */ + /* but it will also align entire function to 16 bytes, */ + /* potentially creating largish padding at link time. */ + /* We are aligning to 8 bytes instead: */ + .p2align 3,,8 +L(3): + addq $4, %rax /* adjust pointer for full loop round */ + + movb (%rax), %cl /* get byte from string */ + testb %cl, (%rsp,%rcx) /* is it contained in skipset? */ + jz L(4) /* no => return */ + + movb 1(%rax), %cl /* get byte from string */ + testb %cl, (%rsp,%rcx) /* is it contained in skipset? */ + jz L(5) /* no => return */ + + movb 2(%rax), %cl /* get byte from string */ + testb %cl, (%rsp,%rcx) /* is it contained in skipset? */ + jz L(6) /* no => return */ + + movb 3(%rax), %cl /* get byte from string */ + testb %cl, (%rsp,%rcx) /* is it contained in skipset? */ + jnz L(3) /* yes => start loop again */ + + incq %rax /* adjust pointer */ +L(6): incq %rax +L(5): incq %rax + +L(4): addq $256, %rsp /* remove stopset */ + subq %rdx, %rax /* we have to return the number of valid + characters, so compute distance to first + non-valid character */ + ret +END (strspn) + +libc_hidden_def(strspn) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/xtensa/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/xtensa/Makefile new file mode 100644 index 00000000..0a95346f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/xtensa/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir:=../../../ +top_builddir:=../../../ +all: objs +include $(top_builddir)Rules.mak +include ../Makefile.in +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/xtensa/memcpy.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/xtensa/memcpy.S new file mode 100644 index 00000000..fc04c023 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/xtensa/memcpy.S @@ -0,0 +1,297 @@ +/* Optimized memcpy for Xtensa. + Copyright (C) 2001, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street - Fifth Floor, + Boston, MA 02110-1301, USA. */ + +#include "../../sysdeps/linux/xtensa/sysdep.h" +#include + + .macro src_b r, w0, w1 +#ifdef __XTENSA_EB__ + src \r, \w0, \w1 +#else + src \r, \w1, \w0 +#endif + .endm + + .macro ssa8 r +#ifdef __XTENSA_EB__ + ssa8b \r +#else + ssa8l \r +#endif + .endm + +/* If the Xtensa Unaligned Load Exception option is not used, this + code can run a few cycles faster by relying on the low address bits + being ignored. However, if the code is then run with an Xtensa ISS + client that checks for unaligned accesses, it will produce a lot of + warning messages. Set this flag to disable the use of unaligned + accesses and keep the ISS happy. */ + +#define UNALIGNED_ADDRESSES_CHECKED 1 + +/* Do not use .literal_position in the ENTRY macro. */ +#undef LITERAL_POSITION +#define LITERAL_POSITION + + +/* void *memcpy (void *dst, const void *src, size_t len) + + The algorithm is as follows: + + If the destination is unaligned, align it by conditionally + copying 1- and/or 2-byte pieces. + + If the source is aligned, copy 16 bytes with a loop, and then finish up + with 8, 4, 2, and 1-byte copies conditional on the length. + + Else (if source is unaligned), do the same, but use SRC to align the + source data. + + This code tries to use fall-through branches for the common + case of aligned source and destination and multiple of 4 (or 8) length. */ + + +/* Byte by byte copy. */ + + .text + .align 4 + .literal_position +__memcpy_aux: + + /* Skip a byte to get 1 mod 4 alignment for LOOPNEZ + (0 mod 4 alignment for LBEG). */ + .byte 0 + +.Lbytecopy: +#if XCHAL_HAVE_LOOPS + loopnez a4, 2f +#else + beqz a4, 2f + add a7, a3, a4 /* a7 = end address for source */ +#endif +1: l8ui a6, a3, 0 + addi a3, a3, 1 + s8i a6, a5, 0 + addi a5, a5, 1 +#if !XCHAL_HAVE_LOOPS + blt a3, a7, 1b +#endif +2: retw + + +/* Destination is unaligned. */ + + .align 4 +.Ldst1mod2: /* dst is only byte aligned */ + + /* Do short copies byte-by-byte. */ + _bltui a4, 7, .Lbytecopy + + /* Copy 1 byte. */ + l8ui a6, a3, 0 + addi a3, a3, 1 + addi a4, a4, -1 + s8i a6, a5, 0 + addi a5, a5, 1 + + /* Return to main algorithm if dst is now aligned. */ + _bbci.l a5, 1, .Ldstaligned + +.Ldst2mod4: /* dst has 16-bit alignment */ + + /* Do short copies byte-by-byte. */ + _bltui a4, 6, .Lbytecopy + + /* Copy 2 bytes. */ + l8ui a6, a3, 0 + l8ui a7, a3, 1 + addi a3, a3, 2 + addi a4, a4, -2 + s8i a6, a5, 0 + s8i a7, a5, 1 + addi a5, a5, 2 + + /* dst is now aligned; return to main algorithm. */ + j .Ldstaligned + + +ENTRY (memcpy) + /* a2 = dst, a3 = src, a4 = len */ + + mov a5, a2 /* copy dst so that a2 is return value */ + _bbsi.l a2, 0, .Ldst1mod2 + _bbsi.l a2, 1, .Ldst2mod4 +.Ldstaligned: + + /* Get number of loop iterations with 16B per iteration. */ + srli a7, a4, 4 + + /* Check if source is aligned. */ + movi a8, 3 + _bany a3, a8, .Lsrcunaligned + + /* Destination and source are word-aligned, use word copy. */ +#if XCHAL_HAVE_LOOPS + loopnez a7, 2f +#else + beqz a7, 2f + slli a8, a7, 4 + add a8, a8, a3 /* a8 = end of last 16B source chunk */ +#endif +1: l32i a6, a3, 0 + l32i a7, a3, 4 + s32i a6, a5, 0 + l32i a6, a3, 8 + s32i a7, a5, 4 + l32i a7, a3, 12 + s32i a6, a5, 8 + addi a3, a3, 16 + s32i a7, a5, 12 + addi a5, a5, 16 +#if !XCHAL_HAVE_LOOPS + blt a3, a8, 1b +#endif + + /* Copy any leftover pieces smaller than 16B. */ +2: bbci.l a4, 3, 3f + + /* Copy 8 bytes. */ + l32i a6, a3, 0 + l32i a7, a3, 4 + addi a3, a3, 8 + s32i a6, a5, 0 + s32i a7, a5, 4 + addi a5, a5, 8 + +3: bbsi.l a4, 2, 4f + bbsi.l a4, 1, 5f + bbsi.l a4, 0, 6f + retw + + /* Copy 4 bytes. */ +4: l32i a6, a3, 0 + addi a3, a3, 4 + s32i a6, a5, 0 + addi a5, a5, 4 + bbsi.l a4, 1, 5f + bbsi.l a4, 0, 6f + retw + + /* Copy 2 bytes. */ +5: l16ui a6, a3, 0 + addi a3, a3, 2 + s16i a6, a5, 0 + addi a5, a5, 2 + bbsi.l a4, 0, 6f + retw + + /* Copy 1 byte. */ +6: l8ui a6, a3, 0 + s8i a6, a5, 0 + +.Ldone: + retw + + +/* Destination is aligned; source is unaligned. */ + + .align 4 +.Lsrcunaligned: + /* Avoid loading anything for zero-length copies. */ + _beqz a4, .Ldone + + /* Copy 16 bytes per iteration for word-aligned dst and + unaligned src. */ + ssa8 a3 /* set shift amount from byte offset */ +#if UNALIGNED_ADDRESSES_CHECKED + and a11, a3, a8 /* save unalignment offset for below */ + sub a3, a3, a11 /* align a3 */ +#endif + l32i a6, a3, 0 /* load first word */ +#if XCHAL_HAVE_LOOPS + loopnez a7, 2f +#else + beqz a7, 2f + slli a10, a7, 4 + add a10, a10, a3 /* a10 = end of last 16B source chunk */ +#endif +1: l32i a7, a3, 4 + l32i a8, a3, 8 + src_b a6, a6, a7 + s32i a6, a5, 0 + l32i a9, a3, 12 + src_b a7, a7, a8 + s32i a7, a5, 4 + l32i a6, a3, 16 + src_b a8, a8, a9 + s32i a8, a5, 8 + addi a3, a3, 16 + src_b a9, a9, a6 + s32i a9, a5, 12 + addi a5, a5, 16 +#if !XCHAL_HAVE_LOOPS + blt a3, a10, 1b +#endif + +2: bbci.l a4, 3, 3f + + /* Copy 8 bytes. */ + l32i a7, a3, 4 + l32i a8, a3, 8 + src_b a6, a6, a7 + s32i a6, a5, 0 + addi a3, a3, 8 + src_b a7, a7, a8 + s32i a7, a5, 4 + addi a5, a5, 8 + mov a6, a8 + +3: bbci.l a4, 2, 4f + + /* Copy 4 bytes. */ + l32i a7, a3, 4 + addi a3, a3, 4 + src_b a6, a6, a7 + s32i a6, a5, 0 + addi a5, a5, 4 + mov a6, a7 +4: +#if UNALIGNED_ADDRESSES_CHECKED + add a3, a3, a11 /* readjust a3 with correct misalignment */ +#endif + bbsi.l a4, 1, 5f + bbsi.l a4, 0, 6f + retw + + /* Copy 2 bytes. */ +5: l8ui a6, a3, 0 + l8ui a7, a3, 1 + addi a3, a3, 2 + s8i a6, a5, 0 + s8i a7, a5, 1 + addi a5, a5, 2 + bbsi.l a4, 0, 6f + retw + + /* Copy 1 byte. */ +6: l8ui a6, a3, 0 + s8i a6, a5, 0 + retw + +libc_hidden_def (memcpy) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/xtensa/memset.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/xtensa/memset.S new file mode 100644 index 00000000..076b8f00 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/xtensa/memset.S @@ -0,0 +1,165 @@ +/* Optimized memset for Xtensa. + Copyright (C) 2001, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street - Fifth Floor, + Boston, MA 02110-1301, USA. */ + +#include "../../sysdeps/linux/xtensa/sysdep.h" +#include + +/* Do not use .literal_position in the ENTRY macro. */ +#undef LITERAL_POSITION +#define LITERAL_POSITION + +/* void *memset (void *dst, int c, size_t length) + + The algorithm is as follows: + + Create a word with c in all byte positions. + + If the destination is aligned, set 16B chunks with a loop, and then + finish up with 8B, 4B, 2B, and 1B stores conditional on the length. + + If the destination is unaligned, align it by conditionally + setting 1B and/or 2B and then go to aligned case. + + This code tries to use fall-through branches for the common + case of an aligned destination (except for the branches to + the alignment labels). */ + + +/* Byte-by-byte set. */ + + .text + .align 4 + .literal_position +__memset_aux: + + /* Skip a byte to get 1 mod 4 alignment for LOOPNEZ + (0 mod 4 alignment for LBEG). */ + .byte 0 + +.Lbyteset: +#if XCHAL_HAVE_LOOPS + loopnez a4, 2f +#else + beqz a4, 2f + add a6, a5, a4 /* a6 = ending address */ +#endif +1: s8i a3, a5, 0 + addi a5, a5, 1 +#if !XCHAL_HAVE_LOOPS + blt a5, a6, 1b +#endif +2: retw + + +/* Destination is unaligned. */ + + .align 4 + +.Ldst1mod2: /* dst is only byte aligned */ + + /* Do short sizes byte-by-byte. */ + bltui a4, 8, .Lbyteset + + /* Set 1 byte. */ + s8i a3, a5, 0 + addi a5, a5, 1 + addi a4, a4, -1 + + /* Now retest if dst is aligned. */ + _bbci.l a5, 1, .Ldstaligned + +.Ldst2mod4: /* dst has 16-bit alignment */ + + /* Do short sizes byte-by-byte. */ + bltui a4, 8, .Lbyteset + + /* Set 2 bytes. */ + s16i a3, a5, 0 + addi a5, a5, 2 + addi a4, a4, -2 + + /* dst is now aligned; return to main algorithm */ + j .Ldstaligned + + +ENTRY (memset) + /* a2 = dst, a3 = c, a4 = length */ + + /* Duplicate character into all bytes of word. */ + extui a3, a3, 0, 8 + slli a7, a3, 8 + or a3, a3, a7 + slli a7, a3, 16 + or a3, a3, a7 + + mov a5, a2 /* copy dst so that a2 is return value */ + + /* Check if dst is unaligned. */ + _bbsi.l a2, 0, .Ldst1mod2 + _bbsi.l a2, 1, .Ldst2mod4 +.Ldstaligned: + + /* Get number of loop iterations with 16B per iteration. */ + srli a7, a4, 4 + + /* Destination is word-aligned. */ +#if XCHAL_HAVE_LOOPS + loopnez a7, 2f +#else + beqz a7, 2f + slli a6, a7, 4 + add a6, a6, a5 /* a6 = end of last 16B chunk */ +#endif + /* Set 16 bytes per iteration. */ +1: s32i a3, a5, 0 + s32i a3, a5, 4 + s32i a3, a5, 8 + s32i a3, a5, 12 + addi a5, a5, 16 +#if !XCHAL_HAVE_LOOPS + blt a5, a6, 1b +#endif + + /* Set any leftover pieces smaller than 16B. */ +2: bbci.l a4, 3, 3f + + /* Set 8 bytes. */ + s32i a3, a5, 0 + s32i a3, a5, 4 + addi a5, a5, 8 + +3: bbci.l a4, 2, 4f + + /* Set 4 bytes. */ + s32i a3, a5, 0 + addi a5, a5, 4 + +4: bbci.l a4, 1, 5f + + /* Set 2 bytes. */ + s16i a3, a5, 0 + addi a5, a5, 2 + +5: bbci.l a4, 0, 6f + + /* Set 1 byte. */ + s8i a3, a5, 0 +6: retw + +libc_hidden_def (memset) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/xtensa/strcmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/xtensa/strcmp.S new file mode 100644 index 00000000..ac058a2b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/xtensa/strcmp.S @@ -0,0 +1,314 @@ +/* Optimized strcmp for Xtensa. + Copyright (C) 2001, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street - Fifth Floor, + Boston, MA 02110-1301, USA. */ + +#include "../../sysdeps/linux/xtensa/sysdep.h" +#include +#include + +#ifdef __XTENSA_EB__ +#define MASK0 0xff000000 +#define MASK1 0x00ff0000 +#define MASK2 0x0000ff00 +#define MASK3 0x000000ff +#else +#define MASK0 0x000000ff +#define MASK1 0x0000ff00 +#define MASK2 0x00ff0000 +#define MASK3 0xff000000 +#endif + +#define MASK4 0x40404040 + + .literal .Lmask0, MASK0 + .literal .Lmask1, MASK1 + .literal .Lmask2, MASK2 + .literal .Lmask3, MASK3 + .literal .Lmask4, MASK4 + + .text +ENTRY (strcmp) + /* a2 = s1, a3 = s2 */ + + l8ui a8, a2, 0 /* byte 0 from s1 */ + l8ui a9, a3, 0 /* byte 0 from s2 */ + movi a10, 3 /* mask */ + bne a8, a9, .Lretdiff + + or a11, a2, a3 + bnone a11, a10, .Laligned + + xor a11, a2, a3 /* compare low two bits of s1 and s2 */ + bany a11, a10, .Lunaligned /* if they have different alignment */ + + /* s1/s2 are not word-aligned. */ + addi a2, a2, 1 /* advance s1 */ + beqz a8, .Leq /* bytes equal, if zero, strings are equal */ + addi a3, a3, 1 /* advance s2 */ + bnone a2, a10, .Laligned /* if s1/s2 now aligned */ + l8ui a8, a2, 0 /* byte 1 from s1 */ + l8ui a9, a3, 0 /* byte 1 from s2 */ + addi a2, a2, 1 /* advance s1 */ + bne a8, a9, .Lretdiff /* if different, return difference */ + beqz a8, .Leq /* bytes equal, if zero, strings are equal */ + addi a3, a3, 1 /* advance s2 */ + bnone a2, a10, .Laligned /* if s1/s2 now aligned */ + l8ui a8, a2, 0 /* byte 2 from s1 */ + l8ui a9, a3, 0 /* byte 2 from s2 */ + addi a2, a2, 1 /* advance s1 */ + bne a8, a9, .Lretdiff /* if different, return difference */ + beqz a8, .Leq /* bytes equal, if zero, strings are equal */ + addi a3, a3, 1 /* advance s2 */ + j .Laligned + +/* s1 and s2 have different alignment. + + If the zero-overhead loop option is available, use an (almost) + infinite zero-overhead loop with conditional exits so we only pay + for taken branches when exiting the loop. + + Note: It is important for this unaligned case to come before the + code for aligned strings, because otherwise some of the branches + above cannot reach and have to be transformed to branches around + jumps. The unaligned code is smaller and the branches can reach + over it. */ + + .align 4 + /* (2 mod 4) alignment for loop instruction */ +.Lunaligned: +#if XCHAL_HAVE_LOOPS + _movi.n a8, 0 /* set up for the maximum loop count */ + loop a8, .Lretdiff /* loop forever (almost anyway) */ +#endif +.Lnextbyte: + l8ui a8, a2, 0 + l8ui a9, a3, 0 + addi a2, a2, 1 + bne a8, a9, .Lretdiff + addi a3, a3, 1 +#if XCHAL_HAVE_LOOPS + beqz a8, .Lretdiff +#else + bnez a8, .Lnextbyte +#endif +.Lretdiff: + sub a2, a8, a9 + retw + +/* s1 is word-aligned; s2 is word-aligned. + + If the zero-overhead loop option is available, use an (almost) + infinite zero-overhead loop with conditional exits so we only pay + for taken branches when exiting the loop. */ + +/* New algorithm, relying on the fact that all normal ASCII is between + 32 and 127. + + Rather than check all bytes for zero: + Take one word (4 bytes). Call it w1. + Shift w1 left by one into w1'. + Or w1 and w1'. For all normal ASCII bit 6 will be 1; for zero it won't. + Check that all 4 bit 6's (one for each byte) are one: + If they are, we are definitely not done. + If they are not, we are probably done, but need to check for zero. */ + + .align 4 +#if XCHAL_HAVE_LOOPS +.Laligned: + .begin no-transform + l32r a4, .Lmask0 /* mask for byte 0 */ + l32r a7, .Lmask4 + /* Loop forever. (a4 is more than than the maximum number + of iterations) */ + loop a4, .Laligned_done + + /* First unrolled loop body. */ + l32i a8, a2, 0 /* get word from s1 */ + l32i a9, a3, 0 /* get word from s2 */ + slli a5, a8, 1 + bne a8, a9, .Lwne2 + or a9, a8, a5 + bnall a9, a7, .Lprobeq + + /* Second unrolled loop body. */ + l32i a8, a2, 4 /* get word from s1+4 */ + l32i a9, a3, 4 /* get word from s2+4 */ + slli a5, a8, 1 + bne a8, a9, .Lwne2 + or a9, a8, a5 + bnall a9, a7, .Lprobeq2 + + addi a2, a2, 8 /* advance s1 pointer */ + addi a3, a3, 8 /* advance s2 pointer */ +.Laligned_done: + or a1, a1, a1 /* nop */ + +.Lprobeq2: + /* Adjust pointers to account for the loop unrolling. */ + addi a2, a2, 4 + addi a3, a3, 4 + +#else /* !XCHAL_HAVE_LOOPS */ + +.Laligned: + movi a4, MASK0 /* mask for byte 0 */ + movi a7, MASK4 + j .Lfirstword +.Lnextword: + addi a2, a2, 4 /* advance s1 pointer */ + addi a3, a3, 4 /* advance s2 pointer */ +.Lfirstword: + l32i a8, a2, 0 /* get word from s1 */ + l32i a9, a3, 0 /* get word from s2 */ + slli a5, a8, 1 + bne a8, a9, .Lwne2 + or a9, a8, a5 + ball a9, a7, .Lnextword +#endif /* !XCHAL_HAVE_LOOPS */ + + /* align (0 mod 4) */ +.Lprobeq: + /* Words are probably equal, but check for sure. + If not, loop over the rest of string using normal algorithm. */ + + bnone a8, a4, .Leq /* if byte 0 is zero */ + l32r a5, .Lmask1 /* mask for byte 1 */ + l32r a6, .Lmask2 /* mask for byte 2 */ + bnone a8, a5, .Leq /* if byte 1 is zero */ + l32r a7, .Lmask3 /* mask for byte 3 */ + bnone a8, a6, .Leq /* if byte 2 is zero */ + bnone a8, a7, .Leq /* if byte 3 is zero */ + addi.n a2, a2, 4 /* advance s1 pointer */ + addi.n a3, a3, 4 /* advance s2 pointer */ +#if XCHAL_HAVE_LOOPS + + /* align (1 mod 4) */ + loop a4, .Leq /* loop forever (a4 is bigger than max iters) */ + .end no-transform + + l32i a8, a2, 0 /* get word from s1 */ + l32i a9, a3, 0 /* get word from s2 */ + addi a2, a2, 4 /* advance s1 pointer */ + bne a8, a9, .Lwne + bnone a8, a4, .Leq /* if byte 0 is zero */ + bnone a8, a5, .Leq /* if byte 1 is zero */ + bnone a8, a6, .Leq /* if byte 2 is zero */ + bnone a8, a7, .Leq /* if byte 3 is zero */ + addi a3, a3, 4 /* advance s2 pointer */ + +#else /* !XCHAL_HAVE_LOOPS */ + + j .Lfirstword2 +.Lnextword2: + addi a3, a3, 4 /* advance s2 pointer */ +.Lfirstword2: + l32i a8, a2, 0 /* get word from s1 */ + l32i a9, a3, 0 /* get word from s2 */ + addi a2, a2, 4 /* advance s1 pointer */ + bne a8, a9, .Lwne + bnone a8, a4, .Leq /* if byte 0 is zero */ + bnone a8, a5, .Leq /* if byte 1 is zero */ + bnone a8, a6, .Leq /* if byte 2 is zero */ + bany a8, a7, .Lnextword2 /* if byte 3 is zero */ +#endif /* !XCHAL_HAVE_LOOPS */ + + /* Words are equal; some byte is zero. */ +.Leq: movi a2, 0 /* return equal */ + retw + +.Lwne2: /* Words are not equal. On big-endian processors, if none of the + bytes are zero, the return value can be determined by a simple + comparison. */ +#ifdef __XTENSA_EB__ + or a10, a8, a5 + bnall a10, a7, .Lsomezero + bgeu a8, a9, .Lposreturn + movi a2, -1 + retw +.Lposreturn: + movi a2, 1 + retw +.Lsomezero: /* There is probably some zero byte. */ +#endif /* __XTENSA_EB__ */ +.Lwne: /* Words are not equal. */ + xor a2, a8, a9 /* get word with nonzero in byte that differs */ + bany a2, a4, .Ldiff0 /* if byte 0 differs */ + movi a5, MASK1 /* mask for byte 1 */ + bnone a8, a4, .Leq /* if byte 0 is zero */ + bany a2, a5, .Ldiff1 /* if byte 1 differs */ + movi a6, MASK2 /* mask for byte 2 */ + bnone a8, a5, .Leq /* if byte 1 is zero */ + bany a2, a6, .Ldiff2 /* if byte 2 differs */ + bnone a8, a6, .Leq /* if byte 2 is zero */ +#ifdef __XTENSA_EB__ +.Ldiff3: +.Ldiff2: +.Ldiff1: + /* Byte 0 is equal (at least) and there is a difference before a zero + byte. Just subtract words to get the return value. + The high order equal bytes cancel, leaving room for the sign. */ + sub a2, a8, a9 + retw + +.Ldiff0: + /* Need to make room for the sign, so can't subtract whole words. */ + extui a10, a8, 24, 8 + extui a11, a9, 24, 8 + sub a2, a10, a11 + retw + +#else /* !__XTENSA_EB__ */ + /* Little-endian is a little more difficult because can't subtract + whole words. */ +.Ldiff3: + /* Bytes 0-2 are equal; byte 3 is different. + For little-endian need to have a sign bit for the difference. */ + extui a10, a8, 24, 8 + extui a11, a9, 24, 8 + sub a2, a10, a11 + retw + +.Ldiff0: + /* Byte 0 is different. */ + extui a10, a8, 0, 8 + extui a11, a9, 0, 8 + sub a2, a10, a11 + retw + +.Ldiff1: + /* Byte 0 is equal; byte 1 is different. */ + extui a10, a8, 8, 8 + extui a11, a9, 8, 8 + sub a2, a10, a11 + retw + +.Ldiff2: + /* Bytes 0-1 are equal; byte 2 is different. */ + extui a10, a8, 16, 8 + extui a11, a9, 16, 8 + sub a2, a10, a11 + retw + +#endif /* !__XTENSA_EB */ + +libc_hidden_def (strcmp) + +#ifndef __UCLIBC_HAS_LOCALE__ +strong_alias (strcmp, strcoll) +libc_hidden_def (strcoll) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/xtensa/strcpy.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/xtensa/strcpy.S new file mode 100644 index 00000000..dc0a1517 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/xtensa/strcpy.S @@ -0,0 +1,150 @@ +/* Optimized strcpy for Xtensa. + Copyright (C) 2001, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street - Fifth Floor, + Boston, MA 02110-1301, USA. */ + +#include "../../sysdeps/linux/xtensa/sysdep.h" +#include + +#ifdef __XTENSA_EB__ +#define MASK0 0xff000000 +#define MASK1 0x00ff0000 +#define MASK2 0x0000ff00 +#define MASK3 0x000000ff +#else +#define MASK0 0x000000ff +#define MASK1 0x0000ff00 +#define MASK2 0x00ff0000 +#define MASK3 0xff000000 +#endif + + .text +ENTRY (strcpy) + /* a2 = dst, a3 = src */ + + mov a10, a2 /* leave dst in return value register */ + movi a4, MASK0 + movi a5, MASK1 + movi a6, MASK2 + movi a7, MASK3 + bbsi.l a3, 0, .Lsrc1mod2 + bbsi.l a3, 1, .Lsrc2mod4 +.Lsrcaligned: + + /* Check if the destination is aligned. */ + movi a8, 3 + bnone a10, a8, .Laligned + + j .Ldstunaligned + +.Lsrc1mod2: /* src address is odd */ + l8ui a8, a3, 0 /* get byte 0 */ + addi a3, a3, 1 /* advance src pointer */ + s8i a8, a10, 0 /* store byte 0 */ + beqz a8, 1f /* if byte 0 is zero */ + addi a10, a10, 1 /* advance dst pointer */ + bbci.l a3, 1, .Lsrcaligned /* if src is now word-aligned */ + +.Lsrc2mod4: /* src address is 2 mod 4 */ + l8ui a8, a3, 0 /* get byte 0 */ + /* 1-cycle interlock */ + s8i a8, a10, 0 /* store byte 0 */ + beqz a8, 1f /* if byte 0 is zero */ + l8ui a8, a3, 1 /* get byte 0 */ + addi a3, a3, 2 /* advance src pointer */ + s8i a8, a10, 1 /* store byte 0 */ + addi a10, a10, 2 /* advance dst pointer */ + bnez a8, .Lsrcaligned +1: retw + + +/* dst is word-aligned; src is word-aligned. */ + + .align 4 +#if XCHAL_HAVE_LOOPS + /* (2 mod 4) alignment for loop instruction */ +.Laligned: + _movi.n a8, 0 /* set up for the maximum loop count */ + loop a8, .Lz3 /* loop forever (almost anyway) */ + l32i a8, a3, 0 /* get word from src */ + addi a3, a3, 4 /* advance src pointer */ + bnone a8, a4, .Lz0 /* if byte 0 is zero */ + bnone a8, a5, .Lz1 /* if byte 1 is zero */ + bnone a8, a6, .Lz2 /* if byte 2 is zero */ + s32i a8, a10, 0 /* store word to dst */ + bnone a8, a7, .Lz3 /* if byte 3 is zero */ + addi a10, a10, 4 /* advance dst pointer */ + +#else /* !XCHAL_HAVE_LOOPS */ + +1: addi a10, a10, 4 /* advance dst pointer */ +.Laligned: + l32i a8, a3, 0 /* get word from src */ + addi a3, a3, 4 /* advance src pointer */ + bnone a8, a4, .Lz0 /* if byte 0 is zero */ + bnone a8, a5, .Lz1 /* if byte 1 is zero */ + bnone a8, a6, .Lz2 /* if byte 2 is zero */ + s32i a8, a10, 0 /* store word to dst */ + bany a8, a7, 1b /* if byte 3 is zero */ +#endif /* !XCHAL_HAVE_LOOPS */ + +.Lz3: /* Byte 3 is zero. */ + retw + +.Lz0: /* Byte 0 is zero. */ +#ifdef __XTENSA_EB__ + movi a8, 0 +#endif + s8i a8, a10, 0 + retw + +.Lz1: /* Byte 1 is zero. */ +#ifdef __XTENSA_EB__ + extui a8, a8, 16, 16 +#endif + s16i a8, a10, 0 + retw + +.Lz2: /* Byte 2 is zero. */ +#ifdef __XTENSA_EB__ + extui a8, a8, 16, 16 +#endif + s16i a8, a10, 0 + movi a8, 0 + s8i a8, a10, 2 + retw + + .align 4 + /* (2 mod 4) alignment for loop instruction */ +.Ldstunaligned: + +#if XCHAL_HAVE_LOOPS + _movi.n a8, 0 /* set up for the maximum loop count */ + loop a8, 2f /* loop forever (almost anyway) */ +#endif +1: l8ui a8, a3, 0 + addi a3, a3, 1 + s8i a8, a10, 0 + addi a10, a10, 1 +#if XCHAL_HAVE_LOOPS + beqz a8, 2f +#else + bnez a8, 1b +#endif +2: retw + +libc_hidden_def (strcpy) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/xtensa/strlen.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/xtensa/strlen.S new file mode 100644 index 00000000..9ee4995f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/xtensa/strlen.S @@ -0,0 +1,104 @@ +/* Optimized strlen for Xtensa. + Copyright (C) 2001, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street - Fifth Floor, + Boston, MA 02110-1301, USA. */ + +#include "../../sysdeps/linux/xtensa/sysdep.h" +#include + +#ifdef __XTENSA_EB__ +#define MASK0 0xff000000 +#define MASK1 0x00ff0000 +#define MASK2 0x0000ff00 +#define MASK3 0x000000ff +#else +#define MASK0 0x000000ff +#define MASK1 0x0000ff00 +#define MASK2 0x00ff0000 +#define MASK3 0xff000000 +#endif + + .text +ENTRY (strlen) + /* a2 = s */ + + addi a3, a2, -4 /* because we overincrement at the end */ + movi a4, MASK0 + movi a5, MASK1 + movi a6, MASK2 + movi a7, MASK3 + bbsi.l a2, 0, .L1mod2 + bbsi.l a2, 1, .L2mod4 + j .Laligned + +.L1mod2: /* address is odd */ + l8ui a8, a3, 4 /* get byte 0 */ + addi a3, a3, 1 /* advance string pointer */ + beqz a8, .Lz3 /* if byte 0 is zero */ + bbci.l a3, 1, .Laligned /* if string pointer is now word-aligned */ + +.L2mod4: /* address is 2 mod 4 */ + addi a3, a3, 2 /* advance ptr for aligned access */ + l32i a8, a3, 0 /* get word with first two bytes of string */ + bnone a8, a6, .Lz2 /* if byte 2 (of word, not string) is zero */ + bany a8, a7, .Laligned /* if byte 3 (of word, not string) is nonzero */ + + /* Byte 3 is zero. */ + addi a3, a3, 3 /* point to zero byte */ + sub a2, a3, a2 /* subtract to get length */ + retw + + +/* String is word-aligned. */ + + .align 4 + /* (2 mod 4) alignment for loop instruction */ +.Laligned: +#if XCHAL_HAVE_LOOPS + _movi.n a8, 0 /* set up for the maximum loop count */ + loop a8, .Lz3 /* loop forever (almost anyway) */ +#endif +1: l32i a8, a3, 4 /* get next word of string */ + addi a3, a3, 4 /* advance string pointer */ + bnone a8, a4, .Lz0 /* if byte 0 is zero */ + bnone a8, a5, .Lz1 /* if byte 1 is zero */ + bnone a8, a6, .Lz2 /* if byte 2 is zero */ +#if XCHAL_HAVE_LOOPS + bnone a8, a7, .Lz3 /* if byte 3 is zero */ +#else + bany a8, a7, 1b /* repeat if byte 3 is non-zero */ +#endif + +.Lz3: /* Byte 3 is zero. */ + addi a3, a3, 3 /* point to zero byte */ + /* Fall through.... */ + +.Lz0: /* Byte 0 is zero. */ + sub a2, a3, a2 /* subtract to get length */ + retw + +.Lz1: /* Byte 1 is zero. */ + addi a3, a3, 1 /* point to zero byte */ + sub a2, a3, a2 /* subtract to get length */ + retw + +.Lz2: /* Byte 2 is zero. */ + addi a3, a3, 2 /* point to zero byte */ + sub a2, a3, a2 /* subtract to get length */ + retw + +libc_hidden_def (strlen) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/xtensa/strncpy.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/xtensa/strncpy.S new file mode 100644 index 00000000..fe3ec894 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/string/xtensa/strncpy.S @@ -0,0 +1,241 @@ +/* Optimized strcpy for Xtensa. + Copyright (C) 2001, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street - Fifth Floor, + Boston, MA 02110-1301, USA. */ + +#include "../../sysdeps/linux/xtensa/sysdep.h" +#include + +#ifdef __XTENSA_EB__ +#define MASK0 0xff000000 +#define MASK1 0x00ff0000 +#define MASK2 0x0000ff00 +#define MASK3 0x000000ff +#else +#define MASK0 0x000000ff +#define MASK1 0x0000ff00 +#define MASK2 0x00ff0000 +#define MASK3 0xff000000 +#endif + +/* Do not use .literal_position in the ENTRY macro. */ +#undef LITERAL_POSITION +#define LITERAL_POSITION + + .text + .align 4 + .literal_position +__strncpy_aux: + +.Lsrc1mod2: /* src address is odd */ + l8ui a8, a3, 0 /* get byte 0 */ + addi a3, a3, 1 /* advance src pointer */ + s8i a8, a10, 0 /* store byte 0 */ + addi a4, a4, -1 /* decrement n */ + beqz a4, .Lret /* if n is zero */ + addi a10, a10, 1 /* advance dst pointer */ + beqz a8, .Lfill /* if byte 0 is zero */ + bbci.l a3, 1, .Lsrcaligned /* if src is now word-aligned */ + +.Lsrc2mod4: /* src address is 2 mod 4 */ + l8ui a8, a3, 0 /* get byte 0 */ + addi a4, a4, -1 /* decrement n */ + s8i a8, a10, 0 /* store byte 0 */ + beqz a4, .Lret /* if n is zero */ + addi a10, a10, 1 /* advance dst pointer */ + beqz a8, .Lfill /* if byte 0 is zero */ + l8ui a8, a3, 1 /* get byte 0 */ + addi a3, a3, 2 /* advance src pointer */ + s8i a8, a10, 0 /* store byte 0 */ + addi a4, a4, -1 /* decrement n */ + beqz a4, .Lret /* if n is zero */ + addi a10, a10, 1 /* advance dst pointer */ + bnez a8, .Lsrcaligned + j .Lfill + +.Lret: + retw + + +ENTRY (strncpy) + /* a2 = dst, a3 = src */ + + mov a10, a2 /* leave dst in return value register */ + beqz a4, .Lret /* if n is zero */ + + movi a11, MASK0 + movi a5, MASK1 + movi a6, MASK2 + movi a7, MASK3 + bbsi.l a3, 0, .Lsrc1mod2 + bbsi.l a3, 1, .Lsrc2mod4 +.Lsrcaligned: + + /* Check if the destination is aligned. */ + movi a8, 3 + bnone a10, a8, .Laligned + + j .Ldstunaligned + + +/* Fill the dst with zeros -- n is at least 1. */ + +.Lfill: + movi a9, 0 + bbsi.l a10, 0, .Lfill1mod2 + bbsi.l a10, 1, .Lfill2mod4 +.Lfillaligned: + blti a4, 4, .Lfillcleanup + + /* Loop filling complete words with zero. */ +#if XCHAL_HAVE_LOOPS + + srai a8, a4, 2 + loop a8, 1f + s32i a9, a10, 0 + addi a10, a10, 4 + +1: slli a8, a8, 2 + sub a4, a4, a8 + +#else /* !XCHAL_HAVE_LOOPS */ + +1: s32i a9, a10, 0 + addi a10, a10, 4 + addi a4, a4, -4 + bgei a4, 4, 1b + +#endif /* !XCHAL_HAVE_LOOPS */ + + beqz a4, 2f + +.Lfillcleanup: + /* Fill leftover (1 to 3) bytes with zero. */ + s8i a9, a10, 0 /* store byte 0 */ + addi a4, a4, -1 /* decrement n */ + addi a10, a10, 1 + bnez a4, .Lfillcleanup + +2: retw + +.Lfill1mod2: /* dst address is odd */ + s8i a9, a10, 0 /* store byte 0 */ + addi a4, a4, -1 /* decrement n */ + beqz a4, 2b /* if n is zero */ + addi a10, a10, 1 /* advance dst pointer */ + bbci.l a10, 1, .Lfillaligned /* if dst is now word-aligned */ + +.Lfill2mod4: /* dst address is 2 mod 4 */ + s8i a9, a10, 0 /* store byte 0 */ + addi a4, a4, -1 /* decrement n */ + beqz a4, 2b /* if n is zero */ + s8i a9, a10, 1 /* store byte 1 */ + addi a4, a4, -1 /* decrement n */ + beqz a4, 2b /* if n is zero */ + addi a10, a10, 2 /* advance dst pointer */ + j .Lfillaligned + + +/* dst is word-aligned; src is word-aligned; n is at least 1. */ + + .align 4 + /* (2 mod 4) alignment for loop instruction */ +.Laligned: +#if XCHAL_HAVE_LOOPS + _movi.n a8, 0 /* set up for the maximum loop count */ + loop a8, 1f /* loop forever (almost anyway) */ + blti a4, 5, .Ldstunaligned /* n is near limit; do one at a time */ + l32i a8, a3, 0 /* get word from src */ + addi a3, a3, 4 /* advance src pointer */ + bnone a8, a11, .Lz0 /* if byte 0 is zero */ + bnone a8, a5, .Lz1 /* if byte 1 is zero */ + bnone a8, a6, .Lz2 /* if byte 2 is zero */ + s32i a8, a10, 0 /* store word to dst */ + addi a4, a4, -4 /* decrement n */ + addi a10, a10, 4 /* advance dst pointer */ + bnone a8, a7, .Lfill /* if byte 3 is zero */ +1: + +#else /* !XCHAL_HAVE_LOOPS */ + +1: blti a4, 5, .Ldstunaligned /* n is near limit; do one at a time */ + l32i a8, a3, 0 /* get word from src */ + addi a3, a3, 4 /* advance src pointer */ + bnone a8, a11, .Lz0 /* if byte 0 is zero */ + bnone a8, a5, .Lz1 /* if byte 1 is zero */ + bnone a8, a6, .Lz2 /* if byte 2 is zero */ + s32i a8, a10, 0 /* store word to dst */ + addi a4, a4, -4 /* decrement n */ + addi a10, a10, 4 /* advance dst pointer */ + bany a8, a7, 1b /* no zeroes */ +#endif /* !XCHAL_HAVE_LOOPS */ + + j .Lfill + +.Lz0: /* Byte 0 is zero. */ +#ifdef __XTENSA_EB__ + movi a8, 0 +#endif + s8i a8, a10, 0 + addi a4, a4, -1 /* decrement n */ + addi a10, a10, 1 /* advance dst pointer */ + j .Lfill + +.Lz1: /* Byte 1 is zero. */ +#ifdef __XTENSA_EB__ + extui a8, a8, 16, 16 +#endif + s16i a8, a10, 0 + addi a4, a4, -2 /* decrement n */ + addi a10, a10, 2 /* advance dst pointer */ + j .Lfill + +.Lz2: /* Byte 2 is zero. */ +#ifdef __XTENSA_EB__ + extui a8, a8, 16, 16 +#endif + s16i a8, a10, 0 + movi a8, 0 + s8i a8, a10, 2 + addi a4, a4, -3 /* decrement n */ + addi a10, a10, 3 /* advance dst pointer */ + j .Lfill + + .align 4 + /* (2 mod 4) alignment for loop instruction */ +.Ldstunaligned: + +#if XCHAL_HAVE_LOOPS + _movi.n a8, 0 /* set up for the maximum loop count */ + loop a8, 2f /* loop forever (almost anyway) */ +#endif +1: l8ui a8, a3, 0 + addi a3, a3, 1 + s8i a8, a10, 0 + addi a4, a4, -1 + beqz a4, 3f + addi a10, a10, 1 +#if XCHAL_HAVE_LOOPS + beqz a8, 2f +#else + bnez a8, 1b +#endif +2: j .Lfill + +3: retw + +libc_hidden_def (strncpy) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/Makefile new file mode 100644 index 00000000..11f362a5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../ +top_builddir=../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/Makefile.in new file mode 100644 index 00000000..686cb727 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/Makefile.in @@ -0,0 +1,8 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +include $(top_srcdir)libc/sysdeps/linux/Makefile.in diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/README b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/README new file mode 100644 index 00000000..64484336 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/README @@ -0,0 +1,6 @@ +This directory level abstracts out the UN*X-like Operating System dependent +features of uClibc for all UN*X-like operating systems. If you wanted to port +uClibc to some other UN*X-like OS, this is the place to add that support. + +If you want to port uClibc to support some non-UN*X-like Operating System, you +should probably stop using crack. It is bad for you. ;-) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/Makefile new file mode 100644 index 00000000..4a8f4a07 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../ +top_builddir=../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/Makefile.commonarch b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/Makefile.commonarch new file mode 100644 index 00000000..4e481594 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/Makefile.commonarch @@ -0,0 +1,41 @@ +# Makefile template to be included by sysdeps/linux//Makefile.arch +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +ARCH_DIR := $(top_srcdir)libc/sysdeps/linux/$(TARGET_ARCH) +ARCH_OUT := $(top_builddir)libc/sysdeps/linux/$(TARGET_ARCH) + +ARCH_CSRC := $(patsubst %.c,$(ARCH_DIR)/%.c,$(CSRC)) +ARCH_COBJ := $(patsubst %.c,$(ARCH_OUT)/%.o,$(CSRC)) +ARCH_SSRC = $(patsubst %.s,$(ARCH_DIR)/%.s,$(patsubst %.S,$(ARCH_DIR)/%.S,$(SSRC))) +ARCH_SOBJ = $(patsubst %.s,$(ARCH_OUT)/%.o,$(patsubst %.S,$(ARCH_OUT)/%.o,$(SSRC))) + +ARCH_OBJS = $(ARCH_COBJ) $(ARCH_SOBJ) + +crt-y := FORCE +libc-y += $(ARCH_OBJS) +libc-nomulti-y += $(ARCH_SOBJ) +objclean-y += CLEAN_$(subst $(top_builddir),,$(ARCH_OUT)) + +CFLAGS-crti.S+=$(PICFLAG) +CFLAGS-crtn.S+=$(PICFLAG) + +CLEAN_$(subst $(top_builddir),,$(ARCH_OUT)): + $(do_rm) $(addprefix $(ARCH_OUT)/*., o os oS) $(CTOR_TARGETS) $(CRTS) + +ifneq ($(ARCH_HEADERS),) + +ARCH_HEADERS_OUT := $(patsubst %,$(top_builddir)include/%,$(ARCH_HEADERS)) + +$(ARCH_HEADERS_OUT): + $(do_ln) $(call rel_srcdir)libc/sysdeps/linux/$(TARGET_ARCH)/$(@F) $@ + +headers-y += $(ARCH_HEADERS_OUT) +headers_clean-y += HEADERCLEAN_$(subst $(top_builddir),,$(ARCH_OUT)) +HEADERCLEAN_$(subst $(top_builddir),,$(ARCH_OUT)): + $(RM) $(ARCH_HEADERS_OUT) + +endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/Makefile.in new file mode 100644 index 00000000..dd91f215 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/Makefile.in @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +subdirs += libc/sysdeps/linux/$(TARGET_ARCH) libc/sysdeps/linux/common + +# order is relevant +-include $(top_srcdir)libc/sysdeps/linux/$(TARGET_ARCH)/Makefile.arch +include $(top_srcdir)libc/sysdeps/linux/Makefile.commonarch +include $(top_srcdir)libc/sysdeps/linux/common/Makefile.in diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/README b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/README new file mode 100644 index 00000000..76944f9e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/README @@ -0,0 +1,7 @@ +This directory level abstracts out the Linux Operating System dependent +features of uClibc for supported Linux architectures/CPUs. If you wanted to +port uClibc to some new Linux architecture (arm, mips, etc), this is the place +to add that support. + +All stuff that is not at all dependent on a particular Linux architecture +goes in the 'common' directory. diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/Makefile new file mode 100644 index 00000000..633c91f3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../../ +top_builddir=../../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.arch +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/Makefile.arch b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/Makefile.arch new file mode 100644 index 00000000..d9defc30 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/Makefile.arch @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2006 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +CSRC := __syscall_error.c sigprocmask.c + +SSRC := \ + __longjmp.S brk.S bsd-_setjmp.S bsd-setjmp.S clone.S \ + divl.S divq.S pipe.S reml.S remq.S __syscall_rt_sigaction.S setjmp.S \ + syscall.S diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/__longjmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/__longjmp.S new file mode 100644 index 00000000..910ec078 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/__longjmp.S @@ -0,0 +1,57 @@ +/* Copyright (C) 1992, 1994, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#define _SETJMP_H +#define __ASSEMBLY__ +#include + +#define a0 $16 + +.globl __longjmp; +.align 3; +.ent __longjmp , 0; + +__longjmp: + .frame $30 , 0, $26 + .prologue 0 + + mov $17, $0 + ldq $9, JB_S0*8(a0) + ldq $10, JB_S1*8(a0) + ldq $11, JB_S2*8(a0) + ldq $12, JB_S3*8(a0) + ldq $13, JB_S4*8(a0) + ldq $14, JB_S5*8(a0) + ldq $26, JB_PC*8(a0) + ldq $15, JB_FP*8(a0) + ldq $1, JB_SP*8(a0) + ldt $f2, JB_F2*8(a0) + ldt $f3, JB_F3*8(a0) + ldt $f4, JB_F4*8(a0) + ldt $f5, JB_F5*8(a0) + ldt $f6, JB_F6*8(a0) + ldt $f7, JB_F7*8(a0) + ldt $f8, JB_F8*8(a0) + ldt $f9, JB_F9*8(a0) + cmoveq $0, 1, $0 + mov $1, $30 + ret + +.end __longjmp +libc_hidden_def(__longjmp) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/__syscall_error.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/__syscall_error.c new file mode 100644 index 00000000..7c081f3b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/__syscall_error.c @@ -0,0 +1,16 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +/* This routine is jumped to by all the syscall handlers, to stash + an error number into errno. */ +int attribute_hidden __syscall_error (void) +{ + register int err_no __asm__("$0"); + __set_errno (err_no); + return -1; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/__syscall_rt_sigaction.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/__syscall_rt_sigaction.S new file mode 100644 index 00000000..f7e9e44a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/__syscall_rt_sigaction.S @@ -0,0 +1,81 @@ +/* Copyright (C) 1998, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson , 1998 + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +/* On Alpha we desparately want to avoid having to issue an imb. Ordinarily + the kernel would have to issue one after setting up the signal return + stack, but the Linux rt_sigaction syscall is prepared to accept a pointer + to the sigreturn syscall, instead of inlining it on the stack. + + This just about halves signal delivery time. */ + + .text + +.globl __syscall_rt_sigaction +.align 4 +.ent __syscall_rt_sigaction, 0 +__syscall_rt_sigaction: + .frame sp,0,ra,0 + ldgp gp,0(pv) + .prologue 1 + + beq a1, 0f + ldl t0, 8(a1) # sa_flags + + /* The unwinder will subtract one from the return address when + attempting to find the call instruction that led us here. + Since we didn't get here via a normal call, if we do nothing + we would pick up the wrong symbol and the wrong FDE. Account + for this by adding a nop to the start of the function and + then skipping it here by adding 4. */ + ldah a4, __syscall_sigreturn+4(gp) !gprelhigh + ldah t1, __syscall_rt_sigreturn+4(gp) !gprelhigh + lda a4, __syscall_sigreturn+4(a4) !gprellow + lda t1, __syscall_rt_sigreturn+4(t1) !gprellow + and t0, 0x40, t0 # SA_SIGINFO + cmovne t0, t1, a4 + +0: ldi v0, __NR_rt_sigaction + callsys + bne a3, $error + ret + +$error: + jmp zero,__syscall_error + +.end __syscall_rt_sigaction + +__syscall_sigreturn: + nop + mov sp, a0 + ldi v0, __NR_sigreturn + callsys + .size __syscall_sigreturn, .-__syscall_sigreturn + .type __syscall_sigreturn, @function + +__syscall_rt_sigreturn: + nop + mov sp,a0 + ldi v0,__NR_rt_sigreturn + callsys + .size __syscall_rt_sigreturn, .-__syscall_rt_sigreturn + .type __syscall_rt_sigreturn, @function diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/atomic.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/atomic.h new file mode 100644 index 00000000..5ad4c540 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/atomic.h @@ -0,0 +1,369 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +typedef int8_t atomic8_t; +typedef uint8_t uatomic8_t; +typedef int_fast8_t atomic_fast8_t; +typedef uint_fast8_t uatomic_fast8_t; + +typedef int16_t atomic16_t; +typedef uint16_t uatomic16_t; +typedef int_fast16_t atomic_fast16_t; +typedef uint_fast16_t uatomic_fast16_t; + +typedef int32_t atomic32_t; +typedef uint32_t uatomic32_t; +typedef int_fast32_t atomic_fast32_t; +typedef uint_fast32_t uatomic_fast32_t; + +typedef int64_t atomic64_t; +typedef uint64_t uatomic64_t; +typedef int_fast64_t atomic_fast64_t; +typedef uint_fast64_t uatomic_fast64_t; + +typedef intptr_t atomicptr_t; +typedef uintptr_t uatomicptr_t; +typedef intmax_t atomic_max_t; +typedef uintmax_t uatomic_max_t; + + +#ifdef UP +# define __MB /* nothing */ +#else +# define __MB " mb\n" +#endif + + +/* Compare and exchange. For all of the "xxx" routines, we expect a + "__prev" and a "__cmp" variable to be provided by the enclosing scope, + in which values are returned. */ + +#define __arch_compare_and_exchange_xxx_8_int(mem, new, old, mb1, mb2) \ +({ \ + unsigned long __tmp, __snew, __addr64; \ + __asm__ __volatile__ ( \ + mb1 \ + " andnot %[__addr8],7,%[__addr64]\n" \ + " insbl %[__new],%[__addr8],%[__snew]\n" \ + "1: ldq_l %[__tmp],0(%[__addr64])\n" \ + " extbl %[__tmp],%[__addr8],%[__prev]\n" \ + " cmpeq %[__prev],%[__old],%[__cmp]\n" \ + " beq %[__cmp],2f\n" \ + " mskbl %[__tmp],%[__addr8],%[__tmp]\n" \ + " or %[__snew],%[__tmp],%[__tmp]\n" \ + " stq_c %[__tmp],0(%[__addr64])\n" \ + " beq %[__tmp],1b\n" \ + mb2 \ + "2:" \ + : [__prev] "=&r" (__prev), \ + [__snew] "=&r" (__snew), \ + [__tmp] "=&r" (__tmp), \ + [__cmp] "=&r" (__cmp), \ + [__addr64] "=&r" (__addr64) \ + : [__addr8] "r" (mem), \ + [__old] "Ir" ((uint64_t)(uint8_t)(uint64_t)(old)), \ + [__new] "r" (new) \ + : "memory"); \ +}) + +#define __arch_compare_and_exchange_xxx_16_int(mem, new, old, mb1, mb2) \ +({ \ + unsigned long __tmp, __snew, __addr64; \ + __asm__ __volatile__ ( \ + mb1 \ + " andnot %[__addr16],7,%[__addr64]\n" \ + " inswl %[__new],%[__addr16],%[__snew]\n" \ + "1: ldq_l %[__tmp],0(%[__addr64])\n" \ + " extwl %[__tmp],%[__addr16],%[__prev]\n" \ + " cmpeq %[__prev],%[__old],%[__cmp]\n" \ + " beq %[__cmp],2f\n" \ + " mskwl %[__tmp],%[__addr16],%[__tmp]\n" \ + " or %[__snew],%[__tmp],%[__tmp]\n" \ + " stq_c %[__tmp],0(%[__addr64])\n" \ + " beq %[__tmp],1b\n" \ + mb2 \ + "2:" \ + : [__prev] "=&r" (__prev), \ + [__snew] "=&r" (__snew), \ + [__tmp] "=&r" (__tmp), \ + [__cmp] "=&r" (__cmp), \ + [__addr64] "=&r" (__addr64) \ + : [__addr16] "r" (mem), \ + [__old] "Ir" ((uint64_t)(uint16_t)(uint64_t)(old)), \ + [__new] "r" (new) \ + : "memory"); \ +}) + +#define __arch_compare_and_exchange_xxx_32_int(mem, new, old, mb1, mb2) \ +({ \ + __asm__ __volatile__ ( \ + mb1 \ + "1: ldl_l %[__prev],%[__mem]\n" \ + " cmpeq %[__prev],%[__old],%[__cmp]\n" \ + " beq %[__cmp],2f\n" \ + " mov %[__new],%[__cmp]\n" \ + " stl_c %[__cmp],%[__mem]\n" \ + " beq %[__cmp],1b\n" \ + mb2 \ + "2:" \ + : [__prev] "=&r" (__prev), \ + [__cmp] "=&r" (__cmp) \ + : [__mem] "m" (*(mem)), \ + [__old] "Ir" ((uint64_t)(atomic32_t)(uint64_t)(old)), \ + [__new] "Ir" (new) \ + : "memory"); \ +}) + +#define __arch_compare_and_exchange_xxx_64_int(mem, new, old, mb1, mb2) \ +({ \ + __asm__ __volatile__ ( \ + mb1 \ + "1: ldq_l %[__prev],%[__mem]\n" \ + " cmpeq %[__prev],%[__old],%[__cmp]\n" \ + " beq %[__cmp],2f\n" \ + " mov %[__new],%[__cmp]\n" \ + " stq_c %[__cmp],%[__mem]\n" \ + " beq %[__cmp],1b\n" \ + mb2 \ + "2:" \ + : [__prev] "=&r" (__prev), \ + [__cmp] "=&r" (__cmp) \ + : [__mem] "m" (*(mem)), \ + [__old] "Ir" ((uint64_t)(old)), \ + [__new] "Ir" (new) \ + : "memory"); \ +}) + +/* For all "bool" routines, we return FALSE if exchange succesful. */ + +#define __arch_compare_and_exchange_bool_8_int(mem, new, old, mb1, mb2) \ +({ unsigned long __prev; int __cmp; \ + __arch_compare_and_exchange_xxx_8_int(mem, new, old, mb1, mb2); \ + !__cmp; }) + +#define __arch_compare_and_exchange_bool_16_int(mem, new, old, mb1, mb2) \ +({ unsigned long __prev; int __cmp; \ + __arch_compare_and_exchange_xxx_16_int(mem, new, old, mb1, mb2); \ + !__cmp; }) + +#define __arch_compare_and_exchange_bool_32_int(mem, new, old, mb1, mb2) \ +({ unsigned long __prev; int __cmp; \ + __arch_compare_and_exchange_xxx_32_int(mem, new, old, mb1, mb2); \ + !__cmp; }) + +#define __arch_compare_and_exchange_bool_64_int(mem, new, old, mb1, mb2) \ +({ unsigned long __prev; int __cmp; \ + __arch_compare_and_exchange_xxx_64_int(mem, new, old, mb1, mb2); \ + !__cmp; }) + +/* For all "val" routines, return the old value whether exchange + successful or not. */ + +#define __arch_compare_and_exchange_val_8_int(mem, new, old, mb1, mb2) \ +({ unsigned long __prev; int __cmp; \ + __arch_compare_and_exchange_xxx_8_int(mem, new, old, mb1, mb2); \ + (__typeof (*mem))__prev; }) + +#define __arch_compare_and_exchange_val_16_int(mem, new, old, mb1, mb2) \ +({ unsigned long __prev; int __cmp; \ + __arch_compare_and_exchange_xxx_16_int(mem, new, old, mb1, mb2); \ + (__typeof (*mem))__prev; }) + +#define __arch_compare_and_exchange_val_32_int(mem, new, old, mb1, mb2) \ +({ unsigned long __prev; int __cmp; \ + __arch_compare_and_exchange_xxx_32_int(mem, new, old, mb1, mb2); \ + (__typeof (*mem))__prev; }) + +#define __arch_compare_and_exchange_val_64_int(mem, new, old, mb1, mb2) \ +({ unsigned long __prev; int __cmp; \ + __arch_compare_and_exchange_xxx_64_int(mem, new, old, mb1, mb2); \ + (__typeof (*mem))__prev; }) + +/* Compare and exchange with "acquire" semantics, ie barrier after. */ + +#define atomic_compare_and_exchange_bool_acq(mem, new, old) \ + __atomic_bool_bysize (__arch_compare_and_exchange_bool, int, \ + mem, new, old, "", __MB) + +#define atomic_compare_and_exchange_val_acq(mem, new, old) \ + __atomic_val_bysize (__arch_compare_and_exchange_val, int, \ + mem, new, old, "", __MB) + +/* Compare and exchange with "release" semantics, ie barrier before. */ + +#define atomic_compare_and_exchange_bool_rel(mem, new, old) \ + __atomic_bool_bysize (__arch_compare_and_exchange_bool, int, \ + mem, new, old, __MB, "") + +#define atomic_compare_and_exchange_val_rel(mem, new, old) \ + __atomic_val_bysize (__arch_compare_and_exchange_val, int, \ + mem, new, old, __MB, "") + + +/* Atomically store value and return the previous value. */ + +#define __arch_exchange_8_int(mem, value, mb1, mb2) \ +({ \ + unsigned long __ret, __tmp, __addr64, __sval; \ + __asm__ __volatile__ ( \ + mb1 \ + " andnot %[__addr8],7,%[__addr64]\n" \ + " insbl %[__value],%[__addr8],%[__sval]\n" \ + "1: ldq_l %[__tmp],0(%[__addr64])\n" \ + " extbl %[__tmp],%[__addr8],%[__ret]\n" \ + " mskbl %[__tmp],%[__addr8],%[__tmp]\n" \ + " or %[__sval],%[__tmp],%[__tmp]\n" \ + " stq_c %[__tmp],0(%[__addr64])\n" \ + " beq %[__tmp],1b\n" \ + mb2 \ + : [__ret] "=&r" (__ret), \ + [__sval] "=&r" (__sval), \ + [__tmp] "=&r" (__tmp), \ + [__addr64] "=&r" (__addr64) \ + : [__addr8] "r" (mem), \ + [__value] "r" (value) \ + : "memory"); \ + __ret; }) + +#define __arch_exchange_16_int(mem, value, mb1, mb2) \ +({ \ + unsigned long __ret, __tmp, __addr64, __sval; \ + __asm__ __volatile__ ( \ + mb1 \ + " andnot %[__addr16],7,%[__addr64]\n" \ + " inswl %[__value],%[__addr16],%[__sval]\n" \ + "1: ldq_l %[__tmp],0(%[__addr64])\n" \ + " extwl %[__tmp],%[__addr16],%[__ret]\n" \ + " mskwl %[__tmp],%[__addr16],%[__tmp]\n" \ + " or %[__sval],%[__tmp],%[__tmp]\n" \ + " stq_c %[__tmp],0(%[__addr64])\n" \ + " beq %[__tmp],1b\n" \ + mb2 \ + : [__ret] "=&r" (__ret), \ + [__sval] "=&r" (__sval), \ + [__tmp] "=&r" (__tmp), \ + [__addr64] "=&r" (__addr64) \ + : [__addr16] "r" (mem), \ + [__value] "r" (value) \ + : "memory"); \ + __ret; }) + +#define __arch_exchange_32_int(mem, value, mb1, mb2) \ +({ \ + signed int __ret, __tmp; \ + __asm__ __volatile__ ( \ + mb1 \ + "1: ldl_l %[__ret],%[__mem]\n" \ + " mov %[__val],%[__tmp]\n" \ + " stl_c %[__tmp],%[__mem]\n" \ + " beq %[__tmp],1b\n" \ + mb2 \ + : [__ret] "=&r" (__ret), \ + [__tmp] "=&r" (__tmp) \ + : [__mem] "m" (*(mem)), \ + [__val] "Ir" (value) \ + : "memory"); \ + __ret; }) + +#define __arch_exchange_64_int(mem, value, mb1, mb2) \ +({ \ + unsigned long __ret, __tmp; \ + __asm__ __volatile__ ( \ + mb1 \ + "1: ldq_l %[__ret],%[__mem]\n" \ + " mov %[__val],%[__tmp]\n" \ + " stq_c %[__tmp],%[__mem]\n" \ + " beq %[__tmp],1b\n" \ + mb2 \ + : [__ret] "=&r" (__ret), \ + [__tmp] "=&r" (__tmp) \ + : [__mem] "m" (*(mem)), \ + [__val] "Ir" (value) \ + : "memory"); \ + __ret; }) + +#define atomic_exchange_acq(mem, value) \ + __atomic_val_bysize (__arch_exchange, int, mem, value, "", __MB) + +#define atomic_exchange_rel(mem, value) \ + __atomic_val_bysize (__arch_exchange, int, mem, value, __MB, "") + + +/* Atomically add value and return the previous (unincremented) value. */ + +#define __arch_exchange_and_add_8_int(mem, value, mb1, mb2) \ + ({ __builtin_trap (); 0; }) + +#define __arch_exchange_and_add_16_int(mem, value, mb1, mb2) \ + ({ __builtin_trap (); 0; }) + +#define __arch_exchange_and_add_32_int(mem, value, mb1, mb2) \ +({ \ + signed int __ret, __tmp; \ + __asm__ __volatile__ ( \ + mb1 \ + "1: ldl_l %[__ret],%[__mem]\n" \ + " addl %[__ret],%[__val],%[__tmp]\n" \ + " stl_c %[__tmp],%[__mem]\n" \ + " beq %[__tmp],1b\n" \ + mb2 \ + : [__ret] "=&r" (__ret), \ + [__tmp] "=&r" (__tmp) \ + : [__mem] "m" (*(mem)), \ + [__val] "Ir" ((signed int)(value)) \ + : "memory"); \ + __ret; }) + +#define __arch_exchange_and_add_64_int(mem, value, mb1, mb2) \ +({ \ + unsigned long __ret, __tmp; \ + __asm__ __volatile__ ( \ + mb1 \ + "1: ldq_l %[__ret],%[__mem]\n" \ + " addq %[__ret],%[__val],%[__tmp]\n" \ + " stq_c %[__tmp],%[__mem]\n" \ + " beq %[__tmp],1b\n" \ + mb2 \ + : [__ret] "=&r" (__ret), \ + [__tmp] "=&r" (__tmp) \ + : [__mem] "m" (*(mem)), \ + [__val] "Ir" ((unsigned long)(value)) \ + : "memory"); \ + __ret; }) + +/* ??? Barrier semantics for atomic_exchange_and_add appear to be + undefined. Use full barrier for now, as that's safe. */ +#define atomic_exchange_and_add(mem, value) \ + __atomic_val_bysize (__arch_exchange_and_add, int, mem, value, __MB, __MB) + + +/* ??? Blah, I'm lazy. Implement these later. Can do better than the + compare-and-exchange loop provided by generic code. + +#define atomic_decrement_if_positive(mem) +#define atomic_bit_test_set(mem, bit) + +*/ + +#ifndef UP +# define atomic_full_barrier() __asm__ ("mb" : : : "memory"); +# define atomic_read_barrier() __asm__ ("mb" : : : "memory"); +# define atomic_write_barrier() __asm__ ("wmb" : : : "memory"); +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/dirent.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/dirent.h new file mode 100644 index 00000000..6ed74783 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/dirent.h @@ -0,0 +1,55 @@ +/* Copyright (C) 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _BITS_DIRENT_H +#define _BITS_DIRENT_H 1 + +struct dirent + { +#ifdef __USE_FILE_OFFSET64 + __ino64_t d_ino; +#else + __ino_t d_ino; + int __pad; +#endif + __off_t d_off; + unsigned short int d_reclen; + unsigned char d_type; + char d_name[256]; /* We must not include limits.h! */ + }; + +#ifdef __USE_LARGEFILE64 +/* Note dirent64 is the same as dirent. */ +struct dirent64 + { + __ino64_t d_ino; + __off64_t d_off; + unsigned short int d_reclen; + unsigned char d_type; + char d_name[256]; /* We must not include limits.h! */ + }; +#endif + +#define d_fileno d_ino /* Backwards compatibility. */ + +#undef _DIRENT_HAVE_D_NAMLEN +#define _DIRENT_HAVE_D_RECLEN +#define _DIRENT_HAVE_D_OFF +#define _DIRENT_HAVE_D_TYPE + +#endif /* bits/dirent.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/elfclass.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/elfclass.h new file mode 100644 index 00000000..e5aa4a0f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/elfclass.h @@ -0,0 +1,14 @@ +/* This file specifies the native word size of the machine, which indicates + the ELF file class used for executables and shared objects on this + machine. */ + +#ifndef _LINK_H +# error "Never use directly; include instead." +#endif + +#include + +#define __ELF_NATIVE_CLASS __WORDSIZE + +/* Linux/Alpha is exceptional as it has .hash section with 64 bit entries. */ +typedef uint64_t Elf_Symndx; diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/endian.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/endian.h new file mode 100644 index 00000000..8a16e14e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/endian.h @@ -0,0 +1,7 @@ +/* Alpha is little-endian. */ + +#ifndef _ENDIAN_H +# error "Never use directly; include instead." +#endif + +#define __BYTE_ORDER __LITTLE_ENDIAN diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/fcntl.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/fcntl.h new file mode 100644 index 00000000..649c5633 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/fcntl.h @@ -0,0 +1,230 @@ +/* O_*, F_*, FD_* bit values for Linux. + Copyright (C) 1995-2000,2004,2005,2006,2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FCNTL_H +# error "Never use directly; include instead." +#endif + +#include +#ifdef __USE_GNU +# include +#endif + + +/* open/fcntl - O_SYNC is only implemented on blocks devices and on files + located on an ext2 file system */ +#define O_ACCMODE 0003 +#define O_RDONLY 00 +#define O_WRONLY 01 +#define O_RDWR 02 +#define O_CREAT 01000 /* not fcntl */ +#define O_TRUNC 02000 /* not fcntl */ +#define O_EXCL 04000 /* not fcntl */ +#define O_NOCTTY 010000 /* not fcntl */ + +#define O_NONBLOCK 00004 +#define O_APPEND 00010 +#define O_NDELAY O_NONBLOCK +#define O_SYNC 040000 +#define O_FSYNC O_SYNC +#define O_ASYNC 020000 /* fcntl, for BSD compatibility */ + +#ifdef __USE_GNU +# define O_DIRECTORY 0100000 /* Must be a directory. */ +# define O_NOFOLLOW 0200000 /* Do not follow links. */ +# define O_DIRECT 02000000 /* Direct disk access. */ +# define O_NOATIME 04000000 /* Do not set atime. */ +# define O_CLOEXEC 010000000 /* Set close_on_exec. */ +#endif + +#ifdef __USE_LARGEFILE64 +/* Not necessary, files are always with 64bit off_t. */ +# define O_LARGEFILE 0 +#endif + +/* For now Linux has synchronisity options for data and read operations. + We define the symbols here but let them do the same as O_SYNC since + this is a superset. */ +#if defined __USE_POSIX199309 || defined __USE_UNIX98 +# define O_DSYNC O_SYNC /* Synchronize data. */ +# define O_RSYNC O_SYNC /* Synchronize read operations. */ +#endif + +/* Values for the second argument to `fcntl'. */ +#define F_DUPFD 0 /* Duplicate file descriptor. */ +#define F_GETFD 1 /* Get file descriptor flags. */ +#define F_SETFD 2 /* Set file descriptor flags. */ +#define F_GETFL 3 /* Get file status flags. */ +#define F_SETFL 4 /* Set file status flags. */ +#define F_GETLK 7 /* Get record locking info. */ +#define F_SETLK 8 /* Set record locking info (non-blocking). */ +#define F_SETLKW 9 /* Set record locking info (blocking). */ +#define F_GETLK64 F_GETLK /* Get record locking info. */ +#define F_SETLK64 F_SETLK /* Set record locking info (non-blocking). */ +#define F_SETLKW64 F_SETLKW /* Set record locking info (blocking). */ + +#if defined __USE_BSD || defined __USE_UNIX98 +# define F_SETOWN 5 /* Get owner of socket (receiver of SIGIO). */ +# define F_GETOWN 6 /* Set owner of socket (receiver of SIGIO). */ +#endif + +#ifdef __USE_GNU +# define F_SETSIG 10 /* Set number of signal to be sent. */ +# define F_GETSIG 11 /* Get number of signal to be sent. */ +#endif + +#ifdef __USE_GNU +# define F_SETLEASE 1024 /* Set a lease. */ +# define F_GETLEASE 1025 /* Enquire what lease is active. */ +# define F_NOTIFY 1026 /* Request notfications on a directory. */ +# define F_DUPFD_CLOEXEC 1030 /* Duplicate file descriptor with + close-on-exit set on new fd. */ +#endif + +/* for F_[GET|SET]FD */ +#define FD_CLOEXEC 1 /* actually anything with low bit set goes */ + +/* For posix fcntl() and `l_type' field of a `struct flock' for lockf() */ +#define F_RDLCK 1 /* Read lock. */ +#define F_WRLCK 2 /* Write lock. */ +#define F_UNLCK 8 /* Remove lock. */ + +/* for old implementation of bsd flock () */ +#define F_EXLCK 16 /* or 3 */ +#define F_SHLCK 32 /* or 4 */ + +/* Operations for bsd flock(), also used by the kernel implementation */ +#ifdef __USE_BSD +# define LOCK_SH 1 /* shared lock */ +# define LOCK_EX 2 /* exclusive lock */ +# define LOCK_NB 4 /* or'd with one of the above to prevent + blocking */ +# define LOCK_UN 8 /* remove lock */ +#endif + +#ifdef __USE_GNU +# define LOCK_MAND 32 /* This is a mandatory flock: */ +# define LOCK_READ 64 /* ... which allows concurrent read operations. */ +# define LOCK_WRITE 128 /* ... which allows concurrent write operations. */ +# define LOCK_RW 192 /* ... Which allows concurrent read & write operations. */ +#endif + +#ifdef __USE_GNU +/* Types of directory notifications that may be requested with F_NOTIFY. */ +# define DN_ACCESS 0x00000001 /* File accessed. */ +# define DN_MODIFY 0x00000002 /* File modified. */ +# define DN_CREATE 0x00000004 /* File created. */ +# define DN_DELETE 0x00000008 /* File removed. */ +# define DN_RENAME 0x00000010 /* File renamed. */ +# define DN_ATTRIB 0x00000020 /* File changed attibutes. */ +# define DN_MULTISHOT 0x80000000 /* Don't remove notifier. */ +#endif + +/* We don't need to support __USE_FILE_OFFSET64. */ +struct flock + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ + __off_t l_start; /* Offset where the lock begins. */ + __off_t l_len; /* Size of the locked area; zero means until EOF. */ + __pid_t l_pid; /* Process holding the lock. */ + }; + +#ifdef __USE_LARGEFILE64 +struct flock64 + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ + __pid_t l_pid; /* Process holding the lock. */ + }; +#endif + +/* Define some more compatibility macros to be backward compatible with + BSD systems which did not managed to hide these kernel macros. */ +#ifdef __USE_BSD +# define FAPPEND O_APPEND +# define FFSYNC O_FSYNC +# define FASYNC O_ASYNC +# define FNONBLOCK O_NONBLOCK +# define FNDELAY O_NDELAY +#endif /* Use BSD. */ + +/* Advise to `posix_fadvise'. */ +#ifdef __USE_XOPEN2K +# define POSIX_FADV_NORMAL 0 /* No further special treatment. */ +# define POSIX_FADV_RANDOM 1 /* Expect random page references. */ +# define POSIX_FADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define POSIX_FADV_WILLNEED 3 /* Will need these pages. */ +# define POSIX_FADV_DONTNEED 4 /* Don't need these pages. */ +# define POSIX_FADV_NOREUSE 5 /* Data will be accessed once. */ +#endif + + +#if defined __USE_GNU && defined __UCLIBC_LINUX_SPECIFIC__ +/* Flags for SYNC_FILE_RANGE. */ +# define SYNC_FILE_RANGE_WAIT_BEFORE 1 /* Wait upon writeout of all pages + in the range before performing the + write. */ +# define SYNC_FILE_RANGE_WRITE 2 /* Initiate writeout of all those + dirty pages in the range which are + not presently under writeback. */ +# define SYNC_FILE_RANGE_WAIT_AFTER 4 /* Wait upon writeout of all pages in + the range after performing the + write. */ + +/* Flags for SPLICE and VMSPLICE. */ +# define SPLICE_F_MOVE 1 /* Move pages instead of copying. */ +# define SPLICE_F_NONBLOCK 2 /* Don't block on the pipe splicing + (but we may still block on the fd + we splice from/to). */ +# define SPLICE_F_MORE 4 /* Expect more data. */ +# define SPLICE_F_GIFT 8 /* Pages passed in are a gift. */ +#endif + +__BEGIN_DECLS + +#if defined __USE_GNU && defined __UCLIBC_LINUX_SPECIFIC__ + +/* Provide kernel hint to read ahead. */ +extern ssize_t readahead (int __fd, __off64_t __offset, size_t __count) + __THROW; + + +/* Selective file content synch'ing. */ +extern int sync_file_range (int __fd, __off64_t __from, __off64_t __to, + unsigned int __flags); + +/* Splice address range into a pipe. */ +extern ssize_t vmsplice (int __fdout, const struct iovec *__iov, + size_t __count, unsigned int __flags); + +/* Splice two files together. */ +extern ssize_t splice (int __fdin, __off64_t *__offin, int __fdout, + __off64_t *__offout, size_t __len, + unsigned int __flags); + +/* In-kernel implementation of tee for pipe buffers. */ +extern ssize_t tee (int __fdin, int __fdout, size_t __len, + unsigned int __flags); + +#endif +__END_DECLS + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/fenv.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/fenv.h new file mode 100644 index 00000000..a9e89b49 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/fenv.h @@ -0,0 +1,123 @@ +/* Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FENV_H +# error "Never use directly; include instead." +#endif + + +/* Define the bits representing the exception. + + Note that these are the bit positions as defined by the OSF/1 + ieee_{get,set}_control_word interface and not by the hardware fpcr. + + See the Alpha Architecture Handbook section 4.7.7.3 for details, + but in summary, trap shadows mean the hardware register can acquire + extra exception bits so for proper IEEE support the tracking has to + be done in software -- in this case with kernel support. + + As to why the system call interface isn't in the same format as + the hardware register, only those crazy folks at DEC can tell you. */ + +enum + { +#ifdef __USE_GNU + FE_DENORMAL = 1UL << 22, +#define FE_DENORMAL FE_DENORMAL +#endif + + FE_INEXACT = 1UL << 21, +#define FE_INEXACT FE_INEXACT + + FE_UNDERFLOW = 1UL << 20, +#define FE_UNDERFLOW FE_UNDERFLOW + + FE_OVERFLOW = 1UL << 19, +#define FE_OVERFLOW FE_OVERFLOW + + FE_DIVBYZERO = 1UL << 18, +#define FE_DIVBYZERO FE_DIVBYZERO + + FE_INVALID = 1UL << 17, +#define FE_INVALID FE_INVALID + + FE_ALL_EXCEPT = 0x3f << 17 +#define FE_ALL_EXCEPT FE_ALL_EXCEPT + }; + +/* Alpha chips support all four defined rouding modes. + + Note that code must be compiled to use dynamic rounding (/d) instructions + to see these changes. For gcc this is -mfp-rounding-mode=d; for DEC cc + this is -fprm d. The default for both is static rounding to nearest. + + These are shifted down 58 bits from the hardware fpcr because the + functions are declared to take integers. */ + +enum + { + FE_TOWARDZERO = 0, +#define FE_TOWARDZERO FE_TOWARDZERO + + FE_DOWNWARD = 1, +#define FE_DOWNWARD FE_DOWNWARD + + FE_TONEAREST = 2, +#define FE_TONEAREST FE_TONEAREST + + FE_UPWARD = 3, +#define FE_UPWARD FE_UPWARD + }; + +#ifdef __USE_GNU +/* On later hardware, and later kernels for earlier hardware, we can forcibly + underflow denormal inputs and outputs. This can speed up certain programs + significantly, usually without affecting accuracy. */ +enum + { + FE_MAP_DMZ = 1UL << 12, /* Map denorm inputs to zero */ +#define FE_MAP_DMZ FE_MAP_DMZ + + FE_MAP_UMZ = 1UL << 13, /* Map underflowed outputs to zero */ +#define FE_MAP_UMZ FE_MAP_UMZ + }; +#endif + +/* Type representing exception flags. */ +typedef unsigned long int fexcept_t; + +/* Type representing floating-point environment. */ +typedef unsigned long int fenv_t; + +/* If the default argument is used we use this value. Note that due to + architecture-specified page mappings, no user-space pointer will ever + have its two high bits set. Co-opt one. */ +#define FE_DFL_ENV ((__const fenv_t *) 0x8800000000000000UL) + +#ifdef __USE_GNU +/* Floating-point environment where none of the exceptions are masked. */ +# define FE_NOMASK_ENV ((__const fenv_t *) 0x880000000000003eUL) + +/* Floating-point environment with (processor-dependent) non-IEEE floating + point. In this case, mapping denormals to zero. */ +# define FE_NONIEEE_ENV ((__const fenv_t *) 0x8800000000003000UL) +#endif + +/* The system calls to talk to the kernel's FP code. */ +extern unsigned long int __ieee_get_fp_control (void) __THROW; +extern void __ieee_set_fp_control (unsigned long int __value) __THROW; diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/ioctls.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/ioctls.h new file mode 100644 index 00000000..c525046e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/ioctls.h @@ -0,0 +1,37 @@ +/* Copyright (C) 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_IOCTL_H +# error "Never use directly; include instead." +#endif + +/* Use the definitions from the kernel header files. */ +#include + +/* Oh well, this is necessary since the kernel data structure is + different from the user-level version. */ +#undef TCGETS +#undef TCSETS +#undef TCSETSW +#undef TCSETSF +#define TCGETS _IOR ('t', 19, char[44]) +#define TCSETS _IOW ('t', 20, char[44]) +#define TCSETSW _IOW ('t', 21, char[44]) +#define TCSETSF _IOW ('t', 22, char[44]) + +#include diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/ipc.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/ipc.h new file mode 100644 index 00000000..77f3c938 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/ipc.h @@ -0,0 +1,55 @@ +/* Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_IPC_H +# error "Never use directly; include instead." +#endif + +#include + +/* Mode bits for `msgget', `semget', and `shmget'. */ +#define IPC_CREAT 01000 /* Create key if key does not exist. */ +#define IPC_EXCL 02000 /* Fail if key exists. */ +#define IPC_NOWAIT 04000 /* Return error on wait. */ + +/* Control commands for `msgctl', `semctl', and `shmctl'. */ +#define IPC_RMID 0 /* Remove identifier. */ +#define IPC_SET 1 /* Set `ipc_perm' options. */ +#define IPC_STAT 2 /* Get `ipc_perm' options. */ +#ifdef __USE_GNU +# define IPC_INFO 3 /* See ipcs. */ +#endif + +/* Special key values. */ +#define IPC_PRIVATE ((__key_t) 0) /* Private key. */ + + +/* Data structure used to pass permission information to IPC operations. */ +struct ipc_perm + { + __key_t __key; /* Key. */ + unsigned int uid; /* Owner's user ID. */ + unsigned int gid; /* Owner's group ID. */ + unsigned int cuid; /* Creator's user ID. */ + unsigned int cgid; /* Creator's group ID. */ + unsigned int mode; /* Read/write permission. */ + unsigned short int __seq; /* Sequence number. */ + unsigned short int __pad1; + unsigned long int __unused1; + unsigned long int __unused2; + }; diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/kernel_sigaction.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/kernel_sigaction.h new file mode 100644 index 00000000..cd6b2133 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/kernel_sigaction.h @@ -0,0 +1,20 @@ +#ifndef _BITS_SIGACTION_STRUCT_H +#define _BITS_SIGACTION_STRUCT_H + +/* This is the sigaction struction from the Linux 2.1.20 kernel. */ + +struct old_kernel_sigaction { + __sighandler_t k_sa_handler; + unsigned long sa_mask; + unsigned int sa_flags; +}; + +/* In uclibc, userspace struct sigaction is identical to + * "new" struct kernel_sigaction (one from the Linux 2.1.68 kernel). + * See sigaction.h + */ + +extern int __syscall_rt_sigaction (int, const struct sigaction *, + struct sigaction *, size_t) attribute_hidden; + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/kernel_stat.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/kernel_stat.h new file mode 100644 index 00000000..8279a391 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/kernel_stat.h @@ -0,0 +1,49 @@ +#ifndef _BITS_STAT_STRUCT_H +#define _BITS_STAT_STRUCT_H + +#ifndef _LIBC +#error bits/kernel_stat.h is for internal uClibc use only! +#endif + +/* This file provides whatever this particular arch's kernel thinks + * struct kernel_stat should look like... It turns out each arch has a + * different opinion on the subject... */ +struct kernel_stat { + unsigned int st_dev; + unsigned int st_ino; + unsigned int st_mode; + unsigned int st_nlink; + unsigned int st_uid; + unsigned int st_gid; + unsigned int st_rdev; + long int st_size; + unsigned long st_atime; + unsigned long st_mtime; + unsigned long st_ctime; + unsigned int st_blksize; + int st_blocks; + unsigned int st_flags; + unsigned int st_gen; +}; + +struct kernel_stat64 { + unsigned long st_dev; + unsigned long st_ino; + unsigned long st_rdev; + long st_size; + unsigned long st_blocks; + + unsigned int st_mode; + unsigned int st_uid; + unsigned int st_gid; + unsigned int st_blksize; + unsigned int st_nlink; + unsigned int __pad0; + + struct timespec st_atim; + struct timespec st_mtim; + struct timespec st_ctim; + long __unused[3]; +}; + +#endif /* _BITS_STAT_STRUCT_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/kernel_types.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/kernel_types.h new file mode 100644 index 00000000..d5574c9b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/kernel_types.h @@ -0,0 +1,41 @@ +/* Note that we use the exact same include guard #define names + * as asm/posix_types.h. This will avoid gratuitous conflicts + * with the posix_types.h kernel header, and will ensure that + * our private content, and not the kernel header, will win. + * -Erik + */ +#ifndef _ALPHA_POSIX_TYPES_H +#define _ALPHA_POSIX_TYPES_H + +typedef unsigned int __kernel_dev_t; +typedef unsigned int __kernel_ino_t; +typedef unsigned int __kernel_mode_t; +typedef unsigned int __kernel_nlink_t; +typedef long __kernel_off_t; +typedef long __kernel_loff_t; +typedef int __kernel_pid_t; +typedef int __kernel_ipc_pid_t; +typedef unsigned int __kernel_uid_t; +typedef unsigned int __kernel_gid_t; +typedef unsigned long __kernel_size_t; +typedef long __kernel_ssize_t; +typedef long __kernel_ptrdiff_t; +typedef long __kernel_time_t; +typedef long __kernel_suseconds_t; +typedef long __kernel_clock_t; +typedef int __kernel_daddr_t; +typedef char * __kernel_caddr_t; +typedef unsigned long __kernel_sigset_t; +typedef unsigned short __kernel_uid16_t; +typedef unsigned short __kernel_gid16_t; +typedef __kernel_uid_t __kernel_old_uid_t; +typedef __kernel_gid_t __kernel_old_gid_t; +typedef __kernel_uid_t __kernel_uid32_t; +typedef __kernel_gid_t __kernel_gid32_t; +typedef __kernel_dev_t __kernel_old_dev_t; + +typedef struct { + int val[2]; +} __kernel_fsid_t; + +#endif /* _ALPHA_POSIX_TYPES_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/mathdef.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/mathdef.h new file mode 100644 index 00000000..615eb9db --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/mathdef.h @@ -0,0 +1,66 @@ +/* Copyright (C) 1997,1998,1999,2000,2003,2004,2006 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#if !defined _MATH_H && !defined _COMPLEX_H +# error "Never use directly; include instead" +#endif + +/* FIXME! This file describes properties of the compiler, not the machine; + it should not be part of libc! */ + +#if defined __USE_ISOC99 && defined _MATH_H && !defined _MATH_H_MATHDEF +# define _MATH_H_MATHDEF 1 + +/* Alpha has both `float' and `double' arithmetic. */ +typedef float float_t; +typedef double double_t; + +/* The values returned by `ilogb' for 0 and NaN respectively. */ +# define FP_ILOGB0 (-2147483647) +# define FP_ILOGBNAN (2147483647) + +#endif /* ISO C99 && MATH_H */ + +#if defined _COMPLEX_H && !defined _COMPLEX_H_MATHDEF +# define _COMPLEX_H_MATHDEF 1 +# if defined(__GNUC__) && !__GNUC_PREREQ(3,4) + +/* Due to an ABI change, we need to remap the complex float symbols. */ +# define _Mdouble_ float +# define __MATHCALL(function, args) \ + __MATHDECL(_Complex float, function, args) +# define __MATHDECL(type, function, args) \ + __MATHDECL_1(type, function##f, args, __c1_##function##f); \ + __MATHDECL_1(type, __##function##f, args, __c1_##function##f) +# define __MATHDECL_1(type, function, args, alias) \ + extern type function args __asm__(#alias) __THROW + +# include + +# undef _Mdouble_ +# undef __MATHCALL +# undef __MATHDECL +# undef __MATHDECL_1 + +# endif /* GNUC before 3.4 */ +#endif /* COMPLEX_H */ + +#if !defined __NO_LONG_DOUBLE_MATH && !defined __UCLIBC_HAS_LONG_DOUBLE_MATH__ +# define __NO_LONG_DOUBLE_MATH 1 +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/mathinline.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/mathinline.h new file mode 100644 index 00000000..3dd38e89 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/mathinline.h @@ -0,0 +1,183 @@ +/* Inline math functions for Alpha. + Copyright (C) 1996, 1997, 1999-2001, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by David Mosberger-Tang. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _MATH_H +# error "Never use directly; include instead." +#endif + +#ifdef __cplusplus +# define __MATH_INLINE __inline +#else +# define __MATH_INLINE extern __inline +#endif + +#if defined __USE_ISOC99 && defined __GNUC__ && !__GNUC_PREREQ(3,0) +# undef isgreater +# undef isgreaterequal +# undef isless +# undef islessequal +# undef islessgreater +# undef isunordered +# define isunordered(u, v) \ + (__extension__ \ + ({ double __r, __u = (u), __v = (v); \ + __asm__ ("cmptun/su %1,%2,%0\n\ttrapb" \ + : "=&f" (__r) : "f" (__u), "f"(__v)); \ + __r != 0; })) +#endif /* ISO C99 */ + +#if (!defined __NO_MATH_INLINES || defined __LIBC_INTERNAL_MATH_INLINES) \ + && defined __OPTIMIZE__ + +#if !__GNUC_PREREQ (4, 0) +# define __inline_copysign(NAME, TYPE) \ +__MATH_INLINE TYPE \ +__NTH (NAME (TYPE __x, TYPE __y)) \ +{ \ + TYPE __z; \ + __asm__ ("cpys %1, %2, %0" : "=f" (__z) : "f" (__y), "f" (__x)); \ + return __z; \ +} + +__inline_copysign (__copysignf, float) +__inline_copysign (copysignf, float) +__inline_copysign (__copysign, double) +__inline_copysign (copysign, double) + +# undef __inline_copysign +#endif + + +#if !__GNUC_PREREQ (2, 8) +# define __inline_fabs(NAME, TYPE) \ +__MATH_INLINE TYPE \ +__NTH (NAME (TYPE __x)) \ +{ \ + TYPE __z; \ + __asm__ ("cpys $f31, %1, %0" : "=f" (__z) : "f" (__x)); \ + return __z; \ +} + +__inline_fabs (__fabsf, float) +__inline_fabs (fabsf, float) +__inline_fabs (__fabs, double) +__inline_fabs (fabs, double) + +# undef __inline_fabs +#endif + + +/* Use the -inf rounding mode conversion instructions to implement + floor. We note when the exponent is large enough that the value + must be integral, as this avoids unpleasant integer overflows. */ + +__MATH_INLINE float +__NTH (__floorf (float __x)) +{ + /* Check not zero since floor(-0) == -0. */ + if (__x != 0 && fabsf (__x) < 16777216.0f) /* 1 << FLT_MANT_DIG */ + { + /* Note that Alpha S_Floating is stored in registers in a + restricted T_Floating format, so we don't even need to + convert back to S_Floating in the end. The initial + conversion to T_Floating is needed to handle denormals. */ + + float __tmp1, __tmp2; + + __asm__ ("cvtst/s %3,%2\n\t" +#ifdef _IEEE_FP_INEXACT + "cvttq/svim %2,%1\n\t" +#else + "cvttq/svm %2,%1\n\t" +#endif + "cvtqt/m %1,%0\n\t" + : "=f"(__x), "=&f"(__tmp1), "=&f"(__tmp2) + : "f"(__x)); + } + return __x; +} + +__MATH_INLINE double +__NTH (__floor (double __x)) +{ + if (__x != 0 && fabs (__x) < 9007199254740992.0) /* 1 << DBL_MANT_DIG */ + { + double __tmp1; + __asm__ ( +#ifdef _IEEE_FP_INEXACT + "cvttq/svim %2,%1\n\t" +#else + "cvttq/svm %2,%1\n\t" +#endif + "cvtqt/m %1,%0\n\t" + : "=f"(__x), "=&f"(__tmp1) + : "f"(__x)); + } + return __x; +} + +__MATH_INLINE float __NTH (floorf (float __x)) { return __floorf(__x); } +__MATH_INLINE double __NTH (floor (double __x)) { return __floor(__x); } + + +#ifdef __USE_ISOC99 + +__MATH_INLINE float +__NTH (__fdimf (float __x, float __y)) +{ + return __x <= __y ? 0.0f : __x - __y; +} + +__MATH_INLINE float +__NTH (fdimf (float __x, float __y)) +{ + return __x <= __y ? 0.0f : __x - __y; +} + +__MATH_INLINE double +__NTH (__fdim (double __x, double __y)) +{ + return __x <= __y ? 0.0 : __x - __y; +} + +__MATH_INLINE double +__NTH (fdim (double __x, double __y)) +{ + return __x <= __y ? 0.0 : __x - __y; +} + +/* Test for negative number. Used in the signbit() macro. */ +__MATH_INLINE int +__NTH (__signbitf (float __x)) +{ + __extension__ union { float __f; int __i; } __u = { __f: __x }; + return __u.__i < 0; +} + +__MATH_INLINE int +__NTH (__signbit (double __x)) +{ + __extension__ union { double __d; long __i; } __u = { __d: __x }; + return __u.__i < 0; +} + +#endif /* C99 */ + +#endif /* __NO_MATH_INLINES */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/mman.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/mman.h new file mode 100644 index 00000000..cafad4a2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/mman.h @@ -0,0 +1,120 @@ +/* Definitions for POSIX memory map interface. Linux/Alpha version. + Copyright (C) 1997, 1998, 2000, 2003, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_MMAN_H +# error "Never use directly; include instead." +#endif + +/* The following definitions basically come from the kernel headers. + But the kernel header is not namespace clean. */ + + +/* Protections are chosen from these bits, OR'd together. The + implementation does not necessarily support PROT_EXEC or PROT_WRITE + without PROT_READ. The only guarantees are that no writing will be + allowed without PROT_WRITE and no access will be allowed for PROT_NONE. */ + +#define PROT_READ 0x1 /* Page can be read. */ +#define PROT_WRITE 0x2 /* Page can be written. */ +#define PROT_EXEC 0x4 /* Page can be executed. */ +#define PROT_NONE 0x0 /* Page can not be accessed. */ +#define PROT_GROWSDOWN 0x01000000 /* Extend change to start of + growsdown vma (mprotect only). */ +#define PROT_GROWSUP 0x02000000 /* Extend change to start of + growsup vma (mprotect only). */ + +/* Sharing types (must choose one and only one of these). */ +#define MAP_SHARED 0x01 /* Share changes. */ +#define MAP_PRIVATE 0x02 /* Changes are private. */ +#ifdef __USE_MISC +# define MAP_TYPE 0x0f /* Mask for type of mapping. */ +#endif + +/* Other flags. */ +#define MAP_FIXED 0x100 /* Interpret addr exactly. */ +#ifdef __USE_MISC +# define MAP_FILE 0 +# define MAP_ANONYMOUS 0x10 /* Don't use a file. */ +# define MAP_ANON MAP_ANONYMOUS +#endif + +/* Not used by Linux, but here to make sure we don't clash with + OSF/1 defines. */ +#if 0 && defined __USE_BSD +# define MAP_HASSEMAPHORE 0x0200 +# define MAP_INHERIT 0x0400 +# define MAP_UNALIGNED 0x0800 +#endif + +/* These are Linux-specific. */ +#ifdef __USE_MISC +# define MAP_GROWSDOWN 0x01000 /* Stack-like segment. */ +# define MAP_DENYWRITE 0x02000 /* ETXTBSY */ +# define MAP_EXECUTABLE 0x04000 /* Mark it as an executable. */ +# define MAP_LOCKED 0x08000 /* Lock the mapping. */ +# define MAP_NORESERVE 0x10000 /* Don't check for reservations. */ +# define MAP_POPULATE 0x20000 /* Populate (prefault) pagetables. */ +# define MAP_NONBLOCK 0x40000 /* Do not block on IO. */ +# define MAP_UNINITIALIZE 0x4000000 /* For anonymous mmap, memory could + be uninitialized. */ +#endif + +/* Flags to `msync'. */ +#define MS_ASYNC 1 /* Sync memory asynchronously. */ +#define MS_SYNC 2 /* Synchronous memory sync. */ +#define MS_INVALIDATE 4 /* Invalidate the caches. */ + +/* Flags for `mlockall'. */ +#define MCL_CURRENT 8192 /* Lock all currently mapped pages. */ +#define MCL_FUTURE 16384 /* Lock all additions to address + space. */ + +/* Flags for `mremap'. */ +#ifdef __USE_GNU +# define MREMAP_MAYMOVE 1 +# define MREMAP_FIXED 2 +#endif + +/* Advice to `madvise'. */ +#ifdef __USE_BSD +# define MADV_NORMAL 0 /* No further special treatment. */ +# define MADV_RANDOM 1 /* Expect random page references. */ +# define MADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define MADV_WILLNEED 3 /* Will need these pages. */ +# define MADV_DONTNEED 6 /* Don't need these pages. */ +# define MADV_REMOVE 9 /* Remove these pages and resources. */ +# define MADV_DONTFORK 10 /* Do not inherit across fork. */ +# define MADV_DOFORK 11 /* Do inherit across fork. */ +#endif + +/* The POSIX people had to invent similar names for the same things. */ +#ifdef __USE_XOPEN2K +# define POSIX_MADV_NORMAL 0 /* No further special treatment. */ +# define POSIX_MADV_RANDOM 1 /* Expect random page references. */ +# define POSIX_MADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define POSIX_MADV_WILLNEED 3 /* Will need these pages. */ +# define POSIX_MADV_DONTNEED 6 /* Don't need these pages. */ +#endif + +/* Not used by Linux, but here to make sure we don't clash with + OSF/1 defines. */ +#if 0 && defined __USE_BSD +# define MADV_DONTNEED_COMPAT 4 /* Old version? */ +# define MADV_SPACEAVAIL 5 /* Ensure resources are available. */ +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/msq.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/msq.h new file mode 100644 index 00000000..ab251eaf --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/msq.h @@ -0,0 +1,74 @@ +/* Copyright (C) 1995, 1996, 1997, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_MSG_H +# error "Never use directly; include instead." +#endif + +#include + +/* Define options for message queue functions. */ +#define MSG_NOERROR 010000 /* no error if message is too big */ +#ifdef __USE_GNU +# define MSG_EXCEPT 020000 /* recv any msg except of specified type */ +#endif + +/* Types used in the structure definition. */ +typedef unsigned long int msgqnum_t; +typedef unsigned long int msglen_t; + + +/* Structure of record for one message inside the kernel. + The type `struct msg' is opaque. */ +struct msqid_ds +{ + struct ipc_perm msg_perm; /* structure describing operation permission */ + __time_t msg_stime; /* time of last msgsnd command */ + __time_t msg_rtime; /* time of last msgrcv command */ + __time_t msg_ctime; /* time of last change */ + unsigned long int __msg_cbytes; /* current number of bytes on queue */ + msgqnum_t msg_qnum; /* number of messages currently on queue */ + msglen_t msg_qbytes; /* max number of bytes allowed on queue */ + __pid_t msg_lspid; /* pid of last msgsnd() */ + __pid_t msg_lrpid; /* pid of last msgrcv() */ + unsigned long int __unused1; + unsigned long int __unused2; +}; + +#ifdef __USE_MISC + +# define msg_cbytes __msg_cbytes + +/* ipcs ctl commands */ +# define MSG_STAT 11 +# define MSG_INFO 12 + +/* buffer for msgctl calls IPC_INFO, MSG_INFO */ +struct msginfo + { + int msgpool; + int msgmap; + int msgmax; + int msgmnb; + int msgmni; + int msgssz; + int msgtql; + unsigned short int msgseg; + }; + +#endif /* __USE_MISC */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/netdb.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/netdb.h new file mode 100644 index 00000000..e3664fd2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/netdb.h @@ -0,0 +1,35 @@ +/* Copyright (C) 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _NETDB_H +# error "Never include directly; use instead." +#endif + + +/* Description of data base entry for a single network. NOTE: here a + poor assumption is made. The network number is expected to fit + into an unsigned long int variable. */ +struct netent +{ + char *n_name; /* Official name of network. */ + char **n_aliases; /* Alias list. */ + int n_addrtype; /* Net address type. */ + /* XXX We should probably use uint32_t for the field and ensure + compatiblity by adding appropriate padding. */ + unsigned long int n_net; /* Network number. */ +}; diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/resource.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/resource.h new file mode 100644 index 00000000..21637458 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/resource.h @@ -0,0 +1,225 @@ +/* Bit values & structures for resource limits. Alpha/Linux version. + Copyright (C) 1994, 1996, 1997, 1998, 1999, 2000, 2004, 2005 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_RESOURCE_H +# error "Never use directly; include instead." +#endif + +#include + +/* Transmute defines to enumerations. The macro re-definitions are + necessary because some programs want to test for operating system + features with #ifdef RUSAGE_SELF. In ISO C the reflexive + definition is a no-op. */ + +/* Kinds of resource limit. */ +enum __rlimit_resource +{ + /* Per-process CPU limit, in seconds. */ + RLIMIT_CPU = 0, +#define RLIMIT_CPU RLIMIT_CPU + + /* Largest file that can be created, in bytes. */ + RLIMIT_FSIZE = 1, +#define RLIMIT_FSIZE RLIMIT_FSIZE + + /* Maximum size of data segment, in bytes. */ + RLIMIT_DATA = 2, +#define RLIMIT_DATA RLIMIT_DATA + + /* Maximum size of stack segment, in bytes. */ + RLIMIT_STACK = 3, +#define RLIMIT_STACK RLIMIT_STACK + + /* Largest core file that can be created, in bytes. */ + RLIMIT_CORE = 4, +#define RLIMIT_CORE RLIMIT_CORE + + /* Largest resident set size, in bytes. + This affects swapping; processes that are exceeding their + resident set size will be more likely to have physical memory + taken from them. */ + __RLIMIT_RSS = 5, +#define RLIMIT_RSS __RLIMIT_RSS + + /* Number of open files. */ + RLIMIT_NOFILE = 6, + __RLIMIT_OFILE = RLIMIT_NOFILE, /* BSD name for same. */ +#define RLIMIT_NOFILE RLIMIT_NOFILE +#define RLIMIT_OFILE __RLIMIT_OFILE + + /* Address space limit (?) */ + RLIMIT_AS = 7, +#define RLIMIT_AS RLIMIT_AS + + /* Number of processes. */ + __RLIMIT_NPROC = 8, +#define RLIMIT_NPROC __RLIMIT_NPROC + + /* Locked-in-memory address space. */ + __RLIMIT_MEMLOCK = 9, +#define RLIMIT_MEMLOCK __RLIMIT_MEMLOCK + + /* Maximum number of file locks. */ + __RLIMIT_LOCKS = 10, +#define RLIMIT_LOCKS __RLIMIT_LOCKS + + /* Maximum number of pending signals. */ + __RLIMIT_SIGPENDING = 11, +#define RLIMIT_SIGPENDING __RLIMIT_SIGPENDING + + /* Maximum bytes in POSIX message queues. */ + __RLIMIT_MSGQUEUE = 12, +#define RLIMIT_MSGQUEUE __RLIMIT_MSGQUEUE + + /* Maximum nice priority allowed to raise to. + Nice levels 19 .. -20 correspond to 0 .. 39 + values of this resource limit. */ + __RLIMIT_NICE = 13, +#define RLIMIT_NICE __RLIMIT_NICE + + /* Maximum realtime priority allowed for non-priviledged + processes. */ + __RLIMIT_RTPRIO = 14, +#define RLIMIT_RTPRIO __RLIMIT_RTPRIO + + __RLIMIT_NLIMITS = 15, + __RLIM_NLIMITS = __RLIMIT_NLIMITS +#define RLIMIT_NLIMITS __RLIMIT_NLIMITS +#define RLIM_NLIMITS __RLIM_NLIMITS +}; + +/* Value to indicate that there is no limit. */ +#ifndef __USE_FILE_OFFSET64 +# define RLIM_INFINITY ((long int)(~0UL >> 1)) +#else +# define RLIM_INFINITY 0x7fffffffffffffffLL +#endif + +#ifdef __USE_LARGEFILE64 +# define RLIM64_INFINITY 0x7fffffffffffffffLL +#endif + +/* We can represent all limits. */ +#define RLIM_SAVED_MAX RLIM_INFINITY +#define RLIM_SAVED_CUR RLIM_INFINITY + + +/* Type for resource quantity measurement. */ +#ifndef __USE_FILE_OFFSET64 +typedef __rlim_t rlim_t; +#else +typedef __rlim64_t rlim_t; +#endif +#ifdef __USE_LARGEFILE64 +typedef __rlim64_t rlim64_t; +#endif + +struct rlimit + { + /* The current (soft) limit. */ + rlim_t rlim_cur; + /* The hard limit. */ + rlim_t rlim_max; + }; + +#ifdef __USE_LARGEFILE64 +struct rlimit64 + { + /* The current (soft) limit. */ + rlim64_t rlim_cur; + /* The hard limit. */ + rlim64_t rlim_max; + }; +#endif + +/* Whose usage statistics do you want? */ +enum __rusage_who +{ + /* The calling process. */ + RUSAGE_SELF = 0, +#define RUSAGE_SELF RUSAGE_SELF + + /* All of its terminated child processes. */ + RUSAGE_CHILDREN = -1 +#define RUSAGE_CHILDREN RUSAGE_CHILDREN +}; + +#define __need_timeval +#include /* For `struct timeval'. */ + +/* Structure which says how much of each resource has been used. */ +struct rusage + { + /* Total amount of user time used. */ + struct timeval ru_utime; + /* Total amount of system time used. */ + struct timeval ru_stime; + /* Maximum resident set size (in kilobytes). */ + long int ru_maxrss; + /* Amount of sharing of text segment memory + with other processes (kilobyte-seconds). */ + long int ru_ixrss; + /* Amount of data segment memory used (kilobyte-seconds). */ + long int ru_idrss; + /* Amount of stack memory used (kilobyte-seconds). */ + long int ru_isrss; + /* Number of soft page faults (i.e. those serviced by reclaiming + a page from the list of pages awaiting reallocation. */ + long int ru_minflt; + /* Number of hard page faults (i.e. those that required I/O). */ + long int ru_majflt; + /* Number of times a process was swapped out of physical memory. */ + long int ru_nswap; + /* Number of input operations via the file system. Note: This + and `ru_oublock' do not include operations with the cache. */ + long int ru_inblock; + /* Number of output operations via the file system. */ + long int ru_oublock; + /* Number of IPC messages sent. */ + long int ru_msgsnd; + /* Number of IPC messages received. */ + long int ru_msgrcv; + /* Number of signals delivered. */ + long int ru_nsignals; + /* Number of voluntary context switches, i.e. because the process + gave up the process before it had to (usually to wait for some + resource to be available). */ + long int ru_nvcsw; + /* Number of involuntary context switches, i.e. a higher priority process + became runnable or the current process used up its time slice. */ + long int ru_nivcsw; + }; + +/* Priority limits. */ +#define PRIO_MIN -20 /* Minimum priority a process can have. */ +#define PRIO_MAX 20 /* Maximum priority a process can have. */ + +/* The type of the WHICH argument to `getpriority' and `setpriority', + indicating what flavor of entity the WHO argument specifies. */ +enum __priority_which +{ + PRIO_PROCESS = 0, /* WHO is a process ID. */ +#define PRIO_PROCESS PRIO_PROCESS + PRIO_PGRP = 1, /* WHO is a process group ID. */ +#define PRIO_PGRP PRIO_PGRP + PRIO_USER = 2 /* WHO is a user ID. */ +#define PRIO_USER PRIO_USER +}; diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/sem.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/sem.h new file mode 100644 index 00000000..f63360b2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/sem.h @@ -0,0 +1,85 @@ +/* Copyright (C) 1995, 1996, 1997, 1998, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_SEM_H +# error "Never include directly; use instead." +#endif + +#include + +/* Flags for `semop'. */ +#define SEM_UNDO 0x1000 /* undo the operation on exit */ + +/* Commands for `semctl'. */ +#define GETPID 11 /* get sempid */ +#define GETVAL 12 /* get semval */ +#define GETALL 13 /* get all semval's */ +#define GETNCNT 14 /* get semncnt */ +#define GETZCNT 15 /* get semzcnt */ +#define SETVAL 16 /* set semval */ +#define SETALL 17 /* set all semval's */ + + +/* Data structure describing a set of semaphores. */ +struct semid_ds +{ + struct ipc_perm sem_perm; /* operation permission struct */ + __time_t sem_otime; /* last semop() time */ + __time_t sem_ctime; /* last time changed by semctl() */ + unsigned long int sem_nsems; /* number of semaphores in set */ + unsigned long int __unused1; + unsigned long int __unused2; +}; + +/* The user should define a union like the following to use it for arguments + for `semctl'. + + union semun + { + int val; <= value for SETVAL + struct semid_ds *buf; <= buffer for IPC_STAT & IPC_SET + unsigned short int *array; <= array for GETALL & SETALL + struct seminfo *__buf; <= buffer for IPC_INFO + }; + + Previous versions of this file used to define this union but this is + incorrect. One can test the macro _SEM_SEMUN_UNDEFINED to see whether + one must define the union or not. */ +#define _SEM_SEMUN_UNDEFINED 1 + +#ifdef __USE_MISC + +/* ipcs ctl cmds */ +# define SEM_STAT 18 +# define SEM_INFO 19 + +struct seminfo +{ + int semmap; + int semmni; + int semmns; + int semmnu; + int semmsl; + int semopm; + int semume; + int semusz; + int semvmx; + int semaem; +}; + +#endif /* __USE_MISC */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/setjmp.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/setjmp.h new file mode 100644 index 00000000..4471ba97 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/setjmp.h @@ -0,0 +1,87 @@ +/* Define the machine-dependent type `jmp_buf'. Alpha version. + Copyright (C) 1992,1997,2003,2005,2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _BITS_SETJMP_H +#define _BITS_SETJMP_H 1 + +#if !defined _SETJMP_H && !defined _PTHREAD_H +# error "Never include directly; use instead." +#endif + +/* The previous bits/setjmp.h had __jmp_buf defined as a structure. + We use an array of 'long int' instead, to make writing the + assembler easier. Naturally, user code should not depend on + either representation. */ + +/* + * Integer registers: + * $0 is the return value (va); + * $1-$8, $22-$25, $28 are call-used (t0-t7, t8-t11, at); + * $9-$14 we save here (s0-s5); + * $15 is the FP and we save it here (fp or s6); + * $16-$21 are input arguments (call-used) (a0-a5); + * $26 is the return PC and we save it here (ra); + * $27 is the procedure value (i.e., the address of __setjmp) (pv or t12); + * $29 is the global pointer, which the caller will reconstruct + * from the return address restored in $26 (gp); + * $30 is the stack pointer and we save it here (sp); + * $31 is always zero (zero). + * + * Floating-point registers: + * $f0 is the floating return value; + * $f1, $f10-$f15, $f22-$f30 are call-used; + * $f2-$f9 we save here; + * $f16-$21 are input args (call-used); + * $f31 is always zero. + * + * Note that even on Alpha hardware that does not have an FPU (there + * isn't such a thing currently) it is required to implement the FP + * registers. + */ + +#if defined __USE_MISC || defined __ASSEMBLY__ +# define JB_S0 0 +# define JB_S1 1 +# define JB_S2 2 +# define JB_S3 3 +# define JB_S4 4 +# define JB_S5 5 +# define JB_PC 6 +# define JB_FP 7 +# define JB_SP 8 +# define JB_F2 9 +# define JB_F3 10 +# define JB_F4 11 +# define JB_F5 12 +# define JB_F6 13 +# define JB_F7 14 +# define JB_F8 15 +# define JB_F9 16 +#endif + +#ifndef __ASSEMBLY__ +typedef long int __jmp_buf[17]; + +/* Test if longjmp to JMPBUF would unwind the frame containing a local + variable at ADDRESS. */ +#define _JMPBUF_UNWINDS(_jmpbuf, _address) \ + ((void *)(_address) < (void *)((_jmpbuf)[JB_SP])) +#endif + +#endif /* bits/setjmp.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/shm.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/shm.h new file mode 100644 index 00000000..35226c16 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/shm.h @@ -0,0 +1,101 @@ +/* Copyright (C) 1995, 1996, 1997, 2000, 2002, 2004 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_SHM_H +# error "Never include directly; use instead." +#endif + +#include + +/* Permission flag for shmget. */ +#define SHM_R 0400 /* or S_IRUGO from */ +#define SHM_W 0200 /* or S_IWUGO from */ + +/* Flags for `shmat'. */ +#define SHM_RDONLY 010000 /* attach read-only else read-write */ +#define SHM_RND 020000 /* round attach address to SHMLBA */ +#define SHM_REMAP 040000 /* take-over region on attach */ + +/* Commands for `shmctl'. */ +#define SHM_LOCK 11 /* lock segment (root only) */ +#define SHM_UNLOCK 12 /* unlock segment (root only) */ + +__BEGIN_DECLS + +/* Segment low boundary address multiple. */ +#define SHMLBA (__getpagesize ()) +extern int __getpagesize (void) __THROW __attribute__ ((__const__)); + + +/* Type to count number of attaches. */ +typedef unsigned long int shmatt_t; + +/* Data structure describing a set of semaphores. */ +struct shmid_ds + { + struct ipc_perm shm_perm; /* operation permission struct */ + size_t shm_segsz; /* size of segment in bytes */ + __time_t shm_atime; /* time of last shmat() */ + __time_t shm_dtime; /* time of last shmdt() */ + __time_t shm_ctime; /* time of last change by shmctl() */ + __pid_t shm_cpid; /* pid of creator */ + __pid_t shm_lpid; /* pid of last shmop */ + shmatt_t shm_nattch; /* number of current attaches */ + unsigned long int __unused1; + unsigned long int __unused2; + }; + +#ifdef __USE_MISC + +/* ipcs ctl commands */ +# define SHM_STAT 13 +# define SHM_INFO 14 + +/* shm_mode upper byte flags */ +# define SHM_DEST 01000 /* segment will be destroyed on last detach */ +# define SHM_LOCKED 02000 /* segment will not be swapped */ +# define SHM_HUGETLB 04000 /* segment is mapped via hugetlb */ +# define SHM_NORESERVE 010000 /* don't check for reservations */ + +struct shminfo + { + unsigned long int shmmax; + unsigned long int shmmin; + unsigned long int shmmni; + unsigned long int shmseg; + unsigned long int shmall; + unsigned long int __unused1; + unsigned long int __unused2; + unsigned long int __unused3; + unsigned long int __unused4; + }; + +struct shm_info + { + int used_ids; + unsigned long int shm_tot; /* total allocated shm */ + unsigned long int shm_rss; /* total resident shm */ + unsigned long int shm_swp; /* total swapped shm */ + unsigned long int swap_attempts; + unsigned long int swap_successes; + }; + +#endif /* __USE_MISC */ + +__END_DECLS diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/sigaction.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/sigaction.h new file mode 100644 index 00000000..61dea118 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/sigaction.h @@ -0,0 +1,65 @@ +/* The proper definitions for Linux/Alpha sigaction. + Copyright (C) 1996, 1997, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SIGNAL_H +# error "Never include directly; use instead." +#endif + +/* Structure describing the action to be taken when a signal arrives. */ +struct sigaction { +#ifdef __USE_POSIX199309 + union { + __sighandler_t sa_handler; + void (*sa_sigaction)(int, siginfo_t *, void *); + } __sigaction_handler; +# define sa_handler __sigaction_handler.sa_handler +# define sa_sigaction __sigaction_handler.sa_sigaction +#else + __sighandler_t sa_handler; +#endif + unsigned sa_flags; + sigset_t sa_mask; + /* Alpha has no sa_restorer field. */ +}; + +/* Bits in `sa_flags'. */ +#define SA_NOCLDSTOP 0x00000004 /* Don't send SIGCHLD when children stop. */ +#define SA_NOCLDWAIT 0x00000020 /* Don't create zombie on child death. */ +#define SA_SIGINFO 0x00000040 /* Invoke signal-catching function with + three arguments instead of one. */ +#if defined __USE_UNIX98 || defined __USE_MISC +# define SA_ONSTACK 0x00000001 /* Use signal stack by using `sa_restorer'. */ +# define SA_RESTART 0x00000002 /* Restart syscall on signal return. */ +# define SA_NODEFER 0x00000008 /* Don't automatically block the signal + when its handler is being executed. */ +# define SA_RESETHAND 0x00000010 /* Reset to SIG_DFL on entry to handler. */ +#endif +#ifdef __USE_MISC +# define SA_INTERRUPT 0x20000000 /* Historical no-op. */ + +/* Some aliases for the SA_ constants. */ +# define SA_NOMASK SA_NODEFER +# define SA_ONESHOT SA_RESETHAND +# define SA_STACK SA_ONSTACK +#endif + +/* Values for the HOW argument to `sigprocmask'. */ +#define SIG_BLOCK 1 /* Block signals. */ +#define SIG_UNBLOCK 2 /* Unblock signals. */ +#define SIG_SETMASK 3 /* Set the set of blocked signals. */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/sigcontextinfo.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/sigcontextinfo.h new file mode 100644 index 00000000..16c5dcbc --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/sigcontextinfo.h @@ -0,0 +1,25 @@ +/* Copyright (C) 1999, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define SIGCONTEXT int _code, struct sigcontext * +#define SIGCONTEXT_EXTRA_ARGS _code, +#define GET_PC(ctx) ((void *) (ctx)->sc_pc) +#define GET_FRAME(ctx) ((void *) (ctx)->sc_regs[15]) +#define GET_STACK(ctx) ((void *) (ctx)->sc_regs[30]) +#define CALL_SIGHANDLER(handler, signo, ctx) \ + (handler)((signo), SIGCONTEXT_EXTRA_ARGS (ctx)) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/siginfo.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/siginfo.h new file mode 100644 index 00000000..a2aacc04 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/siginfo.h @@ -0,0 +1,303 @@ +/* siginfo_t, sigevent and constants. Linux/Alpha version. + Copyright (C) 1997-2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#if !defined _SIGNAL_H && !defined __need_siginfo_t \ + && !defined __need_sigevent_t +# error "Never include this file directly. Use instead" +#endif + +#if (!defined __have_sigval_t \ + && (defined _SIGNAL_H || defined __need_siginfo_t \ + || defined __need_sigevent_t)) +# define __have_sigval_t 1 + +/* Type for data associated with a signal. */ +typedef union sigval + { + int sival_int; + void *sival_ptr; + } sigval_t; +#endif + +#if (!defined __have_siginfo_t \ + && (defined _SIGNAL_H || defined __need_siginfo_t)) +# define __have_siginfo_t 1 + +# define __SI_MAX_SIZE 128 +# define __SI_PAD_SIZE ((__SI_MAX_SIZE / sizeof (int)) - 4) + +typedef struct siginfo + { + int si_signo; /* Signal number. */ + int si_errno; /* If non-zero, an errno value associated with + this signal, as defined in . */ + int si_code; /* Signal code. */ + + union + { + int _pad[__SI_PAD_SIZE]; + + /* kill(). */ + struct + { + __pid_t si_pid; /* Sending process ID. */ + __uid_t si_uid; /* Real user ID of sending process. */ + } _kill; + + /* POSIX.1b timers. */ + struct + { + int si_tid; /* Timer ID. */ + int si_overrun; /* Overrun count. */ + sigval_t si_sigval; /* Signal value. */ + } _timer; + + /* POSIX.1b signals. */ + struct + { + __pid_t si_pid; /* Sending process ID. */ + __uid_t si_uid; /* Real user ID of sending process. */ + sigval_t si_sigval; /* Signal value. */ + } _rt; + + /* SIGCHLD. */ + struct + { + __pid_t si_pid; /* Which child. */ + __uid_t si_uid; /* Real user ID of sending process. */ + int si_status; /* Exit value or signal. */ + __clock_t si_utime; + __clock_t si_stime; + } _sigchld; + + /* SIGILL, SIGFPE, SIGSEGV, SIGBUS. */ + struct + { + void *si_addr; /* Faulting insn/memory ref. */ + } _sigfault; + + /* SIGPOLL. */ + struct + { + int si_band; /* Band event for SIGPOLL. */ + int si_fd; + } _sigpoll; + } _sifields; + } siginfo_t; + + +/* X/Open requires some more fields with fixed names. */ +# define si_pid _sifields._kill.si_pid +# define si_uid _sifields._kill.si_uid +# define si_timerid _sifields._timer.si_tid +# define si_overrun _sifields._timer.si_overrun +# define si_status _sifields._sigchld.si_status +# define si_utime _sifields._sigchld.si_utime +# define si_stime _sifields._sigchld.si_stime +# define si_value _sifields._rt.si_sigval +# define si_int _sifields._rt.si_sigval.sival_int +# define si_ptr _sifields._rt.si_sigval.sival_ptr +# define si_addr _sifields._sigfault.si_addr +# define si_band _sifields._sigpoll.si_band +# define si_fd _sifields._sigpoll.si_fd + + +/* Values for `si_code'. Positive values are reserved for kernel-generated + signals. */ +enum +{ + SI_ASYNCNL = -60, /* Sent by asynch name lookup completion. */ +# define SI_ASYNCNL SI_ASYNCNL + SI_TKILL = -6, /* Sent by tkill. */ +# define SI_TKILL SI_TKILL + SI_SIGIO, /* Sent by queued SIGIO. */ +# define SI_SIGIO SI_SIGIO + SI_ASYNCIO, /* Sent by AIO completion. */ +# define SI_ASYNCIO SI_ASYNCIO + SI_MESGQ, /* Sent by real time mesq state change. */ +# define SI_MESGQ SI_MESGQ + SI_TIMER, /* Sent by timer expiration. */ +# define SI_TIMER SI_TIMER + SI_QUEUE, /* Sent by sigqueue. */ +# define SI_QUEUE SI_QUEUE + SI_USER, /* Sent by kill, sigsend, raise. */ +# define SI_USER SI_USER + SI_KERNEL = 0x80 /* Send by kernel. */ +#define SI_KERNEL SI_KERNEL +}; + + +/* `si_code' values for SIGILL signal. */ +enum +{ + ILL_ILLOPC = 1, /* Illegal opcode. */ +# define ILL_ILLOPC ILL_ILLOPC + ILL_ILLOPN, /* Illegal operand. */ +# define ILL_ILLOPN ILL_ILLOPN + ILL_ILLADR, /* Illegal addressing mode. */ +# define ILL_ILLADR ILL_ILLADR + ILL_ILLTRP, /* Illegal trap. */ +# define ILL_ILLTRP ILL_ILLTRP + ILL_PRVOPC, /* Privileged opcode. */ +# define ILL_PRVOPC ILL_PRVOPC + ILL_PRVREG, /* Privileged register. */ +# define ILL_PRVREG ILL_PRVREG + ILL_COPROC, /* Coprocessor error. */ +# define ILL_COPROC ILL_COPROC + ILL_BADSTK /* Internal stack error. */ +# define ILL_BADSTK ILL_BADSTK +}; + +/* `si_code' values for SIGFPE signal. */ +enum +{ + FPE_INTDIV = 1, /* Integer divide by zero. */ +# define FPE_INTDIV FPE_INTDIV + FPE_INTOVF, /* Integer overflow. */ +# define FPE_INTOVF FPE_INTOVF + FPE_FLTDIV, /* Floating point divide by zero. */ +# define FPE_FLTDIV FPE_FLTDIV + FPE_FLTOVF, /* Floating point overflow. */ +# define FPE_FLTOVF FPE_FLTOVF + FPE_FLTUND, /* Floating point underflow. */ +# define FPE_FLTUND FPE_FLTUND + FPE_FLTRES, /* Floating point inexact result. */ +# define FPE_FLTRES FPE_FLTRES + FPE_FLTINV, /* Floating point invalid operation. */ +# define FPE_FLTINV FPE_FLTINV + FPE_FLTSUB /* Subscript out of range. */ +# define FPE_FLTSUB FPE_FLTSUB +}; + +/* `si_code' values for SIGSEGV signal. */ +enum +{ + SEGV_MAPERR = 1, /* Address not mapped to object. */ +# define SEGV_MAPERR SEGV_MAPERR + SEGV_ACCERR /* Invalid permissions for mapped object. */ +# define SEGV_ACCERR SEGV_ACCERR +}; + +/* `si_code' values for SIGBUS signal. */ +enum +{ + BUS_ADRALN = 1, /* Invalid address alignment. */ +# define BUS_ADRALN BUS_ADRALN + BUS_ADRERR, /* Non-existant physical address. */ +# define BUS_ADRERR BUS_ADRERR + BUS_OBJERR /* Object specific hardware error. */ +# define BUS_OBJERR BUS_OBJERR +}; + +/* `si_code' values for SIGTRAP signal. */ +enum +{ + TRAP_BRKPT = 1, /* Process breakpoint. */ +# define TRAP_BRKPT TRAP_BRKPT + TRAP_TRACE /* Process trace trap. */ +# define TRAP_TRACE TRAP_TRACE +}; + +/* `si_code' values for SIGCHLD signal. */ +enum +{ + CLD_EXITED = 1, /* Child has exited. */ +# define CLD_EXITED CLD_EXITED + CLD_KILLED, /* Child was killed. */ +# define CLD_KILLED CLD_KILLED + CLD_DUMPED, /* Child terminated abnormally. */ +# define CLD_DUMPED CLD_DUMPED + CLD_TRAPPED, /* Traced child has trapped. */ +# define CLD_TRAPPED CLD_TRAPPED + CLD_STOPPED, /* Child has stopped. */ +# define CLD_STOPPED CLD_STOPPED + CLD_CONTINUED /* Stopped child has continued. */ +# define CLD_CONTINUED CLD_CONTINUED +}; + +/* `si_code' values for SIGPOLL signal. */ +enum +{ + POLL_IN = 1, /* Data input available. */ +# define POLL_IN POLL_IN + POLL_OUT, /* Output buffers available. */ +# define POLL_OUT POLL_OUT + POLL_MSG, /* Input message available. */ +# define POLL_MSG POLL_MSG + POLL_ERR, /* I/O error. */ +# define POLL_ERR POLL_ERR + POLL_PRI, /* High priority input available. */ +# define POLL_PRI POLL_PRI + POLL_HUP /* Device disconnected. */ +# define POLL_HUP POLL_HUP +}; + +# undef __need_siginfo_t +#endif /* !have siginfo_t && (have _SIGNAL_H || need siginfo_t). */ + + +#if (defined _SIGNAL_H || defined __need_sigevent_t) \ + && !defined __have_sigevent_t +# define __have_sigevent_t 1 + +/* Structure to transport application-defined values with signals. */ +# define __SIGEV_MAX_SIZE 64 +# define __SIGEV_PAD_SIZE ((__SIGEV_MAX_SIZE / sizeof (int)) - 4) + +typedef struct sigevent + { + sigval_t sigev_value; + int sigev_signo; + int sigev_notify; + + union + { + int _pad[__SIGEV_PAD_SIZE]; + + /* When SIGEV_SIGNAL and SIGEV_THREAD_ID set, LWP ID of the + thread to receive the signal. */ + __pid_t _tid; + + struct + { + void (*_function) (sigval_t); /* Function to start. */ + void *_attribute; /* Really pthread_attr_t. */ + } _sigev_thread; + } _sigev_un; + } sigevent_t; + +/* POSIX names to access some of the members. */ +# define sigev_notify_function _sigev_un._sigev_thread._function +# define sigev_notify_attributes _sigev_un._sigev_thread._attribute + +/* `sigev_notify' values. */ +enum +{ + SIGEV_SIGNAL = 0, /* Notify via signal. */ +# define SIGEV_SIGNAL SIGEV_SIGNAL + SIGEV_NONE, /* Other notification: meaningless. */ +# define SIGEV_NONE SIGEV_NONE + SIGEV_THREAD, /* Deliver via thread creation. */ +# define SIGEV_THREAD SIGEV_THREAD + + SIGEV_THREAD_ID = 4 /* Send signal to specific thread. */ +#define SIGEV_THREAD_ID SIGEV_THREAD_ID +}; + +#endif /* have _SIGNAL_H. */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/signum.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/signum.h new file mode 100644 index 00000000..46dca8c0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/signum.h @@ -0,0 +1,63 @@ +/* Signal number definitions. Linux/Alpha version. + Copyright (C) 1996, 1997, 1998, 1999, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifdef _SIGNAL_H + +/* + * Linux/AXP has different signal numbers that Linux/i386: I'm trying + * to make it OSF/1 binary compatible, at least for normal binaries. + */ +#define SIGHUP 1 +#define SIGINT 2 +#define SIGQUIT 3 +#define SIGILL 4 +#define SIGTRAP 5 +#define SIGABRT 6 +#define SIGEMT 7 +#define SIGFPE 8 +#define SIGKILL 9 +#define SIGBUS 10 +#define SIGSEGV 11 +#define SIGSYS 12 +#define SIGPIPE 13 +#define SIGALRM 14 +#define SIGTERM 15 +#define SIGURG 16 +#define SIGSTOP 17 +#define SIGTSTP 18 +#define SIGCONT 19 +#define SIGCHLD 20 +#define SIGCLD SIGCHLD +#define SIGTTIN 21 +#define SIGTTOU 22 +#define SIGIO 23 +#define SIGXCPU 24 +#define SIGXFSZ 25 +#define SIGVTALRM 26 +#define SIGPROF 27 +#define SIGWINCH 28 +#define SIGINFO 29 +#define SIGUSR1 30 +#define SIGUSR2 31 + +#define SIGPOLL SIGIO +#define SIGPWR SIGINFO +#define SIGIOT SIGABRT + +#endif /* included. */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/sigstack.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/sigstack.h new file mode 100644 index 00000000..7faaf98d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/sigstack.h @@ -0,0 +1,55 @@ +/* sigstack, sigaltstack definitions. + Copyright (C) 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SIGNAL_H +# error "Never include this file directly. Use instead" +#endif + + +/* Structure describing a signal stack (obsolete). */ +struct sigstack + { + __ptr_t ss_sp; /* Signal stack pointer. */ + int ss_onstack; /* Nonzero if executing on this stack. */ + }; + + +/* Possible values for `ss_flags.'. */ +enum +{ + SS_ONSTACK = 1, +#define SS_ONSTACK SS_ONSTACK + SS_DISABLE +#define SS_DISABLE SS_DISABLE +}; + +/* Minimum stack size for a signal handler. */ +#define MINSIGSTKSZ 4096 + +/* System default stack size. */ +#define SIGSTKSZ 16384 + + +/* Alternate, preferred interface. */ +typedef struct sigaltstack + { + __ptr_t ss_sp; + int ss_flags; + size_t ss_size; + } stack_t; diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/stackinfo.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/stackinfo.h new file mode 100644 index 00000000..0a281bd4 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/stackinfo.h @@ -0,0 +1,28 @@ +/* Copyright (C) 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This file contains a bit of information about the stack allocation + of the processor. */ + +#ifndef _STACKINFO_H +#define _STACKINFO_H 1 + +/* On Alpha the stack grows down. */ +#define _STACK_GROWS_DOWN 1 + +#endif /* stackinfo.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/stat.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/stat.h new file mode 100644 index 00000000..6cb16485 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/stat.h @@ -0,0 +1,156 @@ +/* Copyright (C) 1996,1997,1998,1999,2000,2001,2004 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_STAT_H +# error "Never include directly; use instead." +#endif + +/* Versions of the `struct stat' data structure. */ +#define _STAT_VER_KERNEL 0 +#define _STAT_VER_GLIBC2 1 +#define _STAT_VER_GLIBC2_1 2 +#define _STAT_VER_KERNEL64 3 +#define _STAT_VER_GLIBC2_3_4 3 +#define _STAT_VER _STAT_VER_GLIBC2_3_4 + +/* Versions of the `xmknod' interface. */ +#define _MKNOD_VER_LINUX 0 + + +/* Nanosecond resolution timestamps are stored in a format equivalent to + 'struct timespec'. This is the type used whenever possible but the + Unix namespace rules do not allow the identifier 'timespec' to appear + in the header. Therefore we have to handle the use of + this header in strictly standard-compliant sources special. + + Use neat tidy anonymous unions and structures when possible. */ + +#ifdef __USE_MISC +# if __GNUC_PREREQ(3,3) +# define __ST_TIME(X) \ + __extension__ union { \ + struct timespec st_##X##tim; \ + struct { \ + __time_t st_##X##time; \ + unsigned long st_##X##timensec; \ + }; \ + } +# else +# define __ST_TIME(X) struct timespec st_##X##tim +# define st_atime st_atim.tv_sec +# define st_mtime st_mtim.tv_sec +# define st_ctime st_ctim.tv_sec +# endif +#else +# define __ST_TIME(X) \ + __time_t st_##X##time; \ + unsigned long st_##X##timensec +#endif + + +struct stat + { + __dev_t st_dev; /* Device. */ +#ifdef __USE_FILE_OFFSET64 + __ino64_t st_ino; /* File serial number. */ +#else + __ino_t st_ino; /* File serial number. */ + int __pad0; /* 64-bit st_ino. */ +#endif + __dev_t st_rdev; /* Device number, if device. */ + __off_t st_size; /* Size of file, in bytes. */ +#ifdef __USE_FILE_OFFSET64 + __blkcnt64_t st_blocks; /* Nr. 512-byte blocks allocated. */ +#else + __blkcnt_t st_blocks; /* Nr. 512-byte blocks allocated. */ + int __pad1; /* 64-bit st_blocks. */ +#endif + __mode_t st_mode; /* File mode. */ + __uid_t st_uid; /* User ID of the file's owner. */ + __gid_t st_gid; /* Group ID of the file's group.*/ + __blksize_t st_blksize; /* Optimal block size for I/O. */ + __nlink_t st_nlink; /* Link count. */ + int __pad2; /* Real padding. */ + __ST_TIME(a); /* Time of last access. */ + __ST_TIME(m); /* Time of last modification. */ + __ST_TIME(c); /* Time of last status change. */ + long __unused[3]; + }; + +#ifdef __USE_LARGEFILE64 +/* Note stat64 is the same shape as stat. */ +struct stat64 + { + __dev_t st_dev; /* Device. */ + __ino64_t st_ino; /* File serial number. */ + __dev_t st_rdev; /* Device number, if device. */ + __off_t st_size; /* Size of file, in bytes. */ + __blkcnt64_t st_blocks; /* Nr. 512-byte blocks allocated. */ + __mode_t st_mode; /* File mode. */ + __uid_t st_uid; /* User ID of the file's owner. */ + __gid_t st_gid; /* Group ID of the file's group.*/ + __blksize_t st_blksize; /* Optimal block size for I/O. */ + __nlink_t st_nlink; /* Link count. */ + int __pad0; /* Real padding. */ + __ST_TIME(a); /* Time of last access. */ + __ST_TIME(m); /* Time of last modification. */ + __ST_TIME(c); /* Time of last status change. */ + long __unused[3]; + }; +#endif + +#undef __ST_TIME + +/* Tell code we have these members. */ +#define _STATBUF_ST_BLKSIZE +#define _STATBUF_ST_RDEV +#define _STATBUF_ST_NSEC + +/* Encoding of the file mode. */ + +#define __S_IFMT 0170000 /* These bits determine file type. */ + +/* File types. */ +#define __S_IFDIR 0040000 /* Directory. */ +#define __S_IFCHR 0020000 /* Character device. */ +#define __S_IFBLK 0060000 /* Block device. */ +#define __S_IFREG 0100000 /* Regular file. */ +#define __S_IFIFO 0010000 /* FIFO. */ +#define __S_IFLNK 0120000 /* Symbolic link. */ +#define __S_IFSOCK 0140000 /* Socket. */ + +/* POSIX.1b objects. Note that these macros always evaluate to zero. But + they do it by enforcing the correct use of the macros. */ +#define __S_TYPEISMQ(buf) ((buf)->st_mode - (buf)->st_mode) +#define __S_TYPEISSEM(buf) ((buf)->st_mode - (buf)->st_mode) +#define __S_TYPEISSHM(buf) ((buf)->st_mode - (buf)->st_mode) + +/* Protection bits. */ + +#define __S_ISUID 04000 /* Set user ID on execution. */ +#define __S_ISGID 02000 /* Set group ID on execution. */ +#define __S_ISVTX 01000 /* Save swapped text after use (sticky). */ +#define __S_IREAD 0400 /* Read by owner. */ +#define __S_IWRITE 0200 /* Write by owner. */ +#define __S_IEXEC 0100 /* Execute by owner. */ + +#ifdef __USE_ATFILE +# define UTIME_NOW ((1l << 30) - 1l) +# define UTIME_OMIT ((1l << 30) - 2l) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/statfs.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/statfs.h new file mode 100644 index 00000000..d838e6bf --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/statfs.h @@ -0,0 +1,67 @@ +/* Copyright (C) 1997, 1998, 2000, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_STATFS_H +# error "Never include directly; use instead." +#endif + +#include /* for __fsid_t and __fsblkcnt_t. */ + +struct statfs + { + int f_type; + int f_bsize; +#ifndef __USE_FILE_OFFSET64 + __fsblkcnt_t f_blocks; + __fsblkcnt_t f_bfree; + __fsblkcnt_t f_bavail; + __fsfilcnt_t f_files; + __fsfilcnt_t f_ffree; +#else + __fsblkcnt64_t f_blocks; + __fsblkcnt64_t f_bfree; + __fsblkcnt64_t f_bavail; + __fsfilcnt64_t f_files; + __fsfilcnt64_t f_ffree; +#endif + __fsid_t f_fsid; + int f_namelen; + int f_frsize; + int f_spare[5]; + }; + +#ifdef __USE_LARGEFILE64 +struct statfs64 + { + int f_type; + int f_bsize; + __fsblkcnt64_t f_blocks; + __fsblkcnt64_t f_bfree; + __fsblkcnt64_t f_bavail; + __fsfilcnt64_t f_files; + __fsfilcnt64_t f_ffree; + __fsid_t f_fsid; + int f_namelen; + int f_frsize; + int f_spare[5]; + }; +#endif + +/* Tell code we have this member. */ +#define _STATFS_F_NAMELEN +#define _STATFS_F_FRSIZE diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/statvfs.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/statvfs.h new file mode 100644 index 00000000..d37d0ffc --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/statvfs.h @@ -0,0 +1,96 @@ +/* Copyright (C) 1997, 1998, 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_STATVFS_H +# error "Never include directly; use instead." +#endif + +#include /* For __fsblkcnt_t and __fsfilcnt_t. */ + +struct statvfs + { + unsigned long int f_bsize; + unsigned long int f_frsize; +#ifndef __USE_FILE_OFFSET64 + __fsblkcnt_t f_blocks; + __fsblkcnt_t f_bfree; + __fsblkcnt_t f_bavail; + __fsfilcnt_t f_files; + __fsfilcnt_t f_ffree; + __fsfilcnt_t f_favail; +#else + __fsblkcnt64_t f_blocks; + __fsblkcnt64_t f_bfree; + __fsblkcnt64_t f_bavail; + __fsfilcnt64_t f_files; + __fsfilcnt64_t f_ffree; + __fsfilcnt64_t f_favail; +#endif + unsigned long int f_fsid; + unsigned long int f_flag; + unsigned long int f_namemax; + int __f_spare[6]; + }; + +#ifdef __USE_LARGEFILE64 +struct statvfs64 + { + unsigned long int f_bsize; + unsigned long int f_frsize; + __fsblkcnt64_t f_blocks; + __fsblkcnt64_t f_bfree; + __fsblkcnt64_t f_bavail; + __fsfilcnt64_t f_files; + __fsfilcnt64_t f_ffree; + __fsfilcnt64_t f_favail; + unsigned long int f_fsid; + unsigned long int f_flag; + unsigned long int f_namemax; + int __f_spare[6]; + }; +#endif + +/* Definitions for the flag in `f_flag'. These definitions should be + kept in sync which the definitions in . */ +enum +{ + ST_RDONLY = 1, /* Mount read-only. */ +#define ST_RDONLY ST_RDONLY + ST_NOSUID = 2, /* Ignore suid and sgid bits. */ +#define ST_NOSUID ST_NOSUID +#ifdef __USE_GNU + ST_NODEV = 4, /* Disallow access to device special files. */ +# define ST_NODEV ST_NODEV + ST_NOEXEC = 8, /* Disallow program execution. */ +# define ST_NOEXEC ST_NOEXEC + ST_SYNCHRONOUS = 16, /* Writes are synced at once. */ +# define ST_SYNCHRONOUS ST_SYNCHRONOUS + ST_MANDLOCK = 64, /* Allow mandatory locks on an FS. */ +# define ST_MANDLOCK ST_MANDLOCK + ST_WRITE = 128, /* Write on file/directory/symlink. */ +# define ST_WRITE ST_WRITE + ST_APPEND = 256, /* Append-only file. */ +# define ST_APPEND ST_APPEND + ST_IMMUTABLE = 512, /* Immutable file. */ +# define ST_IMMUTABLE ST_IMMUTABLE + ST_NOATIME = 1024, /* Do not update access times. */ +# define ST_NOATIME ST_NOATIME + ST_NODIRATIME /* Do not update directory access times. */ +# define ST_NODIRATIME ST_NODIRATIME +#endif /* Use GNU. */ +}; diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/syscalls.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/syscalls.h new file mode 100644 index 00000000..ee56788a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/syscalls.h @@ -0,0 +1,257 @@ +/* Copyright (C) 1992, 1995, 1996, 2000, 2003, 2004, 2006 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Brendan Kehoe (brendan@zen.org). + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _BITS_SYSCALLS_H +#define _BITS_SYSCALLS_H +#ifndef _SYSCALL_H +# error "Never use directly; include instead." +#endif + +#ifndef __ASSEMBLER__ + +#define INLINE_SYSCALL_NCS(name, nr, args...) \ +({ \ + long _sc_ret, _sc_err; \ + inline_syscall##nr(name, args); \ + if (__builtin_expect (_sc_err, 0)) \ + { \ + __set_errno (_sc_ret); \ + _sc_ret = -1L; \ + } \ + _sc_ret; \ +}) + +#define INTERNAL_SYSCALL_NCS(name, err_out, nr, args...) \ +({ \ + long _sc_ret, _sc_err; \ + inline_syscall##nr(name, args); \ + err_out = _sc_err; \ + _sc_ret; \ +}) + +#define INTERNAL_SYSCALL_DECL(err) long int err +#define INTERNAL_SYSCALL_ERROR_P(val, err) err +#define INTERNAL_SYSCALL_ERRNO(val, err) val + +#define inline_syscall_clobbers \ + "$1", "$2", "$3", "$4", "$5", "$6", "$7", "$8", \ + "$22", "$23", "$24", "$25", "$27", "$28", "memory" + +/* If TLS is in use, we have a conflict between the PAL_rduniq primitive, + as modeled within GCC, and explicit use of the R0 register. If we use + the register via the asm, the scheduler may place the PAL_rduniq insn + before we've copied the data from R0 into _sc_ret. If this happens + we'll get a reload abort, since R0 is live at the same time it is + needed for the PAL_rduniq. + + Solve this by using the "v" constraint instead of an asm for the syscall + output. We don't do this unconditionally to allow compilation with + older compilers. */ + +#ifdef HAVE___THREAD +#define inline_syscall_r0_asm +#define inline_syscall_r0_out_constraint "=v" +#else +#define inline_syscall_r0_asm __asm__("$0") +#define inline_syscall_r0_out_constraint "=r" +#endif + +/* It is moderately important optimization-wise to limit the lifetime + of the hard-register variables as much as possible. Thus we copy + in/out as close to the asm as possible. */ + +#define inline_syscall0(name, args...) \ +{ \ + register long _sc_0 inline_syscall_r0_asm; \ + register long _sc_19 __asm__("$19"); \ + \ + _sc_0 = name; \ + __asm__ __volatile__ \ + ("callsys # %0 %1 <= %2" \ + : inline_syscall_r0_out_constraint (_sc_0), \ + "=r"(_sc_19) \ + : "0"(_sc_0) \ + : inline_syscall_clobbers, \ + "$16", "$17", "$18", "$20", "$21"); \ + _sc_ret = _sc_0, _sc_err = _sc_19; \ +} + +#define inline_syscall1(name,arg1) \ +{ \ + register long _sc_0 inline_syscall_r0_asm; \ + register long _sc_16 __asm__("$16"); \ + register long _sc_19 __asm__("$19"); \ + register long _tmp_16 = (long) (arg1); \ + \ + _sc_0 = name; \ + _sc_16 = _tmp_16; \ + __asm__ __volatile__ \ + ("callsys # %0 %1 <= %2 %3" \ + : inline_syscall_r0_out_constraint (_sc_0), \ + "=r"(_sc_19), "=r"(_sc_16) \ + : "0"(_sc_0), "2"(_sc_16) \ + : inline_syscall_clobbers, \ + "$17", "$18", "$20", "$21"); \ + _sc_ret = _sc_0, _sc_err = _sc_19; \ +} + +#define inline_syscall2(name,arg1,arg2) \ +{ \ + register long _sc_0 inline_syscall_r0_asm; \ + register long _sc_16 __asm__("$16"); \ + register long _sc_17 __asm__("$17"); \ + register long _sc_19 __asm__("$19"); \ + register long _tmp_16 = (long) (arg1); \ + register long _tmp_17 = (long) (arg2); \ + \ + _sc_0 = name; \ + _sc_16 = _tmp_16; \ + _sc_17 = _tmp_17; \ + __asm__ __volatile__ \ + ("callsys # %0 %1 <= %2 %3 %4" \ + : inline_syscall_r0_out_constraint (_sc_0), \ + "=r"(_sc_19), "=r"(_sc_16), "=r"(_sc_17) \ + : "0"(_sc_0), "2"(_sc_16), "3"(_sc_17) \ + : inline_syscall_clobbers, \ + "$18", "$20", "$21"); \ + _sc_ret = _sc_0, _sc_err = _sc_19; \ +} + +#define inline_syscall3(name,arg1,arg2,arg3) \ +{ \ + register long _sc_0 inline_syscall_r0_asm; \ + register long _sc_16 __asm__("$16"); \ + register long _sc_17 __asm__("$17"); \ + register long _sc_18 __asm__("$18"); \ + register long _sc_19 __asm__("$19"); \ + register long _tmp_16 = (long) (arg1); \ + register long _tmp_17 = (long) (arg2); \ + register long _tmp_18 = (long) (arg3); \ + \ + _sc_0 = name; \ + _sc_16 = _tmp_16; \ + _sc_17 = _tmp_17; \ + _sc_18 = _tmp_18; \ + __asm__ __volatile__ \ + ("callsys # %0 %1 <= %2 %3 %4 %5" \ + : inline_syscall_r0_out_constraint (_sc_0), \ + "=r"(_sc_19), "=r"(_sc_16), "=r"(_sc_17), \ + "=r"(_sc_18) \ + : "0"(_sc_0), "2"(_sc_16), "3"(_sc_17), \ + "4"(_sc_18) \ + : inline_syscall_clobbers, "$20", "$21"); \ + _sc_ret = _sc_0, _sc_err = _sc_19; \ +} + +#define inline_syscall4(name,arg1,arg2,arg3,arg4) \ +{ \ + register long _sc_0 inline_syscall_r0_asm; \ + register long _sc_16 __asm__("$16"); \ + register long _sc_17 __asm__("$17"); \ + register long _sc_18 __asm__("$18"); \ + register long _sc_19 __asm__("$19"); \ + register long _tmp_16 = (long) (arg1); \ + register long _tmp_17 = (long) (arg2); \ + register long _tmp_18 = (long) (arg3); \ + register long _tmp_19 = (long) (arg4); \ + \ + _sc_0 = name; \ + _sc_16 = _tmp_16; \ + _sc_17 = _tmp_17; \ + _sc_18 = _tmp_18; \ + _sc_19 = _tmp_19; \ + __asm__ __volatile__ \ + ("callsys # %0 %1 <= %2 %3 %4 %5 %6" \ + : inline_syscall_r0_out_constraint (_sc_0), \ + "=r"(_sc_19), "=r"(_sc_16), "=r"(_sc_17), \ + "=r"(_sc_18) \ + : "0"(_sc_0), "2"(_sc_16), "3"(_sc_17), \ + "4"(_sc_18), "1"(_sc_19) \ + : inline_syscall_clobbers, "$20", "$21"); \ + _sc_ret = _sc_0, _sc_err = _sc_19; \ +} + +#define inline_syscall5(name,arg1,arg2,arg3,arg4,arg5) \ +{ \ + register long _sc_0 inline_syscall_r0_asm; \ + register long _sc_16 __asm__("$16"); \ + register long _sc_17 __asm__("$17"); \ + register long _sc_18 __asm__("$18"); \ + register long _sc_19 __asm__("$19"); \ + register long _sc_20 __asm__("$20"); \ + register long _tmp_16 = (long) (arg1); \ + register long _tmp_17 = (long) (arg2); \ + register long _tmp_18 = (long) (arg3); \ + register long _tmp_19 = (long) (arg4); \ + register long _tmp_20 = (long) (arg5); \ + \ + _sc_0 = name; \ + _sc_16 = _tmp_16; \ + _sc_17 = _tmp_17; \ + _sc_18 = _tmp_18; \ + _sc_19 = _tmp_19; \ + _sc_20 = _tmp_20; \ + __asm__ __volatile__ \ + ("callsys # %0 %1 <= %2 %3 %4 %5 %6 %7" \ + : inline_syscall_r0_out_constraint (_sc_0), \ + "=r"(_sc_19), "=r"(_sc_16), "=r"(_sc_17), \ + "=r"(_sc_18), "=r"(_sc_20) \ + : "0"(_sc_0), "2"(_sc_16), "3"(_sc_17), \ + "4"(_sc_18), "1"(_sc_19), "5"(_sc_20) \ + : inline_syscall_clobbers, "$21"); \ + _sc_ret = _sc_0, _sc_err = _sc_19; \ +} + +#define inline_syscall6(name,arg1,arg2,arg3,arg4,arg5,arg6) \ +{ \ + register long _sc_0 inline_syscall_r0_asm; \ + register long _sc_16 __asm__("$16"); \ + register long _sc_17 __asm__("$17"); \ + register long _sc_18 __asm__("$18"); \ + register long _sc_19 __asm__("$19"); \ + register long _sc_20 __asm__("$20"); \ + register long _sc_21 __asm__("$21"); \ + register long _tmp_16 = (long) (arg1); \ + register long _tmp_17 = (long) (arg2); \ + register long _tmp_18 = (long) (arg3); \ + register long _tmp_19 = (long) (arg4); \ + register long _tmp_20 = (long) (arg5); \ + register long _tmp_21 = (long) (arg6); \ + \ + _sc_0 = name; \ + _sc_16 = _tmp_16; \ + _sc_17 = _tmp_17; \ + _sc_18 = _tmp_18; \ + _sc_19 = _tmp_19; \ + _sc_20 = _tmp_20; \ + _sc_21 = _tmp_21; \ + __asm__ __volatile__ \ + ("callsys # %0 %1 <= %2 %3 %4 %5 %6 %7 %8" \ + : inline_syscall_r0_out_constraint (_sc_0), \ + "=r"(_sc_19), "=r"(_sc_16), "=r"(_sc_17), \ + "=r"(_sc_18), "=r"(_sc_20), "=r"(_sc_21) \ + : "0"(_sc_0), "2"(_sc_16), "3"(_sc_17), "4"(_sc_18), \ + "1"(_sc_19), "5"(_sc_20), "6"(_sc_21) \ + : inline_syscall_clobbers); \ + _sc_ret = _sc_0, _sc_err = _sc_19; \ +} + +#endif /* __ASSEMBLER__ */ +#endif /* _BITS_SYSCALLS_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/termios.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/termios.h new file mode 100644 index 00000000..966ccf94 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/termios.h @@ -0,0 +1,226 @@ +/* termios type and macro definitions. Linux version. + Copyright (C) 1993, 1994, 1995, 1996, 1997, 1999, 2003, 2005 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _TERMIOS_H +# error "Never include directly; use instead." +#endif + +typedef unsigned char cc_t; +typedef unsigned int speed_t; +typedef unsigned int tcflag_t; + +#define NCCS 32 +struct termios + { + tcflag_t c_iflag; /* input mode flags */ + tcflag_t c_oflag; /* output mode flags */ + tcflag_t c_cflag; /* control mode flags */ + tcflag_t c_lflag; /* local mode flags */ + cc_t c_cc[NCCS]; /* control characters */ + cc_t c_line; /* line discipline (== c_cc[33]) */ + speed_t c_ispeed; /* input speed */ + speed_t c_ospeed; /* output speed */ +#define _HAVE_STRUCT_TERMIOS_C_ISPEED 1 +#define _HAVE_STRUCT_TERMIOS_C_OSPEED 1 + }; + +/* c_cc characters */ +#define VEOF 0 +#define VEOL 1 +#define VEOL2 2 +#define VERASE 3 +#define VWERASE 4 +#define VKILL 5 +#define VREPRINT 6 +#define VSWTC 7 +#define VINTR 8 +#define VQUIT 9 +#define VSUSP 10 +#define VSTART 12 +#define VSTOP 13 +#define VLNEXT 14 +#define VDISCARD 15 +#define VMIN 16 +#define VTIME 17 + +/* c_iflag bits */ +#define IGNBRK 0000001 +#define BRKINT 0000002 +#define IGNPAR 0000004 +#define PARMRK 0000010 +#define INPCK 0000020 +#define ISTRIP 0000040 +#define INLCR 0000100 +#define IGNCR 0000200 +#define ICRNL 0000400 +#define IXON 0001000 +#define IXOFF 0002000 +#ifdef __USE_BSD + /* POSIX.1 doesn't want these... */ +# define IXANY 0004000 +# define IUCLC 0010000 +# define IMAXBEL 0020000 +# define IUTF8 0040000 +#endif + +/* c_oflag bits */ +#define OPOST 0000001 +#define ONLCR 0000002 +#define OLCUC 0000004 + +#define OCRNL 0000010 +#define ONOCR 0000020 +#define ONLRET 0000040 + +#define OFILL 00000100 +#define OFDEL 00000200 +#if defined __USE_MISC || defined __USE_XOPEN +# define NLDLY 00001400 +# define NL0 00000000 +# define NL1 00000400 +# define NL2 00001000 +# define NL3 00001400 +# define TABDLY 00006000 +# define TAB0 00000000 +# define TAB1 00002000 +# define TAB2 00004000 +# define TAB3 00006000 +# define CRDLY 00030000 +# define CR0 00000000 +# define CR1 00010000 +# define CR2 00020000 +# define CR3 00030000 +# define FFDLY 00040000 +# define FF0 00000000 +# define FF1 00040000 +# define BSDLY 00100000 +# define BS0 00000000 +# define BS1 00100000 +#endif + +#define VTDLY 00200000 +#define VT0 00000000 +#define VT1 00200000 + +#ifdef __USE_MISC +# define XTABS 01000000 /* Hmm.. Linux/i386 considers this part of TABDLY.. */ +#endif + +/* c_cflag bit meaning */ +#ifdef __USE_MISC +# define CBAUD 0000037 +#endif +#define B0 0000000 /* hang up */ +#define B50 0000001 +#define B75 0000002 +#define B110 0000003 +#define B134 0000004 +#define B150 0000005 +#define B200 0000006 +#define B300 0000007 +#define B600 0000010 +#define B1200 0000011 +#define B1800 0000012 +#define B2400 0000013 +#define B4800 0000014 +#define B9600 0000015 +#define B19200 0000016 +#define B38400 0000017 +#ifdef __USE_MISC +# define EXTA B19200 +# define EXTB B38400 +# define CBAUDEX 0000000 +#endif +#define B57600 00020 +#define B115200 00021 +#define B230400 00022 +#define B460800 00023 +#define B500000 00024 +#define B576000 00025 +#define B921600 00026 +#define B1000000 00027 +#define B1152000 00030 +#define B1500000 00031 +#define B2000000 00032 +#define B2500000 00033 +#define B3000000 00034 +#define B3500000 00035 +#define B4000000 00036 + +#define __MAX_BAUD B4000000 + +#define CSIZE 00001400 +#define CS5 00000000 +#define CS6 00000400 +#define CS7 00001000 +#define CS8 00001400 + +#define CSTOPB 00002000 +#define CREAD 00004000 +#define PARENB 00010000 +#define PARODD 00020000 +#define HUPCL 00040000 + +#define CLOCAL 00100000 +#ifdef __USE_MISC +# define CMSPAR 010000000000 /* mark or space (stick) parity */ +# define CRTSCTS 020000000000 /* flow control */ +#endif + +/* c_lflag bits */ +#define ISIG 0x00000080 +#define ICANON 0x00000100 +#if defined __USE_MISC || defined __USE_XOPEN +# define XCASE 0x00004000 +#endif +#define ECHO 0x00000008 +#define ECHOE 0x00000002 +#define ECHOK 0x00000004 +#define ECHONL 0x00000010 +#define NOFLSH 0x80000000 +#define TOSTOP 0x00400000 +#ifdef __USE_MISC +# define ECHOCTL 0x00000040 +# define ECHOPRT 0x00000020 +# define ECHOKE 0x00000001 +# define FLUSHO 0x00800000 +# define PENDIN 0x20000000 +#endif +#define IEXTEN 0x00000400 + +/* Values for the ACTION argument to `tcflow'. */ +#define TCOOFF 0 +#define TCOON 1 +#define TCIOFF 2 +#define TCION 3 + +/* Values for the QUEUE_SELECTOR argument to `tcflush'. */ +#define TCIFLUSH 0 +#define TCOFLUSH 1 +#define TCIOFLUSH 2 + +/* Values for the OPTIONAL_ACTIONS argument to `tcsetattr'. */ +#define TCSANOW 0 +#define TCSADRAIN 1 +#define TCSAFLUSH 2 + + +#define _IOT_termios /* Hurd ioctl type field. */ \ + _IOT (_IOTS (cflag_t), 4, _IOTS (cc_t), NCCS, _IOTS (speed_t), 2) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/typesizes.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/typesizes.h new file mode 100644 index 00000000..201585af --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/typesizes.h @@ -0,0 +1,66 @@ +/* bits/typesizes.h -- underlying types for *_t. Linux/Alpha version. + Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _BITS_TYPES_H +# error "Never include directly; use instead." +#endif + +#ifndef _BITS_TYPESIZES_H +#define _BITS_TYPESIZES_H 1 + +/* See for the meaning of these macros. This file exists so + that need not vary across different GNU platforms. */ + +#define __DEV_T_TYPE __U64_TYPE +#define __UID_T_TYPE __U32_TYPE +#define __GID_T_TYPE __U32_TYPE +#define __INO_T_TYPE __U32_TYPE +#define __INO64_T_TYPE __U64_TYPE +#define __MODE_T_TYPE __U32_TYPE +#define __NLINK_T_TYPE __U32_TYPE +#define __OFF_T_TYPE __SLONGWORD_TYPE +#define __OFF64_T_TYPE __S64_TYPE +#define __PID_T_TYPE __S32_TYPE +#define __RLIM_T_TYPE __ULONGWORD_TYPE +#define __RLIM64_T_TYPE __U64_TYPE +#define __BLKCNT_T_TYPE __U32_TYPE +#define __BLKCNT64_T_TYPE __U64_TYPE +#define __FSBLKCNT_T_TYPE __S32_TYPE +#define __FSBLKCNT64_T_TYPE __S64_TYPE +#define __FSFILCNT_T_TYPE __U32_TYPE +#define __FSFILCNT64_T_TYPE __U64_TYPE +#define __ID_T_TYPE __U32_TYPE +#define __CLOCK_T_TYPE __SLONGWORD_TYPE +#define __TIME_T_TYPE __SLONGWORD_TYPE +#define __USECONDS_T_TYPE __U32_TYPE +#define __SUSECONDS_T_TYPE __S64_TYPE +#define __DADDR_T_TYPE __S32_TYPE +#define __SWBLK_T_TYPE __SLONGWORD_TYPE +#define __KEY_T_TYPE __S32_TYPE +#define __CLOCKID_T_TYPE __S32_TYPE +#define __TIMER_T_TYPE void * +#define __BLKSIZE_T_TYPE __U32_TYPE +#define __FSID_T_TYPE struct { int __val[2]; } +#define __SSIZE_T_TYPE __SWORD_TYPE + +/* Number of descriptors that can fit in an `fd_set'. */ +#define __FD_SETSIZE 1024 + + +#endif /* bits/typesizes.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/uClibc_arch_features.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/uClibc_arch_features.h new file mode 100644 index 00000000..e106d12f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/uClibc_arch_features.h @@ -0,0 +1,47 @@ +/* + * Track misc arch-specific features that aren't config options + */ + +#ifndef _BITS_UCLIBC_ARCH_FEATURES_H +#define _BITS_UCLIBC_ARCH_FEATURES_H + +/* instruction used when calling abort() to kill yourself */ +#define __UCLIBC_ABORT_INSTRUCTION__ "call_pal 0" + +/* can your target use syscall6() for mmap ? */ +#define __UCLIBC_MMAP_HAS_6_ARGS__ + +/* does your target use syscall4() for truncate64 ? (32bit arches only) */ +#undef __UCLIBC_TRUNCATE64_HAS_4_ARGS__ + +/* does your target have a broken create_module() ? */ +#define __UCLIBC_SLIGHTLY_BROKEN_CREATE_MODULE__ + +/* does your target have to worry about older [gs]etrlimit() ? */ +#undef __UCLIBC_HANDLE_OLDER_RLIMIT__ + +/* does your target have an asm .set ? */ +#undef __UCLIBC_HAVE_ASM_SET_DIRECTIVE__ + +/* define if target doesn't like .global */ +#undef __UCLIBC_ASM_GLOBAL_DIRECTIVE__ + +/* define if target supports .weak */ +#define __UCLIBC_HAVE_ASM_WEAK_DIRECTIVE__ + +/* define if target supports .weakext */ +#undef __UCLIBC_HAVE_ASM_WEAKEXT_DIRECTIVE__ + +/* needed probably only for ppc64 */ +#undef __UCLIBC_HAVE_ASM_GLOBAL_DOT_NAME__ + +/* define if target supports CFI pseudo ops */ +#undef __UCLIBC_HAVE_ASM_CFI_DIRECTIVES__ + +/* define if target supports IEEE signed zero floats */ +#define __UCLIBC_HAVE_SIGNED_ZERO__ + +/* only weird assemblers generally need this */ +#undef __UCLIBC_ASM_LINE_SEP__ + +#endif /* _BITS_UCLIBC_ARCH_FEATURES_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/uClibc_clk_tck.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/uClibc_clk_tck.h new file mode 100644 index 00000000..f7cd69ae --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/uClibc_clk_tck.h @@ -0,0 +1,8 @@ +/* Follow glibc's example and use 1024 for CLK_TCK to implement sysconf and + * clock.c instead of the normal default of 100. + * + * WARNING: It is assumed that this is a constant integer value usable in + * preprocessor conditionals!!! + */ + +#define __UCLIBC_CLK_TCK_CONST 1024 diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/uClibc_page.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/uClibc_page.h new file mode 100644 index 00000000..8219a19d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/uClibc_page.h @@ -0,0 +1,28 @@ +/* Copyright (C) 2004 Erik Andersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* Supply an architecture specific value for PAGE_SIZE and friends. */ + +#ifndef _UCLIBC_PAGE_H +#define _UCLIBC_PAGE_H + +/* PAGE_SHIFT determines the page size -- in this case 8192 */ +#define PAGE_SHIFT 13 +#define PAGE_SIZE (1UL << PAGE_SHIFT) +#define PAGE_MASK (~(PAGE_SIZE-1)) + +#endif /* _UCLIBC_PAGE_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/wordsize.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/wordsize.h new file mode 100644 index 00000000..22fc6410 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bits/wordsize.h @@ -0,0 +1,30 @@ +/* Copyright (C) 1999, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define __WORDSIZE 64 + +#if !defined __NO_LONG_DOUBLE_MATH && !defined __LONG_DOUBLE_MATH_OPTIONAL + +/* Signal that we didn't used to have a `long double'. The changes all + the `long double' function variants to be redirects to the double + functions. */ +# define __LONG_DOUBLE_MATH_OPTIONAL 1 +# ifndef __LONG_DOUBLE_128__ +# define __NO_LONG_DOUBLE_MATH 1 +# endif +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/brk.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/brk.S new file mode 100644 index 00000000..42c7368b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/brk.S @@ -0,0 +1,82 @@ +/* Copyright (C) 1993, 1995, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Brendan Kehoe , 1993. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* __brk is a special syscall under Linux since it never returns an + error. Instead, the error condition is indicated by returning the old + break value (instead of the new, requested one). */ + +#include +#define _ERRNO_H +#include +#include + +#ifdef __PIC__ +.section .bss + .align 3 + .globl __curbrk + .hidden __curbrk +__curbrk: .skip 8 + .type __curbrk,@object + .size __curbrk,8 +#else +.comm __curbrk, 8 +#endif + + .text +.globl brk; +.align 3; +.ent brk , 0; + +brk: + .frame $30 , 8 , $26 + ldgp $29, 0($27) + subq $30, 8, $30 + .prologue 1 + + /* Save the requested brk across the system call. */ + stq $16, 0($30) + + ldiq $0, __NR_brk + call_pal 131 + + ldq $16, 0($30) + + /* Be prepared for an OSF-style brk. */ + bne $19, $err1 + beq $0, $ok + + /* Correctly handle the brk(0) query case. */ + cmoveq $16, $0, $16 + xor $16, $0, $1 + bne $1, $err0 + + /* Update __curbrk and return cleanly. */ + mov $31, $0 +$ok: stq $16, __curbrk + addq $30, 8, $30 + ret + + /* What a horrible way to die. */ +$err0: ldi $0, ENOMEM +$err1: addq $30, 8, $30 + jmp $31, __syscall_error + + .end brk + +libc_hidden_def(brk) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bsd-_setjmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bsd-_setjmp.S new file mode 100644 index 00000000..4e6a2da5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bsd-_setjmp.S @@ -0,0 +1 @@ +/* _setjmp is in setjmp.S */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bsd-setjmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bsd-setjmp.S new file mode 100644 index 00000000..1da848d2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/bsd-setjmp.S @@ -0,0 +1 @@ +/* setjmp is in setjmp.S */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/clone.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/clone.S new file mode 100644 index 00000000..79d4511f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/clone.S @@ -0,0 +1,95 @@ +/* Copyright (C) 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson , 1996. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* clone() is even more special than fork() as it mucks with stacks + and invokes a function in the right context after its all over. */ + +#include +#define _ERRNO_H 1 +#include +#include +#include + +/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg) */ + +.text +.globl clone; +.align 3; +.ent clone , 0; + +clone: + .frame $30 , 0, $26 + .prologue 0 + + /* Sanity check arguments. */ + ldiq v0,EINVAL + beq a0,$error /* no NULL function pointers */ + beq a1,$error /* no NULL stack pointers */ + + /* Save the fn ptr and arg on the new stack. */ + subq a1,16,a1 + stq a0,0(a1) + stq a3,8(a1) + + /* Do the system call */ + mov a2,a0 + ldiq v0,__NR_clone + call_pal 131 + + bne a3,$error + beq v0,thread_start + + /* Successful return from the parent */ + ret + + /* Something bad happened -- no child created */ +$error: + br gp,1f +1: ldgp gp,0(gp) + jmp zero,__syscall_error + +.end clone + +/* Load up the arguments to the function. Put this block of code in + its own function so that we can terminate the stack trace with our + debug info. */ + + .ent thread_start +thread_start: + .frame fp,0,zero,0 + mov zero,fp + .prologue 0 + + /* Load up the arguments. */ + ldq pv,0($30) + ldq a0,8($30) + addq $30,16,$30 + + /* Call the user's function */ + jsr ra,(pv) + ldgp gp,0(ra) + + /* Call _exit rather than doing it inline for breakpoint purposes */ + mov v0,a0 + jsr ra,HIDDEN_JUMPTARGET(_exit) + + /* Die horribly. */ + halt + + .end thread_start diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/crt1.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/crt1.S new file mode 100644 index 00000000..0bf71248 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/crt1.S @@ -0,0 +1,97 @@ +/* Startup code for Alpha/ELF. + Copyright (C) 1993, 1995, 1996, 1997, 1998, 2000, 2001, 2002, 2003 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file with other + programs, and to distribute those programs without any restriction + coming from the use of this file. (The GNU Lesser General Public + License restrictions do apply in other respects; for example, they + cover modification of the file, and distribution when not linked + into another program.) + + Note that people who make modified versions of this file are not + obligated to grant this special exception for their modified + versions; it is their choice whether to do so. The GNU Lesser + General Public License gives permission to release a modified + version without this exception; this exception also makes it + possible to release a modified version which carries forward this + exception. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + + .text + .align 3 + .globl _start + .ent _start, 0 + .type _start,@function +#if defined(__UCLIBC_CTOR_DTOR__) + .type _init,%function + .type _fini,%function +#else + .weak _init + .weak _fini +#endif + .type __uClibc_main,%function + +_start: + .frame $15, 0, $15 + br gp, 1f +1: ldgp gp, 0(gp) + subq sp, 16, sp + mov 0, $15 + .prologue 0 + + /* Load address of the user's main function. */ + lda a0, main + + ldl a1, 16(sp) /* get argc */ + lda a2, 24(sp) /* get argv */ + + /* Load address of our own entry points to .fini and .init. */ + lda a3, _init + lda a4, _fini + + /* Store address of the shared library termination function. */ + mov v0, a5 + + /* Provide the highest stack address to the user code. */ + stq sp, 0(sp) + + /* Call the user's main function, and exit with its value. + But let the libc call main. */ + jsr ra, __uClibc_main + + /* Die very horribly if exit returns. Call_pal hlt is callable from + kernel mode only; this will result in an illegal instruction trap. */ + call_pal 0 + .end _start + +/* For ECOFF backwards compatibility. */ +/*weak_alias (_start, __start)*/ + +/* Define a symbol for the first piece of initialized data. */ + .data + .globl __data_start +__data_start: + .weak data_start + data_start = __data_start diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/crti.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/crti.S new file mode 100644 index 00000000..5c25539c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/crti.S @@ -0,0 +1,43 @@ + .set noat + .set noreorder + .set nomacro + .set macro + + .section .init + .set nomacro + .align 2 + .globl _init + .ent _init +_init: + .frame $30,0,$26,0 + .mask 0x4000000,0 + ldah $29,0($27) !gpdisp!3 + lda $29,0($29) !gpdisp!3 +$_init..ng: + lda $30,-16($30) + stq $26,0($30) + .prologue 1 + .set macro + + .align 2 + .end _init + + .section .fini + .set nomacro + .align 2 + .globl _fini + .ent _fini +_fini: + .frame $30,0,$26,0 + .mask 0x4000000,0 + ldah $29,0($27) !gpdisp!6 + lda $29,0($29) !gpdisp!6 +$_fini..ng: + lda $30,-16($30) + stq $26,0($30) + .prologue 1 + .set macro + .align 2 + .end _fini + + .ident "GCC: (GNU) 3.3.2" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/crtn.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/crtn.S new file mode 100644 index 00000000..bf847ab0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/crtn.S @@ -0,0 +1,13 @@ + .section .init + .align 2 + .globl _init + ldq $26,0($30) + lda $30,16($30) + ret $31,($26),1 + + .section .fini + .align 2 + .globl _fini + ldq $26,0($30) + lda $30,16($30) + ret $31,($26),1 diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/divl.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/divl.S new file mode 100644 index 00000000..fdf053fc --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/divl.S @@ -0,0 +1,6 @@ +#define IS_REM 0 +#define SIZE 4 +#define UFUNC_NAME __divlu +#define SFUNC_NAME __divl + +#include "divrem.h" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/divq.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/divq.S new file mode 100644 index 00000000..8c88af97 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/divq.S @@ -0,0 +1,6 @@ +#define IS_REM 0 +#define SIZE 8 +#define UFUNC_NAME __divqu +#define SFUNC_NAME __divq + +#include "divrem.h" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/divrem.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/divrem.h new file mode 100644 index 00000000..bd4e2d1b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/divrem.h @@ -0,0 +1,198 @@ +/* Copyright (C) 1996, 1997 Free Software Foundation, Inc. + Contributed by David Mosberger (davidm@cs.arizona.edu). + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* The current Alpha chips don't provide hardware for integer + division. The C compiler expects the functions + + __divqu: 64-bit unsigned long divide + __remqu: 64-bit unsigned long remainder + __divqs/__remqs: signed 64-bit + __divlu/__remlu: unsigned 32-bit + __divls/__remls: signed 32-bit + + These are not normal C functions: instead of the normal calling + sequence, these expect their arguments in registers t10 and t11, and + return the result in t12 (aka pv). Register AT may be clobbered + (assembly temporary), anything else must be saved. */ + +#include + +#include +#ifdef __linux__ +# include +# include +#else +# include +#endif + +#define mask v0 +#define divisor t0 +#define compare AT +#define tmp1 t2 +#define tmp2 t3 +#define retaddr t9 +#define arg1 t10 +#define arg2 t11 +#define result t12 + + +#if IS_REM +# define DIV_ONLY(x,y...) +# define REM_ONLY(x,y...) x,##y +# define modulus result +# define quotient t1 +# define GETSIGN(x) mov arg1, x +# define STACK 32 +#else +# define DIV_ONLY(x,y...) x,##y +# define REM_ONLY(x,y...) +# define modulus t1 +# define quotient result +# define GETSIGN(x) xor arg1, arg2, x +# define STACK 48 +#endif + +#if SIZE == 8 +# define LONGIFY(x,y) mov x,y +# define SLONGIFY(x,y) mov x,y +# define _SLONGIFY(x) +# define NEG(x,y) negq x,y +#else +# define LONGIFY(x,y) zapnot x,15,y +# define SLONGIFY(x,y) sextl x,y +# define _SLONGIFY(x) sextl x,x +# define NEG(x,y) negl x,y +#endif + + .set noreorder + .set noat + + .ent UFUNC_NAME + .globl UFUNC_NAME +#ifndef IS_IN_rtld + .hidden UFUNC_NAME +#endif + + .align 3 +UFUNC_NAME: + lda sp, -STACK(sp) + .frame sp, STACK, retaddr, 0 + .prologue 0 + +$udiv: + stq t0, 0(sp) + LONGIFY (arg2, divisor) + stq t1, 8(sp) + LONGIFY (arg1, modulus) + stq v0, 16(sp) + clr quotient + stq tmp1, 24(sp) + ldiq mask, 1 + DIV_ONLY(stq tmp2,32(sp)) + + beq divisor, $divbyzero + + .align 3 +#if SIZE == 8 + /* Shift divisor left. */ +1: cmpult divisor, modulus, compare + blt divisor, 2f + addq divisor, divisor, divisor + addq mask, mask, mask + bne compare, 1b + unop +2: +#else + /* Shift divisor left using 3-bit shifts as we can't overflow. + This results in looping three times less here, but up to + two more times later. Thus using a large shift isn't worth it. */ +1: cmpult divisor, modulus, compare + s8addq divisor, zero, divisor + s8addq mask, zero, mask + bne compare, 1b +#endif + + /* Now go back to the right. */ +3: DIV_ONLY(addq quotient, mask, tmp2) + srl mask, 1, mask + cmpule divisor, modulus, compare + subq modulus, divisor, tmp1 + DIV_ONLY(cmovne compare, tmp2, quotient) + srl divisor, 1, divisor + cmovne compare, tmp1, modulus + bne mask, 3b + +$done: ldq t0, 0(sp) + ldq t1, 8(sp) + ldq v0, 16(sp) + ldq tmp1, 24(sp) + DIV_ONLY(ldq tmp2, 32(sp)) + lda sp, STACK(sp) + ret zero, (retaddr), 1 + +$divbyzero: + mov a0, tmp1 + ldiq a0, GEN_INTDIV + call_pal PAL_gentrap + mov tmp1, a0 + clr result /* If trap returns, return zero. */ + br $done + + .end UFUNC_NAME + + .ent SFUNC_NAME + .globl SFUNC_NAME + + .align 3 +SFUNC_NAME: + lda sp, -STACK(sp) + .frame sp, STACK, retaddr, 0 + .prologue 0 + + or arg1, arg2, AT + _SLONGIFY(AT) + bge AT, $udiv /* don't need to mess with signs */ + + /* Save originals and find absolute values. */ + stq arg1, 0(sp) + NEG (arg1, AT) + stq arg2, 8(sp) + cmovge AT, AT, arg1 + stq retaddr, 16(sp) + NEG (arg2, AT) + stq tmp1, 24(sp) + cmovge AT, AT, arg2 + + /* Do the unsigned division. */ + bsr retaddr, UFUNC_NAME + + /* Restore originals and adjust the sign of the result. */ + ldq arg1, 0(sp) + ldq arg2, 8(sp) + GETSIGN (AT) + NEG (result, tmp1) + _SLONGIFY(AT) + ldq retaddr, 16(sp) + cmovlt AT, tmp1, result + ldq tmp1, 24(sp) + + lda sp, STACK(sp) + ret zero, (retaddr), 1 + + .end SFUNC_NAME diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/fpu_control.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/fpu_control.h new file mode 100644 index 00000000..cdffcfb9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/fpu_control.h @@ -0,0 +1,108 @@ +/* FPU control word bits. Alpha-mapped-to-Intel version. + Copyright (C) 1996, 1998, 2000, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Olaf Flebbe. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _ALPHA_FPU_CONTROL_H +#define _ALPHA_FPU_CONTROL_H + +/* + * Since many programs seem to hardcode the values passed to __setfpucw() + * (rather than using the manifest constants) we emulate the x87 interface + * here (at least where this makes sense). + * + * 15-13 12 11-10 9-8 7-6 5 4 3 2 1 0 + * | reserved | IC | RC | PC | reserved | PM | UM | OM | ZM | DM | IM + * + * IM: Invalid operation mask + * DM: Denormalized operand mask + * ZM: Zero-divide mask + * OM: Overflow mask + * UM: Underflow mask + * PM: Precision (inexact result) mask + * + * Mask bit is 1 means no interrupt. + * + * PC: Precision control + * 11 - round to extended precision + * 10 - round to double precision + * 00 - round to single precision + * + * RC: Rounding control + * 00 - rounding to nearest + * 01 - rounding down (toward - infinity) + * 10 - rounding up (toward + infinity) + * 11 - rounding toward zero + * + * IC: Infinity control + * That is for 8087 and 80287 only. + * + * The hardware default is 0x037f. I choose 0x1372. + */ + +#include + +/* masking of interrupts */ +#define _FPU_MASK_IM 0x01 +#define _FPU_MASK_DM 0x02 +#define _FPU_MASK_ZM 0x04 +#define _FPU_MASK_OM 0x08 +#define _FPU_MASK_UM 0x10 +#define _FPU_MASK_PM 0x20 + +/* precision control -- without effect on Alpha */ +#define _FPU_EXTENDED 0x300 /* RECOMMENDED */ +#define _FPU_DOUBLE 0x200 +#define _FPU_SINGLE 0x0 /* DO NOT USE */ + +/* + * rounding control---notice that on the Alpha this affects only + * instructions with the dynamic rounding mode qualifier (/d). + */ +#define _FPU_RC_NEAREST 0x000 /* RECOMMENDED */ +#define _FPU_RC_DOWN 0x400 +#define _FPU_RC_UP 0x800 +#define _FPU_RC_ZERO 0xC00 + +#define _FPU_RESERVED 0xF0C0 /* Reserved bits in cw */ + + +/* Now two recommended cw */ + +/* Linux default: + - extended precision + - rounding to positive infinity. There is no /p instruction + qualifier. By setting the dynamic rounding mode to +infinity, + one can use /d to get round to +infinity with no extra overhead + (so long as the default isn't changed, of course...) + - no exceptions enabled. */ + +#define _FPU_DEFAULT 0x137f + +/* IEEE: same as above. */ +#define _FPU_IEEE 0x137f + +/* Type of the control word. */ +typedef unsigned int fpu_control_t; + +#if 0 +/* Default control word set at startup. */ +extern fpu_control_t __fpu_control; +#endif + +#endif /* _ALPHA_FPU_CONTROL */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/pipe.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/pipe.S new file mode 100644 index 00000000..8a9236bc --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/pipe.S @@ -0,0 +1,48 @@ +/* Copyright (C) 1993, 1995, 1997, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by David Mosberger (davidm@cs.arizona.edu). + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + +/* __pipe is a special syscall since it returns two values. */ + +.globl pipe +.align 4 +.ent pipe, 0 +pipe: + .frame sp, 0, ra + ldgp gp,0(pv) + .prologue 1 + lda v0, __NR_pipe + call_pal PAL_callsys + bne a3, $syscall_error + + stl r0, 0(a0) + stl r1, 4(a0) + mov zero, v0 + ret + +$syscall_error: + jmp zero,__syscall_error + +.end pipe + +libc_hidden_def (pipe) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/reml.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/reml.S new file mode 100644 index 00000000..8c00365e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/reml.S @@ -0,0 +1,6 @@ +#define IS_REM 1 +#define SIZE 4 +#define UFUNC_NAME __remlu +#define SFUNC_NAME __reml + +#include "divrem.h" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/remq.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/remq.S new file mode 100644 index 00000000..cd1064af --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/remq.S @@ -0,0 +1,6 @@ +#define IS_REM 1 +#define SIZE 8 +#define UFUNC_NAME __remqu +#define SFUNC_NAME __remq + +#include "divrem.h" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/setjmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/setjmp.S new file mode 100644 index 00000000..105cc829 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/setjmp.S @@ -0,0 +1,91 @@ +/* Copyright (C) 1992, 1994, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#define _ASM +#define _SETJMP_H +#define __ASSEMBLY__ +#include + +#define a0 $16 + + .ent __sigsetjmp + .global __sigsetjmp +__sigsetjmp: + ldgp $29, 0($27) + +$sigsetjmp_local: + subq $30, 16, $30 + .frame $26, 16, $26, 0 + stq $26, 0($30) + .mask 0x04000000, -16 + .prologue 1 + + stq $9, JB_S0*8(a0) + stq $10, JB_S1*8(a0) + stq $11, JB_S2*8(a0) + stq $12, JB_S3*8(a0) + stq $13, JB_S4*8(a0) + stq $14, JB_S5*8(a0) + stq $26, JB_PC*8(a0) + addq $30, 16, $1 + stq $15, JB_FP*8(a0) + stq $1, JB_SP*8(a0) + stt $f2, JB_F2*8(a0) + stt $f3, JB_F3*8(a0) + stt $f4, JB_F4*8(a0) + stt $f5, JB_F5*8(a0) + stt $f6, JB_F6*8(a0) + stt $f7, JB_F7*8(a0) + stt $f8, JB_F8*8(a0) + stt $f9, JB_F9*8(a0) + + /* Call to C to (potentially) save our signal mask. */ + jsr $26, __sigjmp_save + + ldq $26, 0($30) + addq $30, 16, $30 + ret + +.end __sigsetjmp + +/* Put these traditional entry points in the same file so that we can + elide much of the nonsense in trying to jmp to the real function. */ + +.globl _setjmp; +.align 3; +.ent _setjmp , 0; +_setjmp: + .frame $30 , 0, $26 + ldgp $29, 0($27) + mov 0, $17 + br $sigsetjmp_local +.end _setjmp + +.globl setjmp; +.align 3; +.ent setjmp , 0; +setjmp: + .frame $30 , 0, $26 + ldgp $29, 0($27) + mov 1, $17 + br $sigsetjmp_local +.end setjmp + +.weak _setjmp +.weak setjmp diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/sigprocmask.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/sigprocmask.c new file mode 100644 index 00000000..9d611e27 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/sigprocmask.c @@ -0,0 +1,62 @@ +/* Copyright (C) 1993, 1995, 1997, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by David Mosberger (davidm@azstarnet.com). + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include + +/* When there is kernel support for more than 64 signals, we'll have to + switch to a new system call convention here. */ + +static __inline__ _syscall2(int, osf_sigprocmask, int, how, unsigned long int, setval) + +int +sigprocmask (int how, const sigset_t *set, sigset_t *oset) +{ + unsigned long int setval; + long result; + + if (set) + setval = set->__val[0]; + else + { + setval = 0; + how = SIG_BLOCK; /* ensure blocked mask doesn't get changed */ + } + + result = osf_sigprocmask(how, setval); + if (result == -1) + /* If there are ever more than 64 signals, we need to recode this + in assembler since we wouldn't be able to distinguish a mask of + all 1s from -1, but for now, we're doing just fine... */ + return result; + + if (oset) + { + if (_SIGSET_NWORDS == 2) /* typical */ + oset->__val[1] = 0; + if (_SIGSET_NWORDS > 2) + memset(oset, 0, sizeof(*oset)); + oset->__val[0] = result; + } + return 0; +} +libc_hidden_def(sigprocmask) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/sys/acct.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/sys/acct.h new file mode 100644 index 00000000..1e00006e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/sys/acct.h @@ -0,0 +1,66 @@ +/* Copyright (C) 1996, 1997, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_ACCT_H + +#define _SYS_ACCT_H 1 +#include + +#define __need_time_t +#include + + +__BEGIN_DECLS + +#define ACCT_COMM 16 + +struct acct + { + char ac_comm[ACCT_COMM]; /* Accounting command name. */ + time_t ac_utime; /* Accounting user time. */ + time_t ac_stime; /* Accounting system time. */ + time_t ac_etime; /* Accounting elapsed time. */ + time_t ac_btime; /* Beginning time. */ + unsigned int ac_uid; /* Accounting user ID. */ + unsigned int ac_gid; /* Accounting group ID. */ + unsigned int ac_tty; /* Controlling tty. */ + /* Please note that the value of the `ac_tty' field, a device number, + is encoded differently in the kernel and for the libc dev_t type. */ + char ac_flag; /* Accounting flag. */ + long int ac_minflt; /* Accounting minor pagefaults. */ + long int ac_majflt; /* Accounting major pagefaults. */ + long int ac_exitcode; /* Accounting process exitcode. */ + }; + +enum + { + AFORK = 0001, /* Has executed fork, but no exec. */ + ASU = 0002, /* Used super-user privileges. */ + ACORE = 0004, /* Dumped core. */ + AXSIG = 0010 /* Killed by a signal. */ + }; + +#define AHZ 100 + + +/* Switch process accounting on and off. */ +extern int acct (__const char *__filename) __THROW; + +__END_DECLS + +#endif /* sys/acct.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/sys/io.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/sys/io.h new file mode 100644 index 00000000..9cb8d254 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/sys/io.h @@ -0,0 +1,96 @@ +/* Copyright (C) 1996, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_IO_H + +#define _SYS_IO_H 1 +#include + +__BEGIN_DECLS + +/* If TURN_ON is TRUE, request for permission to do direct i/o on the + port numbers in the range [FROM,FROM+NUM-1]. Otherwise, turn I/O + permission off for that range. This call requires root privileges. + + Portability note: not all Linux platforms support this call. Most + platforms based on the PC I/O architecture probably will, however. + E.g., Linux/Alpha for Alpha PCs supports this. */ +extern int ioperm (unsigned long int __from, unsigned long int __num, + int __turn_on) __THROW; +libc_hidden_proto(ioperm) + +/* Set the I/O privilege level to LEVEL. If LEVEL>3, permission to + access any I/O port is granted. This call requires root + privileges. */ +extern int iopl (int __level) __THROW; + +/* Return the physical address of the DENSE I/O memory or NULL if none + is available (e.g. on a jensen). */ +extern unsigned long int _bus_base (void) __THROW __attribute__ ((const)); +extern unsigned long int bus_base (void) __THROW __attribute__ ((const)); + +/* Return the physical address of the SPARSE I/O memory. */ +extern unsigned long _bus_base_sparse (void) __THROW __attribute__ ((const)); +extern unsigned long bus_base_sparse (void) __THROW __attribute__ ((const)); + +/* Return the HAE shift used by the SPARSE I/O memory. */ +extern int _hae_shift (void) __THROW __attribute__ ((const)); +extern int hae_shift (void) __THROW __attribute__ ((const)); + +/* Previous three are deprecated in favour of the following, which + knows about multiple PCI "hoses". Provide the PCI bus and dfn + numbers just as to pciconfig_read/write. */ + +enum __pciconfig_iobase_which +{ + IOBASE_HOSE = 0, /* Return hose index. */ + IOBASE_SPARSE_MEM = 1, /* Return physical memory addresses. */ + IOBASE_DENSE_MEM = 2, + IOBASE_SPARSE_IO = 3, + IOBASE_DENSE_IO = 4 +}; + +extern long pciconfig_iobase(enum __pciconfig_iobase_which __which, + unsigned long int __bus, + unsigned long int __dfn) + __THROW __attribute__ ((const)); + +/* Access PCI space protected from machine checks. */ +extern int pciconfig_read (unsigned long int __bus, + unsigned long int __dfn, + unsigned long int __off, + unsigned long int __len, + unsigned char *__buf) __THROW; + +extern int pciconfig_write (unsigned long int __bus, + unsigned long int __dfn, + unsigned long int __off, + unsigned long int __len, + unsigned char *__buf) __THROW; + +/* Userspace declarations. */ +extern unsigned int inb (unsigned long __port) __THROW; +extern unsigned int inw (unsigned long __port) __THROW; +extern unsigned int inl (unsigned long __port) __THROW; +extern void outb (unsigned char __b, unsigned long __port) __THROW; +extern void outw (unsigned short __w, unsigned long __port) __THROW; +extern void outl (unsigned int __l, unsigned long __port) __THROW; + +__END_DECLS + +#endif /* _SYS_IO_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/sys/procfs.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/sys/procfs.h new file mode 100644 index 00000000..2c9d119a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/sys/procfs.h @@ -0,0 +1,128 @@ +/* Copyright (C) 1996, 1997, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_PROCFS_H +#define _SYS_PROCFS_H 1 + +/* This is somehow modelled after the file of the same name on SysVr4 + systems. It provides a definition of the core file format for ELF + used on Linux. */ + +#include +#include +#include +#include +#include +#include + +__BEGIN_DECLS + +/* + * The OSF/1 version of makes gregset_t 46 entries long. + * I have no idea why that is so. For now, we just leave it at 33 + * (32 general regs + processor status word). + */ +#define ELF_NGREG 33 +#define ELF_NFPREG 32 + +typedef unsigned long elf_greg_t; +typedef elf_greg_t elf_gregset_t[ELF_NGREG]; + +typedef double elf_fpreg_t; +typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; + +struct elf_siginfo + { + int si_signo; /* Signal number. */ + int si_code; /* Extra code. */ + int si_errno; /* Errno. */ + }; + +/* Definitions to generate Intel SVR4-like core files. These mostly + have the same names as the SVR4 types with "elf_" tacked on the + front to prevent clashes with linux definitions, and the typedef + forms have been avoided. This is mostly like the SVR4 structure, + but more Linuxy, with things that Linux does not support and which + gdb doesn't really use excluded. Fields present but not used are + marked with "XXX". */ +struct elf_prstatus + { +#if 0 + long int pr_flags; /* XXX Process flags. */ + short int pr_why; /* XXX Reason for process halt. */ + short int pr_what; /* XXX More detailed reason. */ +#endif + struct elf_siginfo pr_info; /* Info associated with signal. */ + short int pr_cursig; /* Current signal. */ + unsigned long int pr_sigpend; /* Set of pending signals. */ + unsigned long int pr_sighold; /* Set of held signals. */ +#if 0 + struct sigaltstack pr_altstack; /* Alternate stack info. */ + struct sigaction pr_action; /* Signal action for current sig. */ +#endif + __pid_t pr_pid; + __pid_t pr_ppid; + __pid_t pr_pgrp; + __pid_t pr_sid; + struct timeval pr_utime; /* User time. */ + struct timeval pr_stime; /* System time. */ + struct timeval pr_cutime; /* Cumulative user time. */ + struct timeval pr_cstime; /* Cumulative system time. */ +#if 0 + long int pr_instr; /* Current instruction. */ +#endif + elf_gregset_t pr_reg; /* GP registers. */ + int pr_fpvalid; /* True if math copro being used. */ + }; + + +#define ELF_PRARGSZ (80) /* Number of chars for args */ + +struct elf_prpsinfo + { + char pr_state; /* Numeric process state. */ + char pr_sname; /* Char for pr_state. */ + char pr_zomb; /* Zombie. */ + char pr_nice; /* Nice val. */ + unsigned long int pr_flag; /* Flags. */ + unsigned int pr_uid; + unsigned int pr_gid; + int pr_pid, pr_ppid, pr_pgrp, pr_sid; + /* Lots missing */ + char pr_fname[16]; /* Filename of executable. */ + char pr_psargs[ELF_PRARGSZ]; /* Initial part of arg list. */ + }; + +/* Addresses. */ +typedef void *psaddr_t; + +/* Register sets. Linux has different names. */ +typedef gregset_t prgregset_t; +typedef fpregset_t prfpregset_t; + +/* We don't have any differences between processes and threads, + therefore habe only ine PID type. */ +typedef __pid_t lwpid_t; + + +typedef struct elf_prstatus prstatus_t; +typedef struct elf_prpsinfo prpsinfo_t; + +__END_DECLS + +#endif /* sys/procfs.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/sys/regdef.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/sys/regdef.h new file mode 100644 index 00000000..18fb0d5d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/sys/regdef.h @@ -0,0 +1,47 @@ +#ifndef __alpha_regdef_h__ +#define __alpha_regdef_h__ + +#define v0 $0 /* function return value */ + +#define t0 $1 /* temporary registers (caller-saved) */ +#define t1 $2 +#define t2 $3 +#define t3 $4 +#define t4 $5 +#define t5 $6 +#define t6 $7 +#define t7 $8 + +#define s0 $9 /* saved-registers (callee-saved registers) */ +#define s1 $10 +#define s2 $11 +#define s3 $12 +#define s4 $13 +#define s5 $14 +#define s6 $15 +#define fp s6 /* frame-pointer (s6 in frame-less procedures) */ + +#define a0 $16 /* argument registers (caller-saved) */ +#define a1 $17 +#define a2 $18 +#define a3 $19 +#define a4 $20 +#define a5 $21 + +#define t8 $22 /* more temps (caller-saved) */ +#define t9 $23 +#define t10 $24 +#define t11 $25 +#define ra $26 /* return address register */ +#define t12 $27 + +#define pv t12 /* procedure-variable register */ +#define AT $at /* assembler temporary */ +#define gp $29 /* global pointer */ +#define sp $30 /* stack pointer */ +#define zero $31 /* reads as zero, writes are noops */ + +#define r0 v0 +#define r1 a4 + +#endif /* __alpha_regdef_h__ */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/sys/ucontext.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/sys/ucontext.h new file mode 100644 index 00000000..438293c6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/sys/ucontext.h @@ -0,0 +1,61 @@ +/* Copyright (C) 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_UCONTEXT_H +#define _SYS_UCONTEXT_H 1 + +#include +#include + +#include + + +/* Type for general register. */ +typedef long int greg_t; + +/* Number of general registers. */ +#define NGREG 33 + +/* Container for all general registers. */ +typedef greg_t gregset_t[NGREG]; + +/* Type for floating-point register. */ +typedef long int fpreg_t; + +/* Number of general registers. */ +#define NFPREG 32 + +/* Container for all general registers. */ +typedef fpreg_t fpregset_t[NFPREG]; + + +/* A machine context is exactly a sigcontext. */ +typedef struct sigcontext mcontext_t; + +/* Userlevel context. */ +typedef struct ucontext + { + unsigned long int uc_flags; + struct ucontext *uc_link; + unsigned long __uc_osf_sigmask; + stack_t uc_stack; + mcontext_t uc_mcontext; + __sigset_t uc_sigmask; + } ucontext_t; + +#endif /* sys/ucontext.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/sys/user.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/sys/user.h new file mode 100644 index 00000000..f9beea08 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/sys/user.h @@ -0,0 +1,50 @@ +/* Copyright (C) 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_USER_H +#define _SYS_USER_H 1 + +/* The whole purpose of this file is for gdb/strace and gdb/strace + only. Don't read too much into it. Don't use it for anything other + than gdb/strace unless you know what you are doing. */ + +#include +#include + +struct user +{ + unsigned long int regs[EF_SIZE / 8 + 32]; /* integer and fp regs */ + size_t u_tsize; /* text size (pages) */ + size_t u_dsize; /* data size (pages) */ + size_t u_ssize; /* stack size (pages) */ + unsigned long int start_code; /* text starting address */ + unsigned long int start_data; /* data starting address */ + unsigned long int start_stack; /* stack starting address */ + long int signal; /* signal causing core dump */ + struct regs *u_ar0; /* help gdb find registers */ + unsigned long int magic; /* identifies a core file */ + char u_comm[32]; /* user command name */ +}; + +#define NBPG PAGE_SIZE +#define UPAGES 1 +#define HOST_TEXT_START_ADDR (u.start_code) +#define HOST_DATA_START_ADDR (u.start_data) +#define HOST_STACK_END_ADDR (u.start_stack + u.u_ssize * NBPG) + +#endif /* sys/user.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/syscall.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/syscall.S new file mode 100644 index 00000000..89901d54 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/alpha/syscall.S @@ -0,0 +1,71 @@ +/* Copyright (C) 1996 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by David Mosberger , 1996. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +/* + * This is for COMPATIBILITY with Linux/x86 only. Linux/Alpha system + * calls return an error indication in a3. This allows arbitrary 64bit + * values to be returned in v0 (because negative values are not + * mistaken as error numbers). However, C allows only one value to + * be returned, so the interface below folds the error indication passed in + * a3 back into v0: it sets v0 to -errno if an error occurs. Thus, + * no negative 64bit numbers can be returned. To avoid this problem, + * use assembly stubs wherever possible/convenient. + * + * Usage: + * + * long syscall(syscall_number, arg1, arg2, arg3, arg4, arg5) + * + * syscall_number = the index of the system call we're invoking + * arg1-arg5 = up to 5 integer arguments to the system call + * + * We need to do some arg shifting: the kernel expects the + * syscall number in v0 and the first five args in a0-a4. + * + */ + +.globl __syscall; +.align 4; +.ent __syscall, 0; +__syscall: +.frame sp, 0, ra + .prologue 0 + + mov a0, v0 /* Syscall number -> v0 */ + mov a1, a0 /* arg1-arg5 -> a0-a4 */ + mov a2, a1 + mov a3, a2 + mov a4, a3 + mov a5, a4 + + call_pal PAL_callsys /* Invoke system call */ + bne a3, $error + ret + +$error: + br gp, 2f +2: ldgp gp, 0(gp) + jmp zero,__syscall_error + +.end __syscall + +weak_alias (__syscall, syscall) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/Makefile new file mode 100644 index 00000000..633c91f3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../../ +top_builddir=../../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.arch +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/Makefile.arch b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/Makefile.arch new file mode 100644 index 00000000..b53c539b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/Makefile.arch @@ -0,0 +1,46 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +CSRC := brk.c ioperm.c iopl.c mmap.c __syscall_error.c + +ifneq ($(UCLIBC_HAS_THREADS_NATIVE),y) +CSRC += sigaction.c +endif + +SSRC := \ + __longjmp.S setjmp.S bsd-setjmp.S \ + bsd-_setjmp.S sigrestorer.S mmap64.S \ + vfork.S clone.S + +ifeq ($(UCLIBC_HAS_THREADS_NATIVE),y) +SSRC += libc-aeabi_read_tp.S libc-thumb_atomics.S +endif + +ifeq ($(UCLIBC_HAS_ADVANCED_REALTIME),y) +CSRC += posix_fadvise.c posix_fadvise64.c +endif + +ifeq ($(CONFIG_ARM_EABI),y) +CSRC += aeabi_assert.c aeabi_atexit.c aeabi_errno_addr.c \ + aeabi_localeconv.c aeabi_memclr.c aeabi_memcpy.c \ + aeabi_memmove.c aeabi_memset.c find_exidx.c +SSRC += syscall-eabi.S +ARCH_OBJ_FILTEROUT := syscall.c +ifeq ($(UCLIBC_HAS_WCHAR),y) +CSRC += aeabi_mb_cur_max.c +endif +else +CSRC += syscall.c +endif + +ifeq ($(CONFIG_ARM_EABI),y) +libc-static-y += $(ARCH_OUT)/aeabi_lcsts.o $(ARCH_OUT)/aeabi_math.o \ + $(ARCH_OUT)/aeabi_sighandlers.o +libc-nonshared-y += $(ARCH_OUT)/aeabi_lcsts.os $(ARCH_OUT)/aeabi_math.os \ + $(ARCH_OUT)/aeabi_sighandlers.os +libc-shared-y += $(ARCH_OUT)/aeabi_unwind_cpp_pr1.os +endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/__longjmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/__longjmp.S new file mode 100644 index 00000000..5faf4ece --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/__longjmp.S @@ -0,0 +1,114 @@ +/* longjmp for ARM. + Copyright (C) 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#define _SETJMP_H +#define _ASM +#include + + +.global __longjmp +.type __longjmp,%function +.align 2 +#if defined(THUMB1_ONLY) +.thumb_func +__longjmp: + mov r2, r0 + movs r0, r1 + /* can't let setjmp() return zero! */ + bne 1f + mov r0, #1 +1: + mov r1, r2 + /* Restore registers, shuffling them through low regs. */ + add r2, #(4 * 4) + ldmia r2!, {r4, r5, r6, r7} + mov r8, r4 + mov r9, r5 + mov sl, r6 + mov fp, r7 + ldmia r2!, {r4, r5} + mov sp, r4 + mov lr, r5 + ldmia r1!, {r4, r5, r6, r7} + bx lr +#else +__longjmp: + mov ip, r0 /* save jmp_buf pointer */ + + movs r0, r1 /* get the return value in place */ + IT(t, eq) + moveq r0, #1 /* can't let setjmp() return zero! */ + +#if defined(__thumb2__) + /* Thumb-2 does not allow loading sp with ldm. */ + ldmia ip!, {v1-v6, sl, fp} + ldr sp, [ip], #4 + ldr lr, [ip], #4 +#else + ldmia ip!, {v1-v6, sl, fp, sp, lr} +#endif + +#if defined __UCLIBC_HAS_FLOATS__ && ! defined __UCLIBC_HAS_SOFT_FLOAT__ +#ifdef __VFP_FP__ + /* Restore the VFP registers. */ + /* Following instruction is fldmiax ip!, {d8-d15}. */ + ldc p11, cr8, [r12], #68 + /* Restore the floating-point status register. */ + ldr r1, [ip], #4 + /* Following instruction is fmxr fpscr, r1. */ + mcr p10, 7, r1, cr1, cr0, 0 +# elif defined __MAVERICK__ + cfldrd mvd4, [ip], #8 ; nop + cfldrd mvd5, [ip], #8 ; nop + cfldrd mvd6, [ip], #8 ; nop + cfldrd mvd7, [ip], #8 ; nop + cfldrd mvd8, [ip], #8 ; nop + cfldrd mvd9, [ip], #8 ; nop + cfldrd mvd10, [ip], #8 ; nop + cfldrd mvd11, [ip], #8 ; nop + cfldrd mvd12, [ip], #8 ; nop + cfldrd mvd13, [ip], #8 ; nop + cfldrd mvd14, [ip], #8 ; nop + cfldrd mvd15, [ip], #8 +# else + lfmfd f4, 4, [ip] ! /* load the floating point regs */ +# endif +#endif +#ifdef __IWMMXT__ + /* Restore the call-preserved iWMMXt registers. */ + /* Following instructions are wldrd wr10, [ip], #8 (etc.) */ + ldcl p1, cr10, [r12], #8 + ldcl p1, cr11, [r12], #8 + ldcl p1, cr12, [r12], #8 + ldcl p1, cr13, [r12], #8 + ldcl p1, cr14, [r12], #8 + ldcl p1, cr15, [r12], #8 +#endif + +#if defined(__USE_BX__) + bx lr +#else + mov pc, lr +#endif +#endif + +.size __longjmp,.-__longjmp +libc_hidden_def(__longjmp) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/__syscall_error.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/__syscall_error.c new file mode 100644 index 00000000..2b642e81 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/__syscall_error.c @@ -0,0 +1,18 @@ +/* Wrapper for setting errno. + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +/* This routine is jumped to by all the syscall handlers, to stash + * an error number into errno. */ +int __syscall_error(int err_no) attribute_hidden; +int __syscall_error(int err_no) +{ + __set_errno(-err_no); + return -1; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/aeabi_assert.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/aeabi_assert.c new file mode 100644 index 00000000..a725ad45 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/aeabi_assert.c @@ -0,0 +1,28 @@ +/* Copyright (C) 2004, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#undef NDEBUG +#include +#include + + +void __aeabi_assert(const char *assertion, const char *file, unsigned int line); +void __aeabi_assert(const char *assertion, const char *file, unsigned int line) +{ + __assert (assertion, file, line, NULL); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/aeabi_atexit.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/aeabi_atexit.c new file mode 100644 index 00000000..ebb233b4 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/aeabi_atexit.c @@ -0,0 +1,31 @@ +/* Copyright (C) 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +extern int __cxa_atexit (void (*func) (void *), void *arg, void *dso_handle); +libc_hidden_proto(__cxa_atexit) + +/* Register a function to be called by exit or when a shared library + is unloaded. This routine is like __cxa_atexit, but uses the + calling sequence required by the ARM EABI. */ +int __aeabi_atexit (void *arg, void (*func) (void *), void *d); +int __aeabi_atexit (void *arg, void (*func) (void *), void *d) +{ + return __cxa_atexit (func, arg, d); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/aeabi_errno_addr.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/aeabi_errno_addr.c new file mode 100644 index 00000000..5e262a6d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/aeabi_errno_addr.c @@ -0,0 +1,25 @@ +/* Copyright (C) 2004, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +volatile int * __aeabi_errno_addr (void); +volatile int * __aeabi_errno_addr (void) +{ + return &errno; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/aeabi_lcsts.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/aeabi_lcsts.c new file mode 100644 index 00000000..0c620d4f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/aeabi_lcsts.c @@ -0,0 +1,99 @@ +/* Link-time constants for ARM EABI. + Copyright (C) 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file with other + programs, and to distribute those programs without any restriction + coming from the use of this file. (The GNU Lesser General Public + License restrictions do apply in other respects; for example, they + cover modification of the file, and distribution when not linked + into another program.) + + Note that people who make modified versions of this file are not + obligated to grant this special exception for their modified + versions; it is their choice whether to do so. The GNU Lesser + General Public License gives permission to release a modified + version without this exception; this exception also makes it + possible to release a modified version which carries forward this + exception. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* The ARM EABI requires that we provide ISO compile-time constants as + link-time constants. Some portable applications may reference these. */ + +#include +#include +#include +#include +#include +#include +#include + +#define eabi_constant2(X,Y) const int __aeabi_##X attribute_hidden = Y +#define eabi_constant(X) const int __aeabi_##X attribute_hidden = X + +eabi_constant (EDOM); +eabi_constant (ERANGE); +eabi_constant (EILSEQ); + +eabi_constant (MB_LEN_MAX); + +eabi_constant (LC_COLLATE); +eabi_constant (LC_CTYPE); +eabi_constant (LC_MONETARY); +eabi_constant (LC_NUMERIC); +eabi_constant (LC_TIME); +eabi_constant (LC_ALL); + +/* The value of __aeabi_JMP_BUF_SIZE is the number of doublewords in a + jmp_buf. */ +eabi_constant2 (JMP_BUF_SIZE, sizeof (jmp_buf) / 8); + +eabi_constant (SIGABRT); +eabi_constant (SIGFPE); +eabi_constant (SIGILL); +eabi_constant (SIGINT); +eabi_constant (SIGSEGV); +eabi_constant (SIGTERM); + +eabi_constant2 (IOFBF, _IOFBF); +eabi_constant2 (IOLBF, _IOLBF); +eabi_constant2 (IONBF, _IONBF); +eabi_constant (BUFSIZ); +eabi_constant (FOPEN_MAX); +eabi_constant (TMP_MAX); +eabi_constant (FILENAME_MAX); +eabi_constant (L_tmpnam); + +FILE *__aeabi_stdin attribute_hidden; +FILE *__aeabi_stdout attribute_hidden; +FILE *__aeabi_stderr attribute_hidden; + +static void __attribute__ ((used)) +setup_aeabi_stdio (void) +{ + __aeabi_stdin = stdin; + __aeabi_stdout = stdout; + __aeabi_stderr = stderr; +} + +static void (*fp) (void) __attribute__ ((used, section (".preinit_array"))) + = setup_aeabi_stdio; + +eabi_constant (CLOCKS_PER_SEC); diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/aeabi_localeconv.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/aeabi_localeconv.c new file mode 100644 index 00000000..0cd0f37f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/aeabi_localeconv.c @@ -0,0 +1,26 @@ +/* Copyright (C) 2004, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + + +struct lconv * __aeabi_localeconv (void); +struct lconv * __aeabi_localeconv (void) +{ + return localeconv (); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/aeabi_math.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/aeabi_math.c new file mode 100644 index 00000000..e7f1dbf5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/aeabi_math.c @@ -0,0 +1,42 @@ +/* Copyright (C) 2004, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file with other + programs, and to distribute those programs without any restriction + coming from the use of this file. (The GNU Lesser General Public + License restrictions do apply in other respects; for example, they + cover modification of the file, and distribution when not linked + into another program.) + + Note that people who make modified versions of this file are not + obligated to grant this special exception for their modified + versions; it is their choice whether to do so. The GNU Lesser + General Public License gives permission to release a modified + version without this exception; this exception also makes it + possible to release a modified version which carries forward this + exception. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +const double __aeabi_HUGE_VAL attribute_hidden = HUGE_VAL; +const long double __aeabi_HUGE_VALL attribute_hidden = HUGE_VALL; +const float __aeabi_HUGE_VALF attribute_hidden = HUGE_VALF; +const float __aeabi_INFINITY attribute_hidden = INFINITY; +const float __aeabi_NAN attribute_hidden = NAN; diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/aeabi_mb_cur_max.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/aeabi_mb_cur_max.c new file mode 100644 index 00000000..f12309ea --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/aeabi_mb_cur_max.c @@ -0,0 +1,31 @@ +/* Copyright (C) 2004, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +int +__aeabi_MB_CUR_MAX (void) +{ +#ifdef __UCLIBC_HAS_WCHAR__ + return MB_CUR_MAX; +#else + return 1; +#endif +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/aeabi_memclr.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/aeabi_memclr.c new file mode 100644 index 00000000..c6e2e3a7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/aeabi_memclr.c @@ -0,0 +1,32 @@ +/* Copyright (C) 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + + +/* Clear memory. Can't alias to bzero because it's not defined in the + same translation unit. */ +void __aeabi_memclr (void *dest, size_t n); +void __aeabi_memclr (void *dest, size_t n) +{ + memset (dest, 0, n); +} + +/* Versions of the above which may assume memory alignment. */ +strong_alias (__aeabi_memclr, __aeabi_memclr4) +strong_alias (__aeabi_memclr, __aeabi_memclr8) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/aeabi_memcpy.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/aeabi_memcpy.c new file mode 100644 index 00000000..2fce4fd2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/aeabi_memcpy.c @@ -0,0 +1,33 @@ +/* Copyright (C) 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + + +/* Copy memory like memcpy, but no return value required. Can't alias + to memcpy because it's not defined in the same translation + unit. */ +void __aeabi_memcpy (void *dest, const void *src, size_t n); +void __aeabi_memcpy (void *dest, const void *src, size_t n) +{ + memcpy (dest, src, n); +} + +/* Versions of the above which may assume memory alignment. */ +strong_alias (__aeabi_memcpy, __aeabi_memcpy4) +strong_alias (__aeabi_memcpy, __aeabi_memcpy8) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/aeabi_memmove.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/aeabi_memmove.c new file mode 100644 index 00000000..8a5f33a7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/aeabi_memmove.c @@ -0,0 +1,33 @@ +/* Copyright (C) 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + + +/* Copy memory like memmove, but no return value required. Can't + alias to memmove because it's not defined in the same translation + unit. */ +void __aeabi_memmove (void *dest, const void *src, size_t n); +void __aeabi_memmove (void *dest, const void *src, size_t n) +{ + memmove (dest, src, n); +} + +/* Versions of the above which may assume memory alignment. */ +strong_alias (__aeabi_memmove, __aeabi_memmove4) +strong_alias (__aeabi_memmove, __aeabi_memmove8) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/aeabi_memset.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/aeabi_memset.c new file mode 100644 index 00000000..eca59b13 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/aeabi_memset.c @@ -0,0 +1,32 @@ +/* Copyright (C) 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + + +/* Set memory like memset, but different argument order and no return + value required. */ +void __aeabi_memset (void *dest, size_t n, int c); +void __aeabi_memset (void *dest, size_t n, int c) +{ + memset (dest, c, n); +} + +/* Versions of the above which may assume memory alignment. */ +strong_alias (__aeabi_memset, __aeabi_memset4) +strong_alias (__aeabi_memset, __aeabi_memset8) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/aeabi_sighandlers.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/aeabi_sighandlers.S new file mode 100644 index 00000000..ba9769fd --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/aeabi_sighandlers.S @@ -0,0 +1,52 @@ +/* Link-time constants for ARM EABI - signal handlers. + Copyright (C) 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file with other + programs, and to distribute those programs without any restriction + coming from the use of this file. (The GNU Lesser General Public + License restrictions do apply in other respects; for example, they + cover modification of the file, and distribution when not linked + into another program.) + + Note that people who make modified versions of this file are not + obligated to grant this special exception for their modified + versions; it is their choice whether to do so. The GNU Lesser + General Public License gives permission to release a modified + version without this exception; this exception also makes it + possible to release a modified version which carries forward this + exception. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* The ARM EABI defines these as "functions". */ + + .global __aeabi_SIG_DFL + .hidden __aeabi_SIG_DFL + .type __aeabi_SIG_DFL, %function + .set __aeabi_SIG_DFL, 0 + + .global __aeabi_SIG_IGN + .hidden __aeabi_SIG_IGN + .type __aeabi_SIG_IGN, %function + .set __aeabi_SIG_IGN, 1 + + .global __aeabi_SIG_ERR + .hidden __aeabi_SIG_ERR + .type __aeabi_SIG_ERR, %function + .set __aeabi_SIG_ERR, -1 diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/aeabi_unwind_cpp_pr1.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/aeabi_unwind_cpp_pr1.c new file mode 100644 index 00000000..4544dc7d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/aeabi_unwind_cpp_pr1.c @@ -0,0 +1,40 @@ +/* Copyright (C) 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Because some objects in ld.so and libc.so are built with + -fexceptions, we end up with references to this personality + routine. However, these libraries are not linked against + libgcc_eh.a, so we need a dummy definition. This routine will + never actually be called. */ + +#include + +attribute_hidden void __aeabi_unwind_cpp_pr0 (void); +attribute_hidden void __aeabi_unwind_cpp_pr0 (void) +{ +} + +attribute_hidden void __aeabi_unwind_cpp_pr1 (void); +attribute_hidden void __aeabi_unwind_cpp_pr1 (void) +{ +} + +attribute_hidden void __aeabi_unwind_cpp_pr2 (void); +attribute_hidden void __aeabi_unwind_cpp_pr2 (void) +{ +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/bits/arm_asm.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/bits/arm_asm.h new file mode 100644 index 00000000..1d87df6e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/bits/arm_asm.h @@ -0,0 +1,28 @@ +/* Various definitons used the the ARM uClibc assembly code. */ +#ifndef _ARM_ASM_H +#define _ARM_ASM_H + +#ifdef __thumb2__ +.thumb +.syntax unified +#define IT(t, cond) i##t cond +#else +/* XXX: This can be removed if/when we require an assembler that supports + unified assembly syntax. */ +#define IT(t, cond) +/* Code to return from a thumb function stub. */ +#ifdef __ARM_ARCH_4T__ +#define POP_RET pop {r2, pc} +#else +#define POP_RET pop {r2, r3}; bx r3 +#endif +#endif + +#if defined(__ARM_ARCH_6M__) +/* Force arm mode to flush out errors on M profile cores. */ +#undef IT +#define THUMB1_ONLY 1 +#endif + +#endif /* _ARM_ASM_H */ + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/bits/armsigctx.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/bits/armsigctx.h new file mode 100644 index 00000000..4530cdbd --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/bits/armsigctx.h @@ -0,0 +1,73 @@ +/* Definition of `struct sigcontext' for Linux/ARM + Copyright (C) 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* The format of struct sigcontext changed between 2.0 and 2.1 kernels. + Fortunately 2.0 puts a magic number in the first word and this is not + a legal value for `trap_no', so we can tell them apart. */ + +/* Early 2.2 and 2.3 kernels do not have the `fault_address' member in + the sigcontext structure. Unfortunately there is no reliable way + to test for its presence and this word will contain garbage for too-old + kernels. Versions 2.2.14 and 2.3.35 (plus later versions) are known to + include this element. */ + +#ifndef __ARMSIGCTX_H +#define __ARMSIGCTX_H 1 + +#include + +union k_sigcontext + { + struct + { + unsigned long int trap_no; + unsigned long int error_code; + unsigned long int oldmask; + unsigned long int arm_r0; + unsigned long int arm_r1; + unsigned long int arm_r2; + unsigned long int arm_r3; + unsigned long int arm_r4; + unsigned long int arm_r5; + unsigned long int arm_r6; + unsigned long int arm_r7; + unsigned long int arm_r8; + unsigned long int arm_r9; + unsigned long int arm_r10; + unsigned long int arm_fp; + unsigned long int arm_ip; + unsigned long int arm_sp; + unsigned long int arm_lr; + unsigned long int arm_pc; + unsigned long int arm_cpsr; + unsigned long fault_address; + } v21; + struct + { + unsigned long int magic; + struct pt_regs reg; + unsigned long int trap_no; + unsigned long int error_code; + unsigned long int oldmask; + } v20; +}; + +#define SIGCONTEXT_2_0_MAGIC 0x4B534154 + +#endif /* bits/armsigctx.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/bits/endian.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/bits/endian.h new file mode 100644 index 00000000..6e9967db --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/bits/endian.h @@ -0,0 +1,19 @@ +#ifndef _ENDIAN_H +# error "Never use directly; include instead." +#endif + +/* ARM can be either big or little endian. */ +#ifdef __ARMEB__ +# define __BYTE_ORDER __BIG_ENDIAN +#else +# define __BYTE_ORDER __LITTLE_ENDIAN +#endif + +/* FPA floating point units are always big-endian, irrespective of the + CPU endianness. VFP floating point units use the same endianness + as the rest of the system. */ +#if defined __VFP_FP__ || defined __MAVERICK__ +# define __FLOAT_WORD_ORDER __BYTE_ORDER +#else +# define __FLOAT_WORD_ORDER __BIG_ENDIAN +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/bits/fcntl.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/bits/fcntl.h new file mode 100644 index 00000000..7cc5a9dc --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/bits/fcntl.h @@ -0,0 +1,238 @@ +/* O_*, F_*, FD_* bit values for Linux. + Copyright (C) 1995-1998, 2000, 2004, 2006, 2007, 2008 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FCNTL_H +# error "Never use directly; include instead." +#endif + +#include +#ifdef __USE_GNU +# include +#endif + + +/* open/fcntl - O_SYNC is only implemented on blocks devices and on files + located on an ext2 file system */ +#define O_ACCMODE 0003 +#define O_RDONLY 00 +#define O_WRONLY 01 +#define O_RDWR 02 +#define O_CREAT 0100 /* not fcntl */ +#define O_EXCL 0200 /* not fcntl */ +#define O_NOCTTY 0400 /* not fcntl */ +#define O_TRUNC 01000 /* not fcntl */ +#define O_APPEND 02000 +#define O_NONBLOCK 04000 +#define O_NDELAY O_NONBLOCK +#define O_SYNC 010000 +#define O_FSYNC O_SYNC +#define O_ASYNC 020000 + +#ifdef __USE_GNU +# define O_DIRECTORY 040000 /* Must be a directory. */ +# define O_NOFOLLOW 0100000 /* Do not follow links. */ +# define O_DIRECT 0200000 /* Direct disk access. */ +# define O_NOATIME 01000000 /* Do not set atime. */ +# define O_CLOEXEC 02000000 /* Set close_on_exec. */ +#endif + +/* For now Linux has synchronisity options for data and read operations. + We define the symbols here but let them do the same as O_SYNC since + this is a superset. */ +#if defined __USE_POSIX199309 || defined __USE_UNIX98 +# define O_DSYNC O_SYNC /* Synchronize data. */ +# define O_RSYNC O_SYNC /* Synchronize read operations. */ +#endif + +#ifdef __USE_LARGEFILE64 +# define O_LARGEFILE 0400000 +#endif + +/* Values for the second argument to `fcntl'. */ +#define F_DUPFD 0 /* Duplicate file descriptor. */ +#define F_GETFD 1 /* Get file descriptor flags. */ +#define F_SETFD 2 /* Set file descriptor flags. */ +#define F_GETFL 3 /* Get file status flags. */ +#define F_SETFL 4 /* Set file status flags. */ +#ifndef __USE_FILE_OFFSET64 +# define F_GETLK 5 /* Get record locking info. */ +# define F_SETLK 6 /* Set record locking info (non-blocking). */ +# define F_SETLKW 7 /* Set record locking info (blocking). */ +#else +# define F_GETLK F_GETLK64 /* Get record locking info. */ +# define F_SETLK F_SETLK64 /* Set record locking info (non-blocking).*/ +# define F_SETLKW F_SETLKW64 /* Set record locking info (blocking). */ +#endif +#define F_GETLK64 12 /* Get record locking info. */ +#define F_SETLK64 13 /* Set record locking info (non-blocking). */ +#define F_SETLKW64 14 /* Set record locking info (blocking). */ + +#if defined __USE_BSD || defined __USE_UNIX98 +# define F_SETOWN 8 /* Get owner of socket (receiver of SIGIO). */ +# define F_GETOWN 9 /* Set owner of socket (receiver of SIGIO). */ +#endif + +#ifdef __USE_GNU +# define F_SETSIG 10 /* Set number of signal to be sent. */ +# define F_GETSIG 11 /* Get number of signal to be sent. */ +#endif + +#ifdef __USE_GNU +# define F_SETLEASE 1024 /* Set a lease. */ +# define F_GETLEASE 1025 /* Enquire what lease is active. */ +# define F_NOTIFY 1026 /* Request notfications on a directory. */ +# define F_DUPFD_CLOEXEC 1030 /* Duplicate file descriptor with + close-on-exit set on new fd. */ +#endif + +/* For F_[GET|SET]FD. */ +#define FD_CLOEXEC 1 /* actually anything with low bit set goes */ + +/* For posix fcntl() and `l_type' field of a `struct flock' for lockf(). */ +#define F_RDLCK 0 /* Read lock. */ +#define F_WRLCK 1 /* Write lock. */ +#define F_UNLCK 2 /* Remove lock. */ + +/* For old implementation of bsd flock(). */ +#define F_EXLCK 4 /* or 3 */ +#define F_SHLCK 8 /* or 4 */ + +#ifdef __USE_BSD +/* Operations for bsd flock(), also used by the kernel implementation. */ +# define LOCK_SH 1 /* shared lock */ +# define LOCK_EX 2 /* exclusive lock */ +# define LOCK_NB 4 /* or'd with one of the above to prevent + blocking */ +# define LOCK_UN 8 /* remove lock */ +#endif + +#ifdef __USE_GNU +# define LOCK_MAND 32 /* This is a mandatory flock: */ +# define LOCK_READ 64 /* ... which allows concurrent read operations. */ +# define LOCK_WRITE 128 /* ... which allows concurrent write operations. */ +# define LOCK_RW 192 /* ... Which allows concurrent read & write operations. */ +#endif + +#ifdef __USE_GNU +/* Types of directory notifications that may be requested with F_NOTIFY. */ +# define DN_ACCESS 0x00000001 /* File accessed. */ +# define DN_MODIFY 0x00000002 /* File modified. */ +# define DN_CREATE 0x00000004 /* File created. */ +# define DN_DELETE 0x00000008 /* File removed. */ +# define DN_RENAME 0x00000010 /* File renamed. */ +# define DN_ATTRIB 0x00000020 /* File changed attibutes. */ +# define DN_MULTISHOT 0x80000000 /* Don't remove notifier. */ +#endif + +struct flock + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ +#ifndef __USE_FILE_OFFSET64 + __off_t l_start; /* Offset where the lock begins. */ + __off_t l_len; /* Size of the locked area; zero means until EOF. */ +#else + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ +#endif + __pid_t l_pid; /* Process holding the lock. */ + }; + +#ifdef __USE_LARGEFILE64 +struct flock64 + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ + __pid_t l_pid; /* Process holding the lock. */ + }; +#endif + +/* Define some more compatibility macros to be backward compatible with + BSD systems which did not managed to hide these kernel macros. */ +#ifdef __USE_BSD +# define FAPPEND O_APPEND +# define FFSYNC O_FSYNC +# define FASYNC O_ASYNC +# define FNONBLOCK O_NONBLOCK +# define FNDELAY O_NDELAY +#endif /* Use BSD. */ + +/* Advise to `posix_fadvise'. */ +#ifdef __USE_XOPEN2K +# define POSIX_FADV_NORMAL 0 /* No further special treatment. */ +# define POSIX_FADV_RANDOM 1 /* Expect random page references. */ +# define POSIX_FADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define POSIX_FADV_WILLNEED 3 /* Will need these pages. */ +# define POSIX_FADV_DONTNEED 4 /* Don't need these pages. */ +# define POSIX_FADV_NOREUSE 5 /* Data will be accessed once. */ +#endif + + +#if defined __USE_GNU && defined __UCLIBC_LINUX_SPECIFIC__ +/* Flags for SYNC_FILE_RANGE. */ +# define SYNC_FILE_RANGE_WAIT_BEFORE 1 /* Wait upon writeout of all pages + in the range before performing the + write. */ +# define SYNC_FILE_RANGE_WRITE 2 /* Initiate writeout of all those + dirty pages in the range which are + not presently under writeback. */ +# define SYNC_FILE_RANGE_WAIT_AFTER 4 /* Wait upon writeout of all pages in + the range after performing the + write. */ + +/* Flags for SPLICE and VMSPLICE. */ +# define SPLICE_F_MOVE 1 /* Move pages instead of copying. */ +# define SPLICE_F_NONBLOCK 2 /* Don't block on the pipe splicing + (but we may still block on the fd + we splice from/to). */ +# define SPLICE_F_MORE 4 /* Expect more data. */ +# define SPLICE_F_GIFT 8 /* Pages passed in are a gift. */ +#endif + +__BEGIN_DECLS + +#if defined __USE_GNU && defined __UCLIBC_LINUX_SPECIFIC__ + +/* Provide kernel hint to read ahead. */ +extern ssize_t readahead (int __fd, __off64_t __offset, size_t __count) + __THROW; + +/* Selective file content synch'ing. */ +extern int sync_file_range (int __fd, __off64_t __from, __off64_t __to, + unsigned int __flags); + +/* Splice address range into a pipe. */ +extern ssize_t vmsplice (int __fdout, const struct iovec *__iov, + size_t __count, unsigned int __flags); + +/* Splice two files together. */ +extern ssize_t splice (int __fdin, __off64_t *__offin, int __fdout, + __off64_t *__offout, size_t __len, + unsigned int __flags); + +/* In-kernel implementation of tee for pipe buffers. */ +extern ssize_t tee (int __fdin, int __fdout, size_t __len, + unsigned int __flags); + +#endif +__END_DECLS + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/bits/fenv.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/bits/fenv.h new file mode 100644 index 00000000..3764d774 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/bits/fenv.h @@ -0,0 +1,99 @@ +/* Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FENV_H +# error "Never use directly; include instead." +#endif + +#ifdef __MAVERICK__ + +/* Define bits representing exceptions in the FPU status word. */ +enum + { + FE_INVALID = 1, +#define FE_INVALID FE_INVALID + FE_OVERFLOW = 4, +#define FE_OVERFLOW FE_OVERFLOW + FE_UNDERFLOW = 8, +#define FE_UNDERFLOW FE_UNDERFLOW + FE_INEXACT = 16, +#define FE_INEXACT FE_INEXACT + }; + +/* Amount to shift by to convert an exception to a mask bit. */ +#define FE_EXCEPT_SHIFT 5 + +/* All supported exceptions. */ +#define FE_ALL_EXCEPT \ + (FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW | FE_INEXACT) + +/* IEEE rounding modes. */ +enum + { + FE_TONEAREST = 0, +#define FE_TONEAREST FE_TONEAREST + FE_TOWARDZERO = 0x400, +#define FE_TOWARDZERO FE_TOWARDZERO + FE_DOWNWARD = 0x800, +#define FE_DOWNWARD FE_DOWNWARD + FE_UPWARD = 0xc00, +#define FE_UPWARD FE_UPWARD + }; + +#define FE_ROUND_MASK (FE_UPWARD) + +#else /* !__MAVERICK__ */ + +/* Define bits representing exceptions in the FPU status word. */ +enum + { + FE_INVALID = 1, +#define FE_INVALID FE_INVALID + FE_DIVBYZERO = 2, +#define FE_DIVBYZERO FE_DIVBYZERO + FE_OVERFLOW = 4, +#define FE_OVERFLOW FE_OVERFLOW + FE_UNDERFLOW = 8, +#define FE_UNDERFLOW FE_UNDERFLOW + }; + +/* Amount to shift by to convert an exception to a mask bit. */ +#define FE_EXCEPT_SHIFT 16 + +/* All supported exceptions. */ +#define FE_ALL_EXCEPT \ + (FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW) + +/* The ARM FPU basically only supports round-to-nearest. Other rounding + modes exist, but you have to encode them in the actual instruction. */ +#define FE_TONEAREST 0 + +#endif /* __MAVERICK__ */ + +/* Type representing exception flags. */ +typedef unsigned long int fexcept_t; + +/* Type representing floating-point environment. */ +typedef struct + { + unsigned long int __cw; + } +fenv_t; + +/* If the default argument is used we use this value. */ +#define FE_DFL_ENV ((fenv_t *) -1l) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/bits/huge_val.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/bits/huge_val.h new file mode 100644 index 00000000..a215f3c0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/bits/huge_val.h @@ -0,0 +1,72 @@ +/* `HUGE_VAL' constant for IEEE 754 machines (where it is infinity). + Used by and functions for overflow. + ARM version. + Copyright (C) 1992, 95, 96, 97, 98, 99, 2000, 2004 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _MATH_H +# error "Never use directly; include instead." +#endif + +/* IEEE positive infinity (-HUGE_VAL is negative infinity). */ + +#if __GNUC_PREREQ(3,3) +# define HUGE_VAL (__builtin_huge_val()) +#elif __GNUC_PREREQ(2,96) +# define HUGE_VAL (__extension__ 0x1.0p2047) +#elif defined __GNUC__ + +#ifndef __CONFIG_ARM_EABI__ +# define HUGE_VAL \ + (__extension__ \ + ((union { unsigned __l __attribute__((__mode__(__DI__))); double __d; }) \ + { __l: 0x000000007ff00000ULL }).__d) +#else +# define HUGE_VAL \ + (__extension__ \ + ((union { unsigned __l __attribute__((__mode__(__DI__))); double __d; }) \ + { __l: 0x7ff0000000000000ULL }).__d) +#endif + +#else /* not GCC */ + +# include + +typedef union { unsigned char __c[8]; double __d; } __huge_val_t; + +#ifndef __CONFIG_ARM_EABI__ +# if __BYTE_ORDER == __BIG_ENDIAN +# define __HUGE_VAL_bytes { 0, 0, 0, 0, 0x7f, 0xf0, 0, 0 } +# endif +# if __BYTE_ORDER == __LITTLE_ENDIAN +# define __HUGE_VAL_bytes { 0, 0, 0xf0, 0x7f, 0, 0, 0, 0 } +# endif +#else +# if __BYTE_ORDER == __BIG_ENDIAN +# define __HUGE_VAL_bytes { 0x7f, 0xf0, 0, 0, 0, 0, 0, 0 } +# endif +# if __BYTE_ORDER == __LITTLE_ENDIAN +# define __HUGE_VAL_bytes { 0, 0, 0, 0, 0, 0, 0xf0, 0x7f } +# endif +#endif + +static __huge_val_t __huge_val = { __HUGE_VAL_bytes }; +# define HUGE_VAL (__huge_val.__d) + +#endif /* GCC. */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/bits/kernel_stat.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/bits/kernel_stat.h new file mode 100644 index 00000000..2ca63a22 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/bits/kernel_stat.h @@ -0,0 +1,68 @@ +#ifndef _BITS_STAT_STRUCT_H +#define _BITS_STAT_STRUCT_H + +#ifndef _LIBC +#error bits/kernel_stat.h is for internal uClibc use only! +#endif + +/* This file provides whatever this particular arch's kernel thinks + * struct kernel_stat should look like... It turns out each arch has a + * different opinion on the subject... */ + +struct kernel_stat { +#if defined(__ARMEB__) + unsigned short st_dev; + unsigned short __pad1; +#else + unsigned long st_dev; +#endif + unsigned long st_ino; + unsigned short st_mode; + unsigned short st_nlink; + unsigned short st_uid; + unsigned short st_gid; +#if defined(__ARMEB__) + unsigned short st_rdev; + unsigned short __pad2; +#else + unsigned long st_rdev; +#endif + unsigned long st_size; + unsigned long st_blksize; + unsigned long st_blocks; + struct timespec st_atim; + struct timespec st_mtim; + struct timespec st_ctim; + unsigned long __unused4; + unsigned long __unused5; +}; + +struct kernel_stat64 { + unsigned long long st_dev; + unsigned char __pad0[4]; + +#define _HAVE_STAT64___ST_INO + unsigned long __st_ino; + unsigned int st_mode; + unsigned int st_nlink; + unsigned long st_uid; + unsigned long st_gid; + + unsigned long long st_rdev; + unsigned char __pad3[4]; + + long long st_size; + unsigned long st_blksize; + unsigned long long st_blocks; /* Number 512-byte blocks allocated. */ + + struct timespec st_atim; + struct timespec st_mtim; + struct timespec st_ctim; + unsigned long long st_ino; +#ifndef __ARM_EABI__ +} __attribute__((packed)); +#else +}; +#endif + +#endif /* _BITS_STAT_STRUCT_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/bits/kernel_types.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/bits/kernel_types.h new file mode 100644 index 00000000..766a3062 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/bits/kernel_types.h @@ -0,0 +1,44 @@ +/* Note that we use the exact same include guard #define names + * as asm/posix_types.h. This will avoid gratuitous conflicts + * with the posix_types.h kernel header, and will ensure that + * our private content, and not the kernel header, will win. + * -Erik + */ +#ifndef __ARCH_ARM_POSIX_TYPES_H +#define __ARCH_ARM_POSIX_TYPES_H + +typedef unsigned short __kernel_dev_t; +typedef unsigned long __kernel_ino_t; +typedef unsigned short __kernel_mode_t; +typedef unsigned short __kernel_nlink_t; +typedef long __kernel_off_t; +typedef int __kernel_pid_t; +typedef unsigned short __kernel_ipc_pid_t; +typedef unsigned short __kernel_uid_t; +typedef unsigned short __kernel_gid_t; +typedef unsigned int __kernel_size_t; +typedef int __kernel_ssize_t; +typedef int __kernel_ptrdiff_t; +typedef long __kernel_time_t; +typedef long __kernel_suseconds_t; +typedef long __kernel_clock_t; +typedef int __kernel_daddr_t; +typedef char * __kernel_caddr_t; +typedef unsigned short __kernel_uid16_t; +typedef unsigned short __kernel_gid16_t; +typedef unsigned int __kernel_uid32_t; +typedef unsigned int __kernel_gid32_t; +typedef unsigned short __kernel_old_uid_t; +typedef unsigned short __kernel_old_gid_t; +typedef long long __kernel_loff_t; +typedef __kernel_dev_t __kernel_old_dev_t; + +typedef struct { +#ifdef __USE_ALL + int val[2]; +#else + int __val[2]; +#endif +} __kernel_fsid_t; + +#endif /* __ARCH_ARM_POSIX_TYPES_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/bits/mathdef.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/bits/mathdef.h new file mode 100644 index 00000000..1be9b59d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/bits/mathdef.h @@ -0,0 +1,46 @@ +/* Copyright (C) 1999, 2000, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#if !defined _MATH_H && !defined _COMPLEX_H +# error "Never use directly; include instead" +#endif + +#if defined __USE_ISOC99 && defined _MATH_H && !defined _MATH_H_MATHDEF +# define _MATH_H_MATHDEF 1 + +/* GCC does not promote `float' values to `double'. */ +typedef float float_t; /* `float' expressions are evaluated as + `float'. */ +typedef double double_t; /* `double' expressions are evaluated as + `double'. */ + +/* The values returned by `ilogb' for 0 and NaN respectively. */ +# define FP_ILOGB0 (-2147483647) +# define FP_ILOGBNAN (2147483647) + +#endif /* ISO C99 */ + +#ifdef L4_DISABLE_LONG_DOUBLE_MATH +#ifndef __NO_LONG_DOUBLE_MATH +/* Signal that we do not really have a `long double'. This disables the + declaration of all the `long double' function variants. */ +/* XXX The FPA does support this but the patterns in GCC are currently + turned off. */ +# define __NO_LONG_DOUBLE_MATH 1 +#endif +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/bits/setjmp.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/bits/setjmp.h new file mode 100644 index 00000000..ac52f128 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/bits/setjmp.h @@ -0,0 +1,52 @@ +/* Copyright (C) 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Define the machine-dependent type `jmp_buf'. ARM version. */ +#ifndef _BITS_SETJMP_H +#define _BITS_SETJMP_H 1 + +#if !defined _SETJMP_H && !defined _PTHREAD_H +# error "Never include directly; use instead." +#endif + +#ifndef _ASM +/* Jump buffer contains v1-v6, sl, fp, sp and pc. Other registers are not + saved. */ +#ifdef __ARM_EABI__ +/* The exact set of registers saved may depend on the particular core + in use, as some coprocessor registers may need to be saved. The C + Library ABI requires that the buffer be 8-byte aligned, and + recommends that the buffer contain 64 words. The first 28 words + are occupied by v1-v6, sl, fp, sp, pc, d8-d15, and fpscr. (Note + that d8-15 require 17 words, due to the use of fstmx.) */ +typedef int __jmp_buf[64] __attribute__((aligned (8))); +#elif defined __MAVERICK__ || defined __IWMMXT__ +typedef int __jmp_buf[34]; +#else +typedef int __jmp_buf[22]; +#endif +#endif + +#define __JMP_BUF_SP 8 + +/* Test if longjmp to JMPBUF would unwind the frame + containing a local variable at ADDRESS. */ +#define _JMPBUF_UNWINDS(jmpbuf, address) \ + ((void *) (address) < (void *) (jmpbuf[__JMP_BUF_SP])) + +#endif /* bits/setjmp.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/bits/shm.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/bits/shm.h new file mode 100644 index 00000000..c89c00a1 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/bits/shm.h @@ -0,0 +1,103 @@ +/* Copyright (C) 1995,1996,1997,2000,2002,2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_SHM_H +# error "Never include directly; use instead." +#endif + +#include + +/* Permission flag for shmget. */ +#define SHM_R 0400 /* or S_IRUGO from */ +#define SHM_W 0200 /* or S_IWUGO from */ + +/* Flags for `shmat'. */ +#define SHM_RDONLY 010000 /* attach read-only else read-write */ +#define SHM_RND 020000 /* round attach address to SHMLBA */ +#define SHM_REMAP 040000 /* take-over region on attach */ + +/* Commands for `shmctl'. */ +#define SHM_LOCK 11 /* lock segment (root only) */ +#define SHM_UNLOCK 12 /* unlock segment (root only) */ + +__BEGIN_DECLS + +/* Segment low boundary address multiple. */ +#define SHMLBA (__getpagesize () << 2) +extern int __getpagesize (void) __THROW __attribute__ ((__const__)); + + +/* Type to count number of attaches. */ +typedef unsigned long int shmatt_t; + +/* Data structure describing a set of semaphores. */ +struct shmid_ds + { + struct ipc_perm shm_perm; /* operation permission struct */ + size_t shm_segsz; /* size of segment in bytes */ + __time_t shm_atime; /* time of last shmat() */ + unsigned long int __unused1; + __time_t shm_dtime; /* time of last shmdt() */ + unsigned long int __unused2; + __time_t shm_ctime; /* time of last change by shmctl() */ + unsigned long int __unused3; + __pid_t shm_cpid; /* pid of creator */ + __pid_t shm_lpid; /* pid of last shmop */ + shmatt_t shm_nattch; /* number of current attaches */ + unsigned long int __unused4; + unsigned long int __unused5; + }; + +#ifdef __USE_MISC + +/* ipcs ctl commands */ +# define SHM_STAT 13 +# define SHM_INFO 14 + +/* shm_mode upper byte flags */ +# define SHM_DEST 01000 /* segment will be destroyed on last detach */ +# define SHM_LOCKED 02000 /* segment will not be swapped */ +# define SHM_HUGETLB 04000 /* segment is mapped via hugetlb */ +# define SHM_NORESERVE 010000 /* don't check for reservations */ + +struct shminfo + { + unsigned long int shmmax; + unsigned long int shmmin; + unsigned long int shmmni; + unsigned long int shmseg; + unsigned long int shmall; + unsigned long int __unused1; + unsigned long int __unused2; + unsigned long int __unused3; + unsigned long int __unused4; + }; + +struct shm_info + { + int used_ids; + unsigned long int shm_tot; /* total allocated shm */ + unsigned long int shm_rss; /* total resident shm */ + unsigned long int shm_swp; /* total swapped shm */ + unsigned long int swap_attempts; + unsigned long int swap_successes; + }; + +#endif /* __USE_MISC */ + +__END_DECLS diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/bits/sigcontextinfo.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/bits/sigcontextinfo.h new file mode 100644 index 00000000..67167f90 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/bits/sigcontextinfo.h @@ -0,0 +1,51 @@ +/* Copyright (C) 1999, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Philip Blundell , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +#define SIGCONTEXT int _a2, int _a3, int _a4, union k_sigcontext +#define SIGCONTEXT_EXTRA_ARGS _a2, _a3, _a4, + +/* The sigcontext structure changed between 2.0 and 2.1 kernels. On any + modern system we should be able to assume that the "new" format will be + in use. */ +#if LINUX_VERSION_CODE > 131328 + +#define GET_PC(ctx) ((void *) ctx.v21.arm_pc) +#define GET_FRAME(ctx) ADVANCE_STACK_FRAME ((void *) ctx.v21.arm_fp) +#define GET_STACK(ctx) ((void *) ctx.v21.arm_sp) + +#else + +#define GET_PC(ctx) ((void *)((ctx.v20.magic == SIGCONTEXT_2_0_MAGIC) ? \ + ctx.v20.reg.ARM_pc : ctx.v21.arm_pc)) +#define GET_FRAME(ctx) \ + ADVANCE_STACK_FRAME((void *)((ctx.v20.magic == SIGCONTEXT_2_0_MAGIC) ? \ + ctx.v20.reg.ARM_fp : ctx.v21.arm_fp)) +#define GET_STACK(ctx) ((void *)((ctx.v20.magic == SIGCONTEXT_2_0_MAGIC) ? \ + ctx.v20.reg.ARM_sp : ctx.v21.arm_sp)) + +#endif + +#define ADVANCE_STACK_FRAME(frm) \ + ((struct layout *)frm - 1) + +#define CALL_SIGHANDLER(handler, signo, ctx) \ + (handler)((signo), SIGCONTEXT_EXTRA_ARGS (ctx)) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/bits/stackinfo.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/bits/stackinfo.h new file mode 100644 index 00000000..2410ba9b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/bits/stackinfo.h @@ -0,0 +1,28 @@ +/* Copyright (C) 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This file contains a bit of information about the stack allocation + of the processor. */ + +#ifndef _STACKINFO_H +#define _STACKINFO_H 1 + +/* On Arm the stack grows down. */ +#define _STACK_GROWS_DOWN 1 + +#endif /* stackinfo.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/bits/syscalls.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/bits/syscalls.h new file mode 100644 index 00000000..92bba7da --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/bits/syscalls.h @@ -0,0 +1,139 @@ +#ifndef _BITS_SYSCALLS_H +#define _BITS_SYSCALLS_H +#ifndef _SYSCALL_H +# error "Never use directly; include instead." +#endif + +/* + Some of the sneaky macros in the code were taken from + glibc-2.3.2/sysdeps/unix/sysv/linux/arm/sysdep.h +*/ + +#ifdef __ASSEMBLER__ + +/* Call a given syscall, with arguments loaded. For EABI, we must + save and restore r7 for the syscall number. Unlike the DO_CALL + macro in glibc, this macro does not load syscall arguments. */ +#undef DO_CALL +#if defined(__ARM_EABI__) +#define DO_CALL(syscall_name) \ + mov ip, r7; \ + ldr r7, =SYS_ify (syscall_name); \ + swi 0x0; \ + mov r7, ip; +#else +#define DO_CALL(syscall_name) \ + swi SYS_ify (syscall_name); +#endif + +#else + +#include + +#define INLINE_SYSCALL_NCS(name, nr, args...) \ + ({ unsigned int _inline_sys_result = INTERNAL_SYSCALL_NCS (name, , nr, args); \ + if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (_inline_sys_result, ), 0)) \ + { \ + __set_errno (INTERNAL_SYSCALL_ERRNO (_inline_sys_result, )); \ + _inline_sys_result = (unsigned int) -1; \ + } \ + (int) _inline_sys_result; }) + +#if !defined(__thumb__) +#if defined(__ARM_EABI__) +#define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \ + ({unsigned int __internal_sys_result; \ + { \ + register int __a1 __asm__ ("r0"), _nr __asm__ ("r7"); \ + LOAD_ARGS_##nr (args) \ + _nr = (name); \ + __asm__ __volatile__ ("swi 0x0 @ syscall " #name \ + : "=r" (__a1) \ + : "r" (_nr) ASM_ARGS_##nr \ + : "memory"); \ + __internal_sys_result = __a1; \ + } \ + (int) __internal_sys_result; }) +#else /* defined(__ARM_EABI__) */ + +#define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \ + ({ unsigned int __internal_sys_result; \ + { \ + register int __a1 __asm__ ("a1"); \ + LOAD_ARGS_##nr (args) \ + __asm__ __volatile__ ("swi %1 @ syscall " #name \ + : "=r" (__a1) \ + : "i" (name) ASM_ARGS_##nr \ + : "memory"); \ + __internal_sys_result = __a1; \ + } \ + (int) __internal_sys_result; }) +#endif +#else /* !defined(__thumb__) */ +/* We can't use push/pop inside the asm because that breaks + unwinding (ie. thread cancellation). + */ +#define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \ + ({ unsigned int __internal_sys_result; \ + { \ + int _sys_buf[2]; \ + register int __a1 __asm__ ("a1"); \ + register int *_v3 __asm__ ("v3") = _sys_buf; \ + *_v3 = (int) (name); \ + LOAD_ARGS_##nr (args) \ + __asm__ __volatile__ ("str r7, [v3, #4]\n" \ + "\tldr r7, [v3]\n" \ + "\tswi 0 @ syscall " #name "\n" \ + "\tldr r7, [v3, #4]" \ + : "=r" (__a1) \ + : "r" (_v3) ASM_ARGS_##nr \ + : "memory"); \ + __internal_sys_result = __a1; \ + } \ + (int) __internal_sys_result; }) +#endif /*!defined(__thumb__)*/ + +#define INTERNAL_SYSCALL_ERROR_P(val, err) \ + ((unsigned int) (val) >= 0xfffff001u) + +#define LOAD_ARGS_0() +#define ASM_ARGS_0 +#define LOAD_ARGS_1(a1) \ + int __a1tmp = (int) (a1); \ + LOAD_ARGS_0 () \ + __a1 = __a1tmp; +#define ASM_ARGS_1 ASM_ARGS_0, "r" (__a1) +#define LOAD_ARGS_2(a1, a2) \ + int __a2tmp = (int) (a2); \ + LOAD_ARGS_1 (a1) \ + register int __a2 __asm__ ("a2") = __a2tmp; +#define ASM_ARGS_2 ASM_ARGS_1, "r" (__a2) +#define LOAD_ARGS_3(a1, a2, a3) \ + int __a3tmp = (int) (a3); \ + LOAD_ARGS_2 (a1, a2) \ + register int __a3 __asm__ ("a3") = __a3tmp; +#define ASM_ARGS_3 ASM_ARGS_2, "r" (__a3) +#define LOAD_ARGS_4(a1, a2, a3, a4) \ + int __a4tmp = (int) (a4); \ + LOAD_ARGS_3 (a1, a2, a3) \ + register int __a4 __asm__ ("a4") = __a4tmp; +#define ASM_ARGS_4 ASM_ARGS_3, "r" (__a4) +#define LOAD_ARGS_5(a1, a2, a3, a4, a5) \ + int _v1tmp = (int) (a5); \ + LOAD_ARGS_4 (a1, a2, a3, a4) \ + register int _v1 __asm__ ("v1") = _v1tmp; +#define ASM_ARGS_5 ASM_ARGS_4, "r" (_v1) +#define LOAD_ARGS_6(a1, a2, a3, a4, a5, a6) \ + int _v2tmp = (int) (a6); \ + LOAD_ARGS_5 (a1, a2, a3, a4, a5) \ + register int _v2 __asm__ ("v2") = _v2tmp; +#define ASM_ARGS_6 ASM_ARGS_5, "r" (_v2) +#define LOAD_ARGS_7(a1, a2, a3, a4, a5, a6, a7) \ + int _v3tmp = (int) (a7); \ + LOAD_ARGS_6 (a1, a2, a3, a4, a5, a6) \ + register int _v3 __asm__ ("v3") = _v3tmp; +#define ASM_ARGS_7 ASM_ARGS_6, "r" (_v3) + + +#endif /* __ASSEMBLER__ */ +#endif /* _BITS_SYSCALLS_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/bits/uClibc_arch_features.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/bits/uClibc_arch_features.h new file mode 100644 index 00000000..14621d9b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/bits/uClibc_arch_features.h @@ -0,0 +1,51 @@ +/* + * Track misc arch-specific features that aren't config options + */ + +#ifndef _BITS_UCLIBC_ARCH_FEATURES_H +#define _BITS_UCLIBC_ARCH_FEATURES_H + +/* instruction used when calling abort() to kill yourself */ +#define __UCLIBC_ABORT_INSTRUCTION__ "bl abort" + +/* can your target use syscall6() for mmap ? */ +#undef __UCLIBC_MMAP_HAS_6_ARGS__ + +/* does your target use syscall4() for truncate64 ? (32bit arches only) */ +#ifdef __ARM_EABI__ +#define __UCLIBC_TRUNCATE64_HAS_4_ARGS__ +#else +#undef __UCLIBC_TRUNCATE64_HAS_4_ARGS__ +#endif + +/* does your target have a broken create_module() ? */ +#define __UCLIBC_BROKEN_CREATE_MODULE__ + +/* does your target have to worry about older [gs]etrlimit() ? */ +#undef __UCLIBC_HANDLE_OLDER_RLIMIT__ + +/* does your target have an asm .set ? */ +#define __UCLIBC_HAVE_ASM_SET_DIRECTIVE__ + +/* define if target doesn't like .global */ +#undef __UCLIBC_ASM_GLOBAL_DIRECTIVE__ + +/* define if target supports .weak */ +#define __UCLIBC_HAVE_ASM_WEAK_DIRECTIVE__ + +/* define if target supports .weakext */ +#undef __UCLIBC_HAVE_ASM_WEAKEXT_DIRECTIVE__ + +/* needed probably only for ppc64 */ +#undef __UCLIBC_HAVE_ASM_GLOBAL_DOT_NAME__ + +/* define if target supports CFI pseudo ops */ +#undef __UCLIBC_HAVE_ASM_CFI_DIRECTIVES__ + +/* define if target supports IEEE signed zero floats */ +#define __UCLIBC_HAVE_SIGNED_ZERO__ + +/* only weird assemblers generally need this */ +#undef __UCLIBC_ASM_LINE_SEP__ + +#endif /* _BITS_UCLIBC_ARCH_FEATURES_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/bits/wordsize.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/bits/wordsize.h new file mode 100644 index 00000000..ba643b60 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/bits/wordsize.h @@ -0,0 +1,19 @@ +/* Copyright (C) 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define __WORDSIZE 32 diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/brk.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/brk.c new file mode 100644 index 00000000..9e41c570 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/brk.c @@ -0,0 +1,41 @@ +/* brk system call for Linux/ARM. + Copyright (C) 1995, 1996 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + + +/* This must be initialized data because commons can't have aliases. */ +void *__curbrk attribute_hidden = 0; + +int brk (void *addr) +{ + void *newbrk = (void*)INTERNAL_SYSCALL(brk, , 1, addr); + + __curbrk = newbrk; + + if (newbrk < addr) { + __set_errno (ENOMEM); + return -1; + } + + return 0; +} +libc_hidden_def(brk) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/bsd-_setjmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/bsd-_setjmp.S new file mode 100644 index 00000000..a05570df --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/bsd-_setjmp.S @@ -0,0 +1,61 @@ +/* BSD `_setjmp' entry point to `sigsetjmp (..., 0)'. ARM version. + Copyright (C) 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +/* This just does a tail-call to `__sigsetjmp (ARG, 0)'. + We cannot do it in C because it must be a tail-call, so frame-unwinding + in setjmp doesn't clobber the state restored by longjmp. */ + +.global _setjmp +.type _setjmp,%function +.align 2 +#if defined(THUMB1_ONLY) +.thumb_func +_setjmp: + mov r1, #0 +#ifdef __PIC__ + ldr r3, .L_GOT + adr r2, .L_GOT + add r3, r2, r3 + + ldr r2, .L_GOT+4 /* __sigsetjmp */ + ldr r2, [r2, r3] + bx r2 + + .align 2 +.L_GOT: + .word _GLOBAL_OFFSET_TABLE_-.L_GOT + .word __sigsetjmp(GOT) +#else + ldr r2, =__sigsetjmp + bx r2 +.pool +#endif +#else +_setjmp: + mov r1, #0 +#ifdef __PIC__ + b __sigsetjmp(PLT) +#else + b __sigsetjmp +#endif +#endif + +.size _setjmp,.-_setjmp diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/bsd-setjmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/bsd-setjmp.S new file mode 100644 index 00000000..d7ca72ad --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/bsd-setjmp.S @@ -0,0 +1,61 @@ +/* BSD `setjmp' entry point to `sigsetjmp (..., 1)'. ARM version. + Copyright (C) 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +/* This just does a tail-call to `__sigsetjmp (ARG, 1)'. + We cannot do it in C because it must be a tail-call, so frame-unwinding + in setjmp doesn't clobber the state restored by longjmp. */ + +.global setjmp +.type setjmp,%function +.align 2 +#if defined(THUMB1_ONLY) +.thumb_func +setjmp: + mov r1, #1 +#ifdef __PIC__ + ldr r3, .L_GOT + adr r2, .L_GOT + add r3, r2, r3 + + ldr r2, .L_GOT+4 /* __sigsetjmp */ + ldr r2, [r2, r3] + bx r2 + + .align 2 +.L_GOT: + .word _GLOBAL_OFFSET_TABLE_-.L_GOT + .word __sigsetjmp(GOT) +#else + ldr r2, =__sigsetjmp + bx r2 +.pool +#endif +#else +setjmp: + mov r1, #1 +#ifdef __PIC__ + b __sigsetjmp(PLT) +#else + b __sigsetjmp +#endif +#endif + +.size setjmp,.-setjmp diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/clone.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/clone.S new file mode 100644 index 00000000..fdc05b88 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/clone.S @@ -0,0 +1,138 @@ +/* Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Pat Beirne + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* clone() is even more special than fork() as it mucks with stacks + and invokes a function in the right context after its all over. */ + +#define _ERRNO_H +#include +#include +#include +#include + +#if defined(__NR_clone) +/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg); */ + +.text +.global __clone +.type __clone,%function +.align 2 +#if defined(THUMB1_ONLY) +.thumb_func +__clone: + @ sanity check args + cmp r0, #0 + beq __einval + cmp r1, #0 + beq __einval + + @ insert the args onto the new stack + sub r1, r1, #8 + str r3, [r1, #4] + @ save the function pointer as the 0th element + str r0, [r1] + + @ do the system call + @ get flags + mov r0, r2 + @ new sp is already in r1 + @ load remaining arguments off the stack + stmfd sp!, {r4} + ldr r2, [sp, #4] + ldr r3, [sp, #8] + ldr r4, [sp, #12] + DO_CALL (clone) + movs a1, a1 + blt __error + ldmnefd sp!, {r4} + beq 1f + bx lr +1: + + @ pick the function arg and call address off the stack and execute + ldr r0, [sp, #4] + ldr r1, [sp] + bl 2f @ blx r1 + + @ and we are done, passing the return value through r0 + bl HIDDEN_JUMPTARGET(_exit) + @ Should never return + b . + +2: + bx r1 + +__einval: + ldr r0, =-EINVAL +__error: + push {r3, lr} + bl __syscall_error + POP_RET +.pool +#else +__clone: + @ sanity check args + cmp r0, #0 + IT(te, ne) + cmpne r1, #0 + moveq r0, #-EINVAL + beq __error + + @ insert the args onto the new stack + sub r1, r1, #8 + str r3, [r1, #4] + @ save the function pointer as the 0th element + str r0, [r1] + + @ do the system call + @ get flags + mov r0, r2 + @ new sp is already in r1 + @ load remaining arguments off the stack + stmfd sp!, {r4} + ldr r2, [sp, #4] + ldr r3, [sp, #8] + ldr r4, [sp, #12] + DO_CALL (clone) + movs a1, a1 + blt __error + ldmnefd sp!, {r4} + IT(t, ne) +#if defined(__USE_BX__) + bxne lr +#else + movne pc, lr +#endif + + @ pick the function arg and call address off the stack and execute + ldr r0, [sp, #4] + mov lr, pc + ldr pc, [sp] + + @ and we are done, passing the return value through r0 + b HIDDEN_JUMPTARGET(_exit) + +__error: + b __syscall_error +#endif + +.size __clone,.-__clone +weak_alias(__clone, clone) + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/crt1.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/crt1.S new file mode 100644 index 00000000..f2d9507b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/crt1.S @@ -0,0 +1,253 @@ +/* Startup code for ARM & ELF + Copyright (C) 1995, 1996, 1997, 1998, 2001, 2002, 2005 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file with other + programs, and to distribute those programs without any restriction + coming from the use of this file. (The GNU Lesser General Public + License restrictions do apply in other respects; for example, they + cover modification of the file, and distribution when not linked + into another program.) + + Note that people who make modified versions of this file are not + obligated to grant this special exception for their modified + versions; it is their choice whether to do so. The GNU Lesser + General Public License gives permission to release a modified + version without this exception; this exception also makes it + possible to release a modified version which carries forward this + exception. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This is the canonical entry point, usually the first thing in the text + segment. + + Note that the code in the .init section has already been run. + This includes _init and _libc_init + + + At this entry point, most registers' values are unspecified, except: + + a1 Contains a function pointer to be registered with `atexit'. + This is how the dynamic linker arranges to have DT_FINI + functions called for shared libraries that have been loaded + before this code runs. + + sp The stack contains the arguments and environment: + 0(sp) argc + 4(sp) argv[0] + ... + (4*argc)(sp) NULL + (4*(argc+1))(sp) envp[0] + ... + NULL +*/ +/* + For uClinux it looks like this: + + argc argument counter (integer) + argv char *argv[] + envp char *envp[] + argv[0] program name (pointer) + argv[1...N] program args (pointers) + argv[argc-1] end of args (integer) + NULL + env[0...N] environment variables (pointers) + NULL + +ARM register quick reference: + + Name Number ARM Procedure Calling Standard Role + + a1 r0 argument 1 / integer result / scratch register / argc + a2 r1 argument 2 / scratch register / argv + a3 r2 argument 3 / scratch register / envp + a4 r3 argument 4 / scratch register + v1 r4 register variable + v2 r5 register variable + v3 r6 register variable + v4 r7 register variable + v5 r8 register variable + sb/v6 r9 static base / register variable + sl/v7 r10 stack limit / stack chunk handle / reg. variable + fp r11 frame pointer + ip r12 scratch register / new-sb in inter-link-unit calls + sp r13 lower end of current stack frame + lr r14 link address / scratch register + pc r15 program counter +*/ + +#include +#include + +.text + .globl _start + .type _start,%function + .type _init,%function + .type _fini,%function +#ifndef __UCLIBC_CTOR_DTOR__ + .weak _init + .weak _fini +#endif + +#if defined(THUMB1_ONLY) +.thumb_func +_start: + /* Clear the frame pointer since this is the outermost frame. */ + mov r3, #0 + mov fp, r3 + +#ifdef __ARCH_USE_MMU__ + /* Pop argc off the stack and save a pointer to argv */ + pop {a2} + mov a3, sp +#else + /* + * uClinux/arm stacks look a little different from normal + * MMU-full Linux/arm stacks (for no good reason) + */ + /* pull argc and argv off the stack. We are going to push 3 + * arguments, so pop one here to maintain doubleword alignment. */ + pop {a2} + ldr a3, [sp] +#endif + + /* Push stack limit and rtld_fini */ + push {a1, a3} + +#ifdef __PIC__ + ldr r4, .L_GOT + adr r5, .L_GOT + add r4, r5, r4 + + ldr r5, .L_GOT+4 /* _fini */ + ldr a1, [r4, r5] + push {a1} /* Push _fini */ + + ldr r5, .L_GOT+8 /* _init */ + ldr a4, [r4, r5] + + ldr r5, .L_GOT+12 /* main */ + ldr a1, [r4, r5] + +#else + /* Fetch address of fini */ + ldr r4, =_fini + /* Push fini */ + push {r4} + + /* Set up the other arguments in registers */ + ldr a1, =main + ldr a4, =_init +#endif + /* __uClibc_main (main, argc, argv, init, fini, rtld_fini, stack_end) */ + /* Let the libc call main and exit with its return code. */ + bl __uClibc_main + + /* should never get here....*/ + bl abort +.pool + +#ifdef __PIC__ +.L_GOT: + .word _GLOBAL_OFFSET_TABLE_-.L_GOT + .word _fini(GOT) + .word _init(GOT) + .word main(GOT) +#endif +#else /* !THUMB1_ONLY */ +_start: + /* Clear the frame pointer and link register since this is the outermost frame. */ + mov fp, #0 + mov lr, #0 + +#ifdef __ARCH_USE_MMU__ + /* Pop argc off the stack and save a pointer to argv */ + ldr a2, [sp], #4 + mov a3, sp +#else + /* + * uClinux/arm stacks look a little different from normal + * MMU-full Linux/arm stacks (for no good reason) + */ + /* pull argc and argv off the stack. We are going to push 3 + * arguments, so pop one here to maintain doubleword alignment. */ + ldr a2, [sp], #4 + ldr a3, [sp] +#endif + + /* Push stack limit */ + str a3, [sp, #-4]! + + /* Push rtld_fini */ + str a1, [sp, #-4]! + +#ifdef __PIC__ + ldr sl, .L_GOT + adr a4, .L_GOT + add sl, sl, a4 + + ldr ip, .L_GOT+4 /* _fini */ + ldr a1, [sl, ip] + str a1, [sp, #-4]! /* Push _fini */ + + ldr ip, .L_GOT+8 /* _init */ + ldr a4, [sl, ip] + + ldr ip, .L_GOT+12 /* main */ + ldr a1, [sl, ip] + + /* __uClibc_main (main, argc, argv, init, fini, rtld_fini, stack_end) */ + /* Let the libc call main and exit with its return code. */ + b __uClibc_main(PLT) +#else + /* Fetch address of fini */ + ldr ip, =_fini + /* Push fini */ + str ip, [sp, #-4]! + + /* Set up the other arguments in registers */ + ldr a1, =main + ldr a4, =_init + + /* __uClibc_main (main, argc, argv, init, fini, rtld_fini, stack_end) */ + + /* Let the libc call main and exit with its return code. */ + b __uClibc_main +#endif + + /* should never get here....*/ + bl abort + +#ifdef __PIC__ +.L_GOT: + .word _GLOBAL_OFFSET_TABLE_ - .L_GOT + .word _fini(GOT) + .word _init(GOT) + .word main(GOT) +#endif +#endif + +/* Define a symbol for the first piece of initialized data. */ + .data + .globl __data_start +__data_start: + .long 0 + .weak data_start + data_start = __data_start diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/crti.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/crti.S new file mode 100644 index 00000000..e335b714 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/crti.S @@ -0,0 +1,87 @@ + .file "initfini.c" + +#include + .section .init + .global _init + .type _init, %function +#if defined __thumb__ + .align 1 + .thumb + .thumb_func +_init: + push {r4-r7, lr} +#else + .align 2 + .arm +_init: + @ gcc 3.3.2 didn't create a stack frame, gcc 3.4.4 does - + @ presumably 3.4.4 can put stuff into .init which requires + @ the arguments to be saved. This code is copied from 3.4.4 + mov ip, sp + stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, ip, lr, pc} + sub fp, ip, #4 +#endif + + + .section .fini + .global _fini + .type _fini, %function +#if defined __thumb__ + .align 1 + .thumb + .thumb_func +_fini: + push {r4-r7, lr} +#else + .align 2 + .arm +_fini: + mov ip, sp + stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, ip, lr, pc} + sub fp, ip, #4 +#endif + + +#if (defined __thumb__ || defined __THUMB_INTERWORK__) && (defined __ARM_ARCH_4T__ || defined __ARM_ARCH_5T__ || defined __ARM_ARCH_5TE__) + @ To support thumb code it is currently necessary to have the _call_via_rX + @ functions exposed to the linker for any program or shared library. PLT + @ references are inadequate - the PLT zaps ip and therefore breaks _call_via_ip + @ (and the compiler does generate this). It is simpler to put all the + @ required code in here - it only amounts to 60 bytes overhead. + @NOTE: it would be better to have the compiler generate this stuff as + @ required... + .section ".text" + .align 0 + .force_thumb + +.macro call_via register + .global _call_via_\register + .type _call_via_\register, %function + .weak _call_via_\register + .hidden _call_via_\register + .thumb_func +_call_via_\register: + bx \register + nop + .size _call_via_\register, . - _call_via_\register +.endm + + @ and calls for the 15 general purpose registers (2 bytes each). + call_via r0 + call_via r1 + call_via r2 + call_via r3 + call_via r4 + call_via r5 + call_via r6 + call_via r7 + call_via r8 + call_via r9 + call_via sl + call_via fp + call_via ip + call_via sp + call_via lr +#endif + + .ident "GCC: (GNU) 3.3.2 20031005 (Debian prerelease)" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/crtn.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/crtn.S new file mode 100644 index 00000000..a4752c18 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/crtn.S @@ -0,0 +1,33 @@ + .file "initfini.c" + +#include + .section .init + .global _init + .type _init, %function +#if defined __thumb__ + .align 1 + .thumb + @ this will not work on ARMv4T, but lots of stuff + @ in here won't work there anyway... + pop {r4-r7, pc} +#else + .align 2 + .arm + ldmdb fp, {r4, r5, r6, r7, r8, r9, sl, fp, sp, pc} +#endif + + .section .fini + .global _fini + .type _fini, %function +#if defined __thumb__ + .align 1 + .thumb + pop {r4-r7, pc} +#else + .align 2 + .arm + ldmdb fp, {r4, r5, r6, r7, r8, r9, sl, fp, sp, pc} +#endif + + @ In fact this is modified to 3.4.4 + .ident "GCC: (GNU) 3.3.2 20031005 (Debian prerelease)" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/find_exidx.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/find_exidx.c new file mode 100644 index 00000000..a16534bb --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/find_exidx.c @@ -0,0 +1,80 @@ +/* Copyright (C) 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +struct unw_eh_callback_data +{ + _Unwind_Ptr pc; + _Unwind_Ptr exidx_start; + int exidx_len; +}; + + +/* Callback to determins if the PC lies within an object, and remember the + location of the exception index table if it does. */ + +static int +find_exidx_callback (struct dl_phdr_info * info, size_t size, void * ptr) +{ + struct unw_eh_callback_data * data; + const ElfW(Phdr) *phdr; + int i; + int match; + _Unwind_Ptr load_base; + + data = (struct unw_eh_callback_data *) ptr; + load_base = info->dlpi_addr; + phdr = info->dlpi_phdr; + + match = 0; + for (i = info->dlpi_phnum; i > 0; i--, phdr++) + { + if (phdr->p_type == PT_LOAD) + { + _Unwind_Ptr vaddr = phdr->p_vaddr + load_base; + if (data->pc >= vaddr && data->pc < vaddr + phdr->p_memsz) + match = 1; + } + else if (phdr->p_type == PT_ARM_EXIDX) + { + data->exidx_start = (_Unwind_Ptr) (phdr->p_vaddr + load_base); + data->exidx_len = phdr->p_memsz; + } + } + + return match; +} + + +/* Find the exception index table containing PC. */ + +_Unwind_Ptr __gnu_Unwind_Find_exidx (_Unwind_Ptr pc, int * pcount); +_Unwind_Ptr __gnu_Unwind_Find_exidx (_Unwind_Ptr pc, int * pcount) +{ + struct unw_eh_callback_data data; + + data.pc = pc; + data.exidx_start = 0; + if (dl_iterate_phdr (find_exidx_callback, &data) <= 0) + return 0; + + *pcount = data.exidx_len / 8; + return data.exidx_start; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/fpu_control.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/fpu_control.h new file mode 100644 index 00000000..1170c9e9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/fpu_control.h @@ -0,0 +1,203 @@ +/* FPU control word definitions. ARM version. + Copyright (C) 1996, 1997, 1998, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FPU_CONTROL_H +#define _FPU_CONTROL_H + +#ifdef __VFP_FP__ + +/* masking of interrupts */ +#define _FPU_MASK_IM 0x00000100 /* invalid operation */ +#define _FPU_MASK_ZM 0x00000200 /* divide by zero */ +#define _FPU_MASK_OM 0x00000400 /* overflow */ +#define _FPU_MASK_UM 0x00000800 /* underflow */ +#define _FPU_MASK_PM 0x00001000 /* inexact */ + +/* Some bits in the FPSCR are not yet defined. They must be preserved when + modifying the contents. */ +#define _FPU_RESERVED 0x0e08e0e0 +#define _FPU_DEFAULT 0x00000000 +/* Default + exceptions enabled. */ +#define _FPU_IEEE (_FPU_DEFAULT | 0x00001f00) + +/* Type of the control word. */ +typedef unsigned int fpu_control_t; + +/* Macros for accessing the hardware control word. */ +/* This is fmrx %0, fpscr. */ +#define _FPU_GETCW(cw) \ + __asm__ __volatile__ ("mrc p10, 7, %0, cr1, cr0, 0" : "=r" (cw)) +/* This is fmxr fpscr, %0. */ +#define _FPU_SETCW(cw) \ + __asm__ __volatile__ ("mcr p10, 7, %0, cr1, cr0, 0" : : "r" (cw)) + +#elif defined __MAVERICK__ + +/* DSPSC register: (from EP9312 User's Guide) + * + * bits 31..29 - DAID + * bits 28..26 - HVID + * bits 25..24 - RSVD + * bit 23 - ISAT + * bit 22 - UI + * bit 21 - INT + * bit 20 - AEXC + * bits 19..18 - SAT + * bits 17..16 - FCC + * bit 15 - V + * bit 14 - FWDEN + * bit 13 - Invalid + * bit 12 - Denorm + * bits 11..10 - RM + * bits 9..5 - IXE, UFE, OFE, RSVD, IOE + * bits 4..0 - IX, UF, OF, RSVD, IO + */ + +/* masking of interrupts */ +#define _FPU_MASK_IM (1 << 5) /* invalid operation */ +#define _FPU_MASK_ZM 0 /* divide by zero */ +#define _FPU_MASK_OM (1 << 7) /* overflow */ +#define _FPU_MASK_UM (1 << 8) /* underflow */ +#define _FPU_MASK_PM (1 << 9) /* inexact */ +#define _FPU_MASK_DM 0 /* denormalized operation */ + +#define _FPU_RESERVED 0xfffff000 /* These bits are reserved. */ + +#define _FPU_DEFAULT 0x00b00000 /* Default value. */ +#define _FPU_IEEE 0x00b003a0 /* Default + exceptions enabled. */ + +/* Type of the control word. */ +typedef unsigned int fpu_control_t; + +/* Macros for accessing the hardware control word. */ +#define _FPU_GETCW(cw) ({ \ + register int __t1, __t2; \ + \ + __asm__ __volatile__ ( \ + "cfmvr64l %1, mvdx0\n\t" \ + "cfmvr64h %2, mvdx0\n\t" \ + "cfmv32sc mvdx0, dspsc\n\t" \ + "cfmvr64l %0, mvdx0\n\t" \ + "cfmv64lr mvdx0, %1\n\t" \ + "cfmv64hr mvdx0, %2" \ + : "=r" (cw), "=r" (__t1), "=r" (__t2) \ + ); \ +}) + +#define _FPU_SETCW(cw) ({ \ + register int __t0, __t1, __t2; \ + \ + __asm__ __volatile__ ( \ + "cfmvr64l %1, mvdx0\n\t" \ + "cfmvr64h %2, mvdx0\n\t" \ + "cfmv64lr mvdx0, %0\n\t" \ + "cfmvsc32 dspsc, mvdx0\n\t" \ + "cfmv64lr mvdx0, %1\n\t" \ + "cfmv64hr mvdx0, %2" \ + : "=r" (__t0), "=r" (__t1), "=r" (__t2) \ + : "0" (cw) \ + ); \ +}) + +#else /* !__MAVERICK__ */ + +/* We have a slight terminology confusion here. On the ARM, the register + * we're interested in is actually the FPU status word - the FPU control + * word is something different (which is implementation-defined and only + * accessible from supervisor mode.) + * + * The FPSR looks like this: + * + * 31-24 23-16 15-8 7-0 + * | system ID | trap enable | system control | exception flags | + * + * We ignore the system ID bits; for interest's sake they are: + * + * 0000 "old" FPE + * 1000 FPPC hardware + * 0001 FPE 400 + * 1001 FPA hardware + * + * The trap enable and exception flags are both structured like this: + * + * 7 - 5 4 3 2 1 0 + * | reserved | INX | UFL | OFL | DVZ | IVO | + * + * where a `1' bit in the enable byte means that the trap can occur, and + * a `1' bit in the flags byte means the exception has occurred. + * + * The exceptions are: + * + * IVO - invalid operation + * DVZ - divide by zero + * OFL - overflow + * UFL - underflow + * INX - inexact (do not use; implementations differ) + * + * The system control byte looks like this: + * + * 7-5 4 3 2 1 0 + * | reserved | AC | EP | SO | NE | ND | + * + * where the bits mean + * + * ND - no denormalised numbers (force them all to zero) + * NE - enable NaN exceptions + * SO - synchronous operation + * EP - use expanded packed-decimal format + * AC - use alternate definition for C flag on compare operations + */ + +/* masking of interrupts */ +#define _FPU_MASK_IM 0x00010000 /* invalid operation */ +#define _FPU_MASK_ZM 0x00020000 /* divide by zero */ +#define _FPU_MASK_OM 0x00040000 /* overflow */ +#define _FPU_MASK_UM 0x00080000 /* underflow */ +#define _FPU_MASK_PM 0x00100000 /* inexact */ +#define _FPU_MASK_DM 0x00000000 /* denormalized operation */ + +/* The system id bytes cannot be changed. + Only the bottom 5 bits in the trap enable byte can be changed. + Only the bottom 5 bits in the system control byte can be changed. + Only the bottom 5 bits in the exception flags are used. + The exception flags are set by the fpu, but can be zeroed by the user. */ +#define _FPU_RESERVED 0xffe0e0e0 /* These bits are reserved. */ + +/* The fdlibm code requires strict IEEE double precision arithmetic, + no interrupts for exceptions, rounding to nearest. Changing the + rounding mode will break long double I/O. Turn on the AC bit, + the compiler generates code that assumes it is on. */ +#define _FPU_DEFAULT 0x00001000 /* Default value. */ +#define _FPU_IEEE 0x001f1000 /* Default + exceptions enabled. */ + +/* Type of the control word. */ +typedef unsigned int fpu_control_t; + +/* Macros for accessing the hardware control word. */ +#define _FPU_GETCW(cw) __asm__ ("rfs %0" : "=r" (cw)) +#define _FPU_SETCW(cw) __asm__ ("wfs %0" : : "r" (cw)) + +#endif /* __MAVERICK__ */ + +#if 0 +/* Default control word set at startup. */ +extern fpu_control_t __fpu_control; +#endif + +#endif /* _FPU_CONTROL_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/ioperm.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/ioperm.c new file mode 100644 index 00000000..a7f6c306 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/ioperm.c @@ -0,0 +1,246 @@ +/* Copyright (C) 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Phil Blundell, based on the Alpha version by + David Mosberger. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* I/O port access on the ARM is something of a fiction. What we do is to + map an appropriate area of /dev/mem into user space so that a program + can blast away at the hardware in such a way as to generate I/O cycles + on the bus. To insulate user code from dependencies on particular + hardware we don't allow calls to inb() and friends to be inlined, but + force them to come through code in here every time. Performance-critical + registers tend to be memory mapped these days so this should be no big + problem. */ + +/* Once upon a time this file used mprotect to enable and disable + access to particular areas of I/O space. Unfortunately the + mprotect syscall also has the side effect of enabling caching for + the area affected (this is a kernel limitation). So we now just + enable all the ports all of the time. */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + + + +#include + +#define PATH_ARM_SYSTYPE "/etc/arm_systype" +#define PATH_CPUINFO "/proc/cpuinfo" + +#define MAX_PORT 0x10000 + +static struct { + unsigned long int base; + unsigned long int io_base; + unsigned int shift; + unsigned int initdone; /* since all the above could be 0 */ +} io; + +#define IO_BASE_FOOTBRIDGE 0x7c000000 +#define IO_SHIFT_FOOTBRIDGE 0 + +static struct platform { + const char *name; + unsigned long int io_base; + unsigned int shift; +} platform[] = { + /* All currently supported platforms are in fact the same. :-) */ + {"Chalice-CATS", IO_BASE_FOOTBRIDGE, IO_SHIFT_FOOTBRIDGE}, + {"DEC-EBSA285", IO_BASE_FOOTBRIDGE, IO_SHIFT_FOOTBRIDGE}, + {"Corel-NetWinder", IO_BASE_FOOTBRIDGE, IO_SHIFT_FOOTBRIDGE}, + {"Rebel-NetWinder", IO_BASE_FOOTBRIDGE, IO_SHIFT_FOOTBRIDGE}, +}; + +#define IO_ADDR(port) (io.base + ((port) << io.shift)) + +/* + * Initialize I/O system. There are several ways to get the information + * we need. Each is tried in turn until one succeeds. + * + * 1. Sysctl (CTL_BUS, BUS_ISA, ISA_*). This is the preferred method + * but not all kernels support it. + * + * 2. Read the value (not the contents) of symlink PATH_ARM_SYSTYPE. + * - If it matches one of the entries in the table above, use the + * corresponding values. + * - If it begins with a number, assume this is a previously + * unsupported system and the values encode, in order, + * ",". + * + * 3. Lookup the "system type" field in /proc/cpuinfo. Again, if it + * matches an entry in the platform[] table, use the corresponding + * values. + * + * 4. BUS_ISA is changed to CTL_BUS_ISA (for kernel since 2.4.23). + */ + +static int +init_iosys (void) +{ + char systype[256]; + int i, n; + +#if LINUX_VERSION_CODE < 132119 + static int iobase_name[] = { CTL_BUS, BUS_ISA, BUS_ISA_PORT_BASE }; + static int ioshift_name[] = { CTL_BUS, BUS_ISA, BUS_ISA_PORT_SHIFT }; +#else + static int iobase_name[] = { CTL_BUS, CTL_BUS_ISA, BUS_ISA_PORT_BASE }; + static int ioshift_name[] = { CTL_BUS, CTL_BUS_ISA, BUS_ISA_PORT_SHIFT }; +#endif + + size_t len = sizeof(io.base); + + if (! sysctl (iobase_name, 3, &io.io_base, &len, NULL, 0) + && ! sysctl (ioshift_name, 3, &io.shift, &len, NULL, 0)) { + io.initdone = 1; + return 0; + } + + n = readlink (PATH_ARM_SYSTYPE, systype, sizeof (systype) - 1); + if (n > 0) { + systype[n] = '\0'; + if (isdigit (systype[0])) { + if (sscanf (systype, "%li,%i", &io.io_base, &io.shift) == 2) { + io.initdone = 1; + return 0; + } + /* else we're likely going to fail with the system match below */ + } + } + else { + FILE * fp; + + fp = fopen (PATH_CPUINFO, "r"); + if (! fp) + return -1; + while ((n = fscanf (fp, "Hardware\t: %256[^\n]\n", systype)) != EOF) { + if (n == 1) + break; + else + fgets (systype, 256, fp); + } + fclose (fp); + + if (n == EOF) { + /* this can happen if the format of /proc/cpuinfo changes... */ + fprintf (stderr, "ioperm: Unable to determine system type.\n" + "\t(May need " PATH_ARM_SYSTYPE " symlink?)\n"); + __set_errno (ENODEV); + return -1; + } + } + + /* translate systype name into i/o system: */ + for (i = 0; i < sizeof (platform) / sizeof (platform[0]); ++i) { + if (strcmp (platform[i].name, systype) == 0) { + io.shift = platform[i].shift; + io.io_base = platform[i].io_base; + io.initdone = 1; + return 0; + } + } + + /* systype is not a known platform name... */ + __set_errno (EINVAL); + return -1; +} + +int ioperm (unsigned long int from, unsigned long int num, int turn_on) +{ + if (! io.initdone && init_iosys () < 0) + return -1; + + /* this test isn't as silly as it may look like; consider overflows! */ + if (from >= MAX_PORT || from + num > MAX_PORT) { + __set_errno (EINVAL); + return -1; + } + + if (turn_on) { + if (! io.base) { + int fd; + + fd = open ("/dev/mem", O_RDWR); + if (fd < 0) + return -1; + + io.base = (unsigned long int) mmap (0, MAX_PORT << io.shift, + PROT_READ | PROT_WRITE, + MAP_SHARED, fd, io.io_base); + close (fd); + if ((long) io.base == -1) + return -1; + } + } + + return 0; +} +libc_hidden_def(ioperm) + + +void +outb(unsigned char b, unsigned long int port) +{ + *((__volatile__ unsigned char *)(IO_ADDR (port))) = b; +} + + +void +outw(unsigned short b, unsigned long int port) +{ + *((__volatile__ unsigned short *)(IO_ADDR (port))) = b; +} + + +void +outl(unsigned long b, unsigned long int port) +{ + *((__volatile__ unsigned long *)(IO_ADDR (port))) = b; +} + + +unsigned char +inb (unsigned long int port) +{ + return *((__volatile__ unsigned char *)(IO_ADDR (port))); +} + + +unsigned short int +inw(unsigned long int port) +{ + return *((__volatile__ unsigned short *)(IO_ADDR (port))); +} + + +unsigned long int +inl(unsigned long int port) +{ + return *((__volatile__ unsigned long *)(IO_ADDR (port))); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/iopl.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/iopl.c new file mode 100644 index 00000000..df953d3c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/iopl.c @@ -0,0 +1,36 @@ +/* Copyright (C) 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Phil Blundell, based on the Alpha version by + David Mosberger. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + + +#define MAX_PORT 0x10000 + +int iopl(int level) +{ + if (level > 3) { + __set_errno(EINVAL); + return -1; + } + if (level) + return ioperm(0, MAX_PORT, 1); + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/libc-aeabi_read_tp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/libc-aeabi_read_tp.S new file mode 100644 index 00000000..3aa135bf --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/libc-aeabi_read_tp.S @@ -0,0 +1 @@ +#include diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/libc-thumb_atomics.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/libc-thumb_atomics.S new file mode 100644 index 00000000..e7bc8950 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/libc-thumb_atomics.S @@ -0,0 +1 @@ +#include diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/mmap.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/mmap.c new file mode 100644 index 00000000..df550fed --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/mmap.c @@ -0,0 +1,74 @@ +/* vi: set sw=4 ts=4: */ +/* + * _mmap() for uClibc + * + * Copyright (C) 2000-2004 by Erik Andersen + * + * GNU Library General Public License (LGPL) version 2 or later. + */ +#include +#include +#include +#include + +#if defined (__NR_mmap) || defined (__NR_mmap2) + +libc_hidden_proto(mmap) +#if defined (__UCLIBC_MMAP_HAS_6_ARGS__) && defined (__NR_mmap) +#define __NR__mmap __NR_mmap +static __inline__ _syscall6 (__ptr_t, _mmap, __ptr_t, addr, size_t, len, + int, prot, int, flags, int, fd, __off_t, offset) +__ptr_t mmap(__ptr_t addr, size_t len, int prot, + int flags, int fd, __off_t offset) +{ + return (__ptr_t) _mmap (addr, len, prot, flags, + fd, offset); +} + +#elif defined (__NR_mmap2) +#define __NR__mmap __NR_mmap2 + +#ifndef MMAP2_PAGE_SHIFT +# define MMAP2_PAGE_SHIFT 12 +#endif + +static __inline__ _syscall6 (__ptr_t, _mmap, __ptr_t, addr, size_t, len, + int, prot, int, flags, int, fd, __off_t, offset); +__ptr_t mmap(__ptr_t addr, size_t len, int prot, + int flags, int fd, __off_t offset) +{ + /* check if offset is page aligned */ + if (offset & ((1 << MMAP2_PAGE_SHIFT) - 1)) + { + __set_errno(EINVAL); + return MAP_FAILED; + } +#ifdef __USE_FILE_OFFSET64 + return (__ptr_t) _mmap (addr, len, prot, flags, + fd, ((__u_quad_t) offset >> MMAP2_PAGE_SHIFT)); +#else + return (__ptr_t) _mmap (addr, len, prot, flags, + fd, ((__u_long) offset >> MMAP2_PAGE_SHIFT)); +#endif +} +#elif defined (__NR_mmap) +# define __NR__mmap __NR_mmap +static __inline__ _syscall1(__ptr_t, _mmap, unsigned long *, buffer) +__ptr_t mmap(__ptr_t addr, size_t len, int prot, + int flags, int fd, __off_t offset) +{ + unsigned long buffer[6]; + + buffer[0] = (unsigned long) addr; + buffer[1] = (unsigned long) len; + buffer[2] = (unsigned long) prot; + buffer[3] = (unsigned long) flags; + buffer[4] = (unsigned long) fd; + buffer[5] = (unsigned long) offset; + return (__ptr_t) _mmap(buffer); +} +#endif +libc_hidden_def (mmap) +#else +# error "Your architecture doesn't seem to provide mmap() !?" +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/mmap64.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/mmap64.S new file mode 100644 index 00000000..70715412 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/mmap64.S @@ -0,0 +1,142 @@ +/* Copyright (C) 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#define _ERRNO_H +#include +#include +#include + +#if defined __UCLIBC_HAS_LFS__ && defined __NR_mmap2 + +/* The mmap2 system call takes six arguments, all in registers. */ +.text +.global mmap64 +.type mmap64,%function +.align 2 + +#ifdef __ARM_EABI__ +#if defined(THUMB1_ONLY) +.thumb_func +mmap64: +#ifdef __ARMEB__ +/* Offsets are after pushing 3 words. */ +# define LOW_OFFSET 12 + 8 + 4 +# define HIGH_OFFSET 12 + 8 + 0 +#else +# define LOW_OFFSET 12 + 8 + 0 +# define HIGH_OFFSET 12 + 8 + 4 +#endif + push {r4, r5, r6} + ldr r6, [sp, $LOW_OFFSET] + ldr r5, [sp, $HIGH_OFFSET] + lsl r4, r6, #20 @ check that offset is page-aligned + bne .Linval + lsr r4, r5, #12 @ check for overflow + bne .Linval + @ compose page offset + lsr r6, r6, #12 + lsl r5, r5, #20 + orr r5, r5, r6 + ldr r4, [sp, #8] @ load fd + DO_CALL (mmap2) + ldr r1, =0xfffff000 + cmp r0, r1 + bcs .Lerror + bx lr +.Linval: + ldr r0, =-EINVAL + pop {r4, r5, r6} +.Lerror: + push {r3, lr} + bl __syscall_error + POP_RET +.pool +#else /* !THUMB1_ONLY */ +mmap64: +#ifdef __ARMEB__ +# define LOW_OFFSET 8 + 4 +/* The initial + 4 is for the stack postdecrement. */ +# define HIGH_OFFSET 4 + 8 + 0 +#else +# define LOW_OFFSET 8 + 0 +# define HIGH_OFFSET 4 + 8 + 4 +#endif + ldr ip, [sp, $LOW_OFFSET] + str r5, [sp, #-4]! + ldr r5, [sp, $HIGH_OFFSET] + str r4, [sp, #-4]! + movs r4, ip, lsl $20 @ check that offset is page-aligned + mov ip, ip, lsr $12 + IT(t, eq) + moveqs r4, r5, lsr $12 @ check for overflow + bne .Linval + ldr r4, [sp, $8] @ load fd + orr r5, ip, r5, lsl $20 @ compose page offset + DO_CALL (mmap2) + cmn r0, $4096 + ldmfd sp!, {r4, r5} + IT(t, cc) +#if defined(__USE_BX__) + bxcc lr +#else + movcc pc, lr +#endif + b __syscall_error +.Linval: + mov r0, $-EINVAL + ldmfd sp!, {r4, r5} + b __syscall_error +#endif +#else /* !__ARM_EABI__ */ +mmap64: + stmfd sp!, {r4, r5, lr} + ldr r5, [sp, $16] + ldr r4, [sp, $12] + movs ip, r5, lsl $20 @ check that offset is page-aligned + bne .Linval + ldr ip, [sp, $20] + mov r5, r5, lsr $12 + orr r5, r5, ip, lsl $20 @ compose page offset + movs ip, ip, lsr $12 + bne .Linval @ check for overflow + mov ip, r0 + DO_CALL (mmap2) + cmn r0, $4096 + ldmccfd sp!, {r4, r5, pc} + cmn r0, $ENOSYS + ldmnefd sp!, {r4, r5, lr} + bne __error + /* The current kernel does not support mmap2. Fall back to plain + mmap if the offset is small enough. */ + ldr r5, [sp, $20] + mov r0, ip @ first arg was clobbered + teq r5, $0 + ldmeqfd sp!, {r4, r5, lr} + beq HIDDEN_JUMPTARGET(mmap) +.Linval: + mov r0, $-EINVAL + ldmfd sp!, {r4, r5, lr} + b __error + +__error: + b __syscall_error +#endif +.size mmap64,.-mmap64 + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/posix_fadvise.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/posix_fadvise.c new file mode 100644 index 00000000..278bff98 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/posix_fadvise.c @@ -0,0 +1,49 @@ +/* vi: set sw=4 ts=4: */ +/* + * posix_fadvise() for ARM uClibc + * http://www.opengroup.org/onlinepubs/009695399/functions/posix_fadvise.html + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ +#include +#include + +#if defined __NR_arm_fadvise64_64 + +#define HIGH_BITS(x) (sizeof(x) > 4 ? (x) >> 32 : 0) + +/* Was named __libc_posix_fadvise for some inexplicable reason. +** google says only uclibc has *__libc*_posix_fadviseXXX, +** so it cannot be compat with anything. +** +** Remove this comment and one at the end after 0.9.31 +*/ + +/* This is for the ARM version of fadvise64_64 which swaps the params + * * about to avoid having ABI compat issues + * */ +#define __NR___syscall_arm_fadvise64_64 __NR_arm_fadvise64_64 +int posix_fadvise(int fd, off_t offset, off_t len, int advise) +{ + INTERNAL_SYSCALL_DECL (err); + int ret = INTERNAL_SYSCALL (arm_fadvise64_64, err, 6, fd, advise, + __LONG_LONG_PAIR (HIGH_BITS(offset), (long)offset), + __LONG_LONG_PAIR (HIGH_BITS(len), (long)len)); + + if (INTERNAL_SYSCALL_ERROR_P (ret, err)) + return INTERNAL_SYSCALL_ERRNO (ret, err); + return 0; +} + +/* weak_alias(__libc_posix_fadvise, posix_fadvise); */ + +#else + +int posix_fadvise(int fd attribute_unused, off_t offset attribute_unused, off_t len attribute_unused, int advice attribute_unused) +{ + return ENOSYS; +} + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/posix_fadvise64.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/posix_fadvise64.c new file mode 100644 index 00000000..4b27381d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/posix_fadvise64.c @@ -0,0 +1,59 @@ +/* vi: set sw=4 ts=4: */ +/* + * posix_fadvise64() for ARM uClibc + * http://www.opengroup.org/onlinepubs/009695399/functions/posix_fadvise.html + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __UCLIBC_HAS_LFS__ + +#if defined __NR_arm_fadvise64_64 + +/* Was named __libc_posix_fadvise64 for some inexplicable reason. +** google says only uclibc has *__libc*_posix_fadviseXXX, +** so it cannot be compat with anything. +** +** Remove this comment and one at the end after 0.9.31 +*/ + +/* This is for the ARM version of fadvise64_64 which swaps the params + * about to avoid having ABI compat issues + */ +#define __NR___syscall_arm_fadvise64_64 __NR_arm_fadvise64_64 +int posix_fadvise64(int fd, __off64_t offset, __off64_t len, int advise) +{ + INTERNAL_SYSCALL_DECL (err); + int ret = INTERNAL_SYSCALL (arm_fadvise64_64, err, 6, fd, advise, + __LONG_LONG_PAIR ((long)(offset >> 32), (long)offset), + __LONG_LONG_PAIR ((long)(len >> 32), (long)len)); + if (!INTERNAL_SYSCALL_ERROR_P (ret, err)) + return 0; + if (INTERNAL_SYSCALL_ERRNO (ret, err) != ENOSYS) + return INTERNAL_SYSCALL_ERRNO (ret, err); + return 0; +} + +/* weak_alias(__libc_posix_fadvise64, posix_fadvise64); */ + +#else + +int posix_fadvise64(int fd, __off64_t offset, __off64_t len, int advise) +{ + return ENOSYS; +} + +#endif + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/setjmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/setjmp.S new file mode 100644 index 00000000..76d17904 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/setjmp.S @@ -0,0 +1,101 @@ +/* setjmp for ARM. + Copyright (C) 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +.global __sigsetjmp +.type __sigsetjmp,%function +.align 2 +#if defined(THUMB1_ONLY) +.thumb_func +__sigsetjmp: + push {r3, r4, r5, r6, r7, lr} + mov ip, r0 + stmia r0!, {r4, r5, r6, r7} + mov r2, r8 + mov r3, r9 + mov r4, sl + mov r5, fp + add r6, sp, #(6 * 4) + mov r7, lr + stmia r0!, {r2, r3, r4, r5, r6, r7} + + mov r0, ip + bl __sigjmp_save + pop {r3, r4, r5, r6, r7, pc} + +#else +__sigsetjmp: + /* Save registers */ + mov ip, r0 +#if defined(__thumb2__) + stmia ip!, {v1-v6, sl, fp} + mov r2, sp + stmia ip!, {r2, lr} +#else + /* Save registers */ + stmia ip!, {v1-v6, sl, fp, sp, lr} +#endif +#if defined __UCLIBC_HAS_FLOATS__ && ! defined __UCLIBC_HAS_SOFT_FLOAT__ +# ifdef __VFP_FP__ + /* Store the VFP registers. */ + /* Following instruction is fstmiax ip!, {d8-d15}. */ + stc p11, cr8, [r12], #68 + /* Store the floating-point status register. */ + /* Following instruction is fmrx r2, fpscr. */ + mrc p10, 7, r2, cr1, cr0, 0 + str r2, [ip], #4 +# elif defined __MAVERICK__ + cfstrd mvd4, [ip], #8 ; nop + cfstrd mvd5, [ip], #8 ; nop + cfstrd mvd6, [ip], #8 ; nop + cfstrd mvd7, [ip], #8 ; nop + cfstrd mvd8, [ip], #8 ; nop + cfstrd mvd9, [ip], #8 ; nop + cfstrd mvd10, [ip], #8 ; nop + cfstrd mvd11, [ip], #8 ; nop + cfstrd mvd12, [ip], #8 ; nop + cfstrd mvd13, [ip], #8 ; nop + cfstrd mvd14, [ip], #8 ; nop + cfstrd mvd15, [ip], #8 +# else + sfmea f4, 4, [ip]! +# endif +#endif +#ifdef __IWMMXT__ + /* Save the call-preserved iWMMXt registers. */ + /* Following instructions are wstrd wr10, [ip], #8 (etc.) */ + stcl p1, cr10, [r12], #8 + stcl p1, cr11, [r12], #8 + stcl p1, cr12, [r12], #8 + stcl p1, cr13, [r12], #8 + stcl p1, cr14, [r12], #8 + stcl p1, cr15, [r12], #8 +#endif + + /* Make a tail call to __sigjmp_save; it takes the same args. */ +#ifdef __PIC__ + B __sigjmp_save(PLT) +#else + B __sigjmp_save +#endif +#endif + +.size __sigsetjmp,.-__sigsetjmp diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/sigaction.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/sigaction.c new file mode 100644 index 00000000..01140aaf --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/sigaction.c @@ -0,0 +1,101 @@ +/* Copyright (C) 1997,1998,1999,2000,2002,2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. + + Totally hacked up for uClibc by Erik Andersen + */ + +#include +#include +#include +#include +#include + +#define SA_RESTORER 0x04000000 +extern void __default_sa_restorer(void); +extern void __default_rt_sa_restorer(void); + +extern __typeof(sigaction) __libc_sigaction; + +/* When RT signals are in use we need to use a different return stub. */ +#ifdef __NR_rt_sigreturn +#define choose_restorer(flags) \ + (flags & SA_SIGINFO) ? __default_rt_sa_restorer \ + : __default_sa_restorer +#else +#define choose_restorer(flags) \ + __default_sa_restorer +#endif + + +#ifdef __NR_rt_sigaction + +/* If ACT is not NULL, change the action for SIG to *ACT. + If OACT is not NULL, put the old action for SIG in *OACT. */ +int __libc_sigaction(int sig, const struct sigaction *act, struct sigaction *oact) +{ + struct sigaction kact; + if (act && !(act->sa_flags & SA_RESTORER)) { + memcpy(&kact, act, sizeof(kact)); + kact.sa_restorer = choose_restorer(kact.sa_flags); + kact.sa_flags |= SA_RESTORER; + act = &kact; + } + /* NB: kernel (as of 2.6.25) will return EINVAL + * if sizeof(act->sa_mask) does not match kernel's sizeof(sigset_t) */ + return __syscall_rt_sigaction(sig, act, oact, sizeof(act->sa_mask)); +} + +#else + +/* If ACT is not NULL, change the action for SIG to *ACT. + If OACT is not NULL, put the old action for SIG in *OACT. */ +int __libc_sigaction(int sig, const struct sigaction *act, struct sigaction *oact) +{ + int result; + struct old_kernel_sigaction kact, koact; + + if (act) { + kact.k_sa_handler = act->sa_handler; + kact.sa_mask = act->sa_mask.__val[0]; + kact.sa_flags = act->sa_flags; + if (kact.sa_flags & SA_RESTORER) { + kact.sa_restorer = act->sa_restorer; + } else { + kact.sa_restorer = choose_restorer(kact.sa_flags); + kact.sa_flags |= SA_RESTORER; + } + } + result = __syscall_sigaction(sig, + act ? &kact : NULL, + oact ? &koact : NULL); + if (oact && result >= 0) { + oact->sa_handler = koact.k_sa_handler; + oact->sa_mask.__val[0] = koact.sa_mask; + oact->sa_flags = koact.sa_flags; + oact->sa_restorer = koact.sa_restorer; + } + return result; +} + +#endif + + +#ifndef LIBC_SIGACTION +weak_alias(__libc_sigaction,sigaction) +libc_hidden_weak(sigaction) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/sigrestorer.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/sigrestorer.S new file mode 100644 index 00000000..79728fd4 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/sigrestorer.S @@ -0,0 +1,89 @@ +/* Copyright (C) 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +/* If no SA_RESTORER function was specified by the application we use + one of these. This avoids the need for the kernel to synthesise a return + instruction on the stack, which would involve expensive cache flushes. + + Nowadays (2.6 series, and somewhat earlier) the kernel uses a high page + for signal trampolines, so the cache flushes are not an issue. But since + we do not have a vDSO, continue to use these so that we can provide + unwind information. + + Start the unwind tables at least one instruction before the signal + trampoline, because the unwinder will assume we are returning after + a call site. + + The signal frame layout changed in 2.6.18. */ + +.global __default_sa_restorer +.type __default_sa_restorer,%function +.align 2 +#ifdef __ARM_EABI__ +#ifdef __thumb__ +.thumb_func +#endif + .fnstart + .save {r0-r15} +#if LINUX_VERSION_CODE >= 0x020612 + .pad #32 +#else + .pad #12 +#endif + nop +__default_sa_restorer: + mov r7, $SYS_ify(sigreturn) + swi 0x0 + .fnend +#else +__default_sa_restorer: + DO_CALL (sigreturn) +#endif + + +#ifdef __NR_rt_sigreturn + +.global __default_rt_sa_restorer +.type __default_rt_sa_restorer,%function +.align 2 +#ifdef __ARM_EABI__ +#ifdef __thumb__ +.thumb_func +#endif + .fnstart + .save {r0-r15} +#if LINUX_VERSION_CODE >= 0x020612 + .pad #160 +#else + .pad #168 +#endif + nop +__default_rt_sa_restorer: + mov r7, $SYS_ify(rt_sigreturn) + swi 0x0 + .fnend +#else +__default_rt_sa_restorer: + DO_CALL (rt_sigreturn) +#endif + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/sys/elf.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/sys/elf.h new file mode 100644 index 00000000..faa73106 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/sys/elf.h @@ -0,0 +1,26 @@ +/* Copyright (C) 1996, 1997, 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_ELF_H +#define _SYS_ELF_H 1 + +#warning "This header is obsolete; use instead." + +#include + +#endif /* sys/elf.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/sys/io.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/sys/io.h new file mode 100644 index 00000000..81762bec --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/sys/io.h @@ -0,0 +1,49 @@ +/* Copyright (C) 1996, 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_IO_H + +#define _SYS_IO_H 1 +#include + +__BEGIN_DECLS + +/* If TURN_ON is TRUE, request for permission to do direct i/o on the + port numbers in the range [FROM,FROM+NUM-1]. Otherwise, turn I/O + permission off for that range. This call requires root privileges. */ +extern int ioperm (unsigned long int __from, unsigned long int __num, + int __turn_on) __THROW; +libc_hidden_proto(ioperm) + +/* Set the I/O privilege level to LEVEL. If LEVEL is nonzero, + permission to access any I/O port is granted. This call requires + root privileges. */ +extern int iopl (int __level) __THROW; + +/* The functions that actually perform reads and writes. */ +extern unsigned char inb (unsigned long int port) __THROW; +extern unsigned short int inw (unsigned long int port) __THROW; +extern unsigned long int inl (unsigned long int port) __THROW; + +extern void outb (unsigned char value, unsigned long int port) __THROW; +extern void outw (unsigned short value, unsigned long int port) __THROW; +extern void outl (unsigned long value, unsigned long int port) __THROW; + +__END_DECLS + +#endif /* _SYS_IO_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/sys/procfs.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/sys/procfs.h new file mode 100644 index 00000000..3b373632 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/sys/procfs.h @@ -0,0 +1,123 @@ +/* Copyright (C) 1996, 1997, 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_PROCFS_H +#define _SYS_PROCFS_H 1 + +/* This is somewhat modelled after the file of the same name on SVR4 + systems. It provides a definition of the core file format for ELF + used on Linux. It doesn't have anything to do with the /proc file + system, even though Linux has one. + + Anyway, the whole purpose of this file is for GDB and GDB only. + Don't read too much into it. Don't use it for anything other than + GDB unless you know what you are doing. */ + +#include +#include +#include +#include + +__BEGIN_DECLS + +/* Type for a general-purpose register. */ +typedef unsigned long elf_greg_t; + +/* And the whole bunch of them. We could have used `struct + user_regs' directly in the typedef, but tradition says that + the register set is an array, which does have some peculiar + semantics, so leave it that way. */ +#define ELF_NGREG (sizeof (struct user_regs) / sizeof(elf_greg_t)) +typedef elf_greg_t elf_gregset_t[ELF_NGREG]; + +/* Register set for the floating-point registers. */ +typedef struct user_fpregs elf_fpregset_t; + +/* Signal info. */ +struct elf_siginfo + { + int si_signo; /* Signal number. */ + int si_code; /* Extra code. */ + int si_errno; /* Errno. */ + }; + +/* Definitions to generate Intel SVR4-like core files. These mostly + have the same names as the SVR4 types with "elf_" tacked on the + front to prevent clashes with Linux definitions, and the typedef + forms have been avoided. This is mostly like the SVR4 structure, + but more Linuxy, with things that Linux does not support and which + GDB doesn't really use excluded. */ + +struct elf_prstatus + { + struct elf_siginfo pr_info; /* Info associated with signal. */ + short int pr_cursig; /* Current signal. */ + unsigned long int pr_sigpend; /* Set of pending signals. */ + unsigned long int pr_sighold; /* Set of held signals. */ + __pid_t pr_pid; + __pid_t pr_ppid; + __pid_t pr_pgrp; + __pid_t pr_sid; + struct timeval pr_utime; /* User time. */ + struct timeval pr_stime; /* System time. */ + struct timeval pr_cutime; /* Cumulative user time. */ + struct timeval pr_cstime; /* Cumulative system time. */ + elf_gregset_t pr_reg; /* GP registers. */ + int pr_fpvalid; /* True if math copro being used. */ + }; + + +#define ELF_PRARGSZ (80) /* Number of chars for args. */ + +struct elf_prpsinfo + { + char pr_state; /* Numeric process state. */ + char pr_sname; /* Char for pr_state. */ + char pr_zomb; /* Zombie. */ + char pr_nice; /* Nice val. */ + unsigned long int pr_flag; /* Flags. */ + unsigned short int pr_uid; + unsigned short int pr_gid; + int pr_pid, pr_ppid, pr_pgrp, pr_sid; + /* Lots missing */ + char pr_fname[16]; /* Filename of executable. */ + char pr_psargs[ELF_PRARGSZ]; /* Initial part of arg list. */ + }; + +/* The rest of this file provides the types for emulation of the + Solaris interfaces that should be implemented by + users of libthread_db. */ + +/* Addresses. */ +typedef void *psaddr_t; + +/* Register sets. Linux has different names. */ +typedef elf_gregset_t prgregset_t; +typedef elf_fpregset_t prfpregset_t; + +/* We don't have any differences between processes and threads, + therefore have only one PID type. */ +typedef __pid_t lwpid_t; + +/* Process status and info. In the end we do provide typedefs for them. */ +typedef struct elf_prstatus prstatus_t; +typedef struct elf_prpsinfo prpsinfo_t; + +__END_DECLS + +#endif /* sys/procfs.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/sys/ucontext.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/sys/ucontext.h new file mode 100644 index 00000000..9ecff7b5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/sys/ucontext.h @@ -0,0 +1,97 @@ +/* Copyright (C) 1998, 1999, 2001, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* System V/ARM ABI compliant context switching support. */ + +#ifndef _SYS_UCONTEXT_H +#define _SYS_UCONTEXT_H 1 + +#include +#include +#include + +/* We need the signal context definitions even if they are not used + included in . */ +#include + +typedef int greg_t; + +/* Number of general registers. */ +#define NGREG 18 + +/* Container for all general registers. */ +typedef elf_gregset_t gregset_t; + +/* Number of each register is the `gregset_t' array. */ +enum +{ + R0 = 0, +#define R0 R0 + R1 = 1, +#define R1 R1 + R2 = 2, +#define R2 R2 + R3 = 3, +#define R3 R3 + R4 = 4, +#define R4 R4 + R5 = 5, +#define R5 R5 + R6 = 6, +#define R6 R6 + R7 = 7, +#define R7 R7 + R8 = 8, +#define R8 R8 + R9 = 9, +#define R9 R9 + R10 = 10, +#define R10 R10 + R11 = 11, +#define R11 R11 + R12 = 12, +#define R12 R12 + R13 = 13, +#define R13 R13 + R14 = 14, +#define R14 R14 + R15 = 15 +#define R15 R15 +}; + +/* Structure to describe FPU registers. */ +typedef elf_fpregset_t fpregset_t; + +/* Context to describe whole processor state. This only describes + the core registers; coprocessor registers get saved elsewhere + (e.g. in uc_regspace, or somewhere unspecified on the stack + during non-RT signal handlers). */ +typedef struct sigcontext mcontext_t; + +/* Userlevel context. */ +typedef struct ucontext + { + unsigned long uc_flags; + struct ucontext *uc_link; + stack_t uc_stack; + mcontext_t uc_mcontext; + __sigset_t uc_sigmask; + unsigned long uc_regspace[128] __attribute__((__aligned__(8))); + } ucontext_t; + +#endif /* sys/ucontext.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/sys/user.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/sys/user.h new file mode 100644 index 00000000..3fae43f8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/sys/user.h @@ -0,0 +1,72 @@ +/* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_USER_H +#define _SYS_USER_H 1 + +/* The whole purpose of this file is for GDB and GDB only. Don't read + too much into it. Don't use it for anything other than GDB unless + you know what you are doing. */ + +struct user_fpregs +{ + struct fp_reg + { + unsigned int sign1:1; + unsigned int unused:15; + unsigned int sign2:1; + unsigned int exponent:14; + unsigned int j:1; + unsigned int mantissa1:31; + unsigned int mantissa0:32; + } fpregs[8]; + unsigned int fpsr:32; + unsigned int fpcr:32; + unsigned char ftype[8]; + unsigned int init_flag; +}; + +struct user_regs +{ + unsigned long int uregs[18]; +}; + +struct user +{ + struct user_regs regs; /* General registers */ + int u_fpvalid; /* True if math co-processor being used. */ + + unsigned long int u_tsize; /* Text segment size (pages). */ + unsigned long int u_dsize; /* Data segment size (pages). */ + unsigned long int u_ssize; /* Stack segment size (pages). */ + + unsigned long start_code; /* Starting virtual address of text. */ + unsigned long start_stack; /* Starting virtual address of stack. */ + + long int signal; /* Signal that caused the core dump. */ + int reserved; /* No longer used */ + struct user_regs *u_ar0; /* help gdb to find the general registers. */ + + unsigned long magic; /* uniquely identify a core file */ + char u_comm[32]; /* User command that was responsible */ + int u_debugreg[8]; + struct user_fpregs u_fp; /* Floating point registers */ + struct user_fpregs *u_fp0; /* help gdb to find the FP registers. */ +}; + +#endif /* sys/user.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/syscall-eabi.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/syscall-eabi.S new file mode 100644 index 00000000..b9318821 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/syscall-eabi.S @@ -0,0 +1,73 @@ +/* Copyright (C) 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +/* In the EABI syscall interface, we don't need a special syscall to + implement syscall(). It won't work reliably with 64-bit arguments + (but that is true on many modern platforms). */ + +.text +.global syscall +.type syscall,%function +.align 4 +#if defined(THUMB1_ONLY) +.thumb_func +syscall: + push {r4, r5, r6, r7} + mov ip, r0 + mov r0, r1 + mov r1, r2 + mov r2, r3 + add r7, sp, #(4 * 4) + ldmia r7!, {r3, r4, r5, r6} + mov r7, ip + swi 0x0 + pop {r4, r5, r6, r7} + ldr r1, =0xfffff000 + cmp r0, r1 + bcs 1f + bx lr +1: + push {r3, lr} + bl __syscall_error + POP_RET +.pool +#else +syscall: + mov ip, sp + stmfd sp!, {r4, r5, r6, r7} + mov r7, r0 + mov r0, r1 + mov r1, r2 + mov r2, r3 + ldmfd ip, {r3, r4, r5, r6} + swi 0x0 + ldmfd sp!, {r4, r5, r6, r7} + cmn r0, #4096 + IT(t, cc) +#if defined(__USE_BX__) + bxcc lr +#else + movcc pc, lr +#endif + b __syscall_error +#endif + +.size syscall,.-syscall diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/syscall.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/syscall.c new file mode 100644 index 00000000..60fbcf89 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/syscall.c @@ -0,0 +1,53 @@ +/* vi: set sw=4 ts=4: */ +/* syscall for arm/uClibc + * + * Copyright (C) 2002 by Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include + + +long syscall(long sysnum, long a, long b, long c, long d, long e, long f) +{ +#if !defined(__thumb__) + register long _r0 __asm__("r0")=(long)(sysnum); + register long _r6 __asm__("r6")=(long)(f); + register long _r5 __asm__("r5")=(long)(e); + register long _r4 __asm__("r4")=(long)(d); + register long _r3 __asm__("r3")=(long)(c); + register long _r2 __asm__("r2")=(long)(b); + register long _r1 __asm__("r1")=(long)(a); + __asm__ __volatile__( + "swi %1" + : "=r"(_r0) + : "i"(__NR_syscall), "r"(_r0), "r"(_r1), + "r"(_r2), "r"(_r3), "r"(_r4), "r"(_r5), + "r"(_r6) + : "memory"); +#else + register long _r7 __asm__("r7")=(long)(sysnum); + register long _r5 __asm__("r5")=(long)(f); + register long _r4 __asm__("r4")=(long)(e); + register long _r3 __asm__("r3")=(long)(d); + register long _r2 __asm__("r2")=(long)(c); + register long _r1 __asm__("r1")=(long)(b); + register long _r0 __asm__("r0")=(long)(a); + __asm__ __volatile__( + "swi 0" + : "=r"(_r0) + : "r"(_r0), "r"(_r1), "r"(_r2), "r"(_r3), + "r"(_r4), "r"(_r5), "r"(_r7) + : "memory"); +#endif + if(_r0 >=(unsigned long) -4095) { + long err = _r0; + (*__errno_location())=(-err); + _r0=(unsigned long) -1; + } + return (long) _r0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/sysdep.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/sysdep.h new file mode 100644 index 00000000..013f88cd --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/sysdep.h @@ -0,0 +1,367 @@ +/* Assembler macros for ARM. + Copyright (C) 1997, 1998, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _LINUX_ARM_SYSDEP_H +#define _LINUX_ARM_SYSDEP_H 1 + +#include + +#include +/* For Linux we can use the system call table in the header file + /usr/include/asm/unistd.h + of the kernel. But these symbols do not follow the SYS_* syntax + so we have to redefine the `SYS_ify' macro here. */ +#undef SYS_ify +#define SWI_BASE (0x900000) +#define SYS_ify(syscall_name) (__NR_##syscall_name) + +#ifdef __ASSEMBLER__ + +/* Syntactic details of assembler. */ + +#define ALIGNARG(log2) log2 +/* For ELF we need the `.type' directive to make shared libs work right. */ +#define ASM_TYPE_DIRECTIVE(name,typearg) .type name,%##typearg; +#define ASM_SIZE_DIRECTIVE(name) .size name,.-name + +/* In ELF C symbols are asm symbols. */ +#undef NO_UNDERSCORES +#define NO_UNDERSCORES + +#define PLTJMP(_x) _x##(PLT) + +/* APCS-32 doesn't preserve the condition codes across function call. */ +#ifdef __APCS_32__ +#define LOADREGS(cond, base, reglist...)\ + ldm##cond base,reglist +#ifdef __USE_BX__ +#define RETINSTR(cond, reg) \ + bx##cond reg +#define DO_RET(_reg) \ + bx _reg +#else +#define RETINSTR(cond, reg) \ + mov##cond pc, reg +#define DO_RET(_reg) \ + mov pc, _reg +#endif +#else /* APCS-26 */ +#define LOADREGS(cond, base, reglist...) \ + ldm##cond base,reglist^ +#define RETINSTR(cond, reg) \ + mov##cond##s pc, reg +#define DO_RET(_reg) \ + movs pc, _reg +#endif + +/* Define an entry point visible from C. */ +#define ENTRY(name) \ + ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(name); \ + ASM_TYPE_DIRECTIVE (C_SYMBOL_NAME(name),function) \ + .align ALIGNARG(4); \ + name##: \ + CALL_MCOUNT + +#undef END +#define END(name) \ + ASM_SIZE_DIRECTIVE(name) + +/* If compiled for profiling, call `mcount' at the start of each function. */ +#ifdef PROF +#define CALL_MCOUNT \ + str lr,[sp, #-4]! ; \ + bl PLTJMP(mcount) ; \ + ldr lr, [sp], #4 ; +#else +#define CALL_MCOUNT /* Do nothing. */ +#endif + +#ifdef NO_UNDERSCORES +/* Since C identifiers are not normally prefixed with an underscore + on this system, the asm identifier `syscall_error' intrudes on the + C name space. Make sure we use an innocuous name. */ +#define syscall_error __syscall_error +#define mcount _mcount +#endif +/* Linux uses a negative return value to indicate syscall errors, + unlike most Unices, which use the condition codes' carry flag. + + Since version 2.1 the return value of a system call might be + negative even if the call succeeded. E.g., the `lseek' system call + might return a large offset. Therefore we must not anymore test + for < 0, but test for a real error by making sure the value in R0 + is a real error number. Linus said he will make sure the no syscall + returns a value in -1 .. -4095 as a valid result so we can safely + test with -4095. */ + +#undef PSEUDO +#define PSEUDO(name, syscall_name, args) \ + .text; \ + ENTRY (name); \ + DO_CALL (syscall_name, args); \ + cmn r0, $4096; + +#define PSEUDO_RET \ + RETINSTR(cc, lr); \ + b PLTJMP(SYSCALL_ERROR) +#undef ret +#define ret PSEUDO_RET + +#undef PSEUDO_END +#define PSEUDO_END(name) \ + SYSCALL_ERROR_HANDLER \ + END (name) + +#undef PSEUDO_NOERRNO +#define PSEUDO_NOERRNO(name, syscall_name, args) \ + .text; \ + ENTRY (name); \ + DO_CALL (syscall_name, args); + +#define PSEUDO_RET_NOERRNO \ + DO_RET (lr); + +#undef ret_NOERRNO +#define ret_NOERRNO PSEUDO_RET_NOERRNO + +#undef PSEUDO_END_NOERRNO +#define PSEUDO_END_NOERRNO(name) \ + END (name) + +/* The function has to return the error code. */ +#undef PSEUDO_ERRVAL +#define PSEUDO_ERRVAL(name, syscall_name, args) \ + .text; \ + ENTRY (name) \ + DO_CALL (syscall_name, args); \ + rsb r0, r0, #0 + +#undef PSEUDO_END_ERRVAL +#define PSEUDO_END_ERRVAL(name) \ + END (name) + +#define ret_ERRVAL PSEUDO_RET_NOERRNO + +#if defined NOT_IN_libc +# define SYSCALL_ERROR __local_syscall_error +# ifdef RTLD_PRIVATE_ERRNO +# define SYSCALL_ERROR_HANDLER \ +__local_syscall_error: \ + ldr r1, 1f; \ + rsb r0, r0, #0; \ +0: str r0, [pc, r1]; \ + mvn r0, #0; \ + DO_RET(lr); \ +1: .word C_SYMBOL_NAME(rtld_errno) - 0b - 8; +# else +# define SYSCALL_ERROR_HANDLER \ +__local_syscall_error: \ + str lr, [sp, #-4]!; \ + str r0, [sp, #-4]!; \ + bl PLTJMP(C_SYMBOL_NAME(__errno_location)); \ + ldr r1, [sp], #4; \ + rsb r1, r1, #0; \ + str r1, [r0]; \ + mvn r0, #0; \ + ldr pc, [sp], #4; +# endif +#else +# define SYSCALL_ERROR_HANDLER /* Nothing here; code in sysdep.S is used. */ +# define SYSCALL_ERROR __syscall_error +#endif + +/* Linux takes system call args in registers: + syscall number in the SWI instruction + arg 1 r0 + arg 2 r1 + arg 3 r2 + arg 4 r3 + arg 5 r4 (this is different from the APCS convention) + arg 6 r5 + arg 7 r6 + + The compiler is going to form a call by coming here, through PSEUDO, with + arguments + syscall number in the DO_CALL macro + arg 1 r0 + arg 2 r1 + arg 3 r2 + arg 4 r3 + arg 5 [sp] + arg 6 [sp+4] + arg 7 [sp+8] + + We need to shuffle values between R4..R6 and the stack so that the + caller's v1..v3 and stack frame are not corrupted, and the kernel + sees the right arguments. + +*/ + +#undef DO_CALL +#if defined(__ARM_EABI__) +#define DO_CALL(syscall_name, args) \ + DOARGS_##args \ + mov ip, r7; \ + ldr r7, =SYS_ify (syscall_name); \ + swi 0x0; \ + mov r7, ip; \ + UNDOARGS_##args +#else +#define DO_CALL(syscall_name, args) \ + DOARGS_##args \ + swi SYS_ify (syscall_name); \ + UNDOARGS_##args +#endif + +#define DOARGS_0 /* nothing */ +#define DOARGS_1 /* nothing */ +#define DOARGS_2 /* nothing */ +#define DOARGS_3 /* nothing */ +#define DOARGS_4 /* nothing */ +#define DOARGS_5 str r4, [sp, $-4]!; ldr r4, [sp, $4]; +#define DOARGS_6 mov ip, sp; stmfd sp!, {r4, r5}; ldmia ip, {r4, r5}; +#define DOARGS_7 mov ip, sp; stmfd sp!, {r4, r5, r6}; ldmia ip, {r4, r5, r6}; + +#define UNDOARGS_0 /* nothing */ +#define UNDOARGS_1 /* nothing */ +#define UNDOARGS_2 /* nothing */ +#define UNDOARGS_3 /* nothing */ +#define UNDOARGS_4 /* nothing */ +#define UNDOARGS_5 ldr r4, [sp], $4; +#define UNDOARGS_6 ldmfd sp!, {r4, r5}; +#define UNDOARGS_7 ldmfd sp!, {r4, r5, r6}; + +#else /* not __ASSEMBLER__ */ +/* Define a macro which expands into the inline wrapper code for a system + call. */ +#undef INLINE_SYSCALL +#define INLINE_SYSCALL(name, nr, args...) \ + ({ unsigned int _inline_sys_result = INTERNAL_SYSCALL (name, , nr, args); \ + if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (_inline_sys_result, ), 0)) \ + { \ + __set_errno (INTERNAL_SYSCALL_ERRNO (_inline_sys_result, )); \ + _inline_sys_result = (unsigned int) -1; \ + } \ + (int) _inline_sys_result; }) + +#undef INTERNAL_SYSCALL_DECL +#define INTERNAL_SYSCALL_DECL(err) do { } while (0) + +#undef INTERNAL_SYSCALL_RAW +#if defined(__thumb__) +/* Hide the use of r7 from the compiler, this would be a lot + * easier but for the fact that the syscalls can exceed 255. + * For the moment the LOAD_ARG_7 is sacrificed. + * We can't use push/pop inside the asm because that breaks + * unwinding (ie. thread cancellation). + */ +#define INTERNAL_SYSCALL_RAW(name, err, nr, args...) \ + ({ unsigned int _internal_sys_result; \ + { \ + int _sys_buf[2]; \ + register int __a1 __asm__ ("a1"); \ + register int *_v3 __asm__ ("v3") = _sys_buf; \ + LOAD_ARGS_##nr (args) \ + *_v3 = (int) (name); \ + __asm__ __volatile__ ("str r7, [v3, #4]\n" \ + "\tldr r7, [v3]\n" \ + "\tswi 0 @ syscall " #name "\n" \ + "\tldr r7, [v3, #4]" \ + : "=r" (__a1) \ + : "r" (_v3) ASM_ARGS_##nr \ + : "memory"); \ + _internal_sys_result = __a1; \ + } \ + (int) _internal_sys_result; }) +#elif defined(__ARM_EABI__) +#define INTERNAL_SYSCALL_RAW(name, err, nr, args...) \ + ({unsigned int _internal_sys_result; \ + { \ + register int __a1 __asm__ ("r0"), _nr __asm__ ("r7"); \ + LOAD_ARGS_##nr (args) \ + _nr = name; \ + __asm__ __volatile__ ("swi 0x0 @ syscall " #name \ + : "=r" (__a1) \ + : "r" (_nr) ASM_ARGS_##nr \ + : "memory"); \ + _internal_sys_result = __a1; \ + } \ + (int) _internal_sys_result; }) +#else /* !defined(__ARM_EABI__) */ +#define INTERNAL_SYSCALL_RAW(name, err, nr, args...) \ + ({ unsigned int _internal_sys_result; \ + { \ + register int __a1 __asm__ ("a1"); \ + LOAD_ARGS_##nr (args) \ + __asm__ __volatile__ ("swi %1 @ syscall " #name \ + : "=r" (__a1) \ + : "i" (name) ASM_ARGS_##nr \ + : "memory"); \ + _internal_sys_result = __a1; \ + } \ + (int) _internal_sys_result; }) +#endif + +#undef INTERNAL_SYSCALL +#define INTERNAL_SYSCALL(name, err, nr, args...) \ + INTERNAL_SYSCALL_RAW(SYS_ify(name), err, nr, args) + +#undef INTERNAL_SYSCALL_ARM +#define INTERNAL_SYSCALL_ARM(name, err, nr, args...) \ + INTERNAL_SYSCALL_RAW(__ARM_NR_##name, err, nr, args) + +#undef INTERNAL_SYSCALL_ERROR_P +#define INTERNAL_SYSCALL_ERROR_P(val, err) \ + ((unsigned int) (val) >= 0xfffff001u) + +#undef INTERNAL_SYSCALL_ERRNO +#define INTERNAL_SYSCALL_ERRNO(val, err) (-(val)) + +#if defined(__ARM_EABI__) +#undef INTERNAL_SYSCALL_NCS +#define INTERNAL_SYSCALL_NCS(number, err, nr, args...) \ + INTERNAL_SYSCALL_RAW(number, err, nr, args) +#else +/* We can't implement non-constant syscalls directly since the syscall + number is normally encoded in the instruction. So use SYS_syscall. */ +#undef INTERNAL_SYSCALL_NCS +#define INTERNAL_SYSCALL_NCS(number, err, nr, args...) \ + INTERNAL_SYSCALL_NCS_##nr (number, err, args) + +#define INTERNAL_SYSCALL_NCS_0(number, err, args...) \ + INTERNAL_SYSCALL (syscall, err, 1, number, args) +#define INTERNAL_SYSCALL_NCS_1(number, err, args...) \ + INTERNAL_SYSCALL (syscall, err, 2, number, args) +#define INTERNAL_SYSCALL_NCS_2(number, err, args...) \ + INTERNAL_SYSCALL (syscall, err, 3, number, args) +#define INTERNAL_SYSCALL_NCS_3(number, err, args...) \ + INTERNAL_SYSCALL (syscall, err, 4, number, args) +#define INTERNAL_SYSCALL_NCS_4(number, err, args...) \ + INTERNAL_SYSCALL (syscall, err, 5, number, args) +#define INTERNAL_SYSCALL_NCS_5(number, err, args...) \ + INTERNAL_SYSCALL (syscall, err, 6, number, args) +#endif + +#endif /* __ASSEMBLER__ */ + +/* Pointer mangling is not yet supported for ARM. */ +#define PTR_MANGLE(var) (void) (var) +#define PTR_DEMANGLE(var) (void) (var) + +#endif /* linux/arm/sysdep.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/vfork.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/vfork.S new file mode 100644 index 00000000..17d6a4db --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/arm/vfork.S @@ -0,0 +1,108 @@ +/* vi: set sw=4 ts=4: */ +/* + * vfork for uClibc + * Copyright (C) 2000-2006 by Erik Andersen + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +#define _ERRNO_H +#include +#include + +#ifndef SAVE_PID +#define SAVE_PID +#endif + +#ifndef RESTORE_PID +#define RESTORE_PID +#endif + + +#ifdef __NR_fork +.text +.global __vfork +.hidden __vfork +.type __vfork,%function +.align 4 + +#if defined(__thumb__) && !defined(__thumb2__) +.thumb_func +__vfork: +#ifdef __NR_vfork + SAVE_PID + DO_CALL (vfork) + RESTORE_PID + ldr r1, =0xfffff000 + cmp r0, r1 + bcs 1f + bx lr +1: + + /* Check if vfork even exists. */ + ldr r1, =-ENOSYS + cmp r0, r1 + bne __error + + /* If we don't have vfork, use fork. */ + DO_CALL (fork) + ldr r1, =0xfffff000 + cmp r0, r1 + + /* Syscall worked. Return to child/parent */ + bcs 1f + bx lr +1: + +__error: + push {r3, lr} + bl __syscall_error + POP_RET +.pool + +#endif + +#else +__vfork: + +#ifdef __NR_vfork + SAVE_PID + DO_CALL (vfork) + RESTORE_PID + cmn r0, #4096 + IT(t, cc) +#if defined(__USE_BX__) + bxcc lr +#else + movcc pc, lr +#endif + + /* Check if vfork even exists. */ + ldr r1, =-ENOSYS + teq r0, r1 + bne __error +#endif + + /* If we don't have vfork, use fork. */ + DO_CALL (fork) + cmn r0, #4096 + + /* Syscall worked. Return to child/parent */ + IT(t, cc) +#if defined(__USE_BX__) + bxcc lr +#else + movcc pc, lr +#endif + +__error: + b __syscall_error +#endif + +.size __vfork,.-__vfork + +weak_alias(__vfork,vfork) +libc_hidden_weak(vfork) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/Makefile new file mode 100644 index 00000000..338abc08 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/Makefile @@ -0,0 +1,25 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2003 Erik Andersen +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU Library General Public License as published by the Free +# Software Foundation; either version 2 of the License, or (at your option) any +# later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more +# details. +# +# You should have received a copy of the GNU Library General Public License +# along with this program; if not, write to the Free Software Foundation, Inc., +# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +top_srcdir=../../../../ +top_builddir=../../../../ +all: objs + +include $(top_builddir)Rules.mak +include Makefile.arch +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/Makefile.arch b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/Makefile.arch new file mode 100644 index 00000000..98b85a7c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/Makefile.arch @@ -0,0 +1,11 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +CSRC := brk.c clone.c mmap.c prctl.c sigaction.c + +SSRC := __longjmp.S setjmp.S bsd-setjmp.S bsd-_setjmp.S \ + sigrestorer.S syscall.S vfork.S diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/__longjmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/__longjmp.S new file mode 100644 index 00000000..6154bb2a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/__longjmp.S @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2004-2007 Atmel Corporation + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License. See the file "COPYING.LIB" in the main directory of this + * archive for more details. + */ + + .global __longjmp + .type __longjmp,"function" + .align 1 +__longjmp: + ldm r12++, r0-r8,sp,lr + mustr r8 /* restore status register (lower half) */ + cp r11, 0 /* can't return zero */ + frs + moveq r11, 1 + retal r11 + .size __longjmp, . - __longjmp + +libc_hidden_def(__longjmp) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/bits/atomic.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/bits/atomic.h new file mode 100644 index 00000000..e6be41f0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/bits/atomic.h @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2007 Atmel Corporation + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License. See the file "COPYING.LIB" in the main directory of this + * archive for more details. + */ +#ifndef _AVR32_BITS_ATOMIC_H +#define _AVR32_BITS_ATOMIC_H 1 + +#include + +typedef int32_t atomic32_t; +typedef uint32_t uatomic32_t; +typedef int_fast32_t atomic_fast32_t; +typedef uint_fast32_t uatomic_fast32_t; + +typedef intptr_t atomicptr_t; +typedef uintptr_t uatomicptr_t; +typedef intmax_t atomic_max_t; +typedef uintmax_t uatomic_max_t; + +#define __arch_compare_and_exchange_val_8_acq(mem, newval, oldval) \ + (abort(), 0) + +#define __arch_compare_and_exchange_val_16_acq(mem, newval, oldval) \ + (abort(), 0) + +#define __arch_compare_and_exchange_val_32_acq(mem, newval, oldval) \ + ({ \ + __typeof__(*(mem)) __prev; \ + __asm__ __volatile__( \ + "/* __arch_compare_and_exchange_val_32_acq */\n" \ + "1: ssrf 5\n" \ + " ld.w %[result], %[m]\n" \ + " cp.w %[result], %[old]\n" \ + " brne 2f\n" \ + " stcond %[m], %[new]\n" \ + " brne 1b\n" \ + "2:" \ + : [result] "=&r"(__result), [m] "=m"(*(mem)) \ + : "m"(*(mem)), [old] "ir"(oldval), \ + [new] "r"(newval) \ + : "memory", "cc"); \ + __prev; \ + }) + +#define __arch_compare_and_exchange_val_64_acq(mem, newval, oldval) \ + (abort(), 0) + +#define __arch_exchange_32_acq(mem, newval) \ + ({ \ + __typeof__(*(mem)) __oldval; \ + __asm__ __volatile__( \ + "/*__arch_exchange_32_acq */\n" \ + " xchg %[old], %[m], %[new]" \ + : [old] "=&r"(__oldval) \ + : [m] "r"(mem), [new] "r"(newval) \ + : "memory"); \ + __oldval; \ + }) + +#define __arch_atomic_exchange_and_add_32(mem, value) \ + ({ \ + __typeof__(*(mem)) __oldval, __tmp; \ + __asm__ __volatile__( \ + "/* __arch_atomic_exchange_and_add_32 */\n" \ + "1: ssrf 5\n" \ + " ld.w %[old], %[m]\n" \ + " add %[tmp], %[old], %[val]\n" \ + " stcond %[m], %[tmp]\n" \ + " brne 1b" \ + : [old] "=&r"(__oldval), [tmp] "=&r"(__tmp), \ + [m] "=m"(*(mem)) \ + : "m"(*(mem)), [val] "r"(value) \ + : "memory", "cc"); \ + __oldval; \ + }) + +#define __arch_atomic_decrement_if_positive_32(mem) \ + ({ \ + __typeof__(*(mem)) __oldval, __tmp; \ + __asm__ __volatile__( \ + "/* __arch_atomic_decrement_if_positive_32 */\n" \ + "1: ssrf 5\n" \ + " ld.w %[old], %[m]\n" \ + " sub %[tmp], %[old], 1\n" \ + " brlt 2f\n" \ + " stcond %[m], %[tmp]\n" \ + " brne 1b" \ + "2:" \ + : [old] "=&r"(__oldval), [tmp] "=&r"(__tmp), \ + [m] "=m"(*(mem)) \ + : "m"(*(mem)) \ + : "memory", "cc"); \ + __oldval; \ + }) + +#define atomic_exchange_acq(mem, newval) \ + ({ \ + if (sizeof(*(mem)) != 4) \ + abort(); \ + __arch_exchange_32_acq(mem, newval); \ + }) + +#define atomic_exchange_and_add(mem, newval) \ + ({ \ + if (sizeof(*(mem)) != 4) \ + abort(); \ + __arch_atomic_exchange_and_add_32(mem, newval); \ + }) + +#define atomic_decrement_if_positive(mem) \ + ({ \ + if (sizeof(*(mem)) != 4) \ + abort(); \ + __arch_atomic_decrement_if_positive_32(mem); \ + }) + +#endif /* _AVR32_BITS_ATOMIC_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/bits/endian.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/bits/endian.h new file mode 100644 index 00000000..7bb63585 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/bits/endian.h @@ -0,0 +1,7 @@ +/* AVR32 is big-endian */ + +#ifndef _ENDIAN_H +# error "Never use directly; include instead." +#endif + +#define __BYTE_ORDER __BIG_ENDIAN diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/bits/fcntl.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/bits/fcntl.h new file mode 100644 index 00000000..767243ee --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/bits/fcntl.h @@ -0,0 +1,215 @@ +#ifndef _FCNTL_H +# error "Never use directly; include instead." +#endif + +#include +#ifdef __USE_GNU +# include +#endif + +/* + * open/fcntl - O_SYNC is only implemented on blocks devices and on files + * located on an ext2 file system + */ +#define O_ACCMODE 00000003 +#define O_RDONLY 00000000 +#define O_WRONLY 00000001 +#define O_RDWR 00000002 +#define O_CREAT 00000100 /* not fcntl */ +#define O_EXCL 00000200 /* not fcntl */ +#define O_NOCTTY 00000400 /* not fcntl */ +#define O_TRUNC 00001000 /* not fcntl */ +#define O_APPEND 00002000 +#define O_NONBLOCK 00004000 +#define O_NDELAY O_NONBLOCK +#define O_SYNC 00010000 +#define O_ASYNC 00020000 + +#ifdef __USE_GNU +# define O_DIRECT 00040000 /* must be a directory */ +# define O_DIRECTORY 00200000 /* direct disk access */ +# define O_NOFOLLOW 00400000 /* don't follow links */ +# define O_NOATIME 01000000 /* don't set atime */ +# define O_CLOEXEC 02000000 /* set close_on_exec */ +#endif + +#ifdef __USE_LARGEFILE64 +# define O_LARGEFILE 00100000 +#endif + +/* For now Linux has synchronisity options for data and read operations. + We define the symbols here but let them do the same as O_SYNC since + this is a superset. */ +#if defined __USE_POSIX199309 || defined __USE_UNIX98 +# define O_DSYNC O_SYNC /* Synchronize data. */ +# define O_RSYNC O_SYNC /* Synchronize read operations. */ +#endif + +#define F_DUPFD 0 /* dup */ +#define F_GETFD 1 /* get close_on_exec */ +#define F_SETFD 2 /* set/clear close_on_exec */ +#define F_GETFL 3 /* get file->f_flags */ +#define F_SETFL 4 /* set file->f_flags */ + +#ifndef __USE_FILE_OFFSET64 +# define F_GETLK 5 +# define F_SETLK 6 +# define F_SETLKW 7 +#else +# define F_GETLK F_GETLK64 +# define F_SETLK F_SETLK64 +# define F_SETLKW F_SETLKW64 +#endif +#define F_GETLK64 12 /* using 'struct flock64' */ +#define F_SETLK64 13 +#define F_SETLKW64 14 + +#if defined __USE_BSD || defined __USE_XOPEN2K +# define F_SETOWN 8 /* for sockets. */ +# define F_GETOWN 9 /* for sockets. */ +#endif + +#ifdef __USE_GNU +# define F_SETSIG 10 /* for sockets. */ +# define F_GETSIG 11 /* for sockets. */ +#endif + +#ifdef __USE_GNU +# define F_SETLEASE 1024 /* Set a lease. */ +# define F_GETLEASE 1025 /* Enquire what lease is active. */ +# define F_NOTIFY 1026 /* Request notfications on a directory. */ +#endif + +/* for F_[GET|SET]FL */ +#define FD_CLOEXEC 1 /* actually anything with low bit set goes */ + +/* for posix fcntl() and lockf() */ +#define F_RDLCK 0 +#define F_WRLCK 1 +#define F_UNLCK 2 + +/* for old implementation of bsd flock () */ +#define F_EXLCK 4 /* or 3 */ +#define F_SHLCK 8 /* or 4 */ + +/* for leases */ +#define F_INPROGRESS 16 + +#ifdef __USE_BSD +/* operations for bsd flock(), also used by the kernel implementation */ +# define LOCK_SH 1 /* shared lock */ +# define LOCK_EX 2 /* exclusive lock */ +# define LOCK_NB 4 /* or'd with one of the above to prevent + blocking */ +# define LOCK_UN 8 /* remove lock */ +#endif + +#ifdef __USE_GNU +# define LOCK_MAND 32 /* This is a mandatory flock */ +# define LOCK_READ 64 /* ... Which allows concurrent + read operations */ +# define LOCK_WRITE 128 /* ... Which allows concurrent + write operations */ +# define LOCK_RW 192 /* ... Which allows concurrent + read & write ops */ +#endif + +#ifdef __USE_GNU +/* Types of directory notifications that may be requested with F_NOTIFY. */ +# define DN_ACCESS 0x00000001 /* File accessed. */ +# define DN_MODIFY 0x00000002 /* File modified. */ +# define DN_CREATE 0x00000004 /* File created. */ +# define DN_DELETE 0x00000008 /* File removed. */ +# define DN_RENAME 0x00000010 /* File renamed. */ +# define DN_ATTRIB 0x00000020 /* File changed attibutes. */ +# define DN_MULTISHOT 0x80000000 /* Don't remove notifier. */ +#endif + +struct flock { + short l_type; + short l_whence; +#ifndef __USE_FILE_OFFSET64 + __off_t l_start; + __off_t l_len; +#else + __off64_t l_start; + __off64_t l_len; +#endif + __pid_t l_pid; +}; + +#ifdef __USE_LARGEFILE64 +struct flock64 { + short l_type; + short l_whence; + __off64_t l_start; + __off64_t l_len; + __pid_t l_pid; +}; +#endif + +/* Define some more compatibility macros to be backward compatible with + * BSD systems which did not managed to hide these kernel macros. */ +#ifdef __USE_BSD +# define FAPPEND O_APPEND +# define FFSYNC O_FSYNC +# define FASYNC O_ASYNC +# define FNONBLOCK O_NONBLOCK +# define FNDELAY O_NDELAY +#endif /* Use BSD. */ + +/* Advise to `posix_fadvise'. */ +#ifdef __USE_XOPEN2K +# define POSIX_FADV_NORMAL 0 /* No further special treatment. */ +# define POSIX_FADV_RANDOM 1 /* Expect random page references. */ +# define POSIX_FADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define POSIX_FADV_WILLNEED 3 /* Will need these pages. */ +# define POSIX_FADV_DONTNEED 4 /* Don't need these pages. */ +# define POSIX_FADV_NOREUSE 5 /* Data will be accessed once. */ +#endif + + +#if defined __USE_GNU && defined __UCLIBC_LINUX_SPECIFIC__ +/* Flags for SYNC_FILE_RANGE. */ +# define SYNC_FILE_RANGE_WAIT_BEFORE 1 /* Wait upon writeout of all pages + in the range before performing + the write */ +# define SYNC_FILE_RANGE_WRITE 2 /* Initiate writeout of all those + dirty pages in the range which are + not presently under writeback */ +# define SYNC_FILE_RANGE_WAIT_AFTER 4 /* Wait upon writeout of all pages + in the range after performing the + write */ + +/* Flags for splice() and vmsplice() */ +# define SPLICE_F_MOVE 1 /* Move pages instead of copying */ +# define SPLICE_F_NONBLOCK 2 /* Don't block on the pipe splicing + (but we may still block on the fd + we splice from/to) */ +# define SPLICE_F_MORE 4 /* Expect more data */ +# define SPLICE_F_GIFT 8 /* Pages passed in are a gift */ + +__BEGIN_DECLS + +/* Provide kernel hint to read ahead. */ +extern ssize_t readahead (int __fd, __off64_t __offset, size_t __count) __THROW; + +/* Selective file content synch'ing */ +extern int sync_file_range (int __fd, __off64_t __from, __off64_t __to, + unsigned int __flags); + +/* Splice address range into a pipe */ +extern ssize_t vmsplice (int __fdout, const struct iovec *__iov, + size_t __count, unsigned int __flags); + +/* Splice two files together */ +extern ssize_t splice (int __fdin, __off64_t *__offin, int __fdout, + __off64_t *__offout, size_t __len, + unsigned int __flags); + +/* In-kernel implementation of tee for pipe buffers */ +extern ssize_t tee (int __fdin, int __fdout, size_t __len, + unsigned int __flags); + +__END_DECLS +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/bits/kernel_stat.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/bits/kernel_stat.h new file mode 100644 index 00000000..8442c3c1 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/bits/kernel_stat.h @@ -0,0 +1,57 @@ +#ifndef _BITS_STAT_STRUCT_H +#define _BITS_STAT_STRUCT_H + +#ifndef _LIBC +#error bits/kernel_stat.h is for internal uClibc use only! +#endif + +/* + * This file provides struct stat, taken from kernel 2.6.4. Verified + * to match kernel 2.6.22. + */ + +struct kernel_stat { + unsigned long st_dev; + unsigned long st_ino; + unsigned short st_mode; + unsigned short st_nlink; + unsigned short st_uid; + unsigned short st_gid; + unsigned long st_rdev; + unsigned long st_size; + unsigned long st_blksize; + unsigned long st_blocks; + struct timespec st_atim; + struct timespec st_mtim; + struct timespec st_ctim; + unsigned long __unused4; + unsigned long __unused5; +}; + +struct kernel_stat64 { + unsigned long long st_dev; + + unsigned long long st_ino; + unsigned int st_mode; + unsigned int st_nlink; + + unsigned long st_uid; + unsigned long st_gid; + + unsigned long long st_rdev; + + long long st_size; + unsigned long __pad1; + unsigned long st_blksize; + + unsigned long long st_blocks; + + struct timespec st_atim; + struct timespec st_mtim; + struct timespec st_ctim; + + unsigned long __unused1; + unsigned long __unused2; +}; + +#endif /* _BITS_STAT_STRUCT_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/bits/kernel_types.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/bits/kernel_types.h new file mode 100644 index 00000000..f7d8b529 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/bits/kernel_types.h @@ -0,0 +1,55 @@ +/* Note that we use the exact same include guard #define names + * as asm/posix_types.h. This will avoid gratuitous conflicts + * with the posix_types.h kernel header, and will ensure that + * our private content, and not the kernel header, will win. + * -Erik + */ +#ifndef __ASM_AVR32_POSIX_TYPES_H +#define __ASM_AVR32_POSIX_TYPES_H + +/* + * This file is generally used by user-level software, so you need to + * be a little careful about namespace pollution etc. Also, we cannot + * assume GCC is being used. + */ + +typedef unsigned long __kernel_dev_t; +typedef unsigned long __kernel_ino_t; +typedef unsigned short __kernel_mode_t; +typedef unsigned short __kernel_nlink_t; +typedef long __kernel_off_t; +typedef int __kernel_pid_t; +typedef unsigned short __kernel_ipc_pid_t; +typedef unsigned int __kernel_uid_t; +typedef unsigned int __kernel_gid_t; +typedef unsigned long __kernel_size_t; +typedef long __kernel_ssize_t; +typedef int __kernel_ptrdiff_t; +typedef long __kernel_time_t; +typedef long __kernel_suseconds_t; +typedef long __kernel_clock_t; +typedef int __kernel_timer_t; +typedef int __kernel_clockid_t; +typedef int __kernel_daddr_t; +typedef char * __kernel_caddr_t; +typedef unsigned short __kernel_uid16_t; +typedef unsigned short __kernel_gid16_t; +typedef unsigned int __kernel_uid32_t; +typedef unsigned int __kernel_gid32_t; +typedef unsigned short __kernel_old_uid_t; +typedef unsigned short __kernel_old_gid_t; +typedef unsigned short __kernel_old_dev_t; + +#ifdef __GNUC__ +typedef long long __kernel_loff_t; +#endif + +typedef struct { +#if defined(__USE_ALL) + int val[2]; +#else + int __val[2]; +#endif +} __kernel_fsid_t; + +#endif /* __ASM_AVR32_POSIX_TYPES_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/bits/setjmp.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/bits/setjmp.h new file mode 100644 index 00000000..78348a32 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/bits/setjmp.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2004-2005 Atmel Corporation + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License. See the file "COPYING.LIB" in the main directory of this + * archive for more details. + */ +#ifndef _BITS_SETJMP_H +#define _BITS_SETJMP_H 1 + +#if !defined _SETJMP_H && !defined _PTHREAD_H +# error "Never include directly; use instead." +#endif + +#ifndef _ASM +/* + * The jump buffer contains r0-r7, sr, sp and lr. Other registers are + * not saved. + */ +typedef int __jmp_buf[11]; +#endif + +#define __JMP_BUF_SP 4 + +/* Test if longjmp to JMPBUF would unwind the frame containing a local + variable at ADDRESS. */ +#define _JMPBUF_UNWINDS(jmpbuf, address) \ + ((void *)(address) < (void *)(jmpbuf[__JMP_BUF_SP])) + +#endif /* _BITS_SETJMP_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/bits/stackinfo.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/bits/stackinfo.h new file mode 100644 index 00000000..2c17d30a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/bits/stackinfo.h @@ -0,0 +1,28 @@ +/* Copyright (C) 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This file contains a bit of information about the stack allocation + of the processor. */ + +#ifndef _STACKINFO_H +#define _STACKINFO_H 1 + +/* On AVR32 the stack grows down. */ +#define _STACK_GROWS_DOWN 1 + +#endif /* stackinfo.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/bits/syscalls.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/bits/syscalls.h new file mode 100644 index 00000000..836cb2d7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/bits/syscalls.h @@ -0,0 +1,54 @@ +#ifndef _BITS_SYSCALLS_H +#define _BITS_SYSCALLS_H +#ifndef _SYSCALL_H +# error "Never use directly; include instead." +#endif + +#ifndef __ASSEMBLER__ + +#include + +#define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \ + ({ \ + register int __a1 __asm__("r12"); \ + register int _scno __asm__("r8") = name; \ + LOAD_ARGS_##nr (args); \ + __asm__ __volatile__("scall /* syscall " #name " */" \ + : "=r" (__a1) \ + : "r"(_scno) ASM_ARGS_##nr \ + : "cc", "memory"); \ + __a1; \ + }) + +#define INTERNAL_SYSCALL_ERROR_P(val, err) \ + ((unsigned int)(val) >= 0xfffff001U) + +#define LOAD_ARGS_0() do { } while(0) +#define ASM_ARGS_0 +#define LOAD_ARGS_1(a1) \ + __a1 = (int) (a1); \ + LOAD_ARGS_0() +#define ASM_ARGS_1 ASM_ARGS_0, "r"(__a1) +#define LOAD_ARGS_2(a1, a2) \ + register int __a2 __asm__("r11") = (int)(a2); \ + LOAD_ARGS_1(a1) +#define ASM_ARGS_2 ASM_ARGS_1, "r"(__a2) +#define LOAD_ARGS_3(a1, a2, a3) \ + register int __a3 __asm__("r10") = (int)(a3); \ + LOAD_ARGS_2(a1, a2) +#define ASM_ARGS_3 ASM_ARGS_2, "r"(__a3) +#define LOAD_ARGS_4(a1, a2, a3, a4) \ + register int __a4 __asm__("r9") = (int)(a4); \ + LOAD_ARGS_3(a1, a2, a3) +#define ASM_ARGS_4 ASM_ARGS_3, "r"(__a4) +#define LOAD_ARGS_5(a1, a2, a3, a4, a5) \ + register int __a5 __asm__("r5") = (int)(a5); \ + LOAD_ARGS_4(a1, a2, a3, a4) +#define ASM_ARGS_5 ASM_ARGS_4, "r"(__a5) +#define LOAD_ARGS_6(a1, a2, a3, a4, a5, a6) \ + register int __a6 __asm__("r3") = (int)(a6); \ + LOAD_ARGS_5(a1, a2, a3, a4, a5) +#define ASM_ARGS_6 ASM_ARGS_5, "r"(__a6) + +#endif /* __ASSEMBLER__ */ +#endif /* _BITS_SYSCALLS_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/bits/uClibc_arch_features.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/bits/uClibc_arch_features.h new file mode 100644 index 00000000..c3065777 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/bits/uClibc_arch_features.h @@ -0,0 +1,48 @@ +/* + * Track misc arch-specific features that aren't config options + */ + +#ifndef _BITS_UCLIBC_ARCH_FEATURES_H +#define _BITS_UCLIBC_ARCH_FEATURES_H + +/* instruction used when calling abort() to kill yourself */ +/* trigger illegal instruction exception, same as BUG in Linux */ +#define __UCLIBC_ABORT_INSTRUCTION__ ".short 0x5df0" + +/* can your target use syscall6() for mmap ? */ +#define __UCLIBC_MMAP_HAS_6_ARGS__ + +/* does your target use syscall4() for truncate64 ? (32bit arches only) */ +#undef __UCLIBC_TRUNCATE64_HAS_4_ARGS__ + +/* does your target have a broken create_module() ? */ +#undef __UCLIBC_BROKEN_CREATE_MODULE__ + +/* does your target have to worry about older [gs]etrlimit() ? */ +#undef __UCLIBC_HANDLE_OLDER_RLIMIT__ + +/* does your target have an asm .set ? */ +#define __UCLIBC_HAVE_ASM_SET_DIRECTIVE__ + +/* define if target doesn't like .global */ +#undef __UCLIBC_ASM_GLOBAL_DIRECTIVE__ + +/* define if target supports .weak */ +#define __UCLIBC_HAVE_ASM_WEAK_DIRECTIVE__ + +/* define if target supports .weakext */ +#undef __UCLIBC_HAVE_ASM_WEAKEXT_DIRECTIVE__ + +/* needed probably only for ppc64 */ +#undef __UCLIBC_HAVE_ASM_GLOBAL_DOT_NAME__ + +/* define if target supports CFI pseudo ops */ +#undef __UCLIBC_HAVE_ASM_CFI_DIRECTIVES__ + +/* define if target supports IEEE signed zero floats */ +#define __UCLIBC_HAVE_SIGNED_ZERO__ + +/* only weird assemblers generally need this */ +#undef __UCLIBC_ASM_LINE_SEP__ + +#endif /* _BITS_UCLIBC_ARCH_FEATURES_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/bits/wordsize.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/bits/wordsize.h new file mode 100644 index 00000000..1b5842ad --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/bits/wordsize.h @@ -0,0 +1 @@ +#define __WORDSIZE 32 diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/brk.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/brk.c new file mode 100644 index 00000000..58f04f95 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/brk.c @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2004-2007 Atmel Corporation + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License. See the file "COPYING.LIB" in the main directory of this + * archive for more details. + */ +#include +#include +#include + + +void *__curbrk attribute_hidden = 0; + +int brk (void *addr) +{ + void *newbrk; + + newbrk = (void *)INLINE_SYSCALL(brk, 1, addr); + + __curbrk = newbrk; + + if (newbrk < addr) { + __set_errno (ENOMEM); + return -1; + } + + return 0; +} +libc_hidden_def(brk) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/bsd-_setjmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/bsd-_setjmp.S new file mode 100644 index 00000000..f23e73b8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/bsd-_setjmp.S @@ -0,0 +1,16 @@ +/* + * Copyright (C) 2004-2007 Atmel Corporation + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License. See the file "COPYING.LIB" in the main directory of this + * archive for more details. + */ + + /* This just does a tail-call to __sigsetjmp(env, 0) */ + .global _setjmp + .type _setjmp,"function" + .align 1 +_setjmp: + mov r11, 0 + bral HIDDEN_JUMPTARGET(__sigsetjmp) + .size _setjmp, . - _setjmp diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/bsd-setjmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/bsd-setjmp.S new file mode 100644 index 00000000..5247ec36 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/bsd-setjmp.S @@ -0,0 +1,16 @@ +/* + * Copyright (C) 2004-2007 Atmel Corporation + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License. See the file "COPYING.LIB" in the main directory of this + * archive for more details. + */ + + /* This just does a tail-call to __sigsetjmp(env, 1) */ + .global setjmp + .type setjmp,"function" + .align 1 +setjmp: + mov r11, 1 + bral HIDDEN_JUMPTARGET(__sigsetjmp) + .size setjmp, . - setjmp diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/clone.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/clone.c new file mode 100644 index 00000000..06e3388b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/clone.c @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2004 Atmel Corporation + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License. See the file "COPYING.LIB" in the main directory of this + * archive for more details. + */ +#include +#include +#include +#include + +/* + * I don't know if we can be absolutely certain that the fn and arg + * parameters are preserved when returning as the child. If the + * compiler stores them in registers (r0-r7), they should be. + */ +int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg, ...) +{ + register int (*_fn)(void *arg) = fn; + register void *_arg = arg; + int err; + + /* Sanity check the arguments */ + err = -EINVAL; + if (!fn) + goto syscall_error; + if (!child_stack) + goto syscall_error; + + err = INLINE_SYSCALL(clone, 2, flags, child_stack); + if (err < 0) + goto syscall_error; + else if (err != 0) + return err; + + _exit(_fn(_arg)); + +syscall_error: + __set_errno (-err); + return -1; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/crt1.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/crt1.S new file mode 100644 index 00000000..ca1fa7a4 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/crt1.S @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2004-2007 Atmel Corporation + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License. See the file "COPYING.LIB" in the main directory of this + * archive for more details. + * + * When we enter _start, the stack looks like this: + * argc argument counter + * argv[0] pointer to program name + * argv[1..argc-1] pointers to program args + * NULL + * env[0..N] pointers to environment variables + * NULL + * + * r12 contains a function pointer to be registered with `atexit'. + * This is how the dynamic linker arranges to have DT_FINI functions + * called for shared libraries that have been loaded before this + * code runs. + * + * We're going to call the following function: + * __uClibc_main(int (*main)(int, char **, char **), int argc, + * char **argv, void (*app_init)(void), void (*app_fini)(void), + * void (*rtld_fini)(void), void *stack_end) + * + * So we need to set up things as follows: + * r12 = address of main + * r11 = argc + * r10 = &argv[0] + * r9 = address of _init + * r8 = address of _fini + * sp[0] = whatever we got passed in r12 + */ + +#include + + .text + .global _start + .type _start, @function +_start: + /* Clear the frame pointer and link register since this is the outermost frame. */ + mov r7, 0 + mov lr, 0 + + ld.w r11, sp++ /* argc */ + mov r10, sp /* &argv[0] */ + + st.w --sp, r10 /* stack_end */ + st.w --sp, r12 /* rtld_fini */ + +#ifdef __PIC__ + lddpc r6, .L_GOT +.L_RGOT: + rsub r6, pc + lda.w r9, _init + lda.w r8, _fini + lda.w r12, main + + /* Ok, now run uClibc's main() -- should not return */ + call __uClibc_main + + .align 2 +.L_GOT: + .long .L_RGOT - _GLOBAL_OFFSET_TABLE_ +#else + lddpc r9, __init_addr /* app_init */ + lddpc r8, __fini_addr /* app_fini */ + lddpc r12, __main_addr /* main */ + + /* Ok, now run uClibc's main() -- should not return */ + lddpc pc, ___uClibc_main_addr + + .align 2 +__init_addr: + .long _init +__fini_addr: + .long _fini +__main_addr: + .long main +___uClibc_main_addr: + .long __uClibc_main +#endif + .size _start, . - _start + + /* + * The LSB says we need this. + */ + .section ".note.ABI-tag", "a" + .align 4 + .long 2f - 1f /* namesz */ + .long 4f - 3f /* descsz */ + .long 1 /* type */ +1: .asciz "GNU" /* name */ +2: .align 4 +3: .long 0 /* Linux executable */ + .long 2,6,0 /* Earliest compatible kernel */ +4: .align 4 diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/crti.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/crti.S new file mode 100644 index 00000000..660f47c4 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/crti.S @@ -0,0 +1,26 @@ + + .section .init + .align 2 + .global _init + .type _init, @function +_init: + stm --sp, r6, lr + lddpc r6, 2f +1: rsub r6, pc + rjmp 3f + .align 2 +2: .long 1b - _GLOBAL_OFFSET_TABLE_ +3: + + .section .fini + .align 2 + .global _fini + .type _fini, @function +_fini: + stm --sp, r6, lr + lddpc r6, 2f +1: rsub r6, pc + rjmp 3f + .align 2 +2: .long 1b - _GLOBAL_OFFSET_TABLE_ +3: diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/crtn.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/crtn.S new file mode 100644 index 00000000..c37f7d20 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/crtn.S @@ -0,0 +1,12 @@ + + .section .init + .align 2 + .global _init + .type _init, @function + ldm sp++, r6, pc + + .section .fini + .align 2 + .global _fini + .type _fini, @function + ldm sp++, r6, pc diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/mmap.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/mmap.c new file mode 100644 index 00000000..dee88aaf --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/mmap.c @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2004-2007 Atmel Corporation + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License. See the file "COPYING.LIB" in the main directory of this + * archive for more details. + */ + +#include +#include +#include +#include + + +static _syscall6(__ptr_t, mmap2, __ptr_t, addr, size_t, len, int, prot, + int, flags, int, fd, __off_t, pgoff) + +__ptr_t mmap(__ptr_t addr, size_t len, int prot, int flags, int fd, __off_t offset) +{ + unsigned long page_size = sysconf(_SC_PAGESIZE); + unsigned long pgoff; + + if (offset & (page_size - 1)) { + __set_errno(EINVAL); + return MAP_FAILED; + } + + pgoff = (unsigned long)offset >> (31 - __builtin_clz(page_size)); + + return mmap2(addr, len, prot, flags, fd, pgoff); +} +libc_hidden_def(mmap) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/prctl.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/prctl.c new file mode 100644 index 00000000..4e146e35 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/prctl.c @@ -0,0 +1,36 @@ +/* + * prctl syscall for AVR32 Linux. + * + * Copyright (C) 2010 Atmel Corporation + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License. See the file "COPYING.LIB" in the main directory of this + * archive for more details. + */ +#include +#include +#include + +#ifdef __NR_prctl +#define __NR___syscall_prctl __NR_prctl +static inline _syscall5(int, __syscall_prctl, int, option, long, arg2, + long, arg3, long, arg4, long, arg5); + +int prctl(int __option, ...) +{ + long arg2; + long arg3; + long arg4; + long arg5; + va_list ap; + + va_start(ap, __option); + arg2 = va_arg(ap, long); + arg3 = va_arg(ap, long); + arg4 = va_arg(ap, long); + arg5 = va_arg(ap, long); + va_end(ap); + + return INLINE_SYSCALL(prctl, 5, __option, arg2, arg3, arg4, arg5); +} +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/setjmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/setjmp.S new file mode 100644 index 00000000..7d0354be --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/setjmp.S @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2004-2007 Atmel Corporation + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License. See the file "COPYING.LIB" in the main directory of this + * archive for more details. + */ +#define _SETJMP_H +#define _ASM +#include + + .text + + .global __sigsetjmp + .type __sigsetjmp,"function" + + .align 1 +__sigsetjmp: + mustr r8 + stm r12, r0,r1,r2,r3,r4,r5,r6,r7,r8,sp,lr + + /* + * Make a tail call to __sigjmp_save; it takes the same args + * and is hidden so we don't need to mess around with the GOT. + */ + rjmp __sigjmp_save + .size __sigsetjmp, . - __sigsetjmp + +libc_hidden_def(__sigsetjmp) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/sigaction.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/sigaction.c new file mode 100644 index 00000000..61530912 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/sigaction.c @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2004-2007 Atmel Corporation + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License. See the file "COPYING.LIB" in the main directory of this + * archive for more details. + */ +#include +#include +#include +#include +#include + +#define SA_RESTORER 0x04000000 +extern void __default_rt_sa_restorer(void); + +extern __typeof(sigaction) __libc_sigaction; + +/* + * If act is not NULL, change the action for sig to *act. + * If oact is not NULL, put the old action for sig in *oact. + */ +int __libc_sigaction(int sig, const struct sigaction *act, + struct sigaction *oact) +{ + struct sigaction kact; + + if (act && !(act->sa_flags & SA_RESTORER)) { + memcpy(&kact, act, sizeof(kact)); + kact.sa_restorer = __default_rt_sa_restorer; + kact.sa_flags |= SA_RESTORER; + act = &kact; + } + + /* NB: kernel (as of 2.6.25) will return EINVAL + * if sizeof(act->sa_mask) does not match kernel's sizeof(sigset_t) */ + return __syscall_rt_sigaction(sig, act, oact, sizeof(act->sa_mask)); +} + +#ifndef LIBC_SIGACTION +weak_alias(__libc_sigaction, sigaction) +libc_hidden_weak(sigaction) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/sigrestorer.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/sigrestorer.S new file mode 100644 index 00000000..df6a1ba3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/sigrestorer.S @@ -0,0 +1,15 @@ +/* + * Copyright (C) 2004 Atmel Corporation + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License. See the file "COPYING.LIB" in the main directory of this + * archive for more details. + */ +#include + + .global __default_rt_sa_restorer + .type __default_rt_sa_restorer,"function" + .align 1 +__default_rt_sa_restorer: + mov r8, __NR_rt_sigreturn + scall diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/sys/elf.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/sys/elf.h new file mode 100644 index 00000000..faa73106 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/sys/elf.h @@ -0,0 +1,26 @@ +/* Copyright (C) 1996, 1997, 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_ELF_H +#define _SYS_ELF_H 1 + +#warning "This header is obsolete; use instead." + +#include + +#endif /* sys/elf.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/sys/procfs.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/sys/procfs.h new file mode 100644 index 00000000..3b373632 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/sys/procfs.h @@ -0,0 +1,123 @@ +/* Copyright (C) 1996, 1997, 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_PROCFS_H +#define _SYS_PROCFS_H 1 + +/* This is somewhat modelled after the file of the same name on SVR4 + systems. It provides a definition of the core file format for ELF + used on Linux. It doesn't have anything to do with the /proc file + system, even though Linux has one. + + Anyway, the whole purpose of this file is for GDB and GDB only. + Don't read too much into it. Don't use it for anything other than + GDB unless you know what you are doing. */ + +#include +#include +#include +#include + +__BEGIN_DECLS + +/* Type for a general-purpose register. */ +typedef unsigned long elf_greg_t; + +/* And the whole bunch of them. We could have used `struct + user_regs' directly in the typedef, but tradition says that + the register set is an array, which does have some peculiar + semantics, so leave it that way. */ +#define ELF_NGREG (sizeof (struct user_regs) / sizeof(elf_greg_t)) +typedef elf_greg_t elf_gregset_t[ELF_NGREG]; + +/* Register set for the floating-point registers. */ +typedef struct user_fpregs elf_fpregset_t; + +/* Signal info. */ +struct elf_siginfo + { + int si_signo; /* Signal number. */ + int si_code; /* Extra code. */ + int si_errno; /* Errno. */ + }; + +/* Definitions to generate Intel SVR4-like core files. These mostly + have the same names as the SVR4 types with "elf_" tacked on the + front to prevent clashes with Linux definitions, and the typedef + forms have been avoided. This is mostly like the SVR4 structure, + but more Linuxy, with things that Linux does not support and which + GDB doesn't really use excluded. */ + +struct elf_prstatus + { + struct elf_siginfo pr_info; /* Info associated with signal. */ + short int pr_cursig; /* Current signal. */ + unsigned long int pr_sigpend; /* Set of pending signals. */ + unsigned long int pr_sighold; /* Set of held signals. */ + __pid_t pr_pid; + __pid_t pr_ppid; + __pid_t pr_pgrp; + __pid_t pr_sid; + struct timeval pr_utime; /* User time. */ + struct timeval pr_stime; /* System time. */ + struct timeval pr_cutime; /* Cumulative user time. */ + struct timeval pr_cstime; /* Cumulative system time. */ + elf_gregset_t pr_reg; /* GP registers. */ + int pr_fpvalid; /* True if math copro being used. */ + }; + + +#define ELF_PRARGSZ (80) /* Number of chars for args. */ + +struct elf_prpsinfo + { + char pr_state; /* Numeric process state. */ + char pr_sname; /* Char for pr_state. */ + char pr_zomb; /* Zombie. */ + char pr_nice; /* Nice val. */ + unsigned long int pr_flag; /* Flags. */ + unsigned short int pr_uid; + unsigned short int pr_gid; + int pr_pid, pr_ppid, pr_pgrp, pr_sid; + /* Lots missing */ + char pr_fname[16]; /* Filename of executable. */ + char pr_psargs[ELF_PRARGSZ]; /* Initial part of arg list. */ + }; + +/* The rest of this file provides the types for emulation of the + Solaris interfaces that should be implemented by + users of libthread_db. */ + +/* Addresses. */ +typedef void *psaddr_t; + +/* Register sets. Linux has different names. */ +typedef elf_gregset_t prgregset_t; +typedef elf_fpregset_t prfpregset_t; + +/* We don't have any differences between processes and threads, + therefore have only one PID type. */ +typedef __pid_t lwpid_t; + +/* Process status and info. In the end we do provide typedefs for them. */ +typedef struct elf_prstatus prstatus_t; +typedef struct elf_prpsinfo prpsinfo_t; + +__END_DECLS + +#endif /* sys/procfs.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/sys/ucontext.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/sys/ucontext.h new file mode 100644 index 00000000..82c7fe24 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/sys/ucontext.h @@ -0,0 +1,90 @@ +/* Copyright (C) 1998, 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Linux/AVR32 ABI compliant context switching support. */ + +#ifndef _SYS_UCONTEXT_H +#define _SYS_UCONTEXT_H 1 + +#include +#include +#include +#include + +typedef int greg_t; + +/* Number of general registers. */ +#define NGREG 16 + +/* Container for all general registers. */ +typedef elf_gregset_t gregset_t; + +/* Number of each register is the `gregset_t' array. */ +enum +{ + R0 = 0, +#define R0 R0 + R1 = 1, +#define R1 R1 + R2 = 2, +#define R2 R2 + R3 = 3, +#define R3 R3 + R4 = 4, +#define R4 R4 + R5 = 5, +#define R5 R5 + R6 = 6, +#define R6 R6 + R7 = 7, +#define R7 R7 + R8 = 8, +#define R8 R8 + R9 = 9, +#define R9 R9 + R10 = 10, +#define R10 R10 + R11 = 11, +#define R11 R11 + R12 = 12, +#define R12 R12 + R13 = 13, +#define R13 R13 + R14 = 14, +#define R14 R14 + R15 = 15 +#define R15 R15 +}; + +/* Structure to describe FPU registers. */ +typedef elf_fpregset_t fpregset_t; + +/* Context to describe whole processor state. */ +typedef struct sigcontext mcontext_t; + +/* Userlevel context. */ +typedef struct ucontext +{ + unsigned long uc_flags; + struct ucontext *uc_link; + stack_t uc_stack; + mcontext_t uc_mcontext; + sigset_t uc_sigmask; /* mask last for extensibility */ +} ucontext_t; + +#endif /* sys/ucontext.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/sys/user.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/sys/user.h new file mode 100644 index 00000000..c0b3d384 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/sys/user.h @@ -0,0 +1,46 @@ +#ifndef _SYS_USER_H +#define _SYS_USER_H + +struct user_fpregs +{ + +}; + +struct user_regs +{ + unsigned long sr; + unsigned long pc; + unsigned long lr; + unsigned long sp; + unsigned long r12; + unsigned long r11; + unsigned long r10; + unsigned long r9; + unsigned long r8; + unsigned long r7; + unsigned long r6; + unsigned long r5; + unsigned long r4; + unsigned long r3; + unsigned long r2; + unsigned long r1; + unsigned long r0; + unsigned long r12_orig; +}; + +struct user +{ + struct user_regs regs; /* general registers */ + size_t u_tsize; /* text size (pages) */ + size_t u_dsize; /* data size (pages) */ + size_t u_ssize; /* stack size (pages) */ + unsigned long start_code; /* text starting address */ + unsigned long start_data; /* data starting address */ + unsigned long start_stack; /* stack starting address */ + long int signal; /* signal causing core dump */ + struct user_regs * u_ar0; /* help gdb find registers */ + unsigned long magic; /* identifies a core file */ + char u_comm[32]; /* user command name */ +}; + +#endif /* _SYS_USER_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/syscall.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/syscall.S new file mode 100644 index 00000000..55c1b1fa --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/syscall.S @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2004-2007 Atmel Corporation + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License. See the file "COPYING.LIB" in the main directory of this + * archive for more details. + */ +#include + + .text + + /* + * long int syscall(long int sysno, ...) + */ + .global syscall + .type syscall, @function + .align 2 +syscall: + stm --sp, r3,r5,r6,lr + sub lr, sp, -16 + mov r8, r12 + ldm lr, r3,r5,r9-r12 + scall + cp.w r12, -4095 + brlo .Ldone + +#ifdef __PIC__ + lddpc r6, .Lgot +.Lgotcalc: + rsub r6, pc +# ifdef __UCLIBC_HAS_THREADS__ + rsub r3, r12, 0 + mcall r6[__errno_location@got] + st.w r12[0], r3 +# else + ld.w r3, r6[errno@got] + neg r12 + st.w r3[0], r12 +# endif +#else +# ifdef __UCLIBC_HAS_THREADS__ + rsub r3, r12, 0 + mcall .Lerrno_location + st.w r12[0], r3 +# else + lddpc r3, .Lerrno + neg r12 + st.w r3[0], r12 +# endif +#endif + mov r12, -1 + +.Ldone: + ldm sp++, r3,r5,r6,pc + + .align 2 +#ifdef __PIC__ +.Lgot: + .long .Lgotcalc - _GLOBAL_OFFSET_TABLE_ +#else +# ifdef __UCLIBC_HAS_THREADS__ +.Lerrno_location: + .long __errno_location +# else +.Lerrno: + .long errno +# endif +#endif + + + .size syscall, . - syscall diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/vfork.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/vfork.S new file mode 100644 index 00000000..03ca99f6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/avr32/vfork.S @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2005 Atmel Corporation + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License. See the file "COPYING.LIB" in the main directory of this + * archive for more details. + */ + +/* + * Clone the process without copying the address space. The + * calling process is suspended until the child either exits + * or calls execve. + * + * This all means that we cannot rely on the stack to store + * away registers, since they will be overwritten by the child + * as soon as it makes another function call (e.g. execve()). + * Fortunately, the Linux kernel preserves LR across system calls. + */ + +#include +#include + + .global __vfork + .type __vfork,@function + .align 1 +__vfork: + mov r8, __NR_vfork + scall + cp.w r12, -4096 + retls r12 + + /* vfork failed, so we may use the stack freely */ + pushm r4-r7,lr +#ifdef __PIC__ + lddpc r6, .L_GOT + rsub r4, r12, 0 +.L_RGOT: + rsub r6, pc + mcall r6[__errno_location@got] +#else + rsub r4, r12, 0 + mcall .L__errno_location +#endif + st.w r12[0], r4 + popm r4-r7,pc,r12=-1 + + .align 2 +#ifdef __PIC__ +.L_GOT: + .long .L_RGOT - _GLOBAL_OFFSET_TABLE_ +#else +.L__errno_location: + .long __errno_location +#endif + .size __vfork, . - __vfork + +weak_alias(__vfork,vfork) +libc_hidden_weak(vfork) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/Makefile new file mode 100644 index 00000000..3970f626 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2006 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../../ +top_builddir=../../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.arch +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/Makefile.arch b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/Makefile.arch new file mode 100644 index 00000000..24270375 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/Makefile.arch @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2006 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +CSRC := bsdsetjmp.c clone.c \ + sram-alloc.c sram-free.c dma-memcpy.c + +SSRC := __longjmp.S setjmp.S bsd-_setjmp.S + +ARCH_HEADERS := bfin_fixed_code.h bfin_l1layout.h bfin_sram.h diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/__longjmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/__longjmp.S new file mode 100644 index 00000000..673cd30e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/__longjmp.S @@ -0,0 +1,107 @@ +/* longjmp for the Blackfin project + * + * Copyright (C) 2000-2006 Erik Andersen + * Copyright (C) 2004 Metrowerks + * Based on code from Analog Devices. + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +.text +.global ___longjmp; +.type ___longjmp,STT_FUNC; +.align 4; + +___longjmp: + P0 = R0; + R0 = [P0 + 0x00]; + [--SP] = R0; /* Put P0 on the stack */ + + P1 = [P0 + 0x04]; + P2 = [P0 + 0x08]; + P3 = [P0 + 0x0C]; + P4 = [P0 + 0x10]; + P5 = [P0 + 0x14]; + + FP = [P0 + 0x18]; + R0 = [SP++]; /* Grab P0 from old stack */ + SP = [P0 + 0x1C]; /* Update Stack Pointer */ + [--SP] = R0; /* Put P0 on new stack */ + [--SP] = R1; /* Put VAL arg on new stack */ + + R0 = [P0 + 0x20]; /* Data Registers */ + R1 = [P0 + 0x24]; + R2 = [P0 + 0x28]; + R3 = [P0 + 0x2C]; + R4 = [P0 + 0x30]; + R5 = [P0 + 0x34]; + R6 = [P0 + 0x38]; + R7 = [P0 + 0x3C]; + + R0 = [P0 + 0x40]; + ASTAT = R0; + + R0 = [P0 + 0x44]; /* Loop Counters */ + LC0 = R0; + R0 = [P0 + 0x48]; + LC1 = R0; + + R0 = [P0 + 0x4C]; /* Accumulators */ + A0.W = R0; + R0 = [P0 + 0x50]; + A0.X = R0; + R0 = [P0 + 0x54]; + A1.W = R0; + R0 = [P0 + 0x58]; + A1.X = R0; + + R0 = [P0 + 0x5C]; /* Index Registers */ + I0 = R0; + R0 = [P0 + 0x60]; + I1 = R0; + R0 = [P0 + 0x64]; + I2 = R0; + R0 = [P0 + 0x68]; + I3 = R0; + + R0 = [P0 + 0x6C]; /* Modifier Registers */ + M0 = R0; + R0 = [P0 + 0x70]; + M1 = R0; + R0 = [P0 + 0x74]; + M2 = R0; + R0 = [P0 + 0x78]; + M3 = R0; + + R0 = [P0 + 0x7C]; /* Length Registers */ + L0 = R0; + R0 = [P0 + 0x80]; + L1 = R0; + R0 = [P0 + 0x84]; + L2 = R0; + R0 = [P0 + 0x88]; + L3 = R0; + + R0 = [P0 + 0x8C]; /* Base Registers */ + B0 = R0; + R0 = [P0 + 0x90]; + B1 = R0; + R0 = [P0 + 0x94]; + B2 = R0; + R0 = [P0 + 0x98]; + B3 = R0; + + R0 = [P0 + 0x9C]; /* Return Address (PC) */ + RETS = R0; + + R0 = [SP++]; + P0 = [SP++]; + + CC = R0 == 0; + IF !CC JUMP .Lfinished; + R0 = 1; +.Lfinished: + RTS; +.size ___longjmp,.-___longjmp + +libc_hidden_def(__longjmp) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/bfin_fixed_code.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/bfin_fixed_code.h new file mode 100644 index 00000000..91425715 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/bfin_fixed_code.h @@ -0,0 +1,155 @@ +/* Atomic instructions for userspace. + * + * The actual implementations can be found in the kernel. + * + * Copyright (c) 2008 Analog Devices, Inc. + * + * Licensed under the LGPL v2.1. + */ + +#ifndef __BFIN_FIXED_CODE_H__ +#define __BFIN_FIXED_CODE_H__ + +#include + +#include + +#ifndef __ASSEMBLY__ + +static inline +uint32_t bfin_atomic_xchg32(uint32_t *__bfin_ptr, uint32_t __bfin_newval) +{ + uint32_t __bfin_ret; + /* Input: P0: memory address to use + * R1: value to store + * Output: R0: old contents of the memory address + */ + __asm__ __volatile__( + "CALL (%[__bfin_func])" + : "=q0" (__bfin_ret), "=m" (*__bfin_ptr) + : [__bfin_func] "a" (ATOMIC_XCHG32), "q1" (__bfin_newval), + "qA" (__bfin_ptr), "m" (*__bfin_ptr) + : "RETS", "memory" + ); + return __bfin_ret; +} + +static inline +uint32_t bfin_atomic_cas32(uint32_t *__bfin_ptr, uint32_t __bfin_exp, uint32_t __bfin_newval) +{ + uint32_t __bfin_ret; + /* Input: P0: memory address to use + * R1: compare value + * R2: new value to store + * Output: R0: old contents of the memory address + */ + __asm__ __volatile__( + "CALL (%[__bfin_func])" + : "=q0" (__bfin_ret), "=m" (*__bfin_ptr) + : [__bfin_func] "a" (ATOMIC_CAS32), "q1" (__bfin_exp), "q2" (__bfin_newval), + "qA" (__bfin_ptr), "m" (*__bfin_ptr) + : "RETS", "memory" + ); + return __bfin_ret; +} + +static inline +uint32_t bfin_atomic_add32(uint32_t *__bfin_ptr, uint32_t __bfin_inc) +{ + uint32_t __bfin_ret; + /* Input: P0: memory address to use + * R0: value to add + * Output: R0: new contents of the memory address + * R1: previous contents of the memory address + */ + __asm__ __volatile__( + "CALL (%[__bfin_func])" + : "=q0" (__bfin_ret), "=m" (*__bfin_ptr) + : [__bfin_func] "a" (ATOMIC_ADD32), "q0" (__bfin_inc), + "qA" (__bfin_ptr), "m" (*__bfin_ptr) + : "R1", "RETS", "memory" + ); + return __bfin_ret; +} +#define bfin_atomic_inc32(ptr) bfin_atomic_add32(ptr, 1) + +static inline +uint32_t bfin_atomic_sub32(uint32_t *__bfin_ptr, uint32_t __bfin_dec) +{ + uint32_t __bfin_ret; + /* Input: P0: memory address to use + * R0: value to subtract + * Output: R0: new contents of the memory address + * R1: previous contents of the memory address + */ + __asm__ __volatile__( + "CALL (%[__bfin_func])" + : "=q0" (__bfin_ret), "=m" (*__bfin_ptr) + : [__bfin_func] "a" (ATOMIC_SUB32), "q0" (__bfin_dec), + "qA" (__bfin_ptr), "m" (*__bfin_ptr) + : "R1", "RETS", "memory" + ); + return __bfin_ret; +} +#define bfin_atomic_dec32(ptr) bfin_atomic_sub32(ptr, 1) + +static inline +uint32_t bfin_atomic_ior32(uint32_t *__bfin_ptr, uint32_t __bfin_ior) +{ + uint32_t __bfin_ret; + /* Input: P0: memory address to use + * R0: value to ior + * Output: R0: new contents of the memory address + * R1: previous contents of the memory address + */ + __asm__ __volatile__( + "CALL (%[__bfin_func])" + : "=q0" (__bfin_ret), "=m" (*__bfin_ptr) + : [__bfin_func] "a" (ATOMIC_IOR32), "q0" (__bfin_ior), + "qA" (__bfin_ptr), "m" (*__bfin_ptr) + : "R1", "RETS", "memory" + ); + return __bfin_ret; +} + +static inline +uint32_t bfin_atomic_and32(uint32_t *__bfin_ptr, uint32_t __bfin_and) +{ + uint32_t __bfin_ret; + /* Input: P0: memory address to use + * R0: value to and + * Output: R0: new contents of the memory address + * R1: previous contents of the memory address + */ + __asm__ __volatile__( + "CALL (%[__bfin_func])" + : "=q0" (__bfin_ret), "=m" (*__bfin_ptr) + : [__bfin_func] "a" (ATOMIC_AND32), "q0" (__bfin_and), + "qA" (__bfin_ptr), "m" (*__bfin_ptr) + : "R1", "RETS", "memory" + ); + return __bfin_ret; +} + +static inline +uint32_t bfin_atomic_xor32(uint32_t *__bfin_ptr, uint32_t __bfin_xor) +{ + uint32_t __bfin_ret; + /* Input: P0: memory address to use + * R0: value to xor + * Output: R0: new contents of the memory address + * R1: previous contents of the memory address + */ + __asm__ __volatile__( + "CALL (%[__bfin_func])" + : "=q0" (__bfin_ret), "=m" (*__bfin_ptr) + : [__bfin_func] "a" (ATOMIC_XOR32), "q0" (__bfin_xor), + "qA" (__bfin_ptr), "m" (*__bfin_ptr) + : "R1", "RETS", "memory" + ); + return __bfin_ret; +} + +#endif + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/bfin_l1layout.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/bfin_l1layout.h new file mode 100644 index 00000000..00efd235 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/bfin_l1layout.h @@ -0,0 +1,17 @@ +#define L1_SCRATCH_START 0xFFB00000 + +/* Data that is "mapped" into the process VM at the start of the L1 scratch + memory, so that each process can access it at a fixed address. Used for + stack checking. */ +struct l1_scratch_task_info +{ + /* Points to the start of the stack. */ + void *stack_start; + /* Not updated by the kernel; a user process can modify this to + keep track of the lowest address of the stack pointer during its + runtime. */ + void *lowest_sp; +}; + +/* A pointer to the structure in memory. */ +#define L1_SCRATCH_TASK_INFO ((struct l1_scratch_task_info *)L1_SCRATCH_START) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/bfin_sram.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/bfin_sram.h new file mode 100644 index 00000000..278514d5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/bfin_sram.h @@ -0,0 +1,31 @@ +/* + * bfin_sram.h - userspace interface to L1 memory allocator + * + * Copyright (c) 2007 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#ifndef __BFIN_SRAM_H__ +#define __BFIN_SRAM_H__ + +#include +#include + +__BEGIN_DECLS + +#define L1_INST_SRAM 0x00000001 +#define L1_DATA_A_SRAM 0x00000002 +#define L1_DATA_B_SRAM 0x00000004 +#define L1_DATA_SRAM 0x00000006 +#define L2_SRAM 0x00000008 + +extern void *sram_alloc(size_t size, unsigned long flags) + __attribute_malloc__ __attribute_warn_unused_result__; +extern int sram_free(const void *addr); +extern void *dma_memcpy(void *dest, const void *src, size_t len) + __nonnull((1, 2)); + +__END_DECLS + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/bits/byteswap.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/bits/byteswap.h new file mode 100644 index 00000000..a7270025 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/bits/byteswap.h @@ -0,0 +1,34 @@ +/* File: libc/sysdeps/linux/bfin/bits/byteswap.h + * + * Copyright 2004-2006 Analog Devices Inc. + * + * Enter bugs at http://blackfin.uclinux.org/ + * + * Licensed under the GPL-2 or later. + */ + +#ifndef _ASM_BITS_BYTESWAP_H +#define _ASM_BITS_BYTESWAP_H 1 + +#define __bswap_non_constant_16(x) \ + (__extension__ \ + ({ register unsigned short int __v; \ + __asm__ ("%0 = PACK (%1.L, %1.L);" \ + "%0 >>= 8;" \ + : "=d" (__v) \ + : "d" (x)); \ + __v; })) + +#define __bswap_non_constant_32(x) \ + (__extension__ \ + ({ register unsigned int __v; \ + __asm__ ("%1 = %0 >> 8 (V);" \ + "%0 = %0 << 8 (V);" \ + "%0 = %0 | %1;" \ + "%1 = PACK(%0.L, %0.H);" \ + : "+d"(x), "=&d"(__v)); \ + __v; })) + +#endif + +#include diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/bits/elf-fdpic.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/bits/elf-fdpic.h new file mode 100644 index 00000000..b7e87b8e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/bits/elf-fdpic.h @@ -0,0 +1,115 @@ +/* Copyright 2003, 2004 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation; either version 2.1 of the +License, or (at your option) any later version. + +In addition to the permissions in the GNU Lesser General Public +License, the Free Software Foundation gives you unlimited +permission to link the compiled version of this file with other +programs, and to distribute those programs without any restriction +coming from the use of this file. (The GNU Lesser General Public +License restrictions do apply in other respects; for example, they +cover modification of the file, and distribution when not linked +into another program.) + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#ifndef _BITS_ELF_FDPIC_H +#define _BITS_ELF_FDPIC_H + +/* These data structures are described in the FDPIC ABI extension. + The kernel passes a process a memory map, such that for every LOAD + segment there is an elf32_fdpic_loadseg entry. A pointer to an + elf32_fdpic_loadmap is passed in GR8 at start-up, and a pointer to + an additional such map is passed in GR9 for the interpreter, when + there is one. */ + +#include + +/* This data structure represents a PT_LOAD segment. */ +struct elf32_fdpic_loadseg +{ + /* Core address to which the segment is mapped. */ + Elf32_Addr addr; + /* VMA recorded in the program header. */ + Elf32_Addr p_vaddr; + /* Size of this segment in memory. */ + Elf32_Word p_memsz; +}; + +struct elf32_fdpic_loadmap { + /* Protocol version number, must be zero. */ + Elf32_Half version; + /* Number of segments in this map. */ + Elf32_Half nsegs; + /* The actual memory map. */ + struct elf32_fdpic_loadseg segs[/*nsegs*/]; +}; + +struct elf32_fdpic_loadaddr { + struct elf32_fdpic_loadmap *map; + void *got_value; +}; + +/* Map a pointer's VMA to its corresponding address according to the + load map. */ +static __always_inline void * +__reloc_pointer (void *p, + const struct elf32_fdpic_loadmap *map) +{ + int c; + +#if 0 + if (map->version != 0) + /* Crash. */ + ((void(*)())0)(); +#endif + + /* No special provision is made for NULL. We don't want NULL + addresses to go through relocation, so they shouldn't be in + .rofixup sections, and, if they're present in dynamic + relocations, they shall be mapped to the NULL address without + undergoing relocations. */ + + for (c = 0; + /* Take advantage of the fact that the loadmap is ordered by + virtual addresses. In general there will only be 2 entries, + so it's not profitable to do a binary search. */ + c < map->nsegs && p >= (void*)map->segs[c].p_vaddr; + c++) + { + /* This should be computed as part of the pointer comparison + above, but we want to use the carry in the comparison, so we + can't convert it to an integer type beforehand. */ + unsigned long offset = p - (void*)map->segs[c].p_vaddr; + /* We only check for one-past-the-end for the last segment, + assumed to be the data segment, because other cases are + ambiguous in the absence of padding between segments, and + rofixup already serves as padding between text and data. + Unfortunately, unless we special-case the last segment, we + fail to relocate the _end symbol. */ + if (offset < map->segs[c].p_memsz + || (offset == map->segs[c].p_memsz && c + 1 == map->nsegs)) + return (char*)map->segs[c].addr + offset; + } + + /* We might want to crash instead. */ + return (void*)-1; +} + +# define __RELOC_POINTER(ptr, loadaddr) \ + (__reloc_pointer ((void*)(ptr), \ + (loadaddr).map)) + +#endif /* _BITS_ELF_FDPIC_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/bits/endian.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/bits/endian.h new file mode 100644 index 00000000..8a36cf70 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/bits/endian.h @@ -0,0 +1,7 @@ +/* Blackfin is Little-endian. */ + +#ifndef _ENDIAN_H +# error "Never use directly; include instead." +#endif + +#define __BYTE_ORDER __LITTLE_ENDIAN diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/bits/fcntl.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/bits/fcntl.h new file mode 100644 index 00000000..f019b71d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/bits/fcntl.h @@ -0,0 +1,238 @@ +/* O_*, F_*, FD_* bit values for Linux. + Copyright (C) 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FCNTL_H +# error "Never use directly; include instead." +#endif + + +#include +#ifdef __USE_GNU +# include +#endif + +/* open/fcntl - O_SYNC is only implemented on blocks devices and on files + located on an ext2 file system */ +#define O_ACCMODE 0003 +#define O_RDONLY 00 +#define O_WRONLY 01 +#define O_RDWR 02 +#define O_CREAT 0100 /* not fcntl */ +#define O_EXCL 0200 /* not fcntl */ +#define O_NOCTTY 0400 /* not fcntl */ +#define O_TRUNC 01000 /* not fcntl */ +#define O_APPEND 02000 +#define O_NONBLOCK 04000 +#define O_NDELAY O_NONBLOCK +#define O_SYNC 010000 +#define O_FSYNC O_SYNC +#define O_ASYNC 020000 + +#ifdef __USE_GNU +# define O_DIRECTORY 040000 /* Must be a directory. */ +# define O_NOFOLLOW 0100000 /* Do not follow links. */ +# define O_DIRECT 0200000 /* Direct disk access. */ +# define O_NOATIME 01000000 /* don't set atime */ +# define O_CLOEXEC 02000000 /* set close_on_exec */ +#endif + +/* For now Linux has synchronisity options for data and read operations. + We define the symbols here but let them do the same as O_SYNC since + this is a superset. */ +#if defined __USE_POSIX199309 || defined __USE_UNIX98 +# define O_DSYNC O_SYNC /* Synchronize data. */ +# define O_RSYNC O_SYNC /* Synchronize read operations. */ +#endif + +#ifdef __USE_LARGEFILE64 +# define O_LARGEFILE 0400000 +#endif + +/* Values for the second argument to `fcntl'. */ +#define F_DUPFD 0 /* Duplicate file descriptor. */ +#define F_GETFD 1 /* Get file descriptor flags. */ +#define F_SETFD 2 /* Set file descriptor flags. */ +#define F_GETFL 3 /* Get file status flags. */ +#define F_SETFL 4 /* Set file status flags. */ +#ifndef __USE_FILE_OFFSET64 +# define F_GETLK 5 /* Get record locking info. */ +# define F_SETLK 6 /* Set record locking info (non-blocking). */ +# define F_SETLKW 7 /* Set record locking info (blocking). */ +#else +# define F_GETLK F_GETLK64 /* Get record locking info. */ +# define F_SETLK F_SETLK64 /* Set record locking info (non-blocking).*/ +# define F_SETLKW F_SETLKW64 /* Set record locking info (blocking). */ +#endif +#define F_GETLK64 12 /* Get record locking info. */ +#define F_SETLK64 13 /* Set record locking info (non-blocking). */ +#define F_SETLKW64 14 /* Set record locking info (blocking). */ + +#if defined __USE_BSD || defined __USE_XOPEN2K +# define F_SETOWN 8 /* Get owner of socket (receiver of SIGIO). */ +# define F_GETOWN 9 /* Set owner of socket (receiver of SIGIO). */ +#endif + +#ifdef __USE_GNU +# define F_SETSIG 10 /* Set number of signal to be sent. */ +# define F_GETSIG 11 /* Get number of signal to be sent. */ +#endif + +#ifdef __USE_GNU +# define F_SETLEASE 1024 /* Set a lease. */ +# define F_GETLEASE 1025 /* Enquire what lease is active. */ +# define F_NOTIFY 1026 /* Request notfications on a directory. */ +# define F_DUPFD_CLOEXEC 1030 /* Duplicate file descriptor with + close-on-exit set on new fd. */ +#endif + +/* For F_[GET|SET]FL. */ +#define FD_CLOEXEC 1 /* actually anything with low bit set goes */ + +/* For posix fcntl() and `l_type' field of a `struct flock' for lockf(). */ +#define F_RDLCK 0 /* Read lock. */ +#define F_WRLCK 1 /* Write lock. */ +#define F_UNLCK 2 /* Remove lock. */ + +/* For old implementation of bsd flock(). */ +#define F_EXLCK 4 /* or 3 */ +#define F_SHLCK 8 /* or 4 */ + +#ifdef __USE_BSD +/* Operations for bsd flock(), also used by the kernel implementation. */ +# define LOCK_SH 1 /* shared lock */ +# define LOCK_EX 2 /* exclusive lock */ +# define LOCK_NB 4 /* or'd with one of the above to prevent + blocking */ +# define LOCK_UN 8 /* remove lock */ +#endif + +#ifdef __USE_GNU +# define LOCK_MAND 32 /* This is a mandatory flock: */ +# define LOCK_READ 64 /* ... which allows concurrent read operations. */ +# define LOCK_WRITE 128 /* ... which allows concurrent write operations. */ +# define LOCK_RW 192 /* ... Which allows concurrent read & write operations. */ +#endif + +#ifdef __USE_GNU +/* Types of directory notifications that may be requested with F_NOTIFY. */ +# define DN_ACCESS 0x00000001 /* File accessed. */ +# define DN_MODIFY 0x00000002 /* File modified. */ +# define DN_CREATE 0x00000004 /* File created. */ +# define DN_DELETE 0x00000008 /* File removed. */ +# define DN_RENAME 0x00000010 /* File renamed. */ +# define DN_ATTRIB 0x00000020 /* File changed attibutes. */ +# define DN_MULTISHOT 0x80000000 /* Don't remove notifier. */ +#endif + +struct flock + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ +#ifndef __USE_FILE_OFFSET64 + __off_t l_start; /* Offset where the lock begins. */ + __off_t l_len; /* Size of the locked area; zero means until EOF. */ +#else + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ +#endif + __pid_t l_pid; /* Process holding the lock. */ + }; + +#ifdef __USE_LARGEFILE64 +struct flock64 + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ + __pid_t l_pid; /* Process holding the lock. */ + }; +#endif + +/* Define some more compatibility macros to be backward compatible with + BSD systems which did not managed to hide these kernel macros. */ +#ifdef __USE_BSD +# define FAPPEND O_APPEND +# define FFSYNC O_FSYNC +# define FASYNC O_ASYNC +# define FNONBLOCK O_NONBLOCK +# define FNDELAY O_NDELAY +#endif /* Use BSD. */ + +/* Advise to `posix_fadvise'. */ +#ifdef __USE_XOPEN2K +# define POSIX_FADV_NORMAL 0 /* No further special treatment. */ +# define POSIX_FADV_RANDOM 1 /* Expect random page references. */ +# define POSIX_FADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define POSIX_FADV_WILLNEED 3 /* Will need these pages. */ +# define POSIX_FADV_DONTNEED 4 /* Don't need these pages. */ +# define POSIX_FADV_NOREUSE 5 /* Data will be accessed once. */ +#endif + + +#if defined __USE_GNU && defined __UCLIBC_LINUX_SPECIFIC__ +/* Flags for SYNC_FILE_RANGE. */ +# define SYNC_FILE_RANGE_WAIT_BEFORE 1 /* Wait upon writeout of all pages + in the range before performing the + write. */ +# define SYNC_FILE_RANGE_WRITE 2 /* Initiate writeout of all those + dirty pages in the range which are + not presently under writeback. */ +# define SYNC_FILE_RANGE_WAIT_AFTER 4 /* Wait upon writeout of all pages in + the range after performing the + write. */ + +/* Flags for SPLICE and VMSPLICE. */ +# define SPLICE_F_MOVE 1 /* Move pages instead of copying. */ +# define SPLICE_F_NONBLOCK 2 /* Don't block on the pipe splicing + (but we may still block on the fd + we splice from/to). */ +# define SPLICE_F_MORE 4 /* Expect more data. */ +# define SPLICE_F_GIFT 8 /* Pages passed in are a gift. */ +#endif + +__BEGIN_DECLS + +#if defined __USE_GNU && defined __UCLIBC_LINUX_SPECIFIC__ + +/* Provide kernel hint to read ahead. */ +extern ssize_t readahead (int __fd, __off64_t __offset, size_t __count) + __THROW; + + +/* Selective file content synch'ing. */ +extern int sync_file_range (int __fd, __off64_t __from, __off64_t __to, + unsigned int __flags); + +/* Splice address range into a pipe. */ +extern ssize_t vmsplice (int __fdout, const struct iovec *__iov, + size_t __count, unsigned int __flags); + +/* Splice two files together. */ +extern ssize_t splice (int __fdin, __off64_t *__offin, int __fdout, + __off64_t *__offout, size_t __len, + unsigned int __flags); + +/* In-kernel implementation of tee for pipe buffers. */ +extern ssize_t tee (int __fdin, int __fdout, size_t __len, + unsigned int __flags); + +#endif +__END_DECLS + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/bits/huge_val.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/bits/huge_val.h new file mode 100644 index 00000000..9c8b7215 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/bits/huge_val.h @@ -0,0 +1,56 @@ +/* `HUGE_VAL' constant for IEEE 754 machines (where it is infinity). + Used by and functions for overflow. + Blackfin version. + Copyright (C) 1992, 95, 96, 97, 98, 99, 2000, 2004 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _MATH_H +# error "Never use directly; include instead." +#endif + +/* IEEE positive infinity (-HUGE_VAL is negative infinity). */ + +#if __GNUC_PREREQ(3,3) +# define HUGE_VAL (__builtin_huge_val()) +#elif __GNUC_PREREQ(2,96) +# define HUGE_VAL (__extension__ 0x1.0p2047) +#elif defined __GNUC__ + +# define HUGE_VAL \ + (__extension__ \ + ((union { unsigned __l __attribute__((__mode__(__DI__))); double __d; }) \ + { __l: 0x000000007ff00000ULL }).__d) + +#else /* not GCC */ + +# include + +typedef union { unsigned char __c[8]; double __d; } __huge_val_t; + +# if __BYTE_ORDER == __BIG_ENDIAN +# define __HUGE_VAL_bytes { 0, 0, 0, 0, 0x7f, 0xf0, 0, 0 } +# endif +# if __BYTE_ORDER == __LITTLE_ENDIAN +# define __HUGE_VAL_bytes { 0, 0, 0xf0, 0x7f, 0, 0, 0, 0 } +# endif + +static __huge_val_t __huge_val = { __HUGE_VAL_bytes }; +# define HUGE_VAL (__huge_val.__d) + +#endif /* GCC. */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/bits/kernel_stat.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/bits/kernel_stat.h new file mode 100644 index 00000000..b1a3251e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/bits/kernel_stat.h @@ -0,0 +1,53 @@ +#ifndef _BITS_STAT_STRUCT_H +#define _BITS_STAT_STRUCT_H + +#ifndef _LIBC +#error bits/kernel_stat.h is for internal uClibc use only! +#endif + +/* This file provides whatever this particular arch's kernel thinks + * struct kernel_stat should look like... It turns out each arch has a + * different opinion on the subject... */ + +struct kernel_stat { + unsigned short st_dev; + unsigned short __pad1; + unsigned long st_ino; + unsigned short st_mode; + unsigned short st_nlink; + unsigned short st_uid; + unsigned short st_gid; + unsigned short st_rdev; + unsigned short __pad2; + unsigned long st_size; + unsigned long st_blksize; + unsigned long st_blocks; + struct timespec st_atim; + struct timespec st_mtim; + struct timespec st_ctim; + unsigned long __unused4; + unsigned long __unused5; +}; + +struct kernel_stat64 { + unsigned short st_dev; + unsigned char __pad0[10]; +#define _HAVE_STAT64___ST_INO + unsigned long __st_ino; + unsigned int st_mode; + unsigned int st_nlink; + unsigned long st_uid; + unsigned long st_gid; + unsigned short st_rdev; + unsigned char __pad3[10]; + long long st_size; + unsigned long st_blksize; + unsigned long st_blocks; /* Number 512-byte blocks allocated. */ + unsigned long __pad4; /* future possible st_blocks high bits */ + struct timespec st_atim; + struct timespec st_mtim; + struct timespec st_ctim; + unsigned long long st_ino; +}; + +#endif /* _BITS_STAT_STRUCT_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/bits/kernel_types.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/bits/kernel_types.h new file mode 100644 index 00000000..d69a875d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/bits/kernel_types.h @@ -0,0 +1,44 @@ +/* Note that we use the exact same include guard #define names + * as asm/posix_types.h. This will avoid gratuitous conflicts + * with the posix_types.h kernel header, and will ensure that + * our private content, and not the kernel header, will win. + * -Erik + */ + +#ifndef __ARCH_BFIN_POSIX_TYPES_H +#define __ARCH_BFIN_POSIX_TYPES_H +typedef unsigned short __kernel_dev_t; +typedef unsigned long __kernel_ino_t; +typedef unsigned short __kernel_mode_t; +typedef unsigned short __kernel_nlink_t; +typedef long __kernel_off_t; +typedef int __kernel_pid_t; +typedef unsigned int __kernel_ipc_pid_t; +typedef unsigned int __kernel_uid_t; +typedef unsigned int __kernel_gid_t; +typedef unsigned int __kernel_size_t; +typedef int __kernel_ssize_t; +typedef int __kernel_ptrdiff_t; +typedef long __kernel_time_t; +typedef long __kernel_suseconds_t; +typedef long __kernel_clock_t; +typedef int __kernel_daddr_t; +typedef char * __kernel_caddr_t; +typedef unsigned short __kernel_uid16_t; +typedef unsigned short __kernel_gid16_t; +typedef unsigned int __kernel_uid32_t; +typedef unsigned int __kernel_gid32_t; +typedef unsigned short __kernel_old_uid_t; +typedef unsigned short __kernel_old_gid_t; +typedef long long __kernel_loff_t; +typedef __kernel_dev_t __kernel_old_dev_t; + +typedef struct { +#ifdef __USE_ALL + int val[2]; +#else + int __val[2]; +#endif +} __kernel_fsid_t; + +#endif /* __ARCH_BFIN_POSIX_TYPES_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/bits/setjmp.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/bits/setjmp.h new file mode 100644 index 00000000..ee3f5e78 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/bits/setjmp.h @@ -0,0 +1,57 @@ +/* Copyright (C) 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Define the machine-dependent type `jmp_buf'. bfin version. Lineo, Inc. 2001*/ +#ifndef _BITS_SETJMP_H +#define _BITS_SETJMP_H 1 + +#if !defined _SETJMP_H && !defined _PTHREAD_H +# error "Never include directly; use instead." +#endif + +#ifndef _ASM +/* Jump buffer contains r7-r4, p5-p3, fp, sp and pc. Other registers are not saved. */ +typedef struct +{ + unsigned long __pregs[6]; + unsigned long fp; + unsigned long sp; + unsigned long __rregs[8]; + unsigned long astat; + unsigned long __lcregs[2]; + unsigned long a0w; + unsigned long a0x; + unsigned long a1w; + unsigned long a1x; + unsigned long __iregs[4]; + unsigned long __mregs[4]; + unsigned long __lregs[4]; + unsigned long __bregs[4]; + unsigned long pc; +}__jmp_buf[1]; + +#endif + +#define __JMP_BUF_SP 8 + +/* Test if longjmp to JMPBUF would unwind the frame + containing a local variable at ADDRESS. */ +#define _JMPBUF_UNWINDS(jmpbuf, address) \ + ((void *) (address) < (void *) (jmpbuf)->__pregs[6]) + +#endif /* bits/setjmp.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/bits/sigcontextinfo.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/bits/sigcontextinfo.h new file mode 100644 index 00000000..b7e08cfc --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/bits/sigcontextinfo.h @@ -0,0 +1,26 @@ +/* Copyright (C) 1998, 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Andreas Schwab , 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define SIGCONTEXT int _code, struct sigcontext * +#define SIGCONTEXT_EXTRA_ARGS _code, +#define GET_PC(ctx) ((void *) (ctx)->sc_pc) +#define GET_FRAME(ctx) ((void *) __builtin_frame_address (1)) +#define GET_STACK(ctx) ((void *) (ctx)->sc_usp) +#define CALL_SIGHANDLER(handler, signo, ctx) \ + (handler)((signo), SIGCONTEXT_EXTRA_ARGS (ctx)) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/bits/stackinfo.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/bits/stackinfo.h new file mode 100644 index 00000000..9e26de13 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/bits/stackinfo.h @@ -0,0 +1,28 @@ +/* Copyright (C) 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This file contains a bit of information about the stack allocation + of the processor. */ + +#ifndef _STACKINFO_H +#define _STACKINFO_H 1 + +/* On blackfin the stack grows down. */ +#define _STACK_GROWS_DOWN 1 + +#endif /* stackinfo.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/bits/syscalls.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/bits/syscalls.h new file mode 100644 index 00000000..6230b03d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/bits/syscalls.h @@ -0,0 +1,46 @@ +#ifndef _BITS_SYSCALLS_H +#define _BITS_SYSCALLS_H +#ifndef _SYSCALL_H +# error "Never use directly; include instead." +#endif + +#ifndef __ASSEMBLER__ + +#define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \ +({ \ + long __res; \ + __asm__ __volatile__ ( \ + "excpt 0;\n\t" \ + : "=q0" (__res) \ + : "qA" (name) ASMFMT_##nr(args) \ + : "memory","CC"); \ + __res; \ +}) + +#define ASMFMT_0() + +#define ASMFMT_1(arg1) \ + , "q0" ((long)(arg1)) + +#define ASMFMT_2(arg1, arg2) \ + ASMFMT_1(arg1) \ + , "q1" ((long)(arg2)) + +#define ASMFMT_3(arg1, arg2, arg3) \ + ASMFMT_2(arg1, arg2) \ + , "q2" ((long)(arg3)) + +#define ASMFMT_4(arg1, arg2, arg3, arg4) \ + ASMFMT_3(arg1, arg2, arg3) \ + , "q3" ((long)(arg4)) + +#define ASMFMT_5(arg1, arg2, arg3, arg4, arg5) \ + ASMFMT_4(arg1, arg2, arg3, arg4) \ + , "q4" ((long)(arg5)) + +#define ASMFMT_6(arg1, arg2, arg3, arg4, arg5, arg6) \ + ASMFMT_5(arg1, arg2, arg3, arg4, arg5) \ + , "q5" ((long)(arg6)) + +#endif /* __ASSEMBLER__ */ +#endif /* _BITS_SYSCALLS_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/bits/typesizes.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/bits/typesizes.h new file mode 100644 index 00000000..eb61fc99 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/bits/typesizes.h @@ -0,0 +1,66 @@ +/* bits/typesizes.h -- underlying types for *_t. Generic version. + Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _BITS_TYPES_H +# error "Never include directly; use instead." +#endif + +#ifndef _BITS_TYPESIZES_H +#define _BITS_TYPESIZES_H 1 + +/* See for the meaning of these macros. This file exists so + that need not vary across different GNU platforms. */ + +#define __DEV_T_TYPE __UQUAD_TYPE +#define __UID_T_TYPE __U32_TYPE +#define __GID_T_TYPE __U32_TYPE +#define __INO_T_TYPE __ULONGWORD_TYPE +#define __INO64_T_TYPE __UQUAD_TYPE +#define __MODE_T_TYPE __U32_TYPE +#define __NLINK_T_TYPE __UWORD_TYPE +#define __OFF_T_TYPE __SLONGWORD_TYPE +#define __OFF64_T_TYPE __SQUAD_TYPE +#define __PID_T_TYPE __S32_TYPE +#define __RLIM_T_TYPE __ULONGWORD_TYPE +#define __RLIM64_T_TYPE __UQUAD_TYPE +#define __BLKCNT_T_TYPE __SLONGWORD_TYPE +#define __BLKCNT64_T_TYPE __SQUAD_TYPE +#define __FSBLKCNT_T_TYPE __ULONGWORD_TYPE +#define __FSBLKCNT64_T_TYPE __UQUAD_TYPE +#define __FSFILCNT_T_TYPE __ULONGWORD_TYPE +#define __FSFILCNT64_T_TYPE __UQUAD_TYPE +#define __ID_T_TYPE __U32_TYPE +#define __CLOCK_T_TYPE __SLONGWORD_TYPE +#define __TIME_T_TYPE __SLONGWORD_TYPE +#define __USECONDS_T_TYPE __U32_TYPE +#define __SUSECONDS_T_TYPE __SLONGWORD_TYPE +#define __DADDR_T_TYPE __S32_TYPE +#define __SWBLK_T_TYPE __SLONGWORD_TYPE +#define __KEY_T_TYPE __S32_TYPE +#define __CLOCKID_T_TYPE __S32_TYPE +#define __TIMER_T_TYPE void * +#define __BLKSIZE_T_TYPE __SLONGWORD_TYPE +#define __FSID_T_TYPE struct { int __val[2]; } +#define __SSIZE_T_TYPE __SLONGWORD_TYPE + +/* Number of descriptors that can fit in an `fd_set'. */ +#define __FD_SETSIZE 1024 + + +#endif /* bits/typesizes.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/bits/uClibc_arch_features.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/bits/uClibc_arch_features.h new file mode 100644 index 00000000..4bab5476 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/bits/uClibc_arch_features.h @@ -0,0 +1,48 @@ +/* + * Track misc arch-specific features that aren't config options + */ + +#ifndef _BITS_UCLIBC_ARCH_FEATURES_H +#define _BITS_UCLIBC_ARCH_FEATURES_H + +/* instruction used when calling abort() to kill yourself */ +/*#define __UCLIBC_ABORT_INSTRUCTION__ "asm instruction"*/ +#undef __UCLIBC_ABORT_INSTRUCTION__ + +/* can your target use syscall6() for mmap ? */ +#define __UCLIBC_MMAP_HAS_6_ARGS__ + +/* does your target use syscall4() for truncate64 ? (32bit arches only) */ +#undef __UCLIBC_TRUNCATE64_HAS_4_ARGS__ + +/* does your target have a broken create_module() ? */ +#undef __UCLIBC_BROKEN_CREATE_MODULE__ + +/* does your target have to worry about older [gs]etrlimit() ? */ +#undef __UCLIBC_HANDLE_OLDER_RLIMIT__ + +/* does your target have an asm .set ? */ +#define __UCLIBC_HAVE_ASM_SET_DIRECTIVE__ + +/* define if target doesn't like .global */ +#undef __UCLIBC_ASM_GLOBAL_DIRECTIVE__ + +/* define if target supports .weak */ +#define __UCLIBC_HAVE_ASM_WEAK_DIRECTIVE__ + +/* define if target supports .weakext */ +#undef __UCLIBC_HAVE_ASM_WEAKEXT_DIRECTIVE__ + +/* needed probably only for ppc64 */ +#undef __UCLIBC_HAVE_ASM_GLOBAL_DOT_NAME__ + +/* define if target supports CFI pseudo ops */ +#undef __UCLIBC_HAVE_ASM_CFI_DIRECTIVES__ + +/* define if target supports IEEE signed zero floats */ +#define __UCLIBC_HAVE_SIGNED_ZERO__ + +/* only weird assemblers generally need this */ +#undef __UCLIBC_ASM_LINE_SEP__ + +#endif /* _BITS_UCLIBC_ARCH_FEATURES_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/bits/wordsize.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/bits/wordsize.h new file mode 100644 index 00000000..ba643b60 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/bits/wordsize.h @@ -0,0 +1,19 @@ +/* Copyright (C) 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define __WORDSIZE 32 diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/bsd-_setjmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/bsd-_setjmp.S new file mode 100644 index 00000000..c365b4ef --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/bsd-_setjmp.S @@ -0,0 +1,99 @@ +/* __setjmp for the Blackfin project + * + * Copyright (C) 2000-2006 Erik Andersen + * Copyright (C) 2002, David McCullough + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +.text +.global __setjmp; +.type __setjmp,STT_FUNC; +.align 4; + +__setjmp: + [--SP] = P0; /* Save P0 */ + P0 = R0; + R0 = [SP++]; + [P0 + 0x00] = R0; /* Save saved P0 */ + [P0 + 0x04] = P1; + [P0 + 0x08] = P2; + [P0 + 0x0C] = P3; + [P0 + 0x10] = P4; + [P0 + 0x14] = P5; + + [P0 + 0x18] = FP; /* Frame Pointer */ + [P0 + 0x1C] = SP; /* Stack Pointer */ + + [P0 + 0x20] = P0; /* Data Registers */ + [P0 + 0x24] = R1; + [P0 + 0x28] = R2; + [P0 + 0x2C] = R3; + [P0 + 0x30] = R4; + [P0 + 0x34] = R5; + [P0 + 0x38] = R6; + [P0 + 0x3C] = R7; + + R0 = ASTAT; + [P0 + 0x40] = R0; + + R0 = LC0; /* Loop Counters */ + [P0 + 0x44] = R0; + R0 = LC1; + [P0 + 0x48] = R0; + + R0 = A0.W; /* Accumulators */ + [P0 + 0x4C] = R0; + R0 = A0.X; + [P0 + 0x50] = R0; + R0 = A1.W; + [P0 + 0x54] = R0; + R0 = A1.X; + [P0 + 0x58] = R0; + + R0 = I0; /* Index Registers */ + [P0 + 0x5C] = R0; + R0 = I1; + [P0 + 0x60] = R0; + R0 = I2; + [P0 + 0x64] = R0; + R0 = I3; + [P0 + 0x68] = R0; + + R0 = M0; /* Modifier Registers */ + [P0 + 0x6C] = R0; + R0 = M1; + [P0 + 0x70] = R0; + R0 = M2; + [P0 + 0x74] = R0; + R0 = M3; + [P0 + 0x78] = R0; + + R0 = L0; /* Length Registers */ + [P0 + 0x7c] = R0; + R0 = L1; + [P0 + 0x80] = R0; + R0 = L2; + [P0 + 0x84] = R0; + R0 = L3; + [P0 + 0x88] = R0; + + R0 = B0; /* Base Registers */ + [P0 + 0x8C] = R0; + R0 = B1; + [P0 + 0x90] = R0; + R0 = B2; + [P0 + 0x94] = R0; + R0 = B3; + [P0 + 0x98] = R0; + + R0 = RETS; + [P0 + 0x9C] = R0; + + R0 = [P0 + 0x20]; + R1 = 0; + JUMP.L ___sigjmp_save; + +.size __setjmp,.-__setjmp + +.section .note.GNU-stack,"",%progbits diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/bsdsetjmp.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/bsdsetjmp.c new file mode 100644 index 00000000..0a57d344 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/bsdsetjmp.c @@ -0,0 +1,103 @@ +/* setjmp for the Blackfin project + * + * Copyright (C) 2000-2006 Erik Andersen + * Copyright (C) 2003 Metrowerks + * Based on code from Analog Devices. + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +#undef setjmp + +int setjmp(jmp_buf env) +{ + __asm__ __volatile__( + "[--SP] = p0;\n\t" + "p0 = r0;\n\t" + "r0 = [SP++];\n\t" + + "[p0++] = r0;\n\t" /* GP address registers */ + "[p0++] = p1;\n\t" + "[p0++] = p2;\n\t" + "[p0++] = p3;\n\t" + "[p0++] = p4;\n\t" + "[p0++] = p5;\n\t" + + "[p0++] = FP;\n\t" /* frame pointer */ + "[p0++] = SP;\n\t" /* stack pointer */ + + "[p0++] = p0;\n\t" /* data regs */ + "[p0++] = r1;\n\t" + "[p0++] = r2;\n\t" + "[p0++] = r3;\n\t" + "[p0++] = r4;\n\t" + "[p0++] = r5;\n\t" + "[p0++] = r6;\n\t" + "[p0++] = r7;\n\t" + + "r0 = ASTAT;\n\t" + "[p0++] = r0;\n\t" + + "r0 = LC0;\n\t" /* loop counters */ + "[p0++] = r0;\n\t" + "r0 = LC1;\n\t" + "[p0++] = r0;\n\t" + + "r0 = A0.w;\n\t" + "[p0++] = r0;\n\t" + "r0.l = A0.x;\n\t" + "[p0++] = r0;\n\t" + "r0 = A1.w;\n\t" + "[p0++] = r0;\n\t" + "r0.l = A1.x;\n\t" + "[p0++] = r0;\n\t" + + /* Dag regs */ + "r0 = i0;\n\t" /* index registers */ + "[p0++] = r0;\n\t" + "r0 = i1;\n\t" + "[p0++] = r0;\n\t" + "r0 = i2;\n\t" + "[p0++] = r0;\n\t" + "r0 = i3;\n\t" + "[p0++] = r0;\n\t" + + "r0 = m0;\n\t" /* modifier registers */ + "[p0++] = r0;\n\t" + "r0 = m1;\n\t" + "[p0++] = r0;\n\t" + "r0 = m2;\n\t" + "[p0++] = r0;\n\t" + "r0 = m3;\n\t" + "[p0++] = r0;\n\t" + + "r0 = l0;\n\t" /* length registers */ + "[p0++] = r0;\n\t" + "r0 = l1;\n\t" + "[p0++] = r0;\n\t" + "r0 = l2;\n\t" + "[p0++] = r0;\n\t" + "r0 = l3;\n\t" + "[p0++] = r0;\n\t" + + "r0 = b0;\n\t" /* base registers */ + "[p0++] = r0;\n\t" + "r0 = b1;\n\t" + "[p0++] = r0;\n\t" + "r0 = b2;\n\t" + "[p0++] = r0;\n\t" + "r0 = b3;\n\t" + "[p0++] = r0;\n\t" + + "r0 = RETS;\n\t" /* store return address */ + "[p0++] = r0;\n\t" + + "r0 = 0;\n\t" + : + : + ); + + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/clone.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/clone.c new file mode 100644 index 00000000..067fdc76 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/clone.c @@ -0,0 +1,45 @@ +/* + * libc/sysdeps/linux/bfin/clone.c -- `clone' syscall for linux/blackfin + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include + +int +clone (int (*fn)(void *arg), void *child_stack, int flags, void *arg, ...) +{ + long rval = -1; + + if (fn && child_stack) { + + __asm__ __volatile__ ( + "excpt 0;" /* Call sys_clone */ + "cc = r0 == 0;" + "if !cc jump 1f;" /* if (rval != 0) skip to parent */ + "r0 = %4;" + "p0 = %5;" + "fp = 0;" +#ifdef __BFIN_FDPIC__ + "p1 = [p0];" + "p3 = [p0 + 4];" + "call (p1);" /* Call cloned function */ +#else + "call (p0);" /* Call cloned function */ +#endif + "p0 = %6;" + "excpt 0;" /* Call sys_exit */ + "1: nop;" + : "=q0" (rval) + : "qA" (__NR_clone), "q1" (child_stack), "q0" (flags), "a" (arg), "a" (fn), "i" (__NR_exit) + : "CC"); + + } else + __set_errno(EINVAL); + + return rval; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/crt1.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/crt1.S new file mode 100644 index 00000000..22b2b761 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/crt1.S @@ -0,0 +1,168 @@ +/* Copyright (C) 1991, 1992 Free Software Foundation, Inc. + +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + + +/* When we enter this piece of code, the user stack looks like this: +* argc argument counter (integer) +* argv[0] program name (pointer) +* argv[1...N] program args (pointers) +* NULL +* env[0...N] environment variables (pointers) +* NULL + +* When we are done here, we want +* R0=argc +* R1=*argv[0] +* R2=*envp[0] +*/ + +#include + +#undef USE_GOT +#if defined (__UCLIBC_FORMAT_SHARED_FLAT__) || defined (__UCLIBC_FORMAT_FLAT_SEP_DATA__) +#define USE_GOT +#endif + +#if !(defined L_Scrt1 && defined __UCLIBC_FORMAT_SHARED_FLAT__) + +.text +.align 2 +.global __start; +.type __start,STT_FUNC; +.weak __init; +.weak __fini; +.global ___uClibc_main; +.type ___uClibc_main,STT_FUNC; + +/* Stick in a dummy reference to main(), so that if an application + * is linking when the main() function is in a static library (.a) + * we can be sure that main() actually gets linked in */ + +.type _main,STT_FUNC; + +__start: + +#if defined(__BFIN_FDPIC__) && !defined(L_Scrt1) + /* P0 contains a pointer to the program's load map. */ + call .Lcall; +.Lcall: + R4 = RETS; + SP += -12; + R0.L = .Lcall; + R0.H = .Lcall; + R1.L = __ROFIXUP_LIST__; + R1.H = __ROFIXUP_LIST__; + R2.L = __ROFIXUP_END__; + R2.H = __ROFIXUP_END__; + R1 = R1 - R0; + R1 = R1 + R4; + R2 = R2 - R0; + R2 = R2 + R4; + R0 = P0; + CALL ___self_reloc; + SP += 12; + P3 = R0; +#endif + +/* clear the frame pointer and the L registers. */ + FP = 0; + L0 = 0; + L1 = 0; + L2 = 0; + L3 = 0; + +#ifdef __ID_SHARED_LIB__ + /* We know we have a local copy, so we can avoid the GOT. */ + CALL ___shared_flat_add_library; +#endif +/* Load register R1 (argc) from the stack to its final resting place */ + P0 = SP; + R1 = [P0++]; + +/* Copy argv pointer into R2 -- which its final resting place */ + R2 = P0; + + SP += -28; + +#ifndef __BFIN_FDPIC__ + R7 = 0; +#endif + /* Pass highest stack pointer to the app. */ + [SP + 24] = P2; + /* Store the pointer to ld.so's fini that we got in P1. */ + [SP + 20] = R7; + +/* Ok, now run uClibc's main() -- shouldn't return */ +#if (defined L_crt1 || defined L_Scrt1) && defined __UCLIBC_CTOR_DTOR__ + +#ifdef __BFIN_FDPIC__ + R3 = [P3 + __init@FUNCDESC_GOT17M4]; +#elif defined USE_GOT + R3 = [P5 + ___shared_flat_init@GOT]; +#else + R3.H = __init; + R3.L = __init; +#endif + [SP+12] = R3; + + +#ifdef __BFIN_FDPIC__ + R3 = [P3 + __fini@FUNCDESC_GOT17M4]; +#elif defined USE_GOT + R3 = [P5 + ___shared_flat_fini@GOT]; +#else + R3.H = __fini; + R3.L = __fini; +#endif + [SP+16] = R3; +#else /* no ctor/dtor handling */ + R3 = 0; + [SP + 12] = R3; + [SP + 16] = R3; +#endif + +#ifdef __BFIN_FDPIC__ + R0 = [P3 + _main@FUNCDESC_GOT17M4]; +#elif defined USE_GOT + R0 = [P5 + _main@GOT]; +#else + R0.H = _main; + R0.L = _main; +#endif +#ifdef USE_GOT + P0 = [P5 + ___uClibc_main@GOT]; + jump (P0) +#else + jump.l ___uClibc_main; +#endif + +#else + .text + .global lib_main + .hidden lib_main + .type lib_main,@function +lib_main: + RETS = [SP++]; + /* We know we have a local copy, so we can avoid the GOT. */ + JUMP.L ___shared_flat_add_library; + + .hidden _current_shared_library_p5_offset_ +#endif + +.section .note.GNU-stack,"",%progbits diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/crti.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/crti.S new file mode 100644 index 00000000..f2831cc2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/crti.S @@ -0,0 +1,64 @@ +/* Specialized code needed to support construction and destruction of + file-scope objects in C++ and Java code, and to support exception handling. + Copyright (C) 1999 Free Software Foundation, Inc. + Contributed by Charles-Antoine Gauthier (charles.gauthier@iit.nrc.ca). + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GCC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +/* As a special exception, if you link this library with files + compiled with GCC to produce an executable, this does not cause + the resulting executable to be covered by the GNU General Public License. + This exception does not however invalidate any other reasons why + the executable file might be covered by the GNU General Public License. */ + +/* + * This file just supplies function prologues for the .init and .fini + * sections. It is linked in before crtbegin.o. + */ + + .file "crti.o" + .ident "GNU C crti.o" + + .section .init + .globl __init + .type __init,@function +__init: +#if defined __ID_SHARED_LIB__ + [--SP] = P5; +#elif defined __BFIN_FDPIC__ + [--SP] = P3; +#endif + LINK 12; +#if defined __ID_SHARED_LIB__ + P5 = [P5 + _current_shared_library_p5_offset_] +#endif + .section .fini + .globl __fini + .type __fini,@function +__fini: +#if defined __ID_SHARED_LIB__ + [--SP] = P5; +#elif defined __BFIN_FDPIC__ + [--SP] = P3; +#endif + LINK 12; +#if defined __ID_SHARED_LIB__ + P5 = [P5 + _current_shared_library_p5_offset_] +#endif + +.section .note.GNU-stack,"",%progbits diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/crtn.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/crtn.S new file mode 100644 index 00000000..a35ebe05 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/crtn.S @@ -0,0 +1,55 @@ +/* Specialized code needed to support construction and destruction of + file-scope objects in C++ and Java code, and to support exception handling. + Copyright (C) 1999 Free Software Foundation, Inc. + Contributed by Charles-Antoine Gauthier (charles.gauthier@iit.nrc.ca). + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GCC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +/* As a special exception, if you link this library with files + compiled with GCC to produce an executable, this does not cause + the resulting executable to be covered by the GNU General Public License. + This exception does not however invalidate any other reasons why + the executable file might be covered by the GNU General Public License. */ + +/* + * This file supplies function epilogues for the .init and .fini sections. + * It is linked in after all other files. + */ + + .file "crtn.o" + .ident "GNU C crtn.o" + + .section .init + unlink; +#if defined __ID_SHARED_LIB__ + P5 = [SP++]; +#elif defined __BFIN_FDPIC__ + P3 = [SP++]; +#endif + rts; + + .section .fini + unlink; +#if defined __ID_SHARED_LIB__ + P5 = [SP++]; +#elif defined __BFIN_FDPIC__ + P3 = [SP++]; +#endif + rts; + +.section .note.GNU-stack,"",%progbits diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/crtreloc.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/crtreloc.c new file mode 100644 index 00000000..a44b50ba --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/crtreloc.c @@ -0,0 +1,145 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. + written by Alexandre Oliva +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation; either version 2.1 of the +License, or (at your option) any later version. + +In addition to the permissions in the GNU Lesser General Public +License, the Free Software Foundation gives you unlimited +permission to link the compiled version of this file with other +programs, and to distribute those programs without any restriction +coming from the use of this file. (The GNU Lesser General Public +License restrictions do apply in other respects; for example, they +cover modification of the file, and distribution when not linked +into another program.) + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#ifdef __BFIN_FDPIC__ + +#include +#include + +/* This file is to be compiled into crt object files, to enable + executables to easily self-relocate. */ + +union word { + char c[4]; + void *v; +}; + +/* Compute the runtime address of pointer in the range [p,e), and then + map the pointer pointed by it. */ +static __always_inline void *** +reloc_range_indirect (void ***p, void ***e, + const struct elf32_fdpic_loadmap *map) +{ + while (p < e) + { + if (*p != (void **)-1) + { + void *ptr = __reloc_pointer (*p, map); + if (ptr != (void *)-1) + { + void *pt; + if ((long)ptr & 3) + { + unsigned char *c = ptr; + int i; + unsigned long v = 0; + for (i = 0; i < 4; i++) + v |= c[i] << 8 * i; + pt = (void *)v; + } + else + pt = *(void**)ptr; + pt = __reloc_pointer (pt, map); + if ((long)ptr & 3) + { + unsigned char *c = ptr; + int i; + unsigned long v = (unsigned long)pt; + for (i = 0; i < 4; i++, v >>= 8) + c[i] = v; + } + else + *(void**)ptr = pt; + } + } + p++; + } + return p; +} + +/* Call __reloc_range_indirect for the given range except for the last + entry, whose contents are only relocated. It's expected to hold + the GOT value. */ +attribute_hidden void* +__self_reloc (const struct elf32_fdpic_loadmap *map, + void ***p, void ***e) +{ + p = reloc_range_indirect (p, e-1, map); + + if (p >= e) + return (void*)-1; + + return __reloc_pointer (*p, map); +} + +#if 0 +/* These are other functions that might be useful, but that we don't + need. */ + +/* Remap pointers in [p,e). */ +static __always_inline void** +reloc_range (void **p, void **e, + const struct elf32_fdpic_loadmap *map) +{ + while (p < e) + { + *p = __reloc_pointer (*p, map); + p++; + } + return p; +} + +/* Remap p, adjust e by the same offset, then map the pointers in the + range determined by them. */ +void attribute_hidden +__reloc_range (const struct elf32_fdpic_loadmap *map, + void **p, void **e) +{ + void **old = p; + + p = __reloc_pointer (p, map); + e += p - old; + reloc_range (p, e, map); +} + +/* Remap p, adjust e by the same offset, then map pointers referenced + by the (unadjusted) pointers in the range. Return the relocated + value of the last pointer in the range. */ +void* attribute_hidden +__reloc_range_indirect (const struct elf32_fdpic_loadmap *map, + void ***p, void ***e) +{ + void ***old = p; + + p = __reloc_pointer (p, map); + e += p - old; + return reloc_range_indirect (p, e, map); +} +#endif + +#endif /* __BFIN_FDPIC__ */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/dma-memcpy.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/dma-memcpy.c new file mode 100644 index 00000000..274b99e8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/dma-memcpy.c @@ -0,0 +1,6 @@ +#include +#include +#include + +_syscall3 (__ptr_t, dma_memcpy, __ptr_t, dest, __ptr_t, src, size_t, len) + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/setjmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/setjmp.S new file mode 100644 index 00000000..a2b6176d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/setjmp.S @@ -0,0 +1,98 @@ +/* setjmp for the Blackfin project + * + * Copyright (C) 2000-2006 Erik Andersen + * Copyright (C) 2003 Metrowerks + * Based on code from Analog Devices. + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +.text +.global ___sigsetjmp; +.type ___sigsetjmp,STT_FUNC; +.align 4; + +___sigsetjmp: + [--SP] = P0; /* Save P0 */ + P0 = R0; + R0 = [SP++]; + [P0 + 0x00] = R0; /* Save saved P0 */ + [P0 + 0x04] = P1; + [P0 + 0x08] = P2; + [P0 + 0x0C] = P3; + [P0 + 0x10] = P4; + [P0 + 0x14] = P5; + + [P0 + 0x18] = FP; /* Frame Pointer */ + [P0 + 0x1C] = SP; /* Stack Pointer */ + + [P0 + 0x20] = P0; /* Data Registers */ + [P0 + 0x24] = R1; + [P0 + 0x28] = R2; + [P0 + 0x2C] = R3; + [P0 + 0x30] = R4; + [P0 + 0x34] = R5; + [P0 + 0x38] = R6; + [P0 + 0x3C] = R7; + + R0 = ASTAT; + [P0 + 0x40] = R0; + + R0 = LC0; /* Loop Counters */ + [P0 + 0x44] = R0; + R0 = LC1; + [P0 + 0x48] = R0; + + R0 = A0.W; /* Accumulators */ + [P0 + 0x4C] = R0; + R0 = A0.X; + [P0 + 0x50] = R0; + R0 = A1.W; + [P0 + 0x54] = R0; + R0 = A1.X; + [P0 + 0x58] = R0; + + R0 = I0; /* Index Registers */ + [P0 + 0x5C] = R0; + R0 = I1; + [P0 + 0x60] = R0; + R0 = I2; + [P0 + 0x64] = R0; + R0 = I3; + [P0 + 0x68] = R0; + + R0 = M0; /* Modifier Registers */ + [P0 + 0x6C] = R0; + R0 = M1; + [P0 + 0x70] = R0; + R0 = M2; + [P0 + 0x74] = R0; + R0 = M3; + [P0 + 0x78] = R0; + + R0 = L0; /* Length Registers */ + [P0 + 0x7c] = R0; + R0 = L1; + [P0 + 0x80] = R0; + R0 = L2; + [P0 + 0x84] = R0; + R0 = L3; + [P0 + 0x88] = R0; + + R0 = B0; /* Base Registers */ + [P0 + 0x8C] = R0; + R0 = B1; + [P0 + 0x90] = R0; + R0 = B2; + [P0 + 0x94] = R0; + R0 = B3; + [P0 + 0x98] = R0; + + R0 = RETS; + [P0 + 0x9C] = R0; + + R0 = [P0 + 0x20]; + JUMP.L ___sigjmp_save; +.size ___sigsetjmp, .-___sigsetjmp + +.section .note.GNU-stack,"",%progbits diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/sram-alloc.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/sram-alloc.c new file mode 100644 index 00000000..6b33b267 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/sram-alloc.c @@ -0,0 +1,6 @@ +#include +#include +#include + +_syscall2 (__ptr_t, sram_alloc, size_t, len, unsigned long, flags) + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/sram-free.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/sram-free.c new file mode 100644 index 00000000..0fba936c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/sram-free.c @@ -0,0 +1,6 @@ +#include +#include +#include + +_syscall1 (__ptr_t, sram_free, __ptr_t, addr) + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/sys/elf.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/sys/elf.h new file mode 100644 index 00000000..d959cdca --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/sys/elf.h @@ -0,0 +1,26 @@ +/* Copyright (C) 1998, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_ELF_H +#define _SYS_ELF_H 1 + +#warning "This header is obsolete; use instead." + +#include + +#endif /* _SYS_ELF_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/sys/io.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/sys/io.h new file mode 100644 index 00000000..81762bec --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/sys/io.h @@ -0,0 +1,49 @@ +/* Copyright (C) 1996, 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_IO_H + +#define _SYS_IO_H 1 +#include + +__BEGIN_DECLS + +/* If TURN_ON is TRUE, request for permission to do direct i/o on the + port numbers in the range [FROM,FROM+NUM-1]. Otherwise, turn I/O + permission off for that range. This call requires root privileges. */ +extern int ioperm (unsigned long int __from, unsigned long int __num, + int __turn_on) __THROW; +libc_hidden_proto(ioperm) + +/* Set the I/O privilege level to LEVEL. If LEVEL is nonzero, + permission to access any I/O port is granted. This call requires + root privileges. */ +extern int iopl (int __level) __THROW; + +/* The functions that actually perform reads and writes. */ +extern unsigned char inb (unsigned long int port) __THROW; +extern unsigned short int inw (unsigned long int port) __THROW; +extern unsigned long int inl (unsigned long int port) __THROW; + +extern void outb (unsigned char value, unsigned long int port) __THROW; +extern void outw (unsigned short value, unsigned long int port) __THROW; +extern void outl (unsigned long value, unsigned long int port) __THROW; + +__END_DECLS + +#endif /* _SYS_IO_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/sys/procfs.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/sys/procfs.h new file mode 100644 index 00000000..45a65f39 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/sys/procfs.h @@ -0,0 +1,125 @@ +/* Copyright (C) 1996, 1997, 1999, 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_PROCFS_H +#define _SYS_PROCFS_H 1 + +/* This is somewhat modelled after the file of the same name on SVR4 + systems. It provides a definition of the core file format for ELF + used on Linux. It doesn't have anything to do with the /proc file + system, even though Linux has one. + + Anyway, the whole purpose of this file is for GDB and GDB only. + Don't read too much into it. Don't use it for anything other than + GDB unless you know what you are doing. */ + +#include +#include +#include +#include + +__BEGIN_DECLS + +/* Type for a general-purpose register. */ +typedef unsigned long elf_greg_t; + +/* And the whole bunch of them. We could have used `struct + user_regs_struct' directly in the typedef, but tradition says that + the register set is an array, which does have some peculiar + semantics, so leave it that way. */ +#define ELF_NGREG (sizeof (struct user_regs_struct) / sizeof(elf_greg_t)) +typedef elf_greg_t elf_gregset_t[ELF_NGREG]; + +/* Register set for the floating-point registers. Empty on the Blackfin. */ +typedef struct { } elf_fpregset_t; + +/* Signal info. */ +struct elf_siginfo + { + int si_signo; /* Signal number. */ + int si_code; /* Extra code. */ + int si_errno; /* Errno. */ + }; + + +/* Definitions to generate Intel SVR4-like core files. These mostly + have the same names as the SVR4 types with "elf_" tacked on the + front to prevent clashes with Linux definitions, and the typedef + forms have been avoided. This is mostly like the SVR4 structure, + but more Linuxy, with things that Linux does not support and which + GDB doesn't really use excluded. */ + +struct elf_prstatus + { + struct elf_siginfo pr_info; /* Info associated with signal. */ + short int pr_cursig; /* Current signal. */ + unsigned long int pr_sigpend; /* Set of pending signals. */ + unsigned long int pr_sighold; /* Set of held signals. */ + __pid_t pr_pid; + __pid_t pr_ppid; + __pid_t pr_pgrp; + __pid_t pr_sid; + struct timeval pr_utime; /* User time. */ + struct timeval pr_stime; /* System time. */ + struct timeval pr_cutime; /* Cumulative user time. */ + struct timeval pr_cstime; /* Cumulative system time. */ + elf_gregset_t pr_reg; /* GP registers. */ + int pr_fpvalid; /* True if math copro being used. */ + }; + + +#define ELF_PRARGSZ (80) /* Number of chars for args. */ + +struct elf_prpsinfo + { + char pr_state; /* Numeric process state. */ + char pr_sname; /* Char for pr_state. */ + char pr_zomb; /* Zombie. */ + char pr_nice; /* Nice val. */ + unsigned long int pr_flag; /* Flags. */ + unsigned short int pr_uid; + unsigned short int pr_gid; + int pr_pid, pr_ppid, pr_pgrp, pr_sid; + /* Lots missing */ + char pr_fname[16]; /* Filename of executable. */ + char pr_psargs[ELF_PRARGSZ]; /* Initial part of arg list. */ + }; + + +/* The rest of this file provides the types for emulation of the + Solaris interfaces that should be implemented by + users of libthread_db. */ + +/* Addresses. */ +typedef void *psaddr_t; + +/* Register sets. Linux has different names. */ +typedef elf_gregset_t prgregset_t; +typedef elf_fpregset_t prfpregset_t; + +/* We don't have any differences between processes and threads, + therefore have only one PID type. */ +typedef __pid_t lwpid_t; + +/* Process status and info. In the end we do provide typedefs for them. */ +typedef struct elf_prstatus prstatus_t; +typedef struct elf_prpsinfo prpsinfo_t; + +__END_DECLS + +#endif /* sys/procfs.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/sys/ucontext.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/sys/ucontext.h new file mode 100644 index 00000000..ac2ef94e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/sys/ucontext.h @@ -0,0 +1,152 @@ +/* Copyright (C) 1997, 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* System V/blackfin ABI compliant context switching support. */ + +#ifndef _SYS_UCONTEXT_H +#define _SYS_UCONTEXT_H 1 + +#include +#include + +/* Type for general register. */ +typedef int greg_t; + +/* Number of general registers. */ +#define NGREG 47 + +/* Container for all general registers. */ +typedef greg_t gregset_t[NGREG]; + +/* Number of each register is the `gregset_t' array. */ +enum +{ + REG_R0 = 0, +#define REG_R0 REG_R0 + REG_R1 = 1, +#define REG_R1 REG_R1 + REG_R2 = 2, +#define REG_R2 REG_R2 + REG_R3 = 3, +#define REG_R3 REG_R3 + REG_R4 = 4, +#define REG_R4 REG_R4 + REG_R5 = 5, +#define REG_R5 REG_R5 + REG_R6 = 6, +#define REG_R6 REG_R6 + REG_R7 = 7, +#define REG_R7 REG_R7 + REG_P0 = 8, +#define REG_P0 REG_P0 + REG_P1 = 9, +#define REG_P1 REG_P1 + REG_P2 = 10, +#define REG_P2 REG_P2 + REG_P3 = 11, +#define REG_P3 REG_P3 + REG_P4 = 12, +#define REG_P4 REG_P4 + REG_P5 = 13, +#define REG_P5 REG_P5 + REG_USP = 14, +#define REG_USP REG_USP + REG_A0W = 15, +#define REG_A0W REG_A0W + REG_A1W = 16, +#define REG_A1W REG_A1W + REG_A0X = 17, +#define REG_A0X REG_A0X + REG_A1X = 18, +#define REG_A1X REG_A1X + REG_ASTAT = 19, +#define REG_ASTAT REG_ASTAT + REG_RETS = 20, +#define REG_RETS REG_RETS + REG_PC= 21, +#define REG_PC REG_PC + REG_RETX = 22, +#define REG_RETX REG_RETX + REG_FP = 23, +#define REG_FP REG_FP + REG_I0 = 24, +#define REG_I0 REG_I0 + REG_I1 = 25, +#define REG_I1 REG_I1 + REG_I2 = 26, +#define REG_I2 REG_I2 + REG_I3 = 27, +#define REG_I3 REG_I3 + REG_M0 = 28, +#define REG_M0 REG_M0 + REG_M1 = 29, +#define REG_M1 REG_M1 + REG_M2 = 30, +#define REG_M2 REG_M2 + REG_M3 = 31, +#define REG_M3 REG_M3 + REG_L0 = 32, +#define REG_L0 REG_L0 + REG_L1 = 33, +#define REG_L1 REG_L1 + REG_L2 = 34, +#define REG_L2 REG_L2 + REG_L3 = 35, +#define REG_L3 REG_L3 + REG_B_0 = 36, +#define REG_B0 REG_B0 + REG_B1 = 37, +#define REG_B1 REG_B1 + REG_B2 = 38, +#define REG_B2 REG_B2 + REG_B3 = 39, +#define REG_B3 REG_B3 + REG_LC0 = 40, +#define REG_LC0 REG_LC0 + REG_LC1 = 41, +#define REG_LC1 REG_LC1 + REG_LT0 = 42, +#define REG_LT0 REG_LT0 + REG_LT1 = 43, +#define REG_LT1 REG_LT1 + REG_LB0 = 44, +#define REG_LB0 REG_LB0 + REG_LB1 = 45, +#define REG_LB1 REG_LB1 + REG_SEQSTAT = 46 +#define REG_SEQSTAT REG_SEQSTAT +}; + +/* Context to describe whole processor state. */ +typedef struct +{ + gregset_t gregs; +} mcontext_t; + + +/* Userlevel context. */ +typedef struct ucontext +{ + unsigned long int uc_flags; + struct ucontext *uc_link; + stack_t uc_stack; + mcontext_t uc_mcontext; + __sigset_t uc_sigmask; +} ucontext_t; + +#endif /* sys/ucontext.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/sys/user.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/sys/user.h new file mode 100644 index 00000000..558abd6a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/sys/user.h @@ -0,0 +1,57 @@ +#ifndef _SYS_USER_H +#define _SYS_USER_H + +struct user_bfinfp_struct { +}; + +/* This is the old layout of "struct pt_regs" as of Linux 1.x, and + is still the layout used by user (the new pt_regs doesn't have + all registers). */ +struct user_regs_struct { + long r0, r1, r2, r3, r4, r5, r6, r7; + long p0, p1, p2, p3, p4, p5, usp, fp; + long i0, i1, i2, i3; + long l0, l1, l2, l3; + long b0, b1, b2, b3; + long m0, m1, m2, m3; + long a0w, a1w; + long a0x, a1x; + unsigned long rets; + unsigned long astat; + unsigned long pc; + unsigned long orig_p0; +}; + +/* When the kernel dumps core, it starts by dumping the user struct - + this will be used by gdb to figure out where the data and stack segments + are within the file, and what virtual addresses to use. */ + +struct user { +/* We start with the registers, to mimic the way that "memory" is returned + from the ptrace(3,...) function. */ + + struct user_regs_struct regs; /* Where the registers are actually stored */ + +/* The rest of this junk is to help gdb figure out what goes where */ + unsigned long int u_tsize; /* Text segment size (pages). */ + unsigned long int u_dsize; /* Data segment size (pages). */ + unsigned long int u_ssize; /* Stack segment size (pages). */ + unsigned long start_code; /* Starting virtual address of text. */ + unsigned long start_stack; /* Starting virtual address of stack area. + This is actually the bottom of the stack, + the top of the stack is always found in the + esp register. */ + long int signal; /* Signal that caused the core dump. */ + int reserved; /* No longer used */ + unsigned long u_ar0; + /* Used by gdb to help find the values for */ + /* the registers. */ + unsigned long magic; /* To uniquely identify a core file */ + char u_comm[32]; /* User command that was responsible */ +}; +#define NBPG PAGE_SIZE +#define UPAGES 1 +#define HOST_TEXT_START_ADDR (u.start_code) +#define HOST_STACK_END_ADDR (u.start_stack + u.u_ssize * NBPG) + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/sysdep.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/sysdep.h new file mode 100644 index 00000000..352fbf42 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/bfin/sysdep.h @@ -0,0 +1,21 @@ +/* + * libc/sysdeps/linux/bfin/sysdep.h + * + * Copyright (C) 2007 Analog Devices Inc. + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#ifndef __BFIN_SYSDEP_H__ +#define __BFIN_SYSDEP_H__ + +#include + +#ifdef __ASSEMBLER__ + +#define ENTRY(sym) .global sym; .type sym, STT_FUNC; sym: +#define ENDPROC(sym) .size sym, . - sym + +#endif + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/.indent.pro b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/.indent.pro new file mode 100644 index 00000000..492ecf1c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/.indent.pro @@ -0,0 +1,33 @@ +--blank-lines-after-declarations +--blank-lines-after-procedures +--break-before-boolean-operator +--no-blank-lines-after-commas +--braces-on-if-line +--braces-on-struct-decl-line +--comment-indentation25 +--declaration-comment-column25 +--no-comment-delimiters-on-blank-lines +--cuddle-else +--continuation-indentation4 +--case-indentation0 +--else-endif-column33 +--space-after-cast +--line-comments-indentation0 +--declaration-indentation1 +--dont-format-first-column-comments +--dont-format-comments +--honour-newlines +--indent-level4 +/* changed from 0 to 4 */ +--parameter-indentation4 +--line-length78 /* changed from 75 */ +--continue-at-parentheses +--no-space-after-function-call-names +--dont-break-procedure-type +--dont-star-comments +--leave-optional-blank-lines +--dont-space-special-semicolon +--tab-size4 +/* additions by Mark */ +--case-brace-indentation0 +--leave-preprocessor-space diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/Makefile new file mode 100644 index 00000000..3ed177ae --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../../ +top_builddir=../../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/Makefile.in new file mode 100644 index 00000000..8a4add81 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/Makefile.in @@ -0,0 +1,138 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +COMMON_DIR := $(top_srcdir)libc/sysdeps/linux/common +COMMON_OUT := $(top_builddir)libc/sysdeps/linux/common + +CSRC := $(notdir $(wildcard $(COMMON_DIR)/*.c)) + +ifneq ($(UCLIBC_HAS_LFS),y) +CSRC_LFS := $(notdir $(wildcard $(COMMON_DIR)/*64.c)) +CSRC := $(filter-out llseek.c $(CSRC_LFS),$(CSRC)) +endif + +CSRC := $(filter-out ssp-local.c,$(CSRC)) +ifneq ($(UCLIBC_HAS_SSP),y) +CSRC := $(filter-out ssp.c,$(CSRC)) +endif + +ifneq ($(UCLIBC_LINUX_MODULE_24),y) +CSRC := $(filter-out create_module.c query_module.c get_kernel_syms.c,$(CSRC)) +endif + +ifneq ($(UCLIBC_LINUX_SPECIFIC),y) +# we need these internally: fstatfs.c statfs.c +CSRC := $(filter-out capget.c capset.c inotify.c ioperm.c iopl.c \ + modify_ldt.c personality.c ppoll.c prctl.c readahead.c reboot.c \ + remap_file_pages.c sched_getaffinity.c sched_setaffinity.c \ + sendfile64.c sendfile.c setfsgid.c setfsuid.c setresuid.c \ + splice.c vmsplice.c tee.c signalfd.c swapoff.c swapon.c \ + sync_file_range.c sysctl.c sysinfo.c timerfd.c uselib.c vhangup.c,$(CSRC)) +ifneq ($(UCLIBC_HAS_THREADS_NATIVE),y) +# we need madvise.c in NPTL +CSRC := $(filter-pout madvise.c,$(CSRC)) +endif +endif + +ifeq ($(UCLIBC_HAS_THREADS_NATIVE),y) +CSRC := $(filter-out fork.c getpid.c raise.c open.c close.c read.c write.c, $(CSRC)) +ifeq ($(TARGET_ARCH),arm) +CSRC := $(filter-out vfork.c, $(CSRC)) +else ifeq ($(TARGET_ARCH),x86_64) +CSRC := $(filter-out vfork.c, $(CSRC)) +else +CSRC := $(filter-out waitpid.c, $(CSRC)) +endif +endif + +ifneq ($(ARCH_USE_MMU),y) +# stubbed out in mman.h +CSRC := $(filter-out msync.c, $(CSRC)) +endif + +ifneq ($(UCLIBC_BSD_SPECIFIC),y) +# we need these internally: getdomainname.c +CSRC := $(filter-out mincore.c setdomainname.c,$(CSRC)) +endif + +ifneq ($(UCLIBC_NTP_LEGACY),y) +CSRC := $(filter-out ntp_gettime.c,$(CSRC)) +endif + + +ifneq ($(UCLIBC_HAS_REALTIME),y) +# aio_cancel|aio_error|aio_fsync|aio_read|aio_return|aio_suspend|aio_write|clock_getres|clock_gettime|clock_settime|clock_settime|fdatasync|lio_listio|mlockall|munlockall|mlock|munlock|mq_close|mq_getattr|mq_notify|mq_open|mq_receive|mq_timedreceive|mq_send|mq_timedsend|mq_setattr|mq_unlink|nanosleep|sched_getparam|sched_get_priority_max|sched_get_priority_min|sched_getscheduler|sched_rr_get_interval|sched_setparam|sched_setscheduler|sem_close|sem_destroy|sem_getvalue|sem_init|sem_open|sem_post|sem_trywait|sem_wait|sem_unlink|sem_wait|shm_open|shm_unlink|sigqueue|sigtimedwait|sigwaitinfo|sigwaitinfo|timer_create|timer_delete|timer_getoverrun|timer_gettime|timer_settime +CSRC := $(filter-out clock_getres.c clock_gettime.c clock_settime.c fdatasync.c Makefile.in mlockall.c mlock.c munlockall.c munlock.c nanosleep.c __rt_sigtimedwait.c sched_getparam.c sched_get_priority_max.c sched_get_priority_min.c sched_getscheduler.c sched_rr_get_interval.c sched_setparam.c sched_setscheduler.c sigqueue.c,$(CSRC)) +endif + + +ifneq ($(UCLIBC_HAS_ADVANCED_REALTIME),y) +# clock_getcpuclockid|clock_nanosleep|mq_timedreceive|mq_timedsend|posix_fadvise|posix_fallocate|posix_madvise|posix_memalign|posix_mem_offset|posix_spawnattr_destroy|posix_spawnattr_init|posix_spawnattr_getflags|posix_spawnattr_setflags|posix_spawnattr_getpgroup|posix_spawnattr_setpgroup|posix_spawnattr_getschedparam|posix_spawnattr_setschedparam|posix_spawnattr_getschedpolicy|posix_spawnattr_setschedpolicy|posix_spawnattr_getsigdefault|posix_spawnattr_setsigdefault|posix_spawnattr_getsigmask|posix_spawnattr_setsigmask|posix_spawnattr_init|posix_spawnattr_setflags|posix_spawnattr_setpgroup|posix_spawnattr_setschedparam|posix_spawnattr_setschedpolicy|posix_spawnattr_setsigdefault|posix_spawnattr_setsigmask|posix_spawn_file_actions_addclose|posix_spawn_file_actions_addopen|posix_spawn_file_actions_adddup2|posix_spawn_file_actions_addopen|posix_spawn_file_actions_destroy|posix_spawn_file_actions_init|posix_spawn_file_actions_init|posix_spawn|posix_spawnp|posix_spawnp|posix_typed_mem_get_info|pthread_mutex_timedlock|sem_timedwait +CSRC := $(filter-out posix_fadvise64.c posix_fadvise.c,$(CSRC)) +endif + +ifneq ($(UCLIBC_SUSV4_LEGACY),y) +CSRC := $(filter-out utime.c,$(CSRC)) +endif + +ifneq ($(UCLIBC_HAS_EPOLL),y) +CSRC := $(filter-out epoll.c,$(CSRC)) +endif + +ifneq ($(UCLIBC_HAS_XATTR),y) +CSRC := $(filter-out xattr.c,$(CSRC)) +endif + +ifneq ($(UCLIBC_HAS_PROFILING),y) +CSRC := $(filter-out noophooks.c pcprofile.c,$(CSRC)) +endif + +ifneq ($(UCLIBC_SV4_DEPRECATED),y) +CSRC := $(filter-out ustat.c,$(CSRC)) +endif + +ifeq ($(TARGET_ARCH),sh) +CSRC := $(filter-out longjmp.c vfork.c,$(CSRC)) +endif + +ifeq ($(TARGET_ARCH),sparc) +CSRC := $(filter-out vfork.c,$(CSRC)) +endif + +ifeq ($(TARGET_ARCH),i386) +CSRC := $(filter-out vfork.c,$(CSRC)) +endif + +# provided via pthreads builddir +CSRC := $(filter-out $(libc_a_CSRC) $(notdir $(libpthread_libc_OBJS:.o=.c)),$(CSRC)) +SSRC := $(filter-out $(libc_a_SSRC) $(notdir $(libpthread_libc_OBJS:.o=.S)),$(SSRC)) + +# fails for some reason +ifneq ($(strip $(ARCH_OBJS)),) +CSRC := $(filter-out $(notdir $(ARCH_OBJS:.o=.c)) $(ARCH_OBJ_FILTEROUT),$(CSRC)) +endif + +CFLAGS-ssp.c := $(SSP_DISABLE_FLAGS) +CFLAGS-ssp-local.c := $(SSP_DISABLE_FLAGS) + +COMMON_SRC := $(patsubst %.c,$(COMMON_DIR)/%.c,$(CSRC)) +COMMON_OBJ := $(patsubst %.c,$(COMMON_OUT)/%.o,$(CSRC)) + +libc-y += $(COMMON_OBJ) +libc-static-$(UCLIBC_HAS_SSP) += $(COMMON_OUT)/ssp-local.o +libc-nonshared-$(UCLIBC_HAS_SSP) += $(COMMON_OUT)/ssp-local.os + +libc-nomulti-y += $(COMMON_OUT)/__syscall_rt_sigaction.o \ + $(COMMON_OUT)/__syscall_sigaction.o \ + $(COMMON_OUT)/mremap.o \ + $(COMMON_OUT)/stat.o +libc-nomulti-$(UCLIBC_HAS_SSP) += $(COMMON_OUT)/ssp.o + +objclean-y += CLEAN_libc/sysdeps/linux/common + +CLEAN_libc/sysdeps/linux/common: + $(do_rm) $(addprefix $(COMMON_OUT)/*., o os oS) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/__rt_sigtimedwait.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/__rt_sigtimedwait.c new file mode 100644 index 00000000..a7ab8fb6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/__rt_sigtimedwait.c @@ -0,0 +1,101 @@ +/* vi: set sw=4 ts=4: */ +/* + * __rt_sigtimedwait() for uClibc + * + * Copyright (C) 2006 by Steven Hill + * Copyright (C) 2000-2004 by Erik Andersen + * + * GNU Library General Public License (LGPL) version 2 or later. + */ + +#include +#include +#include + +#ifdef __NR_rt_sigtimedwait + +# ifdef __UCLIBC_HAS_THREADS_NATIVE__ +# include + +static int do_sigtimedwait(const sigset_t *set, siginfo_t *info, + const struct timespec *timeout) +{ +# ifdef SIGCANCEL + sigset_t tmpset; + + if (set != NULL && (__builtin_expect (__sigismember (set, SIGCANCEL), 0) +# ifdef SIGSETXID + || __builtin_expect (__sigismember (set, SIGSETXID), 0) +# endif + )) + { + /* Create a temporary mask without the bit for SIGCANCEL set. */ + // We are not copying more than we have to. + memcpy (&tmpset, set, _NSIG / 8); + __sigdelset (&tmpset, SIGCANCEL); +# ifdef SIGSETXID + __sigdelset (&tmpset, SIGSETXID); +# endif + set = &tmpset; + } +# endif + + /* XXX The size argument hopefully will have to be changed to the + real size of the user-level sigset_t. */ + int result = INLINE_SYSCALL (rt_sigtimedwait, 4, set, info, + timeout, _NSIG / 8); + + /* The kernel generates a SI_TKILL code in si_code in case tkill is + used. tkill is transparently used in raise(). Since having + SI_TKILL as a code is useful in general we fold the results + here. */ + if (result != -1 && info != NULL && info->si_code == SI_TKILL) + info->si_code = SI_USER; + + return result; +} + +/* Return any pending signal or wait for one for the given time. */ +int attribute_hidden __sigtimedwait(const sigset_t *set, siginfo_t *info, + const struct timespec *timeout) +{ + if(SINGLE_THREAD_P) + return do_sigtimedwait(set, info, timeout); + + int oldtype = LIBC_CANCEL_ASYNC(); + + /* XXX The size argument hopefully will have to be changed to the + real size of the user-level sigset_t. */ + int result = do_sigtimedwait(set, info, timeout); + + LIBC_CANCEL_RESET(oldtype); + + return result; +} +# else +# define __need_NULL +# include +# define __NR___rt_sigtimedwait __NR_rt_sigtimedwait +static _syscall4(int, __rt_sigtimedwait, const sigset_t *, set, + siginfo_t *, info, const struct timespec *, timeout, + size_t, setsize); + +int attribute_hidden __sigtimedwait(const sigset_t * set, siginfo_t * info, + const struct timespec *timeout) +{ + return __rt_sigtimedwait(set, info, timeout, _NSIG / 8); +} +# endif /* !__UCLIBC_HAS_THREADS_NATIVE__ */ +#else +int attribute_hidden __sigtimedwait(const sigset_t * set, siginfo_t * info, + const struct timespec *timeout) +{ + if (set == NULL) + __set_errno(EINVAL); + else + __set_errno(ENOSYS); + return -1; +} +#endif +weak_alias(__sigtimedwait,sigtimedwait) +libc_hidden_weak(sigtimedwait) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/__rt_sigwaitinfo.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/__rt_sigwaitinfo.c new file mode 100644 index 00000000..92a11c9b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/__rt_sigwaitinfo.c @@ -0,0 +1,98 @@ +/* vi: set sw=4 ts=4: */ +/* + * __rt_sigwaitinfo() for uClibc + * + * Copyright (C) 2006 by Steven Hill + * Copyright (C) 2000-2004 by Erik Andersen + * + * GNU Library General Public License (LGPL) version 2 or later. + */ + +#include +#include +#include + +#ifdef __NR_rt_sigtimedwait + +# ifdef __UCLIBC_HAS_THREADS_NATIVE__ +# include + +static int do_sigwaitinfo(const sigset_t *set, siginfo_t *info) +{ +# ifdef SIGCANCEL + sigset_t tmpset; + + if (set != NULL && (__builtin_expect (__sigismember (set, SIGCANCEL), 0) +# ifdef SIGSETXID + || __builtin_expect (__sigismember (set, SIGSETXID), 0) +# endif + )) + { + /* Create a temporary mask without the bit for SIGCANCEL set. */ + // We are not copying more than we have to. + memcpy (&tmpset, set, _NSIG / 8); + __sigdelset (&tmpset, SIGCANCEL); +# ifdef SIGSETXID + __sigdelset (&tmpset, SIGSETXID); +# endif + set = &tmpset; + } +# endif + + /* XXX The size argument hopefully will have to be changed to the + real size of the user-level sigset_t. */ + int result = INLINE_SYSCALL (rt_sigtimedwait, 4, set, info, + NULL, _NSIG / 8); + + /* The kernel generates a SI_TKILL code in si_code in case tkill is + used. tkill is transparently used in raise(). Since having + SI_TKILL as a code is useful in general we fold the results + here. */ + if (result != -1 && info != NULL && info->si_code == SI_TKILL) + info->si_code = SI_USER; + + return result; +} + +/* Return any pending signal or wait for one for the given time. */ +int __sigwaitinfo(const sigset_t *set, siginfo_t *info) +{ + if(SINGLE_THREAD_P) + return do_sigwaitinfo(set, info); + + int oldtype = LIBC_CANCEL_ASYNC(); + + /* XXX The size argument hopefully will have to be changed to the + real size of the user-level sigset_t. */ + int result = do_sigwaitinfo(set, info); + + LIBC_CANCEL_RESET(oldtype); + + return result; +} +# else +# define __need_NULL +# include +# define __NR___rt_sigwaitinfo __NR_rt_sigtimedwait +static _syscall4(int, __rt_sigwaitinfo, const sigset_t *, set, + siginfo_t *, info, const struct timespec *, timeout, + size_t, setsize); + +int attribute_hidden __sigwaitinfo(const sigset_t * set, siginfo_t * info) +{ + return __rt_sigwaitinfo(set, info, NULL, _NSIG / 8); +} +# endif +#else +int attribute_hidden __sigwaitinfo(const sigset_t * set, siginfo_t * info) +{ + if (set == NULL) + __set_errno(EINVAL); + else + __set_errno(ENOSYS); + return -1; +} +#endif +libc_hidden_proto(sigwaitinfo) +weak_alias (__sigwaitinfo, sigwaitinfo) +libc_hidden_weak(sigwaitinfo) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/__socketcall.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/__socketcall.c new file mode 100644 index 00000000..e49fb21b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/__socketcall.c @@ -0,0 +1,15 @@ +/* vi: set sw=4 ts=4: */ +/* + * __socketcall() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#ifdef __NR_socketcall +#define __NR___socketcall __NR_socketcall +int __socketcall(int __call, unsigned long *__args) attribute_hidden; +_syscall2(int, __socketcall, int, call, unsigned long *, args) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/__syscall_fcntl.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/__syscall_fcntl.c new file mode 100644 index 00000000..5da3c5f3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/__syscall_fcntl.c @@ -0,0 +1,90 @@ +/* vi: set sw=4 ts=4: */ +/* + * __syscall_fcntl() for uClibc + * + * Copyright (C) 2006 Steven J. Hill + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#ifdef __UCLIBC_HAS_THREADS_NATIVE__ +#include /* Must come before . */ +#endif +#include +#include + +extern __typeof(fcntl) __libc_fcntl; +libc_hidden_proto(__libc_fcntl) + +int __fcntl_nocancel (int fd, int cmd, ...) +{ + va_list ap; + void *arg; + + va_start (ap, cmd); + arg = va_arg (ap, void *); + va_end (ap); + +# if __WORDSIZE == 32 + if (cmd == F_GETLK64 || cmd == F_SETLK64 || cmd == F_SETLKW64) { +# if defined __UCLIBC_HAS_LFS__ && defined __NR_fcntl64 + return INLINE_SYSCALL (fcntl64, 3, fd, cmd, arg); +# else + __set_errno(ENOSYS); + return -1; +# endif + } +# endif + return INLINE_SYSCALL (fcntl, 3, fd, cmd, arg); +} + +int __libc_fcntl (int fd, int cmd, ...) +{ + va_list ap; + void *arg; + + va_start (ap, cmd); + arg = va_arg (ap, void *); + va_end (ap); + +#ifdef __UCLIBC_HAS_THREADS_NATIVE__ + if (SINGLE_THREAD_P || (cmd != F_SETLKW && cmd != F_SETLKW64)) +# if defined __UCLIBC_HAS_LFS__ && defined __NR_fcntl64 + return INLINE_SYSCALL (fcntl64, 3, fd, cmd, arg); +# else + return INLINE_SYSCALL (fcntl, 3, fd, cmd, arg); +# endif + + int oldtype = LIBC_CANCEL_ASYNC (); + +# if defined __UCLIBC_HAS_LFS__ && defined __NR_fcntl64 + int result = INLINE_SYSCALL (fcntl64, 3, fd, cmd, arg); +# else + int result = INLINE_SYSCALL (fcntl, 3, fd, cmd, arg); +# endif + + LIBC_CANCEL_RESET (oldtype); + + return result; +#else +# if __WORDSIZE == 32 + if (cmd == F_GETLK64 || cmd == F_SETLK64 || cmd == F_SETLKW64) { +# if defined __UCLIBC_HAS_LFS__ && defined __NR_fcntl64 + return INLINE_SYSCALL (fcntl64, 3, fd, cmd, arg); +# else + __set_errno(ENOSYS); + return -1; +# endif + } +# endif + return INLINE_SYSCALL (fcntl, 3, fd, cmd, arg); +#endif +} +libc_hidden_def(__libc_fcntl) + +libc_hidden_proto(fcntl) +weak_alias(__libc_fcntl,fcntl) +libc_hidden_weak(fcntl) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/__syscall_fcntl64.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/__syscall_fcntl64.c new file mode 100644 index 00000000..e8782e96 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/__syscall_fcntl64.c @@ -0,0 +1,30 @@ +/* vi: set sw=4 ts=4: */ +/* + * __syscall_fcntl64() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include + +#if defined __UCLIBC_HAS_LFS__ && defined __NR_fcntl64 + +#define __NR___syscall_fcntl64 __NR_fcntl64 +static __inline__ _syscall3(int, __syscall_fcntl64, int, fd, int, cmd, long, arg) +int fcntl64(int fd, int cmd, ...) +{ + long arg; + va_list list; + + va_start(list, cmd); + arg = va_arg(list, long); + va_end(list); + + return (__syscall_fcntl64(fd, cmd, arg)); +} +libc_hidden_def(fcntl64) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/__syscall_rt_sigaction.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/__syscall_rt_sigaction.c new file mode 100644 index 00000000..006b38a2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/__syscall_rt_sigaction.c @@ -0,0 +1,22 @@ +/* vi: set sw=4 ts=4: */ +/* + * __syscall_rt_sigaction() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +#ifdef __NR_rt_sigaction +#include + +int __syscall_rt_sigaction (int __signum, const struct sigaction *__act, + struct sigaction *__oldact, size_t __size); + +#define __NR___syscall_rt_sigaction __NR_rt_sigaction +_syscall4(int, __syscall_rt_sigaction, int, signum, + const struct sigaction *, act, struct sigaction *, oldact, + size_t, size) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/__syscall_sigaction.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/__syscall_sigaction.c new file mode 100644 index 00000000..ae0f01e9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/__syscall_sigaction.c @@ -0,0 +1,19 @@ +/* vi: set sw=4 ts=4: */ +/* + * __syscall_sigaction() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +#ifndef __NR_rt_sigaction +#define __NR___syscall_sigaction __NR_sigaction +#include +int __syscall_sigaction (int __signum, const struct sigaction *__act, struct sigaction *__oldact) attribute_hidden; +_syscall3(int, __syscall_sigaction, int, signum, const struct sigaction *, + act, struct sigaction *, oldact) +#endif + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/_exit.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/_exit.c new file mode 100644 index 00000000..51117d10 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/_exit.c @@ -0,0 +1,34 @@ +/* vi: set sw=4 ts=4: */ +/* + * exit syscall for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include +#include +#ifdef __UCLIBC_HAS_THREADS_NATIVE__ +#include +#endif + + +void attribute_noreturn _exit(int status) +{ + /* The loop is added only to keep gcc happy. */ + while(1) + { +#ifdef __UCLIBC_HAS_THREADS_NATIVE__ +# ifdef __NR_exit_group + INLINE_SYSCALL(exit_group, 1, status); +# endif +#endif + INLINE_SYSCALL(exit, 1, status); + } +} +libc_hidden_def(_exit) +weak_alias(_exit,_Exit) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/access.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/access.c new file mode 100644 index 00000000..a075d421 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/access.c @@ -0,0 +1,12 @@ +/* vi: set sw=4 ts=4: */ +/* + * access() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +_syscall2(int, access, const char *, pathname, int, mode) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/acct.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/acct.c new file mode 100644 index 00000000..e0a43200 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/acct.c @@ -0,0 +1,14 @@ +/* vi: set sw=4 ts=4: */ +/* + * acct() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#if defined __USE_BSD || (defined __USE_XOPEN && !defined __USE_UNIX98) +_syscall1(int, acct, const char *, filename) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/adjtimex.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/adjtimex.c new file mode 100644 index 00000000..45cb3849 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/adjtimex.c @@ -0,0 +1,18 @@ +/* vi: set sw=4 ts=4: */ +/* + * adjtimex() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + + +_syscall1(int, adjtimex, struct timex *, buf) +libc_hidden_def(adjtimex) +#if defined __UCLIBC_NTP_LEGACY__ +strong_alias(adjtimex,ntp_adjtime) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/alarm.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/alarm.c new file mode 100644 index 00000000..cfd68fe1 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/alarm.c @@ -0,0 +1,39 @@ +/* vi: set sw=4 ts=4: */ +/* + * alarm() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + + +#ifdef __NR_alarm +_syscall1(unsigned int, alarm, unsigned int, seconds) +#else +#include + + +unsigned int alarm(unsigned int seconds) +{ + struct itimerval old, new; + unsigned int retval; + + new.it_value.tv_usec = 0; + new.it_interval.tv_sec = 0; + new.it_interval.tv_usec = 0; + new.it_value.tv_sec = (long int) seconds; + if (setitimer(ITIMER_REAL, &new, &old) < 0) { + return 0; + } + retval = old.it_value.tv_sec; + if (old.it_value.tv_usec) { + ++retval; + } + return retval; +} +#endif +libc_hidden_def(alarm) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/arch_prctl.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/arch_prctl.c new file mode 100644 index 00000000..5816f539 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/arch_prctl.c @@ -0,0 +1,15 @@ +/* vi: set sw=4 ts=4: */ +/* + * arch_prctl() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +#ifdef __NR_arch_prctl +extern int arch_prctl(int code, unsigned long addr); +_syscall2(int, arch_prctl, int, code, unsigned long, addr) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bdflush.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bdflush.c new file mode 100644 index 00000000..687a8f9a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bdflush.c @@ -0,0 +1,21 @@ +/* vi: set sw=4 ts=4: */ +/* + * bdflush() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +#ifdef __NR_bdflush +_syscall2(int, bdflush, int, __func, long int, __data) +#else +int bdflush(int __func, long int __data) +{ + __set_errno(ENOSYS); + return -1; +} +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/atomic.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/atomic.h new file mode 100644 index 00000000..6245130a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/atomic.h @@ -0,0 +1,43 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _BITS_ATOMIC_H +#define _BITS_ATOMIC_H 1 + +/* We have by default no support for atomic operations. So define + them non-atomic. If this is a problem somebody will have to come + up with real definitions. */ + +/* The only basic operation needed is compare and exchange. */ +#define atomic_compare_and_exchange_val_acq(mem, newval, oldval) \ + ({ __typeof (mem) __gmemp = (mem); \ + __typeof (*mem) __gret = *__gmemp; \ + __typeof (*mem) __gnewval = (newval); \ + \ + if (__gret == (oldval)) \ + *__gmemp = __gnewval; \ + __gret; }) + +#define atomic_compare_and_exchange_bool_acq(mem, newval, oldval) \ + ({ __typeof (mem) __gmemp = (mem); \ + __typeof (*mem) __gnewval = (newval); \ + \ + *__gmemp == (oldval) ? (*__gmemp = __gnewval, 0) : 1; }) + +#endif /* bits/atomic.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/byteswap-common.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/byteswap-common.h new file mode 100644 index 00000000..8586ed00 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/byteswap-common.h @@ -0,0 +1,108 @@ +/* Macros to swap the order of bytes in integer values. + Copyright (C) 1997,1998,2000,2001,2002,2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#if !defined _BYTESWAP_H && !defined _NETINET_IN_H +# error "Never use directly; include instead." +#endif + +#ifndef _BITS_BYTESWAP_H +#define _BITS_BYTESWAP_H 1 + +/* Swap bytes in 16 bit value. */ +#define __bswap_constant_16(x) \ + ((((x) >> 8) & 0xffu) | (((x) & 0xffu) << 8)) + +#ifndef __bswap_non_constant_16 +# define __bswap_non_constant_16(x) __bswap_constant_16(x) +#endif +#ifdef __GNUC__ +# define __bswap_16(x) \ + (__extension__ \ + ({ unsigned short int __bsv, __bsx = (x); \ + if (__builtin_constant_p (__bsx)) \ + __bsv = __bswap_constant_16 (__bsx); \ + else \ + __bsv = __bswap_non_constant_16 (__bsx); \ + __bsv; })) +#else +static __inline unsigned short int +__bswap_16 (unsigned short int __bsx) +{ + return __bswap_constant_16 (__bsx); +} +#endif + +/* Swap bytes in 32 bit value. */ +#define __bswap_constant_32(x) \ + ((((x) & 0xff000000u) >> 24) | (((x) & 0x00ff0000u) >> 8) | \ + (((x) & 0x0000ff00u) << 8) | (((x) & 0x000000ffu) << 24)) + +#ifndef __bswap_non_constant_32 +# define __bswap_non_constant_32(x) __bswap_constant_32(x) +#endif +#ifdef __GNUC__ +# define __bswap_32(x) \ + (__extension__ \ + ({ unsigned int __bsv, __bsx = (x); \ + if (__builtin_constant_p (__bsx)) \ + __bsv = __bswap_constant_32 (__bsx); \ + else \ + __bsv = __bswap_non_constant_32 (__bsx); \ + __bsv; })) +#else +static __inline unsigned int +__bswap_32 (unsigned int __bsx) +{ + return __bswap_constant_32 (__bsx); +} +#endif + +#if defined __GNUC__ && __GNUC__ >= 2 +/* Swap bytes in 64 bit value. */ +# define __bswap_constant_64(x) \ + ((((x) & 0xff00000000000000ull) >> 56) \ + | (((x) & 0x00ff000000000000ull) >> 40) \ + | (((x) & 0x0000ff0000000000ull) >> 24) \ + | (((x) & 0x000000ff00000000ull) >> 8) \ + | (((x) & 0x00000000ff000000ull) << 8) \ + | (((x) & 0x0000000000ff0000ull) << 24) \ + | (((x) & 0x000000000000ff00ull) << 40) \ + | (((x) & 0x00000000000000ffull) << 56)) + +# ifndef __bswap_non_constant_64 +# define __bswap_non_constant_64(x) \ + (__extension__ \ + ({ union { __extension__ unsigned long long int __ll; \ + unsigned int __l[2]; } __w, __r; \ + __w.__ll = (x); \ + __r.__l[0] = __bswap_non_constant_32 (__w.__l[1]); \ + __r.__l[1] = __bswap_non_constant_32 (__w.__l[0]); \ + __r.__ll; })) +# endif +# define __bswap_64(x) \ + (__extension__ \ + ({ __extension__ unsigned long long int __ll; \ + if (__builtin_constant_p (x)) \ + __ll = __bswap_constant_64 (x); \ + else \ + __ll = __bswap_non_constant_64 (x); \ + __ll; })) +#endif + +#endif /* _BITS_BYTESWAP_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/byteswap.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/byteswap.h new file mode 100644 index 00000000..3f02506b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/byteswap.h @@ -0,0 +1 @@ +#include diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/cmathcalls.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/cmathcalls.h new file mode 100644 index 00000000..762c1e3c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/cmathcalls.h @@ -0,0 +1,181 @@ +/* Prototype declarations for complex math functions; + helper file for . + Copyright (C) 1997, 1998, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* NOTE: Because of the special way this file is used by , this + file must NOT be protected from multiple inclusion as header files + usually are. + + This file provides prototype declarations for the math functions. + Most functions are declared using the macro: + + __MATHCALL (NAME, (ARGS...)); + + This means there is a function `NAME' returning `double' and a function + `NAMEf' returning `float'. Each place `_Mdouble_' appears in the + prototype, that is actually `double' in the prototype for `NAME' and + `float' in the prototype for `NAMEf'. Reentrant variant functions are + called `NAME_r' and `NAMEf_r'. + + Functions returning other types like `int' are declared using the macro: + + __MATHDECL (TYPE, NAME, (ARGS...)); + + This is just like __MATHCALL but for a function returning `TYPE' + instead of `_Mdouble_'. In all of these cases, there is still + both a `NAME' and a `NAMEf' that takes `float' arguments. */ + +#ifndef _COMPLEX_H +#error "Never use directly; include instead." +#endif + +#define _Mdouble_complex_ _Mdouble_ _Complex + + +/* Trigonometric functions. */ + +/* Arc cosine of Z. */ +__MATHCALL (cacos, (_Mdouble_complex_ __z)); +libm_hidden_proto(cacos) +/* Arc sine of Z. */ +__MATHCALL (casin, (_Mdouble_complex_ __z)); +libm_hidden_proto(casin) +/* Arc tangent of Z. */ +__MATHCALL (catan, (_Mdouble_complex_ __z)); +libm_hidden_proto(catan) + +/* Cosine of Z. */ +__MATHCALL (ccos, (_Mdouble_complex_ __z)); +libm_hidden_proto(ccos) +/* Sine of Z. */ +__MATHCALL (csin, (_Mdouble_complex_ __z)); +libm_hidden_proto(csin) +/* Tangent of Z. */ +__MATHCALL (ctan, (_Mdouble_complex_ __z)); +libm_hidden_proto(ctan) + + +/* Hyperbolic functions. */ + +/* Hyperbolic arc cosine of Z. */ +__MATHCALL (cacosh, (_Mdouble_complex_ __z)); +libm_hidden_proto(cacosh) +/* Hyperbolic arc sine of Z. */ +__MATHCALL (casinh, (_Mdouble_complex_ __z)); +libm_hidden_proto(casinh) +/* Hyperbolic arc tangent of Z. */ +__MATHCALL (catanh, (_Mdouble_complex_ __z)); +libm_hidden_proto(catanh) + +/* Hyperbolic cosine of Z. */ +__MATHCALL (ccosh, (_Mdouble_complex_ __z)); +libm_hidden_proto(ccosh) +/* Hyperbolic sine of Z. */ +__MATHCALL (csinh, (_Mdouble_complex_ __z)); +libm_hidden_proto(ccosh) +/* Hyperbolic tangent of Z. */ +__MATHCALL (ctanh, (_Mdouble_complex_ __z)); +libm_hidden_proto(ctanh) + + +/* Exponential and logarithmic functions. */ + +/* Exponential function of Z. */ +__MATHCALL (cexp, (_Mdouble_complex_ __z)); +libm_hidden_proto(cexp) + +/* Natural logarithm of Z. */ +__MATHCALL (clog, (_Mdouble_complex_ __z)); +libm_hidden_proto(clog) + +#ifdef __USE_GNU +/* The base 10 logarithm is not defined by the standard but to implement + the standard C++ library it is handy. */ +__MATHCALL (clog10, (_Mdouble_complex_ __z)); +libm_hidden_proto(clog10) +#endif + +/* Power functions. */ + +/* Return X to the Y power. */ +__MATHCALL (cpow, (_Mdouble_complex_ __x, _Mdouble_complex_ __y)); +libm_hidden_proto(cpow) + +/* Return the square root of Z. */ +__MATHCALL (csqrt, (_Mdouble_complex_ __z)); +libm_hidden_proto(csqrt) + + +/* Absolute value, conjugates, and projection. */ + +/* Absolute value of Z. */ +__MATHDECL (_Mdouble_,cabs, (_Mdouble_complex_ __z)); +libm_hidden_proto(cabs) + +/* Argument value of Z. */ +__MATHDECL (_Mdouble_,carg, (_Mdouble_complex_ __z)); +libm_hidden_proto(carg) + +/* Complex conjugate of Z. */ +__MATHCALL (conj, (_Mdouble_complex_ __z)); +libm_hidden_proto(conj) + +/* Projection of Z onto the Riemann sphere. */ +__MATHCALL (cproj, (_Mdouble_complex_ __z)); +libm_hidden_proto(cproj) + + +/* Decomposing complex values. */ + +/* Imaginary part of Z. */ +__MATHDECL (_Mdouble_,cimag, (_Mdouble_complex_ __z)); +libm_hidden_proto(cimag) + +/* Real part of Z. */ +__MATHDECL (_Mdouble_,creal, (_Mdouble_complex_ __z)); +libm_hidden_proto(creal) + + +/* Now some optimized versions. GCC has handy notations for these + functions. Recent GCC handles these as builtin functions so does + not need inlines. */ +#if defined __GNUC__ && !__GNUC_PREREQ (2, 97) && defined __OPTIMIZE__ + +/* Imaginary part of Z. */ +__extern_inline _Mdouble_ +__MATH_PRECNAME(cimag) (_Mdouble_complex_ __z) __THROW +{ + return __imag__ __z; +} + +/* Real part of Z. */ +__extern_inline _Mdouble_ +__MATH_PRECNAME(creal) (_Mdouble_complex_ __z) __THROW +{ + return __real__ __z; +} + +/* Complex conjugate of Z. */ +__extern_inline _Mdouble_complex_ +__MATH_PRECNAME(conj) (_Mdouble_complex_ __z) __THROW +{ + return __extension__ ~__z; +} + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/confname.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/confname.h new file mode 100644 index 00000000..97ddd475 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/confname.h @@ -0,0 +1,681 @@ +/* `sysconf', `pathconf', and `confstr' NAME values. Generic version. + Copyright (C) 1993,1995-1998,2000,2001,2003,2004,2007,2009 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _UNISTD_H +# error "Never use directly; include instead." +#endif + +/* Values for the NAME argument to `pathconf' and `fpathconf'. */ +enum + { + _PC_LINK_MAX, +#define _PC_LINK_MAX _PC_LINK_MAX + _PC_MAX_CANON, +#define _PC_MAX_CANON _PC_MAX_CANON + _PC_MAX_INPUT, +#define _PC_MAX_INPUT _PC_MAX_INPUT + _PC_NAME_MAX, +#define _PC_NAME_MAX _PC_NAME_MAX + _PC_PATH_MAX, +#define _PC_PATH_MAX _PC_PATH_MAX + _PC_PIPE_BUF, +#define _PC_PIPE_BUF _PC_PIPE_BUF + _PC_CHOWN_RESTRICTED, +#define _PC_CHOWN_RESTRICTED _PC_CHOWN_RESTRICTED + _PC_NO_TRUNC, +#define _PC_NO_TRUNC _PC_NO_TRUNC + _PC_VDISABLE, +#define _PC_VDISABLE _PC_VDISABLE + _PC_SYNC_IO, +#define _PC_SYNC_IO _PC_SYNC_IO + _PC_ASYNC_IO, +#define _PC_ASYNC_IO _PC_ASYNC_IO + _PC_PRIO_IO, +#define _PC_PRIO_IO _PC_PRIO_IO + _PC_SOCK_MAXBUF, +#define _PC_SOCK_MAXBUF _PC_SOCK_MAXBUF + _PC_FILESIZEBITS, +#define _PC_FILESIZEBITS _PC_FILESIZEBITS + _PC_REC_INCR_XFER_SIZE, +#define _PC_REC_INCR_XFER_SIZE _PC_REC_INCR_XFER_SIZE + _PC_REC_MAX_XFER_SIZE, +#define _PC_REC_MAX_XFER_SIZE _PC_REC_MAX_XFER_SIZE + _PC_REC_MIN_XFER_SIZE, +#define _PC_REC_MIN_XFER_SIZE _PC_REC_MIN_XFER_SIZE + _PC_REC_XFER_ALIGN, +#define _PC_REC_XFER_ALIGN _PC_REC_XFER_ALIGN + _PC_ALLOC_SIZE_MIN, +#define _PC_ALLOC_SIZE_MIN _PC_ALLOC_SIZE_MIN + _PC_SYMLINK_MAX, +#define _PC_SYMLINK_MAX _PC_SYMLINK_MAX + _PC_2_SYMLINKS +#define _PC_2_SYMLINKS _PC_2_SYMLINKS + }; + +/* Values for the argument to `sysconf'. */ +enum + { + _SC_ARG_MAX, +#define _SC_ARG_MAX _SC_ARG_MAX + _SC_CHILD_MAX, +#define _SC_CHILD_MAX _SC_CHILD_MAX + _SC_CLK_TCK, +#define _SC_CLK_TCK _SC_CLK_TCK + _SC_NGROUPS_MAX, +#define _SC_NGROUPS_MAX _SC_NGROUPS_MAX + _SC_OPEN_MAX, +#define _SC_OPEN_MAX _SC_OPEN_MAX + _SC_STREAM_MAX, +#define _SC_STREAM_MAX _SC_STREAM_MAX + _SC_TZNAME_MAX, +#define _SC_TZNAME_MAX _SC_TZNAME_MAX + _SC_JOB_CONTROL, +#define _SC_JOB_CONTROL _SC_JOB_CONTROL + _SC_SAVED_IDS, +#define _SC_SAVED_IDS _SC_SAVED_IDS + _SC_REALTIME_SIGNALS, +#define _SC_REALTIME_SIGNALS _SC_REALTIME_SIGNALS + _SC_PRIORITY_SCHEDULING, +#define _SC_PRIORITY_SCHEDULING _SC_PRIORITY_SCHEDULING + _SC_TIMERS, +#define _SC_TIMERS _SC_TIMERS + _SC_ASYNCHRONOUS_IO, +#define _SC_ASYNCHRONOUS_IO _SC_ASYNCHRONOUS_IO + _SC_PRIORITIZED_IO, +#define _SC_PRIORITIZED_IO _SC_PRIORITIZED_IO + _SC_SYNCHRONIZED_IO, +#define _SC_SYNCHRONIZED_IO _SC_SYNCHRONIZED_IO + _SC_FSYNC, +#define _SC_FSYNC _SC_FSYNC + _SC_MAPPED_FILES, +#define _SC_MAPPED_FILES _SC_MAPPED_FILES + _SC_MEMLOCK, +#define _SC_MEMLOCK _SC_MEMLOCK + _SC_MEMLOCK_RANGE, +#define _SC_MEMLOCK_RANGE _SC_MEMLOCK_RANGE + _SC_MEMORY_PROTECTION, +#define _SC_MEMORY_PROTECTION _SC_MEMORY_PROTECTION + _SC_MESSAGE_PASSING, +#define _SC_MESSAGE_PASSING _SC_MESSAGE_PASSING + _SC_SEMAPHORES, +#define _SC_SEMAPHORES _SC_SEMAPHORES + _SC_SHARED_MEMORY_OBJECTS, +#define _SC_SHARED_MEMORY_OBJECTS _SC_SHARED_MEMORY_OBJECTS + _SC_AIO_LISTIO_MAX, +#define _SC_AIO_LISTIO_MAX _SC_AIO_LISTIO_MAX + _SC_AIO_MAX, +#define _SC_AIO_MAX _SC_AIO_MAX + _SC_AIO_PRIO_DELTA_MAX, +#define _SC_AIO_PRIO_DELTA_MAX _SC_AIO_PRIO_DELTA_MAX + _SC_DELAYTIMER_MAX, +#define _SC_DELAYTIMER_MAX _SC_DELAYTIMER_MAX + _SC_MQ_OPEN_MAX, +#define _SC_MQ_OPEN_MAX _SC_MQ_OPEN_MAX + _SC_MQ_PRIO_MAX, +#define _SC_MQ_PRIO_MAX _SC_MQ_PRIO_MAX + _SC_VERSION, +#define _SC_VERSION _SC_VERSION + _SC_PAGESIZE, +#define _SC_PAGESIZE _SC_PAGESIZE +#define _SC_PAGE_SIZE _SC_PAGESIZE + _SC_RTSIG_MAX, +#define _SC_RTSIG_MAX _SC_RTSIG_MAX + _SC_SEM_NSEMS_MAX, +#define _SC_SEM_NSEMS_MAX _SC_SEM_NSEMS_MAX + _SC_SEM_VALUE_MAX, +#define _SC_SEM_VALUE_MAX _SC_SEM_VALUE_MAX + _SC_SIGQUEUE_MAX, +#define _SC_SIGQUEUE_MAX _SC_SIGQUEUE_MAX + _SC_TIMER_MAX, +#define _SC_TIMER_MAX _SC_TIMER_MAX + + /* Values for the argument to `sysconf' + corresponding to _POSIX2_* symbols. */ + _SC_BC_BASE_MAX, +#define _SC_BC_BASE_MAX _SC_BC_BASE_MAX + _SC_BC_DIM_MAX, +#define _SC_BC_DIM_MAX _SC_BC_DIM_MAX + _SC_BC_SCALE_MAX, +#define _SC_BC_SCALE_MAX _SC_BC_SCALE_MAX + _SC_BC_STRING_MAX, +#define _SC_BC_STRING_MAX _SC_BC_STRING_MAX + _SC_COLL_WEIGHTS_MAX, +#define _SC_COLL_WEIGHTS_MAX _SC_COLL_WEIGHTS_MAX + _SC_EQUIV_CLASS_MAX, +#define _SC_EQUIV_CLASS_MAX _SC_EQUIV_CLASS_MAX + _SC_EXPR_NEST_MAX, +#define _SC_EXPR_NEST_MAX _SC_EXPR_NEST_MAX + _SC_LINE_MAX, +#define _SC_LINE_MAX _SC_LINE_MAX + _SC_RE_DUP_MAX, +#define _SC_RE_DUP_MAX _SC_RE_DUP_MAX + _SC_CHARCLASS_NAME_MAX, +#define _SC_CHARCLASS_NAME_MAX _SC_CHARCLASS_NAME_MAX + + _SC_2_VERSION, +#define _SC_2_VERSION _SC_2_VERSION + _SC_2_C_BIND, +#define _SC_2_C_BIND _SC_2_C_BIND + _SC_2_C_DEV, +#define _SC_2_C_DEV _SC_2_C_DEV + _SC_2_FORT_DEV, +#define _SC_2_FORT_DEV _SC_2_FORT_DEV + _SC_2_FORT_RUN, +#define _SC_2_FORT_RUN _SC_2_FORT_RUN + _SC_2_SW_DEV, +#define _SC_2_SW_DEV _SC_2_SW_DEV + _SC_2_LOCALEDEF, +#define _SC_2_LOCALEDEF _SC_2_LOCALEDEF + + _SC_PII, +#define _SC_PII _SC_PII + _SC_PII_XTI, +#define _SC_PII_XTI _SC_PII_XTI + _SC_PII_SOCKET, +#define _SC_PII_SOCKET _SC_PII_SOCKET + _SC_PII_INTERNET, +#define _SC_PII_INTERNET _SC_PII_INTERNET + _SC_PII_OSI, +#define _SC_PII_OSI _SC_PII_OSI + _SC_POLL, +#define _SC_POLL _SC_POLL + _SC_SELECT, +#define _SC_SELECT _SC_SELECT + _SC_UIO_MAXIOV, +#define _SC_UIO_MAXIOV _SC_UIO_MAXIOV + _SC_IOV_MAX = _SC_UIO_MAXIOV, +#define _SC_IOV_MAX _SC_IOV_MAX + _SC_PII_INTERNET_STREAM, +#define _SC_PII_INTERNET_STREAM _SC_PII_INTERNET_STREAM + _SC_PII_INTERNET_DGRAM, +#define _SC_PII_INTERNET_DGRAM _SC_PII_INTERNET_DGRAM + _SC_PII_OSI_COTS, +#define _SC_PII_OSI_COTS _SC_PII_OSI_COTS + _SC_PII_OSI_CLTS, +#define _SC_PII_OSI_CLTS _SC_PII_OSI_CLTS + _SC_PII_OSI_M, +#define _SC_PII_OSI_M _SC_PII_OSI_M + _SC_T_IOV_MAX, +#define _SC_T_IOV_MAX _SC_T_IOV_MAX + + /* Values according to POSIX 1003.1c (POSIX threads). */ + _SC_THREADS, +#define _SC_THREADS _SC_THREADS + _SC_THREAD_SAFE_FUNCTIONS, +#define _SC_THREAD_SAFE_FUNCTIONS _SC_THREAD_SAFE_FUNCTIONS + _SC_GETGR_R_SIZE_MAX, +#define _SC_GETGR_R_SIZE_MAX _SC_GETGR_R_SIZE_MAX + _SC_GETPW_R_SIZE_MAX, +#define _SC_GETPW_R_SIZE_MAX _SC_GETPW_R_SIZE_MAX + _SC_LOGIN_NAME_MAX, +#define _SC_LOGIN_NAME_MAX _SC_LOGIN_NAME_MAX + _SC_TTY_NAME_MAX, +#define _SC_TTY_NAME_MAX _SC_TTY_NAME_MAX + _SC_THREAD_DESTRUCTOR_ITERATIONS, +#define _SC_THREAD_DESTRUCTOR_ITERATIONS _SC_THREAD_DESTRUCTOR_ITERATIONS + _SC_THREAD_KEYS_MAX, +#define _SC_THREAD_KEYS_MAX _SC_THREAD_KEYS_MAX + _SC_THREAD_STACK_MIN, +#define _SC_THREAD_STACK_MIN _SC_THREAD_STACK_MIN + _SC_THREAD_THREADS_MAX, +#define _SC_THREAD_THREADS_MAX _SC_THREAD_THREADS_MAX + _SC_THREAD_ATTR_STACKADDR, +#define _SC_THREAD_ATTR_STACKADDR _SC_THREAD_ATTR_STACKADDR + _SC_THREAD_ATTR_STACKSIZE, +#define _SC_THREAD_ATTR_STACKSIZE _SC_THREAD_ATTR_STACKSIZE + _SC_THREAD_PRIORITY_SCHEDULING, +#define _SC_THREAD_PRIORITY_SCHEDULING _SC_THREAD_PRIORITY_SCHEDULING + _SC_THREAD_PRIO_INHERIT, +#define _SC_THREAD_PRIO_INHERIT _SC_THREAD_PRIO_INHERIT + _SC_THREAD_PRIO_PROTECT, +#define _SC_THREAD_PRIO_PROTECT _SC_THREAD_PRIO_PROTECT + _SC_THREAD_PROCESS_SHARED, +#define _SC_THREAD_PROCESS_SHARED _SC_THREAD_PROCESS_SHARED + + _SC_NPROCESSORS_CONF, +#define _SC_NPROCESSORS_CONF _SC_NPROCESSORS_CONF + _SC_NPROCESSORS_ONLN, +#define _SC_NPROCESSORS_ONLN _SC_NPROCESSORS_ONLN + _SC_PHYS_PAGES, +#define _SC_PHYS_PAGES _SC_PHYS_PAGES + _SC_AVPHYS_PAGES, +#define _SC_AVPHYS_PAGES _SC_AVPHYS_PAGES + _SC_ATEXIT_MAX, +#define _SC_ATEXIT_MAX _SC_ATEXIT_MAX + _SC_PASS_MAX, +#define _SC_PASS_MAX _SC_PASS_MAX + + _SC_XOPEN_VERSION, +#define _SC_XOPEN_VERSION _SC_XOPEN_VERSION + _SC_XOPEN_XCU_VERSION, +#define _SC_XOPEN_XCU_VERSION _SC_XOPEN_XCU_VERSION + _SC_XOPEN_UNIX, +#define _SC_XOPEN_UNIX _SC_XOPEN_UNIX + _SC_XOPEN_CRYPT, +#define _SC_XOPEN_CRYPT _SC_XOPEN_CRYPT + _SC_XOPEN_ENH_I18N, +#define _SC_XOPEN_ENH_I18N _SC_XOPEN_ENH_I18N + _SC_XOPEN_SHM, +#define _SC_XOPEN_SHM _SC_XOPEN_SHM + + _SC_2_CHAR_TERM, +#define _SC_2_CHAR_TERM _SC_2_CHAR_TERM + _SC_2_C_VERSION, +#define _SC_2_C_VERSION _SC_2_C_VERSION + _SC_2_UPE, +#define _SC_2_UPE _SC_2_UPE + + _SC_XOPEN_XPG2, +#define _SC_XOPEN_XPG2 _SC_XOPEN_XPG2 + _SC_XOPEN_XPG3, +#define _SC_XOPEN_XPG3 _SC_XOPEN_XPG3 + _SC_XOPEN_XPG4, +#define _SC_XOPEN_XPG4 _SC_XOPEN_XPG4 + + _SC_CHAR_BIT, +#define _SC_CHAR_BIT _SC_CHAR_BIT + _SC_CHAR_MAX, +#define _SC_CHAR_MAX _SC_CHAR_MAX + _SC_CHAR_MIN, +#define _SC_CHAR_MIN _SC_CHAR_MIN + _SC_INT_MAX, +#define _SC_INT_MAX _SC_INT_MAX + _SC_INT_MIN, +#define _SC_INT_MIN _SC_INT_MIN + _SC_LONG_BIT, +#define _SC_LONG_BIT _SC_LONG_BIT + _SC_WORD_BIT, +#define _SC_WORD_BIT _SC_WORD_BIT + _SC_MB_LEN_MAX, +#define _SC_MB_LEN_MAX _SC_MB_LEN_MAX + _SC_NZERO, +#define _SC_NZERO _SC_NZERO + _SC_SSIZE_MAX, +#define _SC_SSIZE_MAX _SC_SSIZE_MAX + _SC_SCHAR_MAX, +#define _SC_SCHAR_MAX _SC_SCHAR_MAX + _SC_SCHAR_MIN, +#define _SC_SCHAR_MIN _SC_SCHAR_MIN + _SC_SHRT_MAX, +#define _SC_SHRT_MAX _SC_SHRT_MAX + _SC_SHRT_MIN, +#define _SC_SHRT_MIN _SC_SHRT_MIN + _SC_UCHAR_MAX, +#define _SC_UCHAR_MAX _SC_UCHAR_MAX + _SC_UINT_MAX, +#define _SC_UINT_MAX _SC_UINT_MAX + _SC_ULONG_MAX, +#define _SC_ULONG_MAX _SC_ULONG_MAX + _SC_USHRT_MAX, +#define _SC_USHRT_MAX _SC_USHRT_MAX + + _SC_NL_ARGMAX, +#define _SC_NL_ARGMAX _SC_NL_ARGMAX + _SC_NL_LANGMAX, +#define _SC_NL_LANGMAX _SC_NL_LANGMAX + _SC_NL_MSGMAX, +#define _SC_NL_MSGMAX _SC_NL_MSGMAX + _SC_NL_NMAX, +#define _SC_NL_NMAX _SC_NL_NMAX + _SC_NL_SETMAX, +#define _SC_NL_SETMAX _SC_NL_SETMAX + _SC_NL_TEXTMAX, +#define _SC_NL_TEXTMAX _SC_NL_TEXTMAX + + _SC_XBS5_ILP32_OFF32, +#define _SC_XBS5_ILP32_OFF32 _SC_XBS5_ILP32_OFF32 + _SC_XBS5_ILP32_OFFBIG, +#define _SC_XBS5_ILP32_OFFBIG _SC_XBS5_ILP32_OFFBIG + _SC_XBS5_LP64_OFF64, +#define _SC_XBS5_LP64_OFF64 _SC_XBS5_LP64_OFF64 + _SC_XBS5_LPBIG_OFFBIG, +#define _SC_XBS5_LPBIG_OFFBIG _SC_XBS5_LPBIG_OFFBIG + + _SC_XOPEN_LEGACY, +#define _SC_XOPEN_LEGACY _SC_XOPEN_LEGACY + _SC_XOPEN_REALTIME, +#define _SC_XOPEN_REALTIME _SC_XOPEN_REALTIME + _SC_XOPEN_REALTIME_THREADS, +#define _SC_XOPEN_REALTIME_THREADS _SC_XOPEN_REALTIME_THREADS + + _SC_ADVISORY_INFO, +#define _SC_ADVISORY_INFO _SC_ADVISORY_INFO + _SC_BARRIERS, +#define _SC_BARRIERS _SC_BARRIERS + _SC_BASE, +#define _SC_BASE _SC_BASE + _SC_C_LANG_SUPPORT, +#define _SC_C_LANG_SUPPORT _SC_C_LANG_SUPPORT + _SC_C_LANG_SUPPORT_R, +#define _SC_C_LANG_SUPPORT_R _SC_C_LANG_SUPPORT_R + _SC_CLOCK_SELECTION, +#define _SC_CLOCK_SELECTION _SC_CLOCK_SELECTION + _SC_CPUTIME, +#define _SC_CPUTIME _SC_CPUTIME + _SC_THREAD_CPUTIME, +#define _SC_THREAD_CPUTIME _SC_THREAD_CPUTIME + _SC_DEVICE_IO, +#define _SC_DEVICE_IO _SC_DEVICE_IO + _SC_DEVICE_SPECIFIC, +#define _SC_DEVICE_SPECIFIC _SC_DEVICE_SPECIFIC + _SC_DEVICE_SPECIFIC_R, +#define _SC_DEVICE_SPECIFIC_R _SC_DEVICE_SPECIFIC_R + _SC_FD_MGMT, +#define _SC_FD_MGMT _SC_FD_MGMT + _SC_FIFO, +#define _SC_FIFO _SC_FIFO + _SC_PIPE, +#define _SC_PIPE _SC_PIPE + _SC_FILE_ATTRIBUTES, +#define _SC_FILE_ATTRIBUTES _SC_FILE_ATTRIBUTES + _SC_FILE_LOCKING, +#define _SC_FILE_LOCKING _SC_FILE_LOCKING + _SC_FILE_SYSTEM, +#define _SC_FILE_SYSTEM _SC_FILE_SYSTEM + _SC_MONOTONIC_CLOCK, +#define _SC_MONOTONIC_CLOCK _SC_MONOTONIC_CLOCK + _SC_MULTI_PROCESS, +#define _SC_MULTI_PROCESS _SC_MULTI_PROCESS + _SC_SINGLE_PROCESS, +#define _SC_SINGLE_PROCESS _SC_SINGLE_PROCESS + _SC_NETWORKING, +#define _SC_NETWORKING _SC_NETWORKING + _SC_READER_WRITER_LOCKS, +#define _SC_READER_WRITER_LOCKS _SC_READER_WRITER_LOCKS + _SC_SPIN_LOCKS, +#define _SC_SPIN_LOCKS _SC_SPIN_LOCKS + _SC_REGEXP, +#define _SC_REGEXP _SC_REGEXP + _SC_REGEX_VERSION, +#define _SC_REGEX_VERSION _SC_REGEX_VERSION + _SC_SHELL, +#define _SC_SHELL _SC_SHELL + _SC_SIGNALS, +#define _SC_SIGNALS _SC_SIGNALS + _SC_SPAWN, +#define _SC_SPAWN _SC_SPAWN + _SC_SPORADIC_SERVER, +#define _SC_SPORADIC_SERVER _SC_SPORADIC_SERVER + _SC_THREAD_SPORADIC_SERVER, +#define _SC_THREAD_SPORADIC_SERVER _SC_THREAD_SPORADIC_SERVER + _SC_SYSTEM_DATABASE, +#define _SC_SYSTEM_DATABASE _SC_SYSTEM_DATABASE + _SC_SYSTEM_DATABASE_R, +#define _SC_SYSTEM_DATABASE_R _SC_SYSTEM_DATABASE_R + _SC_TIMEOUTS, +#define _SC_TIMEOUTS _SC_TIMEOUTS + _SC_TYPED_MEMORY_OBJECTS, +#define _SC_TYPED_MEMORY_OBJECTS _SC_TYPED_MEMORY_OBJECTS + _SC_USER_GROUPS, +#define _SC_USER_GROUPS _SC_USER_GROUPS + _SC_USER_GROUPS_R, +#define _SC_USER_GROUPS_R _SC_USER_GROUPS_R + _SC_2_PBS, +#define _SC_2_PBS _SC_2_PBS + _SC_2_PBS_ACCOUNTING, +#define _SC_2_PBS_ACCOUNTING _SC_2_PBS_ACCOUNTING + _SC_2_PBS_LOCATE, +#define _SC_2_PBS_LOCATE _SC_2_PBS_LOCATE + _SC_2_PBS_MESSAGE, +#define _SC_2_PBS_MESSAGE _SC_2_PBS_MESSAGE + _SC_2_PBS_TRACK, +#define _SC_2_PBS_TRACK _SC_2_PBS_TRACK + _SC_SYMLOOP_MAX, +#define _SC_SYMLOOP_MAX _SC_SYMLOOP_MAX + _SC_STREAMS, +#define _SC_STREAMS _SC_STREAMS + _SC_2_PBS_CHECKPOINT, +#define _SC_2_PBS_CHECKPOINT _SC_2_PBS_CHECKPOINT + + _SC_V6_ILP32_OFF32, +#define _SC_V6_ILP32_OFF32 _SC_V6_ILP32_OFF32 + _SC_V6_ILP32_OFFBIG, +#define _SC_V6_ILP32_OFFBIG _SC_V6_ILP32_OFFBIG + _SC_V6_LP64_OFF64, +#define _SC_V6_LP64_OFF64 _SC_V6_LP64_OFF64 + _SC_V6_LPBIG_OFFBIG, +#define _SC_V6_LPBIG_OFFBIG _SC_V6_LPBIG_OFFBIG + + _SC_HOST_NAME_MAX, +#define _SC_HOST_NAME_MAX _SC_HOST_NAME_MAX + _SC_TRACE, +#define _SC_TRACE _SC_TRACE + _SC_TRACE_EVENT_FILTER, +#define _SC_TRACE_EVENT_FILTER _SC_TRACE_EVENT_FILTER + _SC_TRACE_INHERIT, +#define _SC_TRACE_INHERIT _SC_TRACE_INHERIT + _SC_TRACE_LOG, +#define _SC_TRACE_LOG _SC_TRACE_LOG + + _SC_LEVEL1_ICACHE_SIZE, +#define _SC_LEVEL1_ICACHE_SIZE _SC_LEVEL1_ICACHE_SIZE + _SC_LEVEL1_ICACHE_ASSOC, +#define _SC_LEVEL1_ICACHE_ASSOC _SC_LEVEL1_ICACHE_ASSOC + _SC_LEVEL1_ICACHE_LINESIZE, +#define _SC_LEVEL1_ICACHE_LINESIZE _SC_LEVEL1_ICACHE_LINESIZE + _SC_LEVEL1_DCACHE_SIZE, +#define _SC_LEVEL1_DCACHE_SIZE _SC_LEVEL1_DCACHE_SIZE + _SC_LEVEL1_DCACHE_ASSOC, +#define _SC_LEVEL1_DCACHE_ASSOC _SC_LEVEL1_DCACHE_ASSOC + _SC_LEVEL1_DCACHE_LINESIZE, +#define _SC_LEVEL1_DCACHE_LINESIZE _SC_LEVEL1_DCACHE_LINESIZE + _SC_LEVEL2_CACHE_SIZE, +#define _SC_LEVEL2_CACHE_SIZE _SC_LEVEL2_CACHE_SIZE + _SC_LEVEL2_CACHE_ASSOC, +#define _SC_LEVEL2_CACHE_ASSOC _SC_LEVEL2_CACHE_ASSOC + _SC_LEVEL2_CACHE_LINESIZE, +#define _SC_LEVEL2_CACHE_LINESIZE _SC_LEVEL2_CACHE_LINESIZE + _SC_LEVEL3_CACHE_SIZE, +#define _SC_LEVEL3_CACHE_SIZE _SC_LEVEL3_CACHE_SIZE + _SC_LEVEL3_CACHE_ASSOC, +#define _SC_LEVEL3_CACHE_ASSOC _SC_LEVEL3_CACHE_ASSOC + _SC_LEVEL3_CACHE_LINESIZE, +#define _SC_LEVEL3_CACHE_LINESIZE _SC_LEVEL3_CACHE_LINESIZE + _SC_LEVEL4_CACHE_SIZE, +#define _SC_LEVEL4_CACHE_SIZE _SC_LEVEL4_CACHE_SIZE + _SC_LEVEL4_CACHE_ASSOC, +#define _SC_LEVEL4_CACHE_ASSOC _SC_LEVEL4_CACHE_ASSOC + _SC_LEVEL4_CACHE_LINESIZE, +#define _SC_LEVEL4_CACHE_LINESIZE _SC_LEVEL4_CACHE_LINESIZE + /* Leave room here, maybe we need a few more cache levels some day. */ + + _SC_IPV6 = _SC_LEVEL1_ICACHE_SIZE + 50, +#define _SC_IPV6 _SC_IPV6 + _SC_RAW_SOCKETS, +#define _SC_RAW_SOCKETS _SC_RAW_SOCKETS + + _SC_V7_ILP32_OFF32, +#define _SC_V7_ILP32_OFF32 _SC_V7_ILP32_OFF32 + _SC_V7_ILP32_OFFBIG, +#define _SC_V7_ILP32_OFFBIG _SC_V7_ILP32_OFFBIG + _SC_V7_LP64_OFF64, +#define _SC_V7_LP64_OFF64 _SC_V7_LP64_OFF64 + _SC_V7_LPBIG_OFFBIG, +#define _SC_V7_LPBIG_OFFBIG _SC_V7_LPBIG_OFFBIG + + _SC_SS_REPL_MAX, +#define _SC_SS_REPL_MAX _SC_SS_REPL_MAX + + _SC_TRACE_EVENT_NAME_MAX, +#define _SC_TRACE_EVENT_NAME_MAX _SC_TRACE_EVENT_NAME_MAX + _SC_TRACE_NAME_MAX, +#define _SC_TRACE_NAME_MAX _SC_TRACE_NAME_MAX + _SC_TRACE_SYS_MAX, +#define _SC_TRACE_SYS_MAX _SC_TRACE_SYS_MAX + _SC_TRACE_USER_EVENT_MAX, +#define _SC_TRACE_USER_EVENT_MAX _SC_TRACE_USER_EVENT_MAX + + _SC_XOPEN_STREAMS, +#define _SC_XOPEN_STREAMS _SC_XOPEN_STREAMS + + _SC_THREAD_ROBUST_PRIO_INHERIT, +#define _SC_THREAD_ROBUST_PRIO_INHERIT _SC_THREAD_ROBUST_PRIO_INHERIT + _SC_THREAD_ROBUST_PRIO_PROTECT +#define _SC_THREAD_ROBUST_PRIO_PROTECT _SC_THREAD_ROBUST_PRIO_PROTECT + }; + +/* Values for the NAME argument to `confstr'. */ +enum + { + _CS_PATH, /* The default search path. */ +#define _CS_PATH _CS_PATH + + _CS_V6_WIDTH_RESTRICTED_ENVS, +#define _CS_V6_WIDTH_RESTRICTED_ENVS _CS_V6_WIDTH_RESTRICTED_ENVS +#define _CS_POSIX_V6_WIDTH_RESTRICTED_ENVS _CS_V6_WIDTH_RESTRICTED_ENVS + + _CS_GNU_LIBC_VERSION, +#define _CS_GNU_LIBC_VERSION _CS_GNU_LIBC_VERSION + _CS_GNU_LIBPTHREAD_VERSION, +#define _CS_GNU_LIBPTHREAD_VERSION _CS_GNU_LIBPTHREAD_VERSION + + _CS_V5_WIDTH_RESTRICTED_ENVS, +#define _CS_V5_WIDTH_RESTRICTED_ENVS _CS_V5_WIDTH_RESTRICTED_ENVS +#define _CS_POSIX_V5_WIDTH_RESTRICTED_ENVS _CS_V5_WIDTH_RESTRICTED_ENVS + + _CS_V7_WIDTH_RESTRICTED_ENVS, +#define _CS_V7_WIDTH_RESTRICTED_ENVS _CS_V7_WIDTH_RESTRICTED_ENVS +#define _CS_POSIX_V7_WIDTH_RESTRICTED_ENVS _CS_V7_WIDTH_RESTRICTED_ENVS + +# if (defined __USE_FILE_OFFSET64 || defined __USE_LARGEFILE64 \ + || defined __USE_LARGEFILE) + _CS_LFS_CFLAGS = 1000, +#define _CS_LFS_CFLAGS _CS_LFS_CFLAGS + _CS_LFS_LDFLAGS, +#define _CS_LFS_LDFLAGS _CS_LFS_LDFLAGS + _CS_LFS_LIBS, +#define _CS_LFS_LIBS _CS_LFS_LIBS + _CS_LFS_LINTFLAGS, +#define _CS_LFS_LINTFLAGS _CS_LFS_LINTFLAGS + _CS_LFS64_CFLAGS, +#define _CS_LFS64_CFLAGS _CS_LFS64_CFLAGS + _CS_LFS64_LDFLAGS, +#define _CS_LFS64_LDFLAGS _CS_LFS64_LDFLAGS + _CS_LFS64_LIBS, +#define _CS_LFS64_LIBS _CS_LFS64_LIBS + _CS_LFS64_LINTFLAGS, +#define _CS_LFS64_LINTFLAGS _CS_LFS64_LINTFLAGS +# endif + +# ifdef __USE_UNIX98 + _CS_XBS5_ILP32_OFF32_CFLAGS = 1100, +#define _CS_XBS5_ILP32_OFF32_CFLAGS _CS_XBS5_ILP32_OFF32_CFLAGS + _CS_XBS5_ILP32_OFF32_LDFLAGS, +#define _CS_XBS5_ILP32_OFF32_LDFLAGS _CS_XBS5_ILP32_OFF32_LDFLAGS + _CS_XBS5_ILP32_OFF32_LIBS, +#define _CS_XBS5_ILP32_OFF32_LIBS _CS_XBS5_ILP32_OFF32_LIBS + _CS_XBS5_ILP32_OFF32_LINTFLAGS, +#define _CS_XBS5_ILP32_OFF32_LINTFLAGS _CS_XBS5_ILP32_OFF32_LINTFLAGS + _CS_XBS5_ILP32_OFFBIG_CFLAGS, +#define _CS_XBS5_ILP32_OFFBIG_CFLAGS _CS_XBS5_ILP32_OFFBIG_CFLAGS + _CS_XBS5_ILP32_OFFBIG_LDFLAGS, +#define _CS_XBS5_ILP32_OFFBIG_LDFLAGS _CS_XBS5_ILP32_OFFBIG_LDFLAGS + _CS_XBS5_ILP32_OFFBIG_LIBS, +#define _CS_XBS5_ILP32_OFFBIG_LIBS _CS_XBS5_ILP32_OFFBIG_LIBS + _CS_XBS5_ILP32_OFFBIG_LINTFLAGS, +#define _CS_XBS5_ILP32_OFFBIG_LINTFLAGS _CS_XBS5_ILP32_OFFBIG_LINTFLAGS + _CS_XBS5_LP64_OFF64_CFLAGS, +#define _CS_XBS5_LP64_OFF64_CFLAGS _CS_XBS5_LP64_OFF64_CFLAGS + _CS_XBS5_LP64_OFF64_LDFLAGS, +#define _CS_XBS5_LP64_OFF64_LDFLAGS _CS_XBS5_LP64_OFF64_LDFLAGS + _CS_XBS5_LP64_OFF64_LIBS, +#define _CS_XBS5_LP64_OFF64_LIBS _CS_XBS5_LP64_OFF64_LIBS + _CS_XBS5_LP64_OFF64_LINTFLAGS, +#define _CS_XBS5_LP64_OFF64_LINTFLAGS _CS_XBS5_LP64_OFF64_LINTFLAGS + _CS_XBS5_LPBIG_OFFBIG_CFLAGS, +#define _CS_XBS5_LPBIG_OFFBIG_CFLAGS _CS_XBS5_LPBIG_OFFBIG_CFLAGS + _CS_XBS5_LPBIG_OFFBIG_LDFLAGS, +#define _CS_XBS5_LPBIG_OFFBIG_LDFLAGS _CS_XBS5_LPBIG_OFFBIG_LDFLAGS + _CS_XBS5_LPBIG_OFFBIG_LIBS, +#define _CS_XBS5_LPBIG_OFFBIG_LIBS _CS_XBS5_LPBIG_OFFBIG_LIBS + _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS, +#define _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS +# endif + +# ifdef __USE_XOPEN2K + _CS_POSIX_V6_ILP32_OFF32_CFLAGS, +#define _CS_POSIX_V6_ILP32_OFF32_CFLAGS _CS_POSIX_V6_ILP32_OFF32_CFLAGS + _CS_POSIX_V6_ILP32_OFF32_LDFLAGS, +#define _CS_POSIX_V6_ILP32_OFF32_LDFLAGS _CS_POSIX_V6_ILP32_OFF32_LDFLAGS + _CS_POSIX_V6_ILP32_OFF32_LIBS, +#define _CS_POSIX_V6_ILP32_OFF32_LIBS _CS_POSIX_V6_ILP32_OFF32_LIBS + _CS_POSIX_V6_ILP32_OFF32_LINTFLAGS, +#define _CS_POSIX_V6_ILP32_OFF32_LINTFLAGS _CS_POSIX_V6_ILP32_OFF32_LINTFLAGS + _CS_POSIX_V6_ILP32_OFFBIG_CFLAGS, +#define _CS_POSIX_V6_ILP32_OFFBIG_CFLAGS _CS_POSIX_V6_ILP32_OFFBIG_CFLAGS + _CS_POSIX_V6_ILP32_OFFBIG_LDFLAGS, +#define _CS_POSIX_V6_ILP32_OFFBIG_LDFLAGS _CS_POSIX_V6_ILP32_OFFBIG_LDFLAGS + _CS_POSIX_V6_ILP32_OFFBIG_LIBS, +#define _CS_POSIX_V6_ILP32_OFFBIG_LIBS _CS_POSIX_V6_ILP32_OFFBIG_LIBS + _CS_POSIX_V6_ILP32_OFFBIG_LINTFLAGS, +#define _CS_POSIX_V6_ILP32_OFFBIG_LINTFLAGS _CS_POSIX_V6_ILP32_OFFBIG_LINTFLAGS + _CS_POSIX_V6_LP64_OFF64_CFLAGS, +#define _CS_POSIX_V6_LP64_OFF64_CFLAGS _CS_POSIX_V6_LP64_OFF64_CFLAGS + _CS_POSIX_V6_LP64_OFF64_LDFLAGS, +#define _CS_POSIX_V6_LP64_OFF64_LDFLAGS _CS_POSIX_V6_LP64_OFF64_LDFLAGS + _CS_POSIX_V6_LP64_OFF64_LIBS, +#define _CS_POSIX_V6_LP64_OFF64_LIBS _CS_POSIX_V6_LP64_OFF64_LIBS + _CS_POSIX_V6_LP64_OFF64_LINTFLAGS, +#define _CS_POSIX_V6_LP64_OFF64_LINTFLAGS _CS_POSIX_V6_LP64_OFF64_LINTFLAGS + _CS_POSIX_V6_LPBIG_OFFBIG_CFLAGS, +#define _CS_POSIX_V6_LPBIG_OFFBIG_CFLAGS _CS_POSIX_V6_LPBIG_OFFBIG_CFLAGS + _CS_POSIX_V6_LPBIG_OFFBIG_LDFLAGS, +#define _CS_POSIX_V6_LPBIG_OFFBIG_LDFLAGS _CS_POSIX_V6_LPBIG_OFFBIG_LDFLAGS + _CS_POSIX_V6_LPBIG_OFFBIG_LIBS, +#define _CS_POSIX_V6_LPBIG_OFFBIG_LIBS _CS_POSIX_V6_LPBIG_OFFBIG_LIBS + _CS_POSIX_V6_LPBIG_OFFBIG_LINTFLAGS, +#define _CS_POSIX_V6_LPBIG_OFFBIG_LINTFLAGS _CS_POSIX_V6_LPBIG_OFFBIG_LINTFLAGS +# endif + +# ifdef __USE_XOPEN2K8 + _CS_POSIX_V7_ILP32_OFF32_CFLAGS, +#define _CS_POSIX_V7_ILP32_OFF32_CFLAGS _CS_POSIX_V7_ILP32_OFF32_CFLAGS + _CS_POSIX_V7_ILP32_OFF32_LDFLAGS, +#define _CS_POSIX_V7_ILP32_OFF32_LDFLAGS _CS_POSIX_V7_ILP32_OFF32_LDFLAGS + _CS_POSIX_V7_ILP32_OFF32_LIBS, +#define _CS_POSIX_V7_ILP32_OFF32_LIBS _CS_POSIX_V7_ILP32_OFF32_LIBS + _CS_POSIX_V7_ILP32_OFF32_LINTFLAGS, +#define _CS_POSIX_V7_ILP32_OFF32_LINTFLAGS _CS_POSIX_V7_ILP32_OFF32_LINTFLAGS + _CS_POSIX_V7_ILP32_OFFBIG_CFLAGS, +#define _CS_POSIX_V7_ILP32_OFFBIG_CFLAGS _CS_POSIX_V7_ILP32_OFFBIG_CFLAGS + _CS_POSIX_V7_ILP32_OFFBIG_LDFLAGS, +#define _CS_POSIX_V7_ILP32_OFFBIG_LDFLAGS _CS_POSIX_V7_ILP32_OFFBIG_LDFLAGS + _CS_POSIX_V7_ILP32_OFFBIG_LIBS, +#define _CS_POSIX_V7_ILP32_OFFBIG_LIBS _CS_POSIX_V7_ILP32_OFFBIG_LIBS + _CS_POSIX_V7_ILP32_OFFBIG_LINTFLAGS, +#define _CS_POSIX_V7_ILP32_OFFBIG_LINTFLAGS _CS_POSIX_V7_ILP32_OFFBIG_LINTFLAGS + _CS_POSIX_V7_LP64_OFF64_CFLAGS, +#define _CS_POSIX_V7_LP64_OFF64_CFLAGS _CS_POSIX_V7_LP64_OFF64_CFLAGS + _CS_POSIX_V7_LP64_OFF64_LDFLAGS, +#define _CS_POSIX_V7_LP64_OFF64_LDFLAGS _CS_POSIX_V7_LP64_OFF64_LDFLAGS + _CS_POSIX_V7_LP64_OFF64_LIBS, +#define _CS_POSIX_V7_LP64_OFF64_LIBS _CS_POSIX_V7_LP64_OFF64_LIBS + _CS_POSIX_V7_LP64_OFF64_LINTFLAGS, +#define _CS_POSIX_V7_LP64_OFF64_LINTFLAGS _CS_POSIX_V7_LP64_OFF64_LINTFLAGS + _CS_POSIX_V7_LPBIG_OFFBIG_CFLAGS, +#define _CS_POSIX_V7_LPBIG_OFFBIG_CFLAGS _CS_POSIX_V7_LPBIG_OFFBIG_CFLAGS + _CS_POSIX_V7_LPBIG_OFFBIG_LDFLAGS, +#define _CS_POSIX_V7_LPBIG_OFFBIG_LDFLAGS _CS_POSIX_V7_LPBIG_OFFBIG_LDFLAGS + _CS_POSIX_V7_LPBIG_OFFBIG_LIBS, +#define _CS_POSIX_V7_LPBIG_OFFBIG_LIBS _CS_POSIX_V7_LPBIG_OFFBIG_LIBS + _CS_POSIX_V7_LPBIG_OFFBIG_LINTFLAGS +#define _CS_POSIX_V7_LPBIG_OFFBIG_LINTFLAGS _CS_POSIX_V7_LPBIG_OFFBIG_LINTFLAGS +# endif + }; diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/dirent.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/dirent.h new file mode 100644 index 00000000..76794b08 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/dirent.h @@ -0,0 +1,53 @@ +/* Copyright (C) 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _DIRENT_H +# error "Never use directly; include instead." +#endif + +struct dirent + { +#ifndef __USE_FILE_OFFSET64 + __ino_t d_ino; + __off_t d_off; +#else + __ino64_t d_ino; + __off64_t d_off; +#endif + unsigned short int d_reclen; + unsigned char d_type; + char d_name[256]; /* We must not include limits.h! */ + }; + +#ifdef __USE_LARGEFILE64 +struct dirent64 + { + __ino64_t d_ino; + __off64_t d_off; + unsigned short int d_reclen; + unsigned char d_type; + char d_name[256]; /* We must not include limits.h! */ + }; +#endif + +#define d_fileno d_ino /* Backwards compatibility. */ + +#undef _DIRENT_HAVE_D_NAMLEN +#define _DIRENT_HAVE_D_RECLEN +#define _DIRENT_HAVE_D_OFF +#define _DIRENT_HAVE_D_TYPE diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/dlfcn.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/dlfcn.h new file mode 100644 index 00000000..4bfbbff0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/dlfcn.h @@ -0,0 +1,67 @@ +/* System dependent definitions for run-time dynamic loading. + Copyright (C) 1996-2001, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _DLFCN_H +# error "Never use directly; include instead." +#endif + +/* The MODE argument to `dlopen' contains one of the following: */ +#define RTLD_LAZY 0x00001 /* Lazy function call binding. */ +#define RTLD_NOW 0x00002 /* Immediate function call binding. */ +#if 0 /* uClibc doesnt support these */ +#define RTLD_BINDING_MASK 0x3 /* Mask of binding time value. */ +#define RTLD_NOLOAD 0x00004 /* Do not load the object. */ +#define RTLD_DEEPBIND 0x00008 /* Use deep binding. */ +#endif + +/* If the following bit is set in the MODE argument to `dlopen', + the symbols of the loaded object and its dependencies are made + visible as if the object were linked directly into the program. */ +#define RTLD_GLOBAL 0x00100 + +/* Unix98 demands the following flag which is the inverse to RTLD_GLOBAL. + The implementation does this by default and so we can define the + value to zero. */ +#define RTLD_LOCAL 0 + +/* Do not delete object when closed. */ +#define RTLD_NODELETE 0x01000 + +#if 0 /*def __USE_GNU*/ +/* To support profiling of shared objects it is a good idea to call + the function found using `dlsym' using the following macro since + these calls do not use the PLT. But this would mean the dynamic + loader has no chance to find out when the function is called. The + macro applies the necessary magic so that profiling is possible. + Rewrite + foo = (*fctp) (arg1, arg2); + into + foo = DL_CALL_FCT (fctp, (arg1, arg2)); +*/ +# define DL_CALL_FCT(fctp, args) \ + (_dl_mcount_wrapper_check ((void *) (fctp)), (*(fctp)) args) + +__BEGIN_DECLS + +/* This function calls the profiling functions. */ +extern void _dl_mcount_wrapper_check (void *__selfpc) __THROW; + +__END_DECLS + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/elfclass.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/elfclass.h new file mode 100644 index 00000000..180227d9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/elfclass.h @@ -0,0 +1,14 @@ +/* This file specifies the native word size of the machine, which indicates + the ELF file class used for executables and shared objects on this + machine. */ + +#ifndef _LINK_H +# error "Never use directly; include instead." +#endif + +#include + +#define __ELF_NATIVE_CLASS __WORDSIZE + +/* The entries in the .hash table always have a size of 32 bits. */ +typedef uint32_t Elf_Symndx; diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/endian.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/endian.h new file mode 100644 index 00000000..0086a1cd --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/endian.h @@ -0,0 +1,18 @@ +/* This file should define __BYTE_ORDER as appropriate for the machine + in question. See string/endian.h for how to define it. + + If only the stub bits/endian.h applies to a particular configuration, + bytesex.h is generated by running a program on the host machine. + So if cross-compiling to a machine with a different byte order, + the bits/endian.h file for that machine must exist. */ + +#ifndef _ENDIAN_H +# error "Never use directly; include instead." +#endif + +#error Machine byte order unknown. + +#if 0 +#define __BYTE_ORDER __BIG_ENDIAN +#define __BYTE_ORDER __LITTLE_ENDIAN +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/environments.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/environments.h new file mode 100644 index 00000000..548ea7f8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/environments.h @@ -0,0 +1,88 @@ +/* Copyright (C) 1999, 2001, 2004, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _UNISTD_H +# error "Never include this file directly. Use instead" +#endif + +#include + +/* This header should define the following symbols under the described + situations. A value `1' means that the model is always supported, + `-1' means it is never supported. Undefined means it cannot be + statically decided. + + _POSIX_V7_ILP32_OFF32 32bit int, long, pointers, and off_t type + _POSIX_V7_ILP32_OFFBIG 32bit int, long, and pointers and larger off_t type + + _POSIX_V7_LP64_OFF32 64bit long and pointers and 32bit off_t type + _POSIX_V7_LPBIG_OFFBIG 64bit long and pointers and large off_t type + + The macros _POSIX_V6_ILP32_OFF32, _POSIX_V6_ILP32_OFFBIG, + _POSIX_V6_LP64_OFF32, _POSIX_V6_LPBIG_OFFBIG, _XBS5_ILP32_OFF32, + _XBS5_ILP32_OFFBIG, _XBS5_LP64_OFF32, and _XBS5_LPBIG_OFFBIG were + used in previous versions of the Unix standard and are available + only for compatibility. +*/ + +#if __WORDSIZE == 64 + +/* We can never provide environments with 32-bit wide pointers. */ +# define _POSIX_V7_ILP32_OFF32 -1 +# define _POSIX_V7_ILP32_OFFBIG -1 +# define _POSIX_V6_ILP32_OFF32 -1 +# define _POSIX_V6_ILP32_OFFBIG -1 +# define _XBS5_ILP32_OFF32 -1 +# define _XBS5_ILP32_OFFBIG -1 +/* We also have no use (for now) for an environment with bigger pointers + and offsets. */ +# define _POSIX_V7_LPBIG_OFFBIG -1 +# define _POSIX_V6_LPBIG_OFFBIG -1 +# define _XBS5_LPBIG_OFFBIG -1 + +/* By default we have 64-bit wide `long int', pointers and `off_t'. */ +# define _POSIX_V7_LP64_OFF64 1 +# define _POSIX_V6_LP64_OFF64 1 +# define _XBS5_LP64_OFF64 1 + +#else /* __WORDSIZE == 32 */ + +/* By default we have 32-bit wide `int', `long int', pointers and `off_t' + and all platforms support LFS. */ +# define _POSIX_V7_ILP32_OFF32 1 +# define _POSIX_V7_ILP32_OFFBIG 1 +# define _POSIX_V6_ILP32_OFF32 1 +# define _POSIX_V6_ILP32_OFFBIG 1 +# define _XBS5_ILP32_OFF32 1 +# define _XBS5_ILP32_OFFBIG 1 + +/* We optionally provide an environment with the above size but an 64-bit + side `off_t'. Therefore we don't define _POSIX_V7_ILP32_OFFBIG. */ + +/* We can never provide environments with 64-bit wide pointers. */ +# define _POSIX_V7_LP64_OFF64 -1 +# define _POSIX_V7_LPBIG_OFFBIG -1 +# define _POSIX_V6_LP64_OFF64 -1 +# define _POSIX_V6_LPBIG_OFFBIG -1 +# define _XBS5_LP64_OFF64 -1 +# define _XBS5_LPBIG_OFFBIG -1 + +/* CFLAGS. */ +#define __ILP32_OFFBIG_CFLAGS "-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64" + +#endif /* __WORDSIZE == 32 */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/errno.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/errno.h new file mode 100644 index 00000000..0bf6354f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/errno.h @@ -0,0 +1,62 @@ +/* Error constants. Linux specific version. + Copyright (C) 1996, 1997, 1998, 1999, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifdef _ERRNO_H + +# undef EDOM +# undef EILSEQ +# undef ERANGE +# include + +/* Linux has no ENOTSUP error code. */ +# ifndef ENOTSUP +# define ENOTSUP EOPNOTSUPP +# endif + +/* Older Linux versions also had no ECANCELED error code. */ +# ifndef ECANCELED +# define ECANCELED 125 +# endif + +/* Support for error codes to support robust mutexes was added later, too. */ +# ifndef EOWNERDEAD +# define EOWNERDEAD 130 +# define ENOTRECOVERABLE 131 +# endif + +# ifndef __ASSEMBLER__ +/* Function to get address of global `errno' variable. */ +extern int *__errno_location (void) __THROW __attribute__ ((__const__)); +libc_hidden_proto(__errno_location) + +# ifdef __UCLIBC_HAS_THREADS__ +/* When using threads, errno is a per-thread value. */ +# define errno (*__errno_location ()) +# endif +# endif /* !__ASSEMBLER__ */ +#endif /* _ERRNO_H */ + +#if !defined _ERRNO_H && defined __need_Emath +/* This is ugly but the kernel header is not clean enough. We must + define only the values EDOM, EILSEQ and ERANGE in case __need_Emath is + defined. */ +# define EDOM 33 /* Math argument out of domain of function. */ +# define EILSEQ 84 /* Illegal byte sequence. */ +# define ERANGE 34 /* Math result not representable. */ +#endif /* !_ERRNO_H && __need_Emath */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/fcntl.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/fcntl.h new file mode 100644 index 00000000..be40350e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/fcntl.h @@ -0,0 +1,3 @@ +/* bits/fcntl.h is architecture specific. */ +#error "This file must be supplied by every Linux architecture." + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/fenv.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/fenv.h new file mode 100644 index 00000000..a9cb53b4 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/fenv.h @@ -0,0 +1,56 @@ +/* Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FENV_H +# error "Never use directly; include instead." +#endif + + +/* Here should be the exception be defined: + FE_INVALID + FE_DIVBYZERO + FE_OVERFLOW + FE_UNDERFLOW + FE_INEXACT + We define no macro which signals no exception is supported. */ + +#define FE_ALL_EXCEPT 0 + + +/* Here should the rounding modes be defined: + FE_TONEAREST + FE_DOWNWARD + FE_UPWARD + FE_TOWARDZERO + We define no macro which signals no rounding mode is selectable. */ + + +/* Type representing exception flags. */ +typedef unsigned int fexcept_t; + + +/* Type representing floating-point environment. */ +typedef struct + { + fexcept_t __excepts; + /* XXX I don't know what else we should save. */ + } +fenv_t; + +/* If the default argument is used we use this value. */ +#define FE_DFL_ENV ((__const fenv_t *) -1l) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/fenvinline.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/fenvinline.h new file mode 100644 index 00000000..42f77b56 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/fenvinline.h @@ -0,0 +1,8 @@ +/* This file provides inline versions of floating-pint environment + handling functions. If there were any. */ + +#ifndef __NO_MATH_INLINES + +/* Here is where the code would go. */ + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/getopt.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/getopt.h new file mode 100644 index 00000000..89bd3323 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/getopt.h @@ -0,0 +1,183 @@ +/* Declarations for getopt. + Copyright (C) 1989-1994,1996-1999,2001,2003,2004 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _GETOPT_H + +#include + +#ifndef __need_getopt +# define _GETOPT_H 1 +#endif + +/* If __GNU_LIBRARY__ is not already defined, either we are being used + standalone, or this is the first header included in the source file. + If we are being used with glibc, we need to include , but + that does not exist if we are standalone. So: if __GNU_LIBRARY__ is + not defined, include , which will pull in for us + if it's from glibc. (Why ctype.h? It's guaranteed to exist and it + doesn't flood the namespace with stuff the way some other headers do.) */ +#if !defined __GNU_LIBRARY__ +# include +#endif + +#ifndef __THROW +# ifndef __GNUC_PREREQ +# define __GNUC_PREREQ(maj, min) (0) +# endif +# if defined __cplusplus && __GNUC_PREREQ (2,8) +# define __THROW throw () +# else +# define __THROW +# endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* For communication from `getopt' to the caller. + When `getopt' finds an option that takes an argument, + the argument value is returned here. + Also, when `ordering' is RETURN_IN_ORDER, + each non-option ARGV-element is returned here. */ + +extern char *optarg; + +/* Index in ARGV of the next element to be scanned. + This is used for communication to and from the caller + and for communication between successive calls to `getopt'. + + On entry to `getopt', zero means this is the first call; initialize. + + When `getopt' returns -1, this is the index of the first of the + non-option elements that the caller should itself scan. + + Otherwise, `optind' communicates from one call to the next + how much of ARGV has been scanned so far. */ + +extern int optind; + +/* Callers store zero here to inhibit the error message `getopt' prints + for unrecognized options. */ + +extern int opterr; + +/* Set to an option character which was unrecognized. */ + +extern int optopt; + +#ifndef __need_getopt +/* Describe the long-named options requested by the application. + The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector + of `struct option' terminated by an element containing a name which is + zero. + + The field `has_arg' is: + no_argument (or 0) if the option does not take an argument, + required_argument (or 1) if the option requires an argument, + optional_argument (or 2) if the option takes an optional argument. + + If the field `flag' is not NULL, it points to a variable that is set + to the value given in the field `val' when the option is found, but + left unchanged if the option is not found. + + To have a long-named option do something other than set an `int' to + a compiled-in constant, such as set a value from `optarg', set the + option's `flag' field to zero and its `val' field to a nonzero + value (the equivalent single-letter option character, if there is + one). For long options that have a zero `flag' field, `getopt' + returns the contents of the `val' field. */ + +struct option +{ + const char *name; + /* has_arg can't be an enum because some compilers complain about + type mismatches in all the code that assumes it is an int. */ + int has_arg; + int *flag; + int val; +}; + +/* Names for the values of the `has_arg' field of `struct option'. */ + +# define no_argument 0 +# define required_argument 1 +# define optional_argument 2 +#endif /* need getopt */ + + +/* Get definitions and prototypes for functions to process the + arguments in ARGV (ARGC of them, minus the program name) for + options given in OPTS. + + Return the option character from OPTS just read. Return -1 when + there are no more options. For unrecognized options, or options + missing arguments, `optopt' is set to the option letter, and '?' is + returned. + + The OPTS string is a list of characters which are recognized option + letters, optionally followed by colons, specifying that that letter + takes an argument, to be placed in `optarg'. + + If a letter in OPTS is followed by two colons, its argument is + optional. This behavior is specific to the GNU `getopt'. + + The argument `--' causes premature termination of argument + scanning, explicitly telling `getopt' that there are no more + options. + + If OPTS begins with `--', then non-option arguments are treated as + arguments to the option '\0'. This behavior is specific to the GNU + `getopt'. */ + +#if defined __GNU_LIBRARY__ || defined __UCLIBC__ +/* Many other libraries have conflicting prototypes for getopt, with + differences in the consts, in stdlib.h. To avoid compilation + errors, only prototype getopt for the GNU C library. */ +extern int getopt (int ___argc, char *const *___argv, const char *__shortopts) + __THROW; +libc_hidden_proto(getopt) +#else /* not __GNU_LIBRARY__ */ +extern int getopt (); +libc_hidden_proto(getopt) +#endif /* __GNU_LIBRARY__ */ + +#if defined __UCLIBC_HAS_GNU_GETOPT__ || defined __UCLIBC_HAS_GETOPT_LONG__ +#ifndef __need_getopt +extern int getopt_long (int ___argc, char *const *___argv, + const char *__shortopts, + const struct option *__longopts, int *__longind) + __THROW; +extern int getopt_long_only (int ___argc, char *const *___argv, + const char *__shortopts, + const struct option *__longopts, int *__longind) + __THROW; + +#endif +#endif + +#ifdef __cplusplus +} +#endif + +/* Make sure we later can get all the definitions and declarations. */ +#undef __need_getopt + +#endif /* getopt.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/huge_val.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/huge_val.h new file mode 100644 index 00000000..11ca11f1 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/huge_val.h @@ -0,0 +1,55 @@ +/* `HUGE_VAL' constant for IEEE 754 machines (where it is infinity). + Used by and functions for overflow. + Copyright (C) 1992, 1995, 1996, 1997, 1999, 2000, 2004 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _MATH_H +# error "Never use directly; include instead." +#endif + +/* IEEE positive infinity (-HUGE_VAL is negative infinity). */ + +#if __GNUC_PREREQ(3,3) +# define HUGE_VAL (__builtin_huge_val()) +#elif __GNUC_PREREQ(2,96) +# define HUGE_VAL (__extension__ 0x1.0p2047) +#elif defined __GNUC__ + +# define HUGE_VAL \ + (__extension__ \ + ((union { unsigned __l __attribute__((__mode__(__DI__))); double __d; }) \ + { __l: 0x7ff0000000000000ULL }).__d) + +#else /* not GCC */ + +# include + +typedef union { unsigned char __c[8]; double __d; } __huge_val_t; + +# if __BYTE_ORDER == __BIG_ENDIAN +# define __HUGE_VAL_bytes { 0x7f, 0xf0, 0, 0, 0, 0, 0, 0 } +# endif +# if __BYTE_ORDER == __LITTLE_ENDIAN +# define __HUGE_VAL_bytes { 0, 0, 0, 0, 0, 0, 0xf0, 0x7f } +# endif + +static __huge_val_t __huge_val = { __HUGE_VAL_bytes }; +# define HUGE_VAL (__huge_val.__d) + +#endif /* GCC. */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/huge_valf.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/huge_valf.h new file mode 100644 index 00000000..1785342c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/huge_valf.h @@ -0,0 +1,53 @@ +/* `HUGE_VALF' constant for IEEE 754 machines (where it is infinity). + Used by and functions for overflow. + Copyright (C) 1992, 1995, 1996, 1997, 1999, 2000, 2004 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _MATH_H +# error "Never use directly; include instead." +#endif + +/* IEEE positive infinity (-HUGE_VAL is negative infinity). */ + +#if __GNUC_PREREQ(3,3) +# define HUGE_VALF (__builtin_huge_valf()) +#elif __GNUC_PREREQ(2,96) +# define HUGE_VALF (__extension__ 0x1.0p255f) +#elif defined __GNUC__ + +# define HUGE_VALF \ + (__extension__ \ + ((union { unsigned __l __attribute__((__mode__(__SI__))); float __d; }) \ + { __l: 0x7f800000UL }).__d) + +#else /* not GCC */ + +typedef union { unsigned char __c[4]; float __f; } __huge_valf_t; + +# if __BYTE_ORDER == __BIG_ENDIAN +# define __HUGE_VALF_bytes { 0x7f, 0x80, 0, 0 } +# endif +# if __BYTE_ORDER == __LITTLE_ENDIAN +# define __HUGE_VALF_bytes { 0, 0, 0x80, 0x7f } +# endif + +static __huge_valf_t __huge_valf = { __HUGE_VALF_bytes }; +# define HUGE_VALF (__huge_valf.__f) + +#endif /* GCC. */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/huge_vall.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/huge_vall.h new file mode 100644 index 00000000..d5e8e223 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/huge_vall.h @@ -0,0 +1,29 @@ +/* Default `HUGE_VALL' constant. + Used by and functions for overflow. + Copyright (C) 1992, 1996, 1997, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _MATH_H +# error "Never use directly; include instead." +#endif + +#if __GNUC_PREREQ(3,3) +# define HUGE_VALL (__builtin_huge_vall()) +#else +# define HUGE_VALL ((long double) HUGE_VAL) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/in.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/in.h new file mode 100644 index 00000000..1f2b8179 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/in.h @@ -0,0 +1,172 @@ +/* Copyright (C) 1991-1999, 2000, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Linux version. */ + +#ifndef _NETINET_IN_H +# error "Never use directly; include instead." +#endif + +/* Options for use with `getsockopt' and `setsockopt' at the IP level. + The first word in the comment at the right is the data type used; + "bool" means a boolean value stored in an `int'. */ +#define IP_OPTIONS 4 /* ip_opts; IP per-packet options. */ +#define IP_HDRINCL 3 /* int; Header is included with data. */ +#define IP_TOS 1 /* int; IP type of service and precedence. */ +#define IP_TTL 2 /* int; IP time to live. */ +#define IP_RECVOPTS 6 /* bool; Receive all IP options w/datagram. */ +/* For BSD compatibility. */ +#define IP_RECVRETOPTS IP_RETOPTS /* bool; Receive IP options for response. */ +#define IP_RETOPTS 7 /* ip_opts; Set/get IP per-packet options. */ +#define IP_MULTICAST_IF 32 /* in_addr; set/get IP multicast i/f */ +#define IP_MULTICAST_TTL 33 /* u_char; set/get IP multicast ttl */ +#define IP_MULTICAST_LOOP 34 /* i_char; set/get IP multicast loopback */ +#define IP_ADD_MEMBERSHIP 35 /* ip_mreq; add an IP group membership */ +#define IP_DROP_MEMBERSHIP 36 /* ip_mreq; drop an IP group membership */ +#define IP_UNBLOCK_SOURCE 37 /* ip_mreq_source: unblock data from source */ +#define IP_BLOCK_SOURCE 38 /* ip_mreq_source: block data from source */ +#define IP_ADD_SOURCE_MEMBERSHIP 39 /* ip_mreq_source: join source group */ +#define IP_DROP_SOURCE_MEMBERSHIP 40 /* ip_mreq_source: leave source group */ +#define IP_MSFILTER 41 +#define MCAST_JOIN_GROUP 42 /* group_req: join any-source group */ +#define MCAST_BLOCK_SOURCE 43 /* group_source_req: block from given group */ +#define MCAST_UNBLOCK_SOURCE 44 /* group_source_req: unblock from given group*/ +#define MCAST_LEAVE_GROUP 45 /* group_req: leave any-source group */ +#define MCAST_JOIN_SOURCE_GROUP 46 /* group_source_req: join source-spec gr */ +#define MCAST_LEAVE_SOURCE_GROUP 47 /* group_source_req: leave source-spec gr*/ +#define MCAST_MSFILTER 48 + +#define MCAST_EXCLUDE 0 +#define MCAST_INCLUDE 1 + +#define IP_ROUTER_ALERT 5 /* bool */ +#define IP_PKTINFO 8 /* bool */ +#define IP_PKTOPTIONS 9 +#define IP_PMTUDISC 10 /* obsolete name? */ +#define IP_MTU_DISCOVER 10 /* int; see below */ +#define IP_RECVERR 11 /* bool */ +#define IP_RECVTTL 12 /* bool */ +#define IP_RECVTOS 13 /* bool */ + + +/* IP_MTU_DISCOVER arguments. */ +#define IP_PMTUDISC_DONT 0 /* Never send DF frames. */ +#define IP_PMTUDISC_WANT 1 /* Use per route hints. */ +#define IP_PMTUDISC_DO 2 /* Always DF. */ + +/* To select the IP level. */ +#define SOL_IP 0 + +#define IP_DEFAULT_MULTICAST_TTL 1 +#define IP_DEFAULT_MULTICAST_LOOP 1 +#define IP_MAX_MEMBERSHIPS 20 + +/* Structure used to describe IP options for IP_OPTIONS and IP_RETOPTS. + The `ip_dst' field is used for the first-hop gateway when using a + source route (this gets put into the header proper). */ +struct ip_opts + { + struct in_addr ip_dst; /* First hop; zero without source route. */ + char ip_opts[40]; /* Actually variable in size. */ + }; + +/* Like `struct ip_mreq' but including interface specification by index. */ +struct ip_mreqn + { + struct in_addr imr_multiaddr; /* IP multicast address of group */ + struct in_addr imr_address; /* local IP address of interface */ + int imr_ifindex; /* Interface index */ + }; + +/* Structure used for IP_PKTINFO. */ +struct in_pktinfo + { + int ipi_ifindex; /* Interface index */ + struct in_addr ipi_spec_dst; /* Routing destination address */ + struct in_addr ipi_addr; /* Header destination address */ + }; + +#ifdef __UCLIBC_HAS_IPV6__ +/* Options for use with `getsockopt' and `setsockopt' at the IPv6 level. + The first word in the comment at the right is the data type used; + "bool" means a boolean value stored in an `int'. */ +#define IPV6_ADDRFORM 1 +#define IPV6_2292PKTINFO 2 +#define IPV6_2292HOPOPTS 3 +#define IPV6_2292DSTOPTS 4 +#define IPV6_2292RTHDR 5 +#define IPV6_2292PKTOPTIONS 6 +#define IPV6_CHECKSUM 7 +#define IPV6_2292HOPLIMIT 8 + +#define SCM_SRCRT IPV6_RXSRCRT + +#define IPV6_NEXTHOP 9 +#define IPV6_AUTHHDR 10 +#define IPV6_UNICAST_HOPS 16 +#define IPV6_MULTICAST_IF 17 +#define IPV6_MULTICAST_HOPS 18 +#define IPV6_MULTICAST_LOOP 19 +#define IPV6_JOIN_GROUP 20 +#define IPV6_LEAVE_GROUP 21 +#define IPV6_ROUTER_ALERT 22 +#define IPV6_MTU_DISCOVER 23 +#define IPV6_MTU 24 +#define IPV6_RECVERR 25 +#define IPV6_V6ONLY 26 +#define IPV6_JOIN_ANYCAST 27 +#define IPV6_LEAVE_ANYCAST 28 +#define IPV6_IPSEC_POLICY 34 +#define IPV6_XFRM_POLICY 35 + +#define IPV6_RECVPKTINFO 49 +#define IPV6_PKTINFO 50 +#define IPV6_RECVHOPLIMIT 51 +#define IPV6_HOPLIMIT 52 +#define IPV6_RECVHOPOPTS 53 +#define IPV6_HOPOPTS 54 +#define IPV6_RTHDRDSTOPTS 55 +#define IPV6_RECVRTHDR 56 +#define IPV6_RTHDR 57 +#define IPV6_RECVDSTOPTS 58 +#define IPV6_DSTOPTS 59 + +#define IPV6_RECVTCLASS 66 +#define IPV6_TCLASS 67 + +/* Obsolete synonyms for the above. */ +#define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP +#define IPV6_DROP_MEMBERSHIP IPV6_LEAVE_GROUP +#define IPV6_RXHOPOPTS IPV6_HOPOPTS +#define IPV6_RXDSTOPTS IPV6_DSTOPTS + +/* IPV6_MTU_DISCOVER values. */ +#define IPV6_PMTUDISC_DONT 0 /* Never send DF frames. */ +#define IPV6_PMTUDISC_WANT 1 /* Use per route hints. */ +#define IPV6_PMTUDISC_DO 2 /* Always DF. */ + +/* Socket level values for IPv6. */ +#define SOL_IPV6 41 +#define SOL_ICMPV6 58 + +/* Routing header options for IPv6. */ +#define IPV6_RTHDR_LOOSE 0 /* Hop doesn't need to be neighbour. */ +#define IPV6_RTHDR_STRICT 1 /* Hop must be a neighbour. */ + +#define IPV6_RTHDR_TYPE_0 0 /* IPv6 Routing header type 0. */ +#endif /* __UCLIBC_HAS_IPV6__ */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/inf.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/inf.h new file mode 100644 index 00000000..1619f756 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/inf.h @@ -0,0 +1,30 @@ +/* `INFINITY' constant for IEEE 754 machines. + Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _MATH_H +# error "Never use directly; include instead." +#endif + +/* IEEE positive infinity. */ + +#if __GNUC_PREREQ(3,3) +# define INFINITY (__builtin_inff()) +#else +# define INFINITY HUGE_VALF +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/initspin.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/initspin.h new file mode 100644 index 00000000..a19ec077 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/initspin.h @@ -0,0 +1,28 @@ +/* Generic definitions for spinlock initializers. + Copyright (C) 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* Initial value of a spinlock. Most platforms should use zero, + unless they only implement a "test and clear" operation instead of + the usual "test and set". */ +#define __LT_SPINLOCK_INIT 0 + +/* Macros for lock initializers, using the above definition. */ +#define __LOCK_INITIALIZER { 0, __LT_SPINLOCK_INIT } +#define __ALT_LOCK_INITIALIZER { 0, __LT_SPINLOCK_INIT } +#define __ATOMIC_INITIALIZER { 0, __LT_SPINLOCK_INIT } diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/ioctl-types.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/ioctl-types.h new file mode 100644 index 00000000..e856a04b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/ioctl-types.h @@ -0,0 +1,78 @@ +/* Structure types for pre-termios terminal ioctls. Linux version. + Copyright (C) 1996, 1997, 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_IOCTL_H +# error "Never use directly; include instead." +#endif + +/* Get definition of constants for use with `ioctl'. */ +#include + + +struct winsize + { + unsigned short int ws_row; + unsigned short int ws_col; + unsigned short int ws_xpixel; + unsigned short int ws_ypixel; + }; + +#define NCC 8 +struct termio + { + unsigned short int c_iflag; /* input mode flags */ + unsigned short int c_oflag; /* output mode flags */ + unsigned short int c_cflag; /* control mode flags */ + unsigned short int c_lflag; /* local mode flags */ + unsigned char c_line; /* line discipline */ + unsigned char c_cc[NCC]; /* control characters */ +}; + +/* modem lines */ +#define TIOCM_LE 0x001 +#define TIOCM_DTR 0x002 +#define TIOCM_RTS 0x004 +#define TIOCM_ST 0x008 +#define TIOCM_SR 0x010 +#define TIOCM_CTS 0x020 +#define TIOCM_CAR 0x040 +#define TIOCM_RNG 0x080 +#define TIOCM_DSR 0x100 +#define TIOCM_CD TIOCM_CAR +#define TIOCM_RI TIOCM_RNG + +/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */ + +/* line disciplines */ +#define N_TTY 0 +#define N_SLIP 1 +#define N_MOUSE 2 +#define N_PPP 3 +#define N_STRIP 4 +#define N_AX25 5 +#define N_X25 6 /* X.25 async */ +#define N_6PACK 7 +#define N_MASC 8 /* Mobitex module */ +#define N_R3964 9 /* Simatic R3964 module */ +#define N_PROFIBUS_FDL 10 /* Profibus */ +#define N_IRDA 11 /* Linux IR */ +#define N_SMSBLOCK 12 /* SMS block mode */ +#define N_HDLC 13 /* synchronous HDLC */ +#define N_SYNC_PPP 14 /* synchronous PPP */ +#define N_HCI 15 /* Bluetooth HCI UART */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/ioctls.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/ioctls.h new file mode 100644 index 00000000..268c0e48 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/ioctls.h @@ -0,0 +1,109 @@ +/* Copyright (C) 1996, 1997, 1998, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_IOCTL_H +# error "Never use directly; include instead." +#endif + +/* Use the definitions from the kernel header files. */ +#include + +/* Routing table calls. */ +#define SIOCADDRT 0x890B /* add routing table entry */ +#define SIOCDELRT 0x890C /* delete routing table entry */ +#define SIOCRTMSG 0x890D /* call to routing system */ + +/* Socket configuration controls. */ +#define SIOCGIFNAME 0x8910 /* get iface name */ +#define SIOCSIFLINK 0x8911 /* set iface channel */ +#define SIOCGIFCONF 0x8912 /* get iface list */ +#define SIOCGIFFLAGS 0x8913 /* get flags */ +#define SIOCSIFFLAGS 0x8914 /* set flags */ +#define SIOCGIFADDR 0x8915 /* get PA address */ +#define SIOCSIFADDR 0x8916 /* set PA address */ +#define SIOCGIFDSTADDR 0x8917 /* get remote PA address */ +#define SIOCSIFDSTADDR 0x8918 /* set remote PA address */ +#define SIOCGIFBRDADDR 0x8919 /* get broadcast PA address */ +#define SIOCSIFBRDADDR 0x891a /* set broadcast PA address */ +#define SIOCGIFNETMASK 0x891b /* get network PA mask */ +#define SIOCSIFNETMASK 0x891c /* set network PA mask */ +#define SIOCGIFMETRIC 0x891d /* get metric */ +#define SIOCSIFMETRIC 0x891e /* set metric */ +#define SIOCGIFMEM 0x891f /* get memory address (BSD) */ +#define SIOCSIFMEM 0x8920 /* set memory address (BSD) */ +#define SIOCGIFMTU 0x8921 /* get MTU size */ +#define SIOCSIFMTU 0x8922 /* set MTU size */ +#define SIOCSIFNAME 0x8923 /* set interface name */ +#define SIOCSIFHWADDR 0x8924 /* set hardware address */ +#define SIOCGIFENCAP 0x8925 /* get/set encapsulations */ +#define SIOCSIFENCAP 0x8926 +#define SIOCGIFHWADDR 0x8927 /* Get hardware address */ +#define SIOCGIFSLAVE 0x8929 /* Driver slaving support */ +#define SIOCSIFSLAVE 0x8930 +#define SIOCADDMULTI 0x8931 /* Multicast address lists */ +#define SIOCDELMULTI 0x8932 +#define SIOCGIFINDEX 0x8933 /* name -> if_index mapping */ +#define SIOGIFINDEX SIOCGIFINDEX /* misprint compatibility :-) */ +#define SIOCSIFPFLAGS 0x8934 /* set/get extended flags set */ +#define SIOCGIFPFLAGS 0x8935 +#define SIOCDIFADDR 0x8936 /* delete PA address */ +#define SIOCSIFHWBROADCAST 0x8937 /* set hardware broadcast addr */ +#define SIOCGIFCOUNT 0x8938 /* get number of devices */ + +#define SIOCGIFBR 0x8940 /* Bridging support */ +#define SIOCSIFBR 0x8941 /* Set bridging options */ + +#define SIOCGIFTXQLEN 0x8942 /* Get the tx queue length */ +#define SIOCSIFTXQLEN 0x8943 /* Set the tx queue length */ + + +/* ARP cache control calls. */ + /* 0x8950 - 0x8952 * obsolete calls, don't re-use */ +#define SIOCDARP 0x8953 /* delete ARP table entry */ +#define SIOCGARP 0x8954 /* get ARP table entry */ +#define SIOCSARP 0x8955 /* set ARP table entry */ + +/* RARP cache control calls. */ +#define SIOCDRARP 0x8960 /* delete RARP table entry */ +#define SIOCGRARP 0x8961 /* get RARP table entry */ +#define SIOCSRARP 0x8962 /* set RARP table entry */ + +/* Driver configuration calls */ + +#define SIOCGIFMAP 0x8970 /* Get device parameters */ +#define SIOCSIFMAP 0x8971 /* Set device parameters */ + +/* DLCI configuration calls */ + +#define SIOCADDDLCI 0x8980 /* Create new DLCI device */ +#define SIOCDELDLCI 0x8981 /* Delete DLCI device */ + +/* Device private ioctl calls. */ + +/* These 16 ioctls are available to devices via the do_ioctl() device + vector. Each device should include this file and redefine these + names as their own. Because these are device dependent it is a good + idea _NOT_ to issue them to random objects and hope. */ + +#define SIOCDEVPRIVATE 0x89F0 /* to 89FF */ + +/* + * These 16 ioctl calls are protocol private + */ + +#define SIOCPROTOPRIVATE 0x89E0 /* to 89EF */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/ipc.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/ipc.h new file mode 100644 index 00000000..f1a043fe --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/ipc.h @@ -0,0 +1,56 @@ +/* Copyright (C) 1995-1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_IPC_H +# error "Never use directly; include instead." +#endif + +#include + +/* Mode bits for `msgget', `semget', and `shmget'. */ +#define IPC_CREAT 01000 /* Create key if key does not exist. */ +#define IPC_EXCL 02000 /* Fail if key exists. */ +#define IPC_NOWAIT 04000 /* Return error on wait. */ + +/* Control commands for `msgctl', `semctl', and `shmctl'. */ +#define IPC_RMID 0 /* Remove identifier. */ +#define IPC_SET 1 /* Set `ipc_perm' options. */ +#define IPC_STAT 2 /* Get `ipc_perm' options. */ +#ifdef __USE_GNU +# define IPC_INFO 3 /* See ipcs. */ +#endif + +/* Special key values. */ +#define IPC_PRIVATE ((__key_t) 0) /* Private key. */ + + +/* Data structure used to pass permission information to IPC operations. */ +struct ipc_perm + { + __key_t __key; /* Key. */ + __uid_t uid; /* Owner's user ID. */ + __gid_t gid; /* Owner's group ID. */ + __uid_t cuid; /* Creator's user ID. */ + __gid_t cgid; /* Creator's group ID. */ + unsigned short int mode; /* Read/write permission. */ + unsigned short int __pad1; + unsigned short int __seq; /* Sequence number. */ + unsigned short int __pad2; + unsigned long int __unused1; + unsigned long int __unused2; + }; diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/kernel-features.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/kernel-features.h new file mode 100644 index 00000000..68b881c0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/kernel-features.h @@ -0,0 +1,472 @@ +/* Set flags signalling availability of kernel features based on given + kernel version number. + Copyright (C) 1999-2003, 2004, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This file must not contain any C code. At least it must be protected + to allow using the file also in assembler files. */ + +#if defined __mips__ +# include +#endif + +#include +#define __LINUX_KERNEL_VERSION LINUX_VERSION_CODE + +/* We assume for __LINUX_KERNEL_VERSION the same encoding used in + linux/version.h. I.e., the major, minor, and subminor all get a + byte with the major number being in the highest byte. This means + we can do numeric comparisons. + + In the following we will define certain symbols depending on + whether the describes kernel feature is available in the kernel + version given by __LINUX_KERNEL_VERSION. We are not always exactly + recording the correct versions in which the features were + introduced. If somebody cares these values can afterwards be + corrected. Most of the numbers here are set corresponding to + 2.2.0. */ + +/* `getcwd' system call. */ +#if __LINUX_KERNEL_VERSION >= 131584 +# define __ASSUME_GETCWD_SYSCALL 1 +#endif + +/* When was `poll' introduced? */ +#if __LINUX_KERNEL_VERSION >= 131584 +# define __ASSUME_POLL_SYSCALL 1 +#endif + +/* Real-time signal became usable in 2.1.70. */ +#if __LINUX_KERNEL_VERSION >= 131398 +# define __ASSUME_REALTIME_SIGNALS 1 +#endif + +/* When were the `pread'/`pwrite' syscalls introduced? */ +#if __LINUX_KERNEL_VERSION >= 131584 +# define __ASSUME_PREAD_SYSCALL 1 +# define __ASSUME_PWRITE_SYSCALL 1 +#endif + +/* When was `poll' introduced? */ +#if __LINUX_KERNEL_VERSION >= 131584 +# define __ASSUME_POLL_SYSCALL 1 +#endif + +/* The `lchown' syscall was introduced in 2.1.80. */ +#if __LINUX_KERNEL_VERSION >= 131408 +# define __ASSUME_LCHOWN_SYSCALL 1 +#endif + +/* When did the `setresuid' sysall became available? */ +#if __LINUX_KERNEL_VERSION >= 131584 && !defined __sparc__ +# define __ASSUME_SETRESUID_SYSCALL 1 +#endif + +/* The SIOCGIFNAME ioctl is available starting with 2.1.50. */ +#if __LINUX_KERNEL_VERSION >= 131408 +# define __ASSUME_SIOCGIFNAME 1 +#endif + +/* MSG_NOSIGNAL was at least available with Linux 2.2.0. */ +#if __LINUX_KERNEL_VERSION >= 131584 +# define __ASSUME_MSG_NOSIGNAL 1 +#endif + +/* On x86 another `getrlimit' syscall was added in 2.3.25. */ +#if __LINUX_KERNEL_VERSION >= 131865 && defined __i386__ +# define __ASSUME_NEW_GETRLIMIT_SYSCALL 1 +#endif + +/* On x86 the truncate64/ftruncate64 syscalls were introduced in 2.3.31. */ +#if __LINUX_KERNEL_VERSION >= 131871 && defined __i386__ +# define __ASSUME_TRUNCATE64_SYSCALL 1 +#endif + +/* On x86 the mmap2 syscall was introduced in 2.3.31. */ +#if __LINUX_KERNEL_VERSION >= 131871 && defined __i386__ +# define __ASSUME_MMAP2_SYSCALL 1 +#endif + +/* On x86 the stat64/lstat64/fstat64 syscalls were introduced in 2.3.34. */ +#if __LINUX_KERNEL_VERSION >= 131874 && defined __i386__ +# define __ASSUME_STAT64_SYSCALL 1 +#endif + +/* On sparc and ARM the truncate64/ftruncate64/mmap2/stat64/lstat64/fstat64 + syscalls were introduced in 2.3.35. */ +#if __LINUX_KERNEL_VERSION >= 131875 && (defined __sparc__ || defined __arm__) +# define __ASSUME_TRUNCATE64_SYSCALL 1 +# define __ASSUME_MMAP2_SYSCALL 1 +# define __ASSUME_STAT64_SYSCALL 1 +#endif + +/* I know for sure that getrlimit are in 2.3.35 on powerpc. */ +#if __LINUX_KERNEL_VERSION >= 131875 && defined __powerpc__ +# define __ASSUME_NEW_GETRLIMIT_SYSCALL 1 +#endif + +/* I know for sure that these are in 2.3.35 on powerpc. But PowerPC64 does not + support separate 64-bit syscalls, already 64-bit */ +#if __LINUX_KERNEL_VERSION >= 131875 && defined __powerpc__ \ + && !defined __powerpc64__ +# define __ASSUME_TRUNCATE64_SYSCALL 1 +# define __ASSUME_STAT64_SYSCALL 1 +#endif + +/* Linux 2.3.39 introduced 32bit UID/GIDs. Some platforms had 32 + bit type all along. */ +#if __LINUX_KERNEL_VERSION >= 131879 || defined __powerpc__ || defined __mips__ +# define __ASSUME_32BITUIDS 1 +#endif + +/* Linux 2.3.39 sparc added setresuid. */ +#if __LINUX_KERNEL_VERSION >= 131879 && defined __sparc__ +# define __ASSUME_SETRESUID_SYSCALL 1 +#endif + +#if __LINUX_KERNEL_VERSION >= 131879 +# define __ASSUME_SETRESGID_SYSCALL 1 +#endif + +/* Linux 2.3.39 introduced IPC64. Except for powerpc. */ +#if __LINUX_KERNEL_VERSION >= 131879 && !defined __powerpc__ +# define __ASSUME_IPC64 1 +#endif + +/* MIPS platforms had IPC64 all along. */ +#if defined __mips__ +# define __ASSUME_IPC64 1 +#endif + +/* We can use the LDTs for threading with Linux 2.3.99 and newer. */ +#if __LINUX_KERNEL_VERSION >= 131939 +# define __ASSUME_LDT_WORKS 1 +#endif + +/* Linux 2.4.0 on PPC introduced a correct IPC64. But PowerPC64 does not + support a separate 64-bit sys call, already 64-bit */ +#if __LINUX_KERNEL_VERSION >= 132096 && defined __powerpc__ \ + && !defined __powerpc64__ +# define __ASSUME_IPC64 1 +#endif + +/* SH kernels got stat64, mmap2, and truncate64 during 2.4.0-test. */ +#if __LINUX_KERNEL_VERSION >= 132096 && defined __sh__ +# define __ASSUME_TRUNCATE64_SYSCALL 1 +# define __ASSUME_MMAP2_SYSCALL 1 +# define __ASSUME_STAT64_SYSCALL 1 +#endif + +/* The changed st_ino field appeared in 2.4.0-test6. But we cannot + distinguish this version from other 2.4.0 releases. Therefore play + save and assume it available is for 2.4.1 and up. However, SH is lame, + and still does not have a 64-bit inode field. */ +#if __LINUX_KERNEL_VERSION >= 132097 && !defined __alpha__ && !defined __sh__ +# define __ASSUME_ST_INO_64_BIT 1 +#endif + +/* To support locking of large files a new fcntl() syscall was introduced + in 2.4.0-test7. We test for 2.4.1 for the earliest version we know + the syscall is available. */ +#if __LINUX_KERNEL_VERSION >= 132097 && (defined __i386__ || defined __sparc__) +# define __ASSUME_FCNTL64 1 +#endif + +/* The AT_CLKTCK auxiliary vector entry was introduction in the 2.4.0 + series. */ +#if __LINUX_KERNEL_VERSION >= 132097 +# define __ASSUME_AT_CLKTCK 1 +#endif + +/* Arm got fcntl64 in 2.4.4, PowerPC and SH have it also in 2.4.4 (I + don't know when it got introduced). But PowerPC64 does not support + separate FCNTL64 call, FCNTL is already 64-bit */ +#if __LINUX_KERNEL_VERSION >= 132100 \ + && (defined __arm__ || defined __powerpc__ || defined __sh__) \ + && !defined __powerpc64__ +# define __ASSUME_FCNTL64 1 +#endif + +/* The getdents64 syscall was introduced in 2.4.0-test7. We test for + 2.4.1 for the earliest version we know the syscall is available. */ +#if __LINUX_KERNEL_VERSION >= 132097 +# define __ASSUME_GETDENTS64_SYSCALL 1 +#endif + +/* When did O_DIRECTORY became available? Early in 2.3 but when? + Be safe, use 2.3.99. */ +#if __LINUX_KERNEL_VERSION >= 131939 +# define __ASSUME_O_DIRECTORY 1 +#endif + +/* Starting with one of the 2.4.0 pre-releases the Linux kernel passes + up the page size information. */ +#if __LINUX_KERNEL_VERSION >= 132097 +# define __ASSUME_AT_PAGESIZE 1 +#endif + +/* Starting with at least 2.4.0 the kernel passes the uid/gid unconditionally + up to the child. */ +#if __LINUX_KERNEL_VERSION >= 132097 +# define __ASSUME_AT_XID 1 +#endif + +/* Starting with 2.4.5 kernels PPC passes the AUXV in the standard way + and the vfork syscall made it into the official kernel. */ +#if __LINUX_KERNEL_VERSION >= (132096+5) && defined __powerpc__ +# define __ASSUME_STD_AUXV 1 +# define __ASSUME_VFORK_SYSCALL 1 +#endif + +/* Starting with 2.4.5 kernels the mmap2 syscall made it into the official + kernel. But PowerPC64 does not support a separate MMAP2 call. */ +#if __LINUX_KERNEL_VERSION >= (132096+5) && defined __powerpc__ \ + && !defined __powerpc64__ +# define __ASSUME_MMAP2_SYSCALL 1 +#endif + +/* Starting with 2.4.21 PowerPC implements the new prctl syscall. + This allows applications to get/set the Floating Point Exception Mode. */ +#if __LINUX_KERNEL_VERSION >= (132096+21) && defined __powerpc__ +# define __ASSUME_NEW_PRCTL_SYSCALL 1 +#endif + +/* Starting with 2.4.21 the PowerPC32 clone syscall works as expected. */ +#if __LINUX_KERNEL_VERSION >= (132096+21) && defined __powerpc__ \ + && !defined __powerpc64__ +# define __ASSUME_FIXED_CLONE_SYSCALL 1 +#endif + +/* Starting with 2.4.21 PowerPC64 implements the new rt_sigreturn syscall. + The new rt_sigreturn takes an ucontext pointer allowing rt_sigreturn + to be used in the set/swapcontext implementation. */ +#if __LINUX_KERNEL_VERSION >= (132096+21) && defined __powerpc64__ +# define __ASSUME_NEW_RT_SIGRETURN_SYSCALL 1 +#endif + +/* On x86, the set_thread_area syscall was introduced in 2.5.29, but its + semantics was changed in 2.5.30, and again after 2.5.31. */ +#if __LINUX_KERNEL_VERSION >= 132384 && defined __i386__ +# define __ASSUME_SET_THREAD_AREA_SYSCALL 1 +#endif + +/* The vfork syscall on x86 and arm was definitely available in 2.4. */ +#if __LINUX_KERNEL_VERSION >= 132097 && (defined __i386__ || defined __arm__) +# define __ASSUME_VFORK_SYSCALL 1 +#endif + +/* There are an infinite number of PA-RISC kernel versions numbered + 2.4.0. But they've not really been released as such. We require + and expect the final version here. */ +#ifdef __hppa__ +# define __ASSUME_32BITUIDS 1 +# define __ASSUME_TRUNCATE64_SYSCALL 1 +# define __ASSUME_MMAP2_SYSCALL 1 +# define __ASSUME_STAT64_SYSCALL 1 +# define __ASSUME_IPC64 1 +# define __ASSUME_ST_INO_64_BIT 1 +# define __ASSUME_FCNTL64 1 +# define __ASSUME_GETDENTS64_SYSCALL 1 +#endif + +/* Alpha switched to a 64-bit timeval sometime before 2.2.0. */ +#if __LINUX_KERNEL_VERSION >= 131584 && defined __alpha__ +# define __ASSUME_TIMEVAL64 1 +#endif + +#if defined __mips__ && _MIPS_SIM == _ABIN32 +# define __ASSUME_FCNTL64 1 +#endif + +/* The late 2.5 kernels saw a lot of new CLONE_* flags. Summarize + their availability with one define. The changes were made first + for i386 and the have to be done separately for the other archs. + For i386 we pick 2.5.50 as the first version with support. */ +#if __LINUX_KERNEL_VERSION >= 132402 && defined __i386__ +# define __ASSUME_CLONE_THREAD_FLAGS 1 +#endif + +/* Support for various CLOEXEC and NONBLOCK flags was added for x86, + x86-64, PPC, IA-64, SPARC< and S390 in 2.6.23. */ +#if __LINUX_KERNEL_VERSION >= 0x020617 \ + && (defined __i386__ || defined __x86_64__ || defined __powerpc__ \ + || defined __ia64__ || defined __sparc__ || defined __s390__) +# define __ASSUME_O_CLOEXEC 1 +#endif + +/* These features were surely available with 2.4.12. */ +#if __LINUX_KERNEL_VERSION >= 132108 && defined __mc68000__ +# define __ASSUME_MMAP2_SYSCALL 1 +# define __ASSUME_TRUNCATE64_SYSCALL 1 +# define __ASSUME_STAT64_SYSCALL 1 +# define __ASSUME_FCNTL64 1 +# define __ASSUME_VFORK_SYSCALL 1 +#endif + +/* Beginning with 2.5.63 support for realtime and monotonic clocks and + timers based on them is available. */ +#if __LINUX_KERNEL_VERSION >= 132415 +# define __ASSUME_POSIX_TIMERS 1 +#endif + +/* Beginning with 2.6.12 the clock and timer supports CPU clocks. */ +#if __LINUX_KERNEL_VERSION >= 0x2060c +# define __ASSUME_POSIX_CPU_TIMERS 1 +#endif + +/* The late 2.5 kernels saw a lot of new CLONE_* flags. Summarize + their availability with one define. The changes were made first + for i386 and the have to be done separately for the other archs. + For ia64, s390*, PPC, x86-64 we pick 2.5.64 as the first version + with support. */ +#if __LINUX_KERNEL_VERSION >= 132416 \ + && (defined __ia64__ || defined __s390__ || defined __powerpc__ \ + || defined __x86_64__ || defined __sh__) +# define __ASSUME_CLONE_THREAD_FLAGS 1 +#endif + +/* With kernel 2.4.17 we always have netlink support. */ +#if __LINUX_KERNEL_VERSION >= (132096+17) +# define __ASSUME_NETLINK_SUPPORT 1 +#endif + +/* The requeue futex functionality was introduced in 2.5.70. */ +#if __LINUX_KERNEL_VERSION >= 132422 +# define __ASSUME_FUTEX_REQUEUE 1 +#endif + +/* The statfs64 syscalls are available in 2.5.74. */ +#if __LINUX_KERNEL_VERSION >= 132426 +# define __ASSUME_STATFS64 1 +#endif + +/* Starting with at least 2.5.74 the kernel passes the setuid-like exec + flag unconditionally up to the child. */ +#if __LINUX_KERNEL_VERSION >= 132426 +# define __ASSUME_AT_SECURE 1 +#endif + +/* Starting with the 2.5.75 kernel the kernel fills in the correct value + in the si_pid field passed as part of the siginfo_t struct to signal + handlers. */ +#if __LINUX_KERNEL_VERSION >= 132427 +# define __ASSUME_CORRECT_SI_PID 1 +#endif + +/* The tgkill syscall was instroduced for i386 in 2.5.75. For Alpha + it was introduced in 2.6.0-test1 which unfortunately cannot be + distinguished from 2.6.0. On x86-64, ppc, and ppc64 it was + introduced in 2.6.0-test3. */ +#if (__LINUX_KERNEL_VERSION >= 132427 && defined __i386__) \ + || (__LINUX_KERNEL_VERSION >= 132609 && defined __alpha__) \ + || (__LINUX_KERNEL_VERSION >= 132609 && defined __x86_64__) \ + || (__LINUX_KERNEL_VERSION >= 132609 && defined __powerpc__) \ + || (__LINUX_KERNEL_VERSION >= 132609 && defined __sh__) +# define __ASSUME_TGKILL 1 +#endif + +/* The utimes syscall has been available for some architectures + forever. For x86 it was introduced after 2.5.75, for x86-64, + ppc, and ppc64 it was introduced in 2.6.0-test3. */ +#if defined __alpha__ || defined __ia64__ || defined __hppa__ \ + || defined __sparc__ \ + || (__LINUX_KERNEL_VERSION > 132427 && defined __i386__) \ + || (__LINUX_KERNEL_VERSION > 132609 && defined __x86_64__) \ + || (__LINUX_KERNEL_VERSION >= 132609 && defined __powerpc__) \ + || (__LINUX_KERNEL_VERSION >= 132609 && defined __sh__) +# define __ASSUME_UTIMES 1 +#endif + +// XXX Disabled for now since the semantics we want is not achieved. +#if 0 +/* The CLONE_STOPPED flag was introduced in the 2.6.0-test1 series. */ +#if __LINUX_KERNEL_VERSION >= 132609 +# define __ASSUME_CLONE_STOPPED 1 +#endif +#endif + +/* The fixed version of the posix_fadvise64 syscall appeared in + 2.6.0-test3. At least for x86. Powerpc support appeared in + 2.6.2, but for 32-bit userspace only. */ +#if (__LINUX_KERNEL_VERSION >= 132609 && defined __i386__) \ + || (__LINUX_KERNEL_VERSION >= 132610 && defined __powerpc__ \ + && !defined __powerpc64__) +# define __ASSUME_FADVISE64_64_SYSCALL 1 +#endif + +/* The PROT_GROWSDOWN/PROT_GROWSUP flags were introduced in the 2.6.0-test + series. */ +#if __LINUX_KERNEL_VERSION >= 132609 +# define __ASSUME_PROT_GROWSUPDOWN 1 +#endif + +/* Starting with 2.6.0 PowerPC adds signal/swapcontext support for Vector + SIMD (AKA Altivec, VMX) instructions and register state. This changes + the overall size of the sigcontext and adds the swapcontext syscall. */ +#if __LINUX_KERNEL_VERSION >= 132608 && defined __powerpc__ +# define __ASSUME_SWAPCONTEXT_SYSCALL 1 +#endif + +/* The CLONE_DETACHED flag is not necessary in 2.6.2 kernels, it is + implied. */ +#if __LINUX_KERNEL_VERSION >= 132610 +# define __ASSUME_NO_CLONE_DETACHED 1 +#endif + +/* Starting with version 2.6.4-rc1 the getdents syscall returns d_type + information as well and in between 2.6.5 and 2.6.8 most compat wrappers + were fixed too. Except s390{,x} which was fixed in 2.6.11. */ +#if (__LINUX_KERNEL_VERSION >= 0x020608 && !defined __s390__) \ + || (__LINUX_KERNEL_VERSION >= 0x02060b && defined __s390__) +# define __ASSUME_GETDENTS32_D_TYPE 1 +#endif + +/* Starting with version 2.5.3, the initial location returned by `brk' + after exec is always rounded up to the next page. */ +#if __LINUX_KERNEL_VERSION >= 132355 +# define __ASSUME_BRK_PAGE_ROUNDED 1 +#endif + +/* Starting with version 2.6.9, the waitid system call is available. + Except for powerpc and powerpc64, where it is available in 2.6.12. */ +#if (__LINUX_KERNEL_VERSION >= 0x020609 && !defined __powerpc__) \ + || (__LINUX_KERNEL_VERSION >= 0x02060c && defined __powerpc__) +# define __ASSUME_WAITID_SYSCALL 1 +#endif + +/* Starting with version 2.6.9, SSI_IEEE_RAISE_EXCEPTION exists. */ +#if __LINUX_KERNEL_VERSION >= 0x020609 && defined __alpha__ +#define __ASSUME_IEEE_RAISE_EXCEPTION 1 +#endif + +/* Support for the FUTEX_CLOCK_REALTIME flag was added in 2.6.29. */ +#if __LINUX_KERNEL_VERSION >= 0x02061d +# define __ASSUME_FUTEX_CLOCK_REALTIME 1 +#endif + +/* Support for PI futexes was added in 2.6.18. */ +#if __LINUX_KERNEL_VERSION >= 0x020612 +# define __ASSUME_FUTEX_LOCK_PI 1 +#endif + +/* Support for private futexes was added in 2.6.22. */ +#if __LINUX_KERNEL_VERSION >= 0x020616 +# define __ASSUME_PRIVATE_FUTEX 1 +#endif + + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/kernel_sigaction.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/kernel_sigaction.h new file mode 100644 index 00000000..0a35ac8c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/kernel_sigaction.h @@ -0,0 +1,36 @@ +#ifndef _BITS_SIGACTION_STRUCT_H +#define _BITS_SIGACTION_STRUCT_H + +/* This file provides whatever this particular arch's kernel thinks + * the sigaction struct should look like... */ + + +#if defined(__ia64__) + +#undef HAVE_SA_RESTORER + +#else + +#define HAVE_SA_RESTORER +/* This is the sigaction structure from the Linux 2.1.20 kernel. */ +struct old_kernel_sigaction { + __sighandler_t k_sa_handler; + unsigned long sa_mask; + unsigned long sa_flags; + void (*sa_restorer)(void); +}; +/* In uclibc, userspace struct sigaction is identical to + * "new" struct kernel_sigaction (one from the Linux 2.1.68 kernel). + * See sigaction.h + */ + +extern int __syscall_sigaction(int, const struct old_kernel_sigaction *, + struct old_kernel_sigaction *); + +#endif + + +extern int __syscall_rt_sigaction(int, const struct sigaction *, + struct sigaction *, size_t); + +#endif /* _BITS_SIGACTION_STRUCT_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/kernel_stat.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/kernel_stat.h new file mode 100644 index 00000000..571c08fa --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/kernel_stat.h @@ -0,0 +1,2 @@ +/* bits/kernel_stat.h is architecture specific. */ +#error "This file must be supplied by every Linux architecture." diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/kernel_types.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/kernel_types.h new file mode 100644 index 00000000..1c23ebfe --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/kernel_types.h @@ -0,0 +1,20 @@ +#ifndef _BITS_KERNEL_TYPES_H +#define _BITS_KERNEL_TYPES_H + +/* Sigh. We need to carefully wrap this one... No guarantees + * that the asm/posix_types.h kernel header is working. Many + * arches have broken headers that introduce tons of gratuitous + * conflicts with uClibc's namespace. See bits/kernel_types.h + * for i386, arm, etc for examples... */ +#warning You really should include a proper bits/kernel_types.h for your architecture + +#ifndef __GLIBC__ +#define __GLIBC__ 2 +#include +#undef __GLIBC__ +#else +#include +#endif + + +#endif /* _BITS_KERNEL_TYPES_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/local_lim.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/local_lim.h new file mode 100644 index 00000000..a263b5d2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/local_lim.h @@ -0,0 +1,95 @@ +/* Minimum guaranteed maximum values for system limits. Linux version. + Copyright (C) 1993-1998,2000,2002-2004,2008 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* The kernel header pollutes the namespace with the NR_OPEN symbol + and defines LINK_MAX although filesystems have different maxima. A + similar thing is true for OPEN_MAX: the limit can be changed at + runtime and therefore the macro must not be defined. Remove this + after including the header if necessary. */ +#ifndef NR_OPEN +# define __undef_NR_OPEN +#endif +#ifndef LINK_MAX +# define __undef_LINK_MAX +#endif +#ifndef OPEN_MAX +# define __undef_OPEN_MAX +#endif +#ifndef ARG_MAX +# define __undef_ARG_MAX +#endif + +/* The kernel sources contain a file with all the needed information. */ +#include + +/* Have to remove NR_OPEN? */ +#ifdef __undef_NR_OPEN +# undef NR_OPEN +# undef __undef_NR_OPEN +#endif +/* Have to remove LINK_MAX? */ +#ifdef __undef_LINK_MAX +# undef LINK_MAX +# undef __undef_LINK_MAX +#endif +/* Have to remove OPEN_MAX? */ +#ifdef __undef_OPEN_MAX +# undef OPEN_MAX +# undef __undef_OPEN_MAX +#endif +/* Have to remove ARG_MAX? */ +#ifdef __undef_ARG_MAX +# undef ARG_MAX +# undef __undef_ARG_MAX +#endif + +/* The number of data keys per process. */ +#define _POSIX_THREAD_KEYS_MAX 128 +/* This is the value this implementation supports. */ +#define PTHREAD_KEYS_MAX 1024 + +/* Controlling the iterations of destructors for thread-specific data. */ +#define _POSIX_THREAD_DESTRUCTOR_ITERATIONS 4 +/* Number of iterations this implementation does. */ +#define PTHREAD_DESTRUCTOR_ITERATIONS _POSIX_THREAD_DESTRUCTOR_ITERATIONS + +/* The number of threads per process. */ +#define _POSIX_THREAD_THREADS_MAX 64 + +/* Maximum amount by which a process can descrease its asynchronous I/O + priority level. */ +#define AIO_PRIO_DELTA_MAX 20 + +/* Minimum size for a thread. We are free to choose a reasonable value. */ +#define PTHREAD_STACK_MIN 16384 + +/* Maximum number of timer expiration overruns. */ +#define DELAYTIMER_MAX 2147483647 + +/* Maximum tty name length. */ +#define TTY_NAME_MAX 32 + +/* Maximum login name length. This is arbitrary. */ +#define LOGIN_NAME_MAX 256 + +/* Maximum host name length. */ +#define HOST_NAME_MAX 64 + +/* Maximum message queue priority level. */ +#define MQ_PRIO_MAX 32768 diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/locale.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/locale.h new file mode 100644 index 00000000..50064b53 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/locale.h @@ -0,0 +1,44 @@ +/* Definition of locale category symbol values. + Copyright (C) 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#if !defined _LOCALE_H && !defined _LANGINFO_H +# error "Never use directly; include instead." +#endif + +#ifndef _BITS_LOCALE_H +#define _BITS_LOCALE_H 1 + +enum +{ + __LC_CTYPE = 0, + __LC_NUMERIC = 1, + __LC_TIME = 2, + __LC_COLLATE = 3, + __LC_MONETARY = 4, + __LC_MESSAGES = 5, + __LC_ALL = 6, + __LC_PAPER = 7, + __LC_NAME = 8, + __LC_ADDRESS = 9, + __LC_TELEPHONE = 10, + __LC_MEASUREMENT = 11, + __LC_IDENTIFICATION = 12 +}; + +#endif /* bits/locale.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/mathcalls.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/mathcalls.h new file mode 100644 index 00000000..1e92b527 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/mathcalls.h @@ -0,0 +1,380 @@ +/* Prototype declarations for math functions; helper file for . + Copyright (C) 1996-2002, 2003, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* NOTE: Because of the special way this file is used by , this + file must NOT be protected from multiple inclusion as header files + usually are. + + This file provides prototype declarations for the math functions. + Most functions are declared using the macro: + + __MATHCALL (NAME,[_r], (ARGS...)) + + This means there is a function `NAME' returning `double' and a function + `NAMEf' returning `float'. Each place `_Mdouble_' appears in the + prototype, that is actually `double' in the prototype for `NAME' and + `float' in the prototype for `NAMEf'. Reentrant variant functions are + called `NAME_r' and `NAMEf_r'. + + Functions returning other types like `int' are declared using the macro: + + __MATHDECL (TYPE, NAME,[_r], (ARGS...)) + + This is just like __MATHCALL but for a function returning `TYPE' + instead of `_Mdouble_'. In all of these cases, there is still + both a `NAME' and a `NAMEf' that takes `float' arguments. + + Note that there must be no whitespace before the argument passed for + NAME, to make token pasting work with -traditional. */ + +#ifndef _MATH_H +# error "Never include directly; include instead." +#endif + + +/* __MATHCALLX(type,function,[suffix],args,attrib) and + * __MATHCALLI(type,function,[suffix],args) include libm_hidden_def + * (for "double" versions only, xxxf and xxxl do not get this treatment). + * + * __MATHDECL(type,function,[suffix],args) does not. + * __MATHCALL(function,[suffix],args) also does not + * (it is just a shortcut to __MATHDECL(_Mdouble_,function,[suffix],args)). + * + * __MATHDECL_PRIV(type,function,[suffix],args,attrib) + * includes libm_hidden_def (always) and declares __foo, not foo. + */ + + +/* Trigonometric functions. */ + +_Mdouble_BEGIN_NAMESPACE +/* Arc cosine of X. */ +__MATHCALLI (acos,, (_Mdouble_ __x)) +/* Arc sine of X. */ +__MATHCALLI (asin,, (_Mdouble_ __x)) +/* Arc tangent of X. */ +__MATHCALLI (atan,, (_Mdouble_ __x)) +/* Arc tangent of Y/X. */ +__MATHCALLI (atan2,, (_Mdouble_ __y, _Mdouble_ __x)) + +/* Cosine of X. */ +__MATHCALLI (cos,, (_Mdouble_ __x)) +/* Sine of X. */ +__MATHCALLI (sin,, (_Mdouble_ __x)) +/* Tangent of X. */ +__MATHCALLI (tan,, (_Mdouble_ __x)) + +/* Hyperbolic functions. */ + +/* Hyperbolic cosine of X. */ +__MATHCALLI (cosh,, (_Mdouble_ __x)) +/* Hyperbolic sine of X. */ +__MATHCALLI (sinh,, (_Mdouble_ __x)) +/* Hyperbolic tangent of X. */ +__MATHCALLI (tanh,, (_Mdouble_ __x)) +_Mdouble_END_NAMESPACE + +#if 0 /*def __USE_GNU*/ +/* Cosine and sine of X. */ +__MATHDECL (void,sincos,, + (_Mdouble_ __x, _Mdouble_ *__sinx, _Mdouble_ *__cosx)) +#endif + +#if defined __USE_MISC || defined __USE_XOPEN_EXTENDED || defined __USE_ISOC99 +__BEGIN_NAMESPACE_C99 +/* Hyperbolic arc cosine of X. */ +__MATHCALLI (acosh,, (_Mdouble_ __x)) +/* Hyperbolic arc sine of X. */ +__MATHCALLI (asinh,, (_Mdouble_ __x)) +/* Hyperbolic arc tangent of X. */ +__MATHCALLI (atanh,, (_Mdouble_ __x)) +__END_NAMESPACE_C99 +#endif + +/* Exponential and logarithmic functions. */ + +_Mdouble_BEGIN_NAMESPACE +/* Exponential function of X. */ +__MATHCALLI (exp,, (_Mdouble_ __x)) + +/* Break VALUE into a normalized fraction and an integral power of 2. */ +__MATHCALLI (frexp,, (_Mdouble_ __x, int *__exponent)) + +/* X times (two to the EXP power). */ +__MATHCALLI (ldexp,, (_Mdouble_ __x, int __exponent)) + +/* Natural logarithm of X. */ +__MATHCALLI (log,, (_Mdouble_ __x)) + +/* Base-ten logarithm of X. */ +__MATHCALLI (log10,, (_Mdouble_ __x)) + +/* Break VALUE into integral and fractional parts. */ +__MATHCALLI (modf,, (_Mdouble_ __x, _Mdouble_ *__iptr)) +_Mdouble_END_NAMESPACE + +#if 0 /*def __USE_GNU*/ +/* A function missing in all standards: compute exponent to base ten. */ +__MATHCALL (exp10,, (_Mdouble_ __x)) +/* Another name occasionally used. */ +__MATHCALL (pow10,, (_Mdouble_ __x)) +#endif + +#if defined __USE_MISC || defined __USE_XOPEN_EXTENDED || defined __USE_ISOC99 +__BEGIN_NAMESPACE_C99 +/* Return exp(X) - 1. */ +__MATHCALLI (expm1,, (_Mdouble_ __x)) + +/* Return log(1 + X). */ +__MATHCALLI (log1p,, (_Mdouble_ __x)) + +/* Return the base 2 signed integral exponent of X. */ +__MATHCALLI (logb,, (_Mdouble_ __x)) +__END_NAMESPACE_C99 +#endif + +#ifdef __USE_ISOC99 +__BEGIN_NAMESPACE_C99 +/* Compute base-2 exponential of X. */ +__MATHCALLI (exp2,, (_Mdouble_ __x)) + +/* Compute base-2 logarithm of X. */ +__MATHCALL (log2,, (_Mdouble_ __x)) +__END_NAMESPACE_C99 +#endif + + +/* Power functions. */ + +_Mdouble_BEGIN_NAMESPACE +/* Return X to the Y power. */ +__MATHCALLI (pow,, (_Mdouble_ __x, _Mdouble_ __y)) + +/* Return the square root of X. */ +__MATHCALLI (sqrt,, (_Mdouble_ __x)) +_Mdouble_END_NAMESPACE + +#if defined __USE_MISC || defined __USE_XOPEN || defined __USE_ISOC99 +__BEGIN_NAMESPACE_C99 +/* Return `sqrt(X*X + Y*Y)'. */ +__MATHCALLI (hypot,, (_Mdouble_ __x, _Mdouble_ __y)) +__END_NAMESPACE_C99 +#endif + +#if defined __USE_MISC || defined __USE_XOPEN_EXTENDED || defined __USE_ISOC99 +__BEGIN_NAMESPACE_C99 +/* Return the cube root of X. */ +__MATHCALLI (cbrt,, (_Mdouble_ __x)) +__END_NAMESPACE_C99 +#endif + + +/* Nearest integer, absolute value, and remainder functions. */ + +_Mdouble_BEGIN_NAMESPACE +/* Smallest integral value not less than X. */ +__MATHCALLX (ceil,, (_Mdouble_ __x), (__const__)) + +/* Absolute value of X. */ +__MATHCALLX (fabs,, (_Mdouble_ __x), (__const__)) + +/* Largest integer not greater than X. */ +__MATHCALLX (floor,, (_Mdouble_ __x), (__const__)) + +/* Floating-point modulo remainder of X/Y. */ +__MATHCALLI (fmod,, (_Mdouble_ __x, _Mdouble_ __y)) + + +/* Return 0 if VALUE is finite or NaN, +1 if it + is +Infinity, -1 if it is -Infinity. */ +__MATHDECL_PRIV (int,isinf,, (_Mdouble_ __value), (__const__)) + +/* Return nonzero if VALUE is finite and not NaN. */ +__MATHDECL_PRIV (int,finite,, (_Mdouble_ __value), (__const__)) +_Mdouble_END_NAMESPACE + +#ifdef __USE_MISC +#if 0 +/* Return 0 if VALUE is finite or NaN, +1 if it + is +Infinity, -1 if it is -Infinity. */ +__MATHDECL_PRIV (int,isinf,, (_Mdouble_ __value), (__const__)) + +/* Return nonzero if VALUE is finite and not NaN. */ +__MATHDECL_PRIV (int,finite,, (_Mdouble_ __value), (__const__)) +#endif +/* Return the remainder of X/Y. */ +__MATHCALL (drem,, (_Mdouble_ __x, _Mdouble_ __y)) + + +/* Return the fractional part of X after dividing out `ilogb (X)'. */ +__MATHCALL (significand,, (_Mdouble_ __x)) +#endif /* Use misc. */ + +#if defined __USE_MISC || defined __USE_ISOC99 +__BEGIN_NAMESPACE_C99 +/* Return X with its signed changed to Y's. */ +__MATHCALLX (copysign,, (_Mdouble_ __x, _Mdouble_ __y), (__const__)) +__END_NAMESPACE_C99 +#endif + +#ifdef __USE_ISOC99 +__BEGIN_NAMESPACE_C99 +/* Return representation of NaN for double type. */ +__MATHCALLX (nan,, (__const char *__tagb), (__const__)) +__END_NAMESPACE_C99 +#endif + +#if defined __USE_MISC || defined __USE_XOPEN || defined __USE_ISOC99 +/* Return nonzero if VALUE is not a number. */ +__BEGIN_NAMESPACE_C99 +__MATHDECL_PRIV (int,isnan,, (_Mdouble_ __value), (__const__)) +__END_NAMESPACE_C99 +#endif + +#if defined __USE_MISC || defined __USE_XOPEN +# ifdef __DO_XSI_MATH__ +/* Bessel functions. */ +__MATHCALL (j0,, (_Mdouble_)) +__MATHCALL (j1,, (_Mdouble_)) +__MATHCALL (jn,, (int, _Mdouble_)) +__MATHCALL (y0,, (_Mdouble_)) +__MATHCALL (y1,, (_Mdouble_)) +__MATHCALL (yn,, (int, _Mdouble_)) +# endif +#endif + + +#if defined __USE_MISC || defined __USE_XOPEN || defined __USE_ISOC99 +__BEGIN_NAMESPACE_C99 +/* Error and gamma functions. */ +__MATHCALLI (erf,, (_Mdouble_)) +__MATHCALLI (erfc,, (_Mdouble_)) +__MATHCALLI (lgamma,, (_Mdouble_)) +__END_NAMESPACE_C99 +#endif + +#ifdef __USE_ISOC99 +__BEGIN_NAMESPACE_C99 +/* True gamma function. */ +__MATHCALLI (tgamma,, (_Mdouble_)) +__END_NAMESPACE_C99 +#endif + +#if defined __USE_MISC || defined __USE_XOPEN +/* Obsolete alias for `lgamma'. */ +__MATHCALL (gamma,, (_Mdouble_)) +#endif + +#ifdef __USE_MISC +/* Reentrant version of lgamma. This function uses the global variable + `signgam'. The reentrant version instead takes a pointer and stores + the value through it. */ +__MATHCALL (lgamma,_r, (_Mdouble_, int *__signgamp)) +#endif + + +#if defined __USE_MISC || defined __USE_XOPEN_EXTENDED || defined __USE_ISOC99 +__BEGIN_NAMESPACE_C99 +/* Return the integer nearest X in the direction of the + prevailing rounding mode. */ +__MATHCALLI (rint,, (_Mdouble_ __x)) + +/* Return X + epsilon if X < Y, X - epsilon if X > Y. */ +__MATHCALLX (nextafter,, (_Mdouble_ __x, _Mdouble_ __y), (__const__)) +# if defined __USE_ISOC99 && !defined __LDBL_COMPAT +__MATHCALLX (nexttoward,, (_Mdouble_ __x, long double __y), (__const__)) +# endif + +/* Return the remainder of integer divison X / Y with infinite precision. */ +__MATHCALLI (remainder,, (_Mdouble_ __x, _Mdouble_ __y)) + +# if defined __USE_MISC || defined __USE_ISOC99 +/* Return X times (2 to the Nth power). */ +__MATHCALLI (scalbn,, (_Mdouble_ __x, int __n)) +# endif + +/* Return the binary exponent of X, which must be nonzero. */ +__MATHDECLI (int,ilogb,, (_Mdouble_ __x)) +#endif + +#ifdef __USE_ISOC99 +/* Return X times (2 to the Nth power). */ +__MATHCALLI (scalbln,, (_Mdouble_ __x, long int __n)) + +/* Round X to integral value in floating-point format using current + rounding direction, but do not raise inexact exception. */ +__MATHCALLI (nearbyint,, (_Mdouble_ __x)) + +/* Round X to nearest integral value, rounding halfway cases away from + zero. */ +__MATHCALLX (round,, (_Mdouble_ __x), (__const__)) + +/* Round X to the integral value in floating-point format nearest but + not larger in magnitude. */ +__MATHCALLX (trunc,, (_Mdouble_ __x), (__const__)) + +/* Compute remainder of X and Y and put in *QUO a value with sign of x/y + and magnitude congruent `mod 2^n' to the magnitude of the integral + quotient x/y, with n >= 3. */ +__MATHCALLI (remquo,, (_Mdouble_ __x, _Mdouble_ __y, int *__quo)) + + +/* Conversion functions. */ + +/* Round X to nearest integral value according to current rounding + direction. */ +__MATHDECLI (long int,lrint,, (_Mdouble_ __x)) +__MATHDECLI (long long int,llrint,, (_Mdouble_ __x)) + +/* Round X to nearest integral value, rounding halfway cases away from + zero. */ +__MATHDECLI (long int,lround,, (_Mdouble_ __x)) +__MATHDECLI (long long int,llround,, (_Mdouble_ __x)) + + +/* Return positive difference between X and Y. */ +__MATHCALLI (fdim,, (_Mdouble_ __x, _Mdouble_ __y)) + +/* Return maximum numeric value from X and Y. */ +__MATHCALLI (fmax,, (_Mdouble_ __x, _Mdouble_ __y)) + +/* Return minimum numeric value from X and Y. */ +__MATHCALLI (fmin,, (_Mdouble_ __x, _Mdouble_ __y)) + + +/* Classify given number. */ +__MATHDECL_PRIV (int, fpclassify,, (_Mdouble_ __value), (__const__)) + +/* Test for negative number. */ +__MATHDECL_PRIV (int, signbit,, (_Mdouble_ __value), (__const__)) + + +/* Multiply-add function computed as a ternary operation. */ +__MATHCALLI (fma,, (_Mdouble_ __x, _Mdouble_ __y, _Mdouble_ __z)) +#endif /* Use ISO C99. */ + +#if defined __USE_MISC || defined __USE_XOPEN_EXTENDED || defined __USE_ISOC99 +__END_NAMESPACE_C99 +#endif + +#if (defined __USE_MISC || defined __USE_XOPEN_EXTENDED) \ + && defined __UCLIBC_SUSV3_LEGACY__ +/* Return X times (2 to the Nth power). */ +__MATHCALL (scalb,, (_Mdouble_ __x, _Mdouble_ __n)) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/mathdef.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/mathdef.h new file mode 100644 index 00000000..00c67241 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/mathdef.h @@ -0,0 +1,43 @@ +/* Copyright (C) 1997, 1998, 1999, 2000, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#if !defined _MATH_H && !defined _COMPLEX_H +# error "Never use directly; include instead" +#endif + +#if defined __USE_ISOC99 && defined _MATH_H && !defined _MATH_H_MATHDEF +# define _MATH_H_MATHDEF 1 + +/* Normally, there is no long double type and the `float' and `double' + expressions are evaluated as `double'. */ +typedef double float_t; /* `float' expressions are evaluated as + `double'. */ +typedef double double_t; /* `double' expressions are evaluated as + `double'. */ + +/* The values returned by `ilogb' for 0 and NaN respectively. */ +# define FP_ILOGB0 (-2147483647) +# define FP_ILOGBNAN 2147483647 + +#endif /* ISO C99 */ + +#ifndef __NO_LONG_DOUBLE_MATH +/* Signal that we do not really have a `long double'. The disables the + declaration of all the `long double' function variants. */ +# define __NO_LONG_DOUBLE_MATH 1 +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/mathinline.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/mathinline.h new file mode 100644 index 00000000..5498af6b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/mathinline.h @@ -0,0 +1,12 @@ +/* This file should provide inline versions of math functions. + + Surround GCC-specific parts with #ifdef __GNUC__, and use `extern __inline'. + + This file should define __MATH_INLINES if functions are actually defined as + inlines. */ + +#if !defined __NO_MATH_INLINES && defined __OPTIMIZE__ + +/* Here goes the real code. */ + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/mman-common.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/mman-common.h new file mode 100644 index 00000000..f00cb1ab --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/mman-common.h @@ -0,0 +1,109 @@ +/* Definitions for POSIX memory map interface. Linux/generic version. + Copyright (C) 1997,2000,2003,2005,2006,2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_MMAN_H +# error "Never use directly; include instead." +#endif + +/* The following definitions basically come from the kernel headers. + But the kernel header is not namespace clean. */ + + +/* Protections are chosen from these bits, OR'd together. The + implementation does not necessarily support PROT_EXEC or PROT_WRITE + without PROT_READ. The only guarantees are that no writing will be + allowed without PROT_WRITE and no access will be allowed for PROT_NONE. */ + +#define PROT_READ 0x1 /* Page can be read. */ +#define PROT_WRITE 0x2 /* Page can be written. */ +#define PROT_EXEC 0x4 /* Page can be executed. */ +#define PROT_NONE 0x0 /* Page can not be accessed. */ +#define PROT_GROWSDOWN 0x01000000 /* Extend change to start of + growsdown vma (mprotect only). */ +#define PROT_GROWSUP 0x02000000 /* Extend change to start of + growsup vma (mprotect only). */ + +/* Sharing types (must choose one and only one of these). */ +#define MAP_SHARED 0x01 /* Share changes. */ +#define MAP_PRIVATE 0x02 /* Changes are private. */ +#ifdef __USE_MISC +# define MAP_TYPE 0x0f /* Mask for type of mapping. */ +#endif + +/* Other flags. */ +#define MAP_FIXED 0x10 /* Interpret addr exactly. */ +#ifdef __USE_MISC +# define MAP_FILE 0 +# define MAP_ANONYMOUS 0x20 /* Don't use a file. */ +# define MAP_ANON MAP_ANONYMOUS +#endif + +/* These are Linux-specific. */ +#ifdef __USE_MISC +# define MAP_GROWSDOWN 0x00100 /* Stack-like segment. */ +# define MAP_DENYWRITE 0x00800 /* ETXTBSY */ +# define MAP_EXECUTABLE 0x01000 /* Mark it as an executable. */ +# define MAP_LOCKED 0x02000 /* Lock the mapping. */ +# define MAP_NORESERVE 0x04000 /* Don't check for reservations. */ +# define MAP_POPULATE 0x08000 /* Populate (prefault) pagetables. */ +# define MAP_NONBLOCK 0x10000 /* Do not block on IO. */ +# define MAP_STACK 0x20000 /* Allocation is for a stack. */ +# define MAP_UNINITIALIZE 0x4000000 /* For anonymous mmap, memory could + be uninitialized. */ +#endif + +/* Flags to `msync'. */ +#define MS_ASYNC 1 /* Sync memory asynchronously. */ +#define MS_SYNC 4 /* Synchronous memory sync. */ +#define MS_INVALIDATE 2 /* Invalidate the caches. */ + +/* Flags for `mlockall'. */ +#define MCL_CURRENT 1 /* Lock all currently mapped pages. */ +#define MCL_FUTURE 2 /* Lock all additions to address + space. */ + +/* Flags for `mremap'. */ +#ifdef __USE_GNU +# define MREMAP_MAYMOVE 1 +# define MREMAP_FIXED 2 +#endif + +/* Advice to `madvise'. */ +#ifdef __USE_BSD +# define MADV_NORMAL 0 /* No further special treatment. */ +# define MADV_RANDOM 1 /* Expect random page references. */ +# define MADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define MADV_WILLNEED 3 /* Will need these pages. */ +# define MADV_DONTNEED 4 /* Don't need these pages. */ +# define MADV_REMOVE 9 /* Remove these pages and resources. */ +# define MADV_DONTFORK 10 /* Do not inherit across fork. */ +# define MADV_DOFORK 11 /* Do inherit across fork. */ +# define MADV_MERGEABLE 12 /* KSM may merge identical pages. */ +# define MADV_UNMERGEABLE 13 /* KSM may not merge identical pages. */ +# define MADV_HWPOISON 100 /* Poison a page for testing. */ +#endif + +/* The POSIX people had to invent similar names for the same things. */ +#ifdef __USE_XOPEN2K +# define POSIX_MADV_NORMAL 0 /* No further special treatment. */ +# define POSIX_MADV_RANDOM 1 /* Expect random page references. */ +# define POSIX_MADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define POSIX_MADV_WILLNEED 3 /* Will need these pages. */ +# define POSIX_MADV_DONTNEED 4 /* Don't need these pages. */ +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/mman.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/mman.h new file mode 100644 index 00000000..11b8e2a8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/mman.h @@ -0,0 +1 @@ +#include diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/mqueue.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/mqueue.h new file mode 100644 index 00000000..df528f87 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/mqueue.h @@ -0,0 +1,32 @@ +/* Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _MQUEUE_H +# error "Never use directly; include instead." +#endif + +typedef int mqd_t; + +struct mq_attr +{ + long int mq_flags; /* Message queue flags. */ + long int mq_maxmsg; /* Maximum number of messages. */ + long int mq_msgsize; /* Maximum message size. */ + long int mq_curmsgs; /* Number of messages currently queued. */ + long int __pad[4]; +}; diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/msq.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/msq.h new file mode 100644 index 00000000..32a49b59 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/msq.h @@ -0,0 +1,77 @@ +/* Copyright (C) 1995, 1996, 1997, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_MSG_H +# error "Never use directly; include instead." +#endif + +#include + +/* Define options for message queue functions. */ +#define MSG_NOERROR 010000 /* no error if message is too big */ +#ifdef __USE_GNU +# define MSG_EXCEPT 020000 /* recv any msg except of specified type */ +#endif + +/* Types used in the structure definition. */ +typedef unsigned long int msgqnum_t; +typedef unsigned long int msglen_t; + + +/* Structure of record for one message inside the kernel. + The type `struct msg' is opaque. */ +struct msqid_ds +{ + struct ipc_perm msg_perm; /* structure describing operation permission */ + __time_t msg_stime; /* time of last msgsnd command */ + unsigned long int __unused1; + __time_t msg_rtime; /* time of last msgrcv command */ + unsigned long int __unused2; + __time_t msg_ctime; /* time of last change */ + unsigned long int __unused3; + unsigned long int __msg_cbytes; /* current number of bytes on queue */ + msgqnum_t msg_qnum; /* number of messages currently on queue */ + msglen_t msg_qbytes; /* max number of bytes allowed on queue */ + __pid_t msg_lspid; /* pid of last msgsnd() */ + __pid_t msg_lrpid; /* pid of last msgrcv() */ + unsigned long int __unused4; + unsigned long int __unused5; +}; + +#ifdef __USE_MISC + +# define msg_cbytes __msg_cbytes + +/* ipcs ctl commands */ +# define MSG_STAT 11 +# define MSG_INFO 12 + +/* buffer for msgctl calls IPC_INFO, MSG_INFO */ +struct msginfo + { + int msgpool; + int msgmap; + int msgmax; + int msgmnb; + int msgmni; + int msgssz; + int msgtql; + unsigned short int msgseg; + }; + +#endif /* __USE_MISC */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/nan.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/nan.h new file mode 100644 index 00000000..bae97f21 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/nan.h @@ -0,0 +1,53 @@ +/* `NAN' constant for IEEE 754 machines. + Copyright (C) 1992,1996,1997,1999,2004,2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _MATH_H +# error "Never use directly; include instead." +#endif + + +/* IEEE Not A Number. */ + +#if __GNUC_PREREQ(3,3) + +# define NAN (__builtin_nanf ("")) + +#elif defined __GNUC__ + +# define NAN \ + (__extension__ \ + ((union { unsigned __l __attribute__ ((__mode__ (__SI__))); float __d; }) \ + { __l: 0x7fc00000UL }).__d) + +#else + +# include + +# if __BYTE_ORDER == __BIG_ENDIAN +# define __nan_bytes { 0x7f, 0xc0, 0, 0 } +# endif +# if __BYTE_ORDER == __LITTLE_ENDIAN +# define __nan_bytes { 0, 0, 0xc0, 0x7f } +# endif + +static union { unsigned char __c[4]; float __d; } __nan_union + __attribute_used__ = { __nan_bytes }; +# define NAN (__nan_union.__d) + +#endif /* GCC. */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/netdb.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/netdb.h new file mode 100644 index 00000000..41dc7319 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/netdb.h @@ -0,0 +1,33 @@ +/* Copyright (C) 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _NETDB_H +# error "Never include directly; use instead." +#endif + + +/* Description of data base entry for a single network. NOTE: here a + poor assumption is made. The network number is expected to fit + into an unsigned long int variable. */ +struct netent +{ + char *n_name; /* Official name of network. */ + char **n_aliases; /* Alias list. */ + int n_addrtype; /* Net address type. */ + uint32_t n_net; /* Network number. */ +}; diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/poll.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/poll.h new file mode 100644 index 00000000..d7996b46 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/poll.h @@ -0,0 +1,50 @@ +/* Copyright (C) 1997, 2001, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_POLL_H +# error "Never use directly; include instead." +#endif + +/* Event types that can be polled for. These bits may be set in `events' + to indicate the interesting event types; they will appear in `revents' + to indicate the status of the file descriptor. */ +#define POLLIN 0x001 /* There is data to read. */ +#define POLLPRI 0x002 /* There is urgent data to read. */ +#define POLLOUT 0x004 /* Writing now will not block. */ + +#ifdef __USE_XOPEN +/* These values are defined in XPG4.2. */ +# define POLLRDNORM 0x040 /* Normal data may be read. */ +# define POLLRDBAND 0x080 /* Priority data may be read. */ +# define POLLWRNORM 0x100 /* Writing now will not block. */ +# define POLLWRBAND 0x200 /* Priority data may be written. */ +#endif + +#ifdef __USE_GNU +/* These are extensions for Linux. */ +# define POLLMSG 0x400 +# define POLLREMOVE 0x1000 +# define POLLRDHUP 0x2000 +#endif + +/* Event types always implicitly polled for. These bits need not be set in + `events', but they will appear in `revents' to indicate the status of + the file descriptor. */ +#define POLLERR 0x008 /* Error condition. */ +#define POLLHUP 0x010 /* Hung up. */ +#define POLLNVAL 0x020 /* Invalid polling request. */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/posix1_lim.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/posix1_lim.h new file mode 100644 index 00000000..3c86dcec --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/posix1_lim.h @@ -0,0 +1,169 @@ +/* Copyright (C) 1991-1993,96,98,2000-2003,2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * POSIX Standard: 2.9.2 Minimum Values Added to + * + * Never include this file directly; use instead. + */ + +#ifndef _BITS_POSIX1_LIM_H +#define _BITS_POSIX1_LIM_H 1 + + +/* These are the standard-mandated minimum values. */ + +/* Minimum number of operations in one list I/O call. */ +#define _POSIX_AIO_LISTIO_MAX 2 + +/* Minimal number of outstanding asynchronous I/O operations. */ +#define _POSIX_AIO_MAX 1 + +/* Maximum length of arguments to `execve', including environment. */ +#define _POSIX_ARG_MAX 4096 + +/* Maximum simultaneous processes per real user ID. */ +#ifdef __USE_XOPEN2K +# define _POSIX_CHILD_MAX 25 +#else +# define _POSIX_CHILD_MAX 6 +#endif + +/* Minimal number of timer expiration overruns. */ +#define _POSIX_DELAYTIMER_MAX 32 + +/* Maximum length of a host name (not including the terminating null) + as returned from the GETHOSTNAME function. */ +#define _POSIX_HOST_NAME_MAX 255 + +/* Maximum link count of a file. */ +#define _POSIX_LINK_MAX 8 + +/* Maximum length of login name. */ +#define _POSIX_LOGIN_NAME_MAX 9 + +/* Number of bytes in a terminal canonical input queue. */ +#define _POSIX_MAX_CANON 255 + +/* Number of bytes for which space will be + available in a terminal input queue. */ +#define _POSIX_MAX_INPUT 255 + +/* Maximum number of message queues open for a process. */ +#define _POSIX_MQ_OPEN_MAX 8 + +/* Maximum number of supported message priorities. */ +#define _POSIX_MQ_PRIO_MAX 32 + +/* Number of bytes in a filename. */ +#define _POSIX_NAME_MAX 14 + +/* Number of simultaneous supplementary group IDs per process. */ +#ifdef __USE_XOPEN2K +# define _POSIX_NGROUPS_MAX 8 +#else +# define _POSIX_NGROUPS_MAX 0 +#endif + +/* Number of files one process can have open at once. */ +#ifdef __USE_XOPEN2K +# define _POSIX_OPEN_MAX 20 +#else +# define _POSIX_OPEN_MAX 16 +#endif + +/* Number of descriptors that a process may examine with `pselect' or + `select'. */ +#define _POSIX_FD_SETSIZE _POSIX_OPEN_MAX + +/* Number of bytes in a pathname. */ +#define _POSIX_PATH_MAX 256 + +/* Number of bytes than can be written atomically to a pipe. */ +#define _POSIX_PIPE_BUF 512 + +/* The number of repeated occurrences of a BRE permitted by the + REGEXEC and REGCOMP functions when using the interval notation. */ +#define _POSIX_RE_DUP_MAX 255 + +/* Minimal number of realtime signals reserved for the application. */ +#define _POSIX_RTSIG_MAX 8 + +/* Number of semaphores a process can have. */ +#define _POSIX_SEM_NSEMS_MAX 256 + +/* Maximal value of a semaphore. */ +#define _POSIX_SEM_VALUE_MAX 32767 + +/* Number of pending realtime signals. */ +#define _POSIX_SIGQUEUE_MAX 32 + +/* Largest value of a `ssize_t'. */ +#define _POSIX_SSIZE_MAX 32767 + +/* Number of streams a process can have open at once. */ +#define _POSIX_STREAM_MAX 8 + +/* The number of bytes in a symbolic link. */ +#define _POSIX_SYMLINK_MAX 255 + +/* The number of symbolic links that can be traversed in the + resolution of a pathname in the absence of a loop. */ +#define _POSIX_SYMLOOP_MAX 8 + +/* Number of timer for a process. */ +#define _POSIX_TIMER_MAX 32 + +/* Maximum number of characters in a tty name. */ +#define _POSIX_TTY_NAME_MAX 9 + +/* Maximum length of a timezone name (element of `tzname'). */ +#define _POSIX_TZNAME_MAX 6 + +/* Maximum number of connections that can be queued on a socket. */ +#define _POSIX_QLIMIT 1 + +/* Maximum number of bytes that can be buffered on a socket for send + or receive. */ +#define _POSIX_HIWAT _POSIX_PIPE_BUF + +/* Maximum number of elements in an `iovec' array. */ +#define _POSIX_UIO_MAXIOV 16 + +/* Maximum clock resolution in nanoseconds. */ +#define _POSIX_CLOCKRES_MIN 20000000 + + +/* Get the implementation-specific values for the above. */ +#include +#include + + +#ifndef SSIZE_MAX +# define SSIZE_MAX LONG_MAX +#endif + + +/* This value is a guaranteed minimum maximum. + The current maximum can be got from `sysconf'. */ + +#ifndef NGROUPS_MAX +# define NGROUPS_MAX 8 +#endif + +#endif /* bits/posix1_lim.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/posix2_lim.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/posix2_lim.h new file mode 100644 index 00000000..24483a09 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/posix2_lim.h @@ -0,0 +1,91 @@ +/* Copyright (C) 1991, 1996, 1999, 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * Never include this file directly; include instead. + */ + +#ifndef _BITS_POSIX2_LIM_H +#define _BITS_POSIX2_LIM_H 1 + + +/* The maximum `ibase' and `obase' values allowed by the `bc' utility. */ +#define _POSIX2_BC_BASE_MAX 99 + +/* The maximum number of elements allowed in an array by the `bc' utility. */ +#define _POSIX2_BC_DIM_MAX 2048 + +/* The maximum `scale' value allowed by the `bc' utility. */ +#define _POSIX2_BC_SCALE_MAX 99 + +/* The maximum length of a string constant accepted by the `bc' utility. */ +#define _POSIX2_BC_STRING_MAX 1000 + +/* The maximum number of weights that can be assigned to an entry of + the LC_COLLATE `order' keyword in the locale definition file. */ +#define _POSIX2_COLL_WEIGHTS_MAX 2 + +/* The maximum number of expressions that can be nested + within parentheses by the `expr' utility. */ +#define _POSIX2_EXPR_NEST_MAX 32 + +/* The maximum length, in bytes, of an input line. */ +#define _POSIX2_LINE_MAX 2048 + +/* The maximum number of repeated occurrences of a regular expression + permitted when using the interval notation `\{M,N\}'. */ +#define _POSIX2_RE_DUP_MAX 255 + +/* The maximum number of bytes in a character class name. We have no + fixed limit, 2048 is a high number. */ +#define _POSIX2_CHARCLASS_NAME_MAX 14 + + +/* These values are implementation-specific, + and may vary within the implementation. + Their precise values can be obtained from sysconf. */ + +#ifndef BC_BASE_MAX +#define BC_BASE_MAX _POSIX2_BC_BASE_MAX +#endif +#ifndef BC_DIM_MAX +#define BC_DIM_MAX _POSIX2_BC_DIM_MAX +#endif +#ifndef BC_SCALE_MAX +#define BC_SCALE_MAX _POSIX2_BC_SCALE_MAX +#endif +#ifndef BC_STRING_MAX +#define BC_STRING_MAX _POSIX2_BC_STRING_MAX +#endif +#ifndef COLL_WEIGHTS_MAX +#define COLL_WEIGHTS_MAX 255 +#endif +#ifndef EXPR_NEST_MAX +#define EXPR_NEST_MAX _POSIX2_EXPR_NEST_MAX +#endif +#ifndef LINE_MAX +#define LINE_MAX _POSIX2_LINE_MAX +#endif +#ifndef CHARCLASS_NAME_MAX +#define CHARCLASS_NAME_MAX 2048 +#endif + +/* This value is defined like this in regex.h. */ +#define RE_DUP_MAX (0x7fff) + +#endif /* bits/posix2_lim.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/posix_opt.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/posix_opt.h new file mode 100644 index 00000000..aa40eae4 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/posix_opt.h @@ -0,0 +1,190 @@ +/* Define POSIX options for Linux. + Copyright (C) 1996-2001, 2002, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _POSIX_OPT_H +#define _POSIX_OPT_H 1 + +/* Job control is supported. */ +#define _POSIX_JOB_CONTROL 1 + +/* Processes have a saved set-user-ID and a saved set-group-ID. */ +#define _POSIX_SAVED_IDS 1 + +/* Priority scheduling is supported. */ +#define _POSIX_PRIORITY_SCHEDULING 200112L + +/* Synchronizing file data is supported. */ +#define _POSIX_SYNCHRONIZED_IO 200112L + +/* The fsync function is present. */ +#define _POSIX_FSYNC 200112L + +/* Mapping of files to memory is supported. */ +#define _POSIX_MAPPED_FILES 200112L + +/* Locking of all memory is supported. */ +#define _POSIX_MEMLOCK 200112L + +/* Locking of ranges of memory is supported. */ +#define _POSIX_MEMLOCK_RANGE 200112L + +/* Setting of memory protections is supported. */ +#define _POSIX_MEMORY_PROTECTION 200112L + +/* Only root can change owner of file. */ +#define _POSIX_CHOWN_RESTRICTED 1 + +/* `c_cc' member of 'struct termios' structure can be disabled by + using the value _POSIX_VDISABLE. */ +#define _POSIX_VDISABLE '\0' + +/* Filenames are not silently truncated. */ +#define _POSIX_NO_TRUNC 1 + +/* X/Open realtime support is available. */ +#define _XOPEN_REALTIME 1 + +/* XPG4.2 shared memory is supported. */ +#define _XOPEN_SHM 1 + +/* Tell we have POSIX threads. */ +#define _POSIX_THREADS 200112L + +/* We have the reentrant functions described in POSIX. */ +#define _POSIX_REENTRANT_FUNCTIONS 1 +#define _POSIX_THREAD_SAFE_FUNCTIONS 200112L + +/* We provide priority scheduling for threads. */ +#define _POSIX_THREAD_PRIORITY_SCHEDULING 200112L + +/* We support user-defined stack sizes. */ +#define _POSIX_THREAD_ATTR_STACKSIZE 200112L + +/* We support user-defined stacks. */ +#define _POSIX_THREAD_ATTR_STACKADDR 200112L + +#ifdef __UCLIBC_HAS_REALTIME__ +/* We support POSIX.1b semaphores. */ +#define _POSIX_SEMAPHORES 200112L +#endif + +/* Real-time signals are supported. */ +#define _POSIX_REALTIME_SIGNALS 200112L + +/* We support asynchronous I/O. */ +#define _POSIX_ASYNCHRONOUS_IO 200112L +#define _POSIX_ASYNC_IO 1 +/* Alternative name for Unix98. */ +#define _LFS_ASYNCHRONOUS_IO 1 +/* Support for prioritization is also available. */ +#define _POSIX_PRIORITIZED_IO 200112L + +/* The LFS support in asynchronous I/O is also available. */ +#define _LFS64_ASYNCHRONOUS_IO 1 + +#ifdef __UCLIBC_HAS_LFS__ +/* The rest of the LFS is also available. */ +#define _LFS_LARGEFILE 1 +#define _LFS64_LARGEFILE 1 +#define _LFS64_STDIO 1 +#endif + +/* POSIX shared memory objects are implemented. */ +#define _POSIX_SHARED_MEMORY_OBJECTS 200112L + +/* CPU-time clocks support needs to be checked at runtime. */ +#define _POSIX_CPUTIME 0 + +/* Clock support in threads must be also checked at runtime. */ +#define _POSIX_THREAD_CPUTIME 0 + +#ifdef __UCLIBC_HAS_REGEX__ +/* GNU libc provides regular expression handling. */ +#define _POSIX_REGEXP 1 +#endif + +/* Reader/Writer locks are available. */ +#define _POSIX_READER_WRITER_LOCKS 200112L + +/* We have a POSIX shell. */ +#define _POSIX_SHELL 1 + +/* We support the Timeouts option. */ +#define _POSIX_TIMEOUTS 200112L + +/* We support spinlocks. */ +#define _POSIX_SPIN_LOCKS 200112L + +/* The `spawn' function family is supported. */ +#if 0 /* no support in uClibc (yet) */ +#define _POSIX_SPAWN 200112L +#endif + +/* We have POSIX timers. */ +#define _POSIX_TIMERS 200112L + +/* The barrier functions are available. */ +#define _POSIX_BARRIERS 200112L + +/* POSIX message queues are available. */ +#define _POSIX_MESSAGE_PASSING 200112L + +/* Thread process-shared synchronization is supported. */ +#define _POSIX_THREAD_PROCESS_SHARED 200112L + +/* The monotonic clock might be available. */ +#define _POSIX_MONOTONIC_CLOCK 0 + +/* The clock selection interfaces are available. */ +#define _POSIX_CLOCK_SELECTION 200112L + +/* Advisory information interfaces are available. */ +#define _POSIX_ADVISORY_INFO 200112L + +#ifdef __UCLIBC_HAS_IPV6__ +/* IPv6 support is available. */ +#define _POSIX_IPV6 200112L +#endif + +#ifdef __UCLIBC_HAS_SOCKET__ +/* Raw socket support is available. */ +#define _POSIX_RAW_SOCKETS 200112L +#endif + +/* We have at least one terminal. */ +#define _POSIX2_CHAR_TERM 200112L + +/* Neither process nor thread sporadic server interfaces is available. */ +#define _POSIX_SPORADIC_SERVER -1 +#define _POSIX_THREAD_SPORADIC_SERVER -1 + +/* trace.h is not available. */ +#define _POSIX_TRACE -1 +#define _POSIX_TRACE_EVENT_FILTER -1 +#define _POSIX_TRACE_INHERIT -1 +#define _POSIX_TRACE_LOG -1 + +/* Typed memory objects are not available. */ +#define _POSIX_TYPED_MEMORY_OBJECTS -1 + +/* No support for priority inheritance or protection so far. */ +#define _POSIX_THREAD_PRIO_INHERIT -1 +#define _POSIX_THREAD_PRIO_PROTECT -1 + +#endif /* posix_opt.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/resource.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/resource.h new file mode 100644 index 00000000..526cdaf5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/resource.h @@ -0,0 +1,225 @@ +/* Bit values & structures for resource limits. Linux version. + Copyright (C) 1994, 1996, 1997, 1998, 1999, 2000, 2004, 2005 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_RESOURCE_H +# error "Never use directly; include instead." +#endif + +#include + +/* Transmute defines to enumerations. The macro re-definitions are + necessary because some programs want to test for operating system + features with #ifdef RUSAGE_SELF. In ISO C the reflexive + definition is a no-op. */ + +/* Kinds of resource limit. */ +enum __rlimit_resource +{ + /* Per-process CPU limit, in seconds. */ + RLIMIT_CPU = 0, +#define RLIMIT_CPU RLIMIT_CPU + + /* Largest file that can be created, in bytes. */ + RLIMIT_FSIZE = 1, +#define RLIMIT_FSIZE RLIMIT_FSIZE + + /* Maximum size of data segment, in bytes. */ + RLIMIT_DATA = 2, +#define RLIMIT_DATA RLIMIT_DATA + + /* Maximum size of stack segment, in bytes. */ + RLIMIT_STACK = 3, +#define RLIMIT_STACK RLIMIT_STACK + + /* Largest core file that can be created, in bytes. */ + RLIMIT_CORE = 4, +#define RLIMIT_CORE RLIMIT_CORE + + /* Largest resident set size, in bytes. + This affects swapping; processes that are exceeding their + resident set size will be more likely to have physical memory + taken from them. */ + __RLIMIT_RSS = 5, +#define RLIMIT_RSS __RLIMIT_RSS + + /* Number of open files. */ + RLIMIT_NOFILE = 7, + __RLIMIT_OFILE = RLIMIT_NOFILE, /* BSD name for same. */ +#define RLIMIT_NOFILE RLIMIT_NOFILE +#define RLIMIT_OFILE __RLIMIT_OFILE + + /* Address space limit. */ + RLIMIT_AS = 9, +#define RLIMIT_AS RLIMIT_AS + + /* Number of processes. */ + __RLIMIT_NPROC = 6, +#define RLIMIT_NPROC __RLIMIT_NPROC + + /* Locked-in-memory address space. */ + __RLIMIT_MEMLOCK = 8, +#define RLIMIT_MEMLOCK __RLIMIT_MEMLOCK + + /* Maximum number of file locks. */ + __RLIMIT_LOCKS = 10, +#define RLIMIT_LOCKS __RLIMIT_LOCKS + + /* Maximum number of pending signals. */ + __RLIMIT_SIGPENDING = 11, +#define RLIMIT_SIGPENDING __RLIMIT_SIGPENDING + + /* Maximum bytes in POSIX message queues. */ + __RLIMIT_MSGQUEUE = 12, +#define RLIMIT_MSGQUEUE __RLIMIT_MSGQUEUE + + /* Maximum nice priority allowed to raise to. + Nice levels 19 .. -20 correspond to 0 .. 39 + values of this resource limit. */ + __RLIMIT_NICE = 13, +#define RLIMIT_NICE __RLIMIT_NICE + + /* Maximum realtime priority allowed for non-priviledged + processes. */ + __RLIMIT_RTPRIO = 14, +#define RLIMIT_RTPRIO __RLIMIT_RTPRIO + + __RLIMIT_NLIMITS = 15, + __RLIM_NLIMITS = __RLIMIT_NLIMITS +#define RLIMIT_NLIMITS __RLIMIT_NLIMITS +#define RLIM_NLIMITS __RLIM_NLIMITS +}; + +/* Value to indicate that there is no limit. */ +#ifndef __USE_FILE_OFFSET64 +# define RLIM_INFINITY ((unsigned long int)(~0UL)) +#else +# define RLIM_INFINITY 0xffffffffffffffffuLL +#endif + +#ifdef __USE_LARGEFILE64 +# define RLIM64_INFINITY 0xffffffffffffffffuLL +#endif + +/* We can represent all limits. */ +#define RLIM_SAVED_MAX RLIM_INFINITY +#define RLIM_SAVED_CUR RLIM_INFINITY + + +/* Type for resource quantity measurement. */ +#ifndef __USE_FILE_OFFSET64 +typedef __rlim_t rlim_t; +#else +typedef __rlim64_t rlim_t; +#endif +#ifdef __USE_LARGEFILE64 +typedef __rlim64_t rlim64_t; +#endif + +struct rlimit + { + /* The current (soft) limit. */ + rlim_t rlim_cur; + /* The hard limit. */ + rlim_t rlim_max; + }; + +#ifdef __USE_LARGEFILE64 +struct rlimit64 + { + /* The current (soft) limit. */ + rlim64_t rlim_cur; + /* The hard limit. */ + rlim64_t rlim_max; + }; +#endif + +/* Whose usage statistics do you want? */ +enum __rusage_who +{ + /* The calling process. */ + RUSAGE_SELF = 0, +#define RUSAGE_SELF RUSAGE_SELF + + /* All of its terminated child processes. */ + RUSAGE_CHILDREN = -1 +#define RUSAGE_CHILDREN RUSAGE_CHILDREN +}; + +#define __need_timeval +#include /* For `struct timeval'. */ + +/* Structure which says how much of each resource has been used. */ +struct rusage + { + /* Total amount of user time used. */ + struct timeval ru_utime; + /* Total amount of system time used. */ + struct timeval ru_stime; + /* Maximum resident set size (in kilobytes). */ + long int ru_maxrss; + /* Amount of sharing of text segment memory + with other processes (kilobyte-seconds). */ + long int ru_ixrss; + /* Amount of data segment memory used (kilobyte-seconds). */ + long int ru_idrss; + /* Amount of stack memory used (kilobyte-seconds). */ + long int ru_isrss; + /* Number of soft page faults (i.e. those serviced by reclaiming + a page from the list of pages awaiting reallocation. */ + long int ru_minflt; + /* Number of hard page faults (i.e. those that required I/O). */ + long int ru_majflt; + /* Number of times a process was swapped out of physical memory. */ + long int ru_nswap; + /* Number of input operations via the file system. Note: This + and `ru_oublock' do not include operations with the cache. */ + long int ru_inblock; + /* Number of output operations via the file system. */ + long int ru_oublock; + /* Number of IPC messages sent. */ + long int ru_msgsnd; + /* Number of IPC messages received. */ + long int ru_msgrcv; + /* Number of signals delivered. */ + long int ru_nsignals; + /* Number of voluntary context switches, i.e. because the process + gave up the process before it had to (usually to wait for some + resource to be available). */ + long int ru_nvcsw; + /* Number of involuntary context switches, i.e. a higher priority process + became runnable or the current process used up its time slice. */ + long int ru_nivcsw; + }; + +/* Priority limits. */ +#define PRIO_MIN -20 /* Minimum priority a process can have. */ +#define PRIO_MAX 20 /* Maximum priority a process can have. */ + +/* The type of the WHICH argument to `getpriority' and `setpriority', + indicating what flavor of entity the WHO argument specifies. */ +enum __priority_which +{ + PRIO_PROCESS = 0, /* WHO is a process ID. */ +#define PRIO_PROCESS PRIO_PROCESS + PRIO_PGRP = 1, /* WHO is a process group ID. */ +#define PRIO_PGRP PRIO_PGRP + PRIO_USER = 2 /* WHO is a user ID. */ +#define PRIO_USER PRIO_USER +}; diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/sched.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/sched.h new file mode 100644 index 00000000..b48a0c87 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/sched.h @@ -0,0 +1,132 @@ +/* Definitions of constants and data structure for POSIX 1003.1b-1993 + scheduling interface. + Copyright (C) 1996-1999,2001-2003,2005,2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef __need_schedparam + +#ifndef _SCHED_H +# error "Never include directly; use instead." +#endif + + +/* Scheduling algorithms. */ +#define SCHED_OTHER 0 +#define SCHED_FIFO 1 +#define SCHED_RR 2 +#ifdef __USE_GNU +# define SCHED_BATCH 3 +#endif + +#ifdef __USE_MISC +/* Cloning flags. */ +# define CSIGNAL 0x000000ff /* Signal mask to be sent at exit. */ +# define CLONE_VM 0x00000100 /* Set if VM shared between processes. */ +# define CLONE_FS 0x00000200 /* Set if fs info shared between processes. */ +# define CLONE_FILES 0x00000400 /* Set if open files shared between processes. */ +# define CLONE_SIGHAND 0x00000800 /* Set if signal handlers shared. */ +# define CLONE_PTRACE 0x00002000 /* Set if tracing continues on the child. */ +# define CLONE_VFORK 0x00004000 /* Set if the parent wants the child to + wake it up on mm_release. */ +# define CLONE_PARENT 0x00008000 /* Set if we want to have the same + parent as the cloner. */ +# define CLONE_THREAD 0x00010000 /* Set to add to same thread group. */ +# define CLONE_NEWNS 0x00020000 /* Set to create new namespace. */ +# define CLONE_SYSVSEM 0x00040000 /* Set to shared SVID SEM_UNDO semantics. */ +# define CLONE_SETTLS 0x00080000 /* Set TLS info. */ +# define CLONE_PARENT_SETTID 0x00100000 /* Store TID in userlevel buffer + before MM copy. */ +# define CLONE_CHILD_CLEARTID 0x00200000 /* Register exit futex and memory + location to clear. */ +# define CLONE_DETACHED 0x00400000 /* Create clone detached. */ +# define CLONE_UNTRACED 0x00800000 /* Set if the tracing process can't + force CLONE_PTRACE on this clone. */ +# define CLONE_CHILD_SETTID 0x01000000 /* Store TID in userlevel buffer in + the child. */ +# define CLONE_STOPPED 0x02000000 /* Start in stopped state. */ +#endif + +/* The official definition. */ +struct sched_param + { + int __sched_priority; + }; + +__BEGIN_DECLS + +#ifdef __USE_MISC +/* Clone current process. */ +extern int clone (int (*__fn) (void *__arg), void *__child_stack, + int __flags, void *__arg, ...) __THROW; + +#if 0 +/* Unshare the specified resources. */ +extern int unshare (int __flags) __THROW; +#endif +#endif + +__END_DECLS + +#endif /* need schedparam */ + +#if !defined __defined_schedparam \ + && (defined __need_schedparam || defined _SCHED_H) +# define __defined_schedparam 1 +/* Data structure to describe a process' schedulability. */ +struct __sched_param + { + int __sched_priority; + }; +# undef __need_schedparam +#endif + + +#if defined _SCHED_H && !defined __cpu_set_t_defined +# define __cpu_set_t_defined +/* Size definition for CPU sets. */ +# define __CPU_SETSIZE 1024 +# define __NCPUBITS (8 * sizeof (__cpu_mask)) + +/* Type for array elements in 'cpu_set'. */ +typedef unsigned long int __cpu_mask; + +/* Basic access functions. */ +# define __CPUELT(cpu) ((cpu) / __NCPUBITS) +# define __CPUMASK(cpu) ((__cpu_mask) 1 << ((cpu) % __NCPUBITS)) + +/* Data structure to describe CPU mask. */ +typedef struct +{ + __cpu_mask __bits[__CPU_SETSIZE / __NCPUBITS]; +} cpu_set_t; + +/* Access functions for CPU masks. */ +# define __CPU_ZERO(cpusetp) \ + do { \ + unsigned int __i; \ + cpu_set_t *__arr = (cpusetp); \ + for (__i = 0; __i < sizeof (cpu_set_t) / sizeof (__cpu_mask); ++__i) \ + __arr->__bits[__i] = 0; \ + } while (0) +# define __CPU_SET(cpu, cpusetp) \ + ((cpusetp)->__bits[__CPUELT (cpu)] |= __CPUMASK (cpu)) +# define __CPU_CLR(cpu, cpusetp) \ + ((cpusetp)->__bits[__CPUELT (cpu)] &= ~__CPUMASK (cpu)) +# define __CPU_ISSET(cpu, cpusetp) \ + (((cpusetp)->__bits[__CPUELT (cpu)] & __CPUMASK (cpu)) != 0) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/select.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/select.h new file mode 100644 index 00000000..47e7dedc --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/select.h @@ -0,0 +1,35 @@ +/* Copyright (C) 1997, 1998, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_SELECT_H +# error "Never use directly; include instead." +#endif + + +/* We don't use `memset' because this would require a prototype and + the array isn't too big. */ +#define __FD_ZERO(s) \ + do { \ + unsigned int __i; \ + fd_set *__arr = (s); \ + for (__i = 0; __i < sizeof (fd_set) / sizeof (__fd_mask); ++__i) \ + __FDS_BITS (__arr)[__i] = 0; \ + } while (0) +#define __FD_SET(d, s) (__FDS_BITS (s)[__FDELT(d)] |= __FDMASK(d)) +#define __FD_CLR(d, s) (__FDS_BITS (s)[__FDELT(d)] &= ~__FDMASK(d)) +#define __FD_ISSET(d, s) ((__FDS_BITS (s)[__FDELT(d)] & __FDMASK(d)) != 0) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/sem.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/sem.h new file mode 100644 index 00000000..6193501e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/sem.h @@ -0,0 +1,87 @@ +/* Copyright (C) 1995, 1996, 1997, 1998, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_SEM_H +# error "Never include directly; use instead." +#endif + +#include + +/* Flags for `semop'. */ +#define SEM_UNDO 0x1000 /* undo the operation on exit */ + +/* Commands for `semctl'. */ +#define GETPID 11 /* get sempid */ +#define GETVAL 12 /* get semval */ +#define GETALL 13 /* get all semval's */ +#define GETNCNT 14 /* get semncnt */ +#define GETZCNT 15 /* get semzcnt */ +#define SETVAL 16 /* set semval */ +#define SETALL 17 /* set all semval's */ + + +/* Data structure describing a set of semaphores. */ +struct semid_ds +{ + struct ipc_perm sem_perm; /* operation permission struct */ + __time_t sem_otime; /* last semop() time */ + unsigned long int __unused1; + __time_t sem_ctime; /* last time changed by semctl() */ + unsigned long int __unused2; + unsigned long int sem_nsems; /* number of semaphores in set */ + unsigned long int __unused3; + unsigned long int __unused4; +}; + +/* The user should define a union like the following to use it for arguments + for `semctl'. + + union semun + { + int val; <= value for SETVAL + struct semid_ds *buf; <= buffer for IPC_STAT & IPC_SET + unsigned short int *array; <= array for GETALL & SETALL + struct seminfo *__buf; <= buffer for IPC_INFO + }; + + Previous versions of this file used to define this union but this is + incorrect. One can test the macro _SEM_SEMUN_UNDEFINED to see whether + one must define the union or not. */ +#define _SEM_SEMUN_UNDEFINED 1 + +#ifdef __USE_MISC + +/* ipcs ctl cmds */ +# define SEM_STAT 18 +# define SEM_INFO 19 + +struct seminfo +{ + int semmap; + int semmni; + int semmns; + int semmnu; + int semmsl; + int semopm; + int semume; + int semusz; + int semvmx; + int semaem; +}; + +#endif /* __USE_MISC */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/setjmp.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/setjmp.h new file mode 100644 index 00000000..ad9f04d7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/setjmp.h @@ -0,0 +1,2 @@ +/* bits/setjmp.h is architecture specific. */ +#error "This file must be supplied by every Linux architecture." diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/shm.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/shm.h new file mode 100644 index 00000000..87ccd0fc --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/shm.h @@ -0,0 +1,103 @@ +/* Copyright (C) 1995,1996,1997,2000,2002,2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_SHM_H +# error "Never include directly; use instead." +#endif + +#include + +/* Permission flag for shmget. */ +#define SHM_R 0400 /* or S_IRUGO from */ +#define SHM_W 0200 /* or S_IWUGO from */ + +/* Flags for `shmat'. */ +#define SHM_RDONLY 010000 /* attach read-only else read-write */ +#define SHM_RND 020000 /* round attach address to SHMLBA */ +#define SHM_REMAP 040000 /* take-over region on attach */ + +/* Commands for `shmctl'. */ +#define SHM_LOCK 11 /* lock segment (root only) */ +#define SHM_UNLOCK 12 /* unlock segment (root only) */ + +__BEGIN_DECLS + +/* Segment low boundary address multiple. */ +#define SHMLBA (__getpagesize ()) +extern int __getpagesize (void) __THROW __attribute__ ((__const__)); + + +/* Type to count number of attaches. */ +typedef unsigned long int shmatt_t; + +/* Data structure describing a set of semaphores. */ +struct shmid_ds + { + struct ipc_perm shm_perm; /* operation permission struct */ + size_t shm_segsz; /* size of segment in bytes */ + __time_t shm_atime; /* time of last shmat() */ + unsigned long int __unused1; + __time_t shm_dtime; /* time of last shmdt() */ + unsigned long int __unused2; + __time_t shm_ctime; /* time of last change by shmctl() */ + unsigned long int __unused3; + __pid_t shm_cpid; /* pid of creator */ + __pid_t shm_lpid; /* pid of last shmop */ + shmatt_t shm_nattch; /* number of current attaches */ + unsigned long int __unused4; + unsigned long int __unused5; + }; + +#ifdef __USE_MISC + +/* ipcs ctl commands */ +# define SHM_STAT 13 +# define SHM_INFO 14 + +/* shm_mode upper byte flags */ +# define SHM_DEST 01000 /* segment will be destroyed on last detach */ +# define SHM_LOCKED 02000 /* segment will not be swapped */ +# define SHM_HUGETLB 04000 /* segment is mapped via hugetlb */ +# define SHM_NORESERVE 010000 /* don't check for reservations */ + +struct shminfo + { + unsigned long int shmmax; + unsigned long int shmmin; + unsigned long int shmmni; + unsigned long int shmseg; + unsigned long int shmall; + unsigned long int __unused1; + unsigned long int __unused2; + unsigned long int __unused3; + unsigned long int __unused4; + }; + +struct shm_info + { + int used_ids; + unsigned long int shm_tot; /* total allocated shm */ + unsigned long int shm_rss; /* total resident shm */ + unsigned long int shm_swp; /* total swapped shm */ + unsigned long int swap_attempts; + unsigned long int swap_successes; + }; + +#endif /* __USE_MISC */ + +__END_DECLS diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/sigaction.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/sigaction.h new file mode 100644 index 00000000..7489aa87 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/sigaction.h @@ -0,0 +1,69 @@ +/* The proper definitions for Linux's sigaction. + Copyright (C) 1993-1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SIGNAL_H +# error "Never include directly; use instead." +#endif + +/* Structure describing the action to be taken when a signal arrives. + * In uclibc, it is identical to "new" struct kernel_sigaction + * (one from the Linux 2.1.68 kernel). + * This minimizes amount of translation in sigaction(). + */ +struct sigaction { +#ifdef __USE_POSIX199309 + union { + __sighandler_t sa_handler; + void (*sa_sigaction)(int, siginfo_t *, void *); + } __sigaction_handler; +# define sa_handler __sigaction_handler.sa_handler +# define sa_sigaction __sigaction_handler.sa_sigaction +#else + __sighandler_t sa_handler; +#endif + unsigned long sa_flags; + void (*sa_restorer)(void); + sigset_t sa_mask; +}; + +/* Bits in `sa_flags'. */ +#define SA_NOCLDSTOP 1 /* Don't send SIGCHLD when children stop. */ +#define SA_NOCLDWAIT 2 /* Don't create zombie on child death. */ +#define SA_SIGINFO 4 /* Invoke signal-catching function with + three arguments instead of one. */ +#if defined __USE_UNIX98 || defined __USE_MISC +# define SA_ONSTACK 0x08000000 /* Use signal stack by using `sa_restorer'. */ +# define SA_RESTART 0x10000000 /* Restart syscall on signal return. */ +# define SA_NODEFER 0x40000000 /* Don't automatically block the signal when + its handler is being executed. */ +# define SA_RESETHAND 0x80000000 /* Reset to SIG_DFL on entry to handler. */ +#endif +#ifdef __USE_MISC +# define SA_INTERRUPT 0x20000000 /* Historical no-op. */ + +/* Some aliases for the SA_ constants. */ +# define SA_NOMASK SA_NODEFER +# define SA_ONESHOT SA_RESETHAND +# define SA_STACK SA_ONSTACK +#endif + +/* Values for the HOW argument to `sigprocmask'. */ +#define SIG_BLOCK 0 /* Block signals. */ +#define SIG_UNBLOCK 1 /* Unblock signals. */ +#define SIG_SETMASK 2 /* Set the set of blocked signals. */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/sigcontext.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/sigcontext.h new file mode 100644 index 00000000..35bf5bc8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/sigcontext.h @@ -0,0 +1,32 @@ +/* Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#if !defined _SIGNAL_H && !defined _SYS_UCONTEXT_H +# error "Never use directly; include instead." +#endif + +#ifndef sigcontext_struct +/* Kernel headers before 2.1.1 define a struct sigcontext_struct, but + we need sigcontext. */ +# define sigcontext_struct sigcontext + +# ifndef __user +# define __user +# endif +# include +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/sigcontextinfo.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/sigcontextinfo.h new file mode 100644 index 00000000..40305b48 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/sigcontextinfo.h @@ -0,0 +1,27 @@ +/* Copyright (C) 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* In general we cannot provide any information. */ +#define SIGCONTEXT struct sigcontext * +#define SIGCONTEXT_EXTRA_ARGS +#define GET_PC(ctx) ((void *) 0) +#define GET_FRAME(ctx) ((void *) 0) +#define GET_STACK(ctx) ((void *) 0) +#define CALL_SIGHANDLER(handler, signo, ctx) \ + (handler)((signo), SIGCONTEXT_EXTRA_ARGS (ctx)) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/siginfo.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/siginfo.h new file mode 100644 index 00000000..4ce319dc --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/siginfo.h @@ -0,0 +1,313 @@ +/* siginfo_t, sigevent and constants. Linux version. + Copyright (C) 1997-2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#if !defined _SIGNAL_H && !defined __need_siginfo_t \ + && !defined __need_sigevent_t +# error "Never include this file directly. Use instead" +#endif + +#include + +#if (!defined __have_sigval_t \ + && (defined _SIGNAL_H || defined __need_siginfo_t \ + || defined __need_sigevent_t)) +# define __have_sigval_t 1 + +/* Type for data associated with a signal. */ +typedef union sigval + { + int sival_int; + void *sival_ptr; + } sigval_t; +#endif + +#if (!defined __have_siginfo_t \ + && (defined _SIGNAL_H || defined __need_siginfo_t)) +# define __have_siginfo_t 1 + +# define __SI_MAX_SIZE 128 +# if __WORDSIZE == 64 +# define __SI_PAD_SIZE ((__SI_MAX_SIZE / sizeof (int)) - 4) +# else +# define __SI_PAD_SIZE ((__SI_MAX_SIZE / sizeof (int)) - 3) +# endif + +typedef struct siginfo + { + int si_signo; /* Signal number. */ + int si_errno; /* If non-zero, an errno value associated with + this signal, as defined in . */ + int si_code; /* Signal code. */ + + union + { + int _pad[__SI_PAD_SIZE]; + + /* kill(). */ + struct + { + __pid_t si_pid; /* Sending process ID. */ + __uid_t si_uid; /* Real user ID of sending process. */ + } _kill; + + /* POSIX.1b timers. */ + struct + { + int si_tid; /* Timer ID. */ + int si_overrun; /* Overrun count. */ + sigval_t si_sigval; /* Signal value. */ + } _timer; + + /* POSIX.1b signals. */ + struct + { + __pid_t si_pid; /* Sending process ID. */ + __uid_t si_uid; /* Real user ID of sending process. */ + sigval_t si_sigval; /* Signal value. */ + } _rt; + + /* SIGCHLD. */ + struct + { + __pid_t si_pid; /* Which child. */ + __uid_t si_uid; /* Real user ID of sending process. */ + int si_status; /* Exit value or signal. */ + __clock_t si_utime; + __clock_t si_stime; + } _sigchld; + + /* SIGILL, SIGFPE, SIGSEGV, SIGBUS. */ + struct + { + void *si_addr; /* Faulting insn/memory ref. */ + } _sigfault; + + /* SIGPOLL. */ + struct + { + long int si_band; /* Band event for SIGPOLL. */ + int si_fd; + } _sigpoll; + } _sifields; + } siginfo_t; + + +/* X/Open requires some more fields with fixed names. */ +# define si_pid _sifields._kill.si_pid +# define si_uid _sifields._kill.si_uid +# define si_timerid _sifields._timer.si_tid +# define si_overrun _sifields._timer.si_overrun +# define si_status _sifields._sigchld.si_status +# define si_utime _sifields._sigchld.si_utime +# define si_stime _sifields._sigchld.si_stime +# define si_value _sifields._rt.si_sigval +# define si_int _sifields._rt.si_sigval.sival_int +# define si_ptr _sifields._rt.si_sigval.sival_ptr +# define si_addr _sifields._sigfault.si_addr +# define si_band _sifields._sigpoll.si_band +# define si_fd _sifields._sigpoll.si_fd + + +/* Values for `si_code'. Positive values are reserved for kernel-generated + signals. */ +enum +{ + SI_ASYNCNL = -60, /* Sent by asynch name lookup completion. */ +# define SI_ASYNCNL SI_ASYNCNL + SI_TKILL = -6, /* Sent by tkill. */ +# define SI_TKILL SI_TKILL + SI_SIGIO, /* Sent by queued SIGIO. */ +# define SI_SIGIO SI_SIGIO + SI_ASYNCIO, /* Sent by AIO completion. */ +# define SI_ASYNCIO SI_ASYNCIO + SI_MESGQ, /* Sent by real time mesq state change. */ +# define SI_MESGQ SI_MESGQ + SI_TIMER, /* Sent by timer expiration. */ +# define SI_TIMER SI_TIMER + SI_QUEUE, /* Sent by sigqueue. */ +# define SI_QUEUE SI_QUEUE + SI_USER, /* Sent by kill, sigsend, raise. */ +# define SI_USER SI_USER + SI_KERNEL = 0x80 /* Send by kernel. */ +#define SI_KERNEL SI_KERNEL +}; + + +/* `si_code' values for SIGILL signal. */ +enum +{ + ILL_ILLOPC = 1, /* Illegal opcode. */ +# define ILL_ILLOPC ILL_ILLOPC + ILL_ILLOPN, /* Illegal operand. */ +# define ILL_ILLOPN ILL_ILLOPN + ILL_ILLADR, /* Illegal addressing mode. */ +# define ILL_ILLADR ILL_ILLADR + ILL_ILLTRP, /* Illegal trap. */ +# define ILL_ILLTRP ILL_ILLTRP + ILL_PRVOPC, /* Privileged opcode. */ +# define ILL_PRVOPC ILL_PRVOPC + ILL_PRVREG, /* Privileged register. */ +# define ILL_PRVREG ILL_PRVREG + ILL_COPROC, /* Coprocessor error. */ +# define ILL_COPROC ILL_COPROC + ILL_BADSTK /* Internal stack error. */ +# define ILL_BADSTK ILL_BADSTK +}; + +/* `si_code' values for SIGFPE signal. */ +enum +{ + FPE_INTDIV = 1, /* Integer divide by zero. */ +# define FPE_INTDIV FPE_INTDIV + FPE_INTOVF, /* Integer overflow. */ +# define FPE_INTOVF FPE_INTOVF + FPE_FLTDIV, /* Floating point divide by zero. */ +# define FPE_FLTDIV FPE_FLTDIV + FPE_FLTOVF, /* Floating point overflow. */ +# define FPE_FLTOVF FPE_FLTOVF + FPE_FLTUND, /* Floating point underflow. */ +# define FPE_FLTUND FPE_FLTUND + FPE_FLTRES, /* Floating point inexact result. */ +# define FPE_FLTRES FPE_FLTRES + FPE_FLTINV, /* Floating point invalid operation. */ +# define FPE_FLTINV FPE_FLTINV + FPE_FLTSUB /* Subscript out of range. */ +# define FPE_FLTSUB FPE_FLTSUB +}; + +/* `si_code' values for SIGSEGV signal. */ +enum +{ + SEGV_MAPERR = 1, /* Address not mapped to object. */ +# define SEGV_MAPERR SEGV_MAPERR + SEGV_ACCERR /* Invalid permissions for mapped object. */ +# define SEGV_ACCERR SEGV_ACCERR +}; + +/* `si_code' values for SIGBUS signal. */ +enum +{ + BUS_ADRALN = 1, /* Invalid address alignment. */ +# define BUS_ADRALN BUS_ADRALN + BUS_ADRERR, /* Non-existant physical address. */ +# define BUS_ADRERR BUS_ADRERR + BUS_OBJERR /* Object specific hardware error. */ +# define BUS_OBJERR BUS_OBJERR +}; + +/* `si_code' values for SIGTRAP signal. */ +enum +{ + TRAP_BRKPT = 1, /* Process breakpoint. */ +# define TRAP_BRKPT TRAP_BRKPT + TRAP_TRACE /* Process trace trap. */ +# define TRAP_TRACE TRAP_TRACE +}; + +/* `si_code' values for SIGCHLD signal. */ +enum +{ + CLD_EXITED = 1, /* Child has exited. */ +# define CLD_EXITED CLD_EXITED + CLD_KILLED, /* Child was killed. */ +# define CLD_KILLED CLD_KILLED + CLD_DUMPED, /* Child terminated abnormally. */ +# define CLD_DUMPED CLD_DUMPED + CLD_TRAPPED, /* Traced child has trapped. */ +# define CLD_TRAPPED CLD_TRAPPED + CLD_STOPPED, /* Child has stopped. */ +# define CLD_STOPPED CLD_STOPPED + CLD_CONTINUED /* Stopped child has continued. */ +# define CLD_CONTINUED CLD_CONTINUED +}; + +/* `si_code' values for SIGPOLL signal. */ +enum +{ + POLL_IN = 1, /* Data input available. */ +# define POLL_IN POLL_IN + POLL_OUT, /* Output buffers available. */ +# define POLL_OUT POLL_OUT + POLL_MSG, /* Input message available. */ +# define POLL_MSG POLL_MSG + POLL_ERR, /* I/O error. */ +# define POLL_ERR POLL_ERR + POLL_PRI, /* High priority input available. */ +# define POLL_PRI POLL_PRI + POLL_HUP /* Device disconnected. */ +# define POLL_HUP POLL_HUP +}; + +# undef __need_siginfo_t +#endif /* !have siginfo_t && (have _SIGNAL_H || need siginfo_t). */ + + +#if (defined _SIGNAL_H || defined __need_sigevent_t) \ + && !defined __have_sigevent_t +# define __have_sigevent_t 1 + +/* Structure to transport application-defined values with signals. */ +# define __SIGEV_MAX_SIZE 64 +# if __WORDSIZE == 64 +# define __SIGEV_PAD_SIZE ((__SIGEV_MAX_SIZE / sizeof (int)) - 4) +# else +# define __SIGEV_PAD_SIZE ((__SIGEV_MAX_SIZE / sizeof (int)) - 3) +# endif + +typedef struct sigevent + { + sigval_t sigev_value; + int sigev_signo; + int sigev_notify; + + union + { + int _pad[__SIGEV_PAD_SIZE]; + + /* When SIGEV_SIGNAL and SIGEV_THREAD_ID set, LWP ID of the + thread to receive the signal. */ + __pid_t _tid; + + struct + { + void (*_function) (sigval_t); /* Function to start. */ + void *_attribute; /* Really pthread_attr_t. */ + } _sigev_thread; + } _sigev_un; + } sigevent_t; + +/* POSIX names to access some of the members. */ +# define sigev_notify_function _sigev_un._sigev_thread._function +# define sigev_notify_attributes _sigev_un._sigev_thread._attribute + +/* `sigev_notify' values. */ +enum +{ + SIGEV_SIGNAL = 0, /* Notify via signal. */ +# define SIGEV_SIGNAL SIGEV_SIGNAL + SIGEV_NONE, /* Other notification: meaningless. */ +# define SIGEV_NONE SIGEV_NONE + SIGEV_THREAD, /* Deliver via thread creation. */ +# define SIGEV_THREAD SIGEV_THREAD + + SIGEV_THREAD_ID = 4 /* Send signal to specific thread. */ +#define SIGEV_THREAD_ID SIGEV_THREAD_ID +}; + +#endif /* have _SIGNAL_H. */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/signum.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/signum.h new file mode 100644 index 00000000..81d38f5c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/signum.h @@ -0,0 +1,58 @@ +/* Signal number definitions. Linux version. + Copyright (C) 1995,1996,1997,1998,1999,2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifdef _SIGNAL_H + +#define SIGHUP 1 /* Hangup (POSIX). */ +#define SIGINT 2 /* Interrupt (ANSI). */ +#define SIGQUIT 3 /* Quit (POSIX). */ +#define SIGILL 4 /* Illegal instruction (ANSI). */ +#define SIGTRAP 5 /* Trace trap (POSIX). */ +#define SIGABRT 6 /* Abort (ANSI). */ +#define SIGIOT 6 /* IOT trap (4.2 BSD). */ +#define SIGBUS 7 /* BUS error (4.2 BSD). */ +#define SIGFPE 8 /* Floating-point exception (ANSI). */ +#define SIGKILL 9 /* Kill, unblockable (POSIX). */ +#define SIGUSR1 10 /* User-defined signal 1 (POSIX). */ +#define SIGSEGV 11 /* Segmentation violation (ANSI). */ +#define SIGUSR2 12 /* User-defined signal 2 (POSIX). */ +#define SIGPIPE 13 /* Broken pipe (POSIX). */ +#define SIGALRM 14 /* Alarm clock (POSIX). */ +#define SIGTERM 15 /* Termination (ANSI). */ +#define SIGSTKFLT 16 /* Stack fault. */ +#define SIGCLD SIGCHLD /* Same as SIGCHLD (System V). */ +#define SIGCHLD 17 /* Child status has changed (POSIX). */ +#define SIGCONT 18 /* Continue (POSIX). */ +#define SIGSTOP 19 /* Stop, unblockable (POSIX). */ +#define SIGTSTP 20 /* Keyboard stop (POSIX). */ +#define SIGTTIN 21 /* Background read from tty (POSIX). */ +#define SIGTTOU 22 /* Background write to tty (POSIX). */ +#define SIGURG 23 /* Urgent condition on socket (4.2 BSD). */ +#define SIGXCPU 24 /* CPU limit exceeded (4.2 BSD). */ +#define SIGXFSZ 25 /* File size limit exceeded (4.2 BSD). */ +#define SIGVTALRM 26 /* Virtual alarm clock (4.2 BSD). */ +#define SIGPROF 27 /* Profiling alarm clock (4.2 BSD). */ +#define SIGWINCH 28 /* Window size change (4.3 BSD, Sun). */ +#define SIGPOLL SIGIO /* Pollable event occurred (System V). */ +#define SIGIO 29 /* I/O now possible (4.2 BSD). */ +#define SIGPWR 30 /* Power failure restart (System V). */ +#define SIGSYS 31 /* Bad system call. */ +#define SIGUNUSED 31 + +#endif /* included. */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/sigset.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/sigset.h new file mode 100644 index 00000000..4ef22311 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/sigset.h @@ -0,0 +1,223 @@ +/* __sig_atomic_t, __sigset_t, and related definitions. Linux version. + Copyright (C) 1991, 1992, 1994, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SIGSET_H_types +# define _SIGSET_H_types 1 + +typedef int __sig_atomic_t; + +/* A 'sigset_t' has a bit for each signal. + * glibc has space for 1024 signals (!), but most arches supported + * by Linux have 64 signals, and only MIPS has 128. + * There seems to be some historical baggage in sparc[64] + * where they might have (or had in the past) 32 signals only, + * I hope it's irrelevant now. + * Signal 0 does not exist, so we have signals 1..64, not 0..63. + * In uclibc, kernel and userspace sigset_t is always the same. + * BTW, struct sigaction is also the same on kernel and userspace side. + */ +#if defined(__mips__) +# define _SIGSET_NWORDS (128 / (8 * sizeof (unsigned long))) +#else +# define _SIGSET_NWORDS (64 / (8 * sizeof (unsigned long))) +#endif +typedef struct { + unsigned long __val[_SIGSET_NWORDS]; +} __sigset_t; + +#endif + + +/* We only want to define these functions if was actually + included; otherwise we were included just to define the types. Since we + are namespace-clean, it wouldn't hurt to define extra macros. But + trouble can be caused by functions being defined (e.g., any global + register vars declared later will cause compilation errors). */ + +#if !defined _SIGSET_H_fns && defined _SIGNAL_H +# define _SIGSET_H_fns 1 + +/* Return a mask that includes the bit for SIG only. */ +/* Unsigned cast ensures shift/mask insns are used. */ +# define __sigmask(sig) \ + (((unsigned long) 1) << ((unsigned)((sig) - 1) % (8 * sizeof (unsigned long)))) + +/* Return the word index for SIG. */ +# define __sigword(sig) ((unsigned)((sig) - 1) / (8 * sizeof (unsigned long))) + +/* gcc 4.3.1 is not clever enough to optimize for _SIGSET_NWORDS == 1 and 2, + * which are about the only values which can be there */ + +# if defined __GNUC__ && __GNUC__ >= 2 +# define __sigemptyset(set) \ +(__extension__ ({ \ + sigset_t *__set = (set); \ + if (_SIGSET_NWORDS <= 2) { \ + __set->__val[0] = 0; \ + if (_SIGSET_NWORDS == 2) \ + __set->__val[1] = 0; \ + } else { \ + int __cnt = _SIGSET_NWORDS; \ + while (--__cnt >= 0) __set->__val[__cnt] = 0; \ + } \ + 0; \ +})) +# define __sigfillset(set) \ +(__extension__ ({ \ + sigset_t *__set = (set); \ + if (_SIGSET_NWORDS <= 2) { \ + __set->__val[0] = ~0UL; \ + if (_SIGSET_NWORDS == 2) \ + __set->__val[1] = ~0UL; \ + } else { \ + int __cnt = _SIGSET_NWORDS; \ + while (--__cnt >= 0) __set->__val[__cnt] = ~0UL; \ + } \ + 0; \ +})) + +# ifdef __USE_GNU +/* The POSIX does not specify for handling the whole signal set in one + command. This is often wanted and so we define three more functions + here. */ +# define __sigisemptyset(set) \ +(__extension__ ({ \ + long __ret; \ + const sigset_t *__set = (set); \ + if (_SIGSET_NWORDS == 1) { \ + __ret = __set->__val[0]; \ + } else if (_SIGSET_NWORDS == 2) { \ + __ret = __set->__val[0] | __set->__val[1]; \ + } else { \ + int __cnt = _SIGSET_NWORDS; \ + __ret = __set->__val[--__cnt]; \ + while (!__ret && --__cnt >= 0) \ + __ret = __set->__val[__cnt]; \ + } \ + __ret == 0; \ +})) +# define __sigandset(dest, left, right) \ +(__extension__ ({ \ + sigset_t *__dest = (dest); \ + const sigset_t *__left = (left); \ + const sigset_t *__right = (right); \ + if (_SIGSET_NWORDS <= 2) { \ + __dest->__val[0] = __left->__val[0] & __right->__val[0];\ + if (_SIGSET_NWORDS == 2) \ + __dest->__val[1] = __left->__val[1] & __right->__val[1];\ + } else { \ + int __cnt = _SIGSET_NWORDS; \ + while (--__cnt >= 0) \ + __dest->__val[__cnt] = (__left->__val[__cnt] \ + & __right->__val[__cnt]); \ + } \ + 0; \ +})) +# define __sigorset(dest, left, right) \ +(__extension__ ({ \ + sigset_t *__dest = (dest); \ + const sigset_t *__left = (left); \ + const sigset_t *__right = (right); \ + if (_SIGSET_NWORDS <= 2) { \ + __dest->__val[0] = __left->__val[0] | __right->__val[0];\ + if (_SIGSET_NWORDS == 2) \ + __dest->__val[1] = __left->__val[1] | __right->__val[1];\ + } else { \ + int __cnt = _SIGSET_NWORDS; \ + while (--__cnt >= 0) \ + __dest->__val[__cnt] = (__left->__val[__cnt] \ + | __right->__val[__cnt]); \ + } \ + 0; \ +})) +# endif +# endif + +/* These functions needn't check for a bogus signal number -- error + checking is done in the non __ versions. */ + +# if !defined __USE_EXTERN_INLINES || defined __PROVIDE_OUT_OF_LINE_SIGSETFN +extern int __sigismember (__const __sigset_t *, int); +libc_hidden_proto(__sigismember) +extern int __sigaddset (__sigset_t *, int); +libc_hidden_proto(__sigaddset) +extern int __sigdelset (__sigset_t *, int); +libc_hidden_proto(__sigdelset) +# endif + +# ifdef __USE_EXTERN_INLINES +# undef _EXTERN_INLINE +# ifdef __PROVIDE_OUT_OF_LINE_SIGSETFN +# define _EXTERN_INLINE +# else /* normal case */ + /* dropped extern below: otherwise every module with __USE_EXTERN_INLINES + * will have its own copy of out-of line function emitted. */ +# define _EXTERN_INLINE /*extern*/ __always_inline +# endif +# define __SIGSETFN(NAME, BODY, CONST) \ +_EXTERN_INLINE int \ +NAME (CONST __sigset_t *__set, int __sig) \ +{ \ + unsigned long __mask = __sigmask (__sig); \ + unsigned __word = __sigword (__sig); \ + return BODY; \ +} + +__SIGSETFN (__sigismember, (__set->__val[__word] & __mask) ? 1 : 0, __const) +__SIGSETFN (__sigaddset, ((__set->__val[__word] |= __mask), 0), ) +__SIGSETFN (__sigdelset, ((__set->__val[__word] &= ~__mask), 0), ) + +# undef __SIGSETFN +# endif + +# ifdef _LIBC +/* It's far too much PITA to __USE_EXTERN_INLINES from within libc. + * Especially since we want to inline only calls with const sig, + * but __USE_EXTERN_INLINES will inline all calls! + */ +static __always_inline unsigned long +const_sigismember(const __sigset_t *set, int sig) +{ + unsigned long mask = __sigmask(sig); + unsigned word = __sigword(sig); + return (set->__val[word] & mask); +} +# define __sigismember(set, sig) \ + (__builtin_constant_p(sig) ? (const_sigismember(set, sig) != 0) : __sigismember(set, sig)) +static __always_inline void +const_sigaddset(__sigset_t *set, int sig) +{ + unsigned long mask = __sigmask(sig); + unsigned word = __sigword(sig); + set->__val[word] |= mask; +} +# define __sigaddset(set, sig) \ + (__builtin_constant_p(sig) ? (const_sigaddset(set, sig), 0) : __sigaddset(set, sig)) +static __always_inline void +const_sigdelset(__sigset_t *set, int sig) +{ + unsigned long mask = __sigmask(sig); + unsigned word = __sigword(sig); + set->__val[word] &= ~mask; +} +# define __sigdelset(set, sig) \ + (__builtin_constant_p(sig) ? (const_sigdelset(set, sig), 0) : __sigdelset(set, sig)) +# endif + +#endif /* ! _SIGSET_H_fns. */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/sigstack.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/sigstack.h new file mode 100644 index 00000000..7f260367 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/sigstack.h @@ -0,0 +1,55 @@ +/* sigstack, sigaltstack definitions. + Copyright (C) 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SIGNAL_H +# error "Never include this file directly. Use instead" +#endif + + +/* Structure describing a signal stack (obsolete). */ +struct sigstack + { + void *ss_sp; /* Signal stack pointer. */ + int ss_onstack; /* Nonzero if executing on this stack. */ + }; + + +/* Possible values for `ss_flags.'. */ +enum +{ + SS_ONSTACK = 1, +#define SS_ONSTACK SS_ONSTACK + SS_DISABLE +#define SS_DISABLE SS_DISABLE +}; + +/* Minimum stack size for a signal handler. */ +#define MINSIGSTKSZ 2048 + +/* System default stack size. */ +#define SIGSTKSZ 8192 + + +/* Alternate, preferred interface. */ +typedef struct sigaltstack + { + void *ss_sp; + int ss_flags; + size_t ss_size; + } stack_t; diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/sigthread.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/sigthread.h new file mode 100644 index 00000000..960bde18 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/sigthread.h @@ -0,0 +1,38 @@ +/* Signal handling function for threaded programs. + Copyright (C) 1998, 1999, 2000, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _BITS_SIGTHREAD_H +#define _BITS_SIGTHREAD_H 1 + +#if !defined _SIGNAL_H && !defined _PTHREAD_H +# error "Never include this file directly. Use instead" +#endif + +/* Functions for handling signals. */ + +/* Modify the signal mask for the calling thread. The arguments have + the same meaning as for sigprocmask(2). */ +extern int pthread_sigmask (int __how, + __const __sigset_t *__restrict __newmask, + __sigset_t *__restrict __oldmask)__THROW; + +/* Send signal SIGNO to the given thread. */ +extern int pthread_kill (pthread_t __threadid, int __signo) __THROW; + +#endif /* bits/sigthread.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/sockaddr.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/sockaddr.h new file mode 100644 index 00000000..3e1d1312 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/sockaddr.h @@ -0,0 +1,40 @@ +/* Definition of `struct sockaddr_*' common members. Generic/4.2 BSD version. + Copyright (C) 1995,1996,1997,1998,2000,2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * Never include this file directly; use instead. + */ + +#ifndef _BITS_SOCKADDR_H +#define _BITS_SOCKADDR_H 1 + + +/* POSIX.1g specifies this type name for the `sa_family' member. */ +typedef unsigned short int sa_family_t; + +/* This macro is used to declare the initial common members + of the data types used for socket addresses, `struct sockaddr', + `struct sockaddr_in', `struct sockaddr_un', etc. */ + +#define __SOCKADDR_COMMON(sa_prefix) \ + sa_family_t sa_prefix##family + +#define __SOCKADDR_COMMON_SIZE (sizeof (unsigned short int)) + +#endif /* bits/sockaddr.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/socket.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/socket.h new file mode 100644 index 00000000..11f6e971 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/socket.h @@ -0,0 +1,344 @@ +/* System-specific socket constants and types. Linux version. + Copyright (C) 1991,1992,1994-2001,2004,2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef __BITS_SOCKET_H +#define __BITS_SOCKET_H + +#if !defined _SYS_SOCKET_H && !defined _NETINET_IN_H +# error "Never include directly; use instead." +#endif + +#define __need_size_t +#define __need_NULL +#include + +#include +#include + +/* Type for length arguments in socket calls. */ +#ifndef __socklen_t_defined +typedef __socklen_t socklen_t; +# define __socklen_t_defined +#endif + +/* Types of sockets. */ +enum __socket_type +{ + SOCK_STREAM = 1, /* Sequenced, reliable, connection-based + byte streams. */ +#define SOCK_STREAM SOCK_STREAM + SOCK_DGRAM = 2, /* Connectionless, unreliable datagrams + of fixed maximum length. */ +#define SOCK_DGRAM SOCK_DGRAM + SOCK_RAW = 3, /* Raw protocol interface. */ +#define SOCK_RAW SOCK_RAW + SOCK_RDM = 4, /* Reliably-delivered messages. */ +#define SOCK_RDM SOCK_RDM + SOCK_SEQPACKET = 5, /* Sequenced, reliable, connection-based, + datagrams of fixed maximum length. */ +#define SOCK_SEQPACKET SOCK_SEQPACKET + SOCK_PACKET = 10, /* Linux specific way of getting packets + at the dev level. For writing rarp and + other similar things on the user level. */ +#define SOCK_PACKET SOCK_PACKET + + /* Flags to be ORed into the type parameter of socket and socketpair and + used for the flags parameter of paccept. */ + + SOCK_CLOEXEC = 02000000, /* Atomically set close-on-exec flag for the + new descriptor(s). */ +#define SOCK_CLOEXEC SOCK_CLOEXEC + SOCK_NONBLOCK = 04000 /* Atomically mark descriptor(s) as + non-blocking. */ +#define SOCK_NONBLOCK SOCK_NONBLOCK +}; + +/* Protocol families. */ +#define PF_UNSPEC 0 /* Unspecified. */ +#define PF_LOCAL 1 /* Local to host (pipes and file-domain). */ +#define PF_UNIX PF_LOCAL /* Old BSD name for PF_LOCAL. */ +#define PF_FILE PF_LOCAL /* Another non-standard name for PF_LOCAL. */ +#define PF_INET 2 /* IP protocol family. */ +#define PF_AX25 3 /* Amateur Radio AX.25. */ +#define PF_IPX 4 /* Novell Internet Protocol. */ +#define PF_APPLETALK 5 /* Appletalk DDP. */ +#define PF_NETROM 6 /* Amateur radio NetROM. */ +#define PF_BRIDGE 7 /* Multiprotocol bridge. */ +#define PF_ATMPVC 8 /* ATM PVCs. */ +#define PF_X25 9 /* Reserved for X.25 project. */ +#define PF_INET6 10 /* IP version 6. */ +#define PF_ROSE 11 /* Amateur Radio X.25 PLP. */ +#define PF_DECnet 12 /* Reserved for DECnet project. */ +#define PF_NETBEUI 13 /* Reserved for 802.2LLC project. */ +#define PF_SECURITY 14 /* Security callback pseudo AF. */ +#define PF_KEY 15 /* PF_KEY key management API. */ +#define PF_NETLINK 16 +#define PF_ROUTE PF_NETLINK /* Alias to emulate 4.4BSD. */ +#define PF_PACKET 17 /* Packet family. */ +#define PF_ASH 18 /* Ash. */ +#define PF_ECONET 19 /* Acorn Econet. */ +#define PF_ATMSVC 20 /* ATM SVCs. */ +#define PF_SNA 22 /* Linux SNA Project */ +#define PF_IRDA 23 /* IRDA sockets. */ +#define PF_PPPOX 24 /* PPPoX sockets. */ +#define PF_WANPIPE 25 /* Wanpipe API sockets. */ +#define PF_BLUETOOTH 31 /* Bluetooth sockets. */ +#define PF_MAX 32 /* For now.. */ + +/* Address families. */ +#define AF_UNSPEC PF_UNSPEC +#define AF_LOCAL PF_LOCAL +#define AF_UNIX PF_UNIX +#define AF_FILE PF_FILE +#define AF_INET PF_INET +#define AF_AX25 PF_AX25 +#define AF_IPX PF_IPX +#define AF_APPLETALK PF_APPLETALK +#define AF_NETROM PF_NETROM +#define AF_BRIDGE PF_BRIDGE +#define AF_ATMPVC PF_ATMPVC +#define AF_X25 PF_X25 +#define AF_INET6 PF_INET6 +#define AF_ROSE PF_ROSE +#define AF_DECnet PF_DECnet +#define AF_NETBEUI PF_NETBEUI +#define AF_SECURITY PF_SECURITY +#define AF_KEY PF_KEY +#define AF_NETLINK PF_NETLINK +#define AF_ROUTE PF_ROUTE +#define AF_PACKET PF_PACKET +#define AF_ASH PF_ASH +#define AF_ECONET PF_ECONET +#define AF_ATMSVC PF_ATMSVC +#define AF_SNA PF_SNA +#define AF_IRDA PF_IRDA +#define AF_PPPOX PF_PPPOX +#define AF_WANPIPE PF_WANPIPE +#define AF_BLUETOOTH PF_BLUETOOTH +#define AF_MAX PF_MAX + +/* Socket level values. Others are defined in the appropriate headers. + + XXX These definitions also should go into the appropriate headers as + far as they are available. */ +#define SOL_RAW 255 +#define SOL_DECNET 261 +#define SOL_X25 262 +#define SOL_PACKET 263 +#define SOL_ATM 264 /* ATM layer (cell level). */ +#define SOL_AAL 265 /* ATM Adaption Layer (packet level). */ +#define SOL_IRDA 266 + +/* Maximum queue length specifiable by listen. */ +#define SOMAXCONN 128 + +/* Get the definition of the macro to define the common sockaddr members. */ +#include + +/* Structure describing a generic socket address. */ +struct sockaddr + { + __SOCKADDR_COMMON (sa_); /* Common data: address family and length. */ + char sa_data[14]; /* Address data. */ + }; + + +/* Structure large enough to hold any socket address (with the historical + exception of AF_UNIX). We reserve 128 bytes. */ +#if ULONG_MAX > 0xffffffff +# define __ss_aligntype __uint64_t +#else +# define __ss_aligntype __uint32_t +#endif +#define _SS_SIZE 128 +#define _SS_PADSIZE (_SS_SIZE - (2 * sizeof (__ss_aligntype))) + +struct sockaddr_storage + { + __SOCKADDR_COMMON (ss_); /* Address family, etc. */ + __ss_aligntype __ss_align; /* Force desired alignment. */ + char __ss_padding[_SS_PADSIZE]; + }; + + +/* Bits in the FLAGS argument to `send', `recv', et al. */ +enum + { + MSG_OOB = 0x01, /* Process out-of-band data. */ +#define MSG_OOB MSG_OOB + MSG_PEEK = 0x02, /* Peek at incoming messages. */ +#define MSG_PEEK MSG_PEEK + MSG_DONTROUTE = 0x04, /* Don't use local routing. */ +#define MSG_DONTROUTE MSG_DONTROUTE +#ifdef __USE_GNU + /* DECnet uses a different name. */ + MSG_TRYHARD = MSG_DONTROUTE, +# define MSG_TRYHARD MSG_DONTROUTE +#endif + MSG_CTRUNC = 0x08, /* Control data lost before delivery. */ +#define MSG_CTRUNC MSG_CTRUNC + MSG_PROXY = 0x10, /* Supply or ask second address. */ +#define MSG_PROXY MSG_PROXY + MSG_TRUNC = 0x20, +#define MSG_TRUNC MSG_TRUNC + MSG_DONTWAIT = 0x40, /* Nonblocking IO. */ +#define MSG_DONTWAIT MSG_DONTWAIT + MSG_EOR = 0x80, /* End of record. */ +#define MSG_EOR MSG_EOR + MSG_WAITALL = 0x100, /* Wait for a full request. */ +#define MSG_WAITALL MSG_WAITALL + MSG_FIN = 0x200, +#define MSG_FIN MSG_FIN + MSG_SYN = 0x400, +#define MSG_SYN MSG_SYN + MSG_CONFIRM = 0x800, /* Confirm path validity. */ +#define MSG_CONFIRM MSG_CONFIRM + MSG_RST = 0x1000, +#define MSG_RST MSG_RST + MSG_ERRQUEUE = 0x2000, /* Fetch message from error queue. */ +#define MSG_ERRQUEUE MSG_ERRQUEUE + MSG_NOSIGNAL = 0x4000, /* Do not generate SIGPIPE. */ +#define MSG_NOSIGNAL MSG_NOSIGNAL + MSG_MORE = 0x8000 /* Sender will send more. */ +#define MSG_MORE MSG_MORE + }; + + +/* Structure describing messages sent by + `sendmsg' and received by `recvmsg'. */ +/* Note: do not change these members to match glibc; these match the + SuSv3 spec already (e.g. msg_iovlen/msg_controllen). + http://www.opengroup.org/onlinepubs/009695399/basedefs/sys/socket.h.html */ +/* Note: linux kernel uses __kernel_size_t (which is 8bytes on 64bit + platforms, and 4bytes on 32bit platforms) for msg_iovlen/msg_controllen */ +struct msghdr + { + void *msg_name; /* Address to send to/receive from. */ + socklen_t msg_namelen; /* Length of address data. */ + + struct iovec *msg_iov; /* Vector of data to send/receive into. */ +#if __WORDSIZE == 32 + int msg_iovlen; /* Number of elements in the vector. */ +#else + size_t msg_iovlen; /* Number of elements in the vector. */ +#endif + + void *msg_control; /* Ancillary data (eg BSD filedesc passing). */ +#if __WORDSIZE == 32 + socklen_t msg_controllen; /* Ancillary data buffer length. */ +#else + size_t msg_controllen; /* Ancillary data buffer length. */ +#endif + + int msg_flags; /* Flags on received message. */ + }; + +/* Structure used for storage of ancillary data object information. */ +struct cmsghdr + { + size_t cmsg_len; /* Length of data in cmsg_data plus length + of cmsghdr structure. */ + int cmsg_level; /* Originating protocol. */ + int cmsg_type; /* Protocol specific type. */ +#if (!defined __STRICT_ANSI__ && __GNUC__ >= 2) || __STDC_VERSION__ >= 199901L + __extension__ unsigned char __cmsg_data __flexarr; /* Ancillary data. */ +#endif + }; + +/* Ancillary data object manipulation macros. */ +#if (!defined __STRICT_ANSI__ && __GNUC__ >= 2) || __STDC_VERSION__ >= 199901L +# define CMSG_DATA(cmsg) ((cmsg)->__cmsg_data) +#else +# define CMSG_DATA(cmsg) ((unsigned char *) ((struct cmsghdr *) (cmsg) + 1)) +#endif +#define CMSG_NXTHDR(mhdr, cmsg) __cmsg_nxthdr (mhdr, cmsg) +#define CMSG_FIRSTHDR(mhdr) \ + ((size_t) (mhdr)->msg_controllen >= sizeof (struct cmsghdr) \ + ? (struct cmsghdr *) (mhdr)->msg_control : (struct cmsghdr *) NULL) +#define CMSG_ALIGN(len) (((len) + sizeof (size_t) - 1) \ + & (size_t) ~(sizeof (size_t) - 1)) +#define CMSG_SPACE(len) (CMSG_ALIGN (len) \ + + CMSG_ALIGN (sizeof (struct cmsghdr))) +#define CMSG_LEN(len) (CMSG_ALIGN (sizeof (struct cmsghdr)) + (len)) + +extern struct cmsghdr *__cmsg_nxthdr (struct msghdr *__mhdr, + struct cmsghdr *__cmsg) __THROW; +libc_hidden_proto(__cmsg_nxthdr) +#ifdef __USE_EXTERN_INLINES +# ifndef _EXTERN_INLINE +# define _EXTERN_INLINE extern __inline +# endif +_EXTERN_INLINE struct cmsghdr * +__NTH (__cmsg_nxthdr (struct msghdr *__mhdr, struct cmsghdr *__cmsg)) +{ + if ((size_t) __cmsg->cmsg_len < sizeof (struct cmsghdr)) + /* The kernel header does this so there may be a reason. */ + return 0; + + __cmsg = (struct cmsghdr *) ((unsigned char *) __cmsg + + CMSG_ALIGN (__cmsg->cmsg_len)); + if ((unsigned char *) (__cmsg + 1) > ((unsigned char *) __mhdr->msg_control + + __mhdr->msg_controllen) + || ((unsigned char *) __cmsg + CMSG_ALIGN (__cmsg->cmsg_len) + > ((unsigned char *) __mhdr->msg_control + __mhdr->msg_controllen))) + /* No more entries. */ + return 0; + return __cmsg; +} +#endif /* Use `extern inline'. */ + +/* Socket level message types. This must match the definitions in + . */ +enum + { + SCM_RIGHTS = 0x01 /* Transfer file descriptors. */ +#define SCM_RIGHTS SCM_RIGHTS +#ifdef __USE_BSD + , SCM_CREDENTIALS = 0x02 /* Credentials passing. */ +# define SCM_CREDENTIALS SCM_CREDENTIALS +#endif + }; + +/* User visible structure for SCM_CREDENTIALS message */ + +struct ucred +{ + pid_t pid; /* PID of sending process. */ + uid_t uid; /* UID of sending process. */ + gid_t gid; /* GID of sending process. */ +}; + +/* Get socket manipulation related informations from kernel headers. */ +#ifndef __GLIBC__ +#define __GLIBC__ 2 +#include +#undef __GLIBC__ +#else +#include +#endif + + +/* Structure used to manipulate the SO_LINGER option. */ +struct linger + { + int l_onoff; /* Nonzero to linger on close. */ + int l_linger; /* Time to linger. */ + }; + +#endif /* bits/socket.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/stab.def b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/stab.def new file mode 100644 index 00000000..3d54774c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/stab.def @@ -0,0 +1,234 @@ +/* Table of DBX symbol codes for the GNU system. + Copyright (C) 1988, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This contains contribution from Cygnus Support. */ + +/* Global variable. Only the name is significant. + To find the address, look in the corresponding external symbol. */ +__define_stab (N_GSYM, 0x20, "GSYM") + +/* Function name for BSD Fortran. Only the name is significant. + To find the address, look in the corresponding external symbol. */ +__define_stab (N_FNAME, 0x22, "FNAME") + +/* Function name or text-segment variable for C. Value is its address. + Desc is supposedly starting line number, but GCC doesn't set it + and DBX seems not to miss it. */ +__define_stab (N_FUN, 0x24, "FUN") + +/* Data-segment variable with internal linkage. Value is its address. + "Static Sym". */ +__define_stab (N_STSYM, 0x26, "STSYM") + +/* BSS-segment variable with internal linkage. Value is its address. */ +__define_stab (N_LCSYM, 0x28, "LCSYM") + +/* Name of main routine. Only the name is significant. + This is not used in C. */ +__define_stab (N_MAIN, 0x2a, "MAIN") + +/* Global symbol in Pascal. + Supposedly the value is its line number; I'm skeptical. */ +__define_stab (N_PC, 0x30, "PC") + +/* Number of symbols: 0, files,,funcs,lines according to Ultrix V4.0. */ +__define_stab (N_NSYMS, 0x32, "NSYMS") + +/* "No DST map for sym: name, ,0,type,ignored" according to Ultrix V4.0. */ +__define_stab (N_NOMAP, 0x34, "NOMAP") + +/* New stab from Solaris. I don't know what it means, but it + don't seem to contain useful information. */ +__define_stab (N_OBJ, 0x38, "OBJ") + +/* New stab from Solaris. I don't know what it means, but it + don't seem to contain useful information. Possibly related to the + optimization flags used in this module. */ +__define_stab (N_OPT, 0x3c, "OPT") + +/* Register variable. Value is number of register. */ +__define_stab (N_RSYM, 0x40, "RSYM") + +/* Modula-2 compilation unit. Can someone say what info it contains? */ +__define_stab (N_M2C, 0x42, "M2C") + +/* Line number in text segment. Desc is the line number; + value is corresponding address. */ +__define_stab (N_SLINE, 0x44, "SLINE") + +/* Similar, for data segment. */ +__define_stab (N_DSLINE, 0x46, "DSLINE") + +/* Similar, for bss segment. */ +__define_stab (N_BSLINE, 0x48, "BSLINE") + +/* Sun's source-code browser stabs. ?? Don't know what the fields are. + Supposedly the field is "path to associated .cb file". THIS VALUE + OVERLAPS WITH N_BSLINE! */ +__define_stab (N_BROWS, 0x48, "BROWS") + +/* GNU Modula-2 definition module dependency. Value is the modification time + of the definition file. Other is non-zero if it is imported with the + GNU M2 keyword %INITIALIZE. Perhaps N_M2C can be used if there + are enough empty fields? */ +__define_stab(N_DEFD, 0x4a, "DEFD") + +/* THE FOLLOWING TWO STAB VALUES CONFLICT. Happily, one is for Modula-2 + and one is for C++. Still,... */ +/* GNU C++ exception variable. Name is variable name. */ +__define_stab (N_EHDECL, 0x50, "EHDECL") +/* Modula2 info "for imc": name,,0,0,0 according to Ultrix V4.0. */ +__define_stab (N_MOD2, 0x50, "MOD2") + +/* GNU C++ `catch' clause. Value is its address. Desc is nonzero if + this entry is immediately followed by a CAUGHT stab saying what exception + was caught. Multiple CAUGHT stabs means that multiple exceptions + can be caught here. If Desc is 0, it means all exceptions are caught + here. */ +__define_stab (N_CATCH, 0x54, "CATCH") + +/* Structure or union element. Value is offset in the structure. */ +__define_stab (N_SSYM, 0x60, "SSYM") + +/* Name of main source file. + Value is starting text address of the compilation. */ +__define_stab (N_SO, 0x64, "SO") + +/* Automatic variable in the stack. Value is offset from frame pointer. + Also used for type descriptions. */ +__define_stab (N_LSYM, 0x80, "LSYM") + +/* Beginning of an include file. Only Sun uses this. + In an object file, only the name is significant. + The Sun linker puts data into some of the other fields. */ +__define_stab (N_BINCL, 0x82, "BINCL") + +/* Name of sub-source file (#include file). + Value is starting text address of the compilation. */ +__define_stab (N_SOL, 0x84, "SOL") + +/* Parameter variable. Value is offset from argument pointer. + (On most machines the argument pointer is the same as the frame pointer. */ +__define_stab (N_PSYM, 0xa0, "PSYM") + +/* End of an include file. No name. + This and N_BINCL act as brackets around the file's output. + In an object file, there is no significant data in this entry. + The Sun linker puts data into some of the fields. */ +__define_stab (N_EINCL, 0xa2, "EINCL") + +/* Alternate entry point. Value is its address. */ +__define_stab (N_ENTRY, 0xa4, "ENTRY") + +/* Beginning of lexical block. + The desc is the nesting level in lexical blocks. + The value is the address of the start of the text for the block. + The variables declared inside the block *precede* the N_LBRAC symbol. */ +__define_stab (N_LBRAC, 0xc0, "LBRAC") + +/* Place holder for deleted include file. Replaces a N_BINCL and everything + up to the corresponding N_EINCL. The Sun linker generates these when + it finds multiple identical copies of the symbols from an include file. + This appears only in output from the Sun linker. */ +__define_stab (N_EXCL, 0xc2, "EXCL") + +/* Modula-2 scope information. Can someone say what info it contains? */ +__define_stab (N_SCOPE, 0xc4, "SCOPE") + +/* End of a lexical block. Desc matches the N_LBRAC's desc. + The value is the address of the end of the text for the block. */ +__define_stab (N_RBRAC, 0xe0, "RBRAC") + +/* Begin named common block. Only the name is significant. */ +__define_stab (N_BCOMM, 0xe2, "BCOMM") + +/* End named common block. Only the name is significant + (and it should match the N_BCOMM). */ +__define_stab (N_ECOMM, 0xe4, "ECOMM") + +/* End common (local name): value is address. + I'm not sure how this is used. */ +__define_stab (N_ECOML, 0xe8, "ECOML") + +/* These STAB's are used on Gould systems for Non-Base register symbols + or something like that. FIXME. I have assigned the values at random + since I don't have a Gould here. Fixups from Gould folk welcome... */ +__define_stab (N_NBTEXT, 0xF0, "NBTEXT") +__define_stab (N_NBDATA, 0xF2, "NBDATA") +__define_stab (N_NBBSS, 0xF4, "NBBSS") +__define_stab (N_NBSTS, 0xF6, "NBSTS") +__define_stab (N_NBLCS, 0xF8, "NBLCS") + +/* Second symbol entry containing a length-value for the preceding entry. + The value is the length. */ +__define_stab (N_LENG, 0xfe, "LENG") + +/* The above information, in matrix format. + + STAB MATRIX + _________________________________________________ + | 00 - 1F are not dbx stab symbols | + | In most cases, the low bit is the EXTernal bit| + + | 00 UNDEF | 02 ABS | 04 TEXT | 06 DATA | + | 01 |EXT | 03 |EXT | 05 |EXT | 07 |EXT | + + | 08 BSS | 0A INDR | 0C FN_SEQ | 0E | + | 09 |EXT | 0B | 0D | 0F | + + | 10 | 12 COMM | 14 SETA | 16 SETT | + | 11 | 13 | 15 | 17 | + + | 18 SETD | 1A SETB | 1C SETV | 1E WARNING| + | 19 | 1B | 1D | 1F FN | + + |_______________________________________________| + | Debug entries with bit 01 set are unused. | + | 20 GSYM | 22 FNAME | 24 FUN | 26 STSYM | + | 28 LCSYM | 2A MAIN | 2C | 2E | + | 30 PC | 32 NSYMS | 34 NOMAP | 36 | + | 38 OBJ | 3A | 3C OPT | 3E | + | 40 RSYM | 42 M2C | 44 SLINE | 46 DSLINE | + | 48 BSLINE*| 4A DEFD | 4C | 4E | + | 50 EHDECL*| 52 | 54 CATCH | 56 | + | 58 | 5A | 5C | 5E | + | 60 SSYM | 62 | 64 SO | 66 | + | 68 | 6A | 6C | 6E | + | 70 | 72 | 74 | 76 | + | 78 | 7A | 7C | 7E | + | 80 LSYM | 82 BINCL | 84 SOL | 86 | + | 88 | 8A | 8C | 8E | + | 90 | 92 | 94 | 96 | + | 98 | 9A | 9C | 9E | + | A0 PSYM | A2 EINCL | A4 ENTRY | A6 | + | A8 | AA | AC | AE | + | B0 | B2 | B4 | B6 | + | B8 | BA | BC | BE | + | C0 LBRAC | C2 EXCL | C4 SCOPE | C6 | + | C8 | CA | CC | CE | + | D0 | D2 | D4 | D6 | + | D8 | DA | DC | DE | + | E0 RBRAC | E2 BCOMM | E4 ECOMM | E6 | + | E8 ECOML | EA | EC | EE | + | F0 | F2 | F4 | F6 | + | F8 | FA | FC | FE LENG | + +-----------------------------------------------+ + * 50 EHDECL is also MOD2. + * 48 BSLINE is also BROWS. + */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/stackinfo.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/stackinfo.h new file mode 100644 index 00000000..1ed7b950 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/stackinfo.h @@ -0,0 +1,34 @@ +/* Copyright (C) 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This file contains a bit of information about the stack allocation + of the processor. Since there is no general truth we can't say + anything here. */ + +#ifndef _STACKINFO_H +#define _STACKINFO_H 1 + +#error Machine stack direction unknown. +#if 0 +#define _STACK_GROWS_DOWN 1 +#define _STACK_GROWS_UP 1 +#endif + +#endif /* stackinfo.h */ + + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/stat.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/stat.h new file mode 100644 index 00000000..5fb868d0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/stat.h @@ -0,0 +1,170 @@ +/* Copyright (C) 1992, 1995-2001, 2002, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_STAT_H +# error "Never include directly; use instead." +#endif + +/* Versions of the `struct stat' data structure. */ +#define _STAT_VER_LINUX_OLD 1 +#define _STAT_VER_KERNEL 1 +#define _STAT_VER_SVR4 2 +#define _STAT_VER_LINUX 3 +#define _STAT_VER _STAT_VER_LINUX /* The one defined below. */ + +/* Versions of the `xmknod' interface. */ +#define _MKNOD_VER_LINUX 1 +#define _MKNOD_VER_SVR4 2 +#define _MKNOD_VER _MKNOD_VER_LINUX /* The bits defined below. */ + + +struct stat + { + __dev_t st_dev; /* Device. */ +#ifndef __USE_FILE_OFFSET64 + unsigned short int __pad1; + __ino_t st_ino; /* File serial number. */ +#else + unsigned int __pad1; + __ino_t __st_ino; /* 32bit file serial number. */ +#endif + __mode_t st_mode; /* File mode. */ + __nlink_t st_nlink; /* Link count. */ + __uid_t st_uid; /* User ID of the file's owner. */ + __gid_t st_gid; /* Group ID of the file's group.*/ + __dev_t st_rdev; /* Device number, if device. */ +#ifndef __USE_FILE_OFFSET64 + unsigned short int __pad2; + __off_t st_size; /* Size of file, in bytes. */ +#else + unsigned int __pad2; + __off64_t st_size; /* Size of file, in bytes. */ +#endif + __blksize_t st_blksize; /* Optimal block size for I/O. */ + +#ifndef __USE_FILE_OFFSET64 + __blkcnt_t st_blocks; /* Number 512-byte blocks allocated. */ +#else + __blkcnt64_t st_blocks; /* Number 512-byte blocks allocated. */ +#endif +#ifdef __USE_MISC + /* Nanosecond resolution timestamps are stored in a format + equivalent to 'struct timespec'. This is the type used + whenever possible but the Unix namespace rules do not allow the + identifier 'timespec' to appear in the header. + Therefore we have to handle the use of this header in strictly + standard-compliant sources special. */ + struct timespec st_atim; /* Time of last access. */ + struct timespec st_mtim; /* Time of last modification. */ + struct timespec st_ctim; /* Time of last status change. */ +# define st_atime st_atim.tv_sec /* Backward compatibility. */ +# define st_mtime st_mtim.tv_sec +# define st_ctime st_ctim.tv_sec +#else + __time_t st_atime; /* Time of last access. */ + unsigned long int st_atimensec; /* Nscecs of last access. */ + __time_t st_mtime; /* Time of last modification. */ + unsigned long int st_mtimensec; /* Nsecs of last modification. */ + __time_t st_ctime; /* Time of last status change. */ + unsigned long int st_ctimensec; /* Nsecs of last status change. */ +#endif +#ifndef __USE_FILE_OFFSET64 + unsigned long int __unused4; + unsigned long int __unused5; +#else + __ino64_t st_ino; /* File serial number. */ +#endif + }; + +#ifdef __USE_LARGEFILE64 +struct stat64 + { + __dev_t st_dev; /* Device. */ + unsigned int __pad1; + + __ino_t __st_ino; /* 32bit file serial number. */ + __mode_t st_mode; /* File mode. */ + __nlink_t st_nlink; /* Link count. */ + __uid_t st_uid; /* User ID of the file's owner. */ + __gid_t st_gid; /* Group ID of the file's group.*/ + __dev_t st_rdev; /* Device number, if device. */ + unsigned int __pad2; + __off64_t st_size; /* Size of file, in bytes. */ + __blksize_t st_blksize; /* Optimal block size for I/O. */ + + __blkcnt64_t st_blocks; /* Number 512-byte blocks allocated. */ +#ifdef __USE_MISC + /* Nanosecond resolution timestamps are stored in a format + equivalent to 'struct timespec'. This is the type used + whenever possible but the Unix namespace rules do not allow the + identifier 'timespec' to appear in the header. + Therefore we have to handle the use of this header in strictly + standard-compliant sources special. */ + struct timespec st_atim; /* Time of last access. */ + struct timespec st_mtim; /* Time of last modification. */ + struct timespec st_ctim; /* Time of last status change. */ +#else + __time_t st_atime; /* Time of last access. */ + unsigned long int st_atimensec; /* Nscecs of last access. */ + __time_t st_mtime; /* Time of last modification. */ + unsigned long int st_mtimensec; /* Nsecs of last modification. */ + __time_t st_ctime; /* Time of last status change. */ + unsigned long int st_ctimensec; /* Nsecs of last status change. */ +#endif + __ino64_t st_ino; /* File serial number. */ + }; +#endif + +/* Tell code we have these members. */ +#define _STATBUF_ST_BLKSIZE +#define _STATBUF_ST_RDEV +/* Nanosecond resolution time values are supported. */ +#define _STATBUF_ST_NSEC + +/* Encoding of the file mode. */ + +#define __S_IFMT 0170000 /* These bits determine file type. */ + +/* File types. */ +#define __S_IFDIR 0040000 /* Directory. */ +#define __S_IFCHR 0020000 /* Character device. */ +#define __S_IFBLK 0060000 /* Block device. */ +#define __S_IFREG 0100000 /* Regular file. */ +#define __S_IFIFO 0010000 /* FIFO. */ +#define __S_IFLNK 0120000 /* Symbolic link. */ +#define __S_IFSOCK 0140000 /* Socket. */ + +/* POSIX.1b objects. Note that these macros always evaluate to zero. But + they do it by enforcing the correct use of the macros. */ +#define __S_TYPEISMQ(buf) ((buf)->st_mode - (buf)->st_mode) +#define __S_TYPEISSEM(buf) ((buf)->st_mode - (buf)->st_mode) +#define __S_TYPEISSHM(buf) ((buf)->st_mode - (buf)->st_mode) + +/* Protection bits. */ + +#define __S_ISUID 04000 /* Set user ID on execution. */ +#define __S_ISGID 02000 /* Set group ID on execution. */ +#define __S_ISVTX 01000 /* Save swapped text after use (sticky). */ +#define __S_IREAD 0400 /* Read by owner. */ +#define __S_IWRITE 0200 /* Write by owner. */ +#define __S_IEXEC 0100 /* Execute by owner. */ + +#ifdef __USE_ATFILE +# define UTIME_NOW ((1l << 30) - 1l) +# define UTIME_OMIT ((1l << 30) - 2l) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/statfs.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/statfs.h new file mode 100644 index 00000000..0e27865e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/statfs.h @@ -0,0 +1,67 @@ +/* Copyright (C) 1997, 1998, 2000, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_STATFS_H +# error "Never include directly; use instead." +#endif + +#include + +struct statfs + { + __SWORD_TYPE f_type; + __SWORD_TYPE f_bsize; +#ifndef __USE_FILE_OFFSET64 + __fsblkcnt_t f_blocks; + __fsblkcnt_t f_bfree; + __fsblkcnt_t f_bavail; + __fsfilcnt_t f_files; + __fsfilcnt_t f_ffree; +#else + __fsblkcnt64_t f_blocks; + __fsblkcnt64_t f_bfree; + __fsblkcnt64_t f_bavail; + __fsfilcnt64_t f_files; + __fsfilcnt64_t f_ffree; +#endif + __fsid_t f_fsid; + __SWORD_TYPE f_namelen; + __SWORD_TYPE f_frsize; + __SWORD_TYPE f_spare[5]; + }; + +#ifdef __USE_LARGEFILE64 +struct statfs64 + { + __SWORD_TYPE f_type; + __SWORD_TYPE f_bsize; + __fsblkcnt64_t f_blocks; + __fsblkcnt64_t f_bfree; + __fsblkcnt64_t f_bavail; + __fsfilcnt64_t f_files; + __fsfilcnt64_t f_ffree; + __fsid_t f_fsid; + __SWORD_TYPE f_namelen; + __SWORD_TYPE f_frsize; + __SWORD_TYPE f_spare[5]; + }; +#endif + +/* Tell code we have these members. */ +#define _STATFS_F_NAMELEN +#define _STATFS_F_FRSIZE diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/statvfs.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/statvfs.h new file mode 100644 index 00000000..cca0871a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/statvfs.h @@ -0,0 +1,107 @@ +/* Copyright (C) 1997, 1998, 2000, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_STATVFS_H +# error "Never include directly; use instead." +#endif + +#include /* For __fsblkcnt_t and __fsfilcnt_t. */ + +#if __WORDSIZE == 32 +#define _STATVFSBUF_F_UNUSED +#endif + +struct statvfs + { + unsigned long int f_bsize; + unsigned long int f_frsize; +#ifndef __USE_FILE_OFFSET64 + __fsblkcnt_t f_blocks; + __fsblkcnt_t f_bfree; + __fsblkcnt_t f_bavail; + __fsfilcnt_t f_files; + __fsfilcnt_t f_ffree; + __fsfilcnt_t f_favail; +#else + __fsblkcnt64_t f_blocks; + __fsblkcnt64_t f_bfree; + __fsblkcnt64_t f_bavail; + __fsfilcnt64_t f_files; + __fsfilcnt64_t f_ffree; + __fsfilcnt64_t f_favail; +#endif + unsigned long int f_fsid; +#ifdef _STATVFSBUF_F_UNUSED + int __f_unused; +#endif + unsigned long int f_flag; + unsigned long int f_namemax; + int __f_spare[6]; + }; + +#ifdef __USE_LARGEFILE64 +struct statvfs64 + { + unsigned long int f_bsize; + unsigned long int f_frsize; + __fsblkcnt64_t f_blocks; + __fsblkcnt64_t f_bfree; + __fsblkcnt64_t f_bavail; + __fsfilcnt64_t f_files; + __fsfilcnt64_t f_ffree; + __fsfilcnt64_t f_favail; + unsigned long int f_fsid; +#ifdef _STATVFSBUF_F_UNUSED + int __f_unused; +#endif + unsigned long int f_flag; + unsigned long int f_namemax; + int __f_spare[6]; + }; +#endif + +/* Definitions for the flag in `f_flag'. These definitions should be + kept in sync with the definitions in . */ +enum +{ + ST_RDONLY = 1, /* Mount read-only. */ +#define ST_RDONLY ST_RDONLY + ST_NOSUID = 2 /* Ignore suid and sgid bits. */ +#define ST_NOSUID ST_NOSUID +#ifdef __USE_GNU + , + ST_NODEV = 4, /* Disallow access to device special files. */ +# define ST_NODEV ST_NODEV + ST_NOEXEC = 8, /* Disallow program execution. */ +# define ST_NOEXEC ST_NOEXEC + ST_SYNCHRONOUS = 16, /* Writes are synced at once. */ +# define ST_SYNCHRONOUS ST_SYNCHRONOUS + ST_MANDLOCK = 64, /* Allow mandatory locks on an FS. */ +# define ST_MANDLOCK ST_MANDLOCK + ST_WRITE = 128, /* Write on file/directory/symlink. */ +# define ST_WRITE ST_WRITE + ST_APPEND = 256, /* Append-only file. */ +# define ST_APPEND ST_APPEND + ST_IMMUTABLE = 512, /* Immutable file. */ +# define ST_IMMUTABLE ST_IMMUTABLE + ST_NOATIME = 1024, /* Do not update access times. */ +# define ST_NOATIME ST_NOATIME + ST_NODIRATIME = 2048 /* Do not update directory access times. */ +# define ST_NODIRATIME ST_NODIRATIME +#endif /* Use GNU. */ +}; diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/stdio.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/stdio.h new file mode 100644 index 00000000..d0ba4630 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/stdio.h @@ -0,0 +1,23 @@ +/* Optimizing macros and inline functions for stdio functions. + Copyright (C) 1998, 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _STDIO_H +# error "Never include directly; use instead." +#endif + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/stdio_lim.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/stdio_lim.h new file mode 100644 index 00000000..c35ee601 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/stdio_lim.h @@ -0,0 +1,41 @@ +/* Copyright (C) 1994, 1997, 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#if !defined _STDIO_H && !defined __need_FOPEN_MAX && !defined __need_IOV_MAX +# error "Never include directly; use instead." +#endif + +#ifdef _STDIO_H +# define L_tmpnam 20 +# define TMP_MAX 238328 +# define FILENAME_MAX 4095 + +# ifdef __USE_POSIX +# define L_ctermid 9 +# define L_cuserid 9 +# endif +#endif + +#if defined __need_FOPEN_MAX || defined _STDIO_H +# undef FOPEN_MAX +# define FOPEN_MAX 16 +#endif + +#if defined __need_IOV_MAX && !defined IOV_MAX +# define IOV_MAX 1024 +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/syscalls-common.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/syscalls-common.h new file mode 100644 index 00000000..5e4e350c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/syscalls-common.h @@ -0,0 +1,112 @@ +/* + * Common syscall type defines + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#ifndef _SYSCALLS_COMMON_H +#define _SYSCALLS_COMMON_H 1 + +#ifndef _SYSCALL_H +# error "Never use directly; include instead." +#endif + +#ifndef SYS_ify +# define SYS_ify(syscall_name) (__NR_##syscall_name) +#endif + +#ifndef __ASSEMBLER__ + +#include + +#ifndef INTERNAL_SYSCALL_DECL +# define INTERNAL_SYSCALL_DECL(err) do { } while (0) +#endif +#ifndef INTERNAL_SYSCALL_ERROR_P +# define INTERNAL_SYSCALL_ERROR_P(val, err) ((unsigned long)val >= (unsigned long)(-4095)) +#endif +#ifndef INTERNAL_SYSCALL_ERRNO +# define INTERNAL_SYSCALL_ERRNO(val, err) (-(val)) +#endif + +/* Define a macro which expands into the inline wrapper code for a system call */ +#ifndef INLINE_SYSCALL +# define INLINE_SYSCALL(name, nr, args...) INLINE_SYSCALL_NCS(__NR_##name, nr, args) +#endif +#ifndef INLINE_SYSCALL_NOERR +# define INLINE_SYSCALL_NOERR(name, nr, args...) INLINE_SYSCALL_NOERR_NCS(__NR_##name, nr, args) +#endif + +/* Just like INLINE_SYSCALL(), but take a non-constant syscall (NCS) argument */ +#ifndef INLINE_SYSCALL_NCS +# define INLINE_SYSCALL_NCS(name, nr, args...) \ +({ \ + INTERNAL_SYSCALL_DECL(__err); \ + long __res = INTERNAL_SYSCALL_NCS(name, __err, nr, args); \ + if (unlikely(INTERNAL_SYSCALL_ERROR_P(__res, __err))) { \ + __set_errno(INTERNAL_SYSCALL_ERRNO(__res, __err)); \ + __res = -1L; \ + } \ + __res; \ +}) +#endif +#ifndef INLINE_SYSCALL_NOERR_NCS +# define INLINE_SYSCALL_NOERR_NCS(name, nr, args...) \ +({ \ + INTERNAL_SYSCALL_DECL(__err); \ + long __res = INTERNAL_SYSCALL_NCS(name, __err, nr, args); \ + __res; \ +}) +#endif + +/* No point in forcing people to implement both when they only need one */ +#ifndef INTERNAL_SYSCALL +# define INTERNAL_SYSCALL(name, err, nr, args...) INTERNAL_SYSCALL_NCS(__NR_##name, err, nr, args) +#endif + +#ifndef INTERNAL_SYSCALL_NCS +# error your port needs to define INTERNAL_SYSCALL_NCS in bits/syscalls.h +#endif + +#ifndef _syscall0 + +#define C_DECL_ARGS_0() void +#define C_DECL_ARGS_1(t, v) t v +#define C_DECL_ARGS_2(t, v, args...) t v, C_DECL_ARGS_1(args) +#define C_DECL_ARGS_3(t, v, args...) t v, C_DECL_ARGS_2(args) +#define C_DECL_ARGS_4(t, v, args...) t v, C_DECL_ARGS_3(args) +#define C_DECL_ARGS_5(t, v, args...) t v, C_DECL_ARGS_4(args) +#define C_DECL_ARGS_6(t, v, args...) t v, C_DECL_ARGS_5(args) + +#define C_ARGS_0() +#define C_ARGS_1(t, v) v +#define C_ARGS_2(t, v, args...) v, C_ARGS_1(args) +#define C_ARGS_3(t, v, args...) v, C_ARGS_2(args) +#define C_ARGS_4(t, v, args...) v, C_ARGS_3(args) +#define C_ARGS_5(t, v, args...) v, C_ARGS_4(args) +#define C_ARGS_6(t, v, args...) v, C_ARGS_5(args) + +#define SYSCALL_FUNC(nargs, type, name, args...) \ +type name(C_DECL_ARGS_##nargs(args)) { \ + return (type)INLINE_SYSCALL(name, nargs, C_ARGS_##nargs(args)); \ +} + +#define SYSCALL_NOERR_FUNC(nargs, type, name, args...) \ +type name(C_DECL_ARGS_##nargs(args)) { \ + return (type)INLINE_SYSCALL_NOERR(name, nargs, C_ARGS_##nargs(args)); \ +} + +#define _syscall0(args...) SYSCALL_FUNC(0, args) +#define _syscall1(args...) SYSCALL_FUNC(1, args) +#define _syscall_noerr1(args...) SYSCALL_NOERR_FUNC(1, args) +#define _syscall2(args...) SYSCALL_FUNC(2, args) +#define _syscall3(args...) SYSCALL_FUNC(3, args) +#define _syscall4(args...) SYSCALL_FUNC(4, args) +#define _syscall5(args...) SYSCALL_FUNC(5, args) +#define _syscall6(args...) SYSCALL_FUNC(6, args) + +#endif /* _syscall0 */ + +#endif /* __ASSEMBLER__ */ + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/syscalls.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/syscalls.h new file mode 100644 index 00000000..03d08d1d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/syscalls.h @@ -0,0 +1,9 @@ +/* Unlike the asm/unistd.h kernel header file (which this is partly based on), + * this file must be able to cope with PIC and non-PIC code. For some arches + * there is no difference. For x86 (which has far too few registers) there is + * a difference. Regardless, including asm/unistd.h is hereby officially + * forbidden. Don't do it. It is bad for you. + */ + +#error You have not provided architecture specific bits/syscalls.h +#error You should need to define only INTERNAL_SYSCALL_NCS diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/termios.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/termios.h new file mode 100644 index 00000000..b648d800 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/termios.h @@ -0,0 +1,219 @@ +/* termios type and macro definitions. Linux version. + Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2003, 2005 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _TERMIOS_H +# error "Never include directly; use instead." +#endif + +typedef unsigned char cc_t; +typedef unsigned int speed_t; +typedef unsigned int tcflag_t; + +#define NCCS 32 +struct termios + { + tcflag_t c_iflag; /* input mode flags */ + tcflag_t c_oflag; /* output mode flags */ + tcflag_t c_cflag; /* control mode flags */ + tcflag_t c_lflag; /* local mode flags */ + cc_t c_line; /* line discipline */ + cc_t c_cc[NCCS]; /* control characters */ + speed_t c_ispeed; /* input speed */ + speed_t c_ospeed; /* output speed */ +#define _HAVE_STRUCT_TERMIOS_C_ISPEED 1 +#define _HAVE_STRUCT_TERMIOS_C_OSPEED 1 + }; + +/* c_cc characters */ +#define VINTR 0 +#define VQUIT 1 +#define VERASE 2 +#define VKILL 3 +#define VEOF 4 +#define VTIME 5 +#define VMIN 6 +#define VSWTC 7 +#define VSTART 8 +#define VSTOP 9 +#define VSUSP 10 +#define VEOL 11 +#define VREPRINT 12 +#define VDISCARD 13 +#define VWERASE 14 +#define VLNEXT 15 +#define VEOL2 16 + +/* c_iflag bits */ +#define IGNBRK 0000001 +#define BRKINT 0000002 +#define IGNPAR 0000004 +#define PARMRK 0000010 +#define INPCK 0000020 +#define ISTRIP 0000040 +#define INLCR 0000100 +#define IGNCR 0000200 +#define ICRNL 0000400 +#define IUCLC 0001000 +#define IXON 0002000 +#define IXANY 0004000 +#define IXOFF 0010000 +#define IMAXBEL 0020000 +#define IUTF8 0040000 + +/* c_oflag bits */ +#define OPOST 0000001 +#define OLCUC 0000002 +#define ONLCR 0000004 +#define OCRNL 0000010 +#define ONOCR 0000020 +#define ONLRET 0000040 +#define OFILL 0000100 +#define OFDEL 0000200 +#if defined __USE_MISC || defined __USE_XOPEN +# define NLDLY 0000400 +# define NL0 0000000 +# define NL1 0000400 +# define CRDLY 0003000 +# define CR0 0000000 +# define CR1 0001000 +# define CR2 0002000 +# define CR3 0003000 +# define TABDLY 0014000 +# define TAB0 0000000 +# define TAB1 0004000 +# define TAB2 0010000 +# define TAB3 0014000 +# define BSDLY 0020000 +# define BS0 0000000 +# define BS1 0020000 +# define FFDLY 0100000 +# define FF0 0000000 +# define FF1 0100000 +#endif + +#define VTDLY 0040000 +#define VT0 0000000 +#define VT1 0040000 + +#ifdef __USE_MISC +# define XTABS 0014000 +#endif + +/* c_cflag bit meaning */ +#ifdef __USE_MISC +# define CBAUD 0010017 +#endif +#define B0 0000000 /* hang up */ +#define B50 0000001 +#define B75 0000002 +#define B110 0000003 +#define B134 0000004 +#define B150 0000005 +#define B200 0000006 +#define B300 0000007 +#define B600 0000010 +#define B1200 0000011 +#define B1800 0000012 +#define B2400 0000013 +#define B4800 0000014 +#define B9600 0000015 +#define B19200 0000016 +#define B38400 0000017 +#ifdef __USE_MISC +# define EXTA B19200 +# define EXTB B38400 +#endif +#define CSIZE 0000060 +#define CS5 0000000 +#define CS6 0000020 +#define CS7 0000040 +#define CS8 0000060 +#define CSTOPB 0000100 +#define CREAD 0000200 +#define PARENB 0000400 +#define PARODD 0001000 +#define HUPCL 0002000 +#define CLOCAL 0004000 +#ifdef __USE_MISC +# define CBAUDEX 0010000 +#endif +#define BOTHER 0010000 +#define B57600 0010001 +#define B115200 0010002 +#define B230400 0010003 +#define B460800 0010004 +#define B500000 0010005 +#define B576000 0010006 +#define B921600 0010007 +#define B1000000 0010010 +#define B1152000 0010011 +#define B1500000 0010012 +#define B2000000 0010013 +#define B2500000 0010014 +#define B3000000 0010015 +#define B3500000 0010016 +#define B4000000 0010017 +#define __MAX_BAUD B4000000 +#ifdef __USE_MISC +# define CIBAUD 002003600000 /* input baud rate (not used) */ +# define CMSPAR 010000000000 /* mark or space (stick) parity */ +# define CRTSCTS 020000000000 /* flow control */ +#endif + +/* c_lflag bits */ +#define ISIG 0000001 +#define ICANON 0000002 +#if defined __USE_MISC || defined __USE_XOPEN +# define XCASE 0000004 +#endif +#define ECHO 0000010 +#define ECHOE 0000020 +#define ECHOK 0000040 +#define ECHONL 0000100 +#define NOFLSH 0000200 +#define TOSTOP 0000400 +#ifdef __USE_MISC +# define ECHOCTL 0001000 +# define ECHOPRT 0002000 +# define ECHOKE 0004000 +# define FLUSHO 0010000 +# define PENDIN 0040000 +#endif +#define IEXTEN 0100000 + +/* tcflow() and TCXONC use these */ +#define TCOOFF 0 +#define TCOON 1 +#define TCIOFF 2 +#define TCION 3 + +/* tcflush() and TCFLSH use these */ +#define TCIFLUSH 0 +#define TCOFLUSH 1 +#define TCIOFLUSH 2 + +/* tcsetattr uses these */ +#define TCSANOW 0 +#define TCSADRAIN 1 +#define TCSAFLUSH 2 + + +#define _IOT_termios /* Hurd ioctl type field. */ \ + _IOT (_IOTS (cflag_t), 4, _IOTS (cc_t), NCCS, _IOTS (speed_t), 2) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/time.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/time.h new file mode 100644 index 00000000..7ed54bfa --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/time.h @@ -0,0 +1,79 @@ +/* System-dependent timing definitions. Generic version. + Copyright (C) 1996,1997,1999-2002,2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * Never include this file directly; use instead. + */ + +#ifndef __need_timeval +# ifndef _BITS_TIME_H +# define _BITS_TIME_H 1 + +/* ISO/IEC 9899:1990 7.12.1: + The macro `CLOCKS_PER_SEC' is the number per second of the value + returned by the `clock' function. */ +/* CAE XSH, Issue 4, Version 2: + The value of CLOCKS_PER_SEC is required to be 1 million on all + XSI-conformant systems. */ +# define CLOCKS_PER_SEC 1000000l + +/* Get the arch-specific value of __UCLIBC_CLK_TCK_CONST used for CLK_TCK + * in sysconf() and clock(). */ +#include + +# if !defined __STRICT_ANSI__ && !defined __USE_XOPEN2K +/* Even though CLOCKS_PER_SEC has such a strange value CLK_TCK + presents the real value for clock ticks per second for the system. */ +# include +/* Note (uClibc): glibc #defines CLK_TCK as a sysconf() call. */ +# define CLK_TCK ((__clock_t) __UCLIBC_CLK_TCK_CONST) +# endif + +# ifdef __USE_POSIX199309 +/* Identifier for system-wide realtime clock. */ +# define CLOCK_REALTIME 0 +/* Monotonic system-wide clock. */ +# define CLOCK_MONOTONIC 1 +/* High-resolution timer from the CPU. */ +# define CLOCK_PROCESS_CPUTIME_ID 2 +/* Thread-specific CPU-time clock. */ +# define CLOCK_THREAD_CPUTIME_ID 3 + +/* Flag to indicate time is absolute. */ +# define TIMER_ABSTIME 1 +# endif + +# endif /* bits/time.h */ +#endif + +#ifdef __need_timeval +# undef __need_timeval +# ifndef _STRUCT_TIMEVAL +# define _STRUCT_TIMEVAL 1 +# include + +/* A time value that is accurate to the nearest + microsecond but also has a range of years. */ +struct timeval + { + __time_t tv_sec; /* Seconds. */ + __suseconds_t tv_usec; /* Microseconds. */ + }; +# endif /* struct timeval */ +#endif /* need timeval */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/types.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/types.h new file mode 100644 index 00000000..24d0056f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/types.h @@ -0,0 +1,213 @@ +/* bits/types.h -- definitions of __*_t types underlying *_t types. + Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * Never include this file directly; use instead. + */ + +#ifndef _BITS_TYPES_H +#define _BITS_TYPES_H 1 + +#include +#include + +#define __need_size_t +#include +#ifdef _LIBC +#include +#endif + +/* Convenience types. */ +typedef unsigned char __u_char; +typedef unsigned short int __u_short; +typedef unsigned int __u_int; +typedef unsigned long int __u_long; + +/* Fixed-size types, underlying types depend on word size and compiler. */ +typedef signed char __int8_t; +typedef unsigned char __uint8_t; +typedef signed short int __int16_t; +typedef unsigned short int __uint16_t; +typedef signed int __int32_t; +typedef unsigned int __uint32_t; +#if __WORDSIZE == 64 +typedef signed long int __int64_t; +typedef unsigned long int __uint64_t; +#elif defined(__GNUC__) +__extension__ typedef signed long long int __int64_t; +__extension__ typedef unsigned long long int __uint64_t; +#endif + +/* quad_t is also 64 bits. */ +#if __WORDSIZE == 64 +typedef long int __quad_t; +typedef unsigned long int __u_quad_t; +#elif defined(__GNUC__) +__extension__ typedef long long int __quad_t; +__extension__ typedef unsigned long long int __u_quad_t; +#else +typedef struct +{ + long __val[2]; +} __quad_t; +typedef struct +{ + __u_long __val[2]; +} __u_quad_t; +#endif + + +/* The machine-dependent file defines __*_T_TYPE + macros for each of the OS types we define below. The definitions + of those macros must use the following macros for underlying types. + We define __S_TYPE and __U_TYPE for the signed and unsigned + variants of each of the following integer types on this machine. + + 16 -- "natural" 16-bit type (always short) + 32 -- "natural" 32-bit type (always int) + 64 -- "natural" 64-bit type (long or long long) + LONG32 -- 32-bit type, traditionally long + QUAD -- 64-bit type, always long long + WORD -- natural type of __WORDSIZE bits (int or long) + LONGWORD -- type of __WORDSIZE bits, traditionally long + + We distinguish WORD/LONGWORD, 32/LONG32, and 64/QUAD so that the + conventional uses of `long' or `long long' type modifiers match the + types we define, even when a less-adorned type would be the same size. + This matters for (somewhat) portably writing printf/scanf formats for + these types, where using the appropriate l or ll format modifiers can + make the typedefs and the formats match up across all GNU platforms. If + we used `long' when it's 64 bits where `long long' is expected, then the + compiler would warn about the formats not matching the argument types, + and the programmer changing them to shut up the compiler would break the + program's portability. + + Here we assume what is presently the case in all the GCC configurations + we support: long long is always 64 bits, long is always word/address size, + and int is always 32 bits. */ + +#define __S16_TYPE short int +#define __U16_TYPE unsigned short int +#define __S32_TYPE int +#define __U32_TYPE unsigned int +#define __SLONGWORD_TYPE long int +#define __ULONGWORD_TYPE unsigned long int +#if __WORDSIZE == 32 +# define __SQUAD_TYPE __quad_t +# define __UQUAD_TYPE __u_quad_t +# define __SWORD_TYPE int +# define __UWORD_TYPE unsigned int +# define __SLONG32_TYPE long int +# define __ULONG32_TYPE unsigned long int +# define __S64_TYPE __quad_t +# define __U64_TYPE __u_quad_t +/* We want __extension__ before typedef's that use nonstandard base types + such as `long long' in C89 mode. */ +# define __STD_TYPE __extension__ typedef +#elif __WORDSIZE == 64 +# define __SQUAD_TYPE long int +# define __UQUAD_TYPE unsigned long int +# define __SWORD_TYPE long int +# define __UWORD_TYPE unsigned long int +# define __SLONG32_TYPE int +# define __ULONG32_TYPE unsigned int +# define __S64_TYPE long int +# define __U64_TYPE unsigned long int +/* No need to mark the typedef with __extension__. */ +# define __STD_TYPE typedef +#else +# error your machine is neither 32 bit or 64 bit ... it must be magical +#endif +#include /* Defines __*_T_TYPE macros. */ + + +__STD_TYPE __DEV_T_TYPE __dev_t; /* Type of device numbers. */ +__STD_TYPE __UID_T_TYPE __uid_t; /* Type of user identifications. */ +__STD_TYPE __GID_T_TYPE __gid_t; /* Type of group identifications. */ +__STD_TYPE __INO_T_TYPE __ino_t; /* Type of file serial numbers. */ +__STD_TYPE __INO64_T_TYPE __ino64_t; /* Type of file serial numbers (LFS).*/ +__STD_TYPE __MODE_T_TYPE __mode_t; /* Type of file attribute bitmasks. */ +__STD_TYPE __NLINK_T_TYPE __nlink_t; /* Type of file link counts. */ +__STD_TYPE __OFF_T_TYPE __off_t; /* Type of file sizes and offsets. */ +__STD_TYPE __OFF64_T_TYPE __off64_t; /* Type of file sizes and offsets (LFS). */ +__STD_TYPE __PID_T_TYPE __pid_t; /* Type of process identifications. */ +__STD_TYPE __FSID_T_TYPE __fsid_t; /* Type of file system IDs. */ +__STD_TYPE __CLOCK_T_TYPE __clock_t; /* Type of CPU usage counts. */ +__STD_TYPE __RLIM_T_TYPE __rlim_t; /* Type for resource measurement. */ +__STD_TYPE __RLIM64_T_TYPE __rlim64_t; /* Type for resource measurement (LFS). */ +__STD_TYPE __ID_T_TYPE __id_t; /* General type for IDs. */ +__STD_TYPE __TIME_T_TYPE __time_t; /* Seconds since the Epoch. */ +__STD_TYPE __USECONDS_T_TYPE __useconds_t; /* Count of microseconds. */ +__STD_TYPE __SUSECONDS_T_TYPE __suseconds_t; /* Signed count of microseconds. */ + +__STD_TYPE __DADDR_T_TYPE __daddr_t; /* The type of a disk address. */ +__STD_TYPE __SWBLK_T_TYPE __swblk_t; /* Type of a swap block maybe? */ +__STD_TYPE __KEY_T_TYPE __key_t; /* Type of an IPC key. */ + +/* Clock ID used in clock and timer functions. */ +__STD_TYPE __CLOCKID_T_TYPE __clockid_t; + +/* Timer ID returned by `timer_create'. */ +__STD_TYPE __TIMER_T_TYPE __timer_t; + +/* Type to represent block size. */ +__STD_TYPE __BLKSIZE_T_TYPE __blksize_t; + +/* Types from the Large File Support interface. */ + +/* Type to count number of disk blocks. */ +__STD_TYPE __BLKCNT_T_TYPE __blkcnt_t; +__STD_TYPE __BLKCNT64_T_TYPE __blkcnt64_t; + +/* Type to count file system blocks. */ +__STD_TYPE __FSBLKCNT_T_TYPE __fsblkcnt_t; +__STD_TYPE __FSBLKCNT64_T_TYPE __fsblkcnt64_t; + +/* Type to count file system nodes. */ +__STD_TYPE __FSFILCNT_T_TYPE __fsfilcnt_t; +__STD_TYPE __FSFILCNT64_T_TYPE __fsfilcnt64_t; + +__STD_TYPE __SSIZE_T_TYPE __ssize_t; /* Type of a byte count, or error. */ + +/* These few don't really vary by system, they always correspond + to one of the other defined types. */ +typedef __off64_t __loff_t; /* Type of file sizes and offsets (LFS). */ +typedef __quad_t *__qaddr_t; +typedef char *__caddr_t; + +/* Duplicates info from stdint.h but this is used in unistd.h. */ +__STD_TYPE __SWORD_TYPE __intptr_t; + +/* Duplicate info from sys/socket.h. */ +__STD_TYPE __U32_TYPE __socklen_t; + + +#undef __STD_TYPE + +#ifdef _LIBC +/* Used in `struct shmid_ds'. */ +typedef __kernel_ipc_pid_t __ipc_pid_t; +#endif + +/* Now add the thread types. */ +#if defined __UCLIBC_HAS_THREADS__ && (defined __USE_POSIX199506 || defined __USE_UNIX98) +# include +#endif + +#endif /* bits/types.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/typesizes.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/typesizes.h new file mode 100644 index 00000000..e9226c41 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/typesizes.h @@ -0,0 +1,66 @@ +/* bits/typesizes.h -- underlying types for *_t. Generic version. + Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _BITS_TYPES_H +# error "Never include directly; use instead." +#endif + +#ifndef _BITS_TYPESIZES_H +#define _BITS_TYPESIZES_H 1 + +/* See for the meaning of these macros. This file exists so + that need not vary across different GNU platforms. */ + +#define __DEV_T_TYPE __UQUAD_TYPE +#define __UID_T_TYPE __U32_TYPE +#define __GID_T_TYPE __U32_TYPE +#define __INO_T_TYPE __ULONGWORD_TYPE +#define __INO64_T_TYPE __UQUAD_TYPE +#define __MODE_T_TYPE __U32_TYPE +#define __NLINK_T_TYPE __UWORD_TYPE +#define __OFF_T_TYPE __SLONGWORD_TYPE +#define __OFF64_T_TYPE __SQUAD_TYPE +#define __PID_T_TYPE __S32_TYPE +#define __RLIM_T_TYPE __ULONGWORD_TYPE +#define __RLIM64_T_TYPE __UQUAD_TYPE +#define __BLKCNT_T_TYPE __SLONGWORD_TYPE +#define __BLKCNT64_T_TYPE __SQUAD_TYPE +#define __FSBLKCNT_T_TYPE __ULONGWORD_TYPE +#define __FSBLKCNT64_T_TYPE __UQUAD_TYPE +#define __FSFILCNT_T_TYPE __ULONGWORD_TYPE +#define __FSFILCNT64_T_TYPE __UQUAD_TYPE +#define __ID_T_TYPE __U32_TYPE +#define __CLOCK_T_TYPE __SLONGWORD_TYPE +#define __TIME_T_TYPE __SLONGWORD_TYPE +#define __USECONDS_T_TYPE __U32_TYPE +#define __SUSECONDS_T_TYPE __SLONGWORD_TYPE +#define __DADDR_T_TYPE __S32_TYPE +#define __SWBLK_T_TYPE __SLONGWORD_TYPE +#define __KEY_T_TYPE __S32_TYPE +#define __CLOCKID_T_TYPE __S32_TYPE +#define __TIMER_T_TYPE void * +#define __BLKSIZE_T_TYPE __SLONGWORD_TYPE +#define __FSID_T_TYPE struct { int __val[2]; } +#define __SSIZE_T_TYPE __SWORD_TYPE + +/* Number of descriptors that can fit in an `fd_set'. */ +#define __FD_SETSIZE 1024 + + +#endif /* bits/typesizes.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/uClibc_alloc.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/uClibc_alloc.h new file mode 100644 index 00000000..6a70d27b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/uClibc_alloc.h @@ -0,0 +1,26 @@ +/* + * Macros to transparently switch between the stack and heap for large + * allocations. The former is useful on MMU systems as it results in + * smaller code, but the latter is required on NoMMU systems. This is + * due to small stacks that cannot grow and so doing large allocs will + * cause a stack overflow. + * + * Copyright (C) 2010 Mike Frysinger + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#ifndef _UCLIBC_ALLOC_H +#define _UCLIBC_ALLOC_H + +#include +#include + +#ifdef __ARCH_USE_MMU__ +# define stack_heap_alloc(x) alloca(x) +# define stack_heap_free(x) do { if (0) free(x); } while (0) +#else +# define stack_heap_alloc(x) malloc(x) +# define stack_heap_free(x) free(x) +#endif + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/uClibc_arch_features.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/uClibc_arch_features.h new file mode 100644 index 00000000..6cb61775 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/uClibc_arch_features.h @@ -0,0 +1,50 @@ +/* + * Track misc arch-specific features that aren't config options + */ + +#ifndef _BITS_UCLIBC_ARCH_FEATURES_H +#define _BITS_UCLIBC_ARCH_FEATURES_H + +#error "You should copy this to your arch/bits/ dir and customize" + +/* instruction used when calling abort() to kill yourself */ +/*#define __UCLIBC_ABORT_INSTRUCTION__ "asm instruction"*/ +#undef __UCLIBC_ABORT_INSTRUCTION__ + +/* can your target use syscall6() for mmap ? */ +#undef __UCLIBC_MMAP_HAS_6_ARGS__ + +/* does your target use syscall4() for truncate64 ? (32bit arches only) */ +#undef __UCLIBC_TRUNCATE64_HAS_4_ARGS__ + +/* does your target have a broken create_module() ? */ +#undef __UCLIBC_BROKEN_CREATE_MODULE__ + +/* does your target have to worry about older [gs]etrlimit() ? */ +#undef __UCLIBC_HANDLE_OLDER_RLIMIT__ + +/* does your target have an asm .set ? */ +#define __UCLIBC_HAVE_ASM_SET_DIRECTIVE__ + +/* define if target doesn't like .global */ +#undef __UCLIBC_ASM_GLOBAL_DIRECTIVE__ + +/* define if target supports .weak */ +#define __UCLIBC_HAVE_ASM_WEAK_DIRECTIVE__ + +/* define if target supports .weakext */ +#undef __UCLIBC_HAVE_ASM_WEAKEXT_DIRECTIVE__ + +/* needed probably only for ppc64 */ +#undef __UCLIBC_HAVE_ASM_GLOBAL_DOT_NAME__ + +/* define if target supports CFI pseudo ops */ +#undef __UCLIBC_HAVE_ASM_CFI_DIRECTIVES__ + +/* define if target supports IEEE signed zero floats */ +#define __UCLIBC_HAVE_SIGNED_ZERO__ + +/* only weird assemblers generally need this */ +#undef __UCLIBC_ASM_LINE_SEP__ + +#endif /* _BITS_UCLIBC_ARCH_FEATURES_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/uClibc_charclass.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/uClibc_charclass.h new file mode 100644 index 00000000..50df539b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/uClibc_charclass.h @@ -0,0 +1,40 @@ +/* Copyright (C) 2008 Denys Vlasenko + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + */ + +#ifndef _BITS_UCLIBC_CHARCLASS_H +#define _BITS_UCLIBC_CHARCLASS_H + +/* Taking advantage of the C99 mutual-exclusion guarantees for the various + * (w)ctype classes, including the descriptions of printing and control + * (w)chars, we can place each in one of the following mutually-exlusive + * subsets. Since there are less than 16, we can store the data for + * each (w)chars in a nibble. In contrast, glibc uses an unsigned int + * per (w)char, with one bit flag for each is* type. While this allows + * a simple '&' operation to determine the type vs. a range test and a + * little special handling for the "blank" and "xdigit" types in my + * approach, it also uses 8 times the space for the tables on the typical + * 32-bit archs we supported.*/ +enum { + __CTYPE_unclassified = 0, + __CTYPE_alpha_nonupper_nonlower, + __CTYPE_alpha_lower, + __CTYPE_alpha_upper_lower, + __CTYPE_alpha_upper, + __CTYPE_digit, + __CTYPE_punct, + __CTYPE_graph, + __CTYPE_print_space_nonblank, + __CTYPE_print_space_blank, + __CTYPE_space_nonblank_noncntrl, + __CTYPE_space_blank_noncntrl, + __CTYPE_cntrl_space_nonblank, + __CTYPE_cntrl_space_blank, + __CTYPE_cntrl_nonspace +}; + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/uClibc_clk_tck.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/uClibc_clk_tck.h new file mode 100644 index 00000000..00b77bfc --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/uClibc_clk_tck.h @@ -0,0 +1,8 @@ +/* Use a default of 100 for CLK_TCK to implement sysconf() and clock(). + * Override this by supplying an arch-specific version of this header file. + * + * WARNING: It is assumed that this is a constant integer value usable in + * preprocessor conditionals!!! + */ + +#define __UCLIBC_CLK_TCK_CONST 100 diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/uClibc_ctype.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/uClibc_ctype.h new file mode 100644 index 00000000..3bf4e1b2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/uClibc_ctype.h @@ -0,0 +1,199 @@ +/* Copyright (C) 2002 Manuel Novoa III + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * The GNU C Library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the GNU C Library; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 USA. + */ + +/* ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION! + * + * Besides uClibc, I'm using this code in my libc for elks, which is + * a 16-bit environment with a fairly limited compiler. It would make + * things much easier for me if this file isn't modified unnecessarily. + * In particular, please put any new or replacement functions somewhere + * else, and modify the makefile to use your version instead. + * Thanks. Manuel + * + * ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION! */ + +#if !defined(_CTYPE_H) && !defined(_WCTYPE_H) +#error Always include <{w}ctype.h> rather than +#endif + +#ifndef _BITS_UCLIBC_CTYPE_H +#define _BITS_UCLIBC_CTYPE_H + +#ifdef __UCLIBC_GEN_LOCALE +/* We are in extra/locale/gen_XXX tools build */ + +#include "uClibc_charclass.h" + +#else + +/* Define some ctype macros valid for the C/POSIX locale. */ + +/* ASCII ords of \t, \f, \n, \r, and \v are 9, 12, 10, 13, 11 respectively. */ +#define __C_isspace(c) \ + ((sizeof(c) == sizeof(char)) \ + ? ((((c) == ' ') || (((unsigned char)((c) - 9)) <= (13 - 9)))) \ + : ((((c) == ' ') || (((unsigned int)((c) - 9)) <= (13 - 9))))) +#define __C_isblank(c) (((c) == ' ') || ((c) == '\t')) +#define __C_isdigit(c) \ + ((sizeof(c) == sizeof(char)) \ + ? (((unsigned char)((c) - '0')) < 10) \ + : (((unsigned int)((c) - '0')) < 10)) +#define __C_isxdigit(c) \ + (__C_isdigit(c) \ + || ((sizeof(c) == sizeof(char)) \ + ? (((unsigned char)((((c)) | 0x20) - 'a')) < 6) \ + : (((unsigned int)((((c)) | 0x20) - 'a')) < 6))) +#define __C_iscntrl(c) \ + ((sizeof(c) == sizeof(char)) \ + ? ((((unsigned char)(c)) < 0x20) || ((c) == 0x7f)) \ + : ((((unsigned int)(c)) < 0x20) || ((c) == 0x7f))) +#define __C_isalpha(c) \ + ((sizeof(c) == sizeof(char)) \ + ? (((unsigned char)(((c) | 0x20) - 'a')) < 26) \ + : (((unsigned int)(((c) | 0x20) - 'a')) < 26)) +#define __C_isalnum(c) (__C_isalpha(c) || __C_isdigit(c)) +#define __C_isprint(c) \ + ((sizeof(c) == sizeof(char)) \ + ? (((unsigned char)((c) - 0x20)) <= (0x7e - 0x20)) \ + : (((unsigned int)((c) - 0x20)) <= (0x7e - 0x20))) +#define __C_islower(c) \ + ((sizeof(c) == sizeof(char)) \ + ? (((unsigned char)((c) - 'a')) < 26) \ + : (((unsigned int)((c) - 'a')) < 26)) +#define __C_isupper(c) \ + ((sizeof(c) == sizeof(char)) \ + ? (((unsigned char)((c) - 'A')) < 26) \ + : (((unsigned int)((c) - 'A')) < 26)) +#define __C_ispunct(c) \ + ((!__C_isalnum(c)) \ + && ((sizeof(c) == sizeof(char)) \ + ? (((unsigned char)((c) - 0x21)) <= (0x7e - 0x21)) \ + : (((unsigned int)((c) - 0x21)) <= (0x7e - 0x21)))) +#define __C_isgraph(c) \ + ((sizeof(c) == sizeof(char)) \ + ? (((unsigned char)((c) - 0x21)) <= (0x7e - 0x21)) \ + : (((unsigned int)((c) - 0x21)) <= (0x7e - 0x21))) + +#define __C_tolower(c) (__C_isupper(c) ? ((c) | 0x20) : (c)) +#define __C_toupper(c) (__C_islower(c) ? ((c) ^ 0x20) : (c)) + +/**********************************************************************/ +__BEGIN_DECLS + +#if defined _LIBC && (defined NOT_IN_libc || defined IS_IN_libc) +/* These are uClibc-specific. */ +# define __isdigit_char(c) ((unsigned char)((c) - '0') <= 9) +# define __isdigit_int(c) ((unsigned int)((c) - '0') <= 9) +#endif + +/* Now some non-ansi/iso c99 macros. */ + +#ifdef __UCLIBC_SUSV4_LEGACY__ +#define __isascii(c) (((c) & ~0x7f) == 0) +#define __toascii(c) ((c) & 0x7f) +/* Works correctly *only* on lowercase letters! */ +#define _toupper(c) ((c) ^ 0x20) +/* Works correctly *only* on letters (of any case) and numbers */ +#define _tolower(c) ((c) | 0x20) +#endif + +__END_DECLS + +/**********************************************************************/ +#ifdef __GNUC__ + +# define __body_C_macro(f,args) __C_ ## f args + +# define __body(f,c) \ +(__extension__ ({ \ + int __res; \ + if (sizeof(c) > sizeof(char)) { \ + int __c = (c); \ + __res = __body_C_macro(f,(__c)); \ + } else { \ + unsigned char __c = (c); \ + __res = __body_C_macro(f,(__c)); \ + } \ + __res; \ +})) + +# define __isspace(c) __body(isspace,c) +# define __isblank(c) __body(isblank,c) +# define __isdigit(c) __body(isdigit,c) +# define __isxdigit(c) __body(isxdigit,c) +# define __iscntrl(c) __body(iscntrl,c) +# define __isalpha(c) __body(isalpha,c) +# define __isalnum(c) __body(isalnum,c) +# define __isprint(c) __body(isprint,c) +# define __islower(c) __body(islower,c) +# define __isupper(c) __body(isupper,c) +# define __ispunct(c) __body(ispunct,c) +# define __isgraph(c) __body(isgraph,c) + +/*locale-aware ctype.h has no __tolower, why stub locale + *tries to have it? remove after 0.9.31 + *# define __tolower(c) __body(tolower,c) + *# define __toupper(c) __body(toupper,c) + */ + +/* Do not combine in one #if - unifdef tool is not that clever */ +# ifndef __NO_CTYPE +# ifndef __cplusplus + +# define isspace(c) __isspace(c) +# define isblank(c) __isblank(c) +# define isdigit(c) __isdigit(c) +# define isxdigit(c) __isxdigit(c) +# define iscntrl(c) __iscntrl(c) +# define isalpha(c) __isalpha(c) +# define isalnum(c) __isalnum(c) +# define isprint(c) __isprint(c) +# define islower(c) __islower(c) +# define isupper(c) __isupper(c) +# define ispunct(c) __ispunct(c) +# define isgraph(c) __isgraph(c) + +# define tolower(c) __body(tolower,c) +# define toupper(c) __body(toupper,c) + +# endif +# endif + +#else /* !_GNUC__ */ + +# ifndef __NO_CTYPE +# ifndef __cplusplus + +/* These macros should be safe from side effects! + * (not all __C_xxx macros are) */ +# define isdigit(c) __C_isdigit(c) +# define isalpha(c) __C_isalpha(c) +# define isprint(c) __C_isprint(c) +# define islower(c) __C_islower(c) +# define isupper(c) __C_isupper(c) +# define isgraph(c) __C_isgraph(c) + +# endif +# endif + +#endif /* __GNUC__ */ +/**********************************************************************/ + +#endif /* __UCLIBC_GEN_LOCALE */ + +#endif /* _BITS_UCLIBC_CTYPE_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/uClibc_errno.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/uClibc_errno.h new file mode 100644 index 00000000..9c156184 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/uClibc_errno.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ +#ifndef _BITS_UCLIBC_ERRNO_H +#define _BITS_UCLIBC_ERRNO_H 1 + +#ifdef IS_IN_rtld +# undef errno +# define errno _dl_errno +extern int _dl_errno; /* attribute_hidden; */ +#elif defined __UCLIBC_HAS_THREADS__ +# include +# if defined USE___THREAD && USE___THREAD +# undef errno +# ifndef NOT_IN_libc +# define errno __libc_errno +# else +# define errno errno +# endif +extern __thread int errno attribute_tls_model_ie; +# endif /* USE___THREAD */ +#endif /* IS_IN_rtld */ + +#define __set_errno(val) (errno = (val)) + +#ifndef __ASSEMBLER__ +extern int *__errno_location (void) __THROW __attribute__ ((__const__)) +# ifdef IS_IN_rtld + attribute_hidden +# endif +; +# if defined __UCLIBC_HAS_THREADS__ +# include +# if defined USE___THREAD && USE___THREAD +libc_hidden_proto(__errno_location) +# endif +# endif + +#endif /* !__ASSEMBLER__ */ + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/uClibc_fpmax.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/uClibc_fpmax.h new file mode 100644 index 00000000..e1721bf4 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/uClibc_fpmax.h @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2003-2006 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ +/* Define a maximal floating point type, and the associated constants + * that are defined for the floating point types in float.h. + * + * This is to support archs that are missing long double, or even double. + */ + +#ifndef _UCLIBC_FPMAX_H +#define _UCLIBC_FPMAX_H + +#ifndef _ISOC99_SOURCE +#define _ISOC99_SOURCE 1 +#endif + +#include +#include + +#ifdef __UCLIBC_HAS_FLOATS__ + +#if defined(LDBL_MANT_DIG) + +typedef long double __fpmax_t; +#define FPMAX_TYPE 3 + +#define FPMAX_MANT_DIG LDBL_MANT_DIG +#define FPMAX_DIG LDBL_DIG +#define FPMAX_EPSILON LDBL_EPSILON +#define FPMAX_MIN_EXP LDBL_MIN_EXP +#define FPMAX_MIN LDBL_MIN +#define FPMAX_MIN_10_EXP LDBL_MIN_10_EXP +#define FPMAX_MAX_EXP LDBL_MAX_EXP +#define FPMAX_MAX LDBL_MAX +#define FPMAX_MAX_10_EXP LDBL_MAX_10_EXP + +#elif defined(DBL_MANT_DIG) + +typedef double __fpmax_t; +#define FPMAX_TYPE 2 + +#define FPMAX_MANT_DIG DBL_MANT_DIG +#define FPMAX_DIG DBL_DIG +#define FPMAX_EPSILON DBL_EPSILON +#define FPMAX_MIN_EXP DBL_MIN_EXP +#define FPMAX_MIN DBL_MIN +#define FPMAX_MIN_10_EXP DBL_MIN_10_EXP +#define FPMAX_MAX_EXP DBL_MAX_EXP +#define FPMAX_MAX DBL_MAX +#define FPMAX_MAX_10_EXP DBL_MAX_10_EXP + +#elif defined(FLT_MANT_DIG) + +typedef float __fpmax_t; +#define FPMAX_TYPE 1 + +#define FPMAX_MANT_DIG FLT_MANT_DIG +#define FPMAX_DIG FLT_DIG +#define FPMAX_EPSILON FLT_EPSILON +#define FPMAX_MIN_EXP FLT_MIN_EXP +#define FPMAX_MIN FLT_MIN +#define FPMAX_MIN_10_EXP FLT_MIN_10_EXP +#define FPMAX_MAX_EXP FLT_MAX_EXP +#define FPMAX_MAX FLT_MAX +#define FPMAX_MAX_10_EXP FLT_MAX_10_EXP + +#else +#error unable to determine appropriate type for __fpmax_t! +#endif + +#ifndef DECIMAL_DIG + +#ifdef L___strtofpmax +/* Emit warning only once. */ +#warning DECIMAL_DIG is not defined! If you are using gcc, it may not be defining __STDC_VERSION__ as it should. +#endif +#if !defined(FLT_RADIX) || (FLT_RADIX != 2) +#error unable to compensate for missing DECIMAL_DIG! +#endif + +/* ceil (1 + #mantissa * log10 (FLT_RADIX)) */ +#define DECIMAL_DIG (1 + (((FPMAX_MANT_DIG * 100) + 331) / 332)) + +#endif /* DECIMAL_DIG */ + +#if defined _LIBC && defined IS_IN_libc +extern __fpmax_t __strtofpmax(const char *str, char **endptr, int exp_adjust) attribute_hidden; + +#ifdef __UCLIBC_HAS_XLOCALE__ +extern __fpmax_t __strtofpmax_l(const char *str, char **endptr, int exp_adjust, + __locale_t locale_arg) attribute_hidden; +#endif + +#ifdef __UCLIBC_HAS_WCHAR__ +extern __fpmax_t __wcstofpmax(const wchar_t *wcs, wchar_t **endptr, + int exp_adjust) attribute_hidden; + +#ifdef __UCLIBC_HAS_XLOCALE__ +extern __fpmax_t __wcstofpmax_l(const wchar_t *wcs, wchar_t **endptr, + int exp_adjust, __locale_t locale_arg) attribute_hidden; +#endif +#endif /* __UCLIBC_HAS_WCHAR__ */ +#endif /* _LIBC */ + +/* The following checks in an __fpmax_t is either 0 or +/- infinity. + * + * WARNING!!! WARNING!!! WARNING!!! WARNING!!! WARNING!!! WARNING!!! + * + * This only works if __fpmax_t is the actual maximal floating point type used + * in intermediate calculations. Otherwise, excess precision in the + * intermediate values can cause the test to fail. + * + * WARNING!!! WARNING!!! WARNING!!! WARNING!!! WARNING!!! WARNING!!! + */ + +#define __FPMAX_ZERO_OR_INF_CHECK(x) ((x) == ((x)/4) ) + +#endif /* __UCLIBC_HAS_FLOATS__ */ + +#endif /* _UCLIBC_FPMAX_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/uClibc_local_lim.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/uClibc_local_lim.h new file mode 100644 index 00000000..abfc86de --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/uClibc_local_lim.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ +/* + * Never include this file directly; use instead. + */ + +#ifndef _BITS_UCLIBC_LOCAL_LIM_H +#define _BITS_UCLIBC_LOCAL_LIM_H 1 + +/* This file works correctly only if local_lim.h is the NPTL version */ +#if !defined PTHREAD_KEYS_MAX || defined TIMER_MAX +# error local_lim.h was incorrectly updated, use the NPTL version from glibc +#endif + +/* This should really be moved to thread specific directories */ +#if defined __UCLIBC_HAS_THREADS__ && !defined __UCLIBC_HAS_THREADS_NATIVE__ +# define PTHREAD_THREADS_MAX 1024 +# define TIMER_MAX 256 +#endif + +#ifndef __UCLIBC_HAS_THREADS__ +# undef _POSIX_THREAD_KEYS_MAX +# undef PTHREAD_KEYS_MAX +# undef _POSIX_THREAD_DESTRUCTOR_ITERATIONS +# undef PTHREAD_DESTRUCTOR_ITERATIONS +# undef PTHREAD_STACK_MIN +# undef DELAYTIMER_MAX +#endif + +#endif /* bits/uClibc_local_lim.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/uClibc_locale.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/uClibc_locale.h new file mode 100644 index 00000000..9790da29 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/uClibc_locale.h @@ -0,0 +1,374 @@ +/* Copyright (C) 2002, 2003 Manuel Novoa III + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * The GNU C Library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the GNU C Library; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 USA. + */ + +/* ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION! + * + * Besides uClibc, I'm using this code in my libc for elks, which is + * a 16-bit environment with a fairly limited compiler. It would make + * things much easier for me if this file isn't modified unnecessarily. + * In particular, please put any new or replacement functions somewhere + * else, and modify the makefile to use your version instead. + * Thanks. Manuel + * + * ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION! */ + +#ifndef _UCLIBC_LOCALE_H +#define _UCLIBC_LOCALE_H + +/**********************************************************************/ +/* uClibc compatibilty stuff */ + +#ifdef __UCLIBC_HAS_LOCALE__ + +# undef __LOCALE_C_ONLY + +#else + +# define __LOCALE_C_ONLY + +# ifdef _LIBC +# define __XL_NPP(N) N +# define __LOCALE_PARAM +# define __LOCALE_ARG +# endif + +#endif + +/**********************************************************************/ + +#define __NL_ITEM_CATEGORY_SHIFT 8 +#define __NL_ITEM_INDEX_MASK 0xff + +/* TODO: Make sure these agree with the locale mmap file gererator! */ + +#define __LC_CTYPE 0 +#define __LC_NUMERIC 1 +#define __LC_MONETARY 2 +#define __LC_TIME 3 +#define __LC_COLLATE 4 +#define __LC_MESSAGES 5 +#define __LC_ALL 6 + +/**********************************************************************/ +#ifndef __LOCALE_C_ONLY + +enum { + __ctype_encoding_7_bit, /* C/POSIX */ + __ctype_encoding_utf8, /* UTF-8 */ + __ctype_encoding_8_bit /* for 8-bit codeset locales */ +}; + +#define LOCALE_STRING_SIZE (2 * __LC_ALL + 2) + + /* + * '#' + 2_per_category + '\0' + * {locale row # : 0 = C|POSIX} + 0x8001 + * encoded in two chars as (((N+1) >> 8) | 0x80) and ((N+1) & 0xff) + * so decode is ((((uint16_t)(*s & 0x7f)) << 8) + s[1]) - 1 + * + * Note: 0s are not used as they are nul-terminators for strings. + * Note: 0xff, 0xff is the encoding for a non-selected locale. + * (see setlocale() below). + * In particular, C/POSIX locale is '#' + "\x80\x01"}*LC_ALL + nul. + */ + +struct __uclibc_locale_struct; +typedef struct __uclibc_locale_struct *__locale_t; + +#ifdef _LIBC + +/* extern void _locale_set(const unsigned char *p); */ +/* extern void _locale_init(void); */ + +#include +#include +#include +#ifndef __UCLIBC_GEN_LOCALE +# include +#endif + +#ifndef __UCLIBC_GEN_LOCALE /* && (defined IS_IN_libc || defined NOT_IN_libc) */ +typedef struct { + uint16_t num_weights; + uint16_t num_starters; + uint16_t ii_shift; + uint16_t ti_shift; + uint16_t ii_len; + uint16_t ti_len; + uint16_t max_weight; + uint16_t num_col_base; + uint16_t max_col_index; + uint16_t undefined_idx; + uint16_t range_low; + uint16_t range_count; + uint16_t range_base_weight; + uint16_t range_rule_offset; /* change name to index? */ + + uint16_t ii_mask; + uint16_t ti_mask; + + const uint16_t *index2weight_tbl; + const uint16_t *index2ruleidx_tbl; + const uint16_t *multistart_tbl; + /* uint16_t wcs2colidt_offset_low; */ + /* uint16_t wcs2colidt_offset_hi; */ + const uint16_t *wcs2colidt_tbl; + + /* uint16_t undefined_idx; */ + const uint16_t *overrides_tbl; + /* uint16_t *multistart_tbl; */ + + const uint16_t *weightstr; + const uint16_t *ruletable; + + + uint16_t *index2weight; + uint16_t *index2ruleidx; + + uint16_t MAX_WEIGHTS; +} __collate_t; + +/* static unsigned char cur_locale[LOCALE_STRING_SIZE]; */ + +struct __uclibc_locale_struct { +#ifdef __UCLIBC_HAS_XLOCALE__ + const __ctype_mask_t *__ctype_b; + const __ctype_touplow_t *__ctype_tolower; + const __ctype_touplow_t *__ctype_toupper; +#endif + + /* For now, just embed this in the structure. */ + __ctype_mask_t __ctype_b_data[256 + __UCLIBC_CTYPE_B_TBL_OFFSET]; + __ctype_touplow_t __ctype_tolower_data[256 + __UCLIBC_CTYPE_TO_TBL_OFFSET]; + __ctype_touplow_t __ctype_toupper_data[256 + __UCLIBC_CTYPE_TO_TBL_OFFSET]; + +/* int tables_loaded; */ +/* unsigned char lctypes[LOCALE_STRING_SIZE]; */ + unsigned char cur_locale[LOCALE_STRING_SIZE]; + + /* NL_LANGINFO stuff. BEWARE ORDERING!!! must agree with NL_* constants! */ + /* Also, numeric must be followed by monetary and the items must be in + * the "struct lconv" order. */ + + uint16_t category_offsets[__LC_ALL]; /* TODO -- fix? */ + unsigned char category_item_count[__LC_ALL]; /* TODO - fix */ + + /* ctype */ + unsigned char encoding; /* C/POSIX, 8-bit, UTF-8 */ + unsigned char mb_cur_max; /* determined by encoding _AND_ translit!!! */ + const unsigned char outdigit_length[10]; + +#ifdef __CTYPE_HAS_8_BIT_LOCALES + const unsigned char *idx8ctype; + const unsigned char *tbl8ctype; + const unsigned char *idx8uplow; + const unsigned char *tbl8uplow; +# ifdef __UCLIBC_HAS_WCHAR__ + const unsigned char *idx8c2wc; + const uint16_t *tbl8c2wc; /* char > 0x7f to wide char */ + const unsigned char *idx8wc2c; + const unsigned char *tbl8wc2c; + /* translit */ +# endif +#endif /* __CTYPE_HAS_8_BIT_LOCALES */ +#ifdef __UCLIBC_HAS_WCHAR__ + + const uint16_t *code2flag; + + const unsigned char *tblwctype; + const unsigned char *tblwuplow; +/* const unsigned char *tblwcomb; */ + const int16_t *tblwuplow_diff; /* yes... signed */ + /* width?? */ + + wchar_t decimal_point_wc; + wchar_t thousands_sep_wc; + int decimal_point_len; + int thousands_sep_len; + +#endif /* __UCLIBC_HAS_WCHAR__ */ + + /* ctype */ + const char *outdigit0_mb; + const char *outdigit1_mb; + const char *outdigit2_mb; + const char *outdigit3_mb; + const char *outdigit4_mb; + const char *outdigit5_mb; + const char *outdigit6_mb; + const char *outdigit7_mb; + const char *outdigit8_mb; + const char *outdigit9_mb; + const char *codeset; /* MUST BE LAST!!! */ + + /* numeric */ + const char *decimal_point; + const char *thousands_sep; + const char *grouping; + + /* monetary */ + const char *int_curr_symbol; + const char *currency_symbol; + const char *mon_decimal_point; + const char *mon_thousands_sep; + const char *mon_grouping; + const char *positive_sign; + const char *negative_sign; + const char *int_frac_digits; + const char *frac_digits; + const char *p_cs_precedes; + const char *p_sep_by_space; + const char *n_cs_precedes; + const char *n_sep_by_space; + const char *p_sign_posn; + const char *n_sign_posn; + const char *int_p_cs_precedes; + const char *int_p_sep_by_space; + const char *int_n_cs_precedes; + const char *int_n_sep_by_space; + const char *int_p_sign_posn; + const char *int_n_sign_posn; + + const char *crncystr; /* not returned by localeconv */ + + /* time */ + const char *abday_1; + const char *abday_2; + const char *abday_3; + const char *abday_4; + const char *abday_5; + const char *abday_6; + const char *abday_7; + + const char *day_1; + const char *day_2; + const char *day_3; + const char *day_4; + const char *day_5; + const char *day_6; + const char *day_7; + + const char *abmon_1; + const char *abmon_2; + const char *abmon_3; + const char *abmon_4; + const char *abmon_5; + const char *abmon_6; + const char *abmon_7; + const char *abmon_8; + const char *abmon_9; + const char *abmon_10; + const char *abmon_11; + const char *abmon_12; + + const char *mon_1; + const char *mon_2; + const char *mon_3; + const char *mon_4; + const char *mon_5; + const char *mon_6; + const char *mon_7; + const char *mon_8; + const char *mon_9; + const char *mon_10; + const char *mon_11; + const char *mon_12; + + const char *am_str; + const char *pm_str; + + const char *d_t_fmt; + const char *d_fmt; + const char *t_fmt; + const char *t_fmt_ampm; + const char *era; + + const char *era_year; /* non SUSv3 */ + const char *era_d_fmt; + const char *alt_digits; + const char *era_d_t_fmt; + const char *era_t_fmt; + + /* messages */ + const char *yesexpr; + const char *noexpr; + const char *yesstr; + const char *nostr; + + /* collate is at the end */ + __collate_t collate; +}; + +extern struct __uclibc_locale_struct __global_locale_data; +extern struct __uclibc_locale_struct *__global_locale; +#endif /* !__UCLIBC_GEN_LOCALE */ + +#if defined IS_IN_libc || defined NOT_IN_libc +/* If you plan to remove xxx_IN_libc guards, + * remove attribute_hidden, it won't work. + */ +extern int __locale_mbrtowc_l(wchar_t *__restrict dst, + const char *__restrict src, + __locale_t loc) attribute_hidden; +#endif + +#ifdef L_setlocale +/* so we only get the warning once... */ +#warning need thread version of CUR_LOCALE! +#endif + +/**********************************************************************/ +#ifdef __UCLIBC_HAS_XLOCALE__ + +extern __locale_t __curlocale_var; +# ifdef __UCLIBC_HAS_THREADS__ +extern __locale_t __curlocale(void) __THROW __attribute__ ((__const__)); +extern __locale_t __curlocale_set(__locale_t newloc); +# define __UCLIBC_CURLOCALE (__curlocale()) +# else +# define __UCLIBC_CURLOCALE (__curlocale_var) +# endif + +#elif defined(__UCLIBC_HAS_LOCALE__) + +# define __UCLIBC_CURLOCALE (__global_locale) + +#endif +/**********************************************************************/ +#if defined(__UCLIBC_HAS_XLOCALE__) && defined(__UCLIBC_DO_XLOCALE) + +# define __XL_NPP(N) N ## _l +# define __LOCALE_PARAM , __locale_t locale_arg +# define __LOCALE_ARG , locale_arg +# define __LOCALE_PTR locale_arg + +#else + +# define __XL_NPP(N) N +# define __LOCALE_PARAM +# define __LOCALE_ARG +# define __LOCALE_PTR __UCLIBC_CURLOCALE + +#endif +/**********************************************************************/ + +#endif /* _LIBC */ + +#endif /* !defined(__LOCALE_C_ONLY) */ + +#endif /* _UCLIBC_LOCALE_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/uClibc_mutex.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/uClibc_mutex.h new file mode 100644 index 00000000..ef8016d6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/uClibc_mutex.h @@ -0,0 +1,157 @@ +/* Copyright (C) 2006 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#ifndef _UCLIBC_MUTEX_H +#define _UCLIBC_MUTEX_H + +#include + +#ifdef __UCLIBC_HAS_THREADS__ + +#include +#include + +#define __UCLIBC_MUTEX_TYPE pthread_mutex_t + +#define __UCLIBC_MUTEX(M) pthread_mutex_t M +#define __UCLIBC_MUTEX_INIT(M,I) pthread_mutex_t M = I +#define __UCLIBC_MUTEX_STATIC(M,I) static pthread_mutex_t M = I +#define __UCLIBC_MUTEX_EXTERN(M) extern pthread_mutex_t M + +#define __UCLIBC_MUTEX_INIT_VAR(M) \ + ((M) = (pthread_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP) + +#define __UCLIBC_MUTEX_LOCK_CANCEL_UNSAFE(M) \ + __pthread_mutex_lock(&(M)) + +#define __UCLIBC_MUTEX_UNLOCK_CANCEL_UNSAFE(M) \ + __pthread_mutex_unlock(&(M)) + +#define __UCLIBC_MUTEX_TRYLOCK_CANCEL_UNSAFE(M) \ + __pthread_mutex_trylock(&(M)) + +#define __UCLIBC_MUTEX_CONDITIONAL_LOCK(M,C) \ + do { \ + struct _pthread_cleanup_buffer __infunc_pthread_cleanup_buffer; \ + int __infunc_need_locking = (C); \ + if (__infunc_need_locking) { \ + _pthread_cleanup_push_defer(&__infunc_pthread_cleanup_buffer, \ + (void (*) (void *))__pthread_mutex_unlock, \ + &(M)); \ + __pthread_mutex_lock(&(M)); \ + } \ + ((void)0) + +#define __UCLIBC_MUTEX_CONDITIONAL_UNLOCK(M,C) \ + if (__infunc_need_locking) { \ + _pthread_cleanup_pop_restore(&__infunc_pthread_cleanup_buffer,1); \ + } \ + } while (0) + +#define __UCLIBC_MUTEX_AUTO_LOCK_VAR(A) int A + +#define __UCLIBC_MUTEX_AUTO_LOCK(M,A,V) \ + __UCLIBC_MUTEX_CONDITIONAL_LOCK(M,((A=(V)) == 0)) + +#define __UCLIBC_MUTEX_AUTO_UNLOCK(M,A) \ + __UCLIBC_MUTEX_CONDITIONAL_UNLOCK(M,(A == 0)) + +#define __UCLIBC_MUTEX_LOCK(M) \ + __UCLIBC_MUTEX_CONDITIONAL_LOCK(M, 1) + +#define __UCLIBC_MUTEX_UNLOCK(M) \ + __UCLIBC_MUTEX_CONDITIONAL_UNLOCK(M, 1) + +#ifdef __USE_STDIO_FUTEXES__ + +#include + +#define __UCLIBC_IO_MUTEX(M) _IO_lock_t M +#define __UCLIBC_IO_MUTEX_LOCK(M) _IO_lock_lock(M) +#define __UCLIBC_IO_MUTEX_UNLOCK(M) _IO_lock_unlock(M) +#define __UCLIBC_IO_MUTEX_TRYLOCK(M) _IO_lock_trylock(M) +#define __UCLIBC_IO_MUTEX_INIT(M) _IO_lock_t M = _IO_lock_initializer +#define __UCLIBC_IO_MUTEX_EXTERN(M) extern _IO_lock_t M + +#define __UCLIBC_IO_MUTEX_CONDITIONAL_LOCK(M,C) \ + if (C) { \ + _IO_lock_lock(M); \ + } + +#define __UCLIBC_IO_MUTEX_CONDITIONAL_UNLOCK(M,C) \ + if (C) { \ + _IO_lock_unlock(M); \ + } + +#define __UCLIBC_IO_MUTEX_AUTO_LOCK(M,A,V) \ + __UCLIBC_IO_MUTEX_CONDITIONAL_LOCK(M,((A=(V))) == 0) + +#define __UCLIBC_IO_MUTEX_AUTO_UNLOCK(M,A) \ + __UCLIBC_IO_MUTEX_CONDITIONAL_UNLOCK(M,((A) == 0)) + +#define __UCLIBC_IO_MUTEX_LOCK_CANCEL_UNSAFE(M) _IO_lock_lock(M) +#define __UCLIBC_IO_MUTEX_UNLOCK_CANCEL_UNSAFE(M) _IO_lock_unlock(M) + +#else /* of __USE_STDIO_FUTEXES__ */ + +#define __UCLIBC_IO_MUTEX(M) __UCLIBC_MUTEX(M) +#define __UCLIBC_IO_MUTEX_LOCK(M) __UCLIBC_MUTEX_CONDITIONAL_LOCK(M, 1) +#define __UCLIBC_IO_MUTEX_UNLOCK(M) __UCLIBC_MUTEX_CONDITIONAL_UNLOCK(M, 1) +#define __UCLIBC_IO_MUTEX_TRYLOCK(M) __UCLIBC_MUTEX_TRYLOCK_CANCEL_UNSAFE(M) +#define __UCLIBC_IO_MUTEX_INIT(M) __UCLIBC_MUTEX_INIT(M, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP) +#define __UCLIBC_IO_MUTEX_EXTERN(M) __UCLIBC_MUTEX_EXTERN(M) +#define __UCLIBC_IO_MUTEX_AUTO_LOCK(M,A,V) __UCLIBC_MUTEX_AUTO_LOCK(M,A,V) +#define __UCLIBC_IO_MUTEX_AUTO_UNLOCK(M,A) __UCLIBC_MUTEX_AUTO_UNLOCK(M,A) +#define __UCLIBC_IO_MUTEX_LOCK_CANCEL_UNSAFE(M) __UCLIBC_MUTEX_LOCK_CANCEL_UNSAFE(M) +#define __UCLIBC_IO_MUTEX_UNLOCK_CANCEL_UNSAFE(M) __UCLIBC_MUTEX_UNLOCK_CANCEL_UNSAFE(M) +#define __UCLIBC_IO_MUTEX_CONDITIONAL_LOCK(M,C) __UCLIBC_MUTEX_CONDITIONAL_LOCK(M, 1) +#define __UCLIBC_IO_MUTEX_CONDITIONAL_UNLOCK(M,C) __UCLIBC_MUTEX_CONDITIONAL_UNLOCK(M, 1) + +#endif /* of __USE_STDIO_FUTEXES__ */ + + +#else /* of __UCLIBC_HAS_THREADS__ */ + +#define __UCLIBC_MUTEX(M) void *__UCLIBC_MUTEX_DUMMY_ ## M +#define __UCLIBC_MUTEX_INIT(M,I) extern void *__UCLIBC_MUTEX_DUMMY_ ## M +#define __UCLIBC_MUTEX_STATIC(M,I) extern void *__UCLIBC_MUTEX_DUMMY_ ## M +#define __UCLIBC_MUTEX_EXTERN(M) extern void *__UCLIBC_MUTEX_DUMMY_ ## M + +#define __UCLIBC_MUTEX_INIT_VAR(M) ((void)0) +#define __UCLIBC_MUTEX_LOCK_CANCEL_UNSAFE(M) ((void)0) +#define __UCLIBC_MUTEX_UNLOCK_CANCEL_UNSAFE(M) ((void)0) +#define __UCLIBC_MUTEX_TRYLOCK_CANCEL_UNSAFE(M) (0) /* Always succeed? */ + +#define __UCLIBC_MUTEX_CONDITIONAL_LOCK(M,C) ((void)0) +#define __UCLIBC_MUTEX_CONDITIONAL_UNLOCK(M,C) ((void)0) + +#define __UCLIBC_MUTEX_AUTO_LOCK_VAR(A) ((void)0) +#define __UCLIBC_MUTEX_AUTO_LOCK(M,A,V) ((void)0) +#define __UCLIBC_MUTEX_AUTO_UNLOCK(M,A) ((void)0) + +#define __UCLIBC_MUTEX_LOCK(M) ((void)0) +#define __UCLIBC_MUTEX_UNLOCK(M) ((void)0) + +#define __UCLIBC_IO_MUTEX(M) __UCLIBC_MUTEX(M) +#define __UCLIBC_IO_MUTEX_LOCK(M) __UCLIBC_MUTEX_CONDITIONAL_LOCK(M, 1) +#define __UCLIBC_IO_MUTEX_UNLOCK(M) __UCLIBC_MUTEX_CONDITIONAL_UNLOCK(M, 1) +#define __UCLIBC_IO_MUTEX_TRYLOCK(M) __UCLIBC_MUTEX_TRYLOCK_CANCEL_UNSAFE(M) +#define __UCLIBC_IO_MUTEX_INIT(M) __UCLIBC_MUTEX_INIT(M, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP) +#define __UCLIBC_IO_MUTEX_EXTERN(M) __UCLIBC_MUTEX_EXTERN(M) +#define __UCLIBC_IO_MUTEX_AUTO_LOCK(M,A,V) __UCLIBC_MUTEX_AUTO_LOCK(M,A,V) +#define __UCLIBC_IO_MUTEX_AUTO_UNLOCK(M,A) __UCLIBC_MUTEX_AUTO_UNLOCK(M,A) +#define __UCLIBC_IO_MUTEX_LOCK_CANCEL_UNSAFE(M) __UCLIBC_MUTEX_LOCK_CANCEL_UNSAFE(M) +#define __UCLIBC_IO_MUTEX_UNLOCK_CANCEL_UNSAFE(M) __UCLIBC_MUTEX_UNLOCK_CANCEL_UNSAFE(M) +#define __UCLIBC_IO_MUTEX_CONDITIONAL_LOCK(M,C) __UCLIBC_MUTEX_CONDITIONAL_LOCK(M, 1) +#define __UCLIBC_IO_MUTEX_CONDITIONAL_UNLOCK(M,C) __UCLIBC_MUTEX_CONDITIONAL_UNLOCK(M, 1) + +#endif /* of __UCLIBC_HAS_THREADS__ */ + +#define __UCLIBC_IO_MUTEX_TRYLOCK_CANCEL_UNSAFE(M) \ + __UCLIBC_IO_MUTEX_TRYLOCK(M) + +#endif /* _UCLIBC_MUTEX_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/uClibc_page.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/uClibc_page.h new file mode 100644 index 00000000..13409453 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/uClibc_page.h @@ -0,0 +1,29 @@ +/* Copyright (C) 2004 Erik Andersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * The GNU C Library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the GNU C Library; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 USA. + */ + +/* Supply an architecture specific value for PAGE_SIZE and friends. */ + +#ifndef _UCLIBC_PAGE_H +#define _UCLIBC_PAGE_H + +/* PAGE_SHIFT determines the page size -- in this case 4096 */ +#define PAGE_SHIFT 12 +#define PAGE_SIZE (1UL << PAGE_SHIFT) +#define PAGE_MASK (~(PAGE_SIZE-1)) + +#endif /* _UCLIBC_PAGE_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/uClibc_pthread.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/uClibc_pthread.h new file mode 100644 index 00000000..f648cbd6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/uClibc_pthread.h @@ -0,0 +1,51 @@ +/* Copyright (C) 2003 Manuel Novoa III + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * The GNU C Library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the GNU C Library; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 USA. + */ + +/* Supply prototypes for the internal thread functions used by the + * uClibc library code. + */ + +#ifndef _UCLIBC_PTHREAD_H +#define _UCLIBC_PTHREAD_H + +#ifndef _PTHREAD_H +# error "Always include rather than " +#endif + +#if defined _LIBC && (defined IS_IN_libc || defined NOT_IN_libc) + +struct _pthread_cleanup_buffer; + +/* Threading functions internal to uClibc. Make these thread functions + * weak so that we can elide them from single-threaded processes. */ +extern int weak_function __pthread_mutex_init (pthread_mutex_t *__mutex, + __const pthread_mutexattr_t *__mutex_attr); +extern int weak_function __pthread_mutex_destroy (pthread_mutex_t *__mutex); +extern int weak_function __pthread_mutex_lock (pthread_mutex_t *__mutex); +extern int weak_function __pthread_mutex_unlock (pthread_mutex_t *__mutex); +extern int weak_function __pthread_mutex_trylock (pthread_mutex_t *__mutex); +extern void weak_function _pthread_cleanup_push_defer ( + struct _pthread_cleanup_buffer *__buffer, + void (*__routine) (void *), void *__arg) /* L4 added: */ __THROW; +extern void weak_function _pthread_cleanup_pop_restore ( + struct _pthread_cleanup_buffer *__buffer, + int __execute) /* L4 added: */ __THROW; + +#endif + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/uClibc_stdio.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/uClibc_stdio.h new file mode 100644 index 00000000..a8cf4eb5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/uClibc_stdio.h @@ -0,0 +1,527 @@ +/* Copyright (C) 2002-2004 Manuel Novoa III + * + * GNU Library General Public License (LGPL) version 2 or later. + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + */ + +#ifndef _STDIO_H +#error Always include rather than +#endif + +/**********************************************************************/ + +#define __STDIO_BUFFERS +/* ANSI/ISO mandate at least 256. */ +#if defined(__UCLIBC_HAS_STDIO_BUFSIZ_NONE__) +/* Fake this because some apps use stdio.h BUFSIZ. */ +#define __STDIO_BUFSIZ 256 +#undef __STDIO_BUFFERS +#elif defined(__UCLIBC_HAS_STDIO_BUFSIZ_256__) +#define __STDIO_BUFSIZ 256 +#elif defined(__UCLIBC_HAS_STDIO_BUFSIZ_512__) +#define __STDIO_BUFSIZ 512 +#elif defined(__UCLIBC_HAS_STDIO_BUFSIZ_1024__) +#define __STDIO_BUFSIZ 1024 +#elif defined(__UCLIBC_HAS_STDIO_BUFSIZ_2048__) +#define __STDIO_BUFSIZ 2048 +#elif defined(__UCLIBC_HAS_STDIO_BUFSIZ_4096__) +#define __STDIO_BUFSIZ 4096 +#elif defined(__UCLIBC_HAS_STDIO_BUFSIZ_8192__) +#define __STDIO_BUFSIZ 8192 +#else +#error config seems to be out of sync regarding bufsiz options +#endif + +#ifdef __UCLIBC_HAS_STDIO_BUFSIZ_NONE__ +#define __STDIO_BUILTIN_BUF_SIZE 0 +#else /* __UCLIBC_HAS_STDIO_BUFSIZ_NONE__ */ +#if defined(__UCLIBC_HAS_STDIO_BUILTIN_BUFFER_NONE__) +#define __STDIO_BUILTIN_BUF_SIZE 0 +#elif defined(__UCLIBC_HAS_STDIO_BUILTIN_BUFFER_4__) +#define __STDIO_BUILTIN_BUF_SIZE 4 +#elif defined(__UCLIBC_HAS_STDIO_BUILTIN_BUFFER_8__) +#define __STDIO_BUILTIN_BUF_SIZE 8 +#else +#error config seems to be out of sync regarding builtin buffer size +#endif +#endif + +#if defined(__STDIO_BUFFERS) || defined(__UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__) || defined(__UCLIBC_HAS_THREADS__) +#define __STDIO_HAS_OPENLIST 1 +#else +#undef __STDIO_HAS_OPENLIST +#endif + +/**********************************************************************/ +/* Make sure defines related to large files are consistent. */ +#ifdef _LIBC + +#ifdef __UCLIBC_HAS_LFS__ +#undef __USE_LARGEFILE +#undef __USE_LARGEFILE64 +#undef __USE_FILE_OFFSET64 +/* If we're actually building uClibc with large file support, only define... */ +#define __USE_LARGEFILE64 1 +#endif /* __UCLIBC_HAS_LFS__ */ + +#else /* not _LIBC */ + +#ifndef __UCLIBC_HAS_LFS__ +#if defined(__LARGEFILE64_SOURCE) || defined(__USE_LARGEFILE64) || defined(__USE_FILE_OFFSET64) +#error Sorry... uClibc was built without large file support! +#endif +#endif /* __UCLIBC_HAS_LFS__ */ + +#endif /* _LIBC */ +/**********************************************************************/ +#ifdef __UCLIBC_HAS_WCHAR__ + +#define __need_wchar_t +#include + +/* Note: we don't really need mbstate for 8-bit locales. We do for UTF-8. + * For now, always use it. */ +#define __STDIO_MBSTATE +#define __need_mbstate_t +#include + +#endif +/**********************************************************************/ +/* Currently unimplemented/untested */ +/* #define __STDIO_FLEXIBLE_SETVBUF */ + +#ifdef __UCLIBC_HAS_STDIO_GETC_MACRO__ +#define __STDIO_GETC_MACRO +#endif + +#ifdef __UCLIBC_HAS_STDIO_PUTC_MACRO__ +#define __STDIO_PUTC_MACRO +#endif + + +/* These are consistency checks on the different options */ + +#ifndef __STDIO_BUFFERS +#undef __STDIO_GETC_MACRO +#undef __STDIO_PUTC_MACRO +#endif + +#ifdef __BCC__ +#undef __UCLIBC_HAS_LFS__ +#endif + +#ifndef __UCLIBC_HAS_LFS__ +#undef __UCLIBC_HAS_FOPEN_LARGEFILE_MODE__ +#endif + +/**********************************************************************/ +#include + +/* user_locking + * 0 : do auto locking/unlocking + * 1 : user does locking/unlocking + * 2 : initial state prior to thread initialization + * with no auto locking/unlocking + * + * When threading is initialized, walk the stdio open stream list + * and do "if (user_locking == 2) user_locking = 0;". + * + * This way, we avoid calling the weak lock/unlock functions. + */ + +#define __STDIO_AUTO_THREADLOCK_VAR \ + __UCLIBC_MUTEX_AUTO_LOCK_VAR(__infunc_user_locking) + +#define __STDIO_AUTO_THREADLOCK(__stream) \ + __UCLIBC_IO_MUTEX_AUTO_LOCK((__stream)->__lock, __infunc_user_locking, \ + (__stream)->__user_locking) + +#define __STDIO_AUTO_THREADUNLOCK(__stream) \ + __UCLIBC_IO_MUTEX_AUTO_UNLOCK((__stream)->__lock, __infunc_user_locking) + +#define __STDIO_ALWAYS_THREADLOCK(__stream) \ + __UCLIBC_IO_MUTEX_LOCK((__stream)->__lock) + +#define __STDIO_ALWAYS_THREADUNLOCK(__stream) \ + __UCLIBC_IO_MUTEX_UNLOCK((__stream)->__lock) + +#define __STDIO_ALWAYS_THREADLOCK_CANCEL_UNSAFE(__stream) \ + __UCLIBC_IO_MUTEX_LOCK_CANCEL_UNSAFE((__stream)->__lock) + +#define __STDIO_ALWAYS_THREADTRYLOCK_CANCEL_UNSAFE(__stream) \ + __UCLIBC_IO_MUTEX_TRYLOCK_CANCEL_UNSAFE((__stream)->__lock) + +#define __STDIO_ALWAYS_THREADUNLOCK_CANCEL_UNSAFE(__stream) \ + __UCLIBC_IO_MUTEX_UNLOCK_CANCEL_UNSAFE((__stream)->__lock) + +#ifdef __UCLIBC_HAS_THREADS__ +#define __STDIO_SET_USER_LOCKING(__stream) ((__stream)->__user_locking = 1) +#else +#define __STDIO_SET_USER_LOCKING(__stream) ((void)0) +#endif + +#ifdef __UCLIBC_HAS_THREADS__ +#ifdef __USE_STDIO_FUTEXES__ +#define STDIO_INIT_MUTEX(M) _IO_lock_init(M) +#else +#define STDIO_INIT_MUTEX(M) __stdio_init_mutex(& M) +#endif +#endif + +/**********************************************************************/ + +#define __STDIO_IOFBF 0 /* Fully buffered. */ +#define __STDIO_IOLBF 1 /* Line buffered. */ +#define __STDIO_IONBF 2 /* No buffering. */ + +typedef struct { + __off_t __pos; +#ifdef __STDIO_MBSTATE + __mbstate_t __mbstate; +#endif +#ifdef __UCLIBC_HAS_WCHAR__ + int __mblen_pending; +#endif +} __STDIO_fpos_t; + +#ifdef __UCLIBC_HAS_LFS__ +typedef struct { + __off64_t __pos; +#ifdef __STDIO_MBSTATE + __mbstate_t __mbstate; +#endif +#ifdef __UCLIBC_HAS_WCHAR__ + int __mblen_pending; +#endif +} __STDIO_fpos64_t; +#endif + +/**********************************************************************/ +#ifdef __UCLIBC_HAS_LFS__ +typedef __off64_t __offmax_t; /* TODO -- rename this? */ +#else +typedef __off_t __offmax_t; /* TODO -- rename this? */ +#endif + +/**********************************************************************/ +#ifdef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ + +typedef __ssize_t __io_read_fn(void *__cookie, char *__buf, size_t __bufsize); +typedef __ssize_t __io_write_fn(void *__cookie, + __const char *__buf, size_t __bufsize); +/* NOTE: GLIBC difference!!! -- fopencookie seek function + * For glibc, the type of pos is always (__off64_t *) but in our case + * it is type (__off_t *) when the lib is built without large file support. + */ +typedef int __io_seek_fn(void *__cookie, __offmax_t *__pos, int __whence); +typedef int __io_close_fn(void *__cookie); + +typedef struct { + __io_read_fn *read; + __io_write_fn *write; + __io_seek_fn *seek; + __io_close_fn *close; +} _IO_cookie_io_functions_t; + +#if defined(_LIBC) || defined(_GNU_SOURCE) + +typedef __io_read_fn cookie_read_function_t; +typedef __io_write_fn cookie_write_function_t; +typedef __io_seek_fn cookie_seek_function_t; +typedef __io_close_fn cookie_close_function_t; + +typedef _IO_cookie_io_functions_t cookie_io_functions_t; + +#endif + +#endif +/**********************************************************************/ + +struct __STDIO_FILE_STRUCT { + unsigned short __modeflags; + /* There could be a hole here, but modeflags is used most.*/ +#ifdef __UCLIBC_HAS_WCHAR__ + unsigned char __ungot_width[2]; /* 0: current (building) char; 1: scanf */ + /* Move the following futher down to avoid problems with getc/putc + * macros breaking shared apps when wchar config support is changed. */ + /* wchar_t ungot[2]; */ +#else /* __UCLIBC_HAS_WCHAR__ */ + unsigned char __ungot[2]; +#endif /* __UCLIBC_HAS_WCHAR__ */ + int __filedes; +#ifdef __STDIO_BUFFERS + unsigned char *__bufstart; /* pointer to buffer */ + unsigned char *__bufend; /* pointer to 1 past end of buffer */ + unsigned char *__bufpos; + unsigned char *__bufread; /* pointer to 1 past last buffered read char */ + +#ifdef __STDIO_GETC_MACRO + unsigned char *__bufgetc_u; /* 1 past last readable by getc_unlocked */ +#endif /* __STDIO_GETC_MACRO */ +#ifdef __STDIO_PUTC_MACRO + unsigned char *__bufputc_u; /* 1 past last writeable by putc_unlocked */ +#endif /* __STDIO_PUTC_MACRO */ + +#endif /* __STDIO_BUFFERS */ + +#ifdef __STDIO_HAS_OPENLIST + struct __STDIO_FILE_STRUCT *__nextopen; +#endif +#ifdef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ + void *__cookie; + _IO_cookie_io_functions_t __gcs; +#endif +#ifdef __UCLIBC_HAS_WCHAR__ + wchar_t __ungot[2]; +#endif +#ifdef __STDIO_MBSTATE + __mbstate_t __state; +#endif +#ifdef __UCLIBC_HAS_XLOCALE__ + void *__unused; /* Placeholder for codeset binding. */ +#endif +#ifdef __UCLIBC_HAS_THREADS__ + int __user_locking; + __UCLIBC_IO_MUTEX(__lock); +#endif +/* Everything after this is unimplemented... and may be trashed. */ +#if __STDIO_BUILTIN_BUF_SIZE > 0 + unsigned char __builtinbuf[__STDIO_BUILTIN_BUF_SIZE]; +#endif /* __STDIO_BUILTIN_BUF_SIZE > 0 */ +}; + + +/***********************************************************************/ +/* Having ungotten characters implies the stream is reading. + * The scheme used here treats the least significant 2 bits of + * the stream's modeflags member as follows: + * 0 0 Not currently reading. + * 0 1 Reading, but no ungetc() or scanf() push back chars. + * 1 0 Reading with one ungetc() char (ungot[1] is 1) + * or one scanf() pushed back char (ungot[1] is 0). + * 1 1 Reading with both an ungetc() char and a scanf() + * pushed back char. Note that this must be the result + * of a scanf() push back (in ungot[0]) _followed_ by + * an ungetc() call (in ungot[1]). + * + * Notes: + * scanf() can NOT use ungetc() to push back characters. + * (See section 7.19.6.2 of the C9X rationale -- WG14/N897.) + */ + +#define __MASK_READING 0x0003U /* (0x0001 | 0x0002) */ +#define __FLAG_READING 0x0001U +#define __FLAG_UNGOT 0x0002U +#define __FLAG_EOF 0x0004U +#define __FLAG_ERROR 0x0008U +#define __FLAG_WRITEONLY 0x0010U +#define __FLAG_READONLY 0x0020U /* (__FLAG_WRITEONLY << 1) */ +#define __FLAG_WRITING 0x0040U +#define __FLAG_NARROW 0x0080U + +#define __FLAG_FBF 0x0000U /* must be 0 */ +#define __FLAG_LBF 0x0100U +#define __FLAG_NBF 0x0200U /* (__FLAG_LBF << 1) */ +#define __MASK_BUFMODE 0x0300U /* (__FLAG_LBF|__FLAG_NBF) */ +#define __FLAG_APPEND 0x0400U /* fixed! == O_APPEND for linux */ +#define __FLAG_WIDE 0x0800U +/* available slot 0x1000U */ +#define __FLAG_FREEFILE 0x2000U +#define __FLAG_FREEBUF 0x4000U +#define __FLAG_LARGEFILE 0x8000U /* fixed! == 0_LARGEFILE for linux */ +#define __FLAG_FAILED_FREOPEN __FLAG_LARGEFILE + +/* Note: In no-buffer mode, it would be possible to pack the necessary + * flags into one byte. Since we wouldn't be buffering and there would + * be no support for wchar, the only flags we would need would be: + * 2 bits : ungot count + * 2 bits : eof + error + * 2 bits : readonly + writeonly + * 1 bit : freefile + * 1 bit : appending + * So, for a very small system (< 128 files) we might have a + * 4-byte FILE struct of: + * unsigned char flags; + * signed char filedes; + * unsigned char ungot[2]; + */ +/********************************************************************** + * PROTOTYPES OF INTERNAL FUNCTIONS + **********************************************************************/ +#if defined _LIBC && (defined IS_IN_libc || defined NOT_IN_libc) + +extern void _stdio_init(void) attribute_hidden; +extern void _stdio_term(void) attribute_hidden; + +#ifdef __STDIO_HAS_OPENLIST + +extern struct __STDIO_FILE_STRUCT *_stdio_openlist; + +#ifdef __UCLIBC_HAS_THREADS__ +__UCLIBC_IO_MUTEX_EXTERN(_stdio_openlist_add_lock); +#ifdef __STDIO_BUFFERS +__UCLIBC_IO_MUTEX_EXTERN(_stdio_openlist_del_lock); +extern volatile int _stdio_openlist_use_count; /* _stdio_openlist_del_lock */ +extern int _stdio_openlist_del_count; /* _stdio_openlist_del_lock */ +#endif +extern int _stdio_user_locking; +extern void __stdio_init_mutex(__UCLIBC_MUTEX_TYPE *m) attribute_hidden; +#endif + +#endif + +#endif +/**********************************************************************/ + +#define __CLEARERR_UNLOCKED(__stream) \ + ((void)((__stream)->__modeflags &= ~(__FLAG_EOF|__FLAG_ERROR))) +#define __FEOF_UNLOCKED(__stream) ((__stream)->__modeflags & __FLAG_EOF) +#define __FERROR_UNLOCKED(__stream) ((__stream)->__modeflags & __FLAG_ERROR) + +#ifdef __UCLIBC_HAS_THREADS__ +# define __CLEARERR(__stream) (clearerr)(__stream) +# define __FERROR(__stream) (ferror)(__stream) +# define __FEOF(__stream) (feof)(__stream) +#else +# define __CLEARERR(__stream) __CLEARERR_UNLOCKED(__stream) +# define __FERROR(__stream) __FERROR_UNLOCKED(__stream) +# define __FEOF(__stream) __FEOF_UNLOCKED(__stream) +#endif + +extern int __fgetc_unlocked(FILE *__stream); +libc_hidden_proto(__fgetc_unlocked) +extern int __fputc_unlocked(int __c, FILE *__stream); +libc_hidden_proto(__fputc_unlocked) + +/* First define the default definitions. + They are overridden below as necessary. */ +#define __FGETC_UNLOCKED(__stream) (__fgetc_unlocked)((__stream)) +#define __FGETC(__stream) (fgetc)((__stream)) +#define __GETC_UNLOCKED_MACRO(__stream) (__fgetc_unlocked)((__stream)) +#define __GETC_UNLOCKED(__stream) (__fgetc_unlocked)((__stream)) +#define __GETC(__stream) (fgetc)((__stream)) + +#define __FPUTC_UNLOCKED(__c, __stream) (__fputc_unlocked)((__c),(__stream)) +#define __FPUTC(__c, __stream) (fputc)((__c),(__stream)) +#define __PUTC_UNLOCKED_MACRO(__c, __stream) (__fputc_unlocked)((__c),(__stream)) +#define __PUTC_UNLOCKED(__c, __stream) (__fputc_unlocked)((__c),(__stream)) +#define __PUTC(__c, __stream) (fputc)((__c),(__stream)) + + +#ifdef __STDIO_GETC_MACRO + +extern FILE *__stdin; /* For getchar() macro. */ + +# undef __GETC_UNLOCKED_MACRO +# define __GETC_UNLOCKED_MACRO(__stream) \ + ( ((__stream)->__bufpos < (__stream)->__bufgetc_u) \ + ? (*(__stream)->__bufpos++) \ + : __fgetc_unlocked(__stream) ) + +# if 0 + /* Classic macro approach. getc{_unlocked} can have side effects. */ +# undef __GETC_UNLOCKED +# define __GETC_UNLOCKED(__stream) __GETC_UNLOCKED_MACRO((__stream)) +# ifndef __UCLIBC_HAS_THREADS__ +# undef __GETC +# define __GETC(__stream) __GETC_UNLOCKED_MACRO((__stream)) +# endif + +# else + /* Using gcc extension for safety and additional inlining. */ +# undef __FGETC_UNLOCKED +# define __FGETC_UNLOCKED(__stream) \ + (__extension__ ({ \ + FILE *__S = (__stream); \ + __GETC_UNLOCKED_MACRO(__S); \ + }) ) + +# undef __GETC_UNLOCKED +# define __GETC_UNLOCKED(__stream) __FGETC_UNLOCKED((__stream)) + +# ifdef __UCLIBC_HAS_THREADS__ +# undef __FGETC +# define __FGETC(__stream) \ + (__extension__ ({ \ + FILE *__S = (__stream); \ + ((__S->__user_locking ) \ + ? __GETC_UNLOCKED_MACRO(__S) \ + : (fgetc)(__S)); \ + }) ) + +# undef __GETC +# define __GETC(__stream) __FGETC((__stream)) + +# else + +# undef __FGETC +# define __FGETC(__stream) __FGETC_UNLOCKED((__stream)) +# undef __GETC +# define __GETC(__stream) __FGETC_UNLOCKED((__stream)) + +# endif +# endif + +#else + +#endif /* __STDIO_GETC_MACRO */ + + +#ifdef __STDIO_PUTC_MACRO + +extern FILE *__stdout; /* For putchar() macro. */ + +# undef __PUTC_UNLOCKED_MACRO +# define __PUTC_UNLOCKED_MACRO(__c, __stream) \ + ( ((__stream)->__bufpos < (__stream)->__bufputc_u) \ + ? (*(__stream)->__bufpos++) = (__c) \ + : __fputc_unlocked((__c),(__stream)) ) + +# if 0 + /* Classic macro approach. putc{_unlocked} can have side effects.*/ +# undef __PUTC_UNLOCKED +# define __PUTC_UNLOCKED(__c, __stream) \ + __PUTC_UNLOCKED_MACRO((__c), (__stream)) +# ifndef __UCLIBC_HAS_THREADS__ +# undef __PUTC +# define __PUTC(__c, __stream) __PUTC_UNLOCKED_MACRO((__c), (__stream)) +# endif + +# else + /* Using gcc extension for safety and additional inlining. */ + +# undef __FPUTC_UNLOCKED +# define __FPUTC_UNLOCKED(__c, __stream) \ + (__extension__ ({ \ + FILE *__S = (__stream); \ + __PUTC_UNLOCKED_MACRO((__c),__S); \ + }) ) + +# undef __PUTC_UNLOCKED +# define __PUTC_UNLOCKED(__c, __stream) __FPUTC_UNLOCKED((__c), (__stream)) + +# ifdef __UCLIBC_HAS_THREADS__ +# undef __FPUTC +# define __FPUTC(__c, __stream) \ + (__extension__ ({ \ + FILE *__S = (__stream); \ + ((__S->__user_locking) \ + ? __PUTC_UNLOCKED_MACRO((__c),__S) \ + : (fputc)((__c),__S)); \ + }) ) + +# undef __PUTC +# define __PUTC(__c, __stream) __FPUTC((__c), (__stream)) + +# else + +# undef __FPUTC +# define __FPUTC(__c, __stream) __FPUTC_UNLOCKED((__c),(__stream)) +# undef __PUTC +# define __PUTC(__c, __stream) __FPUTC_UNLOCKED((__c),(__stream)) + +# endif +# endif + +#endif /* __STDIO_PUTC_MACRO */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/uClibc_touplow.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/uClibc_touplow.h new file mode 100644 index 00000000..a65d6134 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/uClibc_touplow.h @@ -0,0 +1,55 @@ +/* Copyright (C) 2003 Manuel Novoa III + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * The GNU C Library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the GNU C Library; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 USA. + */ + +/* ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION! + * + * Besides uClibc, I'm using this code in my libc for elks, which is + * a 16-bit environment with a fairly limited compiler. It would make + * things much easier for me if this file isn't modified unnecessarily. + * In particular, please put any new or replacement functions somewhere + * else, and modify the makefile to use your version instead. + * Thanks. Manuel + * + * ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION! */ + +#ifndef _UCLIBC_TOUPLOW_H +#define _UCLIBC_TOUPLOW_H + +#include +#include + +/* glibc uses the equivalent of - typedef __int32_t __ctype_touplow_t; */ + +typedef __uint16_t __ctype_mask_t; + +#ifdef __UCLIBC_HAS_CTYPE_SIGNED__ + +typedef __int16_t __ctype_touplow_t; +#define __UCLIBC_CTYPE_B_TBL_OFFSET 128 +#define __UCLIBC_CTYPE_TO_TBL_OFFSET 128 + +#else + +typedef unsigned char __ctype_touplow_t; +#define __UCLIBC_CTYPE_B_TBL_OFFSET 1 +#define __UCLIBC_CTYPE_TO_TBL_OFFSET 0 + +#endif + +#endif /* _UCLIBC_TOUPLOW_H */ + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/uClibc_uintmaxtostr.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/uClibc_uintmaxtostr.h new file mode 100644 index 00000000..92633ffa --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/uClibc_uintmaxtostr.h @@ -0,0 +1,116 @@ +/* Copyright (C) 2003 Manuel Novoa III + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * The GNU C Library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the GNU C Library; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 USA. + */ + +/* ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION! + * + * This code is currently under development. Also, I plan to port + * it to elks which is a 16-bit environment with a fairly limited + * compiler. Therefore, please refrain from modifying this code + * and, instead, pass any bug-fixes, etc. to me. Thanks. Manuel + * + * ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION! */ + +#ifndef _UINTMAXTOSTR_H +#define _UINTMAXTOSTR_H 1 + +#ifdef _FEATURES_H +# ifndef __USE_ISOC99 +# error features was included without defining _ISOC99_SOURCE! +# endif +#else +# ifndef _ISOC99_SOURCE +# define _ISOC99_SOURCE +# endif +#endif + +#include +#include +#include + +#if INTMAX_MAX <= 2147483647L +#define __UIM_BUFLEN 12 /* 10 digits + 1 nul + 1 sign */ +#elif INTMAX_MAX <= 9223372036854775807LL +#define __UIM_BUFLEN 22 /* 20 digits + 1 nul + 1 sign */ +#else +#error unknown number of digits for intmax_t! +#endif + +#ifdef LLONG_MAX /* --------------- */ +#if LLONG_MAX <= 2147483647L +#define __UIM_BUFLEN_LLONG 12 /* 10 digits + 1 nul + 1 sign */ +#elif LLONG_MAX <= 9223372036854775807LL +#define __UIM_BUFLEN_LLONG 22 /* 20 digits + 1 nul + 1 sign */ +#else +#error unknown number of digits for long long! +#endif +#endif /* ULLONG_MAX ----------------------------- */ + +#if LONG_MAX <= 2147483647L +#define __UIM_BUFLEN_LONG 12 /* 10 digits + 1 nul + 1 sign */ +#elif LONG_MAX <= 9223372036854775807LL +#define __UIM_BUFLEN_LONG 22 /* 20 digits + 1 nul + 1 sign */ +#else +#error unknown number of digits for long! +#endif + +#if INT_MAX <= 32767 +#define __UIM_BUFLEN_INT 7 /* 10 digits + 1 nul + 1 sign */ +#elif INT_MAX <= 2147483647L +#define __UIM_BUFLEN_INT 12 /* 10 digits + 1 nul + 1 sign */ +#else +#error unknown number of digits for int! +#endif + +typedef enum { + __UIM_DECIMAL = 0, + __UIM_GROUP = ',', /* Base 10 locale-dependent grouping. */ + __UIM_LOWER = 'a' - 10, + __UIM_UPPER = 'A' - 10, +} __UIM_CASE; + +/* Convert the int val to a string in base abs(base). val is treated as + * an unsigned ??? int type if base > 0, and signed if base < 0. This + * is an internal function with _no_ error checking done unless assert()s + * are enabled. + * + * Note: bufend is a pointer to the END of the buffer passed. + * Call like this: + * char buf[SIZE], *p; + * p = _xltostr(buf + sizeof(buf) - 1, {unsigned int}, 10, __UIM_DECIMAL) + * p = _xltostr(buf + sizeof(buf) - 1, {int}, -10, __UIM_DECIMAL) + * + * WARNING: If base > 10, case _must_be_ either __UIM_LOWER or __UIM_UPPER + * for lower and upper case alphas respectively. + * WARNING: If val is really a signed type, make sure base is negative! + * Otherwise, you could overflow your buffer. + */ +extern char *_uintmaxtostr(char * __restrict bufend, uintmax_t uval, + int base, __UIM_CASE alphacase) attribute_hidden; + +/* TODO -- make this either a (possibly inline) function? */ +#ifndef __BCC__ +#define _int10tostr(bufend, intval) \ + _uintmaxtostr((bufend), (intval), -10, __UIM_DECIMAL) +#else /* bcc doesn't do prototypes, we need to explicitly cast */ +#define _int10tostr(bufend, intval) \ + _uintmaxtostr((bufend), (uintmax_t)(intval), -10, __UIM_DECIMAL) +#endif + +#define __BUFLEN_INT10TOSTR __UIM_BUFLEN_INT + +#endif /* _UINTMAXTOSTR_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/uClibc_uwchar.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/uClibc_uwchar.h new file mode 100644 index 00000000..ba2c42db --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/uClibc_uwchar.h @@ -0,0 +1,57 @@ +/* Copyright (C) 2003 Manuel Novoa III + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * The GNU C Library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the GNU C Library; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 USA. + */ + +/* ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION! + * + * Besides uClibc, I'm using this code in my libc for elks, which is + * a 16-bit environment with a fairly limited compiler. It would make + * things much easier for me if this file isn't modified unnecessarily. + * In particular, please put any new or replacement functions somewhere + * else, and modify the makefile to use your version instead. + * Thanks. Manuel + * + * ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION! */ + + +/* Define an internal unsigned int type __uwchar_t just large enough + * to hold a wchar_t. + */ + +#ifndef _UCLIBC_UWCHAR_H +#define _UCLIBC_UWCHAR_H + +#include +#include + +#if WCHAR_MIN == 0 +typedef wchar_t __uwchar_t; +#elif WCHAR_MAX <= USHRT_MAX +typedef unsigned short __uwchar_t; +#elif WCHAR_MAX <= UINT_MAX +typedef unsigned int __uwchar_t; +#elif WCHAR_MAX <= ULONG_MAX +typedef unsigned long __uwchar_t; +#elif defined(ULLONG_MAX) && (WCHAR_MAX <= ULLONG_MAX) +typedef unsigned long long __uwchar_t; +#elif WCHAR_MAX <= UINTMAX_MAX +typedef uintmax_t __uwchar_t; +#else +#error Can not determine an appropriate type for __uwchar_t! +#endif + +#endif /* _UCLIBC_UWCHAR_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/uClibc_va_copy.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/uClibc_va_copy.h new file mode 100644 index 00000000..98663fc0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/uClibc_va_copy.h @@ -0,0 +1,40 @@ +/* Copyright (C) 2005 Manuel Novoa III + * + * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * The GNU C Library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the GNU C Library; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 USA. + */ + +#ifndef _UCLIBC_VA_COPY_H +#define _UCLIBC_VA_COPY_H 1 + +#include + +/* Deal with pre-C99 compilers. */ +#ifndef va_copy + +#ifdef __va_copy +#define va_copy(A,B) __va_copy(A,B) +#else +#warning Neither va_copy (C99/SUSv3) or __va_copy is defined. Using a simple copy instead. But you should really check that this is appropriate and supply an arch-specific override if necessary. + /* the glibc manual suggests that this will usually suffice when + __va_copy doesn't exist. */ +#define va_copy(A,B) A = B +#endif + +#endif /* va_copy */ + +#endif /* _UCLIBC_VA_COPY_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/uio.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/uio.h new file mode 100644 index 00000000..87f916d7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/uio.h @@ -0,0 +1,51 @@ +/* Copyright (C) 1996, 1997, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#if !defined _SYS_UIO_H && !defined _FCNTL_H +# error "Never include directly; use instead." +#endif + +#ifndef _BITS_UIO_H +#define _BITS_UIO_H 1 + +#include + + +/* We should normally use the Linux kernel header file to define this + type and macros but this calls for trouble because of the header + includes other kernel headers. */ + +/* Size of object which can be written atomically. + + This macro has different values in different kernel versions. The + latest versions of the kernel use 1024 and this is good choice. Since + the C library implementation of readv/writev is able to emulate the + functionality even if the currently running kernel does not support + this large value the readv/writev call will not fail because of this. */ +#define UIO_MAXIOV 1024 +#define UIO_FASTIOV 8 + + +/* Structure for scatter/gather I/O. */ +struct iovec + { + void *iov_base; /* Pointer to data. */ + size_t iov_len; /* Length of data. */ + }; + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/ustat.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/ustat.h new file mode 100644 index 00000000..69c6b722 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/ustat.h @@ -0,0 +1,31 @@ +/* Copyright (C) 1997, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_USTAT_H +# error "Never include directly; use instead." +#endif + +#include + +struct ustat + { + __daddr_t f_tfree; /* Number of free blocks. */ + __ino_t f_tinode; /* Number of free inodes. */ + char f_fname[6]; + char f_fpack[6]; + }; diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/utmp.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/utmp.h new file mode 100644 index 00000000..e855ad73 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/utmp.h @@ -0,0 +1,125 @@ +/* The `struct utmp' type, describing entries in the utmp file. GNU version. + Copyright (C) 1993, 1996, 1997, 1998, 1999, 2002 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _UTMP_H +# error "Never include directly; use instead." +#endif + +#include +#include +#include +#include + + +#define UT_LINESIZE 32 +#define UT_NAMESIZE 32 +#define UT_HOSTSIZE 256 + + +/* The structure describing an entry in the database of + previous logins. */ +struct lastlog + { +#if __WORDSIZE == 64 && defined __WORDSIZE_COMPAT32 + int32_t ll_time; +#else + __time_t ll_time; +#endif + char ll_line[UT_LINESIZE]; + char ll_host[UT_HOSTSIZE]; + }; + + +/* The structure describing the status of a terminated process. This + type is used in `struct utmp' below. */ +struct exit_status + { + short int e_termination; /* Process termination status. */ + short int e_exit; /* Process exit status. */ + }; + + +/* The structure describing an entry in the user accounting database. */ +struct utmp +{ + short int ut_type; /* Type of login. */ + pid_t ut_pid; /* Process ID of login process. */ + char ut_line[UT_LINESIZE]; /* Devicename. */ + char ut_id[4]; /* Inittab ID. */ + char ut_user[UT_NAMESIZE]; /* Username. */ + char ut_host[UT_HOSTSIZE]; /* Hostname for remote login. */ + struct exit_status ut_exit; /* Exit status of a process marked + as DEAD_PROCESS. */ +/* The ut_session and ut_tv fields must be the same size when compiled + 32- and 64-bit. This allows data files and shared memory to be + shared between 32- and 64-bit applications. */ +#if __WORDSIZE == 64 && defined __WORDSIZE_COMPAT32 + int32_t ut_session; /* Session ID, used for windowing. */ + struct + { + int32_t tv_sec; /* Seconds. */ + int32_t tv_usec; /* Microseconds. */ + } ut_tv; /* Time entry was made. */ +#else + long int ut_session; /* Session ID, used for windowing. */ + struct timeval ut_tv; /* Time entry was made. */ +#endif + + int32_t ut_addr_v6[4]; /* Internet address of remote host. */ + char __unused[20]; /* Reserved for future use. */ +}; + +/* Backwards compatibility hacks. */ +#define ut_name ut_user +#ifndef _NO_UT_TIME +/* We have a problem here: `ut_time' is also used otherwise. Define + _NO_UT_TIME if the compiler complains. */ +# define ut_time ut_tv.tv_sec +#endif +#define ut_xtime ut_tv.tv_sec +#define ut_addr ut_addr_v6[0] + + +/* Values for the `ut_type' field of a `struct utmp'. */ +#define EMPTY 0 /* No valid user accounting information. */ + +#define RUN_LVL 1 /* The system's runlevel. */ +#define BOOT_TIME 2 /* Time of system boot. */ +#define NEW_TIME 3 /* Time after system clock changed. */ +#define OLD_TIME 4 /* Time when system clock changed. */ + +#define INIT_PROCESS 5 /* Process spawned by the init process. */ +#define LOGIN_PROCESS 6 /* Session leader of a logged in user. */ +#define USER_PROCESS 7 /* Normal process. */ +#define DEAD_PROCESS 8 /* Terminated process. */ + +#define ACCOUNTING 9 + +/* Old Linux name for the EMPTY type. */ +#define UT_UNKNOWN EMPTY + + +/* Tell the user that we have a modern system with UT_HOST, UT_PID, + UT_TYPE, UT_ID and UT_TV fields. */ +#define _HAVE_UT_TYPE 1 +#define _HAVE_UT_PID 1 +#define _HAVE_UT_ID 1 +#define _HAVE_UT_TV 1 +#define _HAVE_UT_HOST 1 diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/utmpx.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/utmpx.h new file mode 100644 index 00000000..c84cda6f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/utmpx.h @@ -0,0 +1,103 @@ +/* Structures and definitions for the user accounting database. GNU version. + Copyright (C) 1997, 1998, 2000, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _UTMPX_H +# error "Never include directly; use instead." +#endif + +#include +#include +#include + + +#ifdef __USE_GNU +# include +# define _PATH_UTMPX _PATH_UTMP +# define _PATH_WTMPX _PATH_WTMP +#endif + + +#define __UT_LINESIZE 32 +#define __UT_NAMESIZE 32 +#define __UT_HOSTSIZE 256 + + +/* The structure describing the status of a terminated process. This + type is used in `struct utmpx' below. */ +struct __exit_status + { +#ifdef __USE_GNU + short int e_termination; /* Process termination status. */ + short int e_exit; /* Process exit status. */ +#else + short int __e_termination; /* Process termination status. */ + short int __e_exit; /* Process exit status. */ +#endif + }; + + +/* The structure describing an entry in the user accounting database. */ +struct utmpx +{ + short int ut_type; /* Type of login. */ + __pid_t ut_pid; /* Process ID of login process. */ + char ut_line[__UT_LINESIZE]; /* Devicename. */ + char ut_id[4]; /* Inittab ID. */ + char ut_user[__UT_NAMESIZE]; /* Username. */ + char ut_host[__UT_HOSTSIZE]; /* Hostname for remote login. */ + struct __exit_status ut_exit; /* Exit status of a process marked + as DEAD_PROCESS. */ + +/* The fields ut_session and ut_tv must be the same size when compiled + 32- and 64-bit. This allows files and shared memory to be shared + between 32- and 64-bit applications. */ +#if __WORDSIZE == 64 && defined __WORDSIZE_COMPAT32 + __int32_t ut_session; /* Session ID, used for windowing. */ + struct + { + __int32_t tv_sec; /* Seconds. */ + __int32_t tv_usec; /* Microseconds. */ + } ut_tv; /* Time entry was made. */ +#else + long int ut_session; /* Session ID, used for windowing. */ + struct timeval ut_tv; /* Time entry was made. */ +#endif + __int32_t ut_addr_v6[4]; /* Internet address of remote host. */ + char __unused[20]; /* Reserved for future use. */ +}; + + +/* Values for the `ut_type' field of a `struct utmpx'. */ +#define EMPTY 0 /* No valid user accounting information. */ + +#ifdef __USE_GNU +# define RUN_LVL 1 /* The system's runlevel. */ +#endif +#define BOOT_TIME 2 /* Time of system boot. */ +#define NEW_TIME 3 /* Time after system clock changed. */ +#define OLD_TIME 4 /* Time when system clock changed. */ + +#define INIT_PROCESS 5 /* Process spawned by the init process. */ +#define LOGIN_PROCESS 6 /* Session leader of a logged in user. */ +#define USER_PROCESS 7 /* Normal process. */ +#define DEAD_PROCESS 8 /* Terminated process. */ + +#ifdef __USE_GNU +# define ACCOUNTING 9 /* System accounting. */ +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/utsname.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/utsname.h new file mode 100644 index 00000000..35e71e3b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/utsname.h @@ -0,0 +1,29 @@ +/* Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_UTSNAME_H +# error "Never include directly; use instead." +#endif + +/* Length of the entries in `struct utsname' is 65. */ +#define _UTSNAME_LENGTH 65 + +/* Linux provides as additional information in the `struct utsname' + the name of the current domain. Define _UTSNAME_DOMAIN_LENGTH + to a value != 0 to activate this entry. */ +#define _UTSNAME_DOMAIN_LENGTH _UTSNAME_LENGTH diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/waitflags.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/waitflags.h new file mode 100644 index 00000000..464cedb1 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/waitflags.h @@ -0,0 +1,38 @@ +/* Definitions of flag bits for `waitpid' et al. + Copyright (C) 1992,1996,1997,2000,2004,2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#if !defined _SYS_WAIT_H && !defined _STDLIB_H +# error "Never include directly; use instead." +#endif + + +/* Bits in the third argument to `waitpid'. */ +#define WNOHANG 1 /* Don't block waiting. */ +#define WUNTRACED 2 /* Report status of stopped children. */ + +/* Bits in the fourth argument to `waitid'. */ +#define WSTOPPED 2 /* Report stopped child (same as WUNTRACED). */ +#define WEXITED 4 /* Report dead child. */ +#define WCONTINUED 8 /* Report continued child. */ +#define WNOWAIT 0x01000000 /* Don't reap, just poll status. */ + +#define __WNOTHREAD 0x20000000 /* Don't wait on children of other threads + in this group */ +#define __WALL 0x40000000 /* Wait for any child. */ +#define __WCLONE 0x80000000 /* Wait for cloned process. */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/waitstatus.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/waitstatus.h new file mode 100644 index 00000000..699c2249 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/waitstatus.h @@ -0,0 +1,106 @@ +/* Definitions of status bits for `wait' et al. + Copyright (C) 1992,1994,1996,1997,2000,2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#if !defined _SYS_WAIT_H && !defined _STDLIB_H +# error "Never include directly; use instead." +#endif + + +/* Everything extant so far uses these same bits. */ + + +/* If WIFEXITED(STATUS), the low-order 8 bits of the status. */ +#define __WEXITSTATUS(status) (((status) & 0xff00) >> 8) + +/* If WIFSIGNALED(STATUS), the terminating signal. */ +#define __WTERMSIG(status) ((status) & 0x7f) + +/* If WIFSTOPPED(STATUS), the signal that stopped the child. */ +#define __WSTOPSIG(status) __WEXITSTATUS(status) + +/* Nonzero if STATUS indicates normal termination. */ +#define __WIFEXITED(status) (__WTERMSIG(status) == 0) + +/* Nonzero if STATUS indicates termination by a signal. */ +#define __WIFSIGNALED(status) \ + (((signed char) (((status) & 0x7f) + 1) >> 1) > 0) + +/* Nonzero if STATUS indicates the child is stopped. */ +#define __WIFSTOPPED(status) (((status) & 0xff) == 0x7f) + +/* Nonzero if STATUS indicates the child continued after a stop. We only + define this if provides the WCONTINUED flag bit. */ +#ifdef WCONTINUED +# define __WIFCONTINUED(status) ((status) == __W_CONTINUED) +#endif + +/* Nonzero if STATUS indicates the child dumped core. */ +#define __WCOREDUMP(status) ((status) & __WCOREFLAG) + +/* Macros for constructing status values. */ +#define __W_EXITCODE(ret, sig) ((ret) << 8 | (sig)) +#define __W_STOPCODE(sig) ((sig) << 8 | 0x7f) +#define __W_CONTINUED 0xffff +#define __WCOREFLAG 0x80 + + +#ifdef __USE_BSD + +# include + +union wait + { + int w_status; + struct + { +# if __BYTE_ORDER == __LITTLE_ENDIAN + unsigned int __w_termsig:7; /* Terminating signal. */ + unsigned int __w_coredump:1; /* Set if dumped core. */ + unsigned int __w_retcode:8; /* Return code if exited normally. */ + unsigned int:16; +# endif /* Little endian. */ +# if __BYTE_ORDER == __BIG_ENDIAN + unsigned int:16; + unsigned int __w_retcode:8; + unsigned int __w_coredump:1; + unsigned int __w_termsig:7; +# endif /* Big endian. */ + } __wait_terminated; + struct + { +# if __BYTE_ORDER == __LITTLE_ENDIAN + unsigned int __w_stopval:8; /* W_STOPPED if stopped. */ + unsigned int __w_stopsig:8; /* Stopping signal. */ + unsigned int:16; +# endif /* Little endian. */ +# if __BYTE_ORDER == __BIG_ENDIAN + unsigned int:16; + unsigned int __w_stopsig:8; /* Stopping signal. */ + unsigned int __w_stopval:8; /* W_STOPPED if stopped. */ +# endif /* Big endian. */ + } __wait_stopped; + }; + +# define w_termsig __wait_terminated.__w_termsig +# define w_coredump __wait_terminated.__w_coredump +# define w_retcode __wait_terminated.__w_retcode +# define w_stopsig __wait_stopped.__w_stopsig +# define w_stopval __wait_stopped.__w_stopval + +#endif /* Use BSD. */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/wchar.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/wchar.h new file mode 100644 index 00000000..ef1f5636 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/wchar.h @@ -0,0 +1,26 @@ +/* wchar_t type related definitions. + Copyright (C) 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _BITS_WCHAR_H +#define _BITS_WCHAR_H 1 + +#define __WCHAR_MIN (-2147483647 - 1) +#define __WCHAR_MAX (2147483647) + +#endif /* bits/wchar.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/wordsize.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/wordsize.h new file mode 100644 index 00000000..2d8e2b94 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/wordsize.h @@ -0,0 +1,6 @@ +#error "This file must be written based on the data type sizes of the target" + +#if 0 +#define __WORDSIZE 32 +#define __WORDSIZE 64 +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/xopen_lim.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/xopen_lim.h new file mode 100644 index 00000000..c2363ab0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/bits/xopen_lim.h @@ -0,0 +1,150 @@ +/* Copyright (C) 1996, 1997, 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * Never include this file directly; use instead. + */ + +/* Additional definitions from X/Open Portability Guide, Issue 4, Version 2 + System Interfaces and Headers, 4.16 + + Please note only the values which are not greater than the minimum + stated in the standard document are listed. The `sysconf' functions + should be used to obtain the actual value. */ + +#ifndef _XOPEN_LIM_H +#define _XOPEN_LIM_H 1 + +#define __need_IOV_MAX +#include + +/* We do not provide fixed values for + + ARG_MAX Maximum length of argument to the `exec' function + including environment data. + + ATEXIT_MAX Maximum number of functions that may be registered + with `atexit'. + + CHILD_MAX Maximum number of simultaneous processes per real + user ID. + + OPEN_MAX Maximum number of files that one process can have open + at anyone time. + + PAGESIZE + PAGE_SIZE Size of bytes of a page. + + PASS_MAX Maximum number of significant bytes in a password. + + We only provide a fixed limit for + + IOV_MAX Maximum number of `iovec' structures that one process has + available for use with `readv' or writev'. + + if this is indeed fixed by the underlying system. +*/ + + +/* Maximum number of `iovec' structures that one process has available + for use with `readv' or writev'. */ +#define _XOPEN_IOV_MAX _POSIX_UIO_MAXIOV + + +/* Maximum value of `digit' in calls to the `printf' and `scanf' + functions. Posix dictates this should be a minimum of 9 */ +#if !defined(__UCLIBC_PRINTF_SCANF_POSITIONAL_ARGS__) || (__UCLIBC_PRINTF_SCANF_POSITIONAL_ARGS__ <= 1) +#undef NL_ARGMAX +#elif __UCLIBC_PRINTF_SCANF_POSITIONAL_ARGS__ < 9 +#define NL_ARGMAX 9 +#else +#define NL_ARGMAX __UCLIBC_PRINTF_SCANF_POSITIONAL_ARGS__ +#endif + +/* Maximum number of bytes in a `LANG' name. We have no limit. */ +#define NL_LANGMAX _POSIX2_LINE_MAX + +/* Maximum message number. We have no limit. */ +#define NL_MSGMAX INT_MAX + +/* Maximum number of bytes in N-to-1 collation mapping. We have no + limit. */ +#define NL_NMAX INT_MAX + +/* Maximum set number. We have no limit. */ +#define NL_SETMAX INT_MAX + +/* Maximum number of bytes in a message. We have no limit. */ +#define NL_TEXTMAX INT_MAX + +/* Default process priority. */ +#define NZERO 20 + + +/* Number of bits in a word of type `int'. */ +#ifdef INT_MAX +# if INT_MAX == 32767 +# define WORD_BIT 16 +# else +# if INT_MAX == 2147483647 +# define WORD_BIT 32 +# else +/* Safe assumption. */ +# define WORD_BIT 64 +# endif +# endif +#elif defined __INT_MAX__ +# if __INT_MAX__ == 32767 +# define WORD_BIT 16 +# else +# if __INT_MAX__ == 2147483647 +# define WORD_BIT 32 +# else +/* Safe assumption. */ +# define WORD_BIT 64 +# endif +# endif +#else +# define WORD_BIT 32 +#endif + +/* Number of bits in a word of type `long int'. */ +#ifdef LONG_MAX +# if LONG_MAX == 2147483647 +# define LONG_BIT 32 +# else +/* Safe assumption. */ +# define LONG_BIT 64 +# endif +#elif defined __LONG_MAX__ +# if __LONG_MAX__ == 2147483647 +# define LONG_BIT 32 +# else +/* Safe assumption. */ +# define LONG_BIT 64 +# endif +#else +# include +# if __WORDSIZE == 64 +# define LONG_BIT 64 +# else +# define LONG_BIT 32 +# endif +#endif + +#endif /* bits/xopen_lim.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/brk.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/brk.c new file mode 100644 index 00000000..18836ba5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/brk.c @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include + +libc_hidden_proto(brk) + +#define __NR___syscall_brk __NR_brk +static inline _syscall1(void *, __syscall_brk, void *, end) + +/* This must be initialized data because commons can't have aliases. */ +void * __curbrk attribute_hidden = 0; + +int brk(void *addr) +{ + void *newbrk = __syscall_brk(addr); + + __curbrk = newbrk; + + if (newbrk < addr) { + __set_errno (ENOMEM); + return -1; + } + + return 0; +} +libc_hidden_def(brk) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/capget.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/capget.c new file mode 100644 index 00000000..361de845 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/capget.c @@ -0,0 +1,20 @@ +/* vi: set sw=4 ts=4: */ +/* + * capget() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +int capget(void *header, void *data); +#ifdef __NR_capget +_syscall2(int, capget, void *, header, void *, data) +#else +int capget(void *header, void *data) +{ + __set_errno(ENOSYS); + return -1; +} +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/capset.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/capset.c new file mode 100644 index 00000000..0a77e05f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/capset.c @@ -0,0 +1,20 @@ +/* vi: set sw=4 ts=4: */ +/* + * capset() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +int capset(void *header, const void *data); +#ifdef __NR_capset +_syscall2(int, capset, void *, header, const void *, data) +#elif defined __UCLIBC_HAS_STUBS__ +int capset(void *header, const void *data) +{ + __set_errno(ENOSYS); + return -1; +} +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/chdir.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/chdir.c new file mode 100644 index 00000000..e1381019 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/chdir.c @@ -0,0 +1,22 @@ +/* vi: set sw=4 ts=4: */ +/* + * chdir() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include + + +#define __NR___syscall_chdir __NR_chdir +static __inline__ _syscall1(int, __syscall_chdir, const char *, path) +int chdir(const char *path) +{ + return __syscall_chdir(path); +} +libc_hidden_def(chdir) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/chmod.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/chmod.c new file mode 100644 index 00000000..871e0233 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/chmod.c @@ -0,0 +1,21 @@ +/* vi: set sw=4 ts=4: */ +/* + * chmod() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + + +#define __NR___syscall_chmod __NR_chmod +static __inline__ _syscall2(int, __syscall_chmod, const char *, path, __kernel_mode_t, mode) + +int chmod(const char *path, mode_t mode) +{ + return __syscall_chmod(path, mode); +} +libc_hidden_def(chmod) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/chown.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/chown.c new file mode 100644 index 00000000..f2c60e0b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/chown.c @@ -0,0 +1,40 @@ +/* vi: set sw=4 ts=4: */ +/* + * chown() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include + + +#if (__WORDSIZE == 32 && defined(__NR_chown32)) || __WORDSIZE == 64 +# ifdef __NR_chown32 +# undef __NR_chown +# define __NR_chown __NR_chown32 +# endif + +_syscall3(int, chown, const char *, path, uid_t, owner, gid_t, group) + +#else + +# define __NR___syscall_chown __NR_chown +static __inline__ _syscall3(int, __syscall_chown, const char *, path, + __kernel_uid_t, owner, __kernel_gid_t, group) + +int chown(const char *path, uid_t owner, gid_t group) +{ + if (((owner + 1) > (uid_t) ((__kernel_uid_t) - 1U)) + || ((group + 1) > (gid_t) ((__kernel_gid_t) - 1U))) { + __set_errno(EINVAL); + return -1; + } + return (__syscall_chown(path, owner, group)); +} +#endif + +libc_hidden_def(chown) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/chroot.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/chroot.c new file mode 100644 index 00000000..4c085f21 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/chroot.c @@ -0,0 +1,23 @@ +/* vi: set sw=4 ts=4: */ +/* + * chroot() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include + +#if defined __USE_BSD || (defined __USE_XOPEN && !defined __USE_XOPEN2K) +#define __NR___syscall_chroot __NR_chroot +static __inline__ _syscall1(int, __syscall_chroot, const char *, path) + +int chroot(const char *path) +{ + return __syscall_chroot(path); +} +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/clock_getres.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/clock_getres.c new file mode 100644 index 00000000..61413b6c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/clock_getres.c @@ -0,0 +1,43 @@ +/* + * clock_getres() for uClibc + * + * Copyright (C) 2005 by Peter Kjellerstedt + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include + +#ifdef __NR_clock_getres +_syscall2(int, clock_getres, clockid_t, clock_id, struct timespec*, res) +#else + +int clock_getres(clockid_t clock_id, struct timespec* res) +{ + int retval = -1; + + switch (clock_id) { + case CLOCK_REALTIME: + if (res) { + long clk_tck; + + if ((clk_tck = sysconf(_SC_CLK_TCK)) < 0) + clk_tck = 100; + res->tv_sec = 0; + res->tv_nsec = 1000000000 / clk_tck; + } + retval = 0; + break; + + default: + errno = EINVAL; + break; + } + + return retval; +} +#endif +libc_hidden_def(clock_getres) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/clock_gettime.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/clock_gettime.c new file mode 100644 index 00000000..d3755a7a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/clock_gettime.c @@ -0,0 +1,41 @@ +/* + * clock_gettime() for uClibc + * + * Copyright (C) 2003 by Justus Pendleton + * Copyright (C) 2005 by Peter Kjellerstedt + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include + +#ifdef __NR_clock_gettime +_syscall2(int, clock_gettime, clockid_t, clock_id, struct timespec*, tp) +#else + +int clock_gettime(clockid_t clock_id, struct timespec* tp) +{ + struct timeval tv; + int retval = -1; + + switch (clock_id) { + case CLOCK_REALTIME: + /* In Linux, gettimeofday fails only on bad parameter. + * We know that here parameter isn't bad. + */ + gettimeofday(&tv, NULL); + TIMEVAL_TO_TIMESPEC(&tv, tp); + retval = 0; + break; + + default: + errno = EINVAL; + break; + } + + return retval; +} +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/clock_settime.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/clock_settime.c new file mode 100644 index 00000000..0c9c840a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/clock_settime.c @@ -0,0 +1,41 @@ +/* + * clock_settime() for uClibc + * + * Copyright (C) 2005 by Peter Kjellerstedt + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include + +#ifdef __NR_clock_settime +_syscall2(int, clock_settime, clockid_t, clock_id, const struct timespec*, tp) +#else + +int clock_settime(clockid_t clock_id, const struct timespec* tp) +{ + struct timeval tv; + int retval = -1; + + if (tp->tv_nsec < 0 || tp->tv_nsec >= 1000000000) { + errno = EINVAL; + return -1; + } + + switch (clock_id) { + case CLOCK_REALTIME: + TIMESPEC_TO_TIMEVAL(&tv, tp); + retval = settimeofday(&tv, NULL); + break; + + default: + errno = EINVAL; + break; + } + + return retval; +} +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/close.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/close.c new file mode 100644 index 00000000..d6b5fbb2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/close.c @@ -0,0 +1,20 @@ +/* vi: set sw=4 ts=4: */ +/* + * close() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +_syscall1(int, close, int, fd) + +#ifndef __LINUXTHREADS_OLD__ +libc_hidden_def(close) +#else +libc_hidden_weak(close) +strong_alias(close,__libc_close) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/cmsg_nxthdr.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/cmsg_nxthdr.c new file mode 100644 index 00000000..0360b479 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/cmsg_nxthdr.c @@ -0,0 +1,44 @@ +/* Return point to next ancillary data entry in message header. + Copyright (C) 1997, 1998, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define __FORCE_GLIBC +#include +/* Prevent math.h from defining a colliding inline */ +#undef __USE_EXTERN_INLINES +#include + + +struct cmsghdr * +__cmsg_nxthdr (struct msghdr *mhdr, struct cmsghdr *cmsg) +{ + if ((size_t) cmsg->cmsg_len < sizeof (struct cmsghdr)) + /* The kernel header does this so there may be a reason. */ + return NULL; + + cmsg = (struct cmsghdr *) ((unsigned char *) cmsg + + CMSG_ALIGN (cmsg->cmsg_len)); + if ((unsigned char *) (cmsg + 1) > ((unsigned char *) mhdr->msg_control + + mhdr->msg_controllen) + || ((unsigned char *) cmsg + CMSG_ALIGN (cmsg->cmsg_len) + > ((unsigned char *) mhdr->msg_control + mhdr->msg_controllen))) + /* No more entries. */ + return NULL; + return cmsg; +} +libc_hidden_def(__cmsg_nxthdr) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/creat.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/creat.c new file mode 100644 index 00000000..77cf44e6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/creat.c @@ -0,0 +1,15 @@ +/* vi: set sw=4 ts=4: */ +/* + * creat() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +int creat(const char *file, mode_t mode) +{ + return open(file, O_WRONLY | O_CREAT | O_TRUNC, mode); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/creat64.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/creat64.c new file mode 100644 index 00000000..577ad14b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/creat64.c @@ -0,0 +1,30 @@ +/* Copyright (C) 1991, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <_lfs_64.h> + +#ifdef __UCLIBC_HAS_LFS__ +#include +#include + +/* Create FILE with protections MODE. */ +int creat64(const char *file, mode_t mode) +{ + return open64(file, O_WRONLY|O_CREAT|O_TRUNC, mode); +} +#endif /* __UCLIBC_HAS_LFS__ */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/create_module.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/create_module.c new file mode 100644 index 00000000..d8f24466 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/create_module.c @@ -0,0 +1,59 @@ +/* vi: set sw=4 ts=4: */ +/* + * create_module syscall for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include +#include + +#ifdef __NR_create_module + +unsigned long create_module(const char *name, size_t size); + +#if defined(__UCLIBC_BROKEN_CREATE_MODULE__) +# define __NR___create_module __NR_create_module +static __inline__ _syscall2(long, __create_module, const char *, name, size_t, size) +/* By checking the value of errno, we know if we have been fooled + * by the syscall2 macro making a very high address look like a + * negative, so we we fix it up here. */ +unsigned long create_module(const char *name, size_t size) +{ + long ret = __create_module(name, size); + + /* Jump through hoops to fixup error return codes */ + if (ret == -1 && errno > 125) { + ret = -errno; + __set_errno(0); + } + return ret; +} +#elif defined(__UCLIBC_SLIGHTLY_BROKEN_CREATE_MODULE__) +# define __NR___create_module __NR_create_module +/* Alpha doesn't have the same problem, exactly, but a bug in older + kernels fails to clear the error flag. Clear it here explicitly. */ +static __inline__ _syscall4(unsigned long, __create_module, const char *, name, + size_t, size, size_t, dummy, size_t, err) +unsigned long create_module(const char *name, size_t size) +{ + return __create_module(name, size, 0, 0); +} +#else +/* Sparc, MIPS, etc don't mistake return values for errors. */ +_syscall2(unsigned long, create_module, const char *, name, size_t, size) +#endif + +#else /* !__NR_create_module */ +caddr_t create_module(const char *name attribute_unused, size_t size attribute_unused); +caddr_t create_module(const char *name attribute_unused, size_t size attribute_unused) +{ + __set_errno(ENOSYS); + return (caddr_t)-1; +} +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/delete_module.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/delete_module.c new file mode 100644 index 00000000..44f9b30a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/delete_module.c @@ -0,0 +1,19 @@ +/* vi: set sw=4 ts=4: */ +/* + * delete_module() for uClibc + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +int delete_module(const char *name, unsigned int flags); +#ifdef __NR_delete_module +_syscall2(int, delete_module, const char *, name, unsigned int, flags) +#elif defined __UCLIBC_HAS_STUBS__ +int delete_module(const char *name, unsigned int flags) +{ + __set_errno(ENOSYS); + return -1; +} +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/dl-osinfo.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/dl-osinfo.h new file mode 100644 index 00000000..649d203f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/dl-osinfo.h @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2000-2005 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#ifndef _DL_OSINFO_H +#define _DL_OSINFO_H 1 + +#include + +#ifdef __UCLIBC_HAS_SSP__ +# if defined IS_IN_libc || defined IS_IN_rtld + +# if defined __SSP__ || defined __SSP_ALL__ +# error "file must not be compiled with stack protection enabled on it. Use -fno-stack-protector" +# endif + +# include +# include + +# ifdef IS_IN_libc +#include +# define OPEN open +# define READ read +# define CLOSE close +# define GETTIMEOFDAY gettimeofday +# else +# define OPEN _dl_open +# define READ _dl_read +# define CLOSE _dl_close +# define GETTIMEOFDAY _dl_gettimeofday +# endif + +static __always_inline uintptr_t _dl_setup_stack_chk_guard(void) +{ + uintptr_t ret; +# ifndef __SSP_QUICK_CANARY__ + { + int fd = OPEN("/dev/urandom", O_RDONLY, 0); + if (fd >= 0) { + size_t size = READ(fd, &ret, sizeof(ret)); + CLOSE(fd); + if (size == (size_t) sizeof(ret)) + return ret; + } + } +# endif /* !__SSP_QUICK_CANARY__ */ + + /* Start with the "terminator canary". */ + ret = 0xFF0A0D00UL; + + /* Everything failed? Or we are using a weakened model of the + * terminator canary */ + { + struct timeval tv; + if (GETTIMEOFDAY(&tv, NULL) != (-1)) + ret ^= tv.tv_usec ^ tv.tv_sec; + } + return ret; +} +# endif /* libc || rtld */ +#endif /* __UCLIBC_HAS_SSP__ */ + +#endif /* _DL_OSINFO_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/dup.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/dup.c new file mode 100644 index 00000000..d3517667 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/dup.c @@ -0,0 +1,11 @@ +/* vi: set sw=4 ts=4: */ +/* + * dup() for uClibc + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +_syscall1(int, dup, int, oldfd) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/dup2.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/dup2.c new file mode 100644 index 00000000..006f06b6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/dup2.c @@ -0,0 +1,15 @@ +/* vi: set sw=4 ts=4: */ +/* + * dup2() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + + +_syscall2(int, dup2, int, oldfd, int, newfd) +libc_hidden_def(dup2) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/epoll.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/epoll.c new file mode 100644 index 00000000..86272d9a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/epoll.c @@ -0,0 +1,50 @@ +/* vi: set sw=4 ts=4: */ +/* + * epoll_create() / epoll_ctl() / epoll_wait() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +/* + * epoll_create() + */ +#ifdef __NR_epoll_create +_syscall1(int, epoll_create, int, size) +#else +int epoll_create(int size) +{ + __set_errno(ENOSYS); + return -1; +} +#endif + +/* + * epoll_ctl() + */ +#ifdef __NR_epoll_ctl +_syscall4(int,epoll_ctl, int, epfd, int, op, int, fd, struct epoll_event *, event) +#else +int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event) +{ + __set_errno(ENOSYS); + return -1; +} +#endif + +/* + * epoll_wait() + */ +#ifdef __NR_epoll_wait +_syscall4(int, epoll_wait, int, epfd, struct epoll_event *, events, int, maxevents, int, timeout) +#else +int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout) +{ + __set_errno(ENOSYS); + return -1; +} +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/execve.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/execve.c new file mode 100644 index 00000000..e8568df2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/execve.c @@ -0,0 +1,17 @@ +/* vi: set sw=4 ts=4: */ +/* + * execve() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include + +_syscall3(int, execve, const char *, filename, + char *const *, argv, char *const *, envp) +libc_hidden_def(execve) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/faccessat.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/faccessat.c new file mode 100644 index 00000000..09ca129a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/faccessat.c @@ -0,0 +1,16 @@ +/* + * faccessat() for uClibc + * + * Copyright (C) 2009 Analog Devices Inc. + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +#ifdef __NR_faccessat +_syscall4(int, faccessat, int, fd, const char *, file, int, type, int, flag) +#else +/* should add emulation with faccess() and /proc/self/fd/ ... */ +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/fchdir.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/fchdir.c new file mode 100644 index 00000000..4d54ef82 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/fchdir.c @@ -0,0 +1,15 @@ +/* vi: set sw=4 ts=4: */ +/* + * fchdir() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + + +_syscall1(int, fchdir, int, fd) +libc_hidden_def(fchdir) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/fchmod.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/fchmod.c new file mode 100644 index 00000000..791f530b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/fchmod.c @@ -0,0 +1,20 @@ +/* vi: set sw=4 ts=4: */ +/* + * fchmod() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +#define __NR___syscall_fchmod __NR_fchmod +static __inline__ _syscall2(int, __syscall_fchmod, + int, fildes, __kernel_mode_t, mode) + +int fchmod(int fildes, mode_t mode) +{ + return (__syscall_fchmod(fildes, mode)); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/fchmodat.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/fchmodat.c new file mode 100644 index 00000000..7d4dd4e2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/fchmodat.c @@ -0,0 +1,16 @@ +/* + * fchmodat() for uClibc + * + * Copyright (C) 2009 Analog Devices Inc. + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +#ifdef __NR_fchmodat +_syscall4(int, fchmodat, int, fd, const char *, file, mode_t, mode, int, flag) +#else +/* should add emulation with fchmod() and /proc/self/fd/ ... */ +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/fchown.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/fchown.c new file mode 100644 index 00000000..61618dcf --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/fchown.c @@ -0,0 +1,38 @@ +/* vi: set sw=4 ts=4: */ +/* + * fchown() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include + +#if (__WORDSIZE == 32 && defined(__NR_fchown32)) || __WORDSIZE == 64 +# ifdef __NR_fchown32 +# undef __NR_fchown +# define __NR_fchown __NR_fchown32 +# endif + +_syscall3(int, fchown, int, fd, uid_t, owner, gid_t, group) + +#else + +# define __NR___syscall_fchown __NR_fchown +static __inline__ _syscall3(int, __syscall_fchown, int, fd, + __kernel_uid_t, owner, __kernel_gid_t, group) + +int fchown(int fd, uid_t owner, gid_t group) +{ + if (((owner + 1) > (uid_t) ((__kernel_uid_t) - 1U)) + || ((group + 1) > (gid_t) ((__kernel_gid_t) - 1U))) { + __set_errno(EINVAL); + return -1; + } + return (__syscall_fchown(fd, owner, group)); +} + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/fchownat.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/fchownat.c new file mode 100644 index 00000000..707164d1 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/fchownat.c @@ -0,0 +1,16 @@ +/* + * fchownat() for uClibc + * + * Copyright (C) 2009 Analog Devices Inc. + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +#ifdef __NR_fchownat +_syscall5(int, fchownat, int, fd, const char *, file, uid_t, owner, gid_t, group, int, flag) +#else +/* should add emulation with fchown() and /proc/self/fd/ ... */ +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/fdatasync.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/fdatasync.c new file mode 100644 index 00000000..19d37b6e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/fdatasync.c @@ -0,0 +1,50 @@ +/* vi: set sw=4 ts=4: */ +/* + * fdatasync() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +#if !defined __NR_fdatasync && defined __NR_osf_fdatasync +# define __NR_fdatasync __NR_osf_fdatasync +#endif + +#ifdef __NR_fdatasync + +# ifdef __UCLIBC_HAS_THREADS_NATIVE__ +# include +# else +# define SINGLE_THREAD_P 1 +# endif + +#define __NR___syscall_fdatasync __NR_fdatasync + +static __always_inline +_syscall1(int, __syscall_fdatasync, int, fd) + +int fdatasync(int fd) +{ + if (SINGLE_THREAD_P) + return __syscall_fdatasync(fd); + +# ifdef __UCLIBC_HAS_THREADS_NATIVE__ + int oldtype = LIBC_CANCEL_ASYNC (); + int result = __syscall_fdatasync(fd); + LIBC_CANCEL_RESET (oldtype); + return result; +# endif +} + +#elif defined __UCLIBC_HAS_STUBS__ +/* no syscall available, so provide a stub */ +int fdatasync(int fd) +{ + __set_errno(ENOSYS); + return -1; +} +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/flock.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/flock.c new file mode 100644 index 00000000..3dcd1aee --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/flock.c @@ -0,0 +1,19 @@ +/* vi: set sw=4 ts=4: */ +/* + * flock() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +#define __NR___syscall_flock __NR_flock +static __inline__ _syscall2(int, __syscall_flock, int, fd, int, operation) + +int flock(int fd, int operation) +{ + return (__syscall_flock(fd, operation)); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/fork.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/fork.c new file mode 100644 index 00000000..f21ec35b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/fork.c @@ -0,0 +1,35 @@ +/* vi: set sw=4 ts=4: */ +/* + * fork() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +#ifdef __ARCH_USE_MMU__ + +#ifdef __NR_fork +#define __NR___libc_fork __NR_fork +extern __typeof(fork) __libc_fork; +_syscall0(pid_t, __libc_fork) +weak_alias(__libc_fork,fork) +libc_hidden_weak(fork) +#endif + +#elif defined __UCLIBC_HAS_STUBS__ + +extern __typeof(fork) __libc_fork; +pid_t __libc_fork(void) +{ + __set_errno(ENOSYS); + return -1; +} +weak_alias(__libc_fork,fork) +libc_hidden_weak(fork) +link_warning(fork, "fork: this function is not implemented on no-mmu systems") + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/fpu_control.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/fpu_control.h new file mode 100644 index 00000000..de261c2e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/fpu_control.h @@ -0,0 +1,41 @@ +/* FPU control word definitions. Stub version. + Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FPU_CONTROL_H +#define _FPU_CONTROL_H + +#define _FPU_RESERVED 0xffffffff /* These bits are reserved and not changed. */ + +/* The fdlibm code requires no interrupts for exceptions. Don't + change the rounding mode, it would break long double I/O! */ +#define _FPU_DEFAULT 0x00000000 /* Default value. */ + +/* Type of the control word. */ +typedef unsigned int fpu_control_t; + +/* Macros for accessing the hardware control word. */ +#define _FPU_GETCW(cw) 0 +#define _FPU_SETCW(cw) do { } while (0) + +#if 0 +/* Default control word set at startup. */ +extern fpu_control_t __fpu_control; +#endif + +#endif /* _FPU_CONTROL_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/fstat.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/fstat.c new file mode 100644 index 00000000..acc639bc --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/fstat.c @@ -0,0 +1,34 @@ +/* vi: set sw=4 ts=4: */ +/* + * fstat() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include "xstatconv.h" + +#define __NR___syscall_fstat __NR_fstat +static __inline__ _syscall2(int, __syscall_fstat, int, fd, struct kernel_stat *, buf) + +int fstat(int fd, struct stat *buf) +{ + int result; + struct kernel_stat kbuf; + + result = __syscall_fstat(fd, &kbuf); + if (result == 0) { + __xstat_conv(&kbuf, buf); + } + return result; +} +libc_hidden_def(fstat) + +#if ! defined __NR_fstat64 && defined __UCLIBC_HAS_LFS__ +strong_alias_untyped(fstat,fstat64) +libc_hidden_def(fstat64) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/fstat64.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/fstat64.c new file mode 100644 index 00000000..60613433 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/fstat64.c @@ -0,0 +1,34 @@ +/* vi: set sw=4 ts=4: */ +/* + * fstat64() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +#if defined __UCLIBC_HAS_LFS__ && defined __NR_fstat64 +#include +#include +#include "xstatconv.h" + + +#define __NR___syscall_fstat64 __NR_fstat64 +static __inline__ _syscall2(int, __syscall_fstat64, + int, filedes, struct kernel_stat64 *, buf) + +int fstat64(int fd, struct stat64 *buf) +{ + int result; + struct kernel_stat64 kbuf; + + result = __syscall_fstat64(fd, &kbuf); + if (result == 0) { + __xstat64_conv(&kbuf, buf); + } + return result; +} +libc_hidden_def(fstat64) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/fstatat.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/fstatat.c new file mode 100644 index 00000000..33daa7c9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/fstatat.c @@ -0,0 +1,32 @@ +/* + * fstatat() for uClibc + * + * Copyright (C) 2009 Analog Devices Inc. + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include "xstatconv.h" + +/* 64bit ports tend to favor newfstatat() */ +#ifdef __NR_newfstatat +# define __NR_fstatat64 __NR_newfstatat +#endif + +#ifdef __NR_fstatat64 +int fstatat(int fd, const char *file, struct stat *buf, int flag) +{ + int ret; + struct kernel_stat64 kbuf; + + ret = INLINE_SYSCALL(fstatat64, 4, fd, file, &kbuf, flag); + if (ret == 0) + __xstat32_conv(&kbuf, buf); + + return ret; +} +#else +/* should add emulation with fstat() and /proc/self/fd/ ... */ +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/fstatat64.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/fstatat64.c new file mode 100644 index 00000000..95627afa --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/fstatat64.c @@ -0,0 +1,36 @@ +/* + * fstatat64() for uClibc + * + * Copyright (C) 2009 Analog Devices Inc. + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include "xstatconv.h" + +#ifdef __UCLIBC_HAS_LFS__ + +/* 64bit ports tend to favor newfstatat() */ +#ifdef __NR_newfstatat +# define __NR_fstatat64 __NR_newfstatat +#endif + +#ifdef __NR_fstatat64 +int fstatat64(int fd, const char *file, struct stat64 *buf, int flag) +{ + int ret; + struct kernel_stat64 kbuf; + + ret = INLINE_SYSCALL(fstatat64, 4, fd, file, &kbuf, flag); + if (ret == 0) + __xstat64_conv(&kbuf, buf); + + return ret; +} +#else +/* should add emulation with fstat64() and /proc/self/fd/ ... */ +#endif + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/fstatfs.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/fstatfs.c new file mode 100644 index 00000000..fa0024ad --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/fstatfs.c @@ -0,0 +1,31 @@ +/* vi: set sw=4 ts=4: */ +/* + * fstatfs() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +#ifndef __USE_FILE_OFFSET64 +extern int fstatfs (int __fildes, struct statfs *__buf) + __THROW __nonnull ((2)); +#else +# ifdef __REDIRECT_NTH +extern int __REDIRECT_NTH (fstatfs, (int __fildes, struct statfs *__buf), + fstatfs64) __nonnull ((2)); +# else +# define fstatfs fstatfs64 +# endif +#endif + +extern __typeof(fstatfs) __libc_fstatfs attribute_hidden; +#define __NR___libc_fstatfs __NR_fstatfs +_syscall2(int, __libc_fstatfs, int, fd, struct statfs *, buf) + +#if defined __UCLIBC_LINUX_SPECIFIC__ +weak_alias(__libc_fstatfs,fstatfs) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/fsync.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/fsync.c new file mode 100644 index 00000000..711811f2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/fsync.c @@ -0,0 +1,37 @@ +/* vi: set sw=4 ts=4: */ +/* + * fsync() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +#ifdef __UCLIBC_HAS_THREADS_NATIVE__ +#include "sysdep-cancel.h" +#else +#define SINGLE_THREAD_P 1 +#endif + +#define __NR___syscall_fsync __NR_fsync +static inline _syscall1(int, __syscall_fsync, int, fd) + +extern __typeof(fsync) __libc_fsync; + +int __libc_fsync(int fd) +{ + if (SINGLE_THREAD_P) + return __syscall_fsync(fd); + +#ifdef __UCLIBC_HAS_THREADS_NATIVE__ + int oldtype = LIBC_CANCEL_ASYNC (); + int result = __syscall_fsync(fd); + LIBC_CANCEL_RESET (oldtype); + return result; +#endif +} + +weak_alias(__libc_fsync, fsync) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/ftruncate.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/ftruncate.c new file mode 100644 index 00000000..3bdef3f4 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/ftruncate.c @@ -0,0 +1,15 @@ +/* vi: set sw=4 ts=4: */ +/* + * ftruncate() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + + +_syscall2(int, ftruncate, int, fd, __off_t, length) +libc_hidden_def(ftruncate) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/ftruncate64.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/ftruncate64.c new file mode 100644 index 00000000..c5a61600 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/ftruncate64.c @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * ftruncate64 syscall. Copes with 64 bit and 32 bit machines + * and on 32 bit machines this sends things into the kernel as + * two 32-bit arguments (high and low 32 bits of length) that + * are ordered based on endianess. It turns out endian.h has + * just the macro we need to order things, __LONG_LONG_PAIR. + */ + +#include + +#ifdef __UCLIBC_HAS_LFS__ + +# include +# include +# include +# include +# include +# include + + +# ifdef __NR_ftruncate64 + +# if __WORDSIZE == 64 + +/* For a 64 bit machine, life is simple... */ +_syscall2(int, ftruncate64, int, fd, __off64_t, length) + +# elif __WORDSIZE == 32 + +/* The exported ftruncate64 function. */ +int ftruncate64 (int fd, __off64_t length) +{ + uint32_t low = length & 0xffffffff; + uint32_t high = length >> 32; +# if defined(__UCLIBC_TRUNCATE64_HAS_4_ARGS__) + return INLINE_SYSCALL(ftruncate64, + 4, fd, 0, __LONG_LONG_PAIR (high, low)); +# else + return INLINE_SYSCALL(ftruncate64, 3, fd, + __LONG_LONG_PAIR (high, low)); +# endif +} + +# else /* __WORDSIZE */ +# error Your machine is not 64 bit or 32 bit, I am dazed and confused. +# endif /* __WORDSIZE */ + +# else /* __NR_ftruncate64 */ + + +int ftruncate64 (int fd, __off64_t length) +{ + __off_t x = (__off_t) length; + + if (x == length) { + return ftruncate(fd, x); + } + + __set_errno((x < 0) ? EINVAL : EFBIG); + + return -1; +} + +# endif /* __NR_ftruncate64 */ +libc_hidden_def(ftruncate64) + +#endif /* __UCLIBC_HAS_LFS__ */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/futimens.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/futimens.c new file mode 100644 index 00000000..0eaf26a4 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/futimens.c @@ -0,0 +1,29 @@ +/* vi: set sw=4 ts=4: */ +/* + * futimens() implementation for uClibc + * + * Copyright (C) 2009 Bernhard Reutner-Fischer + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#ifdef __NR_utimensat +/* To avoid superfluous warnings about passing NULL to the non-null annotated + * 2nd param "__path" below, we bypass inclusion of sys/stat.h and use + * a non annotated, local decl. + * Note that due to not including the header, we have to alias the call + * manually. + */ +extern int utimensat (int __fd, __const char *__path, + __const struct timespec __times[2], + int __flags) __THROW; +libc_hidden_proto(utimensat) + +int futimens (int __fd, __const struct timespec __times[2]) __THROW; +int futimens (int fd, __const struct timespec ts[2]) +{ + return utimensat(fd, 0, ts, 0); +} +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/futimesat.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/futimesat.c new file mode 100644 index 00000000..bd73eae7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/futimesat.c @@ -0,0 +1,16 @@ +/* + * futimesat() for uClibc + * + * Copyright (C) 2009 Analog Devices Inc. + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +#ifdef __NR_futimesat +_syscall3(int, futimesat, int, fd, const char *, file, const struct timeval *, tvp) +#else +/* should add emulation with futimes() and /proc/self/fd/ ... */ +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/get_kernel_syms.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/get_kernel_syms.c new file mode 100644 index 00000000..d6595eaf --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/get_kernel_syms.c @@ -0,0 +1,22 @@ +/* vi: set sw=4 ts=4: */ +/* + * get_kernel_syms() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +struct kernel_sym; +int get_kernel_syms(struct kernel_sym *table attribute_unused); +#ifdef __NR_get_kernel_syms +_syscall1(int, get_kernel_syms, struct kernel_sym *, table) +#else +int get_kernel_syms(struct kernel_sym *table attribute_unused) +{ + __set_errno(ENOSYS); + return -1; +} +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getcwd.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getcwd.c new file mode 100644 index 00000000..75d7a1c8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getcwd.c @@ -0,0 +1,198 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* These functions find the absolute path to the current working directory. */ + +#include +#include +#include +#include +#include +#include +#include +#include + + + +#ifdef __NR_getcwd + +# define __NR___syscall_getcwd __NR_getcwd +static __always_inline +_syscall2(int, __syscall_getcwd, char *, buf, unsigned long, size) + +#else + +/* If the syscall is not present, we have to walk up the + * directory tree till we hit the root. Now we _could_ + * use /proc/self/cwd if /proc is mounted... That approach + * is left an an exercise for the reader... */ + + +/* Seems a few broken filesystems (like coda) don't like this */ +/* #undef FAST_DIR_SEARCH_POSSIBLE on Linux */ + + +/* Routine to find the step back down */ +static char *search_dir(dev_t this_dev, ino_t this_ino, char *path_buf, int path_size) +{ + DIR *dp; + struct dirent *d; + char *ptr; + int slen; + struct stat st; + +# ifdef FAST_DIR_SEARCH_POSSIBLE + /* The test is for ELKS lib 0.0.9, this should be fixed in the real kernel */ + int slow_search = (sizeof(ino_t) != sizeof(d->d_ino)); +# endif + + if (stat(path_buf, &st) < 0) { + goto oops; + } +# ifdef FAST_DIR_SEARCH_POSSIBLE + if (this_dev != st.st_dev) + slow_search = 1; +# endif + + slen = strlen(path_buf); + ptr = path_buf + slen - 1; + if (*ptr != '/') { + if (slen + 2 > path_size) { + goto oops; + } + strcpy(++ptr, "/"); + slen++; + } + slen++; + + dp = opendir(path_buf); + if (dp == 0) { + goto oops; + } + + while ((d = readdir(dp)) != 0) { +# ifdef FAST_DIR_SEARCH_POSSIBLE + if (slow_search || this_ino == d->d_ino) { +# endif + if (slen + strlen(d->d_name) > path_size) { + goto oops; + } + strcpy(ptr + 1, d->d_name); + if (stat(path_buf, &st) < 0) + continue; + if (st.st_ino == this_ino && st.st_dev == this_dev) { + closedir(dp); + return path_buf; + } +# ifdef FAST_DIR_SEARCH_POSSIBLE + } +# endif + } + + closedir(dp); + return 0; + +oops: + __set_errno(ERANGE); + return 0; +} + +/* Routine to go up tree */ +static char *recurser(char *path_buf, int path_size, dev_t root_dev, ino_t root_ino) +{ + struct stat st; + dev_t this_dev; + ino_t this_ino; + + if (stat(path_buf, &st) < 0) { + if (errno != EFAULT) + goto oops; + return 0; + } + this_dev = st.st_dev; + this_ino = st.st_ino; + if (this_dev == root_dev && this_ino == root_ino) { + if (path_size < 2) { + goto oops; + } + strcpy(path_buf, "/"); + return path_buf; + } + if (strlen(path_buf) + 4 > path_size) { + goto oops; + } + strcat(path_buf, "/.."); + if (recurser(path_buf, path_size, root_dev, root_ino) == 0) + return 0; + + return search_dir(this_dev, this_ino, path_buf, path_size); +oops: + __set_errno(ERANGE); + return 0; +} + +static __always_inline +int __syscall_getcwd(char * buf, unsigned long size) +{ + int len; + char *cwd; + struct stat st; + int olderrno; + + olderrno = errno; + len = -1; + + /* get stat for root to have a valid parameters for the terminating condition */ + if (stat("/", &st) < 0) { + /* root dir not found! */ + return -1; + } + /* start with actual dir */ + if (buf) strncpy(buf, ".", size); + + cwd = recurser(buf, size, st.st_dev, st.st_ino); + if (cwd) { + len = strlen(buf) + 1; + __set_errno(olderrno); + } + return len; +} + +#endif /* __NR_getcwd */ + +char *getcwd(char *buf, size_t size) +{ + int ret; + char *path; + size_t alloc_size = size; + + if (size == 0) { + if (buf != NULL) { + __set_errno(EINVAL); + return NULL; + } + alloc_size = MAX (PATH_MAX, getpagesize ()); + } + path=buf; + if (buf == NULL) { + path = malloc(alloc_size); + if (path == NULL) + return NULL; + } + ret = __syscall_getcwd(path, alloc_size); + if (ret >= 0) + { + if (buf == NULL && size == 0) + buf = realloc(path, ret); + if (buf == NULL) + buf = path; + return buf; + } + if (buf == NULL) + free (path); + return NULL; +} +libc_hidden_def(getcwd) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getdents.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getdents.c new file mode 100644 index 00000000..46f7b8e1 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getdents.c @@ -0,0 +1,174 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if !(defined __UCLIBC_HAS_LFS__ && defined __NR_getdents64 && __WORDSIZE == 64) +/* If the condition above is met, __getdents is defined as an alias + * for __getdents64 (see getdents64.c). Otherwise... + */ + +/* With newer versions of linux, the getdents syscall returns d_type + * information after the name field. + * + * See __ASSUME_GETDENTS32_D_TYPE in glibc's kernel-features.h for specific + * version / arch details. + */ + +#ifndef offsetof +# define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) +#endif + +struct kernel_dirent +{ + long int d_ino; + __kernel_off_t d_off; + unsigned short int d_reclen; + char d_name[256]; +}; + +ssize_t __getdents (int fd, char *buf, size_t nbytes) attribute_hidden; + +#define __NR___syscall_getdents __NR_getdents +static __always_inline _syscall3(int, __syscall_getdents, int, fd, unsigned char *, kdirp, size_t, count) + +#if defined __ASSUME_GETDENTS32_D_TYPE + +ssize_t __getdents (int fd, char *buf, size_t nbytes) +{ + ssize_t retval; + + retval = __syscall_getdents(fd, (unsigned char *)buf, nbytes); + + /* The kernel added the d_type value after the name. Change + this now. */ + if (retval != -1) { + union { + struct kernel_dirent k; + struct dirent u; + } *kbuf = (void *) buf; + + while ((char *) kbuf < buf + retval) { + char d_type = *((char *) kbuf + kbuf->k.d_reclen - 1); + memmove (kbuf->u.d_name, kbuf->k.d_name, + strlen (kbuf->k.d_name) + 1); + kbuf->u.d_type = d_type; + + kbuf = (void *) ((char *) kbuf + kbuf->k.d_reclen); + } + } + + return retval; +} + +#elif ! defined __UCLIBC_HAS_LFS__ || ! defined __NR_getdents64 + +ssize_t __getdents (int fd, char *buf, size_t nbytes) +{ + struct dirent *dp; + off_t last_offset = -1; + ssize_t retval; + size_t red_nbytes; + struct kernel_dirent *skdp, *kdp; + const size_t size_diff = (offsetof (struct dirent, d_name) + - offsetof (struct kernel_dirent, d_name)); + + red_nbytes = MIN (nbytes - ((nbytes / + (offsetof (struct dirent, d_name) + 14)) * size_diff), + nbytes - size_diff); + + dp = (struct dirent *) buf; + skdp = kdp = stack_heap_alloc(red_nbytes); + + retval = __syscall_getdents(fd, (unsigned char *)kdp, red_nbytes); + if (retval == -1) { + stack_heap_free(skdp); + return -1; + } + + while ((char *) kdp < (char *) skdp + retval) { + const size_t alignment = __alignof__ (struct dirent); + /* Since kdp->d_reclen is already aligned for the kernel structure + this may compute a value that is bigger than necessary. */ + size_t new_reclen = ((kdp->d_reclen + size_diff + alignment - 1) + & ~(alignment - 1)); + if ((char *) dp + new_reclen > buf + nbytes) { + /* Our heuristic failed. We read too many entries. Reset + the stream. */ + assert (last_offset != -1); + lseek(fd, last_offset, SEEK_SET); + + if ((char *) dp == buf) { + /* The buffer the user passed in is too small to hold even + one entry. */ + stack_heap_free(skdp); + __set_errno (EINVAL); + return -1; + } + break; + } + + last_offset = kdp->d_off; + dp->d_ino = kdp->d_ino; + dp->d_off = kdp->d_off; + dp->d_reclen = new_reclen; + dp->d_type = DT_UNKNOWN; + memcpy (dp->d_name, kdp->d_name, + kdp->d_reclen - offsetof (struct kernel_dirent, d_name)); + dp = (struct dirent *) ((char *) dp + new_reclen); + kdp = (struct kernel_dirent *) (((char *) kdp) + kdp->d_reclen); + } + stack_heap_free(skdp); + return (char *) dp - buf; +} + +#elif __WORDSIZE == 32 + +extern __typeof(__getdents) __getdents64 attribute_hidden; +ssize_t __getdents (int fd, char *buf, size_t nbytes) +{ + struct dirent *dp; + struct dirent64 *dp64; + ssize_t ret = __getdents64 (fd, buf, nbytes); + + if (ret <= 0) + return ret; + + dp64 = (struct dirent64 *) buf; + buf += ret; + while ((void *) dp64 < (void *) buf) { + dp = (struct dirent *) dp64; + dp->d_ino = dp64->d_ino; + dp->d_off = dp64->d_off; + dp->d_reclen = dp64->d_reclen; + dp->d_type = dp64->d_type; + memmove (dp->d_name, dp64->d_name, dp->d_reclen - offsetof (struct dirent64, d_name)); + memmove (dp64, dp, dp->d_reclen); + dp64 = ((void *) dp64) + dp->d_reclen; + } + + return ret; +} + +#endif + +#if defined __UCLIBC_HAS_LFS__ && ! defined __NR_getdents64 +attribute_hidden strong_alias(__getdents,__getdents64) +#endif + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getdents64.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getdents64.c new file mode 100644 index 00000000..30686f25 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getdents64.c @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined __UCLIBC_HAS_LFS__ && defined __NR_getdents64 + +# ifndef offsetof +# define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) +# endif + +struct kernel_dirent64 +{ + uint64_t d_ino; + int64_t d_off; + unsigned short d_reclen; + unsigned char d_type; + char d_name[256]; +}; + +# define __NR___syscall_getdents64 __NR_getdents64 +static __inline__ _syscall3(int, __syscall_getdents64, int, fd, unsigned char *, dirp, size_t, count) + +ssize_t __getdents64 (int fd, char *buf, size_t nbytes) attribute_hidden; +ssize_t __getdents64 (int fd, char *buf, size_t nbytes) +{ + struct dirent64 *dp; + off64_t last_offset = -1; + ssize_t retval; + size_t red_nbytes; + struct kernel_dirent64 *skdp, *kdp; + const size_t size_diff = (offsetof (struct dirent64, d_name) + - offsetof (struct kernel_dirent64, d_name)); + + red_nbytes = MIN (nbytes - ((nbytes / + (offsetof (struct dirent64, d_name) + 14)) * size_diff), + nbytes - size_diff); + + dp = (struct dirent64 *) buf; + skdp = kdp = stack_heap_alloc(red_nbytes); + + retval = __syscall_getdents64(fd, (unsigned char *)kdp, red_nbytes); + if (retval == -1) { + stack_heap_free(skdp); + return -1; + } + + while ((char *) kdp < (char *) skdp + retval) { + const size_t alignment = __alignof__ (struct dirent64); + /* Since kdp->d_reclen is already aligned for the kernel structure + this may compute a value that is bigger than necessary. */ + size_t new_reclen = ((kdp->d_reclen + size_diff + alignment - 1) + & ~(alignment - 1)); + if ((char *) dp + new_reclen > buf + nbytes) { + /* Our heuristic failed. We read too many entries. Reset + the stream. */ + assert (last_offset != -1); + lseek64(fd, last_offset, SEEK_SET); + + if ((char *) dp == buf) { + /* The buffer the user passed in is too small to hold even + one entry. */ + stack_heap_free(skdp); + __set_errno (EINVAL); + return -1; + } + break; + } + + last_offset = kdp->d_off; + dp->d_ino = kdp->d_ino; + dp->d_off = kdp->d_off; + dp->d_reclen = new_reclen; + dp->d_type = kdp->d_type; + memcpy (dp->d_name, kdp->d_name, + kdp->d_reclen - offsetof (struct kernel_dirent64, d_name)); + dp = (struct dirent64 *) ((char *) dp + new_reclen); + kdp = (struct kernel_dirent64 *) (((char *) kdp) + kdp->d_reclen); + } + stack_heap_free(skdp); + return (char *) dp - buf; +} + +#if __WORDSIZE == 64 +/* since getdents doesnt give us d_type but getdents64 does, try and + * use getdents64 as much as possible */ +attribute_hidden strong_alias(__getdents64,__getdents) +#endif + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getdirname.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getdirname.c new file mode 100644 index 00000000..c02f66bb --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getdirname.c @@ -0,0 +1,58 @@ +/* vi: set sw=4 ts=4: */ +/* Copyright (C) 1992, 1997, 1998, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#ifdef __USE_GNU +#include +#include +#include +#include + +/* Return a malloc'd string containing the current directory name. + If the environment variable `PWD' is set, and its value is correct, + that value is used. */ + +char * +get_current_dir_name (void) +{ + char *pwd; +#ifdef __UCLIBC_HAS_LFS__ + struct stat64 dotstat, pwdstat; +#else + struct stat dotstat, pwdstat; +#endif + + pwd = getenv ("PWD"); + if (pwd != NULL +#ifdef __UCLIBC_HAS_LFS__ + && stat64 (".", &dotstat) == 0 + && stat64 (pwd, &pwdstat) == 0 +#else + && stat (".", &dotstat) == 0 + && stat (pwd, &pwdstat) == 0 +#endif + && pwdstat.st_dev == dotstat.st_dev + && pwdstat.st_ino == dotstat.st_ino) + /* The PWD value is correct. Use it. */ + return strdup (pwd); + + return getcwd ((char *) NULL, 0); +} +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getdomainname.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getdomainname.c new file mode 100644 index 00000000..8590283f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getdomainname.c @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include +#include +#include + +#if defined __USE_BSD || (defined __USE_XOPEN && !defined __USE_UNIX98) + +int +#ifndef __UCLIBC_BSD_SPECIFIC__ +attribute_hidden +#endif +getdomainname(char *name, size_t len) +{ + struct utsname uts; + + if (name == NULL) { + __set_errno(EINVAL); + return -1; + } + + if (uname(&uts) == -1) return -1; + +#ifdef __USE_GNU + if (strlen(uts.domainname)+1 > len) { +#else + if (strlen(uts.__domainname)+1 > len) { +#endif + __set_errno(EINVAL); + return -1; + } +#ifdef __USE_GNU + strcpy(name, uts.domainname); +#else + strcpy(name, uts.__domainname); +#endif + return 0; +} +# ifdef __UCLIBC_BSD_SPECIFIC__ +libc_hidden_def(getdomainname) +# endif +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getdtablesize.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getdtablesize.c new file mode 100644 index 00000000..7dd3a54d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getdtablesize.c @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include + +/* XXX: _BSD || _XOPEN_SOURCE >= 500 */ +#if defined __USE_BSD || defined __USE_XOPEN_EXTENDED + + +#define __LOCAL_OPEN_MAX 256 + +/* Return the maximum number of file descriptors + the current process could possibly have. */ +int getdtablesize (void) +{ + struct rlimit ru; + + /* This should even work if `getrlimit' is not implemented. POSIX.1 + does not define this function but we will generate a stub which + returns -1. */ + return getrlimit (RLIMIT_NOFILE, &ru) < 0 ? __LOCAL_OPEN_MAX : ru.rlim_cur; +} +libc_hidden_def(getdtablesize) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getegid.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getegid.c new file mode 100644 index 00000000..f2b6401c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getegid.c @@ -0,0 +1,33 @@ +/* vi: set sw=4 ts=4: */ +/* + * getegid() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + + +#if defined(__NR_getegid32) +# undef __NR_getegid +# define __NR_getegid __NR_getegid32 +_syscall0(gid_t, getegid) + +#elif defined(__NR_getegid) +# define __NR___syscall_getegid __NR_getegid +static __inline__ _syscall0(int, __syscall_getegid) +gid_t getegid(void) +{ + return (__syscall_getegid()); +} +#else + +gid_t getegid(void) +{ + return (getgid()); +} +#endif +libc_hidden_def(getegid) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/geteuid.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/geteuid.c new file mode 100644 index 00000000..6111e5d1 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/geteuid.c @@ -0,0 +1,34 @@ +/* vi: set sw=4 ts=4: */ +/* + * geteuid() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + + +#if defined(__NR_geteuid32) +# undef __NR_geteuid +# define __NR_geteuid __NR_geteuid32 +_syscall0(uid_t, geteuid) + +#elif defined(__NR_geteuid) +# define __NR___syscall_geteuid __NR_geteuid +static __inline__ _syscall0(int, __syscall_geteuid) +uid_t geteuid(void) +{ + return (__syscall_geteuid()); +} + +#else +uid_t geteuid(void) +{ + return (getuid()); +} +#endif + +libc_hidden_def(geteuid) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getgid.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getgid.c new file mode 100644 index 00000000..80c60034 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getgid.c @@ -0,0 +1,23 @@ +/* vi: set sw=4 ts=4: */ +/* + * getgid() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +#if defined __NR_getxgid +# undef __NR_getgid +# define __NR_getgid __NR_getxgid +#endif +#ifdef __NR_getgid32 +# undef __NR_getgid +# define __NR_getgid __NR_getgid32 +#endif + +_syscall0(gid_t, getgid) +libc_hidden_def(getgid) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getgroups.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getgroups.c new file mode 100644 index 00000000..ddc2caee --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getgroups.c @@ -0,0 +1,60 @@ +/* vi: set sw=4 ts=4: */ +/* + * getgroups() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include + + +#if defined(__NR_getgroups32) +# undef __NR_getgroups +# define __NR_getgroups __NR_getgroups32 +_syscall2(int, getgroups, int, size, gid_t *, list) + +#elif __WORDSIZE == 64 +_syscall2(int, getgroups, int, size, gid_t *, list) + +#else + +#define MIN(a,b) (((a)<(b))?(a):(b)) + +#define __NR___syscall_getgroups __NR_getgroups +static __inline__ _syscall2(int, __syscall_getgroups, + int, size, __kernel_gid_t *, list) + +int getgroups(int size, gid_t groups[]) +{ + if (unlikely(size < 0)) { +ret_error: + __set_errno(EINVAL); + return -1; + } else { + int i, ngids; + __kernel_gid_t *kernel_groups; + + size = MIN(size, sysconf(_SC_NGROUPS_MAX)); + kernel_groups = (__kernel_gid_t *)malloc(sizeof(*kernel_groups) * size); + if (size && kernel_groups == NULL) + goto ret_error; + + ngids = __syscall_getgroups(size, kernel_groups); + if (size != 0 && ngids > 0) { + for (i = 0; i < ngids; i++) { + groups[i] = kernel_groups[i]; + } + } + + free(kernel_groups); + return ngids; + } +} +#endif + +libc_hidden_def(getgroups) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/gethostname.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/gethostname.c new file mode 100644 index 00000000..3b59e567 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/gethostname.c @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include + + + +int +gethostname(char *name, size_t len) +{ + struct utsname uts; + + if (name == NULL) { + __set_errno(EINVAL); + return -1; + } + + if (uname(&uts) == -1) return -1; + + if (strlen(uts.nodename)+1 > len) { + __set_errno(EINVAL); + return -1; + } + strcpy(name, uts.nodename); + return 0; +} +libc_hidden_def(gethostname) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getitimer.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getitimer.c new file mode 100644 index 00000000..b324233a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getitimer.c @@ -0,0 +1,12 @@ +/* vi: set sw=4 ts=4: */ +/* + * getitimer() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +_syscall2(int, getitimer, __itimer_which_t, which, struct itimerval *, value) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getpagesize.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getpagesize.c new file mode 100644 index 00000000..1faa5488 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getpagesize.c @@ -0,0 +1,47 @@ +/* Copyright (C) 1991,1992,1995-1997,2000,2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +extern size_t __pagesize; + +/* Return the system page size. */ +/* couldn't make __getpagesize hidden, because shm.h uses it in a macro */ +extern __typeof(getpagesize) __getpagesize; +int __getpagesize(void) +{ + if (__pagesize != 0) + return __pagesize; + +#ifdef EXEC_PAGESIZE + return EXEC_PAGESIZE; +#else /* No EXEC_PAGESIZE. */ +#ifdef NBPG +#ifndef CLSIZE +#define CLSIZE 1 +#endif /* No CLSIZE. */ + return NBPG * CLSIZE; +#else /* No NBPG. */ + return NBPC; +#endif /* NBPG. */ +#endif /* EXEC_PAGESIZE. */ +} +strong_alias(__getpagesize,getpagesize) +libc_hidden_def(getpagesize) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getpgid.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getpgid.c new file mode 100644 index 00000000..8e7516f1 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getpgid.c @@ -0,0 +1,25 @@ +/* vi: set sw=4 ts=4: */ +/* + * getpgid() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +#if defined __USE_UNIX98 +#include + +#define __NR___syscall_getpgid __NR_getpgid +static __inline__ _syscall1(__kernel_pid_t, __syscall_getpgid, __kernel_pid_t, pid) + +pid_t __getpgid(pid_t pid) +{ + return (__syscall_getpgid(pid)); +} +#ifdef __USE_XOPEN_EXTENDED +weak_alias(__getpgid,getpgid) +#endif +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getpgrp.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getpgrp.c new file mode 100644 index 00000000..5d36ba15 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getpgrp.c @@ -0,0 +1,28 @@ +/* vi: set sw=4 ts=4: */ +/* + * getpgrp() for uClibc + * + * Copyright (C) 2000-2008 by Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +#ifdef __NR_getpgrp +/* According to the manpage the POSIX.1 version is favoured */ +_syscall0(pid_t, getpgrp) +#elif defined __NR_getpgid && (defined __NR_getpid || defined __NR_getxpid) +/* IA64 doesn't have a getpgrp syscall */ +pid_t getpgrp(void) +{ + return getpgid(getpid()); +} +#elif defined __UCLIBC_HAS_STUBS__ +pid_t getpgrp(void) +{ + __set_errno(ENOSYS); + return -1; +} +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getpid.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getpid.c new file mode 100644 index 00000000..8041022e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getpid.c @@ -0,0 +1,20 @@ +/* vi: set sw=4 ts=4: */ +/* + * getpid() for uClibc + * + * Copyright (C) 2000-2006 by Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +extern __typeof(getpid) __libc_getpid; +#if defined __NR_getxpid +# define __NR_getpid __NR_getxpid +#endif +#define __NR___libc_getpid __NR_getpid +_syscall0(pid_t, __libc_getpid) +weak_alias(__libc_getpid, getpid) +libc_hidden_weak(getpid) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getppid.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getppid.c new file mode 100644 index 00000000..4f2b0e93 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getppid.c @@ -0,0 +1,19 @@ +/* vi: set sw=4 ts=4: */ +/* + * getppid() for uClibc + * + * Copyright (C) 2000-2006 by Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#ifdef __NR_getppid +_syscall0(pid_t, getppid) +#else +pid_t getppid(void) +{ + return getpid(); +} +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getpriority.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getpriority.c new file mode 100644 index 00000000..eba54a5f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getpriority.c @@ -0,0 +1,30 @@ +/* vi: set sw=4 ts=4: */ +/* + * getpriority() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + + +#define __NR___syscall_getpriority __NR_getpriority +static __inline__ _syscall2(int, __syscall_getpriority, + __priority_which_t, which, id_t, who) + +/* The return value of __syscall_getpriority is biased by this value + * to avoid returning negative values. */ +#define PZERO 20 +int getpriority(__priority_which_t which, id_t who) +{ + int res; + + res = __syscall_getpriority(which, who); + if (res >= 0) + res = PZERO - res; + return res; +} +libc_hidden_def(getpriority) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getresgid.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getresgid.c new file mode 100644 index 00000000..425263e7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getresgid.c @@ -0,0 +1,38 @@ +/* vi: set sw=4 ts=4: */ +/* + * getresgid() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#ifdef __USE_GNU +#include + +#if defined(__NR_getresgid32) +# undef __NR_getresgid +# define __NR_getresgid __NR_getresgid32 +_syscall3(int, getresgid, gid_t *, rgid, gid_t *, egid, gid_t *, sgid) + +#elif defined(__NR_getresgid) +# define __NR___syscall_getresgid __NR_getresgid +static __inline__ _syscall3(int, __syscall_getresgid, __kernel_gid_t *, rgid, + __kernel_gid_t *, egid, __kernel_gid_t *, sgid) + +int getresgid(gid_t * rgid, gid_t * egid, gid_t * sgid) +{ + int result; + __kernel_gid_t k_rgid, k_egid, k_sgid; + + result = __syscall_getresgid(&k_rgid, &k_egid, &k_sgid); + if (result == 0) { + *rgid = (gid_t) k_rgid; + *egid = (gid_t) k_egid; + *sgid = (gid_t) k_sgid; + } + return result; +} +#endif +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getresuid.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getresuid.c new file mode 100644 index 00000000..87cf6d6d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getresuid.c @@ -0,0 +1,38 @@ +/* vi: set sw=4 ts=4: */ +/* + * getresuid() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#ifdef __USE_GNU +#include + +#if defined(__NR_getresuid32) +# undef __NR_getresuid +# define __NR_getresuid __NR_getresuid32 +_syscall3(int, getresuid, uid_t *, ruid, uid_t *, euid, uid_t *, suid) + +#elif defined(__NR_getresuid) +# define __NR___syscall_getresuid __NR_getresuid +static __inline__ _syscall3(int, __syscall_getresuid, __kernel_uid_t *, ruid, + __kernel_uid_t *, euid, __kernel_uid_t *, suid) + +int getresuid(uid_t * ruid, uid_t * euid, uid_t * suid) +{ + int result; + __kernel_uid_t k_ruid, k_euid, k_suid; + + result = __syscall_getresuid(&k_ruid, &k_euid, &k_suid); + if (result == 0) { + *ruid = (uid_t) k_ruid; + *euid = (uid_t) k_euid; + *suid = (uid_t) k_suid; + } + return result; +} +#endif +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getrlimit.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getrlimit.c new file mode 100644 index 00000000..4d3163f7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getrlimit.c @@ -0,0 +1,67 @@ +/* vi: set sw=4 ts=4: */ +/* + * getrlimit() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define getrlimit64 __hide_getrlimit64 +#include +#include +#include +#undef getrlimit64 + + +/* Only wrap getrlimit if the new ugetrlimit is not present and getrlimit sucks */ + +#if defined __NR_ugetrlimit + +/* just call ugetrlimit() */ +# define __NR___syscall_ugetrlimit __NR_ugetrlimit +static __always_inline +_syscall2(int, __syscall_ugetrlimit, enum __rlimit_resource, resource, + struct rlimit *, rlim) +int getrlimit(__rlimit_resource_t resource, struct rlimit *rlimits) +{ + return (__syscall_ugetrlimit(resource, rlimits)); +} + +#elif !defined(__UCLIBC_HANDLE_OLDER_RLIMIT__) + +/* We don't need to wrap getrlimit() */ +_syscall2(int, getrlimit, __rlimit_resource_t, resource, + struct rlimit *, rlim) + +#else + +/* we have to handle old style getrlimit() */ +# define __NR___syscall_getrlimit __NR_getrlimit +static __always_inline +_syscall2(int, __syscall_getrlimit, int, resource, struct rlimit *, rlim) + +int getrlimit(__rlimit_resource_t resource, struct rlimit *rlimits) +{ + int result; + + result = __syscall_getrlimit(resource, rlimits); + + if (result == -1) + return result; + + /* We might have to correct the limits values. Since the old values + * were signed the infinity value is too small. */ + if (rlimits->rlim_cur == RLIM_INFINITY >> 1) + rlimits->rlim_cur = RLIM_INFINITY; + if (rlimits->rlim_max == RLIM_INFINITY >> 1) + rlimits->rlim_max = RLIM_INFINITY; + return result; +} +#endif + +libc_hidden_def(getrlimit) + +#if defined __UCLIBC_HAS_LFS__ && __WORDSIZE == 64 +strong_alias(getrlimit, getrlimit64) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getrlimit64.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getrlimit64.c new file mode 100644 index 00000000..d537241e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getrlimit64.c @@ -0,0 +1,50 @@ +/* Copyright (C) 1991, 1995, 1996, 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <_lfs_64.h> + +#include +#include +#include + +/* the regular getrlimit will work just fine for 64bit users */ + +#if defined __UCLIBC_HAS_LFS__ && __WORDSIZE == 32 + + +/* Put the soft and hard limits for RESOURCE in *RLIMITS. + Returns 0 if successful, -1 if not (and sets errno). */ +int getrlimit64 (__rlimit_resource_t resource, struct rlimit64 *rlimits) +{ + struct rlimit rlimits32; + + if (getrlimit (resource, &rlimits32) < 0) + return -1; + + if (rlimits32.rlim_cur == RLIM_INFINITY) + rlimits->rlim_cur = RLIM64_INFINITY; + else + rlimits->rlim_cur = rlimits32.rlim_cur; + if (rlimits32.rlim_max == RLIM_INFINITY) + rlimits->rlim_max = RLIM64_INFINITY; + else + rlimits->rlim_max = rlimits32.rlim_max; + + return 0; +} +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getrusage.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getrusage.c new file mode 100644 index 00000000..3e719f29 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getrusage.c @@ -0,0 +1,13 @@ +/* vi: set sw=4 ts=4: */ +/* + * getrusage() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +_syscall2(int, getrusage, __rusage_who_t, who, struct rusage *, usage) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getsid.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getsid.c new file mode 100644 index 00000000..5a178bba --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getsid.c @@ -0,0 +1,23 @@ +/* vi: set sw=4 ts=4: */ +/* + * getsid() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +#ifdef __USE_XOPEN_EXTENDED + +#define __NR___syscall_getsid __NR_getsid +static __inline__ _syscall1(__kernel_pid_t, __syscall_getsid, __kernel_pid_t, pid) + +pid_t getsid(pid_t pid) +{ + return (__syscall_getsid(pid)); +} +libc_hidden_def(getsid) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/gettimeofday.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/gettimeofday.c new file mode 100644 index 00000000..52490fec --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/gettimeofday.c @@ -0,0 +1,18 @@ +/* vi: set sw=4 ts=4: */ +/* + * gettimeofday() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +#ifdef __USE_BSD +_syscall2(int, gettimeofday, struct timeval *, tv, struct timezone *, tz) +#else +_syscall2(int, gettimeofday, struct timeval *, tv, void *, tz) +#endif +libc_hidden_def(gettimeofday) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getuid.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getuid.c new file mode 100644 index 00000000..b6f813a0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/getuid.c @@ -0,0 +1,23 @@ +/* vi: set sw=4 ts=4: */ +/* + * getuid() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +#if defined __NR_getxuid +# undef __NR_getuid +# define __NR_getuid __NR_getxuid +#endif +#ifdef __NR_getuid32 +# undef __NR_getuid +# define __NR_getuid __NR_getuid32 +#endif + +_syscall0(uid_t, getuid) +libc_hidden_def(getuid) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/hp-timing.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/hp-timing.h new file mode 100644 index 00000000..099342db --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/hp-timing.h @@ -0,0 +1,83 @@ +/* High precision, low overhead timing functions. Generic version. + Copyright (C) 1998, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _HP_TIMING_H +#define _HP_TIMING_H 1 + + +/* There are no generic definitions for the times. We could write something + using the `gettimeofday' system call where available but the overhead of + the system call might be too high. + + In case a platform supports timers in the hardware the following macros + and types must be defined: + + - HP_TIMING_AVAIL: test for availability. + + - HP_TIMING_INLINE: this macro is non-zero if the functionality is not + implemented using function calls but instead uses some inlined code + which might simply consist of a few assembler instructions. We have to + know this since we might want to use the macros here in places where we + cannot make function calls. + + - hp_timing_t: This is the type for variables used to store the time + values. + + - HP_TIMING_ZERO: clear `hp_timing_t' object. + + - HP_TIMING_NOW: place timestamp for current time in variable given as + parameter. + + - HP_TIMING_DIFF_INIT: do whatever is necessary to be able to use the + HP_TIMING_DIFF macro. + + - HP_TIMING_DIFF: compute difference between two times and store it + in a third. Source and destination might overlap. + + - HP_TIMING_ACCUM: add time difference to another variable. This might + be a bit more complicated to implement for some platforms as the + operation should be thread-safe and 64bit arithmetic on 32bit platforms + is not. + + - HP_TIMING_ACCUM_NT: this is the variant for situations where we know + there are no threads involved. + + - HP_TIMING_PRINT: write decimal representation of the timing value into + the given string. This operation need not be inline even though + HP_TIMING_INLINE is specified. + +*/ + +/* Provide dummy definitions. */ +#define HP_TIMING_AVAIL (0) +#define HP_TIMING_INLINE (0) +typedef int hp_timing_t; +#define HP_TIMING_ZERO(Var) +#define HP_TIMING_NOW(var) +#define HP_TIMING_DIFF_INIT() +#define HP_TIMING_DIFF(Diff, Start, End) +#define HP_TIMING_ACCUM(Sum, Diff) +#define HP_TIMING_ACCUM_NT(Sum, Diff) +#define HP_TIMING_PRINT(Buf, Len, Val) + +/* Since this implementation is not available we tell the user about it. */ +#define HP_TIMING_NONAVAIL 1 + +#endif /* hp-timing.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/init_module.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/init_module.c new file mode 100644 index 00000000..8a6e9419 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/init_module.c @@ -0,0 +1,25 @@ +/* vi: set sw=4 ts=4: */ +/* + * init_module() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +int init_module(void *first, void *second, void *third, void *fourth, void *fifth); +#ifdef __NR_init_module +/* This may have 5 arguments (for old 2.0 kernels) or 2 arguments + * (for 2.2 and 2.4 kernels). Use the greatest common denominator, + * and let the kernel cope with whatever it gets. It's good at that. */ +_syscall5(int, init_module, void *, first, void *, second, void *, third, + void *, fourth, void *, fifth) +#else +int init_module(void *first, void *second, void *third, void *fourth, void *fifth) +{ + __set_errno(ENOSYS); + return -1; +} +#endif + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/inotify.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/inotify.c new file mode 100644 index 00000000..e35f0430 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/inotify.c @@ -0,0 +1,28 @@ +/* vi: set sw=4 ts=4: */ +/* + * inotify interface for uClibc + * + * Copyright (C) 2006 Austin Morgan + * Copyright (C) 2006 by Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +#ifdef __NR_inotify_init +_syscall0(int, inotify_init) +#endif + +#ifdef __NR_inotify_init1 +_syscall1(int, inotify_init1, int, flags) +#endif + +#ifdef __NR_inotify_add_watch +_syscall3(int, inotify_add_watch, int, fd, const char *, path, uint32_t, mask) +#endif + +#ifdef __NR_inotify_rm_watch +_syscall2(int, inotify_rm_watch, int, fd, uint32_t, wd) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/ioctl.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/ioctl.c new file mode 100644 index 00000000..f2f0f539 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/ioctl.c @@ -0,0 +1,46 @@ +/* vi: set sw=4 ts=4: */ +/* + * ioctl() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include + +#ifdef __UCLIBC_HAS_THREADS_NATIVE__ +#include +#else +#define SINGLE_THREAD_P 1 +#endif + +libc_hidden_proto(ioctl) + +#define __NR___syscall_ioctl __NR_ioctl +static __always_inline +_syscall3(int, __syscall_ioctl, int, fd, unsigned long int, request, void *, arg) + +int ioctl(int fd, unsigned long int request, ...) +{ + void *arg; + va_list list; + + va_start(list, request); + arg = va_arg(list, void *); + + va_end(list); + + if (SINGLE_THREAD_P) + return __syscall_ioctl(fd, request, arg); + +#ifdef __UCLIBC_HAS_THREADS_NATIVE__ + int oldtype = LIBC_CANCEL_ASYNC (); + int result = __syscall_ioctl(fd, request, arg); + LIBC_CANCEL_RESET (oldtype); + return result; +#endif +} +libc_hidden_def(ioctl) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/ioperm.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/ioperm.c new file mode 100644 index 00000000..bca2fff0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/ioperm.c @@ -0,0 +1,22 @@ +/* vi: set sw=4 ts=4: */ +/* + * ioperm() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +#if defined __ARCH_USE_MMU__ && defined __NR_ioperm + +/* psm: can't #include , some archs miss it */ +extern int ioperm(unsigned long __from, unsigned long __num, int __turn_on) __THROW; +/* Not needed internally; +libc_hidden_proto(ioperm) +*/ +_syscall3(int, ioperm, unsigned long, from, unsigned long, num, int, turn_on) +/*libc_hidden_def(ioperm)*/ + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/iopl.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/iopl.c new file mode 100644 index 00000000..4d9c4587 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/iopl.c @@ -0,0 +1,15 @@ +/* vi: set sw=4 ts=4: */ +/* + * iopl() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#if defined __ARCH_USE_MMU__ && defined __NR_iopl +/* psm: can't #include , some archs miss it */ +extern int iopl(int __level) __THROW; +_syscall1(int, iopl, int, level) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/kill.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/kill.c new file mode 100644 index 00000000..c11a0ed0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/kill.c @@ -0,0 +1,21 @@ +/* vi: set sw=4 ts=4: */ +/* + * kill() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + + +#define __NR___syscall_kill __NR_kill +static __inline__ _syscall2(int, __syscall_kill, __kernel_pid_t, pid, int, sig) + +int kill(pid_t pid, int sig) +{ + return (__syscall_kill(pid, sig)); +} +libc_hidden_def(kill) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/klogctl.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/klogctl.c new file mode 100644 index 00000000..58467dfa --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/klogctl.c @@ -0,0 +1,18 @@ +/* vi: set sw=4 ts=4: */ +/* + * klogctl() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#define __NR__syslog __NR_syslog +static __inline__ _syscall3(int, _syslog, int, type, char *, buf, int, len) +int klogctl(int type, char *buf, int len) +{ + return (_syslog(type, buf, len)); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/lchown.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/lchown.c new file mode 100644 index 00000000..c0f8ce76 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/lchown.c @@ -0,0 +1,38 @@ +/* vi: set sw=4 ts=4: */ +/* + * lchown() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include + +#if (__WORDSIZE == 32 && defined(__NR_lchown32)) || __WORDSIZE == 64 +# ifdef __NR_lchown32 +# undef __NR_lchown +# define __NR_lchown __NR_lchown32 +# endif + +_syscall3(int, lchown, const char *, path, uid_t, owner, gid_t, group) + +#else + +# define __NR___syscall_lchown __NR_lchown +static __inline__ _syscall3(int, __syscall_lchown, const char *, path, + __kernel_uid_t, owner, __kernel_gid_t, group) + +int lchown(const char *path, uid_t owner, gid_t group) +{ + if (((owner + 1) > (uid_t) ((__kernel_uid_t) - 1U)) + || ((group + 1) > (gid_t) ((__kernel_gid_t) - 1U))) { + __set_errno(EINVAL); + return -1; + } + return __syscall_lchown(path, owner, group); +} + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/libgcc_s.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/libgcc_s.h new file mode 100644 index 00000000..e74a1034 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/libgcc_s.h @@ -0,0 +1,2 @@ +/* Name of libgcc_s library provided by gcc. */ +#define LIBGCC_S_SO "libgcc_s.so.1" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/link.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/link.c new file mode 100644 index 00000000..b5e5536d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/link.c @@ -0,0 +1,12 @@ +/* vi: set sw=4 ts=4: */ +/* + * link() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +_syscall2(int, link, const char *, oldpath, const char *, newpath) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/linkat.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/linkat.c new file mode 100644 index 00000000..9abe9ec7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/linkat.c @@ -0,0 +1,16 @@ +/* + * linkat() for uClibc + * + * Copyright (C) 2009 Analog Devices Inc. + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +#ifdef __NR_linkat +_syscall5(int, linkat, int, fromfd, const char *, from, int, tofd, const char *, to, int, flags) +#else +/* should add emulation with link() and /proc/self/fd/ ... */ +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/llseek.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/llseek.c new file mode 100644 index 00000000..cd150ad9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/llseek.c @@ -0,0 +1,37 @@ +/* vi: set sw=4 ts=4: */ +/* + * llseek/lseek64 syscall for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include + +#if defined __NR__llseek && defined __UCLIBC_HAS_LFS__ + +loff_t lseek64(int fd, loff_t offset, int whence) +{ + loff_t result; + return (loff_t)(INLINE_SYSCALL(_llseek, 5, fd, (off_t) (offset >> 32), + (off_t) (offset & 0xffffffff), &result, whence) ?: result); +} + +#else + +loff_t lseek64(int fd, loff_t offset, int whence) +{ + return (loff_t)(lseek(fd, (off_t) (offset), whence)); +} + +#endif + +#ifndef __LINUXTHREADS_OLD__ +libc_hidden_def(lseek64) +#else +libc_hidden_weak(lseek64) +strong_alias(lseek64,__libc_lseek64) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/longjmp.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/longjmp.c new file mode 100644 index 00000000..4d144241 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/longjmp.c @@ -0,0 +1,49 @@ +/* Copyright (C) 1991, 92, 94, 95, 97, 98, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + + +extern void __longjmp (__jmp_buf __env, int __val) attribute_noreturn; +libc_hidden_proto(__longjmp) + +extern __typeof(longjmp) __libc_longjmp attribute_noreturn; +/* Set the signal mask to the one specified in ENV, and jump + to the position specified in ENV, causing the setjmp + call there to return VAL, or 1 if VAL is 0. */ +void __libc_longjmp (sigjmp_buf env, int val) +{ +#if 0 + /* Perform any cleanups needed by the frames being unwound. */ + _longjmp_unwind (env, val); +#endif + + if (env[0].__mask_was_saved) + /* Restore the saved signal mask. */ + (void) sigprocmask (SIG_SETMASK, &env[0].__saved_mask, NULL); + + /* Call the machine-dependent function to restore machine state. */ + __longjmp (env[0].__jmpbuf, val ?: 1); +} + +weak_alias(__libc_longjmp,longjmp) +weak_alias(__libc_longjmp,siglongjmp) +strong_alias(__libc_longjmp,__libc_siglongjmp) +strong_alias(__libc_longjmp,_longjmp) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/lseek.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/lseek.c new file mode 100644 index 00000000..9ff42404 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/lseek.c @@ -0,0 +1,27 @@ +/* vi: set sw=4 ts=4: */ +/* + * lseek() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +#ifdef __NR_lseek +_syscall3(__off_t, lseek, int, fildes, __off_t, offset, int, whence) +#else + +__off_t lseek(int fildes, __off_t offset, int whence) +{ + return lseek64(fildes, offset, whence); +} +#endif +#ifndef __LINUXTHREADS_OLD__ +libc_hidden_def(lseek) +#else +libc_hidden_weak(lseek) +strong_alias(lseek,__libc_lseek) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/lstat.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/lstat.c new file mode 100644 index 00000000..aa774473 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/lstat.c @@ -0,0 +1,35 @@ +/* vi: set sw=4 ts=4: */ +/* + * lstat() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include "xstatconv.h" + +#define __NR___syscall_lstat __NR_lstat +static __inline__ _syscall2(int, __syscall_lstat, + const char *, file_name, struct kernel_stat *, buf) + +int lstat(const char *file_name, struct stat *buf) +{ + int result; + struct kernel_stat kbuf; + + result = __syscall_lstat(file_name, &kbuf); + if (result == 0) { + __xstat_conv(&kbuf, buf); + } + return result; +} +libc_hidden_def(lstat) + +#if ! defined __NR_lstat64 && defined __UCLIBC_HAS_LFS__ +strong_alias_untyped(lstat,lstat64) +libc_hidden_def(lstat64) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/lstat64.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/lstat64.c new file mode 100644 index 00000000..235b76d4 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/lstat64.c @@ -0,0 +1,35 @@ +/* vi: set sw=4 ts=4: */ +/* + * lstat64() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +#if defined __UCLIBC_HAS_LFS__ && defined __NR_lstat64 +# include +# include +# include "xstatconv.h" + + +# define __NR___syscall_lstat64 __NR_lstat64 +static __inline__ _syscall2(int, __syscall_lstat64, const char *, file_name, + struct kernel_stat64 *, buf) + +int lstat64(const char *file_name, struct stat64 *buf) +{ + int result; + struct kernel_stat64 kbuf; + + result = __syscall_lstat64(file_name, &kbuf); + if (result == 0) { + __xstat64_conv(&kbuf, buf); + } + return result; +} +libc_hidden_def(lstat64) + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/lutimes.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/lutimes.c new file mode 100644 index 00000000..0b4a8ea4 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/lutimes.c @@ -0,0 +1,38 @@ +/* vi: set sw=4 ts=4: */ +/* + * lutimes() implementation for uClibc + * + * Copyright (C) 2010 Vladimir Zapolskiy + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +#ifdef __NR_lutimes +_syscall2(int, lutimes, const char *, file, const struct timeval *, tvp) +#else +#include +#include + +int lutimes(const char *file, const struct timeval tvp[2]) +{ + struct timespec ts[2]; + + if (tvp != NULL) + { + if (tvp[0].tv_usec < 0 || tvp[0].tv_usec >= 1000000 + || tvp[1].tv_usec < 0 || tvp[1].tv_usec >= 1000000) + { + __set_errno(EINVAL); + return -1; + } + + TIMEVAL_TO_TIMESPEC(&tvp[0], &ts[0]); + TIMEVAL_TO_TIMESPEC(&tvp[1], &ts[1]); + } + + return utimensat(AT_FDCWD, file, tvp ? ts : NULL, AT_SYMLINK_NOFOLLOW); +} +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/madvise.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/madvise.c new file mode 100644 index 00000000..e953d7b9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/madvise.c @@ -0,0 +1,14 @@ +/* vi: set sw=4 ts=4: */ +/* + * madvise() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#if defined __NR_madvise && defined __USE_BSD +_syscall3(int, madvise, void *, __addr, size_t, __len, int, __advice) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/mincore.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/mincore.c new file mode 100644 index 00000000..f1f3557c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/mincore.c @@ -0,0 +1,15 @@ +/* + * This file provides the mincore() system call to uClibc. + * Copyright (C) 20041215 - + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +#if defined __NR_mincore && (defined __USE_BSD || defined __USE_SVID) +#include +#include +_syscall3(int, mincore, void *, start, size_t, length, unsigned char *, vec) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/mkdir.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/mkdir.c new file mode 100644 index 00000000..fbc587d3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/mkdir.c @@ -0,0 +1,22 @@ +/* vi: set sw=4 ts=4: */ +/* + * mkdir() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + + +#define __NR___syscall_mkdir __NR_mkdir +static __inline__ _syscall2(int, __syscall_mkdir, const char *, pathname, + __kernel_mode_t, mode) + +int mkdir(const char *pathname, mode_t mode) +{ + return (__syscall_mkdir(pathname, mode)); +} +libc_hidden_def(mkdir) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/mkdirat.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/mkdirat.c new file mode 100644 index 00000000..4da9468e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/mkdirat.c @@ -0,0 +1,16 @@ +/* + * mkdirat() for uClibc + * + * Copyright (C) 2009 Analog Devices Inc. + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +#ifdef __NR_mkdirat +_syscall3(int, mkdirat, int, fd, const char *, path, mode_t, mode) +#else +/* should add emulation with mkdir() and /proc/self/fd/ ... */ +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/mkfifo.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/mkfifo.c new file mode 100644 index 00000000..06168141 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/mkfifo.c @@ -0,0 +1,30 @@ +/* Copyright (C) 1991, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + + +/* Create a named pipe (FIFO) named PATH with protections MODE. */ +int +mkfifo (const char *path, mode_t mode) +{ + return mknod (path, mode | S_IFIFO, 0); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/mkfifoat.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/mkfifoat.c new file mode 100644 index 00000000..e442fe22 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/mkfifoat.c @@ -0,0 +1,19 @@ +/* + * mkfifoat() for uClibc + * + * Copyright (C) 2009 Analog Devices Inc. + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +#ifdef __NR_mknodat +int mkfifoat(int fd, const char *path, mode_t mode) +{ + return mknodat(fd, path, mode | S_IFIFO, 0); +} +#else +/* should add emulation with mkfifo() and /proc/self/fd/ ... */ +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/mknod.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/mknod.c new file mode 100644 index 00000000..b52c8c55 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/mknod.c @@ -0,0 +1,22 @@ +/* vi: set sw=4 ts=4: */ +/* + * mknod() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +int mknod(const char *path, mode_t mode, dev_t dev) +{ + unsigned long long int k_dev; + + /* We must convert the value to dev_t type used by the kernel. */ + k_dev = (dev) & ((1ULL << 32) - 1); + + return INLINE_SYSCALL(mknod, 3, path, mode, (unsigned int)k_dev); +} +libc_hidden_def(mknod) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/mknodat.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/mknodat.c new file mode 100644 index 00000000..93b9e6e7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/mknodat.c @@ -0,0 +1,25 @@ +/* + * mknodat() for uClibc + * + * Copyright (C) 2009 Analog Devices Inc. + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +#ifdef __NR_mknodat +int mknodat(int fd, const char *path, mode_t mode, dev_t dev) +{ + unsigned long long int k_dev; + + /* We must convert the value to dev_t type used by the kernel. */ + k_dev = (dev) & ((1ULL << 32) - 1); + + return INLINE_SYSCALL(mknodat, 4, fd, path, mode, (unsigned int)k_dev); +} +libc_hidden_def(mknodat) +#else +/* should add emulation with mknod() and /proc/self/fd/ ... */ +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/mlock.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/mlock.c new file mode 100644 index 00000000..12120d8e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/mlock.c @@ -0,0 +1,14 @@ +/* vi: set sw=4 ts=4: */ +/* + * mlock() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#if defined __ARCH_USE_MMU__ && defined __NR_mlock +_syscall2(int, mlock, const void *, addr, size_t, len) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/mlockall.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/mlockall.c new file mode 100644 index 00000000..99f72018 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/mlockall.c @@ -0,0 +1,14 @@ +/* vi: set sw=4 ts=4: */ +/* + * mlockall() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#if defined __ARCH_USE_MMU__ && defined __NR_mlockall +_syscall1(int, mlockall, int, flags) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/mmap.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/mmap.c new file mode 100644 index 00000000..89958985 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/mmap.c @@ -0,0 +1,71 @@ +/* vi: set sw=4 ts=4: */ +/* + * mmap() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include + +#ifdef __NR_mmap + + +#ifdef __UCLIBC_MMAP_HAS_6_ARGS__ + +_syscall6(void *, mmap, void *, start, size_t, length, + int, prot, int, flags, int, fd, off_t, offset) + +#else + +# define __NR__mmap __NR_mmap +static __inline__ _syscall1(__ptr_t, _mmap, unsigned long *, buffer) +__ptr_t mmap(__ptr_t addr, size_t len, int prot, + int flags, int fd, __off_t offset) +{ + unsigned long buffer[6]; + + buffer[0] = (unsigned long) addr; + buffer[1] = (unsigned long) len; + buffer[2] = (unsigned long) prot; + buffer[3] = (unsigned long) flags; + buffer[4] = (unsigned long) fd; + buffer[5] = (unsigned long) offset; + return (__ptr_t) _mmap(buffer); +} + +#endif + +libc_hidden_def(mmap) + +#elif defined(__NR_mmap2) + + +#define __NR___syscall_mmap2 __NR_mmap2 +static __inline__ _syscall6(__ptr_t, __syscall_mmap2, __ptr_t, addr, + size_t, len, int, prot, int, flags, int, fd, off_t, offset) + +/* Some architectures always use 12 as page shift for mmap2() eventhough the + * real PAGE_SHIFT != 12. Other architectures use the same value as + * PAGE_SHIFT... + */ +# ifndef MMAP2_PAGE_SHIFT +# define MMAP2_PAGE_SHIFT 12 +# endif + +__ptr_t mmap(__ptr_t addr, size_t len, int prot, int flags, int fd, __off_t offset) +{ + if (offset & ((1 << MMAP2_PAGE_SHIFT) - 1)) { + __set_errno(EINVAL); + return MAP_FAILED; + } + return __syscall_mmap2(addr, len, prot, flags, fd, offset >> MMAP2_PAGE_SHIFT); +} + +libc_hidden_def(mmap) + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/mmap64.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/mmap64.c new file mode 100644 index 00000000..4ef03971 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/mmap64.c @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ +/* Massivly hacked up for uClibc by Erik Andersen */ + +#include <_lfs_64.h> + +#ifdef __UCLIBC_HAS_LFS__ + +#include +#include +#include +#include +#include + + +# if !defined __NR_mmap2 + +/* + * This version is a stub that just chops off everything at the mmap 32 bit + * mmap() address space... You will probably need to add in an arch specific + * implementation to override this as there is not a generic way for me to + * implement this particular syscall if your arch lacks _syscall6... + * + */ + +__ptr_t mmap64(__ptr_t addr, size_t len, int prot, int flags, int fd, __off64_t offset) +{ + if (offset != (off_t) offset || + (offset + len) != (off_t) (offset + len)) { + __set_errno(EINVAL); + return MAP_FAILED; + } + + return mmap(addr, len, prot, flags, fd, (off_t) offset); +} + +# else + +# define __NR___syscall_mmap2 __NR_mmap2 +static __inline__ _syscall6(__ptr_t, __syscall_mmap2, __ptr_t, addr, + size_t, len, int, prot, int, flags, int, fd, + off_t, offset) + +/* Some architectures always use 12 as page shift for mmap2() eventhough the + * real PAGE_SHIFT != 12. Other architectures use the same value as + * PAGE_SHIFT... + */ +# ifndef MMAP2_PAGE_SHIFT +# define MMAP2_PAGE_SHIFT 12 +# endif + +__ptr_t mmap64(__ptr_t addr, size_t len, int prot, int flags, int fd, __off64_t offset) +{ + if (offset & ((1 << MMAP2_PAGE_SHIFT) - 1)) { + __set_errno(EINVAL); + return MAP_FAILED; + } + +# ifdef __USE_FILE_OFFSET64 + return __syscall_mmap2(addr, len, prot, flags, + fd, ((__u_quad_t) offset >> MMAP2_PAGE_SHIFT)); +# else + return __syscall_mmap2(addr, len, prot, flags, + fd, ((__u_long) offset >> MMAP2_PAGE_SHIFT)); +# endif +} + +# endif +#endif /* __UCLIBC_HAS_LFS__ */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/modify_ldt.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/modify_ldt.c new file mode 100644 index 00000000..d70bd40b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/modify_ldt.c @@ -0,0 +1,15 @@ +/* vi: set sw=4 ts=4: */ +/* + * modify_ldt() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +int modify_ldt (int func, void *ptr, unsigned long bytecount); +#ifdef __NR_modify_ldt +_syscall3(int, modify_ldt, int, func, void *, ptr, unsigned long, bytecount) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/mount.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/mount.c new file mode 100644 index 00000000..39e5db1c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/mount.c @@ -0,0 +1,14 @@ +/* vi: set sw=4 ts=4: */ +/* + * mount() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +_syscall5(int, mount, const char *, specialfile, const char *, dir, + const char *, filesystemtype, unsigned long, rwflag, + const void *, data) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/mprotect.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/mprotect.c new file mode 100644 index 00000000..d60fc04d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/mprotect.c @@ -0,0 +1,15 @@ +/* vi: set sw=4 ts=4: */ +/* + * mprotect() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +#if defined __NR_mprotect +_syscall3(int, mprotect, void *, addr, size_t, len, int, prot) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/mremap.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/mremap.c new file mode 100644 index 00000000..0295a25d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/mremap.c @@ -0,0 +1,28 @@ +/* vi: set sw=4 ts=4: */ +/* + * mremap() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +#ifdef __NR_mremap + +/* Why do we do this?! */ + +#define mremap _hidemremap +#include +#undef mremap + +void *mremap(void *, size_t, size_t, int, void *); +libc_hidden_proto(mremap) + +_syscall5(void *, mremap, void *, old_address, size_t, old_size, size_t, + new_size, int, may_move, void *, new_address) +libc_hidden_def(mremap) + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/msync.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/msync.c new file mode 100644 index 00000000..844dbaa8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/msync.c @@ -0,0 +1,45 @@ +/* vi: set sw=4 ts=4: */ +/* + * msync() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include + +#ifdef __NR_msync + +#ifdef __UCLIBC_HAS_THREADS_NATIVE__ +#include +#else +#define SINGLE_THREAD_P 1 +#endif + +#define __NR___syscall_msync __NR_msync +static __always_inline _syscall3(int, __syscall_msync, void *, addr, size_t, length, + int, flags) + +extern __typeof(msync) __libc_msync; +int __libc_msync(void * addr, size_t length, int flags) +{ +#ifdef __UCLIBC_HAS_THREADS_NATIVE__ + int oldtype, result; +#endif + + if (SINGLE_THREAD_P) + return __syscall_msync(addr, length, flags); + +#ifdef __UCLIBC_HAS_THREADS_NATIVE__ + oldtype = LIBC_CANCEL_ASYNC (); + result = __syscall_msync(addr, length, flags); + LIBC_CANCEL_RESET (oldtype); + return result; +#endif +} +weak_alias(__libc_msync,msync) + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/munlock.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/munlock.c new file mode 100644 index 00000000..07f93760 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/munlock.c @@ -0,0 +1,14 @@ +/* vi: set sw=4 ts=4: */ +/* + * munlock() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#if defined __ARCH_USE_MMU__ && defined __NR_munlock +_syscall2(int, munlock, const void *, addr, size_t, len) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/munlockall.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/munlockall.c new file mode 100644 index 00000000..cc152645 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/munlockall.c @@ -0,0 +1,16 @@ +/* vi: set sw=4 ts=4: */ +/* + * munlockall() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +#if defined __NR_munlockall && defined __ARCH_USE_MMU__ +#include + +_syscall0(int, munlockall) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/munmap.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/munmap.c new file mode 100644 index 00000000..736bffee --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/munmap.c @@ -0,0 +1,16 @@ +/* vi: set sw=4 ts=4: */ +/* + * munmap() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include + + +_syscall2(int, munmap, void *, start, size_t, length) +libc_hidden_def(munmap) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/nanosleep.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/nanosleep.c new file mode 100644 index 00000000..0be59c51 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/nanosleep.c @@ -0,0 +1,41 @@ +/* vi: set sw=4 ts=4: */ +/* + * nanosleep() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +#ifdef __UCLIBC_HAS_THREADS_NATIVE__ +#include +#include +#else +#define SINGLE_THREAD_P 1 +#endif + +#define __NR___syscall_nanosleep __NR_nanosleep +static inline _syscall2(int, __syscall_nanosleep, const struct timespec *, req, + struct timespec *, rem); + +extern __typeof(nanosleep) __libc_nanosleep; + +int __libc_nanosleep(const struct timespec *req, struct timespec *rem) +{ + if (SINGLE_THREAD_P) + return __syscall_nanosleep(req, rem); + +#ifdef __UCLIBC_HAS_THREADS_NATIVE__ + int oldtype = LIBC_CANCEL_ASYNC (); + int result = __syscall_nanosleep(req, rem); + LIBC_CANCEL_RESET (oldtype); + return result; +#endif +} + +libc_hidden_proto(nanosleep) +weak_alias(__libc_nanosleep,nanosleep) +libc_hidden_weak(nanosleep) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/nice.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/nice.c new file mode 100644 index 00000000..3694db88 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/nice.c @@ -0,0 +1,75 @@ +/* vi: set sw=4 ts=4: */ +/* + * nice() for uClibc + * + * Copyright (C) 2005 by Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include + + +#ifdef __NR_nice + +# define __NR___syscall_nice __NR_nice +static __inline__ _syscall1(int, __syscall_nice, int, incr) + +#else + +# include + + +static __inline__ int int_add_no_wrap(int a, int b) +{ + int s = a + b; + + if (b < 0) { + if (s > a) s = INT_MIN; + } else { + if (s < a) s = INT_MAX; + } + + return s; +} + +static __inline__ int __syscall_nice(int incr) +{ + int old_priority; +# if 1 + /* This should never fail. */ + old_priority = getpriority(PRIO_PROCESS, 0); +# else + /* But if you want to be paranoid... */ + int old_errno; + + old_errno = errno; + __set_errno(0); + old_priority = getpriority(PRIO_PROCESS, 0); + if ((old_priority == -1) && errno) { + return -1; + } + __set_errno(old_errno); +# endif + + if (setpriority(PRIO_PROCESS, 0, int_add_no_wrap(old_priority, incr))) { + __set_errno(EPERM); /* SUSv3 mandates EPERM for nice failure. */ + return -1; + } + + return 0; +} + +#endif + +int nice(int incr) +{ + if (__syscall_nice(incr)) { + return -1; + } + + return getpriority(PRIO_PROCESS, 0); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/noophooks.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/noophooks.c new file mode 100644 index 00000000..a6c9d767 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/noophooks.c @@ -0,0 +1,29 @@ +/* Noop hooks for the instrumenting functions. + Copyright (C) 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +void +__cyg_profile_func_enter (attribute_unused void *this_fn, attribute_unused void *call_site); +void +__cyg_profile_func_enter (attribute_unused void *this_fn, attribute_unused void *call_site) +{ +} +strong_alias (__cyg_profile_func_enter, __cyg_profile_func_exit) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/not-cancel.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/not-cancel.h new file mode 100644 index 00000000..9418417b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/not-cancel.h @@ -0,0 +1,60 @@ +/* Uncancelable versions of cancelable interfaces. Linux version. + Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +/* Uncancelable open. */ +#define open_not_cancel(name, flags, mode) \ + INLINE_SYSCALL (open, 3, (const char *) (name), (flags), (mode)) +#define open_not_cancel_2(name, flags) \ + INLINE_SYSCALL (open, 2, (const char *) (name), (flags)) + +/* Uncancelable close. */ +#define close_not_cancel(fd) \ + INLINE_SYSCALL (close, 1, fd) +#define close_not_cancel_no_status(fd) \ + (void) ({ INTERNAL_SYSCALL_DECL (err); \ + INTERNAL_SYSCALL (close, err, 1, (fd)); }) + +/* Uncancelable read. */ +#define read_not_cancel(fd, buf, n) \ + INLINE_SYSCALL (read, 3, (fd), (buf), (n)) + +/* Uncancelable write. */ +#define write_not_cancel(fd, buf, n) \ + INLINE_SYSCALL (write, 3, (fd), (buf), (n)) + +/* Uncancelable writev. */ +#define writev_not_cancel_no_status(fd, iov, n) \ + (void) ({ INTERNAL_SYSCALL_DECL (err); \ + INTERNAL_SYSCALL (writev, err, 3, (fd), (iov), (n)); }) + +/* Uncancelable fcntl. */ +#define fcntl_not_cancel(fd, cmd, val) \ + __fcntl_nocancel (fd, cmd, val) + +/* Uncancelable waitpid. */ +#ifdef __NR_waitpid +# define waitpid_not_cancel(pid, stat_loc, options) \ + INLINE_SYSCALL (waitpid, 3, pid, stat_loc, options) +#else +# define waitpid_not_cancel(pid, stat_loc, options) \ + INLINE_SYSCALL (wait4, 4, pid, stat_loc, options, NULL) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/ntp_gettime.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/ntp_gettime.c new file mode 100644 index 00000000..83959e86 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/ntp_gettime.c @@ -0,0 +1,33 @@ +/* Copyright (C) 1999, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + + +int ntp_gettime(struct ntptimeval *ntv) +{ + struct timex tntx; + int result; + + tntx.modes = 0; + result = adjtimex(&tntx); + ntv->time = tntx.time; + ntv->maxerror = tntx.maxerror; + ntv->esterror = tntx.esterror; + return result; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/open.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/open.c new file mode 100644 index 00000000..9fb694d2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/open.c @@ -0,0 +1,39 @@ +/* vi: set sw=4 ts=4: */ +/* + * open() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include +#include +#include + +#define __NR___syscall_open __NR_open +static __inline__ _syscall3(int, __syscall_open, const char *, file, + int, flags, __kernel_mode_t, mode) + +int open(const char *file, int oflag, ...) +{ + mode_t mode = 0; + + if (oflag & O_CREAT) { + va_list arg; + va_start(arg, oflag); + mode = va_arg(arg, mode_t); + va_end(arg); + } + + return __syscall_open(file, oflag, mode); +} +#ifndef __LINUXTHREADS_OLD__ +libc_hidden_def(open) +#else +libc_hidden_weak(open) +strong_alias(open,__libc_open) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/open64.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/open64.c new file mode 100644 index 00000000..c1f5400b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/open64.c @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#ifdef __UCLIBC_HAS_THREADS_NATIVE__ +#include +#include +#endif + +#ifdef __UCLIBC_HAS_LFS__ + +#ifndef O_LARGEFILE +# define O_LARGEFILE 0100000 +#endif + +/* Open FILE with access OFLAG. If OFLAG includes O_CREAT, + a third argument is the file protection. */ +int open64 (const char *file, int oflag, ...) +{ + mode_t mode = 0; + + if (oflag & O_CREAT) + { + va_list arg; + va_start (arg, oflag); + mode = va_arg (arg, mode_t); + va_end (arg); + } + +#ifdef __UCLIBC_HAS_THREADS_NATIVE__ + if (SINGLE_THREAD_P) + return INLINE_SYSCALL (open, 3, file, oflag | O_LARGEFILE, mode); + + int oldtype = LIBC_CANCEL_ASYNC (); + + int result = INLINE_SYSCALL (open, 3, file, oflag | O_LARGEFILE, mode); + + LIBC_CANCEL_RESET (oldtype); + + return result; +#else + return open(file, oflag | O_LARGEFILE, mode); +#endif +} +#ifndef __LINUXTHREADS_OLD__ +libc_hidden_def(open64) +#else +libc_hidden_weak(open64) +strong_alias(open64,__libc_open64) +#endif + +#endif /* __UCLIBC_HAS_LFS__ */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/openat.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/openat.c new file mode 100644 index 00000000..8380ec68 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/openat.c @@ -0,0 +1,25 @@ +/* + * openat() for uClibc + * + * Copyright (C) 2009 Analog Devices Inc. + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define openat __xx_openat +#include +#include +#undef openat + +#ifdef __NR_openat +/* The openat() prototype is varargs based, but we don't care about that + * here, so need to provide our own dedicated signature. + */ +extern int openat(int fd, const char *file, int oflag, mode_t mode); +libc_hidden_proto(openat) + +_syscall4(int, openat, int, fd, const char *, file, int, oflag, mode_t, mode) +libc_hidden_def(openat) +#else +/* should add emulation with open() and /proc/self/fd/ ... */ +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/openat64.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/openat64.c new file mode 100644 index 00000000..06a5819d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/openat64.c @@ -0,0 +1,32 @@ +/* + * openat() for uClibc + * + * Copyright (C) 2009 Analog Devices Inc. + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define openat64 __xx_openat +#include +#include +#undef openat64 + +#ifdef __UCLIBC_HAS_LFS__ + +#ifdef __NR_openat +/* The openat() prototype is varargs based, but we don't care about that + * here, so need to provide our own dedicated signature. + */ +extern int openat64(int fd, const char *file, int oflag, mode_t mode); +libc_hidden_proto(openat64) + +int openat64(int fd, const char *file, int oflag, mode_t mode) +{ + return openat(fd, file, oflag | O_LARGEFILE, mode); +} +libc_hidden_def(openat64) +#else +/* should add emulation with open() and /proc/self/fd/ ... */ +#endif + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/pause.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/pause.c new file mode 100644 index 00000000..ab16fa73 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/pause.c @@ -0,0 +1,41 @@ +/* vi: set sw=4 ts=4: */ +/* + * pause() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define __UCLIBC_HIDE_DEPRECATED__ +#include +#include + +#ifdef __UCLIBC_HAS_THREADS_NATIVE__ +#include +#endif + +#include + +/* Suspend the process until a signal arrives. + This always returns -1 and sets errno to EINTR. */ +extern __typeof(pause) __libc_pause; +int +__libc_pause (void) +{ + sigset_t set; + + /*__sigemptyset (&set); - why? */ + sigprocmask (SIG_BLOCK, NULL, &set); + + /* pause is a cancellation point, but so is sigsuspend. + So no need for anything special here. */ + + return sigsuspend (&set); +} +weak_alias (__libc_pause, pause) + +#ifdef __UCLIBC_HAS_THREADS_NATIVE__ +LIBC_CANCEL_HANDLED (); /* sigsuspend handles our cancellation. */ +#endif + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/personality.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/personality.c new file mode 100644 index 00000000..fa304de0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/personality.c @@ -0,0 +1,12 @@ +/* vi: set sw=4 ts=4: */ +/* + * personality() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +_syscall1(int, personality, unsigned long int, __persona) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/pipe.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/pipe.c new file mode 100644 index 00000000..8eae27ca --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/pipe.c @@ -0,0 +1,15 @@ +/* vi: set sw=4 ts=4: */ +/* + * pipe() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + + +_syscall1(int, pipe, int *, filedes) +libc_hidden_def(pipe) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/pivot_root.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/pivot_root.c new file mode 100644 index 00000000..3e970590 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/pivot_root.c @@ -0,0 +1,21 @@ +/* vi: set sw=4 ts=4: */ +/* + * pivot_root() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +int pivot_root(const char *new_root, const char *put_old); +#ifdef __NR_pivot_root +_syscall2(int, pivot_root, const char *, new_root, const char *, put_old) +#else +int pivot_root(const char *new_root, const char *put_old) +{ + __set_errno(ENOSYS); + return -1; +} +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/poll.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/poll.c new file mode 100644 index 00000000..3895e0da --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/poll.c @@ -0,0 +1,230 @@ +/* Copyright (C) 1994,1996,1997,1998,1999,2001,2002 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +#ifdef __UCLIBC_HAS_THREADS_NATIVE__ +#include +#else +#define SINGLE_THREAD_P 1 +#endif + +libc_hidden_proto(poll) + +#if defined __ASSUME_POLL_SYSCALL && defined __NR_poll + +#define __NR___syscall_poll __NR_poll +static inline _syscall3(int, __syscall_poll, struct pollfd *, fds, + unsigned long int, nfds, int, timeout); + +int poll(struct pollfd *fds, nfds_t nfds, int timeout) +{ + if (SINGLE_THREAD_P) + return __syscall_poll(fds, nfds, timeout); + +#ifdef __UCLIBC_HAS_THREADS_NATIVE__ + int oldtype = LIBC_CANCEL_ASYNC (); + int result = __syscall_poll(fds, nfds, timeout); + LIBC_CANCEL_RESET (oldtype); + return result; +#endif +} +#else /* !__NR_poll */ + +#include +#include +#include +#include +#include +#include +#include + +libc_hidden_proto(getdtablesize) +libc_hidden_proto(select) + +/* uClinux 2.0 doesn't have poll, emulate it using select */ + +/* Poll the file descriptors described by the NFDS structures starting at + FDS. If TIMEOUT is nonzero and not -1, allow TIMEOUT milliseconds for + an event to occur; if TIMEOUT is -1, block until an event occurs. + Returns the number of file descriptors with events, zero if timed out, + or -1 for errors. */ + +int poll(struct pollfd *fds, nfds_t nfds, int timeout) +{ + static int max_fd_size; + struct timeval tv; + fd_set *rset, *wset, *xset; + struct pollfd *f; + int ready; + int maxfd = 0; + int bytes; + + if (!max_fd_size) + max_fd_size = getdtablesize (); + + bytes = howmany (max_fd_size, __NFDBITS); + rset = alloca (bytes); + wset = alloca (bytes); + xset = alloca (bytes); + + /* We can't call FD_ZERO, since FD_ZERO only works with sets + of exactly __FD_SETSIZE size. */ + memset (rset, 0, bytes); + memset (wset, 0, bytes); + memset (xset, 0, bytes); + + for (f = fds; f < &fds[nfds]; ++f) + { + f->revents = 0; + if (f->fd >= 0) + { + if (f->fd >= max_fd_size) + { + /* The user provides a file descriptor number which is higher + than the maximum we got from the `getdtablesize' call. + Maybe this is ok so enlarge the arrays. */ + fd_set *nrset, *nwset, *nxset; + int nbytes; + + max_fd_size = roundup (f->fd, __NFDBITS); + nbytes = howmany (max_fd_size, __NFDBITS); + + nrset = alloca (nbytes); + nwset = alloca (nbytes); + nxset = alloca (nbytes); + + memset ((char *) nrset + bytes, 0, nbytes - bytes); + memset ((char *) nwset + bytes, 0, nbytes - bytes); + memset ((char *) nxset + bytes, 0, nbytes - bytes); + + rset = memcpy (nrset, rset, bytes); + wset = memcpy (nwset, wset, bytes); + xset = memcpy (nxset, xset, bytes); + + bytes = nbytes; + } + + if (f->events & POLLIN) + FD_SET (f->fd, rset); + if (f->events & POLLOUT) + FD_SET (f->fd, wset); + if (f->events & POLLPRI) + FD_SET (f->fd, xset); + if (f->fd > maxfd && (f->events & (POLLIN|POLLOUT|POLLPRI))) + maxfd = f->fd; + } + } + + tv.tv_sec = timeout / 1000; + tv.tv_usec = (timeout % 1000) * 1000; + + while (1) + { + ready = select (maxfd + 1, rset, wset, xset, + timeout == -1 ? NULL : &tv); + + /* It might be that one or more of the file descriptors is invalid. + We now try to find and mark them and then try again. */ + if (ready == -1 && errno == EBADF) + { + fd_set *sngl_rset = alloca (bytes); + fd_set *sngl_wset = alloca (bytes); + fd_set *sngl_xset = alloca (bytes); + struct timeval sngl_tv; + + /* Clear the original set. */ + memset (rset, 0, bytes); + memset (wset, 0, bytes); + memset (xset, 0, bytes); + + /* This means we don't wait for input. */ + sngl_tv.tv_sec = 0; + sngl_tv.tv_usec = 0; + + maxfd = -1; + + /* Reset the return value. */ + ready = 0; + + for (f = fds; f < &fds[nfds]; ++f) + if (f->fd != -1 && (f->events & (POLLIN|POLLOUT|POLLPRI)) + && (f->revents & POLLNVAL) == 0) + { + int n; + + memset (sngl_rset, 0, bytes); + memset (sngl_wset, 0, bytes); + memset (sngl_xset, 0, bytes); + + if (f->events & POLLIN) + FD_SET (f->fd, sngl_rset); + if (f->events & POLLOUT) + FD_SET (f->fd, sngl_wset); + if (f->events & POLLPRI) + FD_SET (f->fd, sngl_xset); + + n = select (f->fd + 1, sngl_rset, sngl_wset, sngl_xset, + &sngl_tv); + if (n != -1) + { + /* This descriptor is ok. */ + if (f->events & POLLIN) + FD_SET (f->fd, rset); + if (f->events & POLLOUT) + FD_SET (f->fd, wset); + if (f->events & POLLPRI) + FD_SET (f->fd, xset); + if (f->fd > maxfd) + maxfd = f->fd; + if (n > 0) + /* Count it as being available. */ + ++ready; + } + else if (errno == EBADF) + f->revents |= POLLNVAL; + } + /* Try again. */ + continue; + } + + break; + } + + if (ready > 0) + for (f = fds; f < &fds[nfds]; ++f) + { + if (f->fd >= 0) + { + if (FD_ISSET (f->fd, rset)) + f->revents |= POLLIN; + if (FD_ISSET (f->fd, wset)) + f->revents |= POLLOUT; + if (FD_ISSET (f->fd, xset)) + f->revents |= POLLPRI; + } + } + + return ready; +} + +#endif +libc_hidden_def(poll) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/posix_fadvise.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/posix_fadvise.c new file mode 100644 index 00000000..7c43be95 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/posix_fadvise.c @@ -0,0 +1,36 @@ +/* vi: set sw=4 ts=4: */ +/* + * posix_fadvise() for uClibc + * http://www.opengroup.org/onlinepubs/009695399/functions/posix_fadvise.html + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +#ifdef __NR_fadvise64 +#define __NR_posix_fadvise __NR_fadvise64 +int posix_fadvise(int fd, off_t offset, off_t len, int advice) +{ + INTERNAL_SYSCALL_DECL(err); + int ret = (int) (INTERNAL_SYSCALL(posix_fadvise, err, 5, fd, + __LONG_LONG_PAIR (offset >> 31, offset), len, advice)); + if (INTERNAL_SYSCALL_ERROR_P (ret, err)) + return INTERNAL_SYSCALL_ERRNO (ret, err); + return 0; +} + +#if defined __UCLIBC_HAS_LFS__ && !defined __NR_fadvise64_64 +strong_alias(posix_fadvise,posix_fadvise64) +#endif + +#else +int posix_fadvise(int fd attribute_unused, off_t offset attribute_unused, off_t len attribute_unused, int advice attribute_unused) +{ +#warning This is not correct as far as SUSv3 is concerned. + return ENOSYS; +} +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/posix_fadvise64.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/posix_fadvise64.c new file mode 100644 index 00000000..b53e6432 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/posix_fadvise64.c @@ -0,0 +1,71 @@ +/* vi: set sw=4 ts=4: */ +/* + * posix_fadvise64() for uClibc + * http://www.opengroup.org/onlinepubs/009695399/functions/posix_fadvise.html + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __UCLIBC_HAS_LFS__ +#ifdef __NR_fadvise64_64 + +/* 64 bit implementation is cake ... or more like pie ... */ +#if __WORDSIZE == 64 + +#define __NR_posix_fadvise64 __NR_fadvise64_64 + +int posix_fadvise64(int fd, __off64_t offset, __off64_t len, int advice) +{ + if (len != (off_t) len) + return EOVERFLOW; + INTERNAL_SYSCALL_DECL (err); + int ret = INTERNAL_SYSCALL (posix_fadvise64, err, 5, fd, + __LONG_LONG_PAIR ((long) (offset >> 32), + (long) offset), + (off_t) len, advice); + if (!INTERNAL_SYSCALL_ERROR_P (ret, err)) + return 0; + return INTERNAL_SYSCALL_ERRNO (ret, err); +} + +/* 32 bit implementation is kind of a pita */ +#elif __WORDSIZE == 32 + +int posix_fadvise64(int fd, __off64_t offset, __off64_t len, int advice) +{ + INTERNAL_SYSCALL_DECL (err); + int ret = INTERNAL_SYSCALL (fadvise64_64, err, 6, fd, + __LONG_LONG_PAIR(offset >> 32, offset & 0xffffffff), + __LONG_LONG_PAIR(len >> 32, len & 0xffffffff), + advice); + if (!INTERNAL_SYSCALL_ERROR_P (ret, err)) + return 0; + return INTERNAL_SYSCALL_ERRNO (ret, err); +} + +#else +#error your machine is neither 32 bit or 64 bit ... it must be magical +#endif + +#elif !defined __NR_fadvise64 +/* This is declared as a strong alias in posix_fadvise.c if __NR_fadvise64 + * is defined. + */ +int posix_fadvise64(int fd, __off64_t offset, __off64_t len, int advice) +{ +#warning This is not correct as far as SUSv3 is concerned. + return ENOSYS; +} +#endif /* __NR_fadvise64_64 */ +#endif /* __UCLIBC_HAS_LFS__ */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/ppoll.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/ppoll.c new file mode 100644 index 00000000..09b2b153 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/ppoll.c @@ -0,0 +1,55 @@ +/* Copyright (C) 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2006. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#define __need_NULL +#include + +#if defined __NR_ppoll && defined __UCLIBC_LINUX_SPECIFIC__ +# ifdef __UCLIBC_HAS_THREADS_NATIVE__ +# include +# else +# define SINGLE_THREAD_P 1 +# endif + +int +ppoll(struct pollfd *fds, nfds_t nfds, const struct timespec *timeout, + const sigset_t *sigmask) +{ + /* The Linux kernel can in some situations update the timeout value. + We do not want that so use a local variable. */ + struct timespec tval; + if (timeout != NULL) { + tval = *timeout; + timeout = &tval; + } + if (SINGLE_THREAD_P) + return INLINE_SYSCALL(ppoll, 5, fds, nfds, timeout, sigmask, _NSIG / 8); + +# ifdef __UCLIBC_HAS_THREADS_NATIVE__ + int oldtype = LIBC_CANCEL_ASYNC (); + int result = INLINE_SYSCALL(ppoll, 5, fds, nfds, timeout, sigmask, _NSIG / 8); + LIBC_CANCEL_RESET (oldtype); + return result; +# endif +} +libc_hidden_def(ppoll) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/prctl.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/prctl.c new file mode 100644 index 00000000..39c0d4fb --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/prctl.c @@ -0,0 +1,17 @@ +/* vi: set sw=4 ts=4: */ +/* + * prctl() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +/* psm: including sys/prctl.h would depend on kernel headers */ + +#ifdef __NR_prctl +extern int prctl (int, long, long, long, long); +_syscall5(int, prctl, int, option, long, _a2, long, _a3, long, _a4, long, _a5) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/pread_write.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/pread_write.c new file mode 100644 index 00000000..88e6957a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/pread_write.c @@ -0,0 +1,187 @@ +/* vi: set sw=4 ts=4: */ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ +/* + * Based in part on the files + * ./sysdeps/unix/sysv/linux/pwrite.c, + * ./sysdeps/unix/sysv/linux/pread.c, + * sysdeps/posix/pread.c + * sysdeps/posix/pwrite.c + * from GNU libc 2.2.5, but reworked considerably... + */ + +#include +#include +#include +#include + +extern __typeof(pread) __libc_pread; +extern __typeof(pwrite) __libc_pwrite; +#ifdef __UCLIBC_HAS_LFS__ +extern __typeof(pread64) __libc_pread64; +extern __typeof(pwrite64) __libc_pwrite64; +#endif + +#include + +#ifdef __NR_pread + +# define __NR___syscall_pread __NR_pread +static __inline__ _syscall5(ssize_t, __syscall_pread, int, fd, void *, buf, + size_t, count, off_t, offset_hi, off_t, offset_lo) + +ssize_t __libc_pread(int fd, void *buf, size_t count, off_t offset) +{ + return __syscall_pread(fd, buf, count, __LONG_LONG_PAIR(offset >> 31, offset)); +} +weak_alias(__libc_pread,pread) + +# ifdef __UCLIBC_HAS_LFS__ +ssize_t __libc_pread64(int fd, void *buf, size_t count, off64_t offset) +{ + uint32_t low = offset & 0xffffffff; + uint32_t high = offset >> 32; + return __syscall_pread(fd, buf, count, __LONG_LONG_PAIR(high, low)); +} +weak_alias(__libc_pread64,pread64) +# endif /* __UCLIBC_HAS_LFS__ */ + +#endif /* __NR_pread */ + +#ifdef __NR_pwrite + +# define __NR___syscall_pwrite __NR_pwrite +static __inline__ _syscall5(ssize_t, __syscall_pwrite, int, fd, const void *, buf, + size_t, count, off_t, offset_hi, off_t, offset_lo) + +ssize_t __libc_pwrite(int fd, const void *buf, size_t count, off_t offset) +{ + return __syscall_pwrite(fd, buf, count, __LONG_LONG_PAIR(offset >> 31, offset)); +} +weak_alias(__libc_pwrite,pwrite) + +# ifdef __UCLIBC_HAS_LFS__ +ssize_t __libc_pwrite64(int fd, const void *buf, size_t count, off64_t offset) +{ + uint32_t low = offset & 0xffffffff; + uint32_t high = offset >> 32; + return __syscall_pwrite(fd, buf, count, __LONG_LONG_PAIR(high, low)); +} +weak_alias(__libc_pwrite64,pwrite64) +# endif /* __UCLIBC_HAS_LFS__ */ +#endif /* __NR_pwrite */ + +#if ! defined __NR_pread || ! defined __NR_pwrite + +static ssize_t __fake_pread_write(int fd, void *buf, + size_t count, off_t offset, int do_pwrite) +{ + int save_errno; + ssize_t result; + off_t old_offset; + + /* Since we must not change the file pointer preserve the + * value so that we can restore it later. */ + if ((old_offset=lseek(fd, 0, SEEK_CUR)) == (off_t) -1) + return -1; + + /* Set to wanted position. */ + if (lseek(fd, offset, SEEK_SET) == (off_t) -1) + return -1; + + if (do_pwrite == 1) { + /* Write the data. */ + result = write(fd, buf, count); + } else { + /* Read the data. */ + result = read(fd, buf, count); + } + + /* Now we have to restore the position. If this fails we + * have to return this as an error. */ + save_errno = errno; + if (lseek(fd, old_offset, SEEK_SET) == (off_t) -1) + { + if (result == -1) + __set_errno(save_errno); + return -1; + } + __set_errno(save_errno); + return(result); +} + +# ifdef __UCLIBC_HAS_LFS__ + +static ssize_t __fake_pread_write64(int fd, void *buf, + size_t count, off64_t offset, int do_pwrite) +{ + int save_errno; + ssize_t result; + off64_t old_offset; + + /* Since we must not change the file pointer preserve the + * value so that we can restore it later. */ + if ((old_offset=lseek64(fd, 0, SEEK_CUR)) == (off64_t) -1) + return -1; + + /* Set to wanted position. */ + if (lseek64(fd, offset, SEEK_SET) == (off64_t) -1) + return -1; + + if (do_pwrite == 1) { + /* Write the data. */ + result = write(fd, buf, count); + } else { + /* Read the data. */ + result = read(fd, buf, count); + } + + /* Now we have to restore the position. */ + save_errno = errno; + if (lseek64(fd, old_offset, SEEK_SET) == (off64_t) -1) { + if (result == -1) + __set_errno (save_errno); + return -1; + } + __set_errno (save_errno); + return result; +} +# endif /* __UCLIBC_HAS_LFS__ */ +#endif /* ! defined __NR_pread || ! defined __NR_pwrite */ + +#ifndef __NR_pread +ssize_t __libc_pread(int fd, void *buf, size_t count, off_t offset) +{ + return __fake_pread_write(fd, buf, count, offset, 0); +} +weak_alias(__libc_pread,pread) + +# ifdef __UCLIBC_HAS_LFS__ +ssize_t __libc_pread64(int fd, void *buf, size_t count, off64_t offset) +{ + return __fake_pread_write64(fd, buf, count, offset, 0); +} +weak_alias(__libc_pread64,pread64) +# endif /* __UCLIBC_HAS_LFS__ */ +#endif /* ! __NR_pread */ + +#ifndef __NR_pwrite +ssize_t __libc_pwrite(int fd, const void *buf, size_t count, off_t offset) +{ + /* we won't actually be modifying the buffer, + *just cast it to get rid of warnings */ + return __fake_pread_write(fd, (void*)buf, count, offset, 1); +} +weak_alias(__libc_pwrite,pwrite) + +# ifdef __UCLIBC_HAS_LFS__ +ssize_t __libc_pwrite64(int fd, const void *buf, size_t count, off64_t offset) +{ + return __fake_pread_write64(fd, (void*)buf, count, offset, 1); +} +weak_alias(__libc_pwrite64,pwrite64) +# endif /* __UCLIBC_HAS_LFS__ */ +#endif /* ! __NR_pwrite */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/pselect.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/pselect.c new file mode 100644 index 00000000..7e93537d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/pselect.c @@ -0,0 +1,94 @@ +/* Copyright (C) 1996-1998,2001,2002,2003,2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1996. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include /* For NULL. */ +#include +#include +#ifdef __UCLIBC_HAS_THREADS_NATIVE__ +#include +#endif + +libc_hidden_proto(sigprocmask) +libc_hidden_proto(select) + + +/* Check the first NFDS descriptors each in READFDS (if not NULL) for read + readiness, in WRITEFDS (if not NULL) for write readiness, and in EXCEPTFDS + (if not NULL) for exceptional conditions. If TIMEOUT is not NULL, time out + after waiting the interval specified therein. Additionally set the sigmask + SIGMASK for this call. Returns the number of ready descriptors, or -1 for + errors. */ +#ifdef __UCLIBC_HAS_THREADS_NATIVE__ +static int +__pselect (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, +#else +int +pselect (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, +#endif + const struct timespec *timeout, const sigset_t *sigmask) +{ + struct timeval tval; + int retval; + sigset_t savemask; + + /* Change nanosecond number to microseconds. This might mean losing + precision and therefore the `pselect` should be available. But + for now it is hardly found. */ + if (timeout != NULL) + TIMESPEC_TO_TIMEVAL (&tval, timeout); + + /* The setting and restoring of the signal mask and the select call + should be an atomic operation. This can't be done without kernel + help. */ + if (sigmask != NULL) + sigprocmask (SIG_SETMASK, sigmask, &savemask); + + /* Note the pselect() is a cancellation point. But since we call + select() which itself is a cancellation point we do not have + to do anything here. */ + retval = select (nfds, readfds, writefds, exceptfds, + timeout != NULL ? &tval : NULL); + + if (sigmask != NULL) + sigprocmask (SIG_SETMASK, &savemask, NULL); + + return retval; +} + +#ifdef __UCLIBC_HAS_THREADS_NATIVE__ +int +pselect (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, + const struct timespec *timeout, const sigset_t *sigmask) +{ + if (SINGLE_THREAD_P) + return __pselect (nfds, readfds, writefds, exceptfds, + timeout, sigmask); + + int oldtype = LIBC_CANCEL_ASYNC (); + + int result = __pselect (nfds, readfds, writefds, exceptfds, + timeout, sigmask); + + LIBC_CANCEL_RESET (oldtype); + + return result; +} +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/ptrace.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/ptrace.c new file mode 100644 index 00000000..8b8ebf08 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/ptrace.c @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include + +#if defined __NR_ptrace && defined __USE_BSD && defined __USE_MISC +#define __NR___syscall_ptrace __NR_ptrace + +static __inline__ _syscall4(long, __syscall_ptrace, enum __ptrace_request, request, + __kernel_pid_t, pid, void*, addr, void*, data) + +long int +ptrace (enum __ptrace_request request, ...) +{ + long int res, ret; + va_list ap; + pid_t pid; + void *addr, *data; + + va_start (ap, request); + pid = va_arg (ap, pid_t); + addr = va_arg (ap, void *); + data = va_arg (ap, void *); + va_end (ap); + + if (request > 0 && request < 4) + data = &ret; + + res = __syscall_ptrace(request, pid, addr, data); + if (res >= 0 && request > 0 && request < 4) { + __set_errno(0); + return ret; + } + + return res; +} +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/query_module.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/query_module.c new file mode 100644 index 00000000..0f3d4700 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/query_module.c @@ -0,0 +1,23 @@ +/* vi: set sw=4 ts=4: */ +/* + * query_module() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +int query_module(const char *name attribute_unused, int which attribute_unused, + void *buf attribute_unused, size_t bufsize attribute_unused, size_t * ret attribute_unused); +#ifdef __NR_query_module +_syscall5(int, query_module, const char *, name, int, which, + void *, buf, size_t, bufsize, size_t *, ret) +#elif defined __UCLIBC_HAS_STUBS__ +int query_module(const char *name attribute_unused, int which attribute_unused, + void *buf attribute_unused, size_t bufsize attribute_unused, size_t * ret attribute_unused) +{ + __set_errno(ENOSYS); + return -1; +} +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/quotactl.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/quotactl.c new file mode 100644 index 00000000..edd50925 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/quotactl.c @@ -0,0 +1,16 @@ +/* vi: set sw=4 ts=4: */ +/* + * quotactl() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +#if defined __USE_BSD +#include +_syscall4(int, quotactl, int, cmd, const char *, special, + int, id, caddr_t, addr) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/read.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/read.c new file mode 100644 index 00000000..9e122fc1 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/read.c @@ -0,0 +1,19 @@ +/* vi: set sw=4 ts=4: */ +/* + * read() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +_syscall3(ssize_t, read, int, fd, __ptr_t, buf, size_t, count) +#ifndef __LINUXTHREADS_OLD__ +libc_hidden_def(read) +#else +libc_hidden_weak(read) +strong_alias(read,__libc_read) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/readahead.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/readahead.c new file mode 100644 index 00000000..cd40352d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/readahead.c @@ -0,0 +1,58 @@ +/* Provide kernel hint to read ahead. + Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include + +#ifdef __UCLIBC_HAS_LFS__ + +#include <_lfs_64.h> + +#ifdef __NR_readahead + +# define __NR___readahead __NR_readahead + +# if __WORDSIZE == 64 + +static __inline__ _syscall3(ssize_t, __readahead, int, fd, + off_t, offset, size_t, count) + +ssize_t readahead(int fd, off_t offset, size_t count) +{ + return __readahead(fd, offset, count); +} + +# else + +static __inline__ _syscall4(ssize_t, __readahead, int, fd, + off_t, high_offset, off_t, low_offset, size_t, count) + +ssize_t readahead(int fd, off64_t offset, size_t count) +{ + return __readahead(fd, (off_t) (offset >> 32), (off_t) (offset & 0xffffffff), count); +} + +# endif + +#endif + +#endif /* __UCLIBC_HAS_LFS__ */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/readlink.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/readlink.c new file mode 100644 index 00000000..ef9e8353 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/readlink.c @@ -0,0 +1,14 @@ +/* vi: set sw=4 ts=4: */ +/* + * readlink() for uClibc + * + * Copyright (C) 2000-2007 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +_syscall3(ssize_t, readlink, const char *, path, char *, buf, size_t, bufsiz) +libc_hidden_def(readlink) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/readlinkat.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/readlinkat.c new file mode 100644 index 00000000..d0a98e11 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/readlinkat.c @@ -0,0 +1,16 @@ +/* + * readlinkat() for uClibc + * + * Copyright (C) 2009 Analog Devices Inc. + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +#ifdef __NR_readlinkat +_syscall4(ssize_t, readlinkat, int, fd, const char *, path, char *, buf, size_t, len) +#else +/* should add emulation with readlink() and /proc/self/fd/ ... */ +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/readv.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/readv.c new file mode 100644 index 00000000..fce396d5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/readv.c @@ -0,0 +1,50 @@ +/* vi: set sw=4 ts=4: */ +/* + * readv() for uClibc + * + * Copyright (C) 2006 by Steven J. Hill + * Copyright (C) 2000-2004 by Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +#ifdef __UCLIBC_HAS_THREADS_NATIVE__ +#include + +/* We should deal with kernel which have a smaller UIO_FASTIOV as well + as a very big count. */ +static ssize_t __readv (int fd, const struct iovec *vector, int count) +{ + ssize_t bytes_read; + + bytes_read = INLINE_SYSCALL (readv, 3, fd, vector, count); + + if (bytes_read >= 0 || errno != EINVAL || count <= UIO_FASTIOV) + return bytes_read; + + /* glibc tries again, but we do not. */ + //return __atomic_readv_replacement (fd, vector, count); + + return -1; +} + +ssize_t readv (int fd, const struct iovec *vector, int count) +{ + if (SINGLE_THREAD_P) + return __readv (fd, vector, count); + + int oldtype = LIBC_CANCEL_ASYNC (); + + int result = __readv (fd, vector, count); + + LIBC_CANCEL_RESET (oldtype); + + return result; +} +#else +_syscall3(ssize_t, readv, int, filedes, const struct iovec *, vector, + int, count) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/reboot.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/reboot.c new file mode 100644 index 00000000..ec271b17 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/reboot.c @@ -0,0 +1,17 @@ +/* vi: set sw=4 ts=4: */ +/* + * _reboot() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#define __NR__reboot __NR_reboot +static __inline__ _syscall3(int, _reboot, int, magic, int, magic2, int, flag) +int reboot(int flag) +{ + return (_reboot((int) 0xfee1dead, 672274793, flag)); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/remap_file_pages.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/remap_file_pages.c new file mode 100644 index 00000000..0512b883 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/remap_file_pages.c @@ -0,0 +1,16 @@ +/* + * remap_file_pages() for uClibc + * + * Copyright (C) 2008 Will Newton + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ +#include +#include + +#ifdef __NR_remap_file_pages + +_syscall5(int, remap_file_pages, void *, __start, size_t, __size, + int, __prot, size_t, __pgoff, int, __flags) + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/rename.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/rename.c new file mode 100644 index 00000000..9d8397a8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/rename.c @@ -0,0 +1,24 @@ +/* vi: set sw=4 ts=4: */ +/* + * rename() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include +#include + +#define __NR___syscall_rename __NR_rename +static __inline__ _syscall2(int, __syscall_rename, const char *, oldpath, + const char *, newpath) + +int rename(const char * oldpath, const char * newpath) +{ + return __syscall_rename(oldpath, newpath); +} + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/renameat.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/renameat.c new file mode 100644 index 00000000..a898f7b8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/renameat.c @@ -0,0 +1,16 @@ +/* + * renameat() for uClibc + * + * Copyright (C) 2009 Analog Devices Inc. + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +#ifdef __NR_renameat +_syscall4(int, renameat, int, oldfd, const char *, old, int, newfd, const char *, new) +#else +/* should add emulation with rename() and /proc/self/fd/ ... */ +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/rmdir.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/rmdir.c new file mode 100644 index 00000000..bad66544 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/rmdir.c @@ -0,0 +1,15 @@ +/* vi: set sw=4 ts=4: */ +/* + * rmdir() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + + +_syscall1(int, rmdir, const char *, pathname) +libc_hidden_def(rmdir) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sbrk.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sbrk.c new file mode 100644 index 00000000..4f0a8c40 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sbrk.c @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + + +/* Defined in brk.c. */ +extern void *__curbrk attribute_hidden; + +/* Extend the process's data space by INCREMENT. + If INCREMENT is negative, shrink data space by - INCREMENT. + Return start of new space allocated, or -1 for errors. */ +void * sbrk (intptr_t increment) +{ + void *oldbrk; + + if (__curbrk == NULL) + if (brk (NULL) < 0) /* Initialize the break. */ + return (void *) -1; + + if (increment == 0) + return __curbrk; + + oldbrk = __curbrk; + if (brk (oldbrk + increment) < 0) + return (void *) -1; + + return oldbrk; +} +libc_hidden_def(sbrk) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sched_get_priority_max.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sched_get_priority_max.c new file mode 100644 index 00000000..cf5447ca --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sched_get_priority_max.c @@ -0,0 +1,12 @@ +/* vi: set sw=4 ts=4: */ +/* + * sched_get_priority_max() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +_syscall1(int, sched_get_priority_max, int, policy) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sched_get_priority_min.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sched_get_priority_min.c new file mode 100644 index 00000000..884efed6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sched_get_priority_min.c @@ -0,0 +1,12 @@ +/* vi: set sw=4 ts=4: */ +/* + * sched_get_priority_min() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +_syscall1(int, sched_get_priority_min, int, policy) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sched_getaffinity.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sched_getaffinity.c new file mode 100644 index 00000000..5d5e5b2c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sched_getaffinity.c @@ -0,0 +1,54 @@ +/* Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#ifdef __USE_GNU + +#include +#include +#include + +#include +#include + +#if defined __NR_sched_getaffinity +#define __NR___syscall_sched_getaffinity __NR_sched_getaffinity +static __inline__ _syscall3(int, __syscall_sched_getaffinity, __kernel_pid_t, pid, + size_t, cpusetsize, cpu_set_t *, cpuset) + +int sched_getaffinity(pid_t pid, size_t cpusetsize, cpu_set_t *cpuset) +{ + int res = (__syscall_sched_getaffinity(pid, MIN(INT_MAX, cpusetsize), + cpuset)); + + if (res != -1) { + /* Clean the rest of the memory the kernel didn't do. */ + memset ((char *) cpuset + res, '\0', cpusetsize - res); + + res = 0; + } + return res; +} +#elif defined __UCLIBC_HAS_STUBS__ +int sched_getaffinity(pid_t pid, size_t cpusetsize, cpu_set_t *cpuset) +{ + __set_errno(ENOSYS); + return -1; +} +#endif +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sched_getparam.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sched_getparam.c new file mode 100644 index 00000000..eb17e255 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sched_getparam.c @@ -0,0 +1,21 @@ +/* vi: set sw=4 ts=4: */ +/* + * sched_getparam() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include + +#define __NR___syscall_sched_getparam __NR_sched_getparam +static __inline__ _syscall2(int, __syscall_sched_getparam, + __kernel_pid_t, pid, struct sched_param *, p) + +int sched_getparam(pid_t pid, struct sched_param *p) +{ + return (__syscall_sched_getparam(pid, p)); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sched_getscheduler.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sched_getscheduler.c new file mode 100644 index 00000000..e657abd7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sched_getscheduler.c @@ -0,0 +1,20 @@ +/* vi: set sw=4 ts=4: */ +/* + * sched_getscheduler() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include + +#define __NR___syscall_sched_getscheduler __NR_sched_getscheduler +static __inline__ _syscall1(int, __syscall_sched_getscheduler, __kernel_pid_t, pid) + +int sched_getscheduler(pid_t pid) +{ + return (__syscall_sched_getscheduler(pid)); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sched_rr_get_interval.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sched_rr_get_interval.c new file mode 100644 index 00000000..31d620fd --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sched_rr_get_interval.c @@ -0,0 +1,21 @@ +/* vi: set sw=4 ts=4: */ +/* + * sched_rr_get_interval() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include + +#define __NR___syscall_sched_rr_get_interval __NR_sched_rr_get_interval +static __inline__ _syscall2(int, __syscall_sched_rr_get_interval, + __kernel_pid_t, pid, struct timespec *, tp) + +int sched_rr_get_interval(pid_t pid, struct timespec *tp) +{ + return (__syscall_sched_rr_get_interval(pid, tp)); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sched_setaffinity.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sched_setaffinity.c new file mode 100644 index 00000000..1a0f55f7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sched_setaffinity.c @@ -0,0 +1,85 @@ +/* Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#ifdef __USE_GNU + +#include +#include +#include +#include +#include +#include +#include + +#if defined __NR_sched_setaffinity + +#define __NR___syscall_sched_setaffinity __NR_sched_setaffinity +static __inline__ _syscall3(int, __syscall_sched_setaffinity, __kernel_pid_t, pid, + size_t, cpusetsize, cpu_set_t *, cpuset) + +static size_t __kernel_cpumask_size; + +int sched_setaffinity(pid_t pid, size_t cpusetsize, const cpu_set_t *cpuset) +{ + size_t cnt; + if (unlikely (__kernel_cpumask_size == 0)) { + INTERNAL_SYSCALL_DECL (err); + int res; + size_t psize = 128; + void *p = alloca (psize); + + while (res = INTERNAL_SYSCALL (sched_getaffinity, err, 3, getpid (), + psize, p), + INTERNAL_SYSCALL_ERROR_P (res, err) + && INTERNAL_SYSCALL_ERRNO (res, err) == EINVAL) + p = extend_alloca (p, psize, 2 * psize); + + if (res == 0 || INTERNAL_SYSCALL_ERROR_P (res, err)) { + __set_errno (INTERNAL_SYSCALL_ERRNO (res, err)); + return -1; + } + + __kernel_cpumask_size = res; + } + + /* We now know the size of the kernel cpumask_t. Make sure the user + does not request to set a bit beyond that. */ + for (cnt = __kernel_cpumask_size; cnt < cpusetsize; ++cnt) + if (((char *) cpuset)[cnt] != '\0') { + /* Found a nonzero byte. This means the user request cannot be + fulfilled. */ + __set_errno (EINVAL); + return -1; + } + + return INLINE_SYSCALL (sched_setaffinity, 3, pid, cpusetsize, cpuset); +} +#else +#define ___HAVE_NO_sched_setaffinity +#endif + +#if defined ___HAVE_NO_sched_setaffinity && defined __UCLIBC_HAS_STUBS__ +int sched_setaffinity(pid_t pid, size_t cpusetsize, const cpu_set_t *cpuset) +{ + __set_errno(ENOSYS); + return -1; +} +#endif + +#endif /* __USE_GNU */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sched_setparam.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sched_setparam.c new file mode 100644 index 00000000..0f5f74f0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sched_setparam.c @@ -0,0 +1,21 @@ +/* vi: set sw=4 ts=4: */ +/* + * sched_setparam() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include + +#define __NR___syscall_sched_setparam __NR_sched_setparam +static __inline__ _syscall2(int, __syscall_sched_setparam, + __kernel_pid_t, pid, const struct sched_param *, p) + +int sched_setparam(pid_t pid, const struct sched_param *p) +{ + return (__syscall_sched_setparam(pid, p)); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sched_setscheduler.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sched_setscheduler.c new file mode 100644 index 00000000..0af498fc --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sched_setscheduler.c @@ -0,0 +1,21 @@ +/* vi: set sw=4 ts=4: */ +/* + * sched_setscheduler() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include + +#define __NR___syscall_sched_setscheduler __NR_sched_setscheduler +static __inline__ _syscall3(int, __syscall_sched_setscheduler, + __kernel_pid_t, pid, int, policy, const struct sched_param *, p) + +int sched_setscheduler(pid_t pid, int policy, const struct sched_param *p) +{ + return (__syscall_sched_setscheduler(pid, policy, p)); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sched_yield.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sched_yield.c new file mode 100644 index 00000000..2d584bdc --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sched_yield.c @@ -0,0 +1,12 @@ +/* vi: set sw=4 ts=4: */ +/* + * sched_yield() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +_syscall0(int, sched_yield) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/select.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/select.c new file mode 100644 index 00000000..029fb08a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/select.c @@ -0,0 +1,94 @@ +/* vi: set sw=4 ts=4: */ +/* + * select() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include + +#ifdef __UCLIBC_HAS_THREADS_NATIVE__ +#include +#else +#define SINGLE_THREAD_P 1 +#endif + +#define USEC_PER_SEC 1000000L + +extern __typeof(select) __libc_select; + +#if !defined(__NR__newselect) && !defined(__NR_select) && defined __USE_XOPEN2K +# define __NR___libc_pselect6 __NR_pselect6 +static _syscall6(int, __libc_pselect6, int, n, fd_set *, readfds, fd_set *, writefds, + fd_set *, exceptfds, const struct timespec *, timeout, + const sigset_t *, sigmask) + +int __libc_select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, + struct timeval *timeout) +{ + struct timespec _ts, *ts = 0; + if (timeout) { + uint32_t usec; + _ts.tv_sec = timeout->tv_sec; + + /* GNU extension: allow for timespec values where the sub-sec + * field is equal to or more than 1 second. The kernel will + * reject this on us, so take care of the time shift ourself. + * Some applications (like readline and linphone) do this. + * See 'clarification on select() type calls and invalid timeouts' + * on the POSIX general list for more information. + */ + usec = timeout->tv_usec; + if (usec >= USEC_PER_SEC) { + _ts.tv_sec += usec / USEC_PER_SEC; + usec %= USEC_PER_SEC; + } + _ts.tv_nsec = usec * 1000; + + ts = &_ts; + } + + if (SINGLE_THREAD_P) + return __libc_pselect6(n, readfds, writefds, exceptfds, ts, 0); +#ifdef __UCLIBC_HAS_THREADS_NATIVE__ + int oldtype = LIBC_CANCEL_ASYNC (); + int result = __libc_pselect6(n, readfds, writefds, exceptfds, ts, 0); + LIBC_CANCEL_RESET (oldtype); + return result; +#endif + +} + +#else + +#ifdef __NR__newselect +# define __NR___syscall_select __NR__newselect +#else +# define __NR___syscall_select __NR_select +#endif + +static _syscall5(int, __syscall_select, int, n, fd_set *, readfds, + fd_set *, writefds, fd_set *, exceptfds, struct timeval *, timeout); + +int __libc_select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, + struct timeval *timeout) +{ + if (SINGLE_THREAD_P) + return __syscall_select(n, readfds, writefds, exceptfds, timeout); + +#ifdef __UCLIBC_HAS_THREADS_NATIVE__ + int oldtype = LIBC_CANCEL_ASYNC (); + int result = __syscall_select(n, readfds, writefds, exceptfds, timeout); + LIBC_CANCEL_RESET (oldtype); + return result; +#endif +} + +#endif + +weak_alias(__libc_select,select) +libc_hidden_weak(select) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sendfile.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sendfile.c new file mode 100644 index 00000000..89bab9f3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sendfile.c @@ -0,0 +1,23 @@ +/* vi: set sw=4 ts=4: */ +/* + * sendfile() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include + +#ifdef __NR_sendfile + +_syscall4(ssize_t, sendfile, int, out_fd, int, in_fd, __off_t *, offset, + size_t, count) + +#if ! defined __NR_sendfile64 && defined __UCLIBC_HAS_LFS__ +strong_alias(sendfile,sendfile64) +#endif + +#endif /* __NR_sendfile */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sendfile64.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sendfile64.c new file mode 100644 index 00000000..fc5155fd --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sendfile64.c @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ +/* sendfile64 syscall. Copes with 64 bit and 32 bit machines + * and on 32 bit machines this sends things into the kernel as + * two 32-bit arguments (high and low 32 bits of length) that + * are ordered based on endianess. It turns out endian.h has + * just the macro we need to order things, __LONG_LONG_PAIR. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined __UCLIBC_HAS_LFS__ && defined __NR_sendfile64 +_syscall4(ssize_t,sendfile64, int, out_fd, int, in_fd, __off64_t *, offset, size_t, count) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/setdomainname.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/setdomainname.c new file mode 100644 index 00000000..6b768b7f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/setdomainname.c @@ -0,0 +1,14 @@ +/* vi: set sw=4 ts=4: */ +/* + * setdomainname() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#if defined __USE_BSD || (defined __USE_XOPEN && !defined __USE_UNIX98) +_syscall2(int, setdomainname, const char *, name, size_t, len) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/setegid.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/setegid.c new file mode 100644 index 00000000..30329bc5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/setegid.c @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include +#include +#include + +int setegid(gid_t gid) +{ + int result; + + if (gid == (gid_t) ~0) + { + __set_errno (EINVAL); + return -1; + } + +#if (defined __NR_setresgid || defined __NR_setresgid32) && defined __USE_GNU + result = setresgid(-1, gid, -1); + if (result == -1 && errno == ENOSYS) + /* Will also set the saved group ID if egid != gid, + * making it impossible to switch back...*/ +#endif + result = setregid(-1, gid); + + return result; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/seteuid.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/seteuid.c new file mode 100644 index 00000000..3e1611d0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/seteuid.c @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include +#include +#include + +#if !defined __UCLIBC_LINUX_SPECIFIC__ +#undef __NR_setresuid +#undef __NR_setresuid32 +#endif + +int seteuid(uid_t uid) +{ + int result; + + if (uid == (uid_t) ~0) + { + __set_errno (EINVAL); + return -1; + } + +#if (defined __NR_setresuid || defined __NR_setresuid32) && defined __USE_GNU + result = setresuid(-1, uid, -1); + if (result == -1 && errno == ENOSYS) + /* Will also set the saved user ID if euid != uid, + * making it impossible to switch back...*/ +#endif + result = setreuid(-1, uid); + + return result; +} +libc_hidden_def(seteuid) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/setfsgid.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/setfsgid.c new file mode 100644 index 00000000..78d35dd5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/setfsgid.c @@ -0,0 +1,35 @@ +/* vi: set sw=4 ts=4: */ +/* + * setfsgid() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include + +#if (__WORDSIZE == 32 && defined(__NR_setfsgid32)) || __WORDSIZE == 64 +# ifdef __NR_setfsgid32 +# undef __NR_setfsgid +# define __NR_setfsgid __NR_setfsgid32 +# endif + +_syscall1(int, setfsgid, gid_t, gid) + +#else + +# define __NR___syscall_setfsgid __NR_setfsgid +static __inline__ _syscall1(int, __syscall_setfsgid, __kernel_gid_t, gid) + +int setfsgid(gid_t gid) +{ + if (gid != (gid_t) ((__kernel_gid_t) gid)) { + __set_errno(EINVAL); + return -1; + } + return (__syscall_setfsgid(gid)); +} +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/setfsuid.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/setfsuid.c new file mode 100644 index 00000000..a7372bd2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/setfsuid.c @@ -0,0 +1,35 @@ +/* vi: set sw=4 ts=4: */ +/* + * setfsuid() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include + +#if (__WORDSIZE == 32 && defined(__NR_setfsuid32)) || __WORDSIZE == 64 +# ifdef __NR_setfsuid32 +# undef __NR_setfsuid +# define __NR_setfsuid __NR_setfsuid32 +# endif + +_syscall1(int, setfsuid, uid_t, uid) + +#else + +# define __NR___syscall_setfsuid __NR_setfsuid +static __inline__ _syscall1(int, __syscall_setfsuid, __kernel_uid_t, uid) + +int setfsuid(uid_t uid) +{ + if (uid != (uid_t) ((__kernel_uid_t) uid)) { + __set_errno(EINVAL); + return -1; + } + return (__syscall_setfsuid(uid)); +} +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/setgid.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/setgid.c new file mode 100644 index 00000000..88341ba8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/setgid.c @@ -0,0 +1,35 @@ +/* vi: set sw=4 ts=4: */ +/* + * setgid() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include + +#if (__WORDSIZE == 32 && defined(__NR_setgid32)) || __WORDSIZE == 64 +# ifdef __NR_setgid32 +# undef __NR_setgid +# define __NR_setgid __NR_setgid32 +# endif + +_syscall1(int, setgid, gid_t, gid) + +#else + +# define __NR___syscall_setgid __NR_setgid +static __inline__ _syscall1(int, __syscall_setgid, __kernel_gid_t, gid) + +int setgid(gid_t gid) +{ + if (gid == (gid_t) ~ 0 || gid != (gid_t) ((__kernel_gid_t) gid)) { + __set_errno(EINVAL); + return -1; + } + return (__syscall_setgid(gid)); +} +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/setgroups.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/setgroups.c new file mode 100644 index 00000000..72c98783 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/setgroups.c @@ -0,0 +1,64 @@ +/* vi: set sw=4 ts=4: */ +/* + * setgroups() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include + +#ifdef __USE_BSD + + +#if defined(__NR_setgroups32) +# undef __NR_setgroups +# define __NR_setgroups __NR_setgroups32 +_syscall2(int, setgroups, size_t, size, const gid_t *, list) + +#elif __WORDSIZE == 64 +_syscall2(int, setgroups, size_t, size, const gid_t *, list) + +#else + + +#define __NR___syscall_setgroups __NR_setgroups +static __inline__ _syscall2(int, __syscall_setgroups, + size_t, size, const __kernel_gid_t *, list) + +int setgroups(size_t size, const gid_t *groups) +{ + if (size > (size_t) sysconf(_SC_NGROUPS_MAX)) { +ret_error: + __set_errno(EINVAL); + return -1; + } else { + size_t i; + __kernel_gid_t *kernel_groups = NULL; + + if (size) { + kernel_groups = (__kernel_gid_t *)malloc(sizeof(*kernel_groups) * size); + if (kernel_groups == NULL) + goto ret_error; + } + + for (i = 0; i < size; i++) { + kernel_groups[i] = (groups)[i]; + if (groups[i] != (gid_t) ((__kernel_gid_t) groups[i])) { + goto ret_error; + } + } + + i = __syscall_setgroups(size, kernel_groups); + free(kernel_groups); + return i; + } +} +#endif + +libc_hidden_def(setgroups) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sethostname.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sethostname.c new file mode 100644 index 00000000..1ceb2a08 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sethostname.c @@ -0,0 +1,14 @@ +/* vi: set sw=4 ts=4: */ +/* + * sethostname() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#if defined __USE_BSD || (defined __USE_XOPEN && !defined __USE_UNIX98) +_syscall2(int, sethostname, const char *, name, size_t, len) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/setitimer.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/setitimer.c new file mode 100644 index 00000000..427ff1ef --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/setitimer.c @@ -0,0 +1,16 @@ +/* vi: set sw=4 ts=4: */ +/* + * setitimer() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + + +_syscall3(int, setitimer, __itimer_which_t, which, + const struct itimerval *, new, struct itimerval *, old) +libc_hidden_def(setitimer) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/setpgid.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/setpgid.c new file mode 100644 index 00000000..0410c64f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/setpgid.c @@ -0,0 +1,25 @@ +/* vi: set sw=4 ts=4: */ +/* + * setpgid() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +#if defined __USE_UNIX98 || defined __USE_SVID +#include + + +#define __NR___syscall_setpgid __NR_setpgid +static __inline__ _syscall2(int, __syscall_setpgid, + __kernel_pid_t, pid, __kernel_pid_t, pgid) + +int setpgid(pid_t pid, pid_t pgid) +{ + return (__syscall_setpgid(pid, pgid)); +} +libc_hidden_def(setpgid) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/setpgrp.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/setpgrp.c new file mode 100644 index 00000000..1a82ac88 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/setpgrp.c @@ -0,0 +1,14 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + + +int setpgrp(void) +{ + return setpgid(0,0); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/setpriority.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/setpriority.c new file mode 100644 index 00000000..05d5dd99 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/setpriority.c @@ -0,0 +1,15 @@ +/* vi: set sw=4 ts=4: */ +/* + * setpriority() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + + +_syscall3(int, setpriority, __priority_which_t, which, id_t, who, int, prio) +libc_hidden_def(setpriority) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/setregid.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/setregid.c new file mode 100644 index 00000000..15d590a6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/setregid.c @@ -0,0 +1,40 @@ +/* vi: set sw=4 ts=4: */ +/* + * setregid() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include + + +#if (__WORDSIZE == 32 && defined(__NR_setregid32)) || __WORDSIZE == 64 +# ifdef __NR_setregid32 +# undef __NR_setregid +# define __NR_setregid __NR_setregid32 +# endif + +_syscall2(int, setregid, gid_t, rgid, gid_t, egid) + +#else + +# define __NR___syscall_setregid __NR_setregid +static __inline__ _syscall2(int, __syscall_setregid, + __kernel_gid_t, rgid, __kernel_gid_t, egid) + +int setregid(gid_t rgid, gid_t egid) +{ + if (((rgid + 1) > (gid_t) ((__kernel_gid_t) - 1U)) + || ((egid + 1) > (gid_t) ((__kernel_gid_t) - 1U))) { + __set_errno(EINVAL); + return -1; + } + return (__syscall_setregid(rgid, egid)); +} +#endif + +libc_hidden_def(setregid) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/setresgid.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/setresgid.c new file mode 100644 index 00000000..95decc29 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/setresgid.c @@ -0,0 +1,41 @@ +/* vi: set sw=4 ts=4: */ +/* + * setresgid() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#ifdef __USE_GNU +#include + +#if defined(__NR_setresgid32) +# undef __NR_setresgid +# define __NR_setresgid __NR_setresgid32 + +_syscall3(int, setresgid, gid_t, rgid, gid_t, egid, gid_t, sgid) +libc_hidden_def(setresgid) + +#elif defined(__NR_setresgid) + +# define __NR___syscall_setresgid __NR_setresgid +static __inline__ _syscall3(int, __syscall_setresgid, + __kernel_gid_t, rgid, __kernel_gid_t, egid, __kernel_gid_t, sgid) + +int setresgid(gid_t rgid, gid_t egid, gid_t sgid) +{ + if (((rgid + 1) > (gid_t) ((__kernel_gid_t) - 1U)) + || ((egid + 1) > (gid_t) ((__kernel_gid_t) - 1U)) + || ((sgid + 1) > (gid_t) ((__kernel_gid_t) - 1U))) { + __set_errno(EINVAL); + return -1; + } + return (__syscall_setresgid(rgid, egid, sgid)); +} +libc_hidden_def(setresgid) + +#endif + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/setresuid.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/setresuid.c new file mode 100644 index 00000000..022ccfe6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/setresuid.c @@ -0,0 +1,41 @@ +/* vi: set sw=4 ts=4: */ +/* + * setresuid() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#if defined __USE_GNU && defined __UCLIBC_LINUX_SPECIFIC__ +#include + +#if defined(__NR_setresuid32) +# undef __NR_setresuid +# define __NR_setresuid __NR_setresuid32 + +_syscall3(int, setresuid, uid_t, ruid, uid_t, euid, uid_t, suid) +libc_hidden_def(setresuid) + +#elif defined(__NR_setresuid) + +# define __NR___syscall_setresuid __NR_setresuid +static __inline__ _syscall3(int, __syscall_setresuid, + __kernel_uid_t, rgid, __kernel_uid_t, egid, __kernel_uid_t, sgid) + +int setresuid(uid_t ruid, uid_t euid, uid_t suid) +{ + if (((ruid + 1) > (uid_t) ((__kernel_uid_t) - 1U)) + || ((euid + 1) > (uid_t) ((__kernel_uid_t) - 1U)) + || ((suid + 1) > (uid_t) ((__kernel_uid_t) - 1U))) { + __set_errno(EINVAL); + return -1; + } + return (__syscall_setresuid(ruid, euid, suid)); +} +libc_hidden_def(setresuid) + +#endif + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/setreuid.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/setreuid.c new file mode 100644 index 00000000..a9eea6dc --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/setreuid.c @@ -0,0 +1,40 @@ +/* vi: set sw=4 ts=4: */ +/* + * setreuid() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include + + +#if (__WORDSIZE == 32 && defined(__NR_setreuid32)) || __WORDSIZE == 64 +# ifdef __NR_setreuid32 +# undef __NR_setreuid +# define __NR_setreuid __NR_setreuid32 +# endif + +_syscall2(int, setreuid, uid_t, ruid, uid_t, euid) + +#else + +# define __NR___syscall_setreuid __NR_setreuid +static __inline__ _syscall2(int, __syscall_setreuid, + __kernel_uid_t, ruid, __kernel_uid_t, euid) + +int setreuid(uid_t ruid, uid_t euid) +{ + if (((ruid + 1) > (uid_t) ((__kernel_uid_t) - 1U)) + || ((euid + 1) > (uid_t) ((__kernel_uid_t) - 1U))) { + __set_errno(EINVAL); + return -1; + } + return (__syscall_setreuid(ruid, euid)); +} +#endif + +libc_hidden_def(setreuid) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/setrlimit.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/setrlimit.c new file mode 100644 index 00000000..ed773f7a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/setrlimit.c @@ -0,0 +1,69 @@ +/* vi: set sw=4 ts=4: */ +/* + * setrlimit() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define setrlimit64 __hide_setrlimit64 +#include +#include +#include +#undef setrlimit64 + + +/* Only wrap setrlimit if the new usetrlimit is not present and setrlimit sucks */ + +#if defined(__NR_usetrlimit) + +/* just call usetrlimit() */ +# define __NR___syscall_usetrlimit __NR_usetrlimit +static __always_inline +_syscall2(int, __syscall_usetrlimit, enum __rlimit_resource, resource, + const struct rlimit *, rlim) +int setrlimit(__rlimit_resource_t resource, struct rlimit *rlimits) +{ + return (__syscall_usetrlimit(resource, rlimits)); +} + +#elif !defined(__UCLIBC_HANDLE_OLDER_RLIMIT__) + +/* We don't need to wrap setrlimit() */ +_syscall2(int, setrlimit, __rlimit_resource_t, resource, + const struct rlimit *, rlim) + +#else + +/* we have to handle old style setrlimit() */ +# define __NR___syscall_setrlimit __NR_setrlimit +static __always_inline +_syscall2(int, __syscall_setrlimit, int, resource, const struct rlimit *, rlim) + +int setrlimit(__rlimit_resource_t resource, const struct rlimit *rlimits) +{ + struct rlimit rlimits_small; + + if (rlimits == NULL) { + __set_errno(EINVAL); + return -1; + } + + /* We might have to correct the limits values. Since the old values + * were signed the new values might be too large. */ +# define RMIN(x, y) ((x) < (y) ? (x) : (y)) + rlimits_small.rlim_cur = RMIN((unsigned long int) rlimits->rlim_cur, + RLIM_INFINITY >> 1); + rlimits_small.rlim_max = RMIN((unsigned long int) rlimits->rlim_max, + RLIM_INFINITY >> 1); +#undef RMIN + return (__syscall_setrlimit(resource, &rlimits_small)); +} +#endif + +libc_hidden_def(setrlimit) + +#if defined __UCLIBC_HAS_LFS__ && __WORDSIZE == 64 +strong_alias(setrlimit, setrlimit64) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/setrlimit64.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/setrlimit64.c new file mode 100644 index 00000000..8705c6f5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/setrlimit64.c @@ -0,0 +1,48 @@ +/* Copyright (C) 1991,1995,1996,1997,1998,2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <_lfs_64.h> + +#include +#include +#include + +/* the regular setrlimit will work just fine for 64bit users */ + +#if defined __UCLIBC_HAS_LFS__ && __WORDSIZE == 32 + + +/* Set the soft and hard limits for RESOURCE to *RLIMITS. + Only the super-user can increase hard limits. + Return 0 if successful, -1 if not (and sets errno). */ +int setrlimit64 (__rlimit_resource_t resource, const struct rlimit64 *rlimits) +{ + struct rlimit rlimits32; + + if (rlimits->rlim_cur >= RLIM_INFINITY) + rlimits32.rlim_cur = RLIM_INFINITY; + else + rlimits32.rlim_cur = rlimits->rlim_cur; + if (rlimits->rlim_max >= RLIM_INFINITY) + rlimits32.rlim_max = RLIM_INFINITY; + else + rlimits32.rlim_max = rlimits->rlim_max; + + return setrlimit (resource, &rlimits32); +} +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/setsid.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/setsid.c new file mode 100644 index 00000000..4ca95fcc --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/setsid.c @@ -0,0 +1,15 @@ +/* vi: set sw=4 ts=4: */ +/* + * setsid() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + + +_syscall0(pid_t, setsid) +libc_hidden_def(setsid) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/settimeofday.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/settimeofday.c new file mode 100644 index 00000000..7e508aea --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/settimeofday.c @@ -0,0 +1,19 @@ +/* vi: set sw=4 ts=4: */ +/* + * settimeofday() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +#ifdef __USE_BSD + + +_syscall2(int, settimeofday, const struct timeval *, tv, + const struct timezone *, tz) +libc_hidden_def(settimeofday) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/setuid.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/setuid.c new file mode 100644 index 00000000..7fd8c65e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/setuid.c @@ -0,0 +1,35 @@ +/* vi: set sw=4 ts=4: */ +/* + * setuid() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include + +#if (__WORDSIZE == 32 && defined(__NR_setuid32)) || __WORDSIZE == 64 +# ifdef __NR_setuid32 +# undef __NR_setuid +# define __NR_setuid __NR_setuid32 +# endif + +_syscall1(int, setuid, uid_t, uid) + +#else + +# define __NR___syscall_setuid __NR_setuid +static __inline__ _syscall1(int, __syscall_setuid, __kernel_uid_t, uid) + +int setuid(uid_t uid) +{ + if (uid == (uid_t) ~ 0 || uid != (uid_t) ((__kernel_uid_t) uid)) { + __set_errno(EINVAL); + return -1; + } + return (__syscall_setuid(uid)); +} +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sigaltstack.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sigaltstack.c new file mode 100644 index 00000000..964e16f9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sigaltstack.c @@ -0,0 +1,17 @@ +/* vi: set sw=4 ts=4: */ +/* + * sigaltstack() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +#if defined __NR_sigaltstack && (defined __USE_BSD || defined __USE_UNIX98) + +_syscall2(int, sigaltstack, const struct sigaltstack *, ss, + struct sigaltstack *, oss) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/signalfd.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/signalfd.c new file mode 100644 index 00000000..3d76e04c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/signalfd.c @@ -0,0 +1,41 @@ +/* vi: set sw=4 ts=4: */ +/* + * signalfd() for uClibc + * + * Copyright (C) 2008 Bernhard Reutner-Fischer + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include + +#if defined __NR_signalfd4 +#define __NR___syscall_signalfd4 __NR_signalfd4 +static __inline__ _syscall4(int, __syscall_signalfd4, int, fd, + const sigset_t *, mask, size_t, sizemask, int, flags) +#elif defined __NR_signalfd +#define __NR___syscall_signalfd __NR_signalfd +static __inline__ _syscall3(int, __syscall_signalfd, int, fd, + const sigset_t *, mask, size_t, sizemask) +#endif + +#if defined __NR_signalfd4 || defined __NR_signalfd \ + || defined __UCLIBC_HAS_STUBS__ +int signalfd (int fd, const sigset_t *mask, int flags) +{ +#if defined __NR___syscall_signalfd4 + return __syscall_signalfd4(fd, mask, _NSIG / 8, flags); +#elif defined __NR___syscall_signalfd + if (flags != 0) { + __set_errno(EINVAL); + return -1; + } + return __syscall_signalfd(fd, mask, _NSIG / 8); +#elif defined __UCLIBC_HAS_STUBS__ + __set_errno(ENOSYS); + return -1; +#endif +} +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sigpending.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sigpending.c new file mode 100644 index 00000000..8fa2a512 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sigpending.c @@ -0,0 +1,27 @@ +/* vi: set sw=4 ts=4: */ +/* + * sigpending() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +#if defined __USE_POSIX +#include +#undef sigpending + +#ifdef __NR_rt_sigpending +# define __NR___rt_sigpending __NR_rt_sigpending +static __inline__ _syscall2(int, __rt_sigpending, sigset_t *, set, size_t, size) + +int sigpending(sigset_t * set) +{ + return __rt_sigpending(set, _NSIG / 8); +} +#else +_syscall1(int, sigpending, sigset_t *, set) +#endif +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sigprocmask.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sigprocmask.c new file mode 100644 index 00000000..011d7b36 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sigprocmask.c @@ -0,0 +1,89 @@ +/* vi: set sw=4 ts=4: */ +/* + * sigprocmask() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +#if defined __USE_POSIX +#include + +#undef sigprocmask + +libc_hidden_proto(sigprocmask) + +#ifdef __NR_rt_sigprocmask + +# define __NR___rt_sigprocmask __NR_rt_sigprocmask +static __always_inline +_syscall4(int, __rt_sigprocmask, int, how, const sigset_t *, set, + sigset_t *, oldset, size_t, size) + +int sigprocmask(int how, const sigset_t * set, sigset_t * oldset) +{ +#ifdef SIGCANCEL + sigset_t local_newmask; + + /* + * The only thing we have to make sure here is that SIGCANCEL and + * SIGSETXID are not blocked. + */ + if (set != NULL && (__builtin_expect (__sigismember (set, SIGCANCEL), 0) +# ifdef SIGSETXID + || __builtin_expect (__sigismember (set, SIGSETXID), 0) +# endif + )) + { + local_newmask = *set; + __sigdelset (&local_newmask, SIGCANCEL); +# ifdef SIGSETXID + __sigdelset (&local_newmask, SIGSETXID); +# endif + set = &local_newmask; + } +#endif + + return __rt_sigprocmask(how, set, oldset, _NSIG / 8); +} + + +#else + +# define __NR___syscall_sigprocmask __NR_sigprocmask +static __always_inline +_syscall3(int, __syscall_sigprocmask, int, how, const sigset_t *, set, + sigset_t *, oldset) + +int sigprocmask(int how, const sigset_t * set, sigset_t * oldset) +{ +#ifdef SIGCANCEL + sigset_t local_newmask; + + /* + * The only thing we have to make sure here is that SIGCANCEL and + * SIGSETXID are not blocked. + */ + if (set != NULL && (__builtin_expect (__sigismember (set, SIGCANCEL), 0) +# ifdef SIGSETXID + || __builtin_expect (__sigismember (set, SIGSETXID), 0) +# endif + )) + { + local_newmask = *set; + __sigdelset (&local_newmask, SIGCANCEL); +# ifdef SIGSETXID + __sigdelset (&local_newmask, SIGSETXID); +# endif + set = &local_newmask; + } +#endif + + return (__syscall_sigprocmask(how, set, oldset)); +} +#endif +libc_hidden_def(sigprocmask) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sigqueue.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sigqueue.c new file mode 100644 index 00000000..e55d3b34 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sigqueue.c @@ -0,0 +1,52 @@ +/* Copyright (C) 1997, 1998, 2000, 2003, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + +#include +#if defined __USE_POSIX199309 + + +#ifdef __NR_rt_sigqueueinfo + +# define __NR___libc_rt_sigqueueinfo __NR_rt_sigqueueinfo +static __inline__ _syscall3(int, __libc_rt_sigqueueinfo, pid_t, pid, int, sig, void*, value) + +/* Return any pending signal or wait for one for the given time. */ +int sigqueue (pid_t pid, int sig, const union sigval val) +{ + siginfo_t info; + + /* First, clear the siginfo_t structure, so that we don't pass our + stack content to other tasks. */ + memset (&info, 0, sizeof (siginfo_t)); + /* We must pass the information about the data in a siginfo_t value. */ + info.si_signo = sig; + info.si_code = SI_QUEUE; + info.si_pid = getpid (); + info.si_uid = getuid (); + info.si_value = val; + + return __libc_rt_sigqueueinfo(pid, sig, &info); +} + +#endif +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sigsuspend.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sigsuspend.c new file mode 100644 index 00000000..789eeda8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sigsuspend.c @@ -0,0 +1,59 @@ +/* vi: set sw=4 ts=4: */ +/* + * sigsuspend() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +#if defined __USE_POSIX +#include +#undef sigsuspend + +libc_hidden_proto(sigsuspend) + +#ifdef __NR_rt_sigsuspend +# define __NR___rt_sigsuspend __NR_rt_sigsuspend + +# ifdef __UCLIBC_HAS_THREADS_NATIVE__ +# include +# include + +/* Change the set of blocked signals to SET, + wait until a signal arrives, and restore the set of blocked signals. */ +int sigsuspend (const sigset_t *set) +{ + if (SINGLE_THREAD_P) + return INLINE_SYSCALL (rt_sigsuspend, 2, set, _NSIG / 8); + + int oldtype = LIBC_CANCEL_ASYNC (); + + int result = INLINE_SYSCALL (rt_sigsuspend, 2, set, _NSIG / 8); + + LIBC_CANCEL_RESET (oldtype); + + return result; +} +# else +static inline _syscall2(int, __rt_sigsuspend, const sigset_t *, mask, size_t, size); + +int sigsuspend(const sigset_t * mask) +{ + return __rt_sigsuspend(mask, _NSIG / 8); +} +# endif +#else +# define __NR___syscall_sigsuspend __NR_sigsuspend +static __inline__ _syscall3(int, __syscall_sigsuspend, int, a, unsigned long int, b, + unsigned long int, c) + +int sigsuspend(const sigset_t * set) +{ + return __syscall_sigsuspend(0, 0, set->__val[0]); +} +#endif +libc_hidden_def(sigsuspend) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/splice.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/splice.c new file mode 100644 index 00000000..b21d1033 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/splice.c @@ -0,0 +1,23 @@ +/* vi: set sw=4 ts=4: */ +/* + * splice() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +#ifdef __NR_splice +_syscall6(ssize_t, splice, int, __fdin, __off64_t *, __offin, int, __fdout, + __off64_t *, __offout, size_t, __len, unsigned int, __flags) +#else +ssize_t splice(int __fdin, __off64_t *__offin, int __fdout, + __off64_t *__offout, size_t __len, unsigned int __flags) +{ + __set_errno(ENOSYS); + return -1; +} +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/ssp-local.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/ssp-local.c new file mode 100644 index 00000000..202d956a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/ssp-local.c @@ -0,0 +1,35 @@ +/* Copyright (C) 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * Peter S. Mazinger ps.m[@]gmx.net + * copied stack_chk_fail_local.c from glibc and adapted for uClibc + */ + +#include + +extern void __stack_chk_fail (void) attribute_noreturn; + +/* On some architectures, this helps needless PIC pointer setup + that would be needed just for the __stack_chk_fail call. */ + +void __stack_chk_fail_local (void) attribute_noreturn attribute_hidden; +void __stack_chk_fail_local (void) +{ + __stack_chk_fail (); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/ssp.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/ssp.c new file mode 100644 index 00000000..a2d7ff2c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/ssp.c @@ -0,0 +1,117 @@ +/* + * Distributed under the terms of the GNU Lesser General Public License + * $Header: $ + * + * This is a modified version of Hiroaki Etoh's stack smashing routines + * implemented for glibc. + * + * The following people have contributed input to this code. + * Ned Ludd - + * Alexander Gabert - + * The PaX Team - + * Peter S. Mazinger - + * Yoann Vandoorselaere - + * Robert Connolly - + * Cory Visi + * Mike Frysinger + */ + +#if defined __SSP__ || defined __SSP_ALL__ +#error "file must not be compiled with stack protection enabled on it. Use -fno-stack-protector" +#endif + +#ifdef __PROPOLICE_BLOCK_SEGV__ +# define SSP_SIGTYPE SIGSEGV +#else +# define SSP_SIGTYPE SIGABRT +#endif + +#include +#include +#include +#if defined __UCLIBC_HAS_SYSLOG__ +#include + +#endif + + +static void block_signals(void) +{ + struct sigaction sa; + sigset_t mask; + + __sigfillset(&mask); + __sigdelset(&mask, SSP_SIGTYPE); /* Block all signal handlers */ + sigprocmask(SIG_BLOCK, &mask, NULL); /* except SSP_SIGTYPE */ + + /* Make the default handler associated with the signal handler */ + memset(&sa, 0, sizeof(sa)); + __sigfillset(&sa.sa_mask); /* Block all signals */ + if (SIG_DFL) /* if it's constant zero, it's already done */ + sa.sa_handler = SIG_DFL; + sigaction(SSP_SIGTYPE, &sa, NULL); +} + +static void __cold ssp_write(int fd, const char *msg1, const char *msg2, const char *msg3) +{ + write(fd, msg1, strlen(msg1)); + write(fd, msg2, strlen(msg2)); + write(fd, msg3, strlen(msg3)); + write(fd, "()\n", 3); +#if defined __UCLIBC_HAS_SYSLOG__ + openlog("ssp", LOG_CONS | LOG_PID, LOG_USER); + syslog(LOG_INFO, "%s%s%s()", msg1, msg2, msg3); + closelog(); +#endif +} + +static attribute_noreturn void terminate(void) +{ + (void) kill(getpid(), SSP_SIGTYPE); + _exit(127); +} + +void __stack_smash_handler(char func[], int damaged __attribute__ ((unused))) attribute_noreturn __cold; +void __stack_smash_handler(char func[], int damaged) +{ + static const char message[] = ": stack smashing attack in function "; + + block_signals(); + + ssp_write(STDERR_FILENO, __uclibc_progname, message, func); + + /* The loop is added only to keep gcc happy. */ + while(1) + terminate(); +} + +void __stack_chk_fail(void) attribute_noreturn __cold; +void __stack_chk_fail(void) +{ + static const char msg1[] = "stack smashing detected: "; + static const char msg3[] = " terminated"; + + block_signals(); + + ssp_write(STDERR_FILENO, msg1, __uclibc_progname, msg3); + + /* The loop is added only to keep gcc happy. */ + while(1) + terminate(); +} + +void __chk_fail(void) attribute_noreturn; +void __chk_fail(void) +{ + static const char msg1[] = "buffer overflow detected: "; + static const char msg3[] = " terminated"; + + block_signals(); + + ssp_write(STDERR_FILENO, msg1, __uclibc_progname, msg3); + + /* The loop is added only to keep gcc happy. */ + while(1) + terminate(); +} + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/stat.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/stat.c new file mode 100644 index 00000000..a6ab291f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/stat.c @@ -0,0 +1,36 @@ +/* vi: set sw=4 ts=4: */ +/* + * stat() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include "xstatconv.h" + +#define __NR___syscall_stat __NR_stat +#undef stat +static __inline__ _syscall2(int, __syscall_stat, + const char *, file_name, struct kernel_stat *, buf) + +int stat(const char *file_name, struct stat *buf) +{ + int result; + struct kernel_stat kbuf; + + result = __syscall_stat(file_name, &kbuf); + if (result == 0) { + __xstat_conv(&kbuf, buf); + } + return result; +} +libc_hidden_def(stat) + +#if ! defined __NR_stat64 && defined __UCLIBC_HAS_LFS__ +strong_alias_untyped(stat,stat64) +libc_hidden_def(stat64) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/stat64.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/stat64.c new file mode 100644 index 00000000..a76f182d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/stat64.c @@ -0,0 +1,34 @@ +/* vi: set sw=4 ts=4: */ +/* + * stat64() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +#if defined __UCLIBC_HAS_LFS__ && defined __NR_stat64 + +# define __NR___syscall_stat64 __NR_stat64 +# include +# include "xstatconv.h" + +static __inline__ _syscall2(int, __syscall_stat64, + const char *, file_name, struct kernel_stat64 *, buf) + +int stat64(const char *file_name, struct stat64 *buf) +{ + int result; + struct kernel_stat64 kbuf; + + result = __syscall_stat64(file_name, &kbuf); + if (result == 0) { + __xstat64_conv(&kbuf, buf); + } + return result; +} +libc_hidden_def(stat64) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/statfs.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/statfs.c new file mode 100644 index 00000000..d24bc9d0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/statfs.c @@ -0,0 +1,22 @@ +/* vi: set sw=4 ts=4: */ +/* + * statfs() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include + +extern __typeof(statfs) __libc_statfs attribute_hidden; +#define __NR___libc_statfs __NR_statfs +_syscall2(int, __libc_statfs, const char *, path, struct statfs *, buf) + +#if defined __UCLIBC_LINUX_SPECIFIC__ || defined __UCLIBC_HAS_THREADS_NATIVE__ +/* statfs is used by NPTL, so it must exported in case */ +weak_alias(__libc_statfs,statfs) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/stime.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/stime.c new file mode 100644 index 00000000..cb7e8040 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/stime.c @@ -0,0 +1,32 @@ +/* vi: set sw=4 ts=4: */ +/* + * stime() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include + +#ifdef __USE_SVID +#ifdef __NR_stime +_syscall1(int, stime, const time_t *, t) +#else + +int stime(const time_t * when) +{ + struct timeval tv; + + if (when == NULL) { + __set_errno(EINVAL); + return -1; + } + tv.tv_sec = *when; + tv.tv_usec = 0; + return settimeofday(&tv, (struct timezone *) 0); +} +#endif +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/swapoff.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/swapoff.c new file mode 100644 index 00000000..db0b9bef --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/swapoff.c @@ -0,0 +1,17 @@ +/* vi: set sw=4 ts=4: */ +/* + * swapoff() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +#ifdef __NR_swapoff + +#include +_syscall1(int, swapoff, const char *, path) + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/swapon.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/swapon.c new file mode 100644 index 00000000..5d6b6e2d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/swapon.c @@ -0,0 +1,17 @@ +/* vi: set sw=4 ts=4: */ +/* + * swapon() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +#ifdef __NR_swapon + +#include +_syscall2(int, swapon, const char *, path, int, swapflags) + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/symlink.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/symlink.c new file mode 100644 index 00000000..e53e8d41 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/symlink.c @@ -0,0 +1,14 @@ +/* vi: set sw=4 ts=4: */ +/* + * symlink() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#if defined __USE_BSD || defined __USE_UNIX98 || defined __USE_XOPEN2K +#include +_syscall2(int, symlink, const char *, oldpath, const char *, newpath) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/symlinkat.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/symlinkat.c new file mode 100644 index 00000000..6381b331 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/symlinkat.c @@ -0,0 +1,16 @@ +/* + * symlinkat() for uClibc + * + * Copyright (C) 2009 Analog Devices Inc. + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +#ifdef __NR_symlinkat +_syscall3(int, symlinkat, const char *, from, int, tofd, const char *, to) +#else +/* should add emulation with symlink() and /proc/self/fd/ ... */ +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sync.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sync.c new file mode 100644 index 00000000..126f40dd --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sync.c @@ -0,0 +1,19 @@ +/* vi: set sw=4 ts=4: */ +/* + * sync syscall for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +# if defined __USE_BSD || defined __USE_UNIX98 +#include +#include + +void sync(void) +{ + INLINE_SYSCALL(sync, 0); +} +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sync_file_range.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sync_file_range.c new file mode 100644 index 00000000..7e2deff4 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sync_file_range.c @@ -0,0 +1,33 @@ +/* vi: set sw=4 ts=4: */ +/* + * sync_file_range() for uClibc + * + * Copyright (C) 2008 Bernhard Reutner-Fischer + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#if defined __USE_GNU +#include + +#if defined __NR_sync_file_range && defined __UCLIBC_HAS_LFS__ +#define __NR___syscall_sync_file_range __NR_sync_file_range +static __inline__ _syscall6(int, __syscall_sync_file_range, int, fd, + off_t, offset_hi, off_t, offset_lo, + off_t, nbytes_hi, off_t, nbytes_lo, unsigned int, flags) +int sync_file_range(int fd, off64_t offset, off64_t nbytes, unsigned int flags) +{ + return __syscall_sync_file_range(fd, + __LONG_LONG_PAIR((long)(offset >> 32), (long)(offset & 0xffffffff)), + __LONG_LONG_PAIR((long)(nbytes >> 32), (long)(nbytes & 0xffffffff)), + flags); +} +#elif defined __UCLIBC_HAS_STUBS__ +int sync_file_range(int fd, __off64_t offset, __off64_t nbytes, unsigned int flags) +{ + __set_errno(ENOSYS); + return -1; +} +#endif +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sys/acct.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sys/acct.h new file mode 100644 index 00000000..9ee8564f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sys/acct.h @@ -0,0 +1,77 @@ +/* Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_ACCT_H +#define _SYS_ACCT_H 1 + +#include + +#define __need_time_t +#include +#include + +__BEGIN_DECLS + +#define ACCT_COMM 16 + +/* + comp_t is a 16-bit "floating" point number with a 3-bit base 8 + exponent and a 13-bit fraction. See linux/kernel/acct.c for the + specific encoding system used. +*/ + +typedef u_int16_t comp_t; + +struct acct + { + char ac_flag; /* Accounting flags. */ + u_int16_t ac_uid; /* Accounting user ID. */ + u_int16_t ac_gid; /* Accounting group ID. */ + u_int16_t ac_tty; /* Controlling tty. */ + u_int32_t ac_btime; /* Beginning time. */ + comp_t ac_utime; /* Accounting user time. */ + comp_t ac_stime; /* Accounting system time. */ + comp_t ac_etime; /* Accounting elapsed time. */ + comp_t ac_mem; /* Accounting average memory usage. */ + comp_t ac_io; /* Accounting chars transferred. */ + comp_t ac_rw; /* Accounting blocks read or written. */ + comp_t ac_minflt; /* Accounting minor pagefaults. */ + comp_t ac_majflt; /* Accounting major pagefaults. */ + comp_t ac_swaps; /* Accounting number of swaps. */ + u_int32_t ac_exitcode; /* Accounting process exitcode. */ + char ac_comm[ACCT_COMM+1]; /* Accounting command name. */ + char ac_pad[10]; /* Accounting padding bytes. */ + }; + +enum + { + AFORK = 0x01, /* Has executed fork, but no exec. */ + ASU = 0x02, /* Used super-user privileges. */ + ACORE = 0x08, /* Dumped core. */ + AXSIG = 0x10 /* Killed by a signal. */ + }; + +#define AHZ 100 + + +/* Switch process accounting on and off. */ +extern int acct (__const char *__filename) __THROW; + +__END_DECLS + +#endif /* sys/acct.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sys/epoll.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sys/epoll.h new file mode 100644 index 00000000..44e814bf --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sys/epoll.h @@ -0,0 +1,112 @@ +/* Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_EPOLL_H +#define _SYS_EPOLL_H 1 + +#include +#include + + +enum EPOLL_EVENTS + { + EPOLLIN = 0x001, +#define EPOLLIN EPOLLIN + EPOLLPRI = 0x002, +#define EPOLLPRI EPOLLPRI + EPOLLOUT = 0x004, +#define EPOLLOUT EPOLLOUT + EPOLLRDNORM = 0x040, +#define EPOLLRDNORM EPOLLRDNORM + EPOLLRDBAND = 0x080, +#define EPOLLRDBAND EPOLLRDBAND + EPOLLWRNORM = 0x100, +#define EPOLLWRNORM EPOLLWRNORM + EPOLLWRBAND = 0x200, +#define EPOLLWRBAND EPOLLWRBAND + EPOLLMSG = 0x400, +#define EPOLLMSG EPOLLMSG + EPOLLERR = 0x008, +#define EPOLLERR EPOLLERR + EPOLLHUP = 0x010, +#define EPOLLHUP EPOLLHUP + EPOLLRDHUP = 0x2000, +#define EPOLLRDHUP EPOLLRDHUP + EPOLLONESHOT = (1 << 30), +#define EPOLLONESHOT EPOLLONESHOT + EPOLLET = (1 << 31) +#define EPOLLET EPOLLET + }; + + +/* Valid opcodes ( "op" parameter ) to issue to epoll_ctl(). */ +#define EPOLL_CTL_ADD 1 /* Add a file decriptor to the interface. */ +#define EPOLL_CTL_DEL 2 /* Remove a file decriptor from the interface. */ +#define EPOLL_CTL_MOD 3 /* Change file decriptor epoll_event structure. */ + + +typedef union epoll_data +{ + void *ptr; + int fd; + uint32_t u32; + uint64_t u64; +} epoll_data_t; + +struct epoll_event +{ + uint32_t events; /* Epoll events */ + epoll_data_t data; /* User data variable */ +}; + + +__BEGIN_DECLS + +/* Creates an epoll instance. Returns an fd for the new instance. + The "size" parameter is a hint specifying the number of file + descriptors to be associated with the new instance. The fd + returned by epoll_create() should be closed with close(). */ +extern int epoll_create (int __size) __THROW; + + +/* Manipulate an epoll instance "epfd". Returns 0 in case of success, + -1 in case of error ( the "errno" variable will contain the + specific error code ) The "op" parameter is one of the EPOLL_CTL_* + constants defined above. The "fd" parameter is the target of the + operation. The "event" parameter describes which events the caller + is interested in and any associated user data. */ +extern int epoll_ctl (int __epfd, int __op, int __fd, + struct epoll_event *__event) __THROW; + + +/* Wait for events on an epoll instance "epfd". Returns the number of + triggered events returned in "events" buffer. Or -1 in case of + error with the "errno" variable set to the specific error code. The + "events" parameter is a buffer that will contain triggered + events. The "maxevents" is the maximum number of events to be + returned ( usually size of "events" ). The "timeout" parameter + specifies the maximum wait time in milliseconds (-1 == infinite). + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern int epoll_wait (int __epfd, struct epoll_event *__events, + int __maxevents, int __timeout); + +__END_DECLS + +#endif /* sys/epoll.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sys/inotify.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sys/inotify.h new file mode 100644 index 00000000..dc4e19da --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sys/inotify.h @@ -0,0 +1,105 @@ +/* Copyright (C) 2005, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_INOTIFY_H +#define _SYS_INOTIFY_H 1 + +#include + + +/* Flags for the parameter of inotify_init1. */ +enum + { + IN_CLOEXEC = 02000000, +#define IN_CLOEXEC IN_CLOEXEC + IN_NONBLOCK = 04000 +#define IN_NONBLOCK IN_NONBLOCK + }; + + +/* Structure describing an inotify event. */ +struct inotify_event +{ + int wd; /* Watch descriptor. */ + uint32_t mask; /* Watch mask. */ + uint32_t cookie; /* Cookie to synchronize two events. */ + uint32_t len; /* Length (including NULs) of name. */ + char name __flexarr; /* Name. */ +}; + + +/* Supported events suitable for MASK parameter of INOTIFY_ADD_WATCH. */ +#define IN_ACCESS 0x00000001 /* File was accessed. */ +#define IN_MODIFY 0x00000002 /* File was modified. */ +#define IN_ATTRIB 0x00000004 /* Metadata changed. */ +#define IN_CLOSE_WRITE 0x00000008 /* Writtable file was closed. */ +#define IN_CLOSE_NOWRITE 0x00000010 /* Unwrittable file closed. */ +#define IN_CLOSE (IN_CLOSE_WRITE | IN_CLOSE_NOWRITE) /* Close. */ +#define IN_OPEN 0x00000020 /* File was opened. */ +#define IN_MOVED_FROM 0x00000040 /* File was moved from X. */ +#define IN_MOVED_TO 0x00000080 /* File was moved to Y. */ +#define IN_MOVE (IN_MOVED_FROM | IN_MOVED_TO) /* Moves. */ +#define IN_CREATE 0x00000100 /* Subfile was created. */ +#define IN_DELETE 0x00000200 /* Subfile was deleted. */ +#define IN_DELETE_SELF 0x00000400 /* Self was deleted. */ +#define IN_MOVE_SELF 0x00000800 /* Self was moved. */ + +/* Events sent by the kernel. */ +#define IN_UNMOUNT 0x00002000 /* Backing fs was unmounted. */ +#define IN_Q_OVERFLOW 0x00004000 /* Event queued overflowed. */ +#define IN_IGNORED 0x00008000 /* File was ignored. */ + +/* Helper events. */ +#define IN_CLOSE (IN_CLOSE_WRITE | IN_CLOSE_NOWRITE) /* Close. */ +#define IN_MOVE (IN_MOVED_FROM | IN_MOVED_TO) /* Moves. */ + +/* Special flags. */ +#define IN_ONLYDIR 0x01000000 /* Only watch the path if it is a + directory. */ +#define IN_DONT_FOLLOW 0x02000000 /* Do not follow a sym link. */ +#define IN_MASK_ADD 0x20000000 /* Add to the mask of an already + existing watch. */ +#define IN_ISDIR 0x40000000 /* Event occurred against dir. */ +#define IN_ONESHOT 0x80000000 /* Only send event once. */ + +/* All events which a program can wait on. */ +#define IN_ALL_EVENTS (IN_ACCESS | IN_MODIFY | IN_ATTRIB | IN_CLOSE_WRITE \ + | IN_CLOSE_NOWRITE | IN_OPEN | IN_MOVED_FROM \ + | IN_MOVED_TO | IN_CREATE | IN_DELETE \ + | IN_DELETE_SELF | IN_MOVE_SELF) + + +__BEGIN_DECLS + +/* Create and initialize inotify instance. */ +extern int inotify_init (void) __THROW; + +/* Create and initialize inotify instance. */ +extern int inotify_init1 (int __flags) __THROW; + +/* Add watch of object NAME to inotify instance FD. Notify about + events specified by MASK. */ +extern int inotify_add_watch (int __fd, const char *__name, uint32_t __mask) + __THROW; + +/* Remove the watch specified by WD from the inotify instance FD. */ +extern int inotify_rm_watch (int __fd, uint32_t __wd) __THROW; + +__END_DECLS + +#endif /* sys/inotify.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sys/prctl.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sys/prctl.h new file mode 100644 index 00000000..7e9b72d3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sys/prctl.h @@ -0,0 +1,32 @@ +/* Copyright (C) 1997, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_PRCTL_H +#define _SYS_PRCTL_H 1 + +#include +#include /* The magic values come from here */ + +__BEGIN_DECLS + +/* Control process execution. */ +extern int prctl (int __option, ...) __THROW; + +__END_DECLS + +#endif /* sys/prctl.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sys/ptrace.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sys/ptrace.h new file mode 100644 index 00000000..08658f97 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sys/ptrace.h @@ -0,0 +1,168 @@ +/* `ptrace' debugger support interface. Linux version. + Copyright (C) 1996-1999,2000,2006,2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_PTRACE_H +#define _SYS_PTRACE_H 1 + +#include + +__BEGIN_DECLS + +/* Type of the REQUEST argument to `ptrace.' */ +enum __ptrace_request +{ + /* Indicate that the process making this request should be traced. + All signals received by this process can be intercepted by its + parent, and its parent can use the other `ptrace' requests. */ + PTRACE_TRACEME = 0, +#define PT_TRACE_ME PTRACE_TRACEME + + /* Return the word in the process's text space at address ADDR. */ + PTRACE_PEEKTEXT = 1, +#define PT_READ_I PTRACE_PEEKTEXT + + /* Return the word in the process's data space at address ADDR. */ + PTRACE_PEEKDATA = 2, +#define PT_READ_D PTRACE_PEEKDATA + + /* Return the word in the process's user area at offset ADDR. */ + PTRACE_PEEKUSER = 3, +#define PT_READ_U PTRACE_PEEKUSER + + /* Write the word DATA into the process's text space at address ADDR. */ + PTRACE_POKETEXT = 4, +#define PT_WRITE_I PTRACE_POKETEXT + + /* Write the word DATA into the process's data space at address ADDR. */ + PTRACE_POKEDATA = 5, +#define PT_WRITE_D PTRACE_POKEDATA + + /* Write the word DATA into the process's user area at offset ADDR. */ + PTRACE_POKEUSER = 6, +#define PT_WRITE_U PTRACE_POKEUSER + + /* Continue the process. */ + PTRACE_CONT = 7, +#define PT_CONTINUE PTRACE_CONT + + /* Kill the process. */ + PTRACE_KILL = 8, +#define PT_KILL PTRACE_KILL + + /* Single step the process. + This is not supported on all machines. */ + PTRACE_SINGLESTEP = 9, +#define PT_STEP PTRACE_SINGLESTEP + + /* Get all general purpose registers used by a processes. + This is not supported on all machines. */ + PTRACE_GETREGS = 12, +#define PT_GETREGS PTRACE_GETREGS + + /* Set all general purpose registers used by a processes. + This is not supported on all machines. */ + PTRACE_SETREGS = 13, +#define PT_SETREGS PTRACE_SETREGS + + /* Get all floating point registers used by a processes. + This is not supported on all machines. */ + PTRACE_GETFPREGS = 14, +#define PT_GETFPREGS PTRACE_GETFPREGS + + /* Set all floating point registers used by a processes. + This is not supported on all machines. */ + PTRACE_SETFPREGS = 15, +#define PT_SETFPREGS PTRACE_SETFPREGS + + /* Attach to a process that is already running. */ + PTRACE_ATTACH = 16, +#define PT_ATTACH PTRACE_ATTACH + + /* Detach from a process attached to with PTRACE_ATTACH. */ + PTRACE_DETACH = 17, +#define PT_DETACH PTRACE_DETACH + + /* Get all extended floating point registers used by a processes. + This is not supported on all machines. */ + PTRACE_GETFPXREGS = 18, +#define PT_GETFPXREGS PTRACE_GETFPXREGS + + /* Set all extended floating point registers used by a processes. + This is not supported on all machines. */ + PTRACE_SETFPXREGS = 19, +#define PT_SETFPXREGS PTRACE_SETFPXREGS + + /* Continue and stop at the next (return from) syscall. */ + PTRACE_SYSCALL = 24, +#define PT_SYSCALL PTRACE_SYSCALL + + /* Set ptrace filter options. */ + PTRACE_SETOPTIONS = 0x4200, +#define PT_SETOPTIONS PTRACE_SETOPTIONS + + /* Get last ptrace message. */ + PTRACE_GETEVENTMSG = 0x4201, +#define PT_GETEVENTMSG PTRACE_GETEVENTMSG + + /* Get siginfo for process. */ + PTRACE_GETSIGINFO = 0x4202, +#define PT_GETSIGINFO PTRACE_GETSIGINFO + + /* Set new siginfo for process. */ + PTRACE_SETSIGINFO = 0x4203 +#define PT_SETSIGINFO PTRACE_SETSIGINFO +}; + + +/* Options set using PTRACE_SETOPTIONS. */ +enum __ptrace_setoptions { + PTRACE_O_TRACESYSGOOD = 0x00000001, + PTRACE_O_TRACEFORK = 0x00000002, + PTRACE_O_TRACEVFORK = 0x00000004, + PTRACE_O_TRACECLONE = 0x00000008, + PTRACE_O_TRACEEXEC = 0x00000010, + PTRACE_O_TRACEVFORKDONE = 0x00000020, + PTRACE_O_TRACEEXIT = 0x00000040, + PTRACE_O_MASK = 0x0000007f +}; + +/* Wait extended result codes for the above trace options. */ +enum __ptrace_eventcodes { + PTRACE_EVENT_FORK = 1, + PTRACE_EVENT_VFORK = 2, + PTRACE_EVENT_CLONE = 3, + PTRACE_EVENT_EXEC = 4, + PTRACE_EVENT_VFORK_DONE = 5, + PTRACE_EVENT_EXIT = 6 +}; + +/* Perform process tracing functions. REQUEST is one of the values + above, and determines the action to be taken. + For all requests except PTRACE_TRACEME, PID specifies the process to be + traced. + + PID and the other arguments described above for the various requests should + appear (those that are used for the particular request) as: + pid_t PID, void *ADDR, int DATA, void *ADDR2 + after REQUEST. */ +extern long int ptrace (enum __ptrace_request __request, ...) __THROW; + +__END_DECLS + +#endif /* _SYS_PTRACE_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sys/timerfd.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sys/timerfd.h new file mode 100644 index 00000000..c1bb06f5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sys/timerfd.h @@ -0,0 +1,60 @@ +/* Copyright (C) 2008 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_TIMERFD_H +#define _SYS_TIMERFD_H 1 + +#include + + +/* Bits to be set in the FLAGS parameter of `timerfd_create'. */ +enum + { + TFD_CLOEXEC = 02000000, +#define TFD_CLOEXEC TFD_CLOEXEC + TFD_NONBLOCK = 04000 +#define TFD_NONBLOCK TFD_NONBLOCK + }; + + +/* Bits to be set in the FLAGS parameter of `timerfd_settime'. */ +enum + { + TFD_TIMER_ABSTIME = 1 << 0 +#define TFD_TIMER_ABSTIME TFD_TIMER_ABSTIME + }; + + +__BEGIN_DECLS + +/* Return file descriptor for new interval timer source. */ +extern int timerfd_create (clockid_t __clock_id, int __flags) __THROW; + +/* Set next expiration time of interval timer source UFD to UTMR. If + FLAGS has the TFD_TIMER_ABSTIME flag set the timeout value is + absolute. Optionally return the old expiration time in OTMR. */ +extern int timerfd_settime (int __ufd, int __flags, + __const struct itimerspec *__utmr, + struct itimerspec *__otmr) __THROW; + +/* Return the next expiration time of UFD. */ +extern int timerfd_gettime (int __ufd, struct itimerspec *__otmr) __THROW; + +__END_DECLS + +#endif /* sys/timerfd.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sys/user.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sys/user.h new file mode 100644 index 00000000..03e56c3d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sys/user.h @@ -0,0 +1 @@ +#error "This file is machine-dependent and not provided for this machine." diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/syscall.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/syscall.c new file mode 100644 index 00000000..61f798e2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/syscall.c @@ -0,0 +1,12 @@ +/* + * syscall() library function + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +long syscall(long sysnum, long arg1, long arg2, long arg3, long arg4, long arg5, long arg6) +{ + return INLINE_SYSCALL_NCS(sysnum, 6, arg1, arg2, arg3, arg4, arg5, arg6); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/syscalls.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/syscalls.h new file mode 100644 index 00000000..c4f6a44f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/syscalls.h @@ -0,0 +1,24 @@ +/* vi: set sw=4 ts=4: */ +/* + * Common header file for uClibc syscalls + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define _LARGEFILE64_SOURCE +#include +#include +#include +#include +#include + +#undef __OPTIMIZE__ +/* We absolutely do _NOT_ want interfaces silently + * being renamed under us or very bad things will happen... */ +#ifdef __USE_FILE_OFFSET64 +# undef __USE_FILE_OFFSET64 +#endif + +#include diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sysctl.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sysctl.c new file mode 100644 index 00000000..dde00be4 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sysctl.c @@ -0,0 +1,38 @@ +/* vi: set sw=4 ts=4: */ +/* + * _sysctl() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#if defined __NR__sysctl && (defined __USE_GNU || defined __USE_BSD) + +/* psm: including sys/sysctl.h would depend on kernel headers */ +struct __sysctl_args { + int *name; + int nlen; + void *oldval; + size_t *oldlenp; + void *newval; + size_t newlen; + unsigned long __unused[4]; +}; +extern int sysctl (int *__name, int __nlen, void *__oldval, + size_t *__oldlenp, void *__newval, size_t __newlen) __THROW; +int sysctl(int *name, int nlen, void *oldval, size_t * oldlenp, + void *newval, size_t newlen) +{ + /* avoid initializing on the stack as gcc will call memset() */ + struct __sysctl_args args; + args.name = name; + args.nlen = nlen; + args.oldval = oldval; + args.oldlenp = oldlenp; + args.newval = newval; + args.newlen = newlen; + return INLINE_SYSCALL(_sysctl, 1, &args); +} +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sysdep.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sysdep.h new file mode 100644 index 00000000..a7ec9548 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sysdep.h @@ -0,0 +1,170 @@ +/* Generic asm macros used on many machines. + Copyright (C) 1991,92,93,96,98,2002,2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#ifndef C_LABEL + +/* Define a macro we can use to construct the asm name for a C symbol. */ +#ifndef __UCLIBC_UNDERSCORES__ +#ifdef __STDC__ +#define C_LABEL(name) name##: +#else +#define C_LABEL(name) name/**/: +#endif +#else +#ifdef __STDC__ +#define C_LABEL(name) _##name##: +#else +#define C_LABEL(name) _/**/name/**/: +#endif +#endif + +#endif + +#ifdef __ASSEMBLER__ +/* Mark the end of function named SYM. This is used on some platforms + to generate correct debugging information. */ +#ifndef END +#define END(sym) +#endif + +#ifndef JUMPTARGET +#define JUMPTARGET(sym) sym +#endif + +/* Macros to generate eh_frame unwind information. */ +# ifdef HAVE_ASM_CFI_DIRECTIVES +# define cfi_startproc .cfi_startproc +# define cfi_endproc .cfi_endproc +# define cfi_def_cfa(reg, off) .cfi_def_cfa reg, off +# define cfi_def_cfa_register(reg) .cfi_def_cfa_register reg +# define cfi_def_cfa_offset(off) .cfi_def_cfa_offset off +# define cfi_adjust_cfa_offset(off) .cfi_adjust_cfa_offset off +# define cfi_offset(reg, off) .cfi_offset reg, off +# define cfi_rel_offset(reg, off) .cfi_rel_offset reg, off +# define cfi_register(r1, r2) .cfi_register r1, r2 +# define cfi_return_column(reg) .cfi_return_column reg +# define cfi_restore(reg) .cfi_restore reg +# define cfi_same_value(reg) .cfi_same_value reg +# define cfi_undefined(reg) .cfi_undefined reg +# define cfi_remember_state .cfi_remember_state +# define cfi_restore_state .cfi_restore_state +# define cfi_window_save .cfi_window_save +# define cfi_personality(enc, exp) .cfi_personality enc, exp +# define cfi_lsda(enc, exp) .cfi_lsda enc, exp + +# else +# define cfi_startproc +# define cfi_endproc +# define cfi_def_cfa(reg, off) +# define cfi_def_cfa_register(reg) +# define cfi_def_cfa_offset(off) +# define cfi_adjust_cfa_offset(off) +# define cfi_offset(reg, off) +# define cfi_rel_offset(reg, off) +# define cfi_register(r1, r2) +# define cfi_return_column(reg) +# define cfi_restore(reg) +# define cfi_same_value(reg) +# define cfi_undefined(reg) +# define cfi_remember_state +# define cfi_restore_state +# define cfi_window_save +# define cfi_personality(enc, exp) +# define cfi_lsda(enc, exp) +# endif + +#else /* ! ASSEMBLER */ +# ifdef HAVE_ASM_CFI_DIRECTIVES +# define CFI_STRINGIFY(Name) CFI_STRINGIFY2 (Name) +# define CFI_STRINGIFY2(Name) #Name +# define CFI_STARTPROC ".cfi_startproc" +# define CFI_ENDPROC ".cfi_endproc" +# define CFI_DEF_CFA(reg, off) \ + ".cfi_def_cfa " CFI_STRINGIFY(reg) "," CFI_STRINGIFY(off) +# define CFI_DEF_CFA_REGISTER(reg) \ + ".cfi_def_cfa_register " CFI_STRINGIFY(reg) +# define CFI_DEF_CFA_OFFSET(off) \ + ".cfi_def_cfa_offset " CFI_STRINGIFY(off) +# define CFI_ADJUST_CFA_OFFSET(off) \ + ".cfi_adjust_cfa_offset " CFI_STRINGIFY(off) +# define CFI_OFFSET(reg, off) \ + ".cfi_offset " CFI_STRINGIFY(reg) "," CFI_STRINGIFY(off) +# define CFI_REL_OFFSET(reg, off) \ + ".cfi_rel_offset " CFI_STRINGIFY(reg) "," CFI_STRINGIFY(off) +# define CFI_REGISTER(r1, r2) \ + ".cfi_register " CFI_STRINGIFY(r1) "," CFI_STRINGIFY(r2) +# define CFI_RETURN_COLUMN(reg) \ + ".cfi_return_column " CFI_STRINGIFY(reg) +# define CFI_RESTORE(reg) \ + ".cfi_restore " CFI_STRINGIFY(reg) +# define CFI_UNDEFINED(reg) \ + ".cfi_undefined " CFI_STRINGIFY(reg) +# define CFI_REMEMBER_STATE \ + ".cfi_remember_state" +# define CFI_RESTORE_STATE \ + ".cfi_restore_state" +# define CFI_WINDOW_SAVE \ + ".cfi_window_save" +# define CFI_PERSONALITY(enc, exp) \ + ".cfi_personality " CFI_STRINGIFY(enc) "," CFI_STRINGIFY(exp) +# define CFI_LSDA(enc, exp) \ + ".cfi_lsda " CFI_STRINGIFY(enc) "," CFI_STRINGIFY(exp) +# else +# define CFI_STARTPROC +# define CFI_ENDPROC +# define CFI_DEF_CFA(reg, off) +# define CFI_DEF_CFA_REGISTER(reg) +# define CFI_DEF_CFA_OFFSET(off) +# define CFI_ADJUST_CFA_OFFSET(off) +# define CFI_OFFSET(reg, off) +# define CFI_REL_OFFSET(reg, off) +# define CFI_REGISTER(r1, r2) +# define CFI_RETURN_COLUMN(reg) +# define CFI_RESTORE(reg) +# define CFI_UNDEFINED(reg) +# define CFI_REMEMBER_STATE +# define CFI_RESTORE_STATE +# define CFI_WINDOW_SAVE +# define CFI_PERSONALITY(enc, exp) +# define CFI_LSDA(enc, exp) +# endif + +#endif /* __ASSEMBLER__ */ + +/* Values used for encoding parameter of cfi_personality and cfi_lsda. */ +#define DW_EH_PE_absptr 0x00 +#define DW_EH_PE_omit 0xff +#define DW_EH_PE_uleb128 0x01 +#define DW_EH_PE_udata2 0x02 +#define DW_EH_PE_udata4 0x03 +#define DW_EH_PE_udata8 0x04 +#define DW_EH_PE_sleb128 0x09 +#define DW_EH_PE_sdata2 0x0a +#define DW_EH_PE_sdata4 0x0b +#define DW_EH_PE_sdata8 0x0c +#define DW_EH_PE_signed 0x08 +#define DW_EH_PE_pcrel 0x10 +#define DW_EH_PE_textrel 0x20 +#define DW_EH_PE_datarel 0x30 +#define DW_EH_PE_funcrel 0x40 +#define DW_EH_PE_aligned 0x50 +#define DW_EH_PE_indirect 0x80 + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sysfs.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sysfs.c new file mode 100644 index 00000000..02f37d78 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sysfs.c @@ -0,0 +1,17 @@ +/* vi: set sw=4 ts=4: */ +/* + * sysfs() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* libc isn't really supposed to export this */ +#if 0 +#include + +#if defined __USE_SVID +_syscall3(int, sysfs, int, option, unsigned int, index, char, addr) +#endif +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sysinfo.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sysinfo.c new file mode 100644 index 00000000..fc37aaff --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/sysinfo.c @@ -0,0 +1,12 @@ +/* vi: set sw=4 ts=4: */ +/* + * sysinfo() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +_syscall1(int, sysinfo, struct sysinfo *, info) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/tee.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/tee.c new file mode 100644 index 00000000..50477671 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/tee.c @@ -0,0 +1,16 @@ +/* vi: set sw=4 ts=4: */ +/* + * tee() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +#ifdef __NR_tee +_syscall4(ssize_t, tee, int, __fdin, int, __fdout, size_t, __len, + unsigned int, __flags) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/time.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/time.c new file mode 100644 index 00000000..e13b44f4 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/time.c @@ -0,0 +1,34 @@ +/* vi: set sw=4 ts=4: */ +/* + * time() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include + + +#ifdef __NR_time +_syscall_noerr1(time_t, time, time_t *, t) +#else +time_t time(time_t * t) +{ + time_t result; + struct timeval tv; + + /* In Linux, gettimeofday fails only on bad parameter. + * We know that here parameter isn't bad. + */ + gettimeofday(&tv, NULL); + result = (time_t) tv.tv_sec; + if (t != NULL) { + *t = result; + } + return result; +} +#endif +libc_hidden_def(time) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/timerfd.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/timerfd.c new file mode 100644 index 00000000..23320448 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/timerfd.c @@ -0,0 +1,32 @@ +/* vi: set sw=4 ts=4: */ +/* + * timerfd_create() / timerfd_settime() / timerfd_gettime() for uClibc + * + * Copyright (C) 2009 Stephan Raue + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +/* + * timerfd_create() + */ +#ifdef __NR_timerfd_create +_syscall2(int, timerfd_create, int, clockid, int, flags) +#endif + +/* + * timerfd_settime() + */ +#ifdef __NR_timerfd_settime +_syscall4(int,timerfd_settime, int, ufd, int, flags, const struct itimerspec *, utmr, struct itimerspec *, otmr) +#endif + +/* + * timerfd_gettime() + */ +#ifdef __NR_timerfd_gettime +_syscall2(int, timerfd_gettime, int, ufd, struct itimerspec *, otmr) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/times.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/times.c new file mode 100644 index 00000000..37ae040d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/times.c @@ -0,0 +1,15 @@ +/* vi: set sw=4 ts=4: */ +/* + * times() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + + +_syscall_noerr1(clock_t, times, struct tms *, buf) +libc_hidden_def(times) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/truncate.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/truncate.c new file mode 100644 index 00000000..2331bddb --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/truncate.c @@ -0,0 +1,15 @@ +/* vi: set sw=4 ts=4: */ +/* + * truncate() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + + +_syscall2(int, truncate, const char *, path, __off_t, length) +libc_hidden_def(truncate) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/truncate64.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/truncate64.c new file mode 100644 index 00000000..1f6c4596 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/truncate64.c @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ +/* truncate64 syscall. Copes with 64 bit and 32 bit machines + * and on 32 bit machines this sends things into the kernel as + * two 32-bit arguments (high and low 32 bits of length) that + * are ordered based on endianess. It turns out endian.h has + * just the macro we need to order things, __LONG_LONG_PAIR. + */ + +#include +#include +#include +#include +#include +#include +#include + +#if defined __UCLIBC_HAS_LFS__ + +#if defined __NR_truncate64 + +#if __WORDSIZE == 64 + +/* For a 64 bit machine, life is simple... */ +_syscall2(int, truncate64, const char *, path, __off64_t, length) + +#elif __WORDSIZE == 32 + +/* The exported truncate64 function. */ +int truncate64(const char * path, __off64_t length) +{ + uint32_t low = length & 0xffffffff; + uint32_t high = length >> 32; +#if defined(__UCLIBC_TRUNCATE64_HAS_4_ARGS__) + return INLINE_SYSCALL(truncate64, 4, path, 0, + __LONG_LONG_PAIR(high, low)); +#else + return INLINE_SYSCALL(truncate64, 3, path, + __LONG_LONG_PAIR(high, low)); +#endif +} + +#else /* __WORDSIZE */ +#error Your machine is not 64 bit nor 32 bit, I am dazed and confused. +#endif /* __WORDSIZE */ + +#else /* __NR_truncate64 */ + + +int truncate64(const char * path, __off64_t length) +{ + __off_t x = (__off_t) length; + + if (x == length) { + return truncate(path, x); + } + + __set_errno((x < 0) ? EINVAL : EFBIG); + + return -1; +} + +#endif /* __NR_truncate64 */ + +#endif /* __UCLIBC_HAS_LFS__ */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/ulimit.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/ulimit.c new file mode 100644 index 00000000..74b45337 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/ulimit.c @@ -0,0 +1,56 @@ +/* vi: set sw=4 ts=4: */ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +#ifdef __NR_ulimit + +extern long int ulimit(int cmd, long arg); +_syscall2(long, ulimit, int, cmd, long, arg) + +#else + +#include +#include +#include +#include + + +long int ulimit(int cmd, ...) +{ + va_list va; + struct rlimit limit; + long int result = -1; + va_start (va, cmd); + switch (cmd) { + /* Get limit on file size. */ + case UL_GETFSIZE: + if (getrlimit(RLIMIT_FSIZE, &limit) == 0) + result = limit.rlim_cur / 512; /* bytes to 512 byte blocksize */ + break; + /* Set limit on file size. */ + case UL_SETFSIZE: + result = va_arg (va, long int); + if ((rlim_t) result > RLIM_INFINITY / 512) { + limit.rlim_cur = RLIM_INFINITY; + limit.rlim_max = RLIM_INFINITY; + } else { + limit.rlim_cur = result * 512; + limit.rlim_max = result * 512; + } + result = setrlimit(RLIMIT_FSIZE, &limit); + break; + case __UL_GETOPENMAX: + result = sysconf(_SC_OPEN_MAX); + break; + default: + __set_errno(EINVAL); + } + va_end (va); + return result; +} +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/umask.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/umask.c new file mode 100644 index 00000000..ef9860e3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/umask.c @@ -0,0 +1,19 @@ +/* vi: set sw=4 ts=4: */ +/* + * umask() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +#define __NR___syscall_umask __NR_umask +static __inline__ _syscall1(__kernel_mode_t, __syscall_umask, __kernel_mode_t, mode) + +mode_t umask(mode_t mode) +{ + return (__syscall_umask(mode)); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/umount.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/umount.c new file mode 100644 index 00000000..453ecd27 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/umount.c @@ -0,0 +1,41 @@ +/* vi: set sw=4 ts=4: */ +/* + * umount() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +#if defined __USE_GNU +#include + +/* arch provides umount() syscall */ +#ifdef __NR_umount + +_syscall1(int, umount, const char *, specialfile) + +/* arch provides umount2() syscall */ +#elif defined __NR_umount2 + +# define __NR___syscall_umount2 __NR_umount2 +static __inline__ _syscall2(int, __syscall_umount2, const char *, special_file, int, flags) + +int umount(const char *special_file) +{ + return (__syscall_umount2(special_file, 0)); +} + +/* arch doesn't provide any umount syscall !? */ +#else + +int umount(const char *special_file) +{ + __set_errno(ENOSYS); + return -1; +} + +#endif +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/umount2.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/umount2.c new file mode 100644 index 00000000..bd44717d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/umount2.c @@ -0,0 +1,23 @@ +/* vi: set sw=4 ts=4: */ +/* + * umount2() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +#if defined __USE_GNU +#include +#ifdef __NR_umount2 /* Old kernels don't have umount2 */ +_syscall2(int, umount2, const char *, special_file, int, flags) +#else +int umount2(const char *special_file, int flags) +{ + __set_errno(ENOSYS); + return -1; +} +#endif +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/uname.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/uname.c new file mode 100644 index 00000000..0feec934 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/uname.c @@ -0,0 +1,15 @@ +/* vi: set sw=4 ts=4: */ +/* + * uname() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + + +_syscall1(int, uname, struct utsname *, buf) +libc_hidden_def(uname) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/unlink.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/unlink.c new file mode 100644 index 00000000..513cdd5e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/unlink.c @@ -0,0 +1,15 @@ +/* vi: set sw=4 ts=4: */ +/* + * unlink() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + + +_syscall1(int, unlink, const char *, pathname) +libc_hidden_def(unlink) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/unlinkat.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/unlinkat.c new file mode 100644 index 00000000..0eaf2b67 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/unlinkat.c @@ -0,0 +1,16 @@ +/* + * unlinkat() for uClibc + * + * Copyright (C) 2009 Analog Devices Inc. + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +#ifdef __NR_unlinkat +_syscall3(int, unlinkat, int, fd, const char *, file, int, flag) +#else +/* should add emulation with unlink() and /proc/self/fd/ ... */ +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/uselib.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/uselib.c new file mode 100644 index 00000000..b2b806f3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/uselib.c @@ -0,0 +1,18 @@ +/* vi: set sw=4 ts=4: */ +/* + * uselib() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ +#if 0 +linux specific and we do not use it in uClibc. + +#include +#include +#ifdef __NR_uselib +int uselib (const char *library); +_syscall1(int, uselib, const char *, library) +#endif +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/ustat.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/ustat.c new file mode 100644 index 00000000..e97fa76b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/ustat.c @@ -0,0 +1,26 @@ +/* vi: set sw=4 ts=4: */ +/* + * ustat() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include + +#define __NR___syscall_ustat __NR_ustat +/* Kernel's fs/super.c defines this: + * long sys_ustat(unsigned dev, struct ustat __user * ubuf), + * thus we use unsigned, not __kernel_dev_t. + */ +static __inline__ _syscall2(int, __syscall_ustat, + unsigned, kdev_t, + struct ustat *, ubuf) + +int ustat(dev_t dev, struct ustat *ubuf) +{ + return __syscall_ustat(dev, ubuf); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/utime.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/utime.c new file mode 100644 index 00000000..c9fd1bfb --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/utime.c @@ -0,0 +1,35 @@ +/* vi: set sw=4 ts=4: */ +/* + * utime() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + + +#ifdef __NR_utime +_syscall2(int, utime, const char *, file, const struct utimbuf *, times) +#else +#include +#include + + +int utime(const char *file, const struct utimbuf *times) +{ + struct timeval timevals[2]; + + if (times != NULL) { + timevals[0].tv_usec = 0L; + timevals[1].tv_usec = 0L; + timevals[0].tv_sec = (long int) times->actime; + timevals[1].tv_sec = (long int) times->modtime; + } + return utimes(file, times ? timevals : NULL); +} +#endif +link_warning(utime, "the use of OBSOLESCENT `utime' is discouraged, use `utimes'") +libc_hidden_def(utime) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/utimensat.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/utimensat.c new file mode 100644 index 00000000..2cfb8247 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/utimensat.c @@ -0,0 +1,18 @@ +/* + * utimensat() for uClibc + * + * Copyright (C) 2009 Analog Devices Inc. + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +#ifdef __NR_utimensat +_syscall4(int, utimensat, int, fd, const char *, path, const struct timespec *, times, int, flags) +libc_hidden_def(utimensat) +#else +/* should add emulation with utimens() and /proc/self/fd/ ... */ +#endif + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/utimes.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/utimes.c new file mode 100644 index 00000000..99d92027 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/utimes.c @@ -0,0 +1,35 @@ +/* vi: set sw=4 ts=4: */ +/* + * utimes() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include + + +#ifdef __NR_utimes +_syscall2(int, utimes, const char *, file, const struct timeval *, tvp) +#else +#include + + +int utimes(const char *file, const struct timeval tvp[2]) +{ + struct utimbuf buf, *times; + + if (tvp) { + times = &buf; + times->actime = tvp[0].tv_sec; + times->modtime = tvp[1].tv_sec; + } else { + times = NULL; + } + return utime(file, times); +} +#endif +libc_hidden_def(utimes) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/vfork.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/vfork.c new file mode 100644 index 00000000..e7c92089 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/vfork.c @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include + +extern __typeof(vfork) __vfork attribute_hidden; + +#ifdef __NR_vfork + +# define __NR___vfork __NR_vfork +_syscall0(pid_t, __vfork) + +weak_alias(__vfork,vfork) +libc_hidden_weak(vfork) + +#elif defined __ARCH_USE_MMU__ && defined __NR_fork + +/* Trivial implementation for arches that lack vfork */ + +pid_t __vfork(void) +{ + return fork(); +} + +weak_alias(__vfork,vfork) +libc_hidden_weak(vfork) + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/vhangup.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/vhangup.c new file mode 100644 index 00000000..77910e68 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/vhangup.c @@ -0,0 +1,14 @@ +/* vi: set sw=4 ts=4: */ +/* + * vhangup() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#if defined __USE_BSD || (defined __USE_XOPEN && !defined __USE_UNIX98) +_syscall0(int, vhangup) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/vmsplice.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/vmsplice.c new file mode 100644 index 00000000..c5fd6c7e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/vmsplice.c @@ -0,0 +1,23 @@ +/* vi: set sw=4 ts=4: */ +/* + * vmsplice() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +#ifdef __NR_vmsplice +_syscall4(ssize_t, vmsplice, int, __fdout, const struct iovec *, __iov, + size_t, __count, unsigned int, __flags) +#else +ssize_t vmsplice(int __fdout, const struct iovec *__iov, size_t __count, + unsigned int __flags) +{ + __set_errno(ENOSYS); + return -1; +} +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/wait.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/wait.c new file mode 100644 index 00000000..9b529eb2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/wait.c @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2006 Steven J. Hill + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ +#include +#include +#include +#include +#include + +extern __typeof(wait) __libc_wait; +/* Wait for a child to die. When one does, put its status in *STAT_LOC + * and return its process ID. For errors, return (pid_t) -1. */ +#ifdef __UCLIBC_HAS_THREADS_NATIVE__ +#include +#include + +pid_t attribute_hidden +__libc_wait (__WAIT_STATUS_DEFN stat_loc) +{ + if (SINGLE_THREAD_P) + return INLINE_SYSCALL (wait4, 4, WAIT_ANY, stat_loc, 0, + (struct rusage *) NULL); + + int oldtype = LIBC_CANCEL_ASYNC (); + + pid_t result = INLINE_SYSCALL (wait4, 4, WAIT_ANY, stat_loc, 0, + (struct rusage *) NULL); + + LIBC_CANCEL_RESET (oldtype); + + return result; +} +#else +/* Wait for a child to die. When one does, put its status in *STAT_LOC + * and return its process ID. For errors, return (pid_t) -1. */ +__pid_t __libc_wait (__WAIT_STATUS_DEFN stat_loc) +{ + return wait4 (WAIT_ANY, stat_loc, 0, (struct rusage *) NULL); +} +#endif +weak_alias(__libc_wait,wait) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/wait3.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/wait3.c new file mode 100644 index 00000000..0d480ec5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/wait3.c @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include + +#if defined __USE_BSD + + +/* Wait for a child to exit. When one does, put its status in *STAT_LOC and + * return its process ID. For errors return (pid_t) -1. If USAGE is not nil, + * store information about the child's resource usage (as a `struct rusage') + * there. If the WUNTRACED bit is set in OPTIONS, return status for stopped + * children; otherwise don't. */ +pid_t wait3 (__WAIT_STATUS stat_loc, int options, struct rusage * usage) +{ + return wait4 (WAIT_ANY, stat_loc, options, usage); +} +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/wait4.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/wait4.c new file mode 100644 index 00000000..dceab41b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/wait4.c @@ -0,0 +1,25 @@ +/* vi: set sw=4 ts=4: */ +/* + * wait4() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#if defined __USE_BSD || defined __USE_XOPEN_EXTENDED +#include +#include + + +#define __NR___syscall_wait4 __NR_wait4 +static __inline__ _syscall4(int, __syscall_wait4, __kernel_pid_t, pid, + int *, status, int, opts, struct rusage *, rusage) + +pid_t wait4(pid_t pid, int *status, int opts, struct rusage *rusage) +{ + return (__syscall_wait4(pid, status, opts, rusage)); +} +libc_hidden_def(wait4) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/waitid.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/waitid.c new file mode 100644 index 00000000..c8115f9a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/waitid.c @@ -0,0 +1,81 @@ +/* vi: set sw=4 ts=4: */ +/* + * Copyright (C) 2007 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +#if defined __USE_SVID || defined __USE_XOPEN +# include +# include +# include +# include + +# ifdef __NR_waitid + +# ifdef __UCLIBC_HAS_THREADS_NATIVE__ +# include +# else +# define SINGLE_THREAD_P 1 +# endif + +/* The waitid() POSIX interface takes 4 arguments, but the kernel function + * actually takes 5. The fifth is a pointer to struct rusage. Make sure + * we pass NULL rather than letting whatever was in the register bleed up. + */ +#define __NR_waitid5 __NR_waitid +static __always_inline +_syscall5(int, waitid5, idtype_t, idtype, id_t, id, siginfo_t*, infop, + int, options, struct rusage*, ru) +# endif + +int waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options) +{ +# ifdef __NR_waitid + if (SINGLE_THREAD_P) + return waitid5(idtype, id, infop, options, NULL); + +# ifdef __UCLIBC_HAS_THREADS_NATIVE__ + int oldtype = LIBC_CANCEL_ASYNC (); + int result = waitid5(idtype, id, infop, options, NULL); + LIBC_CANCEL_RESET (oldtype); + return result; +# endif + +# elif defined __NR_waitpid + switch (idtype) { + case P_PID: + if (id <= 0) + goto invalid; + break; + case P_PGID: + if (id < 0 || id == 1) + goto invalid; + id = -id; + break; + case P_ALL: + id = -1; + break; + default: + invalid: + __set_errno(EINVAL); + return -1; + } + + memset(infop, 0, sizeof *infop); + infop->si_pid = waitpid(id, &infop->si_status, options +# ifdef WEXITED + &~ WEXITED +# endif + ); + if (infop->si_pid < 0) + return infop->si_pid; + return 0; +# else + __set_errno(ENOSYS); + return -1; +# endif +} +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/waitpid.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/waitpid.c new file mode 100644 index 00000000..d0437194 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/waitpid.c @@ -0,0 +1,37 @@ +/* vi: set sw=4 ts=4: */ +/* + * Copyright (C) 2006 Steven J. Hill + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include + +#ifdef __UCLIBC_HAS_THREADS_NATIVE__ +#include "sysdep-cancel.h" +#else +#define SINGLE_THREAD_P 1 +#endif + +libc_hidden_proto(wait4) + +extern __typeof(waitpid) __libc_waitpid; +__pid_t __libc_waitpid(__pid_t pid, int *wait_stat, int options) +{ + if (SINGLE_THREAD_P) + return wait4(pid, wait_stat, options, NULL); + +#ifdef __UCLIBC_HAS_THREADS_NATIVE__ + int oldtype = LIBC_CANCEL_ASYNC (); + int result = wait4(pid, wait_stat, options, NULL); + LIBC_CANCEL_RESET (oldtype); + return result; +#endif +} +libc_hidden_proto(waitpid) +weak_alias(__libc_waitpid,waitpid) +libc_hidden_weak(waitpid) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/write.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/write.c new file mode 100644 index 00000000..5a6f7225 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/write.c @@ -0,0 +1,25 @@ +/* vi: set sw=4 ts=4: */ +/* + * write() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +_syscall3(ssize_t, write, int, fd, const __ptr_t, buf, size_t, count) +#ifndef __LINUXTHREADS_OLD__ +libc_hidden_def(write) +#else +libc_hidden_weak(write) +strong_alias(write,__libc_write) +#endif + +#if 0 +/* Stupid libgcc.a from gcc 2.95.x uses __write in pure.o + * which is a blatant GNU libc-ism... */ +strong_alias(write,__write) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/writev.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/writev.c new file mode 100644 index 00000000..bd0e4077 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/writev.c @@ -0,0 +1,50 @@ +/* vi: set sw=4 ts=4: */ +/* + * writev() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +#ifdef __UCLIBC_HAS_THREADS_NATIVE__ +#include +#include + +/* We should deal with kernel which have a smaller UIO_FASTIOV as well + as a very big count. */ +static ssize_t __writev (int fd, const struct iovec *vector, int count) +{ + ssize_t bytes_written; + + bytes_written = INLINE_SYSCALL (writev, 3, fd, vector, count); + + if (bytes_written >= 0 || errno != EINVAL || count <= UIO_FASTIOV) + return bytes_written; + + /* glibc tries again, but we do not. */ + /* return __atomic_writev_replacement (fd, vector, count); */ + + return -1; +} + +ssize_t writev (int fd, const struct iovec *vector, int count) +{ + if (SINGLE_THREAD_P) + return __writev (fd, vector, count); + + int oldtype = LIBC_CANCEL_ASYNC (); + + ssize_t result = __writev (fd, vector, count); + + LIBC_CANCEL_RESET (oldtype); + + return result; +} +#else +_syscall3(ssize_t, writev, int, filedes, const struct iovec *, vector, + int, count) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/xattr.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/xattr.c new file mode 100644 index 00000000..8a4e3be2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/xattr.c @@ -0,0 +1,164 @@ +/* + * Copyright (C) 2004 + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ +/* This file provides the following Extended Attribute system calls to uClibc. + * + * setxattr(), lsetxattr(), fsetxattr(), + * getxattr(), lgetxattr(), fgetxattr(), + * listxattr(), llistxattr(), flistxattr(), + * removexattr(), lremovexattr(), fremovexattr() + * + * Dec 2004 - + */ + +/* Taken from the manpage. + * On success, a positive number is returned indicating the size of the + * extended attribute name list. On failure, -1 is returned and errno + * is set appropriately. If extended attributes are not supported by the + * filesystem, or are disabled, errno is set to ENOSYS. + */ + +#include +#include +#include + +/* sets */ +#ifdef __NR_setxattr +_syscall5(int, setxattr, const char *, path, const char *, name, + const void *, value, size_t, size, int, flags) +#else +int setxattr(__const char *__path, __const char *__name, + __const void *__value, size_t __size, int __flags) +{ + __set_errno(ENOSYS); + return -1; +} +#endif + +#ifdef __NR_lsetxattr +_syscall5(int, lsetxattr, const char *, path, const char *, name, + const void *, value, size_t, size, int, flags) +#else +int lsetxattr(__const char *__path, __const char *__name, + __const void *__value, size_t __size, int __flags) +{ + __set_errno(ENOSYS); + return -1; +} +#endif + +#ifdef __NR_fsetxattr +_syscall5(int, fsetxattr, int, filedes, const char *, name, const void *, + value, size_t, size, int, flags) +#else +int fsetxattr(int __fd, __const char *__name, __const void *__value, + size_t __size, int __flags) +{ + __set_errno(ENOSYS); + return -1; +} +#endif + +/* gets */ +#ifdef __NR_getxattr +_syscall4(ssize_t, getxattr, const char *, path, const char *, name, + void *, value, size_t, size) +#else +ssize_t getxattr(__const char *__path, __const char *__name, void *__value, + size_t __size) +{ + __set_errno(ENOSYS); + return -1; +} +#endif + +#ifdef __NR_lgetxattr +_syscall4(ssize_t, lgetxattr, const char *, path, const char *, name, + void *, value, size_t, size) +#else +ssize_t lgetxattr(__const char *__path, __const char *__name, + void *__value, size_t __size) +{ + __set_errno(ENOSYS); + return -1; +} +#endif + +#ifdef __NR_fgetxattr +_syscall4(ssize_t, fgetxattr, int, filedes, const char *, name, void *, + value, size_t, size) +#else +ssize_t fgetxattr(int __fd, __const char *__name, void *__value, + size_t __size) +{ + __set_errno(ENOSYS); + return -1; +} +#endif + +/* list */ +#ifdef __NR_listxattr +_syscall3(ssize_t, listxattr, const char *, path, char *, list, size_t, + size) +#else +ssize_t listxattr(__const char *__path, char *__list, size_t __size) +{ + __set_errno(ENOSYS); + return -1; +} +#endif + +#ifdef __NR_llistxattr +_syscall3(ssize_t, llistxattr, const char *, path, char *, list, size_t, + size) +#else +ssize_t llistxattr(__const char *__path, char *__list, size_t __size) +{ + __set_errno(ENOSYS); + return -1; +} +#endif + +#ifdef __NR_flistxattr +_syscall3(ssize_t, flistxattr, int, filedes, char *, list, size_t, size) +#else +ssize_t flistxattr(int __fd, char *__list, size_t __size) +{ + __set_errno(ENOSYS); + return -1; +} +#endif + +/* remove */ +#ifdef __NR_removexattr +_syscall2(int, removexattr, const char *, path, const char *, name) +#else +int removexattr(__const char *__path, __const char *__name) +{ + __set_errno(ENOSYS); + return -1; +} +#endif + +#ifdef __NR_lremovexattr +_syscall2(int, lremovexattr, const char *, path, const char *, name) +#else +int lremovexattr(__const char *__path, __const char *__name) +{ + __set_errno(ENOSYS); + return -1; +} +#endif + +#ifdef __NR_fremovexattr +_syscall2(int, fremovexattr, int, filedes, const char *, name) +#else +int fremovexattr(int __fd, __const char *__name) +{ + __set_errno(ENOSYS); + return -1; +} +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/xstatconv.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/xstatconv.c new file mode 100644 index 00000000..deef3929 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/xstatconv.c @@ -0,0 +1,90 @@ +/* Convert between the kernel's `struct stat' format, and libc's. + Copyright (C) 1991,1995,1996,1997,2000,2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. + + Modified for uClibc by Erik Andersen + */ + +#include +#include +#include +#include "xstatconv.h" + +void __xstat_conv(struct kernel_stat *kbuf, struct stat *buf) +{ + /* Convert to current kernel version of `struct stat'. */ + memset(buf, 0x00, sizeof(*buf)); + buf->st_dev = kbuf->st_dev; + buf->st_ino = kbuf->st_ino; + buf->st_mode = kbuf->st_mode; + buf->st_nlink = kbuf->st_nlink; + buf->st_uid = kbuf->st_uid; + buf->st_gid = kbuf->st_gid; + buf->st_rdev = kbuf->st_rdev; + buf->st_size = kbuf->st_size; + buf->st_blksize = kbuf->st_blksize; + buf->st_blocks = kbuf->st_blocks; + buf->st_atim = kbuf->st_atim; + buf->st_mtim = kbuf->st_mtim; + buf->st_ctim = kbuf->st_ctim; +} + +void __xstat32_conv(struct kernel_stat64 *kbuf, struct stat *buf) +{ + /* Convert to current kernel version of `struct stat64'. */ + memset(buf, 0x00, sizeof(*buf)); + buf->st_dev = kbuf->st_dev; + buf->st_ino = kbuf->st_ino; + buf->st_mode = kbuf->st_mode; + buf->st_nlink = kbuf->st_nlink; + buf->st_uid = kbuf->st_uid; + buf->st_gid = kbuf->st_gid; + buf->st_rdev = kbuf->st_rdev; + buf->st_size = kbuf->st_size; + buf->st_blksize = kbuf->st_blksize; + buf->st_blocks = kbuf->st_blocks; + buf->st_atim = kbuf->st_atim; + buf->st_mtim = kbuf->st_mtim; + buf->st_ctim = kbuf->st_ctim; +} + +#ifdef __UCLIBC_HAS_LFS__ + +void __xstat64_conv(struct kernel_stat64 *kbuf, struct stat64 *buf) +{ + /* Convert to current kernel version of `struct stat64'. */ + memset(buf, 0x00, sizeof(*buf)); + buf->st_dev = kbuf->st_dev; + buf->st_ino = kbuf->st_ino; +# ifdef _HAVE_STAT64___ST_INO + buf->__st_ino = kbuf->__st_ino; +# endif + buf->st_mode = kbuf->st_mode; + buf->st_nlink = kbuf->st_nlink; + buf->st_uid = kbuf->st_uid; + buf->st_gid = kbuf->st_gid; + buf->st_rdev = kbuf->st_rdev; + buf->st_size = kbuf->st_size; + buf->st_blksize = kbuf->st_blksize; + buf->st_blocks = kbuf->st_blocks; + buf->st_atim = kbuf->st_atim; + buf->st_mtim = kbuf->st_mtim; + buf->st_ctim = kbuf->st_ctim; +} + +#endif /* __UCLIBC_HAS_LFS__ */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/xstatconv.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/xstatconv.h new file mode 100644 index 00000000..7568da85 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/common/xstatconv.h @@ -0,0 +1,33 @@ +/* Convert between the kernel's `struct stat' format, and libc's. + Copyright (C) 1991,1995,1996,1997,2000,2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. + + Modified for uClibc by Erik Andersen + */ + +/* Pull in whatever this particular arch's kernel thinks the kernel version of + * struct stat should look like. It turns out that each arch has a different + * opinion on the subject, and different kernel revs use different names... */ +#include + +extern void __xstat_conv(struct kernel_stat *kbuf, struct stat *buf) attribute_hidden; +extern void __xstat32_conv(struct kernel_stat64 *kbuf, struct stat *buf) attribute_hidden; +#if defined __UCLIBC_HAS_LFS__ +extern void __xstat64_conv(struct kernel_stat64 *kbuf, struct stat64 *buf) attribute_hidden; +#endif + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/Makefile new file mode 100644 index 00000000..633c91f3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../../ +top_builddir=../../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.arch +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/Makefile.arch b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/Makefile.arch new file mode 100644 index 00000000..43e19120 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/Makefile.arch @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +CSRC := __init_brk.c brk.c sbrk.c + +SSRC := setjmp.S __longjmp.S clone.S sysdep.S syscall.S +ifeq ($(UNIFIED_SYSCALL),y) +SSRC += __uClibc_syscall.S +endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/__init_brk.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/__init_brk.c new file mode 100644 index 00000000..27b8524b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/__init_brk.c @@ -0,0 +1,32 @@ +/* From libc-5.3.12 */ + +#include +#include +#include +#include "sysdep.h" + +void * __curbrk attribute_hidden = 0; + +extern int __init_brk (void) attribute_hidden; +int +__init_brk (void) +{ + if (__curbrk == 0) { + /* Notice that we don't need to save/restore the GOT + * register since that is not call clobbered by the syscall. + */ + __asm__ ("clear.d $r10\n\t" + "movu.w " STR(__NR_brk) ",$r9\n\t" + "break 13\n\t" + "move.d $r10, %0" + : "=r" (__curbrk) + : + : "r9", "r10"); + + if (__curbrk == 0) { + __set_errno(ENOMEM); + return -1; + } + } + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/__longjmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/__longjmp.S new file mode 100644 index 00000000..52a986fd --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/__longjmp.S @@ -0,0 +1,62 @@ +/* longjmp for CRIS. + Copyright (C) 2001, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include "sysdep.h" +#define _SETJMP_H +#define _ASM +#include + + .syntax no_register_prefix + +/* Saving and restoring CCR is meaningless, so we don't do it. */ +ENTRY (__longjmp) + /* Note that r10 = jmp_buf, r11 = retval. */ +#ifdef __arch_v32 + + /* We don't restore the call-clobbered registers for v32; + their space (corresponding to v10) is now defined as + reserved. */ + movem [r10],r9 + addq 14*4,r10 + cmpq 0,r11 + beq 0f + move.d [r10+],sp + + move.d r11,r9 +0: + move.d [r10+],acr + jump acr + move [r10],srp + +#else + + move [r10+16*4],srp + test.d r11 + beq 0f /* Already a 1 in place. */ + nop + /* Offset for r9, the return value (see setjmp). */ + move.d r11,[r10+6*4] +0: + movem [r10],pc + +#endif +END (__longjmp) + +libc_hidden_def(__longjmp) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/bits/byteswap.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/bits/byteswap.h new file mode 100644 index 00000000..a82f9c09 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/bits/byteswap.h @@ -0,0 +1,20 @@ +#ifndef _ASM_BITS_BYTESWAP_H +#define _ASM_BITS_BYTESWAP_H 1 + +/* CRIS specific byte swap operations: 16, 32 and 64-bit */ + +#define __bswap_non_constant_16(x) \ + __extension__ \ + ({ unsigned short __bswap_16_v; \ + __asm__ ("swapb %0" : "=r" (__bswap_16_v) : "0" (x)); \ + __bswap_16_v; }) + +#define __bswap_non_constant_32(x) \ + __extension__ \ + ({ unsigned int __bswap_32_v; \ + __asm__ ("swapwb %0" : "=r" (__bswap_32_v) : "0" (x)); \ + __bswap_32_v; }) + +#endif + +#include diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/bits/endian.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/bits/endian.h new file mode 100644 index 00000000..90e290b9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/bits/endian.h @@ -0,0 +1,7 @@ +/* cris is little-endian. */ + +#ifndef _ENDIAN_H +# error "Never use directly; include instead." +#endif + +#define __BYTE_ORDER __LITTLE_ENDIAN diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/bits/fcntl.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/bits/fcntl.h new file mode 100644 index 00000000..29443ba0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/bits/fcntl.h @@ -0,0 +1,239 @@ +/* O_*, F_*, FD_* bit values for Linux. + Copyright (C) 1995, 1996, 1997, 1998, 2000, 2001, 2004 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FCNTL_H +# error "Never use directly; include instead." +#endif + + +#include +#ifdef __USE_GNU +# include +#endif + +/* open/fcntl - O_SYNC is only implemented on blocks devices and on files + located on an ext2 file system */ +#define O_ACCMODE 0003 +#define O_RDONLY 00 +#define O_WRONLY 01 +#define O_RDWR 02 +#define O_CREAT 0100 /* not fcntl */ +#define O_EXCL 0200 /* not fcntl */ +#define O_NOCTTY 0400 /* not fcntl */ +#define O_TRUNC 01000 /* not fcntl */ +#define O_APPEND 02000 +#define O_NONBLOCK 04000 +#define O_NDELAY O_NONBLOCK +#define O_SYNC 010000 +#define O_FSYNC O_SYNC +#define O_ASYNC 020000 + +#ifdef __USE_GNU +# define O_DIRECT 040000 /* Direct disk access. */ +# define O_DIRECTORY 0200000 /* Must be a directory. */ +# define O_NOFOLLOW 0400000 /* Do not follow links. */ +# define O_NOATIME 01000000 /* Do not set atime. */ +# define O_CLOEXEC 02000000 /* set close_on_exec */ +#endif + +/* For now Linux has synchronisity options for data and read operations. + We define the symbols here but let them do the same as O_SYNC since + this is a superset. */ +#if defined __USE_POSIX199309 || defined __USE_UNIX98 +# define O_DSYNC O_SYNC /* Synchronize data. */ +# define O_RSYNC O_SYNC /* Synchronize read operations. */ +#endif + +#ifdef __USE_LARGEFILE64 +# define O_LARGEFILE 0100000 +#endif + +/* Values for the second argument to `fcntl'. */ +#define F_DUPFD 0 /* Duplicate file descriptor. */ +#define F_GETFD 1 /* Get file descriptor flags. */ +#define F_SETFD 2 /* Set file descriptor flags. */ +#define F_GETFL 3 /* Get file status flags. */ +#define F_SETFL 4 /* Set file status flags. */ +#ifndef __USE_FILE_OFFSET64 +# define F_GETLK 5 /* Get record locking info. */ +# define F_SETLK 6 /* Set record locking info (non-blocking). */ +# define F_SETLKW 7 /* Set record locking info (blocking). */ +#else +# define F_GETLK F_GETLK64 /* Get record locking info. */ +# define F_SETLK F_SETLK64 /* Set record locking info (non-blocking).*/ +# define F_SETLKW F_SETLKW64 /* Set record locking info (blocking). */ +#endif +#define F_GETLK64 12 /* Get record locking info. */ +#define F_SETLK64 13 /* Set record locking info (non-blocking). */ +#define F_SETLKW64 14 /* Set record locking info (blocking). */ + +#if defined __USE_BSD || defined __USE_UNIX98 +# define F_SETOWN 8 /* Get owner of socket (receiver of SIGIO). */ +# define F_GETOWN 9 /* Set owner of socket (receiver of SIGIO). */ +#endif + +#ifdef __USE_GNU +# define F_SETSIG 10 /* Set number of signal to be sent. */ +# define F_GETSIG 11 /* Get number of signal to be sent. */ +#endif + +#ifdef __USE_GNU +# define F_SETLEASE 1024 /* Set a lease. */ +# define F_GETLEASE 1025 /* Enquire what lease is active. */ +# define F_NOTIFY 1026 /* Request notfications on a directory. */ +# define F_DUPFD_CLOEXEC 1030 /* Duplicate file descriptor with + close-on-exit set on new fd. */ +#endif + +/* For F_[GET|SET]FL. */ +#define FD_CLOEXEC 1 /* actually anything with low bit set goes */ + +/* For posix fcntl() and `l_type' field of a `struct flock' for lockf(). */ +#define F_RDLCK 0 /* Read lock. */ +#define F_WRLCK 1 /* Write lock. */ +#define F_UNLCK 2 /* Remove lock. */ + +/* For old implementation of bsd flock(). */ +#define F_EXLCK 4 /* or 3 */ +#define F_SHLCK 8 /* or 4 */ + +#ifdef __USE_BSD +/* Operations for bsd flock(), also used by the kernel implementation. */ +# define LOCK_SH 1 /* shared lock */ +# define LOCK_EX 2 /* exclusive lock */ +# define LOCK_NB 4 /* or'd with one of the above to prevent + blocking */ +# define LOCK_UN 8 /* remove lock */ +#endif + +#ifdef __USE_GNU +# define LOCK_MAND 32 /* This is a mandatory flock: */ +# define LOCK_READ 64 /* ... which allows concurrent read operations. */ +# define LOCK_WRITE 128 /* ... which allows concurrent write operations. */ +# define LOCK_RW 192 /* ... Which allows concurrent read & write operations. */ +#endif + +#ifdef __USE_GNU +/* Types of directory notifications that may be requested with F_NOTIFY. */ +# define DN_ACCESS 0x00000001 /* File accessed. */ +# define DN_MODIFY 0x00000002 /* File modified. */ +# define DN_CREATE 0x00000004 /* File created. */ +# define DN_DELETE 0x00000008 /* File removed. */ +# define DN_RENAME 0x00000010 /* File renamed. */ +# define DN_ATTRIB 0x00000020 /* File changed attibutes. */ +# define DN_MULTISHOT 0x80000000 /* Don't remove notifier. */ +#endif + +struct flock + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ +#ifndef __USE_FILE_OFFSET64 + __off_t l_start; /* Offset where the lock begins. */ + __off_t l_len; /* Size of the locked area; zero means until EOF. */ +#else + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ +#endif + __pid_t l_pid; /* Process holding the lock. */ + }; + +#ifdef __USE_LARGEFILE64 +struct flock64 + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ + __pid_t l_pid; /* Process holding the lock. */ + }; +#endif + +/* Define some more compatibility macros to be backward compatible with + BSD systems which did not managed to hide these kernel macros. */ +#ifdef __USE_BSD +# define FAPPEND O_APPEND +# define FFSYNC O_FSYNC +# define FASYNC O_ASYNC +# define FNONBLOCK O_NONBLOCK +# define FNDELAY O_NDELAY +#endif /* Use BSD. */ + +/* Advise to `posix_fadvise'. */ +#ifdef __USE_XOPEN2K +# define POSIX_FADV_NORMAL 0 /* No further special treatment. */ +# define POSIX_FADV_RANDOM 1 /* Expect random page references. */ +# define POSIX_FADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define POSIX_FADV_WILLNEED 3 /* Will need these pages. */ +# define POSIX_FADV_DONTNEED 4 /* Don't need these pages. */ +# define POSIX_FADV_NOREUSE 5 /* Data will be accessed once. */ +#endif + + +#if defined __USE_GNU && defined __UCLIBC_LINUX_SPECIFIC__ +/* Flags for SYNC_FILE_RANGE. */ +# define SYNC_FILE_RANGE_WAIT_BEFORE 1 /* Wait upon writeout of all pages + in the range before performing the + write. */ +# define SYNC_FILE_RANGE_WRITE 2 /* Initiate writeout of all those + dirty pages in the range which are + not presently under writeback. */ +# define SYNC_FILE_RANGE_WAIT_AFTER 4 /* Wait upon writeout of all pages in + the range after performing the + write. */ + +/* Flags for SPLICE and VMSPLICE. */ +# define SPLICE_F_MOVE 1 /* Move pages instead of copying. */ +# define SPLICE_F_NONBLOCK 2 /* Don't block on the pipe splicing + (but we may still block on the fd + we splice from/to). */ +# define SPLICE_F_MORE 4 /* Expect more data. */ +# define SPLICE_F_GIFT 8 /* Pages passed in are a gift. */ +#endif + +__BEGIN_DECLS + +#if defined __USE_GNU && defined __UCLIBC_LINUX_SPECIFIC__ + +/* Provide kernel hint to read ahead. */ +extern ssize_t readahead (int __fd, __off64_t __offset, size_t __count) + __THROW; + + +/* Selective file content synch'ing. */ +extern int sync_file_range (int __fd, __off64_t __from, __off64_t __to, + unsigned int __flags); + +/* Splice address range into a pipe. */ +extern ssize_t vmsplice (int __fdout, const struct iovec *__iov, + size_t __count, unsigned int __flags); + +/* Splice two files together. */ +extern ssize_t splice (int __fdin, __off64_t *__offin, int __fdout, + __off64_t *__offout, size_t __len, + unsigned int __flags); + +/* In-kernel implementation of tee for pipe buffers. */ +extern ssize_t tee (int __fdin, int __fdout, size_t __len, + unsigned int __flags); + +#endif +__END_DECLS + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/bits/kernel_stat.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/bits/kernel_stat.h new file mode 100644 index 00000000..b54f2921 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/bits/kernel_stat.h @@ -0,0 +1,62 @@ +/* Taken from linux/include/asm-cris/stat.h */ + +#ifndef _CRIS_STAT_H +#define _CRIS_STAT_H + +#ifndef _LIBC +#error bits/kernel_stat.h is for internal uClibc use only! +#endif + +struct kernel_stat { + unsigned short st_dev; + unsigned short __pad1; + unsigned long st_ino; + unsigned short st_mode; + unsigned short st_nlink; + unsigned short st_uid; + unsigned short st_gid; + unsigned short st_rdev; + unsigned short __pad2; + unsigned long st_size; + unsigned long st_blksize; + unsigned long st_blocks; + struct timespec st_atim; + struct timespec st_mtim; + struct timespec st_ctim; + unsigned long __unused4; + unsigned long __unused5; +}; + +/* This matches struct kernel_stat64 in glibc2.1, hence the absolutely + * insane amounts of padding around dev_t's. + */ +struct kernel_stat64 { + unsigned short st_dev; + unsigned char __pad0[10]; + +#define _HAVE_STAT64___ST_INO + unsigned long __st_ino; + + unsigned int st_mode; + unsigned int st_nlink; + + unsigned long st_uid; + unsigned long st_gid; + + unsigned short st_rdev; + unsigned char __pad3[10]; + + long long st_size; + unsigned long st_blksize; + + unsigned long st_blocks; /* Number 512-byte blocks allocated. */ + unsigned long __pad4; /* future possible st_blocks high bits */ + + struct timespec st_atim; + struct timespec st_mtim; + struct timespec st_ctim; + + unsigned long long st_ino; +}; + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/bits/kernel_types.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/bits/kernel_types.h new file mode 100644 index 00000000..f122c7f5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/bits/kernel_types.h @@ -0,0 +1,46 @@ +/* Taken from linux/include/asm-cris/posix_types.h */ + +#ifndef __ARCH_CRIS_POSIX_TYPES_H +#define __ARCH_CRIS_POSIX_TYPES_H + +typedef unsigned short __kernel_dev_t; +typedef unsigned long __kernel_ino_t; +typedef unsigned short __kernel_mode_t; +typedef unsigned short __kernel_nlink_t; +typedef long __kernel_off_t; +typedef int __kernel_pid_t; +typedef unsigned short __kernel_ipc_pid_t; +typedef unsigned short __kernel_uid_t; +typedef unsigned short __kernel_gid_t; +typedef unsigned long __kernel_size_t; +typedef long __kernel_ssize_t; +typedef int __kernel_ptrdiff_t; +typedef long __kernel_time_t; +typedef long __kernel_suseconds_t; +typedef long __kernel_clock_t; +typedef int __kernel_daddr_t; +typedef char * __kernel_caddr_t; +typedef unsigned short __kernel_uid16_t; +typedef unsigned short __kernel_gid16_t; +typedef unsigned int __kernel_uid32_t; +typedef unsigned int __kernel_gid32_t; + +typedef unsigned short __kernel_old_uid_t; +typedef unsigned short __kernel_old_gid_t; +typedef __kernel_dev_t __kernel_old_dev_t; + +#ifdef __GNUC__ +typedef long long __kernel_loff_t; +#endif + +typedef struct { +#if defined(__USE_ALL) + int val[2]; +#else + int __val[2]; +#endif + } __kernel_fsid_t; + +/* should this ifdef be here ? */ + +#endif /* __ARCH_CRIS_POSIX_TYPES_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/bits/setjmp.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/bits/setjmp.h new file mode 100644 index 00000000..2a29c8ca --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/bits/setjmp.h @@ -0,0 +1,66 @@ +/* Copyright (C) 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Define the machine-dependent type `jmp_buf'. CRIS version. */ +#ifndef _BITS_SETJMP_H +#define _BITS_SETJMP_H 1 + +#if !defined _SETJMP_H && !defined _PTHREAD_H +# error "Never include directly; use instead." +#endif + +/* + Note that we save and restore CCR to be able to + correctly handle DI/EI. Note also that the "move x,ccr" does NOT affect + the DMA enable bits (E and D). + + jmp_buf[0] - PC + jmp_buf[1] - SP (R14) + jmp_buf[2] - R13 + jmp_buf[3] - R12 + jmp_buf[4] - R11 + jmp_buf[5] - R10 + jmp_buf[6] - R9 + jmp_buf[7] - R8 + jmp_buf[8] - R7 + jmp_buf[9] - R6 + jmp_buf[10] - R5 + jmp_buf[11] - R4 + jmp_buf[12] - R3 + jmp_buf[13] - R2 + jmp_buf[14] - R1 + jmp_buf[15] - R0 + jmp_buf[16] - SRP + jmp_buf[17] - CCR + */ + +#define _JBLEN 18 +#if defined (__USE_MISC) || defined (_ASM) +#define JB_SP 1 +#endif + +#ifndef _ASM +typedef int __jmp_buf[_JBLEN]; +#endif + +/* Test if longjmp to JMPBUF would unwind the frame + containing a local variable at ADDRESS. */ +#define _JMPBUF_UNWINDS(jmpbuf, address) \ + ((void *) (address) < (void *) (jmpbuf)[JB_SP]) + +#endif /* bits/setjmp.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/bits/stackinfo.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/bits/stackinfo.h new file mode 100644 index 00000000..43c94483 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/bits/stackinfo.h @@ -0,0 +1,28 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This file contains a bit of information about the stack allocation + of the processor. */ + +#ifndef _STACKINFO_H +#define _STACKINFO_H 1 + +/* On cris the stack grows down. */ +#define _STACK_GROWS_DOWN 1 + +#endif /* stackinfo.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/bits/syscalls.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/bits/syscalls.h new file mode 100644 index 00000000..9db08407 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/bits/syscalls.h @@ -0,0 +1,95 @@ +#ifndef _BITS_SYSCALLS_H +#define _BITS_SYSCALLS_H + +#ifndef _SYSCALL_H +#error "Never use directly; include instead." +#endif + +#ifndef __ASSEMBLER__ + +#define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \ + ({ \ + register unsigned long __res __asm__ ("r10"); \ + LOAD_ARGS_c_##nr(args) \ + register unsigned long __callno __asm__ ("r9") \ + = name; \ + __asm__ __volatile__ (LOAD_ARGS_asm_##nr (args) \ + CHECK_ARGS_asm_##nr \ + "break 13" \ + : "=r" (__res) \ + : ASM_ARGS_##nr (args) \ + : ASM_CLOBBER_##nr); \ + __res; \ + }) + +#define LOAD_ARGS_c_0() +#define LOAD_ARGS_asm_0() +#define ASM_CLOBBER_0 "memory" +#define ASM_ARGS_0() "r" (__callno) +#define CHECK_ARGS_asm_0 + +#define LOAD_ARGS_c_1(r10) \ + LOAD_ARGS_c_0() \ + register unsigned long __r10 __asm__ ("r10") = (unsigned long) (r10); +#define LOAD_ARGS_asm_1(r10) LOAD_ARGS_asm_0 () +#define ASM_CLOBBER_1 ASM_CLOBBER_0 +#define ASM_ARGS_1(r10) ASM_ARGS_0 (), "0" (__r10) +#define CHECK_ARGS_asm_1 \ + ".ifnc %0,$r10\n\t" \ + ".err\n\t" \ + ".endif\n\t" + +#define LOAD_ARGS_c_2(r10, r11) \ + LOAD_ARGS_c_1(r10) \ + register unsigned long __r11 __asm__ ("r11") = (unsigned long) (r11); +#define LOAD_ARGS_asm_2(r10, r11) LOAD_ARGS_asm_1 (r10) +#define ASM_CLOBBER_2 ASM_CLOBBER_1 +#define ASM_ARGS_2(r10, r11) ASM_ARGS_1 (r10), "r" (__r11) +#define CHECK_ARGS_asm_2 \ + ".ifnc %0-%3,$r10-$r11\n\t" \ + ".err\n\t" \ + ".endif\n\t" + +#define LOAD_ARGS_c_3(r10, r11, r12) \ + LOAD_ARGS_c_2(r10, r11) \ + register unsigned long __r12 __asm__ ("r12") = (unsigned long) (r12); +#define LOAD_ARGS_asm_3(r10, r11, r12) LOAD_ARGS_asm_2 (r10, r11) +#define ASM_CLOBBER_3 ASM_CLOBBER_2 +#define ASM_ARGS_3(r10, r11, r12) ASM_ARGS_2 (r10, r11), "r" (__r12) +#define CHECK_ARGS_asm_3 \ + ".ifnc %0-%3-%4,$r10-$r11-$r12\n\t" \ + ".err\n\t" \ + ".endif\n\t" + +#define LOAD_ARGS_c_4(r10, r11, r12, r13) \ + LOAD_ARGS_c_3(r10, r11, r12) \ + register unsigned long __r13 __asm__ ("r13") = (unsigned long) (r13); +#define LOAD_ARGS_asm_4(r10, r11, r12, r13) LOAD_ARGS_asm_3 (r10, r11, r12) +#define ASM_CLOBBER_4 ASM_CLOBBER_3 +#define ASM_ARGS_4(r10, r11, r12, r13) ASM_ARGS_3 (r10, r11, r12), "r" (__r13) +#define CHECK_ARGS_asm_4 \ + ".ifnc %0-%3-%4-%5,$r10-$r11-$r12-$r13\n\t" \ + ".err\n\t" \ + ".endif\n\t" + +#define LOAD_ARGS_c_5(r10, r11, r12, r13, mof) \ + LOAD_ARGS_c_4(r10, r11, r12, r13) +#define LOAD_ARGS_asm_5(r10, r11, r12, r13, mof) \ + LOAD_ARGS_asm_4 (r10, r11, r12, r13) "move %6,$mof\n\t" +#define ASM_CLOBBER_5 ASM_CLOBBER_4 +#define ASM_ARGS_5(r10, r11, r12, r13, mof) \ + ASM_ARGS_4 (r10, r11, r12, r13), "g" (mof) +#define CHECK_ARGS_asm_5 CHECK_ARGS_asm_4 + +#define LOAD_ARGS_c_6(r10, r11, r12, r13, mof, srp) \ + LOAD_ARGS_c_5(r10, r11, r12, r13, mof) +#define LOAD_ARGS_asm_6(r10, r11, r12, r13, mof, srp) \ + LOAD_ARGS_asm_5(r10, r11, r12, r13, mof) \ + "move %7,$srp\n\t" +#define ASM_CLOBBER_6 ASM_CLOBBER_5, "srp" +#define ASM_ARGS_6(r10, r11, r12, r13, mof, srp) \ + ASM_ARGS_5 (r10, r11, r12, r13, mof), "g" (srp) +#define CHECK_ARGS_asm_6 CHECK_ARGS_asm_5 + +#endif /* not __ASSEMBLER__ */ +#endif /* _BITS_SYSCALLS_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/bits/termios.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/bits/termios.h new file mode 100644 index 00000000..63ca4ea9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/bits/termios.h @@ -0,0 +1,215 @@ +/* termios type and macro definitions. Linux version. + Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2003, 2005 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _TERMIOS_H +# error "Never include directly; use instead." +#endif + +typedef unsigned char cc_t; +typedef unsigned int speed_t; +typedef unsigned int tcflag_t; + +#define NCCS 32 +struct termios + { + tcflag_t c_iflag; /* input mode flags */ + tcflag_t c_oflag; /* output mode flags */ + tcflag_t c_cflag; /* control mode flags */ + tcflag_t c_lflag; /* local mode flags */ + cc_t c_line; /* line discipline */ + cc_t c_cc[NCCS]; /* control characters */ + speed_t c_ispeed; /* input speed */ + speed_t c_ospeed; /* output speed */ +#define _HAVE_STRUCT_TERMIOS_C_ISPEED 1 +#define _HAVE_STRUCT_TERMIOS_C_OSPEED 1 + }; + +/* c_cc characters */ +#define VINTR 0 +#define VQUIT 1 +#define VERASE 2 +#define VKILL 3 +#define VEOF 4 +#define VTIME 5 +#define VMIN 6 +#define VSWTC 7 +#define VSTART 8 +#define VSTOP 9 +#define VSUSP 10 +#define VEOL 11 +#define VREPRINT 12 +#define VDISCARD 13 +#define VWERASE 14 +#define VLNEXT 15 +#define VEOL2 16 + +/* c_iflag bits */ +#define IGNBRK 0000001 +#define BRKINT 0000002 +#define IGNPAR 0000004 +#define PARMRK 0000010 +#define INPCK 0000020 +#define ISTRIP 0000040 +#define INLCR 0000100 +#define IGNCR 0000200 +#define ICRNL 0000400 +#define IUCLC 0001000 +#define IXON 0002000 +#define IXANY 0004000 +#define IXOFF 0010000 +#define IMAXBEL 0020000 +#define IUTF8 0040000 + +/* c_oflag bits */ +#define OPOST 0000001 +#define OLCUC 0000002 +#define ONLCR 0000004 +#define OCRNL 0000010 +#define ONOCR 0000020 +#define ONLRET 0000040 +#define OFILL 0000100 +#define OFDEL 0000200 +#if defined __USE_MISC || defined __USE_XOPEN +# define NLDLY 0000400 +# define NL0 0000000 +# define NL1 0000400 +# define CRDLY 0003000 +# define CR0 0000000 +# define CR1 0001000 +# define CR2 0002000 +# define CR3 0003000 +# define TABDLY 0014000 +# define TAB0 0000000 +# define TAB1 0004000 +# define TAB2 0010000 +# define TAB3 0014000 +# define BSDLY 0020000 +# define BS0 0000000 +# define BS1 0020000 +# define FFDLY 0100000 +# define FF0 0000000 +# define FF1 0100000 +#endif + +#define VTDLY 0040000 +#define VT0 0000000 +#define VT1 0040000 + +#ifdef __USE_MISC +# define XTABS 0014000 +#endif + +/* c_cflag bit meaning */ +#ifdef __USE_MISC +# define CBAUD 0010017 +#endif +#define B0 0000000 /* hang up */ +#define B50 0000001 +#define B75 0000002 +#define B110 0000003 +#define B134 0000004 +#define B150 0000005 +#define B200 0000006 +#define B300 0000007 +#define B600 0000010 +#define B1200 0000011 +#define B1800 0000012 +#define B2400 0000013 +#define B4800 0000014 +#define B9600 0000015 +#define B19200 0000016 +#define B38400 0000017 +#ifdef __USE_MISC +# define EXTA B19200 +# define EXTB B38400 +#endif +#define CSIZE 0000060 +#define CS5 0000000 +#define CS6 0000020 +#define CS7 0000040 +#define CS8 0000060 +#define CSTOPB 0000100 +#define CREAD 0000200 +#define PARENB 0000400 +#define PARODD 0001000 +#define HUPCL 0002000 +#define CLOCAL 0004000 +#ifdef __USE_MISC +# define CBAUDEX 0010000 +#endif +#define B57600 0010001 +#define B115200 0010002 +#define B230400 0010003 +#define B460800 0010004 +#define B921600 0010005 +#define B1843200 0010006 +#define B6250000 0010007 +#ifdef __arch_v32 +#define B12500000 0010010 +#define __MAX_BAUD B12500000 +#else +#define __MAX_BAUD B6250000 +#endif +#ifdef __USE_MISC +# define CIBAUD 002003600000 /* input baud rate (not used) */ +# define CMSPAR 010000000000 /* mark or space (stick) parity */ +# define CRTSCTS 020000000000 /* flow control */ +#endif + +/* c_lflag bits */ +#define ISIG 0000001 +#define ICANON 0000002 +#if defined __USE_MISC || defined __USE_XOPEN +# define XCASE 0000004 +#endif +#define ECHO 0000010 +#define ECHOE 0000020 +#define ECHOK 0000040 +#define ECHONL 0000100 +#define NOFLSH 0000200 +#define TOSTOP 0000400 +#ifdef __USE_MISC +# define ECHOCTL 0001000 +# define ECHOPRT 0002000 +# define ECHOKE 0004000 +# define FLUSHO 0010000 +# define PENDIN 0040000 +#endif +#define IEXTEN 0100000 + +/* tcflow() and TCXONC use these */ +#define TCOOFF 0 +#define TCOON 1 +#define TCIOFF 2 +#define TCION 3 + +/* tcflush() and TCFLSH use these */ +#define TCIFLUSH 0 +#define TCOFLUSH 1 +#define TCIOFLUSH 2 + +/* tcsetattr uses these */ +#define TCSANOW 0 +#define TCSADRAIN 1 +#define TCSAFLUSH 2 + + +#define _IOT_termios /* Hurd ioctl type field. */ \ + _IOT (_IOTS (cflag_t), 4, _IOTS (cc_t), NCCS, _IOTS (speed_t), 2) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/bits/uClibc_arch_features.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/bits/uClibc_arch_features.h new file mode 100644 index 00000000..fc149461 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/bits/uClibc_arch_features.h @@ -0,0 +1,48 @@ +/* + * Track misc arch-specific features that aren't config options + */ + +#ifndef _BITS_UCLIBC_ARCH_FEATURES_H +#define _BITS_UCLIBC_ARCH_FEATURES_H + +/* instruction used when calling abort() to kill yourself */ +/*#define __UCLIBC_ABORT_INSTRUCTION__ "asm instruction"*/ +#undef __UCLIBC_ABORT_INSTRUCTION__ + +/* can your target use syscall6() for mmap ? */ +#undef __UCLIBC_MMAP_HAS_6_ARGS__ + +/* does your target use syscall4() for truncate64 ? (32bit arches only) */ +#undef __UCLIBC_TRUNCATE64_HAS_4_ARGS__ + +/* does your target have a broken create_module() ? */ +#define __UCLIBC_BROKEN_CREATE_MODULE__ + +/* does your target have to worry about older [gs]etrlimit() ? */ +#undef __UCLIBC_HANDLE_OLDER_RLIMIT__ + +/* does your target have an asm .set ? */ +#define __UCLIBC_HAVE_ASM_SET_DIRECTIVE__ + +/* define if target doesn't like .global */ +#undef __UCLIBC_ASM_GLOBAL_DIRECTIVE__ + +/* define if target supports .weak */ +#define __UCLIBC_HAVE_ASM_WEAK_DIRECTIVE__ + +/* define if target supports .weakext */ +#undef __UCLIBC_HAVE_ASM_WEAKEXT_DIRECTIVE__ + +/* needed probably only for ppc64 */ +#undef __UCLIBC_HAVE_ASM_GLOBAL_DOT_NAME__ + +/* define if target supports CFI pseudo ops */ +#undef __UCLIBC_HAVE_ASM_CFI_DIRECTIVES__ + +/* define if target supports IEEE signed zero floats */ +#define __UCLIBC_HAVE_SIGNED_ZERO__ + +/* only weird assemblers generally need this */ +#define __UCLIBC_ASM_LINE_SEP__ @ + +#endif /* _BITS_UCLIBC_ARCH_FEATURES_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/bits/uClibc_page.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/bits/uClibc_page.h new file mode 100644 index 00000000..adfc3c9a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/bits/uClibc_page.h @@ -0,0 +1,34 @@ +/* Copyright (C) 2004 Erik Andersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* Supply an architecture specific value for PAGE_SIZE and friends. */ + +#ifndef _UCLIBC_PAGE_H +#define _UCLIBC_PAGE_H + +/* PAGE_SHIFT determines the page size -- in this case 8192 */ +#define PAGE_SHIFT 13 +#define PAGE_SIZE (1UL << PAGE_SHIFT) +#define PAGE_MASK (~(PAGE_SIZE-1)) + +/* Some architectures always use 12 as page shift for mmap2() eventhough the + * real PAGE_SHIFT != 12. Other architectures use the same value as + * PAGE_SHIFT... + */ +#define MMAP2_PAGE_SHIFT PAGE_SHIFT + +#endif /* _UCLIBC_PAGE_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/bits/wordsize.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/bits/wordsize.h new file mode 100644 index 00000000..d6a2fc68 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/bits/wordsize.h @@ -0,0 +1,19 @@ +/* Copyright (C) 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#define __WORDSIZE 32 diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/brk.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/brk.c new file mode 100644 index 00000000..6c877bb9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/brk.c @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include "sysdep.h" + +extern void * __curbrk attribute_hidden; +extern int __init_brk (void) attribute_hidden; + +int brk(void * end_data_seg) +{ + if (__init_brk () == 0) { + /* + * Notice that we don't need to save/restore the GOT + * register since that is not call clobbered by the syscall. + */ + __asm__ ("move.d %1,$r10\n\t" + "movu.w " STR(__NR_brk) ",$r9\n\t" + "break 13\n\t" + "move.d $r10, %0" + : "=r" (__curbrk) + : "g" (end_data_seg) + : "r9", "r10"); + + if (__curbrk == end_data_seg) + return 0; + __set_errno(ENOMEM); + } + return -1; + +} +libc_hidden_def(brk) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/clone.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/clone.S new file mode 100644 index 00000000..9e284fe0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/clone.S @@ -0,0 +1,96 @@ +/* Copyright (C) 2001, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include "sysdep.h" +#define _ERRNO_H 1 +#include + +/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg); */ + + .syntax no_register_prefix + + .text +ENTRY (clone) + /* Sanity check arguments: No NULL function pointers. Allow a NULL + stack pointer though; it makes the kernel allocate stack. */ + cmpq 0,r10 + beq 1f + nop + + /* We need to muck with a few registers. */ + subq 8,sp + movem r1,[sp] + + /* Save the function pointer and argument. We can't save them + onto the new stack since it can be NULL. */ + move.d r10,r0 + move.d r13,r1 + + /* Move the other arguments into place for the system call. */ + move.d r11,r10 + move.d r12,r11 + + /* Do the system call. */ + movu.w SYS_ify (clone),r9 + break 13 + cmpq 0,r10 + beq .Lthread_start + nop + + /* Jump to error handler if we get (unsigned) -4096 .. 0xffffffff. */ + cmps.w -4096,r10 + bhs 0f + movem [sp+],r1 + + /* In parent, successful return. (Avoid using "ret" - it's a macro.) */ + Ret + nop + +.Lthread_start: + /* Terminate frame pointers here. */ + moveq 0,r8 + +#ifdef __arch_v32 + /* Is this the right place for an argument? */ + jsr r0 + move.d r1,r10 +#else + /* I've told you once. */ + move.d r1,r10 + jsr r0 +#endif + + SETUP_PIC + PLTCALL (HIDDEN_JUMPTARGET(_exit)) + + /* Die horribly. */ + move.d 6809,r13 + test.d [r13] + + /* Stop the unstoppable. */ +9: + ba 9b + nop + +/* Local error handler. */ +1: + movs.w -EINVAL,r10 + /* Drop through into the ordinary error handler. */ +PSEUDO_END (clone) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/crt1.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/crt1.S new file mode 100644 index 00000000..b07e36b5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/crt1.S @@ -0,0 +1,56 @@ +/* Startup code compliant to the ELF CRIS ABI */ + +#include + + .syntax no_register_prefix + +/* The first piece of initialized data. */ + .data + .global __data_start + .align 2 + .type __data_start, @object + .size __data_start, 4 +__data_start: + .dword 0 + + .text + .align 1 + .global _start + .type _start, %function +#if defined(__UCLIBC_CTOR_DTOR__) + .type _init, %function + .type _fini, %function +#else + .weak _init + .weak _fini +#endif + .type main, %function + .type __uClibc_main, %function + +/* + * On the stack we have argc. We can calculate argv/envp + * from that and the succeeding stack location, but fix so + * we get the right calling convention (regs in r10/r11). + * + * Please view linux/fs/binfmt_elf.c for a complete + * understanding of this. + */ + +/* + * Need to call __uClibc_main(main, argc, argv, _init, _fini) + */ + +_start: + move.d main, r10 + move.d [sp+], r11 + move.d sp, r12 + subq 4, sp + move srp, [sp] + subq 4, sp + move.d _fini, r13 + move.d r13, [sp] + move.d _init, r13 + /* Leave control to the libc */ + jsr __uClibc_main + nop + .size _start, .-_start diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/crti.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/crti.S new file mode 100644 index 00000000..d9e1397d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/crti.S @@ -0,0 +1,37 @@ +/* glibc's sysdeps/cris/elf/initfini.c used for reference [PROLOG] */ + + .section .init + .align 1 + .global _init + .type _init, @function +_init: + subq 4,$sp + move.d $r1,[$sp] + move $srp,$r1 + subq 4,$sp + move.d $r0,[$sp] +#ifdef __arch_v32 + lapc _GLOBAL_OFFSET_TABLE_,$r0 +#else + move.d $pc,$r0 + sub.d .:GOTOFF,$r0 +#endif + .align 1 + + .section .fini + .align 1 + .global _fini + .type _fini, @function +_fini: + subq 4,$sp + move.d $r1,[$sp] + move $srp,$r1 + subq 4,$sp + move.d $r0,[$sp] +#ifdef __arch_v32 + lapc _GLOBAL_OFFSET_TABLE_,$r0 +#else + move.d $pc,$r0 + sub.d .:GOTOFF,$r0 +#endif + .align 1 diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/crtn.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/crtn.S new file mode 100644 index 00000000..7b2dce17 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/crtn.S @@ -0,0 +1,21 @@ +/* glibc's sysdeps/cris/elf/initfini.c used for reference [EPILOG] */ + + .section .init + .align 1 + .global _init + .type _init, @function + move.d [$sp+],$r0 + move $r1,$srp + move.d [$sp+],$r1 + Ret + nop + + .section .fini + .align 1 + .global _fini + .type _fini, @function + move.d [$sp+],$r0 + move $r1,$srp + move.d [$sp+],$r1 + Ret + nop diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/fork.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/fork.c new file mode 100644 index 00000000..19aa1727 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/fork.c @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include "sysdep.h" + +#define __NR___libc_fork __NR_fork +SYSCALL__ (__libc_fork, 0) + /* R1 is now 0 for the parent and 1 for the child. Decrement it to + make it -1 (all bits set) for the parent, and 0 (no bits set) + for the child. Then AND it with R0, so the parent gets + R0&-1==R0, and the child gets R0&0==0. */ + /* i dunno what the blurb above is useful for. we just return. */ +__asm__("ret\n\tnop"); +weak_alias(__libc_fork,fork) +libc_hidden_weak(fork) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/libc.map b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/libc.map new file mode 100644 index 00000000..6710c733 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/libc.map @@ -0,0 +1,3 @@ +U { + local: __sigjmp_save; +}; diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/sbrk.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/sbrk.c new file mode 100644 index 00000000..fa04b20b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/sbrk.c @@ -0,0 +1,41 @@ +/* From libc-5.3.12 */ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include "sysdep.h" + +extern void * __curbrk attribute_hidden; +extern int __init_brk (void) attribute_hidden; + +void * +sbrk(intptr_t increment) +{ + if (__init_brk () == 0) { + void * tmp = __curbrk + increment; + + /* + * Notice that we don't need to save/restore the GOT + * register since that is not call clobbered by the syscall. + */ + __asm__ ("move.d %1,$r10\n\t" + "movu.w " STR(__NR_brk) ",$r9\n\t" + "break 13\n\t" + "move.d $r10, %0" + : "=r" (__curbrk) + : "g" (tmp) + : "r9", "r10"); + + if (__curbrk == tmp) + return tmp - increment; + __set_errno(ENOMEM); + return ((void *) -1); + } + return ((void *) -1); +} +libc_hidden_def(sbrk) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/setjmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/setjmp.S new file mode 100644 index 00000000..e7bb6358 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/setjmp.S @@ -0,0 +1,84 @@ +/* setjmp for CRIS. + Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include "sysdep.h" +#define _SETJMP_H +#define _ASM +#include + + .syntax no_register_prefix + +ENTRY (__sigsetjmp) +.Local__sigsetjmp: + +#ifdef __arch_v32 + + moveq 1,r9 + move.d r10,r12 + addq 14*4,r12 + movem r9,[r10] + lapc 0f,r13 + move.d sp,[r12+] + move.d r13,[r12+] + move srp,[r12+] + +#else + + moveq 1,r9 + movem sp,[r10+1*4] +#ifdef __PIC__ + move.d pc,r9 + addq 0f-.,r9 +#else + move.d 0f,r9 +#endif + move.d r9,[r10] + move srp,[r10+16*4] + +#endif + +/* Saving and restoring CCR is meaningless, so we don't do it. */ + +/* Saving registers would complicate the implementation, but we + can get away with not setting up R0 here since we know that + __sigjmp_save is a local symbol; it doesn't have a PLT (which + would have required GOT in R0 at the time of the jump). */ + PLTJUMP (__sigjmp_save) +0: /* This is where longjmp returns. (Don't use "ret" - it's a macro. */ + Ret + move.d r9,r10 +END (__sigsetjmp) + +/* Binary compatibility entry points. Having these in separate files + is not meaningful and just adds library overhead. */ + +ENTRY (__setjmp) + ba .Local__sigsetjmp + moveq 0,r11 +END (__setjmp) + +ENTRY (_setjmp) + ba .Local__sigsetjmp + moveq 0,r11 +END (_setjmp) + +ENTRY (setjmp) + ba .Local__sigsetjmp + moveq 1,r11 +END (setjmp) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/sys/procfs.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/sys/procfs.h new file mode 100644 index 00000000..072029bc --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/sys/procfs.h @@ -0,0 +1,115 @@ +/* Copyright (C) 1996, 1997, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _SYS_PROCFS_H +#define _SYS_PROCFS_H 1 + +/* This is somehow modelled after the file of the same name on SysVr4 + systems. It provides a definition of the core file format for ELF + used on Linux. */ + +#include +#include +#include +#include +#include +#include +#include + +__BEGIN_DECLS + +struct elf_siginfo + { + int si_signo; /* Signal number. */ + int si_code; /* Extra code. */ + int si_errno; /* Errno. */ + }; + +/* Definitions to generate Intel SVR4-like core files. These mostly + have the same names as the SVR4 types with "elf_" tacked on the + front to prevent clashes with linux definitions, and the typedef + forms have been avoided. This is mostly like the SVR4 structure, + but more Linuxy, with things that Linux does not support and which + gdb doesn't really use excluded. Fields present but not used are + marked with "XXX". */ +struct elf_prstatus + { +#if 0 + long int pr_flags; /* XXX Process flags. */ + short int pr_why; /* XXX Reason for process halt. */ + short int pr_what; /* XXX More detailed reason. */ +#endif + struct elf_siginfo pr_info; /* Info associated with signal. */ + short int pr_cursig; /* Current signal. */ + unsigned long int pr_sigpend; /* Set of pending signals. */ + unsigned long int pr_sighold; /* Set of held signals. */ +#if 0 + struct sigaltstack pr_altstack; /* Alternate stack info. */ + struct sigaction pr_action; /* Signal action for current sig. */ +#endif + __pid_t pr_pid; + __pid_t pr_ppid; + __pid_t pr_pgrp; + __pid_t pr_sid; + struct timeval pr_utime; /* User time. */ + struct timeval pr_stime; /* System time. */ + struct timeval pr_cutime; /* Cumulative user time. */ + struct timeval pr_cstime; /* Cumulative system time. */ +#if 0 + long int pr_instr; /* Current instruction. */ +#endif + elf_gregset_t pr_reg; /* GP registers. */ + int pr_fpvalid; /* True if math copro being used. */ + }; + + +#define ELF_PRARGSZ (80) /* Number of chars for args */ + +struct elf_prpsinfo + { + char pr_state; /* Numeric process state. */ + char pr_sname; /* Char for pr_state. */ + char pr_zomb; /* Zombie. */ + char pr_nice; /* Nice val. */ + unsigned long int pr_flag; /* Flags. */ + unsigned short int pr_uid; + unsigned short int pr_gid; + int pr_pid, pr_ppid, pr_pgrp, pr_sid; + /* Lots missing */ + char pr_fname[16]; /* Filename of executable. */ + char pr_psargs[ELF_PRARGSZ]; /* Initial part of arg list. */ + }; + +/* Addresses. */ +typedef void *psaddr_t; + +/* Register sets. Linux has different names. */ +typedef gregset_t prgregset_t; +typedef fpregset_t prfpregset_t; + +/* We don't have any differences between processes and threads, + therefore habe only ine PID type. */ +typedef __pid_t lwpid_t; + + +typedef struct elf_prstatus prstatus_t; +typedef struct elf_prpsinfo prpsinfo_t; + +__END_DECLS + +#endif /* sys/procfs.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/sys/ucontext.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/sys/ucontext.h new file mode 100644 index 00000000..5f875453 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/sys/ucontext.h @@ -0,0 +1,95 @@ +/* Copyright (C) 1997, 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* System V/cris ABI compliant context switching support. */ + +#ifndef _SYS_UCONTEXT_H +#define _SYS_UCONTEXT_H 1 + +#include +#include + +#include + +/* Type for general register. */ +typedef long int greg_t; + +/* Number of general registers. */ +#define NGREG 20 + +/* Container for all general registers. */ +typedef greg_t gregset_t[NGREG]; + +/* Number of each register is the `gregset_t' array. */ +enum +{ + R0 = 0, +#define R0 R0 + R1 = 1, +#define R1 R1 + R2 = 2, +#define R2 R2 + R3 = 3, +#define R3 R3 + R4 = 4, +#define R4 R4 + R5 = 5, +#define R5 R5 + R6 = 6, +#define R6 R6 + R7 = 7, +#define R7 R7 + R8 = 8, +#define R8 R8 + R9 = 9, +#define R9 R9 + R10 = 10, +#define R10 R10 + R11 = 11, +#define R11 R11 + R12 = 12, +#define R12 R12 + R13 = 13, +#define R13 R13 + R14 = 14, +#define R14 R14 + R15 = 15, +#define R15 R15 + R_SP = R14, +#define R_SP R_SP + R_PC = R15, +#define R_PC R_PC +}; + +/* A placeholder; CRIS does not have any fp regs. */ +typedef unsigned long fpregset_t; + +/* A machine context is exactly a sigcontext. */ +typedef struct sigcontext mcontext_t; + +/* Userlevel context. */ +typedef struct ucontext + { + unsigned long int uc_flags; + struct ucontext *uc_link; + stack_t uc_stack; + mcontext_t uc_mcontext; + __sigset_t uc_sigmask; + } ucontext_t; + +#endif /* sys/ucontext.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/syscall.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/syscall.S new file mode 100644 index 00000000..d4b052e8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/syscall.S @@ -0,0 +1,61 @@ +/* Copyright (C) 2001, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include "sysdep.h" + + .syntax no_register_prefix + +/* Make syscall (callno, ...) into a system call. */ + +ENTRY (syscall) +#ifdef __arch_v32 + subq 4,sp + move.d r10,r9 + move srp,[sp] + addoq 8,sp,acr + move.d r11,r10 + move [acr],mof + addoq 12,sp,acr + move.d r12,r11 + move [acr],srp + addoq 4,sp,acr + move.d r13,r12 + move.d [acr],r13 + break 13 + cmps.w -4096,r10 + bhs 0f + move [sp+],srp + Ret + nop +#else + push srp + move.d r10,r9 + move.d r11,r10 + move.d r12,r11 + move.d r13,r12 + move.d [sp+4],r13 + move [sp+8],mof + move [sp+12],srp + break 13 + cmps.w -4096,r10 + bhs 0f + pop srp + Ret + nop +#endif +PSEUDO_END (syscall) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/sysdep.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/sysdep.S new file mode 100644 index 00000000..416751d6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/sysdep.S @@ -0,0 +1,80 @@ +/* Copyright (C) 2001, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include "sysdep.h" + +/* The syscall stubs jump here when they detect an error, bot for PIC and + non-PIC. */ + + .syntax no_register_prefix + +ENTRY (__syscall_error) + neg.d r10,r10 + +#ifdef __UCLIBC_HAS_THREADS__ + subq 4,sp + move.d r10,[sp] + subq 4,sp + move srp,[sp] + + /* Note that __syscall_error is only visible within this library, + and no-one passes it on as a pointer, so can assume that R0 (GOT + pointer) is correctly set up. */ + PLTCALL (HIDDEN_JUMPTARGET(__errno_location)) + + move [sp+],srp + move.d [sp+],r11 + move.d r11,[r10] + +#else /* not __UCLIBC_HAS_THREADS__ */ +#ifdef __arch_v32 +# ifdef __PIC__ + addo.d C_SYMBOL_NAME(errno:GOT),r0,acr + move.d [acr],r9 + move.d r10,[r9] +# else /* not __PIC__ */ + lapc C_SYMBOL_NAME(errno),acr + move.d r10,[r9] +# endif /* not __PIC__ */ +#else /* not __arch_v32 */ +# ifdef __PIC__ + move.d [r0+C_SYMBOL_NAME(errno:GOT)],r9 + move.d r10,[r9] +# else + move.d r10,[C_SYMBOL_NAME(errno)] +# endif +#endif /* not __arch_v32 */ +#endif /* __UCLIBC_HAS_THREADS__ */ + +#ifdef __PIC__ +/* PIC callers are supposed to have R0 on stack, ready for us to restore. + Callers are only allowed from within this DSO, so the GOT in r0 is the + one we want to use. + + (Don't use "ret" - it's a macro). */ + + moveq -1,r10 + Ret + move.d [sp+],r0 +#else + Ret + moveq -1,r10 +#endif + +END (__syscall_error) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/sysdep.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/sysdep.h new file mode 100644 index 00000000..593e7772 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/cris/sysdep.h @@ -0,0 +1,149 @@ +/* Assembler macros for CRIS. + Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _SYSDEP_H_ +#define _SYSDEP_H_ + +#ifndef C_LABEL + +/* Define a macro we can use to construct the asm name for a C symbol. */ +#ifdef __STDC__ +#define C_LABEL(name) name##: +#else +#define C_LABEL(name) name/**/: +#endif + +#endif /* C_LABEL */ + +#define __STR(x) #x +#define STR(x) __STR(x) + +/* Mark the end of function named SYM. This is used on some platforms + to generate correct debugging information. */ +#ifndef END +#define END(sym) +#endif + +#undef SYS_ify +#define SYS_ify(syscall_name) (__NR_##syscall_name) + +#ifdef __ASSEMBLER__ + +#undef SYS_ify +#define SYS_ify(syscall_name) __NR_##syscall_name + +/* Syntactic details of assembly-code. */ + +/* It is *not* generally true that "ELF uses byte-counts for .align, most + others use log2 of count of bytes", like some neighboring configs say. + See "align" in gas/read.c which is not overridden by + gas/config/obj-elf.c. It takes a log2 argument. *Some* targets + override it to take a byte argument. People should read source instead + of relying on hearsay. */ +#define ALIGNARG(log2) log2 + +#define ASM_TYPE_DIRECTIVE(name,typearg) .type name,typearg +#define ASM_SIZE_DIRECTIVE(name) .size name,.-name + +/* The non-PIC jump is preferred, since it does not stall, and does not + invoke generation of a PLT. These macros assume that $r0 is set up as + GOT register. */ +#ifdef __arch_v32 +#ifdef __PIC__ +#define PLTJUMP(_x) \ + ba C_SYMBOL_NAME (_x):PLT @ \ + nop + +#define PLTCALL(_x) \ + bsr C_SYMBOL_NAME (_x):PLT @ \ + nop + +#define SETUP_PIC \ + subq 4,$sp @ \ + move.d $r0,[$sp] @ \ + lapc _GLOBAL_OFFSET_TABLE_,$r0 + +#define TEARDOWN_PIC move.d [$sp+],$r0 +#else +#define PLTJUMP(_x) \ + ba C_SYMBOL_NAME (_x) @ \ + nop + +#define PLTCALL(_x) \ + bsr C_SYMBOL_NAME (_x) @ \ + nop + +#define SETUP_PIC +#define TEARDOWN_PIC +#endif + +#else + +#ifdef __PIC__ +#define PLTJUMP(_x) \ + add.d C_SYMBOL_NAME (_x):PLT,$pc + +#define PLTCALL(_x) \ + jsr [$r0+C_SYMBOL_NAME (_x):GOTPLT16] + +#define SETUP_PIC \ + push $r0 @ \ + move.d $pc,$r0 @ \ + sub.d .:GOTOFF,$r0 + +#define TEARDOWN_PIC pop $r0 +#else +#define PLTJUMP(_x) jump C_SYMBOL_NAME (_x) +#define PLTCALL(_x) jsr C_SYMBOL_NAME (_x) +#define SETUP_PIC +#define TEARDOWN_PIC +#endif + +#endif /* __arch_v32 */ + +/* Define an entry point visible from C. */ +#define ENTRY(name) \ + .text @ \ + ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME (name) @ \ + ASM_TYPE_DIRECTIVE (C_SYMBOL_NAME (name), function) @ \ + .align ALIGNARG (2) @ \ + C_LABEL(name) + +#undef END +#define END(name) \ + ASM_SIZE_DIRECTIVE (C_SYMBOL_NAME (name)) + +#define PSEUDO(name, syscall_name, args) \ + ENTRY (name) @ \ + DOARGS_##args @ \ + movu.w SYS_ify (syscall_name),$r9 @ \ + break 13 @ \ + cmps.w -4096,$r10 @ \ + bhs 0f @ \ + nop @ \ + UNDOARGS_return_##args + +#define PSEUDO_END(name) \ +0: @ \ + SETUP_PIC @ \ + PLTJUMP (__syscall_error) @ \ + END (name) + +#endif /* __ASSEMBLER__ */ +#endif /* _SYSDEP_H_ */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/e1/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/e1/Makefile new file mode 100644 index 00000000..c69ccb9e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/e1/Makefile @@ -0,0 +1,56 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2006 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + +TOPDIR=../../../../ +include $(TOPDIR)Rules.mak + +#FIXME -- this arch should include its own crti.S and crtn.S +UCLIBC_CTOR_DTOR=n + +# If you're looking for vfork(), it is defined in include/unistd.h + +CRT_SRC := crt0.S +CRT_OBJ := crt0.o +CTOR_TARGETS := $(TOPDIR)lib/crti.o $(TOPDIR)lib/crtn.o + +# why is crt1.c listed in CSRC ? +CSRC := crt1.c syscalls.c longjmp.c setjmp.c vfork.c +OBJS := $(patsubst %.c,%.o, $(CSRC)) + +OBJ_LIST := ../../../obj.sysdeps.$(TARGET_ARCH) + +all: $(OBJ_LIST) $(CTOR_TARGETS) + +$(OBJ_LIST): $(OBJS) $(CRT_OBJ) + $(STRIPTOOL) -x -R .note -R .comment $^ + $(INSTALL) -d $(TOPDIR)lib/ + cp $(CRT_OBJ) $(TOPDIR)lib/ + echo $(patsubst %, sysdeps/linux/$(TARGET_ARCH)/%, $(OBJS)) > $@ + +$(CRT_OBJ): %.o : %.S + $(CC) $(ASFLAGS) -c $< -o $@ + +$(OBJS): %.o : %.c + $(CC) $(CFLAGS) -c $< -o $@ + +ifeq ($(UCLIBC_CTOR_DTOR),y) +$(TOPDIR)lib/crti.o: crti.S + $(INSTALL) -d $(TOPDIR)lib/ + $(CC) $(ASFLAGS) $(SSP_DISABLE_FLAGS) -c $< -o $@ + +$(TOPDIR)lib/crtn.o: crtn.S + $(INSTALL) -d $(TOPDIR)lib/ + $(CC) $(ASFLAGS) $(SSP_DISABLE_FLAGS) -c $< -o $@ +else +$(CTOR_TARGETS): + $(INSTALL) -d $(TOPDIR)lib/ + $(AR) $(ARFLAGS) $@ +endif + +headers: + +clean: + $(RM) *.o *~ core diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/e1/bits/endian.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/e1/bits/endian.h new file mode 100644 index 00000000..0d38c1ca --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/e1/bits/endian.h @@ -0,0 +1,7 @@ +/* e1 is big-endian. */ + +#ifndef _ENDIAN_H +# error "Never use directly; include instead." +#endif + +#define __BYTE_ORDER __BIG_ENDIAN diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/e1/bits/fcntl.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/e1/bits/fcntl.h new file mode 100644 index 00000000..a9cb7221 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/e1/bits/fcntl.h @@ -0,0 +1,233 @@ +/* O_*, F_*, FD_* bit values for Linux. + Copyright (C) 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FCNTL_H +# error "Never use directly; include instead." +#endif + + +#include + +/* open/fcntl - O_SYNC is only implemented on blocks devices and on files + located on an ext2 file system */ +#define O_ACCMODE 0003 +#define O_RDONLY 00 +#define O_WRONLY 01 +#define O_RDWR 02 +#define O_CREAT 0100 /* not fcntl */ +#define O_EXCL 0200 /* not fcntl */ +#define O_NOCTTY 0400 /* not fcntl */ +#define O_TRUNC 01000 /* not fcntl */ +#define O_APPEND 02000 +#define O_NONBLOCK 04000 +#define O_NDELAY O_NONBLOCK +#define O_SYNC 010000 +#define O_FSYNC O_SYNC +#define O_ASYNC 020000 + +#ifdef __USE_GNU +# define O_DIRECTORY 040000 /* Must be a directory. */ +# define O_NOFOLLOW 0100000 /* Do not follow links. */ +# define O_DIRECT 0200000 /* Direct disk access. */ +#endif + +/* For now Linux has synchronisity options for data and read operations. + We define the symbols here but let them do the same as O_SYNC since + this is a superset. */ +#if defined __USE_POSIX199309 || defined __USE_UNIX98 +# define O_DSYNC O_SYNC /* Synchronize data. */ +# define O_RSYNC O_SYNC /* Synchronize read operations. */ +#endif + +#ifdef __USE_LARGEFILE64 +# define O_LARGEFILE 0400000 +#endif + +/* Values for the second argument to `fcntl'. */ +#define F_DUPFD 0 /* Duplicate file descriptor. */ +#define F_GETFD 1 /* Get file descriptor flags. */ +#define F_SETFD 2 /* Set file descriptor flags. */ +#define F_GETFL 3 /* Get file status flags. */ +#define F_SETFL 4 /* Set file status flags. */ +#ifndef __USE_FILE_OFFSET64 +# define F_GETLK 5 /* Get record locking info. */ +# define F_SETLK 6 /* Set record locking info (non-blocking). */ +# define F_SETLKW 7 /* Set record locking info (blocking). */ +#else +# define F_GETLK F_GETLK64 /* Get record locking info. */ +# define F_SETLK F_SETLK64 /* Set record locking info (non-blocking).*/ +# define F_SETLKW F_SETLKW64 /* Set record locking info (blocking). */ +#endif +#define F_GETLK64 12 /* Get record locking info. */ +#define F_SETLK64 13 /* Set record locking info (non-blocking). */ +#define F_SETLKW64 14 /* Set record locking info (blocking). */ + +#if defined __USE_BSD || defined __USE_XOPEN2K +# define F_SETOWN 8 /* Get owner of socket (receiver of SIGIO). */ +# define F_GETOWN 9 /* Set owner of socket (receiver of SIGIO). */ +#endif + +#ifdef __USE_GNU +# define F_SETSIG 10 /* Set number of signal to be sent. */ +# define F_GETSIG 11 /* Get number of signal to be sent. */ +#endif + +#ifdef __USE_GNU +# define F_SETLEASE 1024 /* Set a lease. */ +# define F_GETLEASE 1025 /* Enquire what lease is active. */ +# define F_NOTIFY 1026 /* Request notfications on a directory. */ +# define F_DUPFD_CLOEXEC 1030 /* Duplicate file descriptor with + close-on-exit set on new fd. */ +#endif + +/* For F_[GET|SET]FL. */ +#define FD_CLOEXEC 1 /* actually anything with low bit set goes */ + +/* For posix fcntl() and `l_type' field of a `struct flock' for lockf(). */ +#define F_RDLCK 0 /* Read lock. */ +#define F_WRLCK 1 /* Write lock. */ +#define F_UNLCK 2 /* Remove lock. */ + +/* For old implementation of bsd flock(). */ +#define F_EXLCK 4 /* or 3 */ +#define F_SHLCK 8 /* or 4 */ + +#ifdef __USE_BSD +/* Operations for bsd flock(), also used by the kernel implementation. */ +# define LOCK_SH 1 /* shared lock */ +# define LOCK_EX 2 /* exclusive lock */ +# define LOCK_NB 4 /* or'd with one of the above to prevent + blocking */ +# define LOCK_UN 8 /* remove lock */ +#endif + +#ifdef __USE_GNU +# define LOCK_MAND 32 /* This is a mandatory flock: */ +# define LOCK_READ 64 /* ... which allows concurrent read operations. */ +# define LOCK_WRITE 128 /* ... which allows concurrent write operations. */ +# define LOCK_RW 192 /* ... Which allows concurrent read & write operations. */ +#endif + +#ifdef __USE_GNU +/* Types of directory notifications that may be requested with F_NOTIFY. */ +# define DN_ACCESS 0x00000001 /* File accessed. */ +# define DN_MODIFY 0x00000002 /* File modified. */ +# define DN_CREATE 0x00000004 /* File created. */ +# define DN_DELETE 0x00000008 /* File removed. */ +# define DN_RENAME 0x00000010 /* File renamed. */ +# define DN_ATTRIB 0x00000020 /* File changed attibutes. */ +# define DN_MULTISHOT 0x80000000 /* Don't remove notifier. */ +#endif + +struct flock + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ +#ifndef __USE_FILE_OFFSET64 + __off_t l_start; /* Offset where the lock begins. */ + __off_t l_len; /* Size of the locked area; zero means until EOF. */ +#else + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ +#endif + __pid_t l_pid; /* Process holding the lock. */ + }; + +#ifdef __USE_LARGEFILE64 +struct flock64 + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ + __pid_t l_pid; /* Process holding the lock. */ + }; +#endif + +/* Define some more compatibility macros to be backward compatible with + BSD systems which did not managed to hide these kernel macros. */ +#ifdef __USE_BSD +# define FAPPEND O_APPEND +# define FFSYNC O_FSYNC +# define FASYNC O_ASYNC +# define FNONBLOCK O_NONBLOCK +# define FNDELAY O_NDELAY +#endif /* Use BSD. */ + +/* Advise to `posix_fadvise'. */ +#ifdef __USE_XOPEN2K +# define POSIX_FADV_NORMAL 0 /* No further special treatment. */ +# define POSIX_FADV_RANDOM 1 /* Expect random page references. */ +# define POSIX_FADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define POSIX_FADV_WILLNEED 3 /* Will need these pages. */ +# define POSIX_FADV_DONTNEED 4 /* Don't need these pages. */ +# define POSIX_FADV_NOREUSE 5 /* Data will be accessed once. */ +#endif + + +#if defined __USE_GNU && defined __UCLIBC_LINUX_SPECIFIC__ +/* Flags for SYNC_FILE_RANGE. */ +# define SYNC_FILE_RANGE_WAIT_BEFORE 1 /* Wait upon writeout of all pages + in the range before performing the + write. */ +# define SYNC_FILE_RANGE_WRITE 2 /* Initiate writeout of all those + dirty pages in the range which are + not presently under writeback. */ +# define SYNC_FILE_RANGE_WAIT_AFTER 4 /* Wait upon writeout of all pages in + the range after performing the + write. */ + +/* Flags for SPLICE and VMSPLICE. */ +# define SPLICE_F_MOVE 1 /* Move pages instead of copying. */ +# define SPLICE_F_NONBLOCK 2 /* Don't block on the pipe splicing + (but we may still block on the fd + we splice from/to). */ +# define SPLICE_F_MORE 4 /* Expect more data. */ +# define SPLICE_F_GIFT 8 /* Pages passed in are a gift. */ +#endif + +__BEGIN_DECLS + +#if defined __USE_GNU && defined __UCLIBC_LINUX_SPECIFIC__ + +/* Provide kernel hint to read ahead. */ +extern ssize_t readahead (int __fd, __off64_t __offset, size_t __count) + __THROW; + + +/* Selective file content synch'ing. */ +extern int sync_file_range (int __fd, __off64_t __from, __off64_t __to, + unsigned int __flags); + +/* Splice address range into a pipe. */ +extern ssize_t vmsplice (int __fdout, const struct iovec *__iov, + size_t __count, unsigned int __flags); + +/* Splice two files together. */ +extern ssize_t splice (int __fdin, __off64_t *__offin, int __fdout, + __off64_t *__offout, size_t __len, + unsigned int __flags); + +/* In-kernel implementation of tee for pipe buffers. */ +extern ssize_t tee (int __fdin, int __fdout, size_t __len, + unsigned int __flags); + +#endif +__END_DECLS +#endif /* LINUX_SPECIFIC */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/e1/bits/fenv.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/e1/bits/fenv.h new file mode 100644 index 00000000..beeea3d5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/e1/bits/fenv.h @@ -0,0 +1,88 @@ + +/* Copyright (C) 2002-2003, George Thanos + Yannis Mitsos + + Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FENV_H +# error "Never use directly; include instead." +#endif + + +/* Define bits representing the exception. We use the bit positions of + the appropriate bits in the SR. */ +enum + { + FE_INEXACT = (1 << 8), +#define FE_INEXACT FE_INEXACT + FE_UNDERFLOW = (1 << 9), +#define FE_UNDERFLOW FE_UNDERFLOW + FE_OVERFLOW = (1 << 10), +#define FE_OVERFLOW FE_OVERFLOW + FE_DIVBYZERO = (1 << 11), +#define FE_DIVBYZERO FE_DIVBYZERO + FE_INVALID = (1 << 12) +#define FE_INVALID FE_INVALID + }; + +#define FE_ALL_EXCEPT \ + (FE_INEXACT | FE_DIVBYZERO | FE_UNDERFLOW | FE_OVERFLOW | FE_INVALID) + +/* We support all of the four defined rounding modes. We use + the bit positions in the FPCR Mode Control Byte as the values for the + appropriate macros. */ +enum + { + FE_TONEAREST = 0, +#define FE_TONEAREST FE_TONEAREST + FE_TOWARDZERO = 1 << 13 , +#define FE_TOWARDZERO FE_TOWARDZERO + FE_DOWNWARD = 2 << 13, +#define FE_DOWNWARD FE_DOWNWARD + FE_UPWARD = 3 << 13 +#define FE_UPWARD FE_UPWARD + }; + + +/* Type representing exception flags. */ +typedef unsigned int fexcept_t; + + +/* Type representing floating-point environment.*/ +typedef struct +{ + unsigned int round_mode; + unsigned int trap_enabled; + unsigned int accrued_except; + unsigned int actual_except; +} fenv_t; + +#if 0 +/* If the default argument is used we use this value. */ +const fenv FE_DFL_ENV_OBJ = {0, 0x1C00, 0} +#define FE_DFL_ENV (&FE_DFL_ENV_OBJ) + +#ifdef __USE_GNU +/* Floating-point environment where none of the exceptions are masked. */ +const fenv_t FE_NOMASK_ENV_OBJ = { 0, 0x1F00, 0 }; +# define FE_NOMASK_ENV (&FE_NOMASK_ENV_OBJ) +#endif + +#endif + +#include diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/e1/bits/fenvinline.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/e1/bits/fenvinline.h new file mode 100644 index 00000000..25562471 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/e1/bits/fenvinline.h @@ -0,0 +1,298 @@ +/* + Inline floating-point environment handling functions for Hyperstone e1-32X. + Copyright (C) 2002-2003, George Thanos + Yannis Mitsos + + Copyright (C) 1995, 1996, 1997, 1998, 1999 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#if defined __GNUC__ && !defined _SOFT_FLOAT && !defined __NO_MATH_INLINES + +/********************************************************** + * --- A small description of the E1-16/32X FP unit. --- + * FP exceptions can be enabled and disabled through + * , . + * + * - When an enabled exception takes place a SIGFPE signal + * is sent to the process by the exception handler. User + * can test for the exception that took place through + * . + * feraiseexcept works only for accrued exceptions. + * + * - When a disabld exception takes place it does not generate + * a trap. The user can check if any exception took place after + * an FP instruction by issuing an command. + * User should first clear the G2 register by issuing an + * function. + * The following program is a typical example of how the user + * should check for exceptions that did not generate a SIGFPE + * signal : + * { + * double f; + * int raised; + * feclearexcept (FE_ALL_EXCEPT); + * f = compute (); + * raised = fetestexcept (FE_OVERFLOW | FE_INVALID); + * if (raised & FE_OVERFLOW) { ... } + * if (raised & FE_INVALID) { ... } + * ... + * } + ***********************************************************/ + +/* Get FPU rounding mode */ +#define fegetround() \ +({ \ + unsigned int tmp; \ + __asm__ __volatile__("mov %0, SR" \ + :"=l"(tmp) \ + :/*no input*/); \ + tmp &= (3<<13); \ + (tmp); \ +}) + +/* Set FPU rounding mode */ +#define fesetround(round) \ +({ \ + unsigned int tmp = (3 << 13); \ + while(1) { \ + /* Clear SR.FRM field */ \ + __asm__ __volatile__("andn SR, %0" \ + :/*no output*/ \ + :"l"(tmp) ); \ + tmp &= round; \ + \ + if(tmp) { \ + tmp = -1; \ + break; \ + } \ + \ + __asm__ __volatile__("or SR, %0" \ + :/*no input*/ \ + :"l"(round) ); \ + tmp = 0; \ + break; \ + } \ + (tmp); \ +}) + +/* The following functions test for accrued exceptions. + * No trap is generated on an FP exception. + */ +static __inline__ feclearexcept(int __excepts) +{ + unsigned int enabled_excepts, disabled_excepts; + + /* Check that __excepts is correctly set */ + if( __excepts & (~0x1F00) ) + return -1; + + __asm__ __volatile__("mov %0, SR" + :"=l"(enabled_excepts) + :/*no input*/ ); + + enabled_excepts &= 0x1F00; + disabled_excepts = ~enabled_excepts; + disabled_excepts &= 0x1F00; + + enabled_excepts &= __excepts; + disabled_excepts &= __excepts; + + /* Clear accrued exceptions */ + __asm__ __volatile__("andn G2, %0\n\t" + "andn G2, %1\n\t" + :/*no output*/ + :"l"(enabled_excepts), + "l"(disabled_excepts >> 8) ); + return 0; +} + +/* fetestexcepts tests both for actual and accrued + * excepts. You can test for an exception either after + * an FP instruction or within a SIGFPE handler + */ +__inline__ int fetestexcept(int __excepts) +{ + unsigned int G2, G2en, G2dis; + unsigned int enabled_excepts, disabled_excepts; + + /* Check that __excepts is correctly set */ + if( __excepts & (~0x1F00) ) + return -1; + + __asm__ __volatile__("mov %0, SR" + :"=l"(enabled_excepts) + :/*no input*/ ); + + enabled_excepts &= 0x1F00; + disabled_excepts = ~enabled_excepts; + disabled_excepts &= 0x1F00; + + __asm__ __volatile__("mov %0, G2" + :"=l"(G2) + :/*no input*/ ); + + G2en = G2 & 0x1F00; + G2dis = G2 & 0x1F; + G2en &= enabled_excepts; + G2dis &= (disabled_excepts >> 8); + return ( G2en | (G2dis << 8) ); +} + +static __inline__ int feraiseexcept(int __excepts) +{ + __asm__ __volatile__("or G2, %0" + :/*no output*/ + :"l"( __excepts >> 8 ) ); + return 0; +} + +/* The following functions enable/disable individual exceptions. + * If enabling an exception trap is going to occur, in case of error. + */ +#define feenableexcept(__excepts) \ +({ \ + int __retval, __pexcepts; \ + int __tmpexcepts = __excepts; \ + \ + while(1) { \ + __asm__ __volatile__("mov %0, SR" \ + :"=l"(__pexcepts) \ + :/*no input*/ ); \ + __pexcepts &= 0x1F00; \ + \ +/* Check if __except values are valid */ \ + if( __tmpexcepts & ~0x1F00 ) { \ + __retval = -1; \ + fprintf(stderr,"Non valid excepts\n");\ + break; \ + } \ + \ + __asm__ __volatile__("or SR, %0" \ + :/*no output*/ \ + :"l"(__tmpexcepts) ); \ + __retval = __pexcepts; \ + break; \ + } \ + (__retval); \ +}) + + +#define fedisableexcept(__excepts) \ +({ \ + int __retval, __pexcepts; \ + int __tmpexcepts = __excepts; \ + \ + while(1) { \ + __asm__ __volatile__("mov %0, SR" \ + :"=l"(__pexcepts) \ + :/*no input*/ ); \ + __pexcepts &= 0x1F00; \ + \ +/* Check if __except values are valid */ \ + if( __tmpexcepts & ~0x1F00 ) { \ + __retval = -1; \ + fprintf(stderr,"Non valid excepts\n");\ + break; \ + } \ + \ + __asm__ __volatile__("andn SR, %0" \ + :/*no output*/ \ + :"l"(__tmpexcepts) ); \ + __retval = __pexcepts; \ + break; \ + } \ + (__retval); \ +}) + +static __inline__ int fegetexcept(int excepts) +{ + unsigned int tmp; + __asm__ __volatile__("mov %0, SR" + :"=l"(tmp) + :/*no input*/ ); + tmp &= 0x1F00; + return tmp; +} + +static __inline__ int fegetenv(fenv_t *envp) +{ + __asm__ __volatile__("mov %0, SR\n\t + mov %1, SR\n\t + mov %2, G2\n\t + mov %3, G2\n\t" + :"=l"(envp->round_mode), + "=l"(envp->trap_enabled), + "=l"(envp->accrued_except), + "=l"(envp->actual_except) + :/*no input*/ ); + envp->round_mode &= (3<<13); + envp->trap_enabled &= 0x1F00; + envp->accrued_except &= 0x1F; + envp->accrued_except <<= 8; + envp->actual_except &= 0x1F00; +} + +#define feholdexcept(envp) \ +( \ + fegetenv(envp); \ + fedisableexcept(FE_ALL_EXCEPT); \ + feclearexcept(FE_ALL_EXCEPT); \ + (0); \ +) + +#define fesetenv(envp) \ +({ \ + /* Clear FRM & FTE field of SR */ \ + unsigned long clearSR = ( 127<<8 ); \ + __asm__ __volatile__("andn SR, %0\n\t" \ + "or SR, %1\n\t" \ + "or SR, %2\n\t" \ + :/*no output*/ \ + :"l"(clearSR), \ + "l"(envp->round_mode), \ + "l"(envp->trap_enabled) ); \ + __asm__ __volatile__("andn G2, 0x1F1F\n\t" \ + "or G2, %0\n\t" \ + "or G2, %1\n\t" \ + :/*no output*/ \ + :"l"( envp->accrued_except >> 8),\ + :"l"( envp->actual_except ) ); \ + (0); /* return 0 */ \ +}) + +#define feupdateenv(envp) \ +({ \ + /* Clear FRM & FTE field of SR */ \ + __asm__ __volatile__(/* We dont clear the prev SR*/ \ + "or SR, %1\n\t" \ + "or SR, %2\n\t" \ + :/*no output*/ \ + :"l"(clearSR), \ + "l"(envp->round_mode), \ + "l"(envp->accrued_except) ); \ + __asm__ __volatile__(/* We dont clear the prev SR*/ \ + "or G2, %0\n\t" \ + "or G2, %1\n\t" \ + :/*no output*/ \ + :"l"( envp->accrued_except >> 8),\ + :"l"( envp->actual_except ) ); \ + (0); /* return 0 */ \ +}) + + +#endif /* __GNUC__ && !_SOFT_FLOAT */ + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/e1/bits/kernel_stat.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/e1/bits/kernel_stat.h new file mode 100644 index 00000000..2b432cf5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/e1/bits/kernel_stat.h @@ -0,0 +1,54 @@ +#ifndef _BITS_STAT_STRUCT_H +#define _BITS_STAT_STRUCT_H + +#ifndef _LIBC +#error bits/kernel_stat.h is for internal uClibc use only! +#endif + +/* This file provides whatever this particular arch's kernel thinks + * struct kernel_stat should look like... It turns out each arch has a + * different opinion on the subject... */ + +struct kernel_stat { + unsigned short st_dev; + unsigned short __pad1; + unsigned long st_ino; + unsigned short st_mode; + unsigned short st_nlink; + unsigned short st_uid; + unsigned short st_gid; + unsigned short st_rdev; + unsigned short __pad2; + unsigned long st_size; + unsigned long st_blksize; + unsigned long st_blocks; + struct timespec st_atim; + struct timespec st_mtim; + struct timespec st_ctim; + unsigned long __unused4; + unsigned long __unused5; +}; + +struct kernel_stat64 { + unsigned short st_dev; + unsigned char __pad0[10]; +#define _HAVE_STAT64___ST_INO + unsigned long __st_ino; + unsigned int st_mode; + unsigned int st_nlink; + unsigned long st_uid; + unsigned long st_gid; + unsigned short st_rdev; + unsigned char __pad3[10]; + long long st_size; + unsigned long st_blksize; + unsigned long st_blocks; /* Number 512-byte blocks allocated. */ + unsigned long __pad4; /* future possible st_blocks high bits */ + struct timespec st_atim; + struct timespec st_mtim; + struct timespec st_ctim; + unsigned long long st_ino; +}; + +#endif /* _BITS_STAT_STRUCT_H */ + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/e1/bits/kernel_types.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/e1/bits/kernel_types.h new file mode 100644 index 00000000..8017d857 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/e1/bits/kernel_types.h @@ -0,0 +1,46 @@ +/* Note that we use the exact same include guard #define names + * as asm/posix_types.h. This will avoid gratuitous conflicts + * with the posix_types.h kernel header, and will ensure that + * our private content, and not the kernel header, will win. + * -Erik + */ +#ifndef __ARCH_E1_POSIX_TYPES_H +#define __ARCH_E1_POSIX_TYPES_H + +typedef unsigned short __kernel_dev_t; +typedef unsigned long __kernel_ino_t; +typedef unsigned short __kernel_mode_t; +typedef unsigned short __kernel_nlink_t; +typedef long __kernel_off_t; +typedef int __kernel_pid_t; +typedef unsigned short __kernel_ipc_pid_t; +typedef unsigned short __kernel_uid_t; +typedef unsigned short __kernel_gid_t; +typedef unsigned int __kernel_size_t; +typedef int __kernel_ssize_t; +typedef int __kernel_ptrdiff_t; +typedef long __kernel_time_t; +typedef long __kernel_suseconds_t; +typedef long __kernel_clock_t; +typedef int __kernel_daddr_t; +typedef char * __kernel_caddr_t; +typedef unsigned short __kernel_uid16_t; +typedef unsigned short __kernel_gid16_t; +typedef unsigned int __kernel_uid32_t; +typedef unsigned int __kernel_gid32_t; +typedef unsigned short __kernel_old_uid_t; +typedef unsigned short __kernel_old_gid_t; +typedef __kernel_dev_t __kernel_old_dev_t; +typedef long long __kernel_loff_t; + +/* +typedef struct { +#ifdef __USE_ALL + int val[2]; +#else + int __val[2]; +#endif +} __kernel_fsid_t; +*/ + +#endif /* __ARCH_E1_POSIX_TYPES_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/e1/bits/proto.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/e1/bits/proto.h new file mode 100644 index 00000000..7aa38ffe --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/e1/bits/proto.h @@ -0,0 +1,5 @@ +#ifndef _E1_PROTO_H_ +#define _E1_PROTO_H_ +int kprintf( char *msg, int len); +#define KPRINTF(msg) kprintf(msg, strlen(msg)+1) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/e1/bits/setjmp.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/e1/bits/setjmp.h new file mode 100644 index 00000000..88fa76fd --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/e1/bits/setjmp.h @@ -0,0 +1,22 @@ +/* This file is lisenced under LGPL. + * Copyright (C) 2002-2003, George Thanos + * Yannis Mitsos + */ + +#ifndef _BITS_SETJMP_H +#define _BITS_SETJMP_H 1 + +#if !defined _SETJMP_H && !defined _PTHREAD_H +# error "Never include directly; use instead." +#endif + +typedef struct { + unsigned long G3; + unsigned long G4; + unsigned long SavedSP; + unsigned long SavedPC; + unsigned long SavedSR; + unsigned long ReturnValue; +} __jmp_buf[1]; + +#endif /* bits/setjmp.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/e1/bits/syscalls.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/e1/bits/syscalls.h new file mode 100644 index 00000000..8852a0f5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/e1/bits/syscalls.h @@ -0,0 +1,17 @@ +/* This file is licensed under LGPL. + * Copyright (C) 2002-2003, George Thanos + * Yannis Mitsos + */ +#ifndef _BITS_SYSCALLS_H +#define _BITS_SYSCALLS_H +#ifndef _SYSCALL_H +# error "Never use directly; include instead." +#endif + +#include + +/* Include the library _syscallx macros */ +#include + +#endif /* _BITS_SYSCALLS_H */ + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/e1/bits/uClibc_arch_features.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/e1/bits/uClibc_arch_features.h new file mode 100644 index 00000000..2a9422e2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/e1/bits/uClibc_arch_features.h @@ -0,0 +1,48 @@ +/* + * Track misc arch-specific features that aren't config options + */ + +#ifndef _BITS_UCLIBC_ARCH_FEATURES_H +#define _BITS_UCLIBC_ARCH_FEATURES_H + +/* instruction used when calling abort() to kill yourself */ +/*#define __UCLIBC_ABORT_INSTRUCTION__ "asm instruction"*/ +#undef __UCLIBC_ABORT_INSTRUCTION__ + +/* can your target use syscall6() for mmap ? */ +#undef __UCLIBC_MMAP_HAS_6_ARGS__ + +/* does your target use syscall4() for truncate64 ? (32bit arches only) */ +#undef __UCLIBC_TRUNCATE64_HAS_4_ARGS__ + +/* does your target have a broken create_module() ? */ +#undef __UCLIBC_BROKEN_CREATE_MODULE__ + +/* does your target have to worry about older [gs]etrlimit() ? */ +#undef __UCLIBC_HANDLE_OLDER_RLIMIT__ + +/* does your target have an asm .set ? */ +#define __UCLIBC_HAVE_ASM_SET_DIRECTIVE__ + +/* define if target doesn't like .global */ +#undef __UCLIBC_ASM_GLOBAL_DIRECTIVE__ + +/* define if target supports .weak */ +#define __UCLIBC_HAVE_ASM_WEAK_DIRECTIVE__ + +/* define if target supports .weakext */ +#undef __UCLIBC_HAVE_ASM_WEAKEXT_DIRECTIVE__ + +/* needed probably only for ppc64 */ +#undef __UCLIBC_HAVE_ASM_GLOBAL_DOT_NAME__ + +/* define if target supports CFI pseudo ops */ +#undef __UCLIBC_HAVE_ASM_CFI_DIRECTIVES__ + +/* define if target supports IEEE signed zero floats */ +#define __UCLIBC_HAVE_SIGNED_ZERO__ + +/* only weird assemblers generally need this */ +#undef __UCLIBC_ASM_LINE_SEP__ + +#endif /* _BITS_UCLIBC_ARCH_FEATURES_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/e1/bits/unistd.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/e1/bits/unistd.h new file mode 100644 index 00000000..f492b8b8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/e1/bits/unistd.h @@ -0,0 +1,464 @@ + /* This file is lisenced under LGPL. + * Copyright (C) 2002-2003, George Thanos + * Yannis Mitsos + */ +#ifndef _BITS_UNISTD_H_ +#define _BITS_UNISTD_H_ + +#include +#include + +#define __E1_COFF_GCC__ + +/* The following macros have been provided by C.Baumhof + * They can be inlined in contrast to the previous ones*/ +#define _syscall0(type, name) \ +type name(void) \ +{ \ + register int par1 __asm__("L15"); \ + register int par2 __asm__("L14"); \ + par1 = -1; \ + par2 = __NR_##name; \ + __asm__ __volatile__( \ + "trap 47" \ + :"=l"(par1) \ + :"0"(par1), "l"(par2) \ + :"memory","L14","L15"); \ + \ + if( par1 < 0 ) { \ + __set_errno( -par1 ); \ + return -1; \ + } else \ + return (type)(par1); \ +} + +#define _syscall1(type, name,atype, a) \ +type name(atype a) \ +{ \ + register int par1 __asm__("L15"); \ + register int par2 __asm__("L14"); \ + register int par3 __asm__("L13"); \ + par1 = -1; \ + par2 = __NR_##name; \ + par3 = (int)a; \ + __asm__ __volatile__( \ + "trap 47" \ + :"=l"(par1) \ + :"0"(par1), "l"(par2), "l"(par3) \ + :"memory","L13","L14","L15"); \ + \ + if( par1 < 0 ) { \ + __set_errno( -par1 ); \ + return -1; \ + } else \ + return (type)(par1); \ +} + +#define _syscall2(type, name,atype, a, btype, b) \ +type name(atype a, btype b) \ +{ \ + register int par1 __asm__("L15"); \ + register int par2 __asm__("L14"); \ + register int par3 __asm__("L13"); \ + register int par4 __asm__("L12"); \ + par1 = -1; \ + par2 = __NR_##name; \ + par3 = (int)a; \ + par4 = (int)b; \ + __asm__ __volatile__( \ + "trap 47" \ + :"=l"(par1) \ + :"0"(par1), "l"(par2), "l"(par3), "l"(par4) \ + :"memory","L12","L13","L14","L15"); \ + \ + if( par1 < 0 ) { \ + __set_errno( -par1 ); \ + return -1; \ + } else \ + return (type)(par1); \ +} + +#define _syscall3(type, name,atype, a, btype, b, ctype, c) \ +type name(atype a, btype b, ctype c) \ +{ \ + register int par1 __asm__("L15"); \ + register int par2 __asm__("L14"); \ + register int par3 __asm__("L13"); \ + register int par4 __asm__("L12"); \ + register int par5 __asm__("L11"); \ + par1 = -1; \ + par2 = __NR_##name; \ + par3 = (int)a; \ + par4 = (int)b; \ + par5 = (int)c; \ + __asm__ __volatile__( \ + "trap 47" \ + :"=l"(par1) \ + :"0"(par1), "l"(par2), "l"(par3), "l"(par4), "l"(par5) \ + :"memory","L11","L12","L13","L14","L15"); \ + \ + if( par1 < 0 ) { \ + __set_errno( -par1 ); \ + return -1; \ + } else \ + return (type)(par1); \ +} + +#define _syscall4(type, name,atype, a, btype, b, ctype, c, dtype, d) \ +type name(atype a, btype b, ctype c,dtype d) \ +{ \ + register int par1 __asm__("L15"); \ + register int par2 __asm__("L14"); \ + register int par3 __asm__("L13"); \ + register int par4 __asm__("L12"); \ + register int par5 __asm__("L11"); \ + register int par6 __asm__("L10"); \ + par1 = -1; \ + par2 = __NR_##name; \ + par3 = (int)a; \ + par4 = (int)b; \ + par5 = (int)c; \ + par6 = (int)d; \ + __asm__ __volatile__( \ + "trap 47" \ + :"=l"(par1) \ + :"0"(par1),"l"(par2),"l"(par3),"l"(par4),"l"(par5),"l"(par6) \ + :"memory","L10","L11","L12","L13","L14","L15"); \ + \ + if( par1 < 0 ) { \ + __set_errno( -par1 ); \ + return -1; \ + } else \ + return (type)(par1); \ +} + +#define _syscall5(type, name,atype, a, btype, b, ctype, c, dtype, d, etype, e) \ +type name(atype a, btype b, ctype c,dtype d, etype e) \ +{ \ + register int par1 __asm__("L15"); \ + register int par2 __asm__("L14"); \ + register int par3 __asm__("L13"); \ + register int par4 __asm__("L12"); \ + register int par5 __asm__("L11"); \ + register int par6 __asm__("L10"); \ + register int par7 __asm__("L9"); \ + par1 = -1; \ + par2 = __NR_##name; \ + par3 = (int)a; \ + par4 = (int)b; \ + par5 = (int)c; \ + par6 = (int)d; \ + par7 = (int)e; \ + __asm__ __volatile__( \ + "trap 47" \ + :"=l"(par1) \ + :"0"(par1),"l"(par2),"l"(par3),"l"(par4),"l"(par5),"l"(par6),"l"(par7) \ + :"memory","L9","L10","L11","L12","L13","L14","L15"); \ + \ + if( par1 < 0 ) { \ + __set_errno( -par1 ); \ + return -1; \ + } else \ + return (type)(par1); \ + return (type)(par1); \ +} + +#define _syscall6(type, name,atype, a, btype, b, ctype, c, dtype, d, etype, e, ftype, f) \ +type name(atype a, btype b, ctype c,dtype d, etype e, ftype f) \ +{ \ + register int par1 __asm__("L15"); \ + register int par2 __asm__("L14"); \ + register int par3 __asm__("L13"); \ + register int par4 __asm__("L12"); \ + register int par5 __asm__("L11"); \ + register int par6 __asm__("L10"); \ + register int par7 __asm__("L9"); \ + register int par8 __asm__("L8"); \ + int sys_retval; \ + par1 = -1; \ + par2 = __NR_##name; \ + par3 = (int)a; \ + par4 = (int)b; \ + par5 = (int)c; \ + par6 = (int)d; \ + par7 = (int)e; \ + par7 = (int)f; \ + __asm__ __volatile__( \ + "trap 47" \ + :"=l"(par1) \ + :"0"(par1),"l"(par2),"l"(par3),"l"(par4),"l"(par5),"l"(par6),"l"(par7),"l"(par8) \ + :"memory","L8","L9","L10","L11","L12","L13","L14","L15"); \ + \ + if( par1 < 0 ) { \ + __set_errno( -par1 ); \ + return -1; \ + } else \ + return (type)(par1); \ +} + +#define __syscall0(type, name) \ +type name(...) \ +{ \ + register int par1 __asm__("L15"); \ + register int par2 __asm__("L14"); \ + par1 = -1; \ + par2 = __NR_##name; \ + __asm__ __volatile__( \ + "trap 47" \ + :"=l"(par1) \ + :"0"(par1), "l"(par2)\ + :"memory","L14","L15"); \ + \ + if( par1 < 0 ) { \ + __set_errno( -par1 ); \ + return -1; \ + } else \ + return (type)(par1); \ +} + +#define __syscall1(type, name, atype, a) \ +type name(atype a, ...) \ +{ \ + register int par1 __asm__("L15"); \ + register int par2 __asm__("L14"); \ + register int par3 __asm__("L13"); \ + par1 = -1; \ + par2 = __NR_##name; \ + par3 = (int)a; \ + __asm__ __volatile__( \ + "trap 47" \ + :"=l"(par1) \ + :"0"(par1), "l"(par2), "l"(par3)\ + :"memory","L13","L14","L15"); \ + \ + if( par1 < 0 ) { \ + __set_errno( -par1 ); \ + return -1; \ + } else \ + return (type)(par1); \ +} + +#define __syscall2(type, name,atype, a, btype, b) \ +type name(atype a, btype b, ...) \ +{ \ + register int par1 __asm__("L15"); \ + register int par2 __asm__("L14"); \ + register int par3 __asm__("L13"); \ + register int par4 __asm__("L12"); \ + par1 = -1; \ + par2 = __NR_##name; \ + par3 = (int)a; \ + par4 = (int)b; \ + __asm__ __volatile__( \ + "trap 47" \ + :"=l"(par1) \ + :"0"(par1), "l"(par2), "l"(par3), "l"(par4)\ + :"memory","L12","L13","L14","L15"); \ + \ + if( par1 < 0 ) { \ + __set_errno( -par1 ); \ + return -1; \ + } else \ + return (type)(par1); \ +} + +#define __syscall3(type, name,atype, a, btype, b, ctype, c) \ +type name(atype a, btype b, ctype c, ...) \ +{ \ + register int par1 __asm__("L15"); \ + register int par2 __asm__("L14"); \ + register int par3 __asm__("L13"); \ + register int par4 __asm__("L12"); \ + register int par5 __asm__("L11"); \ + par1 = -1; \ + par2 = __NR_##name; \ + par3 = (int)a; \ + par4 = (int)b; \ + par5 = (int)c; \ + __asm__ __volatile__( \ + "trap 47" \ + :"=l"(par1) \ + :"0"(par1), "l"(par2), "l"(par3), "l"(par4), "l"(par5) \ + :"memory","L11","L12","L13","L14","L15"); \ + \ + if( par1 < 0 ) { \ + __set_errno( -par1 ); \ + return -1; \ + } else \ + return (type)(par1); \ +} + +#define __syscall4(type, name,atype, a, btype, b, ctype, c, dtype, d) \ +type name(atype a, btype b, ctype c,dtype d, ...) \ +{ \ + register int par1 __asm__("L15"); \ + register int par2 __asm__("L14"); \ + register int par3 __asm__("L13"); \ + register int par4 __asm__("L12"); \ + register int par5 __asm__("L11"); \ + register int par6 __asm__("L10"); \ + par1 = -1; \ + par2 = __NR_##name; \ + par3 = (int)a; \ + par4 = (int)b; \ + par5 = (int)c; \ + par6 = (int)d; \ + __asm__ __volatile__( \ + "trap 47" \ + :"=l"(par1) \ + :"0"(par1),"l"(par2),"l"(par3),"l"(par4),"l"(par5),"l"(par6) \ + :"memory","L10","L11","L12","L13","L14","L15"); \ + \ + if( par1 < 0 ) { \ + __set_errno( -par1 ); \ + return -1; \ + } else \ + return (type)(par1); \ +} + +#define __syscall5(type, name,atype, a, btype, b, ctype, c, dtype, d, etype, e) \ +type name(atype a, btype b, ctype c,dtype d, etype e, ...) \ +{ \ + register int par1 __asm__("L15"); \ + register int par2 __asm__("L14"); \ + register int par3 __asm__("L13"); \ + register int par4 __asm__("L12"); \ + register int par5 __asm__("L11"); \ + register int par6 __asm__("L10"); \ + register int par7 __asm__("L9"); \ + par1 = -1; \ + par2 = __NR_##name; \ + par3 = (int)a; \ + par4 = (int)b; \ + par5 = (int)c; \ + par6 = (int)d; \ + par7 = (int)e; \ + __asm__ __volatile__( \ + "trap 47" \ + :"=l"(par1) \ + :"0"(par1),"l"(par2),"l"(par3),"l"(par4),"l"(par5),"l"(par6),"l"(par7) \ + :"memory","L9","L10","L11","L12","L13","L14","L15"); \ + \ + if( par1 < 0 ) { \ + __set_errno( -par1 ); \ + return -1; \ + } else \ + return (type)(par1); \ +} + +#define __syscall6(type, name,atype, a, btype, b, ctype, c, dtype, d, etype, e, ftype, f) \ +type name(atype a, btype b, ctype c,dtype d, etype e, ftype f, ...) \ +{ \ + register int par1 __asm__("L15"); \ + register int par2 __asm__("L14"); \ + register int par3 __asm__("L13"); \ + register int par4 __asm__("L12"); \ + register int par5 __asm__("L11"); \ + register int par6 __asm__("L10"); \ + register int par7 __asm__("L9"); \ + register int par8 __asm__("L8"); \ + par1 = -1; \ + par2 = __NR_##name; \ + par3 = (int)a; \ + par4 = (int)b; \ + par5 = (int)c; \ + par6 = (int)d; \ + par7 = (int)e; \ + par7 = (int)f; \ + __asm__ __volatile__( \ + "trap 47" \ + :"=l"(par1) \ + :"0"(par1),"l"(par2),"l"(par3),"l"(par4),"l"(par5),"l"(par6),"l"(par7),"l"(par8) \ + :"memory","L8","L9","L10","L11","L12","L13","L14","L15"); \ + \ + if( par1 < 0 ) { \ + __set_errno( -par1 ); \ + return -1; \ + } else \ + return (type)(par1); \ +} + +#include +/* Taken from */ +#ifndef _LIBC +/* We don't support pthreads for the moment*/ +#define __set_errno(val) ((errno) = (val)) +#endif + +#if 0 +#define _syscall3(type, name,atype, a , btype, b, ctype, c) \ +type name(atype a, btype b, ctype c,) \ +{ \ + __asm__ __volatile__( \ + "movi L9, -1\n\t" \ + "movi L8, %0\n\t" \ + "ldw.d G3, L7, 0\n\t" \ + "ldw.d G3, L6, 4\n\t" \ + "ldw.d G3, L5, 8\n\t" \ + :/* no output */ \ + :"i"(__NR_##name) \ + :"cc","memory","%L5","L6","L7","L8","L9");\ + __asm__ __volatile__( \ + "trap 47\n\t" \ + "mov L2, L9\n\t"); \ +} + +#define _syscall4(type, name,atype, a, btype, b, ctype, c, dtype, d) \ +type name(atype a, btype b, ctype c,dtype d) \ +{ \ + __asm__ __volatile__( \ + "movi L11, -1\n\t" \ + "movi L10, %0\n\t" \ + "ldw.d G3, L9, 0\n\t" \ + "ldw.d G3, L8, 4\n\t" \ + "ldw.d G3, L7, 8\n\t" \ + "ldw.d G3, L6, 12\n\t" \ + :/* no output */ \ + :"i"(__NR_##name) \ + :"cc","memory","L6","L7","L8","L9","L10","L11");\ + __asm__ __volatile__( \ + "trap 47\n\t" \ + "mov L2, L11\n\t"); \ +} + +#define _syscall5(type, name,atype, a, btype, b, ctype, c, dtype, d, etype, e) \ +type name(atype a, btype b, ctype c,dtype d, etype e) \ +{ \ + __asm__ __volatile__( \ + "movi L13, -1\n\t" \ + "movi L12, %0\n\t" \ + "ldw.d G3, L11, 0\n\t" \ + "ldw.d G3, L10, 4\n\t" \ + "ldw.d G3, L9, 8\n\t" \ + "ldw.d G3, L8, 12\n\t" \ + "ldw.d G3, L7, 16\n\t" \ + :/* no output */ \ + :"i"(__NR_##name) \ + :"cc","memory","L7","L8","L9","L10","L11","L12","L13");\ + __asm__ __volatile__( \ + "trap 47\n\t" \ + "mov L2, L13\n\t"); \ +} + +#define _syscall6(type, name,atype, a, btype, b, ctype, c, dtype, d, etype, e, ftype, f) \ +type name(atype a, btype b, ctype c,dtype d, etype e, ftype f) \ +{ \ + __asm__ __volatile__( \ + "movi L15, -1\n\t" \ + "movi L14, %0\n\t" \ + "ldw.d G3, L13, 0\n\t" \ + "ldw.d G3, L12, 4\n\t" \ + "ldw.d G3, L11, 8\n\t" \ + "ldw.d G3, L10, 12\n\t" \ + "ldw.d G3, L9, 16\n\t" \ + "ldw.d G3, L8, 20\n\t" \ + :/* no output */ \ + :"i"(__NR_##name) \ + :"cc","memory","L8","L9","L10","L11","L12","L13","L14","L15");\ + __asm__ __volatile__( \ + "trap 47\n\t" \ + "mov L2, L15\n\t"); \ +} +#endif + +#endif /* !_HYPERSTONE_NOMMU_UNISTD_H_ */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/e1/bits/wordsize.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/e1/bits/wordsize.h new file mode 100644 index 00000000..a56d3ef5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/e1/bits/wordsize.h @@ -0,0 +1,22 @@ +/* Copyright (C) 2002-2003, George Thanos + Yannis Mitsos + + Copyright (C) 1999 Free Software Foundation, Inc. + This file is part of the GNU C library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define __WORDSIZE 32 diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/e1/crt0.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/e1/crt0.S new file mode 100644 index 00000000..9d5e98d3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/e1/crt0.S @@ -0,0 +1,17 @@ +/* This file is lisenced under LGPL + * Copyright (C) 2002-2003, George Thanos + * Yannis Mitsos + */ + +.global __start +__start: + call L1, 0, __uClibc_start + +/* Define a symbol for the first piece of initialized data. */ + .data + .globl __data_start +__data_start: + .long 0 + .weak data_start + data_start = __data_start + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/e1/crt1.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/e1/crt1.c new file mode 100644 index 00000000..dd8ed6a2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/e1/crt1.c @@ -0,0 +1,48 @@ +/* vi: set sw=4 ts=4: */ +/* uClibc/sysdeps/linux/m68k/crt0.S + * Pull stuff off the stack and get uClibc moving. + * + * Copyright (C) 2002-2003, George Thanos + * Yannis Mitsos + * + * Copyright (C) 2000,2001 by Erik Andersen + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License + * for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* Stick in a dummy reference to main(), so that if an application + * is linking when the main() function is in a static library (.a) + * we can be sure that main() actually gets linked in */ +extern void main(int argc,void *argv,void *envp); +/* void (*mainp)(int argc,void *argv,void *envp) = main; */ + +void __uClibc_main(int argc,void *argv,void *envp); + +void _uClibc_start(unsigned int first_arg) +{ + unsigned int argc; + char **argv, **envp; + unsigned long *stack; + + stack = (unsigned long*) first_arg; + argc = *(stack); + argv = (char **)(stack + 1); + envp = (char **)(stack + 1 + argc + 1); + + __uClibc_main(argc, argv, envp); +} + +void __main() { } + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/e1/longjmp.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/e1/longjmp.c new file mode 100644 index 00000000..3d188c42 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/e1/longjmp.c @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2002-2003, George Thanos + * Yannis Mitsos + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include + +#define __NR_e1newSP 224 +static __inline__ _syscall1(int, e1newSP, unsigned long, SavedSP ) + +unsigned long jmpbuf_ptr; + +void longjmp(jmp_buf state, int value ) +{ + if(!value) + state->__jmpbuf->ReturnValue = 1; + else + state->__jmpbuf->ReturnValue = value; + + jmpbuf_ptr = (unsigned long)state; + e1newSP(state->__jmpbuf->SavedSP); + +#define _state_ ((struct __jmp_buf_tag*)jmpbuf_ptr) + __asm__ __volatile__("mov L0, %0\n\t" + "mov L1, %1\n\t" + "mov L2, %2\n\t" + "mov G3, %3\n\t" + "mov G4, %4\n\t" + "ret PC, L1\n\t" + :/*no output*/ + :"l"(_state_->__jmpbuf->ReturnValue), + "l"(_state_->__jmpbuf->SavedPC), + "l"(_state_->__jmpbuf->SavedSR), + "l"(_state_->__jmpbuf->G3), + "l"(_state_->__jmpbuf->G4) + :"%G3", "%G4", "%L0", "%L1" ); +#undef _state_ +} + + +void siglongjmp(sigjmp_buf state, int value ) +{ + if( state->__mask_was_saved ) + sigprocmask(SIG_SETMASK, &state->__saved_mask, NULL); + + if(!value) + state->__jmpbuf->ReturnValue = 1; + else + state->__jmpbuf->ReturnValue = value; + + jmpbuf_ptr = (unsigned long)state; + e1newSP(state->__jmpbuf->SavedSP); + + +#define _state_ ((struct __jmp_buf_tag*)jmpbuf_ptr) + __asm__ __volatile__("mov L0, %0\n\t" + "mov L1, %1\n\t" + "mov L2, %2\n\t" + "mov G3, %3\n\t" + "mov G4, %4\n\t" + "ret PC, L1\n\t" + :/*no output*/ + :"l"(_state_->__jmpbuf->ReturnValue), + "l"(_state_->__jmpbuf->SavedPC), + "l"(_state_->__jmpbuf->SavedSR), + "l"(_state_->__jmpbuf->G3), + "l"(_state_->__jmpbuf->G4) + :"%G3", "%G4", "%L0", "%L1" ); +#undef _state_ +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/e1/setjmp.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/e1/setjmp.c new file mode 100644 index 00000000..e8a758c9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/e1/setjmp.c @@ -0,0 +1,55 @@ +/* This file is lisenced under LGPL + * Copyright (C) 2002-2003, George Thanos + * Yannis Mitsos + */ + +#include +#include +#include + + +int setjmp( jmp_buf state) +{ + __asm__ __volatile__( "mov %0, G3\n\t" + "mov %1, G4\n\t" + :"=l"(state->__jmpbuf->G3), + "=l"(state->__jmpbuf->G4) + :/*no input*/ + :"%G3", "%G4" ); + + __asm__ __volatile__( "setadr %0\n\t" + "mov %1, L1\n\t" + "mov %2, L2\n\t" + :"=l"(state->__jmpbuf->SavedSP), + "=l"(state->__jmpbuf->SavedPC), + "=l"(state->__jmpbuf->SavedSR) + :/*no input*/); + return 0; +} + +int sigsetjmp( sigjmp_buf state , int savesigs) +{ + + if(savesigs) { + state->__mask_was_saved = 1; + /* how arg in is not significant */ + sigprocmask(SIG_SETMASK, NULL, &state->__saved_mask); + } else + state->__mask_was_saved = 0; + + __asm__ __volatile__( "mov %0, G3\n\t" + "mov %1, G4\n\t" + :"=l"(state->__jmpbuf->G3), + "=l"(state->__jmpbuf->G4) + :/*no input*/ + :"%G3", "%G4" ); + + __asm__ __volatile__( "setadr %0\n\t" + "mov %1, L2\n\t" + "mov %2, L3\n\t" + :"=l"(state->__jmpbuf->SavedSP), + "=l"(state->__jmpbuf->SavedPC), + "=l"(state->__jmpbuf->SavedSR) + :/*no input*/); + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/e1/sys/procfs.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/e1/sys/procfs.h new file mode 100644 index 00000000..8416b3b5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/e1/sys/procfs.h @@ -0,0 +1,31 @@ +/* Copyright (C) 1996, 1997, 1999, 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_PROCFS_H +#define _SYS_PROCFS_H 1 + +/* This is somewhat modelled after the file of the same name on SVR4 + systems. It provides a definition of the core file format for ELF + used on Linux. It doesn't have anything to do with the /proc file + system, even though Linux has one. + + Anyway, the whole purpose of this file is for GDB and GDB only. + Don't read too much into it. Don't use it for anything other than + GDB unless you know what you are doing. */ + +#endif /* sys/procfs.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/e1/sys/reg.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/e1/sys/reg.h new file mode 100644 index 00000000..a8a7ec1b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/e1/sys/reg.h @@ -0,0 +1,25 @@ +/* Copyright (C) 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_REG_H +#define _SYS_REG_H 1 + +/* Index into an array of 4 byte integers returned from ptrace for + location of the users' stored general purpose registers. */ + +#endif /* _SYS_REG_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/e1/sys/ucontext.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/e1/sys/ucontext.h new file mode 100644 index 00000000..3c441dc5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/e1/sys/ucontext.h @@ -0,0 +1,109 @@ +/* Copyright (C) 1997, 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* System V/m68k ABI compliant context switching support. */ + +#ifndef _SYS_UCONTEXT_H +#define _SYS_UCONTEXT_H 1 + +#include +#include + +/* Type for general register. */ +typedef int greg_t; + +/* Number of general registers. */ +#define NGREG 18 + +/* Container for all general registers. */ +typedef greg_t gregset_t[NGREG]; + +/* Number of each register is the `gregset_t' array. */ +enum +{ + R_D0 = 0, +#define R_D0 R_D0 + R_D1 = 1, +#define R_D1 R_D1 + R_D2 = 2, +#define R_D2 R_D2 + R_D3 = 3, +#define R_D3 R_D3 + R_D4 = 4, +#define R_D4 R_D4 + R_D5 = 5, +#define R_D5 R_D5 + R_D6 = 6, +#define R_D6 R_D6 + R_D7 = 7, +#define R_D7 R_D7 + R_A0 = 8, +#define R_A0 R_A0 + R_A1 = 9, +#define R_A1 R_A1 + R_A2 = 10, +#define R_A2 R_A2 + R_A3 = 11, +#define R_A3 R_A3 + R_A4 = 12, +#define R_A4 R_A4 + R_A5 = 13, +#define R_A5 R_A5 + R_A6 = 14, +#define R_A6 R_A6 + R_A7 = 15, +#define R_A7 R_A7 + R_SP = 15, +#define R_SP R_SP + R_PC = 16, +#define R_PC R_PC + R_PS = 17 +#define R_PS R_PS +}; + +/* Structure to describe FPU registers. */ +typedef struct fpregset +{ + int f_fpregs[8][3]; + int f_pcr; + int f_psr; + int f_fpiaddr; +} fpregset_t; + +/* Context to describe whole processor state. */ +typedef struct +{ + int version; + gregset_t gregs; + fpregset_t fpregs; +} mcontext_t; + +#define MCONTEXT_VERSION 2 + +/* Userlevel context. */ +typedef struct ucontext +{ + unsigned long int uc_flags; + struct ucontext *uc_link; + __sigset_t uc_sigmask; + stack_t uc_stack; + mcontext_t uc_mcontext; + long int uc_filler[174]; +} ucontext_t; + +#endif /* sys/ucontext.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/e1/syscalls.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/e1/syscalls.c new file mode 100644 index 00000000..e58ad5f7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/e1/syscalls.c @@ -0,0 +1,11 @@ +/* This file is lisenced under LGPL + * Copyright (C) 2002-2003, George Thanos + * Yannis Mitsos + */ + +#include + +/* We now need a declaration of the `errno' variable. */ +extern int errno; +# define __set_errno(val) ((errno) = (val)) +_syscall2( int, kprintf, char *, msg, int, len) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/e1/vfork.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/e1/vfork.c new file mode 100644 index 00000000..c7caafd3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/e1/vfork.c @@ -0,0 +1,14 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include + +#define __NR___vfork __NR_vfork +attribute_hidden _syscall0(pid_t, __vfork) +weak_alias(__vfork,vfork) +libc_hidden_weak(vfork) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/Makefile new file mode 100644 index 00000000..554fdb0f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/Makefile @@ -0,0 +1,58 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2006 Erik Andersen +# ported to FR-V by Alexandre Oliva +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + +TOPDIR=../../../../ +include $(TOPDIR)Rules.mak + +CRT_SRC := crt0.S +CRT_OBJ := crt0.o crt1.o +SCRT_OBJ := $(patsubst %,S%, $(CRT_OBJ)) + +CTOR_TARGETS := crti.o crtn.o + +SSRC := __longjmp.S setjmp.S clone.S vfork.S +SOBJ := $(patsubst %.S,%.o, $(SSRC)) + +CSRC = mmap.c sysdep.c syscall.c brk.c sbrk.c __init_brk.c dl-iterate-phdr.c +CSRC += xstatconv.c stat.c stat64.c fstat.c fstat64.c lstat.c lstat64.c +COBJ := $(patsubst %.c,%.o, $(CSRC)) + +OBJS := $(SOBJ) $(COBJ) + +OBJ_LIST := ../../../obj.sysdeps.$(TARGET_ARCH) + +all: $(OBJ_LIST) + +$(OBJ_LIST): $(OBJS) $(CRT_OBJ) $(SCRT_OBJ) $(CTOR_TARGETS) + $(STRIPTOOL) -x -R .note -R .comment $^ + $(INSTALL) -d $(TOPDIR)lib/ + cp $(CRT_OBJ) $(SCRT_OBJ) $(CTOR_TARGETS) $(TOPDIR)lib/ + echo $(patsubst %, sysdeps/linux/$(TARGET_ARCH)/%, $(OBJS)) > $@ + +$(CRT_OBJ): $(CRT_SRC) crtreloc.o + $(CC) $(ASFLAGS) -DL_$* -r -nostdlib $^ -o $*.o + +crtreloc.o: crtreloc.c + $(CC) $(CFLAGS) -c $< -o $@ + +$(SCRT_OBJ): $(CRT_SRC) Scrtreloc.o + $(CC) $(ASFLAGS) $(PIEFLAG) -DL_$* -r -nostdlib $^ -o $*.o + +Scrtreloc.o: crtreloc.c + $(CC) $(CFLAGS) $(PIEFLAG) -c $< -o $@ + +$(CTOR_TARGETS): %.o : %.S + $(CC) $(ASFLAGS) $(SSP_DISABLE_FLAGS) -c $< -o $@ + +$(SOBJ): %.o : %.S + $(CC) $(ASFLAGS) -c $< -o $@ + +$(COBJ): %.o : %.c + $(CC) $(CFLAGS) -c $< -o $@ + +clean: + $(RM) *.o *~ core diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/__init_brk.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/__init_brk.c new file mode 100644 index 00000000..7e4c8d13 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/__init_brk.c @@ -0,0 +1,26 @@ +/* From libc-5.3.12 */ + +#include +#include +#include + +void * __curbrk attribute_hidden = 0; + +#define __NR__brk __NR_brk +attribute_hidden _syscall1(void *, _brk, void *, ptr) + +extern int __init_brk(void) attribute_hidden; +int +__init_brk (void) +{ + if (__curbrk == 0) + { + __curbrk = _brk(0); + if (__curbrk == 0) + { + __set_errno(ENOMEM); + return -1; + } + } + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/__longjmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/__longjmp.S new file mode 100644 index 00000000..c3145c84 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/__longjmp.S @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define _SETJMP_H +#define _ASM +#include + +# setjmp/longjmp for Frv. The jmpbuf looks like this: +# +# Register jmpbuf offset +# R16-R31 0x0-0x03c +# R48-R63 0x40-0x7c +# FR16-FR31 0x80-0xbc +# FR48-FR63 0xc0-0xfc +# LR 0x100 +# SP 0x104 +# FP 0x108 +# +# R8 contains the pointer to jmpbuf + + .text + .global __longjmp + .type __longjmp,@function +__longjmp: + lddi @(gr8,0), gr16 + lddi @(gr8,8), gr18 + lddi @(gr8,16), gr20 + lddi @(gr8,24), gr22 + lddi @(gr8,32), gr24 + lddi @(gr8,40), gr26 + lddi @(gr8,48), gr28 + lddi @(gr8,56), gr30 +#if __FRV_GPR__ != 32 + lddi @(gr8,64), gr48 + lddi @(gr8,72), gr50 + lddi @(gr8,80), gr52 + lddi @(gr8,88), gr54 + lddi @(gr8,96), gr56 + lddi @(gr8,104), gr58 + lddi @(gr8,112), gr60 + lddi @(gr8,120), gr62 +#endif + +#if __FRV_FPR__ != 0 + lddfi @(gr8,128), fr16 + lddfi @(gr8,136), fr18 + lddfi @(gr8,144), fr20 + lddfi @(gr8,152), fr22 + lddfi @(gr8,160), fr24 + lddfi @(gr8,168), fr26 + lddfi @(gr8,176), fr28 + lddfi @(gr8,184), fr30 +#if __FRV_FPR__ != 32 + lddfi @(gr8,192), fr48 + lddfi @(gr8,200), fr50 + lddfi @(gr8,208), fr52 + lddfi @(gr8,216), fr54 + lddfi @(gr8,224), fr56 + lddfi @(gr8,232), fr58 + lddfi @(gr8,240), fr60 + lddfi @(gr8,248), fr62 +#endif +#endif + + ldi @(gr8,256), gr4 + movgs gr4,lr + + ldi @(gr8,260), sp + ldi @(gr8,264), fp + +# Value to return is in r9. If zero, return 1 + cmp gr9, gr0, icc0 + setlos #1, gr8 + ckne icc0, cc4 + cmov gr9, gr8, cc4, 1 + ret +.Lend2: + .size __longjmp,.Lend2-__longjmp + +libc_hidden_def(__longjmp) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/bits/elf-fdpic.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/bits/elf-fdpic.h new file mode 100644 index 00000000..b7e87b8e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/bits/elf-fdpic.h @@ -0,0 +1,115 @@ +/* Copyright 2003, 2004 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation; either version 2.1 of the +License, or (at your option) any later version. + +In addition to the permissions in the GNU Lesser General Public +License, the Free Software Foundation gives you unlimited +permission to link the compiled version of this file with other +programs, and to distribute those programs without any restriction +coming from the use of this file. (The GNU Lesser General Public +License restrictions do apply in other respects; for example, they +cover modification of the file, and distribution when not linked +into another program.) + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#ifndef _BITS_ELF_FDPIC_H +#define _BITS_ELF_FDPIC_H + +/* These data structures are described in the FDPIC ABI extension. + The kernel passes a process a memory map, such that for every LOAD + segment there is an elf32_fdpic_loadseg entry. A pointer to an + elf32_fdpic_loadmap is passed in GR8 at start-up, and a pointer to + an additional such map is passed in GR9 for the interpreter, when + there is one. */ + +#include + +/* This data structure represents a PT_LOAD segment. */ +struct elf32_fdpic_loadseg +{ + /* Core address to which the segment is mapped. */ + Elf32_Addr addr; + /* VMA recorded in the program header. */ + Elf32_Addr p_vaddr; + /* Size of this segment in memory. */ + Elf32_Word p_memsz; +}; + +struct elf32_fdpic_loadmap { + /* Protocol version number, must be zero. */ + Elf32_Half version; + /* Number of segments in this map. */ + Elf32_Half nsegs; + /* The actual memory map. */ + struct elf32_fdpic_loadseg segs[/*nsegs*/]; +}; + +struct elf32_fdpic_loadaddr { + struct elf32_fdpic_loadmap *map; + void *got_value; +}; + +/* Map a pointer's VMA to its corresponding address according to the + load map. */ +static __always_inline void * +__reloc_pointer (void *p, + const struct elf32_fdpic_loadmap *map) +{ + int c; + +#if 0 + if (map->version != 0) + /* Crash. */ + ((void(*)())0)(); +#endif + + /* No special provision is made for NULL. We don't want NULL + addresses to go through relocation, so they shouldn't be in + .rofixup sections, and, if they're present in dynamic + relocations, they shall be mapped to the NULL address without + undergoing relocations. */ + + for (c = 0; + /* Take advantage of the fact that the loadmap is ordered by + virtual addresses. In general there will only be 2 entries, + so it's not profitable to do a binary search. */ + c < map->nsegs && p >= (void*)map->segs[c].p_vaddr; + c++) + { + /* This should be computed as part of the pointer comparison + above, but we want to use the carry in the comparison, so we + can't convert it to an integer type beforehand. */ + unsigned long offset = p - (void*)map->segs[c].p_vaddr; + /* We only check for one-past-the-end for the last segment, + assumed to be the data segment, because other cases are + ambiguous in the absence of padding between segments, and + rofixup already serves as padding between text and data. + Unfortunately, unless we special-case the last segment, we + fail to relocate the _end symbol. */ + if (offset < map->segs[c].p_memsz + || (offset == map->segs[c].p_memsz && c + 1 == map->nsegs)) + return (char*)map->segs[c].addr + offset; + } + + /* We might want to crash instead. */ + return (void*)-1; +} + +# define __RELOC_POINTER(ptr, loadaddr) \ + (__reloc_pointer ((void*)(ptr), \ + (loadaddr).map)) + +#endif /* _BITS_ELF_FDPIC_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/bits/endian.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/bits/endian.h new file mode 100644 index 00000000..3ce83c59 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/bits/endian.h @@ -0,0 +1,7 @@ +/* frv is big-endian. */ + +#ifndef _ENDIAN_H +# error "Never use directly; include instead." +#endif + +#define __BYTE_ORDER __BIG_ENDIAN diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/bits/fcntl.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/bits/fcntl.h new file mode 100644 index 00000000..d437175c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/bits/fcntl.h @@ -0,0 +1,217 @@ +/* O_*, F_*, FD_* bit values for Linux. + Copyright (C) 1995, 1996, 1997, 1998, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FCNTL_H +# error "Never use directly; include instead." +#endif + + +#include + +/* open/fcntl - O_SYNC is only implemented on blocks devices and on files + located on an ext2 file system */ +#define O_ACCMODE 0003 +#define O_RDONLY 00 +#define O_WRONLY 01 +#define O_RDWR 02 +#define O_CREAT 0100 /* not fcntl */ +#define O_EXCL 0200 /* not fcntl */ +#define O_NOCTTY 0400 /* not fcntl */ +#define O_TRUNC 01000 /* not fcntl */ +#define O_APPEND 02000 +#define O_NONBLOCK 04000 +#define O_NDELAY O_NONBLOCK +#define O_SYNC 010000 +#define O_FSYNC O_SYNC +#define O_ASYNC 020000 + +#ifdef __USE_GNU +# define O_DIRECT 040000 /* Direct disk access. */ +# define O_DIRECTORY 0200000 /* Must be a directory. */ +# define O_NOFOLLOW 0400000 /* Do not follow links. */ +# define O_NOATIME 01000000 /* don't set atime */ +# define O_CLOEXEC 02000000 /* set close_on_exec */ +#endif + +/* For now Linux has synchronisity options for data and read operations. + We define the symbols here but let them do the same as O_SYNC since + this is a superset. */ +#if defined __USE_POSIX199309 || defined __USE_UNIX98 +# define O_DSYNC O_SYNC /* Synchronize data. */ +# define O_RSYNC O_SYNC /* Synchronize read operations. */ +#endif + +#ifdef __USE_LARGEFILE64 +# define O_LARGEFILE 0100000 +#endif + +/* Values for the second argument to `fcntl'. */ +#define F_DUPFD 0 /* Duplicate file descriptor. */ +#define F_GETFD 1 /* Get file descriptor flags. */ +#define F_SETFD 2 /* Set file descriptor flags. */ +#define F_GETFL 3 /* Get file status flags. */ +#define F_SETFL 4 /* Set file status flags. */ +#ifndef __USE_FILE_OFFSET64 +# define F_GETLK 5 /* Get record locking info. */ +# define F_SETLK 6 /* Set record locking info (non-blocking). */ +# define F_SETLKW 7 /* Set record locking info (blocking). */ +#else +# define F_GETLK F_GETLK64 /* Get record locking info. */ +# define F_SETLK F_SETLK64 /* Set record locking info (non-blocking).*/ +# define F_SETLKW F_SETLKW64 /* Set record locking info (blocking). */ +#endif +#define F_GETLK64 12 /* Get record locking info. */ +#define F_SETLK64 13 /* Set record locking info (non-blocking). */ +#define F_SETLKW64 14 /* Set record locking info (blocking). */ + +#if defined __USE_BSD || defined __USE_XOPEN2K +# define F_SETOWN 8 /* Get owner of socket (receiver of SIGIO). */ +# define F_GETOWN 9 /* Set owner of socket (receiver of SIGIO). */ +#endif + +#ifdef __USE_GNU +# define F_SETSIG 10 /* Set number of signal to be sent. */ +# define F_GETSIG 11 /* Get number of signal to be sent. */ +#endif + +#ifdef __USE_GNU +# define F_SETLEASE 1024 /* Set a lease. */ +# define F_GETLEASE 1025 /* Enquire what lease is active. */ +# define F_NOTIFY 1026 /* Request notfications on a directory. */ +# define F_DUPFD_CLOEXEC 1030 /* Duplicate file descriptor with + close-on-exit set on new fd. */ +#endif + +/* For F_[GET|SET]FL. */ +#define FD_CLOEXEC 1 /* actually anything with low bit set goes */ + +/* For posix fcntl() and `l_type' field of a `struct flock' for lockf(). */ +#define F_RDLCK 0 /* Read lock. */ +#define F_WRLCK 1 /* Write lock. */ +#define F_UNLCK 2 /* Remove lock. */ + +/* For old implementation of bsd flock(). */ +#define F_EXLCK 4 /* or 3 */ +#define F_SHLCK 8 /* or 4 */ + +#ifdef __USE_BSD +/* Operations for bsd flock(), also used by the kernel implementation. */ +# define LOCK_SH 1 /* shared lock */ +# define LOCK_EX 2 /* exclusive lock */ +# define LOCK_NB 4 /* or'd with one of the above to prevent + blocking */ +# define LOCK_UN 8 /* remove lock */ +#endif + +struct flock + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ +#ifndef __USE_FILE_OFFSET64 + __off_t l_start; /* Offset where the lock begins. */ + __off_t l_len; /* Size of the locked area; zero means until EOF. */ +#else + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ +#endif + __pid_t l_pid; /* Process holding the lock. */ + }; + +#ifdef __USE_LARGEFILE64 +struct flock64 + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ + __pid_t l_pid; /* Process holding the lock. */ + }; +#endif + +/* Define some more compatibility macros to be backward compatible with + BSD systems which did not managed to hide these kernel macros. */ +#ifdef __USE_BSD +# define FAPPEND O_APPEND +# define FFSYNC O_FSYNC +# define FASYNC O_ASYNC +# define FNONBLOCK O_NONBLOCK +# define FNDELAY O_NDELAY +#endif /* Use BSD. */ + +/* Advise to `posix_fadvise'. */ +#ifdef __USE_XOPEN2K +# define POSIX_FADV_NORMAL 0 /* No further special treatment. */ +# define POSIX_FADV_RANDOM 1 /* Expect random page references. */ +# define POSIX_FADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define POSIX_FADV_WILLNEED 3 /* Will need these pages. */ +# define POSIX_FADV_DONTNEED 4 /* Don't need these pages. */ +# define POSIX_FADV_NOREUSE 5 /* Data will be accessed once. */ +#endif + + +#if defined __USE_GNU && defined __UCLIBC_LINUX_SPECIFIC__ +/* Flags for SYNC_FILE_RANGE. */ +# define SYNC_FILE_RANGE_WAIT_BEFORE 1 /* Wait upon writeout of all pages + in the range before performing the + write. */ +# define SYNC_FILE_RANGE_WRITE 2 /* Initiate writeout of all those + dirty pages in the range which are + not presently under writeback. */ +# define SYNC_FILE_RANGE_WAIT_AFTER 4 /* Wait upon writeout of all pages in + the range after performing the + write. */ + +/* Flags for SPLICE and VMSPLICE. */ +# define SPLICE_F_MOVE 1 /* Move pages instead of copying. */ +# define SPLICE_F_NONBLOCK 2 /* Don't block on the pipe splicing + (but we may still block on the fd + we splice from/to). */ +# define SPLICE_F_MORE 4 /* Expect more data. */ +# define SPLICE_F_GIFT 8 /* Pages passed in are a gift. */ +#endif + +__BEGIN_DECLS + +#if defined __USE_GNU && defined __UCLIBC_LINUX_SPECIFIC__ + +/* Provide kernel hint to read ahead. */ +extern ssize_t readahead (int __fd, __off64_t __offset, size_t __count) + __THROW; + + +/* Selective file content synch'ing. */ +extern int sync_file_range (int __fd, __off64_t __from, __off64_t __to, + unsigned int __flags); + +/* Splice address range into a pipe. */ +extern ssize_t vmsplice (int __fdout, const struct iovec *__iov, + size_t __count, unsigned int __flags); + +/* Splice two files together. */ +extern ssize_t splice (int __fdin, __off64_t *__offin, int __fdout, + __off64_t *__offout, size_t __len, + unsigned int __flags); + +/* In-kernel implementation of tee for pipe buffers. */ +extern ssize_t tee (int __fdin, int __fdout, size_t __len, + unsigned int __flags); + +#endif +__END_DECLS + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/bits/kernel_stat.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/bits/kernel_stat.h new file mode 100644 index 00000000..634066df --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/bits/kernel_stat.h @@ -0,0 +1,78 @@ +#ifndef _BITS_STAT_STRUCT_H +#define _BITS_STAT_STRUCT_H + +#ifndef _LIBC +#error bits/kernel_stat.h is for internal uClibc use only! +#endif + +/* This file provides whatever this particular arch's kernel thinks + * struct kernel_stat should look like... It turns out each arch has a + * different opinion on the subject... */ + +struct kernel_stat { + unsigned char __pad1[6]; + unsigned short st_dev; + + unsigned long __pad2; + unsigned long st_ino; + + unsigned short __pad3; + unsigned short st_mode; + unsigned short __pad4; + unsigned short st_nlink; + + unsigned short __pad5; + unsigned short st_uid; + unsigned short __pad6; + unsigned short st_gid; + + unsigned char __pad7[6]; + unsigned short st_rdev; + + unsigned long __pad8; + unsigned long st_size; + + unsigned long __pad9; /* align 64-bit st_blocks to 2-word */ + unsigned long st_blksize; + + unsigned long __pad10; /* future possible st_blocks high bits */ + unsigned long st_blocks; /* Number 512-byte blocks allocated. */ + + struct timespec st_atim; + struct timespec st_mtim; + struct timespec st_ctim; + + unsigned long long __unused4; +}; + +struct kernel_stat64 { + unsigned char __pad1[6]; + unsigned short st_dev; + + unsigned long long st_ino; + + unsigned int st_mode; + unsigned int st_nlink; + + unsigned long st_uid; + unsigned long st_gid; + + unsigned char __pad2[6]; + unsigned short st_rdev; + + long long st_size; + + unsigned long __pad3; /* align 64-bit st_blocks to 2-word */ + unsigned long st_blksize; + + unsigned long __pad4; /* future possible st_blocks high bits */ + unsigned long st_blocks; /* Number 512-byte blocks allocated. */ + + struct timespec st_atim; + struct timespec st_mtim; + struct timespec st_ctim; + + unsigned long long __unused4; +}; + +#endif /* _BITS_STAT_STRUCT_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/bits/kernel_types.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/bits/kernel_types.h new file mode 100644 index 00000000..8403fd3e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/bits/kernel_types.h @@ -0,0 +1,43 @@ +/* Note that we use the exact same include guard #define names + * as asm/posix_types.h. This will avoid gratuitous conflicts + * with the posix_types.h kernel header, and will ensure that + * our private content, and not the kernel header, will win. + * -Erik + */ +#ifndef _ASM_POSIX_TYPES_H +#define _ASM_POSIX_TYPES_H + +typedef unsigned short __kernel_dev_t; +typedef unsigned long __kernel_ino_t; +typedef unsigned short __kernel_mode_t; +typedef unsigned short __kernel_nlink_t; +typedef long __kernel_off_t; +typedef int __kernel_pid_t; +typedef unsigned short __kernel_ipc_pid_t; +typedef unsigned short __kernel_uid_t; +typedef unsigned short __kernel_gid_t; +typedef unsigned int __kernel_size_t; +typedef int __kernel_ssize_t; +typedef int __kernel_ptrdiff_t; +typedef long __kernel_time_t; +typedef long __kernel_suseconds_t; +typedef long __kernel_clock_t; +typedef int __kernel_daddr_t; +typedef char * __kernel_caddr_t; +typedef unsigned short __kernel_uid16_t; +typedef unsigned short __kernel_gid16_t; +typedef unsigned int __kernel_uid32_t; +typedef unsigned int __kernel_gid32_t; +typedef unsigned short __kernel_old_uid_t; +typedef unsigned short __kernel_old_gid_t; +typedef long long __kernel_loff_t; + +typedef struct { +#ifdef __USE_ALL + int val[2]; +#else + int __val[2]; +#endif +} __kernel_fsid_t; + +#endif /* _ASM_POSIX_TYPES_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/bits/setjmp.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/bits/setjmp.h new file mode 100644 index 00000000..d49ad7b7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/bits/setjmp.h @@ -0,0 +1,58 @@ +/* Copyright (C) 1999, 2000, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Define the machine-dependent type `jmp_buf'. FRV version. */ + +#ifndef _BITS_SETJMP_H +#define _BITS_SETJMP_H 1 + +#if !defined _SETJMP_H && !defined _PTHREAD_H +# error "Never include directly; use instead." +#endif + +#define __SETJMP_NUM_INT 32 /* number of integer registers to save */ +#define __SETJMP_NUM_DBL 32 /* number of double registers to save */ + +#define __SETJMP_INT(x) (x) +#define __SETJMP_DBL(x) (__SETJMP_NUM_INT+(x)) +#define __SETJMP_LR (__SETJMP_NUM_INT+__SETJMP_NUM_DBL) +#define __SETJMP_SP (__SETJMP_LR+1) +#define __SETJMP_FP (__SETJMP_SP+1) + + +#ifndef _ASM +typedef struct +/* Demand 64-bit alignment such that we can use std/ldd in + setjmp/longjmp. */ +__attribute__((__aligned__(8))) + { + /* Callee-saved registers. */ + unsigned long __ints[__SETJMP_NUM_INT]; /* integer registers */ + unsigned long __dbls[__SETJMP_NUM_DBL]; /* double registers */ + unsigned long __lr; /* linkage register */ + unsigned long __sp; /* stack pointer */ + unsigned long __fp; /* frame pointer */ + } __jmp_buf[1]; +#endif + +/* Test if longjmp to JMPBUF would unwind the frame + containing a local variable at ADDRESS. */ +#define _JMPBUF_UNWINDS(jmpbuf, address) \ + ((void *) (address) < (void *) (jmpbuf)->__sp) + +#endif /* bits/setjmp.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/bits/stackinfo.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/bits/stackinfo.h new file mode 100644 index 00000000..03412e00 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/bits/stackinfo.h @@ -0,0 +1,28 @@ +/* Copyright (C) 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This file contains a bit of information about the stack allocation + of the processor. */ + +#ifndef _STACKINFO_H +#define _STACKINFO_H 1 + +/* On FRV the stack grows down. */ +#define _STACK_GROWS_DOWN 1 + +#endif /* stackinfo.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/bits/stat.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/bits/stat.h new file mode 100644 index 00000000..0fcacf19 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/bits/stat.h @@ -0,0 +1,159 @@ +/* Copyright (C) 1992,95,96,97,98,99,2000,2001, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_STAT_H +# error "Never include directly; use instead." +#endif + +#ifndef _BITS_STAT_H +#define _BITS_STAT_H + +/* Versions of the `struct stat' data structure. */ +#define _STAT_VER_KERNEL 0 +#define _STAT_VER_LINUX 0 +#define _STAT_VER _STAT_VER_LINUX /* The one defined below. */ + +/* Versions of the `xmknod' interface. */ +#define _MKNOD_VER_LINUX 1 +#define _MKNOD_VER_SVR4 2 +#define _MKNOD_VER _MKNOD_VER_LINUX /* The bits defined below. */ + +struct stat +{ + __dev_t st_dev; /* Device. */ + +#ifndef __USE_FILE_OFFSET64 + unsigned long __pad1; + __ino_t st_ino; /* File serial number. */ +#else + __ino64_t st_ino; /* File serial number. */ +#endif + + __mode_t st_mode; /* File mode. */ + __nlink_t st_nlink; /* Link count. */ + + __uid_t st_uid; /* User ID of the file's owner. */ + __gid_t st_gid; /* Group ID of the file's group.*/ + + __dev_t st_rdev; /* Device number, if device. */ + +#ifndef __USE_FILE_OFFSET64 + unsigned long __pad2; + __off_t st_size; /* Size of file, in bytes. */ + + unsigned long __pad3; +#else + __off64_t st_size; /* Size of file, in bytes. */ + + unsigned long __pad1; +#endif + __blksize_t st_blksize; /* Optimal block size for I/O. */ + +#ifndef __USE_FILE_OFFSET64 + unsigned long __pad4; + __blkcnt_t st_blocks; /* Number 512-byte blocks allocated. */ +#else + __blkcnt64_t st_blocks; /* Number 512-byte blocks allocated. */ +#endif + + unsigned long int __unused1; + __time_t st_atime; /* Time of last access. */ + + unsigned long int __unused2; + __time_t st_mtime; /* Time of last modification. */ + + unsigned long int __unused3; + __time_t st_ctime; /* Time of last status change. */ + + unsigned long long __unused4; +}; + +#ifdef __USE_LARGEFILE64 +struct stat64 +{ + __dev_t st_dev; /* Device. */ + + __ino64_t st_ino; /* File serial number. */ + + __mode_t st_mode; /* File mode. */ + __nlink_t st_nlink; /* Link count. */ + + __uid_t st_uid; /* User ID of the file's owner. */ + __gid_t st_gid; /* Group ID of the file's group.*/ + + __dev_t st_rdev; /* Device number, if device. */ + + __off64_t st_size; /* Size of file, in bytes. */ + + unsigned long __pad1; + __blksize_t st_blksize; /* Optimal block size for I/O. */ + + __blkcnt64_t st_blocks; /* Number 512-byte blocks allocated. */ + + unsigned long int __unused1; + __time_t st_atime; /* Time of last access. */ + + unsigned long int __unused2; + __time_t st_mtime; /* Time of last modification. */ + + unsigned long int __unused3; + __time_t st_ctime; /* Time of last status change. */ + + unsigned long long __unused4; +}; +#endif + + +/* Tell code we have these members. */ +#define _STATBUF_ST_BLKSIZE +#define _STATBUF_ST_RDEV + +/* Encoding of the file mode. */ + +#define __S_IFMT 0170000 /* These bits determine file type. */ + +/* File types. */ +#define __S_IFDIR 0040000 /* Directory. */ +#define __S_IFCHR 0020000 /* Character device. */ +#define __S_IFBLK 0060000 /* Block device. */ +#define __S_IFREG 0100000 /* Regular file. */ +#define __S_IFIFO 0010000 /* FIFO. */ +#define __S_IFLNK 0120000 /* Symbolic link. */ +#define __S_IFSOCK 0140000 /* Socket. */ + +/* POSIX.1b objects. Note that these macros always evaluate to zero. But + they do it by enforcing the correct use of the macros. */ +#define __S_TYPEISMQ(buf) ((buf)->st_mode - (buf)->st_mode) +#define __S_TYPEISSEM(buf) ((buf)->st_mode - (buf)->st_mode) +#define __S_TYPEISSHM(buf) ((buf)->st_mode - (buf)->st_mode) + +/* Protection bits. */ + +#define __S_ISUID 04000 /* Set user ID on execution. */ +#define __S_ISGID 02000 /* Set group ID on execution. */ +#define __S_ISVTX 01000 /* Save swapped text after use (sticky). */ +#define __S_IREAD 0400 /* Read by owner. */ +#define __S_IWRITE 0200 /* Write by owner. */ +#define __S_IEXEC 0100 /* Execute by owner. */ + +#ifdef __USE_ATFILE +# define UTIME_NOW ((1l << 30) - 1l) +# define UTIME_OMIT ((1l << 30) - 2l) +#endif + +#endif /* _BITS_STAT_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/bits/syscalls.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/bits/syscalls.h new file mode 100644 index 00000000..eea3050b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/bits/syscalls.h @@ -0,0 +1,139 @@ +#ifndef _BITS_SYSCALLS_H +#define _BITS_SYSCALLS_H +#ifndef _SYSCALL_H +# error "Never use directly; include instead." +#endif + +#ifndef __ASSEMBLER__ + +#include + +#define SYS_ify(syscall_name) (__NR_##syscall_name) + +/* user-visible error numbers are in the range -1 - -4095: see */ +#if defined _LIBC && !defined __set_errno +# define __syscall_return(type, res) \ +do { \ + unsigned long __sr2 = (res); \ + if (__builtin_expect ((unsigned long)(__sr2) \ + >= (unsigned long)(-4095), 0)) { \ + extern int __syscall_error (int); \ + return (type) __syscall_error (__sr2); \ + } \ + return (type) (__sr2); \ +} while (0) +#else +# define __syscall_return(type, res) \ +do { \ + unsigned long __sr2 = (res); \ + if (__builtin_expect ((unsigned long)(__sr2) \ + >= (unsigned long)(-4095), 0)) { \ + __set_errno (-__sr2); \ + __sr2 = -1; \ + } \ + return (type) (__sr2); \ +} while (0) +#endif + +#ifndef __set_errno +# define __set_errno(val) ((*__errno_location ()) = (val)) +#endif + +/* XXX - _foo needs to be __foo, while __NR_bar could be _NR_bar. */ + +#define _syscall0(type,name) \ +type name(void) \ +{ \ +register unsigned long __scnum __asm__ ("gr7") = (__NR_##name); \ +register unsigned long __sc0 __asm__ ("gr8"); \ +__asm__ __volatile__ ("tra gr0,gr0" \ + : "=r" (__sc0) \ + : "r" (__scnum)); \ +__syscall_return(type,__sc0); \ +} + +#define _syscall1(type,name,type1,arg1) \ +type name(type1 arg1) \ +{ \ +register unsigned long __scnum __asm__ ("gr7") = (__NR_##name); \ +register unsigned long __sc0 __asm__ ("gr8") = (unsigned long) arg1; \ +__asm__ __volatile__ ("tra gr0,gr0" \ + : "+r" (__sc0) \ + : "r" (__scnum)); \ +__syscall_return(type,__sc0); \ +} + +#define _syscall2(type,name,type1,arg1,type2,arg2) \ +type name(type1 arg1,type2 arg2) \ +{ \ +register unsigned long __scnum __asm__ ("gr7") = (__NR_##name); \ +register unsigned long __sc0 __asm__ ("gr8") = (unsigned long) arg1; \ +register unsigned long __sc1 __asm__ ("gr9") = (unsigned long) arg2; \ +__asm__ __volatile__ ("tra gr0,gr0" \ + : "+r" (__sc0) \ + : "r" (__scnum), "r" (__sc1)); \ +__syscall_return(type,__sc0); \ +} + +#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \ +type name(type1 arg1,type2 arg2,type3 arg3) \ +{ \ +register unsigned long __scnum __asm__ ("gr7") = (__NR_##name); \ +register unsigned long __sc0 __asm__ ("gr8") = (unsigned long) arg1; \ +register unsigned long __sc1 __asm__ ("gr9") = (unsigned long) arg2; \ +register unsigned long __sc2 __asm__ ("gr10") = (unsigned long) arg3; \ +__asm__ __volatile__ ("tra gr0,gr0" \ + : "+r" (__sc0) \ + : "r" (__scnum), "r" (__sc1), "r" (__sc2)); \ +__syscall_return(type,__sc0); \ +} + +#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \ +type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4) \ +{ \ +register unsigned long __scnum __asm__ ("gr7") = (__NR_##name); \ +register unsigned long __sc0 __asm__ ("gr8") = (unsigned long) arg1; \ +register unsigned long __sc1 __asm__ ("gr9") = (unsigned long) arg2; \ +register unsigned long __sc2 __asm__ ("gr10") = (unsigned long) arg3; \ +register unsigned long __sc3 __asm__ ("gr11") = (unsigned long) arg4; \ +__asm__ __volatile__ ("tra gr0,gr0" \ + : "+r" (__sc0) \ + : "r" (__scnum), "r" (__sc1), "r" (__sc2), "r" (__sc3)); \ +__syscall_return(type,__sc0); \ +} + +#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5) \ +type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) \ +{ \ +register unsigned long __scnum __asm__ ("gr7") = (__NR_##name); \ +register unsigned long __sc0 __asm__ ("gr8") = (unsigned long) arg1; \ +register unsigned long __sc1 __asm__ ("gr9") = (unsigned long) arg2; \ +register unsigned long __sc2 __asm__ ("gr10") = (unsigned long) arg3; \ +register unsigned long __sc3 __asm__ ("gr11") = (unsigned long) arg4; \ +register unsigned long __sc4 __asm__ ("gr12") = (unsigned long) arg5; \ +__asm__ __volatile__ ("tra gr0,gr0" \ + : "+r" (__sc0) \ + : "r" (__scnum), "r" (__sc1), "r" (__sc2), \ + "r" (__sc3), "r" (__sc4)); \ +__syscall_return(type,__sc0); \ +} + +#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5, type6, arg6) \ +type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6) \ +{ \ +register unsigned long __scnum __asm__ ("gr7") = (__NR_##name); \ +register unsigned long __sc0 __asm__ ("gr8") = (unsigned long) arg1; \ +register unsigned long __sc1 __asm__ ("gr9") = (unsigned long) arg2; \ +register unsigned long __sc2 __asm__ ("gr10") = (unsigned long) arg3; \ +register unsigned long __sc3 __asm__ ("gr11") = (unsigned long) arg4; \ +register unsigned long __sc4 __asm__ ("gr12") = (unsigned long) arg5; \ +register unsigned long __sc5 __asm__ ("gr13") = (unsigned long) arg6; \ +__asm__ __volatile__ ("tra gr0,gr0" \ + : "+r" (__sc0) \ + : "r" (__scnum), "r" (__sc1), "r" (__sc2), \ + "r" (__sc3), "r" (__sc4), "r" (__sc5)); \ +__syscall_return(type,__sc0); \ +} + +#endif /* __ASSEMBLER__ */ +#endif /* _BITS_SYSCALLS_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/bits/uClibc_arch_features.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/bits/uClibc_arch_features.h new file mode 100644 index 00000000..2a9422e2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/bits/uClibc_arch_features.h @@ -0,0 +1,48 @@ +/* + * Track misc arch-specific features that aren't config options + */ + +#ifndef _BITS_UCLIBC_ARCH_FEATURES_H +#define _BITS_UCLIBC_ARCH_FEATURES_H + +/* instruction used when calling abort() to kill yourself */ +/*#define __UCLIBC_ABORT_INSTRUCTION__ "asm instruction"*/ +#undef __UCLIBC_ABORT_INSTRUCTION__ + +/* can your target use syscall6() for mmap ? */ +#undef __UCLIBC_MMAP_HAS_6_ARGS__ + +/* does your target use syscall4() for truncate64 ? (32bit arches only) */ +#undef __UCLIBC_TRUNCATE64_HAS_4_ARGS__ + +/* does your target have a broken create_module() ? */ +#undef __UCLIBC_BROKEN_CREATE_MODULE__ + +/* does your target have to worry about older [gs]etrlimit() ? */ +#undef __UCLIBC_HANDLE_OLDER_RLIMIT__ + +/* does your target have an asm .set ? */ +#define __UCLIBC_HAVE_ASM_SET_DIRECTIVE__ + +/* define if target doesn't like .global */ +#undef __UCLIBC_ASM_GLOBAL_DIRECTIVE__ + +/* define if target supports .weak */ +#define __UCLIBC_HAVE_ASM_WEAK_DIRECTIVE__ + +/* define if target supports .weakext */ +#undef __UCLIBC_HAVE_ASM_WEAKEXT_DIRECTIVE__ + +/* needed probably only for ppc64 */ +#undef __UCLIBC_HAVE_ASM_GLOBAL_DOT_NAME__ + +/* define if target supports CFI pseudo ops */ +#undef __UCLIBC_HAVE_ASM_CFI_DIRECTIVES__ + +/* define if target supports IEEE signed zero floats */ +#define __UCLIBC_HAVE_SIGNED_ZERO__ + +/* only weird assemblers generally need this */ +#undef __UCLIBC_ASM_LINE_SEP__ + +#endif /* _BITS_UCLIBC_ARCH_FEATURES_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/bits/uClibc_page.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/bits/uClibc_page.h new file mode 100644 index 00000000..51a6e15d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/bits/uClibc_page.h @@ -0,0 +1,32 @@ +/* Copyright (C) 2004 Erik Andersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* Supply an architecture specific value for PAGE_SIZE and friends. */ + +#ifndef _UCLIBC_PAGE_H +#define _UCLIBC_PAGE_H + +/* PAGE_SHIFT determines the page size -- in this case 4096 */ +#define PAGE_SHIFT (14) +#ifndef __ASSEMBLY__ +#define PAGE_SIZE (1UL << PAGE_SHIFT) +#else +#define PAGE_SIZE (1 << PAGE_SHIFT) +#endif +#define PAGE_MASK (~(PAGE_SIZE-1)) + +#endif /* _UCLIBC_PAGE_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/bits/wordsize.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/bits/wordsize.h new file mode 100644 index 00000000..ba643b60 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/bits/wordsize.h @@ -0,0 +1,19 @@ +/* Copyright (C) 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define __WORDSIZE 32 diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/brk.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/brk.c new file mode 100644 index 00000000..a98cd544 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/brk.c @@ -0,0 +1,27 @@ +/* From libc-5.3.12 */ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include + +extern void * __curbrk attribute_hidden; +extern int __init_brk (void) attribute_hidden; +extern void *_brk(void *ptr) attribute_hidden; + +int brk(void * end_data_seg) +{ + if (__init_brk () == 0) + { + __curbrk = _brk(end_data_seg); + if (__curbrk == end_data_seg) + return 0; + __set_errno(ENOMEM); + } + return -1; +} +libc_hidden_def(brk) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/clone.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/clone.S new file mode 100644 index 00000000..14561573 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/clone.S @@ -0,0 +1,83 @@ +/* Copyright (C) 2003, 2004 Free Software Foudnation, Inc. + This file is part of the GNU C Library. + Contributed by Alexandre Oliva , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* clone() is even more special than fork() as it mucks with stacks + and invokes a function in the right context after its all over. */ + +#include +#include +#define _ERRNO_H 1 +#include + + .text + .globl clone + .type clone,@function +/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg) */ +clone: + /* Sanity check arguments. */ + cmp.p gr8, gr0, icc0 + cmp gr9, gr0, icc1 + mov.p gr8, gr4 + beq icc0, #0, .Lerror + mov.p gr11, gr5 + beq icc1, #0, .Lerror + + mov.p gr10, gr8 + setlos #__NR_clone, gr7 + tra gr0,gr0 + + cmp.p gr8, gr0, icc0 + setlos #-4096, gr6 + cmp.p gr8, gr6, icc1 + beq icc0, #0, .Lthread_start + blslr icc1, #2 + +.Lsys_error: + sethi.p #gotofffuncdeschi(__syscall_error), gr14 + setlo #gotofffuncdesclo(__syscall_error), gr14 + ldd @(gr14, gr15), gr14 + jmpl @(gr14, gr0) + +.Lerror: + setlos.p #-EINVAL, gr8 + bra .Lsys_error + +############################################################################### +# +# come here as the new thread [GR4 is fn, GR5 is arg] +# +############################################################################### +.Lthread_start: + /* Save the PIC register. */ + mov gr15, gr17 + + /* Call the user's function. */ + ldd.p @(gr4, gr0), gr14 + mov gr5, gr8 + calll @(gr14, gr0) + + /* Call _exit, rather simply inlining the syscall, such that + breakpoints work.*/ + + mov.p gr17, gr15 + call HIDDEN_JUMPTARGET(_exit) + + /* Should never get here. */ + jmpl @(gr0, gr0) + .size clone,.-clone diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/crt0.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/crt0.S new file mode 100644 index 00000000..a1d07bb6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/crt0.S @@ -0,0 +1,125 @@ +/* Copyright (C) 1991, 1992, 2003, 2004 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation; either version 2.1 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +In addition to the permissions in the GNU Lesser General Public +License, the Free Software Foundation gives you unlimited +permission to link the compiled version of this file with other +programs, and to distribute those programs without any restriction +coming from the use of this file. (The GNU Lesser General Public +License restrictions do apply in other respects; for example, they +cover modification of the file, and distribution when not linked +into another program.) + +You should have received a copy of the GNU Lesser General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + + +/* Based on ../i386/crt0.S and newlib's libgloss/frv/crt0.S */ + +/* + When we enter this piece of code, the program stack looks like this: + argc argument counter (integer) + argv[0] program name (pointer) + argv[1...N] program args (pointers) + argv[argc-1] end of args (integer) + NULL + env[0...N] environment variables (pointers) + NULL + + Also, GR16 holds a pointer to a memory map. */ + +#include + + .text + .global _start + .type _start,%function +#if defined L_crt0 || defined L_Scrt0 || ! defined __UCLIBC_CTOR_DTOR__ + .type __uClibc_main,%function +#else + .weak _init + .weak _fini + .type __uClibc_start_main,%function +#endif +_start: + /* Make sure the stack pointer is properly aligned. Save the + original value in gr21 such that we can get to arguments and + such from there. */ + mov.p sp, gr21 + andi sp, #-8, sp + /* At program start-up, gr16 contains a pointer to a memory + map, that we use to relocate addresses. */ + call .Lcall +.Lcall: + movsg lr, gr4 + sethi.p #gprelhi(.Lcall), gr5 + setlo #gprello(.Lcall), gr5 + sub.p gr4, gr5, gr4 + /* gr4 now holds the _gp address. */ + + mov gr16, gr8 + sethi.p #gprelhi(__ROFIXUP_LIST__), gr9 + sethi #gprelhi(__ROFIXUP_END__), gr10 + setlo.p #gprello(__ROFIXUP_LIST__), gr9 + setlo #gprello(__ROFIXUP_END__), gr10 + add.p gr9, gr4, gr9 + add gr10, gr4, gr10 + call __self_reloc + mov.p gr8, gr17 + mov gr8, gr15 + /* gr17 now holds the self-relocated _GLOBAL_OFFSET_TABLE_ + address, because the linker added its unrelocated address as + the last entry in the ROFIXUP list, and __self_reloc returns + the last entry, relocated. */ + + /* Prepare arguments for uClibc main. */ + ld @(gr21, gr0), gr8 + slli gr8, #2, gr10 + add gr21, gr10, gr10 + addi.p gr21, #4, gr9 + addi gr10, #8, gr10 + + /* Set up an invalid (NULL return address, NULL frame pointer) + callers stack frame so anybody unrolling the stack knows where + to stop */ + mov gr0, fp + movgs gr0, lr + +#if (defined L_crt1 || defined L_Scrt1) && defined __UCLIBC_CTOR_DTOR__ + /* Pass .init and .fini arguments to __uClibc_start_main(). */ + sethi.p #gotfuncdeschi(_init), gr11 + sethi #gotfuncdeschi(_fini), gr12 + setlo.p #gotfuncdesclo(_init), gr11 + setlo #gotfuncdesclo(_fini), gr12 + ld.p @(gr11, gr17), gr11 + mov gr17, gr15 + ld.p @(gr12, gr17), gr12 + call __uClibc_start_main +#else + mov.p gr17, gr15 + call __uClibc_main +#endif + + /* Crash if somehow `exit' returns anyways. */ + jmpl @(gr0,gr0) +.size _start,.-_start + +/* Define a symbol for the first piece of initialized data. */ + .data + .globl __data_start +__data_start: + .long 0 + .weak data_start + data_start = __data_start + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/crti.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/crti.S new file mode 100644 index 00000000..17885246 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/crti.S @@ -0,0 +1,50 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation; either version 2.1 of the +License, or (at your option) any later version. + +In addition to the permissions in the GNU Lesser General Public +License, the Free Software Foundation gives you unlimited +permission to link the compiled version of this file with other +programs, and to distribute those programs without any restriction +coming from the use of this file. (The GNU Lesser General Public +License restrictions do apply in other respects; for example, they +cover modification of the file, and distribution when not linked +into another program.) + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + + .section .init,"x" + .p2align 2 + .globl _init + .type _init, @function +_init: + addi sp,#-16,sp + st.p fp, @(sp,gr0) + mov sp, fp + movsg lr, gr5 + sti gr15, @(fp,4) + sti gr5, @(fp,8) + + .section .fini,"x" + .p2align 2 + .globl _fini + .type _fini, @function +_fini: + addi sp,#-16,sp + st.p fp, @(sp,gr0) + mov sp, fp + movsg lr, gr5 + sti gr15, @(fp,4) + sti gr5, @(fp,8) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/crtn.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/crtn.S new file mode 100644 index 00000000..bd11901a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/crtn.S @@ -0,0 +1,42 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation; either version 2.1 of the +License, or (at your option) any later version. + +In addition to the permissions in the GNU Lesser General Public +License, the Free Software Foundation gives you unlimited +permission to link the compiled version of this file with other +programs, and to distribute those programs without any restriction +coming from the use of this file. (The GNU Lesser General Public +License restrictions do apply in other respects; for example, they +cover modification of the file, and distribution when not linked +into another program.) + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + + .section .init,"x" + .globl _init + .type _init, @function + ldi @(fp,8), gr5 + ld @(sp,gr0), fp + addi sp,#16,sp + jmpl @(gr5,gr0) + + .section .fini,"x" + .globl _fini + .type _fini, @function + ldi @(fp,8), gr5 + ld @(sp,gr0), fp + addi sp,#16,sp + jmpl @(gr5,gr0) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/crtreloc.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/crtreloc.c new file mode 100644 index 00000000..ba934bc5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/crtreloc.c @@ -0,0 +1,120 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. + written by Alexandre Oliva +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation; either version 2.1 of the +License, or (at your option) any later version. + +In addition to the permissions in the GNU Lesser General Public +License, the Free Software Foundation gives you unlimited +permission to link the compiled version of this file with other +programs, and to distribute those programs without any restriction +coming from the use of this file. (The GNU Lesser General Public +License restrictions do apply in other respects; for example, they +cover modification of the file, and distribution when not linked +into another program.) + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include +#include + +/* This file is to be compiled into crt object files, to enable + executables to easily self-relocate. */ + +/* Compute the runtime address of pointer in the range [p,e), and then + map the pointer pointed by it. */ +static __always_inline void *** +reloc_range_indirect (void ***p, void ***e, + const struct elf32_fdpic_loadmap *map) +{ + while (p < e) + { + void *ptr = __reloc_pointer (*p, map); + if (ptr) + { + void *pt; + if ((long)ptr & 3) + __builtin_memcpy(&pt, ptr, sizeof(pt)); + else + pt = *(void**)ptr; + pt = __reloc_pointer (pt, map); + if ((long)ptr & 3) + __builtin_memcpy(ptr, &pt, sizeof(pt)); + else + *(void**)ptr = pt; + } + p++; + } + return p; +} + +/* Call __reloc_range_indirect for the given range except for the last + entry, whose contents are only relocated. It's expected to hold + the GOT value. */ +void* attribute_hidden +__self_reloc (const struct elf32_fdpic_loadmap *map, + void ***p, void ***e) +{ + p = reloc_range_indirect (p, e-1, map); + + if (p >= e) + return (void*)-1; + + return __reloc_pointer (*p, map); +} + +#if 0 +/* These are other functions that might be useful, but that we don't + need. */ + +/* Remap pointers in [p,e). */ +static __always_inline void** +reloc_range (void **p, void **e, + const struct elf32_fdpic_loadmap *map) +{ + while (p < e) + { + *p = __reloc_pointer (*p, map); + p++; + } + return p; +} + +/* Remap p, adjust e by the same offset, then map the pointers in the + range determined by them. */ +void attribute_hidden +__reloc_range (const struct elf32_fdpic_loadmap *map, + void **p, void **e) +{ + void **old = p; + + p = __reloc_pointer (p, map); + e += p - old; + reloc_range (p, e, map); +} + +/* Remap p, adjust e by the same offset, then map pointers referenced + by the (unadjusted) pointers in the range. Return the relocated + value of the last pointer in the range. */ +void* attribute_hidden +__reloc_range_indirect (const struct elf32_fdpic_loadmap *map, + void ***p, void ***e) +{ + void ***old = p; + + p = __reloc_pointer (p, map); + e += p - old; + return reloc_range_indirect (p, e, map); +} +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/dl-iterate-phdr.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/dl-iterate-phdr.c new file mode 100644 index 00000000..144e4c14 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/dl-iterate-phdr.c @@ -0,0 +1,42 @@ +/* Copyright 2003 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation; either version 2.1 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include + +extern int weak_function +__dl_iterate_phdr (int (*callback) (struct dl_phdr_info *info, + size_t size, void *data), + void *data); + +/* Define it as a pointer, such that we get a pointer to the global + function descriptor, that won't be optimized away by the + linker. */ +static int (*ptr) (int (*callback) (struct dl_phdr_info *info, + size_t size, void *data), + void *data) = __dl_iterate_phdr; + +int +dl_iterate_phdr (int (*callback) (struct dl_phdr_info *info, + size_t size, void *data), + void *data) +{ + if (ptr) + return ptr (callback, data); + + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/fstat.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/fstat.c new file mode 100644 index 00000000..45d2746b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/fstat.c @@ -0,0 +1,17 @@ +/* + * Syscalls for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ +/* Extracted from ../common/syscalls.c by Erik Andersen + * Adapted to FR-V by Alexandre Oliva + */ + +#include +#include +#include + +_syscall2(int, fstat, int, fd, struct stat *, buf) +libc_hidden_def(fstat) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/fstat64.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/fstat64.c new file mode 100644 index 00000000..f795342f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/fstat64.c @@ -0,0 +1,19 @@ +/* + * Syscalls for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ +/* Extracted from ../common/syscalls.c by Erik Andersen + * Adapted to FR-V by Alexandre Oliva + */ + +#include +#include +#include + +#ifdef __UCLIBC_HAS_LFS__ +_syscall2(int, fstat64, int, fd, struct stat64 *, buf) +libc_hidden_def(fstat64) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/lstat.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/lstat.c new file mode 100644 index 00000000..94f722f4 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/lstat.c @@ -0,0 +1,17 @@ +/* + * Syscalls for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ +/* Extracted from ../common/syscalls.c by Erik Andersen + * Adapted to FR-V by Alexandre Oliva + */ + +#include +#include +#include + +_syscall2(int, lstat, const char *, file_name, struct stat *, buf) +libc_hidden_def(lstat) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/lstat64.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/lstat64.c new file mode 100644 index 00000000..f038fb0e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/lstat64.c @@ -0,0 +1,19 @@ +/* + * Syscalls for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ +/* Extracted from ../common/syscalls.c by Erik Andersen + * Adapted to FR-V by Alexandre Oliva + */ + +#include +#include +#include + +#ifdef __UCLIBC_HAS_LFS__ +_syscall2(int, lstat64, const char *, file_name, struct stat64 *, buf) +libc_hidden_def(lstat64) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/mmap.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/mmap.c new file mode 100644 index 00000000..cb911248 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/mmap.c @@ -0,0 +1,50 @@ +/* Copyright (C) 1997, 1998, 1999, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Daniel Jacobowitz , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Massivly hacked up for uClibc by Erik Andersen */ + +/* Extracted from ../common/mmap64.c by Alexandre Oliva + + We don't want to use the old mmap interface. */ + +#include +#include +#include +#include +#include + + +#define __NR___syscall_mmap2 __NR_mmap2 +static __inline__ _syscall6(__ptr_t, __syscall_mmap2, __ptr_t, addr, + size_t, len, int, prot, int, flags, int, fd, off_t, offset) + +/* This is always 12, even on architectures where PAGE_SHIFT != 12. */ +# ifndef MMAP2_PAGE_SHIFT +# define MMAP2_PAGE_SHIFT 12 +# endif + +__ptr_t mmap(__ptr_t addr, size_t len, int prot, int flags, int fd, __off_t offset) +{ + if (offset & ((1 << MMAP2_PAGE_SHIFT) - 1)) { + __set_errno (EINVAL); + return MAP_FAILED; + } + return(__syscall_mmap2(addr, len, prot, flags, fd, (off_t) (offset >> MMAP2_PAGE_SHIFT))); +} +libc_hidden_def(mmap) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/sbrk.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/sbrk.c new file mode 100644 index 00000000..2dc719a1 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/sbrk.c @@ -0,0 +1,25 @@ +/* From libc-5.3.12 */ + +#include +#include +#include + +extern void * __curbrk attribute_hidden; +extern int __init_brk (void) attribute_hidden; +extern void *_brk(void *ptr) attribute_hidden; + +void * +sbrk(intptr_t increment) +{ + if (__init_brk () == 0) + { + char * tmp = (char*)__curbrk+increment; + __curbrk = _brk(tmp); + if (__curbrk == tmp) + return tmp-increment; + __set_errno(ENOMEM); + return ((void *) -1); + } + return ((void *) -1); +} +libc_hidden_def(sbrk) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/setjmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/setjmp.S new file mode 100644 index 00000000..66008d12 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/setjmp.S @@ -0,0 +1,90 @@ + .text + +/* This just does a tail-call to `__sigsetjmp (ARG, 0)'. + We cannot do it in C because it must be a tail-call, so frame-unwinding + in setjmp doesn't clobber the state restored by longjmp. */ + + .global _setjmp + .type _setjmp,@function +_setjmp: + setlos #0, gr9 + bra .Lsigsetjmp_intern + .size _setjmp,.-_setjmp + +/* This just does a tail-call to `__sigsetjmp (ARG, 1)'. + We cannot do it in C because it must be a tail-call, so frame-unwinding + in setjmp doesn't clobber the state restored by longjmp. */ + + .align 4 + .type setjmp,@function + .globl setjmp +setjmp: + setlos #1, gr9 + bra .Lsigsetjmp_intern + .size setjmp,.-setjmp + +# setjmp/longjmp for Frv. The jmpbuf looks like this: +# +# Register jmpbuf offset +# R16-R31 0x0-0x03c +# R48-R63 0x40-0x7c +# FR16-FR31 0x80-0xbc +# FR48-FR63 0xc0-0xfc +# LR 0x100 +# SP 0x104 +# FP 0x108 + + .global __sigsetjmp + .type __sigsetjmp,@function +__sigsetjmp: +.Lsigsetjmp_intern: + stdi gr16, @(gr8,0) + stdi gr18, @(gr8,8) + stdi gr20, @(gr8,16) + stdi gr22, @(gr8,24) + stdi gr24, @(gr8,32) + stdi gr26, @(gr8,40) + stdi gr28, @(gr8,48) + stdi gr30, @(gr8,56) +#if __FRV_GPR__ != 32 + stdi gr48, @(gr8,64) + stdi gr50, @(gr8,72) + stdi gr52, @(gr8,80) + stdi gr54, @(gr8,88) + stdi gr56, @(gr8,96) + stdi gr58, @(gr8,104) + stdi gr60, @(gr8,112) + stdi gr62, @(gr8,120) +#endif + +#if __FRV_FPR__ != 0 + stdfi fr16, @(gr8,128) + stdfi fr18, @(gr8,136) + stdfi fr20, @(gr8,144) + stdfi fr22, @(gr8,152) + stdfi fr24, @(gr8,160) + stdfi fr26, @(gr8,168) + stdfi fr28, @(gr8,176) + stdfi fr30, @(gr8,184) +#if __FRV_FPR__ != 32 + stdfi fr48, @(gr8,192) + stdfi fr50, @(gr8,200) + stdfi fr52, @(gr8,208) + stdfi fr54, @(gr8,216) + stdfi fr56, @(gr8,224) + stdfi fr58, @(gr8,232) + stdfi fr60, @(gr8,240) + stdfi fr62, @(gr8,248) +#endif +#endif + + movsg lr, gr4 + sti gr4, @(gr8,256) + sti sp, @(gr8,260) + sti fp, @(gr8,264) + + sethi.p #gotofffuncdeschi(__sigjmp_save), gr4 + setlo #gotofffuncdesclo(__sigjmp_save), gr4 + ldd @(gr15, gr4), gr14 + jmpl @(gr14, gr0) + .size __sigsetjmp,.-__sigsetjmp diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/stat.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/stat.c new file mode 100644 index 00000000..74e31007 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/stat.c @@ -0,0 +1,17 @@ +/* + * Syscalls for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ +/* Extracted from ../common/syscalls.c by Erik Andersen + * Adapted to FR-V by Alexandre Oliva + */ + +#include +#include +#include + +_syscall2(int, stat, const char *, file_name, struct stat *, buf) +libc_hidden_def(stat) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/stat64.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/stat64.c new file mode 100644 index 00000000..675e6349 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/stat64.c @@ -0,0 +1,19 @@ +/* + * Syscalls for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ +/* Extracted from ../common/syscalls.c by Erik Andersen + * Adapted to FR-V by Alexandre Oliva + */ + +#include +#include +#include + +#ifdef __UCLIBC_HAS_LFS__ +_syscall2(int, stat64, const char *, file_name, struct stat64 *, buf) +libc_hidden_def(stat64) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/sys/procfs.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/sys/procfs.h new file mode 100644 index 00000000..f0752334 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/sys/procfs.h @@ -0,0 +1,125 @@ +/* Copyright (C) 1996, 1997, 1999, 2000, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_PROCFS_H +#define _SYS_PROCFS_H 1 + +/* This is somewhat modelled after the file of the same name on SVR4 + systems. It provides a definition of the core file format for ELF + used on Linux. It doesn't have anything to do with the /proc file + system, even though Linux has one. + + Anyway, the whole purpose of this file is for GDB and GDB only. + Don't read too much into it. Don't use it for anything other than + GDB unless you know what you are doing. */ + +#include +#include +#include +#include + +__BEGIN_DECLS + +/* Type for a general-purpose register. */ +typedef unsigned long elf_greg_t; + +/* And the whole bunch of them. We could have used `struct + user_regs_struct' directly in the typedef, but tradition says that + the register set is an array, which does have some peculiar + semantics, so leave it that way. */ +#define ELF_NGREG (sizeof (struct user_int_regs) / sizeof(elf_greg_t)) +typedef elf_greg_t elf_gregset_t[ELF_NGREG]; + +/* Register set for the floating-point registers. */ +typedef struct user_fpmedia_regs elf_fpregset_t; + +/* Signal info. */ +struct elf_siginfo + { + int si_signo; /* Signal number. */ + int si_code; /* Extra code. */ + int si_errno; /* Errno. */ + }; + + +/* Definitions to generate Intel SVR4-like core files. These mostly + have the same names as the SVR4 types with "elf_" tacked on the + front to prevent clashes with Linux definitions, and the typedef + forms have been avoided. This is mostly like the SVR4 structure, + but more Linuxy, with things that Linux does not support and which + GDB doesn't really use excluded. */ + +struct elf_prstatus + { + struct elf_siginfo pr_info; /* Info associated with signal. */ + short int pr_cursig; /* Current signal. */ + unsigned long int pr_sigpend; /* Set of pending signals. */ + unsigned long int pr_sighold; /* Set of held signals. */ + __pid_t pr_pid; + __pid_t pr_ppid; + __pid_t pr_pgrp; + __pid_t pr_sid; + struct timeval pr_utime; /* User time. */ + struct timeval pr_stime; /* System time. */ + struct timeval pr_cutime; /* Cumulative user time. */ + struct timeval pr_cstime; /* Cumulative system time. */ + elf_gregset_t pr_reg; /* GP registers. */ + int pr_fpvalid; /* True if math copro being used. */ + }; + + +#define ELF_PRARGSZ (80) /* Number of chars for args. */ + +struct elf_prpsinfo + { + char pr_state; /* Numeric process state. */ + char pr_sname; /* Char for pr_state. */ + char pr_zomb; /* Zombie. */ + char pr_nice; /* Nice val. */ + unsigned long int pr_flag; /* Flags. */ + unsigned short int pr_uid; + unsigned short int pr_gid; + int pr_pid, pr_ppid, pr_pgrp, pr_sid; + /* Lots missing */ + char pr_fname[16]; /* Filename of executable. */ + char pr_psargs[ELF_PRARGSZ]; /* Initial part of arg list. */ + }; + + +/* The rest of this file provides the types for emulation of the + Solaris interfaces that should be implemented by + users of libthread_db. */ + +/* Addresses. */ +typedef void *psaddr_t; + +/* Register sets. Linux has different names. */ +typedef elf_gregset_t prgregset_t; +typedef elf_fpregset_t prfpregset_t; + +/* We don't have any differences between processes and threads, + therefore have only one PID type. */ +typedef __pid_t lwpid_t; + +/* Process status and info. In the end we do provide typedefs for them. */ +typedef struct elf_prstatus prstatus_t; +typedef struct elf_prpsinfo prpsinfo_t; + +__END_DECLS + +#endif /* sys/procfs.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/sys/ptrace.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/sys/ptrace.h new file mode 100644 index 00000000..6b0eca7b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/sys/ptrace.h @@ -0,0 +1,139 @@ +/* `ptrace' debugger support interface. FRV-Linux version. + Copyright (C) 1996, 1997, 1998, 1999, 2000, 2004 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_PTRACE_H +#define _SYS_PTRACE_H 1 + +#include + +__BEGIN_DECLS + +/* Type of the REQUEST argument to `ptrace.' */ +enum __ptrace_request +{ + /* Indicate that the process making this request should be traced. + All signals received by this process can be intercepted by its + parent, and its parent can use the other `ptrace' requests. */ + PTRACE_TRACEME = 0, +#define PT_TRACE_ME PTRACE_TRACEME + + /* Return the word in the process's text space at address ADDR. */ + PTRACE_PEEKTEXT = 1, +#define PT_READ_I PTRACE_PEEKTEXT + + /* Return the word in the process's data space at address ADDR. */ + PTRACE_PEEKDATA = 2, +#define PT_READ_D PTRACE_PEEKDATA + + /* Return the word in the process's user area at offset ADDR. */ + PTRACE_PEEKUSER = 3, +#define PT_READ_U PTRACE_PEEKUSER + + /* Write the word DATA into the process's text space at address ADDR. */ + PTRACE_POKETEXT = 4, +#define PT_WRITE_I PTRACE_POKETEXT + + /* Write the word DATA into the process's data space at address ADDR. */ + PTRACE_POKEDATA = 5, +#define PT_WRITE_D PTRACE_POKEDATA + + /* Write the word DATA into the process's user area at offset ADDR. */ + PTRACE_POKEUSER = 6, +#define PT_WRITE_U PTRACE_POKEUSER + + /* Continue the process. */ + PTRACE_CONT = 7, +#define PT_CONTINUE PTRACE_CONT + + /* Kill the process. */ + PTRACE_KILL = 8, +#define PT_KILL PTRACE_KILL + + /* Single step the process. + This is not supported on all machines. */ + PTRACE_SINGLESTEP = 9, +#define PT_STEP PTRACE_SINGLESTEP + + /* Get all general purpose registers used by a processes. + This is not supported on all machines. */ + PTRACE_GETREGS = 12, +#define PT_GETREGS PTRACE_GETREGS + + /* Set all general purpose registers used by a processes. + This is not supported on all machines. */ + PTRACE_SETREGS = 13, +#define PT_SETREGS PTRACE_SETREGS + + /* Get all floating point registers used by a processes. + This is not supported on all machines. */ + PTRACE_GETFPREGS = 14, +#define PT_GETFPREGS PTRACE_GETFPREGS + + /* Set all floating point registers used by a processes. + This is not supported on all machines. */ + PTRACE_SETFPREGS = 15, +#define PT_SETFPREGS PTRACE_SETFPREGS + + /* Attach to a process that is already running. */ + PTRACE_ATTACH = 16, +#define PT_ATTACH PTRACE_ATTACH + + /* Detach from a process attached to with PTRACE_ATTACH. */ + PTRACE_DETACH = 17, +#define PT_DETACH PTRACE_DETACH + + /* Get all extended floating point registers used by a processes. + This is not supported on all machines. */ + PTRACE_GETFPXREGS = 18, +#define PT_GETFPXREGS PTRACE_GETFPXREGS + + /* Set all extended floating point registers used by a processes. + This is not supported on all machines. */ + PTRACE_SETFPXREGS = 19, +#define PT_SETFPXREGS PTRACE_SETFPXREGS + + /* Continue and stop at the next (return from) syscall. */ + PTRACE_SYSCALL = 24, +#define PT_SYSCALL PTRACE_SYSCALL + + /* Obtain the load map of the main program or the interpreter of the + ptraced process, depending on whether the addr argument is + (void*)0 or (void*)1, respectively. */ + PTRACE_GETFDPIC = 31 +#define PT_GETFDPIC PTRACE_GETFDPIC +}; + +#define PTRACE_GETFDPIC_EXEC ((void*)0) /* [addr] request the executable loadmap */ +#define PTRACE_GETFDPIC_INTERP ((void*)1) /* [addr] request the interpreter loadmap */ + +/* Perform process tracing functions. REQUEST is one of the values + above, and determines the action to be taken. + For all requests except PTRACE_TRACEME, PID specifies the process to be + traced. + + PID and the other arguments described above for the various requests should + appear (those that are used for the particular request) as: + pid_t PID, void *ADDR, int DATA, void *ADDR2 + after REQUEST. */ +extern long int ptrace (enum __ptrace_request __request, ...) __THROW; + +__END_DECLS + +#endif /* _SYS_PTRACE_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/sys/ucontext.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/sys/ucontext.h new file mode 100644 index 00000000..487c9ee0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/sys/ucontext.h @@ -0,0 +1,451 @@ +/* Copyright (C) 1999, 2000, 2001, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _SYS_UCONTEXT_H +#define _SYS_UCONTEXT_H 1 + +#include +#include + +/* We need the signal context definitions even if they are not used + included in . */ +#include + + +typedef unsigned long greg_t; + +/* Number of general registers. */ +#define NGREG (10+2+64) + +/* Container for all general registers. */ +typedef greg_t gregset_t[NGREG]; + +#ifdef __USE_GNU +/* Number of each register is the `gregset_t' array. */ +enum +{ + REG_PSR = 0, +#define REG_PSR REG_PSR + REG_ISR = 1, +#define REG_ISR REG_ISR + REG_CCR = 2, +#define REG_CCR REG_CCR + REG_CCCR = 3, +#define REG_CCCR REG_CCCR + REG_LR = 4, +#define REG_LR REG_LR + REG_LCR = 5, +#define REG_LCR REG_LCR + REG_PC = 6, +#define REG_PC REG_PC + REG___STATUS = 7, +#define REG___STATUS REG___STATUS + REG_SYSCALLNO = 8, +#define REG_SYSCALLNO REG_SYSCALLNO + REG_ORIG_GR8 = 9, +#define REG_ORIG_GR8 REG_ORIG_GR8 + REG_GNER0 = 10, +#define REG_GNER0 REG_GNER0 + REG_GNER1 = 11, +#define REG_GNER1 REG_GNER1 + REG_GR0 = 12, +#define REG_GR0 REG_GR0 + REG_GR1 = 13, +#define REG_GR1 REG_GR1 + REG_GR2 = 14, +#define REG_GR2 REG_GR2 + REG_GR3 = 15, +#define REG_GR3 REG_GR3 + REG_GR4 = 16, +#define REG_GR4 REG_GR4 + REG_GR5 = 17, +#define REG_GR5 REG_GR5 + REG_GR6 = 18, +#define REG_GR6 REG_GR6 + REG_GR7 = 19, +#define REG_GR7 REG_GR7 + REG_GR8 = 20, +#define REG_GR8 REG_GR8 + REG_GR9 = 21, +#define REG_GR9 REG_GR9 + REG_GR10 = 22, +#define REG_GR10 REG_GR10 + REG_GR11 = 23, +#define REG_GR11 REG_GR11 + REG_GR12 = 24, +#define REG_GR12 REG_GR12 + REG_GR13 = 25, +#define REG_GR13 REG_GR13 + REG_GR14 = 26, +#define REG_GR14 REG_GR14 + REG_GR15 = 27, +#define REG_GR15 REG_GR15 + REG_GR16 = 28, +#define REG_GR16 REG_GR16 + REG_GR17 = 29, +#define REG_GR17 REG_GR17 + REG_GR18 = 30, +#define REG_GR18 REG_GR18 + REG_GR19 = 31, +#define REG_GR19 REG_GR19 + REG_GR20 = 32, +#define REG_GR20 REG_GR20 + REG_GR21 = 33, +#define REG_GR21 REG_GR21 + REG_GR22 = 34, +#define REG_GR22 REG_GR22 + REG_GR23 = 35, +#define REG_GR23 REG_GR23 + REG_GR24 = 36, +#define REG_GR24 REG_GR24 + REG_GR25 = 37, +#define REG_GR25 REG_GR25 + REG_GR26 = 38, +#define REG_GR26 REG_GR26 + REG_GR27 = 39, +#define REG_GR27 REG_GR27 + REG_GR28 = 40, +#define REG_GR28 REG_GR28 + REG_GR29 = 41, +#define REG_GR29 REG_GR29 + REG_GR30 = 42, +#define REG_GR30 REG_GR30 + REG_GR31 = 43, +#define REG_GR31 REG_GR31 + REG_GR32 = 44, +#define REG_GR32 REG_GR32 + REG_GR33 = 45, +#define REG_GR33 REG_GR33 + REG_GR34 = 46, +#define REG_GR34 REG_GR34 + REG_GR35 = 47, +#define REG_GR35 REG_GR35 + REG_GR36 = 48, +#define REG_GR36 REG_GR36 + REG_GR37 = 49, +#define REG_GR37 REG_GR37 + REG_GR38 = 50, +#define REG_GR38 REG_GR38 + REG_GR39 = 51, +#define REG_GR39 REG_GR39 + REG_GR40 = 52, +#define REG_GR40 REG_GR40 + REG_GR41 = 53, +#define REG_GR41 REG_GR41 + REG_GR42 = 54, +#define REG_GR42 REG_GR42 + REG_GR43 = 55, +#define REG_GR43 REG_GR43 + REG_GR44 = 56, +#define REG_GR44 REG_GR44 + REG_GR45 = 57, +#define REG_GR45 REG_GR45 + REG_GR46 = 58, +#define REG_GR46 REG_GR46 + REG_GR47 = 59, +#define REG_GR47 REG_GR47 + REG_GR48 = 60, +#define REG_GR48 REG_GR48 + REG_GR49 = 61, +#define REG_GR49 REG_GR49 + REG_GR50 = 62, +#define REG_GR50 REG_GR50 + REG_GR51 = 63, +#define REG_GR51 REG_GR51 + REG_GR52 = 64, +#define REG_GR52 REG_GR52 + REG_GR53 = 65, +#define REG_GR53 REG_GR53 + REG_GR54 = 66, +#define REG_GR54 REG_GR54 + REG_GR55 = 67, +#define REG_GR55 REG_GR55 + REG_GR56 = 68, +#define REG_GR56 REG_GR56 + REG_GR57 = 69, +#define REG_GR57 REG_GR57 + REG_GR58 = 70, +#define REG_GR58 REG_GR58 + REG_GR59 = 71, +#define REG_GR59 REG_GR59 + REG_GR60 = 72, +#define REG_GR60 REG_GR60 + REG_GR61 = 73, +#define REG_GR61 REG_GR61 + REG_GR62 = 74, +#define REG_GR62 REG_GR62 + REG_GR63 = 75, +#define REG_GR63 REG_GR63 +}; +#endif + +typedef unsigned long freg_t; + +/* Number of FPU registers. */ +#define NFPREG (64+2+2+8+2+1) + +#ifdef __USE_GNU +/* Number of each register is the `gregset_t' array. */ +enum +{ + REG_FR0 = 0, +#define REG_FR0 REG_FR0 + REG_FR1 = 1, +#define REG_FR1 REG_FR1 + REG_FR2 = 2, +#define REG_FR2 REG_FR2 + REG_FR3 = 3, +#define REG_FR3 REG_FR3 + REG_FR4 = 4, +#define REG_FR4 REG_FR4 + REG_FR5 = 5, +#define REG_FR5 REG_FR5 + REG_FR6 = 6, +#define REG_FR6 REG_FR6 + REG_FR7 = 7, +#define REG_FR7 REG_FR7 + REG_FR8 = 8, +#define REG_FR8 REG_FR8 + REG_FR9 = 9, +#define REG_FR9 REG_FR9 + REG_FR10 = 10, +#define REG_FR10 REG_FR10 + REG_FR11 = 11, +#define REG_FR11 REG_FR11 + REG_FR12 = 12, +#define REG_FR12 REG_FR12 + REG_FR13 = 13, +#define REG_FR13 REG_FR13 + REG_FR14 = 14, +#define REG_FR14 REG_FR14 + REG_FR15 = 15, +#define REG_FR15 REG_FR15 + REG_FR16 = 16, +#define REG_FR16 REG_FR16 + REG_FR17 = 17, +#define REG_FR17 REG_FR17 + REG_FR18 = 18, +#define REG_FR18 REG_FR18 + REG_FR19 = 19, +#define REG_FR19 REG_FR19 + REG_FR20 = 20, +#define REG_FR20 REG_FR20 + REG_FR21 = 21, +#define REG_FR21 REG_FR21 + REG_FR22 = 22, +#define REG_FR22 REG_FR22 + REG_FR23 = 23, +#define REG_FR23 REG_FR23 + REG_FR24 = 24, +#define REG_FR24 REG_FR24 + REG_FR25 = 25, +#define REG_FR25 REG_FR25 + REG_FR26 = 26, +#define REG_FR26 REG_FR26 + REG_FR27 = 27, +#define REG_FR27 REG_FR27 + REG_FR28 = 28, +#define REG_FR28 REG_FR28 + REG_FR29 = 29, +#define REG_FR29 REG_FR29 + REG_FR30 = 30, +#define REG_FR30 REG_FR30 + REG_FR31 = 31, +#define REG_FR31 REG_FR31 + REG_FR32 = 32, +#define REG_FR32 REG_FR32 + REG_FR33 = 33, +#define REG_FR33 REG_FR33 + REG_FR34 = 34, +#define REG_FR34 REG_FR34 + REG_FR35 = 35, +#define REG_FR35 REG_FR35 + REG_FR36 = 36, +#define REG_FR36 REG_FR36 + REG_FR37 = 37, +#define REG_FR37 REG_FR37 + REG_FR38 = 38, +#define REG_FR38 REG_FR38 + REG_FR39 = 39, +#define REG_FR39 REG_FR39 + REG_FR40 = 40, +#define REG_FR40 REG_FR40 + REG_FR41 = 41, +#define REG_FR41 REG_FR41 + REG_FR42 = 42, +#define REG_FR42 REG_FR42 + REG_FR43 = 43, +#define REG_FR43 REG_FR43 + REG_FR44 = 44, +#define REG_FR44 REG_FR44 + REG_FR45 = 45, +#define REG_FR45 REG_FR45 + REG_FR46 = 46, +#define REG_FR46 REG_FR46 + REG_FR47 = 47, +#define REG_FR47 REG_FR47 + REG_FR48 = 48, +#define REG_FR48 REG_FR48 + REG_FR49 = 49, +#define REG_FR49 REG_FR49 + REG_FR50 = 50, +#define REG_FR50 REG_FR50 + REG_FR51 = 51, +#define REG_FR51 REG_FR51 + REG_FR52 = 52, +#define REG_FR52 REG_FR52 + REG_FR53 = 53, +#define REG_FR53 REG_FR53 + REG_FR54 = 54, +#define REG_FR54 REG_FR54 + REG_FR55 = 55, +#define REG_FR55 REG_FR55 + REG_FR56 = 56, +#define REG_FR56 REG_FR56 + REG_FR57 = 57, +#define REG_FR57 REG_FR57 + REG_FR58 = 58, +#define REG_FR58 REG_FR58 + REG_FR59 = 59, +#define REG_FR59 REG_FR59 + REG_FR60 = 60, +#define REG_FR60 REG_FR60 + REG_FR61 = 61, +#define REG_FR61 REG_FR61 + REG_FR62 = 62, +#define REG_FR62 REG_FR62 + REG_FR63 = 63, +#define REG_FR63 REG_FR63 + REG_FNER0 = 64, +#define REG_FNER0 REG_FNER0 + REG_FNER1 = 65, +#define REG_FNER1 REG_FNER1 + REG_MSR0 = 66, +#define REG_MSR0 REG_MSR0 + REG_MSR1 = 67, +#define REG_MSR1 REG_MSR1 + REG_ACC0 = 68, +#define REG_ACC0 REG_ACC0 + REG_ACC1 = 69, +#define REG_ACC1 REG_ACC1 + REG_ACC2 = 70, +#define REG_ACC2 REG_ACC2 + REG_ACC3 = 71, +#define REG_ACC3 REG_ACC3 + REG_ACC4 = 72, +#define REG_ACC4 REG_ACC4 + REG_ACC5 = 73, +#define REG_ACC5 REG_ACC5 + REG_ACC6 = 74, +#define REG_ACC6 REG_ACC6 + REG_ACC7 = 75, +#define REG_ACC7 REG_ACC7 + REG_ACCG0123 = 76, +#define REG_ACCG0123 REG_ACCG0123 + REG_ACCG4567 = 77, +#define REG_ACCG4567 REG_ACCG4567 + REG_FSR0 = 78, +#define REG_FSR0 REG_FSR0 +}; +#endif + +/* Structure to describe FPU registers. */ +typedef freg_t fpregset_t[NFPREG]; + +/* Context to describe whole processor state. */ +typedef struct + { + gregset_t gregs; + fpregset_t fpregs; + void *extension; + unsigned long sc_oldmask; /* old sigmask */ + } __attribute__((aligned(8))) mcontext_t; + +#ifdef __USE_GNU +struct kernel_user_int_regs +{ + /* integer registers + * - up to gr[31] mirror pt_regs in the kernel + */ + unsigned long psr; /* Processor Status Register */ + unsigned long isr; /* Integer Status Register */ + unsigned long ccr; /* Condition Code Register */ + unsigned long cccr; /* Condition Code for Conditional Insns Register */ + unsigned long lr; /* Link Register */ + unsigned long lcr; /* Loop Count Register */ + unsigned long pc; /* Program Counter Register */ + unsigned long __status; /* exception status */ + unsigned long syscallno; /* syscall number or -1 */ + unsigned long orig_gr8; /* original syscall arg #1 */ + unsigned long gner[2]; + + union { + unsigned long tbr; + unsigned long gr[64]; + }; +}; + +struct kernel_user_fpmedia_regs +{ + /* FP/Media registers */ + unsigned long fr[64]; + unsigned long fner[2]; + unsigned long msr[2]; + unsigned long acc[8]; + unsigned char accg[8]; + unsigned long fsr[1]; +}; + +struct kernel_user_context +{ + struct kernel_user_int_regs i; + struct kernel_user_fpmedia_regs f; + + /* we provide a context extension so that we can save the regs for CPUs that + * implement many more of Fujitsu's lavish register spec + */ + void *extension; + + /* This is not part of the kernel's struct user_context, but + rather of the enclosing struct sigcontext, but we add it + here to parallel mcontext_t, just for completeness. */ + unsigned long sc_oldmask; /* old sigmask */ +} __attribute__((aligned(8))); + +/* This union enables alias-safe casts from mcontext_t* to the union + type, that can then be dereferenced as_aliases. */ +union kmcontext_t +{ + mcontext_t as_regsets; + /* as_aliases is actually missing sc_oldmask, that is present in + mcontext_t. */ + struct kernel_user_context as_aliases; +}; +#endif + +/* Userlevel context. */ +typedef struct ucontext + { + unsigned long int uc_flags; + struct ucontext *uc_link; + stack_t uc_stack; + mcontext_t uc_mcontext; + __sigset_t uc_sigmask; + } ucontext_t; + +#endif /* sys/ucontext.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/syscall.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/syscall.c new file mode 100644 index 00000000..7b416e87 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/syscall.c @@ -0,0 +1,41 @@ +/* syscall for frv/uClibc + * + * Copyright (C) 2004 by Alexandre Oliva + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License + * for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include + + +long syscall(long sysnum, long arg1, long arg2, long arg3, + long arg4, long arg5, long arg6) +{ + register unsigned long __scnum __asm__ ("gr7") = (sysnum); + register unsigned long __sc0 __asm__ ("gr8") = (unsigned long) (arg1); + register unsigned long __sc1 __asm__ ("gr9") = (unsigned long) (arg2); + register unsigned long __sc2 __asm__ ("gr10") = (unsigned long) (arg3); + register unsigned long __sc3 __asm__ ("gr11") = (unsigned long) (arg4); + register unsigned long __sc4 __asm__ ("gr12") = (unsigned long) (arg5); + register unsigned long __sc5 __asm__ ("gr13") = (unsigned long) (arg6); + __asm__ __volatile__ ("tra gr0,gr0" + : "+r" (__sc0) + : "r" (__scnum), "r" (__sc1), "r" (__sc2), + "r" (__sc3), "r" (__sc4), "r" (__sc5)); + __syscall_return(long,__sc0); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/sysdep.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/sysdep.c new file mode 100644 index 00000000..7387d116 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/sysdep.c @@ -0,0 +1,27 @@ +/* Copyright (C) 1997, 1998, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +/* This routine is jumped to by all the syscall handlers, to stash + an error number into errno. */ +int __syscall_error (int err_no) +{ + __set_errno (-err_no); + return -1; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/vfork.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/vfork.S new file mode 100644 index 00000000..8935a12f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/vfork.S @@ -0,0 +1,47 @@ +/* Copyright (C) 2003, 2004 Free Software Foudnation, Inc. + This file is part of the GNU C Library. + Contributed by David Howells , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#include +#define _ERRNO_H 1 +#include + + .text + .globl __vfork + .hidden __vfork + .type __vfork,@function +/* int vfork(void) */ +__vfork: + setlos.p #__NR_vfork, gr7 + setlos #-4096, gr4 + tra gr0, gr0 + + cmp gr8, gr4, icc0 + blslr icc0, #2 + + sethi.p #gotofffuncdeschi(__syscall_error), gr14 + setlo #gotofffuncdesclo(__syscall_error), gr14 + ldd @(gr14, gr15), gr14 + jmpl @(gr14, gr0) + + .size __vfork,.-__vfork + +weak_alias(__vfork,vfork) +libc_hidden_weak(vfork) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/xstatconv.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/xstatconv.c new file mode 100644 index 00000000..d7948c07 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/frv/xstatconv.c @@ -0,0 +1 @@ +/* We don't need any of this. */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/Makefile new file mode 100644 index 00000000..2ab4ee6f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/Makefile @@ -0,0 +1,65 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2006 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + +TOPDIR=../../../../ +include $(TOPDIR)Rules.mak +ifeq ($(DOPIC),y) +# is this not provided by gcc ? +ASFLAGS+=-D__PIC__ +endif + +#FIXME -- this arch should include its own crti.S and crtn.S +UCLIBC_CTOR_DTOR=n + +CRT_SRC := crt0.S +CRT_OBJ := crt0.o crt1.o +CTOR_TARGETS := $(TOPDIR)lib/crti.o $(TOPDIR)lib/crtn.o + +SSRC := __longjmp.S bsd-_setjmp.S bsd-setjmp.S clone.S setjmp.S vfork.S +SOBJ := $(patsubst %.S,%.o, $(SSRC)) + +CSRC := ptrace.c brk.c +COBJ := $(patsubst %.c,%.o, $(CSRC)) + +OBJS := $(SOBJ) $(COBJ) + +OBJ_LIST := ../../../obj.sysdeps.$(TARGET_ARCH) + +all: $(OBJ_LIST) $(CTOR_TARGETS) + +$(OBJ_LIST): $(OBJS) $(CRT_OBJ) + $(STRIPTOOL) -x -R .note -R .comment $^ + $(INSTALL) -d $(TOPDIR)lib/ + cp $(CRT_OBJ) $(TOPDIR)lib/ + echo $(patsubst %, sysdeps/linux/$(TARGET_ARCH)/%, $(OBJS)) > $@ + +$(CRT_OBJ): $(CRT_SRC) + $(CC) $(ASFLAGS) -DL_$* $< -c -o $*.o + +$(SOBJ): %.o : %.S + $(CC) $(ASFLAGS) -c $< -o $@ + +$(COBJ): %.o : %.c + $(CC) $(CFLAGS) -c $< -o $@ + +ifeq ($(UCLIBC_CTOR_DTOR),y) +$(TOPDIR)lib/crti.o: crti.S + $(INSTALL) -d $(TOPDIR)lib/ + $(CC) $(ASFLAGS) $(SSP_DISABLE_FLAGS) -c $< -o $@ + +$(TOPDIR)lib/crtn.o: crtn.S + $(INSTALL) -d $(TOPDIR)lib/ + $(CC) $(ASFLAGS) $(SSP_DISABLE_FLAGS) -c $< -o $@ +else +$(CTOR_TARGETS): + $(INSTALL) -d $(TOPDIR)lib/ + $(AR) $(ARFLAGS) $@ +endif + +headers: + +clean: + $(RM) *.o *~ core diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/__longjmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/__longjmp.S new file mode 100644 index 00000000..5cffa3e5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/__longjmp.S @@ -0,0 +1,22 @@ +#ifdef __H8300S__ + .h8300s +#else + .h8300h +#endif + .text + +.global ___longjmp + +___longjmp: + mov.l er1,er1 + bne 1f + sub.l er1,er1 + inc.l #1,er1 +1: + mov.l @er0+,er4 + mov.l @er0+,er5 + mov.l @er0+,er6 + mov.l @er0+,sp + mov.l @er0+,er3 ; return PC + adds #4,sp ; adjust return stack + jmp @er3 diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/bits/byteswap.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/bits/byteswap.h new file mode 100644 index 00000000..781a4dbf --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/bits/byteswap.h @@ -0,0 +1,40 @@ +/* Macros to swap the order of bytes in integer values. H8/300 version. + Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _ASM_BITS_BYTESWAP_H +#define _ASM_BITS_BYTESWAP_H 1 + +#define __bswap_non_constant_32(x) \ + __extension__ \ + ({ unsigned int __v; \ + __asm__ __volatile__ ("mov.l %0,er0\n\t" \ + "mov.b r0l,r1h\n\t" \ + "mov.b r0h,r1l\n\t" \ + "mov.w r1,e1\n\t" \ + "mov.w e0,r0\n\t" \ + "mov.b r0l,r1h\n\t" \ + "mov.b r0h,r1l\n\t" \ + "mov.l er1,%0" \ + : "=d" (__v) \ + : "0" (x): "er0","er1"); \ + __v; }) + +#endif + +#include diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/bits/endian.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/bits/endian.h new file mode 100644 index 00000000..383918d6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/bits/endian.h @@ -0,0 +1,7 @@ +/* H8/300 is big-endian. */ + +#ifndef _ENDIAN_H +# error "Never use directly; include instead." +#endif + +#define __BYTE_ORDER __BIG_ENDIAN diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/bits/fcntl.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/bits/fcntl.h new file mode 100644 index 00000000..c8aeb919 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/bits/fcntl.h @@ -0,0 +1,233 @@ +/* O_*, F_*, FD_* bit values for Linux. + Copyright (C) 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FCNTL_H +# error "Never use directly; include instead." +#endif + + +#include + +/* open/fcntl - O_SYNC is only implemented on blocks devices and on files + located on an ext2 file system */ +#define O_ACCMODE 0003 +#define O_RDONLY 00 +#define O_WRONLY 01 +#define O_RDWR 02 +#define O_CREAT 0100 /* not fcntl */ +#define O_EXCL 0200 /* not fcntl */ +#define O_NOCTTY 0400 /* not fcntl */ +#define O_TRUNC 01000 /* not fcntl */ +#define O_APPEND 02000 +#define O_NONBLOCK 04000 +#define O_NDELAY O_NONBLOCK +#define O_SYNC 010000 +#define O_FSYNC O_SYNC +#define O_ASYNC 020000 + +#ifdef __USE_GNU +# define O_DIRECTORY 040000 /* Must be a directory. */ +# define O_NOFOLLOW 0100000 /* Do not follow links. */ +# define O_DIRECT 0200000 /* Direct disk access. */ +#endif + +/* For now Linux has synchronisity options for data and read operations. + We define the symbols here but let them do the same as O_SYNC since + this is a superset. */ +#if defined __USE_POSIX199309 || defined __USE_UNIX98 +# define O_DSYNC O_SYNC /* Synchronize data. */ +# define O_RSYNC O_SYNC /* Synchronize read operations. */ +#endif + +#ifdef __USE_LARGEFILE64 +# define O_LARGEFILE 0400000 +#endif + +/* Values for the second argument to `fcntl'. */ +#define F_DUPFD 0 /* Duplicate file descriptor. */ +#define F_GETFD 1 /* Get file descriptor flags. */ +#define F_SETFD 2 /* Set file descriptor flags. */ +#define F_GETFL 3 /* Get file status flags. */ +#define F_SETFL 4 /* Set file status flags. */ +#ifndef __USE_FILE_OFFSET64 +# define F_GETLK 5 /* Get record locking info. */ +# define F_SETLK 6 /* Set record locking info (non-blocking). */ +# define F_SETLKW 7 /* Set record locking info (blocking). */ +#else +# define F_GETLK F_GETLK64 /* Get record locking info. */ +# define F_SETLK F_SETLK64 /* Set record locking info (non-blocking).*/ +# define F_SETLKW F_SETLKW64 /* Set record locking info (blocking). */ +#endif +#define F_GETLK64 12 /* Get record locking info. */ +#define F_SETLK64 13 /* Set record locking info (non-blocking). */ +#define F_SETLKW64 14 /* Set record locking info (blocking). */ + +#if defined __USE_BSD || defined __USE_XOPEN2K +# define F_SETOWN 8 /* Get owner of socket (receiver of SIGIO). */ +# define F_GETOWN 9 /* Set owner of socket (receiver of SIGIO). */ +#endif + +#ifdef __USE_GNU +# define F_SETSIG 10 /* Set number of signal to be sent. */ +# define F_GETSIG 11 /* Get number of signal to be sent. */ +#endif + +#ifdef __USE_GNU +# define F_SETLEASE 1024 /* Set a lease. */ +# define F_GETLEASE 1025 /* Enquire what lease is active. */ +# define F_NOTIFY 1026 /* Request notfications on a directory. */ +# define F_DUPFD_CLOEXEC 1030 /* Duplicate file descriptor with + close-on-exit set on new fd. */ +#endif + +/* For F_[GET|SET]FL. */ +#define FD_CLOEXEC 1 /* actually anything with low bit set goes */ + +/* For posix fcntl() and `l_type' field of a `struct flock' for lockf(). */ +#define F_RDLCK 0 /* Read lock. */ +#define F_WRLCK 1 /* Write lock. */ +#define F_UNLCK 2 /* Remove lock. */ + +/* For old implementation of bsd flock(). */ +#define F_EXLCK 4 /* or 3 */ +#define F_SHLCK 8 /* or 4 */ + +#ifdef __USE_BSD +/* Operations for bsd flock(), also used by the kernel implementation. */ +# define LOCK_SH 1 /* shared lock */ +# define LOCK_EX 2 /* exclusive lock */ +# define LOCK_NB 4 /* or'd with one of the above to prevent + blocking */ +# define LOCK_UN 8 /* remove lock */ +#endif + +#ifdef __USE_GNU +# define LOCK_MAND 32 /* This is a mandatory flock: */ +# define LOCK_READ 64 /* ... which allows concurrent read operations. */ +# define LOCK_WRITE 128 /* ... which allows concurrent write operations. */ +# define LOCK_RW 192 /* ... Which allows concurrent read & write operations. */ +#endif + +#ifdef __USE_GNU +/* Types of directory notifications that may be requested with F_NOTIFY. */ +# define DN_ACCESS 0x00000001 /* File accessed. */ +# define DN_MODIFY 0x00000002 /* File modified. */ +# define DN_CREATE 0x00000004 /* File created. */ +# define DN_DELETE 0x00000008 /* File removed. */ +# define DN_RENAME 0x00000010 /* File renamed. */ +# define DN_ATTRIB 0x00000020 /* File changed attibutes. */ +# define DN_MULTISHOT 0x80000000 /* Don't remove notifier. */ +#endif + +struct flock + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ +#ifndef __USE_FILE_OFFSET64 + __off_t l_start; /* Offset where the lock begins. */ + __off_t l_len; /* Size of the locked area; zero means until EOF. */ +#else + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ +#endif + __pid_t l_pid; /* Process holding the lock. */ + }; + +#ifdef __USE_LARGEFILE64 +struct flock64 + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ + __pid_t l_pid; /* Process holding the lock. */ + }; +#endif + +/* Define some more compatibility macros to be backward compatible with + BSD systems which did not managed to hide these kernel macros. */ +#ifdef __USE_BSD +# define FAPPEND O_APPEND +# define FFSYNC O_FSYNC +# define FASYNC O_ASYNC +# define FNONBLOCK O_NONBLOCK +# define FNDELAY O_NDELAY +#endif /* Use BSD. */ + +/* Advise to `posix_fadvise'. */ +#ifdef __USE_XOPEN2K +# define POSIX_FADV_NORMAL 0 /* No further special treatment. */ +# define POSIX_FADV_RANDOM 1 /* Expect random page references. */ +# define POSIX_FADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define POSIX_FADV_WILLNEED 3 /* Will need these pages. */ +# define POSIX_FADV_DONTNEED 4 /* Don't need these pages. */ +# define POSIX_FADV_NOREUSE 5 /* Data will be accessed once. */ +#endif + + +#if defined __USE_GNU && defined __UCLIBC_LINUX_SPECIFIC__ +/* Flags for SYNC_FILE_RANGE. */ +# define SYNC_FILE_RANGE_WAIT_BEFORE 1 /* Wait upon writeout of all pages + in the range before performing the + write. */ +# define SYNC_FILE_RANGE_WRITE 2 /* Initiate writeout of all those + dirty pages in the range which are + not presently under writeback. */ +# define SYNC_FILE_RANGE_WAIT_AFTER 4 /* Wait upon writeout of all pages in + the range after performing the + write. */ + +/* Flags for SPLICE and VMSPLICE. */ +# define SPLICE_F_MOVE 1 /* Move pages instead of copying. */ +# define SPLICE_F_NONBLOCK 2 /* Don't block on the pipe splicing + (but we may still block on the fd + we splice from/to). */ +# define SPLICE_F_MORE 4 /* Expect more data. */ +# define SPLICE_F_GIFT 8 /* Pages passed in are a gift. */ +#endif + +__BEGIN_DECLS + +#if defined __USE_GNU && defined __UCLIBC_LINUX_SPECIFIC__ + +/* Provide kernel hint to read ahead. */ +extern ssize_t readahead (int __fd, __off64_t __offset, size_t __count) + __THROW; + + +/* Selective file content synch'ing. */ +extern int sync_file_range (int __fd, __off64_t __from, __off64_t __to, + unsigned int __flags); + +/* Splice address range into a pipe. */ +extern ssize_t vmsplice (int __fdout, const struct iovec *__iov, + size_t __count, unsigned int __flags); + +/* Splice two files together. */ +extern ssize_t splice (int __fdin, __off64_t *__offin, int __fdout, + __off64_t *__offout, size_t __len, + unsigned int __flags); + +/* In-kernel implementation of tee for pipe buffers. */ +extern ssize_t tee (int __fdin, int __fdout, size_t __len, + unsigned int __flags); + +#endif +__END_DECLS + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/bits/kernel_stat.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/bits/kernel_stat.h new file mode 100644 index 00000000..2b95465b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/bits/kernel_stat.h @@ -0,0 +1,54 @@ +#ifndef _BITS_STAT_STRUCT_H +#define _BITS_STAT_STRUCT_H + +#ifndef _LIBC +#error bits/kernel_stat.h is for internal uClibc use only! +#endif + +/* This file provides whatever this particular arch's kernel thinks + * struct kernel_stat should look like... It turns out each arch has a + * different opinion on the subject... */ + +struct kernel_stat { + unsigned short st_dev; + unsigned short __pad1; + unsigned long st_ino; + unsigned short st_mode; + unsigned short st_nlink; + unsigned short st_uid; + unsigned short st_gid; + unsigned short st_rdev; + unsigned short __pad2; + unsigned long st_size; + unsigned long st_blksize; + unsigned long st_blocks; + struct timespec st_atim; + struct timespec st_mtim; + struct timespec st_ctim; + unsigned long __unused4; + unsigned long __unused5; +}; + +struct kernel_stat64 { + unsigned long long st_dev; + unsigned char __pad1[2]; +#define _HAVE_STAT64___ST_INO + unsigned long __st_ino; + unsigned int st_mode; + unsigned int st_nlink; + unsigned long st_uid; + unsigned long st_gid; + unsigned short st_rdev; + unsigned char __pad3[10]; + long long st_size; + unsigned long st_blksize; + unsigned long st_blocks; /* Number 512-byte blocks allocated. */ + unsigned long __pad4; /* future possible st_blocks high bits */ + struct timespec st_atim; + struct timespec st_mtim; + struct timespec st_ctim; + unsigned long long st_ino; +}; + +#endif /* _BITS_STAT_STRUCT_H */ + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/bits/kernel_types.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/bits/kernel_types.h new file mode 100644 index 00000000..05706756 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/bits/kernel_types.h @@ -0,0 +1,44 @@ +#ifndef _BITS_KERNEL_TYPES_H +#define _BITS_KERNEL_TYPES_H + +/* Sigh. We need to carefully wrap this one... No guarantees + * that the asm/posix_types.h kernel header is working. Many + * arches have broken headers that introduce tons of gratuitous + * conflicts with uClibc's namespace. See bits/kernel_types.h + * for i386, arm, etc for examples... */ + +typedef unsigned short __kernel_dev_t; +typedef unsigned long __kernel_ino_t; +typedef unsigned short __kernel_mode_t; +typedef unsigned short __kernel_nlink_t; +typedef long __kernel_off_t; +typedef int __kernel_pid_t; +typedef unsigned short __kernel_ipc_pid_t; +typedef unsigned short __kernel_uid_t; +typedef unsigned short __kernel_gid_t; +typedef unsigned int __kernel_size_t; +typedef int __kernel_ssize_t; +typedef int __kernel_ptrdiff_t; +typedef long __kernel_time_t; +typedef long __kernel_suseconds_t; +typedef long __kernel_clock_t; +typedef int __kernel_daddr_t; +typedef char * __kernel_caddr_t; +typedef unsigned short __kernel_uid16_t; +typedef unsigned short __kernel_gid16_t; +typedef unsigned int __kernel_uid32_t; +typedef unsigned int __kernel_gid32_t; +typedef unsigned short __kernel_old_uid_t; +typedef unsigned short __kernel_old_gid_t; +typedef long long __kernel_loff_t; +typedef __kernel_dev_t __kernel_old_dev_t; + +typedef struct { +#ifdef __USE_ALL + int val[2]; +#else + int __val[2]; +#endif +} __kernel_fsid_t; + +#endif /* _BITS_KERNEL_TYPES_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/bits/setjmp.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/bits/setjmp.h new file mode 100644 index 00000000..15f8d844 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/bits/setjmp.h @@ -0,0 +1,32 @@ + +/* Copyright (C) 2004, Yoshinori Sato */ +/* Define the machine-dependent type `jmp_buf'. H8/300 version. */ + +#ifndef _BITS_SETJMP_H +#define _BITS_SETJMP_H 1 + +#if !defined _SETJMP_H && !defined _PTHREAD_H +# error "Never include directly; use instead." +#endif + +#ifndef _ASM + +typedef struct + { + unsigned long __regs[4]; /* save er4 - er7(sp) */ + unsigned long __pc; /* the return address */ + } __jmp_buf[1]; + +#endif /* _ASM */ + +#define JB_REGS 0 +#define JB_PC 16 +#define JB_SIZE 20 + + +/* Test if longjmp to JMPBUF would unwind the frame + containing a local variable at ADDRESS. */ +#define _JMPBUF_UNWINDS(jmpbuf, address) \ + ((void *) (address) < (void *) (jmpbuf)->__regs[3]) + +#endif /* bits/setjmp.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/bits/sigcontextinfo.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/bits/sigcontextinfo.h new file mode 100644 index 00000000..b7e08cfc --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/bits/sigcontextinfo.h @@ -0,0 +1,26 @@ +/* Copyright (C) 1998, 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Andreas Schwab , 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define SIGCONTEXT int _code, struct sigcontext * +#define SIGCONTEXT_EXTRA_ARGS _code, +#define GET_PC(ctx) ((void *) (ctx)->sc_pc) +#define GET_FRAME(ctx) ((void *) __builtin_frame_address (1)) +#define GET_STACK(ctx) ((void *) (ctx)->sc_usp) +#define CALL_SIGHANDLER(handler, signo, ctx) \ + (handler)((signo), SIGCONTEXT_EXTRA_ARGS (ctx)) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/bits/stackinfo.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/bits/stackinfo.h new file mode 100644 index 00000000..89a77d93 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/bits/stackinfo.h @@ -0,0 +1,28 @@ +/* Copyright (C) 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This file contains a bit of information about the stack allocation + of the processor. */ + +#ifndef _STACKINFO_H +#define _STACKINFO_H 1 + +/* On h8300 the stack grows down. */ +#define _STACK_GROWS_DOWN 1 + +#endif /* stackinfo.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/bits/syscalls.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/bits/syscalls.h new file mode 100644 index 00000000..5867ed60 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/bits/syscalls.h @@ -0,0 +1,151 @@ +/* Unlike the asm/unistd.h kernel header file (which this is partly based on), + * this file must be able to cope with PIC and non-PIC code. For some arches + * there is no difference. For x86 (which has far too few registers) there is + * a difference. Regardless, including asm/unistd.h is hereby officially + * forbidden. Don't do it. It is bad for you. + */ +#ifndef _SYSCALL_H +# error "Never use directly; include instead." +#endif + +#define __syscall_return(type, res) \ +do { \ + if ((unsigned long)(res) >= (unsigned long)(-125)) { \ + /* avoid using res which is declared to be in register d0; \ + errno might expand to a function call and clobber it. */ \ + int __err = -(res); \ + errno = __err; \ + res = -1; \ + } \ + return (type) (res); \ +} while (0) + +#define _syscall0(type, name) \ +type name(void) \ +{ \ + register long __res __asm__("er0"); \ + __asm__ __volatile__ ("mov.l %1,er0\n\t" \ + "trapa #0\n\t" \ + : "=r" (__res) \ + : "ir" (__NR_##name) \ + : "cc"); \ + if ((unsigned long)(__res) >= (unsigned long)(-125)) { \ + errno = -__res; \ + __res = -1; \ + } \ + return (type)__res; \ +} + +#define _syscall1(type, name, atype, a) \ +type name(atype a) \ +{ \ + register long __res __asm__("er0"); \ + __asm__ __volatile__ ("mov.l %2, er1\n\t" \ + "mov.l %1, er0\n\t" \ + "trapa #0\n\t" \ + : "=r" (__res) \ + : "ir" (__NR_##name), \ + "g" ((long)a) \ + : "cc", "er1"); \ + if ((unsigned long)(__res) >= (unsigned long)(-125)) { \ + errno = -__res; \ + __res = -1; \ + } \ + return (type)__res; \ +} + +#define _syscall2(type, name, atype, a, btype, b) \ +type name(atype a, btype b) \ +{ \ + register long __res __asm__("er0"); \ + __asm__ __volatile__ ("mov.l %3, er2\n\t" \ + "mov.l %2, er1\n\t" \ + "mov.l %1, er0\n\t" \ + "trapa #0\n\t" \ + : "=r" (__res) \ + : "ir" (__NR_##name), \ + "g" ((long)a), \ + "g" ((long)b) \ + : "cc", "er1", "er2"); \ + if ((unsigned long)(__res) >= (unsigned long)(-125)) { \ + errno = -__res; \ + __res = -1; \ + } \ + return (type)__res; \ +} + +#define _syscall3(type, name, atype, a, btype, b, ctype, c) \ +type name(atype a, btype b, ctype c) \ +{ \ + register long __res __asm__("er0"); \ + __asm__ __volatile__ ("mov.l %4, er3\n\t" \ + "mov.l %3, er2\n\t" \ + "mov.l %2, er1\n\t" \ + "mov.l %1, er0\n\t" \ + "trapa #0\n\t" \ + : "=r" (__res) \ + : "ir" (__NR_##name), \ + "g" ((long)a), \ + "g" ((long)b), \ + "g" ((long)c) \ + : "cc", "er1", "er2", "er3"); \ + if ((unsigned long)(__res) >= (unsigned long)(-125)) { \ + errno = -__res; \ + __res = -1; \ + } \ + return (type)__res; \ +} + +#define _syscall4(type, name, atype, a, btype, b, ctype, c, dtype, d) \ +type name(atype a, btype b, ctype c, dtype d) \ +{ \ + register long __res __asm__("er0"); \ + __asm__ __volatile__ ("mov.l %5, er4\n\t" \ + "mov.l %4, er3\n\t" \ + "mov.l %3, er2\n\t" \ + "mov.l %2, er1\n\t" \ + "mov.l %1, er0\n\t" \ + "trapa #0\n\t" \ + : "=r" (__res) \ + : "ir" (__NR_##name), \ + "g" ((long)a), \ + "g" ((long)b), \ + "g" ((long)c), \ + "g" ((long)d) \ + : "cc", "er1", "er2", "er3", "er4"); \ + if ((unsigned long)(__res) >= (unsigned long)(-125)) { \ + errno = -__res; \ + __res = -1; \ + } \ + return (type)__res; \ +} + +#define _syscall5(type, name, atype, a, btype, b, ctype, c, dtype, d, etype, e) \ +type name(atype a, btype b, ctype c, dtype d, etype e) \ +{ \ + register long __res __asm__("er0"); \ + __asm__ __volatile__ ( \ + "mov.l er5,@-sp\n\t" \ + "mov.l %5, er4\n\t" \ + "mov.l %4, er3\n\t" \ + "mov.l %3, er2\n\t" \ + "mov.l %2, er1\n\t" \ + "mov.l %1, er0\n\t" \ + "mov.l %6, er5\n\t" \ + "trapa #0\n\t" \ + "mov.l @sp+,er5\n\t" \ + : "=r" (__res) \ + : "ir" (__NR_##name), \ + "g" ((long)a), \ + "g" ((long)b), \ + "g" ((long)c), \ + "g" ((long)d), \ + "m" ((long)e) \ + : "cc", "er1", "er2", "er3", "er4"); \ + if ((unsigned long)(__res) >= (unsigned long)(-125)) { \ + errno = -__res; \ + __res = -1; \ + } \ + return (type)__res; \ +} + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/bits/uClibc_arch_features.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/bits/uClibc_arch_features.h new file mode 100644 index 00000000..4bab5476 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/bits/uClibc_arch_features.h @@ -0,0 +1,48 @@ +/* + * Track misc arch-specific features that aren't config options + */ + +#ifndef _BITS_UCLIBC_ARCH_FEATURES_H +#define _BITS_UCLIBC_ARCH_FEATURES_H + +/* instruction used when calling abort() to kill yourself */ +/*#define __UCLIBC_ABORT_INSTRUCTION__ "asm instruction"*/ +#undef __UCLIBC_ABORT_INSTRUCTION__ + +/* can your target use syscall6() for mmap ? */ +#define __UCLIBC_MMAP_HAS_6_ARGS__ + +/* does your target use syscall4() for truncate64 ? (32bit arches only) */ +#undef __UCLIBC_TRUNCATE64_HAS_4_ARGS__ + +/* does your target have a broken create_module() ? */ +#undef __UCLIBC_BROKEN_CREATE_MODULE__ + +/* does your target have to worry about older [gs]etrlimit() ? */ +#undef __UCLIBC_HANDLE_OLDER_RLIMIT__ + +/* does your target have an asm .set ? */ +#define __UCLIBC_HAVE_ASM_SET_DIRECTIVE__ + +/* define if target doesn't like .global */ +#undef __UCLIBC_ASM_GLOBAL_DIRECTIVE__ + +/* define if target supports .weak */ +#define __UCLIBC_HAVE_ASM_WEAK_DIRECTIVE__ + +/* define if target supports .weakext */ +#undef __UCLIBC_HAVE_ASM_WEAKEXT_DIRECTIVE__ + +/* needed probably only for ppc64 */ +#undef __UCLIBC_HAVE_ASM_GLOBAL_DOT_NAME__ + +/* define if target supports CFI pseudo ops */ +#undef __UCLIBC_HAVE_ASM_CFI_DIRECTIVES__ + +/* define if target supports IEEE signed zero floats */ +#define __UCLIBC_HAVE_SIGNED_ZERO__ + +/* only weird assemblers generally need this */ +#undef __UCLIBC_ASM_LINE_SEP__ + +#endif /* _BITS_UCLIBC_ARCH_FEATURES_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/bits/wordsize.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/bits/wordsize.h new file mode 100644 index 00000000..b47eee94 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/bits/wordsize.h @@ -0,0 +1 @@ +#define __WORDSIZE 32 diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/brk.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/brk.c new file mode 100644 index 00000000..b3378137 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/brk.c @@ -0,0 +1,37 @@ +/* brk on H8/300 by ysato */ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include + +/* This must be initialized data because commons can't have aliases. */ +void *__curbrk attribute_hidden = 0; + +int brk (void *addr) +{ + void *newbrk; + + __asm__ ("mov.l %2,er1\n\t" + "mov.l %1,er0\n\t" + "trapa #0\n\t" + "mov.l er0,%0" + : "=r" (newbrk) + : "0" (__NR_brk), "g" (addr) + : "er0","er1"); + + __curbrk = newbrk; + + if (newbrk < addr) + { + __set_errno (ENOMEM); + return -1; + } + + return 0; +} +libc_hidden_def(brk) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/bsd-_setjmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/bsd-_setjmp.S new file mode 100644 index 00000000..e315058a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/bsd-_setjmp.S @@ -0,0 +1,27 @@ +/* BSD `_setjmp' entry point to `sigsetjmp (..., 0)'. H8/300 version. */ + +#define _ASM +#define _SETJMP_H +#include + +#ifdef __H8300S__ + .h8300s +#else + .h8300h +#endif + .text + +.global __setjmp + +__setjmp: + add.l #JB_SIZE,er0 + mov.l @sp,er1 ; return PC + mov.l er1,@-er0 + mov.l sp,@-er0 + mov.l er6,@-er0 + mov.l er5,@-er0 + mov.l er4,@-er0 + mov.l er0,er1 + sub.l er0,er0 + mov.l er0,@(JB_SIZE:16,er1) + rts diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/bsd-setjmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/bsd-setjmp.S new file mode 100644 index 00000000..9c353550 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/bsd-setjmp.S @@ -0,0 +1,30 @@ +/* BSD `_setjmp' entry point to `sigsetjmp (..., 1)'. H8/300 version. */ + +#define _ASM +#define _SETJMP_H +#include + +#ifdef __H8300S__ + .h8300s +#else + .h8300h +#endif + .text + +.global _setjmp + +_setjmp: + add.l #JB_SIZE,er0 + mov.l @sp,er1 ; return PC + mov.l er1,@-er0 + mov.l sp,@-er0 + mov.l er6,@-er0 + mov.l er5,@-er0 + mov.l er4,@-er0 + sub.l er0,er0 +#if !defined(__PIC__) + jmp @___sigjmp_save +#else + mov.l @(___sigjmp_save@GOTOFF,er5),er1 + jmp @er3 +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/clone.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/clone.S new file mode 100644 index 00000000..554a2970 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/clone.S @@ -0,0 +1,68 @@ +/* Adapted from glibc */ +/* Copyright (C) 1996, 1997 Free Software Foundation, Inc. */ + +/* clone is even more special than fork as it mucks with stacks + and invokes a function in the right context after its all over. */ + +#define _ERRNO_H +#include +#include + +/* int _clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg); */ + +#ifdef __H8300H__ + .h8300h +#endif +#ifdef __H8300S__ + .h8300s +#endif + +.text +.globl _clone +_clone: + /* Sanity check arguments. */ + mov.l #-EINVAL,er3 + mov.l er0,er0 /* no NULL function pointers */ + beq __syscall_error + mov.l er1,er1 /* no NULL stack pointers */ + beq __syscall_error + + /* Allocate space and copy the argument onto the new stack. */ + mov.l @(4:16,sp),er3 + mov.l er3,@-er1 + + /* Do the system call */ + mov.l er0,er3 /* er3 = child entry */ + mov.l er1,er0 + mov.l er2,er1 /* er1 = flags */ + mov.l er0,er2 /* er2 = child sp */ + mov.l #__NR_clone,r0 + trapa #0 + mov.l er0,er0 + bmi __syscall_error + beq thread_start + + rts + +__syscall_error: + neg.l er0 + mov.l er0,@-sp +#if !defined(__PIC__) + jsr @__errno_location +#else + mov.l @(__errno_location@GOTOFF,er5),er1 + jsr @er1 +#endif + mov.l @sp,er1 + mov.l er1,@er0 + sub.l er0,er0 + dec.l #1,er0 + + rts + +thread_start: + mov.l @sp+,er0 /* restore args */ + jsr @er3 + mov.l er0,er1 + mov.l #__NR_exit,er0 + trapa #0 diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/crt0.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/crt0.S new file mode 100644 index 00000000..ebdca18e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/crt0.S @@ -0,0 +1,70 @@ +/* Copyright (C) 1991, 1992 Free Software Foundation, Inc. + +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include + + .global _start + .global __exit + .global atexit + .global main + +#ifdef __H8300S__ + .h8300s +#else + .h8300h +#endif + .text + +_start: /* put here so that references to _start work with elf-PIC */ + + mov.l @(0,sp),er0 /* argc */ + mov.l @(4,sp),er1 /* argv */ + mov.l @(8,sp),er2 /* envp */ +#if !defined(__PIC__) + jsr @___uClibc_main +#else + mov.l @(___uClibc_main@GOTOFF,er5),er3 + jsr @er3 +#endif + + /* If that didn't kill us, ... */ +__exit: + mov.l er0,er1 + sub.l er0,er0 + inc.l #1,er0 /* __NR_exit */ + trapa #0 + +/* + * this was needed for gcc/g++-builds, atexit was not getting included + * for some stupid reason, this gets us a compiler + */ +empty_func: + rts + .weak atexit + atexit = empty_func + + +/* Define a symbol for the first piece of initialized data. */ + .data + .globl __data_start +__data_start: + .long 0 + .weak data_start + data_start = __data_start + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/crti.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/crti.S new file mode 100644 index 00000000..270df276 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/crti.S @@ -0,0 +1,30 @@ +#ifdef __H8300H__ + .h8300h +#endif +#ifdef __H8300S__ + .h8300s +#endif + .file "initfini.c" +; #APP + + .section .init +; #NO_APP + .align 1 + .global __init +__init: + mov.l er6,@-er7 + mov.l er7,er6 +; #APP + .align 1 + + .section .fini +; #NO_APP + .align 1 + .global __fini +__fini: + mov.l er6,@-er7 + mov.l er7,er6 +; #APP + .align 1 + + .end diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/crtn.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/crtn.S new file mode 100644 index 00000000..8f9fa1fa --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/crtn.S @@ -0,0 +1,28 @@ +#ifdef __H8300H__ + .h8300h +#endif +#ifdef __H8300S__ + .h8300s +#endif + .file "initfini.c" +; #APP + + .section .init +; #NO_APP + .align 1 + .global __init +; #NO_APP + mov.l @er7+,er6 + rts +; #APP + + .section .fini +; #NO_APP + .align 1 + .global __fini +; #NO_APP + mov.l @er7+,er6 + rts +; #APP + + .end diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/float.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/float.h new file mode 100644 index 00000000..7dbe4e92 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/float.h @@ -0,0 +1,96 @@ +/* float.h for target with IEEE 32 bit and 64 bit floating point formats */ +#ifndef _FLOAT_H_ +#define _FLOAT_H_ +/* Produced by enquire version 4.3, CWI, Amsterdam */ + + /* Radix of exponent representation */ +#undef FLT_RADIX +#define FLT_RADIX 2 + /* Number of base-FLT_RADIX digits in the significand of a float */ +#undef FLT_MANT_DIG +#define FLT_MANT_DIG 24 + /* Number of decimal digits of precision in a float */ +#undef FLT_DIG +#define FLT_DIG 6 + /* Addition rounds to 0: zero, 1: nearest, 2: +inf, 3: -inf, -1: unknown */ +#undef FLT_ROUNDS +#define FLT_ROUNDS 1 + /* Difference between 1.0 and the minimum float greater than 1.0 */ +#undef FLT_EPSILON +#define FLT_EPSILON 1.19209290e-07F + /* Minimum int x such that FLT_RADIX**(x-1) is a normalised float */ +#undef FLT_MIN_EXP +#define FLT_MIN_EXP (-125) + /* Minimum normalised float */ +#undef FLT_MIN +#define FLT_MIN 1.17549435e-38F + /* Minimum int x such that 10**x is a normalised float */ +#undef FLT_MIN_10_EXP +#define FLT_MIN_10_EXP (-37) + /* Maximum int x such that FLT_RADIX**(x-1) is a representable float */ +#undef FLT_MAX_EXP +#define FLT_MAX_EXP 128 + /* Maximum float */ +#undef FLT_MAX +#define FLT_MAX 3.40282347e+38F + /* Maximum int x such that 10**x is a representable float */ +#undef FLT_MAX_10_EXP +#define FLT_MAX_10_EXP 38 + + /* Number of base-FLT_RADIX digits in the significand of a double */ +#undef DBL_MANT_DIG +#define DBL_MANT_DIG 53 + /* Number of decimal digits of precision in a double */ +#undef DBL_DIG +#define DBL_DIG 15 + /* Difference between 1.0 and the minimum double greater than 1.0 */ +#undef DBL_EPSILON +#define DBL_EPSILON 2.2204460492503131e-16 + /* Minimum int x such that FLT_RADIX**(x-1) is a normalised double */ +#undef DBL_MIN_EXP +#define DBL_MIN_EXP (-1021) + /* Minimum normalised double */ +#undef DBL_MIN +#define DBL_MIN 2.2250738585072014e-308 + /* Minimum int x such that 10**x is a normalised double */ +#undef DBL_MIN_10_EXP +#define DBL_MIN_10_EXP (-307) + /* Maximum int x such that FLT_RADIX**(x-1) is a representable double */ +#undef DBL_MAX_EXP +#define DBL_MAX_EXP 1024 + /* Maximum double */ +#undef DBL_MAX +#define DBL_MAX 1.7976931348623157e+308 + /* Maximum int x such that 10**x is a representable double */ +#undef DBL_MAX_10_EXP +#define DBL_MAX_10_EXP 308 + + /* Number of base-FLT_RADIX digits in the significand of a long double */ +#undef LDBL_MANT_DIG +#define LDBL_MANT_DIG 53 + /* Number of decimal digits of precision in a long double */ +#undef LDBL_DIG +#define LDBL_DIG 15 + /* Difference between 1.0 and the minimum long double greater than 1.0 */ +#undef LDBL_EPSILON +#define LDBL_EPSILON 2.2204460492503131e-16L + /* Minimum int x such that FLT_RADIX**(x-1) is a normalised long double */ +#undef LDBL_MIN_EXP +#define LDBL_MIN_EXP (-1021) + /* Minimum normalised long double */ +#undef LDBL_MIN +#define LDBL_MIN 2.2250738585072014e-308L + /* Minimum int x such that 10**x is a normalised long double */ +#undef LDBL_MIN_10_EXP +#define LDBL_MIN_10_EXP (-307) + /* Maximum int x such that FLT_RADIX**(x-1) is a representable long double */ +#undef LDBL_MAX_EXP +#define LDBL_MAX_EXP 1024 + /* Maximum long double */ +#undef LDBL_MAX +#define LDBL_MAX 1.7976931348623157e+308L + /* Maximum int x such that 10**x is a representable long double */ +#undef LDBL_MAX_10_EXP +#define LDBL_MAX_10_EXP 308 + +#endif /* _FLOAT_H_ */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/ptrace.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/ptrace.c new file mode 100644 index 00000000..1dd7d063 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/ptrace.c @@ -0,0 +1,36 @@ + +#include +#include +#include + +int +ptrace(int request, int pid, int addr, int data) +{ + int ret; + int res; + + if (request > 0 && request < 4) data = (int)&ret; + + __asm__ __volatile__ ("sub.l er0,er0\n\t" + "mov.b %1,r0l\n\t" + "mov.l %2,er1\n\t" + "mov.l %3,er2\n\t" + "mov.l %4,er3\n\t" + "mov.l %5,er4\n\t" + "trapa #0\n\t" + "mov.l er0,%0" + :"=g" (res) + :"i" (__NR_ptrace), "g" (request), "g" (pid), + "g" (addr), "g" (data) + : "er0", "er1", "er2", "er3", "er4"); + + if (res >= 0) { + if (request > 0 && request < 4) { + __set_errno(0); + return (ret); + } + return (int) res; + } + __set_errno(-res); + return -1; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/setjmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/setjmp.S new file mode 100644 index 00000000..5e487674 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/setjmp.S @@ -0,0 +1,23 @@ +#define _ASM +#define _SETJMP_H +#include + +#ifdef __H8300S__ + .h8300s +#else + .h8300h +#endif + .text + +.global ___sigsetjmp + +___sigsetjmp: + add.l #JB_SIZE,er0 + mov.l @sp,er1 ; return PC + mov.l er1,@-er0 + mov.l sp,@-er0 + mov.l er6,@-er0 + mov.l er5,@-er0 + mov.l er4,@-er0 + sub.l er0,er0 + rts diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/sys/procfs.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/sys/procfs.h new file mode 100644 index 00000000..27abf8ef --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/sys/procfs.h @@ -0,0 +1,126 @@ +/* Copyright (C) 1996, 1997, 1999, 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_PROCFS_H +#define _SYS_PROCFS_H 1 + +/* This is somewhat modelled after the file of the same name on SVR4 + systems. It provides a definition of the core file format for ELF + used on Linux. It doesn't have anything to do with the /proc file + system, even though Linux has one. + + Anyway, the whole purpose of this file is for GDB and GDB only. + Don't read too much into it. Don't use it for anything other than + GDB unless you know what you are doing. */ + +#include +#include +#include +#include + +__BEGIN_DECLS + +/* Type for a general-purpose register. */ +typedef unsigned long elf_greg_t; + +/* And the whole bunch of them. We could have used `struct + user_regs_struct' directly in the typedef, but tradition says that + the register set is an array, which does have some peculiar + semantics, so leave it that way. */ +#define ELF_NGREG (sizeof (struct user_regs_struct) / sizeof(elf_greg_t)) +typedef elf_greg_t elf_gregset_t[ELF_NGREG]; + +/* Register set for the floating-point registers. */ +typedef struct user_m68kfp_struct elf_fpregset_t; + + +/* Signal info. */ +struct elf_siginfo + { + int si_signo; /* Signal number. */ + int si_code; /* Extra code. */ + int si_errno; /* Errno. */ + }; + + +/* Definitions to generate Intel SVR4-like core files. These mostly + have the same names as the SVR4 types with "elf_" tacked on the + front to prevent clashes with Linux definitions, and the typedef + forms have been avoided. This is mostly like the SVR4 structure, + but more Linuxy, with things that Linux does not support and which + GDB doesn't really use excluded. */ + +struct elf_prstatus + { + struct elf_siginfo pr_info; /* Info associated with signal. */ + short int pr_cursig; /* Current signal. */ + unsigned long int pr_sigpend; /* Set of pending signals. */ + unsigned long int pr_sighold; /* Set of held signals. */ + __pid_t pr_pid; + __pid_t pr_ppid; + __pid_t pr_pgrp; + __pid_t pr_sid; + struct timeval pr_utime; /* User time. */ + struct timeval pr_stime; /* System time. */ + struct timeval pr_cutime; /* Cumulative user time. */ + struct timeval pr_cstime; /* Cumulative system time. */ + elf_gregset_t pr_reg; /* GP registers. */ + int pr_fpvalid; /* True if math copro being used. */ + }; + + +#define ELF_PRARGSZ (80) /* Number of chars for args. */ + +struct elf_prpsinfo + { + char pr_state; /* Numeric process state. */ + char pr_sname; /* Char for pr_state. */ + char pr_zomb; /* Zombie. */ + char pr_nice; /* Nice val. */ + unsigned long int pr_flag; /* Flags. */ + unsigned short int pr_uid; + unsigned short int pr_gid; + int pr_pid, pr_ppid, pr_pgrp, pr_sid; + /* Lots missing */ + char pr_fname[16]; /* Filename of executable. */ + char pr_psargs[ELF_PRARGSZ]; /* Initial part of arg list. */ + }; + + +/* The rest of this file provides the types for emulation of the + Solaris interfaces that should be implemented by + users of libthread_db. */ + +/* Addresses. */ +typedef void *psaddr_t; + +/* Register sets. Linux has different names. */ +typedef elf_gregset_t prgregset_t; +typedef elf_fpregset_t prfpregset_t; + +/* We don't have any differences between processes and threads, + therefore have only one PID type. */ +typedef __pid_t lwpid_t; + +/* Process status and info. In the end we do provide typedefs for them. */ +typedef struct elf_prstatus prstatus_t; +typedef struct elf_prpsinfo prpsinfo_t; + +__END_DECLS + +#endif /* sys/procfs.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/sys/ucontext.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/sys/ucontext.h new file mode 100644 index 00000000..ffc9ea02 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/sys/ucontext.h @@ -0,0 +1,75 @@ +/* Copyright (C) 1997, 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* H8/300 compliant context switching support. */ + +#ifndef _SYS_UCONTEXT_H +#define _SYS_UCONTEXT_H 1 + +#include +#include + +typedef int greg_t; + +/* Number of general registers. */ +#define NFPREG 8 + +/* Container for all general registers. */ +typedef greg_t gregset_t[NFPREG]; + +#ifdef __USE_GNU +/* Number of each register is the `gregset_t' array. */ +enum +{ + ER0 = 0, +#define ER0 ER0 + ER1 = 1, +#define ER1 ER1 + ER2 = 2, +#define ER2 ER2 + ER3 = 3, +#define ER3 ER3 + ER4 = 4, +#define ER4 ER4 + ER5 = 5, +#define ER5 ER5 + ER6 = 6, +#define ER6 ER6 + ER7 = 7, +#define ER7 ER7 +}; +#endif + +/* Context to describe whole processor state. */ +typedef struct + { + gregset_t gregs; + } mcontext_t; + +/* Userlevel context. */ +typedef struct ucontext + { + unsigned long int uc_flags; + struct ucontext *uc_link; + stack_t uc_stack; + mcontext_t uc_mcontext; + __sigset_t uc_sigmask; + } ucontext_t; + +#endif + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/vfork.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/vfork.S new file mode 100644 index 00000000..35c04e55 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/h8300/vfork.S @@ -0,0 +1,41 @@ + +#include + +#ifndef __NR_vfork +#define __NR_vfork __NR_fork /* uClinux-2.0 only has fork which is vfork */ +#endif + +#ifdef __H8300S__ + .h8300s +#else + .h8300h +#endif + .text + .align 2 + .globl _errno + .globl ___vfork + .hidden ___vfork + .type ___vfork,@function +___vfork: + mov.l @sp+, er1 + sub.l er0,er0 + mov.b #__NR_vfork,r0l + trapa #0 + mov.l #-4096, er2 + cmp.l er0,er2 + bcs fix_errno + jmp @er1 /* don't return, just jmp directly */ +fix_errno: + neg.l er0 +#if !defined(__PIC__) + mov.l er0,@_errno +#else + mov.l @(_errno@GOTOFF,er5),er2 + mov.l er0,@er2 +#endif + sub.l er0,er0 + dec.l #1,er0 + jmp @er1 /* don't return, just jmp directly */ + +weak_alias(__vfork,vfork) +libc_hidden_weak(vfork) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/Makefile new file mode 100644 index 00000000..633c91f3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../../ +top_builddir=../../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.arch +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/Makefile.arch b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/Makefile.arch new file mode 100644 index 00000000..2b0cf09a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/Makefile.arch @@ -0,0 +1,11 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +CSRC := __syscall_error.c brk.c mmap.c syscall.c + +SSRC := __longjmp.S bsd-_setjmp.S bsd-setjmp.S clone.S setjmp.S \ + add_n.s lshift.s rshift.s sub_n.s udiv_qrnnd.s diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/__longjmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/__longjmp.S new file mode 100644 index 00000000..750863e9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/__longjmp.S @@ -0,0 +1,74 @@ +/* longjmp for PA-RISC. + Copyright (C) 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#define _SETJMP_H +#define _ASM +#include + +/* __longjmp(jmpbuf, val) */ + + .text + .align 4 + .globl __longjmp + .export __longjmp, code + .proc + .callinfo +__longjmp: + /* set return value */ + copy %r25, %r28 + + ldw 0(%r26), %r3 + ldw 8(%r26), %r4 + ldw 12(%r26), %r5 + ldw 16(%r26), %r6 + ldw 20(%r26), %r7 + ldw 24(%r26), %r8 + ldw 28(%r26), %r9 + ldw 32(%r26), %r10 + ldw 36(%r26), %r11 + ldw 40(%r26), %r12 + ldw 44(%r26), %r13 + ldw 48(%r26), %r14 + ldw 52(%r26), %r15 + ldw 56(%r26), %r16 + ldw 60(%r26), %r17 + ldw 64(%r26), %r18 + ldw 68(%r26), %r19 + ldw 72(%r26), %r27 + ldw 76(%r26), %r30 + + ldw 80(%r26), %rp + + ldo 88(%r26),%r20 + fldds,ma 8(%r20), %fr12 + fldds,ma 8(%r20), %fr13 + fldds,ma 8(%r20), %fr14 + fldds,ma 8(%r20), %fr15 + fldds,ma 8(%r20), %fr16 + fldds,ma 8(%r20), %fr17 + fldds,ma 8(%r20), %fr18 + fldds,ma 8(%r20), %fr19 + fldds,ma 8(%r20), %fr20 + fldds 0(%r20), %fr21 + + bv,n %r0(%r2) + .procend + +libc_hidden_def(__longjmp) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/__syscall_error.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/__syscall_error.c new file mode 100644 index 00000000..5e109a83 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/__syscall_error.c @@ -0,0 +1,18 @@ +/* Wrapper for setting errno. + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +/* This routine is jumped to by all the syscall handlers, to stash + * an error number into errno. */ +int __syscall_error(int err_no) attribute_hidden; +int __syscall_error(int err_no) +{ + __set_errno(err_no); + return -1; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/add_n.s b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/add_n.s new file mode 100644 index 00000000..a396b347 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/add_n.s @@ -0,0 +1,58 @@ +;! HP-PA __mpn_add_n -- Add two limb vectors of the same length > 0 and store +;! sum in a third limb vector. + +;! Copyright (C) 1992, 1994 Free Software Foundation, Inc. + +;! This file is part of the GNU MP Library. + +;! The GNU MP Library is free software; you can redistribute it and/or modify +;! it under the terms of the GNU Lesser General Public License as published by +;! the Free Software Foundation; either version 2.1 of the License, or (at your +;! option) any later version. + +;! The GNU MP Library is distributed in the hope that it will be useful, but +;! WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +;! or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public +;! License for more details. + +;! You should have received a copy of the GNU Lesser General Public License +;! along with the GNU MP Library; see the file COPYING.LIB. If not, write to +;! the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +;! MA 02111-1307, USA. + + +;! INPUT PARAMETERS +;! res_ptr gr26 +;! s1_ptr gr25 +;! s2_ptr gr24 +;! size gr23 + +;! One might want to unroll this as for other processors, but it turns +;! out that the data cache contention after a store makes such +;! unrolling useless. We can't come under 5 cycles/limb anyway. + + .text + .export __mpn_add_n +__mpn_add_n: + .proc + .callinfo frame=0,no_calls + .entry + + ldws,ma 4(%r25),%r21 + ldws,ma 4(%r24),%r20 + + addib,= -1,%r23,L$end ;! check for (SIZE == 1) + add %r21,%r20,%r28 ;! add first limbs ignoring cy + +L$loop: ldws,ma 4(%r25),%r21 + ldws,ma 4(%r24),%r20 + stws,ma %r28,4(%r26) + addib,<> -1,%r23,L$loop + addc %r21,%r20,%r28 + +L$end: stws %r28,0(%r26) + bv 0(%r2) + addc %r0,%r0,%r28 + + .exit + .procend diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/bits/endian.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/bits/endian.h new file mode 100644 index 00000000..585db0c0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/bits/endian.h @@ -0,0 +1,7 @@ +/* hppa1.1 big-endian. */ + +#ifndef _ENDIAN_H +# error "Never use directly; include instead." +#endif + +#define __BYTE_ORDER __BIG_ENDIAN diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/bits/fcntl.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/bits/fcntl.h new file mode 100644 index 00000000..86e3b6f4 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/bits/fcntl.h @@ -0,0 +1,229 @@ +/* O_*, F_*, FD_* bit values for Linux/HPPA. + Copyright (C) 1995,1996,1997,1998,1999,2000,2002,2004 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FCNTL_H +# error "Never use directly; include instead." +#endif + +#include +#ifdef __USE_GNU +# include +#endif + +/* open/fcntl - O_SYNC is only implemented on blocks devices and on files + located on an ext2 file system */ +#define O_RDONLY 00000000 +#define O_WRONLY 00000001 +#define O_RDWR 00000002 +#define O_ACCMODE 00000003 +#define O_APPEND 00000010 +#define O_BLKSEEK 00000100 /* HPUX only */ +#define O_CREAT 00000400 /* not fcntl */ +#define O_TRUNC 00001000 /* not fcntl */ +#define O_EXCL 00002000 /* not fcntl */ +#define O_ASYNC 00020000 +#define O_SYNC 00100000 +#define O_NONBLOCK 00200004 /* HPUX has separate NDELAY & NONBLOCK */ +#define O_NDELAY O_NONBLOCK +#define O_NOCTTY 00400000 /* not fcntl */ + + +#ifdef __USE_GNU +# define O_DIRECT 00040000 /* Direct disk access. */ +# define O_DIRECTORY 00010000 /* Must be a directory. */ +# define O_NOFOLLOW 00000200 /* Do not follow links. */ +# define O_NOATIME 04000000 /* Do not set atime. */ +# define O_CLOEXEC 010000000 /* set close_on_exec */ +#endif + +#ifdef __USE_LARGEFILE64 +# define O_LARGEFILE 00004000 +#endif + +#if defined __USE_POSIX199309 || defined __USE_UNIX98 +# define O_DSYNC 01000000 /* HPUX only */ +# define O_RSYNC 02000000 /* HPUX only */ +#endif + +/* Values for the second argument to `fcntl'. */ +#define F_DUPFD 0 /* Duplicate file descriptor. */ +#define F_GETFD 1 /* Get file descriptor flags. */ +#define F_SETFD 2 /* Set file descriptor flags. */ +#define F_GETFL 3 /* Get file status flags. */ +#define F_SETFL 4 /* Set file status flags. */ +#ifndef __USE_FILE_OFFSET64 +# define F_GETLK 5 /* Get record locking info. */ +# define F_SETLK 6 /* Set record locking info (non-blocking). */ +# define F_SETLKW 7 /* Set record locking info (blocking). */ +#else +# define F_GETLK F_GETLK64 /* Get record locking info. */ +# define F_SETLK F_SETLK64 /* Set record locking info (non-blocking). */ +# define F_SETLKW F_SETLKW64 /* Set record locking info (blocking). */ +#endif +#define F_GETLK64 8 /* Get record locking info. */ +#define F_SETLK64 9 /* Set record locking info (non-blocking). */ +#define F_SETLKW64 10 /* Set record locking info (blocking). */ + +#if defined __USE_BSD || defined __USE_UNIX98 +# define F_GETOWN 11 /* Get owner of socket (receiver of SIGIO). */ +# define F_SETOWN 12 /* Set owner of socket (receiver of SIGIO). */ +#endif + +#ifdef __USE_GNU +# define F_SETSIG 13 /* Set number of signal to be sent. */ +# define F_GETSIG 14 /* Get number of signal to be sent. */ +#endif + +#ifdef __USE_GNU +# define F_SETLEASE 1024 /* Set a lease. */ +# define F_GETLEASE 1025 /* Enquire what lease is active. */ +# define F_NOTIFY 1026 /* Request notfications on a directory. */ +# define F_DUPFD_CLOEXEC 1030 /* Duplicate file descriptor with + close-on-exit set on new fd. */ +#endif + +/* for F_[GET|SET]FL */ +#define FD_CLOEXEC 1 /* actually anything with low bit set goes */ + +/* For posix fcntl() and `l_type' field of a `struct flock' for lockf(). */ +#define F_RDLCK 1 /* Read lock. */ +#define F_WRLCK 2 /* Write lock. */ +#define F_UNLCK 3 /* Remove lock. */ + +/* for old implementation of bsd flock () */ +#define F_EXLCK 4 /* or 3 */ +#define F_SHLCK 8 /* or 4 */ + +#ifdef __USE_BSD +/* operations for bsd flock(), also used by the kernel implementation */ +# define LOCK_SH 1 /* shared lock */ +# define LOCK_EX 2 /* exclusive lock */ +# define LOCK_NB 4 /* or'd with one of the above to prevent + blocking */ +# define LOCK_UN 8 /* remove lock */ +#endif + +#ifdef __USE_GNU +/* Types of directory notifications that may be requested with F_NOTIFY. */ +# define DN_ACCESS 0x00000001 /* File accessed. */ +# define DN_MODIFY 0x00000002 /* File modified. */ +# define DN_CREATE 0x00000004 /* File created. */ +# define DN_DELETE 0x00000008 /* File removed. */ +# define DN_RENAME 0x00000010 /* File renamed. */ +# define DN_ATTRIB 0x00000020 /* File changed attibutes. */ +# define DN_MULTISHOT 0x80000000 /* Don't remove notifier. */ +#endif + +struct flock + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ +#ifndef __USE_FILE_OFFSET64 + __off_t l_start; /* Offset where the lock begins. */ + __off_t l_len; /* Size of the locked area; zero means until EOF. */ +#else + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ +#endif + __pid_t l_pid; /* Process holding the lock. */ + }; + +#ifdef __USE_LARGEFILE64 +struct flock64 + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ + __pid_t l_pid; /* Process holding the lock. */ + }; +#endif + +/* Define some more compatibility macros to be backward compatible with + BSD systems which did not managed to hide these kernel macros. */ +#ifdef __USE_BSD +# define FAPPEND O_APPEND +# define FFSYNC O_FSYNC +# define FASYNC O_ASYNC +# define FNONBLOCK O_NONBLOCK +# define FNDELAY O_NDELAY +#endif /* Use BSD. */ + +/* Advise to `posix_fadvise'. */ +#ifdef __USE_XOPEN2K +# define POSIX_FADV_NORMAL 0 /* No further special treatment. */ +# define POSIX_FADV_RANDOM 1 /* Expect random page references. */ +# define POSIX_FADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define POSIX_FADV_WILLNEED 3 /* Will need these pages. */ +# define POSIX_FADV_DONTNEED 4 /* Don't need these pages. */ +# define POSIX_FADV_NOREUSE 5 /* Data will be accessed once. */ +#endif + + +#if defined __USE_GNU && defined __UCLIBC_LINUX_SPECIFIC__ +/* Flags for SYNC_FILE_RANGE. */ +# define SYNC_FILE_RANGE_WAIT_BEFORE 1 /* Wait upon writeout of all pages + in the range before performing the + write. */ +# define SYNC_FILE_RANGE_WRITE 2 /* Initiate writeout of all those + dirty pages in the range which are + not presently under writeback. */ +# define SYNC_FILE_RANGE_WAIT_AFTER 4 /* Wait upon writeout of all pages in + the range after performing the + write. */ + +/* Flags for SPLICE and VMSPLICE. */ +# define SPLICE_F_MOVE 1 /* Move pages instead of copying. */ +# define SPLICE_F_NONBLOCK 2 /* Don't block on the pipe splicing + (but we may still block on the fd + we splice from/to). */ +# define SPLICE_F_MORE 4 /* Expect more data. */ +# define SPLICE_F_GIFT 8 /* Pages passed in are a gift. */ +#endif + +__BEGIN_DECLS + +#if defined __USE_GNU && defined __UCLIBC_LINUX_SPECIFIC__ + +/* Provide kernel hint to read ahead. */ +extern ssize_t readahead (int __fd, __off64_t __offset, size_t __count) + __THROW; + + +/* Selective file content synch'ing. */ +extern int sync_file_range (int __fd, __off64_t __from, __off64_t __to, + unsigned int __flags); + +/* Splice address range into a pipe. */ +extern ssize_t vmsplice (int __fdout, const struct iovec *__iov, + size_t __count, unsigned int __flags); + +/* Splice two files together. */ +extern ssize_t splice (int __fdin, __off64_t *__offin, int __fdout, + __off64_t *__offout, size_t __len, + unsigned int __flags); + +/* In-kernel implementation of tee for pipe buffers. */ +extern ssize_t tee (int __fdin, int __fdout, size_t __len, + unsigned int __flags); + +#endif +__END_DECLS + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/bits/fenv.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/bits/fenv.h new file mode 100644 index 00000000..c5f8c434 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/bits/fenv.h @@ -0,0 +1,78 @@ +/* Copyright (C) 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by David Huggins-Daines + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FENV_H +# error "Never use directly; include instead." +#endif + +/* Define bits representing the exception. We use the values of the + appropriate enable bits in the FPU status word (which, + coincidentally, are the same as the flag bits, but shifted right by + 27 bits). */ +enum +{ + FE_INVALID = 1<<4, /* V */ +#define FE_INVALID FE_INVALID + FE_DIVBYZERO = 1<<3, /* Z */ +#define FE_DIVBYZERO FE_DIVBYZERO + FE_OVERFLOW = 1<<2, /* O */ +#define FE_OVERFLOW FE_OVERFLOW + FE_UNDERFLOW = 1<<1, /* U */ +#define FE_UNDERFLOW FE_UNDERFLOW + FE_INEXACT = 1<<0, /* I */ +#define FE_INEXACT FE_INEXACT +}; + +#define FE_ALL_EXCEPT \ + (FE_INEXACT | FE_DIVBYZERO | FE_UNDERFLOW | FE_OVERFLOW | FE_INVALID) + +/* The PA-RISC FPU supports all of the four defined rounding modes. + We use the values of the RM field in the floating point status + register for the appropriate macros. */ +enum + { + FE_TONEAREST = 0 << 9, +#define FE_TONEAREST FE_TONEAREST + FE_TOWARDZERO = 1 << 9, +#define FE_TOWARDZERO FE_TOWARDZERO + FE_UPWARD = 2 << 9, +#define FE_UPWARD FE_UPWARD + FE_DOWNWARD = 3 << 9, +#define FE_DOWNWARD FE_DOWNWARD + }; + +/* Type representing exception flags. */ +typedef unsigned int fexcept_t; + +/* Type representing floating-point environment. This structure + corresponds to the layout of the status and exception words in the + register file. */ +typedef struct +{ + unsigned int __status_word; + unsigned int __exception[7]; +} fenv_t; + +/* If the default argument is used we use this value. */ +#define FE_DFL_ENV ((fenv_t *) -1) + +#ifdef __USE_GNU +/* Floating-point environment where none of the exceptions are masked. */ +# define FE_NOMASK_ENV ((fenv_t *) -2) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/bits/ipc.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/bits/ipc.h new file mode 100644 index 00000000..d80cf069 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/bits/ipc.h @@ -0,0 +1,63 @@ +/* Copyright (C) 1995-1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_IPC_H +# error "Never use directly; include instead." +#endif + +#include +#include + +/* Mode bits for `msgget', `semget', and `shmget'. */ +#define IPC_CREAT 01000 /* Create key if key does not exist. */ +#define IPC_EXCL 02000 /* Fail if key exists. */ +#define IPC_NOWAIT 04000 /* Return error on wait. */ + +/* Control commands for `msgctl', `semctl', and `shmctl'. */ +#define IPC_RMID 0 /* Remove identifier. */ +#define IPC_SET 1 /* Set `ipc_perm' options. */ +#define IPC_STAT 2 /* Get `ipc_perm' options. */ +#ifdef __USE_GNU +# define IPC_INFO 3 /* See ipcs. */ +#endif + +/* Special key values. */ +#define IPC_PRIVATE ((__key_t) 0) /* Private key. */ + + +/* Data structure used to pass permission information to IPC operations. */ +struct ipc_perm + { + __key_t __key; /* Key. */ + __uid_t uid; /* Owner's user ID. */ + __gid_t gid; /* Owner's group ID. */ + __uid_t cuid; /* Creator's user ID. */ + __gid_t cgid; /* Creator's group ID. */ +#if __WORDSIZE == 32 + unsigned short int __pad1; + unsigned short int mode; /* Read/write permission. */ + unsigned short int __pad2; +#else + __mode_t mode; /* Read/write permission. */ + unsigned short int __pad2; +#endif + unsigned short int __seq; /* Sequence number. */ + unsigned int __pad3; + unsigned long long int __unused1; + unsigned long long int __unused2; + }; diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/bits/kernel_sigaction.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/bits/kernel_sigaction.h new file mode 100644 index 00000000..1c093a52 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/bits/kernel_sigaction.h @@ -0,0 +1,23 @@ +#ifndef _BITS_SIGACTION_STRUCT_H +#define _BITS_SIGACTION_STRUCT_H + +/* We have a separate header file here because we do not support + SA_RESTORER on hppa. */ + +/* This is the sigaction struction from the Linux 2.1.20 kernel. */ +/* Blah. This is bogus. We don't ever use it. */ +struct old_kernel_sigaction { + __sighandler_t k_sa_handler; + unsigned long sa_mask; + unsigned long sa_flags; +}; + +/* In uclibc, userspace struct sigaction is identical to + * "new" struct kernel_sigaction (one from the Linux 2.1.68 kernel). + * See sigaction.h + */ + +extern int __syscall_rt_sigaction (int, const struct sigaction *, + struct sigaction *, size_t) attribute_hidden; + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/bits/kernel_stat.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/bits/kernel_stat.h new file mode 100644 index 00000000..d33a7e72 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/bits/kernel_stat.h @@ -0,0 +1,64 @@ +/* Ripped from linux/include/asm-parisc/stat.h + * and renamed 'struct stat' to 'struct kernel_stat' */ + +#ifndef _PARISC_STAT_H +#define _PARISC_STAT_H + +#ifndef _LIBC +#error bits/kernel_stat.h is for internal uClibc use only! +#endif + +struct kernel_stat { + unsigned int st_dev; /* dev_t is 32 bits on parisc */ + ino_t st_ino; /* 32 bits */ + mode_t st_mode; /* 16 bits */ + nlink_t st_nlink; /* 16 bits */ + unsigned short st_reserved1; /* old st_uid */ + unsigned short st_reserved2; /* old st_gid */ + unsigned int st_rdev; + off_t st_size; + struct timespec st_atim; + struct timespec st_mtim; + struct timespec st_ctim; + int st_blksize; + int st_blocks; + unsigned int __unused1; /* ACL stuff */ + unsigned int __unused2; /* network */ + ino_t __unused3; /* network */ + unsigned int __unused4; /* cnodes */ + unsigned short __unused5; /* netsite */ + short st_fstype; + unsigned int st_realdev; + unsigned short st_basemode; + unsigned short st_spareshort; + uid_t st_uid; + gid_t st_gid; + unsigned int st_spare4[3]; +}; + +/* This is the struct that 32-bit userspace applications are expecting. + * How 64-bit apps are going to be compiled, I have no idea. But at least + * this way, we don't have a wrapper in the kernel. + */ +struct kernel_stat64 { + unsigned long long st_dev; + unsigned int __pad1; + + unsigned int __st_ino; /* Not actually filled in */ + unsigned int st_mode; + unsigned int st_nlink; + unsigned int st_uid; + unsigned int st_gid; + unsigned long long st_rdev; + unsigned int __pad2; + signed long long st_size; + signed int st_blksize; + + signed long long st_blocks; + struct timespec st_atim; + struct timespec st_mtim; + struct timespec st_ctim; + unsigned long long st_ino; +}; + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/bits/kernel_types.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/bits/kernel_types.h new file mode 100644 index 00000000..4441f9b2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/bits/kernel_types.h @@ -0,0 +1,61 @@ +/* Note that we use the exact same include guard #define names + * as asm/posix_types.h. This will avoid gratuitous conflicts + * with the posix_types.h kernel header, and will ensure that + * our private content, and not the kernel header, will win. + * -Erik + */ +#ifndef __ARCH_PARISC_POSIX_TYPES_H +#define __ARCH_PARISC_POSIX_TYPES_H + +typedef unsigned long __kernel_dev_t; +typedef unsigned long __kernel_ino_t; +typedef unsigned short __kernel_mode_t; +typedef unsigned short __kernel_nlink_t; +typedef long __kernel_off_t; +typedef int __kernel_pid_t; +typedef unsigned short __kernel_ipc_pid_t; +typedef unsigned int __kernel_uid_t; +typedef unsigned int __kernel_gid_t; +typedef int __kernel_suseconds_t; +typedef long __kernel_clock_t; +typedef int __kernel_timer_t; +typedef int __kernel_clockid_t; +typedef int __kernel_daddr_t; +/* Note these change from narrow to wide kernels */ +#ifdef __LP64__ +typedef unsigned long __kernel_size_t; +typedef long __kernel_ssize_t; +typedef long __kernel_ptrdiff_t; +typedef long __kernel_time_t; +#else +typedef unsigned int __kernel_size_t; +typedef int __kernel_ssize_t; +typedef int __kernel_ptrdiff_t; +typedef long __kernel_time_t; +#endif +typedef char * __kernel_caddr_t; + +typedef unsigned short __kernel_uid16_t; +typedef unsigned short __kernel_gid16_t; +typedef unsigned int __kernel_uid32_t; +typedef unsigned int __kernel_gid32_t; + +typedef long long __kernel_loff_t; +typedef long long __kernel_off64_t; +typedef unsigned long long __kernel_ino64_t; + +typedef unsigned int __kernel_old_dev_t; + +typedef struct { +#ifdef __USE_ALL + int val[2]; +#else + int __val[2]; +#endif +} __kernel_fsid_t; + +/* compatibility stuff */ +typedef __kernel_uid_t __kernel_old_uid_t; +typedef __kernel_gid_t __kernel_old_gid_t; + +#endif /* __ARCH_PARISC_POSIX_TYPES_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/bits/mman.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/bits/mman.h new file mode 100644 index 00000000..7f9bf4ed --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/bits/mman.h @@ -0,0 +1,94 @@ +/* Definitions for POSIX memory map interface. Linux/HPPA version. + Copyright (C) 1997, 1998, 2000, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_MMAN_H +# error "Never use directly; include instead." +#endif + +/* these are basically taken from the kernel definitions */ + +#define PROT_READ 0x1 /* page can be read */ +#define PROT_WRITE 0x2 /* page can be written */ +#define PROT_EXEC 0x4 /* page can be executed */ +#define PROT_NONE 0x0 /* page can not be accessed */ +#define PROT_GROWSDOWN 0x01000000 /* Extend change to start of + growsdown vma (mprotect only). */ +#define PROT_GROWSUP 0x02000000 /* Extend change to start of + growsup vma (mprotect only). */ + +#define MAP_SHARED 0x01 /* Share changes */ +#define MAP_PRIVATE 0x02 /* Changes are private */ +#define MAP_TYPE 0x03 /* Mask for type of mapping */ +#define MAP_FIXED 0x04 /* Interpret addr exactly */ +#define MAP_ANONYMOUS 0x10 /* don't use a file */ + +#define MAP_DENYWRITE 0x0800 /* ETXTBSY */ +#define MAP_EXECUTABLE 0x1000 /* mark it as an executable */ +#define MAP_LOCKED 0x2000 /* pages are locked */ +#define MAP_NORESERVE 0x4000 /* don't check for reservations */ +#define MAP_GROWSDOWN 0x8000 /* stack-like segment */ +#define MAP_POPULATE 0x10000 /* populate (prefault) pagetables */ +#define MAP_NONBLOCK 0x20000 /* do not block on IO */ +#define MAP_UNINITIALIZE 0x4000000 /* For anonymous mmap, memory could + be uninitialized. */ + +#define MS_SYNC 1 /* synchronous memory sync */ +#define MS_ASYNC 2 /* sync memory asynchronously */ +#define MS_INVALIDATE 4 /* invalidate the caches */ + +#define MCL_CURRENT 1 /* lock all current mappings */ +#define MCL_FUTURE 2 /* lock all future mappings */ + +/* Advice to "madvise" */ +#ifdef __USE_BSD +# define MADV_NORMAL 0 /* no further special treatment */ +# define MADV_RANDOM 1 /* expect random page references */ +# define MADV_SEQUENTIAL 2 /* expect sequential page references */ +# define MADV_WILLNEED 3 /* will need these pages */ +# define MADV_DONTNEED 4 /* dont need these pages */ +# define MADV_SPACEAVAIL 5 /* insure that resources are reserved */ +# define MADV_VPS_PURGE 6 /* Purge pages from VM page cache */ +# define MADV_VPS_INHERIT 7 /* Inherit parents page size */ +# define MADV_REMOVE 9 /* Remove these pages and resources. */ +# define MADV_DONTFORK 10 /* Do not inherit across fork. */ +# define MADV_DOFORK 11 /* Do inherit across fork. */ +#endif + +/* The range 12-64 is reserved for page size specification. */ +#define MADV_4K_PAGES 12 /* Use 4K pages */ +#define MADV_16K_PAGES 14 /* Use 16K pages */ +#define MADV_64K_PAGES 16 /* Use 64K pages */ +#define MADV_256K_PAGES 18 /* Use 256K pages */ +#define MADV_1M_PAGES 20 /* Use 1 Megabyte pages */ +#define MADV_4M_PAGES 22 /* Use 4 Megabyte pages */ +#define MADV_16M_PAGES 24 /* Use 16 Megabyte pages */ +#define MADV_64M_PAGES 26 /* Use 64 Megabyte pages */ + +/* compatibility flags */ +#define MAP_ANON MAP_ANONYMOUS +#define MAP_FILE 0 +#define MAP_VARIABLE 0 + +/* Flags for `mremap'. */ +#ifdef __USE_GNU +# define MREMAP_MAYMOVE 1 +# define MREMAP_FIXED 2 +#endif + + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/bits/setjmp.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/bits/setjmp.h new file mode 100644 index 00000000..4395b8f5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/bits/setjmp.h @@ -0,0 +1,45 @@ +/* Copyright (C) 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Define the machine-dependent type `jmp_buf'. HPPA version. */ +#ifndef _BITS_SETJMP_H +#define _BITS_SETJMP_H 1 + +#if !defined _SETJMP_H && !defined _PTHREAD_H +# error "Never include directly; use instead." +#endif + +/* The previous bits/setjmp.h had __jmp_buf defined as a structure. + We use an array of 'double' instead, to make writing the assembler + easier, and to ensure proper alignment. Naturally, user code should + not depend on either representation. */ + +#if defined __USE_MISC || defined _ASM +#define JB_SP (76/4) +#endif + +#ifndef _ASM +typedef double __jmp_buf[21]; +#endif + +/* Test if longjmp to JMPBUF would unwind the frame containing a local + variable at ADDRESS. */ +#define _JMPBUF_UNWINDS(_jmpbuf, _address) \ + ((void *)(_address) > (void *)(((unsigned long *) _jmpbuf)[JB_SP])) + +#endif /* bits/setjmp.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/bits/sigaction.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/bits/sigaction.h new file mode 100644 index 00000000..3dac69e7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/bits/sigaction.h @@ -0,0 +1,66 @@ +/* Definitions for Linux/HPPA sigaction. + Copyright (C) 1996, 1997, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SIGNAL_H +# error "Never include directly; use instead." +#endif + +/* Structure describing the action to be taken when a signal arrives. */ +struct sigaction { +#ifdef __USE_POSIX199309 + union { + __sighandler_t sa_handler; + void (*sa_sigaction)(int, siginfo_t *, void *); + } __sigaction_handler; +# define sa_handler __sigaction_handler.sa_handler +# define sa_sigaction __sigaction_handler.sa_sigaction +#else + __sighandler_t sa_handler; +#endif + unsigned long sa_flags; + sigset_t sa_mask; + /* HPPA has no sa_restorer field. */ +}; + +/* Bits in `sa_flags'. */ + +#define SA_NOCLDSTOP 0x00000008 /* Don't send SIGCHLD when children stop. */ +#define SA_NOCLDWAIT 0x00000080 /* Don't create zombie on child death. */ +#define SA_SIGINFO 0x00000010 /* Invoke signal-catching function with + three arguments instead of one. */ +#if defined __USE_UNIX98 || defined __USE_MISC +# define SA_ONSTACK 0x00000001 /* Use signal stack by using `sa_restorer'. */ +# define SA_RESETHAND 0x00000004 /* Reset to SIG_DFL on entry to handler. */ +# define SA_NODEFER 0x00000020 /* Don't automatically block the signal + when its handler is being executed. */ +# define SA_RESTART 0x00000040 /* Restart syscall on signal return. */ +#endif +#ifdef __USE_MISC +# define SA_INTERRUPT 0x20000000 /* Historic no-op. */ + +/* Some aliases for the SA_ constants. */ +# define SA_NOMASK SA_NODEFER +# define SA_ONESHOT SA_RESETHAND +# define SA_STACK SA_ONSTACK +#endif + +/* Values for the HOW argument to `sigprocmask'. */ +#define SIG_BLOCK 0 /* for blocking signals */ +#define SIG_UNBLOCK 1 /* for unblocking signals */ +#define SIG_SETMASK 2 /* for setting the signal mask */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/bits/signum.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/bits/signum.h new file mode 100644 index 00000000..d1d0f38b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/bits/signum.h @@ -0,0 +1,62 @@ +/* Signal number definitions. Linux/HPPA version. + Copyright (C) 1995,1996,1997,1998,1999,2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifdef _SIGNAL_H + +#define SIGHUP 1 /* Hangup (POSIX). */ +#define SIGINT 2 /* Interrupt (ANSI). */ +#define SIGQUIT 3 /* Quit (POSIX). */ +#define SIGILL 4 /* Illegal instruction (ANSI). */ +#define SIGTRAP 5 /* Trace trap (POSIX). */ +#define SIGABRT 6 /* Abort (ANSI). */ +#define SIGIOT 6 /* IOT trap (4.2 BSD). */ +#define SIGEMT 7 +#define SIGFPE 8 /* Floating-point exception (ANSI). */ +#define SIGKILL 9 /* Kill, unblockable (POSIX). */ +#define SIGBUS 10 /* BUS error (4.2 BSD). */ +#define SIGSEGV 11 /* Segmentation violation (ANSI). */ +#define SIGSYS 12 /* Bad system call. */ +#define SIGPIPE 13 /* Broken pipe (POSIX). */ +#define SIGALRM 14 /* Alarm clock (POSIX). */ +#define SIGTERM 15 /* Termination (ANSI). */ +#define SIGUSR1 16 /* User-defined signal 1 (POSIX). */ +#define SIGUSR2 17 /* User-defined signal 2 (POSIX). */ +#define SIGCLD SIGCHLD /* Same as SIGCHLD (System V). */ +#define SIGCHLD 18 /* Child status has changed (POSIX). */ +#define SIGPWR 19 /* Power failure restart (System V). */ +#define SIGVTALRM 20 /* Virtual alarm clock (4.2 BSD). */ +#define SIGPROF 21 /* Profiling alarm clock (4.2 BSD). */ +#define SIGPOLL SIGIO /* Pollable event occurred (System V). */ +#define SIGIO 22 /* I/O now possible (4.2 BSD). */ +#define SIGWINCH 23 /* Window size change (4.3 BSD, Sun). */ +#define SIGSTOP 24 /* Stop, unblockable (POSIX). */ +#define SIGTSTP 25 /* Keyboard stop (POSIX). */ +#define SIGCONT 26 /* Continue (POSIX). */ +#define SIGTTIN 27 /* Background read from tty (POSIX). */ +#define SIGTTOU 28 /* Background write to tty (POSIX). */ +#define SIGURG 29 /* Urgent condition on socket (4.2 BSD). */ +#define SIGLOST 30 /* Operating System Has Lost (HP/UX). */ +#define SIGUNUSED 31 +#define SIGXCPU 33 /* CPU limit exceeded (4.2 BSD). */ +#define SIGXFSZ 34 /* File size limit exceeded (4.2 BSD). */ +#define SIGSTKFLT 36 /* Stack fault. */ + +#define __SIGRTMIN 37 + +#endif /* included. */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/bits/stackinfo.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/bits/stackinfo.h new file mode 100644 index 00000000..318de714 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/bits/stackinfo.h @@ -0,0 +1,28 @@ +/* Copyright (C) 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This file contains a bit of information about the stack allocation + of the processor. */ + +#ifndef _STACKINFO_H +#define _STACKINFO_H 1 + +/* On PA the stack grows up. */ +#define _STACK_GROWS_UP 1 + +#endif /* stackinfo.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/bits/syscalls.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/bits/syscalls.h new file mode 100644 index 00000000..783ed324 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/bits/syscalls.h @@ -0,0 +1,98 @@ +#ifndef _BITS_SYSCALLS_H +#define _BITS_SYSCALLS_H +#ifndef _SYSCALL_H +# error "Never use directly; include instead." +#endif + +#ifndef __ASSEMBLER__ + +/* Assume all syscalls are done from PIC code just to be + * safe. The worst case scenario is that you lose a register + * and save/restore r19 across the syscall. */ +#define PIC + +/* Definition taken from glibc 2.3.3 + * sysdeps/unix/sysv/linux/hppa/sysdep.h + */ + +#ifdef PIC +/* WARNING: CANNOT BE USED IN A NOP! */ +# define K_STW_ASM_PIC " copy %%r19, %%r4\n" +# define K_LDW_ASM_PIC " copy %%r4, %%r19\n" +# define K_USING_GR4 "%r4", +#else +# define K_STW_ASM_PIC " \n" +# define K_LDW_ASM_PIC " \n" +# define K_USING_GR4 +#endif + +/* GCC has to be warned that a syscall may clobber all the ABI + registers listed as "caller-saves", see page 8, Table 2 + in section 2.2.6 of the PA-RISC RUN-TIME architecture + document. However! r28 is the result and will conflict with + the clobber list so it is left out. Also the input arguments + registers r20 -> r26 will conflict with the list so they + are treated specially. Although r19 is clobbered by the syscall + we cannot say this because it would violate ABI, thus we say + r4 is clobbered and use that register to save/restore r19 + across the syscall. */ + +#define K_CALL_CLOB_REGS "%r1", "%r2", K_USING_GR4 \ + "%r20", "%r29", "%r31" + +#define INTERNAL_SYSCALL_NCS(name, err, nr, args...) ({ \ + register unsigned long __res __asm__("r28"); \ + K_LOAD_ARGS_##nr(args) \ + /* FIXME: HACK stw/ldw r19 around syscall */ \ + __asm__ __volatile__( \ + K_STW_ASM_PIC \ + " ble 0x100(%%sr2, %%r0)\n" \ + " ldi %1, %%r20\n" \ + K_LDW_ASM_PIC \ + : "=r" (__res) \ + : "i" (name) K_ASM_ARGS_##nr \ + : "memory", K_CALL_CLOB_REGS K_CLOB_ARGS_##nr \ + ); \ + __res; \ +}) + +#define K_LOAD_ARGS_0() +#define K_LOAD_ARGS_1(r26) \ + register unsigned long __r26 __asm__("r26") = (unsigned long)(r26); \ + K_LOAD_ARGS_0() +#define K_LOAD_ARGS_2(r26,r25) \ + register unsigned long __r25 __asm__("r25") = (unsigned long)(r25); \ + K_LOAD_ARGS_1(r26) +#define K_LOAD_ARGS_3(r26,r25,r24) \ + register unsigned long __r24 __asm__("r24") = (unsigned long)(r24); \ + K_LOAD_ARGS_2(r26,r25) +#define K_LOAD_ARGS_4(r26,r25,r24,r23) \ + register unsigned long __r23 __asm__("r23") = (unsigned long)(r23); \ + K_LOAD_ARGS_3(r26,r25,r24) +#define K_LOAD_ARGS_5(r26,r25,r24,r23,r22) \ + register unsigned long __r22 __asm__("r22") = (unsigned long)(r22); \ + K_LOAD_ARGS_4(r26,r25,r24,r23) +#define K_LOAD_ARGS_6(r26,r25,r24,r23,r22,r21) \ + register unsigned long __r21 __asm__("r21") = (unsigned long)(r21); \ + K_LOAD_ARGS_5(r26,r25,r24,r23,r22) + +/* Even with zero args we use r20 for the syscall number */ +#define K_ASM_ARGS_0 +#define K_ASM_ARGS_1 K_ASM_ARGS_0, "r" (__r26) +#define K_ASM_ARGS_2 K_ASM_ARGS_1, "r" (__r25) +#define K_ASM_ARGS_3 K_ASM_ARGS_2, "r" (__r24) +#define K_ASM_ARGS_4 K_ASM_ARGS_3, "r" (__r23) +#define K_ASM_ARGS_5 K_ASM_ARGS_4, "r" (__r22) +#define K_ASM_ARGS_6 K_ASM_ARGS_5, "r" (__r21) + +/* The registers not listed as inputs but clobbered */ +#define K_CLOB_ARGS_6 +#define K_CLOB_ARGS_5 K_CLOB_ARGS_6, "%r21" +#define K_CLOB_ARGS_4 K_CLOB_ARGS_5, "%r22" +#define K_CLOB_ARGS_3 K_CLOB_ARGS_4, "%r23" +#define K_CLOB_ARGS_2 K_CLOB_ARGS_3, "%r24" +#define K_CLOB_ARGS_1 K_CLOB_ARGS_2, "%r25" +#define K_CLOB_ARGS_0 K_CLOB_ARGS_1, "%r26" + +#endif /* __ASSEMBLER__ */ +#endif /* _BITS_SYSCALLS_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/bits/uClibc_arch_features.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/bits/uClibc_arch_features.h new file mode 100644 index 00000000..722447da --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/bits/uClibc_arch_features.h @@ -0,0 +1,47 @@ +/* + * Track misc arch-specific features that aren't config options + */ + +#ifndef _BITS_UCLIBC_ARCH_FEATURES_H +#define _BITS_UCLIBC_ARCH_FEATURES_H + +/* instruction used when calling abort() to kill yourself */ +#define __UCLIBC_ABORT_INSTRUCTION__ "iitlbp %r0,(%sr0,%r0)" + +/* can your target use syscall6() for mmap ? */ +#undef __UCLIBC_MMAP_HAS_6_ARGS__ + +/* does your target use syscall4() for truncate64 ? (32bit arches only) */ +#undef __UCLIBC_TRUNCATE64_HAS_4_ARGS__ + +/* does your target have a broken create_module() ? */ +#undef __UCLIBC_BROKEN_CREATE_MODULE__ + +/* does your target have to worry about older [gs]etrlimit() ? */ +#undef __UCLIBC_HANDLE_OLDER_RLIMIT__ + +/* does your target have an asm .set ? */ +#define __UCLIBC_HAVE_ASM_SET_DIRECTIVE__ + +/* define if target doesn't like .global */ +#undef __UCLIBC_ASM_GLOBAL_DIRECTIVE__ + +/* define if target supports .weak */ +#define __UCLIBC_HAVE_ASM_WEAK_DIRECTIVE__ + +/* define if target supports .weakext */ +#undef __UCLIBC_HAVE_ASM_WEAKEXT_DIRECTIVE__ + +/* needed probably only for ppc64 */ +#undef __UCLIBC_HAVE_ASM_GLOBAL_DOT_NAME__ + +/* define if target supports CFI pseudo ops */ +#undef __UCLIBC_HAVE_ASM_CFI_DIRECTIVES__ + +/* define if target supports IEEE signed zero floats */ +#define __UCLIBC_HAVE_SIGNED_ZERO__ + +/* the default ; is a comment on hppa */ +#define __UCLIBC_ASM_LINE_SEP__ ! + +#endif /* _BITS_UCLIBC_ARCH_FEATURES_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/bits/wordsize.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/bits/wordsize.h new file mode 100644 index 00000000..951e8389 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/bits/wordsize.h @@ -0,0 +1,7 @@ +/* Determine the wordsize from the preprocessor defines. */ + +#ifdef __LP64__ +# define __WORDSIZE 64 +#else +# define __WORDSIZE 32 +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/brk.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/brk.c new file mode 100644 index 00000000..10e1fc8b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/brk.c @@ -0,0 +1,42 @@ +/* brk system call for Linux/HPPA. + Copyright (C) 1995, 1996, 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +/* This must be initialized data because commons can't have aliases. */ +void *__curbrk attribute_hidden = 0; + +int +brk (void *addr) +{ + void *newbrk; + + __curbrk = newbrk = (void *) INLINE_SYSCALL (brk, 1, addr); + + if (newbrk < addr) + { + __set_errno (ENOMEM); + return -1; + } + + return 0; +} +libc_hidden_def(brk) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/bsd-_setjmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/bsd-_setjmp.S new file mode 100644 index 00000000..30e53f56 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/bsd-_setjmp.S @@ -0,0 +1,36 @@ +/* BSD `_setjmp' entry point to `sigsetjmp (..., 0)'. HPPA version. + Copyright (C) 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This just does a tail-call to `__sigsetjmp (ARG, 1)'. + We cannot do it in C because it must be a tail-call, so frame-unwinding + in setjmp doesn't clobber the state restored by longjmp. */ + + .text + .align 4 + .globl _setjmp + .export _setjmp, code + .level 2.0 + .proc + .callinfo + .import __sigsetjmp +_setjmp: + b __sigsetjmp + ldi 0, %r25 + + .procend diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/bsd-setjmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/bsd-setjmp.S new file mode 100644 index 00000000..04ddba46 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/bsd-setjmp.S @@ -0,0 +1,36 @@ +/* BSD `setjmp' entry point to `sigsetjmp (..., 1)'. HPPA version. + Copyright (C) 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This just does a tail-call to `__sigsetjmp (ARG, 1)'. + We cannot do it in C because it must be a tail-call, so frame-unwinding + in setjmp doesn't clobber the state restored by longjmp. */ + + .text + .align 4 + .globl setjmp + .export setjmp, code + .level 2.0 + .proc + .callinfo + .import __sigsetjmp +setjmp: + b __sigsetjmp + ldi 1, %r25 + + .procend diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/clone.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/clone.S new file mode 100644 index 00000000..b8e354cd --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/clone.S @@ -0,0 +1,135 @@ +/* Copyright (C) 1996, 1997, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by David Huggins-Daines , 2000. + Based on the Alpha version by Richard Henderson , 1996. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* clone() is even more special than fork() as it mucks with stacks + and invokes a function in the right context after its all over. */ + +#include +#define _ERRNO_H 1 +#include +#include + +/* Non-thread code calls __clone with the following parameters: + int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg) + + NPTL Code will call __clone with the following parameters: + int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg, + int *parent_tidptr, struct user_desc *newtls, int *child_pidptr) + + The code should not mangle the extra input registers. + Syscall expects: Input to __clone: + 4(r25) - function pointer (r26, arg0) + 0(r25) - argument (r23, arg3) + r26 - clone flags. (r24, arg2) + r25+64 - user stack pointer. (r25, arg1) + r24 - parent tid pointer. (stack - 52) + r23 - struct user_desc newtls pointer. (stack - 56) + r22 - child tid pointer. (stack - 60) + r20 - clone syscall number (constant) + */ + +.text +.global __clone +.type __clone,%function +__clone: + + /* Sanity check arguments. */ + ldi -EINVAL,%ret0 + comib,=,n 0,%arg0,.Lerror /* no NULL function pointers */ + comib,=,n 0,%arg1,.Lerror /* no NULL stack pointers */ + + /* Save the fn ptr and arg on the new stack. */ + stwm %r26,64(%r25) + stw %r23,-60(%r25) + /* Clone arguments are (int flags, void * child_stack) */ + copy %r24,%r26 /* flags are first */ + /* User stack pointer is in the correct register already */ + + /* Load args from stack... */ + ldw -52(%sp), %r24 /* Load parent_tidptr */ + ldw -56(%sp), %r23 /* Load newtls */ + ldw -60(%sp), %r22 /* Load child_tidptr */ + + /* Create frame to get r3 free */ + copy %sp, %r21 + stwm %r3, 64(%sp) + stw %r21, -4(%sp) + + /* Save the PIC register. */ +#ifdef __PIC__ + copy %r19, %r3 /* parent */ +#endif + + /* Do the system call */ + ble 0x100(%sr2,%r0) + ldi __NR_clone,%r20 + + ldi -4096,%r1 + comclr,>>= %r1,%ret0,%r0 /* Note: unsigned compare. */ + b,n .LerrorRest + + comib,=,n 0,%ret0,thread_start + + /* Successful return from the parent + No need to restore the PIC register, + since we return immediately. */ + + bv %r0(%rp) + ldwm -64(%sp), %r3 + +.LerrorRest: + /* Restore the PIC register on error */ +#ifdef __PIC__ + copy %r3, %r19 /* parent */ +#endif + + /* Something bad happened -- no child created */ +.Lerror: + + /* Set errno, save ret0 so we return with that value. */ + copy %ret0, %r3 + b __syscall_error + sub %r0,%ret0,%arg0 + copy %r3, %ret0 + /* Return after setting errno, and restoring ret0 */ + bv %r0(%rp) + ldwm -64(%sp), %r3 + +thread_start: + + /* Load up the arguments. */ + ldw -60(%sr0, %sp),%arg0 + ldw -64(%sr0, %sp),%r22 + + /* $$dyncall fixes childs PIC register */ + + /* Call the user's function */ + bl $$dyncall,%r31 + copy %r31,%rp + + bl HIDDEN_JUMPTARGET(_exit),%rp + copy %ret0,%arg0 + + /* Die horribly. */ + iitlbp %r0,(%sr0,%r0) + +.size clone,.-clone + +weak_alias (__clone, clone) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/crt1.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/crt1.S new file mode 100644 index 00000000..8b42dacd --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/crt1.S @@ -0,0 +1,126 @@ +/* ELF startup code for HPPA. + Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file with other + programs, and to distribute those programs without any restriction + coming from the use of this file. (The GNU Lesser General Public + License restrictions do apply in other respects; for example, they + cover modification of the file, and distribution when not linked + into another program.) + + Note that people who make modified versions of this file are not + obligated to grant this special exception for their modified + versions; it is their choice whether to do so. The GNU Lesser + General Public License gives permission to release a modified + version without this exception; this exception also makes it + possible to release a modified version which carries forward this + exception. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + + .import main, code + .import $global$, data + .import __uClibc_main, code +#if defined(__UCLIBC_CTOR_DTOR__) + .import _fini, code + .import _init, code +#else + .weak _fini + .weak _init +#endif + + /* Have the linker create plabel words + so we get PLABEL32 relocs and not 21/14 */ + .section .rodata + .align 4 +.Lpmain: + .word P%main +.Lp__uClibc_main: + .word P%__uClibc_main +.Lp_fini: + .word P%_fini +.Lp_init: + .word P%_init + + .text + .align 4 + .globl _start + .export _start, ENTRY + .type _start,@function +_start: + + .proc + .callinfo + + /* Expand the stack to store the 5th through 7th args */ + ldo 64(%sp), %sp + /* TODO: Follow ABI? Place more things on the stack here... */ + +#ifdef __PIC__ + /* load main (1st argument) */ + addil LR'.Lpmain, %r19 + ldw RR'.Lpmain(%r1), %r26 + ldw 0(%r26),%r26 + /* argc and argv should be in 25 and 24 (2nd and 3rd argument) */ + /* void (*init) (void) (4th argument) */ + addil LR'.Lp_init, %r19 + ldw RR'.Lp_init(%r1), %r23 + ldw 0(%r23), %r23 + /* void (*fini) (void) (5th argument) */ + addil LR'.Lp_fini, %r19 + ldw RR'.Lp_fini(%r1), %r22 + ldw 0(%r22), %r22 +#else + /* load main (1st argument) */ + ldil LR'.Lpmain, %r26 + ldw RR'.Lpmain(%r26), %r26 + /* argc and argv should be in 25 and 24 (2nd and 3rd argument) */ + /* void (*init) (void) (4th argument) */ + ldil LR'.Lp_init, %r23 + ldw RR'.Lp_init(%r23), %r23 + /* void (*fini) (void) (5th argument) */ + ldil LR'.Lp_fini, %r22 + ldw RR'.Lp_fini(%r22), %r22 +#endif + /* Store 5th argument */ + stw %r22, -52(%sp) + /* void (*rtld_fini) (void) (6th argument) */ + stw %r23, -56(%sp) + /* void *stack_end (7th argument) */ + stw %sp, -60(%sp) + + /* load global */ + ldil L%$global$, %dp + ldo R%$global$(%dp), %dp + + bl __uClibc_main,%r2 + nop + /* die horribly if it returned (it shouldn't) */ + iitlbp %r0,(%sr0,%r0) + nop + + .procend + +/* Define a symbol for the first piece of initialized data. */ + .data + .globl __data_start +__data_start: + .long 0 + .weak data_start + data_start = __data_start diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/crti.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/crti.S new file mode 100644 index 00000000..9a37c718 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/crti.S @@ -0,0 +1,24 @@ +/* glibc's sysdeps/hppa/elf/initfini.c used for reference [PROLOG] */ + + .section .init + .align 4 + .globl _init + .type _init,@function +_init: + stw %rp,-20(%sp) + stwm %r4,64(%sp) + stw %r19,-32(%sp) + copy %r19,%r4 /* delay slot */ + copy %r4,%r19 + + + + .section .fini + .align 4 + .globl _fini + .type _fini,@function +_fini: + stw %rp,-20(%sp) + stwm %r4,64(%sp) + stw %r19,-32(%sp) + copy %r19,%r4 diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/crtn.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/crtn.S new file mode 100644 index 00000000..6602eced --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/crtn.S @@ -0,0 +1,34 @@ +/* glibc's sysdeps/hppa/elf/initfini.c used for reference [EPILOG] */ + + .text + .align 4 +/* Here is the tail end of _init. We put __gmon_start before this so + that the assembler creates the .PARISC.unwind section for us, ie. + with the right attributes. */ + .section .init + ldw -84(%sp),%rp + copy %r4,%r19 + bv %r0(%rp) +_end_init: + ldwm -64(%sp),%r4 + +/* Our very own unwind info, because the assembler can't handle + functions split into two or more pieces. */ + .section .PARISC.unwind + .extern _init + .word _init, _end_init + .byte 0x08, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08 + + + + .section .fini + ldw -84(%sp),%rp + copy %r4,%r19 + bv %r0(%rp) +_end_fini: + ldwm -64(%sp),%r4 + + .section .PARISC.unwind + .extern _fini + .word _fini, _end_fini + .byte 0x08, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08 diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/lshift.s b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/lshift.s new file mode 100644 index 00000000..151b283e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/lshift.s @@ -0,0 +1,66 @@ +;! HP-PA __mpn_lshift -- + +;! Copyright (C) 1992, 1994 Free Software Foundation, Inc. + +;! This file is part of the GNU MP Library. + +;! The GNU MP Library is free software; you can redistribute it and/or modify +;! it under the terms of the GNU Lesser General Public License as published by +;! the Free Software Foundation; either version 2.1 of the License, or (at your +;! option) any later version. + +;! The GNU MP Library is distributed in the hope that it will be useful, but +;! WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +;! or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public +;! License for more details. + +;! You should have received a copy of the GNU Lesser General Public License +;! along with the GNU MP Library; see the file COPYING.LIB. If not, write to +;! the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +;! MA 02111-1307, USA. + + +;! INPUT PARAMETERS +;! res_ptr gr26 +;! s_ptr gr25 +;! size gr24 +;! cnt gr23 + + .text + .export __mpn_lshift +__mpn_lshift: + .proc + .callinfo frame=64,no_calls + .entry + + sh2add %r24,%r25,%r25 + sh2add %r24,%r26,%r26 + ldws,mb -4(%r25),%r22 + subi 32,%r23,%r1 + mtsar %r1 + addib,= -1,%r24,L$0004 + vshd %r0,%r22,%r28 ;! compute carry out limb + ldws,mb -4(%r25),%r29 + addib,= -1,%r24,L$0002 + vshd %r22,%r29,%r20 + +L$loop: ldws,mb -4(%r25),%r22 + stws,mb %r20,-4(%r26) + addib,= -1,%r24,L$0003 + vshd %r29,%r22,%r20 + ldws,mb -4(%r25),%r29 + stws,mb %r20,-4(%r26) + addib,<> -1,%r24,L$loop + vshd %r22,%r29,%r20 + +L$0002: stws,mb %r20,-4(%r26) + vshd %r29,%r0,%r20 + bv 0(%r2) + stw %r20,-4(%r26) +L$0003: stws,mb %r20,-4(%r26) +L$0004: vshd %r22,%r0,%r20 + bv 0(%r2) + stw %r20,-4(%r26) + + .exit + .procend diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/mmap.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/mmap.c new file mode 100644 index 00000000..bb1352f9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/mmap.c @@ -0,0 +1,19 @@ +/* vi: set sw=4 ts=4: */ +/* + * mmap() for uClibc/x86_64 + * + * Copyright (C) 2000-2006 Erik Andersen + * Copyright (C) 2005 by Mike Frysinger + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include + + +_syscall6(void *, mmap, void *, start, size_t, length, int, prot, + int, flags, int, fd, off_t, offset) +libc_hidden_def(mmap) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/rshift.s b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/rshift.s new file mode 100644 index 00000000..dff189dc --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/rshift.s @@ -0,0 +1,63 @@ +;! HP-PA __mpn_rshift -- + +;! Copyright (C) 1992, 1994 Free Software Foundation, Inc. + +;! This file is part of the GNU MP Library. + +;! The GNU MP Library is free software; you can redistribute it and/or modify +;! it under the terms of the GNU Lesser General Public License as published by +;! the Free Software Foundation; either version 2.1 of the License, or (at your +;! option) any later version. + +;! The GNU MP Library is distributed in the hope that it will be useful, but +;! WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +;! or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public +;! License for more details. + +;! You should have received a copy of the GNU Lesser General Public License +;! along with the GNU MP Library; see the file COPYING.LIB. If not, write to +;! the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +;! MA 02111-1307, USA. + + +;! INPUT PARAMETERS +;! res_ptr gr26 +;! s_ptr gr25 +;! size gr24 +;! cnt gr23 + + .text + .export __mpn_rshift +__mpn_rshift: + .proc + .callinfo frame=64,no_calls + .entry + + ldws,ma 4(%r25),%r22 + mtsar %r23 + addib,= -1,%r24,L$0004 + vshd %r22,%r0,%r28 ;! compute carry out limb + ldws,ma 4(%r25),%r29 + addib,= -1,%r24,L$0002 + vshd %r29,%r22,%r20 + +L$loop: ldws,ma 4(%r25),%r22 + stws,ma %r20,4(%r26) + addib,= -1,%r24,L$0003 + vshd %r22,%r29,%r20 + ldws,ma 4(%r25),%r29 + stws,ma %r20,4(%r26) + addib,<> -1,%r24,L$loop + vshd %r29,%r22,%r20 + +L$0002: stws,ma %r20,4(%r26) + vshd %r0,%r29,%r20 + bv 0(%r2) + stw %r20,0(%r26) +L$0003: stws,ma %r20,4(%r26) +L$0004: vshd %r0,%r22,%r20 + bv 0(%r2) + stw %r20,0(%r26) + + .exit + .procend diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/setjmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/setjmp.S new file mode 100644 index 00000000..fdc4c424 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/setjmp.S @@ -0,0 +1,63 @@ +/* setjmp for HPPA. + Copyright (C) 1995, 1996, 1997, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + + .text + .align 4 + .import __sigjmp_save, code + .globl __sigsetjmp + .export __sigsetjmp, code + .proc + .callinfo +__sigsetjmp: + stw %r3, 0(%r26) + stw %r4, 8(%r26) + stw %r5, 12(%r26) + stw %r6, 16(%r26) + stw %r7, 20(%r26) + stw %r8, 24(%r26) + stw %r9, 28(%r26) + stw %r10, 32(%r26) + stw %r11, 36(%r26) + stw %r12, 40(%r26) + stw %r13, 44(%r26) + stw %r14, 48(%r26) + stw %r15, 52(%r26) + stw %r16, 56(%r26) + stw %r17, 60(%r26) + stw %r18, 64(%r26) + stw %r19, 68(%r26) + stw %r27, 72(%r26) + stw %r30, 76(%r26) + + stw %rp, 80(%r26) + + ldo 88(%r26),%r1 + fstds,ma %fr12, 8(%r1) /* 88 */ + fstds,ma %fr13, 8(%r1) /* 96 */ + fstds,ma %fr14, 8(%r1) /* 104 */ + fstds,ma %fr15, 8(%r1) /* 112 */ + fstds,ma %fr16, 8(%r1) /* 120 */ + fstds,ma %fr17, 8(%r1) /* 128 */ + fstds,ma %fr18, 8(%r1) /* 136 */ + fstds,ma %fr19, 8(%r1) /* 144 */ + fstds,ma %fr20, 8(%r1) /* 152 */ + fstds %fr21, 0(%r1) /* 160 */ + b __sigjmp_save + nop + .procend diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/sub_n.s b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/sub_n.s new file mode 100644 index 00000000..7764961a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/sub_n.s @@ -0,0 +1,59 @@ +;! HP-PA __mpn_sub_n -- Subtract two limb vectors of the same length > 0 and +;! store difference in a third limb vector. + +;! Copyright (C) 1992, 1994 Free Software Foundation, Inc. + +;! This file is part of the GNU MP Library. + +;! The GNU MP Library is free software; you can redistribute it and/or modify +;! it under the terms of the GNU Lesser General Public License as published by +;! the Free Software Foundation; either version 2.1 of the License, or (at your +;! option) any later version. + +;! The GNU MP Library is distributed in the hope that it will be useful, but +;! WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +;! or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public +;! License for more details. + +;! You should have received a copy of the GNU Lesser General Public License +;! along with the GNU MP Library; see the file COPYING.LIB. If not, write to +;! the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +;! MA 02111-1307, USA. + + +;! INPUT PARAMETERS +;! res_ptr gr26 +;! s1_ptr gr25 +;! s2_ptr gr24 +;! size gr23 + +;! One might want to unroll this as for other processors, but it turns +;! out that the data cache contention after a store makes such +;! unrolling useless. We can't come under 5 cycles/limb anyway. + + .text + .export __mpn_sub_n +__mpn_sub_n: + .proc + .callinfo frame=0,no_calls + .entry + + ldws,ma 4(%r25),%r21 + ldws,ma 4(%r24),%r20 + + addib,= -1,%r23,L$end ;! check for (SIZE == 1) + sub %r21,%r20,%r28 ;! subtract first limbs ignoring cy + +L$loop: ldws,ma 4(%r25),%r21 + ldws,ma 4(%r24),%r20 + stws,ma %r28,4(%r26) + addib,<> -1,%r23,L$loop + subb %r21,%r20,%r28 + +L$end: stws %r28,0(%r26) + addc %r0,%r0,%r28 + bv 0(%r2) + subi 1,%r28,%r28 + + .exit + .procend diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/sys/procfs.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/sys/procfs.h new file mode 100644 index 00000000..2e6d1095 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/sys/procfs.h @@ -0,0 +1,113 @@ +/* Copyright (C) 1996, 1997, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_PROCFS_H +#define _SYS_PROCFS_H 1 + +/* This is somewhat modelled after the file of the same name on SVR4 + systems. It provides a definition of the core file format for ELF + used on Linux. It doesn't have anything to do with the /proc file + system, even though Linux has one. + + Anyway, the whole purpose of this file is for GDB and GDB only. + Don't read too much into it. Don't use it for anything other than + GDB unless you know what you are doing. */ + +#include +#include +#include +#include +#include +#include +#include + +__BEGIN_DECLS + +struct elf_siginfo + { + int si_signo; /* Signal number. */ + int si_code; /* Extra code. */ + int si_errno; /* Errno. */ + }; + +/* Definitions to generate Intel SVR4-like core files. These mostly + have the same names as the SVR4 types with "elf_" tacked on the + front to prevent clashes with Linux definitions, and the typedef + forms have been avoided. This is mostly like the SVR4 structure, + but more Linuxy, with things that Linux does not support and which + GDB doesn't really use excluded. */ + +struct elf_prstatus + { + struct elf_siginfo pr_info; /* Info associated with signal. */ + short int pr_cursig; /* Current signal. */ + unsigned long int pr_sigpend; /* Set of pending signals. */ + unsigned long int pr_sighold; /* Set of held signals. */ + __pid_t pr_pid; + __pid_t pr_ppid; + __pid_t pr_pgrp; + __pid_t pr_sid; + struct timeval pr_utime; /* User time. */ + struct timeval pr_stime; /* System time. */ + struct timeval pr_cutime; /* Cumulative user time. */ + struct timeval pr_cstime; /* Cumulative system time. */ + elf_gregset_t pr_reg; /* GP registers. */ + int pr_fpvalid; /* True if math copro being used. */ + }; + + +#define ELF_PRARGSZ (80) /* Number of chars for args. */ + +struct elf_prpsinfo + { + char pr_state; /* Numeric process state. */ + char pr_sname; /* Char for pr_state. */ + char pr_zomb; /* Zombie. */ + char pr_nice; /* Nice val. */ + unsigned long int pr_flag; /* Flags. */ + unsigned int pr_uid; + unsigned int pr_gid; + int pr_pid, pr_ppid, pr_pgrp, pr_sid; + /* Lots missing */ + char pr_fname[16]; /* Filename of executable. */ + char pr_psargs[ELF_PRARGSZ]; /* Initial part of arg list. */ + }; + + +/* The rest of this file provides the types for emulation of the + Solaris interfaces that should be implemented by + users of libthread_db. */ + +/* Addresses. */ +typedef void *psaddr_t; + +/* Register sets. Linux has different names. */ +typedef elf_gregset_t prgregset_t; +typedef elf_fpregset_t prfpregset_t; + +/* We don't have any differences between processes and threads, + therefore have only one PID type. */ +typedef __pid_t lwpid_t; + +/* Process status and info. In the end we do provide typedefs for them. */ +typedef struct elf_prstatus prstatus_t; +typedef struct elf_prpsinfo prpsinfo_t; + +__END_DECLS + +#endif /* sys/procfs.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/sys/ucontext.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/sys/ucontext.h new file mode 100644 index 00000000..14311438 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/sys/ucontext.h @@ -0,0 +1,67 @@ +/* Copyright (C) 1997, 1998, 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Don't rely on this, the interface is currently messed up and may need to + be broken to be fixed. */ +#ifndef _SYS_UCONTEXT_H +#define _SYS_UCONTEXT_H 1 + +#include +#include + +/* We need the signal context definitions even if they are not used + included in . */ +#include + + +/* Type for general register. */ +typedef unsigned long int greg_t; + +/* Number of general registers. */ +#define NGREG 80 +#define NFPREG 32 + +/* Container for all general registers. */ +typedef struct gregset + { + greg_t g_regs[32]; + greg_t sr_regs[8]; + greg_t cr_regs[24]; + greg_t g_pad[16]; + } gregset_t; + +/* Container for all FPU registers. */ +typedef struct fpregset + { + double fp_dregs[32]; + } fpregset_t; + +/* Context to describe whole processor state. */ +typedef struct sigcontext mcontext_t; + +/* Userlevel context. */ +typedef struct ucontext + { + unsigned long int uc_flags; + struct ucontext *uc_link; + stack_t uc_stack; + mcontext_t uc_mcontext; + __sigset_t uc_sigmask; + } ucontext_t; + +#endif /* sys/ucontext.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/syscall.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/syscall.c new file mode 100644 index 00000000..cd11e084 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/syscall.c @@ -0,0 +1,65 @@ +/* Copyright (C) 1997, 1998, 2001, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + +/* HPPA implements syscall() in 'C'; the assembler version would + typically be in syscall.S. Also note that we have INLINE_SYSCALL, + INTERNAL_SYSCALL, and all the generated pure assembly syscall wrappers. + How often the function is used is unknown. */ + +long int +syscall (long int __sysno, ...) +{ + /* FIXME: Keep this matching INLINE_SYSCALL for hppa */ + va_list args; + long int arg0, arg1, arg2, arg3, arg4, arg5; + long int __sys_res; + + /* Load varargs */ + va_start (args, __sysno); + arg0 = va_arg (args, long int); + arg1 = va_arg (args, long int); + arg2 = va_arg (args, long int); + arg3 = va_arg (args, long int); + arg4 = va_arg (args, long int); + arg5 = va_arg (args, long int); + va_end (args); + + { + register unsigned long int __res __asm__("r28"); + K_LOAD_ARGS_6 (arg0, arg1, arg2, arg3, arg4, arg5) + __asm__ __volatile__ (K_STW_ASM_PIC + " ble 0x100(%%sr2, %%r0) \n" + " copy %1, %%r20 \n" + K_LDW_ASM_PIC + : "=r" (__res) + : "r" (__sysno) K_ASM_ARGS_6 + : "memory", K_CALL_CLOB_REGS K_CLOB_ARGS_6); + __sys_res = __res; + } + if ((unsigned long int) __sys_res >= (unsigned long int) -4095) + { + __set_errno (-__sys_res); + __sys_res = -1; + } + return __sys_res; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/udiv_qrnnd.s b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/udiv_qrnnd.s new file mode 100644 index 00000000..8e9c07a2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/hppa/udiv_qrnnd.s @@ -0,0 +1,286 @@ +;! HP-PA __udiv_qrnnd division support, used from longlong.h. +;! This version runs fast on pre-PA7000 CPUs. + +;! Copyright (C) 1993, 1994 Free Software Foundation, Inc. + +;! This file is part of the GNU MP Library. + +;! The GNU MP Library is free software; you can redistribute it and/or modify +;! it under the terms of the GNU Lesser General Public License as published by +;! the Free Software Foundation; either version 2.1 of the License, or (at your +;! option) any later version. + +;! The GNU MP Library is distributed in the hope that it will be useful, but +;! WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +;! or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public +;! License for more details. + +;! You should have received a copy of the GNU Lesser General Public License +;! along with the GNU MP Library; see the file COPYING.LIB. If not, write to +;! the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, +;! MA 02111-1307, USA. + + +;! INPUT PARAMETERS +;! rem_ptr gr26 +;! n1 gr25 +;! n0 gr24 +;! d gr23 + +;! The code size is a bit excessive. We could merge the last two ds;addc +;! sequences by simply moving the "bb,< Odd" instruction down. The only +;! trouble is the FFFFFFFF code that would need some hacking. + + .text + .export __udiv_qrnnd +__udiv_qrnnd: + .proc + .callinfo frame=0,no_calls + .entry + + comb,< %r23,%r0,L$largedivisor + sub %r0,%r23,%r1 ;! clear cy as side-effect + ds %r0,%r1,%r0 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r24 + ds %r25,%r23,%r25 + addc %r24,%r24,%r28 + ds %r25,%r23,%r25 + comclr,>= %r25,%r0,%r0 + addl %r25,%r23,%r25 + stws %r25,0(%r26) + bv 0(%r2) + addc %r28,%r28,%r28 + +L$largedivisor: + extru %r24,31,1,%r20 ;! r20 = n0 & 1 + bb,< %r23,31,L$odd + extru %r23,30,31,%r22 ;! r22 = d >> 1 + shd %r25,%r24,1,%r24 ;! r24 = new n0 + extru %r25,30,31,%r25 ;! r25 = new n1 + sub %r0,%r22,%r21 + ds %r0,%r21,%r0 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + comclr,>= %r25,%r0,%r0 + addl %r25,%r22,%r25 + sh1addl %r25,%r20,%r25 + stws %r25,0(%r26) + bv 0(%r2) + addc %r24,%r24,%r28 + +L$odd: addib,sv,n 1,%r22,L$FF.. ;! r22 = (d / 2 + 1) + shd %r25,%r24,1,%r24 ;! r24 = new n0 + extru %r25,30,31,%r25 ;! r25 = new n1 + sub %r0,%r22,%r21 + ds %r0,%r21,%r0 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r24 + ds %r25,%r22,%r25 + addc %r24,%r24,%r28 + comclr,>= %r25,%r0,%r0 + addl %r25,%r22,%r25 + sh1addl %r25,%r20,%r25 +;! We have computed (n1,,n0) / (d + 1), q' = r28, r' = r25 + add,nuv %r28,%r25,%r25 + addl %r25,%r1,%r25 + addc %r0,%r28,%r28 + sub,<< %r25,%r23,%r0 + addl %r25,%r1,%r25 + stws %r25,0(%r26) + bv 0(%r2) + addc %r0,%r28,%r28 + +;! This is just a special case of the code above. +;! We come here when d == 0xFFFFFFFF +L$FF..: add,uv %r25,%r24,%r24 + sub,<< %r24,%r23,%r0 + ldo 1(%r24),%r24 + stws %r24,0(%r26) + bv 0(%r2) + addc %r0,%r25,%r28 + + .exit + .procend diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/Makefile new file mode 100644 index 00000000..633c91f3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../../ +top_builddir=../../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.arch +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/Makefile.arch b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/Makefile.arch new file mode 100644 index 00000000..668cca74 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/Makefile.arch @@ -0,0 +1,21 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +CSRC := brk.c __syscall_error.c + +ifneq ($(UCLIBC_HAS_THREADS_NATIVE),y) +CSRC += sigaction.c +endif + +SSRC := \ + __longjmp.S setjmp.S bsd-setjmp.S bsd-_setjmp.S \ + sync_file_range.S syscall.S mmap.S mmap64.S posix_fadvise64.S + + +ifneq ($(UCLIBC_HAS_THREADS_NATIVE),y) +SSRC += vfork.S clone.S +endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/__longjmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/__longjmp.S new file mode 100644 index 00000000..e2809c06 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/__longjmp.S @@ -0,0 +1,42 @@ +/* longjmp for i386. + Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#define _ASM +#define _SETJMP_H +#include + +.global __longjmp +.type __longjmp,%function +__longjmp: + movl 4(%esp), %ecx /* User's jmp_buf in %ecx. */ + movl 8(%esp), %eax /* Second argument is return value. */ + /* Save the return address now. */ + movl (JB_PC*4)(%ecx), %edx + /* Restore registers. */ + movl (JB_BX*4)(%ecx), %ebx + movl (JB_SI*4)(%ecx), %esi + movl (JB_DI*4)(%ecx), %edi + movl (JB_BP*4)(%ecx), %ebp + movl (JB_SP*4)(%ecx), %esp + /* Jump to saved PC. */ + jmp *%edx +.size __longjmp,.-__longjmp + +libc_hidden_def(__longjmp) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/__syscall_error.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/__syscall_error.c new file mode 100644 index 00000000..36946bc6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/__syscall_error.c @@ -0,0 +1,35 @@ +/* Wrapper for setting errno. + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* This routine is jumped to by all the syscall handlers, to stash + * an error number into errno. */ + +/* This version uses a lot of magic and relies heavily on x86 + * calling convention ... The advantage is that this is the same + * size as the previous __syscall_error() but all the .S functions + * need just one instruction. + * + * Local .S files have to set %eax to the negative errno value + * and then jump to this function. The neglected return to caller + * and return value of -1 is taken care of here so we don't have to + * worry about it in the .S functions. + * + * We have to stash the errno from %eax in a local stack var because + * __set_errno will prob call a function thus clobbering %eax on us. + */ + +#include +#include + +int __syscall_error(void) attribute_hidden; +int __syscall_error(void) +{ + register int eax __asm__ ("%eax"); + int _errno = -eax; + __set_errno (_errno); + return -1; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/bits/atomic.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/bits/atomic.h new file mode 100644 index 00000000..c838978a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/bits/atomic.h @@ -0,0 +1,369 @@ +/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#if defined __CONFIG_GENERIC_I386__ || defined __CONFIG_I386__ +# warning this file is only good for 486 or better +#endif + +typedef int8_t atomic8_t; +typedef uint8_t uatomic8_t; +typedef int_fast8_t atomic_fast8_t; +typedef uint_fast8_t uatomic_fast8_t; + +typedef int16_t atomic16_t; +typedef uint16_t uatomic16_t; +typedef int_fast16_t atomic_fast16_t; +typedef uint_fast16_t uatomic_fast16_t; + +typedef int32_t atomic32_t; +typedef uint32_t uatomic32_t; +typedef int_fast32_t atomic_fast32_t; +typedef uint_fast32_t uatomic_fast32_t; + +typedef int64_t atomic64_t; +typedef uint64_t uatomic64_t; +typedef int_fast64_t atomic_fast64_t; +typedef uint_fast64_t uatomic_fast64_t; + +typedef intptr_t atomicptr_t; +typedef uintptr_t uatomicptr_t; +typedef intmax_t atomic_max_t; +typedef uintmax_t uatomic_max_t; + + +#ifndef LOCK_PREFIX +# ifdef UP +# define LOCK_PREFIX /* nothing */ +# else +# define LOCK_PREFIX "lock;" +# endif +#endif + + +#define __arch_compare_and_exchange_val_8_acq(mem, newval, oldval) \ + ({ __typeof (*mem) ret; \ + __asm__ __volatile__ (LOCK_PREFIX "cmpxchgb %b2, %1" \ + : "=a" (ret), "=m" (*mem) \ + : "q" (newval), "m" (*mem), "0" (oldval)); \ + ret; }) + +#define __arch_compare_and_exchange_val_16_acq(mem, newval, oldval) \ + ({ __typeof (*mem) ret; \ + __asm__ __volatile__ (LOCK_PREFIX "cmpxchgw %w2, %1" \ + : "=a" (ret), "=m" (*mem) \ + : "r" (newval), "m" (*mem), "0" (oldval)); \ + ret; }) + +#define __arch_compare_and_exchange_val_32_acq(mem, newval, oldval) \ + ({ __typeof (*mem) ret; \ + __asm__ __volatile__ (LOCK_PREFIX "cmpxchgl %2, %1" \ + : "=a" (ret), "=m" (*mem) \ + : "r" (newval), "m" (*mem), "0" (oldval)); \ + ret; }) + +/* XXX We do not really need 64-bit compare-and-exchange. At least + not in the moment. Using it would mean causing portability + problems since not many other 32-bit architectures have support for + such an operation. So don't define any code for now. If it is + really going to be used the code below can be used on Intel Pentium + and later, but NOT on i486. */ +#if 1 +# define __arch_compare_and_exchange_val_64_acq(mem, newval, oldval) \ + ({ __typeof (*mem) ret = *(mem); abort (); ret = (newval); ret = (oldval); }) +#else +# ifdef __PIC__ +# define __arch_compare_and_exchange_val_64_acq(mem, newval, oldval) \ + ({ __typeof (*mem) ret; \ + __asm__ __volatile__ ("xchgl %2, %%ebx\n\t" \ + LOCK_PREFIX "cmpxchg8b %1\n\t" \ + "xchgl %2, %%ebx" \ + : "=A" (ret), "=m" (*mem) \ + : "DS" (((unsigned long long int) (newval)) \ + & 0xffffffff), \ + "c" (((unsigned long long int) (newval)) >> 32), \ + "m" (*mem), "a" (((unsigned long long int) (oldval)) \ + & 0xffffffff), \ + "d" (((unsigned long long int) (oldval)) >> 32)); \ + ret; }) +# else +# define __arch_compare_and_exchange_val_64_acq(mem, newval, oldval) \ + ({ __typeof (*mem) ret; \ + __asm__ __volatile__ (LOCK_PREFIX "cmpxchg8b %1" \ + : "=A" (ret), "=m" (*mem) \ + : "b" (((unsigned long long int) (newval)) \ + & 0xffffffff), \ + "c" (((unsigned long long int) (newval)) >> 32), \ + "m" (*mem), "a" (((unsigned long long int) (oldval)) \ + & 0xffffffff), \ + "d" (((unsigned long long int) (oldval)) >> 32)); \ + ret; }) +# endif +#endif + + +/* Note that we need no lock prefix. */ +#define atomic_exchange_acq(mem, newvalue) \ + ({ __typeof (*mem) result; \ + if (sizeof (*mem) == 1) \ + __asm__ __volatile__ ("xchgb %b0, %1" \ + : "=r" (result), "=m" (*mem) \ + : "0" (newvalue), "m" (*mem)); \ + else if (sizeof (*mem) == 2) \ + __asm__ __volatile__ ("xchgw %w0, %1" \ + : "=r" (result), "=m" (*mem) \ + : "0" (newvalue), "m" (*mem)); \ + else if (sizeof (*mem) == 4) \ + __asm__ __volatile__ ("xchgl %0, %1" \ + : "=r" (result), "=m" (*mem) \ + : "0" (newvalue), "m" (*mem)); \ + else \ + { \ + result = 0; \ + abort (); \ + } \ + result; }) + + +#define atomic_exchange_and_add(mem, value) \ + ({ __typeof (*mem) __result; \ + __typeof (value) __addval = (value); \ + if (sizeof (*mem) == 1) \ + __asm__ __volatile__ (LOCK_PREFIX "xaddb %b0, %1" \ + : "=r" (__result), "=m" (*mem) \ + : "0" (__addval), "m" (*mem)); \ + else if (sizeof (*mem) == 2) \ + __asm__ __volatile__ (LOCK_PREFIX "xaddw %w0, %1" \ + : "=r" (__result), "=m" (*mem) \ + : "0" (__addval), "m" (*mem)); \ + else if (sizeof (*mem) == 4) \ + __asm__ __volatile__ (LOCK_PREFIX "xaddl %0, %1" \ + : "=r" (__result), "=m" (*mem) \ + : "0" (__addval), "m" (*mem)); \ + else \ + { \ + __typeof (mem) __memp = (mem); \ + __typeof (*mem) __tmpval; \ + __result = *__memp; \ + do \ + __tmpval = __result; \ + while ((__result = __arch_compare_and_exchange_val_64_acq \ + (__memp, __result + __addval, __result)) == __tmpval); \ + } \ + __result; }) + + +#define atomic_add(mem, value) \ + (void) ({ if (__builtin_constant_p (value) && (value) == 1) \ + atomic_increment (mem); \ + else if (__builtin_constant_p (value) && (value) == -1) \ + atomic_decrement (mem); \ + else if (sizeof (*mem) == 1) \ + __asm__ __volatile__ (LOCK_PREFIX "addb %b1, %0" \ + : "=m" (*mem) \ + : "ir" (value), "m" (*mem)); \ + else if (sizeof (*mem) == 2) \ + __asm__ __volatile__ (LOCK_PREFIX "addw %w1, %0" \ + : "=m" (*mem) \ + : "ir" (value), "m" (*mem)); \ + else if (sizeof (*mem) == 4) \ + __asm__ __volatile__ (LOCK_PREFIX "addl %1, %0" \ + : "=m" (*mem) \ + : "ir" (value), "m" (*mem)); \ + else \ + { \ + __typeof (value) __addval = (value); \ + __typeof (mem) __memp = (mem); \ + __typeof (*mem) __oldval = *__memp; \ + __typeof (*mem) __tmpval; \ + do \ + __tmpval = __oldval; \ + while ((__oldval = __arch_compare_and_exchange_val_64_acq \ + (__memp, __oldval + __addval, __oldval)) == __tmpval); \ + } \ + }) + + +#define atomic_add_negative(mem, value) \ + ({ unsigned char __result; \ + if (sizeof (*mem) == 1) \ + __asm__ __volatile__ (LOCK_PREFIX "addb %b2, %0; sets %1" \ + : "=m" (*mem), "=qm" (__result) \ + : "iq" (value), "m" (*mem)); \ + else if (sizeof (*mem) == 2) \ + __asm__ __volatile__ (LOCK_PREFIX "addw %w2, %0; sets %1" \ + : "=m" (*mem), "=qm" (__result) \ + : "ir" (value), "m" (*mem)); \ + else if (sizeof (*mem) == 4) \ + __asm__ __volatile__ (LOCK_PREFIX "addl %2, %0; sets %1" \ + : "=m" (*mem), "=qm" (__result) \ + : "ir" (value), "m" (*mem)); \ + else \ + abort (); \ + __result; }) + + +#define atomic_add_zero(mem, value) \ + ({ unsigned char __result; \ + if (sizeof (*mem) == 1) \ + __asm__ __volatile__ (LOCK_PREFIX "addb %b2, %0; setz %1" \ + : "=m" (*mem), "=qm" (__result) \ + : "ir" (value), "m" (*mem)); \ + else if (sizeof (*mem) == 2) \ + __asm__ __volatile__ (LOCK_PREFIX "addw %w2, %0; setz %1" \ + : "=m" (*mem), "=qm" (__result) \ + : "ir" (value), "m" (*mem)); \ + else if (sizeof (*mem) == 4) \ + __asm__ __volatile__ (LOCK_PREFIX "addl %2, %0; setz %1" \ + : "=m" (*mem), "=qm" (__result) \ + : "ir" (value), "m" (*mem)); \ + else \ + abort (); \ + __result; }) + + +#define atomic_increment(mem) \ + (void) ({ if (sizeof (*mem) == 1) \ + __asm__ __volatile__ (LOCK_PREFIX "incb %b0" \ + : "=m" (*mem) \ + : "m" (*mem)); \ + else if (sizeof (*mem) == 2) \ + __asm__ __volatile__ (LOCK_PREFIX "incw %w0" \ + : "=m" (*mem) \ + : "m" (*mem)); \ + else if (sizeof (*mem) == 4) \ + __asm__ __volatile__ (LOCK_PREFIX "incl %0" \ + : "=m" (*mem) \ + : "m" (*mem)); \ + else \ + { \ + __typeof (mem) __memp = (mem); \ + __typeof (*mem) __oldval = *__memp; \ + __typeof (*mem) __tmpval; \ + do \ + __tmpval = __oldval; \ + while ((__oldval = __arch_compare_and_exchange_val_64_acq \ + (__memp, __oldval + 1, __oldval)) == __tmpval); \ + } \ + }) + + +#define atomic_increment_and_test(mem) \ + ({ unsigned char __result; \ + if (sizeof (*mem) == 1) \ + __asm__ __volatile__ (LOCK_PREFIX "incb %0; sete %b1" \ + : "=m" (*mem), "=qm" (__result) \ + : "m" (*mem)); \ + else if (sizeof (*mem) == 2) \ + __asm__ __volatile__ (LOCK_PREFIX "incw %0; sete %w1" \ + : "=m" (*mem), "=qm" (__result) \ + : "m" (*mem)); \ + else if (sizeof (*mem) == 4) \ + __asm__ __volatile__ (LOCK_PREFIX "incl %0; sete %1" \ + : "=m" (*mem), "=qm" (__result) \ + : "m" (*mem)); \ + else \ + abort (); \ + __result; }) + + +#define atomic_decrement(mem) \ + (void) ({ if (sizeof (*mem) == 1) \ + __asm__ __volatile__ (LOCK_PREFIX "decb %b0" \ + : "=m" (*mem) \ + : "m" (*mem)); \ + else if (sizeof (*mem) == 2) \ + __asm__ __volatile__ (LOCK_PREFIX "decw %w0" \ + : "=m" (*mem) \ + : "m" (*mem)); \ + else if (sizeof (*mem) == 4) \ + __asm__ __volatile__ (LOCK_PREFIX "decl %0" \ + : "=m" (*mem) \ + : "m" (*mem)); \ + else \ + { \ + __typeof (mem) __memp = (mem); \ + __typeof (*mem) __oldval = *__memp; \ + __typeof (*mem) __tmpval; \ + do \ + __tmpval = __oldval; \ + while ((__oldval = __arch_compare_and_exchange_val_64_acq \ + (__memp, __oldval - 1, __oldval)) == __tmpval); \ + } \ + }) + + +#define atomic_decrement_and_test(mem) \ + ({ unsigned char __result; \ + if (sizeof (*mem) == 1) \ + __asm__ __volatile__ (LOCK_PREFIX "decb %b0; sete %1" \ + : "=m" (*mem), "=qm" (__result) \ + : "m" (*mem)); \ + else if (sizeof (*mem) == 2) \ + __asm__ __volatile__ (LOCK_PREFIX "decw %w0; sete %1" \ + : "=m" (*mem), "=qm" (__result) \ + : "m" (*mem)); \ + else if (sizeof (*mem) == 4) \ + __asm__ __volatile__ (LOCK_PREFIX "decl %0; sete %1" \ + : "=m" (*mem), "=qm" (__result) \ + : "m" (*mem)); \ + else \ + abort (); \ + __result; }) + + +#define atomic_bit_set(mem, bit) \ + (void) ({ if (sizeof (*mem) == 1) \ + __asm__ __volatile__ (LOCK_PREFIX "orb %b2, %0" \ + : "=m" (*mem) \ + : "m" (*mem), "ir" (1 << (bit))); \ + else if (sizeof (*mem) == 2) \ + __asm__ __volatile__ (LOCK_PREFIX "orw %w2, %0" \ + : "=m" (*mem) \ + : "m" (*mem), "ir" (1 << (bit))); \ + else if (sizeof (*mem) == 4) \ + __asm__ __volatile__ (LOCK_PREFIX "orl %2, %0" \ + : "=m" (*mem) \ + : "m" (*mem), "ir" (1 << (bit))); \ + else \ + abort (); \ + }) + + +#define atomic_bit_test_set(mem, bit) \ + ({ unsigned char __result; \ + if (sizeof (*mem) == 1) \ + __asm__ __volatile__ (LOCK_PREFIX "btsb %3, %1; setc %0" \ + : "=q" (__result), "=m" (*mem) \ + : "m" (*mem), "ir" (bit)); \ + else if (sizeof (*mem) == 2) \ + __asm__ __volatile__ (LOCK_PREFIX "btsw %3, %1; setc %0" \ + : "=q" (__result), "=m" (*mem) \ + : "m" (*mem), "ir" (bit)); \ + else if (sizeof (*mem) == 4) \ + __asm__ __volatile__ (LOCK_PREFIX "btsl %3, %1; setc %0" \ + : "=q" (__result), "=m" (*mem) \ + : "m" (*mem), "ir" (bit)); \ + else \ + abort (); \ + __result; }) + + +#define atomic_delay() __asm__ ("rep; nop") diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/bits/byteswap.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/bits/byteswap.h new file mode 100644 index 00000000..052eda38 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/bits/byteswap.h @@ -0,0 +1,56 @@ +/* Macros to swap the order of bytes in integer values. + Copyright (C) 1997, 1998, 2000, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _ASM_BITS_BYTESWAP_H +#define _ASM_BITS_BYTESWAP_H 1 + +#define __bswap_non_constant_16(x) \ + (__extension__ \ + ({ register unsigned short int __v; \ + __asm__ ("rorw $8, %w0" \ + : "=r" (__v) \ + : "0" (x) \ + : "cc"); \ + __v; })) + +/* To swap the bytes in a word the i486 processors and up provide the + `bswap' opcode. On i386 we have to use three instructions. */ +#if !defined __i486__ && !defined __pentium__ && !defined __pentiumpro__ \ + && !defined __pentium4__ +# define __bswap_non_constant_32(x) \ + (__extension__ \ + ({ register unsigned int __v; \ + __asm__ ("rorw $8, %w0;" \ + "rorl $16, %0;" \ + "rorw $8, %w0" \ + : "=r" (__v) \ + : "0" (x) \ + : "cc"); \ + __v; })) +#else +# define __bswap_non_constant_32(x) \ + (__extension__ \ + ({ register unsigned int __v; \ + __asm__ ("bswap %0" : "=r" (__v) : "0" (x)); \ + __v; })) +#endif + +#endif + +#include diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/bits/endian.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/bits/endian.h new file mode 100644 index 00000000..54bd9d14 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/bits/endian.h @@ -0,0 +1,7 @@ +/* i386 is little-endian. */ + +#ifndef _ENDIAN_H +# error "Never use directly; include instead." +#endif + +#define __BYTE_ORDER __LITTLE_ENDIAN diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/bits/fcntl.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/bits/fcntl.h new file mode 100644 index 00000000..22e073bb --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/bits/fcntl.h @@ -0,0 +1,239 @@ +/* O_*, F_*, FD_* bit values for Linux. + Copyright (C) 1995, 1996, 1997, 1998, 2000, 2004, 2006, 2007, 2008 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FCNTL_H +# error "Never use directly; include instead." +#endif + +#include +#ifdef __USE_GNU +# include +#endif + + +/* open/fcntl - O_SYNC is only implemented on blocks devices and on files + located on an ext2 file system */ +#define O_ACCMODE 0003 +#define O_RDONLY 00 +#define O_WRONLY 01 +#define O_RDWR 02 +#define O_CREAT 0100 /* not fcntl */ +#define O_EXCL 0200 /* not fcntl */ +#define O_NOCTTY 0400 /* not fcntl */ +#define O_TRUNC 01000 /* not fcntl */ +#define O_APPEND 02000 +#define O_NONBLOCK 04000 +#define O_NDELAY O_NONBLOCK +#define O_SYNC 010000 +#define O_FSYNC O_SYNC +#define O_ASYNC 020000 + +#ifdef __USE_GNU +# define O_DIRECT 040000 /* Direct disk access. */ +# define O_DIRECTORY 0200000 /* Must be a directory. */ +# define O_NOFOLLOW 0400000 /* Do not follow links. */ +# define O_NOATIME 01000000 /* Do not set atime. */ +# define O_CLOEXEC 02000000 /* Set close_on_exec. */ +#endif + +/* For now Linux has synchronisity options for data and read operations. + We define the symbols here but let them do the same as O_SYNC since + this is a superset. */ +#if defined __USE_POSIX199309 || defined __USE_UNIX98 +# define O_DSYNC O_SYNC /* Synchronize data. */ +# define O_RSYNC O_SYNC /* Synchronize read operations. */ +#endif + +#ifdef __USE_LARGEFILE64 +# define O_LARGEFILE 0100000 +#endif + +/* Values for the second argument to `fcntl'. */ +#define F_DUPFD 0 /* Duplicate file descriptor. */ +#define F_GETFD 1 /* Get file descriptor flags. */ +#define F_SETFD 2 /* Set file descriptor flags. */ +#define F_GETFL 3 /* Get file status flags. */ +#define F_SETFL 4 /* Set file status flags. */ +#ifndef __USE_FILE_OFFSET64 +# define F_GETLK 5 /* Get record locking info. */ +# define F_SETLK 6 /* Set record locking info (non-blocking). */ +# define F_SETLKW 7 /* Set record locking info (blocking). */ +#else +# define F_GETLK F_GETLK64 /* Get record locking info. */ +# define F_SETLK F_SETLK64 /* Set record locking info (non-blocking).*/ +# define F_SETLKW F_SETLKW64 /* Set record locking info (blocking). */ +#endif +#define F_GETLK64 12 /* Get record locking info. */ +#define F_SETLK64 13 /* Set record locking info (non-blocking). */ +#define F_SETLKW64 14 /* Set record locking info (blocking). */ + +#if defined __USE_BSD || defined __USE_UNIX98 +# define F_SETOWN 8 /* Get owner of socket (receiver of SIGIO). */ +# define F_GETOWN 9 /* Set owner of socket (receiver of SIGIO). */ +#endif + +#ifdef __USE_GNU +# define F_SETSIG 10 /* Set number of signal to be sent. */ +# define F_GETSIG 11 /* Get number of signal to be sent. */ +#endif + +#ifdef __USE_GNU +# define F_SETLEASE 1024 /* Set a lease. */ +# define F_GETLEASE 1025 /* Enquire what lease is active. */ +# define F_NOTIFY 1026 /* Request notfications on a directory. */ +# define F_DUPFD_CLOEXEC 1030 /* Duplicate file descriptor with + close-on-exit set on new fd. */ +#endif + +/* For F_[GET|SET]FD. */ +#define FD_CLOEXEC 1 /* actually anything with low bit set goes */ + +/* For posix fcntl() and `l_type' field of a `struct flock' for lockf(). */ +#define F_RDLCK 0 /* Read lock. */ +#define F_WRLCK 1 /* Write lock. */ +#define F_UNLCK 2 /* Remove lock. */ + +/* For old implementation of bsd flock(). */ +#define F_EXLCK 4 /* or 3 */ +#define F_SHLCK 8 /* or 4 */ + +#ifdef __USE_BSD +/* Operations for bsd flock(), also used by the kernel implementation. */ +# define LOCK_SH 1 /* shared lock */ +# define LOCK_EX 2 /* exclusive lock */ +# define LOCK_NB 4 /* or'd with one of the above to prevent + blocking */ +# define LOCK_UN 8 /* remove lock */ +#endif + +#ifdef __USE_GNU +# define LOCK_MAND 32 /* This is a mandatory flock: */ +# define LOCK_READ 64 /* ... which allows concurrent read operations. */ +# define LOCK_WRITE 128 /* ... which allows concurrent write operations. */ +# define LOCK_RW 192 /* ... Which allows concurrent read & write operations. */ +#endif + +#ifdef __USE_GNU +/* Types of directory notifications that may be requested with F_NOTIFY. */ +# define DN_ACCESS 0x00000001 /* File accessed. */ +# define DN_MODIFY 0x00000002 /* File modified. */ +# define DN_CREATE 0x00000004 /* File created. */ +# define DN_DELETE 0x00000008 /* File removed. */ +# define DN_RENAME 0x00000010 /* File renamed. */ +# define DN_ATTRIB 0x00000020 /* File changed attibutes. */ +# define DN_MULTISHOT 0x80000000 /* Don't remove notifier. */ +#endif + +struct flock + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ +#ifndef __USE_FILE_OFFSET64 + __off_t l_start; /* Offset where the lock begins. */ + __off_t l_len; /* Size of the locked area; zero means until EOF. */ +#else + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ +#endif + __pid_t l_pid; /* Process holding the lock. */ + }; + +#ifdef __USE_LARGEFILE64 +struct flock64 + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ + __pid_t l_pid; /* Process holding the lock. */ + }; +#endif + +/* Define some more compatibility macros to be backward compatible with + BSD systems which did not managed to hide these kernel macros. */ +#ifdef __USE_BSD +# define FAPPEND O_APPEND +# define FFSYNC O_FSYNC +# define FASYNC O_ASYNC +# define FNONBLOCK O_NONBLOCK +# define FNDELAY O_NDELAY +#endif /* Use BSD. */ + +/* Advise to `posix_fadvise'. */ +#ifdef __USE_XOPEN2K +# define POSIX_FADV_NORMAL 0 /* No further special treatment. */ +# define POSIX_FADV_RANDOM 1 /* Expect random page references. */ +# define POSIX_FADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define POSIX_FADV_WILLNEED 3 /* Will need these pages. */ +# define POSIX_FADV_DONTNEED 4 /* Don't need these pages. */ +# define POSIX_FADV_NOREUSE 5 /* Data will be accessed once. */ +#endif + + +#if defined __USE_GNU && defined __UCLIBC_LINUX_SPECIFIC__ +/* Flags for SYNC_FILE_RANGE. */ +# define SYNC_FILE_RANGE_WAIT_BEFORE 1 /* Wait upon writeout of all pages + in the range before performing the + write. */ +# define SYNC_FILE_RANGE_WRITE 2 /* Initiate writeout of all those + dirty pages in the range which are + not presently under writeback. */ +# define SYNC_FILE_RANGE_WAIT_AFTER 4 /* Wait upon writeout of all pages in + the range after performing the + write. */ + +/* Flags for SPLICE and VMSPLICE. */ +# define SPLICE_F_MOVE 1 /* Move pages instead of copying. */ +# define SPLICE_F_NONBLOCK 2 /* Don't block on the pipe splicing + (but we may still block on the fd + we splice from/to). */ +# define SPLICE_F_MORE 4 /* Expect more data. */ +# define SPLICE_F_GIFT 8 /* Pages passed in are a gift. */ +#endif + +__BEGIN_DECLS + +#if defined __USE_GNU && defined __UCLIBC_LINUX_SPECIFIC__ + +/* Provide kernel hint to read ahead. */ +extern ssize_t readahead (int __fd, __off64_t __offset, size_t __count) + __THROW; + + +/* Selective file content synch'ing. */ +extern int sync_file_range (int __fd, __off64_t __from, __off64_t __to, + unsigned int __flags); + +/* Splice address range into a pipe. */ +extern ssize_t vmsplice (int __fdout, const struct iovec *__iov, + size_t __count, unsigned int __flags); + +/* Splice two files together. */ +extern ssize_t splice (int __fdin, __off64_t *__offin, int __fdout, + __off64_t *__offout, size_t __len, + unsigned int __flags); + +/* In-kernel implementation of tee for pipe buffers. */ +extern ssize_t tee (int __fdin, int __fdout, size_t __len, + unsigned int __flags); + +#endif +__END_DECLS + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/bits/fenv.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/bits/fenv.h new file mode 100644 index 00000000..ef3fcb38 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/bits/fenv.h @@ -0,0 +1,90 @@ +/* Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FENV_H +# error "Never use directly; include instead." +#endif + + +/* Define bits representing the exception. We use the bit positions + of the appropriate bits in the FPU control word. */ +enum + { + FE_INVALID = 0x01, +#define FE_INVALID FE_INVALID + __FE_DENORM = 0x02, + FE_DIVBYZERO = 0x04, +#define FE_DIVBYZERO FE_DIVBYZERO + FE_OVERFLOW = 0x08, +#define FE_OVERFLOW FE_OVERFLOW + FE_UNDERFLOW = 0x10, +#define FE_UNDERFLOW FE_UNDERFLOW + FE_INEXACT = 0x20 +#define FE_INEXACT FE_INEXACT + }; + +#define FE_ALL_EXCEPT \ + (FE_INEXACT | FE_DIVBYZERO | FE_UNDERFLOW | FE_OVERFLOW | FE_INVALID) + +/* The ix87 FPU supports all of the four defined rounding modes. We + use again the bit positions in the FPU control word as the values + for the appropriate macros. */ +enum + { + FE_TONEAREST = 0, +#define FE_TONEAREST FE_TONEAREST + FE_DOWNWARD = 0x400, +#define FE_DOWNWARD FE_DOWNWARD + FE_UPWARD = 0x800, +#define FE_UPWARD FE_UPWARD + FE_TOWARDZERO = 0xc00 +#define FE_TOWARDZERO FE_TOWARDZERO + }; + + +/* Type representing exception flags. */ +typedef unsigned short int fexcept_t; + + +/* Type representing floating-point environment. This function corresponds + to the layout of the block written by the `fstenv'. */ +typedef struct + { + unsigned short int __control_word; + unsigned short int __unused1; + unsigned short int __status_word; + unsigned short int __unused2; + unsigned short int __tags; + unsigned short int __unused3; + unsigned int __eip; + unsigned short int __cs_selector; + unsigned int __opcode:11; + unsigned int __unused4:5; + unsigned int __data_offset; + unsigned short int __data_selector; + unsigned short int __unused5; + } +fenv_t; + +/* If the default argument is used we use this value. */ +#define FE_DFL_ENV ((__const fenv_t *) -1) + +#ifdef __USE_GNU +/* Floating-point environment where none of the exception is masked. */ +# define FE_NOMASK_ENV ((__const fenv_t *) -2) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/bits/kernel_stat.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/bits/kernel_stat.h new file mode 100644 index 00000000..decbeb91 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/bits/kernel_stat.h @@ -0,0 +1,53 @@ +#ifndef _BITS_STAT_STRUCT_H +#define _BITS_STAT_STRUCT_H + +#ifndef _LIBC +#error bits/kernel_stat.h is for internal uClibc use only! +#endif + +/* This file provides whatever this particular arch's kernel thinks + * struct stat should look like... It turns out each arch has a + * different opinion on the subject... */ + +struct kernel_stat { + unsigned long st_dev; + unsigned long st_ino; + unsigned short st_mode; + unsigned short st_nlink; + unsigned short st_uid; + unsigned short st_gid; + unsigned short st_rdev; + unsigned short __pad2; + unsigned long st_size; + unsigned long st_blksize; + unsigned long st_blocks; + struct timespec st_atim; + struct timespec st_mtim; + struct timespec st_ctim; + unsigned long __unused4; + unsigned long __unused5; +}; + +struct kernel_stat64 { + unsigned long long st_dev; + unsigned char __pad0[4]; +#define _HAVE_STAT64___ST_INO + unsigned long __st_ino; + unsigned int st_mode; + unsigned int st_nlink; + unsigned long st_uid; + unsigned long st_gid; + unsigned short st_rdev; + unsigned char __pad3[10]; + long long st_size; + unsigned long st_blksize; + unsigned long st_blocks; /* Number 512-byte blocks allocated. */ + unsigned long __pad4; /* future possible st_blocks high bits */ + struct timespec st_atim; + struct timespec st_mtim; + struct timespec st_ctim; + unsigned long long st_ino; +}; + +#endif /* _BITS_STAT_STRUCT_H */ + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/bits/kernel_types.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/bits/kernel_types.h new file mode 100644 index 00000000..9c07c722 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/bits/kernel_types.h @@ -0,0 +1,53 @@ +/* Note that we use the exact same include guard #define names + * as asm/posix_types.h. This will avoid gratuitous conflicts + * with the posix_types.h kernel header, and will ensure that + * our private content, and not the kernel header, will win. + * -Erik + */ + +/* a hack for compiling a 32 bit user space with 64 bit + * kernel on x86_64 */ +#if !defined(__ARCH_I386_POSIX_TYPES_H) && \ + !defined(_ASM_X86_64_POSIX_TYPES_H) && \ + !defined(_ASM_X86_POSIX_TYPES_32_H) && \ + !defined(_ASM_X86_POSIX_TYPES_64_H) +#define _ASM_X86_64_POSIX_TYPES_H +#define __ARCH_I386_POSIX_TYPES_H +#define _ASM_X86_POSIX_TYPES_32_H +#define _ASM_X86_POSIX_TYPES_64_H + +typedef unsigned short __kernel_dev_t; +typedef unsigned long __kernel_ino_t; +typedef unsigned short __kernel_mode_t; +typedef unsigned short __kernel_nlink_t; +typedef long __kernel_off_t; +typedef int __kernel_pid_t; +typedef unsigned short __kernel_ipc_pid_t; +typedef unsigned short __kernel_uid_t; +typedef unsigned short __kernel_gid_t; +typedef unsigned int __kernel_size_t; +typedef int __kernel_ssize_t; +typedef int __kernel_ptrdiff_t; +typedef long __kernel_time_t; +typedef long __kernel_suseconds_t; +typedef long __kernel_clock_t; +typedef int __kernel_daddr_t; +typedef char * __kernel_caddr_t; +typedef unsigned short __kernel_uid16_t; +typedef unsigned short __kernel_gid16_t; +typedef unsigned int __kernel_uid32_t; +typedef unsigned int __kernel_gid32_t; +typedef unsigned short __kernel_old_uid_t; +typedef unsigned short __kernel_old_gid_t; +typedef __kernel_dev_t __kernel_old_dev_t; +typedef long long __kernel_loff_t; + +typedef struct { +#ifdef __USE_ALL + int val[2]; +#else + int __val[2]; +#endif +} __kernel_fsid_t; + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/bits/mathdef.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/bits/mathdef.h new file mode 100644 index 00000000..a3786fc8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/bits/mathdef.h @@ -0,0 +1,50 @@ +/* Copyright (C) 1997, 1998, 1999, 2000, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#if !defined _MATH_H && !defined _COMPLEX_H +# error "Never use directly; include instead" +#endif + +#if defined __USE_ISOC99 && defined _MATH_H && !defined _MATH_H_MATHDEF +# define _MATH_H_MATHDEF 1 + +# if defined __FLT_EVAL_METHOD__ && __FLT_EVAL_METHOD__ == 0 +/* When using -mfpmath=sse, values are computed with the precission of the + used type. */ +typedef float float_t; /* `float' expressions are evaluated as `float'. */ +typedef double double_t; /* `double' expressions are evaluated as + `double'. */ +# else +/* The ix87 FPUs evaluate all values in the 80 bit floating-point format + which is also available for the user as `long double'. Therefore we + define: */ +typedef long double float_t; /* `float' expressions are evaluated as + `long double'. */ +typedef long double double_t; /* `double' expressions are evaluated as + `long double'. */ +# endif + +/* The values returned by `ilogb' for 0 and NaN respectively. */ +# define FP_ILOGB0 (-2147483647 - 1) +# define FP_ILOGBNAN (-2147483647 - 1) + +#endif /* ISO C99 */ + +#if !defined __NO_LONG_DOUBLE_MATH && !defined __UCLIBC_HAS_LONG_DOUBLE_MATH__ +# define __NO_LONG_DOUBLE_MATH 1 +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/bits/mathinline.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/bits/mathinline.h new file mode 100644 index 00000000..9e67182d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/bits/mathinline.h @@ -0,0 +1,766 @@ +/* Inline math functions for i387. + Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by John C. Bowman , 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _MATH_H +# error "Never use directly; include instead." +#endif + +#ifdef __cplusplus +# define __MATH_INLINE __inline +#else +# define __MATH_INLINE extern __inline +#endif + + +#if defined __USE_ISOC99 && defined __GNUC__ && __GNUC__ >= 2 +/* GCC 2.97 and up have builtins that actually can be used. */ +# if !__GNUC_PREREQ (2,97) +/* ISO C99 defines some macros to perform unordered comparisons. The + ix87 FPU supports this with special opcodes and we should use them. + These must not be inline functions since we have to be able to handle + all floating-point types. */ +# undef isgreater +# undef isgreaterequal +# undef isless +# undef islessequal +# undef islessgreater +# undef isunordered +# ifdef __i686__ +/* For the PentiumPro and more recent processors we can provide + better code. */ +# define isgreater(x, y) \ + ({ register char __result; \ + __asm__ ("fucomip %%st(1), %%st; seta %%al" \ + : "=a" (__result) : "u" (y), "t" (x) : "cc", "st"); \ + __result; }) +# define isgreaterequal(x, y) \ + ({ register char __result; \ + __asm__ ("fucomip %%st(1), %%st; setae %%al" \ + : "=a" (__result) : "u" (y), "t" (x) : "cc", "st"); \ + __result; }) + +# define isless(x, y) \ + ({ register char __result; \ + __asm__ ("fucomip %%st(1), %%st; seta %%al" \ + : "=a" (__result) : "u" (x), "t" (y) : "cc", "st"); \ + __result; }) + +# define islessequal(x, y) \ + ({ register char __result; \ + __asm__ ("fucomip %%st(1), %%st; setae %%al" \ + : "=a" (__result) : "u" (x), "t" (y) : "cc", "st"); \ + __result; }) + +# define islessgreater(x, y) \ + ({ register char __result; \ + __asm__ ("fucomip %%st(1), %%st; setne %%al" \ + : "=a" (__result) : "u" (y), "t" (x) : "cc", "st"); \ + __result; }) + +# define isunordered(x, y) \ + ({ register char __result; \ + __asm__ ("fucomip %%st(1), %%st; setp %%al" \ + : "=a" (__result) : "u" (y), "t" (x) : "cc", "st"); \ + __result; }) +# else +/* This is the dumb, portable code for i386 and above. */ +# define isgreater(x, y) \ + ({ register char __result; \ + __asm__ ("fucompp; fnstsw; testb $0x45, %%ah; setz %%al" \ + : "=a" (__result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \ + __result; }) + +# define isgreaterequal(x, y) \ + ({ register char __result; \ + __asm__ ("fucompp; fnstsw; testb $0x05, %%ah; setz %%al" \ + : "=a" (__result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \ + __result; }) + +# define isless(x, y) \ + ({ register char __result; \ + __asm__ ("fucompp; fnstsw; testb $0x45, %%ah; setz %%al" \ + : "=a" (__result) : "u" (x), "t" (y) : "cc", "st", "st(1)"); \ + __result; }) + +# define islessequal(x, y) \ + ({ register char __result; \ + __asm__ ("fucompp; fnstsw; testb $0x05, %%ah; setz %%al" \ + : "=a" (__result) : "u" (x), "t" (y) : "cc", "st", "st(1)"); \ + __result; }) + +# define islessgreater(x, y) \ + ({ register char __result; \ + __asm__ ("fucompp; fnstsw; testb $0x44, %%ah; setz %%al" \ + : "=a" (__result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \ + __result; }) + +# define isunordered(x, y) \ + ({ register char __result; \ + __asm__ ("fucompp; fnstsw; sahf; setp %%al" \ + : "=a" (__result) : "u" (y), "t" (x) : "cc", "st", "st(1)"); \ + __result; }) +# endif /* __i686__ */ +# endif /* GCC 2.97 */ + +/* The gcc, version 2.7 or below, has problems with all this inlining + code. So disable it for this version of the compiler. */ +# if __GNUC_PREREQ (2, 8) +/* Test for negative number. Used in the signbit() macro. */ +__MATH_INLINE int +__NTH (__signbitf (float __x)) +{ + __extension__ union { float __f; int __i; } __u = { __f: __x }; + return __u.__i < 0; +} +__MATH_INLINE int +__NTH (__signbit (double __x)) +{ + __extension__ union { double __d; int __i[2]; } __u = { __d: __x }; + return __u.__i[1] < 0; +} +__MATH_INLINE int +__NTH (__signbitl (long double __x)) +{ + __extension__ union { long double __l; int __i[3]; } __u = { __l: __x }; + return (__u.__i[2] & 0x8000) != 0; +} +# endif +#endif + + +/* The gcc, version 2.7 or below, has problems with all this inlining + code. So disable it for this version of the compiler. */ +#if __GNUC_PREREQ (2, 8) + +#if ((!defined __NO_MATH_INLINES || defined __LIBC_INTERNAL_MATH_INLINES) \ + && defined __OPTIMIZE__) + +/* A macro to define float, double, and long double versions of various + math functions for the ix87 FPU. FUNC is the function name (which will + be suffixed with f and l for the float and long double version, + respectively). OP is the name of the FPU operation. + We define two sets of macros. The set with the additional NP + doesn't add a prototype declaration. */ + +#if defined __USE_MISC || defined __USE_ISOC99 +# define __inline_mathop(func, op) \ + __inline_mathop_ (double, func, op) \ + __inline_mathop_ (float, __CONCAT(func,f), op) \ + __inline_mathop_ (long double, __CONCAT(func,l), op) +# define __inline_mathopNP(func, op) \ + __inline_mathopNP_ (double, func, op) \ + __inline_mathopNP_ (float, __CONCAT(func,f), op) \ + __inline_mathopNP_ (long double, __CONCAT(func,l), op) +#else +# define __inline_mathop(func, op) \ + __inline_mathop_ (double, func, op) +# define __inline_mathopNP(func, op) \ + __inline_mathopNP_ (double, func, op) +#endif + +#define __inline_mathop_(float_type, func, op) \ + __inline_mathop_decl_ (float_type, func, op, "0" (__x)) +#define __inline_mathopNP_(float_type, func, op) \ + __inline_mathop_declNP_ (float_type, func, op, "0" (__x)) + + +#if defined __USE_MISC || defined __USE_ISOC99 +# define __inline_mathop_decl(func, op, params...) \ + __inline_mathop_decl_ (double, func, op, params) \ + __inline_mathop_decl_ (float, __CONCAT(func,f), op, params) \ + __inline_mathop_decl_ (long double, __CONCAT(func,l), op, params) +# define __inline_mathop_declNP(func, op, params...) \ + __inline_mathop_declNP_ (double, func, op, params) \ + __inline_mathop_declNP_ (float, __CONCAT(func,f), op, params) \ + __inline_mathop_declNP_ (long double, __CONCAT(func,l), op, params) +#else +# define __inline_mathop_decl(func, op, params...) \ + __inline_mathop_decl_ (double, func, op, params) +# define __inline_mathop_declNP(func, op, params...) \ + __inline_mathop_declNP_ (double, func, op, params) +#endif + +#define __inline_mathop_decl_(float_type, func, op, params...) \ + __MATH_INLINE float_type func (float_type) __THROW; \ + __inline_mathop_declNP_ (float_type, func, op, params) + +#define __inline_mathop_declNP_(float_type, func, op, params...) \ + __MATH_INLINE float_type __NTH (func (float_type __x)) \ + { \ + register float_type __result; \ + __asm__ __volatile__ (op : "=t" (__result) : params); \ + return __result; \ + } + + +#if defined __USE_MISC || defined __USE_ISOC99 +# define __inline_mathcode(func, arg, code) \ + __inline_mathcode_ (double, func, arg, code) \ + __inline_mathcode_ (float, __CONCAT(func,f), arg, code) \ + __inline_mathcode_ (long double, __CONCAT(func,l), arg, code) +# define __inline_mathcodeNP(func, arg, code) \ + __inline_mathcodeNP_ (double, func, arg, code) \ + __inline_mathcodeNP_ (float, __CONCAT(func,f), arg, code) \ + __inline_mathcodeNP_ (long double, __CONCAT(func,l), arg, code) +# define __inline_mathcode2(func, arg1, arg2, code) \ + __inline_mathcode2_ (double, func, arg1, arg2, code) \ + __inline_mathcode2_ (float, __CONCAT(func,f), arg1, arg2, code) \ + __inline_mathcode2_ (long double, __CONCAT(func,l), arg1, arg2, code) +# define __inline_mathcodeNP2(func, arg1, arg2, code) \ + __inline_mathcodeNP2_ (double, func, arg1, arg2, code) \ + __inline_mathcodeNP2_ (float, __CONCAT(func,f), arg1, arg2, code) \ + __inline_mathcodeNP2_ (long double, __CONCAT(func,l), arg1, arg2, code) +# define __inline_mathcode3(func, arg1, arg2, arg3, code) \ + __inline_mathcode3_ (double, func, arg1, arg2, arg3, code) \ + __inline_mathcode3_ (float, __CONCAT(func,f), arg1, arg2, arg3, code) \ + __inline_mathcode3_ (long double, __CONCAT(func,l), arg1, arg2, arg3, code) +# define __inline_mathcodeNP3(func, arg1, arg2, arg3, code) \ + __inline_mathcodeNP3_ (double, func, arg1, arg2, arg3, code) \ + __inline_mathcodeNP3_ (float, __CONCAT(func,f), arg1, arg2, arg3, code) \ + __inline_mathcodeNP3_ (long double, __CONCAT(func,l), arg1, arg2, arg3, code) +#else +# define __inline_mathcode(func, arg, code) \ + __inline_mathcode_ (double, func, (arg), code) +# define __inline_mathcodeNP(func, arg, code) \ + __inline_mathcodeNP_ (double, func, (arg), code) +# define __inline_mathcode2(func, arg1, arg2, code) \ + __inline_mathcode2_ (double, func, arg1, arg2, code) +# define __inline_mathcodeNP2(func, arg1, arg2, code) \ + __inline_mathcodeNP2_ (double, func, arg1, arg2, code) +# define __inline_mathcode3(func, arg1, arg2, arg3, code) \ + __inline_mathcode3_ (double, func, arg1, arg2, arg3, code) +# define __inline_mathcodeNP3(func, arg1, arg2, arg3, code) \ + __inline_mathcodeNP3_ (double, func, arg1, arg2, arg3, code) +#endif + +#define __inline_mathcode_(float_type, func, arg, code) \ + __MATH_INLINE float_type func (float_type) __THROW; \ + __inline_mathcodeNP_(float_type, func, arg, code) + +#define __inline_mathcodeNP_(float_type, func, arg, code) \ + __MATH_INLINE float_type __NTH (func (float_type arg)) \ + { \ + code; \ + } + + +#define __inline_mathcode2_(float_type, func, arg1, arg2, code) \ + __MATH_INLINE float_type func (float_type, float_type) __THROW; \ + __inline_mathcodeNP2_ (float_type, func, arg1, arg2, code) + +#define __inline_mathcodeNP2_(float_type, func, arg1, arg2, code) \ + __MATH_INLINE float_type __NTH (func (float_type arg1, float_type arg2)) \ + { \ + code; \ + } + +#define __inline_mathcode3_(float_type, func, arg1, arg2, arg3, code) \ + __MATH_INLINE float_type func (float_type, float_type, float_type) __THROW; \ + __inline_mathcodeNP3_(float_type, func, arg1, arg2, arg3, code) + +#define __inline_mathcodeNP3_(float_type, func, arg1, arg2, arg3, code) \ + __MATH_INLINE float_type __NTH (func (float_type arg1, float_type arg2, \ + float_type arg3)) \ + { \ + code; \ + } +#endif + + +#if !defined __NO_MATH_INLINES && defined __OPTIMIZE__ +/* Miscellaneous functions */ + +__inline_mathcode (__sgn, __x, \ + return __x == 0.0 ? 0.0 : (__x > 0.0 ? 1.0 : -1.0)) + +/* __FAST_MATH__ is defined by gcc -ffast-math. */ +#ifdef __FAST_MATH__ +__inline_mathcode (__pow2, __x, \ + register long double __value; \ + register long double __exponent; \ + __extension__ long long int __p = (long long int) __x; \ + if (__x == (long double) __p) \ + { \ + __asm__ __volatile__ \ + ("fscale" \ + : "=t" (__value) : "0" (1.0), "u" (__x)); \ + return __value; \ + } \ + __asm__ __volatile__ \ + ("fld %%st(0)\n\t" \ + "frndint # int(x)\n\t" \ + "fxch\n\t" \ + "fsub %%st(1) # fract(x)\n\t" \ + "f2xm1 # 2^(fract(x)) - 1\n\t" \ + : "=t" (__value), "=u" (__exponent) : "0" (__x)); \ + __value += 1.0; \ + __asm__ __volatile__ \ + ("fscale" \ + : "=t" (__value) : "0" (__value), "u" (__exponent)); \ + return __value) + +# ifdef __USE_GNU +# define __sincos_code \ + register long double __cosr; \ + register long double __sinr; \ + __asm__ __volatile__ \ + ("fsincos\n\t" \ + "fnstsw %%ax\n\t" \ + "testl $0x400, %%eax\n\t" \ + "jz 1f\n\t" \ + "fldpi\n\t" \ + "fadd %%st(0)\n\t" \ + "fxch %%st(1)\n\t" \ + "2: fprem1\n\t" \ + "fnstsw %%ax\n\t" \ + "testl $0x400, %%eax\n\t" \ + "jnz 2b\n\t" \ + "fstp %%st(1)\n\t" \ + "fsincos\n\t" \ + "1:" \ + : "=t" (__cosr), "=u" (__sinr) : "0" (__x)); \ + *__sinx = __sinr; \ + *__cosx = __cosr + +__MATH_INLINE void +__NTH (__sincos (double __x, double *__sinx, double *__cosx)) +{ + __sincos_code; +} + +__MATH_INLINE void +__NTH (__sincosf (float __x, float *__sinx, float *__cosx)) +{ + __sincos_code; +} + +__MATH_INLINE void +__NTH (__sincosl (long double __x, long double *__sinx, long double *__cosx)) +{ + __sincos_code; +} +# endif + + +/* Optimized inline implementation, sometimes with reduced precision + and/or argument range. */ + +# if __GNUC_PREREQ (3, 5) +# define __expm1_code \ + register long double __temp; \ + __temp = __builtin_expm1l (__x); \ + return __temp ? __temp : __x +# else +# define __expm1_code \ + register long double __value; \ + register long double __exponent; \ + register long double __temp; \ + __asm__ __volatile__ \ + ("fldl2e # e^x - 1 = 2^(x * log2(e)) - 1\n\t" \ + "fmul %%st(1) # x * log2(e)\n\t" \ + "fst %%st(1)\n\t" \ + "frndint # int(x * log2(e))\n\t" \ + "fxch\n\t" \ + "fsub %%st(1) # fract(x * log2(e))\n\t" \ + "f2xm1 # 2^(fract(x * log2(e))) - 1\n\t" \ + "fscale # 2^(x * log2(e)) - 2^(int(x * log2(e)))\n\t" \ + : "=t" (__value), "=u" (__exponent) : "0" (__x)); \ + __asm__ __volatile__ \ + ("fscale # 2^int(x * log2(e))\n\t" \ + : "=t" (__temp) : "0" (1.0), "u" (__exponent)); \ + __temp -= 1.0; \ + __temp += __value; \ + return __temp ? __temp : __x +# endif +__inline_mathcodeNP_ (long double, __expm1l, __x, __expm1_code) + +# if __GNUC_PREREQ (3, 4) +__inline_mathcodeNP_ (long double, __expl, __x, return __builtin_expl (__x)) +# else +# define __exp_code \ + register long double __value; \ + register long double __exponent; \ + __asm__ __volatile__ \ + ("fldl2e # e^x = 2^(x * log2(e))\n\t" \ + "fmul %%st(1) # x * log2(e)\n\t" \ + "fst %%st(1)\n\t" \ + "frndint # int(x * log2(e))\n\t" \ + "fxch\n\t" \ + "fsub %%st(1) # fract(x * log2(e))\n\t" \ + "f2xm1 # 2^(fract(x * log2(e))) - 1\n\t" \ + : "=t" (__value), "=u" (__exponent) : "0" (__x)); \ + __value += 1.0; \ + __asm__ __volatile__ \ + ("fscale" \ + : "=t" (__value) : "0" (__value), "u" (__exponent)); \ + return __value +__inline_mathcodeNP (exp, __x, __exp_code) +__inline_mathcodeNP_ (long double, __expl, __x, __exp_code) +# endif + + +# if !__GNUC_PREREQ (3, 5) +__inline_mathcodeNP (tan, __x, \ + register long double __value; \ + register long double __value2 __attribute__ ((__unused__)); \ + __asm__ __volatile__ \ + ("fptan" \ + : "=t" (__value2), "=u" (__value) : "0" (__x)); \ + return __value) +# endif +#endif /* __FAST_MATH__ */ + + +#if __GNUC_PREREQ (3, 4) +__inline_mathcodeNP2_ (long double, __atan2l, __y, __x, + return __builtin_atan2l (__y, __x)) +#else +# define __atan2_code \ + register long double __value; \ + __asm__ __volatile__ \ + ("fpatan" \ + : "=t" (__value) : "0" (__x), "u" (__y) : "st(1)"); \ + return __value +# ifdef __FAST_MATH__ +__inline_mathcodeNP2 (atan2, __y, __x, __atan2_code) +# endif +__inline_mathcodeNP2_ (long double, __atan2l, __y, __x, __atan2_code) +#endif + + +#if defined __FAST_MATH__ && !__GNUC_PREREQ (3, 5) +__inline_mathcodeNP2 (fmod, __x, __y, \ + register long double __value; \ + __asm__ __volatile__ \ + ("1: fprem\n\t" \ + "fnstsw %%ax\n\t" \ + "sahf\n\t" \ + "jp 1b" \ + : "=t" (__value) : "0" (__x), "u" (__y) : "ax", "cc"); \ + return __value) +#endif + + +#ifdef __FAST_MATH__ +# if !__GNUC_PREREQ (3,3) +__inline_mathopNP (sqrt, "fsqrt") +__inline_mathopNP_ (long double, __sqrtl, "fsqrt") +# define __libc_sqrtl(n) __sqrtl (n) +# else +# define __libc_sqrtl(n) __builtin_sqrtl (n) +# endif +#endif + +#if __GNUC_PREREQ (2, 8) +__inline_mathcodeNP_ (double, fabs, __x, return __builtin_fabs (__x)) +# if defined __USE_MISC || defined __USE_ISOC99 +__inline_mathcodeNP_ (float, fabsf, __x, return __builtin_fabsf (__x)) +__inline_mathcodeNP_ (long double, fabsl, __x, return __builtin_fabsl (__x)) +# endif +__inline_mathcodeNP_ (long double, __fabsl, __x, return __builtin_fabsl (__x)) +#else +__inline_mathop (fabs, "fabs") +__inline_mathop_ (long double, __fabsl, "fabs") +#endif + +#ifdef __FAST_MATH__ +# if !__GNUC_PREREQ (3, 4) +/* The argument range of this inline version is reduced. */ +__inline_mathopNP (sin, "fsin") +/* The argument range of this inline version is reduced. */ +__inline_mathopNP (cos, "fcos") + +__inline_mathop_declNP (log, "fldln2; fxch; fyl2x", "0" (__x) : "st(1)") +# endif + +# if !__GNUC_PREREQ (3, 5) +__inline_mathop_declNP (log10, "fldlg2; fxch; fyl2x", "0" (__x) : "st(1)") + +__inline_mathcodeNP (asin, __x, return __atan2l (__x, __libc_sqrtl (1.0 - __x * __x))) +__inline_mathcodeNP (acos, __x, return __atan2l (__libc_sqrtl (1.0 - __x * __x), __x)) +# endif + +# if !__GNUC_PREREQ (3, 4) +__inline_mathop_declNP (atan, "fld1; fpatan", "0" (__x) : "st(1)") +# endif +#endif /* __FAST_MATH__ */ + +__inline_mathcode_ (long double, __sgn1l, __x, \ + __extension__ union { long double __xld; unsigned int __xi[3]; } __n = \ + { __xld: __x }; \ + __n.__xi[2] = (__n.__xi[2] & 0x8000) | 0x3fff; \ + __n.__xi[1] = 0x80000000; \ + __n.__xi[0] = 0; \ + return __n.__xld) + + +#ifdef __FAST_MATH__ +/* The argument range of the inline version of sinhl is slightly reduced. */ +__inline_mathcodeNP (sinh, __x, \ + register long double __exm1 = __expm1l (__fabsl (__x)); \ + return 0.5 * (__exm1 / (__exm1 + 1.0) + __exm1) * __sgn1l (__x)) + +__inline_mathcodeNP (cosh, __x, \ + register long double __ex = __expl (__x); \ + return 0.5 * (__ex + 1.0 / __ex)) + +__inline_mathcodeNP (tanh, __x, \ + register long double __exm1 = __expm1l (-__fabsl (__x + __x)); \ + return __exm1 / (__exm1 + 2.0) * __sgn1l (-__x)) +#endif + +__inline_mathcodeNP (floor, __x, \ + register long double __value; \ + __volatile__ unsigned short int __cw; \ + __volatile__ unsigned short int __cwtmp; \ + __asm__ __volatile__ ("fnstcw %0" : "=m" (__cw)); \ + __cwtmp = (__cw & 0xf3ff) | 0x0400; /* rounding down */ \ + __asm__ __volatile__ ("fldcw %0" : : "m" (__cwtmp)); \ + __asm__ __volatile__ ("frndint" : "=t" (__value) : "0" (__x)); \ + __asm__ __volatile__ ("fldcw %0" : : "m" (__cw)); \ + return __value) + +__inline_mathcodeNP (ceil, __x, \ + register long double __value; \ + __volatile__ unsigned short int __cw; \ + __volatile__ unsigned short int __cwtmp; \ + __asm__ __volatile__ ("fnstcw %0" : "=m" (__cw)); \ + __cwtmp = (__cw & 0xf3ff) | 0x0800; /* rounding up */ \ + __asm__ __volatile__ ("fldcw %0" : : "m" (__cwtmp)); \ + __asm__ __volatile__ ("frndint" : "=t" (__value) : "0" (__x)); \ + __asm__ __volatile__ ("fldcw %0" : : "m" (__cw)); \ + return __value) + +#ifdef __FAST_MATH__ +# define __ldexp_code \ + register long double __value; \ + __asm__ __volatile__ \ + ("fscale" \ + : "=t" (__value) : "0" (__x), "u" ((long double) __y)); \ + return __value + +__MATH_INLINE double +__NTH (ldexp (double __x, int __y)) +{ + __ldexp_code; +} +#endif + + +/* Optimized versions for some non-standardized functions. */ +#if defined __USE_ISOC99 || defined __USE_MISC + +# ifdef __FAST_MATH__ +__inline_mathcodeNP (expm1, __x, __expm1_code) + +/* We cannot rely on M_SQRT being defined. So we do it for ourself + here. */ +# define __M_SQRT2 1.41421356237309504880L /* sqrt(2) */ + +# if !__GNUC_PREREQ (3, 5) +__inline_mathcodeNP (log1p, __x, \ + register long double __value; \ + if (__fabsl (__x) >= 1.0 - 0.5 * __M_SQRT2) \ + __value = logl (1.0 + __x); \ + else \ + __asm__ __volatile__ \ + ("fldln2\n\t" \ + "fxch\n\t" \ + "fyl2xp1" \ + : "=t" (__value) : "0" (__x) : "st(1)"); \ + return __value) +# endif + + +/* The argument range of the inline version of asinhl is slightly reduced. */ +__inline_mathcodeNP (asinh, __x, \ + register long double __y = __fabsl (__x); \ + return (log1pl (__y * __y / (__libc_sqrtl (__y * __y + 1.0) + 1.0) + __y) \ + * __sgn1l (__x))) + +__inline_mathcodeNP (acosh, __x, \ + return logl (__x + __libc_sqrtl (__x - 1.0) * __libc_sqrtl (__x + 1.0))) + +__inline_mathcodeNP (atanh, __x, \ + register long double __y = __fabsl (__x); \ + return -0.5 * log1pl (-(__y + __y) / (1.0 + __y)) * __sgn1l (__x)) + +/* The argument range of the inline version of hypotl is slightly reduced. */ +__inline_mathcodeNP2 (hypot, __x, __y, + return __libc_sqrtl (__x * __x + __y * __y)) + +# if !__GNUC_PREREQ (3, 5) +__inline_mathcodeNP(logb, __x, \ + register long double __value; \ + register long double __junk; \ + __asm__ __volatile__ \ + ("fxtract\n\t" \ + : "=t" (__junk), "=u" (__value) : "0" (__x)); \ + return __value) +# endif + +# endif +#endif + +#ifdef __USE_ISOC99 +# ifdef __FAST_MATH__ + +# if !__GNUC_PREREQ (3, 5) +__inline_mathop_declNP (log2, "fld1; fxch; fyl2x", "0" (__x) : "st(1)") +# endif + +__MATH_INLINE float +__NTH (ldexpf (float __x, int __y)) +{ + __ldexp_code; +} + +__MATH_INLINE long double +__NTH (ldexpl (long double __x, int __y)) +{ + __ldexp_code; +} + +__inline_mathcodeNP3 (fma, __x, __y, __z, return (__x * __y) + __z) + +__inline_mathopNP (rint, "frndint") +# endif /* __FAST_MATH__ */ + +# define __lrint_code \ + long int __lrintres; \ + __asm__ __volatile__ \ + ("fistpl %0" \ + : "=m" (__lrintres) : "t" (__x) : "st"); \ + return __lrintres +__MATH_INLINE long int +__NTH (lrintf (float __x)) +{ + __lrint_code; +} +__MATH_INLINE long int +__NTH (lrint (double __x)) +{ + __lrint_code; +} +__MATH_INLINE long int +__NTH (lrintl (long double __x)) +{ + __lrint_code; +} +# undef __lrint_code + +# define __llrint_code \ + long long int __llrintres; \ + __asm__ __volatile__ \ + ("fistpll %0" \ + : "=m" (__llrintres) : "t" (__x) : "st"); \ + return __llrintres +__MATH_INLINE long long int +__NTH (llrintf (float __x)) +{ + __llrint_code; +} +__MATH_INLINE long long int +__NTH (llrint (double __x)) +{ + __llrint_code; +} +__MATH_INLINE long long int +__NTH (llrintl (long double __x)) +{ + __llrint_code; +} +# undef __llrint_code + +#endif + + +#ifdef __USE_MISC + +# if defined __FAST_MATH__ && !__GNUC_PREREQ (3, 5) +__inline_mathcodeNP2 (drem, __x, __y, \ + register double __value; \ + register int __clobbered; \ + __asm__ __volatile__ \ + ("1: fprem1\n\t" \ + "fstsw %%ax\n\t" \ + "sahf\n\t" \ + "jp 1b" \ + : "=t" (__value), "=&a" (__clobbered) : "0" (__x), "u" (__y) : "cc"); \ + return __value) +# endif + + +/* This function is used in the `isfinite' macro. */ +__MATH_INLINE int +__NTH (__finite (double __x)) +{ + union { double __d; int __i[2]; } u; + u.__d = __x; + /* Finite numbers have at least one zero bit in exponent. */ + /* All other numbers will result in 0xffffffff after OR: */ + return (u.__i[1] | 0x800fffff) != 0xffffffff; +} + +__MATH_INLINE int +__NTH (__finitef (float __x)) +{ + union { float __d; int __i; } u; + u.__d = __x; + return (u.__i | 0x807fffff) != 0xffffffff; +} + + +/* Miscellaneous functions */ +# ifdef __FAST_MATH__ +__inline_mathcode (__coshm1, __x, \ + register long double __exm1 = __expm1l (__fabsl (__x)); \ + return 0.5 * (__exm1 / (__exm1 + 1.0)) * __exm1) + +__inline_mathcode (__acosh1p, __x, \ + return log1pl (__x + __libc_sqrtl (__x) * __libc_sqrtl (__x + 2.0))) + +# endif /* __FAST_MATH__ */ +#endif /* __USE_MISC */ + +/* Undefine some of the large macros which are not used anymore. */ +#undef __atan2_code +#ifdef __FAST_MATH__ +# undef __expm1_code +# undef __exp_code +# undef __sincos_code +#endif /* __FAST_MATH__ */ + +#endif /* __NO_MATH_INLINES */ + + +/* This code is used internally in the GNU libc. */ +#ifdef __LIBC_INTERNAL_MATH_INLINES +__inline_mathop (__ieee754_sqrt, "fsqrt") +__inline_mathcode2 (__ieee754_atan2, __y, __x, + register long double __value; + __asm__ __volatile__ ("fpatan\n\t" + : "=t" (__value) + : "0" (__x), "u" (__y) : "st(1)"); + return __value;) +#endif + +#endif /* __GNUC__ */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/bits/select.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/bits/select.h new file mode 100644 index 00000000..972bfb68 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/bits/select.h @@ -0,0 +1,72 @@ +/* Copyright (C) 1997, 1998, 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_SELECT_H +# error "Never use directly; include instead." +#endif + + +#if defined __GNUC__ && __GNUC__ >= 2 + +# define __FD_ZERO(fdsp) \ + do { \ + int __d0, __d1; \ + __asm__ __volatile__ ("cld; rep; stosl" \ + : "=c" (__d0), "=D" (__d1) \ + : "a" (0), "0" (sizeof (fd_set) \ + / sizeof (__fd_mask)), \ + "1" (&__FDS_BITS (fdsp)[0]) \ + : "memory"); \ + } while (0) + +# define __FD_SET(fd, fdsp) \ + __asm__ __volatile__ ("btsl %1,%0" \ + : "=m" (__FDS_BITS (fdsp)[__FDELT (fd)]) \ + : "r" (((int) (fd)) % __NFDBITS) \ + : "cc","memory") +# define __FD_CLR(fd, fdsp) \ + __asm__ __volatile__ ("btrl %1,%0" \ + : "=m" (__FDS_BITS (fdsp)[__FDELT (fd)]) \ + : "r" (((int) (fd)) % __NFDBITS) \ + : "cc","memory") +# define __FD_ISSET(fd, fdsp) \ + (__extension__ \ + ({register char __result; \ + __asm__ __volatile__ ("btl %1,%2 ; setcb %b0" \ + : "=q" (__result) \ + : "r" (((int) (fd)) % __NFDBITS), \ + "m" (__FDS_BITS (fdsp)[__FDELT (fd)]) \ + : "cc"); \ + __result; })) + +#else /* ! GNU CC */ + +/* We don't use `memset' because this would require a prototype and + the array isn't too big. */ +# define __FD_ZERO(set) \ + do { \ + unsigned int __i; \ + fd_set *__arr = (set); \ + for (__i = 0; __i < sizeof (fd_set) / sizeof (__fd_mask); ++__i) \ + __FDS_BITS (__arr)[__i] = 0; \ + } while (0) +# define __FD_SET(d, set) (__FDS_BITS (set)[__FDELT (d)] |= __FDMASK (d)) +# define __FD_CLR(d, set) (__FDS_BITS (set)[__FDELT (d)] &= ~__FDMASK (d)) +# define __FD_ISSET(d, set) (__FDS_BITS (set)[__FDELT (d)] & __FDMASK (d)) + +#endif /* GNU CC */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/bits/setjmp.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/bits/setjmp.h new file mode 100644 index 00000000..107fe58b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/bits/setjmp.h @@ -0,0 +1,46 @@ +/* Copyright (C) 1997, 1998, 2000, 2001, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Define the machine-dependent type `jmp_buf'. Intel 386 version. */ +#ifndef _BITS_SETJMP_H +#define _BITS_SETJMP_H 1 + +#if !defined _SETJMP_H && !defined _PTHREAD_H +# error "Never include directly; use instead." +#endif + +#if defined __USE_MISC || defined _ASM +# define JB_BX 0 +# define JB_SI 1 +# define JB_DI 2 +# define JB_BP 3 +# define JB_SP 4 +# define JB_PC 5 +# define JB_SIZE 24 +#endif + +#ifndef _ASM +typedef int __jmp_buf[6]; +#endif + +/* Test if longjmp to JMPBUF would unwind the frame + containing a local variable at ADDRESS. */ +#define _JMPBUF_UNWINDS(jmpbuf, address) \ + ((void *) (address) < (void *) (jmpbuf)[JB_SP]) + +#endif /* bits/setjmp.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/bits/sigcontextinfo.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/bits/sigcontextinfo.h new file mode 100644 index 00000000..b7367bac --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/bits/sigcontextinfo.h @@ -0,0 +1,51 @@ +/* Copyright (C) 1998, 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define SIGCONTEXT struct sigcontext +#define SIGCONTEXT_EXTRA_ARGS +#define GET_PC(ctx) ((void *) ctx.eip) +#define GET_FRAME(ctx) ((void *) ctx.ebp) +#define GET_STACK(ctx) ((void *) ctx.esp_at_signal) +#define CALL_SIGHANDLER(handler, signo, ctx) \ +do { \ + int __tmp1, __tmp2, __tmp3, __tmp4; \ + __asm__ __volatile__ ("movl\t%%esp, %%edi\n\t" \ + "andl\t$-16, %%esp\n\t" \ + "subl\t%8, %%esp\n\t" \ + "movl\t%%edi, %c8-4(%%esp)\n\t" \ + "movl\t%1, 0(%%esp)\n\t" \ + "leal\t4(%%esp), %%edi\n\t" \ + "cld\n\t" \ + "rep\tmovsl\n\t" \ + "call\t*%0\n\t" \ + "cld\n\t" \ + "movl\t%9, %%ecx\n\t" \ + "subl\t%%edi, %%esi\n\t" \ + "leal\t4(%%esp,%%esi,1), %%edi\n\t" \ + "leal\t4(%%esp), %%esi\n\t" \ + "rep\tmovsl\n\t" \ + "movl\t%c8-4(%%esp), %%esp\n\t" \ + : "=a" (__tmp1), "=d" (__tmp2), "=S" (__tmp3), \ + "=c" (__tmp4) \ + : "0" (handler), "1" (signo), "2" (&ctx), \ + "3" (sizeof (struct sigcontext) / 4), \ + "n" ((sizeof (struct sigcontext) + 19) & ~15), \ + "i" (sizeof (struct sigcontext) / 4) \ + : "cc", "edi"); \ +} while (0) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/bits/stackinfo.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/bits/stackinfo.h new file mode 100644 index 00000000..a9a6745a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/bits/stackinfo.h @@ -0,0 +1,28 @@ +/* Copyright (C) 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This file contains a bit of information about the stack allocation + of the processor. */ + +#ifndef _STACKINFO_H +#define _STACKINFO_H 1 + +/* On x86 the stack grows down. */ +#define _STACK_GROWS_DOWN 1 + +#endif /* stackinfo.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/bits/syscalls.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/bits/syscalls.h new file mode 100644 index 00000000..9184bd6c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/bits/syscalls.h @@ -0,0 +1,189 @@ +#ifndef _BITS_SYSCALLS_H +#define _BITS_SYSCALLS_H + +#ifndef _SYSCALL_H +# error "Never use directly; include instead." +#endif + +/* + * Some of the sneaky macros in the code were taken from + * glibc-2.2.5/sysdeps/unix/sysv/linux/i386/sysdep.h + */ + +#ifndef __ASSEMBLER__ + +#include + +#define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \ +({ \ + register unsigned int resultvar; \ + __asm__ __volatile__ ( \ + LOADARGS_##nr \ + "movl %1, %%eax\n\t" \ + "int $0x80\n\t" \ + RESTOREARGS_##nr \ + : "=a" (resultvar) \ + : "g" (name) ASMFMT_##nr(args) : "memory", "cc" \ + ); \ + (int) resultvar; \ +}) + + +#if 1 /* defined __PIC__ || defined __pic__ */ + +/* This code avoids pushing/popping ebx as much as possible. + * I think the main reason was that older GCCs had problems + * with proper saving/restoring of ebx if "b" constraint was used, + * which was breaking -fPIC code really badly. + * At least gcc 4.2.x seems to not need these tricks anymore, + * but this code is still useful because it often avoids + * using stack for saving ebx. + * Keeping it unconditionally enabled for now. + */ + +/* We need some help from the assembler to generate optimal code. + * We define some macros here which later will be used. */ + +__asm__ ( +#ifdef __DOMULTI__ + /* Protect against asm macro redefinition (happens in __DOMULTI__ mode). + * Unfortunately, it ends up visible in .o files. */ + ".ifndef _BITS_SYSCALLS_ASM\n\t" + ".set _BITS_SYSCALLS_ASM,1\n\t" +#endif + ".L__X'%ebx = 1\n\t" + ".L__X'%ecx = 2\n\t" + ".L__X'%edx = 2\n\t" + ".L__X'%eax = 3\n\t" + ".L__X'%esi = 3\n\t" + ".L__X'%edi = 3\n\t" + ".L__X'%ebp = 3\n\t" + ".L__X'%esp = 3\n\t" + + /* Loading param #1 (ebx) is done by loading it into + * another register, and then performing bpushl+bmovl, + * since we must preserve ebx */ + + ".macro bpushl name reg\n\t" + ".if 1 - \\name\n\t" /* if reg!=ebx... */ + ".if 2 - \\name\n\t" /* if reg can't be clobbered... */ + "pushl %ebx\n\t" /* save ebx on stack */ + ".else\n\t" + "xchgl \\reg, %ebx\n\t" /* else save ebx in reg, and load reg to ebx */ + ".endif\n\t" + ".endif\n\t" + ".endm\n\t" + + ".macro bmovl name reg\n\t" + ".if 1 - \\name\n\t" + ".if 2 - \\name\n\t" /* if reg can't be clobbered... */ + "movl \\reg, %ebx\n\t" /* load reg to ebx */ + ".endif\n\t" + ".endif\n\t" + ".endm\n\t" + + ".macro bpopl name reg\n\t" + ".if 1 - \\name\n\t" + ".if 2 - \\name\n\t" /* if reg can't be clobbered... */ + "popl %ebx\n\t" /* restore ebx from stack */ + ".else\n\t" + "xchgl \\reg, %ebx\n\t" /* else restore ebx from reg */ + ".endif\n\t" + ".endif\n\t" + ".endm\n\t" + +#ifdef __DOMULTI__ + ".endif\n\t" /* _BITS_SYSCALLS_ASM */ +#endif +); + +#define LOADARGS_0 +#define LOADARGS_1 "bpushl .L__X'%k2, %k2\n\t" "bmovl .L__X'%k2, %k2\n\t" +#define LOADARGS_2 LOADARGS_1 +#define LOADARGS_3 LOADARGS_1 +#define LOADARGS_4 LOADARGS_1 +#define LOADARGS_5 LOADARGS_1 +#define LOADARGS_6 LOADARGS_1 "push %%ebp\n\t" "movl %7, %%ebp\n\t" + +#define RESTOREARGS_0 +#define RESTOREARGS_1 "bpopl .L__X'%k2, %k2\n\t" +#define RESTOREARGS_2 RESTOREARGS_1 +#define RESTOREARGS_3 RESTOREARGS_1 +#define RESTOREARGS_4 RESTOREARGS_1 +#define RESTOREARGS_5 RESTOREARGS_1 +#define RESTOREARGS_6 "pop %%ebp\n\t" RESTOREARGS_1 + +#define ASMFMT_0() +/* "acdSD" constraint would work too, but "SD" would use esi/edi and cause + * them to be pushed/popped by compiler, "a" would use eax and cause ebx + * to be saved/restored on stack, not in register. Narrowing choice down + * to "ecx or edx" results in smaller and faster code: */ +#define ASMFMT_1(arg1) \ + , "cd" (arg1) +/* Can use "adSD" constraint here: */ +#define ASMFMT_2(arg1, arg2) \ + , "d" (arg1), "c" (arg2) +/* Can use "aSD" constraint here: */ +#define ASMFMT_3(arg1, arg2, arg3) \ + , "a" (arg1), "c" (arg2), "d" (arg3) +/* Can use "aD" constraint here: */ +#define ASMFMT_4(arg1, arg2, arg3, arg4) \ + , "a" (arg1), "c" (arg2), "d" (arg3), "S" (arg4) +#define ASMFMT_5(arg1, arg2, arg3, arg4, arg5) \ + , "a" (arg1), "c" (arg2), "d" (arg3), "S" (arg4), "D" (arg5) +#define ASMFMT_6(arg1, arg2, arg3, arg4, arg5, arg6) \ + , "a" (arg1), "c" (arg2), "d" (arg3), "S" (arg4), "D" (arg5), "m" (arg6) + +#else /* !PIC */ + +/* Simpler code which just uses "b" constraint to load ebx. + * Seems to work with gc 4.2.x, and generates slightly smaller, + * but slightly slower code. Example (time syscall): + * + * - 8b 4c 24 04 mov 0x4(%esp),%ecx + * - 87 cb xchg %ecx,%ebx + * + 53 push %ebx + * + 8b 5c 24 08 mov 0x8(%esp),%ebx + * b8 0d 00 00 00 mov $0xd,%eax + * cd 80 int $0x80 + * - 87 cb xchg %ecx,%ebx + * + 5b pop %ebx + * c3 ret + * + * 2 bytes smaller, but uses stack via "push/pop ebx" + */ + +#define LOADARGS_0 +#define LOADARGS_1 +#define LOADARGS_2 +#define LOADARGS_3 +#define LOADARGS_4 +#define LOADARGS_5 +#define LOADARGS_6 "push %%ebp\n\t" "movl %7, %%ebp\n\t" + +#define RESTOREARGS_0 +#define RESTOREARGS_1 +#define RESTOREARGS_2 +#define RESTOREARGS_3 +#define RESTOREARGS_4 +#define RESTOREARGS_5 +#define RESTOREARGS_6 "pop %%ebp\n\t" + +#define ASMFMT_0() +#define ASMFMT_1(arg1) \ + , "b" (arg1) +#define ASMFMT_2(arg1, arg2) \ + , "b" (arg1), "c" (arg2) +#define ASMFMT_3(arg1, arg2, arg3) \ + , "b" (arg1), "c" (arg2), "d" (arg3) +#define ASMFMT_4(arg1, arg2, arg3, arg4) \ + , "b" (arg1), "c" (arg2), "d" (arg3), "S" (arg4) +#define ASMFMT_5(arg1, arg2, arg3, arg4, arg5) \ + , "b" (arg1), "c" (arg2), "d" (arg3), "S" (arg4), "D" (arg5) +#define ASMFMT_6(arg1, arg2, arg3, arg4, arg5, arg6) \ + , "b" (arg1), "c" (arg2), "d" (arg3), "S" (arg4), "D" (arg5), "m" (arg6) + +#endif /* !PIC */ + +#endif /* __ASSEMBLER__ */ +#endif /* _BITS_SYSCALLS_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/bits/uClibc_arch_features.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/bits/uClibc_arch_features.h new file mode 100644 index 00000000..536e9c15 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/bits/uClibc_arch_features.h @@ -0,0 +1,52 @@ +/* + * Track misc arch-specific features that aren't config options + */ + +#ifndef _BITS_UCLIBC_ARCH_FEATURES_H +#define _BITS_UCLIBC_ARCH_FEATURES_H + +/* instruction used when calling abort() to kill yourself */ +#define __UCLIBC_ABORT_INSTRUCTION__ "hlt" + +/* can your target use syscall6() for mmap ? */ +#undef __UCLIBC_MMAP_HAS_6_ARGS__ + +/* does your target use syscall4() for truncate64 ? (32bit arches only) */ +#undef __UCLIBC_TRUNCATE64_HAS_4_ARGS__ + +/* does your target have a broken create_module() ? */ +#define __UCLIBC_BROKEN_CREATE_MODULE__ + +/* does your target have to worry about older [gs]etrlimit() ? */ +/* this is only an issue on i386 where linux < 2.3.25, so we just assume it works ... */ +#undef __UCLIBC_HANDLE_OLDER_RLIMIT__ + +/* does your target have an asm .set ? */ +#define __UCLIBC_HAVE_ASM_SET_DIRECTIVE__ + +/* define if target doesn't like .global */ +#undef __UCLIBC_ASM_GLOBAL_DIRECTIVE__ + +/* define if target supports .weak */ +#define __UCLIBC_HAVE_ASM_WEAK_DIRECTIVE__ + +/* define if target supports .weakext */ +#undef __UCLIBC_HAVE_ASM_WEAKEXT_DIRECTIVE__ + +/* needed probably only for ppc64 */ +#undef __UCLIBC_HAVE_ASM_GLOBAL_DOT_NAME__ + +/* define if target supports CFI pseudo ops */ +#define __UCLIBC_HAVE_ASM_CFI_DIRECTIVES__ + +/* define if target supports IEEE signed zero floats */ +#define __UCLIBC_HAVE_SIGNED_ZERO__ + +/* only weird assemblers generally need this */ +#undef __UCLIBC_ASM_LINE_SEP__ + +#if defined _LIBC +#define internal_function __attribute__ ((regparm (3), stdcall)) +#endif + +#endif /* _BITS_UCLIBC_ARCH_FEATURES_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/bits/wchar.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/bits/wchar.h new file mode 100644 index 00000000..442a4621 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/bits/wchar.h @@ -0,0 +1,26 @@ +/* wchar_t type related definitions. + Copyright (C) 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _BITS_WCHAR_H +#define _BITS_WCHAR_H 1 + +#define __WCHAR_MIN (-2147483647l - 1l) +#define __WCHAR_MAX (2147483647l) + +#endif /* bits/wchar.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/bits/wordsize.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/bits/wordsize.h new file mode 100644 index 00000000..f4c2144e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/bits/wordsize.h @@ -0,0 +1,25 @@ +/* Copyright (C) 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define __WORDSIZE 32 + +#ifdef _LIBC +#ifndef smallint_type +#define smallint_type char +#endif +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/brk.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/brk.c new file mode 100644 index 00000000..51aa6f85 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/brk.c @@ -0,0 +1,51 @@ +/* brk system call for Linux/i386. + Copyright (C) 1995, 1996, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +/* This must be initialized data because commons can't have aliases. */ +void *__curbrk attribute_hidden = 0; + +int brk(void *addr) +{ + void *newbrk; + + /* %ebx is used in PIC code, need to save/restore it manually. + * gcc won't do it for us if we will request it in constraints + */ + __asm__("pushl %%ebx\n" + "movl %2, %%ebx\n" + "int $0x80\n" + "popl %%ebx\n" + : "=a" (newbrk) + : "0" (__NR_brk), "g" (addr) + ); + + __curbrk = newbrk; + + if (newbrk < addr) { + __set_errno(ENOMEM); + return -1; + } + + return 0; +} +libc_hidden_def(brk) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/bsd-_setjmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/bsd-_setjmp.S new file mode 100644 index 00000000..f3cd6cbf --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/bsd-_setjmp.S @@ -0,0 +1,46 @@ +/* BSD `_setjmp' entry point to `sigsetjmp (..., 0)'. i386 version. + Copyright (C) 1994,1995,1996,1997,2000,2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This just does a tail-call to `__sigsetjmp (ARG, 0)'. + We cannot do it in C because it must be a tail-call, so frame-unwinding + in setjmp doesn't clobber the state restored by longjmp. */ + +#define _ASM +#define _SETJMP_H +#include + +.global _setjmp +.type _setjmp,%function +_setjmp: + xorl %eax, %eax + movl 4 (%esp), %edx + + /* Save registers. */ + movl %ebx, (JB_BX*4)(%edx) + movl %esi, (JB_SI*4)(%edx) + movl %edi, (JB_DI*4)(%edx) + leal 4 (%esp), %ecx /* Save SP as it will be after we return. */ + movl %ecx, (JB_SP*4)(%edx) + movl 0 (%esp), %ecx /* Save PC we are returning to now. */ + movl %ecx, (JB_PC*4)(%edx) + movl %ebp, (JB_BP*4)(%edx) /* Save caller's frame pointer. */ + + movl %eax, JB_SIZE(%edx) /* No signal mask set. */ + ret +.size _setjmp,.-_setjmp diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/bsd-setjmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/bsd-setjmp.S new file mode 100644 index 00000000..df46997d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/bsd-setjmp.S @@ -0,0 +1,60 @@ +/* BSD `setjmp' entry point to `sigsetjmp (..., 1)'. i386 version. + Copyright (C) 1995, 1996, 1997, 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define _ASM +#define _SETJMP_H +#include + +.global setjmp +.type setjmp,%function +setjmp: + movl 4 (%esp), %eax + /* Save registers. */ + movl %ebx, (0 *4)(%eax) + movl %esi, (1 *4)(%eax) + movl %edi, (2 *4)(%eax) + /* Save SP as it will be after we return. */ + leal 4 (%esp), %ecx + movl %ecx, (4 *4)(%eax) + /* Save PC we are returning to now. */ + movl 0 (%esp), %ecx + movl %ecx, (5 *4)(%eax) + /* Save caller's frame pointer. */ + movl %ebp, (3 *4)(%eax) + + /* Call __sigjmp_save. */ + pushl $1 + pushl 8(%esp) +#ifdef __PIC__ + /* We cannot use the PLT, because it requires that %ebx be set, but + we can't save and restore our caller's value. Instead, we do an + indirect jump through the GOT, using for the temporary register + %ecx, which is call-clobbered. */ + call here2 +here2: popl %ecx + addl $_GLOBAL_OFFSET_TABLE_+[.-here2], %ecx + movl __sigjmp_save @GOT (%ecx), %ecx + call *%ecx +#else + call __sigjmp_save +#endif + popl %ecx + popl %edx + ret +.size setjmp,.-setjmp diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/clone.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/clone.S new file mode 100644 index 00000000..a7de3fe2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/clone.S @@ -0,0 +1,131 @@ +/* Copyright (C) 1996-2000,02,03,04,2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson (rth@tamu.edu) + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* clone() is even more special than fork() as it mucks with stacks + and invokes a function in the right context after its all over. + + Hacked up for uClibc by Erik Andersen +*/ + +#define _ERRNO_H 1 +#include +#include + +/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg, + pid_t *ptid, struct user_desc *tls, pid_t *ctid); */ + +#define LINKAGE 4 +#define PTR_SIZE 4 +#define PARMS LINKAGE /* no space for saved regs */ +#define FUNC PARMS +#define STACK FUNC+4 +#define FLAGS STACK+PTR_SIZE +#define ARG FLAGS+4 +#define PTID ARG+PTR_SIZE +#define TLS PTID+PTR_SIZE +#define CTID TLS+PTR_SIZE + +.text +.global clone +.type clone,%function +clone: + /* Sanity check arguments. */ + movl $-EINVAL,%eax + + /* no NULL function pointers */ + movl FUNC(%esp),%ecx +#ifdef __PIC__ + jecxz __error +#else + testl %ecx,%ecx + jz __error +#endif + + /* no NULL stack pointers */ + movl STACK(%esp),%ecx +#ifdef __PIC__ + jecxz __error +#else + testl %ecx,%ecx + jz __error +#endif + + /* Insert the argument onto the new stack. Make sure the new + thread is started with an alignment of (mod 16). */ + andl $0xfffffff0, %ecx + subl $28,%ecx + movl ARG(%esp),%eax /* no negative argument counts */ + movl %eax,12(%ecx) + + /* Save the function pointer as the zeroth argument. + It will be popped off in the child in the ebx frobbing below. */ + movl FUNC(%esp),%eax + movl %eax,8(%ecx) + /* Don't leak any information. */ + movl $0,4(%ecx) +#ifndef RESET_PID + movl $0,(%ecx) +#endif + + + /* Do the system call */ + pushl %ebx + pushl %esi + pushl %edi + movl TLS+12(%esp),%esi + movl PTID+12(%esp),%edx + movl FLAGS+12(%esp),%ebx + movl CTID+12(%esp),%edi + movl $__NR_clone,%eax +#ifdef RESET_PID + /* Remember the flag value. */ + movl %ebx, (%ecx) +#endif + int $0x80 + popl %edi + popl %esi + popl %ebx + + test %eax,%eax + jl __error + jz .Lthread_start + ret + +.Lthread_start: + /* Note: %esi is zero. */ + movl %esi,%ebp /* terminate the stack frame */ + call *%ebx +#ifdef __PIC__ + call .Lhere +.Lhere: + popl %ebx + addl $_GLOBAL_OFFSET_TABLE_+[.-.Lhere], %ebx +#endif + movl %eax, %ebx + movl $__NR_exit, %eax + int $0x80 + +/* Need to indirect jump to syscall error + * or we end up with TEXTREL's + */ +__error: + jmp __syscall_error + +.size clone,.-clone +weak_alias(clone, __clone) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/crt1.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/crt1.S new file mode 100644 index 00000000..a133cb9e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/crt1.S @@ -0,0 +1,140 @@ +/* Startup code compliant to the ELF i386 ABI. + Copyright (C) 1995, 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2004 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file with other + programs, and to distribute those programs without any restriction + coming from the use of this file. (The GNU Lesser General Public + License restrictions do apply in other respects; for example, they + cover modification of the file, and distribution when not linked + into another program.) + + Note that people who make modified versions of this file are not + obligated to grant this special exception for their modified + versions; it is their choice whether to do so. The GNU Lesser + General Public License gives permission to release a modified + version without this exception; this exception also makes it + possible to release a modified version which carries forward this + exception. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This is the canonical entry point, usually the first thing in the text + segment. The SVR4/i386 ABI (pages 3-31, 3-32) says that when the entry + point runs, most registers' values are unspecified, except for: + + %edx Contains a function pointer to be registered with `atexit'. + This is how the dynamic linker arranges to have DT_FINI + functions called for shared libraries that have been loaded + before this code runs. + + %esp The stack contains the arguments and environment: + 0(%esp) argc + 4(%esp) argv[0] + ... + (4*argc)(%esp) NULL + (4*(argc+1))(%esp) envp[0] + ... + NULL +*/ + +#include + +.text +.global _start +.type _start,%function +#if defined(__UCLIBC_CTOR_DTOR__) +.type _init,%function +.type _fini,%function +#else +.weak _init +.weak _fini +#endif +.type main,%function +.type __uClibc_main,%function +_start: + /* Clear the frame pointer. The ABI suggests this be done, to mark + the outermost frame obviously. */ + xorl %ebp, %ebp + + /* Extract the arguments as encoded on the stack and set up + the arguments for `main': argc, argv. envp will be determined + later in __libc_start_main. */ + popl %esi /* Pop the argument count. */ + movl %esp, %ecx /* argv starts just at the current stack top.*/ + + /* Before pushing the arguments align the stack to a 16-byte + (SSE needs 16-byte alignment) boundary to avoid penalties from + misaligned accesses. Thanks to Edward Seidl + for pointing this out. */ + andl $0xfffffff0, %esp + pushl %eax /* Push garbage because we allocate + 28 more bytes. */ + + /* Provide the highest stack address to the user code (for stacks + which grow downwards). */ + pushl %esp + + pushl %edx /* Push address of the shared library + termination function. */ + +#ifdef __PIC__ + /* Load PIC register. */ + call .L0 +.L0: + pop %ebx + addl $_GLOBAL_OFFSET_TABLE_+[.-.L0],%ebx + + /* Push address of our own entry points to .fini and .init. */ + pushl _fini@GOT(%ebx) + pushl _init@GOT(%ebx) + + pushl %ecx /* Push second argument: argv. */ + pushl %esi /* Push first argument: argc. */ + + pushl main@GOT(%ebx) + + /* Call the user's main function, and exit with its value. + But let the libc call main. */ + call __uClibc_main@PLT +#else + /* Push address of our own entry points to .fini and .init. */ + pushl $_fini + pushl $_init + + pushl %ecx /* Push second argument: argv. */ + pushl %esi /* Push first argument: argc. */ + + pushl $main + + /* Call the user's main function, and exit with its value. + But let the libc call main. */ + call __uClibc_main +#endif + + hlt /* Crash if somehow `exit' does return. */ +.size _start,.-_start + +/* Define a symbol for the first piece of initialized data. */ +.data +.global __data_start +__data_start: +.long 0 +.weak data_start + data_start = __data_start diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/crti.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/crti.S new file mode 100644 index 00000000..7dbaaadc --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/crti.S @@ -0,0 +1,31 @@ +.section .init +.global _init +.type _init,%function +_init: + pushl %ebp + movl %esp, %ebp + pushl %ebx + call __get_pc_thunk_bx + addl $_GLOBAL_OFFSET_TABLE_, %ebx + + + +.section .fini +.global _fini +.type _fini,%function +_fini: + pushl %ebp + movl %esp, %ebp + pushl %ebx + call __get_pc_thunk_bx + addl $_GLOBAL_OFFSET_TABLE_, %ebx + + + +.section .gnu.linkonce.t.__get_pc_thunk_bx,"ax",@progbits +.global __get_pc_thunk_bx +.hidden __get_pc_thunk_bx +.type __get_pc_thunk_bx,%function +__get_pc_thunk_bx: + movl (%esp), %ebx + ret diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/crtn.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/crtn.S new file mode 100644 index 00000000..34d5b38e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/crtn.S @@ -0,0 +1,27 @@ +.file "initfini.c" + +.section .init +.global _init +.type _init,%function + popl %ebx + popl %ebp + ret + + + +.section .fini +.global _fini +.type _fini,%function + popl %ebx + popl %ebp + ret + + + +.section .gnu.linkonce.t.__get_pc_thunk_bx,"ax",@progbits +.global __get_pc_thunk_bx +.hidden __get_pc_thunk_bx +.type __get_pc_thunk_bx,%function +__get_pc_thunk_bx: + movl (%esp), %ebx + ret diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/fpu_control.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/fpu_control.h new file mode 100644 index 00000000..c6cb005d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/fpu_control.h @@ -0,0 +1,104 @@ +/* FPU control word bits. i387 version. + Copyright (C) 1993,1995-1998,2000,2001,2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Olaf Flebbe. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FPU_CONTROL_H +#define _FPU_CONTROL_H 1 + +/* Here is the dirty part. Set up your 387 through the control word + * (cw) register. + * + * 15-13 12 11-10 9-8 7-6 5 4 3 2 1 0 + * | reserved | IC | RC | PC | reserved | PM | UM | OM | ZM | DM | IM + * + * IM: Invalid operation mask + * DM: Denormalized operand mask + * ZM: Zero-divide mask + * OM: Overflow mask + * UM: Underflow mask + * PM: Precision (inexact result) mask + * + * Mask bit is 1 means no interrupt. + * + * PC: Precision control + * 11 - round to extended precision + * 10 - round to double precision + * 00 - round to single precision + * + * RC: Rounding control + * 00 - rounding to nearest + * 01 - rounding down (toward - infinity) + * 10 - rounding up (toward + infinity) + * 11 - rounding toward zero + * + * IC: Infinity control + * That is for 8087 and 80287 only. + * + * The hardware default is 0x037f which we use. + */ + +#include + +/* masking of interrupts */ +#define _FPU_MASK_IM 0x01 +#define _FPU_MASK_DM 0x02 +#define _FPU_MASK_ZM 0x04 +#define _FPU_MASK_OM 0x08 +#define _FPU_MASK_UM 0x10 +#define _FPU_MASK_PM 0x20 + +/* precision control */ +#define _FPU_EXTENDED 0x300 /* libm requires double extended precision. */ +#define _FPU_DOUBLE 0x200 +#define _FPU_SINGLE 0x0 + +/* rounding control */ +#define _FPU_RC_NEAREST 0x0 /* RECOMMENDED */ +#define _FPU_RC_DOWN 0x400 +#define _FPU_RC_UP 0x800 +#define _FPU_RC_ZERO 0xC00 + +#define _FPU_RESERVED 0xF0C0 /* Reserved bits in cw */ + + +/* The fdlibm code requires strict IEEE double precision arithmetic, + and no interrupts for exceptions, rounding to nearest. */ + +#define _FPU_DEFAULT 0x037f + +/* IEEE: same as above. */ +#define _FPU_IEEE 0x037f + +/* Type of the control word. */ +typedef unsigned int fpu_control_t __attribute__ ((__mode__ (__HI__))); + +/* Macros for accessing the hardware control word. + + Note that the use of these macros is no sufficient anymore with + recent hardware. Some floating point operations are executed in + the SSE/SSE2 engines which have their own control and status register. */ +#define _FPU_GETCW(cw) __asm__ __volatile__ ("fnstcw %0" : "=m" (*&cw)) +#define _FPU_SETCW(cw) __asm__ __volatile__ ("fldcw %0" : : "m" (*&cw)) + +#if 0 +/* Default control word set at startup. */ +extern fpu_control_t __fpu_control; +#endif + +#endif /* fpu_control.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/mmap.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/mmap.S new file mode 100644 index 00000000..fe7a7986 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/mmap.S @@ -0,0 +1,51 @@ +/* Copyright (C) 1995,96,97,98,99,2000,2002,2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define _ERRNO_H 1 +#include +#include +#include + +.text +.global mmap +.type mmap,%function +mmap: + + /* Save registers. */ + movl %ebx, %edx + + movl $__NR_mmap, %eax /* System call number in %eax. */ + + lea 4(%esp), %ebx /* Address of args is 1st arg. */ + + /* Do the system call trap. */ + int $0x80 + + /* Restore registers. */ + movl %edx, %ebx + + /* If 0 > %eax > -4096 there was an error. */ + cmpl $-4096, %eax + ja __syscall_error + + /* Successful; return the syscall's value. */ + ret + +.size mmap,.-mmap + +libc_hidden_def(mmap) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/mmap64.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/mmap64.S new file mode 100644 index 00000000..a6b4aa04 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/mmap64.S @@ -0,0 +1,93 @@ +/* Copyright (C) 1995,96,97,98,99,2000,2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + + +#define _ERRNO_H 1 +#include +#include +#include + +#if defined __UCLIBC_HAS_LFS__ && defined __NR_mmap2 + + +#define LINKAGE 4 +#define PTR_SIZE 4 +#define SVRSP 16 /* saved register space */ +#define PARMS LINKAGE+SVRSP /* space for 4 saved regs */ +#define ADDR PARMS +#define LEN ADDR+PTR_SIZE +#define PROT LEN+4 +#define FLAGS PROT+4 +#define FD FLAGS+4 +#define OFFLO FD+4 +#define OFFHI OFFLO+4 + +.text +.global mmap64 +.type mmap64,%function + +mmap64: + /* Save registers. */ + pushl %ebp + pushl %ebx + pushl %esi + pushl %edi + + movl OFFLO(%esp), %edx + movl OFFHI(%esp), %ecx + testl $0xfff, %edx + jne L_einval + shrdl $12, %ecx, %edx /* mmap2 takes the offset in pages. */ + shrl $12, %ecx + jne L_einval + movl %edx, %ebp + + movl ADDR(%esp), %ebx + movl LEN(%esp), %ecx + movl PROT(%esp), %edx + movl FLAGS(%esp), %esi + movl FD(%esp), %edi + + movl $__NR_mmap2, %eax /* System call number in %eax. */ + /* Do the system call trap. */ + int $0x80 + + /* Restore registers. */ + popl %edi + popl %esi + popl %ebx + popl %ebp + + /* If 0 > %eax > -4096 there was an error. */ + cmpl $-4095,%eax + ja __syscall_error + /* Successful; return the syscall's value. */ + ret + + /* This means the offset value is too large. */ +L_einval: + popl %edi + popl %esi + popl %ebx + popl %ebp + movl $-EINVAL, %eax + jmp __syscall_error + +.size mmap64,.-mmap64 + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/posix_fadvise64.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/posix_fadvise64.S new file mode 100644 index 00000000..17f006aa --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/posix_fadvise64.S @@ -0,0 +1,108 @@ +/* Copyright (C) 1995-2000,2002,2003,2004,2005,2006 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define _ERRNO_H 1 +#include +#include +#include + +/* Was named __libc_posix_fadvise64 for some inexplicable reason. +** google says only uclibc has *__libc*_posix_fadviseXXX, +** so it cannot be compat with anything. +** +** Remove this comment and one at the end after 0.9.31 +*/ + +.text +.global posix_fadvise64 +.type posix_fadvise64,%function +posix_fadvise64: +#if defined __NR_fadvise64_64 + /* Save regs */ + pushl %ebp + pushl %ebx + pushl %esi + pushl %edi + + movl $__NR_fadvise64_64, %eax /* Syscall number in %eax. */ + + movl 20(%esp), %ebx + movl 24(%esp), %ecx + movl 28(%esp), %edx + movl 32(%esp), %esi + movl 36(%esp), %edi + movl 40(%esp), %ebp + + /* Do the system call trap. */ + int $0x80 + + /* Restore regs */ + popl %edi + popl %esi + popl %ebx + popl %ebp + + /* Returns 0 on success, else an error code. */ + negl %eax + +#elif defined __NR_fadvise64 + /* Save regs */ + pushl %ebx + pushl %esi + pushl %edi +#if 0 + /* does len overflow long? */ + cmpl $0, 28(%esp) + movl $-EOVERFLOW, %eax + jne overflow +#endif + movl $__NR_fadvise64, %eax /* Syscall number in %eax. */ + + movl 16(%esp), %ebx + movl 20(%esp), %ecx + movl 24(%esp), %edx + movl 28(%esp), %esi + movl 32(%esp), %edi + + /* Do the system call trap. */ + int $0x80 +overflow: + /* Restore regs */ + popl %edi + popl %esi + popl %ebx + + /* Returns 0 on success, else an error code. */ + negl %eax + +#elif defined __UCLIBC_HAS_STUBS__ + movl $-ENOSYS, %eax + jmp __syscall_error +#endif + /* Successful; return the syscall's value. */ + ret + +.size posix_fadvise64,.-posix_fadvise64 + +/* +** libc_hidden_def(__libc_posix_fadvise64) +** #if defined __UCLIBC_HAS_LFS__ && defined __UCLIBC_HAS_ADVANCED_REALTIME__ +** weak_alias(__libc_posix_fadvise64,posix_fadvise64) +** #endif +*/ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/setjmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/setjmp.S new file mode 100644 index 00000000..20a6a0bc --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/setjmp.S @@ -0,0 +1,58 @@ +/* setjmp for i386, ELF version. + Copyright (C) 1995, 1996, 1997, 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define _ASM +#define _SETJMP_H +#include + + +.global __sigsetjmp +.type __sigsetjmp,%function + +__sigsetjmp: + movl 4 (%esp), %eax + /* Save registers. */ + movl %ebx, (0 *4)(%eax) + movl %esi, (1 *4)(%eax) + movl %edi, (2 *4)(%eax) + /* Save SP as it will be after we return. */ + leal 4(%esp), %ecx + movl %ecx, (4 *4)(%eax) + /* Save PC we are returning to now. */ + movl 0(%esp), %ecx + movl %ecx, (5 *4)(%eax) + /* Save caller's frame pointer. */ + movl %ebp, (3 *4)(%eax) + + /* Make a tail call to __sigjmp_save; it takes the same args. */ +#ifdef __PIC__ + /* We cannot use the PLT, because it requires that %ebx be set, but + we can't save and restore our caller's value. Instead, we do an + indirect jump through the GOT, using for the temporary register + %ecx, which is call-clobbered. */ + call .Lhere +.Lhere: + popl %ecx + addl $_GLOBAL_OFFSET_TABLE_+[.- .Lhere ], %ecx + movl __sigjmp_save @GOT (%ecx), %ecx + jmp *%ecx +#else + jmp __sigjmp_save +#endif +.size __sigsetjmp,.-__sigsetjmp diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/sigaction.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/sigaction.c new file mode 100644 index 00000000..de0c75de --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/sigaction.c @@ -0,0 +1,138 @@ +/* Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + Totally hacked up for uClibc by Erik Andersen + */ + +#include +#include +#include +#include +#include + +#define SA_RESTORER 0x04000000 + +extern __typeof(sigaction) __libc_sigaction; + + +#if defined __NR_rt_sigaction + +extern void restore_rt(void) __asm__ ("__restore_rt") attribute_hidden; +extern void restore(void) __asm__ ("__restore") attribute_hidden; + +/* If ACT is not NULL, change the action for SIG to *ACT. + If OACT is not NULL, put the old action for SIG in *OACT. */ +int __libc_sigaction(int sig, const struct sigaction *act, struct sigaction *oact) +{ + struct sigaction kact; + + if (act) { + memcpy(&kact, act, sizeof(kact)); + kact.sa_flags |= SA_RESTORER; + kact.sa_restorer = (act->sa_flags & SA_SIGINFO) ? &restore_rt : &restore; + act = &kact; + } + /* NB: kernel (as of 2.6.25) will return EINVAL + * if sizeof(act->sa_mask) does not match kernel's sizeof(sigset_t) */ + return __syscall_rt_sigaction(sig, act, oact, sizeof(act->sa_mask)); +} + +#else + +extern void restore(void) __asm__ ("__restore") attribute_hidden; + +/* If ACT is not NULL, change the action for SIG to *ACT. + If OACT is not NULL, put the old action for SIG in *OACT. */ +int __libc_sigaction(int sig, const struct sigaction *act, struct sigaction *oact) +{ + int result; + struct old_kernel_sigaction kact, koact; + + if (act) { + kact.k_sa_handler = act->sa_handler; + kact.sa_mask = act->sa_mask.__val[0]; + kact.sa_flags = act->sa_flags | SA_RESTORER; + kact.sa_restorer = &restore; + } + __asm__ __volatile__ ( + " pushl %%ebx\n" + " movl %3, %%ebx\n" + " int $0x80\n" + " popl %%ebx\n" + : "=a" (result), "=m" (koact) + : "0" (__NR_sigaction), "r" (sig), "m" (kact), + "c" (act ? &kact : NULL), + "d" (oact ? &koact : NULL)); + if (result < 0) { + __set_errno(-result); + return -1; + } + if (oact) { + oact->sa_handler = koact.k_sa_handler; + oact->sa_mask.__val[0] = koact.sa_mask; + oact->sa_flags = koact.sa_flags; + oact->sa_restorer = koact.sa_restorer; + } + return result; +} + +#endif + + +#ifndef LIBC_SIGACTION +weak_alias(__libc_sigaction,sigaction) +libc_hidden_weak(sigaction) +#endif + + +/* NOTE: Please think twice before making any changes to the bits of + code below. GDB needs some intimate knowledge about it to + recognize them as signal trampolines, and make backtraces through + signal handlers work right. Important are both the names + (__restore and __restore_rt) and the exact instruction sequence. + If you ever feel the need to make any changes, please notify the + appropriate GDB maintainer. */ + +#define RESTORE(name, syscall) RESTORE2(name, syscall) +#define RESTORE2(name, syscall) \ +__asm__ ( \ + ".text\n" \ + "__" #name ":\n" \ + " movl $" #syscall ", %eax\n" \ + " int $0x80\n" \ +); + +#ifdef __NR_rt_sigaction +/* The return code for realtime-signals. */ +RESTORE(restore_rt, __NR_rt_sigreturn) +#endif + +#ifdef __NR_sigreturn +/* For the boring old signals. */ +# undef RESTORE2 +# define RESTORE2(name, syscall) \ +__asm__ ( \ + ".text\n" \ + "__" #name ":\n" \ + " popl %eax\n" \ + " movl $" #syscall ", %eax\n" \ + " int $0x80\n" \ +); + +RESTORE(restore, __NR_sigreturn) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/sync_file_range.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/sync_file_range.S new file mode 100644 index 00000000..6cdaf452 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/sync_file_range.S @@ -0,0 +1,67 @@ +/* Copyright (C) 2006, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define _ERRNO_H 1 +#include +#include +#include + +.text +.global sync_file_range +.type sync_file_range,%function +sync_file_range: +#ifdef __NR_sync_file_range + + /* Save regs */ + pushl %ebx + pushl %esi + pushl %edi + pushl %ebp + + movl $__NR_sync_file_range, %eax /* Syscall number in %eax. */ + + movl 20(%esp), %ebx + movl 24(%esp), %ecx + movl 28(%esp), %edx + movl 32(%esp), %esi + movl 36(%esp), %edi + movl 40(%esp), %ebp + + /* Do the system call trap. */ + int $0x80 + + /* Restore regs */ + popl %ebp + popl %edi + popl %esi + popl %ebx + + /* If 0 > %eax > -4096 there was an error. */ + cmpl $-4096, %eax + ja __syscall_error +#else + movl $-ENOSYS, %eax + jmp __syscall_error +#endif + /* Successful; return the syscall's value. */ + ret + +.size sync_file_range,.-sync_file_range + +libc_hidden_def(sync_file_range) + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/sys/debugreg.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/sys/debugreg.h new file mode 100644 index 00000000..c99c9435 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/sys/debugreg.h @@ -0,0 +1,91 @@ +/* Copyright (C) 1998, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_DEBUGREG_H +#define _SYS_DEBUGREG_H 1 + +/* Indicate the register numbers for a number of the specific + debug registers. Registers 0-3 contain the addresses we wish to trap on */ +#define DR_FIRSTADDR 0 /* u_debugreg[DR_FIRSTADDR] */ +#define DR_LASTADDR 3 /* u_debugreg[DR_LASTADDR] */ + +#define DR_STATUS 6 /* u_debugreg[DR_STATUS] */ +#define DR_CONTROL 7 /* u_debugreg[DR_CONTROL] */ + +/* Define a few things for the status register. We can use this to determine + which debugging register was responsible for the trap. The other bits + are either reserved or not of interest to us. */ + +#define DR_TRAP0 (0x1) /* db0 */ +#define DR_TRAP1 (0x2) /* db1 */ +#define DR_TRAP2 (0x4) /* db2 */ +#define DR_TRAP3 (0x8) /* db3 */ + +#define DR_STEP (0x4000) /* single-step */ +#define DR_SWITCH (0x8000) /* task switch */ + +/* Now define a bunch of things for manipulating the control register. + The top two bytes of the control register consist of 4 fields of 4 + bits - each field corresponds to one of the four debug registers, + and indicates what types of access we trap on, and how large the data + field is that we are looking at */ + +#define DR_CONTROL_SHIFT 16 /* Skip this many bits in ctl register */ +#define DR_CONTROL_SIZE 4 /* 4 control bits per register */ + +#define DR_RW_EXECUTE (0x0) /* Settings for the access types to trap on */ +#define DR_RW_WRITE (0x1) +#define DR_RW_READ (0x3) + +#define DR_LEN_1 (0x0) /* Settings for data length to trap on */ +#define DR_LEN_2 (0x4) +#define DR_LEN_4 (0xC) + +/* The low byte to the control register determine which registers are + enabled. There are 4 fields of two bits. One bit is "local", meaning + that the processor will reset the bit after a task switch and the other + is global meaning that we have to explicitly reset the bit. With linux, + you can use either one, since we explicitly zero the register when we enter + kernel mode. */ + +#define DR_LOCAL_ENABLE_SHIFT 0 /* Extra shift to the local enable bit */ +#define DR_GLOBAL_ENABLE_SHIFT 1 /* Extra shift to the global enable bit */ +#define DR_ENABLE_SIZE 2 /* 2 enable bits per register */ + +#define DR_LOCAL_ENABLE_MASK (0x55) /* Set local bits for all 4 regs */ +#define DR_GLOBAL_ENABLE_MASK (0xAA) /* Set global bits for all 4 regs */ + +/* The second byte to the control register has a few special things. + + On the i386, you should set the DR_LOCAL_SLOWDOWN or + DR_GLOBAL_SLOWDOWN bits if you want to know exactly which + instruction triggered the watchpoint. Setting these bits causes + the processor to run more slowly, but leaving them clear makes it + treat watchpoint hits as imprecise exceptions, so you can't + reliably determine which instruction caused the hit. + + The i486 and all later IA-32 processors ignore DR_LOCAL_SLOWDOWN + and DR_GLOBAL_SLOWDOWN. They always report the exception + precisely, except in some rare cases, which the user can't do + anything about. */ + +#define DR_CONTROL_RESERVED (0xFC00) /* Reserved by Intel */ +#define DR_LOCAL_SLOWDOWN (0x100) /* Local slow the pipeline */ +#define DR_GLOBAL_SLOWDOWN (0x200) /* Global slow the pipeline */ + +#endif /* sys/debugreg.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/sys/elf.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/sys/elf.h new file mode 100644 index 00000000..d959cdca --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/sys/elf.h @@ -0,0 +1,26 @@ +/* Copyright (C) 1998, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_ELF_H +#define _SYS_ELF_H 1 + +#warning "This header is obsolete; use instead." + +#include + +#endif /* _SYS_ELF_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/sys/io.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/sys/io.h new file mode 100644 index 00000000..00205e4c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/sys/io.h @@ -0,0 +1,184 @@ +/* Copyright (C) 1996, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_IO_H +#define _SYS_IO_H 1 + +#include + +__BEGIN_DECLS + +#if defined __UCLIBC_LINUX_SPECIFIC__ +/* If TURN_ON is TRUE, request for permission to do direct i/o on the + port numbers in the range [FROM,FROM+NUM-1]. Otherwise, turn I/O + permission off for that range. This call requires root privileges. + + Portability note: not all Linux platforms support this call. Most + platforms based on the PC I/O architecture probably will, however. + E.g., Linux/Alpha for Alpha PCs supports this. */ +extern int ioperm (unsigned long int __from, unsigned long int __num, + int __turn_on) __THROW; +libc_hidden_proto(ioperm) + +/* Set the I/O privilege level to LEVEL. If LEVEL>3, permission to + access any I/O port is granted. This call requires root + privileges. */ +extern int iopl (int __level) __THROW; +#endif /* __UCLIBC_LINUX_SPECIFIC__ */ + +#if defined __GNUC__ && __GNUC__ >= 2 + +static __inline unsigned char +inb (unsigned short int port) +{ + unsigned char _v; + + __asm__ __volatile__ ("inb %w1,%0":"=a" (_v):"Nd" (port)); + return _v; +} + +static __inline unsigned char +inb_p (unsigned short int port) +{ + unsigned char _v; + + __asm__ __volatile__ ("inb %w1,%0\noutb %%al,$0x80":"=a" (_v):"Nd" (port)); + return _v; +} + +static __inline unsigned short int +inw (unsigned short int port) +{ + unsigned short _v; + + __asm__ __volatile__ ("inw %w1,%0":"=a" (_v):"Nd" (port)); + return _v; +} + +static __inline unsigned short int +inw_p (unsigned short int port) +{ + unsigned short int _v; + + __asm__ __volatile__ ("inw %w1,%0\noutb %%al,$0x80":"=a" (_v):"Nd" (port)); + return _v; +} + +static __inline unsigned int +inl (unsigned short int port) +{ + unsigned int _v; + + __asm__ __volatile__ ("inl %w1,%0":"=a" (_v):"Nd" (port)); + return _v; +} + +static __inline unsigned int +inl_p (unsigned short int port) +{ + unsigned int _v; + __asm__ __volatile__ ("inl %w1,%0\noutb %%al,$0x80":"=a" (_v):"Nd" (port)); + return _v; +} + +static __inline void +outb (unsigned char value, unsigned short int port) +{ + __asm__ __volatile__ ("outb %b0,%w1": :"a" (value), "Nd" (port)); +} + +static __inline void +outb_p (unsigned char value, unsigned short int port) +{ + __asm__ __volatile__ ("outb %b0,%w1\noutb %%al,$0x80": :"a" (value), + "Nd" (port)); +} + +static __inline void +outw (unsigned short int value, unsigned short int port) +{ + __asm__ __volatile__ ("outw %w0,%w1": :"a" (value), "Nd" (port)); + +} + +static __inline void +outw_p (unsigned short int value, unsigned short int port) +{ + __asm__ __volatile__ ("outw %w0,%w1\noutb %%al,$0x80": :"a" (value), + "Nd" (port)); +} + +static __inline void +outl (unsigned int value, unsigned short int port) +{ + __asm__ __volatile__ ("outl %0,%w1": :"a" (value), "Nd" (port)); +} + +static __inline void +outl_p (unsigned int value, unsigned short int port) +{ + __asm__ __volatile__ ("outl %0,%w1\noutb %%al,$0x80": :"a" (value), + "Nd" (port)); +} + +static __inline void +insb (unsigned short int port, void *addr, unsigned long int count) +{ + __asm__ __volatile__ ("cld ; rep ; insb":"=D" (addr), + "=c" (count):"d" (port), "0" (addr), "1" (count)); +} + +static __inline void +insw (unsigned short int port, void *addr, unsigned long int count) +{ + __asm__ __volatile__ ("cld ; rep ; insw":"=D" (addr), + "=c" (count):"d" (port), "0" (addr), "1" (count)); +} + +static __inline void +insl (unsigned short int port, void *addr, unsigned long int count) +{ + __asm__ __volatile__ ("cld ; rep ; insl":"=D" (addr), + "=c" (count):"d" (port), "0" (addr), "1" (count)); +} + +static __inline void +outsb (unsigned short int port, const void *addr, unsigned long int count) +{ + __asm__ __volatile__ ("cld ; rep ; outsb":"=S" (addr), + "=c" (count):"d" (port), "0" (addr), "1" (count)); +} + +static __inline void +outsw (unsigned short int port, const void *addr, unsigned long int count) +{ + __asm__ __volatile__ ("cld ; rep ; outsw":"=S" (addr), + "=c" (count):"d" (port), "0" (addr), "1" (count)); +} + +static __inline void +outsl (unsigned short int port, const void *addr, unsigned long int count) +{ + __asm__ __volatile__ ("cld ; rep ; outsl":"=S" (addr), + "=c" (count):"d" (port), "0" (addr), "1" (count)); +} + +#endif /* GNU C */ + +__END_DECLS +#endif /* _SYS_IO_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/sys/perm.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/sys/perm.h new file mode 100644 index 00000000..db67d36e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/sys/perm.h @@ -0,0 +1,37 @@ +/* Copyright (C) 1996, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_PERM_H + +#define _SYS_PERM_H 1 +#include + +__BEGIN_DECLS + +/* Set port input/output permissions. */ +extern int ioperm (unsigned long int __from, unsigned long int __num, + int __turn_on) __THROW; +libc_hidden_proto(ioperm) + + +/* Change I/O privilege level. */ +extern int iopl (int __level) __THROW; + +__END_DECLS + +#endif /* _SYS_PERM_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/sys/procfs.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/sys/procfs.h new file mode 100644 index 00000000..f0be4330 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/sys/procfs.h @@ -0,0 +1,131 @@ +/* Copyright (C) 1996, 1997, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_PROCFS_H +#define _SYS_PROCFS_H 1 + +/* This is somewhat modelled after the file of the same name on SVR4 + systems. It provides a definition of the core file format for ELF + used on Linux. It doesn't have anything to do with the /proc file + system, even though Linux has one. + + Anyway, the whole purpose of this file is for GDB and GDB only. + Don't read too much into it. Don't use it for anything other than + GDB unless you know what you are doing. */ + +#include +#include +#include +#include + +__BEGIN_DECLS + +/* Type for a general-purpose register. */ +typedef unsigned long elf_greg_t; + +/* And the whole bunch of them. We could have used `struct + user_regs_struct' directly in the typedef, but tradition says that + the register set is an array, which does have some peculiar + semantics, so leave it that way. */ +#define ELF_NGREG (sizeof (struct user_regs_struct) / sizeof(elf_greg_t)) +typedef elf_greg_t elf_gregset_t[ELF_NGREG]; + +/* Register set for the floating-point registers. */ +typedef struct user_fpregs_struct elf_fpregset_t; + +/* Register set for the extended floating-point registers. Includes + the Pentium III SSE registers in addition to the classic + floating-point stuff. */ +typedef struct user_fpxregs_struct elf_fpxregset_t; + + +/* Signal info. */ +struct elf_siginfo + { + int si_signo; /* Signal number. */ + int si_code; /* Extra code. */ + int si_errno; /* Errno. */ + }; + + +/* Definitions to generate Intel SVR4-like core files. These mostly + have the same names as the SVR4 types with "elf_" tacked on the + front to prevent clashes with Linux definitions, and the typedef + forms have been avoided. This is mostly like the SVR4 structure, + but more Linuxy, with things that Linux does not support and which + GDB doesn't really use excluded. */ + +struct elf_prstatus + { + struct elf_siginfo pr_info; /* Info associated with signal. */ + short int pr_cursig; /* Current signal. */ + unsigned long int pr_sigpend; /* Set of pending signals. */ + unsigned long int pr_sighold; /* Set of held signals. */ + __pid_t pr_pid; + __pid_t pr_ppid; + __pid_t pr_pgrp; + __pid_t pr_sid; + struct timeval pr_utime; /* User time. */ + struct timeval pr_stime; /* System time. */ + struct timeval pr_cutime; /* Cumulative user time. */ + struct timeval pr_cstime; /* Cumulative system time. */ + elf_gregset_t pr_reg; /* GP registers. */ + int pr_fpvalid; /* True if math copro being used. */ + }; + + +#define ELF_PRARGSZ (80) /* Number of chars for args. */ + +struct elf_prpsinfo + { + char pr_state; /* Numeric process state. */ + char pr_sname; /* Char for pr_state. */ + char pr_zomb; /* Zombie. */ + char pr_nice; /* Nice val. */ + unsigned long int pr_flag; /* Flags. */ + unsigned short int pr_uid; + unsigned short int pr_gid; + int pr_pid, pr_ppid, pr_pgrp, pr_sid; + /* Lots missing */ + char pr_fname[16]; /* Filename of executable. */ + char pr_psargs[ELF_PRARGSZ]; /* Initial part of arg list. */ + }; + + +/* The rest of this file provides the types for emulation of the + Solaris interfaces that should be implemented by + users of libthread_db. */ + +/* Addresses. */ +typedef void *psaddr_t; + +/* Register sets. Linux has different names. */ +typedef elf_gregset_t prgregset_t; +typedef elf_fpregset_t prfpregset_t; + +/* We don't have any differences between processes and threads, + therefore have only one PID type. */ +typedef __pid_t lwpid_t; + +/* Process status and info. In the end we do provide typedefs for them. */ +typedef struct elf_prstatus prstatus_t; +typedef struct elf_prpsinfo prpsinfo_t; + +__END_DECLS + +#endif /* sys/procfs.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/sys/reg.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/sys/reg.h new file mode 100644 index 00000000..39003c45 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/sys/reg.h @@ -0,0 +1,43 @@ +/* Copyright (C) 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_REG_H +#define _SYS_REG_H 1 + +/* Index into an array of 4 byte integers returned from ptrace for + * location of the users' stored general purpose registers. */ + +#define EBX 0 +#define ECX 1 +#define EDX 2 +#define ESI 3 +#define EDI 4 +#define EBP 5 +#define EAX 6 +#define DS 7 +#define ES 8 +#define FS 9 +#define GS 10 +#define ORIG_EAX 11 +#define EIP 12 +#define CS 13 +#define EFL 14 +#define UESP 15 +#define SS 16 + +#endif /* _SYS_REG_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/sys/ucontext.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/sys/ucontext.h new file mode 100644 index 00000000..d6474c72 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/sys/ucontext.h @@ -0,0 +1,129 @@ +/* Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_UCONTEXT_H +#define _SYS_UCONTEXT_H 1 + +#include +#include + +/* We need the signal context definitions even if they are not used + included in . */ +#include + + +/* Type for general register. */ +typedef int greg_t; + +/* Number of general registers. */ +#define NGREG 19 + +/* Container for all general registers. */ +typedef greg_t gregset_t[NGREG]; + +#ifdef __USE_GNU +/* Number of each register is the `gregset_t' array. */ +enum +{ + REG_GS = 0, +# define REG_GS REG_GS + REG_FS, +# define REG_FS REG_FS + REG_ES, +# define REG_ES REG_ES + REG_DS, +# define REG_DS REG_DS + REG_EDI, +# define REG_EDI REG_EDI + REG_ESI, +# define REG_ESI REG_ESI + REG_EBP, +# define REG_EBP REG_EBP + REG_ESP, +# define REG_ESP REG_ESP + REG_EBX, +# define REG_EBX REG_EBX + REG_EDX, +# define REG_EDX REG_EDX + REG_ECX, +# define REG_ECX REG_ECX + REG_EAX, +# define REG_EAX REG_EAX + REG_TRAPNO, +# define REG_TRAPNO REG_TRAPNO + REG_ERR, +# define REG_ERR REG_ERR + REG_EIP, +# define REG_EIP REG_EIP + REG_CS, +# define REG_CS REG_CS + REG_EFL, +# define REG_EFL REG_EFL + REG_UESP, +# define REG_UESP REG_UESP + REG_SS +# define REG_SS REG_SS +}; +#endif + +/* Definitions taken from the kernel headers. */ +struct _libc_fpreg +{ + unsigned short int significand[4]; + unsigned short int exponent; +}; + +struct _libc_fpstate +{ + unsigned long int cw; + unsigned long int sw; + unsigned long int tag; + unsigned long int ipoff; + unsigned long int cssel; + unsigned long int dataoff; + unsigned long int datasel; + struct _libc_fpreg _st[8]; + unsigned long int status; +}; + +/* Structure to describe FPU registers. */ +typedef struct _libc_fpstate *fpregset_t; + +/* Context to describe whole processor state. */ +typedef struct + { + gregset_t gregs; + /* Due to Linux's history we have to use a pointer here. The SysV/i386 + ABI requires a struct with the values. */ + fpregset_t fpregs; + unsigned long int oldmask; + unsigned long int cr2; + } mcontext_t; + +/* Userlevel context. */ +typedef struct ucontext + { + unsigned long int uc_flags; + struct ucontext *uc_link; + stack_t uc_stack; + mcontext_t uc_mcontext; + __sigset_t uc_sigmask; + struct _libc_fpstate __fpregs_mem; + } ucontext_t; + +#endif /* sys/ucontext.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/sys/user.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/sys/user.h new file mode 100644 index 00000000..c5cfff25 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/sys/user.h @@ -0,0 +1,101 @@ +/* Copyright (C) 1998, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_USER_H +#define _SYS_USER_H 1 + +/* The whole purpose of this file is for GDB and GDB only. Don't read + too much into it. Don't use it for anything other than GDB unless + you know what you are doing. */ + +struct user_fpregs_struct +{ + long int cwd; + long int swd; + long int twd; + long int fip; + long int fcs; + long int foo; + long int fos; + long int st_space [20]; +}; + +struct user_fpxregs_struct +{ + unsigned short int cwd; + unsigned short int swd; + unsigned short int twd; + unsigned short int fop; + long int fip; + long int fcs; + long int foo; + long int fos; + long int mxcsr; + long int reserved; + long int st_space[32]; /* 8*16 bytes for each FP-reg = 128 bytes */ + long int xmm_space[32]; /* 8*16 bytes for each XMM-reg = 128 bytes */ + long int padding[56]; +}; + +struct user_regs_struct +{ + long int ebx; + long int ecx; + long int edx; + long int esi; + long int edi; + long int ebp; + long int eax; + long int xds; + long int xes; + long int xfs; + long int xgs; + long int orig_eax; + long int eip; + long int xcs; + long int eflags; + long int esp; + long int xss; +}; + +struct user +{ + struct user_regs_struct regs; + int u_fpvalid; + struct user_fpregs_struct i387; + unsigned long int u_tsize; + unsigned long int u_dsize; + unsigned long int u_ssize; + unsigned long start_code; + unsigned long start_stack; + long int signal; + int reserved; + struct user_regs_struct* u_ar0; + struct user_fpregs_struct* u_fpstate; + unsigned long int magic; + char u_comm [32]; + int u_debugreg [8]; +}; + +#include +#define NBPG PAGE_SIZE +#define UPAGES 1 +#define HOST_TEXT_START_ADDR (u.start_code) +#define HOST_STACK_END_ADDR (u.start_stack + u.u_ssize * NBPG) + +#endif /* _SYS_USER_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/sys/vm86.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/sys/vm86.h new file mode 100644 index 00000000..8faeed7f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/sys/vm86.h @@ -0,0 +1,34 @@ +/* Copyright (C) 1996, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_VM86_H + +#define _SYS_VM86_H 1 +#include + +/* Get constants and data types from kernel header file. */ +#include + +__BEGIN_DECLS + +/* Enter virtual 8086 mode. */ +extern int vm86 (struct vm86_struct *__info) __THROW; + +__END_DECLS + +#endif /* _SYS_VM86_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/syscall.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/syscall.S new file mode 100644 index 00000000..b9f65feb --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/syscall.S @@ -0,0 +1,50 @@ +/* + * June 27, 2001 Manuel Novoa III + * + * This is a heavily modified version of gcc's output for the _syscall5 macro. + * The idea (originally from dietlibc) is that all syscall functions simply set + * the syscall number as the first argument, then set the syscall arguments as + * the next up-to-five arguments, and then jump here. All the common work is + * done by syscall(), saving a fair amount of generated code when a number of + * syscalls are used. The (potential) cost is some unnecessary pushes, pops, + * and movs but the execution time penalty should be relatively small compared + * to the cost of the syscall itself. + * + * July 24, 2002 + * + * Modified by Erik Andersen to take all function parameters from off the stack + * like a proper function and eliminates the old 255 syscall number limit. So + * now we can just call this as a function as syscall() per the function + * prototype in unistd.h, so to call _exit(42) you can just call. + * syscall(__NR_exit, 42); + * and things will just work. + */ + +.text +.global syscall +.type syscall,%function +syscall: + pushl %ebp + pushl %edi + pushl %esi + pushl %ebx + + movl 44(%esp),%ebp /* Load the 6 syscall argument registers */ + movl 40(%esp),%edi + movl 36(%esp),%esi + movl 32(%esp),%edx + movl 28(%esp),%ecx + movl 24(%esp),%ebx + movl 20(%esp),%eax /* Load syscall number into %eax. */ + int $0x80 + + popl %ebx + popl %esi + popl %edi + popl %ebp + + cmpl $-4095,%eax + jae __syscall_error + ret /* Return to caller. */ + +.size syscall,.-syscall diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/sysdep.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/sysdep.h new file mode 100644 index 00000000..b06d392a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/sysdep.h @@ -0,0 +1,462 @@ +/* Copyright (C) 1992,1993,1995-2000,2002-2006,2007 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper, , August 1995. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _LINUX_I386_SYSDEP_H +#define _LINUX_I386_SYSDEP_H 1 + +#include +#include + +#ifdef __ASSEMBLER__ + +/* Syntactic details of assembler. */ + +/* ELF uses byte-counts for .align, most others use log2 of count of bytes. */ +#define ALIGNARG(log2) 1<MEMBER) +#endif + +/* For Linux we can use the system call table in the header file + /usr/include/asm/unistd.h + of the kernel. But these symbols do not follow the SYS_* syntax + so we have to redefine the `SYS_ify' macro here. */ +#undef SYS_ify +#define SYS_ify(syscall_name) __NR_##syscall_name + +#if defined USE_DL_SYSINFO \ + && (!defined NOT_IN_libc || defined IS_IN_libpthread) +# define I386_USE_SYSENTER 1 +#else +# undef I386_USE_SYSENTER +#endif + +#ifdef __ASSEMBLER__ + +/* Linux uses a negative return value to indicate syscall errors, + unlike most Unices, which use the condition codes' carry flag. + + Since version 2.1 the return value of a system call might be + negative even if the call succeeded. E.g., the `lseek' system call + might return a large offset. Therefore we must not anymore test + for < 0, but test for a real error by making sure the value in %eax + is a real error number. Linus said he will make sure the no syscall + returns a value in -1 .. -4095 as a valid result so we can savely + test with -4095. */ + +/* We don't want the label for the error handle to be global when we define + it here. */ +#ifdef __PIC__ +# define SYSCALL_ERROR_LABEL 0f +#else +# define SYSCALL_ERROR_LABEL syscall_error +#endif + +#undef PSEUDO +#define PSEUDO(name, syscall_name, args) \ + .text; \ + ENTRY (name) \ + DO_CALL (syscall_name, args); \ + cmpl $-4095, %eax; \ + jae SYSCALL_ERROR_LABEL; \ + L(pseudo_end): + +#undef PSEUDO_END +#define PSEUDO_END(name) \ + SYSCALL_ERROR_HANDLER \ + END (name) + +#undef PSEUDO_NOERRNO +#define PSEUDO_NOERRNO(name, syscall_name, args) \ + .text; \ + ENTRY (name) \ + DO_CALL (syscall_name, args) + +#undef PSEUDO_END_NOERRNO +#define PSEUDO_END_NOERRNO(name) \ + END (name) + +#define ret_NOERRNO ret + +/* The function has to return the error code. */ +#undef PSEUDO_ERRVAL +#define PSEUDO_ERRVAL(name, syscall_name, args) \ + .text; \ + ENTRY (name) \ + DO_CALL (syscall_name, args); \ + negl %eax + +#undef PSEUDO_END_ERRVAL +#define PSEUDO_END_ERRVAL(name) \ + END (name) + +#define ret_ERRVAL ret + +#ifndef __PIC__ +# define SYSCALL_ERROR_HANDLER /* Nothing here; code in sysdep.S is used. */ +#else + +# ifdef RTLD_PRIVATE_ERRNO +# define SYSCALL_ERROR_HANDLER \ +0:SETUP_PIC_REG(cx); \ + addl $_GLOBAL_OFFSET_TABLE_, %ecx; \ + xorl %edx, %edx; \ + subl %eax, %edx; \ + movl %edx, rtld_errno@GOTOFF(%ecx); \ + orl $-1, %eax; \ + jmp L(pseudo_end); + +# elif defined _LIBC_REENTRANT + +# if defined USE___THREAD +# ifndef NOT_IN_libc +# define SYSCALL_ERROR_ERRNO __libc_errno +# else +# define SYSCALL_ERROR_ERRNO errno +# endif +# define SYSCALL_ERROR_HANDLER \ +0:SETUP_PIC_REG (cx); \ + addl $_GLOBAL_OFFSET_TABLE_, %ecx; \ + movl SYSCALL_ERROR_ERRNO@GOTNTPOFF(%ecx), %ecx; \ + xorl %edx, %edx; \ + subl %eax, %edx; \ + SYSCALL_ERROR_HANDLER_TLS_STORE (%edx, %ecx); \ + orl $-1, %eax; \ + jmp L(pseudo_end); +# ifndef NO_TLS_DIRECT_SEG_REFS +# define SYSCALL_ERROR_HANDLER_TLS_STORE(src, destoff) \ + movl src, %gs:(destoff) +# else +# define SYSCALL_ERROR_HANDLER_TLS_STORE(src, destoff) \ + addl %gs:0, destoff; \ + movl src, (destoff) +# endif +# else +# define SYSCALL_ERROR_HANDLER \ +0:pushl %ebx; \ + cfi_adjust_cfa_offset (4); \ + cfi_rel_offset (ebx, 0); \ + SETUP_PIC_REG (bx); \ + addl $_GLOBAL_OFFSET_TABLE_, %ebx; \ + xorl %edx, %edx; \ + subl %eax, %edx; \ + pushl %edx; \ + cfi_adjust_cfa_offset (4); \ + call __errno_location@PLT; \ + popl %ecx; \ + cfi_adjust_cfa_offset (-4); \ + popl %ebx; \ + cfi_adjust_cfa_offset (-4); \ + cfi_restore (ebx); \ + movl %ecx, (%eax); \ + orl $-1, %eax; \ + jmp L(pseudo_end); +/* A quick note: it is assumed that the call to `__errno_location' does + not modify the stack! */ +# endif +# else +/* Store (- %eax) into errno through the GOT. */ +# define SYSCALL_ERROR_HANDLER \ +0:SETUP_PIC_REG(cx); \ + addl $_GLOBAL_OFFSET_TABLE_, %ecx; \ + xorl %edx, %edx; \ + subl %eax, %edx; \ + movl errno@GOT(%ecx), %ecx; \ + movl %edx, (%ecx); \ + orl $-1, %eax; \ + jmp L(pseudo_end); +# endif /* _LIBC_REENTRANT */ +#endif /* __PIC__ */ + + +/* The original calling convention for system calls on Linux/i386 is + to use int $0x80. */ +#ifdef I386_USE_SYSENTER +# ifdef SHARED +# define ENTER_KERNEL call *%gs:SYSINFO_OFFSET +# else +# define ENTER_KERNEL call *_dl_sysinfo +# endif +#else +# define ENTER_KERNEL int $0x80 +#endif + +/* Linux takes system call arguments in registers: + + syscall number %eax call-clobbered + arg 1 %ebx call-saved + arg 2 %ecx call-clobbered + arg 3 %edx call-clobbered + arg 4 %esi call-saved + arg 5 %edi call-saved + arg 6 %ebp call-saved + + The stack layout upon entering the function is: + + 24(%esp) Arg# 6 + 20(%esp) Arg# 5 + 16(%esp) Arg# 4 + 12(%esp) Arg# 3 + 8(%esp) Arg# 2 + 4(%esp) Arg# 1 + (%esp) Return address + + (Of course a function with say 3 arguments does not have entries for + arguments 4, 5, and 6.) + + The following code tries hard to be optimal. A general assumption + (which is true according to the data books I have) is that + + 2 * xchg is more expensive than pushl + movl + popl + + Beside this a neat trick is used. The calling conventions for Linux + tell that among the registers used for parameters %ecx and %edx need + not be saved. Beside this we may clobber this registers even when + they are not used for parameter passing. + + As a result one can see below that we save the content of the %ebx + register in the %edx register when we have less than 3 arguments + (2 * movl is less expensive than pushl + popl). + + Second unlike for the other registers we don't save the content of + %ecx and %edx when we have more than 1 and 2 registers resp. + + The code below might look a bit long but we have to take care for + the pipelined processors (i586). Here the `pushl' and `popl' + instructions are marked as NP (not pairable) but the exception is + two consecutive of these instruction. This gives no penalty on + other processors though. */ + +#undef DO_CALL +#define DO_CALL(syscall_name, args) \ + PUSHARGS_##args \ + DOARGS_##args \ + movl $SYS_ify (syscall_name), %eax; \ + ENTER_KERNEL \ + POPARGS_##args + +#define PUSHARGS_0 /* No arguments to push. */ +#define DOARGS_0 /* No arguments to frob. */ +#define POPARGS_0 /* No arguments to pop. */ +#define _PUSHARGS_0 /* No arguments to push. */ +#define _DOARGS_0(n) /* No arguments to frob. */ +#define _POPARGS_0 /* No arguments to pop. */ + +#define PUSHARGS_1 movl %ebx, %edx; L(SAVEBX1): PUSHARGS_0 +#define DOARGS_1 _DOARGS_1 (4) +#define POPARGS_1 POPARGS_0; movl %edx, %ebx; L(RESTBX1): +#define _PUSHARGS_1 pushl %ebx; cfi_adjust_cfa_offset (4); \ + cfi_rel_offset (ebx, 0); L(PUSHBX1): _PUSHARGS_0 +#define _DOARGS_1(n) movl n(%esp), %ebx; _DOARGS_0(n-4) +#define _POPARGS_1 _POPARGS_0; popl %ebx; cfi_adjust_cfa_offset (-4); \ + cfi_restore (ebx); L(POPBX1): + +#define PUSHARGS_2 PUSHARGS_1 +#define DOARGS_2 _DOARGS_2 (8) +#define POPARGS_2 POPARGS_1 +#define _PUSHARGS_2 _PUSHARGS_1 +#define _DOARGS_2(n) movl n(%esp), %ecx; _DOARGS_1 (n-4) +#define _POPARGS_2 _POPARGS_1 + +#define PUSHARGS_3 _PUSHARGS_2 +#define DOARGS_3 _DOARGS_3 (16) +#define POPARGS_3 _POPARGS_3 +#define _PUSHARGS_3 _PUSHARGS_2 +#define _DOARGS_3(n) movl n(%esp), %edx; _DOARGS_2 (n-4) +#define _POPARGS_3 _POPARGS_2 + +#define PUSHARGS_4 _PUSHARGS_4 +#define DOARGS_4 _DOARGS_4 (24) +#define POPARGS_4 _POPARGS_4 +#define _PUSHARGS_4 pushl %esi; cfi_adjust_cfa_offset (4); \ + cfi_rel_offset (esi, 0); L(PUSHSI1): _PUSHARGS_3 +#define _DOARGS_4(n) movl n(%esp), %esi; _DOARGS_3 (n-4) +#define _POPARGS_4 _POPARGS_3; popl %esi; cfi_adjust_cfa_offset (-4); \ + cfi_restore (esi); L(POPSI1): + +#define PUSHARGS_5 _PUSHARGS_5 +#define DOARGS_5 _DOARGS_5 (32) +#define POPARGS_5 _POPARGS_5 +#define _PUSHARGS_5 pushl %edi; cfi_adjust_cfa_offset (4); \ + cfi_rel_offset (edi, 0); L(PUSHDI1): _PUSHARGS_4 +#define _DOARGS_5(n) movl n(%esp), %edi; _DOARGS_4 (n-4) +#define _POPARGS_5 _POPARGS_4; popl %edi; cfi_adjust_cfa_offset (-4); \ + cfi_restore (edi); L(POPDI1): + +#define PUSHARGS_6 _PUSHARGS_6 +#define DOARGS_6 _DOARGS_6 (40) +#define POPARGS_6 _POPARGS_6 +#define _PUSHARGS_6 pushl %ebp; cfi_adjust_cfa_offset (4); \ + cfi_rel_offset (ebp, 0); L(PUSHBP1): _PUSHARGS_5 +#define _DOARGS_6(n) movl n(%esp), %ebp; _DOARGS_5 (n-4) +#define _POPARGS_6 _POPARGS_5; popl %ebp; cfi_adjust_cfa_offset (-4); \ + cfi_restore (ebp); L(POPBP1): + +#endif /* __ASSEMBLER__ */ + + +/* Pointer mangling support. */ +#if defined NOT_IN_libc && defined IS_IN_rtld +/* We cannot use the thread descriptor because in ld.so we use setjmp + earlier than the descriptor is initialized. Using a global variable + is too complicated here since we have no PC-relative addressing mode. */ +#else +# ifdef __ASSEMBLER__ +# define PTR_MANGLE(reg) xorl %gs:POINTER_GUARD, reg; \ + roll $9, reg +# define PTR_DEMANGLE(reg) rorl $9, reg; \ + xorl %gs:POINTER_GUARD, reg +# else +# define PTR_MANGLE(var) __asm__ ("xorl %%gs:%c2, %0\n" \ + "roll $9, %0" \ + : "=r" (var) \ + : "0" (var), \ + "i" (offsetof (tcbhead_t, \ + pointer_guard))) +# define PTR_DEMANGLE(var) __asm__ ("rorl $9, %0\n" \ + "xorl %%gs:%c2, %0" \ + : "=r" (var) \ + : "0" (var), \ + "i" (offsetof (tcbhead_t, \ + pointer_guard))) +# endif +#endif + +#endif /* linux/i386/sysdep.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/vfork.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/vfork.S new file mode 100644 index 00000000..c9db2f48 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i386/vfork.S @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +#ifndef __NR_vfork +/* No vfork so use fork instead */ +# define __NR_vfork __NR_fork +#endif + +.text +.global __vfork +.hidden __vfork +.type __vfork,%function + +__vfork: + popl %ecx + +#ifdef SAVE_PID + SAVE_PID +#endif + + movl $__NR_vfork,%eax + int $0x80 + pushl %ecx + +#ifdef RESTORE_PID + RESTORE_PID +#endif + + cmpl $-4095,%eax + jae __syscall_error + ret + +.size __vfork,.-__vfork + +weak_alias(__vfork,vfork) +libc_hidden_weak(vfork) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i960/AUTHORS b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i960/AUTHORS new file mode 100644 index 00000000..0d655492 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i960/AUTHORS @@ -0,0 +1,4 @@ +The initial support (inspired by what was done in an old i960 port of uC-libc): + +Martin Proulx +http://www.okiok.com diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i960/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i960/Makefile new file mode 100644 index 00000000..d6ae358e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i960/Makefile @@ -0,0 +1,55 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2006 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + +TOPDIR=../../../../ +include $(TOPDIR)Rules.mak + +#FIXME -- this arch should include its own crti.S and crtn.S +UCLIBC_CTOR_DTOR=n + +CRT_SRC := crt0.S +CRT_OBJ := crt0.o crt1.o +CTOR_TARGETS := $(TOPDIR)lib/crti.o $(TOPDIR)lib/crtn.o + +SSRC := clone.S _mmap.S setjmp.S vfork.S +SOBJ := $(patsubst %.S,%.o, $(SSRC)) + +OBJS := $(SOBJ) + +OBJ_LIST := ../../../obj.sysdeps.$(TARGET_ARCH) + +all: $(OBJ_LIST) $(CTOR_TARGETS) + +$(OBJ_LIST): $(OBJS) $(CRT_OBJ) + $(STRIPTOOL) -x -R .note -R .comment $^ + $(INSTALL) -d $(TOPDIR)lib/ + cp $(CRT_OBJ) $(TOPDIR)lib/ + echo $(patsubst %, sysdeps/linux/$(TARGET_ARCH)/%, $(OBJS)) > $@ + +$(CRT_OBJ): $(CRT_SRC) + $(CC) $(ASFLAGS) -DL_$* $< -c -o $*.o + +$(SOBJ): %.o : %.S + $(CC) $(ASFLAGS) -c $< -o $@ + +ifeq ($(UCLIBC_CTOR_DTOR),y) +$(TOPDIR)lib/crti.o: crti.S + $(INSTALL) -d $(TOPDIR)lib/ + $(CC) $(ASFLAGS) $(SSP_DISABLE_FLAGS) -c $< -o $@ + +$(TOPDIR)lib/crtn.o: crtn.S + $(INSTALL) -d $(TOPDIR)lib/ + $(CC) $(ASFLAGS) $(SSP_DISABLE_FLAGS) -c $< -o $@ +else +$(CTOR_TARGETS): + $(INSTALL) -d $(TOPDIR)lib/ + $(AR) $(ARFLAGS) $@ +endif + +headers: + +clean: + $(RM) *.o *~ core diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i960/README b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i960/README new file mode 100644 index 00000000..75167350 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i960/README @@ -0,0 +1,71 @@ +Overview +--------------------------------------------------------------------------- + +This is the README file for the i960 support in uClibc. + +This has been tested with gcc 2.95.3 and i960-intel-coff target. + +There is no support at all to compile with the intel CTOOLS, as this would +have required too many changes to uClibc. So you won't see any support +in the asm files for position independent data or code. + +Quirks needed +--------------------------------------------------------------------------- + +prepended underscore +-------------------- + +As the i960 compiler prepends an underscore to symbols, it is critical that +Rules.mak defines SYMBOL_PREFIX as _, such that -D__UCLIBC_UNDERSCORES__ +is added to CFLAGS to make sure that underscores are applied to symbol +names when needed. + + +__va_copy in va-i960.h +---------------------- + +When compiled with gcc-2.95, the __va_copy macro in va-i960.h seems to be broken +and it has to be modified in order for uClibc to compile correctly. + +Change: + +#define __va_copy(dest, src) (dest) = (src) + +To: + +#define __va_copy(dest, src) dest[0] = src[0]; dest[1] = src[1] + + +gcc integration +--------------------------------------------------------------------------- + +I've preferred modifying the specs file so that the i960-intel-coff compiler +directly compiles with uClibc. + +First, compile and install the standard i960-intel-coff compiler, which is meant +to be used with newlib. + +Then, compile uClibc, installing over the newlib include files and libraries. + +Update the specs file with the included specs.uclinux.gcc-2.95.i960-intel-coff + +This specs file always build relocatable objects, which has the disadvantage +of not letting you know if the link is missing any symbols. + +coff2flt +--------------------------------------------------------------------------- + +In order to run the executables under uClinux, fully relocatable binaries +need to be built using coff2flt. + +We have built a working coff2flt that works with the i960 and the current version +of binfmt_flat with uClinux. + +Contact Martin Proulx for further informations. + + + + + +Check: + _mmap.S: besoin??? diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i960/bits/endian.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i960/bits/endian.h new file mode 100644 index 00000000..e2b13161 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i960/bits/endian.h @@ -0,0 +1,15 @@ +/* This file should define __BYTE_ORDER as appropriate for the machine + in question. See string/endian.h for how to define it. + + If only the stub bits/endian.h applies to a particular configuration, + bytesex.h is generated by running a program on the host machine. + So if cross-compiling to a machine with a different byte order, + the bits/endian.h file for that machine must exist. */ + +#ifndef _ENDIAN_H +# error "Never use directly; include instead." +#endif + +#define __BYTE_ORDER __LITTLE_ENDIAN + + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i960/bits/fcntl.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i960/bits/fcntl.h new file mode 100644 index 00000000..696f9618 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i960/bits/fcntl.h @@ -0,0 +1,233 @@ +/* O_*, F_*, FD_* bit values for Linux. + Copyright (C) 1995, 1996, 1997, 1998, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FCNTL_H +# error "Never use directly; include instead." +#endif + + +#include + +/* open/fcntl - O_SYNC is only implemented on blocks devices and on files + located on an ext2 file system */ +#define O_ACCMODE 0003 +#define O_RDONLY 00 +#define O_WRONLY 01 +#define O_RDWR 02 +#define O_CREAT 0100 /* not fcntl */ +#define O_EXCL 0200 /* not fcntl */ +#define O_NOCTTY 0400 /* not fcntl */ +#define O_TRUNC 01000 /* not fcntl */ +#define O_APPEND 02000 +#define O_NONBLOCK 04000 +#define O_NDELAY O_NONBLOCK +#define O_SYNC 010000 +#define O_FSYNC O_SYNC +#define O_ASYNC 020000 + +#ifdef __USE_GNU +# define O_DIRECT 040000 /* Direct disk access. */ +# define O_DIRECTORY 0200000 /* Must be a directory. */ +# define O_NOFOLLOW 0400000 /* Do not follow links. */ +#endif + +/* For now Linux has synchronisity options for data and read operations. + We define the symbols here but let them do the same as O_SYNC since + this is a superset. */ +#if defined __USE_POSIX199309 || defined __USE_UNIX98 +# define O_DSYNC O_SYNC /* Synchronize data. */ +# define O_RSYNC O_SYNC /* Synchronize read operations. */ +#endif + +#ifdef __USE_LARGEFILE64 +# define O_LARGEFILE 0100000 +#endif + +/* Values for the second argument to `fcntl'. */ +#define F_DUPFD 0 /* Duplicate file descriptor. */ +#define F_GETFD 1 /* Get file descriptor flags. */ +#define F_SETFD 2 /* Set file descriptor flags. */ +#define F_GETFL 3 /* Get file status flags. */ +#define F_SETFL 4 /* Set file status flags. */ +#ifndef __USE_FILE_OFFSET64 +# define F_GETLK 5 /* Get record locking info. */ +# define F_SETLK 6 /* Set record locking info (non-blocking). */ +# define F_SETLKW 7 /* Set record locking info (blocking). */ +#else +# define F_GETLK F_GETLK64 /* Get record locking info. */ +# define F_SETLK F_SETLK64 /* Set record locking info (non-blocking).*/ +# define F_SETLKW F_SETLKW64 /* Set record locking info (blocking). */ +#endif +#define F_GETLK64 12 /* Get record locking info. */ +#define F_SETLK64 13 /* Set record locking info (non-blocking). */ +#define F_SETLKW64 14 /* Set record locking info (blocking). */ + +#if defined __USE_BSD || defined __USE_XOPEN2K +# define F_SETOWN 8 /* Get owner of socket (receiver of SIGIO). */ +# define F_GETOWN 9 /* Set owner of socket (receiver of SIGIO). */ +#endif + +#ifdef __USE_GNU +# define F_SETSIG 10 /* Set number of signal to be sent. */ +# define F_GETSIG 11 /* Get number of signal to be sent. */ +#endif + +#ifdef __USE_GNU +# define F_SETLEASE 1024 /* Set a lease. */ +# define F_GETLEASE 1025 /* Enquire what lease is active. */ +# define F_NOTIFY 1026 /* Request notfications on a directory. */ +# define F_DUPFD_CLOEXEC 1030 /* Duplicate file descriptor with + close-on-exit set on new fd. */ +#endif + +/* For F_[GET|SET]FL. */ +#define FD_CLOEXEC 1 /* actually anything with low bit set goes */ + +/* For posix fcntl() and `l_type' field of a `struct flock' for lockf(). */ +#define F_RDLCK 0 /* Read lock. */ +#define F_WRLCK 1 /* Write lock. */ +#define F_UNLCK 2 /* Remove lock. */ + +/* For old implementation of bsd flock(). */ +#define F_EXLCK 4 /* or 3 */ +#define F_SHLCK 8 /* or 4 */ + +#ifdef __USE_BSD +/* Operations for bsd flock(), also used by the kernel implementation. */ +# define LOCK_SH 1 /* shared lock */ +# define LOCK_EX 2 /* exclusive lock */ +# define LOCK_NB 4 /* or'd with one of the above to prevent + blocking */ +# define LOCK_UN 8 /* remove lock */ +#endif + +#ifdef __USE_GNU +# define LOCK_MAND 32 /* This is a mandatory flock: */ +# define LOCK_READ 64 /* ... which allows concurrent read operations. */ +# define LOCK_WRITE 128 /* ... which allows concurrent write operations. */ +# define LOCK_RW 192 /* ... Which allows concurrent read & write operations. */ +#endif + +#ifdef __USE_GNU +/* Types of directory notifications that may be requested with F_NOTIFY. */ +# define DN_ACCESS 0x00000001 /* File accessed. */ +# define DN_MODIFY 0x00000002 /* File modified. */ +# define DN_CREATE 0x00000004 /* File created. */ +# define DN_DELETE 0x00000008 /* File removed. */ +# define DN_RENAME 0x00000010 /* File renamed. */ +# define DN_ATTRIB 0x00000020 /* File changed attibutes. */ +# define DN_MULTISHOT 0x80000000 /* Don't remove notifier. */ +#endif + +struct flock + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ +#ifndef __USE_FILE_OFFSET64 + __off_t l_start; /* Offset where the lock begins. */ + __off_t l_len; /* Size of the locked area; zero means until EOF. */ +#else + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ +#endif + __pid_t l_pid; /* Process holding the lock. */ + }; + +#ifdef __USE_LARGEFILE64 +struct flock64 + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ + __pid_t l_pid; /* Process holding the lock. */ + }; +#endif + +/* Define some more compatibility macros to be backward compatible with + BSD systems which did not managed to hide these kernel macros. */ +#ifdef __USE_BSD +# define FAPPEND O_APPEND +# define FFSYNC O_FSYNC +# define FASYNC O_ASYNC +# define FNONBLOCK O_NONBLOCK +# define FNDELAY O_NDELAY +#endif /* Use BSD. */ + +/* Advise to `posix_fadvise'. */ +#ifdef __USE_XOPEN2K +# define POSIX_FADV_NORMAL 0 /* No further special treatment. */ +# define POSIX_FADV_RANDOM 1 /* Expect random page references. */ +# define POSIX_FADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define POSIX_FADV_WILLNEED 3 /* Will need these pages. */ +# define POSIX_FADV_DONTNEED 4 /* Don't need these pages. */ +# define POSIX_FADV_NOREUSE 5 /* Data will be accessed once. */ +#endif + + +#if defined __USE_GNU && defined __UCLIBC_LINUX_SPECIFIC__ +/* Flags for SYNC_FILE_RANGE. */ +# define SYNC_FILE_RANGE_WAIT_BEFORE 1 /* Wait upon writeout of all pages + in the range before performing the + write. */ +# define SYNC_FILE_RANGE_WRITE 2 /* Initiate writeout of all those + dirty pages in the range which are + not presently under writeback. */ +# define SYNC_FILE_RANGE_WAIT_AFTER 4 /* Wait upon writeout of all pages in + the range after performing the + write. */ + +/* Flags for SPLICE and VMSPLICE. */ +# define SPLICE_F_MOVE 1 /* Move pages instead of copying. */ +# define SPLICE_F_NONBLOCK 2 /* Don't block on the pipe splicing + (but we may still block on the fd + we splice from/to). */ +# define SPLICE_F_MORE 4 /* Expect more data. */ +# define SPLICE_F_GIFT 8 /* Pages passed in are a gift. */ +#endif + +__BEGIN_DECLS + +#if defined __USE_GNU && defined __UCLIBC_LINUX_SPECIFIC__ + +/* Provide kernel hint to read ahead. */ +extern ssize_t readahead (int __fd, __off64_t __offset, size_t __count) + __THROW; + + +/* Selective file content synch'ing. */ +extern int sync_file_range (int __fd, __off64_t __from, __off64_t __to, + unsigned int __flags); + +/* Splice address range into a pipe. */ +extern ssize_t vmsplice (int __fdout, const struct iovec *__iov, + size_t __count, unsigned int __flags); + +/* Splice two files together. */ +extern ssize_t splice (int __fdin, __off64_t *__offin, int __fdout, + __off64_t *__offout, size_t __len, + unsigned int __flags); + +/* In-kernel implementation of tee for pipe buffers. */ +extern ssize_t tee (int __fdin, int __fdout, size_t __len, + unsigned int __flags); + +#endif +__END_DECLS + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i960/bits/setjmp.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i960/bits/setjmp.h new file mode 100644 index 00000000..f90e4cec --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i960/bits/setjmp.h @@ -0,0 +1,38 @@ +/* Define the machine-dependent type `jmp_buf'. i960 version. */ + +#ifndef _BITS_SETJMP_H +#define _BITS_SETJMP_H 1 + +#if !defined _SETJMP_H && !defined _PTHREAD_H +# error "Never include directly; use instead." +#endif + +/* + * assume that every single local and global register + * must be saved. + * + * ___SAVEREGS is the number of quads to save. + * + * Using the structure will guarantee quad-word alignment for the + * jmp_buf type. + */ + +#define ___SAVEREGS 8 + +typedef struct __jmp_buf__ { + long _q0; + long _q1; + long _q2; + long _q3; +} __attribute__ ((aligned (16))) __jmp_buf[___SAVEREGS] ; + +/* I have not yet figured out what this should be for the i960... */ + +#if 0 +/* Test if longjmp to JMPBUF would unwind the frame + containing a local variable at ADDRESS. */ +#define _JMPBUF_UNWINDS(jmpbuf, address) \ + ((void *) (address) < (void *) (jmpbuf)[0].__sp) +#endif + +#endif /* bits/setjmp.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i960/bits/syscalls.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i960/bits/syscalls.h new file mode 100644 index 00000000..b2185133 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i960/bits/syscalls.h @@ -0,0 +1,15 @@ +#ifndef _BITS_SYSCALLS_H +#define _BITS_SYSCALLS_H +#ifndef _SYSCALL_H +# error "Never use directly; include instead." +#endif + +#include + +/* Do something very evil for now. Until we create our own syscall + * macros, short circuit bits/sysnum.h and use asm/unistd.h instead */ +#warning "fixme -- add arch specific syscall macros.h" +#include + +#endif /* _BITS_SYSCALLS_H */ + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i960/bits/uClibc_arch_features.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i960/bits/uClibc_arch_features.h new file mode 100644 index 00000000..0ddef34b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i960/bits/uClibc_arch_features.h @@ -0,0 +1,48 @@ +/* + * Track misc arch-specific features that aren't config options + */ + +#ifndef _BITS_UCLIBC_ARCH_FEATURES_H +#define _BITS_UCLIBC_ARCH_FEATURES_H + +/* instruction used when calling abort() to kill yourself */ +/*#define __UCLIBC_ABORT_INSTRUCTION__ "asm instruction"*/ +#undef __UCLIBC_ABORT_INSTRUCTION__ + +/* can your target use syscall6() for mmap ? */ +#undef __UCLIBC_MMAP_HAS_6_ARGS__ + +/* does your target use syscall4() for truncate64 ? (32bit arches only) */ +#undef __UCLIBC_TRUNCATE64_HAS_4_ARGS__ + +/* does your target have a broken create_module() ? */ +#define __UCLIBC_BROKEN_CREATE_MODULE__ + +/* does your target have to worry about older [gs]etrlimit() ? */ +#undef __UCLIBC_HANDLE_OLDER_RLIMIT__ + +/* does your target have an asm .set ? */ +#define __UCLIBC_HAVE_ASM_SET_DIRECTIVE__ + +/* define if target doesn't like .global */ +#undef __UCLIBC_ASM_GLOBAL_DIRECTIVE__ + +/* define if target supports .weak */ +#define __UCLIBC_HAVE_ASM_WEAK_DIRECTIVE__ + +/* define if target supports .weakext */ +#undef __UCLIBC_HAVE_ASM_WEAKEXT_DIRECTIVE__ + +/* needed probably only for ppc64 */ +#undef __UCLIBC_HAVE_ASM_GLOBAL_DOT_NAME__ + +/* define if target supports CFI pseudo ops */ +#undef __UCLIBC_HAVE_ASM_CFI_DIRECTIVES__ + +/* define if target supports IEEE signed zero floats */ +#define __UCLIBC_HAVE_SIGNED_ZERO__ + +/* only weird assemblers generally need this */ +#undef __UCLIBC_ASM_LINE_SEP__ + +#endif /* _BITS_UCLIBC_ARCH_FEATURES_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i960/bits/wordsize.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i960/bits/wordsize.h new file mode 100644 index 00000000..ba643b60 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i960/bits/wordsize.h @@ -0,0 +1,19 @@ +/* Copyright (C) 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define __WORDSIZE 32 diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i960/clone.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i960/clone.S new file mode 100644 index 00000000..f602fbab --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i960/clone.S @@ -0,0 +1,62 @@ +# +# clone.S, part of the i960 support for the uClibc library. +# +# Copyright (C) 2002 by Okiok Data Ltd. http://www.okiok.com/ +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU Library General Public License as published by the Free +# Software Foundation; either version 2 of the License, or (at your option) any +# later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more +# details. +# +# You should have received a copy of the GNU Library General Public License +# along with this program; if not, write to the Free Software Foundation, Inc., +# at 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# Derived from an old port of uC-libc to the i960 by Keith Adams (kma@cse.ogi.edu). +# + +#include +#include + +/* clone is even more special than fork as it mucks with stacks + and invokes a function in the right context after its all over. */ + +/* int _clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg); */ + + .globl clone +clone: + /* set up new stack image in regs r4-r7; argument will be in r3 in child. */ + ldconst 0, r4 /* pfp == 0 */ + addo 16, g1, r5 /* sp == newfp + 16 */ + mov g0, r6 /* rip == fnc */ + mov g2, r7 + stq r4, (g1) + + addo sp, 4, sp + st g10, -4(sp) + mov sp, g10 + ldconst __NR_clone, g13 + calls 0 + + /* Do the system call */ + cmpibg 0, g0, __syscall_error /* if < 0, error */ + be thread_start /* if == 0, we're the child */ + ret /* we're the parent */ + +__syscall_error: + not g0, r3 + callx ___errno_location + st r3, (g0) + ret + +thread_start: + # our new pfp is in g1; here we go + flushreg + mov g1, pfp + flushreg + ret diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i960/crt0.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i960/crt0.S new file mode 100644 index 00000000..b167ad71 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i960/crt0.S @@ -0,0 +1,58 @@ +# +# crt0.S, part of the i960 support for the uClibc library. +# +# Copyright (C) 2002 by Okiok Data Ltd. http://www.okiok.com/ +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU Library General Public License as published by the Free +# Software Foundation; either version 2 of the License, or (at your option) any +# later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more +# details. +# +# You should have received a copy of the GNU Library General Public License +# along with this program; if not, write to the Free Software Foundation, Inc., +# at 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# + +/* + * + * The behavior in this file is tightly coupled with how the linux kernel sets things up + * on the stack before calling us. + * + * Currently fs/binfmt_flat.c (for STACK_GROWS_UP) and arch/i960/kernel/process.c + * build things so that a pointer to argc is left in g13 by start_thread(). + * + * ^ + * | <- sp somewhere around here, after being aligned. + * | + * |envp -> envp[0] + * |argv -> argv[0] + * |argc <- g13 + * + * A complete picture of how things are set up can be seen in the comments of + * create_flat_tables_stack_grows_up in fs/binfmt_flat.c + * + * I believe having to use this register could probably be avoided. + * + */ + + .globl start +start: + mov g13, r3 + ldt (r3), g0 + callx ___uClibc_main + +/* We might want to add some instruction so that it crashes if main returns */ + +/* Define a symbol for the first piece of initialized data. */ + .data + .globl __data_start +__data_start: + .long 0 + .weak data_start + data_start = __data_start + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i960/mmap.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i960/mmap.S new file mode 100644 index 00000000..bc426794 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i960/mmap.S @@ -0,0 +1,52 @@ +# +# __mmap.S, part of the i960 support for the uClibc library. +# +# Copyright (C) 2002 by Okiok Data Ltd. http://www.okiok.com/ +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU Library General Public License as published by the Free +# Software Foundation; either version 2 of the License, or (at your option) any +# later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more +# details. +# +# You should have received a copy of the GNU Library General Public License +# along with this program; if not, write to the Free Software Foundation, Inc., +# at 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# Derived from an old port of uC-libc to the i960 by Keith Adams (kma@cse.ogi.edu). +# + +#include + +/* This is a plain system call. The 6 arguments are already set up correctly */ +/* void * mmap(void *start, size_t length, int prot , int flags, int fd, off_t offset) */ + + + .globl _mmap +_mmap: + mov g13, r3 + ldconst __NR_mmap, g13 + calls 0 + mov r3, g13 + + /* We now need to check if the return value is a small negative integer. */ + /* This is somewhat tricky as the return code (normally an address) is an */ + /* unsigned type, or an ordinal in i960 assembler. */ + /* We'll use the fact that, integers from -256 to -1 are ordinals 0xFFFFFF00 to 0xFFFFFFFF. */ + /* So by checking that the return address is in the top range of the ordinals, we'll */ + /* in fact be checking if it's not an encoded negated erro code. */ + + /* The range -256 to -1 should be enough since that in uClinux 2.0.39, there are */ + /* 124 system calls for the i960. */ + + ldconst 0xFFFFFF00, r3 /* This is the integer's -256 representation */ + cmpobl g0, r3, 1f /* Something smaller than this means it's out of the range, and a valid address */ + subi g0, 0, r3 /* If it's an errno, save its negated (now positive) value in _errno. */ + st r3, _errno + subi 1, 0, g0 /* And return -1. */ +1: + ret diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i960/setjmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i960/setjmp.S new file mode 100644 index 00000000..2133ef55 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i960/setjmp.S @@ -0,0 +1,124 @@ +/******************************************************************************* + * + * Copyright (c) 1993 Intel Corporation + * + * Intel hereby grants you permission to copy, modify, and distribute this + * software and its documentation. Intel grants this permission provided + * that the above copyright notice appears in all copies and that both the + * copyright notice and this permission notice appear in supporting + * documentation. In addition, Intel grants this permission provided that + * you prominently mark as "not part of the original" any modifications + * made to this software or documentation, and that the name of Intel + * Corporation not be used in advertising or publicity pertaining to + * distribution of the software or the documentation without specific, + * written prior permission. + * + * Intel Corporation provides this AS IS, WITHOUT ANY WARRANTY, EXPRESS OR + * IMPLIED, INCLUDING, WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY + * OR FITNESS FOR A PARTICULAR PURPOSE. Intel makes no guarantee or + * representations regarding the use of, or the results of the use of, + * the software and documentation in terms of correctness, accuracy, + * reliability, currentness, or otherwise; and you rely on the software, + * documentation and results solely at your own risk. + * + * IN NO EVENT SHALL INTEL BE LIABLE FOR ANY LOSS OF USE, LOSS OF BUSINESS, + * LOSS OF PROFITS, INDIRECT, INCIDENTAL, SPECIAL OR CONSEQUENTIAL DAMAGES + * OF ANY KIND. IN NO EVENT SHALL INTEL'S TOTAL LIABILITY EXCEED THE SUM + * PAID TO INTEL FOR THE PRODUCT LICENSED HEREUNDER. + * + ******************************************************************************/ + +/*************************************************************************** + * + * Modified from the original in order to fit with + * uClibc's setjmp, _setjmp, __sigsetjmp and ___sigjmp_save. + * + * + * int setjmp (jmp_buf __env) is the BSD style setjmp function. + * It simply calls __sigsetjmp(env, 1) + * + * int _setjmp (jmp_buf __env) is the posix style setjmp function. + * It simply calls __sigsetjmp(env, 0) + * This is the one normally used. + * + ***************************************************************************/ + + .text + .align 4 + .globl _setjmp + .globl __setjmp + +_setjmp: + mov 1, g1 /* __sigsetjmp(env, 1) */ + bx __sigsetjmp + +__setjmp: + mov 0, g1 /* __sigsetjmp(env, 0) */ + bx __sigsetjmp + + +/******************************************************************************/ +/* */ +/* setjmp(), longjmp() */ +/* */ +/******************************************************************************/ + .file "setjmp.S" + .text + /* .link_pix */ + + .align 4 + .globl __sigsetjmp +__sigsetjmp: + flushreg + andnot 0xf,pfp,g2 /* get pfp, mask out return status bits */ + st g2, 0x58(g0) /* save fp of caller*/ + /* save globals not killed by the calling convention */ + stq g8, 0x40(g0) /* save g8-g11*/ + st g12, 0x50(g0) /* save g12*/ + st g14, 0x54(g0) /* save g14*/ + /* save previous frame local registers */ + ldq (g2), g4 /* get previous frame pfp, sp, rip, r3 */ + stq g4, (g0) /* save pfp, sp, rip, r3 */ + ldq 0x10(g2), g4 /* get previous frame r4-r7 */ + stq g4, 0x10(g0) /* save r4-r7 */ + ldq 0x20(g2), g4 /* get previous frame r8-r11 */ + stq g4, 0x20(g0) /* save r8-r11 */ + ldq 0x30(g2), g4 /* get previous frame r12-r15 */ + stq g4, 0x30(g0) /* save r12-r15 */ + + bx ___sigjmp_save + + /* + * fake a return to the place that called the corresponding __sigsetjmp + */ + .align 4 + .globl ___longjmp +___longjmp: + call 0f /* ensure there is at least one stack frame */ + +0: + flushreg /* do this before swapping stack */ + ld 0x58(g0), pfp /* get fp of caller of setjmp */ + /* restore local registers + * the following code modifies the frame of the function which originally + * called setjmp. + */ + ldq (g0), g4 /* get pfp, sp, rip, r3 */ + stq g4, (pfp) /* restore pfp, sp, rip, r3 */ + ldq 0x10(g0), g4 /* get r4-r7 */ + stq g4, 0x10(pfp) /* restore r4-r7 */ + ldq 0x20(g0), g4 /* get r8-r11 */ + stq g4, 0x20(pfp) /* restore r8-r11 */ + ldq 0x30(g0), g4 /* get r12-r15 */ + stq g4, 0x30(pfp) /* restore r12-r15 */ + /* restore global registers */ + ldq 0x40(g0), g8 /* get old g8-g11 values */ + ld 0x50(g0), g12 /* get old g12 value */ + ld 0x54(g0), g14 /* get old g14 value */ + + mov g1, g0 /* get return value */ + cmpo g0, 0 /* make sure it is not zero */ + bne 0f + mov 1, g0 /* return 1 by default */ +0: + ret /* return to caller of __sigsetjmp */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i960/specs.uclinux.gcc-2.95.i960-intel-coff b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i960/specs.uclinux.gcc-2.95.i960-intel-coff new file mode 100644 index 00000000..cefd8533 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i960/specs.uclinux.gcc-2.95.i960-intel-coff @@ -0,0 +1,64 @@ +*asm: +%{mka:-AKA}%{mkb:-AKB}%{msa:-ASA}%{msb:-ASB} %{mmc:-AMC}%{mca:-ACA}%{mcc:-ACC}%{mcf:-ACF} %{mja:-AJX}%{mjd:-AJX}%{mjf:-AJX}%{mrp:-AJX} %{!mka:%{!mkb:%{!msa:%{!msb:%{!mmc:%{!mca:%{!mcc:%{!mcf:%{!mja:%{!mjd:%{!mjf:%{!mrp:-AKB}}}}}}}}}}}} %{mlink-relax:-linkrelax} + +*asm_final: + + +*cpp: +%{mic*:-D__i960 %{mka:-D__i960KA}%{mkb:-D__i960KB} %{mja:-D__i960JA}%{mjd:-D__i960JD}%{mjf:-D__i960JF} %{mrp:-D__i960RP} %{msa:-D__i960SA}%{msb:-D__i960SB} %{mmc:-D__i960MC} %{mca:-D__i960CA}%{mcc:-D__i960CC} %{mcf:-D__i960CF}} %{mka:-D__i960KA__ -D__i960_KA__} %{mkb:-D__i960KB__ -D__i960_KB__} %{msa:-D__i960SA__ -D__i960_SA__} %{msb:-D__i960SB__ -D__i960_SB__} %{mmc:-D__i960MC__ -D__i960_MC__} %{mca:-D__i960CA__ -D__i960_CA__} %{mcc:-D__i960CC__ -D__i960_CC__} %{mcf:-D__i960CF__ -D__i960_CF__} %{!mka:%{!mkb:%{!msa:%{!msb:%{!mmc:%{!mca: %{!mcc:%{!mcf:-D__i960_KB -D__i960KB__ %{mic*:-D__i960KB}}}}}}}}} %{mlong-double-64:-D__LONG_DOUBLE_64__} + +*cc1: +%{!mka:%{!mkb:%{!msa:%{!msb:%{!mmc:%{!mca:%{!mcc:%{!mcf:%{!mja:%{!mjd:%{!mjf:%{!mrp:-mka}}}}}}}}}}}} %{!gs*:%{!gc*:%{mbout:%{g*:-gstabs}} %{mcoff:%{g*:-gcoff}} %{!mbout:%{!mcoff:%{g*:-gstabs}}}}} + +*cc1plus: + + +*endfile: +crtn.o%s + +*link: +%{mka:-AKA}%{mkb:-AKB}%{msa:-ASA}%{msb:-ASB} %{mmc:-AMC}%{mca:-ACA}%{mcc:-ACC}%{mcf:-ACF} %{mja:-AJX}%{mjd:-AJX}%{mjf:-AJX}%{mrp:-AJX} %{mbout:-Fbout}%{mcoff:-Fcoff} %{mlink-relax:-relax} -r -d + +*lib: +-lc -lgcc + +*libgcc: + + +*startfile: +%{!shared:%{pg:pgcrt0%O%s}%{!pg:%{p:pcrt0%O%s}%{!p:crt0%O%s}}} crti.o%s + +*switches_need_spaces: + + +*signed_char: +%{!fsigned-char:%{!mic*:-D__CHAR_UNSIGNED__}} + +*predefines: +-Di960 -Di80960 -DI960 -DI80960 -Acpu(i960) -Amachine(i960) -Dunix -Dlinux -Asystem(posix) -D__linux__ -D__uClinux__ -DEMBED + +*cross_compile: +1 + +*version: +2.95.3 + +*multilib: +. !mnumerics !msoft-float !mlong-double-64;float mnumerics !msoft-float !mlong-double-64;soft-float !mnumerics msoft-float !mlong-double-64;ld64 !mnumerics !msoft-float mlong-double-64;float/ld64 mnumerics !msoft-float mlong-double-64;soft-float/ld64 !mnumerics msoft-float mlong-double-64; + +*multilib_defaults: +mnumerics + +*multilib_extra: + + +*multilib_matches: +msb mnumerics;msc mnumerics;mkb mnumerics;mkc mnumerics;mmc mnumerics;mcb mnumerics;mcc mnumerics;mjf mnumerics;msa msoft-float;mka msoft-float;mca msoft-float;mcf msoft-float;mnumerics mnumerics;msoft-float msoft-float;mlong-double-64 mlong-double-64; + +*linker: +collect2 + +*link_command: +%{!fsyntax-only: %{!c:%{!M:%{!MM:%{!E:%{!S:%(linker) %l %X %{o*} %{A} %{d} %{e*} %{m} %{N} %{n} %{r} %{s} %{t} %{u*} %{x} %{z} %{Z} %{!A:%{!nostdlib:%{!nostartfiles:%S}}} %{static:} %{L*} %D %o %{!nostdlib:%{!nodefaultlibs:%G %L %G}} %{!A:%{!nostdlib:%{!nostartfiles:%E}}} %{T*} + }}}}}} + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i960/sys/procfs.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i960/sys/procfs.h new file mode 100644 index 00000000..27abf8ef --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i960/sys/procfs.h @@ -0,0 +1,126 @@ +/* Copyright (C) 1996, 1997, 1999, 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_PROCFS_H +#define _SYS_PROCFS_H 1 + +/* This is somewhat modelled after the file of the same name on SVR4 + systems. It provides a definition of the core file format for ELF + used on Linux. It doesn't have anything to do with the /proc file + system, even though Linux has one. + + Anyway, the whole purpose of this file is for GDB and GDB only. + Don't read too much into it. Don't use it for anything other than + GDB unless you know what you are doing. */ + +#include +#include +#include +#include + +__BEGIN_DECLS + +/* Type for a general-purpose register. */ +typedef unsigned long elf_greg_t; + +/* And the whole bunch of them. We could have used `struct + user_regs_struct' directly in the typedef, but tradition says that + the register set is an array, which does have some peculiar + semantics, so leave it that way. */ +#define ELF_NGREG (sizeof (struct user_regs_struct) / sizeof(elf_greg_t)) +typedef elf_greg_t elf_gregset_t[ELF_NGREG]; + +/* Register set for the floating-point registers. */ +typedef struct user_m68kfp_struct elf_fpregset_t; + + +/* Signal info. */ +struct elf_siginfo + { + int si_signo; /* Signal number. */ + int si_code; /* Extra code. */ + int si_errno; /* Errno. */ + }; + + +/* Definitions to generate Intel SVR4-like core files. These mostly + have the same names as the SVR4 types with "elf_" tacked on the + front to prevent clashes with Linux definitions, and the typedef + forms have been avoided. This is mostly like the SVR4 structure, + but more Linuxy, with things that Linux does not support and which + GDB doesn't really use excluded. */ + +struct elf_prstatus + { + struct elf_siginfo pr_info; /* Info associated with signal. */ + short int pr_cursig; /* Current signal. */ + unsigned long int pr_sigpend; /* Set of pending signals. */ + unsigned long int pr_sighold; /* Set of held signals. */ + __pid_t pr_pid; + __pid_t pr_ppid; + __pid_t pr_pgrp; + __pid_t pr_sid; + struct timeval pr_utime; /* User time. */ + struct timeval pr_stime; /* System time. */ + struct timeval pr_cutime; /* Cumulative user time. */ + struct timeval pr_cstime; /* Cumulative system time. */ + elf_gregset_t pr_reg; /* GP registers. */ + int pr_fpvalid; /* True if math copro being used. */ + }; + + +#define ELF_PRARGSZ (80) /* Number of chars for args. */ + +struct elf_prpsinfo + { + char pr_state; /* Numeric process state. */ + char pr_sname; /* Char for pr_state. */ + char pr_zomb; /* Zombie. */ + char pr_nice; /* Nice val. */ + unsigned long int pr_flag; /* Flags. */ + unsigned short int pr_uid; + unsigned short int pr_gid; + int pr_pid, pr_ppid, pr_pgrp, pr_sid; + /* Lots missing */ + char pr_fname[16]; /* Filename of executable. */ + char pr_psargs[ELF_PRARGSZ]; /* Initial part of arg list. */ + }; + + +/* The rest of this file provides the types for emulation of the + Solaris interfaces that should be implemented by + users of libthread_db. */ + +/* Addresses. */ +typedef void *psaddr_t; + +/* Register sets. Linux has different names. */ +typedef elf_gregset_t prgregset_t; +typedef elf_fpregset_t prfpregset_t; + +/* We don't have any differences between processes and threads, + therefore have only one PID type. */ +typedef __pid_t lwpid_t; + +/* Process status and info. In the end we do provide typedefs for them. */ +typedef struct elf_prstatus prstatus_t; +typedef struct elf_prpsinfo prpsinfo_t; + +__END_DECLS + +#endif /* sys/procfs.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i960/sys/ucontext.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i960/sys/ucontext.h new file mode 100644 index 00000000..8c55ea45 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i960/sys/ucontext.h @@ -0,0 +1,76 @@ +/* Copyright (C) 1997, 1998, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Don't rely on this, the interface is currently messed up and may need to + be broken to be fixed. */ +#ifndef _SYS_UCONTEXT_H +#define _SYS_UCONTEXT_H 1 + +#include +#include + +/* We need the signal context definitions even if they are not used + included in . */ +#include + + +/* Type for general register. */ +typedef unsigned long int greg_t; + +/* Number of general registers. */ +#define NGREG 32 /* 16 global and 16 local */ + +/* Container for all general registers. */ +/* gregset_t must be an array. The below declared array corresponds to: +typedef struct gregset { + greg_t g_regs[32]; + greg_t g_hi; + greg_t g_lo; + greg_t g_pad[3]; +} gregset_t; */ +typedef greg_t gregset_t[NGREG]; + +/* Container for all FPU registers. */ +typedef struct fpregset { + /* No floating point registers on most i960 */ + + /* Otherwise, signal the missing implementation */ +#if defined(__i960SB) || defined(__i960KB) +#error Floating point support is not yet implemented for the i960 platform. +#endif +} fpregset_t; + + +/* Context to describe whole processor state. */ +typedef struct + { + gregset_t gregs; + fpregset_t fpregs; + } mcontext_t; + +/* Userlevel context. */ +typedef struct ucontext + { + unsigned long int uc_flags; + struct ucontext *uc_link; + stack_t uc_stack; + mcontext_t uc_mcontext; + __sigset_t uc_sigmask; + } ucontext_t; + +#endif /* sys/ucontext.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i960/vfork.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i960/vfork.S new file mode 100644 index 00000000..1646e1be --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/i960/vfork.S @@ -0,0 +1,33 @@ +/* + * clone.S, part of the i960 support for the uClibc library. + * + * Copyright (C) 2002 by Okiok Data Ltd. http://www.okiok.com/ + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ +/* + * Derived from an old port of uC-libc to the i960 by Keith Adams (kma@cse.ogi.edu). + */ + +#include + +#ifndef __NR_vfork +#define __NR_vfork __NR_fork /* uClinux-2.0 only has fork which is vfork */ +#endif + + .globl ___vfork + .hidden ___vfork +___vfork: + mov g13, r3 + ldconst __NR_vfork, g13 + calls 0 + mov r3, g13 + cmpible 0, g0, 1f + subo g0, 0, r3 + st r3, _errno +1: + ret + +weak_alias(__vfork,vfork) +libc_hidden_weak(vfork) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/Makefile new file mode 100644 index 00000000..b1bf1ef1 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/Makefile @@ -0,0 +1,15 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +TOPDIR=../../../../ + +top_srcdir=$(TOPDIR) +top_builddir=../../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.arch +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/Makefile.arch b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/Makefile.arch new file mode 100644 index 00000000..223f9ef7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/Makefile.arch @@ -0,0 +1,12 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +CSRC := __syscall_error.c + +SSRC := \ + __longjmp.S brk.S bsd-setjmp.S bsd-_setjmp.S clone2.S fork.S \ + pipe.S setjmp.S syscall.S vfork.S diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/__longjmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/__longjmp.S new file mode 100644 index 00000000..85fe9363 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/__longjmp.S @@ -0,0 +1,162 @@ +/* Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc. + Contributed by David Mosberger-Tang . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. + + Note that __sigsetjmp() did NOT flush the register stack. Instead, + we do it here since __longjmp() is usually much less frequently + invoked than __sigsetjmp(). The only difficulty is that __sigsetjmp() + didn't (and wouldn't be able to) save ar.rnat either. This is a problem + because if we're not careful, we could end up loading random NaT bits. + There are two cases: + + (i) ar.bsp < ia64_rse_rnat_addr(jmpbuf.ar_bsp) + ar.rnat contains the desired bits---preserve ar.rnat + across loadrs and write to ar.bspstore + + (ii) ar.bsp >= ia64_rse_rnat_addr(jmpbuf.ar_bsp) + The desired ar.rnat is stored in + ia64_rse_rnat_addr(jmpbuf.ar_bsp). Load those + bits into ar.rnat after setting ar.bspstore. */ + +#include "sysdep.h" +#include + +# define pPos p6 /* is rotate count positive? */ +# define pNeg p7 /* is rotate count negative? */ + + + /* __longjmp(__jmp_buf buf, int val) */ + +LEAF(__longjmp) + alloc r8=ar.pfs,2,1,0,0 + mov r27=ar.rsc + add r2=0x98,in0 /* r2 <- &jmpbuf.orig_jmp_buf_addr */ + ;; + ld8 r8=[r2],-16 /* r8 <- orig_jmp_buf_addr */ + mov r10=ar.bsp + and r11=~0x3,r27 /* clear ar.rsc.mode */ + ;; + flushrs /* flush dirty regs to backing store (must be first in insn grp) */ + ld8 r23=[r2],8 /* r23 <- jmpbuf.ar_bsp */ + sub r8=r8,in0 /* r8 <- &orig_jmpbuf - &jmpbuf */ + ;; + ld8 r25=[r2] /* r25 <- jmpbuf.ar_unat */ + extr.u r8=r8,3,6 /* r8 <- (&orig_jmpbuf - &jmpbuf)/8 & 0x3f */ + ;; + cmp.lt pNeg,pPos=r8,r0 + mov r2=in0 + ;; +(pPos) mov r16=r8 +(pNeg) add r16=64,r8 +(pPos) sub r17=64,r8 +(pNeg) sub r17=r0,r8 + ;; + mov ar.rsc=r11 /* put RSE in enforced lazy mode */ + shr.u r8=r25,r16 + add r3=8,in0 /* r3 <- &jmpbuf.r1 */ + shl r9=r25,r17 + ;; + or r25=r8,r9 + ;; + mov r26=ar.rnat + mov ar.unat=r25 /* setup ar.unat (NaT bits for r1, r4-r7, and r12) */ + ;; + ld8.fill.nta sp=[r2],16 /* r12 (sp) */ + ld8.fill.nta gp=[r3],16 /* r1 (gp) */ + dep r11=-1,r23,3,6 /* r11 <- ia64_rse_rnat_addr(jmpbuf.ar_bsp) */ + ;; + ld8.nta r16=[r2],16 /* caller's unat */ + ld8.nta r17=[r3],16 /* fpsr */ + ;; + ld8.fill.nta r4=[r2],16 /* r4 */ + ld8.fill.nta r5=[r3],16 /* r5 (gp) */ + cmp.geu p8,p0=r10,r11 /* p8 <- (ar.bsp >= jmpbuf.ar_bsp) */ + ;; + ld8.fill.nta r6=[r2],16 /* r6 */ + ld8.fill.nta r7=[r3],16 /* r7 */ + ;; + mov ar.unat=r16 /* restore caller's unat */ + mov ar.fpsr=r17 /* restore fpsr */ + ;; + ld8.nta r16=[r2],16 /* b0 */ + ld8.nta r17=[r3],16 /* b1 */ + ;; +(p8) ld8 r26=[r11] /* r26 <- *ia64_rse_rnat_addr(jmpbuf.ar_bsp) */ + mov ar.bspstore=r23 /* restore ar.bspstore */ + ;; + ld8.nta r18=[r2],16 /* b2 */ + ld8.nta r19=[r3],16 /* b3 */ + ;; + ld8.nta r20=[r2],16 /* b4 */ + ld8.nta r21=[r3],16 /* b5 */ + ;; + ld8.nta r11=[r2],16 /* ar.pfs */ + ld8.nta r22=[r3],56 /* ar.lc */ + ;; + ld8.nta r24=[r2],32 /* pr */ + mov b0=r16 + ;; + ldf.fill.nta f2=[r2],32 + ldf.fill.nta f3=[r3],32 + mov b1=r17 + ;; + ldf.fill.nta f4=[r2],32 + ldf.fill.nta f5=[r3],32 + mov b2=r18 + ;; + ldf.fill.nta f16=[r2],32 + ldf.fill.nta f17=[r3],32 + mov b3=r19 + ;; + ldf.fill.nta f18=[r2],32 + ldf.fill.nta f19=[r3],32 + mov b4=r20 + ;; + ldf.fill.nta f20=[r2],32 + ldf.fill.nta f21=[r3],32 + mov b5=r21 + ;; + ldf.fill.nta f22=[r2],32 + ldf.fill.nta f23=[r3],32 + mov ar.lc=r22 + ;; + ldf.fill.nta f24=[r2],32 + ldf.fill.nta f25=[r3],32 + cmp.eq p8,p9=0,in1 + ;; + ldf.fill.nta f26=[r2],32 + ldf.fill.nta f27=[r3],32 + mov ar.pfs=r11 + ;; + ldf.fill.nta f28=[r2],32 + ldf.fill.nta f29=[r3],32 + ;; + ldf.fill.nta f30=[r2] + ldf.fill.nta f31=[r3] +(p8) mov r8=1 + + mov ar.rnat=r26 /* restore ar.rnat */ + ;; + mov ar.rsc=r27 /* restore ar.rsc */ +(p9) mov r8=in1 + + invala /* virt. -> phys. regnum mapping may change */ + mov pr=r24,-1 + ret +END(__longjmp) + +libc_hidden_def(__longjmp) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/__syscall_error.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/__syscall_error.c new file mode 100644 index 00000000..0727b2b5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/__syscall_error.c @@ -0,0 +1,19 @@ +/* Wrapper for setting errno. + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +/* This routine is jumped to by all the syscall handlers, to stash + * an error number into errno. */ +int __syscall_error(void) attribute_hidden; +int __syscall_error(void) +{ + register int err_no __asm__("%r8"); + __set_errno(err_no); + return -1; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/atomic.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/atomic.h new file mode 100644 index 00000000..1020c2f2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/atomic.h @@ -0,0 +1,119 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +typedef int8_t atomic8_t; +typedef uint8_t uatomic8_t; +typedef int_fast8_t atomic_fast8_t; +typedef uint_fast8_t uatomic_fast8_t; + +typedef int16_t atomic16_t; +typedef uint16_t uatomic16_t; +typedef int_fast16_t atomic_fast16_t; +typedef uint_fast16_t uatomic_fast16_t; + +typedef int32_t atomic32_t; +typedef uint32_t uatomic32_t; +typedef int_fast32_t atomic_fast32_t; +typedef uint_fast32_t uatomic_fast32_t; + +typedef int64_t atomic64_t; +typedef uint64_t uatomic64_t; +typedef int_fast64_t atomic_fast64_t; +typedef uint_fast64_t uatomic_fast64_t; + +typedef intptr_t atomicptr_t; +typedef uintptr_t uatomicptr_t; +typedef intmax_t atomic_max_t; +typedef uintmax_t uatomic_max_t; + + +#define __arch_compare_and_exchange_bool_8_acq(mem, newval, oldval) \ + (abort (), 0) + +#define __arch_compare_and_exchange_bool_16_acq(mem, newval, oldval) \ + (abort (), 0) + +#define __arch_compare_and_exchange_bool_32_acq(mem, newval, oldval) \ + (!__sync_bool_compare_and_swap ((mem), (int) (long) (oldval), \ + (int) (long) (newval))) + +#define __arch_compare_and_exchange_bool_64_acq(mem, newval, oldval) \ + (!__sync_bool_compare_and_swap ((mem), (long) (oldval), \ + (long) (newval))) + +#define __arch_compare_and_exchange_val_8_acq(mem, newval, oldval) \ + (abort (), (__typeof (*mem)) 0) + +#define __arch_compare_and_exchange_val_16_acq(mem, newval, oldval) \ + (abort (), (__typeof (*mem)) 0) + +#define __arch_compare_and_exchange_val_32_acq(mem, newval, oldval) \ + __sync_val_compare_and_swap ((mem), (int) (long) (oldval), \ + (int) (long) (newval)) + +#define __arch_compare_and_exchange_val_64_acq(mem, newval, oldval) \ + __sync_val_compare_and_swap ((mem), (long) (oldval), (long) (newval)) + +/* Atomically store newval and return the old value. */ +#define atomic_exchange_acq(mem, value) \ + __sync_lock_test_and_set (mem, value) + +#define atomic_exchange_rel(mem, value) \ + (__sync_synchronize (), __sync_lock_test_and_set (mem, value)) + +#define atomic_exchange_and_add(mem, value) \ + ({ __typeof (*mem) __result; \ + __result = __sync_fetch_and_add ((mem), (int) (value)); \ + __result; }) + +#define atomic_decrement_if_positive(mem) \ + ({ __typeof (*mem) __oldval, __val; \ + __typeof (mem) __memp = (mem); \ + \ + __val = (*__memp); \ + do \ + { \ + __oldval = __val; \ + if (__builtin_expect (__val <= 0, 0)) \ + break; \ + __val = atomic_compare_and_exchange_val_acq (__memp, __oldval - 1, \ + __oldval); \ + } \ + while (__builtin_expect (__val != __oldval, 0)); \ + __oldval; }) + +#define atomic_bit_test_set(mem, bit) \ + ({ __typeof (*mem) __oldval, __val; \ + __typeof (mem) __memp = (mem); \ + __typeof (*mem) __mask = ((__typeof (*mem)) 1 << (bit)); \ + \ + __val = (*__memp); \ + do \ + { \ + __oldval = __val; \ + __val = atomic_compare_and_exchange_val_acq (__memp, \ + __oldval | __mask, \ + __oldval); \ + } \ + while (__builtin_expect (__val != __oldval, 0)); \ + __oldval & __mask; }) + +#define atomic_full_barrier() __sync_synchronize () diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/byteswap.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/byteswap.h new file mode 100644 index 00000000..346c82c0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/byteswap.h @@ -0,0 +1,52 @@ +/* Macros to swap the order of bytes in integer values. + Copyright (C) 1997, 1998, 2000, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _ASM_BITS_BYTESWAP_H +#define _ASM_BITS_BYTESWAP_H 1 + +#define __bswap_non_constant_16(x) \ + (__extension__ \ + ({ register unsigned short int __v; \ + __asm__ __volatile__ ("shl %0 = %1, 48 ;;" \ + "mux1 %0 = %0, @rev ;;" \ + : "=r" (__v) \ + : "r" ((unsigned short int) (x))); \ + __v; })) + +#define __bswap_non_constant_32(x) \ + (__extension__ \ + ({ register unsigned int __v; \ + __asm__ __volatile__ ("shl %0 = %1, 32 ;;" \ + "mux1 %0 = %0, @rev ;;" \ + : "=r" (__v) \ + : "r" ((unsigned int) (x))); \ + __v; })) + +#define __bswap_non_constant_64(x) \ + (__extension__ \ + ({ register unsigned long int __v; \ + __asm__ __volatile__ ("mux1 %0 = %1, @rev ;;" \ + : "=r" (__v) \ + : "r" ((unsigned long int) (x))); \ + __v; })) +#endif + +#endif + +#include diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/endian.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/endian.h new file mode 100644 index 00000000..98a5e239 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/endian.h @@ -0,0 +1,7 @@ +/* Linux/ia64 is little-endian. */ + +#ifndef _ENDIAN_H +# error "Never use directly; include instead." +#endif + +#define __BYTE_ORDER __LITTLE_ENDIAN diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/fcntl.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/fcntl.h new file mode 100644 index 00000000..85a55f6a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/fcntl.h @@ -0,0 +1,232 @@ +/* O_*, F_*, FD_* bit values for Linux/IA64. + Copyright (C) 1999, 2000, 2004, 2006, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FCNTL_H +# error "Never use directly; include instead." +#endif + + +#include +#ifdef __USE_GNU +# include +#endif + +/* open/fcntl - O_SYNC is only implemented on blocks devices and on files + located on an ext2 file system */ +#define O_ACCMODE 0003 +#define O_RDONLY 00 +#define O_WRONLY 01 +#define O_RDWR 02 +#define O_CREAT 0100 /* not fcntl */ +#define O_EXCL 0200 /* not fcntl */ +#define O_NOCTTY 0400 /* not fcntl */ +#define O_TRUNC 01000 /* not fcntl */ +#define O_APPEND 02000 +#define O_NONBLOCK 04000 +#define O_NDELAY O_NONBLOCK +#define O_SYNC 010000 +#define O_FSYNC O_SYNC +#define O_ASYNC 020000 + +#ifdef __USE_GNU +# define O_DIRECT 040000 +# define O_DIRECTORY 0200000 /* must be a directory */ +# define O_NOFOLLOW 0400000 /* don't follow links */ +# define O_NOATIME 01000000 /* Do not set atime. */ +# define O_CLOEXEC 02000000 /* Set close_on_exec. */ +#endif + +#ifdef __USE_LARGEFILE64 +/* Not necessary, files are always with 64bit off_t. */ +# define O_LARGEFILE 0 +#endif + +/* For now Linux has synchronisity options for data and read operations. + We define the symbols here but let them do the same as O_SYNC since + this is a superset. */ +#if defined __USE_POSIX199309 || defined __USE_UNIX98 +# define O_DSYNC O_SYNC /* Synchronize data. */ +# define O_RSYNC O_SYNC /* Synchronize read operations. */ +#endif + +/* Values for the second argument to `fcntl'. */ +#define F_DUPFD 0 /* Duplicate file descriptor. */ +#define F_GETFD 1 /* Get file descriptor flags. */ +#define F_SETFD 2 /* Set file descriptor flags. */ +#define F_GETFL 3 /* Get file status flags. */ +#define F_SETFL 4 /* Set file status flags. */ +#define F_GETLK 5 /* Get record locking info. */ +#define F_SETLK 6 /* Set record locking info (non-blocking). */ +#define F_SETLKW 7 /* Set record locking info (blocking). */ + +/* Not necessary, we always have 64-bit offsets. */ +#define F_GETLK64 5 /* Get record locking info. */ +#define F_SETLK64 6 /* Set record locking info (non-blocking). */ +#define F_SETLKW64 7 /* Set record locking info (blocking). */ + +#if defined __USE_BSD || defined __USE_UNIX98 +# define F_SETOWN 8 /* Get owner of socket (receiver of SIGIO). */ +# define F_GETOWN 9 /* Set owner of socket (receiver of SIGIO). */ +#endif + +#ifdef __USE_GNU +# define F_SETSIG 10 /* Set number of signal to be sent. */ +# define F_GETSIG 11 /* Get number of signal to be sent. */ +#endif + +#ifdef __USE_GNU +# define F_SETLEASE 1024 /* Set a lease. */ +# define F_GETLEASE 1025 /* Enquire what lease is active. */ +# define F_NOTIFY 1026 /* Request notfications on a directory. */ +# define F_DUPFD_CLOEXEC 1030 /* Duplicate file descriptor with + close-on-exit set on new fd. */ +#endif + +/* For F_[GET|SET]FD. */ +#define FD_CLOEXEC 1 /* actually anything with low bit set goes */ + +/* For posix fcntl() and `l_type' field of a `struct flock' for lockf(). */ +#define F_RDLCK 0 /* Read lock. */ +#define F_WRLCK 1 /* Write lock. */ +#define F_UNLCK 2 /* Remove lock. */ + +/* for old implementation of bsd flock () */ +#define F_EXLCK 4 /* or 3 */ +#define F_SHLCK 8 /* or 4 */ + +#ifdef __USE_BSD +/* Operations for bsd flock(), also used by the kernel implementation */ +# define LOCK_SH 1 /* shared lock */ +# define LOCK_EX 2 /* exclusive lock */ +# define LOCK_NB 4 /* or'd with one of the above to prevent + blocking */ +# define LOCK_UN 8 /* remove lock */ +#endif + +#ifdef __USE_GNU +# define LOCK_MAND 32 /* This is a mandatory flock: */ +# define LOCK_READ 64 /* ... which allows concurrent read operations. */ +# define LOCK_WRITE 128 /* ... which allows concurrent write operations. */ +# define LOCK_RW 192 /* ... Which allows concurrent read & write operations. */ +#endif + + +#ifdef __USE_GNU +/* Types of directory notifications that may be requested with F_NOTIFY. */ +# define DN_ACCESS 0x00000001 /* File accessed. */ +# define DN_MODIFY 0x00000002 /* File modified. */ +# define DN_CREATE 0x00000004 /* File created. */ +# define DN_DELETE 0x00000008 /* File removed. */ +# define DN_RENAME 0x00000010 /* File renamed. */ +# define DN_ATTRIB 0x00000020 /* File changed attibutes. */ +# define DN_MULTISHOT 0x80000000 /* Don't remove notifier. */ +#endif + +/* We don't need to support __USE_FILE_OFFSET64. */ +struct flock + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ + __off_t l_start; /* Offset where the lock begins. */ + __off_t l_len; /* Size of the locked area; zero means until EOF. */ + __pid_t l_pid; /* Process holding the lock. */ + }; + +#ifdef __USE_LARGEFILE64 +struct flock64 + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ + __pid_t l_pid; /* Process holding the lock. */ + }; +#endif + +/* Define some more compatibility macros to be backward compatible with + BSD systems which did not managed to hide these kernel macros. */ +#ifdef __USE_BSD +# define FAPPEND O_APPEND +# define FFSYNC O_FSYNC +# define FASYNC O_ASYNC +# define FNONBLOCK O_NONBLOCK +# define FNDELAY O_NDELAY +#endif /* Use BSD. */ + +/* Advise to `posix_fadvise'. */ +#ifdef __USE_XOPEN2K +# define POSIX_FADV_NORMAL 0 /* No further special treatment. */ +# define POSIX_FADV_RANDOM 1 /* Expect random page references. */ +# define POSIX_FADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define POSIX_FADV_WILLNEED 3 /* Will need these pages. */ +# define POSIX_FADV_DONTNEED 4 /* Don't need these pages. */ +# define POSIX_FADV_NOREUSE 5 /* Data will be accessed once. */ +#endif + + +#if defined __USE_GNU && defined __UCLIBC_LINUX_SPECIFIC__ +/* Flags for SYNC_FILE_RANGE. */ +# define SYNC_FILE_RANGE_WAIT_BEFORE 1 /* Wait upon writeout of all pages + in the range before performing the + write. */ +# define SYNC_FILE_RANGE_WRITE 2 /* Initiate writeout of all those + dirty pages in the range which are + not presently under writeback. */ +# define SYNC_FILE_RANGE_WAIT_AFTER 4 /* Wait upon writeout of all pages in + the range after performing the + write. */ + +/* Flags for SPLICE and VMSPLICE. */ +# define SPLICE_F_MOVE 1 /* Move pages instead of copying. */ +# define SPLICE_F_NONBLOCK 2 /* Don't block on the pipe splicing + (but we may still block on the fd + we splice from/to). */ +# define SPLICE_F_MORE 4 /* Expect more data. */ +# define SPLICE_F_GIFT 8 /* Pages passed in are a gift. */ +#endif + +__BEGIN_DECLS + +#if defined __USE_GNU && defined __UCLIBC_LINUX_SPECIFIC__ + +/* Provide kernel hint to read ahead. */ +extern ssize_t readahead (int __fd, __off64_t __offset, size_t __count) + __THROW; + + +/* Selective file content synch'ing. */ +extern int sync_file_range (int __fd, __off64_t __from, __off64_t __to, + unsigned int __flags); + +/* Splice address range into a pipe. */ +extern ssize_t vmsplice (int __fdout, const struct iovec *__iov, + size_t __count, unsigned int __flags); + +/* Splice two files together. */ +extern ssize_t splice (int __fdin, __off64_t *__offin, int __fdout, + __off64_t *__offout, size_t __len, + unsigned int __flags); + +/* In-kernel implementation of tee for pipe buffers. */ +extern ssize_t tee (int __fdin, int __fdout, size_t __len, + unsigned int __flags); + +#endif +__END_DECLS + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/fenv.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/fenv.h new file mode 100644 index 00000000..32515f07 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/fenv.h @@ -0,0 +1,87 @@ +/* Copyright (C) 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FENV_H +# error "Never use directly; include instead." +#endif + + +/* Define bits representing the exception. We use the bit positions of + the appropriate bits in the FPSR... (Tahoe EAS 2.4 5-4)*/ + +enum + { + FE_INEXACT = 1UL << 5, +#define FE_INEXACT FE_INEXACT + + FE_UNDERFLOW = 1UL << 4, +#define FE_UNDERFLOW FE_UNDERFLOW + + FE_OVERFLOW = 1UL << 3, +#define FE_OVERFLOW FE_OVERFLOW + + FE_DIVBYZERO = 1UL << 2, +#define FE_DIVBYZERO FE_DIVBYZERO + + FE_UNNORMAL = 1UL << 1, +#define FE_UNNORMAL FE_UNNORMAL + + FE_INVALID = 1UL << 0, +#define FE_INVALID FE_INVALID + + FE_ALL_EXCEPT = + (FE_INEXACT | FE_UNDERFLOW | FE_OVERFLOW | FE_DIVBYZERO | FE_UNNORMAL | FE_INVALID) +#define FE_ALL_EXCEPT FE_ALL_EXCEPT + }; + + +enum + { + FE_TOWARDZERO = 3, +#define FE_TOWARDZERO FE_TOWARDZERO + + FE_UPWARD = 2, +#define FE_UPWARD FE_UPWARD + + FE_DOWNWARD = 1, +#define FE_DOWNWARD FE_DOWNWARD + + FE_TONEAREST = 0, +#define FE_TONEAREST FE_TONEAREST + }; + + +/* Type representing exception flags. */ +typedef unsigned long int fexcept_t; + +/* Type representing floating-point environment. */ +typedef unsigned long int fenv_t; + +/* If the default argument is used we use this value. */ +#define FE_DFL_ENV ((__const fenv_t *) 0xc009804c0270033fUL) + +#ifdef __USE_GNU +/* Floating-point environment where only FE_UNNORMAL is masked since this + exception is not generally supported by glibc. */ +# define FE_NOMASK_ENV ((__const fenv_t *) 0xc009804c02700302UL) + +/* Floating-point environment with (processor-dependent) non-IEEE + floating point. In this case, turning on flush-to-zero mode for + s0, s2, and s3. */ +# define FE_NONIEEE_ENV ((__const fenv_t *) 0xc009a04d0270037fUL) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/ipc.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/ipc.h new file mode 100644 index 00000000..858c332f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/ipc.h @@ -0,0 +1,54 @@ +/* Copyright (C) 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by David Mosberger-Tang + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_IPC_H +# error "Never use directly; include instead." +#endif + +#include + +/* Mode bits for `msgget', `semget', and `shmget'. */ +#define IPC_CREAT 01000 /* Create key if key does not exist. */ +#define IPC_EXCL 02000 /* Fail if key exists. */ +#define IPC_NOWAIT 04000 /* Return error on wait. */ + +/* Control commands for `msgctl', `semctl', and `shmctl'. */ +#define IPC_RMID 0 /* Remove identifier. */ +#define IPC_SET 1 /* Set `ipc_perm' options. */ +#define IPC_STAT 2 /* Get `ipc_perm' options. */ +#define IPC_INFO 3 /* See ipcs. */ + +/* Special key values. */ +#define IPC_PRIVATE ((__key_t) 0) /* Private key. */ + + +/* Data structure used to pass permission information to IPC operations. */ +struct ipc_perm + { + __key_t __key; /* Key. */ + __uid_t uid; /* Owner's user ID. */ + __gid_t gid; /* Owner's group ID. */ + __uid_t cuid; /* Creator's user ID. */ + __gid_t cgid; /* Creator's group ID. */ + __mode_t mode; /* Read/write permission. */ + unsigned short int __seq; /* Sequence number. */ + unsigned short int __pad1; + unsigned long int __unused1; + unsigned long int __unused2; + }; diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/kernel_stat.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/kernel_stat.h new file mode 100644 index 00000000..5af7e93a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/kernel_stat.h @@ -0,0 +1,37 @@ +/* Ripped from linux/include/asm-ia64/stat.h + * and renamed 'struct stat' to 'struct kernel_stat' */ + +#ifndef _ASM_IA64_STAT_H +#define _ASM_IA64_STAT_H + +#ifndef _LIBC +#error bits/kernel_stat.h is for internal uClibc use only! +#endif + +/* + * Modified 1998, 1999 + * David Mosberger-Tang , Hewlett-Packard Co + */ + +struct kernel_stat { + unsigned long st_dev; + unsigned long st_ino; + unsigned long st_nlink; + unsigned int st_mode; + unsigned int st_uid; + unsigned int st_gid; + unsigned int __pad0; + unsigned long st_rdev; + unsigned long st_size; + struct timespec st_atim; + struct timespec st_mtim; + struct timespec st_ctim; + unsigned long st_blksize; + long st_blocks; + unsigned long __unused[3]; +}; + +/* ia64 stat64 is same as stat */ +#define kernel_stat64 kernel_stat + +#endif /* _ASM_IA64_STAT_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/kernel_types.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/kernel_types.h new file mode 100644 index 00000000..c8ef86d7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/kernel_types.h @@ -0,0 +1,56 @@ +/* Note that we use the exact same include guard #define names + * as asm/posix_types.h. This will avoid gratuitous conflicts + * with the posix_types.h kernel header, and will ensure that + * our private content, and not the kernel header, will win. + * -Erik + */ +#ifndef _ASM_IA64_POSIX_TYPES_H +#define _ASM_IA64_POSIX_TYPES_H + +/* + * This file is generally used by user-level software, so you need to + * be a little careful about namespace pollution etc. Also, we cannot + * assume GCC is being used. + * + * Based on . + * + * Modified 1998-2000, 2003 + * David Mosberger-Tang , Hewlett-Packard Co + */ + +typedef unsigned long __kernel_ino_t; +typedef unsigned int __kernel_mode_t; +typedef unsigned int __kernel_nlink_t; +typedef long __kernel_off_t; +typedef long long __kernel_loff_t; +typedef int __kernel_pid_t; +typedef int __kernel_ipc_pid_t; +typedef unsigned int __kernel_uid_t; +typedef unsigned int __kernel_gid_t; +typedef unsigned long __kernel_size_t; +typedef long __kernel_ssize_t; +typedef long __kernel_ptrdiff_t; +typedef long __kernel_time_t; +typedef long __kernel_suseconds_t; +typedef long __kernel_clock_t; +typedef int __kernel_timer_t; +typedef int __kernel_clockid_t; +typedef int __kernel_daddr_t; +typedef char * __kernel_caddr_t; +typedef unsigned long __kernel_sigset_t; /* at least 32 bits */ +typedef unsigned short __kernel_uid16_t; +typedef unsigned short __kernel_gid16_t; + +typedef struct { + int val[2]; +} __kernel_fsid_t; + +typedef __kernel_uid_t __kernel_old_uid_t; +typedef __kernel_gid_t __kernel_old_gid_t; +typedef __kernel_uid_t __kernel_uid32_t; +typedef __kernel_gid_t __kernel_gid32_t; + +typedef unsigned int __kernel_dev_t; +typedef unsigned int __kernel_old_dev_t; + +#endif /* _ASM_IA64_POSIX_TYPES_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/mathdef.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/mathdef.h new file mode 100644 index 00000000..5da23cc8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/mathdef.h @@ -0,0 +1,41 @@ +/* Copyright (C) 2000, 2001, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#if !defined _MATH_H && !defined _COMPLEX_H +# error "Never use directly; include instead" +#endif + +#if defined __USE_ISOC99 && defined _MATH_H && !defined _MATH_H_MATHDEF +# define _MATH_H_MATHDEF 1 + +/* The IA-64 architecture computes values with the precision of the + used type. */ +typedef float float_t; /* `float' expressions are evaluated as + `float'. */ +typedef double double_t; /* `double' expressions are evaluated as + `double'. */ + +/* The values returned by `ilogb' for 0 and NaN respectively. */ +# define FP_ILOGB0 (-2147483647 - 1) +# define FP_ILOGBNAN 2147483647 + +#endif /* ISO C99 */ + +#if !defined __NO_LONG_DOUBLE_MATH && !defined __UCLIBC_HAS_LONG_DOUBLE_MATH__ +# define __NO_LONG_DOUBLE_MATH 1 +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/mathinline.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/mathinline.h new file mode 100644 index 00000000..9bb5f1a7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/mathinline.h @@ -0,0 +1,54 @@ +/* Inline math functions for ia64. + Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _MATH_H +# error "Never use directly; include instead." +#endif + +#ifdef __cplusplus +# define __MATH_INLINE __inline +#else +# define __MATH_INLINE extern __inline +#endif + +#if defined __USE_ISOC99 && defined __GNUC__ && __GNUC__ >= 2 +/* The gcc, version 2.7 or below, has problems with all this inlining + code. So disable it for this version of the compiler. */ +# if __GNUC_PREREQ (2, 8) +/* Test for negative number. Used in the signbit() macro. */ +__MATH_INLINE int +__NTH (__signbitf (float __x)) +{ + __extension__ union { float __f; int __i; } __u = { __f: __x }; + return __u.__i < 0; +} +__MATH_INLINE int +__NTH (__signbit (double __x)) +{ + __extension__ union { double __d; int __i[2]; } __u = { __d: __x }; + return __u.__i[1] < 0; +} +__MATH_INLINE int +__NTH (__signbitl (long double __x)) +{ + __extension__ union { long double __l; int __i[3]; } __u = { __l: __x }; + return (__u.__i[2] & 0x8000) != 0; +} +# endif +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/mman.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/mman.h new file mode 100644 index 00000000..a9d56ed0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/mman.h @@ -0,0 +1,4 @@ +#ifdef __USE_MISC +# define MAP_GROWSUP 0x00200 /* Register stack-like segment */ +#endif +#include diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/msq.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/msq.h new file mode 100644 index 00000000..cd268eea --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/msq.h @@ -0,0 +1,69 @@ +/* Copyright (C) 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contribute by David Mosberger-Tang + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_MSG_H +#error "Never use directly; include instead." +#endif + +#include + +/* Define options for message queue functions. */ +#define MSG_NOERROR 010000 /* no error if message is too big */ +#define MSG_EXCEPT 020000 /* recv any msg except of specified type */ + + +/* Structure of record for one message inside the kernel. + The type `struct __msg' is opaque. */ +struct msqid_ds +{ + struct ipc_perm msg_perm; /* structure describing operation permission */ + __time_t msg_stime; /* time of last msgsnd command */ + __time_t msg_rtime; /* time of last msgrcv command */ + __time_t msg_ctime; /* time of last change */ + unsigned long int __msg_cbytes; /* current number of bytes on queue */ + unsigned long int msg_qnum; /* number of messages currently on queue */ + unsigned long int msg_qbytes; /* max number of bytes allowed on queue */ + __pid_t msg_lspid; /* pid of last msgsnd() */ + __pid_t msg_lrpid; /* pid of last msgrcv() */ + unsigned long int __unused1; + unsigned long int __unused2; +}; + +#ifdef __USE_MISC + +# define msg_cbytes __msg_cbytes + +/* ipcs ctl commands */ +# define MSG_STAT 11 +# define MSG_INFO 12 + +/* buffer for msgctl calls IPC_INFO, MSG_INFO */ +struct msginfo + { + int msgpool; + int msgmap; + int msgmax; + int msgmnb; + int msgmni; + int msgssz; + int msgtql; + unsigned short int msgseg; + }; + +#endif /* __USE_MISC */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/sem.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/sem.h new file mode 100644 index 00000000..449f1ecc --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/sem.h @@ -0,0 +1,87 @@ +/* Copyright (C) 2000 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by David Mosberger-Tang + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_SEM_H +# error "Never include directly; use instead." +#endif + +#include + +/* Flags for `semop'. */ +#define SEM_UNDO 0x1000 /* undo the operation on exit */ + +/* Commands for `semctl'. */ +#define GETPID 11 /* get sempid */ +#define GETVAL 12 /* get semval */ +#define GETALL 13 /* get all semval's */ +#define GETNCNT 14 /* get semncnt */ +#define GETZCNT 15 /* get semzcnt */ +#define SETVAL 16 /* set semval */ +#define SETALL 17 /* set all semval's */ + + +/* Data structure describing a set of semaphores. */ +struct semid_ds +{ + struct ipc_perm sem_perm; /* operation permission struct */ + __time_t sem_otime; /* last semop() time */ + __time_t sem_ctime; /* last time changed by semctl() */ + unsigned long int sem_nsems; /* number of semaphores in set */ + unsigned long int __unused1; + unsigned long int __unused2; +}; + +/* The user should define a union like the following to use it for arguments + for `semctl'. + + union semun + { + int val; <= value for SETVAL + struct semid_ds *buf; <= buffer for IPC_STAT & IPC_SET + unsigned short int *array; <= array for GETALL & SETALL + struct seminfo *__buf; <= buffer for IPC_INFO + }; + + Previous versions of this file used to define this union but this is + incorrect. One can test the macro _SEM_SEMUN_UNDEFINED to see whether + one must define the union or not. */ +#define _SEM_SEMUN_UNDEFINED 1 + +#ifdef __USE_MISC + +/* ipcs ctl cmds */ +# define SEM_STAT 18 +# define SEM_INFO 19 + +struct seminfo +{ + int semmap; + int semmni; + int semmns; + int semmnu; + int semmsl; + int semopm; + int semume; + int semusz; + int semvmx; + int semaem; +}; + +#endif /* __USE_MISC */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/setjmp.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/setjmp.h new file mode 100644 index 00000000..76625753 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/setjmp.h @@ -0,0 +1,40 @@ +/* Define the machine-dependent type `jmp_buf'. Linux/IA-64 version. + Copyright (C) 1999, 2000, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by David Mosberger-Tang . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _BITS_SETJMP_H +#define _BITS_SETJMP_H 1 + +#if !defined _SETJMP_H && !defined _PTHREAD_H +# error "Never include directly; use instead." +#endif + +/* User code must not depend on the internal representation of jmp_buf. */ + +#define _JBLEN 70 + +/* the __jmp_buf element type should be __float80 per ABI... */ +typedef long __jmp_buf[_JBLEN] __attribute__ ((aligned (16))); /* guarantees 128-bit alignment! */ + +/* Test if longjmp to JMPBUF would unwind the frame containing a local + variable at ADDRESS. */ +#define _JMPBUF_UNWINDS(_jmpbuf, _address) \ + ((void *)(_address) < (void *)(((long *)_jmpbuf)[0])) + +#endif /* bits/setjmp.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/shm.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/shm.h new file mode 100644 index 00000000..7f38f2dd --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/shm.h @@ -0,0 +1,94 @@ +/* Copyright (C) 2000, 2002, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_SHM_H +# error "Never include directly; use instead." +#endif + +#include + +/* Permission flag for shmget. */ +#define SHM_R 0400 /* or S_IRUGO from */ +#define SHM_W 0200 /* or S_IWUGO from */ + +/* Flags for `shmat'. */ +#define SHM_RDONLY 010000 /* attach read-only else read-write */ +#define SHM_RND 020000 /* round attach address to SHMLBA */ +#define SHM_REMAP 040000 /* take-over region on attach */ + +/* Commands for `shmctl'. */ +#define SHM_LOCK 11 /* lock segment (root only) */ +#define SHM_UNLOCK 12 /* unlock segment (root only) */ + +/* Segment low boundary address multiple. */ +#define SHMLBA (1024 * 1024) + +/* Type to count number of attaches. */ +typedef unsigned long int shmatt_t; + +/* Data structure describing a set of semaphores. */ +struct shmid_ds + { + struct ipc_perm shm_perm; /* operation permission struct */ + size_t shm_segsz; /* size of segment in bytes */ + __time_t shm_atime; /* time of last shmat() */ + __time_t shm_dtime; /* time of last shmdt() */ + __time_t shm_ctime; /* time of last change by shmctl() */ + __pid_t shm_cpid; /* pid of creator */ + __pid_t shm_lpid; /* pid of last shmop */ + shmatt_t shm_nattch; /* number of current attaches */ + unsigned long int __unused1; + unsigned long int __unused2; + }; + +#ifdef __USE_MISC + +/* ipcs ctl commands */ +# define SHM_STAT 13 +# define SHM_INFO 14 + +/* shm_mode upper byte flags */ +# define SHM_DEST 01000 /* segment will be destroyed on last detach */ +# define SHM_LOCKED 02000 /* segment will not be swapped */ +# define SHM_HUGETLB 04000 /* segment is mapped via hugetlb */ +# define SHM_NORESERVE 010000 /* don't check for reservations */ + +struct shminfo + { + unsigned long int shmmax; + unsigned long int shmmin; + unsigned long int shmmni; + unsigned long int shmseg; + unsigned long int shmall; + unsigned long int __unused1; + unsigned long int __unused2; + unsigned long int __unused3; + unsigned long int __unused4; + }; + +struct shm_info + { + int used_ids; + unsigned long int shm_tot; /* total allocated shm */ + unsigned long int shm_rss; /* total resident shm */ + unsigned long int shm_swp; /* total swapped shm */ + unsigned long int swap_attempts; + unsigned long int swap_successes; + }; + +#endif /* __USE_MISC */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/sigaction.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/sigaction.h new file mode 100644 index 00000000..4049402c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/sigaction.h @@ -0,0 +1,64 @@ +/* Definitions for Linux/ia64 sigaction. + Copyright (C) 1996, 1997, 2000, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SIGNAL_H +# error "Never include directly; use instead." +#endif + +/* Structure describing the action to be taken when a signal arrives. */ +struct sigaction { +#ifdef __USE_POSIX199309 + union { + __sighandler_t sa_handler; + void (*sa_sigaction)(int, siginfo_t *, void *); + } __sigaction_handler; +# define sa_handler __sigaction_handler.sa_handler +# define sa_sigaction __sigaction_handler.sa_sigaction +#else + __sighandler_t sa_handler; +#endif + unsigned long sa_flags; + sigset_t sa_mask; + /* IA64 has no sa_restorer field. */ +}; + +/* Bits in `sa_flags'. */ +#define SA_NOCLDSTOP 0x00000001 /* Don't send SIGCHLD when children stop. */ +#define SA_NOCLDWAIT 0x00000002 /* Don't create zombie on child death. */ +#define SA_SIGINFO 0x00000004 +#if defined __USE_UNIX98 || defined __USE_MISC +# define SA_ONSTACK 0x08000000 /* Use signal stack by using `sa_restorer'. */ +# define SA_RESTART 0x10000000 /* Restart syscall on signal return. */ +# define SA_NODEFER 0x40000000 /* Don't automatically block the signal + when its handler is being executed. */ +# define SA_RESETHAND 0x80000000 /* Reset to SIG_DFL on entry to handler. */ +#endif +#ifdef __USE_MISC +# define SA_INTERRUPT 0x20000000 /* Historic no-op. */ + +/* Some aliases for the SA_ constants. */ +# define SA_NOMASK SA_NODEFER +# define SA_ONESHOT SA_RESETHAND +# define SA_STACK SA_ONSTACK +#endif + +/* Values for the HOW argument to `sigprocmask'. */ +#define SIG_BLOCK 0 /* for blocking signals */ +#define SIG_UNBLOCK 1 /* for unblocking signals */ +#define SIG_SETMASK 2 /* for setting the signal mask */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/sigcontext.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/sigcontext.h new file mode 100644 index 00000000..72c60ec2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/sigcontext.h @@ -0,0 +1,79 @@ +/* Copyright (C) 1996, 1997, 1998, 2000, 2001, 2003, 2004 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jes Sorensen , July 2000 + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#if !defined _SIGNAL_H && !defined _SYS_UCONTEXT_H +# error "Never use directly; include instead." +#endif + +#ifndef _BITS_SIGCONTEXT_H +#define _BITS_SIGCONTEXT_H 1 + +#include + +struct ia64_fpreg + { + union + { + unsigned long bits[2]; + } u; + } __attribute__ ((aligned (16))); + +struct sigcontext +{ + unsigned long int sc_flags; /* see manifest constants below */ + unsigned long int sc_nat; /* bit i == 1 iff scratch reg gr[i] is a NaT */ + stack_t sc_stack; /* previously active stack */ + + unsigned long int sc_ip; /* instruction pointer */ + unsigned long int sc_cfm; /* current frame marker */ + unsigned long int sc_um; /* user mask bits */ + unsigned long int sc_ar_rsc; /* register stack configuration register */ + unsigned long int sc_ar_bsp; /* backing store pointer */ + unsigned long int sc_ar_rnat; /* RSE NaT collection register */ + unsigned long int sc_ar_ccv; /* compare & exchange compare value register */ + unsigned long int sc_ar_unat; /* ar.unat of interrupted context */ + unsigned long int sc_ar_fpsr; /* floating-point status register */ + unsigned long int sc_ar_pfs; /* previous function state */ + unsigned long int sc_ar_lc; /* loop count register */ + unsigned long int sc_pr; /* predicate registers */ + unsigned long int sc_br[8]; /* branch registers */ + unsigned long int sc_gr[32]; /* general registers (static partition) */ + struct ia64_fpreg sc_fr[128]; /* floating-point registers */ + unsigned long int sc_rbs_base;/* NULL or new base of sighandler's rbs */ + unsigned long int sc_loadrs; /* see description above */ + unsigned long int sc_ar25; /* cmp8xchg16 uses this */ + unsigned long int sc_ar26; /* rsvd for scratch use */ + unsigned long int sc_rsvd[12];/* reserved for future use */ + + /* sc_mask is actually an sigset_t but we don't want to + * include the kernel headers here. */ + unsigned long int sc_mask; /* signal mask to restore after handler returns */ +}; + +/* sc_flag bit definitions. */ +#define IA64_SC_FLAG_ONSTACK_BIT 0 /* is handler running on signal stack? */ +#define IA64_SC_FLAG_IN_SYSCALL_BIT 1 /* did signal interrupt a syscall? */ +#define IA64_SC_FLAG_FPH_VALID_BIT 2 /* is state in f[32]-f[127] valid? */ + +#define IA64_SC_FLAG_ONSTACK (1 << IA64_SC_FLAG_ONSTACK_BIT) +#define IA64_SC_FLAG_IN_SYSCALL (1 << IA64_SC_FLAG_IN_SYSCALL_BIT) +#define IA64_SC_FLAG_FPH_VALID (1 << IA64_SC_FLAG_FPH_VALID_BIT) + +#endif /* _BITS_SIGCONTEXT_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/siginfo.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/siginfo.h new file mode 100644 index 00000000..66310c65 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/siginfo.h @@ -0,0 +1,339 @@ +/* siginfo_t, sigevent and constants. Linux/ia64 version. + Copyright (C) 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by David Mosberger-Tang . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#if !defined _SIGNAL_H && !defined __need_siginfo_t \ + && !defined __need_sigevent_t +# error "Never include this file directly. Use instead" +#endif + +#if (!defined __have_sigval_t \ + && (defined _SIGNAL_H || defined __need_siginfo_t \ + || defined __need_sigevent_t)) +# define __have_sigval_t 1 + +/* Type for data associated with a signal. */ +typedef union sigval + { + int sival_int; + void *sival_ptr; + } sigval_t; +#endif + +#if (!defined __have_siginfo_t \ + && (defined _SIGNAL_H || defined __need_siginfo_t)) +# define __have_siginfo_t 1 + +# define __SI_MAX_SIZE 128 +# define __SI_PAD_SIZE ((__SI_MAX_SIZE / sizeof (int)) - 4) + +typedef struct siginfo + { + int si_signo; /* Signal number. */ + int si_errno; /* If non-zero, an errno value associated with + this signal, as defined in . */ + int si_code; /* Signal code. */ + int __pad0; /* Explicit padding. */ + + union + { + int _pad[__SI_PAD_SIZE]; + + /* kill(). */ + struct + { + __pid_t si_pid; /* Sending process ID. */ + __uid_t si_uid; /* Real user ID of sending process. */ + } _kill; + + /* POSIX.1b timers. */ + struct + { + int si_tid; /* Timer ID. */ + int si_overrun; /* Overrun count. */ + sigval_t si_sigval; /* Signal value. */ + } _timer; + + /* POSIX.1b signals. */ + struct + { + __pid_t si_pid; /* Sending process ID. */ + __uid_t si_uid; /* Real user ID of sending process. */ + sigval_t si_sigval; /* Signal value. */ + } _rt; + + /* SIGCHLD. */ + struct + { + __pid_t si_pid; /* Which child. */ + __uid_t si_uid; /* Real user ID of sending process. */ + int si_status; /* Exit value or signal. */ + __clock_t si_utime; + __clock_t si_stime; + } _sigchld; + + /* SIGILL, SIGFPE, SIGSEGV, SIGBUS. */ + struct + { + void *si_addr; /* Faulting insn/memory ref. */ + int _si_imm; + unsigned int _si_flags; + unsigned long int _si_isr; + } _sigfault; + + /* SIGPOLL. */ + struct + { + long int si_band; /* Band event for SIGPOLL. */ + int si_fd; + } _sigpoll; + } _sifields; + } siginfo_t; + + +/* X/Open requires some more fields with fixed names. */ +# define si_pid _sifields._kill.si_pid +# define si_uid _sifields._kill.si_uid +# define si_timerid _sifields._timer.si_tid +# define si_overrun _sifields._timer.si_overrun +# define si_status _sifields._sigchld.si_status +# define si_utime _sifields._sigchld.si_utime +# define si_stime _sifields._sigchld.si_stime +# define si_value _sifields._rt.si_sigval +# define si_int _sifields._rt.si_sigval.sival_int +# define si_ptr _sifields._rt.si_sigval.sival_ptr +# define si_addr _sifields._sigfault.si_addr +# define si_band _sifields._sigpoll.si_band +# define si_fd _sifields._sigpoll.si_fd + +# ifdef __USE_GNU +# define si_imm _sifields._sigfault._si_imm +# define si_segvflags _sifields._sigfault._si_flags +# define si_isr _sifields._sigfault._si_isr +# endif + +/* Values for `si_code'. Positive values are reserved for kernel-generated + signals. */ +enum +{ + SI_ASYNCNL = -60, /* Sent by asynch name lookup completion. */ +# define SI_ASYNCNL SI_ASYNCNL + SI_TKILL = -6, /* Sent by tkill. */ +# define SI_TKILL SI_TKILL + SI_SIGIO, /* Sent by queued SIGIO. */ +# define SI_SIGIO SI_SIGIO + SI_ASYNCIO, /* Sent by AIO completion. */ +# define SI_ASYNCIO SI_ASYNCIO + SI_MESGQ, /* Sent by real time mesq state change. */ +# define SI_MESGQ SI_MESGQ + SI_TIMER, /* Sent by timer expiration. */ +# define SI_TIMER SI_TIMER + SI_QUEUE, /* Sent by sigqueue. */ +# define SI_QUEUE SI_QUEUE + SI_USER, /* Sent by kill, sigsend, raise. */ +# define SI_USER SI_USER + SI_KERNEL = 0x80 /* Send by kernel. */ +#define SI_KERNEL SI_KERNEL +}; + + +/* `si_code' values for SIGILL signal. */ +enum +{ + ILL_ILLOPC = 1, /* Illegal opcode. */ +# define ILL_ILLOPC ILL_ILLOPC + ILL_ILLOPN, /* Illegal operand. */ +# define ILL_ILLOPN ILL_ILLOPN + ILL_ILLADR, /* Illegal addressing mode. */ +# define ILL_ILLADR ILL_ILLADR + ILL_ILLTRP, /* Illegal trap. */ +# define ILL_ILLTRP ILL_ILLTRP + ILL_PRVOPC, /* Privileged opcode. */ +# define ILL_PRVOPC ILL_PRVOPC + ILL_PRVREG, /* Privileged register. */ +# define ILL_PRVREG ILL_PRVREG + ILL_COPROC, /* Coprocessor error. */ +# define ILL_COPROC ILL_COPROC + ILL_BADSTK, /* Internal stack error. */ +# define ILL_BADSTK ILL_BADSTK + ILL_BADIADDR /* Unimplemented instruction address. */ +# define ILL_BADIADDR ILL_BADIADDR + +# ifdef __USE_GNU + , ILL_BREAK +# define ILL_BREAK ILL_BREAK +# endif +}; + +/* `si_code' values for SIGFPE signal. */ +enum +{ + FPE_INTDIV = 1, /* Integer divide by zero. */ +# define FPE_INTDIV FPE_INTDIV + FPE_INTOVF, /* Integer overflow. */ +# define FPE_INTOVF FPE_INTOVF + FPE_FLTDIV, /* Floating point divide by zero. */ +# define FPE_FLTDIV FPE_FLTDIV + FPE_FLTOVF, /* Floating point overflow. */ +# define FPE_FLTOVF FPE_FLTOVF + FPE_FLTUND, /* Floating point underflow. */ +# define FPE_FLTUND FPE_FLTUND + FPE_FLTRES, /* Floating point inexact result. */ +# define FPE_FLTRES FPE_FLTRES + FPE_FLTINV, /* Floating point invalid operation. */ +# define FPE_FLTINV FPE_FLTINV + FPE_FLTSUB /* Subscript out of range. */ +# define FPE_FLTSUB FPE_FLTSUB +# ifdef __USE_GNU + , FPE_DECOVF +# define FPE_DECOVF FPE_DECOVF + , FPE_DECDIV +# define FPE_DECDIV FPE_DECDIV + , FPE_DECERR +# define FPE_DECERR FPE_DECERR + , FPE_INVASC +# define FPE_INVASC FPE_INVASC + , FPE_INVDEC +# define FPE_INVDEC FPE_INVDEC +# endif +}; + +/* `si_code' values for SIGSEGV signal. */ +enum +{ + SEGV_MAPERR = 1, /* Address not mapped to object. */ +# define SEGV_MAPERR SEGV_MAPERR + SEGV_ACCERR /* Invalid permissions for mapped object. */ +# define SEGV_ACCERR SEGV_ACCERR +# ifdef __USE_GNU + , SEGV_PSTKOVF /* Paragraph stack overflow. */ +# define SEGV_PSTKOVF SEGV_PSTKOVF +# endif +}; + +/* `si_code' values for SIGBUS signal. */ +enum +{ + BUS_ADRALN = 1, /* Invalid address alignment. */ +# define BUS_ADRALN BUS_ADRALN + BUS_ADRERR, /* Non-existant physical address. */ +# define BUS_ADRERR BUS_ADRERR + BUS_OBJERR /* Object specific hardware error. */ +# define BUS_OBJERR BUS_OBJERR +}; + +/* `si_code' values for SIGTRAP signal. */ +enum +{ + TRAP_BRKPT = 1, /* Process breakpoint. */ +# define TRAP_BRKPT TRAP_BRKPT + TRAP_TRACE /* Process trace trap. */ +# define TRAP_TRACE TRAP_TRACE + +# ifdef __USE_GNU + , TRAP_BRANCH +# define TRAP_BRANCH TRAP_BRANCH + , TRAP_HWBKPT +# define TRAP_HWBKPT TRAP_HWBKPT +# endif +}; + +/* `si_code' values for SIGCHLD signal. */ +enum +{ + CLD_EXITED = 1, /* Child has exited. */ +# define CLD_EXITED CLD_EXITED + CLD_KILLED, /* Child was killed. */ +# define CLD_KILLED CLD_KILLED + CLD_DUMPED, /* Child terminated abnormally. */ +# define CLD_DUMPED CLD_DUMPED + CLD_TRAPPED, /* Traced child has trapped. */ +# define CLD_TRAPPED CLD_TRAPPED + CLD_STOPPED, /* Child has stopped. */ +# define CLD_STOPPED CLD_STOPPED + CLD_CONTINUED /* Stopped child has continued. */ +# define CLD_CONTINUED CLD_CONTINUED +}; + +/* `si_code' values for SIGPOLL signal. */ +enum +{ + POLL_IN = 1, /* Data input available. */ +# define POLL_IN POLL_IN + POLL_OUT, /* Output buffers available. */ +# define POLL_OUT POLL_OUT + POLL_MSG, /* Input message available. */ +# define POLL_MSG POLL_MSG + POLL_ERR, /* I/O error. */ +# define POLL_ERR POLL_ERR + POLL_PRI, /* High priority input available. */ +# define POLL_PRI POLL_PRI + POLL_HUP /* Device disconnected. */ +# define POLL_HUP POLL_HUP +}; + +# undef __need_siginfo_t +#endif /* !have siginfo_t && (have _SIGNAL_H || need siginfo_t). */ + + +#if (defined _SIGNAL_H || defined __need_sigevent_t) \ + && !defined __have_sigevent_t +# define __have_sigevent_t 1 + +/* Structure to transport application-defined values with signals. */ +# define __SIGEV_MAX_SIZE 64 +# define __SIGEV_PAD_SIZE ((__SIGEV_MAX_SIZE / sizeof (int)) - 4) + +typedef struct sigevent + { + sigval_t sigev_value; + int sigev_signo; + int sigev_notify; + + union + { + int _pad[__SIGEV_PAD_SIZE]; + + struct + { + void (*_function) (sigval_t); /* Function to start. */ + void *_attribute; /* Really pthread_attr_t. */ + } _sigev_thread; + } _sigev_un; + } sigevent_t; + +/* POSIX names to access some of the members. */ +# define sigev_notify_function _sigev_un._sigev_thread._function +# define sigev_notify_attributes _sigev_un._sigev_thread._attribute + +/* `sigev_notify' values. */ +enum +{ + SIGEV_SIGNAL = 0, /* Notify via signal. */ +# define SIGEV_SIGNAL SIGEV_SIGNAL + SIGEV_NONE, /* Other notification: meaningless. */ +# define SIGEV_NONE SIGEV_NONE + SIGEV_THREAD, /* Deliver via thread creation. */ +# define SIGEV_THREAD SIGEV_THREAD + + SIGEV_THREAD_ID = 4 /* Send signal to specific thread. */ +#define SIGEV_THREAD_ID SIGEV_THREAD_ID +}; + +#endif /* have _SIGNAL_H. */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/sigstack.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/sigstack.h new file mode 100644 index 00000000..c9c9d2fe --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/sigstack.h @@ -0,0 +1,63 @@ +/* sigstack, sigaltstack definitions. + Copyright (C) 1998, 2000, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SIGNAL_H +# error "Never include this file directly. Use instead" +#endif + +#ifndef _SIGSTACK_H +#define _SIGSTACK_H 1 + +/* Structure describing a signal stack (obsolete). */ +struct sigstack + { + __ptr_t ss_sp; /* Signal stack pointer. */ + int ss_onstack; /* Nonzero if executing on this stack. */ + }; + + +/* Possible values for `ss_flags.'. */ +enum +{ + SS_ONSTACK = 1, +#define SS_ONSTACK SS_ONSTACK + SS_DISABLE +#define SS_DISABLE SS_DISABLE +}; + +/* Minimum stack size for a signal handler. + + Yes, this should be 131072 but the constant got defined incorrectly + in the kernel and we have to live with it. Users should in any case + use SIGSTKSZ as the size user-supplied buffers should have. */ +#define MINSIGSTKSZ 131027 + +/* System default stack size. */ +#define SIGSTKSZ 262144 + + +/* Alternate, preferred interface. */ +typedef struct sigaltstack + { + __ptr_t ss_sp; + int ss_flags; + size_t ss_size; + } stack_t; + +#endif /* bits/sigstack.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/stackinfo.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/stackinfo.h new file mode 100644 index 00000000..b7dc5d91 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/stackinfo.h @@ -0,0 +1,29 @@ +/* Copyright (C) 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This file contains a bit of information about the stack allocation + of the processor. */ + +#ifndef _STACKINFO_H +#define _STACKINFO_H 1 + +/* On IA-64 the stack grows down. The register stack is of no concern + here. */ +#define _STACK_GROWS_DOWN 1 + +#endif /* stackinfo.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/stat.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/stat.h new file mode 100644 index 00000000..75a33182 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/stat.h @@ -0,0 +1,145 @@ +/* Copyright (C) 1999, 2000, 2001, 2002, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_STAT_H +# error "Never include directly; use instead." +#endif + +/* Versions of the `struct stat' data structure. */ +#define _STAT_VER_KERNEL 0 +#define _STAT_VER_LINUX 1 +#define _STAT_VER _STAT_VER_LINUX + +/* Versions of the `xmknod' interface. */ +#define _MKNOD_VER_LINUX 0 + +struct stat + { + __dev_t st_dev; /* Device. */ + __ino_t st_ino; /* File serial number. */ + __nlink_t st_nlink; /* Link count. */ + __mode_t st_mode; /* File mode. */ + __uid_t st_uid; /* User ID of the file's owner. */ + __gid_t st_gid; /* Group ID of the file's group.*/ + int pad0; + __dev_t st_rdev; /* Device number, if device. */ + __off_t st_size; /* Size of file, in bytes. */ +#ifdef __USE_MISC + /* Nanosecond resolution timestamps are stored in a format + equivalent to 'struct timespec'. This is the type used + whenever possible but the Unix namespace rules do not allow the + identifier 'timespec' to appear in the header. + Therefore we have to handle the use of this header in strictly + standard-compliant sources special. */ + struct timespec st_atim; /* Time of last access. */ + struct timespec st_mtim; /* Time of last modification. */ + struct timespec st_ctim; /* Time of last status change. */ +# define st_atime st_atim.tv_sec /* Backward compatibility. */ +# define st_mtime st_mtim.tv_sec +# define st_ctime st_ctim.tv_sec +#else + __time_t st_atime; /* Time of last access. */ + unsigned long int st_atimensec; /* Nscecs of last access. */ + __time_t st_mtime; /* Time of last modification. */ + unsigned long int st_mtimensec; /* Nsecs of last modification. */ + __time_t st_ctime; /* Time of last status change. */ + unsigned long int st_ctimensec; /* Nsecs of last status change. */ +#endif + __blksize_t st_blksize; /* Optimal block size for I/O. */ + __blkcnt_t st_blocks; /* Nr. 512-byte blocks allocated. */ + long int __unused[3]; + }; + +#ifdef __USE_LARGEFILE64 +/* Note stat64 is the same shape as stat. */ +struct stat64 + { + __dev_t st_dev; /* Device. */ + __ino64_t st_ino; /* File serial number. */ + __nlink_t st_nlink; /* Link count. */ + __mode_t st_mode; /* File mode. */ + __uid_t st_uid; /* User ID of the file's owner. */ + __gid_t st_gid; /* Group ID of the file's group.*/ + int pad0; + __dev_t st_rdev; /* Device number, if device. */ + __off_t st_size; /* Size of file, in bytes. */ +#ifdef __USE_MISC + /* Nanosecond resolution timestamps are stored in a format + equivalent to 'struct timespec'. This is the type used + whenever possible but the Unix namespace rules do not allow the + identifier 'timespec' to appear in the header. + Therefore we have to handle the use of this header in strictly + standard-compliant sources special. */ + struct timespec st_atim; /* Time of last access. */ + struct timespec st_mtim; /* Time of last modification. */ + struct timespec st_ctim; /* Time of last status change. */ +# define st_atime st_atim.tv_sec /* Backward compatibility. */ +# define st_mtime st_mtim.tv_sec +# define st_ctime st_ctim.tv_sec +#else + __time_t st_atime; /* Time of last access. */ + unsigned long int st_atimensec; /* Nscecs of last access. */ + __time_t st_mtime; /* Time of last modification. */ + unsigned long int st_mtimensec; /* Nsecs of last modification. */ + __time_t st_ctime; /* Time of last status change. */ + unsigned long int st_ctimensec; /* Nsecs of last status change. */ +#endif + __blksize_t st_blksize; /* Optimal block size for I/O. */ + __blkcnt64_t st_blocks; /* Nr. 512-byte blocks allocated. */ + long int __unused[3]; + }; +#endif + +/* Tell code we have these members. */ +#define _STATBUF_ST_BLKSIZE +#define _STATBUF_ST_RDEV +/* Nanosecond resolution time values are supported. */ +#define _STATBUF_ST_NSEC + +/* Encoding of the file mode. */ + +#define __S_IFMT 0170000 /* These bits determine file type. */ + +/* File types. */ +#define __S_IFDIR 0040000 /* Directory. */ +#define __S_IFCHR 0020000 /* Character device. */ +#define __S_IFBLK 0060000 /* Block device. */ +#define __S_IFREG 0100000 /* Regular file. */ +#define __S_IFIFO 0010000 /* FIFO. */ +#define __S_IFLNK 0120000 /* Symbolic link. */ +#define __S_IFSOCK 0140000 /* Socket. */ + +/* POSIX.1b objects. Note that these macros always evaluate to zero. But + they do it by enforcing the correct use of the macros. */ +#define __S_TYPEISMQ(buf) ((buf)->st_mode - (buf)->st_mode) +#define __S_TYPEISSEM(buf) ((buf)->st_mode - (buf)->st_mode) +#define __S_TYPEISSHM(buf) ((buf)->st_mode - (buf)->st_mode) + +/* Protection bits. */ + +#define __S_ISUID 04000 /* Set user ID on execution. */ +#define __S_ISGID 02000 /* Set group ID on execution. */ +#define __S_ISVTX 01000 /* Save swapped text after use (sticky). */ +#define __S_IREAD 0400 /* Read by owner. */ +#define __S_IWRITE 0200 /* Write by owner. */ +#define __S_IEXEC 0100 /* Execute by owner. */ + +#ifdef __USE_ATFILE +# define UTIME_NOW ((1l << 30) - 1l) +# define UTIME_OMIT ((1l << 30) - 2l) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/syscalls.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/syscalls.h new file mode 100644 index 00000000..9c6a2b77 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/syscalls.h @@ -0,0 +1,161 @@ +/* Copyright (C) 1999, 2000, 2002, 2003, 2004, 2005, 2006 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + Written by Jes Sorensen, , April 1999. + Based on code originally written by David Mosberger-Tang + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _BITS_SYSCALLS_H +#define _BITS_SYSCALLS_H + +#ifndef _SYSCALL_H +# error "Never use directly; include instead." +#endif + +#ifndef __ASSEMBLER__ + +#include + +#undef IA64_USE_NEW_STUB + +#define __IA64_BREAK_SYSCALL 0x100000 + +/* mostly taken from glibc sysdeps/unix/sysv/linux/ia64/sysdep.h */ +#define BREAK_INSN_1(num) "break " #num ";;\n\t" +#define BREAK_INSN(num) BREAK_INSN_1(num) + +/* On IA-64 we have stacked registers for passing arguments. The + "out" registers end up being the called function's "in" + registers. + + Also, since we have plenty of registers we have two return values + from a syscall. r10 is set to -1 on error, whilst r8 contains the + (non-negative) errno on error or the return value on success. + */ + +# define DO_INLINE_SYSCALL_NCS(name, nr, args...) \ + LOAD_ARGS_##nr (args) \ + register long _r8 __asm__ ("r8"); \ + register long _r10 __asm__ ("r10"); \ + register long _r15 __asm__ ("r15") = name; \ + long _retval; \ + LOAD_REGS_##nr \ + __asm__ __volatile__ (BREAK_INSN (__IA64_BREAK_SYSCALL) \ + : "=r" (_r8), "=r" (_r10), "=r" (_r15) \ + ASM_OUTARGS_##nr \ + : "2" (_r15) ASM_ARGS_##nr \ + : "memory" ASM_CLOBBERS_##nr); \ + _retval = _r8; + +#define INLINE_SYSCALL_NCS(name, nr, args...) \ + ({ \ + DO_INLINE_SYSCALL_NCS (name, nr, args) \ + if (_r10 == -1) \ + { \ + __set_errno (_retval); \ + _retval = -1; \ + } \ + _retval; }) + +#define INTERNAL_SYSCALL_DECL(err) long int err + +#define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \ + ({ \ + DO_INLINE_SYSCALL_NCS (name, nr, args) \ + err = _r10; \ + _retval; }) + +#define INTERNAL_SYSCALL_ERROR_P(val, err) (err == -1) + +#define INTERNAL_SYSCALL_ERRNO(val, err) (val) + +#define LOAD_ARGS_0() +#define LOAD_REGS_0 +#define LOAD_ARGS_1(a1) \ + long _arg1 = (long) (a1); \ + LOAD_ARGS_0 () +#define LOAD_REGS_1 \ + register long _out0 __asm__ ("out0") = _arg1; \ + LOAD_REGS_0 +#define LOAD_ARGS_2(a1, a2) \ + long _arg2 = (long) (a2); \ + LOAD_ARGS_1 (a1) +#define LOAD_REGS_2 \ + register long _out1 __asm__ ("out1") = _arg2; \ + LOAD_REGS_1 +#define LOAD_ARGS_3(a1, a2, a3) \ + long _arg3 = (long) (a3); \ + LOAD_ARGS_2 (a1, a2) +#define LOAD_REGS_3 \ + register long _out2 __asm__ ("out2") = _arg3; \ + LOAD_REGS_2 +#define LOAD_ARGS_4(a1, a2, a3, a4) \ + long _arg4 = (long) (a4); \ + LOAD_ARGS_3 (a1, a2, a3) +#define LOAD_REGS_4 \ + register long _out3 __asm__ ("out3") = _arg4; \ + LOAD_REGS_3 +#define LOAD_ARGS_5(a1, a2, a3, a4, a5) \ + long _arg5 = (long) (a5); \ + LOAD_ARGS_4 (a1, a2, a3, a4) +#define LOAD_REGS_5 \ + register long _out4 __asm__ ("out4") = _arg5; \ + LOAD_REGS_4 +#define LOAD_ARGS_6(a1, a2, a3, a4, a5, a6) \ + long _arg6 = (long) (a6); \ + LOAD_ARGS_5 (a1, a2, a3, a4, a5) +#define LOAD_REGS_6 \ + register long _out5 __asm__ ("out5") = _arg6; \ + LOAD_REGS_5 + +#define ASM_OUTARGS_0 +#define ASM_OUTARGS_1 ASM_OUTARGS_0, "=r" (_out0) +#define ASM_OUTARGS_2 ASM_OUTARGS_1, "=r" (_out1) +#define ASM_OUTARGS_3 ASM_OUTARGS_2, "=r" (_out2) +#define ASM_OUTARGS_4 ASM_OUTARGS_3, "=r" (_out3) +#define ASM_OUTARGS_5 ASM_OUTARGS_4, "=r" (_out4) +#define ASM_OUTARGS_6 ASM_OUTARGS_5, "=r" (_out5) + +#define ASM_ARGS_0 +#define ASM_ARGS_1 ASM_ARGS_0, "3" (_out0) +#define ASM_ARGS_2 ASM_ARGS_1, "4" (_out1) +#define ASM_ARGS_3 ASM_ARGS_2, "5" (_out2) +#define ASM_ARGS_4 ASM_ARGS_3, "6" (_out3) +#define ASM_ARGS_5 ASM_ARGS_4, "7" (_out4) +#define ASM_ARGS_6 ASM_ARGS_5, "8" (_out5) + +#define ASM_CLOBBERS_0 ASM_CLOBBERS_1, "out0" +#define ASM_CLOBBERS_1 ASM_CLOBBERS_2, "out1" +#define ASM_CLOBBERS_2 ASM_CLOBBERS_3, "out2" +#define ASM_CLOBBERS_3 ASM_CLOBBERS_4, "out3" +#define ASM_CLOBBERS_4 ASM_CLOBBERS_5, "out4" +#define ASM_CLOBBERS_5 ASM_CLOBBERS_6, "out5" +#define ASM_CLOBBERS_6 ASM_CLOBBERS_6_COMMON , "b7" +#define ASM_CLOBBERS_6_COMMON , "out6", "out7", \ + /* Non-stacked integer registers, minus r8, r10, r15. */ \ + "r2", "r3", "r9", "r11", "r12", "r13", "r14", "r16", "r17", "r18", \ + "r19", "r20", "r21", "r22", "r23", "r24", "r25", "r26", "r27", \ + "r28", "r29", "r30", "r31", \ + /* Predicate registers. */ \ + "p6", "p7", "p8", "p9", "p10", "p11", "p12", "p13", "p14", "p15", \ + /* Non-rotating fp registers. */ \ + "f6", "f7", "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", \ + /* Branch registers. */ \ + "b6" + +#endif /* __ASSEMBLER__ */ +#endif /* _BITS_SYSCALLS_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/uClibc_arch_features.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/uClibc_arch_features.h new file mode 100644 index 00000000..a3644ceb --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/uClibc_arch_features.h @@ -0,0 +1,47 @@ +/* + * Track misc arch-specific features that aren't config options + */ + +#ifndef _BITS_UCLIBC_ARCH_FEATURES_H +#define _BITS_UCLIBC_ARCH_FEATURES_H + +/* instruction used when calling abort() to kill yourself */ +#define __UCLIBC_ABORT_INSTRUCTION__ "break 0" + +/* can your target use syscall6() for mmap ? */ +#define __UCLIBC_MMAP_HAS_6_ARGS__ + +/* does your target use syscall4() for truncate64 ? (32bit arches only) */ +#undef __UCLIBC_TRUNCATE64_HAS_4_ARGS__ + +/* does your target have a broken create_module() ? */ +#undef __UCLIBC_BROKEN_CREATE_MODULE__ + +/* does your target have to worry about older [gs]etrlimit() ? */ +#undef __UCLIBC_HANDLE_OLDER_RLIMIT__ + +/* does your target have an asm .set ? */ +#define __UCLIBC_HAVE_ASM_SET_DIRECTIVE__ + +/* define if target doesn't like .global */ +#undef __UCLIBC_ASM_GLOBAL_DIRECTIVE__ + +/* define if target supports .weak */ +#define __UCLIBC_HAVE_ASM_WEAK_DIRECTIVE__ + +/* define if target supports .weakext */ +#undef __UCLIBC_HAVE_ASM_WEAKEXT_DIRECTIVE__ + +/* needed probably only for ppc64 */ +#undef __UCLIBC_HAVE_ASM_GLOBAL_DOT_NAME__ + +/* define if target supports CFI pseudo ops */ +#undef __UCLIBC_HAVE_ASM_CFI_DIRECTIVES__ + +/* define if target supports IEEE signed zero floats */ +#define __UCLIBC_HAVE_SIGNED_ZERO__ + +/* only weird assemblers generally need this */ +#undef __UCLIBC_ASM_LINE_SEP__ + +#endif /* _BITS_UCLIBC_ARCH_FEATURES_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/wordsize.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/wordsize.h new file mode 100644 index 00000000..dd698fa9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bits/wordsize.h @@ -0,0 +1,19 @@ +/* Copyright (C) 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define __WORDSIZE 64 diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/brk.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/brk.S new file mode 100644 index 00000000..e9974d51 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/brk.S @@ -0,0 +1,52 @@ +/* brk system call for Linux/ia64 + Copyright (C) 1999,2000,2001,2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Written by Stephane Eranian and + Jes Sorensen, , April 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "sysdep.h" + +#include +#include + + .global __curbrk + .hidden __curbrk + .type __curbrk,@object + .size __curbrk,8 + .data + .align 8 +__curbrk: + data8 0 + +weak_alias (__curbrk, ___brk_addr) + +LEAF(brk) + .regstk 1, 0, 0, 0 + DO_CALL(__NR_brk) + cmp.ltu p6, p0 = ret0, in0 + addl r9 = @ltoff(__curbrk), gp + ;; + ld8 r9 = [r9] +(p6) mov ret0 = ENOMEM +(p6) br.cond.spnt.few __syscall_error + ;; + st8 [r9] = ret0 + mov ret0 = 0 + ret +END(brk) +libc_hidden_def(brk) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bsd-_setjmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bsd-_setjmp.S new file mode 100644 index 00000000..4e6a2da5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bsd-_setjmp.S @@ -0,0 +1 @@ +/* _setjmp is in setjmp.S */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bsd-setjmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bsd-setjmp.S new file mode 100644 index 00000000..1da848d2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/bsd-setjmp.S @@ -0,0 +1 @@ +/* setjmp is in setjmp.S */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/clone2.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/clone2.S new file mode 100644 index 00000000..7f067dff --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/clone2.S @@ -0,0 +1,107 @@ +/* Copyright (C) 2000, 2001, 2003, 2004, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "sysdep.h" + +#include "sysdep.h" +#include + + +/* int __clone2(int (*fn) (void *arg), void *child_stack_base, */ +/* size_t child_stack_size, int flags, void *arg, */ +/* pid_t *parent_tid, void *tls, pid_t *child_tid) */ + +#define CHILD p8 +#define PARENT p9 + +ENTRY(__clone2) + .prologue + alloc r2=ar.pfs,8,1,6,0 + cmp.eq p6,p0=0,in0 + cmp.eq p7,p0=0,in1 + mov r8=EINVAL + mov out0=in3 /* Flags are first syscall argument. */ + mov out1=in1 /* Stack address. */ +(p6) br.cond.spnt.many __syscall_error /* no NULL function pointers */ +(p7) br.cond.spnt.many __syscall_error /* no NULL stack pointers */ + ;; + mov out2=in2 /* Stack size. */ + mov out3=in5 /* Parent TID Pointer */ + mov out4=in7 /* Child TID Pointer */ + mov out5=in6 /* TLS pointer */ + /* + * clone2() is special: the child cannot execute br.ret right + * after the system call returns, because it starts out + * executing on an empty stack. Because of this, we can't use + * the new (lightweight) syscall convention here. Instead, we + * just fall back on always using "break". + * + * Furthermore, since the child starts with an empty stack, we + * need to avoid unwinding past invalid memory. To that end, + * we'll pretend now that __clone2() is the end of the + * call-chain. This is wrong for the parent, but only until + * it returns from clone2() but it's better than the + * alternative. + */ + mov r15=SYS_ify (clone2) + .save rp, r0 + break __BREAK_SYSCALL + .body + cmp.eq p6,p0=-1,r10 + cmp.eq CHILD,PARENT=0,r8 /* Are we the child? */ +(p6) br.cond.spnt.many __syscall_error + ;; +(CHILD) mov loc0=gp +(PARENT) ret + ;; +#ifdef RESET_PID + tbit.nz p6,p0=in3,16 /* CLONE_THREAD */ + tbit.z p7,p10=in3,8 /* CLONE_VM */ +(p6) br.cond.dptk 1f + ;; + mov r15=SYS_ify (getpid) +(p10) addl r8=-1,r0 +(p7) break __BREAK_SYSCALL + ;; + add r9=PID,r13 + add r10=TID,r13 + ;; + st4 [r9]=r8 + st4 [r10]=r8 + ;; +#endif +1: ld8 out1=[in0],8 /* Retrieve code pointer. */ + mov out0=in4 /* Pass proper argument to fn */ + ;; + ld8 gp=[in0] /* Load function gp. */ + mov b6=out1 + br.call.dptk.many rp=b6 /* Call fn(arg) in the child */ + ;; + mov out0=r8 /* Argument to _exit */ + mov gp=loc0 + .globl HIDDEN_JUMPTARGET(_exit) + br.call.dpnt.many rp=HIDDEN_JUMPTARGET(_exit) + /* call _exit with result from fn. */ + ret /* Not reached. */ +PSEUDO_END(__clone2) + +/* For now we leave __clone undefined. This is unlikely to be a */ +/* problem, since at least the i386 __clone in glibc always failed */ +/* with a 0 sp (eventhough the kernel explicitly handled it). */ +/* Thus all such calls needed to pass an explicit sp, and as a result, */ +/* would be unlikely to work on ia64. */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/crt1.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/crt1.S new file mode 100644 index 00000000..774e84ff --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/crt1.S @@ -0,0 +1,129 @@ +/* Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Written by Jes Sorensen, , April 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file with other + programs, and to distribute those programs without any restriction + coming from the use of this file. (The GNU Lesser General Public + License restrictions do apply in other respects; for example, they + cover modification of the file, and distribution when not linked + into another program.) + + Note that people who make modified versions of this file are not + obligated to grant this special exception for their modified + versions; it is their choice whether to do so. The GNU Lesser + General Public License gives permission to release a modified + version without this exception; this exception also makes it + possible to release a modified version which carries forward this + exception. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define __ASSEMBLY__ +#include "sysdep.h" + +#include +#include + +/* + * Arguments for __uClibc_main: + * out0: main + * out1: argc + * out2: argv + * out3: init + * out4: fini + * out5: rtld_fini + * out6: stack_end + */ + +#if defined(__UCLIBC_CTOR_DTOR__) +.type _init,%function +.type _fini,%function +#else +.weak _init +.weak _fini +#endif + + .align 32 + .global _start + + .proc _start + .type _start,@function +_start: + .prologue + .save rp, r0 + .body + .prologue + { .mlx + alloc r2 = ar.pfs,0,0,7,0 + movl r3 = FPSR_DEFAULT + } + { .mlx + adds out2 = 16, sp /* get address of argc value */ + movl gp = @gprel(0f) + ;; + } +0: { .mmi + ld8 out1 = [out2], 8 /* load argc and move out2 to become argv */ + mov.m r10 = ar.bsp /* fetch rbs base address */ + mov r9 = ip + ;; + } + { .mii + mov ar.fpsr = r3 + sub gp = r9, gp /* back-compute gp value */ + adds out6 = 16, sp /* highest non-environment stack address */ + ;; + } + { + addl r11 = @ltoff(__libc_ia64_register_backing_store_base), gp + addl out0 = @ltoff(@fptr(main)), gp + addl out3 = @ltoff(@fptr(_init)), gp + ;; + } + { .mmi + ld8 r3 = [r11] /* pointer to __libc_ia64_register_backing_store_base */ + ld8 out0 = [out0] /* pointer to `main' function descriptor */ + addl out4 = @ltoff(@fptr(_fini)), gp + ;; + } + { .mmi + ld8 out3 = [out3] /* pointer to `init' function descriptor */ + ld8 out4 = [out4] /* pointer to `fini' function descriptor */ + nop 0 + } + .body + { .mib + st8 [r3] = r10 + mov out5 = ret0 /* dynamic linker destructor */ + br.call.sptk.few rp = __uClibc_main + } + { .mib + break 0 /* break miserably if we ever return */ + } + .endp _start + +/* Define a symbol for the first piece of initialized data. */ + .data + .globl __data_start +__data_start: + .long 0 + .weak data_start + data_start = __data_start + + .common __libc_ia64_register_backing_store_base, 8, 8 diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/crti.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/crti.S new file mode 100644 index 00000000..c22bbf19 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/crti.S @@ -0,0 +1,36 @@ +/* glibc's sysdeps/ia64/elf/initfini.c used for reference [PROLOG] */ + + .text + .section .init + .global _init# + .proc _init# +_init: + .prologue + .save ar.pfs, r34 + alloc r34 = ar.pfs, 0, 3, 0, 0 + .vframe r32 + mov r32 = r12 + .save rp, r33 + mov r33 = b0 + .body + adds r12 = -16, r12 + ;; + .endp _init# + + + + .section .fini + .global _fini# + .proc _fini# +_fini: + .prologue + .save ar.pfs, r34 + alloc r34 = ar.pfs, 0, 3, 0, 0 + .vframe r32 + mov r32 = r12 + .save rp, r33 + mov r33 = b0 + .body + adds r12 = -16, r12 + ;; + .endp _fini# diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/crtn.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/crtn.S new file mode 100644 index 00000000..5403446b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/crtn.S @@ -0,0 +1,33 @@ +/* glibc's sysdeps/ia64/elf/initfini.c used for reference [EPILOG] */ + + .text + .section .init + .proc _init# +_init: + .prologue + .save ar.pfs, r34 + .vframe r32 + .save rp, r33 + .body + .regstk 0,2,0,0 + mov r12 = r32 + mov ar.pfs = r34 + mov b0 = r33 + br.ret.sptk.many b0 + .endp _init# + + + + .section .fini + .proc _fini# +_fini: + .prologue + .save ar.pfs, r34 + .vframe r32 + .save rp, r33 + .body + mov r12 = r32 + mov ar.pfs = r34 + mov b0 = r33 + br.ret.sptk.many b0 + .endp _fini# diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/fork.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/fork.S new file mode 100644 index 00000000..c657453f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/fork.S @@ -0,0 +1,42 @@ +/* Copyright (C) 2000, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + + +#include "sysdep.h" +#define _SIGNAL_H +#include + +/* pid_t fork(void); */ +/* Implemented as a clone system call with parameters SIGCHLD and 0 */ + +ENTRY(__libc_fork) + alloc r2=ar.pfs,0,0,2,0 + mov out0=SIGCHLD /* Return SIGCHLD when child finishes */ + /* no other clone flags; nothing shared */ + mov out1=0 /* Standard sp value. */ + ;; + DO_CALL (SYS_ify (clone)) + cmp.eq p6,p0=-1,r10 +(p6) br.cond.spnt.few __syscall_error + ret +PSEUDO_END(__libc_fork) + +weak_alias (__libc_fork, __fork) +libc_hidden_def (__fork) +weak_alias (__libc_fork, fork) +libc_hidden_weak (fork) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/pipe.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/pipe.S new file mode 100644 index 00000000..2bfa8a71 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/pipe.S @@ -0,0 +1,37 @@ +/* Copyright (C) 1999, 2000, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by David Mosberger + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* __pipe is a special syscall since it returns two values. */ + +#include "sysdep.h" + +ENTRY(pipe) + .regstk 1,0,0,0 + DO_CALL (SYS_ify (pipe)) + cmp.ne p6,p0=-1,r10 + ;; +(p6) st4 [in0]=r8,4 +(p6) mov ret0=0 + ;; +(p6) st4 [in0]=r9 +(p6) ret + br.cond.spnt.few __syscall_error +PSEUDO_END(pipe) + +libc_hidden_def (pipe) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/setjmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/setjmp.S new file mode 100644 index 00000000..cf6c75d3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/setjmp.S @@ -0,0 +1,189 @@ +/* Copyright (C) 1999, 2000, 2001, 2002, 2004, 2005 + Free Software Foundation, Inc. + Contributed by David Mosberger-Tang . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. + + The layout of the jmp_buf is as follows. This is subject to change + and user-code should never depend on the particular layout of + jmp_buf! + + + offset: description: + ------- ------------ + 0x000 stack pointer (r12) ; unchangeable (see _JMPBUF_UNWINDS) + 0x008 r1 (gp) + 0x010 caller's unat + 0x018 fpsr + 0x020 r4 + 0x028 r5 + 0x030 r6 + 0x038 r7 + 0x040 rp (b0) + 0x048 b1 + 0x050 b2 + 0x058 b3 + 0x060 b4 + 0x068 b5 + 0x070 ar.pfs + 0x078 ar.lc + 0x080 pr + 0x088 ar.bsp ; unchangeable (see __longjmp.S) + 0x090 ar.unat + 0x098 &__jmp_buf ; address of the jmpbuf (needed to locate NaT bits in unat) + 0x0a0 f2 + 0x0b0 f3 + 0x0c0 f4 + 0x0d0 f5 + 0x0e0 f16 + 0x0f0 f17 + 0x100 f18 + 0x110 f19 + 0x120 f20 + 0x130 f21 + 0x130 f22 + 0x140 f23 + 0x150 f24 + 0x160 f25 + 0x170 f26 + 0x180 f27 + 0x190 f28 + 0x1a0 f29 + 0x1b0 f30 + 0x1c0 f31 */ + +#include "sysdep.h" +#include + + /* The following two entry points are the traditional entry points: */ + +LEAF(setjmp) + alloc r8=ar.pfs,2,0,0,0 + mov in1=1 + br.cond.sptk.many _GI___sigsetjmp +END(setjmp) + +LEAF(_setjmp) + alloc r8=ar.pfs,2,0,0,0 + mov in1=0 + br.cond.sptk.many _GI___sigsetjmp +END(_setjmp) +libc_hidden_def (_setjmp) + + /* __sigsetjmp(__jmp_buf buf, int savemask) */ + +ENTRY(__sigsetjmp) + .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(2) + alloc loc1=ar.pfs,2,5,2,0 + .save ar.unat, loc2 + mov loc2=ar.unat + ;; + mov r17=ar.fpsr + mov r2=in0 + add r3=8,in0 + ;; +.mem.offset 8,0; st8.spill.nta [r2]=sp,16 /* r12 (sp) */ +.mem.offset 0,0; st8.spill.nta [r3]=gp,16 /* r1 (gp) */ + ;; + st8.nta [r2]=loc2,16 /* save caller's unat */ + st8.nta [r3]=r17,16 /* save fpsr */ + add r8=0xa0,in0 + ;; +.mem.offset 8,0; st8.spill.nta [r2]=r4,16 /* r4 */ +.mem.offset 0,0; st8.spill.nta [r3]=r5,16 /* r5 */ + add r9=0xb0,in0 + ;; + stf.spill.nta [r8]=f2,32 + stf.spill.nta [r9]=f3,32 + mov loc0=rp + .body + ;; + stf.spill.nta [r8]=f4,32 + stf.spill.nta [r9]=f5,32 + mov r17=b1 + ;; + stf.spill.nta [r8]=f16,32 + stf.spill.nta [r9]=f17,32 + mov r18=b2 + ;; + stf.spill.nta [r8]=f18,32 + stf.spill.nta [r9]=f19,32 + mov r19=b3 + ;; + stf.spill.nta [r8]=f20,32 + stf.spill.nta [r9]=f21,32 + mov r20=b4 + ;; + stf.spill.nta [r8]=f22,32 + stf.spill.nta [r9]=f23,32 + mov r21=b5 + ;; + stf.spill.nta [r8]=f24,32 + stf.spill.nta [r9]=f25,32 + mov r22=ar.lc + ;; + stf.spill.nta [r8]=f26,32 + stf.spill.nta [r9]=f27,32 + mov r24=pr + ;; + stf.spill.nta [r8]=f28,32 + stf.spill.nta [r9]=f29,32 + ;; + stf.spill.nta [r8]=f30 + stf.spill.nta [r9]=f31 + +.mem.offset 8,0; st8.spill.nta [r2]=r6,16 /* r6 */ +.mem.offset 0,0; st8.spill.nta [r3]=r7,16 /* r7 */ + ;; + mov r23=ar.bsp + mov r25=ar.unat + mov out0=in0 + + st8.nta [r2]=loc0,16 /* b0 */ + st8.nta [r3]=r17,16 /* b1 */ + mov out1=in1 + ;; + st8.nta [r2]=r18,16 /* b2 */ + st8.nta [r3]=r19,16 /* b3 */ + ;; + st8.nta [r2]=r20,16 /* b4 */ + st8.nta [r3]=r21,16 /* b5 */ + ;; + st8.nta [r2]=loc1,16 /* ar.pfs */ + st8.nta [r3]=r22,16 /* ar.lc */ + ;; + st8.nta [r2]=r24,16 /* pr */ + st8.nta [r3]=r23,16 /* ar.bsp */ + ;; + st8.nta [r2]=r25 /* ar.unat */ + st8.nta [r3]=in0 /* &__jmp_buf */ +#if defined NOT_IN_libc && defined IS_IN_rtld + /* In ld.so we never save the signal mask. */ + ;; +#else + br.call.dpnt.few rp=__sigjmp_save +#endif +.ret0: /* force a new bundle ::q */ + mov.m ar.unat=loc2 /* restore caller's unat */ + mov rp=loc0 + mov ar.pfs=loc1 + mov r8=0 + ret +END(__sigsetjmp) +strong_alias(__sigsetjmp, _GI___sigsetjmp) + +weak_extern(_setjmp) +weak_extern(setjmp) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/sys/io.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/sys/io.h new file mode 100644 index 00000000..cdd60919 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/sys/io.h @@ -0,0 +1,69 @@ +/* Copyright (C) 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by David Mosberger-Tang + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_IO_H +#define _SYS_IO_H 1 + +#include + +__BEGIN_DECLS + +/* If TURN_ON is TRUE, request for permission to do direct i/o on the + port numbers in the range [FROM,FROM+NUM-1]. Otherwise, turn I/O + permission off for that range. This call requires root privileges. + + Portability note: not all Linux platforms support this call. Most + platforms based on the PC I/O architecture probably will, however. + E.g., Linux/Alpha for Alpha PCs supports this. */ +extern int ioperm (unsigned long int __from, unsigned long int __num, + int __turn_on); +libc_hidden_proto(ioperm) + +/* Set the I/O privilege level to LEVEL. If LEVEL>3, permission to + access any I/O port is granted. This call requires root + privileges. */ +extern int iopl (int __level); + +extern unsigned int _inb (unsigned long int __port); +extern unsigned int _inb (unsigned long int __port); +extern unsigned int _inw (unsigned long int __port); +extern unsigned int _inl (unsigned long int __port); +extern void _outb (unsigned char __val, unsigned long int __port); +extern void _outw (unsigned short __val, unsigned long int __port); +extern void _outl (unsigned int __val, unsigned long int __port); + +#define inb _inb +#define inw _inw +#define inl _inl +#define outb _outb +#define outw _outw +#define outl _outl + +/* Access PCI space protected from machine checks. */ +extern int pciconfig_read (unsigned long int __bus, unsigned long int __dfn, + unsigned long int __off, unsigned long int __len, + unsigned char *__buf); + +extern int pciconfig_write (unsigned long int __bus, unsigned long int __dfn, + unsigned long int __off, unsigned long int __len, + unsigned char *__buf); + +__END_DECLS + +#endif /* _SYS_IO_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/sys/procfs.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/sys/procfs.h new file mode 100644 index 00000000..b5196b99 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/sys/procfs.h @@ -0,0 +1,130 @@ +/* Copyright (C) 1999, 2000, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_PROCFS_H +#define _SYS_PROCFS_H 1 + +/* This is somehow modelled after the file of the same name on SysVr4 + systems. It provides a definition of the core file format for ELF + used on Linux. */ + +#include +#include +#include +#include +#include +#include + +__BEGIN_DECLS + +struct elf_siginfo + { + int si_signo; /* Signal number. */ + int si_code; /* Extra code. */ + int si_errno; /* Errno. */ + }; + +/* We really need just 72 but let's leave some headroom... */ +#define ELF_NGREG 128 +/* f0 and f1 could be omitted, but so what... */ +#define ELF_NFPREG 128 + +typedef unsigned long elf_greg_t; +typedef elf_greg_t elf_gregset_t[ELF_NGREG]; + +typedef struct ia64_fpreg elf_fpreg_t; +typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; + +typedef elf_greg_t greg_t; +typedef elf_gregset_t gregset_t; +typedef elf_fpregset_t fpregset_t; +#define NGREG ELF_NGREG + +/* Definitions to generate Intel SVR4-like core files. These mostly + have the same names as the SVR4 types with "elf_" tacked on the + front to prevent clashes with linux definitions, and the typedef + forms have been avoided. This is mostly like the SVR4 structure, + but more Linuxy, with things that Linux does not support and which + gdb doesn't really use excluded. Fields present but not used are + marked with "XXX". */ +struct elf_prstatus + { +#if 0 + long int pr_flags; /* XXX Process flags. */ + short int pr_why; /* XXX Reason for process halt. */ + short int pr_what; /* XXX More detailed reason. */ +#endif + struct elf_siginfo pr_info; /* Info associated with signal. */ + short int pr_cursig; /* Current signal. */ + unsigned long int pr_sigpend; /* Set of pending signals. */ + unsigned long int pr_sighold; /* Set of held signals. */ +#if 0 + struct sigaltstack pr_altstack; /* Alternate stack info. */ + struct sigaction pr_action; /* Signal action for current sig. */ +#endif + __pid_t pr_pid; + __pid_t pr_ppid; + __pid_t pr_pgrp; + __pid_t pr_sid; + struct timeval pr_utime; /* User time. */ + struct timeval pr_stime; /* System time. */ + struct timeval pr_cutime; /* Cumulative user time. */ + struct timeval pr_cstime; /* Cumulative system time. */ +#if 0 + long int pr_instr; /* Current instruction. */ +#endif + elf_gregset_t pr_reg; /* GP registers. */ + int pr_fpvalid; /* True if math copro being used. */ + }; + + +#define ELF_PRARGSZ (80) /* Number of chars for args */ + +struct elf_prpsinfo + { + char pr_state; /* Numeric process state. */ + char pr_sname; /* Char for pr_state. */ + char pr_zomb; /* Zombie. */ + char pr_nice; /* Nice val. */ + unsigned long int pr_flag; /* Flags. */ + unsigned int pr_uid; + unsigned int pr_gid; + int pr_pid, pr_ppid, pr_pgrp, pr_sid; + /* Lots missing */ + char pr_fname[16]; /* Filename of executable. */ + char pr_psargs[ELF_PRARGSZ]; /* Initial part of arg list. */ + }; + +/* Addresses. */ +typedef void *psaddr_t; + +/* Register sets. Linux has different names. */ +typedef gregset_t prgregset_t; +typedef fpregset_t prfpregset_t; + +/* We don't have any differences between processes and threads, + therefore habe only ine PID type. */ +typedef __pid_t lwpid_t; + + +typedef struct elf_prstatus prstatus_t; +typedef struct elf_prpsinfo prpsinfo_t; + +__END_DECLS + +#endif /* sys/procfs.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/sys/ptrace.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/sys/ptrace.h new file mode 100644 index 00000000..986c4b2d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/sys/ptrace.h @@ -0,0 +1,135 @@ +/* `ptrace' debugger support interface. Linux/ia64 version. + Copyright (C) 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_PTRACE_H +#define _SYS_PTRACE_H 1 + +#include +#include + +__BEGIN_DECLS + +/* Type of the REQUEST argument to `ptrace.' */ +enum __ptrace_request +{ + /* Indicate that the process making this request should be traced. + All signals received by this process can be intercepted by its + parent, and its parent can use the other `ptrace' requests. */ + PTRACE_TRACEME = 0, +#define PT_TRACE_ME PTRACE_TRACEME + + /* Return the word in the process's text space at address ADDR. */ + PTRACE_PEEKTEXT = 1, +#define PT_READ_I PTRACE_PEEKTEXT + + /* Return the word in the process's data space at address ADDR. */ + PTRACE_PEEKDATA = 2, +#define PT_READ_D PTRACE_PEEKDATA + + /* Return the word in the process's user area at offset ADDR. */ + PTRACE_PEEKUSER = 3, +#define PT_READ_U PTRACE_PEEKUSER + + /* Write the word DATA into the process's text space at address ADDR. */ + PTRACE_POKETEXT = 4, +#define PT_WRITE_I PTRACE_POKETEXT + + /* Write the word DATA into the process's data space at address ADDR. */ + PTRACE_POKEDATA = 5, +#define PT_WRITE_D PTRACE_POKEDATA + + /* Write the word DATA into the process's user area at offset ADDR. */ + PTRACE_POKEUSER = 6, +#define PT_WRITE_U PTRACE_POKEUSER + + /* Continue the process. */ + PTRACE_CONT = 7, +#define PT_CONTINUE PTRACE_CONT + + /* Kill the process. */ + PTRACE_KILL = 8, +#define PT_KILL PTRACE_KILL + + /* Single step the process. + This is not supported on all machines. */ + PTRACE_SINGLESTEP = 9, +#define PT_STEP PTRACE_SINGLESTEP + + /* Execute process until next taken branch. */ + PTRACE_SINGLEBLOCK = 12, +#define PT_STEPBLOCK PTRACE_SINGLEBLOCK + + /* Get siginfo for process. */ + PTRACE_GETSIGINFO = 13, +#define PT_GETSIGINFO PTRACE_GETSIGINFO + + /* Set new siginfo for process. */ + PTRACE_SETSIGINFO = 14, +#define PT_GETSIGINFO PTRACE_GETSIGINFO + + /* Attach to a process that is already running. */ + PTRACE_ATTACH = 16, +#define PT_ATTACH PTRACE_ATTACH + + /* Detach from a process attached to with PTRACE_ATTACH. */ + PTRACE_DETACH = 17, +#define PT_DETACH PTRACE_DETACH + + /* Get all registers (pt_all_user_regs) in one shot */ + PTRACE_GETREGS = 18, +#define PT_GETREGS PTRACE_GETREGS + + /* Set all registers (pt_all_user_regs) in one shot */ + PTRACE_SETREGS = 19, +#define PT_SETREGS PTRACE_SETREGS + + /* Continue and stop at the next (return from) syscall. */ + PTRACE_SYSCALL = 24 +#define PT_SYSCALL PTRACE_SYSCALL +}; + +/* pt_all_user_regs is used for PTRACE_GETREGS/PTRACE_SETREGS. */ +struct pt_all_user_regs + { + unsigned long nat; + unsigned long cr_iip; + unsigned long cfm; + unsigned long cr_ipsr; + unsigned long pr; + + unsigned long gr[32]; + unsigned long br[8]; + unsigned long ar[128]; + struct ia64_fpreg fr[128]; + }; + +/* Perform process tracing functions. REQUEST is one of the values + above, and determines the action to be taken. + For all requests except PTRACE_TRACEME, PID specifies the process to be + traced. + + PID and the other arguments described above for the various requests should + appear (those that are used for the particular request) as: + pid_t PID, void *ADDR, int DATA, void *ADDR2 + after REQUEST. */ +extern long int ptrace (enum __ptrace_request __request, ...) __THROW; + +__END_DECLS + +#endif /* _SYS_PTRACE_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/sys/ucontext.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/sys/ucontext.h new file mode 100644 index 00000000..17dc85f9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/sys/ucontext.h @@ -0,0 +1,66 @@ +/* Copyright (C) 1998, 2000, 2001, 2002, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_UCONTEXT_H +#define _SYS_UCONTEXT_H 1 + +#include +#include + +#include + +/* + * These are here mostly for backwards compatibility with older Unices. + * IA-64 Linux does not distinguish between "struct sigcontext" and + * "ucontext_t" as all the necessary info is inside the former. + */ + +typedef struct sigcontext mcontext_t; + +#if defined __cplusplus && __GNUC_PREREQ (3, 5) +# define _SC_GR0_OFFSET \ + __builtin_offsetof (struct sigcontext, sc_gr[0]) +#elif defined __GNUC__ +# define _SC_GR0_OFFSET \ + (((char *) &((struct sigcontext *) 0)->sc_gr[0]) - (char *) 0) +#else +# define _SC_GR0_OFFSET 0xc8 /* pray that this is correct... */ +#endif + +typedef struct ucontext + { + union + { + mcontext_t _mc; + struct + { + unsigned long _pad[_SC_GR0_OFFSET/8]; + struct ucontext *_link; /* this should overlay sc_gr[0] */ + } + _uc; + } + _u; + } +ucontext_t; + +#define uc_mcontext _u._mc +#define uc_sigmask _u._mc.sc_mask +#define uc_stack _u._mc.sc_stack +#define uc_link _u._uc._link + +#endif /* sys/ucontext.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/sys/user.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/sys/user.h new file mode 100644 index 00000000..03921876 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/sys/user.h @@ -0,0 +1,54 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_USER_H +#define _SYS_USER_H 1 + +#include +#include + +/* This definition comes directly from the kernel headers. If + anything changes in them this header has to be changed, too. */ + + +/* The definition in the kernel has the comment "XXX fix me". */ +#define EF_SIZE 3072 + + +struct user +{ + unsigned long int regs[EF_SIZE / 8 + 32]; /* Integer and fp regs. */ + size_t u_tsize; /* Text size (pages). */ + size_t u_dsize; /* Data size (pages). */ + size_t u_ssize; /* Stack size (pages). */ + unsigned long int start_code; /* Text starting address. */ + unsigned long int start_data; /* Data starting address. */ + unsigned long int start_stack; /* Stack starting address. */ + long int signal; /* Signal causing core dump. */ + struct regs *u_ar0; /* Help gdb find registers. */ + unsigned long int magic; /* Identifies a core file. */ + char u_comm[32]; /* User command name. */ +}; + +#define NBPG PAGE_SIZE +#define UPAGES 1 +#define HOST_TEXT_START_ADDR (u.start_code) +#define HOST_DATA_START_ADDR (u.start_data) +#define HOST_STACK_END_ADDR (u.start_stack + u.u_ssize * NBPG) + +#endif /* sys/user.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/syscall.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/syscall.S new file mode 100644 index 00000000..e4ac834c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/syscall.S @@ -0,0 +1,30 @@ +/* Copyright (C) 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jes Sorensen . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "sysdep.h" + +ENTRY(syscall) + alloc r2=ar.pfs,1,0,8,0 + mov r15=r32 /* syscall number */ + break __BREAK_SYSCALL + ;; + cmp.ne p6,p0=-1,r10 /* r10 = -1 on error */ +(p6) ret + br.cond.spnt.few __syscall_error +PSEUDO_END(syscall) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/sysdep.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/sysdep.h new file mode 100644 index 00000000..d10020ac --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/sysdep.h @@ -0,0 +1,168 @@ +/* Copyright (C) 1999, 2000, 2002, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Written by Jes Sorensen, , April 1999. + Based on code originally written by David Mosberger-Tang + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _LINUX_IA64_SYSDEP_H +#define _LINUX_IA64_SYSDEP_H 1 + +#include +#include + +#ifdef __ASSEMBLER__ + +/* Macros to help writing .prologue directives in assembly code. */ +#define ASM_UNW_PRLG_RP 0x8 +#define ASM_UNW_PRLG_PFS 0x4 +#define ASM_UNW_PRLG_PSP 0x2 +#define ASM_UNW_PRLG_PR 0x1 +#define ASM_UNW_PRLG_GRSAVE(ninputs) (32+(ninputs)) + +#ifdef __STDC__ +#define C_LABEL(name) name : +#else +#define C_LABEL(name) name/**/: +#endif + +#define CALL_MCOUNT + +#define ENTRY(name) \ + .text; \ + .align 32; \ + .proc C_SYMBOL_NAME(name); \ + .global C_SYMBOL_NAME(name); \ + C_LABEL(name) \ + CALL_MCOUNT + +#define LEAF(name) \ + .text; \ + .align 32; \ + .proc C_SYMBOL_NAME(name); \ + .global name; \ + C_LABEL(name) + +/* Mark the end of function SYM. */ +#undef END +#define END(sym) .endp C_SYMBOL_NAME(sym) + +/* For Linux we can use the system call table in the header file + /usr/include/asm/unistd.h + of the kernel. But these symbols do not follow the SYS_* syntax + so we have to redefine the `SYS_ify' macro here. */ +#undef SYS_ify +#ifdef __STDC__ +# define SYS_ify(syscall_name) __NR_##syscall_name +#else +# define SYS_ify(syscall_name) __NR_/**/syscall_name +#endif + +/* Linux uses a negative return value to indicate syscall errors, unlike + most Unices, which use the condition codes' carry flag. + + Since version 2.1 the return value of a system call might be negative + even if the call succeeded. E.g., the `lseek' system call might return + a large offset. Therefore we must not anymore test for < 0, but test + for a real error by making sure the value in %d0 is a real error + number. Linus said he will make sure the no syscall returns a value + in -1 .. -4095 as a valid result so we can savely test with -4095. */ + +/* We don't want the label for the error handler to be visible in the symbol + table when we define it here. */ +#define SYSCALL_ERROR_LABEL __syscall_error + +#undef PSEUDO +#define PSEUDO(name, syscall_name, args) \ + ENTRY(name) \ + DO_CALL (SYS_ify(syscall_name)); \ + cmp.eq p6,p0=-1,r10; \ +(p6) br.cond.spnt.few __syscall_error; + +#define DO_CALL_VIA_BREAK(num) \ + mov r15=num; \ + break __BREAK_SYSCALL + +#ifdef IA64_USE_NEW_STUB +# ifdef SHARED +# define DO_CALL(num) \ + .prologue; \ + adds r2 = SYSINFO_OFFSET, r13;; \ + ld8 r2 = [r2]; \ + .save ar.pfs, r11; \ + mov r11 = ar.pfs;; \ + .body; \ + mov r15 = num; \ + mov b7 = r2; \ + br.call.sptk.many b6 = b7;; \ + .restore sp; \ + mov ar.pfs = r11; \ + .prologue; \ + .body +# else /* !SHARED */ +# define DO_CALL(num) \ + .prologue; \ + mov r15 = num; \ + movl r2 = _dl_sysinfo;; \ + ld8 r2 = [r2]; \ + .save ar.pfs, r11; \ + mov r11 = ar.pfs;; \ + .body; \ + mov b7 = r2; \ + br.call.sptk.many b6 = b7;; \ + .restore sp; \ + mov ar.pfs = r11; \ + .prologue; \ + .body +# endif +#else +# define DO_CALL(num) DO_CALL_VIA_BREAK(num) +#endif + +#undef PSEUDO_END +#define PSEUDO_END(name) .endp C_SYMBOL_NAME(name); + +#undef PSEUDO_NOERRNO +#define PSEUDO_NOERRNO(name, syscall_name, args) \ + ENTRY(name) \ + DO_CALL (SYS_ify(syscall_name)); + +#undef PSEUDO_END_NOERRNO +#define PSEUDO_END_NOERRNO(name) .endp C_SYMBOL_NAME(name); + +#undef PSEUDO_ERRVAL +#define PSEUDO_ERRVAL(name, syscall_name, args) \ + ENTRY(name) \ + DO_CALL (SYS_ify(syscall_name)); \ + cmp.eq p6,p0=-1,r10; \ +(p6) mov r10=r8; + + +#undef PSEUDO_END_ERRVAL +#define PSEUDO_END_ERRVAL(name) .endp C_SYMBOL_NAME(name); + +#undef END +#define END(name) \ + .size C_SYMBOL_NAME(name), . - C_SYMBOL_NAME(name) ; \ + .endp C_SYMBOL_NAME(name) + +#define ret br.ret.sptk.few b0 +#define ret_NOERRNO ret +#define ret_ERRVAL ret + +#endif /* not __ASSEMBLER__ */ + +#endif /* linux/ia64/sysdep.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/vfork.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/vfork.S new file mode 100644 index 00000000..f233b05e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/ia64/vfork.S @@ -0,0 +1,44 @@ +/* Copyright (C) 2000, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + + +#include "sysdep.h" +#define _SIGNAL_H +#include + +/* The following are defined in linux/sched.h, which unfortunately */ +/* is not safe for inclusion in an assembly file. */ +#define CLONE_VM 0x00000100 /* set if VM shared between processes */ +#define CLONE_VFORK 0x00004000 /* set if the parent wants the child to wake it up on mm_release */ + +/* pid_t vfork(void); */ +/* Implemented as __clone_syscall(CLONE_VFORK | CLONE_VM | SIGCHLD, 0) */ + +ENTRY(__vfork) + alloc r2=ar.pfs,0,0,2,0 + mov out0=CLONE_VM+CLONE_VFORK+SIGCHLD + mov out1=0 /* Standard sp value. */ + ;; + DO_CALL_VIA_BREAK (SYS_ify (clone)) + cmp.eq p6,p0=-1,r10 +(p6) br.cond.spnt.few __syscall_error + ret +PSEUDO_END(__vfork) + +weak_alias(__vfork,vfork) +libc_hidden_weak(vfork) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/Makefile new file mode 100644 index 00000000..633c91f3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../../ +top_builddir=../../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.arch +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/Makefile.arch b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/Makefile.arch new file mode 100644 index 00000000..bde54c5b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/Makefile.arch @@ -0,0 +1,10 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +CSRC := brk.c __syscall_error.c + +SSRC := __longjmp.S bsd-_setjmp.S bsd-setjmp.S clone.S setjmp.S vfork.S diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/README.m68k b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/README.m68k new file mode 100644 index 00000000..a6bb17e4 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/README.m68k @@ -0,0 +1,54 @@ + +README for uC-libc on the m68k[nommu] architecture + +James Graves + +For now (2001/1/9) support for the m68k should be considered "alpha" +quality at best. It mostly works OK for some of the stuff I'm working +on, but you can't fully compile other things (like the user +applications for uClinux). Needs lots more testing. + +Only developed/tested with m68k-pic-coff-gcc 2.7.2.3-pic-060999, from +Lineo. + +Configuration: + + Read and edit the Config file, carefully. + + TARGET_ARCH=m68k + CROSS = m68k-pic-coff- + CC = $(CROSS)gcc + STRIPTOOL = $(CROSS)strip + KERNEL_SOURCE=/opt/uClinux/linux + HAS_MMU = false + HAS_FLOATS = false + MALLOC = malloc-simple + INSTALL_DIR = /opt/uClinux/m68k-pic-coff + + The regular malloc library is broken, dunno why. Use + simple-malloc. + +Installation: + Theoretically, you should be able to install right over the + existing uC-libc 0.9.1 files in + /opt/uClinux/m68k-pic-coff/include, but I recommend cleaning + out all the include files there. + + The only file in there that's not from the old uC-libc is + assert.h, but I don't know why that would be the valid copy. + + run: + make install + +Problems: + + I _may_ be able to help if you run into problems. Create a + really, really short program that demonstrates the problem, + and contact me. + +TODO: + Fix vfork(). + + Does crt0.o still need to be a separate file? Can't I just + stick it in libc.a and be done with it? Is that specified in + the GCC link options? diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/__longjmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/__longjmp.S new file mode 100644 index 00000000..5db9e436 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/__longjmp.S @@ -0,0 +1,26 @@ + +/* Copyright (C) 2002, David McCullough */ +/* This file is released under the LGPL, any version you like */ + +#define _ASM +#define _SETJMP_H +#include +#include + +.globl __longjmp +.type __longjmp,@function +.align 4 +__longjmp: + moveal %sp@(4), %a0 + movel %sp@(8), %d0 + bne 1f + movel #1, %d0 +1: + moveml %a0@(JB_REGS), %d2-%d7/%a2-%a7 +#if defined(__HAVE_68881__) || defined(__HAVE_FPU__) + fmovemx %a0@(JB_FPREGS), %fp2-%fp7 +#endif + movel %a0@(JB_PC), %sp@ + rts + +libc_hidden_def(__longjmp) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/__syscall_error.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/__syscall_error.c new file mode 100644 index 00000000..a29f6ffd --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/__syscall_error.c @@ -0,0 +1,19 @@ +/* Wrapper for setting errno. + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +/* This routine is jumped to by all the syscall handlers, to stash + * an error number into errno. */ +int __syscall_error(void) attribute_hidden; +int __syscall_error(void) +{ + register int err_no __asm__("%d0"); + __set_errno(-err_no); + return -1; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/bits/byteswap.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/bits/byteswap.h new file mode 100644 index 00000000..48847421 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/bits/byteswap.h @@ -0,0 +1,37 @@ +/* Macros to swap the order of bytes in integer values. m68k version. + Copyright (C) 1997, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _ASM_BITS_BYTESWAP_H +#define _ASM_BITS_BYTESWAP_H 1 + +#if !defined __mcoldfire__ +# define __bswap_non_constant_32(x) \ + __extension__ \ + ({ unsigned int __bswap_32_v; \ + __asm__ __volatile__ ("ror%.w %#8, %0;" \ + "swap %0;" \ + "ror%.w %#8, %0" \ + : "=d" (__bswap_32_v) \ + : "0" ((unsigned int) (x))); \ + __bswap_32_v; }) +#endif + +#endif + +#include diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/bits/endian.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/bits/endian.h new file mode 100644 index 00000000..bf4ecb60 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/bits/endian.h @@ -0,0 +1,7 @@ +/* m68k is big-endian. */ + +#ifndef _ENDIAN_H +# error "Never use directly; include instead." +#endif + +#define __BYTE_ORDER __BIG_ENDIAN diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/bits/fcntl.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/bits/fcntl.h new file mode 100644 index 00000000..e564b421 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/bits/fcntl.h @@ -0,0 +1,238 @@ +/* O_*, F_*, FD_* bit values for Linux. + Copyright (C) 2000, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FCNTL_H +# error "Never use directly; include instead." +#endif + + +#include +#ifdef __USE_GNU +# include +#endif + +/* open/fcntl - O_SYNC is only implemented on blocks devices and on files + located on an ext2 file system */ +#define O_ACCMODE 0003 +#define O_RDONLY 00 +#define O_WRONLY 01 +#define O_RDWR 02 +#define O_CREAT 0100 /* not fcntl */ +#define O_EXCL 0200 /* not fcntl */ +#define O_NOCTTY 0400 /* not fcntl */ +#define O_TRUNC 01000 /* not fcntl */ +#define O_APPEND 02000 +#define O_NONBLOCK 04000 +#define O_NDELAY O_NONBLOCK +#define O_SYNC 010000 +#define O_FSYNC O_SYNC +#define O_ASYNC 020000 + +#ifdef __USE_GNU +# define O_DIRECTORY 040000 /* Must be a directory. */ +# define O_NOFOLLOW 0100000 /* Do not follow links. */ +# define O_DIRECT 0200000 /* Direct disk access. */ +# define O_NOATIME 01000000 /* Do not set atime. */ +# define O_CLOEXEC 02000000 /* set close_on_exec */ +#endif + +/* For now Linux has synchronisity options for data and read operations. + We define the symbols here but let them do the same as O_SYNC since + this is a superset. */ +#if defined __USE_POSIX199309 || defined __USE_UNIX98 +# define O_DSYNC O_SYNC /* Synchronize data. */ +# define O_RSYNC O_SYNC /* Synchronize read operations. */ +#endif + +#ifdef __USE_LARGEFILE64 +# define O_LARGEFILE 0400000 +#endif + +/* Values for the second argument to `fcntl'. */ +#define F_DUPFD 0 /* Duplicate file descriptor. */ +#define F_GETFD 1 /* Get file descriptor flags. */ +#define F_SETFD 2 /* Set file descriptor flags. */ +#define F_GETFL 3 /* Get file status flags. */ +#define F_SETFL 4 /* Set file status flags. */ +#ifndef __USE_FILE_OFFSET64 +# define F_GETLK 5 /* Get record locking info. */ +# define F_SETLK 6 /* Set record locking info (non-blocking). */ +# define F_SETLKW 7 /* Set record locking info (blocking). */ +#else +# define F_GETLK F_GETLK64 /* Get record locking info. */ +# define F_SETLK F_SETLK64 /* Set record locking info (non-blocking).*/ +# define F_SETLKW F_SETLKW64 /* Set record locking info (blocking). */ +#endif +#define F_GETLK64 12 /* Get record locking info. */ +#define F_SETLK64 13 /* Set record locking info (non-blocking). */ +#define F_SETLKW64 14 /* Set record locking info (blocking). */ + +#if defined __USE_BSD || defined __USE_UNIX98 +# define F_SETOWN 8 /* Get owner of socket (receiver of SIGIO). */ +# define F_GETOWN 9 /* Set owner of socket (receiver of SIGIO). */ +#endif + +#ifdef __USE_GNU +# define F_SETSIG 10 /* Set number of signal to be sent. */ +# define F_GETSIG 11 /* Get number of signal to be sent. */ +#endif + +#ifdef __USE_GNU +# define F_SETLEASE 1024 /* Set a lease. */ +# define F_GETLEASE 1025 /* Enquire what lease is active. */ +# define F_NOTIFY 1026 /* Request notfications on a directory. */ +# define F_DUPFD_CLOEXEC 1030 /* Duplicate file descriptor with + close-on-exit set on new fd. */ +#endif + +/* For F_[GET|SET]FL. */ +#define FD_CLOEXEC 1 /* actually anything with low bit set goes */ + +/* For posix fcntl() and `l_type' field of a `struct flock' for lockf(). */ +#define F_RDLCK 0 /* Read lock. */ +#define F_WRLCK 1 /* Write lock. */ +#define F_UNLCK 2 /* Remove lock. */ + +/* For old implementation of bsd flock(). */ +#define F_EXLCK 4 /* or 3 */ +#define F_SHLCK 8 /* or 4 */ + +#ifdef __USE_BSD +/* Operations for bsd flock(), also used by the kernel implementation. */ +# define LOCK_SH 1 /* shared lock */ +# define LOCK_EX 2 /* exclusive lock */ +# define LOCK_NB 4 /* or'd with one of the above to prevent + blocking */ +# define LOCK_UN 8 /* remove lock */ +#endif + +#ifdef __USE_GNU +# define LOCK_MAND 32 /* This is a mandatory flock: */ +# define LOCK_READ 64 /* ... which allows concurrent read operations. */ +# define LOCK_WRITE 128 /* ... which allows concurrent write operations. */ +# define LOCK_RW 192 /* ... Which allows concurrent read & write operations. */ +#endif + +#ifdef __USE_GNU +/* Types of directory notifications that may be requested with F_NOTIFY. */ +# define DN_ACCESS 0x00000001 /* File accessed. */ +# define DN_MODIFY 0x00000002 /* File modified. */ +# define DN_CREATE 0x00000004 /* File created. */ +# define DN_DELETE 0x00000008 /* File removed. */ +# define DN_RENAME 0x00000010 /* File renamed. */ +# define DN_ATTRIB 0x00000020 /* File changed attibutes. */ +# define DN_MULTISHOT 0x80000000 /* Don't remove notifier. */ +#endif + +struct flock + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ +#ifndef __USE_FILE_OFFSET64 + __off_t l_start; /* Offset where the lock begins. */ + __off_t l_len; /* Size of the locked area; zero means until EOF. */ +#else + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ +#endif + __pid_t l_pid; /* Process holding the lock. */ + }; + +#ifdef __USE_LARGEFILE64 +struct flock64 + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ + __pid_t l_pid; /* Process holding the lock. */ + }; +#endif + +/* Define some more compatibility macros to be backward compatible with + BSD systems which did not managed to hide these kernel macros. */ +#ifdef __USE_BSD +# define FAPPEND O_APPEND +# define FFSYNC O_FSYNC +# define FASYNC O_ASYNC +# define FNONBLOCK O_NONBLOCK +# define FNDELAY O_NDELAY +#endif /* Use BSD. */ + +/* Advise to `posix_fadvise'. */ +#ifdef __USE_XOPEN2K +# define POSIX_FADV_NORMAL 0 /* No further special treatment. */ +# define POSIX_FADV_RANDOM 1 /* Expect random page references. */ +# define POSIX_FADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define POSIX_FADV_WILLNEED 3 /* Will need these pages. */ +# define POSIX_FADV_DONTNEED 4 /* Don't need these pages. */ +# define POSIX_FADV_NOREUSE 5 /* Data will be accessed once. */ +#endif + + +#if defined __USE_GNU && defined __UCLIBC_LINUX_SPECIFIC__ +/* Flags for SYNC_FILE_RANGE. */ +# define SYNC_FILE_RANGE_WAIT_BEFORE 1 /* Wait upon writeout of all pages + in the range before performing the + write. */ +# define SYNC_FILE_RANGE_WRITE 2 /* Initiate writeout of all those + dirty pages in the range which are + not presently under writeback. */ +# define SYNC_FILE_RANGE_WAIT_AFTER 4 /* Wait upon writeout of all pages in + the range after performing the + write. */ + +/* Flags for SPLICE and VMSPLICE. */ +# define SPLICE_F_MOVE 1 /* Move pages instead of copying. */ +# define SPLICE_F_NONBLOCK 2 /* Don't block on the pipe splicing + (but we may still block on the fd + we splice from/to). */ +# define SPLICE_F_MORE 4 /* Expect more data. */ +# define SPLICE_F_GIFT 8 /* Pages passed in are a gift. */ +#endif + +__BEGIN_DECLS + +#if defined __USE_GNU && defined __UCLIBC_LINUX_SPECIFIC__ + +/* Provide kernel hint to read ahead. */ +extern ssize_t readahead (int __fd, __off64_t __offset, size_t __count) + __THROW; + + +/* Selective file content synch'ing. */ +extern int sync_file_range (int __fd, __off64_t __from, __off64_t __to, + unsigned int __flags); + +/* Splice address range into a pipe. */ +extern ssize_t vmsplice (int __fdout, const struct iovec *__iov, + size_t __count, unsigned int __flags); + +/* Splice two files together. */ +extern ssize_t splice (int __fdin, __off64_t *__offin, int __fdout, + __off64_t *__offout, size_t __len, + unsigned int __flags); + +/* In-kernel implementation of tee for pipe buffers. */ +extern ssize_t tee (int __fdin, int __fdout, size_t __len, + unsigned int __flags); + +#endif +__END_DECLS + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/bits/fenv.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/bits/fenv.h new file mode 100644 index 00000000..7c0bcb66 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/bits/fenv.h @@ -0,0 +1,79 @@ +/* Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FENV_H +# error "Never use directly; include instead." +#endif + + +/* Define bits representing the exception. We use the bit positions of + the appropriate bits in the FPSR Accrued Exception Byte. */ +enum + { + FE_INEXACT = 1 << 3, +#define FE_INEXACT FE_INEXACT + FE_DIVBYZERO = 1 << 4, +#define FE_DIVBYZERO FE_DIVBYZERO + FE_UNDERFLOW = 1 << 5, +#define FE_UNDERFLOW FE_UNDERFLOW + FE_OVERFLOW = 1 << 6, +#define FE_OVERFLOW FE_OVERFLOW + FE_INVALID = 1 << 7 +#define FE_INVALID FE_INVALID + }; + +#define FE_ALL_EXCEPT \ + (FE_INEXACT | FE_DIVBYZERO | FE_UNDERFLOW | FE_OVERFLOW | FE_INVALID) + +/* The m68k FPU supports all of the four defined rounding modes. We use + the bit positions in the FPCR Mode Control Byte as the values for the + appropriate macros. */ +enum + { + FE_TONEAREST = 0, +#define FE_TONEAREST FE_TONEAREST + FE_TOWARDZERO = 1 << 4, +#define FE_TOWARDZERO FE_TOWARDZERO + FE_DOWNWARD = 2 << 4, +#define FE_DOWNWARD FE_DOWNWARD + FE_UPWARD = 3 << 4 +#define FE_UPWARD FE_UPWARD + }; + + +/* Type representing exception flags. */ +typedef unsigned int fexcept_t; + + +/* Type representing floating-point environment. This structure + corresponds to the layout of the block written by `fmovem'. */ +typedef struct + { + unsigned int __control_register; + unsigned int __status_register; + unsigned int __instruction_address; + } +fenv_t; + +/* If the default argument is used we use this value. */ +#define FE_DFL_ENV ((__const fenv_t *) -1) + +#ifdef __USE_GNU +/* Floating-point environment where none of the exceptions are masked. */ +# define FE_NOMASK_ENV ((__const fenv_t *) -2) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/bits/kernel_stat.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/bits/kernel_stat.h new file mode 100644 index 00000000..4cb06cc9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/bits/kernel_stat.h @@ -0,0 +1,56 @@ +#ifndef _BITS_STAT_STRUCT_H +#define _BITS_STAT_STRUCT_H + +#ifndef _LIBC +#error bits/kernel_stat.h is for internal uClibc use only! +#endif + +/* This file provides whatever this particular arch's kernel thinks + * struct kernel_stat should look like... It turns out each arch has a + * different opinion on the subject... */ + +struct kernel_stat { + unsigned short st_dev; + unsigned short __pad1; + unsigned long st_ino; + unsigned short st_mode; + unsigned short st_nlink; + unsigned short st_uid; + unsigned short st_gid; + unsigned short st_rdev; + unsigned short __pad2; + unsigned long st_size; + unsigned long st_blksize; + unsigned long st_blocks; + struct timespec st_atim; + struct timespec st_mtim; + struct timespec st_ctim; + unsigned long __unused4; + unsigned long __unused5; +}; + +struct kernel_stat64 { + unsigned char __pad0[6]; + unsigned short st_dev; + unsigned char __pad1[2]; +#define _HAVE_STAT64___ST_INO + unsigned long __st_ino; + unsigned int st_mode; + unsigned int st_nlink; + unsigned long st_uid; + unsigned long st_gid; + unsigned char __pad2[6]; + unsigned short st_rdev; + unsigned char __pad3[2]; + long long st_size; + unsigned long st_blksize; + unsigned long __pad4; /* future possible st_blocks high bits */ + unsigned long st_blocks; /* Number 512-byte blocks allocated. */ + struct timespec st_atim; + struct timespec st_mtim; + struct timespec st_ctim; + unsigned long long st_ino; +}; + +#endif /* _BITS_STAT_STRUCT_H */ + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/bits/kernel_types.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/bits/kernel_types.h new file mode 100644 index 00000000..0a77a8f4 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/bits/kernel_types.h @@ -0,0 +1,44 @@ +/* Note that we use the exact same include guard #define names + * as asm/posix_types.h. This will avoid gratuitous conflicts + * with the posix_types.h kernel header, and will ensure that + * our private content, and not the kernel header, will win. + * -Erik + */ +#ifndef __ARCH_M68K_POSIX_TYPES_H +#define __ARCH_M68K_POSIX_TYPES_H + +typedef unsigned short __kernel_dev_t; +typedef unsigned long __kernel_ino_t; +typedef unsigned short __kernel_mode_t; +typedef unsigned short __kernel_nlink_t; +typedef long __kernel_off_t; +typedef int __kernel_pid_t; +typedef unsigned short __kernel_ipc_pid_t; +typedef unsigned short __kernel_uid_t; +typedef unsigned short __kernel_gid_t; +typedef unsigned int __kernel_size_t; +typedef int __kernel_ssize_t; +typedef int __kernel_ptrdiff_t; +typedef long __kernel_time_t; +typedef long __kernel_suseconds_t; +typedef long __kernel_clock_t; +typedef int __kernel_daddr_t; +typedef char * __kernel_caddr_t; +typedef unsigned short __kernel_uid16_t; +typedef unsigned short __kernel_gid16_t; +typedef unsigned int __kernel_uid32_t; +typedef unsigned int __kernel_gid32_t; +typedef unsigned short __kernel_old_uid_t; +typedef unsigned short __kernel_old_gid_t; +typedef long long __kernel_loff_t; +typedef __kernel_dev_t __kernel_old_dev_t; + +typedef struct { +#ifdef __USE_ALL + int val[2]; +#else + int __val[2]; +#endif +} __kernel_fsid_t; + +#endif /* __ARCH_M68K_POSIX_TYPES_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/bits/mathdef.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/bits/mathdef.h new file mode 100644 index 00000000..a69e9308 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/bits/mathdef.h @@ -0,0 +1,42 @@ +/* Copyright (C) 1997, 1998, 1999, 2000, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#if !defined _MATH_H && !defined _COMPLEX_H +# error "Never use directly; include instead" +#endif + +#if defined __USE_ISOC99 && defined _MATH_H && !defined _MATH_H_MATHDEF +# define _MATH_H_MATHDEF 1 + +/* The m68k FPUs evaluate all values in the 96 bit floating-point format + which is also available for the user as `long double'. Therefore we + define: */ +typedef long double float_t; /* `float' expressions are evaluated as + `long double'. */ +typedef long double double_t; /* `double' expressions are evaluated as + `long double'. */ + +/* The values returned by `ilogb' for 0 and NaN respectively. */ +# define FP_ILOGB0 (-2147483647 - 1) +# define FP_ILOGBNAN (2147483647) + +#endif /* ISO C99 */ + +#if !defined __NO_LONG_DOUBLE_MATH && !defined __UCLIBC_HAS_LONG_DOUBLE_MATH__ +# define __NO_LONG_DOUBLE_MATH 1 +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/bits/mathinline.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/bits/mathinline.h new file mode 100644 index 00000000..f3166000 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/bits/mathinline.h @@ -0,0 +1,445 @@ +/* Definitions of inline math functions implemented by the m68881/2. + Copyright (C) 1991,92,93,94,96,97,98,99,2000,2002, 2003, 2004 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifdef __GNUC__ + +#ifdef __USE_ISOC99 +/* GCC 3.1 and up have builtins that actually can be used. */ +# if !__GNUC_PREREQ (3,1) +/* ISO C99 defines some macros to perform unordered comparisons. The + m68k FPU supports this with special opcodes and we should use them. + These must not be inline functions since we have to be able to handle + all floating-point types. */ +# undef isgreater +# undef isgreaterequal +# undef isless +# undef islessequal +# undef islessgreater +# undef isunordered +# define isgreater(x, y) \ + __extension__ \ + ({ char __result; \ + __asm__ ("fcmp%.x %2,%1; fsogt %0" \ + : "=dm" (__result) : "f" (x), "f" (y)); \ + __result != 0; }) + +# define isgreaterequal(x, y) \ + __extension__ \ + ({ char __result; \ + __asm__ ("fcmp%.x %2,%1; fsoge %0" \ + : "=dm" (__result) : "f" (x), "f" (y)); \ + __result != 0; }) + +# define isless(x, y) \ + __extension__ \ + ({ char __result; \ + __asm__ ("fcmp%.x %2,%1; fsolt %0" \ + : "=dm" (__result) : "f" (x), "f" (y)); \ + __result != 0; }) + +# define islessequal(x, y) \ + __extension__ \ + ({ char __result; \ + __asm__ ("fcmp%.x %2,%1; fsole %0" \ + : "=dm" (__result) : "f" (x), "f" (y)); \ + __result != 0; }) + +# define islessgreater(x, y) \ + __extension__ \ + ({ char __result; \ + __asm__ ("fcmp%.x %2,%1; fsogl %0" \ + : "=dm" (__result) : "f" (x), "f" (y)); \ + __result != 0; }) + +# define isunordered(x, y) \ + __extension__ \ + ({ char __result; \ + __asm__ ("fcmp%.x %2,%1; fsun %0" \ + : "=dm" (__result) : "f" (x), "f" (y)); \ + __result != 0; }) +# endif /* GCC 3.1 */ +#endif + + +#if (!defined __NO_MATH_INLINES && defined __OPTIMIZE__) \ + || defined __LIBC_INTERNAL_MATH_INLINES + +#ifdef __LIBC_INTERNAL_MATH_INLINES +/* This is used when defining the functions themselves. Define them with + __ names, and with `static inline' instead of `extern inline' so the + bodies will always be used, never an external function call. */ +# define __m81_u(x) __CONCAT(__,x) +# define __m81_inline static __inline +#else +# define __m81_u(x) x +# ifdef __cplusplus +# define __m81_inline __inline +# else +# define __m81_inline extern __inline +# endif +# define __M81_MATH_INLINES 1 +#endif + +/* Define a const math function. */ +#define __m81_defun(rettype, func, args) \ + __m81_inline rettype __attribute__((__const__)) \ + __m81_u(func) args + +/* Define the three variants of a math function that has a direct + implementation in the m68k fpu. FUNC is the name for C (which will be + suffixed with f and l for the float and long double version, resp). OP + is the name of the fpu operation (without leading f). */ + +#if defined __USE_MISC || defined __USE_ISOC99 +# define __inline_mathop(func, op) \ + __inline_mathop1(double, func, op) \ + __inline_mathop1(float, __CONCAT(func,f), op) \ + __inline_mathop1(long double, __CONCAT(func,l), op) +#else +# define __inline_mathop(func, op) \ + __inline_mathop1(double, func, op) +#endif + +#define __inline_mathop1(float_type,func, op) \ + __m81_defun (float_type, func, (float_type __mathop_x)) \ + { \ + float_type __result; \ + __asm__("f" __STRING(op) "%.x %1, %0" : "=f" (__result) : "f" (__mathop_x));\ + return __result; \ + } + +__inline_mathop(__atan, atan) +__inline_mathop(__cos, cos) +__inline_mathop(__sin, sin) +__inline_mathop(__tan, tan) +__inline_mathop(__tanh, tanh) +__inline_mathop(__fabs, abs) + +#if defined __USE_MISC || defined __USE_XOPEN_EXTENDED || defined __USE_ISOC99 +__inline_mathop(__rint, int) +__inline_mathop(__expm1, etoxm1) +__inline_mathop(__log1p, lognp1) +#endif + +#ifdef __USE_MISC +__inline_mathop(__significand, getman) +#endif + +#ifdef __USE_ISOC99 +__inline_mathop(__trunc, intrz) +#endif + +#if !defined __NO_MATH_INLINES && defined __OPTIMIZE__ + +__inline_mathop(atan, atan) +__inline_mathop(cos, cos) +__inline_mathop(sin, sin) +__inline_mathop(tan, tan) +__inline_mathop(tanh, tanh) + +# if defined __USE_MISC || defined __USE_XOPEN_EXTENDED || defined __USE_ISOC99 +__inline_mathop(rint, int) +__inline_mathop(expm1, etoxm1) +__inline_mathop(log1p, lognp1) +# endif + +# ifdef __USE_MISC +__inline_mathop(significand, getman) +# endif + +# ifdef __USE_ISOC99 +__inline_mathop(trunc, intrz) +# endif + +#endif /* !__NO_MATH_INLINES && __OPTIMIZE__ */ + +/* This macro contains the definition for the rest of the inline + functions, using FLOAT_TYPE as the domain type and S as the suffix + for the function names. */ + +#define __inline_functions(float_type, s) \ +__m81_defun (float_type, __CONCAT(__floor,s), (float_type __x)) \ +{ \ + float_type __result; \ + unsigned long int __ctrl_reg; \ + __asm__ __volatile__ ("fmove%.l %!, %0" : "=dm" (__ctrl_reg)); \ + /* Set rounding towards negative infinity. */ \ + __asm__ __volatile__ ("fmove%.l %0, %!" : /* No outputs. */ \ + : "dmi" ((__ctrl_reg & ~0x10) | 0x20)); \ + /* Convert X to an integer, using -Inf rounding. */ \ + __asm__ __volatile__ ("fint%.x %1, %0" : "=f" (__result) : "f" (__x)); \ + /* Restore the previous rounding mode. */ \ + __asm__ __volatile__ ("fmove%.l %0, %!" : /* No outputs. */ \ + : "dmi" (__ctrl_reg)); \ + return __result; \ +} \ + \ +__m81_defun (float_type, __CONCAT(__ceil,s), (float_type __x)) \ +{ \ + float_type __result; \ + unsigned long int __ctrl_reg; \ + __asm__ __volatile__ ("fmove%.l %!, %0" : "=dm" (__ctrl_reg)); \ + /* Set rounding towards positive infinity. */ \ + __asm__ __volatile__ ("fmove%.l %0, %!" : /* No outputs. */ \ + : "dmi" (__ctrl_reg | 0x30)); \ + /* Convert X to an integer, using +Inf rounding. */ \ + __asm__ __volatile__ ("fint%.x %1, %0" : "=f" (__result) : "f" (__x)); \ + /* Restore the previous rounding mode. */ \ + __asm__ __volatile__ ("fmove%.l %0, %!" : /* No outputs. */ \ + : "dmi" (__ctrl_reg)); \ + return __result; \ +} + +__inline_functions(double,) +#if defined __USE_MISC || defined __USE_ISOC99 +__inline_functions(float,f) +__inline_functions(long double,l) +#endif +#undef __inline_functions + +#ifdef __USE_MISC + +# define __inline_functions(float_type, s) \ +__m81_defun (int, __CONCAT(__isinf,s), (float_type __value)) \ +{ \ + /* There is no branch-condition for infinity, \ + so we must extract and examine the condition codes manually. */ \ + unsigned long int __fpsr; \ + __asm__("ftst%.x %1\n" \ + "fmove%.l %/fpsr, %0" : "=dm" (__fpsr) : "f" (__value)); \ + return (__fpsr & (2 << 24)) ? (__fpsr & (8 << 24) ? -1 : 1) : 0; \ +} \ + \ +__m81_defun (int, __CONCAT(__finite,s), (float_type __value)) \ +{ \ + /* There is no branch-condition for infinity, so we must extract and \ + examine the condition codes manually. */ \ + unsigned long int __fpsr; \ + __asm__ ("ftst%.x %1\n" \ + "fmove%.l %/fpsr, %0" : "=dm" (__fpsr) : "f" (__value)); \ + return (__fpsr & (3 << 24)) == 0; \ +} \ + \ +__m81_defun (float_type, __CONCAT(__scalbn,s), \ + (float_type __x, int __n)) \ +{ \ + float_type __result; \ + __asm__ ("fscale%.l %1, %0" : "=f" (__result) : "dmi" (__n), "0" (__x)); \ + return __result; \ +} + +__inline_functions(double,) +__inline_functions(float,f) +__inline_functions(long double,l) +# undef __inline_functions + +#endif /* Use misc. */ + +#if defined __USE_MISC || defined __USE_XOPEN + +# define __inline_functions(float_type, s) \ +__m81_defun (int, __CONCAT(__isnan,s), (float_type __value)) \ +{ \ + char __result; \ + __asm__("ftst%.x %1\n" \ + "fsun %0" : "=dm" (__result) : "f" (__value)); \ + return __result; \ +} + +__inline_functions(double,) +# ifdef __USE_MISC +__inline_functions(float,f) +__inline_functions(long double,l) +# endif +# undef __inline_functions + +#endif + +#ifdef __USE_ISOC99 + +# define __inline_functions(float_type, s) \ +__m81_defun (int, __CONCAT(__signbit,s), (float_type __value)) \ +{ \ + /* There is no branch-condition for the sign bit, so we must extract \ + and examine the condition codes manually. */ \ + unsigned long int __fpsr; \ + __asm__ ("ftst%.x %1\n" \ + "fmove%.l %/fpsr, %0" : "=dm" (__fpsr) : "f" (__value)); \ + return (__fpsr >> 27) & 1; \ +} \ + \ + __m81_defun (float_type, __CONCAT(__scalbln,s), \ + (float_type __x, long int __n)) \ +{ \ + return __CONCAT(__scalbn,s) (__x, __n); \ +} \ + \ +__m81_defun (float_type, __CONCAT(__nearbyint,s), (float_type __x)) \ +{ \ + float_type __result; \ + unsigned long int __ctrl_reg; \ + __asm__ __volatile__ ("fmove%.l %!, %0" : "=dm" (__ctrl_reg)); \ + /* Temporarily disable the inexact exception. */ \ + __asm__ __volatile__ ("fmove%.l %0, %!" : /* No outputs. */ \ + : "dmi" (__ctrl_reg & ~0x200)); \ + __asm__ __volatile__ ("fint%.x %1, %0" : "=f" (__result) : "f" (__x)); \ + __asm__ __volatile__ ("fmove%.l %0, %!" : /* No outputs. */ \ + : "dmi" (__ctrl_reg)); \ + return __result; \ +} \ + \ +__m81_defun (long int, __CONCAT(__lrint,s), (float_type __x)) \ +{ \ + long int __result; \ + __asm__ ("fmove%.l %1, %0" : "=dm" (__result) : "f" (__x)); \ + return __result; \ +} \ + \ +__m81_inline float_type \ +__m81_u(__CONCAT(__fma,s))(float_type __x, float_type __y, \ + float_type __z) \ +{ \ + return (__x * __y) + __z; \ +} + +__inline_functions (double,) +__inline_functions (float,f) +__inline_functions (long double,l) +# undef __inline_functions + +#endif /* Use ISO C9x */ + +#ifdef __USE_GNU + +# define __inline_functions(float_type, s) \ +__m81_inline void \ +__m81_u(__CONCAT(__sincos,s))(float_type __x, float_type *__sinx, \ + float_type *__cosx) \ +{ \ + __asm__ ("fsincos%.x %2,%1:%0" \ + : "=f" (*__sinx), "=f" (*__cosx) : "f" (__x)); \ +} + +__inline_functions (double,) +__inline_functions (float,f) +__inline_functions (long double,l) +# undef __inline_functions + +#endif + +#if !defined __NO_MATH_INLINES && defined __OPTIMIZE__ + +/* Define inline versions of the user visible functions. */ + +/* Note that there must be no whitespace before the argument passed for + NAME, to make token pasting work correctly with -traditional. */ +# define __inline_forward_c(rettype, name, args1, args2) \ +extern __inline rettype __attribute__((__const__)) \ + name args1 \ +{ \ + return __CONCAT(__,name) args2; \ +} + +# define __inline_forward(rettype, name, args1, args2) \ +extern __inline rettype name args1 \ +{ \ + return __CONCAT(__,name) args2; \ +} + +__inline_forward_c(double,floor, (double __x), (__x)) +__inline_forward_c(double,ceil, (double __x), (__x)) +# ifdef __USE_MISC +# ifndef __USE_ISOC99 /* Conflict with macro of same name. */ +__inline_forward_c(int,isinf, (double __value), (__value)) +# endif +__inline_forward_c(int,finite, (double __value), (__value)) +__inline_forward_c(double,scalbn, (double __x, int __n), (__x, __n)) +# endif +# if defined __USE_MISC || defined __USE_XOPEN +# ifndef __USE_ISOC99 /* Conflict with macro of same name. */ +__inline_forward_c(int,isnan, (double __value), (__value)) +# endif +# endif +# ifdef __USE_ISOC99 +__inline_forward_c(double,scalbln, (double __x, long int __n), (__x, __n)) +__inline_forward_c(double,nearbyint, (double __value), (__value)) +__inline_forward_c(long int,lrint, (double __value), (__value)) +__inline_forward_c(double,fma, (double __x, double __y, double __z), + (__x, __y, __z)) +# endif +# ifdef __USE_GNU +__inline_forward(void,sincos, (double __x, double *__sinx, double *__cosx), + (__x, __sinx, __cosx)) +# endif + +# if defined __USE_MISC || defined __USE_ISOC99 + +__inline_forward_c(float,floorf, (float __x), (__x)) +__inline_forward_c(float,ceilf, (float __x), (__x)) +# ifdef __USE_MISC +__inline_forward_c(int,isinff, (float __value), (__value)) +__inline_forward_c(int,finitef, (float __value), (__value)) +__inline_forward_c(float,scalbnf, (float __x, int __n), (__x, __n)) +__inline_forward_c(int,isnanf, (float __value), (__value)) +# endif +# ifdef __USE_ISOC99 +__inline_forward_c(float,scalblnf, (float __x, long int __n), (__x, __n)) +__inline_forward_c(float,nearbyintf, (float __value), (__value)) +__inline_forward_c(long int,lrintf, (float __value), (__value)) +__inline_forward_c(float,fmaf, (float __x, float __y, float __z), + (__x, __y, __z)) +# endif +# ifdef __USE_GNU +__inline_forward(void,sincosf, (float __x, float *__sinx, float *__cosx), + (__x, __sinx, __cosx)) +# endif + +__inline_forward_c(long double,floorl, (long double __x), (__x)) +__inline_forward_c(long double,ceill, (long double __x), (__x)) +# ifdef __USE_MISC +__inline_forward_c(int,isinfl, (long double __value), (__value)) +__inline_forward_c(int,finitel, (long double __value), (__value)) +__inline_forward_c(long double,scalbnl, (long double __x, int __n), (__x, __n)) +__inline_forward_c(int,isnanl, (long double __value), (__value)) +# endif +# ifdef __USE_ISOC99 +__inline_forward_c(long double,scalblnl, (long double __x, long int __n), + (__x, __n)) +__inline_forward_c(long double,nearbyintl, (long double __value), (__value)) +__inline_forward_c(long int,lrintl, (long double __value), (__value)) +__inline_forward_c(long double,fmal, + (long double __x, long double __y, long double __z), + (__x, __y, __z)) +# endif +# ifdef __USE_GNU +__inline_forward(void,sincosl, + (long double __x, long double *__sinx, long double *__cosx), + (__x, __sinx, __cosx)) +# endif + +#endif /* Use misc or ISO C99 */ + +#undef __inline_forward +#undef __inline_forward_c + +#endif /* !__NO_MATH_INLINES && __OPTIMIZE__ */ + +#endif +#endif /* GCC. */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/bits/poll.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/bits/poll.h new file mode 100644 index 00000000..f7a73931 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/bits/poll.h @@ -0,0 +1,43 @@ +/* Copyright (C) 1997, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_POLL_H +# error "Never use directly; include instead." +#endif + +/* Event types that can be polled for. These bits may be set in `events' + to indicate the interesting event types; they will appear in `revents' + to indicate the status of the file descriptor. */ +#define POLLIN 0x001 /* There is data to read. */ +#define POLLPRI 0x002 /* There is urgent data to read. */ +#define POLLOUT 0x004 /* Writing now will not block. */ + +#ifdef __USE_XOPEN +/* These values are defined in XPG4.2. */ +# define POLLRDNORM 0x040 /* Normal data may be read. */ +# define POLLRDBAND 0x080 /* Priority data may be read. */ +# define POLLWRNORM POLLOUT /* Writing now will not block. */ +# define POLLWRBAND 0x100 /* Priority data may be written. */ +#endif + +/* Event types always implicitly polled for. These bits need not be set in + `events', but they will appear in `revents' to indicate the status of + the file descriptor. */ +#define POLLERR 0x008 /* Error condition. */ +#define POLLHUP 0x010 /* Hung up. */ +#define POLLNVAL 0x020 /* Invalid polling request. */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/bits/setjmp.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/bits/setjmp.h new file mode 100644 index 00000000..a6b0ed0f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/bits/setjmp.h @@ -0,0 +1,68 @@ +/* Copyright (C) 2002, David McCullough */ +/* Copyright (C) 1997,1998,2005,2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Define the machine-dependent type `jmp_buf'. m68k version. */ +#ifndef _BITS_SETJMP_H +#define _BITS_SETJMP_H 1 + +#if !defined _SETJMP_H && !defined _PTHREAD_H +# error "Never include directly; use instead." +#endif + +#ifndef _ASM + +typedef struct + { + /* There are eight 4-byte data registers, but D0 is not saved. */ + long int __dregs[7]; + + /* There are six 4-byte address registers, plus the FP and SP. */ + int *__aregs[6]; + int *__fp; + int *__sp; + +#if defined __HAVE_68881__ || defined __HAVE_FPU__ + /* There are eight floating point registers which + are saved in IEEE 96-bit extended format. */ + char __fpregs[8 * (96 / 8)]; +#endif + + } __jmp_buf[1]; + +#endif + +#define JB_REGS 0 +#define JB_DREGS 0 +#define JB_AREGS 24 +#define JB_PC 48 +#define JB_FPREGS 52 + +#if defined __HAVE_68881__ || defined __HAVE_FPU__ +# define JB_SIZE 76 +#else +# define JB_SIZE 52 +#endif + + +/* Test if longjmp to JMPBUF would unwind the frame + containing a local variable at ADDRESS. */ +#define _JMPBUF_UNWINDS(jmpbuf, address) \ + ((void *) (address) < (void *) (jmpbuf)->__aregs[5]) + +#endif /* bits/setjmp.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/bits/sigcontextinfo.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/bits/sigcontextinfo.h new file mode 100644 index 00000000..b7e08cfc --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/bits/sigcontextinfo.h @@ -0,0 +1,26 @@ +/* Copyright (C) 1998, 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Andreas Schwab , 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define SIGCONTEXT int _code, struct sigcontext * +#define SIGCONTEXT_EXTRA_ARGS _code, +#define GET_PC(ctx) ((void *) (ctx)->sc_pc) +#define GET_FRAME(ctx) ((void *) __builtin_frame_address (1)) +#define GET_STACK(ctx) ((void *) (ctx)->sc_usp) +#define CALL_SIGHANDLER(handler, signo, ctx) \ + (handler)((signo), SIGCONTEXT_EXTRA_ARGS (ctx)) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/bits/stackinfo.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/bits/stackinfo.h new file mode 100644 index 00000000..66e5a17f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/bits/stackinfo.h @@ -0,0 +1,28 @@ +/* Copyright (C) 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This file contains a bit of information about the stack allocation + of the processor. */ + +#ifndef _STACKINFO_H +#define _STACKINFO_H 1 + +/* On m68k the stack grows down. */ +#define _STACK_GROWS_DOWN 1 + +#endif /* stackinfo.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/bits/stat.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/bits/stat.h new file mode 100644 index 00000000..8d18d6de --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/bits/stat.h @@ -0,0 +1,169 @@ +/* Copyright (C) 1992,95,96,97,98,99,2000,2001,2002,2008,2009 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_STAT_H +# error "Never include directly; use instead." +#endif + +/* Versions of the `struct stat' data structure. */ +#define _STAT_VER_LINUX_OLD 1 +#define _STAT_VER_KERNEL 1 +#define _STAT_VER_SVR4 2 +#define _STAT_VER_LINUX 3 +#define _STAT_VER _STAT_VER_LINUX /* The one defined below. */ + +/* Versions of the `xmknod' interface. */ +#define _MKNOD_VER_LINUX 1 +#define _MKNOD_VER_SVR4 2 +#define _MKNOD_VER _MKNOD_VER_LINUX /* The bits defined below. */ + + +struct stat + { + __dev_t st_dev; /* Device. */ + unsigned short int __pad1; +#ifndef __USE_FILE_OFFSET64 + __ino_t st_ino; /* File serial number. */ +#else + __ino_t __st_ino; /* 32bit file serial number. */ +#endif + __mode_t st_mode; /* File mode. */ + __nlink_t st_nlink; /* Link count. */ + __uid_t st_uid; /* User ID of the file's owner. */ + __gid_t st_gid; /* Group ID of the file's group.*/ + __dev_t st_rdev; /* Device number, if device. */ + unsigned short int __pad2; +#ifndef __USE_FILE_OFFSET64 + __off_t st_size; /* Size of file, in bytes. */ +#else + __off64_t st_size; /* Size of file, in bytes. */ +#endif + __blksize_t st_blksize; /* Optimal block size for I/O. */ + +#ifndef __USE_FILE_OFFSET64 + __blkcnt_t st_blocks; /* Number 512-byte blocks allocated. */ +#else + __blkcnt64_t st_blocks; /* Number 512-byte blocks allocated. */ +#endif +#ifdef __USE_MISC + /* Nanosecond resolution timestamps are stored in a format + equivalent to 'struct timespec'. This is the type used + whenever possible but the Unix namespace rules do not allow the + identifier 'timespec' to appear in the header. + Therefore we have to handle the use of this header in strictly + standard-compliant sources special. */ + struct timespec st_atim; /* Time of last access. */ + struct timespec st_mtim; /* Time of last modification. */ + struct timespec st_ctim; /* Time of last status change. */ +# define st_atime st_atim.tv_sec /* Backward compatibility. */ +# define st_mtime st_mtim.tv_sec +# define st_ctime st_ctim.tv_sec +#else + __time_t st_atime; /* Time of last access. */ + unsigned long int st_atimensec; /* Nscecs of last access. */ + __time_t st_mtime; /* Time of last modification. */ + unsigned long int st_mtimensec; /* Nsecs of last modification. */ + __time_t st_ctime; /* Time of last status change. */ + unsigned long int st_ctimensec; /* Nsecs of last status change. */ +#endif +#ifndef __USE_FILE_OFFSET64 + unsigned long int __unused4; + unsigned long int __unused5; +#else + __ino64_t st_ino; /* File serial number. */ +#endif + }; + +#ifdef __USE_LARGEFILE64 +struct stat64 + { + __dev_t st_dev; /* Device. */ + unsigned short int __pad1; + + __ino_t __st_ino; /* 32bit file serial number. */ + __mode_t st_mode; /* File mode. */ + __nlink_t st_nlink; /* Link count. */ + __uid_t st_uid; /* User ID of the file's owner. */ + __gid_t st_gid; /* Group ID of the file's group.*/ + __dev_t st_rdev; /* Device number, if device. */ + unsigned short int __pad2; + __off64_t st_size; /* Size of file, in bytes. */ + __blksize_t st_blksize; /* Optimal block size for I/O. */ + + __blkcnt64_t st_blocks; /* Number 512-byte blocks allocated. */ +#ifdef __USE_MISC + /* Nanosecond resolution timestamps are stored in a format + equivalent to 'struct timespec'. This is the type used + whenever possible but the Unix namespace rules do not allow the + identifier 'timespec' to appear in the header. + Therefore we have to handle the use of this header in strictly + standard-compliant sources special. */ + struct timespec st_atim; /* Time of last access. */ + struct timespec st_mtim; /* Time of last modification. */ + struct timespec st_ctim; /* Time of last status change. */ +#else + __time_t st_atime; /* Time of last access. */ + unsigned long int st_atimensec; /* Nscecs of last access. */ + __time_t st_mtime; /* Time of last modification. */ + unsigned long int st_mtimensec; /* Nsecs of last modification. */ + __time_t st_ctime; /* Time of last status change. */ + unsigned long int st_ctimensec; /* Nsecs of last status change. */ +#endif + __ino64_t st_ino; /* File serial number. */ + }; +#endif + +/* Tell code we have these members. */ +#define _STATBUF_ST_BLKSIZE +#define _STATBUF_ST_RDEV +/* Nanosecond resolution time values are supported. */ +#define _STATBUF_ST_NSEC + +/* Encoding of the file mode. */ + +#define __S_IFMT 0170000 /* These bits determine file type. */ + +/* File types. */ +#define __S_IFDIR 0040000 /* Directory. */ +#define __S_IFCHR 0020000 /* Character device. */ +#define __S_IFBLK 0060000 /* Block device. */ +#define __S_IFREG 0100000 /* Regular file. */ +#define __S_IFIFO 0010000 /* FIFO. */ +#define __S_IFLNK 0120000 /* Symbolic link. */ +#define __S_IFSOCK 0140000 /* Socket. */ + +/* POSIX.1b objects. Note that these macros always evaluate to zero. But + they do it by enforcing the correct use of the macros. */ +#define __S_TYPEISMQ(buf) ((buf)->st_mode - (buf)->st_mode) +#define __S_TYPEISSEM(buf) ((buf)->st_mode - (buf)->st_mode) +#define __S_TYPEISSHM(buf) ((buf)->st_mode - (buf)->st_mode) + +/* Protection bits. */ + +#define __S_ISUID 04000 /* Set user ID on execution. */ +#define __S_ISGID 02000 /* Set group ID on execution. */ +#define __S_ISVTX 01000 /* Save swapped text after use (sticky). */ +#define __S_IREAD 0400 /* Read by owner. */ +#define __S_IWRITE 0200 /* Write by owner. */ +#define __S_IEXEC 0100 /* Execute by owner. */ + +#ifdef __USE_ATFILE +# define UTIME_NOW ((1l << 30) - 1l) +# define UTIME_OMIT ((1l << 30) - 2l) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/bits/syscalls.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/bits/syscalls.h new file mode 100644 index 00000000..2c56613e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/bits/syscalls.h @@ -0,0 +1,111 @@ +#ifndef _BITS_SYSCALLS_H +#define _BITS_SYSCALLS_H +#ifndef _SYSCALL_H +# error "Never use directly; include instead." +#endif + +/* m68k headers does stupid stuff with __NR_iopl / __NR_vm86: + * #define __NR_iopl not supported + * #define __NR_vm86 not supported + */ +#undef __NR_iopl +#undef __NR_vm86 + +#ifndef __ASSEMBLER__ + +/* Linux takes system call arguments in registers: + + syscall number %d0 call-clobbered + arg 1 %d1 call-clobbered + arg 2 %d2 call-saved + arg 3 %d3 call-saved + arg 4 %d4 call-saved + arg 5 %d5 call-saved + arg 6 %a0 call-clobbered + + The stack layout upon entering the function is: + + 24(%sp) Arg# 6 + 20(%sp) Arg# 5 + 16(%sp) Arg# 4 + 12(%sp) Arg# 3 + 8(%sp) Arg# 2 + 4(%sp) Arg# 1 + (%sp) Return address + + (Of course a function with say 3 arguments does not have entries for + arguments 4 and 5.) + + Separate move's are faster than movem, but need more space. Since + speed is more important, we don't use movem. Since %a0 and %a1 are + scratch registers, we can use them for saving as well. */ + +/* Define a macro which expands inline into the wrapper code for a system + call. This use is for internal calls that do not need to handle errors + normally. It will never touch errno. This returns just what the kernel + gave back. */ +#define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \ + ({ unsigned int _sys_result; \ + { \ + /* Load argument values in temporary variables + to perform side effects like function calls + before the call used registers are set. */ \ + LOAD_ARGS_##nr (args) \ + LOAD_REGS_##nr \ + register int _d0 __asm__ ("%d0") = name; \ + __asm__ __volatile__ ("trap #0" \ + : "=d" (_d0) \ + : "0" (_d0) ASM_ARGS_##nr \ + : "memory"); \ + _sys_result = _d0; \ + } \ + (int) _sys_result; }) + +#define LOAD_ARGS_0() +#define LOAD_REGS_0 +#define ASM_ARGS_0 +#define LOAD_ARGS_1(a1) \ + LOAD_ARGS_0 () \ + int __arg1 = (int) (a1); +#define LOAD_REGS_1 \ + register int _d1 __asm__ ("d1") = __arg1; \ + LOAD_REGS_0 +#define ASM_ARGS_1 ASM_ARGS_0, "d" (_d1) +#define LOAD_ARGS_2(a1, a2) \ + LOAD_ARGS_1 (a1) \ + int __arg2 = (int) (a2); +#define LOAD_REGS_2 \ + register int _d2 __asm__ ("d2") = __arg2; \ + LOAD_REGS_1 +#define ASM_ARGS_2 ASM_ARGS_1, "d" (_d2) +#define LOAD_ARGS_3(a1, a2, a3) \ + LOAD_ARGS_2 (a1, a2) \ + int __arg3 = (int) (a3); +#define LOAD_REGS_3 \ + register int _d3 __asm__ ("d3") = __arg3; \ + LOAD_REGS_2 +#define ASM_ARGS_3 ASM_ARGS_2, "d" (_d3) +#define LOAD_ARGS_4(a1, a2, a3, a4) \ + LOAD_ARGS_3 (a1, a2, a3) \ + int __arg4 = (int) (a4); +#define LOAD_REGS_4 \ + register int _d4 __asm__ ("d4") = __arg4; \ + LOAD_REGS_3 +#define ASM_ARGS_4 ASM_ARGS_3, "d" (_d4) +#define LOAD_ARGS_5(a1, a2, a3, a4, a5) \ + LOAD_ARGS_4 (a1, a2, a3, a4) \ + int __arg5 = (int) (a5); +#define LOAD_REGS_5 \ + register int _d5 __asm__ ("d5") = __arg5; \ + LOAD_REGS_4 +#define ASM_ARGS_5 ASM_ARGS_4, "d" (_d5) +#define LOAD_ARGS_6(a1, a2, a3, a4, a5, a6) \ + LOAD_ARGS_5 (a1, a2, a3, a4, a5) \ + int __arg6 = (int) (a6); +#define LOAD_REGS_6 \ + register int _a0 __asm__ ("a0") = __arg6; \ + LOAD_REGS_5 +#define ASM_ARGS_6 ASM_ARGS_5, "a" (_a0) + +#endif /* __ASSEMBLER__ */ +#endif /* _BITS_SYSCALLS_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/bits/uClibc_arch_features.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/bits/uClibc_arch_features.h new file mode 100644 index 00000000..518fb395 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/bits/uClibc_arch_features.h @@ -0,0 +1,51 @@ +/* + * Track misc arch-specific features that aren't config options + */ + +#ifndef _BITS_UCLIBC_ARCH_FEATURES_H +#define _BITS_UCLIBC_ARCH_FEATURES_H + +/* instruction used when calling abort() to kill yourself */ +#if defined(__mc68000__) +# define __UCLIBC_ABORT_INSTRUCTION__ ".long 0xffffffff" +#else /* defined(__m68k__) */ +# define __UCLIBC_ABORT_INSTRUCTION__ "illegal" +#endif + +/* can your target use syscall6() for mmap ? */ +#undef __UCLIBC_MMAP_HAS_6_ARGS__ + +/* does your target use syscall4() for truncate64 ? (32bit arches only) */ +#undef __UCLIBC_TRUNCATE64_HAS_4_ARGS__ + +/* does your target have a broken create_module() ? */ +#define __UCLIBC_BROKEN_CREATE_MODULE__ + +/* does your target have to worry about older [gs]etrlimit() ? */ +#define __UCLIBC_HANDLE_OLDER_RLIMIT__ + +/* does your target have an asm .set ? */ +#define __UCLIBC_HAVE_ASM_SET_DIRECTIVE__ + +/* define if target doesn't like .global */ +#undef __UCLIBC_ASM_GLOBAL_DIRECTIVE__ + +/* define if target supports .weak */ +#define __UCLIBC_HAVE_ASM_WEAK_DIRECTIVE__ + +/* define if target supports .weakext */ +#undef __UCLIBC_HAVE_ASM_WEAKEXT_DIRECTIVE__ + +/* needed probably only for ppc64 */ +#undef __UCLIBC_HAVE_ASM_GLOBAL_DOT_NAME__ + +/* define if target supports CFI pseudo ops */ +#undef __UCLIBC_HAVE_ASM_CFI_DIRECTIVES__ + +/* define if target supports IEEE signed zero floats */ +#define __UCLIBC_HAVE_SIGNED_ZERO__ + +/* only weird assemblers generally need this */ +#undef __UCLIBC_ASM_LINE_SEP__ + +#endif /* _BITS_UCLIBC_ARCH_FEATURES_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/bits/uClibc_page.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/bits/uClibc_page.h new file mode 100644 index 00000000..51c6f144 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/bits/uClibc_page.h @@ -0,0 +1,41 @@ +/* Copyright (C) 2004 Erik Andersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* Supply an architecture specific value for PAGE_SIZE and friends. */ + +#ifndef _UCLIBC_PAGE_H +#define _UCLIBC_PAGE_H + +/* +#include +*/ + +/* PAGE_SHIFT determines the page size */ + +/* +#ifndef CONFIG_SUN3 +*/ +#define PAGE_SHIFT (12) +/* +#else +#define PAGE_SHIFT (13) +#endif +*/ +#define PAGE_SIZE (1UL << PAGE_SHIFT) +#define PAGE_MASK (~(PAGE_SIZE-1)) + +#endif /* _UCLIBC_PAGE_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/bits/wordsize.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/bits/wordsize.h new file mode 100644 index 00000000..ba643b60 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/bits/wordsize.h @@ -0,0 +1,19 @@ +/* Copyright (C) 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define __WORDSIZE 32 diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/brk.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/brk.c new file mode 100644 index 00000000..40ebf4fc --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/brk.c @@ -0,0 +1,37 @@ +/* consider this code LGPL - davidm */ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include + + +/* This must be initialized data because commons can't have aliases. */ +void * __curbrk = 0; + +int brk (void *addr) +{ + void *newbrk; + + __asm__ __volatile__ ("movel %2,%/d1\n\t" + "moveq %1,%/d0\n\t" + "trap #0\n\t" + "movel %/d0,%0" + :"=g" (newbrk) + :"i" (__NR_brk),"g" (addr) : "%d0", "%d1"); + + __curbrk = newbrk; + + if (newbrk < addr) + { + __set_errno (ENOMEM); + return -1; + } + + return 0; +} +libc_hidden_def(brk) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/bsd-_setjmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/bsd-_setjmp.S new file mode 100644 index 00000000..0380c3de --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/bsd-_setjmp.S @@ -0,0 +1,24 @@ + +/* Copyright (C) 2002, David McCullough */ +/* This file is released under the LGPL, any version you like */ + +#define _ASM +#define _SETJMP_H +#include + +.globl _setjmp; +.type _setjmp,@function +.align 4; + +_setjmp: + moveal %sp@(4), %a0 + movel %sp@(0), %a0@(JB_PC) + moveml %d2-%d7/%a2-%a7, %a0@(JB_REGS) +#if defined(__HAVE_68881__) || defined(__HAVE_FPU__) + fmovemx %fp2-%fp7, %a0@(JB_FPREGS) +#endif + clrl %d0 + movl %d0, JB_SIZE(%a0) /* No signal mask set. */ + rts + + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/bsd-setjmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/bsd-setjmp.S new file mode 100644 index 00000000..fdd7540a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/bsd-setjmp.S @@ -0,0 +1,23 @@ + +/* Copyright (C) 2002, David McCullough */ +/* This file is released under the LGPL, any version you like */ + +#define _ASM +#define _SETJMP_H +#include +#include "m68k_pic.S" + +.globl setjmp; +.type setjmp,@function +.align 4; + +setjmp: + moveal %sp@(4), %a0 + movel %sp@(0), %a0@(JB_PC) + moveml %d2-%d7/%a2-%a7, %a0@(JB_REGS) +#if defined(__HAVE_68881__) || defined(__HAVE_FPU__) + fmovemx %fp2-%fp7, %a0@(JB_FPREGS) +#endif + clrl %d0 + JUMP __sigjmp_save,%a0 + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/clone.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/clone.S new file mode 100644 index 00000000..7eddff10 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/clone.S @@ -0,0 +1,69 @@ +/* Adapted from glibc */ +/* Copyright (C) 1996, 1997 Free Software Foundation, Inc. */ + +/* clone is even more special than fork as it mucks with stacks + and invokes a function in the right context after its all over. */ + +#define _ERRNO_H +#include +#include +#include +#include "m68k_pic.S" + +/* int _clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg); */ + +.text +.align 4 +.type clone,@function +.globl clone; +clone: + /* Sanity check arguments. */ + movel #-EINVAL, %d0 + movel 4(%sp), %d1 /* no NULL function pointers */ + movel %d1, %a0 + tstl %d1 + beq.w __syscall_error_trampoline + movel 8(%sp), %d1 /* no NULL stack pointers */ + movel %d1, %a1 + tstl %d1 + beq.w __syscall_error_trampoline + + /* Allocate space and copy the argument onto the new stack. */ + movel 16(%sp), -(%a1) + + /* Do the system call */ +#if 1 /* defined (CONFIG_COLDFIRE) */ + movel %d2, %d1 /* save %d2 and get stack pointer */ + movel %a1, %d2 + movel %d1, %a1 +#else + exg %d2, %a1 /* save %d2 and get stack pointer */ +#endif + movel 12(%sp), %d1 /* get flags */ + movel #__NR_clone, %d0 + trap #0 +#if 1 /* defined (CONFIG_COLDFIRE) */ + movel %d2, %d1 /* restore %d2 */ + movel %a1, %d2 + movel %d1, %a1 +#else + exg %d2, %a1 /* restore %d2 */ +#endif + + tstl %d0 + bmi.w __syscall_error_trampoline + beq.w thread_start + + rts + +thread_start: + /*subl %fp, %fp*/ /* terminate the stack frame */ + jsr (%a0) + movel %d0, -(%sp) + movel #__NR_exit, %d0 + trap #0 + /*jsr exit*/ + +__syscall_error_trampoline: + JUMP __syscall_error,%a0 + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/crt1.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/crt1.S new file mode 100644 index 00000000..a9cf0019 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/crt1.S @@ -0,0 +1,152 @@ +/* Startup code compliant to the ELF m68k ABI. + Copyright (C) 1996, 1997, 1998, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file with other + programs, and to distribute those programs without any restriction + coming from the use of this file. (The GNU Lesser General Public + License restrictions do apply in other respects; for example, they + cover modification of the file, and distribution when not linked + into another program.) + + Note that people who make modified versions of this file are not + obligated to grant this special exception for their modified + versions; it is their choice whether to do so. The GNU Lesser + General Public License gives permission to release a modified + version without this exception; this exception also makes it + possible to release a modified version which carries forward this + exception. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include "m68k_pic.S" + +#ifndef L_Scrt1 +/* This is the canonical entry point, usually the first thing in the text + segment. The SVR4/m68k ABI says that when the entry point runs, + most registers' values are unspecified, except for: + + %a1 Contains a function pointer to be registered with `atexit'. + This is how the dynamic linker arranges to have DT_FINI + functions called for shared libraries that have been loaded + before this code runs. + + %sp The stack contains the arguments and environment: + 0(%sp) argc + 4(%sp) argv[0] + ... + (4*argc)(%sp) NULL + (4*(argc+1))(%sp) envp[0] + ... + NULL + + The uclinux conventions are different. %a1 is not defined on entry + and the stack is laid out as follows: + + 0(%sp) argc + 4(%sp) argv + 8(%sp) envp +*/ + + .text + .type _init,%function + .type _fini,%function +#ifndef __UCLIBC_CTOR_DTOR__ + .weak _init + .weak _fini +#endif + .globl _start + .type _start,@function +_start: + /* Clear the frame pointer. The ABI suggests this be done, to mark + the outermost frame obviously. */ + sub.l %fp, %fp + +#if !defined __ARCH_USE_MMU__ && defined __PIC__ + /* Set up the global pointer. The GOT is at the beginning of the + data segment, whose address is in %d5. */ + move.l %d5,%a5 + .equ have_current_got, 1 +#endif + +#ifdef __UCLIBC_FORMAT_SHARED_FLAT__ + CALL __shared_flat_add_library,%a1 +#endif + + /* Extract the arguments as encoded on the stack and set up the + arguments for `main': argc, argv. envp will be determined + later in __libc_start_main. */ + move.l (%sp)+, %d0 /* Pop the argument count. */ +#ifndef __ARCH_USE_MMU__ + move.l (%sp)+, %a0 +#else + move.l %sp, %a0 /* The argument vector starts just at the + current stack top. */ +#endif + + /* Provide the highest stack address to the user code (for stacks + which grow downward). */ + pea (%sp) + +#ifndef __ARCH_USE_MMU__ + clr.l -(%sp) +#else + pea (%a1) /* Push address of the shared library + termination function. */ +#endif + + /* Push the address of our own entry points to `.fini' and + `.init'. */ +#if defined __UCLIBC_FORMAT_SHARED_FLAT__ + PEA_TEXT __shared_flat_fini,%a1 + PEA_TEXT __shared_flat_init,%a1 +#else + PEA_TEXT _fini,%a1 + PEA_TEXT _init,%a1 +#endif + + pea (%a0) /* Push second argument: argv. */ + move.l %d0, -(%sp) /* Push first argument: argc. */ + + PEA_TEXT main,%a1 + + /* Call the user's main function, and exit with its value. But + let the libc call main. */ + CALL __uClibc_main,%a1 + + illegal /* Crash if somehow `exit' does return. */ +#else + .text + .globl lib_main + .hidden lib_main + .type lib_main,@function +lib_main: + move.l %d5,%a5 + JUMP __shared_flat_add_library,%a0 + + .hidden _current_shared_library_a5_offset_ +#endif + +/* Define a symbol for the first piece of initialized data. */ + .data + .globl __data_start +__data_start: + .long 0 + .weak data_start + data_start = __data_start diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/crti.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/crti.S new file mode 100644 index 00000000..1b4b643b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/crti.S @@ -0,0 +1,17 @@ +#include "m68k_pic.S" + + .section .init + .align 2 + .globl _init + .type _init, @function +_init: + link.w %a6,#0 + INIT_GP + + .section .fini + .align 2 + .globl _fini + .type _fini, @function +_fini: + link.w %a6,#0 + INIT_GP diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/crtn.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/crtn.S new file mode 100644 index 00000000..2a29b872 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/crtn.S @@ -0,0 +1,11 @@ +#include "m68k_pic.S" + + .section .init + FINI_GP + unlk %a6 + rts + + .section .fini + FINI_GP + unlk %a6 + rts diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/float.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/float.h new file mode 100644 index 00000000..7dbe4e92 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/float.h @@ -0,0 +1,96 @@ +/* float.h for target with IEEE 32 bit and 64 bit floating point formats */ +#ifndef _FLOAT_H_ +#define _FLOAT_H_ +/* Produced by enquire version 4.3, CWI, Amsterdam */ + + /* Radix of exponent representation */ +#undef FLT_RADIX +#define FLT_RADIX 2 + /* Number of base-FLT_RADIX digits in the significand of a float */ +#undef FLT_MANT_DIG +#define FLT_MANT_DIG 24 + /* Number of decimal digits of precision in a float */ +#undef FLT_DIG +#define FLT_DIG 6 + /* Addition rounds to 0: zero, 1: nearest, 2: +inf, 3: -inf, -1: unknown */ +#undef FLT_ROUNDS +#define FLT_ROUNDS 1 + /* Difference between 1.0 and the minimum float greater than 1.0 */ +#undef FLT_EPSILON +#define FLT_EPSILON 1.19209290e-07F + /* Minimum int x such that FLT_RADIX**(x-1) is a normalised float */ +#undef FLT_MIN_EXP +#define FLT_MIN_EXP (-125) + /* Minimum normalised float */ +#undef FLT_MIN +#define FLT_MIN 1.17549435e-38F + /* Minimum int x such that 10**x is a normalised float */ +#undef FLT_MIN_10_EXP +#define FLT_MIN_10_EXP (-37) + /* Maximum int x such that FLT_RADIX**(x-1) is a representable float */ +#undef FLT_MAX_EXP +#define FLT_MAX_EXP 128 + /* Maximum float */ +#undef FLT_MAX +#define FLT_MAX 3.40282347e+38F + /* Maximum int x such that 10**x is a representable float */ +#undef FLT_MAX_10_EXP +#define FLT_MAX_10_EXP 38 + + /* Number of base-FLT_RADIX digits in the significand of a double */ +#undef DBL_MANT_DIG +#define DBL_MANT_DIG 53 + /* Number of decimal digits of precision in a double */ +#undef DBL_DIG +#define DBL_DIG 15 + /* Difference between 1.0 and the minimum double greater than 1.0 */ +#undef DBL_EPSILON +#define DBL_EPSILON 2.2204460492503131e-16 + /* Minimum int x such that FLT_RADIX**(x-1) is a normalised double */ +#undef DBL_MIN_EXP +#define DBL_MIN_EXP (-1021) + /* Minimum normalised double */ +#undef DBL_MIN +#define DBL_MIN 2.2250738585072014e-308 + /* Minimum int x such that 10**x is a normalised double */ +#undef DBL_MIN_10_EXP +#define DBL_MIN_10_EXP (-307) + /* Maximum int x such that FLT_RADIX**(x-1) is a representable double */ +#undef DBL_MAX_EXP +#define DBL_MAX_EXP 1024 + /* Maximum double */ +#undef DBL_MAX +#define DBL_MAX 1.7976931348623157e+308 + /* Maximum int x such that 10**x is a representable double */ +#undef DBL_MAX_10_EXP +#define DBL_MAX_10_EXP 308 + + /* Number of base-FLT_RADIX digits in the significand of a long double */ +#undef LDBL_MANT_DIG +#define LDBL_MANT_DIG 53 + /* Number of decimal digits of precision in a long double */ +#undef LDBL_DIG +#define LDBL_DIG 15 + /* Difference between 1.0 and the minimum long double greater than 1.0 */ +#undef LDBL_EPSILON +#define LDBL_EPSILON 2.2204460492503131e-16L + /* Minimum int x such that FLT_RADIX**(x-1) is a normalised long double */ +#undef LDBL_MIN_EXP +#define LDBL_MIN_EXP (-1021) + /* Minimum normalised long double */ +#undef LDBL_MIN +#define LDBL_MIN 2.2250738585072014e-308L + /* Minimum int x such that 10**x is a normalised long double */ +#undef LDBL_MIN_10_EXP +#define LDBL_MIN_10_EXP (-307) + /* Maximum int x such that FLT_RADIX**(x-1) is a representable long double */ +#undef LDBL_MAX_EXP +#define LDBL_MAX_EXP 1024 + /* Maximum long double */ +#undef LDBL_MAX +#define LDBL_MAX 1.7976931348623157e+308L + /* Maximum int x such that 10**x is a representable long double */ +#undef LDBL_MAX_10_EXP +#define LDBL_MAX_10_EXP 308 + +#endif /* _FLOAT_H_ */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/fpu_control.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/fpu_control.h new file mode 100644 index 00000000..040e62c9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/fpu_control.h @@ -0,0 +1,103 @@ +/* 68k FPU control word definitions. + Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FPU_CONTROL_H +#define _FPU_CONTROL_H + +/* + * Motorola floating point control register bits. + * + * 31-16 -> reserved (read as 0, ignored on write) + * 15 -> enable trap for BSUN exception + * 14 -> enable trap for SNAN exception + * 13 -> enable trap for OPERR exception + * 12 -> enable trap for OVFL exception + * 11 -> enable trap for UNFL exception + * 10 -> enable trap for DZ exception + * 9 -> enable trap for INEX2 exception + * 8 -> enable trap for INEX1 exception + * 7-6 -> Precision Control + * 5-4 -> Rounding Control + * 3-0 -> zero (read as 0, write as 0) + * + * + * Precision Control: + * 00 - round to extended precision + * 01 - round to single precision + * 10 - round to double precision + * 11 - undefined + * + * Rounding Control: + * 00 - rounding to nearest (RN) + * 01 - rounding toward zero (RZ) + * 10 - rounding (down)toward minus infinity (RM) + * 11 - rounding (up) toward plus infinity (RP) + * + * The hardware default is 0x0000. I choose 0x5400. + */ + +#include + +/* masking of interrupts */ +#define _FPU_MASK_BSUN 0x8000 +#define _FPU_MASK_SNAN 0x4000 +#define _FPU_MASK_OPERR 0x2000 +#define _FPU_MASK_OVFL 0x1000 +#define _FPU_MASK_UNFL 0x0800 +#define _FPU_MASK_DZ 0x0400 +#define _FPU_MASK_INEX1 0x0200 +#define _FPU_MASK_INEX2 0x0100 + +/* precision control */ +#define _FPU_EXTENDED 0x00 /* RECOMMENDED */ +#define _FPU_DOUBLE 0x80 +#define _FPU_SINGLE 0x40 /* DO NOT USE */ + +/* rounding control */ +#define _FPU_RC_NEAREST 0x00 /* RECOMMENDED */ +#define _FPU_RC_ZERO 0x10 +#define _FPU_RC_DOWN 0x20 +#define _FPU_RC_UP 0x30 + +#define _FPU_RESERVED 0xFFFF000F /* Reserved bits in fpucr */ + + +/* Now two recommended fpucr */ + +/* The fdlibm code requires no interrupts for exceptions. Don't + change the rounding mode, it would break long double I/O! */ +#define _FPU_DEFAULT 0x00000000 + +/* IEEE: same as above, but exceptions. We must make it non-zero so + that __setfpucw works. This bit will be ignored. */ +#define _FPU_IEEE 0x00000001 + +/* Type of the control word. */ +typedef unsigned int fpu_control_t __attribute__ ((__mode__ (__SI__))); + +/* Macros for accessing the hardware control word. */ +#define _FPU_GETCW(cw) __asm__ ("fmove%.l %!, %0" : "=dm" (cw)) +#define _FPU_SETCW(cw) __asm__ __volatile__ ("fmove%.l %0, %!" : : "dm" (cw)) + +#if 0 +/* Default control word set at startup. */ +extern fpu_control_t __fpu_control; +#endif + +#endif /* _M68K_FPU_CONTROL_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/m68k_pic.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/m68k_pic.S new file mode 100644 index 00000000..d41509ec --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/m68k_pic.S @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2006 CodeSourcery Inc + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * This file defines some m68k assembly macros for handling the differences + * between PIC and non-PIC. + */ +#include + + /* When assembling code for shared flat libraries, this is nonzero + * if %a5 points the current library's GOT. */ + .equ have_current_got, 0 + + /* Perform the equivalent of " ", where is + * a text address. is available as a temporary address + * register. */ + .macro DO_TEXT op,target,tmp +#if defined __UCLIBC_FORMAT_SHARED_FLAT__ + .ifne have_current_got + move.l \target@GOT(%a5),\tmp + .else + move.l _current_shared_library_a5_offset_(%a5),\tmp + move.l \target@GOT(\tmp),\tmp + .endif + \op (\tmp) +#elif defined __PIC__ + lea \target-.-8,\tmp + \op (%pc,\tmp) +#else + \op \target +#endif + .endm + + /* Do "pea " when is a text address. + * is available as a temporary register. */ + .macro PEA_TEXT target,tmp + DO_TEXT pea,\target,\tmp + .endm + + /* Likewise jsr. */ + .macro CALL target,tmp + DO_TEXT jsr,\target,\tmp + .endm + + /* Likewise jmp. */ + .macro JUMP target,tmp + DO_TEXT jmp,\target,\tmp + .endm + + /* Initialize the global pointer, if functions need to do that. */ + .macro INIT_GP +#if defined __UCLIBC_FORMAT_SHARED_FLAT__ + move.l %a5,-(%sp) + move.l _current_shared_library_a5_offset_(%a5),%a5 +#endif + .endm + + /* Undo the effects of INIT_GP. */ + .macro FINI_GP +#if defined __UCLIBC_FORMAT_SHARED_FLAT__ + move.l (%sp)+,%a5 +#endif + .endm diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/setjmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/setjmp.S new file mode 100644 index 00000000..4adda0af --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/setjmp.S @@ -0,0 +1,23 @@ + +/* Copyright (C) 2002, David McCullough */ +/* This file is released under the LGPL, any version you like */ + +#define _ASM +#define _SETJMP_H +#include +#include "m68k_pic.S" + +.globl __sigsetjmp; +.type __sigsetjmp,@function +.align 4; + +__sigsetjmp: + moveal %sp@(4), %a0 + movel %sp@(0), %a0@(JB_PC) + moveml %d2-%d7/%a2-%a7, %a0@(JB_REGS) +#if defined(__HAVE_68881__) || defined(__HAVE_FPU__) + fmovemx %fp2-%fp7, %a0@(JB_FPREGS) +#endif + clrl %d0 + JUMP __sigjmp_save,%a0 + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/sys/procfs.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/sys/procfs.h new file mode 100644 index 00000000..27abf8ef --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/sys/procfs.h @@ -0,0 +1,126 @@ +/* Copyright (C) 1996, 1997, 1999, 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_PROCFS_H +#define _SYS_PROCFS_H 1 + +/* This is somewhat modelled after the file of the same name on SVR4 + systems. It provides a definition of the core file format for ELF + used on Linux. It doesn't have anything to do with the /proc file + system, even though Linux has one. + + Anyway, the whole purpose of this file is for GDB and GDB only. + Don't read too much into it. Don't use it for anything other than + GDB unless you know what you are doing. */ + +#include +#include +#include +#include + +__BEGIN_DECLS + +/* Type for a general-purpose register. */ +typedef unsigned long elf_greg_t; + +/* And the whole bunch of them. We could have used `struct + user_regs_struct' directly in the typedef, but tradition says that + the register set is an array, which does have some peculiar + semantics, so leave it that way. */ +#define ELF_NGREG (sizeof (struct user_regs_struct) / sizeof(elf_greg_t)) +typedef elf_greg_t elf_gregset_t[ELF_NGREG]; + +/* Register set for the floating-point registers. */ +typedef struct user_m68kfp_struct elf_fpregset_t; + + +/* Signal info. */ +struct elf_siginfo + { + int si_signo; /* Signal number. */ + int si_code; /* Extra code. */ + int si_errno; /* Errno. */ + }; + + +/* Definitions to generate Intel SVR4-like core files. These mostly + have the same names as the SVR4 types with "elf_" tacked on the + front to prevent clashes with Linux definitions, and the typedef + forms have been avoided. This is mostly like the SVR4 structure, + but more Linuxy, with things that Linux does not support and which + GDB doesn't really use excluded. */ + +struct elf_prstatus + { + struct elf_siginfo pr_info; /* Info associated with signal. */ + short int pr_cursig; /* Current signal. */ + unsigned long int pr_sigpend; /* Set of pending signals. */ + unsigned long int pr_sighold; /* Set of held signals. */ + __pid_t pr_pid; + __pid_t pr_ppid; + __pid_t pr_pgrp; + __pid_t pr_sid; + struct timeval pr_utime; /* User time. */ + struct timeval pr_stime; /* System time. */ + struct timeval pr_cutime; /* Cumulative user time. */ + struct timeval pr_cstime; /* Cumulative system time. */ + elf_gregset_t pr_reg; /* GP registers. */ + int pr_fpvalid; /* True if math copro being used. */ + }; + + +#define ELF_PRARGSZ (80) /* Number of chars for args. */ + +struct elf_prpsinfo + { + char pr_state; /* Numeric process state. */ + char pr_sname; /* Char for pr_state. */ + char pr_zomb; /* Zombie. */ + char pr_nice; /* Nice val. */ + unsigned long int pr_flag; /* Flags. */ + unsigned short int pr_uid; + unsigned short int pr_gid; + int pr_pid, pr_ppid, pr_pgrp, pr_sid; + /* Lots missing */ + char pr_fname[16]; /* Filename of executable. */ + char pr_psargs[ELF_PRARGSZ]; /* Initial part of arg list. */ + }; + + +/* The rest of this file provides the types for emulation of the + Solaris interfaces that should be implemented by + users of libthread_db. */ + +/* Addresses. */ +typedef void *psaddr_t; + +/* Register sets. Linux has different names. */ +typedef elf_gregset_t prgregset_t; +typedef elf_fpregset_t prfpregset_t; + +/* We don't have any differences between processes and threads, + therefore have only one PID type. */ +typedef __pid_t lwpid_t; + +/* Process status and info. In the end we do provide typedefs for them. */ +typedef struct elf_prstatus prstatus_t; +typedef struct elf_prpsinfo prpsinfo_t; + +__END_DECLS + +#endif /* sys/procfs.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/sys/reg.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/sys/reg.h new file mode 100644 index 00000000..418f8323 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/sys/reg.h @@ -0,0 +1,89 @@ +/* Copyright (C) 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_REG_H +#define _SYS_REG_H 1 + +/* Index into an array of 4 byte integers returned from ptrace for + location of the users' stored general purpose registers. */ + +enum +{ + PT_D1 = 0, +#define PT_D1 PT_D1 + PT_D2 = 1, +#define PT_D2 PT_D2 + PT_D3 = 2, +#define PT_D3 PT_D3 + PT_D4 = 3, +#define PT_D4 PT_D4 + PT_D5 = 4, +#define PT_D5 PT_D5 + PT_D6 = 5, +#define PT_D6 PT_D6 + PT_D7 = 6, +#define PT_D7 PT_D7 + PT_A0 = 7, +#define PT_A0 PT_A0 + PT_A1 = 8, +#define PT_A1 PT_A1 + PT_A2 = 9, +#define PT_A2 PT_A2 + PT_A3 = 10, +#define PT_A3 PT_A3 + PT_A4 = 11, +#define PT_A4 PT_A4 + PT_A5 = 12, +#define PT_A5 PT_A5 + PT_A6 = 13, +#define PT_A6 PT_A6 + PT_D0 = 14, +#define PT_D0 PT_D0 + PT_USP = 15, +#define PT_USP PT_USP + PT_ORIG_D0 = 16, +#define PT_ORIG_D0 PT_ORIG_D0 + PT_SR = 17, +#define PT_SR PT_SR + PT_PC = 18, +#define PT_PC PT_PC + PT_FP0 = 21, +#define PT_FP0 PT_FP0 + PT_FP1 = 24, +#define PT_FP1 PT_FP1 + PT_FP2 = 27, +#define PT_FP2 PT_FP2 + PT_FP3 = 30, +#define PT_FP3 PT_FP3 + PT_FP4 = 33, +#define PT_FP4 PT_FP4 + PT_FP5 = 36, +#define PT_FP5 PT_FP5 + PT_FP6 = 39, +#define PT_FP6 PT_FP6 + PT_FP7 = 42, +#define PT_FP7 PT_FP7 + PT_FPCR = 45, +#define PT_FPCR PT_FPCR + PT_FPSR = 46, +#define PT_FPSR PT_FPSR + PT_FPIAR = 47 +#define PT_FPIAR PT_FPIAR +}; + +#endif /* _SYS_REG_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/sys/ucontext.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/sys/ucontext.h new file mode 100644 index 00000000..3c441dc5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/sys/ucontext.h @@ -0,0 +1,109 @@ +/* Copyright (C) 1997, 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* System V/m68k ABI compliant context switching support. */ + +#ifndef _SYS_UCONTEXT_H +#define _SYS_UCONTEXT_H 1 + +#include +#include + +/* Type for general register. */ +typedef int greg_t; + +/* Number of general registers. */ +#define NGREG 18 + +/* Container for all general registers. */ +typedef greg_t gregset_t[NGREG]; + +/* Number of each register is the `gregset_t' array. */ +enum +{ + R_D0 = 0, +#define R_D0 R_D0 + R_D1 = 1, +#define R_D1 R_D1 + R_D2 = 2, +#define R_D2 R_D2 + R_D3 = 3, +#define R_D3 R_D3 + R_D4 = 4, +#define R_D4 R_D4 + R_D5 = 5, +#define R_D5 R_D5 + R_D6 = 6, +#define R_D6 R_D6 + R_D7 = 7, +#define R_D7 R_D7 + R_A0 = 8, +#define R_A0 R_A0 + R_A1 = 9, +#define R_A1 R_A1 + R_A2 = 10, +#define R_A2 R_A2 + R_A3 = 11, +#define R_A3 R_A3 + R_A4 = 12, +#define R_A4 R_A4 + R_A5 = 13, +#define R_A5 R_A5 + R_A6 = 14, +#define R_A6 R_A6 + R_A7 = 15, +#define R_A7 R_A7 + R_SP = 15, +#define R_SP R_SP + R_PC = 16, +#define R_PC R_PC + R_PS = 17 +#define R_PS R_PS +}; + +/* Structure to describe FPU registers. */ +typedef struct fpregset +{ + int f_fpregs[8][3]; + int f_pcr; + int f_psr; + int f_fpiaddr; +} fpregset_t; + +/* Context to describe whole processor state. */ +typedef struct +{ + int version; + gregset_t gregs; + fpregset_t fpregs; +} mcontext_t; + +#define MCONTEXT_VERSION 2 + +/* Userlevel context. */ +typedef struct ucontext +{ + unsigned long int uc_flags; + struct ucontext *uc_link; + __sigset_t uc_sigmask; + stack_t uc_stack; + mcontext_t uc_mcontext; + long int uc_filler[174]; +} ucontext_t; + +#endif /* sys/ucontext.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/sys/user.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/sys/user.h new file mode 100644 index 00000000..8114a2bd --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/sys/user.h @@ -0,0 +1,90 @@ +#ifndef _M68K_USER_H +#define _M68K_USER_H +/* + This file was taken verbatim from linux-2.6.26.5. + The linux kernel is Copyright (C) Linus Torvalds et al. + and is licensed under the GNU General Public License, version 2. +*/ +/* Core file format: The core file is written in such a way that gdb + can understand it and provide useful information to the user (under + linux we use the 'trad-core' bfd). There are quite a number of + obstacles to being able to view the contents of the floating point + registers, and until these are solved you will not be able to view the + contents of them. Actually, you can read in the core file and look at + the contents of the user struct to find out what the floating point + registers contain. + The actual file contents are as follows: + UPAGE: 1 page consisting of a user struct that tells gdb what is present + in the file. Directly after this is a copy of the task_struct, which + is currently not used by gdb, but it may come in useful at some point. + All of the registers are stored as part of the upage. The upage should + always be only one page. + DATA: The data area is stored. We use current->end_text to + current->brk to pick up all of the user variables, plus any memory + that may have been malloced. No attempt is made to determine if a page + is demand-zero or if a page is totally unused, we just cover the entire + range. All of the addresses are rounded in such a way that an integral + number of pages is written. + STACK: We need the stack information in order to get a meaningful + backtrace. We need to write the data from (esp) to + current->start_stack, so we round each of these off in order to be able + to write an integer number of pages. + The minimum core file size is 3 pages, or 12288 bytes. +*/ + +struct user_m68kfp_struct { + unsigned long fpregs[8*3]; /* fp0-fp7 registers */ + unsigned long fpcntl[3]; /* fp control regs */ +}; + +/* This is the old layout of "struct pt_regs" as of Linux 1.x, and + is still the layout used by user (the new pt_regs doesn't have + all registers). */ +struct user_regs_struct { + long d1,d2,d3,d4,d5,d6,d7; + long a0,a1,a2,a3,a4,a5,a6; + long d0; + long usp; + long orig_d0; + short stkadj; + short sr; + long pc; + short fmtvec; + short __fill; +}; + + +/* When the kernel dumps core, it starts by dumping the user struct - + this will be used by gdb to figure out where the data and stack segments + are within the file, and what virtual addresses to use. */ +struct user{ +/* We start with the registers, to mimic the way that "memory" is returned + from the ptrace(3,...) function. */ + struct user_regs_struct regs; /* Where the registers are actually stored */ +/* ptrace does not yet supply these. Someday.... */ + int u_fpvalid; /* True if math co-processor being used. */ + /* for this mess. Not yet used. */ + struct user_m68kfp_struct m68kfp; /* Math Co-processor registers. */ +/* The rest of this junk is to help gdb figure out what goes where */ + unsigned long int u_tsize; /* Text segment size (pages). */ + unsigned long int u_dsize; /* Data segment size (pages). */ + unsigned long int u_ssize; /* Stack segment size (pages). */ + unsigned long start_code; /* Starting virtual address of text. */ + unsigned long start_stack; /* Starting virtual address of stack area. + This is actually the bottom of the stack, + the top of the stack is always found in the + esp register. */ + long int signal; /* Signal that caused the core dump. */ + int reserved; /* No longer used */ + unsigned long u_ar0; /* Used by gdb to help find the values for */ + /* the registers. */ + struct user_m68kfp_struct* u_fpstate; /* Math Co-processor pointer. */ + unsigned long magic; /* To uniquely identify a core file */ + char u_comm[32]; /* User command that was responsible */ +}; +#define NBPG 4096 +#define UPAGES 1 +#define HOST_TEXT_START_ADDR (u.start_code) +#define HOST_STACK_END_ADDR (u.start_stack + u.u_ssize * NBPG) + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/vfork.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/vfork.S new file mode 100644 index 00000000..56d57f73 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/m68k/vfork.S @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +#include + +#ifndef __NR_vfork +#define __NR_vfork __NR_fork /* uClinux-2.0 only has fork which is vfork */ +#endif + +#define IMM # + + .text + .align 2 + .globl errno + .globl __vfork + .hidden __vfork + .type __vfork,@function + +__vfork: + movl %sp@+, %a1 /* save the return address for later */ + movl IMM __NR_vfork,%d0 + trap #0 + movl IMM -4097, %d1 + cmpl %d0, %d1 + bcs fix_errno + jmp %a1@ /* don't return, just jmp directly */ +fix_errno: + negl %d0 +#ifndef __PIC__ /* needs handling as the other archs */ + movl errno, %a0 +#else + movl errno@GOT(%a5), %a0 +#endif + movl %d0, %a0@ + movl IMM -1, %d0 + jmp %a1@ /* don't return, just jmp directly */ + +.size __vfork,.-__vfork +weak_alias(__vfork,vfork) +libc_hidden_weak(vfork) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/Makefile new file mode 100644 index 00000000..338abc08 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/Makefile @@ -0,0 +1,25 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2003 Erik Andersen +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU Library General Public License as published by the Free +# Software Foundation; either version 2 of the License, or (at your option) any +# later version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more +# details. +# +# You should have received a copy of the GNU Library General Public License +# along with this program; if not, write to the Free Software Foundation, Inc., +# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +top_srcdir=../../../../ +top_builddir=../../../../ +all: objs + +include $(top_builddir)Rules.mak +include Makefile.arch +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/Makefile.arch b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/Makefile.arch new file mode 100644 index 00000000..ecbd8014 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/Makefile.arch @@ -0,0 +1,14 @@ +# Makefile for uClibc +# +# Copyright (C) 2001,2002 NEC Corporation +# Copyright (C) 2001,2002 Miles Bader +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + +CSRC := mmap.c clone.c fixdfsi.c + +SSRC := setjmp.S __longjmp.S vfork.S + +ARCH_HEADERS := floatlib.h + +include $(top_srcdir)libc/sysdeps/linux/Makefile.commonarch diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/__longjmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/__longjmp.S new file mode 100644 index 00000000..c4423bec --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/__longjmp.S @@ -0,0 +1,49 @@ +/* + * libc/sysdeps/linux/microblaze/longjmp.S -- `longjmp' for microblaze + * + * Copyright (C) 2003 John Williams + * Copyright (C) 2001 NEC Corporation + * Copyright (C) 2001 Miles Bader + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + * + * Written by Miles Bader + */ + +#define _SETJMP_H +#define _ASM +#include + +#include + + .text + .globl C_SYMBOL_NAME(__longjmp) + .align 4 +C_SYMBOL_NAME(__longjmp): + /* load registers from memory to r5 (arg0) */ + lwi r1, r5, 0 + lwi r15, r5, 4 + lwi r2, r5, 8 + lwi r13, r5, 12 + lwi r18, r5, 16 + lwi r19, r5, 20 + lwi r20, r5, 24 + lwi r21, r5, 28 + lwi r22, r5, 32 + lwi r23, r5, 36 + lwi r24, r5, 40 + lwi r25, r5, 44 + lwi r26, r5, 48 + lwi r27, r5, 52 + lwi r28, r5, 56 + lwi r29, r5, 60 + lwi r30, r5, 64 + lwi r31, r5, 68 + + addi r3, r0, 1 /* return val */ + rtsd r15, 8 /* normal return */ + nop + +libc_hidden_def(__longjmp) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/bits/endian.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/bits/endian.h new file mode 100644 index 00000000..8a4f6efc --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/bits/endian.h @@ -0,0 +1,20 @@ +/* + * libc/sysdeps/linux/microblaze/bits/endian.h -- Define processor endianess + * + * Copyright (C) 2003 John Williams + * Copyright (C) 2001 NEC Corporation + * Copyright (C) 2001 Miles Bader + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + * + * Written by Miles Bader + * Microblaze port by John Williams + */ + +#ifndef _ENDIAN_H +# error "Never use directly; include instead." +#endif + +#define __BYTE_ORDER __BIG_ENDIAN diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/bits/fcntl.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/bits/fcntl.h new file mode 100644 index 00000000..44e8f3f5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/bits/fcntl.h @@ -0,0 +1,240 @@ +/* O_*, F_*, FD_* bit values for Linux. + Copyright (C) 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FCNTL_H +# error "Never use directly; include instead." +#endif + + +#include +#ifdef __USE_GNU +# include +#endif + +/* open/fcntl - O_SYNC is only implemented on blocks devices and on files + located on an ext2 file system */ +#define O_ACCMODE 0003 +#define O_RDONLY 00 +#define O_WRONLY 01 +#define O_RDWR 02 +#define O_CREAT 0100 /* not fcntl */ +#define O_EXCL 0200 /* not fcntl */ +#define O_NOCTTY 0400 /* not fcntl */ +#define O_TRUNC 01000 /* not fcntl */ +#define O_APPEND 02000 +#define O_NONBLOCK 04000 +#define O_NDELAY O_NONBLOCK +#define O_SYNC 010000 +#define O_FSYNC O_SYNC +#define O_ASYNC 020000 + +#ifdef __USE_GNU +# define O_DIRECTORY 0200000 /* Must be a directory. */ +# define O_NOFOLLOW 0400000 /* Do not follow links. */ +# define O_DIRECT 040000 /* Direct disk access. */ +# define O_NOATIME 01000000 /* Do not set atime. */ +# define O_CLOEXEC 02000000 /* set close_on_exec */ +#endif + +/* For now Linux has synchronisity options for data and read operations. + We define the symbols here but let them do the same as O_SYNC since + this is a superset. */ +#if defined __USE_POSIX199309 || defined __USE_UNIX98 +# define O_DSYNC O_SYNC /* Synchronize data. */ +# define O_RSYNC O_SYNC /* Synchronize read operations. */ +#endif + +#ifdef __USE_LARGEFILE64 +# define O_LARGEFILE 0100000 +#endif + +/* Values for the second argument to `fcntl'. */ +#define F_DUPFD 0 /* Duplicate file descriptor. */ +#define F_GETFD 1 /* Get file descriptor flags. */ +#define F_SETFD 2 /* Set file descriptor flags. */ +#define F_GETFL 3 /* Get file status flags. */ +#define F_SETFL 4 /* Set file status flags. */ +#ifndef __USE_FILE_OFFSET64 +# define F_GETLK 5 /* Get record locking info. */ +# define F_SETLK 6 /* Set record locking info (non-blocking). */ +# define F_SETLKW 7 /* Set record locking info (blocking). */ +#else +# define F_GETLK F_GETLK64 /* Get record locking info. */ +# define F_SETLK F_SETLK64 /* Set record locking info (non-blocking).*/ +# define F_SETLKW F_SETLKW64 /* Set record locking info (blocking). */ +#endif +#define F_GETLK64 12 /* Get record locking info. */ +#define F_SETLK64 13 /* Set record locking info (non-blocking). */ +#define F_SETLKW64 14 /* Set record locking info (blocking). */ + +#if defined __USE_BSD || defined __USE_XOPEN2K +# define F_SETOWN 8 /* Get owner of socket (receiver of SIGIO). */ +# define F_GETOWN 9 /* Set owner of socket (receiver of SIGIO). */ +#endif + +#ifdef __USE_GNU +# define F_SETSIG 10 /* Set number of signal to be sent. */ +# define F_GETSIG 11 /* Get number of signal to be sent. */ +#endif + +#ifdef __USE_GNU +# define F_SETLEASE 1024 /* Set a lease. */ +# define F_GETLEASE 1025 /* Enquire what lease is active. */ +# define F_NOTIFY 1026 /* Request notfications on a directory. */ +# define F_DUPFD_CLOEXEC 1030 /* Duplicate file descriptor with + close-on-exit set on new fd. */ +# define F_SETPIPE_SZ 1031 /* Set of pipe page size array */ +# define F_GETPIPE_SZ 1032 /* Get of pipe page size array */ +#endif + +/* For F_[GET|SET]FL. */ +#define FD_CLOEXEC 1 /* actually anything with low bit set goes */ + +/* For posix fcntl() and `l_type' field of a `struct flock' for lockf(). */ +#define F_RDLCK 0 /* Read lock. */ +#define F_WRLCK 1 /* Write lock. */ +#define F_UNLCK 2 /* Remove lock. */ + +/* For old implementation of bsd flock(). */ +#define F_EXLCK 4 /* or 3 */ +#define F_SHLCK 8 /* or 4 */ + +#ifdef __USE_BSD +/* Operations for bsd flock(), also used by the kernel implementation. */ +# define LOCK_SH 1 /* shared lock */ +# define LOCK_EX 2 /* exclusive lock */ +# define LOCK_NB 4 /* or'd with one of the above to prevent + blocking */ +# define LOCK_UN 8 /* remove lock */ +#endif + +#ifdef __USE_GNU +# define LOCK_MAND 32 /* This is a mandatory flock: */ +# define LOCK_READ 64 /* ... which allows concurrent read operations. */ +# define LOCK_WRITE 128 /* ... which allows concurrent write operations. */ +# define LOCK_RW 192 /* ... Which allows concurrent read & write operations. */ +#endif + +#ifdef __USE_GNU +/* Types of directory notifications that may be requested with F_NOTIFY. */ +# define DN_ACCESS 0x00000001 /* File accessed. */ +# define DN_MODIFY 0x00000002 /* File modified. */ +# define DN_CREATE 0x00000004 /* File created. */ +# define DN_DELETE 0x00000008 /* File removed. */ +# define DN_RENAME 0x00000010 /* File renamed. */ +# define DN_ATTRIB 0x00000020 /* File changed attibutes. */ +# define DN_MULTISHOT 0x80000000 /* Don't remove notifier. */ +#endif + +struct flock + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ +#ifndef __USE_FILE_OFFSET64 + __off_t l_start; /* Offset where the lock begins. */ + __off_t l_len; /* Size of the locked area; zero means until EOF. */ +#else + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ +#endif + __pid_t l_pid; /* Process holding the lock. */ + }; + +#ifdef __USE_LARGEFILE64 +struct flock64 + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ + __pid_t l_pid; /* Process holding the lock. */ + }; +#endif + +/* Define some more compatibility macros to be backward compatible with + BSD systems which did not managed to hide these kernel macros. */ +#ifdef __USE_BSD +# define FAPPEND O_APPEND +# define FFSYNC O_FSYNC +# define FASYNC O_ASYNC +# define FNONBLOCK O_NONBLOCK +# define FNDELAY O_NDELAY +#endif /* Use BSD. */ + +/* Advise to `posix_fadvise'. */ +#ifdef __USE_XOPEN2K +# define POSIX_FADV_NORMAL 0 /* No further special treatment. */ +# define POSIX_FADV_RANDOM 1 /* Expect random page references. */ +# define POSIX_FADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define POSIX_FADV_WILLNEED 3 /* Will need these pages. */ +# define POSIX_FADV_DONTNEED 4 /* Don't need these pages. */ +# define POSIX_FADV_NOREUSE 5 /* Data will be accessed once. */ +#endif + + +#if defined __USE_GNU && defined __UCLIBC_LINUX_SPECIFIC__ +/* Flags for SYNC_FILE_RANGE. */ +# define SYNC_FILE_RANGE_WAIT_BEFORE 1 /* Wait upon writeout of all pages + in the range before performing the + write. */ +# define SYNC_FILE_RANGE_WRITE 2 /* Initiate writeout of all those + dirty pages in the range which are + not presently under writeback. */ +# define SYNC_FILE_RANGE_WAIT_AFTER 4 /* Wait upon writeout of all pages in + the range after performing the + write. */ + +/* Flags for SPLICE and VMSPLICE. */ +# define SPLICE_F_MOVE 1 /* Move pages instead of copying. */ +# define SPLICE_F_NONBLOCK 2 /* Don't block on the pipe splicing + (but we may still block on the fd + we splice from/to). */ +# define SPLICE_F_MORE 4 /* Expect more data. */ +# define SPLICE_F_GIFT 8 /* Pages passed in are a gift. */ +#endif + +__BEGIN_DECLS + +#if defined __USE_GNU && defined __UCLIBC_LINUX_SPECIFIC__ + +/* Provide kernel hint to read ahead. */ +extern ssize_t readahead (int __fd, __off64_t __offset, size_t __count) + __THROW; + + +/* Selective file content synch'ing. */ +extern int sync_file_range (int __fd, __off64_t __from, __off64_t __to, + unsigned int __flags); + +/* Splice address range into a pipe. */ +extern ssize_t vmsplice (int __fdout, const struct iovec *__iov, + size_t __count, unsigned int __flags); + +/* Splice two files together. */ +extern ssize_t splice (int __fdin, __off64_t *__offin, int __fdout, + __off64_t *__offout, size_t __len, + unsigned int __flags); + +/* In-kernel implementation of tee for pipe buffers. */ +extern ssize_t tee (int __fdin, int __fdout, size_t __len, + unsigned int __flags); + +#endif +__END_DECLS + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/bits/kernel_stat.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/bits/kernel_stat.h new file mode 100644 index 00000000..2c5eb28a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/bits/kernel_stat.h @@ -0,0 +1,52 @@ +/* Stat structure for linux/microblaze*/ + +#ifndef _BITS_STAT_STRUCT_H +#define _BITS_STAT_STRUCT_H + +#ifndef _LIBC +#error bits/kernel_stat.h is for internal uClibc use only! +#endif + +struct kernel_stat +{ + unsigned long st_dev; /* Device. */ + unsigned long st_ino; /* File serial number. */ + unsigned int st_mode; /* File mode. */ + unsigned int st_nlink; /* Link count. */ + unsigned int st_uid; /* User ID of the file's owner. */ + unsigned int st_gid; /* Group ID of the file's group. */ + unsigned long st_rdev; /* Device number, if device. */ + unsigned long __pad1; + long st_size; /* Size of file, in bytes. */ + int st_blksize; /* Optimal block size for I/O. */ + int __pad2; + long st_blocks; /* Number 512-byte blocks allocated. */ + struct timespec st_atim; + struct timespec st_mtim; + struct timespec st_ctim; + unsigned int __unused4; + unsigned int __unused5; +}; + +struct kernel_stat64 +{ + unsigned long long st_dev; /* Device. */ + unsigned long long st_ino; /* File serial number. */ + unsigned int st_mode; /* File mode. */ + unsigned int st_nlink; /* Link count. */ + unsigned int st_uid; /* User ID of the file's owner. */ + unsigned int st_gid; /* Group ID of the file's group. */ + unsigned long long st_rdev; /* Device number, if device. */ + unsigned long long __pad1; + long long st_size; /* Size of file, in bytes. */ + int st_blksize; /* Optimal block size for I/O. */ + int __pad2; + long long st_blocks; /* Number 512-byte blocks allocated. */ + struct timespec st_atim; + struct timespec st_mtim; + struct timespec st_ctim; + unsigned int __unused4; + unsigned int __unused5; +}; + +#endif /* _BITS_STAT_STRUCT_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/bits/kernel_types.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/bits/kernel_types.h new file mode 100644 index 00000000..2a705750 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/bits/kernel_types.h @@ -0,0 +1,60 @@ +/* + * sysdeps/linux/microblaze/bits/kernel_types.h -- Kernel versions of standard types + * + * Copyright (C) 2003 John Williams + * Copyright (C) 2001,2002 NEC Corporation + * Copyright (C) 2001,2002 Miles Bader + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + * + * Written by Miles Bader + * Microblaze port by John Williams + */ + +#ifndef _ASM_MICROBLAZE_POSIX_TYPES_H +#define _ASM_MICROBLAZE_POSIX_TYPES_H + +typedef unsigned long __kernel_dev_t; +typedef unsigned long __kernel_ino_t; +//typedef unsigned long long __kernel_ino64_t; +typedef unsigned short __kernel_mode_t; +typedef unsigned long __kernel_nlink_t; +typedef long __kernel_off_t; +typedef int __kernel_pid_t; +typedef int __kernel_ipc_pid_t; +typedef unsigned int __kernel_uid_t; +typedef unsigned int __kernel_gid_t; +typedef unsigned int __kernel_size_t; +typedef int __kernel_ssize_t; +typedef int __kernel_ptrdiff_t; +typedef long __kernel_time_t; +typedef long __kernel_suseconds_t; +typedef long __kernel_clock_t; +typedef int __kernel_timer_t; +typedef int __kernel_clockid_t; +typedef int __kernel_daddr_t; +typedef char * __kernel_caddr_t; +typedef unsigned short __kernel_uid16_t; +typedef unsigned short __kernel_gid16_t; +typedef unsigned int __kernel_uid32_t; +typedef unsigned int __kernel_gid32_t; + +typedef unsigned int __kernel_old_uid_t; +typedef unsigned int __kernel_old_gid_t; +typedef unsigned int __kernel_old_dev_t; + +#ifdef __GNUC__ +typedef long long __kernel_loff_t; +#endif + +typedef struct { +#ifdef __USE_ALL + int val[2]; +#else + int __val[2]; +#endif +} __kernel_fsid_t; + +#endif /* _ASM_MICROBLAZE_POSIX_TYPES_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/bits/poll.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/bits/poll.h new file mode 100644 index 00000000..78ee877c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/bits/poll.h @@ -0,0 +1,43 @@ +/* Copyright (C) 1997, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_POLL_H +# error "Never use directly; include instead." +#endif + +/* Event types that can be polled for. These bits may be set in `events' + to indicate the interesting event types; they will appear in `revents' + to indicate the status of the file descriptor. */ +#define POLLIN 0x001 /* There is data to read. */ +#define POLLPRI 0x002 /* There is urgent data to read. */ +#define POLLOUT 0x004 /* Writing now will not block. */ + +#ifdef __USE_XOPEN +/* These values are defined in XPG4.2. */ +# define POLLRDNORM 0x0040 /* Normal data may be read. */ +# define POLLRDBAND 0x0080 /* Priority data may be read. */ +# define POLLWRNORM 0x0100 /* Writing now will not block. */ +# define POLLWRBAND 0x0200 /* Priority data may be written. */ +#endif + +/* Event types always implicitly polled for. These bits need not be set in + `events', but they will appear in `revents' to indicate the status of + the file descriptor. */ +#define POLLERR 0x008 /* Error condition. */ +#define POLLHUP 0x010 /* Hung up. */ +#define POLLNVAL 0x020 /* Invalid polling request. */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/bits/select.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/bits/select.h new file mode 100644 index 00000000..7c787b32 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/bits/select.h @@ -0,0 +1,58 @@ +/* + * include/bits/select.h -- fd_set operations + * + * Copyright (C) 2003 John Williams + * Copyright (C) 2001 NEC Corporation + * Copyright (C) 2001 Miles Bader + * Copyright (C) 1997, 1998 Free Software Foundation, Inc. + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + */ + +#ifndef _SYS_SELECT_H +# error "Never use directly; include instead." +#endif + +#ifdef __GNUC__ + +/* We don't use `memset' because this would require a prototype and + the array isn't too big. */ +#define __FD_ZERO(s) \ + do { \ + unsigned int __i; \ + fd_set *__arr = (s); \ + for (__i = 0; __i < sizeof (fd_set) / sizeof (__fd_mask); ++__i) \ + __FDS_BITS (__arr)[__i] = 0; \ + } while (0) + +#define __FD_SET(fd, s) \ + do { \ + int __fd = (fd); \ + unsigned int *__addr = (unsigned int *)&__FDS_BITS (s); \ + *__addr |= (1 << __fd); \ + } while (0) + +#define __FD_CLR(fd, s) \ + do { \ + int __fd = (fd); \ + unsigned int *__addr = (unsigned int *)&__FDS_BITS (s); \ + *__addr &= ~(1 << __fd); \ + } while (0) + +#define __FD_ISSET(fd, s) \ + ({ \ + int __fd = (fd); \ + unsigned int *__addr = (unsigned int *)&__FDS_BITS (s); \ + int res; \ + res = (*__addr & (1 << fd)) ? 1 : 0; \ + }) + +#else /* !__GNUC__ */ + +#define __FD_SET(d, s) (__FDS_BITS (s)[__FDELT(d)] |= __FDMASK(d)) +#define __FD_CLR(d, s) (__FDS_BITS (s)[__FDELT(d)] &= ~__FDMASK(d)) +#define __FD_ISSET(d, s) ((__FDS_BITS (s)[__FDELT(d)] & __FDMASK(d)) != 0) + +#endif /* __GNUC__ */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/bits/setjmp.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/bits/setjmp.h new file mode 100644 index 00000000..0c0573cd --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/bits/setjmp.h @@ -0,0 +1,47 @@ +/* + * libc/sysdeps/linux/microblaze/bits/setjmp.h -- microblaze version of `jmp_buf' type + * + * Copyright (C) 2003 John Williams + * Copyright (C) 2001 NEC Corporation + * Copyright (C) 2001 Miles Bader + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + * + * Written by Miles Bader + */ + +#ifndef _BITS_SETJMP_H +#define _BITS_SETJMP_H 1 + +#if !defined _SETJMP_H && !defined _PTHREAD_H +# error "Never include directly; use instead." +#endif + +#ifndef _ASM +typedef struct + { + /* Stack pointer. */ + void *__sp; + + /* Link pointer. */ + void *__lp; + + /* SDA pointers */ + void *__SDA; + void *__SDA2; + + /* Callee-saved registers r18-r31. */ + int __regs[14]; + } __jmp_buf[1]; +#endif + +#define JB_SIZE (4 * 18) + +/* Test if longjmp to JMPBUF would unwind the frame + containing a local variable at ADDRESS. */ +#define _JMPBUF_UNWINDS(jmpbuf, address) \ + ((void *) (address) < (void *) (jmpbuf)[0].__sp) + +#endif /* bits/setjmp.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/bits/stackinfo.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/bits/stackinfo.h new file mode 100644 index 00000000..819e8197 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/bits/stackinfo.h @@ -0,0 +1,28 @@ +/* Copyright (C) 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This file contains a bit of information about the stack allocation + of the processor. */ + +#ifndef _STACKINFO_H +#define _STACKINFO_H 1 + +/* On microblaze the stack grows down. */ +#define _STACK_GROWS_DOWN 1 + +#endif /* stackinfo.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/bits/syscalls.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/bits/syscalls.h new file mode 100644 index 00000000..f4bdc452 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/bits/syscalls.h @@ -0,0 +1,57 @@ +#ifndef _BITS_SYSCALLS_H +#define _BITS_SYSCALLS_H +#ifndef _SYSCALL_H +# error "Never use directly; include instead." +#endif + + +#ifndef __ASSEMBLER__ + +#include + +#define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \ + ({ \ + register int __ret __asm__("r3"); \ + register int _scno __asm__("r12") = name; \ + LOAD_ARGS_##nr (args); \ + __asm__ __volatile__("brki r14, 0x8" \ + : "=r" (__ret) \ + : "r"(_scno) ASM_ARGS_##nr \ + : __SYSCALL_CLOBBERS ); \ + __ret; \ + }) + +#define INTERNAL_SYSCALL_ERROR_P(val, err) \ + ((unsigned int)(val) >= 0xfffff001U) + +#define LOAD_ARGS_0() do { } while(0) +#define ASM_ARGS_0 +#define LOAD_ARGS_1(a1) \ + register int _a1 __asm__("r5") = (int)(a1); \ + LOAD_ARGS_0() +#define ASM_ARGS_1 ASM_ARGS_0, "r"(_a1) +#define LOAD_ARGS_2(a1, a2) \ + register int _a2 __asm__("r6") = (int)(a2); \ + LOAD_ARGS_1(a1) +#define ASM_ARGS_2 ASM_ARGS_1, "r"(_a2) +#define LOAD_ARGS_3(a1, a2, a3) \ + register int _a3 __asm__("r7") = (int)(a3); \ + LOAD_ARGS_2(a1, a2) +#define ASM_ARGS_3 ASM_ARGS_2, "r"(_a3) +#define LOAD_ARGS_4(a1, a2, a3, a4) \ + register int _a4 __asm__("r8") = (int)(a4); \ + LOAD_ARGS_3(a1, a2, a3) +#define ASM_ARGS_4 ASM_ARGS_3, "r"(_a4) +#define LOAD_ARGS_5(a1, a2, a3, a4, a5) \ + register int _a5 __asm__("r9") = (int)(a5); \ + LOAD_ARGS_4(a1, a2, a3, a4) +#define ASM_ARGS_5 ASM_ARGS_4, "r"(_a5) +#define LOAD_ARGS_6(a1, a2, a3, a4, a5, a6) \ + register int _a6 __asm__("r10") = (int)(a6); \ + LOAD_ARGS_5(a1, a2, a3, a4, a5) +#define ASM_ARGS_6 ASM_ARGS_5, "r"(_a6) + +#define __SYSCALL_CLOBBERS "r4", "r14", "cc", "memory" + +#endif /* __ASSEMBLER__ */ +#endif /* _BITS_SYSCALLS_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/bits/uClibc_arch_features.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/bits/uClibc_arch_features.h new file mode 100644 index 00000000..86d00084 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/bits/uClibc_arch_features.h @@ -0,0 +1,48 @@ +/* + * Track misc arch-specific features that aren't config options + */ + +#ifndef _BITS_UCLIBC_ARCH_FEATURES_H +#define _BITS_UCLIBC_ARCH_FEATURES_H + +/* instruction used when calling abort() to kill yourself */ +/*#define __UCLIBC_ABORT_INSTRUCTION__ "asm instruction"*/ +#undef __UCLIBC_ABORT_INSTRUCTION__ + +/* can your target use syscall6() for mmap ? */ +#define __UCLIBC_MMAP_HAS_6_ARGS__ + +/* does your target use syscall4() for truncate64 ? (32bit arches only) */ +#undef __UCLIBC_TRUNCATE64_HAS_4_ARGS__ + +/* does your target have a broken create_module() ? */ +#undef __UCLIBC_BROKEN_CREATE_MODULE__ + +/* does your target have to worry about older [gs]etrlimit() ? */ +#undef __UCLIBC_HANDLE_OLDER_RLIMIT__ + +/* does your target have an asm .set ? */ +#undef __UCLIBC_HAVE_ASM_SET_DIRECTIVE__ + +/* define if target doesn't like .global */ +#undef __UCLIBC_ASM_GLOBAL_DIRECTIVE__ + +/* define if target supports .weak */ +#define __UCLIBC_HAVE_ASM_WEAK_DIRECTIVE__ + +/* define if target supports .weakext */ +#undef __UCLIBC_HAVE_ASM_WEAKEXT_DIRECTIVE__ + +/* needed probably only for ppc64 */ +#undef __UCLIBC_HAVE_ASM_GLOBAL_DOT_NAME__ + +/* define if target supports CFI pseudo ops */ +#undef __UCLIBC_HAVE_ASM_CFI_DIRECTIVES__ + +/* define if target supports IEEE signed zero floats */ +#define __UCLIBC_HAVE_SIGNED_ZERO__ + +/* only weird assemblers generally need this */ +#undef __UCLIBC_ASM_LINE_SEP__ + +#endif /* _BITS_UCLIBC_ARCH_FEATURES_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/bits/uClibc_page.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/bits/uClibc_page.h new file mode 100644 index 00000000..8fc81ae3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/bits/uClibc_page.h @@ -0,0 +1,41 @@ +/* Copyright (C) 2004 Erik Andersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* Supply an architecture specific value for PAGE_SIZE and friends. */ + +#ifndef _UCLIBC_PAGE_H +#define _UCLIBC_PAGE_H + +#include + +#if defined(CONFIG_MICROBLAZE_32K_PAGES) +#define PAGE_SHIFT 15 +#elif defined(CONFIG_MICROBLAZE_16K_PAGES) +#define PAGE_SHIFT 14 +#elif defined(CONFIG_MICROBLAZE_8K_PAGES) +#define PAGE_SHIFT 13 +#elif defined(CONFIG_MICROBLAZE_4K_PAGES) +#define PAGE_SHIFT 12 +#else +#warning Missing CONFIG_MICROBLAZE_nnK_PAGES, assuming 4K +#define PAGE_SHIFT 12 +#endif + +#define PAGE_SIZE (1UL << PAGE_SHIFT) +#define PAGE_MASK (~(PAGE_SIZE-1)) + +#endif /* _UCLIBC_PAGE_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/bits/wordsize.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/bits/wordsize.h new file mode 100644 index 00000000..ba643b60 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/bits/wordsize.h @@ -0,0 +1,19 @@ +/* Copyright (C) 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define __WORDSIZE 32 diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/clone.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/clone.c new file mode 100644 index 00000000..d9210086 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/clone.c @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2004 Atmel Corporation + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License. See the file "COPYING.LIB" in the main directory of this + * archive for more details. + */ +#include +#include +#include +#include + +int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg, ...) +{ + int rval = -EINVAL; + if (fn && child_stack) + rval = INTERNAL_SYSCALL(clone, 0, 2, flags, child_stack); + + if (rval == 0) + { + int exitCode = fn(arg); + rval = INTERNAL_SYSCALL(exit, 0, 1, exitCode); + } + + return rval; +} + +#ifdef __NR_clone2 +int +__clone2(int (*fn)(void *arg), void *child_stack, size_t stack_size, + int flags, void *arg, ...) +{ + int rval = -EINVAL; + if (fn && child_stack) + { + rval = INTERNAL_SYSCALL(clone2, 0, 3, flags, child_stack, stack_size); + } + + if (rval == 0) + { + int exitCode = fn(arg); + rval = INTERNAL_SYSCALL(exit, 0, 1, exitCode); + } + + return rval; +} +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/crt0.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/crt0.S new file mode 100644 index 00000000..591c3a2f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/crt0.S @@ -0,0 +1,56 @@ +/* + * libc/sysdeps/linux/microblaze/crt0.S -- Initial program entry point for linux/microblaze + * + * Copyright (C) 2003 John Williams + * Copyright (C) 2001,2002 NEC Corporation + * Copyright (C) 2001,2002 Miles Bader + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + * + * Written by Miles Bader + */ + +#include + +/* Upon entry, the stack contains the following data: + argc, argv[0], ..., argv[argc-1], 0, envp[0], ..., 0 +*/ + + .text +C_ENTRY(_start): + lw r5, r0, r1 /* Arg 0: argc */ + + addi r6, r1, 4 /* Arg 1: argv */ + + /* Arg 2: envp */ + addi r3, r5, 1 /* skip argc elements to get envp start */ + /* ...plus the NULL at the end of argv */ + add r3, r3, r3 /* Make word offset */ + add r3, r3, r3 + add r7, r6, r3 /* add to argv to get offset */ + + /* Load SDAs */ + la r2, r0, C_SYMBOL_NAME(_SDA_BASE_) + la r13, r0, C_SYMBOL_NAME(_SDA2_BASE_) + + /* tail-call uclibc's startup routine */ + brid C_SYMBOL_NAME(__uClibc_main) + nop + + +/* Stick in a dummy reference to `main', so that if an application + is linking when the `main' function is in a static library (.a) + we can be sure that `main' actually gets linked in. */ +L_dummy_main_reference: + .long C_SYMBOL_NAME(main) + +/* Define a symbol for the first piece of initialized data. */ + .data + .globl __data_start +__data_start: + .long 0 + .weak data_start + data_start = __data_start + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/crt1.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/crt1.S new file mode 100644 index 00000000..e9564cfb --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/crt1.S @@ -0,0 +1,61 @@ +/* + * libc/sysdeps/linux/microblaze/crt1.S -- Initial program entry point for linux/microblaze + * + * Copyright (C) 2009 Meyer Sound Laboratories + * Copyright (C) 2003 John Williams + * Copyright (C) 2001,2002 NEC Corporation + * Copyright (C) 2001,2002 Miles Bader + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + * + * Written by Miles Bader + */ + +#include + +/* Upon entry, the stack contains the following data: + argc, argv[0], ..., argv[argc-1], 0, envp[0], ..., 0 +*/ + + .text + .globl C_SYMBOL_NAME(_start) + .align 4 +C_SYMBOL_NAME(_start): + + /* Load SDAs */ + la r2, r0, C_SYMBOL_NAME(_SDA2_BASE_) /* in the original source r2 was SDA, and r13 was SDA2, no idea why */ + la r13, r0, C_SYMBOL_NAME(_SDA_BASE_) + + /* + Preparing arguments for uClibc's startup routine. + The routine has 6 arguments, so 5 of them are placed + into registers, one on the stack + */ + + la r5, r0, C_SYMBOL_NAME(main) /* Arg 1: main() */ + lw r6, r0, r1 /* Arg 2: argc */ + addi r7, r1, 4 /* Arg 3: argv */ + la r8, r0, _init /* Arg 4: init */ + la r9, r0, _fini /* Arg 5: fini */ + addk r10,r0,r0 /* Arg 6: rtld_fini = NULL */ + + + /* Reserve space for __uClibc_main to save parameters + (Microblaze ABI stack calling convention) + and for stack_end argument to __uClibc_main */ + add r3, r1, r0 + addi r1, r1, -32 + + /* tail-call uClibc's startup routine */ + brid C_SYMBOL_NAME(__uClibc_main) + swi r3, r1, 28 /* Arg 7: stack end [DELAY SLOT] */ + +/* Define a symbol for the first piece of initialized data. */ + .data + .globl __data_start +__data_start: + .long 0 + .weak data_start + data_start = __data_start diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/crti.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/crti.S new file mode 100644 index 00000000..e0039689 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/crti.S @@ -0,0 +1,41 @@ +/* + * libc/sysdeps/linux/microblaze/crti.S -- init/fini entry code for microblaze + * (baselined with gcc 4.1.2) + * + * Copyright (C) 2010 Digital Design Corporation + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + */ + +#define END_INIT +#define END_FINI +#define ALIGN +#include + +/*@HEADER_ENDS*/ + + .section .init + .align 2 + .globl _init +_init: + addik r1, r1, -32 + swi r19, r1, 28 + addk r19, r1, r0 + swi r15, r1, 0 + + ALIGN + END_INIT + + .section .fini + .align 2 + .globl _fini +_fini: + addik r1, r1, -32 + swi r19, r1, 28 + addk r19, r1, r0 + swi r15, r1, 0 + + ALIGN + END_FINI diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/crtn.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/crtn.S new file mode 100644 index 00000000..6f4ef60d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/crtn.S @@ -0,0 +1,43 @@ +/* + * libc/sysdeps/linux/microblaze/crtn.S -- init/fini exit code for microblaze + * (baselined with gcc 4.1.2) + * + * Copyright (C) 2010 Digital Design Corporation + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + */ + +#define END_INIT +#define END_FINI +#define ALIGN +#include + + .section .init + .align 2 + .globl _init + .ent _init + + lwi r15, r1, 0 + lwi r19, r1, 28 + rtsd r15, 8 + addik r1, r1, 32 # Delay slot + + .end _init +$Lfe2: + + .section .fini + .align 2 + .globl _fini + .ent _fini + + lwi r15, r1, 0 + lwi r19, r1, 28 + rtsd r15, 8 + addik r1, r1, 32 # Delay slot + + .end _fini +$Lfe3: + +/*@TRAILER_BEGINS*/ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/fixdfsi.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/fixdfsi.c new file mode 100644 index 00000000..1611176a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/fixdfsi.c @@ -0,0 +1,85 @@ +/* +** libgcc support for software floating point. +** Copyright (C) 1991 by Pipeline Associates, Inc. All rights reserved. +** Permission is granted to do *anything* you want with this file, +** commercial or otherwise, provided this message remains intact. So there! +** I would appreciate receiving any updates/patches/changes that anyone +** makes, and am willing to be the repository for said changes (am I +** making a big mistake?). + +Warning! Only single-precision is actually implemented. This file +won't really be much use until double-precision is supported. + +However, once that is done, this file might eventually become a +replacement for libgcc1.c. It might also make possible +cross-compilation for an IEEE target machine from a non-IEEE +host such as a VAX. + +If you'd like to work on completing this, please talk to rms@gnu.ai.mit.edu. + +--> Double precision floating support added by James Carlson on 20 April 1998. + +** +** Pat Wood +** Pipeline Associates, Inc. +** pipeline!phw@motown.com or +** sun!pipeline!phw or +** uunet!motown!pipeline!phw +** +** 05/01/91 -- V1.0 -- first release to gcc mailing lists +** 05/04/91 -- V1.1 -- added float and double prototypes and return values +** -- fixed problems with adding and subtracting zero +** -- fixed rounding in truncdfsf2 +** -- fixed SWAP define and tested on 386 +*/ + +/* +** The following are routines that replace the libgcc soft floating point +** routines that are called automatically when -msoft-float is selected. +** The support single and double precision IEEE format, with provisions +** for byte-swapped machines (tested on 386). Some of the double-precision +** routines work at full precision, but most of the hard ones simply punt +** and call the single precision routines, producing a loss of accuracy. +** long long support is not assumed or included. +** Overall accuracy is close to IEEE (actually 68882) for single-precision +** arithmetic. I think there may still be a 1 in 1000 chance of a bit +** being rounded the wrong way during a multiply. I'm not fussy enough to +** bother with it, but if anyone is, knock yourself out. +** +** Efficiency has only been addressed where it was obvious that something +** would make a big difference. Anyone who wants to do this right for +** best speed should go in and rewrite in assembler. +** +** I have tested this only on a 68030 workstation and 386/ix integrated +** in with -msoft-float. +*/ + +#include "floatlib.h" + +/* convert double to int */ +long +__fixdfsi (double a1) +{ + register union double_long dl1; + register int exp; + register long l; + + dl1.d = a1; + + if (!dl1.l.upper && !dl1.l.lower) + return (0); + + exp = EXPD (dl1) - EXCESSD - 31; + l = MANTD (dl1); + + if (exp > 0) + return SIGND(dl1) ? (1<<31) : ((1ul<<31)-1); + + /* shift down until exp = 0 or l = 0 */ + if (exp < 0 && exp > -32 && l) + l >>= -exp; + else + return (0); + + return (SIGND (dl1) ? -l : l); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/floatlib.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/floatlib.h new file mode 100644 index 00000000..817ba7de --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/floatlib.h @@ -0,0 +1,140 @@ +/* +** libgcc support for software floating point. +** Copyright (C) 1991 by Pipeline Associates, Inc. All rights reserved. +** Permission is granted to do *anything* you want with this file, +** commercial or otherwise, provided this message remains intact. So there! +** I would appreciate receiving any updates/patches/changes that anyone +** makes, and am willing to be the repository for said changes (am I +** making a big mistake?). + +Warning! Only single-precision is actually implemented. This file +won't really be much use until double-precision is supported. + +However, once that is done, this file might eventually become a +replacement for libgcc1.c. It might also make possible +cross-compilation for an IEEE target machine from a non-IEEE +host such as a VAX. + +If you'd like to work on completing this, please talk to rms@gnu.ai.mit.edu. + +--> Double precision floating support added by James Carlson on 20 April 1998. + +** +** Pat Wood +** Pipeline Associates, Inc. +** pipeline!phw@motown.com or +** sun!pipeline!phw or +** uunet!motown!pipeline!phw +** +** 05/01/91 -- V1.0 -- first release to gcc mailing lists +** 05/04/91 -- V1.1 -- added float and double prototypes and return values +** -- fixed problems with adding and subtracting zero +** -- fixed rounding in truncdfsf2 +** -- fixed SWAP define and tested on 386 +*/ + +/* +** The following are routines that replace the libgcc soft floating point +** routines that are called automatically when -msoft-float is selected. +** The support single and double precision IEEE format, with provisions +** for byte-swapped machines (tested on 386). Some of the double-precision +** routines work at full precision, but most of the hard ones simply punt +** and call the single precision routines, producing a loss of accuracy. +** long long support is not assumed or included. +** Overall accuracy is close to IEEE (actually 68882) for single-precision +** arithmetic. I think there may still be a 1 in 1000 chance of a bit +** being rounded the wrong way during a multiply. I'm not fussy enough to +** bother with it, but if anyone is, knock yourself out. +** +** Efficiency has only been addressed where it was obvious that something +** would make a big difference. Anyone who wants to do this right for +** best speed should go in and rewrite in assembler. +** +** I have tested this only on a 68030 workstation and 386/ix integrated +** in with -msoft-float. +*/ + +#ifndef __FLOAT_LIB_H__ +#define __FLOAT_LIB_H__ +/* the following deal with IEEE single-precision numbers */ +#define EXCESS 126 +#define SIGNBIT 0x80000000 +#define HIDDEN (1 << 23) +#define SIGN(fp) ((fp) & SIGNBIT) +#define EXP(fp) (((fp) >> 23) & 0xFF) +#define MANT(fp) (((fp) & 0x7FFFFF) | HIDDEN) +#define PACK(s,e,m) ((s) | ((e) << 23) | (m)) + +/* the following deal with IEEE double-precision numbers */ +#define EXCESSD 1022 +#define HIDDEND (1 << 20) +#define EXPD(fp) (((fp.l.upper) >> 20) & 0x7FF) +#define SIGND(fp) ((fp.l.upper) & SIGNBIT) +#define MANTD(fp) (((((fp.l.upper) & 0xFFFFF) | HIDDEND) << 10) | \ + (fp.l.lower >> 22)) +#define HIDDEND_LL ((long long)1 << 52) +#define MANTD_LL(fp) ((fp.ll & (HIDDEND_LL-1)) | HIDDEND_LL) +#define PACKD_LL(s,e,m) (((long long)((s)+((e)<<20))<<32)|(m)) + +/* define SWAP for 386/960 reverse-byte-order brain-damaged CPUs */ +union double_long { + double d; +#ifdef SWAP + struct { + unsigned long lower; + long upper; + } l; +#else + struct { + long upper; + unsigned long lower; + } l; +#endif + long long ll; +}; + +union float_long + { + float f; + long l; + }; + +#endif + +/* Functions defined in different files */ + +float __addsf3 (float, float); +float __subsf3 (float, float); +long __cmpsf2 (float, float); +float __mulsf3 (float, float); +float __divsf3 (float, float); +double __floatsidf (register long); +double __floatdidf (register long long); +float __floatsisf (register long ); +float __floatdisf (register long long ); +float __negsf2 (float); +double __negdf2 (double); +double __extendsfdf2 (float); +float __truncdfsf2 (double); +long __cmpdf2 (double, double); +long __fixsfsi (float); +long __fixdfsi (double); +long long __fixdfdi (double); +unsigned long __fixunsdfsi (double); +unsigned long long __fixunsdfdi (double); +double __adddf3 (double, double); +double __subdf3 (double, double); +double __muldf3 (double, double); +double __divdf3 (double, double); +int __gtdf2 (double, double); +int __gedf2 (double, double); +int __ltdf2 (double, double); +int __ledf2 (double, double); +int __eqdf2 (double, double); +int __nedf2 (double, double); +int __gtsf2 (float, float); +int __gesf2 (float, float); +int __ltsf2 (float, float); +int __lesf2 (float, float); +int __eqsf2 (float, float); +int __nesf2 (float, float); diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/mmap.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/mmap.c new file mode 100644 index 00000000..41cf6f45 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/mmap.c @@ -0,0 +1,16 @@ +/* Use new style mmap for microblaze */ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include + + +_syscall6 (__ptr_t, mmap, __ptr_t, addr, size_t, len, int, prot, + int, flags, int, fd, __off_t, offset) +libc_hidden_def(mmap) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/setjmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/setjmp.S new file mode 100644 index 00000000..7acb9ea5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/setjmp.S @@ -0,0 +1,56 @@ +/* + * libc/sysdeps/linux/microblaze/setjmp.S -- `setjmp' for microblaze + * + * Copyright (C) 2003 John Williams + * Copyright (C) 2001,2002 NEC Corporation + * Copyright (C) 2001,2002 Miles Bader + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + * + * Written by Miles Bader + */ + +#define _SETJMP_H +#define _ASM +#include + +#include + + .text + .globl C_SYMBOL_NAME(setjmp) + .align 4 +C_SYMBOL_NAME(setjmp): + braid C_SYMBOL_NAME(__sigsetjmp) + addi r6, r0, 1 /* Save the signal mask. */ + + .globl C_SYMBOL_NAME(_setjmp) +C_SYMBOL_NAME(_setjmp): + and r6, r0, r0 /* Don't save the signal mask. */ + + .globl C_SYMBOL_NAME(__sigsetjmp) +C_SYMBOL_NAME(__sigsetjmp): + /* Save registers relative to r5 (arg0)*/ + swi r1, r5, 0 /* stack pointer */ + swi r15, r5, 4 /* link register */ + swi r2, r5, 8 /* SDA and SDA2 ptrs */ + swi r13, r5, 12 + swi r18, r5, 16 /* assembler temp */ + swi r19, r5, 20 /* now call-preserved regs */ + swi r20, r5, 24 + swi r21, r5, 28 + swi r22, r5, 32 + swi r23, r5, 36 + swi r24, r5, 40 + swi r25, r5, 44 + swi r26, r5, 48 + swi r27, r5, 52 + swi r28, r5, 56 + swi r29, r5, 60 + swi r30, r5, 64 + swi r31, r5, 68 + + /* Make a tail call to __sigjmp_save; it takes the same args. */ + braid C_SYMBOL_NAME(__sigjmp_save) + nop diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/sys/procfs.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/sys/procfs.h new file mode 100644 index 00000000..8fb87ef1 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/sys/procfs.h @@ -0,0 +1,145 @@ +/* Copyright (C) 1996, 1997, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_PROCFS_H +#define _SYS_PROCFS_H 1 + +/* This is somewhat modelled after the file of the same name on SVR4 + systems. It provides a definition of the core file format for ELF + used on Linux. It doesn't have anything to do with the /proc file + system, even though Linux has one. + + Anyway, the whole purpose of this file is for GDB and GDB only. + Don't read too much into it. Don't use it for anything other than + GDB unless you know what you are doing. */ + +#include +#include +#include + + +/* Type for a general-purpose register. */ +#ifndef ELF_GREG_T +#define ELF_GREG_T +typedef unsigned long elf_greg_t; +#endif + +/* This is exactly the same as `struct pt_regs' in the kernel. */ +struct elf_gregset +{ + elf_greg_t gpr[32]; /* General purpose registers. */ + + elf_greg_t pc; /* program counter */ + elf_greg_t psw; /* program status word */ + elf_greg_t ear; /* Exception address register */ + elf_greg_t esr; /* Excep[tion Status Register */ + elf_greg_t fsr; /* FPU Status register */ + + elf_greg_t kernel_mode; /* 1 if in `kernel mode', 0 if user mode */ + elf_greg_t single_step; /* 1 if in single step mode */ +}; + +#ifndef ELF_NGREG +#define ELF_NGREG (sizeof (struct elf_gregset) / sizeof(elf_greg_t)) +#endif + +#ifndef ELF_GREGSET_T +#define ELF_GREGSET_T +typedef elf_greg_t elf_gregset_t[ELF_NGREG]; +#endif + +/* Register set for the floating-point registers. */ +#ifndef ELF_FPREGSET_T +#define ELF_FPREGSET_T +typedef elf_greg_t elf_fpregset_t; +#endif + +struct elf_siginfo +{ + int si_signo; /* signal number */ + int si_code; /* extra code */ + int si_errno; /* errno */ +}; + + +/* + * Definitions to generate Intel SVR4-like core files. + * These mostly have the same names as the SVR4 types with "elf_" + * tacked on the front to prevent clashes with linux definitions, + * and the typedef forms have been avoided. This is mostly like + * the SVR4 structure, but more Linuxy, with things that Linux does + * not support and which gdb doesn't really use excluded. + * Fields present but not used are marked with "XXX". + */ +struct elf_prstatus +{ + struct elf_siginfo pr_info; /* Info associated with signal */ + short pr_cursig; /* Current signal */ + unsigned long pr_sigpend; /* Set of pending signals */ + unsigned long pr_sighold; /* Set of held signals */ + __kernel_pid_t pr_pid; + __kernel_pid_t pr_ppid; + __kernel_pid_t pr_pgrp; + __kernel_pid_t pr_sid; + struct timeval pr_utime; /* User time */ + struct timeval pr_stime; /* System time */ + struct timeval pr_cutime; /* Cumulative user time */ + struct timeval pr_cstime; /* Cumulative system time */ + elf_gregset_t pr_reg; /* GP registers */ + int pr_fpvalid; /* True if math co-processor being used. */ +}; + +#define ELF_PRARGSZ (80) /* Number of chars for args */ + +struct elf_prpsinfo +{ + char pr_state; /* numeric process state */ + char pr_sname; /* char for pr_state */ + char pr_zomb; /* zombie */ + char pr_nice; /* nice val */ + unsigned long pr_flag; /* flags */ + __kernel_uid_t pr_uid; + __kernel_gid_t pr_gid; + __kernel_pid_t pr_pid, pr_ppid, pr_pgrp, pr_sid; + /* Lots missing */ + char pr_fname[16]; /* filename of executable */ + char pr_psargs[ELF_PRARGSZ]; /* initial part of arg list */ +}; + + +/* The rest of this file provides the types for emulation of the + Solaris interfaces that should be implemented by + users of libthread_db. */ + +/* Addresses. */ +typedef void *psaddr_t; + +/* Register sets. Linux has different names. */ +typedef elf_gregset_t prgregset_t; +typedef elf_fpregset_t prfpregset_t; + +/* We don't have any differences between processes and threads, + therefore have only one PID type. */ +typedef __kernel_pid_t lwpid_t; + +/* Process status and info. In the end we do provide typedefs for them. */ +typedef struct elf_prstatus prstatus_t; +typedef struct elf_prpsinfo prpsinfo_t; + + +#endif /* sys/procfs.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/sys/ptrace.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/sys/ptrace.h new file mode 100644 index 00000000..26d153ce --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/sys/ptrace.h @@ -0,0 +1,98 @@ +/* `ptrace' debugger support interface. Linux/microblaze version. + Copyright (C) 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_PTRACE_H +#define _SYS_PTRACE_H 1 + +#include + +__BEGIN_DECLS + +/* Type of the REQUEST argument to `ptrace.' */ +enum __ptrace_request +{ + /* Indicate that the process making this request should be traced. + All signals received by this process can be intercepted by its + parent, and its parent can use the other `ptrace' requests. */ + PTRACE_TRACEME = 0, +#define PT_TRACE_ME PTRACE_TRACEME + + /* Return the word in the process's text space at address ADDR. */ + PTRACE_PEEKTEXT = 1, +#define PT_READ_I PTRACE_PEEKTEXT + + /* Return the word in the process's data space at address ADDR. */ + PTRACE_PEEKDATA = 2, +#define PT_READ_D PTRACE_PEEKDATA + + /* Return the word in the process's user area at offset ADDR. */ + PTRACE_PEEKUSER = 3, +#define PT_READ_U PTRACE_PEEKUSER + + /* Write the word DATA into the process's text space at address ADDR. */ + PTRACE_POKETEXT = 4, +#define PT_WRITE_I PTRACE_POKETEXT + + /* Write the word DATA into the process's data space at address ADDR. */ + PTRACE_POKEDATA = 5, +#define PT_WRITE_D PTRACE_POKEDATA + + /* Write the word DATA into the process's user area at offset ADDR. */ + PTRACE_POKEUSER = 6, +#define PT_WRITE_U PTRACE_POKEUSER + + /* Continue the process. */ + PTRACE_CONT = 7, +#define PT_CONTINUE PTRACE_CONT + + /* Kill the process. */ + PTRACE_KILL = 8, +#define PT_KILL PTRACE_KILL + + /* Single step the process. */ + PTRACE_SINGLESTEP = 9, +#define PT_STEP PTRACE_SINGLESTEP + + /* Attach to a process that is already running. */ + PTRACE_ATTACH = 16, +#define PT_ATTACH PTRACE_ATTACH + + /* Detach from a process attached to with PTRACE_ATTACH. */ + PTRACE_DETACH = 17, +#define PT_DETACH PTRACE_DETACH + + /* Continue and stop at the next (return from) syscall. */ + PTRACE_SYSCALL = 24 +#define PT_SYSCALL PTRACE_SYSCALL +}; + +/* Perform process tracing functions. REQUEST is one of the values + above, and determines the action to be taken. + For all requests except PTRACE_TRACEME, PID specifies the process to be + traced. + + PID and the other arguments described above for the various requests should + appear (those that are used for the particular request) as: + pid_t PID, void *ADDR, int DATA, void *ADDR2 + after REQUEST. */ +extern long int ptrace (enum __ptrace_request __request, ...) __THROW; + +__END_DECLS + +#endif /* _SYS_PTRACE_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/sys/ucontext.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/sys/ucontext.h new file mode 100644 index 00000000..07f0933f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/sys/ucontext.h @@ -0,0 +1,41 @@ +/* Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_UCONTEXT_H +#define _SYS_UCONTEXT_H 1 + +#include +#include + +/* We need the signal context definitions even if they are not used + included in . */ +#include + +typedef struct sigcontext mcontext_t; + +/* Userlevel context. */ +typedef struct ucontext + { + unsigned long int uc_flags; + struct ucontext *uc_link; + stack_t uc_stack; + mcontext_t uc_mcontext; + __sigset_t uc_sigmask; + } ucontext_t; + +#endif /* sys/ucontext.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/vfork.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/vfork.S new file mode 100644 index 00000000..c4b4dbf2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/microblaze/vfork.S @@ -0,0 +1,46 @@ +/* + * libc/sysdeps/linux/microblaze/vfork.S -- `vfork' syscall for linux/microblaze + * + * Copyright (C) 2003 John Williams + * Copyright (C) 2001 NEC Corporation + * Copyright (C) 2001 Miles Bader + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + * + * Written by Miles Bader + * Microblaze port by John Williams + */ + +#define _ERRNO_H 1 +#include +#define _SYSCALL_H +#include + +#include + +/* Clone the calling process, but without copying the whole address space. + The calling process is suspended until the new process exits or is + replaced by a call to `execve'. Return -1 for errors, 0 to the new process, + and the process ID of the new process to the old process. */ + +.global C_SYMBOL_NAME(errno) + + .globl __vfork + .align 4 +__vfork: + addi r12, r0, SYS_vfork + brki r14, 0x08; + addi r4, r3, 125 /* minimum err value */ + blti r4, 1f /* is r3 < -125? */ + bri 2f /* normal return */ +1: sub r3, r3, r0 /* r3 = -r3 */ + swi r3, r0, C_SYMBOL_NAME(errno); + /* state restore etc */ +2: rtsd r15, 8 /* error return */ + nop + .size __vfork, .-__vfork + +weak_alias(__vfork,vfork) +libc_hidden_weak(vfork) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/Makefile new file mode 100644 index 00000000..633c91f3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../../ +top_builddir=../../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.arch +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/Makefile.arch b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/Makefile.arch new file mode 100644 index 00000000..8bbc0bc1 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/Makefile.arch @@ -0,0 +1,27 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +CSRC := \ + __longjmp.c brk.c setjmp_aux.c mmap.c \ + cacheflush.c pread_write.c sysmips.c _test_and_set.c \ + readahead.c + +SSRC := bsd-_setjmp.S bsd-setjmp.S setjmp.S syscall.S pipe.S syscall_error.S + +ifeq ($(UCLIBC_HAS_ADVANCED_REALTIME),y) +CSRC += posix_fadvise.c posix_fadvise64.c +endif + +ifneq ($(UCLIBC_HAS_THREADS_NATIVE),y) +CSRC += sigaction.c +SSRC += vfork.S clone.S +endif + +ASFLAGS-syscall_error.S += -D_LIBC_REENTRANT + +ARCH_HEADERS := sgidefs.h +# regdef.h diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/__longjmp.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/__longjmp.c new file mode 100644 index 00000000..9dc09f27 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/__longjmp.c @@ -0,0 +1,128 @@ +/* Copyright (C) 1992, 1995, 1997, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Brendan Kehoe (brendan@zen.org). + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + +#ifndef __GNUC__ + #error This file uses GNU C extensions; you must compile with GCC. +#endif + +extern void __longjmp (__jmp_buf __env, int __val) attribute_noreturn; +libc_hidden_proto(__longjmp) + +void __longjmp (__jmp_buf env, int val_arg) +{ + /* gcc 1.39.19 miscompiled the longjmp routine (as it did setjmp before + the hack around it); force it to use $a1 for the longjmp value. + Without this it saves $a1 in a register which gets clobbered + along the way. */ + register int val __asm__ ("a1"); + + /* Pull back the floating point callee-saved registers. */ +#if defined __UCLIBC_HAS_FLOATS__ && ! defined __UCLIBC_HAS_SOFT_FLOAT__ +#if _MIPS_SIM == _MIPS_SIM_ABI64 + __asm__ __volatile__ ("l.d $f24, %0" : : "m" (env[0].__fpregs[0])); + __asm__ __volatile__ ("l.d $f25, %0" : : "m" (env[0].__fpregs[1])); + __asm__ __volatile__ ("l.d $f26, %0" : : "m" (env[0].__fpregs[2])); + __asm__ __volatile__ ("l.d $f27, %0" : : "m" (env[0].__fpregs[3])); + __asm__ __volatile__ ("l.d $f28, %0" : : "m" (env[0].__fpregs[4])); + __asm__ __volatile__ ("l.d $f29, %0" : : "m" (env[0].__fpregs[5])); + __asm__ __volatile__ ("l.d $f30, %0" : : "m" (env[0].__fpregs[6])); + __asm__ __volatile__ ("l.d $f31, %0" : : "m" (env[0].__fpregs[7])); +#else /* O32 || N32 */ + __asm__ __volatile__ ("l.d $f20, %0" : : "m" (env[0].__fpregs[0])); + __asm__ __volatile__ ("l.d $f22, %0" : : "m" (env[0].__fpregs[1])); + __asm__ __volatile__ ("l.d $f24, %0" : : "m" (env[0].__fpregs[2])); + __asm__ __volatile__ ("l.d $f26, %0" : : "m" (env[0].__fpregs[3])); + __asm__ __volatile__ ("l.d $f28, %0" : : "m" (env[0].__fpregs[4])); + __asm__ __volatile__ ("l.d $f30, %0" : : "m" (env[0].__fpregs[5])); +#endif /* O32 || N32 */ + + /* Get and reconstruct the floating point csr. */ + __asm__ __volatile__ ("lw $2, %0" : : "m" (env[0].__fpc_csr)); + __asm__ __volatile__ ("ctc1 $2, $31"); +#endif + + /* Get the GP. */ +#if _MIPS_SIM == _MIPS_SIM_ABI64 + __asm__ __volatile__ ("ld $gp, %0" : : "m" (env[0].__gp)); +#else /* O32 || N32 */ + __asm__ __volatile__ ("lw $gp, %0" : : "m" (env[0].__gp)); +#endif /* O32 || N32 */ + + /* Get the callee-saved registers. */ +#if _MIPS_SIM == _MIPS_SIM_ABI32 + __asm__ __volatile__ ("lw $16, %0" : : "m" (env[0].__regs[0])); + __asm__ __volatile__ ("lw $17, %0" : : "m" (env[0].__regs[1])); + __asm__ __volatile__ ("lw $18, %0" : : "m" (env[0].__regs[2])); + __asm__ __volatile__ ("lw $19, %0" : : "m" (env[0].__regs[3])); + __asm__ __volatile__ ("lw $20, %0" : : "m" (env[0].__regs[4])); + __asm__ __volatile__ ("lw $21, %0" : : "m" (env[0].__regs[5])); + __asm__ __volatile__ ("lw $22, %0" : : "m" (env[0].__regs[6])); + __asm__ __volatile__ ("lw $23, %0" : : "m" (env[0].__regs[7])); +#else /* N32 || N64 */ + __asm__ __volatile__ ("ld $16, %0" : : "m" (env[0].__regs[0])); + __asm__ __volatile__ ("ld $17, %0" : : "m" (env[0].__regs[1])); + __asm__ __volatile__ ("ld $18, %0" : : "m" (env[0].__regs[2])); + __asm__ __volatile__ ("ld $19, %0" : : "m" (env[0].__regs[3])); + __asm__ __volatile__ ("ld $20, %0" : : "m" (env[0].__regs[4])); + __asm__ __volatile__ ("ld $21, %0" : : "m" (env[0].__regs[5])); + __asm__ __volatile__ ("ld $22, %0" : : "m" (env[0].__regs[6])); + __asm__ __volatile__ ("ld $23, %0" : : "m" (env[0].__regs[7])); +#endif /* N32 || N64 */ + + /* Get the PC. */ +#if _MIPS_SIM == _MIPS_SIM_ABI32 + __asm__ __volatile__ ("lw $25, %0" : : "m" (env[0].__pc)); +#elif _MIPS_SIM == _MIPS_SIM_NABI32 + __asm__ __volatile__ ("lw $31, %0" : : "m" (env[0].__pc)); +#else /* N64 */ + __asm__ __volatile__ ("ld $31, %0" : : "m" (env[0].__pc)); +#endif /* N64 */ + + /* Restore the stack pointer and the FP. They have to be restored + last and in a single asm as gcc, depending on options used, may + use either of them to access env. */ +#if _MIPS_SIM == _MIPS_SIM_ABI64 + __asm__ __volatile__ ("ld $29, %0\n\t" + "ld $30, %1\n\t" : : "m" (env[0].__sp), "m" (env[0].__fp)); +#else /* O32 || N32 */ + __asm__ __volatile__ ("lw $29, %0\n\t" + "lw $30, %1\n\t" : : "m" (env[0].__sp), "m" (env[0].__fp)); +#endif /* O32 || N32 */ + + /* Give setjmp 1 if given a 0, or what they gave us if non-zero. */ + if (val == 0) + __asm__ __volatile__ ("li $2, 1"); + else + __asm__ __volatile__ ("move $2, %0" : : "r" (val)); + +#if _MIPS_SIM == _MIPS_SIM_ABI32 + __asm__ __volatile__ ("jr $25"); +#else /* N32 || N64 */ + __asm__ __volatile__ ("jr $31"); +#endif /* N32 || N64 */ + + /* Avoid `volatile function does return' warnings. */ + for (;;); +} +libc_hidden_def(__longjmp) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/__syscall_error.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/__syscall_error.c new file mode 100644 index 00000000..5e109a83 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/__syscall_error.c @@ -0,0 +1,18 @@ +/* Wrapper for setting errno. + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +/* This routine is jumped to by all the syscall handlers, to stash + * an error number into errno. */ +int __syscall_error(int err_no) attribute_hidden; +int __syscall_error(int err_no) +{ + __set_errno(err_no); + return -1; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/_test_and_set.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/_test_and_set.c new file mode 100644 index 00000000..9fd48f75 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/_test_and_set.c @@ -0,0 +1,30 @@ +/* Copyright (C) 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Maciej W. Rozycki , 2000. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Define the real-function versions of all inline functions + defined in sys/tas.h */ + +#include + +#define _EXTERN_INLINE +#ifndef __USE_EXTERN_INLINES +# define __USE_EXTERN_INLINES 1 +#endif + +#include "sys/tas.h" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/atomic.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/atomic.h new file mode 100644 index 00000000..4f73cc26 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/atomic.h @@ -0,0 +1,303 @@ +/* Low-level functions for atomic operations. Mips version. + Copyright (C) 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _MIPS_BITS_ATOMIC_H +#define _MIPS_BITS_ATOMIC_H 1 + +#include +#include + +typedef int32_t atomic32_t; +typedef uint32_t uatomic32_t; +typedef int_fast32_t atomic_fast32_t; +typedef uint_fast32_t uatomic_fast32_t; + +typedef int64_t atomic64_t; +typedef uint64_t uatomic64_t; +typedef int_fast64_t atomic_fast64_t; +typedef uint_fast64_t uatomic_fast64_t; + +typedef intptr_t atomicptr_t; +typedef uintptr_t uatomicptr_t; +typedef intmax_t atomic_max_t; +typedef uintmax_t uatomic_max_t; + +#if _MIPS_SIM == _ABIO32 +#define MIPS_PUSH_MIPS2 ".set mips2\n\t" +#else +#define MIPS_PUSH_MIPS2 +#endif + +/* See the comments in about the use of the sync instruction. */ +#ifndef MIPS_SYNC +# define MIPS_SYNC sync +#endif + +#define MIPS_SYNC_STR_2(X) #X +#define MIPS_SYNC_STR_1(X) MIPS_SYNC_STR_2(X) +#define MIPS_SYNC_STR MIPS_SYNC_STR_1(MIPS_SYNC) + +/* Compare and exchange. For all of the "xxx" routines, we expect a + "__prev" and a "__cmp" variable to be provided by the enclosing scope, + in which values are returned. */ + +#define __arch_compare_and_exchange_xxx_8_int(mem, newval, oldval, rel, acq) \ + (abort (), __prev = __cmp = 0) + +#define __arch_compare_and_exchange_xxx_16_int(mem, newval, oldval, rel, acq) \ + (abort (), __prev = __cmp = 0) + +#define __arch_compare_and_exchange_xxx_32_int(mem, newval, oldval, rel, acq) \ + __asm__ __volatile__ ( \ + ".set push\n\t" \ + MIPS_PUSH_MIPS2 \ + rel "\n" \ + "1:\t" \ + "ll %0,%4\n\t" \ + "move %1,$0\n\t" \ + "bne %0,%2,2f\n\t" \ + "move %1,%3\n\t" \ + "sc %1,%4\n\t" \ + "beqz %1,1b\n" \ + acq "\n\t" \ + ".set pop\n" \ + "2:\n\t" \ + : "=&r" (__prev), "=&r" (__cmp) \ + : "r" (oldval), "r" (newval), "m" (*mem) \ + : "memory") + +#if _MIPS_SIM == _ABIO32 +/* We can't do an atomic 64-bit operation in O32. */ +#define __arch_compare_and_exchange_xxx_64_int(mem, newval, oldval, rel, acq) \ + (abort (), __prev = __cmp = 0) +#else +#define __arch_compare_and_exchange_xxx_64_int(mem, newval, oldval, rel, acq) \ + __asm__ __volatile__ ("\n" \ + ".set push\n\t" \ + MIPS_PUSH_MIPS2 \ + rel "\n" \ + "1:\t" \ + "lld %0,%4\n\t" \ + "move %1,$0\n\t" \ + "bne %0,%2,2f\n\t" \ + "move %1,%3\n\t" \ + "scd %1,%4\n\t" \ + "beqz %1,1b\n" \ + acq "\n\t" \ + ".set pop\n" \ + "2:\n\t" \ + : "=&r" (__prev), "=&r" (__cmp) \ + : "r" (oldval), "r" (newval), "m" (*mem) \ + : "memory") +#endif + +/* For all "bool" routines, we return FALSE if exchange succesful. */ + +#define __arch_compare_and_exchange_bool_8_int(mem, new, old, rel, acq) \ +({ __typeof (*mem) __prev; int __cmp; \ + __arch_compare_and_exchange_xxx_8_int(mem, new, old, rel, acq); \ + !__cmp; }) + +#define __arch_compare_and_exchange_bool_16_int(mem, new, old, rel, acq) \ +({ __typeof (*mem) __prev; int __cmp; \ + __arch_compare_and_exchange_xxx_16_int(mem, new, old, rel, acq); \ + !__cmp; }) + +#define __arch_compare_and_exchange_bool_32_int(mem, new, old, rel, acq) \ +({ __typeof (*mem) __prev; int __cmp; \ + __arch_compare_and_exchange_xxx_32_int(mem, new, old, rel, acq); \ + !__cmp; }) + +#define __arch_compare_and_exchange_bool_64_int(mem, new, old, rel, acq) \ +({ __typeof (*mem) __prev; int __cmp; \ + __arch_compare_and_exchange_xxx_64_int(mem, new, old, rel, acq); \ + !__cmp; }) + +/* For all "val" routines, return the old value whether exchange + successful or not. */ + +#define __arch_compare_and_exchange_val_8_int(mem, new, old, rel, acq) \ +({ __typeof (*mem) __prev; int __cmp; \ + __arch_compare_and_exchange_xxx_8_int(mem, new, old, rel, acq); \ + (__typeof (*mem))__prev; }) + +#define __arch_compare_and_exchange_val_16_int(mem, new, old, rel, acq) \ +({ __typeof (*mem) __prev; int __cmp; \ + __arch_compare_and_exchange_xxx_16_int(mem, new, old, rel, acq); \ + (__typeof (*mem))__prev; }) + +#define __arch_compare_and_exchange_val_32_int(mem, new, old, rel, acq) \ +({ __typeof (*mem) __prev; int __cmp; \ + __arch_compare_and_exchange_xxx_32_int(mem, new, old, rel, acq); \ + (__typeof (*mem))__prev; }) + +#define __arch_compare_and_exchange_val_64_int(mem, new, old, rel, acq) \ +({ __typeof (*mem) __prev; int __cmp; \ + __arch_compare_and_exchange_xxx_64_int(mem, new, old, rel, acq); \ + (__typeof (*mem))__prev; }) + +/* Compare and exchange with "acquire" semantics, ie barrier after. */ + +#define atomic_compare_and_exchange_bool_acq(mem, new, old) \ + __atomic_bool_bysize (__arch_compare_and_exchange_bool, int, \ + mem, new, old, "", MIPS_SYNC_STR) + +#define atomic_compare_and_exchange_val_acq(mem, new, old) \ + __atomic_val_bysize (__arch_compare_and_exchange_val, int, \ + mem, new, old, "", MIPS_SYNC_STR) + +/* Compare and exchange with "release" semantics, ie barrier before. */ + +#define atomic_compare_and_exchange_bool_rel(mem, new, old) \ + __atomic_bool_bysize (__arch_compare_and_exchange_bool, int, \ + mem, new, old, MIPS_SYNC_STR, "") + +#define atomic_compare_and_exchange_val_rel(mem, new, old) \ + __atomic_val_bysize (__arch_compare_and_exchange_val, int, \ + mem, new, old, MIPS_SYNC_STR, "") + + + +/* Atomic exchange (without compare). */ + +#define __arch_exchange_xxx_8_int(mem, newval, rel, acq) \ + (abort (), 0) + +#define __arch_exchange_xxx_16_int(mem, newval, rel, acq) \ + (abort (), 0) + +#define __arch_exchange_xxx_32_int(mem, newval, rel, acq) \ +({ __typeof (*mem) __prev; int __cmp; \ + __asm__ __volatile__ ("\n" \ + ".set push\n\t" \ + MIPS_PUSH_MIPS2 \ + rel "\n" \ + "1:\t" \ + "ll %0,%3\n\t" \ + "move %1,%2\n\t" \ + "sc %1,%3\n\t" \ + "beqz %1,1b\n" \ + acq "\n\t" \ + ".set pop\n" \ + "2:\n\t" \ + : "=&r" (__prev), "=&r" (__cmp) \ + : "r" (newval), "m" (*mem) \ + : "memory"); \ + __prev; }) + +#if _MIPS_SIM == _ABIO32 +/* We can't do an atomic 64-bit operation in O32. */ +#define __arch_exchange_xxx_64_int(mem, newval, rel, acq) \ + (abort (), 0) +#else +#define __arch_exchange_xxx_64_int(mem, newval, rel, acq) \ +({ __typeof (*mem) __prev; int __cmp; \ + __asm__ __volatile__ ("\n" \ + ".set push\n\t" \ + MIPS_PUSH_MIPS2 \ + rel "\n" \ + "1:\n" \ + "lld %0,%3\n\t" \ + "move %1,%2\n\t" \ + "scd %1,%3\n\t" \ + "beqz %1,1b\n" \ + acq "\n\t" \ + ".set pop\n" \ + "2:\n\t" \ + : "=&r" (__prev), "=&r" (__cmp) \ + : "r" (newval), "m" (*mem) \ + : "memory"); \ + __prev; }) +#endif + +#define atomic_exchange_acq(mem, value) \ + __atomic_val_bysize (__arch_exchange_xxx, int, mem, value, "", MIPS_SYNC_STR) + +#define atomic_exchange_rel(mem, value) \ + __atomic_val_bysize (__arch_exchange_xxx, int, mem, value, MIPS_SYNC_STR, "") + + +/* Atomically add value and return the previous (unincremented) value. */ + +#define __arch_exchange_and_add_8_int(mem, newval, rel, acq) \ + (abort (), (__typeof(*mem)) 0) + +#define __arch_exchange_and_add_16_int(mem, newval, rel, acq) \ + (abort (), (__typeof(*mem)) 0) + +#define __arch_exchange_and_add_32_int(mem, value, rel, acq) \ +({ __typeof (*mem) __prev; int __cmp; \ + __asm__ __volatile__ ("\n" \ + ".set push\n\t" \ + MIPS_PUSH_MIPS2 \ + rel "\n" \ + "1:\t" \ + "ll %0,%3\n\t" \ + "addu %1,%0,%2\n\t" \ + "sc %1,%3\n\t" \ + "beqz %1,1b\n" \ + acq "\n\t" \ + ".set pop\n" \ + "2:\n\t" \ + : "=&r" (__prev), "=&r" (__cmp) \ + : "r" (value), "m" (*mem) \ + : "memory"); \ + __prev; }) + +#if _MIPS_SIM == _ABIO32 +/* We can't do an atomic 64-bit operation in O32. */ +#define __arch_exchange_and_add_64_int(mem, value, rel, acq) \ + (abort (), (__typeof(*mem)) 0) +#else +#define __arch_exchange_and_add_64_int(mem, value, rel, acq) \ +({ __typeof (*mem) __prev; int __cmp; \ + __asm__ __volatile__ ( \ + ".set push\n\t" \ + MIPS_PUSH_MIPS2 \ + rel "\n" \ + "1:\t" \ + "lld %0,%3\n\t" \ + "daddu %1,%0,%2\n\t" \ + "scd %1,%3\n\t" \ + "beqz %1,1b\n" \ + acq "\n\t" \ + ".set pop\n" \ + "2:\n\t" \ + : "=&r" (__prev), "=&r" (__cmp) \ + : "r" (value), "m" (*mem) \ + : "memory"); \ + __prev; }) +#endif + +/* ??? Barrier semantics for atomic_exchange_and_add appear to be + undefined. Use full barrier for now, as that's safe. */ +#define atomic_exchange_and_add(mem, value) \ + __atomic_val_bysize (__arch_exchange_and_add, int, mem, value, \ + MIPS_SYNC_STR, MIPS_SYNC_STR) + +/* TODO: More atomic operations could be implemented efficiently; only the + basic requirements are done. */ + +#define atomic_full_barrier() \ + __asm__ __volatile__ (".set push\n\t" \ + MIPS_PUSH_MIPS2 \ + MIPS_SYNC_STR "\n\t" \ + ".set pop" : : : "memory") + +#endif /* bits/atomic.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/dirent.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/dirent.h new file mode 100644 index 00000000..014e011c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/dirent.h @@ -0,0 +1,61 @@ +/* Copyright (C) 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _DIRENT_H +# error "Never use directly; include instead." +#endif +#include +#include + +struct dirent + { +#if defined(__USE_FILE_OFFSET64) && defined(__NR_getdents64) + __ino64_t d_ino; + __off64_t d_off; +#else + __ino_t d_ino; + __off_t d_off; +#endif + unsigned short int d_reclen; + unsigned char d_type; + char d_name[256]; /* We must not include limits.h! */ + }; + +#ifdef __USE_LARGEFILE64 +struct dirent64 + { +#ifdef __NR_getdents64 + __ino64_t d_ino; + __off64_t d_off; +#else + /* dirent64 is the same as dirent. */ + __ino_t d_ino; + __off_t d_off; +#endif + unsigned short int d_reclen; + unsigned char d_type; + char d_name[256]; /* We must not include limits.h! */ + }; +#endif + +#define d_fileno d_ino /* Backwards compatibility. */ + +#undef _DIRENT_HAVE_D_NAMLEN +#define _DIRENT_HAVE_D_RECLEN +#define _DIRENT_HAVE_D_OFF +#define _DIRENT_HAVE_D_TYPE diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/dlfcn.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/dlfcn.h new file mode 100644 index 00000000..1f054f97 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/dlfcn.h @@ -0,0 +1,66 @@ +/* System dependent definitions for run-time dynamic loading. + Copyright (C) 1996, 1997, 1999, 2000, 2001, 2004 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _DLFCN_H +# error "Never use directly; include instead." +#endif + +/* The MODE argument to `dlopen' contains one of the following: */ +#define RTLD_LAZY 0x0001 /* Lazy function call binding. */ +#define RTLD_NOW 0x0002 /* Immediate function call binding. */ +#define RTLD_BINDING_MASK 0x3 /* Mask of binding time value. */ +#define RTLD_NOLOAD 0x00008 /* Do not load the object. */ +#define RTLD_DEEPBIND 0x00010 /* Use deep binding. */ + +/* If the following bit is set in the MODE argument to `dlopen', + the symbols of the loaded object and its dependencies are made + visible as if the object were linked directly into the program. */ +#define RTLD_GLOBAL 0x0004 + +/* Unix98 demands the following flag which is the inverse to RTLD_GLOBAL. + The implementation does this by default and so we can define the + value to zero. */ +#define RTLD_LOCAL 0 + +/* Do not delete object when closed. */ +#define RTLD_NODELETE 0x01000 + +#if 0 /*def __USE_GNU*/ +/* To support profiling of shared objects it is a good idea to call + the function found using `dlsym' using the following macro since + these calls do not use the PLT. But this would mean the dynamic + loader has no chance to find out when the function is called. The + macro applies the necessary magic so that profiling is possible. + Rewrite + foo = (*fctp) (arg1, arg2); + into + foo = DL_CALL_FCT (fctp, (arg1, arg2)); +*/ +# define DL_CALL_FCT(fctp, args) \ + (_dl_mcount_wrapper_check ((void *) (fctp)), (*(fctp)) args) + +__BEGIN_DECLS + +/* This function calls the profiling functions. */ +extern void _dl_mcount_wrapper_check (void *__selfpc) __THROW; + +__END_DECLS + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/endian.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/endian.h new file mode 100644 index 00000000..0a3d2fab --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/endian.h @@ -0,0 +1,16 @@ +/* The MIPS architecture has selectable endianness. + Linux/MIPS exists in two both little and big endian flavours and we + want to be able to share the installed headerfiles between both, + so we define __BYTE_ORDER based on GCC's predefines. */ + +#ifndef _ENDIAN_H +# error "Never use directly; include instead." +#endif + +#ifdef __MIPSEB__ +# define __BYTE_ORDER __BIG_ENDIAN +#else +# ifdef __MIPSEL__ +# define __BYTE_ORDER __LITTLE_ENDIAN +# endif +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/fcntl.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/fcntl.h new file mode 100644 index 00000000..f0072fd7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/fcntl.h @@ -0,0 +1,262 @@ +/* O_*, F_*, FD_* bit values for Linux. + Copyright (C) 1995, 1996, 1997, 1998, 2000, 2002, 2003, 2004, 2006 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FCNTL_H +# error "Never use directly; include instead." +#endif + +#include +#include +#ifdef __USE_GNU +# include +#endif + + +/* open/fcntl - O_SYNC is only implemented on blocks devices and on files + located on an ext2 file system */ +#define O_ACCMODE 0003 +#define O_RDONLY 00 +#define O_WRONLY 01 +#define O_RDWR 02 +#define O_APPEND 0x0008 +#define O_SYNC 0x0010 +#define O_NONBLOCK 0x0080 +#define O_NDELAY O_NONBLOCK +#define O_CREAT 0x0100 /* not fcntl */ +#define O_TRUNC 0x0200 /* not fcntl */ +#define O_EXCL 0x0400 /* not fcntl */ +#define O_NOCTTY 0x0800 /* not fcntl */ +#define O_FSYNC O_SYNC +#define O_ASYNC 0x1000 + +#ifdef __USE_GNU +# define O_NOFOLLOW 0x20000 /* Do not follow links. */ +# define O_DIRECT 0x8000 /* Direct disk access hint. */ +# define O_DIRECTORY 0x10000 /* Must be a directory. */ +# define O_NOATIME 0x40000 /* Do not set atime. */ +# define O_CLOEXEC 02000000 /* set close_on_exec */ +#endif + +/* For now Linux has no synchronisity options for data and read operations. + We define the symbols here but let them do the same as O_SYNC since + this is a superset. */ +#if defined __USE_POSIX199309 || defined __USE_UNIX98 +# define O_DSYNC O_SYNC /* Synchronize data. */ +# define O_RSYNC O_SYNC /* Synchronize read operations. */ +#endif + +#ifdef __USE_LARGEFILE64 +# if __WORDSIZE == 64 +# define O_LARGEFILE 0 +# else +# define O_LARGEFILE 0x2000 /* Allow large file opens. */ +# endif +#endif + +/* Values for the second argument to `fcntl'. */ +#define F_DUPFD 0 /* Duplicate file descriptor. */ +#define F_GETFD 1 /* Get file descriptor flags. */ +#define F_SETFD 2 /* Set file descriptor flags. */ +#define F_GETFL 3 /* Get file status flags. */ +#define F_SETFL 4 /* Set file status flags. */ +#ifndef __USE_FILE_OFFSET64 +# define F_GETLK 14 /* Get record locking info. */ +# define F_SETLK 6 /* Set record locking info (non-blocking). */ +# define F_SETLKW 7 /* Set record locking info (blocking). */ +#else +# define F_GETLK F_GETLK64 /* Get record locking info. */ +# define F_SETLK F_SETLK64 /* Set record locking info (non-blocking).*/ +# define F_SETLKW F_SETLKW64 /* Set record locking info (blocking). */ +#endif + +#if __WORDSIZE == 64 +# define F_GETLK64 14 /* Get record locking info. */ +# define F_SETLK64 6 /* Set record locking info (non-blocking). */ +# define F_SETLKW64 7 /* Set record locking info (blocking). */ +#else +# define F_GETLK64 33 /* Get record locking info. */ +# define F_SETLK64 34 /* Set record locking info (non-blocking). */ +# define F_SETLKW64 35 /* Set record locking info (blocking). */ +#endif + +#if defined __USE_BSD || defined __USE_UNIX98 +# define F_SETOWN 24 /* Get owner of socket (receiver of SIGIO). */ +# define F_GETOWN 23 /* Set owner of socket (receiver of SIGIO). */ +#endif + +#ifdef __USE_GNU +# define F_SETSIG 10 /* Set number of signal to be sent. */ +# define F_GETSIG 11 /* Get number of signal to be sent. */ +#endif + +#ifdef __USE_GNU +# define F_SETLEASE 1024 /* Set a lease. */ +# define F_GETLEASE 1025 /* Enquire what lease is active. */ +# define F_NOTIFY 1026 /* Request notfications on a directory. */ +# define F_DUPFD_CLOEXEC 1030 /* Duplicate file descriptor with + close-on-exit set on new fd. */ +#endif + +/* For F_[GET|SET]FL. */ +#define FD_CLOEXEC 1 /* actually anything with low bit set goes */ + +/* For posix fcntl() and `l_type' field of a `struct flock' for lockf(). */ +#define F_RDLCK 0 /* Read lock. */ +#define F_WRLCK 1 /* Write lock. */ +#define F_UNLCK 2 /* Remove lock. */ + +/* For old implementation of bsd flock(). */ +#define F_EXLCK 4 /* or 3 */ +#define F_SHLCK 8 /* or 4 */ + +#ifdef __USE_BSD +/* Operations for bsd flock(), also used by the kernel implementation. */ +# define LOCK_SH 1 /* shared lock */ +# define LOCK_EX 2 /* exclusive lock */ +# define LOCK_NB 4 /* or'd with one of the above to prevent + blocking */ +# define LOCK_UN 8 /* remove lock */ +#endif + +#ifdef __USE_GNU +# define LOCK_MAND 32 /* This is a mandatory flock: */ +# define LOCK_READ 64 /* ... which allows concurrent read operations. */ +# define LOCK_WRITE 128 /* ... which allows concurrent write operations. */ +# define LOCK_RW 192 /* ... Which allows concurrent read & write operations. */ +#endif + +#ifdef __USE_GNU +/* Types of directory notifications that may be requested with F_NOTIFY. */ +# define DN_ACCESS 0x00000001 /* File accessed. */ +# define DN_MODIFY 0x00000002 /* File modified. */ +# define DN_CREATE 0x00000004 /* File created. */ +# define DN_DELETE 0x00000008 /* File removed. */ +# define DN_RENAME 0x00000010 /* File renamed. */ +# define DN_ATTRIB 0x00000020 /* File changed attibutes. */ +# define DN_MULTISHOT 0x80000000 /* Don't remove notifier. */ +#endif + +struct flock + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ +#ifndef __USE_FILE_OFFSET64 + __off_t l_start; /* Offset where the lock begins. */ + __off_t l_len; /* Size of the locked area; zero means until EOF. */ +#if _MIPS_SIM != _ABI64 + /* The 64-bit flock structure, used by the n64 ABI, and for 64-bit + fcntls in o32 and n32, never has this field. */ + long int l_sysid; +#endif +#else + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ +#endif + __pid_t l_pid; /* Process holding the lock. */ +#if ! defined __USE_FILE_OFFSET64 && _MIPS_SIM != _ABI64 + /* The 64-bit flock structure, used by the n64 ABI, and for 64-bit + flock in o32 and n32, never has this field. */ + long int pad[4]; +#endif + }; +typedef struct flock flock_t; + +#ifdef __USE_LARGEFILE64 +struct flock64 + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ + __pid_t l_pid; /* Process holding the lock. */ + }; +#endif + +/* Define some more compatibility macros to be backward compatible with + BSD systems which did not managed to hide these kernel macros. */ +#ifdef __USE_BSD +# define FAPPEND O_APPEND +# define FFSYNC O_FSYNC +# define FASYNC O_ASYNC +# define FNONBLOCK O_NONBLOCK +# define FNDELAY O_NDELAY +#endif /* Use BSD. */ + +/* Advise to `posix_fadvise'. */ +#ifdef __USE_XOPEN2K +# define POSIX_FADV_NORMAL 0 /* No further special treatment. */ +# define POSIX_FADV_RANDOM 1 /* Expect random page references. */ +# define POSIX_FADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define POSIX_FADV_WILLNEED 3 /* Will need these pages. */ +# define POSIX_FADV_DONTNEED 4 /* Don't need these pages. */ +# define POSIX_FADV_NOREUSE 5 /* Data will be accessed once. */ +#endif + + +#if defined __USE_GNU && defined __UCLIBC_LINUX_SPECIFIC__ +/* Flags for SYNC_FILE_RANGE. */ +# define SYNC_FILE_RANGE_WAIT_BEFORE 1 /* Wait upon writeout of all pages + in the range before performing the + write. */ +# define SYNC_FILE_RANGE_WRITE 2 /* Initiate writeout of all those + dirty pages in the range which are + not presently under writeback. */ +# define SYNC_FILE_RANGE_WAIT_AFTER 4 /* Wait upon writeout of all pages in + the range after performing the + write. */ + +/* Flags for SPLICE and VMSPLICE. */ +# define SPLICE_F_MOVE 1 /* Move pages instead of copying. */ +# define SPLICE_F_NONBLOCK 2 /* Don't block on the pipe splicing + (but we may still block on the fd + we splice from/to). */ +# define SPLICE_F_MORE 4 /* Expect more data. */ +# define SPLICE_F_GIFT 8 /* Pages passed in are a gift. */ +#endif + +__BEGIN_DECLS + +#if defined __USE_GNU && defined __UCLIBC_LINUX_SPECIFIC__ + +/* Provide kernel hint to read ahead. */ +extern ssize_t readahead (int __fd, __off64_t __offset, size_t __count) + __THROW; + + +/* Selective file content synch'ing. */ +extern int sync_file_range (int __fd, __off64_t __from, __off64_t __to, + unsigned int __flags); + +/* Splice address range into a pipe. */ +extern ssize_t vmsplice (int __fdout, const struct iovec *__iov, + size_t __count, unsigned int __flags); + +/* Splice two files together. */ +extern ssize_t splice (int __fdin, __off64_t *__offin, int __fdout, + __off64_t *__offout, size_t __len, + unsigned int __flags); + +/* In-kernel implementation of tee for pipe buffers. */ +extern ssize_t tee (int __fdin, int __fdout, size_t __len, + unsigned int __flags); + +#endif +__END_DECLS + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/fenv.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/fenv.h new file mode 100644 index 00000000..24e0694c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/fenv.h @@ -0,0 +1,77 @@ +/* Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FENV_H +# error "Never use directly; include instead." +#endif + + +/* Define bits representing the exception. We use the bit positions + of the appropriate bits in the FPU control word. */ +enum + { + FE_INEXACT = 0x04, +#define FE_INEXACT FE_INEXACT + FE_UNDERFLOW = 0x08, +#define FE_UNDERFLOW FE_UNDERFLOW + FE_OVERFLOW = 0x10, +#define FE_OVERFLOW FE_OVERFLOW + FE_DIVBYZERO = 0x20, +#define FE_DIVBYZERO FE_DIVBYZERO + FE_INVALID = 0x40, +#define FE_INVALID FE_INVALID + }; + +#define FE_ALL_EXCEPT \ + (FE_INEXACT | FE_DIVBYZERO | FE_UNDERFLOW | FE_OVERFLOW | FE_INVALID) + +/* The MIPS FPU supports all of the four defined rounding modes. We + use again the bit positions in the FPU control word as the values + for the appropriate macros. */ +enum + { + FE_TONEAREST = 0x0, +#define FE_TONEAREST FE_TONEAREST + FE_TOWARDZERO = 0x1, +#define FE_TOWARDZERO FE_TOWARDZERO + FE_UPWARD = 0x2, +#define FE_UPWARD FE_UPWARD + FE_DOWNWARD = 0x3 +#define FE_DOWNWARD FE_DOWNWARD + }; + + +/* Type representing exception flags. */ +typedef unsigned short int fexcept_t; + + +/* Type representing floating-point environment. This function corresponds + to the layout of the block written by the `fstenv'. */ +typedef struct + { + unsigned int __fp_control_register; + } +fenv_t; + +/* If the default argument is used we use this value. */ +#define FE_DFL_ENV ((__const fenv_t *) -1) + +#ifdef __USE_GNU +/* Floating-point environment where none of the exception is masked. */ +# define FE_NOMASK_ENV ((__const fenv_t *) -2) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/ioctl-types.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/ioctl-types.h new file mode 100644 index 00000000..a8dcf242 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/ioctl-types.h @@ -0,0 +1,76 @@ +/* Structure types for pre-termios terminal ioctls. Linux/MIPS version. + Copyright (C) 1997, 1999, 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_IOCTL_H +# error "Never use directly; include instead." +#endif + +/* Get definition of constants for use with `ioctl'. */ +#include + +struct winsize + { + unsigned short int ws_row; + unsigned short int ws_col; + unsigned short int ws_xpixel; + unsigned short int ws_ypixel; + }; + +#define NCC 8 +struct termio + { + unsigned short int c_iflag; /* input mode flags */ + unsigned short int c_oflag; /* output mode flags */ + unsigned short int c_cflag; /* control mode flags */ + unsigned short int c_lflag; /* local mode flags */ + char c_line; /* line discipline */ + /* Yes, this is really NCCS. */ + unsigned char c_cc[32 /* NCCS */]; /* control characters */ + }; + +/* modem lines */ +#define TIOCM_LE 0x001 /* line enable */ +#define TIOCM_DTR 0x002 /* data terminal ready */ +#define TIOCM_RTS 0x004 /* request to send */ +#define TIOCM_ST 0x010 /* secondary transmit */ +#define TIOCM_SR 0x020 /* secondary receive */ +#define TIOCM_CTS 0x040 /* clear to send */ +#define TIOCM_CAR 0x100 /* carrier detect */ +#define TIOCM_CD TIOCM_CAR +#define TIOCM_RNG 0x200 /* ring */ +#define TIOCM_RI TIOCM_RNG +#define TIOCM_DSR 0x400 /* data set ready */ + +/* line disciplines */ +#define N_TTY 0 +#define N_SLIP 1 +#define N_MOUSE 2 +#define N_PPP 3 +#define N_STRIP 4 +#define N_AX25 5 +#define N_X25 6 /* X.25 async */ +#define N_6PACK 7 +#define N_MASC 8 /* Mobitex module */ +#define N_R3964 9 /* Simatic R3964 module */ +#define N_PROFIBUS_FDL 10 /* Profibus */ +#define N_IRDA 11 /* Linux IR */ +#define N_SMSBLOCK 12 /* SMS block mode */ +#define N_HDLC 13 /* synchronous HDLC */ +#define N_SYNC_PPP 14 /* synchronous PPP */ +#define N_HCI 15 /* Bluetooth HCI UART */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/ipc.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/ipc.h new file mode 100644 index 00000000..1f629ce6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/ipc.h @@ -0,0 +1,55 @@ +/* Copyright (C) 1995, 96, 97, 98, 99, 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_IPC_H +# error "Never use directly; include instead." +#endif + +#include + +/* Mode bits for `msgget', `semget', and `shmget'. */ +#define IPC_CREAT 01000 /* Create key if key does not exist. */ +#define IPC_EXCL 02000 /* Fail if key exists. */ +#define IPC_NOWAIT 04000 /* Return error on wait. */ + +/* Control commands for `msgctl', `semctl', and `shmctl'. */ +#define IPC_RMID 0 /* Remove identifier. */ +#define IPC_SET 1 /* Set `ipc_perm' options. */ +#define IPC_STAT 2 /* Get `ipc_perm' options. */ +#ifdef __USE_GNU +# define IPC_INFO 3 /* See ipcs. */ +#endif + +/* Special key values. */ +#define IPC_PRIVATE ((__key_t) 0) /* Private key. */ + + +/* Data structure used to pass permission information to IPC operations. */ +struct ipc_perm + { + __key_t __key; /* Key. */ + unsigned int uid; /* Owner's user ID. */ + unsigned int gid; /* Owner's group ID. */ + unsigned int cuid; /* Creator's user ID. */ + unsigned int cgid; /* Creator's group ID. */ + unsigned int mode; /* Read/write permission. */ + unsigned short int __seq; /* Sequence number. */ + unsigned short int __pad1; + unsigned long int __unused1; + unsigned long int __unused2; +}; diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/kernel_sigaction.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/kernel_sigaction.h new file mode 100644 index 00000000..2048095c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/kernel_sigaction.h @@ -0,0 +1,35 @@ +#ifndef _BITS_SIGACTION_STRUCT_H +#define _BITS_SIGACTION_STRUCT_H + +/* This is the sigaction structure from the Linux 2.1.24 kernel. */ + +#include + +#define HAVE_SA_RESTORER + +struct old_kernel_sigaction { + unsigned int sa_flags; + __sighandler_t k_sa_handler; + unsigned long sa_mask; + unsigned int __pad0[3]; /* reserved, keep size constant */ + + /* Abi says here follows reserved int[2] */ + void (*sa_restorer)(void); +#if (_MIPS_SZPTR < 64) + /* + * For 32 bit code we have to pad struct sigaction to get + * constant size for the ABI + */ + int pad1[1]; /* reserved */ +#endif +}; + +/* In uclibc, userspace struct sigaction is identical to + * "new" struct kernel_sigaction (one from the Linux 2.1.68 kernel). + * See sigaction.h + */ + +extern int __syscall_rt_sigaction (int, const struct sigaction *, + struct sigaction *, size_t) attribute_hidden; + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/kernel_stat.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/kernel_stat.h new file mode 100644 index 00000000..dc3565ac --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/kernel_stat.h @@ -0,0 +1,98 @@ +#ifndef _BITS_STAT_STRUCT_H +#define _BITS_STAT_STRUCT_H + +#ifndef _LIBC +#error bits/kernel_stat.h is for internal uClibc use only! +#endif + +/* This file provides whatever this particular arch's kernel thinks + * struct kernel_stat should look like... It turns out each arch has a + * different opinion on the subject... */ + +#include + +#if _MIPS_SIM == _MIPS_SIM_ABI64 +/* The memory layout is the same as of struct stat64 of the 32-bit kernel. */ +struct kernel_stat { + __kernel_dev_t st_dev; + unsigned int st_pad1[3]; + __kernel_ino_t st_ino; + __kernel_mode_t st_mode; + __kernel_nlink_t st_nlink; + __kernel_uid_t st_uid; + __kernel_gid_t st_gid; + __kernel_dev_t st_rdev; + unsigned int st_pad2[3]; + __kernel_off_t st_size; + struct timespec st_atim; + struct timespec st_mtim; + struct timespec st_ctim; + unsigned int st_blksize; + unsigned int reserved3; + unsigned long st_blocks; +}; +#define kernel_stat64 kernel_stat +#elif _MIPS_SIM == _MIPS_SIM_NABI32 +/* The memory layout is the same as of struct stat64 of the 32-bit kernel. */ +struct kernel_stat { + unsigned int st_dev; + unsigned int st_pad1[3]; + unsigned long long st_ino; + __kernel_mode_t st_mode; + __kernel_nlink_t st_nlink; + __kernel_uid_t st_uid; + __kernel_gid_t st_gid; + unsigned int st_rdev; + unsigned int st_pad2[3]; + unsigned long long st_size; + struct timespec st_atim; + struct timespec st_mtim; + struct timespec st_ctim; + unsigned int st_blksize; + unsigned int reserved3; + unsigned long long st_blocks; +}; +#define kernel_stat64 kernel_stat +#else /* O32 */ +struct kernel_stat { + __kernel_dev_t st_dev; + long st_pad1[3]; + __kernel_ino_t st_ino; + __kernel_mode_t st_mode; + __kernel_nlink_t st_nlink; + __kernel_uid_t st_uid; + __kernel_gid_t st_gid; + __kernel_dev_t st_rdev; + long st_pad2[2]; + __kernel_off_t st_size; + long st_pad3; + struct timespec st_atim; + struct timespec st_mtim; + struct timespec st_ctim; + long st_blksize; + long st_blocks; + long st_pad4[14]; +}; + +struct kernel_stat64 { + unsigned long st_dev; + unsigned long st_pad0[3]; /* Reserved for st_dev expansion */ + unsigned long long st_ino; + __kernel_mode_t st_mode; + __kernel_nlink_t st_nlink; + __kernel_uid_t st_uid; + __kernel_gid_t st_gid; + unsigned long st_rdev; + unsigned long st_pad1[3]; /* Reserved for st_rdev expansion */ + long long st_size; + struct timespec st_atim; + struct timespec st_mtim; + struct timespec st_ctim; + unsigned long st_blksize; + unsigned long st_pad2; + long long st_blocks; +}; +#endif /* O32 */ + +#endif /* _BITS_STAT_STRUCT_H */ + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/kernel_types.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/kernel_types.h new file mode 100644 index 00000000..9fc3b967 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/kernel_types.h @@ -0,0 +1,79 @@ +/* Note that we use the exact same include guard #define names + * as asm/posix_types.h. This will avoid gratuitous conflicts + * with the posix_types.h kernel header, and will ensure that + * our private content, and not the kernel header, will win. + * -Erik + */ +#ifndef _ASM_POSIX_TYPES_H +#define _ASM_POSIX_TYPES_H + +# if __WORDSIZE == 64 +typedef unsigned int __kernel_dev_t; +typedef unsigned long __kernel_ino_t; +typedef unsigned int __kernel_mode_t; +typedef unsigned int __kernel_nlink_t; +typedef long __kernel_off_t; +typedef int __kernel_pid_t; +typedef long int __kernel_ipc_pid_t; +typedef int __kernel_uid_t; +typedef int __kernel_gid_t; +typedef unsigned long __kernel_size_t; +typedef long __kernel_ssize_t; +typedef long __kernel_ptrdiff_t; +typedef long __kernel_time_t; +typedef long __kernel_suseconds_t; +typedef long __kernel_clock_t; +typedef long __kernel_daddr_t; +typedef char * __kernel_caddr_t; +typedef unsigned short __kernel_uid16_t; +typedef unsigned short __kernel_gid16_t; +typedef int __kernel_uid32_t; +typedef int __kernel_gid32_t; +typedef __kernel_uid_t __kernel_old_uid_t; +typedef __kernel_gid_t __kernel_old_gid_t; +typedef __kernel_dev_t __kernel_old_dev_t; +typedef long long __kernel_loff_t; +#else +typedef unsigned int __kernel_dev_t; +typedef unsigned long __kernel_ino_t; +typedef unsigned int __kernel_mode_t; + +/* Linux 2.4.20 include/asm-mips/posix_types.h has this: +but apparently that is an error?!?!? +*/ +#if 0 +typedef int __kernel_nlink_t; +#else +/* So use this instead */ +typedef unsigned long __kernel_nlink_t; +#endif + +typedef long __kernel_off_t; +typedef int __kernel_pid_t; +typedef long int __kernel_ipc_pid_t; +typedef int __kernel_uid_t; +typedef int __kernel_gid_t; +typedef unsigned int __kernel_size_t; +typedef int __kernel_ssize_t; +typedef int __kernel_ptrdiff_t; +typedef long __kernel_time_t; +typedef long __kernel_suseconds_t; +typedef long __kernel_clock_t; +typedef long __kernel_daddr_t; +typedef char * __kernel_caddr_t; +typedef unsigned short __kernel_uid16_t; +typedef unsigned short __kernel_gid16_t; +typedef int __kernel_uid32_t; +typedef int __kernel_gid32_t; +typedef __kernel_uid_t __kernel_old_uid_t; +typedef __kernel_gid_t __kernel_old_gid_t; +typedef __kernel_dev_t __kernel_old_dev_t; +typedef long long __kernel_loff_t; +#endif + + +typedef struct { + long val[2]; +} __kernel_fsid_t; + +#endif /* _ASM_POSIX_TYPES_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/mathdef.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/mathdef.h new file mode 100644 index 00000000..331da13a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/mathdef.h @@ -0,0 +1,48 @@ +/* Copyright (C) 1997, 1998, 1999, 2000, 2002, 2003, 2004 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#if !defined _MATH_H && !defined _COMPLEX_H +# error "Never use directly; include instead" +#endif + +#include + +#if defined __USE_ISOC99 && defined _MATH_H && !defined _MATH_H_MATHDEF +# define _MATH_H_MATHDEF 1 + +/* Normally, there is no long double type and the `float' and `double' + expressions are evaluated as `double'. */ +typedef double float_t; /* `float' expressions are evaluated as + `double'. */ +typedef double double_t; /* `double' expressions are evaluated as + `double'. */ + +/* The values returned by `ilogb' for 0 and NaN respectively. */ +# define FP_ILOGB0 (-2147483647) +# define FP_ILOGBNAN 2147483647 + +#endif /* ISO C99 */ + +#if ! defined __NO_LONG_DOUBLE_MATH && _MIPS_SIM == _ABIO32 +/* Signal that we do not really have a `long double'. This disables the + declaration of all the `long double' function variants. */ +# define __NO_LONG_DOUBLE_MATH 1 +#elif !defined __NO_LONG_DOUBLE_MATH && !defined __UCLIBC_HAS_LONG_DOUBLE_MATH__ +# define __NO_LONG_DOUBLE_MATH 1 +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/mman.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/mman.h new file mode 100644 index 00000000..c480be46 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/mman.h @@ -0,0 +1,108 @@ +/* Definitions for POSIX memory map interface. Linux/MIPS version. + Copyright (C) 1997, 2000, 2003, 2004, 2005, 2006 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_MMAN_H +# error "Never use directly; include instead." +#endif + +/* The following definitions basically come from the kernel headers. + But the kernel header is not namespace clean. */ + + +/* Protections are chosen from these bits, OR'd together. The + implementation does not necessarily support PROT_EXEC or PROT_WRITE + without PROT_READ. The only guarantees are that no writing will be + allowed without PROT_WRITE and no access will be allowed for PROT_NONE. */ + +#define PROT_READ 0x1 /* Page can be read. */ +#define PROT_WRITE 0x2 /* Page can be written. */ +#define PROT_EXEC 0x4 /* Page can be executed. */ +#define PROT_NONE 0x0 /* Page can not be accessed. */ +#define PROT_GROWSDOWN 0x01000000 /* Extend change to start of + growsdown vma (mprotect only). */ +#define PROT_GROWSUP 0x02000000 /* Extend change to start of + growsup vma (mprotect only). */ + +/* Sharing types (must choose one and only one of these). */ +#define MAP_SHARED 0x01 /* Share changes. */ +#define MAP_PRIVATE 0x02 /* Changes are private. */ +#ifdef __USE_MISC +# define MAP_TYPE 0x0f /* Mask for type of mapping. */ +#endif + +/* Other flags. */ +#define MAP_FIXED 0x10 /* Interpret addr exactly. */ +#ifdef __USE_MISC +# define MAP_FILE 0 +# define MAP_ANONYMOUS 0x0800 /* Don't use a file. */ +# define MAP_ANON MAP_ANONYMOUS +# define MAP_RENAME MAP_ANONYMOUS +#endif + +/* These are Linux-specific. */ +#ifdef __USE_MISC +# define MAP_NORESERVE 0x0400 /* don't check for reservations */ +# define MAP_ANONYMOUS 0x0800 /* don't use a file */ +# define MAP_GROWSDOWN 0x1000 /* stack-like segment */ +# define MAP_DENYWRITE 0x2000 /* ETXTBSY */ +# define MAP_EXECUTABLE 0x4000 /* mark it as an executable */ +# define MAP_LOCKED 0x8000 /* pages are locked */ +# define MAP_POPULATE 0x10000 /* populate (prefault) pagetables */ +# define MAP_NONBLOCK 0x20000 /* do not block on IO */ +# define MAP_UNINITIALIZE 0x4000000 /* For anonymous mmap, memory could + be uninitialized. */ +#endif + +/* Flags to `msync'. */ +#define MS_ASYNC 1 /* Sync memory asynchronously. */ +#define MS_SYNC 4 /* Synchronous memory sync. */ +#define MS_INVALIDATE 2 /* Invalidate the caches. */ + +/* Flags for `mlockall'. */ +#define MCL_CURRENT 1 /* Lock all currently mapped pages. */ +#define MCL_FUTURE 2 /* Lock all additions to address + space. */ + +/* Flags for `mremap'. */ +#ifdef __USE_GNU +# define MREMAP_MAYMOVE 1 +# define MREMAP_FIXED 2 +#endif + +/* Advice to `madvise'. */ +#ifdef __USE_BSD +# define MADV_NORMAL 0 /* No further special treatment. */ +# define MADV_RANDOM 1 /* Expect random page references. */ +# define MADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define MADV_WILLNEED 3 /* Will need these pages. */ +# define MADV_DONTNEED 4 /* Don't need these pages. */ +# define MADV_REMOVE 9 /* Remove these pages and resources. */ +# define MADV_DONTFORK 10 /* Do not inherit across fork. */ +# define MADV_DOFORK 11 /* Do inherit across fork. */ +#endif + +/* The POSIX people had to invent similar names for the same things. */ +#ifdef __USE_XOPEN2K +# define POSIX_MADV_NORMAL 0 /* No further special treatment. */ +# define POSIX_MADV_RANDOM 1 /* Expect random page references. */ +# define POSIX_MADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define POSIX_MADV_WILLNEED 3 /* Will need these pages. */ +# define POSIX_MADV_DONTNEED 4 /* Don't need these pages. */ +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/msq.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/msq.h new file mode 100644 index 00000000..2b0d38ec --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/msq.h @@ -0,0 +1,93 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_MSG_H +# error "Never use directly; include instead." +#endif + +#include +#include + +/* Define options for message queue functions. */ +#define MSG_NOERROR 010000 /* no error if message is too big */ +#ifdef __USE_GNU +# define MSG_EXCEPT 020000 /* recv any msg except of specified type */ +#endif + +/* Types used in the structure definition. */ +typedef unsigned long int msgqnum_t; +typedef unsigned long int msglen_t; + + +/* Structure of record for one message inside the kernel. + The type `struct msg' is opaque. */ +struct msqid_ds +{ + struct ipc_perm msg_perm; /* structure describing operation permission */ +#if (__WORDSIZE == 32) && !defined(__MIPSEL__) + unsigned long __unused1; +#endif + __time_t msg_stime; /* time of last msgsnd command */ +#if (__WORDSIZE == 32) && defined(__MIPSEL__) + unsigned long __unused1; +#endif +#if (__WORDSIZE == 32) && !defined(__MIPSEL__) + unsigned long __unused2; +#endif + __time_t msg_rtime; /* time of last msgrcv command */ +#if (__WORDSIZE == 32) && defined(__MIPSEL__) + unsigned long __unused2; +#endif +#if (__WORDSIZE == 32) && !defined(__MIPSEL__) + unsigned long __unused3; +#endif + __time_t msg_ctime; /* time of last change */ +#if (__WORDSIZE == 32) && defined(__MIPSEL__) + unsigned long __unused3; +#endif + unsigned long int __msg_cbytes; /* current number of bytes on queue */ + msgqnum_t msg_qnum; /* number of messages currently on queue */ + msglen_t msg_qbytes; /* max number of bytes allowed on queue */ + __pid_t msg_lspid; /* pid of last msgsnd() */ + __pid_t msg_lrpid; /* pid of last msgrcv() */ + unsigned long int __unused4; + unsigned long int __unused5; +}; + +#ifdef __USE_MISC + +# define msg_cbytes __msg_cbytes + +/* ipcs ctl commands */ +# define MSG_STAT 11 +# define MSG_INFO 12 + +/* buffer for msgctl calls IPC_INFO, MSG_INFO */ +struct msginfo + { + int msgpool; + int msgmap; + int msgmax; + int msgmnb; + int msgmni; + int msgssz; + int msgtql; + unsigned short int msgseg; + }; + +#endif /* __USE_MISC */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/poll.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/poll.h new file mode 100644 index 00000000..eee4ea25 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/poll.h @@ -0,0 +1,50 @@ +/* Copyright (C) 1997, 2001, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_POLL_H +# error "Never use directly; include instead." +#endif + +/* Event types that can be polled for. These bits may be set in `events' + to indicate the interesting event types; they will appear in `revents' + to indicate the status of the file descriptor. */ +#define POLLIN 0x001 /* There is data to read. */ +#define POLLPRI 0x002 /* There is urgent data to read. */ +#define POLLOUT 0x004 /* Writing now will not block. */ + +#ifdef __USE_XOPEN +/* These values are defined in XPG4.2. */ +# define POLLRDNORM 0x040 /* Normal data may be read. */ +# define POLLRDBAND 0x080 /* Priority data may be read. */ +# define POLLWRNORM POLLOUT /* Writing now will not block. */ +# define POLLWRBAND 0x100 /* Priority data may be written. */ +#endif + +#ifdef __USE_GNU +/* These are extensions for Linux. */ +# define POLLMSG 0x400 +# define POLLREMOVE 0x1000 +# define POLLRDHUP 0x2000 +#endif + +/* Event types always implicitly polled for. These bits need not be set in + `events', but they will appear in `revents' to indicate the status of + the file descriptor. */ +#define POLLERR 0x008 /* Error condition. */ +#define POLLHUP 0x010 /* Hung up. */ +#define POLLNVAL 0x020 /* Invalid polling request. */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/resource.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/resource.h new file mode 100644 index 00000000..1c8b99a9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/resource.h @@ -0,0 +1,233 @@ +/* Bit values & structures for resource limits. Linux/MIPS version. + Copyright (C) 1994, 1996, 1997, 1998, 1999, 2000, 2004, 2005, 2006 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_RESOURCE_H +# error "Never use directly; include instead." +#endif + +#include + +/* Transmute defines to enumerations. The macro re-definitions are + necessary because some programs want to test for operating system + features with #ifdef RUSAGE_SELF. In ISO C the reflexive + definition is a no-op. */ + +/* Kinds of resource limit. */ +enum __rlimit_resource +{ + /* Per-process CPU limit, in seconds. */ + RLIMIT_CPU = 0, +#define RLIMIT_CPU RLIMIT_CPU + + /* Largest file that can be created, in bytes. */ + RLIMIT_FSIZE = 1, +#define RLIMIT_FSIZE RLIMIT_FSIZE + + /* Maximum size of data segment, in bytes. */ + RLIMIT_DATA = 2, +#define RLIMIT_DATA RLIMIT_DATA + + /* Maximum size of stack segment, in bytes. */ + RLIMIT_STACK = 3, +#define RLIMIT_STACK RLIMIT_STACK + + /* Largest core file that can be created, in bytes. */ + RLIMIT_CORE = 4, +#define RLIMIT_CORE RLIMIT_CORE + + /* Largest resident set size, in bytes. + This affects swapping; processes that are exceeding their + resident set size will be more likely to have physical memory + taken from them. */ + __RLIMIT_RSS = 7, +#define RLIMIT_RSS __RLIMIT_RSS + + /* Number of open files. */ + RLIMIT_NOFILE = 5, + __RLIMIT_OFILE = RLIMIT_NOFILE, /* BSD name for same. */ +#define RLIMIT_NOFILE RLIMIT_NOFILE +#define RLIMIT_OFILE __RLIMIT_OFILE + + /* Address space limit (?) */ + RLIMIT_AS = 6, +#define RLIMIT_AS RLIMIT_AS + + /* Number of processes. */ + __RLIMIT_NPROC = 8, +#define RLIMIT_NPROC __RLIMIT_NPROC + + /* Locked-in-memory address space. */ + __RLIMIT_MEMLOCK = 9, +#define RLIMIT_MEMLOCK __RLIMIT_MEMLOCK + + /* Maximum number of file locks. */ + __RLIMIT_LOCKS = 10, +#define RLIMIT_LOCKS __RLIMIT_LOCKS + + /* Maximum number of pending signals. */ + __RLIMIT_SIGPENDING = 11, +#define RLIMIT_SIGPENDING __RLIMIT_SIGPENDING + + /* Maximum bytes in POSIX message queues. */ + __RLIMIT_MSGQUEUE = 12, +#define RLIMIT_MSGQUEUE __RLIMIT_MSGQUEUE + + /* Maximum nice priority allowed to raise to. + Nice levels 19 .. -20 correspond to 0 .. 39 + values of this resource limit. */ + __RLIMIT_NICE = 13, +#define RLIMIT_NICE __RLIMIT_NICE + + /* Maximum realtime priority allowed for non-priviledged + processes. */ + __RLIMIT_RTPRIO = 14, +#define RLIMIT_RTPRIO __RLIMIT_RTPRIO + + __RLIMIT_NLIMITS = 15, + __RLIM_NLIMITS = __RLIMIT_NLIMITS +#define RLIMIT_NLIMITS __RLIMIT_NLIMITS +#define RLIM_NLIMITS __RLIM_NLIMITS +}; + +/* Value to indicate that there is no limit. */ +#if _MIPS_SIM == _ABI64 +/* The N64 syscall uses this value. */ +# define RLIM_INFINITY 0xffffffffffffffffUL +# ifdef __USE_LARGEFILE64 +# define RLIM64_INFINITY 0xffffffffffffffffUL +# endif +#else +/* The O32 and N32 syscalls use 0x7fffffff. */ +# ifndef __USE_FILE_OFFSET64 +# define RLIM_INFINITY ((long int)(~0UL >> 1)) +# else +# define RLIM_INFINITY 0x7fffffffffffffffULL +# endif +# ifdef __USE_LARGEFILE64 +# define RLIM64_INFINITY 0x7fffffffffffffffULL +# endif +#endif + +/* We can represent all limits. */ +#define RLIM_SAVED_MAX RLIM_INFINITY +#define RLIM_SAVED_CUR RLIM_INFINITY + + +/* Type for resource quantity measurement. */ +#ifndef __USE_FILE_OFFSET64 +typedef __rlim_t rlim_t; +#else +typedef __rlim64_t rlim_t; +#endif +#ifdef __USE_LARGEFILE64 +typedef __rlim64_t rlim64_t; +#endif + +struct rlimit + { + /* The current (soft) limit. */ + rlim_t rlim_cur; + /* The hard limit. */ + rlim_t rlim_max; + }; + +#ifdef __USE_LARGEFILE64 +struct rlimit64 + { + /* The current (soft) limit. */ + rlim64_t rlim_cur; + /* The hard limit. */ + rlim64_t rlim_max; + }; +#endif + +/* Whose usage statistics do you want? */ +enum __rusage_who +{ + /* The calling process. */ + RUSAGE_SELF = 0, +#define RUSAGE_SELF RUSAGE_SELF + + /* All of its terminated child processes. */ + RUSAGE_CHILDREN = -1 +#define RUSAGE_CHILDREN RUSAGE_CHILDREN +}; + +#define __need_timeval +#include /* For `struct timeval'. */ + +/* Structure which says how much of each resource has been used. */ +struct rusage + { + /* Total amount of user time used. */ + struct timeval ru_utime; + /* Total amount of system time used. */ + struct timeval ru_stime; + /* Maximum resident set size (in kilobytes). */ + long int ru_maxrss; + /* Amount of sharing of text segment memory + with other processes (kilobyte-seconds). */ + long int ru_ixrss; + /* Amount of data segment memory used (kilobyte-seconds). */ + long int ru_idrss; + /* Amount of stack memory used (kilobyte-seconds). */ + long int ru_isrss; + /* Number of soft page faults (i.e. those serviced by reclaiming + a page from the list of pages awaiting reallocation. */ + long int ru_minflt; + /* Number of hard page faults (i.e. those that required I/O). */ + long int ru_majflt; + /* Number of times a process was swapped out of physical memory. */ + long int ru_nswap; + /* Number of input operations via the file system. Note: This + and `ru_oublock' do not include operations with the cache. */ + long int ru_inblock; + /* Number of output operations via the file system. */ + long int ru_oublock; + /* Number of IPC messages sent. */ + long int ru_msgsnd; + /* Number of IPC messages received. */ + long int ru_msgrcv; + /* Number of signals delivered. */ + long int ru_nsignals; + /* Number of voluntary context switches, i.e. because the process + gave up the process before it had to (usually to wait for some + resource to be available). */ + long int ru_nvcsw; + /* Number of involuntary context switches, i.e. a higher priority process + became runnable or the current process used up its time slice. */ + long int ru_nivcsw; + }; + +/* Priority limits. */ +#define PRIO_MIN -20 /* Minimum priority a process can have. */ +#define PRIO_MAX 20 /* Maximum priority a process can have. */ + +/* The type of the WHICH argument to `getpriority' and `setpriority', + indicating what flavor of entity the WHO argument specifies. */ +enum __priority_which +{ + PRIO_PROCESS = 0, /* WHO is a process ID. */ +#define PRIO_PROCESS PRIO_PROCESS + PRIO_PGRP = 1, /* WHO is a process group ID. */ +#define PRIO_PGRP PRIO_PGRP + PRIO_USER = 2 /* WHO is a user ID. */ +#define PRIO_USER PRIO_USER +}; diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/sem.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/sem.h new file mode 100644 index 00000000..6282de9c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/sem.h @@ -0,0 +1,85 @@ +/* Copyright (C) 1995, 1996, 1997, 1998, 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_SEM_H +# error "Never include directly; use instead." +#endif + +#include + +/* Flags for `semop'. */ +#define SEM_UNDO 0x1000 /* undo the operation on exit */ + +/* Commands for `semctl'. */ +#define GETPID 11 /* get sempid */ +#define GETVAL 12 /* get semval */ +#define GETALL 13 /* get all semval's */ +#define GETNCNT 14 /* get semncnt */ +#define GETZCNT 15 /* get semzcnt */ +#define SETVAL 16 /* set semval */ +#define SETALL 17 /* set all semval's */ + + +/* Data structure describing a set of semaphores. */ +struct semid_ds +{ + struct ipc_perm sem_perm; /* operation permission struct */ + __time_t sem_otime; /* last semop() time */ + __time_t sem_ctime; /* last time changed by semctl() */ + unsigned long int sem_nsems; /* number of semaphores in set */ + unsigned long int __unused1; + unsigned long int __unused2; +}; + +/* The user should define a union like the following to use it for arguments + for `semctl'. + + union semun + { + int val; <= value for SETVAL + struct semid_ds *buf; <= buffer for IPC_STAT & IPC_SET + unsigned short int *array; <= array for GETALL & SETALL + struct seminfo *__buf; <= buffer for IPC_INFO + }; + + Previous versions of this file used to define this union but this is + incorrect. One can test the macro _SEM_SEMUN_UNDEFINED to see whether + one must define the union or not. */ +#define _SEM_SEMUN_UNDEFINED 1 + +#ifdef __USE_MISC + +/* ipcs ctl cmds */ +# define SEM_STAT 18 +# define SEM_INFO 19 + +struct seminfo +{ + int semmap; + int semmni; + int semmns; + int semmnu; + int semmsl; + int semopm; + int semume; + int semusz; + int semvmx; + int semaem; +}; + +#endif /* __USE_MISC */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/setjmp.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/setjmp.h new file mode 100644 index 00000000..08e74fe0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/setjmp.h @@ -0,0 +1,72 @@ +/* Define the machine-dependent type `jmp_buf'. MIPS version. + Copyright (C) 1992,93,95,97,2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _BITS_SETJMP_H +#define _BITS_SETJMP_H 1 + +#if !defined _SETJMP_H && !defined _PTHREAD_H +# error "Never include directly; use instead." +#endif + +#include + +typedef struct + { + /* Program counter. */ + void * __pc; + + /* Stack pointer. */ + void * __sp; + + /* Callee-saved registers s0 through s7. */ +#if _MIPS_SIM == _MIPS_SIM_ABI32 + int __regs[8]; +#else + long long __regs[8]; +#endif + + /* The frame pointer. */ + void * __fp; + + /* The global pointer. */ + void * __gp; + + /* Floating point status register. */ + int __fpc_csr; + + /* Callee-saved floating point registers. */ +#if _MIPS_SIM == _MIPS_SIM_ABI64 + double __fpregs[8]; +#else /* N32 || O32 */ + double __fpregs[6]; +#endif /* N32 || O32 */ + } __jmp_buf[1]; + +#ifdef __USE_MISC +/* Offset to the program counter in `jmp_buf'. */ +# define JB_PC 0 +#endif + + +/* Test if longjmp to JMPBUF would unwind the frame + containing a local variable at ADDRESS. */ +#define _JMPBUF_UNWINDS(jmpbuf, address) \ + ((void *) (address) < (void *) (jmpbuf)[0].__sp) + +#endif /* bits/setjmp.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/shm.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/shm.h new file mode 100644 index 00000000..b3083346 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/shm.h @@ -0,0 +1,94 @@ +/* Copyright (C) 1995,1996,1997,2000,2001,2002,2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_SHM_H +# error "Never include directly; use instead." +#endif + +#include + +/* Permission flag for shmget. */ +#define SHM_R 0400 /* or S_IRUGO from */ +#define SHM_W 0200 /* or S_IWUGO from */ + +/* Flags for `shmat'. */ +#define SHM_RDONLY 010000 /* attach read-only else read-write */ +#define SHM_RND 020000 /* round attach address to SHMLBA */ +#define SHM_REMAP 040000 /* take-over region on attach */ + +/* Commands for `shmctl'. */ +#define SHM_LOCK 11 /* lock segment (root only) */ +#define SHM_UNLOCK 12 /* unlock segment (root only) */ + +/* Segment low boundary address multiple. */ +#define SHMLBA 0x40000 + + +/* Type to count number of attaches. */ +typedef unsigned long int shmatt_t; + +/* Data structure describing a set of semaphores. */ +struct shmid_ds + { + struct ipc_perm shm_perm; /* operation permission struct */ + size_t shm_segsz; /* size of segment in bytes */ + __time_t shm_atime; /* time of last shmat() */ + __time_t shm_dtime; /* time of last shmdt() */ + __time_t shm_ctime; /* time of last change by shmctl() */ + __pid_t shm_cpid; /* pid of creator */ + __pid_t shm_lpid; /* pid of last shmop */ + shmatt_t shm_nattch; /* number of current attaches */ + unsigned long int __unused1; + unsigned long int __unused2; + }; + +#ifdef __USE_MISC + +/* ipcs ctl commands */ +# define SHM_STAT 13 +# define SHM_INFO 14 + +/* shm_mode upper byte flags */ +# define SHM_DEST 01000 /* segment will be destroyed on last detach */ +# define SHM_LOCKED 02000 /* segment will not be swapped */ +# define SHM_HUGETLB 04000 /* segment is mapped via hugetlb */ + +struct shminfo + { + unsigned long int shmmax; + unsigned long int shmmin; + unsigned long int shmmni; + unsigned long int shmseg; + unsigned long int shmall; + unsigned long int __unused1; + unsigned long int __unused2; + unsigned long int __unused3; + unsigned long int __unused4; + }; + +struct shm_info + { + int used_ids; + unsigned long int shm_tot; /* total allocated shm */ + unsigned long int shm_rss; /* total resident shm */ + unsigned long int shm_swp; /* total swapped shm */ + unsigned long int swap_attempts; + unsigned long int swap_successes; + }; + +#endif /* __USE_MISC */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/sigaction.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/sigaction.h new file mode 100644 index 00000000..cc689d14 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/sigaction.h @@ -0,0 +1,74 @@ +/* The proper definitions for Linux/MIPS's sigaction. + Copyright (C) 1993, 1994, 1995, 1997, 1998, 1999, 2000, 2003 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SIGNAL_H +# error "Never include directly; use instead." +#endif + +/* Structure describing the action to be taken when a signal arrives. */ +struct sigaction { + unsigned sa_flags; +#ifdef __USE_POSIX199309 + union { + __sighandler_t sa_handler; + void (*sa_sigaction)(int, siginfo_t *, void *); + } __sigaction_handler; +# define sa_handler __sigaction_handler.sa_handler +# define sa_sigaction __sigaction_handler.sa_sigaction +#else + __sighandler_t sa_handler; +#endif + sigset_t sa_mask; + void (*sa_restorer)(void); + /*int s_resv[1]; - reserved [deleted in uclibc] */ +}; + +/* Bits in `sa_flags'. */ +/* Please note that some Linux kernels versions use different values for these + flags which is a bug in those kernel versions. */ +#define SA_NOCLDSTOP 0x00000001 /* Don't send SIGCHLD when children stop. */ +#define SA_NOCLDWAIT 0x00010000 /* Don't create zombie on child death. */ +#define SA_SIGINFO 0x00000008 /* Invoke signal-catching function with + three arguments instead of one. */ +#if defined __USE_UNIX98 || defined __USE_MISC +# define SA_ONSTACK 0x08000000 /* Use signal stack by using `sa_restorer'. */ +# define SA_RESETHAND 0x80000000 /* Reset to SIG_DFL on entry to handler. */ +# define SA_RESTART 0x10000000 /* Restart syscall on signal return. */ +# define SA_NODEFER 0x40000000 /* Don't automatically block the signal when + its handler is being executed. */ +#endif +#ifdef __USE_MISC +# define SA_INTERRUPT 0x20000000 /* Historical no-op. */ + +/* Some aliases for the SA_ constants. */ +# define SA_NOMASK SA_NODEFER +# define SA_ONESHOT SA_RESETHAND +# define SA_STACK SA_ONSTACK +#endif + +/* Values for the HOW argument to `sigprocmask'. */ +#define SIG_NOP 0 /* 0 is unused to catch errors */ +#define SIG_BLOCK 1 /* Block signals. */ +#define SIG_UNBLOCK 2 /* Unblock signals. */ +#define SIG_SETMASK 3 /* Set the set of blocked signals. */ +#ifdef __USE_MISC +# define SIG_SETMASK32 256 /* Goodie from SGI for BSD compatibility: + set only the low 32 bit of the sigset. */ +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/sigcontext.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/sigcontext.h new file mode 100644 index 00000000..99faeed3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/sigcontext.h @@ -0,0 +1,84 @@ +/* Copyright (C) 1996, 1997, 1998, 2003, 2004, 2006 Free Software + Foundation, Inc. This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _BITS_SIGCONTEXT_H +#define _BITS_SIGCONTEXT_H 1 + +#if !defined _SIGNAL_H && !defined _SYS_UCONTEXT_H +# error "Never use directly; include instead." +#endif + +#include + +#if _MIPS_SIM == _ABIO32 + +/* Certain unused fields were replaced with new ones in 2.6.12-rc4. + The changes were as follows: + + sc_cause -> sc_hi1 + sc_badvaddr -> sc_lo1 + sc_sigset[0] -> sc_hi2 + sc_sigset[1] -> sc_lo2 + sc_sigset[2] -> sc_hi3 + sc_sigset[3] -> sc_lo3 + + sc_regmask, sc_ownedfp and sc_fpc_eir are not used. */ +struct sigcontext { + unsigned int sc_regmask; + unsigned int sc_status; + unsigned long long sc_pc; + unsigned long long sc_regs[32]; + unsigned long long sc_fpregs[32]; + unsigned int sc_ownedfp; + unsigned int sc_fpc_csr; + unsigned int sc_fpc_eir; + unsigned int sc_used_math; + unsigned int sc_dsp; + unsigned long long sc_mdhi; + unsigned long long sc_mdlo; + unsigned long sc_hi1; + unsigned long sc_lo1; + unsigned long sc_hi2; + unsigned long sc_lo2; + unsigned long sc_hi3; + unsigned long sc_lo3; +}; + +#else + +/* This structure changed in 2.6.12-rc4 when DSP support was added. */ +struct sigcontext { + unsigned long long sc_regs[32]; + unsigned long long sc_fpregs[32]; + unsigned long long sc_mdhi; + unsigned long long sc_hi1; + unsigned long long sc_hi2; + unsigned long long sc_hi3; + unsigned long long sc_mdlo; + unsigned long long sc_lo1; + unsigned long long sc_lo2; + unsigned long long sc_lo3; + unsigned long long sc_pc; + unsigned int sc_fpc_csr; + unsigned int sc_used_math; + unsigned int sc_dsp; + unsigned int sc_reserved; +}; + +#endif /* _MIPS_SIM != _ABIO32 */ +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/sigcontextinfo.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/sigcontextinfo.h new file mode 100644 index 00000000..f453c8d9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/sigcontextinfo.h @@ -0,0 +1,43 @@ +/* Copyright (C) 2000, 2001, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Andreas Jaeger , 2000. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + + +#include + +#if _MIPS_SIM == _ABIO32 + +#define SIGCONTEXT unsigned long _code, struct sigcontext * +#define SIGCONTEXT_EXTRA_ARGS _code, +#define GET_PC(ctx) ((void *) ctx->sc_pc) +#define GET_FRAME(ctx) ((void *) ctx->sc_regs[30]) +#define GET_STACK(ctx) ((void *) ctx->sc_regs[29]) +#define CALL_SIGHANDLER(handler, signo, ctx) \ + (handler)((signo), SIGCONTEXT_EXTRA_ARGS (ctx)) + +#else + +#define SIGCONTEXT unsigned long _code, ucontext_t * +#define SIGCONTEXT_EXTRA_ARGS _code, +#define GET_PC(ctx) ((void *) ctx->uc_mcontext.pc) +#define GET_FRAME(ctx) ((void *) ctx->uc_mcontext.gregs[30]) +#define GET_STACK(ctx) ((void *) ctx->uc_mcontext.gregs[29]) +#define CALL_SIGHANDLER(handler, signo, ctx) \ + (handler)((signo), SIGCONTEXT_EXTRA_ARGS (ctx)) + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/siginfo.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/siginfo.h new file mode 100644 index 00000000..ba3e1f63 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/siginfo.h @@ -0,0 +1,311 @@ +/* siginfo_t, sigevent and constants. Linux/MIPS version. + Copyright (C) 1997, 1998, 2000, 2001, 2002, 2003, 2004, 2005 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#if !defined _SIGNAL_H && !defined __need_siginfo_t \ + && !defined __need_sigevent_t +# error "Never include this file directly. Use instead" +#endif + +#include + +#if (!defined __have_sigval_t \ + && (defined _SIGNAL_H || defined __need_siginfo_t \ + || defined __need_sigevent_t)) +# define __have_sigval_t 1 + +/* Type for data associated with a signal. */ +typedef union sigval + { + int sival_int; + void *sival_ptr; + } sigval_t; +#endif + +#if (!defined __have_siginfo_t \ + && (defined _SIGNAL_H || defined __need_siginfo_t)) +# define __have_siginfo_t 1 + +# define __SI_MAX_SIZE 128 +# if __WORDSIZE == 64 +# define __SI_PAD_SIZE ((__SI_MAX_SIZE / sizeof (int)) - 4) +# else +# define __SI_PAD_SIZE ((__SI_MAX_SIZE / sizeof (int)) - 3) +# endif + + +typedef struct siginfo + { + int si_signo; /* Signal number. */ + int si_code; /* Signal code. */ + int si_errno; /* If non-zero, an errno value associated with + this signal, as defined in . */ + int __pad0[__SI_MAX_SIZE / sizeof (int) - __SI_PAD_SIZE - 3]; + /* Explicit padding. */ + + union + { + int _pad[__SI_PAD_SIZE]; + + /* kill(). */ + struct + { + __pid_t si_pid; /* Sending process ID. */ + __uid_t si_uid; /* Real user ID of sending process. */ + } _kill; + + /* SIGCHLD. */ + struct + { + __pid_t si_pid; /* Which child. */ + __uid_t si_uid; /* Real user ID of sending process. */ + int si_status; /* Exit value or signal. */ + __clock_t si_utime; + __clock_t si_stime; + } _sigchld; + + /* SIGILL, SIGFPE, SIGSEGV, SIGBUS. */ + struct + { + void *si_addr; /* Faulting insn/memory ref. */ + } _sigfault; + + /* SIGPOLL. */ + struct + { + int si_band; /* Band event for SIGPOLL. */ + int si_fd; + } _sigpoll; + + /* POSIX.1b timers. */ + struct + { + unsigned int _timer1; + unsigned int _timer2; + } _timer; + + /* POSIX.1b signals. */ + struct + { + __pid_t si_pid; /* Sending process ID. */ + __uid_t si_uid; /* Real user ID of sending process. */ + sigval_t si_sigval; /* Signal value. */ + } _rt; + } _sifields; + } siginfo_t; + + +/* X/Open requires some more fields with fixed names. */ +# define si_pid _sifields._kill.si_pid +# define si_uid _sifields._kill.si_uid +# define si_status _sifields._sigchld.si_status +# define si_utime _sifields._sigchld.si_utime +# define si_stime _sifields._sigchld.si_stime +# define si_value _sifields._rt.si_sigval +# define si_int _sifields._rt.si_sigval.sival_int +# define si_ptr _sifields._rt.si_sigval.sival_ptr +# define si_addr _sifields._sigfault.si_addr +# define si_band _sifields._sigpoll.si_band +# define si_fd _sifields._sigpoll.si_fd + + +/* Values for `si_code'. Positive values are reserved for kernel-generated + signals. */ +enum +{ + SI_ASYNCNL = -60, /* Sent by asynch name lookup completion. */ +# define SI_ASYNCNL SI_ASYNCNL + SI_TKILL = -6, /* Sent by tkill. */ +# define SI_TKILL SI_TKILL + SI_SIGIO, /* Sent by queued SIGIO. */ +# define SI_SIGIO SI_SIGIO + SI_MESGQ, /* Sent by real time mesq state change. */ +# define SI_MESGQ SI_MESGQ + SI_TIMER, /* Sent by real time mesq state change. */ +# define SI_TIMER SI_TIMER + SI_ASYNCIO, /* Sent by AIO completion. */ +# define SI_ASYNCIO SI_ASYNCIO + SI_QUEUE, /* Sent by sigqueue. */ +# define SI_QUEUE SI_QUEUE + SI_USER, /* Sent by kill, sigsend, raise. */ +# define SI_USER SI_USER + SI_KERNEL = 0x80 /* Send by kernel. */ +#define SI_KERNEL SI_KERNEL +}; + + +/* `si_code' values for SIGILL signal. */ +enum +{ + ILL_ILLOPC = 1, /* Illegal opcode. */ +# define ILL_ILLOPC ILL_ILLOPC + ILL_ILLOPN, /* Illegal operand. */ +# define ILL_ILLOPN ILL_ILLOPN + ILL_ILLADR, /* Illegal addressing mode. */ +# define ILL_ILLADR ILL_ILLADR + ILL_ILLTRP, /* Illegal trap. */ +# define ILL_ILLTRP ILL_ILLTRP + ILL_PRVOPC, /* Privileged opcode. */ +# define ILL_PRVOPC ILL_PRVOPC + ILL_PRVREG, /* Privileged register. */ +# define ILL_PRVREG ILL_PRVREG + ILL_COPROC, /* Coprocessor error. */ +# define ILL_COPROC ILL_COPROC + ILL_BADSTK /* Internal stack error. */ +# define ILL_BADSTK ILL_BADSTK +}; + +/* `si_code' values for SIGFPE signal. */ +enum +{ + FPE_INTDIV = 1, /* Integer divide by zero. */ +# define FPE_INTDIV FPE_INTDIV + FPE_INTOVF, /* Integer overflow. */ +# define FPE_INTOVF FPE_INTOVF + FPE_FLTDIV, /* Floating point divide by zero. */ +# define FPE_FLTDIV FPE_FLTDIV + FPE_FLTOVF, /* Floating point overflow. */ +# define FPE_FLTOVF FPE_FLTOVF + FPE_FLTUND, /* Floating point underflow. */ +# define FPE_FLTUND FPE_FLTUND + FPE_FLTRES, /* Floating point inexact result. */ +# define FPE_FLTRES FPE_FLTRES + FPE_FLTINV, /* Floating point invalid operation. */ +# define FPE_FLTINV FPE_FLTINV + FPE_FLTSUB /* Subscript out of range. */ +# define FPE_FLTSUB FPE_FLTSUB +}; + +/* `si_code' values for SIGSEGV signal. */ +enum +{ + SEGV_MAPERR = 1, /* Address not mapped to object. */ +# define SEGV_MAPERR SEGV_MAPERR + SEGV_ACCERR /* Invalid permissions for mapped object. */ +# define SEGV_ACCERR SEGV_ACCERR +}; + +/* `si_code' values for SIGBUS signal. */ +enum +{ + BUS_ADRALN = 1, /* Invalid address alignment. */ +# define BUS_ADRALN BUS_ADRALN + BUS_ADRERR, /* Non-existant physical address. */ +# define BUS_ADRERR BUS_ADRERR + BUS_OBJERR /* Object specific hardware error. */ +# define BUS_OBJERR BUS_OBJERR +}; + +/* `si_code' values for SIGTRAP signal. */ +enum +{ + TRAP_BRKPT = 1, /* Process breakpoint. */ +# define TRAP_BRKPT TRAP_BRKPT + TRAP_TRACE /* Process trace trap. */ +# define TRAP_TRACE TRAP_TRACE +}; + +/* `si_code' values for SIGCHLD signal. */ +enum +{ + CLD_EXITED = 1, /* Child has exited. */ +# define CLD_EXITED CLD_EXITED + CLD_KILLED, /* Child was killed. */ +# define CLD_KILLED CLD_KILLED + CLD_DUMPED, /* Child terminated abnormally. */ +# define CLD_DUMPED CLD_DUMPED + CLD_TRAPPED, /* Traced child has trapped. */ +# define CLD_TRAPPED CLD_TRAPPED + CLD_STOPPED, /* Child has stopped. */ +# define CLD_STOPPED CLD_STOPPED + CLD_CONTINUED /* Stopped child has continued. */ +# define CLD_CONTINUED CLD_CONTINUED +}; + +/* `si_code' values for SIGPOLL signal. */ +enum +{ + POLL_IN = 1, /* Data input available. */ +# define POLL_IN POLL_IN + POLL_OUT, /* Output buffers available. */ +# define POLL_OUT POLL_OUT + POLL_MSG, /* Input message available. */ +# define POLL_MSG POLL_MSG + POLL_ERR, /* I/O error. */ +# define POLL_ERR POLL_ERR + POLL_PRI, /* High priority input available. */ +# define POLL_PRI POLL_PRI + POLL_HUP /* Device disconnected. */ +# define POLL_HUP POLL_HUP +}; + +# undef __need_siginfo_t +#endif /* !have siginfo_t && (have _SIGNAL_H || need siginfo_t). */ + + +#if (defined _SIGNAL_H || defined __need_sigevent_t) \ + && !defined __have_sigevent_t +# define __have_sigevent_t 1 + +/* Structure to transport application-defined values with signals. */ +# define __SIGEV_MAX_SIZE 64 +# define __SIGEV_HEAD_SIZE (sizeof(long) + 2*sizeof(int)) +# define __SIGEV_PAD_SIZE ((__SIGEV_MAX_SIZE - __SIGEV_HEAD_SIZE) / sizeof (int)) + +/* Forward declaration of the `pthread_attr_t' type. */ +struct __pthread_attr_s; + +/* XXX This one might need to change!!! */ +typedef struct sigevent + { + sigval_t sigev_value; + int sigev_signo; + int sigev_notify; + + union + { + int _pad[__SIGEV_PAD_SIZE]; + + struct + { + void (*_function) (sigval_t); /* Function to start. */ + void *_attribute; /* Really pthread_attr_t. */ + } _sigev_thread; + } _sigev_un; + } sigevent_t; + +/* POSIX names to access some of the members. */ +# define sigev_notify_function _sigev_un._sigev_thread._function +# define sigev_notify_attributes _sigev_un._sigev_thread._attribute + +/* `sigev_notify' values. */ +enum +{ + SIGEV_SIGNAL = 0, /* Notify via signal. */ +# define SIGEV_SIGNAL SIGEV_SIGNAL + SIGEV_NONE, /* Other notification: meaningless. */ +# define SIGEV_NONE SIGEV_NONE + SIGEV_THREAD, /* Deliver via thread creation. */ +# define SIGEV_THREAD SIGEV_THREAD + + SIGEV_THREAD_ID = 4 /* Send signal to specific thread. */ +#define SIGEV_THREAD_ID SIGEV_THREAD_ID +}; + +#endif /* have _SIGNAL_H. */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/signum.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/signum.h new file mode 100644 index 00000000..b9c64e67 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/signum.h @@ -0,0 +1,60 @@ +/* Signal number definitions. Linux version. + Copyright (C) 1995, 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifdef _SIGNAL_H + +#define SIGHUP 1 /* Hangup (POSIX). */ +#define SIGINT 2 /* Interrupt (ANSI). */ +#define SIGQUIT 3 /* Quit (POSIX). */ +#define SIGILL 4 /* Illegal instruction (ANSI). */ +#define SIGTRAP 5 /* Trace trap (POSIX). */ +#define SIGIOT 6 /* IOT trap (4.2 BSD). */ +#define SIGABRT SIGIOT /* Abort (ANSI). */ +#define SIGEMT 7 +#define SIGFPE 8 /* Floating-point exception (ANSI). */ +#define SIGKILL 9 /* Kill, unblockable (POSIX). */ +#define SIGBUS 10 /* BUS error (4.2 BSD). */ +#define SIGSEGV 11 /* Segmentation violation (ANSI). */ +#define SIGSYS 12 +#define SIGPIPE 13 /* Broken pipe (POSIX). */ +#define SIGALRM 14 /* Alarm clock (POSIX). */ +#define SIGTERM 15 /* Termination (ANSI). */ +#define SIGUSR1 16 /* User-defined signal 1 (POSIX). */ +#define SIGUSR2 17 /* User-defined signal 2 (POSIX). */ +#define SIGCHLD 18 /* Child status has changed (POSIX). */ +#define SIGCLD SIGCHLD /* Same as SIGCHLD (System V). */ +#define SIGPWR 19 /* Power failure restart (System V). */ +#define SIGWINCH 20 /* Window size change (4.3 BSD, Sun). */ +#define SIGURG 21 /* Urgent condition on socket (4.2 BSD). */ +#define SIGIO 22 /* I/O now possible (4.2 BSD). */ +#define SIGPOLL SIGIO /* Pollable event occurred (System V). */ +#define SIGSTOP 23 /* Stop, unblockable (POSIX). */ +#define SIGTSTP 24 /* Keyboard stop (POSIX). */ +#define SIGCONT 25 /* Continue (POSIX). */ +#define SIGTTIN 26 /* Background read from tty (POSIX). */ +#define SIGTTOU 27 /* Background write to tty (POSIX). */ +#define SIGVTALRM 28 /* Virtual alarm clock (4.2 BSD). */ +#define SIGPROF 29 /* Profiling alarm clock (4.2 BSD). */ +#define SIGXCPU 30 /* CPU limit exceeded (4.2 BSD). */ +#define SIGXFSZ 31 /* File size limit exceeded (4.2 BSD). */ + +/* Biggest signal number + 1 (including real-time signals). */ +#define _NSIG 129 + +#endif /* included. */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/sigstack.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/sigstack.h new file mode 100644 index 00000000..d2c85522 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/sigstack.h @@ -0,0 +1,55 @@ +/* sigstack, sigaltstack definitions. + Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SIGNAL_H +# error "Never include this file directly. Use instead" +#endif + + +/* Structure describing a signal stack (obsolete). */ +struct sigstack + { + void *ss_sp; /* Signal stack pointer. */ + int ss_onstack; /* Nonzero if executing on this stack. */ + }; + + +/* Possible values for `ss_flags.'. */ +enum +{ + SS_ONSTACK = 1, +#define SS_ONSTACK SS_ONSTACK + SS_DISABLE +#define SS_DISABLE SS_DISABLE +}; + +/* Minimum stack size for a signal handler. */ +#define MINSIGSTKSZ 2048 + +/* System default stack size. */ +#define SIGSTKSZ 8192 + + +/* Alternate, preferred interface. */ +typedef struct sigaltstack + { + void *ss_sp; + size_t ss_size; + int ss_flags; + } stack_t; diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/socket.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/socket.h new file mode 100644 index 00000000..b46e7be2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/socket.h @@ -0,0 +1,349 @@ +/* System-specific socket constants and types. Linux/MIPS version. + Copyright (C) 1991, 92, 1994-1999, 2000, 2001, 2004, 2005, 2006 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef __BITS_SOCKET_H +#define __BITS_SOCKET_H + +#if !defined _SYS_SOCKET_H && !defined _NETINET_IN_H +# error "Never include directly; use instead." +#endif + +#define __need_size_t +#define __need_NULL +#include + +#include +#include + +/* Type for length arguments in socket calls. */ +#ifndef __socklen_t_defined +typedef __socklen_t socklen_t; +# define __socklen_t_defined +#endif + +/* Types of sockets. */ +enum __socket_type +{ + SOCK_DGRAM = 1, /* Connectionless, unreliable datagrams + of fixed maximum length. */ +#define SOCK_DGRAM SOCK_DGRAM + SOCK_STREAM = 2, /* Sequenced, reliable, connection-based + byte streams. */ +#define SOCK_STREAM SOCK_STREAM + SOCK_RAW = 3, /* Raw protocol interface. */ +#define SOCK_RAW SOCK_RAW + SOCK_RDM = 4, /* Reliably-delivered messages. */ +#define SOCK_RDM SOCK_RDM + SOCK_SEQPACKET = 5, /* Sequenced, reliable, connection-based, + datagrams of fixed maximum length. */ +#define SOCK_SEQPACKET SOCK_SEQPACKET + SOCK_DCCP = 6, +#define SOCK_DCCP SOCK_DCCP /* Datagram Congestion Control Protocol. */ + SOCK_PACKET = 10, /* Linux specific way of getting packets + at the dev level. For writing rarp and + other similar things on the user level. */ +#define SOCK_PACKET SOCK_PACKET + /* Flags to be ORed into the type parameter of socket and socketpair and + used for the flags parameter of paccept. */ + + SOCK_CLOEXEC = 02000000, /* Atomically set close-on-exec flag for the + new descriptor(s). */ +#define SOCK_CLOEXEC SOCK_CLOEXEC + SOCK_NONBLOCK = 0200 /* Atomically mark descriptor(s) as + non-blocking. */ +#define SOCK_NONBLOCK SOCK_NONBLOCK +}; + +/* Protocol families. */ +#define PF_UNSPEC 0 /* Unspecified. */ +#define PF_LOCAL 1 /* Local to host (pipes and file-domain). */ +#define PF_UNIX PF_LOCAL /* Old BSD name for PF_LOCAL. */ +#define PF_FILE PF_LOCAL /* Another non-standard name for PF_LOCAL. */ +#define PF_INET 2 /* IP protocol family. */ +#define PF_AX25 3 /* Amateur Radio AX.25. */ +#define PF_IPX 4 /* Novell Internet Protocol. */ +#define PF_APPLETALK 5 /* Appletalk DDP. */ +#define PF_NETROM 6 /* Amateur radio NetROM. */ +#define PF_BRIDGE 7 /* Multiprotocol bridge. */ +#define PF_ATMPVC 8 /* ATM PVCs. */ +#define PF_X25 9 /* Reserved for X.25 project. */ +#define PF_INET6 10 /* IP version 6. */ +#define PF_ROSE 11 /* Amateur Radio X.25 PLP. */ +#define PF_DECnet 12 /* Reserved for DECnet project. */ +#define PF_NETBEUI 13 /* Reserved for 802.2LLC project. */ +#define PF_SECURITY 14 /* Security callback pseudo AF. */ +#define PF_KEY 15 /* PF_KEY key management API. */ +#define PF_NETLINK 16 +#define PF_ROUTE PF_NETLINK /* Alias to emulate 4.4BSD. */ +#define PF_PACKET 17 /* Packet family. */ +#define PF_ASH 18 /* Ash. */ +#define PF_ECONET 19 /* Acorn Econet. */ +#define PF_ATMSVC 20 /* ATM SVCs. */ +#define PF_SNA 22 /* Linux SNA Project */ +#define PF_IRDA 23 /* IRDA sockets. */ +#define PF_PPPOX 24 /* PPPoX sockets. */ +#define PF_WANPIPE 25 /* Wanpipe API sockets. */ +#define PF_BLUETOOTH 31 /* Bluetooth sockets. */ +#define PF_MAX 32 /* For now.. */ + +/* Address families. */ +#define AF_UNSPEC PF_UNSPEC +#define AF_LOCAL PF_LOCAL +#define AF_UNIX PF_UNIX +#define AF_FILE PF_FILE +#define AF_INET PF_INET +#define AF_AX25 PF_AX25 +#define AF_IPX PF_IPX +#define AF_APPLETALK PF_APPLETALK +#define AF_NETROM PF_NETROM +#define AF_BRIDGE PF_BRIDGE +#define AF_ATMPVC PF_ATMPVC +#define AF_X25 PF_X25 +#define AF_INET6 PF_INET6 +#define AF_ROSE PF_ROSE +#define AF_DECnet PF_DECnet +#define AF_NETBEUI PF_NETBEUI +#define AF_SECURITY PF_SECURITY +#define AF_KEY PF_KEY +#define AF_NETLINK PF_NETLINK +#define AF_ROUTE PF_ROUTE +#define AF_PACKET PF_PACKET +#define AF_ASH PF_ASH +#define AF_ECONET PF_ECONET +#define AF_ATMSVC PF_ATMSVC +#define AF_SNA PF_SNA +#define AF_IRDA PF_IRDA +#define AF_PPPOX PF_PPPOX +#define AF_WANPIPE PF_WANPIPE +#define AF_BLUETOOTH PF_BLUETOOTH +#define AF_MAX PF_MAX + +/* Socket level values. Others are defined in the appropriate headers. + + XXX These definitions also should go into the appropriate headers as + far as they are available. */ +#define SOL_RAW 255 +#define SOL_DECNET 261 +#define SOL_X25 262 +#define SOL_PACKET 263 +#define SOL_ATM 264 /* ATM layer (cell level). */ +#define SOL_AAL 265 /* ATM Adaption Layer (packet level). */ +#define SOL_IRDA 266 + +/* Maximum queue length specifiable by listen. */ +#define SOMAXCONN 128 + +/* Get the definition of the macro to define the common sockaddr members. */ +#include + +/* Structure describing a generic socket address. */ +struct sockaddr + { + __SOCKADDR_COMMON (sa_); /* Common data: address family and length. */ + char sa_data[14]; /* Address data. */ + }; + + +/* Structure large enough to hold any socket address (with the historical + exception of AF_UNIX). We reserve 128 bytes. */ +#define __ss_aligntype unsigned long int +#define _SS_SIZE 128 +#define _SS_PADSIZE (_SS_SIZE - (2 * sizeof (__ss_aligntype))) + +struct sockaddr_storage + { + __SOCKADDR_COMMON (ss_); /* Address family, etc. */ + __ss_aligntype __ss_align; /* Force desired alignment. */ + char __ss_padding[_SS_PADSIZE]; + }; + + +/* Bits in the FLAGS argument to `send', `recv', et al. */ +enum + { + MSG_OOB = 0x01, /* Process out-of-band data. */ +#define MSG_OOB MSG_OOB + MSG_PEEK = 0x02, /* Peek at incoming messages. */ +#define MSG_PEEK MSG_PEEK + MSG_DONTROUTE = 0x04, /* Don't use local routing. */ +#define MSG_DONTROUTE MSG_DONTROUTE +#ifdef __USE_GNU + /* DECnet uses a different name. */ + MSG_TRYHARD = MSG_DONTROUTE, +# define MSG_TRYHARD MSG_DONTROUTE +#endif + MSG_CTRUNC = 0x08, /* Control data lost before delivery. */ +#define MSG_CTRUNC MSG_CTRUNC + MSG_PROXY = 0x10, /* Supply or ask second address. */ +#define MSG_PROXY MSG_PROXY + MSG_TRUNC = 0x20, +#define MSG_TRUNC MSG_TRUNC + MSG_DONTWAIT = 0x40, /* Nonblocking IO. */ +#define MSG_DONTWAIT MSG_DONTWAIT + MSG_EOR = 0x80, /* End of record. */ +#define MSG_EOR MSG_EOR + MSG_WAITALL = 0x100, /* Wait for a full request. */ +#define MSG_WAITALL MSG_WAITALL + MSG_FIN = 0x200, +#define MSG_FIN MSG_FIN + MSG_SYN = 0x400, +#define MSG_SYN MSG_SYN + MSG_CONFIRM = 0x800, /* Confirm path validity. */ +#define MSG_CONFIRM MSG_CONFIRM + MSG_RST = 0x1000, +#define MSG_RST MSG_RST + MSG_ERRQUEUE = 0x2000, /* Fetch message from error queue. */ +#define MSG_ERRQUEUE MSG_ERRQUEUE + MSG_NOSIGNAL = 0x4000, /* Do not generate SIGPIPE. */ +#define MSG_NOSIGNAL MSG_NOSIGNAL + MSG_MORE = 0x8000, /* Sender will send more. */ +#define MSG_MORE MSG_MORE + MSG_WAITFORONE = 0x10000, /* Wait for at least one packet to return.*/ +#define MSG_WAITFORONE MSG_WAITFORONE + + MSG_CMSG_CLOEXEC = 0x40000000 /* Set close_on_exit for file + descriptor received through + SCM_RIGHTS. */ +#define MSG_CMSG_CLOEXEC MSG_CMSG_CLOEXEC + }; + + +/* Structure describing messages sent by + `sendmsg' and received by `recvmsg'. */ +/* Note: do not change these members to match glibc; these match the + SuSv3 spec already (e.g. msg_iovlen/msg_controllen). + http://www.opengroup.org/onlinepubs/009695399/basedefs/sys/socket.h.html */ +/* Note: linux kernel uses __kernel_size_t (which is 8bytes on 64bit + platforms, and 4bytes on 32bit platforms) for msg_iovlen/msg_controllen */ +struct msghdr + { + void *msg_name; /* Address to send to/receive from. */ + socklen_t msg_namelen; /* Length of address data. */ + + struct iovec *msg_iov; /* Vector of data to send/receive into. */ +#if __WORDSIZE == 32 + int msg_iovlen; /* Number of elements in the vector. */ +#else + size_t msg_iovlen; /* Number of elements in the vector. */ +#endif + + void *msg_control; /* Ancillary data (eg BSD filedesc passing). */ +#if __WORDSIZE == 32 + socklen_t msg_controllen; /* Ancillary data buffer length. */ +#else + size_t msg_controllen; /* Ancillary data buffer length. */ +#endif + + int msg_flags; /* Flags on received message. */ + }; + +/* Structure used for storage of ancillary data object information. */ +struct cmsghdr + { + size_t cmsg_len; /* Length of data in cmsg_data plus length + of cmsghdr structure. */ + int cmsg_level; /* Originating protocol. */ + int cmsg_type; /* Protocol specific type. */ +#if (!defined __STRICT_ANSI__ && __GNUC__ >= 2) || __STDC_VERSION__ >= 199901L + __extension__ unsigned char __cmsg_data __flexarr; /* Ancillary data. */ +#endif + }; + +/* Ancillary data object manipulation macros. */ +#if (!defined __STRICT_ANSI__ && __GNUC__ >= 2) || __STDC_VERSION__ >= 199901L +# define CMSG_DATA(cmsg) ((cmsg)->__cmsg_data) +#else +# define CMSG_DATA(cmsg) ((unsigned char *) ((struct cmsghdr *) (cmsg) + 1)) +#endif +#define CMSG_NXTHDR(mhdr, cmsg) __cmsg_nxthdr (mhdr, cmsg) +#define CMSG_FIRSTHDR(mhdr) \ + ((size_t) (mhdr)->msg_controllen >= sizeof (struct cmsghdr) \ + ? (struct cmsghdr *) (mhdr)->msg_control : (struct cmsghdr *) NULL) +#define CMSG_ALIGN(len) (((len) + sizeof (size_t) - 1) \ + & (size_t) ~(sizeof (size_t) - 1)) +#define CMSG_SPACE(len) (CMSG_ALIGN (len) \ + + CMSG_ALIGN (sizeof (struct cmsghdr))) +#define CMSG_LEN(len) (CMSG_ALIGN (sizeof (struct cmsghdr)) + (len)) + +extern struct cmsghdr *__cmsg_nxthdr (struct msghdr *__mhdr, + struct cmsghdr *__cmsg) __THROW; +libc_hidden_proto(__cmsg_nxthdr) +#ifdef __USE_EXTERN_INLINES +# ifndef _EXTERN_INLINE +# define _EXTERN_INLINE extern __inline +# endif +_EXTERN_INLINE struct cmsghdr * +__NTH (__cmsg_nxthdr (struct msghdr *__mhdr, struct cmsghdr *__cmsg)) +{ + if ((size_t) __cmsg->cmsg_len < sizeof (struct cmsghdr)) + /* The kernel header does this so there may be a reason. */ + return 0; + + __cmsg = (struct cmsghdr *) ((unsigned char *) __cmsg + + CMSG_ALIGN (__cmsg->cmsg_len)); + if ((unsigned char *) (__cmsg + 1) > ((unsigned char *) __mhdr->msg_control + + __mhdr->msg_controllen) + || ((unsigned char *) __cmsg + CMSG_ALIGN (__cmsg->cmsg_len) + > ((unsigned char *) __mhdr->msg_control + __mhdr->msg_controllen))) + /* No more entries. */ + return 0; + return __cmsg; +} +#endif /* Use `extern inline'. */ + +/* Socket level message types. This must match the definitions in + . */ +enum + { + SCM_RIGHTS = 0x01 /* Transfer file descriptors. */ +#define SCM_RIGHTS SCM_RIGHTS +#ifdef __USE_BSD + , SCM_CREDENTIALS = 0x02 /* Credentials passing. */ +# define SCM_CREDENTIALS SCM_CREDENTIALS +#endif + }; + +/* User visible structure for SCM_CREDENTIALS message */ + +struct ucred +{ + pid_t pid; /* PID of sending process. */ + uid_t uid; /* UID of sending process. */ + gid_t gid; /* GID of sending process. */ +}; + +/* Get socket manipulation related informations from kernel headers. */ +#ifndef __GLIBC__ +#define __GLIBC__ 2 +#include +#undef __GLIBC__ +#else +#include +#endif + + +/* Structure used to manipulate the SO_LINGER option. */ +struct linger + { + int l_onoff; /* Nonzero to linger on close. */ + int l_linger; /* Time to linger. */ + }; + +#endif /* bits/socket.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/stackinfo.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/stackinfo.h new file mode 100644 index 00000000..86e3d621 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/stackinfo.h @@ -0,0 +1,28 @@ +/* Copyright (C) 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This file contains a bit of information about the stack allocation + of the processor. */ + +#ifndef _STACKINFO_H +#define _STACKINFO_H 1 + +/* On MIPS the stack grows down. */ +#define _STACK_GROWS_DOWN 1 + +#endif /* stackinfo.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/stat.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/stat.h new file mode 100644 index 00000000..b9e6bf4a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/stat.h @@ -0,0 +1,254 @@ +/* Copyright (C) 1992, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, + 2007, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_STAT_H +# error "Never include directly; use instead." +#endif + +#include + +/* Versions of the `struct stat' data structure. */ +#define _STAT_VER_LINUX_OLD 1 +#define _STAT_VER_KERNEL 1 +#define _STAT_VER_SVR4 2 +#define _STAT_VER_LINUX 3 +#define _STAT_VER _STAT_VER_LINUX /* The one defined below. */ + +/* Versions of the `xmknod' interface. */ +#define _MKNOD_VER_LINUX 1 +#define _MKNOD_VER_SVR4 2 +#define _MKNOD_VER _MKNOD_VER_LINUX /* The bits defined below. */ + + +#if _MIPS_SIM == _ABIO32 +/* Structure describing file characteristics. */ +struct stat + { + __dev_t st_dev; + long int st_pad1[2]; +#ifndef __USE_FILE_OFFSET64 + __ino_t st_ino; /* File serial number. */ +#else + __ino64_t st_ino; /* File serial number. */ +#endif + __mode_t st_mode; /* File mode. */ + __nlink_t st_nlink; /* Link count. */ + __uid_t st_uid; /* User ID of the file's owner. */ + __gid_t st_gid; /* Group ID of the file's group.*/ + __dev_t st_rdev; /* Device number, if device. */ +#ifndef __USE_FILE_OFFSET64 + long int st_pad2[1]; + __off_t st_size; /* Size of file, in bytes. */ + /* SVR4 added this extra long to allow for expansion of off_t. */ + long int st_pad3; +#else + long int st_pad2[2]; + __off64_t st_size; /* Size of file, in bytes. */ +#endif +#ifdef __USE_MISC + /* Nanosecond resolution timestamps are stored in a format + equivalent to 'struct timespec'. This is the type used + whenever possible but the Unix namespace rules do not allow the + identifier 'timespec' to appear in the header. + Therefore we have to handle the use of this header in strictly + standard-compliant sources special. */ + struct timespec st_atim; /* Time of last access. */ + struct timespec st_mtim; /* Time of last modification. */ + struct timespec st_ctim; /* Time of last status change. */ +# define st_atime st_atim.tv_sec /* Backward compatibility. */ +# define st_mtime st_mtim.tv_sec +# define st_ctime st_ctim.tv_sec +#else + __time_t st_atime; /* Time of last access. */ + unsigned long int st_atimensec; /* Nscecs of last access. */ + __time_t st_mtime; /* Time of last modification. */ + unsigned long int st_mtimensec; /* Nsecs of last modification. */ + __time_t st_ctime; /* Time of last status change. */ + unsigned long int st_ctimensec; /* Nsecs of last status change. */ +#endif + __blksize_t st_blksize; /* Optimal block size for I/O. */ +#ifndef __USE_FILE_OFFSET64 + __blkcnt_t st_blocks; /* Number of 512-byte blocks allocated. */ +#else + long int st_pad4; + __blkcnt64_t st_blocks; /* Number of 512-byte blocks allocated. */ +#endif + long int st_pad5[14]; + }; +#else /* N32 || N64 */ +/* The memory layout is the same as of struct stat64 of the 32-bit kernel. */ +struct stat { + unsigned int st_dev; + int st_pad1[3]; + __ino_t st_ino; /* File serial number. */ + __mode_t st_mode; /* File mode. */ + __nlink_t st_nlink; /* Link count. */ + __uid_t st_uid; /* User ID of the file's owner. */ + __gid_t st_gid; /* Group ID of the file's group.*/ + unsigned int st_rdev; /* Device number, if device. */ + int st_pad2[3]; + __off_t st_size; /* Size of file, in bytes. */ +#ifdef __USE_MISC + /* Nanosecond resolution timestamps are stored in a format + equivalent to 'struct timespec'. This is the type used + whenever possible but the Unix namespace rules do not allow the + identifier 'timespec' to appear in the header. + Therefore we have to handle the use of this header in strictly + standard-compliant sources special. */ + struct timespec st_atim; /* Time of last access. */ + struct timespec st_mtim; /* Time of last modification. */ + struct timespec st_ctim; /* Time of last status change. */ +# define st_atime st_atim.tv_sec /* Backward compatibility. */ +# define st_mtime st_mtim.tv_sec +# define st_ctime st_ctim.tv_sec +#else + int st_atime; + int st_atimensec; + int st_mtime; + int st_mtimensec; + int st_ctime; + int st_ctimensec; +#endif + int st_blksize; /* Optimal block size for I/O. */ + int st_pad3; + __blkcnt_t st_blocks; /* Number of 512-byte blocks allocated. */ + int st_pad4[14]; +}; +#endif /* N32 || N64 */ + +#ifdef __USE_LARGEFILE64 +#if _MIPS_SIM == _ABIO32 +struct stat64 + { + __dev_t st_dev; + long int st_pad1[2]; + __ino64_t st_ino; /* File serial number. */ + __mode_t st_mode; /* File mode. */ + __nlink_t st_nlink; /* Link count. */ + __uid_t st_uid; /* User ID of the file's owner. */ + __gid_t st_gid; /* Group ID of the file's group.*/ + __dev_t st_rdev; /* Device number, if device. */ + long int st_pad2[2]; + __off64_t st_size; /* Size of file, in bytes. */ +#ifdef __USE_MISC + /* Nanosecond resolution timestamps are stored in a format + equivalent to 'struct timespec'. This is the type used + whenever possible but the Unix namespace rules do not allow the + identifier 'timespec' to appear in the header. + Therefore we have to handle the use of this header in strictly + standard-compliant sources special. */ + struct timespec st_atim; /* Time of last access. */ + struct timespec st_mtim; /* Time of last modification. */ + struct timespec st_ctim; /* Time of last status change. */ +# define st_atime st_atim.tv_sec /* Backward compatibility. */ +# define st_mtime st_mtim.tv_sec +# define st_ctime st_ctim.tv_sec +#else + __time_t st_atime; /* Time of last access. */ + unsigned long int st_atimensec; /* Nscecs of last access. */ + __time_t st_mtime; /* Time of last modification. */ + unsigned long int st_mtimensec; /* Nsecs of last modification. */ + __time_t st_ctime; /* Time of last status change. */ + unsigned long int st_ctimensec; /* Nsecs of last status change. */ +#endif + __blksize_t st_blksize; /* Optimal block size for I/O. */ + long int st_pad3; + __blkcnt64_t st_blocks; /* Number of 512-byte blocks allocated. */ + long int st_pad4[14]; + }; +#else /* N32 || N64 */ +/* stat64 of N32/N64 is just an alias of stat syscall. */ +struct stat64 { + unsigned int st_dev; + int st_pad1[3]; + __ino_t st_ino; /* File serial number. */ + __mode_t st_mode; /* File mode. */ + __nlink_t st_nlink; /* Link count. */ + __uid_t st_uid; /* User ID of the file's owner. */ + __gid_t st_gid; /* Group ID of the file's group.*/ + unsigned int st_rdev; /* Device number, if device. */ + int st_pad2[3]; + __off_t st_size; /* Size of file, in bytes. */ +#ifdef __USE_MISC + /* Nanosecond resolution timestamps are stored in a format + equivalent to 'struct timespec'. This is the type used + whenever possible but the Unix namespace rules do not allow the + identifier 'timespec' to appear in the header. + Therefore we have to handle the use of this header in strictly + standard-compliant sources special. */ + struct timespec st_atim; /* Time of last access. */ + struct timespec st_mtim; /* Time of last modification. */ + struct timespec st_ctim; /* Time of last status change. */ +# define st_atime st_atim.tv_sec /* Backward compatibility. */ +# define st_mtime st_mtim.tv_sec +# define st_ctime st_ctim.tv_sec +#else + int st_atime; + int st_atimensec; + int st_mtime; + int st_mtimensec; + int st_ctime; + int st_ctimensec; +#endif + int st_blksize; /* Optimal block size for I/O. */ + int st_pad3; + __blkcnt_t st_blocks; /* Number of 512-byte blocks allocated. */ + int st_pad4[14]; +}; +#endif /* N32 || N64 */ +#endif + +/* Tell code we have these members. */ +#define _STATBUF_ST_BLKSIZE +#define _STATBUF_ST_RDEV +/* Nanosecond resolution time values are supported. */ +#define _STATBUF_ST_NSEC + +/* Encoding of the file mode. */ + +#define __S_IFMT 0170000 /* These bits determine file type. */ + +/* File types. */ +#define __S_IFDIR 0040000 /* Directory. */ +#define __S_IFCHR 0020000 /* Character device. */ +#define __S_IFBLK 0060000 /* Block device. */ +#define __S_IFREG 0100000 /* Regular file. */ +#define __S_IFIFO 0010000 /* FIFO. */ +#define __S_IFLNK 0120000 /* Symbolic link. */ +#define __S_IFSOCK 0140000 /* Socket. */ + +/* POSIX.1b objects. Note that these macros always evaluate to zero. But + they do it by enforcing the correct use of the macros. */ +#define __S_TYPEISMQ(buf) ((buf)->st_mode - (buf)->st_mode) +#define __S_TYPEISSEM(buf) ((buf)->st_mode - (buf)->st_mode) +#define __S_TYPEISSHM(buf) ((buf)->st_mode - (buf)->st_mode) + +/* Protection bits. */ + +#define __S_ISUID 04000 /* Set user ID on execution. */ +#define __S_ISGID 02000 /* Set group ID on execution. */ +#define __S_ISVTX 01000 /* Save swapped text after use (sticky). */ +#define __S_IREAD 0400 /* Read by owner. */ +#define __S_IWRITE 0200 /* Write by owner. */ +#define __S_IEXEC 0100 /* Execute by owner. */ + +#ifdef __USE_ATFILE +# define UTIME_NOW ((1l << 30) - 1l) +# define UTIME_OMIT ((1l << 30) - 2l) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/statfs.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/statfs.h new file mode 100644 index 00000000..2f9bd54e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/statfs.h @@ -0,0 +1,72 @@ +/* Copyright (C) 1997, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_STATFS_H +# error "Never include directly; use instead." +#endif + +#include /* for __fsid_t and __fsblkcnt_t*/ + +struct statfs + { + long int f_type; +#define f_fstyp f_type + long int f_bsize; + long int f_frsize; /* Fragment size - unsupported */ +#ifndef __USE_FILE_OFFSET64 + __fsblkcnt_t f_blocks; + __fsblkcnt_t f_bfree; + __fsblkcnt_t f_files; + __fsblkcnt_t f_ffree; + __fsblkcnt_t f_bavail; +#else + __fsblkcnt64_t f_blocks; + __fsblkcnt64_t f_bfree; + __fsblkcnt64_t f_files; + __fsblkcnt64_t f_ffree; + __fsblkcnt64_t f_bavail; +#endif + + /* Linux specials */ + __fsid_t f_fsid; + long int f_namelen; + long int f_spare[6]; + }; + +#ifdef __USE_LARGEFILE64 +struct statfs64 + { + long int f_type; +#define f_fstyp f_type + long int f_bsize; + long int f_frsize; /* Fragment size - unsupported */ + __fsblkcnt64_t f_blocks; + __fsblkcnt64_t f_bfree; + __fsblkcnt64_t f_files; + __fsblkcnt64_t f_ffree; + __fsblkcnt64_t f_bavail; + + /* Linux specials */ + __fsid_t f_fsid; + long int f_namelen; + long int f_spare[6]; + }; +#endif + +/* Tell code we have these members. */ +#define _STATFS_F_NAMELEN diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/syscalls.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/syscalls.h new file mode 100644 index 00000000..944d0382 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/syscalls.h @@ -0,0 +1,326 @@ +#ifndef _BITS_SYSCALLS_H +#define _BITS_SYSCALLS_H +#ifndef _SYSCALL_H +# error "Never use directly; include instead." +#endif + +#include + +#ifndef __ASSEMBLER__ + +#include + +/* + * Import from: + * glibc-ports/sysdeps/unix/sysv/linux/mips/mips32/sysdep.h + * glibc-ports/sysdeps/unix/sysv/linux/mips/mips64/n32/sysdep.h + * glibc-ports/sysdeps/unix/sysv/linux/mips/mips64/n64/sysdep.h + */ + +/* Define a macro which expands into the inline wrapper code for a system + call. */ +#define INLINE_SYSCALL(name, nr, args...) \ + ({ INTERNAL_SYSCALL_DECL(err); \ + long result_var = INTERNAL_SYSCALL(name, err, nr, args); \ + if ( INTERNAL_SYSCALL_ERROR_P (result_var, err) ) \ + { \ + __set_errno (INTERNAL_SYSCALL_ERRNO (result_var, err)); \ + result_var = -1L; \ + } \ + result_var; }) + +#define INTERNAL_SYSCALL_DECL(err) long err + +#define INTERNAL_SYSCALL_ERROR_P(val, err) ((long) (err)) + +#define INTERNAL_SYSCALL_ERRNO(val, err) (val) + +#define INTERNAL_SYSCALL(name, err, nr, args...) \ + internal_syscall##nr (, "li\t$2, %2\t\t\t# " #name "\n\t", \ + "i" (SYS_ify (name)), err, args) + +#define INTERNAL_SYSCALL_NCS(number, err, nr, args...) \ + internal_syscall##nr (= number, , "r" (__v0), err, args) + +#if _MIPS_SIM == _ABIO32 || _MIPS_SIM == _ABI64 +# define ARG_TYPE long +#else +# define ARG_TYPE long long +#endif + +#define internal_syscall0(ncs_init, cs_init, input, err, dummy...) \ +({ \ + long _sys_result; \ + \ + { \ + register ARG_TYPE __v0 __asm__("$2") ncs_init; \ + register ARG_TYPE __a3 __asm__("$7"); \ + __asm__ __volatile__ ( \ + ".set\tnoreorder\n\t" \ + cs_init \ + "syscall\n\t" \ + ".set reorder" \ + : "=r" (__v0), "=r" (__a3) \ + : input \ + : __SYSCALL_CLOBBERS); \ + err = __a3; \ + _sys_result = __v0; \ + } \ + _sys_result; \ +}) + +#define internal_syscall1(ncs_init, cs_init, input, err, arg1) \ +({ \ + long _sys_result; \ + \ + { \ + register ARG_TYPE __v0 __asm__("$2") ncs_init; \ + register ARG_TYPE __a0 __asm__("$4") = (ARG_TYPE) arg1; \ + register ARG_TYPE __a3 __asm__("$7"); \ + __asm__ __volatile__ ( \ + ".set\tnoreorder\n\t" \ + cs_init \ + "syscall\n\t" \ + ".set reorder" \ + : "=r" (__v0), "=r" (__a3) \ + : input, "r" (__a0) \ + : __SYSCALL_CLOBBERS); \ + err = __a3; \ + _sys_result = __v0; \ + } \ + _sys_result; \ +}) + +#define internal_syscall2(ncs_init, cs_init, input, err, arg1, arg2) \ +({ \ + long _sys_result; \ + \ + { \ + register ARG_TYPE __v0 __asm__("$2") ncs_init; \ + register ARG_TYPE __a0 __asm__("$4") = (ARG_TYPE) arg1; \ + register ARG_TYPE __a1 __asm__("$5") = (ARG_TYPE) arg2; \ + register ARG_TYPE __a3 __asm__("$7"); \ + __asm__ __volatile__ ( \ + ".set\tnoreorder\n\t" \ + cs_init \ + "syscall\n\t" \ + ".set\treorder" \ + : "=r" (__v0), "=r" (__a3) \ + : input, "r" (__a0), "r" (__a1) \ + : __SYSCALL_CLOBBERS); \ + err = __a3; \ + _sys_result = __v0; \ + } \ + _sys_result; \ +}) + +#define internal_syscall3(ncs_init, cs_init, input, err, arg1, arg2, arg3)\ +({ \ + long _sys_result; \ + \ + { \ + register ARG_TYPE __v0 __asm__("$2") ncs_init; \ + register ARG_TYPE __a0 __asm__("$4") = (ARG_TYPE) arg1; \ + register ARG_TYPE __a1 __asm__("$5") = (ARG_TYPE) arg2; \ + register ARG_TYPE __a2 __asm__("$6") = (ARG_TYPE) arg3; \ + register ARG_TYPE __a3 __asm__("$7"); \ + __asm__ __volatile__ ( \ + ".set\tnoreorder\n\t" \ + cs_init \ + "syscall\n\t" \ + ".set\treorder" \ + : "=r" (__v0), "=r" (__a3) \ + : input, "r" (__a0), "r" (__a1), "r" (__a2) \ + : __SYSCALL_CLOBBERS); \ + err = __a3; \ + _sys_result = __v0; \ + } \ + _sys_result; \ +}) + +#define internal_syscall4(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4)\ +({ \ + long _sys_result; \ + \ + { \ + register ARG_TYPE __v0 __asm__("$2") ncs_init; \ + register ARG_TYPE __a0 __asm__("$4") = (ARG_TYPE) arg1; \ + register ARG_TYPE __a1 __asm__("$5") = (ARG_TYPE) arg2; \ + register ARG_TYPE __a2 __asm__("$6") = (ARG_TYPE) arg3; \ + register ARG_TYPE __a3 __asm__("$7") = (ARG_TYPE) arg4; \ + __asm__ __volatile__ ( \ + ".set\tnoreorder\n\t" \ + cs_init \ + "syscall\n\t" \ + ".set\treorder" \ + : "=r" (__v0), "+r" (__a3) \ + : input, "r" (__a0), "r" (__a1), "r" (__a2) \ + : __SYSCALL_CLOBBERS); \ + err = __a3; \ + _sys_result = __v0; \ + } \ + _sys_result; \ +}) + +#if _MIPS_SIM == _ABIO32 +#include +/* We need to use a frame pointer for the functions in which we + adjust $sp around the syscall, or debug information and unwind + information will be $sp relative and thus wrong during the syscall. As + of GCC 3.4.3, this is sufficient. */ +#define FORCE_FRAME_POINTER alloca (4) + +#define internal_syscall5(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4, arg5)\ +({ \ + long _sys_result; \ + \ + FORCE_FRAME_POINTER; \ + { \ + register long __v0 __asm__("$2") ncs_init; \ + register long __a0 __asm__("$4") = (long) arg1; \ + register long __a1 __asm__("$5") = (long) arg2; \ + register long __a2 __asm__("$6") = (long) arg3; \ + register long __a3 __asm__("$7") = (long) arg4; \ + __asm__ __volatile__ ( \ + ".set\tnoreorder\n\t" \ + "subu\t$29, 32\n\t" \ + "sw\t%6, 16($29)\n\t" \ + cs_init \ + "syscall\n\t" \ + "addiu\t$29, 32\n\t" \ + ".set\treorder" \ + : "=r" (__v0), "+r" (__a3) \ + : input, "r" (__a0), "r" (__a1), "r" (__a2), \ + "r" ((long)arg5) \ + : __SYSCALL_CLOBBERS); \ + err = __a3; \ + _sys_result = __v0; \ + } \ + _sys_result; \ +}) + +#define internal_syscall6(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4, arg5, arg6)\ +({ \ + long _sys_result; \ + \ + FORCE_FRAME_POINTER; \ + { \ + register long __v0 __asm__("$2") ncs_init; \ + register long __a0 __asm__("$4") = (long) arg1; \ + register long __a1 __asm__("$5") = (long) arg2; \ + register long __a2 __asm__("$6") = (long) arg3; \ + register long __a3 __asm__("$7") = (long) arg4; \ + __asm__ __volatile__ ( \ + ".set\tnoreorder\n\t" \ + "subu\t$29, 32\n\t" \ + "sw\t%6, 16($29)\n\t" \ + "sw\t%7, 20($29)\n\t" \ + cs_init \ + "syscall\n\t" \ + "addiu\t$29, 32\n\t" \ + ".set\treorder" \ + : "=r" (__v0), "+r" (__a3) \ + : input, "r" (__a0), "r" (__a1), "r" (__a2), \ + "r" ((long)arg5), "r" ((long)arg6) \ + : __SYSCALL_CLOBBERS); \ + err = __a3; \ + _sys_result = __v0; \ + } \ + _sys_result; \ +}) + +#define internal_syscall7(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4, arg5, arg6, arg7)\ +({ \ + long _sys_result; \ + \ + FORCE_FRAME_POINTER; \ + { \ + register long __v0 __asm__("$2") ncs_init; \ + register long __a0 __asm__("$4") = (long) arg1; \ + register long __a1 __asm__("$5") = (long) arg2; \ + register long __a2 __asm__("$6") = (long) arg3; \ + register long __a3 __asm__("$7") = (long) arg4; \ + __asm__ __volatile__ ( \ + ".set\tnoreorder\n\t" \ + "subu\t$29, 32\n\t" \ + "sw\t%6, 16($29)\n\t" \ + "sw\t%7, 20($29)\n\t" \ + "sw\t%8, 24($29)\n\t" \ + cs_init \ + "syscall\n\t" \ + "addiu\t$29, 32\n\t" \ + ".set\treorder" \ + : "=r" (__v0), "+r" (__a3) \ + : input, "r" (__a0), "r" (__a1), "r" (__a2), \ + "r" ((long)arg5), "r" ((long)arg6), "r" ((long)arg7) \ + : __SYSCALL_CLOBBERS); \ + err = __a3; \ + _sys_result = __v0; \ + } \ + _sys_result; \ +}) + +#define __SYSCALL_CLOBBERS "$1", "$3", "$8", "$9", "$10", "$11", "$12", "$13", \ + "$14", "$15", "$24", "$25", "hi", "lo", "memory" + +#else /* N32 || N64 */ + +#define internal_syscall5(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4, arg5) \ +({ \ + long _sys_result; \ + \ + { \ + register ARG_TYPE __v0 __asm__("$2") ncs_init; \ + register ARG_TYPE __a0 __asm__("$4") = (ARG_TYPE) arg1; \ + register ARG_TYPE __a1 __asm__("$5") = (ARG_TYPE) arg2; \ + register ARG_TYPE __a2 __asm__("$6") = (ARG_TYPE) arg3; \ + register ARG_TYPE __a3 __asm__("$7") = (ARG_TYPE) arg4; \ + register ARG_TYPE __a4 __asm__("$8") = (ARG_TYPE) arg5; \ + __asm__ __volatile__ ( \ + ".set\tnoreorder\n\t" \ + cs_init \ + "syscall\n\t" \ + ".set\treorder" \ + : "=r" (__v0), "+r" (__a3) \ + : input, "r" (__a0), "r" (__a1), "r" (__a2), "r" (__a4) \ + : __SYSCALL_CLOBBERS); \ + err = __a3; \ + _sys_result = __v0; \ + } \ + _sys_result; \ +}) + +#define internal_syscall6(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4, arg5, arg6) \ +({ \ + long _sys_result; \ + \ + { \ + register ARG_TYPE __v0 __asm__("$2") ncs_init; \ + register ARG_TYPE __a0 __asm__("$4") = (ARG_TYPE) arg1; \ + register ARG_TYPE __a1 __asm__("$5") = (ARG_TYPE) arg2; \ + register ARG_TYPE __a2 __asm__("$6") = (ARG_TYPE) arg3; \ + register ARG_TYPE __a3 __asm__("$7") = (ARG_TYPE) arg4; \ + register ARG_TYPE __a4 __asm__("$8") = (ARG_TYPE) arg5; \ + register ARG_TYPE __a5 __asm__("$9") = (ARG_TYPE) arg6; \ + __asm__ __volatile__ ( \ + ".set\tnoreorder\n\t" \ + cs_init \ + "syscall\n\t" \ + ".set\treorder" \ + : "=r" (__v0), "+r" (__a3) \ + : input, "r" (__a0), "r" (__a1), "r" (__a2), "r" (__a4), \ + "r" (__a5) \ + : __SYSCALL_CLOBBERS); \ + err = __a3; \ + _sys_result = __v0; \ + } \ + _sys_result; \ +}) + +#define __SYSCALL_CLOBBERS "$1", "$3", "$10", "$11", "$12", "$13", \ + "$14", "$15", "$24", "$25", "hi", "lo", "memory" + +#endif + +#endif /* __ASSEMBLER__ */ +#endif /* _BITS_SYSCALLS_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/termios.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/termios.h new file mode 100644 index 00000000..fb351995 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/termios.h @@ -0,0 +1,218 @@ +/* termios type and macro definitions. Linux/MIPS version. + Copyright (C) 1993, 94, 95, 96, 97, 99 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _TERMIOS_H +# error "Never include directly; use instead." +#endif + +typedef unsigned char cc_t; +typedef unsigned int speed_t; +typedef unsigned int tcflag_t; + +#define NCCS 32 +struct termios + { + tcflag_t c_iflag; /* input mode flags */ + tcflag_t c_oflag; /* output mode flags */ + tcflag_t c_cflag; /* control mode flags */ + tcflag_t c_lflag; /* local mode flags */ + cc_t c_line; /* line discipline */ + cc_t c_cc[NCCS]; /* control characters */ + }; + +/* c_cc characters */ +#define VINTR 0 /* Interrupt character [ISIG]. */ +#define VQUIT 1 /* Quit character [ISIG]. */ +#define VERASE 2 /* Erase character [ICANON]. */ +#define VKILL 3 /* Kill-line character [ICANON]. */ +#define VMIN 4 /* Minimum number of bytes read at once [!ICANON]. */ +#define VTIME 5 /* Time-out value (tenths of a second) [!ICANON]. */ +#define VEOL2 6 /* Second EOL character [ICANON]. */ +#define VSWTC 7 +#define VSWTCH VSWTC +#define VSTART 8 /* Start (X-ON) character [IXON, IXOFF]. */ +#define VSTOP 9 /* Stop (X-OFF) character [IXON, IXOFF]. */ +#define VSUSP 10 /* Suspend character [ISIG]. */ + /* VDSUSP is not supported on Linux. */ +/* #define VDSUSP 11 / * Delayed suspend character [ISIG]. */ +#define VREPRINT 12 /* Reprint-line character [ICANON]. */ +#define VDISCARD 13 /* Discard character [IEXTEN]. */ +#define VWERASE 14 /* Word-erase character [ICANON]. */ +#define VLNEXT 15 /* Literal-next character [IEXTEN]. */ +#define VEOF 16 /* End-of-file character [ICANON]. */ +#define VEOL 17 /* End-of-line character [ICANON]. */ + +/* c_iflag bits */ +#define IGNBRK 0000001 /* Ignore break condition. */ +#define BRKINT 0000002 /* Signal interrupt on break. */ +#define IGNPAR 0000004 /* Ignore characters with parity errors. */ +#define PARMRK 0000010 /* Mark parity and framing errors. */ +#define INPCK 0000020 /* Enable input parity check. */ +#define ISTRIP 0000040 /* Strip 8th bit off characters. */ +#define INLCR 0000100 /* Map NL to CR on input. */ +#define IGNCR 0000200 /* Ignore CR. */ +#define ICRNL 0000400 /* Map CR to NL on input. */ +#define IUCLC 0001000 /* Map upper case to lower case on input. */ +#define IXON 0002000 /* Enable start/stop output control. */ +#define IXANY 0004000 /* Any character will restart after stop. */ +#define IXOFF 0010000 /* Enable start/stop input control. */ +#define IMAXBEL 0020000 /* Ring bell when input queue is full. */ +#define IUTF8 0040000 /* Input is UTF8. */ + +/* c_oflag bits */ +#define OPOST 0000001 /* Perform output processing. */ +#define OLCUC 0000002 /* Map lower case to upper case on output. */ +#define ONLCR 0000004 /* Map NL to CR-NL on output. */ +#define OCRNL 0000010 +#define ONOCR 0000020 +#define ONLRET 0000040 +#define OFILL 0000100 +#define OFDEL 0000200 +#if defined __USE_MISC || defined __USE_XOPEN +# define NLDLY 0000400 +# define NL0 0000000 +# define NL1 0000400 +# define CRDLY 0003000 +# define CR0 0000000 +# define CR1 0001000 +# define CR2 0002000 +# define CR3 0003000 +# define TABDLY 0014000 +# define TAB0 0000000 +# define TAB1 0004000 +# define TAB2 0010000 +# define TAB3 0014000 +# define BSDLY 0020000 +# define BS0 0000000 +# define BS1 0020000 +# define FFDLY 0100000 +# define FF0 0000000 +# define FF1 0100000 +#endif + +#define VTDLY 0040000 +#define VT0 0000000 +#define VT1 0040000 + +#ifdef __USE_MISC +# define XTABS 0014000 +#endif + +/* c_cflag bit meaning */ +#ifdef __USE_MISC +# define CBAUD 0010017 +#endif +#define B0 0000000 /* hang up */ +#define B50 0000001 +#define B75 0000002 +#define B110 0000003 +#define B134 0000004 +#define B150 0000005 +#define B200 0000006 +#define B300 0000007 +#define B600 0000010 +#define B1200 0000011 +#define B1800 0000012 +#define B2400 0000013 +#define B4800 0000014 +#define B9600 0000015 +#define B19200 0000016 +#define B38400 0000017 +#ifdef __USE_MISC +# define EXTA B19200 +# define EXTB B38400 +#endif +#define CSIZE 0000060 /* Number of bits per byte (mask). */ +#define CS5 0000000 /* 5 bits per byte. */ +#define CS6 0000020 /* 6 bits per byte. */ +#define CS7 0000040 /* 7 bits per byte. */ +#define CS8 0000060 /* 8 bits per byte. */ +#define CSTOPB 0000100 /* Two stop bits instead of one. */ +#define CREAD 0000200 /* Enable receiver. */ +#define PARENB 0000400 /* Parity enable. */ +#define PARODD 0001000 /* Odd parity instead of even. */ +#define HUPCL 0002000 /* Hang up on last close. */ +#define CLOCAL 0004000 /* Ignore modem status lines. */ +#ifdef __USE_MISC +# define CBAUDEX 0010000 +#endif +#define B57600 0010001 +#define B115200 0010002 +#define B230400 0010003 +#define B460800 0010004 +#define B500000 0010005 +#define B576000 0010006 +#define B921600 0010007 +#define B1000000 0010010 +#define B1152000 0010011 +#define B1500000 0010012 +#define B2000000 0010013 +#define B2500000 0010014 +#define B3000000 0010015 +#define B3500000 0010016 +#define B4000000 0010017 +#define __MAX_BAUD B4000000 +#ifdef __USE_MISC +# define CIBAUD 002003600000 /* input baud rate (not used) */ +# define CRTSCTS 020000000000 /* flow control */ +#endif + +/* c_lflag bits */ +#define ISIG 0000001 /* Enable signals. */ +#define ICANON 0000002 /* Do erase and kill processing. */ +#if defined __USE_MISC || defined __USE_XOPEN +# define XCASE 0000004 +#endif +#define ECHO 0000010 /* Enable echo. */ +#define ECHOE 0000020 /* Visual erase for ERASE. */ +#define ECHOK 0000040 /* Echo NL after KILL. */ +#define ECHONL 0000100 /* Echo NL even if ECHO is off. */ +#define NOFLSH 0000200 /* Disable flush after interrupt. */ +#define IEXTEN 0000400 /* Enable DISCARD and LNEXT. */ +#ifdef __USE_MISC +# define ECHOCTL 0001000 /* Echo control characters as ^X. */ +# define ECHOPRT 0002000 /* Hardcopy visual erase. */ +# define ECHOKE 0004000 /* Visual erase for KILL. */ +# define FLUSHO 0020000 +# define PENDIN 0040000 /* Retype pending input (state). */ +#endif +#define TOSTOP 0100000 /* Send SIGTTOU for background output. */ +#define ITOSTOP TOSTOP + +/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */ +#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */ + +/* tcflow() and TCXONC use these */ +#define TCOOFF 0 /* Suspend output. */ +#define TCOON 1 /* Restart suspended output. */ +#define TCIOFF 2 /* Send a STOP character. */ +#define TCION 3 /* Send a START character. */ + +/* tcflush() and TCFLSH use these */ +#define TCIFLUSH 0 /* Discard data received but not yet read. */ +#define TCOFLUSH 1 /* Discard data written but not yet sent. */ +#define TCIOFLUSH 2 /* Discard all pending data. */ + +/* tcsetattr uses these */ +#define TCSANOW 0x540e /* Same as TCSETS; change immediately. */ +#define TCSADRAIN 0x540f /* Same as TCSETSW; change when pending output is written. */ +#define TCSAFLUSH 0x5410 /* Same as TCSETSF; flush pending input before changing. */ + +#define _IOT_termios /* Hurd ioctl type field. */ \ + _IOT (_IOTS (cflag_t), 4, _IOTS (cc_t), NCCS, _IOTS (speed_t), 2) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/uClibc_arch_features.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/uClibc_arch_features.h new file mode 100644 index 00000000..82f67bf8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/uClibc_arch_features.h @@ -0,0 +1,47 @@ +/* + * Track misc arch-specific features that aren't config options + */ + +#ifndef _BITS_UCLIBC_ARCH_FEATURES_H +#define _BITS_UCLIBC_ARCH_FEATURES_H + +/* instruction used when calling abort() to kill yourself */ +#define __UCLIBC_ABORT_INSTRUCTION__ "break 255" + +/* can your target use syscall6() for mmap ? */ +#define __UCLIBC_MMAP_HAS_6_ARGS__ + +/* does your target use syscall4() for truncate64 ? (32bit arches only) */ +#define __UCLIBC_TRUNCATE64_HAS_4_ARGS__ + +/* does your target have a broken create_module() ? */ +#undef __UCLIBC_BROKEN_CREATE_MODULE__ + +/* does your target have to worry about older [gs]etrlimit() ? */ +#undef __UCLIBC_HANDLE_OLDER_RLIMIT__ + +/* does your target have an asm .set ? */ +#undef __UCLIBC_HAVE_ASM_SET_DIRECTIVE__ + +/* define if target doesn't like .global */ +#undef __UCLIBC_ASM_GLOBAL_DIRECTIVE__ + +/* define if target supports .weak */ +#define __UCLIBC_HAVE_ASM_WEAK_DIRECTIVE__ + +/* define if target supports .weakext */ +#undef __UCLIBC_HAVE_ASM_WEAKEXT_DIRECTIVE__ + +/* needed probably only for ppc64 */ +#undef __UCLIBC_HAVE_ASM_GLOBAL_DOT_NAME__ + +/* define if target supports CFI pseudo ops */ +#undef __UCLIBC_HAVE_ASM_CFI_DIRECTIVES__ + +/* define if target supports IEEE signed zero floats */ +#define __UCLIBC_HAVE_SIGNED_ZERO__ + +/* only weird assemblers generally need this */ +#undef __UCLIBC_ASM_LINE_SEP__ + +#endif /* _BITS_UCLIBC_ARCH_FEATURES_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/uClibc_page.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/uClibc_page.h new file mode 100644 index 00000000..915918c3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/uClibc_page.h @@ -0,0 +1,35 @@ +/* Copyright (C) 2004 Erik Andersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* Supply an architecture specific value for PAGE_SIZE and friends. */ + +#ifndef _UCLIBC_PAGE_H +#define _UCLIBC_PAGE_H + +/* PAGE_SIZE of mips is sortof wierd, and depends on how the kernel + * happens to have been configured. It might use 4KB, 16K or 64K + * pages. To avoid using the current kernel configuration settings, + * uClibc will simply use 4KB on mips and call it good. */ +#if 0 +#define PAGE_SHIFT 16 +#define PAGE_SHIFT 14 +#endif +#define PAGE_SHIFT 12 +#define PAGE_SIZE (1UL << PAGE_SHIFT) +#define PAGE_MASK (~(PAGE_SIZE-1)) + +#endif /* _UCLIBC_PAGE_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/wordsize.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/wordsize.h new file mode 100644 index 00000000..666c7ad0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bits/wordsize.h @@ -0,0 +1,19 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define __WORDSIZE _MIPS_SZPTR diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/brk.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/brk.c new file mode 100644 index 00000000..f0462d66 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/brk.c @@ -0,0 +1,51 @@ +/* brk system call for Linux/MIPS. + Copyright (C) 2000, 2005, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +void *__curbrk attribute_hidden = 0; + +int brk (void *addr) +{ + void *newbrk; + + { + register long int res __asm__ ("$2"); + + __asm__ ("move\t$4,%2\n\t" + "li\t%0,%1\n\t" + "syscall" /* Perform the system call. */ + : "=r" (res) + : "I" (__NR_brk), "r" (addr) + : "$4", "$7", __SYSCALL_CLOBBERS); + newbrk = (void *) res; + } + __curbrk = newbrk; + + if (newbrk < addr) + { + __set_errno (ENOMEM); + return -1; + } + + return 0; +} +libc_hidden_def(brk) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bsd-_setjmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bsd-_setjmp.S new file mode 100644 index 00000000..6853dea9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bsd-_setjmp.S @@ -0,0 +1,56 @@ +/* BSD `_setjmp' entry point to `sigsetjmp (..., 0)'. MIPS version. + Copyright (C) 1996, 1997, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This just does a tail-call to `__sigsetjmp (ARG, 0)'. + We cannot do it in C because it must be a tail-call, so frame-unwinding + in setjmp doesn't clobber the state restored by longjmp. */ + +#include +#include + +#ifdef __PIC__ + .option pic2 +#endif + +.text +.global _setjmp +.align 2; +.ent _setjmp,0; +.type _setjmp,@function + +_setjmp: +#ifdef __PIC__ +#if (_MIPS_SIM == _MIPS_SIM_ABI32) + .set noreorder + .cpload t9 + .set reorder + la t9, __sigsetjmp +#else + .cpsetup t9, v0, _setjmp + PTR_LA t9, __sigsetjmp + .cpreturn +#endif +#endif + move a1,zero /* Pass a second argument of zero. */ +#ifdef __PIC__ + jr t9 +#else + j __sigsetjmp +#endif + .end _setjmp; diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bsd-setjmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bsd-setjmp.S new file mode 100644 index 00000000..1f57a97e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/bsd-setjmp.S @@ -0,0 +1,56 @@ +/* BSD `setjmp' entry point to `sigsetjmp (..., 1)'. MIPS version. + Copyright (C) 1996, 1997, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This just does a tail-call to `__sigsetjmp (ARG, 1)'. + We cannot do it in C because it must be a tail-call, so frame-unwinding + in setjmp doesn't clobber the state restored by longjmp. */ + +#include +#include + +#ifdef __PIC__ + .option pic2 +#endif + +.text +.global setjmp +.align 2; +.ent setjmp,0; +.type setjmp,@function + +setjmp: + .set noreorder +#ifdef __PIC__ +#if _MIPS_SIM == _MIPS_SIM_ABI32 + .cpload t9 + .set reorder + la t9, __sigsetjmp +#else /* N32 */ + .cpsetup t9, v0, setjmp + PTR_LA t9, __sigsetjmp + .cprestore +#endif /* N32 */ +#endif + li a1, 1 /* Pass a second argument of one. */ +#ifdef __PIC__ + jr t9 +#else + j __sigsetjmp +#endif + .end setjmp diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/cacheflush.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/cacheflush.c new file mode 100644 index 00000000..235414db --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/cacheflush.c @@ -0,0 +1,30 @@ +/* _flush_cache system call for Linux/MIPS. + Copyright (C) 2003 Christophe Massiot + + The uClibc Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The uClibc Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the uClibc Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +#ifdef __NR_cacheflush +_syscall3(int, cacheflush, void *, addr, const int, nbytes, const int, op) +strong_alias(cacheflush, _flush_cache) +#endif + +#ifdef __NR_cachectl +_syscall3(int, cachectl, void *, addr, const int, nbytes, const int, op) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/clone.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/clone.S new file mode 100644 index 00000000..7148e9d2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/clone.S @@ -0,0 +1,173 @@ +/* Copyright (C) 1996, 1997, 2000, 2003, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ralf Baechle , 1996. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* clone() is even more special than fork() as it mucks with stacks + and invokes a function in the right context after its all over. */ + +#include +#include +#include +#define _ERRNO_H 1 +#include +#ifdef RESET_PID +#include +#endif + +#define CLONE_VM 0x00000100 +#define CLONE_THREAD 0x00010000 + +/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg, + void *parent_tidptr, void *tls, void *child_tidptr) */ + + .text +#if _MIPS_SIM == _ABIO32 +# define EXTRA_LOCALS 1 +#else +# define EXTRA_LOCALS 0 +#endif +LOCALSZ= 4 +FRAMESZ= (((NARGSAVE+LOCALSZ)*SZREG)+ALSZ)&ALMASK +GPOFF= FRAMESZ-(1*SZREG) +NESTED(clone,4*SZREG,sp) +#ifdef __PIC__ + SETUP_GP +#endif + PTR_SUBU sp, FRAMESZ + SETUP_GP64 (GPOFF, clone) +#ifdef __PIC__ + SAVE_GP (GPOFF) +#endif +#ifdef PROF + .set noat + move $1,ra + jal _mcount + .set at +#endif + + + /* Sanity check arguments. */ + li v0,EINVAL + beqz a0,L(error) /* No NULL function pointers. */ + beqz a1,L(error) /* No NULL stack pointers. */ + + PTR_SUBU a1,32 /* Reserve argument save space. */ + PTR_S a0,0(a1) /* Save function pointer. */ + PTR_S a3,PTRSIZE(a1) /* Save argument pointer. */ +#ifdef RESET_PID + LONG_S a2,(PTRSIZE*2)(a1) /* Save clone flags. */ +#endif + + move a0,a2 + + /* Shuffle in the last three arguments - arguments 5, 6, and 7 to + this function, but arguments 3, 4, and 5 to the syscall. */ +#if _MIPS_SIM == _ABIO32 + PTR_L a2,(FRAMESZ+PTRSIZE+PTRSIZE+16)(sp) + PTR_S a2,16(sp) + PTR_L a2,(FRAMESZ+16)(sp) + PTR_L a3,(FRAMESZ+PTRSIZE+16)(sp) +#else + move a2,a4 + move a3,a5 + move a4,a6 +#endif + + /* Do the system call */ + li v0,__NR_clone + syscall + + bnez a3,L(error) + beqz v0,L(thread_start) + + /* Successful return from the parent */ + RESTORE_GP64 + PTR_ADDU sp, FRAMESZ + j $31 ; nop + + /* Something bad happened -- no child created */ +L(error): +#ifdef __PIC__ + PTR_LA t9,__syscall_error + RESTORE_GP64 + PTR_ADDU sp, FRAMESZ + /* uClibc change -- start */ + move a0,v0 /* Pass return val to C function. */ + /* uClibc change -- stop */ + jr t9 +#else + RESTORE_GP64 + PTR_ADDU sp, FRAMESZ + /* uClibc change -- start */ + move a0,v0 /* Pass return val to C function. */ + /* uClibc change -- stop */ + j __syscall_error +#endif + END(clone) + +/* Load up the arguments to the function. Put this block of code in + its own function so that we can terminate the stack trace with our + debug info. */ + +ENTRY(__thread_start) +L(thread_start): + /* cp is already loaded. */ + SAVE_GP (GPOFF) + /* The stackframe has been created on entry of clone(). */ + +#ifdef RESET_PID + /* Check and see if we need to reset the PID. */ + LONG_L a0,(PTRSIZE*2)(sp) + and a1,a0,CLONE_THREAD + beqz a1,L(restore_pid) +L(donepid): +#endif + + /* Restore the arg for user's function. */ + PTR_L t9,0(sp) /* Function pointer. */ + PTR_L a0,PTRSIZE(sp) /* Argument pointer. */ + + /* Call the user's function. */ + jal t9 + + /* Call _exit rather than doing it inline for breakpoint purposes. */ + move a0,v0 +#ifdef __PIC__ + PTR_LA t9,_exit + jalr t9 +#else + jal _exit +#endif + +#ifdef RESET_PID +L(restore_pid): + and a1,a0,CLONE_VM + li v0,-1 + bnez a1,L(gotpid) + li v0,__NR_getpid + syscall +L(gotpid): + READ_THREAD_POINTER(v1) + INT_S v0,PID_OFFSET(v1) + INT_S v0,TID_OFFSET(v1) + b L(donepid) +#endif + + END(__thread_start) + +weak_alias(clone, __clone) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/crt1.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/crt1.S new file mode 100644 index 00000000..6a804125 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/crt1.S @@ -0,0 +1,131 @@ +/* Startup code compliant to the ELF Mips ABI. + Copyright (C) 1995, 1997, 2000, 2001, 2002, 2003, 2004 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file with other + programs, and to distribute those programs without any restriction + coming from the use of this file. (The GNU Lesser General Public + License restrictions do apply in other respects; for example, they + cover modification of the file, and distribution when not linked + into another program.) + + Note that people who make modified versions of this file are not + obligated to grant this special exception for their modified + versions; it is their choice whether to do so. The GNU Lesser + General Public License gives permission to release a modified + version without this exception; this exception also makes it + possible to release a modified version which carries forward this + exception. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + + +#include +#include +#include + + +/* This is the canonical entry point, usually the first thing in the text + segment. The SVR4/Mips ABI (pages 3-31, 3-32) says that when the entry + point runs, most registers' values are unspecified, except for: + + v0 ($2) Contains a function pointer to be registered with `atexit'. + This is how the dynamic linker arranges to have DT_FINI + functions called for shared libraries that have been loaded + before this code runs. + + sp ($29) The stack contains the arguments and environment: + 0(%esp) argc + 4(%esp) argv[0] + ... + (4*argc)(%esp) NULL + (4*(argc+1))(%esp) envp[0] + ... + NULL + ra ($31) The return address register is set to zero so that programs + that search backword through stack frames recognize the last + stack frame. +*/ + + +/* We need to call: + __uClibc_main (int (*main) (int, char **, char **), int argc, + char **argv, void (*init) (void), void (*fini) (void), + void (*rtld_fini) (void), void *stack_end) +*/ + +.text + .globl __start + .type __start,@function + .type _init,@function + .type _fini,@function +#ifndef __UCLIBC_CTOR_DTOR__ + .weak _init + .weak _fini +#endif + .type main,@function + .type __uClibc_main,@function + .ent __start + +__start: +#ifdef __PIC__ + SETUP_GPX($0) + SETUP_GPX64($25,$0) +#else + PTR_LA $28, _gp /* Setup GP correctly if we're non-PIC. */ + move $31, $0 +#endif + + PTR_LA $4, main /* main */ + PTR_L $5, 0($29) /* argc */ + PTR_ADDIU $6, $29, PTRSIZE /* argv */ + + /* Allocate space on the stack for seven arguments and + * make sure the stack is aligned to double words (8 bytes) */ + + and $29, -2 * SZREG + +#if _MIPS_SIM == _MIPS_SIM_ABI32 + PTR_SUBIU $29, 32 +#endif + PTR_LA $7, _init /* init */ + PTR_LA $8, _fini +#if _MIPS_SIM == _MIPS_SIM_ABI32 + PTR_S $8, 16($29) /* fini */ + PTR_S $2, 20($29) /* rtld_fini */ + PTR_S $29, 24($29) /* stack_end */ +#else + move $9, $2 /* rtld_fini */ + move $10, $29 /* stack_end */ +#endif + jal __uClibc_main +hlt: + /* Crash if somehow `__uClibc_main' returns anyway. */ + b hlt +.size __start,.-__start +.end __start + +/* Define a symbol for the first piece of initialized data. */ + .data + .globl __data_start +__data_start: + .long 0 + .weak data_start + data_start = __data_start + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/crti.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/crti.S new file mode 100644 index 00000000..9311a735 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/crti.S @@ -0,0 +1,158 @@ +#include "sgidefs.h" +#if _MIPS_SIM == _MIPS_SIM_ABI32 + .file 1 "initfini.c" + .section .mdebug.abi32 + .previous + .abicalls +#APP + + .section .init +#NO_APP + .align 2 + .globl _init + .ent _init + .type _init, @function +_init: + .frame $sp,32,$31 # vars= 0, regs= 2/0, args= 16, extra= 8 + .mask 0x90000000,-4 + .fmask 0x00000000,0 + .set noreorder + .cpload $25 + .set reorder + subu $sp,$sp,32 + .cprestore 16 + sw $31,28($sp) + sw $28,24($sp) +#APP + + .align 2 + .end _init + + .section .fini +#NO_APP + .align 2 + .globl _fini + .ent _fini + .type _fini, @function +_fini: + .frame $sp,32,$31 # vars= 0, regs= 2/0, args= 16, extra= 8 + .mask 0x90000000,-4 + .fmask 0x00000000,0 + .set noreorder + .cpload $25 + .set reorder + subu $sp,$sp,32 + .cprestore 16 + sw $31,28($sp) + sw $28,24($sp) +#APP + .align 2 + .end _fini + + .ident "GCC: (GNU) 3.3.2" +#elif _MIPS_SIM == _MIPS_SIM_NABI32 + .file 1 "initfini.c" + .section .mdebug.abiN32 + .previous + .abicalls +#APP + + .section .init +#NO_APP + .align 2 + .align 3 + .globl _init + .ent _init + .type _init, @function +_init: + .frame $sp,16,$31 # vars= 0, regs= 2/0, args= 0, gp= 0 + .mask 0x90000000,-8 + .fmask 0x00000000,0 + addiu $sp,$sp,-16 + sd $28,0($sp) + lui $28,%hi(%neg(%gp_rel(_init))) + addu $28,$28,$25 + addiu $28,$28,%lo(%neg(%gp_rel(_init))) + sd $31,8($sp) +#APP + + .align 3 + .end _init + + .section .fini +#NO_APP + .align 2 + .align 3 + .globl _fini + .ent _fini + .type _fini, @function +_fini: + .frame $sp,16,$31 # vars= 0, regs= 2/0, args= 0, gp= 0 + .mask 0x90000000,-8 + .fmask 0x00000000,0 + addiu $sp,$sp,-16 + sd $28,0($sp) + lui $28,%hi(%neg(%gp_rel(_fini))) + addu $28,$28,$25 + addiu $28,$28,%lo(%neg(%gp_rel(_fini))) + sd $31,8($sp) +#APP + .align 3 + .end _fini + + .ident "GCC: (GNU) 3.4.3" +#else /* N64 */ + .file 1 "initfini.c" + .section .mdebug.abi64 + .previous + .abicalls +#APP + + + .section .init +#NO_APP + .align 2 + .globl _init + .ent _init + .type _init, @function +_init: + .frame $sp,32,$31 # vars= 0, regs= 2/0, args= 0, extra= 16 + .mask 0x90000000,-8 + .fmask 0x00000000,0 + dsubu $sp,$sp,32 + sd $31,24($sp) + sd $28,16($sp) + .set noat + lui $1,%hi(%neg(%gp_rel(_init))) + addiu $1,$1,%lo(%neg(%gp_rel(_init))) + daddu $gp,$1,$25 + .set at +#APP + + .align 2 + .end _init + + .section .fini +#NO_APP + .align 2 + .globl _fini + .ent _fini + .type _fini, @function +_fini: + .frame $sp,32,$31 # vars= 0, regs= 2/0, args= 0, extra= 16 + .mask 0x90000000,-8 + .fmask 0x00000000,0 + dsubu $sp,$sp,32 + sd $31,24($sp) + sd $28,16($sp) + .set noat + lui $1,%hi(%neg(%gp_rel(_fini))) + addiu $1,$1,%lo(%neg(%gp_rel(_fini))) + daddu $gp,$1,$25 + .set at +#APP + .align 2 + .end _fini + + .ident "GCC: (GNU) 3.3.2" +#endif /* N64 */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/crtn.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/crtn.S new file mode 100644 index 00000000..f3756a2f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/crtn.S @@ -0,0 +1,130 @@ +#include "sgidefs.h" +#if _MIPS_SIM == _MIPS_SIM_ABI32 + .file 1 "initfini.c" + .section .mdebug.abi32 + .previous + .abicalls +#APP + + .section .init +#NO_APP + .align 2 + .globl _init + .type _init, @function +#NO_APP + lw $31,28($sp) + #nop + .set noreorder + .set nomacro + j $31 + addu $sp,$sp,32 + .set macro + .set reorder + +#APP + + .section .fini +#NO_APP + .align 2 + .globl _fini + .type _fini, @function +#NO_APP + lw $31,28($sp) + #nop + .set noreorder + .set nomacro + j $31 + addu $sp,$sp,32 + .set macro + .set reorder + +#APP + + .ident "GCC: (GNU) 3.3.2" +#elif _MIPS_SIM == _MIPS_SIM_NABI32 + .file 1 "initfini.c" + .section .mdebug.abiN32 + .previous + .abicalls +#APP + + .section .init +#NO_APP + .align 3 + .globl _init + .type _init, @function +#NO_APP + ld $31,8($sp) + ld $28,0($sp) + .set noreorder + .set nomacro + j $31 + addiu $sp,$sp,16 + .set macro + .set reorder +#APP + + .section .fini +#NO_APP + .align 3 + .globl _fini + .type _fini, @function +#NO_APP + ld $31,8($sp) + ld $28,0($sp) + .set noreorder + .set nomacro + j $31 + addiu $sp,$sp,16 + .set macro + .set reorder + +#APP + + .ident "GCC: (GNU) 3.4.3" +#else /* N64 */ + .file 1 "initfini.c" + .section .mdebug.abi64 + .previous + .abicalls +#APP + + + .section .init +#NO_APP + .align 2 + .globl _init + .type _init, @function +#NO_APP + ld $31,24($sp) + ld $28,16($sp) + #nop + .set noreorder + .set nomacro + j $31 + daddu $sp,$sp,32 + .set macro + .set reorder + +#APP + + .section .fini +#NO_APP + .align 2 + .globl _fini + .type _fini, @function +#NO_APP + ld $31,24($sp) + ld $28,16($sp) + #nop + .set noreorder + .set nomacro + j $31 + daddu $sp,$sp,32 + .set macro + .set reorder + +#APP + + .ident "GCC: (GNU) 3.3.2" +#endif /* N64 */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/fpu_control.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/fpu_control.h new file mode 100644 index 00000000..c58b2350 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/fpu_control.h @@ -0,0 +1,100 @@ +/* FPU control word bits. Mips version. + Copyright (C) 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Olaf Flebbe and Ralf Baechle. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FPU_CONTROL_H +#define _FPU_CONTROL_H + +/* MIPS FPU floating point control register bits. + * + * 31-25 -> floating point conditions code bits 7-1. These bits are only + * available in MIPS IV. + * 24 -> flush denormalized results to zero instead of + * causing unimplemented operation exception. This bit is only + * available for MIPS III and newer. + * 23 -> Condition bit + * 22-18 -> reserved (read as 0, write with 0) + * 17 -> cause bit for unimplemented operation + * 16 -> cause bit for invalid exception + * 15 -> cause bit for division by zero exception + * 14 -> cause bit for overflow exception + * 13 -> cause bit for underflow exception + * 12 -> cause bit for inexact exception + * 11 -> enable exception for invalid exception + * 10 -> enable exception for division by zero exception + * 9 -> enable exception for overflow exception + * 8 -> enable exception for underflow exception + * 7 -> enable exception for inexact exception + * 6 -> flag invalid exception + * 5 -> flag division by zero exception + * 4 -> flag overflow exception + * 3 -> flag underflow exception + * 2 -> flag inexact exception + * 1-0 -> rounding control + * + * + * Rounding Control: + * 00 - rounding to nearest (RN) + * 01 - rounding toward zero (RZ) + * 10 - rounding (up) toward plus infinity (RP) + * 11 - rounding (down)toward minus infinity (RM) + */ + +#include + +/* masking of interrupts */ +#define _FPU_MASK_V 0x0800 /* Invalid operation */ +#define _FPU_MASK_Z 0x0400 /* Division by zero */ +#define _FPU_MASK_O 0x0200 /* Overflow */ +#define _FPU_MASK_U 0x0100 /* Underflow */ +#define _FPU_MASK_I 0x0080 /* Inexact operation */ + +/* flush denormalized numbers to zero */ +#define _FPU_FLUSH_TZ 0x1000000 + +/* rounding control */ +#define _FPU_RC_NEAREST 0x0 /* RECOMMENDED */ +#define _FPU_RC_ZERO 0x1 +#define _FPU_RC_UP 0x2 +#define _FPU_RC_DOWN 0x3 + +#define _FPU_RESERVED 0xfe3c0000 /* Reserved bits in cw */ + + +/* The fdlibm code requires strict IEEE double precision arithmetic, + and no interrupts for exceptions, rounding to nearest. */ + +#define _FPU_DEFAULT 0x00000000 + +/* IEEE: same as above, but exceptions */ +#define _FPU_IEEE 0x00000F80 + +/* Type of the control word. */ +typedef unsigned int fpu_control_t __attribute__ ((__mode__ (__SI__))); + +/* Macros for accessing the hardware control word. */ +#define _FPU_GETCW(cw) __asm__ ("cfc1 %0,$31" : "=r" (cw)) +#define _FPU_SETCW(cw) __asm__ ("ctc1 %0,$31" : : "r" (cw)) + +#if 0 +/* Default control word set at startup. */ +extern fpu_control_t __fpu_control; +#endif + +#endif /* fpu_control.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/mmap.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/mmap.c new file mode 100644 index 00000000..be96451e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/mmap.c @@ -0,0 +1,26 @@ +/* Use new style mmap for mips */ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include + + +#if 0 +/* For now, leave mmap using mmap1 since mmap2 seems + * to have issues (i.e. it doesn't work 100% properly). + */ +#ifdef __NR_mmap2 +# undef __NR_mmap +# define __NR_mmap __NR_mmap2 +#endif +#endif + +_syscall6 (__ptr_t, mmap, __ptr_t, addr, size_t, len, int, prot, + int, flags, int, fd, __off_t, offset) +libc_hidden_def(mmap) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/pipe.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/pipe.S new file mode 100644 index 00000000..8b302367 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/pipe.S @@ -0,0 +1,45 @@ +/* pipe system call for Linux/MIPS */ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/*see uClibc's sh/pipe.c and glibc-2.2.4's mips/pipe.S */ + +#include +#include +#include +#include + + .globl pipe + .ent pipe, 0 + .type pipe,@function +pipe: +#ifdef __PIC__ + SETUP_GP +#endif + li v0,__NR_pipe + syscall + bnez a3, 1f + sw v0, 0(a0) + sw v1, 4(a0) + li v0, 0 + j ra +1: + /* uClibc change -- start */ + move a0,v0 /* Pass return val to C function. */ + /* uClibc change -- stop */ + +#ifdef __PIC__ + SETUP_GP64(v0, pipe) + PTR_LA t9, __syscall_error + RESTORE_GP64 + jr t9 +#else + j __syscall_error +#endif +1: + .end pipe + .size pipe,.-pipe +libc_hidden_def(pipe) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/posix_fadvise.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/posix_fadvise.c new file mode 100644 index 00000000..8546d96b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/posix_fadvise.c @@ -0,0 +1,39 @@ +/* vi: set sw=4 ts=4: */ +/* + * posix_fadvise() for MIPS uClibc + * http://www.opengroup.org/onlinepubs/009695399/functions/posix_fadvise.html + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +int posix_fadvise(int fd, off_t offset, off_t len, int advice) +{ +/* MIPS kernel only has NR_fadvise64 which acts as NR_fadvise64_64 */ +#ifdef __NR_fadvise64 + INTERNAL_SYSCALL_DECL(err); +# if _MIPS_SIM == _ABIO32 + int ret = INTERNAL_SYSCALL(fadvise64, err, 7, fd, 0, + __LONG_LONG_PAIR ((long) (offset >> 31), (long) offset), + __LONG_LONG_PAIR ((long) (len >> 31), (long) len), + advice); +# else /* N32 || N64 */ + int ret = INTERNAL_SYSCALL(fadvise64, err, 4, fd, offset, len, advice); +# endif + if (INTERNAL_SYSCALL_ERROR_P (ret, err)) + return INTERNAL_SYSCALL_ERRNO (ret, err); + return 0; +#else + return ENOSYS; +#endif +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/posix_fadvise64.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/posix_fadvise64.c new file mode 100644 index 00000000..d9b89d12 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/posix_fadvise64.c @@ -0,0 +1,43 @@ +/* vi: set sw=4 ts=4: */ +/* + * posix_fadvise64() for MIPS uClibc + * http://www.opengroup.org/onlinepubs/009695399/functions/posix_fadvise.html + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __UCLIBC_HAS_LFS__ + +int posix_fadvise64(int fd, __off64_t offset, __off64_t len, int advice) +{ +/* MIPS kernel only has NR_fadvise64 which acts as NR_fadvise64_64 */ +#ifdef __NR_fadvise64 + INTERNAL_SYSCALL_DECL(err); +# if _MIPS_SIM == _MIPS_SIM_ABI32 + int ret = INTERNAL_SYSCALL(fadvise64, err, 7, fd, 0, + __LONG_LONG_PAIR ((long) (offset >> 32), (long) offset), + __LONG_LONG_PAIR ((long) (len >> 32), (long) len), + advice); +# else /* N32 || N64 */ + int ret = INTERNAL_SYSCALL(fadvise64, err, 4, fd, offset, len, advice); +# endif + if (INTERNAL_SYSCALL_ERROR_P (ret, err)) + return INTERNAL_SYSCALL_ERRNO (ret, err); + return 0; +#else + return ENOSYS; +#endif +} + +#endif /* __UCLIBC_HAS_LFS__ */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/pread_write.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/pread_write.c new file mode 100644 index 00000000..ea6b15f6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/pread_write.c @@ -0,0 +1,115 @@ +/* vi: set sw=4 ts=4: */ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ +/* + * Based in part on the files + * ./sysdeps/unix/sysv/linux/pwrite.c, + * ./sysdeps/unix/sysv/linux/pread.c, + * sysdeps/posix/pread.c + * sysdeps/posix/pwrite.c + * from GNU libc 2.2.5, but reworked considerably... + */ + +#include +#include +#include +#include +#include + +#ifdef __NR_pread64 /* Newer kernels renamed but it's the same. */ +# ifdef __NR_pread +# error "__NR_pread and __NR_pread64 both defined???" +# endif +# define __NR_pread __NR_pread64 +#endif + +extern __typeof(pread) __libc_pread; +extern __typeof(pwrite) __libc_pwrite; +#ifdef __UCLIBC_HAS_LFS__ +extern __typeof(pread64) __libc_pread64; +extern __typeof(pwrite64) __libc_pwrite64; +#endif + +#include + + +#ifdef __NR_pread + +# if _MIPS_SIM == _MIPS_SIM_ABI64 +# define __NR___libc_pread __NR_pread +_syscall4(ssize_t, __libc_pread, int, fd, void *, buf, size_t, count, off_t, offset) +weak_alias (__libc_pread, pread) +# ifdef __UCLIBC_HAS_LFS__ +# define __NR___libc_pread64 __NR_pread +_syscall4(ssize_t, __libc_pread64, int, fd, void *, buf, size_t, count, off64_t, offset) +weak_alias (__libc_pread64, pread64) +# endif /* __UCLIBC_HAS_LFS__ */ +# else /* O32 || N32 */ +# define __NR___syscall_pread __NR_pread +static __inline__ _syscall6(ssize_t, __syscall_pread, int, fd, void *, buf, + size_t, count, int, dummy, off_t, offset_hi, off_t, offset_lo) + +ssize_t __libc_pread(int fd, void *buf, size_t count, off_t offset) +{ + return(__syscall_pread(fd,buf,count,0,__LONG_LONG_PAIR(offset>>31,offset))); +} +weak_alias(__libc_pread,pread) + +# ifdef __UCLIBC_HAS_LFS__ +ssize_t __libc_pread64(int fd, void *buf, size_t count, off64_t offset) +{ + uint32_t low = offset & 0xffffffff; + uint32_t high = offset >> 32; + return(__syscall_pread(fd, buf, count, 0, __LONG_LONG_PAIR (high, low))); +} +weak_alias(__libc_pread64,pread64) +# endif /* __UCLIBC_HAS_LFS__ */ +# endif /* O32 || N32 */ + +#endif /* __NR_pread */ + +/**********************************************************************/ + +#ifdef __NR_pwrite64 /* Newer kernels renamed but it's the same. */ +# ifdef __NR_pwrite +# error "__NR_pwrite and __NR_pwrite64 both defined???" +# endif +# define __NR_pwrite __NR_pwrite64 +#endif + +#ifdef __NR_pwrite + +# if _MIPS_SIM == _MIPS_SIM_ABI64 +# define __NR___libc_pwrite __NR_pwrite +_syscall4(ssize_t, __libc_pwrite, int, fd, const void *, buf, size_t, count, off_t, offset) +weak_alias (__libc_pwrite, pwrite) +# ifdef __UCLIBC_HAS_LFS__ +# define __NR___libc_pwrite64 __NR_pwrite +_syscall4(ssize_t, __libc_pwrite64, int, fd, const void *, buf, size_t, count, off64_t, offset) +weak_alias (__libc_pwrite64, pwrite64) +# endif /* __UCLIBC_HAS_LFS__ */ +# else /* O32 || N32 */ +# define __NR___syscall_pwrite __NR_pwrite +static __inline__ _syscall6(ssize_t, __syscall_pwrite, int, fd, const void *, buf, + size_t, count, int, dummy, off_t, offset_hi, off_t, offset_lo) + +ssize_t __libc_pwrite(int fd, const void *buf, size_t count, off_t offset) +{ + return(__syscall_pwrite(fd,buf,count,0,__LONG_LONG_PAIR(offset>>31,offset))); +} +weak_alias(__libc_pwrite,pwrite) + +# ifdef __UCLIBC_HAS_LFS__ +ssize_t __libc_pwrite64(int fd, const void *buf, size_t count, off64_t offset) +{ + uint32_t low = offset & 0xffffffff; + uint32_t high = offset >> 32; + return(__syscall_pwrite(fd, buf, count, 0, __LONG_LONG_PAIR (high, low))); +} +weak_alias(__libc_pwrite64,pwrite64) +# endif /* __UCLIBC_HAS_LFS__ */ +# endif /* O32 || N32 */ +#endif /* __NR_pwrite */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/readahead.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/readahead.c new file mode 100644 index 00000000..9157c276 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/readahead.c @@ -0,0 +1,41 @@ +/* Provide kernel hint to read ahead. + Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + +#ifdef __UCLIBC_HAS_LFS__ +#include <_lfs_64.h> +# ifdef __NR_readahead + +ssize_t readahead(int fd, off64_t offset, size_t count) +{ +# if _MIPS_SIM == _ABIO32 + return INLINE_SYSCALL (readahead, 5, fd, 0, + __LONG_LONG_PAIR ((off_t) (offset >> 32), (off_t) offset), + count); +# else /* N32 || N64 */ + return INLINE_SYSCALL (readahead, 3, fd, offset, count); +# endif +} + +# endif +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/setjmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/setjmp.S new file mode 100644 index 00000000..226f7552 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/setjmp.S @@ -0,0 +1,61 @@ +/* Copyright (C) 1996, 1997, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +/* The function __sigsetjmp_aux saves all the registers, but it can't + reliably access the stack or frame pointers, so we pass them in as + extra arguments. */ +#ifdef __PIC__ + .option pic2 +#endif + + +.text +.global __sigsetjmp +.align 2; +.ent __sigsetjmp,0; +.type __sigsetjmp,@function + +__sigsetjmp: +#ifdef __PIC__ + .set noreorder +#if _MIPS_SIM == _MIPS_SIM_ABI32 + .cpload t9 +#else + .cpsetup t9, v0, __sigsetjmp +#endif + .set reorder +#endif + move a2, sp +#ifdef fp + move a3, fp +#else + move a3, $fp +#endif +#ifdef __PIC__ + PTR_LA t9, __sigsetjmp_aux +#if _MIPS_SIM != _MIPS_SIM_ABI32 + .cpreturn +#endif + jr t9 +#else + j __sigsetjmp_aux +#endif + .end __sigsetjmp diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/setjmp_aux.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/setjmp_aux.c new file mode 100644 index 00000000..751b32d7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/setjmp_aux.c @@ -0,0 +1,108 @@ +/* Copyright (C) 1996, 1997, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Brendan Kehoe (brendan@zen.org). + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + +/* This function is only called via the assembly language routine + __sigsetjmp, which arranges to pass in the stack pointer and the frame + pointer. We do things this way because it's difficult to reliably + access them in C. */ + +extern int __sigjmp_save (sigjmp_buf, int); + +int +#if _MIPS_SIM == _MIPS_SIM_ABI64 +__sigsetjmp_aux (jmp_buf env, int savemask, long sp, long fp) +#else /* O32 || N32 */ +__sigsetjmp_aux (jmp_buf env, int savemask, int sp, int fp) +#endif /* O32 || N32 */ +{ +#if defined __UCLIBC_HAS_FLOATS__ && ! defined __UCLIBC_HAS_SOFT_FLOAT__ + /* Store the floating point callee-saved registers... */ +#if _MIPS_SIM == _MIPS_SIM_ABI64 + __asm__ __volatile__ ("s.d $f24, %0" : : "m" (env[0].__jmpbuf[0].__fpregs[0])); + __asm__ __volatile__ ("s.d $f25, %0" : : "m" (env[0].__jmpbuf[0].__fpregs[1])); + __asm__ __volatile__ ("s.d $f26, %0" : : "m" (env[0].__jmpbuf[0].__fpregs[2])); + __asm__ __volatile__ ("s.d $f27, %0" : : "m" (env[0].__jmpbuf[0].__fpregs[3])); + __asm__ __volatile__ ("s.d $f28, %0" : : "m" (env[0].__jmpbuf[0].__fpregs[4])); + __asm__ __volatile__ ("s.d $f29, %0" : : "m" (env[0].__jmpbuf[0].__fpregs[5])); + __asm__ __volatile__ ("s.d $f30, %0" : : "m" (env[0].__jmpbuf[0].__fpregs[6])); + __asm__ __volatile__ ("s.d $f31, %0" : : "m" (env[0].__jmpbuf[0].__fpregs[7])); +#else /* O32 || N32 */ + __asm__ __volatile__ ("s.d $f20, %0" : : "m" (env[0].__jmpbuf[0].__fpregs[0])); + __asm__ __volatile__ ("s.d $f22, %0" : : "m" (env[0].__jmpbuf[0].__fpregs[1])); + __asm__ __volatile__ ("s.d $f24, %0" : : "m" (env[0].__jmpbuf[0].__fpregs[2])); + __asm__ __volatile__ ("s.d $f26, %0" : : "m" (env[0].__jmpbuf[0].__fpregs[3])); + __asm__ __volatile__ ("s.d $f28, %0" : : "m" (env[0].__jmpbuf[0].__fpregs[4])); + __asm__ __volatile__ ("s.d $f30, %0" : : "m" (env[0].__jmpbuf[0].__fpregs[5])); +#endif /* O32 || N32 */ +#endif + + /* .. and the PC; */ +#if _MIPS_SIM == _MIPS_SIM_ABI64 + __asm__ __volatile__ ("sd $31, %0" : : "m" (env[0].__jmpbuf[0].__pc)); +#else + __asm__ __volatile__ ("sw $31, %0" : : "m" (env[0].__jmpbuf[0].__pc)); +#endif + + /* .. and the stack pointer; */ + env[0].__jmpbuf[0].__sp = (void *) sp; + + /* .. and the FP; it'll be in s8. */ + env[0].__jmpbuf[0].__fp = (void *) fp; + + /* .. and the GP; */ +#if _MIPS_SIM == _MIPS_SIM_ABI64 + __asm__ __volatile__ ("sd $gp, %0" : : "m" (env[0].__jmpbuf[0].__gp)); +#else + __asm__ __volatile__ ("sw $gp, %0" : : "m" (env[0].__jmpbuf[0].__gp)); +#endif + + /* .. and the callee-saved registers; */ +#if (_MIPS_SIM == _MIPS_SIM_ABI32) + __asm__ __volatile__ ("sw $16, %0" : : "m" (env[0].__jmpbuf[0].__regs[0])); + __asm__ __volatile__ ("sw $17, %0" : : "m" (env[0].__jmpbuf[0].__regs[1])); + __asm__ __volatile__ ("sw $18, %0" : : "m" (env[0].__jmpbuf[0].__regs[2])); + __asm__ __volatile__ ("sw $19, %0" : : "m" (env[0].__jmpbuf[0].__regs[3])); + __asm__ __volatile__ ("sw $20, %0" : : "m" (env[0].__jmpbuf[0].__regs[4])); + __asm__ __volatile__ ("sw $21, %0" : : "m" (env[0].__jmpbuf[0].__regs[5])); + __asm__ __volatile__ ("sw $22, %0" : : "m" (env[0].__jmpbuf[0].__regs[6])); + __asm__ __volatile__ ("sw $23, %0" : : "m" (env[0].__jmpbuf[0].__regs[7])); +#else /* N32 || N64 */ + __asm__ __volatile__ ("sd $16, %0" : : "m" (env[0].__jmpbuf[0].__regs[0])); + __asm__ __volatile__ ("sd $17, %0" : : "m" (env[0].__jmpbuf[0].__regs[1])); + __asm__ __volatile__ ("sd $18, %0" : : "m" (env[0].__jmpbuf[0].__regs[2])); + __asm__ __volatile__ ("sd $19, %0" : : "m" (env[0].__jmpbuf[0].__regs[3])); + __asm__ __volatile__ ("sd $20, %0" : : "m" (env[0].__jmpbuf[0].__regs[4])); + __asm__ __volatile__ ("sd $21, %0" : : "m" (env[0].__jmpbuf[0].__regs[5])); + __asm__ __volatile__ ("sd $22, %0" : : "m" (env[0].__jmpbuf[0].__regs[6])); + __asm__ __volatile__ ("sd $23, %0" : : "m" (env[0].__jmpbuf[0].__regs[7])); +#endif /* N32 || N64 */ + +#if defined __UCLIBC_HAS_FLOATS__ && ! defined __UCLIBC_HAS_SOFT_FLOAT__ + /* .. and finally get and reconstruct the floating point csr. */ + __asm__ ("cfc1 %0, $31" : "=r" (env[0].__jmpbuf[0].__fpc_csr)); +#endif + + /* Save the signal mask if requested. */ + return __sigjmp_save (env, savemask); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/sgidefs.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/sgidefs.h new file mode 100644 index 00000000..74509fdb --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/sgidefs.h @@ -0,0 +1,73 @@ +/* Copyright (C) 1996, 1997, 1998, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ralf Baechle . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SGIDEFS_H +#define _SGIDEFS_H 1 + +/* + * A crude hack to stop + */ +#undef __ASM_SGIDEFS_H +#define __ASM_SGIDEFS_H + +/* + * And remove any damage it might have already done + */ +#undef _MIPS_ISA_MIPS1 +#undef _MIPS_ISA_MIPS2 +#undef _MIPS_ISA_MIPS3 +#undef _MIPS_ISA_MIPS4 +#undef _MIPS_ISA_MIPS5 +#undef _MIPS_ISA_MIPS32 +#undef _MIPS_ISA_MIPS64 + +#undef _MIPS_SIM_ABI32 +#undef _MIPS_SIM_NABI32 +#undef _MIPS_SIM_ABI64 + +/* + * Definitions for the ISA level + */ +#define _MIPS_ISA_MIPS1 1 +#define _MIPS_ISA_MIPS2 2 +#define _MIPS_ISA_MIPS3 3 +#define _MIPS_ISA_MIPS4 4 +#define _MIPS_ISA_MIPS5 5 +#define _MIPS_ISA_MIPS32 6 +#define _MIPS_ISA_MIPS64 7 + +/* + * Subprogram calling convention + */ +#ifndef _ABIO32 +# define _ABIO32 1 +#endif +#define _MIPS_SIM_ABI32 _ABIO32 + +#ifndef _ABIN32 +# define _ABIN32 2 +#endif +#define _MIPS_SIM_NABI32 _ABIN32 + +#ifndef _ABI64 +# define _ABI64 3 +#endif +#define _MIPS_SIM_ABI64 _ABI64 + +#endif /* sgidefs.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/sigaction.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/sigaction.c new file mode 100644 index 00000000..f2d2747b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/sigaction.c @@ -0,0 +1,133 @@ +/* Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + Totally hacked up for uClibc by Erik Andersen + */ + +#include +#include +#include +#include +#include + +#define SA_RESTORER 0x04000000 + +extern __typeof(sigaction) __libc_sigaction; + + +#ifdef __NR_rt_sigaction + +# if _MIPS_SIM != _ABIO32 +# ifdef __NR_rt_sigreturn +static void restore_rt(void) __asm__ ("__restore_rt"); +# endif +# ifdef __NR_sigreturn +static void restore(void) __asm__ ("__restore"); +# endif +# endif + +/* If ACT is not NULL, change the action for SIG to *ACT. + If OACT is not NULL, put the old action for SIG in *OACT. */ +int __libc_sigaction(int sig, const struct sigaction *act, struct sigaction *oact) +{ +# if _MIPS_SIM != _ABIO32 + struct sigaction kact; + if (act) { + memcpy(&kact, act, sizeof(kact)); + kact.sa_restorer = &restore_rt; + act = &kact; + } +# endif + + /* NB: kernel (as of 2.6.25) will return EINVAL + * if sizeof(act->sa_mask) does not match kernel's sizeof(sigset_t) */ + return __syscall_rt_sigaction(sig, act, oact, sizeof(act->sa_mask)); +} + +#else + +extern void restore(void) __asm__ ("__restore") attribute_hidden; + +/* If ACT is not NULL, change the action for SIG to *ACT. + If OACT is not NULL, put the old action for SIG in *OACT. */ +int __libc_sigaction(int sig, const struct sigaction *act, struct sigaction *oact) +{ + int result; + struct old_kernel_sigaction kact, koact; + + if (act) { + kact.k_sa_handler = act->sa_handler; + kact.sa_mask = act->sa_mask.__val[0]; + kact.sa_flags = act->sa_flags; +# if _MIPS_SIM == _ABIO32 + kact.sa_restorer = act->sa_restorer; +# else + kact.sa_restorer = &restore_rt; +# endif + } + result = __syscall_sigaction(sig, + act ? &kact : NULL, + oact ? &koact : NULL); + if (result < 0) { + __set_errno(-result); + return -1; + } + if (oact) { + oact->sa_handler = koact.k_sa_handler; + oact->sa_mask.__val[0] = koact.sa_mask; + oact->sa_flags = koact.sa_flags; + oact->sa_restorer = koact.sa_restorer; + } + return result; +} + +#endif + + +#ifndef LIBC_SIGACTION +weak_alias(__libc_sigaction,sigaction) +libc_hidden_weak(sigaction) +#endif + + +/* NOTE: Please think twice before making any changes to the bits of + code below. GDB needs some intimate knowledge about it to + recognize them as signal trampolines, and make backtraces through + signal handlers work right. Important are both the names + (__restore_rt) and the exact instruction sequence. + If you ever feel the need to make any changes, please notify the + appropriate GDB maintainer. */ + +#define RESTORE(name, syscall) RESTORE2(name, syscall) +#define RESTORE2(name, syscall) \ +__asm__ ( \ + ".align 4\n" \ + "__" #name ":\n" \ + " li $2, " #syscall "\n" \ + " syscall\n" \ +); + +/* The return code for realtime-signals. */ +#if _MIPS_SIM != _ABIO32 +# ifdef __NR_rt_sigreturn +RESTORE(restore_rt, __NR_rt_sigreturn) +# endif +# ifdef __NR_sigreturn +RESTORE(restore, __NR_sigreturn) +# endif +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/sys/asm.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/sys/asm.h new file mode 100644 index 00000000..d424ed3b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/sys/asm.h @@ -0,0 +1,491 @@ +/* Copyright (C) 1997, 1998, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ralf Baechle . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_ASM_H +#define _SYS_ASM_H + +#include + +#ifndef CAT +# ifdef __STDC__ +# define __CAT(str1,str2) str1##str2 +# else +# define __CAT(str1,str2) str1/**/str2 +# endif +# define CAT(str1,str2) __CAT(str1,str2) +#endif + +/* + * Macros to handle different pointer/register sizes for 32/64-bit code + * + * 64 bit address space isn't used yet, so we may use the R3000 32 bit + * defines for now. + */ +#if (_MIPS_SIM == _MIPS_SIM_ABI32) || (_MIPS_SIM == _MIPS_SIM_NABI32) +# define PTR .word +# define PTRSIZE 4 +# define PTRLOG 2 +#elif (_MIPS_SIM == _MIPS_SIM_ABI64) +# define PTR .dword +# define PTRSIZE 8 +# define PTRLOG 3 +#endif + +/* + * PIC specific declarations + */ +#if (_MIPS_SIM == _MIPS_SIM_ABI32) +# ifdef __PIC__ +# define CPRESTORE(register) \ + .cprestore register +# define CPLOAD(register) \ + .cpload register +# else +# define CPRESTORE(register) +# define CPLOAD(register) +# endif + +# define CPADD(register) \ + .cpadd register + +/* + * Set gp when at 1st instruction + */ +# define SETUP_GP \ + .set noreorder; \ + .cpload $25; \ + .set reorder +/* Set gp when not at 1st instruction */ +# define SETUP_GPX(r) \ + .set noreorder; \ + move r, $31; /* Save old ra. */ \ + bal 10f; /* Find addr of cpload. */ \ + nop; \ +10: \ + .cpload $31; \ + move $31, r; \ + .set reorder +# define SETUP_GPX_L(r, l) \ + .set noreorder; \ + move r, $31; /* Save old ra. */ \ + bal l; /* Find addr of cpload. */ \ + nop; \ +l: \ + .cpload $31; \ + move $31, r; \ + .set reorder +# define SAVE_GP(x) \ + .cprestore x /* Save gp trigger t9/jalr conversion. */ +# define SETUP_GP64(a, b) +# define SETUP_GPX64(a, b) +# define SETUP_GPX64_L(cp_reg, ra_save, l) +# define RESTORE_GP64 +# define USE_ALT_CP(a) +# define L(label) $L ## label +#else /* (_MIPS_SIM == _MIPS_SIM_ABI64) || (_MIPS_SIM == _MIPS_SIM_NABI32) */ +/* + * For callee-saved gp calling convention: + */ +# define SETUP_GP +# define SETUP_GPX(r) +# define SETUP_GPX_L(r, l) +# define SAVE_GP(x) + +# define SETUP_GP64(gpoffset, proc) \ + .cpsetup $25, gpoffset, proc +# define SETUP_GPX64(cp_reg, ra_save) \ + move ra_save, $31; /* Save old ra. */ \ + .set noreorder; \ + bal 10f; /* Find addr of .cpsetup. */ \ + nop; \ +10: \ + .set reorder; \ + .cpsetup $31, cp_reg, 10b; \ + move $31, ra_save +# define SETUP_GPX64_L(cp_reg, ra_save, l) \ + move ra_save, $31; /* Save old ra. */ \ + .set noreorder; \ + bal l; /* Find addr of .cpsetup. */ \ + nop; \ +l: \ + .set reorder; \ + .cpsetup $31, cp_reg, l; \ + move $31, ra_save +# define RESTORE_GP64 \ + .cpreturn +/* Use alternate register for context pointer. */ +# define USE_ALT_CP(reg) \ + .cplocal reg +# define L(label) .L ## label +#endif /* _MIPS_SIM != _MIPS_SIM_ABI32 */ + +/* + * Stack Frame Definitions + */ +#if (_MIPS_SIM == _MIPS_SIM_ABI32) +# define NARGSAVE 4 /* Space for 4 argument registers must be allocated. */ +#endif +#if (_MIPS_SIM == _MIPS_SIM_ABI64 || _MIPS_SIM == _MIPS_SIM_NABI32) +# define NARGSAVE 0 /* No caller responsibilities. */ +#endif + + +/* + * LEAF - declare leaf routine + */ +#define LEAF(symbol) \ + .globl symbol; \ + .align 2; \ + .type symbol,@function; \ + .ent symbol,0; \ +symbol: .frame sp,0,ra + +/* + * NESTED - declare nested routine entry point + */ +#define NESTED(symbol, framesize, rpc) \ + .globl symbol; \ + .align 2; \ + .type symbol,@function; \ + .ent symbol,0; \ +symbol: .frame sp, framesize, rpc + +/* + * END - mark end of function + */ +#ifndef END +# define END(function) \ + .end function; \ + .size function,.-function +#endif + +/* + * EXPORT - export definition of symbol + */ +#define EXPORT(symbol) \ + .globl symbol; \ +symbol: + +/* + * ABS - export absolute symbol + */ +#define ABS(symbol,value) \ + .globl symbol; \ +symbol = value + +#define PANIC(msg) \ + .set push; \ + .set reorder; \ + la a0,8f; \ + jal panic; \ +9: b 9b; \ + .set pop; \ + TEXT(msg) + +/* + * Print formated string + */ +#define PRINT(string) \ + .set push; \ + .set reorder; \ + la a0,8f; \ + jal printk; \ + .set pop; \ + TEXT(string) + +#define TEXT(msg) \ + .data; \ +8: .asciiz msg; \ + .previous; + +/* + * Build text tables + */ +#define TTABLE(string) \ + .text; \ + .word 1f; \ + .previous; \ + .data; \ +1: .asciz string; \ + .previous + +/* + * MIPS IV pref instruction. + * Use with .set noreorder only! + * + * MIPS IV implementations are free to treat this as a nop. The R5000 + * is one of them. So we should have an option not to use this instruction. + */ +#if (_MIPS_ISA == _MIPS_ISA_MIPS4) || (_MIPS_ISA == _MIPS_ISA_MIPS5) || \ + (_MIPS_ISA == _MIPS_ISA_MIPS32) || (_MIPS_ISA == _MIPS_ISA_MIPS64) +# define PREF(hint,addr) \ + pref hint,addr +# define PREFX(hint,addr) \ + prefx hint,addr +#else +# define PREF +# define PREFX +#endif + +/* + * MIPS ISA IV/V movn/movz instructions and equivalents for older CPUs. + */ +#if _MIPS_ISA == _MIPS_ISA_MIPS1 +# define MOVN(rd,rs,rt) \ + .set push; \ + .set reorder; \ + beqz rt,9f; \ + move rd,rs; \ + .set pop; \ +9: +# define MOVZ(rd,rs,rt) \ + .set push; \ + .set reorder; \ + bnez rt,9f; \ + move rd,rt; \ + .set pop; \ +9: +#endif /* _MIPS_ISA == _MIPS_ISA_MIPS1 */ +#if (_MIPS_ISA == _MIPS_ISA_MIPS2) || (_MIPS_ISA == _MIPS_ISA_MIPS3) +# define MOVN(rd,rs,rt) \ + .set push; \ + .set noreorder; \ + bnezl rt,9f; \ + move rd,rs; \ + .set pop; \ +9: +# define MOVZ(rd,rs,rt) \ + .set push; \ + .set noreorder; \ + beqzl rt,9f; \ + movz rd,rs; \ + .set pop; \ +9: +#endif /* (_MIPS_ISA == _MIPS_ISA_MIPS2) || (_MIPS_ISA == _MIPS_ISA_MIPS3) */ +#if (_MIPS_ISA == _MIPS_ISA_MIPS4) || (_MIPS_ISA == _MIPS_ISA_MIPS5) || \ + (_MIPS_ISA == _MIPS_ISA_MIPS32) || (_MIPS_ISA == _MIPS_ISA_MIPS64) +# define MOVN(rd,rs,rt) \ + movn rd,rs,rt +# define MOVZ(rd,rs,rt) \ + movz rd,rs,rt +#endif /* (_MIPS_ISA == _MIPS_ISA_MIPS4) || (_MIPS_ISA == _MIPS_ISA_MIPS5) */ + +/* + * Stack alignment + */ +#if (_MIPS_SIM == _MIPS_SIM_ABI64) || (_MIPS_SIM == _MIPS_SIM_NABI32) +# define ALSZ 15 +# define ALMASK ~15 +#else +# define ALSZ 7 +# define ALMASK ~7 +#endif + +/* + * Size of a register + */ +#if (_MIPS_SIM == _MIPS_SIM_ABI64) || (_MIPS_SIM == _MIPS_SIM_NABI32) +# define SZREG 8 +#else +# define SZREG 4 +#endif + +/* + * Use the following macros in assemblercode to load/store registers, + * pointers etc. + */ +#if (SZREG == 4) +# define REG_S sw +# define REG_L lw +#else +# define REG_S sd +# define REG_L ld +#endif + +/* + * How to add/sub/load/store/shift C int variables. + */ +#if (_MIPS_SZINT == 32) +# define INT_ADD add +# define INT_ADDI addi +# define INT_ADDU addu +# define INT_ADDIU addiu +# define INT_SUB add +# define INT_SUBI subi +# define INT_SUBU subu +# define INT_SUBIU subu +# define INT_L lw +# define INT_S sw +#endif + +#if (_MIPS_SZINT == 64) +# define INT_ADD dadd +# define INT_ADDI daddi +# define INT_ADDU daddu +# define INT_ADDIU daddiu +# define INT_SUB dadd +# define INT_SUBI dsubi +# define INT_SUBU dsubu +# define INT_SUBIU dsubu +# define INT_L ld +# define INT_S sd +#endif + +/* + * How to add/sub/load/store/shift C long variables. + */ +#if (_MIPS_SZLONG == 32) +# define LONG_ADD add +# define LONG_ADDI addi +# define LONG_ADDU addu +# define LONG_ADDIU addiu +# define LONG_SUB add +# define LONG_SUBI subi +# define LONG_SUBU subu +# define LONG_SUBIU subu +# define LONG_L lw +# define LONG_S sw +# define LONG_SLL sll +# define LONG_SLLV sllv +# define LONG_SRL srl +# define LONG_SRLV srlv +# define LONG_SRA sra +# define LONG_SRAV srav +#endif + +#if (_MIPS_SZLONG == 64) +# define LONG_ADD dadd +# define LONG_ADDI daddi +# define LONG_ADDU daddu +# define LONG_ADDIU daddiu +# define LONG_SUB dadd +# define LONG_SUBI dsubi +# define LONG_SUBU dsubu +# define LONG_SUBIU dsubu +# define LONG_L ld +# define LONG_S sd +# define LONG_SLL dsll +# define LONG_SLLV dsllv +# define LONG_SRL dsrl +# define LONG_SRLV dsrlv +# define LONG_SRA dsra +# define LONG_SRAV dsrav +#endif + +/* + * How to add/sub/load/store/shift pointers. + */ +#if (_MIPS_SIM == _MIPS_SIM_ABI32 && _MIPS_SZPTR == 32) +# define PTR_ADD add +# define PTR_ADDI addi +# define PTR_ADDU addu +# define PTR_ADDIU addiu +# define PTR_SUB add +# define PTR_SUBI subi +# define PTR_SUBU subu +# define PTR_SUBIU subu +# define PTR_L lw +# define PTR_LA la +# define PTR_S sw +# define PTR_SLL sll +# define PTR_SLLV sllv +# define PTR_SRL srl +# define PTR_SRLV srlv +# define PTR_SRA sra +# define PTR_SRAV srav + +# define PTR_SCALESHIFT 2 +#endif + +#if _MIPS_SIM == _MIPS_SIM_NABI32 +# define PTR_ADD add +# define PTR_ADDI addi +# define PTR_ADDU add /* no u */ +# define PTR_ADDIU addi /* no u */ +# define PTR_SUB add +# define PTR_SUBI subi +# define PTR_SUBU sub /* no u */ +# define PTR_SUBIU sub /* no u */ +# define PTR_L lw +# define PTR_LA la +# define PTR_S sw +# define PTR_SLL sll +# define PTR_SLLV sllv +# define PTR_SRL srl +# define PTR_SRLV srlv +# define PTR_SRA sra +# define PTR_SRAV srav + +# define PTR_SCALESHIFT 2 +#endif + +#if (_MIPS_SIM == _MIPS_SIM_ABI32 && _MIPS_SZPTR == 64 /* o64??? */) \ + || _MIPS_SIM == _MIPS_SIM_ABI64 +# define PTR_ADD dadd +# define PTR_ADDI daddi +# define PTR_ADDU daddu +# define PTR_ADDIU daddiu +# define PTR_SUB dadd +# define PTR_SUBI dsubi +# define PTR_SUBU dsubu +# define PTR_SUBIU dsubu +# define PTR_L ld +# define PTR_LA dla +# define PTR_S sd +# define PTR_SLL dsll +# define PTR_SLLV dsllv +# define PTR_SRL dsrl +# define PTR_SRLV dsrlv +# define PTR_SRA dsra +# define PTR_SRAV dsrav + +# define PTR_SCALESHIFT 3 +#endif + +/* + * Some cp0 registers were extended to 64bit for MIPS III. + */ +#if (_MIPS_ISA == _MIPS_ISA_MIPS1) || (_MIPS_ISA == _MIPS_ISA_MIPS2) || \ + (_MIPS_ISA == _MIPS_ISA_MIPS32) +# define MFC0 mfc0 +# define MTC0 mtc0 +#endif +#if (_MIPS_ISA == _MIPS_ISA_MIPS3) || (_MIPS_ISA == _MIPS_ISA_MIPS4) || \ + (_MIPS_ISA == _MIPS_ISA_MIPS5) || (_MIPS_ISA == _MIPS_ISA_MIPS64) +# define MFC0 dmfc0 +# define MTC0 dmtc0 +#endif + +/* The MIPS archtectures do not have a uniform memory model. Particular + platforms may provide additional guarantees - for instance, the R4000 + LL and SC instructions implicitly perform a SYNC, and the 4K promises + strong ordering. + + However, in the absence of those guarantees, we must assume weak ordering + and SYNC explicitly where necessary. + + Some obsolete MIPS processors may not support the SYNC instruction. This + applies to "true" MIPS I processors; most of the processors which compile + using MIPS I implement parts of MIPS II. */ + +#ifndef MIPS_SYNC +# define MIPS_SYNC sync +#endif + +#endif /* sys/asm.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/sys/cachectl.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/sys/cachectl.h new file mode 100644 index 00000000..a93e1fb6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/sys/cachectl.h @@ -0,0 +1,42 @@ +/* Copyright (C) 1995, 1996, 1997, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_CACHECTL_H +#define _SYS_CACHECTL_H 1 + +#include + +/* + * Get the kernel definition for the op bits. + */ +#include + +__BEGIN_DECLS + +#ifdef __USE_MISC +extern int cachectl (void *addr, __const int nbytes, __const int op) __THROW; +#endif +extern int __cachectl (void *addr, __const int nbytes, __const int op) __THROW; +#ifdef __USE_MISC +extern int cacheflush (void *addr, __const int nbytes, __const int op) __THROW; +#endif +extern int _flush_cache (char *addr, __const int nbytes, __const int op) __THROW; + +__END_DECLS + +#endif /* sys/cachectl.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/sys/fpregdef.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/sys/fpregdef.h new file mode 100644 index 00000000..37811527 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/sys/fpregdef.h @@ -0,0 +1,61 @@ +/* Copyright (C) 1991, 92, 94, 95, 96, 97, 98 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_FPREGDEF_H +#define _SYS_FPREGDEF_H + +/* + * These definitions only cover the R3000-ish 16/32 register model. + * But we're trying to be R3000 friendly anyway ... + */ +#define fv0 $f0 /* return value */ +#define fv0f $f1 +#define fv1 $f2 +#define fv1f $f3 +#define fa0 $f12 /* argument registers */ +#define fa0f $f13 +#define fa1 $f14 +#define fa1f $f15 +#define ft0 $f4 /* caller saved */ +#define ft0f $f5 +#define ft1 $f6 +#define ft1f $f7 +#define ft2 $f8 +#define ft2f $f9 +#define ft3 $f10 +#define ft3f $f11 +#define ft4 $f16 +#define ft4f $f17 +#define ft5 $f18 +#define ft5f $f19 +#define fs0 $f20 /* callee saved */ +#define fs0f $f21 +#define fs1 $f22 +#define fs1f $f23 +#define fs2 $f24 +#define fs2f $f25 +#define fs3 $f26 +#define fs3f $f27 +#define fs4 $f28 +#define fs4f $f29 +#define fs5 $f30 +#define fs5f $f31 + +#define fcr31 $31 /* FPU status register */ + +#endif /* sys/fpregdef.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/sys/procfs.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/sys/procfs.h new file mode 100644 index 00000000..a21652e1 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/sys/procfs.h @@ -0,0 +1,112 @@ +/* Copyright (C) 1996, 1997, 1999, 2000, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_PROCFS_H +#define _SYS_PROCFS_H 1 + +/* This is somehow modelled after the file of the same name on SysVr4 + systems. It provides a definition of the core file format for ELF + used on Linux. */ + +#include +#include +#include +#include + +/* ELF register definitions */ +#define ELF_NGREG 45 +#define ELF_NFPREG 33 + +typedef unsigned long elf_greg_t; +typedef elf_greg_t elf_gregset_t[ELF_NGREG]; + +typedef double elf_fpreg_t; +typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; + +__BEGIN_DECLS + +struct elf_siginfo + { + int si_signo; /* Signal number. */ + int si_code; /* Extra code. */ + int si_errno; /* Errno. */ + }; + + +/* Definitions to generate Intel SVR4-like core files. These mostly + have the same names as the SVR4 types with "elf_" tacked on the + front to prevent clashes with linux definitions, and the typedef + forms have been avoided. This is mostly like the SVR4 structure, + but more Linuxy, with things that Linux does not support and which + gdb doesn't really use excluded. Fields present but not used are + marked with "XXX". */ +struct elf_prstatus + { + struct elf_siginfo pr_info; /* Info associated with signal. */ + short int pr_cursig; /* Current signal. */ + unsigned long int pr_sigpend; /* Set of pending signals. */ + unsigned long int pr_sighold; /* Set of held signals. */ + __pid_t pr_pid; + __pid_t pr_ppid; + __pid_t pr_pgrp; + __pid_t pr_sid; + struct timeval pr_utime; /* User time. */ + struct timeval pr_stime; /* System time. */ + struct timeval pr_cutime; /* Cumulative user time. */ + struct timeval pr_cstime; /* Cumulative system time. */ + elf_gregset_t pr_reg; /* GP registers. */ + int pr_fpvalid; /* True if math copro being used. */ + }; + + +#define ELF_PRARGSZ (80) /* Number of chars for args */ + +struct elf_prpsinfo + { + char pr_state; /* Numeric process state. */ + char pr_sname; /* Char for pr_state. */ + char pr_zomb; /* Zombie. */ + char pr_nice; /* Nice val. */ + unsigned long int pr_flag; /* Flags. */ + long pr_uid; + long pr_gid; + int pr_pid, pr_ppid, pr_pgrp, pr_sid; + /* Lots missing */ + char pr_fname[16]; /* Filename of executable. */ + char pr_psargs[ELF_PRARGSZ]; /* Initial part of arg list. */ + }; + + +/* Addresses. */ +typedef void *psaddr_t; + +/* Register sets. Linux has different names. */ +typedef elf_gregset_t prgregset_t; +typedef elf_fpregset_t prfpregset_t; + +/* We don't have any differences between processes and threads, + therefore habe only ine PID type. */ +typedef __pid_t lwpid_t; + + +typedef struct elf_prstatus prstatus_t; +typedef struct elf_prpsinfo prpsinfo_t; + +__END_DECLS + +#endif /* sys/procfs.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/sys/regdef.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/sys/regdef.h new file mode 100644 index 00000000..2d94130a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/sys/regdef.h @@ -0,0 +1,82 @@ +/* Copyright (C) 1997, 1998, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ralf Baechle . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_REGDEF_H +#define _SYS_REGDEF_H + +#include + +/* + * Symbolic register names for 32 bit ABI + */ +#define zero $0 /* wired zero */ +#define AT $1 /* assembler temp - uppercase because of ".set at" */ +#define v0 $2 /* return value */ +#define v1 $3 +#define a0 $4 /* argument registers */ +#define a1 $5 +#define a2 $6 +#define a3 $7 +#if _MIPS_SIM != _MIPS_SIM_ABI32 +#define a4 $8 +#define a5 $9 +#define a6 $10 +#define a7 $11 +#define t0 $12 +#define t1 $13 +#define t2 $14 +#define t3 $15 +#define ta0 a4 +#define ta1 a5 +#define ta2 a6 +#define ta3 a7 +#else /* if _MIPS_SIM == _MIPS_SIM_ABI32 */ +#define t0 $8 /* caller saved */ +#define t1 $9 +#define t2 $10 +#define t3 $11 +#define t4 $12 +#define t5 $13 +#define t6 $14 +#define t7 $15 +#define ta0 t4 +#define ta1 t5 +#define ta2 t6 +#define ta3 t7 +#endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */ +#define s0 $16 /* callee saved */ +#define s1 $17 +#define s2 $18 +#define s3 $19 +#define s4 $20 +#define s5 $21 +#define s6 $22 +#define s7 $23 +#define t8 $24 /* caller saved */ +#define t9 $25 +#define jp $25 /* PIC jump register */ +#define k0 $26 /* kernel scratch */ +#define k1 $27 +#define gp $28 /* global pointer */ +#define sp $29 /* stack pointer */ +#define fp $30 /* frame pointer */ +#define s8 $30 /* same like fp! */ +#define ra $31 /* return address */ + +#endif /* _SYS_REGDEF_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/sys/sysmips.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/sys/sysmips.h new file mode 100644 index 00000000..6a63dc2b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/sys/sysmips.h @@ -0,0 +1,44 @@ +/* Copyright (C) 1991, 92, 94, 95, 96, 97, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_SYSMIPS_H +#define _SYS_SYSMIPS_H 1 + +#include + +/* + * Commands for the sysmips(2) call + * + * sysmips(2) is deprecated - though some existing software uses it. + * We only support the following commands. Sysmips exists for compatibility + * purposes only so new software should avoid it. + */ +#define SETNAME 1 /* set hostname */ +#define FLUSH_CACHE 3 /* writeback and invalidate caches */ +#define MIPS_FIXADE 7 /* control address error fixing */ +#define MIPS_RDNVRAM 10 /* read NVRAM */ +#define MIPS_ATOMIC_SET 2001 /* atomically set variable */ + +__BEGIN_DECLS + +extern int sysmips (__const int cmd, __const long arg1, + __const int arg2, __const int arg3) __THROW; + +__END_DECLS + +#endif /* sys/sysmips.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/sys/tas.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/sys/tas.h new file mode 100644 index 00000000..1183b867 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/sys/tas.h @@ -0,0 +1,67 @@ +/* Copyright (C) 2000, 2002, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Maciej W. Rozycki , 2000. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_TAS_H +#define _SYS_TAS_H 1 + +#include +#include + +__BEGIN_DECLS + +extern int _test_and_set (int *p, int v) __THROW; + +#ifdef __USE_EXTERN_INLINES + +# ifndef _EXTERN_INLINE +# define _EXTERN_INLINE extern __inline +# endif + +_EXTERN_INLINE int +__NTH (_test_and_set (int *p, int v)) +{ + int r, t; + + __asm__ __volatile__ + ("/* Inline test and set */\n" + "1:\n\t" + ".set push\n\t" +#if _MIPS_SIM == _ABIO32 + ".set mips2\n\t" +#endif + "ll %0,%3\n\t" + "move %1,%4\n\t" + "beq %0,%4,2f\n\t" + "sc %1,%2\n\t" + ".set pop\n\t" + "beqz %1,1b\n" + "2:\n\t" + "/* End test and set */" + : "=&r" (r), "=&r" (t), "=m" (*p) + : "m" (*p), "r" (v) + : "memory"); + + return r; +} + +#endif /* __USE_EXTERN_INLINES */ + +__END_DECLS + +#endif /* sys/tas.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/sys/ucontext.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/sys/ucontext.h new file mode 100644 index 00000000..ac496f3d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/sys/ucontext.h @@ -0,0 +1,117 @@ +/* Copyright (C) 1997, 1998, 2000, 2003, 2004, 2006 Free Software + Foundation, Inc. This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Don't rely on this, the interface is currently messed up and may need to + be broken to be fixed. */ +#ifndef _SYS_UCONTEXT_H +#define _SYS_UCONTEXT_H 1 + +#include +#include +#include + +/* We need the signal context definitions even if they are not used + included in . */ +#include + +/* Type for general register. Even in o32 we assume 64-bit registers, + like the kernel. */ +__extension__ typedef unsigned long long int greg_t; + +/* Number of general registers. */ +#define NGREG 32 +#define NFPREG 32 + +/* Container for all general registers. */ +typedef greg_t gregset_t[NGREG]; + +/* Container for all FPU registers. */ +typedef struct fpregset { + union { + double fp_dregs[NFPREG]; + struct { + float _fp_fregs; + unsigned int _fp_pad; + } fp_fregs[NFPREG]; + } fp_r; +} fpregset_t; + + +/* Context to describe whole processor state. */ +#if _MIPS_SIM == _ABIO32 +/* Earlier versions of glibc for mips had an entirely different + definition of mcontext_t, that didn't even resemble the + corresponding kernel data structure. Since all legitimate uses of + ucontext_t in glibc mustn't have accessed anything beyond + uc_mcontext and, even then, taking a pointer to it, casting it to + sigcontext_t, and accessing it as such, which is what it has always + been, this can still be rectified. Fortunately, makecontext, + [gs]etcontext et all have never been implemented. */ +typedef struct + { + unsigned int regmask; + unsigned int status; + greg_t pc; + gregset_t gregs; + fpregset_t fpregs; + unsigned int fp_owned; + unsigned int fpc_csr; + unsigned int fpc_eir; + unsigned int used_math; + unsigned int dsp; + greg_t mdhi; + greg_t mdlo; + unsigned long hi1; + unsigned long lo1; + unsigned long hi2; + unsigned long lo2; + unsigned long hi3; + unsigned long lo3; + } mcontext_t; +#else +typedef struct + { + gregset_t gregs; + fpregset_t fpregs; + greg_t mdhi; + greg_t hi1; + greg_t hi2; + greg_t hi3; + greg_t mdlo; + greg_t lo1; + greg_t lo2; + greg_t lo3; + greg_t pc; + unsigned int fpc_csr; + unsigned int used_math; + unsigned int dsp; + unsigned int reserved; + } mcontext_t; +#endif + +/* Userlevel context. */ +typedef struct ucontext + { + unsigned long int uc_flags; + struct ucontext *uc_link; + stack_t uc_stack; + mcontext_t uc_mcontext; + __sigset_t uc_sigmask; + } ucontext_t; + +#endif /* sys/ucontext.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/sys/user.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/sys/user.h new file mode 100644 index 00000000..5d880943 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/sys/user.h @@ -0,0 +1,217 @@ +/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_USER_H +#define _SYS_USER_H 1 + +#include + +/* The whole purpose of this file is for GDB and GDB only. Don't read + too much into it. Don't use it for anything other than GDB unless + you know what you are doing. */ + +/* #include */ +/* Instead of including the kernel header, that will vary depending on + whether the 32- or the 64-bit kernel is installed, we paste its + contents here. Note that the fact that the file is inline here, + instead of included separately, doesn't change in any way the + licensing status of a program that includes user.h. Since this is + for gdb alone, and gdb is GPLed, no surprises here. */ +#if _MIPS_SIM == _ABIO32 +/* + * Various register offset definitions for debuggers, core file + * examiners and whatnot. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1995, 1999 by Ralf Baechle + */ +#ifndef __ASM_MIPS_REG_H +#define __ASM_MIPS_REG_H + +/* + * This defines/structures correspond to the register layout on stack - + * if the order here is changed, it needs to be updated in + * include/asm-mips/stackframe.h + */ +#define EF_REG0 6 +#define EF_REG1 7 +#define EF_REG2 8 +#define EF_REG3 9 +#define EF_REG4 10 +#define EF_REG5 11 +#define EF_REG6 12 +#define EF_REG7 13 +#define EF_REG8 14 +#define EF_REG9 15 +#define EF_REG10 16 +#define EF_REG11 17 +#define EF_REG12 18 +#define EF_REG13 19 +#define EF_REG14 20 +#define EF_REG15 21 +#define EF_REG16 22 +#define EF_REG17 23 +#define EF_REG18 24 +#define EF_REG19 25 +#define EF_REG20 26 +#define EF_REG21 27 +#define EF_REG22 28 +#define EF_REG23 29 +#define EF_REG24 30 +#define EF_REG25 31 +/* + * k0/k1 unsaved + */ +#define EF_REG28 34 +#define EF_REG29 35 +#define EF_REG30 36 +#define EF_REG31 37 + +/* + * Saved special registers + */ +#define EF_LO 38 +#define EF_HI 39 + +#define EF_CP0_EPC 40 +#define EF_CP0_BADVADDR 41 +#define EF_CP0_STATUS 42 +#define EF_CP0_CAUSE 43 + +#define EF_SIZE 180 /* size in bytes */ + +#endif /* __ASM_MIPS_REG_H */ + +#else /* _MIPS_SIM != _ABIO32 */ + +/* + * Various register offset definitions for debuggers, core file + * examiners and whatnot. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1995, 1999 Ralf Baechle + * Copyright (C) 1995, 1999 Silicon Graphics + */ +#ifndef _ASM_REG_H +#define _ASM_REG_H + +/* + * This defines/structures correspond to the register layout on stack - + * if the order here is changed, it needs to be updated in + * include/asm-mips/stackframe.h + */ +#define EF_REG0 0 +#define EF_REG1 1 +#define EF_REG2 2 +#define EF_REG3 3 +#define EF_REG4 4 +#define EF_REG5 5 +#define EF_REG6 6 +#define EF_REG7 7 +#define EF_REG8 8 +#define EF_REG9 9 +#define EF_REG10 10 +#define EF_REG11 11 +#define EF_REG12 12 +#define EF_REG13 13 +#define EF_REG14 14 +#define EF_REG15 15 +#define EF_REG16 16 +#define EF_REG17 17 +#define EF_REG18 18 +#define EF_REG19 19 +#define EF_REG20 20 +#define EF_REG21 21 +#define EF_REG22 22 +#define EF_REG23 23 +#define EF_REG24 24 +#define EF_REG25 25 +/* + * k0/k1 unsaved + */ +#define EF_REG28 28 +#define EF_REG29 29 +#define EF_REG30 30 +#define EF_REG31 31 + +/* + * Saved special registers + */ +#define EF_LO 32 +#define EF_HI 33 + +#define EF_CP0_EPC 34 +#define EF_CP0_BADVADDR 35 +#define EF_CP0_STATUS 36 +#define EF_CP0_CAUSE 37 + +#define EF_SIZE 304 /* size in bytes */ + +#endif /* _ASM_REG_H */ + +#endif /* _MIPS_SIM != _ABIO32 */ + +#if _MIPS_SIM == _ABIO32 + +struct user +{ + unsigned long regs[EF_SIZE/4+64]; /* integer and fp regs */ + size_t u_tsize; /* text size (pages) */ + size_t u_dsize; /* data size (pages) */ + size_t u_ssize; /* stack size (pages) */ + unsigned long start_code; /* text starting address */ + unsigned long start_data; /* data starting address */ + unsigned long start_stack; /* stack starting address */ + long int signal; /* signal causing core dump */ + void* u_ar0; /* help gdb find registers */ + unsigned long magic; /* identifies a core file */ + char u_comm[32]; /* user command name */ +}; + +#else + +struct user { + __extension__ unsigned long regs[EF_SIZE/8+64]; /* integer and fp regs */ + __extension__ unsigned long u_tsize; /* text size (pages) */ + __extension__ unsigned long u_dsize; /* data size (pages) */ + __extension__ unsigned long u_ssize; /* stack size (pages) */ + __extension__ unsigned long long start_code; /* text starting address */ + __extension__ unsigned long long start_data; /* data starting address */ + __extension__ unsigned long long start_stack; /* stack starting address */ + __extension__ long long signal; /* signal causing core dump */ + __extension__ unsigned long long u_ar0; /* help gdb find registers */ + __extension__ unsigned long long magic; /* identifies a core file */ + char u_comm[32]; /* user command name */ +}; + +#endif + +#include +#define NBPG PAGE_SIZE +#define UPAGES 1 +#define HOST_TEXT_START_ADDR (u.start_code) +#define HOST_DATA_START_ADDR (u.start_data) +#define HOST_STACK_END_ADDR (u.start_stack + u.u_ssize * NBPG) + +#endif /* _SYS_USER_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/syscall.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/syscall.S new file mode 100644 index 00000000..acb91011 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/syscall.S @@ -0,0 +1,80 @@ +/* Copyright (C) 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +#ifdef __PIC__ + .option pic2 +#endif +.text +.align 2 +.globl syscall +.type syscall,@function +.ent syscall +syscall: +#ifdef __PIC__ + SETUP_GP +#endif + move v0, a0 /* Load system call number from first arg. */ + move a0, a1 /* Move the next three args up a register. */ + move a1, a2 + move a2, a3 + /* Load the remaining possible args (up to 7) from the stack. */ +#ifdef __mips64 + move a3, a4 + move a4, a5 + move a5, a6 + move a6, a7 + daddiu sp,sp,-16 + sd v0,0*8(sp) + ld v0,0*8(sp) /* for system call restarts */ +#else + lw a3,4*4(sp) + lw t0,5*4(sp) + lw t1,6*4(sp) + lw t2,7*4(sp) + addiu sp,sp,-32 + sw t0,4*4(sp) + sw t1,5*4(sp) + sw t2,6*4(sp) + sw v0,7*4(sp) + lw v0,7*4(sp) /* for system call restarts */ +#endif + syscall /* Do the system call. */ +#ifdef __mips64 + daddiu sp,sp,16 +#else + addiu sp,sp,32 +#endif + bnez a3, 1f + j ra /* Return to caller. */ +1: + move a0,v0 /* Pass return val to C function. */ + +#ifdef __PIC__ + SETUP_GP64(v0, syscall) + PTR_LA t9, __syscall_error + RESTORE_GP64 + jr t9 +#else + j __syscall_error +#endif +.end syscall +.size syscall,.-syscall diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/syscall_error.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/syscall_error.S new file mode 100644 index 00000000..51a8efa5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/syscall_error.S @@ -0,0 +1,84 @@ +/* Copyright (C) 1992, 1993, 1994, 1997, 1998, 1999, 2000, 2002, 2003 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Brendan Kehoe (brendan@zen.org). + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +#ifdef _LIBC_REENTRANT + +LOCALSZ= 3 +FRAMESZ= (((NARGSAVE+LOCALSZ)*SZREG)+ALSZ)&ALMASK +RAOFF= FRAMESZ-(1*SZREG) +GPOFF= FRAMESZ-(2*SZREG) +V0OFF= FRAMESZ-(3*SZREG) + +ENTRY(__syscall_error) +#ifdef __PIC__ + .set noat + SETUP_GPX (AT) + .set at +#endif + PTR_SUBU sp, FRAMESZ + .set noat + SETUP_GPX64(GPOFF,AT) + .set at +#ifdef __PIC__ + SAVE_GP(GPOFF) +#endif + REG_S v0, V0OFF(sp) + REG_S ra, RAOFF(sp) + + /* Find our per-thread errno address */ + jal __errno_location + + /* Store the error value. */ + REG_L t0, V0OFF(sp) + sw t0, 0(v0) + + /* And just kick back a -1. */ + REG_L ra, RAOFF(sp) + RESTORE_GP64 + PTR_ADDU sp, FRAMESZ + li v0, -1 + j ra + END(__syscall_error) + +#else /* __LIBC_REENTRANT */ + + +ENTRY(__syscall_error) +#ifdef __PIC__ + .set noat + SETUP_GPX (AT) + .set at +#endif + SETUP_GPX64 (t9, AT) + + /* Store it in errno... */ + sw v0, errno + + /* And just kick back a -1. */ + li v0, -1 + + RESTORE_GP64 + j ra + END(__syscall_error) +#endif /* _LIBC_REENTRANT*/ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/sysdep.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/sysdep.h new file mode 100644 index 00000000..9de4f1ac --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/sysdep.h @@ -0,0 +1,393 @@ +/* Copyright (C) 1992, 1995, 1997, 1999, 2000, 2002, 2003, 2004 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Brendan Kehoe (brendan@zen.org). + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _LINUX_MIPS_SYSDEP_H +#define _LINUX_MIPS_SYSDEP_H 1 + +#include +#include + +/* For Linux we can use the system call table in the header file + /usr/include/asm/unistd.h + of the kernel. But these symbols do not follow the SYS_* syntax + so we have to redefine the `SYS_ify' macro here. */ + +#undef SYS_ify +#ifdef __STDC__ +# define SYS_ify(syscall_name) __NR_##syscall_name +#else +# define SYS_ify(syscall_name) __NR_/**/syscall_name +#endif + +#ifdef __ASSEMBLER__ + +#include + +#define ENTRY(name) \ + .globl name; \ + .align 2; \ + .ent name,0; \ + name##: + +#undef END +#define END(function) \ + .end function; \ + .size function,.-function + +#define ret j ra ; nop + +#undef PSEUDO_END +#define PSEUDO_END(sym) .end sym; .size sym,.-sym + +#define PSEUDO_NOERRNO(name, syscall_name, args) \ + .align 2; \ + ENTRY(name) \ + .set noreorder; \ + li v0, SYS_ify(syscall_name); \ + syscall + +#undef PSEUDO_END_NOERRNO +#define PSEUDO_END_NOERRNO(sym) .end sym; .size sym,.-sym + +#define ret_NOERRNO ret + +#define PSEUDO_ERRVAL(name, syscall_name, args) \ + .align 2; \ + ENTRY(name) \ + .set noreorder; \ + li v0, SYS_ify(syscall_name); \ + syscall + +#undef PSEUDO_END_ERRVAL +#define PSEUDO_END_ERRVAL(sym) .end sym; .size sym,.-sym + +#define ret_ERRVAL ret + +#define r0 v0 +#define r1 v1 +/* The mips move insn is d,s. */ +#define MOVE(x,y) move y , x + +#if _MIPS_SIM == _ABIO32 +# define L(label) $L ## label +#else +# define L(label) .L ## label +#endif + +/* Note that while it's better structurally, going back to call __syscall_error + can make things confusing if you're debugging---it looks like it's jumping + backwards into the previous fn. */ + +#ifdef __PIC__ +#define PSEUDO(name, syscall_name, args) \ + .align 2; \ + 99: move a0, v0; \ + la t9,__syscall_error; \ + jr t9; \ + ENTRY(name) \ + .set noreorder; \ + .cpload t9; \ + li v0, SYS_ify(syscall_name); \ + syscall; \ + .set reorder; \ + bne a3, zero, 99b; \ +L(syse1): +#else +#define PSEUDO(name, syscall_name, args) \ + .set noreorder; \ + .align 2; \ + 99: move a0, v0; \ + j __syscall_error; \ + nop; \ + ENTRY(name) \ + .set noreorder; \ + li v0, SYS_ify(syscall_name); \ + syscall; \ + .set reorder; \ + bne a3, zero, 99b; \ +L(syse1): +#endif + +/* We don't want the label for the error handler to be visible in the symbol + table when we define it here. */ +#ifdef __PIC__ +# define SYSCALL_ERROR_LABEL 99b +#endif + +#else /* ! __ASSEMBLER__ */ + +/* Define a macro which expands into the inline wrapper code for a system + call. */ +#undef INLINE_SYSCALL +#define INLINE_SYSCALL(name, nr, args...) \ + ({ INTERNAL_SYSCALL_DECL(err); \ + long result_var = INTERNAL_SYSCALL (name, err, nr, args); \ + if ( INTERNAL_SYSCALL_ERROR_P (result_var, err) ) \ + { \ + __set_errno (INTERNAL_SYSCALL_ERRNO (result_var, err)); \ + result_var = -1L; \ + } \ + result_var; }) + +#undef INTERNAL_SYSCALL_DECL +#define INTERNAL_SYSCALL_DECL(err) long err + +#undef INTERNAL_SYSCALL_ERROR_P +#define INTERNAL_SYSCALL_ERROR_P(val, err) ((long) (err)) + +#undef INTERNAL_SYSCALL_ERRNO +#define INTERNAL_SYSCALL_ERRNO(val, err) (val) + +#undef INTERNAL_SYSCALL +#define INTERNAL_SYSCALL(name, err, nr, args...) \ + internal_syscall##nr (, "li\t$2, %2\t\t\t# " #name "\n\t", \ + "i" (SYS_ify (name)), err, args) + +#undef INTERNAL_SYSCALL_NCS +#define INTERNAL_SYSCALL_NCS(number, err, nr, args...) \ + internal_syscall##nr (= number, , "r" (__v0), err, args) +#undef internal_syscall0 +#define internal_syscall0(ncs_init, cs_init, input, err, dummy...) \ +({ \ + long _sys_result; \ + \ + { \ + register long __v0 __asm__("$2") ncs_init; \ + register long __a3 __asm__("$7"); \ + __asm__ __volatile__ ( \ + ".set\tnoreorder\n\t" \ + cs_init \ + "syscall\n\t" \ + ".set reorder" \ + : "=r" (__v0), "=r" (__a3) \ + : input \ + : __SYSCALL_CLOBBERS); \ + err = __a3; \ + _sys_result = __v0; \ + } \ + _sys_result; \ +}) + +#undef internal_syscall1 +#define internal_syscall1(ncs_init, cs_init, input, err, arg1) \ +({ \ + long _sys_result; \ + \ + { \ + register long __v0 __asm__("$2") ncs_init; \ + register long __a0 __asm__("$4") = (long) arg1; \ + register long __a3 __asm__("$7"); \ + __asm__ __volatile__ ( \ + ".set\tnoreorder\n\t" \ + cs_init \ + "syscall\n\t" \ + ".set reorder" \ + : "=r" (__v0), "=r" (__a3) \ + : input, "r" (__a0) \ + : __SYSCALL_CLOBBERS); \ + err = __a3; \ + _sys_result = __v0; \ + } \ + _sys_result; \ +}) + +#undef internal_syscall2 +#define internal_syscall2(ncs_init, cs_init, input, err, arg1, arg2) \ +({ \ + long _sys_result; \ + \ + { \ + register long __v0 __asm__("$2") ncs_init; \ + register long __a0 __asm__("$4") = (long) arg1; \ + register long __a1 __asm__("$5") = (long) arg2; \ + register long __a3 __asm__("$7"); \ + __asm__ __volatile__ ( \ + ".set\tnoreorder\n\t" \ + cs_init \ + "syscall\n\t" \ + ".set\treorder" \ + : "=r" (__v0), "=r" (__a3) \ + : input, "r" (__a0), "r" (__a1) \ + : __SYSCALL_CLOBBERS); \ + err = __a3; \ + _sys_result = __v0; \ + } \ + _sys_result; \ +}) + +#undef internal_syscall3 +#define internal_syscall3(ncs_init, cs_init, input, err, arg1, arg2, arg3)\ +({ \ + long _sys_result; \ + \ + { \ + register long __v0 __asm__("$2") ncs_init; \ + register long __a0 __asm__("$4") = (long) arg1; \ + register long __a1 __asm__("$5") = (long) arg2; \ + register long __a2 __asm__("$6") = (long) arg3; \ + register long __a3 __asm__("$7"); \ + __asm__ __volatile__ ( \ + ".set\tnoreorder\n\t" \ + cs_init \ + "syscall\n\t" \ + ".set\treorder" \ + : "=r" (__v0), "=r" (__a3) \ + : input, "r" (__a0), "r" (__a1), "r" (__a2) \ + : __SYSCALL_CLOBBERS); \ + err = __a3; \ + _sys_result = __v0; \ + } \ + _sys_result; \ +}) + +#undef internal_syscall4 +#define internal_syscall4(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4)\ +({ \ + long _sys_result; \ + \ + { \ + register long __v0 __asm__("$2") ncs_init; \ + register long __a0 __asm__("$4") = (long) arg1; \ + register long __a1 __asm__("$5") = (long) arg2; \ + register long __a2 __asm__("$6") = (long) arg3; \ + register long __a3 __asm__("$7") = (long) arg4; \ + __asm__ __volatile__ ( \ + ".set\tnoreorder\n\t" \ + cs_init \ + "syscall\n\t" \ + ".set\treorder" \ + : "=r" (__v0), "+r" (__a3) \ + : input, "r" (__a0), "r" (__a1), "r" (__a2) \ + : __SYSCALL_CLOBBERS); \ + err = __a3; \ + _sys_result = __v0; \ + } \ + _sys_result; \ +}) + +/* We need to use a frame pointer for the functions in which we + adjust $sp around the syscall, or debug information and unwind + information will be $sp relative and thus wrong during the syscall. As + of GCC 3.4.3, this is sufficient. */ +#define FORCE_FRAME_POINTER alloca (4) + +#undef internal_syscall5 +#define internal_syscall5(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4, arg5)\ +({ \ + long _sys_result; \ + \ + FORCE_FRAME_POINTER; \ + { \ + register long __v0 __asm__("$2") ncs_init; \ + register long __a0 __asm__("$4") = (long) arg1; \ + register long __a1 __asm__("$5") = (long) arg2; \ + register long __a2 __asm__("$6") = (long) arg3; \ + register long __a3 __asm__("$7") = (long) arg4; \ + __asm__ __volatile__ ( \ + ".set\tnoreorder\n\t" \ + "subu\t$29, 32\n\t" \ + "sw\t%6, 16($29)\n\t" \ + cs_init \ + "syscall\n\t" \ + "addiu\t$29, 32\n\t" \ + ".set\treorder" \ + : "=r" (__v0), "+r" (__a3) \ + : input, "r" (__a0), "r" (__a1), "r" (__a2), \ + "r" ((long)arg5) \ + : __SYSCALL_CLOBBERS); \ + err = __a3; \ + _sys_result = __v0; \ + } \ + _sys_result; \ +}) + +#undef internal_syscall6 +#define internal_syscall6(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4, arg5, arg6)\ +({ \ + long _sys_result; \ + \ + FORCE_FRAME_POINTER; \ + { \ + register long __v0 __asm__("$2") ncs_init; \ + register long __a0 __asm__("$4") = (long) arg1; \ + register long __a1 __asm__("$5") = (long) arg2; \ + register long __a2 __asm__("$6") = (long) arg3; \ + register long __a3 __asm__("$7") = (long) arg4; \ + __asm__ __volatile__ ( \ + ".set\tnoreorder\n\t" \ + "subu\t$29, 32\n\t" \ + "sw\t%6, 16($29)\n\t" \ + "sw\t%7, 20($29)\n\t" \ + cs_init \ + "syscall\n\t" \ + "addiu\t$29, 32\n\t" \ + ".set\treorder" \ + : "=r" (__v0), "+r" (__a3) \ + : input, "r" (__a0), "r" (__a1), "r" (__a2), \ + "r" ((long)arg5), "r" ((long)arg6) \ + : __SYSCALL_CLOBBERS); \ + err = __a3; \ + _sys_result = __v0; \ + } \ + _sys_result; \ +}) + +#undef internal_syscall7 +#define internal_syscall7(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4, arg5, arg6, arg7)\ +({ \ + long _sys_result; \ + \ + FORCE_FRAME_POINTER; \ + { \ + register long __v0 __asm__("$2") ncs_init; \ + register long __a0 __asm__("$4") = (long) arg1; \ + register long __a1 __asm__("$5") = (long) arg2; \ + register long __a2 __asm__("$6") = (long) arg3; \ + register long __a3 __asm__("$7") = (long) arg4; \ + __asm__ __volatile__ ( \ + ".set\tnoreorder\n\t" \ + "subu\t$29, 32\n\t" \ + "sw\t%6, 16($29)\n\t" \ + "sw\t%7, 20($29)\n\t" \ + "sw\t%8, 24($29)\n\t" \ + cs_init \ + "syscall\n\t" \ + "addiu\t$29, 32\n\t" \ + ".set\treorder" \ + : "=r" (__v0), "+r" (__a3) \ + : input, "r" (__a0), "r" (__a1), "r" (__a2), \ + "r" ((long)arg5), "r" ((long)arg6), "r" ((long)arg7) \ + : __SYSCALL_CLOBBERS); \ + err = __a3; \ + _sys_result = __v0; \ + } \ + _sys_result; \ +}) + +#undef __SYSCALL_CLOBBERS +#define __SYSCALL_CLOBBERS "$1", "$3", "$8", "$9", "$10", "$11", "$12", "$13", \ + "$14", "$15", "$24", "$25", "memory" + +/* Pointer mangling is not yet supported for MIPS. */ +#define PTR_MANGLE(var) (void) (var) +#define PTR_DEMANGLE(var) (void) (var) + +#endif /* __ASSEMBLER__ */ +#endif /* _LINUX_MIPS_SYSDEP_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/sysmips.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/sysmips.c new file mode 100644 index 00000000..1384782b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/sysmips.c @@ -0,0 +1,7 @@ +#include +#include +#include + +#ifdef __NR_sysmips +_syscall4(int, sysmips, const int, cmd, const long, arg1, const int, arg2, const int, arg3) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/vfork.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/vfork.S new file mode 100644 index 00000000..b3074475 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/mips/vfork.S @@ -0,0 +1,100 @@ +/* Copyright (C) 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* vfork() is just a special case of clone(). */ + +#include +#include + +#ifndef SAVE_PID +#define SAVE_PID +#endif + +#ifndef RESTORE_PID +#define RESTORE_PID +#endif + +#ifdef __NR_fork + +/* int vfork() */ + + .text +LOCALSZ= 1 +FRAMESZ= (((NARGSAVE+LOCALSZ)*SZREG)+ALSZ)&ALMASK +GPOFF= FRAMESZ-(1*SZREG) +NESTED(__vfork,FRAMESZ,sp) +#ifdef __PIC__ + SETUP_GP +#endif + PTR_SUBU sp, FRAMESZ + SETUP_GP64 (a5, __vfork) +#ifdef __PIC__ + SAVE_GP (GPOFF) +#endif +#ifdef PROF +# if (_MIPS_SIM != _ABIO32) + PTR_S a5, GPOFF(sp) +# endif + .set noat + move $1, ra +# if (_MIPS_SIM == _ABIO32) + subu sp,sp,8 +# endif + jal _mcount + .set at +# if (_MIPS_SIM != _ABIO32) + PTR_L a5, GPOFF(sp) +# endif +#endif + + PTR_ADDU sp, FRAMESZ + + SAVE_PID + + li a0, 0x4112 /* CLONE_VM | CLONE_VFORK | SIGCHLD */ + move a1, sp + + /* Do the system call */ + li v0,__NR_clone + syscall + + RESTORE_PID + + bnez a3,L(error) + + /* Successful return from the parent or child. */ + RESTORE_GP64 + j ra + nop + + /* Something bad happened -- no child created. */ +L(error): +#ifdef __PIC__ + PTR_LA t9, __syscall_error + RESTORE_GP64 + jr t9 +#else + RESTORE_GP64 + j __syscall_error +#endif + END(__vfork) + +weak_alias(__vfork,vfork) +libc_hidden_weak(vfork) + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/Makefile new file mode 100644 index 00000000..3970f626 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2006 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../../ +top_builddir=../../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.arch +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/Makefile.arch b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/Makefile.arch new file mode 100644 index 00000000..6a2c3235 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/Makefile.arch @@ -0,0 +1,12 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2006 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +CSRC := brk.c crtbegin.c crtend.c + +SSRC := \ + __longjmp.S bsd-_setjmp.S bsd-setjmp.S setjmp.S \ + clone.S vfork.S diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/NM_Macros.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/NM_Macros.S new file mode 100644 index 00000000..da613659 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/NM_Macros.S @@ -0,0 +1,473 @@ + +;------------------------------ +; Macros I: Faux Instructions +; +; The following "faux instructions" are +; implemented here as macros: +; +; MOVIP register,constant MOVI with optional PFX & MOVHI, or BGEN +; ADDIP register,constant PFX and ADDI with optional PFX +; SUBIP register,constant PFX and SUBI with optional PFX +; CMPIP register,constant PFX and CMPI with optional PFX +; +; MOVI16 register,constant PFX and MOVI +; MOVI32 register,constant PFX, MOVI, PFX, and MOVHI +; MOVIA register,constant PFX and MOVHI on Nios32, and PFX and MOVI +; +; ANDIP register,constant PFX and ANDI +; ANDNIP register,constant PFX and ANDN +; ORIP register,constant PFX and ORI +; XORIP register,constant PFX and XORI +; +; _BSR address MOVIP address to %g7, and CALL +; _BR address MOVIP address to %g7, and JMP +; +; BEQ address SKPS cc_nz and BR, has delay slot +; BNE address SKPS cc_z and BR, has delay slot +; BLE address SKPS cc_gt and BR, has delay slot +; BLT address SKPS cc_ge and BR, has delay slot +; RESTRET RESTORE and JMP %i7 +; +;------------------------------- +; Macros II: Printing +; +; These macros are guaranteed *not* +; to have branch delay slot after them. +; +; NM_PrintChar char +; NM_Print "string" +; NM_PrintLn "string" Follows it with a carriage return +; NM_PrintRegister reg For debugging, prints register name & value +; +;------------------------------- +; Macros III: Inline Debugging +; +; These macros print various information +; using large sections of expanded inline code. +; They each use either few or no registers. +; Thus, they may be safely used in interrupt handlers. +; +; NM_D_TxChar char print char to UART, affects no registers +; NM_D_TxRegister char,char,register prints the two characters, and the hex register value + +; -------------------------------------- + + + .macro _pfx_op OP,reg,val,pForce=0 + .if (\pForce) || ((\val) > (31)) || ((\val) < (0)) + PFX %hi(\val) + .endif + \OP \reg,%lo(\val) + .endm + + .macro _bgen reg,val,bit + .if ((\val)==(1<<\bit)) + BGEN \reg,\bit + .equ _bgenBit,1 + .endif + .endm + + ;------------------------ + ; MOVIP %reg,32-bit-value + .macro MOVIP reg,val + ; Methodically test every BGEN possibility... + .equ _bgenBit,0 +.if 1 + _bgen \reg,\val,0 + _bgen \reg,\val,1 + _bgen \reg,\val,2 + _bgen \reg,\val,3 + _bgen \reg,\val,4 + _bgen \reg,\val,5 + _bgen \reg,\val,6 + _bgen \reg,\val,7 + _bgen \reg,\val,8 + _bgen \reg,\val,9 + _bgen \reg,\val,10 + _bgen \reg,\val,11 + _bgen \reg,\val,12 + _bgen \reg,\val,13 + _bgen \reg,\val,14 + _bgen \reg,\val,15 + _bgen \reg,\val,16 + _bgen \reg,\val,17 + _bgen \reg,\val,18 + _bgen \reg,\val,19 + _bgen \reg,\val,20 + _bgen \reg,\val,21 + _bgen \reg,\val,22 + _bgen \reg,\val,23 + _bgen \reg,\val,24 + _bgen \reg,\val,25 + _bgen \reg,\val,26 + _bgen \reg,\val,27 + _bgen \reg,\val,28 + _bgen \reg,\val,29 + _bgen \reg,\val,30 + _bgen \reg,\val,31 + + ; If no bgen fit... +.endif + .if !_bgenBit + .if ((\val) & 0xFFE0) + PFX %hi(\val) + .endif + MOVI \reg,%lo(\val) + .if __nios32__ + .if ((\val) & 0xffff0000) + .if ((\val) & 0xFFE00000) + PFX %xhi(\val) + .endif + MOVHI \reg,%xlo(\val) + .endif + .endif + .endif + + .endm + + ; ADDIP %reg,16-bit-value + .macro ADDIP reg,val + _pfx_op ADDI,\reg,\val + .endm + + ; SUBIP %reg,16-bit-value + .macro SUBIP reg,val + _pfx_op SUBI,\reg,\val + .endm + + ; CMPIP %reg,16-bit-value + .macro CMPIP reg,val + _pfx_op CMPI,\reg,\val + .endm + + ; ANDIP %reg,16-bit-value + .macro ANDIP reg,val + PFX %hi(\val) + AND \reg,%lo(\val) + .endm + + ; ANDNIP %reg,16-bit-value + .macro ANDNIP reg,val + PFX %hi(\val) + ANDN \reg,%lo(\val) + .endm + + ; ORIP %reg,16-bit-value + .macro ORIP reg,val + PFX %hi(\val) + OR \reg,%lo(\val) + .endm + + ; XORIP %reg,16-bit-value + .macro XORIP reg,val + PFX %hi(\val) + XOR \reg,%lo(\val) + .endm + + ; BEQ addr + .macro BEQ addr + IFS cc_eq + BR \addr + .endm + + ; BNE addr + .macro BNE addr + IFS cc_ne + BR \addr + .endm + + ; BLE addr + .macro BLE addr + SKPS cc_gt + BR \addr + .endm + + ; BLT addr + .macro BLT addr + SKPS cc_ge + BR \addr + .endm + + .macro digitToChar reg + ANDIP \reg,0x000f + CMPI \reg,10 + SKPS cc_lt + ADDI \reg,'A'-'0'-10 + PFX %hi('0') + ADDI \reg,%lo('0') + .endm + +; PUSHRET == dec sp, and stash return addr + .macro PUSHRET + SUBI %sp,2 + ST [%sp],%o7 + .endm +; POPRET == pop and jump + .macro POPRET + LD %o7,[%sp] + JMP %o7 + ADDI %sp,2 ; branch delay slot + .endm + +; RESTRET = restore & return + .macro RESTRET + JMP %i7 + RESTORE + .endm + + ;-------------------- + ; MOVI16 %reg,Address + ; + .macro MOVI16 reg,val + PFX %hi(\val) + MOVI \reg,%lo(\val) + .endm + + ;-------------------- + ; MOVI32 %reg,Address + ; + .macro MOVI32 reg,val + PFX %hi(\val) + MOVI \reg,%lo(\val) + PFX %xhi(\val) + MOVHI \reg,%xlo(\val) + .endm + + ;-------------------- + ; MOVIA %reg,Address + ; + .macro MOVIA reg,val + .if __nios32__ + MOVI32 \reg,\val + .else + MOVI16 \reg,\val + .endif + .endm + + ;-------------------- + ; _BR + + .macro _BR target,viaRegister=%g7 + MOVIA \viaRegister,\target@h + JMP \viaRegister + .endm + + ;-------------------- + ; _BSR + + .macro _BSR target,viaRegister=%g7 + MOVIA \viaRegister,\target@h + CALL \viaRegister + .endm + + ;--------------------- + ; NM_Print "Your String Here" + ; + .macro NM_Print string + + BR pastStringData\@ + NOP + +stringData\@: + .asciz "\string" + .align 1 ; aligns by 2^n +pastStringData\@: + MOVIA %o0,stringData\@ + _BSR NR_TxString + NOP + .endm + + .macro NM_PrintLn string + NM_Print "\string" + _BSR NR_TxCR + NOP + .endm + + .macro NM_PrintRegister reg ; affects %g0 & %g1 & %g7, but thrashes the CWP a bit + SAVE %sp,-16 + NM_Print "\reg = " + RESTORE + MOV %g0,\reg + SAVE %sp,-16 + MOV %o0,%g0 + _BSR NR_TxHex + NOP + _BSR NR_TxCR + NOP + RESTORE + .endm + + .macro NM_PrintChar char + MOVIP %o0,\char + _BSR NR_TxChar + NOP + .endm + + .macro NM_Print2Chars char1,char2 + MOVIP %o0,(\char2<<8)+\char1 + _BSR NR_TxChar + NOP + _BSR NR_TxChar + LSRI %o0,8 + .endm + + + +; --------------------------- +; Completely inline UART sends +; Send the char, or %g7 if not there. +; Trashes %g5 and %g6 and %g7... + + .macro NM_TxChar char=0 +;NM_D_Delay 1000 + MOVIA %g6,NA_UARTBase +txCharLoop\@: + PFX 2 +.if \char + LD %g7,[%g6] + SKP1 %g7,6 +.else + LD %g5,[%g6] + SKP1 %g5,6 +.endif + BR txCharLoop\@ + NOP +.if \char + MOVIP %g7,\char +.endif + PFX 1 + ST [%g6],%g7 +;NM_D_Delay 4 + .endm + + .macro NM_TxCR + NM_TxChar 13 + NM_TxChar 10 + .endm + + .macro NM_TxHexDigit,reg,shift + MOV %g7,\reg + LSRI %g7,\shift + ANDIP %g7,0x000f + CMPI %g7,10 + SKPS cc_lt + ADDIP %g7,'A'-'0'-10 + ADDIP %g7,'0' + NM_TxChar + .endm + + .macro NM_TxHex + + .if __nios32__ + NM_TxHexDigit %g0,28 + NM_TxHexDigit %g0,24 + NM_TxHexDigit %g0,20 + NM_TxHexDigit %g0,16 + .endif + + NM_TxHexDigit %g0,12 + NM_TxHexDigit %g0,8 + NM_TxHexDigit %g0,4 + NM_TxHexDigit %g0,0 + .endm + + + + + + + + + + +; ---------------------- +; The following macros are +; rather mighty. They expand +; to large inline code for +; printing various things to +; the serial port. They are +; useful for debugging +; trap handlers, where you +; can't just go and call +; NR_TxChar and such, because, +; well, the CWP might be +; off limits! +; +; They do, however, presume +; that the stack is in good +; working order. + + +.macro NM_D_PushGRegisters + SUBIP %sp,16+69 ; oddball number so if we accidentally see it, it looks funny. + STS [%sp,16+0],%g0 + STS [%sp,16+1],%g1 + STS [%sp,16+2],%g2 + STS [%sp,16+3],%g3 + STS [%sp,16+4],%g4 + STS [%sp,16+5],%g5 + STS [%sp,16+6],%g6 + STS [%sp,16+7],%g7 + .endm + +.macro NM_D_PopGRegisters + LDS %g0,[%sp,16+0] + LDS %g1,[%sp,16+1] + LDS %g2,[%sp,16+2] + LDS %g3,[%sp,16+3] + LDS %g4,[%sp,16+4] + LDS %g5,[%sp,16+5] + LDS %g6,[%sp,16+6] + LDS %g7,[%sp,16+7] + ADDIP %sp,16+69 ; must match the push + .endm + + +.macro NM_D_TxChar c + SUBI %sp,16+8 ; 32 or 16 bit, that's enough space + STS [%sp,16+0],%g6 + STS [%sp,16+0],%g7 + NM_TxChar \c + LDS %g6,[%sp,16+0] + LDS %g7,[%sp,16+1] + ADDI %sp,16+8 + .endm + +.macro NM_D_TxChar3 c1,c2,c3 + NM_D_TxChar '<' + NM_D_TxChar \c1 + NM_D_TxChar \c2 + NM_D_TxChar \c3 + NM_D_TxChar '>' +.endm + +.macro NM_D_TxRegister r,n,reg + NM_D_PushGRegisters + NM_TxChar '(' + NM_TxChar \r + NM_TxChar \n + NM_TxChar ':' + MOV %g0,\reg + NM_TxHex + NM_TxChar ')' + NM_D_PopGRegisters +.endm + +.macro NM_D_TxReg r,n,reg + NM_D_TxRegister \r,\n,\reg +.endm + +; Do a delay loop, affects no registers. + +.macro NM_D_Delay d + SUBI %sp,16+4 + STS [%sp,16+0],%g0 + MOVIP %g0,\d +NM_D_DelayLoop\@: + IFRnz %g0 + BR NM_D_DelayLoop\@ + SUBI %g0,1 + LDS %g0,[%sp,16+0] + ADDI %sp,16+4 +.endm + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/NR_Math1.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/NR_Math1.S new file mode 100644 index 00000000..5d5169ba --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/NR_Math1.S @@ -0,0 +1,63 @@ + + + .include "NM_Macros.S" + + .file "okmul.c" +gcc2_compiled.: + .text + .p2align 1 + .globl __mulsi3 + .type __mulsi3,@function +__mulsi3: + + ;SKP0 %o0,31 + ;NEG %o1 + ;ABS %o0 + + .MACRO ZSTEP bit + SKP0 %o0,\bit + ADD %g0,%o1 + LSLI %o1,1 + .ENDM + + MOVI %g0,0 + ZSTEP 0 + ZSTEP 1 + ZSTEP 2 + ZSTEP 3 + ZSTEP 4 + ZSTEP 5 + ZSTEP 6 + ZSTEP 7 + ZSTEP 8 + ZSTEP 9 + ZSTEP 10 + ZSTEP 11 + ZSTEP 12 + ZSTEP 13 + ZSTEP 14 + ZSTEP 15 + ZSTEP 16 + ZSTEP 17 + ZSTEP 18 + ZSTEP 19 + ZSTEP 20 + ZSTEP 21 + ZSTEP 22 + ZSTEP 23 + ZSTEP 24 + ZSTEP 25 + ZSTEP 26 + ZSTEP 27 + ZSTEP 28 + ZSTEP 29 + ZSTEP 30 + ZSTEP 31 + ; No bit 31: we already set %o0 to positive + + JMP %o7 + MOV %o0,%g0 + +.Lfe1: + .size __mulsi3,.Lfe1-__mulsi3 + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/__longjmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/__longjmp.S new file mode 100644 index 00000000..d7d1cdd8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/__longjmp.S @@ -0,0 +1,103 @@ +/* Copyright (C) 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#define _ASM +#define _SETJMP_H +#include + + +;---------------------------------------- +; Name: __longjmp +; Description: Restore the current context +; as saved by a previous nr_setjmp +; Input: %o0: jmp_buf (ptr to) array to restore context from +; %o1: integer to return +; Output: %o0 = 0 the first time we're called, or +; whatever longjmp returns later +; Side Effects: uses %g0, %g1 & %g2 +; CWP Depth: 0 +; + + .align 2 + .global __longjmp +__longjmp: + ; + ; The way we'll do this is by executing + ; RESTORE instructions until the old + ; return address matches. Then we'll + ; jump to where setjmp was called from. + ; + ; Since we're moving the window pointer + ; all over the place, we'll naturally + ; only use the %g registers. + ; + + mov %g0,%o0 ; %g0 -> jmp_buf + mov %g1,%o1 ; %g1 = return value + pfx jmpbuf_callersret + ld %g2,[%g0] ; %g2 = old return address +__longjmp_loop: + cmp %g2,%i7 ; Are we there yet? + skps cc_ne + br __longjmp_done + nop ; (delay slot) + + br __longjmp_loop + restore ; (delay slot) + ; + ; One might put in a watchdog counter here, to + ; prevent a runaway stack crawl... but what would that + ; accomplish? What error can we throw? To whom? + ; + +__longjmp_done: + pfx jmpbuf_l0 ; Restore local register l0 + ld %l0,[%g0] + pfx jmpbuf_l1 ; Restore local register l1 + ld %l1,[%g0] + pfx jmpbuf_l2 ; Restore local register l2 + ld %l2,[%g0] + pfx jmpbuf_l3 ; Restore local register l3 + ld %l3,[%g0] + pfx jmpbuf_l4 ; Restore local register l4 + ld %l4,[%g0] + pfx jmpbuf_l5 ; Restore local register l5 + ld %l5,[%g0] + pfx jmpbuf_l6 ; Restore local register l6 + ld %l6,[%g0] + pfx jmpbuf_l7 ; Restore local register l7 + ld %l7,[%g0] + pfx jmpbuf_i0 ; Restore input register i0 + ld %i0,[%g0] + pfx jmpbuf_i1 ; Restore input register i1 + ld %i1,[%g0] + pfx jmpbuf_i2 ; Restore input register i2 + ld %i2,[%g0] + pfx jmpbuf_i3 ; Restore input register i3 + ld %i3,[%g0] + pfx jmpbuf_i4 ; Restore input register i4 + ld %i4,[%g0] + pfx jmpbuf_i5 ; Restore input register i5 + ld %i5,[%g0] + pfx jmpbuf_jmpret + ld %o7,[%g0] ; set fake return address + jmp %o7 ; and kinda return there. + mov %o0,%g1 ; (delay slot) return value + +libc_hidden_def(__longjmp) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/bits/endian.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/bits/endian.h new file mode 100644 index 00000000..34ea91f7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/bits/endian.h @@ -0,0 +1,8 @@ +/* nios is little-endian. */ + +#ifndef _ENDIAN_H +# error "Never use directly; include instead." +#endif + +/*mle */ +#define __BYTE_ORDER __LITTLE_ENDIAN diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/bits/fcntl.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/bits/fcntl.h new file mode 100644 index 00000000..0656dd6f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/bits/fcntl.h @@ -0,0 +1,236 @@ +/* O_*, F_*, FD_* bit values for Linux. + Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _FCNTL_H +# error "Never use directly; include instead." +#endif + + +#include +#ifdef __USE_GNU +# include +#endif + +/* open/fcntl - O_SYNC is only implemented on blocks devices and on files + located on an ext2 file system */ +#define O_ACCMODE 0003 +#define O_RDONLY 00 +#define O_WRONLY 01 +#define O_RDWR 02 +#define O_CREAT 0100 /* not fcntl */ +#define O_EXCL 0200 /* not fcntl */ +#define O_NOCTTY 0400 /* not fcntl */ +#define O_TRUNC 01000 /* not fcntl */ +#define O_APPEND 02000 +#define O_NONBLOCK 04000 +#define O_NDELAY O_NONBLOCK +#define O_SYNC 010000 +#define O_FSYNC O_SYNC +#define O_ASYNC 020000 + +#ifdef __USE_GNU +# define O_DIRECTORY 040000 /* Must be a directory. */ +# define O_NOFOLLOW 0100000 /* Do not follow links. */ +# define O_DIRECT 0200000 /* Direct disk access. */ +#endif + +/* For now Linux has synchronisity options for data and read operations. + We define the symbols here but let them do the same as O_SYNC since + this is a superset. */ +#if defined __USE_POSIX199309 || defined __USE_UNIX98 +# define O_DSYNC O_SYNC /* Synchronize data. */ +# define O_RSYNC O_SYNC /* Synchronize read operations. */ +#endif + +#ifdef __USE_LARGEFILE64 +# define O_LARGEFILE 0400000 +#endif + +/* Values for the second argument to `fcntl'. */ +#define F_DUPFD 0 /* Duplicate file descriptor. */ +#define F_GETFD 1 /* Get file descriptor flags. */ +#define F_SETFD 2 /* Set file descriptor flags. */ +#define F_GETFL 3 /* Get file status flags. */ +#define F_SETFL 4 /* Set file status flags. */ +#ifndef __USE_FILE_OFFSET64 +# define F_GETLK 5 /* Get record locking info. */ +# define F_SETLK 6 /* Set record locking info (non-blocking). */ +# define F_SETLKW 7 /* Set record locking info (blocking). */ +#else +# define F_GETLK F_GETLK64 /* Get record locking info. */ +# define F_SETLK F_SETLK64 /* Set record locking info (non-blocking).*/ +# define F_SETLKW F_SETLKW64 /* Set record locking info (blocking). */ +#endif +#define F_GETLK64 12 /* Get record locking info. */ +#define F_SETLK64 13 /* Set record locking info (non-blocking). */ +#define F_SETLKW64 14 /* Set record locking info (blocking). */ + +#if defined __USE_BSD || defined __USE_XOPEN2K +# define F_SETOWN 8 /* Get owner of socket (receiver of SIGIO). */ +# define F_GETOWN 9 /* Set owner of socket (receiver of SIGIO). */ +#endif + +#ifdef __USE_GNU +# define F_SETSIG 10 /* Set number of signal to be sent. */ +# define F_GETSIG 11 /* Get number of signal to be sent. */ +#endif + +#ifdef __USE_GNU +# define F_SETLEASE 1024 /* Set a lease. */ +# define F_GETLEASE 1025 /* Enquire what lease is active. */ +# define F_NOTIFY 1026 /* Request notfications on a directory. */ +# define F_DUPFD_CLOEXEC 1030 /* Duplicate file descriptor with + close-on-exit set on new fd. */ +#endif + +/* For F_[GET|SET]FL. */ +#define FD_CLOEXEC 1 /* actually anything with low bit set goes */ + +/* For posix fcntl() and `l_type' field of a `struct flock' for lockf(). */ +#define F_RDLCK 0 /* Read lock. */ +#define F_WRLCK 1 /* Write lock. */ +#define F_UNLCK 2 /* Remove lock. */ + +/* for old implementation of bsd flock () */ +#define F_EXLCK 4 /* or 3 */ +#define F_SHLCK 8 /* or 4 */ + +#ifdef __USE_BSD +/* Operations for bsd flock(), also used by the kernel implementation */ +# define LOCK_SH 1 /* shared lock */ +# define LOCK_EX 2 /* exclusive lock */ +# define LOCK_NB 4 /* or'd with one of the above to prevent + blocking */ +# define LOCK_UN 8 /* remove lock */ +#endif + +#ifdef __USE_GNU +# define LOCK_MAND 32 /* This is a mandatory flock: */ +# define LOCK_READ 64 /* ... which allows concurrent read operations. */ +# define LOCK_WRITE 128 /* ... which allows concurrent write operations. */ +# define LOCK_RW 192 /* ... Which allows concurrent read & write operations. */ +#endif + +#ifdef __USE_GNU +/* Types of directory notifications that may be requested with F_NOTIFY. */ +# define DN_ACCESS 0x00000001 /* File accessed. */ +# define DN_MODIFY 0x00000002 /* File modified. */ +# define DN_CREATE 0x00000004 /* File created. */ +# define DN_DELETE 0x00000008 /* File removed. */ +# define DN_RENAME 0x00000010 /* File renamed. */ +# define DN_ATTRIB 0x00000020 /* File changed attibutes. */ +# define DN_MULTISHOT 0x80000000 /* Don't remove notifier. */ +#endif + +struct flock + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ +#ifndef __USE_FILE_OFFSET64 + __off_t l_start; /* Offset where the lock begins. */ + __off_t l_len; /* Size of the locked area; zero means until EOF. */ +#else + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ +#endif + __pid_t l_pid; /* Process holding the lock. */ + }; + +#ifdef __USE_LARGEFILE64 +struct flock64 + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ + __pid_t l_pid; /* Process holding the lock. */ + }; +#endif + +/* Define some more compatibility macros to be backward compatible with + BSD systems which did not managed to hide these kernel macros. */ +#ifdef __USE_BSD +# define FAPPEND O_APPEND +# define FFSYNC O_FSYNC +# define FASYNC O_ASYNC +# define FNONBLOCK O_NONBLOCK +# define FNDELAY O_NDELAY +#endif /* Use BSD. */ + +/* Advise to `posix_fadvise'. */ +#ifdef __USE_XOPEN2K +# define POSIX_FADV_NORMAL 0 /* No further special treatment. */ +# define POSIX_FADV_RANDOM 1 /* Expect random page references. */ +# define POSIX_FADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define POSIX_FADV_WILLNEED 3 /* Will need these pages. */ +# define POSIX_FADV_DONTNEED 4 /* Don't need these pages. */ +# define POSIX_FADV_NOREUSE 5 /* Data will be accessed once. */ +#endif + + +#if defined __USE_GNU && defined __UCLIBC_LINUX_SPECIFIC__ +/* Flags for SYNC_FILE_RANGE. */ +# define SYNC_FILE_RANGE_WAIT_BEFORE 1 /* Wait upon writeout of all pages + in the range before performing the + write. */ +# define SYNC_FILE_RANGE_WRITE 2 /* Initiate writeout of all those + dirty pages in the range which are + not presently under writeback. */ +# define SYNC_FILE_RANGE_WAIT_AFTER 4 /* Wait upon writeout of all pages in + the range after performing the + write. */ + +/* Flags for SPLICE and VMSPLICE. */ +# define SPLICE_F_MOVE 1 /* Move pages instead of copying. */ +# define SPLICE_F_NONBLOCK 2 /* Don't block on the pipe splicing + (but we may still block on the fd + we splice from/to). */ +# define SPLICE_F_MORE 4 /* Expect more data. */ +# define SPLICE_F_GIFT 8 /* Pages passed in are a gift. */ +#endif + +__BEGIN_DECLS + +#if defined __USE_GNU && defined __UCLIBC_LINUX_SPECIFIC__ + +/* Provide kernel hint to read ahead. */ +extern ssize_t readahead (int __fd, __off64_t __offset, size_t __count) + __THROW; + + +/* Selective file content synch'ing. */ +extern int sync_file_range (int __fd, __off64_t __from, __off64_t __to, + unsigned int __flags); + +/* Splice address range into a pipe. */ +extern ssize_t vmsplice (int __fdout, const struct iovec *__iov, + size_t __count, unsigned int __flags); + +/* Splice two files together. */ +extern ssize_t splice (int __fdin, __off64_t *__offin, int __fdout, + __off64_t *__offout, size_t __len, + unsigned int __flags); + +/* In-kernel implementation of tee for pipe buffers. */ +extern ssize_t tee (int __fdin, int __fdout, size_t __len, + unsigned int __flags); + +#endif +__END_DECLS + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/bits/kernel_types.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/bits/kernel_types.h new file mode 100644 index 00000000..e66f42d7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/bits/kernel_types.h @@ -0,0 +1,43 @@ +/* Note that we use the exact same include guard #define names + * as asm/posix_types.h. This will avoid gratuitous conflicts + * with the posix_types.h kernel header, and will ensure that + * our private content, and not the kernel header, will win. + * -Erik + */ +#ifndef __ARCH_NIOS_POSIX_TYPES_H +#define __ARCH_NIOS_POSIX_TYPES_H + +typedef unsigned short __kernel_dev_t; +typedef unsigned long __kernel_ino_t; +typedef unsigned short __kernel_mode_t; +typedef unsigned short __kernel_nlink_t; +typedef long __kernel_off_t; +typedef int __kernel_pid_t; +typedef unsigned short __kernel_ipc_pid_t; +typedef unsigned short __kernel_uid_t; +typedef unsigned short __kernel_gid_t; +typedef unsigned int __kernel_size_t; +typedef int __kernel_ssize_t; +typedef int __kernel_ptrdiff_t; +typedef long __kernel_time_t; +typedef long __kernel_suseconds_t; +typedef long __kernel_clock_t; +typedef int __kernel_daddr_t; +typedef char * __kernel_caddr_t; +typedef unsigned short __kernel_uid16_t; +typedef unsigned short __kernel_gid16_t; +typedef unsigned int __kernel_uid32_t; +typedef unsigned int __kernel_gid32_t; +typedef unsigned short __kernel_old_uid_t; +typedef unsigned short __kernel_old_gid_t; +typedef long long __kernel_loff_t; + +typedef struct { +#ifdef __USE_ALL + int val[2]; +#else + int __val[2]; +#endif +} __kernel_fsid_t; + +#endif /* __ARCH_NIOS2_POSIX_TYPES_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/bits/mathdef.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/bits/mathdef.h new file mode 100644 index 00000000..e013e74b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/bits/mathdef.h @@ -0,0 +1,44 @@ +/* Copyright (C) 1999, 2000, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#if !defined _MATH_H && !defined _COMPLEX_H +# error "Never use directly; include instead" +#endif + +#if defined __USE_ISOC99 && defined _MATH_H && !defined _MATH_H_MATHDEF +# define _MATH_H_MATHDEF 1 + +/* GCC does not promote `float' values to `double'. */ +typedef float float_t; /* `float' expressions are evaluated as + `float'. */ +typedef double double_t; /* `double' expressions are evaluated as + `double'. */ + +/* The values returned by `ilogb' for 0 and NaN respectively. */ +# define FP_ILOGB0 (-2147483647) +# define FP_ILOGBNAN (2147483647) + +#endif /* ISO C99 */ + +#ifndef __NO_LONG_DOUBLE_MATH +/* Signal that we do not really have a `long double'. This disables the + declaration of all the `long double' function variants. */ +/* XXX The FPA does support this but the patterns in GCC are currently + turned off. */ +# define __NO_LONG_DOUBLE_MATH 1 +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/bits/setjmp.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/bits/setjmp.h new file mode 100644 index 00000000..807ebea0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/bits/setjmp.h @@ -0,0 +1,76 @@ +/* Copyright (C) 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Define the machine-dependent type `jmp_buf'. Nios version. */ +#ifndef _BITS_SETJMP_H +#define _BITS_SETJMP_H 1 + +#if !defined _SETJMP_H && !defined _PTHREAD_H +# error "Never include directly; use instead." +#endif + +#ifndef _ASM + +#include + +typedef struct + { + /* There are eight 4-byte local registers saved. */ + long int __lregs[8]; + + /* There are six 4-byte input registers saved. */ + long int __iregs[6]; + + /* The SP, return address to caller (also for longjmp) + and return address of caller are saved. */ + int *__sp; + int *__jmpret; + int *__callersret; + + } __jmp_buf[1]; + +/* Test if longjmp to JMPBUF would unwind the frame + containing a local variable at ADDRESS. */ +#define _JMPBUF_UNWINDS(jmpbuf, address) \ + ((void *) (address) < (void *) (jmpbuf)->__sp) + +#else /* _ASM */ + +#define jmpbuf_l0 0x00 +#define jmpbuf_l1 0x01 +#define jmpbuf_l2 0x02 +#define jmpbuf_l3 0x03 +#define jmpbuf_l4 0x04 +#define jmpbuf_l5 0x05 +#define jmpbuf_l6 0x06 +#define jmpbuf_l7 0x07 + +#define jmpbuf_i0 0x08 +#define jmpbuf_i1 0x09 +#define jmpbuf_i2 0x0a +#define jmpbuf_i3 0x0b +#define jmpbuf_i4 0x0c +#define jmpbuf_i5 0x0d + +#define jmpbuf_sp 0x0e +#define jmpbuf_jmpret 0x0f +#define jmpbuf_callersret 0x10 + +#endif /* _ASM */ + +#endif /* bits/setjmp.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/bits/sigcontextinfo.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/bits/sigcontextinfo.h new file mode 100644 index 00000000..caf1cf4c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/bits/sigcontextinfo.h @@ -0,0 +1,27 @@ +/* Copyright (C) 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define SIGCONTEXT struct sigcontext * +#define SIGCONTEXT_EXTRA_ARGS +#define GET_PC(ctx) ((void *) ((ctx)->regs.pc)) + +/* now way for nios to do GET_FRAME(ctx), it is not saved in ctx */ +#define GET_STACK(ctx) ((void *) (ctx)->regs.u_regs[14]) +#define CALL_SIGHANDLER(handler, signo, ctx) \ + (handler)((signo), SIGCONTEXT_EXTRA_ARGS (ctx)) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/bits/stackinfo.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/bits/stackinfo.h new file mode 100644 index 00000000..e7fbf563 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/bits/stackinfo.h @@ -0,0 +1,28 @@ +/* Copyright (C) 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This file contains a bit of information about the stack allocation + of the processor. */ + +#ifndef _STACKINFO_H +#define _STACKINFO_H 1 + +/* On nios II the stack grows down. */ +#define _STACK_GROWS_DOWN 1 + +#endif /* stackinfo.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/bits/stat.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/bits/stat.h new file mode 100644 index 00000000..d299ff18 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/bits/stat.h @@ -0,0 +1,168 @@ +/* Copyright (C) 1992,95,96,97,98,99,2000,2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_STAT_H +# error "Never include directly; use instead." +#endif + +/* Versions of the `struct stat' data structure. */ +#define _STAT_VER_LINUX_OLD 1 +#define _STAT_VER_KERNEL 1 +#define _STAT_VER_SVR4 2 +#define _STAT_VER_LINUX 3 +#define _STAT_VER _STAT_VER_LINUX /* The one defined below. */ + +/* Versions of the `xmknod' interface. */ +#define _MKNOD_VER_LINUX 1 +#define _MKNOD_VER_SVR4 2 +#define _MKNOD_VER _MKNOD_VER_LINUX /* The bits defined below. */ + + +struct stat + { + __dev_t st_dev; /* Device. */ + unsigned short int __pad1; +#ifndef __USE_FILE_OFFSET64 + __ino_t st_ino; /* File serial number. */ +#else + __ino_t __st_ino; /* 32bit file serial number. */ +#endif + __mode_t st_mode; /* File mode. */ + __nlink_t st_nlink; /* Link count. */ + __uid_t st_uid; /* User ID of the file's owner. */ + __gid_t st_gid; /* Group ID of the file's group.*/ + __dev_t st_rdev; /* Device number, if device. */ + unsigned short int __pad2; +#ifndef __USE_FILE_OFFSET64 + __off_t st_size; /* Size of file, in bytes. */ +#else + __off64_t st_size; /* Size of file, in bytes. */ +#endif + __blksize_t st_blksize; /* Optimal block size for I/O. */ + +#ifndef __USE_FILE_OFFSET64 + __blkcnt_t st_blocks; /* Number 512-byte blocks allocated. */ +#else + __blkcnt64_t st_blocks; /* Number 512-byte blocks allocated. */ +#endif +#ifdef __USE_MISC + /* Nanosecond resolution timestamps are stored in a format + equivalent to 'struct timespec'. This is the type used + whenever possible but the Unix namespace rules do not allow the + identifier 'timespec' to appear in the header. + Therefore we have to handle the use of this header in strictly + standard-compliant sources special. */ + struct timespec st_atim; /* Time of last access. */ + struct timespec st_mtim; /* Time of last modification. */ + struct timespec st_ctim; /* Time of last status change. */ +# define st_atime st_atim.tv_sec /* Backward compatibility. */ +# define st_mtime st_mtim.tv_sec +# define st_ctime st_ctim.tv_sec +#else + __time_t st_atime; /* Time of last access. */ + unsigned long int st_atimensec; /* Nscecs of last access. */ + __time_t st_mtime; /* Time of last modification. */ + unsigned long int st_mtimensec; /* Nsecs of last modification. */ + __time_t st_ctime; /* Time of last status change. */ + unsigned long int st_ctimensec; /* Nsecs of last status change. */ +#endif +#ifndef __USE_FILE_OFFSET64 + unsigned long int __unused4; + unsigned long int __unused5; +#else + __ino64_t st_ino; /* File serial number. */ +#endif + }; + +#ifdef __USE_LARGEFILE64 +struct stat64 + { + __dev_t st_dev; /* Device. */ + unsigned short int __pad1; + + __ino_t __st_ino; /* 32bit file serial number. */ + __mode_t st_mode; /* File mode. */ + __nlink_t st_nlink; /* Link count. */ + __uid_t st_uid; /* User ID of the file's owner. */ + __gid_t st_gid; /* Group ID of the file's group.*/ + __dev_t st_rdev; /* Device number, if device. */ + unsigned short int __pad2; + __off64_t st_size; /* Size of file, in bytes. */ + __blksize_t st_blksize; /* Optimal block size for I/O. */ + + __blkcnt64_t st_blocks; /* Number 512-byte blocks allocated. */ +#ifdef __USE_MISC + /* Nanosecond resolution timestamps are stored in a format + equivalent to 'struct timespec'. This is the type used + whenever possible but the Unix namespace rules do not allow the + identifier 'timespec' to appear in the header. + Therefore we have to handle the use of this header in strictly + standard-compliant sources special. */ + struct timespec st_atim; /* Time of last access. */ + struct timespec st_mtim; /* Time of last modification. */ + struct timespec st_ctim; /* Time of last status change. */ +#else + __time_t st_atime; /* Time of last access. */ + unsigned long int st_atimensec; /* Nscecs of last access. */ + __time_t st_mtime; /* Time of last modification. */ + unsigned long int st_mtimensec; /* Nsecs of last modification. */ + __time_t st_ctime; /* Time of last status change. */ + unsigned long int st_ctimensec; /* Nsecs of last status change. */ +#endif + __ino64_t st_ino; /* File serial number. */ + }; +#endif + +/* Tell code we have these members. */ +#define _STATBUF_ST_BLKSIZE +#define _STATBUF_ST_RDEV +/* Nanosecond resolution time values are supported. */ +#define _STATBUF_ST_NSEC + +/* Encoding of the file mode. */ + +#define __S_IFMT 0170000 /* These bits determine file type. */ + +/* File types. */ +#define __S_IFDIR 0040000 /* Directory. */ +#define __S_IFCHR 0020000 /* Character device. */ +#define __S_IFBLK 0060000 /* Block device. */ +#define __S_IFREG 0100000 /* Regular file. */ +#define __S_IFIFO 0010000 /* FIFO. */ +#define __S_IFLNK 0120000 /* Symbolic link. */ +#define __S_IFSOCK 0140000 /* Socket. */ + +/* POSIX.1b objects. Note that these macros always evaluate to zero. But + they do it by enforcing the correct use of the macros. */ +#define __S_TYPEISMQ(buf) ((buf)->st_mode - (buf)->st_mode) +#define __S_TYPEISSEM(buf) ((buf)->st_mode - (buf)->st_mode) +#define __S_TYPEISSHM(buf) ((buf)->st_mode - (buf)->st_mode) + +/* Protection bits. */ + +#define __S_ISUID 04000 /* Set user ID on execution. */ +#define __S_ISGID 02000 /* Set group ID on execution. */ +#define __S_ISVTX 01000 /* Save swapped text after use (sticky). */ +#define __S_IREAD 0400 /* Read by owner. */ +#define __S_IWRITE 0200 /* Write by owner. */ +#define __S_IEXEC 0100 /* Execute by owner. */ + +#ifdef __USE_ATFILE +# define UTIME_NOW ((1l << 30) - 1l) +# define UTIME_OMIT ((1l << 30) - 2l) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/bits/syscalls.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/bits/syscalls.h new file mode 100644 index 00000000..c2b6b973 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/bits/syscalls.h @@ -0,0 +1,13 @@ +#ifndef _BITS_SYSCALLS_H +#define _BITS_SYSCALLS_H +#ifndef _SYSCALL_H +# error "Never use directly; include instead." +#endif + +#include +/* Do something very evil for now. Until we include our out syscall + * macros, short circuit bits/syscall.h and use asm/unistd.h instead */ +#include + +#endif /* _BITS_SYSCALLS_H */ + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/bits/uClibc_arch_features.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/bits/uClibc_arch_features.h new file mode 100644 index 00000000..2a9422e2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/bits/uClibc_arch_features.h @@ -0,0 +1,48 @@ +/* + * Track misc arch-specific features that aren't config options + */ + +#ifndef _BITS_UCLIBC_ARCH_FEATURES_H +#define _BITS_UCLIBC_ARCH_FEATURES_H + +/* instruction used when calling abort() to kill yourself */ +/*#define __UCLIBC_ABORT_INSTRUCTION__ "asm instruction"*/ +#undef __UCLIBC_ABORT_INSTRUCTION__ + +/* can your target use syscall6() for mmap ? */ +#undef __UCLIBC_MMAP_HAS_6_ARGS__ + +/* does your target use syscall4() for truncate64 ? (32bit arches only) */ +#undef __UCLIBC_TRUNCATE64_HAS_4_ARGS__ + +/* does your target have a broken create_module() ? */ +#undef __UCLIBC_BROKEN_CREATE_MODULE__ + +/* does your target have to worry about older [gs]etrlimit() ? */ +#undef __UCLIBC_HANDLE_OLDER_RLIMIT__ + +/* does your target have an asm .set ? */ +#define __UCLIBC_HAVE_ASM_SET_DIRECTIVE__ + +/* define if target doesn't like .global */ +#undef __UCLIBC_ASM_GLOBAL_DIRECTIVE__ + +/* define if target supports .weak */ +#define __UCLIBC_HAVE_ASM_WEAK_DIRECTIVE__ + +/* define if target supports .weakext */ +#undef __UCLIBC_HAVE_ASM_WEAKEXT_DIRECTIVE__ + +/* needed probably only for ppc64 */ +#undef __UCLIBC_HAVE_ASM_GLOBAL_DOT_NAME__ + +/* define if target supports CFI pseudo ops */ +#undef __UCLIBC_HAVE_ASM_CFI_DIRECTIVES__ + +/* define if target supports IEEE signed zero floats */ +#define __UCLIBC_HAVE_SIGNED_ZERO__ + +/* only weird assemblers generally need this */ +#undef __UCLIBC_ASM_LINE_SEP__ + +#endif /* _BITS_UCLIBC_ARCH_FEATURES_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/bits/wordsize.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/bits/wordsize.h new file mode 100644 index 00000000..ba643b60 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/bits/wordsize.h @@ -0,0 +1,19 @@ +/* Copyright (C) 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define __WORDSIZE 32 diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/brk.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/brk.c new file mode 100644 index 00000000..c88b692a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/brk.c @@ -0,0 +1,44 @@ +/* brk system call for Linux/Nios2. + Copyright (C) 1995, 1996, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +/* This must be initialized data because commons can't have aliases. */ +void *__curbrk attribute_hidden = 0; + +int brk (void *addr) +{ + void *newbrk; + register int g1 __asm__("%g1") = __NR_brk; + register void *o0 __asm__("%o0") = addr; + + __asm__ __volatile__ ("trap 63\n\t" : "=r"(newbrk) : "0"(o0), "r"(g1)); + + __curbrk = newbrk; + + if (newbrk < addr) { + __set_errno (ENOMEM); + return -1; + } + + return 0; +} +libc_hidden_def(brk) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/bsd-_setjmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/bsd-_setjmp.S new file mode 100644 index 00000000..f2f0f239 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/bsd-_setjmp.S @@ -0,0 +1 @@ +/* _setjmp in setjmp.S */ \ No newline at end of file diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/bsd-setjmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/bsd-setjmp.S new file mode 100644 index 00000000..36f2bab1 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/bsd-setjmp.S @@ -0,0 +1 @@ +/* setjmp in setjmp.S */ \ No newline at end of file diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/clone.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/clone.S new file mode 100644 index 00000000..39eb5403 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/clone.S @@ -0,0 +1,88 @@ +/* Copyright (C) 1996, 1997, 1998, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson (rth@tamu.edu). + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* clone() is even more special than fork() as it mucks with stacks + and invokes a function in the right context after its all over. */ + +#include +#include +#include "NM_Macros.S" + +/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg); */ + + .text + .align 2 + .globl clone + .type clone,@function + +clone: + save %sp,-16 + + MOVIP %l0, -EINVAL + /* sanity check arguments */ + skprnz %i0 /* no NULL function pointers */ + br CLONE_ERROR_LABEL + mov %o0, %i2 + + skprnz %i1 /* no NULL stack pointers */ + br CLONE_ERROR_LABEL + mov %o1, %i1 + + /* Do the system call */ + MOVIP %g1, __NR_clone + trap 63 + + /* if ret >=0? */ + cmpi %o0, 0 + skps cc_pl + br CLONE_ERROR_LABEL + mov %l0, %o0 + + /* Start thread */ + skprz %o1 + br __thread_start + nop + mov %i0, %o0 + ret + restore + +CLONE_ERROR_LABEL: + neg %l0 + MOVIA %g1, __errno_location@h + call %g1 + nop + st [%o0], %l0 /* store errno */ + + xor %i0, %i0 + dec %i0 /* retval=-1 */ + ret + restore + + .size clone, .-clone + + .type __thread_start,@function + +__thread_start: + call %i0 + mov %o0, %i3 + MOVIA %g1, _exit@h + call %g1 + nop + + .size __thread_start, .-__thread_start diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/crt1.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/crt1.S new file mode 100644 index 00000000..e80a8218 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/crt1.S @@ -0,0 +1,59 @@ +/* Copyright (C) 1991, 1992 Free Software Foundation, Inc. + +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include +#include +#include "NM_Macros.S" +#define __ASSEMBLY__ +#include /* for REGWIN_SZ */ + + .global _start + .type __start,@function + .weak _init + .weak _fini + .type main,@function + .type __uClibc_main,@function + .type __h_errno_location, @function + .type _stdio_init, @function + .type _stdio_term, @function + + .text + +_start: + nop + nop + + MOVIA %o0, main@h + lds %o1,[%sp, (REGWIN_SZ / 4) + 0] /* main's argc */ + lds %o2,[%sp, (REGWIN_SZ / 4) + 1] /* main's argv */ + + MOVIA %o3, _init@h + MOVIA %o4, _fini@h + mov %o5, %i0 /* rtld_fini */ + mov %o6, %sp /* stack_end */ + MOVIA %o7, __uClibc_main@h + + call %o7 + nop + + + /* If that didn't kill us, ... */ +__exit: + MOVIP %g1, __NR_exit + trap 63 diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/crtbegin.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/crtbegin.c new file mode 100644 index 00000000..ac3f23f8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/crtbegin.c @@ -0,0 +1,37 @@ +#include +#include +/* +static void (*__CTOR_LIST__[1]) __P((void)) + __attribute__((__unused__)) + __attribute__((section(".ctors"))) = { (void *)0 }; + +static void (*__DTOR_LIST__[1]) __P((void)) + __attribute__((section(".dtors"))) = { (void *)-1 }; +*/ +extern void (*__DTOR_LIST__[]) __P((void)); +static void __do_global_dtors_aux __P((void)); + +static void +__do_global_dtors_aux() +{ + void (**p)(void) = __DTOR_LIST__ + 1; + + while (*p) + (**p++)(); +} + +static void dummy_fini(void) __attribute__((section(".trash"))); + +void +dummy_fini(void) +{ + static void (* volatile call__dtors)(void) = __do_global_dtors_aux; + /* + * Call global destructors. + */ + /* prevent function pointer constant propagation */ + __asm__ __volatile__ (".section .fini"); + (*call__dtors)(); + __asm__ __volatile__ (".section .trash"); + +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/crtend.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/crtend.c new file mode 100644 index 00000000..775eb0f9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/crtend.c @@ -0,0 +1,44 @@ +#include +#include +#include +/* +static void (*__CTOR_END__[1]) __P((void)) + __attribute__((section(".ctors"))) = { (void *)-1 }; + +static void (*__DTOR_END__[1]) __P((void)) + __attribute__((__unused__)) + __attribute__((section(".dtors"))) = { (void *)0 }; +*/ +extern void (*__CTOR_END__[]) __P((void)); +static void __do_global_ctors_aux __P((void)); + +static void +__do_global_ctors_aux() +{ + void (**p)(void) = __CTOR_END__ - 1; + + while (*p) + (**p--)(); +} + +static void dummy_init(void) __attribute__((section(".trash"))); + +void +dummy_init(void) +{ + static smallint initialized; + static void (*volatile call__ctors)(void) = __do_global_ctors_aux; + /* + * Call global constructors. + * Arrange to call global destructors at exit. + */ + /* prevent function pointer constant propagation */ + __asm__ __volatile__ (".section .init"); + + if (!initialized) { + initialized = 1; + (*call__ctors)(); + } + __asm__ __volatile__ (".section .trash"); + +} \ No newline at end of file diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/fpu_control.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/fpu_control.h new file mode 100644 index 00000000..9c317457 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/fpu_control.h @@ -0,0 +1,99 @@ +/* FPU control word bits. Nios2 version. + Copyright (C) 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FPU_CONTROL_H +#define _FPU_CONTROL_H + +/* MIPS FPU floating point control register bits. + * + * 31-25 -> floating point conditions code bits 7-1. These bits are only + * available in MIPS IV. + * 24 -> flush denormalized results to zero instead of + * causing unimplemented operation exception. This bit is only + * available for MIPS III and newer. + * 23 -> Condition bit + * 22-18 -> reserved (read as 0, write with 0) + * 17 -> cause bit for unimplemented operation + * 16 -> cause bit for invalid exception + * 15 -> cause bit for division by zero exception + * 14 -> cause bit for overflow exception + * 13 -> cause bit for underflow exception + * 12 -> cause bit for inexact exception + * 11 -> enable exception for invalid exception + * 10 -> enable exception for division by zero exception + * 9 -> enable exception for overflow exception + * 8 -> enable exception for underflow exception + * 7 -> enable exception for inexact exception + * 6 -> flag invalid exception + * 5 -> flag division by zero exception + * 4 -> flag overflow exception + * 3 -> flag underflow exception + * 2 -> flag inexact exception + * 1-0 -> rounding control + * + * + * Rounding Control: + * 00 - rounding to nearest (RN) + * 01 - rounding toward zero (RZ) + * 10 - rounding (up) toward plus infinity (RP) + * 11 - rounding (down)toward minus infinity (RM) + */ + +#include + +/* masking of interrupts */ +#define _FPU_MASK_V 0x0800 /* Invalid operation */ +#define _FPU_MASK_Z 0x0400 /* Division by zero */ +#define _FPU_MASK_O 0x0200 /* Overflow */ +#define _FPU_MASK_U 0x0100 /* Underflow */ +#define _FPU_MASK_I 0x0080 /* Inexact operation */ + +/* flush denormalized numbers to zero */ +#define _FPU_FLUSH_TZ 0x1000000 + +/* rounding control */ +#define _FPU_RC_NEAREST 0x0 /* RECOMMENDED */ +#define _FPU_RC_ZERO 0x1 +#define _FPU_RC_UP 0x2 +#define _FPU_RC_DOWN 0x3 + +#define _FPU_RESERVED 0xfe3c0000 /* Reserved bits in cw */ + + +/* The fdlibm code requires strict IEEE double precision arithmetic, + and no interrupts for exceptions, rounding to nearest. */ + +#define _FPU_DEFAULT 0x00000000 + +/* IEEE: same as above, but exceptions */ +#define _FPU_IEEE 0x00000F80 + +/* Type of the control word. */ +typedef unsigned int fpu_control_t __attribute__ ((__mode__ (__SI__))); + +/* Macros for accessing the hardware control word. */ +#define _FPU_GETCW(cw) __asm__ ("cfc1 %0,$31" : "=r" (cw)) +#define _FPU_SETCW(cw) __asm__ ("ctc1 %0,$31" : : "r" (cw)) + +#if 0 +/* Default control word set at startup. */ +extern fpu_control_t __fpu_control; +#endif + +#endif /* fpu_control.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/setjmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/setjmp.S new file mode 100644 index 00000000..c2851461 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/setjmp.S @@ -0,0 +1,102 @@ +/* Copyright (C) 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#define _ASM +#define _SETJMP_H +#include +#include "NM_Macros.S" + +;---------------------------------------- +; Name: __sigsetjmp +; Description: Save the current context so +; a nr_longjmp works later. +; Input: %o0: jmp_buf: (ptr to) array to store context in +; Output: %o0 = 0 the first time we're called, or +; whatever longjmp returns later +; Side Effects: Uses %g0 +; CWP Depth: 0 +; + + .align 2 + .global _setjmp + +_setjmp: + br __sigsetjmp + movi %o1,0 ; (Delay slot) Set signal mask to zero + + .align 2 + .global setjmp + +setjmp: + MOVIP %o1,1 ; Set signal mask to 1 to save mask + + .align 2 + .global __sigsetjmp + +__sigsetjmp: + pfx jmpbuf_callersret ; present return address + st [%o0],%i7 + pfx jmpbuf_jmpret ; where the longjmp will later execute from + st [%o0],%o7 + pfx jmpbuf_sp ; Save stack pointer + st [%o0],%o6 + pfx jmpbuf_l0 ; Save local register l0 + st [%o0],%l0 + pfx jmpbuf_l1 ; Save local register l1 + st [%o0],%l1 + pfx jmpbuf_l2 ; Save local register l2 + st [%o0],%l2 + pfx jmpbuf_l3 ; Save local register l3 + st [%o0],%l3 + pfx jmpbuf_l4 ; Save local register l4 + st [%o0],%l4 + pfx jmpbuf_l5 ; Save local register l5 + st [%o0],%l5 + pfx jmpbuf_l6 ; Save local register l6 + st [%o0],%l6 + pfx jmpbuf_l7 ; Save local register l7 + st [%o0],%l7 + pfx jmpbuf_i0 ; Save input register i0 + st [%o0],%i0 + pfx jmpbuf_i1 ; Save input register i1 + st [%o0],%i1 + pfx jmpbuf_i2 ; Save input register i2 + st [%o0],%i2 + pfx jmpbuf_i3 ; Save input register i3 + st [%o0],%i3 + pfx jmpbuf_i4 ; Save input register i4 + st [%o0],%i4 + pfx jmpbuf_i5 ; Save input register i5 + st [%o0],%i5 + pfx %hi(__sigjmp_save@h) ; Load up %g0 with address + movi %g0,%lo(__sigjmp_save@h) + pfx %xhi(__sigjmp_save@h) + movhi %g0,%xlo(__sigjmp_save@h) + jmp %g0 + nop ; (delay slot) + + + + + + + + + + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/sys/procfs.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/sys/procfs.h new file mode 100644 index 00000000..8cbaa41c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/sys/procfs.h @@ -0,0 +1,123 @@ +/* Copyright (C) 1996, 1997, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_PROCFS_H +#define _SYS_PROCFS_H 1 + +/* This is somehow modelled after the file of the same name on SysVr4 + systems. It provides a definition of the core file format for ELF + used on Linux. */ + +#include +#include +#include +#include +#include +#include +#include + +__BEGIN_DECLS + +#define ELF_NGREG 38 + +typedef struct + { + union + { + unsigned long pr_regs[32]; + double pr_dregs[16]; + } pr_fr; + unsigned long __unused; + unsigned long pr_fsr; + unsigned char pr_qcnt; + unsigned char pr_q_entrysize; + unsigned char pr_en; + unsigned int pr_q[64]; + } elf_fpregset_t; + +typedef unsigned long elf_greg_t; +typedef elf_greg_t elf_gregset_t[ELF_NGREG]; + +struct elf_siginfo + { + int si_signo; /* Signal number. */ + int si_code; /* Extra code. */ + int si_errno; /* Errno. */ + }; + +/* Definitions to generate Intel SVR4-like core files. These mostly + have the same names as the SVR4 types with "elf_" tacked on the + front to prevent clashes with linux definitions, and the typedef + forms have been avoided. This is mostly like the SVR4 structure, + but more Linuxy, with things that Linux does not support and which + gdb doesn't really use excluded. Fields present but not used are + marked with "XXX". */ +struct elf_prstatus + { + struct elf_siginfo pr_info; /* Info associated with signal. */ + short int pr_cursig; /* Current signal. */ + unsigned long int pr_sigpend; /* Set of pending signals. */ + unsigned long int pr_sighold; /* Set of held signals. */ + __pid_t pr_pid; + __pid_t pr_ppid; + __pid_t pr_pgrp; + __pid_t pr_sid; + struct timeval pr_utime; /* User time. */ + struct timeval pr_stime; /* System time. */ + struct timeval pr_cutime; /* Cumulative user time. */ + struct timeval pr_cstime; /* Cumulative system time. */ + elf_gregset_t pr_reg; /* GP registers. */ + int pr_fpvalid; /* True if math copro being used. */ + }; + + +#define ELF_PRARGSZ (80) /* Number of chars for args */ + +struct elf_prpsinfo + { + char pr_state; /* Numeric process state. */ + char pr_sname; /* Char for pr_state. */ + char pr_zomb; /* Zombie. */ + char pr_nice; /* Nice val. */ + unsigned long int pr_flag; /* Flags. */ + unsigned short int pr_uid; + unsigned short int pr_gid; + int pr_pid, pr_ppid, pr_pgrp, pr_sid; + /* Lots missing */ + char pr_fname[16]; /* Filename of executable. */ + char pr_psargs[ELF_PRARGSZ]; /* Initial part of arg list. */ + }; + +/* Addresses. */ +typedef void *psaddr_t; + +/* Register sets. Linux has different names. */ +typedef elf_gregset_t prgregset_t; +typedef elf_fpregset_t prfpregset_t; + +/* We don't have any differences between processes and threads, + therefore have only one PID type. */ +typedef __pid_t lwpid_t; + + +typedef struct elf_prstatus prstatus_t; +typedef struct elf_prpsinfo prpsinfo_t; + +__END_DECLS + +#endif /* sys/procfs.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/sys/ucontext.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/sys/ucontext.h new file mode 100644 index 00000000..1805b4ea --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/sys/ucontext.h @@ -0,0 +1,104 @@ +/* Copyright (C) 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_UCONTEXT_H +#define _SYS_UCONTEXT_H 1 + +#include +#include +/* + * Location of the users' stored registers relative to R0. + * Usage is as an index into a gregset_t array or as u.u_ar0[XX]. + */ +#define REG_PSR (0) +#define REG_PC (1) +#define REG_SPARE (2) +#define REG_WVALID (3) +#define REG_G1 (4) +#define REG_G2 (5) +#define REG_G3 (6) +#define REG_G4 (7) +#define REG_G5 (8) +#define REG_G6 (9) +#define REG_G7 (10) +#define REG_O0 (11) +#define REG_O1 (12) +#define REG_O2 (13) +#define REG_O3 (14) +#define REG_O4 (15) +#define REG_O5 (16) +#define REG_O6 (17) +#define REG_O7 (18) +#define REG_GLOBALS (19) + +/* + * A gregset_t is defined as an array type for compatibility with the reference + * source. This is important due to differences in the way the C language + * treats arrays and structures as parameters. + * + * Note that NGREG is really (sizeof (struct regs) / sizeof (greg_t)), + * but that the ABI defines it absolutely to be 21 (resp. 19). + */ + +#define NGREG 20 +typedef int greg_t; + +typedef greg_t gregset_t[NGREG]; + +/* + * The following structures define how a register window can appear on the + * stack. This structure is available (when required) through the `gwins' + * field of an mcontext (nested within ucontext). NIOS_MAXWINDOW is the + * maximum number of outstanding register windows defined in the NIOS + * architecture (*not* implementation). + */ +#define NIOS_MAXREGWINDOW 31 /* max windows in NIOS arch. */ +struct rwindow + { + greg_t rw_local[8]; /* locals */ + greg_t rw_in[8]; /* ins */ + }; + +#define rw_fp rw_in[6] /* frame pointer */ +#define rw_rtn rw_in[7] /* return address */ + +typedef struct gwindows + { + int wbcnt; + int *spbuf[NIOS_MAXREGWINDOW]; + struct rwindow wbuf[NIOS_MAXREGWINDOW]; + } gwindows_t; + +typedef struct + { + gregset_t gregs; /* general register set */ + gwindows_t *gwins; /* POSSIBLE pointer to register windows */ + } mcontext_t; + + +/* Userlevel context. */ +typedef struct ucontext + { + unsigned long uc_flags; + struct ucontext *uc_link; + __sigset_t uc_sigmask; + stack_t uc_stack; + mcontext_t uc_mcontext; + } ucontext_t; + +#endif /* sys/ucontext.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/vfork.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/vfork.S new file mode 100644 index 00000000..f8a6d031 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios/vfork.S @@ -0,0 +1,54 @@ +/* + * libc/sysdeps/linux/nios/vfork.S -- `vfork' syscall for linux/nios + * + * Copyright (C) 2004 Microtronix Datacom Ltd + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + * + * Written by Wentao Xu + */ + +#include + +#include +#include +#include "NM_Macros.S" + +#ifndef __NR_vfork +#define __NR_vfork __NR_fork /* uClinux-2.0 only has fork which is vfork */ +#endif + + .text + .align 2 + .globl __vfork + .hidden __vfork + .type __vfork,@function +__vfork: + MOVIP %g1, __NR_vfork + trap 63 + + bgen %g1, 12 + not %g1 /* (unsigned long) -4096 */ + cmp %o0, %g1 + skps cc_hi + jmp %o7 + nop + +fix_errno: + neg %o0 + save %sp, -16 + MOVIA %g1, __errno_location@h + call %g1 + nop + st [%o0], %i0 /* store errno */ + + xor %i0, %i0 + subi %i0, 1 /* retval=-1 */ + ret + restore + +.size __vfork,.-__vfork +weak_alias(__vfork,vfork) +libc_hidden_weak(vfork) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/Makefile new file mode 100644 index 00000000..633c91f3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../../ +top_builddir=../../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.arch +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/Makefile.arch b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/Makefile.arch new file mode 100644 index 00000000..a0c485aa --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/Makefile.arch @@ -0,0 +1,12 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +CSRC := brk.c syscall.c + +SSRC := \ + __longjmp.S bsd-_setjmp.S bsd-setjmp.S setjmp.S \ + vfork.S clone.S diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/__longjmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/__longjmp.S new file mode 100644 index 00000000..4b6508e5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/__longjmp.S @@ -0,0 +1,50 @@ +/* + * libc/sysdeps/linux/nios2/__longjmp.S + * + * Copyright (C) 2004,05,06 Microtronix Datacom Ltd + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + * + * Written by Wentao Xu + * + */ + +#include +#define _ASM +#define _SETJMP_H +#include + +.globl __longjmp +.type __longjmp,@function +.balign 4 + +__longjmp: + /* return value is in r5*/ + mov r2, r5 + + /* jmp_buf in r4, restore regs. */ + ldw r16, (JB_REGS+ 0)(r4) + ldw r17, (JB_REGS+ 4)(r4) + ldw r18, (JB_REGS+ 8)(r4) + ldw r19, (JB_REGS+12)(r4) + ldw r20, (JB_REGS+16)(r4) + ldw r21, (JB_REGS+20)(r4) + ldw r22, (JB_REGS+24)(r4) + ldw r23, (JB_REGS+28)(r4) + + ldw ra, JB_PC(r4) + ldw fp, JB_FP(r4) + ldw gp, JB_GP(r4) + ldw sp, JB_SP(r4) + +#if defined(__HAVE_FPU__) + RESTORE_FPU r4 JB_FPREGS +#endif + + /* return to saved RA */ + ret + +.size __longjmp,.-__longjmp +libc_hidden_def(__longjmp) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/bits/endian.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/bits/endian.h new file mode 100644 index 00000000..54bd9d14 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/bits/endian.h @@ -0,0 +1,7 @@ +/* i386 is little-endian. */ + +#ifndef _ENDIAN_H +# error "Never use directly; include instead." +#endif + +#define __BYTE_ORDER __LITTLE_ENDIAN diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/bits/fcntl.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/bits/fcntl.h new file mode 100644 index 00000000..e564b421 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/bits/fcntl.h @@ -0,0 +1,238 @@ +/* O_*, F_*, FD_* bit values for Linux. + Copyright (C) 2000, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FCNTL_H +# error "Never use directly; include instead." +#endif + + +#include +#ifdef __USE_GNU +# include +#endif + +/* open/fcntl - O_SYNC is only implemented on blocks devices and on files + located on an ext2 file system */ +#define O_ACCMODE 0003 +#define O_RDONLY 00 +#define O_WRONLY 01 +#define O_RDWR 02 +#define O_CREAT 0100 /* not fcntl */ +#define O_EXCL 0200 /* not fcntl */ +#define O_NOCTTY 0400 /* not fcntl */ +#define O_TRUNC 01000 /* not fcntl */ +#define O_APPEND 02000 +#define O_NONBLOCK 04000 +#define O_NDELAY O_NONBLOCK +#define O_SYNC 010000 +#define O_FSYNC O_SYNC +#define O_ASYNC 020000 + +#ifdef __USE_GNU +# define O_DIRECTORY 040000 /* Must be a directory. */ +# define O_NOFOLLOW 0100000 /* Do not follow links. */ +# define O_DIRECT 0200000 /* Direct disk access. */ +# define O_NOATIME 01000000 /* Do not set atime. */ +# define O_CLOEXEC 02000000 /* set close_on_exec */ +#endif + +/* For now Linux has synchronisity options for data and read operations. + We define the symbols here but let them do the same as O_SYNC since + this is a superset. */ +#if defined __USE_POSIX199309 || defined __USE_UNIX98 +# define O_DSYNC O_SYNC /* Synchronize data. */ +# define O_RSYNC O_SYNC /* Synchronize read operations. */ +#endif + +#ifdef __USE_LARGEFILE64 +# define O_LARGEFILE 0400000 +#endif + +/* Values for the second argument to `fcntl'. */ +#define F_DUPFD 0 /* Duplicate file descriptor. */ +#define F_GETFD 1 /* Get file descriptor flags. */ +#define F_SETFD 2 /* Set file descriptor flags. */ +#define F_GETFL 3 /* Get file status flags. */ +#define F_SETFL 4 /* Set file status flags. */ +#ifndef __USE_FILE_OFFSET64 +# define F_GETLK 5 /* Get record locking info. */ +# define F_SETLK 6 /* Set record locking info (non-blocking). */ +# define F_SETLKW 7 /* Set record locking info (blocking). */ +#else +# define F_GETLK F_GETLK64 /* Get record locking info. */ +# define F_SETLK F_SETLK64 /* Set record locking info (non-blocking).*/ +# define F_SETLKW F_SETLKW64 /* Set record locking info (blocking). */ +#endif +#define F_GETLK64 12 /* Get record locking info. */ +#define F_SETLK64 13 /* Set record locking info (non-blocking). */ +#define F_SETLKW64 14 /* Set record locking info (blocking). */ + +#if defined __USE_BSD || defined __USE_UNIX98 +# define F_SETOWN 8 /* Get owner of socket (receiver of SIGIO). */ +# define F_GETOWN 9 /* Set owner of socket (receiver of SIGIO). */ +#endif + +#ifdef __USE_GNU +# define F_SETSIG 10 /* Set number of signal to be sent. */ +# define F_GETSIG 11 /* Get number of signal to be sent. */ +#endif + +#ifdef __USE_GNU +# define F_SETLEASE 1024 /* Set a lease. */ +# define F_GETLEASE 1025 /* Enquire what lease is active. */ +# define F_NOTIFY 1026 /* Request notfications on a directory. */ +# define F_DUPFD_CLOEXEC 1030 /* Duplicate file descriptor with + close-on-exit set on new fd. */ +#endif + +/* For F_[GET|SET]FL. */ +#define FD_CLOEXEC 1 /* actually anything with low bit set goes */ + +/* For posix fcntl() and `l_type' field of a `struct flock' for lockf(). */ +#define F_RDLCK 0 /* Read lock. */ +#define F_WRLCK 1 /* Write lock. */ +#define F_UNLCK 2 /* Remove lock. */ + +/* For old implementation of bsd flock(). */ +#define F_EXLCK 4 /* or 3 */ +#define F_SHLCK 8 /* or 4 */ + +#ifdef __USE_BSD +/* Operations for bsd flock(), also used by the kernel implementation. */ +# define LOCK_SH 1 /* shared lock */ +# define LOCK_EX 2 /* exclusive lock */ +# define LOCK_NB 4 /* or'd with one of the above to prevent + blocking */ +# define LOCK_UN 8 /* remove lock */ +#endif + +#ifdef __USE_GNU +# define LOCK_MAND 32 /* This is a mandatory flock: */ +# define LOCK_READ 64 /* ... which allows concurrent read operations. */ +# define LOCK_WRITE 128 /* ... which allows concurrent write operations. */ +# define LOCK_RW 192 /* ... Which allows concurrent read & write operations. */ +#endif + +#ifdef __USE_GNU +/* Types of directory notifications that may be requested with F_NOTIFY. */ +# define DN_ACCESS 0x00000001 /* File accessed. */ +# define DN_MODIFY 0x00000002 /* File modified. */ +# define DN_CREATE 0x00000004 /* File created. */ +# define DN_DELETE 0x00000008 /* File removed. */ +# define DN_RENAME 0x00000010 /* File renamed. */ +# define DN_ATTRIB 0x00000020 /* File changed attibutes. */ +# define DN_MULTISHOT 0x80000000 /* Don't remove notifier. */ +#endif + +struct flock + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ +#ifndef __USE_FILE_OFFSET64 + __off_t l_start; /* Offset where the lock begins. */ + __off_t l_len; /* Size of the locked area; zero means until EOF. */ +#else + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ +#endif + __pid_t l_pid; /* Process holding the lock. */ + }; + +#ifdef __USE_LARGEFILE64 +struct flock64 + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ + __pid_t l_pid; /* Process holding the lock. */ + }; +#endif + +/* Define some more compatibility macros to be backward compatible with + BSD systems which did not managed to hide these kernel macros. */ +#ifdef __USE_BSD +# define FAPPEND O_APPEND +# define FFSYNC O_FSYNC +# define FASYNC O_ASYNC +# define FNONBLOCK O_NONBLOCK +# define FNDELAY O_NDELAY +#endif /* Use BSD. */ + +/* Advise to `posix_fadvise'. */ +#ifdef __USE_XOPEN2K +# define POSIX_FADV_NORMAL 0 /* No further special treatment. */ +# define POSIX_FADV_RANDOM 1 /* Expect random page references. */ +# define POSIX_FADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define POSIX_FADV_WILLNEED 3 /* Will need these pages. */ +# define POSIX_FADV_DONTNEED 4 /* Don't need these pages. */ +# define POSIX_FADV_NOREUSE 5 /* Data will be accessed once. */ +#endif + + +#if defined __USE_GNU && defined __UCLIBC_LINUX_SPECIFIC__ +/* Flags for SYNC_FILE_RANGE. */ +# define SYNC_FILE_RANGE_WAIT_BEFORE 1 /* Wait upon writeout of all pages + in the range before performing the + write. */ +# define SYNC_FILE_RANGE_WRITE 2 /* Initiate writeout of all those + dirty pages in the range which are + not presently under writeback. */ +# define SYNC_FILE_RANGE_WAIT_AFTER 4 /* Wait upon writeout of all pages in + the range after performing the + write. */ + +/* Flags for SPLICE and VMSPLICE. */ +# define SPLICE_F_MOVE 1 /* Move pages instead of copying. */ +# define SPLICE_F_NONBLOCK 2 /* Don't block on the pipe splicing + (but we may still block on the fd + we splice from/to). */ +# define SPLICE_F_MORE 4 /* Expect more data. */ +# define SPLICE_F_GIFT 8 /* Pages passed in are a gift. */ +#endif + +__BEGIN_DECLS + +#if defined __USE_GNU && defined __UCLIBC_LINUX_SPECIFIC__ + +/* Provide kernel hint to read ahead. */ +extern ssize_t readahead (int __fd, __off64_t __offset, size_t __count) + __THROW; + + +/* Selective file content synch'ing. */ +extern int sync_file_range (int __fd, __off64_t __from, __off64_t __to, + unsigned int __flags); + +/* Splice address range into a pipe. */ +extern ssize_t vmsplice (int __fdout, const struct iovec *__iov, + size_t __count, unsigned int __flags); + +/* Splice two files together. */ +extern ssize_t splice (int __fdin, __off64_t *__offin, int __fdout, + __off64_t *__offout, size_t __len, + unsigned int __flags); + +/* In-kernel implementation of tee for pipe buffers. */ +extern ssize_t tee (int __fdin, int __fdout, size_t __len, + unsigned int __flags); + +#endif +__END_DECLS + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/bits/kernel_stat.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/bits/kernel_stat.h new file mode 100644 index 00000000..2b432cf5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/bits/kernel_stat.h @@ -0,0 +1,54 @@ +#ifndef _BITS_STAT_STRUCT_H +#define _BITS_STAT_STRUCT_H + +#ifndef _LIBC +#error bits/kernel_stat.h is for internal uClibc use only! +#endif + +/* This file provides whatever this particular arch's kernel thinks + * struct kernel_stat should look like... It turns out each arch has a + * different opinion on the subject... */ + +struct kernel_stat { + unsigned short st_dev; + unsigned short __pad1; + unsigned long st_ino; + unsigned short st_mode; + unsigned short st_nlink; + unsigned short st_uid; + unsigned short st_gid; + unsigned short st_rdev; + unsigned short __pad2; + unsigned long st_size; + unsigned long st_blksize; + unsigned long st_blocks; + struct timespec st_atim; + struct timespec st_mtim; + struct timespec st_ctim; + unsigned long __unused4; + unsigned long __unused5; +}; + +struct kernel_stat64 { + unsigned short st_dev; + unsigned char __pad0[10]; +#define _HAVE_STAT64___ST_INO + unsigned long __st_ino; + unsigned int st_mode; + unsigned int st_nlink; + unsigned long st_uid; + unsigned long st_gid; + unsigned short st_rdev; + unsigned char __pad3[10]; + long long st_size; + unsigned long st_blksize; + unsigned long st_blocks; /* Number 512-byte blocks allocated. */ + unsigned long __pad4; /* future possible st_blocks high bits */ + struct timespec st_atim; + struct timespec st_mtim; + struct timespec st_ctim; + unsigned long long st_ino; +}; + +#endif /* _BITS_STAT_STRUCT_H */ + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/bits/kernel_types.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/bits/kernel_types.h new file mode 100644 index 00000000..3fcd1af0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/bits/kernel_types.h @@ -0,0 +1,44 @@ +/* Note that we use the exact same include guard #define names + * as asm/posix_types.h. This will avoid gratuitous conflicts + * with the posix_types.h kernel header, and will ensure that + * our private content, and not the kernel header, will win. + * -Erik + */ +#ifndef __ARCH_NIOS2_POSIX_TYPES_H +#define __ARCH_NIOS2_POSIX_TYPES_H + +typedef unsigned long __kernel_dev_t; +typedef unsigned long __kernel_ino_t; +typedef unsigned short __kernel_mode_t; +typedef unsigned short __kernel_nlink_t; +typedef long __kernel_off_t; +typedef int __kernel_pid_t; +typedef unsigned short __kernel_ipc_pid_t; +typedef unsigned short __kernel_uid_t; +typedef unsigned short __kernel_gid_t; +typedef unsigned int __kernel_size_t; +typedef int __kernel_ssize_t; +typedef int __kernel_ptrdiff_t; +typedef long __kernel_time_t; +typedef long __kernel_suseconds_t; +typedef long __kernel_clock_t; +typedef int __kernel_daddr_t; +typedef char * __kernel_caddr_t; +typedef unsigned short __kernel_uid16_t; +typedef unsigned short __kernel_gid16_t; +typedef unsigned int __kernel_uid32_t; +typedef unsigned int __kernel_gid32_t; +typedef unsigned short __kernel_old_uid_t; +typedef unsigned short __kernel_old_gid_t; +typedef unsigned short __kernel_old_dev_t; +typedef long long __kernel_loff_t; + +typedef struct { +#ifdef __USE_ALL + int val[2]; +#else + int __val[2]; +#endif +} __kernel_fsid_t; + +#endif /* __ARCH_NIOS2_POSIX_TYPES_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/bits/mathdef.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/bits/mathdef.h new file mode 100644 index 00000000..e013e74b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/bits/mathdef.h @@ -0,0 +1,44 @@ +/* Copyright (C) 1999, 2000, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#if !defined _MATH_H && !defined _COMPLEX_H +# error "Never use directly; include instead" +#endif + +#if defined __USE_ISOC99 && defined _MATH_H && !defined _MATH_H_MATHDEF +# define _MATH_H_MATHDEF 1 + +/* GCC does not promote `float' values to `double'. */ +typedef float float_t; /* `float' expressions are evaluated as + `float'. */ +typedef double double_t; /* `double' expressions are evaluated as + `double'. */ + +/* The values returned by `ilogb' for 0 and NaN respectively. */ +# define FP_ILOGB0 (-2147483647) +# define FP_ILOGBNAN (2147483647) + +#endif /* ISO C99 */ + +#ifndef __NO_LONG_DOUBLE_MATH +/* Signal that we do not really have a `long double'. This disables the + declaration of all the `long double' function variants. */ +/* XXX The FPA does support this but the patterns in GCC are currently + turned off. */ +# define __NO_LONG_DOUBLE_MATH 1 +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/bits/setjmp.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/bits/setjmp.h new file mode 100644 index 00000000..fcff0316 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/bits/setjmp.h @@ -0,0 +1,72 @@ +/* Define the machine-dependent type `jmp_buf'. Nios2 version. + Copyright (C) 1992,93,95,97,2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _BITS_SETJMP_H +#define _BITS_SETJMP_H 1 + +#if !defined _SETJMP_H && !defined _PTHREAD_H +# error "Never include directly; use instead." +#endif + +#ifndef _ASM +typedef struct +{ + /* Callee-saved registers r16 through r23. */ + unsigned long __regs[8]; + + /* Program counter. */ + unsigned long __pc; + + /* Stack pointer. */ + unsigned long __sp; + + /* The frame pointer. */ + unsigned long __fp; + + /* The global pointer. */ + unsigned long __gp; + + /* floating point regs, if any */ +#if defined __HAVE_FPU__ + unsigned long __fpregs[64]; +#endif +} __jmp_buf[1]; + +#endif + +#define JB_REGS 0 +#define JB_PC 32 +#define JB_SP 36 +#define JB_FP 40 +#define JB_GP 44 +#define JB_FPREGS 48 + +#if defined __HAVE_FPU__ +# define JB_SIZE 304 +#else +# define JB_SIZE 48 +#endif + + +/* Test if longjmp to JMPBUF would unwind the frame + containing a local variable at ADDRESS. */ +#define _JMPBUF_UNWINDS(jmpbuf, address) \ + ((void *) (address) < (void*)(jmpbuf)->__sp) + +#endif /* bits/setjmp.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/bits/sigcontextinfo.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/bits/sigcontextinfo.h new file mode 100644 index 00000000..d6383b97 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/bits/sigcontextinfo.h @@ -0,0 +1,26 @@ +/* Copyright (C) 1998, 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Andreas Schwab , 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define SIGCONTEXT struct sigcontext * +#define SIGCONTEXT_EXTRA_ARGS +#define GET_PC(ctx) ((void *) (ctx)->regs.ea) +#define GET_FRAME(ctx) ((void *) (ctx)->regs.sp) +#define GET_STACK(ctx) ((void *) (ctx)->regs.fp) +#define CALL_SIGHANDLER(handler, signo, ctx) \ + (handler)((signo), SIGCONTEXT_EXTRA_ARGS (ctx)) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/bits/stackinfo.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/bits/stackinfo.h new file mode 100644 index 00000000..e7fbf563 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/bits/stackinfo.h @@ -0,0 +1,28 @@ +/* Copyright (C) 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This file contains a bit of information about the stack allocation + of the processor. */ + +#ifndef _STACKINFO_H +#define _STACKINFO_H 1 + +/* On nios II the stack grows down. */ +#define _STACK_GROWS_DOWN 1 + +#endif /* stackinfo.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/bits/stat.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/bits/stat.h new file mode 100644 index 00000000..d380eeed --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/bits/stat.h @@ -0,0 +1,168 @@ +/* Copyright (C) 1992,95,96,97,98,99,2000,2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_STAT_H +# error "Never include directly; use instead." +#endif + +/* Versions of the `struct stat' data structure. */ +#define _STAT_VER_LINUX_OLD 1 +#define _STAT_VER_KERNEL 1 +#define _STAT_VER_SVR4 2 +#define _STAT_VER_LINUX 3 +#define _STAT_VER _STAT_VER_LINUX /* The one defined below. */ + +/* Versions of the `xmknod' interface. */ +#define _MKNOD_VER_LINUX 1 +#define _MKNOD_VER_SVR4 2 +#define _MKNOD_VER _MKNOD_VER_LINUX /* The bits defined below. */ + + +struct stat + { + __dev_t st_dev; /* Device. */ + unsigned short int __pad1; +#ifndef __USE_FILE_OFFSET64 + __ino_t st_ino; /* File serial number. */ +#else + __ino_t __st_ino; /* 32bit file serial number. */ +#endif + __mode_t st_mode; /* File mode. */ + __nlink_t st_nlink; /* Link count. */ + __uid_t st_uid; /* User ID of the file's owner. */ + __gid_t st_gid; /* Group ID of the file's group.*/ + __dev_t st_rdev; /* Device number, if device. */ + unsigned short int __pad2; +#ifndef __USE_FILE_OFFSET64 + __off_t st_size; /* Size of file, in bytes. */ +#else + __off64_t st_size; /* Size of file, in bytes. */ +#endif + __blksize_t st_blksize; /* Optimal block size for I/O. */ + +#ifndef __USE_FILE_OFFSET64 + __blkcnt_t st_blocks; /* Number 512-byte blocks allocated. */ +#else + __blkcnt64_t st_blocks; /* Number 512-byte blocks allocated. */ +#endif +#ifdef __USE_MISC + /* Nanosecond resolution timestamps are stored in a format + equivalent to 'struct timespec'. This is the type used + whenever possible but the Unix namespace rules do not allow the + identifier 'timespec' to appear in the header. + Therefore we have to handle the use of this header in strictly + standard-compliant sources special. */ + struct timespec st_atim; /* Time of last access. */ + struct timespec st_mtim; /* Time of last modification. */ + struct timespec st_ctim; /* Time of last status change. */ +# define st_atime st_atim.tv_sec /* Backward compatibility. */ +# define st_mtime st_mtim.tv_sec +# define st_ctime st_ctim.tv_sec +#else + __time_t st_atime; /* Time of last access. */ + unsigned long int st_atimensec; /* Nscecs of last access. */ + __time_t st_mtime; /* Time of last modification. */ + unsigned long int st_mtimensec; /* Nsecs of last modification. */ + __time_t st_ctime; /* Time of last status change. */ + unsigned long int st_ctimensec; /* Nsecs of last status change. */ +#endif +#ifndef __USE_FILE_OFFSET64 + unsigned long int __unused4; + unsigned long int __unused5; +#else + __ino64_t st_ino; /* File serial number. */ +#endif + }; + +#ifdef __USE_LARGEFILE64 +struct stat64 + { + __dev_t st_dev; /* Device. */ + unsigned int __pad1; + + __ino_t __st_ino; /* 32bit file serial number. */ + __mode_t st_mode; /* File mode. */ + __nlink_t st_nlink; /* Link count. */ + __uid_t st_uid; /* User ID of the file's owner. */ + __gid_t st_gid; /* Group ID of the file's group.*/ + __dev_t st_rdev; /* Device number, if device. */ + unsigned int __pad2; + __off64_t st_size; /* Size of file, in bytes. */ + __blksize_t st_blksize; /* Optimal block size for I/O. */ + + __blkcnt64_t st_blocks; /* Number 512-byte blocks allocated. */ +#ifdef __USE_MISC + /* Nanosecond resolution timestamps are stored in a format + equivalent to 'struct timespec'. This is the type used + whenever possible but the Unix namespace rules do not allow the + identifier 'timespec' to appear in the header. + Therefore we have to handle the use of this header in strictly + standard-compliant sources special. */ + struct timespec st_atim; /* Time of last access. */ + struct timespec st_mtim; /* Time of last modification. */ + struct timespec st_ctim; /* Time of last status change. */ +#else + __time_t st_atime; /* Time of last access. */ + unsigned long int st_atimensec; /* Nscecs of last access. */ + __time_t st_mtime; /* Time of last modification. */ + unsigned long int st_mtimensec; /* Nsecs of last modification. */ + __time_t st_ctime; /* Time of last status change. */ + unsigned long int st_ctimensec; /* Nsecs of last status change. */ +#endif + __ino64_t st_ino; /* File serial number. */ + }; +#endif + +/* Tell code we have these members. */ +#define _STATBUF_ST_BLKSIZE +#define _STATBUF_ST_RDEV +/* Nanosecond resolution time values are supported. */ +#define _STATBUF_ST_NSEC + +/* Encoding of the file mode. */ + +#define __S_IFMT 0170000 /* These bits determine file type. */ + +/* File types. */ +#define __S_IFDIR 0040000 /* Directory. */ +#define __S_IFCHR 0020000 /* Character device. */ +#define __S_IFBLK 0060000 /* Block device. */ +#define __S_IFREG 0100000 /* Regular file. */ +#define __S_IFIFO 0010000 /* FIFO. */ +#define __S_IFLNK 0120000 /* Symbolic link. */ +#define __S_IFSOCK 0140000 /* Socket. */ + +/* POSIX.1b objects. Note that these macros always evaluate to zero. But + they do it by enforcing the correct use of the macros. */ +#define __S_TYPEISMQ(buf) ((buf)->st_mode - (buf)->st_mode) +#define __S_TYPEISSEM(buf) ((buf)->st_mode - (buf)->st_mode) +#define __S_TYPEISSHM(buf) ((buf)->st_mode - (buf)->st_mode) + +/* Protection bits. */ + +#define __S_ISUID 04000 /* Set user ID on execution. */ +#define __S_ISGID 02000 /* Set group ID on execution. */ +#define __S_ISVTX 01000 /* Save swapped text after use (sticky). */ +#define __S_IREAD 0400 /* Read by owner. */ +#define __S_IWRITE 0200 /* Write by owner. */ +#define __S_IEXEC 0100 /* Execute by owner. */ + +#ifdef __USE_ATFILE +# define UTIME_NOW ((1l << 30) - 1l) +# define UTIME_OMIT ((1l << 30) - 2l) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/bits/syscalls.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/bits/syscalls.h new file mode 100644 index 00000000..f80bea20 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/bits/syscalls.h @@ -0,0 +1,106 @@ +#ifndef _BITS_SYSCALLS_H +#define _BITS_SYSCALLS_H +#ifndef _SYSCALL_H +# error "Never use directly; include instead." +#endif + +#ifndef __ASSEMBLER__ + +#include +#include + +#define __syscall_return(type, res) \ + do { \ + if (unlikely(INTERNAL_SYSCALL_ERROR_P(res, ))) { \ + __set_errno(INTERNAL_SYSCALL_ERRNO(res, )); \ + res = (unsigned long) -1; \ + } \ + return (type) (res); \ + } while (0) + +#define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \ + ({ \ + long __res; \ + __asm__ __volatile__ ( \ + "movi r2, %2\n\t" /* TRAP_ID_SYSCALL */ \ + "movi r3, %1\n\t" /* __NR_##name */ \ + ASM_ARGS_##nr \ + "trap\n\t" \ + "mov %0, r2\n\t" /* syscall return */ \ + : "=r" (__res) /* %0 */ \ + : "i" (name) /* %1 */ \ + , "i" (TRAP_ID_SYSCALL) /* %2 */ \ + MAP_ARGS_##nr (args) /* %3-%8 */ \ + : "r2" \ + , "r3" \ + CLOB_ARGS_##nr /* Clobbered */ \ + ); \ + __res; \ + }) + +#define INTERNAL_SYSCALL_ERROR_P(val, err) \ + ((unsigned long)(val) >= (unsigned long)(-125)) + +#define ASM_ARGS_0 +#define MAP_ARGS_0() +#define CLOB_ARGS_0 + +#define ASM_ARGS_1 \ + "mov r4, %3\n\t" +#define MAP_ARGS_1(a) \ + , "r" ((long) a) +#define CLOB_ARGS_1 \ + , "r4" + +#define ASM_ARGS_2 \ + ASM_ARGS_1 \ + "mov r5, %4\n\t" +#define MAP_ARGS_2(a, b) \ + MAP_ARGS_1(a) \ + , "r" ((long) b) +#define CLOB_ARGS_2 \ + CLOB_ARGS_1 \ + , "r5" + +#define ASM_ARGS_3 \ + ASM_ARGS_2 \ + "mov r6, %5\n\t" +#define MAP_ARGS_3(a, b, c) \ + MAP_ARGS_2(a, b) \ + , "r" ((long) c) +#define CLOB_ARGS_3 \ + CLOB_ARGS_2 \ + , "r6" + +#define ASM_ARGS_4 \ + ASM_ARGS_3 \ + "mov r7, %6\n\t" +#define MAP_ARGS_4(a, b, c, d) \ + MAP_ARGS_3(a, b, c) \ + , "r" ((long) d) +#define CLOB_ARGS_4 \ + CLOB_ARGS_3 \ + , "r7" + +#define ASM_ARGS_5 \ + ASM_ARGS_4 \ + "mov r8, %7\n\t" +#define MAP_ARGS_5(a, b, c, d, e) \ + MAP_ARGS_4(a, b, c, d) \ + , "r" ((long) e) +#define CLOB_ARGS_5 \ + CLOB_ARGS_4 \ + , "r8" + +#define ASM_ARGS_6 \ + ASM_ARGS_5 \ + "mov r9, %8\n\t" +#define MAP_ARGS_6(a, b, c, d, e, f) \ + MAP_ARGS_5(a, b, c, d, e) \ + , "r" ((long) f) +#define CLOB_ARGS_6 \ + CLOB_ARGS_5 \ + , "r9" + +#endif /* __ASSEMBLER__ */ +#endif /* _BITS_SYSCALLS_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/bits/uClibc_arch_features.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/bits/uClibc_arch_features.h new file mode 100644 index 00000000..2a9422e2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/bits/uClibc_arch_features.h @@ -0,0 +1,48 @@ +/* + * Track misc arch-specific features that aren't config options + */ + +#ifndef _BITS_UCLIBC_ARCH_FEATURES_H +#define _BITS_UCLIBC_ARCH_FEATURES_H + +/* instruction used when calling abort() to kill yourself */ +/*#define __UCLIBC_ABORT_INSTRUCTION__ "asm instruction"*/ +#undef __UCLIBC_ABORT_INSTRUCTION__ + +/* can your target use syscall6() for mmap ? */ +#undef __UCLIBC_MMAP_HAS_6_ARGS__ + +/* does your target use syscall4() for truncate64 ? (32bit arches only) */ +#undef __UCLIBC_TRUNCATE64_HAS_4_ARGS__ + +/* does your target have a broken create_module() ? */ +#undef __UCLIBC_BROKEN_CREATE_MODULE__ + +/* does your target have to worry about older [gs]etrlimit() ? */ +#undef __UCLIBC_HANDLE_OLDER_RLIMIT__ + +/* does your target have an asm .set ? */ +#define __UCLIBC_HAVE_ASM_SET_DIRECTIVE__ + +/* define if target doesn't like .global */ +#undef __UCLIBC_ASM_GLOBAL_DIRECTIVE__ + +/* define if target supports .weak */ +#define __UCLIBC_HAVE_ASM_WEAK_DIRECTIVE__ + +/* define if target supports .weakext */ +#undef __UCLIBC_HAVE_ASM_WEAKEXT_DIRECTIVE__ + +/* needed probably only for ppc64 */ +#undef __UCLIBC_HAVE_ASM_GLOBAL_DOT_NAME__ + +/* define if target supports CFI pseudo ops */ +#undef __UCLIBC_HAVE_ASM_CFI_DIRECTIVES__ + +/* define if target supports IEEE signed zero floats */ +#define __UCLIBC_HAVE_SIGNED_ZERO__ + +/* only weird assemblers generally need this */ +#undef __UCLIBC_ASM_LINE_SEP__ + +#endif /* _BITS_UCLIBC_ARCH_FEATURES_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/bits/uClibc_page.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/bits/uClibc_page.h new file mode 100644 index 00000000..311dd40a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/bits/uClibc_page.h @@ -0,0 +1,29 @@ +/* Copyright (C) 2004 Erik Andersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * The GNU C Library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the GNU C Library; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 USA. + */ + +/* Supply an architecture specific value for PAGE_SIZE and friends. */ + +#ifndef _UCLIBC_PAGE_H +#define _UCLIBC_PAGE_H + +/* PAGE_SHIFT determines the page size -- in this case 4096 */ +#define PAGE_SHIFT (12) +#define PAGE_SIZE (1UL << PAGE_SHIFT) +#define PAGE_MASK (~(PAGE_SIZE-1)) + +#endif /* _UCLIBC_PAGE_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/bits/wordsize.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/bits/wordsize.h new file mode 100644 index 00000000..ba643b60 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/bits/wordsize.h @@ -0,0 +1,19 @@ +/* Copyright (C) 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define __WORDSIZE 32 diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/brk.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/brk.c new file mode 100644 index 00000000..24bd719b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/brk.c @@ -0,0 +1,45 @@ +/* brk system call for Linux/Nios2. + Copyright (C) 1995, 1996, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +/* This must be initialized data because commons can't have aliases. */ +void *__curbrk attribute_hidden = 0; + +int brk (void *addr) +{ + void *newbrk; + register int r2 __asm__("r2") = TRAP_ID_SYSCALL; + register int r3 __asm__("r3") = __NR_brk; + register void *r4 __asm__("r4") = addr; + + __asm__ __volatile__ ("trap\n\t" : "=r"(newbrk) : "0"(r2), "r"(r3), "r"(r4)); + + __curbrk = newbrk; + + if (newbrk < addr) { + __set_errno (ENOMEM); + return -1; + } + + return 0; +} +libc_hidden_def(brk) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/bsd-_setjmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/bsd-_setjmp.S new file mode 100644 index 00000000..ed4061cd --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/bsd-_setjmp.S @@ -0,0 +1,45 @@ +/* + * libc/sysdeps/linux/nios2/bsd-_setjmp.S + * + * Copyright (C) 2004,05,06 Microtronix Datacom Ltd + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + * + * Written by Wentao Xu + * + */ + +#define _ASM +#define _SETJMP_H +#include + + .globl _setjmp + .type _setjmp,@function + .balign 4 + +_setjmp: + stw r16, (JB_REGS+ 0)(r4) + stw r17, (JB_REGS+ 4)(r4) + stw r18, (JB_REGS+ 8)(r4) + stw r19, (JB_REGS+12)(r4) + stw r20, (JB_REGS+16)(r4) + stw r21, (JB_REGS+20)(r4) + stw r22, (JB_REGS+24)(r4) + stw r23, (JB_REGS+28)(r4) + + stw ra, JB_PC(r4) + stw sp, JB_SP(r4) + stw fp, JB_FP(r4) + stw gp, JB_GP(r4) + +#if defined(__HAVE_FPU__) + SAVE_FPU r4 JB_FPREGS +#endif + stw r0, JB_SIZE(r4) /* signal mask is not saved */ + mov r2, zero + ret + + + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/bsd-setjmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/bsd-setjmp.S new file mode 100644 index 00000000..ac99bfe0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/bsd-setjmp.S @@ -0,0 +1,52 @@ +/* + * libc/sysdeps/linux/nios2/bsd-setjmp.S + * + * Copyright (C) 2004,05,06 Microtronix Datacom Ltd + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + * + * Written by Wentao Xu + * + */ + + +#define _ASM +#define _SETJMP_H +#include + + .globl setjmp + .type setjmp,@function + .balign 4 + +setjmp: + stw r16, (JB_REGS+ 0)(r4) + stw r17, (JB_REGS+ 4)(r4) + stw r18, (JB_REGS+ 8)(r4) + stw r19, (JB_REGS+12)(r4) + stw r20, (JB_REGS+16)(r4) + stw r21, (JB_REGS+20)(r4) + stw r22, (JB_REGS+24)(r4) + stw r23, (JB_REGS+28)(r4) + + stw ra, JB_PC(r4) + stw sp, JB_SP(r4) + stw fp, JB_FP(r4) + stw gp, JB_GP(r4) + +#if defined(__HAVE_FPU__) + SAVE_FPU r4 JB_FPREGS +#endif + + movui r5, 1 +#ifdef __PIC__ + /* just pray 16 bit offset is enough */ + br __sigjmp_save +#else + movhi r8, %hi(__sigjmp_save) + ori r8, r8, %lo(__sigjmp_save) + jmp r8 +#endif + + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/clone.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/clone.S new file mode 100644 index 00000000..4afcb7d7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/clone.S @@ -0,0 +1,70 @@ +/* + * libc/sysdeps/linux/nios2/clone.S -- `clone' syscall for linux/nios2 + * + * Copyright (C) 2004 Microtronix Datacom Ltd + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + * + * Written by Wentao Xu + */ + +#define _ERRNO_H +#include +#include + +#ifdef __NR_clone +/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg); */ + +.text +.global clone +.type clone,%function +.align 4 +clone: + addi sp,sp,-8 + mov r8,r4 + stw ra,4(sp) + stw r16,0(sp) + + mov r4,r6 + movi r2,-EINVAL + + /* sanity check */ + beq r8,zero,CLONE_ERROR_LABEL + beq r5,zero,CLONE_ERROR_LABEL + + /* system call */ + movi r2,TRAP_ID_SYSCALL + movi r3,__NR_clone + trap + + /* child call the function */ + mov r4,r7 + bne r2,zero,CLONE_ERROR_LABEL + callr r8 + + /* exit if it returns */ + mov r4,r2 + movi r3,__NR_exit + trap + +CLONE_ERROR_LABEL: + movi r3,-4096 + sub r16,zero,r2 + bgeu r3,r2,CLONE_OK + + /* store errno */ + call __errno_location + stw r16,0(r2) + movi r2,-1 + +CLONE_OK: + ldw ra,4(sp) + ldw r16,0(sp) + addi sp,sp,8 + ret + +.size clone,.-clone + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/clone.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/clone.c new file mode 100644 index 00000000..eec9f42f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/clone.c @@ -0,0 +1,50 @@ +/* + * libc/sysdeps/linux/nios2/clone.c -- `clone' syscall for linux/nios2 + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * + * Copyright (C) 2004,05 Microtronix Datacom Ltd + * Copyright (C) 2002,03 NEC Electronics Corporation + * Copyright (C) 2002,03 Miles Bader + * + * Written by Miles Bader + * Nios2 port by Wentao Xu + */ + +#include +#include +#include + +int clone (int (*fn)(void *arg), void *child_stack, int flags, void *arg, ...) +{ + register unsigned long rval __asm__ ("r2") = -EINVAL; + + if (fn && child_stack) { + register unsigned long syscall __asm__ ("r3"); + register unsigned long arg0 __asm__ ("r4"); + register unsigned long arg1 __asm__ ("r5"); + + /* Clone this thread. */ + rval = TRAP_ID_SYSCALL; + syscall = __NR_clone; + arg0 = flags; + arg1 = (unsigned long)child_stack; + __asm__ __volatile__ ("trap " + : "=r" (rval), "=r" (syscall) + : "0" (rval),"1" (syscall), "r" (arg0), "r" (arg1) + ); + + if (rval == 0) { + /* In child thread, call fn and exit. */ + arg0 = (*fn) (arg); + syscall = __NR_exit; + __asm__ __volatile__ ("trap " + : "=r" (rval), "=r" (syscall) + : "1" (syscall), "r" (arg0)); + } + } + + __syscall_return (int, rval); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/crt1.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/crt1.S new file mode 100644 index 00000000..0ba8d59e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/crt1.S @@ -0,0 +1,73 @@ +/* + * libc/sysdeps/linux/nios2/crt0.S -- entry point for linux/nios2 + * + * Copyright (C) 2004,05,06 Microtronix Datacom Ltd + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + * + * Written by Wentao Xu + * Updated by Thomas Chou for crt1.S + * + */ + +#include +#include + + .global _start + .type _start,@function + .type _init,%function + .type _fini,%function +#ifndef __UCLIBC_CTOR_DTOR__ + .weak _init + .weak _fini +#endif + .type main,@function + .type __uClibc_main,@function + .type __h_errno_location, @function + .type _stdio_init, @function + .type _stdio_term, @function + .text + .balign 4 +_start: + nop + br 0f +0: + /* load gp */ + movhi gp, %hiadj(_gp) + addi gp, gp, %lo(_gp) + + /* load main, argc, argv from stack */ + movhi r4, %hi(main) + ori r4, r4, %lo(main) /* main */ + ldw r5, 0(sp) /* argc */ + ldw r6, 4(sp) /* argv */ + + /* load the 4th arg */ + movhi r7, %hi(_init) + ori r7, r7, %lo(_init) + + /* Allocate space on the stack for 6-7th arg, reuse 5th space */ + addi sp,sp,-8 + /* push 5-7th args on stack */ + movhi r8, %hi(_fini) + ori r8, r8, %lo(_fini) + stw r8, 0(sp) + + stw r2, 4(sp) /* rtld_fini */ + stw sp, 8(sp) /* stack_end */ + + /* call uClibc_main, shouldn't return */ +#ifdef __PIC__ + /* just pray 16 bit offset is enough */ + br __uClibc_main +#else + call __uClibc_main +#endif + + /* crash in the event of return */ +__exit: + movui r2, TRAP_ID_SYSCALL + movui r3, __NR_exit + trap diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/crti.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/crti.S new file mode 100644 index 00000000..26c55c97 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/crti.S @@ -0,0 +1,22 @@ + + .section .init + .balign 4 + .global _init + .type _init, @function +_init: + addi sp, sp, -8 + stw ra, 0(sp) + stw fp, 4(sp) + + .balign 4 + + + .section .fini + .balign 4 + .global _fini + .type _fini, @function +_fini: + addi sp, sp, -8 + stw ra, 0(sp) + stw fp, 4(sp) + .balign 4 diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/crtn.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/crtn.S new file mode 100644 index 00000000..de00fd13 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/crtn.S @@ -0,0 +1,14 @@ + + .section .init + + ldw ra, 0(sp) + ldw fp, 4(sp) + addi sp, sp, 8 + ret + + .section .fini + + ldw ra, 0(sp) + ldw fp, 4(sp) + addi sp, sp, 8 + ret diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/fpu_control.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/fpu_control.h new file mode 100644 index 00000000..9c317457 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/fpu_control.h @@ -0,0 +1,99 @@ +/* FPU control word bits. Nios2 version. + Copyright (C) 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FPU_CONTROL_H +#define _FPU_CONTROL_H + +/* MIPS FPU floating point control register bits. + * + * 31-25 -> floating point conditions code bits 7-1. These bits are only + * available in MIPS IV. + * 24 -> flush denormalized results to zero instead of + * causing unimplemented operation exception. This bit is only + * available for MIPS III and newer. + * 23 -> Condition bit + * 22-18 -> reserved (read as 0, write with 0) + * 17 -> cause bit for unimplemented operation + * 16 -> cause bit for invalid exception + * 15 -> cause bit for division by zero exception + * 14 -> cause bit for overflow exception + * 13 -> cause bit for underflow exception + * 12 -> cause bit for inexact exception + * 11 -> enable exception for invalid exception + * 10 -> enable exception for division by zero exception + * 9 -> enable exception for overflow exception + * 8 -> enable exception for underflow exception + * 7 -> enable exception for inexact exception + * 6 -> flag invalid exception + * 5 -> flag division by zero exception + * 4 -> flag overflow exception + * 3 -> flag underflow exception + * 2 -> flag inexact exception + * 1-0 -> rounding control + * + * + * Rounding Control: + * 00 - rounding to nearest (RN) + * 01 - rounding toward zero (RZ) + * 10 - rounding (up) toward plus infinity (RP) + * 11 - rounding (down)toward minus infinity (RM) + */ + +#include + +/* masking of interrupts */ +#define _FPU_MASK_V 0x0800 /* Invalid operation */ +#define _FPU_MASK_Z 0x0400 /* Division by zero */ +#define _FPU_MASK_O 0x0200 /* Overflow */ +#define _FPU_MASK_U 0x0100 /* Underflow */ +#define _FPU_MASK_I 0x0080 /* Inexact operation */ + +/* flush denormalized numbers to zero */ +#define _FPU_FLUSH_TZ 0x1000000 + +/* rounding control */ +#define _FPU_RC_NEAREST 0x0 /* RECOMMENDED */ +#define _FPU_RC_ZERO 0x1 +#define _FPU_RC_UP 0x2 +#define _FPU_RC_DOWN 0x3 + +#define _FPU_RESERVED 0xfe3c0000 /* Reserved bits in cw */ + + +/* The fdlibm code requires strict IEEE double precision arithmetic, + and no interrupts for exceptions, rounding to nearest. */ + +#define _FPU_DEFAULT 0x00000000 + +/* IEEE: same as above, but exceptions */ +#define _FPU_IEEE 0x00000F80 + +/* Type of the control word. */ +typedef unsigned int fpu_control_t __attribute__ ((__mode__ (__SI__))); + +/* Macros for accessing the hardware control word. */ +#define _FPU_GETCW(cw) __asm__ ("cfc1 %0,$31" : "=r" (cw)) +#define _FPU_SETCW(cw) __asm__ ("ctc1 %0,$31" : : "r" (cw)) + +#if 0 +/* Default control word set at startup. */ +extern fpu_control_t __fpu_control; +#endif + +#endif /* fpu_control.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/setjmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/setjmp.S new file mode 100644 index 00000000..8acd2204 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/setjmp.S @@ -0,0 +1,51 @@ +/* + * libc/sysdeps/linux/nios2/setjmp.S + * + * Copyright (C) 2004,05,06 Microtronix Datacom Ltd + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + * + * Written by Wentao Xu + * + */ + +#include +#define _ASM +#define _SETJMP_H +#include + +.globl __sigsetjmp +.type __sigsetjmp,@function +.balign 4 + +__sigsetjmp: + stw r16, (JB_REGS+ 0)(r4) + stw r17, (JB_REGS+ 4)(r4) + stw r18, (JB_REGS+ 8)(r4) + stw r19, (JB_REGS+12)(r4) + stw r20, (JB_REGS+16)(r4) + stw r21, (JB_REGS+20)(r4) + stw r22, (JB_REGS+24)(r4) + stw r23, (JB_REGS+28)(r4) + + stw ra, JB_PC(r4) + stw sp, JB_SP(r4) + stw fp, JB_FP(r4) + stw gp, JB_GP(r4) + +#if defined(__HAVE_FPU__) + SAVE_FPU r4 JB_FPREGS +#endif + +#ifdef __PIC__ + /* just pray 16 bit offset is enough */ + br __sigjmp_save +#else + movhi r8, %hi(__sigjmp_save) + ori r8, r8, %lo(__sigjmp_save) + jmp r8 +#endif + +.size __sigsetjmp,.-__sigsetjmp diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/sys/procfs.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/sys/procfs.h new file mode 100644 index 00000000..8cbaa41c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/sys/procfs.h @@ -0,0 +1,123 @@ +/* Copyright (C) 1996, 1997, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_PROCFS_H +#define _SYS_PROCFS_H 1 + +/* This is somehow modelled after the file of the same name on SysVr4 + systems. It provides a definition of the core file format for ELF + used on Linux. */ + +#include +#include +#include +#include +#include +#include +#include + +__BEGIN_DECLS + +#define ELF_NGREG 38 + +typedef struct + { + union + { + unsigned long pr_regs[32]; + double pr_dregs[16]; + } pr_fr; + unsigned long __unused; + unsigned long pr_fsr; + unsigned char pr_qcnt; + unsigned char pr_q_entrysize; + unsigned char pr_en; + unsigned int pr_q[64]; + } elf_fpregset_t; + +typedef unsigned long elf_greg_t; +typedef elf_greg_t elf_gregset_t[ELF_NGREG]; + +struct elf_siginfo + { + int si_signo; /* Signal number. */ + int si_code; /* Extra code. */ + int si_errno; /* Errno. */ + }; + +/* Definitions to generate Intel SVR4-like core files. These mostly + have the same names as the SVR4 types with "elf_" tacked on the + front to prevent clashes with linux definitions, and the typedef + forms have been avoided. This is mostly like the SVR4 structure, + but more Linuxy, with things that Linux does not support and which + gdb doesn't really use excluded. Fields present but not used are + marked with "XXX". */ +struct elf_prstatus + { + struct elf_siginfo pr_info; /* Info associated with signal. */ + short int pr_cursig; /* Current signal. */ + unsigned long int pr_sigpend; /* Set of pending signals. */ + unsigned long int pr_sighold; /* Set of held signals. */ + __pid_t pr_pid; + __pid_t pr_ppid; + __pid_t pr_pgrp; + __pid_t pr_sid; + struct timeval pr_utime; /* User time. */ + struct timeval pr_stime; /* System time. */ + struct timeval pr_cutime; /* Cumulative user time. */ + struct timeval pr_cstime; /* Cumulative system time. */ + elf_gregset_t pr_reg; /* GP registers. */ + int pr_fpvalid; /* True if math copro being used. */ + }; + + +#define ELF_PRARGSZ (80) /* Number of chars for args */ + +struct elf_prpsinfo + { + char pr_state; /* Numeric process state. */ + char pr_sname; /* Char for pr_state. */ + char pr_zomb; /* Zombie. */ + char pr_nice; /* Nice val. */ + unsigned long int pr_flag; /* Flags. */ + unsigned short int pr_uid; + unsigned short int pr_gid; + int pr_pid, pr_ppid, pr_pgrp, pr_sid; + /* Lots missing */ + char pr_fname[16]; /* Filename of executable. */ + char pr_psargs[ELF_PRARGSZ]; /* Initial part of arg list. */ + }; + +/* Addresses. */ +typedef void *psaddr_t; + +/* Register sets. Linux has different names. */ +typedef elf_gregset_t prgregset_t; +typedef elf_fpregset_t prfpregset_t; + +/* We don't have any differences between processes and threads, + therefore have only one PID type. */ +typedef __pid_t lwpid_t; + + +typedef struct elf_prstatus prstatus_t; +typedef struct elf_prpsinfo prpsinfo_t; + +__END_DECLS + +#endif /* sys/procfs.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/sys/ucontext.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/sys/ucontext.h new file mode 100644 index 00000000..1805b4ea --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/sys/ucontext.h @@ -0,0 +1,104 @@ +/* Copyright (C) 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_UCONTEXT_H +#define _SYS_UCONTEXT_H 1 + +#include +#include +/* + * Location of the users' stored registers relative to R0. + * Usage is as an index into a gregset_t array or as u.u_ar0[XX]. + */ +#define REG_PSR (0) +#define REG_PC (1) +#define REG_SPARE (2) +#define REG_WVALID (3) +#define REG_G1 (4) +#define REG_G2 (5) +#define REG_G3 (6) +#define REG_G4 (7) +#define REG_G5 (8) +#define REG_G6 (9) +#define REG_G7 (10) +#define REG_O0 (11) +#define REG_O1 (12) +#define REG_O2 (13) +#define REG_O3 (14) +#define REG_O4 (15) +#define REG_O5 (16) +#define REG_O6 (17) +#define REG_O7 (18) +#define REG_GLOBALS (19) + +/* + * A gregset_t is defined as an array type for compatibility with the reference + * source. This is important due to differences in the way the C language + * treats arrays and structures as parameters. + * + * Note that NGREG is really (sizeof (struct regs) / sizeof (greg_t)), + * but that the ABI defines it absolutely to be 21 (resp. 19). + */ + +#define NGREG 20 +typedef int greg_t; + +typedef greg_t gregset_t[NGREG]; + +/* + * The following structures define how a register window can appear on the + * stack. This structure is available (when required) through the `gwins' + * field of an mcontext (nested within ucontext). NIOS_MAXWINDOW is the + * maximum number of outstanding register windows defined in the NIOS + * architecture (*not* implementation). + */ +#define NIOS_MAXREGWINDOW 31 /* max windows in NIOS arch. */ +struct rwindow + { + greg_t rw_local[8]; /* locals */ + greg_t rw_in[8]; /* ins */ + }; + +#define rw_fp rw_in[6] /* frame pointer */ +#define rw_rtn rw_in[7] /* return address */ + +typedef struct gwindows + { + int wbcnt; + int *spbuf[NIOS_MAXREGWINDOW]; + struct rwindow wbuf[NIOS_MAXREGWINDOW]; + } gwindows_t; + +typedef struct + { + gregset_t gregs; /* general register set */ + gwindows_t *gwins; /* POSSIBLE pointer to register windows */ + } mcontext_t; + + +/* Userlevel context. */ +typedef struct ucontext + { + unsigned long uc_flags; + struct ucontext *uc_link; + __sigset_t uc_sigmask; + stack_t uc_stack; + mcontext_t uc_mcontext; + } ucontext_t; + +#endif /* sys/ucontext.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/sys/user.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/sys/user.h new file mode 100644 index 00000000..b34e93e9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/sys/user.h @@ -0,0 +1,93 @@ +#ifndef _SYS_USER_H +#define _SYS_USER_H 1 + +/* + This file was taken from the nios2 port of the Linux Kernel. + + Copyright (c) 2008 Atle Nissestad + Copyright (c) 2010 Tobias Klauser + + This file is licensed under the terms of the GNU General Public License, + Version 2. + */ + +#include + +/* Core file format: The core file is written in such a way that gdb + can understand it and provide useful information to the user (under + linux we use the 'trad-core' bfd). There are quite a number of + obstacles to being able to view the contents of the floating point + registers, and until these are solved you will not be able to view the + contents of them. Actually, you can read in the core file and look at + the contents of the user struct to find out what the floating point + registers contain. + The actual file contents are as follows: + UPAGE: 1 page consisting of a user struct that tells gdb what is present + in the file. Directly after this is a copy of the task_struct, which + is currently not used by gdb, but it may come in useful at some point. + All of the registers are stored as part of the upage. The upage should + always be only one page. + DATA: The data area is stored. We use current->end_text to + current->brk to pick up all of the user variables, plus any memory + that may have been malloced. No attempt is made to determine if a page + is demand-zero or if a page is totally unused, we just cover the entire + range. All of the addresses are rounded in such a way that an integral + number of pages is written. + STACK: We need the stack information in order to get a meaningful + backtrace. We need to write the data from (esp) to + current->start_stack, so we round each of these off in order to be able + to write an integer number of pages. + The minimum core file size is 3 pages, or 12288 bytes. +*/ + +struct user_nios2fp_struct { +}; + +/* This is the old layout of "struct pt_regs" as of Linux 1.x, and + is still the layout used by user (the new pt_regs doesn't have + all registers). */ +struct user_regs_struct { + long r1,r2,r3,r4,r5,r6,r7,r8; + long r9,r10,r11,r12,r13,r14,r15; + long r16,r17,r18,r19,r20,r21,r22,r23; + long gp; + long sp; + long ra; + long fp; + long orig_r2; + long estatus; + long status_extension; + long ea; +}; + +/* When the kernel dumps core, it starts by dumping the user struct - + this will be used by gdb to figure out where the data and stack segments + are within the file, and what virtual addresses to use. */ +struct user { +/* We start with the registers, to mimic the way that "memory" is returned + from the ptrace(3,...) function. */ + struct user_regs_struct regs; /* Where the registers are actually stored */ + +/* The rest of this junk is to help gdb figure out what goes where */ + unsigned long int u_tsize; /* Text segment size (pages). */ + unsigned long int u_dsize; /* Data segment size (pages). */ + unsigned long int u_ssize; /* Stack segment size (pages). */ + unsigned long start_code; /* Starting virtual address of text. */ + unsigned long start_stack; /* Starting virtual address of stack area. + This is actually the bottom of the stack, + the top of the stack is always found in the + esp register. */ + long int signal; /* Signal that caused the core dump. */ + int reserved; /* No longer used */ + unsigned long u_ar0; /* Used by gdb to help find the values for */ + /* the registers. */ + unsigned long magic; /* To uniquely identify a core file */ + char u_comm[32]; /* User command that was responsible */ +}; + +#define NBPG PAGE_SIZE +#define UPAGES 1 +#define HOST_TEXT_START_ADDR (u.start_code) +#define HOST_STACK_END_ADDR (u.start_stack + u.u_ssize * NBPG) + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/syscall.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/syscall.c new file mode 100644 index 00000000..c3eb0022 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/syscall.c @@ -0,0 +1,47 @@ +/* + * libc/sysdeps/linux/nios2/syscall.c -- generic syscall function for linux/nios2 + * + * Copyright (C) 2004 Microtronix Datacom Ltd. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License + * for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include + + +long syscall(long sysnum, long a, long b, long c, long d, long e, long f) +{ + register long _r2 __asm__("r2")=(long)TRAP_ID_SYSCALL; + register long _r3 __asm__("r3")=(long)sysnum; + + register long _r4 __asm__("r4")=(long)(a); + register long _r5 __asm__("r5")=(long)(b); + register long _r6 __asm__("r6")=(long)(c); + register long _r7 __asm__("r7")=(long)(d); + register long _r8 __asm__("r8")=(long)(e); + register long _r9 __asm__("r9")=(long)(f); + __asm__ __volatile__( + "trap " + : "=r"(_r2), "=r"(_r3) + : "0"(_r2), "1"(_r3), + "r"(_r4), "r"(_r5), "r"(_r6), "r"(_r7), "r"(_r8), "r"(_r9) + : "memory"); + + __syscall_return (long, _r2); +} + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/vfork.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/vfork.S new file mode 100644 index 00000000..5d275ffd --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/nios2/vfork.S @@ -0,0 +1,56 @@ +/* + * libc/sysdeps/linux/nios2/vfork.S -- `vfork' syscall for linux/nios2 + * + * Copyright (C) 2004 Microtronix Datacom Ltd + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + * + * Written by Wentao Xu + */ + +#include + +#define _ERRNO_H +#include +#include + +#ifndef __NR_vfork +#define __NR_vfork __NR_fork /* uClinux-2.0 only has fork which is vfork */ +#endif + +.text +.global __vfork +.hidden __vfork +.type __vfork,%function +.align 4 +__vfork: + movui r2, TRAP_ID_SYSCALL + movui r3, __NR_vfork + trap + movi r8, -4096 + bltu r8, r2, fix_errno + ret +fix_errno: + sub r8, r0, r2 + + addi sp, sp, -8 + stw ra, 4(sp) + stw r8, 0(sp) +#ifndef __PIC__ + call __errno_location +#else + +#endif + ldw ra, 4(sp) + ldw r8, 0(sp) + stw r8, 0(r2) + + addi r2, r0, -1 + addi sp, sp, 8 + ret + +.size __vfork,.-__vfork +weak_alias(__vfork,vfork) +libc_hidden_weak(vfork) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/Makefile new file mode 100644 index 00000000..633c91f3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../../ +top_builddir=../../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.arch +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/Makefile.arch b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/Makefile.arch new file mode 100644 index 00000000..cdb35ba4 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/Makefile.arch @@ -0,0 +1,23 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +CSRC := __syscall_error.c pread_write.c ioctl.c + +ifeq ($(UCLIBC_HAS_ADVANCED_REALTIME),y) +CSRC += posix_fadvise.c posix_fadvise64.c +endif + +SSRC := \ + __longjmp.S setjmp.S bsd-setjmp.S bsd-_setjmp.S brk.S \ + __uClibc_syscall.S syscall.S +ifneq ($(UCLIBC_HAS_THREADS_NATIVE),y) +SSRC += clone.S vfork.S +endif + +ifeq ($(CONFIG_E500),y) +ARCH_HEADERS := fenv.h +endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/README.bits b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/README.bits new file mode 100644 index 00000000..c0542e5b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/README.bits @@ -0,0 +1,14 @@ + +include/bits is mostly the same as glibc-2.2.4. The glibc-2.2.4 +versions can be accessed with the tag glibc224. + +Major differences: + + - termios.h is from the Linux kernel, not glibc, because glibc has + a very strange legacy conversion layer, which we ignore. + + - syscall.h is deleted; instead, sysnum.h is autogenerated in uClibc + + - syscalls.h is added. + + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/__longjmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/__longjmp.S new file mode 100644 index 00000000..765a8731 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/__longjmp.S @@ -0,0 +1,94 @@ +/* longjmp for PowerPC and PowerPC e500. + Copyright (C) 1995, 1996, 1997, 1999, 2000, 2004 + Free Software Foundation, Inc. + e500 contributed by Aldy Hernandez . + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include "ppc_asm.h" +#define _ASM +#define _SETJMP_H +#include + + +#if defined __UCLIBC_HAS_FLOATS__ && ! defined __UCLIBC_HAS_SOFT_FLOAT__ +#define FP(x...) x +#else +#define FP(x...) +#endif + +#if defined __CONFIG_E500__ +#define LFD(reg) evldd r##reg +#define STFD(reg) evstdd r##reg +#else +#define LFD(reg) lfd fp##reg +#define STFD(reg) stfd fp##reg +#endif /* __CONFIG_E500__ */ + +.globl __longjmp; +.type __longjmp, @function; +.align 2; + +__longjmp: + lwz r1,(JB_GPR1*4)(r3) + lwz r2,(JB_GPR2*4)(r3) + lwz r0,(JB_LR*4)(r3) + lwz r14,((JB_GPRS+0)*4)(r3) +FP( LFD (14),((JB_FPRS+0*2)*4)(r3)) + lwz r15,((JB_GPRS+1)*4)(r3) +FP( LFD (15),((JB_FPRS+1*2)*4)(r3)) + lwz r16,((JB_GPRS+2)*4)(r3) +FP( LFD (16),((JB_FPRS+2*2)*4)(r3)) + lwz r17,((JB_GPRS+3)*4)(r3) +FP( LFD (17),((JB_FPRS+3*2)*4)(r3)) + lwz r18,((JB_GPRS+4)*4)(r3) +FP( LFD (18),((JB_FPRS+4*2)*4)(r3)) + lwz r19,((JB_GPRS+5)*4)(r3) +FP( LFD (19),((JB_FPRS+5*2)*4)(r3)) + lwz r20,((JB_GPRS+6)*4)(r3) +FP( LFD (20),((JB_FPRS+6*2)*4)(r3)) + mtlr r0 + lwz r21,((JB_GPRS+7)*4)(r3) +FP( LFD (21),((JB_FPRS+7*2)*4)(r3)) + lwz r22,((JB_GPRS+8)*4)(r3) +FP( LFD (22),((JB_FPRS+8*2)*4)(r3)) + lwz r0,(JB_CR*4)(r3) + lwz r23,((JB_GPRS+9)*4)(r3) +FP( LFD (23),((JB_FPRS+9*2)*4)(r3)) + lwz r24,((JB_GPRS+10)*4)(r3) +FP( LFD (24),((JB_FPRS+10*2)*4)(r3)) + lwz r25,((JB_GPRS+11)*4)(r3) +FP( LFD (25),((JB_FPRS+11*2)*4)(r3)) + mtcrf 0xFF,r0 + lwz r26,((JB_GPRS+12)*4)(r3) +FP( LFD (26),((JB_FPRS+12*2)*4)(r3)) + lwz r27,((JB_GPRS+13)*4)(r3) +FP( LFD (27),((JB_FPRS+13*2)*4)(r3)) + lwz r28,((JB_GPRS+14)*4)(r3) +FP( LFD (28),((JB_FPRS+14*2)*4)(r3)) + lwz r29,((JB_GPRS+15)*4)(r3) +FP( LFD (29),((JB_FPRS+15*2)*4)(r3)) + lwz r30,((JB_GPRS+16)*4)(r3) +FP( LFD (30),((JB_FPRS+16*2)*4)(r3)) + lwz r31,((JB_GPRS+17)*4)(r3) +FP( LFD (31),((JB_FPRS+17*2)*4)(r3)) + mr r3,r4 + blr +.size __longjmp,.-__longjmp + +libc_hidden_def(__longjmp) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/__syscall_error.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/__syscall_error.c new file mode 100644 index 00000000..5e109a83 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/__syscall_error.c @@ -0,0 +1,18 @@ +/* Wrapper for setting errno. + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +/* This routine is jumped to by all the syscall handlers, to stash + * an error number into errno. */ +int __syscall_error(int err_no) attribute_hidden; +int __syscall_error(int err_no) +{ + __set_errno(err_no); + return -1; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/__uClibc_syscall.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/__uClibc_syscall.S new file mode 100644 index 00000000..5a14c948 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/__uClibc_syscall.S @@ -0,0 +1,12 @@ + .text + .align 2 + .globl __uClibc_syscall + .type __uClibc_syscall,@function +__uClibc_syscall: +.Lsize: + sc + bnslr + + b __syscall_error + + .size __uClibc_syscall,.Lsize-__uClibc_syscall diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/atomic.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/atomic.h new file mode 100644 index 00000000..dba11367 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/atomic.h @@ -0,0 +1,630 @@ +/* Atomic operations. PowerPC Common version. + Copyright (C) 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Paul Mackerras , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#if __WORDSIZE == 64 +/* Atomic operations. PowerPC64 version. + Copyright (C) 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Paul Mackerras , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* The 32-bit exchange_bool is different on powerpc64 because the subf + does signed 64-bit arthmatic while the lwarx is 32-bit unsigned + (a load word and zero (high 32) form) load. + In powerpc64 register values are 64-bit by default, including oldval. + The value in old val unknown sign extension, lwarx loads the 32-bit + value as unsigned. So we explicitly clear the high 32 bits in oldval. */ +# define __arch_compare_and_exchange_bool_32_acq(mem, newval, oldval) \ +({ \ + unsigned int __tmp, __tmp2; \ + __asm__ __volatile__ (" clrldi %1,%1,32\n" \ + "1: lwarx %0,0,%2\n" \ + " subf. %0,%1,%0\n" \ + " bne 2f\n" \ + " stwcx. %4,0,%2\n" \ + " bne- 1b\n" \ + "2: " __ARCH_ACQ_INSTR \ + : "=&r" (__tmp), "=r" (__tmp2) \ + : "b" (mem), "1" (oldval), "r" (newval) \ + : "cr0", "memory"); \ + __tmp != 0; \ +}) + +# define __arch_compare_and_exchange_bool_32_rel(mem, newval, oldval) \ +({ \ + unsigned int __tmp, __tmp2; \ + __asm__ __volatile__ (__ARCH_REL_INSTR "\n" \ + " clrldi %1,%1,32\n" \ + "1: lwarx %0,0,%2\n" \ + " subf. %0,%1,%0\n" \ + " bne 2f\n" \ + " stwcx. %4,0,%2\n" \ + " bne- 1b\n" \ + "2: " \ + : "=&r" (__tmp), "=r" (__tmp2) \ + : "b" (mem), "1" (oldval), "r" (newval) \ + : "cr0", "memory"); \ + __tmp != 0; \ +}) + +/* + * Only powerpc64 processors support Load doubleword and reserve index (ldarx) + * and Store doubleword conditional indexed (stdcx) instructions. So here + * we define the 64-bit forms. + */ +# define __arch_compare_and_exchange_bool_64_acq(mem, newval, oldval) \ +({ \ + unsigned long __tmp; \ + __asm__ __volatile__ ( \ + "1: ldarx %0,0,%1\n" \ + " subf. %0,%2,%0\n" \ + " bne 2f\n" \ + " stdcx. %3,0,%1\n" \ + " bne- 1b\n" \ + "2: " __ARCH_ACQ_INSTR \ + : "=&r" (__tmp) \ + : "b" (mem), "r" (oldval), "r" (newval) \ + : "cr0", "memory"); \ + __tmp != 0; \ +}) + +# define __arch_compare_and_exchange_bool_64_rel(mem, newval, oldval) \ +({ \ + unsigned long __tmp; \ + __asm__ __volatile__ (__ARCH_REL_INSTR "\n" \ + "1: ldarx %0,0,%1\n" \ + " subf. %0,%2,%0\n" \ + " bne 2f\n" \ + " stdcx. %3,0,%1\n" \ + " bne- 1b\n" \ + "2: " \ + : "=&r" (__tmp) \ + : "b" (mem), "r" (oldval), "r" (newval) \ + : "cr0", "memory"); \ + __tmp != 0; \ +}) + +#define __arch_compare_and_exchange_val_64_acq(mem, newval, oldval) \ + ({ \ + __typeof (*(mem)) __tmp; \ + __typeof (mem) __memp = (mem); \ + __asm__ __volatile__ ( \ + "1: ldarx %0,0,%1\n" \ + " cmpd %0,%2\n" \ + " bne 2f\n" \ + " stdcx. %3,0,%1\n" \ + " bne- 1b\n" \ + "2: " __ARCH_ACQ_INSTR \ + : "=&r" (__tmp) \ + : "b" (__memp), "r" (oldval), "r" (newval) \ + : "cr0", "memory"); \ + __tmp; \ + }) + +#define __arch_compare_and_exchange_val_64_rel(mem, newval, oldval) \ + ({ \ + __typeof (*(mem)) __tmp; \ + __typeof (mem) __memp = (mem); \ + __asm__ __volatile__ (__ARCH_REL_INSTR "\n" \ + "1: ldarx %0,0,%1\n" \ + " cmpd %0,%2\n" \ + " bne 2f\n" \ + " stdcx. %3,0,%1\n" \ + " bne- 1b\n" \ + "2: " \ + : "=&r" (__tmp) \ + : "b" (__memp), "r" (oldval), "r" (newval) \ + : "cr0", "memory"); \ + __tmp; \ + }) + +# define __arch_atomic_exchange_64_acq(mem, value) \ + ({ \ + __typeof (*mem) __val; \ + __asm__ __volatile__ (__ARCH_REL_INSTR "\n" \ + "1: ldarx %0,0,%2\n" \ + " stdcx. %3,0,%2\n" \ + " bne- 1b\n" \ + " " __ARCH_ACQ_INSTR \ + : "=&r" (__val), "=m" (*mem) \ + : "b" (mem), "r" (value), "m" (*mem) \ + : "cr0", "memory"); \ + __val; \ + }) + +# define __arch_atomic_exchange_64_rel(mem, value) \ + ({ \ + __typeof (*mem) __val; \ + __asm__ __volatile__ (__ARCH_REL_INSTR "\n" \ + "1: ldarx %0,0,%2\n" \ + " stdcx. %3,0,%2\n" \ + " bne- 1b" \ + : "=&r" (__val), "=m" (*mem) \ + : "b" (mem), "r" (value), "m" (*mem) \ + : "cr0", "memory"); \ + __val; \ + }) + +# define __arch_atomic_exchange_and_add_64(mem, value) \ + ({ \ + __typeof (*mem) __val, __tmp; \ + __asm__ __volatile__ ("1: ldarx %0,0,%3\n" \ + " add %1,%0,%4\n" \ + " stdcx. %1,0,%3\n" \ + " bne- 1b" \ + : "=&b" (__val), "=&r" (__tmp), "=m" (*mem) \ + : "b" (mem), "r" (value), "m" (*mem) \ + : "cr0", "memory"); \ + __val; \ + }) + +# define __arch_atomic_increment_val_64(mem) \ + ({ \ + __typeof (*(mem)) __val; \ + __asm__ __volatile__ ("1: ldarx %0,0,%2\n" \ + " addi %0,%0,1\n" \ + " stdcx. %0,0,%2\n" \ + " bne- 1b" \ + : "=&b" (__val), "=m" (*mem) \ + : "b" (mem), "m" (*mem) \ + : "cr0", "memory"); \ + __val; \ + }) + +# define __arch_atomic_decrement_val_64(mem) \ + ({ \ + __typeof (*(mem)) __val; \ + __asm__ __volatile__ ("1: ldarx %0,0,%2\n" \ + " subi %0,%0,1\n" \ + " stdcx. %0,0,%2\n" \ + " bne- 1b" \ + : "=&b" (__val), "=m" (*mem) \ + : "b" (mem), "m" (*mem) \ + : "cr0", "memory"); \ + __val; \ + }) + +# define __arch_atomic_decrement_if_positive_64(mem) \ + ({ int __val, __tmp; \ + __asm__ __volatile__ ("1: ldarx %0,0,%3\n" \ + " cmpdi 0,%0,0\n" \ + " addi %1,%0,-1\n" \ + " ble 2f\n" \ + " stdcx. %1,0,%3\n" \ + " bne- 1b\n" \ + "2: " __ARCH_ACQ_INSTR \ + : "=&b" (__val), "=&r" (__tmp), "=m" (*mem) \ + : "b" (mem), "m" (*mem) \ + : "cr0", "memory"); \ + __val; \ + }) + +/* + * All powerpc64 processors support the new "light weight" sync (lwsync). + */ +# define atomic_read_barrier() __asm__ ("lwsync" ::: "memory") +/* + * "light weight" sync can also be used for the release barrier. + */ +# ifndef UP +# define __ARCH_REL_INSTR "lwsync" +# endif + +#else +/* Atomic operations. PowerPC32 version. + Copyright (C) 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Paul Mackerras , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * The 32-bit exchange_bool is different on powerpc64 because the subf + * does signed 64-bit arthmatic while the lwarx is 32-bit unsigned + * (a load word and zero (high 32) form). So powerpc64 has a slightly + * different version in sysdeps/powerpc/powerpc64/bits/atomic.h. + */ +# define __arch_compare_and_exchange_bool_32_acq(mem, newval, oldval) \ +({ \ + unsigned int __tmp; \ + __asm__ __volatile__ ( \ + "1: lwarx %0,0,%1\n" \ + " subf. %0,%2,%0\n" \ + " bne 2f\n" \ + " stwcx. %3,0,%1\n" \ + " bne- 1b\n" \ + "2: " __ARCH_ACQ_INSTR \ + : "=&r" (__tmp) \ + : "b" (mem), "r" (oldval), "r" (newval) \ + : "cr0", "memory"); \ + __tmp != 0; \ +}) + +# define __arch_compare_and_exchange_bool_32_rel(mem, newval, oldval) \ +({ \ + unsigned int __tmp; \ + __asm__ __volatile__ (__ARCH_REL_INSTR "\n" \ + "1: lwarx %0,0,%1\n" \ + " subf. %0,%2,%0\n" \ + " bne 2f\n" \ + " stwcx. %3,0,%1\n" \ + " bne- 1b\n" \ + "2: " \ + : "=&r" (__tmp) \ + : "b" (mem), "r" (oldval), "r" (newval) \ + : "cr0", "memory"); \ + __tmp != 0; \ +}) + +/* Powerpc32 processors don't implement the 64-bit (doubleword) forms of + load and reserve (ldarx) and store conditional (stdcx.) instructions. + So for powerpc32 we stub out the 64-bit forms. */ +# define __arch_compare_and_exchange_bool_64_acq(mem, newval, oldval) \ + (abort (), 0) + +# define __arch_compare_and_exchange_val_64_acq(mem, newval, oldval) \ + (abort (), (__typeof (*mem)) 0) + +# define __arch_compare_and_exchange_bool_64_rel(mem, newval, oldval) \ + (abort (), 0) + +# define __arch_compare_and_exchange_val_64_rel(mem, newval, oldval) \ + (abort (), (__typeof (*mem)) 0) + +# define __arch_atomic_exchange_64_acq(mem, value) \ + ({ abort (); (*mem) = (value); }) + +# define __arch_atomic_exchange_64_rel(mem, value) \ + ({ abort (); (*mem) = (value); }) + +# define __arch_atomic_exchange_and_add_64(mem, value) \ + ({ abort (); (*mem) = (value); }) + +# define __arch_atomic_increment_val_64(mem) \ + ({ abort (); (*mem)++; }) + +# define __arch_atomic_decrement_val_64(mem) \ + ({ abort (); (*mem)--; }) + +# define __arch_atomic_decrement_if_positive_64(mem) \ + ({ abort (); (*mem)--; }) + +#ifdef _ARCH_PWR4 +/* + * Newer powerpc64 processors support the new "light weight" sync (lwsync) + * So if the build is using -mcpu=[power4,power5,power5+,970] we can + * safely use lwsync. + */ +# define atomic_read_barrier() __asm__ ("lwsync" ::: "memory") +/* + * "light weight" sync can also be used for the release barrier. + */ +# ifndef UP +# define __ARCH_REL_INSTR "lwsync" +# endif +#else + +/* + * Older powerpc32 processors don't support the new "light weight" + * sync (lwsync). So the only safe option is to use normal sync + * for all powerpc32 applications. + */ +# define atomic_read_barrier() __asm__ ("sync" ::: "memory") +#endif + +#endif + +#include + +typedef int32_t atomic32_t; +typedef uint32_t uatomic32_t; +typedef int_fast32_t atomic_fast32_t; +typedef uint_fast32_t uatomic_fast32_t; + +typedef int64_t atomic64_t; +typedef uint64_t uatomic64_t; +typedef int_fast64_t atomic_fast64_t; +typedef uint_fast64_t uatomic_fast64_t; + +typedef intptr_t atomicptr_t; +typedef uintptr_t uatomicptr_t; +typedef intmax_t atomic_max_t; +typedef uintmax_t uatomic_max_t; + +/* + * Powerpc does not have byte and halfword forms of load and reserve and + * store conditional. So for powerpc we stub out the 8- and 16-bit forms. + */ +#define __arch_compare_and_exchange_bool_8_acq(mem, newval, oldval) \ + (abort (), 0) + +#define __arch_compare_and_exchange_bool_16_acq(mem, newval, oldval) \ + (abort (), 0) + +#define __arch_compare_and_exchange_bool_8_rel(mem, newval, oldval) \ + (abort (), 0) + +#define __arch_compare_and_exchange_bool_16_rel(mem, newval, oldval) \ + (abort (), 0) + +#ifdef UP +# define __ARCH_ACQ_INSTR "" +# define __ARCH_REL_INSTR "" +#else +# define __ARCH_ACQ_INSTR "isync" +# ifndef __ARCH_REL_INSTR +# define __ARCH_REL_INSTR "sync" +# endif +#endif + +#ifndef MUTEX_HINT_ACQ +# define MUTEX_HINT_ACQ +#endif +#ifndef MUTEX_HINT_REL +# define MUTEX_HINT_REL +#endif + +#define atomic_full_barrier() __asm__ ("sync" ::: "memory") +#define atomic_write_barrier() __asm__ ("eieio" ::: "memory") + +#define __arch_compare_and_exchange_val_32_acq(mem, newval, oldval) \ + ({ \ + __typeof (*(mem)) __tmp; \ + __typeof (mem) __memp = (mem); \ + __asm__ __volatile__ ( \ + "1: lwarx %0,0,%1\n" \ + " cmpw %0,%2\n" \ + " bne 2f\n" \ + " stwcx. %3,0,%1\n" \ + " bne- 1b\n" \ + "2: " __ARCH_ACQ_INSTR \ + : "=&r" (__tmp) \ + : "b" (__memp), "r" (oldval), "r" (newval) \ + : "cr0", "memory"); \ + __tmp; \ + }) + +#define __arch_compare_and_exchange_val_32_rel(mem, newval, oldval) \ + ({ \ + __typeof (*(mem)) __tmp; \ + __typeof (mem) __memp = (mem); \ + __asm__ __volatile__ (__ARCH_REL_INSTR "\n" \ + "1: lwarx %0,0,%1\n" \ + " cmpw %0,%2\n" \ + " bne 2f\n" \ + " stwcx. %3,0,%1\n" \ + " bne- 1b\n" \ + "2: " \ + : "=&r" (__tmp) \ + : "b" (__memp), "r" (oldval), "r" (newval) \ + : "cr0", "memory"); \ + __tmp; \ + }) + +#define __arch_atomic_exchange_32_acq(mem, value) \ + ({ \ + __typeof (*mem) __val; \ + __asm__ __volatile__ ( \ + "1: lwarx %0,0,%2\n" \ + " stwcx. %3,0,%2\n" \ + " bne- 1b\n" \ + " " __ARCH_ACQ_INSTR \ + : "=&r" (__val), "=m" (*mem) \ + : "b" (mem), "r" (value), "m" (*mem) \ + : "cr0", "memory"); \ + __val; \ + }) + +#define __arch_atomic_exchange_32_rel(mem, value) \ + ({ \ + __typeof (*mem) __val; \ + __asm__ __volatile__ (__ARCH_REL_INSTR "\n" \ + "1: lwarx %0,0,%2\n" \ + " stwcx. %3,0,%2\n" \ + " bne- 1b" \ + : "=&r" (__val), "=m" (*mem) \ + : "b" (mem), "r" (value), "m" (*mem) \ + : "cr0", "memory"); \ + __val; \ + }) + +#define __arch_atomic_exchange_and_add_32(mem, value) \ + ({ \ + __typeof (*mem) __val, __tmp; \ + __asm__ __volatile__ ("1: lwarx %0,0,%3\n" \ + " add %1,%0,%4\n" \ + " stwcx. %1,0,%3\n" \ + " bne- 1b" \ + : "=&b" (__val), "=&r" (__tmp), "=m" (*mem) \ + : "b" (mem), "r" (value), "m" (*mem) \ + : "cr0", "memory"); \ + __val; \ + }) + +#define __arch_atomic_increment_val_32(mem) \ + ({ \ + __typeof (*(mem)) __val; \ + __asm__ __volatile__ ("1: lwarx %0,0,%2\n" \ + " addi %0,%0,1\n" \ + " stwcx. %0,0,%2\n" \ + " bne- 1b" \ + : "=&b" (__val), "=m" (*mem) \ + : "b" (mem), "m" (*mem) \ + : "cr0", "memory"); \ + __val; \ + }) + +#define __arch_atomic_decrement_val_32(mem) \ + ({ \ + __typeof (*(mem)) __val; \ + __asm__ __volatile__ ("1: lwarx %0,0,%2\n" \ + " subi %0,%0,1\n" \ + " stwcx. %0,0,%2\n" \ + " bne- 1b" \ + : "=&b" (__val), "=m" (*mem) \ + : "b" (mem), "m" (*mem) \ + : "cr0", "memory"); \ + __val; \ + }) + +#define __arch_atomic_decrement_if_positive_32(mem) \ + ({ int __val, __tmp; \ + __asm__ __volatile__ ("1: lwarx %0,0,%3\n" \ + " cmpwi 0,%0,0\n" \ + " addi %1,%0,-1\n" \ + " ble 2f\n" \ + " stwcx. %1,0,%3\n" \ + " bne- 1b\n" \ + "2: " __ARCH_ACQ_INSTR \ + : "=&b" (__val), "=&r" (__tmp), "=m" (*mem) \ + : "b" (mem), "m" (*mem) \ + : "cr0", "memory"); \ + __val; \ + }) + +#define atomic_compare_and_exchange_val_acq(mem, newval, oldval) \ + ({ \ + __typeof (*(mem)) __result; \ + if (sizeof (*mem) == 4) \ + __result = __arch_compare_and_exchange_val_32_acq(mem, newval, oldval); \ + else if (sizeof (*mem) == 8) \ + __result = __arch_compare_and_exchange_val_64_acq(mem, newval, oldval); \ + else \ + abort (); \ + __result; \ + }) + +#define atomic_compare_and_exchange_val_rel(mem, newval, oldval) \ + ({ \ + __typeof (*(mem)) __result; \ + if (sizeof (*mem) == 4) \ + __result = __arch_compare_and_exchange_val_32_rel(mem, newval, oldval); \ + else if (sizeof (*mem) == 8) \ + __result = __arch_compare_and_exchange_val_64_rel(mem, newval, oldval); \ + else \ + abort (); \ + __result; \ + }) + +#define atomic_exchange_acq(mem, value) \ + ({ \ + __typeof (*(mem)) __result; \ + if (sizeof (*mem) == 4) \ + __result = __arch_atomic_exchange_32_acq (mem, value); \ + else if (sizeof (*mem) == 8) \ + __result = __arch_atomic_exchange_64_acq (mem, value); \ + else \ + abort (); \ + __result; \ + }) + +#define atomic_exchange_rel(mem, value) \ + ({ \ + __typeof (*(mem)) __result; \ + if (sizeof (*mem) == 4) \ + __result = __arch_atomic_exchange_32_rel (mem, value); \ + else if (sizeof (*mem) == 8) \ + __result = __arch_atomic_exchange_64_rel (mem, value); \ + else \ + abort (); \ + __result; \ + }) + +#define atomic_exchange_and_add(mem, value) \ + ({ \ + __typeof (*(mem)) __result; \ + if (sizeof (*mem) == 4) \ + __result = __arch_atomic_exchange_and_add_32 (mem, value); \ + else if (sizeof (*mem) == 8) \ + __result = __arch_atomic_exchange_and_add_64 (mem, value); \ + else \ + abort (); \ + __result; \ + }) + +#define atomic_increment_val(mem) \ + ({ \ + __typeof (*(mem)) __result; \ + if (sizeof (*(mem)) == 4) \ + __result = __arch_atomic_increment_val_32 (mem); \ + else if (sizeof (*(mem)) == 8) \ + __result = __arch_atomic_increment_val_64 (mem); \ + else \ + abort (); \ + __result; \ + }) + +#define atomic_increment(mem) ({ atomic_increment_val (mem); (void) 0; }) + +#define atomic_decrement_val(mem) \ + ({ \ + __typeof (*(mem)) __result; \ + if (sizeof (*(mem)) == 4) \ + __result = __arch_atomic_decrement_val_32 (mem); \ + else if (sizeof (*(mem)) == 8) \ + __result = __arch_atomic_decrement_val_64 (mem); \ + else \ + abort (); \ + __result; \ + }) + +#define atomic_decrement(mem) ({ atomic_decrement_val (mem); (void) 0; }) + + +/* Decrement *MEM if it is > 0, and return the old value. */ +#define atomic_decrement_if_positive(mem) \ + ({ __typeof (*(mem)) __result; \ + if (sizeof (*mem) == 4) \ + __result = __arch_atomic_decrement_if_positive_32 (mem); \ + else if (sizeof (*mem) == 8) \ + __result = __arch_atomic_decrement_if_positive_64 (mem); \ + else \ + abort (); \ + __result; \ + }) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/endian.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/endian.h new file mode 100644 index 00000000..2a079347 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/endian.h @@ -0,0 +1,37 @@ +/* Copyright (C) 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* PowerPC can be little or big endian. Hopefully gcc will know... */ + +#ifndef _ENDIAN_H +# error "Never use directly; include instead." +#endif + +#if defined __BIG_ENDIAN__ || defined _BIG_ENDIAN +# if defined __LITTLE_ENDIAN__ || defined _LITTLE_ENDIAN +# error Both BIG_ENDIAN and LITTLE_ENDIAN defined! +# endif +# define __BYTE_ORDER __BIG_ENDIAN +#else +# if defined __LITTLE_ENDIAN__ || defined _LITTLE_ENDIAN +# define __BYTE_ORDER __LITTLE_ENDIAN +# else +# warning Cannot determine current byte order, assuming big-endian. +# define __BYTE_ORDER __BIG_ENDIAN +# endif +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/fcntl.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/fcntl.h new file mode 100644 index 00000000..0759c6a7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/fcntl.h @@ -0,0 +1,239 @@ +/* O_*, F_*, FD_* bit values for Linux/PowerPC. + Copyright (C) 1995, 1996, 1997, 1998, 2000, 2003, 2004, 2006, 2007 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FCNTL_H +# error "Never use directly; include instead." +#endif + +#include +#ifdef __USE_GNU +# include +#endif + + +/* open/fcntl - O_SYNC is only implemented on blocks devices and on files + located on an ext2 file system */ +#define O_ACCMODE 0003 +#define O_RDONLY 00 +#define O_WRONLY 01 +#define O_RDWR 02 +#define O_CREAT 0100 /* not fcntl */ +#define O_EXCL 0200 /* not fcntl */ +#define O_NOCTTY 0400 /* not fcntl */ +#define O_TRUNC 01000 /* not fcntl */ +#define O_APPEND 02000 +#define O_NONBLOCK 04000 +#define O_NDELAY O_NONBLOCK +#define O_SYNC 010000 +#define O_FSYNC O_SYNC +#define O_ASYNC 020000 + +#ifdef __USE_GNU +# define O_DIRECT 0400000 /* Direct disk access. */ +# define O_DIRECTORY 040000 /* Must be a directory. */ +# define O_NOFOLLOW 0100000 /* Do not follow links. */ +# define O_NOATIME 01000000 /* Do not set atime. */ +# define O_CLOEXEC 02000000 /* Set close_on_exec. */ +#endif + +#ifdef __USE_LARGEFILE64 +# define O_LARGEFILE 0200000 +#endif + +/* For now Linux has synchronisity options for data and read operations. + We define the symbols here but let them do the same as O_SYNC since + this is a superset. */ +#if defined __USE_POSIX199309 || defined __USE_UNIX98 +# define O_DSYNC O_SYNC /* Synchronize data. */ +# define O_RSYNC O_SYNC /* Synchronize read operations. */ +#endif + +/* Values for the second argument to `fcntl'. */ +#define F_DUPFD 0 /* Duplicate file descriptor. */ +#define F_GETFD 1 /* Get file descriptor flags. */ +#define F_SETFD 2 /* Set file descriptor flags. */ +#define F_GETFL 3 /* Get file status flags. */ +#define F_SETFL 4 /* Set file status flags. */ +#ifndef __USE_FILE_OFFSET64 +# define F_GETLK 5 /* Get record locking info. */ +# define F_SETLK 6 /* Set record locking info (non-blocking). */ +# define F_SETLKW 7 /* Set record locking info (blocking). */ +#else +# define F_GETLK F_GETLK64 /* Get record locking info. */ +# define F_SETLK F_SETLK64 /* Set record locking info (non-blocking).*/ +# define F_SETLKW F_SETLKW64 /* Set record locking info (blocking). */ +#endif +#define F_GETLK64 12 /* Get record locking info. */ +#define F_SETLK64 13 /* Set record locking info (non-blocking). */ +#define F_SETLKW64 14 /* Set record locking info (blocking). */ + +#if defined __USE_BSD || defined __USE_UNIX98 +# define F_SETOWN 8 /* Get owner of socket (receiver of SIGIO). */ +# define F_GETOWN 9 /* Set owner of socket (receiver of SIGIO). */ +#endif + +#ifdef __USE_GNU +# define F_SETSIG 10 /* Set number of signal to be sent. */ +# define F_GETSIG 11 /* Get number of signal to be sent. */ +#endif + +#ifdef __USE_GNU +# define F_SETLEASE 1024 /* Set a lease. */ +# define F_GETLEASE 1025 /* Enquire what lease is active. */ +# define F_NOTIFY 1026 /* Request notfications on a directory. */ +# define F_DUPFD_CLOEXEC 1030 /* Duplicate file descriptor with + close-on-exit set on new fd. */ +#endif + +/* For F_[GET|SET]FD. */ +#define FD_CLOEXEC 1 /* actually anything with low bit set goes */ + +/* For posix fcntl() and `l_type' field of a `struct flock' for lockf(). */ +#define F_RDLCK 0 /* Read lock. */ +#define F_WRLCK 1 /* Write lock. */ +#define F_UNLCK 2 /* Remove lock. */ + +/* For old implementation of bsd flock(). */ +#define F_EXLCK 4 /* or 3 */ +#define F_SHLCK 8 /* or 4 */ + +#ifdef __USE_BSD +/* Operations for bsd flock(), also used by the kernel implementation. */ +# define LOCK_SH 1 /* shared lock */ +# define LOCK_EX 2 /* exclusive lock */ +# define LOCK_NB 4 /* or'd with one of the above to prevent + blocking */ +# define LOCK_UN 8 /* remove lock */ +#endif + +#ifdef __USE_GNU +# define LOCK_MAND 32 /* This is a mandatory flock: */ +# define LOCK_READ 64 /* ... which allows concurrent read operations. */ +# define LOCK_WRITE 128 /* ... which allows concurrent write operations. */ +# define LOCK_RW 192 /* ... Which allows concurrent read & write operations. */ +#endif + +#ifdef __USE_GNU +/* Types of directory notifications that may be requested with F_NOTIFY. */ +# define DN_ACCESS 0x00000001 /* File accessed. */ +# define DN_MODIFY 0x00000002 /* File modified. */ +# define DN_CREATE 0x00000004 /* File created. */ +# define DN_DELETE 0x00000008 /* File removed. */ +# define DN_RENAME 0x00000010 /* File renamed. */ +# define DN_ATTRIB 0x00000020 /* File changed attibutes. */ +# define DN_MULTISHOT 0x80000000 /* Don't remove notifier. */ +#endif + +struct flock + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ +#ifndef __USE_FILE_OFFSET64 + __off_t l_start; /* Offset where the lock begins. */ + __off_t l_len; /* Size of the locked area; zero means until EOF. */ +#else + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ +#endif + __pid_t l_pid; /* Process holding the lock. */ + }; + +#ifdef __USE_LARGEFILE64 +struct flock64 + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ + __pid_t l_pid; /* Process holding the lock. */ + }; +#endif + +/* Define some more compatibility macros to be backward compatible with + BSD systems which did not managed to hide these kernel macros. */ +#ifdef __USE_BSD +# define FAPPEND O_APPEND +# define FFSYNC O_FSYNC +# define FASYNC O_ASYNC +# define FNONBLOCK O_NONBLOCK +# define FNDELAY O_NDELAY +#endif /* Use BSD. */ + +/* Advise to `posix_fadvise'. */ +#ifdef __USE_XOPEN2K +# define POSIX_FADV_NORMAL 0 /* No further special treatment. */ +# define POSIX_FADV_RANDOM 1 /* Expect random page references. */ +# define POSIX_FADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define POSIX_FADV_WILLNEED 3 /* Will need these pages. */ +# define POSIX_FADV_DONTNEED 4 /* Don't need these pages. */ +# define POSIX_FADV_NOREUSE 5 /* Data will be accessed once. */ +#endif + + +#if defined __USE_GNU && defined __UCLIBC_LINUX_SPECIFIC__ +/* Flags for SYNC_FILE_RANGE. */ +# define SYNC_FILE_RANGE_WAIT_BEFORE 1 /* Wait upon writeout of all pages + in the range before performing the + write. */ +# define SYNC_FILE_RANGE_WRITE 2 /* Initiate writeout of all those + dirty pages in the range which are + not presently under writeback. */ +# define SYNC_FILE_RANGE_WAIT_AFTER 4 /* Wait upon writeout of all pages in + the range after performing the + write. */ + +/* Flags for SPLICE and VMSPLICE. */ +# define SPLICE_F_MOVE 1 /* Move pages instead of copying. */ +# define SPLICE_F_NONBLOCK 2 /* Don't block on the pipe splicing + (but we may still block on the fd + we splice from/to). */ +# define SPLICE_F_MORE 4 /* Expect more data. */ +# define SPLICE_F_GIFT 8 /* Pages passed in are a gift. */ +#endif + +__BEGIN_DECLS + +#if defined __USE_GNU && defined __UCLIBC_LINUX_SPECIFIC__ + +/* Provide kernel hint to read ahead. */ +extern ssize_t readahead (int __fd, __off64_t __offset, size_t __count) + __THROW; + + +/* Selective file content synch'ing. */ +extern int sync_file_range (int __fd, __off64_t __from, __off64_t __to, + unsigned int __flags); + +/* Splice address range into a pipe. */ +extern ssize_t vmsplice (int __fdout, const struct iovec *__iov, + size_t __count, unsigned int __flags); + +/* Splice two files together. */ +extern ssize_t splice (int __fdin, __off64_t *__offin, int __fdout, + __off64_t *__offout, size_t __len, + unsigned int __flags); + +/* In-kernel implementation of tee for pipe buffers. */ +extern ssize_t tee (int __fdin, int __fdout, size_t __len, + unsigned int __flags); + +#endif +__END_DECLS + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/fenv.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/fenv.h new file mode 100644 index 00000000..b674965f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/fenv.h @@ -0,0 +1,168 @@ +/* Copyright (C) 1997, 1998, 1999, 2004, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FENV_H +# error "Never use directly; include instead." +#endif + +#include + +#ifdef __CONFIG_E500__ + +/* Define bits representing the exception. We use the bit positions of + the appropriate bits in the SPEFSCR... */ +enum + { + FE_INEXACT = 1 << (63 - 42), +#define FE_INEXACT FE_INEXACT + FE_INVALID = 1 << (63 - 43), +#define FE_INVALID FE_INVALID + FE_DIVBYZERO = 1 << (63 - 44), +#define FE_DIVBYZERO FE_DIVBYZERO + FE_UNDERFLOW = 1 << (63 - 45), +#define FE_UNDERFLOW FE_UNDERFLOW + FE_OVERFLOW = 1 << (63 - 46) +#define FE_OVERFLOW FE_OVERFLOW + }; + +#else /* PowerPC 6xx floating-point. */ + +/* Define bits representing the exception. We use the bit positions of + the appropriate bits in the FPSCR... */ +enum + { + FE_INEXACT = 1 << (31 - 6), +#define FE_INEXACT FE_INEXACT + FE_DIVBYZERO = 1 << (31 - 5), +#define FE_DIVBYZERO FE_DIVBYZERO + FE_UNDERFLOW = 1 << (31 - 4), +#define FE_UNDERFLOW FE_UNDERFLOW + FE_OVERFLOW = 1 << (31 - 3), +#define FE_OVERFLOW FE_OVERFLOW + + /* ... except for FE_INVALID, for which we use bit 31. FE_INVALID + actually corresponds to bits 7 through 12 and 21 through 23 + in the FPSCR, but we can't use that because the current draft + says that it must be a power of 2. Instead we use bit 2 which + is the summary bit for all the FE_INVALID exceptions, which + kind of makes sense. */ + FE_INVALID = 1 << (31 - 2), +#define FE_INVALID FE_INVALID + +#ifdef __USE_GNU + /* Breakdown of the FE_INVALID bits. Setting FE_INVALID on an + input to a routine is equivalent to setting all of these bits; + FE_INVALID will be set on output from a routine iff one of + these bits is set. Note, though, that you can't disable or + enable these exceptions individually. */ + + /* Operation with SNaN. */ + FE_INVALID_SNAN = 1 << (31 - 7), +# define FE_INVALID_SNAN FE_INVALID_SNAN + + /* Inf - Inf */ + FE_INVALID_ISI = 1 << (31 - 8), +# define FE_INVALID_ISI FE_INVALID_ISI + + /* Inf / Inf */ + FE_INVALID_IDI = 1 << (31 - 9), +# define FE_INVALID_IDI FE_INVALID_IDI + + /* 0 / 0 */ + FE_INVALID_ZDZ = 1 << (31 - 10), +# define FE_INVALID_ZDZ FE_INVALID_ZDZ + + /* Inf * 0 */ + FE_INVALID_IMZ = 1 << (31 - 11), +# define FE_INVALID_IMZ FE_INVALID_IMZ + + /* Comparison with NaN or SNaN. */ + FE_INVALID_COMPARE = 1 << (31 - 12), +# define FE_INVALID_COMPARE FE_INVALID_COMPARE + + /* Invalid operation flag for software (not set by hardware). */ + /* Note that some chips don't have this implemented, presumably + because no-one expected anyone to write software for them %-). */ + FE_INVALID_SOFTWARE = 1 << (31 - 21), +# define FE_INVALID_SOFTWARE FE_INVALID_SOFTWARE + + /* Square root of negative number (including -Inf). */ + /* Note that some chips don't have this implemented. */ + FE_INVALID_SQRT = 1 << (31 - 22), +# define FE_INVALID_SQRT FE_INVALID_SQRT + + /* Conversion-to-integer of a NaN or a number too large or too small. */ + FE_INVALID_INTEGER_CONVERSION = 1 << (31 - 23) +# define FE_INVALID_INTEGER_CONVERSION FE_INVALID_INTEGER_CONVERSION + +# define FE_ALL_INVALID \ + (FE_INVALID_SNAN | FE_INVALID_ISI | FE_INVALID_IDI | FE_INVALID_ZDZ \ + | FE_INVALID_IMZ | FE_INVALID_COMPARE | FE_INVALID_SOFTWARE \ + | FE_INVALID_SQRT | FE_INVALID_INTEGER_CONVERSION) +#endif /* __USE_GNU */ + }; + +#endif /* __CONFIG_E500__ */ + +#define FE_ALL_EXCEPT \ + (FE_INEXACT | FE_DIVBYZERO | FE_UNDERFLOW | FE_OVERFLOW | FE_INVALID) + +/* PowerPC chips support all of the four defined rounding modes. We + use the bit pattern in the FPSCR as the values for the + appropriate macros. */ +enum + { + FE_TONEAREST = 0, +#define FE_TONEAREST FE_TONEAREST + FE_TOWARDZERO = 1, +#define FE_TOWARDZERO FE_TOWARDZERO + FE_UPWARD = 2, +#define FE_UPWARD FE_UPWARD + FE_DOWNWARD = 3 +#define FE_DOWNWARD FE_DOWNWARD + }; + +/* Type representing exception flags. */ +typedef unsigned int fexcept_t; + +/* Type representing floating-point environment. We leave it as 'double' + for efficiency reasons (rather than writing it to a 32-bit integer). */ +typedef double fenv_t; + +/* If the default argument is used we use this value. */ +extern const fenv_t __fe_dfl_env; +#define FE_DFL_ENV (&__fe_dfl_env) + +#ifdef __USE_GNU +/* Floating-point environment where all exceptions are enabled. Note that + this is not sufficient to give you SIGFPE. */ +extern const fenv_t __fe_enabled_env; +# define FE_ENABLED_ENV (&__fe_enabled_env) + +/* Floating-point environment with (processor-dependent) non-IEEE floating + point. */ +extern const fenv_t __fe_nonieee_env; +# define FE_NONIEEE_ENV (&__fe_nonieee_env) + +/* Floating-point environment with all exceptions enabled. Note that + just evaluating this value will set the processor into 'FPU + exceptions imprecise recoverable' mode, which may cause a significant + performance penalty (but have no other visible effect). */ +extern const fenv_t *__fe_nomask_env (void); +# define FE_NOMASK_ENV (__fe_nomask_env ()) +#endif /* __USE_GNU */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/fenvinline.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/fenvinline.h new file mode 100644 index 00000000..8146479d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/fenvinline.h @@ -0,0 +1,64 @@ +/* Inline floating-point environment handling functions for powerpc. + Copyright (C) 1995, 1996, 1997, 1998, 1999, 2006 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#if defined __GNUC__ && !defined _SOFT_FLOAT && !defined __NO_MATH_INLINES + +/* Inline definition for fegetround. */ +# define fegetround() \ + (__extension__ ({ int __fegetround_result; \ + __asm__ __volatile__ \ + ("mcrfs 7,7 ; mfcr %0" \ + : "=r"(__fegetround_result) : : "cr7"); \ + __fegetround_result & 3; })) + +/* The weird 'i#*X' constraints on the following suppress a gcc + warning when __excepts is not a constant. Otherwise, they mean the + same as just plain 'i'. */ + +/* Inline definition for feraiseexcept. */ +# define feraiseexcept(__excepts) \ + ((__builtin_constant_p (__excepts) \ + && ((__excepts) & ((__excepts)-1)) == 0 \ + && (__excepts) != FE_INVALID) \ + ? ((__excepts) != 0 \ + ? (__extension__ ({ __asm__ __volatile__ \ + ("mtfsb1 %s0" \ + : : "i#*X"(__builtin_ffs (__excepts))); \ + 0; })) \ + : 0) \ + : (feraiseexcept) (__excepts)) + +/* Inline definition for feclearexcept. */ +# define feclearexcept(__excepts) \ + ((__builtin_constant_p (__excepts) \ + && ((__excepts) & ((__excepts)-1)) == 0 \ + && (__excepts) != FE_INVALID) \ + ? ((__excepts) != 0 \ + ? (__extension__ ({ __asm__ __volatile__ \ + ("mtfsb0 %s0" \ + : : "i#*X"(__builtin_ffs (__excepts))); \ + 0; })) \ + : 0) \ + : (feclearexcept) (__excepts)) + +#endif /* __GNUC__ && !_SOFT_FLOAT */ + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/ioctl-types.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/ioctl-types.h new file mode 100644 index 00000000..87b8265a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/ioctl-types.h @@ -0,0 +1,5 @@ +#ifndef _SYS_IOCTL_H +# error "Never use directly; include instead." +#endif + +#include diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/ipc.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/ipc.h new file mode 100644 index 00000000..4f45aca3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/ipc.h @@ -0,0 +1,62 @@ +/* Copyright (C) 1995-1999, 2000, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_IPC_H +# error "Never use directly; include instead." +#endif + +#include + +/* Mode bits for `msgget', `semget', and `shmget'. */ +#define IPC_CREAT 01000 /* Create key if key does not exist. */ +#define IPC_EXCL 02000 /* Fail if key exists. */ +#define IPC_NOWAIT 04000 /* Return error on wait. */ + +/* Control commands for `msgctl', `semctl', and `shmctl'. */ +#define IPC_RMID 0 /* Remove identifier. */ +#define IPC_SET 1 /* Set `ipc_perm' options. */ +#define IPC_STAT 2 /* Get `ipc_perm' options. */ +#ifdef __USE_GNU +# define IPC_INFO 3 /* See ipcs. */ +#endif + +/* Special key values. */ +#define IPC_PRIVATE ((__key_t) 0) /* Private key. */ + + +/* Data structure used to pass permission information to IPC operations. */ +struct ipc_perm + { + __key_t __key; /* Key. */ + __uid_t uid; /* Owner's user ID. */ + __gid_t gid; /* Owner's group ID. */ + __uid_t cuid; /* Creator's user ID. */ + __gid_t cgid; /* Creator's group ID. */ + __mode_t mode; /* Read/write permission. */ +#if 0 + unsigned long __seq; /* Sequence number. */ + unsigned int __pad2; + unsigned long long int __unused1; + unsigned long long int __unused2; +#else + __uint32_t __seq; /* Sequence number. */ + __uint32_t __pad1; + __uint64_t __unused1; + __uint64_t __unused2; +#endif + }; diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/kernel_stat.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/kernel_stat.h new file mode 100644 index 00000000..d8a9bc2e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/kernel_stat.h @@ -0,0 +1,54 @@ +#ifndef _BITS_STAT_STRUCT_H +#define _BITS_STAT_STRUCT_H + +#ifndef _LIBC +#error bits/kernel_stat.h is for internal uClibc use only! +#endif + +/* This file provides whatever this particular arch's kernel thinks + * struct kernel_stat should look like... It turns out each arch has a + * different opinion on the subject... */ + +#if __WORDSIZE == 64 +#define kernel_stat kernel_stat64 +#else +struct kernel_stat { + __kernel_dev_t st_dev; + __kernel_ino_t st_ino; + __kernel_mode_t st_mode; + __kernel_nlink_t st_nlink; + __kernel_uid_t st_uid; + __kernel_gid_t st_gid; + __kernel_dev_t st_rdev; + __kernel_off_t st_size; + unsigned long st_blksize; + unsigned long st_blocks; + struct timespec st_atim; + struct timespec st_mtim; + struct timespec st_ctim; + unsigned long __unused4; + unsigned long __unused5; +}; +#endif + +struct kernel_stat64 { + unsigned long long st_dev; /* Device. */ + unsigned long long st_ino; /* File serial number. */ + unsigned int st_mode; /* File mode. */ + unsigned int st_nlink; /* Link count. */ + unsigned int st_uid; /* User ID of the file's owner. */ + unsigned int st_gid; /* Group ID of the file's group. */ + unsigned long long st_rdev; /* Device number, if device. */ + unsigned short int __pad2; + long long st_size; /* Size of file, in bytes. */ + long st_blksize; /* Optimal block size for I/O. */ + long long st_blocks; /* Number 512-byte blocks allocated. */ + struct timespec st_atim; /* Time of last access. */ + struct timespec st_mtim; /* Time of last modification. */ + struct timespec st_ctim; /* Time of last status change. */ + unsigned long int __unused4; + unsigned long int __unused5; +}; + +#endif /* _BITS_STAT_STRUCT_H */ + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/kernel_types.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/kernel_types.h new file mode 100644 index 00000000..3f3b9337 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/kernel_types.h @@ -0,0 +1,72 @@ +/* Note that we use the exact same include guard #define names + * as asm/posix_types.h. This will avoid gratuitous conflicts + * with the posix_types.h kernel header, and will ensure that + * our private content, and not the kernel header, will win. + * -Erik + */ +#if ! defined _PPC_POSIX_TYPES_H && ! defined _PPC64_POSIX_TYPES_H && \ + ! defined _ASM_POWERPC_POSIX_TYPES_H +#define _PPC_POSIX_TYPES_H +#define _PPC64_POSIX_TYPES_H +#define _ASM_POWERPC_POSIX_TYPES_H + +# if __WORDSIZE == 64 +typedef unsigned int __kernel_dev_t; +typedef unsigned int __kernel_ino_t; +typedef unsigned int __kernel_nlink_t; +typedef unsigned int __kernel_mode_t; +typedef long __kernel_off_t; +typedef long long __kernel_loff_t; +typedef int __kernel_pid_t; +typedef int __kernel_ipc_pid_t; +typedef unsigned int __kernel_uid_t; +typedef unsigned int __kernel_gid_t; +typedef unsigned long __kernel_size_t; +typedef long __kernel_ssize_t; +typedef long __kernel_ptrdiff_t; +typedef long __kernel_time_t; +typedef long __kernel_suseconds_t; +typedef long __kernel_clock_t; +typedef int __kernel_daddr_t; +typedef char * __kernel_caddr_t; +typedef unsigned short __kernel_uid16_t; +typedef unsigned short __kernel_gid16_t; +typedef unsigned int __kernel_uid32_t; +typedef unsigned int __kernel_gid32_t; +typedef unsigned int __kernel_old_uid_t; +typedef unsigned int __kernel_old_gid_t; +typedef __kernel_dev_t __kernel_old_dev_t; +#else +typedef unsigned int __kernel_dev_t; +typedef unsigned int __kernel_ino_t; +typedef unsigned int __kernel_mode_t; +typedef unsigned short __kernel_nlink_t; +typedef long __kernel_off_t; +typedef int __kernel_pid_t; +typedef unsigned int __kernel_uid_t; +typedef unsigned int __kernel_gid_t; +typedef unsigned int __kernel_size_t; +typedef int __kernel_ssize_t; +typedef long __kernel_ptrdiff_t; +typedef long __kernel_time_t; +typedef long __kernel_suseconds_t; +typedef long __kernel_clock_t; +typedef int __kernel_daddr_t; +typedef char * __kernel_caddr_t; +typedef short __kernel_ipc_pid_t; +typedef unsigned short __kernel_uid16_t; +typedef unsigned short __kernel_gid16_t; +typedef unsigned int __kernel_uid32_t; +typedef unsigned int __kernel_gid32_t; +typedef unsigned int __kernel_old_uid_t; +typedef unsigned int __kernel_old_gid_t; +typedef __kernel_dev_t __kernel_old_dev_t; +typedef long long __kernel_loff_t; +#endif + +typedef struct { + int val[2]; +} __kernel_fsid_t; + +#endif /* ! defined _PPC_POSIX_TYPES_H && ! defined _PPC64_POSIX_TYPES_H */ + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/mathdef.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/mathdef.h new file mode 100644 index 00000000..c64b8a39 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/mathdef.h @@ -0,0 +1,54 @@ +/* Copyright (C) 1997,1998,1999,2000,2003,2004,2006 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#if !defined _MATH_H && !defined _COMPLEX_H +# error "Never use directly; include instead" +#endif + + +/* FIXME! This file describes properties of the compiler, not the machine; + it should not be part of libc! + + FIXME! This file does not deal with the -fshort-double option of + gcc! */ + +#if defined __USE_ISOC99 && defined _MATH_H && !defined _MATH_H_MATHDEF +# define _MATH_H_MATHDEF 1 + +/* PowerPC has both `float' and `double' arithmetic. */ +typedef float float_t; /* `float' expressions are evaluated as + `float'. */ +typedef double double_t; /* `double' expressions are evaluated as + `double'. */ + +/* The values returned by `ilogb' for 0 and NaN respectively. */ +# define FP_ILOGB0 (-2147483647) +# define FP_ILOGBNAN (2147483647) + +#endif /* ISO C99 */ + +#ifndef __NO_LONG_DOUBLE_MATH +/* Signal that we do not really have a `long double'. The disables the + declaration of all the `long double' function variants. */ +# if !defined __UCLIBC_HAS_LONG_DOUBLE_MATH__ +# define __NO_LONG_DOUBLE_MATH 1 +# endif +#endif /* __NO_LONG_DOUBLE_MATH */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/mathinline.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/mathinline.h new file mode 100644 index 00000000..d1b05f38 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/mathinline.h @@ -0,0 +1,185 @@ +/* Inline math functions for powerpc. + Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2004, 2006 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#ifndef _MATH_H +# error "Never use directly; include instead." +#endif + +#ifdef __cplusplus +# define __MATH_INLINE __inline +#else +# define __MATH_INLINE extern __inline +#endif /* __cplusplus */ + +#if defined __GNUC__ && !defined _SOFT_FLOAT + +#ifdef __USE_ISOC99 +# if !__GNUC_PREREQ (2,97) +# define __unordered_cmp(x, y) \ + (__extension__ \ + ({ __typeof__(x) __x = (x); __typeof__(y) __y = (y); \ + unsigned __r; \ + __asm__("fcmpu 7,%1,%2 ; mfcr %0" : "=r" (__r) : "f" (__x), "f"(__y) \ + : "cr7"); \ + __r; })) + +# undef isgreater +# undef isgreaterequal +# undef isless +# undef islessequal +# undef islessgreater +# undef isunordered + +# define isgreater(x, y) (__unordered_cmp (x, y) >> 2 & 1) +# define isgreaterequal(x, y) ((__unordered_cmp (x, y) & 6) != 0) +# define isless(x, y) (__unordered_cmp (x, y) >> 3 & 1) +# define islessequal(x, y) ((__unordered_cmp (x, y) & 0xA) != 0) +# define islessgreater(x, y) ((__unordered_cmp (x, y) & 0xC) != 0) +# define isunordered(x, y) (__unordered_cmp (x, y) & 1) + +# endif /* __GNUC_PREREQ (2,97) */ + +/* The gcc, version 2.7 or below, has problems with all this inlining + code. So disable it for this version of the compiler. */ +# if __GNUC_PREREQ (2, 8) +/* Test for negative number. Used in the signbit() macro. */ +__MATH_INLINE int +__NTH (__signbitf (float __x)) +{ + __extension__ union { float __f; int __i; } __u = { __f: __x }; + return __u.__i < 0; +} +__MATH_INLINE int +__NTH (__signbit (double __x)) +{ + __extension__ union { double __d; int __i[2]; } __u = { __d: __x }; + return __u.__i[0] < 0; +} +# endif +#endif /* __USE_ISOC99 */ + +#if !defined __NO_MATH_INLINES && defined __OPTIMIZE__ + +#ifdef __USE_ISOC99 + +# ifndef __powerpc64__ +__MATH_INLINE long int lrint (double __x) __THROW; +__MATH_INLINE long int +__NTH (lrint (double __x)) +{ + union { + double __d; + int __ll[2]; + } __u; + __asm__ ("fctiw %0,%1" : "=f"(__u.__d) : "f"(__x)); + return __u.__ll[1]; +} + +__MATH_INLINE long int lrintf (float __x) __THROW; +__MATH_INLINE long int +__NTH (lrintf (float __x)) +{ + union { + double __d; + int __ll[2]; + } __u; + __asm__ ("fctiw %0,%1" : "=f"(__u.__d) : "f"(__x)); + return __u.__ll[1]; +} +# endif + +__MATH_INLINE double fdim (double __x, double __y) __THROW; +__MATH_INLINE double +__NTH (fdim (double __x, double __y)) +{ + return __x <= __y ? 0 : __x - __y; +} + +__MATH_INLINE float fdimf (float __x, float __y) __THROW; +__MATH_INLINE float +__NTH (fdimf (float __x, float __y)) +{ + return __x <= __y ? 0 : __x - __y; +} + +#endif /* __USE_ISOC99 */ +#endif /* !__NO_MATH_INLINES && __OPTIMIZE__ */ + +/* This code is used internally in the GNU libc. */ +#if 0 /*def __LIBC_INTERNAL_MATH_INLINES*/ + +#include +#include +#include + +# if __WORDSIZE == 64 || defined _ARCH_PWR4 +# define __CPU_HAS_FSQRT 1 +# else +# define __CPU_HAS_FSQRT ((GLRO(dl_hwcap) & PPC_FEATURE_64) != 0) +# endif + +extern double __slow_ieee754_sqrt (double); +__MATH_INLINE double +__NTH (__ieee754_sqrt (double __x)) +{ + double __z; + + /* If the CPU is 64-bit we can use the optional FP instructions. */ + if (__CPU_HAS_FSQRT) + { + /* Volatile is required to prevent the compiler from moving the + fsqrt instruction above the branch. */ + __asm__ __volatile__ ( + " fsqrt %0,%1\n" + : "=f" (__z) + : "f" (__x)); + } + else + __z = __slow_ieee754_sqrt(__x); + + return __z; +} + +extern float __slow_ieee754_sqrtf (float); +__MATH_INLINE float +__NTH (__ieee754_sqrtf (float __x)) +{ + float __z; + + /* If the CPU is 64-bit we can use the optional FP instructions. */ + if (__CPU_HAS_FSQRT) + { + /* Volatile is required to prevent the compiler from moving the + fsqrts instruction above the branch. */ + __asm__ __volatile__ ( + " fsqrts %0,%1\n" + : "=f" (__z) + : "f" (__x)); + } + else + __z = __slow_ieee754_sqrtf(__x); + + return __z; +} +#endif /* __LIBC_INTERNAL_MATH_INLINES */ +#endif /* __GNUC__ && !_SOFT_FLOAT */ + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/mman.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/mman.h new file mode 100644 index 00000000..2d234c5f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/mman.h @@ -0,0 +1,106 @@ +/* Definitions for POSIX memory map interface. Linux/PowerPC version. + Copyright (C) 1997, 2000, 2003, 2005, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_MMAN_H +# error "Never use directly; iclude instead." +#endif + +/* The following definitions basically come from the kernel headers. + But the kernel header is not namespace clean. */ + + +/* Protections are chosen from these bits, OR'd together. The + implementation does not necessarily support PROT_EXEC or PROT_WRITE + without PROT_READ. The only guarantees are that no writing will be + allowed without PROT_WRITE and no access will be allowed for PROT_NONE. */ + +#define PROT_READ 0x1 /* Page can be read. */ +#define PROT_WRITE 0x2 /* Page can be written. */ +#define PROT_EXEC 0x4 /* Page can be executed. */ +#define PROT_NONE 0x0 /* Page can not be accessed. */ +#define PROT_GROWSDOWN 0x01000000 /* Extend change to start of + growsdown vma (mprotect only). */ +#define PROT_GROWSUP 0x02000000 /* Extend change to start of + growsup vma (mprotect only). */ + +/* Sharing types (must choose one and only one of these). */ +#define MAP_SHARED 0x001 /* Share changes. */ +#define MAP_PRIVATE 0x002 /* Changes are private. */ +#ifdef __USE_MISC +# define MAP_TYPE 0x00f /* Mask for type of mapping. */ +#endif + +/* Other flags. */ +#define MAP_FIXED 0x010 /* Interpret addr exactly. */ +#ifdef __USE_MISC +# define MAP_FILE 0x000 +# define MAP_ANONYMOUS 0x020 /* Don't use a file. */ +# define MAP_ANON MAP_ANONYMOUS +#endif + +/* These are Linux-specific. */ +#ifdef __USE_MISC +# define MAP_GROWSDOWN 0x00100 /* Stack-like segment. */ +# define MAP_DENYWRITE 0x00800 /* ETXTBSY */ +# define MAP_EXECUTABLE 0x01000 /* Mark it as an executable. */ +# define MAP_LOCKED 0x00080 /* Lock the mapping. */ +# define MAP_NORESERVE 0x00040 /* Don't check for reservations. */ +# define MAP_POPULATE 0x08000 /* Populate (prefault) pagetables. */ +# define MAP_NONBLOCK 0x10000 /* Do not block on IO. */ +# define MAP_UNINITIALIZE 0x4000000 /* For anonymous mmap, memory could + be uninitialized. */ +#endif + +/* Flags to `msync'. */ +#define MS_ASYNC 1 /* Sync memory asynchronously. */ +#define MS_SYNC 4 /* Synchronous memory sync. */ +#define MS_INVALIDATE 2 /* Invalidate the caches. */ + +/* Flags for `mlockall'. */ +#define MCL_CURRENT 0x2000 /* Lock all currently mapped pages. */ +#define MCL_FUTURE 0x4000 /* Lock all additions to address + space. */ + + +/* Flags for `mremap'. */ +#ifdef __USE_GNU +# define MREMAP_MAYMOVE 1 +# define MREMAP_FIXED 2 +#endif + +/* Advice to `madvise'. */ +#ifdef __USE_BSD +# define MADV_NORMAL 0 /* No further special treatment. */ +# define MADV_RANDOM 1 /* Expect random page references. */ +# define MADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define MADV_WILLNEED 3 /* Will need these pages. */ +# define MADV_DONTNEED 4 /* Don't need these pages. */ +# define MADV_REMOVE 9 /* Remove these pages and resources. */ +# define MADV_DONTFORK 10 /* Do not inherit across fork. */ +# define MADV_DOFORK 11 /* Do inherit across fork. */ +#endif + +/* The POSIX people had to invent similar names for the same things. */ +#ifdef __USE_XOPEN2K +# define POSIX_MADV_NORMAL 0 /* No further special treatment. */ +# define POSIX_MADV_RANDOM 1 /* Expect random page references. */ +# define POSIX_MADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define POSIX_MADV_WILLNEED 3 /* Will need these pages. */ +# define POSIX_MADV_DONTNEED 4 /* Don't need these pages. */ +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/msq.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/msq.h new file mode 100644 index 00000000..f1988443 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/msq.h @@ -0,0 +1,83 @@ +/* Copyright (C) 1995, 1996, 1997, 2000, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_MSG_H +# error "Never use directly; include instead." +#endif + +#include + +/* Define options for message queue functions. */ +#define MSG_NOERROR 010000 /* no error if message is too big */ +#ifdef __USE_GNU +# define MSG_EXCEPT 020000 /* recv any msg except of specified type */ +#endif + +/* Types used in the structure definition. */ +typedef unsigned long int msgqnum_t; +typedef unsigned long int msglen_t; + + +/* Structure of record for one message inside the kernel. + The type `struct msg' is opaque. */ +struct msqid_ds +{ + struct ipc_perm msg_perm; /* structure describing operation permission */ +#if __WORDSIZE == 32 + unsigned int __unused1; +#endif + __time_t msg_stime; /* time of last msgsnd command */ +#if __WORDSIZE == 32 + unsigned int __unused2; +#endif + __time_t msg_rtime; /* time of last msgrcv command */ +#if __WORDSIZE == 32 + unsigned int __unused3; +#endif + __time_t msg_ctime; /* time of last change */ + unsigned long __msg_cbytes; /* current number of bytes on queue */ + msgqnum_t msg_qnum; /* number of messages currently on queue */ + msglen_t msg_qbytes; /* max number of bytes allowed on queue */ + __pid_t msg_lspid; /* pid of last msgsnd() */ + __pid_t msg_lrpid; /* pid of last msgrcv() */ + unsigned long __unused4; + unsigned long __unused5; +}; + +#ifdef __USE_MISC + +# define msg_cbytes __msg_cbytes + +/* ipcs ctl commands */ +# define MSG_STAT 11 +# define MSG_INFO 12 + +/* buffer for msgctl calls IPC_INFO, MSG_INFO */ +struct msginfo + { + int msgpool; + int msgmap; + int msgmax; + int msgmnb; + int msgmni; + int msgssz; + int msgtql; + unsigned short int msgseg; + }; + +#endif /* __USE_MISC */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/sem.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/sem.h new file mode 100644 index 00000000..92a7a904 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/sem.h @@ -0,0 +1,92 @@ +/* Copyright (C) 1995, 1996, 1997, 1998, 2000, 2002 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_SEM_H +# error "Never include directly; use instead." +#endif + +#include + +/* Flags for `semop'. */ +#define SEM_UNDO 0x1000 /* undo the operation on exit */ + +/* Commands for `semctl'. */ +#define GETPID 11 /* get sempid */ +#define GETVAL 12 /* get semval */ +#define GETALL 13 /* get all semval's */ +#define GETNCNT 14 /* get semncnt */ +#define GETZCNT 15 /* get semzcnt */ +#define SETVAL 16 /* set semval */ +#define SETALL 17 /* set all semval's */ + + +/* Data structure describing a set of semaphores. */ +struct semid_ds +{ + struct ipc_perm sem_perm; /* operation permission struct */ +#if __WORDSIZE == 32 + unsigned int __unused1; +#endif + __time_t sem_otime; /* last semop() time */ +#if __WORDSIZE == 32 + unsigned int __unused2; +#endif + __time_t sem_ctime; /* last time changed by semctl() */ + unsigned long int sem_nsems; /* number of semaphores in set */ + unsigned long __unused3; + unsigned long __unused4; +}; + +/* The user should define a union like the following to use it for arguments + for `semctl'. + + union semun + { + int val; <= value for SETVAL + struct semid_ds *buf; <= buffer for IPC_STAT & IPC_SET + unsigned short int *array; <= array for GETALL & SETALL + struct seminfo *__buf; <= buffer for IPC_INFO + }; + + Previous versions of this file used to define this union but this is + incorrect. One can test the macro _SEM_SEMUN_UNDEFINED to see whether + one must define the union or not. */ +#define _SEM_SEMUN_UNDEFINED 1 + +#ifdef __USE_MISC + +/* ipcs ctl cmds */ +# define SEM_STAT 18 +# define SEM_INFO 19 + +struct seminfo +{ + int semmap; + int semmni; + int semmns; + int semmnu; + int semmsl; + int semopm; + int semume; + int semusz; + int semvmx; + int semaem; +}; + +#endif /* __USE_MISC */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/setjmp.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/setjmp.h new file mode 100644 index 00000000..dad90c74 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/setjmp.h @@ -0,0 +1,80 @@ +/* Copyright (C) 1997, 1998, 2000, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Define the machine-dependent type `jmp_buf'. PowerPC version. */ +#ifndef _BITS_SETJMP_H +#define _BITS_SETJMP_H 1 + +#if !defined _SETJMP_H && !defined _PTHREAD_H +# error "Never include directly; use instead." +#endif + +/* The previous bits/setjmp.h had __jmp_buf defined as a structure. + We use an array of 'long int' instead, to make writing the + assembler easier. Naturally, user code should not depend on + either representation. */ + +#include + +#if defined __USE_MISC || defined _ASM +# define JB_GPR1 0 /* Also known as the stack pointer */ +# define JB_GPR2 1 +# define JB_LR 2 /* The address we will return to */ +# if __WORDSIZE == 64 +# define JB_GPRS 3 /* GPRs 14 through 31 are saved, 18*2 words total. */ +# define JB_CR 21 /* Condition code registers with the VRSAVE at */ + /* offset 172 (low half of the double word. */ +# define JB_FPRS 22 /* FPRs 14 through 31 are saved, 18*2 words total. */ +# define JB_SIZE (64 * 8) /* As per PPC64-VMX ABI. */ +# define JB_VRSAVE 21 /* VRSAVE shares a double word with the CR at offset */ + /* 168 (high half of the double word). */ +# define JB_VRS 40 /* VRs 20 through 31 are saved, 12*4 words total. */ +# else +# define JB_GPRS 3 /* GPRs 14 through 31 are saved, 18 in total. */ +# define JB_CR 21 /* Condition code registers. */ +# define JB_FPRS 22 /* FPRs 14 through 31 are saved, 18*2 words total. */ +# define JB_SIZE ((64 + (12 * 4)) * 4) +# define JB_VRSAVE 62 +# define JB_VRS 64 +# endif +#endif + + +/* The current powerpc 32-bit Altivec ABI specifies for SVR4 ABI and EABI + the vrsave must be at byte 248 & v20 at byte 256. So we must pad this + correctly on 32 bit. It also insists that vecregs are only gauranteed + 4 byte alignment so we need to use vperm in the setjmp/longjmp routines. + We have to version the code because members like int __mask_was_saved + in the jmp_buf will move as jmp_buf is now larger than 248 bytes. We + cannot keep the altivec jmp_buf backward compatible with the jmp_buf. */ +#ifndef _ASM +# if __WORDSIZE == 64 +typedef long int __jmp_buf[64] __attribute__ ((__aligned__ (16))); +# else +/* The alignment is not essential, i.e.the buffer can be copied to a 4 byte + aligned buffer as per the ABI it is just added for performance reasons. */ +typedef long int __jmp_buf[64 + (12 * 4)] __attribute__ ((__aligned__ (16))); +# endif +#endif + +/* Test if longjmp to JMPBUF would unwind the frame + containing a local variable at ADDRESS. */ +#define _JMPBUF_UNWINDS(jmpbuf, address) \ + ((void *) (address) < (void *) (jmpbuf)[JB_GPR1]) + +#endif /* bits/setjmp.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/shm.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/shm.h new file mode 100644 index 00000000..62560c0c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/shm.h @@ -0,0 +1,113 @@ +/* Copyright (C) 1995, 1996, 1997, 2000, 2002, 2004 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_SHM_H +# error "Never include directly; use instead." +#endif + +#include + +/* Permission flag for shmget. */ +#define SHM_R 0400 /* or S_IRUGO from */ +#define SHM_W 0200 /* or S_IWUGO from */ + +/* Flags for `shmat'. */ +#define SHM_RDONLY 010000 /* attach read-only else read-write */ +#define SHM_RND 020000 /* round attach address to SHMLBA */ +#define SHM_REMAP 040000 /* take-over region on attach */ + +/* Commands for `shmctl'. */ +#define SHM_LOCK 11 /* lock segment (root only) */ +#define SHM_UNLOCK 12 /* unlock segment (root only) */ + +__BEGIN_DECLS + +/* Segment low boundary address multiple. */ +#define SHMLBA (__getpagesize ()) +extern int __getpagesize (void) __THROW __attribute__ ((__const__)); + + +/* Type to count number of attaches. */ +typedef unsigned long int shmatt_t; + +/* Data structure describing a set of semaphores. */ +struct shmid_ds + { + struct ipc_perm shm_perm; /* operation permission struct */ +#if __WORDSIZE == 32 + unsigned int __unused1; +#endif + __time_t shm_atime; /* time of last shmat() */ +#if __WORDSIZE == 32 + unsigned int __unused2; +#endif + __time_t shm_dtime; /* time of last shmdt() */ +#if __WORDSIZE == 32 + unsigned int __unused3; +#endif + __time_t shm_ctime; /* time of last change by shmctl() */ +#if __WORDSIZE == 32 + unsigned int __unused4; +#endif + size_t shm_segsz; /* size of segment in bytes */ + __pid_t shm_cpid; /* pid of creator */ + __pid_t shm_lpid; /* pid of last shmop */ + shmatt_t shm_nattch; /* number of current attaches */ + unsigned long __unused5; + unsigned long __unused6; + }; + +#ifdef __USE_MISC + +/* ipcs ctl commands */ +# define SHM_STAT 13 +# define SHM_INFO 14 + +/* shm_mode upper byte flags */ +# define SHM_DEST 01000 /* segment will be destroyed on last detach */ +# define SHM_LOCKED 02000 /* segment will not be swapped */ +# define SHM_HUGETLB 04000 /* segment is mapped via hugetlb */ +# define SHM_NORESERVE 010000 /* don't check for reservations */ + +struct shminfo + { + unsigned long int shmmax; + unsigned long int shmmin; + unsigned long int shmmni; + unsigned long int shmseg; + unsigned long int shmall; + unsigned long int __unused1; + unsigned long int __unused2; + unsigned long int __unused3; + unsigned long int __unused4; + }; + +struct shm_info + { + int used_ids; + unsigned long int shm_tot; /* total allocated shm */ + unsigned long int shm_rss; /* total resident shm */ + unsigned long int shm_swp; /* total swapped shm */ + unsigned long int swap_attempts; + unsigned long int swap_successes; + }; + +#endif /* __USE_MISC */ + +__END_DECLS diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/sigcontextinfo.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/sigcontextinfo.h new file mode 100644 index 00000000..138a15cf --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/sigcontextinfo.h @@ -0,0 +1,27 @@ +/* Copyright (C) 1998, 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#define SIGCONTEXT struct sigcontext * +#define SIGCONTEXT_EXTRA_ARGS +#define GET_PC(ctx) ((void *)((ctx)->regs->nip)) +#define GET_FRAME(ctx) (*(void **)((ctx)->regs->gpr[1])) +#define GET_STACK(ctx) ((void *)((ctx)->regs->gpr[1])) +#define CALL_SIGHANDLER(handler, signo, ctx) \ + (handler)((signo), SIGCONTEXT_EXTRA_ARGS (ctx)) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/stackinfo.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/stackinfo.h new file mode 100644 index 00000000..839758a4 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/stackinfo.h @@ -0,0 +1,28 @@ +/* Copyright (C) 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This file contains a bit of information about the stack allocation + of the processor. */ + +#ifndef _STACKINFO_H +#define _STACKINFO_H 1 + +/* On PPC the stack grows down. */ +#define _STACK_GROWS_DOWN 1 + +#endif /* stackinfo.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/stat.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/stat.h new file mode 100644 index 00000000..b6c82c55 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/stat.h @@ -0,0 +1,272 @@ +/* Copyright (C) 1992, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2009 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_STAT_H +# error "Never include directly; use instead." +#endif + +#include + +/* Versions of the `struct stat' data structure. */ +#define _STAT_VER_LINUX_OLD 1 +#define _STAT_VER_KERNEL 1 +#define _STAT_VER_SVR4 2 +#define _STAT_VER_LINUX 3 +#if __WORDSIZE == 32 +# define _STAT_VER _STAT_VER_LINUX +#else +# define _STAT_VER _STAT_VER_KERNEL +#endif + +/* Versions of the `xmknod' interface. */ +#define _MKNOD_VER_LINUX 1 +#define _MKNOD_VER_SVR4 2 +#define _MKNOD_VER _MKNOD_VER_LINUX /* The bits defined below. */ + + +#if __WORDSIZE == 32 + +struct stat + { + __dev_t st_dev; /* Device. */ +# ifndef __USE_FILE_OFFSET64 + unsigned short int __pad1; + __ino_t st_ino; /* File serial number. */ +# else + __ino64_t st_ino; /* File serial number. */ +# endif + __mode_t st_mode; /* File mode. */ + __nlink_t st_nlink; /* Link count. */ + __uid_t st_uid; /* User ID of the file's owner. */ + __gid_t st_gid; /* Group ID of the file's group.*/ + __dev_t st_rdev; /* Device number, if device. */ + unsigned short int __pad2; +# ifndef __USE_FILE_OFFSET64 + __off_t st_size; /* Size of file, in bytes. */ +# else + __off64_t st_size; /* Size of file, in bytes. */ +# endif + __blksize_t st_blksize; /* Optimal block size for I/O. */ + +# ifndef __USE_FILE_OFFSET64 + __blkcnt_t st_blocks; /* Number 512-byte blocks allocated. */ +# else + __blkcnt64_t st_blocks; /* Number 512-byte blocks allocated. */ +# endif +#ifdef __USE_MISC + /* Nanosecond resolution timestamps are stored in a format + equivalent to 'struct timespec'. This is the type used + whenever possible but the Unix namespace rules do not allow the + identifier 'timespec' to appear in the header. + Therefore we have to handle the use of this header in strictly + standard-compliant sources special. */ + struct timespec st_atim; /* Time of last access. */ + struct timespec st_mtim; /* Time of last modification. */ + struct timespec st_ctim; /* Time of last status change. */ +# define st_atime st_atim.tv_sec /* Backward compatibility. */ +# define st_mtime st_mtim.tv_sec +# define st_ctime st_ctim.tv_sec +#else + __time_t st_atime; /* Time of last access. */ + unsigned long int st_atimensec; /* Nscecs of last access. */ + __time_t st_mtime; /* Time of last modification. */ + unsigned long int st_mtimensec; /* Nsecs of last modification. */ + __time_t st_ctime; /* Time of last status change. */ + unsigned long int st_ctimensec; /* Nsecs of last status change. */ +#endif + unsigned long int __unused4; + unsigned long int __unused5; + }; + + +# ifdef __USE_LARGEFILE64 +struct stat64 + { + __dev_t st_dev; /* Device. */ + __ino64_t st_ino; /* File serial number. */ + __mode_t st_mode; /* File mode. */ + __nlink_t st_nlink; /* Link count. */ + __uid_t st_uid; /* User ID of the file's owner. */ + __gid_t st_gid; /* Group ID of the file's group.*/ + __dev_t st_rdev; /* Device number, if device. */ + unsigned short int __pad2; + __off64_t st_size; /* Size of file, in bytes. */ + __blksize_t st_blksize; /* Optimal block size for I/O. */ + __blkcnt64_t st_blocks; /* Number 512-byte blocks allocated. */ +#ifdef __USE_MISC + /* Nanosecond resolution timestamps are stored in a format + equivalent to 'struct timespec'. This is the type used + whenever possible but the Unix namespace rules do not allow the + identifier 'timespec' to appear in the header. + Therefore we have to handle the use of this header in strictly + standard-compliant sources special. */ + struct timespec st_atim; /* Time of last access. */ + struct timespec st_mtim; /* Time of last modification. */ + struct timespec st_ctim; /* Time of last status change. */ +# define st_atime st_atim.tv_sec /* Backward compatibility. */ +# define st_mtime st_mtim.tv_sec +# define st_ctime st_ctim.tv_sec +#else + __time_t st_atime; /* Time of last access. */ + unsigned long int st_atimensec; /* Nscecs of last access. */ + __time_t st_mtime; /* Time of last modification. */ + unsigned long int st_mtimensec; /* Nsecs of last modification. */ + __time_t st_ctime; /* Time of last status change. */ + unsigned long int st_ctimensec; /* Nsecs of last status change. */ +#endif + unsigned long int __unused4; + unsigned long int __unused5; + }; +# endif /* __USE_LARGEFILE64 */ + +#else /* __WORDSIZE == 32 */ + +struct stat + { + __dev_t st_dev; /* Device. */ +# ifndef __USE_FILE_OFFSET64 + __ino_t st_ino; /* File serial number. */ +# else + __ino64_t st_ino; /* File serial number. */ +# endif + __nlink_t st_nlink; /* Link count. */ + __mode_t st_mode; /* File mode. */ + __uid_t st_uid; /* User ID of the file's owner. */ + __gid_t st_gid; /* Group ID of the file's group.*/ + int __pad2; + __dev_t st_rdev; /* Device number, if device. */ +# ifndef __USE_FILE_OFFSET64 + __off_t st_size; /* Size of file, in bytes. */ +# else + __off64_t st_size; /* Size of file, in bytes. */ +# endif + __blksize_t st_blksize; /* Optimal block size for I/O. */ + +# ifndef __USE_FILE_OFFSET64 + __blkcnt_t st_blocks; /* Number 512-byte blocks allocated. */ +# else + __blkcnt64_t st_blocks; /* Number 512-byte blocks allocated. */ +# endif +#ifdef __USE_MISC + /* Nanosecond resolution timestamps are stored in a format + equivalent to 'struct timespec'. This is the type used + whenever possible but the Unix namespace rules do not allow the + identifier 'timespec' to appear in the header. + Therefore we have to handle the use of this header in strictly + standard-compliant sources special. */ + struct timespec st_atim; /* Time of last access. */ + struct timespec st_mtim; /* Time of last modification. */ + struct timespec st_ctim; /* Time of last status change. */ +# define st_atime st_atim.tv_sec /* Backward compatibility. */ +# define st_mtime st_mtim.tv_sec +# define st_ctime st_ctim.tv_sec +#else + __time_t st_atime; /* Time of last access. */ + unsigned long int st_atimensec; /* Nscecs of last access. */ + __time_t st_mtime; /* Time of last modification. */ + unsigned long int st_mtimensec; /* Nsecs of last modification. */ + __time_t st_ctime; /* Time of last status change. */ + unsigned long int st_ctimensec; /* Nsecs of last status change. */ +#endif + unsigned long int __unused4; + unsigned long int __unused5; + unsigned long int __unused6; + }; + +# ifdef __USE_LARGEFILE64 +struct stat64 + { + __dev_t st_dev; /* Device. */ + __ino64_t st_ino; /* File serial number. */ + __nlink_t st_nlink; /* Link count. */ + __mode_t st_mode; /* File mode. */ + __uid_t st_uid; /* User ID of the file's owner. */ + __gid_t st_gid; /* Group ID of the file's group.*/ + int __pad2; + __dev_t st_rdev; /* Device number, if device. */ + __off64_t st_size; /* Size of file, in bytes. */ + __blksize_t st_blksize; /* Optimal block size for I/O. */ + __blkcnt64_t st_blocks; /* Number 512-byte blocks allocated. */ +#ifdef __USE_MISC + /* Nanosecond resolution timestamps are stored in a format + equivalent to 'struct timespec'. This is the type used + whenever possible but the Unix namespace rules do not allow the + identifier 'timespec' to appear in the header. + Therefore we have to handle the use of this header in strictly + standard-compliant sources special. */ + struct timespec st_atim; /* Time of last access. */ + struct timespec st_mtim; /* Time of last modification. */ + struct timespec st_ctim; /* Time of last status change. */ +# define st_atime st_atim.tv_sec /* Backward compatibility. */ +# define st_mtime st_mtim.tv_sec +# define st_ctime st_ctim.tv_sec +#else + __time_t st_atime; /* Time of last access. */ + unsigned long int st_atimensec; /* Nscecs of last access. */ + __time_t st_mtime; /* Time of last modification. */ + unsigned long int st_mtimensec; /* Nsecs of last modification. */ + __time_t st_ctime; /* Time of last status change. */ + unsigned long int st_ctimensec; /* Nsecs of last status change. */ +#endif + unsigned long int __unused4; + unsigned long int __unused5; + unsigned long int __unused6; + }; +# endif /* __USE_LARGEFILE64 */ +#endif + + +/* Tell code we have these members. */ +#define _STATBUF_ST_BLKSIZE +#define _STATBUF_ST_RDEV +/* Nanosecond resolution time values are supported. */ +#define _STATBUF_ST_NSEC + +/* Encoding of the file mode. */ + +#define __S_IFMT 0170000 /* These bits determine file type. */ + +/* File types. */ +#define __S_IFDIR 0040000 /* Directory. */ +#define __S_IFCHR 0020000 /* Character device. */ +#define __S_IFBLK 0060000 /* Block device. */ +#define __S_IFREG 0100000 /* Regular file. */ +#define __S_IFIFO 0010000 /* FIFO. */ +#define __S_IFLNK 0120000 /* Symbolic link. */ +#define __S_IFSOCK 0140000 /* Socket. */ + +/* POSIX.1b objects. Note that these macros always evaluate to zero. But + they do it by enforcing the correct use of the macros. */ +#define __S_TYPEISMQ(buf) ((buf)->st_mode - (buf)->st_mode) +#define __S_TYPEISSEM(buf) ((buf)->st_mode - (buf)->st_mode) +#define __S_TYPEISSHM(buf) ((buf)->st_mode - (buf)->st_mode) + +/* Protection bits. */ + +#define __S_ISUID 04000 /* Set user ID on execution. */ +#define __S_ISGID 02000 /* Set group ID on execution. */ +#define __S_ISVTX 01000 /* Save swapped text after use (sticky). */ +#define __S_IREAD 0400 /* Read by owner. */ +#define __S_IWRITE 0200 /* Write by owner. */ +#define __S_IEXEC 0100 /* Execute by owner. */ + +#ifdef __USE_ATFILE +# define UTIME_NOW ((1l << 30) - 1l) +# define UTIME_OMIT ((1l << 30) - 2l) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/syscalls.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/syscalls.h new file mode 100644 index 00000000..1c7b929b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/syscalls.h @@ -0,0 +1,255 @@ +/* Copyright (C) 1992,1997-2003,2004,2005,2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _BITS_SYSCALLS_H +#define _BITS_SYSCALLS_H + +#ifndef _SYSCALL_H +# error "Never use directly; include instead." +#endif + +#ifndef __ASSEMBLER__ + +# include + +# ifdef SHARED +# define INLINE_VSYSCALL(name, nr, args...) \ + ({ \ + __label__ out; \ + __label__ iserr; \ + INTERNAL_SYSCALL_DECL (sc_err); \ + long int sc_ret; \ + \ + if (__vdso_##name != NULL) \ + { \ + sc_ret = INTERNAL_VSYSCALL_NCS (__vdso_##name, sc_err, nr, ##args); \ + if (!INTERNAL_SYSCALL_ERROR_P (sc_ret, sc_err)) \ + goto out; \ + if (INTERNAL_SYSCALL_ERRNO (sc_ret, sc_err) != ENOSYS) \ + goto iserr; \ + } \ + \ + sc_ret = INTERNAL_SYSCALL (name, sc_err, nr, ##args); \ + if (INTERNAL_SYSCALL_ERROR_P (sc_ret, sc_err)) \ + { \ + iserr: \ + __set_errno (INTERNAL_SYSCALL_ERRNO (sc_ret, sc_err)); \ + sc_ret = -1L; \ + } \ + out: \ + sc_ret; \ + }) +# else +# define INLINE_VSYSCALL(name, nr, args...) \ + INLINE_SYSCALL (name, nr, ##args) +# endif + +# ifdef SHARED +# define INTERNAL_VSYSCALL(name, err, nr, args...) \ + ({ \ + __label__ out; \ + long int v_ret; \ + \ + if (__vdso_##name != NULL) \ + { \ + v_ret = INTERNAL_VSYSCALL_NCS (__vdso_##name, err, nr, ##args); \ + if (!INTERNAL_SYSCALL_ERROR_P (v_ret, err) \ + || INTERNAL_SYSCALL_ERRNO (v_ret, err) != ENOSYS) \ + goto out; \ + } \ + v_ret = INTERNAL_SYSCALL (name, err, nr, ##args); \ + out: \ + v_ret; \ + }) +# else +# define INTERNAL_VSYSCALL(name, err, nr, args...) \ + INTERNAL_SYSCALL (name, err, nr, ##args) +# endif + +# define INTERNAL_VSYSCALL_NO_SYSCALL_FALLBACK(name, err, nr, args...) \ + ({ \ + long int sc_ret = ENOSYS; \ + \ + if (__vdso_##name != NULL) \ + sc_ret = INTERNAL_VSYSCALL_NCS (__vdso_##name, err, nr, ##args); \ + else \ + err = 1 << 28; \ + sc_ret; \ + }) + +/* List of system calls which are supported as vsyscalls. */ +# define HAVE_CLOCK_GETRES_VSYSCALL 1 +# define HAVE_CLOCK_GETTIME_VSYSCALL 1 + +/* Define a macro which expands inline into the wrapper code for a VDSO + call. This use is for internal calls that do not need to handle errors + normally. It will never touch errno. + On powerpc a system call basically clobbers the same registers like a + function call, with the exception of LR (which is needed for the + "sc; bnslr+" sequence) and CR (where only CR0.SO is clobbered to signal + an error return status). */ +# define INTERNAL_VSYSCALL_NCS(funcptr, err, nr, args...) \ + ({ \ + register void *r0 __asm__ ("r0"); \ + register long int r3 __asm__ ("r3"); \ + register long int r4 __asm__ ("r4"); \ + register long int r5 __asm__ ("r5"); \ + register long int r6 __asm__ ("r6"); \ + register long int r7 __asm__ ("r7"); \ + register long int r8 __asm__ ("r8"); \ + register long int r9 __asm__ ("r9"); \ + register long int r10 __asm__ ("r10"); \ + register long int r11 __asm__ ("r11"); \ + register long int r12 __asm__ ("r12"); \ + LOAD_ARGS_##nr (funcptr, args); \ + __asm__ __volatile__ \ + ("mtctr %0\n\t" \ + "bctrl\n\t" \ + "mfcr %0" \ + : "=&r" (r0), \ + "=&r" (r3), "=&r" (r4), "=&r" (r5), "=&r" (r6), "=&r" (r7), \ + "=&r" (r8), "=&r" (r9), "=&r" (r10), "=&r" (r11), "=&r" (r12) \ + : ASM_INPUT_##nr \ + : "cr0", "ctr", "lr", "memory"); \ + err = (long int) r0; \ + (int) r3; \ + }) + +/* Define a macro which expands inline into the wrapper code for a system + call. This use is for internal calls that do not need to handle errors + normally. It will never touch errno. + On powerpc a system call basically clobbers the same registers like a + function call, with the exception of LR (which is needed for the + "sc; bnslr+" sequence) and CR (where only CR0.SO is clobbered to signal + an error return status). */ + +# define INTERNAL_SYSCALL_DECL(err) long int err + +# define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \ + ({ \ + register long int r0 __asm__ ("r0"); \ + register long int r3 __asm__ ("r3"); \ + register long int r4 __asm__ ("r4"); \ + register long int r5 __asm__ ("r5"); \ + register long int r6 __asm__ ("r6"); \ + register long int r7 __asm__ ("r7"); \ + register long int r8 __asm__ ("r8"); \ + register long int r9 __asm__ ("r9"); \ + register long int r10 __asm__ ("r10"); \ + register long int r11 __asm__ ("r11"); \ + register long int r12 __asm__ ("r12"); \ + LOAD_ARGS_##nr(name, args); \ + __asm__ __volatile__ \ + ("sc \n\t" \ + "mfcr %0" \ + : "=&r" (r0), \ + "=&r" (r3), "=&r" (r4), "=&r" (r5), "=&r" (r6), "=&r" (r7), \ + "=&r" (r8), "=&r" (r9), "=&r" (r10), "=&r" (r11), "=&r" (r12) \ + : ASM_INPUT_##nr \ + : "cr0", "ctr", "memory"); \ + err = r0; \ + (int) r3; \ + }) + +# define INTERNAL_SYSCALL_ERROR_P(val, err) \ + ((void) (val), __builtin_expect ((err) & (1 << 28), 0)) + +# define INTERNAL_SYSCALL_ERRNO(val, err) (val) + +extern void __illegally_sized_syscall_arg1(void); +extern void __illegally_sized_syscall_arg2(void); +extern void __illegally_sized_syscall_arg3(void); +extern void __illegally_sized_syscall_arg4(void); +extern void __illegally_sized_syscall_arg5(void); +extern void __illegally_sized_syscall_arg6(void); + +# define LOAD_ARGS_0(name, dummy) \ + r0 = name +# define LOAD_ARGS_1(name, __arg1) \ + long int arg1 = (long int) (__arg1); \ + LOAD_ARGS_0(name, 0); \ + if (__builtin_classify_type (__arg1) != 5 && sizeof (__arg1) > 4) \ + __illegally_sized_syscall_arg1 (); \ + r3 = arg1 +# define LOAD_ARGS_2(name, __arg1, __arg2) \ + long int arg2 = (long int) (__arg2); \ + LOAD_ARGS_1(name, __arg1); \ + if (__builtin_classify_type (__arg2) != 5 && sizeof (__arg2) > 4) \ + __illegally_sized_syscall_arg2 (); \ + r4 = arg2 +# define LOAD_ARGS_3(name, __arg1, __arg2, __arg3) \ + long int arg3 = (long int) (__arg3); \ + LOAD_ARGS_2(name, __arg1, __arg2); \ + if (__builtin_classify_type (__arg3) != 5 && sizeof (__arg3) > 4) \ + __illegally_sized_syscall_arg3 (); \ + r5 = arg3 +# define LOAD_ARGS_4(name, __arg1, __arg2, __arg3, __arg4) \ + long int arg4 = (long int) (__arg4); \ + LOAD_ARGS_3(name, __arg1, __arg2, __arg3); \ + if (__builtin_classify_type (__arg4) != 5 && sizeof (__arg4) > 4) \ + __illegally_sized_syscall_arg4 (); \ + r6 = arg4 +# define LOAD_ARGS_5(name, __arg1, __arg2, __arg3, __arg4, __arg5) \ + long int arg5 = (long int) (__arg5); \ + LOAD_ARGS_4(name, __arg1, __arg2, __arg3, __arg4); \ + if (__builtin_classify_type (__arg5) != 5 && sizeof (__arg5) > 4) \ + __illegally_sized_syscall_arg5 (); \ + r7 = arg5 +# define LOAD_ARGS_6(name, __arg1, __arg2, __arg3, __arg4, __arg5, __arg6) \ + long int arg6 = (long int) (__arg6); \ + LOAD_ARGS_5(name, __arg1, __arg2, __arg3, __arg4, __arg5); \ + if (__builtin_classify_type (__arg6) != 5 && sizeof (__arg6) > 4) \ + __illegally_sized_syscall_arg6 (); \ + r8 = arg6 + +# define ASM_INPUT_0 "0" (r0) +# define ASM_INPUT_1 ASM_INPUT_0, "1" (r3) +# define ASM_INPUT_2 ASM_INPUT_1, "2" (r4) +# define ASM_INPUT_3 ASM_INPUT_2, "3" (r5) +# define ASM_INPUT_4 ASM_INPUT_3, "4" (r6) +# define ASM_INPUT_5 ASM_INPUT_4, "5" (r7) +# define ASM_INPUT_6 ASM_INPUT_5, "6" (r8) + +#endif /* __ASSEMBLER__ */ + + +/* Pointer mangling support. */ +#if defined NOT_IN_libc && defined IS_IN_rtld +/* We cannot use the thread descriptor because in ld.so we use setjmp + earlier than the descriptor is initialized. */ +#else +# ifdef __ASSEMBLER__ +# define PTR_MANGLE(reg, tmpreg) \ + lwz tmpreg,POINTER_GUARD(r2); \ + xor reg,tmpreg,reg +# define PTR_MANGLE2(reg, tmpreg) \ + xor reg,tmpreg,reg +# define PTR_MANGLE3(destreg, reg, tmpreg) \ + lwz tmpreg,POINTER_GUARD(r2); \ + xor destreg,tmpreg,reg +# define PTR_DEMANGLE(reg, tmpreg) PTR_MANGLE (reg, tmpreg) +# define PTR_DEMANGLE2(reg, tmpreg) PTR_MANGLE2 (reg, tmpreg) +# define PTR_DEMANGLE3(destreg, reg, tmpreg) PTR_MANGLE3 (destreg, reg, tmpreg) +# else +# define PTR_MANGLE(var) \ + (var) = (__typeof (var)) ((uintptr_t) (var) ^ THREAD_GET_POINTER_GUARD ()) +# define PTR_DEMANGLE(var) PTR_MANGLE (var) +# endif +#endif + +#endif /* _BITS_SYSCALLS_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/termios.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/termios.h new file mode 100644 index 00000000..7aac02dc --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/termios.h @@ -0,0 +1,319 @@ +/* Copyright (C) 1997,1999,2001,2003,2004,2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _TERMIOS_H +# error "Never include directly; use instead." +#endif + +typedef unsigned char cc_t; +typedef unsigned int speed_t; +typedef unsigned int tcflag_t; + +/* + * termios type and macro definitions. Be careful about adding stuff + * to this file since it's used in GNU libc and there are strict rules + * concerning namespace pollution. + */ + +#define NCCS 32 +struct termios { + tcflag_t c_iflag; /* input mode flags */ + tcflag_t c_oflag; /* output mode flags */ + tcflag_t c_cflag; /* control mode flags */ + tcflag_t c_lflag; /* local mode flags */ + cc_t c_line; /* line discipline (== c_cc[19]) */ + cc_t c_cc[NCCS]; /* control characters */ + speed_t c_ispeed; /* input speed */ + speed_t c_ospeed; /* output speed */ +#define _HAVE_STRUCT_TERMIOS_C_ISPEED 1 +#define _HAVE_STRUCT_TERMIOS_C_OSPEED 1 +}; + +/* c_cc characters */ +#define VINTR 0 +#define VQUIT 1 +#define VERASE 2 +#define VKILL 3 +#define VEOF 4 +#define VMIN 5 +#define VEOL 6 +#define VTIME 7 +#define VEOL2 8 +#define VSWTC 9 + +#define VWERASE 10 +#define VREPRINT 11 +#define VSUSP 12 +#define VSTART 13 +#define VSTOP 14 +#define VLNEXT 15 +#define VDISCARD 16 + +/* c_iflag bits */ +#define IGNBRK 0000001 +#define BRKINT 0000002 +#define IGNPAR 0000004 +#define PARMRK 0000010 +#define INPCK 0000020 +#define ISTRIP 0000040 +#define INLCR 0000100 +#define IGNCR 0000200 +#define ICRNL 0000400 +#define IXON 0001000 +#define IXOFF 0002000 +#define IXANY 0004000 +#define IUCLC 0010000 +#define IMAXBEL 0020000 +#define IUTF8 0040000 + +/* c_oflag bits */ +#define OPOST 0000001 +#define ONLCR 0000002 +#define OLCUC 0000004 + +#define OCRNL 0000010 +#define ONOCR 0000020 +#define ONLRET 0000040 + +#define OFILL 00000100 +#define OFDEL 00000200 +#if defined __USE_MISC || defined __USE_XOPEN +# define NLDLY 00001400 +# define NL0 00000000 +# define NL1 00000400 +# define NL2 00001000 +# define NL3 00001400 +# define TABDLY 00006000 +# define TAB0 00000000 +# define TAB1 00002000 +# define TAB2 00004000 +# define TAB3 00006000 +# define CRDLY 00030000 +# define CR0 00000000 +# define CR1 00010000 +# define CR2 00020000 +# define CR3 00030000 +# define FFDLY 00040000 +# define FF0 00000000 +# define FF1 00040000 +# define BSDLY 00100000 +# define BS0 00000000 +# define BS1 00100000 +#endif +#define VTDLY 00200000 +#define VT0 00000000 +#define VT1 00200000 + +#ifdef __USE_MISC +# define XTABS 00006000 +#endif + +/* c_cflag bit meaning */ +#ifdef __USE_MISC +# define CBAUD 0000377 +#endif +#define B0 0000000 /* hang up */ +#define B50 0000001 +#define B75 0000002 +#define B110 0000003 +#define B134 0000004 +#define B150 0000005 +#define B200 0000006 +#define B300 0000007 +#define B600 0000010 +#define B1200 0000011 +#define B1800 0000012 +#define B2400 0000013 +#define B4800 0000014 +#define B9600 0000015 +#define B19200 0000016 +#define B38400 0000017 +#ifdef __USE_MISC +# define EXTA B19200 +# define EXTB B38400 +# define CBAUDEX 0000020 +#endif +#define B57600 00020 +#define B115200 00021 +#define B230400 00022 +#define B460800 00023 +#define B500000 00024 +#define B576000 00025 +#define B921600 00026 +#define B1000000 00027 +#define B1152000 00030 +#define B1500000 00031 +#define B2000000 00032 +#define B2500000 00033 +#define B3000000 00034 +#define B3500000 00035 +#define B4000000 00036 +#define __MAX_BAUD B4000000 + +#define CSIZE 00001400 +#define CS5 00000000 +#define CS6 00000400 +#define CS7 00001000 +#define CS8 00001400 + +#define CSTOPB 00002000 +#define CREAD 00004000 +#define PARENB 00010000 +#define PARODD 00020000 +#define HUPCL 00040000 + +#define CLOCAL 00100000 +#ifdef __USE_MISC +# define CMSPAR 010000000000 /* mark or space (stick) parity */ +# define CRTSCTS 020000000000 /* flow control */ +#endif + +/* c_lflag bits */ +#define ISIG 0x00000080 +#define ICANON 0x00000100 +#if defined __USE_MISC || defined __USE_XOPEN +# define XCASE 0x00004000 +#endif +#define ECHO 0x00000008 +#define ECHOE 0x00000002 +#define ECHOK 0x00000004 +#define ECHONL 0x00000010 +#define NOFLSH 0x80000000 +#define TOSTOP 0x00400000 +#ifdef __USE_MISC +# define ECHOCTL 0x00000040 +# define ECHOPRT 0x00000020 +# define ECHOKE 0x00000001 +# define FLUSHO 0x00800000 +# define PENDIN 0x20000000 +#endif +#define IEXTEN 0x00000400 + +/* Values for the ACTION argument to `tcflow'. */ +#define TCOOFF 0 +#define TCOON 1 +#define TCIOFF 2 +#define TCION 3 + +/* Values for the QUEUE_SELECTOR argument to `tcflush'. */ +#define TCIFLUSH 0 +#define TCOFLUSH 1 +#define TCIOFLUSH 2 + +/* Values for the OPTIONAL_ACTIONS argument to `tcsetattr'. */ +#define TCSANOW 0 +#define TCSADRAIN 1 +#define TCSAFLUSH 2 + +struct sgttyb { + char sg_ispeed; + char sg_ospeed; + char sg_erase; + char sg_kill; + short sg_flags; +}; + +struct tchars { + char t_intrc; + char t_quitc; + char t_startc; + char t_stopc; + char t_eofc; + char t_brkc; +}; + +struct ltchars { + char t_suspc; + char t_dsuspc; + char t_rprntc; + char t_flushc; + char t_werasc; + char t_lnextc; +}; + +/* Used for packet mode */ +#define TIOCPKT_DATA 0 +#define TIOCPKT_FLUSHREAD 1 +#define TIOCPKT_FLUSHWRITE 2 +#define TIOCPKT_STOP 4 +#define TIOCPKT_START 8 +#define TIOCPKT_NOSTOP 16 +#define TIOCPKT_DOSTOP 32 + +struct winsize { + unsigned short ws_row; + unsigned short ws_col; + unsigned short ws_xpixel; + unsigned short ws_ypixel; +}; + +#define NCC 10 +struct termio { + unsigned short c_iflag; /* input mode flags */ + unsigned short c_oflag; /* output mode flags */ + unsigned short c_cflag; /* control mode flags */ + unsigned short c_lflag; /* local mode flags */ + unsigned char c_line; /* line discipline */ + unsigned char c_cc[NCC]; /* control characters */ +}; + +/* c_cc characters */ +#define _VINTR 0 +#define _VQUIT 1 +#define _VERASE 2 +#define _VKILL 3 +#define _VEOF 4 +#define _VMIN 5 +#define _VEOL 6 +#define _VTIME 7 +#define _VEOL2 8 +#define _VSWTC 9 + +/* modem lines */ +#define TIOCM_LE 0x001 +#define TIOCM_DTR 0x002 +#define TIOCM_RTS 0x004 +#define TIOCM_ST 0x008 +#define TIOCM_SR 0x010 +#define TIOCM_CTS 0x020 +#define TIOCM_CAR 0x040 +#define TIOCM_RNG 0x080 +#define TIOCM_DSR 0x100 +#define TIOCM_CD TIOCM_CAR +#define TIOCM_RI TIOCM_RNG + +/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */ +#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */ + +/* line disciplines */ +#define N_TTY 0 +#define N_SLIP 1 +#define N_MOUSE 2 +#define N_PPP 3 +#define N_STRIP 4 +#define N_AX25 5 +#define N_X25 6 /* X.25 async */ +#define N_6PACK 7 +#define N_MASC 8 /* Mobitex module */ +#define N_R3964 9 /* Simatic R3964 module */ +#define N_PROFIBUS_FDL 10 /* Profibus */ +#define N_IRDA 11 /* Linux IR */ +#define N_SMSBLOCK 12 /* SMS block mode */ +#define N_HDLC 13 /* synchronous HDLC */ +#define N_SYNC_PPP 14 /* synchronous PPP */ +#define N_HCI 15 /* Bluetooth HCI UART */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/uClibc_arch_features.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/uClibc_arch_features.h new file mode 100644 index 00000000..6f1f396f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/uClibc_arch_features.h @@ -0,0 +1,47 @@ +/* + * Track misc arch-specific features that aren't config options + */ + +#ifndef _BITS_UCLIBC_ARCH_FEATURES_H +#define _BITS_UCLIBC_ARCH_FEATURES_H + +/* instruction used when calling abort() to kill yourself */ +#define __UCLIBC_ABORT_INSTRUCTION__ ".long 0" + +/* can your target use syscall6() for mmap ? */ +#define __UCLIBC_MMAP_HAS_6_ARGS__ + +/* does your target use syscall4() for truncate64 ? (32bit arches only) */ +#define __UCLIBC_TRUNCATE64_HAS_4_ARGS__ + +/* does your target have a broken create_module() ? */ +#undef __UCLIBC_BROKEN_CREATE_MODULE__ + +/* does your target have to worry about older [gs]etrlimit() ? */ +#undef __UCLIBC_HANDLE_OLDER_RLIMIT__ + +/* does your target have an asm .set ? */ +#define __UCLIBC_HAVE_ASM_SET_DIRECTIVE__ + +/* define if target doesn't like .global */ +#undef __UCLIBC_ASM_GLOBAL_DIRECTIVE__ + +/* define if target supports .weak */ +#define __UCLIBC_HAVE_ASM_WEAK_DIRECTIVE__ + +/* define if target supports .weakext */ +#undef __UCLIBC_HAVE_ASM_WEAKEXT_DIRECTIVE__ + +/* needed probably only for ppc64 */ +#undef __UCLIBC_HAVE_ASM_GLOBAL_DOT_NAME__ + +/* define if target supports CFI pseudo ops */ +#undef __UCLIBC_HAVE_ASM_CFI_DIRECTIVES__ + +/* define if target supports IEEE signed zero floats */ +#define __UCLIBC_HAVE_SIGNED_ZERO__ + +/* only weird assemblers generally need this */ +#undef __UCLIBC_ASM_LINE_SEP__ + +#endif /* _BITS_UCLIBC_ARCH_FEATURES_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/wordsize.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/wordsize.h new file mode 100644 index 00000000..cf934234 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bits/wordsize.h @@ -0,0 +1,19 @@ +/* Determine the wordsize from the preprocessor defines. */ + +#if defined __powerpc64__ +# define __WORDSIZE 64 +# define __WORDSIZE_COMPAT32 1 +#else +# define __WORDSIZE 32 +#endif + +#if !defined __NO_LONG_DOUBLE_MATH && !defined __LONG_DOUBLE_MATH_OPTIONAL + +/* Signal the glibc ABI didn't used to have a `long double'. + The changes all the `long double' function variants to be redirects + to the double functions. */ +# define __LONG_DOUBLE_MATH_OPTIONAL 1 +# ifndef __LONG_DOUBLE_128__ +# define __NO_LONG_DOUBLE_MATH 1 +# endif +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/brk.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/brk.S new file mode 100644 index 00000000..5fe8d408 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/brk.S @@ -0,0 +1,80 @@ +/* brk system call for Linux/ppc. + Copyright (C) 1995, 1996, 1997, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include "ppc_asm.h" +#define _ERRNO_H 1 +#include +#include + +#ifdef __NR_brk + +#ifdef __PIC__ +.section .bss + .align 4 + .globl __curbrk + .hidden __curbrk +__curbrk: .skip 4 + .type __curbrk,@object + .size __curbrk,4 +#else +.comm __curbrk, 4,4 +#endif + + .text + .globl brk + .type brk,@function + .align 2 + +brk: + stwu r1,-16(r1) + stw r3,8(r1) + li 0, __NR_brk; + sc + lwz r6,8(r1) +#ifdef __PIC__ + mflr r4 +# ifdef HAVE_ASM_PPC_REL16 + bcl 20,31,1f +1: mflr r5 + addis r5,r5,_GLOBAL_OFFSET_TABLE_-1b@ha + addi r5,r5,_GLOBAL_OFFSET_TABLE_-1b@l +# else + bl _GLOBAL_OFFSET_TABLE_@local-4 + mflr r5 +# endif + lwz r5,__curbrk@got(r5) + mtlr r4 + stw r3,0(r5) +#else + lis r4,__curbrk@ha + stw r3,__curbrk@l(r4) +#endif + cmplw r6,r3 + addi r1,r1,16 + li r3,0 + blelr+ + li r3,ENOMEM + + b __syscall_error + + .size brk,.-brk + +libc_hidden_def(brk) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bsd-_setjmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bsd-_setjmp.S new file mode 100644 index 00000000..585878ac --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bsd-_setjmp.S @@ -0,0 +1,35 @@ +/* BSD `_setjmp' entry point to `sigsetjmp (..., 0)'. PowerPC version. + Copyright (C) 1994, 1997, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This just does a tail-call to `__sigsetjmp (ARG, 0)'. + We cannot do it in C because it must be a tail-call, so frame-unwinding + in setjmp doesn't clobber the state restored by longjmp. */ + +#include "ppc_asm.h" + +.globl _setjmp; +.type _setjmp, @function; +.align 2; + +_setjmp: + li r4,0 /* Set second argument to 0. */ + + b __sigsetjmp@local + +.size _setjmp,.-_setjmp diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bsd-setjmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bsd-setjmp.S new file mode 100644 index 00000000..f95d0821 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/bsd-setjmp.S @@ -0,0 +1,38 @@ +/* BSD `setjmp' entry point to `sigsetjmp (..., 1)'. PowerPC version. + Copyright (C) 1994, 1997, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This just does a tail-call to `__sigsetjmp (ARG, 1)'. + We cannot do it in C because it must be a tail-call, so frame-unwinding + in setjmp doesn't clobber the state restored by longjmp. */ + +#include "ppc_asm.h" + +.globl __setjmp; +.type __setjmp, @function; +.align 2; + +__setjmp: + li r4,1 /* Set second argument to 1. */ + + b __sigsetjmp@local + +.size __setjmp,.-__setjmp + +.globl setjmp; +.set setjmp,__setjmp diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/clone.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/clone.S new file mode 100644 index 00000000..307053fe --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/clone.S @@ -0,0 +1,145 @@ +/* Wrapper around clone system call. + Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#define _ERRNO_H 1 +#include +#include + +#define CLONE_VM 0x00000100 +#define CLONE_THREAD 0x00010000 + +/* This is the only really unusual system call in PPC linux, but not + because of any weirdness in the system call itself; because of + all the freaky stuff we have to do to make the call useful. */ + +/* int [r3] clone(int (*fn)(void *arg) [r3], void *child_stack [r4], + int flags [r5], void *arg [r6], void *parent_tid [r7], + void *tls [r8], void *child_tid [r9]); */ + +#ifdef __NR_clone + .globl __clone + .type __clone,@function + .align 2 + +__clone: + /* Check for child_stack == NULL || fn == NULL. */ + cmpwi cr0,r4,0 + cmpwi cr1,r3,0 + cror cr0*4+eq,cr1*4+eq,cr0*4+eq + beq- cr0,.Lbadargs + + /* Set up stack frame for parent. */ + stwu r1,-32(r1) + cfi_adjust_cfa_offset (32) +#ifdef RESET_PID + stmw r28,16(r1) +#else +# ifdef __ASSUME_FIXED_CLONE_SYSCALL + stmw r29,16(r1) +# else + stmw r30,16(r1) +# endif +#endif + + /* Set up stack frame for child. */ + clrrwi r4,r4,4 + li r0,0 + stwu r0,-16(r4) + + /* Save fn, args, stack across syscall. */ + mr r30,r3 /* Function in r30. */ +#ifndef __ASSUME_FIXED_CLONE_SYSCALL + mr r29,r4 /* Stack pointer in r29. */ +#endif +#ifdef RESET_PID + mr r28,r5 +#endif + mr r31,r6 /* Argument in r31. */ + + /* 'flags' argument is first parameter to clone syscall. (The other + argument is the stack pointer, already in r4.) */ + mr r3,r5 + + /* Move the parent_tid, child_tid and tls arguments. */ + mr r5,r7 + mr r6,r8 + mr r7,r9 + + /* End FDE now, because in the child the unwind info will be wrong. */ + cfi_endproc + + /* Do the call. */ + li 0, __NR_clone + sc + + /* Check for child process. */ + cmpwi cr1,r3,0 + crandc cr1*4+eq,cr1*4+eq,cr0*4+so + bne- cr1,.Lparent /* The '-' is to minimise the race. */ + +#ifndef __ASSUME_FIXED_CLONE_SYSCALL + /* On at least mklinux DR3a5, clone() doesn't actually change + the stack pointer. I'm pretty sure this is a bug, because + it adds a race condition if a signal is sent to a thread + just after it is created (in the previous three instructions). */ + mr r1,r29 +#endif + +#ifdef RESET_PID + andis. r0,r28,CLONE_THREAD>>16 + bne+ r0,.Loldpid + andi. r0,r28,CLONE_VM + li r3,-1 + bne- r0,.Lnomoregetpid +.Lnomoregetpid: + stw r3,TID(r2) + stw r3,PID(r2) +.Loldpid: +#endif + /* Call procedure. */ + mtctr r30 + mr r3,r31 + bctrl + /* Call _exit with result from procedure. */ + b HIDDEN_JUMPTARGET(_exit) + +.Lparent: + /* Parent. Restore registers & return. */ +#ifdef RESET_PID + lmw r28,16(r1) +#else +# ifndef __ASSUME_FIXED_CLONE_SYSCALL + lmw r29,16(r1) +# else + lmw r30,16(r1) +# endif +#endif + addi r1,r1,32 + bnslr+ + b __syscall_error + +.Lbadargs: + li r3,EINVAL + b __syscall_error + + cfi_startproc + .size __clone,.-__clone +weak_alias(__clone, clone) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/crt1.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/crt1.S new file mode 100644 index 00000000..4f1494a8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/crt1.S @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2003 by Erik Andersen + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License + * for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +/* Integer registers. */ +#define r0 0 +#define r1 1 +#define r2 2 +#define r3 3 +#define r4 4 +#define r5 5 +#define r6 6 +#define r7 7 +#define r8 8 +#define r9 9 +#define r10 10 +#define r13 13 +#define r31 31 + +.text + .globl _start + .type _start,%function + .type _init,%function + .type _fini,%function +#ifndef __UCLIBC_CTOR_DTOR__ + .weak _init + .weak _fini +#endif + .type main,%function + .type __uClibc_main,%function + +_start: + mr r9,r1 /* Save the stack pointer and pass it to __uClibc_main */ + clrrwi r1,r1,4 /* Align stack ptr to 16 bytes */ +#ifdef __PIC__ +# ifdef HAVE_ASM_PPC_REL16 + bcl 20,31,1f +1: mflr r31 + addis r31,r31,_GLOBAL_OFFSET_TABLE_-1b@ha + addi r31,r31,_GLOBAL_OFFSET_TABLE_-1b@l +# else + bl _GLOBAL_OFFSET_TABLE_-4@local + mflr r31 +# endif +#endif + /* Set up the small data pointer in r13. */ +#ifdef __PIC__ + lwz r13,_SDA_BASE_@got(r31) +#else + lis r13,_SDA_BASE_@ha + addi r13,r13,_SDA_BASE_@l +#endif + /* Set up an initial stack frame, and clear the LR. */ + li r0,0 + stwu r1,-16(r1) + mtlr r0 + stw r0,0(r1) + /* find argc from the stack pointer */ + lwz r4,0(r9) + /* find argv one word offset from the stack pointer */ + addi r5,r9,4 + mr r8,r3 /* Pass _dl_fini from ldso or NULL if statically linked */ + /* Note: PPC depends on the kernel to zero r3 before */ + /* handing over to user space, otherwise static apps */ + /* will SEGV during exit() */ + + /* Ok, now run uClibc's main() -- shouldn't return */ +#ifdef __PIC__ + lwz r6,_init@got(r31) + lwz r7,_fini@got(r31) + lwz r3,main@got(r31) + b __uClibc_main@plt +#else + lis r6,_init@ha # load top 16 bits + addi r6,r6,_init@l # load bottom 16 bits + lis r7,_fini@ha # load top 16 bits + addi r7,r7,_fini@l # load bottom 16 bits + lis r3,main@ha # load top 16 bits + addi r3,r3,main@l # load bottom 16 bits + b __uClibc_main +#endif + +.size _start,.-_start + +/* Define a symbol for the first piece of initialized data. */ + .data + .globl __data_start +__data_start: + .long 0 + .weak data_start + data_start = __data_start + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/crti.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/crti.S new file mode 100644 index 00000000..09589ba8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/crti.S @@ -0,0 +1,24 @@ + .file "initfini.c" + + .section .init + .align 2 + .globl _init + .type _init, @function +_init: + stwu 1,-32(1) + mflr 0 + stw 0,36(1) + + .align 2 + + + .section .fini + .align 2 + .globl _fini + .type _fini, @function +_fini: + stwu 1,-32(1) + mflr 0 + stw 0,36(1) + + .align 2 diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/crtn.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/crtn.S new file mode 100644 index 00000000..938367ca --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/crtn.S @@ -0,0 +1,21 @@ + .file "initfini.c" + + .section .init + .align 2 + .globl _init + .type _init, @function + + lwz 0,36(1) + addi 1,1,32 + mtlr 0 + blr + + .section .fini + .align 2 + .globl _fini + .type _fini, @function + + lwz 0,36(1) + addi 1,1,32 + mtlr 0 + blr diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/fenv.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/fenv.h new file mode 100644 index 00000000..8a06f024 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/fenv.h @@ -0,0 +1,136 @@ +/* Copyright (C) 1997, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * ISO C99 7.6: Floating-point environment + */ + +#ifndef _FENV_H +#define _FENV_H 1 + +#include + +/* Get the architecture dependend definitions. The following definitions + are expected to be done: + + fenv_t type for object representing an entire floating-point + environment + + FE_DFL_ENV macro of type pointer to fenv_t to be used as the argument + to functions taking an argument of type fenv_t; in this + case the default environment will be used + + fexcept_t type for object representing the floating-point exception + flags including status associated with the flags + + The following macros are defined iff the implementation supports this + kind of exception. + FE_INEXACT inexact result + FE_DIVBYZERO division by zero + FE_UNDERFLOW result not representable due to underflow + FE_OVERFLOW result not representable due to overflow + FE_INVALID invalid operation + + FE_ALL_EXCEPT bitwise OR of all supported exceptions + + The next macros are defined iff the appropriate rounding mode is + supported by the implementation. + FE_TONEAREST round to nearest + FE_UPWARD round toward +Inf + FE_DOWNWARD round toward -Inf + FE_TOWARDZERO round toward 0 +*/ +#include + +__BEGIN_DECLS + +/* Floating-point exception handling. */ + +/* Clear the supported exceptions represented by EXCEPTS. */ +extern int feclearexcept (int __excepts) __THROW; + +/* Store implementation-defined representation of the exception flags + indicated by EXCEPTS in the object pointed to by FLAGP. */ +extern int fegetexceptflag (fexcept_t *__flagp, int __excepts) __THROW; + +/* Raise the supported exceptions represented by EXCEPTS. */ +extern int feraiseexcept (int __excepts) __THROW; + +/* Set complete status for exceptions indicated by EXCEPTS according to + the representation in the object pointed to by FLAGP. */ +extern int fesetexceptflag (__const fexcept_t *__flagp, int __excepts) __THROW; + +/* Determine which of subset of the exceptions specified by EXCEPTS are + currently set. */ +extern int fetestexcept (int __excepts) __THROW; + + +/* Rounding control. */ + +/* Get current rounding direction. */ +extern int fegetround (void) __THROW; + +/* Establish the rounding direction represented by ROUND. */ +extern int fesetround (int __rounding_direction) __THROW; + + +/* Floating-point environment. */ + +/* Store the current floating-point environment in the object pointed + to by ENVP. */ +extern int fegetenv (fenv_t *__envp) __THROW; + +/* Save the current environment in the object pointed to by ENVP, clear + exception flags and install a non-stop mode (if available) for all + exceptions. */ +extern int feholdexcept (fenv_t *__envp) __THROW; + +/* Establish the floating-point environment represented by the object + pointed to by ENVP. */ +extern int fesetenv (__const fenv_t *__envp) __THROW; + +/* Save current exceptions in temporary storage, install environment + represented by object pointed to by ENVP and raise exceptions + according to saved exceptions. */ +extern int feupdateenv (__const fenv_t *__envp) __THROW; + + +/* Include optimization. */ +#ifdef __OPTIMIZE__ +# include +#endif + +#ifdef __USE_GNU + +/* Enable individual exceptions. Will not enable more exceptions than + EXCEPTS specifies. Returns the previous enabled exceptions if all + exceptions are successfully set, otherwise returns -1. */ +extern int feenableexcept (int __excepts) __THROW; + +/* Disable individual exceptions. Will not disable more exceptions than + EXCEPTS specifies. Returns the previous enabled exceptions if all + exceptions are successfully disabled, otherwise returns -1. */ +extern int fedisableexcept (int __excepts) __THROW; + +/* Return enabled exceptions. */ +extern int fegetexcept (void) __THROW; +#endif + +__END_DECLS + +#endif /* fenv.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/fpu_control.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/fpu_control.h new file mode 100644 index 00000000..442da472 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/fpu_control.h @@ -0,0 +1,94 @@ +/* FPU control word definitions. PowerPC and PowerPC e500 versions. + Copyright (C) 1996, 1997, 1998, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + e500 parts contributed by Aldy Hernandez . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FPU_CONTROL_H +#define _FPU_CONTROL_H + +#include + +/* rounding control */ +#define _FPU_RC_NEAREST 0x00 /* RECOMMENDED */ +#define _FPU_RC_DOWN 0x03 +#define _FPU_RC_UP 0x02 +#define _FPU_RC_ZERO 0x01 + +#define _FPU_MASK_NI 0x04 /* non-ieee mode */ + +/* masking of interrupts */ +#define _FPU_MASK_ZM 0x10 /* zero divide */ +#define _FPU_MASK_OM 0x40 /* overflow */ +#define _FPU_MASK_UM 0x20 /* underflow */ +#define _FPU_MASK_XM 0x08 /* inexact */ +#define _FPU_MASK_IM 0x80 /* invalid operation */ + + +/* The fdlibm code requires no interrupts for exceptions. */ +#define _FPU_DEFAULT 0x00000000 /* Default value. */ + + +/* Type of the control word. */ +typedef unsigned int fpu_control_t __attribute__ ((__mode__ (__SI__))); + + +#ifdef __CONFIG_E500__ +#define _FPU_RESERVED 0xff3fff7f /* These bits are reserved are not changed. */ +/* IEEE: same as above, but (some) exceptions; + we leave the 'inexact' exception off. + */ +#define _FPU_IEEE 0x000003c0 + +/* Macros for accessing the hardware control word. */ +#define _FPU_GETCW(__cw) ({ \ + unsigned int env; \ + __asm__ __volatile__ ("mfspefscr %0" : "=r" (env)); \ + (__cw) = env; }) +#define _FPU_SETCW(__cw) ({ \ + unsigned int env = __cw; \ + __asm__ __volatile__ ("mtspefscr %0" : : "r" (env)); }) +#else +#define _FPU_RESERVED 0xffffff00 /* These bits are reserved are not changed. */ +/* IEEE: same as above, but (some) exceptions; + we leave the 'inexact' exception off. + */ +#define _FPU_IEEE 0x000000f0 + +/* Macros for accessing the hardware control word. */ +#define _FPU_GETCW(__cw) ( { \ + union { double d; fpu_control_t cw[2]; } \ + tmp __attribute__ ((__aligned__(8))); \ + __asm__ ("mffs 0; stfd%U0 0,%0" : "=m" (tmp.d) : : "fr0"); \ + (__cw)=tmp.cw[1]; \ + tmp.cw[1]; } ) +#define _FPU_SETCW(__cw) { \ + union { double d; fpu_control_t cw[2]; } \ + tmp __attribute__ ((__aligned__(8))); \ + tmp.cw[0] = 0xFFF80000; /* More-or-less arbitrary; this is a QNaN. */ \ + tmp.cw[1] = __cw; \ + __asm__ ("lfd%U0 0,%0; mtfsf 255,0" : : "m" (tmp.d) : "fr0"); \ +} + +#endif /* __CONFIG_E500__ */ + +#if 0 +/* Default control word set at startup. */ +extern fpu_control_t __fpu_control; +#endif + +#endif /* _FPU_CONTROL_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/ioctl.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/ioctl.c new file mode 100644 index 00000000..26bab0d0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/ioctl.c @@ -0,0 +1,71 @@ +/* Copyright (C) 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include + + + +/* The user-visible size of struct termios has changed. Catch ioctl calls + using the new-style struct termios, and translate them to old-style. */ + +#define __NR___syscall_ioctl __NR_ioctl +static __always_inline +_syscall3(int, __syscall_ioctl, int, fd, unsigned long int, request, void *, arg) + + +int ioctl (int fd, unsigned long int request, ...) +{ + void *arg; + va_list ap; + int result; + + va_start (ap, request); + arg = va_arg (ap, void *); + + switch (request) + { + case TCGETS: + result = tcgetattr (fd, (struct termios *) arg); + break; + + case TCSETS: + result = tcsetattr (fd, TCSANOW, (struct termios *) arg); + break; + + case TCSETSW: + result = tcsetattr (fd, TCSADRAIN, (struct termios *) arg); + break; + + case TCSETSF: + result = tcsetattr (fd, TCSAFLUSH, (struct termios *) arg); + break; + + default: + result = __syscall_ioctl (fd, request, arg); + break; + } + + va_end (ap); + + return result; +} +libc_hidden_def(ioctl) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/posix_fadvise.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/posix_fadvise.c new file mode 100644 index 00000000..ce3574f4 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/posix_fadvise.c @@ -0,0 +1,36 @@ +/* vi: set sw=4 ts=4: */ +/* + * posix_fadvise() for uClibc + * http://www.opengroup.org/onlinepubs/009695399/functions/posix_fadvise.html + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +#ifdef __NR_fadvise64 +#define __NR_posix_fadvise __NR_fadvise64 +int posix_fadvise(int fd, off_t offset, off_t len, int advice) +{ + INTERNAL_SYSCALL_DECL(err); + int ret = (int) (INTERNAL_SYSCALL(posix_fadvise, err, 6, fd, 0, + __LONG_LONG_PAIR (offset >> 31, offset), len, advice)); + if (INTERNAL_SYSCALL_ERROR_P (ret, err)) + return INTERNAL_SYSCALL_ERRNO (ret, err); + return 0; +} + +#if defined __UCLIBC_HAS_LFS__ && (!defined __NR_fadvise64_64 || !defined _syscall6) +strong_alias(posix_fadvise,posix_fadvise64) +#endif + +#else +int posix_fadvise(int fd attribute_unused, off_t offset attribute_unused, off_t len attribute_unused, int advice attribute_unused) +{ +#warning This is not correct as far as SUSv3 is concerned. + return ENOSYS; +} +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/posix_fadvise64.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/posix_fadvise64.c new file mode 100644 index 00000000..2c7d207c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/posix_fadvise64.c @@ -0,0 +1,69 @@ +/* vi: set sw=4 ts=4: */ +/* + * posix_fadvise64() for uClibc + * http://www.opengroup.org/onlinepubs/009695399/functions/posix_fadvise.html + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __UCLIBC_HAS_LFS__ +#ifdef __NR_fadvise64_64 + +/* 64 bit implementation is cake ... or more like pie ... */ +#if __WORDSIZE == 64 + +#define __NR_posix_fadvise64 __NR_fadvise64_64 + +int posix_fadvise64(int fd, __off64_t offset, __off64_t len, int advise) +{ + if (len != (off_t) len) + return EOVERFLOW; + INTERNAL_SYSCALL_DECL (err); + int ret = INTERNAL_SYSCALL (posix_fadvise64, err, 6, fd, 0, + __LONG_LONG_PAIR ((long) (offset >> 32), (long) offset), + (off_t) len, advise); + if (!INTERNAL_SYSCALL_ERROR_P (ret, err)) + return 0; + return INTERNAL_SYSCALL_ERRNO (ret, err); +} + +/* 32 bit implementation is kind of a pita */ +#elif __WORDSIZE == 32 + +int posix_fadvise64(int fd, __off64_t offset, __off64_t len, int advise) +{ + INTERNAL_SYSCALL_DECL (err); + int ret = INTERNAL_SYSCALL (fadvise64_64, err, 6, fd, advise, + __LONG_LONG_PAIR((long) (offset >> 32), (long) offset ), + __LONG_LONG_PAIR((long) (len >> 32), (long) len)); + if (!INTERNAL_SYSCALL_ERROR_P (ret, err)) + return 0; + return INTERNAL_SYSCALL_ERRNO (ret, err); +} + +#else +#error your machine is neither 32 bit or 64 bit ... it must be magical +#endif + +#elif !defined __NR_fadvise64 +/* This is declared as a strong alias in posix_fadvise.c if __NR_fadvise64 + * is defined. + */ +int posix_fadvise64(int fd, __off64_t offset, __off64_t len, int advise) +{ +#warning This is not correct as far as SUSv3 is concerned. + return ENOSYS; +} +#endif /* __NR_fadvise64_64 */ +#endif /* __UCLIBC_HAS_LFS__ */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/powerpc32/sysdep.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/powerpc32/sysdep.h new file mode 100644 index 00000000..3f6fefdc --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/powerpc32/sysdep.h @@ -0,0 +1,151 @@ +/* Assembly macros for 32-bit PowerPC. + Copyright (C) 1999, 2001, 2002, 2003, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA + 02110-1301 USA. */ + +#ifdef __ASSEMBLER__ + +#ifdef __ELF__ + +/* If compiled for profiling, call `_mcount' at the start of each + function. */ +#ifdef PROF +/* The mcount code relies on a the return address being on the stack + to locate our caller and so it can restore it; so store one just + for its benefit. */ +# define CALL_MCOUNT \ + mflr r0; \ + stw r0,4(r1); \ + cfi_offset (lr, 4); \ + bl JUMPTARGET(_mcount); +#else /* PROF */ +# define CALL_MCOUNT /* Do nothing. */ +#endif /* PROF */ + +#define ENTRY(name) \ + ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(name); \ + ASM_TYPE_DIRECTIVE (C_SYMBOL_NAME(name),@function) \ + .align ALIGNARG(2); \ + C_LABEL(name) \ + cfi_startproc; \ + CALL_MCOUNT + +#define EALIGN_W_0 /* No words to insert. */ +#define EALIGN_W_1 nop +#define EALIGN_W_2 nop;nop +#define EALIGN_W_3 nop;nop;nop +#define EALIGN_W_4 EALIGN_W_3;nop +#define EALIGN_W_5 EALIGN_W_4;nop +#define EALIGN_W_6 EALIGN_W_5;nop +#define EALIGN_W_7 EALIGN_W_6;nop + +/* EALIGN is like ENTRY, but does alignment to 'words'*4 bytes + past a 2^align boundary. */ +#ifdef PROF +# define EALIGN(name, alignt, words) \ + ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(name); \ + ASM_TYPE_DIRECTIVE (C_SYMBOL_NAME(name),@function) \ + .align ALIGNARG(2); \ + C_LABEL(name) \ + cfi_startproc; \ + CALL_MCOUNT \ + b 0f; \ + .align ALIGNARG(alignt); \ + EALIGN_W_##words; \ + 0: +#else /* PROF */ +# define EALIGN(name, alignt, words) \ + ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(name); \ + ASM_TYPE_DIRECTIVE (C_SYMBOL_NAME(name),@function) \ + .align ALIGNARG(alignt); \ + EALIGN_W_##words; \ + C_LABEL(name) \ + cfi_startproc; +#endif + +#undef END +#define END(name) \ + cfi_endproc; \ + ASM_SIZE_DIRECTIVE(name) + +#define DO_CALL(syscall) \ + li 0,syscall; \ + sc + +#undef JUMPTARGET +#ifdef PIC +# define JUMPTARGET(name) name##@plt +#else +# define JUMPTARGET(name) name +#endif + +#if defined SHARED && defined DO_VERSIONING && defined PIC \ + && !defined NO_HIDDEN +# undef HIDDEN_JUMPTARGET +# define HIDDEN_JUMPTARGET(name) __GI_##name##@local +#endif + +#define PSEUDO(name, syscall_name, args) \ + .section ".text"; \ + ENTRY (name) \ + DO_CALL (SYS_ify (syscall_name)); + +#define PSEUDO_RET \ + bnslr+; \ + b __syscall_error@local +#define ret PSEUDO_RET + +#undef PSEUDO_END +#define PSEUDO_END(name) \ + END (name) + +#define PSEUDO_NOERRNO(name, syscall_name, args) \ + .section ".text"; \ + ENTRY (name) \ + DO_CALL (SYS_ify (syscall_name)); + +#define PSEUDO_RET_NOERRNO \ + blr +#define ret_NOERRNO PSEUDO_RET_NOERRNO + +#undef PSEUDO_END_NOERRNO +#define PSEUDO_END_NOERRNO(name) \ + END (name) + +#define PSEUDO_ERRVAL(name, syscall_name, args) \ + .section ".text"; \ + ENTRY (name) \ + DO_CALL (SYS_ify (syscall_name)); + +#define PSEUDO_RET_ERRVAL \ + blr +#define ret_ERRVAL PSEUDO_RET_ERRVAL + +#undef PSEUDO_END_ERRVAL +#define PSEUDO_END_ERRVAL(name) \ + END (name) + +/* Local labels stripped out by the linker. */ +#undef L +#define L(x) .L##x + +/* Label in text section. */ +#define C_TEXT(name) name + +#endif /* __ELF__ */ + +#endif /* __ASSEMBLER__ */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/powerpc64/sysdep.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/powerpc64/sysdep.h new file mode 100644 index 00000000..46728857 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/powerpc64/sysdep.h @@ -0,0 +1,264 @@ +/* Assembly macros for 64-bit PowerPC. + Copyright (C) 2002, 2003, 2004, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA + 02110-1301 USA. */ + +#ifdef __ELF__ + +#ifdef __ASSEMBLER__ + +/* Support macros for CALL_MCOUNT. */ + .macro SAVE_ARG NARG + .if \NARG + SAVE_ARG \NARG-1 + std 2+\NARG,-72+8*(\NARG)(1) + .endif + .endm + + .macro REST_ARG NARG + .if \NARG + REST_ARG \NARG-1 + ld 2+\NARG,40+8*(\NARG)(1) + .endif + .endm + +/* If compiled for profiling, call `_mcount' at the start of each function. + see ppc-mcount.S for more details. */ + .macro CALL_MCOUNT NARG +#ifdef PROF + mflr r0 + SAVE_ARG \NARG + std r0,16(r1) + stdu r1,-112(r1) + bl JUMPTARGET (_mcount) + ld r0,128(r1) + REST_ARG \NARG + addi r1,r1,112 + mtlr r0 +#endif + .endm + +#ifdef USE_PPC64_OVERLAPPING_OPD +# define OPD_ENT(name) .quad BODY_LABEL (name), .TOC.@tocbase +#else +# define OPD_ENT(name) .quad BODY_LABEL (name), .TOC.@tocbase, 0 +#endif + +#define ENTRY_1(name) \ + .section ".text"; \ + .type BODY_LABEL(name),@function; \ + .globl name; \ + .section ".opd","aw"; \ + .align 3; \ +name##: OPD_ENT (name); \ + .previous; + +#ifdef HAVE_ASM_GLOBAL_DOT_NAME +# define DOT_LABEL(X) .##X +# define BODY_LABEL(X) .##X +# define ENTRY_2(name) \ + .globl BODY_LABEL(name); \ + ENTRY_1(name) \ + .size name, 24; +# define END_2(name) \ + .size BODY_LABEL(name),.-BODY_LABEL(name); +#else +# define DOT_LABEL(X) X +# define BODY_LABEL(X) .LY##X +# define ENTRY_2(name) \ + .type name,@function; \ + ENTRY_1(name) +# define END_2(name) \ + .size name,.-BODY_LABEL(name); \ + .size BODY_LABEL(name),.-BODY_LABEL(name); +#endif + +#define ENTRY(name) \ + ENTRY_2(name) \ + .align ALIGNARG(2); \ +BODY_LABEL(name): \ + cfi_startproc; + +#define EALIGN_W_0 /* No words to insert. */ +#define EALIGN_W_1 nop +#define EALIGN_W_2 nop;nop +#define EALIGN_W_3 nop;nop;nop +#define EALIGN_W_4 EALIGN_W_3;nop +#define EALIGN_W_5 EALIGN_W_4;nop +#define EALIGN_W_6 EALIGN_W_5;nop +#define EALIGN_W_7 EALIGN_W_6;nop + +/* EALIGN is like ENTRY, but does alignment to 'words'*4 bytes + past a 2^alignt boundary. */ +#define EALIGN(name, alignt, words) \ + ENTRY_2(name) \ + .align ALIGNARG(alignt); \ + EALIGN_W_##words; \ +BODY_LABEL(name): \ + cfi_startproc; + +/* Local labels stripped out by the linker. */ +#undef L +#define L(x) .L##x + +#define tostring(s) #s +#define stringify(s) tostring(s) +#define XGLUE(a,b) a##b +#define GLUE(a,b) XGLUE(a,b) +#define LT_LABEL(name) GLUE(.LT,name) +#define LT_LABELSUFFIX(name,suffix) GLUE(GLUE(.LT,name),suffix) + +/* Support Traceback tables */ +#define TB_ASM 0x000c000000000000 +#define TB_GLOBALLINK 0x0000800000000000 +#define TB_IS_EPROL 0x0000400000000000 +#define TB_HAS_TBOFF 0x0000200000000000 +#define TB_INT_PROC 0x0000100000000000 +#define TB_HAS_CTL 0x0000080000000000 +#define TB_TOCLESS 0x0000040000000000 +#define TB_FP_PRESENT 0x0000020000000000 +#define TB_LOG_ABORT 0x0000010000000000 +#define TB_INT_HANDL 0x0000008000000000 +#define TB_NAME_PRESENT 0x0000004000000000 +#define TB_USES_ALLOCA 0x0000002000000000 +#define TB_SAVES_CR 0x0000000200000000 +#define TB_SAVES_LR 0x0000000100000000 +#define TB_STORES_BC 0x0000000080000000 +#define TB_FIXUP 0x0000000040000000 +#define TB_FP_SAVED(fprs) (((fprs) & 0x3f) << 24) +#define TB_GPR_SAVED(gprs) (((fprs) & 0x3f) << 16) +#define TB_FIXEDPARMS(parms) (((parms) & 0xff) << 8) +#define TB_FLOATPARMS(parms) (((parms) & 0x7f) << 1) +#define TB_PARMSONSTK 0x0000000000000001 + +#define PPC_HIGHER(v) (((v) >> 32) & 0xffff) +#define TB_DEFAULT TB_ASM | TB_HAS_TBOFF | TB_NAME_PRESENT + +#define TRACEBACK(name) \ +LT_LABEL(name): ; \ + .long 0 ; \ + .quad TB_DEFAULT ; \ + .long LT_LABEL(name)-BODY_LABEL(name) ; \ + .short LT_LABELSUFFIX(name,_name_end)-LT_LABELSUFFIX(name,_name_start) ; \ +LT_LABELSUFFIX(name,_name_start): ;\ + .ascii stringify(name) ; \ +LT_LABELSUFFIX(name,_name_end): ; \ + .align 2 ; + +#define TRACEBACK_MASK(name,mask) \ +LT_LABEL(name): ; \ + .long 0 ; \ + .quad TB_DEFAULT | mask ; \ + .long LT_LABEL(name)-BODY_LABEL(name) ; \ + .short LT_LABELSUFFIX(name,_name_end)-LT_LABELSUFFIX(name,_name_start) ; \ +LT_LABELSUFFIX(name,_name_start): ;\ + .ascii stringify(name) ; \ +LT_LABELSUFFIX(name,_name_end): ; \ + .align 2 ; + +/* END generates Traceback tables */ +#undef END +#define END(name) \ + cfi_endproc; \ + TRACEBACK(name) \ + END_2(name) + +/* This form supports more informative traceback tables */ +#define END_GEN_TB(name,mask) \ + cfi_endproc; \ + TRACEBACK_MASK(name,mask) \ + END_2(name) + +#define DO_CALL(syscall) \ + li 0,syscall; \ + sc + +/* ppc64 is always PIC */ +#undef JUMPTARGET +#define JUMPTARGET(name) DOT_LABEL(name) + +#define PSEUDO(name, syscall_name, args) \ + .section ".text"; \ + ENTRY (name) \ + DO_CALL (SYS_ify (syscall_name)); + +#define PSEUDO_RET \ + bnslr+; \ + b JUMPTARGET(__syscall_error) + +#define ret PSEUDO_RET + +#undef PSEUDO_END +#define PSEUDO_END(name) \ + END (name) + +#define PSEUDO_NOERRNO(name, syscall_name, args) \ + .section ".text"; \ + ENTRY (name) \ + DO_CALL (SYS_ify (syscall_name)); + +#define PSEUDO_RET_NOERRNO \ + blr + +#define ret_NOERRNO PSEUDO_RET_NOERRNO + +#undef PSEUDO_END_NOERRNO +#define PSEUDO_END_NOERRNO(name) \ + END (name) + +#define PSEUDO_ERRVAL(name, syscall_name, args) \ + .section ".text"; \ + ENTRY (name) \ + DO_CALL (SYS_ify (syscall_name)); + +#define PSEUDO_RET_ERRVAL \ + blr + +#define ret_ERRVAL PSEUDO_RET_ERRVAL + +#undef PSEUDO_END_ERRVAL +#define PSEUDO_END_ERRVAL(name) \ + END (name) + +#else /* !__ASSEMBLER__ */ + +#ifdef USE_PPC64_OVERLAPPING_OPD +# define OPD_ENT(name) ".quad " BODY_PREFIX #name ", .TOC.@tocbase;" +#else +# define OPD_ENT(name) ".quad " BODY_PREFIX #name ", .TOC.@tocbase, 0;" +#endif + +#ifdef HAVE_ASM_GLOBAL_DOT_NAME +# define DOT_PREFIX "." +# define BODY_PREFIX "." +# define ENTRY_2(name) \ + ".globl " BODY_PREFIX #name ";\n" \ + ".size " #name ", 24;" +# define END_2(name) \ + ".size " BODY_PREFIX #name ",.-" BODY_PREFIX #name ";" +#else +# define DOT_PREFIX "" +# define BODY_PREFIX ".LY" +# define ENTRY_2(name) ".type " #name ",@function;" +# define END_2(name) \ + ".size " #name ",.-" BODY_PREFIX #name ";\n" \ + ".size " BODY_PREFIX #name ",.-" BODY_PREFIX #name ";" +#endif + +#endif /* __ASSEMBLER__ */ + +#endif /* __ELF__ */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/ppc_asm.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/ppc_asm.h new file mode 100644 index 00000000..e51d88f7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/ppc_asm.h @@ -0,0 +1,137 @@ +/* Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifdef __ASSEMBLER__ + +/* Symbolic names for the registers. The only portable way to write asm + code is to use number but this produces really unreadable code. + Therefore these symbolic names. */ + +/* Integer registers. */ +#define r0 0 +#define r1 1 +#define r2 2 +#define r3 3 +#define r4 4 +#define r5 5 +#define r6 6 +#define r7 7 +#define r8 8 +#define r9 9 +#define r10 10 +#define r11 11 +#define r12 12 +#define r13 13 +#define r14 14 +#define r15 15 +#define r16 16 +#define r17 17 +#define r18 18 +#define r19 19 +#define r20 20 +#define r21 21 +#define r22 22 +#define r23 23 +#define r24 24 +#define r25 25 +#define r26 26 +#define r27 27 +#define r28 28 +#define r29 29 +#define r30 30 +#define r31 31 + +/* Floating-point registers. */ +#define fp0 0 +#define fp1 1 +#define fp2 2 +#define fp3 3 +#define fp4 4 +#define fp5 5 +#define fp6 6 +#define fp7 7 +#define fp8 8 +#define fp9 9 +#define fp10 10 +#define fp11 11 +#define fp12 12 +#define fp13 13 +#define fp14 14 +#define fp15 15 +#define fp16 16 +#define fp17 17 +#define fp18 18 +#define fp19 19 +#define fp20 20 +#define fp21 21 +#define fp22 22 +#define fp23 23 +#define fp24 24 +#define fp25 25 +#define fp26 26 +#define fp27 27 +#define fp28 28 +#define fp29 29 +#define fp30 30 +#define fp31 31 + +/* Condition code registers. */ +#define cr0 0 +#define cr1 1 +#define cr2 2 +#define cr3 3 +#define cr4 4 +#define cr5 5 +#define cr6 6 +#define cr7 7 + +/* Vector registers. */ +#define v0 0 +#define v1 1 +#define v2 2 +#define v3 3 +#define v4 4 +#define v5 5 +#define v6 6 +#define v7 7 +#define v8 8 +#define v9 9 +#define v10 10 +#define v11 11 +#define v12 12 +#define v13 13 +#define v14 14 +#define v15 15 +#define v16 16 +#define v17 17 +#define v18 18 +#define v19 19 +#define v20 20 +#define v21 21 +#define v22 22 +#define v23 23 +#define v24 24 +#define v25 25 +#define v26 26 +#define v27 27 +#define v28 28 +#define v29 29 +#define v30 30 +#define v31 31 + +#endif /* __ASSEMBLER__ */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/pread_write.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/pread_write.c new file mode 100644 index 00000000..7f988d30 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/pread_write.c @@ -0,0 +1,183 @@ +/* vi: set sw=4 ts=4: + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ +/* Based in part on the files + * ./sysdeps/unix/sysv/linux/pwrite.c, + * ./sysdeps/unix/sysv/linux/pread.c, + * sysdeps/posix/pread.c + * sysdeps/posix/pwrite.c + * from GNU libc 2.2.5, but reworked considerably... + */ + +#include +#include +#include + +#ifndef __UCLIBC_HAS_LFS__ +# define off64_t off_t +#endif + +#ifdef __NR_pread +extern __typeof(pread) __libc_pread; +# define __NR___syscall_pread __NR_pread +static __inline__ _syscall6(ssize_t, __syscall_pread, int, fd, + void *, buf, size_t, count, int, dummy, off_t, offset_hi, off_t, offset_lo) + +ssize_t __libc_pread(int fd, void *buf, size_t count, off_t offset) +{ + return(__syscall_pread(fd, buf, count, 0, __LONG_LONG_PAIR(offset >> 31, offset))); +} +weak_alias(__libc_pread,pread) + +# ifdef __UCLIBC_HAS_LFS__ +extern __typeof(pread64) __libc_pread64; +ssize_t __libc_pread64(int fd, void *buf, size_t count, off64_t offset) +{ + return(__syscall_pread(fd, buf, count, 0, __LONG_LONG_PAIR(offset >> 32, offset))); +} +weak_alias(__libc_pread64,pread64) +# endif /* __UCLIBC_HAS_LFS__ */ +#endif /* __NR_pread */ + + +#ifdef __NR_pwrite +extern __typeof(pwrite) __libc_pwrite; +# define __NR___syscall_pwrite __NR_pwrite +static __inline__ _syscall6(ssize_t, __syscall_pwrite, int, fd, + const void *, buf, size_t, count, int, dummy, off_t, offset_hi, off_t, offset_lo) + +ssize_t __libc_pwrite(int fd, const void *buf, size_t count, off_t offset) +{ + return(__syscall_pwrite(fd, buf, count, 0, __LONG_LONG_PAIR(offset >> 31, offset))); +} +weak_alias(__libc_pwrite,pwrite) + +# ifdef __UCLIBC_HAS_LFS__ +extern __typeof(pwrite64) __libc_pwrite64; +ssize_t __libc_pwrite64(int fd, const void *buf, size_t count, off64_t offset) +{ + return(__syscall_pwrite(fd, buf, count, 0, __LONG_LONG_PAIR(offset >> 32, offset))); +} +weak_alias(__libc_pwrite64,pwrite64) +# endif /* __UCLIBC_HAS_LFS__ */ +#endif /* __NR_pwrite */ + + + +#if ! defined __NR_pread || ! defined __NR_pwrite + +static ssize_t __fake_pread_write(int fd, void *buf, + size_t count, off_t offset, int do_pwrite) +{ + int save_errno; + ssize_t result; + off_t old_offset; + + /* Since we must not change the file pointer preserve the + * value so that we can restore it later. */ + if ((old_offset=lseek(fd, 0, SEEK_CUR)) == (off_t) -1) + return -1; + + /* Set to wanted position. */ + if (lseek (fd, offset, SEEK_SET) == (off_t) -1) + return -1; + + if (do_pwrite == 1) { + /* Write the data. */ + result = write(fd, buf, count); + } else { + /* Read the data. */ + result = read(fd, buf, count); + } + + /* Now we have to restore the position. If this fails we + * have to return this as an error. */ + save_errno = errno; + if (lseek(fd, old_offset, SEEK_SET) == (off_t) -1) + { + if (result == -1) + __set_errno(save_errno); + return -1; + } + __set_errno(save_errno); + return(result); +} + +# ifdef __UCLIBC_HAS_LFS__ + +static ssize_t __fake_pread_write64(int fd, void *buf, + size_t count, off64_t offset, int do_pwrite) +{ + int save_errno; + ssize_t result; + off64_t old_offset; + + /* Since we must not change the file pointer preserve the + * value so that we can restore it later. */ + if ((old_offset=lseek64(fd, 0, SEEK_CUR)) == (off64_t) -1) + return -1; + + /* Set to wanted position. */ + if (lseek64(fd, offset, SEEK_SET) == (off64_t) -1) + return -1; + + if (do_pwrite == 1) { + /* Write the data. */ + result = write(fd, buf, count); + } else { + /* Read the data. */ + result = read(fd, buf, count); + } + + /* Now we have to restore the position. */ + save_errno = errno; + if (lseek64 (fd, old_offset, SEEK_SET) == (off64_t) -1) { + if (result == -1) + __set_errno (save_errno); + return -1; + } + __set_errno (save_errno); + return result; +} +# endif /* __UCLIBC_HAS_LFS__ */ +#endif /* ! defined __NR_pread || ! defined __NR_pwrite */ + +#ifndef __NR_pread +ssize_t __libc_pread(int fd, void *buf, size_t count, off_t offset); +ssize_t __libc_pread(int fd, void *buf, size_t count, off_t offset) +{ + return(__fake_pread_write(fd, buf, count, offset, 0)); +} +weak_alias(__libc_pread,pread) + +# ifdef __UCLIBC_HAS_LFS__ +ssize_t __libc_pread64(int fd, void *buf, size_t count, off64_t offset); +ssize_t __libc_pread64(int fd, void *buf, size_t count, off64_t offset) +{ + return(__fake_pread_write64(fd, buf, count, offset, 0)); +} +weak_alias(__libc_pread64,pread64) +# endif /* __UCLIBC_HAS_LFS__ */ +#endif /* ! __NR_pread */ + + +#ifndef __NR_pwrite +ssize_t __libc_pwrite(int fd, const void *buf, size_t count, off_t offset); +ssize_t __libc_pwrite(int fd, const void *buf, size_t count, off_t offset) +{ + return(__fake_pread_write(fd, (void*)buf, count, offset, 1)); +} +weak_alias(__libc_pwrite,pwrite) + +# ifdef __UCLIBC_HAS_LFS__ +ssize_t __libc_pwrite64(int fd, const void *buf, size_t count, off64_t offset); +ssize_t __libc_pwrite64(int fd, const void *buf, size_t count, off64_t offset) +{ + return(__fake_pread_write64(fd, (void*)buf, count, offset, 1)); +} +weak_alias(__libc_pwrite64,pwrite64) +# endif /* __UCLIBC_HAS_LFS__ */ +#endif /* ! __NR_pwrite */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/setjmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/setjmp.S new file mode 100644 index 00000000..04b06d68 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/setjmp.S @@ -0,0 +1,92 @@ +/* setjmp for PowerPC and PowerPC e500. + Copyright (C) 1995, 1996, 1997, 1999, 2000, 2004 + Free Software Foundation, Inc. + e500 contributed by Aldy Hernandez . + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include "ppc_asm.h" +#define _ASM +#define _SETJMP_H +#include + +#if defined __UCLIBC_HAS_FLOATS__ && ! defined __UCLIBC_HAS_SOFT_FLOAT__ +#define FP(x...) x +#else +#define FP(x...) +#endif + +#if defined __CONFIG_E500__ +#define LFD(reg) evldd r##reg +#define STFD(reg) evstdd r##reg +#else +#define LFD(reg) lfd fp##reg +#define STFD(reg) stfd fp##reg +#endif /* __CONFIG_E500__ */ + +.globl __sigsetjmp; +.type __sigsetjmp, @function; +.align 2; + +__sigsetjmp: + stw r1,(JB_GPR1*4)(3) + mflr r0 + stw r2,(JB_GPR2*4)(3) + stw r14,((JB_GPRS+0)*4)(3) +FP( STFD (14),((JB_FPRS+0*2)*4)(3)) + stw r0,(JB_LR*4)(3) + stw r15,((JB_GPRS+1)*4)(3) +FP( STFD (15),((JB_FPRS+1*2)*4)(3)) + mfcr r0 + stw r16,((JB_GPRS+2)*4)(3) +FP( STFD (16),((JB_FPRS+2*2)*4)(3)) + stw r0,(JB_CR*4)(3) + stw r17,((JB_GPRS+3)*4)(3) +FP( STFD (17),((JB_FPRS+3*2)*4)(3)) + stw r18,((JB_GPRS+4)*4)(3) +FP( STFD (18),((JB_FPRS+4*2)*4)(3)) + stw r19,((JB_GPRS+5)*4)(3) +FP( STFD (19),((JB_FPRS+5*2)*4)(3)) + stw r20,((JB_GPRS+6)*4)(3) +FP( STFD (20),((JB_FPRS+6*2)*4)(3)) + stw r21,((JB_GPRS+7)*4)(3) +FP( STFD (21),((JB_FPRS+7*2)*4)(3)) + stw r22,((JB_GPRS+8)*4)(3) +FP( STFD (22),((JB_FPRS+8*2)*4)(3)) + stw r23,((JB_GPRS+9)*4)(3) +FP( STFD (23),((JB_FPRS+9*2)*4)(3)) + stw r24,((JB_GPRS+10)*4)(3) +FP( STFD (24),((JB_FPRS+10*2)*4)(3)) + stw r25,((JB_GPRS+11)*4)(3) +FP( STFD (25),((JB_FPRS+11*2)*4)(3)) + stw r26,((JB_GPRS+12)*4)(3) +FP( STFD (26),((JB_FPRS+12*2)*4)(3)) + stw r27,((JB_GPRS+13)*4)(3) +FP( STFD (27),((JB_FPRS+13*2)*4)(3)) + stw r28,((JB_GPRS+14)*4)(3) +FP( STFD (28),((JB_FPRS+14*2)*4)(3)) + stw r29,((JB_GPRS+15)*4)(3) +FP( STFD (29),((JB_FPRS+15*2)*4)(3)) + stw r30,((JB_GPRS+16)*4)(3) +FP( STFD (30),((JB_FPRS+16*2)*4)(3)) + stw r31,((JB_GPRS+17)*4)(3) +FP( STFD (31),((JB_FPRS+17*2)*4)(3)) + + b __sigjmp_save@local + +.size __sigsetjmp,.-__sigsetjmp diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/sys/procfs.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/sys/procfs.h new file mode 100644 index 00000000..11846364 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/sys/procfs.h @@ -0,0 +1,140 @@ +/* Copyright (C) 1996, 1997, 1999, 2002, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_PROCFS_H +#define _SYS_PROCFS_H 1 + +/* This is somehow modelled after the file of the same name on SysVr4 + systems. It provides a definition of the core file format for ELF + used on Linux. */ + +#include +#include +#include +#include +#include +#include + +__BEGIN_DECLS + +/* These definitions are normally provided by ucontext.h via + asm/sigcontext.h, asm/ptrace.h, and asm/elf.h. Otherwise we define + them here. */ +#ifndef __PPC64_ELF_H +#define ELF_NGREG 48 /* includes nip, msr, lr, etc. */ +#define ELF_NFPREG 33 /* includes fpscr */ +#if __WORDSIZE == 32 +# define ELF_NVRREG 33 /* includes vscr */ +#else +# define ELF_NVRREG 34 /* includes vscr */ +#endif + +typedef unsigned long elf_greg_t; +typedef elf_greg_t elf_gregset_t[ELF_NGREG]; + +typedef double elf_fpreg_t; +typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; + +/* Altivec registers */ +typedef struct { + unsigned int u[4]; +} __attribute__ ((aligned (16))) elf_vrreg_t; +typedef elf_vrreg_t elf_vrregset_t[ELF_NVRREG]; +#endif + +struct elf_siginfo + { + int si_signo; /* Signal number. */ + int si_code; /* Extra code. */ + int si_errno; /* Errno. */ + }; + + +/* Definitions to generate Intel SVR4-like core files. These mostly + have the same names as the SVR4 types with "elf_" tacked on the + front to prevent clashes with linux definitions, and the typedef + forms have been avoided. This is mostly like the SVR4 structure, + but more Linuxy, with things that Linux does not support and which + gdb doesn't really use excluded. Fields present but not used are + marked with "XXX". */ +struct elf_prstatus + { +#if 0 + long int pr_flags; /* XXX Process flags. */ + short int pr_why; /* XXX Reason for process halt. */ + short int pr_what; /* XXX More detailed reason. */ +#endif + struct elf_siginfo pr_info; /* Info associated with signal. */ + short int pr_cursig; /* Current signal. */ + unsigned long int pr_sigpend; /* Set of pending signals. */ + unsigned long int pr_sighold; /* Set of held signals. */ +#if 0 + struct sigaltstack pr_altstack; /* Alternate stack info. */ + struct sigaction pr_action; /* Signal action for current sig. */ +#endif + __pid_t pr_pid; + __pid_t pr_ppid; + __pid_t pr_pgrp; + __pid_t pr_sid; + struct timeval pr_utime; /* User time. */ + struct timeval pr_stime; /* System time. */ + struct timeval pr_cutime; /* Cumulative user time. */ + struct timeval pr_cstime; /* Cumulative system time. */ +#if 0 + long int pr_instr; /* Current instruction. */ +#endif + elf_gregset_t pr_reg; /* GP registers. */ + int pr_fpvalid; /* True if math copro being used. */ + }; + + +#define ELF_PRARGSZ (80) /* Number of chars for args */ + +struct elf_prpsinfo + { + char pr_state; /* Numeric process state. */ + char pr_sname; /* Char for pr_state. */ + char pr_zomb; /* Zombie. */ + char pr_nice; /* Nice val. */ + unsigned long int pr_flag; /* Flags. */ + __uid_t pr_uid; + __gid_t pr_gid; + __pid_t pr_pid, pr_ppid, pr_pgrp, pr_sid; + /* Lots missing */ + char pr_fname[16]; /* Filename of executable. */ + char pr_psargs[ELF_PRARGSZ]; /* Initial part of arg list. */ + }; + +/* Addresses. */ +typedef void *psaddr_t; + +/* Register sets. Linux has different names. */ +typedef elf_gregset_t prgregset_t; +typedef elf_fpregset_t prfpregset_t; + +/* We don't have any differences between processes and threads, + therefore habe only ine PID type. */ +typedef __pid_t lwpid_t; + + +typedef struct elf_prstatus prstatus_t; +typedef struct elf_prpsinfo prpsinfo_t; + +__END_DECLS + +#endif /* sys/procfs.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/sys/ptrace.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/sys/ptrace.h new file mode 100644 index 00000000..91a87307 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/sys/ptrace.h @@ -0,0 +1,99 @@ +/* `ptrace' debugger support interface. Linux version. + Copyright (C) 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_PTRACE_H +#define _SYS_PTRACE_H 1 + +#include + +__BEGIN_DECLS + +/* Type of the REQUEST argument to `ptrace.' */ +enum __ptrace_request +{ + /* Indicate that the process making this request should be traced. + All signals received by this process can be intercepted by its + parent, and its parent can use the other `ptrace' requests. */ + PTRACE_TRACEME = 0, +#define PT_TRACE_ME PTRACE_TRACEME + + /* Return the word in the process's text space at address ADDR. */ + PTRACE_PEEKTEXT = 1, +#define PT_READ_I PTRACE_PEEKTEXT + + /* Return the word in the process's data space at address ADDR. */ + PTRACE_PEEKDATA = 2, +#define PT_READ_D PTRACE_PEEKDATA + + /* Return the word in the process's user area at offset ADDR. */ + PTRACE_PEEKUSER = 3, +#define PT_READ_U PTRACE_PEEKUSER + + /* Write the word DATA into the process's text space at address ADDR. */ + PTRACE_POKETEXT = 4, +#define PT_WRITE_I PTRACE_POKETEXT + + /* Write the word DATA into the process's data space at address ADDR. */ + PTRACE_POKEDATA = 5, +#define PT_WRITE_D PTRACE_POKEDATA + + /* Write the word DATA into the process's user area at offset ADDR. */ + PTRACE_POKEUSER = 6, +#define PT_WRITE_U PTRACE_POKEUSER + + /* Continue the process. */ + PTRACE_CONT = 7, +#define PT_CONTINUE PTRACE_CONT + + /* Kill the process. */ + PTRACE_KILL = 8, +#define PT_KILL PTRACE_KILL + + /* Single step the process. + This is not supported on all machines. */ + PTRACE_SINGLESTEP = 9, +#define PT_STEP PTRACE_SINGLESTEP + + /* Attach to a process that is already running. */ + PTRACE_ATTACH = 16, +#define PT_ATTACH PTRACE_ATTACH + + /* Detach from a process attached to with PTRACE_ATTACH. */ + PTRACE_DETACH = 17, +#define PT_DETACH PTRACE_DETACH + + /* Continue and stop at the next (return from) syscall. */ + PTRACE_SYSCALL = 24 +#define PT_SYSCALL PTRACE_SYSCALL +}; + +/* Perform process tracing functions. REQUEST is one of the values + above, and determines the action to be taken. + For all requests except PTRACE_TRACEME, PID specifies the process to be + traced. + + PID and the other arguments described above for the various requests should + appear (those that are used for the particular request) as: + pid_t PID, void *ADDR, int DATA, void *ADDR2 + after REQUEST. */ +extern long int ptrace (enum __ptrace_request __request, ...) __THROW; + +__END_DECLS + +#endif /* _SYS_PTRACE_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/sys/ucontext.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/sys/ucontext.h new file mode 100644 index 00000000..737512af --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/sys/ucontext.h @@ -0,0 +1,177 @@ +/* Copyright (C) 1998, 1999, 2002, 2004, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_UCONTEXT_H +#define _SYS_UCONTEXT_H 1 + +#include +#include + +/* We need the signal context definitions even if they are not used + included in . */ +#include + +#if __WORDSIZE == 32 + +/* Number of general registers. */ +# define NGREG 48 + +/* Container for all general registers. */ +typedef unsigned long gregset_t[NGREG]; + +/* Container for floating-point registers and status */ +typedef struct _libc_fpstate +{ + double fpregs[32]; + double fpscr; + unsigned int _pad[2]; +} fpregset_t; + +/* Container for Altivec/VMX registers and status. + Needs to be aligned on a 16-byte boundary. */ +typedef struct _libc_vrstate +{ + unsigned int vrregs[32][4]; + unsigned int vrsave; + unsigned int _pad[2]; + unsigned int vscr; +} vrregset_t; + +/* Context to describe whole processor state. */ +typedef struct +{ + gregset_t gregs; + fpregset_t fpregs; + vrregset_t vrregs __attribute__((__aligned__(16))); +} mcontext_t; + +#else + +/* For 64-bit kernels with Altivec support, a machine context is exactly + * a sigcontext. For older kernel (without Altivec) the sigcontext matches + * the mcontext upto but not including the v_regs field. For kernels that + * don't AT_HWCAP or return AT_HWCAP without PPC_FEATURE_HAS_ALTIVEC the + * v_regs field may not exit and should not be referenced. The v_regd field + * can be refernced safely only after verifying that PPC_FEATURE_HAS_ALTIVEC + * is set in AT_HWCAP. */ + +/* Number of general registers. */ +# define NGREG 48 /* includes r0-r31, nip, msr, lr, etc. */ +# define NFPREG 33 /* includes fp0-fp31 &fpscr. */ +# define NVRREG 34 /* includes v0-v31, vscr, & vrsave in split vectors */ + +typedef unsigned long gregset_t[NGREG]; +typedef double fpregset_t[NFPREG]; + +/* Container for Altivec/VMX Vector Status and Control Register. Only 32-bits + but can only be copied to/from a 128-bit vector register. So we allocated + a whole quadword speedup save/restore. */ +typedef struct _libc_vscr +{ + unsigned int __pad[3]; + unsigned int vscr_word; +} vscr_t; + +/* Container for Altivec/VMX registers and status. + Must to be aligned on a 16-byte boundary. */ +typedef struct _libc_vrstate +{ + unsigned int vrregs[32][4]; + vscr_t vscr; + unsigned int vrsave; + unsigned int __pad[3]; +} vrregset_t __attribute__((__aligned__(16))); + +typedef struct { + unsigned long __unused[4]; + int signal; + int __pad0; + unsigned long handler; + unsigned long oldmask; + struct pt_regs *regs; + gregset_t gp_regs; + fpregset_t fp_regs; +/* + * To maintain compatibility with current implementations the sigcontext is + * extended by appending a pointer (v_regs) to a quadword type (elf_vrreg_t) + * followed by an unstructured (vmx_reserve) field of 69 doublewords. This + * allows the array of vector registers to be quadword aligned independent of + * the alignment of the containing sigcontext or ucontext. It is the + * responsibility of the code setting the sigcontext to set this pointer to + * either NULL (if this processor does not support the VMX feature) or the + * address of the first quadword within the allocated (vmx_reserve) area. + * + * The pointer (v_regs) of vector type (elf_vrreg_t) is essentually + * an array of 34 quadword entries. The entries with + * indexes 0-31 contain the corresponding vector registers. The entry with + * index 32 contains the vscr as the last word (offset 12) within the + * quadword. This allows the vscr to be stored as either a quadword (since + * it must be copied via a vector register to/from storage) or as a word. + * The entry with index 33 contains the vrsave as the first word (offset 0) + * within the quadword. + */ + vrregset_t *v_regs; + long vmx_reserve[NVRREG+NVRREG+1]; +} mcontext_t; + +#endif + +/* Userlevel context. */ +typedef struct ucontext + { + unsigned long int uc_flags; + struct ucontext *uc_link; + stack_t uc_stack; +#if __WORDSIZE == 32 + /* + * These fields are set up this way to maximize source and + * binary compatibility with code written for the old + * ucontext_t definition, which didn't include space for the + * registers. + * + * Different versions of the kernel have stored the registers on + * signal delivery at different offsets from the ucontext struct. + * Programs should thus use the uc_mcontext.uc_regs pointer to + * find where the registers are actually stored. The registers + * will be stored within the ucontext_t struct but not necessarily + * at a fixed address. As a side-effect, this lets us achieve + * 16-byte alignment for the register storage space if the + * Altivec registers are to be saved, without requiring 16-byte + * alignment on the whole ucontext_t. + * + * The uc_mcontext.regs field is included for source compatibility + * with programs written against the older ucontext_t definition, + * and its name should therefore not change. The uc_pad field + * is for binary compatibility with programs compiled against the + * old ucontext_t; it ensures that uc_mcontext.regs and uc_sigmask + * are at the same offset as previously. + */ + int uc_pad[7]; + union uc_regs_ptr { + struct pt_regs *regs; + mcontext_t *uc_regs; + } uc_mcontext; + sigset_t uc_sigmask; + char uc_reg_space[sizeof(mcontext_t) + 12]; /* last for extensibility */ +#else /* 64-bit */ + sigset_t uc_sigmask; + mcontext_t uc_mcontext; /* last for extensibility */ +#endif + } ucontext_t; + +#endif /* sys/ucontext.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/sys/user.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/sys/user.h new file mode 100644 index 00000000..e8a8aaa9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/sys/user.h @@ -0,0 +1,40 @@ +/* Copyright (C) 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_USER_H + +#define _SYS_USER_H 1 +#include + +#include + +struct user { + struct pt_regs regs; /* entire machine state */ + size_t u_tsize; /* text size (pages) */ + size_t u_dsize; /* data size (pages) */ + size_t u_ssize; /* stack size (pages) */ + unsigned long start_code; /* text starting address */ + unsigned long start_data; /* data starting address */ + unsigned long start_stack; /* stack starting address */ + long int signal; /* signal causing core dump */ + struct regs * u_ar0; /* help gdb find registers */ + unsigned long magic; /* identifies a core file */ + char u_comm[32]; /* user command name */ +}; + +#endif /* sys/user.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/syscall.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/syscall.S new file mode 100644 index 00000000..b8539841 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/syscall.S @@ -0,0 +1,38 @@ +/* Copyright (C) 1991, 1992, 1997, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + + .text + .globl syscall + .type syscall,@function + .align 2 + +syscall: + mr 0,3 + mr 3,4 + mr 4,5 + mr 5,6 + mr 6,7 + mr 7,8 + sc + bnslr; + + b __syscall_error + + .size syscall,.-syscall diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/sysdep.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/sysdep.h new file mode 100644 index 00000000..14b86ac4 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/sysdep.h @@ -0,0 +1,196 @@ +/* Copyright (C) 1999, 2001, 2002, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +/* + * Powerpc Feature masks for the Aux Vector Hardware Capabilities (AT_HWCAP). + * This entry is copied to _dl_hwcap or rtld_global._dl_hwcap during startup. + * The following must match the kernels linux/asm/cputable.h. + */ +#define PPC_FEATURE_32 0x80000000 /* 32-bit mode. */ +#define PPC_FEATURE_64 0x40000000 /* 64-bit mode. */ +#define PPC_FEATURE_601_INSTR 0x20000000 /* 601 chip, Old POWER ISA. */ +#define PPC_FEATURE_HAS_ALTIVEC 0x10000000 /* SIMD/Vector Unit. */ +#define PPC_FEATURE_HAS_FPU 0x08000000 /* Floating Point Unit. */ +#define PPC_FEATURE_HAS_MMU 0x04000000 /* Memory Management Unit. */ +#define PPC_FEATURE_HAS_4xxMAC 0x02000000 /* 4xx Multiply Accumulator. */ +#define PPC_FEATURE_UNIFIED_CACHE 0x01000000 /* Unified I/D cache. */ +#define PPC_FEATURE_HAS_SPE 0x00800000 /* Signal Processing ext. */ +#define PPC_FEATURE_HAS_EFP_SINGLE 0x00400000 /* SPE Float. */ +#define PPC_FEATURE_HAS_EFP_DOUBLE 0x00200000 /* SPE Double. */ +#define PPC_FEATURE_NO_TB 0x00100000 /* 601/403gx have no timebase */ +#define PPC_FEATURE_POWER4 0x00080000 /* POWER4 ISA 2.00 */ +#define PPC_FEATURE_POWER5 0x00040000 /* POWER5 ISA 2.02 */ +#define PPC_FEATURE_POWER5_PLUS 0x00020000 /* POWER5+ ISA 2.03 */ +#define PPC_FEATURE_CELL_BE 0x00010000 /* CELL Broadband Engine */ +#define PPC_FEATURE_BOOKE 0x00008000 +#define PPC_FEATURE_SMT 0x00004000 /* Simultaneous Multi-Threading */ +#define PPC_FEATURE_ICACHE_SNOOP 0x00002000 +#define PPC_FEATURE_ARCH_2_05 0x00001000 /* ISA 2.05 */ +#define PPC_FEATURE_PA6T 0x00000800 /* PA Semi 6T Core */ +#define PPC_FEATURE_HAS_DFP 0x00000400 /* Decimal FP Unit */ +#define PPC_FEATURE_POWER6_EXT 0x00000200 /* P6 + mffgpr/mftgpr */ +#define PPC_FEATURE_ARCH_2_06 0x00000100 /* ISA 2.06 */ +#define PPC_FEATURE_HAS_VSX 0x00000080 /* P7 Vector Extension. */ +#define PPC_FEATURE_970 (PPC_FEATURE_POWER4 + PPC_FEATURE_HAS_ALTIVEC) + +#ifdef __ASSEMBLER__ + +/* Symbolic names for the registers. The only portable way to write asm + code is to use number but this produces really unreadable code. + Therefore these symbolic names. */ + +/* Integer registers. */ +#define r0 0 +#define r1 1 +#define r2 2 +#define r3 3 +#define r4 4 +#define r5 5 +#define r6 6 +#define r7 7 +#define r8 8 +#define r9 9 +#define r10 10 +#define r11 11 +#define r12 12 +#define r13 13 +#define r14 14 +#define r15 15 +#define r16 16 +#define r17 17 +#define r18 18 +#define r19 19 +#define r20 20 +#define r21 21 +#define r22 22 +#define r23 23 +#define r24 24 +#define r25 25 +#define r26 26 +#define r27 27 +#define r28 28 +#define r29 29 +#define r30 30 +#define r31 31 + +/* Floating-point registers. */ +#define fp0 0 +#define fp1 1 +#define fp2 2 +#define fp3 3 +#define fp4 4 +#define fp5 5 +#define fp6 6 +#define fp7 7 +#define fp8 8 +#define fp9 9 +#define fp10 10 +#define fp11 11 +#define fp12 12 +#define fp13 13 +#define fp14 14 +#define fp15 15 +#define fp16 16 +#define fp17 17 +#define fp18 18 +#define fp19 19 +#define fp20 20 +#define fp21 21 +#define fp22 22 +#define fp23 23 +#define fp24 24 +#define fp25 25 +#define fp26 26 +#define fp27 27 +#define fp28 28 +#define fp29 29 +#define fp30 30 +#define fp31 31 + +/* Condition code registers. */ +#define cr0 0 +#define cr1 1 +#define cr2 2 +#define cr3 3 +#define cr4 4 +#define cr5 5 +#define cr6 6 +#define cr7 7 + +/* Vector registers. */ +#define v0 0 +#define v1 1 +#define v2 2 +#define v3 3 +#define v4 4 +#define v5 5 +#define v6 6 +#define v7 7 +#define v8 8 +#define v9 9 +#define v10 10 +#define v11 11 +#define v12 12 +#define v13 13 +#define v14 14 +#define v15 15 +#define v16 16 +#define v17 17 +#define v18 18 +#define v19 19 +#define v20 20 +#define v21 21 +#define v22 22 +#define v23 23 +#define v24 24 +#define v25 25 +#define v26 26 +#define v27 27 +#define v28 28 +#define v29 29 +#define v30 30 +#define v31 31 + +#define VRSAVE 256 + + +#ifdef __ELF__ + +/* This seems to always be the case on PPC. */ +#define ALIGNARG(log2) log2 +/* For ELF we need the `.type' directive to make shared libs work right. */ +#define ASM_TYPE_DIRECTIVE(name,typearg) .type name,typearg; +#define ASM_SIZE_DIRECTIVE(name) .size name,.-name + +/* In ELF C symbols are asm symbols. */ +#undef NO_UNDERSCORES +#define NO_UNDERSCORES + +#endif /* __ELF__ */ + +# include +# if defined(__powerpc64__) +# include "powerpc64/sysdep.h" +# else +# include "powerpc32/sysdep.h" +# endif + +#endif /* __ASSEMBLER__ */ + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/vfork.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/vfork.S new file mode 100644 index 00000000..00837426 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/vfork.S @@ -0,0 +1,30 @@ +/* vi: set sw=4 ts=4: */ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +#ifndef __NR_vfork +/* No vfork so use fork instead */ +# define __NR_vfork __NR_fork +#endif + +.text +.global __vfork +.hidden __vfork +.type __vfork,@function +.type __syscall_error,@function + +__vfork: + li 0, __NR_vfork + sc + bnslr+ + b __syscall_error + +.size __vfork,.-__vfork + +weak_alias(__vfork,vfork) +libc_hidden_weak(vfork) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/Makefile new file mode 100644 index 00000000..633c91f3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../../ +top_builddir=../../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.arch +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/Makefile.arch b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/Makefile.arch new file mode 100644 index 00000000..3e32e109 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/Makefile.arch @@ -0,0 +1,12 @@ +# Makefile for uClibc +# +# Copyright (C) 2001 by Hewlett-Packard Australia +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +CSRC := \ + mmap.c pipe.c __init_brk.c brk.c sbrk.c pread_write.c longjmp.c cacheflush.c + +SSRC := setjmp.S __longjmp.S ___fpscr_values.S diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/___fpscr_values.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/___fpscr_values.S new file mode 100644 index 00000000..3a1c8318 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/___fpscr_values.S @@ -0,0 +1,34 @@ +/* Startup code for SH & ELF. + Copyright (C) 1999 Free Software Foundation, Inc. + Copyright (C) 2001 Hewlett-Packard Australia + Copyright (C) 2002 Stefan Allius + + This program is free software; you can redistribute it and/or modify it under + the terms of the GNU Library General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at your option) any + later version. + + This program is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more + details. + + You should have received a copy of the GNU Library General Public License + along with this program; if not, write to the Free Software Foundation, Inc., + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include + +.data +#ifdef __SH4__ +.global ___fpscr_values +.type ___fpscr_values,@object +.size ___fpscr_values,8 +___fpscr_values: + .long 0 + .long 0x80000 + +.weak __fpscr_values + __fpscr_values = ___fpscr_values +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/__init_brk.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/__init_brk.c new file mode 100644 index 00000000..8a41eb3c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/__init_brk.c @@ -0,0 +1,26 @@ +/* From libc-5.3.12 */ + +#include +#include +#include + +void * __curbrk attribute_hidden = 0; + +#define __NR__brk __NR_brk +attribute_hidden _syscall1(void *, _brk, void *, ptr) + +extern int __init_brk (void) attribute_hidden; +int +__init_brk (void) +{ + if (__curbrk == 0) + { + __curbrk = _brk(0); + if (__curbrk == 0) + { + __set_errno(ENOMEM); + return -1; + } + } + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/__longjmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/__longjmp.S new file mode 100644 index 00000000..eb569917 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/__longjmp.S @@ -0,0 +1,65 @@ +/* longjmp for SH. + Copyright (C) 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#define _SETJMP_H +#define _ASM +#include +#include + +/* __longjmp(jmpbuf, val) */ + +.text +.align 4 +.type __longjmp,@function +.globl __longjmp; +__longjmp: + mov.l @r4+, r8 + mov.l @r4+, r9 + mov.l @r4+, r10 + mov.l @r4+, r11 + mov.l @r4+, r12 + mov.l @r4+, r13 + mov.l @r4+, r14 + mov.l @r4+, r15 +#if defined __UCLIBC_HAS_FLOATS__ && ! defined __UCLIBC_HAS_SOFT_FLOAT__ + lds.l @r4+, pr + ldc.l @r4+, gbr + lds.l @r4+, fpscr + fmov.s @r4+, fr12 + fmov.s @r4+, fr13 + mov r5, r0 /* get the return value in place */ + tst r0, r0 + bf.s 1f + fmov.s @r4+, fr14 + mov #1,r0 /* can't let setjmp() return zero! */ +1: + rts + fmov.s @r4+, fr15 +#else + mov r5, r0 /* get the return value in place */ + tst r0, r0 + bf.s 1f + lds.l @r4+, pr + mov #1,r0 /* can't let setjmp() return zero! */ +1: + rts + ldc.l @r4+, gbr +#endif +.size __longjmp,.-__longjmp +libc_hidden_def(__longjmp) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/bits/atomic.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/bits/atomic.h new file mode 100644 index 00000000..fa6d0de9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/bits/atomic.h @@ -0,0 +1,293 @@ +/* Atomic operations used inside libc. Linux/SH version. + Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + + +typedef int8_t atomic8_t; +typedef uint8_t uatomic8_t; +typedef int_fast8_t atomic_fast8_t; +typedef uint_fast8_t uatomic_fast8_t; + +typedef int16_t atomic16_t; +typedef uint16_t uatomic16_t; +typedef int_fast16_t atomic_fast16_t; +typedef uint_fast16_t uatomic_fast16_t; + +typedef int32_t atomic32_t; +typedef uint32_t uatomic32_t; +typedef int_fast32_t atomic_fast32_t; +typedef uint_fast32_t uatomic_fast32_t; + +typedef int64_t atomic64_t; +typedef uint64_t uatomic64_t; +typedef int_fast64_t atomic_fast64_t; +typedef uint_fast64_t uatomic_fast64_t; + +typedef intptr_t atomicptr_t; +typedef uintptr_t uatomicptr_t; +typedef intmax_t atomic_max_t; +typedef uintmax_t uatomic_max_t; + +/* SH kernel has implemented a gUSA ("g" User Space Atomicity) support + for the user space atomicity. The atomicity macros use this scheme. + + Reference: + Niibe Yutaka, "gUSA: Simple and Efficient User Space Atomicity + Emulation with Little Kernel Modification", Linux Conference 2002, + Japan. http://lc.linux.or.jp/lc2002/papers/niibe0919h.pdf (in + Japanese). + + Niibe Yutaka, "gUSA: User Space Atomicity with Little Kernel + Modification", LinuxTag 2003, Rome. + http://www.semmel.ch/Linuxtag-DVD/talks/170/paper.html (in English). + + B.N. Bershad, D. Redell, and J. Ellis, "Fast Mutual Exclusion for + Uniprocessors", Proceedings of the Fifth Architectural Support for + Programming Languages and Operating Systems (ASPLOS), pp. 223-233, + October 1992. http://www.cs.washington.edu/homes/bershad/Papers/Rcs.ps + + SuperH ABI: + r15: -(size of atomic instruction sequence) < 0 + r0: end point + r1: saved stack pointer +*/ + +/* Avoid having lots of different versions of compare and exchange, + by having this one complicated version. Parameters: + bwl: b, w or l for 8, 16 and 32 bit versions. + version: val or bool, depending on whether the result is the + previous value or a bool indicating whether the transfer + did happen (note this needs inverting before being + returned in atomic_compare_and_exchange_bool). +*/ + +#define __arch_compare_and_exchange_n(mem, newval, oldval, bwl, version) \ + ({ signed long __arch_result; \ + __asm__ __volatile__ ("\ + .align 2\n\ + mova 1f,r0\n\ + nop\n\ + mov r15,r1\n\ + mov #-8,r15\n\ + 0: mov." #bwl " @%1,%0\n\ + cmp/eq %0,%3\n\ + bf 1f\n\ + mov." #bwl " %2,@%1\n\ + 1: mov r1,r15\n\ + .ifeqs \"bool\",\"" #version "\"\n\ + movt %0\n\ + .endif\n" \ + : "=&r" (__arch_result) \ + : "r" (mem), "r" (newval), "r" (oldval) \ + : "r0", "r1", "t", "memory"); \ + __arch_result; }) + +#define __arch_compare_and_exchange_val_8_acq(mem, newval, oldval) \ + __arch_compare_and_exchange_n(mem, newval, (int8_t)(oldval), b, val) + +#define __arch_compare_and_exchange_val_16_acq(mem, newval, oldval) \ + __arch_compare_and_exchange_n(mem, newval, (int16_t)(oldval), w, val) + +#define __arch_compare_and_exchange_val_32_acq(mem, newval, oldval) \ + __arch_compare_and_exchange_n(mem, newval, (int32_t)(oldval), l, val) + +/* XXX We do not really need 64-bit compare-and-exchange. At least + not in the moment. Using it would mean causing portability + problems since not many other 32-bit architectures have support for + such an operation. So don't define any code for now. */ + +# define __arch_compare_and_exchange_val_64_acq(mem, newval, oldval) \ + (abort (), 0) + +/* For "bool" routines, return if the exchange did NOT occur */ + +#define __arch_compare_and_exchange_bool_8_acq(mem, newval, oldval) \ + (! __arch_compare_and_exchange_n(mem, newval, (int8_t)(oldval), b, bool)) + +#define __arch_compare_and_exchange_bool_16_acq(mem, newval, oldval) \ + (! __arch_compare_and_exchange_n(mem, newval, (int16_t)(oldval), w, bool)) + +#define __arch_compare_and_exchange_bool_32_acq(mem, newval, oldval) \ + (! __arch_compare_and_exchange_n(mem, newval, (int32_t)(oldval), l, bool)) + +# define __arch_compare_and_exchange_bool_64_acq(mem, newval, oldval) \ + (abort (), 0) + +/* Similar to the above, have one template which can be used in a + number of places. This version returns both the old and the new + values of the location. Parameters: + bwl: b, w or l for 8, 16 and 32 bit versions. + oper: The instruction to perform on the old value. + Note old is not sign extended, so should be an unsigned long. +*/ + +#define __arch_operate_old_new_n(mem, value, old, new, bwl, oper) \ + (void) ({ __asm__ __volatile__ ("\ + .align 2\n\ + mova 1f,r0\n\ + mov r15,r1\n\ + nop\n\ + mov #-8,r15\n\ + 0: mov." #bwl " @%2,%0\n\ + mov %0,%1\n\ + " #oper " %3,%1\n\ + mov." #bwl " %1,@%2\n\ + 1: mov r1,r15" \ + : "=&r" (old), "=&r"(new) \ + : "r" (mem), "r" (value) \ + : "r0", "r1", "memory"); \ + }) + +#define __arch_exchange_and_add_8_int(mem, value) \ + ({ int32_t __value = (value), __new, __old; \ + __arch_operate_old_new_n((mem), __value, __old, __new, b, add); \ + __old; }) + +#define __arch_exchange_and_add_16_int(mem, value) \ + ({ int32_t __value = (value), __new, __old; \ + __arch_operate_old_new_n((mem), __value, __old, __new, w, add); \ + __old; }) + +#define __arch_exchange_and_add_32_int(mem, value) \ + ({ int32_t __value = (value), __new, __old; \ + __arch_operate_old_new_n((mem), __value, __old, __new, l, add); \ + __old; }) + +#define __arch_exchange_and_add_64_int(mem, value) \ + (abort (), 0) + +#define atomic_exchange_and_add(mem, value) \ + __atomic_val_bysize (__arch_exchange_and_add, int, mem, value) + + +/* Again, another template. We get a slight optimisation when the old value + does not need to be returned. Parameters: + bwl: b, w or l for 8, 16 and 32 bit versions. + oper: The instruction to perform on the old value. +*/ + +#define __arch_operate_new_n(mem, value, bwl, oper) \ + ({ int32_t __value = (value), __new; \ + __asm__ __volatile__ ("\ + .align 2\n\ + mova 1f,r0\n\ + mov r15,r1\n\ + mov #-6,r15\n\ + 0: mov." #bwl " @%1,%0\n\ + " #oper " %2,%0\n\ + mov." #bwl " %0,@%1\n\ + 1: mov r1,r15" \ + : "=&r" (__new) \ + : "r" (mem), "r" (__value) \ + : "r0", "r1", "memory"); \ + __new; \ + }) + +#define __arch_add_8_int(mem, value) \ + __arch_operate_new_n(mem, value, b, add) + +#define __arch_add_16_int(mem, value) \ + __arch_operate_new_n(mem, value, w, add) + +#define __arch_add_32_int(mem, value) \ + __arch_operate_new_n(mem, value, l, add) + +#define __arch_add_64_int(mem, value) \ + (abort (), 0) + +#define atomic_add(mem, value) \ + ((void) __atomic_val_bysize (__arch_add, int, mem, value)) + + +#define __arch_add_negative_8_int(mem, value) \ + (__arch_operate_new_n(mem, value, b, add) < 0) + +#define __arch_add_negative_16_int(mem, value) \ + (__arch_operate_new_n(mem, value, w, add) < 0) + +#define __arch_add_negative_32_int(mem, value) \ + (__arch_operate_new_n(mem, value, l, add) < 0) + +#define __arch_add_negative_64_int(mem, value) \ + (abort (), 0) + +#define atomic_add_negative(mem, value) \ + __atomic_bool_bysize (__arch_add_negative, int, mem, value) + + +#define __arch_add_zero_8_int(mem, value) \ + (__arch_operate_new_n(mem, value, b, add) == 0) + +#define __arch_add_zero_16_int(mem, value) \ + (__arch_operate_new_n(mem, value, w, add) == 0) + +#define __arch_add_zero_32_int(mem, value) \ + (__arch_operate_new_n(mem, value, l, add) == 0) + +#define __arch_add_zero_64_int(mem, value) \ + (abort (), 0) + +#define atomic_add_zero(mem, value) \ + __atomic_bool_bysize (__arch_add_zero, int, mem, value) + + +#define atomic_increment_and_test(mem) atomic_add_zero((mem), 1) +#define atomic_decrement_and_test(mem) atomic_add_zero((mem), -1) + + +#define __arch_bit_set_8_int(mem, value) \ + __arch_operate_new_n(mem, 1<<(value), b, or) + +#define __arch_bit_set_16_int(mem, value) \ + __arch_operate_new_n(mem, 1<<(value), w, or) + +#define __arch_bit_set_32_int(mem, value) \ + __arch_operate_new_n(mem, 1<<(value), l, or) + +#define __arch_bit_set_64_int(mem, value) \ + (abort (), 0) + +#define __arch_add_64_int(mem, value) \ + (abort (), 0) + +#define atomic_bit_set(mem, value) \ + ((void) __atomic_val_bysize (__arch_bit_set, int, mem, value)) + + +#define __arch_bit_test_set_8_int(mem, value) \ + ({ int32_t __value = 1<<(value), __new, __old; \ + __arch_operate_old_new_n((mem), __value, __old, __new, b, or); \ + __old & __value; }) + +#define __arch_bit_test_set_16_int(mem, value) \ + ({ int32_t __value = 1<<(value), __new, __old; \ + __arch_operate_old_new_n((mem), __value, __old, __new, w, or); \ + __old & __value; }) + +#define __arch_bit_test_set_32_int(mem, value) \ + ({ int32_t __value = 1<<(value), __new, __old; \ + __arch_operate_old_new_n((mem), __value, __old, __new, l, or); \ + __old & __value; }) + +#define __arch_bit_test_set_64_int(mem, value) \ + (abort (), 0) + +#define atomic_bit_test_set(mem, value) \ + __atomic_val_bysize (__arch_bit_test_set, int, mem, value) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/bits/endian.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/bits/endian.h new file mode 100644 index 00000000..1fef1ff9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/bits/endian.h @@ -0,0 +1,13 @@ +/* SH is bi-endian but with a big-endian FPU. */ + +#ifndef _ENDIAN_H +# error "Never use directly; include instead." +#endif + +#ifdef __LITTLE_ENDIAN__ +#define __BYTE_ORDER __LITTLE_ENDIAN +#define __FLOAT_WORD_ORDER __LITTLE_ENDIAN +#else +#define __BYTE_ORDER __BIG_ENDIAN +#define __FLOAT_WORD_ORDER __BIG_ENDIAN +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/bits/fcntl.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/bits/fcntl.h new file mode 100644 index 00000000..adb73776 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/bits/fcntl.h @@ -0,0 +1,239 @@ +/* O_*, F_*, FD_* bit values for Linux. + Copyright (C) 1995, 1996, 1997, 1998, 2000, 2004, 2006, 2007 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FCNTL_H +# error "Never use directly; include instead." +#endif + +#include +#ifdef __USE_GNU +# include +#endif + + +/* open/fcntl - O_SYNC is only implemented on blocks devices and on files + located on an ext2 file system */ +#define O_ACCMODE 0003 +#define O_RDONLY 00 +#define O_WRONLY 01 +#define O_RDWR 02 +#define O_CREAT 0100 /* not fcntl */ +#define O_EXCL 0200 /* not fcntl */ +#define O_NOCTTY 0400 /* not fcntl */ +#define O_TRUNC 01000 /* not fcntl */ +#define O_APPEND 02000 +#define O_NONBLOCK 04000 +#define O_NDELAY O_NONBLOCK +#define O_SYNC 010000 +#define O_FSYNC O_SYNC +#define O_ASYNC 020000 + +#ifdef __USE_GNU +# define O_DIRECT 040000 /* Direct disk access. */ +# define O_DIRECTORY 0200000 /* Must be a directory. */ +# define O_NOFOLLOW 0400000 /* Do not follow links. */ +# define O_NOATIME 01000000 /* Do not set atime. */ +# define O_CLOEXEC 02000000 /* Set close_on_exec. */ +#endif + +/* For now Linux has synchronisity options for data and read operations. + We define the symbols here but let them do the same as O_SYNC since + this is a superset. */ +#if defined __USE_POSIX199309 || defined __USE_UNIX98 +# define O_DSYNC O_SYNC /* Synchronize data. */ +# define O_RSYNC O_SYNC /* Synchronize read operations. */ +#endif + +#ifdef __USE_LARGEFILE64 +# define O_LARGEFILE 0100000 +#endif + +/* Values for the second argument to `fcntl'. */ +#define F_DUPFD 0 /* Duplicate file descriptor. */ +#define F_GETFD 1 /* Get file descriptor flags. */ +#define F_SETFD 2 /* Set file descriptor flags. */ +#define F_GETFL 3 /* Get file status flags. */ +#define F_SETFL 4 /* Set file status flags. */ +#ifndef __USE_FILE_OFFSET64 +# define F_GETLK 5 /* Get record locking info. */ +# define F_SETLK 6 /* Set record locking info (non-blocking). */ +# define F_SETLKW 7 /* Set record locking info (blocking). */ +#else +# define F_GETLK F_GETLK64 /* Get record locking info. */ +# define F_SETLK F_SETLK64 /* Set record locking info (non-blocking).*/ +# define F_SETLKW F_SETLKW64 /* Set record locking info (blocking). */ +#endif +#define F_GETLK64 12 /* Get record locking info. */ +#define F_SETLK64 13 /* Set record locking info (non-blocking). */ +#define F_SETLKW64 14 /* Set record locking info (blocking). */ + +#if defined __USE_BSD || defined __USE_UNIX98 +# define F_SETOWN 8 /* Get owner of socket (receiver of SIGIO). */ +# define F_GETOWN 9 /* Set owner of socket (receiver of SIGIO). */ +#endif + +#ifdef __USE_GNU +# define F_SETSIG 10 /* Set number of signal to be sent. */ +# define F_GETSIG 11 /* Get number of signal to be sent. */ +#endif + +#ifdef __USE_GNU +# define F_SETLEASE 1024 /* Set a lease. */ +# define F_GETLEASE 1025 /* Enquire what lease is active. */ +# define F_NOTIFY 1026 /* Request notfications on a directory. */ +# define F_DUPFD_CLOEXEC 1030 /* Duplicate file descriptor with + close-on-exit set on new fd. */ +#endif + +/* For F_[GET|SET]FD. */ +#define FD_CLOEXEC 1 /* actually anything with low bit set goes */ + +/* For posix fcntl() and `l_type' field of a `struct flock' for lockf(). */ +#define F_RDLCK 0 /* Read lock. */ +#define F_WRLCK 1 /* Write lock. */ +#define F_UNLCK 2 /* Remove lock. */ + +/* For old implementation of bsd flock(). */ +#define F_EXLCK 4 /* or 3 */ +#define F_SHLCK 8 /* or 4 */ + +#ifdef __USE_BSD +/* Operations for bsd flock(), also used by the kernel implementation. */ +# define LOCK_SH 1 /* shared lock */ +# define LOCK_EX 2 /* exclusive lock */ +# define LOCK_NB 4 /* or'd with one of the above to prevent + blocking */ +# define LOCK_UN 8 /* remove lock */ +#endif + +#ifdef __USE_GNU +# define LOCK_MAND 32 /* This is a mandatory flock: */ +# define LOCK_READ 64 /* ... which allows concurrent read operations. */ +# define LOCK_WRITE 128 /* ... which allows concurrent write operations. */ +# define LOCK_RW 192 /* ... Which allows concurrent read & write operations. */ +#endif + +#ifdef __USE_GNU +/* Types of directory notifications that may be requested with F_NOTIFY. */ +# define DN_ACCESS 0x00000001 /* File accessed. */ +# define DN_MODIFY 0x00000002 /* File modified. */ +# define DN_CREATE 0x00000004 /* File created. */ +# define DN_DELETE 0x00000008 /* File removed. */ +# define DN_RENAME 0x00000010 /* File renamed. */ +# define DN_ATTRIB 0x00000020 /* File changed attibutes. */ +# define DN_MULTISHOT 0x80000000 /* Don't remove notifier. */ +#endif + +struct flock + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ +#ifndef __USE_FILE_OFFSET64 + __off_t l_start; /* Offset where the lock begins. */ + __off_t l_len; /* Size of the locked area; zero means until EOF. */ +#else + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ +#endif + __pid_t l_pid; /* Process holding the lock. */ + }; + +#ifdef __USE_LARGEFILE64 +struct flock64 + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ + __pid_t l_pid; /* Process holding the lock. */ + }; +#endif + +/* Define some more compatibility macros to be backward compatible with + BSD systems which did not managed to hide these kernel macros. */ +#ifdef __USE_BSD +# define FAPPEND O_APPEND +# define FFSYNC O_FSYNC +# define FASYNC O_ASYNC +# define FNONBLOCK O_NONBLOCK +# define FNDELAY O_NDELAY +#endif /* Use BSD. */ + +/* Advise to `posix_fadvise'. */ +#ifdef __USE_XOPEN2K +# define POSIX_FADV_NORMAL 0 /* No further special treatment. */ +# define POSIX_FADV_RANDOM 1 /* Expect random page references. */ +# define POSIX_FADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define POSIX_FADV_WILLNEED 3 /* Will need these pages. */ +# define POSIX_FADV_DONTNEED 4 /* Don't need these pages. */ +# define POSIX_FADV_NOREUSE 5 /* Data will be accessed once. */ +#endif + + +#if defined __USE_GNU && defined __UCLIBC_LINUX_SPECIFIC__ +/* Flags for SYNC_FILE_RANGE. */ +# define SYNC_FILE_RANGE_WAIT_BEFORE 1 /* Wait upon writeout of all pages + in the range before performing the + write. */ +# define SYNC_FILE_RANGE_WRITE 2 /* Initiate writeout of all those + dirty pages in the range which are + not presently under writeback. */ +# define SYNC_FILE_RANGE_WAIT_AFTER 4 /* Wait upon writeout of all pages in + the range after performing the + write. */ + +/* Flags for SPLICE and VMSPLICE. */ +# define SPLICE_F_MOVE 1 /* Move pages instead of copying. */ +# define SPLICE_F_NONBLOCK 2 /* Don't block on the pipe splicing + (but we may still block on the fd + we splice from/to). */ +# define SPLICE_F_MORE 4 /* Expect more data. */ +# define SPLICE_F_GIFT 8 /* Pages passed in are a gift. */ +#endif + +__BEGIN_DECLS + +#if defined __USE_GNU && defined __UCLIBC_LINUX_SPECIFIC__ + +/* Provide kernel hint to read ahead. */ +extern ssize_t readahead (int __fd, __off64_t __offset, size_t __count) + __THROW; + + +/* Selective file content synch'ing. */ +extern int sync_file_range (int __fd, __off64_t __from, __off64_t __to, + unsigned int __flags); + +/* Splice address range into a pipe. */ +extern ssize_t vmsplice (int __fdout, const struct iovec *__iov, + size_t __count, unsigned int __flags); + +/* Splice two files together. */ +extern ssize_t splice (int __fdin, __off64_t *__offin, int __fdout, + __off64_t *__offout, size_t __len, + unsigned int __flags); + +/* In-kernel implementation of tee for pipe buffers. */ +extern ssize_t tee (int __fdin, int __fdout, size_t __len, + unsigned int __flags); + +#endif +__END_DECLS + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/bits/fenv.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/bits/fenv.h new file mode 100644 index 00000000..cbbad92e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/bits/fenv.h @@ -0,0 +1,72 @@ +/* Copyright (C) 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FENV_H +# error "Never use directly; include instead." +#endif + + +/* Define bits representing the exception. We use the bit positions + of the appropriate bits in the FPU control word. */ +enum + { + FE_INEXACT = 0x04, +#define FE_INEXACT FE_INEXACT + FE_UNDERFLOW = 0x08, +#define FE_UNDERFLOW FE_UNDERFLOW + FE_OVERFLOW = 0x10, +#define FE_OVERFLOW FE_OVERFLOW + FE_DIVBYZERO = 0x20, +#define FE_DIVBYZERO FE_DIVBYZERO + FE_INVALID = 0x40, +#define FE_INVALID FE_INVALID + }; + +#define FE_ALL_EXCEPT \ + (FE_INEXACT | FE_DIVBYZERO | FE_UNDERFLOW | FE_OVERFLOW | FE_INVALID) + +/* The SH FPU supports all of the four defined rounding modes. We + use again the bit positions in the FPU control word as the values + for the appropriate macros. */ +enum + { + FE_TONEAREST = 0x0, +#define FE_TONEAREST FE_TONEAREST + FE_TOWARDZERO = 0x1, +#define FE_TOWARDZERO FE_TOWARDZERO + FE_UPWARD = 0x2, +#define FE_UPWARD FE_UPWARD + FE_DOWNWARD = 0x3 +#define FE_DOWNWARD FE_DOWNWARD + }; + + +/* Type representing exception flags. */ +typedef unsigned short int fexcept_t; + + +/* Type representing floating-point environment. This function corresponds + to the layout of the block written by the `fstenv'. */ +typedef struct + { + unsigned int __fpscr; + } +fenv_t; + +/* If the default argument is used we use this value. */ +#define FE_DFL_ENV ((fenv_t *) -1) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/bits/huge_val.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/bits/huge_val.h new file mode 100644 index 00000000..732b0650 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/bits/huge_val.h @@ -0,0 +1,56 @@ +/* `HUGE_VAL' constants for IEEE 754 machines (where it is infinity). + Used by and functions for overflow. + SH version. + Copyright (C) 1992, 95, 96, 97, 98, 99, 2000, 2004 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _MATH_H +# error "Never use directly; include instead." +#endif + +/* IEEE positive infinity (-HUGE_VAL is negative infinity). */ + +#if __GNUC_PREREQ(3,3) +# define HUGE_VAL (__builtin_huge_val()) +#elif __GNUC_PREREQ(2,96) +# define HUGE_VAL (__extension__ 0x1.0p2047) +#elif defined __GNUC__ + +# define HUGE_VAL \ + (__extension__ \ + ((union { unsigned __l __attribute__((__mode__(__DI__))); double __d; }) \ + { __l: 0x000000007ff00000ULL }).__d) + +#else /* not GCC */ + +# include + +typedef union { unsigned char __c[8]; double __d; } __huge_val_t; + +# if __BYTE_ORDER == __BIG_ENDIAN +# define __HUGE_VAL_bytes { 0, 0, 0, 0, 0x7f, 0xf0, 0, 0 } +# endif +# if __BYTE_ORDER == __LITTLE_ENDIAN +# define __HUGE_VAL_bytes { 0, 0, 0xf0, 0x7f, 0, 0, 0, 0 } +# endif + +static __huge_val_t __huge_val = { __HUGE_VAL_bytes }; +# define HUGE_VAL (__huge_val.__d) + +#endif /* GCC. */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/bits/kernel_stat.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/bits/kernel_stat.h new file mode 100644 index 00000000..8e6ffb49 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/bits/kernel_stat.h @@ -0,0 +1,81 @@ +#ifndef _BITS_STAT_STRUCT_H +#define _BITS_STAT_STRUCT_H + +#ifndef _LIBC +#error bits/kernel_stat.h is for internal uClibc use only! +#endif + +/* This file provides whatever this particular arch's kernel thinks + * struct kernel_stat should look like... It turns out each arch has a + * different opinion on the subject... */ +#include + +struct kernel_stat { + unsigned short st_dev; + unsigned short __pad1; + unsigned long st_ino; + unsigned short st_mode; + unsigned short st_nlink; + unsigned short st_uid; + unsigned short st_gid; + unsigned short st_rdev; + unsigned short __pad2; + unsigned long st_size; + unsigned long st_blksize; + unsigned long st_blocks; + struct timespec st_atim; + struct timespec st_mtim; + struct timespec st_ctim; + unsigned long __unused4; + unsigned long __unused5; +}; + +struct kernel_stat64 { +#if (__BYTE_ORDER == __BIG_ENDIAN) + unsigned char __pad0b[6]; + unsigned short st_dev; +#elif (__BYTE_ORDER == __LITTLE_ENDIAN) + unsigned short st_dev; + unsigned char __pad0b[6]; +#else +#error Must know endian to build stat64 structure! +#endif + unsigned char __pad0[4]; + + unsigned long st_ino; + unsigned int st_mode; + unsigned int st_nlink; + + unsigned long st_uid; + unsigned long st_gid; + +#if (__BYTE_ORDER == __BIG_ENDIAN) + unsigned char __pad3b[6]; + unsigned short st_rdev; +#else /* Must be little */ + unsigned short st_rdev; + unsigned char __pad3b[6]; +#endif + unsigned char __pad3[4]; + + long long st_size; + unsigned long st_blksize; + +#if (__BYTE_ORDER == __BIG_ENDIAN) + unsigned long __pad4; /* Future possible st_blocks hi bits */ + unsigned long st_blocks; /* Number 512-byte blocks allocated. */ +#else /* Must be little */ + unsigned long st_blocks; /* Number 512-byte blocks allocated. */ + unsigned long __pad4; /* Future possible st_blocks hi bits */ +#endif + + struct timespec st_atim; + struct timespec st_mtim; + struct timespec st_ctim; + + unsigned long __unused1; + unsigned long __unused2; +}; + +#endif /* _BITS_STAT_STRUCT_H */ + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/bits/kernel_types.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/bits/kernel_types.h new file mode 100644 index 00000000..f96e9fa3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/bits/kernel_types.h @@ -0,0 +1,45 @@ +/* Note that we use the exact same include guard #define names + * as asm/posix_types.h. This will avoid gratuitous conflicts + * with the posix_types.h kernel header, and will ensure that + * our private content, and not the kernel header, will win. + * -Erik + */ +#if !defined __ASM_SH_POSIX_TYPES_H && !defined __ASM_SH_POSIX_TYPES_32_H +#define __ASM_SH_POSIX_TYPES_H +#define __ASM_SH_POSIX_TYPES_32_H + +typedef unsigned short __kernel_dev_t; +typedef unsigned long __kernel_ino_t; +typedef unsigned short __kernel_mode_t; +typedef unsigned short __kernel_nlink_t; +typedef long __kernel_off_t; +typedef int __kernel_pid_t; +typedef unsigned short __kernel_ipc_pid_t; +typedef unsigned short __kernel_uid_t; +typedef unsigned short __kernel_gid_t; +typedef unsigned int __kernel_size_t; +typedef int __kernel_ssize_t; +typedef int __kernel_ptrdiff_t; +typedef long __kernel_time_t; +typedef long __kernel_suseconds_t; +typedef long __kernel_clock_t; +typedef int __kernel_daddr_t; +typedef char * __kernel_caddr_t; +typedef unsigned short __kernel_uid16_t; +typedef unsigned short __kernel_gid16_t; +typedef unsigned int __kernel_uid32_t; +typedef unsigned int __kernel_gid32_t; +typedef unsigned short __kernel_old_uid_t; +typedef unsigned short __kernel_old_gid_t; +typedef __kernel_dev_t __kernel_old_dev_t; +typedef long long __kernel_loff_t; + +typedef struct { +#ifdef __USE_ALL + int val[2]; +#else + int __val[2]; +#endif +} __kernel_fsid_t; + +#endif /* __ASM_SH_POSIX_TYPES_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/bits/mathdef.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/bits/mathdef.h new file mode 100644 index 00000000..70315ddf --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/bits/mathdef.h @@ -0,0 +1,49 @@ +/* Copyright (C) 1997, 1998, 1999, 2000, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#if !defined _MATH_H && !defined _COMPLEX_H +# error "Never use directly; include instead" +#endif + + +/* FIXME! This file describes properties of the compiler, not the machine; + it should not be part of libc! + + FIXME! This file does not deal with the -fshort-double option of + gcc! */ + +#if defined __USE_ISOC99 && defined _MATH_H && !defined _MATH_H_MATHDEF +# define _MATH_H_MATHDEF 1 + +/* SH has both `float' and `double' arithmetic. */ +typedef float float_t; /* `float' expressions are evaluated as + `float'. */ +typedef double double_t; /* `double' expressions are evaluated as + `double'. */ + +/* The values returned by `ilogb' for 0 and NaN respectively. */ +# define FP_ILOGB0 0x80000001 +# define FP_ILOGBNAN 0x7fffffff + +#endif /* ISO C99 */ + +#ifndef __NO_LONG_DOUBLE_MATH +/* Signal that we do not really have a `long double'. The disables the + declaration of all the `long double' function variants. */ +# define __NO_LONG_DOUBLE_MATH 1 +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/bits/setjmp.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/bits/setjmp.h new file mode 100644 index 00000000..6458dfef --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/bits/setjmp.h @@ -0,0 +1,56 @@ +/* Copyright (C) 1999, 2000, 2003, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Define the machine-dependent type `jmp_buf'. SH version. */ +#ifndef _BITS_SETJMP_H +#define _BITS_SETJMP_H 1 + +#if !defined _SETJMP_H && !defined _PTHREAD_H +# error "Never include directly; use instead." +#endif + +#ifndef _ASM +typedef struct + { + /* Callee-saved registers r8 through r15. */ + int __regs[8]; + + /* Program counter. */ + void * __pc; + + /* The global pointer. */ + void * __gbr; + + /* Floating point status register. */ + int __fpscr; + + /* Callee-saved floating point registers fr12 through fr15. */ + int __fpregs[4]; + } __jmp_buf[1]; +#endif + +#if defined __USE_MISC || defined _ASM +# define JB_SIZE (4 * 15) +#endif + +/* Test if longjmp to JMPBUF would unwind the frame + containing a local variable at ADDRESS. */ +#define _JMPBUF_UNWINDS(jmpbuf, address) \ + ((void *) (address) < (void *) (jmpbuf)[0].__regs[7]) + +#endif /* bits/setjmp.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/bits/shm.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/bits/shm.h new file mode 100644 index 00000000..ccf4b894 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/bits/shm.h @@ -0,0 +1,109 @@ +/* Copyright (C) 1995,1996,1997,2000,2002,2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_SHM_H +# error "Never include directly; use instead." +#endif + +#include + +/* Permission flag for shmget. */ +#define SHM_R 0400 /* or S_IRUGO from */ +#define SHM_W 0200 /* or S_IWUGO from */ + +/* Flags for `shmat'. */ +#define SHM_RDONLY 010000 /* attach read-only else read-write */ +#define SHM_RND 020000 /* round attach address to SHMLBA */ +#define SHM_REMAP 040000 /* take-over region on attach */ + +/* Commands for `shmctl'. */ +#define SHM_LOCK 11 /* lock segment (root only) */ +#define SHM_UNLOCK 12 /* unlock segment (root only) */ + +__BEGIN_DECLS + +/* Segment low boundary address multiple. */ +/* + * XXX: This is misleading, SH-4 and SH-3 7705 in 32kb mode have dcache + * aliases to contend with in the 4k page case. This is not an issue for + * the other parts. Leave this bumped up for sanity until this can be + * accurately defined by the L1D shape through the auxiliary vector. + */ +#define SHMLBA (__getpagesize() << 2) +extern int __getpagesize (void) __THROW __attribute__ ((__const__)); + + +/* Type to count number of attaches. */ +typedef unsigned long int shmatt_t; + +/* Data structure describing a set of semaphores. */ +struct shmid_ds + { + struct ipc_perm shm_perm; /* operation permission struct */ + size_t shm_segsz; /* size of segment in bytes */ + __time_t shm_atime; /* time of last shmat() */ + unsigned long int __unused1; + __time_t shm_dtime; /* time of last shmdt() */ + unsigned long int __unused2; + __time_t shm_ctime; /* time of last change by shmctl() */ + unsigned long int __unused3; + __pid_t shm_cpid; /* pid of creator */ + __pid_t shm_lpid; /* pid of last shmop */ + shmatt_t shm_nattch; /* number of current attaches */ + unsigned long int __unused4; + unsigned long int __unused5; + }; + +#ifdef __USE_MISC + +/* ipcs ctl commands */ +# define SHM_STAT 13 +# define SHM_INFO 14 + +/* shm_mode upper byte flags */ +# define SHM_DEST 01000 /* segment will be destroyed on last detach */ +# define SHM_LOCKED 02000 /* segment will not be swapped */ +# define SHM_HUGETLB 04000 /* segment is mapped via hugetlb */ +# define SHM_NORESERVE 010000 /* don't check for reservations */ + +struct shminfo + { + unsigned long int shmmax; + unsigned long int shmmin; + unsigned long int shmmni; + unsigned long int shmseg; + unsigned long int shmall; + unsigned long int __unused1; + unsigned long int __unused2; + unsigned long int __unused3; + unsigned long int __unused4; + }; + +struct shm_info + { + int used_ids; + unsigned long int shm_tot; /* total allocated shm */ + unsigned long int shm_rss; /* total resident shm */ + unsigned long int shm_swp; /* total swapped shm */ + unsigned long int swap_attempts; + unsigned long int swap_successes; + }; + +#endif /* __USE_MISC */ + +__END_DECLS diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/bits/sigcontextinfo.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/bits/sigcontextinfo.h new file mode 100644 index 00000000..3e1f3e94 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/bits/sigcontextinfo.h @@ -0,0 +1,27 @@ +/* Copyright (C) 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Philip Blundell , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define SIGCONTEXT int _a2, int _a3, int _a4, struct sigcontext + +#define SIGCONTEXT_EXTRA_ARGS _a2, _a3, _a4, +#define GET_PC(ctx) ((void *) ctx.sc_pc) +#define GET_FRAME(ctx) ((void *) ctx.sc_regs[14]) +#define GET_STACK(ctx) ((void *) ctx.sc_regs[15]) +#define CALL_SIGHANDLER(handler, signo, ctx) \ + (handler)((signo), SIGCONTEXT_EXTRA_ARGS (ctx)) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/bits/stackinfo.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/bits/stackinfo.h new file mode 100644 index 00000000..e65338f2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/bits/stackinfo.h @@ -0,0 +1,28 @@ +/* Copyright (C) 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This file contains a bit of information about the stack allocation + of the processor. */ + +#ifndef _STACKINFO_H +#define _STACKINFO_H 1 + +/* On SH the stack grows down. */ +#define _STACK_GROWS_DOWN 1 + +#endif /* stackinfo.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/bits/syscalls.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/bits/syscalls.h new file mode 100644 index 00000000..59d2d1ec --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/bits/syscalls.h @@ -0,0 +1,134 @@ +#ifndef _BITS_SYSCALLS_H +#define _BITS_SYSCALLS_H +#ifndef _SYSCALL_H +# error "Never use directly; include instead." +#endif + +/* The Linux kernel uses different trap numbers on sh-2. */ +#if defined __sh2__ || defined __SH2A__ +# define __SH_SYSCALL_TRAP_BASE 0x20 +#else +# define __SH_SYSCALL_TRAP_BASE 0x10 +#endif + +#ifndef __ASSEMBLER__ + +#include + +#define SYSCALL_INST_STR(x) "trapa #"__stringify(__SH_SYSCALL_TRAP_BASE + x)"\n\t" +#define SYSCALL_INST_STR0 SYSCALL_INST_STR(0) +#define SYSCALL_INST_STR1 SYSCALL_INST_STR(1) +#define SYSCALL_INST_STR2 SYSCALL_INST_STR(2) +#define SYSCALL_INST_STR3 SYSCALL_INST_STR(3) +#define SYSCALL_INST_STR4 SYSCALL_INST_STR(4) +#define SYSCALL_INST_STR5 SYSCALL_INST_STR(5) +#define SYSCALL_INST_STR6 SYSCALL_INST_STR(6) + +# ifdef NEED_SYSCALL_INST_PAD +# define SYSCALL_INST_PAD "\ + or r0,r0; or r0,r0; or r0,r0; or r0,r0; or r0,r0" +# else +# define SYSCALL_INST_PAD +# endif + +#define ASMFMT_0 +#define ASMFMT_1 \ + , "r" (r4) +#define ASMFMT_2 \ + , "r" (r4), "r" (r5) +#define ASMFMT_3 \ + , "r" (r4), "r" (r5), "r" (r6) +#define ASMFMT_4 \ + , "r" (r4), "r" (r5), "r" (r6), "r" (r7) +#define ASMFMT_5 \ + , "r" (r4), "r" (r5), "r" (r6), "r" (r7), "0" (r0) +#define ASMFMT_6 \ + , "r" (r4), "r" (r5), "r" (r6), "r" (r7), "0" (r0), "r" (r1) +#define ASMFMT_7 \ + , "r" (r4), "r" (r5), "r" (r6), "r" (r7), "0" (r0), "r" (r1), "r" (r2) + +#define SUBSTITUTE_ARGS_0() +#define SUBSTITUTE_ARGS_1(arg1) \ + long int _arg1 = (long int) (arg1); \ + register long int r4 __asm__ ("%r4") = (long int) (_arg1) +#define SUBSTITUTE_ARGS_2(arg1, arg2) \ + long int _arg1 = (long int) (arg1); \ + long int _arg2 = (long int) (arg2); \ + register long int r4 __asm__ ("%r4") = (long int) (_arg1); \ + register long int r5 __asm__ ("%r5") = (long int) (_arg2) +#define SUBSTITUTE_ARGS_3(arg1, arg2, arg3) \ + long int _arg1 = (long int) (arg1); \ + long int _arg2 = (long int) (arg2); \ + long int _arg3 = (long int) (arg3); \ + register long int r4 __asm__ ("%r4") = (long int) (_arg1); \ + register long int r5 __asm__ ("%r5") = (long int) (_arg2); \ + register long int r6 __asm__ ("%r6") = (long int) (_arg3) +#define SUBSTITUTE_ARGS_4(arg1, arg2, arg3, arg4) \ + long int _arg1 = (long int) (arg1); \ + long int _arg2 = (long int) (arg2); \ + long int _arg3 = (long int) (arg3); \ + long int _arg4 = (long int) (arg4); \ + register long int r4 __asm__ ("%r4") = (long int) (_arg1); \ + register long int r5 __asm__ ("%r5") = (long int) (_arg2); \ + register long int r6 __asm__ ("%r6") = (long int) (_arg3); \ + register long int r7 __asm__ ("%r7") = (long int) (_arg4) +#define SUBSTITUTE_ARGS_5(arg1, arg2, arg3, arg4, arg5) \ + long int _arg1 = (long int) (arg1); \ + long int _arg2 = (long int) (arg2); \ + long int _arg3 = (long int) (arg3); \ + long int _arg4 = (long int) (arg4); \ + long int _arg5 = (long int) (arg5); \ + register long int r4 __asm__ ("%r4") = (long int) (_arg1); \ + register long int r5 __asm__ ("%r5") = (long int) (_arg2); \ + register long int r6 __asm__ ("%r6") = (long int) (_arg3); \ + register long int r7 __asm__ ("%r7") = (long int) (_arg4); \ + register long int r0 __asm__ ("%r0") = (long int) (_arg5) +#define SUBSTITUTE_ARGS_6(arg1, arg2, arg3, arg4, arg5, arg6) \ + long int _arg1 = (long int) (arg1); \ + long int _arg2 = (long int) (arg2); \ + long int _arg3 = (long int) (arg3); \ + long int _arg4 = (long int) (arg4); \ + long int _arg5 = (long int) (arg5); \ + long int _arg6 = (long int) (arg6); \ + register long int r4 __asm__ ("%r4") = (long int)(_arg1); \ + register long int r5 __asm__ ("%r5") = (long int) (_arg2); \ + register long int r6 __asm__ ("%r6") = (long int) (_arg3); \ + register long int r7 __asm__ ("%r7") = (long int) (_arg4); \ + register long int r0 __asm__ ("%r0") = (long int) (_arg5); \ + register long int r1 __asm__ ("%r1") = (long int) (_arg6) +#define SUBSTITUTE_ARGS_7(arg1, arg2, arg3, arg4, arg5, arg6, arg7) \ + long int _arg1 = (long int) (arg1); \ + long int _arg2 = (long int) (arg2); \ + long int _arg3 = (long int) (arg3); \ + long int _arg4 = (long int) (arg4); \ + long int _arg5 = (long int) (arg5); \ + long int _arg6 = (long int) (arg6); \ + long int _arg7 = (long int) (arg7); \ + register long int r4 __asm__ ("%r4") = (long int) (_arg1); \ + register long int r5 __asm__ ("%r5") = (long int) (_arg2); \ + register long int r6 __asm__ ("%r6") = (long int) (_arg3); \ + register long int r7 __asm__ ("%r7") = (long int) (_arg4); \ + register long int r0 __asm__ ("%r0") = (long int) (_arg5); \ + register long int r1 __asm__ ("%r1") = (long int) (_arg6); \ + register long int r2 __asm__ ("%r2") = (long int) (_arg7) + +/* The _NCS variant allows non-constant syscall numbers. */ +#define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \ + ({ \ + unsigned long int resultvar; \ + register long int r3 __asm__ ("%r3") = (name); \ + SUBSTITUTE_ARGS_##nr(args); \ + \ + __asm__ __volatile__ (SYSCALL_INST_STR##nr SYSCALL_INST_PAD \ + : "=z" (resultvar) \ + : "r" (r3) ASMFMT_##nr \ + : "memory"); \ + \ + (int) resultvar; }) + +#define INTERNAL_SYSCALL_ERROR_P(val, err) \ + ((unsigned int) (val) >= 0xfffff001u) + +#endif /* __ASSEMBLER__ */ +#endif /* _BITS_SYSCALLS_H */ + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/bits/uClibc_arch_features.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/bits/uClibc_arch_features.h new file mode 100644 index 00000000..5e3528d2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/bits/uClibc_arch_features.h @@ -0,0 +1,51 @@ +/* + * Track misc arch-specific features that aren't config options + */ + +#ifndef _BITS_UCLIBC_ARCH_FEATURES_H +#define _BITS_UCLIBC_ARCH_FEATURES_H + +/* instruction used when calling abort() to kill yourself */ +#ifdef __sh2__ +# define __UCLIBC_ABORT_INSTRUCTION__ "trapa #32" +#else +# define __UCLIBC_ABORT_INSTRUCTION__ "trapa #0xff" +#endif + +/* can your target use syscall6() for mmap ? */ +#define __UCLIBC_MMAP_HAS_6_ARGS__ + +/* does your target use syscall4() for truncate64 ? (32bit arches only) */ +#undef __UCLIBC_TRUNCATE64_HAS_4_ARGS__ + +/* does your target have a broken create_module() ? */ +#undef __UCLIBC_BROKEN_CREATE_MODULE__ + +/* does your target have to worry about older [gs]etrlimit() ? */ +#undef __UCLIBC_HANDLE_OLDER_RLIMIT__ + +/* does your target have an asm .set ? */ +#define __UCLIBC_HAVE_ASM_SET_DIRECTIVE__ + +/* define if target doesn't like .global */ +#undef __UCLIBC_ASM_GLOBAL_DIRECTIVE__ + +/* define if target supports .weak */ +#define __UCLIBC_HAVE_ASM_WEAK_DIRECTIVE__ + +/* define if target supports .weakext */ +#undef __UCLIBC_HAVE_ASM_WEAKEXT_DIRECTIVE__ + +/* needed probably only for ppc64 */ +#undef __UCLIBC_HAVE_ASM_GLOBAL_DOT_NAME__ + +/* define if target supports CFI pseudo ops */ +#define __UCLIBC_HAVE_ASM_CFI_DIRECTIVES__ + +/* define if target supports IEEE signed zero floats */ +#define __UCLIBC_HAVE_SIGNED_ZERO__ + +/* only weird assemblers generally need this */ +#undef __UCLIBC_ASM_LINE_SEP__ + +#endif /* _BITS_UCLIBC_ARCH_FEATURES_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/bits/wordsize.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/bits/wordsize.h new file mode 100644 index 00000000..ba643b60 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/bits/wordsize.h @@ -0,0 +1,19 @@ +/* Copyright (C) 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define __WORDSIZE 32 diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/brk.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/brk.c new file mode 100644 index 00000000..a98cd544 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/brk.c @@ -0,0 +1,27 @@ +/* From libc-5.3.12 */ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include + +extern void * __curbrk attribute_hidden; +extern int __init_brk (void) attribute_hidden; +extern void *_brk(void *ptr) attribute_hidden; + +int brk(void * end_data_seg) +{ + if (__init_brk () == 0) + { + __curbrk = _brk(end_data_seg); + if (__curbrk == end_data_seg) + return 0; + __set_errno(ENOMEM); + } + return -1; +} +libc_hidden_def(brk) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/cacheflush.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/cacheflush.c new file mode 100644 index 00000000..58229186 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/cacheflush.c @@ -0,0 +1,15 @@ +/* + * cacheflush syscall for SUPERH + * + * Copyright (C) 2009 STMicroelectronics Ltd + * Author: Giuseppe Cavallaro + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ +#include +#include +#include + +#ifdef __NR_cacheflush +_syscall3(int, cacheflush, char *, addr, int, nbytes, int, op) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/clone.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/clone.S new file mode 100644 index 00000000..423a6c2f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/clone.S @@ -0,0 +1,134 @@ +/* Copyright (C) 1999, 2000, 2003, 2004, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* clone() is even more special than fork() as it mucks with stacks + and invokes a function in the right context after its all over. */ + +#include +#include +#include +#define _ERRNO_H 1 +#include +#ifdef RESET_PID +#include +#endif +/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg, + pid_t *ptid, void *tls, pid_t *ctid); */ + + .text +ENTRY(__clone) + /* sanity check arguments. */ + tst r4, r4 + bt/s 0f + tst r5, r5 + bf 1f +0: + bra .Lsyscall_error + mov #-EINVAL,r0 +1: + /* insert the args onto the new stack */ + mov.l r7, @-r5 + /* save the function pointer as the 0th element */ + mov.l r4, @-r5 + + /* do the system call */ + mov r6, r4 + mov.l @r15, r6 + mov.l @(8,r15), r7 + mov.l @(4,r15), r0 + mov #+SYS_ify(clone), r3 + trapa #0x15 + mov r0, r1 + mov #-12, r2 + shad r2, r1 + not r1, r1 // r1=0 means r0 = -1 to -4095 + tst r1, r1 // i.e. error in linux + bf .Lclone_end +.Lsyscall_error: + SYSCALL_ERROR_HANDLER +.Lclone_end: + tst r0, r0 + bt 2f +.Lpseudo_end: + rts + nop +2: + /* terminate the stack frame */ + mov #0, r14 +#ifdef RESET_PID + mov r4, r0 + shlr16 r0 + tst #1, r0 // CLONE_THREAD = (1 << 16) + bf/s 4f + mov r4, r0 + /* new pid */ + shlr8 r0 + tst #1, r0 // CLONE_VM = (1 << 8) + bf/s 3f + mov #-1, r0 + mov #+SYS_ify(getpid), r3 + trapa #0x15 +3: + stc gbr, r1 + mov.w .Lpidoff, r2 + add r1, r2 + mov.l r0, @r2 + mov.w .Ltidoff, r2 + add r1, r2 + mov.l r0, @r2 +4: +#endif + /* thread starts */ + mov.l @r15, r1 + jsr @r1 + mov.l @(4,r15), r4 + + /* we are done, passing the return value through r0 */ + mov.l .L3, r1 +#ifdef SHARED + mov.l r12, @-r15 + sts.l pr, @-r15 + mov r0, r4 + mova .LG, r0 + mov.l .LG, r12 + add r0, r12 + mova .L3, r0 + add r0, r1 + jsr @r1 + nop + lds.l @r15+, pr + rts + mov.l @r15+, r12 +#else + jmp @r1 + mov r0, r4 +#endif + .align 2 +.LG: + .long _GLOBAL_OFFSET_TABLE_ +.L3: + .long PLTJMP(C_SYMBOL_NAME(_exit)) +#ifdef RESET_PID +.Lpidoff: + .word PID - TLS_PRE_TCB_SIZE +.Ltidoff: + .word TID - TLS_PRE_TCB_SIZE +#endif +PSEUDO_END (__clone) + +weak_alias (__clone, clone) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/crt1.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/crt1.S new file mode 100644 index 00000000..9707f831 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/crt1.S @@ -0,0 +1,142 @@ +/* Startup code for SH & ELF. + Copyright (C) 1999 Free Software Foundation, Inc. + Copyright (C) 2001 Hewlett-Packard Australia + Copyright (C) 2002 Stefan Allius + + This program is free software; you can redistribute it and/or modify it under + the terms of the GNU Library General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at your option) any + later version. + + This program is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more + details. + + You should have received a copy of the GNU Library General Public License + along with this program; if not, write to the Free Software Foundation, Inc., + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + +/* This is the canonical entry point, usually the first thing in the text + segment. + + At this entry point, most registers' values are unspecified, except: + + r4 Contains a function pointer to be registered with `atexit'. + This is how the dynamic linker arranges to have DT_FINI + functions called for shared libraries that have been loaded + before this code runs. + + sp The stack contains the arguments and environment: + 0(sp) argc + 4(sp) argv[0] + ... + (4*argc)(sp) NULL + (4*(argc+1))(sp) envp[0] + ... + NULL +*/ + +#include + + .text + .globl _start + .type _start,%function + .type main,%function +_start: + /* Clear the frame pointer since this is the outermost frame. */ + mov #0, r14 + + /* Pop argc off the stack and save a pointer to argv */ + mov.l @r15+,r5 + mov r15, r6 + + /* Push the stack_end, rtld_fini and fini func onto the stack */ + mov.l r6,@-r15 + mov.l r4,@-r15 + +#ifdef __PIC__ + mova L_got, r0 + mov.l L_got, r12 + add r0, r12 + + mov.l L_fini,r0 + add r12, r0 + mov.l r0,@-r15 + + /* Set up the main/init funcs that go in registers */ + mov.l L_main, r4 + add r12, r4 + mov.l L_init, r7 + add r12, r7 + + /* __uClibc_main (main, argc, argv, init, fini, rtld_fini, stack_end) */ + + /* Let the libc call main and exit with its return code. */ + mov.l L_uClibc_main,r0 + mov.l @(r0,r12),r1 + jsr @r1 + nop + /* We should not get here. */ + mov.l L_abort,r0 + mov.l @(r0,r12),r1 + jsr @r1 + nop +#else + mov.l L_fini,r0 + mov.l r0,@-r15 + + /* Set up the main/init funcs that go in registers */ + mov.l L_main,r4 + mov.l L_init,r7 + + /* __uClibc_main (main, argc, argv, init, fini, rtld_fini, stack_end) */ + + /* Let the libc call main and exit with its return code. */ + mov.l L_uClibc_main,r1 + jsr @r1 + nop + /* We should not get here. */ + mov.l L_abort,r1 + jmp @r1 + nop +#endif + + .size _start,.-_start + .align 2 + +#ifdef __PIC__ +L_got: + .long _GLOBAL_OFFSET_TABLE_ +L_main: + .long main@GOTOFF +L_init: + .long _init@GOTOFF +L_fini: + .long _fini@GOTOFF +L_uClibc_main: + .long __uClibc_main@GOT +L_abort: + .long abort@GOT +#else +L_main: + .long main +L_init: + .long _init +L_fini: + .long _fini +L_uClibc_main: + .long __uClibc_main +L_abort: + .long abort +#endif + +/* Define a symbol for the first piece of initialized data. */ + .data + .globl __data_start +__data_start: + .long 0 + .weak data_start + data_start = __data_start diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/crti.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/crti.S new file mode 100644 index 00000000..7fba2663 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/crti.S @@ -0,0 +1,32 @@ + .file "crti.S" + .text + + .section .init + .hidden _init + .align 1 + .global _init + .type _init, @function +_init: + mov.l r12,@-r15 + mov.l r14,@-r15 + sts.l pr,@-r15 + mov r15,r14 + bra 1f + nop + .align 2 +1: + + .section .fini + .hidden _fini + .align 1 + .global _fini + .type _fini, @function +_fini: + mov.l r12,@-r15 + mov.l r14,@-r15 + sts.l pr,@-r15 + mov r15,r14 + bra 1f + nop + .align 2 +1: diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/crtn.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/crtn.S new file mode 100644 index 00000000..e8be7e51 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/crtn.S @@ -0,0 +1,34 @@ + .file "crtn.S" + .text + + .section .init + .hidden _init + .align 1 + .global _init + .type _init, @function + mov r14,r15 + lds.l @r15+,pr + mov.l @r15+,r14 + rts + mov.l @r15+,r12 +.L8: + .align 2 +.L6: +.L7: + + .section .fini + .hidden _fini + .align 1 + .global _fini + .type _fini, @function + mov r14,r15 + lds.l @r15+,pr + mov.l @r15+,r14 + rts + mov.l @r15+,r12 +.L13: + .align 2 +.L11: +.L12: + + .ident "GCC: (GNU) 3.3.2" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/fpu_control.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/fpu_control.h new file mode 100644 index 00000000..da01725c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/fpu_control.h @@ -0,0 +1,64 @@ +/* FPU control word definitions. SH version. + Copyright (C) 1999, 2000, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FPU_CONTROL_H +#define _FPU_CONTROL_H + +#ifndef __SH4__ +#error This file is only correct for sh4 +#endif + +/* masking of interrupts */ +#define _FPU_MASK_VM 0x0800 /* Invalid operation */ +#define _FPU_MASK_ZM 0x0400 /* Division by zero */ +#define _FPU_MASK_OM 0x0200 /* Overflow */ +#define _FPU_MASK_UM 0x0100 /* Underflow */ +#define _FPU_MASK_IM 0x0080 /* Inexact operation */ + +/* rounding control */ +#define _FPU_RC_NEAREST 0x0 /* RECOMMENDED */ +#define _FPU_RC_ZERO 0x1 + +#define _FPU_RESERVED 0xffc00000 /* These bits are reserved. */ + +/* The fdlibm code requires strict IEEE double precision arithmetic, + and no interrupts for exceptions, rounding to nearest. */ +#define _FPU_DEFAULT 0x00080000 /* Default value. */ +#define _FPU_IEEE 0x00080f80 /* Default + exceptions enabled. */ + +/* Type of the control word. */ +typedef unsigned int fpu_control_t; + +/* Macros for accessing the hardware control word. */ +#define _FPU_GETCW(cw) __asm__ ("sts fpscr,%0" : "=r" (cw)) + +#if defined __GNUC__ +/* GCC provides this function */ +extern void __set_fpscr (unsigned long); +#define _FPU_SETCW(cw) __set_fpscr ((cw)) +#else +#define _FPU_SETCW(cw) __asm__ ("lds %0,fpscr" : : "r" (cw)) +#endif + +#if 0 +/* Default control word set at startup. */ +extern fpu_control_t __fpu_control; +#endif + +#endif /* _FPU_CONTROL_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/longjmp.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/longjmp.c new file mode 100644 index 00000000..dd0616d8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/longjmp.c @@ -0,0 +1,56 @@ +/* Copyright (C) 1991, 92, 94, 95, 97, 98, 2000 Free Software Foundation, Inc. + Copyright (C) 2001 Hewlett-Packard Australia + + This program is free software; you can redistribute it and/or modify it under + the terms of the GNU Library General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at your option) any + later version. + + This program is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more + details. + + You should have received a copy of the GNU Library General Public License + along with this program; if not, write to the Free Software Foundation, Inc., + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Derived in part from the Linux-8086 C library, the GNU C Library, and several + other sundry sources. Files within this library are copyright by their + respective copyright holders. +*/ + +#include +#include +#include + +libc_hidden_proto(sigprocmask) + +extern int __longjmp(char *env, int val); +libc_hidden_proto(__longjmp) + +extern void _longjmp_unwind (jmp_buf env, int val); + + +/* Set the signal mask to the one specified in ENV, and jump + to the position specified in ENV, causing the setjmp + call there to return VAL, or 1 if VAL is 0. */ +void __libc_siglongjmp (sigjmp_buf env, int val) +{ + /* Perform any cleanups needed by the frames being unwound. */ + + _longjmp_unwind (env, val); + + if (env[0].__mask_was_saved) + /* Restore the saved signal mask. */ + (void) sigprocmask (SIG_SETMASK, &env[0].__saved_mask, + (sigset_t *) NULL); + + /* Call the machine-dependent function to restore machine state. */ + __longjmp ((char *) env[0].__jmpbuf, val ?: 1); +} + +__asm__(".weak longjmp; longjmp = __libc_siglongjmp"); +__asm__(".weak _longjmp; _longjmp = __libc_siglongjmp"); +__asm__(".weak siglongjmp; siglongjmp = __libc_siglongjmp"); +strong_alias(__libc_siglongjmp, __libc_longjmp) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/mmap.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/mmap.c new file mode 100644 index 00000000..b14181cb --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/mmap.c @@ -0,0 +1,34 @@ +/* Copyright (C) 2001 Hewlett-Packard + + This program is free software; you can redistribute it and/or modify it under + the terms of the GNU Library General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at your option) any + later version. + + This program is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more + details. + + You should have received a copy of the GNU Library General Public License + along with this program; if not, write to the Free Software Foundation, Inc., + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Derived in part from the Linux-8086 C library, the GNU C Library, and several + other sundry sources. Files within this library are copyright by their + respective copyright holders. +*/ + +#include +#include +#include + + +#ifdef HIOS +# define __SH_SYSCALL6_TRAPA 0x2E +#endif + +#include + +_syscall6(__ptr_t, mmap, __ptr_t, addr, size_t, len, int, prot, int, flags, int, fd, __off_t, offset) +libc_hidden_def(mmap) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/pipe.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/pipe.c new file mode 100644 index 00000000..799f5183 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/pipe.c @@ -0,0 +1,39 @@ +/* vi: set sw=4 ts=4: */ +/* + * pipe syscall for uClibc sh + * + * Copyright (C) 2001 Lineo, + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include + + +int pipe(int *fd) +{ + long __res, __res2; + __asm__ __volatile__ ( + "mov %2, r3;" + "mov %3, r4;" + "trapa %4;" + "mov r1, %1;" + : "=z" (__res), + "=r" ((long) __res2) + : "r" ((long) __NR_pipe), + "r" ((long) fd), + "i" (__SH_SYSCALL_TRAP_BASE + 3) + : "cc", "memory", "r1", "r3", "r4"); + if ((unsigned long)(__res) >= (unsigned long)(-125)) { + int __err = -(__res); + errno = __err; + return(-1); + } + fd[0] = __res; + fd[1] = __res2; + return(0); +} +libc_hidden_def(pipe) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/pread_write.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/pread_write.c new file mode 100644 index 00000000..86feb9cc --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/pread_write.c @@ -0,0 +1,125 @@ +/* vi: set sw=4 ts=4: */ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ +/* + * Based in part on the files + * ./sysdeps/unix/sysv/linux/pwrite.c, + * ./sysdeps/unix/sysv/linux/pread.c, + * sysdeps/posix/pread.c + * sysdeps/posix/pwrite.c + * from GNU libc 2.2.5, but reworked considerably... + */ + +#include +#include +#include +#include + +#ifdef __UCLIBC_HAS_THREADS_NATIVE__ +#include +#else +#define SINGLE_THREAD_P 1 +#endif + + +#ifdef __NR_pread64 /* Newer kernels renamed but it's the same. */ +# ifdef __NR_pread +# error "__NR_pread and __NR_pread64 both defined???" +# endif +# define __NR_pread __NR_pread64 +#endif + +#ifdef __NR_pread +extern __typeof(pread) __libc_pread; +# define __NR___syscall_pread __NR_pread +static __inline__ _syscall6(ssize_t, __syscall_pread, int, fd, void *, buf, + size_t, count, int, dummy, off_t, offset_hi, off_t, offset_lo) + +ssize_t __libc_pread(int fd, void *buf, size_t count, off_t offset) +{ + if (SINGLE_THREAD_P) + return(__syscall_pread(fd,buf,count,0,__LONG_LONG_PAIR(offset >> 31,offset))); + +#ifdef __UCLIBC_HAS_THREADS_NATIVE__ + int oldtype = LIBC_CANCEL_ASYNC (); + ssize_t result = __syscall_pread(fd,buf,count,0,__LONG_LONG_PAIR(offset >> 31,offset)); + LIBC_CANCEL_RESET (oldtype); + return result; +#endif +} +weak_alias(__libc_pread,pread) + +# ifdef __UCLIBC_HAS_LFS__ +extern __typeof(pread64) __libc_pread64; +ssize_t __libc_pread64(int fd, void *buf, size_t count, off64_t offset) +{ + uint32_t low = offset & 0xffffffff; + uint32_t high = offset >> 32; + + if (SINGLE_THREAD_P) + return __syscall_pread(fd, buf, count, 0, __LONG_LONG_PAIR (high, low)); + +#ifdef __UCLIBC_HAS_THREADS_NATIVE__ + int oldtype = LIBC_CANCEL_ASYNC (); + ssize_t result = __syscall_pread(fd, buf, count, 0, __LONG_LONG_PAIR (high, low)); + LIBC_CANCEL_RESET (oldtype); + return result; +#endif +} +weak_alias(__libc_pread64,pread64) +# endif /* __UCLIBC_HAS_LFS__ */ +#endif /* __NR_pread */ + +/**********************************************************************/ + +#ifdef __NR_pwrite64 /* Newer kernels renamed but it's the same. */ +# ifdef __NR_pwrite +# error "__NR_pwrite and __NR_pwrite64 both defined???" +# endif +# define __NR_pwrite __NR_pwrite64 +#endif + +#ifdef __NR_pwrite +extern __typeof(pwrite) __libc_pwrite; +# define __NR___syscall_pwrite __NR_pwrite +static __inline__ _syscall6(ssize_t, __syscall_pwrite, int, fd, const void *, buf, + size_t, count, int, dummy, off_t, offset_hi, off_t, offset_lo) + +ssize_t __libc_pwrite(int fd, const void *buf, size_t count, off_t offset) +{ + if (SINGLE_THREAD_P) + return __syscall_pwrite(fd,buf,count,0,__LONG_LONG_PAIR(offset >> 31,offset)); + +#ifdef __UCLIBC_HAS_THREADS_NATIVE__ + int oldtype = LIBC_CANCEL_ASYNC (); + ssize_t result = __syscall_pwrite(fd,buf,count,0,__LONG_LONG_PAIR(offset >> 31,offset)); + LIBC_CANCEL_RESET (oldtype); + return result; +#endif + +} +weak_alias(__libc_pwrite,pwrite) + +# ifdef __UCLIBC_HAS_LFS__ +extern __typeof(pwrite64) __libc_pwrite64; +ssize_t __libc_pwrite64(int fd, const void *buf, size_t count, off64_t offset) +{ + uint32_t low = offset & 0xffffffff; + uint32_t high = offset >> 32; + + if (SINGLE_THREAD_P) + return __syscall_pwrite(fd, buf, count, 0, __LONG_LONG_PAIR (high, low)); + +#ifdef __UCLIBC_HAS_THREADS_NATIVE__ + int oldtype = LIBC_CANCEL_ASYNC (); + ssize_t result = __syscall_pwrite(fd, buf, count, 0, __LONG_LONG_PAIR (high, low)); + LIBC_CANCEL_RESET (oldtype); + return result; +#endif +} +weak_alias(__libc_pwrite64,pwrite64) +# endif /* __UCLIBC_HAS_LFS__ */ +#endif /* __NR_pwrite */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/sbrk.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/sbrk.c new file mode 100644 index 00000000..2dc719a1 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/sbrk.c @@ -0,0 +1,25 @@ +/* From libc-5.3.12 */ + +#include +#include +#include + +extern void * __curbrk attribute_hidden; +extern int __init_brk (void) attribute_hidden; +extern void *_brk(void *ptr) attribute_hidden; + +void * +sbrk(intptr_t increment) +{ + if (__init_brk () == 0) + { + char * tmp = (char*)__curbrk+increment; + __curbrk = _brk(tmp); + if (__curbrk == tmp) + return tmp-increment; + __set_errno(ENOMEM); + return ((void *) -1); + } + return ((void *) -1); +} +libc_hidden_def(sbrk) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/setjmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/setjmp.S new file mode 100644 index 00000000..0a81424e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/setjmp.S @@ -0,0 +1,102 @@ +/* setjmp for SH3. + Copyright (C) 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#define _SETJMP_H +#define _ASM +#include + + .text + +/* This just does a tail-call to `__sigsetjmp (ARG, 0)'. + We cannot do it in C because it must be a tail-call, so frame-unwinding + in setjmp doesn't clobber the state restored by longjmp. */ + + .align 4 + .type _setjmp,@function + .globl _setjmp; +_setjmp: + bra __sigsetjmp_intern + mov #0, r1 + .size _setjmp,.-_setjmp; + +/* This just does a tail-call to `__sigsetjmp (ARG, 1)'. + We cannot do it in C because it must be a tail-call, so frame-unwinding + in setjmp doesn't clobber the state restored by longjmp. */ + + .align 4 + .type setjmp,@function + .globl setjmp; +setjmp: + bra __sigsetjmp_intern + mov #1, r1 + .size setjmp,.-setjmp; + + .align 4 + .type __sigsetjmp,@function + .globl __sigsetjmp; +__sigsetjmp: + mov r0, r1 + nop /* align this guy */ +__sigsetjmp_intern: + /* Save registers */ +#if defined __UCLIBC_HAS_FLOATS__ && ! defined __UCLIBC_HAS_SOFT_FLOAT__ + add #(JB_SIZE), r4 + fmov.s fr15, @-r4 + fmov.s fr14, @-r4 + fmov.s fr13, @-r4 + fmov.s fr12, @-r4 + sts.l fpscr, @-r4 +#else + add #(JB_SIZE-(5*4)), r4 /* this code doesn't do FP yet */ +#endif + stc.l gbr, @-r4 + sts.l pr, @-r4 + mov.l r15, @-r4 + mov.l r14, @-r4 + mov.l r13, @-r4 + mov.l r12, @-r4 + mov.l r11, @-r4 + mov.l r10, @-r4 + mov.l r9, @-r4 + mov.l r8, @-r4 + +#ifdef __HAVE_SHARED__ + mov.l .LG, r2 + mova .LG, r0 + add r0, r2 + /* Make a tail call to __sigjmp_save; it takes the same args. */ + mov.l .L1, r0 + mov.l @(r0,r2),r0 + jmp @r0 + mov r1, r0 + .align 2 +.LG: .long _GLOBAL_OFFSET_TABLE_ +.L1: .long __sigjmp_save@GOT +#else + /* Make a tail call to __sigjmp_save; it takes the same args. */ + mov.l .L1, r0 + braf r0 + mov r1, r0 +.jmp_loc: + .align 2 +.L1: .long __sigjmp_save - .jmp_loc +#endif + + .size __sigsetjmp,.-__sigsetjmp; diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/sys/io.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/sys/io.h new file mode 100644 index 00000000..f833c4e8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/sys/io.h @@ -0,0 +1,49 @@ +/* Copyright (C) 1996, 1998, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_IO_H + +#define _SYS_IO_H 1 +#include + +__BEGIN_DECLS + +/* If TURN_ON is TRUE, request for permission to do direct i/o on the + port numbers in the range [FROM,FROM+NUM-1]. Otherwise, turn I/O + permission off for that range. This call requires root privileges. */ +extern int ioperm (unsigned long int __from, unsigned long int __num, + int __turn_on) __THROW; +libc_hidden_proto(ioperm) + +/* Set the I/O privilege level to LEVEL. If LEVEL is nonzero, + permission to access any I/O port is granted. This call requires + root privileges. */ +extern int iopl (int __level) __THROW; + +/* The functions that actually perform reads and writes. */ +extern unsigned char inb (unsigned long int port) __THROW; +extern unsigned short int inw (unsigned long int port) __THROW; +extern unsigned long int inl (unsigned long int port) __THROW; + +extern void outb (unsigned char value, unsigned long int port) __THROW; +extern void outw (unsigned short value, unsigned long int port) __THROW; +extern void outl (unsigned long value, unsigned long int port) __THROW; + +__END_DECLS + +#endif /* _SYS_IO_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/sys/procfs.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/sys/procfs.h new file mode 100644 index 00000000..aad21e5f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/sys/procfs.h @@ -0,0 +1,126 @@ +/* Copyright (C) 1996, 1997, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_PROCFS_H +#define _SYS_PROCFS_H 1 + +/* This is somehow modelled after the file of the same name on SysVr4 + systems. It provides a definition of the core file format for ELF + used on Linux. */ + +#include +#include +#include +#include +#include +#include + +__BEGIN_DECLS + +/* + * ELF register definitions... + */ +typedef unsigned long elf_greg_t; + +#define ELF_NGREG (sizeof (struct pt_regs) / sizeof(elf_greg_t)) +typedef elf_greg_t elf_gregset_t[ELF_NGREG]; + +typedef struct user_fpu_struct elf_fpregset_t; + +struct elf_siginfo + { + int si_signo; /* Signal number. */ + int si_code; /* Extra code. */ + int si_errno; /* Errno. */ + }; + + +/* Definitions to generate Intel SVR4-like core files. These mostly + have the same names as the SVR4 types with "elf_" tacked on the + front to prevent clashes with linux definitions, and the typedef + forms have been avoided. This is mostly like the SVR4 structure, + but more Linuxy, with things that Linux does not support and which + gdb doesn't really use excluded. Fields present but not used are + marked with "XXX". */ +struct elf_prstatus + { +#if 0 + long int pr_flags; /* XXX Process flags. */ + short int pr_why; /* XXX Reason for process halt. */ + short int pr_what; /* XXX More detailed reason. */ +#endif + struct elf_siginfo pr_info; /* Info associated with signal. */ + short int pr_cursig; /* Current signal. */ + unsigned long int pr_sigpend; /* Set of pending signals. */ + unsigned long int pr_sighold; /* Set of held signals. */ +#if 0 + struct sigaltstack pr_altstack; /* Alternate stack info. */ + struct sigaction pr_action; /* Signal action for current sig. */ +#endif + __pid_t pr_pid; + __pid_t pr_ppid; + __pid_t pr_pgrp; + __pid_t pr_sid; + struct timeval pr_utime; /* User time. */ + struct timeval pr_stime; /* System time. */ + struct timeval pr_cutime; /* Cumulative user time. */ + struct timeval pr_cstime; /* Cumulative system time. */ +#if 0 + long int pr_instr; /* Current instruction. */ +#endif + elf_gregset_t pr_reg; /* GP registers. */ + int pr_fpvalid; /* True if math copro being used. */ + }; + + +#define ELF_PRARGSZ (80) /* Number of chars for args */ + +struct elf_prpsinfo + { + char pr_state; /* Numeric process state. */ + char pr_sname; /* Char for pr_state. */ + char pr_zomb; /* Zombie. */ + char pr_nice; /* Nice val. */ + unsigned long int pr_flag; /* Flags. */ + long pr_uid; + long pr_gid; + int pr_pid, pr_ppid, pr_pgrp, pr_sid; + /* Lots missing */ + char pr_fname[16]; /* Filename of executable. */ + char pr_psargs[ELF_PRARGSZ]; /* Initial part of arg list. */ + }; + + +/* Addresses. */ +typedef void *psaddr_t; + +/* Register sets. Linux has different names. */ +typedef elf_gregset_t prgregset_t; +typedef elf_fpregset_t prfpregset_t; + +/* We don't have any differences between processes and threads, + therefore habe only ine PID type. */ +typedef __pid_t lwpid_t; + + +typedef struct elf_prstatus prstatus_t; +typedef struct elf_prpsinfo prpsinfo_t; + +__END_DECLS + +#endif /* sys/procfs.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/sys/ucontext.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/sys/ucontext.h new file mode 100644 index 00000000..4ed2484b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/sys/ucontext.h @@ -0,0 +1,121 @@ +/* Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Where is System V/SH ABI? */ + +#ifndef _SYS_UCONTEXT_H +#define _SYS_UCONTEXT_H 1 + +#include +#include + +/* We need the signal context definitions even if they are not used + included in . */ +#include + + +typedef int greg_t; + +/* Number of general registers. */ +#define NFPREG 16 + +/* Container for all general registers. */ +typedef greg_t gregset_t[NFPREG]; + +#ifdef __USE_GNU +/* Number of each register is the `gregset_t' array. */ +enum +{ + R0 = 0, +#define R0 R0 + R1 = 1, +#define R1 R1 + R2 = 2, +#define R2 R2 + R3 = 3, +#define R3 R3 + R4 = 4, +#define R4 R4 + R5 = 5, +#define R5 R5 + R6 = 6, +#define R6 R6 + R7 = 7, +#define R7 R7 + R8 = 8, +#define R8 R8 + R9 = 9, +#define R9 R9 + R10 = 10, +#define R10 R10 + R11 = 11, +#define R11 R11 + R12 = 12, +#define R12 R12 + R13 = 13, +#define R13 R13 + R14 = 14, +#define R14 R14 + R15 = 15, +#define R15 R15 +}; +#endif + +typedef int freg_t; + +/* Number of FPU registers. */ +#define NFPREG 16 + +/* Structure to describe FPU registers. */ +typedef freg_t fpregset_t[NFPREG]; + +/* Context to describe whole processor state. */ +typedef struct + { + unsigned int oldmask; + + /* CPU registers */ + gregset_t gregs; + unsigned int pc; + unsigned int pr; + unsigned int sr; + unsigned int gbr; + unsigned int mach; + unsigned int macl; + +#ifdef __SH4__ + /* FPU registers */ + fpregset_t fpregs; + fpregset_t xfpregs; + unsigned int fpscr; + unsigned int fpul; + unsigned int ownedfp; +#endif + } mcontext_t; + +/* Userlevel context. */ +typedef struct ucontext + { + unsigned long int uc_flags; + struct ucontext *uc_link; + stack_t uc_stack; + mcontext_t uc_mcontext; + __sigset_t uc_sigmask; + } ucontext_t; + +#endif /* sys/ucontext.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/sys/user.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/sys/user.h new file mode 100644 index 00000000..91b00916 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/sys/user.h @@ -0,0 +1,89 @@ +/* Copyright (C) 1998, 1999, 2000, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_USER_H +#define _SYS_USER_H 1 + +#include +#include + +/* asm/ptrace.h polutes the namespace. */ +#undef PTRACE_GETREGS +#undef PTRACE_SETREGS +#undef PTRACE_GETFPREGS +#undef PTRACE_SETFPREGS +#undef PTRACE_GETFDPIC +#undef PTRACE_GETFDPIC_EXEC +#undef PTRACE_GETFDPIC_INTERP +#undef PTRACE_GETDSPREGS +#undef PTRACE_SETDSPREGS + +/* + * Core file format: The core file is written in such a way that gdb + * can understand it and provide useful information to the user (under + * linux we use the `trad-core' bfd). The file contents are as follows: + * + * upage: 1 page consisting of a user struct that tells gdb + * what is present in the file. Directly after this is a + * copy of the task_struct, which is currently not used by gdb, + * but it may come in handy at some point. All of the registers + * are stored as part of the upage. The upage should always be + * only one page long. + * data: The data segment follows next. We use current->end_text to + * current->brk to pick up all of the user variables, plus any memory + * that may have been sbrk'ed. No attempt is made to determine if a + * page is demand-zero or if a page is totally unused, we just cover + * the entire range. All of the addresses are rounded in such a way + * that an integral number of pages is written. + * stack: We need the stack information in order to get a meaningful + * backtrace. We need to write the data from usp to + * current->start_stack, so we round each of these in order to be able + * to write an integer number of pages. + */ + +struct user_fpu_struct { + unsigned long fp_regs[16]; + unsigned long xfp_regs[16]; + unsigned long fpscr; + unsigned long fpul; +}; + +struct user { + struct pt_regs regs; /* entire machine state */ + struct user_fpu_struct fpu; /* Math Co-processor registers */ + int u_fpvalid; /* True if math co-processor being used */ + size_t u_tsize; /* text size (pages) */ + size_t u_dsize; /* data size (pages) */ + size_t u_ssize; /* stack size (pages) */ + unsigned long start_code; /* text starting address */ + unsigned long start_data; /* data starting address */ + unsigned long start_stack; /* stack starting address */ + long int signal; /* signal causing core dump */ + struct regs * u_ar0; /* help gdb find registers */ + struct user_fpu_struct* u_fpstate; /* Math Co-processor pointer */ + unsigned long magic; /* identifies a core file */ + char u_comm[32]; /* user command name */ +}; + +#define NBPG getpagesize() +#define UPAGES 1 +#define HOST_TEXT_START_ADDR (u.start_code) +#define HOST_DATA_START_ADDR (u.start_data) +#define HOST_STACK_END_ADDR (u.start_stack + u.u_ssize * NBPG) + +#endif /* sys/user.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/syscall_error.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/syscall_error.S new file mode 100644 index 00000000..73795030 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/syscall_error.S @@ -0,0 +1,37 @@ + .align 4 +__syscall_error: + /* Call errno_location, store '-r4' in errno and return -1 */ + mov.l r12, @-r15 + sts.l pr, @-r15 +#ifdef SHARED + mova .LG, r0 + mov.l .LG, r12 + add r0, r12 + mov.l 1f, r0 + mov.l @(r0,r12),r0 + jsr @r0 + neg r4, r12 +#else + mov.l 1f, r0 + bsrf r0 + neg r4, r12 +.jmp_loc: +#endif + mov.l r12, @r0 + lds.l @r15+, pr + mov.l @r15+,r12 + + /* And just kick back a -1. */ + rts + mov #-1, r0 + + .align 4 + +#ifdef SHARED +1: .long __errno_location@GOT +.LG: .long _GLOBAL_OFFSET_TABLE_ +#else +1: .long __errno_location - .jmp_loc +#endif + + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/sysdep.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/sysdep.h new file mode 100644 index 00000000..8b3c6822 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/sysdep.h @@ -0,0 +1,297 @@ +/* Assembler macros for SH. + Copyright (C) 1999, 2000, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#include +#include + +#ifdef __ASSEMBLER__ + +/* Syntactic details of assembler. */ + +#define LOCAL(X) .L_##X +#define ALIGNARG(log2) log2 +/* For ELF we need the `.type' directive to make shared libs work right. */ +#define ASM_TYPE_DIRECTIVE(name,typearg) .type name,@##typearg; +#define ASM_SIZE_DIRECTIVE(name) .size name,.-name + +#ifdef SHARED +#define PLTJMP(_x) _x##@PLT +#else +#define PLTJMP(_x) _x +#endif + +/* Define an entry point visible from C. */ +#define ENTRY(name) \ + ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(name); \ + ASM_TYPE_DIRECTIVE (C_SYMBOL_NAME(name),function) \ + .align ALIGNARG(5); \ + C_LABEL(name) \ + cfi_startproc; \ + CALL_MCOUNT + +#undef END +#define END(name) \ + cfi_endproc; \ + ASM_SIZE_DIRECTIVE(C_SYMBOL_NAME(name)) + +/* If compiled for profiling, call `mcount' at the start of each function. */ +#ifdef PROF +#define CALL_MCOUNT \ + mov.l 1f,r1; \ + sts.l pr,@-r15; \ + cfi_adjust_cfa_offset (4); \ + cfi_rel_offset (pr, 0); \ + mova 2f,r0; \ + jmp @r1; \ + lds r0,pr; \ + .align 2; \ +1: .long mcount; \ +2: lds.l @r15+,pr; \ + cfi_adjust_cfa_offset (-4); \ + cfi_restore (pr) + +#else +#define CALL_MCOUNT /* Do nothing. */ +#endif + +#ifdef __UCLIBC_UNDERSCORES__ +/* Since C identifiers are not normally prefixed with an underscore + on this system, the asm identifier `syscall_error' intrudes on the + C name space. Make sure we use an innocuous name. */ +#define syscall_error __syscall_error +#define mcount _mcount +#endif + +/* For Linux we can use the system call table in the header file + /usr/include/asm/unistd.h + of the kernel. But these symbols do not follow the SYS_* syntax + so we have to redefine the `SYS_ify' macro here. */ +#undef SYS_ify +#define SYS_ify(syscall_name) (__NR_##syscall_name) + +#define ret rts ; nop +/* The sh move insn is s, d. */ +#define MOVE(x,y) mov x , y + +/* Linux uses a negative return value to indicate syscall errors, + unlike most Unices, which use the condition codes' carry flag. + + Since version 2.1 the return value of a system call might be + negative even if the call succeeded. E.g., the `lseek' system call + might return a large offset. Therefore we must not anymore test + for < 0, but test for a real error by making sure the value in R0 + is a real error number. Linus said he will make sure the no syscall + returns a value in -1 .. -4095 as a valid result so we can savely + test with -4095. */ + +#define _IMM1 #-1 +#define _IMM12 #-12 +#undef PSEUDO +#define PSEUDO(name, syscall_name, args) \ + .text; \ + ENTRY (name); \ + DO_CALL (syscall_name, args); \ + mov r0,r1; \ + mov _IMM12,r2; \ + shad r2,r1; \ + not r1,r1; \ + tst r1,r1; \ + bf .Lpseudo_end; \ + SYSCALL_ERROR_HANDLER; \ + .Lpseudo_end: + +#undef PSEUDO_END +#define PSEUDO_END(name) \ + END (name) + +#undef PSEUDO_NOERRNO +#define PSEUDO_NOERRNO(name, syscall_name, args) \ + .text; \ + ENTRY (name); \ + DO_CALL (syscall_name, args) + +#undef PSEUDO_END_NOERRNO +#define PSEUDO_END_NOERRNO(name) \ + END (name) + +#define ret_NOERRNO ret + +#define PSEUDO_ERRVAL(name, syscall_name, args) \ + .text; \ + ENTRY (name); \ + DO_CALL (syscall_name, args); + +#undef PSEUDO_END_ERRVAL +#define PSEUDO_END_ERRVAL(name) \ + END (name) + +#define ret_ERRVAL ret + +#ifndef __PIC__ +# define SYSCALL_ERROR_HANDLER \ + mov.l 0f,r1; \ + jmp @r1; \ + mov r0,r4; \ + .align 2; \ + 0: .long __syscall_error + +#include +#else +# ifdef RTLD_PRIVATE_ERRNO + +# define SYSCALL_ERROR_HANDLER \ + neg r0,r1; \ + mov.l 0f,r12; \ + mova 0f,r0; \ + add r0,r12; \ + mov.l 1f,r0; \ + mov.l r1,@(r0,r12) + bra .Lpseudo_end; \ + mov _IMM1,r0; \ + .align 2; \ + 0: .long _GLOBAL_OFFSET_TABLE_; \ + 1: .long rtld_errno@GOTOFF + +# elif defined _LIBC_REENTRANT + +# if defined USE___THREAD + +# ifndef NOT_IN_libc +# define SYSCALL_ERROR_ERRNO __libc_errno +# else +# define SYSCALL_ERROR_ERRNO errno +# endif +# define SYSCALL_ERROR_HANDLER \ + neg r0,r1; \ + mov r12,r2; \ + mov.l 0f,r12; \ + mova 0f,r0; \ + add r0,r12; \ + mov.l 1f,r0; \ + stc gbr, r4; \ + mov.l @(r0,r12),r0; \ + bra .Lskip; \ + add r4,r0; \ + .align 2; \ + 1: .long SYSCALL_ERROR_ERRNO@GOTTPOFF; \ + .Lskip: \ + mov r2,r12; \ + mov.l r1,@r0; \ + bra .Lpseudo_end; \ + mov _IMM1,r0; \ + .align 2; \ + 0: .long _GLOBAL_OFFSET_TABLE_ +# else + +# define SYSCALL_ERROR_HANDLER \ + neg r0,r1; \ + mov.l r14,@-r15; \ + mov.l r12,@-r15; \ + mov.l r1,@-r15; \ + mov.l 0f,r12; \ + mova 0f,r0; \ + add r0,r12; \ + sts.l pr,@-r15; \ + mov r15,r14; \ + mov.l 1f,r1; \ + bsrf r1; \ + nop; \ + 2: mov r14,r15; \ + lds.l @r15+,pr; \ + mov.l @r15+,r1; \ + mov.l r1,@r0; \ + mov.l @r15+,r12; \ + mov.l @r15+,r14; \ + bra .Lpseudo_end; \ + mov _IMM1,r0; \ + .align 2; \ + 0: .long _GLOBAL_OFFSET_TABLE_; \ + 1: .long PLTJMP(C_SYMBOL_NAME(__errno_location))-(2b-.) +/* A quick note: it is assumed that the call to `__errno_location' does + not modify the stack! */ +# endif +# else + +/* Store (-r0) into errno through the GOT. */ +# define SYSCALL_ERROR_HANDLER \ + neg r0,r1; \ + mov r12,r2; \ + mov.l 0f,r12; \ + mova 0f,r0; \ + add r0,r12; \ + mov.l 1f,r0; \ + mov.l @(r0,r12),r0; \ + mov r2,r12; \ + mov.l r1,@r0; \ + bra .Lpseudo_end; \ + mov _IMM1,r0; \ + .align 2; \ + 0: .long _GLOBAL_OFFSET_TABLE_; \ + 1: .long errno@GOT +# endif /* _LIBC_REENTRANT */ +#endif /* __PIC__ */ + +# ifdef __SH4__ +# define SYSCALL_INST_PAD \ + or r0,r0; or r0,r0; or r0,r0; or r0,r0; or r0,r0 +# else +# define SYSCALL_INST_PAD +# endif + +#define SYSCALL_INST0 trapa #0x10 +#define SYSCALL_INST1 trapa #0x11 +#define SYSCALL_INST2 trapa #0x12 +#define SYSCALL_INST3 trapa #0x13 +#define SYSCALL_INST4 trapa #0x14 +#define SYSCALL_INST5 mov.l @(0,r15),r0; trapa #0x15 +#define SYSCALL_INST6 mov.l @(0,r15),r0; mov.l @(4,r15),r1; trapa #0x16 + +#undef DO_CALL +#define DO_CALL(syscall_name, args) \ + mov.l 1f,r3; \ + SYSCALL_INST##args; \ + SYSCALL_INST_PAD; \ + bra 2f; \ + nop; \ + .align 2; \ + 1: .long SYS_ify (syscall_name); \ + 2: +#endif /* __ASSEMBLER__ */ + +/* Pointer mangling support. */ +#if defined NOT_IN_libc && defined IS_IN_rtld +/* We cannot use the thread descriptor because in ld.so we use setjmp + earlier than the descriptor is initialized. Using a global variable + is too complicated here since we have no PC-relative addressing mode. */ +#else +# ifdef __ASSEMBLER__ +# define PTR_MANGLE(reg, tmp) \ + stc gbr,tmp; mov.l @(POINTER_GUARD,tmp),tmp; xor tmp,reg +# define PTR_MANGLE2(reg, tmp) xor tmp,reg +# define PTR_DEMANGLE(reg, tmp) PTR_MANGLE (reg, tmp) +# define PTR_DEMANGLE2(reg, tmp) PTR_MANGLE2 (reg, tmp) +# else +# define PTR_MANGLE(var) \ + (var) = (void *) ((uintptr_t) (var) ^ THREAD_GET_POINTER_GUARD ()) +# define PTR_DEMANGLE(var) PTR_MANGLE (var) +# endif +#endif + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/vfork.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/vfork.S new file mode 100644 index 00000000..d311bff1 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh/vfork.S @@ -0,0 +1,114 @@ +/* Copyright (C) 1999, 2000 Free Software Foundation, Inc. + Copyright (C) 2001 Hewlett-Packard Australia + + This program is free software; you can redistribute it and/or modify it under + the terms of the GNU Library General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at your option) any + later version. + + This program is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more + details. + + You should have received a copy of the GNU Library General Public License + along with this program; if not, write to the Free Software Foundation, Inc., + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Derived in part from the Linux-8086 C library, the GNU C Library, and several + other sundry sources. Files within this library are copyright by their + respective copyright holders. +*/ + +#include +#include +#define _ERRNO_H +#include +#include + +/* Clone the calling process, but without copying the whole address space. + The calling process is suspended until the new process exits or is + replaced by a call to `execve'. Return -1 for errors, 0 to the new process, + and the process ID of the new process to the old process. */ + +.text +.globl __vfork +.hidden __vfork +.type __vfork,@function +.align 4 + +__vfork: + mov.w .L2, r3 + trapa #__SH_SYSCALL_TRAP_BASE + mov r0, r1 +#ifdef __sh2__ +/* 12 arithmetic shifts for the crappy sh2, because shad doesn't exist! */ + shar r1 + shar r1 + shar r1 + shar r1 + shar r1 + shar r1 + shar r1 + shar r1 + shar r1 + shar r1 + shar r1 + shar r1 +#else + mov #-12, r2 + shad r2, r1 +#endif + + not r1, r1 /* r1=0 means r0 = -1 to -4095 */ + tst r1, r1 /* i.e. error in linux */ + bf 2f + mov.w .L1, r1 + cmp/eq r1, r0 + bf/s __syscall_error + mov r0, r4 + + /* If we don't have vfork, use fork. */ + mov.w .L3, r3 + trapa #__SH_SYSCALL_TRAP_BASE + mov r0, r1 +#ifdef __sh2__ +/* 12 arithmetic shifts for the crappy sh2, because shad doesn't exist! */ + shar r1 + shar r1 + shar r1 + shar r1 + shar r1 + shar r1 + shar r1 + shar r1 + shar r1 + shar r1 + shar r1 + shar r1 +#else + mov #-12, r2 + shad r2, r1 +#endif + + not r1, r1 /* r1=0 means r0 = -1 to -4095 */ + tst r1, r1 /* i.e. error in linux */ + bt/s __syscall_error + mov r0, r4 +2: + rts + nop + + .align 2 +.L1: + .word -ENOSYS +.L2: + .word __NR_vfork +.L3: + .word __NR_fork + +.size __vfork, .-__vfork +weak_alias(__vfork,vfork) +libc_hidden_weak(vfork) + +#include "syscall_error.S" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/Makefile new file mode 100644 index 00000000..ecbf1422 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/Makefile @@ -0,0 +1,15 @@ +# Makefile for uClibc +# +# Copyright (C) 2001 SuperH (UK) Ltd. +# Copyright (C) 2003 Paul Mundt +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + +top_srcdir=../../../../ +top_builddir=../../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.arch +include $(top_srcdir)Makerules +TOPDIR=../../../../ +include $(TOPDIR)Rules.mak diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/Makefile.arch b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/Makefile.arch new file mode 100644 index 00000000..4e12532b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/Makefile.arch @@ -0,0 +1,10 @@ +# Makefile for uClibc +# +# Copyright (C) 2008 Paul Mundt +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +CSRC := __init_brk.c brk.c sbrk.c syscall.c + +SSRC := setjmp.S __longjmp.S diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/__init_brk.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/__init_brk.c new file mode 100644 index 00000000..8a41eb3c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/__init_brk.c @@ -0,0 +1,26 @@ +/* From libc-5.3.12 */ + +#include +#include +#include + +void * __curbrk attribute_hidden = 0; + +#define __NR__brk __NR_brk +attribute_hidden _syscall1(void *, _brk, void *, ptr) + +extern int __init_brk (void) attribute_hidden; +int +__init_brk (void) +{ + if (__curbrk == 0) + { + __curbrk = _brk(0); + if (__curbrk == 0) + { + __set_errno(ENOMEM); + return -1; + } + } + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/__longjmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/__longjmp.S new file mode 100644 index 00000000..ca7925f7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/__longjmp.S @@ -0,0 +1,141 @@ +/* __longjmp for SH-5. + Copyright (C) 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + + +#define _SETJMP_H +#define _ASM +#include + + +#define INTEGER(reg,offset) ld.q r2, offset*8, reg +#define DOUBLE(reg,offset) fld.d r2, offset*8, reg + + + .file "__longjmp.S" + + .section .text64,"xa" + .align 2 + + .global __longjmp + .type __longjmp,@function + +__longjmp: + /* + * extern void __longjmp(jmp_buf env, int val); + * + * r2 == env + * r3 == val + * r4 == temporary + */ + + /* callee-save registers R10-R16 */ + INTEGER(r10, __SETJMP_INT(0)) + INTEGER(r11, __SETJMP_INT(1)) + INTEGER(r12, __SETJMP_INT(2)) + INTEGER(r13, __SETJMP_INT(3)) + INTEGER(r14, __SETJMP_INT(4)) + INTEGER(r15, __SETJMP_INT(5)) + INTEGER(r16, __SETJMP_INT(6)) + + /* callee-save registers R28-R35 */ + INTEGER(r28, __SETJMP_INT(7)) + INTEGER(r29, __SETJMP_INT(8)) + INTEGER(r30, __SETJMP_INT(9)) + INTEGER(r31, __SETJMP_INT(10)) + INTEGER(r32, __SETJMP_INT(11)) + INTEGER(r33, __SETJMP_INT(12)) + INTEGER(r34, __SETJMP_INT(13)) + INTEGER(r35, __SETJMP_INT(14)) + + /* callee-save registers R44-R59 */ + INTEGER(r44, __SETJMP_INT(15)) + INTEGER(r45, __SETJMP_INT(16)) + INTEGER(r46, __SETJMP_INT(17)) + INTEGER(r47, __SETJMP_INT(18)) + INTEGER(r48, __SETJMP_INT(19)) + INTEGER(r49, __SETJMP_INT(20)) + INTEGER(r50, __SETJMP_INT(21)) + INTEGER(r51, __SETJMP_INT(22)) + INTEGER(r52, __SETJMP_INT(23)) + INTEGER(r53, __SETJMP_INT(24)) + INTEGER(r54, __SETJMP_INT(25)) + INTEGER(r55, __SETJMP_INT(26)) + INTEGER(r56, __SETJMP_INT(27)) + INTEGER(r57, __SETJMP_INT(28)) + INTEGER(r58, __SETJMP_INT(29)) + INTEGER(r59, __SETJMP_INT(30)) + + #if __SETJMP_NUM_INT != 31 + #error __SETJMP_NUM_INT does agree with expected value + #endif + +#if __SETJMP_NUM_DBL > 0 + /* callee-save registers FR12-FR15 */ + DOUBLE(d12, __SETJMP_DBL(0)) + DOUBLE(d14, __SETJMP_DBL(1)) + + /* callee-save registers FR36-FR63 */ + DOUBLE(d36, __SETJMP_DBL(2)) + DOUBLE(d38, __SETJMP_DBL(3)) + DOUBLE(d40, __SETJMP_DBL(4)) + DOUBLE(d42, __SETJMP_DBL(5)) + DOUBLE(d44, __SETJMP_DBL(6)) + DOUBLE(d46, __SETJMP_DBL(7)) + DOUBLE(d48, __SETJMP_DBL(8)) + DOUBLE(d50, __SETJMP_DBL(9)) + DOUBLE(d52, __SETJMP_DBL(10)) + DOUBLE(d54, __SETJMP_DBL(11)) + DOUBLE(d56, __SETJMP_DBL(12)) + DOUBLE(d58, __SETJMP_DBL(13)) + DOUBLE(d60, __SETJMP_DBL(14)) + DOUBLE(d62, __SETJMP_DBL(15)) + + #if __SETJMP_NUM_DBL != 16 + #error __SETJMP_NUM_DBL does agree with expected value + #endif + +#endif /* __SETJMP_NUM_DBL > 0 */ + + /* callee-save registers TR5-TR7 */ + INTEGER(r4, __SETJMP_TRG(0)) + ptabs r4, tr5 + INTEGER(r4, __SETJMP_TRG(1)) + ptabs r4, tr6 + INTEGER(r4, __SETJMP_TRG(2)) + ptabs r4, tr7 + + #if __SETJMP_NUM_TRG != 3 + #error __SETJMP_NUM_TRG does agree with expected value + #endif + + /* restore Linkage Register (LR) for __longjmp return */ + INTEGER(r18, __SETJMP_LR) + ptabs/l r18, tr0 + + /* + * must ensure __longjmp() never returns 0. + * if 'val' == 0, then return 1. + */ + cmpeq r3, r63, r2 /* r2 = (r3==0) ? 1 : 0; */ + add.l r3, r2, r2 /* return value */ + + /* return to caller */ + blink tr0, r63 + +libc_hidden_def(__longjmp) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/bits/endian.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/bits/endian.h new file mode 100644 index 00000000..ae7e3bb2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/bits/endian.h @@ -0,0 +1,20 @@ +/* + * libc/sysdeps/linux/sh64/bits/endian.h + * + * Copyright (C) 2003 Paul Mundt + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + */ + +#ifndef _ENDIAN_H +# error "Never use directly; include instead." +#endif + +#ifdef __LITTLE_ENDIAN__ +# define __BYTE_ORDER __LITTLE_ENDIAN +#else +# define __BYTE_ORDER __BIG_ENDIAN +#endif + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/bits/fcntl.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/bits/fcntl.h new file mode 100644 index 00000000..156df975 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/bits/fcntl.h @@ -0,0 +1,217 @@ +/* O_*, F_*, FD_* bit values for Linux. + Copyright (C) 1995, 1996, 1997, 1998, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FCNTL_H +# error "Never use directly; include instead." +#endif + + +#include + +/* open/fcntl - O_SYNC is only implemented on blocks devices and on files + located on an ext2 file system */ +#define O_ACCMODE 0003 +#define O_RDONLY 00 +#define O_WRONLY 01 +#define O_RDWR 02 +#define O_CREAT 0100 /* not fcntl */ +#define O_EXCL 0200 /* not fcntl */ +#define O_NOCTTY 0400 /* not fcntl */ +#define O_TRUNC 01000 /* not fcntl */ +#define O_APPEND 02000 +#define O_NONBLOCK 04000 +#define O_NDELAY O_NONBLOCK +#define O_SYNC 010000 +#define O_FSYNC O_SYNC +#define O_ASYNC 020000 + +#ifdef __USE_GNU +# define O_DIRECT 040000 /* Direct disk access. */ +# define O_DIRECTORY 0200000 /* Must be a directory. */ +# define O_NOFOLLOW 0400000 /* Do not follow links. */ +# define O_NOATIME 01000000 /* Do not set atime. */ +# define O_CLOEXEC 02000000 /* set close_on_exec */ +#endif + +/* For now Linux has synchronisity options for data and read operations. + We define the symbols here but let them do the same as O_SYNC since + this is a superset. */ +#if defined __USE_POSIX199309 || defined __USE_UNIX98 +# define O_DSYNC O_SYNC /* Synchronize data. */ +# define O_RSYNC O_SYNC /* Synchronize read operations. */ +#endif + +#ifdef __USE_LARGEFILE64 +# define O_LARGEFILE 0100000 +#endif + +/* Values for the second argument to `fcntl'. */ +#define F_DUPFD 0 /* Duplicate file descriptor. */ +#define F_GETFD 1 /* Get file descriptor flags. */ +#define F_SETFD 2 /* Set file descriptor flags. */ +#define F_GETFL 3 /* Get file status flags. */ +#define F_SETFL 4 /* Set file status flags. */ +#ifndef __USE_FILE_OFFSET64 +# define F_GETLK 5 /* Get record locking info. */ +# define F_SETLK 6 /* Set record locking info (non-blocking). */ +# define F_SETLKW 7 /* Set record locking info (blocking). */ +#else +# define F_GETLK F_GETLK64 /* Get record locking info. */ +# define F_SETLK F_SETLK64 /* Set record locking info (non-blocking).*/ +# define F_SETLKW F_SETLKW64 /* Set record locking info (blocking). */ +#endif +#define F_GETLK64 12 /* Get record locking info. */ +#define F_SETLK64 13 /* Set record locking info (non-blocking). */ +#define F_SETLKW64 14 /* Set record locking info (blocking). */ + +#if defined __USE_BSD || defined __USE_XOPEN2K +# define F_SETOWN 8 /* Get owner of socket (receiver of SIGIO). */ +# define F_GETOWN 9 /* Set owner of socket (receiver of SIGIO). */ +#endif + +#ifdef __USE_GNU +# define F_SETSIG 10 /* Set number of signal to be sent. */ +# define F_GETSIG 11 /* Get number of signal to be sent. */ +#endif + +#ifdef __USE_GNU +# define F_SETLEASE 1024 /* Set a lease. */ +# define F_GETLEASE 1025 /* Enquire what lease is active. */ +# define F_NOTIFY 1026 /* Request notfications on a directory. */ +# define F_DUPFD_CLOEXEC 1030 /* Duplicate file descriptor with + close-on-exit set on new fd. */ +#endif + +/* For F_[GET|SET]FL. */ +#define FD_CLOEXEC 1 /* actually anything with low bit set goes */ + +/* For posix fcntl() and `l_type' field of a `struct flock' for lockf(). */ +#define F_RDLCK 0 /* Read lock. */ +#define F_WRLCK 1 /* Write lock. */ +#define F_UNLCK 2 /* Remove lock. */ + +/* For old implementation of bsd flock(). */ +#define F_EXLCK 4 /* or 3 */ +#define F_SHLCK 8 /* or 4 */ + +#ifdef __USE_BSD +/* Operations for bsd flock(), also used by the kernel implementation. */ +# define LOCK_SH 1 /* shared lock */ +# define LOCK_EX 2 /* exclusive lock */ +# define LOCK_NB 4 /* or'd with one of the above to prevent + blocking */ +# define LOCK_UN 8 /* remove lock */ +#endif + +struct flock + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ +#ifndef __USE_FILE_OFFSET64 + __off_t l_start; /* Offset where the lock begins. */ + __off_t l_len; /* Size of the locked area; zero means until EOF. */ +#else + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ +#endif + __pid_t l_pid; /* Process holding the lock. */ + }; + +#ifdef __USE_LARGEFILE64 +struct flock64 + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ + __pid_t l_pid; /* Process holding the lock. */ + }; +#endif + +/* Define some more compatibility macros to be backward compatible with + BSD systems which did not managed to hide these kernel macros. */ +#ifdef __USE_BSD +# define FAPPEND O_APPEND +# define FFSYNC O_FSYNC +# define FASYNC O_ASYNC +# define FNONBLOCK O_NONBLOCK +# define FNDELAY O_NDELAY +#endif /* Use BSD. */ + +/* Advise to `posix_fadvise'. */ +#ifdef __USE_XOPEN2K +# define POSIX_FADV_NORMAL 0 /* No further special treatment. */ +# define POSIX_FADV_RANDOM 1 /* Expect random page references. */ +# define POSIX_FADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define POSIX_FADV_WILLNEED 3 /* Will need these pages. */ +# define POSIX_FADV_DONTNEED 4 /* Don't need these pages. */ +# define POSIX_FADV_NOREUSE 5 /* Data will be accessed once. */ +#endif + + +#if defined __USE_GNU && defined __UCLIBC_LINUX_SPECIFIC__ +/* Flags for SYNC_FILE_RANGE. */ +# define SYNC_FILE_RANGE_WAIT_BEFORE 1 /* Wait upon writeout of all pages + in the range before performing the + write. */ +# define SYNC_FILE_RANGE_WRITE 2 /* Initiate writeout of all those + dirty pages in the range which are + not presently under writeback. */ +# define SYNC_FILE_RANGE_WAIT_AFTER 4 /* Wait upon writeout of all pages in + the range after performing the + write. */ + +/* Flags for SPLICE and VMSPLICE. */ +# define SPLICE_F_MOVE 1 /* Move pages instead of copying. */ +# define SPLICE_F_NONBLOCK 2 /* Don't block on the pipe splicing + (but we may still block on the fd + we splice from/to). */ +# define SPLICE_F_MORE 4 /* Expect more data. */ +# define SPLICE_F_GIFT 8 /* Pages passed in are a gift. */ +#endif + +__BEGIN_DECLS + +#if defined __USE_GNU && defined __UCLIBC_LINUX_SPECIFIC__ + +/* Provide kernel hint to read ahead. */ +extern ssize_t readahead (int __fd, __off64_t __offset, size_t __count) + __THROW; + + +/* Selective file content synch'ing. */ +extern int sync_file_range (int __fd, __off64_t __from, __off64_t __to, + unsigned int __flags); + +/* Splice address range into a pipe. */ +extern ssize_t vmsplice (int __fdout, const struct iovec *__iov, + size_t __count, unsigned int __flags); + +/* Splice two files together. */ +extern ssize_t splice (int __fdin, __off64_t *__offin, int __fdout, + __off64_t *__offout, size_t __len, + unsigned int __flags); + +/* In-kernel implementation of tee for pipe buffers. */ +extern ssize_t tee (int __fdin, int __fdout, size_t __len, + unsigned int __flags); + +#endif +__END_DECLS + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/bits/kernel_stat.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/bits/kernel_stat.h new file mode 100644 index 00000000..57c16f47 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/bits/kernel_stat.h @@ -0,0 +1,59 @@ +/* Stat structure for Linux/sh64 */ + +#ifndef _BITS_STAT_STRUCT_H +#define _BITS_STAT_STRUCT_H + +#ifndef _LIBC +#error bits/kernel_stat.h is for internal uClibc use only! +#endif + +struct kernel_stat { + unsigned short st_dev; + unsigned short __pad1; + unsigned long st_ino; + unsigned short st_mode; + unsigned short st_nlink; + unsigned short st_uid; + unsigned short st_gid; + unsigned short st_rdev; + unsigned short __pad2; + unsigned long st_size; + unsigned long st_blksize; + unsigned long st_blocks; + struct timespec st_atim; + struct timespec st_mtim; + struct timespec st_ctim; + unsigned long __unused4; + unsigned long __unused5; +}; + +struct kernel_stat64 { + unsigned short st_dev; + unsigned char __pad0[10]; + + unsigned long st_ino; + unsigned int st_mode; + unsigned int st_nlink; + + unsigned long st_uid; + unsigned long st_gid; + + unsigned short st_rdev; + unsigned char __pad3[10]; + + long long st_size; + unsigned long st_blksize; + + unsigned long st_blocks; /* Number 512-byte blocks allocated. */ + unsigned long __pad4; /* future possible st_blocks high bits */ + + struct timespec st_atim; + struct timespec st_mtim; + struct timespec st_ctim; + + unsigned long __unused1; + unsigned long __unused2; +}; + +#endif /* _BITS_STAT_STRUCT_H */ + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/bits/kernel_types.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/bits/kernel_types.h new file mode 100644 index 00000000..671cc834 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/bits/kernel_types.h @@ -0,0 +1,56 @@ +/* + * sysdeps/linux/sh64/bits/kernel_types.h + * + * Copyright (C) 2000, 2001 Paolo Alberelli + * Copyright (C) 2003 Paul Mundt + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + */ + +/* + * Note that we use the exact same include guard #define names + * as asm/posix_types.h. This will avoid gratuitous conflicts + * with the posix_types.h kernel header, and will ensure that + * our private content, and not the kernel header, will win. + * -Erik + */ +#ifndef __ASM_SH64_POSIX_TYPES_H +#define __ASM_SH64_POSIX_TYPES_H + +typedef unsigned short __kernel_dev_t; +typedef unsigned long __kernel_ino_t; +typedef unsigned short __kernel_mode_t; +typedef unsigned short __kernel_nlink_t; +typedef long __kernel_off_t; +typedef int __kernel_pid_t; +typedef unsigned short __kernel_ipc_pid_t; +typedef unsigned short __kernel_uid_t; +typedef unsigned short __kernel_gid_t; +typedef long unsigned int __kernel_size_t; +typedef int __kernel_ssize_t; +typedef int __kernel_ptrdiff_t; +typedef long __kernel_time_t; +typedef long __kernel_suseconds_t; +typedef long __kernel_clock_t; +typedef int __kernel_daddr_t; +typedef char * __kernel_caddr_t; +typedef unsigned short __kernel_uid16_t; +typedef unsigned short __kernel_gid16_t; +typedef unsigned int __kernel_uid32_t; +typedef unsigned int __kernel_gid32_t; +typedef unsigned short __kernel_old_uid_t; +typedef unsigned short __kernel_old_gid_t; +typedef __kernel_dev_t __kernel_old_dev_t; +typedef long long __kernel_loff_t; + +typedef struct { +#ifdef __USE_ALL + int val[2]; +#else + int __val[2]; +#endif +} __kernel_fsid_t; + +#endif /* __ASM_SH64_POSIX_TYPES_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/bits/setjmp.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/bits/setjmp.h new file mode 100644 index 00000000..ad1ec9d4 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/bits/setjmp.h @@ -0,0 +1,50 @@ +/* Copyright (C) 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Define the machine-dependent type `jmp_buf'. SH-5 version. */ +#ifndef _BITS_SETJMP_H +#define _BITS_SETJMP_H 1 + +#if !defined _SETJMP_H && !defined _PTHREAD_H +# error "Never include directly; use instead." +#endif + +#define __SETJMP_NUM_INT 31 /* number of integer registers to save */ +#define __SETJMP_NUM_DBL 0 /* 16 */ /* number of double registers to save */ +#define __SETJMP_NUM_TRG 3 /* number of traget registers to save */ + +#define __SETJMP_INT(x) (x) +#define __SETJMP_DBL(x) (__SETJMP_NUM_INT+(x)) +#define __SETJMP_TRG(x) (__SETJMP_NUM_INT+__SETJMP_NUM_DBL+(x)) +#define __SETJMP_LR (__SETJMP_NUM_INT+__SETJMP_NUM_DBL+__SETJMP_NUM_TRG) + + +#ifndef _ASM +typedef struct + { + /* Callee-saved registers. */ + unsigned long long __ints[__SETJMP_NUM_INT]; /* integer registers */ +#if __SETJMP_NUM_DBL > 0 + unsigned long long __dbls[__SETJMP_NUM_DBL]; /* double registers */ +#endif + unsigned long long __trgs[__SETJMP_NUM_TRG]; /* traget registers */ + unsigned long long __lr; /* linkage register */ + } __jmp_buf[1]; +#endif + +#endif /* bits/setjmp.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/bits/shm.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/bits/shm.h new file mode 100644 index 00000000..3a2e715c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/bits/shm.h @@ -0,0 +1,103 @@ +/* Copyright (C) 1995,1996,1997,2000,2002,2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_SHM_H +# error "Never include directly; use instead." +#endif + +#include + +/* Permission flag for shmget. */ +#define SHM_R 0400 /* or S_IRUGO from */ +#define SHM_W 0200 /* or S_IWUGO from */ + +/* Flags for `shmat'. */ +#define SHM_RDONLY 010000 /* attach read-only else read-write */ +#define SHM_RND 020000 /* round attach address to SHMLBA */ +#define SHM_REMAP 040000 /* take-over region on attach */ + +/* Commands for `shmctl'. */ +#define SHM_LOCK 11 /* lock segment (root only) */ +#define SHM_UNLOCK 12 /* unlock segment (root only) */ + +__BEGIN_DECLS + +/* Segment low boundary address multiple. */ +#define SHMLBA (__getpagesize() << 2) +extern int __getpagesize (void) __THROW __attribute__ ((__const__)); + + +/* Type to count number of attaches. */ +typedef unsigned long int shmatt_t; + +/* Data structure describing a set of semaphores. */ +struct shmid_ds + { + struct ipc_perm shm_perm; /* operation permission struct */ + size_t shm_segsz; /* size of segment in bytes */ + __time_t shm_atime; /* time of last shmat() */ + unsigned long int __unused1; + __time_t shm_dtime; /* time of last shmdt() */ + unsigned long int __unused2; + __time_t shm_ctime; /* time of last change by shmctl() */ + unsigned long int __unused3; + __pid_t shm_cpid; /* pid of creator */ + __pid_t shm_lpid; /* pid of last shmop */ + shmatt_t shm_nattch; /* number of current attaches */ + unsigned long int __unused4; + unsigned long int __unused5; + }; + +#ifdef __USE_MISC + +/* ipcs ctl commands */ +# define SHM_STAT 13 +# define SHM_INFO 14 + +/* shm_mode upper byte flags */ +# define SHM_DEST 01000 /* segment will be destroyed on last detach */ +# define SHM_LOCKED 02000 /* segment will not be swapped */ +# define SHM_HUGETLB 04000 /* segment is mapped via hugetlb */ +# define SHM_NORESERVE 010000 /* don't check for reservations */ + +struct shminfo + { + unsigned long int shmmax; + unsigned long int shmmin; + unsigned long int shmmni; + unsigned long int shmseg; + unsigned long int shmall; + unsigned long int __unused1; + unsigned long int __unused2; + unsigned long int __unused3; + unsigned long int __unused4; + }; + +struct shm_info + { + int used_ids; + unsigned long int shm_tot; /* total allocated shm */ + unsigned long int shm_rss; /* total resident shm */ + unsigned long int shm_swp; /* total swapped shm */ + unsigned long int swap_attempts; + unsigned long int swap_successes; + }; + +#endif /* __USE_MISC */ + +__END_DECLS diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/bits/stackinfo.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/bits/stackinfo.h new file mode 100644 index 00000000..e65338f2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/bits/stackinfo.h @@ -0,0 +1,28 @@ +/* Copyright (C) 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This file contains a bit of information about the stack allocation + of the processor. */ + +#ifndef _STACKINFO_H +#define _STACKINFO_H 1 + +/* On SH the stack grows down. */ +#define _STACK_GROWS_DOWN 1 + +#endif /* stackinfo.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/bits/syscalls.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/bits/syscalls.h new file mode 100644 index 00000000..84877d04 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/bits/syscalls.h @@ -0,0 +1,126 @@ +#ifndef _BITS_SYSCALLS_H +#define _BITS_SYSCALLS_H +#ifndef _SYSCALL_H +# error "Never use directly; include instead." +#endif + +#ifndef __ASSEMBLER__ + +#include + +#define SYS_ify(syscall_name) (__NR_##syscall_name) + +/* user-visible error numbers are in the range -1 - -125: see */ +#define __syscall_return(type, res) \ +do { \ + /* Note: when returning from kernel the return value is in r9 \ + ** This prevents conflicts between return value and arg1 \ + ** when dispatching signal handler, in other words makes \ + ** life easier in the system call epilogue (see entry.S) \ + */ \ + register unsigned long __sr2 __asm__ ("r2") = res; \ + if ((unsigned long)(res) >= (unsigned long)(-125)) { \ + errno = -(res); \ + __sr2 = -1; \ + } \ + return (type) (__sr2); \ +} while (0) + +/* XXX - _foo needs to be __foo, while __NR_bar could be _NR_bar. */ + +#define _syscall0(type,name) \ +type name(void) \ +{ \ +register unsigned long __sc0 __asm__ ("r9") = ((0x10 << 16) | __NR_##name); \ +__asm__ __volatile__ ("trapa %1" \ + : "=r" (__sc0) \ + : "r" (__sc0) ); \ +__syscall_return(type,__sc0); \ +} + +#define _syscall1(type,name,type1,arg1) \ +type name(type1 arg1) \ +{ \ +register unsigned long __sc0 __asm__ ("r9") = ((0x11 << 16) | __NR_##name); \ +register unsigned long __sc2 __asm__ ("r2") = (unsigned long) arg1; \ +__asm__ __volatile__ ("trapa %1" \ + : "=r" (__sc0) \ + : "r" (__sc0), "r" (__sc2)); \ +__syscall_return(type,__sc0); \ +} + +#define _syscall2(type,name,type1,arg1,type2,arg2) \ +type name(type1 arg1,type2 arg2) \ +{ \ +register unsigned long __sc0 __asm__ ("r9") = ((0x12 << 16) | __NR_##name); \ +register unsigned long __sc2 __asm__ ("r2") = (unsigned long) arg1; \ +register unsigned long __sc3 __asm__ ("r3") = (unsigned long) arg2; \ +__asm__ __volatile__ ("trapa %1" \ + : "=r" (__sc0) \ + : "r" (__sc0), "r" (__sc2), "r" (__sc3) ); \ +__syscall_return(type,__sc0); \ +} + +#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \ +type name(type1 arg1,type2 arg2,type3 arg3) \ +{ \ +register unsigned long __sc0 __asm__ ("r9") = ((0x13 << 16) | __NR_##name); \ +register unsigned long __sc2 __asm__ ("r2") = (unsigned long) arg1; \ +register unsigned long __sc3 __asm__ ("r3") = (unsigned long) arg2; \ +register unsigned long __sc4 __asm__ ("r4") = (unsigned long) arg3; \ +__asm__ __volatile__ ("trapa %1" \ + : "=r" (__sc0) \ + : "r" (__sc0), "r" (__sc2), "r" (__sc3), "r" (__sc4) ); \ +__syscall_return(type,__sc0); \ +} + +#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \ +type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4) \ +{ \ +register unsigned long __sc0 __asm__ ("r9") = ((0x14 << 16) | __NR_##name); \ +register unsigned long __sc2 __asm__ ("r2") = (unsigned long) arg1; \ +register unsigned long __sc3 __asm__ ("r3") = (unsigned long) arg2; \ +register unsigned long __sc4 __asm__ ("r4") = (unsigned long) arg3; \ +register unsigned long __sc5 __asm__ ("r5") = (unsigned long) arg4; \ +__asm__ __volatile__ ("trapa %1" \ + : "=r" (__sc0) \ + : "r" (__sc0), "r" (__sc2), "r" (__sc3), "r" (__sc4), "r" (__sc5) );\ +__syscall_return(type,__sc0); \ +} + +#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5) \ +type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) \ +{ \ +register unsigned long __sc0 __asm__ ("r9") = ((0x15 << 16) | __NR_##name); \ +register unsigned long __sc2 __asm__ ("r2") = (unsigned long) arg1; \ +register unsigned long __sc3 __asm__ ("r3") = (unsigned long) arg2; \ +register unsigned long __sc4 __asm__ ("r4") = (unsigned long) arg3; \ +register unsigned long __sc5 __asm__ ("r5") = (unsigned long) arg4; \ +register unsigned long __sc6 __asm__ ("r6") = (unsigned long) arg5; \ +__asm__ __volatile__ ("trapa %1" \ + : "=r" (__sc0) \ + : "r" (__sc0), "r" (__sc2), "r" (__sc3), "r" (__sc4), "r" (__sc5), \ + "r" (__sc6)); \ +__syscall_return(type,__sc0); \ +} + +#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5, type6, arg6) \ +type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6) \ +{ \ +register unsigned long __sc0 __asm__ ("r9") = ((0x16 << 16) | __NR_##name); \ +register unsigned long __sc2 __asm__ ("r2") = (unsigned long) arg1; \ +register unsigned long __sc3 __asm__ ("r3") = (unsigned long) arg2; \ +register unsigned long __sc4 __asm__ ("r4") = (unsigned long) arg3; \ +register unsigned long __sc5 __asm__ ("r5") = (unsigned long) arg4; \ +register unsigned long __sc6 __asm__ ("r6") = (unsigned long) arg5; \ +register unsigned long __sc7 __asm__ ("r7") = (unsigned long) arg6; \ +__asm__ __volatile__ ("trapa %1" \ + : "=r" (__sc0) \ + : "r" (__sc0), "r" (__sc2), "r" (__sc3), "r" (__sc4), "r" (__sc5), \ + "r" (__sc6), "r" (__sc7)); \ +__syscall_return(type,__sc0); \ +} + +#endif /* __ASSEMBLER__ */ +#endif /* _BITS_SYSCALLS_H */ + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/bits/uClibc_arch_features.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/bits/uClibc_arch_features.h new file mode 100644 index 00000000..46bf23e8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/bits/uClibc_arch_features.h @@ -0,0 +1,47 @@ +/* + * Track misc arch-specific features that aren't config options + */ + +#ifndef _BITS_UCLIBC_ARCH_FEATURES_H +#define _BITS_UCLIBC_ARCH_FEATURES_H + +/* instruction used when calling abort() to kill yourself */ +#define __UCLIBC_ABORT_INSTRUCTION__ "movi 0x10, r9; shori 0xff, r9; trapa r9" + +/* can your target use syscall6() for mmap ? */ +#undef __UCLIBC_MMAP_HAS_6_ARGS__ + +/* does your target use syscall4() for truncate64 ? (32bit arches only) */ +#undef __UCLIBC_TRUNCATE64_HAS_4_ARGS__ + +/* does your target have a broken create_module() ? */ +#undef __UCLIBC_BROKEN_CREATE_MODULE__ + +/* does your target have to worry about older [gs]etrlimit() ? */ +#undef __UCLIBC_HANDLE_OLDER_RLIMIT__ + +/* does your target have an asm .set ? */ +#define __UCLIBC_HAVE_ASM_SET_DIRECTIVE__ + +/* define if target doesn't like .global */ +#undef __UCLIBC_ASM_GLOBAL_DIRECTIVE__ + +/* define if target supports .weak */ +#define __UCLIBC_HAVE_ASM_WEAK_DIRECTIVE__ + +/* define if target supports .weakext */ +#undef __UCLIBC_HAVE_ASM_WEAKEXT_DIRECTIVE__ + +/* needed probably only for ppc64 */ +#undef __UCLIBC_HAVE_ASM_GLOBAL_DOT_NAME__ + +/* define if target supports CFI pseudo ops */ +#undef __UCLIBC_HAVE_ASM_CFI_DIRECTIVES__ + +/* define if target supports IEEE signed zero floats */ +#define __UCLIBC_HAVE_SIGNED_ZERO__ + +/* only weird assemblers generally need this */ +#undef __UCLIBC_ASM_LINE_SEP__ + +#endif /* _BITS_UCLIBC_ARCH_FEATURES_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/bits/wordsize.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/bits/wordsize.h new file mode 100644 index 00000000..7c2723be --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/bits/wordsize.h @@ -0,0 +1,12 @@ +/* + * libc/sysdeps/linux/sh64/bits/wordsize.h + * + * Copyright (C) 2003 Paul Mundt + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + */ + +#define __WORDSIZE 32 + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/brk.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/brk.c new file mode 100644 index 00000000..a98cd544 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/brk.c @@ -0,0 +1,27 @@ +/* From libc-5.3.12 */ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include + +extern void * __curbrk attribute_hidden; +extern int __init_brk (void) attribute_hidden; +extern void *_brk(void *ptr) attribute_hidden; + +int brk(void * end_data_seg) +{ + if (__init_brk () == 0) + { + __curbrk = _brk(end_data_seg); + if (__curbrk == end_data_seg) + return 0; + __set_errno(ENOMEM); + } + return -1; +} +libc_hidden_def(brk) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/crt1.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/crt1.S new file mode 100644 index 00000000..1822e2dc --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/crt1.S @@ -0,0 +1,83 @@ +/* Startup code for SH5 & ELF. + Copyright (C) 1999 Free Software Foundation, Inc. + Copyright (C) 2001 Hewlett-Packard Australia + + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* This is the canonical entry point, usually the first thing in the text + segment. + + At this entry point, most registers' values are unspecified, except: + + sp The stack contains the arguments and environment: + 0(sp) argc + 4(sp) argv[0] + ... + (4*argc)(sp) NULL + (4*(argc+1))(sp) envp[0] + ... + NULL +*/ + + .file "crt1.S" + + .globl _start + .type _start,%function + .type main,%function + + .section .text64,"xa" + .align 2 /* 2^2 = 4 */ + +_start: + /* __uClibc_main (main, argc, argv, init, fini) */ + movi __main, r18 + or r2, r63, r18 + + /* Pop argc off the stack and save a pointer to argv */ + ld.l r15, 0, r3 /* argc */ + addi r15, 4, r4 /* argv */ + + movi _init, r5 + movi _fini, r6 + + /* call main() */ + movi __uClibc_main, r17 + ptabs/l r17, tr0 + blink tr0, r18 + + /* should never get here....*/ + movi abort, r17 + ptabs/l r17, tr0 + blink tr0, r63 /* call abort() => (r63) do not come back ... */ + +/* + * The following is a stub to stop the GNU toolchain + * from calling its C-RTL initialization routines. + */ +__main: + movi main, r18 + ptabs/l r18, tr0 + blink tr0, r63 + +/* Define a symbol for the first piece of initialized data. */ + .data + .globl __data_start +__data_start: + .long 0 + .weak data_start + data_start = __data_start diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/crti.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/crti.S new file mode 100644 index 00000000..597be363 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/crti.S @@ -0,0 +1,42 @@ + .file "initfini.c" + .section .text..SHmedia32,"ax" + .little + + .section .init + .hidden _init + .align 2 + .global _init + .type _init, @function +_init: + addi.l r15, -16, r15 + st.l r15, 4, r12 + movi (((datalabel _GLOBAL_OFFSET_TABLE_-(.LPCS0-.)) >> 16) & 65535), r12 + shori ((datalabel _GLOBAL_OFFSET_TABLE_-(.LPCS0-.)) & 65535), r12 + .LPCS0: ptrel/u r12, tr0 + st.l r15, 8, r14 + st.l r15, 12, r18 + add.l r15, r63, r14 + gettr tr0, r12 + + .align 2 + + + .section .fini + .hidden _fini + .align 2 + .global _fini + .type _fini, @function +_fini: + addi.l r15, -16, r15 + st.l r15, 4, r12 + movi (((datalabel _GLOBAL_OFFSET_TABLE_-(.LPCS1-.)) >> 16) & 65535), r12 + shori ((datalabel _GLOBAL_OFFSET_TABLE_-(.LPCS1-.)) & 65535), r12 + .LPCS1: ptrel/u r12, tr0 + st.l r15, 8, r14 + st.l r15, 12, r18 + add.l r15, r63, r14 + gettr tr0, r12 + .align 2 + + + .ident "GCC: (GNU) 3.3.2" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/crtn.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/crtn.S new file mode 100644 index 00000000..501fe916 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/crtn.S @@ -0,0 +1,31 @@ + .file "initfini.c" + .section .text..SHmedia32,"ax" + .little + + .section .init + .hidden _init + .align 2 + .global _init + .type _init, @function + add.l r14, r63, r15 + ld.l r15, 12, r18 + ld.l r15, 4, r12 + ld.l r15, 8, r14 + ptabs r18, tr0 + addi.l r15, 16, r15 + blink tr0, r63 + + .section .fini + .hidden _fini + .align 2 + .global _fini + .type _fini, @function + add.l r14, r63, r15 + ld.l r15, 12, r18 + ld.l r15, 4, r12 + ld.l r15, 8, r14 + ptabs r18, tr0 + addi.l r15, 16, r15 + blink tr0, r63 + + .ident "GCC: (GNU) 3.3.2" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/sbrk.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/sbrk.c new file mode 100644 index 00000000..2dc719a1 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/sbrk.c @@ -0,0 +1,25 @@ +/* From libc-5.3.12 */ + +#include +#include +#include + +extern void * __curbrk attribute_hidden; +extern int __init_brk (void) attribute_hidden; +extern void *_brk(void *ptr) attribute_hidden; + +void * +sbrk(intptr_t increment) +{ + if (__init_brk () == 0) + { + char * tmp = (char*)__curbrk+increment; + __curbrk = _brk(tmp); + if (__curbrk == tmp) + return tmp-increment; + __set_errno(ENOMEM); + return ((void *) -1); + } + return ((void *) -1); +} +libc_hidden_def(sbrk) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/setjmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/setjmp.S new file mode 100644 index 00000000..11d76d37 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/setjmp.S @@ -0,0 +1,140 @@ +/* setjmp for SH-5. + Copyright (C) 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + + +#define _SETJMP_H +#define _ASM +#include + + +#define INTEGER(reg,offset) st.q r2, offset*8, reg +#define DOUBLE(reg,offset) fst.d r2, offset*8, reg + + + .file "setjmp.S" + + .section .text64,"xa" + .align 2 + + .global __sigsetjmp + .type __sigsetjmp,@function + +__sigsetjmp: + /* + * extern int __sigsetjmp(jmp_buf env, int savemask); + * + * r2 == env + * r3 == savemask + * r4 == temporary + */ + + /* callee-save registers R10-R16 */ + INTEGER(r10, __SETJMP_INT(0)) + INTEGER(r11, __SETJMP_INT(1)) + INTEGER(r12, __SETJMP_INT(2)) + INTEGER(r13, __SETJMP_INT(3)) + INTEGER(r14, __SETJMP_INT(4)) + INTEGER(r15, __SETJMP_INT(5)) + INTEGER(r16, __SETJMP_INT(6)) + + /* callee-save registers R28-R35 */ + INTEGER(r28, __SETJMP_INT(7)) + INTEGER(r29, __SETJMP_INT(8)) + INTEGER(r30, __SETJMP_INT(9)) + INTEGER(r31, __SETJMP_INT(10)) + INTEGER(r32, __SETJMP_INT(11)) + INTEGER(r33, __SETJMP_INT(12)) + INTEGER(r34, __SETJMP_INT(13)) + INTEGER(r35, __SETJMP_INT(14)) + + /* callee-save registers R44-R59 */ + INTEGER(r44, __SETJMP_INT(15)) + INTEGER(r45, __SETJMP_INT(16)) + INTEGER(r46, __SETJMP_INT(17)) + INTEGER(r47, __SETJMP_INT(18)) + INTEGER(r48, __SETJMP_INT(19)) + INTEGER(r49, __SETJMP_INT(20)) + INTEGER(r50, __SETJMP_INT(21)) + INTEGER(r51, __SETJMP_INT(22)) + INTEGER(r52, __SETJMP_INT(23)) + INTEGER(r53, __SETJMP_INT(24)) + INTEGER(r54, __SETJMP_INT(25)) + INTEGER(r55, __SETJMP_INT(26)) + INTEGER(r56, __SETJMP_INT(27)) + INTEGER(r57, __SETJMP_INT(28)) + INTEGER(r58, __SETJMP_INT(29)) + INTEGER(r59, __SETJMP_INT(30)) + + #if __SETJMP_NUM_INT != 31 + #error __SETJMP_NUM_INT does agree with expected value + #endif + +#if __SETJMP_NUM_DBL > 0 + /* callee-save registers FR12-FR15 */ + DOUBLE(d12, __SETJMP_DBL(0)) + DOUBLE(d14, __SETJMP_DBL(1)) + + /* callee-save registers FR36-FR63 */ + DOUBLE(d36, __SETJMP_DBL(2)) + DOUBLE(d38, __SETJMP_DBL(3)) + DOUBLE(d40, __SETJMP_DBL(4)) + DOUBLE(d42, __SETJMP_DBL(5)) + DOUBLE(d44, __SETJMP_DBL(6)) + DOUBLE(d46, __SETJMP_DBL(7)) + DOUBLE(d48, __SETJMP_DBL(8)) + DOUBLE(d50, __SETJMP_DBL(9)) + DOUBLE(d52, __SETJMP_DBL(10)) + DOUBLE(d54, __SETJMP_DBL(11)) + DOUBLE(d56, __SETJMP_DBL(12)) + DOUBLE(d58, __SETJMP_DBL(13)) + DOUBLE(d60, __SETJMP_DBL(14)) + DOUBLE(d62, __SETJMP_DBL(15)) + + #if __SETJMP_NUM_DBL != 16 + #error __SETJMP_NUM_DBL does agree with expected value + #endif + +#endif /* __SETJMP_NUM_DBL > 0 */ + + /* callee-save registers TR5-TR7 */ + gettr tr5, r4 + INTEGER(r4, __SETJMP_TRG(0)) + gettr tr6, r4 + INTEGER(r4, __SETJMP_TRG(1)) + gettr tr7, r4 + INTEGER(r4, __SETJMP_TRG(2)) + + #if __SETJMP_NUM_TRG != 3 + #error __SETJMP_NUM_TRG does agree with expected value + #endif + + /* save Linkage Register (LR) for longjmp return */ + INTEGER(r18, __SETJMP_LR) + + /* + * return a value of zero if call is __sigsetjmp(). + * This is so that caller of setjmp() knows + * we have retruned via setjmp, and not via longjmp. + * R0 is the result register. + */ + + ptabs/l r18, tr0 /* return to caller */ + movi 0, r2 /* return value */ + blink tr0, r63 + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/sys/procfs.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/sys/procfs.h new file mode 100644 index 00000000..aad21e5f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/sys/procfs.h @@ -0,0 +1,126 @@ +/* Copyright (C) 1996, 1997, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_PROCFS_H +#define _SYS_PROCFS_H 1 + +/* This is somehow modelled after the file of the same name on SysVr4 + systems. It provides a definition of the core file format for ELF + used on Linux. */ + +#include +#include +#include +#include +#include +#include + +__BEGIN_DECLS + +/* + * ELF register definitions... + */ +typedef unsigned long elf_greg_t; + +#define ELF_NGREG (sizeof (struct pt_regs) / sizeof(elf_greg_t)) +typedef elf_greg_t elf_gregset_t[ELF_NGREG]; + +typedef struct user_fpu_struct elf_fpregset_t; + +struct elf_siginfo + { + int si_signo; /* Signal number. */ + int si_code; /* Extra code. */ + int si_errno; /* Errno. */ + }; + + +/* Definitions to generate Intel SVR4-like core files. These mostly + have the same names as the SVR4 types with "elf_" tacked on the + front to prevent clashes with linux definitions, and the typedef + forms have been avoided. This is mostly like the SVR4 structure, + but more Linuxy, with things that Linux does not support and which + gdb doesn't really use excluded. Fields present but not used are + marked with "XXX". */ +struct elf_prstatus + { +#if 0 + long int pr_flags; /* XXX Process flags. */ + short int pr_why; /* XXX Reason for process halt. */ + short int pr_what; /* XXX More detailed reason. */ +#endif + struct elf_siginfo pr_info; /* Info associated with signal. */ + short int pr_cursig; /* Current signal. */ + unsigned long int pr_sigpend; /* Set of pending signals. */ + unsigned long int pr_sighold; /* Set of held signals. */ +#if 0 + struct sigaltstack pr_altstack; /* Alternate stack info. */ + struct sigaction pr_action; /* Signal action for current sig. */ +#endif + __pid_t pr_pid; + __pid_t pr_ppid; + __pid_t pr_pgrp; + __pid_t pr_sid; + struct timeval pr_utime; /* User time. */ + struct timeval pr_stime; /* System time. */ + struct timeval pr_cutime; /* Cumulative user time. */ + struct timeval pr_cstime; /* Cumulative system time. */ +#if 0 + long int pr_instr; /* Current instruction. */ +#endif + elf_gregset_t pr_reg; /* GP registers. */ + int pr_fpvalid; /* True if math copro being used. */ + }; + + +#define ELF_PRARGSZ (80) /* Number of chars for args */ + +struct elf_prpsinfo + { + char pr_state; /* Numeric process state. */ + char pr_sname; /* Char for pr_state. */ + char pr_zomb; /* Zombie. */ + char pr_nice; /* Nice val. */ + unsigned long int pr_flag; /* Flags. */ + long pr_uid; + long pr_gid; + int pr_pid, pr_ppid, pr_pgrp, pr_sid; + /* Lots missing */ + char pr_fname[16]; /* Filename of executable. */ + char pr_psargs[ELF_PRARGSZ]; /* Initial part of arg list. */ + }; + + +/* Addresses. */ +typedef void *psaddr_t; + +/* Register sets. Linux has different names. */ +typedef elf_gregset_t prgregset_t; +typedef elf_fpregset_t prfpregset_t; + +/* We don't have any differences between processes and threads, + therefore habe only ine PID type. */ +typedef __pid_t lwpid_t; + + +typedef struct elf_prstatus prstatus_t; +typedef struct elf_prpsinfo prpsinfo_t; + +__END_DECLS + +#endif /* sys/procfs.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/sys/ucontext.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/sys/ucontext.h new file mode 100644 index 00000000..74407841 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/sys/ucontext.h @@ -0,0 +1,205 @@ +/* Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* Where is System V/SH ABI? */ + +#ifndef _SYS_UCONTEXT_H +#define _SYS_UCONTEXT_H 1 + +#include +#include + +/* We need the signal context definitions even if they are not used + included in . */ +#include + + +typedef long long greg_t; + +/* Number of general registers. */ +#define NGREG 64 + +/* Container for all general registers. */ +typedef greg_t gregset_t[NGREG]; + +#ifdef __USE_GNU +/* Number of each register is the `gregset_t' array. */ +enum +{ + R0 = 0, +#define R0 R0 + R1 = 1, +#define R1 R1 + R2 = 2, +#define R2 R2 + R3 = 3, +#define R3 R3 + R4 = 4, +#define R4 R4 + R5 = 5, +#define R5 R5 + R6 = 6, +#define R6 R6 + R7 = 7, +#define R7 R7 + R8 = 8, +#define R8 R8 + R9 = 9, +#define R9 R9 + R10 = 10, +#define R10 R10 + R11 = 11, +#define R11 R11 + R12 = 12, +#define R12 R12 + R13 = 13, +#define R13 R13 + R14 = 14, +#define R14 R14 + R15 = 15, +#define R15 R15 + R16 = 16, +#define R16 R16 + R17 = 17, +#define R17 R17 + R18 = 18, +#define R18 R18 + R19 = 19, +#define R19 R19 + R20 = 20, +#define R20 R20 + R21 = 21, +#define R21 R21 + R22 = 22, +#define R22 R22 + R23 = 23, +#define R23 R23 + R24 = 24, +#define R24 R24 + R25 = 25, +#define R25 R25 + R26 = 26, +#define R26 R26 + R27 = 27, +#define R27 R27 + R28 = 28, +#define R28 R28 + R29 = 29, +#define R29 R29 + R30 = 30, +#define R30 R30 + R31 = 31, +#define R31 R31 + R32 = 32, +#define R32 R32 + R33 = 33, +#define R33 R33 + R34 = 34, +#define R34 R34 + R35 = 35, +#define R35 R35 + R36 = 36, +#define R36 R36 + R37 = 37, +#define R37 R37 + R38 = 38, +#define R38 R38 + R39 = 39, +#define R39 R39 + R40 = 40, +#define R40 R40 + R41 = 41, +#define R41 R41 + R42 = 42, +#define R42 R42 + R43 = 43, +#define R43 R43 + R44 = 44, +#define R44 R44 + R45 = 45, +#define R45 R45 + R46 = 46, +#define R46 R46 + R47 = 47, +#define R47 R47 + R48 = 48, +#define R48 R48 + R49 = 49, +#define R49 R49 + R50 = 50, +#define R50 R50 + R51 = 51, +#define R51 R51 + R52 = 52, +#define R52 R52 + R53 = 53, +#define R53 R53 + R54 = 54, +#define R54 R54 + R55 = 55, +#define R55 R55 + R56 = 56, +#define R56 R56 + R57 = 57, +#define R57 R57 + R58 = 58, +#define R58 R58 + R59 = 59, +#define R59 R59 + R60 = 60, +#define R60 R60 + R61 = 61, +#define R61 R61 + R62 = 62, +#define R62 R62 + R63 = 63, +#define R63 R63 +}; +#endif + +typedef int freg_t; + +/* Number of FPU registers. */ +#define NFPREG 32 + +/* Structure to describe FPU registers. */ +typedef freg_t fpregset_t[NFPREG]; + +/* Context to describe whole processor state. */ +typedef struct + { + gregset_t gregs; + fpregset_t fpregs; + unsigned long long sc_tregs[8]; + unsigned long long sc_pc; + unsigned long long sc_sr; + unsigned long long sc_fpscr; + + } mcontext_t; + +/* Userlevel context. */ +typedef struct ucontext + { + unsigned long int uc_flags; + struct ucontext *uc_link; + stack_t uc_stack; + mcontext_t uc_mcontext; + __sigset_t uc_sigmask; + } ucontext_t; + +#endif /* sys/ucontext.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/syscall.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/syscall.c new file mode 100644 index 00000000..a6c55ebe --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sh64/syscall.c @@ -0,0 +1,24 @@ + + +#include +#include +#include +#include + +long syscall(long sysnum, + long arg1, long arg2, long arg3, + long arg4, long arg5, long arg6) +{ +register long __sc0 __asm__ ("r9") = ((0x16 << 16) | sysnum); +register long __sc2 __asm__ ("r2") = (long) arg1; +register long __sc3 __asm__ ("r3") = (long) arg2; +register long __sc4 __asm__ ("r4") = (long) arg3; +register long __sc5 __asm__ ("r5") = (long) arg4; +register long __sc6 __asm__ ("r6") = (long) arg5; +register long __sc7 __asm__ ("r7") = (long) arg6; +__asm__ __volatile__ ("trapa %1" \ + : "=r" (__sc0) \ + : "r" (__sc0), "r" (__sc2), "r" (__sc3), "r" (__sc4), "r" (__sc5), \ + "r" (__sc6), "r" (__sc7)); +__syscall_return(long,__sc0); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/Makefile new file mode 100644 index 00000000..633c91f3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../../ +top_builddir=../../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.arch +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/Makefile.arch b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/Makefile.arch new file mode 100644 index 00000000..91c6e85e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/Makefile.arch @@ -0,0 +1,24 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +CSRC := brk.c __syscall_error.c + +SSRC := \ + __longjmp.S setjmp.S bsd-setjmp.S bsd-_setjmp.S \ + syscall.S urem.S udiv.S umul.S sdiv.S rem.S pipe.S + +ifneq ($(UCLIBC_HAS_THREADS_NATIVE),y) +CSRC += sigaction.c +SSRC += fork.S vfork.S +endif + +CSRC += $(foreach f, \ + q_div.c q_fle.c q_mul.c q_qtoll.c q_stoq.c \ + mp_clz_tab.c q_dtoq.c q_flt.c q_neg.c q_qtos.c q_sub.c \ + q_add.c q_feq.c q_fne.c q_qtod.c q_qtou.c q_ulltoq.c \ + q_cmp.c q_fge.c q_itoq.c q_qtoull.c q_util.c \ + q_cmpe.c q_fgt.c q_lltoq.c q_qtoi.c q_sqrt.c q_utoq.c, soft-fp/$(f)) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/__longjmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/__longjmp.S new file mode 100644 index 00000000..c7d4f079 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/__longjmp.S @@ -0,0 +1,89 @@ +/* Copyright (C) 1991, 93, 96, 97, 98, 99, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +#define _ASM 1 +#define _SETJMP_H +#include +#define ENV(base,reg) [%base + (reg * 4)] +#define ST_FLUSH_WINDOWS 3 +#define RW_FP [%fp + 0x48] + +.global __longjmp +.type __longjmp,%function +.align 4 +__longjmp: + .register %g2, #scratch + .register %g3, #scratch + /* Store our arguments in global registers so we can still + * use them while unwinding frames and their register windows. */ + + ld ENV(o0,JB_FP), %g3 /* Cache target FP in register %g3. */ + mov %o0, %g1 /* ENV in %g1 */ + orcc %o1, %g0, %g2 /* VAL in %g2 */ + be,a 0f /* Branch if zero; else skip delay slot. */ + mov 1, %g2 /* Delay slot only hit if zero: VAL = 1. */ +0: + xor %fp, %g3, %o0 + add %fp, 512, %o1 + andncc %o0, 4095, %o0 + bne .Lthread + cmp %o1, %g3 + bl .Lthread + + /* Now we will loop, unwinding the register windows up the stack + * until the restored %fp value matches the target value in %g3. */ + +.Lloop: + cmp %fp, %g3 /* Have we reached the target frame? */ + bl,a .Lloop /* Loop while current fp is below target. */ + restore /* Unwind register window in delay slot. */ + be,a .Lfound /* Better have hit it exactly. */ + ld ENV(g1,JB_SP), %o0 /* Delay slot: extract target SP. */ + +.Lthread: + /* + * Do a "flush register windows trap". The trap handler in the + * kernel writes all the register windows to their stack slots, and + * marks them all as invalid (needing to be sucked up from the + * stack when used). This ensures that all information needed to + * unwind to these callers is in memory, not in the register + * windows. + */ + ta ST_FLUSH_WINDOWS + ld ENV(g1,JB_PC), %o7 /* Set return PC. */ + ld ENV(g1,JB_SP), %fp /* Set saved SP on restore below. */ + sub %fp, 64, %sp /* Allocate a register frame. */ + st %g3, RW_FP /* Set saved FP on restore below. */ + retl + restore %g2, 0, %o0 /* Restore values from above register frame. */ + +.Lfound: + /* We have unwound register windows so %fp matches the target. */ + mov %o0, %sp /* OK, install new SP. */ + +.Lsp_ok: + ld ENV(g1,JB_PC), %o0 /* Extract target return PC. */ + jmp %o0 + 8 /* Return there. */ + mov %g2, %o0 /* Delay slot: set return value. */ + +.size __longjmp,.-__longjmp + +libc_hidden_def(__longjmp) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/__syscall_error.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/__syscall_error.c new file mode 100644 index 00000000..5e109a83 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/__syscall_error.c @@ -0,0 +1,18 @@ +/* Wrapper for setting errno. + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +/* This routine is jumped to by all the syscall handlers, to stash + * an error number into errno. */ +int __syscall_error(int err_no) attribute_hidden; +int __syscall_error(int err_no) +{ + __set_errno(err_no); + return -1; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/_math_inc.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/_math_inc.h new file mode 100644 index 00000000..1bf84f04 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/_math_inc.h @@ -0,0 +1,32 @@ +/* + * Setup some glibc defines so we can just drop in the + * asm files from glibc without any modification. + */ + +#include +#include + +#define __ASSEMBLY__ +#ifndef __sparc_v9__ +#include +#endif + +/* Is alignment really needed? */ + +#if __WORDSIZE == 32 +# define ENTRY_ALIGN 4 +#else +# define ENTRY_ALIGN 2 +#endif + +#define ENTRY(sym) \ + .global sym; \ + .align ENTRY_ALIGN; \ + .type sym,%function; \ + sym: + +#define LOC(sym) \ + .L ## sym + +#define END(sym) \ + .size sym,.-sym; diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/atomic.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/atomic.h new file mode 100644 index 00000000..16c3c78c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/atomic.h @@ -0,0 +1,329 @@ +/* Atomic operations. sparc32 version. + Copyright (C) 2003, 2004, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _BITS_ATOMIC_H +#define _BITS_ATOMIC_H 1 + +#include + +typedef int8_t atomic8_t; +typedef uint8_t uatomic8_t; +typedef int_fast8_t atomic_fast8_t; +typedef uint_fast8_t uatomic_fast8_t; + +typedef int16_t atomic16_t; +typedef uint16_t uatomic16_t; +typedef int_fast16_t atomic_fast16_t; +typedef uint_fast16_t uatomic_fast16_t; + +typedef int32_t atomic32_t; +typedef uint32_t uatomic32_t; +typedef int_fast32_t atomic_fast32_t; +typedef uint_fast32_t uatomic_fast32_t; + +typedef int64_t atomic64_t; +typedef uint64_t uatomic64_t; +typedef int_fast64_t atomic_fast64_t; +typedef uint_fast64_t uatomic_fast64_t; + +typedef intptr_t atomicptr_t; +typedef uintptr_t uatomicptr_t; +typedef intmax_t atomic_max_t; +typedef uintmax_t uatomic_max_t; + + +/* We have no compare and swap, just test and set. + The following implementation contends on 64 global locks + per library and assumes no variable will be accessed using atomic.h + macros from two different libraries. */ + +__make_section_unallocated + (".gnu.linkonce.b.__sparc32_atomic_locks, \"aw\", %nobits"); + +volatile unsigned char __sparc32_atomic_locks[64] + __attribute__ ((nocommon, section (".gnu.linkonce.b.__sparc32_atomic_locks" + __sec_comment), + visibility ("hidden"))); + +#define __sparc32_atomic_do_lock(addr) \ + do \ + { \ + unsigned int __old_lock; \ + unsigned int __idx = (((long) addr >> 2) ^ ((long) addr >> 12)) \ + & 63; \ + do \ + __asm__ __volatile__ ("ldstub %1, %0" \ + : "=r" (__old_lock), \ + "=m" (__sparc32_atomic_locks[__idx]) \ + : "m" (__sparc32_atomic_locks[__idx]) \ + : "memory"); \ + while (__old_lock); \ + } \ + while (0) + +#define __sparc32_atomic_do_unlock(addr) \ + do \ + { \ + __sparc32_atomic_locks[(((long) addr >> 2) \ + ^ ((long) addr >> 12)) & 63] = 0; \ + __asm__ __volatile__ ("" ::: "memory"); \ + } \ + while (0) + +#define __sparc32_atomic_do_lock24(addr) \ + do \ + { \ + unsigned int __old_lock; \ + do \ + __asm__ __volatile__ ("ldstub %1, %0" \ + : "=r" (__old_lock), "=m" (*(addr)) \ + : "m" (*(addr)) \ + : "memory"); \ + while (__old_lock); \ + } \ + while (0) + +#define __sparc32_atomic_do_unlock24(addr) \ + do \ + { \ + *(char *) (addr) = 0; \ + __asm__ __volatile__ ("" ::: "memory"); \ + } \ + while (0) + + +#ifndef SHARED +# define __v9_compare_and_exchange_val_32_acq(mem, newval, oldval) \ +({ \ + register __typeof (*(mem)) __acev_tmp __asm__ ("%g6"); \ + register __typeof (mem) __acev_mem __asm__ ("%g1") = (mem); \ + register __typeof (*(mem)) __acev_oldval __asm__ ("%g5"); \ + __acev_tmp = (newval); \ + __acev_oldval = (oldval); \ + /* .word 0xcde05005 is cas [%g1], %g5, %g6. Can't use cas here though, \ + because as will then mark the object file as V8+ arch. */ \ + __asm__ __volatile__ (".word 0xcde05005" \ + : "+r" (__acev_tmp), "=m" (*__acev_mem) \ + : "r" (__acev_oldval), "m" (*__acev_mem), \ + "r" (__acev_mem) : "memory"); \ + __acev_tmp; }) +#endif + +/* The only basic operation needed is compare and exchange. */ +#define __v7_compare_and_exchange_val_acq(mem, newval, oldval) \ + ({ __typeof (mem) __acev_memp = (mem); \ + __typeof (*mem) __acev_ret; \ + __typeof (*mem) __acev_newval = (newval); \ + \ + __sparc32_atomic_do_lock (__acev_memp); \ + __acev_ret = *__acev_memp; \ + if (__acev_ret == (oldval)) \ + *__acev_memp = __acev_newval; \ + __sparc32_atomic_do_unlock (__acev_memp); \ + __acev_ret; }) + +#define __v7_compare_and_exchange_bool_acq(mem, newval, oldval) \ + ({ __typeof (mem) __aceb_memp = (mem); \ + int __aceb_ret; \ + __typeof (*mem) __aceb_newval = (newval); \ + \ + __sparc32_atomic_do_lock (__aceb_memp); \ + __aceb_ret = 0; \ + if (*__aceb_memp == (oldval)) \ + *__aceb_memp = __aceb_newval; \ + else \ + __aceb_ret = 1; \ + __sparc32_atomic_do_unlock (__aceb_memp); \ + __aceb_ret; }) + +#define __v7_exchange_acq(mem, newval) \ + ({ __typeof (mem) __acev_memp = (mem); \ + __typeof (*mem) __acev_ret; \ + __typeof (*mem) __acev_newval = (newval); \ + \ + __sparc32_atomic_do_lock (__acev_memp); \ + __acev_ret = *__acev_memp; \ + *__acev_memp = __acev_newval; \ + __sparc32_atomic_do_unlock (__acev_memp); \ + __acev_ret; }) + +#define __v7_exchange_and_add(mem, value) \ + ({ __typeof (mem) __acev_memp = (mem); \ + __typeof (*mem) __acev_ret; \ + \ + __sparc32_atomic_do_lock (__acev_memp); \ + __acev_ret = *__acev_memp; \ + *__acev_memp = __acev_ret + (value); \ + __sparc32_atomic_do_unlock (__acev_memp); \ + __acev_ret; }) + +/* Special versions, which guarantee that top 8 bits of all values + are cleared and use those bits as the ldstub lock. */ +#define __v7_compare_and_exchange_val_24_acq(mem, newval, oldval) \ + ({ __typeof (mem) __acev_memp = (mem); \ + __typeof (*mem) __acev_ret; \ + __typeof (*mem) __acev_newval = (newval); \ + \ + __sparc32_atomic_do_lock24 (__acev_memp); \ + __acev_ret = *__acev_memp & 0xffffff; \ + if (__acev_ret == (oldval)) \ + *__acev_memp = __acev_newval; \ + else \ + __sparc32_atomic_do_unlock24 (__acev_memp); \ + __asm__ __volatile__ ("" ::: "memory"); \ + __acev_ret; }) + +#define __v7_exchange_24_rel(mem, newval) \ + ({ __typeof (mem) __acev_memp = (mem); \ + __typeof (*mem) __acev_ret; \ + __typeof (*mem) __acev_newval = (newval); \ + \ + __sparc32_atomic_do_lock24 (__acev_memp); \ + __acev_ret = *__acev_memp & 0xffffff; \ + *__acev_memp = __acev_newval; \ + __asm__ __volatile__ ("" ::: "memory"); \ + __acev_ret; }) + +#ifdef SHARED + +/* When dynamically linked, we assume pre-v9 libraries are only ever + used on pre-v9 CPU. */ +# define __atomic_is_v9 0 + +# define atomic_compare_and_exchange_val_acq(mem, newval, oldval) \ + __v7_compare_and_exchange_val_acq (mem, newval, oldval) + +# define atomic_compare_and_exchange_bool_acq(mem, newval, oldval) \ + __v7_compare_and_exchange_bool_acq (mem, newval, oldval) + +# define atomic_exchange_acq(mem, newval) \ + __v7_exchange_acq (mem, newval) + +# define atomic_exchange_and_add(mem, value) \ + __v7_exchange_and_add (mem, value) + +# define atomic_compare_and_exchange_val_24_acq(mem, newval, oldval) \ + ({ \ + if (sizeof (*mem) != 4) \ + abort (); \ + __v7_compare_and_exchange_val_24_acq (mem, newval, oldval); }) + +# define atomic_exchange_24_rel(mem, newval) \ + ({ \ + if (sizeof (*mem) != 4) \ + abort (); \ + __v7_exchange_24_rel (mem, newval); }) + +#else + + + +/* + Here's what we'd like to do: + + In libc.a/libpthread.a etc. we don't know if we'll be run on + pre-v9 or v9 CPU. To be interoperable with dynamically linked + apps on v9 CPUs e.g. with process shared primitives, use cas insn + on v9 CPUs and ldstub on pre-v9. + + However, we have no good way to test at run time that I know of, + so resort to the lowest common denominator (v7 ops) -austinf + */ +#define __atomic_is_v9 0 + +# define atomic_compare_and_exchange_val_acq(mem, newval, oldval) \ + ({ \ + __typeof (*mem) __acev_wret; \ + if (sizeof (*mem) != 4) \ + abort (); \ + if (__atomic_is_v9) \ + __acev_wret \ + = __v9_compare_and_exchange_val_32_acq (mem, newval, oldval);\ + else \ + __acev_wret \ + = __v7_compare_and_exchange_val_acq (mem, newval, oldval); \ + __acev_wret; }) + +# define atomic_compare_and_exchange_bool_acq(mem, newval, oldval) \ + ({ \ + int __acev_wret; \ + if (sizeof (*mem) != 4) \ + abort (); \ + if (__atomic_is_v9) \ + { \ + __typeof (oldval) __acev_woldval = (oldval); \ + __acev_wret \ + = __v9_compare_and_exchange_val_32_acq (mem, newval, \ + __acev_woldval) \ + != __acev_woldval; \ + } \ + else \ + __acev_wret \ + = __v7_compare_and_exchange_bool_acq (mem, newval, oldval); \ + __acev_wret; }) + +# define atomic_exchange_rel(mem, newval) \ + ({ \ + __typeof (*mem) __acev_wret; \ + if (sizeof (*mem) != 4) \ + abort (); \ + if (__atomic_is_v9) \ + { \ + __typeof (mem) __acev_wmemp = (mem); \ + __typeof (*(mem)) __acev_wval = (newval); \ + do \ + __acev_wret = *__acev_wmemp; \ + while (__builtin_expect \ + (__v9_compare_and_exchange_val_32_acq (__acev_wmemp,\ + __acev_wval, \ + __acev_wret) \ + != __acev_wret, 0)); \ + } \ + else \ + __acev_wret = __v7_exchange_acq (mem, newval); \ + __acev_wret; }) + +# define atomic_compare_and_exchange_val_24_acq(mem, newval, oldval) \ + ({ \ + __typeof (*mem) __acev_wret; \ + if (sizeof (*mem) != 4) \ + abort (); \ + if (__atomic_is_v9) \ + __acev_wret \ + = __v9_compare_and_exchange_val_32_acq (mem, newval, oldval);\ + else \ + __acev_wret \ + = __v7_compare_and_exchange_val_24_acq (mem, newval, oldval);\ + __acev_wret; }) + +# define atomic_exchange_24_rel(mem, newval) \ + ({ \ + __typeof (*mem) __acev_w24ret; \ + if (sizeof (*mem) != 4) \ + abort (); \ + if (__atomic_is_v9) \ + __acev_w24ret = atomic_exchange_rel (mem, newval); \ + else \ + __acev_w24ret = __v7_exchange_24_rel (mem, newval); \ + __acev_w24ret; }) + +#endif + +#endif /* bits/atomic.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/endian.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/endian.h new file mode 100644 index 00000000..8acfdf5d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/endian.h @@ -0,0 +1,12 @@ +/* Sparc is big-endian, but v9 supports endian conversion on loads/stores + and GCC supports such a mode. Be prepared. */ + +#ifndef _ENDIAN_H +# error "Never use directly; include instead." +#endif + +#ifdef __LITTLE_ENDIAN__ +# define __BYTE_ORDER __LITTLE_ENDIAN +#else +# define __BYTE_ORDER __BIG_ENDIAN +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/fcntl.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/fcntl.h new file mode 100644 index 00000000..31a6d9bd --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/fcntl.h @@ -0,0 +1,258 @@ +/* O_*, F_*, FD_* bit values for Linux/SPARC. + Copyright (C) 1995, 1996, 1997, 1998, 2000, 2003, 2004, 2006, 2007 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FCNTL_H +# error "Never use directly; include instead." +#endif + +#include +#include +#ifdef __USE_GNU +# include +#endif + +/* open/fcntl - O_SYNC is only implemented on blocks devices and on files + located on an ext2 file system */ +#define O_RDONLY 0x0000 +#define O_WRONLY 0x0001 +#define O_RDWR 0x0002 +#define O_ACCMODE 0x0003 +#define O_APPEND 0x0008 +#define O_ASYNC 0x0040 +#define O_CREAT 0x0200 /* not fcntl */ +#define O_TRUNC 0x0400 /* not fcntl */ +#define O_EXCL 0x0800 /* not fcntl */ +#define O_SYNC 0x2000 +#define O_NONBLOCK 0x4000 +#define O_NDELAY (0x0004 | O_NONBLOCK) +#define O_NOCTTY 0x8000 /* not fcntl */ + +#ifdef __USE_GNU +# define O_DIRECTORY 0x10000 /* must be a directory */ +# define O_NOFOLLOW 0x20000 /* don't follow links */ +# define O_DIRECT 0x100000 /* direct disk access hint */ +# define O_NOATIME 0x200000 /* Do not set atime. */ +# define O_CLOEXEC 0x400000 /* Set close_on_exit. */ +#endif + +#ifdef __USE_LARGEFILE64 +# if __WORDSIZE == 64 +# define O_LARGEFILE 0 +# else +# define O_LARGEFILE 0x40000 +# endif +#endif + +/* For now Linux has no synchronisity options for data and read + operations. We define the symbols here but let them do the same as + O_SYNC since this is a superset. */ +#if defined __USE_POSIX199309 || defined __USE_UNIX98 +# define O_DSYNC O_SYNC /* Synchronize data. */ +# define O_RSYNC O_SYNC /* Synchronize read operations. */ +#endif + +/* For now Linux has synchronisity options for data and read operations. + We define the symbols here but let them do the same as O_SYNC since + this is a superset. */ +#if defined __USE_POSIX199309 || defined __USE_UNIX98 +# define O_DSYNC O_SYNC /* Synchronize data. */ +# define O_RSYNC O_SYNC /* Synchronize read operations. */ +#endif + +/* Values for the second argument to `fcntl'. */ +#define F_DUPFD 0 /* Duplicate file descriptor. */ +#define F_GETFD 1 /* Get file descriptor flags. */ +#define F_SETFD 2 /* Set file descriptor flags. */ +#define F_GETFL 3 /* Get file status flags. */ +#define F_SETFL 4 /* Set file status flags. */ +#if defined __USE_BSD || defined __USE_UNIX98 +# define F_GETOWN 5 /* Get owner of socket (receiver of SIGIO). */ +# define F_SETOWN 6 /* Set owner of socket (receiver of SIGIO). */ +#endif +#ifndef __USE_FILE_OFFSET64 +# define F_GETLK 7 /* Get record locking info. */ +# define F_SETLK 8 /* Set record locking info (non-blocking). */ +# define F_SETLKW 9 /* Set record locking info (blocking). */ +#else +# define F_GETLK F_GETLK64 /* Get record locking info. */ +# define F_SETLK F_SETLK64 /* Set record locking info (non-blocking).*/ +# define F_SETLKW F_SETLKW64 /* Set record locking info (blocking). */ +#endif + +#ifdef __USE_GNU +# define F_SETSIG 10 /* Set number of signal to be sent. */ +# define F_GETSIG 11 /* Get number of signal to be sent. */ +#endif + +#ifdef __USE_GNU +# define F_SETLEASE 1024 /* Set a lease. */ +# define F_GETLEASE 1025 /* Enquire what lease is active. */ +# define F_NOTIFY 1026 /* Request notfications on a directory. */ +# define F_DUPFD_CLOEXEC 1030 /* Duplicate file descriptor with + close-on-exit set on new fd. */ +#endif + +#if __WORDSIZE == 64 +# define F_GETLK64 7 /* Get record locking info. */ +# define F_SETLK64 8 /* Set record locking info (non-blocking). */ +# define F_SETLKW64 9 /* Set record locking info (blocking). */ +#else +# define F_GETLK64 12 /* Get record locking info. */ +# define F_SETLK64 13 /* Set record locking info (non-blocking). */ +# define F_SETLKW64 14 /* Set record locking info (blocking). */ +#endif + +/* for F_[GET|SET]FD */ +#define FD_CLOEXEC 1 /* actually anything with low bit set goes */ + +/* For posix fcntl() and `l_type' field of a `struct flock' for lockf(). */ +#define F_RDLCK 1 /* Read lock. */ +#define F_WRLCK 2 /* Write lock. */ +#define F_UNLCK 3 /* Remove lock. */ + +/* for old implementation of bsd flock () */ +#define F_EXLCK 4 /* or 3 */ +#define F_SHLCK 8 /* or 4 */ + +#ifdef __USE_BSD +/* Operations for bsd flock(), also used by the kernel implementation */ +# define LOCK_SH 1 /* shared lock */ +# define LOCK_EX 2 /* exclusive lock */ +# define LOCK_NB 4 /* or'd with one of the above to prevent + blocking */ +# define LOCK_UN 8 /* remove lock */ +#endif + +#ifdef __USE_GNU +# define LOCK_MAND 32 /* This is a mandatory flock: */ +# define LOCK_READ 64 /* ... which allows concurrent read operations. */ +# define LOCK_WRITE 128 /* ... which allows concurrent write operations. */ +# define LOCK_RW 192 /* ... Which allows concurrent read & write operations. */ +#endif + +#ifdef __USE_GNU +/* Types of directory notifications that may be requested with F_NOTIFY. */ +# define DN_ACCESS 0x00000001 /* File accessed. */ +# define DN_MODIFY 0x00000002 /* File modified. */ +# define DN_CREATE 0x00000004 /* File created. */ +# define DN_DELETE 0x00000008 /* File removed. */ +# define DN_RENAME 0x00000010 /* File renamed. */ +# define DN_ATTRIB 0x00000020 /* File changed attibutes. */ +# define DN_MULTISHOT 0x80000000 /* Don't remove notifier. */ +#endif + +struct flock + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ +#ifndef __USE_FILE_OFFSET64 + __off_t l_start; /* Offset where the lock begins. */ + __off_t l_len; /* Size of the locked area; zero means until EOF. */ +#else + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ +#endif + __pid_t l_pid; /* Process holding the lock. */ + short int __unused; + }; + +#ifdef __USE_LARGEFILE64 +struct flock64 + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ + __pid_t l_pid; /* Process holding the lock. */ + short int __unused; + }; +#endif + +/* Define some more compatibility macros to be backward compatible with + BSD systems which did not managed to hide these kernel macros. */ +#ifdef __USE_BSD +# define FAPPEND O_APPEND +# define FFSYNC O_FSYNC +# define FASYNC O_ASYNC +# define FNONBLOCK O_NONBLOCK +# define FNDELAY O_NDELAY +#endif /* Use BSD. */ + +/* Advise to `posix_fadvise'. */ +#ifdef __USE_XOPEN2K +# define POSIX_FADV_NORMAL 0 /* No further special treatment. */ +# define POSIX_FADV_RANDOM 1 /* Expect random page references. */ +# define POSIX_FADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define POSIX_FADV_WILLNEED 3 /* Will need these pages. */ +# define POSIX_FADV_DONTNEED 4 /* Don't need these pages. */ +# define POSIX_FADV_NOREUSE 5 /* Data will be accessed once. */ +#endif + + +#if defined __USE_GNU && defined __UCLIBC_LINUX_SPECIFIC__ +/* Flags for SYNC_FILE_RANGE. */ +# define SYNC_FILE_RANGE_WAIT_BEFORE 1 /* Wait upon writeout of all pages + in the range before performing the + write. */ +# define SYNC_FILE_RANGE_WRITE 2 /* Initiate writeout of all those + dirty pages in the range which are + not presently under writeback. */ +# define SYNC_FILE_RANGE_WAIT_AFTER 4 /* Wait upon writeout of all pages in + the range after performing the + write. */ + +/* Flags for SPLICE and VMSPLICE. */ +# define SPLICE_F_MOVE 1 /* Move pages instead of copying. */ +# define SPLICE_F_NONBLOCK 2 /* Don't block on the pipe splicing + (but we may still block on the fd + we splice from/to). */ +# define SPLICE_F_MORE 4 /* Expect more data. */ +# define SPLICE_F_GIFT 8 /* Pages passed in are a gift. */ +#endif + +__BEGIN_DECLS + +#if defined __USE_GNU && defined __UCLIBC_LINUX_SPECIFIC__ + +/* Provide kernel hint to read ahead. */ +extern ssize_t readahead (int __fd, __off64_t __offset, size_t __count) + __THROW; + + +/* Selective file content synch'ing. */ +extern int sync_file_range (int __fd, __off64_t __from, __off64_t __to, + unsigned int __flags); + +/* Splice address range into a pipe. */ +extern ssize_t vmsplice (int __fdout, const struct iovec *__iov, + size_t __count, unsigned int __flags); + +/* Splice two files together. */ +extern ssize_t splice (int __fdin, __off64_t *__offin, int __fdout, + __off64_t *__offout, size_t __len, + unsigned int __flags); + +/* In-kernel implementation of tee for pipe buffers. */ +extern ssize_t tee (int __fdin, int __fdout, size_t __len, + unsigned int __flags); + +#endif +__END_DECLS + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/fenv.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/fenv.h new file mode 100644 index 00000000..d2ef97e0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/fenv.h @@ -0,0 +1,85 @@ +/* Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FENV_H +# error "Never use directly; include instead." +#endif + +#include + + +/* Define bits representing the exception. We use the bit positions + of the appropriate accrued exception bits from the FSR. */ +enum + { + FE_INVALID = (1 << 9), +#define FE_INVALID FE_INVALID + FE_OVERFLOW = (1 << 8), +#define FE_OVERFLOW FE_OVERFLOW + FE_UNDERFLOW = (1 << 7), +#define FE_UNDERFLOW FE_UNDERFLOW + FE_DIVBYZERO = (1 << 6), +#define FE_DIVBYZERO FE_DIVBYZERO + FE_INEXACT = (1 << 5) +#define FE_INEXACT FE_INEXACT + }; + +#define FE_ALL_EXCEPT \ + (FE_INEXACT | FE_DIVBYZERO | FE_UNDERFLOW | FE_OVERFLOW | FE_INVALID) + +/* The Sparc FPU supports all of the four defined rounding modes. We + use again the bit positions in the FPU control word as the values + for the appropriate macros. */ +enum + { + FE_TONEAREST = (0U << 30), +#define FE_TONEAREST FE_TONEAREST + FE_TOWARDZERO = (1U << 30), +#define FE_TOWARDZERO FE_TOWARDZERO + FE_UPWARD = (2U << 30), +#define FE_UPWARD FE_UPWARD + FE_DOWNWARD = (3U << 30) +#define FE_DOWNWARD FE_DOWNWARD + }; + +#define __FE_ROUND_MASK (3U << 30) + + +/* Type representing exception flags. */ +typedef unsigned long int fexcept_t; + + +/* Type representing floating-point environment. */ +typedef unsigned long int fenv_t; + +/* If the default argument is used we use this value. */ +#define FE_DFL_ENV ((__const fenv_t *) -1) + +#ifdef __USE_GNU +/* Floating-point environment where none of the exception is masked. */ +# define FE_NOMASK_ENV ((__const fenv_t *) -2) +#endif + +/* For internal use only: access the fp state register. */ +#if __WORDSIZE == 64 +# define __fenv_stfsr(X) __asm__ ("stx %%fsr,%0" : "=m" (X)) +# define __fenv_ldfsr(X) __asm__ __volatile__ ("ldx %0,%%fsr" : : "m" (X)) +#else +# define __fenv_stfsr(X) __asm__ ("st %%fsr,%0" : "=m" (X)) +# define __fenv_ldfsr(X) __asm__ __volatile__ ("ld %0,%%fsr" : : "m" (X)) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/ioctls.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/ioctls.h new file mode 100644 index 00000000..e86c503f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/ioctls.h @@ -0,0 +1,37 @@ +/* Copyright (C) 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_IOCTL_H +# error "Never use directly; include instead." +#endif + +/* Use the definitions from the kernel header files. */ +#include + +/* Oh well, this is necessary since the kernel data structure is + different from the user-level version. */ +#undef TCGETS +#undef TCSETS +#undef TCSETSW +#undef TCSETSF +#define TCGETS _IOR ('T', 8, char[36]) +#define TCSETS _IOW ('T', 9, char[36]) +#define TCSETSW _IOW ('T', 10, char[36]) +#define TCSETSF _IOW ('T', 11, char[36]) + +#include diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/ipc.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/ipc.h new file mode 100644 index 00000000..988dc125 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/ipc.h @@ -0,0 +1,62 @@ +/* Copyright (C) 1995-1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_IPC_H +# error "Never use directly; include instead." +#endif + +#include +#include + +/* Mode bits for `msgget', `semget', and `shmget'. */ +#define IPC_CREAT 01000 /* Create key if key does not exist. */ +#define IPC_EXCL 02000 /* Fail if key exists. */ +#define IPC_NOWAIT 04000 /* Return error on wait. */ + +/* Control commands for `msgctl', `semctl', and `shmctl'. */ +#define IPC_RMID 0 /* Remove identifier. */ +#define IPC_SET 1 /* Set `ipc_perm' options. */ +#define IPC_STAT 2 /* Get `ipc_perm' options. */ +#ifdef __USE_GNU +# define IPC_INFO 3 /* See ipcs. */ +#endif + +/* Special key values. */ +#define IPC_PRIVATE ((__key_t) 0) /* Private key. */ + + +/* Data structure used to pass permission information to IPC operations. */ +struct ipc_perm + { + __key_t __key; /* Key. */ + __uid_t uid; /* Owner's user ID. */ + __gid_t gid; /* Owner's group ID. */ + __uid_t cuid; /* Creator's user ID. */ + __gid_t cgid; /* Creator's group ID. */ +#if __WORDSIZE == 32 + unsigned short int __pad1; + unsigned short int mode; /* Read/write permission. */ + unsigned short int __pad2; +#else + __mode_t mode; /* Read/write permission. */ + unsigned short int __pad1; +#endif + unsigned short int __seq; /* Sequence number. */ + unsigned long long int __unused1; + unsigned long long int __unused2; + }; diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/kernel_stat.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/kernel_stat.h new file mode 100644 index 00000000..a9b5b534 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/kernel_stat.h @@ -0,0 +1,55 @@ +#ifndef _BITS_STAT_STRUCT_H +#define _BITS_STAT_STRUCT_H + +#ifndef _LIBC +#error bits/kernel_stat.h is for internal uClibc use only! +#endif + +/* This file provides whatever this particular arch's kernel thinks + * struct kernel_stat should look like... It turns out each arch has a + * different opinion on the subject... */ + +#if __WORDSIZE == 64 +#define kernel_stat kernel_stat64 +#else +struct kernel_stat { + unsigned short st_dev; + unsigned long st_ino; + unsigned short st_mode; + short st_nlink; + unsigned short st_uid; + unsigned short st_gid; + unsigned short st_rdev; + long st_size; + struct timespec st_atim; + struct timespec st_mtim; + struct timespec st_ctim; + long st_blksize; + long st_blocks; + unsigned long __unused4[2]; +}; + +#endif + +struct kernel_stat64 { + unsigned long long st_dev; + unsigned long long st_ino; + unsigned int st_mode; + unsigned int st_nlink; + unsigned int st_uid; + unsigned int st_gid; + unsigned long long st_rdev; + unsigned char __pad3[8]; + long long st_size; + unsigned int st_blksize; + unsigned char __pad4[8]; + unsigned int st_blocks; + struct timespec st_atim; + struct timespec st_mtim; + struct timespec st_ctim; + unsigned int __unused4; + unsigned int __unused5; +}; + +#endif /* _BITS_STAT_STRUCT_H */ + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/kernel_types.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/kernel_types.h new file mode 100644 index 00000000..0cc4bc21 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/kernel_types.h @@ -0,0 +1,77 @@ +/* Note that we use the exact same include guard #define names + * as asm/posix_types.h. This will avoid gratuitous conflicts + * with the posix_types.h kernel header, and will ensure that + * our private content, and not the kernel header, will win. + * -Erik + */ +#if ! defined __ARCH_SPARC_POSIX_TYPES_H && ! defined __ARCH_SPARC64_POSIX_TYPES_H && !defined __SPARC_POSIX_TYPES_H +#define __ARCH_SPARC_POSIX_TYPES_H +#define __ARCH_SPARC64_POSIX_TYPES_H +#define __SPARC_POSIX_TYPES_H + +# if __WORDSIZE == 64 +typedef unsigned long __kernel_size_t; +typedef long __kernel_ssize_t; +typedef long __kernel_ptrdiff_t; +typedef long __kernel_time_t; +typedef long __kernel_clock_t; +typedef int __kernel_pid_t; +typedef int __kernel_ipc_pid_t; +typedef unsigned int __kernel_uid_t; +typedef unsigned int __kernel_gid_t; +typedef unsigned int __kernel_dev_t; +typedef unsigned long __kernel_ino_t; +typedef unsigned int __kernel_mode_t; +typedef unsigned short __kernel_umode_t; +typedef unsigned int __kernel_nlink_t; +typedef int __kernel_daddr_t; +typedef long __kernel_off_t; +typedef char * __kernel_caddr_t; +typedef unsigned short __kernel_uid16_t; +typedef unsigned short __kernel_gid16_t; +typedef __kernel_uid_t __kernel_old_uid_t; +typedef __kernel_gid_t __kernel_old_gid_t; +typedef __kernel_dev_t __kernel_old_dev_t; +typedef __kernel_uid_t __kernel_uid32_t; +typedef __kernel_gid_t __kernel_gid32_t; +typedef int __kernel_suseconds_t; +typedef long long __kernel_loff_t; +#else +typedef unsigned int __kernel_size_t; +typedef int __kernel_ssize_t; +typedef long int __kernel_ptrdiff_t; +typedef long __kernel_time_t; +typedef long __kernel_suseconds_t; +typedef long __kernel_clock_t; +typedef int __kernel_pid_t; +typedef unsigned short __kernel_ipc_pid_t; +typedef unsigned short __kernel_uid_t; +typedef unsigned short __kernel_gid_t; +typedef unsigned short __kernel_dev_t; +typedef unsigned long __kernel_ino_t; +typedef unsigned short __kernel_mode_t; +typedef unsigned short __kernel_umode_t; +typedef short __kernel_nlink_t; +typedef long __kernel_daddr_t; +typedef long __kernel_off_t; +typedef char * __kernel_caddr_t; +typedef unsigned short __kernel_uid16_t; +typedef unsigned short __kernel_gid16_t; +typedef unsigned int __kernel_uid32_t; +typedef unsigned int __kernel_gid32_t; +typedef unsigned short __kernel_old_uid_t; +typedef unsigned short __kernel_old_gid_t; +typedef __kernel_dev_t __kernel_old_dev_t; +typedef long long __kernel_loff_t; +#endif + +typedef struct { +#ifdef __USE_ALL + int val[2]; +#else + int __val[2]; +#endif +} __kernel_fsid_t; + +#endif /* ! defined __ARCH_SPARC_POSIX_TYPES_H && ! defined __ARCH_SPARC64_POSIX_TYPES_H */ + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/mathdef.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/mathdef.h new file mode 100644 index 00000000..718d0643 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/mathdef.h @@ -0,0 +1,55 @@ +/* Copyright (C) 1997, 1998, 1999, 2000, 2004, 2006 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#if !defined _MATH_H && !defined _COMPLEX_H +# error "Never use directly; include instead" +#endif + +#include + +/* FIXME! This file describes properties of the compiler, not the machine; + it should not be part of libc! */ + +#if defined __USE_ISOC99 && defined _MATH_H && !defined _MATH_H_MATHDEF +# define _MATH_H_MATHDEF 1 + +/* SPARC has both `float' and `double' arithmetic. */ +typedef float float_t; +typedef double double_t; + +/* The values returned by `ilogb' for 0 and NaN respectively. */ +# define FP_ILOGB0 (-2147483647) +# define FP_ILOGBNAN (2147483647) + +#endif /* ISO C99 */ + +#ifdef L4_DISABLE_LONG_DOUBLE_MATH +#ifndef __NO_LONG_DOUBLE_MATH + +# if __WORDSIZE == 32 +/* Signal that in 32bit ABI we do not really have a `long double'. + The disables the declaration of all the `long double' function + variants. */ +# define __NO_LONG_DOUBLE_MATH 1 +# elif !defined __UCLIBC_HAS_LONG_DOUBLE_MATH__ +# define __NO_LONG_DOUBLE_MATH 1 +# endif + +#endif +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/mathinline.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/mathinline.h new file mode 100644 index 00000000..c774dea9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/mathinline.h @@ -0,0 +1,292 @@ +/* Inline math functions for SPARC. + Copyright (C) 1999, 2000, 2001, 2002, 2004, 2006 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _MATH_H +# error "Never use directly; include instead." +#endif + +#include + +#ifdef __GNUC__ + +#if defined __USE_ISOC99 && !__GNUC_PREREQ (3, 0) +# undef isgreater +# undef isgreaterequal +# undef isless +# undef islessequal +# undef islessgreater +# undef isunordered + +# if __WORDSIZE == 32 + +# ifndef __NO_LONG_DOUBLE_MATH + +# define __unordered_cmp(x, y) \ + (__extension__ \ + ({ unsigned __r; \ + if (sizeof (x) == 4 && sizeof (y) == 4) \ + { \ + float __x = (x); float __y = (y); \ + __asm__ ("fcmps %1,%2; st %%fsr, %0" : "=m" (__r) : "f" (__x), \ + "f" (__y) : "cc"); \ + } \ + else if (sizeof (x) <= 8 && sizeof (y) <= 8) \ + { \ + double __x = (x); double __y = (y); \ + __asm__ ("fcmpd\t%1,%2\n\tst\t%%fsr,%0" : "=m" (__r) : "f" (__x), \ + "f" (__y) : "cc"); \ + } \ + else \ + { \ + long double __x = (x); long double __y = (y); \ + extern int _Q_cmp (const long double a, const long double b); \ + __r = _Q_cmp (__x, __y) << 10; \ + } \ + __r; })) + +# else + +# define __unordered_cmp(x, y) \ + (__extension__ \ + ({ unsigned __r; \ + if (sizeof (x) == 4 && sizeof (y) == 4) \ + { \ + float __x = (x); float __y = (y); \ + __asm__ ("fcmps %1,%2; st %%fsr, %0" : "=m" (__r) : "f" (__x), \ + "f" (__y) : "cc"); \ + } \ + else \ + { \ + double __x = (x); double __y = (y); \ + __asm__ ("fcmpd\t%1,%2\n\tst\t%%fsr,%0" : "=m" (__r) : "f" (__x), \ + "f" (__y) : "cc"); \ + } \ + __r; })) + +# endif + +# define isgreater(x, y) ((__unordered_cmp (x, y) & (3 << 10)) == (2 << 10)) +# define isgreaterequal(x, y) ((__unordered_cmp (x, y) & (1 << 10)) == 0) +# define isless(x, y) ((__unordered_cmp (x, y) & (3 << 10)) == (1 << 10)) +# define islessequal(x, y) ((__unordered_cmp (x, y) & (2 << 10)) == 0) +# define islessgreater(x, y) (((__unordered_cmp (x, y) + (1 << 10)) & (2 << 10)) != 0) +# define isunordered(x, y) ((__unordered_cmp (x, y) & (3 << 10)) == (3 << 10)) + +# else /* sparc64 */ + +# define __unordered_v9cmp(x, y, op, qop) \ + (__extension__ \ + ({ unsigned __r; \ + if (sizeof (x) == 4 && sizeof (y) == 4) \ + { \ + float __x = (x); float __y = (y); \ + __asm__ ("fcmps\t%%fcc3,%1,%2\n\tmov" op "\t%%fcc3,1,%0" \ + : "=r" (__r) : "f" (__x), "f" (__y), "0" (0) : "cc"); \ + } \ + else if (sizeof (x) <= 8 && sizeof (y) <= 8) \ + { \ + double __x = (x); double __y = (y); \ + __asm__ ("fcmpd\t%%fcc3,%1,%2\n\tmov" op "\t%%fcc3,1,%0" \ + : "=r" (__r) : "f" (__x), "f" (__y), "0" (0) : "cc"); \ + } \ + else \ + { \ + long double __x = (x); long double __y = (y); \ + extern int _Qp_cmp (const long double *a, const long double *b); \ + __r = qop; \ + } \ + __r; })) + +# define isgreater(x, y) __unordered_v9cmp(x, y, "g", _Qp_cmp (&__x, &__y) == 2) +# define isgreaterequal(x, y) __unordered_v9cmp(x, y, "ge", (_Qp_cmp (&__x, &__y) & 1) == 0) +# define isless(x, y) __unordered_v9cmp(x, y, "l", _Qp_cmp (&__x, &__y) == 1) +# define islessequal(x, y) __unordered_v9cmp(x, y, "le", (_Qp_cmp (&__x, &__y) & 2) == 0) +# define islessgreater(x, y) __unordered_v9cmp(x, y, "lg", ((_Qp_cmp (&__x, &__y) + 1) & 2) != 0) +# define isunordered(x, y) __unordered_v9cmp(x, y, "u", _Qp_cmp (&__x, &__y) == 3) + +# endif /* sparc64 */ + +#endif /* __USE_ISOC99 */ + +#if (!defined __NO_MATH_INLINES || defined __LIBC_INTERNAL_MATH_INLINES) && defined __OPTIMIZE__ + +# ifdef __cplusplus +# define __MATH_INLINE __inline +# else +# define __MATH_INLINE extern __inline +# endif /* __cplusplus */ + +/* The gcc, version 2.7 or below, has problems with all this inlining + code. So disable it for this version of the compiler. */ +# if __GNUC_PREREQ (2, 8) + +# ifdef __USE_ISOC99 + +/* Test for negative number. Used in the signbit() macro. */ +__MATH_INLINE int +__NTH (__signbitf (float __x)) +{ + __extension__ union { float __f; int __i; } __u = { __f: __x }; + return __u.__i < 0; +} + +# if __WORDSIZE == 32 + +__MATH_INLINE int +__NTH (__signbit (double __x)) +{ + __extension__ union { double __d; int __i[2]; } __u = { __d: __x }; + return __u.__i[0] < 0; +} + +# ifndef __NO_LONG_DOUBLE_MATH +__MATH_INLINE int +__NTH (__signbitl (long double __x)) +{ + __extension__ union { long double __l; int __i[4]; } __u = { __l: __x }; + return __u.__i[0] < 0; +} +# else +__MATH_INLINE int +__NTH (__signbitl (long double __x)) +{ + return __signbit ((double)__x); +} +# endif + +# else /* sparc64 */ + +__MATH_INLINE int +__NTH (__signbit (double __x)) +{ + __extension__ union { double __d; long int __i; } __u = { __d: __x }; + return __u.__i < 0; +} + +__MATH_INLINE int +__NTH (__signbitl (long double __x)) +{ + __extension__ union { long double __l; long int __i[2]; } __u = { __l: __x }; + return __u.__i[0] < 0; +} + +# endif /* sparc64 */ + +# endif /* __USE_ISOC99 */ + +# if !defined __NO_MATH_INLINES && !__GNUC_PREREQ (3, 2) + +__MATH_INLINE double +__NTH (sqrt (double __x)) +{ + register double __r; + __asm__ ("fsqrtd %1,%0" : "=f" (__r) : "f" (__x)); + return __r; +} + +__MATH_INLINE float +__NTH (sqrtf (float __x)) +{ + register float __r; + __asm__ ("fsqrts %1,%0" : "=f" (__r) : "f" (__x)); + return __r; +} + +# if __WORDSIZE == 64 +__MATH_INLINE long double +__NTH (sqrtl (long double __x)) +{ + long double __r; + extern void _Qp_sqrt (long double *, __const__ long double *); + _Qp_sqrt (&__r, &__x); + return __r; +} +# elif !defined __NO_LONG_DOUBLE_MATH +__MATH_INLINE long double +sqrtl (long double __x) __THROW +{ + extern long double _Q_sqrt (__const__ long double); + return _Q_sqrt (__x); +} +# endif /* sparc64 */ + +# endif /* !__NO_MATH_INLINES && !GCC 3.2+ */ + +/* This code is used internally in the GNU libc. */ +# ifdef __LIBC_INTERNAL_MATH_INLINES +__MATH_INLINE double +__ieee754_sqrt (double __x) +{ + register double __r; + __asm__ ("fsqrtd %1,%0" : "=f" (__r) : "f" (__x)); + return __r; +} + +__MATH_INLINE float +__ieee754_sqrtf (float __x) +{ + register float __r; + __asm__ ("fsqrts %1,%0" : "=f" (__r) : "f" (__x)); + return __r; +} + +# if __WORDSIZE == 64 +__MATH_INLINE long double +__ieee754_sqrtl (long double __x) +{ + long double __r; + extern void _Qp_sqrt (long double *, __const__ long double *); + _Qp_sqrt(&__r, &__x); + return __r; +} +# elif !defined __NO_LONG_DOUBLE_MATH +__MATH_INLINE long double +__ieee754_sqrtl (long double __x) +{ + extern long double _Q_sqrt (__const__ long double); + return _Q_sqrt (__x); +} +# endif /* sparc64 */ +# endif /* __LIBC_INTERNAL_MATH_INLINES */ +# endif /* gcc 2.8+ */ + +# ifdef __USE_ISOC99 + +# ifndef __NO_MATH_INLINES + +__MATH_INLINE double __NTH (fdim (double __x, double __y)); +__MATH_INLINE double +__NTH (fdim (double __x, double __y)) +{ + return __x <= __y ? 0 : __x - __y; +} + +__MATH_INLINE float __NTH (fdimf (float __x, float __y)); +__MATH_INLINE float +__NTH (fdimf (float __x, float __y)) +{ + return __x <= __y ? 0 : __x - __y; +} + +# endif /* !__NO_MATH_INLINES */ +# endif /* __USE_ISOC99 */ +#endif /* !__NO_MATH_INLINES && __OPTIMIZE__ */ +#endif /* __GNUC__ */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/mman.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/mman.h new file mode 100644 index 00000000..74921e4c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/mman.h @@ -0,0 +1,108 @@ +/* Definitions for POSIX memory map interface. Linux/SPARC version. + Copyright (C) 1997,1999,2000,2003,2005,2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_MMAN_H +# error "Never use directly; include instead." +#endif + +/* The following definitions basically come from the kernel headers. + But the kernel header is not namespace clean. */ + + +/* Protections are chosen from these bits, OR'd together. The + implementation does not necessarily support PROT_EXEC or PROT_WRITE + without PROT_READ. The only guarantees are that no writing will be + allowed without PROT_WRITE and no access will be allowed for PROT_NONE. */ + +#define PROT_READ 0x1 /* Page can be read. */ +#define PROT_WRITE 0x2 /* Page can be written. */ +#define PROT_EXEC 0x4 /* Page can be executed. */ +#define PROT_NONE 0x0 /* Page can not be accessed. */ +#define PROT_GROWSDOWN 0x01000000 /* Extend change to start of + growsdown vma (mprotect only). */ +#define PROT_GROWSUP 0x02000000 /* Extend change to start of + growsup vma (mprotect only). */ + +/* Sharing types (must choose one and only one of these). */ +#define MAP_SHARED 0x01 /* Share changes. */ +#define MAP_PRIVATE 0x02 /* Changes are private. */ +#ifdef __USE_MISC +# define MAP_TYPE 0x0f /* Mask for type of mapping. */ +#endif + +/* Other flags. */ +#define MAP_FIXED 0x10 /* Interpret addr exactly. */ +#ifdef __USE_MISC +# define MAP_FILE 0x00 +# define MAP_ANONYMOUS 0x20 /* Don't use a file. */ +# define MAP_ANON MAP_ANONYMOUS +# define MAP_RENAME MAP_ANONYMOUS +#endif + +/* These are Linux-specific. */ +#ifdef __USE_MISC +# define MAP_GROWSDOWN 0x0200 /* Stack-like segment. */ +# define MAP_DENYWRITE 0x0800 /* ETXTBSY */ +# define MAP_EXECUTABLE 0x1000 /* Mark it as an executable. */ +# define MAP_LOCKED 0x0100 /* Lock the mapping. */ +# define MAP_NORESERVE 0x0040 /* Don't check for reservations. */ +# define _MAP_NEW 0x80000000 /* Binary compatibility with SunOS. */ +# define MAP_POPULATE 0x8000 /* Populate (prefault) pagetables. */ +# define MAP_NONBLOCK 0x10000 /* Do not block on IO. */ +# define MAP_UNINITIALIZE 0x4000000 /* For anonymous mmap, memory could + be uninitialized. */ +#endif + +/* Flags to `msync'. */ +#define MS_ASYNC 1 /* Sync memory asynchronously. */ +#define MS_SYNC 4 /* Synchronous memory sync. */ +#define MS_INVALIDATE 2 /* Invalidate the caches. */ + +/* Flags for `mlockall'. */ +#define MCL_CURRENT 0x2000 /* Lock all currently mapped pages. */ +#define MCL_FUTURE 0x4000 /* Lock all additions to address + space. */ + +/* Flags for `mremap'. */ +#ifdef __USE_GNU +# define MREMAP_MAYMOVE 1 +# define MREMAP_FIXED 2 +#endif + +/* Advice to `madvise'. */ +#ifdef __USE_BSD +# define MADV_NORMAL 0 /* No further special treatment. */ +# define MADV_RANDOM 1 /* Expect random page references. */ +# define MADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define MADV_WILLNEED 3 /* Will need these pages. */ +# define MADV_DONTNEED 4 /* Don't need these pages. */ +# define MADV_FREE 5 /* Content can be freed (Solaris). */ +# define MADV_REMOVE 9 /* Remove these pages and resources. */ +# define MADV_DONTFORK 10 /* Do not inherit across fork. */ +# define MADV_DOFORK 11 /* Do inherit across fork. */ +#endif + +/* The POSIX people had to invent similar names for the same things. */ +#ifdef __USE_XOPEN2K +# define POSIX_MADV_NORMAL 0 /* No further special treatment. */ +# define POSIX_MADV_RANDOM 1 /* Expect random page references. */ +# define POSIX_MADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define POSIX_MADV_WILLNEED 3 /* Will need these pages. */ +# define POSIX_MADV_DONTNEED 4 /* Don't need these pages. */ +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/msq.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/msq.h new file mode 100644 index 00000000..1268dc85 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/msq.h @@ -0,0 +1,84 @@ +/* Copyright (C) 1995, 1996, 1997, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_MSG_H +# error "Never use directly; include instead." +#endif + +#include +#include + +/* Define options for message queue functions. */ +#define MSG_NOERROR 010000 /* no error if message is too big */ +#ifdef __USE_GNU +# define MSG_EXCEPT 020000 /* recv any msg except of specified type */ +#endif + +/* Types used in the structure definition. */ +typedef unsigned long int msgqnum_t; +typedef unsigned long int msglen_t; + + +/* Structure of record for one message inside the kernel. + The type `struct msg' is opaque. */ +struct msqid_ds +{ + struct ipc_perm msg_perm; /* structure describing operation permission */ +#if __WORDSIZE == 32 + unsigned int __pad1; +#endif + __time_t msg_stime; /* time of last msgsnd command */ +#if __WORDSIZE == 32 + unsigned int __pad2; +#endif + __time_t msg_rtime; /* time of last msgrcv command */ +#if __WORDSIZE == 32 + unsigned int __pad3; +#endif + __time_t msg_ctime; /* time of last change */ + unsigned long int __msg_cbytes; /* current number of bytes on queue */ + msgqnum_t msg_qnum; /* number of messages currently on queue */ + msglen_t msg_qbytes; /* max number of bytes allowed on queue */ + __pid_t msg_lspid; /* pid of last msgsnd() */ + __pid_t msg_lrpid; /* pid of last msgrcv() */ + unsigned long int __unused1; + unsigned long int __unused2; +}; + +#ifdef __USE_MISC + +# define msg_cbytes __msg_cbytes + +/* ipcs ctl commands */ +# define MSG_STAT 11 +# define MSG_INFO 12 + +/* buffer for msgctl calls IPC_INFO, MSG_INFO */ +struct msginfo + { + int msgpool; + int msgmap; + int msgmax; + int msgmnb; + int msgmni; + int msgssz; + int msgtql; + unsigned short int msgseg; + }; + +#endif /* __USE_MISC */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/poll.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/poll.h new file mode 100644 index 00000000..53b94bc5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/poll.h @@ -0,0 +1,50 @@ +/* Copyright (C) 1997, 2001, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_POLL_H +# error "Never use directly; include instead." +#endif + +/* Event types that can be polled for. These bits may be set in `events' + to indicate the interesting event types; they will appear in `revents' + to indicate the status of the file descriptor. */ +#define POLLIN 0x001 /* There is data to read. */ +#define POLLPRI 0x002 /* There is urgent data to read. */ +#define POLLOUT 0x004 /* Writing now will not block. */ + +#ifdef __USE_XOPEN +/* These values are defined in XPG4.2. */ +# define POLLRDNORM 0x040 /* Normal data may be read. */ +# define POLLRDBAND 0x080 /* Priority data may be read. */ +# define POLLWRNORM POLLOUT /* Writing now will not block. */ +# define POLLWRBAND 0x100 /* Priority data may be written. */ +#endif + +#ifdef __USE_GNU +/* These are extensions for Linux. */ +# define POLLMSG 0x200 +# define POLLREMOVE 0x400 +# define POLLRDHUP 0x800 +#endif + +/* Event types always implicitly polled for. These bits need not be set in + `events', but they will appear in `revents' to indicate the status of + the file descriptor. */ +#define POLLERR 0x008 /* Error condition. */ +#define POLLHUP 0x010 /* Hung up. */ +#define POLLNVAL 0x020 /* Invalid polling request. */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/resource.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/resource.h new file mode 100644 index 00000000..3f2c6001 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/resource.h @@ -0,0 +1,241 @@ +/* Bit values & structures for resource limits. Linux/SPARC version. + Copyright (C) 1994, 1996, 1997, 1998, 1999, 2000, 2004, 2005 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_RESOURCE_H +# error "Never use directly; include instead." +#endif + +#include + +/* Transmute defines to enumerations. The macro re-definitions are + necessary because some programs want to test for operating system + features with #ifdef RUSAGE_SELF. In ISO C the reflexive + definition is a no-op. */ + +/* Kinds of resource limit. */ +enum __rlimit_resource +{ + /* Per-process CPU limit, in seconds. */ + RLIMIT_CPU = 0, +#define RLIMIT_CPU RLIMIT_CPU + + /* Largest file that can be created, in bytes. */ + RLIMIT_FSIZE = 1, +#define RLIMIT_FSIZE RLIMIT_FSIZE + + /* Maximum size of data segment, in bytes. */ + RLIMIT_DATA = 2, +#define RLIMIT_DATA RLIMIT_DATA + + /* Maximum size of stack segment, in bytes. */ + RLIMIT_STACK = 3, +#define RLIMIT_STACK RLIMIT_STACK + + /* Largest core file that can be created, in bytes. */ + RLIMIT_CORE = 4, +#define RLIMIT_CORE RLIMIT_CORE + + /* Largest resident set size, in bytes. + This affects swapping; processes that are exceeding their + resident set size will be more likely to have physical memory + taken from them. */ + __RLIMIT_RSS = 5, +#define RLIMIT_RSS __RLIMIT_RSS + + /* Number of open files. */ + RLIMIT_NOFILE = 6, + __RLIMIT_OFILE = RLIMIT_NOFILE, /* BSD name for same. */ +#define RLIMIT_NOFILE RLIMIT_NOFILE +#define RLIMIT_OFILE __RLIMIT_OFILE + + /* Address space limit (?) */ + RLIMIT_AS = 9, +#define RLIMIT_AS RLIMIT_AS + + /* Number of processes. */ + __RLIMIT_NPROC = 7, +#define RLIMIT_NPROC __RLIMIT_NPROC + + /* Locked-in-memory address space. */ + __RLIMIT_MEMLOCK = 8, +#define RLIMIT_MEMLOCK __RLIMIT_MEMLOCK + + /* Maximum number of file locks. */ + __RLIMIT_LOCKS = 10, +#define RLIMIT_LOCKS __RLIMIT_LOCKS + + /* Maximum number of pending signals. */ + __RLIMIT_SIGPENDING = 11, +#define RLIMIT_SIGPENDING __RLIMIT_SIGPENDING + + /* Maximum bytes in POSIX message queues. */ + __RLIMIT_MSGQUEUE = 12, +#define RLIMIT_MSGQUEUE __RLIMIT_MSGQUEUE + + /* Maximum nice priority allowed to raise to. + Nice levels 19 .. -20 correspond to 0 .. 39 + values of this resource limit. */ + __RLIMIT_NICE = 13, +#define RLIMIT_NICE __RLIMIT_NICE + + /* Maximum realtime priority allowed for non-priviledged + processes. */ + __RLIMIT_RTPRIO = 14, +#define RLIMIT_RTPRIO __RLIMIT_RTPRIO + + __RLIMIT_NLIMITS = 15, + __RLIM_NLIMITS = __RLIMIT_NLIMITS +#define RLIMIT_NLIMITS __RLIMIT_NLIMITS +#define RLIM_NLIMITS __RLIM_NLIMITS +}; + +/* Value to indicate that there is no limit. */ +#if __WORDSIZE == 64 + +#ifndef __USE_FILE_OFFSET64 +# define RLIM_INFINITY ((unsigned long int)(~0UL)) +#else +# define RLIM_INFINITY 0xffffffffffffffffuLL +#endif + +#ifdef __USE_LARGEFILE64 +# define RLIM64_INFINITY 0xffffffffffffffffuLL +#endif + +#else + +#ifndef __USE_FILE_OFFSET64 +# define RLIM_INFINITY ((long int)(~0UL >> 1)) +#else +# define RLIM_INFINITY 0x7fffffffffffffffLL +#endif + +#ifdef __USE_LARGEFILE64 +# define RLIM64_INFINITY 0x7fffffffffffffffLL +#endif + +#endif + +/* We can represent all limits. */ +#define RLIM_SAVED_MAX RLIM_INFINITY +#define RLIM_SAVED_CUR RLIM_INFINITY + + +/* Type for resource quantity measurement. */ +#ifndef __USE_FILE_OFFSET64 +typedef __rlim_t rlim_t; +#else +typedef __rlim64_t rlim_t; +#endif +#ifdef __USE_LARGEFILE64 +typedef __rlim64_t rlim64_t; +#endif + +struct rlimit + { + /* The current (soft) limit. */ + rlim_t rlim_cur; + /* The hard limit. */ + rlim_t rlim_max; + }; + +#ifdef __USE_LARGEFILE64 +struct rlimit64 + { + /* The current (soft) limit. */ + rlim64_t rlim_cur; + /* The hard limit. */ + rlim64_t rlim_max; + }; +#endif + +/* Whose usage statistics do you want? */ +enum __rusage_who +{ + /* The calling process. */ + RUSAGE_SELF = 0, +#define RUSAGE_SELF RUSAGE_SELF + + /* All of its terminated child processes. */ + RUSAGE_CHILDREN = -1 +#define RUSAGE_CHILDREN RUSAGE_CHILDREN +}; + +#define __need_timeval +#include /* For `struct timeval'. */ + +/* Structure which says how much of each resource has been used. */ +struct rusage + { + /* Total amount of user time used. */ + struct timeval ru_utime; + /* Total amount of system time used. */ + struct timeval ru_stime; + /* Maximum resident set size (in kilobytes). */ + long int ru_maxrss; + /* Amount of sharing of text segment memory + with other processes (kilobyte-seconds). */ + long int ru_ixrss; + /* Amount of data segment memory used (kilobyte-seconds). */ + long int ru_idrss; + /* Amount of stack memory used (kilobyte-seconds). */ + long int ru_isrss; + /* Number of soft page faults (i.e. those serviced by reclaiming + a page from the list of pages awaiting reallocation. */ + long int ru_minflt; + /* Number of hard page faults (i.e. those that required I/O). */ + long int ru_majflt; + /* Number of times a process was swapped out of physical memory. */ + long int ru_nswap; + /* Number of input operations via the file system. Note: This + and `ru_oublock' do not include operations with the cache. */ + long int ru_inblock; + /* Number of output operations via the file system. */ + long int ru_oublock; + /* Number of IPC messages sent. */ + long int ru_msgsnd; + /* Number of IPC messages received. */ + long int ru_msgrcv; + /* Number of signals delivered. */ + long int ru_nsignals; + /* Number of voluntary context switches, i.e. because the process + gave up the process before it had to (usually to wait for some + resource to be available). */ + long int ru_nvcsw; + /* Number of involuntary context switches, i.e. a higher priority process + became runnable or the current process used up its time slice. */ + long int ru_nivcsw; + }; + +/* Priority limits. */ +#define PRIO_MIN -20 /* Minimum priority a process can have. */ +#define PRIO_MAX 20 /* Maximum priority a process can have. */ + +/* The type of the WHICH argument to `getpriority' and `setpriority', + indicating what flavor of entity the WHO argument specifies. */ +enum __priority_which +{ + PRIO_PROCESS = 0, /* WHO is a process ID. */ +#define PRIO_PROCESS PRIO_PROCESS + PRIO_PGRP = 1, /* WHO is a process group ID. */ +#define PRIO_PGRP PRIO_PGRP + PRIO_USER = 2 /* WHO is a user ID. */ +#define PRIO_USER PRIO_USER +}; diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/sem.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/sem.h new file mode 100644 index 00000000..28807651 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/sem.h @@ -0,0 +1,92 @@ +/* Copyright (C) 1995, 1996, 1997, 1998, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_SEM_H +# error "Never include directly; use instead." +#endif + +#include +#include + +/* Flags for `semop'. */ +#define SEM_UNDO 0x1000 /* undo the operation on exit */ + +/* Commands for `semctl'. */ +#define GETPID 11 /* get sempid */ +#define GETVAL 12 /* get semval */ +#define GETALL 13 /* get all semval's */ +#define GETNCNT 14 /* get semncnt */ +#define GETZCNT 15 /* get semzcnt */ +#define SETVAL 16 /* set semval */ +#define SETALL 17 /* set all semval's */ + + +/* Data structure describing a set of semaphores. */ +struct semid_ds +{ + struct ipc_perm sem_perm; /* operation permission struct */ +#if __WORDSIZE == 32 + unsigned int __pad1; +#endif + __time_t sem_otime; /* last semop() time */ +#if __WORDSIZE == 32 + unsigned int __pad2; +#endif + __time_t sem_ctime; /* last time changed by semctl() */ + unsigned long int sem_nsems; /* number of semaphores in set */ + unsigned long int __unused1; + unsigned long int __unused2; +}; + +/* The user should define a union like the following to use it for arguments + for `semctl'. + + union semun + { + int val; <= value for SETVAL + struct semid_ds *buf; <= buffer for IPC_STAT & IPC_SET + unsigned short int *array; <= array for GETALL & SETALL + struct seminfo *__buf; <= buffer for IPC_INFO + }; + + Previous versions of this file used to define this union but this is + incorrect. One can test the macro _SEM_SEMUN_UNDEFINED to see whether + one must define the union or not. */ +#define _SEM_SEMUN_UNDEFINED 1 + +#ifdef __USE_MISC + +/* ipcs ctl cmds */ +# define SEM_STAT 18 +# define SEM_INFO 19 + +struct seminfo +{ + int semmap; + int semmni; + int semmns; + int semmnu; + int semmsl; + int semopm; + int semume; + int semusz; + int semvmx; + int semaem; +}; + +#endif /* __USE_MISC */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/setjmp.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/setjmp.h new file mode 100644 index 00000000..ac5a4b2d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/setjmp.h @@ -0,0 +1,84 @@ +/* Copyright (C) 1997,1999,2000,2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _BITS_SETJMP_H +#define _BITS_SETJMP_H 1 + +#if !defined _SETJMP_H && !defined _PTHREAD_H +# error "Never include directly; use instead." +#endif + +#include + +#if 0 /*__WORDSIZE == 64*/ + +#ifndef _ASM +typedef struct __sparc64_jmp_buf + { + struct __sparc64_jmp_buf *uc_link; + unsigned long uc_flags; + unsigned long uc_sigmask; + struct __sparc64_jmp_buf_mcontext + { + unsigned long mc_gregs[19]; + unsigned long mc_fp; + unsigned long mc_i7; + struct __sparc64_jmp_buf_fpu + { + union + { + unsigned int sregs[32]; + unsigned long dregs[32]; + long double qregs[16]; + } mcfpu_fpregs; + unsigned long mcfpu_fprs; + unsigned long mcfpu_gsr; + void *mcfpu_fq; + unsigned char mcfpu_qcnt; + unsigned char mcfpu_qentsz; + unsigned char mcfpu_enab; + } mc_fpregs; + } uc_mcontext; + } __jmp_buf[1]; +#endif + +/* Test if longjmp to JMPBUF would unwind the frame + containing a local variable at ADDRESS. */ +#define _JMPBUF_UNWINDS(jmpbuf, address) \ + ((unsigned long int) (address) < (jmpbuf)->uc_mcontext.mc_fp) + +#else + +#if defined __USE_MISC || defined _ASM +# define JB_SP 0 +# define JB_FP 1 +# define JB_PC 2 +#endif + +#ifndef _ASM +typedef int __jmp_buf[3]; +#endif + +/* Test if longjmp to JMPBUF would unwind the frame + containing a local variable at ADDRESS. */ +#define _JMPBUF_UNWINDS(jmpbuf, address) \ + ((int) (address) < (jmpbuf)[JB_SP]) + +#endif + +#endif /* bits/setjmp.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/shm.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/shm.h new file mode 100644 index 00000000..03decb11 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/shm.h @@ -0,0 +1,111 @@ +/* Copyright (C) 1995, 1996, 1997, 2000, 2002, 2004 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_SHM_H +# error "Never include directly; use instead." +#endif + +#include +#include + +/* Permission flag for shmget. */ +#define SHM_R 0400 /* or S_IRUGO from */ +#define SHM_W 0200 /* or S_IWUGO from */ + +/* Flags for `shmat'. */ +#define SHM_RDONLY 010000 /* attach read-only else read-write */ +#define SHM_RND 020000 /* round attach address to SHMLBA */ +#define SHM_REMAP 040000 /* take-over region on attach */ + +/* Commands for `shmctl'. */ +#define SHM_LOCK 11 /* lock segment (root only) */ +#define SHM_UNLOCK 12 /* unlock segment (root only) */ + +__BEGIN_DECLS + +/* Segment low boundary address multiple. */ +#define SHMLBA (__getpagesize ()) +extern int __getpagesize (void) __THROW __attribute__ ((__const__)); + + +/* Type to count number of attaches. */ +typedef unsigned long int shmatt_t; + +/* Data structure describing a set of semaphores. */ +struct shmid_ds + { + struct ipc_perm shm_perm; /* operation permission struct */ +#if __WORDSIZE == 32 + unsigned int __pad1; +#endif + __time_t shm_atime; /* time of last shmat() */ +#if __WORDSIZE == 32 + unsigned int __pad2; +#endif + __time_t shm_dtime; /* time of last shmdt() */ +#if __WORDSIZE == 32 + unsigned int __pad3; +#endif + __time_t shm_ctime; /* time of last change by shmctl() */ + size_t shm_segsz; /* size of segment in bytes */ + __pid_t shm_cpid; /* pid of creator */ + __pid_t shm_lpid; /* pid of last shmop */ + shmatt_t shm_nattch; /* number of current attaches */ + unsigned long int __unused1; + unsigned long int __unused2; + }; + +#ifdef __USE_MISC + +/* ipcs ctl commands */ +# define SHM_STAT 13 +# define SHM_INFO 14 + +/* shm_mode upper byte flags */ +# define SHM_DEST 01000 /* segment will be destroyed on last detach */ +# define SHM_LOCKED 02000 /* segment will not be swapped */ +# define SHM_HUGETLB 04000 /* segment is mapped via hugetlb */ +# define SHM_NORESERVE 010000 /* don't check for reservations */ + +struct shminfo + { + unsigned long shmmax; + unsigned long shmmin; + unsigned long shmmni; + unsigned long shmseg; + unsigned long shmall; + unsigned long __unused1; + unsigned long __unused2; + unsigned long __unused3; + unsigned long __unused4; + }; + +struct shm_info + { + int used_ids; + unsigned long int shm_tot; /* total allocated shm */ + unsigned long int shm_rss; /* total resident shm */ + unsigned long int shm_swp; /* total swapped shm */ + unsigned long int swap_attempts; + unsigned long int swap_successes; + }; + +#endif /* __USE_MISC */ + +__END_DECLS diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/sigaction.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/sigaction.h new file mode 100644 index 00000000..be9bc028 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/sigaction.h @@ -0,0 +1,64 @@ +/* The proper definitions for Linux/SPARC sigaction. + Copyright (C) 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SIGNAL_H +# error "Never include directly; use instead." +#endif + +/* Structure describing the action to be taken when a signal arrives. */ +struct sigaction { +#ifdef __USE_POSIX199309 + union { + __sighandler_t sa_handler; + void (*sa_sigaction)(int, siginfo_t *, void *); + } __sigaction_handler; +# define sa_handler __sigaction_handler.sa_handler +# define sa_sigaction __sigaction_handler.sa_sigaction +#else + __sighandler_t sa_handler; +#endif + unsigned long sa_flags; + void (*sa_restorer)(void); + sigset_t sa_mask; +}; + + +/* Bits in `sa_flags'. */ +#define SA_NOCLDSTOP 0x00000008 /* Don't send SIGCHLD when children stop. */ +#define SA_NOCLDWAIT 0x00000100 /* Don't create zombie on child death. */ +#define SA_SIGINFO 0x00000200 /* Invoke signal-catching function with + three arguments instead of one. */ +#if defined __USE_UNIX98 || defined __USE_MISC +# define SA_ONSTACK 0x00000001 /* Use signal stack by using `sa_restorer'. */ +# define SA_RESTART 0x00000002 /* Restart syscall on signal return. */ +# define SA_INTERRUPT 0x00000010 /* Historical no-op. */ +# define SA_NOMASK 0x00000020 /* Don't automatically block the signal when + its handler is being executed. */ +# define SA_ONESHOT 0x00000004 /* Reset to SIG_DFL on entry to handler. */ + +/* Some aliases for the SA_ constants. */ +# define SA_NODEFER SA_NOMASK +# define SA_RESETHAND SA_ONESHOT +# define SA_STACK SA_ONSTACK +#endif + +/* Values for the HOW argument to `sigprocmask'. */ +#define SIG_BLOCK 1 /* Block signals. */ +#define SIG_UNBLOCK 2 /* Unblock signals. */ +#define SIG_SETMASK 4 /* Set the set of blocked signals. */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/sigcontext.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/sigcontext.h new file mode 100644 index 00000000..42eca544 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/sigcontext.h @@ -0,0 +1,78 @@ +/* Copyright (C) 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#if !defined _SIGNAL_H && !defined _SYS_UCONTEXT_H +# error "Never use directly; include instead." +#endif + +#include + +#if __WORDSIZE == 32 + +/* It is quite hard to choose what to put here, because + Linux/sparc32 had at least 3 totally incompatible + signal stack layouts. + This one is for the "new" style signals, which are + now delivered unless SA_SIGINFO is requested. */ + +struct sigcontext + { + struct + { + unsigned int psr; + unsigned int pc; + unsigned int npc; + unsigned int y; + unsigned int u_regs[16]; /* globals and ins */ + } si_regs; + int si_mask; + }; + +#else /* sparc64 */ + +typedef struct + { + unsigned int si_float_regs [64]; + unsigned long si_fsr; + unsigned long si_gsr; + unsigned long si_fprs; + } __siginfo_fpu_t; + +struct sigcontext + { + char sigc_info[128]; + struct + { + unsigned long u_regs[16]; /* globals and ins */ + unsigned long tstate; + unsigned long tpc; + unsigned long tnpc; + unsigned int y; + unsigned int fprs; + } sigc_regs; + __siginfo_fpu_t * sigc_fpu_save; + struct + { + void * ss_sp; + int ss_flags; + unsigned long ss_size; + } sigc_stack; + unsigned long sigc_mask; +}; + +#endif /* sparc64 */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/sigcontextinfo.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/sigcontextinfo.h new file mode 100644 index 00000000..2c2770d0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/sigcontextinfo.h @@ -0,0 +1,29 @@ +/* Copyright (C) 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define SIGCONTEXT struct sigcontext * +#define SIGCONTEXT_EXTRA_ARGS +#define GET_PC(__ctx) ((void *) ((__ctx)->si_regs.pc)) +#define ADVANCE_STACK_FRAME(__next) \ + ((void *) (((unsigned *)(__next))+14)) + +#define GET_STACK(__ctx) ((void *) (__ctx)->si_regs.u_regs[14]) +#define GET_FRAME(__ctx) ADVANCE_STACK_FRAME (GET_STACK(__ctx)) +#define CALL_SIGHANDLER(handler, signo, ctx) \ + (handler)((signo), SIGCONTEXT_EXTRA_ARGS (ctx)) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/siginfo.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/siginfo.h new file mode 100644 index 00000000..7ff1971c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/siginfo.h @@ -0,0 +1,318 @@ +/* siginfo_t, sigevent and constants. Linux/SPARC version. + Copyright (C) 1997-2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#if !defined _SIGNAL_H && !defined __need_siginfo_t \ + && !defined __need_sigevent_t +# error "Never include this file directly. Use instead" +#endif + +#include + +#if (!defined __have_sigval_t \ + && (defined _SIGNAL_H || defined __need_siginfo_t \ + || defined __need_sigevent_t)) +# define __have_sigval_t 1 + +/* Type for data associated with a signal. */ +typedef union sigval + { + int sival_int; + void *sival_ptr; + } sigval_t; +#endif + +#if (!defined __have_siginfo_t \ + && (defined _SIGNAL_H || defined __need_siginfo_t)) +# define __have_siginfo_t 1 + +# define __SI_MAX_SIZE 128 +# if __WORDSIZE == 64 +# define __SI_PAD_SIZE ((__SI_MAX_SIZE / sizeof (int)) - 4) +# else +# define __SI_PAD_SIZE ((__SI_MAX_SIZE / sizeof (int)) - 3) +# endif + +typedef struct siginfo + { + int si_signo; /* Signal number. */ + int si_errno; /* If non-zero, an errno value associated with + this signal, as defined in . */ + int si_code; /* Signal code. */ + + union + { + int _pad[__SI_PAD_SIZE]; + + /* kill(). */ + struct + { + __pid_t si_pid; /* Sending process ID. */ + __uid_t si_uid; /* Real user ID of sending process. */ + } _kill; + + /* POSIX.1b timers. */ + struct + { + int si_tid; /* Timer ID. */ + int si_overrun; /* Overrun count. */ + sigval_t si_sigval; /* Signal value. */ + } _timer; + + /* POSIX.1b signals. */ + struct + { + __pid_t si_pid; /* Sending process ID. */ + __uid_t si_uid; /* Real user ID of sending process. */ + sigval_t si_sigval; /* Signal value. */ + } _rt; + + /* SIGCHLD. */ + struct + { + __pid_t si_pid; /* Which child. */ + __uid_t si_uid; /* Real user ID of sending process. */ + int si_status; /* Exit value or signal. */ + __clock_t si_utime; + __clock_t si_stime; + } _sigchld; + + /* SIGILL, SIGFPE, SIGSEGV, SIGBUS. */ + struct + { + void *si_addr; /* Faulting insn/memory ref. */ + int si_trapno; + } _sigfault; + + /* SIGPOLL. */ + struct + { + int si_band; /* Band event for SIGPOLL. */ + int si_fd; + } _sigpoll; + } _sifields; + } siginfo_t; + + +/* X/Open requires some more fields with fixed names. */ +# define si_pid _sifields._kill.si_pid +# define si_uid _sifields._kill.si_uid +# define si_timerid _sifields._timer.si_tid +# define si_overrun _sifields._timer.si_overrun +# define si_status _sifields._sigchld.si_status +# define si_utime _sifields._sigchld.si_utime +# define si_stime _sifields._sigchld.si_stime +# define si_value _sifields._rt.si_sigval +# define si_int _sifields._rt.si_sigval.sival_int +# define si_ptr _sifields._rt.si_sigval.sival_ptr +# define si_addr _sifields._sigfault.si_addr +# define si_trapno _sifields._sigfault.si_trapno +# define si_band _sifields._sigpoll.si_band +# define si_fd _sifields._sigpoll.si_fd + + +/* Values for `si_code'. Positive values are reserved for kernel-generated + signals. */ +enum +{ + SI_ASYNCNL = -60, /* Sent by asynch name lookup completion. */ +# define SI_ASYNCNL SI_ASYNCNL + SI_TKILL = -6, /* Sent by tkill. */ +# define SI_TKILL SI_TKILL + SI_SIGIO, /* Sent by queued SIGIO. */ +# define SI_SIGIO SI_SIGIO + SI_ASYNCIO, /* Sent by AIO completion. */ +# define SI_ASYNCIO SI_ASYNCIO + SI_MESGQ, /* Sent by real time mesq state change. */ +# define SI_MESGQ SI_MESGQ + SI_TIMER, /* Sent by timer expiration. */ +# define SI_TIMER SI_TIMER + SI_QUEUE, /* Sent by sigqueue. */ +# define SI_QUEUE SI_QUEUE + SI_USER, /* Sent by kill, sigsend, raise. */ +# define SI_USER SI_USER + SI_KERNEL = 0x80 /* Send by kernel. */ +#define SI_KERNEL SI_KERNEL +}; + + +/* `si_code' values for SIGILL signal. */ +enum +{ + ILL_ILLOPC = 1, /* Illegal opcode. */ +# define ILL_ILLOPC ILL_ILLOPC + ILL_ILLOPN, /* Illegal operand. */ +# define ILL_ILLOPN ILL_ILLOPN + ILL_ILLADR, /* Illegal addressing mode. */ +# define ILL_ILLADR ILL_ILLADR + ILL_ILLTRP, /* Illegal trap. */ +# define ILL_ILLTRP ILL_ILLTRP + ILL_PRVOPC, /* Privileged opcode. */ +# define ILL_PRVOPC ILL_PRVOPC + ILL_PRVREG, /* Privileged register. */ +# define ILL_PRVREG ILL_PRVREG + ILL_COPROC, /* Coprocessor error. */ +# define ILL_COPROC ILL_COPROC + ILL_BADSTK /* Internal stack error. */ +# define ILL_BADSTK ILL_BADSTK +}; + +/* `si_code' values for SIGFPE signal. */ +enum +{ + FPE_INTDIV = 1, /* Integer divide by zero. */ +# define FPE_INTDIV FPE_INTDIV + FPE_INTOVF, /* Integer overflow. */ +# define FPE_INTOVF FPE_INTOVF + FPE_FLTDIV, /* Floating point divide by zero. */ +# define FPE_FLTDIV FPE_FLTDIV + FPE_FLTOVF, /* Floating point overflow. */ +# define FPE_FLTOVF FPE_FLTOVF + FPE_FLTUND, /* Floating point underflow. */ +# define FPE_FLTUND FPE_FLTUND + FPE_FLTRES, /* Floating point inexact result. */ +# define FPE_FLTRES FPE_FLTRES + FPE_FLTINV, /* Floating point invalid operation. */ +# define FPE_FLTINV FPE_FLTINV + FPE_FLTSUB /* Subscript out of range. */ +# define FPE_FLTSUB FPE_FLTSUB +}; + +/* `si_code' values for SIGSEGV signal. */ +enum +{ + SEGV_MAPERR = 1, /* Address not mapped to object. */ +# define SEGV_MAPERR SEGV_MAPERR + SEGV_ACCERR /* Invalid permissions for mapped object. */ +# define SEGV_ACCERR SEGV_ACCERR +}; + +/* `si_code' values for SIGBUS signal. */ +enum +{ + BUS_ADRALN = 1, /* Invalid address alignment. */ +# define BUS_ADRALN BUS_ADRALN + BUS_ADRERR, /* Non-existant physical address. */ +# define BUS_ADRERR BUS_ADRERR + BUS_OBJERR /* Object specific hardware error. */ +# define BUS_OBJERR BUS_OBJERR +}; + +/* `si_code' values for SIGTRAP signal. */ +enum +{ + TRAP_BRKPT = 1, /* Process breakpoint. */ +# define TRAP_BRKPT TRAP_BRKPT + TRAP_TRACE /* Process trace trap. */ +# define TRAP_TRACE TRAP_TRACE +}; + +/* `si_code' values for SIGCHLD signal. */ +enum +{ + CLD_EXITED = 1, /* Child has exited. */ +# define CLD_EXITED CLD_EXITED + CLD_KILLED, /* Child was killed. */ +# define CLD_KILLED CLD_KILLED + CLD_DUMPED, /* Child terminated abnormally. */ +# define CLD_DUMPED CLD_DUMPED + CLD_TRAPPED, /* Traced child has trapped. */ +# define CLD_TRAPPED CLD_TRAPPED + CLD_STOPPED, /* Child has stopped. */ +# define CLD_STOPPED CLD_STOPPED + CLD_CONTINUED /* Stopped child has continued. */ +# define CLD_CONTINUED CLD_CONTINUED +}; + +/* `si_code' values for SIGPOLL signal. */ +enum +{ + POLL_IN = 1, /* Data input available. */ +# define POLL_IN POLL_IN + POLL_OUT, /* Output buffers available. */ +# define POLL_OUT POLL_OUT + POLL_MSG, /* Input message available. */ +# define POLL_MSG POLL_MSG + POLL_ERR, /* I/O error. */ +# define POLL_ERR POLL_ERR + POLL_PRI, /* High priority input available. */ +# define POLL_PRI POLL_PRI + POLL_HUP /* Device disconnected. */ +# define POLL_HUP POLL_HUP +}; + +/* `si_code' values for SIGEMT signal. */ +enum +{ + EMT_TAGOVF = 1 /* Tag overflow. */ +# define EMT_TAGOVF EMT_TAGOVF +}; + +# undef __need_siginfo_t +#endif /* !have siginfo_t && (have _SIGNAL_H || need siginfo_t). */ + + +#if (defined _SIGNAL_H || defined __need_sigevent_t) \ + && !defined __have_sigevent_t +# define __have_sigevent_t 1 + +/* Structure to transport application-defined values with signals. */ +# define __SIGEV_MAX_SIZE 64 +# if __WORDSIZE == 64 +# define __SIGEV_PAD_SIZE ((__SIGEV_MAX_SIZE / sizeof (int)) - 4) +# else +# define __SIGEV_PAD_SIZE ((__SIGEV_MAX_SIZE / sizeof (int)) - 3) +# endif + +typedef struct sigevent + { + sigval_t sigev_value; + int sigev_signo; + int sigev_notify; + + union + { + int _pad[__SIGEV_PAD_SIZE]; + + struct + { + void (*_function) (sigval_t); /* Function to start. */ + void *_attribute; /* Really pthread_attr_t. */ + } _sigev_thread; + } _sigev_un; + } sigevent_t; + +/* POSIX names to access some of the members. */ +# define sigev_notify_function _sigev_un._sigev_thread._function +# define sigev_notify_attributes _sigev_un._sigev_thread._attribute + +/* `sigev_notify' values. */ +enum +{ + SIGEV_SIGNAL = 0, /* Notify via signal. */ +# define SIGEV_SIGNAL SIGEV_SIGNAL + SIGEV_NONE, /* Other notification: meaningless. */ +# define SIGEV_NONE SIGEV_NONE + SIGEV_THREAD, /* Deliver via thread creation. */ +# define SIGEV_THREAD SIGEV_THREAD + + SIGEV_THREAD_ID = 4 /* Send signal to specific thread. */ +#define SIGEV_THREAD_ID SIGEV_THREAD_ID +}; + +#endif /* have _SIGNAL_H. */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/signum.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/signum.h new file mode 100644 index 00000000..2dcbb3ca --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/signum.h @@ -0,0 +1,64 @@ +/* Signal number definitions. Linux/SPARC version. + Copyright (C) 1996, 1997, 1998, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifdef _SIGNAL_H + +/* + * Linux/SPARC has different signal numbers that Linux/i386: I'm trying + * to make it OSF/1 binary compatible, at least for normal binaries. + */ +#define SIGHUP 1 +#define SIGINT 2 +#define SIGQUIT 3 +#define SIGILL 4 +#define SIGTRAP 5 +#define SIGABRT 6 +#define SIGIOT 6 +#define SIGEMT 7 +#define SIGFPE 8 +#define SIGKILL 9 +#define SIGBUS 10 +#define SIGSEGV 11 +#define SIGSYS 12 +#define SIGPIPE 13 +#define SIGALRM 14 +#define SIGTERM 15 +#define SIGURG 16 + +/* SunOS values which deviate from the Linux/i386 ones */ +#define SIGSTOP 17 +#define SIGTSTP 18 +#define SIGCONT 19 +#define SIGCHLD 20 +#define SIGCLD SIGCHLD /* Same as SIGCHLD (System V). */ +#define SIGTTIN 21 +#define SIGTTOU 22 +#define SIGIO 23 +#define SIGPOLL SIGIO /* SysV name for SIGIO */ +#define SIGXCPU 24 +#define SIGXFSZ 25 +#define SIGVTALRM 26 +#define SIGPROF 27 +#define SIGWINCH 28 +#define SIGLOST 29 +#define SIGPWR SIGLOST +#define SIGUSR1 30 +#define SIGUSR2 31 + +#endif /* included. */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/sigstack.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/sigstack.h new file mode 100644 index 00000000..df465394 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/sigstack.h @@ -0,0 +1,55 @@ +/* sigstack, sigaltstack definitions. + Copyright (C) 1998, 1999, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SIGNAL_H +# error "Never include this file directly. Use instead" +#endif + + +/* Structure describing a signal stack (obsolete). */ +struct sigstack + { + void *ss_sp; /* Signal stack pointer. */ + int ss_onstack; /* Nonzero if executing on this stack. */ + }; + + +/* Possible values for `ss_flags.'. */ +enum +{ + SS_ONSTACK = 1, +#define SS_ONSTACK SS_ONSTACK + SS_DISABLE +#define SS_DISABLE SS_DISABLE +}; + +/* Minimum stack size for a signal handler. */ +#define MINSIGSTKSZ 4096 + +/* System default stack size. */ +#define SIGSTKSZ 16384 + + +/* Alternate, preferred interface. */ +typedef struct sigaltstack + { + void *ss_sp; + int ss_flags; + size_t ss_size; + } stack_t; diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/socket.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/socket.h new file mode 100644 index 00000000..e41527fd --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/socket.h @@ -0,0 +1,356 @@ +/* System-specific socket constants and types. Linux version. + Copyright (C) 1991,1992,1994-2001,2004,2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef __BITS_SOCKET_H +#define __BITS_SOCKET_H + +#if !defined _SYS_SOCKET_H && !defined _NETINET_IN_H +# error "Never include directly; use instead." +#endif + +#define __need_size_t +#define __need_NULL +#include + +#include +#include + +/* Type for length arguments in socket calls. */ +#ifndef __socklen_t_defined +typedef __socklen_t socklen_t; +# define __socklen_t_defined +#endif + +/* Types of sockets. */ +enum __socket_type +{ + SOCK_STREAM = 1, /* Sequenced, reliable, connection-based + byte streams. */ +#define SOCK_STREAM SOCK_STREAM + SOCK_DGRAM = 2, /* Connectionless, unreliable datagrams + of fixed maximum length. */ +#define SOCK_DGRAM SOCK_DGRAM + SOCK_RAW = 3, /* Raw protocol interface. */ +#define SOCK_RAW SOCK_RAW + SOCK_RDM = 4, /* Reliably-delivered messages. */ +#define SOCK_RDM SOCK_RDM + SOCK_SEQPACKET = 5, /* Sequenced, reliable, connection-based, + datagrams of fixed maximum length. */ +#define SOCK_SEQPACKET SOCK_SEQPACKET + SOCK_PACKET = 10 /* Linux specific way of getting packets + at the dev level. For writing rarp and + other similar things on the user level. */ +#define SOCK_PACKET SOCK_PACKET +}; + +/* Protocol families. */ +#define PF_UNSPEC 0 /* Unspecified. */ +#define PF_LOCAL 1 /* Local to host (pipes and file-domain). */ +#define PF_UNIX PF_LOCAL /* Old BSD name for PF_LOCAL. */ +#define PF_FILE PF_LOCAL /* Another non-standard name for PF_LOCAL. */ +#define PF_INET 2 /* IP protocol family. */ +#define PF_AX25 3 /* Amateur Radio AX.25. */ +#define PF_IPX 4 /* Novell Internet Protocol. */ +#define PF_APPLETALK 5 /* Appletalk DDP. */ +#define PF_NETROM 6 /* Amateur radio NetROM. */ +#define PF_BRIDGE 7 /* Multiprotocol bridge. */ +#define PF_ATMPVC 8 /* ATM PVCs. */ +#define PF_X25 9 /* Reserved for X.25 project. */ +#define PF_INET6 10 /* IP version 6. */ +#define PF_ROSE 11 /* Amateur Radio X.25 PLP. */ +#define PF_DECnet 12 /* Reserved for DECnet project. */ +#define PF_NETBEUI 13 /* Reserved for 802.2LLC project. */ +#define PF_SECURITY 14 /* Security callback pseudo AF. */ +#define PF_KEY 15 /* PF_KEY key management API. */ +#define PF_NETLINK 16 +#define PF_ROUTE PF_NETLINK /* Alias to emulate 4.4BSD. */ +#define PF_PACKET 17 /* Packet family. */ +#define PF_ASH 18 /* Ash. */ +#define PF_ECONET 19 /* Acorn Econet. */ +#define PF_ATMSVC 20 /* ATM SVCs. */ +#define PF_SNA 22 /* Linux SNA Project */ +#define PF_IRDA 23 /* IRDA sockets. */ +#define PF_PPPOX 24 /* PPPoX sockets. */ +#define PF_WANPIPE 25 /* Wanpipe API sockets. */ +#define PF_BLUETOOTH 31 /* Bluetooth sockets. */ +#define PF_MAX 32 /* For now.. */ + +/* Address families. */ +#define AF_UNSPEC PF_UNSPEC +#define AF_LOCAL PF_LOCAL +#define AF_UNIX PF_UNIX +#define AF_FILE PF_FILE +#define AF_INET PF_INET +#define AF_AX25 PF_AX25 +#define AF_IPX PF_IPX +#define AF_APPLETALK PF_APPLETALK +#define AF_NETROM PF_NETROM +#define AF_BRIDGE PF_BRIDGE +#define AF_ATMPVC PF_ATMPVC +#define AF_X25 PF_X25 +#define AF_INET6 PF_INET6 +#define AF_ROSE PF_ROSE +#define AF_DECnet PF_DECnet +#define AF_NETBEUI PF_NETBEUI +#define AF_SECURITY PF_SECURITY +#define AF_KEY PF_KEY +#define AF_NETLINK PF_NETLINK +#define AF_ROUTE PF_ROUTE +#define AF_PACKET PF_PACKET +#define AF_ASH PF_ASH +#define AF_ECONET PF_ECONET +#define AF_ATMSVC PF_ATMSVC +#define AF_SNA PF_SNA +#define AF_IRDA PF_IRDA +#define AF_PPPOX PF_PPPOX +#define AF_WANPIPE PF_WANPIPE +#define AF_BLUETOOTH PF_BLUETOOTH +#define AF_MAX PF_MAX + +/* Socket level values. Others are defined in the appropriate headers. + + XXX These definitions also should go into the appropriate headers as + far as they are available. */ +#define SOL_RAW 255 +#define SOL_DECNET 261 +#define SOL_X25 262 +#define SOL_PACKET 263 +#define SOL_ATM 264 /* ATM layer (cell level). */ +#define SOL_AAL 265 /* ATM Adaption Layer (packet level). */ +#define SOL_IRDA 266 + +/* Maximum queue length specifiable by listen. */ +#define SOMAXCONN 128 + +/* Get the definition of the macro to define the common sockaddr members. */ +#include + +/* Structure describing a generic socket address. */ +struct sockaddr + { + __SOCKADDR_COMMON (sa_); /* Common data: address family and length. */ + char sa_data[14]; /* Address data. */ + }; + + +/* Structure large enough to hold any socket address (with the historical + exception of AF_UNIX). We reserve 128 bytes. */ +#if ULONG_MAX > 0xffffffff +# define __ss_aligntype __uint64_t +#else +# define __ss_aligntype __uint32_t +#endif +#define _SS_SIZE 128 +#define _SS_PADSIZE (_SS_SIZE - (2 * sizeof (__ss_aligntype))) + +struct sockaddr_storage + { + __SOCKADDR_COMMON (ss_); /* Address family, etc. */ + __ss_aligntype __ss_align; /* Force desired alignment. */ + char __ss_padding[_SS_PADSIZE]; + }; + + +/* Bits in the FLAGS argument to `send', `recv', et al. */ +enum + { + MSG_OOB = 0x01, /* Process out-of-band data. */ +#define MSG_OOB MSG_OOB + MSG_PEEK = 0x02, /* Peek at incoming messages. */ +#define MSG_PEEK MSG_PEEK + MSG_DONTROUTE = 0x04, /* Don't use local routing. */ +#define MSG_DONTROUTE MSG_DONTROUTE +#ifdef __USE_GNU + /* DECnet uses a different name. */ + MSG_TRYHARD = MSG_DONTROUTE, +# define MSG_TRYHARD MSG_DONTROUTE +#endif + MSG_CTRUNC = 0x08, /* Control data lost before delivery. */ +#define MSG_CTRUNC MSG_CTRUNC + MSG_PROXY = 0x10, /* Supply or ask second address. */ +#define MSG_PROXY MSG_PROXY + MSG_TRUNC = 0x20, +#define MSG_TRUNC MSG_TRUNC + MSG_DONTWAIT = 0x40, /* Nonblocking IO. */ +#define MSG_DONTWAIT MSG_DONTWAIT + MSG_EOR = 0x80, /* End of record. */ +#define MSG_EOR MSG_EOR + MSG_WAITALL = 0x100, /* Wait for a full request. */ +#define MSG_WAITALL MSG_WAITALL + MSG_FIN = 0x200, +#define MSG_FIN MSG_FIN + MSG_SYN = 0x400, +#define MSG_SYN MSG_SYN + MSG_CONFIRM = 0x800, /* Confirm path validity. */ +#define MSG_CONFIRM MSG_CONFIRM + MSG_RST = 0x1000, +#define MSG_RST MSG_RST + MSG_ERRQUEUE = 0x2000, /* Fetch message from error queue. */ +#define MSG_ERRQUEUE MSG_ERRQUEUE + MSG_NOSIGNAL = 0x4000, /* Do not generate SIGPIPE. */ +#define MSG_NOSIGNAL MSG_NOSIGNAL + MSG_MORE = 0x8000 /* Sender will send more. */ +#define MSG_MORE MSG_MORE + }; + + +/* Structure describing messages sent by + `sendmsg' and received by `recvmsg'. */ +/* Note: do not change these members to match glibc; these match the + SuSv3 spec already (e.g. msg_iovlen/msg_controllen). + http://www.opengroup.org/onlinepubs/009695399/basedefs/sys/socket.h.html */ +/* Note: linux kernel uses __kernel_size_t (which is 8bytes on 64bit + platforms, and 4bytes on 32bit platforms) for msg_iovlen/msg_controllen */ +struct msghdr + { + void *msg_name; /* Address to send to/receive from. */ + socklen_t msg_namelen; /* Length of address data. */ + + struct iovec *msg_iov; /* Vector of data to send/receive into. */ +#if __WORDSIZE == 32 + int msg_iovlen; /* Number of elements in the vector. */ +#else + size_t msg_iovlen; /* Number of elements in the vector. */ +#endif + + void *msg_control; /* Ancillary data (eg BSD filedesc passing). */ +#if __WORDSIZE == 32 + socklen_t msg_controllen; /* Ancillary data buffer length. */ +#else + size_t msg_controllen; /* Ancillary data buffer length. */ +#endif + + int msg_flags; /* Flags on received message. */ + }; + +/* Structure used for storage of ancillary data object information. */ +struct cmsghdr + { + size_t cmsg_len; /* Length of data in cmsg_data plus length + of cmsghdr structure. */ + int cmsg_level; /* Originating protocol. */ + int cmsg_type; /* Protocol specific type. */ +#if (!defined __STRICT_ANSI__ && __GNUC__ >= 2) || __STDC_VERSION__ >= 199901L + __extension__ unsigned char __cmsg_data __flexarr; /* Ancillary data. */ +#endif + }; + +/* Ancillary data object manipulation macros. */ +#if (!defined __STRICT_ANSI__ && __GNUC__ >= 2) || __STDC_VERSION__ >= 199901L +# define CMSG_DATA(cmsg) ((cmsg)->__cmsg_data) +#else +# define CMSG_DATA(cmsg) ((unsigned char *) ((struct cmsghdr *) (cmsg) + 1)) +#endif +#define CMSG_NXTHDR(mhdr, cmsg) __cmsg_nxthdr (mhdr, cmsg) +#define CMSG_FIRSTHDR(mhdr) \ + ((size_t) (mhdr)->msg_controllen >= sizeof (struct cmsghdr) \ + ? (struct cmsghdr *) (mhdr)->msg_control : (struct cmsghdr *) NULL) +#define CMSG_ALIGN(len) (((len) + sizeof (size_t) - 1) \ + & (size_t) ~(sizeof (size_t) - 1)) +#define CMSG_SPACE(len) (CMSG_ALIGN (len) \ + + CMSG_ALIGN (sizeof (struct cmsghdr))) +#define CMSG_LEN(len) (CMSG_ALIGN (sizeof (struct cmsghdr)) + (len)) + +extern struct cmsghdr *__cmsg_nxthdr (struct msghdr *__mhdr, + struct cmsghdr *__cmsg) __THROW; +libc_hidden_proto(__cmsg_nxthdr) +#ifdef __USE_EXTERN_INLINES +# ifndef _EXTERN_INLINE +# define _EXTERN_INLINE extern __inline +# endif +_EXTERN_INLINE struct cmsghdr * +__NTH (__cmsg_nxthdr (struct msghdr *__mhdr, struct cmsghdr *__cmsg)) +{ + if ((size_t) __cmsg->cmsg_len < sizeof (struct cmsghdr)) + /* The kernel header does this so there may be a reason. */ + return 0; + + __cmsg = (struct cmsghdr *) ((unsigned char *) __cmsg + + CMSG_ALIGN (__cmsg->cmsg_len)); + if ((unsigned char *) (__cmsg + 1) > ((unsigned char *) __mhdr->msg_control + + __mhdr->msg_controllen) + || ((unsigned char *) __cmsg + CMSG_ALIGN (__cmsg->cmsg_len) + > ((unsigned char *) __mhdr->msg_control + __mhdr->msg_controllen))) + /* No more entries. */ + return 0; + return __cmsg; +} +#endif /* Use `extern inline'. */ + +/* Socket level message types. This must match the definitions in + . */ +enum + { + SCM_RIGHTS = 0x01 /* Transfer file descriptors. */ +#define SCM_RIGHTS SCM_RIGHTS +#ifdef __USE_BSD + , SCM_CREDENTIALS = 0x02 /* Credentials passing. */ +# define SCM_CREDENTIALS SCM_CREDENTIALS +#endif + }; + +/* User visible structure for SCM_CREDENTIALS message */ + +struct ucred +{ + pid_t pid; /* PID of sending process. */ + uid_t uid; /* UID of sending process. */ + gid_t gid; /* GID of sending process. */ +}; + +/* Get socket manipulation related informations from kernel headers. */ +#ifndef __GLIBC__ +#define __GLIBC__ 2 +#include +#undef __GLIBC__ +#else +#include +#endif + + +/* Structure used to manipulate the SO_LINGER option. */ +struct linger + { + int l_onoff; /* Nonzero to linger on close. */ + int l_linger; /* Time to linger. */ + }; + +/* Prefer socketcall over all these for sparc32, + since it only has socketcall */ +#ifndef __arch64__ + #undef __NR_accept + #undef __NR_bind + #undef __NR_connect + #undef __NR_getpeername + #undef __NR_getsockname + #undef __NR_getsockopt + #undef __NR_listen + #undef __NR_recv + #undef __NR_recvfrom + #undef __NR_recvmsg + #undef __NR_send + #undef __NR_sendmsg + #undef __NR_sendto + #undef __NR_setsockopt + #undef __NR_shutdown + #undef __NR_socket + #undef __NR_socketpair +#endif + +#endif /* bits/socket.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/stackinfo.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/stackinfo.h new file mode 100644 index 00000000..fd34e2de --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/stackinfo.h @@ -0,0 +1,28 @@ +/* Copyright (C) 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This file contains a bit of information about the stack allocation + of the processor. */ + +#ifndef _STACKINFO_H +#define _STACKINFO_H 1 + +/* On sparc the stack grows down. */ +#define _STACK_GROWS_DOWN 1 + +#endif /* stackinfo.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/stat.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/stat.h new file mode 100644 index 00000000..7426e168 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/stat.h @@ -0,0 +1,169 @@ +/* Copyright (C) 1992, 1995-2002, 2006, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_STAT_H +# error "Never include directly; use instead." +#endif + +/* Versions of the `struct stat' data structure. */ +#define _STAT_VER_LINUX_OLD 1 +#define _STAT_VER_KERNEL 1 +#define _STAT_VER_SVR4 2 +#define _STAT_VER_LINUX 3 +#define _STAT_VER _STAT_VER_LINUX /* The one defined below. */ + +/* Versions of the `xmknod' interface. */ +#define _MKNOD_VER_LINUX 1 +#define _MKNOD_VER_SVR4 2 +#define _MKNOD_VER _MKNOD_VER_LINUX /* The bits defined below. */ + + +struct stat + { + __dev_t st_dev; /* Device. */ +#if __WORDSIZE == 64 || !defined __USE_FILE_OFFSET64 + unsigned short int __pad1; + __ino_t st_ino; /* File serial number. */ +#else + __ino64_t st_ino; /* File serial number. */ +#endif + __mode_t st_mode; /* File mode. */ + __nlink_t st_nlink; /* Link count. */ + __uid_t st_uid; /* User ID of the file's owner. */ + __gid_t st_gid; /* Group ID of the file's group.*/ + __dev_t st_rdev; /* Device number, if device. */ + unsigned short int __pad2; +#ifndef __USE_FILE_OFFSET64 + __off_t st_size; /* Size of file, in bytes. */ +#else + __off64_t st_size; /* Size of file, in bytes. */ +#endif + __blksize_t st_blksize; /* Optimal block size for I/O. */ + +#ifndef __USE_FILE_OFFSET64 + __blkcnt_t st_blocks; /* Number 512-byte blocks allocated. */ +#else + __blkcnt64_t st_blocks; /* Number 512-byte blocks allocated. */ +#endif +#ifdef __USE_MISC + /* Nanosecond resolution timestamps are stored in a format + equivalent to 'struct timespec'. This is the type used + whenever possible but the Unix namespace rules do not allow the + identifier 'timespec' to appear in the header. + Therefore we have to handle the use of this header in strictly + standard-compliant sources special. */ + struct timespec st_atim; /* Time of last access. */ + struct timespec st_mtim; /* Time of last modification. */ + struct timespec st_ctim; /* Time of last status change. */ +# define st_atime st_atim.tv_sec /* Backward compatibility. */ +# define st_mtime st_mtim.tv_sec +# define st_ctime st_ctim.tv_sec +#else + __time_t st_atime; /* Time of last access. */ + unsigned long int st_atimensec; /* Nscecs of last access. */ + __time_t st_mtime; /* Time of last modification. */ + unsigned long int st_mtimensec; /* Nsecs of last modification. */ + __time_t st_ctime; /* Time of last status change. */ + unsigned long int st_ctimensec; /* Nsecs of last status change. */ +#endif + unsigned long int __unused4; + unsigned long int __unused5; + }; + +#ifdef __USE_LARGEFILE64 +struct stat64 + { + __dev_t st_dev; /* Device. */ +#if __WORDSIZE == 64 + unsigned short int __pad1; +#endif + __ino64_t st_ino; /* File serial number. */ + __mode_t st_mode; /* File mode. */ + __nlink_t st_nlink; /* Link count. */ + __uid_t st_uid; /* User ID of the file's owner. */ + __gid_t st_gid; /* Group ID of the file's group.*/ + __dev_t st_rdev; /* Device number, if device. */ + unsigned short int __pad2; + __off64_t st_size; /* Size of file, in bytes. */ + __blksize_t st_blksize; /* Optimal block size for I/O. */ + + __blkcnt64_t st_blocks; /* Number 512-byte blocks allocated. */ +#ifdef __USE_MISC + /* Nanosecond resolution timestamps are stored in a format + equivalent to 'struct timespec'. This is the type used + whenever possible but the Unix namespace rules do not allow the + identifier 'timespec' to appear in the header. + Therefore we have to handle the use of this header in strictly + standard-compliant sources special. */ + struct timespec st_atim; /* Time of last access. */ + struct timespec st_mtim; /* Time of last modification. */ + struct timespec st_ctim; /* Time of last status change. */ +# define st_atime st_atim.tv_sec /* Backward compatibility. */ +# define st_mtime st_mtim.tv_sec +# define st_ctime st_ctim.tv_sec +#else + __time_t st_atime; /* Time of last access. */ + unsigned long int st_atimensec; /* Nscecs of last access. */ + __time_t st_mtime; /* Time of last modification. */ + unsigned long int st_mtimensec; /* Nsecs of last modification. */ + __time_t st_ctime; /* Time of last status change. */ + unsigned long int st_ctimensec; /* Nsecs of last status change. */ +#endif + unsigned long int __unused4; + unsigned long int __unused5; + }; +#endif + +/* Tell code we have these members. */ +#define _STATBUF_ST_BLKSIZE +#define _STATBUF_ST_RDEV +/* Nanosecond resolution time values are supported. */ +#define _STATBUF_ST_NSEC + +/* Encoding of the file mode. */ + +#define __S_IFMT 0170000 /* These bits determine file type. */ + +/* File types. */ +#define __S_IFDIR 0040000 /* Directory. */ +#define __S_IFCHR 0020000 /* Character device. */ +#define __S_IFBLK 0060000 /* Block device. */ +#define __S_IFREG 0100000 /* Regular file. */ +#define __S_IFIFO 0010000 /* FIFO. */ +#define __S_IFLNK 0120000 /* Symbolic link. */ +#define __S_IFSOCK 0140000 /* Socket. */ + +/* POSIX.1b objects. Note that these macros always evaluate to zero. But + they do it by enforcing the correct use of the macros. */ +#define __S_TYPEISMQ(buf) ((buf)->st_mode - (buf)->st_mode) +#define __S_TYPEISSEM(buf) ((buf)->st_mode - (buf)->st_mode) +#define __S_TYPEISSHM(buf) ((buf)->st_mode - (buf)->st_mode) + +/* Protection bits. */ + +#define __S_ISUID 04000 /* Set user ID on execution. */ +#define __S_ISGID 02000 /* Set group ID on execution. */ +#define __S_ISVTX 01000 /* Save swapped text after use (sticky). */ +#define __S_IREAD 0400 /* Read by owner. */ +#define __S_IWRITE 0200 /* Write by owner. */ +#define __S_IEXEC 0100 /* Execute by owner. */ + +#ifdef __USE_ATFILE +# define UTIME_NOW ((1l << 30) - 1l) +# define UTIME_OMIT ((1l << 30) - 2l) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/statvfs.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/statvfs.h new file mode 100644 index 00000000..3dafcebf --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/statvfs.h @@ -0,0 +1,106 @@ +/* Copyright (C) 1997, 1998, 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_STATVFS_H +# error "Never include directly; use instead." +#endif + +#include /* For __fsblkcnt_t and __fsfilcnt_t. */ + +#if __WORDSIZE == 32 +#define _STATVFSBUF_F_UNUSED +#endif + +struct statvfs + { + unsigned long int f_bsize; + unsigned long int f_frsize; +#ifndef __USE_FILE_OFFSET64 + __fsblkcnt_t f_blocks; + __fsblkcnt_t f_bfree; + __fsblkcnt_t f_bavail; + __fsfilcnt_t f_files; + __fsfilcnt_t f_ffree; + __fsfilcnt_t f_favail; +#else + __fsblkcnt64_t f_blocks; + __fsblkcnt64_t f_bfree; + __fsblkcnt64_t f_bavail; + __fsfilcnt64_t f_files; + __fsfilcnt64_t f_ffree; + __fsfilcnt64_t f_favail; +#endif + unsigned long int f_fsid; +#ifdef _STATVFSBUF_F_UNUSED + int __f_unused; +#endif + unsigned long int f_flag; + unsigned long int f_namemax; + int __f_spare[6]; + }; + +#ifdef __USE_LARGEFILE64 +struct statvfs64 + { + unsigned long int f_bsize; + unsigned long int f_frsize; + __fsblkcnt64_t f_blocks; + __fsblkcnt64_t f_bfree; + __fsblkcnt64_t f_bavail; + __fsfilcnt64_t f_files; + __fsfilcnt64_t f_ffree; + __fsfilcnt64_t f_favail; + unsigned long int f_fsid; +#ifdef _STATVFSBUF_F_UNUSED + int __f_unused; +#endif + unsigned long int f_flag; + unsigned long int f_namemax; + int __f_spare[6]; + }; +#endif + +/* Definitions for the flag in `f_flag'. These definitions should be + kept in sync which the definitions in . */ +enum +{ + ST_RDONLY = 1, /* Mount read-only. */ +#define ST_RDONLY ST_RDONLY + ST_NOSUID = 2, /* Ignore suid and sgid bits. */ +#define ST_NOSUID ST_NOSUID +#ifdef __USE_GNU + ST_NODEV = 4, /* Disallow access to device special files. */ +# define ST_NODEV ST_NODEV + ST_NOEXEC = 8, /* Disallow program execution. */ +# define ST_NOEXEC ST_NOEXEC + ST_SYNCHRONOUS = 16, /* Writes are synced at once. */ +# define ST_SYNCHRONOUS ST_SYNCHRONOUS + ST_MANDLOCK = 64, /* Allow mandatory locks on an FS. */ +# define ST_MANDLOCK ST_MANDLOCK + ST_WRITE = 128, /* Write on file/directory/symlink. */ +# define ST_WRITE ST_WRITE + ST_APPEND = 256, /* Append-only file. */ +# define ST_APPEND ST_APPEND + ST_IMMUTABLE = 512, /* Immutable file. */ +# define ST_IMMUTABLE ST_IMMUTABLE + ST_NOATIME = 1024, /* Do not update access times. */ +# define ST_NOATIME ST_NOATIME + ST_NODIRATIME /* Do not update directory access times. */ +# define ST_NODIRATIME ST_NODIRATIME +#endif /* Use GNU. */ +}; diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/syscalls.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/syscalls.h new file mode 100644 index 00000000..dc8d6371 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/syscalls.h @@ -0,0 +1,118 @@ +#ifndef _BITS_SYSCALLS_H +#define _BITS_SYSCALLS_H +#ifndef _SYSCALL_H +# error "Never use directly; include instead." +#endif + +#include + +#ifndef __ASSEMBLER__ + +#if __WORDSIZE == 32 +# define __SYSCALL_STRING \ + "t 0x10\n\t" \ + "bcc 1f\n\t" \ + "mov %%o0, %0\n\t" \ + "sub %%g0, %%o0, %0\n\t" \ + "1:\n\t" +#elif __WORDSIZE == 64 +# define __SYSCALL_STRING \ + "t 0x6d\n\t" \ + "sub %%g0, %%o0, %0\n\t" \ + "movcc %%xcc, %%o0, %0\n\t" +#else +# error unknown __WORDSIZE +#endif + +#define __SYSCALL_CLOBBERS "cc", "memory" + +#ifndef NOT_IN_libc +#define DEBUG_SYSCALL(name) { \ + char d[64];\ + write( 2, d, snprintf( d, 64, "syscall %d error %d\n", __NR_##name, _inline_sys_result)); \ +} +#else +#define DEBUG_SYSCALL(name) do{} while(0) +#endif + +#define INTERNAL_SYSCALL_NCS(sys_num, err, nr, args...) \ + ({ \ + unsigned int __res; \ + { \ + register long __o0 __asm__("o0"); \ + register long __g1 __asm__("g1") = sys_num; \ + LOAD_ARGS_##nr(args) \ + __asm__ __volatile__( __SYSCALL_STRING \ + : "=r" (__res), "=&r" (__o0) \ + : "1" (__o0) ASM_ARGS_##nr, "r" (__g1) \ + : __SYSCALL_CLOBBERS ); \ + } \ + (int)__res; \ + }) + +#define INTERNAL_SYSCALL_ERROR_P(val, err) \ + ((unsigned int) (val) >= 0xfffff001u) + +# define CALL_ERRNO_LOCATION "call __errno_location;" +#define __CLONE_SYSCALL_STRING \ + "ta 0x10;" \ + "bcs 2f;" \ + " sub %%o1, 1, %%o1;" \ + "and %%o0, %%o1, %%o0;" \ + "1:" \ + ".subsection 2;" \ + "2:" \ + "save %%sp, -192, %%sp;" \ + CALL_ERRNO_LOCATION \ + " nop;" \ + "st %%i0, [%%o0];" \ + "ba 1b;" \ + " restore %%g0, -1, %%o0;" \ + ".previous;" + +#define INLINE_CLONE_SYSCALL(arg1,arg2,arg3,arg4,arg5) \ +({ \ + register long __o0 __asm__ ("o0") = (long)(arg1); \ + register long __o1 __asm__ ("o1") = (long)(arg2); \ + register long __o2 __asm__ ("o2") = (long)(arg3); \ + register long __o3 __asm__ ("o3") = (long)(arg4); \ + register long __o4 __asm__ ("o4") = (long)(arg5); \ + register long __g1 __asm__ ("g1") = __NR_clone; \ + __asm__ __volatile__ (__CLONE_SYSCALL_STRING : \ + "=r" (__g1), "=r" (__o0), "=r" (__o1) : \ + "0" (__g1), "1" (__o0), "2" (__o1), \ + "r" (__o2), "r" (__o3), "r" (__o4) : \ + __SYSCALL_CLOBBERS); \ + __o0; \ +}) + +#define LOAD_ARGS_0() +#define ASM_ARGS_0 +#define LOAD_ARGS_1(o0) \ + __o0 = (int)o0; \ + LOAD_ARGS_0() +#define ASM_ARGS_1 ASM_ARGS_0, "r" (__o0) +#define LOAD_ARGS_2(o0, o1) \ + register int __o1 __asm__ ("o1") = (int) (o1); \ + LOAD_ARGS_1 (o0) +#define ASM_ARGS_2 ASM_ARGS_1, "r" (__o1) +#define LOAD_ARGS_3(o0, o1, o2) \ + register int __o2 __asm__ ("o2") = (int) (o2); \ + LOAD_ARGS_2 (o0, o1) +#define ASM_ARGS_3 ASM_ARGS_2, "r" (__o2) +#define LOAD_ARGS_4(o0, o1, o2, o3) \ + register int __o3 __asm__ ("o3") = (int) (o3); \ + LOAD_ARGS_3 (o0, o1, o2) +#define ASM_ARGS_4 ASM_ARGS_3, "r" (__o3) +#define LOAD_ARGS_5(o0, o1, o2, o3, o4) \ + register int __o4 __asm__ ("o4") = (int) (o4); \ + LOAD_ARGS_4 (o0, o1, o2, o3) +#define ASM_ARGS_5 ASM_ARGS_4, "r" (__o4) +#define LOAD_ARGS_6(o0, o1, o2, o3, o4, o5) \ + register int __o5 __asm__ ("o5") = (int) (o5); \ + LOAD_ARGS_5 (o0, o1, o2, o3, o4) +#define ASM_ARGS_6 ASM_ARGS_5, "r" (__o5) + + +#endif /* __ASSEMBLER__ */ +#endif /* _BITS_SYSCALLS_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/termios.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/termios.h new file mode 100644 index 00000000..cea13227 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/termios.h @@ -0,0 +1,233 @@ +/* termios type and macro definitions. Linux/SPARC version. + Copyright (C) 1993, 1994, 1995, 1996, 1997, 2000, 2005 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _TERMIOS_H +# error "Never include directly; use instead." +#endif + +typedef unsigned char cc_t; +typedef unsigned int speed_t; +typedef unsigned int tcflag_t; + +#define NCCS 17 +struct termios + { + tcflag_t c_iflag; /* input mode flags */ + tcflag_t c_oflag; /* output mode flags */ + tcflag_t c_cflag; /* control mode flags */ + tcflag_t c_lflag; /* local mode flags */ + cc_t c_line; /* line discipline */ + cc_t c_cc[NCCS]; /* control characters */ + }; + +/* c_cc characters */ +#define VINTR 0 +#define VQUIT 1 +#define VERASE 2 +#define VKILL 3 +#define VEOF 4 +#define VEOL 5 +#define VEOL2 6 +#define VSWTC 7 +#define VSTART 8 +#define VSTOP 9 +#define VSUSP 10 +#define VDSUSP 11 /* SunOS POSIX nicety I do believe... */ +#define VREPRINT 12 +#define VDISCARD 13 +#define VWERASE 14 +#define VLNEXT 15 + +/* User apps assume vmin/vtime is shared with eof/eol */ +#define VMIN VEOF +#define VTIME VEOL + +/* c_iflag bits */ +#define IGNBRK 0x00000001 +#define BRKINT 0x00000002 +#define IGNPAR 0x00000004 +#define PARMRK 0x00000008 +#define INPCK 0x00000010 +#define ISTRIP 0x00000020 +#define INLCR 0x00000040 +#define IGNCR 0x00000080 +#define ICRNL 0x00000100 +#define IUCLC 0x00000200 +#define IXON 0x00000400 +#define IXANY 0x00000800 +#define IXOFF 0x00001000 +#define IMAXBEL 0x00002000 +#define IUTF8 0x00004000 + +/* c_oflag bits */ +#define OPOST 0x00000001 +#define OLCUC 0x00000002 +#define ONLCR 0x00000004 +#define OCRNL 0x00000008 +#define ONOCR 0x00000010 +#define ONLRET 0x00000020 +#define OFILL 0x00000040 +#define OFDEL 0x00000080 +#if defined __USE_MISC || defined __USE_XOPEN +# define NLDLY 0x00000100 +# define NL0 0x00000000 +# define NL1 0x00000100 +# define CRDLY 0x00000600 +# define CR0 0x00000000 +# define CR1 0x00000200 +# define CR2 0x00000400 +# define CR3 0x00000600 +# define TABDLY 0x00001800 +# define TAB0 0x00000000 +# define TAB1 0x00000800 +# define TAB2 0x00001000 +# define TAB3 0x00001800 +# define BSDLY 0x00002000 +# define BS0 0x00000000 +# define BS1 0x00002000 +#define FFDLY 0x00008000 +#define FF0 0x00000000 +#define FF1 0x00008000 +#endif +#define VTDLY 0x00004000 +#define VT0 0x00000000 +#define VT1 0x00004000 +#define PAGEOUT 0x00010000 /* SUNOS specific */ +#define WRAP 0x00020000 /* SUNOS specific */ + +#ifdef __USE_MISC +# define XTABS 0x00001800 +#endif + +/* c_cflag bit meaning */ +#ifdef __USE_MISC +# define CBAUD 0x0000100f +#endif +#define B0 0x00000000 /* hang up */ +#define B50 0x00000001 +#define B75 0x00000002 +#define B110 0x00000003 +#define B134 0x00000004 +#define B150 0x00000005 +#define B200 0x00000006 +#define B300 0x00000007 +#define B600 0x00000008 +#define B1200 0x00000009 +#define B1800 0x0000000a +#define B2400 0x0000000b +#define B4800 0x0000000c +#define B9600 0x0000000d +#define B19200 0x0000000e +#define B38400 0x0000000f +#ifdef __USE_MISC +# define EXTA B19200 +# define EXTB B38400 +#endif +#define CSIZE 0x00000030 +#define CS5 0x00000000 +#define CS6 0x00000010 +#define CS7 0x00000020 +#define CS8 0x00000030 +#define CSTOPB 0x00000040 +#define CREAD 0x00000080 +#define PARENB 0x00000100 +#define PARODD 0x00000200 +#define HUPCL 0x00000400 +#define CLOCAL 0x00000800 +#ifdef __USE_MISC +# define CBAUDEX 0x00001000 +#endif +#define B57600 0x00001001 +#define B115200 0x00001002 +#define B230400 0x00001003 +#define B460800 0x00001004 +#define B76800 0x00001005 +#define B153600 0x00001006 +#define B307200 0x00001007 +#define B614400 0x00001008 +#define B921600 0x00001009 +#define B500000 0x0000100a +#define B576000 0x0000100b +#define B1000000 0x0000100c +#define B1152000 0x0000100d +#define B1500000 0x0000100e +#define B2000000 0x0000100f +#define __MAX_BAUD B2000000 + +#ifdef __USE_MISC +# define CIBAUD 0x100f0000 /* input baud rate (not used) */ +# define CMSPAR 0x40000000 /* mark or space (stick) parity */ +# define CRTSCTS 0x80000000 /* flow control */ +#endif + +/* c_lflag bits */ +#define ISIG 0x00000001 +#define ICANON 0x00000002 +#if defined __USE_MISC || defined __USE_XOPEN +# define XCASE 0x00000004 +#endif +#define ECHO 0x00000008 +#define ECHOE 0x00000010 +#define ECHOK 0x00000020 +#define ECHONL 0x00000040 +#define NOFLSH 0x00000080 +#define TOSTOP 0x00000100 +#ifdef __USE_MISC +# define ECHOCTL 0x00000200 +# define ECHOPRT 0x00000400 +# define ECHOKE 0x00000800 +# define DEFECHO 0x00001000 /* SUNOS thing, what is it? */ +# define FLUSHO 0x00002000 +# define PENDIN 0x00004000 +#endif +#define IEXTEN 0x00008000 + +/* modem lines */ +#define TIOCM_LE 0x001 +#define TIOCM_DTR 0x002 +#define TIOCM_RTS 0x004 +#define TIOCM_ST 0x008 +#define TIOCM_SR 0x010 +#define TIOCM_CTS 0x020 +#define TIOCM_CAR 0x040 +#define TIOCM_RNG 0x080 +#define TIOCM_DSR 0x100 +#define TIOCM_CD TIOCM_CAR +#define TIOCM_RI TIOCM_RNG + +/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */ +#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */ + + +/* tcflow() and TCXONC use these */ +#define TCOOFF 0 +#define TCOON 1 +#define TCIOFF 2 +#define TCION 3 + +/* tcflush() and TCFLSH use these */ +#define TCIFLUSH 0 +#define TCOFLUSH 1 +#define TCIOFLUSH 2 + +/* tcsetattr uses these */ +#define TCSANOW 0 +#define TCSADRAIN 1 +#define TCSAFLUSH 2 diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/typesizes.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/typesizes.h new file mode 100644 index 00000000..b0dd1bd8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/typesizes.h @@ -0,0 +1,66 @@ +/* bits/typesizes.h -- underlying types for *_t. Linux/SPARC version. + Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _BITS_TYPES_H +# error "Never include directly; use instead." +#endif + +#ifndef _BITS_TYPESIZES_H +#define _BITS_TYPESIZES_H 1 + +/* See for the meaning of these macros. This file exists so + that need not vary across different GNU platforms. */ + +#define __DEV_T_TYPE __UQUAD_TYPE +#define __UID_T_TYPE __U32_TYPE +#define __GID_T_TYPE __U32_TYPE +#define __INO_T_TYPE __ULONGWORD_TYPE +#define __INO64_T_TYPE __UQUAD_TYPE +#define __MODE_T_TYPE __U32_TYPE +#define __NLINK_T_TYPE __U32_TYPE +#define __OFF_T_TYPE __SLONGWORD_TYPE +#define __OFF64_T_TYPE __SQUAD_TYPE +#define __PID_T_TYPE __S32_TYPE +#define __RLIM_T_TYPE __ULONGWORD_TYPE +#define __RLIM64_T_TYPE __UQUAD_TYPE +#define __BLKCNT_T_TYPE __SLONGWORD_TYPE +#define __BLKCNT64_T_TYPE __SQUAD_TYPE +#define __FSBLKCNT_T_TYPE __ULONGWORD_TYPE +#define __FSBLKCNT64_T_TYPE __UQUAD_TYPE +#define __FSFILCNT_T_TYPE __ULONGWORD_TYPE +#define __FSFILCNT64_T_TYPE __UQUAD_TYPE +#define __ID_T_TYPE __U32_TYPE +#define __CLOCK_T_TYPE __SLONGWORD_TYPE +#define __TIME_T_TYPE __SLONGWORD_TYPE +#define __USECONDS_T_TYPE __U32_TYPE +#define __SUSECONDS_T_TYPE __S32_TYPE +#define __DADDR_T_TYPE __S32_TYPE +#define __SWBLK_T_TYPE __SLONGWORD_TYPE +#define __KEY_T_TYPE __S32_TYPE +#define __CLOCKID_T_TYPE __S32_TYPE +#define __TIMER_T_TYPE void * +#define __BLKSIZE_T_TYPE __SLONGWORD_TYPE +#define __FSID_T_TYPE struct { int __val[2]; } +#define __SSIZE_T_TYPE __SWORD_TYPE + +/* Number of descriptors that can fit in an `fd_set'. */ +#define __FD_SETSIZE 1024 + + +#endif /* bits/typesizes.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/uClibc_arch_features.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/uClibc_arch_features.h new file mode 100644 index 00000000..2d8cdd78 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/uClibc_arch_features.h @@ -0,0 +1,47 @@ +/* + * Track misc arch-specific features that aren't config options + */ + +#ifndef _BITS_UCLIBC_ARCH_FEATURES_H +#define _BITS_UCLIBC_ARCH_FEATURES_H + +/* instruction used when calling abort() to kill yourself */ +#define __UCLIBC_ABORT_INSTRUCTION__ "unimp 0xf00" + +/* can your target use syscall6() for mmap ? */ +#define __UCLIBC_MMAP_HAS_6_ARGS__ + +/* does your target use syscall4() for truncate64 ? (32bit arches only) */ +#undef __UCLIBC_TRUNCATE64_HAS_4_ARGS__ + +/* does your target have a broken create_module() ? */ +#undef __UCLIBC_BROKEN_CREATE_MODULE__ + +/* does your target have to worry about older [gs]etrlimit() ? */ +#undef __UCLIBC_HANDLE_OLDER_RLIMIT__ + +/* does your target have an asm .set ? */ +#define __UCLIBC_HAVE_ASM_SET_DIRECTIVE__ + +/* define if target doesn't like .global */ +#undef __UCLIBC_ASM_GLOBAL_DIRECTIVE__ + +/* define if target supports .weak */ +#define __UCLIBC_HAVE_ASM_WEAK_DIRECTIVE__ + +/* define if target supports .weakext */ +#undef __UCLIBC_HAVE_ASM_WEAKEXT_DIRECTIVE__ + +/* needed probably only for ppc64 */ +#undef __UCLIBC_HAVE_ASM_GLOBAL_DOT_NAME__ + +/* define if target supports CFI pseudo ops */ +#define __UCLIBC_HAVE_ASM_CFI_DIRECTIVES__ + +/* define if target supports IEEE signed zero floats */ +#define __UCLIBC_HAVE_SIGNED_ZERO__ + +/* only weird assemblers generally need this */ +#undef __UCLIBC_ASM_LINE_SEP__ + +#endif /* _BITS_UCLIBC_ARCH_FEATURES_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/wordsize.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/wordsize.h new file mode 100644 index 00000000..c0e600ed --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bits/wordsize.h @@ -0,0 +1,20 @@ +/* Determine the wordsize from the preprocessor defines. */ + +#if defined __arch64__ || defined __sparcv9 +# define __WORDSIZE 64 +#else +# define __WORDSIZE 32 +#endif + +#if 0 /* uClibc: done in mathdefs.h: !defined __NO_LONG_DOUBLE_MATH && !defined __LONG_DOUBLE_MATH_OPTIONAL*/ + +# if __WORDSIZE == 32 +/* Signal that in 32bit ABI we didn't used to have a `long double'. + The changes all the `long double' function variants to be redirects + to the double functions. */ +# define __LONG_DOUBLE_MATH_OPTIONAL 1 +# ifndef __LONG_DOUBLE_128__ +# define __NO_LONG_DOUBLE_MATH 1 +# endif +# endif +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/brk.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/brk.c new file mode 100644 index 00000000..513975c7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/brk.c @@ -0,0 +1,49 @@ +/* brk system call for Linux/i386. + Copyright (C) 1995, 1996, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + + +/* This must be initialized data because commons can't have aliases. */ +void *__curbrk attribute_hidden = 0; + +int brk (void *addr) +{ + void *newbrk; + + { + register void *o0 __asm__("%o0") = addr; + register int g1 __asm__("%g1") = 17 ; + __asm__ ("t 0x10" : "=r"(o0) : "r"(g1), "0"(o0) : "cc"); + newbrk = o0; + } + + __curbrk = newbrk; + + if (newbrk < addr) + { + __set_errno (ENOMEM); + return -1; + } + + return 0; +} +libc_hidden_def(brk) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bsd-_setjmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bsd-_setjmp.S new file mode 100644 index 00000000..4e6a2da5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bsd-_setjmp.S @@ -0,0 +1 @@ +/* _setjmp is in setjmp.S */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bsd-setjmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bsd-setjmp.S new file mode 100644 index 00000000..1da848d2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/bsd-setjmp.S @@ -0,0 +1 @@ +/* setjmp is in setjmp.S */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/clone.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/clone.S new file mode 100644 index 00000000..2b660953 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/clone.S @@ -0,0 +1,107 @@ +/* Copyright (C) 1996, 1997, 1998, 2000, 2003, 2004, 2007 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson (rth@tamu.edu). + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* clone() is even more special than fork() as it mucks with stacks + and invokes a function in the right context after its all over. */ + +#include +#include +#include +#include + +#define CLONE_VM 0x00000100 +#define CLONE_THREAD 0x00010000 + +/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg, + pid_t *ptid, void *tls, pid_t *ctid); */ + + .text +ENTRY (__clone) + save %sp,-96,%sp + cfi_def_cfa_register(%fp) + cfi_window_save + cfi_register(%o7, %i7) + + /* sanity check arguments */ + orcc %i0,%g0,%g2 + be .Leinval + orcc %i1,%g0,%o1 + be .Leinval + mov %i2,%o0 + + /* The child_stack is the top of the stack, allocate one + whole stack frame from that as this is what the kernel + expects. */ + sub %o1, 96, %o1 + mov %i3, %g3 + mov %i2, %g4 + + /* ptid */ + mov %i4,%o2 + /* tls */ + mov %i5,%o3 + /* ctid */ + ld [%fp+92],%o4 + + /* Do the system call */ + set __NR_clone,%g1 + ta 0x10 + bcs .Lerror + tst %o1 + bne __thread_start + nop + jmpl %i7 + 8, %g0 + restore %o0,%g0,%o0 + +.Leinval: + mov EINVAL, %o0 +.Lerror: + call __errno_location + mov %o0, %i0 + st %i0,[%o0] + jmpl %i7 + 8, %g0 + restore %g0,-1,%o0 +END(__clone) + + .type __thread_start,@function +__thread_start: +#ifdef RESET_PID + sethi %hi(CLONE_THREAD), %l0 + andcc %g4, %l0, %g0 + bne 1f + andcc %g4, CLONE_VM, %g0 + bne,a 2f + mov -1,%o0 + set __NR_getpid,%g1 + ta 0x10 +2: + st %o0,[%g7 + PID] + st %o0,[%g7 + TID] +1: +#endif + mov %g0, %fp /* terminate backtrace */ + call %g2 + mov %g3,%o0 + call exit,0 + nop + + .size __thread_start, .-__thread_start + +weak_alias (__clone, clone) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/crt1.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/crt1.S new file mode 100644 index 00000000..f33a714e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/crt1.S @@ -0,0 +1,134 @@ +/* Startup code for elf{32,64}-sparc + Copyright (C) 1997, 1998, 2002, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson , 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file with other + programs, and to distribute those programs without any restriction + coming from the use of this file. (The GNU Lesser General Public + License restrictions do apply in other respects; for example, they + cover modification of the file, and distribution when not linked + into another program.) + + Note that people who make modified versions of this file are not + obligated to grant this special exception for their modified + versions; it is their choice whether to do so. The GNU Lesser + General Public License gives permission to release a modified + version without this exception; this exception also makes it + possible to release a modified version which carries forward this + exception. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Originally based on glibc's sysdeps/sparc/sparc{32,64}/elf/start.S */ + +#include +#include + +/* macro out the 32 / 64 bit differences */ +#if __WORDSIZE == 32 +# define STACK_BIAS 0 +# define ELE_SIZE 4 +# define LD ld +#else +# define STACK_BIAS 2047 /* see glibc/sysdeps/unix/sysv/linux/sparc/sparc64/sysdep.h */ +# define ELE_SIZE 8 +# define LD ldx +#endif + +.text +.align 4 +.global _start +.type _start,%function +#if defined(__UCLIBC_CTOR_DTOR__) +.type _init,%function +.type _fini,%function +#else +.weak _init +.weak _fini +#endif +.type __uClibc_main,%function +/* Stick in a dummy reference to main(), so that if an application + * is linking when the main() function is in a static library (.a) + * we can be sure that main() actually gets linked in */ +.global main +.type main,%function + +#ifdef __PIC__ +.LLGETPC0: + retl + add %o7, %l7, %l7 +#endif + +_start: +#ifdef __PIC__ + sethi %hi(_GLOBAL_OFFSET_TABLE_-4), %l7 + call .LLGETPC0 + add %l7, %lo(_GLOBAL_OFFSET_TABLE_+4), %l7 +#endif + + /* Terminate the stack frame, and reserve space for functions to + * drop their arguments. */ + mov %g0, %fp + sub %sp, 6*ELE_SIZE, %sp + + /* Extract the arguments and environment as encoded on the stack. The + * argument info starts after one register window (16 words) past the SP. */ + LD [%sp+STACK_BIAS+22*ELE_SIZE], %o1 /* %o1 = argc */ + add %sp, STACK_BIAS+23*ELE_SIZE, %o2 /* %o2 = argv */ + + /* Load the addresses of the user entry points. */ + sethi %hi(main), %o0 + sethi %hi(_init), %o3 + sethi %hi(_fini), %o4 + or %o0, %lo(main), %o0 + or %o3, %lo(_init), %o3 + or %o4, %lo(_fini), %o4 +#ifdef __PIC__ + /* Need a little more magic when building PIC to get addr of main */ + LD [%l7 + %o0], %o0 + LD [%l7 + %o3], %o3 + LD [%l7 + %o4], %o4 +#endif + + /* When starting a binary via the dynamic linker, %g1 contains the + * address of the shared library termination function, which will be + * registered with atexit(). If we are statically linked, this will + * be NULL. */ + mov %g1, %o5 + + /* Let libc do the rest of the initialization, and call main. */ + call __uClibc_main + nop + + /* Die very horribly if exit returns. */ +#if __WORDSIZE == 32 + unimp +#else + illtrap 0 +#endif + +.size _start,.-_start + +/* Define a symbol for the first piece of initialized data. */ +.data +.global __data_start +__data_start: +.long 0 +.weak data_start + data_start = __data_start diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/crti.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/crti.S new file mode 100644 index 00000000..6dfc6c61 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/crti.S @@ -0,0 +1,23 @@ + .file "initfini.c" + + .section .init + .align 4 + .global _init + .type _init, %function + .proc 020 +_init: + !#PROLOGUE# 0 + save %sp, -104, %sp + + .align 4 + + + .section .fini + .align 4 + .global _fini + .type _fini, %function + .proc 020 +_fini: + !#PROLOGUE# 0 + save %sp, -104, %sp + .align 4 diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/crtn.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/crtn.S new file mode 100644 index 00000000..d64ffd02 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/crtn.S @@ -0,0 +1,17 @@ + .file "initfini.c" + + .section .init + .align 4 + .global _init + .type _init, %function + .proc 020 + ret + restore + + .section .fini + .align 4 + .global _fini + .type _fini, %function + .proc 020 + ret + restore diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/fork.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/fork.S new file mode 100644 index 00000000..7ead409f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/fork.S @@ -0,0 +1,49 @@ +/* Copyright (C) 1997, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Miguel de Icaza , 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Code taken from glibc2.2.2/sysdeps/unix/sysv/linux/sparc/vfork.S */ + +#include +#include + +.text +.global __libc_fork +.type __libc_fork,%function +.align 4 + +__libc_fork: + mov __NR_fork, %g1 + ta 0x10 + bcc,a 9000f + nop + save %sp,-96,%sp + call HIDDEN_JUMPTARGET(__errno_location) + nop + st %i0,[%o0] + jmpl %i7+8,%g0 + restore %g0,-1,%o0 + +9000: + sub %o1, 1, %o1 + retl + and %o0, %o1, %o0 + +.size __libc_fork,.-__libc_fork +weak_alias(__libc_fork,fork) +libc_hidden_weak(fork) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/fpu_control.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/fpu_control.h new file mode 100644 index 00000000..41ab0a91 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/fpu_control.h @@ -0,0 +1,75 @@ +/* FPU control word bits. SPARC version. + Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Miguel de Icaza + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FPU_CONTROL_H +#define _FPU_CONTROL_H 1 + + +#include +#include + +/* masking of interrupts */ +#define _FPU_MASK_IM 0x08000000 +#define _FPU_MASK_OM 0x04000000 +#define _FPU_MASK_UM 0x02000000 +#define _FPU_MASK_ZM 0x01000000 +#define _FPU_MASK_PM 0x00800000 + +/* precision control */ +#define _FPU_EXTENDED 0x00000000 /* RECOMMENDED */ +#define _FPU_DOUBLE 0x20000000 +#define _FPU_80BIT 0x30000000 +#define _FPU_SINGLE 0x10000000 /* DO NOT USE */ + +/* rounding control / Sparc */ +#define _FPU_RC_DOWN 0xc0000000 +#define _FPU_RC_UP 0x80000000 +#define _FPU_RC_ZERO 0x40000000 +#define _FPU_RC_NEAREST 0x0 /* RECOMMENDED */ + +#define _FPU_RESERVED 0x30300000 /* Reserved bits in cw */ + + +/* Now two recommended cw */ + +/* Linux and IEEE default: + - extended precision + - rounding to nearest + - no exceptions */ +#define _FPU_DEFAULT 0x0 +#define _FPU_IEEE 0x0 + +/* Type of the control word. */ +typedef unsigned long int fpu_control_t; + +#if __WORDSIZE == 64 +# define _FPU_GETCW(cw) __asm__ ("stx %%fsr,%0" : "=m" (*&cw)) +# define _FPU_SETCW(cw) __asm__ ("ldx %0,%%fsr" : : "m" (*&cw)) +#else +# define _FPU_GETCW(cw) __asm__ ("st %%fsr,%0" : "=m" (*&cw)) +# define _FPU_SETCW(cw) __asm__ ("ld %0,%%fsr" : : "m" (*&cw)) +#endif + +#if 0 +/* Default control word set at startup. */ +extern fpu_control_t __fpu_control; +#endif + +#endif /* fpu_control.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/pipe.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/pipe.S new file mode 100644 index 00000000..94913d48 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/pipe.S @@ -0,0 +1,62 @@ +/* Copyright (C) 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. + + Ported to uClibc by: + Austin Foxley, Ceton Corporation + */ + +#include +#include +#include + +.text +.global pipe +.type pipe, @function +.align 4 + +pipe: + save %sp,-96,%sp + + /* sanity check arguments */ + tst %i0 + be .Lerror + orcc %i1,%g0,%o1 + be .Lerror + mov %i2,%o0 + + /* Do the system call */ + set __NR_pipe,%g1 + ta 0x10 + bcs .Lerror + nop + + st %o0,[%i0] + st %o1,[%i0+4] + ret + restore %g0,%g0,%o0 + +.Lerror: + call HIDDEN_JUMPTARGET(__errno_location) + or %g0,EINVAL,%i0 + st %i0,[%o0] + ret + restore %g0,-1,%o0 + +.size pipe,.-pipe +libc_hidden_def(pipe) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/qp_ops.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/qp_ops.c new file mode 100644 index 00000000..123be53f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/qp_ops.c @@ -0,0 +1,47 @@ +/* XXX add ops from glibc sysdeps/sparc/sparc64/soft-fp */ + +#include +#include + +static void fakedef(void) +{ + fputs("Unimplemented _Q* func called, exiting\n", stderr); + exit(-1); +} + +#ifdef __sparc_v9__ +# define fakedef(sym) strong_alias(fakedef, _Qp_##sym) +#else +# define fakedef(sym) strong_alias(fakedef, _Q_##sym) +#endif + +fakedef(fne) +fakedef(feq) +fakedef(div) +fakedef(flt) +fakedef(fgt) +fakedef(mul) +fakedef(fge) +fakedef(qtoux) +fakedef(uxtoq) +fakedef(sub) +fakedef(dtoq) +fakedef(qtod) +fakedef(qtos) +fakedef(stoq) +fakedef(itoq) +fakedef(add) +#ifndef __sparc_v9__ +fakedef(qtou) +fakedef(utoq) +fakedef(cmp) +fakedef(cmpe) +fakedef(fle) +fakedef(lltoq) +fakedef(neg) +fakedef(qtoi) +fakedef(qtoll) +fakedef(qtoull) +fakedef(sqrt) +fakedef(ulltoq) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/rem.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/rem.S new file mode 100644 index 00000000..595e8ea5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/rem.S @@ -0,0 +1,9 @@ +#include "_math_inc.h" + +#if defined(__CONFIG_SPARC_V9__) || defined(__CONFIG_SPARC_V9B__) +# include "sparcv9/rem.S" +#elif defined(__CONFIG_SPARC_V8__) +# include "sparcv8/rem.S" +#else +# include "sparcv7/rem.S" +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sdiv.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sdiv.S new file mode 100644 index 00000000..7e9a9c92 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sdiv.S @@ -0,0 +1,9 @@ +#include "_math_inc.h" + +#if defined(__CONFIG_SPARC_V9__) || defined(__CONFIG_SPARC_V9B__) +# include "sparcv9/sdiv.S" +#elif defined(__CONFIG_SPARC_V8__) +# include "sparcv8/sdiv.S" +#else +# include "sparcv7/sdiv.S" +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/setjmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/setjmp.S new file mode 100644 index 00000000..796abc76 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/setjmp.S @@ -0,0 +1,70 @@ +/* Copyright (C) 1991, 93, 94, 96, 97, 98 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#define _ASM 1 +#define _SETJMP_H +#include +#define ST_FLUSH_WINDOWS 3 + +.global _setjmp +.type _setjmp,%function +.align 4 +_setjmp: + b 1f + set 0, %o1 +.size _setjmp,.-_setjmp + + + + + +.global setjmp +.type setjmp,%function +.align 4 +setjmp: + set 1, %o1 +.size setjmp,.-setjmp + + + + + +.global __sigsetjmp +.type __sigsetjmp,%function +.align 4 +__sigsetjmp: +1: + /* Save our PC, SP and FP. Save the signal mask if requested with + a tail-call for simplicity; it always returns zero. */ + ta ST_FLUSH_WINDOWS + + st %o7, [%o0 + (JB_PC * 4)] + st %sp, [%o0 + (JB_SP * 4)] + st %fp, [%o0 + (JB_FP * 4)] + + mov %o7, %g1 + call __sigjmp_save + mov %g1, %o7 +.size __sigsetjmp,.-__sigsetjmp + + + +.weak _setjmp +.weak setjmp diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sigaction.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sigaction.c new file mode 100644 index 00000000..a22ac40a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sigaction.c @@ -0,0 +1,92 @@ +/* POSIX.1 sigaction call for Linux/SPARC. + Copyright (C) 1997-2000,2002,2003,2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Miguel de Icaza (miguel@nuclecu.unam.mx), 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. + + Ported to uClibc from glibc: 090520: + Jan Buchholz, KIP, Uni Heidelberg + Austin Foxley, Ceton Corporation +*/ + +#include +#include +#include +#include +#include + + +_syscall5(int, rt_sigaction, int, a, int, b, int, c, int, d, int, e); +static void __rt_sigreturn_stub(void); +static void __sigreturn_stub(void); + +int __libc_sigaction(int sig, const struct sigaction *act, struct sigaction *oact) +{ + int ret; + struct sigaction kact, koact; + unsigned long stub = 0; + + if (act) { + kact.sa_handler = act->sa_handler; + memcpy (&kact.sa_mask, &act->sa_mask, sizeof (sigset_t)); + if (((kact.sa_flags = act->sa_flags) & SA_SIGINFO) != 0) + stub = (unsigned long) &__rt_sigreturn_stub; + else + stub = (unsigned long) &__sigreturn_stub; + stub -= 8; + kact.sa_restorer = NULL; + } + + /* XXX The size argument hopefully will have to be changed to the + * real size of the user-level sigset_t. */ + ret = INLINE_SYSCALL (rt_sigaction, 5, sig, act ? &kact : 0, + oact ? &koact : 0, stub, _NSIG / 8); + + if (oact && ret >= 0) { + oact->sa_handler = koact.sa_handler; + memcpy (&oact->sa_mask, &koact.sa_mask, sizeof (sigset_t)); + oact->sa_flags = koact.sa_flags; + oact->sa_restorer = koact.sa_restorer; + } + return ret; +} + +#ifndef LIBC_SIGACTION +weak_alias(__libc_sigaction,sigaction) +libc_hidden_weak(sigaction) +#endif + +static void +__rt_sigreturn_stub(void) +{ + __asm__( + "mov %0, %%g1\n\t" + "ta 0x10\n\t" + : /* no outputs */ + : "i" (__NR_rt_sigreturn) + ); +} +static void +__sigreturn_stub(void) +{ + __asm__( + "mov %0, %%g1\n\t" + "ta 0x10\n\t" + : /* no outputs */ + : "i" (__NR_sigreturn) + ); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/double.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/double.h new file mode 100644 index 00000000..b012d9d5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/double.h @@ -0,0 +1,264 @@ +/* Software floating-point emulation. + Definitions for IEEE Double Precision + Copyright (C) 1997,1998,1999,2006,2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson (rth@cygnus.com), + Jakub Jelinek (jj@ultra.linux.cz), + David S. Miller (davem@redhat.com) and + Peter Maydell (pmaydell@chiark.greenend.org.uk). + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file into + combinations with other programs, and to distribute those + combinations without any restriction coming from the use of this + file. (The Lesser General Public License restrictions do apply in + other respects; for example, they cover modification of the file, + and distribution when not linked into a combine executable.) + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301, USA. */ + +#if _FP_W_TYPE_SIZE < 32 +#error "Here's a nickel kid. Go buy yourself a real computer." +#endif + +#if _FP_W_TYPE_SIZE < 64 +#define _FP_FRACTBITS_D (2 * _FP_W_TYPE_SIZE) +#else +#define _FP_FRACTBITS_D _FP_W_TYPE_SIZE +#endif + +#define _FP_FRACBITS_D 53 +#define _FP_FRACXBITS_D (_FP_FRACTBITS_D - _FP_FRACBITS_D) +#define _FP_WFRACBITS_D (_FP_WORKBITS + _FP_FRACBITS_D) +#define _FP_WFRACXBITS_D (_FP_FRACTBITS_D - _FP_WFRACBITS_D) +#define _FP_EXPBITS_D 11 +#define _FP_EXPBIAS_D 1023 +#define _FP_EXPMAX_D 2047 + +#define _FP_QNANBIT_D \ + ((_FP_W_TYPE)1 << (_FP_FRACBITS_D-2) % _FP_W_TYPE_SIZE) +#define _FP_QNANBIT_SH_D \ + ((_FP_W_TYPE)1 << (_FP_FRACBITS_D-2+_FP_WORKBITS) % _FP_W_TYPE_SIZE) +#define _FP_IMPLBIT_D \ + ((_FP_W_TYPE)1 << (_FP_FRACBITS_D-1) % _FP_W_TYPE_SIZE) +#define _FP_IMPLBIT_SH_D \ + ((_FP_W_TYPE)1 << (_FP_FRACBITS_D-1+_FP_WORKBITS) % _FP_W_TYPE_SIZE) +#define _FP_OVERFLOW_D \ + ((_FP_W_TYPE)1 << _FP_WFRACBITS_D % _FP_W_TYPE_SIZE) + +typedef float DFtype __attribute__((mode(DF))); + +#if _FP_W_TYPE_SIZE < 64 + +union _FP_UNION_D +{ + DFtype flt; + struct { +#if __BYTE_ORDER == __BIG_ENDIAN + unsigned sign : 1; + unsigned exp : _FP_EXPBITS_D; + unsigned frac1 : _FP_FRACBITS_D - (_FP_IMPLBIT_D != 0) - _FP_W_TYPE_SIZE; + unsigned frac0 : _FP_W_TYPE_SIZE; +#else + unsigned frac0 : _FP_W_TYPE_SIZE; + unsigned frac1 : _FP_FRACBITS_D - (_FP_IMPLBIT_D != 0) - _FP_W_TYPE_SIZE; + unsigned exp : _FP_EXPBITS_D; + unsigned sign : 1; +#endif + } bits __attribute__((packed)); +}; + +#define FP_DECL_D(X) _FP_DECL(2,X) +#define FP_UNPACK_RAW_D(X,val) _FP_UNPACK_RAW_2(D,X,val) +#define FP_UNPACK_RAW_DP(X,val) _FP_UNPACK_RAW_2_P(D,X,val) +#define FP_PACK_RAW_D(val,X) _FP_PACK_RAW_2(D,val,X) +#define FP_PACK_RAW_DP(val,X) \ + do { \ + if (!FP_INHIBIT_RESULTS) \ + _FP_PACK_RAW_2_P(D,val,X); \ + } while (0) + +#define FP_UNPACK_D(X,val) \ + do { \ + _FP_UNPACK_RAW_2(D,X,val); \ + _FP_UNPACK_CANONICAL(D,2,X); \ + } while (0) + +#define FP_UNPACK_DP(X,val) \ + do { \ + _FP_UNPACK_RAW_2_P(D,X,val); \ + _FP_UNPACK_CANONICAL(D,2,X); \ + } while (0) + +#define FP_UNPACK_SEMIRAW_D(X,val) \ + do { \ + _FP_UNPACK_RAW_2(D,X,val); \ + _FP_UNPACK_SEMIRAW(D,2,X); \ + } while (0) + +#define FP_UNPACK_SEMIRAW_DP(X,val) \ + do { \ + _FP_UNPACK_RAW_2_P(D,X,val); \ + _FP_UNPACK_SEMIRAW(D,2,X); \ + } while (0) + +#define FP_PACK_D(val,X) \ + do { \ + _FP_PACK_CANONICAL(D,2,X); \ + _FP_PACK_RAW_2(D,val,X); \ + } while (0) + +#define FP_PACK_DP(val,X) \ + do { \ + _FP_PACK_CANONICAL(D,2,X); \ + if (!FP_INHIBIT_RESULTS) \ + _FP_PACK_RAW_2_P(D,val,X); \ + } while (0) + +#define FP_PACK_SEMIRAW_D(val,X) \ + do { \ + _FP_PACK_SEMIRAW(D,2,X); \ + _FP_PACK_RAW_2(D,val,X); \ + } while (0) + +#define FP_PACK_SEMIRAW_DP(val,X) \ + do { \ + _FP_PACK_SEMIRAW(D,2,X); \ + if (!FP_INHIBIT_RESULTS) \ + _FP_PACK_RAW_2_P(D,val,X); \ + } while (0) + +#define FP_ISSIGNAN_D(X) _FP_ISSIGNAN(D,2,X) +#define FP_NEG_D(R,X) _FP_NEG(D,2,R,X) +#define FP_ADD_D(R,X,Y) _FP_ADD(D,2,R,X,Y) +#define FP_SUB_D(R,X,Y) _FP_SUB(D,2,R,X,Y) +#define FP_MUL_D(R,X,Y) _FP_MUL(D,2,R,X,Y) +#define FP_DIV_D(R,X,Y) _FP_DIV(D,2,R,X,Y) +#define FP_SQRT_D(R,X) _FP_SQRT(D,2,R,X) +#define _FP_SQRT_MEAT_D(R,S,T,X,Q) _FP_SQRT_MEAT_2(R,S,T,X,Q) + +#define FP_CMP_D(r,X,Y,un) _FP_CMP(D,2,r,X,Y,un) +#define FP_CMP_EQ_D(r,X,Y) _FP_CMP_EQ(D,2,r,X,Y) +#define FP_CMP_UNORD_D(r,X,Y) _FP_CMP_UNORD(D,2,r,X,Y) + +#define FP_TO_INT_D(r,X,rsz,rsg) _FP_TO_INT(D,2,r,X,rsz,rsg) +#define FP_FROM_INT_D(X,r,rs,rt) _FP_FROM_INT(D,2,X,r,rs,rt) + +#define _FP_FRAC_HIGH_D(X) _FP_FRAC_HIGH_2(X) +#define _FP_FRAC_HIGH_RAW_D(X) _FP_FRAC_HIGH_2(X) + +#else + +union _FP_UNION_D +{ + DFtype flt; + struct { +#if __BYTE_ORDER == __BIG_ENDIAN + unsigned sign : 1; + unsigned exp : _FP_EXPBITS_D; + _FP_W_TYPE frac : _FP_FRACBITS_D - (_FP_IMPLBIT_D != 0); +#else + _FP_W_TYPE frac : _FP_FRACBITS_D - (_FP_IMPLBIT_D != 0); + unsigned exp : _FP_EXPBITS_D; + unsigned sign : 1; +#endif + } bits __attribute__((packed)); +}; + +#define FP_DECL_D(X) _FP_DECL(1,X) +#define FP_UNPACK_RAW_D(X,val) _FP_UNPACK_RAW_1(D,X,val) +#define FP_UNPACK_RAW_DP(X,val) _FP_UNPACK_RAW_1_P(D,X,val) +#define FP_PACK_RAW_D(val,X) _FP_PACK_RAW_1(D,val,X) +#define FP_PACK_RAW_DP(val,X) \ + do { \ + if (!FP_INHIBIT_RESULTS) \ + _FP_PACK_RAW_1_P(D,val,X); \ + } while (0) + +#define FP_UNPACK_D(X,val) \ + do { \ + _FP_UNPACK_RAW_1(D,X,val); \ + _FP_UNPACK_CANONICAL(D,1,X); \ + } while (0) + +#define FP_UNPACK_DP(X,val) \ + do { \ + _FP_UNPACK_RAW_1_P(D,X,val); \ + _FP_UNPACK_CANONICAL(D,1,X); \ + } while (0) + +#define FP_UNPACK_SEMIRAW_D(X,val) \ + do { \ + _FP_UNPACK_RAW_2(1,X,val); \ + _FP_UNPACK_SEMIRAW(D,1,X); \ + } while (0) + +#define FP_UNPACK_SEMIRAW_DP(X,val) \ + do { \ + _FP_UNPACK_RAW_2_P(1,X,val); \ + _FP_UNPACK_SEMIRAW(D,1,X); \ + } while (0) + +#define FP_PACK_D(val,X) \ + do { \ + _FP_PACK_CANONICAL(D,1,X); \ + _FP_PACK_RAW_1(D,val,X); \ + } while (0) + +#define FP_PACK_DP(val,X) \ + do { \ + _FP_PACK_CANONICAL(D,1,X); \ + if (!FP_INHIBIT_RESULTS) \ + _FP_PACK_RAW_1_P(D,val,X); \ + } while (0) + +#define FP_PACK_SEMIRAW_D(val,X) \ + do { \ + _FP_PACK_SEMIRAW(D,1,X); \ + _FP_PACK_RAW_1(D,val,X); \ + } while (0) + +#define FP_PACK_SEMIRAW_DP(val,X) \ + do { \ + _FP_PACK_SEMIRAW(D,1,X); \ + if (!FP_INHIBIT_RESULTS) \ + _FP_PACK_RAW_1_P(D,val,X); \ + } while (0) + +#define FP_ISSIGNAN_D(X) _FP_ISSIGNAN(D,1,X) +#define FP_NEG_D(R,X) _FP_NEG(D,1,R,X) +#define FP_ADD_D(R,X,Y) _FP_ADD(D,1,R,X,Y) +#define FP_SUB_D(R,X,Y) _FP_SUB(D,1,R,X,Y) +#define FP_MUL_D(R,X,Y) _FP_MUL(D,1,R,X,Y) +#define FP_DIV_D(R,X,Y) _FP_DIV(D,1,R,X,Y) +#define FP_SQRT_D(R,X) _FP_SQRT(D,1,R,X) +#define _FP_SQRT_MEAT_D(R,S,T,X,Q) _FP_SQRT_MEAT_1(R,S,T,X,Q) + +/* The implementation of _FP_MUL_D and _FP_DIV_D should be chosen by + the target machine. */ + +#define FP_CMP_D(r,X,Y,un) _FP_CMP(D,1,r,X,Y,un) +#define FP_CMP_EQ_D(r,X,Y) _FP_CMP_EQ(D,1,r,X,Y) +#define FP_CMP_UNORD_D(r,X,Y) _FP_CMP_UNORD(D,1,r,X,Y) + +#define FP_TO_INT_D(r,X,rsz,rsg) _FP_TO_INT(D,1,r,X,rsz,rsg) +#define FP_FROM_INT_D(X,r,rs,rt) _FP_FROM_INT(D,1,X,r,rs,rt) + +#define _FP_FRAC_HIGH_D(X) _FP_FRAC_HIGH_1(X) +#define _FP_FRAC_HIGH_RAW_D(X) _FP_FRAC_HIGH_1(X) + +#endif /* W_TYPE_SIZE < 64 */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/extended.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/extended.h new file mode 100644 index 00000000..e5f16deb --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/extended.h @@ -0,0 +1,431 @@ +/* Software floating-point emulation. + Definitions for IEEE Extended Precision. + Copyright (C) 1999,2006,2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek (jj@ultra.linux.cz). + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file into + combinations with other programs, and to distribute those + combinations without any restriction coming from the use of this + file. (The Lesser General Public License restrictions do apply in + other respects; for example, they cover modification of the file, + and distribution when not linked into a combine executable.) + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301, USA. */ + +#if _FP_W_TYPE_SIZE < 32 +#error "Here's a nickel, kid. Go buy yourself a real computer." +#endif + +#if _FP_W_TYPE_SIZE < 64 +#define _FP_FRACTBITS_E (4*_FP_W_TYPE_SIZE) +#else +#define _FP_FRACTBITS_E (2*_FP_W_TYPE_SIZE) +#endif + +#define _FP_FRACBITS_E 64 +#define _FP_FRACXBITS_E (_FP_FRACTBITS_E - _FP_FRACBITS_E) +#define _FP_WFRACBITS_E (_FP_WORKBITS + _FP_FRACBITS_E) +#define _FP_WFRACXBITS_E (_FP_FRACTBITS_E - _FP_WFRACBITS_E) +#define _FP_EXPBITS_E 15 +#define _FP_EXPBIAS_E 16383 +#define _FP_EXPMAX_E 32767 + +#define _FP_QNANBIT_E \ + ((_FP_W_TYPE)1 << (_FP_FRACBITS_E-2) % _FP_W_TYPE_SIZE) +#define _FP_QNANBIT_SH_E \ + ((_FP_W_TYPE)1 << (_FP_FRACBITS_E-2+_FP_WORKBITS) % _FP_W_TYPE_SIZE) +#define _FP_IMPLBIT_E \ + ((_FP_W_TYPE)1 << (_FP_FRACBITS_E-1) % _FP_W_TYPE_SIZE) +#define _FP_IMPLBIT_SH_E \ + ((_FP_W_TYPE)1 << (_FP_FRACBITS_E-1+_FP_WORKBITS) % _FP_W_TYPE_SIZE) +#define _FP_OVERFLOW_E \ + ((_FP_W_TYPE)1 << (_FP_WFRACBITS_E % _FP_W_TYPE_SIZE)) + +typedef float XFtype __attribute__((mode(XF))); + +#if _FP_W_TYPE_SIZE < 64 + +union _FP_UNION_E +{ + XFtype flt; + struct + { +#if __BYTE_ORDER == __BIG_ENDIAN + unsigned long pad1 : _FP_W_TYPE_SIZE; + unsigned long pad2 : (_FP_W_TYPE_SIZE - 1 - _FP_EXPBITS_E); + unsigned long sign : 1; + unsigned long exp : _FP_EXPBITS_E; + unsigned long frac1 : _FP_W_TYPE_SIZE; + unsigned long frac0 : _FP_W_TYPE_SIZE; +#else + unsigned long frac0 : _FP_W_TYPE_SIZE; + unsigned long frac1 : _FP_W_TYPE_SIZE; + unsigned exp : _FP_EXPBITS_E; + unsigned sign : 1; +#endif /* not bigendian */ + } bits __attribute__((packed)); +}; + + +#define FP_DECL_E(X) _FP_DECL(4,X) + +#define FP_UNPACK_RAW_E(X, val) \ + do { \ + union _FP_UNION_E _flo; _flo.flt = (val); \ + \ + X##_f[2] = 0; X##_f[3] = 0; \ + X##_f[0] = _flo.bits.frac0; \ + X##_f[1] = _flo.bits.frac1; \ + X##_e = _flo.bits.exp; \ + X##_s = _flo.bits.sign; \ + } while (0) + +#define FP_UNPACK_RAW_EP(X, val) \ + do { \ + union _FP_UNION_E *_flo = \ + (union _FP_UNION_E *)(val); \ + \ + X##_f[2] = 0; X##_f[3] = 0; \ + X##_f[0] = _flo->bits.frac0; \ + X##_f[1] = _flo->bits.frac1; \ + X##_e = _flo->bits.exp; \ + X##_s = _flo->bits.sign; \ + } while (0) + +#define FP_PACK_RAW_E(val, X) \ + do { \ + union _FP_UNION_E _flo; \ + \ + if (X##_e) X##_f[1] |= _FP_IMPLBIT_E; \ + else X##_f[1] &= ~(_FP_IMPLBIT_E); \ + _flo.bits.frac0 = X##_f[0]; \ + _flo.bits.frac1 = X##_f[1]; \ + _flo.bits.exp = X##_e; \ + _flo.bits.sign = X##_s; \ + \ + (val) = _flo.flt; \ + } while (0) + +#define FP_PACK_RAW_EP(val, X) \ + do { \ + if (!FP_INHIBIT_RESULTS) \ + { \ + union _FP_UNION_E *_flo = \ + (union _FP_UNION_E *)(val); \ + \ + if (X##_e) X##_f[1] |= _FP_IMPLBIT_E; \ + else X##_f[1] &= ~(_FP_IMPLBIT_E); \ + _flo->bits.frac0 = X##_f[0]; \ + _flo->bits.frac1 = X##_f[1]; \ + _flo->bits.exp = X##_e; \ + _flo->bits.sign = X##_s; \ + } \ + } while (0) + +#define FP_UNPACK_E(X,val) \ + do { \ + FP_UNPACK_RAW_E(X,val); \ + _FP_UNPACK_CANONICAL(E,4,X); \ + } while (0) + +#define FP_UNPACK_EP(X,val) \ + do { \ + FP_UNPACK_RAW_EP(X,val); \ + _FP_UNPACK_CANONICAL(E,4,X); \ + } while (0) + +#define FP_UNPACK_SEMIRAW_E(X,val) \ + do { \ + FP_UNPACK_RAW_E(X,val); \ + _FP_UNPACK_SEMIRAW(E,4,X); \ + } while (0) + +#define FP_UNPACK_SEMIRAW_EP(X,val) \ + do { \ + FP_UNPACK_RAW_EP(X,val); \ + _FP_UNPACK_SEMIRAW(E,4,X); \ + } while (0) + +#define FP_PACK_E(val,X) \ + do { \ + _FP_PACK_CANONICAL(E,4,X); \ + FP_PACK_RAW_E(val,X); \ + } while (0) + +#define FP_PACK_EP(val,X) \ + do { \ + _FP_PACK_CANONICAL(E,4,X); \ + FP_PACK_RAW_EP(val,X); \ + } while (0) + +#define FP_PACK_SEMIRAW_E(val,X) \ + do { \ + _FP_PACK_SEMIRAW(E,4,X); \ + FP_PACK_RAW_E(val,X); \ + } while (0) + +#define FP_PACK_SEMIRAW_EP(val,X) \ + do { \ + _FP_PACK_SEMIRAW(E,4,X); \ + FP_PACK_RAW_EP(val,X); \ + } while (0) + +#define FP_ISSIGNAN_E(X) _FP_ISSIGNAN(E,4,X) +#define FP_NEG_E(R,X) _FP_NEG(E,4,R,X) +#define FP_ADD_E(R,X,Y) _FP_ADD(E,4,R,X,Y) +#define FP_SUB_E(R,X,Y) _FP_SUB(E,4,R,X,Y) +#define FP_MUL_E(R,X,Y) _FP_MUL(E,4,R,X,Y) +#define FP_DIV_E(R,X,Y) _FP_DIV(E,4,R,X,Y) +#define FP_SQRT_E(R,X) _FP_SQRT(E,4,R,X) + +/* + * Square root algorithms: + * We have just one right now, maybe Newton approximation + * should be added for those machines where division is fast. + * This has special _E version because standard _4 square + * root would not work (it has to start normally with the + * second word and not the first), but as we have to do it + * anyway, we optimize it by doing most of the calculations + * in two UWtype registers instead of four. + */ + +#define _FP_SQRT_MEAT_E(R, S, T, X, q) \ + do { \ + q = (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE - 1); \ + _FP_FRAC_SRL_4(X, (_FP_WORKBITS)); \ + while (q) \ + { \ + T##_f[1] = S##_f[1] + q; \ + if (T##_f[1] <= X##_f[1]) \ + { \ + S##_f[1] = T##_f[1] + q; \ + X##_f[1] -= T##_f[1]; \ + R##_f[1] += q; \ + } \ + _FP_FRAC_SLL_2(X, 1); \ + q >>= 1; \ + } \ + q = (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE - 1); \ + while (q) \ + { \ + T##_f[0] = S##_f[0] + q; \ + T##_f[1] = S##_f[1]; \ + if (T##_f[1] < X##_f[1] || \ + (T##_f[1] == X##_f[1] && \ + T##_f[0] <= X##_f[0])) \ + { \ + S##_f[0] = T##_f[0] + q; \ + S##_f[1] += (T##_f[0] > S##_f[0]); \ + _FP_FRAC_DEC_2(X, T); \ + R##_f[0] += q; \ + } \ + _FP_FRAC_SLL_2(X, 1); \ + q >>= 1; \ + } \ + _FP_FRAC_SLL_4(R, (_FP_WORKBITS)); \ + if (X##_f[0] | X##_f[1]) \ + { \ + if (S##_f[1] < X##_f[1] || \ + (S##_f[1] == X##_f[1] && \ + S##_f[0] < X##_f[0])) \ + R##_f[0] |= _FP_WORK_ROUND; \ + R##_f[0] |= _FP_WORK_STICKY; \ + } \ + } while (0) + +#define FP_CMP_E(r,X,Y,un) _FP_CMP(E,4,r,X,Y,un) +#define FP_CMP_EQ_E(r,X,Y) _FP_CMP_EQ(E,4,r,X,Y) +#define FP_CMP_UNORD_E(r,X,Y) _FP_CMP_UNORD(E,4,r,X,Y) + +#define FP_TO_INT_E(r,X,rsz,rsg) _FP_TO_INT(E,4,r,X,rsz,rsg) +#define FP_FROM_INT_E(X,r,rs,rt) _FP_FROM_INT(E,4,X,r,rs,rt) + +#define _FP_FRAC_HIGH_E(X) (X##_f[2]) +#define _FP_FRAC_HIGH_RAW_E(X) (X##_f[1]) + +#else /* not _FP_W_TYPE_SIZE < 64 */ +union _FP_UNION_E +{ + XFtype flt; + struct { +#if __BYTE_ORDER == __BIG_ENDIAN + _FP_W_TYPE pad : (_FP_W_TYPE_SIZE - 1 - _FP_EXPBITS_E); + unsigned sign : 1; + unsigned exp : _FP_EXPBITS_E; + _FP_W_TYPE frac : _FP_W_TYPE_SIZE; +#else + _FP_W_TYPE frac : _FP_W_TYPE_SIZE; + unsigned exp : _FP_EXPBITS_E; + unsigned sign : 1; +#endif + } bits; +}; + +#define FP_DECL_E(X) _FP_DECL(2,X) + +#define FP_UNPACK_RAW_E(X, val) \ + do { \ + union _FP_UNION_E _flo; _flo.flt = (val); \ + \ + X##_f0 = _flo.bits.frac; \ + X##_f1 = 0; \ + X##_e = _flo.bits.exp; \ + X##_s = _flo.bits.sign; \ + } while (0) + +#define FP_UNPACK_RAW_EP(X, val) \ + do { \ + union _FP_UNION_E *_flo = \ + (union _FP_UNION_E *)(val); \ + \ + X##_f0 = _flo->bits.frac; \ + X##_f1 = 0; \ + X##_e = _flo->bits.exp; \ + X##_s = _flo->bits.sign; \ + } while (0) + +#define FP_PACK_RAW_E(val, X) \ + do { \ + union _FP_UNION_E _flo; \ + \ + if (X##_e) X##_f0 |= _FP_IMPLBIT_E; \ + else X##_f0 &= ~(_FP_IMPLBIT_E); \ + _flo.bits.frac = X##_f0; \ + _flo.bits.exp = X##_e; \ + _flo.bits.sign = X##_s; \ + \ + (val) = _flo.flt; \ + } while (0) + +#define FP_PACK_RAW_EP(fs, val, X) \ + do { \ + if (!FP_INHIBIT_RESULTS) \ + { \ + union _FP_UNION_E *_flo = \ + (union _FP_UNION_E *)(val); \ + \ + if (X##_e) X##_f0 |= _FP_IMPLBIT_E; \ + else X##_f0 &= ~(_FP_IMPLBIT_E); \ + _flo->bits.frac = X##_f0; \ + _flo->bits.exp = X##_e; \ + _flo->bits.sign = X##_s; \ + } \ + } while (0) + + +#define FP_UNPACK_E(X,val) \ + do { \ + FP_UNPACK_RAW_E(X,val); \ + _FP_UNPACK_CANONICAL(E,2,X); \ + } while (0) + +#define FP_UNPACK_EP(X,val) \ + do { \ + FP_UNPACK_RAW_EP(X,val); \ + _FP_UNPACK_CANONICAL(E,2,X); \ + } while (0) + +#define FP_UNPACK_SEMIRAW_E(X,val) \ + do { \ + FP_UNPACK_RAW_E(X,val); \ + _FP_UNPACK_SEMIRAW(E,2,X); \ + } while (0) + +#define FP_UNPACK_SEMIRAW_EP(X,val) \ + do { \ + FP_UNPACK_RAW_EP(X,val); \ + _FP_UNPACK_SEMIRAW(E,2,X); \ + } while (0) + +#define FP_PACK_E(val,X) \ + do { \ + _FP_PACK_CANONICAL(E,2,X); \ + FP_PACK_RAW_E(val,X); \ + } while (0) + +#define FP_PACK_EP(val,X) \ + do { \ + _FP_PACK_CANONICAL(E,2,X); \ + FP_PACK_RAW_EP(val,X); \ + } while (0) + +#define FP_PACK_SEMIRAW_E(val,X) \ + do { \ + _FP_PACK_SEMIRAW(E,2,X); \ + FP_PACK_RAW_E(val,X); \ + } while (0) + +#define FP_PACK_SEMIRAW_EP(val,X) \ + do { \ + _FP_PACK_SEMIRAW(E,2,X); \ + FP_PACK_RAW_EP(val,X); \ + } while (0) + +#define FP_ISSIGNAN_E(X) _FP_ISSIGNAN(E,2,X) +#define FP_NEG_E(R,X) _FP_NEG(E,2,R,X) +#define FP_ADD_E(R,X,Y) _FP_ADD(E,2,R,X,Y) +#define FP_SUB_E(R,X,Y) _FP_SUB(E,2,R,X,Y) +#define FP_MUL_E(R,X,Y) _FP_MUL(E,2,R,X,Y) +#define FP_DIV_E(R,X,Y) _FP_DIV(E,2,R,X,Y) +#define FP_SQRT_E(R,X) _FP_SQRT(E,2,R,X) + +/* + * Square root algorithms: + * We have just one right now, maybe Newton approximation + * should be added for those machines where division is fast. + * We optimize it by doing most of the calculations + * in one UWtype registers instead of two, although we don't + * have to. + */ +#define _FP_SQRT_MEAT_E(R, S, T, X, q) \ + do { \ + q = (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE - 1); \ + _FP_FRAC_SRL_2(X, (_FP_WORKBITS)); \ + while (q) \ + { \ + T##_f0 = S##_f0 + q; \ + if (T##_f0 <= X##_f0) \ + { \ + S##_f0 = T##_f0 + q; \ + X##_f0 -= T##_f0; \ + R##_f0 += q; \ + } \ + _FP_FRAC_SLL_1(X, 1); \ + q >>= 1; \ + } \ + _FP_FRAC_SLL_2(R, (_FP_WORKBITS)); \ + if (X##_f0) \ + { \ + if (S##_f0 < X##_f0) \ + R##_f0 |= _FP_WORK_ROUND; \ + R##_f0 |= _FP_WORK_STICKY; \ + } \ + } while (0) + +#define FP_CMP_E(r,X,Y,un) _FP_CMP(E,2,r,X,Y,un) +#define FP_CMP_EQ_E(r,X,Y) _FP_CMP_EQ(E,2,r,X,Y) +#define FP_CMP_UNORD_E(r,X,Y) _FP_CMP_UNORD(E,2,r,X,Y) + +#define FP_TO_INT_E(r,X,rsz,rsg) _FP_TO_INT(E,2,r,X,rsz,rsg) +#define FP_FROM_INT_E(X,r,rs,rt) _FP_FROM_INT(E,2,X,r,rs,rt) + +#define _FP_FRAC_HIGH_E(X) (X##_f1) +#define _FP_FRAC_HIGH_RAW_E(X) (X##_f0) + +#endif /* not _FP_W_TYPE_SIZE < 64 */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/longlong.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/longlong.h new file mode 100644 index 00000000..a2f38ae2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/longlong.h @@ -0,0 +1,1461 @@ +/* longlong.h -- definitions for mixed size 32/64 bit arithmetic. + Copyright (C) 1991, 1992, 1994, 1995, 1996, 1997, 1998, 1999, 2000, + 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. + + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* You have to define the following before including this file: + + UWtype -- An unsigned type, default type for operations (typically a "word") + UHWtype -- An unsigned type, at least half the size of UWtype. + UDWtype -- An unsigned type, at least twice as large a UWtype + W_TYPE_SIZE -- size in bits of UWtype + + UQItype -- Unsigned 8 bit type. + SItype, USItype -- Signed and unsigned 32 bit types. + DItype, UDItype -- Signed and unsigned 64 bit types. + + On a 32 bit machine UWtype should typically be USItype; + on a 64 bit machine, UWtype should typically be UDItype. */ + +#define __BITS4 (W_TYPE_SIZE / 4) +#define __ll_B ((UWtype) 1 << (W_TYPE_SIZE / 2)) +#define __ll_lowpart(t) ((UWtype) (t) & (__ll_B - 1)) +#define __ll_highpart(t) ((UWtype) (t) >> (W_TYPE_SIZE / 2)) + +#ifndef W_TYPE_SIZE +#define W_TYPE_SIZE 32 +#define UWtype USItype +#define UHWtype USItype +#define UDWtype UDItype +#endif + +extern const UQItype __clz_tab[256] attribute_hidden; + +/* Define auxiliary asm macros. + + 1) umul_ppmm(high_prod, low_prod, multiplier, multiplicand) multiplies two + UWtype integers MULTIPLIER and MULTIPLICAND, and generates a two UWtype + word product in HIGH_PROD and LOW_PROD. + + 2) __umulsidi3(a,b) multiplies two UWtype integers A and B, and returns a + UDWtype product. This is just a variant of umul_ppmm. + + 3) udiv_qrnnd(quotient, remainder, high_numerator, low_numerator, + denominator) divides a UDWtype, composed by the UWtype integers + HIGH_NUMERATOR and LOW_NUMERATOR, by DENOMINATOR and places the quotient + in QUOTIENT and the remainder in REMAINDER. HIGH_NUMERATOR must be less + than DENOMINATOR for correct operation. If, in addition, the most + significant bit of DENOMINATOR must be 1, then the pre-processor symbol + UDIV_NEEDS_NORMALIZATION is defined to 1. + + 4) sdiv_qrnnd(quotient, remainder, high_numerator, low_numerator, + denominator). Like udiv_qrnnd but the numbers are signed. The quotient + is rounded towards 0. + + 5) count_leading_zeros(count, x) counts the number of zero-bits from the + msb to the first nonzero bit in the UWtype X. This is the number of + steps X needs to be shifted left to set the msb. Undefined for X == 0, + unless the symbol COUNT_LEADING_ZEROS_0 is defined to some value. + + 6) count_trailing_zeros(count, x) like count_leading_zeros, but counts + from the least significant end. + + 7) add_ssaaaa(high_sum, low_sum, high_addend_1, low_addend_1, + high_addend_2, low_addend_2) adds two UWtype integers, composed by + HIGH_ADDEND_1 and LOW_ADDEND_1, and HIGH_ADDEND_2 and LOW_ADDEND_2 + respectively. The result is placed in HIGH_SUM and LOW_SUM. Overflow + (i.e. carry out) is not stored anywhere, and is lost. + + 8) sub_ddmmss(high_difference, low_difference, high_minuend, low_minuend, + high_subtrahend, low_subtrahend) subtracts two two-word UWtype integers, + composed by HIGH_MINUEND_1 and LOW_MINUEND_1, and HIGH_SUBTRAHEND_2 and + LOW_SUBTRAHEND_2 respectively. The result is placed in HIGH_DIFFERENCE + and LOW_DIFFERENCE. Overflow (i.e. carry out) is not stored anywhere, + and is lost. + + If any of these macros are left undefined for a particular CPU, + C macros are used. */ + +/* The CPUs come in alphabetical order below. + + Please add support for more CPUs here, or improve the current support + for the CPUs below! + (E.g. WE32100, IBM360.) */ + +#if defined (__GNUC__) && !defined (NO_ASM) + +/* We sometimes need to clobber "cc" with gcc2, but that would not be + understood by gcc1. Use cpp to avoid major code duplication. */ +#if __GNUC__ < 2 +#define __CLOBBER_CC +#define __AND_CLOBBER_CC +#else /* __GNUC__ >= 2 */ +#define __CLOBBER_CC : "cc" +#define __AND_CLOBBER_CC , "cc" +#endif /* __GNUC__ < 2 */ + +#if defined (__alpha) && W_TYPE_SIZE == 64 +#define umul_ppmm(ph, pl, m0, m1) \ + do { \ + UDItype __m0 = (m0), __m1 = (m1); \ + (ph) = __builtin_alpha_umulh (__m0, __m1); \ + (pl) = __m0 * __m1; \ + } while (0) +#define UMUL_TIME 46 +#ifndef LONGLONG_STANDALONE +#define udiv_qrnnd(q, r, n1, n0, d) \ + do { UDItype __r; \ + (q) = __udiv_qrnnd (&__r, (n1), (n0), (d)); \ + (r) = __r; \ + } while (0) +extern UDItype __udiv_qrnnd (UDItype *, UDItype, UDItype, UDItype); +#define UDIV_TIME 220 +#endif /* LONGLONG_STANDALONE */ +#ifdef __alpha_cix__ +#define count_leading_zeros(COUNT,X) ((COUNT) = __builtin_clzl (X)) +#define count_trailing_zeros(COUNT,X) ((COUNT) = __builtin_ctzl (X)) +#define COUNT_LEADING_ZEROS_0 64 +#else +#define count_leading_zeros(COUNT,X) \ + do { \ + UDItype __xr = (X), __t, __a; \ + __t = __builtin_alpha_cmpbge (0, __xr); \ + __a = __clz_tab[__t ^ 0xff] - 1; \ + __t = __builtin_alpha_extbl (__xr, __a); \ + (COUNT) = 64 - (__clz_tab[__t] + __a*8); \ + } while (0) +#define count_trailing_zeros(COUNT,X) \ + do { \ + UDItype __xr = (X), __t, __a; \ + __t = __builtin_alpha_cmpbge (0, __xr); \ + __t = ~__t & -~__t; \ + __a = ((__t & 0xCC) != 0) * 2; \ + __a += ((__t & 0xF0) != 0) * 4; \ + __a += ((__t & 0xAA) != 0); \ + __t = __builtin_alpha_extbl (__xr, __a); \ + __a <<= 3; \ + __t &= -__t; \ + __a += ((__t & 0xCC) != 0) * 2; \ + __a += ((__t & 0xF0) != 0) * 4; \ + __a += ((__t & 0xAA) != 0); \ + (COUNT) = __a; \ + } while (0) +#endif /* __alpha_cix__ */ +#endif /* __alpha */ + +#if defined (__arc__) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("add.f %1, %4, %5\n\tadc %0, %2, %3" \ + : "=r" ((USItype) (sh)), \ + "=&r" ((USItype) (sl)) \ + : "%r" ((USItype) (ah)), \ + "rIJ" ((USItype) (bh)), \ + "%r" ((USItype) (al)), \ + "rIJ" ((USItype) (bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("sub.f %1, %4, %5\n\tsbc %0, %2, %3" \ + : "=r" ((USItype) (sh)), \ + "=&r" ((USItype) (sl)) \ + : "r" ((USItype) (ah)), \ + "rIJ" ((USItype) (bh)), \ + "r" ((USItype) (al)), \ + "rIJ" ((USItype) (bl))) +/* Call libgcc routine. */ +#define umul_ppmm(w1, w0, u, v) \ +do { \ + DWunion __w; \ + __w.ll = __umulsidi3 (u, v); \ + w1 = __w.s.high; \ + w0 = __w.s.low; \ +} while (0) +#define __umulsidi3 __umulsidi3 +UDItype __umulsidi3 (USItype, USItype); +#endif + +#if defined (__arm__) && !defined (__thumb__) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("adds %1, %4, %5\n\tadc %0, %2, %3" \ + : "=r" ((USItype) (sh)), \ + "=&r" ((USItype) (sl)) \ + : "%r" ((USItype) (ah)), \ + "rI" ((USItype) (bh)), \ + "%r" ((USItype) (al)), \ + "rI" ((USItype) (bl)) __CLOBBER_CC) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("subs %1, %4, %5\n\tsbc %0, %2, %3" \ + : "=r" ((USItype) (sh)), \ + "=&r" ((USItype) (sl)) \ + : "r" ((USItype) (ah)), \ + "rI" ((USItype) (bh)), \ + "r" ((USItype) (al)), \ + "rI" ((USItype) (bl)) __CLOBBER_CC) +#define umul_ppmm(xh, xl, a, b) \ +{register USItype __t0, __t1, __t2; \ + __asm__ ("%@ Inlined umul_ppmm\n" \ + " mov %2, %5, lsr #16\n" \ + " mov %0, %6, lsr #16\n" \ + " bic %3, %5, %2, lsl #16\n" \ + " bic %4, %6, %0, lsl #16\n" \ + " mul %1, %3, %4\n" \ + " mul %4, %2, %4\n" \ + " mul %3, %0, %3\n" \ + " mul %0, %2, %0\n" \ + " adds %3, %4, %3\n" \ + " addcs %0, %0, #65536\n" \ + " adds %1, %1, %3, lsl #16\n" \ + " adc %0, %0, %3, lsr #16" \ + : "=&r" ((USItype) (xh)), \ + "=r" ((USItype) (xl)), \ + "=&r" (__t0), "=&r" (__t1), "=r" (__t2) \ + : "r" ((USItype) (a)), \ + "r" ((USItype) (b)) __CLOBBER_CC );} +#define UMUL_TIME 20 +#define UDIV_TIME 100 +#endif /* __arm__ */ + +#if defined(__arm__) +/* Let gcc decide how best to implement count_leading_zeros. */ +#define count_leading_zeros(COUNT,X) ((COUNT) = __builtin_clz (X)) +#define COUNT_LEADING_ZEROS_0 32 +#endif + +#if defined (__CRIS__) && __CRIS_arch_version >= 3 +#define count_leading_zeros(COUNT, X) ((COUNT) = __builtin_clz (X)) +#if __CRIS_arch_version >= 8 +#define count_trailing_zeros(COUNT, X) ((COUNT) = __builtin_ctz (X)) +#endif +#endif /* __CRIS__ */ + +#if defined (__hppa) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("add %4,%5,%1\n\taddc %2,%3,%0" \ + : "=r" ((USItype) (sh)), \ + "=&r" ((USItype) (sl)) \ + : "%rM" ((USItype) (ah)), \ + "rM" ((USItype) (bh)), \ + "%rM" ((USItype) (al)), \ + "rM" ((USItype) (bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("sub %4,%5,%1\n\tsubb %2,%3,%0" \ + : "=r" ((USItype) (sh)), \ + "=&r" ((USItype) (sl)) \ + : "rM" ((USItype) (ah)), \ + "rM" ((USItype) (bh)), \ + "rM" ((USItype) (al)), \ + "rM" ((USItype) (bl))) +#if defined (_PA_RISC1_1) +#define umul_ppmm(w1, w0, u, v) \ + do { \ + union \ + { \ + UDItype __f; \ + struct {USItype __w1, __w0;} __w1w0; \ + } __t; \ + __asm__ ("xmpyu %1,%2,%0" \ + : "=x" (__t.__f) \ + : "x" ((USItype) (u)), \ + "x" ((USItype) (v))); \ + (w1) = __t.__w1w0.__w1; \ + (w0) = __t.__w1w0.__w0; \ + } while (0) +#define UMUL_TIME 8 +#else +#define UMUL_TIME 30 +#endif +#define UDIV_TIME 40 +#define count_leading_zeros(count, x) \ + do { \ + USItype __tmp; \ + __asm__ ( \ + "ldi 1,%0\n" \ +" extru,= %1,15,16,%%r0 ; Bits 31..16 zero?\n" \ +" extru,tr %1,15,16,%1 ; No. Shift down, skip add.\n"\ +" ldo 16(%0),%0 ; Yes. Perform add.\n" \ +" extru,= %1,23,8,%%r0 ; Bits 15..8 zero?\n" \ +" extru,tr %1,23,8,%1 ; No. Shift down, skip add.\n"\ +" ldo 8(%0),%0 ; Yes. Perform add.\n" \ +" extru,= %1,27,4,%%r0 ; Bits 7..4 zero?\n" \ +" extru,tr %1,27,4,%1 ; No. Shift down, skip add.\n"\ +" ldo 4(%0),%0 ; Yes. Perform add.\n" \ +" extru,= %1,29,2,%%r0 ; Bits 3..2 zero?\n" \ +" extru,tr %1,29,2,%1 ; No. Shift down, skip add.\n"\ +" ldo 2(%0),%0 ; Yes. Perform add.\n" \ +" extru %1,30,1,%1 ; Extract bit 1.\n" \ +" sub %0,%1,%0 ; Subtract it.\n" \ + : "=r" (count), "=r" (__tmp) : "1" (x)); \ + } while (0) +#endif + +#if (defined (__i370__) || defined (__s390__) || defined (__mvs__)) && W_TYPE_SIZE == 32 +#define smul_ppmm(xh, xl, m0, m1) \ + do { \ + union {DItype __ll; \ + struct {USItype __h, __l;} __i; \ + } __x; \ + __asm__ ("lr %N0,%1\n\tmr %0,%2" \ + : "=&r" (__x.__ll) \ + : "r" (m0), "r" (m1)); \ + (xh) = __x.__i.__h; (xl) = __x.__i.__l; \ + } while (0) +#define sdiv_qrnnd(q, r, n1, n0, d) \ + do { \ + union {DItype __ll; \ + struct {USItype __h, __l;} __i; \ + } __x; \ + __x.__i.__h = n1; __x.__i.__l = n0; \ + __asm__ ("dr %0,%2" \ + : "=r" (__x.__ll) \ + : "0" (__x.__ll), "r" (d)); \ + (q) = __x.__i.__l; (r) = __x.__i.__h; \ + } while (0) +#endif + +#if (defined (__i386__) || defined (__i486__)) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("add{l} {%5,%1|%1,%5}\n\tadc{l} {%3,%0|%0,%3}" \ + : "=r" ((USItype) (sh)), \ + "=&r" ((USItype) (sl)) \ + : "%0" ((USItype) (ah)), \ + "g" ((USItype) (bh)), \ + "%1" ((USItype) (al)), \ + "g" ((USItype) (bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("sub{l} {%5,%1|%1,%5}\n\tsbb{l} {%3,%0|%0,%3}" \ + : "=r" ((USItype) (sh)), \ + "=&r" ((USItype) (sl)) \ + : "0" ((USItype) (ah)), \ + "g" ((USItype) (bh)), \ + "1" ((USItype) (al)), \ + "g" ((USItype) (bl))) +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("mul{l} %3" \ + : "=a" ((USItype) (w0)), \ + "=d" ((USItype) (w1)) \ + : "%0" ((USItype) (u)), \ + "rm" ((USItype) (v))) +#define udiv_qrnnd(q, r, n1, n0, dv) \ + __asm__ ("div{l} %4" \ + : "=a" ((USItype) (q)), \ + "=d" ((USItype) (r)) \ + : "0" ((USItype) (n0)), \ + "1" ((USItype) (n1)), \ + "rm" ((USItype) (dv))) +#define count_leading_zeros(count, x) ((count) = __builtin_clz (x)) +#define count_trailing_zeros(count, x) ((count) = __builtin_ctz (x)) +#define UMUL_TIME 40 +#define UDIV_TIME 40 +#endif /* 80x86 */ + +#if (defined (__x86_64__) || defined (__i386__)) && W_TYPE_SIZE == 64 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("add{q} {%5,%1|%1,%5}\n\tadc{q} {%3,%0|%0,%3}" \ + : "=r" ((UDItype) (sh)), \ + "=&r" ((UDItype) (sl)) \ + : "%0" ((UDItype) (ah)), \ + "rme" ((UDItype) (bh)), \ + "%1" ((UDItype) (al)), \ + "rme" ((UDItype) (bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("sub{q} {%5,%1|%1,%5}\n\tsbb{q} {%3,%0|%0,%3}" \ + : "=r" ((UDItype) (sh)), \ + "=&r" ((UDItype) (sl)) \ + : "0" ((UDItype) (ah)), \ + "rme" ((UDItype) (bh)), \ + "1" ((UDItype) (al)), \ + "rme" ((UDItype) (bl))) +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("mul{q} %3" \ + : "=a" ((UDItype) (w0)), \ + "=d" ((UDItype) (w1)) \ + : "%0" ((UDItype) (u)), \ + "rm" ((UDItype) (v))) +#define udiv_qrnnd(q, r, n1, n0, dv) \ + __asm__ ("div{q} %4" \ + : "=a" ((UDItype) (q)), \ + "=d" ((UDItype) (r)) \ + : "0" ((UDItype) (n0)), \ + "1" ((UDItype) (n1)), \ + "rm" ((UDItype) (dv))) +#define count_leading_zeros(count, x) ((count) = __builtin_clzl (x)) +#define count_trailing_zeros(count, x) ((count) = __builtin_ctzl (x)) +#define UMUL_TIME 40 +#define UDIV_TIME 40 +#endif /* x86_64 */ + +#if defined (__i960__) && W_TYPE_SIZE == 32 +#define umul_ppmm(w1, w0, u, v) \ + ({union {UDItype __ll; \ + struct {USItype __l, __h;} __i; \ + } __xx; \ + __asm__ ("emul %2,%1,%0" \ + : "=d" (__xx.__ll) \ + : "%dI" ((USItype) (u)), \ + "dI" ((USItype) (v))); \ + (w1) = __xx.__i.__h; (w0) = __xx.__i.__l;}) +#define __umulsidi3(u, v) \ + ({UDItype __w; \ + __asm__ ("emul %2,%1,%0" \ + : "=d" (__w) \ + : "%dI" ((USItype) (u)), \ + "dI" ((USItype) (v))); \ + __w; }) +#endif /* __i960__ */ + +#if defined (__M32R__) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + /* The cmp clears the condition bit. */ \ + __asm__ ("cmp %0,%0\n\taddx %1,%5\n\taddx %0,%3" \ + : "=r" ((USItype) (sh)), \ + "=&r" ((USItype) (sl)) \ + : "0" ((USItype) (ah)), \ + "r" ((USItype) (bh)), \ + "1" ((USItype) (al)), \ + "r" ((USItype) (bl)) \ + : "cbit") +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + /* The cmp clears the condition bit. */ \ + __asm__ ("cmp %0,%0\n\tsubx %1,%5\n\tsubx %0,%3" \ + : "=r" ((USItype) (sh)), \ + "=&r" ((USItype) (sl)) \ + : "0" ((USItype) (ah)), \ + "r" ((USItype) (bh)), \ + "1" ((USItype) (al)), \ + "r" ((USItype) (bl)) \ + : "cbit") +#endif /* __M32R__ */ + +#if defined (__mc68000__) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("add%.l %5,%1\n\taddx%.l %3,%0" \ + : "=d" ((USItype) (sh)), \ + "=&d" ((USItype) (sl)) \ + : "%0" ((USItype) (ah)), \ + "d" ((USItype) (bh)), \ + "%1" ((USItype) (al)), \ + "g" ((USItype) (bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("sub%.l %5,%1\n\tsubx%.l %3,%0" \ + : "=d" ((USItype) (sh)), \ + "=&d" ((USItype) (sl)) \ + : "0" ((USItype) (ah)), \ + "d" ((USItype) (bh)), \ + "1" ((USItype) (al)), \ + "g" ((USItype) (bl))) + +/* The '020, '030, '040, '060 and CPU32 have 32x32->64 and 64/32->32q-32r. */ +#if (defined (__mc68020__) && !defined (__mc68060__)) +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("mulu%.l %3,%1:%0" \ + : "=d" ((USItype) (w0)), \ + "=d" ((USItype) (w1)) \ + : "%0" ((USItype) (u)), \ + "dmi" ((USItype) (v))) +#define UMUL_TIME 45 +#define udiv_qrnnd(q, r, n1, n0, d) \ + __asm__ ("divu%.l %4,%1:%0" \ + : "=d" ((USItype) (q)), \ + "=d" ((USItype) (r)) \ + : "0" ((USItype) (n0)), \ + "1" ((USItype) (n1)), \ + "dmi" ((USItype) (d))) +#define UDIV_TIME 90 +#define sdiv_qrnnd(q, r, n1, n0, d) \ + __asm__ ("divs%.l %4,%1:%0" \ + : "=d" ((USItype) (q)), \ + "=d" ((USItype) (r)) \ + : "0" ((USItype) (n0)), \ + "1" ((USItype) (n1)), \ + "dmi" ((USItype) (d))) + +#elif defined (__mcoldfire__) /* not mc68020 */ + +#define umul_ppmm(xh, xl, a, b) \ + __asm__ ("| Inlined umul_ppmm\n" \ + " move%.l %2,%/d0\n" \ + " move%.l %3,%/d1\n" \ + " move%.l %/d0,%/d2\n" \ + " swap %/d0\n" \ + " move%.l %/d1,%/d3\n" \ + " swap %/d1\n" \ + " move%.w %/d2,%/d4\n" \ + " mulu %/d3,%/d4\n" \ + " mulu %/d1,%/d2\n" \ + " mulu %/d0,%/d3\n" \ + " mulu %/d0,%/d1\n" \ + " move%.l %/d4,%/d0\n" \ + " clr%.w %/d0\n" \ + " swap %/d0\n" \ + " add%.l %/d0,%/d2\n" \ + " add%.l %/d3,%/d2\n" \ + " jcc 1f\n" \ + " add%.l %#65536,%/d1\n" \ + "1: swap %/d2\n" \ + " moveq %#0,%/d0\n" \ + " move%.w %/d2,%/d0\n" \ + " move%.w %/d4,%/d2\n" \ + " move%.l %/d2,%1\n" \ + " add%.l %/d1,%/d0\n" \ + " move%.l %/d0,%0" \ + : "=g" ((USItype) (xh)), \ + "=g" ((USItype) (xl)) \ + : "g" ((USItype) (a)), \ + "g" ((USItype) (b)) \ + : "d0", "d1", "d2", "d3", "d4") +#define UMUL_TIME 100 +#define UDIV_TIME 400 +#else /* not ColdFire */ +/* %/ inserts REGISTER_PREFIX, %# inserts IMMEDIATE_PREFIX. */ +#define umul_ppmm(xh, xl, a, b) \ + __asm__ ("| Inlined umul_ppmm\n" \ + " move%.l %2,%/d0\n" \ + " move%.l %3,%/d1\n" \ + " move%.l %/d0,%/d2\n" \ + " swap %/d0\n" \ + " move%.l %/d1,%/d3\n" \ + " swap %/d1\n" \ + " move%.w %/d2,%/d4\n" \ + " mulu %/d3,%/d4\n" \ + " mulu %/d1,%/d2\n" \ + " mulu %/d0,%/d3\n" \ + " mulu %/d0,%/d1\n" \ + " move%.l %/d4,%/d0\n" \ + " eor%.w %/d0,%/d0\n" \ + " swap %/d0\n" \ + " add%.l %/d0,%/d2\n" \ + " add%.l %/d3,%/d2\n" \ + " jcc 1f\n" \ + " add%.l %#65536,%/d1\n" \ + "1: swap %/d2\n" \ + " moveq %#0,%/d0\n" \ + " move%.w %/d2,%/d0\n" \ + " move%.w %/d4,%/d2\n" \ + " move%.l %/d2,%1\n" \ + " add%.l %/d1,%/d0\n" \ + " move%.l %/d0,%0" \ + : "=g" ((USItype) (xh)), \ + "=g" ((USItype) (xl)) \ + : "g" ((USItype) (a)), \ + "g" ((USItype) (b)) \ + : "d0", "d1", "d2", "d3", "d4") +#define UMUL_TIME 100 +#define UDIV_TIME 400 + +#endif /* not mc68020 */ + +/* The '020, '030, '040 and '060 have bitfield insns. + cpu32 disguises as a 68020, but lacks them. */ +#if defined (__mc68020__) && !defined (__mcpu32__) +#define count_leading_zeros(count, x) \ + __asm__ ("bfffo %1{%b2:%b2},%0" \ + : "=d" ((USItype) (count)) \ + : "od" ((USItype) (x)), "n" (0)) +/* Some ColdFire architectures have a ff1 instruction supported via + __builtin_clz. */ +#elif defined (__mcfisaaplus__) || defined (__mcfisac__) +#define count_leading_zeros(count,x) ((count) = __builtin_clz (x)) +#define COUNT_LEADING_ZEROS_0 32 +#endif +#endif /* mc68000 */ + +#if defined (__m88000__) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("addu.co %1,%r4,%r5\n\taddu.ci %0,%r2,%r3" \ + : "=r" ((USItype) (sh)), \ + "=&r" ((USItype) (sl)) \ + : "%rJ" ((USItype) (ah)), \ + "rJ" ((USItype) (bh)), \ + "%rJ" ((USItype) (al)), \ + "rJ" ((USItype) (bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("subu.co %1,%r4,%r5\n\tsubu.ci %0,%r2,%r3" \ + : "=r" ((USItype) (sh)), \ + "=&r" ((USItype) (sl)) \ + : "rJ" ((USItype) (ah)), \ + "rJ" ((USItype) (bh)), \ + "rJ" ((USItype) (al)), \ + "rJ" ((USItype) (bl))) +#define count_leading_zeros(count, x) \ + do { \ + USItype __cbtmp; \ + __asm__ ("ff1 %0,%1" \ + : "=r" (__cbtmp) \ + : "r" ((USItype) (x))); \ + (count) = __cbtmp ^ 31; \ + } while (0) +#define COUNT_LEADING_ZEROS_0 63 /* sic */ +#if defined (__mc88110__) +#define umul_ppmm(wh, wl, u, v) \ + do { \ + union {UDItype __ll; \ + struct {USItype __h, __l;} __i; \ + } __xx; \ + __asm__ ("mulu.d %0,%1,%2" \ + : "=r" (__xx.__ll) \ + : "r" ((USItype) (u)), \ + "r" ((USItype) (v))); \ + (wh) = __xx.__i.__h; \ + (wl) = __xx.__i.__l; \ + } while (0) +#define udiv_qrnnd(q, r, n1, n0, d) \ + ({union {UDItype __ll; \ + struct {USItype __h, __l;} __i; \ + } __xx; \ + USItype __q; \ + __xx.__i.__h = (n1); __xx.__i.__l = (n0); \ + __asm__ ("divu.d %0,%1,%2" \ + : "=r" (__q) \ + : "r" (__xx.__ll), \ + "r" ((USItype) (d))); \ + (r) = (n0) - __q * (d); (q) = __q; }) +#define UMUL_TIME 5 +#define UDIV_TIME 25 +#else +#define UMUL_TIME 17 +#define UDIV_TIME 150 +#endif /* __mc88110__ */ +#endif /* __m88000__ */ + +#if defined (__mips__) && W_TYPE_SIZE == 32 +#define umul_ppmm(w1, w0, u, v) \ + do { \ + UDItype __x = (UDItype) (USItype) (u) * (USItype) (v); \ + (w1) = (USItype) (__x >> 32); \ + (w0) = (USItype) (__x); \ + } while (0) +#define UMUL_TIME 10 +#define UDIV_TIME 100 + +#if (__mips == 32 || __mips == 64) && ! __mips16 +#define count_leading_zeros(COUNT,X) ((COUNT) = __builtin_clz (X)) +#define COUNT_LEADING_ZEROS_0 32 +#endif +#endif /* __mips__ */ + +#if defined (__ns32000__) && W_TYPE_SIZE == 32 +#define umul_ppmm(w1, w0, u, v) \ + ({union {UDItype __ll; \ + struct {USItype __l, __h;} __i; \ + } __xx; \ + __asm__ ("meid %2,%0" \ + : "=g" (__xx.__ll) \ + : "%0" ((USItype) (u)), \ + "g" ((USItype) (v))); \ + (w1) = __xx.__i.__h; (w0) = __xx.__i.__l;}) +#define __umulsidi3(u, v) \ + ({UDItype __w; \ + __asm__ ("meid %2,%0" \ + : "=g" (__w) \ + : "%0" ((USItype) (u)), \ + "g" ((USItype) (v))); \ + __w; }) +#define udiv_qrnnd(q, r, n1, n0, d) \ + ({union {UDItype __ll; \ + struct {USItype __l, __h;} __i; \ + } __xx; \ + __xx.__i.__h = (n1); __xx.__i.__l = (n0); \ + __asm__ ("deid %2,%0" \ + : "=g" (__xx.__ll) \ + : "0" (__xx.__ll), \ + "g" ((USItype) (d))); \ + (r) = __xx.__i.__l; (q) = __xx.__i.__h; }) +#define count_trailing_zeros(count,x) \ + do { \ + __asm__ ("ffsd %2,%0" \ + : "=r" ((USItype) (count)) \ + : "0" ((USItype) 0), \ + "r" ((USItype) (x))); \ + } while (0) +#endif /* __ns32000__ */ + +/* FIXME: We should test _IBMR2 here when we add assembly support for the + system vendor compilers. + FIXME: What's needed for gcc PowerPC VxWorks? __vxworks__ is not good + enough, since that hits ARM and m68k too. */ +#if (defined (_ARCH_PPC) /* AIX */ \ + || defined (_ARCH_PWR) /* AIX */ \ + || defined (_ARCH_COM) /* AIX */ \ + || defined (__powerpc__) /* gcc */ \ + || defined (__POWERPC__) /* BEOS */ \ + || defined (__ppc__) /* Darwin */ \ + || (defined (PPC) && ! defined (CPU_FAMILY)) /* gcc 2.7.x GNU&SysV */ \ + || (defined (PPC) && defined (CPU_FAMILY) /* VxWorks */ \ + && CPU_FAMILY == PPC) \ + ) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + do { \ + if (__builtin_constant_p (bh) && (bh) == 0) \ + __asm__ ("{a%I4|add%I4c} %1,%3,%4\n\t{aze|addze} %0,%2" \ + : "=r" (sh), "=&r" (sl) : "r" (ah), "%r" (al), "rI" (bl));\ + else if (__builtin_constant_p (bh) && (bh) == ~(USItype) 0) \ + __asm__ ("{a%I4|add%I4c} %1,%3,%4\n\t{ame|addme} %0,%2" \ + : "=r" (sh), "=&r" (sl) : "r" (ah), "%r" (al), "rI" (bl));\ + else \ + __asm__ ("{a%I5|add%I5c} %1,%4,%5\n\t{ae|adde} %0,%2,%3" \ + : "=r" (sh), "=&r" (sl) \ + : "%r" (ah), "r" (bh), "%r" (al), "rI" (bl)); \ + } while (0) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + do { \ + if (__builtin_constant_p (ah) && (ah) == 0) \ + __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{sfze|subfze} %0,%2" \ + : "=r" (sh), "=&r" (sl) : "r" (bh), "rI" (al), "r" (bl));\ + else if (__builtin_constant_p (ah) && (ah) == ~(USItype) 0) \ + __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{sfme|subfme} %0,%2" \ + : "=r" (sh), "=&r" (sl) : "r" (bh), "rI" (al), "r" (bl));\ + else if (__builtin_constant_p (bh) && (bh) == 0) \ + __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{ame|addme} %0,%2" \ + : "=r" (sh), "=&r" (sl) : "r" (ah), "rI" (al), "r" (bl));\ + else if (__builtin_constant_p (bh) && (bh) == ~(USItype) 0) \ + __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{aze|addze} %0,%2" \ + : "=r" (sh), "=&r" (sl) : "r" (ah), "rI" (al), "r" (bl));\ + else \ + __asm__ ("{sf%I4|subf%I4c} %1,%5,%4\n\t{sfe|subfe} %0,%3,%2" \ + : "=r" (sh), "=&r" (sl) \ + : "r" (ah), "r" (bh), "rI" (al), "r" (bl)); \ + } while (0) +#define count_leading_zeros(count, x) \ + __asm__ ("{cntlz|cntlzw} %0,%1" : "=r" (count) : "r" (x)) +#define COUNT_LEADING_ZEROS_0 32 +#if defined (_ARCH_PPC) || defined (__powerpc__) || defined (__POWERPC__) \ + || defined (__ppc__) \ + || (defined (PPC) && ! defined (CPU_FAMILY)) /* gcc 2.7.x GNU&SysV */ \ + || (defined (PPC) && defined (CPU_FAMILY) /* VxWorks */ \ + && CPU_FAMILY == PPC) +#define umul_ppmm(ph, pl, m0, m1) \ + do { \ + USItype __m0 = (m0), __m1 = (m1); \ + __asm__ ("mulhwu %0,%1,%2" : "=r" (ph) : "%r" (m0), "r" (m1)); \ + (pl) = __m0 * __m1; \ + } while (0) +#define UMUL_TIME 15 +#define smul_ppmm(ph, pl, m0, m1) \ + do { \ + SItype __m0 = (m0), __m1 = (m1); \ + __asm__ ("mulhw %0,%1,%2" : "=r" (ph) : "%r" (m0), "r" (m1)); \ + (pl) = __m0 * __m1; \ + } while (0) +#define SMUL_TIME 14 +#define UDIV_TIME 120 +#elif defined (_ARCH_PWR) +#define UMUL_TIME 8 +#define smul_ppmm(xh, xl, m0, m1) \ + __asm__ ("mul %0,%2,%3" : "=r" (xh), "=q" (xl) : "r" (m0), "r" (m1)) +#define SMUL_TIME 4 +#define sdiv_qrnnd(q, r, nh, nl, d) \ + __asm__ ("div %0,%2,%4" : "=r" (q), "=q" (r) : "r" (nh), "1" (nl), "r" (d)) +#define UDIV_TIME 100 +#endif +#endif /* 32-bit POWER architecture variants. */ + +/* We should test _IBMR2 here when we add assembly support for the system + vendor compilers. */ +#if (defined (_ARCH_PPC64) || defined (__powerpc64__)) && W_TYPE_SIZE == 64 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + do { \ + if (__builtin_constant_p (bh) && (bh) == 0) \ + __asm__ ("{a%I4|add%I4c} %1,%3,%4\n\t{aze|addze} %0,%2" \ + : "=r" (sh), "=&r" (sl) : "r" (ah), "%r" (al), "rI" (bl));\ + else if (__builtin_constant_p (bh) && (bh) == ~(UDItype) 0) \ + __asm__ ("{a%I4|add%I4c} %1,%3,%4\n\t{ame|addme} %0,%2" \ + : "=r" (sh), "=&r" (sl) : "r" (ah), "%r" (al), "rI" (bl));\ + else \ + __asm__ ("{a%I5|add%I5c} %1,%4,%5\n\t{ae|adde} %0,%2,%3" \ + : "=r" (sh), "=&r" (sl) \ + : "%r" (ah), "r" (bh), "%r" (al), "rI" (bl)); \ + } while (0) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + do { \ + if (__builtin_constant_p (ah) && (ah) == 0) \ + __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{sfze|subfze} %0,%2" \ + : "=r" (sh), "=&r" (sl) : "r" (bh), "rI" (al), "r" (bl));\ + else if (__builtin_constant_p (ah) && (ah) == ~(UDItype) 0) \ + __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{sfme|subfme} %0,%2" \ + : "=r" (sh), "=&r" (sl) : "r" (bh), "rI" (al), "r" (bl));\ + else if (__builtin_constant_p (bh) && (bh) == 0) \ + __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{ame|addme} %0,%2" \ + : "=r" (sh), "=&r" (sl) : "r" (ah), "rI" (al), "r" (bl));\ + else if (__builtin_constant_p (bh) && (bh) == ~(UDItype) 0) \ + __asm__ ("{sf%I3|subf%I3c} %1,%4,%3\n\t{aze|addze} %0,%2" \ + : "=r" (sh), "=&r" (sl) : "r" (ah), "rI" (al), "r" (bl));\ + else \ + __asm__ ("{sf%I4|subf%I4c} %1,%5,%4\n\t{sfe|subfe} %0,%3,%2" \ + : "=r" (sh), "=&r" (sl) \ + : "r" (ah), "r" (bh), "rI" (al), "r" (bl)); \ + } while (0) +#define count_leading_zeros(count, x) \ + __asm__ ("cntlzd %0,%1" : "=r" (count) : "r" (x)) +#define COUNT_LEADING_ZEROS_0 64 +#define umul_ppmm(ph, pl, m0, m1) \ + do { \ + UDItype __m0 = (m0), __m1 = (m1); \ + __asm__ ("mulhdu %0,%1,%2" : "=r" (ph) : "%r" (m0), "r" (m1)); \ + (pl) = __m0 * __m1; \ + } while (0) +#define UMUL_TIME 15 +#define smul_ppmm(ph, pl, m0, m1) \ + do { \ + DItype __m0 = (m0), __m1 = (m1); \ + __asm__ ("mulhd %0,%1,%2" : "=r" (ph) : "%r" (m0), "r" (m1)); \ + (pl) = __m0 * __m1; \ + } while (0) +#define SMUL_TIME 14 /* ??? */ +#define UDIV_TIME 120 /* ??? */ +#endif /* 64-bit PowerPC. */ + +#if defined (__ibm032__) /* RT/ROMP */ && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("a %1,%5\n\tae %0,%3" \ + : "=r" ((USItype) (sh)), \ + "=&r" ((USItype) (sl)) \ + : "%0" ((USItype) (ah)), \ + "r" ((USItype) (bh)), \ + "%1" ((USItype) (al)), \ + "r" ((USItype) (bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("s %1,%5\n\tse %0,%3" \ + : "=r" ((USItype) (sh)), \ + "=&r" ((USItype) (sl)) \ + : "0" ((USItype) (ah)), \ + "r" ((USItype) (bh)), \ + "1" ((USItype) (al)), \ + "r" ((USItype) (bl))) +#define umul_ppmm(ph, pl, m0, m1) \ + do { \ + USItype __m0 = (m0), __m1 = (m1); \ + __asm__ ( \ + "s r2,r2\n" \ +" mts r10,%2\n" \ +" m r2,%3\n" \ +" m r2,%3\n" \ +" m r2,%3\n" \ +" m r2,%3\n" \ +" m r2,%3\n" \ +" m r2,%3\n" \ +" m r2,%3\n" \ +" m r2,%3\n" \ +" m r2,%3\n" \ +" m r2,%3\n" \ +" m r2,%3\n" \ +" m r2,%3\n" \ +" m r2,%3\n" \ +" m r2,%3\n" \ +" m r2,%3\n" \ +" m r2,%3\n" \ +" cas %0,r2,r0\n" \ +" mfs r10,%1" \ + : "=r" ((USItype) (ph)), \ + "=r" ((USItype) (pl)) \ + : "%r" (__m0), \ + "r" (__m1) \ + : "r2"); \ + (ph) += ((((SItype) __m0 >> 31) & __m1) \ + + (((SItype) __m1 >> 31) & __m0)); \ + } while (0) +#define UMUL_TIME 20 +#define UDIV_TIME 200 +#define count_leading_zeros(count, x) \ + do { \ + if ((x) >= 0x10000) \ + __asm__ ("clz %0,%1" \ + : "=r" ((USItype) (count)) \ + : "r" ((USItype) (x) >> 16)); \ + else \ + { \ + __asm__ ("clz %0,%1" \ + : "=r" ((USItype) (count)) \ + : "r" ((USItype) (x))); \ + (count) += 16; \ + } \ + } while (0) +#endif + +#if defined(__sh__) && !__SHMEDIA__ && W_TYPE_SIZE == 32 +#ifndef __sh1__ +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ( \ + "dmulu.l %2,%3\n\tsts%M1 macl,%1\n\tsts%M0 mach,%0" \ + : "=r<" ((USItype)(w1)), \ + "=r<" ((USItype)(w0)) \ + : "r" ((USItype)(u)), \ + "r" ((USItype)(v)) \ + : "macl", "mach") +#define UMUL_TIME 5 +#endif + +/* This is the same algorithm as __udiv_qrnnd_c. */ +#define UDIV_NEEDS_NORMALIZATION 1 + +#define udiv_qrnnd(q, r, n1, n0, d) \ + do { \ + extern UWtype __udiv_qrnnd_16 (UWtype, UWtype) \ + __attribute__ ((visibility ("hidden"))); \ + /* r0: rn r1: qn */ /* r0: n1 r4: n0 r5: d r6: d1 */ /* r2: __m */ \ + __asm__ ( \ + "mov%M4 %4,r5\n" \ +" swap.w %3,r4\n" \ +" swap.w r5,r6\n" \ +" jsr @%5\n" \ +" shll16 r6\n" \ +" swap.w r4,r4\n" \ +" jsr @%5\n" \ +" swap.w r1,%0\n" \ +" or r1,%0" \ + : "=r" (q), "=&z" (r) \ + : "1" (n1), "r" (n0), "rm" (d), "r" (&__udiv_qrnnd_16) \ + : "r1", "r2", "r4", "r5", "r6", "pr"); \ + } while (0) + +#define UDIV_TIME 80 + +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("clrt;subc %5,%1; subc %4,%0" \ + : "=r" (sh), "=r" (sl) \ + : "0" (ah), "1" (al), "r" (bh), "r" (bl)) + +#endif /* __sh__ */ + +#if defined (__SH5__) && __SHMEDIA__ && W_TYPE_SIZE == 32 +#define __umulsidi3(u,v) ((UDItype)(USItype)u*(USItype)v) +#define count_leading_zeros(count, x) \ + do \ + { \ + UDItype x_ = (USItype)(x); \ + SItype c_; \ + \ + __asm__ ("nsb %1, %0" : "=r" (c_) : "r" (x_)); \ + (count) = c_ - 31; \ + } \ + while (0) +#define COUNT_LEADING_ZEROS_0 32 +#endif + +#if defined (__sparc__) && !defined (__arch64__) && !defined (__sparcv9) \ + && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("addcc %r4,%5,%1\n\taddx %r2,%3,%0" \ + : "=r" ((USItype) (sh)), \ + "=&r" ((USItype) (sl)) \ + : "%rJ" ((USItype) (ah)), \ + "rI" ((USItype) (bh)), \ + "%rJ" ((USItype) (al)), \ + "rI" ((USItype) (bl)) \ + __CLOBBER_CC) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("subcc %r4,%5,%1\n\tsubx %r2,%3,%0" \ + : "=r" ((USItype) (sh)), \ + "=&r" ((USItype) (sl)) \ + : "rJ" ((USItype) (ah)), \ + "rI" ((USItype) (bh)), \ + "rJ" ((USItype) (al)), \ + "rI" ((USItype) (bl)) \ + __CLOBBER_CC) +#if defined (__sparc_v8__) +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("umul %2,%3,%1;rd %%y,%0" \ + : "=r" ((USItype) (w1)), \ + "=r" ((USItype) (w0)) \ + : "r" ((USItype) (u)), \ + "r" ((USItype) (v))) +#define udiv_qrnnd(__q, __r, __n1, __n0, __d) \ + __asm__ ("mov %2,%%y;nop;nop;nop;udiv %3,%4,%0;umul %0,%4,%1;sub %3,%1,%1"\ + : "=&r" ((USItype) (__q)), \ + "=&r" ((USItype) (__r)) \ + : "r" ((USItype) (__n1)), \ + "r" ((USItype) (__n0)), \ + "r" ((USItype) (__d))) +#else +#if defined (__sparclite__) +/* This has hardware multiply but not divide. It also has two additional + instructions scan (ffs from high bit) and divscc. */ +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("umul %2,%3,%1;rd %%y,%0" \ + : "=r" ((USItype) (w1)), \ + "=r" ((USItype) (w0)) \ + : "r" ((USItype) (u)), \ + "r" ((USItype) (v))) +#define udiv_qrnnd(q, r, n1, n0, d) \ + __asm__ ("! Inlined udiv_qrnnd\n" \ +" wr %%g0,%2,%%y ! Not a delayed write for sparclite\n" \ +" tst %%g0\n" \ +" divscc %3,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%%g1\n" \ +" divscc %%g1,%4,%0\n" \ +" rd %%y,%1\n" \ +" bl,a 1f\n" \ +" add %1,%4,%1\n" \ +"1: ! End of inline udiv_qrnnd" \ + : "=r" ((USItype) (q)), \ + "=r" ((USItype) (r)) \ + : "r" ((USItype) (n1)), \ + "r" ((USItype) (n0)), \ + "rI" ((USItype) (d)) \ + : "g1" __AND_CLOBBER_CC) +#define UDIV_TIME 37 +#define count_leading_zeros(count, x) \ + do { \ + __asm__ ("scan %1,1,%0" \ + : "=r" ((USItype) (count)) \ + : "r" ((USItype) (x))); \ + } while (0) +/* Early sparclites return 63 for an argument of 0, but they warn that future + implementations might change this. Therefore, leave COUNT_LEADING_ZEROS_0 + undefined. */ +#else +/* SPARC without integer multiplication and divide instructions. + (i.e. at least Sun4/20,40,60,65,75,110,260,280,330,360,380,470,490) */ +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("! Inlined umul_ppmm\n" \ +" wr %%g0,%2,%%y ! SPARC has 0-3 delay insn after a wr\n"\ +" sra %3,31,%%o5 ! Don't move this insn\n" \ +" and %2,%%o5,%%o5 ! Don't move this insn\n" \ +" andcc %%g0,0,%%g1 ! Don't move this insn\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,%3,%%g1\n" \ +" mulscc %%g1,0,%%g1\n" \ +" add %%g1,%%o5,%0\n" \ +" rd %%y,%1" \ + : "=r" ((USItype) (w1)), \ + "=r" ((USItype) (w0)) \ + : "%rI" ((USItype) (u)), \ + "r" ((USItype) (v)) \ + : "g1", "o5" __AND_CLOBBER_CC) +#define UMUL_TIME 39 /* 39 instructions */ +/* It's quite necessary to add this much assembler for the sparc. + The default udiv_qrnnd (in C) is more than 10 times slower! */ +#define udiv_qrnnd(__q, __r, __n1, __n0, __d) \ + __asm__ ("! Inlined udiv_qrnnd\n" \ +" mov 32,%%g1\n" \ +" subcc %1,%2,%%g0\n" \ +"1: bcs 5f\n" \ +" addxcc %0,%0,%0 ! shift n1n0 and a q-bit in lsb\n" \ +" sub %1,%2,%1 ! this kills msb of n\n" \ +" addx %1,%1,%1 ! so this can't give carry\n" \ +" subcc %%g1,1,%%g1\n" \ +"2: bne 1b\n" \ +" subcc %1,%2,%%g0\n" \ +" bcs 3f\n" \ +" addxcc %0,%0,%0 ! shift n1n0 and a q-bit in lsb\n" \ +" b 3f\n" \ +" sub %1,%2,%1 ! this kills msb of n\n" \ +"4: sub %1,%2,%1\n" \ +"5: addxcc %1,%1,%1\n" \ +" bcc 2b\n" \ +" subcc %%g1,1,%%g1\n" \ +"! Got carry from n. Subtract next step to cancel this carry.\n" \ +" bne 4b\n" \ +" addcc %0,%0,%0 ! shift n1n0 and a 0-bit in lsb\n" \ +" sub %1,%2,%1\n" \ +"3: xnor %0,0,%0\n" \ +" ! End of inline udiv_qrnnd" \ + : "=&r" ((USItype) (__q)), \ + "=&r" ((USItype) (__r)) \ + : "r" ((USItype) (__d)), \ + "1" ((USItype) (__n1)), \ + "0" ((USItype) (__n0)) : "g1" __AND_CLOBBER_CC) +#define UDIV_TIME (3+7*32) /* 7 instructions/iteration. 32 iterations. */ +#endif /* __sparclite__ */ +#endif /* __sparc_v8__ */ +#endif /* sparc32 */ + +#if ((defined (__sparc__) && defined (__arch64__)) || defined (__sparcv9)) \ + && W_TYPE_SIZE == 64 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("addcc %r4,%5,%1\n\t" \ + "add %r2,%3,%0\n\t" \ + "bcs,a,pn %%xcc, 1f\n\t" \ + "add %0, 1, %0\n" \ + "1:" \ + : "=r" ((UDItype)(sh)), \ + "=&r" ((UDItype)(sl)) \ + : "%rJ" ((UDItype)(ah)), \ + "rI" ((UDItype)(bh)), \ + "%rJ" ((UDItype)(al)), \ + "rI" ((UDItype)(bl)) \ + __CLOBBER_CC) + +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("subcc %r4,%5,%1\n\t" \ + "sub %r2,%3,%0\n\t" \ + "bcs,a,pn %%xcc, 1f\n\t" \ + "sub %0, 1, %0\n\t" \ + "1:" \ + : "=r" ((UDItype)(sh)), \ + "=&r" ((UDItype)(sl)) \ + : "rJ" ((UDItype)(ah)), \ + "rI" ((UDItype)(bh)), \ + "rJ" ((UDItype)(al)), \ + "rI" ((UDItype)(bl)) \ + __CLOBBER_CC) + +#define umul_ppmm(wh, wl, u, v) \ + do { \ + UDItype tmp1, tmp2, tmp3, tmp4; \ + __asm__ __volatile__ ( \ + "srl %7,0,%3\n\t" \ + "mulx %3,%6,%1\n\t" \ + "srlx %6,32,%2\n\t" \ + "mulx %2,%3,%4\n\t" \ + "sllx %4,32,%5\n\t" \ + "srl %6,0,%3\n\t" \ + "sub %1,%5,%5\n\t" \ + "srlx %5,32,%5\n\t" \ + "addcc %4,%5,%4\n\t" \ + "srlx %7,32,%5\n\t" \ + "mulx %3,%5,%3\n\t" \ + "mulx %2,%5,%5\n\t" \ + "sethi %%hi(0x80000000),%2\n\t" \ + "addcc %4,%3,%4\n\t" \ + "srlx %4,32,%4\n\t" \ + "add %2,%2,%2\n\t" \ + "movcc %%xcc,%%g0,%2\n\t" \ + "addcc %5,%4,%5\n\t" \ + "sllx %3,32,%3\n\t" \ + "add %1,%3,%1\n\t" \ + "add %5,%2,%0" \ + : "=r" ((UDItype)(wh)), \ + "=&r" ((UDItype)(wl)), \ + "=&r" (tmp1), "=&r" (tmp2), "=&r" (tmp3), "=&r" (tmp4) \ + : "r" ((UDItype)(u)), \ + "r" ((UDItype)(v)) \ + __CLOBBER_CC); \ + } while (0) +#define UMUL_TIME 96 +#define UDIV_TIME 230 +#endif /* sparc64 */ + +#if defined (__vax__) && W_TYPE_SIZE == 32 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("addl2 %5,%1\n\tadwc %3,%0" \ + : "=g" ((USItype) (sh)), \ + "=&g" ((USItype) (sl)) \ + : "%0" ((USItype) (ah)), \ + "g" ((USItype) (bh)), \ + "%1" ((USItype) (al)), \ + "g" ((USItype) (bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("subl2 %5,%1\n\tsbwc %3,%0" \ + : "=g" ((USItype) (sh)), \ + "=&g" ((USItype) (sl)) \ + : "0" ((USItype) (ah)), \ + "g" ((USItype) (bh)), \ + "1" ((USItype) (al)), \ + "g" ((USItype) (bl))) +#define umul_ppmm(xh, xl, m0, m1) \ + do { \ + union { \ + UDItype __ll; \ + struct {USItype __l, __h;} __i; \ + } __xx; \ + USItype __m0 = (m0), __m1 = (m1); \ + __asm__ ("emul %1,%2,$0,%0" \ + : "=r" (__xx.__ll) \ + : "g" (__m0), \ + "g" (__m1)); \ + (xh) = __xx.__i.__h; \ + (xl) = __xx.__i.__l; \ + (xh) += ((((SItype) __m0 >> 31) & __m1) \ + + (((SItype) __m1 >> 31) & __m0)); \ + } while (0) +#define sdiv_qrnnd(q, r, n1, n0, d) \ + do { \ + union {DItype __ll; \ + struct {SItype __l, __h;} __i; \ + } __xx; \ + __xx.__i.__h = n1; __xx.__i.__l = n0; \ + __asm__ ("ediv %3,%2,%0,%1" \ + : "=g" (q), "=g" (r) \ + : "g" (__xx.__ll), "g" (d)); \ + } while (0) +#endif /* __vax__ */ + +#if defined (__xtensa__) && W_TYPE_SIZE == 32 +/* This code is not Xtensa-configuration-specific, so rely on the compiler + to expand builtin functions depending on what configuration features + are available. This avoids library calls when the operation can be + performed in-line. */ +#define umul_ppmm(w1, w0, u, v) \ + do { \ + DWunion __w; \ + __w.ll = __builtin_umulsidi3 (u, v); \ + w1 = __w.s.high; \ + w0 = __w.s.low; \ + } while (0) +#define __umulsidi3(u, v) __builtin_umulsidi3 (u, v) +#define count_leading_zeros(COUNT, X) ((COUNT) = __builtin_clz (X)) +#define count_trailing_zeros(COUNT, X) ((COUNT) = __builtin_ctz (X)) +#endif /* __xtensa__ */ + +#if defined (__z8000__) && W_TYPE_SIZE == 16 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("add %H1,%H5\n\tadc %H0,%H3" \ + : "=r" ((unsigned int)(sh)), \ + "=&r" ((unsigned int)(sl)) \ + : "%0" ((unsigned int)(ah)), \ + "r" ((unsigned int)(bh)), \ + "%1" ((unsigned int)(al)), \ + "rQR" ((unsigned int)(bl))) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("sub %H1,%H5\n\tsbc %H0,%H3" \ + : "=r" ((unsigned int)(sh)), \ + "=&r" ((unsigned int)(sl)) \ + : "0" ((unsigned int)(ah)), \ + "r" ((unsigned int)(bh)), \ + "1" ((unsigned int)(al)), \ + "rQR" ((unsigned int)(bl))) +#define umul_ppmm(xh, xl, m0, m1) \ + do { \ + union {long int __ll; \ + struct {unsigned int __h, __l;} __i; \ + } __xx; \ + unsigned int __m0 = (m0), __m1 = (m1); \ + __asm__ ("mult %S0,%H3" \ + : "=r" (__xx.__i.__h), \ + "=r" (__xx.__i.__l) \ + : "%1" (__m0), \ + "rQR" (__m1)); \ + (xh) = __xx.__i.__h; (xl) = __xx.__i.__l; \ + (xh) += ((((signed int) __m0 >> 15) & __m1) \ + + (((signed int) __m1 >> 15) & __m0)); \ + } while (0) +#endif /* __z8000__ */ + +#endif /* __GNUC__ */ + +/* If this machine has no inline assembler, use C macros. */ + +#if !defined (add_ssaaaa) +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + do { \ + UWtype __x; \ + __x = (al) + (bl); \ + (sh) = (ah) + (bh) + (__x < (al)); \ + (sl) = __x; \ + } while (0) +#endif + +#if !defined (sub_ddmmss) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + do { \ + UWtype __x; \ + __x = (al) - (bl); \ + (sh) = (ah) - (bh) - (__x > (al)); \ + (sl) = __x; \ + } while (0) +#endif + +/* If we lack umul_ppmm but have smul_ppmm, define umul_ppmm in terms of + smul_ppmm. */ +#if !defined (umul_ppmm) && defined (smul_ppmm) +#define umul_ppmm(w1, w0, u, v) \ + do { \ + UWtype __w1; \ + UWtype __xm0 = (u), __xm1 = (v); \ + smul_ppmm (__w1, w0, __xm0, __xm1); \ + (w1) = __w1 + (-(__xm0 >> (W_TYPE_SIZE - 1)) & __xm1) \ + + (-(__xm1 >> (W_TYPE_SIZE - 1)) & __xm0); \ + } while (0) +#endif + +/* If we still don't have umul_ppmm, define it using plain C. */ +#if !defined (umul_ppmm) +#define umul_ppmm(w1, w0, u, v) \ + do { \ + UWtype __x0, __x1, __x2, __x3; \ + UHWtype __ul, __vl, __uh, __vh; \ + \ + __ul = __ll_lowpart (u); \ + __uh = __ll_highpart (u); \ + __vl = __ll_lowpart (v); \ + __vh = __ll_highpart (v); \ + \ + __x0 = (UWtype) __ul * __vl; \ + __x1 = (UWtype) __ul * __vh; \ + __x2 = (UWtype) __uh * __vl; \ + __x3 = (UWtype) __uh * __vh; \ + \ + __x1 += __ll_highpart (__x0);/* this can't give carry */ \ + __x1 += __x2; /* but this indeed can */ \ + if (__x1 < __x2) /* did we get it? */ \ + __x3 += __ll_B; /* yes, add it in the proper pos. */ \ + \ + (w1) = __x3 + __ll_highpart (__x1); \ + (w0) = __ll_lowpart (__x1) * __ll_B + __ll_lowpart (__x0); \ + } while (0) +#endif + +#if !defined (__umulsidi3) +#define __umulsidi3(u, v) \ + ({DWunion __w; \ + umul_ppmm (__w.s.high, __w.s.low, u, v); \ + __w.ll; }) +#endif + +/* Define this unconditionally, so it can be used for debugging. */ +#define __udiv_qrnnd_c(q, r, n1, n0, d) \ + do { \ + UWtype __d1, __d0, __q1, __q0; \ + UWtype __r1, __r0, __m; \ + __d1 = __ll_highpart (d); \ + __d0 = __ll_lowpart (d); \ + \ + __r1 = (n1) % __d1; \ + __q1 = (n1) / __d1; \ + __m = (UWtype) __q1 * __d0; \ + __r1 = __r1 * __ll_B | __ll_highpart (n0); \ + if (__r1 < __m) \ + { \ + __q1--, __r1 += (d); \ + if (__r1 >= (d)) /* i.e. we didn't get carry when adding to __r1 */\ + if (__r1 < __m) \ + __q1--, __r1 += (d); \ + } \ + __r1 -= __m; \ + \ + __r0 = __r1 % __d1; \ + __q0 = __r1 / __d1; \ + __m = (UWtype) __q0 * __d0; \ + __r0 = __r0 * __ll_B | __ll_lowpart (n0); \ + if (__r0 < __m) \ + { \ + __q0--, __r0 += (d); \ + if (__r0 >= (d)) \ + if (__r0 < __m) \ + __q0--, __r0 += (d); \ + } \ + __r0 -= __m; \ + \ + (q) = (UWtype) __q1 * __ll_B | __q0; \ + (r) = __r0; \ + } while (0) + +/* If the processor has no udiv_qrnnd but sdiv_qrnnd, go through + __udiv_w_sdiv (defined in libgcc or elsewhere). */ +#if !defined (udiv_qrnnd) && defined (sdiv_qrnnd) +#define udiv_qrnnd(q, r, nh, nl, d) \ + do { \ + USItype __r; \ + (q) = __udiv_w_sdiv (&__r, nh, nl, d); \ + (r) = __r; \ + } while (0) +#endif + +/* If udiv_qrnnd was not defined for this processor, use __udiv_qrnnd_c. */ +#if !defined (udiv_qrnnd) +#define UDIV_NEEDS_NORMALIZATION 1 +#define udiv_qrnnd __udiv_qrnnd_c +#endif + +#if !defined (count_leading_zeros) +#define count_leading_zeros(count, x) \ + do { \ + UWtype __xr = (x); \ + UWtype __a; \ + \ + if (W_TYPE_SIZE <= 32) \ + { \ + __a = __xr < ((UWtype)1<<2*__BITS4) \ + ? (__xr < ((UWtype)1<<__BITS4) ? 0 : __BITS4) \ + : (__xr < ((UWtype)1<<3*__BITS4) ? 2*__BITS4 : 3*__BITS4); \ + } \ + else \ + { \ + for (__a = W_TYPE_SIZE - 8; __a > 0; __a -= 8) \ + if (((__xr >> __a) & 0xff) != 0) \ + break; \ + } \ + \ + (count) = W_TYPE_SIZE - (__clz_tab[__xr >> __a] + __a); \ + } while (0) +#define COUNT_LEADING_ZEROS_0 W_TYPE_SIZE +#endif + +#if !defined (count_trailing_zeros) +/* Define count_trailing_zeros using count_leading_zeros. The latter might be + defined in asm, but if it is not, the C version above is good enough. */ +#define count_trailing_zeros(count, x) \ + do { \ + UWtype __ctz_x = (x); \ + UWtype __ctz_c; \ + count_leading_zeros (__ctz_c, __ctz_x & -__ctz_x); \ + (count) = W_TYPE_SIZE - 1 - __ctz_c; \ + } while (0) +#endif + +#ifndef UDIV_NEEDS_NORMALIZATION +#define UDIV_NEEDS_NORMALIZATION 0 +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/mp_clz_tab.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/mp_clz_tab.c new file mode 100644 index 00000000..2220299e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/mp_clz_tab.c @@ -0,0 +1,37 @@ +/* __clz_tab -- support for longlong.h + Copyright (C) 1991, 1993, 1994, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. Its master source is NOT part of + the C library, however. The master source lives in the GNU MP Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#if 0 +#include +#include "gmp-impl.h" +#endif + +const +unsigned char __clz_tab[] = +{ + 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, +}; diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/op-1.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/op-1.h new file mode 100644 index 00000000..35cd0ba7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/op-1.h @@ -0,0 +1,302 @@ +/* Software floating-point emulation. + Basic one-word fraction declaration and manipulation. + Copyright (C) 1997,1998,1999,2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson (rth@cygnus.com), + Jakub Jelinek (jj@ultra.linux.cz), + David S. Miller (davem@redhat.com) and + Peter Maydell (pmaydell@chiark.greenend.org.uk). + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file into + combinations with other programs, and to distribute those + combinations without any restriction coming from the use of this + file. (The Lesser General Public License restrictions do apply in + other respects; for example, they cover modification of the file, + and distribution when not linked into a combine executable.) + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301, USA. */ + +#define _FP_FRAC_DECL_1(X) _FP_W_TYPE X##_f +#define _FP_FRAC_COPY_1(D,S) (D##_f = S##_f) +#define _FP_FRAC_SET_1(X,I) (X##_f = I) +#define _FP_FRAC_HIGH_1(X) (X##_f) +#define _FP_FRAC_LOW_1(X) (X##_f) +#define _FP_FRAC_WORD_1(X,w) (X##_f) + +#define _FP_FRAC_ADDI_1(X,I) (X##_f += I) +#define _FP_FRAC_SLL_1(X,N) \ + do { \ + if (__builtin_constant_p(N) && (N) == 1) \ + X##_f += X##_f; \ + else \ + X##_f <<= (N); \ + } while (0) +#define _FP_FRAC_SRL_1(X,N) (X##_f >>= N) + +/* Right shift with sticky-lsb. */ +#define _FP_FRAC_SRST_1(X,S,N,sz) __FP_FRAC_SRST_1(X##_f, S, N, sz) +#define _FP_FRAC_SRS_1(X,N,sz) __FP_FRAC_SRS_1(X##_f, N, sz) + +#define __FP_FRAC_SRST_1(X,S,N,sz) \ +do { \ + S = (__builtin_constant_p(N) && (N) == 1 \ + ? X & 1 : (X << (_FP_W_TYPE_SIZE - (N))) != 0); \ + X = X >> (N); \ +} while (0) + +#define __FP_FRAC_SRS_1(X,N,sz) \ + (X = (X >> (N) | (__builtin_constant_p(N) && (N) == 1 \ + ? X & 1 : (X << (_FP_W_TYPE_SIZE - (N))) != 0))) + +#define _FP_FRAC_ADD_1(R,X,Y) (R##_f = X##_f + Y##_f) +#define _FP_FRAC_SUB_1(R,X,Y) (R##_f = X##_f - Y##_f) +#define _FP_FRAC_DEC_1(X,Y) (X##_f -= Y##_f) +#define _FP_FRAC_CLZ_1(z, X) __FP_CLZ(z, X##_f) + +/* Predicates */ +#define _FP_FRAC_NEGP_1(X) ((_FP_WS_TYPE)X##_f < 0) +#define _FP_FRAC_ZEROP_1(X) (X##_f == 0) +#define _FP_FRAC_OVERP_1(fs,X) (X##_f & _FP_OVERFLOW_##fs) +#define _FP_FRAC_CLEAR_OVERP_1(fs,X) (X##_f &= ~_FP_OVERFLOW_##fs) +#define _FP_FRAC_EQ_1(X, Y) (X##_f == Y##_f) +#define _FP_FRAC_GE_1(X, Y) (X##_f >= Y##_f) +#define _FP_FRAC_GT_1(X, Y) (X##_f > Y##_f) + +#define _FP_ZEROFRAC_1 0 +#define _FP_MINFRAC_1 1 +#define _FP_MAXFRAC_1 (~(_FP_WS_TYPE)0) + +/* + * Unpack the raw bits of a native fp value. Do not classify or + * normalize the data. + */ + +#define _FP_UNPACK_RAW_1(fs, X, val) \ + do { \ + union _FP_UNION_##fs _flo; _flo.flt = (val); \ + \ + X##_f = _flo.bits.frac; \ + X##_e = _flo.bits.exp; \ + X##_s = _flo.bits.sign; \ + } while (0) + +#define _FP_UNPACK_RAW_1_P(fs, X, val) \ + do { \ + union _FP_UNION_##fs *_flo = \ + (union _FP_UNION_##fs *)(val); \ + \ + X##_f = _flo->bits.frac; \ + X##_e = _flo->bits.exp; \ + X##_s = _flo->bits.sign; \ + } while (0) + +/* + * Repack the raw bits of a native fp value. + */ + +#define _FP_PACK_RAW_1(fs, val, X) \ + do { \ + union _FP_UNION_##fs _flo; \ + \ + _flo.bits.frac = X##_f; \ + _flo.bits.exp = X##_e; \ + _flo.bits.sign = X##_s; \ + \ + (val) = _flo.flt; \ + } while (0) + +#define _FP_PACK_RAW_1_P(fs, val, X) \ + do { \ + union _FP_UNION_##fs *_flo = \ + (union _FP_UNION_##fs *)(val); \ + \ + _flo->bits.frac = X##_f; \ + _flo->bits.exp = X##_e; \ + _flo->bits.sign = X##_s; \ + } while (0) + + +/* + * Multiplication algorithms: + */ + +/* Basic. Assuming the host word size is >= 2*FRACBITS, we can do the + multiplication immediately. */ + +#define _FP_MUL_MEAT_1_imm(wfracbits, R, X, Y) \ + do { \ + R##_f = X##_f * Y##_f; \ + /* Normalize since we know where the msb of the multiplicands \ + were (bit B), we know that the msb of the of the product is \ + at either 2B or 2B-1. */ \ + _FP_FRAC_SRS_1(R, wfracbits-1, 2*wfracbits); \ + } while (0) + +/* Given a 1W * 1W => 2W primitive, do the extended multiplication. */ + +#define _FP_MUL_MEAT_1_wide(wfracbits, R, X, Y, doit) \ + do { \ + _FP_W_TYPE _Z_f0, _Z_f1; \ + doit(_Z_f1, _Z_f0, X##_f, Y##_f); \ + /* Normalize since we know where the msb of the multiplicands \ + were (bit B), we know that the msb of the of the product is \ + at either 2B or 2B-1. */ \ + _FP_FRAC_SRS_2(_Z, wfracbits-1, 2*wfracbits); \ + R##_f = _Z_f0; \ + } while (0) + +/* Finally, a simple widening multiply algorithm. What fun! */ + +#define _FP_MUL_MEAT_1_hard(wfracbits, R, X, Y) \ + do { \ + _FP_W_TYPE _xh, _xl, _yh, _yl, _z_f0, _z_f1, _a_f0, _a_f1; \ + \ + /* split the words in half */ \ + _xh = X##_f >> (_FP_W_TYPE_SIZE/2); \ + _xl = X##_f & (((_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE/2)) - 1); \ + _yh = Y##_f >> (_FP_W_TYPE_SIZE/2); \ + _yl = Y##_f & (((_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE/2)) - 1); \ + \ + /* multiply the pieces */ \ + _z_f0 = _xl * _yl; \ + _a_f0 = _xh * _yl; \ + _a_f1 = _xl * _yh; \ + _z_f1 = _xh * _yh; \ + \ + /* reassemble into two full words */ \ + if ((_a_f0 += _a_f1) < _a_f1) \ + _z_f1 += (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE/2); \ + _a_f1 = _a_f0 >> (_FP_W_TYPE_SIZE/2); \ + _a_f0 = _a_f0 << (_FP_W_TYPE_SIZE/2); \ + _FP_FRAC_ADD_2(_z, _z, _a); \ + \ + /* normalize */ \ + _FP_FRAC_SRS_2(_z, wfracbits - 1, 2*wfracbits); \ + R##_f = _z_f0; \ + } while (0) + + +/* + * Division algorithms: + */ + +/* Basic. Assuming the host word size is >= 2*FRACBITS, we can do the + division immediately. Give this macro either _FP_DIV_HELP_imm for + C primitives or _FP_DIV_HELP_ldiv for the ISO function. Which you + choose will depend on what the compiler does with divrem4. */ + +#define _FP_DIV_MEAT_1_imm(fs, R, X, Y, doit) \ + do { \ + _FP_W_TYPE _q, _r; \ + X##_f <<= (X##_f < Y##_f \ + ? R##_e--, _FP_WFRACBITS_##fs \ + : _FP_WFRACBITS_##fs - 1); \ + doit(_q, _r, X##_f, Y##_f); \ + R##_f = _q | (_r != 0); \ + } while (0) + +/* GCC's longlong.h defines a 2W / 1W => (1W,1W) primitive udiv_qrnnd + that may be useful in this situation. This first is for a primitive + that requires normalization, the second for one that does not. Look + for UDIV_NEEDS_NORMALIZATION to tell which your machine needs. */ + +#define _FP_DIV_MEAT_1_udiv_norm(fs, R, X, Y) \ + do { \ + _FP_W_TYPE _nh, _nl, _q, _r, _y; \ + \ + /* Normalize Y -- i.e. make the most significant bit set. */ \ + _y = Y##_f << _FP_WFRACXBITS_##fs; \ + \ + /* Shift X op correspondingly high, that is, up one full word. */ \ + if (X##_f < Y##_f) \ + { \ + R##_e--; \ + _nl = 0; \ + _nh = X##_f; \ + } \ + else \ + { \ + _nl = X##_f << (_FP_W_TYPE_SIZE - 1); \ + _nh = X##_f >> 1; \ + } \ + \ + udiv_qrnnd(_q, _r, _nh, _nl, _y); \ + R##_f = _q | (_r != 0); \ + } while (0) + +#define _FP_DIV_MEAT_1_udiv(fs, R, X, Y) \ + do { \ + _FP_W_TYPE _nh, _nl, _q, _r; \ + if (X##_f < Y##_f) \ + { \ + R##_e--; \ + _nl = X##_f << _FP_WFRACBITS_##fs; \ + _nh = X##_f >> _FP_WFRACXBITS_##fs; \ + } \ + else \ + { \ + _nl = X##_f << (_FP_WFRACBITS_##fs - 1); \ + _nh = X##_f >> (_FP_WFRACXBITS_##fs + 1); \ + } \ + udiv_qrnnd(_q, _r, _nh, _nl, Y##_f); \ + R##_f = _q | (_r != 0); \ + } while (0) + + +/* + * Square root algorithms: + * We have just one right now, maybe Newton approximation + * should be added for those machines where division is fast. + */ + +#define _FP_SQRT_MEAT_1(R, S, T, X, q) \ + do { \ + while (q != _FP_WORK_ROUND) \ + { \ + T##_f = S##_f + q; \ + if (T##_f <= X##_f) \ + { \ + S##_f = T##_f + q; \ + X##_f -= T##_f; \ + R##_f += q; \ + } \ + _FP_FRAC_SLL_1(X, 1); \ + q >>= 1; \ + } \ + if (X##_f) \ + { \ + if (S##_f < X##_f) \ + R##_f |= _FP_WORK_ROUND; \ + R##_f |= _FP_WORK_STICKY; \ + } \ + } while (0) + +/* + * Assembly/disassembly for converting to/from integral types. + * No shifting or overflow handled here. + */ + +#define _FP_FRAC_ASSEMBLE_1(r, X, rsize) (r = X##_f) +#define _FP_FRAC_DISASSEMBLE_1(X, r, rsize) (X##_f = r) + + +/* + * Convert FP values between word sizes + */ + +#define _FP_FRAC_COPY_1_1(D, S) (D##_f = S##_f) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/op-2.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/op-2.h new file mode 100644 index 00000000..3a3b3aa0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/op-2.h @@ -0,0 +1,617 @@ +/* Software floating-point emulation. + Basic two-word fraction declaration and manipulation. + Copyright (C) 1997,1998,1999,2006,2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson (rth@cygnus.com), + Jakub Jelinek (jj@ultra.linux.cz), + David S. Miller (davem@redhat.com) and + Peter Maydell (pmaydell@chiark.greenend.org.uk). + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file into + combinations with other programs, and to distribute those + combinations without any restriction coming from the use of this + file. (The Lesser General Public License restrictions do apply in + other respects; for example, they cover modification of the file, + and distribution when not linked into a combine executable.) + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301, USA. */ + +#define _FP_FRAC_DECL_2(X) _FP_W_TYPE X##_f0, X##_f1 +#define _FP_FRAC_COPY_2(D,S) (D##_f0 = S##_f0, D##_f1 = S##_f1) +#define _FP_FRAC_SET_2(X,I) __FP_FRAC_SET_2(X, I) +#define _FP_FRAC_HIGH_2(X) (X##_f1) +#define _FP_FRAC_LOW_2(X) (X##_f0) +#define _FP_FRAC_WORD_2(X,w) (X##_f##w) + +#define _FP_FRAC_SLL_2(X,N) \ +(void)(((N) < _FP_W_TYPE_SIZE) \ + ? ({ \ + if (__builtin_constant_p(N) && (N) == 1) \ + { \ + X##_f1 = X##_f1 + X##_f1 + (((_FP_WS_TYPE)(X##_f0)) < 0); \ + X##_f0 += X##_f0; \ + } \ + else \ + { \ + X##_f1 = X##_f1 << (N) | X##_f0 >> (_FP_W_TYPE_SIZE - (N)); \ + X##_f0 <<= (N); \ + } \ + 0; \ + }) \ + : ({ \ + X##_f1 = X##_f0 << ((N) - _FP_W_TYPE_SIZE); \ + X##_f0 = 0; \ + })) + + +#define _FP_FRAC_SRL_2(X,N) \ +(void)(((N) < _FP_W_TYPE_SIZE) \ + ? ({ \ + X##_f0 = X##_f0 >> (N) | X##_f1 << (_FP_W_TYPE_SIZE - (N)); \ + X##_f1 >>= (N); \ + }) \ + : ({ \ + X##_f0 = X##_f1 >> ((N) - _FP_W_TYPE_SIZE); \ + X##_f1 = 0; \ + })) + +/* Right shift with sticky-lsb. */ +#define _FP_FRAC_SRST_2(X,S, N,sz) \ +(void)(((N) < _FP_W_TYPE_SIZE) \ + ? ({ \ + S = (__builtin_constant_p(N) && (N) == 1 \ + ? X##_f0 & 1 \ + : (X##_f0 << (_FP_W_TYPE_SIZE - (N))) != 0); \ + X##_f0 = (X##_f1 << (_FP_W_TYPE_SIZE - (N)) | X##_f0 >> (N)); \ + X##_f1 >>= (N); \ + }) \ + : ({ \ + S = ((((N) == _FP_W_TYPE_SIZE \ + ? 0 \ + : (X##_f1 << (2*_FP_W_TYPE_SIZE - (N)))) \ + | X##_f0) != 0); \ + X##_f0 = (X##_f1 >> ((N) - _FP_W_TYPE_SIZE)); \ + X##_f1 = 0; \ + })) + +#define _FP_FRAC_SRS_2(X,N,sz) \ +(void)(((N) < _FP_W_TYPE_SIZE) \ + ? ({ \ + X##_f0 = (X##_f1 << (_FP_W_TYPE_SIZE - (N)) | X##_f0 >> (N) | \ + (__builtin_constant_p(N) && (N) == 1 \ + ? X##_f0 & 1 \ + : (X##_f0 << (_FP_W_TYPE_SIZE - (N))) != 0)); \ + X##_f1 >>= (N); \ + }) \ + : ({ \ + X##_f0 = (X##_f1 >> ((N) - _FP_W_TYPE_SIZE) | \ + ((((N) == _FP_W_TYPE_SIZE \ + ? 0 \ + : (X##_f1 << (2*_FP_W_TYPE_SIZE - (N)))) \ + | X##_f0) != 0)); \ + X##_f1 = 0; \ + })) + +#define _FP_FRAC_ADDI_2(X,I) \ + __FP_FRAC_ADDI_2(X##_f1, X##_f0, I) + +#define _FP_FRAC_ADD_2(R,X,Y) \ + __FP_FRAC_ADD_2(R##_f1, R##_f0, X##_f1, X##_f0, Y##_f1, Y##_f0) + +#define _FP_FRAC_SUB_2(R,X,Y) \ + __FP_FRAC_SUB_2(R##_f1, R##_f0, X##_f1, X##_f0, Y##_f1, Y##_f0) + +#define _FP_FRAC_DEC_2(X,Y) \ + __FP_FRAC_DEC_2(X##_f1, X##_f0, Y##_f1, Y##_f0) + +#define _FP_FRAC_CLZ_2(R,X) \ + do { \ + if (X##_f1) \ + __FP_CLZ(R,X##_f1); \ + else \ + { \ + __FP_CLZ(R,X##_f0); \ + R += _FP_W_TYPE_SIZE; \ + } \ + } while(0) + +/* Predicates */ +#define _FP_FRAC_NEGP_2(X) ((_FP_WS_TYPE)X##_f1 < 0) +#define _FP_FRAC_ZEROP_2(X) ((X##_f1 | X##_f0) == 0) +#define _FP_FRAC_OVERP_2(fs,X) (_FP_FRAC_HIGH_##fs(X) & _FP_OVERFLOW_##fs) +#define _FP_FRAC_CLEAR_OVERP_2(fs,X) (_FP_FRAC_HIGH_##fs(X) &= ~_FP_OVERFLOW_##fs) +#define _FP_FRAC_EQ_2(X, Y) (X##_f1 == Y##_f1 && X##_f0 == Y##_f0) +#define _FP_FRAC_GT_2(X, Y) \ + (X##_f1 > Y##_f1 || (X##_f1 == Y##_f1 && X##_f0 > Y##_f0)) +#define _FP_FRAC_GE_2(X, Y) \ + (X##_f1 > Y##_f1 || (X##_f1 == Y##_f1 && X##_f0 >= Y##_f0)) + +#define _FP_ZEROFRAC_2 0, 0 +#define _FP_MINFRAC_2 0, 1 +#define _FP_MAXFRAC_2 (~(_FP_WS_TYPE)0), (~(_FP_WS_TYPE)0) + +/* + * Internals + */ + +#define __FP_FRAC_SET_2(X,I1,I0) (X##_f0 = I0, X##_f1 = I1) + +#define __FP_CLZ_2(R, xh, xl) \ + do { \ + if (xh) \ + __FP_CLZ(R,xh); \ + else \ + { \ + __FP_CLZ(R,xl); \ + R += _FP_W_TYPE_SIZE; \ + } \ + } while(0) + +#if 0 + +#ifndef __FP_FRAC_ADDI_2 +#define __FP_FRAC_ADDI_2(xh, xl, i) \ + (xh += ((xl += i) < i)) +#endif +#ifndef __FP_FRAC_ADD_2 +#define __FP_FRAC_ADD_2(rh, rl, xh, xl, yh, yl) \ + (rh = xh + yh + ((rl = xl + yl) < xl)) +#endif +#ifndef __FP_FRAC_SUB_2 +#define __FP_FRAC_SUB_2(rh, rl, xh, xl, yh, yl) \ + (rh = xh - yh - ((rl = xl - yl) > xl)) +#endif +#ifndef __FP_FRAC_DEC_2 +#define __FP_FRAC_DEC_2(xh, xl, yh, yl) \ + do { \ + UWtype _t = xl; \ + xh -= yh + ((xl -= yl) > _t); \ + } while (0) +#endif + +#else + +#undef __FP_FRAC_ADDI_2 +#define __FP_FRAC_ADDI_2(xh, xl, i) add_ssaaaa(xh, xl, xh, xl, 0, i) +#undef __FP_FRAC_ADD_2 +#define __FP_FRAC_ADD_2 add_ssaaaa +#undef __FP_FRAC_SUB_2 +#define __FP_FRAC_SUB_2 sub_ddmmss +#undef __FP_FRAC_DEC_2 +#define __FP_FRAC_DEC_2(xh, xl, yh, yl) sub_ddmmss(xh, xl, xh, xl, yh, yl) + +#endif + +/* + * Unpack the raw bits of a native fp value. Do not classify or + * normalize the data. + */ + +#define _FP_UNPACK_RAW_2(fs, X, val) \ + do { \ + union _FP_UNION_##fs _flo; _flo.flt = (val); \ + \ + X##_f0 = _flo.bits.frac0; \ + X##_f1 = _flo.bits.frac1; \ + X##_e = _flo.bits.exp; \ + X##_s = _flo.bits.sign; \ + } while (0) + +#define _FP_UNPACK_RAW_2_P(fs, X, val) \ + do { \ + union _FP_UNION_##fs *_flo = \ + (union _FP_UNION_##fs *)(val); \ + \ + X##_f0 = _flo->bits.frac0; \ + X##_f1 = _flo->bits.frac1; \ + X##_e = _flo->bits.exp; \ + X##_s = _flo->bits.sign; \ + } while (0) + + +/* + * Repack the raw bits of a native fp value. + */ + +#define _FP_PACK_RAW_2(fs, val, X) \ + do { \ + union _FP_UNION_##fs _flo; \ + \ + _flo.bits.frac0 = X##_f0; \ + _flo.bits.frac1 = X##_f1; \ + _flo.bits.exp = X##_e; \ + _flo.bits.sign = X##_s; \ + \ + (val) = _flo.flt; \ + } while (0) + +#define _FP_PACK_RAW_2_P(fs, val, X) \ + do { \ + union _FP_UNION_##fs *_flo = \ + (union _FP_UNION_##fs *)(val); \ + \ + _flo->bits.frac0 = X##_f0; \ + _flo->bits.frac1 = X##_f1; \ + _flo->bits.exp = X##_e; \ + _flo->bits.sign = X##_s; \ + } while (0) + + +/* + * Multiplication algorithms: + */ + +/* Given a 1W * 1W => 2W primitive, do the extended multiplication. */ + +#define _FP_MUL_MEAT_2_wide(wfracbits, R, X, Y, doit) \ + do { \ + _FP_FRAC_DECL_4(_z); _FP_FRAC_DECL_2(_b); _FP_FRAC_DECL_2(_c); \ + \ + doit(_FP_FRAC_WORD_4(_z,1), _FP_FRAC_WORD_4(_z,0), X##_f0, Y##_f0); \ + doit(_b_f1, _b_f0, X##_f0, Y##_f1); \ + doit(_c_f1, _c_f0, X##_f1, Y##_f0); \ + doit(_FP_FRAC_WORD_4(_z,3), _FP_FRAC_WORD_4(_z,2), X##_f1, Y##_f1); \ + \ + __FP_FRAC_ADD_3(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2), \ + _FP_FRAC_WORD_4(_z,1), 0, _b_f1, _b_f0, \ + _FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2), \ + _FP_FRAC_WORD_4(_z,1)); \ + __FP_FRAC_ADD_3(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2), \ + _FP_FRAC_WORD_4(_z,1), 0, _c_f1, _c_f0, \ + _FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2), \ + _FP_FRAC_WORD_4(_z,1)); \ + \ + /* Normalize since we know where the msb of the multiplicands \ + were (bit B), we know that the msb of the of the product is \ + at either 2B or 2B-1. */ \ + _FP_FRAC_SRS_4(_z, wfracbits-1, 2*wfracbits); \ + R##_f0 = _FP_FRAC_WORD_4(_z,0); \ + R##_f1 = _FP_FRAC_WORD_4(_z,1); \ + } while (0) + +/* Given a 1W * 1W => 2W primitive, do the extended multiplication. + Do only 3 multiplications instead of four. This one is for machines + where multiplication is much more expensive than subtraction. */ + +#define _FP_MUL_MEAT_2_wide_3mul(wfracbits, R, X, Y, doit) \ + do { \ + _FP_FRAC_DECL_4(_z); _FP_FRAC_DECL_2(_b); _FP_FRAC_DECL_2(_c); \ + _FP_W_TYPE _d; \ + int _c1, _c2; \ + \ + _b_f0 = X##_f0 + X##_f1; \ + _c1 = _b_f0 < X##_f0; \ + _b_f1 = Y##_f0 + Y##_f1; \ + _c2 = _b_f1 < Y##_f0; \ + doit(_d, _FP_FRAC_WORD_4(_z,0), X##_f0, Y##_f0); \ + doit(_FP_FRAC_WORD_4(_z,2), _FP_FRAC_WORD_4(_z,1), _b_f0, _b_f1); \ + doit(_c_f1, _c_f0, X##_f1, Y##_f1); \ + \ + _b_f0 &= -_c2; \ + _b_f1 &= -_c1; \ + __FP_FRAC_ADD_3(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2), \ + _FP_FRAC_WORD_4(_z,1), (_c1 & _c2), 0, _d, \ + 0, _FP_FRAC_WORD_4(_z,2), _FP_FRAC_WORD_4(_z,1)); \ + __FP_FRAC_ADDI_2(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2), \ + _b_f0); \ + __FP_FRAC_ADDI_2(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2), \ + _b_f1); \ + __FP_FRAC_DEC_3(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2), \ + _FP_FRAC_WORD_4(_z,1), \ + 0, _d, _FP_FRAC_WORD_4(_z,0)); \ + __FP_FRAC_DEC_3(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2), \ + _FP_FRAC_WORD_4(_z,1), 0, _c_f1, _c_f0); \ + __FP_FRAC_ADD_2(_FP_FRAC_WORD_4(_z,3), _FP_FRAC_WORD_4(_z,2), \ + _c_f1, _c_f0, \ + _FP_FRAC_WORD_4(_z,3), _FP_FRAC_WORD_4(_z,2)); \ + \ + /* Normalize since we know where the msb of the multiplicands \ + were (bit B), we know that the msb of the of the product is \ + at either 2B or 2B-1. */ \ + _FP_FRAC_SRS_4(_z, wfracbits-1, 2*wfracbits); \ + R##_f0 = _FP_FRAC_WORD_4(_z,0); \ + R##_f1 = _FP_FRAC_WORD_4(_z,1); \ + } while (0) + +#define _FP_MUL_MEAT_2_gmp(wfracbits, R, X, Y) \ + do { \ + _FP_FRAC_DECL_4(_z); \ + _FP_W_TYPE _x[2], _y[2]; \ + _x[0] = X##_f0; _x[1] = X##_f1; \ + _y[0] = Y##_f0; _y[1] = Y##_f1; \ + \ + mpn_mul_n(_z_f, _x, _y, 2); \ + \ + /* Normalize since we know where the msb of the multiplicands \ + were (bit B), we know that the msb of the of the product is \ + at either 2B or 2B-1. */ \ + _FP_FRAC_SRS_4(_z, wfracbits-1, 2*wfracbits); \ + R##_f0 = _z_f[0]; \ + R##_f1 = _z_f[1]; \ + } while (0) + +/* Do at most 120x120=240 bits multiplication using double floating + point multiplication. This is useful if floating point + multiplication has much bigger throughput than integer multiply. + It is supposed to work for _FP_W_TYPE_SIZE 64 and wfracbits + between 106 and 120 only. + Caller guarantees that X and Y has (1LLL << (wfracbits - 1)) set. + SETFETZ is a macro which will disable all FPU exceptions and set rounding + towards zero, RESETFE should optionally reset it back. */ + +#define _FP_MUL_MEAT_2_120_240_double(wfracbits, R, X, Y, setfetz, resetfe) \ + do { \ + static const double _const[] = { \ + /* 2^-24 */ 5.9604644775390625e-08, \ + /* 2^-48 */ 3.5527136788005009e-15, \ + /* 2^-72 */ 2.1175823681357508e-22, \ + /* 2^-96 */ 1.2621774483536189e-29, \ + /* 2^28 */ 2.68435456e+08, \ + /* 2^4 */ 1.600000e+01, \ + /* 2^-20 */ 9.5367431640625e-07, \ + /* 2^-44 */ 5.6843418860808015e-14, \ + /* 2^-68 */ 3.3881317890172014e-21, \ + /* 2^-92 */ 2.0194839173657902e-28, \ + /* 2^-116 */ 1.2037062152420224e-35}; \ + double _a240, _b240, _c240, _d240, _e240, _f240, \ + _g240, _h240, _i240, _j240, _k240; \ + union { double d; UDItype i; } _l240, _m240, _n240, _o240, \ + _p240, _q240, _r240, _s240; \ + UDItype _t240, _u240, _v240, _w240, _x240, _y240 = 0; \ + \ + if (wfracbits < 106 || wfracbits > 120) \ + abort(); \ + \ + setfetz; \ + \ + _e240 = (double)(long)(X##_f0 & 0xffffff); \ + _j240 = (double)(long)(Y##_f0 & 0xffffff); \ + _d240 = (double)(long)((X##_f0 >> 24) & 0xffffff); \ + _i240 = (double)(long)((Y##_f0 >> 24) & 0xffffff); \ + _c240 = (double)(long)(((X##_f1 << 16) & 0xffffff) | (X##_f0 >> 48)); \ + _h240 = (double)(long)(((Y##_f1 << 16) & 0xffffff) | (Y##_f0 >> 48)); \ + _b240 = (double)(long)((X##_f1 >> 8) & 0xffffff); \ + _g240 = (double)(long)((Y##_f1 >> 8) & 0xffffff); \ + _a240 = (double)(long)(X##_f1 >> 32); \ + _f240 = (double)(long)(Y##_f1 >> 32); \ + _e240 *= _const[3]; \ + _j240 *= _const[3]; \ + _d240 *= _const[2]; \ + _i240 *= _const[2]; \ + _c240 *= _const[1]; \ + _h240 *= _const[1]; \ + _b240 *= _const[0]; \ + _g240 *= _const[0]; \ + _s240.d = _e240*_j240;\ + _r240.d = _d240*_j240 + _e240*_i240;\ + _q240.d = _c240*_j240 + _d240*_i240 + _e240*_h240;\ + _p240.d = _b240*_j240 + _c240*_i240 + _d240*_h240 + _e240*_g240;\ + _o240.d = _a240*_j240 + _b240*_i240 + _c240*_h240 + _d240*_g240 + _e240*_f240;\ + _n240.d = _a240*_i240 + _b240*_h240 + _c240*_g240 + _d240*_f240; \ + _m240.d = _a240*_h240 + _b240*_g240 + _c240*_f240; \ + _l240.d = _a240*_g240 + _b240*_f240; \ + _k240 = _a240*_f240; \ + _r240.d += _s240.d; \ + _q240.d += _r240.d; \ + _p240.d += _q240.d; \ + _o240.d += _p240.d; \ + _n240.d += _o240.d; \ + _m240.d += _n240.d; \ + _l240.d += _m240.d; \ + _k240 += _l240.d; \ + _s240.d -= ((_const[10]+_s240.d)-_const[10]); \ + _r240.d -= ((_const[9]+_r240.d)-_const[9]); \ + _q240.d -= ((_const[8]+_q240.d)-_const[8]); \ + _p240.d -= ((_const[7]+_p240.d)-_const[7]); \ + _o240.d += _const[7]; \ + _n240.d += _const[6]; \ + _m240.d += _const[5]; \ + _l240.d += _const[4]; \ + if (_s240.d != 0.0) _y240 = 1; \ + if (_r240.d != 0.0) _y240 = 1; \ + if (_q240.d != 0.0) _y240 = 1; \ + if (_p240.d != 0.0) _y240 = 1; \ + _t240 = (DItype)_k240; \ + _u240 = _l240.i; \ + _v240 = _m240.i; \ + _w240 = _n240.i; \ + _x240 = _o240.i; \ + R##_f1 = (_t240 << (128 - (wfracbits - 1))) \ + | ((_u240 & 0xffffff) >> ((wfracbits - 1) - 104)); \ + R##_f0 = ((_u240 & 0xffffff) << (168 - (wfracbits - 1))) \ + | ((_v240 & 0xffffff) << (144 - (wfracbits - 1))) \ + | ((_w240 & 0xffffff) << (120 - (wfracbits - 1))) \ + | ((_x240 & 0xffffff) >> ((wfracbits - 1) - 96)) \ + | _y240; \ + resetfe; \ + } while (0) + +/* + * Division algorithms: + */ + +#define _FP_DIV_MEAT_2_udiv(fs, R, X, Y) \ + do { \ + _FP_W_TYPE _n_f2, _n_f1, _n_f0, _r_f1, _r_f0, _m_f1, _m_f0; \ + if (_FP_FRAC_GT_2(X, Y)) \ + { \ + _n_f2 = X##_f1 >> 1; \ + _n_f1 = X##_f1 << (_FP_W_TYPE_SIZE - 1) | X##_f0 >> 1; \ + _n_f0 = X##_f0 << (_FP_W_TYPE_SIZE - 1); \ + } \ + else \ + { \ + R##_e--; \ + _n_f2 = X##_f1; \ + _n_f1 = X##_f0; \ + _n_f0 = 0; \ + } \ + \ + /* Normalize, i.e. make the most significant bit of the \ + denominator set. */ \ + _FP_FRAC_SLL_2(Y, _FP_WFRACXBITS_##fs); \ + \ + udiv_qrnnd(R##_f1, _r_f1, _n_f2, _n_f1, Y##_f1); \ + umul_ppmm(_m_f1, _m_f0, R##_f1, Y##_f0); \ + _r_f0 = _n_f0; \ + if (_FP_FRAC_GT_2(_m, _r)) \ + { \ + R##_f1--; \ + _FP_FRAC_ADD_2(_r, Y, _r); \ + if (_FP_FRAC_GE_2(_r, Y) && _FP_FRAC_GT_2(_m, _r)) \ + { \ + R##_f1--; \ + _FP_FRAC_ADD_2(_r, Y, _r); \ + } \ + } \ + _FP_FRAC_DEC_2(_r, _m); \ + \ + if (_r_f1 == Y##_f1) \ + { \ + /* This is a special case, not an optimization \ + (_r/Y##_f1 would not fit into UWtype). \ + As _r is guaranteed to be < Y, R##_f0 can be either \ + (UWtype)-1 or (UWtype)-2. But as we know what kind \ + of bits it is (sticky, guard, round), we don't care. \ + We also don't care what the reminder is, because the \ + guard bit will be set anyway. -jj */ \ + R##_f0 = -1; \ + } \ + else \ + { \ + udiv_qrnnd(R##_f0, _r_f1, _r_f1, _r_f0, Y##_f1); \ + umul_ppmm(_m_f1, _m_f0, R##_f0, Y##_f0); \ + _r_f0 = 0; \ + if (_FP_FRAC_GT_2(_m, _r)) \ + { \ + R##_f0--; \ + _FP_FRAC_ADD_2(_r, Y, _r); \ + if (_FP_FRAC_GE_2(_r, Y) && _FP_FRAC_GT_2(_m, _r)) \ + { \ + R##_f0--; \ + _FP_FRAC_ADD_2(_r, Y, _r); \ + } \ + } \ + if (!_FP_FRAC_EQ_2(_r, _m)) \ + R##_f0 |= _FP_WORK_STICKY; \ + } \ + } while (0) + + +#define _FP_DIV_MEAT_2_gmp(fs, R, X, Y) \ + do { \ + _FP_W_TYPE _x[4], _y[2], _z[4]; \ + _y[0] = Y##_f0; _y[1] = Y##_f1; \ + _x[0] = _x[3] = 0; \ + if (_FP_FRAC_GT_2(X, Y)) \ + { \ + R##_e++; \ + _x[1] = (X##_f0 << (_FP_WFRACBITS_##fs-1 - _FP_W_TYPE_SIZE) | \ + X##_f1 >> (_FP_W_TYPE_SIZE - \ + (_FP_WFRACBITS_##fs-1 - _FP_W_TYPE_SIZE))); \ + _x[2] = X##_f1 << (_FP_WFRACBITS_##fs-1 - _FP_W_TYPE_SIZE); \ + } \ + else \ + { \ + _x[1] = (X##_f0 << (_FP_WFRACBITS_##fs - _FP_W_TYPE_SIZE) | \ + X##_f1 >> (_FP_W_TYPE_SIZE - \ + (_FP_WFRACBITS_##fs - _FP_W_TYPE_SIZE))); \ + _x[2] = X##_f1 << (_FP_WFRACBITS_##fs - _FP_W_TYPE_SIZE); \ + } \ + \ + (void) mpn_divrem (_z, 0, _x, 4, _y, 2); \ + R##_f1 = _z[1]; \ + R##_f0 = _z[0] | ((_x[0] | _x[1]) != 0); \ + } while (0) + + +/* + * Square root algorithms: + * We have just one right now, maybe Newton approximation + * should be added for those machines where division is fast. + */ + +#define _FP_SQRT_MEAT_2(R, S, T, X, q) \ + do { \ + while (q) \ + { \ + T##_f1 = S##_f1 + q; \ + if (T##_f1 <= X##_f1) \ + { \ + S##_f1 = T##_f1 + q; \ + X##_f1 -= T##_f1; \ + R##_f1 += q; \ + } \ + _FP_FRAC_SLL_2(X, 1); \ + q >>= 1; \ + } \ + q = (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE - 1); \ + while (q != _FP_WORK_ROUND) \ + { \ + T##_f0 = S##_f0 + q; \ + T##_f1 = S##_f1; \ + if (T##_f1 < X##_f1 || \ + (T##_f1 == X##_f1 && T##_f0 <= X##_f0)) \ + { \ + S##_f0 = T##_f0 + q; \ + S##_f1 += (T##_f0 > S##_f0); \ + _FP_FRAC_DEC_2(X, T); \ + R##_f0 += q; \ + } \ + _FP_FRAC_SLL_2(X, 1); \ + q >>= 1; \ + } \ + if (X##_f0 | X##_f1) \ + { \ + if (S##_f1 < X##_f1 || \ + (S##_f1 == X##_f1 && S##_f0 < X##_f0)) \ + R##_f0 |= _FP_WORK_ROUND; \ + R##_f0 |= _FP_WORK_STICKY; \ + } \ + } while (0) + + +/* + * Assembly/disassembly for converting to/from integral types. + * No shifting or overflow handled here. + */ + +#define _FP_FRAC_ASSEMBLE_2(r, X, rsize) \ +(void)((rsize <= _FP_W_TYPE_SIZE) \ + ? ({ r = X##_f0; }) \ + : ({ \ + r = X##_f1; \ + r <<= _FP_W_TYPE_SIZE; \ + r += X##_f0; \ + })) + +#define _FP_FRAC_DISASSEMBLE_2(X, r, rsize) \ + do { \ + X##_f0 = r; \ + X##_f1 = (rsize <= _FP_W_TYPE_SIZE ? 0 : r >> _FP_W_TYPE_SIZE); \ + } while (0) + +/* + * Convert FP values between word sizes + */ + +#define _FP_FRAC_COPY_1_2(D, S) (D##_f = S##_f0) + +#define _FP_FRAC_COPY_2_1(D, S) ((D##_f0 = S##_f), (D##_f1 = 0)) + +#define _FP_FRAC_COPY_2_2(D,S) _FP_FRAC_COPY_2(D,S) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/op-4.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/op-4.h new file mode 100644 index 00000000..70b9fafb --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/op-4.h @@ -0,0 +1,688 @@ +/* Software floating-point emulation. + Basic four-word fraction declaration and manipulation. + Copyright (C) 1997,1998,1999,2006,2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson (rth@cygnus.com), + Jakub Jelinek (jj@ultra.linux.cz), + David S. Miller (davem@redhat.com) and + Peter Maydell (pmaydell@chiark.greenend.org.uk). + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file into + combinations with other programs, and to distribute those + combinations without any restriction coming from the use of this + file. (The Lesser General Public License restrictions do apply in + other respects; for example, they cover modification of the file, + and distribution when not linked into a combine executable.) + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301, USA. */ + +#define _FP_FRAC_DECL_4(X) _FP_W_TYPE X##_f[4] +#define _FP_FRAC_COPY_4(D,S) \ + (D##_f[0] = S##_f[0], D##_f[1] = S##_f[1], \ + D##_f[2] = S##_f[2], D##_f[3] = S##_f[3]) +#define _FP_FRAC_SET_4(X,I) __FP_FRAC_SET_4(X, I) +#define _FP_FRAC_HIGH_4(X) (X##_f[3]) +#define _FP_FRAC_LOW_4(X) (X##_f[0]) +#define _FP_FRAC_WORD_4(X,w) (X##_f[w]) + +#define _FP_FRAC_SLL_4(X,N) \ + do { \ + _FP_I_TYPE _up, _down, _skip, _i; \ + _skip = (N) / _FP_W_TYPE_SIZE; \ + _up = (N) % _FP_W_TYPE_SIZE; \ + _down = _FP_W_TYPE_SIZE - _up; \ + if (!_up) \ + for (_i = 3; _i >= _skip; --_i) \ + X##_f[_i] = X##_f[_i-_skip]; \ + else \ + { \ + for (_i = 3; _i > _skip; --_i) \ + X##_f[_i] = X##_f[_i-_skip] << _up \ + | X##_f[_i-_skip-1] >> _down; \ + X##_f[_i--] = X##_f[0] << _up; \ + } \ + for (; _i >= 0; --_i) \ + X##_f[_i] = 0; \ + } while (0) + +/* This one was broken too */ +#define _FP_FRAC_SRL_4(X,N) \ + do { \ + _FP_I_TYPE _up, _down, _skip, _i; \ + _skip = (N) / _FP_W_TYPE_SIZE; \ + _down = (N) % _FP_W_TYPE_SIZE; \ + _up = _FP_W_TYPE_SIZE - _down; \ + if (!_down) \ + for (_i = 0; _i <= 3-_skip; ++_i) \ + X##_f[_i] = X##_f[_i+_skip]; \ + else \ + { \ + for (_i = 0; _i < 3-_skip; ++_i) \ + X##_f[_i] = X##_f[_i+_skip] >> _down \ + | X##_f[_i+_skip+1] << _up; \ + X##_f[_i++] = X##_f[3] >> _down; \ + } \ + for (; _i < 4; ++_i) \ + X##_f[_i] = 0; \ + } while (0) + + +/* Right shift with sticky-lsb. + * What this actually means is that we do a standard right-shift, + * but that if any of the bits that fall off the right hand side + * were one then we always set the LSbit. + */ +#define _FP_FRAC_SRST_4(X,S,N,size) \ + do { \ + _FP_I_TYPE _up, _down, _skip, _i; \ + _FP_W_TYPE _s; \ + _skip = (N) / _FP_W_TYPE_SIZE; \ + _down = (N) % _FP_W_TYPE_SIZE; \ + _up = _FP_W_TYPE_SIZE - _down; \ + for (_s = _i = 0; _i < _skip; ++_i) \ + _s |= X##_f[_i]; \ + if (!_down) \ + for (_i = 0; _i <= 3-_skip; ++_i) \ + X##_f[_i] = X##_f[_i+_skip]; \ + else \ + { \ + _s |= X##_f[_i] << _up; \ + for (_i = 0; _i < 3-_skip; ++_i) \ + X##_f[_i] = X##_f[_i+_skip] >> _down \ + | X##_f[_i+_skip+1] << _up; \ + X##_f[_i++] = X##_f[3] >> _down; \ + } \ + for (; _i < 4; ++_i) \ + X##_f[_i] = 0; \ + S = (_s != 0); \ + } while (0) + +#define _FP_FRAC_SRS_4(X,N,size) \ + do { \ + int _sticky; \ + _FP_FRAC_SRST_4(X, _sticky, N, size); \ + X##_f[0] |= _sticky; \ + } while (0) + +#define _FP_FRAC_ADD_4(R,X,Y) \ + __FP_FRAC_ADD_4(R##_f[3], R##_f[2], R##_f[1], R##_f[0], \ + X##_f[3], X##_f[2], X##_f[1], X##_f[0], \ + Y##_f[3], Y##_f[2], Y##_f[1], Y##_f[0]) + +#define _FP_FRAC_SUB_4(R,X,Y) \ + __FP_FRAC_SUB_4(R##_f[3], R##_f[2], R##_f[1], R##_f[0], \ + X##_f[3], X##_f[2], X##_f[1], X##_f[0], \ + Y##_f[3], Y##_f[2], Y##_f[1], Y##_f[0]) + +#define _FP_FRAC_DEC_4(X,Y) \ + __FP_FRAC_DEC_4(X##_f[3], X##_f[2], X##_f[1], X##_f[0], \ + Y##_f[3], Y##_f[2], Y##_f[1], Y##_f[0]) + +#define _FP_FRAC_ADDI_4(X,I) \ + __FP_FRAC_ADDI_4(X##_f[3], X##_f[2], X##_f[1], X##_f[0], I) + +#define _FP_ZEROFRAC_4 0,0,0,0 +#define _FP_MINFRAC_4 0,0,0,1 +#define _FP_MAXFRAC_4 (~(_FP_WS_TYPE)0), (~(_FP_WS_TYPE)0), (~(_FP_WS_TYPE)0), (~(_FP_WS_TYPE)0) + +#define _FP_FRAC_ZEROP_4(X) ((X##_f[0] | X##_f[1] | X##_f[2] | X##_f[3]) == 0) +#define _FP_FRAC_NEGP_4(X) ((_FP_WS_TYPE)X##_f[3] < 0) +#define _FP_FRAC_OVERP_4(fs,X) (_FP_FRAC_HIGH_##fs(X) & _FP_OVERFLOW_##fs) +#define _FP_FRAC_CLEAR_OVERP_4(fs,X) (_FP_FRAC_HIGH_##fs(X) &= ~_FP_OVERFLOW_##fs) + +#define _FP_FRAC_EQ_4(X,Y) \ + (X##_f[0] == Y##_f[0] && X##_f[1] == Y##_f[1] \ + && X##_f[2] == Y##_f[2] && X##_f[3] == Y##_f[3]) + +#define _FP_FRAC_GT_4(X,Y) \ + (X##_f[3] > Y##_f[3] || \ + (X##_f[3] == Y##_f[3] && (X##_f[2] > Y##_f[2] || \ + (X##_f[2] == Y##_f[2] && (X##_f[1] > Y##_f[1] || \ + (X##_f[1] == Y##_f[1] && X##_f[0] > Y##_f[0]) \ + )) \ + )) \ + ) + +#define _FP_FRAC_GE_4(X,Y) \ + (X##_f[3] > Y##_f[3] || \ + (X##_f[3] == Y##_f[3] && (X##_f[2] > Y##_f[2] || \ + (X##_f[2] == Y##_f[2] && (X##_f[1] > Y##_f[1] || \ + (X##_f[1] == Y##_f[1] && X##_f[0] >= Y##_f[0]) \ + )) \ + )) \ + ) + + +#define _FP_FRAC_CLZ_4(R,X) \ + do { \ + if (X##_f[3]) \ + { \ + __FP_CLZ(R,X##_f[3]); \ + } \ + else if (X##_f[2]) \ + { \ + __FP_CLZ(R,X##_f[2]); \ + R += _FP_W_TYPE_SIZE; \ + } \ + else if (X##_f[1]) \ + { \ + __FP_CLZ(R,X##_f[1]); \ + R += _FP_W_TYPE_SIZE*2; \ + } \ + else \ + { \ + __FP_CLZ(R,X##_f[0]); \ + R += _FP_W_TYPE_SIZE*3; \ + } \ + } while(0) + + +#define _FP_UNPACK_RAW_4(fs, X, val) \ + do { \ + union _FP_UNION_##fs _flo; _flo.flt = (val); \ + X##_f[0] = _flo.bits.frac0; \ + X##_f[1] = _flo.bits.frac1; \ + X##_f[2] = _flo.bits.frac2; \ + X##_f[3] = _flo.bits.frac3; \ + X##_e = _flo.bits.exp; \ + X##_s = _flo.bits.sign; \ + } while (0) + +#define _FP_UNPACK_RAW_4_P(fs, X, val) \ + do { \ + union _FP_UNION_##fs *_flo = \ + (union _FP_UNION_##fs *)(val); \ + \ + X##_f[0] = _flo->bits.frac0; \ + X##_f[1] = _flo->bits.frac1; \ + X##_f[2] = _flo->bits.frac2; \ + X##_f[3] = _flo->bits.frac3; \ + X##_e = _flo->bits.exp; \ + X##_s = _flo->bits.sign; \ + } while (0) + +#define _FP_PACK_RAW_4(fs, val, X) \ + do { \ + union _FP_UNION_##fs _flo; \ + _flo.bits.frac0 = X##_f[0]; \ + _flo.bits.frac1 = X##_f[1]; \ + _flo.bits.frac2 = X##_f[2]; \ + _flo.bits.frac3 = X##_f[3]; \ + _flo.bits.exp = X##_e; \ + _flo.bits.sign = X##_s; \ + (val) = _flo.flt; \ + } while (0) + +#define _FP_PACK_RAW_4_P(fs, val, X) \ + do { \ + union _FP_UNION_##fs *_flo = \ + (union _FP_UNION_##fs *)(val); \ + \ + _flo->bits.frac0 = X##_f[0]; \ + _flo->bits.frac1 = X##_f[1]; \ + _flo->bits.frac2 = X##_f[2]; \ + _flo->bits.frac3 = X##_f[3]; \ + _flo->bits.exp = X##_e; \ + _flo->bits.sign = X##_s; \ + } while (0) + +/* + * Multiplication algorithms: + */ + +/* Given a 1W * 1W => 2W primitive, do the extended multiplication. */ + +#define _FP_MUL_MEAT_4_wide(wfracbits, R, X, Y, doit) \ + do { \ + _FP_FRAC_DECL_8(_z); _FP_FRAC_DECL_2(_b); _FP_FRAC_DECL_2(_c); \ + _FP_FRAC_DECL_2(_d); _FP_FRAC_DECL_2(_e); _FP_FRAC_DECL_2(_f); \ + \ + doit(_FP_FRAC_WORD_8(_z,1), _FP_FRAC_WORD_8(_z,0), X##_f[0], Y##_f[0]); \ + doit(_b_f1, _b_f0, X##_f[0], Y##_f[1]); \ + doit(_c_f1, _c_f0, X##_f[1], Y##_f[0]); \ + doit(_d_f1, _d_f0, X##_f[1], Y##_f[1]); \ + doit(_e_f1, _e_f0, X##_f[0], Y##_f[2]); \ + doit(_f_f1, _f_f0, X##_f[2], Y##_f[0]); \ + __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,3),_FP_FRAC_WORD_8(_z,2), \ + _FP_FRAC_WORD_8(_z,1), 0,_b_f1,_b_f0, \ + 0,0,_FP_FRAC_WORD_8(_z,1)); \ + __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,3),_FP_FRAC_WORD_8(_z,2), \ + _FP_FRAC_WORD_8(_z,1), 0,_c_f1,_c_f0, \ + _FP_FRAC_WORD_8(_z,3),_FP_FRAC_WORD_8(_z,2), \ + _FP_FRAC_WORD_8(_z,1)); \ + __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,4),_FP_FRAC_WORD_8(_z,3), \ + _FP_FRAC_WORD_8(_z,2), 0,_d_f1,_d_f0, \ + 0,_FP_FRAC_WORD_8(_z,3),_FP_FRAC_WORD_8(_z,2)); \ + __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,4),_FP_FRAC_WORD_8(_z,3), \ + _FP_FRAC_WORD_8(_z,2), 0,_e_f1,_e_f0, \ + _FP_FRAC_WORD_8(_z,4),_FP_FRAC_WORD_8(_z,3), \ + _FP_FRAC_WORD_8(_z,2)); \ + __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,4),_FP_FRAC_WORD_8(_z,3), \ + _FP_FRAC_WORD_8(_z,2), 0,_f_f1,_f_f0, \ + _FP_FRAC_WORD_8(_z,4),_FP_FRAC_WORD_8(_z,3), \ + _FP_FRAC_WORD_8(_z,2)); \ + doit(_b_f1, _b_f0, X##_f[0], Y##_f[3]); \ + doit(_c_f1, _c_f0, X##_f[3], Y##_f[0]); \ + doit(_d_f1, _d_f0, X##_f[1], Y##_f[2]); \ + doit(_e_f1, _e_f0, X##_f[2], Y##_f[1]); \ + __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4), \ + _FP_FRAC_WORD_8(_z,3), 0,_b_f1,_b_f0, \ + 0,_FP_FRAC_WORD_8(_z,4),_FP_FRAC_WORD_8(_z,3)); \ + __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4), \ + _FP_FRAC_WORD_8(_z,3), 0,_c_f1,_c_f0, \ + _FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4), \ + _FP_FRAC_WORD_8(_z,3)); \ + __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4), \ + _FP_FRAC_WORD_8(_z,3), 0,_d_f1,_d_f0, \ + _FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4), \ + _FP_FRAC_WORD_8(_z,3)); \ + __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4), \ + _FP_FRAC_WORD_8(_z,3), 0,_e_f1,_e_f0, \ + _FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4), \ + _FP_FRAC_WORD_8(_z,3)); \ + doit(_b_f1, _b_f0, X##_f[2], Y##_f[2]); \ + doit(_c_f1, _c_f0, X##_f[1], Y##_f[3]); \ + doit(_d_f1, _d_f0, X##_f[3], Y##_f[1]); \ + doit(_e_f1, _e_f0, X##_f[2], Y##_f[3]); \ + doit(_f_f1, _f_f0, X##_f[3], Y##_f[2]); \ + __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,6),_FP_FRAC_WORD_8(_z,5), \ + _FP_FRAC_WORD_8(_z,4), 0,_b_f1,_b_f0, \ + 0,_FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4)); \ + __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,6),_FP_FRAC_WORD_8(_z,5), \ + _FP_FRAC_WORD_8(_z,4), 0,_c_f1,_c_f0, \ + _FP_FRAC_WORD_8(_z,6),_FP_FRAC_WORD_8(_z,5), \ + _FP_FRAC_WORD_8(_z,4)); \ + __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,6),_FP_FRAC_WORD_8(_z,5), \ + _FP_FRAC_WORD_8(_z,4), 0,_d_f1,_d_f0, \ + _FP_FRAC_WORD_8(_z,6),_FP_FRAC_WORD_8(_z,5), \ + _FP_FRAC_WORD_8(_z,4)); \ + __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,7),_FP_FRAC_WORD_8(_z,6), \ + _FP_FRAC_WORD_8(_z,5), 0,_e_f1,_e_f0, \ + 0,_FP_FRAC_WORD_8(_z,6),_FP_FRAC_WORD_8(_z,5)); \ + __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,7),_FP_FRAC_WORD_8(_z,6), \ + _FP_FRAC_WORD_8(_z,5), 0,_f_f1,_f_f0, \ + _FP_FRAC_WORD_8(_z,7),_FP_FRAC_WORD_8(_z,6), \ + _FP_FRAC_WORD_8(_z,5)); \ + doit(_b_f1, _b_f0, X##_f[3], Y##_f[3]); \ + __FP_FRAC_ADD_2(_FP_FRAC_WORD_8(_z,7),_FP_FRAC_WORD_8(_z,6), \ + _b_f1,_b_f0, \ + _FP_FRAC_WORD_8(_z,7),_FP_FRAC_WORD_8(_z,6)); \ + \ + /* Normalize since we know where the msb of the multiplicands \ + were (bit B), we know that the msb of the of the product is \ + at either 2B or 2B-1. */ \ + _FP_FRAC_SRS_8(_z, wfracbits-1, 2*wfracbits); \ + __FP_FRAC_SET_4(R, _FP_FRAC_WORD_8(_z,3), _FP_FRAC_WORD_8(_z,2), \ + _FP_FRAC_WORD_8(_z,1), _FP_FRAC_WORD_8(_z,0)); \ + } while (0) + +#define _FP_MUL_MEAT_4_gmp(wfracbits, R, X, Y) \ + do { \ + _FP_FRAC_DECL_8(_z); \ + \ + mpn_mul_n(_z_f, _x_f, _y_f, 4); \ + \ + /* Normalize since we know where the msb of the multiplicands \ + were (bit B), we know that the msb of the of the product is \ + at either 2B or 2B-1. */ \ + _FP_FRAC_SRS_8(_z, wfracbits-1, 2*wfracbits); \ + __FP_FRAC_SET_4(R, _FP_FRAC_WORD_8(_z,3), _FP_FRAC_WORD_8(_z,2), \ + _FP_FRAC_WORD_8(_z,1), _FP_FRAC_WORD_8(_z,0)); \ + } while (0) + +/* + * Helper utility for _FP_DIV_MEAT_4_udiv: + * pppp = m * nnn + */ +#define umul_ppppmnnn(p3,p2,p1,p0,m,n2,n1,n0) \ + do { \ + UWtype _t; \ + umul_ppmm(p1,p0,m,n0); \ + umul_ppmm(p2,_t,m,n1); \ + __FP_FRAC_ADDI_2(p2,p1,_t); \ + umul_ppmm(p3,_t,m,n2); \ + __FP_FRAC_ADDI_2(p3,p2,_t); \ + } while (0) + +/* + * Division algorithms: + */ + +#define _FP_DIV_MEAT_4_udiv(fs, R, X, Y) \ + do { \ + int _i; \ + _FP_FRAC_DECL_4(_n); _FP_FRAC_DECL_4(_m); \ + _FP_FRAC_SET_4(_n, _FP_ZEROFRAC_4); \ + if (_FP_FRAC_GT_4(X, Y)) \ + { \ + _n_f[3] = X##_f[0] << (_FP_W_TYPE_SIZE - 1); \ + _FP_FRAC_SRL_4(X, 1); \ + } \ + else \ + R##_e--; \ + \ + /* Normalize, i.e. make the most significant bit of the \ + denominator set. */ \ + _FP_FRAC_SLL_4(Y, _FP_WFRACXBITS_##fs); \ + \ + for (_i = 3; ; _i--) \ + { \ + if (X##_f[3] == Y##_f[3]) \ + { \ + /* This is a special case, not an optimization \ + (X##_f[3]/Y##_f[3] would not fit into UWtype). \ + As X## is guaranteed to be < Y, R##_f[_i] can be either \ + (UWtype)-1 or (UWtype)-2. */ \ + R##_f[_i] = -1; \ + if (!_i) \ + break; \ + __FP_FRAC_SUB_4(X##_f[3], X##_f[2], X##_f[1], X##_f[0], \ + Y##_f[2], Y##_f[1], Y##_f[0], 0, \ + X##_f[2], X##_f[1], X##_f[0], _n_f[_i]); \ + _FP_FRAC_SUB_4(X, Y, X); \ + if (X##_f[3] > Y##_f[3]) \ + { \ + R##_f[_i] = -2; \ + _FP_FRAC_ADD_4(X, Y, X); \ + } \ + } \ + else \ + { \ + udiv_qrnnd(R##_f[_i], X##_f[3], X##_f[3], X##_f[2], Y##_f[3]); \ + umul_ppppmnnn(_m_f[3], _m_f[2], _m_f[1], _m_f[0], \ + R##_f[_i], Y##_f[2], Y##_f[1], Y##_f[0]); \ + X##_f[2] = X##_f[1]; \ + X##_f[1] = X##_f[0]; \ + X##_f[0] = _n_f[_i]; \ + if (_FP_FRAC_GT_4(_m, X)) \ + { \ + R##_f[_i]--; \ + _FP_FRAC_ADD_4(X, Y, X); \ + if (_FP_FRAC_GE_4(X, Y) && _FP_FRAC_GT_4(_m, X)) \ + { \ + R##_f[_i]--; \ + _FP_FRAC_ADD_4(X, Y, X); \ + } \ + } \ + _FP_FRAC_DEC_4(X, _m); \ + if (!_i) \ + { \ + if (!_FP_FRAC_EQ_4(X, _m)) \ + R##_f[0] |= _FP_WORK_STICKY; \ + break; \ + } \ + } \ + } \ + } while (0) + + +/* + * Square root algorithms: + * We have just one right now, maybe Newton approximation + * should be added for those machines where division is fast. + */ + +#define _FP_SQRT_MEAT_4(R, S, T, X, q) \ + do { \ + while (q) \ + { \ + T##_f[3] = S##_f[3] + q; \ + if (T##_f[3] <= X##_f[3]) \ + { \ + S##_f[3] = T##_f[3] + q; \ + X##_f[3] -= T##_f[3]; \ + R##_f[3] += q; \ + } \ + _FP_FRAC_SLL_4(X, 1); \ + q >>= 1; \ + } \ + q = (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE - 1); \ + while (q) \ + { \ + T##_f[2] = S##_f[2] + q; \ + T##_f[3] = S##_f[3]; \ + if (T##_f[3] < X##_f[3] || \ + (T##_f[3] == X##_f[3] && T##_f[2] <= X##_f[2])) \ + { \ + S##_f[2] = T##_f[2] + q; \ + S##_f[3] += (T##_f[2] > S##_f[2]); \ + __FP_FRAC_DEC_2(X##_f[3], X##_f[2], \ + T##_f[3], T##_f[2]); \ + R##_f[2] += q; \ + } \ + _FP_FRAC_SLL_4(X, 1); \ + q >>= 1; \ + } \ + q = (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE - 1); \ + while (q) \ + { \ + T##_f[1] = S##_f[1] + q; \ + T##_f[2] = S##_f[2]; \ + T##_f[3] = S##_f[3]; \ + if (T##_f[3] < X##_f[3] || \ + (T##_f[3] == X##_f[3] && (T##_f[2] < X##_f[2] || \ + (T##_f[2] == X##_f[2] && T##_f[1] <= X##_f[1])))) \ + { \ + S##_f[1] = T##_f[1] + q; \ + S##_f[2] += (T##_f[1] > S##_f[1]); \ + S##_f[3] += (T##_f[2] > S##_f[2]); \ + __FP_FRAC_DEC_3(X##_f[3], X##_f[2], X##_f[1], \ + T##_f[3], T##_f[2], T##_f[1]); \ + R##_f[1] += q; \ + } \ + _FP_FRAC_SLL_4(X, 1); \ + q >>= 1; \ + } \ + q = (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE - 1); \ + while (q != _FP_WORK_ROUND) \ + { \ + T##_f[0] = S##_f[0] + q; \ + T##_f[1] = S##_f[1]; \ + T##_f[2] = S##_f[2]; \ + T##_f[3] = S##_f[3]; \ + if (_FP_FRAC_GE_4(X,T)) \ + { \ + S##_f[0] = T##_f[0] + q; \ + S##_f[1] += (T##_f[0] > S##_f[0]); \ + S##_f[2] += (T##_f[1] > S##_f[1]); \ + S##_f[3] += (T##_f[2] > S##_f[2]); \ + _FP_FRAC_DEC_4(X, T); \ + R##_f[0] += q; \ + } \ + _FP_FRAC_SLL_4(X, 1); \ + q >>= 1; \ + } \ + if (!_FP_FRAC_ZEROP_4(X)) \ + { \ + if (_FP_FRAC_GT_4(X,S)) \ + R##_f[0] |= _FP_WORK_ROUND; \ + R##_f[0] |= _FP_WORK_STICKY; \ + } \ + } while (0) + + +/* + * Internals + */ + +#define __FP_FRAC_SET_4(X,I3,I2,I1,I0) \ + (X##_f[3] = I3, X##_f[2] = I2, X##_f[1] = I1, X##_f[0] = I0) + +#ifndef __FP_FRAC_ADD_3 +#define __FP_FRAC_ADD_3(r2,r1,r0,x2,x1,x0,y2,y1,y0) \ + do { \ + _FP_W_TYPE _c1, _c2; \ + r0 = x0 + y0; \ + _c1 = r0 < x0; \ + r1 = x1 + y1; \ + _c2 = r1 < x1; \ + r1 += _c1; \ + _c2 |= r1 < _c1; \ + r2 = x2 + y2 + _c2; \ + } while (0) +#endif + +#ifndef __FP_FRAC_ADD_4 +#define __FP_FRAC_ADD_4(r3,r2,r1,r0,x3,x2,x1,x0,y3,y2,y1,y0) \ + do { \ + _FP_W_TYPE _c1, _c2, _c3; \ + r0 = x0 + y0; \ + _c1 = r0 < x0; \ + r1 = x1 + y1; \ + _c2 = r1 < x1; \ + r1 += _c1; \ + _c2 |= r1 < _c1; \ + r2 = x2 + y2; \ + _c3 = r2 < x2; \ + r2 += _c2; \ + _c3 |= r2 < _c2; \ + r3 = x3 + y3 + _c3; \ + } while (0) +#endif + +#ifndef __FP_FRAC_SUB_3 +#define __FP_FRAC_SUB_3(r2,r1,r0,x2,x1,x0,y2,y1,y0) \ + do { \ + _FP_W_TYPE _c1, _c2; \ + r0 = x0 - y0; \ + _c1 = r0 > x0; \ + r1 = x1 - y1; \ + _c2 = r1 > x1; \ + r1 -= _c1; \ + _c2 |= _c1 && (y1 == x1); \ + r2 = x2 - y2 - _c2; \ + } while (0) +#endif + +#ifndef __FP_FRAC_SUB_4 +#define __FP_FRAC_SUB_4(r3,r2,r1,r0,x3,x2,x1,x0,y3,y2,y1,y0) \ + do { \ + _FP_W_TYPE _c1, _c2, _c3; \ + r0 = x0 - y0; \ + _c1 = r0 > x0; \ + r1 = x1 - y1; \ + _c2 = r1 > x1; \ + r1 -= _c1; \ + _c2 |= _c1 && (y1 == x1); \ + r2 = x2 - y2; \ + _c3 = r2 > x2; \ + r2 -= _c2; \ + _c3 |= _c2 && (y2 == x2); \ + r3 = x3 - y3 - _c3; \ + } while (0) +#endif + +#ifndef __FP_FRAC_DEC_3 +#define __FP_FRAC_DEC_3(x2,x1,x0,y2,y1,y0) \ + do { \ + UWtype _t0, _t1, _t2; \ + _t0 = x0, _t1 = x1, _t2 = x2; \ + __FP_FRAC_SUB_3 (x2, x1, x0, _t2, _t1, _t0, y2, y1, y0); \ + } while (0) +#endif + +#ifndef __FP_FRAC_DEC_4 +#define __FP_FRAC_DEC_4(x3,x2,x1,x0,y3,y2,y1,y0) \ + do { \ + UWtype _t0, _t1, _t2, _t3; \ + _t0 = x0, _t1 = x1, _t2 = x2, _t3 = x3; \ + __FP_FRAC_SUB_4 (x3,x2,x1,x0,_t3,_t2,_t1,_t0, y3,y2,y1,y0); \ + } while (0) +#endif + +#ifndef __FP_FRAC_ADDI_4 +#define __FP_FRAC_ADDI_4(x3,x2,x1,x0,i) \ + do { \ + UWtype _t; \ + _t = ((x0 += i) < i); \ + x1 += _t; _t = (x1 < _t); \ + x2 += _t; _t = (x2 < _t); \ + x3 += _t; \ + } while (0) +#endif + +/* Convert FP values between word sizes. This appears to be more + * complicated than I'd have expected it to be, so these might be + * wrong... These macros are in any case somewhat bogus because they + * use information about what various FRAC_n variables look like + * internally [eg, that 2 word vars are X_f0 and x_f1]. But so do + * the ones in op-2.h and op-1.h. + */ +#define _FP_FRAC_COPY_1_4(D, S) (D##_f = S##_f[0]) + +#define _FP_FRAC_COPY_2_4(D, S) \ +do { \ + D##_f0 = S##_f[0]; \ + D##_f1 = S##_f[1]; \ +} while (0) + +/* Assembly/disassembly for converting to/from integral types. + * No shifting or overflow handled here. + */ +/* Put the FP value X into r, which is an integer of size rsize. */ +#define _FP_FRAC_ASSEMBLE_4(r, X, rsize) \ + do { \ + if (rsize <= _FP_W_TYPE_SIZE) \ + r = X##_f[0]; \ + else if (rsize <= 2*_FP_W_TYPE_SIZE) \ + { \ + r = X##_f[1]; \ + r <<= _FP_W_TYPE_SIZE; \ + r += X##_f[0]; \ + } \ + else \ + { \ + /* I'm feeling lazy so we deal with int == 3words (implausible)*/ \ + /* and int == 4words as a single case. */ \ + r = X##_f[3]; \ + r <<= _FP_W_TYPE_SIZE; \ + r += X##_f[2]; \ + r <<= _FP_W_TYPE_SIZE; \ + r += X##_f[1]; \ + r <<= _FP_W_TYPE_SIZE; \ + r += X##_f[0]; \ + } \ + } while (0) + +/* "No disassemble Number Five!" */ +/* move an integer of size rsize into X's fractional part. We rely on + * the _f[] array consisting of words of size _FP_W_TYPE_SIZE to avoid + * having to mask the values we store into it. + */ +#define _FP_FRAC_DISASSEMBLE_4(X, r, rsize) \ + do { \ + X##_f[0] = r; \ + X##_f[1] = (rsize <= _FP_W_TYPE_SIZE ? 0 : r >> _FP_W_TYPE_SIZE); \ + X##_f[2] = (rsize <= 2*_FP_W_TYPE_SIZE ? 0 : r >> 2*_FP_W_TYPE_SIZE); \ + X##_f[3] = (rsize <= 3*_FP_W_TYPE_SIZE ? 0 : r >> 3*_FP_W_TYPE_SIZE); \ + } while (0); + +#define _FP_FRAC_COPY_4_1(D, S) \ +do { \ + D##_f[0] = S##_f; \ + D##_f[1] = D##_f[2] = D##_f[3] = 0; \ +} while (0) + +#define _FP_FRAC_COPY_4_2(D, S) \ +do { \ + D##_f[0] = S##_f0; \ + D##_f[1] = S##_f1; \ + D##_f[2] = D##_f[3] = 0; \ +} while (0) + +#define _FP_FRAC_COPY_4_4(D,S) _FP_FRAC_COPY_4(D,S) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/op-8.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/op-8.h new file mode 100644 index 00000000..e0612a5e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/op-8.h @@ -0,0 +1,111 @@ +/* Software floating-point emulation. + Basic eight-word fraction declaration and manipulation. + Copyright (C) 1997,1998,1999,2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson (rth@cygnus.com), + Jakub Jelinek (jj@ultra.linux.cz) and + Peter Maydell (pmaydell@chiark.greenend.org.uk). + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file into + combinations with other programs, and to distribute those + combinations without any restriction coming from the use of this + file. (The Lesser General Public License restrictions do apply in + other respects; for example, they cover modification of the file, + and distribution when not linked into a combine executable.) + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301, USA. */ + +/* We need just a few things from here for op-4, if we ever need some + other macros, they can be added. */ +#define _FP_FRAC_DECL_8(X) _FP_W_TYPE X##_f[8] +#define _FP_FRAC_HIGH_8(X) (X##_f[7]) +#define _FP_FRAC_LOW_8(X) (X##_f[0]) +#define _FP_FRAC_WORD_8(X,w) (X##_f[w]) + +#define _FP_FRAC_SLL_8(X,N) \ + do { \ + _FP_I_TYPE _up, _down, _skip, _i; \ + _skip = (N) / _FP_W_TYPE_SIZE; \ + _up = (N) % _FP_W_TYPE_SIZE; \ + _down = _FP_W_TYPE_SIZE - _up; \ + if (!_up) \ + for (_i = 7; _i >= _skip; --_i) \ + X##_f[_i] = X##_f[_i-_skip]; \ + else \ + { \ + for (_i = 7; _i > _skip; --_i) \ + X##_f[_i] = X##_f[_i-_skip] << _up \ + | X##_f[_i-_skip-1] >> _down; \ + X##_f[_i--] = X##_f[0] << _up; \ + } \ + for (; _i >= 0; --_i) \ + X##_f[_i] = 0; \ + } while (0) + +#define _FP_FRAC_SRL_8(X,N) \ + do { \ + _FP_I_TYPE _up, _down, _skip, _i; \ + _skip = (N) / _FP_W_TYPE_SIZE; \ + _down = (N) % _FP_W_TYPE_SIZE; \ + _up = _FP_W_TYPE_SIZE - _down; \ + if (!_down) \ + for (_i = 0; _i <= 7-_skip; ++_i) \ + X##_f[_i] = X##_f[_i+_skip]; \ + else \ + { \ + for (_i = 0; _i < 7-_skip; ++_i) \ + X##_f[_i] = X##_f[_i+_skip] >> _down \ + | X##_f[_i+_skip+1] << _up; \ + X##_f[_i++] = X##_f[7] >> _down; \ + } \ + for (; _i < 8; ++_i) \ + X##_f[_i] = 0; \ + } while (0) + + +/* Right shift with sticky-lsb. + * What this actually means is that we do a standard right-shift, + * but that if any of the bits that fall off the right hand side + * were one then we always set the LSbit. + */ +#define _FP_FRAC_SRS_8(X,N,size) \ + do { \ + _FP_I_TYPE _up, _down, _skip, _i; \ + _FP_W_TYPE _s; \ + _skip = (N) / _FP_W_TYPE_SIZE; \ + _down = (N) % _FP_W_TYPE_SIZE; \ + _up = _FP_W_TYPE_SIZE - _down; \ + for (_s = _i = 0; _i < _skip; ++_i) \ + _s |= X##_f[_i]; \ + if (!_down) \ + for (_i = 0; _i <= 7-_skip; ++_i) \ + X##_f[_i] = X##_f[_i+_skip]; \ + else \ + { \ + _s |= X##_f[_i] << _up; \ + for (_i = 0; _i < 7-_skip; ++_i) \ + X##_f[_i] = X##_f[_i+_skip] >> _down \ + | X##_f[_i+_skip+1] << _up; \ + X##_f[_i++] = X##_f[7] >> _down; \ + } \ + for (; _i < 8; ++_i) \ + X##_f[_i] = 0; \ + /* don't fix the LSB until the very end when we're sure f[0] is stable */ \ + X##_f[0] |= (_s != 0); \ + } while (0) + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/op-common.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/op-common.h new file mode 100644 index 00000000..ef11b527 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/op-common.h @@ -0,0 +1,1359 @@ +/* Software floating-point emulation. Common operations. + Copyright (C) 1997,1998,1999,2006,2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson (rth@cygnus.com), + Jakub Jelinek (jj@ultra.linux.cz), + David S. Miller (davem@redhat.com) and + Peter Maydell (pmaydell@chiark.greenend.org.uk). + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file into + combinations with other programs, and to distribute those + combinations without any restriction coming from the use of this + file. (The Lesser General Public License restrictions do apply in + other respects; for example, they cover modification of the file, + and distribution when not linked into a combine executable.) + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301, USA. */ + +#define _FP_DECL(wc, X) \ + _FP_I_TYPE X##_c __attribute__((unused)), X##_s, X##_e; \ + _FP_FRAC_DECL_##wc(X) + +/* + * Finish truely unpacking a native fp value by classifying the kind + * of fp value and normalizing both the exponent and the fraction. + */ + +#define _FP_UNPACK_CANONICAL(fs, wc, X) \ +do { \ + switch (X##_e) \ + { \ + default: \ + _FP_FRAC_HIGH_RAW_##fs(X) |= _FP_IMPLBIT_##fs; \ + _FP_FRAC_SLL_##wc(X, _FP_WORKBITS); \ + X##_e -= _FP_EXPBIAS_##fs; \ + X##_c = FP_CLS_NORMAL; \ + break; \ + \ + case 0: \ + if (_FP_FRAC_ZEROP_##wc(X)) \ + X##_c = FP_CLS_ZERO; \ + else \ + { \ + /* a denormalized number */ \ + _FP_I_TYPE _shift; \ + _FP_FRAC_CLZ_##wc(_shift, X); \ + _shift -= _FP_FRACXBITS_##fs; \ + _FP_FRAC_SLL_##wc(X, (_shift+_FP_WORKBITS)); \ + X##_e -= _FP_EXPBIAS_##fs - 1 + _shift; \ + X##_c = FP_CLS_NORMAL; \ + FP_SET_EXCEPTION(FP_EX_DENORM); \ + } \ + break; \ + \ + case _FP_EXPMAX_##fs: \ + if (_FP_FRAC_ZEROP_##wc(X)) \ + X##_c = FP_CLS_INF; \ + else \ + { \ + X##_c = FP_CLS_NAN; \ + /* Check for signaling NaN */ \ + if (!(_FP_FRAC_HIGH_RAW_##fs(X) & _FP_QNANBIT_##fs)) \ + FP_SET_EXCEPTION(FP_EX_INVALID); \ + } \ + break; \ + } \ +} while (0) + +/* Finish unpacking an fp value in semi-raw mode: the mantissa is + shifted by _FP_WORKBITS but the implicit MSB is not inserted and + other classification is not done. */ +#define _FP_UNPACK_SEMIRAW(fs, wc, X) _FP_FRAC_SLL_##wc(X, _FP_WORKBITS) + +/* A semi-raw value has overflowed to infinity. Adjust the mantissa + and exponent appropriately. */ +#define _FP_OVERFLOW_SEMIRAW(fs, wc, X) \ +do { \ + if (FP_ROUNDMODE == FP_RND_NEAREST \ + || (FP_ROUNDMODE == FP_RND_PINF && !X##_s) \ + || (FP_ROUNDMODE == FP_RND_MINF && X##_s)) \ + { \ + X##_e = _FP_EXPMAX_##fs; \ + _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \ + } \ + else \ + { \ + X##_e = _FP_EXPMAX_##fs - 1; \ + _FP_FRAC_SET_##wc(X, _FP_MAXFRAC_##wc); \ + } \ + FP_SET_EXCEPTION(FP_EX_INEXACT); \ + FP_SET_EXCEPTION(FP_EX_OVERFLOW); \ +} while (0) + +/* Check for a semi-raw value being a signaling NaN and raise the + invalid exception if so. */ +#define _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, X) \ +do { \ + if (X##_e == _FP_EXPMAX_##fs \ + && !_FP_FRAC_ZEROP_##wc(X) \ + && !(_FP_FRAC_HIGH_##fs(X) & _FP_QNANBIT_SH_##fs)) \ + FP_SET_EXCEPTION(FP_EX_INVALID); \ +} while (0) + +/* Choose a NaN result from an operation on two semi-raw NaN + values. */ +#define _FP_CHOOSENAN_SEMIRAW(fs, wc, R, X, Y, OP) \ +do { \ + /* _FP_CHOOSENAN expects raw values, so shift as required. */ \ + _FP_FRAC_SRL_##wc(X, _FP_WORKBITS); \ + _FP_FRAC_SRL_##wc(Y, _FP_WORKBITS); \ + _FP_CHOOSENAN(fs, wc, R, X, Y, OP); \ + _FP_FRAC_SLL_##wc(R, _FP_WORKBITS); \ +} while (0) + +/* Test whether a biased exponent is normal (not zero or maximum). */ +#define _FP_EXP_NORMAL(fs, wc, X) (((X##_e + 1) & _FP_EXPMAX_##fs) > 1) + +/* Prepare to pack an fp value in semi-raw mode: the mantissa is + rounded and shifted right, with the rounding possibly increasing + the exponent (including changing a finite value to infinity). */ +#define _FP_PACK_SEMIRAW(fs, wc, X) \ +do { \ + _FP_ROUND(wc, X); \ + if (_FP_FRAC_HIGH_##fs(X) \ + & (_FP_OVERFLOW_##fs >> 1)) \ + { \ + _FP_FRAC_HIGH_##fs(X) &= ~(_FP_OVERFLOW_##fs >> 1); \ + X##_e++; \ + if (X##_e == _FP_EXPMAX_##fs) \ + _FP_OVERFLOW_SEMIRAW(fs, wc, X); \ + } \ + _FP_FRAC_SRL_##wc(X, _FP_WORKBITS); \ + if (!_FP_EXP_NORMAL(fs, wc, X) && !_FP_FRAC_ZEROP_##wc(X)) \ + { \ + if (X##_e == 0) \ + FP_SET_EXCEPTION(FP_EX_UNDERFLOW); \ + else \ + { \ + if (!_FP_KEEPNANFRACP) \ + { \ + _FP_FRAC_SET_##wc(X, _FP_NANFRAC_##fs); \ + X##_s = _FP_NANSIGN_##fs; \ + } \ + else \ + _FP_FRAC_HIGH_RAW_##fs(X) |= _FP_QNANBIT_##fs; \ + } \ + } \ +} while (0) + +/* + * Before packing the bits back into the native fp result, take care + * of such mundane things as rounding and overflow. Also, for some + * kinds of fp values, the original parts may not have been fully + * extracted -- but that is ok, we can regenerate them now. + */ + +#define _FP_PACK_CANONICAL(fs, wc, X) \ +do { \ + switch (X##_c) \ + { \ + case FP_CLS_NORMAL: \ + X##_e += _FP_EXPBIAS_##fs; \ + if (X##_e > 0) \ + { \ + _FP_ROUND(wc, X); \ + if (_FP_FRAC_OVERP_##wc(fs, X)) \ + { \ + _FP_FRAC_CLEAR_OVERP_##wc(fs, X); \ + X##_e++; \ + } \ + _FP_FRAC_SRL_##wc(X, _FP_WORKBITS); \ + if (X##_e >= _FP_EXPMAX_##fs) \ + { \ + /* overflow */ \ + switch (FP_ROUNDMODE) \ + { \ + case FP_RND_NEAREST: \ + X##_c = FP_CLS_INF; \ + break; \ + case FP_RND_PINF: \ + if (!X##_s) X##_c = FP_CLS_INF; \ + break; \ + case FP_RND_MINF: \ + if (X##_s) X##_c = FP_CLS_INF; \ + break; \ + } \ + if (X##_c == FP_CLS_INF) \ + { \ + /* Overflow to infinity */ \ + X##_e = _FP_EXPMAX_##fs; \ + _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \ + } \ + else \ + { \ + /* Overflow to maximum normal */ \ + X##_e = _FP_EXPMAX_##fs - 1; \ + _FP_FRAC_SET_##wc(X, _FP_MAXFRAC_##wc); \ + } \ + FP_SET_EXCEPTION(FP_EX_OVERFLOW); \ + FP_SET_EXCEPTION(FP_EX_INEXACT); \ + } \ + } \ + else \ + { \ + /* we've got a denormalized number */ \ + X##_e = -X##_e + 1; \ + if (X##_e <= _FP_WFRACBITS_##fs) \ + { \ + _FP_FRAC_SRS_##wc(X, X##_e, _FP_WFRACBITS_##fs); \ + _FP_ROUND(wc, X); \ + if (_FP_FRAC_HIGH_##fs(X) \ + & (_FP_OVERFLOW_##fs >> 1)) \ + { \ + X##_e = 1; \ + _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \ + } \ + else \ + { \ + X##_e = 0; \ + _FP_FRAC_SRL_##wc(X, _FP_WORKBITS); \ + FP_SET_EXCEPTION(FP_EX_UNDERFLOW); \ + } \ + } \ + else \ + { \ + /* underflow to zero */ \ + X##_e = 0; \ + if (!_FP_FRAC_ZEROP_##wc(X)) \ + { \ + _FP_FRAC_SET_##wc(X, _FP_MINFRAC_##wc); \ + _FP_ROUND(wc, X); \ + _FP_FRAC_LOW_##wc(X) >>= (_FP_WORKBITS); \ + } \ + FP_SET_EXCEPTION(FP_EX_UNDERFLOW); \ + } \ + } \ + break; \ + \ + case FP_CLS_ZERO: \ + X##_e = 0; \ + _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \ + break; \ + \ + case FP_CLS_INF: \ + X##_e = _FP_EXPMAX_##fs; \ + _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \ + break; \ + \ + case FP_CLS_NAN: \ + X##_e = _FP_EXPMAX_##fs; \ + if (!_FP_KEEPNANFRACP) \ + { \ + _FP_FRAC_SET_##wc(X, _FP_NANFRAC_##fs); \ + X##_s = _FP_NANSIGN_##fs; \ + } \ + else \ + _FP_FRAC_HIGH_RAW_##fs(X) |= _FP_QNANBIT_##fs; \ + break; \ + } \ +} while (0) + +/* This one accepts raw argument and not cooked, returns + * 1 if X is a signaling NaN. + */ +#define _FP_ISSIGNAN(fs, wc, X) \ +({ \ + int __ret = 0; \ + if (X##_e == _FP_EXPMAX_##fs) \ + { \ + if (!_FP_FRAC_ZEROP_##wc(X) \ + && !(_FP_FRAC_HIGH_RAW_##fs(X) & _FP_QNANBIT_##fs)) \ + __ret = 1; \ + } \ + __ret; \ +}) + + + + + +/* Addition on semi-raw values. */ +#define _FP_ADD_INTERNAL(fs, wc, R, X, Y, OP) \ +do { \ + if (X##_s == Y##_s) \ + { \ + /* Addition. */ \ + R##_s = X##_s; \ + int ediff = X##_e - Y##_e; \ + if (ediff > 0) \ + { \ + R##_e = X##_e; \ + if (Y##_e == 0) \ + { \ + /* Y is zero or denormalized. */ \ + if (_FP_FRAC_ZEROP_##wc(Y)) \ + { \ + _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, X); \ + _FP_FRAC_COPY_##wc(R, X); \ + goto add_done; \ + } \ + else \ + { \ + FP_SET_EXCEPTION(FP_EX_DENORM); \ + ediff--; \ + if (ediff == 0) \ + { \ + _FP_FRAC_ADD_##wc(R, X, Y); \ + goto add3; \ + } \ + if (X##_e == _FP_EXPMAX_##fs) \ + { \ + _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, X); \ + _FP_FRAC_COPY_##wc(R, X); \ + goto add_done; \ + } \ + goto add1; \ + } \ + } \ + else if (X##_e == _FP_EXPMAX_##fs) \ + { \ + /* X is NaN or Inf, Y is normal. */ \ + _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, X); \ + _FP_FRAC_COPY_##wc(R, X); \ + goto add_done; \ + } \ + \ + /* Insert implicit MSB of Y. */ \ + _FP_FRAC_HIGH_##fs(Y) |= _FP_IMPLBIT_SH_##fs; \ + \ + add1: \ + /* Shift the mantissa of Y to the right EDIFF steps; \ + remember to account later for the implicit MSB of X. */ \ + if (ediff <= _FP_WFRACBITS_##fs) \ + _FP_FRAC_SRS_##wc(Y, ediff, _FP_WFRACBITS_##fs); \ + else if (!_FP_FRAC_ZEROP_##wc(Y)) \ + _FP_FRAC_SET_##wc(Y, _FP_MINFRAC_##wc); \ + _FP_FRAC_ADD_##wc(R, X, Y); \ + } \ + else if (ediff < 0) \ + { \ + ediff = -ediff; \ + R##_e = Y##_e; \ + if (X##_e == 0) \ + { \ + /* X is zero or denormalized. */ \ + if (_FP_FRAC_ZEROP_##wc(X)) \ + { \ + _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, Y); \ + _FP_FRAC_COPY_##wc(R, Y); \ + goto add_done; \ + } \ + else \ + { \ + FP_SET_EXCEPTION(FP_EX_DENORM); \ + ediff--; \ + if (ediff == 0) \ + { \ + _FP_FRAC_ADD_##wc(R, Y, X); \ + goto add3; \ + } \ + if (Y##_e == _FP_EXPMAX_##fs) \ + { \ + _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, Y); \ + _FP_FRAC_COPY_##wc(R, Y); \ + goto add_done; \ + } \ + goto add2; \ + } \ + } \ + else if (Y##_e == _FP_EXPMAX_##fs) \ + { \ + /* Y is NaN or Inf, X is normal. */ \ + _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, Y); \ + _FP_FRAC_COPY_##wc(R, Y); \ + goto add_done; \ + } \ + \ + /* Insert implicit MSB of X. */ \ + _FP_FRAC_HIGH_##fs(X) |= _FP_IMPLBIT_SH_##fs; \ + \ + add2: \ + /* Shift the mantissa of X to the right EDIFF steps; \ + remember to account later for the implicit MSB of Y. */ \ + if (ediff <= _FP_WFRACBITS_##fs) \ + _FP_FRAC_SRS_##wc(X, ediff, _FP_WFRACBITS_##fs); \ + else if (!_FP_FRAC_ZEROP_##wc(X)) \ + _FP_FRAC_SET_##wc(X, _FP_MINFRAC_##wc); \ + _FP_FRAC_ADD_##wc(R, Y, X); \ + } \ + else \ + { \ + /* ediff == 0. */ \ + if (!_FP_EXP_NORMAL(fs, wc, X)) \ + { \ + if (X##_e == 0) \ + { \ + /* X and Y are zero or denormalized. */ \ + R##_e = 0; \ + if (_FP_FRAC_ZEROP_##wc(X)) \ + { \ + if (!_FP_FRAC_ZEROP_##wc(Y)) \ + FP_SET_EXCEPTION(FP_EX_DENORM); \ + _FP_FRAC_COPY_##wc(R, Y); \ + goto add_done; \ + } \ + else if (_FP_FRAC_ZEROP_##wc(Y)) \ + { \ + FP_SET_EXCEPTION(FP_EX_DENORM); \ + _FP_FRAC_COPY_##wc(R, X); \ + goto add_done; \ + } \ + else \ + { \ + FP_SET_EXCEPTION(FP_EX_DENORM); \ + _FP_FRAC_ADD_##wc(R, X, Y); \ + if (_FP_FRAC_HIGH_##fs(R) & _FP_IMPLBIT_SH_##fs) \ + { \ + /* Normalized result. */ \ + _FP_FRAC_HIGH_##fs(R) \ + &= ~(_FP_W_TYPE)_FP_IMPLBIT_SH_##fs; \ + R##_e = 1; \ + } \ + goto add_done; \ + } \ + } \ + else \ + { \ + /* X and Y are NaN or Inf. */ \ + _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, X); \ + _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, Y); \ + R##_e = _FP_EXPMAX_##fs; \ + if (_FP_FRAC_ZEROP_##wc(X)) \ + _FP_FRAC_COPY_##wc(R, Y); \ + else if (_FP_FRAC_ZEROP_##wc(Y)) \ + _FP_FRAC_COPY_##wc(R, X); \ + else \ + _FP_CHOOSENAN_SEMIRAW(fs, wc, R, X, Y, OP); \ + goto add_done; \ + } \ + } \ + /* The exponents of X and Y, both normal, are equal. The \ + implicit MSBs will always add to increase the \ + exponent. */ \ + _FP_FRAC_ADD_##wc(R, X, Y); \ + R##_e = X##_e + 1; \ + _FP_FRAC_SRS_##wc(R, 1, _FP_WFRACBITS_##fs); \ + if (R##_e == _FP_EXPMAX_##fs) \ + /* Overflow to infinity (depending on rounding mode). */ \ + _FP_OVERFLOW_SEMIRAW(fs, wc, R); \ + goto add_done; \ + } \ + add3: \ + if (_FP_FRAC_HIGH_##fs(R) & _FP_IMPLBIT_SH_##fs) \ + { \ + /* Overflow. */ \ + _FP_FRAC_HIGH_##fs(R) &= ~(_FP_W_TYPE)_FP_IMPLBIT_SH_##fs; \ + R##_e++; \ + _FP_FRAC_SRS_##wc(R, 1, _FP_WFRACBITS_##fs); \ + if (R##_e == _FP_EXPMAX_##fs) \ + /* Overflow to infinity (depending on rounding mode). */ \ + _FP_OVERFLOW_SEMIRAW(fs, wc, R); \ + } \ + add_done: ; \ + } \ + else \ + { \ + /* Subtraction. */ \ + int ediff = X##_e - Y##_e; \ + if (ediff > 0) \ + { \ + R##_e = X##_e; \ + R##_s = X##_s; \ + if (Y##_e == 0) \ + { \ + /* Y is zero or denormalized. */ \ + if (_FP_FRAC_ZEROP_##wc(Y)) \ + { \ + _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, X); \ + _FP_FRAC_COPY_##wc(R, X); \ + goto sub_done; \ + } \ + else \ + { \ + FP_SET_EXCEPTION(FP_EX_DENORM); \ + ediff--; \ + if (ediff == 0) \ + { \ + _FP_FRAC_SUB_##wc(R, X, Y); \ + goto sub3; \ + } \ + if (X##_e == _FP_EXPMAX_##fs) \ + { \ + _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, X); \ + _FP_FRAC_COPY_##wc(R, X); \ + goto sub_done; \ + } \ + goto sub1; \ + } \ + } \ + else if (X##_e == _FP_EXPMAX_##fs) \ + { \ + /* X is NaN or Inf, Y is normal. */ \ + _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, X); \ + _FP_FRAC_COPY_##wc(R, X); \ + goto sub_done; \ + } \ + \ + /* Insert implicit MSB of Y. */ \ + _FP_FRAC_HIGH_##fs(Y) |= _FP_IMPLBIT_SH_##fs; \ + \ + sub1: \ + /* Shift the mantissa of Y to the right EDIFF steps; \ + remember to account later for the implicit MSB of X. */ \ + if (ediff <= _FP_WFRACBITS_##fs) \ + _FP_FRAC_SRS_##wc(Y, ediff, _FP_WFRACBITS_##fs); \ + else if (!_FP_FRAC_ZEROP_##wc(Y)) \ + _FP_FRAC_SET_##wc(Y, _FP_MINFRAC_##wc); \ + _FP_FRAC_SUB_##wc(R, X, Y); \ + } \ + else if (ediff < 0) \ + { \ + ediff = -ediff; \ + R##_e = Y##_e; \ + R##_s = Y##_s; \ + if (X##_e == 0) \ + { \ + /* X is zero or denormalized. */ \ + if (_FP_FRAC_ZEROP_##wc(X)) \ + { \ + _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, Y); \ + _FP_FRAC_COPY_##wc(R, Y); \ + goto sub_done; \ + } \ + else \ + { \ + FP_SET_EXCEPTION(FP_EX_DENORM); \ + ediff--; \ + if (ediff == 0) \ + { \ + _FP_FRAC_SUB_##wc(R, Y, X); \ + goto sub3; \ + } \ + if (Y##_e == _FP_EXPMAX_##fs) \ + { \ + _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, Y); \ + _FP_FRAC_COPY_##wc(R, Y); \ + goto sub_done; \ + } \ + goto sub2; \ + } \ + } \ + else if (Y##_e == _FP_EXPMAX_##fs) \ + { \ + /* Y is NaN or Inf, X is normal. */ \ + _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, Y); \ + _FP_FRAC_COPY_##wc(R, Y); \ + goto sub_done; \ + } \ + \ + /* Insert implicit MSB of X. */ \ + _FP_FRAC_HIGH_##fs(X) |= _FP_IMPLBIT_SH_##fs; \ + \ + sub2: \ + /* Shift the mantissa of X to the right EDIFF steps; \ + remember to account later for the implicit MSB of Y. */ \ + if (ediff <= _FP_WFRACBITS_##fs) \ + _FP_FRAC_SRS_##wc(X, ediff, _FP_WFRACBITS_##fs); \ + else if (!_FP_FRAC_ZEROP_##wc(X)) \ + _FP_FRAC_SET_##wc(X, _FP_MINFRAC_##wc); \ + _FP_FRAC_SUB_##wc(R, Y, X); \ + } \ + else \ + { \ + /* ediff == 0. */ \ + if (!_FP_EXP_NORMAL(fs, wc, X)) \ + { \ + if (X##_e == 0) \ + { \ + /* X and Y are zero or denormalized. */ \ + R##_e = 0; \ + if (_FP_FRAC_ZEROP_##wc(X)) \ + { \ + _FP_FRAC_COPY_##wc(R, Y); \ + if (_FP_FRAC_ZEROP_##wc(Y)) \ + R##_s = (FP_ROUNDMODE == FP_RND_MINF); \ + else \ + { \ + FP_SET_EXCEPTION(FP_EX_DENORM); \ + R##_s = Y##_s; \ + } \ + goto sub_done; \ + } \ + else if (_FP_FRAC_ZEROP_##wc(Y)) \ + { \ + FP_SET_EXCEPTION(FP_EX_DENORM); \ + _FP_FRAC_COPY_##wc(R, X); \ + R##_s = X##_s; \ + goto sub_done; \ + } \ + else \ + { \ + FP_SET_EXCEPTION(FP_EX_DENORM); \ + _FP_FRAC_SUB_##wc(R, X, Y); \ + R##_s = X##_s; \ + if (_FP_FRAC_HIGH_##fs(R) & _FP_IMPLBIT_SH_##fs) \ + { \ + /* |X| < |Y|, negate result. */ \ + _FP_FRAC_SUB_##wc(R, Y, X); \ + R##_s = Y##_s; \ + } \ + else if (_FP_FRAC_ZEROP_##wc(R)) \ + R##_s = (FP_ROUNDMODE == FP_RND_MINF); \ + goto sub_done; \ + } \ + } \ + else \ + { \ + /* X and Y are NaN or Inf, of opposite signs. */ \ + _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, X); \ + _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, Y); \ + R##_e = _FP_EXPMAX_##fs; \ + if (_FP_FRAC_ZEROP_##wc(X)) \ + { \ + if (_FP_FRAC_ZEROP_##wc(Y)) \ + { \ + /* Inf - Inf. */ \ + R##_s = _FP_NANSIGN_##fs; \ + _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs); \ + _FP_FRAC_SLL_##wc(R, _FP_WORKBITS); \ + FP_SET_EXCEPTION(FP_EX_INVALID); \ + } \ + else \ + { \ + /* Inf - NaN. */ \ + R##_s = Y##_s; \ + _FP_FRAC_COPY_##wc(R, Y); \ + } \ + } \ + else \ + { \ + if (_FP_FRAC_ZEROP_##wc(Y)) \ + { \ + /* NaN - Inf. */ \ + R##_s = X##_s; \ + _FP_FRAC_COPY_##wc(R, X); \ + } \ + else \ + { \ + /* NaN - NaN. */ \ + _FP_CHOOSENAN_SEMIRAW(fs, wc, R, X, Y, OP); \ + } \ + } \ + goto sub_done; \ + } \ + } \ + /* The exponents of X and Y, both normal, are equal. The \ + implicit MSBs cancel. */ \ + R##_e = X##_e; \ + _FP_FRAC_SUB_##wc(R, X, Y); \ + R##_s = X##_s; \ + if (_FP_FRAC_HIGH_##fs(R) & _FP_IMPLBIT_SH_##fs) \ + { \ + /* |X| < |Y|, negate result. */ \ + _FP_FRAC_SUB_##wc(R, Y, X); \ + R##_s = Y##_s; \ + } \ + else if (_FP_FRAC_ZEROP_##wc(R)) \ + { \ + R##_e = 0; \ + R##_s = (FP_ROUNDMODE == FP_RND_MINF); \ + goto sub_done; \ + } \ + goto norm; \ + } \ + sub3: \ + if (_FP_FRAC_HIGH_##fs(R) & _FP_IMPLBIT_SH_##fs) \ + { \ + int diff; \ + /* Carry into most significant bit of larger one of X and Y, \ + canceling it; renormalize. */ \ + _FP_FRAC_HIGH_##fs(R) &= _FP_IMPLBIT_SH_##fs - 1; \ + norm: \ + _FP_FRAC_CLZ_##wc(diff, R); \ + diff -= _FP_WFRACXBITS_##fs; \ + _FP_FRAC_SLL_##wc(R, diff); \ + if (R##_e <= diff) \ + { \ + /* R is denormalized. */ \ + diff = diff - R##_e + 1; \ + _FP_FRAC_SRS_##wc(R, diff, _FP_WFRACBITS_##fs); \ + R##_e = 0; \ + } \ + else \ + { \ + R##_e -= diff; \ + _FP_FRAC_HIGH_##fs(R) &= ~(_FP_W_TYPE)_FP_IMPLBIT_SH_##fs; \ + } \ + } \ + sub_done: ; \ + } \ +} while (0) + +#define _FP_ADD(fs, wc, R, X, Y) _FP_ADD_INTERNAL(fs, wc, R, X, Y, '+') +#define _FP_SUB(fs, wc, R, X, Y) \ + do { \ + if (!(Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(Y))) Y##_s ^= 1; \ + _FP_ADD_INTERNAL(fs, wc, R, X, Y, '-'); \ + } while (0) + + +/* + * Main negation routine. FIXME -- when we care about setting exception + * bits reliably, this will not do. We should examine all of the fp classes. + */ + +#define _FP_NEG(fs, wc, R, X) \ + do { \ + _FP_FRAC_COPY_##wc(R, X); \ + R##_c = X##_c; \ + R##_e = X##_e; \ + R##_s = 1 ^ X##_s; \ + } while (0) + + +/* + * Main multiplication routine. The input values should be cooked. + */ + +#define _FP_MUL(fs, wc, R, X, Y) \ +do { \ + R##_s = X##_s ^ Y##_s; \ + switch (_FP_CLS_COMBINE(X##_c, Y##_c)) \ + { \ + case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NORMAL): \ + R##_c = FP_CLS_NORMAL; \ + R##_e = X##_e + Y##_e + 1; \ + \ + _FP_MUL_MEAT_##fs(R,X,Y); \ + \ + if (_FP_FRAC_OVERP_##wc(fs, R)) \ + _FP_FRAC_SRS_##wc(R, 1, _FP_WFRACBITS_##fs); \ + else \ + R##_e--; \ + break; \ + \ + case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NAN): \ + _FP_CHOOSENAN(fs, wc, R, X, Y, '*'); \ + break; \ + \ + case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NORMAL): \ + case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_INF): \ + case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_ZERO): \ + R##_s = X##_s; \ + \ + case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_INF): \ + case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NORMAL): \ + case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NORMAL): \ + case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_ZERO): \ + _FP_FRAC_COPY_##wc(R, X); \ + R##_c = X##_c; \ + break; \ + \ + case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NAN): \ + case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NAN): \ + case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NAN): \ + R##_s = Y##_s; \ + \ + case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_INF): \ + case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO): \ + _FP_FRAC_COPY_##wc(R, Y); \ + R##_c = Y##_c; \ + break; \ + \ + case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_ZERO): \ + case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_INF): \ + R##_s = _FP_NANSIGN_##fs; \ + R##_c = FP_CLS_NAN; \ + _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs); \ + FP_SET_EXCEPTION(FP_EX_INVALID); \ + break; \ + \ + default: \ + abort(); \ + } \ +} while (0) + + +/* + * Main division routine. The input values should be cooked. + */ + +#define _FP_DIV(fs, wc, R, X, Y) \ +do { \ + R##_s = X##_s ^ Y##_s; \ + switch (_FP_CLS_COMBINE(X##_c, Y##_c)) \ + { \ + case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NORMAL): \ + R##_c = FP_CLS_NORMAL; \ + R##_e = X##_e - Y##_e; \ + \ + _FP_DIV_MEAT_##fs(R,X,Y); \ + break; \ + \ + case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NAN): \ + _FP_CHOOSENAN(fs, wc, R, X, Y, '/'); \ + break; \ + \ + case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NORMAL): \ + case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_INF): \ + case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_ZERO): \ + R##_s = X##_s; \ + _FP_FRAC_COPY_##wc(R, X); \ + R##_c = X##_c; \ + break; \ + \ + case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NAN): \ + case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NAN): \ + case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NAN): \ + R##_s = Y##_s; \ + _FP_FRAC_COPY_##wc(R, Y); \ + R##_c = Y##_c; \ + break; \ + \ + case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_INF): \ + case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_INF): \ + case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NORMAL): \ + R##_c = FP_CLS_ZERO; \ + break; \ + \ + case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO): \ + FP_SET_EXCEPTION(FP_EX_DIVZERO); \ + case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_ZERO): \ + case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NORMAL): \ + R##_c = FP_CLS_INF; \ + break; \ + \ + case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_INF): \ + case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_ZERO): \ + R##_s = _FP_NANSIGN_##fs; \ + R##_c = FP_CLS_NAN; \ + _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs); \ + FP_SET_EXCEPTION(FP_EX_INVALID); \ + break; \ + \ + default: \ + abort(); \ + } \ +} while (0) + + +/* + * Main differential comparison routine. The inputs should be raw not + * cooked. The return is -1,0,1 for normal values, 2 otherwise. + */ + +#define _FP_CMP(fs, wc, ret, X, Y, un) \ + do { \ + /* NANs are unordered */ \ + if ((X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(X)) \ + || (Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(Y))) \ + { \ + ret = un; \ + } \ + else \ + { \ + int __is_zero_x; \ + int __is_zero_y; \ + \ + __is_zero_x = (!X##_e && _FP_FRAC_ZEROP_##wc(X)) ? 1 : 0; \ + __is_zero_y = (!Y##_e && _FP_FRAC_ZEROP_##wc(Y)) ? 1 : 0; \ + \ + if (__is_zero_x && __is_zero_y) \ + ret = 0; \ + else if (__is_zero_x) \ + ret = Y##_s ? 1 : -1; \ + else if (__is_zero_y) \ + ret = X##_s ? -1 : 1; \ + else if (X##_s != Y##_s) \ + ret = X##_s ? -1 : 1; \ + else if (X##_e > Y##_e) \ + ret = X##_s ? -1 : 1; \ + else if (X##_e < Y##_e) \ + ret = X##_s ? 1 : -1; \ + else if (_FP_FRAC_GT_##wc(X, Y)) \ + ret = X##_s ? -1 : 1; \ + else if (_FP_FRAC_GT_##wc(Y, X)) \ + ret = X##_s ? 1 : -1; \ + else \ + ret = 0; \ + } \ + } while (0) + + +/* Simplification for strict equality. */ + +#define _FP_CMP_EQ(fs, wc, ret, X, Y) \ + do { \ + /* NANs are unordered */ \ + if ((X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(X)) \ + || (Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(Y))) \ + { \ + ret = 1; \ + } \ + else \ + { \ + ret = !(X##_e == Y##_e \ + && _FP_FRAC_EQ_##wc(X, Y) \ + && (X##_s == Y##_s || (!X##_e && _FP_FRAC_ZEROP_##wc(X)))); \ + } \ + } while (0) + +/* Version to test unordered. */ + +#define _FP_CMP_UNORD(fs, wc, ret, X, Y) \ + do { \ + ret = ((X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(X)) \ + || (Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(Y))); \ + } while (0) + +/* + * Main square root routine. The input value should be cooked. + */ + +#define _FP_SQRT(fs, wc, R, X) \ +do { \ + _FP_FRAC_DECL_##wc(T); _FP_FRAC_DECL_##wc(S); \ + _FP_W_TYPE q; \ + switch (X##_c) \ + { \ + case FP_CLS_NAN: \ + _FP_FRAC_COPY_##wc(R, X); \ + R##_s = X##_s; \ + R##_c = FP_CLS_NAN; \ + break; \ + case FP_CLS_INF: \ + if (X##_s) \ + { \ + R##_s = _FP_NANSIGN_##fs; \ + R##_c = FP_CLS_NAN; /* NAN */ \ + _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs); \ + FP_SET_EXCEPTION(FP_EX_INVALID); \ + } \ + else \ + { \ + R##_s = 0; \ + R##_c = FP_CLS_INF; /* sqrt(+inf) = +inf */ \ + } \ + break; \ + case FP_CLS_ZERO: \ + R##_s = X##_s; \ + R##_c = FP_CLS_ZERO; /* sqrt(+-0) = +-0 */ \ + break; \ + case FP_CLS_NORMAL: \ + R##_s = 0; \ + if (X##_s) \ + { \ + R##_c = FP_CLS_NAN; /* sNAN */ \ + R##_s = _FP_NANSIGN_##fs; \ + _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs); \ + FP_SET_EXCEPTION(FP_EX_INVALID); \ + break; \ + } \ + R##_c = FP_CLS_NORMAL; \ + if (X##_e & 1) \ + _FP_FRAC_SLL_##wc(X, 1); \ + R##_e = X##_e >> 1; \ + _FP_FRAC_SET_##wc(S, _FP_ZEROFRAC_##wc); \ + _FP_FRAC_SET_##wc(R, _FP_ZEROFRAC_##wc); \ + q = _FP_OVERFLOW_##fs >> 1; \ + _FP_SQRT_MEAT_##wc(R, S, T, X, q); \ + } \ + } while (0) + +/* + * Convert from FP to integer. Input is raw. + */ + +/* RSIGNED can have following values: + * 0: the number is required to be 0..(2^rsize)-1, if not, NV is set plus + * the result is either 0 or (2^rsize)-1 depending on the sign in such + * case. + * 1: the number is required to be -(2^(rsize-1))..(2^(rsize-1))-1, if not, + * NV is set plus the result is either -(2^(rsize-1)) or (2^(rsize-1))-1 + * depending on the sign in such case. + * -1: the number is required to be -(2^(rsize-1))..(2^rsize)-1, if not, NV is + * set plus the result is either -(2^(rsize-1)) or (2^(rsize-1))-1 + * depending on the sign in such case. + */ +#define _FP_TO_INT(fs, wc, r, X, rsize, rsigned) \ +do { \ + if (X##_e < _FP_EXPBIAS_##fs) \ + { \ + r = 0; \ + if (X##_e == 0) \ + { \ + if (!_FP_FRAC_ZEROP_##wc(X)) \ + { \ + FP_SET_EXCEPTION(FP_EX_INEXACT); \ + FP_SET_EXCEPTION(FP_EX_DENORM); \ + } \ + } \ + else \ + FP_SET_EXCEPTION(FP_EX_INEXACT); \ + } \ + else if (X##_e >= _FP_EXPBIAS_##fs + rsize - (rsigned > 0 || X##_s) \ + || (!rsigned && X##_s)) \ + { \ + /* Overflow or converting to the most negative integer. */ \ + if (rsigned) \ + { \ + r = 1; \ + r <<= rsize - 1; \ + r -= 1 - X##_s; \ + } else { \ + r = 0; \ + if (X##_s) \ + r = ~r; \ + } \ + \ + if (rsigned && X##_s && X##_e == _FP_EXPBIAS_##fs + rsize - 1) \ + { \ + /* Possibly converting to most negative integer; check the \ + mantissa. */ \ + int inexact = 0; \ + (void)((_FP_FRACBITS_##fs > rsize) \ + ? ({ _FP_FRAC_SRST_##wc(X, inexact, \ + _FP_FRACBITS_##fs - rsize, \ + _FP_FRACBITS_##fs); 0; }) \ + : 0); \ + if (!_FP_FRAC_ZEROP_##wc(X)) \ + FP_SET_EXCEPTION(FP_EX_INVALID); \ + else if (inexact) \ + FP_SET_EXCEPTION(FP_EX_INEXACT); \ + } \ + else \ + FP_SET_EXCEPTION(FP_EX_INVALID); \ + } \ + else \ + { \ + _FP_FRAC_HIGH_RAW_##fs(X) |= _FP_IMPLBIT_##fs; \ + if (X##_e >= _FP_EXPBIAS_##fs + _FP_FRACBITS_##fs - 1) \ + { \ + _FP_FRAC_ASSEMBLE_##wc(r, X, rsize); \ + r <<= X##_e - _FP_EXPBIAS_##fs - _FP_FRACBITS_##fs + 1; \ + } \ + else \ + { \ + int inexact; \ + _FP_FRAC_SRST_##wc(X, inexact, \ + (_FP_FRACBITS_##fs + _FP_EXPBIAS_##fs - 1 \ + - X##_e), \ + _FP_FRACBITS_##fs); \ + if (inexact) \ + FP_SET_EXCEPTION(FP_EX_INEXACT); \ + _FP_FRAC_ASSEMBLE_##wc(r, X, rsize); \ + } \ + if (rsigned && X##_s) \ + r = -r; \ + } \ +} while (0) + +/* Convert integer to fp. Output is raw. RTYPE is unsigned even if + input is signed. */ +#define _FP_FROM_INT(fs, wc, X, r, rsize, rtype) \ + do { \ + if (r) \ + { \ + rtype ur_; \ + \ + if ((X##_s = (r < 0))) \ + r = -(rtype)r; \ + \ + ur_ = (rtype) r; \ + (void)((rsize <= _FP_W_TYPE_SIZE) \ + ? ({ \ + int lz_; \ + __FP_CLZ(lz_, (_FP_W_TYPE)ur_); \ + X##_e = _FP_EXPBIAS_##fs + _FP_W_TYPE_SIZE - 1 - lz_; \ + }) \ + : ((rsize <= 2 * _FP_W_TYPE_SIZE) \ + ? ({ \ + int lz_; \ + __FP_CLZ_2(lz_, (_FP_W_TYPE)(ur_ >> _FP_W_TYPE_SIZE), \ + (_FP_W_TYPE)ur_); \ + X##_e = (_FP_EXPBIAS_##fs + 2 * _FP_W_TYPE_SIZE - 1 \ + - lz_); \ + }) \ + : (abort(), 0))); \ + \ + if (rsize - 1 + _FP_EXPBIAS_##fs >= _FP_EXPMAX_##fs \ + && X##_e >= _FP_EXPMAX_##fs) \ + { \ + /* Exponent too big; overflow to infinity. (May also \ + happen after rounding below.) */ \ + _FP_OVERFLOW_SEMIRAW(fs, wc, X); \ + goto pack_semiraw; \ + } \ + \ + if (rsize <= _FP_FRACBITS_##fs \ + || X##_e < _FP_EXPBIAS_##fs + _FP_FRACBITS_##fs) \ + { \ + /* Exactly representable; shift left. */ \ + _FP_FRAC_DISASSEMBLE_##wc(X, ur_, rsize); \ + _FP_FRAC_SLL_##wc(X, (_FP_EXPBIAS_##fs \ + + _FP_FRACBITS_##fs - 1 - X##_e)); \ + } \ + else \ + { \ + /* More bits in integer than in floating type; need to \ + round. */ \ + if (_FP_EXPBIAS_##fs + _FP_WFRACBITS_##fs - 1 < X##_e) \ + ur_ = ((ur_ >> (X##_e - _FP_EXPBIAS_##fs \ + - _FP_WFRACBITS_##fs + 1)) \ + | ((ur_ << (rsize - (X##_e - _FP_EXPBIAS_##fs \ + - _FP_WFRACBITS_##fs + 1))) \ + != 0)); \ + _FP_FRAC_DISASSEMBLE_##wc(X, ur_, rsize); \ + if ((_FP_EXPBIAS_##fs + _FP_WFRACBITS_##fs - 1 - X##_e) > 0) \ + _FP_FRAC_SLL_##wc(X, (_FP_EXPBIAS_##fs \ + + _FP_WFRACBITS_##fs - 1 - X##_e)); \ + _FP_FRAC_HIGH_##fs(X) &= ~(_FP_W_TYPE)_FP_IMPLBIT_SH_##fs; \ + pack_semiraw: \ + _FP_PACK_SEMIRAW(fs, wc, X); \ + } \ + } \ + else \ + { \ + X##_s = 0; \ + X##_e = 0; \ + _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \ + } \ + } while (0) + + +/* Extend from a narrower floating-point format to a wider one. Input + and output are raw. */ +#define FP_EXTEND(dfs,sfs,dwc,swc,D,S) \ +do { \ + if (_FP_FRACBITS_##dfs < _FP_FRACBITS_##sfs \ + || (_FP_EXPMAX_##dfs - _FP_EXPBIAS_##dfs \ + < _FP_EXPMAX_##sfs - _FP_EXPBIAS_##sfs) \ + || (_FP_EXPBIAS_##dfs < _FP_EXPBIAS_##sfs + _FP_FRACBITS_##sfs - 1 \ + && _FP_EXPBIAS_##dfs != _FP_EXPBIAS_##sfs)) \ + abort(); \ + D##_s = S##_s; \ + _FP_FRAC_COPY_##dwc##_##swc(D, S); \ + if (_FP_EXP_NORMAL(sfs, swc, S)) \ + { \ + D##_e = S##_e + _FP_EXPBIAS_##dfs - _FP_EXPBIAS_##sfs; \ + _FP_FRAC_SLL_##dwc(D, (_FP_FRACBITS_##dfs - _FP_FRACBITS_##sfs)); \ + } \ + else \ + { \ + if (S##_e == 0) \ + { \ + if (_FP_FRAC_ZEROP_##swc(S)) \ + D##_e = 0; \ + else if (_FP_EXPBIAS_##dfs \ + < _FP_EXPBIAS_##sfs + _FP_FRACBITS_##sfs - 1) \ + { \ + FP_SET_EXCEPTION(FP_EX_DENORM); \ + _FP_FRAC_SLL_##dwc(D, (_FP_FRACBITS_##dfs \ + - _FP_FRACBITS_##sfs)); \ + D##_e = 0; \ + } \ + else \ + { \ + int _lz; \ + FP_SET_EXCEPTION(FP_EX_DENORM); \ + _FP_FRAC_CLZ_##swc(_lz, S); \ + _FP_FRAC_SLL_##dwc(D, \ + _lz + _FP_FRACBITS_##dfs \ + - _FP_FRACTBITS_##sfs); \ + D##_e = (_FP_EXPBIAS_##dfs - _FP_EXPBIAS_##sfs + 1 \ + + _FP_FRACXBITS_##sfs - _lz); \ + } \ + } \ + else \ + { \ + D##_e = _FP_EXPMAX_##dfs; \ + if (!_FP_FRAC_ZEROP_##swc(S)) \ + { \ + if (!(_FP_FRAC_HIGH_RAW_##sfs(S) & _FP_QNANBIT_##sfs)) \ + FP_SET_EXCEPTION(FP_EX_INVALID); \ + _FP_FRAC_SLL_##dwc(D, (_FP_FRACBITS_##dfs \ + - _FP_FRACBITS_##sfs)); \ + } \ + } \ + } \ +} while (0) + +/* Truncate from a wider floating-point format to a narrower one. + Input and output are semi-raw. */ +#define FP_TRUNC(dfs,sfs,dwc,swc,D,S) \ +do { \ + if (_FP_FRACBITS_##sfs < _FP_FRACBITS_##dfs \ + || (_FP_EXPBIAS_##sfs < _FP_EXPBIAS_##dfs + _FP_FRACBITS_##dfs - 1 \ + && _FP_EXPBIAS_##sfs != _FP_EXPBIAS_##dfs)) \ + abort(); \ + D##_s = S##_s; \ + if (_FP_EXP_NORMAL(sfs, swc, S)) \ + { \ + D##_e = S##_e + _FP_EXPBIAS_##dfs - _FP_EXPBIAS_##sfs; \ + if (D##_e >= _FP_EXPMAX_##dfs) \ + _FP_OVERFLOW_SEMIRAW(dfs, dwc, D); \ + else \ + { \ + if (D##_e <= 0) \ + { \ + if (D##_e < 1 - _FP_FRACBITS_##dfs) \ + { \ + _FP_FRAC_SET_##swc(S, _FP_ZEROFRAC_##swc); \ + _FP_FRAC_LOW_##swc(S) |= 1; \ + } \ + else \ + { \ + _FP_FRAC_HIGH_##sfs(S) |= _FP_IMPLBIT_SH_##sfs; \ + _FP_FRAC_SRS_##swc(S, (_FP_WFRACBITS_##sfs \ + - _FP_WFRACBITS_##dfs + 1 - D##_e), \ + _FP_WFRACBITS_##sfs); \ + } \ + D##_e = 0; \ + } \ + else \ + _FP_FRAC_SRS_##swc(S, (_FP_WFRACBITS_##sfs \ + - _FP_WFRACBITS_##dfs), \ + _FP_WFRACBITS_##sfs); \ + _FP_FRAC_COPY_##dwc##_##swc(D, S); \ + } \ + } \ + else \ + { \ + if (S##_e == 0) \ + { \ + D##_e = 0; \ + if (_FP_FRAC_ZEROP_##swc(S)) \ + _FP_FRAC_SET_##dwc(D, _FP_ZEROFRAC_##dwc); \ + else \ + { \ + FP_SET_EXCEPTION(FP_EX_DENORM); \ + if (_FP_EXPBIAS_##sfs \ + < _FP_EXPBIAS_##dfs + _FP_FRACBITS_##dfs - 1) \ + { \ + _FP_FRAC_SRS_##swc(S, (_FP_WFRACBITS_##sfs \ + - _FP_WFRACBITS_##dfs), \ + _FP_WFRACBITS_##sfs); \ + _FP_FRAC_COPY_##dwc##_##swc(D, S); \ + } \ + else \ + { \ + _FP_FRAC_SET_##dwc(D, _FP_ZEROFRAC_##dwc); \ + _FP_FRAC_LOW_##dwc(D) |= 1; \ + } \ + } \ + } \ + else \ + { \ + D##_e = _FP_EXPMAX_##dfs; \ + if (_FP_FRAC_ZEROP_##swc(S)) \ + _FP_FRAC_SET_##dwc(D, _FP_ZEROFRAC_##dwc); \ + else \ + { \ + _FP_CHECK_SIGNAN_SEMIRAW(sfs, swc, S); \ + _FP_FRAC_SRL_##swc(S, (_FP_WFRACBITS_##sfs \ + - _FP_WFRACBITS_##dfs)); \ + _FP_FRAC_COPY_##dwc##_##swc(D, S); \ + /* Semi-raw NaN must have all workbits cleared. */ \ + _FP_FRAC_LOW_##dwc(D) \ + &= ~(_FP_W_TYPE) ((1 << _FP_WORKBITS) - 1); \ + _FP_FRAC_HIGH_##dfs(D) |= _FP_QNANBIT_SH_##dfs; \ + } \ + } \ + } \ +} while (0) + +/* + * Helper primitives. + */ + +/* Count leading zeros in a word. */ + +#ifndef __FP_CLZ +/* GCC 3.4 and later provide the builtins for us. */ +#define __FP_CLZ(r, x) \ + do { \ + if (sizeof (_FP_W_TYPE) == sizeof (unsigned int)) \ + r = __builtin_clz (x); \ + else if (sizeof (_FP_W_TYPE) == sizeof (unsigned long)) \ + r = __builtin_clzl (x); \ + else if (sizeof (_FP_W_TYPE) == sizeof (unsigned long long)) \ + r = __builtin_clzll (x); \ + else \ + abort (); \ + } while (0) +#endif /* ndef __FP_CLZ */ + +#define _FP_DIV_HELP_imm(q, r, n, d) \ + do { \ + q = n / d, r = n % d; \ + } while (0) + + +/* A restoring bit-by-bit division primitive. */ + +#define _FP_DIV_MEAT_N_loop(fs, wc, R, X, Y) \ + do { \ + int count = _FP_WFRACBITS_##fs; \ + _FP_FRAC_DECL_##wc (u); \ + _FP_FRAC_DECL_##wc (v); \ + _FP_FRAC_COPY_##wc (u, X); \ + _FP_FRAC_COPY_##wc (v, Y); \ + _FP_FRAC_SET_##wc (R, _FP_ZEROFRAC_##wc); \ + /* Normalize U and V. */ \ + _FP_FRAC_SLL_##wc (u, _FP_WFRACXBITS_##fs); \ + _FP_FRAC_SLL_##wc (v, _FP_WFRACXBITS_##fs); \ + /* First round. Since the operands are normalized, either the \ + first or second bit will be set in the fraction. Produce a \ + normalized result by checking which and adjusting the loop \ + count and exponent accordingly. */ \ + if (_FP_FRAC_GE_1 (u, v)) \ + { \ + _FP_FRAC_SUB_##wc (u, u, v); \ + _FP_FRAC_LOW_##wc (R) |= 1; \ + count--; \ + } \ + else \ + R##_e--; \ + /* Subsequent rounds. */ \ + do { \ + int msb = (_FP_WS_TYPE) _FP_FRAC_HIGH_##wc (u) < 0; \ + _FP_FRAC_SLL_##wc (u, 1); \ + _FP_FRAC_SLL_##wc (R, 1); \ + if (msb || _FP_FRAC_GE_1 (u, v)) \ + { \ + _FP_FRAC_SUB_##wc (u, u, v); \ + _FP_FRAC_LOW_##wc (R) |= 1; \ + } \ + } while (--count > 0); \ + /* If there's anything left in U, the result is inexact. */ \ + _FP_FRAC_LOW_##wc (R) |= !_FP_FRAC_ZEROP_##wc (u); \ + } while (0) + +#define _FP_DIV_MEAT_1_loop(fs, R, X, Y) _FP_DIV_MEAT_N_loop (fs, 1, R, X, Y) +#define _FP_DIV_MEAT_2_loop(fs, R, X, Y) _FP_DIV_MEAT_N_loop (fs, 2, R, X, Y) +#define _FP_DIV_MEAT_4_loop(fs, R, X, Y) _FP_DIV_MEAT_N_loop (fs, 4, R, X, Y) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_add.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_add.c new file mode 100644 index 00000000..987c7255 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_add.c @@ -0,0 +1,39 @@ +/* Software floating-point emulation. + Return a + b + Copyright (C) 1997,1999,2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson (rth@cygnus.com) and + Jakub Jelinek (jj@ultra.linux.cz). + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "soft-fp.h" +#include "quad.h" + +long double _Q_add(const long double a, const long double b) +{ + FP_DECL_EX; + FP_DECL_Q(A); FP_DECL_Q(B); FP_DECL_Q(C); + long double c; + + FP_INIT_ROUNDMODE; + FP_UNPACK_SEMIRAW_Q(A, a); + FP_UNPACK_SEMIRAW_Q(B, b); + FP_ADD_Q(C, A, B); + FP_PACK_SEMIRAW_Q(c, C); + FP_HANDLE_EXCEPTIONS; + return c; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_cmp.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_cmp.c new file mode 100644 index 00000000..a93792ba --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_cmp.c @@ -0,0 +1,41 @@ +/* Software floating-point emulation. + Compare a and b, return float condition code. + Copyright (C) 1997,1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson (rth@cygnus.com) and + Jakub Jelinek (jj@ultra.linux.cz). + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "soft-fp.h" +#include "quad.h" + +int _Q_cmp(const long double a, const long double b) +{ + FP_DECL_EX; + FP_DECL_Q(A); FP_DECL_Q(B); + int r; + + FP_UNPACK_RAW_Q(A, a); + FP_UNPACK_RAW_Q(B, b); + FP_CMP_Q(r, B, A, 3); + if (r == -1) r = 2; + if (r == 3 && (FP_ISSIGNAN_Q(A) || FP_ISSIGNAN_Q(B))) + FP_SET_EXCEPTION(FP_EX_INVALID); + FP_HANDLE_EXCEPTIONS; + + return r; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_cmpe.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_cmpe.c new file mode 100644 index 00000000..135d63cc --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_cmpe.c @@ -0,0 +1,42 @@ +/* Software floating-point emulation. + Compare a and b, return float condition code. + Signal exception (unless masked) if unordered. + Copyright (C) 1997,1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson (rth@cygnus.com) and + Jakub Jelinek (jj@ultra.linux.cz). + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "soft-fp.h" +#include "quad.h" + +int _Q_cmpe(const long double a, const long double b) +{ + FP_DECL_EX; + FP_DECL_Q(A); FP_DECL_Q(B); + int r; + + FP_UNPACK_RAW_Q(A, a); + FP_UNPACK_RAW_Q(B, b); + FP_CMP_Q(r, B, A, 3); + if (r == -1) r = 2; + if (r == 3) + FP_SET_EXCEPTION(FP_EX_INVALID); + FP_HANDLE_EXCEPTIONS; + + return r; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_div.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_div.c new file mode 100644 index 00000000..86db5ed9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_div.c @@ -0,0 +1,39 @@ +/* Software floating-point emulation. + Return a / b + Copyright (C) 1997, 1999, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson (rth@cygnus.com) and + Jakub Jelinek (jj@ultra.linux.cz). + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "soft-fp.h" +#include "quad.h" + +long double _Q_div(const long double a, const long double b) +{ + FP_DECL_EX; + FP_DECL_Q(A); FP_DECL_Q(B); FP_DECL_Q(C); + long double c; + + FP_INIT_ROUNDMODE; + FP_UNPACK_Q(A, a); + FP_UNPACK_Q(B, b); + FP_DIV_Q(C, A, B); + FP_PACK_Q(c, C); + FP_HANDLE_EXCEPTIONS; + return c; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_dtoq.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_dtoq.c new file mode 100644 index 00000000..6b119f45 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_dtoq.c @@ -0,0 +1,44 @@ +/* Software floating-point emulation. + Return (long double)(a) + Copyright (C) 1997,1999,2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson (rth@cygnus.com) and + Jakub Jelinek (jj@ultra.linux.cz). + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "soft-fp.h" +#include "double.h" +#include "quad.h" + +long double _Q_dtoq(const double a) +{ + FP_DECL_EX; + FP_DECL_D(A); + FP_DECL_Q(C); + long double c; + + FP_INIT_ROUNDMODE; + FP_UNPACK_RAW_D(A, a); +#if (2 * _FP_W_TYPE_SIZE) < _FP_FRACBITS_Q + FP_EXTEND(Q,D,4,2,C,A); +#else + FP_EXTEND(Q,D,2,1,C,A); +#endif + FP_PACK_RAW_Q(c, C); + FP_HANDLE_EXCEPTIONS; + return c; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_feq.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_feq.c new file mode 100644 index 00000000..12cd7972 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_feq.c @@ -0,0 +1,40 @@ +/* Software floating-point emulation. + Return 1 if a == b + Copyright (C) 1997,1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson (rth@cygnus.com) and + Jakub Jelinek (jj@ultra.linux.cz). + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "soft-fp.h" +#include "quad.h" + +int _Q_feq(const long double a, const long double b) +{ + FP_DECL_EX; + FP_DECL_Q(A); FP_DECL_Q(B); + int r; + + FP_UNPACK_RAW_Q(A, a); + FP_UNPACK_RAW_Q(B, b); + FP_CMP_EQ_Q(r, A, B); + if (r && (FP_ISSIGNAN_Q(A) || FP_ISSIGNAN_Q(B))) + FP_SET_EXCEPTION(FP_EX_INVALID); + FP_HANDLE_EXCEPTIONS; + + return !r; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_fge.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_fge.c new file mode 100644 index 00000000..db1fdbe8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_fge.c @@ -0,0 +1,40 @@ +/* Software floating-point emulation. + Return 1 if a >= b + Copyright (C) 1997,1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson (rth@cygnus.com) and + Jakub Jelinek (jj@ultra.linux.cz). + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "soft-fp.h" +#include "quad.h" + +int _Q_fge(const long double a, const long double b) +{ + FP_DECL_EX; + FP_DECL_Q(A); FP_DECL_Q(B); + int r; + + FP_UNPACK_RAW_Q(A, a); + FP_UNPACK_RAW_Q(B, b); + FP_CMP_Q(r, B, A, 3); + if (r == 3) + FP_SET_EXCEPTION(FP_EX_INVALID); + FP_HANDLE_EXCEPTIONS; + + return (r <= 0); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_fgt.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_fgt.c new file mode 100644 index 00000000..a9f8cd0b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_fgt.c @@ -0,0 +1,40 @@ +/* Software floating-point emulation. + Return 1 if a > b + Copyright (C) 1997,1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson (rth@cygnus.com) and + Jakub Jelinek (jj@ultra.linux.cz). + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "soft-fp.h" +#include "quad.h" + +int _Q_fgt(const long double a, const long double b) +{ + FP_DECL_EX; + FP_DECL_Q(A); FP_DECL_Q(B); + int r; + + FP_UNPACK_RAW_Q(A, a); + FP_UNPACK_RAW_Q(B, b); + FP_CMP_Q(r, B, A, 3); + if (r == 3) + FP_SET_EXCEPTION(FP_EX_INVALID); + FP_HANDLE_EXCEPTIONS; + + return (r == -1); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_fle.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_fle.c new file mode 100644 index 00000000..a4b97e6c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_fle.c @@ -0,0 +1,40 @@ +/* Software floating-point emulation. + Return 1 if a <= b + Copyright (C) 1997,1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson (rth@cygnus.com) and + Jakub Jelinek (jj@ultra.linux.cz). + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "soft-fp.h" +#include "quad.h" + +int _Q_fle(const long double a, const long double b) +{ + FP_DECL_EX; + FP_DECL_Q(A); FP_DECL_Q(B); + int r; + + FP_UNPACK_RAW_Q(A, a); + FP_UNPACK_RAW_Q(B, b); + FP_CMP_Q(r, B, A, -2); + if (r == -2) + FP_SET_EXCEPTION(FP_EX_INVALID); + FP_HANDLE_EXCEPTIONS; + + return (r >= 0); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_flt.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_flt.c new file mode 100644 index 00000000..3979d657 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_flt.c @@ -0,0 +1,40 @@ +/* Software floating-point emulation. + Return 1 if a < b + Copyright (C) 1997,1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson (rth@cygnus.com) and + Jakub Jelinek (jj@ultra.linux.cz). + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "soft-fp.h" +#include "quad.h" + +int _Q_flt(const long double a, const long double b) +{ + FP_DECL_EX; + FP_DECL_Q(A); FP_DECL_Q(B); + int r; + + FP_UNPACK_RAW_Q(A, a); + FP_UNPACK_RAW_Q(B, b); + FP_CMP_Q(r, B, A, 3); + if (r == 3) + FP_SET_EXCEPTION(FP_EX_INVALID); + FP_HANDLE_EXCEPTIONS; + + return (r == 1); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_fne.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_fne.c new file mode 100644 index 00000000..a38059bc --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_fne.c @@ -0,0 +1,40 @@ +/* Software floating-point emulation. + Return 1 if a != b + Copyright (C) 1997,1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson (rth@cygnus.com) and + Jakub Jelinek (jj@ultra.linux.cz). + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "soft-fp.h" +#include "quad.h" + +int _Q_fne(const long double a, const long double b) +{ + FP_DECL_EX; + FP_DECL_Q(A); FP_DECL_Q(B); + int r; + + FP_UNPACK_RAW_Q(A, a); + FP_UNPACK_RAW_Q(B, b); + FP_CMP_EQ_Q(r, A, B); + if (r && (FP_ISSIGNAN_Q(A) || FP_ISSIGNAN_Q(B))) + FP_SET_EXCEPTION(FP_EX_INVALID); + FP_HANDLE_EXCEPTIONS; + + return r; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_itoq.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_itoq.c new file mode 100644 index 00000000..b50942f7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_itoq.c @@ -0,0 +1,38 @@ +/* Software floating-point emulation. + Return (long double)(a) + Copyright (C) 1997,1999,2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson (rth@cygnus.com) and + Jakub Jelinek (jj@ultra.linux.cz). + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "soft-fp.h" +#include "quad.h" + +long double _Q_itoq(const int a) +{ + FP_DECL_EX; + FP_DECL_Q(C); + int b = a; + long double c; + + FP_FROM_INT_Q(C, b, 32, unsigned int); + FP_PACK_RAW_Q(c, C); + FP_CLEAR_EXCEPTIONS; + FP_HANDLE_EXCEPTIONS; + return c; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_lltoq.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_lltoq.c new file mode 100644 index 00000000..f977585e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_lltoq.c @@ -0,0 +1,38 @@ +/* Software floating-point emulation. + Return (long double)a + Copyright (C) 1997, 1999, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson (rth@cygnus.com) and + Jakub Jelinek (jj@ultra.linux.cz). + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "soft-fp.h" +#include "quad.h" + +long double _Q_lltoq(const long long a) +{ + FP_DECL_EX; + FP_DECL_Q(C); + long double c; + long long b = a; + + FP_FROM_INT_Q(C, b, 64, unsigned long long); + FP_PACK_RAW_Q(c, C); + FP_CLEAR_EXCEPTIONS; + FP_HANDLE_EXCEPTIONS; + return c; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_mul.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_mul.c new file mode 100644 index 00000000..61c3a8fa --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_mul.c @@ -0,0 +1,39 @@ +/* Software floating-point emulation. + Return a * b + Copyright (C) 1997,1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson (rth@cygnus.com) and + Jakub Jelinek (jj@ultra.linux.cz). + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "soft-fp.h" +#include "quad.h" + +long double _Q_mul(const long double a, const long double b) +{ + FP_DECL_EX; + FP_DECL_Q(A); FP_DECL_Q(B); FP_DECL_Q(C); + long double c; + + FP_INIT_ROUNDMODE; + FP_UNPACK_Q(A, a); + FP_UNPACK_Q(B, b); + FP_MUL_Q(C, A, B); + FP_PACK_Q(c, C); + FP_HANDLE_EXCEPTIONS; + return c; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_neg.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_neg.c new file mode 100644 index 00000000..14f39e82 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_neg.c @@ -0,0 +1,47 @@ +/* Software floating-point emulation. + Return !a + Copyright (C) 1997,1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson (rth@cygnus.com) and + Jakub Jelinek (jj@ultra.linux.cz). + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "soft-fp.h" +#include "quad.h" + +long double _Q_neg(const long double a) +{ + FP_DECL_EX; + long double c = a; + +#if (__BYTE_ORDER == __BIG_ENDIAN) + ((UWtype *)&c)[0] ^= (((UWtype)1) << (W_TYPE_SIZE - 1)); +#elif (__BYTE_ORDER == __LITTLE_ENDIAN) && (W_TYPE_SIZE == 64) + ((UWtype *)&c)[1] ^= (((UWtype)1) << (W_TYPE_SIZE - 1)); +#elif (__BYTE_ORDER == __LITTLE_ENDIAN) && (W_TYPE_SIZE == 32) + ((UWtype *)&c)[3] ^= (((UWtype)1) << (W_TYPE_SIZE - 1)); +#else + FP_DECL_Q(A); FP_DECL_Q(C); + + FP_UNPACK_Q(A, a); + FP_NEG_Q(C, A); + FP_PACK_Q(c, C); +#endif + FP_CLEAR_EXCEPTIONS; + FP_HANDLE_EXCEPTIONS; + return c; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_qtod.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_qtod.c new file mode 100644 index 00000000..82b01ec8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_qtod.c @@ -0,0 +1,45 @@ +/* Software floating-point emulation. + Return (double)a + Copyright (C) 1997,1999,2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson (rth@cygnus.com) and + Jakub Jelinek (jj@ultra.linux.cz). + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "soft-fp.h" +#include "double.h" +#include "quad.h" + +double _Q_qtod(const long double a) +{ + FP_DECL_EX; + FP_DECL_Q(A); + FP_DECL_D(R); + double r; + + FP_INIT_ROUNDMODE; + FP_UNPACK_SEMIRAW_Q(A, a); +#if (2 * _FP_W_TYPE_SIZE) < _FP_FRACBITS_Q + FP_TRUNC(D,Q,2,4,R,A); +#else + FP_TRUNC(D,Q,1,2,R,A); +#endif + FP_PACK_SEMIRAW_D(r, R); + FP_HANDLE_EXCEPTIONS; + + return r; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_qtoi.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_qtoi.c new file mode 100644 index 00000000..270ba9f6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_qtoi.c @@ -0,0 +1,38 @@ +/* Software floating-point emulation. + Return (int)a + Copyright (C) 1997,1999,2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson (rth@cygnus.com) and + Jakub Jelinek (jj@ultra.linux.cz). + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define FP_ROUNDMODE FP_RND_ZERO +#include "soft-fp.h" +#include "quad.h" + +int _Q_qtoi(const long double a) +{ + FP_DECL_EX; + FP_DECL_Q(A); + unsigned int r; + + FP_UNPACK_RAW_Q(A, a); + FP_TO_INT_Q(r, A, 32, 1); + FP_HANDLE_EXCEPTIONS; + + return r; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_qtoll.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_qtoll.c new file mode 100644 index 00000000..e0d29019 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_qtoll.c @@ -0,0 +1,38 @@ +/* Software floating-point emulation. + Return (long long)a + Copyright (C) 1997, 1999, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson (rth@cygnus.com) and + Jakub Jelinek (jj@ultra.linux.cz). + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define FP_ROUNDMODE FP_RND_ZERO +#include "soft-fp.h" +#include "quad.h" + +long long _Q_qtoll(const long double a) +{ + FP_DECL_EX; + FP_DECL_Q(A); + unsigned long long r; + + FP_UNPACK_RAW_Q(A, a); + FP_TO_INT_Q(r, A, 64, 1); + FP_HANDLE_EXCEPTIONS; + + return r; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_qtos.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_qtos.c new file mode 100644 index 00000000..93daa23c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_qtos.c @@ -0,0 +1,45 @@ +/* Software floating-point emulation. + Return (float)a + Copyright (C) 1997,1999,2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson (rth@cygnus.com) and + Jakub Jelinek (jj@ultra.linux.cz). + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "soft-fp.h" +#include "single.h" +#include "quad.h" + +float _Q_qtos(const long double a) +{ + FP_DECL_EX; + FP_DECL_Q(A); + FP_DECL_S(R); + float r; + + FP_INIT_ROUNDMODE; + FP_UNPACK_SEMIRAW_Q(A, a); +#if (2 * _FP_W_TYPE_SIZE) < _FP_FRACBITS_Q + FP_TRUNC(S,Q,1,4,R,A); +#else + FP_TRUNC(S,Q,1,2,R,A); +#endif + FP_PACK_SEMIRAW_S(r, R); + FP_HANDLE_EXCEPTIONS; + + return r; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_qtou.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_qtou.c new file mode 100644 index 00000000..812b4e06 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_qtou.c @@ -0,0 +1,38 @@ +/* Software floating-point emulation. + Return (unsigned int)a + Copyright (C) 1997, 1999, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson (rth@cygnus.com) and + Jakub Jelinek (jj@ultra.linux.cz). + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define FP_ROUNDMODE FP_RND_ZERO +#include "soft-fp.h" +#include "quad.h" + +unsigned int _Q_qtou(const long double a) +{ + FP_DECL_EX; + FP_DECL_Q(A); + unsigned int r; + + FP_UNPACK_RAW_Q(A, a); + FP_TO_INT_Q(r, A, 32, -1); + FP_HANDLE_EXCEPTIONS; + + return r; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_qtoull.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_qtoull.c new file mode 100644 index 00000000..7a88c9f3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_qtoull.c @@ -0,0 +1,38 @@ +/* Software floating-point emulation. + Return (unsigned long long)a + Copyright (C) 1997, 1999, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson (rth@cygnus.com) and + Jakub Jelinek (jj@ultra.linux.cz). + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define FP_ROUNDMODE FP_RND_ZERO +#include "soft-fp.h" +#include "quad.h" + +unsigned long long _Q_qtoull(const long double a) +{ + FP_DECL_EX; + FP_DECL_Q(A); + unsigned long long r; + + FP_UNPACK_RAW_Q(A, a); + FP_TO_INT_Q(r, A, 64, -1); + FP_HANDLE_EXCEPTIONS; + + return r; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_sqrt.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_sqrt.c new file mode 100644 index 00000000..373d02a6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_sqrt.c @@ -0,0 +1,39 @@ +/* Software floating-point emulation. + Return sqrtl(a) + Copyright (C) 1997, 1999, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson (rth@cygnus.com) and + Jakub Jelinek (jj@ultra.linux.cz). + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "soft-fp.h" +#include "quad.h" + +long double _Q_sqrt(const long double a) +{ + FP_DECL_EX; + FP_DECL_Q(A); FP_DECL_Q(C); + long double c; + + FP_INIT_ROUNDMODE; + FP_UNPACK_Q(A, a); + FP_SQRT_Q(C, A); + FP_PACK_Q(c, C); + FP_HANDLE_EXCEPTIONS; + return c; +} +strong_alias (_Q_sqrt, __ieee754_sqrtl); diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_stoq.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_stoq.c new file mode 100644 index 00000000..714d880d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_stoq.c @@ -0,0 +1,43 @@ +/* Software floating-point emulation. + c = (long double)(a) + Copyright (C) 1997,1999,2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson (rth@cygnus.com) and + Jakub Jelinek (jj@ultra.linux.cz). + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "soft-fp.h" +#include "single.h" +#include "quad.h" + +long double _Q_stoq(const float a) +{ + FP_DECL_EX; + FP_DECL_S(A); + FP_DECL_Q(C); + long double c; + + FP_UNPACK_RAW_S(A, a); +#if (2 * _FP_W_TYPE_SIZE) < _FP_FRACBITS_Q + FP_EXTEND(Q,S,4,1,C,A); +#else + FP_EXTEND(Q,S,2,1,C,A); +#endif + FP_PACK_RAW_Q(c, C); + FP_HANDLE_EXCEPTIONS; + return c; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_sub.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_sub.c new file mode 100644 index 00000000..8616727b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_sub.c @@ -0,0 +1,39 @@ +/* Software floating-point emulation. + c = a - b + Copyright (C) 1997,1999,2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson (rth@cygnus.com) and + Jakub Jelinek (jj@ultra.linux.cz). + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "soft-fp.h" +#include "quad.h" + +long double _Q_sub(const long double a, const long double b) +{ + FP_DECL_EX; + FP_DECL_Q(A); FP_DECL_Q(B); FP_DECL_Q(C); + long double c; + + FP_INIT_ROUNDMODE; + FP_UNPACK_SEMIRAW_Q(A, a); + FP_UNPACK_SEMIRAW_Q(B, b); + FP_SUB_Q(C, A, B); + FP_PACK_SEMIRAW_Q(c, C); + FP_HANDLE_EXCEPTIONS; + return c; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_ulltoq.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_ulltoq.c new file mode 100644 index 00000000..53c0add2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_ulltoq.c @@ -0,0 +1,38 @@ +/* Software floating-point emulation. + Return (long double)(a) + Copyright (C) 1997, 1999, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson (rth@cygnus.com) and + Jakub Jelinek (jj@ultra.linux.cz). + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "soft-fp.h" +#include "quad.h" + +long double _Q_ulltoq(const unsigned long long a) +{ + FP_DECL_EX; + FP_DECL_Q(C); + long double c; + unsigned long long b = a; + + FP_FROM_INT_Q(C, b, 64, unsigned long long); + FP_PACK_RAW_Q(c, C); + FP_CLEAR_EXCEPTIONS; + FP_HANDLE_EXCEPTIONS; + return c; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_util.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_util.c new file mode 100644 index 00000000..41ecd685 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_util.c @@ -0,0 +1,57 @@ +/* Software floating-point emulation. + Helper routine for _Q_* routines. + Simulate exceptions using double arithmetics. + Copyright (C) 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek (jj@ultra.linux.cz). + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "soft-fp.h" + +unsigned long long ___Q_numbers [] = { +0x0000000000000000ULL, /* Zero */ +0x0010100000000000ULL, /* Very tiny number */ +0x0010000000000000ULL, /* Minimum normalized number */ +0x7fef000000000000ULL, /* A huge double number */ +}; + +double ___Q_simulate_exceptions(int exceptions) +{ + double d, *p = (double *)___Q_numbers; + if (exceptions & FP_EX_INVALID) + d = p[0]/p[0]; + if (exceptions & FP_EX_OVERFLOW) + { + d = p[3] + p[3]; + exceptions &= ~FP_EX_INEXACT; + } + if (exceptions & FP_EX_UNDERFLOW) + { + if (exceptions & FP_EX_INEXACT) + { + d = p[2] * p[2]; + exceptions &= ~FP_EX_INEXACT; + } + else + d = p[1] - p[2]; + } + if (exceptions & FP_EX_DIVZERO) + d = 1.0/p[0]; + if (exceptions & FP_EX_INEXACT) + d = p[3] - p[2]; + return d; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_utoq.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_utoq.c new file mode 100644 index 00000000..f902bf83 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/q_utoq.c @@ -0,0 +1,38 @@ +/* Software floating-point emulation. + c = (long double)(a) + Copyright (C) 1997, 1999, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson (rth@cygnus.com) and + Jakub Jelinek (jj@ultra.linux.cz). + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "soft-fp.h" +#include "quad.h" + +long double _Q_utoq(const unsigned int a) +{ + FP_DECL_EX; + FP_DECL_Q(C); + long double c; + unsigned int b = a; + + FP_FROM_INT_Q(C, b, 32, unsigned int); + FP_PACK_RAW_Q(c, C); + FP_CLEAR_EXCEPTIONS; + FP_HANDLE_EXCEPTIONS; + return c; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/quad.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/quad.h new file mode 100644 index 00000000..c22e9440 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/quad.h @@ -0,0 +1,271 @@ +/* Software floating-point emulation. + Definitions for IEEE Quad Precision. + Copyright (C) 1997,1998,1999,2006,2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson (rth@cygnus.com), + Jakub Jelinek (jj@ultra.linux.cz), + David S. Miller (davem@redhat.com) and + Peter Maydell (pmaydell@chiark.greenend.org.uk). + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file into + combinations with other programs, and to distribute those + combinations without any restriction coming from the use of this + file. (The Lesser General Public License restrictions do apply in + other respects; for example, they cover modification of the file, + and distribution when not linked into a combine executable.) + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301, USA. */ + +#if _FP_W_TYPE_SIZE < 32 +#error "Here's a nickel, kid. Go buy yourself a real computer." +#endif + +#if _FP_W_TYPE_SIZE < 64 +#define _FP_FRACTBITS_Q (4*_FP_W_TYPE_SIZE) +#else +#define _FP_FRACTBITS_Q (2*_FP_W_TYPE_SIZE) +#endif + +#define _FP_FRACBITS_Q 113 +#define _FP_FRACXBITS_Q (_FP_FRACTBITS_Q - _FP_FRACBITS_Q) +#define _FP_WFRACBITS_Q (_FP_WORKBITS + _FP_FRACBITS_Q) +#define _FP_WFRACXBITS_Q (_FP_FRACTBITS_Q - _FP_WFRACBITS_Q) +#define _FP_EXPBITS_Q 15 +#define _FP_EXPBIAS_Q 16383 +#define _FP_EXPMAX_Q 32767 + +#define _FP_QNANBIT_Q \ + ((_FP_W_TYPE)1 << (_FP_FRACBITS_Q-2) % _FP_W_TYPE_SIZE) +#define _FP_QNANBIT_SH_Q \ + ((_FP_W_TYPE)1 << (_FP_FRACBITS_Q-2+_FP_WORKBITS) % _FP_W_TYPE_SIZE) +#define _FP_IMPLBIT_Q \ + ((_FP_W_TYPE)1 << (_FP_FRACBITS_Q-1) % _FP_W_TYPE_SIZE) +#define _FP_IMPLBIT_SH_Q \ + ((_FP_W_TYPE)1 << (_FP_FRACBITS_Q-1+_FP_WORKBITS) % _FP_W_TYPE_SIZE) +#define _FP_OVERFLOW_Q \ + ((_FP_W_TYPE)1 << (_FP_WFRACBITS_Q % _FP_W_TYPE_SIZE)) + +typedef float TFtype __attribute__((mode(TF))); + +#if _FP_W_TYPE_SIZE < 64 + +union _FP_UNION_Q +{ + TFtype flt; + struct + { +#if __BYTE_ORDER == __BIG_ENDIAN + unsigned sign : 1; + unsigned exp : _FP_EXPBITS_Q; + unsigned long frac3 : _FP_FRACBITS_Q - (_FP_IMPLBIT_Q != 0)-(_FP_W_TYPE_SIZE * 3); + unsigned long frac2 : _FP_W_TYPE_SIZE; + unsigned long frac1 : _FP_W_TYPE_SIZE; + unsigned long frac0 : _FP_W_TYPE_SIZE; +#else + unsigned long frac0 : _FP_W_TYPE_SIZE; + unsigned long frac1 : _FP_W_TYPE_SIZE; + unsigned long frac2 : _FP_W_TYPE_SIZE; + unsigned long frac3 : _FP_FRACBITS_Q - (_FP_IMPLBIT_Q != 0)-(_FP_W_TYPE_SIZE * 3); + unsigned exp : _FP_EXPBITS_Q; + unsigned sign : 1; +#endif /* not bigendian */ + } bits __attribute__((packed)); +}; + + +#define FP_DECL_Q(X) _FP_DECL(4,X) +#define FP_UNPACK_RAW_Q(X,val) _FP_UNPACK_RAW_4(Q,X,val) +#define FP_UNPACK_RAW_QP(X,val) _FP_UNPACK_RAW_4_P(Q,X,val) +#define FP_PACK_RAW_Q(val,X) _FP_PACK_RAW_4(Q,val,X) +#define FP_PACK_RAW_QP(val,X) \ + do { \ + if (!FP_INHIBIT_RESULTS) \ + _FP_PACK_RAW_4_P(Q,val,X); \ + } while (0) + +#define FP_UNPACK_Q(X,val) \ + do { \ + _FP_UNPACK_RAW_4(Q,X,val); \ + _FP_UNPACK_CANONICAL(Q,4,X); \ + } while (0) + +#define FP_UNPACK_QP(X,val) \ + do { \ + _FP_UNPACK_RAW_4_P(Q,X,val); \ + _FP_UNPACK_CANONICAL(Q,4,X); \ + } while (0) + +#define FP_UNPACK_SEMIRAW_Q(X,val) \ + do { \ + _FP_UNPACK_RAW_4(Q,X,val); \ + _FP_UNPACK_SEMIRAW(Q,4,X); \ + } while (0) + +#define FP_UNPACK_SEMIRAW_QP(X,val) \ + do { \ + _FP_UNPACK_RAW_4_P(Q,X,val); \ + _FP_UNPACK_SEMIRAW(Q,4,X); \ + } while (0) + +#define FP_PACK_Q(val,X) \ + do { \ + _FP_PACK_CANONICAL(Q,4,X); \ + _FP_PACK_RAW_4(Q,val,X); \ + } while (0) + +#define FP_PACK_QP(val,X) \ + do { \ + _FP_PACK_CANONICAL(Q,4,X); \ + if (!FP_INHIBIT_RESULTS) \ + _FP_PACK_RAW_4_P(Q,val,X); \ + } while (0) + +#define FP_PACK_SEMIRAW_Q(val,X) \ + do { \ + _FP_PACK_SEMIRAW(Q,4,X); \ + _FP_PACK_RAW_4(Q,val,X); \ + } while (0) + +#define FP_PACK_SEMIRAW_QP(val,X) \ + do { \ + _FP_PACK_SEMIRAW(Q,4,X); \ + if (!FP_INHIBIT_RESULTS) \ + _FP_PACK_RAW_4_P(Q,val,X); \ + } while (0) + +#define FP_ISSIGNAN_Q(X) _FP_ISSIGNAN(Q,4,X) +#define FP_NEG_Q(R,X) _FP_NEG(Q,4,R,X) +#define FP_ADD_Q(R,X,Y) _FP_ADD(Q,4,R,X,Y) +#define FP_SUB_Q(R,X,Y) _FP_SUB(Q,4,R,X,Y) +#define FP_MUL_Q(R,X,Y) _FP_MUL(Q,4,R,X,Y) +#define FP_DIV_Q(R,X,Y) _FP_DIV(Q,4,R,X,Y) +#define FP_SQRT_Q(R,X) _FP_SQRT(Q,4,R,X) +#define _FP_SQRT_MEAT_Q(R,S,T,X,Q) _FP_SQRT_MEAT_4(R,S,T,X,Q) + +#define FP_CMP_Q(r,X,Y,un) _FP_CMP(Q,4,r,X,Y,un) +#define FP_CMP_EQ_Q(r,X,Y) _FP_CMP_EQ(Q,4,r,X,Y) +#define FP_CMP_UNORD_Q(r,X,Y) _FP_CMP_UNORD(Q,4,r,X,Y) + +#define FP_TO_INT_Q(r,X,rsz,rsg) _FP_TO_INT(Q,4,r,X,rsz,rsg) +#define FP_FROM_INT_Q(X,r,rs,rt) _FP_FROM_INT(Q,4,X,r,rs,rt) + +#define _FP_FRAC_HIGH_Q(X) _FP_FRAC_HIGH_4(X) +#define _FP_FRAC_HIGH_RAW_Q(X) _FP_FRAC_HIGH_4(X) + +#else /* not _FP_W_TYPE_SIZE < 64 */ +union _FP_UNION_Q +{ + TFtype flt /* __attribute__((mode(TF))) */ ; + struct { + _FP_W_TYPE a, b; + } longs; + struct { +#if __BYTE_ORDER == __BIG_ENDIAN + unsigned sign : 1; + unsigned exp : _FP_EXPBITS_Q; + _FP_W_TYPE frac1 : _FP_FRACBITS_Q - (_FP_IMPLBIT_Q != 0) - _FP_W_TYPE_SIZE; + _FP_W_TYPE frac0 : _FP_W_TYPE_SIZE; +#else + _FP_W_TYPE frac0 : _FP_W_TYPE_SIZE; + _FP_W_TYPE frac1 : _FP_FRACBITS_Q - (_FP_IMPLBIT_Q != 0) - _FP_W_TYPE_SIZE; + unsigned exp : _FP_EXPBITS_Q; + unsigned sign : 1; +#endif + } bits; +}; + +#define FP_DECL_Q(X) _FP_DECL(2,X) +#define FP_UNPACK_RAW_Q(X,val) _FP_UNPACK_RAW_2(Q,X,val) +#define FP_UNPACK_RAW_QP(X,val) _FP_UNPACK_RAW_2_P(Q,X,val) +#define FP_PACK_RAW_Q(val,X) _FP_PACK_RAW_2(Q,val,X) +#define FP_PACK_RAW_QP(val,X) \ + do { \ + if (!FP_INHIBIT_RESULTS) \ + _FP_PACK_RAW_2_P(Q,val,X); \ + } while (0) + +#define FP_UNPACK_Q(X,val) \ + do { \ + _FP_UNPACK_RAW_2(Q,X,val); \ + _FP_UNPACK_CANONICAL(Q,2,X); \ + } while (0) + +#define FP_UNPACK_QP(X,val) \ + do { \ + _FP_UNPACK_RAW_2_P(Q,X,val); \ + _FP_UNPACK_CANONICAL(Q,2,X); \ + } while (0) + +#define FP_UNPACK_SEMIRAW_Q(X,val) \ + do { \ + _FP_UNPACK_RAW_2(Q,X,val); \ + _FP_UNPACK_SEMIRAW(Q,2,X); \ + } while (0) + +#define FP_UNPACK_SEMIRAW_QP(X,val) \ + do { \ + _FP_UNPACK_RAW_2_P(Q,X,val); \ + _FP_UNPACK_SEMIRAW(Q,2,X); \ + } while (0) + +#define FP_PACK_Q(val,X) \ + do { \ + _FP_PACK_CANONICAL(Q,2,X); \ + _FP_PACK_RAW_2(Q,val,X); \ + } while (0) + +#define FP_PACK_QP(val,X) \ + do { \ + _FP_PACK_CANONICAL(Q,2,X); \ + if (!FP_INHIBIT_RESULTS) \ + _FP_PACK_RAW_2_P(Q,val,X); \ + } while (0) + +#define FP_PACK_SEMIRAW_Q(val,X) \ + do { \ + _FP_PACK_SEMIRAW(Q,2,X); \ + _FP_PACK_RAW_2(Q,val,X); \ + } while (0) + +#define FP_PACK_SEMIRAW_QP(val,X) \ + do { \ + _FP_PACK_SEMIRAW(Q,2,X); \ + if (!FP_INHIBIT_RESULTS) \ + _FP_PACK_RAW_2_P(Q,val,X); \ + } while (0) + +#define FP_ISSIGNAN_Q(X) _FP_ISSIGNAN(Q,2,X) +#define FP_NEG_Q(R,X) _FP_NEG(Q,2,R,X) +#define FP_ADD_Q(R,X,Y) _FP_ADD(Q,2,R,X,Y) +#define FP_SUB_Q(R,X,Y) _FP_SUB(Q,2,R,X,Y) +#define FP_MUL_Q(R,X,Y) _FP_MUL(Q,2,R,X,Y) +#define FP_DIV_Q(R,X,Y) _FP_DIV(Q,2,R,X,Y) +#define FP_SQRT_Q(R,X) _FP_SQRT(Q,2,R,X) +#define _FP_SQRT_MEAT_Q(R,S,T,X,Q) _FP_SQRT_MEAT_2(R,S,T,X,Q) + +#define FP_CMP_Q(r,X,Y,un) _FP_CMP(Q,2,r,X,Y,un) +#define FP_CMP_EQ_Q(r,X,Y) _FP_CMP_EQ(Q,2,r,X,Y) +#define FP_CMP_UNORD_Q(r,X,Y) _FP_CMP_UNORD(Q,2,r,X,Y) + +#define FP_TO_INT_Q(r,X,rsz,rsg) _FP_TO_INT(Q,2,r,X,rsz,rsg) +#define FP_FROM_INT_Q(X,r,rs,rt) _FP_FROM_INT(Q,2,X,r,rs,rt) + +#define _FP_FRAC_HIGH_Q(X) _FP_FRAC_HIGH_2(X) +#define _FP_FRAC_HIGH_RAW_Q(X) _FP_FRAC_HIGH_2(X) + +#endif /* not _FP_W_TYPE_SIZE < 64 */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/sfp-machine.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/sfp-machine.h new file mode 100644 index 00000000..f1211705 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/sfp-machine.h @@ -0,0 +1,213 @@ +/* Machine-dependent software floating-point definitions. + Sparc userland (_Q_*) version. + Copyright (C) 1997,1998,1999, 2002, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson (rth@cygnus.com), + Jakub Jelinek (jj@ultra.linux.cz) and + David S. Miller (davem@redhat.com). + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +#define _FP_W_TYPE_SIZE 32 +#define _FP_W_TYPE unsigned long +#define _FP_WS_TYPE signed long +#define _FP_I_TYPE long + +#define _FP_MUL_MEAT_S(R,X,Y) \ + _FP_MUL_MEAT_1_wide(_FP_WFRACBITS_S,R,X,Y,umul_ppmm) +#define _FP_MUL_MEAT_D(R,X,Y) \ + _FP_MUL_MEAT_2_wide(_FP_WFRACBITS_D,R,X,Y,umul_ppmm) +#define _FP_MUL_MEAT_Q(R,X,Y) \ + _FP_MUL_MEAT_4_wide(_FP_WFRACBITS_Q,R,X,Y,umul_ppmm) + +#define _FP_DIV_MEAT_S(R,X,Y) _FP_DIV_MEAT_1_udiv(S,R,X,Y) +#define _FP_DIV_MEAT_D(R,X,Y) _FP_DIV_MEAT_2_udiv(D,R,X,Y) +#define _FP_DIV_MEAT_Q(R,X,Y) _FP_DIV_MEAT_4_udiv(Q,R,X,Y) + +#define _FP_NANFRAC_S ((_FP_QNANBIT_S << 1) - 1) +#define _FP_NANFRAC_D ((_FP_QNANBIT_D << 1) - 1), -1 +#define _FP_NANFRAC_Q ((_FP_QNANBIT_Q << 1) - 1), -1, -1, -1 +#define _FP_NANSIGN_S 0 +#define _FP_NANSIGN_D 0 +#define _FP_NANSIGN_Q 0 + +#define _FP_KEEPNANFRACP 1 + +/* If one NaN is signaling and the other is not, + * we choose that one, otherwise we choose X. + */ +/* For _Qp_* and _Q_*, this should prefer X, for + * CPU instruction emulation this should prefer Y. + * (see SPAMv9 B.2.2 section). + */ +#define _FP_CHOOSENAN(fs, wc, R, X, Y, OP) \ + do { \ + if ((_FP_FRAC_HIGH_RAW_##fs(X) & _FP_QNANBIT_##fs) \ + && !(_FP_FRAC_HIGH_RAW_##fs(Y) & _FP_QNANBIT_##fs)) \ + { \ + R##_s = Y##_s; \ + _FP_FRAC_COPY_##wc(R,Y); \ + } \ + else \ + { \ + R##_s = X##_s; \ + _FP_FRAC_COPY_##wc(R,X); \ + } \ + R##_c = FP_CLS_NAN; \ + } while (0) + +/* Some assembly to speed things up. */ +#define __FP_FRAC_ADD_3(r2,r1,r0,x2,x1,x0,y2,y1,y0) \ + __asm__ ("addcc %r7,%8,%2\n\ + addxcc %r5,%6,%1\n\ + addx %r3,%4,%0" \ + : "=r" ((USItype)(r2)), \ + "=&r" ((USItype)(r1)), \ + "=&r" ((USItype)(r0)) \ + : "%rJ" ((USItype)(x2)), \ + "rI" ((USItype)(y2)), \ + "%rJ" ((USItype)(x1)), \ + "rI" ((USItype)(y1)), \ + "%rJ" ((USItype)(x0)), \ + "rI" ((USItype)(y0)) \ + : "cc") + +#define __FP_FRAC_SUB_3(r2,r1,r0,x2,x1,x0,y2,y1,y0) \ + __asm__ ("subcc %r7,%8,%2\n\ + subxcc %r5,%6,%1\n\ + subx %r3,%4,%0" \ + : "=r" ((USItype)(r2)), \ + "=&r" ((USItype)(r1)), \ + "=&r" ((USItype)(r0)) \ + : "%rJ" ((USItype)(x2)), \ + "rI" ((USItype)(y2)), \ + "%rJ" ((USItype)(x1)), \ + "rI" ((USItype)(y1)), \ + "%rJ" ((USItype)(x0)), \ + "rI" ((USItype)(y0)) \ + : "cc") + +#define __FP_FRAC_ADD_4(r3,r2,r1,r0,x3,x2,x1,x0,y3,y2,y1,y0) \ + do { \ + /* We need to fool gcc, as we need to pass more than 10 \ + input/outputs. */ \ + register USItype _t1 __asm__ ("g1"), _t2 __asm__ ("g2"); \ + __asm__ __volatile__ ("\ + addcc %r8,%9,%1\n\ + addxcc %r6,%7,%0\n\ + addxcc %r4,%5,%%g2\n\ + addx %r2,%3,%%g1" \ + : "=&r" ((USItype)(r1)), \ + "=&r" ((USItype)(r0)) \ + : "%rJ" ((USItype)(x3)), \ + "rI" ((USItype)(y3)), \ + "%rJ" ((USItype)(x2)), \ + "rI" ((USItype)(y2)), \ + "%rJ" ((USItype)(x1)), \ + "rI" ((USItype)(y1)), \ + "%rJ" ((USItype)(x0)), \ + "rI" ((USItype)(y0)) \ + : "cc", "g1", "g2"); \ + __asm__ __volatile__ ("" : "=r" (_t1), "=r" (_t2)); \ + r3 = _t1; r2 = _t2; \ + } while (0) + +#define __FP_FRAC_SUB_4(r3,r2,r1,r0,x3,x2,x1,x0,y3,y2,y1,y0) \ + do { \ + /* We need to fool gcc, as we need to pass more than 10 \ + input/outputs. */ \ + register USItype _t1 __asm__ ("g1"), _t2 __asm__ ("g2"); \ + __asm__ __volatile__ ("\ + subcc %r8,%9,%1\n\ + subxcc %r6,%7,%0\n\ + subxcc %r4,%5,%%g2\n\ + subx %r2,%3,%%g1" \ + : "=&r" ((USItype)(r1)), \ + "=&r" ((USItype)(r0)) \ + : "%rJ" ((USItype)(x3)), \ + "rI" ((USItype)(y3)), \ + "%rJ" ((USItype)(x2)), \ + "rI" ((USItype)(y2)), \ + "%rJ" ((USItype)(x1)), \ + "rI" ((USItype)(y1)), \ + "%rJ" ((USItype)(x0)), \ + "rI" ((USItype)(y0)) \ + : "cc", "g1", "g2"); \ + __asm__ __volatile__ ("" : "=r" (_t1), "=r" (_t2)); \ + r3 = _t1; r2 = _t2; \ + } while (0) + +#define __FP_FRAC_DEC_3(x2,x1,x0,y2,y1,y0) __FP_FRAC_SUB_3(x2,x1,x0,x2,x1,x0,y2,y1,y0) + +#define __FP_FRAC_DEC_4(x3,x2,x1,x0,y3,y2,y1,y0) __FP_FRAC_SUB_4(x3,x2,x1,x0,x3,x2,x1,x0,y3,y2,y1,y0) + +#define __FP_FRAC_ADDI_4(x3,x2,x1,x0,i) \ + __asm__ ("addcc %3,%4,%3\n\ + addxcc %2,%%g0,%2\n\ + addxcc %1,%%g0,%1\n\ + addx %0,%%g0,%0" \ + : "=&r" ((USItype)(x3)), \ + "=&r" ((USItype)(x2)), \ + "=&r" ((USItype)(x1)), \ + "=&r" ((USItype)(x0)) \ + : "rI" ((USItype)(i)), \ + "0" ((USItype)(x3)), \ + "1" ((USItype)(x2)), \ + "2" ((USItype)(x1)), \ + "3" ((USItype)(x0)) \ + : "cc") + +/* Obtain the current rounding mode. */ +#ifndef FP_ROUNDMODE +#define FP_ROUNDMODE ((_fcw >> 30) & 0x3) +#endif + +/* Exception flags. */ +#define FP_EX_INVALID (1 << 4) +#define FP_EX_OVERFLOW (1 << 3) +#define FP_EX_UNDERFLOW (1 << 2) +#define FP_EX_DIVZERO (1 << 1) +#define FP_EX_INEXACT (1 << 0) + +#define _FP_DECL_EX fpu_control_t _fcw + +#define FP_INIT_ROUNDMODE \ +do { \ + _FPU_GETCW(_fcw); \ +} while (0) + +/* Simulate exceptions using double arithmetics. */ +extern double ___Q_simulate_exceptions(int exc); + +#define FP_HANDLE_EXCEPTIONS \ +do { \ + if (!_fex) \ + { \ + /* This is the common case, so we do it inline. \ + * We need to clear cexc bits if any. \ + */ \ + extern unsigned long long ___Q_numbers[]; \ + __asm__ __volatile__("\ + ldd [%0], %%f30\n\ + faddd %%f30, %%f30, %%f30\ + " : : "r" (___Q_numbers) : "f30"); \ + } \ + else \ + ___Q_simulate_exceptions (_fex); \ +} while (0) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/single.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/single.h new file mode 100644 index 00000000..9c3734ad --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/single.h @@ -0,0 +1,151 @@ +/* Software floating-point emulation. + Definitions for IEEE Single Precision. + Copyright (C) 1997,1998,1999,2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson (rth@cygnus.com), + Jakub Jelinek (jj@ultra.linux.cz), + David S. Miller (davem@redhat.com) and + Peter Maydell (pmaydell@chiark.greenend.org.uk). + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file into + combinations with other programs, and to distribute those + combinations without any restriction coming from the use of this + file. (The Lesser General Public License restrictions do apply in + other respects; for example, they cover modification of the file, + and distribution when not linked into a combine executable.) + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301, USA. */ + +#if _FP_W_TYPE_SIZE < 32 +#error "Here's a nickel kid. Go buy yourself a real computer." +#endif + +#define _FP_FRACTBITS_S _FP_W_TYPE_SIZE + +#define _FP_FRACBITS_S 24 +#define _FP_FRACXBITS_S (_FP_FRACTBITS_S - _FP_FRACBITS_S) +#define _FP_WFRACBITS_S (_FP_WORKBITS + _FP_FRACBITS_S) +#define _FP_WFRACXBITS_S (_FP_FRACTBITS_S - _FP_WFRACBITS_S) +#define _FP_EXPBITS_S 8 +#define _FP_EXPBIAS_S 127 +#define _FP_EXPMAX_S 255 +#define _FP_QNANBIT_S ((_FP_W_TYPE)1 << (_FP_FRACBITS_S-2)) +#define _FP_QNANBIT_SH_S ((_FP_W_TYPE)1 << (_FP_FRACBITS_S-2+_FP_WORKBITS)) +#define _FP_IMPLBIT_S ((_FP_W_TYPE)1 << (_FP_FRACBITS_S-1)) +#define _FP_IMPLBIT_SH_S ((_FP_W_TYPE)1 << (_FP_FRACBITS_S-1+_FP_WORKBITS)) +#define _FP_OVERFLOW_S ((_FP_W_TYPE)1 << (_FP_WFRACBITS_S)) + +/* The implementation of _FP_MUL_MEAT_S and _FP_DIV_MEAT_S should be + chosen by the target machine. */ + +typedef float SFtype __attribute__((mode(SF))); + +union _FP_UNION_S +{ + SFtype flt; + struct { +#if __BYTE_ORDER == __BIG_ENDIAN + unsigned sign : 1; + unsigned exp : _FP_EXPBITS_S; + unsigned frac : _FP_FRACBITS_S - (_FP_IMPLBIT_S != 0); +#else + unsigned frac : _FP_FRACBITS_S - (_FP_IMPLBIT_S != 0); + unsigned exp : _FP_EXPBITS_S; + unsigned sign : 1; +#endif + } bits __attribute__((packed)); +}; + +#define FP_DECL_S(X) _FP_DECL(1,X) +#define FP_UNPACK_RAW_S(X,val) _FP_UNPACK_RAW_1(S,X,val) +#define FP_UNPACK_RAW_SP(X,val) _FP_UNPACK_RAW_1_P(S,X,val) +#define FP_PACK_RAW_S(val,X) _FP_PACK_RAW_1(S,val,X) +#define FP_PACK_RAW_SP(val,X) \ + do { \ + if (!FP_INHIBIT_RESULTS) \ + _FP_PACK_RAW_1_P(S,val,X); \ + } while (0) + +#define FP_UNPACK_S(X,val) \ + do { \ + _FP_UNPACK_RAW_1(S,X,val); \ + _FP_UNPACK_CANONICAL(S,1,X); \ + } while (0) + +#define FP_UNPACK_SP(X,val) \ + do { \ + _FP_UNPACK_RAW_1_P(S,X,val); \ + _FP_UNPACK_CANONICAL(S,1,X); \ + } while (0) + +#define FP_UNPACK_SEMIRAW_S(X,val) \ + do { \ + _FP_UNPACK_RAW_1(S,X,val); \ + _FP_UNPACK_SEMIRAW(S,1,X); \ + } while (0) + +#define FP_UNPACK_SEMIRAW_SP(X,val) \ + do { \ + _FP_UNPACK_RAW_1_P(S,X,val); \ + _FP_UNPACK_SEMIRAW(S,1,X); \ + } while (0) + +#define FP_PACK_S(val,X) \ + do { \ + _FP_PACK_CANONICAL(S,1,X); \ + _FP_PACK_RAW_1(S,val,X); \ + } while (0) + +#define FP_PACK_SP(val,X) \ + do { \ + _FP_PACK_CANONICAL(S,1,X); \ + if (!FP_INHIBIT_RESULTS) \ + _FP_PACK_RAW_1_P(S,val,X); \ + } while (0) + +#define FP_PACK_SEMIRAW_S(val,X) \ + do { \ + _FP_PACK_SEMIRAW(S,1,X); \ + _FP_PACK_RAW_1(S,val,X); \ + } while (0) + +#define FP_PACK_SEMIRAW_SP(val,X) \ + do { \ + _FP_PACK_SEMIRAW(S,1,X); \ + if (!FP_INHIBIT_RESULTS) \ + _FP_PACK_RAW_1_P(S,val,X); \ + } while (0) + +#define FP_ISSIGNAN_S(X) _FP_ISSIGNAN(S,1,X) +#define FP_NEG_S(R,X) _FP_NEG(S,1,R,X) +#define FP_ADD_S(R,X,Y) _FP_ADD(S,1,R,X,Y) +#define FP_SUB_S(R,X,Y) _FP_SUB(S,1,R,X,Y) +#define FP_MUL_S(R,X,Y) _FP_MUL(S,1,R,X,Y) +#define FP_DIV_S(R,X,Y) _FP_DIV(S,1,R,X,Y) +#define FP_SQRT_S(R,X) _FP_SQRT(S,1,R,X) +#define _FP_SQRT_MEAT_S(R,S,T,X,Q) _FP_SQRT_MEAT_1(R,S,T,X,Q) + +#define FP_CMP_S(r,X,Y,un) _FP_CMP(S,1,r,X,Y,un) +#define FP_CMP_EQ_S(r,X,Y) _FP_CMP_EQ(S,1,r,X,Y) +#define FP_CMP_UNORD_S(r,X,Y) _FP_CMP_UNORD(S,1,r,X,Y) + +#define FP_TO_INT_S(r,X,rsz,rsg) _FP_TO_INT(S,1,r,X,rsz,rsg) +#define FP_FROM_INT_S(X,r,rs,rt) _FP_FROM_INT(S,1,X,r,rs,rt) + +#define _FP_FRAC_HIGH_S(X) _FP_FRAC_HIGH_1(X) +#define _FP_FRAC_HIGH_RAW_S(X) _FP_FRAC_HIGH_1(X) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/soft-fp.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/soft-fp.h new file mode 100644 index 00000000..40f0dbd5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/soft-fp/soft-fp.h @@ -0,0 +1,205 @@ +/* Software floating-point emulation. + Copyright (C) 1997,1998,1999,2000,2002,2003,2005,2006,2007 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson (rth@cygnus.com), + Jakub Jelinek (jj@ultra.linux.cz), + David S. Miller (davem@redhat.com) and + Peter Maydell (pmaydell@chiark.greenend.org.uk). + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file into + combinations with other programs, and to distribute those + combinations without any restriction coming from the use of this + file. (The Lesser General Public License restrictions do apply in + other respects; for example, they cover modification of the file, + and distribution when not linked into a combine executable.) + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301, USA. */ + +#ifndef SOFT_FP_H +#define SOFT_FP_H + +#include "sfp-machine.h" + +/* Allow sfp-machine to have its own byte order definitions. */ +#ifndef __BYTE_ORDER +#ifdef _LIBC +#include +#else +#error "endianness not defined by sfp-machine.h" +#endif +#endif + +#define _FP_WORKBITS 3 +#define _FP_WORK_LSB ((_FP_W_TYPE)1 << 3) +#define _FP_WORK_ROUND ((_FP_W_TYPE)1 << 2) +#define _FP_WORK_GUARD ((_FP_W_TYPE)1 << 1) +#define _FP_WORK_STICKY ((_FP_W_TYPE)1 << 0) + +#ifndef FP_RND_NEAREST +# define FP_RND_NEAREST 0 +# define FP_RND_ZERO 1 +# define FP_RND_PINF 2 +# define FP_RND_MINF 3 +#endif +#ifndef FP_ROUNDMODE +# define FP_ROUNDMODE FP_RND_NEAREST +#endif + +/* By default don't care about exceptions. */ +#ifndef FP_EX_INVALID +#define FP_EX_INVALID 0 +#endif +#ifndef FP_EX_OVERFLOW +#define FP_EX_OVERFLOW 0 +#endif +#ifndef FP_EX_UNDERFLOW +#define FP_EX_UNDERFLOW 0 +#endif +#ifndef FP_EX_DIVZERO +#define FP_EX_DIVZERO 0 +#endif +#ifndef FP_EX_INEXACT +#define FP_EX_INEXACT 0 +#endif +#ifndef FP_EX_DENORM +#define FP_EX_DENORM 0 +#endif + +#ifdef _FP_DECL_EX +#define FP_DECL_EX \ + int _fex = 0; \ + _FP_DECL_EX +#else +#define FP_DECL_EX int _fex = 0 +#endif + +#ifndef FP_INIT_ROUNDMODE +#define FP_INIT_ROUNDMODE do {} while (0) +#endif + +#ifndef FP_HANDLE_EXCEPTIONS +#define FP_HANDLE_EXCEPTIONS do {} while (0) +#endif + +#ifndef FP_INHIBIT_RESULTS +/* By default we write the results always. + * sfp-machine may override this and e.g. + * check if some exceptions are unmasked + * and inhibit it in such a case. + */ +#define FP_INHIBIT_RESULTS 0 +#endif + +#define FP_SET_EXCEPTION(ex) \ + _fex |= (ex) + +#define FP_UNSET_EXCEPTION(ex) \ + _fex &= ~(ex) + +#define FP_CLEAR_EXCEPTIONS \ + _fex = 0 + +#define _FP_ROUND_NEAREST(wc, X) \ +do { \ + if ((_FP_FRAC_LOW_##wc(X) & 15) != _FP_WORK_ROUND) \ + _FP_FRAC_ADDI_##wc(X, _FP_WORK_ROUND); \ +} while (0) + +#define _FP_ROUND_ZERO(wc, X) (void)0 + +#define _FP_ROUND_PINF(wc, X) \ +do { \ + if (!X##_s && (_FP_FRAC_LOW_##wc(X) & 7)) \ + _FP_FRAC_ADDI_##wc(X, _FP_WORK_LSB); \ +} while (0) + +#define _FP_ROUND_MINF(wc, X) \ +do { \ + if (X##_s && (_FP_FRAC_LOW_##wc(X) & 7)) \ + _FP_FRAC_ADDI_##wc(X, _FP_WORK_LSB); \ +} while (0) + +#define _FP_ROUND(wc, X) \ +do { \ + if (_FP_FRAC_LOW_##wc(X) & 7) \ + FP_SET_EXCEPTION(FP_EX_INEXACT); \ + switch (FP_ROUNDMODE) \ + { \ + case FP_RND_NEAREST: \ + _FP_ROUND_NEAREST(wc,X); \ + break; \ + case FP_RND_ZERO: \ + _FP_ROUND_ZERO(wc,X); \ + break; \ + case FP_RND_PINF: \ + _FP_ROUND_PINF(wc,X); \ + break; \ + case FP_RND_MINF: \ + _FP_ROUND_MINF(wc,X); \ + break; \ + } \ +} while (0) + +#define FP_CLS_NORMAL 0 +#define FP_CLS_ZERO 1 +#define FP_CLS_INF 2 +#define FP_CLS_NAN 3 + +#define _FP_CLS_COMBINE(x,y) (((x) << 2) | (y)) + +#include "op-1.h" +#include "op-2.h" +#include "op-4.h" +#include "op-8.h" +#include "op-common.h" + +/* Sigh. Silly things longlong.h needs. */ +#define UWtype _FP_W_TYPE +#define W_TYPE_SIZE _FP_W_TYPE_SIZE + +typedef int QItype __attribute__((mode(QI))); +typedef int SItype __attribute__((mode(SI))); +typedef int DItype __attribute__((mode(DI))); +typedef unsigned int UQItype __attribute__((mode(QI))); +typedef unsigned int USItype __attribute__((mode(SI))); +typedef unsigned int UDItype __attribute__((mode(DI))); +#if _FP_W_TYPE_SIZE == 32 +typedef unsigned int UHWtype __attribute__((mode(HI))); +#elif _FP_W_TYPE_SIZE == 64 +typedef USItype UHWtype; +#endif + +#ifndef CMPtype +#define CMPtype int +#endif + +#define SI_BITS (__CHAR_BIT__ * (int)sizeof(SItype)) +#define DI_BITS (__CHAR_BIT__ * (int)sizeof(DItype)) + +#ifndef umul_ppmm +#include "longlong.h" +#endif + +#ifdef _LIBC +#include +#else +extern void abort (void); +#endif + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sparcv7/rem.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sparcv7/rem.S new file mode 100644 index 00000000..ce06e636 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sparcv7/rem.S @@ -0,0 +1,360 @@ + /* This file is generated from divrem.m4; DO NOT EDIT! */ +/* + * Division and remainder, from Appendix E of the Sparc Version 8 + * Architecture Manual, with fixes from Gordon Irlam. + */ + +/* + * Input: dividend and divisor in %o0 and %o1 respectively. + * + * m4 parameters: + * .rem name of function to generate + * rem rem=div => %o0 / %o1; rem=rem => %o0 % %o1 + * true true=true => signed; true=false => unsigned + * + * Algorithm parameters: + * N how many bits per iteration we try to get (4) + * WORDSIZE total number of bits (32) + * + * Derived constants: + * TOPBITS number of bits in the top decade of a number + * + * Important variables: + * Q the partial quotient under development (initially 0) + * R the remainder so far, initially the dividend + * ITER number of main division loop iterations required; + * equal to ceil(log2(quotient) / N). Note that this + * is the log base (2^N) of the quotient. + * V the current comparand, initially divisor*2^(ITER*N-1) + * + * Cost: + * Current estimate for non-large dividend is + * ceil(log2(quotient) / N) * (10 + 7N/2) + C + * A large dividend is one greater than 2^(31-TOPBITS) and takes a + * different path, as the upper bits of the quotient must be developed + * one bit at a time. + */ + + + +ENTRY(.rem) + ! compute sign of result; if neither is negative, no problem + orcc %o1, %o0, %g0 ! either negative? + bge 2f ! no, go do the divide + mov %o0, %g3 ! sign of remainder matches %o0 + tst %o1 + bge 1f + tst %o0 + ! %o1 is definitely negative; %o0 might also be negative + bge 2f ! if %o0 not negative... + sub %g0, %o1, %o1 ! in any case, make %o1 nonneg +1: ! %o0 is negative, %o1 is nonnegative + sub %g0, %o0, %o0 ! make %o0 nonnegative +2: + + ! Ready to divide. Compute size of quotient; scale comparand. + orcc %o1, %g0, %o5 + bne 1f + mov %o0, %o3 + + ! Divide by zero trap. If it returns, return 0 (about as + ! wrong as possible, but that is what SunOS does...). + ta ST_DIV0 + retl + clr %o0 + +1: + cmp %o3, %o5 ! if %o1 exceeds %o0, done + blu LOC(got_result) ! (and algorithm fails otherwise) + clr %o2 + sethi %hi(1 << (32 - 4 - 1)), %g1 + cmp %o3, %g1 + blu LOC(not_really_big) + clr %o4 + + ! Here the dividend is >= 2**(31-N) or so. We must be careful here, + ! as our usual N-at-a-shot divide step will cause overflow and havoc. + ! The number of bits in the result here is N*ITER+SC, where SC <= N. + ! Compute ITER in an unorthodox manner: know we need to shift V into + ! the top decade: so do not even bother to compare to R. + 1: + cmp %o5, %g1 + bgeu 3f + mov 1, %g2 + sll %o5, 4, %o5 + b 1b + add %o4, 1, %o4 + + ! Now compute %g2. + 2: addcc %o5, %o5, %o5 + bcc LOC(not_too_big) + add %g2, 1, %g2 + + ! We get here if the %o1 overflowed while shifting. + ! This means that %o3 has the high-order bit set. + ! Restore %o5 and subtract from %o3. + sll %g1, 4, %g1 ! high order bit + srl %o5, 1, %o5 ! rest of %o5 + add %o5, %g1, %o5 + b LOC(do_single_div) + sub %g2, 1, %g2 + + LOC(not_too_big): + 3: cmp %o5, %o3 + blu 2b + nop + be LOC(do_single_div) + nop + /* NB: these are commented out in the V8-Sparc manual as well */ + /* (I do not understand this) */ + ! %o5 > %o3: went too far: back up 1 step + ! srl %o5, 1, %o5 + ! dec %g2 + ! do single-bit divide steps + ! + ! We have to be careful here. We know that %o3 >= %o5, so we can do the + ! first divide step without thinking. BUT, the others are conditional, + ! and are only done if %o3 >= 0. Because both %o3 and %o5 may have the high- + ! order bit set in the first step, just falling into the regular + ! division loop will mess up the first time around. + ! So we unroll slightly... + LOC(do_single_div): + subcc %g2, 1, %g2 + bl LOC(end_regular_divide) + nop + sub %o3, %o5, %o3 + mov 1, %o2 + b LOC(end_single_divloop) + nop + LOC(single_divloop): + sll %o2, 1, %o2 + bl 1f + srl %o5, 1, %o5 + ! %o3 >= 0 + sub %o3, %o5, %o3 + b 2f + add %o2, 1, %o2 + 1: ! %o3 < 0 + add %o3, %o5, %o3 + sub %o2, 1, %o2 + 2: + LOC(end_single_divloop): + subcc %g2, 1, %g2 + bge LOC(single_divloop) + tst %o3 + b,a LOC(end_regular_divide) + +LOC(not_really_big): +1: + sll %o5, 4, %o5 + cmp %o5, %o3 + bleu 1b + addcc %o4, 1, %o4 + be LOC(got_result) + sub %o4, 1, %o4 + + tst %o3 ! set up for initial iteration +LOC(divloop): + sll %o2, 4, %o2 + ! depth 1, accumulated bits 0 + bl LOC(1.16) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 2, accumulated bits 1 + bl LOC(2.17) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 3, accumulated bits 3 + bl LOC(3.19) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 4, accumulated bits 7 + bl LOC(4.23) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (7*2+1), %o2 + +LOC(4.23): + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (7*2-1), %o2 + + +LOC(3.19): + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 4, accumulated bits 5 + bl LOC(4.21) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (5*2+1), %o2 + +LOC(4.21): + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (5*2-1), %o2 + + + +LOC(2.17): + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 3, accumulated bits 1 + bl LOC(3.17) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 4, accumulated bits 3 + bl LOC(4.19) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (3*2+1), %o2 + +LOC(4.19): + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (3*2-1), %o2 + + +LOC(3.17): + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 4, accumulated bits 1 + bl LOC(4.17) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (1*2+1), %o2 + +LOC(4.17): + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (1*2-1), %o2 + + + + +LOC(1.16): + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 2, accumulated bits -1 + bl LOC(2.15) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 3, accumulated bits -1 + bl LOC(3.15) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 4, accumulated bits -1 + bl LOC(4.15) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (-1*2+1), %o2 + +LOC(4.15): + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (-1*2-1), %o2 + + +LOC(3.15): + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 4, accumulated bits -3 + bl LOC(4.13) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (-3*2+1), %o2 + +LOC(4.13): + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (-3*2-1), %o2 + + + +LOC(2.15): + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 3, accumulated bits -3 + bl LOC(3.13) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 4, accumulated bits -5 + bl LOC(4.11) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (-5*2+1), %o2 + +LOC(4.11): + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (-5*2-1), %o2 + + +LOC(3.13): + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 4, accumulated bits -7 + bl LOC(4.9) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (-7*2+1), %o2 + +LOC(4.9): + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (-7*2-1), %o2 + + + + + 9: +LOC(end_regular_divide): + subcc %o4, 1, %o4 + bge LOC(divloop) + tst %o3 + bl,a LOC(got_result) + ! non-restoring fixup here (one instruction only!) + add %o3, %o1, %o3 + + +LOC(got_result): + ! check to see if answer should be < 0 + tst %g3 + bl,a 1f + sub %g0, %o3, %o3 +1: + retl + mov %o3, %o0 + +END(.rem) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sparcv7/sdiv.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sparcv7/sdiv.S new file mode 100644 index 00000000..d6f2bc7c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sparcv7/sdiv.S @@ -0,0 +1,360 @@ + /* This file is generated from divrem.m4; DO NOT EDIT! */ +/* + * Division and remainder, from Appendix E of the Sparc Version 8 + * Architecture Manual, with fixes from Gordon Irlam. + */ + +/* + * Input: dividend and divisor in %o0 and %o1 respectively. + * + * m4 parameters: + * .div name of function to generate + * div div=div => %o0 / %o1; div=rem => %o0 % %o1 + * true true=true => signed; true=false => unsigned + * + * Algorithm parameters: + * N how many bits per iteration we try to get (4) + * WORDSIZE total number of bits (32) + * + * Derived constants: + * TOPBITS number of bits in the top decade of a number + * + * Important variables: + * Q the partial quotient under development (initially 0) + * R the remainder so far, initially the dividend + * ITER number of main division loop iterations required; + * equal to ceil(log2(quotient) / N). Note that this + * is the log base (2^N) of the quotient. + * V the current comparand, initially divisor*2^(ITER*N-1) + * + * Cost: + * Current estimate for non-large dividend is + * ceil(log2(quotient) / N) * (10 + 7N/2) + C + * A large dividend is one greater than 2^(31-TOPBITS) and takes a + * different path, as the upper bits of the quotient must be developed + * one bit at a time. + */ + + + +ENTRY(.div) + ! compute sign of result; if neither is negative, no problem + orcc %o1, %o0, %g0 ! either negative? + bge 2f ! no, go do the divide + xor %o1, %o0, %g3 ! compute sign in any case + tst %o1 + bge 1f + tst %o0 + ! %o1 is definitely negative; %o0 might also be negative + bge 2f ! if %o0 not negative... + sub %g0, %o1, %o1 ! in any case, make %o1 nonneg +1: ! %o0 is negative, %o1 is nonnegative + sub %g0, %o0, %o0 ! make %o0 nonnegative +2: + + ! Ready to divide. Compute size of quotient; scale comparand. + orcc %o1, %g0, %o5 + bne 1f + mov %o0, %o3 + + ! Divide by zero trap. If it returns, return 0 (about as + ! wrong as possible, but that is what SunOS does...). + ta ST_DIV0 + retl + clr %o0 + +1: + cmp %o3, %o5 ! if %o1 exceeds %o0, done + blu LOC(got_result) ! (and algorithm fails otherwise) + clr %o2 + sethi %hi(1 << (32 - 4 - 1)), %g1 + cmp %o3, %g1 + blu LOC(not_really_big) + clr %o4 + + ! Here the dividend is >= 2**(31-N) or so. We must be careful here, + ! as our usual N-at-a-shot divide step will cause overflow and havoc. + ! The number of bits in the result here is N*ITER+SC, where SC <= N. + ! Compute ITER in an unorthodox manner: know we need to shift V into + ! the top decade: so do not even bother to compare to R. + 1: + cmp %o5, %g1 + bgeu 3f + mov 1, %g2 + sll %o5, 4, %o5 + b 1b + add %o4, 1, %o4 + + ! Now compute %g2. + 2: addcc %o5, %o5, %o5 + bcc LOC(not_too_big) + add %g2, 1, %g2 + + ! We get here if the %o1 overflowed while shifting. + ! This means that %o3 has the high-order bit set. + ! Restore %o5 and subtract from %o3. + sll %g1, 4, %g1 ! high order bit + srl %o5, 1, %o5 ! rest of %o5 + add %o5, %g1, %o5 + b LOC(do_single_div) + sub %g2, 1, %g2 + + LOC(not_too_big): + 3: cmp %o5, %o3 + blu 2b + nop + be LOC(do_single_div) + nop + /* NB: these are commented out in the V8-Sparc manual as well */ + /* (I do not understand this) */ + ! %o5 > %o3: went too far: back up 1 step + ! srl %o5, 1, %o5 + ! dec %g2 + ! do single-bit divide steps + ! + ! We have to be careful here. We know that %o3 >= %o5, so we can do the + ! first divide step without thinking. BUT, the others are conditional, + ! and are only done if %o3 >= 0. Because both %o3 and %o5 may have the high- + ! order bit set in the first step, just falling into the regular + ! division loop will mess up the first time around. + ! So we unroll slightly... + LOC(do_single_div): + subcc %g2, 1, %g2 + bl LOC(end_regular_divide) + nop + sub %o3, %o5, %o3 + mov 1, %o2 + b LOC(end_single_divloop) + nop + LOC(single_divloop): + sll %o2, 1, %o2 + bl 1f + srl %o5, 1, %o5 + ! %o3 >= 0 + sub %o3, %o5, %o3 + b 2f + add %o2, 1, %o2 + 1: ! %o3 < 0 + add %o3, %o5, %o3 + sub %o2, 1, %o2 + 2: + LOC(end_single_divloop): + subcc %g2, 1, %g2 + bge LOC(single_divloop) + tst %o3 + b,a LOC(end_regular_divide) + +LOC(not_really_big): +1: + sll %o5, 4, %o5 + cmp %o5, %o3 + bleu 1b + addcc %o4, 1, %o4 + be LOC(got_result) + sub %o4, 1, %o4 + + tst %o3 ! set up for initial iteration +LOC(divloop): + sll %o2, 4, %o2 + ! depth 1, accumulated bits 0 + bl LOC(1.16) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 2, accumulated bits 1 + bl LOC(2.17) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 3, accumulated bits 3 + bl LOC(3.19) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 4, accumulated bits 7 + bl LOC(4.23) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (7*2+1), %o2 + +LOC(4.23): + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (7*2-1), %o2 + + +LOC(3.19): + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 4, accumulated bits 5 + bl LOC(4.21) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (5*2+1), %o2 + +LOC(4.21): + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (5*2-1), %o2 + + + +LOC(2.17): + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 3, accumulated bits 1 + bl LOC(3.17) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 4, accumulated bits 3 + bl LOC(4.19) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (3*2+1), %o2 + +LOC(4.19): + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (3*2-1), %o2 + + +LOC(3.17): + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 4, accumulated bits 1 + bl LOC(4.17) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (1*2+1), %o2 + +LOC(4.17): + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (1*2-1), %o2 + + + + +LOC(1.16): + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 2, accumulated bits -1 + bl LOC(2.15) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 3, accumulated bits -1 + bl LOC(3.15) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 4, accumulated bits -1 + bl LOC(4.15) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (-1*2+1), %o2 + +LOC(4.15): + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (-1*2-1), %o2 + + +LOC(3.15): + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 4, accumulated bits -3 + bl LOC(4.13) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (-3*2+1), %o2 + +LOC(4.13): + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (-3*2-1), %o2 + + + +LOC(2.15): + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 3, accumulated bits -3 + bl LOC(3.13) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 4, accumulated bits -5 + bl LOC(4.11) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (-5*2+1), %o2 + +LOC(4.11): + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (-5*2-1), %o2 + + +LOC(3.13): + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 4, accumulated bits -7 + bl LOC(4.9) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (-7*2+1), %o2 + +LOC(4.9): + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (-7*2-1), %o2 + + + + + 9: +LOC(end_regular_divide): + subcc %o4, 1, %o4 + bge LOC(divloop) + tst %o3 + bl,a LOC(got_result) + ! non-restoring fixup here (one instruction only!) + sub %o2, 1, %o2 + + +LOC(got_result): + ! check to see if answer should be < 0 + tst %g3 + bl,a 1f + sub %g0, %o2, %o2 +1: + retl + mov %o2, %o0 + +END(.div) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sparcv7/udiv.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sparcv7/udiv.S new file mode 100644 index 00000000..56c64ad0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sparcv7/udiv.S @@ -0,0 +1,343 @@ + /* This file is generated from divrem.m4; DO NOT EDIT! */ +/* + * Division and remainder, from Appendix E of the Sparc Version 8 + * Architecture Manual, with fixes from Gordon Irlam. + */ + +/* + * Input: dividend and divisor in %o0 and %o1 respectively. + * + * m4 parameters: + * .udiv name of function to generate + * div div=div => %o0 / %o1; div=rem => %o0 % %o1 + * false false=true => signed; false=false => unsigned + * + * Algorithm parameters: + * N how many bits per iteration we try to get (4) + * WORDSIZE total number of bits (32) + * + * Derived constants: + * TOPBITS number of bits in the top decade of a number + * + * Important variables: + * Q the partial quotient under development (initially 0) + * R the remainder so far, initially the dividend + * ITER number of main division loop iterations required; + * equal to ceil(log2(quotient) / N). Note that this + * is the log base (2^N) of the quotient. + * V the current comparand, initially divisor*2^(ITER*N-1) + * + * Cost: + * Current estimate for non-large dividend is + * ceil(log2(quotient) / N) * (10 + 7N/2) + C + * A large dividend is one greater than 2^(31-TOPBITS) and takes a + * different path, as the upper bits of the quotient must be developed + * one bit at a time. + */ + + + +ENTRY(.udiv) + + ! Ready to divide. Compute size of quotient; scale comparand. + orcc %o1, %g0, %o5 + bne 1f + mov %o0, %o3 + + ! Divide by zero trap. If it returns, return 0 (about as + ! wrong as possible, but that is what SunOS does...). + ta ST_DIV0 + retl + clr %o0 + +1: + cmp %o3, %o5 ! if %o1 exceeds %o0, done + blu LOC(got_result) ! (and algorithm fails otherwise) + clr %o2 + sethi %hi(1 << (32 - 4 - 1)), %g1 + cmp %o3, %g1 + blu LOC(not_really_big) + clr %o4 + + ! Here the dividend is >= 2**(31-N) or so. We must be careful here, + ! as our usual N-at-a-shot divide step will cause overflow and havoc. + ! The number of bits in the result here is N*ITER+SC, where SC <= N. + ! Compute ITER in an unorthodox manner: know we need to shift V into + ! the top decade: so do not even bother to compare to R. + 1: + cmp %o5, %g1 + bgeu 3f + mov 1, %g2 + sll %o5, 4, %o5 + b 1b + add %o4, 1, %o4 + + ! Now compute %g2. + 2: addcc %o5, %o5, %o5 + bcc LOC(not_too_big) + add %g2, 1, %g2 + + ! We get here if the %o1 overflowed while shifting. + ! This means that %o3 has the high-order bit set. + ! Restore %o5 and subtract from %o3. + sll %g1, 4, %g1 ! high order bit + srl %o5, 1, %o5 ! rest of %o5 + add %o5, %g1, %o5 + b LOC(do_single_div) + sub %g2, 1, %g2 + + LOC(not_too_big): + 3: cmp %o5, %o3 + blu 2b + nop + be LOC(do_single_div) + nop + /* NB: these are commented out in the V8-Sparc manual as well */ + /* (I do not understand this) */ + ! %o5 > %o3: went too far: back up 1 step + ! srl %o5, 1, %o5 + ! dec %g2 + ! do single-bit divide steps + ! + ! We have to be careful here. We know that %o3 >= %o5, so we can do the + ! first divide step without thinking. BUT, the others are conditional, + ! and are only done if %o3 >= 0. Because both %o3 and %o5 may have the high- + ! order bit set in the first step, just falling into the regular + ! division loop will mess up the first time around. + ! So we unroll slightly... + LOC(do_single_div): + subcc %g2, 1, %g2 + bl LOC(end_regular_divide) + nop + sub %o3, %o5, %o3 + mov 1, %o2 + b LOC(end_single_divloop) + nop + LOC(single_divloop): + sll %o2, 1, %o2 + bl 1f + srl %o5, 1, %o5 + ! %o3 >= 0 + sub %o3, %o5, %o3 + b 2f + add %o2, 1, %o2 + 1: ! %o3 < 0 + add %o3, %o5, %o3 + sub %o2, 1, %o2 + 2: + LOC(end_single_divloop): + subcc %g2, 1, %g2 + bge LOC(single_divloop) + tst %o3 + b,a LOC(end_regular_divide) + +LOC(not_really_big): +1: + sll %o5, 4, %o5 + cmp %o5, %o3 + bleu 1b + addcc %o4, 1, %o4 + be LOC(got_result) + sub %o4, 1, %o4 + + tst %o3 ! set up for initial iteration +LOC(divloop): + sll %o2, 4, %o2 + ! depth 1, accumulated bits 0 + bl LOC(1.16) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 2, accumulated bits 1 + bl LOC(2.17) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 3, accumulated bits 3 + bl LOC(3.19) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 4, accumulated bits 7 + bl LOC(4.23) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (7*2+1), %o2 + +LOC(4.23): + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (7*2-1), %o2 + + +LOC(3.19): + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 4, accumulated bits 5 + bl LOC(4.21) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (5*2+1), %o2 + +LOC(4.21): + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (5*2-1), %o2 + + + +LOC(2.17): + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 3, accumulated bits 1 + bl LOC(3.17) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 4, accumulated bits 3 + bl LOC(4.19) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (3*2+1), %o2 + +LOC(4.19): + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (3*2-1), %o2 + + +LOC(3.17): + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 4, accumulated bits 1 + bl LOC(4.17) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (1*2+1), %o2 + +LOC(4.17): + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (1*2-1), %o2 + + + + +LOC(1.16): + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 2, accumulated bits -1 + bl LOC(2.15) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 3, accumulated bits -1 + bl LOC(3.15) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 4, accumulated bits -1 + bl LOC(4.15) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (-1*2+1), %o2 + +LOC(4.15): + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (-1*2-1), %o2 + + +LOC(3.15): + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 4, accumulated bits -3 + bl LOC(4.13) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (-3*2+1), %o2 + +LOC(4.13): + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (-3*2-1), %o2 + + + +LOC(2.15): + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 3, accumulated bits -3 + bl LOC(3.13) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 4, accumulated bits -5 + bl LOC(4.11) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (-5*2+1), %o2 + +LOC(4.11): + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (-5*2-1), %o2 + + +LOC(3.13): + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 4, accumulated bits -7 + bl LOC(4.9) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (-7*2+1), %o2 + +LOC(4.9): + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (-7*2-1), %o2 + + + + + 9: +LOC(end_regular_divide): + subcc %o4, 1, %o4 + bge LOC(divloop) + tst %o3 + bl,a LOC(got_result) + ! non-restoring fixup here (one instruction only!) + sub %o2, 1, %o2 + + +LOC(got_result): + + retl + mov %o2, %o0 + +END(.udiv) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sparcv7/umul.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sparcv7/umul.S new file mode 100644 index 00000000..50b3157d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sparcv7/umul.S @@ -0,0 +1,153 @@ +/* + * Unsigned multiply. Returns %o0 * %o1 in %o1%o0 (i.e., %o1 holds the + * upper 32 bits of the 64-bit product). + * + * This code optimizes short (less than 13-bit) multiplies. Short + * multiplies require 25 instruction cycles, and long ones require + * 45 instruction cycles. + * + * On return, overflow has occurred (%o1 is not zero) if and only if + * the Z condition code is clear, allowing, e.g., the following: + * + * call .umul + * nop + * bnz overflow (or tnz) + */ + +ENTRY(.umul) + or %o0, %o1, %o4 + mov %o0, %y ! multiplier -> Y + andncc %o4, 0xfff, %g0 ! test bits 12..31 of *both* args + be LOC(mul_shortway) ! if zero, can do it the short way + andcc %g0, %g0, %o4 ! zero the partial product; clear N & V + + /* + * Long multiply. 32 steps, followed by a final shift step. + */ + mulscc %o4, %o1, %o4 ! 1 + mulscc %o4, %o1, %o4 ! 2 + mulscc %o4, %o1, %o4 ! 3 + mulscc %o4, %o1, %o4 ! 4 + mulscc %o4, %o1, %o4 ! 5 + mulscc %o4, %o1, %o4 ! 6 + mulscc %o4, %o1, %o4 ! 7 + mulscc %o4, %o1, %o4 ! 8 + mulscc %o4, %o1, %o4 ! 9 + mulscc %o4, %o1, %o4 ! 10 + mulscc %o4, %o1, %o4 ! 11 + mulscc %o4, %o1, %o4 ! 12 + mulscc %o4, %o1, %o4 ! 13 + mulscc %o4, %o1, %o4 ! 14 + mulscc %o4, %o1, %o4 ! 15 + mulscc %o4, %o1, %o4 ! 16 + mulscc %o4, %o1, %o4 ! 17 + mulscc %o4, %o1, %o4 ! 18 + mulscc %o4, %o1, %o4 ! 19 + mulscc %o4, %o1, %o4 ! 20 + mulscc %o4, %o1, %o4 ! 21 + mulscc %o4, %o1, %o4 ! 22 + mulscc %o4, %o1, %o4 ! 23 + mulscc %o4, %o1, %o4 ! 24 + mulscc %o4, %o1, %o4 ! 25 + mulscc %o4, %o1, %o4 ! 26 + mulscc %o4, %o1, %o4 ! 27 + mulscc %o4, %o1, %o4 ! 28 + mulscc %o4, %o1, %o4 ! 29 + mulscc %o4, %o1, %o4 ! 30 + mulscc %o4, %o1, %o4 ! 31 + mulscc %o4, %o1, %o4 ! 32 + mulscc %o4, %g0, %o4 ! final shift + + /* + * Normally, with the shift-and-add approach, if both numbers are + * positive you get the correct result. With 32-bit two's-complement + * numbers, -x is represented as + * + * x 32 + * ( 2 - ------ ) mod 2 * 2 + * 32 + * 2 + * + * (the `mod 2' subtracts 1 from 1.bbbb). To avoid lots of 2^32s, + * we can treat this as if the radix point were just to the left + * of the sign bit (multiply by 2^32), and get + * + * -x = (2 - x) mod 2 + * + * Then, ignoring the `mod 2's for convenience: + * + * x * y = xy + * -x * y = 2y - xy + * x * -y = 2x - xy + * -x * -y = 4 - 2x - 2y + xy + * + * For signed multiplies, we subtract (x << 32) from the partial + * product to fix this problem for negative multipliers (see mul.s). + * Because of the way the shift into the partial product is calculated + * (N xor V), this term is automatically removed for the multiplicand, + * so we don't have to adjust. + * + * But for unsigned multiplies, the high order bit wasn't a sign bit, + * and the correction is wrong. So for unsigned multiplies where the + * high order bit is one, we end up with xy - (y << 32). To fix it + * we add y << 32. + */ +#if 0 + tst %o1 + bl,a 1f ! if %o1 < 0 (high order bit = 1), + add %o4, %o0, %o4 ! %o4 += %o0 (add y to upper half) +1: rd %y, %o0 ! get lower half of product + retl + addcc %o4, %g0, %o1 ! put upper half in place and set Z for %o1==0 +#else + /* Faster code from tege@sics.se. */ + sra %o1, 31, %o2 ! make mask from sign bit + and %o0, %o2, %o2 ! %o2 = 0 or %o0, depending on sign of %o1 + rd %y, %o0 ! get lower half of product + retl + addcc %o4, %o2, %o1 ! add compensation and put upper half in place +#endif + +LOC(mul_shortway): + /* + * Short multiply. 12 steps, followed by a final shift step. + * The resulting bits are off by 12 and (32-12) = 20 bit positions, + * but there is no problem with %o0 being negative (unlike above), + * and overflow is impossible (the answer is at most 24 bits long). + */ + mulscc %o4, %o1, %o4 ! 1 + mulscc %o4, %o1, %o4 ! 2 + mulscc %o4, %o1, %o4 ! 3 + mulscc %o4, %o1, %o4 ! 4 + mulscc %o4, %o1, %o4 ! 5 + mulscc %o4, %o1, %o4 ! 6 + mulscc %o4, %o1, %o4 ! 7 + mulscc %o4, %o1, %o4 ! 8 + mulscc %o4, %o1, %o4 ! 9 + mulscc %o4, %o1, %o4 ! 10 + mulscc %o4, %o1, %o4 ! 11 + mulscc %o4, %o1, %o4 ! 12 + mulscc %o4, %g0, %o4 ! final shift + + /* + * %o4 has 20 of the bits that should be in the result; %y has + * the bottom 12 (as %y's top 12). That is: + * + * %o4 %y + * +----------------+----------------+ + * | -12- | -20- | -12- | -20- | + * +------(---------+------)---------+ + * -----result----- + * + * The 12 bits of %o4 left of the `result' area are all zero; + * in fact, all top 20 bits of %o4 are zero. + */ + + rd %y, %o5 + sll %o4, 12, %o0 ! shift middle bits left 12 + srl %o5, 20, %o5 ! shift low bits right 20 + or %o5, %o0, %o0 + retl + addcc %g0, %g0, %o1 ! %o1 = zero, and set Z + +END(.umul) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sparcv7/urem.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sparcv7/urem.S new file mode 100644 index 00000000..ecf34672 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sparcv7/urem.S @@ -0,0 +1,343 @@ + /* This file is generated from divrem.m4; DO NOT EDIT! */ +/* + * Division and remainder, from Appendix E of the Sparc Version 8 + * Architecture Manual, with fixes from Gordon Irlam. + */ + +/* + * Input: dividend and divisor in %o0 and %o1 respectively. + * + * m4 parameters: + * .urem name of function to generate + * rem rem=div => %o0 / %o1; rem=rem => %o0 % %o1 + * false false=true => signed; false=false => unsigned + * + * Algorithm parameters: + * N how many bits per iteration we try to get (4) + * WORDSIZE total number of bits (32) + * + * Derived constants: + * TOPBITS number of bits in the top decade of a number + * + * Important variables: + * Q the partial quotient under development (initially 0) + * R the remainder so far, initially the dividend + * ITER number of main division loop iterations required; + * equal to ceil(log2(quotient) / N). Note that this + * is the log base (2^N) of the quotient. + * V the current comparand, initially divisor*2^(ITER*N-1) + * + * Cost: + * Current estimate for non-large dividend is + * ceil(log2(quotient) / N) * (10 + 7N/2) + C + * A large dividend is one greater than 2^(31-TOPBITS) and takes a + * different path, as the upper bits of the quotient must be developed + * one bit at a time. + */ + + + +ENTRY(.urem) + + ! Ready to divide. Compute size of quotient; scale comparand. + orcc %o1, %g0, %o5 + bne 1f + mov %o0, %o3 + + ! Divide by zero trap. If it returns, return 0 (about as + ! wrong as possible, but that is what SunOS does...). + ta ST_DIV0 + retl + clr %o0 + +1: + cmp %o3, %o5 ! if %o1 exceeds %o0, done + blu LOC(got_result) ! (and algorithm fails otherwise) + clr %o2 + sethi %hi(1 << (32 - 4 - 1)), %g1 + cmp %o3, %g1 + blu LOC(not_really_big) + clr %o4 + + ! Here the dividend is >= 2**(31-N) or so. We must be careful here, + ! as our usual N-at-a-shot divide step will cause overflow and havoc. + ! The number of bits in the result here is N*ITER+SC, where SC <= N. + ! Compute ITER in an unorthodox manner: know we need to shift V into + ! the top decade: so do not even bother to compare to R. + 1: + cmp %o5, %g1 + bgeu 3f + mov 1, %g2 + sll %o5, 4, %o5 + b 1b + add %o4, 1, %o4 + + ! Now compute %g2. + 2: addcc %o5, %o5, %o5 + bcc LOC(not_too_big) + add %g2, 1, %g2 + + ! We get here if the %o1 overflowed while shifting. + ! This means that %o3 has the high-order bit set. + ! Restore %o5 and subtract from %o3. + sll %g1, 4, %g1 ! high order bit + srl %o5, 1, %o5 ! rest of %o5 + add %o5, %g1, %o5 + b LOC(do_single_div) + sub %g2, 1, %g2 + + LOC(not_too_big): + 3: cmp %o5, %o3 + blu 2b + nop + be LOC(do_single_div) + nop + /* NB: these are commented out in the V8-Sparc manual as well */ + /* (I do not understand this) */ + ! %o5 > %o3: went too far: back up 1 step + ! srl %o5, 1, %o5 + ! dec %g2 + ! do single-bit divide steps + ! + ! We have to be careful here. We know that %o3 >= %o5, so we can do the + ! first divide step without thinking. BUT, the others are conditional, + ! and are only done if %o3 >= 0. Because both %o3 and %o5 may have the high- + ! order bit set in the first step, just falling into the regular + ! division loop will mess up the first time around. + ! So we unroll slightly... + LOC(do_single_div): + subcc %g2, 1, %g2 + bl LOC(end_regular_divide) + nop + sub %o3, %o5, %o3 + mov 1, %o2 + b LOC(end_single_divloop) + nop + LOC(single_divloop): + sll %o2, 1, %o2 + bl 1f + srl %o5, 1, %o5 + ! %o3 >= 0 + sub %o3, %o5, %o3 + b 2f + add %o2, 1, %o2 + 1: ! %o3 < 0 + add %o3, %o5, %o3 + sub %o2, 1, %o2 + 2: + LOC(end_single_divloop): + subcc %g2, 1, %g2 + bge LOC(single_divloop) + tst %o3 + b,a LOC(end_regular_divide) + +LOC(not_really_big): +1: + sll %o5, 4, %o5 + cmp %o5, %o3 + bleu 1b + addcc %o4, 1, %o4 + be LOC(got_result) + sub %o4, 1, %o4 + + tst %o3 ! set up for initial iteration +LOC(divloop): + sll %o2, 4, %o2 + ! depth 1, accumulated bits 0 + bl LOC(1.16) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 2, accumulated bits 1 + bl LOC(2.17) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 3, accumulated bits 3 + bl LOC(3.19) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 4, accumulated bits 7 + bl LOC(4.23) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (7*2+1), %o2 + +LOC(4.23): + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (7*2-1), %o2 + + +LOC(3.19): + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 4, accumulated bits 5 + bl LOC(4.21) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (5*2+1), %o2 + +LOC(4.21): + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (5*2-1), %o2 + + + +LOC(2.17): + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 3, accumulated bits 1 + bl LOC(3.17) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 4, accumulated bits 3 + bl LOC(4.19) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (3*2+1), %o2 + +LOC(4.19): + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (3*2-1), %o2 + + +LOC(3.17): + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 4, accumulated bits 1 + bl LOC(4.17) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (1*2+1), %o2 + +LOC(4.17): + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (1*2-1), %o2 + + + + +LOC(1.16): + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 2, accumulated bits -1 + bl LOC(2.15) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 3, accumulated bits -1 + bl LOC(3.15) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 4, accumulated bits -1 + bl LOC(4.15) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (-1*2+1), %o2 + +LOC(4.15): + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (-1*2-1), %o2 + + +LOC(3.15): + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 4, accumulated bits -3 + bl LOC(4.13) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (-3*2+1), %o2 + +LOC(4.13): + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (-3*2-1), %o2 + + + +LOC(2.15): + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 3, accumulated bits -3 + bl LOC(3.13) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + ! depth 4, accumulated bits -5 + bl LOC(4.11) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (-5*2+1), %o2 + +LOC(4.11): + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (-5*2-1), %o2 + + +LOC(3.13): + ! remainder is negative + addcc %o3,%o5,%o3 + ! depth 4, accumulated bits -7 + bl LOC(4.9) + srl %o5,1,%o5 + ! remainder is positive + subcc %o3,%o5,%o3 + b 9f + add %o2, (-7*2+1), %o2 + +LOC(4.9): + ! remainder is negative + addcc %o3,%o5,%o3 + b 9f + add %o2, (-7*2-1), %o2 + + + + + 9: +LOC(end_regular_divide): + subcc %o4, 1, %o4 + bge LOC(divloop) + tst %o3 + bl,a LOC(got_result) + ! non-restoring fixup here (one instruction only!) + add %o3, %o1, %o3 + + +LOC(got_result): + + retl + mov %o3, %o0 + +END(.urem) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sparcv8/rem.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sparcv8/rem.S new file mode 100644 index 00000000..c4faebe8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sparcv8/rem.S @@ -0,0 +1,19 @@ +/* + * Sparc v8 has divide. + */ + +ENTRY(.rem) + + sra %o0, 31, %o2 + wr %o2, 0, %y + nop + nop + nop + sdivcc %o0, %o1, %o2 + bvs,a 1f + xnor %o2, %g0, %o2 +1: smul %o2, %o1, %o2 + retl + sub %o0, %o2, %o0 + +END(.rem) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sparcv8/sdiv.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sparcv8/sdiv.S new file mode 100644 index 00000000..4ac901a7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sparcv8/sdiv.S @@ -0,0 +1,18 @@ +/* + * Sparc v8 has divide. + */ + +ENTRY(.div) + + sra %o0, 31, %o2 + wr %o2, 0, %y + nop + nop + nop + sdivcc %o0, %o1, %o0 + bvs,a 1f + xnor %o0, %g0, %o0 +1: retl + nop + +END(.div) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sparcv8/udiv.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sparcv8/udiv.S new file mode 100644 index 00000000..d5d93bb8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sparcv8/udiv.S @@ -0,0 +1,13 @@ +/* + * Sparc v8 has divide. + */ + +ENTRY(.udiv) + + wr %g0, 0, %y + nop + nop + retl + udiv %o0, %o1, %o0 + +END(.udiv) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sparcv8/umul.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sparcv8/umul.S new file mode 100644 index 00000000..47b98e9c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sparcv8/umul.S @@ -0,0 +1,11 @@ +/* + * Sparc v8 has multiply. + */ + +ENTRY(.umul) + + umul %o0, %o1, %o0 + retl + rd %y, %o1 + +END(.umul) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sparcv8/urem.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sparcv8/urem.S new file mode 100644 index 00000000..0e96246f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sparcv8/urem.S @@ -0,0 +1,16 @@ +/* + * Sparc v8 has divide. + */ + +ENTRY(.urem) + + wr %g0, 0, %y + nop + nop + nop + udiv %o0, %o1, %o2 + umul %o2, %o1, %o2 + retl + sub %o0, %o2, %o0 + +END(.urem) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sparcv9/clone.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sparcv9/clone.S new file mode 100644 index 00000000..9d101e23 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sparcv9/clone.S @@ -0,0 +1,102 @@ +/* Copyright (C) 1997, 2000, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson (rth@tamu.edu). + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* clone() is even more special than fork() as it mucks with stacks + and invokes a function in the right context after its all over. */ + +#include +#include +#include +#include + +#define CLONE_VM 0x00000100 +#define CLONE_THREAD 0x00010000 + +/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg, + pid_t *ptid, void *tls, pid_t *ctid); */ + + .register %g2,#scratch + .register %g3,#scratch + + .text + +ENTRY (__clone) + save %sp, -192, %sp + cfi_def_cfa_register(%fp) + cfi_window_save + cfi_register(%o7, %i7) + + /* sanity check arguments */ + brz,pn %i0, 99f /* fn non-NULL? */ + mov %i0, %g2 + brz,pn %i1, 99f /* child_stack non-NULL? */ + mov %i2, %o0 /* clone flags */ + + /* The child_stack is the top of the stack, allocate one + whole stack frame from that as this is what the kernel + expects. Also, subtract STACK_BIAS. */ + sub %i1, 192 + 0x7ff, %o1 + mov %i3, %g3 + mov %i2, %g4 + + mov %i4,%o2 /* PTID */ + mov %i5,%o3 /* TLS */ + ldx [%fp+0x7ff+176],%o4 /* CTID */ + + /* Do the system call */ + set __NR_clone, %g1 + ta 0x6d + bcs,pn %xcc, 98f + nop + brnz,pn %o1, __thread_start + nop + jmpl %i7 + 8, %g0 + restore %o0, %g0, %o0 +99: mov EINVAL, %o0 +98: call HIDDEN_JUMPTARGET(__errno_location) + mov %o0, %i0 + st %i0, [%o0] + jmpl %i7 + 8, %g0 + restore %g0,-1,%o0 +END(__clone) + + .type __thread_start,@function +__thread_start: +#ifdef RESET_PID + sethi %hi(CLONE_THREAD), %l0 + andcc %g4, %l0, %g0 + bne,pt %icc, 1f + andcc %g4, CLONE_VM, %g0 + bne,a,pn %icc, 2f + mov -1,%o0 + set __NR_getpid,%g1 + ta 0x6d +2: st %o0,[%g7 + PID] + st %o0,[%g7 + TID] +1: +#endif + mov %g0, %fp /* terminate backtrace */ + call %g2 + mov %g3,%o0 + call HIDDEN_JUMPTARGET(_exit),0 + nop + + .size __thread_start, .-__thread_start + +weak_alias (__clone, clone) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sparcv9/rem.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sparcv9/rem.S new file mode 100644 index 00000000..1474e32a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sparcv9/rem.S @@ -0,0 +1,20 @@ +/* + * Sparc v9 has divide. + * As divx takes 68 cycles and sdivcc only 36, + * we use sdivcc eventhough it is deprecated. + */ + + .text + .align 32 +ENTRY(.rem) + + sra %o0, 31, %o2 + wr %o2, 0, %y + sdivcc %o0, %o1, %o2 + xnor %o2, %g0, %o3 + movvs %icc, %o3, %o2 + smul %o2, %o1, %o2 + retl + sub %o0, %o2, %o0 + +END(.rem) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sparcv9/sdiv.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sparcv9/sdiv.S new file mode 100644 index 00000000..45535bb6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sparcv9/sdiv.S @@ -0,0 +1,18 @@ +/* + * Sparc v9 has divide. + * As divx takes 68 cycles and sdivcc only 36, + * we use sdivcc eventhough it is deprecated. + */ + + .text + .align 32 +ENTRY(.div) + + sra %o0, 31, %o2 + wr %o2, 0, %y + sdivcc %o0, %o1, %o0 + xnor %o0, %g0, %o2 + retl + movvs %icc, %o2, %o0 + +END(.div) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sparcv9/udiv.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sparcv9/udiv.S new file mode 100644 index 00000000..303f29bd --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sparcv9/udiv.S @@ -0,0 +1,15 @@ +/* + * Sparc v9 has divide. + * As divx takes 68 cycles and udiv only 37, + * we use udiv eventhough it is deprecated. + */ + + .text + .align 32 +ENTRY(.udiv) + + wr %g0, 0, %y + retl + udiv %o0, %o1, %o0 + +END(.udiv) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sparcv9/umul.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sparcv9/umul.S new file mode 100644 index 00000000..e65e4b95 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sparcv9/umul.S @@ -0,0 +1,15 @@ +/* + * Sparc v9 has multiply. + */ + + .text + .align 32 +ENTRY(.umul) + + srl %o0, 0, %o0 + srl %o1, 0, %o1 + mulx %o0, %o1, %o0 + retl + srlx %o0, 32, %o1 + +END(.umul) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sparcv9/urem.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sparcv9/urem.S new file mode 100644 index 00000000..93542698 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sparcv9/urem.S @@ -0,0 +1,17 @@ +/* + * Sparc v9 has divide. + * As divx takes 68 cycles and udiv only 37, + * we use udiv eventhough it is deprecated. + */ + + .text + .align 32 +ENTRY(.urem) + + wr %g0, 0, %y + udiv %o0, %o1, %o2 + umul %o2, %o1, %o2 + retl + sub %o0, %o2, %o0 + +END(.urem) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sys/procfs.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sys/procfs.h new file mode 100644 index 00000000..2827b1ec --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sys/procfs.h @@ -0,0 +1,211 @@ +/* Copyright (C) 1996, 1997, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_PROCFS_H +#define _SYS_PROCFS_H 1 + +/* This is somehow modelled after the file of the same name on SysVr4 + systems. It provides a definition of the core file format for ELF + used on Linux. */ + +#include +#include +#include +#include +#include +#include +#include + +__BEGIN_DECLS + +#if __WORDSIZE == 64 + +#define ELF_NGREG 36 + +typedef struct + { + unsigned long pr_regs[32]; + unsigned long pr_fsr; + unsigned long pr_gsr; + unsigned long pr_fprs; + } elf_fpregset_t; + +#else /* sparc32 */ + +#define ELF_NGREG 38 + +typedef struct + { + union + { + unsigned long pr_regs[32]; + double pr_dregs[16]; + } pr_fr; + unsigned long __unused; + unsigned long pr_fsr; + unsigned char pr_qcnt; + unsigned char pr_q_entrysize; + unsigned char pr_en; + unsigned int pr_q[64]; + } elf_fpregset_t; + +#endif /* sparc32 */ + +typedef unsigned long elf_greg_t; +typedef elf_greg_t elf_gregset_t[ELF_NGREG]; + +struct elf_siginfo + { + int si_signo; /* Signal number. */ + int si_code; /* Extra code. */ + int si_errno; /* Errno. */ + }; + +/* Definitions to generate Intel SVR4-like core files. These mostly + have the same names as the SVR4 types with "elf_" tacked on the + front to prevent clashes with linux definitions, and the typedef + forms have been avoided. This is mostly like the SVR4 structure, + but more Linuxy, with things that Linux does not support and which + gdb doesn't really use excluded. Fields present but not used are + marked with "XXX". */ +struct elf_prstatus + { + struct elf_siginfo pr_info; /* Info associated with signal. */ + short int pr_cursig; /* Current signal. */ + unsigned long int pr_sigpend; /* Set of pending signals. */ + unsigned long int pr_sighold; /* Set of held signals. */ + __pid_t pr_pid; + __pid_t pr_ppid; + __pid_t pr_pgrp; + __pid_t pr_sid; + struct timeval pr_utime; /* User time. */ + struct timeval pr_stime; /* System time. */ + struct timeval pr_cutime; /* Cumulative user time. */ + struct timeval pr_cstime; /* Cumulative system time. */ + elf_gregset_t pr_reg; /* GP registers. */ + int pr_fpvalid; /* True if math copro being used. */ + }; + + +#define ELF_PRARGSZ (80) /* Number of chars for args */ + +struct elf_prpsinfo + { + char pr_state; /* Numeric process state. */ + char pr_sname; /* Char for pr_state. */ + char pr_zomb; /* Zombie. */ + char pr_nice; /* Nice val. */ + unsigned long int pr_flag; /* Flags. */ +#if __WORDSIZE == 64 + unsigned int pr_uid; + unsigned int pr_gid; +#else + unsigned short int pr_uid; + unsigned short int pr_gid; +#endif + int pr_pid, pr_ppid, pr_pgrp, pr_sid; + /* Lots missing */ + char pr_fname[16]; /* Filename of executable. */ + char pr_psargs[ELF_PRARGSZ]; /* Initial part of arg list. */ + }; + +/* Addresses. */ +typedef void *psaddr_t; + +/* Register sets. Linux has different names. */ +typedef elf_gregset_t prgregset_t; +typedef elf_fpregset_t prfpregset_t; + +/* We don't have any differences between processes and threads, + therefore have only one PID type. */ +typedef __pid_t lwpid_t; + + +typedef struct elf_prstatus prstatus_t; +typedef struct elf_prpsinfo prpsinfo_t; + +#if __WORDSIZE == 64 + +/* Provide 32-bit variants so that BFD can read 32-bit + core files. */ +#define ELF_NGREG32 38 +typedef struct + { + union + { + unsigned int pr_regs[32]; + double pr_dregs[16]; + } pr_fr; + unsigned int __unused; + unsigned int pr_fsr; + unsigned char pr_qcnt; + unsigned char pr_q_entrysize; + unsigned char pr_en; + unsigned int pr_q[64]; + } elf_fpregset_t32; + +typedef unsigned int elf_greg_t32; +typedef elf_greg_t32 elf_gregset_t32[ELF_NGREG32]; + +struct elf_prstatus32 + { + struct elf_siginfo pr_info; /* Info associated with signal. */ + short int pr_cursig; /* Current signal. */ + unsigned int pr_sigpend; /* Set of pending signals. */ + unsigned int pr_sighold; /* Set of held signals. */ + __pid_t pr_pid; + __pid_t pr_ppid; + __pid_t pr_pgrp; + __pid_t pr_sid; + struct + { + int tv_sec, tv_usec; + } pr_utime, /* User time. */ + pr_stime, /* System time. */ + pr_cutime, /* Cumulative user time. */ + pr_cstime; /* Cumulative system time. */ + elf_gregset_t32 pr_reg; /* GP registers. */ + int pr_fpvalid; /* True if math copro being used. */ + }; + +struct elf_prpsinfo32 + { + char pr_state; /* Numeric process state. */ + char pr_sname; /* Char for pr_state. */ + char pr_zomb; /* Zombie. */ + char pr_nice; /* Nice val. */ + unsigned int pr_flag; /* Flags. */ + unsigned short int pr_uid; + unsigned short int pr_gid; + int pr_pid, pr_ppid, pr_pgrp, pr_sid; + /* Lots missing */ + char pr_fname[16]; /* Filename of executable. */ + char pr_psargs[ELF_PRARGSZ]; /* Initial part of arg list. */ + }; + +typedef elf_gregset_t32 prgregset32_t; +typedef elf_fpregset_t32 prfpregset32_t; + +typedef struct elf_prstatus32 prstatus32_t; +typedef struct elf_prpsinfo32 prpsinfo32_t; + +#endif /* sparc64 */ + +__END_DECLS + +#endif /* sys/procfs.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sys/ptrace.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sys/ptrace.h new file mode 100644 index 00000000..d573f0e9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sys/ptrace.h @@ -0,0 +1,183 @@ +/* `ptrace' debugger support interface. Linux/SPARC version. + Copyright (C) 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_PTRACE_H +#define _SYS_PTRACE_H 1 + +#include + +#include + +/* Linux/SPARC kernels up to 2.3.18 do not care much + about what namespace polution, so use a kludge now. */ +#undef PTRACE_GETREGS +#undef PTRACE_SETREGS +#undef PTRACE_GETFPREGS +#undef PTRACE_SETFPREGS +#undef PTRACE_READDATA +#undef PTRACE_WRITEDATA +#undef PTRACE_READTEXT +#undef PTRACE_WRITETEXT +#undef PTRACE_SUNDETACH + +__BEGIN_DECLS + +/* Type of the REQUEST argument to `ptrace.' */ +enum __ptrace_request +{ + /* Indicate that the process making this request should be traced. + All signals received by this process can be intercepted by its + parent, and its parent can use the other `ptrace' requests. */ + PTRACE_TRACEME = 0, +#define PT_TRACE_ME PTRACE_TRACEME + + /* Return the word in the process's text space at address ADDR. */ + PTRACE_PEEKTEXT = 1, +#define PT_READ_I PTRACE_PEEKTEXT + + /* Return the word in the process's data space at address ADDR. */ + PTRACE_PEEKDATA = 2, +#define PT_READ_D PTRACE_PEEKDATA + + /* Return the word in the process's user area at offset ADDR. */ + PTRACE_PEEKUSER = 3, +#define PT_READ_U PTRACE_PEEKUSER + + /* Write the word DATA into the process's text space at address ADDR. */ + PTRACE_POKETEXT = 4, +#define PT_WRITE_I PTRACE_POKETEXT + + /* Write the word DATA into the process's data space at address ADDR. */ + PTRACE_POKEDATA = 5, +#define PT_WRITE_D PTRACE_POKEDATA + + /* Write the word DATA into the process's user area at offset ADDR. */ + PTRACE_POKEUSER = 6, +#define PT_WRITE_U PTRACE_POKEUSER + + /* Continue the process. */ + PTRACE_CONT = 7, +#define PT_CONTINUE PTRACE_CONT + + /* Kill the process. */ + PTRACE_KILL = 8, +#define PT_KILL PTRACE_KILL + + /* Single step the process. + This is not supported on all machines. */ + PTRACE_SINGLESTEP = 9, +#define PT_STEP PTRACE_SINGLESTEP + + /* Detach from a process attached to with PTRACE_ATTACH. */ + PTRACE_DETACH = 11, +#define PT_DETACH PTRACE_DETACH + + /* This define is needed for older programs which were + trying to work around sparc-linux ptrace nastiness. */ +#define PTRACE_SUNDETACH PTRACE_DETACH + +#if __WORDSIZE == 32 + + /* Get all general purpose registers used by a processes. + This is not supported on all machines. */ + PTRACE_GETREGS = 12, +#define PT_GETREGS PTRACE_GETREGS + + /* Set all general purpose registers used by a processes. + This is not supported on all machines. */ + PTRACE_SETREGS = 13, +#define PT_SETREGS PTRACE_SETREGS + + /* Get all floating point registers used by a processes. + This is not supported on all machines. */ + PTRACE_GETFPREGS = 14, +#define PT_GETFPREGS PTRACE_GETFPREGS + + /* Set all floating point registers used by a processes. + This is not supported on all machines. */ + PTRACE_SETFPREGS = 15, +#define PT_SETFPREGS PTRACE_SETFPREGS + +#endif + + /* Attach to a process that is already running. */ + PTRACE_ATTACH = 16, +#define PT_ATTACH PTRACE_ATTACH + + /* Write several bytes at a time. */ + PTRACE_WRITEDATA = 17, +#define PTRACE_WRITEDATA PTRACE_WRITEDATA + + /* Read several bytes at a time. */ + PTRACE_READTEXT = 18, +#define PTRACE_READTEXT PTRACE_READTEXT +#define PTRACE_READDATA PTRACE_READTEXT + + /* Write several bytes at a time. */ + PTRACE_WRITETEXT = 19, +#define PTRACE_WRITETEXT PTRACE_WRITETEXT + +#if __WORDSIZE == 64 + + /* Get all general purpose registers used by a processes. + This is not supported on all machines. */ + PTRACE_GETREGS = 22, +#define PT_GETREGS PTRACE_GETREGS + + /* Set all general purpose registers used by a processes. + This is not supported on all machines. */ + PTRACE_SETREGS = 23, +#define PT_SETREGS PTRACE_SETREGS + +#endif + + /* Continue and stop at the next (return from) syscall. */ + PTRACE_SYSCALL = 24 +#define PTRACE_SYSCALL PTRACE_SYSCALL + +#if __WORDSIZE == 64 + + , + /* Get all floating point registers used by a processes. + This is not supported on all machines. */ + PTRACE_GETFPREGS = 25, +#define PT_GETFPREGS PTRACE_GETFPREGS + + /* Set all floating point registers used by a processes. + This is not supported on all machines. */ + PTRACE_SETFPREGS = 26 +#define PT_SETFPREGS PTRACE_SETFPREGS + +#endif +}; + +/* Perform process tracing functions. REQUEST is one of the values + above, and determines the action to be taken. + For all requests except PTRACE_TRACEME, PID specifies the process to be + traced. + + PID and the other arguments described above for the various requests should + appear (those that are used for the particular request) as: + pid_t PID, void *ADDR, int DATA, void *ADDR2 + after REQUEST. */ +extern long int ptrace (enum __ptrace_request __request, ...) __THROW; + +__END_DECLS + +#endif /* _SYS_PTRACE_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sys/ucontext.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sys/ucontext.h new file mode 100644 index 00000000..b1102b04 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sys/ucontext.h @@ -0,0 +1,270 @@ +/* Copyright (C) 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_UCONTEXT_H +#define _SYS_UCONTEXT_H 1 + +#include +#include +#include + +#if __WORDSIZE == 64 + +#define MC_TSTATE 0 +#define MC_PC 1 +#define MC_NPC 2 +#define MC_Y 3 +#define MC_G1 4 +#define MC_G2 5 +#define MC_G3 6 +#define MC_G4 7 +#define MC_G5 8 +#define MC_G6 9 +#define MC_G7 10 +#define MC_O0 11 +#define MC_O1 12 +#define MC_O2 13 +#define MC_O3 14 +#define MC_O4 15 +#define MC_O5 16 +#define MC_O6 17 +#define MC_O7 18 +#define MC_NGREG 19 + +typedef unsigned long mc_greg_t; +typedef mc_greg_t mc_gregset_t[MC_NGREG]; + +#define MC_MAXFPQ 16 +struct mc_fq { + unsigned long *mcfq_addr; + unsigned int mcfq_insn; +}; + +struct mc_fpu { + union { + unsigned int sregs[32]; + unsigned long dregs[32]; + long double qregs[16]; + } mcfpu_fregs; + unsigned long mcfpu_fsr; + unsigned long mcfpu_fprs; + unsigned long mcfpu_gsr; + struct mc_fq *mcfpu_fq; + unsigned char mcfpu_qcnt; + unsigned char mcfpu_qentsz; + unsigned char mcfpu_enab; +}; +typedef struct mc_fpu mc_fpu_t; + +typedef struct { + mc_gregset_t mc_gregs; + mc_greg_t mc_fp; + mc_greg_t mc_i7; + mc_fpu_t mc_fpregs; +} mcontext_t; + +typedef struct ucontext { + struct ucontext *uc_link; + unsigned long uc_flags; + unsigned long __uc_sigmask; + mcontext_t uc_mcontext; + stack_t uc_stack; + __sigset_t uc_sigmask; +} ucontext_t; + +#endif /* __WORDISIZE == 64 */ + +/* + * Location of the users' stored registers relative to R0. + * Usage is as an index into a gregset_t array or as u.u_ar0[XX]. + */ +#define REG_PSR (0) +#define REG_PC (1) +#define REG_nPC (2) +#define REG_Y (3) +#define REG_G1 (4) +#define REG_G2 (5) +#define REG_G3 (6) +#define REG_G4 (7) +#define REG_G5 (8) +#define REG_G6 (9) +#define REG_G7 (10) +#define REG_O0 (11) +#define REG_O1 (12) +#define REG_O2 (13) +#define REG_O3 (14) +#define REG_O4 (15) +#define REG_O5 (16) +#define REG_O6 (17) +#define REG_O7 (18) + +/* + * A gregset_t is defined as an array type for compatibility with the reference + * source. This is important due to differences in the way the C language + * treats arrays and structures as parameters. + * + * Note that NGREG is really (sizeof (struct regs) / sizeof (greg_t)), + * but that the ABI defines it absolutely to be 21 (resp. 19). + */ + +#if __WORDSIZE == 64 + +#define REG_ASI (19) +#define REG_FPRS (20) + +#define NGREG 21 +typedef long greg_t; + +#else /* __WORDSIZE == 32 */ + +#define NGREG 19 +typedef int greg_t; + +#endif /* __WORDSIZE == 32 */ + +typedef greg_t gregset_t[NGREG]; + +/* + * The following structures define how a register window can appear on the + * stack. This structure is available (when required) through the `gwins' + * field of an mcontext (nested within ucontext). SPARC_MAXWINDOW is the + * maximum number of outstanding regiters window defined in the SPARC + * architecture (*not* implementation). + */ +#define SPARC_MAXREGWINDOW 31 /* max windows in SPARC arch. */ +struct rwindow + { + greg_t rw_local[8]; /* locals */ + greg_t rw_in[8]; /* ins */ + }; + +#define rw_fp rw_in[6] /* frame pointer */ +#define rw_rtn rw_in[7] /* return address */ + +typedef struct gwindows + { + int wbcnt; + int *spbuf[SPARC_MAXREGWINDOW]; + struct rwindow wbuf[SPARC_MAXREGWINDOW]; + } gwindows_t; + +/* + * Floating point definitions. + */ + +#define MAXFPQ 16 /* max # of fpu queue entries currently supported */ + +/* + * struct fq defines the minimal format of a floating point instruction queue + * entry. The size of entries in the floating point queue are implementation + * dependent. The union FQu is guarenteed to be the first field in any ABI + * conformant system implementation. Any additional fields provided by an + * implementation should not be used applications designed to be ABI conformant. */ + +struct fpq + { + unsigned long *fpq_addr; /* address */ + unsigned long fpq_instr; /* instruction */ + }; + +struct fq + { + union /* FPU inst/addr queue */ + { + double whole; + struct fpq fpq; + } FQu; + }; + +#define FPU_REGS_TYPE unsigned +#define FPU_DREGS_TYPE unsigned long long +#define V7_FPU_FSR_TYPE unsigned +#define V9_FPU_FSR_TYPE unsigned long long +#define V9_FPU_FPRS_TYPE unsigned + +#if __WORDSIZE == 64 + +typedef struct fpu + { + union { /* FPU floating point regs */ + unsigned fpu_regs[32]; /* 32 singles */ + double fpu_dregs[16]; /* 32 doubles */ + long double fpu_qregs[16]; /* 16 quads */ + } fpu_fr; + struct fq *fpu_q; /* ptr to array of FQ entries */ + unsigned long fpu_fsr; /* FPU status register */ + unsigned char fpu_qcnt; /* # of entries in saved FQ */ + unsigned char fpu_q_entrysize; /* # of bytes per FQ entry */ + unsigned char fpu_en; /* flag signifying fpu in use */ + } fpregset_t; + +#else /* __WORDSIZE == 32 */ + +typedef struct fpu + { + union { /* FPU floating point regs */ + unsigned long long fpu_regs[32]; /* 32 singles */ + double fpu_dregs[16]; /* 16 doubles */ + } fpu_fr; + struct fq *fpu_q; /* ptr to array of FQ entries */ + unsigned fpu_fsr; /* FPU status register */ + unsigned char fpu_qcnt; /* # of entries in saved FQ */ + unsigned char fpu_q_entrysize; /* # of bytes per FQ entry */ + unsigned char fpu_en; /* flag signifying fpu in use */ + } fpregset_t; + +/* + * The following structure is for associating extra register state with + * the ucontext structure and is kept within the uc_mcontext filler area. + * + * If (xrs_id == XRS_ID) then the xrs_ptr field is a valid pointer to + * extra register state. The exact format of the extra register state + * pointed to by xrs_ptr is platform-dependent. + * + * Note: a platform may or may not manage extra register state. + */ +typedef struct + { + unsigned int xrs_id; /* indicates xrs_ptr validity */ + void * xrs_ptr; /* ptr to extra reg state */ + } xrs_t; + +#define XRS_ID 0x78727300 /* the string "xrs" */ + +typedef struct + { + gregset_t gregs; /* general register set */ + gwindows_t *gwins; /* POSSIBLE pointer to register windows */ + fpregset_t fpregs; /* floating point register set */ + xrs_t xrs; /* POSSIBLE extra register state association */ + long filler[19]; + } mcontext_t; + + +/* Userlevel context. */ +typedef struct ucontext + { + unsigned long uc_flags; + struct ucontext *uc_link; + __sigset_t uc_sigmask; + stack_t uc_stack; + mcontext_t uc_mcontext; + } ucontext_t; + +#endif /* __WORDSIZE == 32 */ +#endif /* sys/ucontext.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sys/user.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sys/user.h new file mode 100644 index 00000000..2aad01b0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sys/user.h @@ -0,0 +1,85 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_USER_H +#define _SYS_USER_H 1 + +struct sunos_regs +{ + unsigned int psr, pc, npc, y; + unsigned int regs[15]; +}; + +struct sunos_fpqueue +{ + unsigned int *addr; + unsigned int inst; +}; + +struct sunos_fp +{ + union + { + unsigned int regs[32]; + double reg_dbls[16]; + } fregs; + unsigned int fsr; + unsigned int flags; + unsigned int extra; + unsigned int fpq_count; + struct sunos_fpqueue fpq[16]; +}; + +struct sunos_fpu +{ + struct sunos_fp fpstatus; +}; + +/* The SunOS core file header layout. */ +struct user { + unsigned int magic; + unsigned int len; + struct sunos_regs regs; + struct + { + unsigned char a_dynamic :1; + unsigned char a_toolversion :7; + unsigned char a_machtype; + unsigned short a_info; + unsigned int a_text; + unsigned int a_data; + unsigned int a_bss; + unsigned int a_syms; + unsigned int a_entry; + unsigned int a_trsize; + unsigned int a_drsize; + } uexec; + int signal; + size_t u_tsize; + size_t u_dsize; + size_t u_ssize; + char u_comm[17]; + struct sunos_fpu fpu; + unsigned int sigcode; +}; + +#define NBPG 0x2000 +#define UPAGES 1 +#define SUNOS_CORE_MAGIC 0x080456 + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/syscall.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/syscall.S new file mode 100644 index 00000000..86055ec7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/syscall.S @@ -0,0 +1,50 @@ +/* Copyright (C) 1991, 1992, 1997, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +.text +.global syscall +.type syscall,%function +#if __WORDSIZE == 32 +.align 4 +#else +.align 2 +#endif + +syscall: + mov %o0, %g1 + mov %o1, %o0 + mov %o2, %o1 + mov %o3, %o2 + mov %o4, %o3 + mov %o5, %o4 + +#if __WORDSIZE == 32 + ta 0x10 + bcs __syscall_error +#else + ta 0x6d + bcs,pn %xcc,__syscall_error +#endif + + nop + retl + nop +.size syscall,.-syscall diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sysdep.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sysdep.h new file mode 100644 index 00000000..cf3e3afd --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/sysdep.h @@ -0,0 +1,69 @@ +#ifndef _LINUX_SPARC_SYSDEP_H +#define _LINUX_SPARC_SYSDEP_H 1 + +#include + +#undef ENTRY +#undef END + +#ifdef __ASSEMBLER__ + +#define LOADSYSCALL(x) mov __NR_##x, %g1 + +#define ENTRY(name) \ + .align 4; \ + .global C_SYMBOL_NAME(name); \ + .type name, @function; \ +C_LABEL(name) \ + cfi_startproc; + +#define END(name) \ + cfi_endproc; \ + .size name, . - name + +#define LOC(name) .L##name + + /* If the offset to __syscall_error fits into a signed 22-bit + * immediate branch offset, the linker will relax the call into + * a normal branch. + */ +#undef PSEUDO +#undef PSEUDO_END +#undef PSEUDO_NOERRNO +#undef PSEUDO_ERRVAL + +#define PSEUDO(name, syscall_name, args) \ + .text; \ + .globl __syscall_error; \ +ENTRY(name); \ + LOADSYSCALL(syscall_name); \ + ta 0x10; \ + bcc 1f; \ + mov %o7, %g1; \ + call __syscall_error; \ + mov %g1, %o7; \ +1: + +#define PSEUDO_NOERRNO(name, syscall_name, args)\ + .text; \ +ENTRY(name); \ + LOADSYSCALL(syscall_name); \ + ta 0x10; + +#define PSEUDO_ERRVAL(name, syscall_name, args) \ + .text; \ +ENTRY(name); \ + LOADSYSCALL(syscall_name); \ + ta 0x10; + +#define PSEUDO_END(name) \ + END(name) + + +#endif /* __ASSEMBLER__ */ + +/* Pointer mangling is not yet supported for SPARC. */ +#define PTR_MANGLE(var) (void) (var) +#define PTR_DEMANGLE(var) (void) (var) + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/udiv.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/udiv.S new file mode 100644 index 00000000..a1355a76 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/udiv.S @@ -0,0 +1,9 @@ +#include "_math_inc.h" + +#if defined(__CONFIG_SPARC_V9__) || defined(__CONFIG_SPARC_V9B__) +# include "sparcv9/udiv.S" +#elif defined(__CONFIG_SPARC_V8__) +# include "sparcv8/udiv.S" +#else +# include "sparcv7/udiv.S" +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/umul.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/umul.S new file mode 100644 index 00000000..e8605974 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/umul.S @@ -0,0 +1,9 @@ +#include "_math_inc.h" + +#if defined(__CONFIG_SPARC_V9__) || defined(__CONFIG_SPARC_V9B__) +# include "sparcv9/umul.S" +#elif defined(__CONFIG_SPARC_V8__) +# include "sparcv8/umul.S" +#else +# include "sparcv7/umul.S" +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/urem.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/urem.S new file mode 100644 index 00000000..baf6c433 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/urem.S @@ -0,0 +1,9 @@ +#include "_math_inc.h" + +#if defined(__CONFIG_SPARC_V9__) || defined(__CONFIG_SPARC_V9B__) +# include "sparcv9/urem.S" +#elif defined(__CONFIG_SPARC_V8__) +# include "sparcv8/urem.S" +#else +# include "sparcv7/urem.S" +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/vfork.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/vfork.S new file mode 100644 index 00000000..ed3e1a07 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/sparc/vfork.S @@ -0,0 +1,55 @@ +/* Copyright (C) 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Code taken from glibc2.2.2/sysdeps/unix/sysv/linux/sparc/vfork.S */ + +#include + +#ifndef __NR_vfork +/* No vfork so use fork instead */ +# define __NR_vfork __NR_fork +#endif + +.text +.global __vfork +.hidden __vfork +.type __vfork,%function +.align 4 + +__vfork: + mov __NR_vfork, %g1 + ta 0x10 + bcc,a 9000f + nop + save %sp,-96,%sp + call HIDDEN_JUMPTARGET(__errno_location) + nop + st %i0,[%o0] + jmpl %i7+8,%g0 + restore %g0,-1,%o0 + +9000: + sub %o1, 1, %o1 + retl + and %o0, %o1, %o0 + +.size __vfork,.-__vfork + +weak_alias(__vfork,vfork) +libc_hidden_weak(vfork) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/Makefile new file mode 100644 index 00000000..60dc97c1 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/Makefile @@ -0,0 +1,64 @@ +# Makefile for uClibc +# +# Copyright (C) 2001,2002 NEC Corporation +# Copyright (C) 2001,2002 Miles Bader +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + +TOPDIR=../../../../ +include $(TOPDIR)Rules.mak + +CFLAGS += -I.. +ASFLAGS += -I.. -D__ASSEMBLER -DASM_GLOBAL_DIRECTIVE=.globl + +TARGET_MACHINE_TYPE=$(shell $(CC) -dumpmachine) + +CRT_SRC := crt0.S +CRT_OBJ := crt0.o crt1.o +CTOR_TARGETS := $(TOPDIR)lib/crti.o $(TOPDIR)lib/crtn.o + +SSRC := setjmp.S __longjmp.S vfork.S +SOBJ := $(patsubst %.S,%.o, $(SSRC)) + +CSRC := mmap.c syscall.c clone.c +COBJ := $(patsubst %.c,%.o, $(CSRC)) + +OBJS := $(SOBJ) $(COBJ) + +OBJ_LIST := ../../../obj.sysdeps.$(TARGET_ARCH) + +all: $(OBJ_LIST) $(CTOR_TARGETS) + +$(OBJ_LIST): $(OBJS) $(CRT_OBJ) + $(STRIPTOOL) -x -R .note -R .comment $^ + $(INSTALL) -d $(TOPDIR)lib/ + cp $(CRT_OBJ) $(TOPDIR)lib/ + echo $(patsubst %, sysdeps/linux/$(TARGET_ARCH)/%, $(OBJS)) > $@ + +$(CRT_OBJ): $(CRT_SRC) + $(CC) $(ASFLAGS) -DL_$* $< -c -o $*.o + +$(SOBJ): %.o : %.S + $(CC) $(ASFLAGS) -c $< -o $@ + +$(COBJ): %.o : %.c + $(CC) $(CFLAGS) -c $< -o $@ + +ifeq ($(UCLIBC_CTOR_DTOR),y) +$(TOPDIR)lib/crti.o: crti.S + $(INSTALL) -d $(TOPDIR)lib/ + $(CC) $(ASFLAGS) $(SSP_DISABLE_FLAGS) -c $< -o $@ + +$(TOPDIR)lib/crtn.o: crtn.S + $(INSTALL) -d $(TOPDIR)lib/ + $(CC) $(ASFLAGS) $(SSP_DISABLE_FLAGS) -c $< -o $@ +else +$(CTOR_TARGETS): + $(INSTALL) -d $(TOPDIR)lib/ + $(AR) $(ARFLAGS) $@ +endif + +headers: + +clean: + $(RM) *.o *~ core diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/__longjmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/__longjmp.S new file mode 100644 index 00000000..fa29e0f7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/__longjmp.S @@ -0,0 +1,41 @@ +/* + * libc/sysdeps/linux/v850/longjmp.S -- `longjmp' for v850 + * + * Copyright (C) 2001,02 NEC Corporation + * Copyright (C) 2001,02 Miles Bader + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + * + * Written by Miles Bader + */ + +#include +#define _SETJMP_H +#define _ASM +#include + +#include + + .text +C_ENTRY(__longjmp): + /* Save registers */ + mov r6, ep + sld.w 0[ep], sp + sld.w 4[ep], lp + sld.w 8[ep], r2 + sld.w 12[ep], r20 + sld.w 16[ep], r21 + sld.w 20[ep], r22 + sld.w 24[ep], r23 + sld.w 28[ep], r24 + sld.w 32[ep], r25 + sld.w 36[ep], r26 + sld.w 40[ep], r27 + sld.w 44[ep], r28 + sld.w 48[ep], r29 + mov 1, r10 /* return val */ + jmp [lp] +C_END(__longjmp) +libc_hidden_def(__longjmp) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/bits/byteswap.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/bits/byteswap.h new file mode 100644 index 00000000..b2e1ddb9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/bits/byteswap.h @@ -0,0 +1,31 @@ +/* + * libc/sysdeps/linux/v850/bits/byteswap.h -- Macros to swap the order + * of bytes in integer values + * + * Copyright (C) 2001 NEC Corporation + * Copyright (C) 2001 Miles Bader + * Copyright (C) 1997,1998,2001 Free Software Foundation, Inc. + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + */ + +#ifndef _ASM_BITS_BYTESWAP_H +#define _ASM_BITS_BYTESWAP_H 1 + +#define __bswap_non_constant_16(x) \ + (__extension__ \ + ({ unsigned long int __bswap_16_v; \ + __asm__ ("bsh %1, %0" : "=r" (__bswap_16_v) : "r" (x)); \ + __bswap_16_v; })) + +# define __bswap_non_constant_32(x) \ + (__extension__ \ + ({ unsigned long int __bswap_32_v; \ + __asm__ ("bsw %1, %0" : "=r" (__bswap_32_v) : "r" (x)); \ + __bswap_32_v; })) + +#endif + +#include diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/bits/endian.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/bits/endian.h new file mode 100644 index 00000000..ae78da37 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/bits/endian.h @@ -0,0 +1,18 @@ +/* + * libc/sysdeps/linux/v850/bits/endian.h -- Define processor endianess + * + * Copyright (C) 2001 NEC Corporation + * Copyright (C) 2001 Miles Bader + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + * + * Written by Miles Bader + */ + +#ifndef _ENDIAN_H +# error "Never use directly; include instead." +#endif + +#define __BYTE_ORDER __LITTLE_ENDIAN diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/bits/fcntl.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/bits/fcntl.h new file mode 100644 index 00000000..c8aeb919 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/bits/fcntl.h @@ -0,0 +1,233 @@ +/* O_*, F_*, FD_* bit values for Linux. + Copyright (C) 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FCNTL_H +# error "Never use directly; include instead." +#endif + + +#include + +/* open/fcntl - O_SYNC is only implemented on blocks devices and on files + located on an ext2 file system */ +#define O_ACCMODE 0003 +#define O_RDONLY 00 +#define O_WRONLY 01 +#define O_RDWR 02 +#define O_CREAT 0100 /* not fcntl */ +#define O_EXCL 0200 /* not fcntl */ +#define O_NOCTTY 0400 /* not fcntl */ +#define O_TRUNC 01000 /* not fcntl */ +#define O_APPEND 02000 +#define O_NONBLOCK 04000 +#define O_NDELAY O_NONBLOCK +#define O_SYNC 010000 +#define O_FSYNC O_SYNC +#define O_ASYNC 020000 + +#ifdef __USE_GNU +# define O_DIRECTORY 040000 /* Must be a directory. */ +# define O_NOFOLLOW 0100000 /* Do not follow links. */ +# define O_DIRECT 0200000 /* Direct disk access. */ +#endif + +/* For now Linux has synchronisity options for data and read operations. + We define the symbols here but let them do the same as O_SYNC since + this is a superset. */ +#if defined __USE_POSIX199309 || defined __USE_UNIX98 +# define O_DSYNC O_SYNC /* Synchronize data. */ +# define O_RSYNC O_SYNC /* Synchronize read operations. */ +#endif + +#ifdef __USE_LARGEFILE64 +# define O_LARGEFILE 0400000 +#endif + +/* Values for the second argument to `fcntl'. */ +#define F_DUPFD 0 /* Duplicate file descriptor. */ +#define F_GETFD 1 /* Get file descriptor flags. */ +#define F_SETFD 2 /* Set file descriptor flags. */ +#define F_GETFL 3 /* Get file status flags. */ +#define F_SETFL 4 /* Set file status flags. */ +#ifndef __USE_FILE_OFFSET64 +# define F_GETLK 5 /* Get record locking info. */ +# define F_SETLK 6 /* Set record locking info (non-blocking). */ +# define F_SETLKW 7 /* Set record locking info (blocking). */ +#else +# define F_GETLK F_GETLK64 /* Get record locking info. */ +# define F_SETLK F_SETLK64 /* Set record locking info (non-blocking).*/ +# define F_SETLKW F_SETLKW64 /* Set record locking info (blocking). */ +#endif +#define F_GETLK64 12 /* Get record locking info. */ +#define F_SETLK64 13 /* Set record locking info (non-blocking). */ +#define F_SETLKW64 14 /* Set record locking info (blocking). */ + +#if defined __USE_BSD || defined __USE_XOPEN2K +# define F_SETOWN 8 /* Get owner of socket (receiver of SIGIO). */ +# define F_GETOWN 9 /* Set owner of socket (receiver of SIGIO). */ +#endif + +#ifdef __USE_GNU +# define F_SETSIG 10 /* Set number of signal to be sent. */ +# define F_GETSIG 11 /* Get number of signal to be sent. */ +#endif + +#ifdef __USE_GNU +# define F_SETLEASE 1024 /* Set a lease. */ +# define F_GETLEASE 1025 /* Enquire what lease is active. */ +# define F_NOTIFY 1026 /* Request notfications on a directory. */ +# define F_DUPFD_CLOEXEC 1030 /* Duplicate file descriptor with + close-on-exit set on new fd. */ +#endif + +/* For F_[GET|SET]FL. */ +#define FD_CLOEXEC 1 /* actually anything with low bit set goes */ + +/* For posix fcntl() and `l_type' field of a `struct flock' for lockf(). */ +#define F_RDLCK 0 /* Read lock. */ +#define F_WRLCK 1 /* Write lock. */ +#define F_UNLCK 2 /* Remove lock. */ + +/* For old implementation of bsd flock(). */ +#define F_EXLCK 4 /* or 3 */ +#define F_SHLCK 8 /* or 4 */ + +#ifdef __USE_BSD +/* Operations for bsd flock(), also used by the kernel implementation. */ +# define LOCK_SH 1 /* shared lock */ +# define LOCK_EX 2 /* exclusive lock */ +# define LOCK_NB 4 /* or'd with one of the above to prevent + blocking */ +# define LOCK_UN 8 /* remove lock */ +#endif + +#ifdef __USE_GNU +# define LOCK_MAND 32 /* This is a mandatory flock: */ +# define LOCK_READ 64 /* ... which allows concurrent read operations. */ +# define LOCK_WRITE 128 /* ... which allows concurrent write operations. */ +# define LOCK_RW 192 /* ... Which allows concurrent read & write operations. */ +#endif + +#ifdef __USE_GNU +/* Types of directory notifications that may be requested with F_NOTIFY. */ +# define DN_ACCESS 0x00000001 /* File accessed. */ +# define DN_MODIFY 0x00000002 /* File modified. */ +# define DN_CREATE 0x00000004 /* File created. */ +# define DN_DELETE 0x00000008 /* File removed. */ +# define DN_RENAME 0x00000010 /* File renamed. */ +# define DN_ATTRIB 0x00000020 /* File changed attibutes. */ +# define DN_MULTISHOT 0x80000000 /* Don't remove notifier. */ +#endif + +struct flock + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ +#ifndef __USE_FILE_OFFSET64 + __off_t l_start; /* Offset where the lock begins. */ + __off_t l_len; /* Size of the locked area; zero means until EOF. */ +#else + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ +#endif + __pid_t l_pid; /* Process holding the lock. */ + }; + +#ifdef __USE_LARGEFILE64 +struct flock64 + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ + __pid_t l_pid; /* Process holding the lock. */ + }; +#endif + +/* Define some more compatibility macros to be backward compatible with + BSD systems which did not managed to hide these kernel macros. */ +#ifdef __USE_BSD +# define FAPPEND O_APPEND +# define FFSYNC O_FSYNC +# define FASYNC O_ASYNC +# define FNONBLOCK O_NONBLOCK +# define FNDELAY O_NDELAY +#endif /* Use BSD. */ + +/* Advise to `posix_fadvise'. */ +#ifdef __USE_XOPEN2K +# define POSIX_FADV_NORMAL 0 /* No further special treatment. */ +# define POSIX_FADV_RANDOM 1 /* Expect random page references. */ +# define POSIX_FADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define POSIX_FADV_WILLNEED 3 /* Will need these pages. */ +# define POSIX_FADV_DONTNEED 4 /* Don't need these pages. */ +# define POSIX_FADV_NOREUSE 5 /* Data will be accessed once. */ +#endif + + +#if defined __USE_GNU && defined __UCLIBC_LINUX_SPECIFIC__ +/* Flags for SYNC_FILE_RANGE. */ +# define SYNC_FILE_RANGE_WAIT_BEFORE 1 /* Wait upon writeout of all pages + in the range before performing the + write. */ +# define SYNC_FILE_RANGE_WRITE 2 /* Initiate writeout of all those + dirty pages in the range which are + not presently under writeback. */ +# define SYNC_FILE_RANGE_WAIT_AFTER 4 /* Wait upon writeout of all pages in + the range after performing the + write. */ + +/* Flags for SPLICE and VMSPLICE. */ +# define SPLICE_F_MOVE 1 /* Move pages instead of copying. */ +# define SPLICE_F_NONBLOCK 2 /* Don't block on the pipe splicing + (but we may still block on the fd + we splice from/to). */ +# define SPLICE_F_MORE 4 /* Expect more data. */ +# define SPLICE_F_GIFT 8 /* Pages passed in are a gift. */ +#endif + +__BEGIN_DECLS + +#if defined __USE_GNU && defined __UCLIBC_LINUX_SPECIFIC__ + +/* Provide kernel hint to read ahead. */ +extern ssize_t readahead (int __fd, __off64_t __offset, size_t __count) + __THROW; + + +/* Selective file content synch'ing. */ +extern int sync_file_range (int __fd, __off64_t __from, __off64_t __to, + unsigned int __flags); + +/* Splice address range into a pipe. */ +extern ssize_t vmsplice (int __fdout, const struct iovec *__iov, + size_t __count, unsigned int __flags); + +/* Splice two files together. */ +extern ssize_t splice (int __fdin, __off64_t *__offin, int __fdout, + __off64_t *__offout, size_t __len, + unsigned int __flags); + +/* In-kernel implementation of tee for pipe buffers. */ +extern ssize_t tee (int __fdin, int __fdout, size_t __len, + unsigned int __flags); + +#endif +__END_DECLS + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/bits/kernel_stat.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/bits/kernel_stat.h new file mode 100644 index 00000000..a7c9a73b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/bits/kernel_stat.h @@ -0,0 +1,58 @@ +/* Stat structure for linux/v850 */ + +#ifndef _BITS_STAT_STRUCT_H +#define _BITS_STAT_STRUCT_H + +#ifndef _LIBC +#error bits/kernel_stat.h is for internal uClibc use only! +#endif + +struct kernel_stat +{ + __kernel_dev_t st_dev; + __kernel_ino_t st_ino; + __kernel_mode_t st_mode; + __kernel_nlink_t st_nlink; + __kernel_uid_t st_uid; + __kernel_gid_t st_gid; + __kernel_dev_t st_rdev; + __kernel_off_t st_size; + unsigned long st_blksize; + unsigned long st_blocks; + struct timespec st_atim; + struct timespec st_mtim; + struct timespec st_ctim; + unsigned long __unused4; + unsigned long __unused5; +}; + +struct kernel_stat64 +{ + __kernel_dev_t st_dev; + unsigned long __unused0; + unsigned long __unused1; + + __kernel_ino64_t st_ino; + + __kernel_mode_t st_mode; + __kernel_nlink_t st_nlink; + + __kernel_uid_t st_uid; + __kernel_gid_t st_gid; + + __kernel_dev_t st_rdev; + unsigned long __unused2; + unsigned long __unused3; + + __kernel_loff_t st_size; + unsigned long st_blksize; + + unsigned long __unused4; /* future possible st_blocks high bits */ + unsigned long st_blocks; /* Number 512-byte blocks allocated. */ + + struct timespec st_atim; + struct timespec st_mtim; + struct timespec st_ctim; +}; + +#endif /* _BITS_STAT_STRUCT_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/bits/kernel_types.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/bits/kernel_types.h new file mode 100644 index 00000000..3e851ab7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/bits/kernel_types.h @@ -0,0 +1,53 @@ +/* + * sysdeps/linux/v850/bits/kernel_types.h -- Kernel versions of standard types + * + * Copyright (C) 2001,2002 NEC Corporation + * Copyright (C) 2001,2002 Miles Bader + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + * + * Written by Miles Bader + */ + +#ifndef __V850_POSIX_TYPES_H__ +#define __V850_POSIX_TYPES_H__ + +typedef unsigned int __kernel_dev_t; +typedef unsigned long __kernel_ino_t; +typedef unsigned long long __kernel_ino64_t; +typedef unsigned int __kernel_mode_t; +typedef unsigned int __kernel_nlink_t; +typedef long __kernel_off_t; +typedef long long __kernel_loff_t; +typedef int __kernel_pid_t; +typedef unsigned short __kernel_ipc_pid_t; +typedef unsigned int __kernel_uid_t; +typedef unsigned int __kernel_gid_t; +typedef unsigned int __kernel_size_t; +typedef int __kernel_ssize_t; +typedef int __kernel_ptrdiff_t; +typedef long __kernel_time_t; +typedef long __kernel_suseconds_t; +typedef long __kernel_clock_t; +typedef int __kernel_daddr_t; +typedef char * __kernel_caddr_t; +typedef unsigned short __kernel_uid16_t; +typedef unsigned short __kernel_gid16_t; +typedef unsigned int __kernel_uid32_t; +typedef unsigned int __kernel_gid32_t; + +typedef unsigned short __kernel_old_uid_t; +typedef unsigned short __kernel_old_gid_t; +typedef __kernel_dev_t __kernel_old_dev_t; + +typedef struct { +#ifdef __USE_ALL + int val[2]; +#else + int __val[2]; +#endif +} __kernel_fsid_t; + +#endif /* __V850_POSIX_TYPES_H__ */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/bits/poll.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/bits/poll.h new file mode 100644 index 00000000..f7a73931 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/bits/poll.h @@ -0,0 +1,43 @@ +/* Copyright (C) 1997, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_POLL_H +# error "Never use directly; include instead." +#endif + +/* Event types that can be polled for. These bits may be set in `events' + to indicate the interesting event types; they will appear in `revents' + to indicate the status of the file descriptor. */ +#define POLLIN 0x001 /* There is data to read. */ +#define POLLPRI 0x002 /* There is urgent data to read. */ +#define POLLOUT 0x004 /* Writing now will not block. */ + +#ifdef __USE_XOPEN +/* These values are defined in XPG4.2. */ +# define POLLRDNORM 0x040 /* Normal data may be read. */ +# define POLLRDBAND 0x080 /* Priority data may be read. */ +# define POLLWRNORM POLLOUT /* Writing now will not block. */ +# define POLLWRBAND 0x100 /* Priority data may be written. */ +#endif + +/* Event types always implicitly polled for. These bits need not be set in + `events', but they will appear in `revents' to indicate the status of + the file descriptor. */ +#define POLLERR 0x008 /* Error condition. */ +#define POLLHUP 0x010 /* Hung up. */ +#define POLLNVAL 0x020 /* Invalid polling request. */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/bits/select.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/bits/select.h new file mode 100644 index 00000000..b6bb0545 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/bits/select.h @@ -0,0 +1,64 @@ +/* + * include/bits/select.h -- fd_set operations + * + * Copyright (C) 2001 NEC Corporation + * Copyright (C) 2001 Miles Bader + * Copyright (C) 1997, 1998 Free Software Foundation, Inc. + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + */ + +#ifndef _SYS_SELECT_H +# error "Never use directly; include instead." +#endif + +#ifdef __GNUC__ + +/* We don't use `memset' because this would require a prototype and + the array isn't too big. */ +#define __FD_ZERO(s) \ + do { \ + unsigned int __i; \ + fd_set *__arr = (s); \ + for (__i = 0; __i < sizeof (fd_set) / sizeof (__fd_mask); ++__i) \ + __FDS_BITS (__arr)[__i] = 0; \ + } while (0) + +#define __FD_SET(fd, s) \ + do { \ + int __fd = (fd); \ + void *__addr = (void *)&__FDS_BITS (s); \ + __asm__ __volatile__ ("set1 %0, [%1]" \ + : /*nothing*/ \ + : "r" (__fd & 0x7), "r" (__addr + (__fd >> 3)));\ + } while (0) + +#define __FD_CLR(fd, s) \ + do { \ + int __fd = (fd); \ + void *__addr = (void *)&__FDS_BITS (s); \ + __asm__ __volatile__ ("clr1 %0, [%1]" \ + : /*nothing*/ \ + : "r" (__fd & 0x7), "r" (__addr + (__fd >> 3)));\ + } while (0) + +#define __FD_ISSET(fd, s) \ + ({ \ + int __fd = (fd); \ + void *__addr = (void *)&__FDS_BITS (s); \ + int res; \ + __asm__ ("tst1 %1, [%2]; setf nz, %0" \ + : "=r" (res) \ + : "r" (__fd & 0x7), "r" (__addr + (__fd >> 3))); \ + res; \ + }) + +#else /* !__GNUC__ */ + +#define __FD_SET(d, s) (__FDS_BITS (s)[__FDELT(d)] |= __FDMASK(d)) +#define __FD_CLR(d, s) (__FDS_BITS (s)[__FDELT(d)] &= ~__FDMASK(d)) +#define __FD_ISSET(d, s) ((__FDS_BITS (s)[__FDELT(d)] & __FDMASK(d)) != 0) + +#endif /* __GNUC__ */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/bits/setjmp.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/bits/setjmp.h new file mode 100644 index 00000000..c9437378 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/bits/setjmp.h @@ -0,0 +1,42 @@ +/* + * libc/sysdeps/linux/v850/bits/setjmp.h -- v850 version of `jmp_buf' type + * + * Copyright (C) 2001 NEC Corporation + * Copyright (C) 2001 Miles Bader + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + * + * Written by Miles Bader + */ + +#ifndef _BITS_SETJMP_H +#define _BITS_SETJMP_H 1 + +#if !defined _SETJMP_H && !defined _PTHREAD_H +# error "Never include directly; use instead." +#endif + +#ifndef _ASM +typedef struct + { + /* Stack pointer. */ + void *__sp; + + /* Link pointer. */ + void *__lp; + + /* Callee-saved registers r2 and r20-r29. */ + int __regs[11]; + } __jmp_buf[1]; +#endif + +#define JB_SIZE (4 * 13) + +/* Test if longjmp to JMPBUF would unwind the frame + containing a local variable at ADDRESS. */ +#define _JMPBUF_UNWINDS(jmpbuf, address) \ + ((void *) (address) < (void *) (jmpbuf)[0].__sp) + +#endif /* bits/setjmp.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/bits/sigcontextinfo.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/bits/sigcontextinfo.h new file mode 100644 index 00000000..de450ff8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/bits/sigcontextinfo.h @@ -0,0 +1,17 @@ +/* + * sysdeps/v850/sigcontextinfo.h -- v850-specific pthread signal definitions + * + * Copyright (C) 2002 NEC Electronics Corporation + * Copyright (C) 2002 Miles Bader + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + * + * Written by Miles Bader + */ + +#include + +#define SIGCONTEXT struct sigcontext * +#define SIGCONTEXT_EXTRA_ARGS diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/bits/stackinfo.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/bits/stackinfo.h new file mode 100644 index 00000000..3ed732aa --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/bits/stackinfo.h @@ -0,0 +1,23 @@ +/* + * bits/stackinfo.h -- v850-specific pthread definitions + * + * Copyright (C) 2003 NEC Electronics Corporation + * Copyright (C) 2003 Miles Bader + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + * + * Written by Miles Bader + */ + +/* This file contains a bit of information about the stack allocation + of the processor. */ + +#ifndef _STACKINFO_H +#define _STACKINFO_H 1 + +/* On v80 the stack grows down. */ +#define _STACK_GROWS_DOWN 1 + +#endif /* stackinfo.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/bits/syscalls.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/bits/syscalls.h new file mode 100644 index 00000000..b2185133 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/bits/syscalls.h @@ -0,0 +1,15 @@ +#ifndef _BITS_SYSCALLS_H +#define _BITS_SYSCALLS_H +#ifndef _SYSCALL_H +# error "Never use directly; include instead." +#endif + +#include + +/* Do something very evil for now. Until we create our own syscall + * macros, short circuit bits/sysnum.h and use asm/unistd.h instead */ +#warning "fixme -- add arch specific syscall macros.h" +#include + +#endif /* _BITS_SYSCALLS_H */ + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/bits/uClibc_arch_features.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/bits/uClibc_arch_features.h new file mode 100644 index 00000000..2a9422e2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/bits/uClibc_arch_features.h @@ -0,0 +1,48 @@ +/* + * Track misc arch-specific features that aren't config options + */ + +#ifndef _BITS_UCLIBC_ARCH_FEATURES_H +#define _BITS_UCLIBC_ARCH_FEATURES_H + +/* instruction used when calling abort() to kill yourself */ +/*#define __UCLIBC_ABORT_INSTRUCTION__ "asm instruction"*/ +#undef __UCLIBC_ABORT_INSTRUCTION__ + +/* can your target use syscall6() for mmap ? */ +#undef __UCLIBC_MMAP_HAS_6_ARGS__ + +/* does your target use syscall4() for truncate64 ? (32bit arches only) */ +#undef __UCLIBC_TRUNCATE64_HAS_4_ARGS__ + +/* does your target have a broken create_module() ? */ +#undef __UCLIBC_BROKEN_CREATE_MODULE__ + +/* does your target have to worry about older [gs]etrlimit() ? */ +#undef __UCLIBC_HANDLE_OLDER_RLIMIT__ + +/* does your target have an asm .set ? */ +#define __UCLIBC_HAVE_ASM_SET_DIRECTIVE__ + +/* define if target doesn't like .global */ +#undef __UCLIBC_ASM_GLOBAL_DIRECTIVE__ + +/* define if target supports .weak */ +#define __UCLIBC_HAVE_ASM_WEAK_DIRECTIVE__ + +/* define if target supports .weakext */ +#undef __UCLIBC_HAVE_ASM_WEAKEXT_DIRECTIVE__ + +/* needed probably only for ppc64 */ +#undef __UCLIBC_HAVE_ASM_GLOBAL_DOT_NAME__ + +/* define if target supports CFI pseudo ops */ +#undef __UCLIBC_HAVE_ASM_CFI_DIRECTIVES__ + +/* define if target supports IEEE signed zero floats */ +#define __UCLIBC_HAVE_SIGNED_ZERO__ + +/* only weird assemblers generally need this */ +#undef __UCLIBC_ASM_LINE_SEP__ + +#endif /* _BITS_UCLIBC_ARCH_FEATURES_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/bits/wordsize.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/bits/wordsize.h new file mode 100644 index 00000000..ba643b60 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/bits/wordsize.h @@ -0,0 +1,19 @@ +/* Copyright (C) 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define __WORDSIZE 32 diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/clinkage.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/clinkage.h new file mode 100644 index 00000000..e85d39fb --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/clinkage.h @@ -0,0 +1,14 @@ +/* + * libc/sysdeps/linux/v850/clinkage.h -- Macros for C symbols in assembler + * + * Copyright (C) 2001 NEC Corporation + * Copyright (C) 2001 Miles Bader + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + * + * Written by Miles Bader + */ + +#include diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/clone.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/clone.c new file mode 100644 index 00000000..d2e22082 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/clone.c @@ -0,0 +1,50 @@ +/* + * libc/sysdeps/linux/v850/clone.c -- `clone' syscall for linux/v850 + * + * Copyright (C) 2002,03 NEC Electronics Corporation + * Copyright (C) 2002,03 Miles Bader + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + * + * Written by Miles Bader + */ + +#include +#include + +int +clone (int (*fn)(void *arg), void *child_stack, int flags, void *arg) +{ + register unsigned long rval __asm__ (SYSCALL_RET) = -EINVAL; + + if (fn && child_stack) + { + register unsigned long syscall __asm__ (SYSCALL_NUM); + register unsigned long arg0 __asm__ (SYSCALL_ARG0); + register unsigned long arg1 __asm__ (SYSCALL_ARG1); + + /* Clone this thread. */ + arg0 = flags; + arg1 = (unsigned long)child_stack; + syscall = __NR_clone; + __asm__ __volatile__ ("trap " SYSCALL_SHORT_TRAP + : "=r" (rval), "=r" (syscall) + : "1" (syscall), "r" (arg0), "r" (arg1) + : SYSCALL_SHORT_CLOBBERS); + + if (rval == 0) + /* In child thread, call FN and exit. */ + { + arg0 = (*fn) (arg); + syscall = __NR_exit; + __asm__ __volatile__ ("trap " SYSCALL_SHORT_TRAP + : "=r" (rval), "=r" (syscall) + : "1" (syscall), "r" (arg0) + : SYSCALL_SHORT_CLOBBERS); + } + } + + __syscall_return (int, rval); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/crt0.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/crt0.S new file mode 100644 index 00000000..01e9f830 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/crt0.S @@ -0,0 +1,57 @@ +/* + * libc/sysdeps/linux/v850/crt0.S -- Initial program entry point for linux/v850 + * + * Copyright (C) 2001,02,03 NEC Electronics Corporation + * Copyright (C) 2001,02,03 Miles Bader + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + * + * Written by Miles Bader + */ + +#include + +/* Upon entry, the stack contains the following data: + argc, argv[0], ..., argv[argc-1], 0, envp[0], ..., 0 +*/ + + .text +C_ENTRY(start): + ld.w 0[sp], r6 /* Arg 0: argc */ + + addi 4, sp, r7 /* Arg 1: argv */ + + mov r7, r8 /* Arg 2: envp */ + mov r6, r10 /* skip argc elements to get envp start */ + add 1, r10 /* ...plus the NULL at the end of argv */ + shl 2, r10 /* Convert to byte-count to skip */ + add r10, r8 + + /* Load CTBP register */ + mov hilo(C_SYMBOL_NAME(_ctbp)), r19 + ldsr r19, ctbp + + /* Load GP */ + mov hilo(C_SYMBOL_NAME(_gp)), gp + + /* tail-call uclibc's startup routine */ + addi -24, sp, sp /* Stack space reserved for args */ + jr C_SYMBOL_NAME(__uClibc_main) + + +/* Stick in a dummy reference to `main', so that if an application + is linking when the `main' function is in a static library (.a) + we can be sure that `main' actually gets linked in. */ +L_dummy_main_reference: + .long C_SYMBOL_NAME(main) + +/* Define a symbol for the first piece of initialized data. */ + .data + .globl __data_start +__data_start: + .long 0 + .weak data_start + data_start = __data_start + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/crti.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/crti.S new file mode 100644 index 00000000..c1e52939 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/crti.S @@ -0,0 +1,27 @@ + .file "initfini.c" +#APP + + .section .init +#NO_APP + .align 1 + .global __init + .type __init, @function +__init: + jarl __save_r31, r10 +#APP + + .align 1 + + + .section .fini +#NO_APP + .align 1 + .global __fini + .type __fini, @function +__fini: + jarl __save_r31, r10 +#APP + .align 1 + + + .ident "GCC: (GNU) 3.3.2" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/crtn.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/crtn.S new file mode 100644 index 00000000..6bb0b39a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/crtn.S @@ -0,0 +1,22 @@ + .file "initfini.c" +#APP + + .section .init +#NO_APP + .align 1 + .global __init + .type __init, @function +#NO_APP + jr __return_r31 +#APP + + .section .fini +#NO_APP + .align 1 + .global __fini + .type __fini, @function +#NO_APP + jr __return_r31 +#APP + + .ident "GCC: (GNU) 3.3.2" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/mmap.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/mmap.c new file mode 100644 index 00000000..7fb3f22a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/mmap.c @@ -0,0 +1,16 @@ +/* Use new style mmap for v850 */ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include + + +_syscall6 (__ptr_t, mmap, __ptr_t, addr, size_t, len, int, prot, + int, flags, int, fd, __off_t, offset) +libc_hidden_def(mmap) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/setjmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/setjmp.S new file mode 100644 index 00000000..87a5e383 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/setjmp.S @@ -0,0 +1,48 @@ +/* + * libc/sysdeps/linux/v850/setjmp.S -- `setjmp' for v850 + * + * Copyright (C) 2001,2002 NEC Corporation + * Copyright (C) 2001,2002 Miles Bader + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + * + * Written by Miles Bader + */ + +#define _SETJMP_H +#define _ASM +#include + +#include + + .text +C_ENTRY(setjmp): + mov 1, r7 /* Save the signal mask. */ + br C_SYMBOL_NAME(__sigsetjmp) + + .globl C_SYMBOL_NAME(_setjmp) +C_SYMBOL_NAME(_setjmp): + mov 0, r7 /* Don't save the signal mask. */ + + .globl C_SYMBOL_NAME(__sigsetjmp) +C_SYMBOL_NAME(__sigsetjmp): + /* Save registers */ + mov r6, ep + sst.w sp, 0[ep] + sst.w lp, 4[ep] + sst.w r2, 8[ep] + sst.w r20, 12[ep] + sst.w r21, 16[ep] + sst.w r22, 20[ep] + sst.w r23, 24[ep] + sst.w r24, 28[ep] + sst.w r25, 32[ep] + sst.w r26, 36[ep] + sst.w r27, 40[ep] + sst.w r28, 44[ep] + sst.w r29, 48[ep] + /* Make a tail call to __sigjmp_save; it takes the same args. */ + jr C_SYMBOL_NAME(__sigjmp_save) +C_END(setjmp) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/sys/procfs.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/sys/procfs.h new file mode 100644 index 00000000..67acb3cc --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/sys/procfs.h @@ -0,0 +1,136 @@ +/* Copyright (C) 1996, 1997, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_PROCFS_H +#define _SYS_PROCFS_H 1 + +/* This is somewhat modelled after the file of the same name on SVR4 + systems. It provides a definition of the core file format for ELF + used on Linux. It doesn't have anything to do with the /proc file + system, even though Linux has one. + + Anyway, the whole purpose of this file is for GDB and GDB only. + Don't read too much into it. Don't use it for anything other than + GDB unless you know what you are doing. */ + +#include +#include +#include + + +/* Type for a general-purpose register. */ +typedef unsigned long elf_greg_t; + +/* This is exactly the same as `struct pt_regs' in the kernel. */ +struct elf_gregset +{ + /* General purpose registers. */ + elf_greg_t gpr[32]; + + elf_greg_t pc; /* program counter */ + elf_greg_t psw; /* program status word */ + + /* Registers used by `callt' instruction: */ + elf_greg_t ctpc; /* saved program counter */ + elf_greg_t ctpsw; /* saved psw */ + elf_greg_t ctbp; /* base pointer for callt table */ + + char kernel_mode; /* 1 if in `kernel mode', 0 if user mode */ +}; + +#define ELF_NGREG (sizeof (struct elf_gregset) / sizeof(elf_greg_t)) +typedef elf_greg_t elf_gregset_t[ELF_NGREG]; + +/* Register set for the floating-point registers. */ +typedef void elf_fpregset_t; + + +struct elf_siginfo +{ + int si_signo; /* signal number */ + int si_code; /* extra code */ + int si_errno; /* errno */ +}; + + +/* + * Definitions to generate Intel SVR4-like core files. + * These mostly have the same names as the SVR4 types with "elf_" + * tacked on the front to prevent clashes with linux definitions, + * and the typedef forms have been avoided. This is mostly like + * the SVR4 structure, but more Linuxy, with things that Linux does + * not support and which gdb doesn't really use excluded. + * Fields present but not used are marked with "XXX". + */ +struct elf_prstatus +{ + struct elf_siginfo pr_info; /* Info associated with signal */ + short pr_cursig; /* Current signal */ + unsigned long pr_sigpend; /* Set of pending signals */ + unsigned long pr_sighold; /* Set of held signals */ + __kernel_pid_t pr_pid; + __kernel_pid_t pr_ppid; + __kernel_pid_t pr_pgrp; + __kernel_pid_t pr_sid; + struct timeval pr_utime; /* User time */ + struct timeval pr_stime; /* System time */ + struct timeval pr_cutime; /* Cumulative user time */ + struct timeval pr_cstime; /* Cumulative system time */ + elf_gregset_t pr_reg; /* GP registers */ + int pr_fpvalid; /* True if math co-processor being used. */ +}; + +#define ELF_PRARGSZ (80) /* Number of chars for args */ + +struct elf_prpsinfo +{ + char pr_state; /* numeric process state */ + char pr_sname; /* char for pr_state */ + char pr_zomb; /* zombie */ + char pr_nice; /* nice val */ + unsigned long pr_flag; /* flags */ + __kernel_uid_t pr_uid; + __kernel_gid_t pr_gid; + __kernel_pid_t pr_pid, pr_ppid, pr_pgrp, pr_sid; + /* Lots missing */ + char pr_fname[16]; /* filename of executable */ + char pr_psargs[ELF_PRARGSZ]; /* initial part of arg list */ +}; + + +/* The rest of this file provides the types for emulation of the + Solaris interfaces that should be implemented by + users of libthread_db. */ + +/* Addresses. */ +typedef void *psaddr_t; + +/* Register sets. Linux has different names. */ +typedef elf_gregset_t prgregset_t; +typedef elf_fpregset_t prfpregset_t; + +/* We don't have any differences between processes and threads, + therefore have only one PID type. */ +typedef __kernel_pid_t lwpid_t; + +/* Process status and info. In the end we do provide typedefs for them. */ +typedef struct elf_prstatus prstatus_t; +typedef struct elf_prpsinfo prpsinfo_t; + + +#endif /* sys/procfs.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/sys/ptrace.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/sys/ptrace.h new file mode 100644 index 00000000..48690eee --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/sys/ptrace.h @@ -0,0 +1,98 @@ +/* `ptrace' debugger support interface. Linux/v850 version. + Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_PTRACE_H +#define _SYS_PTRACE_H 1 + +#include + +__BEGIN_DECLS + +/* Type of the REQUEST argument to `ptrace.' */ +enum __ptrace_request +{ + /* Indicate that the process making this request should be traced. + All signals received by this process can be intercepted by its + parent, and its parent can use the other `ptrace' requests. */ + PTRACE_TRACEME = 0, +#define PT_TRACE_ME PTRACE_TRACEME + + /* Return the word in the process's text space at address ADDR. */ + PTRACE_PEEKTEXT = 1, +#define PT_READ_I PTRACE_PEEKTEXT + + /* Return the word in the process's data space at address ADDR. */ + PTRACE_PEEKDATA = 2, +#define PT_READ_D PTRACE_PEEKDATA + + /* Return the word in the process's user area at offset ADDR. */ + PTRACE_PEEKUSER = 3, +#define PT_READ_U PTRACE_PEEKUSER + + /* Write the word DATA into the process's text space at address ADDR. */ + PTRACE_POKETEXT = 4, +#define PT_WRITE_I PTRACE_POKETEXT + + /* Write the word DATA into the process's data space at address ADDR. */ + PTRACE_POKEDATA = 5, +#define PT_WRITE_D PTRACE_POKEDATA + + /* Write the word DATA into the process's user area at offset ADDR. */ + PTRACE_POKEUSER = 6, +#define PT_WRITE_U PTRACE_POKEUSER + + /* Continue the process. */ + PTRACE_CONT = 7, +#define PT_CONTINUE PTRACE_CONT + + /* Kill the process. */ + PTRACE_KILL = 8, +#define PT_KILL PTRACE_KILL + + /* Single step the process. */ + PTRACE_SINGLESTEP = 9, +#define PT_STEP PTRACE_SINGLESTEP + + /* Attach to a process that is already running. */ + PTRACE_ATTACH = 16, +#define PT_ATTACH PTRACE_ATTACH + + /* Detach from a process attached to with PTRACE_ATTACH. */ + PTRACE_DETACH = 17, +#define PT_DETACH PTRACE_DETACH + + /* Continue and stop at the next (return from) syscall. */ + PTRACE_SYSCALL = 24 +#define PT_SYSCALL PTRACE_SYSCALL +}; + +/* Perform process tracing functions. REQUEST is one of the values + above, and determines the action to be taken. + For all requests except PTRACE_TRACEME, PID specifies the process to be + traced. + + PID and the other arguments described above for the various requests should + appear (those that are used for the particular request) as: + pid_t PID, void *ADDR, int DATA, void *ADDR2 + after REQUEST. */ +extern long int ptrace (enum __ptrace_request __request, ...) __THROW; + +__END_DECLS + +#endif /* _SYS_PTRACE_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/sys/ucontext.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/sys/ucontext.h new file mode 100644 index 00000000..07f0933f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/sys/ucontext.h @@ -0,0 +1,41 @@ +/* Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_UCONTEXT_H +#define _SYS_UCONTEXT_H 1 + +#include +#include + +/* We need the signal context definitions even if they are not used + included in . */ +#include + +typedef struct sigcontext mcontext_t; + +/* Userlevel context. */ +typedef struct ucontext + { + unsigned long int uc_flags; + struct ucontext *uc_link; + stack_t uc_stack; + mcontext_t uc_mcontext; + __sigset_t uc_sigmask; + } ucontext_t; + +#endif /* sys/ucontext.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/syscall.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/syscall.c new file mode 100644 index 00000000..dbcc87ce --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/syscall.c @@ -0,0 +1,43 @@ +/* + * libc/sysdeps/linux/v850/syscall.c -- generic syscall function for linux/v850 + * + * Copyright (C) 2002 NEC Corporation + * Copyright (C) 2002 Miles Bader + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + * + * Written by Miles Bader + */ + +#include +#include + +typedef unsigned long arg_t; + +/* Invoke `system call' NUM, passing it the remaining arguments. + This is completely system-dependent, and not often useful. */ +long +syscall (long num, arg_t a1, arg_t a2, arg_t a3, arg_t a4, arg_t a5, arg_t a6) +{ + /* We don't know how many arguments are valid, so A5 and A6 are fetched + off the stack even for (the majority of) system calls with fewer + arguments; hopefully this won't cause any problems. A1-A4 are in + registers, so they're OK. */ + register arg_t a __asm__ (SYSCALL_ARG0) = a1; + register arg_t b __asm__ (SYSCALL_ARG1) = a2; + register arg_t c __asm__ (SYSCALL_ARG2) = a3; + register arg_t d __asm__ (SYSCALL_ARG3) = a4; + register arg_t e __asm__ (SYSCALL_ARG4) = a5; + register arg_t f __asm__ (SYSCALL_ARG5) = a6; + register unsigned long syscall __asm__ (SYSCALL_NUM) = num; + register unsigned long ret __asm__ (SYSCALL_RET); + + __asm__ ("trap " SYSCALL_LONG_TRAP + : "=r" (ret) + : "r" (syscall), "r" (a), "r" (b), "r" (c), "r" (d), "r" (e), "r" (f) + : SYSCALL_CLOBBERS); + + __syscall_return (long, ret); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/vfork.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/vfork.S new file mode 100644 index 00000000..2533853b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/v850/vfork.S @@ -0,0 +1,42 @@ +/* + * libc/sysdeps/linux/v850/vfork.S -- `vfork' syscall for linux/v850 + * + * Copyright (C) 2001,2002 NEC Corporation + * Copyright (C) 2001,2002 Miles Bader + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + * + * Written by Miles Bader + */ + +#include +#define _ERRNO_H 1 +#include +#define _SYSCALL_H +#include + +#include + +/* Clone the calling process, but without copying the whole address space. + The calling process is suspended until the new process exits or is + replaced by a call to `execve'. Return -1 for errors, 0 to the new process, + and the process ID of the new process to the old process. */ + +.global C_SYMBOL_NAME(errno) + +C_ENTRY (__vfork): + addi SYS_vfork, r0, r12 + trap 0 + addi -125, r0, r11 /* minimum err value */ + cmp r11, r10 + bh 1f + jmp [lp] /* normal return */ +1: mov hilo(C_SYMBOL_NAME(errno)), r11 + subr r0, r10 + st.w r10, 0[r11] + jmp [lp] /* error return */ +C_END(__vfork) +weak_alias(__vfork,vfork) +libc_hidden_weak(vfork) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/Makefile new file mode 100644 index 00000000..b1bf1ef1 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/Makefile @@ -0,0 +1,15 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +TOPDIR=../../../../ + +top_srcdir=$(TOPDIR) +top_builddir=../../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.arch +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/Makefile.arch b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/Makefile.arch new file mode 100644 index 00000000..027c65f9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/Makefile.arch @@ -0,0 +1,10 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2006 Erik Andersen +# Copyright (C) 2005-2006 Jan-Benedict Glaw +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +CSRC := brk.c mmap.c +SSRC := __longjmp.S setjmp.S _setjmp.S clone.S diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/__longjmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/__longjmp.S new file mode 100644 index 00000000..61b37a3b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/__longjmp.S @@ -0,0 +1,47 @@ +#include + +/* + * longjmp.S atp sept 2001 + * Jan-Benedict Glaw 2006 + * + * Restore regs and info and jmp back to a previous setjmp + */ + +.globl __longjmp +.align 4 +__longjmp: + .word 0x0040 /* This matches setjmp and PLT */ + movl 0x4(%ap), %r0 /* Our scratch reg */ +/* movl $0, %r0 */ +/* movl (%r0), %r0 */ + /* We are going to modify our stack frame */ + /* to the same as that of the setjmp we called earlier */ + movl (%r0), (%fp) /* cond handler */ + movl 0x4(%r0), 0x4(%fp) /* psw */ + movl 0x8(%r0), 0x8(%fp) /* ap */ + movl 0xc(%r0), 0xc(%fp) /* fp */ + movl 0x10(%r0), 0x10(%fp) /* pc */ + + /* Restore the regs */ + movl 0x14(%r0), %r1 + movl 0x18(%r0), %r2 + movl 0x1c(%r0), %r3 + movl 0x20(%r0), %r4 + movl 0x24(%r0), %r5 + movl 0x28(%r0), %r6 + movl 0x2c(%r0), %r7 + movl 0x30(%r0), %r8 + movl 0x34(%r0), %r9 + movl 0x38(%r0), %r10 + movl 0x3c(%r0), %r11 + + /* Check val and set to 1 if set to zero */ + movl 0x8(%ap), %r0 + tstl %r0 + bneq exit_ok + movl $0x1, %r0 +exit_ok: + ret +.size __longjmp,.-__longjmp +libc_hidden_def(__longjmp) + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/_setjmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/_setjmp.S new file mode 100644 index 00000000..680ddd72 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/_setjmp.S @@ -0,0 +1,53 @@ +.globl _setjmp +.align 4 +_setjmp: + .word 0x0040 + + /* push an empty word onto the stack */ + pushl $0 + + /* now copy handler, psw, ap, fp and pc on the stack up one word */ + movl 4(%sp), (%sp) /* copy handler */ + movl 8(%sp), 4(%sp) /* psw */ + movl 12(%sp), 8(%sp) /* ap */ + movl 16(%sp), 12(%sp) /* fp */ + movl 20(%sp), 16(%sp) /* pc */ + movl 24(%sp), 20(%sp) /* r6 from register mask */ + + movl $2, 24(%sp) /* set the number of arguments to 2 */ + movl 32(%sp), 28(%sp) /* copy the jmp_buf */ + movl $1, 32(%sp) /* put the 1 on the stack */ + + addl3 $24, %sp, %ap + movl %sp, %fp + + moval __sigsetjmp, %r0 + addl2 $2, %r0 + pushl %r0 + rsb + +.globl setjmp +.align 4 +setjmp: + .word 0x0040 + pushl $0 + + /* now copy handler, psw, ap, fp and pc on the stack up one word */ + movl 4(%sp), (%sp) + movl 8(%sp), 4(%sp) + movl 12(%sp), 8(%sp) + movl 16(%sp), 12(%sp) + movl 20(%sp), 16(%sp) + movl 24(%sp), 20(%sp) /* r6 from register mask */ + + movl $2, 24(%sp) /* set the number of arguments to 2 */ + movl 32(%sp), 28(%sp) /* copy the jmp_buf */ + movl $0, 32(%sp) /* put the 0 on the stack */ + + addl3 $24, %sp, %ap + movl %sp, %fp + + moval __sigsetjmp, %r0 + addl2 $2, %r0 + pushl %r0 + rsb diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/bits/endian.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/bits/endian.h new file mode 100644 index 00000000..9f0c4e2a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/bits/endian.h @@ -0,0 +1,9 @@ +/* VAX is little endian */ + +#ifndef _ENDIAN_H +# error "Never use directly; include instead." +#endif + +#define __BYTE_ORDER __LITTLE_ENDIAN + +/*#define __FLOAT_WORD_ORDER __BIG_ENDIAN*/ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/bits/fcntl.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/bits/fcntl.h new file mode 100644 index 00000000..66c2812c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/bits/fcntl.h @@ -0,0 +1,214 @@ +/* O_*, F_*, FD_* bit values for Linux. + Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _FCNTL_H +# error "Never use directly; include instead." +#endif + + +#include +#ifdef __USE_GNU +# include +#endif + +/* open/fcntl - O_SYNC is only implemented on blocks devices and on files + located on an ext2 file system */ +#define O_ACCMODE 0003 +#define O_RDONLY 00 +#define O_WRONLY 01 +#define O_RDWR 02 +#define O_CREAT 0100 /* not fcntl */ +#define O_EXCL 0200 /* not fcntl */ +#define O_NOCTTY 0400 /* not fcntl */ +#define O_TRUNC 01000 /* not fcntl */ +#define O_APPEND 02000 +#define O_NONBLOCK 04000 +#define O_NDELAY O_NONBLOCK +#define O_SYNC 010000 +#define O_FSYNC O_SYNC +#define O_ASYNC 020000 + +#ifdef __USE_GNU +# define O_DIRECTORY 040000 /* Must be a directory. */ +# define O_NOFOLLOW 0100000 /* Do not follow links. */ +#endif + +/* XXX missing */ +#ifdef __USE_LARGEFILE64 +# define O_LARGEFILE 0 +#endif + +/* For now Linux has synchronisity options for data and read operations. + We define the symbols here but let them do the same as O_SYNC since + this is a superset. */ +#if defined __USE_POSIX199309 || defined __USE_UNIX98 +# define O_DSYNC O_SYNC /* Synchronize data. */ +# define O_RSYNC O_SYNC /* Synchronize read operations. */ +#endif + +/* Values for the second argument to `fcntl'. */ +#define F_DUPFD 0 /* Duplicate file descriptor. */ +#define F_GETFD 1 /* Get file descriptor flags. */ +#define F_SETFD 2 /* Set file descriptor flags. */ +#define F_GETFL 3 /* Get file status flags. */ +#define F_SETFL 4 /* Set file status flags. */ +#define F_GETLK 5 /* Get record locking info. */ +#define F_SETLK 6 /* Set record locking info (non-blocking). */ +#define F_SETLKW 7 /* Set record locking info (blocking). */ + +/* XXX missing */ +#define F_GETLK64 5 /* Get record locking info. */ +#define F_SETLK64 6 /* Set record locking info (non-blocking). */ +#define F_SETLKW64 7 /* Set record locking info (blocking). */ + +#ifdef __USE_BSD +# define F_SETOWN 8 /* Get owner of socket (receiver of SIGIO). */ +# define F_GETOWN 9 /* Set owner of socket (receiver of SIGIO). */ +#endif + +#ifdef __USE_GNU +# define F_SETSIG 10 /* Set number of signal to be sent. */ +# define F_GETSIG 11 /* Get number of signal to be sent. */ +#endif + +#ifdef __USE_GNU +# define F_SETLEASE 1024 /* Set a lease. */ +# define F_GETLEASE 1025 /* Enquire what lease is active. */ +# define F_NOTIFY 1026 /* Request notfications on a directory. */ +# define F_DUPFD_CLOEXEC 1030 /* Duplicate file descriptor with + close-on-exit set on new fd. */ +#endif + +/* For F_[GET|SET]FL. */ +#define FD_CLOEXEC 1 /* actually anything with low bit set goes */ + +/* For posix fcntl() and `l_type' field of a `struct flock' for lockf(). */ +#define F_RDLCK 0 /* Read lock. */ +#define F_WRLCK 1 /* Write lock. */ +#define F_UNLCK 2 /* Remove lock. */ + +/* for old implementation of bsd flock () */ +#define F_EXLCK 4 /* or 3 */ +#define F_SHLCK 8 /* or 4 */ + +#ifdef __USE_BSD +/* Operations for bsd flock(), also used by the kernel implementation */ +# define LOCK_SH 1 /* shared lock */ +# define LOCK_EX 2 /* exclusive lock */ +# define LOCK_NB 4 /* or'd with one of the above to prevent + blocking */ +# define LOCK_UN 8 /* remove lock */ +#endif + +struct flock + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ +#ifndef __USE_FILE_OFFSET64 + __off_t l_start; /* Offset where the lock begins. */ + __off_t l_len; /* Size of the locked area; zero means until EOF. */ +#else + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ +#endif + __pid_t l_pid; /* Process holding the lock. */ + }; + +#ifdef __USE_LARGEFILE64 +struct flock64 + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ + __pid_t l_pid; /* Process holding the lock. */ + }; +#endif + +/* Define some more compatibility macros to be backward compatible with + BSD systems which did not managed to hide these kernel macros. */ +#ifdef __USE_BSD +# define FAPPEND O_APPEND +# define FFSYNC O_FSYNC +# define FASYNC O_ASYNC +# define FNONBLOCK O_NONBLOCK +# define FNDELAY O_NDELAY +#endif /* Use BSD. */ + +/* Advise to `posix_fadvise'. */ +#ifdef __USE_XOPEN2K +# define POSIX_FADV_NORMAL 0 /* No further special treatment. */ +# define POSIX_FADV_RANDOM 1 /* Expect random page references. */ +# define POSIX_FADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define POSIX_FADV_WILLNEED 3 /* Will need these pages. */ +# define POSIX_FADV_DONTNEED 4 /* Don't need these pages. */ +# define POSIX_FADV_NOREUSE 5 /* Data will be accessed once. */ +#endif + + +#if defined __USE_GNU && defined __UCLIBC_LINUX_SPECIFIC__ +/* Flags for SYNC_FILE_RANGE. */ +# define SYNC_FILE_RANGE_WAIT_BEFORE 1 /* Wait upon writeout of all pages + in the range before performing the + write. */ +# define SYNC_FILE_RANGE_WRITE 2 /* Initiate writeout of all those + dirty pages in the range which are + not presently under writeback. */ +# define SYNC_FILE_RANGE_WAIT_AFTER 4 /* Wait upon writeout of all pages in + the range after performing the + write. */ + +/* Flags for SPLICE and VMSPLICE. */ +# define SPLICE_F_MOVE 1 /* Move pages instead of copying. */ +# define SPLICE_F_NONBLOCK 2 /* Don't block on the pipe splicing + (but we may still block on the fd + we splice from/to). */ +# define SPLICE_F_MORE 4 /* Expect more data. */ +# define SPLICE_F_GIFT 8 /* Pages passed in are a gift. */ +#endif + +__BEGIN_DECLS + +#if defined __USE_GNU && defined __UCLIBC_LINUX_SPECIFIC__ + +/* Provide kernel hint to read ahead. */ +extern ssize_t readahead (int __fd, __off64_t __offset, size_t __count) + __THROW; + + +/* Selective file content synch'ing. */ +extern int sync_file_range (int __fd, __off64_t __from, __off64_t __to, + unsigned int __flags); + +/* Splice address range into a pipe. */ +extern ssize_t vmsplice (int __fdout, const struct iovec *__iov, + size_t __count, unsigned int __flags); + +/* Splice two files together. */ +extern ssize_t splice (int __fdin, __off64_t *__offin, int __fdout, + __off64_t *__offout, size_t __len, + unsigned int __flags); + +/* In-kernel implementation of tee for pipe buffers. */ +extern ssize_t tee (int __fdin, int __fdout, size_t __len, + unsigned int __flags); + +#endif +__END_DECLS + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/bits/ipc.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/bits/ipc.h new file mode 100644 index 00000000..c4e37358 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/bits/ipc.h @@ -0,0 +1,50 @@ +/* Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _SYS_IPC_H +# error "Never use directly; include instead." +#endif + +#include + +/* Mode bits for `msgget', `semget', and `shmget'. */ +#define IPC_CREAT 01000 /* Create key if key does not exist. */ +#define IPC_EXCL 02000 /* Fail if key exists. */ +#define IPC_NOWAIT 04000 /* Return error on wait. */ + +/* Control commands for `msgctl', `semctl', and `shmctl'. */ +#define IPC_RMID 0 /* Remove identifier. */ +#define IPC_SET 1 /* Set `ipc_perm' options. */ +#define IPC_STAT 2 /* Get `ipc_perm' options. */ +#define IPC_INFO 3 /* See ipcs. */ + +/* Special key values. */ +#define IPC_PRIVATE ((__key_t) 0) /* Private key. */ + + +/* Data structure used to pass permission information to IPC operations. */ +struct ipc_perm + { + __key_t __key; /* Key. */ + unsigned short int uid; /* Owner's user ID. */ + unsigned short int gid; /* Owner's group ID. */ + unsigned short int cuid; /* Creator's user ID. */ + unsigned short int cgid; /* Creator's group ID. */ + unsigned short int mode; /* Read/write permission. */ + unsigned short int __seq; /* Sequence number. */ + }; diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/bits/kernel_stat.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/bits/kernel_stat.h new file mode 100644 index 00000000..4636a139 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/bits/kernel_stat.h @@ -0,0 +1,54 @@ +#ifndef _BITS_STAT_STRUCT_H +#define _BITS_STAT_STRUCT_H + +#ifndef _LIBC +#error bits/kernel_stat.h is for internal uClibc use only! +#endif + +/* This file provides whatever this particular arch's kernel thinks + * struct stat should look like... It turns out each arch has a + * different opinion on the subject... */ + +struct kernel_stat { + unsigned short st_dev; + unsigned short __pad1; + unsigned long st_ino; + unsigned short st_mode; + unsigned short st_nlink; + unsigned short st_uid; + unsigned short st_gid; + unsigned short st_rdev; + unsigned short __pad2; + unsigned long st_size; + unsigned long st_blksize; + unsigned long st_blocks; + struct timespec st_atim; + struct timespec st_mtim; + struct timespec st_ctim; + unsigned long __unused4; + unsigned long __unused5; +}; + +struct kernel_stat64 { + unsigned short st_dev; + unsigned char __pad0[10]; +#define _HAVE_STAT64___ST_INO 1 + unsigned long __st_ino; + unsigned int st_mode; + unsigned int st_nlink; + unsigned long st_uid; + unsigned long st_gid; + unsigned short st_rdev; + unsigned char __pad3[10]; + long long st_size; + unsigned long st_blksize; + unsigned long st_blocks; /* Number 512-byte blocks allocated. */ + unsigned long __pad4; /* future possible st_blocks high bits */ + struct timespec st_atim; + struct timespec st_mtim; + struct timespec st_ctim; + unsigned long long st_ino; +}; + +#endif /* _BITS_STAT_STRUCT_H */ + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/bits/kernel_types.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/bits/kernel_types.h new file mode 100644 index 00000000..aef74b54 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/bits/kernel_types.h @@ -0,0 +1,45 @@ +#ifndef _VAX_POSIX_TYPES_H +#define _VAX_POSIX_TYPES_H +/* + * Note that we use the exact same include guard #define names + * as asm/posix_types.h. This will avoid gratuitous conflicts + * with the posix_types.h kernel header, and will ensure that + * our private content, and not the kernel header, will win. + * -Erik + */ + + +typedef unsigned short __kernel_dev_t; +typedef unsigned long __kernel_ino_t; +typedef unsigned short __kernel_mode_t; +typedef unsigned short __kernel_nlink_t; +typedef long __kernel_off_t; +typedef int __kernel_pid_t; +typedef unsigned short __kernel_ipc_pid_t; +typedef unsigned short __kernel_uid_t; +typedef unsigned short __kernel_gid_t; +typedef unsigned int __kernel_size_t; +typedef int __kernel_ssize_t; +typedef int __kernel_ptrdiff_t; +typedef long __kernel_time_t; +typedef long __kernel_suseconds_t; +typedef long __kernel_clock_t; +typedef int __kernel_daddr_t; +typedef char * __kernel_caddr_t; +typedef unsigned short __kernel_uid16_t; +typedef unsigned short __kernel_gid16_t; +typedef unsigned int __kernel_uid32_t; +typedef unsigned int __kernel_gid32_t; +typedef unsigned short __kernel_old_uid_t; +typedef unsigned short __kernel_old_gid_t; +typedef long long __kernel_loff_t; + +typedef struct { +#if defined(__KERNEL__) || defined(__USE_ALL) + int val[2]; +#else + int __val[2]; +#endif +} __kernel_fsid_t; + +#endif /* _VAX_POSIX_TYPES_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/bits/machine-gmon.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/bits/machine-gmon.h new file mode 100644 index 00000000..841518f0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/bits/machine-gmon.h @@ -0,0 +1,41 @@ +/* i386-specific implementation of profiling support. + Copyright (C) 1997, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +/* We need a special version of the `mcount' function since for ix86 it + must not clobber any register. This has several reasons: + - there is a bug in gcc as of version 2.7.2.2 which prohibits the + use of profiling together with nested functions + - the ELF `fixup' function uses GCC's regparm feature + - some (future) systems might want to pass parameters in registers. */ + +/* We must not pollute the global namespace. */ +#define mcount_internal __mcount_internal + +extern void mcount_internal (u_long frompc, u_long selfpc); + +#define _MCOUNT_DECL(frompc, selfpc) \ +void __attribute__ (( regparm (2) )) mcount_internal (u_long frompc, u_long selfpc) + + +/* Define MCOUNT as empty since we have the implementation in another + file. */ +#define MCOUNT diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/bits/sem.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/bits/sem.h new file mode 100644 index 00000000..c5c04bad --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/bits/sem.h @@ -0,0 +1,87 @@ +/* Copyright (C) 1995, 1996, 1997, 1998, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _SYS_SEM_H +# error "Never include directly; use instead." +#endif + +#include + +/* Flags for `semop'. */ +#define SEM_UNDO 0x1000 /* undo the operation on exit */ + +/* Commands for `semctl'. */ +#define GETPID 11 /* get sempid */ +#define GETVAL 12 /* get semval */ +#define GETALL 13 /* get all semval's */ +#define GETNCNT 14 /* get semncnt */ +#define GETZCNT 15 /* get semzcnt */ +#define SETVAL 16 /* set semval */ +#define SETALL 17 /* set all semval's */ + + +/* Data structure describing a set of semaphores. */ +struct semid_ds +{ + struct ipc_perm sem_perm; /* operation permission struct */ + __time_t sem_otime; /* last semop() time */ + unsigned long int __unused1; + __time_t sem_ctime; /* last time changed by semctl() */ + unsigned long int __unused2; + unsigned long int sem_nsems; /* number of semaphores in set */ + unsigned long int __unused3; + unsigned long int __unused4; +}; + +/* The user should define a union like the following to use it for arguments + for `semctl'. + + union semun + { + int val; <= value for SETVAL + struct semid_ds *buf; <= buffer for IPC_STAT & IPC_SET + unsigned short int *array; <= array for GETALL & SETALL + struct seminfo *__buf; <= buffer for IPC_INFO + }; + + Previous versions of this file used to define this union but this is + incorrect. One can test the macro _SEM_SEMUN_UNDEFINED to see whether + one must define the union or not. */ +#define _SEM_SEMUN_UNDEFINED 1 + +#ifdef __USE_MISC + +/* ipcs ctl cmds */ +# define SEM_STAT 18 +# define SEM_INFO 19 + +struct seminfo +{ + int semmap; + int semmni; + int semmns; + int semmnu; + int semmsl; + int semopm; + int semume; + int semusz; + int semvmx; + int semaem; +}; + +#endif /* __USE_MISC */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/bits/setjmp.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/bits/setjmp.h new file mode 100644 index 00000000..68a1b32b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/bits/setjmp.h @@ -0,0 +1,37 @@ +/* Define the machine-dependent type `jmp_buf'. Vax version. */ + +#ifndef _SETJMP_H +# error "Never include directly; use instead." +#endif + +/* we want to save enough that we can use this to fool RET, + * So we basically save all of the CALLS stack frame. Plus regs. */ +#ifndef _ASM +typedef int __jmp_buf[16]; +#endif + +/* Test if longjmp to JMPBUF would unwind the frame + containing a local variable at ADDRESS. */ +#define _JMPBUF_UNWINDS(jmpbuf, address) \ + ((void *) (address) < (void *) (jmpbuf[4])) +/* + jmp_buf layout. jmp_buf[0] + void *__cond; The condition handler + void *__psw; mask and PSW bits + void *__ap; argument pointer + void *__fp; frame pointer + void *__pc; program counter + no need to save r0 + void *__r1; regs, r0->r11. + void *__r2; regs, r0->r11. + void *__r3; regs, r0->r11. + void *__r4; regs, r0->r11. + void *__r5; regs, r0->r11. + void *__r6; regs, r0->r11. + void *__r7; regs, r0->r11. + void *__r8; regs, r0->r11. + void *__r9; regs, r0->r11. + void *__rA; regs, r0->r11. + void *__rB; regs, r0->r11. +*/ + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/bits/shm.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/bits/shm.h new file mode 100644 index 00000000..191709f0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/bits/shm.h @@ -0,0 +1,88 @@ +/* Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _SYS_SHM_H +# error "Never include directly; use instead." +#endif + +#include + +/* Permission flag for shmget. */ +#define SHM_R 0400 /* or S_IRUGO from */ +#define SHM_W 0200 /* or S_IWUGO from */ + +/* Flags for `shmat'. */ +#define SHM_RDONLY 010000 /* attach read-only else read-write */ +#define SHM_RND 020000 /* round attach address to SHMLBA */ +#define SHM_REMAP 040000 /* take-over region on attach */ + +/* Commands for `shmctl'. */ +#define SHM_LOCK 11 /* lock segment (root only) */ +#define SHM_UNLOCK 12 /* unlock segment (root only) */ + +__BEGIN_DECLS +/* Segment low boundary address multiple. */ +#define SHMLBA (__getpagesize ()) +extern int __getpagesize (void) __THROW __attribute__ ((__const__)); + +/* Data structure describing a set of semaphores. */ +struct shmid_ds + { + struct ipc_perm shm_perm; /* operation permission struct */ + int shm_segsz; /* size of segment in bytes */ + __time_t shm_atime; /* time of last shmat() */ + __time_t shm_dtime; /* time of last shmdt() */ + __time_t shm_ctime; /* time of last change by shmctl() */ + __ipc_pid_t shm_cpid; /* pid of creator */ + __ipc_pid_t shm_lpid; /* pid of last shmop */ + unsigned short int shm_nattch; /* number of current attaches */ + unsigned short int __shm_npages; /* size of segment (pages) */ + unsigned long int *__shm_pages; /* array of ptrs to frames -> SHMMAX */ + struct vm_area_struct *__attaches; /* descriptors for attaches */ + }; + +#ifdef __USE_MISC + +/* ipcs ctl commands */ +# define SHM_STAT 13 +# define SHM_INFO 14 + +/* shm_mode upper byte flags */ +# define SHM_DEST 01000 /* segment will be destroyed on last detach */ +# define SHM_LOCKED 02000 /* segment will not be swapped */ + +struct shminfo + { + int shmmax; + int shmmin; + int shmmni; + int shmseg; + int shmall; + }; + +struct shm_info + { + int used_ids; + unsigned long int shm_tot; /* total allocated shm */ + unsigned long int shm_rss; /* total resident shm */ + unsigned long int shm_swp; /* total swapped shm */ + unsigned long int swap_attempts; + unsigned long int swap_successes; + }; + +#endif /* __USE_MISC */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/bits/sigcontext.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/bits/sigcontext.h new file mode 100644 index 00000000..97cbf4b3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/bits/sigcontext.h @@ -0,0 +1,29 @@ +/* Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#if !defined _SIGNAL_H && !defined _SYS_UCONTEXT_H +# error "Never use directly; include instead." +#endif + +#ifndef sigcontext_struct +/* Kernel headers before 2.1.1 define a struct sigcontext_struct, but + we need sigcontext. */ +# define sigcontext_struct sigcontext + +# include +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/bits/stackinfo.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/bits/stackinfo.h new file mode 100644 index 00000000..4bdad496 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/bits/stackinfo.h @@ -0,0 +1,7 @@ +#ifndef _VAX_BITS_STACKINFO_H +#define _VAX_BITS_STACKINFO_H + +/* On VAXen, the stack grows down. */ +#define _STACK_GROWS_DOWN 1 + +#endif /* _VAX_BITS_STACKINFO_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/bits/statfs.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/bits/statfs.h new file mode 100644 index 00000000..31ae564b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/bits/statfs.h @@ -0,0 +1,61 @@ +/* Copyright (C) 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _SYS_STATFS_H +# error "Never include directly; use instead." +#endif + +#include /* for __fsid_t and __fsblkcnt_t*/ + +struct statfs + { + int f_type; + int f_bsize; +#ifndef __USE_FILE_OFFSET64 + __fsblkcnt_t f_blocks; + __fsblkcnt_t f_bfree; + __fsblkcnt_t f_bavail; + __fsfilcnt_t f_files; + __fsfilcnt_t f_ffree; +#else + __fsblkcnt64_t f_blocks; + __fsblkcnt64_t f_bfree; + __fsblkcnt64_t f_bavail; + __fsfilcnt64_t f_files; + __fsfilcnt64_t f_ffree; +#endif + __fsid_t f_fsid; + int f_namelen; + int f_spare[6]; + }; + +#ifdef __USE_LARGEFILE64 +struct statfs64 + { + int f_type; + int f_bsize; + __fsblkcnt64_t f_blocks; + __fsblkcnt64_t f_bfree; + __fsblkcnt64_t f_bavail; + __fsfilcnt64_t f_files; + __fsfilcnt64_t f_ffree; + __fsid_t f_fsid; + int f_namelen; + int f_spare[6]; + }; +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/bits/syscalls.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/bits/syscalls.h new file mode 100644 index 00000000..101aacb2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/bits/syscalls.h @@ -0,0 +1,258 @@ +#ifndef _BITS_SYSCALLS_H +#define _BITS_SYSCALLS_H +#ifndef _SYSCALL_H +# error "Never use directly; include instead." +#endif + +#ifndef __ASSEMBLER__ + +#include + +#define SYS_ify(syscall_name) (__NR_##syscall_name) + +#undef _syscall_return +#define _syscall_return(type) \ + do { \ + if ((unsigned long) (_sc_ret) >= (unsigned long) (-125)) { \ + __set_errno(-_sc_ret); \ + _sc_ret = -1; \ + } \ + \ + return (type) (_sc_ret); \ + } while (0) + +#define _syscall_clobbers \ + "r1", "r2", "r3", "r4", \ + "r5", "r6", "r7", "r8", \ + "r9", "r10", "r11" + +#ifdef _syscall0 +# undef _syscall0 +#endif +#define _syscall0(type, name) \ +type name (void) \ +{ \ + register long _sc_0 __asm__("r0") = SYS_ify (name); \ + long _sc_ret; \ + \ + __asm__ __volatile__ ( \ + " pushl %%ap \n" \ + " pushl $0x0 \n" \ + " movl %%sp, %%ap \n" \ + " chmk %%r0 \n" \ + " addl2 $4, %%sp \n" \ + " movl (%%sp)+, %%ap \n" \ + : "=r" (_sc_0) \ + : "0" (_sc_0) \ + : _syscall_clobbers); \ + \ + _sc_ret = _sc_0; \ + _syscall_return (type); \ +} + +#ifdef _syscall1 +# undef _syscall1 +#endif +#define _syscall1(type, name, type1, arg1) \ +type name (type1 arg1) \ +{ \ + register long _sc_0 __asm__("r0") = SYS_ify (name); \ + long _sc_ret; \ + \ + __asm__ __volatile__ ( \ + " pushl %%ap \n" \ + " pushl %2 \n" \ + " pushl $0x1 \n" \ + " movl %%sp, %%ap \n" \ + " chmk %%r0 \n" \ + " addl2 $8, %%sp \n" \ + " movl (%%sp)+, %%ap \n" \ + : "=r" (_sc_0) \ + : "0" (_sc_0), \ + "m" (arg1) \ + : _syscall_clobbers); \ + \ + _sc_ret = _sc_0; \ + _syscall_return (type); \ +} + +#ifdef _syscall2 +# undef _syscall2 +#endif +#define _syscall2(type, name, type1, arg1, type2, arg2) \ +type name (type1 arg1, \ + type2 arg2) \ +{ \ + register long _sc_0 __asm__("r0") = SYS_ify (name); \ + long _sc_ret; \ + \ + __asm__ __volatile__ ( \ + " pushl %%ap \n" \ + " pushl %3 \n" \ + " pushl %2 \n" \ + " pushl $0x2 \n" \ + " movl %%sp, %%ap \n" \ + " chmk %%r0 \n" \ + " addl2 $12, %%sp \n" \ + " movl (%%sp)+, %%ap \n" \ + : "=r" (_sc_0) \ + : "0" (_sc_0), \ + "m" (arg1), \ + "m" (arg2) \ + : _syscall_clobbers); \ + \ + _sc_ret = _sc_0; \ + _syscall_return (type); \ +} + +#ifdef _syscall3 +# undef _syscall3 +#endif +#define _syscall3(type, name, type1, arg1, type2, arg2, type3, arg3) \ +type name (type1 arg1, \ + type2 arg2, \ + type3 arg3) \ +{ \ + register long _sc_0 __asm__("r0") = SYS_ify (name); \ + long _sc_ret; \ + \ + __asm__ __volatile__ ( \ + " pushl %%ap \n" \ + " pushl %4 \n" \ + " pushl %3 \n" \ + " pushl %2 \n" \ + " pushl $0x3 \n" \ + " movl %%sp, %%ap \n" \ + " chmk %%r0 \n" \ + " addl2 $16, %%sp \n" \ + " movl (%%sp)+, %%ap \n" \ + : "=r" (_sc_0) \ + : "0" (_sc_0), \ + "m" (arg1), \ + "m" (arg2), \ + "m" (arg3) \ + : _syscall_clobbers); \ + \ + _sc_ret = _sc_0; \ + _syscall_return (type); \ +} + +#ifdef _syscall4 +# undef _syscall4 +#endif +#define _syscall4(type, name, type1, arg1, type2, arg2, type3, arg3, \ + type4, arg4) \ +type name (type1 arg1, \ + type2 arg2, \ + type3 arg3, \ + type4 arg4) \ +{ \ + register long _sc_0 __asm__("r0") = SYS_ify (name); \ + long _sc_ret; \ + \ + __asm__ __volatile__ ( \ + " pushl %%ap \n" \ + " pushl %5 \n" \ + " pushl %4 \n" \ + " pushl %3 \n" \ + " pushl %2 \n" \ + " pushl $0x4 \n" \ + " movl %%sp, %%ap \n" \ + " chmk %%r0 \n" \ + " addl2 $20, %%sp \n" \ + " movl (%%sp)+, %%ap \n" \ + : "=r" (_sc_0) \ + : "0" (_sc_0), \ + "m" (arg1), \ + "m" (arg2), \ + "m" (arg3), \ + "m" (arg4) \ + : _syscall_clobbers); \ + \ + _sc_ret = _sc_0; \ + _syscall_return (type); \ +} + +#ifdef _syscall5 +# undef _syscall5 +#endif +#define _syscall5(type, name, type1, arg1, type2, arg2, type3, arg3, \ + type4, arg4, type5, arg5) \ +type name (type1 arg1, \ + type2 arg2, \ + type3 arg3, \ + type4 arg4, \ + type5 arg5) \ +{ \ + register long _sc_0 __asm__("r0") = SYS_ify (name); \ + long _sc_ret; \ + \ + __asm__ __volatile__ ( \ + " pushl %%ap \n" \ + " pushl %6 \n" \ + " pushl %5 \n" \ + " pushl %4 \n" \ + " pushl %3 \n" \ + " pushl %2 \n" \ + " pushl $0x5 \n" \ + " movl %%sp, %%ap \n" \ + " chmk %%r0 \n" \ + " addl2 $24, %%sp \n" \ + " movl (%%sp)+, %%ap \n" \ + : "=r" (_sc_0) \ + : "0" (_sc_0), \ + "m" (arg1), \ + "m" (arg2), \ + "m" (arg3), \ + "m" (arg4), \ + "m" (arg5) \ + : _syscall_clobbers); \ + \ + _sc_ret = _sc_0; \ + _syscall_return (type); \ +} + +#ifdef _syscall6 +# undef _syscall6 +#endif +#define _syscall6(type, name, type1, arg1, type2, arg2, type3, arg3, \ + type4, arg4, type5, arg5, type6, arg6) \ +type name (type1 arg1, \ + type2 arg2, \ + type3 arg3, \ + type4 arg4, \ + type5 arg5, \ + type6 arg6) \ +{ \ + register long _sc_0 __asm__("r0") = SYS_ify (name); \ + long _sc_ret; \ + \ + __asm__ __volatile__ ( \ + " pushl %%ap \n" \ + " pushl %7 \n" \ + " pushl %6 \n" \ + " pushl %5 \n" \ + " pushl %4 \n" \ + " pushl %3 \n" \ + " pushl %2 \n" \ + " pushl $0x6 \n" \ + " movl %%sp, %%ap \n" \ + " chmk %%r0 \n" \ + " addl2 $28, %%sp \n" \ + " movl (%%sp)+, %%ap \n" \ + : "=r" (_sc_0) \ + : "0" (_sc_0), \ + "m" (arg1), \ + "m" (arg2), \ + "m" (arg3), \ + "m" (arg4), \ + "m" (arg5), \ + "m" (arg6) \ + : _syscall_clobbers); \ + \ + _sc_ret = _sc_0; \ + _syscall_return (type); \ +} + +#endif /* __ASSEMBLER__ */ +#endif /* _BITS_SYSCALLS_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/bits/uClibc_arch_features.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/bits/uClibc_arch_features.h new file mode 100644 index 00000000..f9a7b39c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/bits/uClibc_arch_features.h @@ -0,0 +1,47 @@ +/* + * Track misc arch-specific features that aren't config options + */ + +#ifndef _BITS_UCLIBC_ARCH_FEATURES_H +#define _BITS_UCLIBC_ARCH_FEATURES_H + +/* instruction used when calling abort() to kill yourself */ +#define __UCLIBC_ABORT_INSTRUCTION__ "halt" + +/* can your target use syscall6() for mmap ? */ +#define __UCLIBC_MMAP_HAS_6_ARGS__ + +/* does your target use syscall4() for truncate64 ? (32bit arches only) */ +#undef __UCLIBC_TRUNCATE64_HAS_4_ARGS__ + +/* does your target have a broken create_module() ? */ +#undef __UCLIBC_BROKEN_CREATE_MODULE__ + +/* does your target have to worry about older [gs]etrlimit() ? */ +#undef __UCLIBC_HANDLE_OLDER_RLIMIT__ + +/* does your target have an asm .set ? */ +#define __UCLIBC_HAVE_ASM_SET_DIRECTIVE__ + +/* define if target doesn't like .global */ +#undef __UCLIBC_ASM_GLOBAL_DIRECTIVE__ + +/* define if target supports .weak */ +#define __UCLIBC_HAVE_ASM_WEAK_DIRECTIVE__ + +/* define if target supports .weakext */ +#undef __UCLIBC_HAVE_ASM_WEAKEXT_DIRECTIVE__ + +/* needed probably only for ppc64 */ +#undef __UCLIBC_HAVE_ASM_GLOBAL_DOT_NAME__ + +/* define if target supports CFI pseudo ops */ +#undef __UCLIBC_HAVE_ASM_CFI_DIRECTIVES__ + +/* define if target supports IEEE signed zero floats */ +#undef __UCLIBC_HAVE_SIGNED_ZERO__ + +/* only weird assemblers generally need this */ +#undef __UCLIBC_ASM_LINE_SEP__ + +#endif /* _BITS_UCLIBC_ARCH_FEATURES_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/bits/wordsize.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/bits/wordsize.h new file mode 100644 index 00000000..62dad0c7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/bits/wordsize.h @@ -0,0 +1,19 @@ +/* Copyright (C) 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#define __WORDSIZE 32 diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/brk.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/brk.c new file mode 100644 index 00000000..c72ae369 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/brk.c @@ -0,0 +1,53 @@ +/* brk system call for Linux/VAX. + Copyright (C) 2000, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +/* This must be initialized data because commons can't have aliases. */ +void *__curbrk attribute_hidden = NULL; + +int +brk (void *addr) +{ + register unsigned long int result __asm__ ("%%r0"); + + __asm__ ( + " pushl %%ap \n" /* Start frame */ + " pushl %2 \n" /* New top address we wish to get */ + " pushl $1 \n" /* One argument */ + " movl %%sp, %%ap \n" /* Finish frame */ + " chmk %1 \n" /* Perform the system call */ + " addl2 $8, %%sp \n" /* Remove pushed arg */ + " movl (%%sp)+, %%ap \n" /* Get back %AP */ + : "=r" (result) + : "0" (__NR_brk), + "g" (addr)); + + if ((void *) result < addr) { + __set_errno (ENOMEM); + return -1; + } else + __curbrk = (void *) result; + + return 0; +} +libc_hidden_def(brk) + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/clone.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/clone.S new file mode 100644 index 00000000..086adc68 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/clone.S @@ -0,0 +1,85 @@ +/* Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* clone() is even more special than fork() as it mucks with stacks + and invokes a function in the right context after its all over. */ + +#include + +#warning "This file contains a hardcoded constant for SYS_clone" + +.section .rodata + .align 2 +.LC0: .long 120 /* SYS_clone */ +.align 4 +.text +.type clone,@function +.globl clone; +clone: + .word 0x0040 + /* subl2 $8, %sp */ + movl 4(%ap), %r1 + movl 8(%ap), %r0 + mcoml $21, %r6 + + /* Sanity check args. */ + tstl %r1 + jeql CLONE_ERROR_LABEL + tstl %r0 + jeql CLONE_ERROR_LABEL + + /* Need to setup the child stack the same as the parent. */ + subl2 $24, %r0 + movl 16(%ap), 20(%r0) + movl %r1, 16(%r0) + movl %r0, %r1 + addl2 $16, %r1 + movl %r1, 12(%r0) + + /* Do the system call. */ + pushl %ap + pushl %r0 + pushl 12(%ap) + pushl $0x2 + movl %sp, %ap + chmk .LC0 /* %r0 .LC0 -4(%fp) -8(%fp) */ + addl2 $12, %sp + movl (%sp)+, %ap + movl %r0, %r6 + jneq CLONE_ERROR_LABEL + + movl $0, %fp + pushl 4(%ap) + movl (%r1), %r0 + calls $1, (%r0) + pushl %r0 + calls $1, HIDDEN_JUMPTARGET(_exit) + +CLONE_ERROR_LABEL: + cmpl %r6, $-126 /* -ENOKEY?!?! Fuck, this must be wrong! FIXME */ + jlequ CLONE_RETURN_LABEL + calls $0, __errno_location + mnegl %r6, (%r0) + mcoml $0, %r6 + movl %r6, %r0 + ret + +CLONE_RETURN_LABEL: + ret + +.size clone,.-clone + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/crt1.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/crt1.S new file mode 100644 index 00000000..70960988 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/crt1.S @@ -0,0 +1,73 @@ +/* + * crt0 for VAX + */ + +/* + * Program stack looks like: + * sp-> argc argument counter (integer) + * argv[0] program name (pointer) + * argv[1...N] program args (pointers) + * argv[argc-1] end of args (integer) + * NULL + * env[0...N] environment variables (pointers) + * NULL + */ + +#include + +.text +.align 4 + +.global __start +__start: +.global _start +_start: + /* Kernel uses a_interp + 2, so __start isn't exactly CALLSed, */ + /* but we need to have two bytes here, so we use NOPs. This */ + /* won't hurt, though R0 would be invalid to push, but at */ + /* lease this looks like a real function. */ + .word 0x0101 + + movl $0, %fp /* FP = 0, since this is the */ + /* top-most stack frame */ + movl %sp, %r0 /* R0 = %sp */ + movl (%sp)+, %r4 /* R4 = argc */ + movl %sp, %r3 /* R3 = argv = &argv[0] */ + +#if (defined L_crt1 || defined L_gcrt1) && defined __UCLIBC_CTOR_DTOR__ + pushl %r0 /* stack_end */ + pushl $0 /* rtld_fini. This is probably needed for the */ + /* case where a dynamic linker is involved. So */ + /* this is an open FIXME that needs to be */ + /* addressed at some time... */ + pushl $_fini + pushl $_init + pushl %r3 /* Argument pointer */ + pushl %r4 /* And the argument count */ + pushl $main /* main() */ + + /* We need to call __uClibc_main which should not return. + * __uClibc_main (int (*main) (int, char **, char **), + * int argc, + * char **argv, + * void (*init) (void), + * void (*fini) (void), + * void (*rtld_fini) (void), + * void *stack_end); + */ + calls $7, __uClibc_main +#else /* FIXME: THIS IS BROKEN!!! */ + /* start to load the arguments from the stack */ + /* arguments are on ap stack */ + pushl %r2 + pushl %r3 + pushl %r4 + + calls $3, __uClibc_main +#endif + + /* The above __uClibc_start_main() shouldn't ever return. If it */ + /* does, we just crash. */ + halt +.align 2 + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/crti.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/crti.S new file mode 100644 index 00000000..0056478b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/crti.S @@ -0,0 +1,21 @@ + .file "initfini.c" + .version "01.01" +gcc2_compiled.: +__gnu_compiled_c: + .section .init + .align 1 +.globl _init + .type _init,@function +_init: + .word 0x0000 + + .align 1 + + .section .fini + .align 1 +.globl _fini + .type _fini,@function +_fini: + .word 0x0000 + .align 1 + .ident "GCC: (GNU) 2.95.2 19991024 (release) (Linux/VAX CVS)" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/crtn.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/crtn.S new file mode 100644 index 00000000..1153fd50 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/crtn.S @@ -0,0 +1,19 @@ + .file "initfini.c" + .version "01.01" +gcc2_compiled.: +__gnu_compiled_c: + + .section .init + .align 1 +.globl _init + .type _init,@function + ret +.Lfe2: + + .section .fini + .align 1 +.globl _fini + .type _fini,@function + ret +.Lfe3: + .ident "GCC: (GNU) 2.95.2 19991024 (release) (Linux/VAX CVS)" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/mmap.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/mmap.c new file mode 100644 index 00000000..2bc347f4 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/mmap.c @@ -0,0 +1,10 @@ + +#include +#include +#include +#include + +_syscall6 (void *, mmap, void *, start, size_t, length, int, prot, int, flags, + int, fd, off_t, offset) +libc_hidden_def(mmap) + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/setjmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/setjmp.S new file mode 100644 index 00000000..bdbde4b1 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/setjmp.S @@ -0,0 +1,39 @@ + +/* + * setjmp.S atp. Sept. 2001 + * Jan-Benedict Glaw 2006 + * + * Save regs and info needed for a longjmp + */ + +.globl __sigsetjmp +.align 4 +__sigsetjmp: + .word 0x0000 /* We look after reg saving here - this */ + /* must match longjmp. */ + movl 0x4(%ap), %r0 /* Our scratch reg */ + /* kenn would probably use movq here. :-) */ + movl %r1, 0x14(%r0) /* save regs */ + movl %r2, 0x18(%r0) + movl %r3, 0x1c(%r0) + movl %r4, 0x20(%r0) + movl %r5, 0x24(%r0) + movl %r6, 0x28(%r0) + movl %r7, 0x2c(%r0) + movl %r8, 0x30(%r0) + movl %r9, 0x34(%r0) + movl %r10, 0x38(%r0) + movl %r11, 0x3c(%r0) + /* Now save our call frame */ + movl (%fp), (%r0) /* Condition handler (for VMS emulation) */ + movl 0x4(%fp), 0x4(%r0) /* psw */ + movl 0x8(%fp), 0x8(%r0) /* ap */ + movl 0xc(%fp), 0xc(%r0) /* fp */ + movl 0x10(%fp), 0x10(%r0) /* pc */ + /* Call the sigjmp save routine */ + pushl 8(%ap) + pushl %r0 + calls $2, __sigjmp_save + /* Done */ + ret + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/sys/procfs.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/sys/procfs.h new file mode 100644 index 00000000..9c233508 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/sys/procfs.h @@ -0,0 +1,123 @@ +/* Copyright (C) 1996, 1997, 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_PROCFS_H +#define _SYS_PROCFS_H 1 + +/* This is somewhat modelled after the file of the same name on SVR4 + systems. It provides a definition of the core file format for ELF + used on Linux. It doesn't have anything to do with the /proc file + system, even though Linux has one. + + Anyway, the whole purpose of this file is for GDB and GDB only. + Don't read too much into it. Don't use it for anything other than + GDB unless you know what you are doing. */ + +#include +#include +#include +#include + +__BEGIN_DECLS + +/* Type for a general-purpose register. */ +typedef unsigned long elf_greg_t; + +/* And the whole bunch of them. We could have used `struct + user_regs' directly in the typedef, but tradition says that + the register set is an array, which does have some peculiar + semantics, so leave it that way. */ +#define ELF_NGREG (sizeof (struct user_regs_struct) / sizeof(elf_greg_t)) +typedef elf_greg_t elf_gregset_t[ELF_NGREG]; + +/* Register set for the floating-point registers. */ +typedef struct user_regs_struct elf_fpregset_t; + +/* Signal info. */ +struct elf_siginfo + { + int si_signo; /* Signal number. */ + int si_code; /* Extra code. */ + int si_errno; /* Errno. */ + }; + +/* Definitions to generate Intel SVR4-like core files. These mostly + have the same names as the SVR4 types with "elf_" tacked on the + front to prevent clashes with Linux definitions, and the typedef + forms have been avoided. This is mostly like the SVR4 structure, + but more Linuxy, with things that Linux does not support and which + GDB doesn't really use excluded. */ + +struct elf_prstatus + { + struct elf_siginfo pr_info; /* Info associated with signal. */ + short int pr_cursig; /* Current signal. */ + unsigned long int pr_sigpend; /* Set of pending signals. */ + unsigned long int pr_sighold; /* Set of held signals. */ + __pid_t pr_pid; + __pid_t pr_ppid; + __pid_t pr_pgrp; + __pid_t pr_sid; + struct timeval pr_utime; /* User time. */ + struct timeval pr_stime; /* System time. */ + struct timeval pr_cutime; /* Cumulative user time. */ + struct timeval pr_cstime; /* Cumulative system time. */ + elf_gregset_t pr_reg; /* GP registers. */ + int pr_fpvalid; /* True if math copro being used. */ + }; + + +#define ELF_PRARGSZ (80) /* Number of chars for args. */ + +struct elf_prpsinfo + { + char pr_state; /* Numeric process state. */ + char pr_sname; /* Char for pr_state. */ + char pr_zomb; /* Zombie. */ + char pr_nice; /* Nice val. */ + unsigned long int pr_flag; /* Flags. */ + unsigned short int pr_uid; + unsigned short int pr_gid; + int pr_pid, pr_ppid, pr_pgrp, pr_sid; + /* Lots missing */ + char pr_fname[16]; /* Filename of executable. */ + char pr_psargs[ELF_PRARGSZ]; /* Initial part of arg list. */ + }; + +/* The rest of this file provides the types for emulation of the + Solaris interfaces that should be implemented by + users of libthread_db. */ + +/* Addresses. */ +typedef void *psaddr_t; + +/* Register sets. Linux has different names. */ +typedef elf_gregset_t prgregset_t; +typedef elf_fpregset_t prfpregset_t; + +/* We don't have any differences between processes and threads, + therefore have only one PID type. */ +typedef __pid_t lwpid_t; + +/* Process status and info. In the end we do provide typedefs for them. */ +typedef struct elf_prstatus prstatus_t; +typedef struct elf_prpsinfo prpsinfo_t; + +__END_DECLS + +#endif /* sys/procfs.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/sys/ucontext.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/sys/ucontext.h new file mode 100644 index 00000000..f57b91e4 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/vax/sys/ucontext.h @@ -0,0 +1,80 @@ +/* Copyright (C) 1997, 1998, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Don't rely on this, the interface is currently messed up and may need to + be broken to be fixed. */ +#ifndef _SYS_UCONTEXT_H +#define _SYS_UCONTEXT_H 1 + +#include +#include + +/* We need the signal context definitions even if they are not used + included in . */ +#include + + +/* Type for general register. */ +typedef unsigned long int greg_t; + +/* Number of general registers. */ +#define NGREG 37 +#define NFPREG 33 + +/* Container for all general registers. */ +/* gregset_t must be an array. The below declared array corresponds to: +typedef struct gregset { + greg_t g_regs[32]; + greg_t g_hi; + greg_t g_lo; + greg_t g_pad[3]; +} gregset_t; */ +typedef greg_t gregset_t[NGREG]; + +/* Container for all FPU registers. */ +typedef struct fpregset { + union { + double fp_dregs[32]; + struct { + float _fp_fregs; + unsigned int _fp_pad; + } fp_fregs[32]; + } fp_r; + unsigned int fp_csr; + unsigned int fp_pad; +} fpregset_t; + + +/* Context to describe whole processor state. */ +typedef struct + { + gregset_t gregs; + fpregset_t fpregs; + } mcontext_t; + +/* Userlevel context. */ +typedef struct ucontext + { + unsigned long int uc_flags; + struct ucontext *uc_link; + stack_t uc_stack; + mcontext_t uc_mcontext; + __sigset_t uc_sigmask; + } ucontext_t; + +#endif /* sys/ucontext.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/Makefile new file mode 100644 index 00000000..633c91f3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../../ +top_builddir=../../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.arch +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/Makefile.arch b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/Makefile.arch new file mode 100644 index 00000000..de7ce728 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/Makefile.arch @@ -0,0 +1,19 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +CSRC := brk.c __syscall_error.c mmap.c + +ifneq ($(UCLIBC_HAS_THREADS_NATIVE),y) +CSRC += sigaction.c +endif + +SSRC := \ + __longjmp.S setjmp.S syscall.S bsd-setjmp.S bsd-_setjmp.S + +ifneq ($(UCLIBC_HAS_THREADS_NATIVE),y) +SSRC += vfork.S clone.S +endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/__longjmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/__longjmp.S new file mode 100644 index 00000000..db2928bf --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/__longjmp.S @@ -0,0 +1,46 @@ +/* Copyright (C) 2001, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#define _ASM +#define _SETJMP_H +#include + +/* Jump to the position specified by ENV, causing the + setjmp call there to return VAL, or 1 if VAL is 0. + void __longjmp (__jmp_buf env, int val). */ +.global __longjmp +.type __longjmp,%function +__longjmp: + /* Restore registers. */ + movq (JB_RBX*8)(%rdi),%rbx + movq (JB_RBP*8)(%rdi),%rbp + movq (JB_R12*8)(%rdi),%r12 + movq (JB_R13*8)(%rdi),%r13 + movq (JB_R14*8)(%rdi),%r14 + movq (JB_R15*8)(%rdi),%r15 + /* Set return value for setjmp. */ + test %esi,%esi + mov $01,%eax + cmove %eax,%esi + mov %esi, %eax + movq (JB_PC*8)(%rdi),%rdx + movq (JB_RSP*8)(%rdi),%rsp + jmpq *%rdx +.size __longjmp,.-__longjmp +libc_hidden_def(__longjmp) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/__syscall_error.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/__syscall_error.c new file mode 100644 index 00000000..448f5098 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/__syscall_error.c @@ -0,0 +1,21 @@ +/* Wrapper for setting errno. + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +/* This routine is jumped to by all the syscall handlers, to stash + * an error number into errno. */ +int __syscall_error(void) attribute_hidden; +int __syscall_error(void) +{ + register int err_no __asm__ ("%rcx"); + __asm__ ("mov %rax, %rcx\n\t" + "neg %rcx"); + __set_errno(err_no); + return -1; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bits/atomic.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bits/atomic.h new file mode 100644 index 00000000..6739afa4 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bits/atomic.h @@ -0,0 +1,324 @@ +/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + + +typedef int8_t atomic8_t; +typedef uint8_t uatomic8_t; +typedef int_fast8_t atomic_fast8_t; +typedef uint_fast8_t uatomic_fast8_t; + +typedef int16_t atomic16_t; +typedef uint16_t uatomic16_t; +typedef int_fast16_t atomic_fast16_t; +typedef uint_fast16_t uatomic_fast16_t; + +typedef int32_t atomic32_t; +typedef uint32_t uatomic32_t; +typedef int_fast32_t atomic_fast32_t; +typedef uint_fast32_t uatomic_fast32_t; + +typedef int64_t atomic64_t; +typedef uint64_t uatomic64_t; +typedef int_fast64_t atomic_fast64_t; +typedef uint_fast64_t uatomic_fast64_t; + +typedef intptr_t atomicptr_t; +typedef uintptr_t uatomicptr_t; +typedef intmax_t atomic_max_t; +typedef uintmax_t uatomic_max_t; + + +#ifndef LOCK_PREFIX +# ifdef UP +# define LOCK_PREFIX /* nothing */ +# else +# define LOCK_PREFIX "lock;" +# endif +#endif + + +#define __arch_compare_and_exchange_val_8_acq(mem, newval, oldval) \ + ({ __typeof (*mem) ret; \ + __asm__ __volatile__ (LOCK_PREFIX "cmpxchgb %b2, %1" \ + : "=a" (ret), "=m" (*mem) \ + : "q" (newval), "m" (*mem), "0" (oldval)); \ + ret; }) + +#define __arch_compare_and_exchange_val_16_acq(mem, newval, oldval) \ + ({ __typeof (*mem) ret; \ + __asm__ __volatile__ (LOCK_PREFIX "cmpxchgw %w2, %1" \ + : "=a" (ret), "=m" (*mem) \ + : "r" (newval), "m" (*mem), "0" (oldval)); \ + ret; }) + +#define __arch_compare_and_exchange_val_32_acq(mem, newval, oldval) \ + ({ __typeof (*mem) ret; \ + __asm__ __volatile__ (LOCK_PREFIX "cmpxchgl %2, %1" \ + : "=a" (ret), "=m" (*mem) \ + : "r" (newval), "m" (*mem), "0" (oldval)); \ + ret; }) + +#define __arch_compare_and_exchange_val_64_acq(mem, newval, oldval) \ + ({ __typeof (*mem) ret; \ + __asm__ __volatile__ (LOCK_PREFIX "cmpxchgq %q2, %1" \ + : "=a" (ret), "=m" (*mem) \ + : "r" ((long) (newval)), "m" (*mem), \ + "0" ((long) (oldval))); \ + ret; }) + + +/* Note that we need no lock prefix. */ +#define atomic_exchange_acq(mem, newvalue) \ + ({ __typeof (*mem) result; \ + if (sizeof (*mem) == 1) \ + __asm__ __volatile__ ("xchgb %b0, %1" \ + : "=r" (result), "=m" (*mem) \ + : "0" (newvalue), "m" (*mem)); \ + else if (sizeof (*mem) == 2) \ + __asm__ __volatile__ ("xchgw %w0, %1" \ + : "=r" (result), "=m" (*mem) \ + : "0" (newvalue), "m" (*mem)); \ + else if (sizeof (*mem) == 4) \ + __asm__ __volatile__ ("xchgl %0, %1" \ + : "=r" (result), "=m" (*mem) \ + : "0" (newvalue), "m" (*mem)); \ + else \ + __asm__ __volatile__ ("xchgq %q0, %1" \ + : "=r" (result), "=m" (*mem) \ + : "0" ((long) (newvalue)), "m" (*mem)); \ + result; }) + + +#define atomic_exchange_and_add(mem, value) \ + ({ __typeof (*mem) result; \ + if (sizeof (*mem) == 1) \ + __asm__ __volatile__ (LOCK_PREFIX "xaddb %b0, %1" \ + : "=r" (result), "=m" (*mem) \ + : "0" (value), "m" (*mem)); \ + else if (sizeof (*mem) == 2) \ + __asm__ __volatile__ (LOCK_PREFIX "xaddw %w0, %1" \ + : "=r" (result), "=m" (*mem) \ + : "0" (value), "m" (*mem)); \ + else if (sizeof (*mem) == 4) \ + __asm__ __volatile__ (LOCK_PREFIX "xaddl %0, %1" \ + : "=r" (result), "=m" (*mem) \ + : "0" (value), "m" (*mem)); \ + else \ + __asm__ __volatile__ (LOCK_PREFIX "xaddq %q0, %1" \ + : "=r" (result), "=m" (*mem) \ + : "0" ((long) (value)), "m" (*mem)); \ + result; }) + + +#define atomic_add(mem, value) \ + (void) ({ if (__builtin_constant_p (value) && (value) == 1) \ + atomic_increment (mem); \ + else if (__builtin_constant_p (value) && (value) == 1) \ + atomic_decrement (mem); \ + else if (sizeof (*mem) == 1) \ + __asm__ __volatile__ (LOCK_PREFIX "addb %b1, %0" \ + : "=m" (*mem) \ + : "ir" (value), "m" (*mem)); \ + else if (sizeof (*mem) == 2) \ + __asm__ __volatile__ (LOCK_PREFIX "addw %w1, %0" \ + : "=m" (*mem) \ + : "ir" (value), "m" (*mem)); \ + else if (sizeof (*mem) == 4) \ + __asm__ __volatile__ (LOCK_PREFIX "addl %1, %0" \ + : "=m" (*mem) \ + : "ir" (value), "m" (*mem)); \ + else \ + __asm__ __volatile__ (LOCK_PREFIX "addq %q1, %0" \ + : "=m" (*mem) \ + : "ir" ((long) (value)), "m" (*mem)); \ + }) + + +#define atomic_add_negative(mem, value) \ + ({ unsigned char __result; \ + if (sizeof (*mem) == 1) \ + __asm__ __volatile__ (LOCK_PREFIX "addb %b2, %0; sets %1" \ + : "=m" (*mem), "=qm" (__result) \ + : "ir" (value), "m" (*mem)); \ + else if (sizeof (*mem) == 2) \ + __asm__ __volatile__ (LOCK_PREFIX "addw %w2, %0; sets %1" \ + : "=m" (*mem), "=qm" (__result) \ + : "ir" (value), "m" (*mem)); \ + else if (sizeof (*mem) == 4) \ + __asm__ __volatile__ (LOCK_PREFIX "addl %2, %0; sets %1" \ + : "=m" (*mem), "=qm" (__result) \ + : "ir" (value), "m" (*mem)); \ + else \ + __asm__ __volatile__ (LOCK_PREFIX "addq %q2, %0; sets %1" \ + : "=m" (*mem), "=qm" (__result) \ + : "ir" ((long) (value)), "m" (*mem)); \ + __result; }) + + +#define atomic_add_zero(mem, value) \ + ({ unsigned char __result; \ + if (sizeof (*mem) == 1) \ + __asm__ __volatile__ (LOCK_PREFIX "addb %b2, %0; setz %1" \ + : "=m" (*mem), "=qm" (__result) \ + : "ir" (value), "m" (*mem)); \ + else if (sizeof (*mem) == 2) \ + __asm__ __volatile__ (LOCK_PREFIX "addw %w2, %0; setz %1" \ + : "=m" (*mem), "=qm" (__result) \ + : "ir" (value), "m" (*mem)); \ + else if (sizeof (*mem) == 4) \ + __asm__ __volatile__ (LOCK_PREFIX "addl %2, %0; setz %1" \ + : "=m" (*mem), "=qm" (__result) \ + : "ir" (value), "m" (*mem)); \ + else \ + __asm__ __volatile__ (LOCK_PREFIX "addq %q2, %0; setz %1" \ + : "=m" (*mem), "=qm" (__result) \ + : "ir" ((long) (value)), "m" (*mem)); \ + __result; }) + + +#define atomic_increment(mem) \ + (void) ({ if (sizeof (*mem) == 1) \ + __asm__ __volatile__ (LOCK_PREFIX "incb %b0" \ + : "=m" (*mem) \ + : "m" (*mem)); \ + else if (sizeof (*mem) == 2) \ + __asm__ __volatile__ (LOCK_PREFIX "incw %w0" \ + : "=m" (*mem) \ + : "m" (*mem)); \ + else if (sizeof (*mem) == 4) \ + __asm__ __volatile__ (LOCK_PREFIX "incl %0" \ + : "=m" (*mem) \ + : "m" (*mem)); \ + else \ + __asm__ __volatile__ (LOCK_PREFIX "incq %q0" \ + : "=m" (*mem) \ + : "m" (*mem)); \ + }) + + +#define atomic_increment_and_test(mem) \ + ({ unsigned char __result; \ + if (sizeof (*mem) == 1) \ + __asm__ __volatile__ (LOCK_PREFIX "incb %b0; sete %1" \ + : "=m" (*mem), "=qm" (__result) \ + : "m" (*mem)); \ + else if (sizeof (*mem) == 2) \ + __asm__ __volatile__ (LOCK_PREFIX "incw %w0; sete %1" \ + : "=m" (*mem), "=qm" (__result) \ + : "m" (*mem)); \ + else if (sizeof (*mem) == 4) \ + __asm__ __volatile__ (LOCK_PREFIX "incl %0; sete %1" \ + : "=m" (*mem), "=qm" (__result) \ + : "m" (*mem)); \ + else \ + __asm__ __volatile__ (LOCK_PREFIX "incq %q0; sete %1" \ + : "=m" (*mem), "=qm" (__result) \ + : "m" (*mem)); \ + __result; }) + + +#define atomic_decrement(mem) \ + (void) ({ if (sizeof (*mem) == 1) \ + __asm__ __volatile__ (LOCK_PREFIX "decb %b0" \ + : "=m" (*mem) \ + : "m" (*mem)); \ + else if (sizeof (*mem) == 2) \ + __asm__ __volatile__ (LOCK_PREFIX "decw %w0" \ + : "=m" (*mem) \ + : "m" (*mem)); \ + else if (sizeof (*mem) == 4) \ + __asm__ __volatile__ (LOCK_PREFIX "decl %0" \ + : "=m" (*mem) \ + : "m" (*mem)); \ + else \ + __asm__ __volatile__ (LOCK_PREFIX "decq %q0" \ + : "=m" (*mem) \ + : "m" (*mem)); \ + }) + + +#define atomic_decrement_and_test(mem) \ + ({ unsigned char __result; \ + if (sizeof (*mem) == 1) \ + __asm__ __volatile__ (LOCK_PREFIX "decb %b0; sete %1" \ + : "=m" (*mem), "=qm" (__result) \ + : "m" (*mem)); \ + else if (sizeof (*mem) == 2) \ + __asm__ __volatile__ (LOCK_PREFIX "decw %w0; sete %1" \ + : "=m" (*mem), "=qm" (__result) \ + : "m" (*mem)); \ + else if (sizeof (*mem) == 4) \ + __asm__ __volatile__ (LOCK_PREFIX "decl %0; sete %1" \ + : "=m" (*mem), "=qm" (__result) \ + : "m" (*mem)); \ + else \ + __asm__ __volatile__ (LOCK_PREFIX "decq %q0; sete %1" \ + : "=m" (*mem), "=qm" (__result) \ + : "m" (*mem)); \ + __result; }) + + +#define atomic_bit_set(mem, bit) \ + (void) ({ if (sizeof (*mem) == 1) \ + __asm__ __volatile__ (LOCK_PREFIX "orb %b2, %0" \ + : "=m" (*mem) \ + : "m" (*mem), "ir" (1L << (bit))); \ + else if (sizeof (*mem) == 2) \ + __asm__ __volatile__ (LOCK_PREFIX "orw %w2, %0" \ + : "=m" (*mem) \ + : "m" (*mem), "ir" (1L << (bit))); \ + else if (sizeof (*mem) == 4) \ + __asm__ __volatile__ (LOCK_PREFIX "orl %2, %0" \ + : "=m" (*mem) \ + : "m" (*mem), "ir" (1L << (bit))); \ + else if (__builtin_constant_p (bit) && (bit) < 32) \ + __asm__ __volatile__ (LOCK_PREFIX "orq %2, %0" \ + : "=m" (*mem) \ + : "m" (*mem), "i" (1L << (bit))); \ + else \ + __asm__ __volatile__ (LOCK_PREFIX "orq %q2, %0" \ + : "=m" (*mem) \ + : "m" (*mem), "r" (1UL << (bit))); \ + }) + + +#define atomic_bit_test_set(mem, bit) \ + ({ unsigned char __result; \ + if (sizeof (*mem) == 1) \ + __asm__ __volatile__ (LOCK_PREFIX "btsb %3, %1; setc %0" \ + : "=q" (__result), "=m" (*mem) \ + : "m" (*mem), "ir" (bit)); \ + else if (sizeof (*mem) == 2) \ + __asm__ __volatile__ (LOCK_PREFIX "btsw %3, %1; setc %0" \ + : "=q" (__result), "=m" (*mem) \ + : "m" (*mem), "ir" (bit)); \ + else if (sizeof (*mem) == 4) \ + __asm__ __volatile__ (LOCK_PREFIX "btsl %3, %1; setc %0" \ + : "=q" (__result), "=m" (*mem) \ + : "m" (*mem), "ir" (bit)); \ + else \ + __asm__ __volatile__ (LOCK_PREFIX "btsq %3, %1; setc %0" \ + : "=q" (__result), "=m" (*mem) \ + : "m" (*mem), "ir" (bit)); \ + __result; }) + + +#define atomic_delay() __asm__ ("rep; nop") diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bits/byteswap.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bits/byteswap.h new file mode 100644 index 00000000..a9cf23d7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bits/byteswap.h @@ -0,0 +1,68 @@ +/* Macros to swap the order of bytes in integer values. + Copyright (C) 1997, 1998, 2000, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _ASM_BITS_BYTESWAP_H +#define _ASM_BITS_BYTESWAP_H 1 + +#include + +#define __bswap_non_constant_16(x) \ + (__extension__ \ + ({ register unsigned short int __v; \ + __asm__ ("rorw $8, %w0" \ + : "=r" (__v) \ + : "0" (x) \ + : "cc"); \ + __v; })) + +#if __WORDSIZE == 64 || (defined __i486__ || defined __pentium__ \ + || defined __pentiumpro__ || defined __pentium4__ \ + || defined __k8__ || defined __athlon__ \ + || defined __k6__) +/* To swap the bytes in a word the i486 processors and up provide the + `bswap' opcode. On i386 we have to use three instructions. */ +# define __bswap_non_constant_32(x) \ + (__extension__ \ + ({ register unsigned int __v; \ + __asm__ ("bswap %0" : "=r" (__v) : "0" (x)); \ + __v; })) +#else +# define __bswap_non_constant_32(x) \ + (__extension__ \ + ({ register unsigned int __v; \ + __asm__ ("rorw $8, %w0;" \ + "rorl $16, %0;" \ + "rorw $8, %w0" \ + : "=r" (__v) \ + : "0" (x) \ + : "cc"); \ + __v; })) +#endif + +#if __WORDSIZE == 64 +# define __bswap_non_constant_64(x) \ + (__extension__ \ + ({ register unsigned long __v; \ + __asm__ ("bswap %q0" : "=r" (__v) : "0" (x)); \ + __v; })) +#endif + +#endif + +#include diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bits/endian.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bits/endian.h new file mode 100644 index 00000000..2f59eada --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bits/endian.h @@ -0,0 +1,7 @@ +/* x86_64 is little-endian. */ + +#ifndef _ENDIAN_H +# error "Never use directly; include instead." +#endif + +#define __BYTE_ORDER __LITTLE_ENDIAN diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bits/environments.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bits/environments.h new file mode 100644 index 00000000..a51a564c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bits/environments.h @@ -0,0 +1,87 @@ +/* Copyright (C) 1999, 2001, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _UNISTD_H +# error "Never include this file directly. Use instead" +#endif + +#include + +/* This header should define the following symbols under the described + situations. A value `1' means that the model is always supported, + `-1' means it is never supported. Undefined means it cannot be + statically decided. + + _POSIX_V6_ILP32_OFF32 32bit int, long, pointers, and off_t type + _POSIX_V6_ILP32_OFFBIG 32bit int, long, and pointers and larger off_t type + + _POSIX_V6_LP64_OFF32 64bit long and pointers and 32bit off_t type + _POSIX_V6_LPBIG_OFFBIG 64bit long and pointers and large off_t type + + The macros _XBS5_ILP32_OFF32, _XBS5_ILP32_OFFBIG, _XBS5_LP64_OFF32, and + _XBS5_LPBIG_OFFBIG were used in previous versions of the Unix standard + and are available only for compatibility. +*/ + +#if __WORDSIZE == 64 + +/* Environments with 32-bit wide pointers are optionally provided. + Therefore following macros aren't defined: + # undef _POSIX_V6_ILP32_OFF32 + # undef _POSIX_V6_ILP32_OFFBIG + # undef _XBS5_ILP32_OFF32 + # undef _XBS5_ILP32_OFFBIG + and users need to check at runtime. */ + +/* We also have no use (for now) for an environment with bigger pointers + and offsets. */ +# define _POSIX_V6_LPBIG_OFFBIG -1 +# define _XBS5_LPBIG_OFFBIG -1 + +/* By default we have 64-bit wide `long int', pointers and `off_t'. */ +# define _POSIX_V6_LP64_OFF64 1 +# define _XBS5_LP64_OFF64 1 + +#else /* __WORDSIZE == 32 */ + +/* By default we have 32-bit wide `int', `long int', pointers and `off_t' + and all platforms support LFS. */ +# define _POSIX_V6_ILP32_OFF32 1 +# define _POSIX_V6_ILP32_OFFBIG 1 +# define _XBS5_ILP32_OFF32 1 +# define _XBS5_ILP32_OFFBIG 1 + +/* We optionally provide an environment with the above size but an 64-bit + side `off_t'. Therefore we don't define _XBS5_ILP32_OFFBIG. */ + +/* Environments with 64-bit wide pointers can be provided, + so these macros aren't defined: + # undef _POSIX_V6_LP64_OFF64 + # undef _POSIX_V6_LPBIG_OFFBIG + # undef _XBS5_LP64_OFF64 + # undef _XBS5_LPBIG_OFFBIG + and sysconf tests for it at runtime. */ + +#endif /* __WORDSIZE == 32 */ + +#define __ILP32_OFF32_CFLAGS "-m32" +#define __ILP32_OFFBIG_CFLAGS "-m32 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64" +#define __ILP32_OFF32_LDFLAGS "-m32" +#define __ILP32_OFFBIG_LDFLAGS "-m32" +#define __LP64_OFF64_CFLAGS "-m64" +#define __LP64_OFF64_LDFLAGS "-m64" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bits/fcntl.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bits/fcntl.h new file mode 100644 index 00000000..f1cf3886 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bits/fcntl.h @@ -0,0 +1,253 @@ +/* O_*, F_*, FD_* bit values for Linux/x86-64. + Copyright (C) 2001, 2002, 2004, 2006, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FCNTL_H +# error "Never use directly; include instead." +#endif + +#include +#include +#ifdef __USE_GNU +# include +#endif + + +/* open/fcntl - O_SYNC is only implemented on blocks devices and on files + located on an ext2 file system */ +#define O_ACCMODE 0003 +#define O_RDONLY 00 +#define O_WRONLY 01 +#define O_RDWR 02 +#define O_CREAT 0100 /* not fcntl */ +#define O_EXCL 0200 /* not fcntl */ +#define O_NOCTTY 0400 /* not fcntl */ +#define O_TRUNC 01000 /* not fcntl */ +#define O_APPEND 02000 +#define O_NONBLOCK 04000 +#define O_NDELAY O_NONBLOCK +#define O_SYNC 010000 +#define O_FSYNC O_SYNC +#define O_ASYNC 020000 + +#ifdef __USE_GNU +# define O_DIRECT 040000 /* Direct disk access. */ +# define O_DIRECTORY 0200000 /* Must be a directory. */ +# define O_NOFOLLOW 0400000 /* Do not follow links. */ +# define O_NOATIME 01000000 /* Do not set atime. */ +# define O_CLOEXEC 02000000 /* Set close_on_exec. */ +#endif + +/* For now Linux has synchronisity options for data and read operations. + We define the symbols here but let them do the same as O_SYNC since + this is a superset. */ +#if defined __USE_POSIX199309 || defined __USE_UNIX98 +# define O_DSYNC O_SYNC /* Synchronize data. */ +# define O_RSYNC O_SYNC /* Synchronize read operations. */ +#endif + +#ifdef __USE_LARGEFILE64 +# if __WORDSIZE == 64 +# define O_LARGEFILE 0 +# else +# define O_LARGEFILE 0100000 +# endif +#endif + +/* Values for the second argument to `fcntl'. */ +#define F_DUPFD 0 /* Duplicate file descriptor. */ +#define F_GETFD 1 /* Get file descriptor flags. */ +#define F_SETFD 2 /* Set file descriptor flags. */ +#define F_GETFL 3 /* Get file status flags. */ +#define F_SETFL 4 /* Set file status flags. */ +#if __WORDSIZE == 64 +# define F_GETLK 5 /* Get record locking info. */ +# define F_SETLK 6 /* Set record locking info (non-blocking). */ +# define F_SETLKW 7 /* Set record locking info (blocking). */ +/* Not necessary, we always have 64-bit offsets. */ +# define F_GETLK64 5 /* Get record locking info. */ +# define F_SETLK64 6 /* Set record locking info (non-blocking). */ +# define F_SETLKW64 7 /* Set record locking info (blocking). */ +#else +# ifndef __USE_FILE_OFFSET64 +# define F_GETLK 5 /* Get record locking info. */ +# define F_SETLK 6 /* Set record locking info (non-blocking). */ +# define F_SETLKW 7 /* Set record locking info (blocking). */ +# else +# define F_GETLK F_GETLK64 /* Get record locking info. */ +# define F_SETLK F_SETLK64 /* Set record locking info (non-blocking).*/ +# define F_SETLKW F_SETLKW64 /* Set record locking info (blocking). */ +# endif +# define F_GETLK64 12 /* Get record locking info. */ +# define F_SETLK64 13 /* Set record locking info (non-blocking). */ +# define F_SETLKW64 14 /* Set record locking info (blocking). */ +#endif + +#if defined __USE_BSD || defined __USE_UNIX98 +# define F_SETOWN 8 /* Get owner of socket (receiver of SIGIO). */ +# define F_GETOWN 9 /* Set owner of socket (receiver of SIGIO). */ +#endif + +#ifdef __USE_GNU +# define F_SETSIG 10 /* Set number of signal to be sent. */ +# define F_GETSIG 11 /* Get number of signal to be sent. */ +#endif + +#ifdef __USE_GNU +# define F_SETLEASE 1024 /* Set a lease. */ +# define F_GETLEASE 1025 /* Enquire what lease is active. */ +# define F_NOTIFY 1026 /* Request notfications on a directory. */ +# define F_DUPFD_CLOEXEC 1030 /* Duplicate file descriptor with + close-on-exit set on new fd. */ +#endif + +/* For F_[GET|SET]FD. */ +#define FD_CLOEXEC 1 /* actually anything with low bit set goes */ + +/* For posix fcntl() and `l_type' field of a `struct flock' for lockf(). */ +#define F_RDLCK 0 /* Read lock. */ +#define F_WRLCK 1 /* Write lock. */ +#define F_UNLCK 2 /* Remove lock. */ + +/* For old implementation of bsd flock(). */ +#define F_EXLCK 4 /* or 3 */ +#define F_SHLCK 8 /* or 4 */ + +#ifdef __USE_BSD +/* Operations for bsd flock(), also used by the kernel implementation. */ +# define LOCK_SH 1 /* shared lock */ +# define LOCK_EX 2 /* exclusive lock */ +# define LOCK_NB 4 /* or'd with one of the above to prevent + blocking */ +# define LOCK_UN 8 /* remove lock */ +#endif + +#ifdef __USE_GNU +# define LOCK_MAND 32 /* This is a mandatory flock: */ +# define LOCK_READ 64 /* ... which allows concurrent read operations. */ +# define LOCK_WRITE 128 /* ... which allows concurrent write operations. */ +# define LOCK_RW 192 /* ... Which allows concurrent read & write operations. */ +#endif + +#ifdef __USE_GNU +/* Types of directory notifications that may be requested with F_NOTIFY. */ +# define DN_ACCESS 0x00000001 /* File accessed. */ +# define DN_MODIFY 0x00000002 /* File modified. */ +# define DN_CREATE 0x00000004 /* File created. */ +# define DN_DELETE 0x00000008 /* File removed. */ +# define DN_RENAME 0x00000010 /* File renamed. */ +# define DN_ATTRIB 0x00000020 /* File changed attibutes. */ +# define DN_MULTISHOT 0x80000000 /* Don't remove notifier. */ +#endif + +struct flock + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ +#ifndef __USE_FILE_OFFSET64 + __off_t l_start; /* Offset where the lock begins. */ + __off_t l_len; /* Size of the locked area; zero means until EOF. */ +#else + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ +#endif + __pid_t l_pid; /* Process holding the lock. */ + }; + +#ifdef __USE_LARGEFILE64 +struct flock64 + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ + __pid_t l_pid; /* Process holding the lock. */ + }; +#endif + +/* Define some more compatibility macros to be backward compatible with + BSD systems which did not managed to hide these kernel macros. */ +#ifdef __USE_BSD +# define FAPPEND O_APPEND +# define FFSYNC O_FSYNC +# define FASYNC O_ASYNC +# define FNONBLOCK O_NONBLOCK +# define FNDELAY O_NDELAY +#endif /* Use BSD. */ + +/* Advise to `posix_fadvise'. */ +#ifdef __USE_XOPEN2K +# define POSIX_FADV_NORMAL 0 /* No further special treatment. */ +# define POSIX_FADV_RANDOM 1 /* Expect random page references. */ +# define POSIX_FADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define POSIX_FADV_WILLNEED 3 /* Will need these pages. */ +# define POSIX_FADV_DONTNEED 4 /* Don't need these pages. */ +# define POSIX_FADV_NOREUSE 5 /* Data will be accessed once. */ +#endif + + +#if defined __USE_GNU && defined __UCLIBC_LINUX_SPECIFIC__ +/* Flags for SYNC_FILE_RANGE. */ +# define SYNC_FILE_RANGE_WAIT_BEFORE 1 /* Wait upon writeout of all pages + in the range before performing the + write. */ +# define SYNC_FILE_RANGE_WRITE 2 /* Initiate writeout of all those + dirty pages in the range which are + not presently under writeback. */ +# define SYNC_FILE_RANGE_WAIT_AFTER 4 /* Wait upon writeout of all pages in + the range after performing the + write. */ + +/* Flags for SPLICE and VMSPLICE. */ +# define SPLICE_F_MOVE 1 /* Move pages instead of copying. */ +# define SPLICE_F_NONBLOCK 2 /* Don't block on the pipe splicing + (but we may still block on the fd + we splice from/to). */ +# define SPLICE_F_MORE 4 /* Expect more data. */ +# define SPLICE_F_GIFT 8 /* Pages passed in are a gift. */ +#endif + +__BEGIN_DECLS + +#if defined __USE_GNU && defined __UCLIBC_LINUX_SPECIFIC__ + +/* Provide kernel hint to read ahead. */ +extern ssize_t readahead (int __fd, __off64_t __offset, size_t __count) + __THROW; + + +/* Selective file content synch'ing. */ +extern int sync_file_range (int __fd, __off64_t __from, __off64_t __to, + unsigned int __flags); + +/* Splice address range into a pipe. */ +extern ssize_t vmsplice (int __fdout, const struct iovec *__iov, + size_t __count, unsigned int __flags); + +/* Splice two files together. */ +extern ssize_t splice (int __fdin, __off64_t *__offin, int __fdout, + __off64_t *__offout, size_t __len, + unsigned int __flags); + +/* In-kernel implementation of tee for pipe buffers. */ +extern ssize_t tee (int __fdin, int __fdout, size_t __len, + unsigned int __flags); + +#endif +__END_DECLS + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bits/fenv.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bits/fenv.h new file mode 100644 index 00000000..11859f00 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bits/fenv.h @@ -0,0 +1,97 @@ +/* Copyright (C) 1997,1998,1999,2000,2001,2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FENV_H +# error "Never use directly; include instead." +#endif + +#include + + +/* Define bits representing the exception. We use the bit positions + of the appropriate bits in the FPU control word. */ +enum + { + FE_INVALID = 0x01, +#define FE_INVALID FE_INVALID + __FE_DENORM = 0x02, + FE_DIVBYZERO = 0x04, +#define FE_DIVBYZERO FE_DIVBYZERO + FE_OVERFLOW = 0x08, +#define FE_OVERFLOW FE_OVERFLOW + FE_UNDERFLOW = 0x10, +#define FE_UNDERFLOW FE_UNDERFLOW + FE_INEXACT = 0x20 +#define FE_INEXACT FE_INEXACT + }; + +#define FE_ALL_EXCEPT \ + (FE_INEXACT | FE_DIVBYZERO | FE_UNDERFLOW | FE_OVERFLOW | FE_INVALID) + +/* The ix87 FPU supports all of the four defined rounding modes. We + use again the bit positions in the FPU control word as the values + for the appropriate macros. */ +enum + { + FE_TONEAREST = 0, +#define FE_TONEAREST FE_TONEAREST + FE_DOWNWARD = 0x400, +#define FE_DOWNWARD FE_DOWNWARD + FE_UPWARD = 0x800, +#define FE_UPWARD FE_UPWARD + FE_TOWARDZERO = 0xc00 +#define FE_TOWARDZERO FE_TOWARDZERO + }; + + +/* Type representing exception flags. */ +typedef unsigned short int fexcept_t; + + +/* Type representing floating-point environment. This structure + corresponds to the layout of the block written by the `fstenv' + instruction and has additional fields for the contents of the MXCSR + register as written by the `stmxcsr' instruction. */ +typedef struct + { + unsigned short int __control_word; + unsigned short int __unused1; + unsigned short int __status_word; + unsigned short int __unused2; + unsigned short int __tags; + unsigned short int __unused3; + unsigned int __eip; + unsigned short int __cs_selector; + unsigned int __opcode:11; + unsigned int __unused4:5; + unsigned int __data_offset; + unsigned short int __data_selector; + unsigned short int __unused5; +#if __WORDSIZE == 64 + unsigned int __mxcsr; +#endif + } +fenv_t; + +/* If the default argument is used we use this value. */ +#define FE_DFL_ENV ((__const fenv_t *) -1) + +#ifdef __USE_GNU +/* Floating-point environment where none of the exception is masked. */ +# define FE_NOMASK_ENV ((__const fenv_t *) -2) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bits/kernel_stat.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bits/kernel_stat.h new file mode 100644 index 00000000..2c1deb0d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bits/kernel_stat.h @@ -0,0 +1,34 @@ +/* Ripped from linux/include/asm-x86_64/stat.h + * and renamed 'struct stat' to 'struct kernel_stat' */ + +#ifndef _ASM_X86_64_STAT_H +#define _ASM_X86_64_STAT_H + +#ifndef _LIBC +#error bits/kernel_stat.h is for internal uClibc use only! +#endif + +struct kernel_stat { + unsigned long st_dev; + unsigned long st_ino; + unsigned long st_nlink; + + unsigned int st_mode; + unsigned int st_uid; + unsigned int st_gid; + unsigned int __pad0; + unsigned long st_rdev; + long st_size; + long st_blksize; + long st_blocks; /* Number 512-byte blocks allocated. */ + + struct timespec st_atim; + struct timespec st_mtim; + struct timespec st_ctim; + long __unused[3]; +}; + +/* x86-64 stat64 is same as stat */ +#define kernel_stat64 kernel_stat + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bits/kernel_types.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bits/kernel_types.h new file mode 100644 index 00000000..de800d70 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bits/kernel_types.h @@ -0,0 +1,53 @@ +/* Note that we use the exact same include guard #define names + * as asm/posix_types.h. This will avoid gratuitous conflicts + * with the posix_types.h kernel header, and will ensure that + * our private content, and not the kernel header, will win. + * -Erik + */ + +/* a hack for compiling a 32 bit user space with 64 bit + * kernel on x86_64 */ +#if !defined(__ARCH_I386_POSIX_TYPES_H) && \ + !defined(_ASM_X86_64_POSIX_TYPES_H) && \ + !defined(_ASM_X86_POSIX_TYPES_32_H) && \ + !defined(_ASM_X86_POSIX_TYPES_64_H) +#define _ASM_X86_64_POSIX_TYPES_H +#define __ARCH_I386_POSIX_TYPES_H +#define _ASM_X86_POSIX_TYPES_32_H +#define _ASM_X86_POSIX_TYPES_64_H + +typedef unsigned long __kernel_dev_t; +typedef unsigned long __kernel_ino_t; +typedef unsigned int __kernel_mode_t; +typedef unsigned long __kernel_nlink_t; +typedef long __kernel_off_t; +typedef int __kernel_pid_t; +typedef int __kernel_ipc_pid_t; +typedef unsigned int __kernel_uid_t; +typedef unsigned int __kernel_gid_t; +typedef unsigned long __kernel_size_t; +typedef long __kernel_ssize_t; +typedef long __kernel_ptrdiff_t; +typedef long __kernel_time_t; +typedef long __kernel_suseconds_t; +typedef long __kernel_clock_t; +typedef int __kernel_daddr_t; +typedef char * __kernel_caddr_t; +typedef unsigned short __kernel_uid16_t; +typedef unsigned short __kernel_gid16_t; +typedef unsigned int __kernel_uid32_t; +typedef unsigned int __kernel_gid32_t; +typedef unsigned short __kernel_old_uid_t; +typedef unsigned short __kernel_old_gid_t; +typedef __kernel_dev_t __kernel_old_dev_t; +typedef long long __kernel_loff_t; + +typedef struct { +#ifdef __USE_ALL + int val[2]; +#else + int __val[2]; +#endif +} __kernel_fsid_t; + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bits/mathdef.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bits/mathdef.h new file mode 100644 index 00000000..b0567e4d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bits/mathdef.h @@ -0,0 +1,52 @@ +/* Copyright (C) 2001, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#if !defined _MATH_H && !defined _COMPLEX_H +# error "Never use directly; include instead" +#endif + +#if defined __USE_ISOC99 && defined _MATH_H && !defined _MATH_H_MATHDEF +# define _MATH_H_MATHDEF 1 + +# include + +# if __WORDSIZE == 64 || (defined __FLT_EVAL_METHOD__ && __FLT_EVAL_METHOD__ == 0) +/* The x86-64 architecture computes values with the precission of the + used type. Similarly for -m32 -mfpmath=sse. */ +typedef float float_t; /* `float' expressions are evaluated as `float'. */ +typedef double double_t; /* `double' expressions are evaluated + as `double'. */ +# else +/* The ix87 FPUs evaluate all values in the 80 bit floating-point format + which is also available for the user as `long double'. Therefore we + define: */ +typedef long double float_t; /* `float' expressions are evaluated as + `long double'. */ +typedef long double double_t; /* `double' expressions are evaluated as + `long double'. */ +# endif + +/* The values returned by `ilogb' for 0 and NaN respectively. */ +# define FP_ILOGB0 (-2147483647 - 1) +# define FP_ILOGBNAN (-2147483647 - 1) + +#endif /* ISO C99 */ + +#if !defined __NO_LONG_DOUBLE_MATH && !defined __UCLIBC_HAS_LONG_DOUBLE_MATH__ +# define __NO_LONG_DOUBLE_MATH 1 +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bits/mathinline.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bits/mathinline.h new file mode 100644 index 00000000..39d11b67 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bits/mathinline.h @@ -0,0 +1,53 @@ +/* Inline math functions for x86-64. + Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Andreas Jaeger , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _MATH_H +# error "Never use directly; include instead." +#endif + +#ifdef __cplusplus +# define __MATH_INLINE __inline +#else +# define __MATH_INLINE extern __inline +#endif + + +#if defined __USE_ISOC99 && defined __GNUC__ && __GNUC__ >= 2 + +/* Test for negative number. Used in the signbit() macro. */ +__MATH_INLINE int +__NTH (__signbitf (float __x)) +{ + __extension__ union { float __f; int __i; } __u = { __f: __x }; + return __u.__i < 0; +} +__MATH_INLINE int +__NTH (__signbit (double __x)) +{ + __extension__ union { double __d; int __i[2]; } __u = { __d: __x }; + return __u.__i[1] < 0; +} +__MATH_INLINE int +__NTH (__signbitl (long double __x)) +{ + __extension__ union { long double __l; int __i[3]; } __u = { __l: __x }; + return (__u.__i[2] & 0x8000) != 0; +} +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bits/mman.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bits/mman.h new file mode 100644 index 00000000..a0b7a0e9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bits/mman.h @@ -0,0 +1,4 @@ +#ifdef __USE_MISC +# define MAP_32BIT 0x40 /* Only give out 32-bit addresses. */ +#endif +#include diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bits/msq.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bits/msq.h new file mode 100644 index 00000000..422218a5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bits/msq.h @@ -0,0 +1,83 @@ +/* Copyright (C) 1995, 1996, 1997, 2000, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_MSG_H +# error "Never use directly; include instead." +#endif + +#include +#include + +/* Define options for message queue functions. */ +#define MSG_NOERROR 010000 /* no error if message is too big */ +#ifdef __USE_GNU +# define MSG_EXCEPT 020000 /* recv any msg except of specified type */ +#endif + +/* Types used in the structure definition. */ +typedef unsigned long int msgqnum_t; +typedef unsigned long int msglen_t; + +/* Structure of record for one message inside the kernel. + The type `struct msg' is opaque. */ +struct msqid_ds +{ + struct ipc_perm msg_perm; /* structure describing operation permission */ + __time_t msg_stime; /* time of last msgsnd command */ +#if __WORDSIZE == 32 + unsigned long int __unused1; +#endif + __time_t msg_rtime; /* time of last msgrcv command */ +#if __WORDSIZE == 32 + unsigned long int __unused2; +#endif + __time_t msg_ctime; /* time of last change */ +#if __WORDSIZE == 32 + unsigned long int __unused3; +#endif + unsigned long int __msg_cbytes; /* current number of bytes on queue */ + msgqnum_t msg_qnum; /* number of messages currently on queue */ + msglen_t msg_qbytes; /* max number of bytes allowed on queue */ + __pid_t msg_lspid; /* pid of last msgsnd() */ + __pid_t msg_lrpid; /* pid of last msgrcv() */ + unsigned long int __unused4; + unsigned long int __unused5; +}; + +#ifdef __USE_MISC + +# define msg_cbytes __msg_cbytes + +/* ipcs ctl commands */ +# define MSG_STAT 11 +# define MSG_INFO 12 + +/* buffer for msgctl calls IPC_INFO, MSG_INFO */ +struct msginfo + { + int msgpool; + int msgmap; + int msgmax; + int msgmnb; + int msgmni; + int msgssz; + int msgtql; + unsigned short int msgseg; + }; + +#endif /* __USE_MISC */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bits/sem.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bits/sem.h new file mode 100644 index 00000000..9b1d993e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bits/sem.h @@ -0,0 +1,87 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_SEM_H +# error "Never include directly; use instead." +#endif + +#include + +/* Flags for `semop'. */ +#define SEM_UNDO 0x1000 /* undo the operation on exit */ + +/* Commands for `semctl'. */ +#define GETPID 11 /* get sempid */ +#define GETVAL 12 /* get semval */ +#define GETALL 13 /* get all semval's */ +#define GETNCNT 14 /* get semncnt */ +#define GETZCNT 15 /* get semzcnt */ +#define SETVAL 16 /* set semval */ +#define SETALL 17 /* set all semval's */ + + +/* Data structure describing a set of semaphores. */ +struct semid_ds +{ + struct ipc_perm sem_perm; /* operation permission struct */ + __time_t sem_otime; /* last semop() time */ + unsigned long int __unused1; + __time_t sem_ctime; /* last time changed by semctl() */ + unsigned long int __unused2; + unsigned long int sem_nsems; /* number of semaphores in set */ + unsigned long int __unused3; + unsigned long int __unused4; +}; + +/* The user should define a union like the following to use it for arguments + for `semctl'. + + union semun + { + int val; <= value for SETVAL + struct semid_ds *buf; <= buffer for IPC_STAT & IPC_SET + unsigned short int *array; <= array for GETALL & SETALL + struct seminfo *__buf; <= buffer for IPC_INFO + }; + + Previous versions of this file used to define this union but this is + incorrect. One can test the macro _SEM_SEMUN_UNDEFINED to see whether + one must define the union or not. */ +#define _SEM_SEMUN_UNDEFINED 1 + +#ifdef __USE_MISC + +/* ipcs ctl cmds */ +# define SEM_STAT 18 +# define SEM_INFO 19 + +struct seminfo +{ + int semmap; + int semmni; + int semmns; + int semmnu; + int semmsl; + int semopm; + int semume; + int semusz; + int semvmx; + int semaem; +}; + +#endif /* __USE_MISC */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bits/setjmp.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bits/setjmp.h new file mode 100644 index 00000000..515d769b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bits/setjmp.h @@ -0,0 +1,78 @@ +/* Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Define the machine-dependent type `jmp_buf'. x86-64 version. */ +#ifndef _BITS_SETJMP_H +#define _BITS_SETJMP_H 1 + +#if !defined _SETJMP_H && !defined _PTHREAD_H +# error "Never include directly; use instead." +#endif + +#include + +#if __WORDSIZE == 64 + +/* We only need to save callee-saved registers plus stackpointer and + program counter. */ +# if defined __USE_MISC || defined _ASM +# define JB_RBX 0 +# define JB_RBP 1 +# define JB_R12 2 +# define JB_R13 3 +# define JB_R14 4 +# define JB_R15 5 +# define JB_RSP 6 +# define JB_PC 7 +# define JB_SIZE (8*8) +# endif + +#else + +# if defined __USE_MISC || defined _ASM +# define JB_BX 0 +# define JB_SI 1 +# define JB_DI 2 +# define JB_BP 3 +# define JB_SP 4 +# define JB_PC 5 +# define JB_SIZE 24 +# endif + +#endif + +#ifndef _ASM + +# if __WORDSIZE == 64 +typedef long int __jmp_buf[8]; +# else +typedef int __jmp_buf[6]; +# endif + +/* Test if longjmp to JMPBUF would unwind the frame + containing a local variable at ADDRESS. */ +# if __WORDSIZE == 64 +# define _JMPBUF_UNWINDS(jmpbuf, address) \ + ((void *) (address) < (void *) (jmpbuf)[JB_RSP]) +# else +# define _JMPBUF_UNWINDS(jmpbuf, address) \ + ((void *) (address) < (void *) (jmpbuf)[JB_SP]) +# endif +#endif + +#endif /* bits/setjmp.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bits/shm.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bits/shm.h new file mode 100644 index 00000000..3d8c05d2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bits/shm.h @@ -0,0 +1,110 @@ +/* Copyright (C) 1995, 1996, 1997, 2000, 2002, 2004 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_SHM_H +# error "Never include directly; use instead." +#endif + +#include + +/* Permission flag for shmget. */ +#define SHM_R 0400 /* or S_IRUGO from */ +#define SHM_W 0200 /* or S_IWUGO from */ + +/* Flags for `shmat'. */ +#define SHM_RDONLY 010000 /* attach read-only else read-write */ +#define SHM_RND 020000 /* round attach address to SHMLBA */ +#define SHM_REMAP 040000 /* take-over region on attach */ + +/* Commands for `shmctl'. */ +#define SHM_LOCK 11 /* lock segment (root only) */ +#define SHM_UNLOCK 12 /* unlock segment (root only) */ + +__BEGIN_DECLS + +/* Segment low boundary address multiple. */ +#define SHMLBA (__getpagesize ()) +extern int __getpagesize (void) __THROW __attribute__ ((__const__)); + + +/* Type to count number of attaches. */ +typedef unsigned long int shmatt_t; + +/* Data structure describing a set of semaphores. */ +struct shmid_ds + { + struct ipc_perm shm_perm; /* operation permission struct */ + size_t shm_segsz; /* size of segment in bytes */ + __time_t shm_atime; /* time of last shmat() */ +#if __WORDSIZE == 32 + unsigned long int __unused1; +#endif + __time_t shm_dtime; /* time of last shmdt() */ +#if __WORDSIZE == 32 + unsigned long int __unused2; +#endif + __time_t shm_ctime; /* time of last change by shmctl() */ +#if __WORDSIZE == 32 + unsigned long int __unused3; +#endif + __pid_t shm_cpid; /* pid of creator */ + __pid_t shm_lpid; /* pid of last shmop */ + shmatt_t shm_nattch; /* number of current attaches */ + unsigned long int __unused4; + unsigned long int __unused5; + }; + +#ifdef __USE_MISC + +/* ipcs ctl commands */ +# define SHM_STAT 13 +# define SHM_INFO 14 + +/* shm_mode upper byte flags */ +# define SHM_DEST 01000 /* segment will be destroyed on last detach */ +# define SHM_LOCKED 02000 /* segment will not be swapped */ +# define SHM_HUGETLB 04000 /* segment is mapped via hugetlb */ +# define SHM_NORESERVE 010000 /* don't check for reservations */ + +struct shminfo + { + unsigned long int shmmax; + unsigned long int shmmin; + unsigned long int shmmni; + unsigned long int shmseg; + unsigned long int shmall; + unsigned long int __unused1; + unsigned long int __unused2; + unsigned long int __unused3; + unsigned long int __unused4; + }; + +struct shm_info + { + int used_ids; + unsigned long int shm_tot; /* total allocated shm */ + unsigned long int shm_rss; /* total resident shm */ + unsigned long int shm_swp; /* total swapped shm */ + unsigned long int swap_attempts; + unsigned long int swap_successes; + }; + +#endif /* __USE_MISC */ + +__END_DECLS diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bits/sigcontext.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bits/sigcontext.h new file mode 100644 index 00000000..c0d5fe72 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bits/sigcontext.h @@ -0,0 +1,159 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _BITS_SIGCONTEXT_H +#define _BITS_SIGCONTEXT_H 1 + +#if !defined _SIGNAL_H && !defined _SYS_UCONTEXT_H +# error "Never use directly; include instead." +#endif + +#include + +struct _fpreg +{ + unsigned short significand[4]; + unsigned short exponent; +}; + +struct _fpxreg +{ + unsigned short significand[4]; + unsigned short exponent; + unsigned short padding[3]; +}; + +struct _xmmreg +{ + __uint32_t element[4]; +}; + + + +#if __WORDSIZE == 32 + +struct _fpstate +{ + /* Regular FPU environment. */ + __uint32_t cw; + __uint32_t sw; + __uint32_t tag; + __uint32_t ipoff; + __uint32_t cssel; + __uint32_t dataoff; + __uint32_t datasel; + struct _fpreg _st[8]; + unsigned short status; + unsigned short magic; + + /* FXSR FPU environment. */ + __uint32_t _fxsr_env[6]; + __uint32_t mxcsr; + __uint32_t reserved; + struct _fpxreg _fxsr_st[8]; + struct _xmmreg _xmm[8]; + __uint32_t padding[56]; +}; + +#ifndef sigcontext_struct +/* Kernel headers before 2.1.1 define a struct sigcontext_struct, but + we need sigcontext. Some packages have come to rely on + sigcontext_struct being defined on 32-bit x86, so define this for + their benefit. */ +# define sigcontext_struct sigcontext +#endif + +struct sigcontext +{ + unsigned short gs, __gsh; + unsigned short fs, __fsh; + unsigned short es, __esh; + unsigned short ds, __dsh; + unsigned long edi; + unsigned long esi; + unsigned long ebp; + unsigned long esp; + unsigned long ebx; + unsigned long edx; + unsigned long ecx; + unsigned long eax; + unsigned long trapno; + unsigned long err; + unsigned long eip; + unsigned short cs, __csh; + unsigned long eflags; + unsigned long esp_at_signal; + unsigned short ss, __ssh; + struct _fpstate * fpstate; + unsigned long oldmask; + unsigned long cr2; +}; + +#else /* __WORDSIZE == 64 */ + +struct _fpstate +{ + /* FPU environment matching the 64-bit FXSAVE layout. */ + __uint16_t cwd; + __uint16_t swd; + __uint16_t ftw; + __uint16_t fop; + __uint64_t rip; + __uint64_t rdp; + __uint32_t mxcsr; + __uint32_t mxcr_mask; + struct _fpxreg _st[8]; + struct _xmmreg _xmm[16]; + __uint32_t padding[24]; +}; + +struct sigcontext +{ + unsigned long r8; + unsigned long r9; + unsigned long r10; + unsigned long r11; + unsigned long r12; + unsigned long r13; + unsigned long r14; + unsigned long r15; + unsigned long rdi; + unsigned long rsi; + unsigned long rbp; + unsigned long rbx; + unsigned long rdx; + unsigned long rax; + unsigned long rcx; + unsigned long rsp; + unsigned long rip; + unsigned long eflags; + unsigned short cs; + unsigned short gs; + unsigned short fs; + unsigned short __pad0; + unsigned long err; + unsigned long trapno; + unsigned long oldmask; + unsigned long cr2; + struct _fpstate * fpstate; + unsigned long __reserved1 [8]; +}; + +#endif /* __WORDSIZE == 64 */ + +#endif /* _BITS_SIGCONTEXT_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bits/sigcontextinfo.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bits/sigcontextinfo.h new file mode 100644 index 00000000..11493c58 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bits/sigcontextinfo.h @@ -0,0 +1,26 @@ +/* Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define SIGCONTEXT siginfo_t *_si, struct ucontext * +#define SIGCONTEXT_EXTRA_ARGS _si, +#define GET_PC(ctx) ((void *) (ctx)->uc_mcontext.gregs[REG_RIP]) +#define GET_FRAME(ctx) ((void *) (ctx)->uc_mcontext.gregs[REG_RBP]) +#define GET_STACK(ctx) ((void *) (ctx)->uc_mcontext.gregs[REG_RSP]) + +#define CALL_SIGHANDLER(handler, signo, ctx) \ + (handler)((signo), SIGCONTEXT_EXTRA_ARGS (ctx)) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bits/stackinfo.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bits/stackinfo.h new file mode 100644 index 00000000..60668d10 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bits/stackinfo.h @@ -0,0 +1,28 @@ +/* Copyright (C) 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This file contains a bit of information about the stack allocation + of the processor. */ + +#ifndef _STACKINFO_H +#define _STACKINFO_H 1 + +/* On x86_64 the stack grows down. */ +#define _STACK_GROWS_DOWN 1 + +#endif /* stackinfo.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bits/stat.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bits/stat.h new file mode 100644 index 00000000..51367b2f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bits/stat.h @@ -0,0 +1,208 @@ +/* Copyright (C) 1999,2000,2001,2002,2003,2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_STAT_H +# error "Never include directly; use instead." +#endif + +/* Versions of the `struct stat' data structure. */ +#define _STAT_VER_KERNEL 0 + +#if __WORDSIZE == 32 +# define _STAT_VER_SVR4 2 +# define _STAT_VER_LINUX 3 + +/* i386 versions of the `xmknod' interface. */ +# define _MKNOD_VER_LINUX 1 +# define _MKNOD_VER_SVR4 2 +# define _MKNOD_VER _MKNOD_VER_LINUX /* The bits defined below. */ +#else +# define _STAT_VER_LINUX 1 + +/* x86-64 versions of the `xmknod' interface. */ +# define _MKNOD_VER_LINUX 0 +#endif + +#define _STAT_VER _STAT_VER_LINUX + +struct stat + { + __dev_t st_dev; /* Device. */ +#if __WORDSIZE == 32 + unsigned short int __pad1; +#endif +#if __WORDSIZE == 64 || !defined __USE_FILE_OFFSET64 + __ino_t st_ino; /* File serial number. */ +#else + __ino_t __st_ino; /* 32bit file serial number. */ +#endif +#if __WORDSIZE == 32 + __mode_t st_mode; /* File mode. */ + __nlink_t st_nlink; /* Link count. */ +#else + __nlink_t st_nlink; /* Link count. */ + __mode_t st_mode; /* File mode. */ +#endif + __uid_t st_uid; /* User ID of the file's owner. */ + __gid_t st_gid; /* Group ID of the file's group.*/ +#if __WORDSIZE == 64 + int __pad0; +#endif + __dev_t st_rdev; /* Device number, if device. */ +#if __WORDSIZE == 32 + unsigned short int __pad2; +#endif +#if __WORDSIZE == 64 || !defined __USE_FILE_OFFSET64 + __off_t st_size; /* Size of file, in bytes. */ +#else + __off64_t st_size; /* Size of file, in bytes. */ +#endif + __blksize_t st_blksize; /* Optimal block size for I/O. */ +#if __WORDSIZE == 64 || !defined __USE_FILE_OFFSET64 + __blkcnt_t st_blocks; /* Number 512-byte blocks allocated. */ +#else + __blkcnt64_t st_blocks; /* Number 512-byte blocks allocated. */ +#endif +#ifdef __USE_MISC + /* Nanosecond resolution timestamps are stored in a format + equivalent to 'struct timespec'. This is the type used + whenever possible but the Unix namespace rules do not allow the + identifier 'timespec' to appear in the header. + Therefore we have to handle the use of this header in strictly + standard-compliant sources special. */ + struct timespec st_atim; /* Time of last access. */ + struct timespec st_mtim; /* Time of last modification. */ + struct timespec st_ctim; /* Time of last status change. */ +# define st_atime st_atim.tv_sec /* Backward compatibility. */ +# define st_mtime st_mtim.tv_sec +# define st_ctime st_ctim.tv_sec +#else + __time_t st_atime; /* Time of last access. */ + unsigned long int st_atimensec; /* Nscecs of last access. */ + __time_t st_mtime; /* Time of last modification. */ + unsigned long int st_mtimensec; /* Nsecs of last modification. */ + __time_t st_ctime; /* Time of last status change. */ + unsigned long int st_ctimensec; /* Nsecs of last status change. */ +#endif +#if __WORDSIZE == 64 + long int __unused[3]; +#else +# ifndef __USE_FILE_OFFSET64 + unsigned long int __unused4; + unsigned long int __unused5; +# else + __ino64_t st_ino; /* File serial number. */ +# endif +#endif + }; + +#ifdef __USE_LARGEFILE64 +/* Note stat64 has the same shape as stat for x86-64. */ +struct stat64 + { + __dev_t st_dev; /* Device. */ +#if __WORDSIZE == 64 + __ino64_t st_ino; /* File serial number. */ + __nlink_t st_nlink; /* Link count. */ + __mode_t st_mode; /* File mode. */ +#else + unsigned int __pad1; + __ino_t __st_ino; /* 32bit file serial number. */ + __mode_t st_mode; /* File mode. */ + __nlink_t st_nlink; /* Link count. */ +#endif + __uid_t st_uid; /* User ID of the file's owner. */ + __gid_t st_gid; /* Group ID of the file's group.*/ +#if __WORDSIZE == 64 + int __pad0; + __dev_t st_rdev; /* Device number, if device. */ + __off_t st_size; /* Size of file, in bytes. */ +#else + __dev_t st_rdev; /* Device number, if device. */ + unsigned int __pad2; + __off64_t st_size; /* Size of file, in bytes. */ +#endif + __blksize_t st_blksize; /* Optimal block size for I/O. */ + __blkcnt64_t st_blocks; /* Nr. 512-byte blocks allocated. */ +#ifdef __USE_MISC + /* Nanosecond resolution timestamps are stored in a format + equivalent to 'struct timespec'. This is the type used + whenever possible but the Unix namespace rules do not allow the + identifier 'timespec' to appear in the header. + Therefore we have to handle the use of this header in strictly + standard-compliant sources special. */ + struct timespec st_atim; /* Time of last access. */ + struct timespec st_mtim; /* Time of last modification. */ + struct timespec st_ctim; /* Time of last status change. */ +# define st_atime st_atim.tv_sec /* Backward compatibility. */ +# define st_mtime st_mtim.tv_sec +# define st_ctime st_ctim.tv_sec +#else + __time_t st_atime; /* Time of last access. */ + unsigned long int st_atimensec; /* Nscecs of last access. */ + __time_t st_mtime; /* Time of last modification. */ + unsigned long int st_mtimensec; /* Nsecs of last modification. */ + __time_t st_ctime; /* Time of last status change. */ + unsigned long int st_ctimensec; /* Nsecs of last status change. */ +#endif +#if __WORDSIZE == 64 + long int __unused[3]; +#else + __ino64_t st_ino; /* File serial number. */ +#endif + }; +#endif + +/* Tell code we have these members. */ +#define _STATBUF_ST_BLKSIZE +#define _STATBUF_ST_RDEV +/* Nanosecond resolution time values are supported. */ +#define _STATBUF_ST_NSEC + +/* Encoding of the file mode. */ + +#define __S_IFMT 0170000 /* These bits determine file type. */ + +/* File types. */ +#define __S_IFDIR 0040000 /* Directory. */ +#define __S_IFCHR 0020000 /* Character device. */ +#define __S_IFBLK 0060000 /* Block device. */ +#define __S_IFREG 0100000 /* Regular file. */ +#define __S_IFIFO 0010000 /* FIFO. */ +#define __S_IFLNK 0120000 /* Symbolic link. */ +#define __S_IFSOCK 0140000 /* Socket. */ + +/* POSIX.1b objects. Note that these macros always evaluate to zero. But + they do it by enforcing the correct use of the macros. */ +#define __S_TYPEISMQ(buf) ((buf)->st_mode - (buf)->st_mode) +#define __S_TYPEISSEM(buf) ((buf)->st_mode - (buf)->st_mode) +#define __S_TYPEISSHM(buf) ((buf)->st_mode - (buf)->st_mode) + +/* Protection bits. */ + +#define __S_ISUID 04000 /* Set user ID on execution. */ +#define __S_ISGID 02000 /* Set group ID on execution. */ +#define __S_ISVTX 01000 /* Save swapped text after use (sticky). */ +#define __S_IREAD 0400 /* Read by owner. */ +#define __S_IWRITE 0200 /* Write by owner. */ +#define __S_IEXEC 0100 /* Execute by owner. */ + +#ifdef __USE_ATFILE +# define UTIME_NOW ((1l << 30) - 1l) +# define UTIME_OMIT ((1l << 30) - 2l) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bits/syscalls.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bits/syscalls.h new file mode 100644 index 00000000..8042ab8b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bits/syscalls.h @@ -0,0 +1,133 @@ +#ifndef _BITS_SYSCALLS_H +#define _BITS_SYSCALLS_H +#ifndef _SYSCALL_H +# error "Never use directly; include instead." +#endif + +/* + Some of the sneaky macros in the code were taken from + glibc-2.2.5/sysdeps/unix/sysv/linux/x86_64/sysdep.h +*/ + +#ifndef __ASSEMBLER__ + +#include + +/* The Linux/x86-64 kernel expects the system call parameters in + registers according to the following table: + + syscall number rax + arg 1 rdi + arg 2 rsi + arg 3 rdx + arg 4 r10 + arg 5 r8 + arg 6 r9 + + The Linux kernel uses and destroys internally these registers: + return address from + syscall rcx + additionally clobered: r12-r15,rbx,rbp + eflags from syscall r11 + + Normal function call, including calls to the system call stub + functions in the libc, get the first six parameters passed in + registers and the seventh parameter and later on the stack. The + register use is as follows: + + system call number in the DO_CALL macro + arg 1 rdi + arg 2 rsi + arg 3 rdx + arg 4 rcx + arg 5 r8 + arg 6 r9 + + We have to take care that the stack is aligned to 16 bytes. When + called the stack is not aligned since the return address has just + been pushed. + + + Syscalls of more than 6 arguments are not supported. */ + +#undef DO_CALL +#define DO_CALL(syscall_name, args) \ + DOARGS_##args \ + movq $SYS_ify (syscall_name), %rax; \ + syscall; + +#define DOARGS_0 /* nothing */ +#define DOARGS_1 /* nothing */ +#define DOARGS_2 /* nothing */ +#define DOARGS_3 /* nothing */ +#define DOARGS_4 movq %rcx, %r10; +#define DOARGS_5 DOARGS_4 +#define DOARGS_6 DOARGS_5 + +/* Define a macro which expands inline into the wrapper code for a system + call. */ +#define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \ + ({ \ + unsigned long resultvar; \ + LOAD_ARGS_##nr (args) \ + LOAD_REGS_##nr \ + __asm__ __volatile__ ( \ + "syscall\n\t" \ + : "=a" (resultvar) \ + : "0" (name) ASM_ARGS_##nr : "memory", "cc", "r11", "cx"); \ + (long) resultvar; }) + +#define LOAD_ARGS_0() +#define LOAD_REGS_0 +#define ASM_ARGS_0 + +#define LOAD_ARGS_1(a1) \ + long int __arg1 = (long) (a1); \ + LOAD_ARGS_0 () +#define LOAD_REGS_1 \ + register long int __a1 __asm__ ("rdi") = __arg1; \ + LOAD_REGS_0 +#define ASM_ARGS_1 ASM_ARGS_0, "r" (__a1) + +#define LOAD_ARGS_2(a1, a2) \ + long int __arg2 = (long) (a2); \ + LOAD_ARGS_1 (a1) +#define LOAD_REGS_2 \ + register long int __a2 __asm__ ("rsi") = __arg2; \ + LOAD_REGS_1 +#define ASM_ARGS_2 ASM_ARGS_1, "r" (__a2) + +#define LOAD_ARGS_3(a1, a2, a3) \ + long int __arg3 = (long) (a3); \ + LOAD_ARGS_2 (a1, a2) +#define LOAD_REGS_3 \ + register long int __a3 __asm__ ("rdx") = __arg3; \ + LOAD_REGS_2 +#define ASM_ARGS_3 ASM_ARGS_2, "r" (__a3) + +#define LOAD_ARGS_4(a1, a2, a3, a4) \ + long int __arg4 = (long) (a4); \ + LOAD_ARGS_3 (a1, a2, a3) +#define LOAD_REGS_4 \ + register long int __a4 __asm__ ("r10") = __arg4; \ + LOAD_REGS_3 +#define ASM_ARGS_4 ASM_ARGS_3, "r" (__a4) + +#define LOAD_ARGS_5(a1, a2, a3, a4, a5) \ + long int __arg5 = (long) (a5); \ + LOAD_ARGS_4 (a1, a2, a3, a4) +#define LOAD_REGS_5 \ + register long int __a5 __asm__ ("r8") = __arg5; \ + LOAD_REGS_4 +#define ASM_ARGS_5 ASM_ARGS_4, "r" (__a5) + +#define LOAD_ARGS_6(a1, a2, a3, a4, a5, a6) \ + long int __arg6 = (long) (a6); \ + LOAD_ARGS_5 (a1, a2, a3, a4, a5) +#define LOAD_REGS_6 \ + register long int __a6 __asm__ ("r9") = __arg6; \ + LOAD_REGS_5 +#define ASM_ARGS_6 ASM_ARGS_5, "r" (__a6) + +#endif /* __ASSEMBLER__ */ +#endif /* _BITS_SYSCALLS_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bits/uClibc_arch_features.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bits/uClibc_arch_features.h new file mode 100644 index 00000000..1d966aee --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bits/uClibc_arch_features.h @@ -0,0 +1,47 @@ +/* + * Track misc arch-specific features that aren't config options + */ + +#ifndef _BITS_UCLIBC_ARCH_FEATURES_H +#define _BITS_UCLIBC_ARCH_FEATURES_H + +/* instruction used when calling abort() to kill yourself */ +#define __UCLIBC_ABORT_INSTRUCTION__ "hlt" + +/* can your target use syscall6() for mmap ? */ +#define __UCLIBC_MMAP_HAS_6_ARGS__ + +/* does your target use syscall4() for truncate64 ? (32bit arches only) */ +#undef __UCLIBC_TRUNCATE64_HAS_4_ARGS__ + +/* does your target have a broken create_module() ? */ +#undef __UCLIBC_BROKEN_CREATE_MODULE__ + +/* does your target have to worry about older [gs]etrlimit() ? */ +#undef __UCLIBC_HANDLE_OLDER_RLIMIT__ + +/* does your target have an asm .set ? */ +#define __UCLIBC_HAVE_ASM_SET_DIRECTIVE__ + +/* define if target doesn't like .global */ +#undef __UCLIBC_ASM_GLOBAL_DIRECTIVE__ + +/* define if target supports .weak */ +#define __UCLIBC_HAVE_ASM_WEAK_DIRECTIVE__ + +/* define if target supports .weakext */ +#undef __UCLIBC_HAVE_ASM_WEAKEXT_DIRECTIVE__ + +/* needed probably only for ppc64 */ +#undef __UCLIBC_HAVE_ASM_GLOBAL_DOT_NAME__ + +/* define if target supports CFI pseudo ops */ +#define __UCLIBC_HAVE_ASM_CFI_DIRECTIVES__ + +/* define if target supports IEEE signed zero floats */ +#define __UCLIBC_HAVE_SIGNED_ZERO__ + +/* only weird assemblers generally need this */ +#undef __UCLIBC_ASM_LINE_SEP__ + +#endif /* _BITS_UCLIBC_ARCH_FEATURES_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bits/wordsize.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bits/wordsize.h new file mode 100644 index 00000000..e5552410 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bits/wordsize.h @@ -0,0 +1,9 @@ +/* Determine the wordsize from the preprocessor defines. */ + +#if defined __x86_64__ +# define __WORDSIZE 64 +/* This makes /var/run/utmp compatible with 32-bit environment: */ +# define __WORDSIZE_COMPAT32 1 +#else +# define __WORDSIZE 32 +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/brk.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/brk.c new file mode 100644 index 00000000..4e9447e1 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/brk.c @@ -0,0 +1,46 @@ +/* brk system call for Linux/x86_64. + Copyright (C) 1995, 1996, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +/* This must be initialized data because commons can't have aliases. */ +void *__curbrk attribute_hidden = 0; + +int brk(void *addr) +{ + void *newbrk; + + __asm__ ("syscall\n" + : "=a" (newbrk) + : "0" (__NR_brk), "D" (addr) + : "r11", "rcx" + ); + + __curbrk = newbrk; + + if (newbrk < addr) { + __set_errno(ENOMEM); + return -1; + } + + return 0; +} +libc_hidden_def(brk) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bsd-_setjmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bsd-_setjmp.S new file mode 100644 index 00000000..81a4352f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bsd-_setjmp.S @@ -0,0 +1,29 @@ +/* BSD `_setjmp' entry point to `sigsetjmp (..., 0)'. i386 version. + Copyright (C) 1994,1995,1996,1997,2000,2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This just does a tail-call to `__sigsetjmp (ARG, 0)'. + We cannot do it in C because it must be a tail-call, so frame-unwinding + in setjmp doesn't clobber the state restored by longjmp. */ + +.global _setjmp +.type _setjmp,%function +_setjmp: + xorq %rsi, %rsi + jmp __sigsetjmp@PLT +.size _setjmp,.-_setjmp diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bsd-setjmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bsd-setjmp.S new file mode 100644 index 00000000..a906a613 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/bsd-setjmp.S @@ -0,0 +1,29 @@ +/* BSD `setjmp' entry point to `sigsetjmp (..., 1)'. i386 version. + Copyright (C) 1995, 1996, 1997, 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define _ASM +#define _SETJMP_H +#include + +.global setjmp +.type setjmp,%function +setjmp: + movq $1, %rsi + jmp __sigsetjmp@PLT +.size setjmp,.-setjmp diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/clone.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/clone.S new file mode 100644 index 00000000..8c66ce54 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/clone.S @@ -0,0 +1,116 @@ +/* Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* clone() is even more special than fork() as it mucks with stacks + and invokes a function in the right context after its all over. */ + +#include +#define _ERRNO_H 1 +#include +#include + +#define CLONE_VM 0x00000100 +#define CLONE_THREAD 0x00010000 + +/* The userland implementation is: + int clone (int (*fn)(void *arg), void *child_stack, int flags, void *arg), + the kernel entry is: + int clone (long flags, void *child_stack). + + The parameters are passed in register and on the stack from userland: + rdi: fn + rsi: child_stack + rdx: flags + rcx: arg + r8d: TID field in parent + r9d: thread pointer +%esp+8: TID field in child + + The kernel expects: + rax: system call number + rdi: flags + rsi: child_stack + rdx: TID field in parent + r10: TID field in child + r8: thread pointer */ + + +.text +.global clone +.type clone,%function +clone: + /* Sanity check arguments. */ + movq $-EINVAL,%rax + testq %rdi,%rdi /* no NULL function pointers */ + jz __syscall_error + testq %rsi,%rsi /* no NULL stack pointers */ + jz __syscall_error + + /* Insert the argument onto the new stack. */ + subq $16,%rsi + movq %rcx,8(%rsi) + + /* Save the function pointer. It will be popped off in the + child in the ebx frobbing below. */ + movq %rdi,0(%rsi) + + /* Do the system call. */ + movq %rdx, %rdi + movq %r8, %rdx + movq %r9, %r8 + movq 8(%rsp), %r10 + movl $__NR_clone,%eax + + syscall + + testq %rax,%rax + jl __syscall_error + jz .Lthread_start + +.Lpseudo_end: + ret + +.Lthread_start: + /* Clear the frame pointer. The ABI suggests this be done, to mark + the outermost frame obviously. */ + xorl %ebp, %ebp + +#ifdef RESET_PID + testq $CLONE_THREAD, %rdi + jne 1f + testq $CLONE_VM, %rdi + movl $-1, %eax + jne 2f + movl $__NR_getpid, %eax + syscall +2: movl %eax, %fs:PID + movl %eax, %fs:TID +1: +#endif + + /* Set up arguments for the function call. */ + popq %rax /* Function to call. */ + popq %rdi /* Argument. */ + call *%rax + /* Call exit with return value from function call. */ + movq %rax, %rdi + movl $__NR_exit, %eax + syscall + +.size clone,.-clone +weak_alias(clone, __clone) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/crt1.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/crt1.S new file mode 100644 index 00000000..f6c1eb1e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/crt1.S @@ -0,0 +1,140 @@ +/* Startup code compliant to the ELF x86-64 ABI. + Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Andreas Jaeger , 2001. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file with other + programs, and to distribute those programs without any restriction + coming from the use of this file. (The GNU Lesser General Public + License restrictions do apply in other respects; for example, they + cover modification of the file, and distribution when not linked + into another program.) + + Note that people who make modified versions of this file are not + obligated to grant this special exception for their modified + versions; it is their choice whether to do so. The GNU Lesser + General Public License gives permission to release a modified + version without this exception; this exception also makes it + possible to release a modified version which carries forward this + exception. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Originally based on glibc's sysdeps/x86_64/elf/start.S */ + +/* This is the canonical entry point, usually the first thing in the text + segment. The SVR4/i386 ABI (pages 3-31, 3-32) says that when the entry + point runs, most registers' values are unspecified, except for: + + %rdx Contains a function pointer to be registered with `atexit'. + This is how the dynamic linker arranges to have DT_FINI + functions called for shared libraries that have been loaded + before this code runs. + + %rsp The stack contains the arguments and environment: + 0(%rsp) argc + 8(%rsp) argv[0] + ... + (8*argc)(%rsp) NULL + (8*(argc+1))(%rsp) envp[0] + ... + NULL +*/ + +#include + +.text +.global _start +.type _start,%function +#if defined(__UCLIBC_CTOR_DTOR__) +.type _init,%function +.type _fini,%function +#else +.weak _init +.weak _fini +#endif +.type __uClibc_main,%function +/* Stick in a dummy reference to main(), so that if an application + * is linking when the main() function is in a static library (.a) + * we can be sure that main() actually gets linked in */ +.type main,%function + +_start: + /* Clear the frame pointer. The ABI suggests this be done, to mark + the outermost frame obviously. */ + xorl %ebp, %ebp + + /* Extract the arguments as encoded on the stack and set up + the arguments for __libc_start_main (int (*main) (int, char **, char **), + int argc, char *argv, + void (*init) (void), void (*fini) (void), + void (*rtld_fini) (void), void *stack_end). + The arguments are passed via registers and on the stack: + main: %rdi + argc: %rsi + argv: %rdx + init: %rcx + fini: %r8 + rtld_fini: %r9 + stack_end: stack. */ + + movq %rdx, %r9 /* Address of the shared library termination function. */ + popq %rsi /* Pop the argument count. */ + movq %rsp, %rdx /* argv starts just at the current stack top. */ + + /* Align the stack to a 16 byte boundary to follow the ABI. */ + andq $~15, %rsp + + pushq %rax /* Push garbage because we push 8 more bytes. */ + + /* Provide the highest stack address to the user code (for stacks + which grow downwards). */ + pushq %rsp + +#if defined(L_Scrt1) + /* Give address for main() */ + movq main@GOTPCREL(%rip), %rdi + + /* setup init/fini address */ + movq _init@GOTPCREL(%rip), %rcx + movq _fini@GOTPCREL(%rip), %r8 + + /* start the fun */ + call __uClibc_main@PLT +#else + /* Give address for main() */ + movq $main, %rdi + + /* setup init/fini address */ + movq $_init, %rcx + movq $_fini, %r8 + + /* start the fun */ + call __uClibc_main +#endif + + hlt /* Crash if somehow `exit' does return. */ +.size _start,.-_start + +/* Define a symbol for the first piece of initialized data. */ +.data +.global __data_start +__data_start: +.long 0 +.weak data_start + data_start = __data_start diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/crti.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/crti.S new file mode 100644 index 00000000..11491db4 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/crti.S @@ -0,0 +1,16 @@ +/* glibc's sysdeps/x86_64/elf/initfini.c used for reference [PROLOG] */ + + + +.section .init +.global _init +.type _init, %function +_init: + subq $8, %rsp + + +.section .fini +.global _fini +.type _fini, %function +_fini: + subq $8, %rsp diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/crtn.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/crtn.S new file mode 100644 index 00000000..9804e0f7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/crtn.S @@ -0,0 +1,16 @@ +/* glibc's sysdeps/x86_64/elf/initfini.c used for reference [EPILOG] */ + +.file "initfini.c" + +.section .init +.global _init +.type _init, %function + addq $8, %rsp + ret + + +.section .fini +.global _fini +.type _fini, %function + addq $8, %rsp + ret diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/fpu_control.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/fpu_control.h new file mode 100644 index 00000000..6e9b3b36 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/fpu_control.h @@ -0,0 +1,103 @@ +/* FPU control word bits. x86-64 version. + Copyright (C) 1993,1995,1996,1997,1998,2000,2001,2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Olaf Flebbe. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FPU_CONTROL_H +#define _FPU_CONTROL_H 1 + +/* Note that this file sets on x86-64 only the x87 FPU, it does not + touch the SSE unit. */ + +/* Here is the dirty part. Set up your 387 through the control word + * (cw) register. + * + * 15-13 12 11-10 9-8 7-6 5 4 3 2 1 0 + * | reserved | IC | RC | PC | reserved | PM | UM | OM | ZM | DM | IM + * + * IM: Invalid operation mask + * DM: Denormalized operand mask + * ZM: Zero-divide mask + * OM: Overflow mask + * UM: Underflow mask + * PM: Precision (inexact result) mask + * + * Mask bit is 1 means no interrupt. + * + * PC: Precision control + * 11 - round to extended precision + * 10 - round to double precision + * 00 - round to single precision + * + * RC: Rounding control + * 00 - rounding to nearest + * 01 - rounding down (toward - infinity) + * 10 - rounding up (toward + infinity) + * 11 - rounding toward zero + * + * IC: Infinity control + * That is for 8087 and 80287 only. + * + * The hardware default is 0x037f which we use. + */ + +#include + +/* masking of interrupts */ +#define _FPU_MASK_IM 0x01 +#define _FPU_MASK_DM 0x02 +#define _FPU_MASK_ZM 0x04 +#define _FPU_MASK_OM 0x08 +#define _FPU_MASK_UM 0x10 +#define _FPU_MASK_PM 0x20 + +/* precision control */ +#define _FPU_EXTENDED 0x300 /* libm requires double extended precision. */ +#define _FPU_DOUBLE 0x200 +#define _FPU_SINGLE 0x0 + +/* rounding control */ +#define _FPU_RC_NEAREST 0x0 /* RECOMMENDED */ +#define _FPU_RC_DOWN 0x400 +#define _FPU_RC_UP 0x800 +#define _FPU_RC_ZERO 0xC00 + +#define _FPU_RESERVED 0xF0C0 /* Reserved bits in cw */ + + +/* The fdlibm code requires strict IEEE double precision arithmetic, + and no interrupts for exceptions, rounding to nearest. */ + +#define _FPU_DEFAULT 0x037f + +/* IEEE: same as above. */ +#define _FPU_IEEE 0x037f + +/* Type of the control word. */ +typedef unsigned int fpu_control_t __attribute__ ((__mode__ (__HI__))); + +/* Macros for accessing the hardware control word. */ +#define _FPU_GETCW(cw) __asm__ ("fnstcw %0" : "=m" (*&cw)) +#define _FPU_SETCW(cw) __asm__ ("fldcw %0" : : "m" (*&cw)) + +#if 0 +/* Default control word set at startup. */ +extern fpu_control_t __fpu_control; +#endif + +#endif /* fpu_control.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/mmap.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/mmap.c new file mode 100644 index 00000000..bb1352f9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/mmap.c @@ -0,0 +1,19 @@ +/* vi: set sw=4 ts=4: */ +/* + * mmap() for uClibc/x86_64 + * + * Copyright (C) 2000-2006 Erik Andersen + * Copyright (C) 2005 by Mike Frysinger + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include + + +_syscall6(void *, mmap, void *, start, size_t, length, int, prot, + int, flags, int, fd, off_t, offset) +libc_hidden_def(mmap) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/setjmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/setjmp.S new file mode 100644 index 00000000..eb4b9736 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/setjmp.S @@ -0,0 +1,45 @@ +/* setjmp for x86-64. + Copyright (C) 2001, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define _ASM +#define _SETJMP_H +#include + +.global __sigsetjmp +.type __sigsetjmp,%function +__sigsetjmp: + /* Save registers. */ + movq %rbx, (JB_RBX*8)(%rdi) + movq %rbp, (JB_RBP*8)(%rdi) + movq %r12, (JB_R12*8)(%rdi) + movq %r13, (JB_R13*8)(%rdi) + movq %r14, (JB_R14*8)(%rdi) + movq %r15, (JB_R15*8)(%rdi) + leaq 8(%rsp), %rdx /* Save SP as it will be after we return. */ + movq %rdx, (JB_RSP*8)(%rdi) + movq (%rsp), %rax /* Save PC we are returning to now. */ + movq %rax, (JB_PC*8)(%rdi) + + /* Make a tail call to __sigjmp_save; it takes the same args. */ +#ifdef __PIC__ + jmp __sigjmp_save@PLT +#else + jmp __sigjmp_save +#endif +.size __sigsetjmp,.-__sigsetjmp diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/sigaction.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/sigaction.c new file mode 100644 index 00000000..91df04e9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/sigaction.c @@ -0,0 +1,130 @@ +/* POSIX.1 `sigaction' call for Linux/x86-64. + Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + + +#include +#include +#include +#include + +#include + +#include + +/* We do not globally define the SA_RESTORER flag so do it here. */ +#define SA_RESTORER 0x04000000 + +extern __typeof(sigaction) __libc_sigaction; + + +#ifdef __NR_rt_sigaction + +/* Using the hidden attribute here does not change the code but it + helps to avoid warnings. */ +extern void restore_rt(void) __asm__ ("__restore_rt") attribute_hidden; +extern void restore(void) __asm__ ("__restore") attribute_hidden; + +/* If ACT is not NULL, change the action for SIG to *ACT. + If OACT is not NULL, put the old action for SIG in *OACT. */ +int +__libc_sigaction(int sig, const struct sigaction *act, struct sigaction *oact) +{ + struct sigaction kact; + + if (act) { + memcpy(&kact, act, sizeof(kact)); + kact.sa_flags |= SA_RESTORER; + kact.sa_restorer = &restore_rt; + act = &kact; + } + /* NB: kernel (as of 2.6.25) will return EINVAL + * if sizeof(act->sa_mask) does not match kernel's sizeof(sigset_t) */ + return INLINE_SYSCALL(rt_sigaction, 4, sig, act, oact, sizeof(act->sa_mask)); +} + +#else + +extern void restore(void) __asm__ ("__restore") attribute_hidden; + +/* If ACT is not NULL, change the action for SIG to *ACT. + If OACT is not NULL, put the old action for SIG in *OACT. */ +int +__libc_sigaction(int sig, const struct sigaction *act, struct sigaction *oact) +{ + int result; + struct old_kernel_sigaction kact, koact; + + if (act) { + kact.k_sa_handler = act->sa_handler; + kact.sa_mask = act->sa_mask.__val[0]; + kact.sa_flags = act->sa_flags | SA_RESTORER; + kact.sa_restorer = &restore; + } + __asm__ __volatile__ ( + "syscall\n" + : "=a" (result) + : "0" (__NR_sigaction), "mr" (sig), + "c" (act ? &kact : NULL), + "d" (oact ? &koact : NULL)); + if (result < 0) { + __set_errno(-result); + return -1; + } + if (oact) { + oact->sa_handler = koact.k_sa_handler; + oact->sa_mask.__val[0] = koact.sa_mask; + oact->sa_flags = koact.sa_flags; + oact->sa_restorer = koact.sa_restorer; + } + return result; +} + +#endif + + +#ifndef LIBC_SIGACTION +weak_alias(__libc_sigaction,sigaction) +libc_hidden_weak(sigaction) +#endif + + +/* NOTE: Please think twice before making any changes to the bits of + code below. GDB needs some intimate knowledge about it to + recognize them as signal trampolines, and make backtraces through + signal handlers work right. Important are both the names + (__restore_rt) and the exact instruction sequence. + If you ever feel the need to make any changes, please notify the + appropriate GDB maintainer. */ + +#define RESTORE(name, syscall) RESTORE2(name, syscall) +#define RESTORE2(name, syscall) \ +__asm__ ( \ + ".text\n" \ + "__" #name ":\n" \ + " movq $" #syscall ", %rax\n" \ + " syscall\n" \ +); + +#ifdef __NR_rt_sigaction +/* The return code for realtime-signals. */ +RESTORE(restore_rt, __NR_rt_sigreturn) +#endif +#ifdef __NR_sigreturn +RESTORE(restore, __NR_sigreturn) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/sys/debugreg.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/sys/debugreg.h new file mode 100644 index 00000000..8abbf754 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/sys/debugreg.h @@ -0,0 +1,88 @@ +/* Copyright (C) 2001, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_DEBUGREG_H +#define _SYS_DEBUGREG_H 1 +#include + +/* Indicate the register numbers for a number of the specific + debug registers. Registers 0-3 contain the addresses we wish to trap on */ +#define DR_FIRSTADDR 0 /* u_debugreg[DR_FIRSTADDR] */ +#define DR_LASTADDR 3 /* u_debugreg[DR_LASTADDR] */ + +#define DR_STATUS 6 /* u_debugreg[DR_STATUS] */ +#define DR_CONTROL 7 /* u_debugreg[DR_CONTROL] */ + +/* Define a few things for the status register. We can use this to determine + which debugging register was responsible for the trap. The other bits + are either reserved or not of interest to us. */ + +#define DR_TRAP0 (0x1) /* db0 */ +#define DR_TRAP1 (0x2) /* db1 */ +#define DR_TRAP2 (0x4) /* db2 */ +#define DR_TRAP3 (0x8) /* db3 */ + +#define DR_STEP (0x4000) /* single-step */ +#define DR_SWITCH (0x8000) /* task switch */ + +/* Now define a bunch of things for manipulating the control register. + The top two bytes of the control register consist of 4 fields of 4 + bits - each field corresponds to one of the four debug registers, + and indicates what types of access we trap on, and how large the data + field is that we are looking at */ + +#define DR_CONTROL_SHIFT 16 /* Skip this many bits in ctl register */ +#define DR_CONTROL_SIZE 4 /* 4 control bits per register */ + +#define DR_RW_EXECUTE (0x0) /* Settings for the access types to trap on */ +#define DR_RW_WRITE (0x1) +#define DR_RW_READ (0x3) + +#define DR_LEN_1 (0x0) /* Settings for data length to trap on */ +#define DR_LEN_2 (0x4) +#define DR_LEN_4 (0xC) +#define DR_LEN_8 (0x8) + +/* The low byte to the control register determine which registers are + enabled. There are 4 fields of two bits. One bit is "local", meaning + that the processor will reset the bit after a task switch and the other + is global meaning that we have to explicitly reset the bit. With linux, + you can use either one, since we explicitly zero the register when we enter + kernel mode. */ + +#define DR_LOCAL_ENABLE_SHIFT 0 /* Extra shift to the local enable bit */ +#define DR_GLOBAL_ENABLE_SHIFT 1 /* Extra shift to the global enable bit */ +#define DR_ENABLE_SIZE 2 /* 2 enable bits per register */ + +#define DR_LOCAL_ENABLE_MASK (0x55) /* Set local bits for all 4 regs */ +#define DR_GLOBAL_ENABLE_MASK (0xAA) /* Set global bits for all 4 regs */ + +/* The second byte to the control register has a few special + things. */ + + + +#if __WORDSIZE == 64 +# define DR_CONTROL_RESERVED (0xFFFFFFFF0000FC00UL) /* Reserved */ +#else +# define DR_CONTROL_RESERVED (0x00FC00U) /* Reserved */ +#endif +#define DR_LOCAL_SLOWDOWN (0x100) /* Local slow the pipeline */ +#define DR_GLOBAL_SLOWDOWN (0x200) /* Global slow the pipeline */ + +#endif /* sys/debugreg.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/sys/epoll.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/sys/epoll.h new file mode 100644 index 00000000..02672d3c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/sys/epoll.h @@ -0,0 +1,110 @@ +/* Copyright (C) 2002,2003,2004,2005,2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_EPOLL_H +#define _SYS_EPOLL_H 1 + +#include +#include + + +enum EPOLL_EVENTS + { + EPOLLIN = 0x001, +#define EPOLLIN EPOLLIN + EPOLLPRI = 0x002, +#define EPOLLPRI EPOLLPRI + EPOLLOUT = 0x004, +#define EPOLLOUT EPOLLOUT + EPOLLRDNORM = 0x040, +#define EPOLLRDNORM EPOLLRDNORM + EPOLLRDBAND = 0x080, +#define EPOLLRDBAND EPOLLRDBAND + EPOLLWRNORM = 0x100, +#define EPOLLWRNORM EPOLLWRNORM + EPOLLWRBAND = 0x200, +#define EPOLLWRBAND EPOLLWRBAND + EPOLLMSG = 0x400, +#define EPOLLMSG EPOLLMSG + EPOLLERR = 0x008, +#define EPOLLERR EPOLLERR + EPOLLHUP = 0x010, +#define EPOLLHUP EPOLLHUP + EPOLLONESHOT = (1 << 30), +#define EPOLLONESHOT EPOLLONESHOT + EPOLLET = (1 << 31) +#define EPOLLET EPOLLET + }; + + +/* Valid opcodes ( "op" parameter ) to issue to epoll_ctl(). */ +#define EPOLL_CTL_ADD 1 /* Add a file decriptor to the interface. */ +#define EPOLL_CTL_DEL 2 /* Remove a file decriptor from the interface. */ +#define EPOLL_CTL_MOD 3 /* Change file decriptor epoll_event structure. */ + + +typedef union epoll_data +{ + void *ptr; + int fd; + uint32_t u32; + uint64_t u64; +} epoll_data_t; + +struct epoll_event +{ + uint32_t events; /* Epoll events */ + epoll_data_t data; /* User data variable */ +} __attribute__ ((__packed__)); + + +__BEGIN_DECLS + +/* Creates an epoll instance. Returns an fd for the new instance. + The "size" parameter is a hint specifying the number of file + descriptors to be associated with the new instance. The fd + returned by epoll_create() should be closed with close(). */ +extern int epoll_create (int __size) __THROW; + + +/* Manipulate an epoll instance "epfd". Returns 0 in case of success, + -1 in case of error ( the "errno" variable will contain the + specific error code ) The "op" parameter is one of the EPOLL_CTL_* + constants defined above. The "fd" parameter is the target of the + operation. The "event" parameter describes which events the caller + is interested in and any associated user data. */ +extern int epoll_ctl (int __epfd, int __op, int __fd, + struct epoll_event *__event) __THROW; + + +/* Wait for events on an epoll instance "epfd". Returns the number of + triggered events returned in "events" buffer. Or -1 in case of + error with the "errno" variable set to the specific error code. The + "events" parameter is a buffer that will contain triggered + events. The "maxevents" is the maximum number of events to be + returned ( usually size of "events" ). The "timeout" parameter + specifies the maximum wait time in milliseconds (-1 == infinite). + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern int epoll_wait (int __epfd, struct epoll_event *__events, + int __maxevents, int __timeout); + +__END_DECLS + +#endif /* sys/epoll.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/sys/io.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/sys/io.h new file mode 100644 index 00000000..ec121256 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/sys/io.h @@ -0,0 +1,182 @@ +/* Copyright (C) 1996, 2000, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_IO_H +#define _SYS_IO_H 1 + +#include + +__BEGIN_DECLS + +/* If TURN_ON is TRUE, request for permission to do direct i/o on the + port numbers in the range [FROM,FROM+NUM-1]. Otherwise, turn I/O + permission off for that range. This call requires root privileges. + + Portability note: not all Linux platforms support this call. Most + platforms based on the PC I/O architecture probably will, however. + E.g., Linux/Alpha for Alpha PCs supports this. */ +extern int ioperm (unsigned long int __from, unsigned long int __num, + int __turn_on) __THROW; +libc_hidden_proto(ioperm) + +/* Set the I/O privilege level to LEVEL. If LEVEL>3, permission to + access any I/O port is granted. This call requires root + privileges. */ +extern int iopl (int __level) __THROW; + +#if defined __GNUC__ && __GNUC__ >= 2 + +static __inline unsigned char +inb (unsigned short int port) +{ + unsigned char _v; + + __asm__ __volatile__ ("inb %w1,%0":"=a" (_v):"Nd" (port)); + return _v; +} + +static __inline unsigned char +inb_p (unsigned short int port) +{ + unsigned char _v; + + __asm__ __volatile__ ("inb %w1,%0\noutb %%al,$0x80":"=a" (_v):"Nd" (port)); + return _v; +} + +static __inline unsigned short int +inw (unsigned short int port) +{ + unsigned short _v; + + __asm__ __volatile__ ("inw %w1,%0":"=a" (_v):"Nd" (port)); + return _v; +} + +static __inline unsigned short int +inw_p (unsigned short int port) +{ + unsigned short int _v; + + __asm__ __volatile__ ("inw %w1,%0\noutb %%al,$0x80":"=a" (_v):"Nd" (port)); + return _v; +} + +static __inline unsigned int +inl (unsigned short int port) +{ + unsigned int _v; + + __asm__ __volatile__ ("inl %w1,%0":"=a" (_v):"Nd" (port)); + return _v; +} + +static __inline unsigned int +inl_p (unsigned short int port) +{ + unsigned int _v; + __asm__ __volatile__ ("inl %w1,%0\noutb %%al,$0x80":"=a" (_v):"Nd" (port)); + return _v; +} + +static __inline void +outb (unsigned char value, unsigned short int port) +{ + __asm__ __volatile__ ("outb %b0,%w1": :"a" (value), "Nd" (port)); +} + +static __inline void +outb_p (unsigned char value, unsigned short int port) +{ + __asm__ __volatile__ ("outb %b0,%w1\noutb %%al,$0x80": :"a" (value), + "Nd" (port)); +} + +static __inline void +outw (unsigned short int value, unsigned short int port) +{ + __asm__ __volatile__ ("outw %w0,%w1": :"a" (value), "Nd" (port)); + +} + +static __inline void +outw_p (unsigned short int value, unsigned short int port) +{ + __asm__ __volatile__ ("outw %w0,%w1\noutb %%al,$0x80": :"a" (value), + "Nd" (port)); +} + +static __inline void +outl (unsigned int value, unsigned short int port) +{ + __asm__ __volatile__ ("outl %0,%w1": :"a" (value), "Nd" (port)); +} + +static __inline void +outl_p (unsigned int value, unsigned short int port) +{ + __asm__ __volatile__ ("outl %0,%w1\noutb %%al,$0x80": :"a" (value), + "Nd" (port)); +} + +static __inline void +insb (unsigned short int port, void *addr, unsigned long int count) +{ + __asm__ __volatile__ ("cld ; rep ; insb":"=D" (addr), + "=c" (count):"d" (port), "0" (addr), "1" (count)); +} + +static __inline void +insw (unsigned short int port, void *addr, unsigned long int count) +{ + __asm__ __volatile__ ("cld ; rep ; insw":"=D" (addr), + "=c" (count):"d" (port), "0" (addr), "1" (count)); +} + +static __inline void +insl (unsigned short int port, void *addr, unsigned long int count) +{ + __asm__ __volatile__ ("cld ; rep ; insl":"=D" (addr), + "=c" (count):"d" (port), "0" (addr), "1" (count)); +} + +static __inline void +outsb (unsigned short int port, const void *addr, unsigned long int count) +{ + __asm__ __volatile__ ("cld ; rep ; outsb":"=S" (addr), + "=c" (count):"d" (port), "0" (addr), "1" (count)); +} + +static __inline void +outsw (unsigned short int port, const void *addr, unsigned long int count) +{ + __asm__ __volatile__ ("cld ; rep ; outsw":"=S" (addr), + "=c" (count):"d" (port), "0" (addr), "1" (count)); +} + +static __inline void +outsl (unsigned short int port, const void *addr, unsigned long int count) +{ + __asm__ __volatile__ ("cld ; rep ; outsl":"=S" (addr), + "=c" (count):"d" (port), "0" (addr), "1" (count)); +} + +#endif /* GNU C */ + +__END_DECLS +#endif /* _SYS_IO_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/sys/perm.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/sys/perm.h new file mode 100644 index 00000000..37964552 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/sys/perm.h @@ -0,0 +1,37 @@ +/* Copyright (C) 1996, 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_PERM_H + +#define _SYS_PERM_H 1 +#include + +__BEGIN_DECLS + +/* Set port input/output permissions. */ +extern int ioperm (unsigned long int __from, unsigned long int __num, + int __turn_on) __THROW; +libc_hidden_proto(ioperm) + + +/* Change I/O privilege level. */ +extern int iopl (int __level) __THROW; + +__END_DECLS + +#endif /* _SYS_PERM_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/sys/procfs.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/sys/procfs.h new file mode 100644 index 00000000..5995b711 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/sys/procfs.h @@ -0,0 +1,143 @@ +/* Copyright (C) 2001, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_PROCFS_H +#define _SYS_PROCFS_H 1 + +/* This is somewhat modelled after the file of the same name on SVR4 + systems. It provides a definition of the core file format for ELF + used on Linux. It doesn't have anything to do with the /proc file + system, even though Linux has one. + + Anyway, the whole purpose of this file is for GDB and GDB only. + Don't read too much into it. Don't use it for anything other than + GDB unless you know what you are doing. */ + +#include +#include +#include +#include +#include + +__BEGIN_DECLS + +/* Type for a general-purpose register. */ +typedef unsigned long elf_greg_t; + +/* And the whole bunch of them. We could have used `struct + user_regs_struct' directly in the typedef, but tradition says that + the register set is an array, which does have some peculiar + semantics, so leave it that way. */ +#define ELF_NGREG (sizeof (struct user_regs_struct) / sizeof(elf_greg_t)) +typedef elf_greg_t elf_gregset_t[ELF_NGREG]; + +#if __WORDSIZE == 32 +/* Register set for the floating-point registers. */ +typedef struct user_fpregs_struct elf_fpregset_t; + +/* Register set for the extended floating-point registers. Includes + the Pentium III SSE registers in addition to the classic + floating-point stuff. */ +typedef struct user_fpxregs_struct elf_fpxregset_t; +#else +/* Register set for the extended floating-point registers. Includes + the Pentium III SSE registers in addition to the classic + floating-point stuff. */ +typedef struct user_fpregs_struct elf_fpregset_t; +#endif + +/* Signal info. */ +struct elf_siginfo + { + int si_signo; /* Signal number. */ + int si_code; /* Extra code. */ + int si_errno; /* Errno. */ + }; + + +/* Definitions to generate Intel SVR4-like core files. These mostly + have the same names as the SVR4 types with "elf_" tacked on the + front to prevent clashes with Linux definitions, and the typedef + forms have been avoided. This is mostly like the SVR4 structure, + but more Linuxy, with things that Linux does not support and which + GDB doesn't really use excluded. */ + +struct elf_prstatus + { + struct elf_siginfo pr_info; /* Info associated with signal. */ + short int pr_cursig; /* Current signal. */ + unsigned long int pr_sigpend; /* Set of pending signals. */ + unsigned long int pr_sighold; /* Set of held signals. */ + __pid_t pr_pid; + __pid_t pr_ppid; + __pid_t pr_pgrp; + __pid_t pr_sid; + struct timeval pr_utime; /* User time. */ + struct timeval pr_stime; /* System time. */ + struct timeval pr_cutime; /* Cumulative user time. */ + struct timeval pr_cstime; /* Cumulative system time. */ + elf_gregset_t pr_reg; /* GP registers. */ + int pr_fpvalid; /* True if math copro being used. */ + }; + + +#define ELF_PRARGSZ (80) /* Number of chars for args. */ + +struct elf_prpsinfo + { + char pr_state; /* Numeric process state. */ + char pr_sname; /* Char for pr_state. */ + char pr_zomb; /* Zombie. */ + char pr_nice; /* Nice val. */ + unsigned long int pr_flag; /* Flags. */ +#if __WORDSIZE == 32 + unsigned short int pr_uid; + unsigned short int pr_gid; +#else + unsigned int pr_uid; + unsigned int pr_gid; +#endif + int pr_pid, pr_ppid, pr_pgrp, pr_sid; + /* Lots missing */ + char pr_fname[16]; /* Filename of executable. */ + char pr_psargs[ELF_PRARGSZ]; /* Initial part of arg list. */ + }; + + +/* The rest of this file provides the types for emulation of the + Solaris interfaces that should be implemented by + users of libthread_db. */ + +/* Addresses. */ +typedef void *psaddr_t; + +/* Register sets. Linux has different names. */ +typedef elf_gregset_t prgregset_t; +typedef elf_fpregset_t prfpregset_t; + +/* We don't have any differences between processes and threads, + therefore have only one PID type. */ +typedef __pid_t lwpid_t; + +/* Process status and info. In the end we do provide typedefs for them. */ +typedef struct elf_prstatus prstatus_t; +typedef struct elf_prpsinfo prpsinfo_t; + +__END_DECLS + +#endif /* sys/procfs.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/sys/reg.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/sys/reg.h new file mode 100644 index 00000000..865e3455 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/sys/reg.h @@ -0,0 +1,79 @@ +/* Copyright (C) 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_REG_H +#define _SYS_REG_H 1 + +#include + +#if __WORDSIZE == 64 +/* Index into an array of 8 byte longs returned from ptrace for + location of the users' stored general purpose registers. */ + +# define R15 0 +# define R14 1 +# define R13 2 +# define R12 3 +# define RBP 4 +# define RBX 5 +# define R11 6 +# define R10 7 +# define R9 8 +# define R8 9 +# define RAX 10 +# define RCX 11 +# define RDX 12 +# define RSI 13 +# define RDI 14 +# define ORIG_RAX 15 +# define RIP 16 +# define CS 17 +# define EFLAGS 18 +# define RSP 19 +# define SS 20 +# define FS_BASE 21 +# define GS_BASE 22 +# define DS 23 +# define ES 24 +# define FS 25 +# define GS 26 +#else + +/* Index into an array of 4 byte integers returned from ptrace for + * location of the users' stored general purpose registers. */ + +# define EBX 0 +# define ECX 1 +# define EDX 2 +# define ESI 3 +# define EDI 4 +# define EBP 5 +# define EAX 6 +# define DS 7 +# define ES 8 +# define FS 9 +# define GS 10 +# define ORIG_EAX 11 +# define EIP 12 +# define CS 13 +# define EFL 14 +# define UESP 15 +# define SS 16 +#endif + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/sys/ucontext.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/sys/ucontext.h new file mode 100644 index 00000000..b59cd292 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/sys/ucontext.h @@ -0,0 +1,248 @@ +/* Copyright (C) 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_UCONTEXT_H +#define _SYS_UCONTEXT_H 1 + +#include +#include +#include + +/* We need the signal context definitions even if they are not used + included in . */ +#include + +#if __WORDSIZE == 64 + +/* Type for general register. */ +typedef long int greg_t; + +/* Number of general registers. */ +#define NGREG 23 + +/* Container for all general registers. */ +typedef greg_t gregset_t[NGREG]; + +#ifdef __USE_GNU +/* Number of each register in the `gregset_t' array. */ +enum +{ + REG_R8 = 0, +# define REG_R8 REG_R8 + REG_R9, +# define REG_R9 REG_R9 + REG_R10, +# define REG_R10 REG_R10 + REG_R11, +# define REG_R11 REG_R11 + REG_R12, +# define REG_R12 REG_R12 + REG_R13, +# define REG_R13 REG_R13 + REG_R14, +# define REG_R14 REG_R14 + REG_R15, +# define REG_R15 REG_R15 + REG_RDI, +# define REG_RDI REG_RDI + REG_RSI, +# define REG_RSI REG_RSI + REG_RBP, +# define REG_RBP REG_RBP + REG_RBX, +# define REG_RBX REG_RBX + REG_RDX, +# define REG_RDX REG_RDX + REG_RAX, +# define REG_RAX REG_RAX + REG_RCX, +# define REG_RCX REG_RCX + REG_RSP, +# define REG_RSP REG_RSP + REG_RIP, +# define REG_RIP REG_RIP + REG_EFL, +# define REG_EFL REG_EFL + REG_CSGSFS, /* Actually short cs, gs, fs, __pad0. */ +# define REG_CSGSFS REG_CSGSFS + REG_ERR, +# define REG_ERR REG_ERR + REG_TRAPNO, +# define REG_TRAPNO REG_TRAPNO + REG_OLDMASK, +# define REG_OLDMASK REG_OLDMASK + REG_CR2 +# define REG_CR2 REG_CR2 +}; +#endif + +struct _libc_fpxreg +{ + unsigned short int significand[4]; + unsigned short int exponent; + unsigned short int padding[3]; +}; + +struct _libc_xmmreg +{ + __uint32_t element[4]; +}; + +struct _libc_fpstate +{ + /* 64-bit FXSAVE format. */ + __uint16_t cwd; + __uint16_t swd; + __uint16_t ftw; + __uint16_t fop; + __uint64_t rip; + __uint64_t rdp; + __uint32_t mxcsr; + __uint32_t mxcr_mask; + struct _libc_fpxreg _st[8]; + struct _libc_xmmreg _xmm[16]; + __uint32_t padding[24]; +}; + +/* Structure to describe FPU registers. */ +typedef struct _libc_fpstate *fpregset_t; + +/* Context to describe whole processor state. */ +typedef struct + { + gregset_t gregs; + /* Note that fpregs is a pointer. */ + fpregset_t fpregs; + unsigned long __reserved1 [8]; +} mcontext_t; + +/* Userlevel context. */ +typedef struct ucontext + { + unsigned long int uc_flags; + struct ucontext *uc_link; + stack_t uc_stack; + mcontext_t uc_mcontext; + __sigset_t uc_sigmask; + struct _libc_fpstate __fpregs_mem; + } ucontext_t; + +#else /* __WORDSIZE == 32 */ + +/* Type for general register. */ +typedef int greg_t; + +/* Number of general registers. */ +#define NGREG 19 + +/* Container for all general registers. */ +typedef greg_t gregset_t[NGREG]; + +#ifdef __USE_GNU +/* Number of each register is the `gregset_t' array. */ +enum +{ + REG_GS = 0, +# define REG_GS REG_GS + REG_FS, +# define REG_FS REG_FS + REG_ES, +# define REG_ES REG_ES + REG_DS, +# define REG_DS REG_DS + REG_EDI, +# define REG_EDI REG_EDI + REG_ESI, +# define REG_ESI REG_ESI + REG_EBP, +# define REG_EBP REG_EBP + REG_ESP, +# define REG_ESP REG_ESP + REG_EBX, +# define REG_EBX REG_EBX + REG_EDX, +# define REG_EDX REG_EDX + REG_ECX, +# define REG_ECX REG_ECX + REG_EAX, +# define REG_EAX REG_EAX + REG_TRAPNO, +# define REG_TRAPNO REG_TRAPNO + REG_ERR, +# define REG_ERR REG_ERR + REG_EIP, +# define REG_EIP REG_EIP + REG_CS, +# define REG_CS REG_CS + REG_EFL, +# define REG_EFL REG_EFL + REG_UESP, +# define REG_UESP REG_UESP + REG_SS +# define REG_SS REG_SS +}; +#endif + +/* Definitions taken from the kernel headers. */ +struct _libc_fpreg +{ + unsigned short int significand[4]; + unsigned short int exponent; +}; + +struct _libc_fpstate +{ + unsigned long int cw; + unsigned long int sw; + unsigned long int tag; + unsigned long int ipoff; + unsigned long int cssel; + unsigned long int dataoff; + unsigned long int datasel; + struct _libc_fpreg _st[8]; + unsigned long int status; +}; + +/* Structure to describe FPU registers. */ +typedef struct _libc_fpstate *fpregset_t; + +/* Context to describe whole processor state. */ +typedef struct + { + gregset_t gregs; + /* Due to Linux's history we have to use a pointer here. The SysV/i386 + ABI requires a struct with the values. */ + fpregset_t fpregs; + unsigned long int oldmask; + unsigned long int cr2; + } mcontext_t; + +/* Userlevel context. */ +typedef struct ucontext + { + unsigned long int uc_flags; + struct ucontext *uc_link; + stack_t uc_stack; + mcontext_t uc_mcontext; + __sigset_t uc_sigmask; + struct _libc_fpstate __fpregs_mem; + } ucontext_t; + +#endif /* __WORDSIZE == 32 */ + +#endif /* sys/ucontext.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/sys/user.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/sys/user.h new file mode 100644 index 00000000..5ff68e57 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/sys/user.h @@ -0,0 +1,176 @@ +/* Copyright (C) 2001, 2002, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_USER_H +#define _SYS_USER_H 1 + +/* The whole purpose of this file is for GDB and GDB only. Don't read + too much into it. Don't use it for anything other than GDB unless + you know what you are doing. */ + +#include + +#if __WORDSIZE == 64 + +struct user_fpregs_struct +{ + __uint16_t cwd; + __uint16_t swd; + __uint16_t ftw; + __uint16_t fop; + __uint64_t rip; + __uint64_t rdp; + __uint32_t mxcsr; + __uint32_t mxcr_mask; + __uint32_t st_space[32]; /* 8*16 bytes for each FP-reg = 128 bytes */ + __uint32_t xmm_space[64]; /* 16*16 bytes for each XMM-reg = 256 bytes */ + __uint32_t padding[24]; +}; + +struct user_regs_struct +{ + unsigned long r15; + unsigned long r14; + unsigned long r13; + unsigned long r12; + unsigned long rbp; + unsigned long rbx; + unsigned long r11; + unsigned long r10; + unsigned long r9; + unsigned long r8; + unsigned long rax; + unsigned long rcx; + unsigned long rdx; + unsigned long rsi; + unsigned long rdi; + unsigned long orig_rax; + unsigned long rip; + unsigned long cs; + unsigned long eflags; + unsigned long rsp; + unsigned long ss; + unsigned long fs_base; + unsigned long gs_base; + unsigned long ds; + unsigned long es; + unsigned long fs; + unsigned long gs; +}; + +struct user +{ + struct user_regs_struct regs; + int u_fpvalid; + struct user_fpregs_struct i387; + unsigned long int u_tsize; + unsigned long int u_dsize; + unsigned long int u_ssize; + unsigned long start_code; + unsigned long start_stack; + long int signal; + int reserved; + struct user_regs_struct* u_ar0; + struct user_fpregs_struct* u_fpstate; + unsigned long int magic; + char u_comm [32]; + unsigned long int u_debugreg [8]; +}; + +#else +/* These are the 32-bit x86 structures. */ +struct user_fpregs_struct +{ + long int cwd; + long int swd; + long int twd; + long int fip; + long int fcs; + long int foo; + long int fos; + long int st_space [20]; +}; + +struct user_fpxregs_struct +{ + unsigned short int cwd; + unsigned short int swd; + unsigned short int twd; + unsigned short int fop; + long int fip; + long int fcs; + long int foo; + long int fos; + long int mxcsr; + long int reserved; + long int st_space[32]; /* 8*16 bytes for each FP-reg = 128 bytes */ + long int xmm_space[32]; /* 8*16 bytes for each XMM-reg = 128 bytes */ + long int padding[56]; +}; + +struct user_regs_struct +{ + long int ebx; + long int ecx; + long int edx; + long int esi; + long int edi; + long int ebp; + long int eax; + long int xds; + long int xes; + long int xfs; + long int xgs; + long int orig_eax; + long int eip; + long int xcs; + long int eflags; + long int esp; + long int xss; +}; + +struct user +{ + struct user_regs_struct regs; + int u_fpvalid; + struct user_fpregs_struct i387; + unsigned long int u_tsize; + unsigned long int u_dsize; + unsigned long int u_ssize; + unsigned long start_code; + unsigned long start_stack; + long int signal; + int reserved; + struct user_regs_struct* u_ar0; + struct user_fpregs_struct* u_fpstate; + unsigned long int magic; + char u_comm [32]; + int u_debugreg [8]; +}; +#endif /* __WORDSIZE */ + +#include +#define PAGE_SHIFT 12 +#define PAGE_SIZE (1UL << PAGE_SHIFT) +#define PAGE_MASK (~(PAGE_SIZE-1)) +#define NBPG PAGE_SIZE +#define UPAGES 1 +#define HOST_TEXT_START_ADDR (u.start_code) +#define HOST_STACK_END_ADDR (u.start_stack + u.u_ssize * NBPG) + +#endif /* _SYS_USER_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/syscall.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/syscall.S new file mode 100644 index 00000000..ee223e3e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/syscall.S @@ -0,0 +1,42 @@ +/* Copyright (C) 2001, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Please consult the file sysdeps/unix/sysv/linux/x86-64/sysdep.h for + more information about the value -4095 used below. */ + +/* Usage: long syscall (syscall_number, arg1, arg2, arg3, arg4, arg5, arg6) + We need to do some arg shifting, the syscall_number will be in + rax. */ + +.text +.globl syscall +.type syscall,%function +syscall: + movq %rdi, %rax /* Syscall number -> rax. */ + movq %rsi, %rdi /* shift arg1 - arg5. */ + movq %rdx, %rsi + movq %rcx, %rdx + movq %r8, %r10 + movq %r9, %r8 + movq 8(%rsp),%r9 /* arg6 is on the stack. */ + syscall /* Do the system call. */ + cmpq $-4095, %rax /* Check %rax for error. */ + jae __syscall_error /* Branch forward if it failed. */ + ret /* Return to caller. */ + +.size syscall,.-syscall diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/sysdep.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/sysdep.h new file mode 100644 index 00000000..4440d2be --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/x86_64/sysdep.h @@ -0,0 +1,333 @@ +/* Copyright (C) 2001-2005, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _LINUX_X86_64_SYSDEP_H +#define _LINUX_X86_64_SYSDEP_H 1 + +/* There is some commonality. */ +#include +#include + +#ifdef __ASSEMBLER__ + +/* Syntactic details of assembler. */ + +/* ELF uses byte-counts for .align, most others use log2 of count of bytes. */ +#define ALIGNARG(log2) 1< + +/* Clone the calling process, but without copying the whole address space. + The calling process is suspended until the new process exits or is + replaced by a call to `execve'. Return -1 for errors, 0 to the new process, + and the process ID of the new process to the old process. */ + +#ifndef __NR_vfork +/* No vfork so use fork instead */ +# define __NR_vfork __NR_fork +#endif + +.text +.global __vfork +.hidden __vfork +.type __vfork,%function + +__vfork: + + /* Pop the return PC value into RDI. We need a register that + is preserved by the syscall and that we're allowed to destroy. */ + popq %rdi + +#ifdef SAVE_PID + SAVE_PID +#endif + + /* Stuff the syscall number in RAX and enter into the kernel. */ + movl $__NR_vfork, %eax + syscall + + /* Push back the return PC. */ + pushq %rdi + +#ifdef RESTORE_PID + RESTORE_PID +#endif + + cmpl $-4095, %eax + jae __syscall_error /* Branch forward if it failed. */ + + /* Normal return. */ + ret + +.size __vfork,.-__vfork + +weak_alias(__vfork,vfork) +libc_hidden_weak(vfork) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/Makefile new file mode 100644 index 00000000..633c91f3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../../ +top_builddir=../../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.arch +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/Makefile.arch b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/Makefile.arch new file mode 100644 index 00000000..bf450313 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/Makefile.arch @@ -0,0 +1,15 @@ +# Makefile for uClibc +# +# Copyright (C) 2007, 2008 Tensilica Inc. +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +CSRC := brk.c fork.c pread_write.c sigaction.c __syscall_error.c + +ifeq ($(UCLIBC_HAS_ADVANCED_REALTIME),y) + CSRC += posix_fadvise.c posix_fadvise64.c +endif + +SSRC := bsd-_setjmp.S bsd-setjmp.S setjmp.S clone.S \ + sigrestorer.S syscall.S mmap.S windowspill.S __longjmp.S vfork.S diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/__longjmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/__longjmp.S new file mode 100644 index 00000000..5d5dd2f5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/__longjmp.S @@ -0,0 +1,126 @@ +/* longjmp for Xtensa Processors. + + Copyright (C) 2001, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street - Fifth Floor, + Boston, MA 02110-1301, USA. */ + +/* This implementation relies heavily on the Xtensa register window + mechanism. Setjmp flushes all the windows except its own to the + stack and then copies registers from the save areas on the stack + into the jmp_buf structure, along with the return address of the call + to setjmp. Longjmp invalidates all the windows except its own, and + then sets things up so that it will return to the right place, + using a window underflow to automatically restore the registers. + + Note that it would probably be sufficient to only copy the + registers from setjmp's caller into jmp_buf. However, we also copy + the save area located at the stack pointer of setjmp's caller. + This save area will typically remain intact until the longjmp call. + The one exception is when there is an intervening alloca in + setjmp's caller. This is certainly an unusual situation and is + likely to cause problems in any case (the storage allocated on the + stack cannot be safely accessed following the longjmp). As bad as + it is, on most systems this situation would not necessarily lead to + a catastrophic failure. If we did not preserve the extra save area + on Xtensa, however, it would. When setjmp's caller returns after a + longjmp, there will be a window underflow; an invalid return + address or stack pointer in the save area will almost certainly + lead to a crash. Keeping a copy of the extra save area in the + jmp_buf avoids this with only a small additional cost. If setjmp + and longjmp are ever time-critical, this could be removed. */ + + +#include "sysdep.h" + + +ENTRY (__longjmp) + + /* Invalidate all but the current window. Reading and writing + special registers WINDOWBASE and WINDOWSTART are + privileged operations, so user processes must call the + slower __window_spill() to do the job. */ + + movi a4, __window_spill + callx4 a4 + + /* Return to the return address of the setjmp, using the + window size bits from the setjmp call so that the caller + will be able to find the return value that we put in a2. */ + + l32i a0, a2, 64 + + /* Copy the first 4 saved registers from jmp_buf into the save area + at the current sp so that the values will be restored to registers + when longjmp returns. */ + + addi a7, a1, -16 + l32i a4, a2, 0 + l32i a5, a2, 4 + s32i a4, a7, 0 + s32i a5, a7, 4 + l32i a4, a2, 8 + l32i a5, a2, 12 + s32i a4, a7, 8 + s32i a5, a7, 12 + + /* Copy the remaining 0-8 saved registers. */ + extui a7, a0, 30, 2 + blti a7, 2, .Lendlj + l32i a8, a2, 52 + slli a4, a7, 4 + sub a6, a8, a4 + addi a5, a2, 16 + addi a8, a8, -16 /* a8 = end of register overflow area */ +.Lljloop: + l32i a7, a5, 0 + l32i a4, a5, 4 + s32i a7, a6, 0 + s32i a4, a6, 4 + l32i a7, a5, 8 + l32i a4, a5, 12 + s32i a7, a6, 8 + s32i a4, a6, 12 + addi a5, a5, 16 + addi a6, a6, 16 + blt a6, a8, .Lljloop +.Lendlj: + + /* The 4 words saved from the register save area at the target's + sp are copied back to the target procedure's save area. The + only point of this is to prevent a catastrophic failure in + case the contents were moved by an alloca after calling + setjmp. This is a bit paranoid but it doesn't cost much. */ + + l32i a7, a2, 4 /* load the target stack pointer */ + addi a7, a7, -16 /* find the destination save area */ + l32i a4, a2, 48 + l32i a5, a2, 52 + s32i a4, a7, 0 + s32i a5, a7, 4 + l32i a4, a2, 56 + l32i a5, a2, 60 + s32i a4, a7, 8 + s32i a5, a7, 12 + + /* Return v ? v : 1. */ + movi a2, 1 + movnez a2, a3, a3 + + retw +END (__longjmp) + +libc_hidden_def (__longjmp) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/__syscall_error.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/__syscall_error.c new file mode 100644 index 00000000..2b642e81 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/__syscall_error.c @@ -0,0 +1,18 @@ +/* Wrapper for setting errno. + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +/* This routine is jumped to by all the syscall handlers, to stash + * an error number into errno. */ +int __syscall_error(int err_no) attribute_hidden; +int __syscall_error(int err_no) +{ + __set_errno(-err_no); + return -1; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/bits/endian.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/bits/endian.h new file mode 100644 index 00000000..38b3af31 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/bits/endian.h @@ -0,0 +1,10 @@ +#ifndef _ENDIAN_H +# error "Never use directly; include instead." +#endif + +/* Xtensa can be either big or little endian. */ +#ifdef __XTENSA_EB__ +# define __BYTE_ORDER __BIG_ENDIAN +#else +# define __BYTE_ORDER __LITTLE_ENDIAN +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/bits/fcntl.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/bits/fcntl.h new file mode 100644 index 00000000..921a6267 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/bits/fcntl.h @@ -0,0 +1,239 @@ +/* O_*, F_*, FD_* bit values for Linux. + Copyright (C) 1995, 1996, 1997, 1998, 2000, 2004, 2007 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street - Fifth Floor, + Boston, MA 02110-1301, USA. */ + +#ifndef _FCNTL_H +# error "Never use directly; include instead." +#endif + +#include +#ifdef __USE_GNU +# include +#endif + + +/* open/fcntl - O_SYNC is only implemented on blocks devices and on files + located on an ext2 file system */ +#define O_ACCMODE 0003 +#define O_RDONLY 00 +#define O_WRONLY 01 +#define O_RDWR 02 +#define O_CREAT 0100 /* not fcntl */ +#define O_EXCL 0200 /* not fcntl */ +#define O_NOCTTY 0400 /* not fcntl */ +#define O_TRUNC 01000 /* not fcntl */ +#define O_APPEND 02000 +#define O_NONBLOCK 04000 +#define O_NDELAY O_NONBLOCK +#define O_SYNC 010000 +#define O_FSYNC O_SYNC +#define O_ASYNC 020000 + +#ifdef __USE_GNU +# define O_DIRECT 040000 /* Direct disk access. */ +# define O_DIRECTORY 0200000 /* Must be a directory. */ +# define O_NOFOLLOW 0400000 /* Do not follow links. */ +# define O_NOATIME 01000000 /* Do not set atime. */ +# define O_CLOEXEC 02000000 /* set close_on_exec */ +#endif + +/* For now Linux has synchronisity options for data and read operations. + We define the symbols here but let them do the same as O_SYNC since + this is a superset. */ +#if defined __USE_POSIX199309 || defined __USE_UNIX98 +# define O_DSYNC O_SYNC /* Synchronize data. */ +# define O_RSYNC O_SYNC /* Synchronize read operations. */ +#endif + +#ifdef __USE_LARGEFILE64 +# define O_LARGEFILE 0100000 +#endif + +/* Values for the second argument to `fcntl'. */ +#define F_DUPFD 0 /* Duplicate file descriptor. */ +#define F_GETFD 1 /* Get file descriptor flags. */ +#define F_SETFD 2 /* Set file descriptor flags. */ +#define F_GETFL 3 /* Get file status flags. */ +#define F_SETFL 4 /* Set file status flags. */ +#ifndef __USE_FILE_OFFSET64 +# define F_GETLK 5 /* Get record locking info. */ +# define F_SETLK 6 /* Set record locking info (non-blocking). */ +# define F_SETLKW 7 /* Set record locking info (blocking). */ +#else +# define F_GETLK F_GETLK64 /* Get record locking info. */ +# define F_SETLK F_SETLK64 /* Set record locking info (non-blocking).*/ +# define F_SETLKW F_SETLKW64 /* Set record locking info (blocking). */ +#endif +#define F_GETLK64 12 /* Get record locking info. */ +#define F_SETLK64 13 /* Set record locking info (non-blocking). */ +#define F_SETLKW64 14 /* Set record locking info (blocking). */ + +#if defined __USE_BSD || defined __USE_UNIX98 +# define F_SETOWN 8 /* Get owner of socket (receiver of SIGIO). */ +# define F_GETOWN 9 /* Set owner of socket (receiver of SIGIO). */ +#endif + +#ifdef __USE_GNU +# define F_SETSIG 10 /* Set number of signal to be sent. */ +# define F_GETSIG 11 /* Get number of signal to be sent. */ +#endif + +#ifdef __USE_GNU +# define F_SETLEASE 1024 /* Set a lease. */ +# define F_GETLEASE 1025 /* Enquire what lease is active. */ +# define F_NOTIFY 1026 /* Request notfications on a directory. */ +# define F_DUPFD_CLOEXEC 1030 /* Duplicate file descriptor with + close-on-exit set on new fd. */ +#endif + +/* For F_[GET|SET]FD. */ +#define FD_CLOEXEC 1 /* actually anything with low bit set goes */ + +/* For posix fcntl() and `l_type' field of a `struct flock' for lockf(). */ +#define F_RDLCK 0 /* Read lock. */ +#define F_WRLCK 1 /* Write lock. */ +#define F_UNLCK 2 /* Remove lock. */ + +/* For old implementation of bsd flock(). */ +#define F_EXLCK 4 /* or 3 */ +#define F_SHLCK 8 /* or 4 */ + +#ifdef __USE_BSD +/* Operations for bsd flock(), also used by the kernel implementation. */ +# define LOCK_SH 1 /* shared lock */ +# define LOCK_EX 2 /* exclusive lock */ +# define LOCK_NB 4 /* or'd with one of the above to prevent + blocking */ +# define LOCK_UN 8 /* remove lock */ +#endif + +#ifdef __USE_GNU +# define LOCK_MAND 32 /* This is a mandatory flock: */ +# define LOCK_READ 64 /* ... which allows concurrent read operations. */ +# define LOCK_WRITE 128 /* ... which allows concurrent write operations. */ +# define LOCK_RW 192 /* ... Which allows concurrent read & write operations. */ +#endif + +#ifdef __USE_GNU +/* Types of directory notifications that may be requested with F_NOTIFY. */ +# define DN_ACCESS 0x00000001 /* File accessed. */ +# define DN_MODIFY 0x00000002 /* File modified. */ +# define DN_CREATE 0x00000004 /* File created. */ +# define DN_DELETE 0x00000008 /* File removed. */ +# define DN_RENAME 0x00000010 /* File renamed. */ +# define DN_ATTRIB 0x00000020 /* File changed attibutes. */ +# define DN_MULTISHOT 0x80000000 /* Don't remove notifier. */ +#endif + +struct flock + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ +#ifndef __USE_FILE_OFFSET64 + __off_t l_start; /* Offset where the lock begins. */ + __off_t l_len; /* Size of the locked area; zero means until EOF. */ +#else + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ +#endif + __pid_t l_pid; /* Process holding the lock. */ + }; + +#ifdef __USE_LARGEFILE64 +struct flock64 + { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ + __pid_t l_pid; /* Process holding the lock. */ + }; +#endif + +/* Define some more compatibility macros to be backward compatible with + BSD systems which did not managed to hide these kernel macros. */ +#ifdef __USE_BSD +# define FAPPEND O_APPEND +# define FFSYNC O_FSYNC +# define FASYNC O_ASYNC +# define FNONBLOCK O_NONBLOCK +# define FNDELAY O_NDELAY +#endif /* Use BSD. */ + +/* Advise to `posix_fadvise'. */ +#ifdef __USE_XOPEN2K +# define POSIX_FADV_NORMAL 0 /* No further special treatment. */ +# define POSIX_FADV_RANDOM 1 /* Expect random page references. */ +# define POSIX_FADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define POSIX_FADV_WILLNEED 3 /* Will need these pages. */ +# define POSIX_FADV_DONTNEED 4 /* Don't need these pages. */ +# define POSIX_FADV_NOREUSE 5 /* Data will be accessed once. */ +#endif + + +#if defined __USE_GNU && defined __UCLIBC_LINUX_SPECIFIC__ +/* Flags for SYNC_FILE_RANGE. */ +# define SYNC_FILE_RANGE_WAIT_BEFORE 1 /* Wait upon writeout of all pages + in the range before performing the + write. */ +# define SYNC_FILE_RANGE_WRITE 2 /* Initiate writeout of all those + dirty pages in the range which are + not presently under writeback. */ +# define SYNC_FILE_RANGE_WAIT_AFTER 4 /* Wait upon writeout of all pages in + the range after performing the + write. */ + +/* Flags for SPLICE and VMSPLICE. */ +# define SPLICE_F_MOVE 1 /* Move pages instead of copying. */ +# define SPLICE_F_NONBLOCK 2 /* Don't block on the pipe splicing + (but we may still block on the fd + we splice from/to). */ +# define SPLICE_F_MORE 4 /* Expect more data. */ +# define SPLICE_F_GIFT 8 /* Pages passed in are a gift. */ +#endif + +__BEGIN_DECLS + +#if defined __USE_GNU && defined __UCLIBC_LINUX_SPECIFIC__ + +/* Provide kernel hint to read ahead. */ +extern ssize_t readahead (int __fd, __off64_t __offset, size_t __count) + __THROW; + + +/* Selective file content synch'ing. */ +extern int sync_file_range (int __fd, __off64_t __from, __off64_t __to, + unsigned int __flags); + +/* Splice address range into a pipe. */ +extern ssize_t vmsplice (int __fdout, const struct iovec *__iov, + size_t __count, unsigned int __flags); + +/* Splice two files together. */ +extern ssize_t splice (int __fdin, __off64_t *__offin, int __fdout, + __off64_t *__offout, size_t __len, + unsigned int __flags); + +/* In-kernel implementation of tee for pipe buffers. */ +extern ssize_t tee (int __fdin, int __fdout, size_t __len, + unsigned int __flags); + +#endif +__END_DECLS + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/bits/ipc.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/bits/ipc.h new file mode 100644 index 00000000..481bdcc5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/bits/ipc.h @@ -0,0 +1,54 @@ +/* Copyright (C) 1995-1999, 2000, 2005, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street - Fifth Floor, + Boston, MA 02110-1301, USA. */ + +#ifndef _SYS_IPC_H +# error "Never use directly; include instead." +#endif + +#include + +/* Mode bits for `msgget', `semget', and `shmget'. */ +#define IPC_CREAT 01000 /* Create key if key does not exist. */ +#define IPC_EXCL 02000 /* Fail if key exists. */ +#define IPC_NOWAIT 04000 /* Return error on wait. */ + +/* Control commands for `msgctl', `semctl', and `shmctl'. */ +#define IPC_RMID 0 /* Remove identifier. */ +#define IPC_SET 1 /* Set `ipc_perm' options. */ +#define IPC_STAT 2 /* Get `ipc_perm' options. */ +#ifdef __USE_GNU +# define IPC_INFO 3 /* See ipcs. */ +#endif + +/* Special key values. */ +#define IPC_PRIVATE ((__key_t) 0) /* Private key. */ + + +/* Data structure used to pass permission information to IPC operations. */ +struct ipc_perm + { + __key_t __key; /* Key. */ + __uid_t uid; /* Owner's user ID. */ + __gid_t gid; /* Owner's group ID. */ + __uid_t cuid; /* Creator's user ID. */ + __gid_t cgid; /* Creator's group ID. */ + unsigned int mode; /* Read/write permission. */ + unsigned int __seq; /* Sequence number. */ + unsigned long int __unused1; + unsigned long int __unused2; + }; diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/bits/kernel_stat.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/bits/kernel_stat.h new file mode 100644 index 00000000..10a35a23 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/bits/kernel_stat.h @@ -0,0 +1,49 @@ +#ifndef _BITS_STAT_STRUCT_H +#define _BITS_STAT_STRUCT_H + +#ifndef _LIBC +#error bits/kernel_stat.h is for internal uClibc use only! +#endif + +/* This file provides whatever this particular arch's kernel thinks + * struct kernel_stat should look like... It turns out each arch has a + * different opinion on the subject... */ + +struct kernel_stat { + unsigned long st_dev; + unsigned long st_ino; + unsigned int st_mode; + unsigned int st_nlink; + unsigned int st_uid; + unsigned int st_gid; + unsigned long st_rdev; + long st_size; + unsigned long st_blksize; + unsigned long st_blocks; + struct timespec st_atim; + struct timespec st_mtim; + struct timespec st_ctim; + unsigned long __unused4; + unsigned long __unused5; +}; + +struct kernel_stat64 { + unsigned long long st_dev; /* Device */ + unsigned long long st_ino; /* File serial number */ + unsigned int st_mode; /* File mode. */ + unsigned int st_nlink; /* Link count. */ + unsigned int st_uid; /* User ID of the file's owner. */ + unsigned int st_gid; /* Group ID of the file's group. */ + unsigned long long st_rdev; /* Device number, if device. */ + long long st_size; /* Size of file, in bytes. */ + unsigned long st_blksize; /* Optimal block size for I/O. */ + unsigned long __unused2; + unsigned long long st_blocks; /* Number 512-byte blocks allocated. */ + struct timespec st_atim; /* Time of last access. */ + struct timespec st_mtim; /* Time of last modification. */ + struct timespec st_ctim; /* Time of last status change. */ + unsigned long __unused4; + unsigned long __unused5; +}; + +#endif /* _BITS_STAT_STRUCT_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/bits/kernel_types.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/bits/kernel_types.h new file mode 100644 index 00000000..44f1075f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/bits/kernel_types.h @@ -0,0 +1,48 @@ +/* Note that we use the exact same include guard #define names + * as asm/posix_types.h. This will avoid gratuitous conflicts + * with the posix_types.h kernel header, and will ensure that + * our private content, and not the kernel header, will win. + * -Erik + */ +#ifndef _XTENSA_POSIX_TYPES_H +#define _XTENSA_POSIX_TYPES_H + +typedef unsigned long __kernel_ino_t; +typedef unsigned int __kernel_mode_t; +typedef unsigned long __kernel_nlink_t; +typedef long __kernel_off_t; +typedef int __kernel_pid_t; +typedef unsigned short __kernel_ipc_pid_t; +typedef unsigned int __kernel_uid_t; +typedef unsigned int __kernel_gid_t; +typedef unsigned int __kernel_size_t; +typedef int __kernel_ssize_t; +typedef long __kernel_ptrdiff_t; +typedef long __kernel_time_t; +typedef long __kernel_suseconds_t; +typedef long __kernel_clock_t; +typedef int __kernel_timer_t; +typedef int __kernel_clockid_t; +typedef int __kernel_daddr_t; +typedef char * __kernel_caddr_t; +typedef unsigned short __kernel_uid16_t; +typedef unsigned short __kernel_gid16_t; +typedef unsigned int __kernel_uid32_t; +typedef unsigned int __kernel_gid32_t; + +typedef unsigned short __kernel_old_uid_t; +typedef unsigned short __kernel_old_gid_t; +typedef unsigned short __kernel_old_dev_t; +typedef long long __kernel_loff_t; + +/* Beginning in 2.6 kernels, which is the first version that includes the + Xtensa port, __kernel_dev_t is defined in "linux/types.h" and is no longer + architecture-specific. It is defined here in uClibc for consistency with + other uClibc ports and for lack of a better place. */ +typedef unsigned int __kernel_dev_t; + +typedef struct { + int val[2]; +} __kernel_fsid_t; + +#endif /* _XTENSA_POSIX_TYPES_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/bits/mathdef.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/bits/mathdef.h new file mode 100644 index 00000000..0177fa9f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/bits/mathdef.h @@ -0,0 +1,43 @@ +/* Copyright (C) 2000, 2001, 2004, 2007 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street - Fifth Floor, + Boston, MA 02110-1301, USA. */ + +#if !defined _MATH_H && !defined _COMPLEX_H +# error "Never use directly; include instead" +#endif + +#if defined __USE_ISOC99 && defined _MATH_H && !defined _MATH_H_MATHDEF +# define _MATH_H_MATHDEF 1 + +/* Xtensa has `float' and `double' operations. */ +typedef float float_t; /* `float' expressions are evaluated as + `float'. */ +typedef double double_t; /* `double' expressions are evaluated as + `double'. */ + +/* The values returned by `ilogb' for 0 and NaN respectively. */ +# define FP_ILOGB0 (-2147483647) +# define FP_ILOGBNAN 2147483647 + +#endif /* ISO C99 */ + +#ifndef __NO_LONG_DOUBLE_MATH +/* Signal that we do not really have a `long double'. The disables the + declaration of all the `long double' function variants. */ +# define __NO_LONG_DOUBLE_MATH 1 +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/bits/mman.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/bits/mman.h new file mode 100644 index 00000000..fead3ac2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/bits/mman.h @@ -0,0 +1,106 @@ +/* Definitions for POSIX memory map interface. Linux/Xtensa version. + Copyright (C) 1997, 2000, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street - Fifth Floor, + Boston, MA 02110-1301, USA. */ + +#ifndef _SYS_MMAN_H +# error "Never use directly; include instead." +#endif + +/* The following definitions basically come from the kernel headers. + But the kernel header is not namespace clean. */ + + +/* Protections are chosen from these bits, OR'd together. The + implementation does not necessarily support PROT_EXEC or PROT_WRITE + without PROT_READ. The only guarantees are that no writing will be + allowed without PROT_WRITE and no access will be allowed for PROT_NONE. */ + +#define PROT_READ 0x1 /* Page can be read. */ +#define PROT_WRITE 0x2 /* Page can be written. */ +#define PROT_EXEC 0x4 /* Page can be executed. */ +#define PROT_NONE 0x0 /* Page can not be accessed. */ +#define PROT_GROWSDOWN 0x01000000 /* Extend change to start of + growsdown vma (mprotect only). */ +#define PROT_GROWSUP 0x02000000 /* Extend change to start of + growsup vma (mprotect only). */ + +/* Sharing types (must choose one and only one of these). */ +#define MAP_SHARED 0x01 /* Share changes. */ +#define MAP_PRIVATE 0x02 /* Changes are private. */ +#ifdef __USE_MISC +# define MAP_TYPE 0x0f /* Mask for type of mapping. */ +#endif + +/* Other flags. */ +#define MAP_FIXED 0x10 /* Interpret addr exactly. */ +#ifdef __USE_MISC +# define MAP_FILE 0 +# define MAP_ANONYMOUS 0x800 /* Don't use a file. */ +# define MAP_ANON MAP_ANONYMOUS +# define MAP_RENAME MAP_ANONYMOUS +#endif + +/* These are Linux-specific. */ +#ifdef __USE_MISC +# define MAP_GROWSDOWN 0x1000 /* Stack-like segment. */ +# define MAP_DENYWRITE 0x2000 /* ETXTBSY */ +# define MAP_EXECUTABLE 0x4000 /* Mark it as an executable. */ +# define MAP_LOCKED 0x8000 /* Lock the mapping. */ +# define MAP_NORESERVE 0x0400 /* Don't check for reservations. */ +# define MAP_POPULATE 0x10000 /* Populate (prefault) pagetables. */ +# define MAP_NONBLOCK 0x20000 /* Do not block on IO. */ +# define MAP_UNINITIALIZE 0x4000000 /* For anonymous mmap, memory could + be uninitialized. */ +#endif + +/* Flags to `msync'. */ +#define MS_ASYNC 1 /* Sync memory asynchronously. */ +#define MS_SYNC 4 /* Synchronous memory sync. */ +#define MS_INVALIDATE 2 /* Invalidate the caches. */ + +/* Flags for `mlockall'. */ +#define MCL_CURRENT 1 /* Lock all currently mapped pages. */ +#define MCL_FUTURE 2 /* Lock all additions to address + space. */ + +/* Flags for `mremap'. */ +#ifdef __USE_GNU +# define MREMAP_MAYMOVE 1 +# define MREMAP_FIXED 2 +#endif + +/* Advice to `madvise'. */ +#ifdef __USE_BSD +# define MADV_NORMAL 0 /* No further special treatment. */ +# define MADV_RANDOM 1 /* Expect random page references. */ +# define MADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define MADV_WILLNEED 3 /* Will need these pages. */ +# define MADV_DONTNEED 4 /* Don't need these pages. */ +# define MADV_REMOVE 9 /* Remove these pages and resources. */ +# define MADV_DONTFORK 10 /* Do not inherit across fork. */ +# define MADV_DOFORK 11 /* Do inherit across fork. */ +#endif + +/* The POSIX people had to invent similar names for the same things. */ +#ifdef __USE_XOPEN2K +# define POSIX_MADV_NORMAL 0 /* No further special treatment. */ +# define POSIX_MADV_RANDOM 1 /* Expect random page references. */ +# define POSIX_MADV_SEQUENTIAL 2 /* Expect sequential page references. */ +# define POSIX_MADV_WILLNEED 3 /* Will need these pages. */ +# define POSIX_MADV_DONTNEED 4 /* Don't need these pages. */ +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/bits/msq.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/bits/msq.h new file mode 100644 index 00000000..2eca21e6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/bits/msq.h @@ -0,0 +1,88 @@ +/* Copyright (C) 1995-1997, 2000, 2004, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street - Fifth Floor, + Boston, MA 02110-1301, USA. */ + +#ifndef _SYS_MSG_H +# error "Never use directly; include instead." +#endif + +#include + +/* Define options for message queue functions. */ +#define MSG_NOERROR 010000 /* no error if message is too big */ +#ifdef __USE_GNU +# define MSG_EXCEPT 020000 /* recv any msg except of specified type */ +#endif + +/* Types used in the structure definition. */ +typedef unsigned long int msgqnum_t; +typedef unsigned long int msglen_t; + + +/* Structure of record for one message inside the kernel. + The type `struct msg' is opaque. */ +struct msqid_ds +{ + struct ipc_perm msg_perm; /* structure describing operation permission */ +#if defined (__XTENSA_EB__) + unsigned long int __unused1; + __time_t msg_stime; /* time of last msgsnd command */ + unsigned long int __unused2; + __time_t msg_rtime; /* time of last msgrcv command */ + unsigned long int __unused3; + __time_t msg_ctime; /* time of last change */ +#elif defined (__XTENSA_EL__) + __time_t msg_stime; /* time of last msgsnd command */ + unsigned long int __unused1; + __time_t msg_rtime; /* time of last msgrcv command */ + unsigned long int __unused2; + __time_t msg_ctime; /* time of last change */ + unsigned long int __unused3; +#else +# error endian order not defined +#endif + unsigned long int __msg_cbytes; /* current number of bytes on queue */ + msgqnum_t msg_qnum; /* number of messages currently on queue */ + msglen_t msg_qbytes; /* max number of bytes allowed on queue */ + __pid_t msg_lspid; /* pid of last msgsnd() */ + __pid_t msg_lrpid; /* pid of last msgrcv() */ + unsigned long int __unused4; + unsigned long int __unused5; +}; + +#ifdef __USE_MISC + +# define msg_cbytes __msg_cbytes + +/* ipcs ctl commands */ +# define MSG_STAT 11 +# define MSG_INFO 12 + +/* buffer for msgctl calls IPC_INFO, MSG_INFO */ +struct msginfo + { + int msgpool; + int msgmap; + int msgmax; + int msgmnb; + int msgmni; + int msgssz; + int msgtql; + unsigned short int msgseg; + }; + +#endif /* __USE_MISC */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/bits/setjmp.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/bits/setjmp.h new file mode 100644 index 00000000..1bc4896c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/bits/setjmp.h @@ -0,0 +1,46 @@ +/* Copyright (C) 1997, 1998, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street - Fifth Floor, + Boston, MA 02110-1301, USA. */ + +/* Define the machine-dependent type `jmp_buf'. Xtensa version. */ +#ifndef _BITS_SETJMP_H +#define _BITS_SETJMP_H 1 + +#if !defined _SETJMP_H && !defined _PTHREAD_H +# error "Never include directly; use instead." +#endif + +/* The jmp_buf structure for Xtensa holds the following (where "proc" + is the procedure that calls setjmp): 4-12 registers from the window + of proc, the 4 words from the save area at proc's $sp (in case a + subsequent alloca in proc moves $sp), and the return address within + proc. Everything else is saved on the stack in the normal save areas. */ + +#ifndef _ASM +typedef int __jmp_buf[17]; +#endif + +#define JB_SP 1 +#define JB_PC 16 + +/* Test if longjmp to JMPBUF would unwind the frame containing a local + variable at ADDRESS. */ + +#define _JMPBUF_UNWINDS(jmpbuf, address) \ + ((void *) (address) < (void *) (jmpbuf)[JB_SP]) + +#endif /* bits/setjmp.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/bits/shm.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/bits/shm.h new file mode 100644 index 00000000..de41d0d9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/bits/shm.h @@ -0,0 +1,115 @@ +/* Copyright (C) 1995, 1996, 1997, 2000, 2002, 2007 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street - Fifth Floor, + Boston, MA 02110-1301, USA. */ + +#ifndef _SYS_SHM_H +# error "Never include directly; use instead." +#endif + +#include + +/* Permission flag for shmget. */ +#define SHM_R 0400 /* or S_IRUGO from */ +#define SHM_W 0200 /* or S_IWUGO from */ + +/* Flags for `shmat'. */ +#define SHM_RDONLY 010000 /* attach read-only else read-write */ +#define SHM_RND 020000 /* round attach address to SHMLBA */ +#define SHM_REMAP 040000 /* take-over region on attach */ + +/* Commands for `shmctl'. */ +#define SHM_LOCK 11 /* lock segment (root only) */ +#define SHM_UNLOCK 12 /* unlock segment (root only) */ + +__BEGIN_DECLS + +/* Segment low boundary address multiple. */ +#define SHMLBA (__getpagesize ()) +extern int __getpagesize (void) __THROW __attribute__ ((__const__)); + + +/* Type to count number of attaches. */ +typedef unsigned long int shmatt_t; + +/* Data structure describing a set of semaphores. */ +struct shmid_ds + { + struct ipc_perm shm_perm; /* operation permission struct */ + size_t shm_segsz; /* size of segment in bytes */ +#if defined (__XTENSA_EL__) + __time_t shm_atime; /* time of last shmat() */ + unsigned long int __unused1; + __time_t shm_dtime; /* time of last shmdt() */ + unsigned long int __unused2; + __time_t shm_ctime; /* time of last change by shmctl() */ + unsigned long int __unused3; +#elif defined (__XTENSA_EB__) + unsigned long int __unused1; + __time_t shm_atime; /* time of last shmat() */ + unsigned long int __unused2; + __time_t shm_dtime; /* time of last shmdt() */ + unsigned long int __unused3; + __time_t shm_ctime; /* time of last change by shmctl() */ +#else +# error endian order not defined +#endif + __pid_t shm_cpid; /* pid of creator */ + __pid_t shm_lpid; /* pid of last shmop */ + shmatt_t shm_nattch; /* number of current attaches */ + unsigned long int __unused4; + unsigned long int __unused5; + }; + +#ifdef __USE_MISC + +/* ipcs ctl commands */ +# define SHM_STAT 13 +# define SHM_INFO 14 + +/* shm_mode upper byte flags */ +# define SHM_DEST 01000 /* segment will be destroyed on last detach */ +# define SHM_LOCKED 02000 /* segment will not be swapped */ +# define SHM_HUGETLB 04000 /* segment is mapped via hugetlb */ +# define SHM_NORESERVE 010000 /* don't check for reservations */ + +struct shminfo + { + unsigned long int shmmax; + unsigned long int shmmin; + unsigned long int shmmni; + unsigned long int shmseg; + unsigned long int shmall; + unsigned long int __unused1; + unsigned long int __unused2; + unsigned long int __unused3; + unsigned long int __unused4; + }; + +struct shm_info + { + int used_ids; + unsigned long int shm_tot; /* total allocated shm */ + unsigned long int shm_rss; /* total resident shm */ + unsigned long int shm_swp; /* total swapped shm */ + unsigned long int swap_attempts; + unsigned long int swap_successes; + }; + +#endif /* __USE_MISC */ + +__END_DECLS diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/bits/sigcontextinfo.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/bits/sigcontextinfo.h new file mode 100644 index 00000000..8f3301c9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/bits/sigcontextinfo.h @@ -0,0 +1,33 @@ +/* Copyright (C) 2003, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street - Fifth Floor, + Boston, MA 02110-1301, USA. */ + +/* Also see register-dump.h, where we spill live registers to the + stack so that we can trace the stack backward. */ + +#define SIGCONTEXT unsigned long _info, ucontext_t * +#define SIGCONTEXT_EXTRA_ARGS _info, + +/* ANDing with 0x3fffffff clears the window-size bits. + Assumes TASK_SIZE = 0x40000000. */ + +#define GET_PC(ctx) ((void *) (ctx->uc_mcontext.sc_pc & 0x3fffffff)) +#define GET_FRAME(ctx) ((void *) ctx->uc_mcontext.sc_a[1]) +#define GET_STACK(ctx) ((void *) ctx->uc_mcontext.sc_a[1]) +#define CALL_SIGHANDLER(handler, signo, ctx) \ + (handler)((signo), SIGCONTEXT_EXTRA_ARGS (ctx)) + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/bits/stackinfo.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/bits/stackinfo.h new file mode 100644 index 00000000..50ddf251 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/bits/stackinfo.h @@ -0,0 +1,28 @@ +/* Copyright (C) 2000, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street - Fifth Floor, + Boston, MA 02110-1301, USA. */ + +/* This file contains a bit of information about the stack allocation + of the processor. */ + +#ifndef _STACKINFO_H +#define _STACKINFO_H 1 + +/* On Xtensa the stack grows down. */ +#define _STACK_GROWS_DOWN 1 + +#endif /* stackinfo.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/bits/stat.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/bits/stat.h new file mode 100644 index 00000000..8b67b157 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/bits/stat.h @@ -0,0 +1,158 @@ +/* Copyright (C) 1992, 1995-2005, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street - Fifth Floor, + Boston, MA 02110-1301, USA. */ + +#ifndef _SYS_STAT_H +# error "Never include directly; use instead." +#endif + +/* Versions of the `struct stat' data structure. */ +#define _STAT_VER_KERNEL 0 +#define _STAT_VER_LINUX 1 +#define _STAT_VER _STAT_VER_LINUX + +/* Versions of the `xmknod' interface. */ +#define _MKNOD_VER_LINUX 0 + + +struct stat + { + __dev_t st_dev; /* Device. */ +#ifndef __USE_FILE_OFFSET64 + __ino_t st_ino; /* File serial number. */ +#else + __ino64_t st_ino; /* File serial number. */ +#endif + __mode_t st_mode; /* File mode. */ + __nlink_t st_nlink; /* Link count. */ + __uid_t st_uid; /* User ID of the file's owner. */ + __gid_t st_gid; /* Group ID of the file's group.*/ + __dev_t st_rdev; /* Device number, if device. */ +#ifndef __USE_FILE_OFFSET64 + __off_t st_size; /* Size of file, in bytes. */ +#else + __off64_t st_size; /* Size of file, in bytes. */ +#endif + __blksize_t st_blksize; /* Optimal block size for I/O. */ + +#ifndef __USE_FILE_OFFSET64 + __blkcnt_t st_blocks; /* Number 512-byte blocks allocated. */ +#else + unsigned long __pad2; + __blkcnt64_t st_blocks; /* Number 512-byte blocks allocated. */ +#endif +#ifdef __USE_MISC + /* Nanosecond resolution timestamps are stored in a format + equivalent to 'struct timespec'. This is the type used + whenever possible but the Unix namespace rules do not allow the + identifier 'timespec' to appear in the header. + Therefore we have to handle the use of this header in strictly + standard-compliant sources special. */ + struct timespec st_atim; /* Time of last access. */ + struct timespec st_mtim; /* Time of last modification. */ + struct timespec st_ctim; /* Time of last status change. */ +# define st_atime st_atim.tv_sec /* Backward compatibility. */ +# define st_mtime st_mtim.tv_sec +# define st_ctime st_ctim.tv_sec +#else + __time_t st_atime; /* Time of last access. */ + unsigned long int st_atimensec; /* Nscecs of last access. */ + __time_t st_mtime; /* Time of last modification. */ + unsigned long int st_mtimensec; /* Nsecs of last modification. */ + __time_t st_ctime; /* Time of last status change. */ + unsigned long int st_ctimensec; /* Nsecs of last status change. */ +#endif + unsigned long int __unused4; + unsigned long int __unused5; + }; + +#ifdef __USE_LARGEFILE64 +struct stat64 + { + __dev_t st_dev; /* Device. */ + __ino64_t st_ino; /* File serial number. */ + __mode_t st_mode; /* File mode. */ + __nlink_t st_nlink; /* Link count. */ + __uid_t st_uid; /* User ID of the file's owner. */ + __gid_t st_gid; /* Group ID of the file's group.*/ + __dev_t st_rdev; /* Device number, if device. */ + __off64_t st_size; /* Size of file, in bytes. */ + __blksize_t st_blksize; /* Optimal block size for I/O. */ + + unsigned long __pad2; + __blkcnt64_t st_blocks; /* Number 512-byte blocks allocated. */ +#ifdef __USE_MISC + /* Nanosecond resolution timestamps are stored in a format + equivalent to 'struct timespec'. This is the type used + whenever possible but the Unix namespace rules do not allow the + identifier 'timespec' to appear in the header. + Therefore we have to handle the use of this header in strictly + standard-compliant sources special. */ + struct timespec st_atim; /* Time of last access. */ + struct timespec st_mtim; /* Time of last modification. */ + struct timespec st_ctim; /* Time of last status change. */ +#else + __time_t st_atime; /* Time of last access. */ + unsigned long int st_atimensec; /* Nscecs of last access. */ + __time_t st_mtime; /* Time of last modification. */ + unsigned long int st_mtimensec; /* Nsecs of last modification. */ + __time_t st_ctime; /* Time of last status change. */ + unsigned long int st_ctimensec; /* Nsecs of last status change. */ +#endif + unsigned long __unused4; + unsigned long __unused5; + }; +#endif + +/* Tell code we have these members. */ +#define _STATBUF_ST_BLKSIZE +#define _STATBUF_ST_RDEV +/* Nanosecond resolution time values are supported. */ +#define _STATBUF_ST_NSEC + +/* Encoding of the file mode. */ + +#define __S_IFMT 0170000 /* These bits determine file type. */ + +/* File types. */ +#define __S_IFDIR 0040000 /* Directory. */ +#define __S_IFCHR 0020000 /* Character device. */ +#define __S_IFBLK 0060000 /* Block device. */ +#define __S_IFREG 0100000 /* Regular file. */ +#define __S_IFIFO 0010000 /* FIFO. */ +#define __S_IFLNK 0120000 /* Symbolic link. */ +#define __S_IFSOCK 0140000 /* Socket. */ + +/* POSIX.1b objects. Note that these macros always evaluate to zero. But + they do it by enforcing the correct use of the macros. */ +#define __S_TYPEISMQ(buf) ((buf)->st_mode - (buf)->st_mode) +#define __S_TYPEISSEM(buf) ((buf)->st_mode - (buf)->st_mode) +#define __S_TYPEISSHM(buf) ((buf)->st_mode - (buf)->st_mode) + +/* Protection bits. */ + +#define __S_ISUID 04000 /* Set user ID on execution. */ +#define __S_ISGID 02000 /* Set group ID on execution. */ +#define __S_ISVTX 01000 /* Save swapped text after use (sticky). */ +#define __S_IREAD 0400 /* Read by owner. */ +#define __S_IWRITE 0200 /* Write by owner. */ +#define __S_IEXEC 0100 /* Execute by owner. */ + +#ifdef __USE_ATFILE +# define UTIME_NOW ((1l << 30) - 1l) +# define UTIME_OMIT ((1l << 30) - 2l) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/bits/syscalls.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/bits/syscalls.h new file mode 100644 index 00000000..cc6c41e1 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/bits/syscalls.h @@ -0,0 +1,85 @@ +#ifndef _BITS_SYSCALLS_H +#define _BITS_SYSCALLS_H +#ifndef _SYSCALL_H +# error "Never use directly; include instead." +#endif + +/* + Some of the sneaky macros in the code were taken from + glibc .../sysdeps/unix/sysv/linux/xtensa/sysdep.h +*/ + +#ifdef __ASSEMBLER__ + +/* The register layout upon entering the function is: + + return addr stack ptr arg0, arg1, arg2, arg3, arg4, arg5 + ----------- --------- ---------------------------------- + a0 a1 a2, a3, a4, a5, a6, a7 + + (Of course a function with say 3 arguments does not have entries for + arguments 4, 5, and 6.) + + Linux takes system-call arguments in registers. The ABI and Xtensa + software conventions require the system-call number in a2. We move any + argument that was in a2 to a7, and a7 to a8 if we have all 6 arguments. + Note that for improved efficiency, we do NOT shift all parameters down + one register to maintain the original order. + + syscall number arg0, arg1, arg2, arg3, arg4, arg5 + -------------- ---------------------------------- + a2 a6, a3, a4, a5, a8, a9 + + Upon return, a2 and a3 are clobbered; all other registers are preserved. */ + +#undef DO_CALL +#define DO_CALL(syscall_name, nargs) \ + DO_ARGS_##nargs \ + movi a2, SYS_ify (syscall_name); \ + syscall + +#define DO_ARGS_0 +#define DO_ARGS_1 mov a6, a2; +#define DO_ARGS_2 mov a6, a2; +#define DO_ARGS_3 mov a6, a2; +#define DO_ARGS_4 mov a6, a2; +#define DO_ARGS_5 mov a8, a6; mov a6, a2; +#define DO_ARGS_6 mov a9, a7; mov a8, a6; mov a6, a2; + +#else /* not __ASSEMBLER__ */ + +#include + +#define STR(s) #s +#define LD_ARG(n,ar) register int _a##n __asm__ (STR(a##n)) = (int) (ar) + +#define LD_ARGS_0() +#define LD_ARGS_1(a0) LD_ARG(6,a0) +#define LD_ARGS_2(a0,a1) LD_ARGS_1(a0); LD_ARG(3,a1) +#define LD_ARGS_3(a0,a1,a2) LD_ARGS_2(a0,a1); LD_ARG(4,a2) +#define LD_ARGS_4(a0,a1,a2,a3) LD_ARGS_3(a0,a1,a2); LD_ARG(5,a3) +#define LD_ARGS_5(a0,a1,a2,a3,a4) LD_ARGS_4(a0,a1,a2,a3); LD_ARG(8,a4) +#define LD_ARGS_6(a0,a1,a2,a3,a4,a5) LD_ARGS_5(a0,a1,a2,a3,a4); LD_ARG(9,a5) + +#define ASM_ARGS_0 "r"(_a2) +#define ASM_ARGS_1 ASM_ARGS_0, "r"(_a6) +#define ASM_ARGS_2 ASM_ARGS_1, "r"(_a3) +#define ASM_ARGS_3 ASM_ARGS_2, "r"(_a4) +#define ASM_ARGS_4 ASM_ARGS_3, "r"(_a5) +#define ASM_ARGS_5 ASM_ARGS_4, "r"(_a8) +#define ASM_ARGS_6 ASM_ARGS_5, "r"(_a9) + +/* Define a macro which expands into the inline wrapper code for a system + call. */ + +#define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \ + ({ LD_ARG(2, name); \ + LD_ARGS_##nr(args); \ + __asm__ __volatile__ ("syscall\n" \ + : "=a" (_a2) \ + : ASM_ARGS_##nr \ + : "memory"); \ + (long) _a2; }) + +#endif /* not __ASSEMBLER__ */ +#endif /* _BITS_SYSCALLS_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/bits/uClibc_arch_features.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/bits/uClibc_arch_features.h new file mode 100644 index 00000000..fef17658 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/bits/uClibc_arch_features.h @@ -0,0 +1,47 @@ +/* + * Track misc arch-specific features that aren't config options + */ + +#ifndef _BITS_UCLIBC_ARCH_FEATURES_H +#define _BITS_UCLIBC_ARCH_FEATURES_H + +/* instruction used when calling abort() to kill yourself */ +#define __UCLIBC_ABORT_INSTRUCTION__ "ill" + +/* can your target use syscall6() for mmap ? */ +#define __UCLIBC_MMAP_HAS_6_ARGS__ + +/* does your target use syscall4() for truncate64 ? (32bit arches only) */ +#define __UCLIBC_TRUNCATE64_HAS_4_ARGS__ + +/* does your target have a broken create_module() ? */ +#undef __UCLIBC_BROKEN_CREATE_MODULE__ + +/* does your target have to worry about older [gs]etrlimit() ? */ +#undef __UCLIBC_HANDLE_OLDER_RLIMIT__ + +/* does your target have an asm .set ? */ +#define __UCLIBC_HAVE_ASM_SET_DIRECTIVE__ + +/* define if target doesn't like .global */ +#undef __UCLIBC_ASM_GLOBAL_DIRECTIVE__ + +/* define if target supports .weak */ +#define __UCLIBC_HAVE_ASM_WEAK_DIRECTIVE__ + +/* define if target supports .weakext */ +#undef __UCLIBC_HAVE_ASM_WEAKEXT_DIRECTIVE__ + +/* needed probably only for ppc64 */ +#undef __UCLIBC_HAVE_ASM_GLOBAL_DOT_NAME__ + +/* define if target supports CFI pseudo ops */ +#undef __UCLIBC_HAVE_ASM_CFI_DIRECTIVES__ + +/* define if target supports IEEE signed zero floats */ +#define __UCLIBC_HAVE_SIGNED_ZERO__ + +/* only weird assemblers generally need this */ +#undef __UCLIBC_ASM_LINE_SEP__ + +#endif /* _BITS_UCLIBC_ARCH_FEATURES_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/bits/uClibc_page.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/bits/uClibc_page.h new file mode 100644 index 00000000..74a9f60b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/bits/uClibc_page.h @@ -0,0 +1,31 @@ +/* Copyright (C) 2004 Erik Andersen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * The GNU C Library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the GNU C Library; if not, write to the Free + * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307 USA. + */ + +/* Supply an architecture specific value for PAGE_SIZE and friends. */ + +#ifndef _UCLIBC_PAGE_H +#define _UCLIBC_PAGE_H + +#include + +/* PAGE_SHIFT determines the page size -- in this case 4096 */ +#define PAGE_SHIFT XCHAL_MMU_MIN_PTE_PAGE_SIZE +#define PAGE_SIZE (1UL << PAGE_SHIFT) +#define PAGE_MASK (~(PAGE_SIZE-1)) + +#endif /* _UCLIBC_PAGE_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/bits/wordsize.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/bits/wordsize.h new file mode 100644 index 00000000..ba643b60 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/bits/wordsize.h @@ -0,0 +1,19 @@ +/* Copyright (C) 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define __WORDSIZE 32 diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/bits/xtensa-config.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/bits/xtensa-config.h new file mode 100644 index 00000000..34cf28c0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/bits/xtensa-config.h @@ -0,0 +1,53 @@ +/* Xtensa configuration settings. + Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007 + Free Software Foundation, Inc. + Contributed by Bob Wilson (bwilson@tensilica.com) at Tensilica. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street - Fifth Floor, + Boston, MA 02110-1301, USA. */ + +#ifndef XTENSA_CONFIG_H +#define XTENSA_CONFIG_H + +/* The macros defined here match those with the same names in the Xtensa + compile-time HAL (Hardware Abstraction Layer). Please refer to the + Xtensa System Software Reference Manual for documentation of these + macros. */ + +/* The following macros reflect the default expectations for Xtensa + processor configurations that can run glibc. If you want to try + building glibc for an Xtensa configuration that is missing these + options, you will at least need to change the values of these + macros. */ + +#undef XCHAL_HAVE_NSA +#define XCHAL_HAVE_NSA 1 + +#undef XCHAL_HAVE_LOOPS +#define XCHAL_HAVE_LOOPS 1 + +/* Assume the maximum number of AR registers. This currently only affects + the __window_spill function, and it is always safe to flush extra. */ + +#undef XCHAL_NUM_AREGS +#define XCHAL_NUM_AREGS 64 + +/* Set a default page size. This is currently needed when bootstrapping + the runtime linker. See comments in dl-machine.h where this is used. */ + +#undef XCHAL_MMU_MIN_PTE_PAGE_SIZE +#define XCHAL_MMU_MIN_PTE_PAGE_SIZE 12 + +#endif /* !XTENSA_CONFIG_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/brk.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/brk.c new file mode 100644 index 00000000..8e98c312 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/brk.c @@ -0,0 +1,42 @@ +/* brk system call for Linux/Xtensa. + Copyright (C) 1996, 1997, 2005, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street - Fifth Floor, + Boston, MA 02110-1301, USA. */ + +#include +#include +#include + +/* This must be initialized data because commons can't have aliases. */ +void *__curbrk attribute_hidden = 0; + +int +brk (void *addr) +{ + void *newbrk; + + __curbrk = newbrk = (void *) INLINE_SYSCALL (brk, 1, addr); + + if (newbrk < addr) + { + __set_errno (ENOMEM); + return -1; + } + + return 0; +} +libc_hidden_def(brk) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/bsd-_setjmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/bsd-_setjmp.S new file mode 100644 index 00000000..4e6a2da5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/bsd-_setjmp.S @@ -0,0 +1 @@ +/* _setjmp is in setjmp.S */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/bsd-setjmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/bsd-setjmp.S new file mode 100644 index 00000000..1da848d2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/bsd-setjmp.S @@ -0,0 +1 @@ +/* setjmp is in setjmp.S */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/clone.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/clone.S new file mode 100644 index 00000000..31921ea4 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/clone.S @@ -0,0 +1,103 @@ +/* Copyright (C) 2001, 2005, 2007 Free Software Foundation, Inc. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street - Fifth Floor, + Boston, MA 02110-1301, USA. */ + +/* clone is even more special than fork as it mucks with stacks + and invokes a function in the right context after it's all over. */ + +#include "sysdep.h" +#include +#define _ERRNO_H 1 +#include + +/* int clone (a2 = int (*fn)(void *arg), + a3 = void *child_stack, + a4 = int flags, + a5 = void *arg, + a6 = pid_t *ptid, + a7 = struct user_desc *tls, + 16(sp) = pid_t *ctid) */ + + .text +ENTRY (__clone) + + /* Sanity check arguments. */ + beqz a2, .Leinval /* no NULL function pointers */ + beqz a3, .Leinval /* no NULL stack pointers */ + + /* a2 and a3 are candidates for destruction by system-call return + parameters. We don't need the stack pointer after the system + call. We trust that the kernel will preserve a7, a9, and a6. */ + + mov a9, a5 /* save function argument */ + mov a5, a7 + mov a7, a2 /* save function pointer */ + mov a8, a6 /* use a8 as a temp */ + mov a6, a4 + mov a4, a8 + l32i a8, a1, 16 /* child_tid */ + movi a2, SYS_ify (clone) + + /* syscall (a2 = NR_clone, + a6 = clone_flags, + a3 = usp, + a4 = parent_tid, + a5 = child_tls, + a8 = child_tid) */ + syscall + bltz a2, SYSCALL_ERROR_LABEL + beqz a2, .Lthread_start + + /* Fall through for parent. */ +.Lpseudo_end: + retw + +.Leinval: + movi a2, -EINVAL + j SYSCALL_ERROR_LABEL + +.Lthread_start: + /* Start child thread. */ + movi a0, 0 /* terminate the stack frame */ + +#ifdef RESET_PID + /* Check and see if we need to reset the PID. */ + bbsi.l a6, 16, 1f /* CLONE_THREAD = 0x00010000 */ + movi a2, -1 + bbsi.l a6, 8, 2f /* CLONE_VM = 0x00000100 */ + movi a2, SYS_ify (getpid) + syscall +2: rur a3, THREADPTR + movi a4, PID_OFFSET + add a4, a4, a3 + s32i a2, a4, 0 + movi a4, TID_OFFSET + add a4, a4, a3 + s32i a2, a3, 0 +1: +#endif /* RESET_PID */ + + mov a6, a9 /* load up the 'arg' parameter */ + callx4 a7 /* call the user's function */ + + /* Call _exit. Note that any return parameter from the user's + function in a6 is seen as inputs to _exit. */ + movi a2, JUMPTARGET(_exit) + callx4 a2 + +PSEUDO_END (__clone) + +weak_alias (__clone, clone) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/crt1.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/crt1.S new file mode 100644 index 00000000..63fbadc1 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/crt1.S @@ -0,0 +1,119 @@ +/* Startup code compliant to the ELF Xtensa ABI. + Copyright (C) 2001, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file with other + programs, and to distribute those programs without any restriction + coming from the use of this file. (The GNU Lesser General Public + License restrictions do apply in other respects; for example, they + cover modification of the file, and distribution when not linked + into another program.) + + Note that people who make modified versions of this file are not + obligated to grant this special exception for their modified + versions; it is their choice whether to do so. The GNU Lesser + General Public License gives permission to release a modified + version without this exception; this exception also makes it + possible to release a modified version which carries forward this + exception. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street - Fifth Floor, + Boston, MA 02110-1301, USA. */ + +#include + +#ifndef __UCLIBC_CTOR_DTOR__ + .weak _init + .weak _fini +#endif + +/* This is the canonical entry point, usually the first thing in the text + segment. When the entry point runs, most register values are unspecified, + except for: + + a2 Contains a function pointer to be registered with `atexit'. + This is how the dynamic linker arranges to have DT_FINI + functions called for shared libraries that have been loaded + before this code runs. + + a1 The stack (i.e., a1+16) contains the arguments and environment: + a1+0 argc + a1+4 argv[0] + ... + a1+(4*argc) NULL + a1+(4*(argc+1)) envp[0] + ... + NULL + + Setup parameters accordingly (for a call4). See function prototype + from sysdeps/generic/libc-start.c + + a6 = *main + a7 = argc + a8 = ubp_av + a9 = *init + a10 = *fini + a11 = *rtld_fini + [sp+0] = stack_end + */ + + .text + .align 4 + .literal_position + .global _start + .type _start, @function +_start: + /* Clear a0 to obviously mark the outermost frame. */ + movi a0, 0 + + /* Load up the user's main function. */ + movi a6, main + + /* Extract the arguments as encoded on the stack and set up + the arguments for `main': argc, argv. envp will be determined + later in __uClibc_main. */ + l32i a7, a1, 0 /* Load the argument count. */ + addi a8, a1, 4 /* Compute the argv pointer. */ + + /* Push address of our own entry points to .fini and .init. */ + movi a9, _init + movi a10, _fini + + /* Setup the shared library termination function. */ + mov a11, a2 + + /* Provide the highest stack address to the user code (for stacks + which grow downwards). Note that we destroy the stack version + of argc here. */ + s32i a1, a1, 0 + + /* Call the user's main function, and exit with its value. + But let the libc call main. */ + movi a4, __uClibc_main + callx4 a4 + + /* Crash if somehow `exit' does return. */ + ill + + /* Define a symbol for the first piece of initialized data. */ + .data + .align 4 + .global __data_start +__data_start: + .long 0 + .weak data_start + data_start = __data_start diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/crti.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/crti.S new file mode 100644 index 00000000..a01c02c9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/crti.S @@ -0,0 +1,16 @@ +/* glibc's sysdeps/xtensa/elf/initfini.c used for reference [PROLOG] */ + + .section .init + .align 4 + .global _init + .type _init, @function +_init: + entry sp, 48 + + + .section .fini + .align 4 + .global _fini + .type _fini, @function +_fini: + entry sp, 48 diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/crtn.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/crtn.S new file mode 100644 index 00000000..ab1a489c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/crtn.S @@ -0,0 +1,8 @@ +/* glibc's sysdeps/xtensa/elf/initfini.c used for reference [EPILOG] */ + + .section .init + retw + + + .section .fini + retw diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/fork.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/fork.c new file mode 100644 index 00000000..f8fae9b5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/fork.c @@ -0,0 +1,25 @@ +/* vi: set sw=4 ts=4: */ +/* + * fork() for Xtensa uClibc + * + * Copyright (C) 2007 Tensilica Inc. + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#define _SIGNAL_H +#include + +/* Xtensa doesn't provide a 'fork' system call, so we use 'clone'. */ + +extern __typeof(fork) __libc_fork; + +libc_hidden_proto(fork) +pid_t __libc_fork(void) +{ + return (pid_t) INLINE_SYSCALL(clone, 2, SIGCHLD, 0); +} +weak_alias(__libc_fork, fork) +libc_hidden_weak(fork) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/mmap.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/mmap.S new file mode 100644 index 00000000..c991e7d2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/mmap.S @@ -0,0 +1,57 @@ +/* Copyright (C) 2005, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street - Fifth Floor, + Boston, MA 02110-1301, USA. */ + +#include "sysdep.h" +#include + +#define PAGE_SHIFT 12 + +/* __ptr_t __mmap (a2 = __ptr_t addr, + a3 = size_t len, + a4 = int prot, + a5 = int flags, + a6 = int fd, + a7 = off_t offset) */ + +ENTRY (__mmap) + + /* We only support mmap2 in the kernel, so shift offset by + page - size. */ + mov a8, a6 + mov a6, a2 + movi a2, SYS_ify (mmap2) + srli a9, a7, PAGE_SHIFT + + /* syscall (a2 = NR_mmap2, + a6 = arg0, + a3 = arg1, + a4 = arg2, + a5 = arg3, + a8 = arg4, + a9 = arg5) */ + + syscall + bltz a2, SYSCALL_ERROR_LABEL + +.Lpseudo_end: + retw + +PSEUDO_END (__mmap) + +weak_alias (__mmap, mmap) +libc_hidden_weak (mmap) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/posix_fadvise.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/posix_fadvise.c new file mode 100644 index 00000000..0fe13a1e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/posix_fadvise.c @@ -0,0 +1,29 @@ +/* vi: set sw=4 ts=4: */ +/* + * posix_fadvise() for Xtensa uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * Copyright (C) 2007 Tensilica Inc. + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +int posix_fadvise (int fd, off_t offset, off_t len, int advice) +{ +#ifdef __NR_fadvise64_64 + INTERNAL_SYSCALL_DECL (err); + int ret = INTERNAL_SYSCALL (fadvise64_64, err, 6, fd, advice, + __LONG_LONG_PAIR ((long) (offset >> 31), + (long) offset), + __LONG_LONG_PAIR ((long) (len >> 31), + (long) len)); + if (!INTERNAL_SYSCALL_ERROR_P (ret, err)) + return 0; + return INTERNAL_SYSCALL_ERRNO (ret, err); +#else + return ENOSYS; +#endif +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/posix_fadvise64.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/posix_fadvise64.c new file mode 100644 index 00000000..1fdeeba7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/posix_fadvise64.c @@ -0,0 +1,39 @@ +/* vi: set sw=4 ts=4: */ +/* + * posix_fadvise64() for Xtensa uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * Copyright (C) 2007 Tensilica Inc. + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __UCLIBC_HAS_LFS__ + +int posix_fadvise64 (int fd, __off64_t offset, __off64_t len, int advice) +{ +#ifdef __NR_fadvise64_64 + INTERNAL_SYSCALL_DECL (err); + int ret = INTERNAL_SYSCALL (fadvise64_64, err, 6, fd, advice, + __LONG_LONG_PAIR ((long) (offset >> 32), + (long) offset), + __LONG_LONG_PAIR ((long) (len >> 32), + (long) len)); + if (!INTERNAL_SYSCALL_ERROR_P (ret, err)) + return 0; + return INTERNAL_SYSCALL_ERRNO (ret, err); +#else + return ENOSYS; +#endif +} + +#endif /* __UCLIBC_HAS_LFS__ */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/pread_write.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/pread_write.c new file mode 100644 index 00000000..71ba22bb --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/pread_write.c @@ -0,0 +1,189 @@ +/* vi: set sw=4 ts=4: */ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ +/* + * Based in part on the files + * ./sysdeps/unix/sysv/linux/pwrite.c, + * ./sysdeps/unix/sysv/linux/pread.c, + * sysdeps/posix/pread.c + * sysdeps/posix/pwrite.c + * from GNU libc 2.2.5, but reworked considerably... + */ + +#include +#include +#include +#include + +extern __typeof(pread) __libc_pread; +extern __typeof(pwrite) __libc_pwrite; +#ifdef __UCLIBC_HAS_LFS__ +extern __typeof(pread64) __libc_pread64; +extern __typeof(pwrite64) __libc_pwrite64; +#endif + +#include + +#ifdef __NR_pread + +# define __NR___syscall_pread __NR_pread +/* On Xtensa, 64-bit values are aligned in even/odd register pairs. */ +static __inline__ _syscall6(ssize_t, __syscall_pread, int, fd, void *, buf, + size_t, count, int, pad, off_t, offset_hi, off_t, offset_lo) + +ssize_t __libc_pread(int fd, void *buf, size_t count, off_t offset) +{ + return __syscall_pread(fd, buf, count, 0, __LONG_LONG_PAIR(offset >> 31, offset)); +} +weak_alias(__libc_pread,pread) + +# ifdef __UCLIBC_HAS_LFS__ +ssize_t __libc_pread64(int fd, void *buf, size_t count, off64_t offset) +{ + uint32_t low = offset & 0xffffffff; + uint32_t high = offset >> 32; + return __syscall_pread(fd, buf, count, 0, __LONG_LONG_PAIR(high, low)); +} +weak_alias(__libc_pread64,pread64) +# endif /* __UCLIBC_HAS_LFS__ */ + +#endif /* __NR_pread */ + +#ifdef __NR_pwrite + +# define __NR___syscall_pwrite __NR_pwrite +/* On Xtensa, 64-bit values are aligned in even/odd register pairs. */ +static __inline__ _syscall6(ssize_t, __syscall_pwrite, int, fd, const void *, buf, + size_t, count, int, pad, off_t, offset_hi, off_t, offset_lo) + +ssize_t __libc_pwrite(int fd, const void *buf, size_t count, off_t offset) +{ + return __syscall_pwrite(fd, buf, count, 0, __LONG_LONG_PAIR(offset >> 31, offset)); +} +weak_alias(__libc_pwrite,pwrite) + +# ifdef __UCLIBC_HAS_LFS__ +ssize_t __libc_pwrite64(int fd, const void *buf, size_t count, off64_t offset) +{ + uint32_t low = offset & 0xffffffff; + uint32_t high = offset >> 32; + return __syscall_pwrite(fd, buf, count, 0, __LONG_LONG_PAIR(high, low)); +} +weak_alias(__libc_pwrite64,pwrite64) +# endif /* __UCLIBC_HAS_LFS__ */ +#endif /* __NR_pwrite */ + +#if ! defined __NR_pread || ! defined __NR_pwrite + +static ssize_t __fake_pread_write(int fd, void *buf, + size_t count, off_t offset, int do_pwrite) +{ + int save_errno; + ssize_t result; + off_t old_offset; + + /* Since we must not change the file pointer preserve the + * value so that we can restore it later. */ + if ((old_offset=lseek(fd, 0, SEEK_CUR)) == (off_t) -1) + return -1; + + /* Set to wanted position. */ + if (lseek(fd, offset, SEEK_SET) == (off_t) -1) + return -1; + + if (do_pwrite == 1) { + /* Write the data. */ + result = write(fd, buf, count); + } else { + /* Read the data. */ + result = read(fd, buf, count); + } + + /* Now we have to restore the position. If this fails we + * have to return this as an error. */ + save_errno = errno; + if (lseek(fd, old_offset, SEEK_SET) == (off_t) -1) + { + if (result == -1) + __set_errno(save_errno); + return -1; + } + __set_errno(save_errno); + return(result); +} + +# ifdef __UCLIBC_HAS_LFS__ + +static ssize_t __fake_pread_write64(int fd, void *buf, + size_t count, off64_t offset, int do_pwrite) +{ + int save_errno; + ssize_t result; + off64_t old_offset; + + /* Since we must not change the file pointer preserve the + * value so that we can restore it later. */ + if ((old_offset=lseek64(fd, 0, SEEK_CUR)) == (off64_t) -1) + return -1; + + /* Set to wanted position. */ + if (lseek64(fd, offset, SEEK_SET) == (off64_t) -1) + return -1; + + if (do_pwrite == 1) { + /* Write the data. */ + result = write(fd, buf, count); + } else { + /* Read the data. */ + result = read(fd, buf, count); + } + + /* Now we have to restore the position. */ + save_errno = errno; + if (lseek64(fd, old_offset, SEEK_SET) == (off64_t) -1) { + if (result == -1) + __set_errno (save_errno); + return -1; + } + __set_errno (save_errno); + return result; +} +# endif /* __UCLIBC_HAS_LFS__ */ +#endif /* ! defined __NR_pread || ! defined __NR_pwrite */ + +#ifndef __NR_pread +ssize_t __libc_pread(int fd, void *buf, size_t count, off_t offset) +{ + return __fake_pread_write(fd, buf, count, offset, 0); +} +weak_alias(__libc_pread,pread) + +# ifdef __UCLIBC_HAS_LFS__ +ssize_t __libc_pread64(int fd, void *buf, size_t count, off64_t offset) +{ + return __fake_pread_write64(fd, buf, count, offset, 0); +} +weak_alias(__libc_pread64,pread64) +# endif /* __UCLIBC_HAS_LFS__ */ +#endif /* ! __NR_pread */ + +#ifndef __NR_pwrite +ssize_t __libc_pwrite(int fd, const void *buf, size_t count, off_t offset) +{ + /* we won't actually be modifying the buffer, + *just cast it to get rid of warnings */ + return __fake_pread_write(fd, (void*)buf, count, offset, 1); +} +weak_alias(__libc_pwrite,pwrite) + +# ifdef __UCLIBC_HAS_LFS__ +ssize_t __libc_pwrite64(int fd, const void *buf, size_t count, off64_t offset) +{ + return __fake_pread_write64(fd, (void*)buf, count, offset, 1); +} +weak_alias(__libc_pwrite64,pwrite64) +# endif /* __UCLIBC_HAS_LFS__ */ +#endif /* ! __NR_pwrite */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/setjmp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/setjmp.S new file mode 100644 index 00000000..cd74caf6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/setjmp.S @@ -0,0 +1,131 @@ +/* setjmp for Xtensa Processors. + Copyright (C) 2001, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street - Fifth Floor, + Boston, MA 02110-1301, USA. */ + +/* This implementation relies heavily on the Xtensa register window + mechanism. Setjmp flushes all the windows except its own to the + stack and then copies registers from the save areas on the stack + into the jmp_buf structure, along with the return address of the call + to setjmp. Longjmp invalidates all the windows except its own, and + then sets things up so that it will return to the right place, + using a window underflow to automatically restore the registers. + + Note that it would probably be sufficient to only copy the + registers from setjmp's caller into jmp_buf. However, we also copy + the save area located at the stack pointer of setjmp's caller. + This save area will typically remain intact until the longjmp call. + The one exception is when there is an intervening alloca in + setjmp's caller. This is certainly an unusual situation and is + likely to cause problems in any case (the storage allocated on the + stack cannot be safely accessed following the longjmp). As bad as + it is, on most systems this situation would not necessarily lead to + a catastrophic failure. If we did not preserve the extra save area + on Xtensa, however, it would. When setjmp's caller returns after a + longjmp, there will be a window underflow; an invalid return + address or stack pointer in the save area will almost certainly + lead to a crash. Keeping a copy of the extra save area in the + jmp_buf avoids this with only a small additional cost. If setjmp + and longjmp are ever time-critical, this could be removed. */ + +#include "sysdep.h" + +/* int setjmp (a2 = jmp_buf env) */ + +ENTRY (_setjmp) + movi a3, 0 + j 1f +END (_setjmp) +libc_hidden_def (_setjmp) + +ENTRY (setjmp) + movi a3, 1 + j 1f +END (setjmp) + +/* int __sigsetjmp (a2 = jmp_buf env, + a3 = int savemask) */ + +ENTRY (__sigsetjmp) +1: + /* Flush registers. */ + movi a4, __window_spill + callx4 a4 + + /* Preserve the second argument (savemask) in a15. The selection + of a15 is arbitrary, except it's otherwise unused. There is no + risk of triggering a window overflow since we just returned + from __window_spill(). */ + mov a15, a3 + + /* Copy the register save area at (sp - 16). */ + addi a5, a1, -16 + l32i a3, a5, 0 + l32i a4, a5, 4 + s32i a3, a2, 0 + s32i a4, a2, 4 + l32i a3, a5, 8 + l32i a4, a5, 12 + s32i a3, a2, 8 + s32i a4, a2, 12 + + /* Copy 0-8 words from the register overflow area. */ + extui a3, a0, 30, 2 + blti a3, 2, .Lendsj + l32i a7, a1, 4 + slli a4, a3, 4 + sub a5, a7, a4 + addi a6, a2, 16 + addi a7, a7, -16 /* a7 = end of register overflow area */ +.Lsjloop: + l32i a3, a5, 0 + l32i a4, a5, 4 + s32i a3, a6, 0 + s32i a4, a6, 4 + l32i a3, a5, 8 + l32i a4, a5, 12 + s32i a3, a6, 8 + s32i a4, a6, 12 + addi a5, a5, 16 + addi a6, a6, 16 + blt a5, a7, .Lsjloop +.Lendsj: + + /* Copy the register save area at sp. */ + l32i a3, a1, 0 + l32i a4, a1, 4 + s32i a3, a2, 48 + s32i a4, a2, 52 + l32i a3, a1, 8 + l32i a4, a1, 12 + s32i a3, a2, 56 + s32i a4, a2, 60 + + /* Save the return address, including the window size bits. */ + s32i a0, a2, 64 + + /* a2 still addresses jmp_buf. a15 contains savemask. */ + mov a6, a2 + mov a7, a15 + movi a3, __sigjmp_save + callx4 a3 + mov a2, a6 + retw +END(__sigsetjmp) + +weak_extern(_setjmp) +weak_extern(setjmp) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/sigaction.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/sigaction.c new file mode 100644 index 00000000..302d1330 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/sigaction.c @@ -0,0 +1,39 @@ +/* vi: set sw=4 ts=4: */ +/* + * sigaction() for Xtensa uClibc + * + * Copyright (C) 2007, 2008 Tensilica Inc. + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include +#include + +#define SA_RESTORER 0x04000000 + +extern void __default_sa_restorer(void); + +int __libc_sigaction(int sig, const struct sigaction *act, + struct sigaction *oact) +{ + struct sigaction kact; + + if (act && !(act->sa_flags & SA_RESTORER)) { + memcpy(&kact, act, sizeof(kact)); + kact.sa_restorer = __default_sa_restorer; + kact.sa_flags |= SA_RESTORER; + act = &kact; + } + /* NB: kernel (as of 2.6.25) will return EINVAL + * if sizeof(act->sa_mask) does not match kernel's sizeof(sigset_t) */ + return __syscall_rt_sigaction(sig, act, oact, sizeof(act->sa_mask)); +} + +#ifndef LIBC_SIGACTION +weak_alias(__libc_sigaction, sigaction) +libc_hidden_weak(sigaction) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/sigrestorer.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/sigrestorer.S new file mode 100644 index 00000000..474a8931 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/sigrestorer.S @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2008 Tensilica Inc. + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +#if __NR_rt_sigreturn > 255 +# error value of __NR_rt_sigreturn is too big! +#endif + + .text + .align 4 + .global __default_sa_restorer + .type __default_sa_restorer, @function +__default_sa_restorer: + movi a2, __NR_rt_sigreturn + syscall diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/sys/procfs.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/sys/procfs.h new file mode 100644 index 00000000..f6f8752b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/sys/procfs.h @@ -0,0 +1,121 @@ +/* Copyright (C) 1996, 1997, 1999, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street - Fifth Floor, + Boston, MA 02110-1301, USA. */ + +#ifndef _SYS_PROCFS_H +#define _SYS_PROCFS_H 1 + +/* This is somewhat modelled after the file of the same name on SVR4 + systems. It provides a definition of the core file format for ELF + used on Linux. It doesn't have anything to do with the /proc file + system, even though Linux has one. + + Anyway, the whole purpose of this file is for GDB and GDB only. + Don't read too much into it. Don't use it for anything other than + GDB unless you know what you are doing. */ + +#include +#include +#include +#include + +__BEGIN_DECLS + +/* Type for a general-purpose register. */ +typedef unsigned long elf_greg_t; + +#define ELF_NGREG 128 +typedef elf_greg_t elf_gregset_t[ELF_NGREG]; + +/* Register set for the floating-point registers. */ +#define ELF_NFPREG 18 +typedef unsigned long elf_fpreg_t; +typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; + +/* Signal info. */ +struct elf_siginfo + { + int si_signo; /* Signal number. */ + int si_code; /* Extra code. */ + int si_errno; /* Errno. */ + }; + +/* Definitions to generate Intel SVR4-like core files. These mostly + have the same names as the SVR4 types with "elf_" tacked on the + front to prevent clashes with Linux definitions, and the typedef + forms have been avoided. This is mostly like the SVR4 structure, + but more Linuxy, with things that Linux does not support and which + GDB doesn't really use excluded. */ + +struct elf_prstatus + { + struct elf_siginfo pr_info; /* Info associated with signal. */ + short int pr_cursig; /* Current signal. */ + unsigned long int pr_sigpend; /* Set of pending signals. */ + unsigned long int pr_sighold; /* Set of held signals. */ + __pid_t pr_pid; + __pid_t pr_ppid; + __pid_t pr_pgrp; + __pid_t pr_sid; + struct timeval pr_utime; /* User time. */ + struct timeval pr_stime; /* System time. */ + struct timeval pr_cutime; /* Cumulative user time. */ + struct timeval pr_cstime; /* Cumulative system time. */ + elf_gregset_t pr_reg; /* GP registers. */ + int pr_fpvalid; /* True if math copro being used. */ + }; + + +#define ELF_PRARGSZ (80) /* Number of chars for args. */ + +struct elf_prpsinfo + { + char pr_state; /* Numeric process state. */ + char pr_sname; /* Char for pr_state. */ + char pr_zomb; /* Zombie. */ + char pr_nice; /* Nice val. */ + unsigned long int pr_flag; /* Flags. */ + unsigned short int pr_uid; + unsigned short int pr_gid; + int pr_pid, pr_ppid, pr_pgrp, pr_sid; + /* Lots missing */ + char pr_fname[16]; /* Filename of executable. */ + char pr_psargs[ELF_PRARGSZ]; /* Initial part of arg list. */ + }; + +/* The rest of this file provides the types for emulation of the + Solaris interfaces that should be implemented by + users of libthread_db. */ + +/* Addresses. */ +typedef void *psaddr_t; + +/* Register sets. Linux has different names. */ +typedef elf_gregset_t prgregset_t; +typedef elf_fpregset_t prfpregset_t; + +/* We don't have any differences between processes and threads, + therefore have only one PID type. */ +typedef __pid_t lwpid_t; + +/* Process status and info. In the end we do provide typedefs for them. */ +typedef struct elf_prstatus prstatus_t; +typedef struct elf_prpsinfo prpsinfo_t; + +__END_DECLS + +#endif /* sys/procfs.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/sys/ptrace.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/sys/ptrace.h new file mode 100644 index 00000000..7aad929b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/sys/ptrace.h @@ -0,0 +1,156 @@ +/* `ptrace' debugger support interface. Linux version. + Copyright (C) 1996, 1997, 1998, 1999, 2000, 2007 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street - Fifth Floor, + Boston, MA 02110-1301, USA. */ + +#ifndef _SYS_PTRACE_H +#define _SYS_PTRACE_H 1 + +#include + +/* Kludge away careless namespace pollution from the kernel. */ + +#undef PTRACE_GETREGS +#undef PTRACE_SETREGS +#undef PTRACE_GETFPREGS +#undef PTRACE_SETFPREGS +#undef PTRACE_GETFPREGSIZE + + +__BEGIN_DECLS + +/* Type of the REQUEST argument to `ptrace.' */ +enum __ptrace_request +{ + /* Indicate that the process making this request should be traced. + All signals received by this process can be intercepted by its + parent, and its parent can use the other `ptrace' requests. */ + PTRACE_TRACEME = 0, +#define PT_TRACE_ME PTRACE_TRACEME + + /* Return the word in the process's text space at address ADDR. */ + PTRACE_PEEKTEXT = 1, +#define PT_READ_I PTRACE_PEEKTEXT + + /* Return the word in the process's data space at address ADDR. */ + PTRACE_PEEKDATA = 2, +#define PT_READ_D PTRACE_PEEKDATA + + /* Return the word in the process's user area at offset ADDR. */ + PTRACE_PEEKUSER = 3, +#define PT_READ_U PTRACE_PEEKUSER + + /* Write the word DATA into the process's text space at address ADDR. */ + PTRACE_POKETEXT = 4, +#define PT_WRITE_I PTRACE_POKETEXT + + /* Write the word DATA into the process's data space at address ADDR. */ + PTRACE_POKEDATA = 5, +#define PT_WRITE_D PTRACE_POKEDATA + + /* Write the word DATA into the process's user area at offset ADDR. */ + PTRACE_POKEUSER = 6, +#define PT_WRITE_U PTRACE_POKEUSER + + /* Continue the process. */ + PTRACE_CONT = 7, +#define PT_CONTINUE PTRACE_CONT + + /* Kill the process. */ + PTRACE_KILL = 8, +#define PT_KILL PTRACE_KILL + + /* Single step the process. + This is not supported on all machines. */ + PTRACE_SINGLESTEP = 9, +#define PT_STEP PTRACE_SINGLESTEP + + /* Get all general purpose registers used by a processes. + This is not supported on all machines. */ + PTRACE_GETREGS = 12, +#define PT_GETREGS PTRACE_GETREGS + + /* Set all general purpose registers used by a processes. + This is not supported on all machines. */ + PTRACE_SETREGS = 13, +#define PT_SETREGS PTRACE_SETREGS + + /* Get all floating point registers used by a processes. + This is not supported on all machines. */ + PTRACE_GETFPREGS = 14, +#define PT_GETFPREGS PTRACE_GETFPREGS + + /* Set all floating point registers used by a processes. + This is not supported on all machines. */ + PTRACE_SETFPREGS = 15, +#define PT_SETFPREGS PTRACE_SETFPREGS + + /* Attach to a process that is already running. */ + PTRACE_ATTACH = 16, +#define PT_ATTACH PTRACE_ATTACH + + /* Detach from a process attached to with PTRACE_ATTACH. */ + PTRACE_DETACH = 17, +#define PT_DETACH PTRACE_DETACH + + /* Get size required for the buffer holding the floating point registers. + This is not supported on all machines. */ + PTRACE_GETFPREGSIZE = 18, +#define PT_GETFPREGSIZE PTRACE_GETFPREGSIZE + + /* Continue and stop at the next (return from) syscall. */ + PTRACE_SYSCALL = 24 +#define PT_SYSCALL PTRACE_SYSCALL +}; + +/* Options set using PTRACE_SETOPTIONS. */ +enum __ptrace_setoptions { + PTRACE_O_TRACESYSGOOD = 0x00000001, + PTRACE_O_TRACEFORK = 0x00000002, + PTRACE_O_TRACEVFORK = 0x00000004, + PTRACE_O_TRACECLONE = 0x00000008, + PTRACE_O_TRACEEXEC = 0x00000010, + PTRACE_O_TRACEVFORKDONE = 0x00000020, + PTRACE_O_TRACEEXIT = 0x00000040, + PTRACE_O_MASK = 0x0000007f +}; + +/* Wait extended result codes for the above trace options. */ +enum __ptrace_eventcodes { + PTRACE_EVENT_FORK = 1, + PTRACE_EVENT_VFORK = 2, + PTRACE_EVENT_CLONE = 3, + PTRACE_EVENT_EXEC = 4, + PTRACE_EVENT_VFORK_DONE = 5, + PTRACE_EVENT_EXIT = 6 +}; + +/* Perform process tracing functions. REQUEST is one of the values + above, and determines the action to be taken. + For all requests except PTRACE_TRACEME, PID specifies the process to be + traced. + + PID and the other arguments described above for the various requests should + appear (those that are used for the particular request) as: + pid_t PID, void *ADDR, int DATA, void *ADDR2 + after REQUEST. */ +extern long int ptrace (enum __ptrace_request __request, ...) __THROW; + +__END_DECLS + +#endif /* _SYS_PTRACE_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/sys/ucontext.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/sys/ucontext.h new file mode 100644 index 00000000..4c37201e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/sys/ucontext.h @@ -0,0 +1,49 @@ +/* Copyright (C) 2001, 2006, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street - Fifth Floor, + Boston, MA 02110-1301, USA. */ + +#ifndef _SYS_UCONTEXT_H +#define _SYS_UCONTEXT_H 1 + +#include +#include + +/* We need the signal context definitions even if they are not used + included in . */ +#include + +/* Revise this structure when we add support for coprocessors. */ + +/* Structure to describe FPU registers. */ +typedef struct fpregset +{ + int dummy; +} fpregset_t; + +typedef struct sigcontext mcontext_t; + +/* Userlevel context. */ +typedef struct ucontext + { + unsigned long int uc_flags; + struct ucontext *uc_link; + stack_t uc_stack; + mcontext_t uc_mcontext; + __sigset_t uc_sigmask; + } ucontext_t; + +#endif /* sys/ucontext.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/syscall.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/syscall.S new file mode 100644 index 00000000..955e889c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/syscall.S @@ -0,0 +1,42 @@ +/* Copyright (C) 2005, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street - Fifth Floor, + Boston, MA 02110-1301, USA. */ + +#include "sysdep.h" + +/* The register layout upon entering the function is: + + arguments syscall number arg0, arg1, arg2, arg3, arg4, arg5 + --------- -------------- ---------------------------------- + function a2 a3, a4, a5, a6, a7, (sp) + syscall a2 a6, a3, a4, a5, a8, a9 + */ + +ENTRY (syscall) + l32i a9, a1, 16 /* load extra argument from stack */ + mov a8, a7 + mov a7, a3 /* preserve a3 in a7 */ + mov a3, a4 + mov a4, a5 + mov a5, a6 + mov a6, a7 + syscall + movi a4, -4095 + bgeu a2, a4, SYSCALL_ERROR_LABEL +.Lpseudo_end: + retw +PSEUDO_END (syscall) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/sysdep.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/sysdep.h new file mode 100644 index 00000000..4c32c2ca --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/sysdep.h @@ -0,0 +1,160 @@ +/* Assembler macros for Xtensa processors. + Copyright (C) 2001, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street - Fifth Floor, + Boston, MA 02110-1301, USA. */ + +#ifdef __ASSEMBLER__ + +#define ALIGNARG(log2) 1 << log2 +#define ASM_TYPE_DIRECTIVE(name, typearg) .type name, typearg +#define ASM_SIZE_DIRECTIVE(name) .size name, . - name + +#ifdef __STDC__ +#define C_LABEL(name) name : +#else +#define C_LABEL(name) name/**/: +#endif + +#define ENTRY(name) \ + ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(name); \ + ASM_TYPE_DIRECTIVE (C_SYMBOL_NAME(name), @function); \ + .align ALIGNARG(2); \ + LITERAL_POSITION; \ + C_LABEL(name) \ + entry sp, FRAMESIZE; \ + CALL_MCOUNT + +#undef END +#define END(name) ASM_SIZE_DIRECTIVE(name) + +/* Define a macro for this directive so it can be removed in a few places. */ +#define LITERAL_POSITION .literal_position + +#undef JUMPTARGET +#ifdef __PIC__ +/* The "@PLT" suffix is currently a no-op for non-shared linking, but + it doesn't hurt to use it conditionally for PIC code in case that + changes someday. */ +#define JUMPTARGET(name) name##@PLT +#else +#define JUMPTARGET(name) name +#endif + +#define FRAMESIZE 16 +#define CALL_MCOUNT /* Do nothing. */ + + +/* Linux uses a negative return value to indicate syscall errors, + unlike most Unices, which use the condition codes' carry flag. + + Since version 2.1 the return value of a system call might be + negative even if the call succeeded. E.g., the `lseek' system call + might return a large offset. Therefore we must not anymore test + for < 0, but test for a real error by making sure the value in a2 + is a real error number. Linus said he will make sure the no syscall + returns a value in -1 .. -4095 as a valid result so we can safely + test with -4095. */ + +/* We don't want the label for the error handler to be global when we define + it here. */ +#define SYSCALL_ERROR_LABEL 0f + +#undef PSEUDO +#define PSEUDO(name, syscall_name, args) \ + .text; \ + ENTRY (name) \ + DO_CALL (syscall_name, args); \ + movi a4, -4095; \ + bgeu a2, a4, SYSCALL_ERROR_LABEL; \ + .Lpseudo_end: + +#undef PSEUDO_END +#define PSEUDO_END(name) \ + SYSCALL_ERROR_HANDLER \ + END (name) + +#undef PSEUDO_NOERRNO +#define PSEUDO_NOERRNO(name, syscall_name, args) \ + .text; \ + ENTRY (name) \ + DO_CALL (syscall_name, args) + +#undef PSEUDO_END_NOERRNO +#define PSEUDO_END_NOERRNO(name) \ + END (name) + +#undef ret_NOERRNO +#define ret_NOERRNO retw + +/* The function has to return the error code. */ +#undef PSEUDO_ERRVAL +#define PSEUDO_ERRVAL(name, syscall_name, args) \ + .text; \ + ENTRY (name) \ + DO_CALL (syscall_name, args); \ + neg a2, a2 + +#undef PSEUDO_END_ERRVAL +#define PSEUDO_END_ERRVAL(name) \ + END (name) + +#define ret_ERRVAL retw + +#if defined RTLD_PRIVATE_ERRNO +# define SYSCALL_ERROR_HANDLER \ +0: movi a4, rtld_errno; \ + neg a2, a2; \ + s32i a2, a4, 0; \ + movi a2, -1; \ + j .Lpseudo_end; + +#elif defined _LIBC_REENTRANT + +# if defined USE___THREAD +# ifndef NOT_IN_libc +# define SYSCALL_ERROR_ERRNO __libc_errno +# else +# define SYSCALL_ERROR_ERRNO errno +# endif +# define SYSCALL_ERROR_HANDLER \ +0: rur a4, THREADPTR; \ + movi a3, SYSCALL_ERROR_ERRNO@TPOFF; \ + neg a2, a2; \ + add a4, a4, a3; \ + s32i a2, a4, 0; \ + movi a2, -1; \ + j .Lpseudo_end; +# else /* !USE___THREAD */ +# define SYSCALL_ERROR_HANDLER \ +0: neg a2, a2; \ + mov a6, a2; \ + movi a4, __errno_location@PLT; \ + callx4 a4; \ + s32i a2, a6, 0; \ + movi a2, -1; \ + j .Lpseudo_end; +# endif /* !USE___THREAD */ +#else /* !_LIBC_REENTRANT */ +#define SYSCALL_ERROR_HANDLER \ +0: movi a4, errno; \ + neg a2, a2; \ + s32i a2, a4, 0; \ + movi a2, -1; \ + j .Lpseudo_end; +#endif /* _LIBC_REENTRANT */ + +#endif /* __ASSEMBLER__ */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/vfork.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/vfork.S new file mode 100644 index 00000000..6e490fe4 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/vfork.S @@ -0,0 +1,170 @@ +/* Copyright (C) 2005, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street - Fifth Floor, + Boston, MA 02110-1301, USA. */ + +#include "sysdep.h" +#include +#define _SIGNAL_H +#include + + +/* Clone the calling process, but without copying the whole address space. + The calling process is suspended until the new process exits or is + replaced by a call to `execve'. Return -1 for errors, 0 to the new process, + and the process ID of the new process to the old process. + + Note that it is important that we don't create a new stack frame for the + caller. */ + + +/* The following are defined in linux/sched.h, which unfortunately + is not safe for inclusion in an assembly file. */ +#define CLONE_VM 0x00000100 /* set if VM shared between processes */ +#define CLONE_VFORK 0x00004000 /* set if the parent wants the child to + wake it up on mm_release */ + +#ifndef SAVE_PID +#define SAVE_PID +#endif + +#ifndef RESTORE_PID +#define RESTORE_PID +#endif + + +/* pid_t vfork(void); + Implemented as __clone_syscall(CLONE_VFORK | CLONE_VM | SIGCHLD, 0) */ + +ENTRY (__vfork) + + movi a6, .Ljumptable + extui a2, a0, 30, 2 /* call-size: call4/8/12 = 1/2/3 */ + addx4 a4, a2, a6 /* find return address in jumptable */ + l32i a4, a4, 0 + add a4, a4, a6 + + slli a2, a2, 30 + xor a3, a0, a2 /* remove call-size from return addr */ + extui a5, a4, 30, 2 /* get high bits of jump target */ + slli a5, a5, 30 + or a3, a3, a5 /* stuff them into the return address */ + xor a4, a4, a5 /* clear high bits of jump target */ + or a0, a4, a2 /* create temporary return address */ + retw /* "return" to .L4, .L8, or .L12 */ + + .align 4 +.Ljumptable: + .word 0 + .word .L4 - .Ljumptable + .word .L8 - .Ljumptable + .word .L12 - .Ljumptable + + /* a7: return address */ +.L4: mov a12, a2 + mov a13, a3 + + SAVE_PID + + /* Use syscall 'clone'. Set new stack pointer to the same address. */ + movi a2, SYS_ify (clone) + movi a3, 0 + movi a6, CLONE_VM | CLONE_VFORK | SIGCHLD + syscall + + RESTORE_PID + + movi a5, -4096 + + mov a6, a2 + mov a2, a12 + mov a3, a13 + + bgeu a6, a5, 1f + jx a7 +1: call4 .Lerr /* returns to original caller */ + + + /* a11: return address */ +.L8: mov a12, a2 + mov a13, a3 + mov a14, a6 + + SAVE_PID + + movi a2, SYS_ify (clone) + movi a3, 0 + movi a6, CLONE_VM | CLONE_VFORK | SIGCHLD + syscall + + RESTORE_PID + + movi a9, -4096 + + mov a10, a2 + mov a2, a12 + mov a3, a13 + mov a6, a14 + + bgeu a10, a9, 1f + jx a11 +1: call8 .Lerr /* returns to original caller */ + + + /* a15: return address */ +.L12: mov a12, a2 + mov a13, a3 + mov a14, a6 + + SAVE_PID + + movi a2, SYS_ify (clone) + movi a3, 0 + movi a6, CLONE_VM | CLONE_VFORK | SIGCHLD + syscall + + RESTORE_PID + + mov a3, a13 + movi a13, -4096 + + mov a6, a14 + mov a14, a2 + + mov a2, a12 + + bgeu a14, a13, 1f + jx a15 +1: call12 .Lerr /* returns to original caller */ + + + .align 4 +.Lerr: entry a1, 16 + + /* Restore the return address. */ + extui a4, a0, 30, 2 /* get the call-size bits */ + slli a4, a4, 30 + slli a3, a3, 2 /* clear high bits of target address */ + srli a3, a3, 2 + or a0, a3, a4 /* combine them */ + + PSEUDO_END (__vfork) +.Lpseudo_end: + retw + +libc_hidden_def (__vfork) + +weak_alias (__vfork, vfork) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/windowspill.S b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/windowspill.S new file mode 100644 index 00000000..1487f079 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/xtensa/windowspill.S @@ -0,0 +1,96 @@ +/* Function to force register windows to the stack. + Copyright (C) 2005, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street - Fifth Floor, + Boston, MA 02110-1301, USA. */ + +#include + + .text + .align 4 + .literal_position + .global __window_spill + .type __window_spill, @function +__window_spill: + entry a1, 48 + bbci.l a0, 31, .L4 /* branch if called with call4 */ + bbsi.l a0, 30, .L12 /* branch if called with call12 */ + + /* Called with call8: touch register NUM_REGS-12 (4/20/52) */ +.L8: +#if XCHAL_NUM_AREGS > 16 + call12 1f + retw + + .align 4 +1: _entry a1, 48 /* touch NUM_REGS-24 (x/8/40) */ + +#if XCHAL_NUM_AREGS == 32 + mov a8, a0 + retw +#else + mov a12, a0 + _entry a1, 48 /* touch NUM_REGS-36 (x/x/28) */ + mov a12, a0 + _entry a1, 48 /* touch NUM_REGS-48 (x/x/16) */ + mov a12, a0 + _entry a1, 16 /* touch NUM_REGS-60 (x/x/4) */ +#endif +#endif + mov a4, a0 + retw + + /* Called with call4: touch register NUM_REGS-8 (8/24/56) */ +.L4: +#if XCHAL_NUM_AREGS == 16 + mov a8, a0 +#else + call12 1f + retw + + .align 4 +1: _entry a1, 48 /* touch NUM_REGS-20 (x/12/44) */ + mov a12, a0 +#if XCHAL_NUM_AREGS > 32 + _entry a1, 48 /* touch NUM_REGS-32 (x/x/32) */ + mov a12, a0 + _entry a1, 48 /* touch NUM_REGS-44 (x/x/20) */ + mov a12, a0 + _entry a1, 48 /* touch NUM_REGS-56 (x/x/8) */ + mov a8, a0 +#endif +#endif + retw + + /* Called with call12: touch register NUM_REGS-16 (x/16/48) */ +.L12: +#if XCHAL_NUM_AREGS > 16 + call12 1f + retw + + .align 4 +1: _entry a1, 48 /* touch NUM_REGS-28 (x/4/36) */ +#if XCHAL_NUM_AREGS == 32 + mov a4, a0 +#else + mov a12, a0 + _entry a1, 48 /* touch NUM_REGS-40 (x/x/24) */ + mov a12, a0 + _entry a1, 48 /* touch NUM_REGS-52 (x/x/12) */ + mov a12, a0 +#endif +#endif + retw diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/termios/.indent.pro b/l4/pkg/uclibc/lib/contrib/uclibc/libc/termios/.indent.pro new file mode 100644 index 00000000..492ecf1c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/termios/.indent.pro @@ -0,0 +1,33 @@ +--blank-lines-after-declarations +--blank-lines-after-procedures +--break-before-boolean-operator +--no-blank-lines-after-commas +--braces-on-if-line +--braces-on-struct-decl-line +--comment-indentation25 +--declaration-comment-column25 +--no-comment-delimiters-on-blank-lines +--cuddle-else +--continuation-indentation4 +--case-indentation0 +--else-endif-column33 +--space-after-cast +--line-comments-indentation0 +--declaration-indentation1 +--dont-format-first-column-comments +--dont-format-comments +--honour-newlines +--indent-level4 +/* changed from 0 to 4 */ +--parameter-indentation4 +--line-length78 /* changed from 75 */ +--continue-at-parentheses +--no-space-after-function-call-names +--dont-break-procedure-type +--dont-star-comments +--leave-optional-blank-lines +--dont-space-special-semicolon +--tab-size4 +/* additions by Mark */ +--case-brace-indentation0 +--leave-preprocessor-space diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/termios/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libc/termios/Makefile new file mode 100644 index 00000000..11f362a5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/termios/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../ +top_builddir=../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/termios/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/libc/termios/Makefile.in new file mode 100644 index 00000000..73f72729 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/termios/Makefile.in @@ -0,0 +1,21 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +subdirs += libc/termios + +TERMIOS_DIR := $(top_srcdir)libc/termios +TERMIOS_OUT := $(top_builddir)libc/termios + +TERMIOS_SRC := $(wildcard $(TERMIOS_DIR)/*.c) +TERMIOS_OBJ := $(patsubst $(TERMIOS_DIR)/%.c,$(TERMIOS_OUT)/%.o,$(TERMIOS_SRC)) + +libc-y += $(TERMIOS_OBJ) + +objclean-y += CLEAN_libc/termios + +CLEAN_libc/termios: + $(do_rm) $(addprefix $(TERMIOS_OUT)/*., o os) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/termios/cfmakeraw.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/termios/cfmakeraw.c new file mode 100644 index 00000000..aae76782 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/termios/cfmakeraw.c @@ -0,0 +1,33 @@ +/* Copyright (C) 1992, 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#ifdef __USE_BSD +/* Set *T to indicate raw mode. */ +void cfmakeraw (struct termios *t) +{ + t->c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON); + t->c_oflag &= ~OPOST; + t->c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN); + t->c_cflag &= ~(CSIZE|PARENB); + t->c_cflag |= CS8; + t->c_cc[VMIN] = 1; /* read returns when one char is available. */ + t->c_cc[VTIME] = 0; +} +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/termios/cfsetspeed.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/termios/cfsetspeed.c new file mode 100644 index 00000000..b1d54cb9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/termios/cfsetspeed.c @@ -0,0 +1,177 @@ +/* Copyright (C) 1992,93,96,97,98,2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +#ifdef __USE_BSD + + +struct speed_struct +{ + speed_t value; + speed_t internal; +}; + +static const struct speed_struct speeds[] = + { +#ifdef B0 + { 0, B0 }, +#endif +#ifdef B50 + { 50, B50 }, +#endif +#ifdef B75 + { 75, B75 }, +#endif +#ifdef B110 + { 110, B110 }, +#endif +#ifdef B134 + { 134, B134 }, +#endif +#ifdef B150 + { 150, B150 }, +#endif +#ifdef B200 + { 200, B200 }, +#endif +#ifdef B300 + { 300, B300 }, +#endif +#ifdef B600 + { 600, B600 }, +#endif +#ifdef B1200 + { 1200, B1200 }, +#endif +#ifdef B1200 + { 1200, B1200 }, +#endif +#ifdef B1800 + { 1800, B1800 }, +#endif +#ifdef B2400 + { 2400, B2400 }, +#endif +#ifdef B4800 + { 4800, B4800 }, +#endif +#ifdef B9600 + { 9600, B9600 }, +#endif +#ifdef B19200 + { 19200, B19200 }, +#endif +#ifdef B38400 + { 38400, B38400 }, +#endif +#ifdef B57600 + { 57600, B57600 }, +#endif +#ifdef B76800 + { 76800, B76800 }, +#endif +#ifdef B115200 + { 115200, B115200 }, +#endif +#ifdef B153600 + { 153600, B153600 }, +#endif +#ifdef B230400 + { 230400, B230400 }, +#endif +#ifdef B307200 + { 307200, B307200 }, +#endif +#ifdef B460800 + { 460800, B460800 }, +#endif +#ifdef B500000 + { 500000, B500000 }, +#endif +#ifdef B576000 + { 576000, B576000 }, +#endif +#ifdef B614400 + { 614400, B614400 }, +#endif +#ifdef B921600 + { 921600, B921600 }, +#endif +#ifdef B1000000 + { 1000000, B1000000 }, +#endif +#ifdef B1152000 + { 1152000, B1152000 }, +#endif +#ifdef B1500000 + { 1500000, B1500000 }, +#endif +#ifdef B1843200 + { 1843200, B1843200 }, +#endif +#ifdef B2000000 + { 2000000, B2000000 }, +#endif +#ifdef B2500000 + { 2500000, B2500000 }, +#endif +#ifdef B3000000 + { 3000000, B3000000 }, +#endif +#ifdef B3500000 + { 3500000, B3500000 }, +#endif +#ifdef B4000000 + { 4000000, B4000000 }, +#endif +#ifdef B6250000 + { 6250000, B6250000 }, +#endif +#ifdef B12500000 + { 12500000, B12500000 }, +#endif + }; + + +/* Set both the input and output baud rates stored in *TERMIOS_P to SPEED. */ +int cfsetspeed (struct termios *termios_p, speed_t speed) +{ + size_t cnt; + + for (cnt = 0; cnt < sizeof (speeds) / sizeof (speeds[0]); ++cnt) + if (speed == speeds[cnt].internal) + { + cfsetispeed (termios_p, speed); + cfsetospeed (termios_p, speed); + return 0; + } + else if (speed == speeds[cnt].value) + { + cfsetispeed (termios_p, speeds[cnt].internal); + cfsetospeed (termios_p, speeds[cnt].internal); + return 0; + } + + __set_errno (EINVAL); + + return -1; +} +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/termios/isatty.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/termios/isatty.c new file mode 100644 index 00000000..9e865225 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/termios/isatty.c @@ -0,0 +1,30 @@ +/* Copyright (C) 1991, 1995, 1996, 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + + +/* Return 1 if FD is a terminal, 0 if not. */ +int isatty (int fd) +{ + struct termios term; + + return tcgetattr (fd, &term) == 0; +} +libc_hidden_def(isatty) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/termios/kernel_termios.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/termios/kernel_termios.h new file mode 100644 index 00000000..87d5c07e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/termios/kernel_termios.h @@ -0,0 +1,139 @@ +/* Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _KERNEL_TERMIOS_H +#define _KERNEL_TERMIOS_H 1 + +/* We need the definition of tcflag_t, cc_t, and speed_t. */ +#include + +/* The following corresponds to the values from the Linux 2.1.20 kernel. */ + + + + +#if defined( __sparc__ ) + + +#define __KERNEL_NCCS 17 +struct __kernel_termios +{ + tcflag_t c_iflag; /* input mode flags */ + tcflag_t c_oflag; /* output mode flags */ + tcflag_t c_cflag; /* control mode flags */ + tcflag_t c_lflag; /* local mode flags */ + cc_t c_line; /* line discipline */ + cc_t c_cc[__KERNEL_NCCS]; /* control characters */ +}; + + + +#elif defined(__powerpc__) + + + +#define __KERNEL_NCCS 19 +struct __kernel_termios + { + tcflag_t c_iflag; /* input mode flags */ + tcflag_t c_oflag; /* output mode flags */ + tcflag_t c_cflag; /* control mode flags */ + tcflag_t c_lflag; /* local mode flags */ + cc_t c_cc[__KERNEL_NCCS]; /* control characters */ + cc_t c_line; /* line discipline */ + speed_t c_ispeed; /* input speed */ + speed_t c_ospeed; /* output speed */ + }; + +#define _HAVE_C_ISPEED 1 +#define _HAVE_C_OSPEED 1 + +/* We have the kernel termios structure, so we can presume this code knows + what it's doing... */ +#undef TCGETS +#undef TCSETS +#undef TCSETSW +#undef TCSETSF +#define TCGETS _IOR ('t', 19, struct __kernel_termios) +#define TCSETS _IOW ('t', 20, struct __kernel_termios) +#define TCSETSW _IOW ('t', 21, struct __kernel_termios) +#define TCSETSF _IOW ('t', 22, struct __kernel_termios) + + + +#elif defined(__mips__) + + + +#define __KERNEL_NCCS 23 +struct __kernel_termios +{ + tcflag_t c_iflag; /* input mode flags */ + tcflag_t c_oflag; /* output mode flags */ + tcflag_t c_cflag; /* control mode flags */ + tcflag_t c_lflag; /* local mode flags */ + cc_t c_line; /* line discipline */ + cc_t c_cc[__KERNEL_NCCS]; /* control characters */ +}; + + + +#elif defined(__alpha__) + + + +#define __KERNEL_NCCS 19 +struct __kernel_termios +{ + tcflag_t c_iflag; /* input mode flags */ + tcflag_t c_oflag; /* output mode flags */ + tcflag_t c_cflag; /* control mode flags */ + tcflag_t c_lflag; /* local mode flags */ + cc_t c_cc[__KERNEL_NCCS]; /* control characters */ + cc_t c_line; /* line discipline */ + speed_t c_ispeed; /* input speed */ + speed_t c_ospeed; /* output speed */ +}; + +#define _HAVE_C_ISPEED 1 +#define _HAVE_C_OSPEED 1 + + + +#else /* None of the above */ + + + +#define __KERNEL_NCCS 19 +struct __kernel_termios +{ + tcflag_t c_iflag; /* input mode flags */ + tcflag_t c_oflag; /* output mode flags */ + tcflag_t c_cflag; /* control mode flags */ + tcflag_t c_lflag; /* local mode flags */ + cc_t c_line; /* line discipline */ + cc_t c_cc[__KERNEL_NCCS]; /* control characters */ +}; + +#endif + + + + +#endif /* kernel_termios.h */ + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/termios/speed.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/termios/speed.c new file mode 100644 index 00000000..33b9c4a9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/termios/speed.c @@ -0,0 +1,95 @@ +/* `struct termios' speed frobnication functions. Linux version. + Copyright (C) 1991,1992,1993,1995,1996,1997,1998,2000,2002,2003 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + + +/* This is a gross hack around a kernel bug. If the cfsetispeed functions + is called with the SPEED argument set to zero this means use the same + speed as for output. But we don't have independent input and output + speeds and therefore cannot record this. + + We use an unused bit in the `c_iflag' field to keep track of this + use of `cfsetispeed'. The value here must correspond to the one used + in `tcsetattr.c'. */ +#define IBAUD0 020000000000 + + +/* Return the output baud rate stored in *TERMIOS_P. */ +speed_t cfgetospeed (const struct termios *termios_p) +{ + return termios_p->c_cflag & (CBAUD | CBAUDEX); +} + +/* Return the input baud rate stored in *TERMIOS_P. + Although for Linux there is no difference between input and output + speed, the numerical 0 is a special case for the input baud rate. It + should set the input baud rate to the output baud rate. */ +speed_t cfgetispeed (const struct termios *termios_p) +{ + return ((termios_p->c_iflag & IBAUD0) + ? 0 : termios_p->c_cflag & (CBAUD | CBAUDEX)); +} + +/* Set the output baud rate stored in *TERMIOS_P to SPEED. */ +int cfsetospeed (struct termios *termios_p, speed_t speed) +{ + if ((speed & ~CBAUD) != 0 + && (speed < B57600 || speed > __MAX_BAUD)) + { + __set_errno (EINVAL); + return -1; + } + + termios_p->c_cflag &= ~(CBAUD | CBAUDEX); + termios_p->c_cflag |= speed; + + return 0; +} +libc_hidden_def (cfsetospeed) + + +/* Set the input baud rate stored in *TERMIOS_P to SPEED. + Although for Linux there is no difference between input and output + speed, the numerical 0 is a special case for the input baud rate. It + should set the input baud rate to the output baud rate. */ +int cfsetispeed (struct termios *termios_p, speed_t speed) +{ + if ((speed & ~CBAUD) != 0 + && (speed < B57600 || speed > __MAX_BAUD)) + { + __set_errno (EINVAL); + return -1; + } + + if (speed == 0) + termios_p->c_iflag |= IBAUD0; + else + { + termios_p->c_iflag &= ~IBAUD0; + termios_p->c_cflag &= ~(CBAUD | CBAUDEX); + termios_p->c_cflag |= speed; + } + + return 0; +} +libc_hidden_def (cfsetispeed) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/termios/tcdrain.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/termios/tcdrain.c new file mode 100644 index 00000000..e0f42313 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/termios/tcdrain.c @@ -0,0 +1,49 @@ +/* Copyright (C) 1995, 1996, 1997, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#ifdef __UCLIBC_HAS_THREADS_NATIVE__ +#include +#endif + +libc_hidden_proto(ioctl) + +extern __typeof(tcdrain) __libc_tcdrain; +/* Wait for pending output to be written on FD. */ +int __libc_tcdrain (int fd) +{ +#ifdef __UCLIBC_HAS_THREADS_NATIVE__ + if (SINGLE_THREAD_P) + /* With an argument of 1, TCSBRK for output to be drain. */ + return INLINE_SYSCALL (ioctl, 3, fd, TCSBRK, 1); + + int oldtype = LIBC_CANCEL_ASYNC (); + + /* With an argument of 1, TCSBRK for output to be drain. */ + int result = INLINE_SYSCALL (ioctl, 3, fd, TCSBRK, 1); + + LIBC_CANCEL_RESET (oldtype); + + return result; +#else + return ioctl(fd, TCSBRK, 1); +#endif +} +weak_alias(__libc_tcdrain,tcdrain) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/termios/tcflow.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/termios/tcflow.c new file mode 100644 index 00000000..35ae1b2a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/termios/tcflow.c @@ -0,0 +1,29 @@ +/* tcflow -- Suspend or restart transmission on termios file descriptor. + Copyright (C) 1993,1997,2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + + +/* Suspend or restart transmission on FD. */ +int tcflow (int fd, int action) +{ + return ioctl (fd, TCXONC, action); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/termios/tcflush.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/termios/tcflush.c new file mode 100644 index 00000000..7c9d1c58 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/termios/tcflush.c @@ -0,0 +1,30 @@ +/* tcflush -- Flush pending data on termios file descriptor. Linux version. + Copyright (C) 1993,1997,2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + + +/* Flush pending data on FD. */ +int +tcflush (int fd, int queue_selector) +{ + return ioctl (fd, TCFLSH, queue_selector); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/termios/tcgetattr.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/termios/tcgetattr.c new file mode 100644 index 00000000..0bdc70b3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/termios/tcgetattr.c @@ -0,0 +1,77 @@ +/* Copyright (C) 1992, 1995, 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include + + +/* The difference here is that the termios structure used in the + kernel is not the same as we use in the libc. Therefore we must + translate it here. */ +#include "kernel_termios.h" + +/* Put the state of FD into *TERMIOS_P. */ +int tcgetattr (int fd, struct termios *termios_p) +{ + struct __kernel_termios k_termios; + int retval; + + retval = ioctl (fd, TCGETS, &k_termios); + if(likely(retval == 0)) { + termios_p->c_iflag = k_termios.c_iflag; + termios_p->c_oflag = k_termios.c_oflag; + termios_p->c_cflag = k_termios.c_cflag; + termios_p->c_lflag = k_termios.c_lflag; + termios_p->c_line = k_termios.c_line; +#ifdef _HAVE_C_ISPEED + termios_p->c_ispeed = k_termios.c_ispeed; +#endif +#ifdef _HAVE_C_OSPEED + termios_p->c_ospeed = k_termios.c_ospeed; +#endif + + + if (sizeof (cc_t) == 1 || _POSIX_VDISABLE == 0 + || (unsigned char) _POSIX_VDISABLE == (unsigned char) -1) + { + memset (mempcpy (&termios_p->c_cc[0], &k_termios.c_cc[0], + __KERNEL_NCCS * sizeof (cc_t)), + _POSIX_VDISABLE, (NCCS - __KERNEL_NCCS) * sizeof (cc_t)); +#if 0 + memset ( (memcpy (&termios_p->c_cc[0], &k_termios.c_cc[0], + __KERNEL_NCCS * sizeof (cc_t)) + (__KERNEL_NCCS * sizeof (cc_t))) , + _POSIX_VDISABLE, (NCCS - __KERNEL_NCCS) * sizeof (cc_t)); +#endif + } else { + size_t cnt; + + memcpy (&termios_p->c_cc[0], &k_termios.c_cc[0], + __KERNEL_NCCS * sizeof (cc_t)); + + for (cnt = __KERNEL_NCCS; cnt < NCCS; ++cnt) + termios_p->c_cc[cnt] = _POSIX_VDISABLE; + } + } + + return retval; +} +libc_hidden_def(tcgetattr) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/termios/tcgetpgrp.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/termios/tcgetpgrp.c new file mode 100644 index 00000000..e2509c83 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/termios/tcgetpgrp.c @@ -0,0 +1,34 @@ +/* Copyright (C) 1991, 1997, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + + +/* Return the foreground process group ID of FD. */ +pid_t tcgetpgrp (int fd) +{ + pid_t pgrp; + + if (ioctl (fd, TIOCGPGRP, &pgrp) < 0) + return -1; + return pgrp; +} +libc_hidden_def (tcgetpgrp) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/termios/tcgetsid.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/termios/tcgetsid.c new file mode 100644 index 00000000..b5da2e76 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/termios/tcgetsid.c @@ -0,0 +1,63 @@ +/* Copyright (C) 1997, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include + + +/* Return the session ID of FD. */ +pid_t +tcgetsid (int fd) +{ + pid_t pgrp; + pid_t sid; +#ifdef TIOCGSID + static smallint tiocgsid_does_not_work; + + if (! tiocgsid_does_not_work) + { + int serrno = errno; + + if (ioctl (fd, TIOCGSID, &sid) < 0) + { + if (errno == EINVAL) + { + tiocgsid_does_not_work = 1; + __set_errno (serrno); + } + else + return (pid_t) -1; + } + else + return (pid_t) sid; + } +#endif + + pgrp = tcgetpgrp (fd); + if (pgrp == -1) + return (pid_t) -1; + + sid = getsid (pgrp); + if (sid == -1 && errno == ESRCH) + __set_errno (ENOTTY); + + return sid; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/termios/tcsendbrk.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/termios/tcsendbrk.c new file mode 100644 index 00000000..322956c7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/termios/tcsendbrk.c @@ -0,0 +1,47 @@ +/* Send break to terminal. + Copyright (C) 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + + +/* Send zero bits on FD. */ +int +tcsendbreak (int fd, int duration) +{ + /* The break lasts 0.25 to 0.5 seconds if DURATION is zero, + and an implementation-defined period if DURATION is nonzero. + We define a positive DURATION to be number of milliseconds to break. */ + if (duration <= 0) + return ioctl (fd, TCSBRK, 0); + +#ifdef TCSBRKP + /* Probably Linux-specific: a positive third TCSBRKP ioctl argument is + defined to be the number of 100ms units to break. */ + return ioctl (fd, TCSBRKP, (duration + 99) / 100); +#else + /* ioctl can't send a break of any other duration for us. + This could be changed to use trickery (e.g. lower speed and + send a '\0') to send the break, but for now just return an error. */ + __set_errno (EINVAL); + return -1; +#endif +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/termios/tcsetattr.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/termios/tcsetattr.c new file mode 100644 index 00000000..786fc69c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/termios/tcsetattr.c @@ -0,0 +1,118 @@ +/* Copyright (C) 1993, 1996, 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include + + +/* The difference here is that the termios structure used in the + kernel is not the same as we use in the libc. Therefore we must + translate it here. */ +#include "kernel_termios.h" + + +/* This is a gross hack around a kernel bug. If the cfsetispeed functions + is called with the SPEED argument set to zero this means use the same + speed as for output. But we don't have independent input and output + speeds and therefore cannot record this. + + We use an unused bit in the `c_iflag' field to keep track of this + use of `cfsetispeed'. The value here must correspond to the one used + in `speed.c'. */ +#if !defined _HAVE_C_ISPEED || !defined _HAVE_C_OSPEED +# define IBAUD0 020000000000 +#else +/* If we have separate values for input and output speed don't bother + with this. Define the value as zero so the compiler sees we don't + have to do the AND below. */ +# define IBAUD0 0 +#endif + + +/* Set the state of FD to *TERMIOS_P. */ +int tcsetattr (int fd, int optional_actions, const struct termios *termios_p) +{ + struct __kernel_termios k_termios; + unsigned long int cmd; + int retval; + + switch (optional_actions) + { + case TCSANOW: + cmd = TCSETS; + break; + case TCSADRAIN: + cmd = TCSETSW; + break; + case TCSAFLUSH: + cmd = TCSETSF; + break; + default: + __set_errno (EINVAL); + return -1; + } + + k_termios.c_iflag = termios_p->c_iflag & ~IBAUD0; + k_termios.c_oflag = termios_p->c_oflag; + k_termios.c_cflag = termios_p->c_cflag; + k_termios.c_lflag = termios_p->c_lflag; + k_termios.c_line = termios_p->c_line; +#ifdef _HAVE_C_ISPEED + k_termios.c_ispeed = termios_p->c_ispeed; +#endif +#ifdef _HAVE_C_OSPEED + k_termios.c_ospeed = termios_p->c_ospeed; +#endif + memcpy (&k_termios.c_cc[0], &termios_p->c_cc[0], + __KERNEL_NCCS * sizeof (cc_t)); + + retval = ioctl (fd, cmd, &k_termios); + + if (retval == 0 && cmd == TCSETS) + { + /* The Linux kernel has a bug which silently ignore the invalid + c_cflag on pty. We have to check it here. */ + int save = errno; + retval = ioctl (fd, TCGETS, &k_termios); + if (retval) + { + /* We cannot verify if the setting is ok. We don't return + an error (?). */ + __set_errno (save); + retval = 0; + } + else if ((termios_p->c_cflag & (PARENB | CREAD)) + != (k_termios.c_cflag & (PARENB | CREAD)) + || ((termios_p->c_cflag & CSIZE) + && ((termios_p->c_cflag & CSIZE) + != (k_termios.c_cflag & CSIZE)))) + { + /* It looks like the Linux kernel silently changed the + PARENB/CREAD/CSIZE bits in c_cflag. Report it as an + error. */ + __set_errno (EINVAL); + retval = -1; + } + } + + return retval; +} +libc_hidden_def(tcsetattr) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/termios/tcsetpgrp.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/termios/tcsetpgrp.c new file mode 100644 index 00000000..6a3b8d82 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/termios/tcsetpgrp.c @@ -0,0 +1,29 @@ +/* Copyright (C) 1991, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + + +/* Set the foreground process group ID of FD set PGRP_ID. */ +int tcsetpgrp (int fd, pid_t pgrp_id) +{ + return ioctl (fd, TIOCSPGRP, &pgrp_id); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/termios/ttyname.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/termios/ttyname.c new file mode 100644 index 00000000..5fcf23b6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/termios/ttyname.c @@ -0,0 +1,127 @@ +/* + * Copyright (C) Jan 1, 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* + * Kept the same approach, but rewrote the code for the most part. + * Fixed some minor issues plus (as I recall) one SUSv3 errno case. + */ + +/* This is a fairly slow approach. We do a linear search through some + * directories looking for a match. Yes this is lame. But it should + * work, should be small, and will return names that match what is on + * disk. Another approach we could use would be to use the info in + * /proc/self/fd, but that is even more lame since it requires /proc */ + +/* SUSv3 mandates TTY_NAME_MAX as 9. This is obviously insufficient. + * However, there is no need to waste space and support non-standard + * tty names either. So we compromise and use the following buffer + * length. (Erik and Manuel agreed that 32 was more than reasonable.) + * + * If you change this, also change _SC_TTY_NAME_MAX in libc/unistd/sysconf.c + */ + +#include +#include +#include +#include +#include +#include + + +#define TTYNAME_BUFLEN 32 + +static const char dirlist[] = +/* 12345670123 */ +"\010/dev/vc/\0" /* Try /dev/vc first (be devfs compatible) */ +"\011/dev/tts/\0" /* and /dev/tts next (be devfs compatible) */ +"\011/dev/pty/\0" /* and /dev/pty next (be devfs compatible) */ +"\011/dev/pts/\0" /* and try /dev/pts next */ +"\005/dev/\0"; /* and try walking through /dev last */ + +int ttyname_r(int fd, char *ubuf, size_t ubuflen) +{ + struct dirent *d; + struct stat st; + struct stat dst; + const char *p; + char *s; + DIR *fp; + int rv; + size_t len; + char buf[TTYNAME_BUFLEN]; + + if (fstat(fd, &st) < 0) { + return errno; + } + + rv = ENOTTY; /* Set up the default return value. */ + + if (!isatty(fd)) { + goto DONE; + } + + for (p = dirlist ; *p ; p += 1 + p[-1]) { + len = *p++; + + assert(len + 2 <= TTYNAME_BUFLEN); /* dirname + 1 char + nul */ + + strcpy(buf, p); + s = buf + len; + len = (TTYNAME_BUFLEN-2) - len; /* Available non-nul space. */ + + if (!(fp = opendir(p))) { + continue; + } + + while ((d = readdir(fp)) != NULL) { + /* This should never trigger for standard names, but we + * check it to be safe. */ + if (strlen(d->d_name) > len) { /* Too big? */ + continue; + } + + strcpy(s, d->d_name); + + if ((lstat(buf, &dst) == 0) +#if 0 + /* Stupid filesystems like cramfs fail to guarantee that + * st_ino and st_dev uniquely identify a file, contrary to + * SuSv3, so we cannot be quite so precise as to require an + * exact match. Settle for something less... Grumble... */ + && (st.st_dev == dst.st_dev) && (st.st_ino == dst.st_ino) +#else + && S_ISCHR(dst.st_mode) && (st.st_rdev == dst.st_rdev) +#endif + ) { /* Found it! */ + closedir(fp); + + /* We treat NULL buf as ERANGE rather than EINVAL. */ + rv = ERANGE; + if (ubuf && (strlen(buf) <= ubuflen)) { + strcpy(ubuf, buf); + rv = 0; + } + goto DONE; + } + } + + closedir(fp); + } + + DONE: + __set_errno(rv); + + return rv; +} +libc_hidden_def(ttyname_r) + +char *ttyname(int fd) +{ + static char name[TTYNAME_BUFLEN]; + + return ttyname_r(fd, name, TTYNAME_BUFLEN) ? NULL : name; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/.indent.pro b/l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/.indent.pro new file mode 100644 index 00000000..492ecf1c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/.indent.pro @@ -0,0 +1,33 @@ +--blank-lines-after-declarations +--blank-lines-after-procedures +--break-before-boolean-operator +--no-blank-lines-after-commas +--braces-on-if-line +--braces-on-struct-decl-line +--comment-indentation25 +--declaration-comment-column25 +--no-comment-delimiters-on-blank-lines +--cuddle-else +--continuation-indentation4 +--case-indentation0 +--else-endif-column33 +--space-after-cast +--line-comments-indentation0 +--declaration-indentation1 +--dont-format-first-column-comments +--dont-format-comments +--honour-newlines +--indent-level4 +/* changed from 0 to 4 */ +--parameter-indentation4 +--line-length78 /* changed from 75 */ +--continue-at-parentheses +--no-space-after-function-call-names +--dont-break-procedure-type +--dont-star-comments +--leave-optional-blank-lines +--dont-space-special-semicolon +--tab-size4 +/* additions by Mark */ +--case-brace-indentation0 +--leave-preprocessor-space diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/Makefile new file mode 100644 index 00000000..11f362a5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../ +top_builddir=../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/Makefile.in new file mode 100644 index 00000000..27041773 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/Makefile.in @@ -0,0 +1,52 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +subdirs += libc/unistd + +UNISTD_DIR := $(top_srcdir)libc/unistd +UNISTD_OUT := $(top_builddir)libc/unistd + +CSRC := $(notdir $(wildcard $(UNISTD_DIR)/*.c)) +# multi source +CSRC := $(filter-out exec.c,$(CSRC)) + +ifeq ($(ARCH_USE_MMU),y) +CSRC := $(filter-out __exec_alloc.c,$(CSRC)) +endif + +ifeq ($(UCLIBC_HAS_GNU_GETOPT),y) +CSRC := $(filter-out getopt-susv3.c getopt_long-simple.c,$(CSRC)) +else +CSRC := $(filter-out getopt.c,$(CSRC)) +ifneq ($(UCLIBC_HAS_GETOPT_LONG),y) +CSRC := $(filter-out getopt_long-simple.c,$(CSRC)) +endif +endif + +ifeq ($(UCLIBC_HAS_GNU_GETSUBOPT),y) +CSRC := $(filter-out getsubopt-susv3.c,$(CSRC)) +else +CSRC := $(filter-out getsubopt.c,$(CSRC)) +endif + +ifneq ($(UCLIBC_SUSV3_LEGACY),y) +CSRC := $(filter-out ualarm.c usleep.c,$(CSRC)) +endif + +ifeq ($(UCLIBC_HAS_THREADS_NATIVE),y) +CSRC := $(filter-out sleep.c,$(CSRC)) +endif + +UNISTD_SRC := $(patsubst %.c,$(UNISTD_DIR)/%.c,$(CSRC)) +UNISTD_OBJ := $(patsubst %.c,$(UNISTD_OUT)/%.o,$(CSRC)) + +libc-y += $(UNISTD_OBJ) + +objclean-y += CLEAN_libc/unistd + +CLEAN_libc/unistd: + $(do_rm) $(addprefix $(UNISTD_OUT)/*., o os) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/__exec_alloc.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/__exec_alloc.c new file mode 100644 index 00000000..837ffb47 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/__exec_alloc.c @@ -0,0 +1,8 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L___exec_alloc +#include "exec.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/confstr.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/confstr.c new file mode 100644 index 00000000..fc0bd599 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/confstr.c @@ -0,0 +1,81 @@ +/* Copyright (C) 1991, 1996, 1997, 2000-2002, 2003, 2004 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + + +#define CS_PATH "/bin:/usr/bin" + +/* If BUF is not NULL and LEN > 0, fill in at most LEN - 1 bytes + of BUF with the value corresponding to NAME and zero-terminate BUF. + Return the number of bytes required to hold NAME's entire value. */ +size_t confstr (int name, char *buf, size_t len) +{ + const char *string; + size_t string_len; + + switch (name) + { + case _CS_PATH: + { + static const char cs_path[] = CS_PATH; + string = cs_path; + string_len = sizeof (cs_path); + } + break; +#ifdef __UCLIBC_HAS_THREADS__ + case _CS_GNU_LIBPTHREAD_VERSION: +# if defined __LINUXTHREADS_OLD__ + string = "linuxthreads-0.01"; + string_len = sizeof("linuxthreads-x.xx"); +# elif defined __LINUXTHREADS_NEW__ + string = "linuxthreads-0.10"; + string_len = sizeof("linuxthreads-x.xx"); +# elif defined __UCLIBC_HAS_THREADS_NATIVE__ +# define __NPTL_VERSION ("NPTL " \ + __stringify(__UCLIBC_MAJOR__) "." \ + __stringify(__UCLIBC_MINOR__) "." \ + __stringify(__UCLIBC_SUBLEVEL__)) + string = __NPTL_VERSION; + string_len = sizeof(__NPTL_VERSION); +# else +# error unable to determine thread impl +# endif + break; +#endif + default: + __set_errno (EINVAL); + return 0; + } + + if (len > 0 && buf != NULL) + { + if (string_len <= len) + memcpy (buf, string, string_len); + else + { + memcpy (buf, string, len - 1); + buf[len - 1] = '\0'; + } + } + return string_len; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/daemon.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/daemon.c new file mode 100644 index 00000000..628df51b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/daemon.c @@ -0,0 +1,144 @@ +/* vi: set sw=4 ts=4: */ +/* daemon implementation for uClibc + * + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. + * + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * Modified for uClibc by Erik Andersen + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __UCLIBC_HAS_THREADS_NATIVE__ +#include +#endif + +#ifdef __UCLIBC_HAS_LFS__ +#define STAT stat64 +#define FSTAT fstat64 +#else +#define STAT stat +#define FSTAT fstat +#endif + +#if defined __USE_BSD || (defined __USE_XOPEN && !defined __USE_UNIX98) + +#ifndef __ARCH_USE_MMU__ +#include +#include +/* use clone() to get fork() like behavior here -- we just want to disassociate + * from the controlling terminal + */ +static inline attribute_optimize("O3") +pid_t _fork_parent(void) +{ + INTERNAL_SYSCALL_DECL(err); + register long ret = INTERNAL_SYSCALL(clone, err, 2, CLONE_VM, 0); + if (ret > 0) + /* parent needs to die now w/out touching stack */ + INTERNAL_SYSCALL(exit, err, 1, 0); + return ret; +} +static inline pid_t fork_parent(void) +{ + /* Block all signals to keep the parent from using the stack */ + pid_t ret; + sigset_t new_set, old_set; + sigfillset(&new_set); + sigprocmask(SIG_BLOCK, &new_set, &old_set); + ret = _fork_parent(); + sigprocmask(SIG_SETMASK, &old_set, NULL); + return ret; +} +#else +static inline pid_t fork_parent(void) +{ + switch (fork()) { + case -1: return -1; + case 0: return 0; + default: _exit(0); + } +} +#endif + +int daemon(int nochdir, int noclose) +{ + int fd; + + if (fork_parent() == -1) + return -1; + + if (setsid() == -1) + return -1; + + if (!nochdir) + chdir("/"); + + if (!noclose) + { + struct STAT st; + + if ((fd = open_not_cancel(_PATH_DEVNULL, O_RDWR, 0)) != -1 + && (__builtin_expect (FSTAT (fd, &st), 0) == 0)) + { + if (__builtin_expect (S_ISCHR (st.st_mode), 1) != 0) { + dup2(fd, STDIN_FILENO); + dup2(fd, STDOUT_FILENO); + dup2(fd, STDERR_FILENO); + if (fd > 2) + close(fd); + } else { + /* We must set an errno value since no + function call actually failed. */ + close_not_cancel_no_status (fd); + __set_errno (ENODEV); + return -1; + } + } else { + close_not_cancel_no_status (fd); + return -1; + } + } + return 0; +} +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/exec.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/exec.c new file mode 100644 index 00000000..7d24072e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/exec.c @@ -0,0 +1,331 @@ +/* Copyright (C) 2004 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* Jan 1, 2004 + * Initial version of a SUSv3 compliant exec*() functions. + * Feb 17, 2004 + * Sigh... Fall back to alloca() if munmap() is broken on uClinux. + */ + +/* NOTE: Strictly speaking, there could be problems from accessing + * __environ in multithreaded programs. The only way around this + * that I see is to essentially lock __environ access (modifying + * the setenv code), make a copy of the environment table (just the + * pointers since the strings themselves are never freed), and then + * unlock prior to the execve call. If that fails, then we'd need + * to free the storage allocated for the copy. Better ideas anyone? + */ + +#include +#include +#include +#include +#include +#include +#include +#include + + + +/**********************************************************************/ +#define EXEC_FUNC_COMMON 0 +#define EXEC_FUNC_EXECVP 1 +#if defined(__ARCH_USE_MMU__) + +/* We have an MMU, so use alloca() to grab space for buffers and arg lists. */ + +# define EXEC_ALLOC_SIZE(VAR) /* nothing to do */ +# define EXEC_ALLOC(SIZE,VAR,FUNC) alloca((SIZE)) +# define EXEC_FREE(PTR,VAR) ((void)0) + +#else + +/* We do not have an MMU, so using alloca() is not an option (as this will + * easily overflow the stack in most setups). Less obviously, using malloc() + * is not an option either since malloc()ed memory can leak in from a vfork()ed + * child into the parent as no one is around after the child calls exec*() to + * free() the memory. Therefore, we must use mmap() and unmap() directly, + * caching the result as we go. This way we minimize the leak by reusing the + * memory with every call to an exec*(). + * + * To prevent recursive use of the same cached memory, we have to give execvp() + * its own cache. Here are the nested exec calls (a/-: alloc/no-alloc): + * execve(-) -> calls straight to kernel + * execl(a) -> execve(-) + * execlp(a) -> execvp(a) !! recursive usage !! + * execle(a) -> execve(-) + * execv(-) -> execve(-) + * execvp(a) -> execve(-) + */ + +# define EXEC_ALLOC_SIZE(VAR) /* nothing to do */ +# define EXEC_ALLOC(SIZE,VAR,FUNC) __exec_alloc((SIZE), FUNC) +# define EXEC_FREE(PTR,VAR) ((void)0) + +extern void *__exec_alloc(size_t size, int func) attribute_hidden; + +# ifdef L___exec_alloc + +void attribute_hidden *__exec_alloc(size_t size, int func) +{ + static void *common_cache, *execvp_cache; + static size_t common_size, execvp_size; + + void **cache = (func ? &execvp_cache : &common_cache); + size_t *cache_size = (func ? &execvp_size : &common_size); + + if (*cache_size >= size) + return *cache; + else if (*cache) + munmap(*cache, *cache_size); + + *cache_size = size; + return *cache = mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0); + + /* We don't actually handle OOM in the exec funcs ... + if (*cache != MAP_FAILED) + return *cache; + else + return (*cache = NULL); + */ +} + +# endif + +#endif +/**********************************************************************/ +#ifdef L_execl + +int execl(const char *path, const char *arg, ...) +{ + EXEC_ALLOC_SIZE(size) /* Do NOT add a semicolon! */ + int n; + char **argv; + char **p; + va_list args; + + n = 0; + va_start(args, arg); + do { + ++n; + } while (va_arg(args, char *)); + va_end(args); + + p = argv = (char **) EXEC_ALLOC((n+1) * sizeof(char *), size, EXEC_FUNC_COMMON); + + p[0] = (char *)arg; + + va_start(args, arg); + do { + *++p = va_arg(args, char *); + } while (--n); + va_end(args); + + n = execve(path, (char *const *) argv, __environ); + + EXEC_FREE(argv, size); + + return n; +} +libc_hidden_def(execl) + +#endif +/**********************************************************************/ +#ifdef L_execv + +int execv(__const char *path, char *__const argv[]) +{ + return execve(path, argv, __environ); +} +libc_hidden_def(execv) + +#endif +/**********************************************************************/ +#ifdef L_execle + +int execle(const char *path, const char *arg, ...) +{ + EXEC_ALLOC_SIZE(size) /* Do NOT add a semicolon! */ + int n; + char **argv; + char **p; + char *const *envp; + va_list args; + + n = 0; + va_start(args, arg); + do { + ++n; + } while (va_arg(args, char *)); + envp = va_arg(args, char *const *); /* Varies from execl and execlp. */ + va_end(args); + + p = argv = (char **) EXEC_ALLOC((n+1) * sizeof(char *), size, EXEC_FUNC_COMMON); + + p[0] = (char *)arg; + + va_start(args, arg); + do { + *++p = va_arg(args, char *); + } while (--n); + va_end(args); + + n = execve(path, (char *const *) argv, envp); + + EXEC_FREE(argv, size); + + return n; +} +libc_hidden_def(execle) + +#endif +/**********************************************************************/ +#ifdef L_execlp + +int execlp(const char *file, const char *arg, ...) +{ + EXEC_ALLOC_SIZE(size) /* Do NOT add a semicolon! */ + int n; + char **argv; + char **p; + va_list args; + + n = 0; + va_start(args, arg); + do { + ++n; + } while (va_arg(args, char *)); + va_end(args); + + p = argv = (char **) EXEC_ALLOC((n+1) * sizeof(char *), size, EXEC_FUNC_COMMON); + + p[0] = (char *)arg; + + va_start(args, arg); + do { + *++p = va_arg(args, char *); + } while (--n); + va_end(args); + + n = execvp(file, (char *const *) argv); + + EXEC_FREE(argv, size); + + return n; +} +libc_hidden_def(execlp) + +#endif +/**********************************************************************/ +#ifdef L_execvp + + +/* Use a default path that matches glibc behavior, since SUSv3 says + * this is implementation-defined. The default is current working dir, + * /bin, and then /usr/bin. */ +static const char default_path[] = ":/bin:/usr/bin"; + +int execvp(const char *path, char *const argv[]) +{ + char *buf = NULL; + char *p; + char *e; + char *s0; + char *s; + EXEC_ALLOC_SIZE(size = 0) /* Do NOT add a semicolon! */ + size_t len; + size_t plen; + + if (!path || !*path) { /* Comply with SUSv3. */ + BAD: + __set_errno(ENOENT); + return -1; + } + + if (strchr(path, '/')) { + execve(path, argv, __environ); + if (errno == ENOEXEC) { + char **nargv; + EXEC_ALLOC_SIZE(size2) /* Do NOT add a semicolon! */ + size_t n; + RUN_BIN_SH: + /* Need the dimension - 1. We omit counting the trailing + * NULL but we actually omit the first entry. */ + for (n=0 ; argv[n] ; n++) {} + nargv = (char **) EXEC_ALLOC((n+2) * sizeof(char *), size2, EXEC_FUNC_EXECVP); + nargv[0] = argv[0]; + nargv[1] = (char *)path; + memcpy(nargv+2, argv+1, n*sizeof(char *)); + execve("/bin/sh", nargv, __environ); + EXEC_FREE(nargv, size2); + } + } else { + if ((p = getenv("PATH")) != NULL) { + if (!*p) { + goto BAD; + } + } else { + p = (char *) default_path; + } + + plen = strlen(path); + if (plen > (FILENAME_MAX - 1)) { + ALL_TOO_LONG: + __set_errno(ENAMETOOLONG); + return -1; + } + len = (FILENAME_MAX - 1) - plen; + + buf = EXEC_ALLOC(FILENAME_MAX, size, EXEC_FUNC_EXECVP); + { + int seen_small = 0; + s0 = buf + len; + memcpy(s0, path, plen+1); + + do { + s = s0; + e = strchrnul(p, ':'); + if (e > p) { + plen = e - p; + if (e[-1] != '/') { + ++plen; + } + if (plen > len) { + goto NEXT; + } + s -= plen; + memcpy(s, p, plen); + s[plen-1] = '/'; + } + + execve(s, argv, __environ); + + seen_small = 1; + + if (errno == ENOEXEC) { + path = s; + goto RUN_BIN_SH; + } + + NEXT: + if (!*e) { + if (!seen_small) { + goto ALL_TOO_LONG; + } + break; + } + p = e + 1; + } while (1); + } + } + + EXEC_FREE(buf, size); + + return -1; +} +libc_hidden_def(execvp) + +#endif +/**********************************************************************/ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/execl.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/execl.c new file mode 100644 index 00000000..176b18bc --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/execl.c @@ -0,0 +1,8 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_execl +#include "exec.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/execle.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/execle.c new file mode 100644 index 00000000..05dd3a02 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/execle.c @@ -0,0 +1,8 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_execle +#include "exec.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/execlp.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/execlp.c new file mode 100644 index 00000000..b7e615d7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/execlp.c @@ -0,0 +1,8 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_execlp +#include "exec.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/execv.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/execv.c new file mode 100644 index 00000000..25030428 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/execv.c @@ -0,0 +1,8 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_execv +#include "exec.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/execvp.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/execvp.c new file mode 100644 index 00000000..9fc025fc --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/execvp.c @@ -0,0 +1,8 @@ +/* Copyright (C) 2004 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define L_execvp +#include "exec.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/fpathconf.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/fpathconf.c new file mode 100644 index 00000000..02b4445a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/fpathconf.c @@ -0,0 +1,253 @@ +/* fpathconf -- adjusted for busybox + Copyright (C) 1991,95,96,98,99,2000,2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include +#include + + +#ifndef __USE_FILE_OFFSET64 +extern int fstatfs (int __fildes, struct statfs *__buf) + __THROW __nonnull ((2)); +#else +# ifdef __REDIRECT_NTH + extern int __REDIRECT_NTH (fstatfs, (int __fildes, struct statfs *__buf), + fstatfs64) __nonnull ((2)); +# else +# define fstatfs fstatfs64 +# endif +#endif + +extern __typeof(fstatfs) __libc_fstatfs; + +/* The Linux kernel headers mention this as a kind of generic value. */ +#define LINUX_LINK_MAX 127 + + +/* Get file-specific information about descriptor FD. */ +long int fpathconf(int fd, int name) +{ + if (fd < 0) + { + __set_errno (EBADF); + return -1; + } + + if (name == _PC_LINK_MAX) + { + /* Cut some corners */ +#if 0 + struct statfs fsbuf; + + /* Determine the filesystem type. */ + if (__libc_fstatfs (fd, &fsbuf) < 0) + { + if (errno == ENOSYS) + /* not possible, return the default value. */ + return LINUX_LINK_MAX; + + /* Some error occured. */ + return -1; + } + + switch (fsbuf.f_type) + { + case EXT2_SUPER_MAGIC: + return EXT2_LINK_MAX; + + case MINIX_SUPER_MAGIC: + case MINIX_SUPER_MAGIC2: + return MINIX_LINK_MAX; + + case MINIX2_SUPER_MAGIC: + case MINIX2_SUPER_MAGIC2: + return MINIX2_LINK_MAX; + + case XENIX_SUPER_MAGIC: + return XENIX_LINK_MAX; + + case SYSV4_SUPER_MAGIC: + case SYSV2_SUPER_MAGIC: + return SYSV_LINK_MAX; + + case COH_SUPER_MAGIC: + return COH_LINK_MAX; + + case UFS_MAGIC: + case UFS_CIGAM: + return UFS_LINK_MAX; + + case REISERFS_SUPER_MAGIC: + return REISERFS_LINK_MAX; + + default: + return LINUX_LINK_MAX; + } +#else + return LINUX_LINK_MAX; +#endif + } + + switch (name) + { + default: + __set_errno (EINVAL); + return -1; + + case _PC_MAX_CANON: +#ifdef MAX_CANON + return MAX_CANON; +#else + return -1; +#endif + + case _PC_MAX_INPUT: +#ifdef MAX_INPUT + return MAX_INPUT; +#else + return -1; +#endif + + case _PC_NAME_MAX: +#ifdef NAME_MAX + { + struct statfs buf; + int save_errno = errno; + + if (__libc_fstatfs (fd, &buf) < 0) + { + if (errno == ENOSYS) + { + errno = save_errno; + return NAME_MAX; + } + return -1; + } + else + { +#ifdef _STATFS_F_NAMELEN + return buf.f_namelen; +#else +# ifdef _STATFS_F_NAME_MAX + return buf.f_name_max; +# else + return NAME_MAX; +# endif +#endif + } + } +#else + return -1; +#endif + + case _PC_PATH_MAX: +#ifdef PATH_MAX + return PATH_MAX; +#else + return -1; +#endif + + case _PC_PIPE_BUF: +#ifdef PIPE_BUF + return PIPE_BUF; +#else + return -1; +#endif + + case _PC_CHOWN_RESTRICTED: +#ifdef _POSIX_CHOWN_RESTRICTED + return _POSIX_CHOWN_RESTRICTED; +#else + return -1; +#endif + + case _PC_NO_TRUNC: +#ifdef _POSIX_NO_TRUNC + return _POSIX_NO_TRUNC; +#else + return -1; +#endif + + case _PC_VDISABLE: +#ifdef _POSIX_VDISABLE + return _POSIX_VDISABLE; +#else + return -1; +#endif + + case _PC_SYNC_IO: +#ifdef _POSIX_SYNC_IO + return _POSIX_SYNC_IO; +#else + return -1; +#endif + + case _PC_ASYNC_IO: +#if defined _POSIX_ASYNC_IO && defined __UCLIBC_HAS_LFS__ + { + /* AIO is only allowed on regular files and block devices. */ + struct stat st; + + if (fstat (fd, &st) < 0 || (! S_ISREG (st.st_mode) && ! S_ISBLK (st.st_mode))) + return -1; + else + return 1; + } +#else + return -1; +#endif + + case _PC_PRIO_IO: +#ifdef _POSIX_PRIO_IO + return _POSIX_PRIO_IO; +#else + return -1; +#endif + + case _PC_SOCK_MAXBUF: +#ifdef SOCK_MAXBUF + return SOCK_MAXBUF; +#else + return -1; +#endif + + case _PC_FILESIZEBITS: +#ifdef FILESIZEBITS + return FILESIZEBITS; +#else + /* We let platforms with larger file sizes overwrite this value. */ + return 32; +#endif + + /* Be lazy -- skip these */ + case _PC_REC_INCR_XFER_SIZE: + case _PC_REC_MAX_XFER_SIZE: + case _PC_REC_MIN_XFER_SIZE: + case _PC_REC_XFER_ALIGN: + case _PC_ALLOC_SIZE_MIN: + case _PC_SYMLINK_MAX: + return -1; + } + +} + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/getlogin.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/getlogin.c new file mode 100644 index 00000000..b855e50a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/getlogin.c @@ -0,0 +1,45 @@ +/* vi: set sw=4 ts=4: */ +/* + * getlogin for uClibc + * Copyright (C) 2000-2006 by Erik Andersen + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include + + +/* uClibc makes it policy to not mess with the utmp file whenever + * possible, since I consider utmp a complete waste of time. Since + * getlogin() should never be used for security purposes, we kindly let + * the user specify whatever they want via the LOGNAME environment + * variable, or we return NULL if getenv() fails to find anything */ + +char * getlogin(void) +{ + return (getenv("LOGNAME")); +} +libc_hidden_def(getlogin) + +int getlogin_r(char *name, size_t len) +{ + char * foo = getenv("LOGNAME"); + + if (! foo) + return -1; + + strncpy(name, foo, len); + name[len-1] = '\0'; + return 0; +} + +char *cuserid(char *s) +{ + char *name = getlogin(); + if (s) { + return(strcpy(s, name ? name : "")); + } + return name; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/getopt-susv3.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/getopt-susv3.c new file mode 100644 index 00000000..d7b8d0dc --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/getopt-susv3.c @@ -0,0 +1,123 @@ +/* Copyright (C) 2003 Manuel Novoa III + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION! + * + * Besides uClibc, I'm using this code in my libc for elks, which is + * a 16-bit environment with a fairly limited compiler. It would make + * things much easier for me if this file isn't modified unnecessarily. + * In particular, please put any new or replacement functions somewhere + * else, and modify the makefile to use your version instead. + * Thanks. Manuel + * + * ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION! */ + +/* Sep 7, 2003 + * Initial version of a SUSv3 compliant getopt(). + */ + +#include +#include +#include +#include + + +#ifdef __UCLIBC_MJN3_ONLY__ +#warning TODO: Enable gettext awareness. +#endif /* __UCLIBC_MJN3_ONLY__ */ + +#undef _ +#define _(X) X + +#ifdef __BCC__ +static const char missing[] = "option requires an argument"; +static const char illegal[] = "illegal option"; +#else +static const char missing[] = "%s: option requires an argument -- %c\n"; +static const char illegal[] = "%s: illegal option -- %c\n"; +#endif + +int opterr = 1; +int optind = 1; +int optopt = 0; +char *optarg = NULL; + +int getopt(int argc, char * const argv[], const char *optstring) +{ + static const char *o; /* multi opt position */ + register const char *p; + register const char *s; + int retval = -1; + + optopt = 0; + optarg = NULL; + + if (!o) { /* Not in a multi-option arg. */ + if ((optind >= argc) /* No more args? */ + || ((p = argv[optind]) == NULL) /* Missing? */ + || (*p != '-') /* Not an option? */ + || (!*++p) /* "-" case? */ + ) { + goto DONE; + } + if ((*p == '-') && (p[1] == 0)) { /* "--" case. */ +/* ++optind; */ +/* goto DONE; */ + goto NEXTOPT; /* Less code generated... */ + } + o = p; + } + +#ifdef __BCC__ + p = o; /* Sigh... Help out bcc. */ +#define o p +#endif + retval = (unsigned char) *o; /* Avoid problems for char val of -1. */ + + if ((*o == ':') || !(s = strchr(optstring, *o))) { /* Illegal option? */ + s = illegal; + retval = '?'; + goto BAD; + } + + if (s[1] == ':') { /* Option takes an arg? */ + if (o[1]) { /* No space between option and arg? */ + optarg = (char *)(o + 1); + goto NEXTOPT; + } + + if (optind + 1 < argc) { /* Space between option and arg? */ + optarg = argv[++optind]; + } else { /* Out of args! */ + s = missing; + retval = ':'; + BAD: + optopt = *o; + if (*optstring != ':') { + retval = '?'; + if (opterr) { +#ifdef __BCC__ + fprintf(stderr, "%s: %s -- %c\n", argv[0], s, *o); +#else + fprintf(stderr, _(s), argv[0], *o); +#endif + } + } + } + } + +#ifdef __BCC__ +#undef o +#endif + + if (!*++o) { + NEXTOPT: + o = NULL; + ++optind; + } + DONE: + return retval; +} +libc_hidden_def(getopt) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/getopt.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/getopt.c new file mode 100644 index 00000000..f4c11309 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/getopt.c @@ -0,0 +1,1198 @@ +/* Getopt for GNU. + NOTE: getopt is now part of the C library, so if you don't know what + "Keep this file name-space clean" means, talk to drepper@gnu.org + before changing it! + Copyright (C) 1987,88,89,90,91,92,93,94,95,96,98,99,2000,2001,2002,2003,2004 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * Modified for uClibc by Manuel Novoa III on 1/5/01. + * Modified once again for uClibc by Erik Andersen 8/7/02 + */ + +/* This tells Alpha OSF/1 not to define a getopt prototype in . + Ditto for AIX 3.2 and . */ +#ifndef _NO_PROTO +# define _NO_PROTO +#endif + +#ifdef HAVE_CONFIG_H +# include +#endif + +#define __FORCE_GLIBC +#include + +#include + +/* Comment out all this code if we are using the GNU C Library, and are not + actually compiling the library itself. This code is part of the GNU C + Library, but also included in many other GNU distributions. Compiling + and linking in this code is a waste when using the GNU C library + (especially if it is a shared library). Rather than having every GNU + program understand `configure --with-gnu-libc' and omit the object files, + it is simpler to just do this in the source for each such file. */ + +#define GETOPT_INTERFACE_VERSION 2 +#if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2 +# include +# if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION +# define ELIDE_CODE +# endif +#endif + +#ifndef ELIDE_CODE + + +/* This needs to come after some library #include + to get __GNU_LIBRARY__ defined. */ +#ifdef __GNU_LIBRARY__ +/* Don't include stdlib.h for non-GNU C libraries because some of them + contain conflicting prototypes for getopt. */ +# include +# include +#endif /* GNU C library. */ + +#include + +#ifdef VMS +# include +#endif + +#if !defined __UCLIBC__ && !defined __UCLIBC_HAS_GETTEXT_AWARENESS__ +#ifdef _LIBC +# include +#else +# include "gettext.h" +# define _(msgid) gettext (msgid) +#endif +#else +#ifdef __UCLIBC_MJN3_ONLY__ +#warning TODO: Enable gettext awareness. +#endif /* __UCLIBC_MJN3_ONLY__ */ + +#undef _ +#define _(X) X + +#endif + +/* Treat '-W foo' the same as the long option '--foo', + * disabled for the moment since it costs about 2k... */ +#undef SPECIAL_TREATMENT_FOR_W + +#if defined _LIBC && defined USE_IN_LIBIO +# include +#endif + +#ifndef attribute_hidden +# define attribute_hidden +#endif + +/* This version of `getopt' appears to the caller like standard Unix `getopt' + but it behaves differently for the user, since it allows the user + to intersperse the options with the other arguments. + + As `getopt' works, it permutes the elements of ARGV so that, + when it is done, all the options precede everything else. Thus + all application programs are extended to handle flexible argument order. + + Setting the environment variable POSIXLY_CORRECT disables permutation. + Then the behavior is completely standard. + + GNU application programs can use a third alternative mode in which + they can distinguish the relative order of options and other arguments. */ + +#include +#include "getopt_int.h" + + +/* For communication from `getopt' to the caller. + When `getopt' finds an option that takes an argument, + the argument value is returned here. + Also, when `ordering' is RETURN_IN_ORDER, + each non-option ARGV-element is returned here. */ + +char *optarg; + +/* Index in ARGV of the next element to be scanned. + This is used for communication to and from the caller + and for communication between successive calls to `getopt'. + + On entry to `getopt', zero means this is the first call; initialize. + + When `getopt' returns -1, this is the index of the first of the + non-option elements that the caller should itself scan. + + Otherwise, `optind' communicates from one call to the next + how much of ARGV has been scanned so far. */ + +/* 1003.2 says this must be 1 before any call. */ +int optind = 1; + +/* Callers store zero here to inhibit the error message + for unrecognized options. */ + +int opterr = 1; + +/* Set to an option character which was unrecognized. + This must be initialized on some systems to avoid linking in the + system's own getopt implementation. */ + +int optopt = '?'; + +/* Keep a global copy of all internal members of getopt_data. */ + +static struct _getopt_data getopt_data; + + +#ifndef __GNU_LIBRARY__ + +/* Avoid depending on library functions or files + whose names are inconsistent. */ + +#ifndef getenv +extern char *getenv (); +#endif + +#endif /* not __GNU_LIBRARY__ */ + +#ifdef _LIBC +/* Stored original parameters. + XXX This is no good solution. We should rather copy the args so + that we can compare them later. But we must not use malloc(3). */ +# ifdef USE_NONOPTION_FLAGS +extern int __libc_argc; +extern char **__libc_argv; + +/* Bash 2.0 gives us an environment variable containing flags + indicating ARGV elements that should not be considered arguments. */ + +/* Defined in getopt_init.c */ +extern char *__getopt_nonoption_flags; + +# define SWAP_FLAGS(ch1, ch2) \ + if (d->__nonoption_flags_len > 0) \ + { \ + char __tmp = __getopt_nonoption_flags[ch1]; \ + __getopt_nonoption_flags[ch1] = __getopt_nonoption_flags[ch2]; \ + __getopt_nonoption_flags[ch2] = __tmp; \ + } +# else +# define SWAP_FLAGS(ch1, ch2) +# endif +#else /* !_LIBC */ +# define SWAP_FLAGS(ch1, ch2) +#endif /* _LIBC */ + +/* Exchange two adjacent subsequences of ARGV. + One subsequence is elements [first_nonopt,last_nonopt) + which contains all the non-options that have been skipped so far. + The other is elements [last_nonopt,optind), which contains all + the options processed since those non-options were skipped. + + `first_nonopt' and `last_nonopt' are relocated so that they describe + the new indices of the non-options in ARGV after they are moved. */ + +static void +exchange (char **argv, struct _getopt_data *d) +{ + int bottom = d->__first_nonopt; + int middle = d->__last_nonopt; + int top = d->optind; + char *tem; + + /* Exchange the shorter segment with the far end of the longer segment. + That puts the shorter segment into the right place. + It leaves the longer segment in the right place overall, + but it consists of two parts that need to be swapped next. */ + +#if defined _LIBC && defined USE_NONOPTION_FLAGS + /* First make sure the handling of the `__getopt_nonoption_flags' + string can work normally. Our top argument must be in the range + of the string. */ + if (d->__nonoption_flags_len > 0 && top >= d->__nonoption_flags_max_len) + { + /* We must extend the array. The user plays games with us and + presents new arguments. */ + char *new_str = malloc (top + 1); + if (new_str == NULL) + d->__nonoption_flags_len = d->__nonoption_flags_max_len = 0; + else + { + memset (__mempcpy (new_str, __getopt_nonoption_flags, + d->__nonoption_flags_max_len), + '\0', top + 1 - d->__nonoption_flags_max_len); + d->__nonoption_flags_max_len = top + 1; + __getopt_nonoption_flags = new_str; + } + } +#endif + + while (top > middle && middle > bottom) + { + if (top - middle > middle - bottom) + { + /* Bottom segment is the short one. */ + int len = middle - bottom; + register int i; + + /* Swap it with the top part of the top segment. */ + for (i = 0; i < len; i++) + { + tem = argv[bottom + i]; + argv[bottom + i] = argv[top - (middle - bottom) + i]; + argv[top - (middle - bottom) + i] = tem; + SWAP_FLAGS (bottom + i, top - (middle - bottom) + i); + } + /* Exclude the moved bottom segment from further swapping. */ + top -= len; + } + else + { + /* Top segment is the short one. */ + int len = top - middle; + register int i; + + /* Swap it with the bottom part of the bottom segment. */ + for (i = 0; i < len; i++) + { + tem = argv[bottom + i]; + argv[bottom + i] = argv[middle + i]; + argv[middle + i] = tem; + SWAP_FLAGS (bottom + i, middle + i); + } + /* Exclude the moved top segment from further swapping. */ + bottom += len; + } + } + + /* Update records for the slots the non-options now occupy. */ + + d->__first_nonopt += (d->optind - d->__last_nonopt); + d->__last_nonopt = d->optind; +} + +/* Initialize the internal data when the first call is made. */ + +static const char * +_getopt_initialize (attribute_unused int argc, attribute_unused char *const *argv, const char *optstring, + struct _getopt_data *d) +{ + /* Start processing options with ARGV-element 1 (since ARGV-element 0 + is the program name); the sequence of previously skipped + non-option ARGV-elements is empty. */ + + d->__first_nonopt = d->__last_nonopt = d->optind; + + d->__nextchar = NULL; + + d->__posixly_correct = !!getenv ("POSIXLY_CORRECT"); + + /* Determine how to handle the ordering of options and nonoptions. */ + + if (optstring[0] == '-') + { + d->__ordering = RETURN_IN_ORDER; + ++optstring; + } + else if (optstring[0] == '+') + { + d->__ordering = REQUIRE_ORDER; + ++optstring; + } + else if (d->__posixly_correct) + d->__ordering = REQUIRE_ORDER; + else + d->__ordering = PERMUTE; + +#if defined _LIBC && defined USE_NONOPTION_FLAGS + if (!d->__posixly_correct + && argc == __libc_argc && argv == __libc_argv) + { + if (d->__nonoption_flags_max_len == 0) + { + if (__getopt_nonoption_flags == NULL + || __getopt_nonoption_flags[0] == '\0') + d->__nonoption_flags_max_len = -1; + else + { + const char *orig_str = __getopt_nonoption_flags; + int len = d->__nonoption_flags_max_len = strlen (orig_str); + if (d->__nonoption_flags_max_len < argc) + d->__nonoption_flags_max_len = argc; + __getopt_nonoption_flags = + (char *) malloc (d->__nonoption_flags_max_len); + if (__getopt_nonoption_flags == NULL) + d->__nonoption_flags_max_len = -1; + else + memset (__mempcpy (__getopt_nonoption_flags, orig_str, len), + '\0', d->__nonoption_flags_max_len - len); + } + } + d->__nonoption_flags_len = d->__nonoption_flags_max_len; + } + else + d->__nonoption_flags_len = 0; +#endif + + return optstring; +} + +/* Scan elements of ARGV (whose length is ARGC) for option characters + given in OPTSTRING. + + If an element of ARGV starts with '-', and is not exactly "-" or "--", + then it is an option element. The characters of this element + (aside from the initial '-') are option characters. If `getopt' + is called repeatedly, it returns successively each of the option characters + from each of the option elements. + + If `getopt' finds another option character, it returns that character, + updating `optind' and `nextchar' so that the next call to `getopt' can + resume the scan with the following option character or ARGV-element. + + If there are no more option characters, `getopt' returns -1. + Then `optind' is the index in ARGV of the first ARGV-element + that is not an option. (The ARGV-elements have been permuted + so that those that are not options now come last.) + + OPTSTRING is a string containing the legitimate option characters. + If an option character is seen that is not listed in OPTSTRING, + return '?' after printing an error message. If you set `opterr' to + zero, the error message is suppressed but we still return '?'. + + If a char in OPTSTRING is followed by a colon, that means it wants an arg, + so the following text in the same ARGV-element, or the text of the following + ARGV-element, is returned in `optarg'. Two colons mean an option that + wants an optional arg; if there is text in the current ARGV-element, + it is returned in `optarg', otherwise `optarg' is set to zero. + + If OPTSTRING starts with `-' or `+', it requests different methods of + handling the non-option ARGV-elements. + See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above. + + Long-named options begin with `--' instead of `-'. + Their names may be abbreviated as long as the abbreviation is unique + or is an exact match for some defined option. If they have an + argument, it follows the option name in the same ARGV-element, separated + from the option name by a `=', or else the in next ARGV-element. + When `getopt' finds a long-named option, it returns 0 if that option's + `flag' field is nonzero, the value of the option's `val' field + if the `flag' field is zero. + + The elements of ARGV aren't really const, because we permute them. + But we pretend they're const in the prototype to be compatible + with other systems. + + LONGOPTS is a vector of `struct option' terminated by an + element containing a name which is zero. + + LONGIND returns the index in LONGOPT of the long-named option found. + It is only valid when a long-named option has been found by the most + recent call. + + If LONG_ONLY is nonzero, '-' as well as '--' can introduce + long-named options. */ + +static int +_getopt_internal_r (int argc, char *const *argv, const char *optstring, + const struct option *longopts, int *longind, + int long_only, struct _getopt_data *d) +{ + int print_errors = d->opterr; + if (optstring[0] == ':') + print_errors = 0; + + if (argc < 1) + return -1; + + d->optarg = NULL; + + if (d->optind == 0 || !d->__initialized) + { + if (d->optind == 0) + d->optind = 1; /* Don't scan ARGV[0], the program name. */ + optstring = _getopt_initialize (argc, argv, optstring, d); + d->__initialized = 1; + } + + /* Test whether ARGV[optind] points to a non-option argument. + Either it does not have option syntax, or there is an environment flag + from the shell indicating it is not an option. The later information + is only used when the used in the GNU libc. */ +#if defined _LIBC && defined USE_NONOPTION_FLAGS +# define NONOPTION_P (argv[d->optind][0] != '-' || argv[d->optind][1] == '\0' \ + || (d->optind < d->__nonoption_flags_len \ + && __getopt_nonoption_flags[d->optind] == '1')) +#else +# define NONOPTION_P (argv[d->optind][0] != '-' || argv[d->optind][1] == '\0') +#endif + + if (d->__nextchar == NULL || *d->__nextchar == '\0') + { + /* Advance to the next ARGV-element. */ + + /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been + moved back by the user (who may also have changed the arguments). */ + if (d->__last_nonopt > d->optind) + d->__last_nonopt = d->optind; + if (d->__first_nonopt > d->optind) + d->__first_nonopt = d->optind; + + if (d->__ordering == PERMUTE) + { + /* If we have just processed some options following some non-options, + exchange them so that the options come first. */ + + if (d->__first_nonopt != d->__last_nonopt + && d->__last_nonopt != d->optind) + exchange ((char **) argv, d); + else if (d->__last_nonopt != d->optind) + d->__first_nonopt = d->optind; + + /* Skip any additional non-options + and extend the range of non-options previously skipped. */ + + while (d->optind < argc && NONOPTION_P) + d->optind++; + d->__last_nonopt = d->optind; + } + + /* The special ARGV-element `--' means premature end of options. + Skip it like a null option, + then exchange with previous non-options as if it were an option, + then skip everything else like a non-option. */ + + if (d->optind != argc && !strcmp (argv[d->optind], "--")) + { + d->optind++; + + if (d->__first_nonopt != d->__last_nonopt + && d->__last_nonopt != d->optind) + exchange ((char **) argv, d); + else if (d->__first_nonopt == d->__last_nonopt) + d->__first_nonopt = d->optind; + d->__last_nonopt = argc; + + d->optind = argc; + } + + /* If we have done all the ARGV-elements, stop the scan + and back over any non-options that we skipped and permuted. */ + + if (d->optind == argc) + { + /* Set the next-arg-index to point at the non-options + that we previously skipped, so the caller will digest them. */ + if (d->__first_nonopt != d->__last_nonopt) + d->optind = d->__first_nonopt; + return -1; + } + + /* If we have come to a non-option and did not permute it, + either stop the scan or describe it to the caller and pass it by. */ + + if (NONOPTION_P) + { + if (d->__ordering == REQUIRE_ORDER) + return -1; + d->optarg = argv[d->optind++]; + return 1; + } + + /* We have found another option-ARGV-element. + Skip the initial punctuation. */ + + d->__nextchar = (argv[d->optind] + 1 + + (longopts != NULL && argv[d->optind][1] == '-')); + } + + /* Decode the current option-ARGV-element. */ + + /* Check whether the ARGV-element is a long option. + + If long_only and the ARGV-element has the form "-f", where f is + a valid short option, don't consider it an abbreviated form of + a long option that starts with f. Otherwise there would be no + way to give the -f short option. + + On the other hand, if there's a long option "fubar" and + the ARGV-element is "-fu", do consider that an abbreviation of + the long option, just like "--fu", and not "-f" with arg "u". + + This distinction seems to be the most useful approach. */ + + if (longopts != NULL + && (argv[d->optind][1] == '-' + || (long_only && (argv[d->optind][2] + || !strchr (optstring, argv[d->optind][1]))))) + { + char *nameend; + const struct option *p; + const struct option *pfound = NULL; + int exact = 0; + int ambig = 0; + int indfound = -1; + int option_index; + + for (nameend = d->__nextchar; *nameend && *nameend != '='; nameend++) + /* Do nothing. */ ; + + /* Test all long options for either exact match + or abbreviated matches. */ + for (p = longopts, option_index = 0; p->name; p++, option_index++) + if (!strncmp (p->name, d->__nextchar, nameend - d->__nextchar)) + { + if ((unsigned int) (nameend - d->__nextchar) + == (unsigned int) strlen (p->name)) + { + /* Exact match found. */ + pfound = p; + indfound = option_index; + exact = 1; + break; + } + else if (pfound == NULL) + { + /* First nonexact match found. */ + pfound = p; + indfound = option_index; + } + else if (long_only + || pfound->has_arg != p->has_arg + || pfound->flag != p->flag + || pfound->val != p->val) + /* Second or later nonexact match found. */ + ambig = 1; + } + + if (ambig && !exact) + { + if (print_errors) + { +#if defined _LIBC && defined USE_IN_LIBIO + char *buf; + + if (__asprintf (&buf, _("%s: option `%s' is ambiguous\n"), + argv[0], argv[d->optind]) >= 0) + { + _IO_flockfile (stderr); + + int old_flags2 = ((_IO_FILE *) stderr)->_flags2; + ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; + + __fxprintf (NULL, "%s", buf); + + ((_IO_FILE *) stderr)->_flags2 = old_flags2; + _IO_funlockfile (stderr); + + free (buf); + } +#else + fprintf (stderr, _("%s: option `%s' is ambiguous\n"), + argv[0], argv[d->optind]); +#endif + } + d->__nextchar += strlen (d->__nextchar); + d->optind++; + d->optopt = 0; + return '?'; + } + + if (pfound != NULL) + { + option_index = indfound; + d->optind++; + if (*nameend) + { + /* Don't test has_arg with >, because some C compilers don't + allow it to be used on enums. */ + if (pfound->has_arg) + d->optarg = nameend + 1; + else + { + if (print_errors) + { +#if defined _LIBC && defined USE_IN_LIBIO + char *buf; + int n; +#endif + + if (argv[d->optind - 1][1] == '-') + { + /* --option */ +#if defined _LIBC && defined USE_IN_LIBIO + n = __asprintf (&buf, _("\ +%s: option `--%s' doesn't allow an argument\n"), + argv[0], pfound->name); +#else + fprintf (stderr, _("\ +%s: option `--%s' doesn't allow an argument\n"), + argv[0], pfound->name); +#endif + } + else + { + /* +option or -option */ +#if defined _LIBC && defined USE_IN_LIBIO + n = __asprintf (&buf, _("\ +%s: option `%c%s' doesn't allow an argument\n"), + argv[0], argv[d->optind - 1][0], + pfound->name); +#else + fprintf (stderr, _("\ +%s: option `%c%s' doesn't allow an argument\n"), + argv[0], argv[d->optind - 1][0], + pfound->name); +#endif + } + +#if defined _LIBC && defined USE_IN_LIBIO + if (n >= 0) + { + _IO_flockfile (stderr); + + int old_flags2 = ((_IO_FILE *) stderr)->_flags2; + ((_IO_FILE *) stderr)->_flags2 + |= _IO_FLAGS2_NOTCANCEL; + + __fxprintf (NULL, "%s", buf); + + ((_IO_FILE *) stderr)->_flags2 = old_flags2; + _IO_funlockfile (stderr); + + free (buf); + } +#endif + } + + d->__nextchar += strlen (d->__nextchar); + + d->optopt = pfound->val; + return '?'; + } + } + else if (pfound->has_arg == 1) + { + if (d->optind < argc) + d->optarg = argv[d->optind++]; + else + { + if (print_errors) + { +#if defined _LIBC && defined USE_IN_LIBIO + char *buf; + + if (__asprintf (&buf, _("\ +%s: option `%s' requires an argument\n"), + argv[0], argv[d->optind - 1]) >= 0) + { + _IO_flockfile (stderr); + + int old_flags2 = ((_IO_FILE *) stderr)->_flags2; + ((_IO_FILE *) stderr)->_flags2 + |= _IO_FLAGS2_NOTCANCEL; + + __fxprintf (NULL, "%s", buf); + + ((_IO_FILE *) stderr)->_flags2 = old_flags2; + _IO_funlockfile (stderr); + + free (buf); + } +#else + fprintf (stderr, + _("%s: option `%s' requires an argument\n"), + argv[0], argv[d->optind - 1]); +#endif + } + d->__nextchar += strlen (d->__nextchar); + d->optopt = pfound->val; + return optstring[0] == ':' ? ':' : '?'; + } + } + d->__nextchar += strlen (d->__nextchar); + if (longind != NULL) + *longind = option_index; + if (pfound->flag) + { + *(pfound->flag) = pfound->val; + return 0; + } + return pfound->val; + } + + /* Can't find it as a long option. If this is not getopt_long_only, + or the option starts with '--' or is not a valid short + option, then it's an error. + Otherwise interpret it as a short option. */ + if (!long_only || argv[d->optind][1] == '-' + || strchr (optstring, *d->__nextchar) == NULL) + { + if (print_errors) + { +#if defined _LIBC && defined USE_IN_LIBIO + char *buf; + int n; +#endif + + if (argv[d->optind][1] == '-') + { + /* --option */ +#if defined _LIBC && defined USE_IN_LIBIO + n = __asprintf (&buf, _("%s: unrecognized option `--%s'\n"), + argv[0], d->__nextchar); +#else + fprintf (stderr, _("%s: unrecognized option `--%s'\n"), + argv[0], d->__nextchar); +#endif + } + else + { + /* +option or -option */ +#if defined _LIBC && defined USE_IN_LIBIO + n = __asprintf (&buf, _("%s: unrecognized option `%c%s'\n"), + argv[0], argv[d->optind][0], d->__nextchar); +#else + fprintf (stderr, _("%s: unrecognized option `%c%s'\n"), + argv[0], argv[d->optind][0], d->__nextchar); +#endif + } + +#if defined _LIBC && defined USE_IN_LIBIO + if (n >= 0) + { + _IO_flockfile (stderr); + + int old_flags2 = ((_IO_FILE *) stderr)->_flags2; + ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; + + __fxprintf (NULL, "%s", buf); + + ((_IO_FILE *) stderr)->_flags2 = old_flags2; + _IO_funlockfile (stderr); + + free (buf); + } +#endif + } + d->__nextchar = (char *) ""; + d->optind++; + d->optopt = 0; + return '?'; + } + } + + /* Look at and handle the next short option-character. */ + + { + char c = *d->__nextchar++; + char *temp = strchr (optstring, c); + + /* Increment `optind' when we start to process its last character. */ + if (*d->__nextchar == '\0') + ++d->optind; + + if (temp == NULL || c == ':') + { + if (print_errors) + { +#if defined _LIBC && defined USE_IN_LIBIO + char *buf; + int n; +#endif + + if (d->__posixly_correct) + { + /* 1003.2 specifies the format of this message. */ +#if defined _LIBC && defined USE_IN_LIBIO + n = __asprintf (&buf, _("%s: illegal option -- %c\n"), + argv[0], c); +#else + fprintf (stderr, _("%s: illegal option -- %c\n"), argv[0], c); +#endif + } + else + { +#if defined _LIBC && defined USE_IN_LIBIO + n = __asprintf (&buf, _("%s: invalid option -- %c\n"), + argv[0], c); +#else + fprintf (stderr, _("%s: invalid option -- %c\n"), argv[0], c); +#endif + } + +#if defined _LIBC && defined USE_IN_LIBIO + if (n >= 0) + { + _IO_flockfile (stderr); + + int old_flags2 = ((_IO_FILE *) stderr)->_flags2; + ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; + + __fxprintf (NULL, "%s", buf); + + ((_IO_FILE *) stderr)->_flags2 = old_flags2; + _IO_funlockfile (stderr); + + free (buf); + } +#endif + } + d->optopt = c; + return '?'; + } +#ifdef SPECIAL_TREATMENT_FOR_W + /* Convenience. Treat POSIX -W foo same as long option --foo */ + if (temp[0] == 'W' && temp[1] == ';') + { + char *nameend; + const struct option *p; + const struct option *pfound = NULL; + int exact = 0; + int ambig = 0; + int indfound = 0; + int option_index; + + /* This is an option that requires an argument. */ + if (*d->__nextchar != '\0') + { + d->optarg = d->__nextchar; + /* If we end this ARGV-element by taking the rest as an arg, + we must advance to the next element now. */ + d->optind++; + } + else if (d->optind == argc) + { + if (print_errors) + { + /* 1003.2 specifies the format of this message. */ +#if defined _LIBC && defined USE_IN_LIBIO + char *buf; + + if (__asprintf (&buf, + _("%s: option requires an argument -- %c\n"), + argv[0], c) >= 0) + { + _IO_flockfile (stderr); + + int old_flags2 = ((_IO_FILE *) stderr)->_flags2; + ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; + + __fxprintf (NULL, "%s", buf); + + ((_IO_FILE *) stderr)->_flags2 = old_flags2; + _IO_funlockfile (stderr); + + free (buf); + } +#else + fprintf (stderr, _("%s: option requires an argument -- %c\n"), + argv[0], c); +#endif + } + d->optopt = c; + if (optstring[0] == ':') + c = ':'; + else + c = '?'; + return c; + } + else + /* We already incremented `d->optind' once; + increment it again when taking next ARGV-elt as argument. */ + d->optarg = argv[d->optind++]; + + /* optarg is now the argument, see if it's in the + table of longopts. */ + + for (d->__nextchar = nameend = d->optarg; *nameend && *nameend != '='; + nameend++) + /* Do nothing. */ ; + + /* Test all long options for either exact match + or abbreviated matches. */ + for (p = longopts, option_index = 0; p->name; p++, option_index++) + if (!strncmp (p->name, d->__nextchar, nameend - d->__nextchar)) + { + if ((unsigned int) (nameend - d->__nextchar) == strlen (p->name)) + { + /* Exact match found. */ + pfound = p; + indfound = option_index; + exact = 1; + break; + } + else if (pfound == NULL) + { + /* First nonexact match found. */ + pfound = p; + indfound = option_index; + } + else + /* Second or later nonexact match found. */ + ambig = 1; + } + if (ambig && !exact) + { + if (print_errors) + { +#if defined _LIBC && defined USE_IN_LIBIO + char *buf; + + if (__asprintf (&buf, _("%s: option `-W %s' is ambiguous\n"), + argv[0], argv[d->optind]) >= 0) + { + _IO_flockfile (stderr); + + int old_flags2 = ((_IO_FILE *) stderr)->_flags2; + ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; + + __fxprintf (NULL, "%s", buf); + + ((_IO_FILE *) stderr)->_flags2 = old_flags2; + _IO_funlockfile (stderr); + + free (buf); + } +#else + fprintf (stderr, _("%s: option `-W %s' is ambiguous\n"), + argv[0], argv[d->optind]); +#endif + } + d->__nextchar += strlen (d->__nextchar); + d->optind++; + return '?'; + } + if (pfound != NULL) + { + option_index = indfound; + if (*nameend) + { + /* Don't test has_arg with >, because some C compilers don't + allow it to be used on enums. */ + if (pfound->has_arg) + d->optarg = nameend + 1; + else + { + if (print_errors) + { +#if defined _LIBC && defined USE_IN_LIBIO + char *buf; + + if (__asprintf (&buf, _("\ +%s: option `-W %s' doesn't allow an argument\n"), + argv[0], pfound->name) >= 0) + { + _IO_flockfile (stderr); + + int old_flags2 = ((_IO_FILE *) stderr)->_flags2; + ((_IO_FILE *) stderr)->_flags2 + |= _IO_FLAGS2_NOTCANCEL; + + __fxprintf (NULL, "%s", buf); + + ((_IO_FILE *) stderr)->_flags2 = old_flags2; + _IO_funlockfile (stderr); + + free (buf); + } +#else + fprintf (stderr, _("\ +%s: option `-W %s' doesn't allow an argument\n"), + argv[0], pfound->name); +#endif + } + + d->__nextchar += strlen (d->__nextchar); + return '?'; + } + } + else if (pfound->has_arg == 1) + { + if (d->optind < argc) + d->optarg = argv[d->optind++]; + else + { + if (print_errors) + { +#if defined _LIBC && defined USE_IN_LIBIO + char *buf; + + if (__asprintf (&buf, _("\ +%s: option `%s' requires an argument\n"), + argv[0], argv[d->optind - 1]) >= 0) + { + _IO_flockfile (stderr); + + int old_flags2 = ((_IO_FILE *) stderr)->_flags2; + ((_IO_FILE *) stderr)->_flags2 + |= _IO_FLAGS2_NOTCANCEL; + + __fxprintf (NULL, "%s", buf); + + ((_IO_FILE *) stderr)->_flags2 = old_flags2; + _IO_funlockfile (stderr); + + free (buf); + } +#else + fprintf (stderr, + _("%s: option `%s' requires an argument\n"), + argv[0], argv[d->optind - 1]); +#endif + } + d->__nextchar += strlen (d->__nextchar); + return optstring[0] == ':' ? ':' : '?'; + } + } + d->__nextchar += strlen (d->__nextchar); + if (longind != NULL) + *longind = option_index; + if (pfound->flag) + { + *(pfound->flag) = pfound->val; + return 0; + } + return pfound->val; + } + d->__nextchar = NULL; + return 'W'; /* Let the application handle it. */ + } +#endif + if (temp[1] == ':') + { + if (temp[2] == ':') + { + /* This is an option that accepts an argument optionally. */ + if (*d->__nextchar != '\0') + { + d->optarg = d->__nextchar; + d->optind++; + } + else + d->optarg = NULL; + d->__nextchar = NULL; + } + else + { + /* This is an option that requires an argument. */ + if (*d->__nextchar != '\0') + { + d->optarg = d->__nextchar; + /* If we end this ARGV-element by taking the rest as an arg, + we must advance to the next element now. */ + d->optind++; + } + else if (d->optind == argc) + { + if (print_errors) + { + /* 1003.2 specifies the format of this message. */ +#if defined _LIBC && defined USE_IN_LIBIO + char *buf; + + if (__asprintf (&buf, _("\ +%s: option requires an argument -- %c\n"), + argv[0], c) >= 0) + { + _IO_flockfile (stderr); + + int old_flags2 = ((_IO_FILE *) stderr)->_flags2; + ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; + + __fxprintf (NULL, "%s", buf); + + ((_IO_FILE *) stderr)->_flags2 = old_flags2; + _IO_funlockfile (stderr); + + free (buf); + } +#else + fprintf (stderr, + _("%s: option requires an argument -- %c\n"), + argv[0], c); +#endif + } + d->optopt = c; + if (optstring[0] == ':') + c = ':'; + else + c = '?'; + } + else + /* We already incremented `optind' once; + increment it again when taking next ARGV-elt as argument. */ + d->optarg = argv[d->optind++]; + d->__nextchar = NULL; + } + } + return c; + } +} + +int +_getopt_internal (int argc, char *const *argv, const char *optstring, + const struct option *longopts, int *longind, int long_only) +{ + int result; + + getopt_data.optind = optind; + getopt_data.opterr = opterr; + + result = _getopt_internal_r (argc, argv, optstring, longopts, + longind, long_only, &getopt_data); + + optind = getopt_data.optind; + optarg = getopt_data.optarg; + optopt = getopt_data.optopt; + + return result; +} + +int +getopt (int argc, char *const *argv, const char *optstring) +{ + return _getopt_internal (argc, argv, optstring, + (const struct option *) 0, + (int *) 0, + 0); +} +libc_hidden_def(getopt) + +int +getopt_long (int argc, char *const *argv, const char *options, + const struct option *long_options, int *opt_index) +{ + return _getopt_internal (argc, argv, options, long_options, opt_index, 0); +} + +/* Like getopt_long, but '-' as well as '--' can indicate a long option. + If an option that starts with '-' (not '--') doesn't match a long option, + but does match a short option, it is parsed as a short option + instead. */ + +int +getopt_long_only (int argc, char *const *argv, const char *options, + const struct option *long_options, int *opt_index) +{ + return _getopt_internal (argc, argv, options, long_options, opt_index, 1); +} + +#endif /* Not ELIDE_CODE. */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/getopt_int.h b/l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/getopt_int.h new file mode 100644 index 00000000..a871785d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/getopt_int.h @@ -0,0 +1,134 @@ +/* Internal declarations for getopt. + Copyright (C) 1989-1994,1996-1999,2001,2003,2004 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _GETOPT_INT_H +#define _GETOPT_INT_H 1 + +extern int _getopt_internal (int ___argc, char *const *___argv, + const char *__shortopts, + const struct option *__longopts, int *__longind, + int __long_only) attribute_hidden; + + +/* Reentrant versions which can handle parsing multiple argument + vectors at the same time. */ + +/* For __ordering member */ +enum { + REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER +}; + +/* Data type for reentrant functions. */ + +struct _getopt_data +{ + /* These have exactly the same meaning as the corresponding global + variables, except that they are used for the reentrant + versions of getopt. */ + int optind; + int opterr; + char *optarg; + smalluint optopt; /* we store characters here, a byte is enough */ + + /* Internal members. */ + + /* True if the internal members have been initialized. */ + smallint __initialized; + + /* Describe how to deal with options that follow non-option ARGV-elements. + + If the caller did not specify anything, + the default is REQUIRE_ORDER if the environment variable + POSIXLY_CORRECT is defined, PERMUTE otherwise. + + REQUIRE_ORDER means don't recognize them as options; + stop option processing when the first non-option is seen. + This is what Unix does. + This mode of operation is selected by either setting the environment + variable POSIXLY_CORRECT, or using `+' as the first character + of the list of option characters. + + PERMUTE is the default. We permute the contents of ARGV as we + scan, so that eventually all the non-options are at the end. + This allows options to be given in any order, even with programs + that were not written to expect this. + + RETURN_IN_ORDER is an option available to programs that were + written to expect options and other ARGV-elements in any order + and that care about the ordering of the two. We describe each + non-option ARGV-element as if it were the argument of an option + with character code 1. Using `-' as the first character of the + list of option characters selects this mode of operation. + + The special argument `--' forces an end of option-scanning regardless + of the value of `ordering'. In the case of RETURN_IN_ORDER, only + `--' can cause `getopt' to return -1 with `optind' != ARGC. */ + smallint __ordering; + + /* If the POSIXLY_CORRECT environment variable is set. */ + smallint __posixly_correct; + + /* The next char to be scanned in the option-element + in which the last option character we returned was found. + This allows us to pick up the scan where we left off. + + If this is zero, or a null string, it means resume the scan + by advancing to the next ARGV-element. */ + char *__nextchar; + + + /* Handle permutation of arguments. */ + + /* Describe the part of ARGV that contains non-options that have + been skipped. `first_nonopt' is the index in ARGV of the first + of them; `last_nonopt' is the index after the last of them. */ + + int __first_nonopt; + int __last_nonopt; + +#if defined _LIBC && defined USE_NONOPTION_FLAGS + int __nonoption_flags_max_len; + int __nonoption_flags_len; +# endif +}; + +/* The initializer is necessary to set OPTIND and OPTERR to their + default values and to clear the initialization flag. */ +#define _GETOPT_DATA_INITIALIZER { 1, 1 } + +#if 0 /* first is static on uClibc, the others not used */ +extern int _getopt_internal_r (int ___argc, char *const *___argv, + const char *__shortopts, + const struct option *__longopts, int *__longind, + int __long_only, struct _getopt_data *__data); + +extern int _getopt_long_r (int ___argc, char *const *___argv, + const char *__shortopts, + const struct option *__longopts, int *__longind, + struct _getopt_data *__data); + +extern int _getopt_long_only_r (int ___argc, char *const *___argv, + const char *__shortopts, + const struct option *__longopts, + int *__longind, + struct _getopt_data *__data); +#endif + +#endif /* getopt_int.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/getopt_long-simple.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/getopt_long-simple.c new file mode 100644 index 00000000..47612dfe --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/getopt_long-simple.c @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2006 Rich Felker + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include + + +static int __getopt_long(int argc, char *const *argv, const char *optstring, const struct option *longopts, int *idx, int longonly) +{ + if (optind >= argc || !argv[optind] || argv[optind][0] != '-') return -1; + if ((longonly && argv[optind][1]) || + (argv[optind][1] == '-' && argv[optind][2])) + { + int i; + for (i=0; longopts[i].name; i++) { + const char *name = longopts[i].name; + char *opt = argv[optind]+2; + while (*name && *name++ == *opt++); + if (*name || (*opt && *opt != '=')) continue; + if (*opt == '=') { + if (!longopts[i].has_arg) continue; + optarg = opt+1; + } else { + if (longopts[i].has_arg == required_argument) { + if (!(optarg = argv[++optind])) + return ':'; + } else optarg = NULL; + } + optind++; + if (idx) *idx = i; + if (longopts[i].flag) { + *longopts[i].flag = longopts[i].val; + return 0; + } + return longopts[i].val; + } + if (argv[optind][1] == '-') { + optind++; + return '?'; + } + } + return getopt(argc, argv, optstring); +} + +int getopt_long(int argc, char *const *argv, const char *optstring, const struct option *longopts, int *idx) +{ + return __getopt_long(argc, argv, optstring, longopts, idx, 0); +} + +int getopt_long_only(int argc, char *const *argv, const char *optstring, const struct option *longopts, int *idx) +{ + return __getopt_long(argc, argv, optstring, longopts, idx, 1); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/getpass.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/getpass.c new file mode 100644 index 00000000..8d801823 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/getpass.c @@ -0,0 +1,107 @@ +/* Copyright (C) 1992-1999,2001,2003,2004,2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + +#if defined __USE_BSD || (defined __USE_XOPEN && !defined __USE_XOPEN2K) + + +/* It is desirable to use this bit on systems that have it. + The only bit of terminal state we want to twiddle is echoing, which is + done in software; there is no need to change the state of the terminal + hardware. */ + +#ifndef TCSASOFT +#define TCSASOFT 0 +#endif +#define PWD_BUFFER_SIZE 256 + +char * getpass (const char *prompt) +{ + FILE *in, *out; + struct termios s, t; + int tty_changed; + static char buf[PWD_BUFFER_SIZE]; + int nread; + + /* Try to write to and read from the terminal if we can. + If we can't open the terminal, use stderr and stdin. */ + + in = fopen ("/dev/tty", "r+"); + if (in == NULL) + { + in = stdin; + out = stderr; + } + else + out = in; + + /* Turn echoing off if it is on now. */ + + if (tcgetattr (fileno (in), &t) == 0) + { + /* Save the old one. */ + s = t; + /* Tricky, tricky. */ + t.c_lflag &= ~(ECHO|ISIG); + tty_changed = (tcsetattr (fileno (in), TCSAFLUSH|TCSASOFT, &t) == 0); + if (in != stdin) { + /* Disable buffering for read/write FILE to prevent problems with + * fseek and buffering for read/write auto-transitioning. */ + setvbuf(in, NULL, _IONBF, 0); + } + } + else + tty_changed = 0; + + /* Write the prompt. */ + fputs(prompt, out); + fflush(out); + + /* Read the password. */ + fgets (buf, PWD_BUFFER_SIZE-1, in); + if (buf != NULL) + { + nread = strlen(buf); + if (nread < 0) + buf[0] = '\0'; + else if (buf[nread - 1] == '\n') + { + /* Remove the newline. */ + buf[nread - 1] = '\0'; + if (tty_changed) + /* Write the newline that was not echoed. */ + putc('\n', out); + } + } + + /* Restore the original setting. */ + if (tty_changed) { + (void) tcsetattr (fileno (in), TCSAFLUSH|TCSASOFT, &s); + } + + if (in != stdin) + /* We opened the terminal; now close it. */ + fclose (in); + + return buf; +} +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/getsubopt-susv3.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/getsubopt-susv3.c new file mode 100644 index 00000000..9ff33ef1 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/getsubopt-susv3.c @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2006 Rich Felker + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + + +int getsubopt(char **opt, char *const *keys, char **val) +{ + char *s = *opt; + int i; + + *val = NULL; + *opt = strchr(s, ','); + if (*opt) *(*opt)++ = 0; + else *opt = s + strlen(s); + + for (i=0; keys[i]; i++) { + size_t l = strlen(keys[i]); + if (strncmp(keys[i], s, l)) continue; + if (s[l] == '=') + *val = s + l; + else if (s[l]) continue; + return i; + } + return -1; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/getsubopt.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/getsubopt.c new file mode 100644 index 00000000..4ff615b6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/getsubopt.c @@ -0,0 +1,72 @@ +/* Parse comma separate list into words. + Copyright (C) 1996, 1997, 1999, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1996. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + + +/* Parse comma separated suboption from *OPTIONP and match against + strings in TOKENS. If found return index and set *VALUEP to + optional value introduced by an equal sign. If the suboption is + not part of TOKENS return in *VALUEP beginning of unknown + suboption. On exit *OPTIONP is set to the beginning of the next + token or at the terminating NUL character. */ +int +getsubopt (char **optionp, char *const *tokens, char **valuep) +{ + char *endp, *vstart; + int cnt; + + if (**optionp == '\0') + return -1; + + /* Find end of next token. */ + endp = strchrnul (*optionp, ','); + + /* Find start of value. */ + vstart = memchr (*optionp, '=', endp - *optionp); + if (vstart == NULL) + vstart = endp; + + /* Try to match the characters between *OPTIONP and VSTART against + one of the TOKENS. */ + for (cnt = 0; tokens[cnt] != NULL; ++cnt) + if (strncmp (*optionp, tokens[cnt], vstart - *optionp) == 0 + && tokens[cnt][vstart - *optionp] == '\0') + { + /* We found the current option in TOKENS. */ + *valuep = vstart != endp ? vstart + 1 : NULL; + + if (*endp != '\0') + *endp++ = '\0'; + *optionp = endp; + + return cnt; + } + + /* The current suboption does not match any option. */ + *valuep = *optionp; + + if (*endp != '\0') + *endp++ = '\0'; + *optionp = endp; + + return -1; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/pathconf.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/pathconf.c new file mode 100644 index 00000000..84f20ed8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/pathconf.c @@ -0,0 +1,199 @@ +/* Copyright (C) 1991,1995,1996,1998,2000,2001,2003 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* pathconf -- adjusted for busybox */ + +/* It would be great it this could be implemented using fpathconf, + * but that doesn't work out very well (think FIFOs and sockets) */ + +#include +#include +#include +#include +#include +#include +#include + +extern __typeof(statfs) __libc_statfs; + + +/* The Linux kernel headers mention this as a kind of generic value. */ +#ifndef LINK_MAX +# define LINK_MAX 127 +#endif + +/* Get file-specific information about PATH. */ +long int +pathconf (const char *path, int name) +{ + if (path[0] == '\0') + { + __set_errno (ENOENT); + return -1; + } + + switch (name) + { + default: + __set_errno (EINVAL); + return -1; + + case _PC_LINK_MAX: +#ifdef LINK_MAX + return LINK_MAX; +#else + return -1; +#endif + + case _PC_MAX_CANON: +#ifdef MAX_CANON + return MAX_CANON; +#else + return -1; +#endif + + case _PC_MAX_INPUT: +#ifdef MAX_INPUT + return MAX_INPUT; +#else + return -1; +#endif + + case _PC_NAME_MAX: +#ifdef NAME_MAX + { + struct statfs buf; + int save_errno = errno; + + if (__libc_statfs (path, &buf) < 0) + { + if (errno == ENOSYS) + { + errno = save_errno; + return NAME_MAX; + } + return -1; + } + else + { +#ifdef _STATFS_F_NAMELEN + return buf.f_namelen; +#else +# ifdef _STATFS_F_NAME_MAX + return buf.f_name_max; +# else + return NAME_MAX; +# endif +#endif + } + } +#else + return -1; +#endif + + case _PC_PATH_MAX: +#ifdef PATH_MAX + return PATH_MAX; +#else + return -1; +#endif + + case _PC_PIPE_BUF: +#ifdef PIPE_BUF + return PIPE_BUF; +#else + return -1; +#endif + + case _PC_CHOWN_RESTRICTED: +#ifdef _POSIX_CHOWN_RESTRICTED + return _POSIX_CHOWN_RESTRICTED; +#else + return -1; +#endif + + case _PC_NO_TRUNC: +#ifdef _POSIX_NO_TRUNC + return _POSIX_NO_TRUNC; +#else + return -1; +#endif + + case _PC_VDISABLE: +#ifdef _POSIX_VDISABLE + return _POSIX_VDISABLE; +#else + return -1; +#endif + + case _PC_SYNC_IO: +#ifdef _POSIX_SYNC_IO + return _POSIX_SYNC_IO; +#else + return -1; +#endif + + case _PC_ASYNC_IO: +#if defined _POSIX_ASYNC_IO && defined __UCLIBC_HAS_LFS__ + { + /* AIO is only allowed on regular files and block devices. */ + struct stat st; + + if (stat (path, &st) < 0 + || (! S_ISREG (st.st_mode) && ! S_ISBLK (st.st_mode))) + return -1; + else + return 1; + } +#else + return -1; +#endif + + case _PC_PRIO_IO: +#ifdef _POSIX_PRIO_IO + return _POSIX_PRIO_IO; +#else + return -1; +#endif + + case _PC_SOCK_MAXBUF: +#ifdef SOCK_MAXBUF + return SOCK_MAXBUF; +#else + return -1; +#endif + + case _PC_FILESIZEBITS: +#ifdef FILESIZEBITS + return FILESIZEBITS; +#else + /* We let platforms with larger file sizes overwrite this value. */ + return 32; +#endif + + /* Be lazy -- skip these */ + case _PC_REC_INCR_XFER_SIZE: + case _PC_REC_MAX_XFER_SIZE: + case _PC_REC_MIN_XFER_SIZE: + case _PC_REC_XFER_ALIGN: + case _PC_ALLOC_SIZE_MIN: + case _PC_SYMLINK_MAX: + return -1; + } +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/sleep.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/sleep.c new file mode 100644 index 00000000..9db115a2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/sleep.c @@ -0,0 +1,193 @@ +/* Implementation of the POSIX sleep function using nanosleep. + Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1996. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include + + +/* version perusing nanosleep */ +#if defined __UCLIBC_HAS_REALTIME__ + +/* I am unable to reproduce alleged "Linux quirk". + * I used the following test program: +#include +#include +#include +static void dummy(int sig) {} +int main() { + struct timespec t = { 2, 0 }; + if (fork() == 0) { + sleep(1); + return 0; + } + signal(SIGCHLD, SIG_DFL); // + signal(SIGCHLD, dummy); // Pick one + signal(SIGCHLD, SIG_IGN); // + nanosleep(&t, &t); + return 0; +} + * Testing on 2.4.20 and on 2.6.35-rc4: + * With SIG_DFL, nanosleep is not interrupted by SIGCHLD. Ok. + * With dummy handler, nanosleep is interrupted by SIGCHLD. Ok. + * With SIG_IGN, nanosleep is NOT interrupted by SIGCHLD. + * It looks like sleep's workaround for SIG_IGN is no longer needed? + * The only emails I can find are from 1998 (!): + * ---------- + * Subject: Re: sleep ignore sigchld + * From: Linus Torvalds + * Date: Mon, 16 Nov 1998 11:02:15 -0800 (PST) + * + * On Mon, 16 Nov 1998, H. J. Lu wrote: + * > That is a kernel bug. SIGCHLD is a special one. Usually it cannot + * > be ignored. [snip...] + * + * No can do. + * + * "nanosleep()" is implemented in a bad way that makes it impossible to + * restart it cleanly. It was done that way because glibc wanted it that way, + * not because it's a good idea. [snip...] + * ---------- + * I assume that in the passed twelve+ years, nanosleep got fixed, + * but the hack in sleep to work around broken nanosleep was never removed. + */ + +# if 0 + +/* This is a quick and dirty, but not 100% compliant with + * the stupid SysV SIGCHLD vs. SIG_IGN behaviour. It is + * fine unless you are messing with SIGCHLD... */ +unsigned int sleep (unsigned int sec) +{ + unsigned int res; + struct timespec ts = { .tv_sec = (long int) seconds, .tv_nsec = 0 }; + res = nanosleep(&ts, &ts); + if (res) res = (unsigned int) ts.tv_sec + (ts.tv_nsec >= 500000000L); + return res; +} + +# else + +/* We are going to use the `nanosleep' syscall of the kernel. But the + kernel does not implement the sstupid SysV SIGCHLD vs. SIG_IGN + behaviour for this syscall. Therefore we have to emulate it here. */ +unsigned int sleep (unsigned int seconds) +{ + struct timespec ts = { .tv_sec = (long int) seconds, .tv_nsec = 0 }; + sigset_t set; + struct sigaction oact; + unsigned int result; + + /* This is not necessary but some buggy programs depend on this. */ + if (seconds == 0) { +# ifdef CANCELLATION_P + CANCELLATION_P (THREAD_SELF); +# endif + return 0; + } + + /* Linux will wake up the system call, nanosleep, when SIGCHLD + arrives even if SIGCHLD is ignored. We have to deal with it + in libc. */ + + __sigemptyset (&set); + __sigaddset (&set, SIGCHLD); + + /* Is SIGCHLD set to SIG_IGN? */ + sigaction (SIGCHLD, NULL, &oact); /* never fails */ + if (oact.sa_handler == SIG_IGN) { + /* Yes. Block SIGCHLD, save old mask. */ + sigprocmask (SIG_BLOCK, &set, &set); /* never fails */ + } + + /* Run nanosleep, with SIGCHLD blocked if SIGCHLD is SIG_IGNed. */ + result = nanosleep (&ts, &ts); + if (result != 0) { + /* Got EINTR. Return remaining time. */ + result = (unsigned int) ts.tv_sec + (ts.tv_nsec >= 500000000L); + } + + if (!__sigismember (&set, SIGCHLD)) { + /* We did block SIGCHLD, and old mask had no SIGCHLD bit. + IOW: we need to unblock SIGCHLD now. Do it. */ + /* this sigprocmask call never fails, thus never updates errno, + and therefore we don't need to save/restore it. */ + sigprocmask (SIG_SETMASK, &set, NULL); /* never fails */ + } + + return result; +} + +# endif + +#else /* __UCLIBC_HAS_REALTIME__ */ + +/* no nanosleep, use signals and alarm() */ +static void sleep_alarm_handler(int attribute_unused sig) +{ +} +unsigned int sleep (unsigned int seconds) +{ + struct sigaction act, oact; + sigset_t set, oset; + unsigned int result, remaining; + time_t before, after; + int old_errno = errno; + + /* This is not necessary but some buggy programs depend on this. */ + if (seconds == 0) + return 0; + + /* block SIGALRM */ + __sigemptyset (&set); + __sigaddset (&set, SIGALRM); + sigprocmask (SIG_BLOCK, &set, &oset); /* can't fail */ + + act.sa_handler = sleep_alarm_handler; + act.sa_flags = 0; + act.sa_mask = oset; + sigaction(SIGALRM, &act, &oact); /* never fails */ + + before = time(NULL); + remaining = alarm(seconds); + if (remaining && remaining > seconds) { + /* restore user's alarm */ + sigaction(SIGALRM, &oact, NULL); + alarm(remaining); /* restore old alarm */ + sigsuspend(&oset); + after = time(NULL); + } else { + sigsuspend (&oset); + after = time(NULL); + sigaction (SIGALRM, &oact, NULL); + } + result = after - before; + alarm(remaining > result ? remaining - result : 0); + sigprocmask (SIG_SETMASK, &oset, NULL); + + __set_errno(old_errno); + + return result > seconds ? 0 : seconds - result; +} + +#endif /* __UCLIBC_HAS_REALTIME__ */ + +libc_hidden_def(sleep) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/swab.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/swab.c new file mode 100644 index 00000000..70ea464c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/swab.c @@ -0,0 +1,23 @@ +#include +#include +#include + +/* Updated implementation based on byteswap.h from Miles Bader + * . This should be much faster on arches with machine + * specific, optimized definitions in include/bits/byteswap.h (i.e. on + * x86, use the bswap instruction on i486 and better boxes). For + * platforms that lack such support, this should be no slower than it + * was before... */ +void swab (const void *source, void *dest, ssize_t count) +{ + const unsigned short *from = source, *from_end = from + (count >> 1); + unsigned short junk; + unsigned short *to = dest; + + while (from < from_end) { + /* Don't put '*from++'into the bswap_16() macros + * or mad things will happen on macro expansion */ + junk=*from++; + *to++ = bswap_16 (junk); + } +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/sysconf.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/sysconf.c new file mode 100644 index 00000000..be58f111 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/sysconf.c @@ -0,0 +1,1014 @@ +/* Copyright (C) 1991,1993,1995-1997,2000 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#define _XOPEN_SOURCE 500 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef __UCLIBC_HAS_REGEX__ +#include +#endif +#ifdef __UCLIBC_HAS_THREADS_NATIVE__ +#include +#include + +#endif +#include +#include +#include "internal/parse_config.h" + +static int nprocessors_onln(void) +{ + char **l = NULL; + parser_t *p = config_open("/proc/stat"); + int ret = 0; + + if (p) { + while (config_read(p, &l, 2, 1, " ", 0)) + if (l[0][0] == 'c' + && l[0][1] == 'p' + && l[0][2] == 'u' + && isdigit(l[0][3])) + ++ret; + } else if ((p = config_open("/proc/cpuinfo"))) { +#if defined __sparc__ + while (config_read(p, &l, 2, 2, "\0:", PARSE_NORMAL)) + if (strncmp("ncpus active", l[0], 12) == 0) { + ret = atoi(l[1]); + break; + } +#else + while (config_read(p, &l, 2, 2, "\0:\t", PARSE_NORMAL)) + if (strcmp("processor", l[0]) == 0) + ++ret; +#endif + } + config_close(p); + return ret != 0 ? ret : 1; +} + +#if defined __UCLIBC__ && !defined __UCLIBC_HAS_LFS__ +# define readdir64 readdir +# define dirent64 dirent +#endif +static int nprocessors_conf(void) +{ + int ret = 0; + DIR *dir = opendir("/sys/devices/system/cpu"); + + if (dir) { + struct dirent64 *dp; + + while ((dp = readdir64(dir))) { + if (dp->d_type == DT_DIR + && dp->d_name[0] == 'c' + && dp->d_name[1] == 'p' + && dp->d_name[2] == 'u' + && isdigit(dp->d_name[3])) + ++ret; + } + closedir(dir); + } else + { +#if defined __sparc__ + char **l = NULL; + parser_t *p = config_open("/proc/stat"); + while (config_read(p, &l, 2, 2, "\0:", PARSE_NORMAL)) + if (strncmp("ncpus probed", l[0], 13) == 0) { + ret = atoi(l[1]); + break; + } + config_close(p); +#else + ret = nprocessors_onln(); +#endif + } + return ret != 0 ? ret : 1; +} + + +#ifndef __UCLIBC_CLK_TCK_CONST +#error __UCLIBC_CLK_TCK_CONST not defined! +#endif + +/***********************************************************************/ +/* + * Manuel Novoa III Jan 2001 + * + * On i386, the switch-based implementation generates 796 bytes of code. + * However, many of the return values are repeats. By collecting these + * repeats and moving to a table-based implementation, we generate 283 + * bytes on i386 (-Os -fomit-frame-pointer). + */ + +#ifdef _UCLIBC_GENERATE_SYSCONF_ARCH +/* + * Set some errno's so the auto-gen code knows what it is dealing with. + * 1) ENOSYS signifies that we're returning a default value. + * This is just extra info for development. + * 2) EISNAM signifies that the value returned varies at runtime. + * + * Option: GETPAGESIZE_IS_DYNAMIC + * The current implementation of getpagesize in uClibc returns + * a constant. The pagesize on the target arch should not vary, + * so it should be safe to set this as 0. + */ +#define RETURN_NEG_1 __set_errno(ENOSYS); return -1 +#define RETURN_FUNCTION(f) __set_errno(EISNAM); return (long int) #f +#define GETPAGESIZE_IS_DYNAMIC 0 +#else +#define RETURN_NEG_1 return -1 +#define RETURN_FUNCTION(f) return f; +#endif /* _UCLIBC_GENERATE_SYSCONF_ARCH */ + +/* Legacy value of ARG_MAX. The macro is now not defined since the + actual value varies based on the stack size. */ +#define legacy_ARG_MAX 131072 + +/* Get the value of the system variable NAME. */ +long int sysconf(int name) +{ +#ifdef __UCLIBC_HAS_THREADS_NATIVE__ + struct rlimit rlimit; +#endif + switch (name) + { + default: + __set_errno(EINVAL); + return -1; + + case _SC_ARG_MAX: +#ifdef __UCLIBC_HAS_THREADS_NATIVE__ + /* Use getrlimit to get the stack limit. */ + if (getrlimit (RLIMIT_STACK, &rlimit) == 0) + return MAX (legacy_ARG_MAX, rlimit.rlim_cur / 4); +#elif defined ARG_MAX + return ARG_MAX; +#else + RETURN_NEG_1; +#endif + + case _SC_CHILD_MAX: +#ifdef CHILD_MAX + return CHILD_MAX; +#else + RETURN_NEG_1; +#endif + + case _SC_CLK_TCK: + /* Can't use CLK_TCK here since that calls __sysconf(_SC_CLK_TCK) */ + return __UCLIBC_CLK_TCK_CONST; + + case _SC_NGROUPS_MAX: +#ifdef NGROUPS_MAX + return NGROUPS_MAX; +#else + RETURN_NEG_1; +#endif + + case _SC_OPEN_MAX: + RETURN_FUNCTION(getdtablesize()); + + case _SC_STREAM_MAX: +#ifdef STREAM_MAX + return STREAM_MAX; +#else + return FOPEN_MAX; +#endif + + case _SC_TZNAME_MAX: + return _POSIX_TZNAME_MAX; + + case _SC_JOB_CONTROL: +#ifdef _POSIX_JOB_CONTROL + return 1; +#else + RETURN_NEG_1; +#endif + + case _SC_SAVED_IDS: +#ifdef _POSIX_SAVED_IDS + return 1; +#else + RETURN_NEG_1; +#endif + + case _SC_REALTIME_SIGNALS: +#ifdef _POSIX_REALTIME_SIGNALS + return 1; +#else + RETURN_NEG_1; +#endif + + case _SC_PRIORITY_SCHEDULING: +#ifdef _POSIX_PRIORITY_SCHEDULING + return 1; +#else + RETURN_NEG_1; +#endif + + case _SC_TIMERS: +#ifdef _POSIX_TIMERS + return 1; +#else + RETURN_NEG_1; +#endif + + case _SC_ASYNCHRONOUS_IO: +#ifdef _POSIX_ASYNCHRONOUS_IO + return 1; +#else + RETURN_NEG_1; +#endif + + case _SC_PRIORITIZED_IO: +#ifdef _POSIX_PRIORITIZED_IO + return 1; +#else + RETURN_NEG_1; +#endif + + case _SC_SYNCHRONIZED_IO: +#ifdef _POSIX_SYNCHRONIZED_IO + return 1; +#else + RETURN_NEG_1; +#endif + + case _SC_FSYNC: +#ifdef _POSIX_FSYNC + return 1; +#else + RETURN_NEG_1; +#endif + + case _SC_MAPPED_FILES: +#ifdef _POSIX_MAPPED_FILES + return 1; +#else + RETURN_NEG_1; +#endif + + case _SC_MEMLOCK: +#ifdef _POSIX_MEMLOCK + return 1; +#else + RETURN_NEG_1; +#endif + + case _SC_MEMLOCK_RANGE: +#ifdef _POSIX_MEMLOCK_RANGE + return 1; +#else + RETURN_NEG_1; +#endif + + case _SC_MEMORY_PROTECTION: +#ifdef _POSIX_MEMORY_PROTECTION + return 1; +#else + RETURN_NEG_1; +#endif + + case _SC_MESSAGE_PASSING: +#ifdef _POSIX_MESSAGE_PASSING + return 1; +#else + RETURN_NEG_1; +#endif + + case _SC_SEMAPHORES: +#ifdef _POSIX_SEMAPHORES + return 1; +#else + RETURN_NEG_1; +#endif + + case _SC_SHARED_MEMORY_OBJECTS: +#ifdef _POSIX_SHARED_MEMORY_OBJECTS + return 1; +#else + RETURN_NEG_1; +#endif + + case _SC_VERSION: + return _POSIX_VERSION; + + case _SC_PAGESIZE: +#if defined(GETPAGESIZE_IS_DYNAMIC) && (GETPAGESIZE_IS_DYNAMIC == 1) + RETURN_FUNCTION(getpagesize()); +#else + return getpagesize(); /* note: currently this is not dynamic */ +#endif + + case _SC_AIO_LISTIO_MAX: +#ifdef AIO_LISTIO_MAX + return AIO_LISTIO_MAX; +#else + RETURN_NEG_1; +#endif + + case _SC_AIO_MAX: +#ifdef AIO_MAX + return AIO_MAX; +#else + RETURN_NEG_1; +#endif + + case _SC_AIO_PRIO_DELTA_MAX: +#ifdef AIO_PRIO_DELTA_MAX + return AIO_PRIO_DELTA_MAX; +#else + RETURN_NEG_1; +#endif + + case _SC_DELAYTIMER_MAX: +#ifdef DELAYTIMER_MAX + return DELAYTIMER_MAX; +#else + RETURN_NEG_1; +#endif + + case _SC_MQ_OPEN_MAX: +#ifdef MQ_OPEN_MAX + return MQ_OPEN_MAX; +#else + RETURN_NEG_1; +#endif + + case _SC_MQ_PRIO_MAX: +#ifdef MQ_PRIO_MAX + return MQ_PRIO_MAX; +#else + RETURN_NEG_1; +#endif + + case _SC_RTSIG_MAX: +#ifdef RTSIG_MAX + return RTSIG_MAX; +#else + RETURN_NEG_1; +#endif + + case _SC_SEM_NSEMS_MAX: +#ifdef SEM_NSEMS_MAX + return SEM_NSEMS_MAX; +#else + RETURN_NEG_1; +#endif + + case _SC_SEM_VALUE_MAX: +#ifdef SEM_VALUE_MAX + return SEM_VALUE_MAX; +#else + RETURN_NEG_1; +#endif + + case _SC_SIGQUEUE_MAX: +#ifdef SIGQUEUE_MAX + return SIGQUEUE_MAX; +#else + RETURN_NEG_1; +#endif + + case _SC_TIMER_MAX: +#ifdef TIMER_MAX + return TIMER_MAX; +#else + RETURN_NEG_1; +#endif + + case _SC_BC_BASE_MAX: +#ifdef BC_BASE_MAX + return BC_BASE_MAX; +#else + RETURN_NEG_1; +#endif + + case _SC_BC_DIM_MAX: +#ifdef BC_DIM_MAX + return BC_DIM_MAX; +#else + RETURN_NEG_1; +#endif + + case _SC_BC_SCALE_MAX: +#ifdef BC_SCALE_MAX + return BC_SCALE_MAX; +#else + RETURN_NEG_1; +#endif + + case _SC_BC_STRING_MAX: +#ifdef BC_STRING_MAX + return BC_STRING_MAX; +#else + RETURN_NEG_1; +#endif + + case _SC_COLL_WEIGHTS_MAX: +#ifdef COLL_WEIGHTS_MAX + return COLL_WEIGHTS_MAX; +#else + RETURN_NEG_1; +#endif + + case _SC_EQUIV_CLASS_MAX: +#ifdef EQUIV_CLASS_MAX + return EQUIV_CLASS_MAX; +#else + RETURN_NEG_1; +#endif + + case _SC_EXPR_NEST_MAX: +#ifdef EXPR_NEST_MAX + return EXPR_NEST_MAX; +#else + RETURN_NEG_1; +#endif + + case _SC_LINE_MAX: +#ifdef LINE_MAX + return LINE_MAX; +#else + RETURN_NEG_1; +#endif + + case _SC_RE_DUP_MAX: +#ifdef RE_DUP_MAX + return RE_DUP_MAX; +#else + RETURN_NEG_1; +#endif + + case _SC_CHARCLASS_NAME_MAX: +#ifdef CHARCLASS_NAME_MAX + return CHARCLASS_NAME_MAX; +#else + RETURN_NEG_1; +#endif + + case _SC_PII: +#ifdef _POSIX_PII + return 1; +#else + RETURN_NEG_1; +#endif + + case _SC_PII_XTI: +#ifdef _POSIX_PII_XTI + return 1; +#else + RETURN_NEG_1; +#endif + + case _SC_PII_SOCKET: +#ifdef _POSIX_PII_SOCKET + return 1; +#else + RETURN_NEG_1; +#endif + + case _SC_PII_INTERNET: +#ifdef _POSIX_PII_INTERNET + return 1; +#else + RETURN_NEG_1; +#endif + + case _SC_PII_OSI: +#ifdef _POSIX_PII_OSI + return 1; +#else + RETURN_NEG_1; +#endif + + case _SC_POLL: +#ifdef _POSIX_POLL + return 1; +#else + RETURN_NEG_1; +#endif + + case _SC_SELECT: +#ifdef _POSIX_SELECT + return 1; +#else + RETURN_NEG_1; +#endif + + case _SC_UIO_MAXIOV: +#ifdef UIO_MAXIOV + return UIO_MAXIOV; +#else + RETURN_NEG_1; +#endif + + case _SC_PII_INTERNET_STREAM: +#ifdef _POSIX_PII_INTERNET_STREAM + return 1; +#else + RETURN_NEG_1; +#endif + + case _SC_PII_INTERNET_DGRAM: +#ifdef _POSIX_PII_INTERNET_DGRAM + return 1; +#else + RETURN_NEG_1; +#endif + + case _SC_PII_OSI_COTS: +#ifdef _POSIX_PII_OSI_COTS + return 1; +#else + RETURN_NEG_1; +#endif + + case _SC_PII_OSI_CLTS: +#ifdef _POSIX_PII_OSI_CLTS + return 1; +#else + RETURN_NEG_1; +#endif + + case _SC_PII_OSI_M: +#ifdef _POSIX_PII_OSI_M + return 1; +#else + RETURN_NEG_1; +#endif + + case _SC_T_IOV_MAX: +#ifdef _T_IOV_MAX + return _T_IOV_MAX; +#else + RETURN_NEG_1; +#endif + + case _SC_2_VERSION: + return _POSIX2_VERSION; + + case _SC_2_C_BIND: +#ifdef _POSIX2_C_BIND + return _POSIX2_C_BIND; +#else + RETURN_NEG_1; +#endif + + case _SC_2_C_DEV: +#ifdef _POSIX2_C_DEV + return _POSIX2_C_DEV; +#else + RETURN_NEG_1; +#endif + + case _SC_2_C_VERSION: +#ifdef _POSIX2_C_VERSION + return _POSIX2_C_VERSION; +#else + RETURN_NEG_1; +#endif + + case _SC_2_FORT_DEV: +#ifdef _POSIX2_FORT_DEV + return _POSIX2_FORT_DEV; +#else + RETURN_NEG_1; +#endif + + case _SC_2_FORT_RUN: +#ifdef _POSIX2_FORT_RUN + return _POSIX2_FORT_RUN; +#else + RETURN_NEG_1; +#endif + + case _SC_2_LOCALEDEF: +#ifdef _POSIX2_LOCALEDEF + return _POSIX2_LOCALEDEF; +#else + RETURN_NEG_1; +#endif + + case _SC_2_SW_DEV: +#ifdef _POSIX2_SW_DEV + return _POSIX2_SW_DEV; +#else + RETURN_NEG_1; +#endif + + case _SC_2_CHAR_TERM: +#ifdef _POSIX2_CHAR_TERM + return _POSIX2_CHAR_TERM; +#else + RETURN_NEG_1; +#endif + + case _SC_2_UPE: +#ifdef _POSIX2_UPE + return _POSIX2_UPE; +#else + RETURN_NEG_1; +#endif + + /* POSIX 1003.1c (POSIX Threads). */ + case _SC_THREADS: +#ifdef __UCLIBC_HAS_THREADS__ + return 1; +#else + RETURN_NEG_1; +#endif + + case _SC_THREAD_SAFE_FUNCTIONS: +#ifdef __UCLIBC_HAS_THREADS__ + return 1; +#else + RETURN_NEG_1; +#endif + +/* If you change these, also change libc/pwd_grp/pwd_grp.c to match */ + case _SC_GETGR_R_SIZE_MAX: + return __UCLIBC_GRP_BUFFER_SIZE__; + + case _SC_GETPW_R_SIZE_MAX: + return __UCLIBC_PWD_BUFFER_SIZE__; + +/* getlogin() is a worthless interface. In uClibc we let the user specify + * whatever they want via the LOGNAME environment variable, or we return NULL + * if getenv() fails to find anything. So this is merely how large a env + * variable can be. Lets use 256 */ + case _SC_LOGIN_NAME_MAX: + return 256; + +/* If you change this, also change _SC_TTY_NAME_MAX in libc/unistd/sysconf.c */ +#define TTYNAME_BUFLEN 32 + case _SC_TTY_NAME_MAX: + return TTYNAME_BUFLEN; + + case _SC_THREAD_DESTRUCTOR_ITERATIONS: +#ifdef _POSIX_THREAD_DESTRUCTOR_ITERATIONS + return _POSIX_THREAD_DESTRUCTOR_ITERATIONS; +#else + RETURN_NEG_1; +#endif + + case _SC_THREAD_KEYS_MAX: +#ifdef PTHREAD_KEYS_MAX + return PTHREAD_KEYS_MAX; +#else + RETURN_NEG_1; +#endif + + case _SC_THREAD_STACK_MIN: +#ifdef PTHREAD_STACK_MIN + return PTHREAD_STACK_MIN; +#else + RETURN_NEG_1; +#endif + + case _SC_THREAD_THREADS_MAX: +#ifdef PTHREAD_THREADS_MAX + return PTHREAD_THREADS_MAX; +#else + RETURN_NEG_1; +#endif + + case _SC_THREAD_ATTR_STACKADDR: +#ifdef _POSIX_THREAD_ATTR_STACKADDR + return 1; +#else + RETURN_NEG_1; +#endif + + case _SC_THREAD_ATTR_STACKSIZE: +#ifdef _POSIX_THREAD_ATTR_STACKSIZE + return 1; +#else + RETURN_NEG_1; +#endif + + case _SC_THREAD_PRIORITY_SCHEDULING: +#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING + return 1; +#else + RETURN_NEG_1; +#endif + + case _SC_THREAD_PRIO_INHERIT: +#ifdef _POSIX_THREAD_PRIO_INHERIT + return 1; +#else + RETURN_NEG_1; +#endif + + case _SC_THREAD_PRIO_PROTECT: +#ifdef _POSIX_THREAD_PRIO_PROTECT + return 1; +#else + RETURN_NEG_1; +#endif + + case _SC_THREAD_PROCESS_SHARED: +#ifdef _POSIX_THREAD_PROCESS_SHARED + return 1; +#else + RETURN_NEG_1; +#endif + + case _SC_NPROCESSORS_CONF: + RETURN_FUNCTION(nprocessors_conf()); + + case _SC_NPROCESSORS_ONLN: + RETURN_FUNCTION(nprocessors_onln()); + + case _SC_PHYS_PAGES: +#if 0 + RETURN_FUNCTION(get_phys_pages()); +#else + RETURN_NEG_1; +#endif + + case _SC_AVPHYS_PAGES: +#if 0 + RETURN_FUNCTION(get_avphys_pages()); +#else + RETURN_NEG_1; +#endif + + case _SC_ATEXIT_MAX: + return __UCLIBC_MAX_ATEXIT; + + case _SC_PASS_MAX: + /* We have no limit but since the return value might be used to + allocate a buffer we restrict the value. */ + return BUFSIZ; + + case _SC_XOPEN_VERSION: + return _XOPEN_VERSION; + + case _SC_XOPEN_XCU_VERSION: + return _XOPEN_XCU_VERSION; + + case _SC_XOPEN_UNIX: + return _XOPEN_UNIX; + + case _SC_XOPEN_CRYPT: +#ifdef _XOPEN_CRYPT + return _XOPEN_CRYPT; +#else + RETURN_NEG_1; +#endif + + case _SC_XOPEN_ENH_I18N: +#ifdef _XOPEN_ENH_I18N + return _XOPEN_ENH_I18N; +#else + RETURN_NEG_1; +#endif + + case _SC_XOPEN_SHM: +#ifdef _XOPEN_SHM + return _XOPEN_SHM; +#else + RETURN_NEG_1; +#endif + + case _SC_XOPEN_XPG2: +#ifdef _XOPEN_XPG2 + return _XOPEN_XPG2; +#else + RETURN_NEG_1; +#endif + + case _SC_XOPEN_XPG3: +#ifdef _XOPEN_XPG3 + return _XOPEN_XPG3; +#else + RETURN_NEG_1; +#endif + + case _SC_XOPEN_XPG4: +#ifdef _XOPEN_XPG4 + return _XOPEN_XPG4; +#else + RETURN_NEG_1; +#endif + + case _SC_CHAR_BIT: + return CHAR_BIT; + + case _SC_CHAR_MAX: + return CHAR_MAX; + + case _SC_CHAR_MIN: + return CHAR_MIN; + + case _SC_INT_MAX: + return INT_MAX; + + case _SC_INT_MIN: + return INT_MIN; + + case _SC_LONG_BIT: + return sizeof (long int) * CHAR_BIT; + + case _SC_WORD_BIT: + return sizeof (int) * CHAR_BIT; + + case _SC_MB_LEN_MAX: + return MB_LEN_MAX; + + case _SC_NZERO: + return NZERO; + + case _SC_SSIZE_MAX: + return _POSIX_SSIZE_MAX; + + case _SC_SCHAR_MAX: + return SCHAR_MAX; + + case _SC_SCHAR_MIN: + return SCHAR_MIN; + + case _SC_SHRT_MAX: + return SHRT_MAX; + + case _SC_SHRT_MIN: + return SHRT_MIN; + + case _SC_UCHAR_MAX: + return UCHAR_MAX; + + case _SC_UINT_MAX: + return UINT_MAX; + + case _SC_ULONG_MAX: + return ULONG_MAX; + + case _SC_USHRT_MAX: + return USHRT_MAX; + + case _SC_NL_ARGMAX: +#ifdef NL_ARGMAX + return NL_ARGMAX; +#else + RETURN_NEG_1; +#endif + + case _SC_NL_LANGMAX: +#ifdef NL_LANGMAX + return NL_LANGMAX; +#else + RETURN_NEG_1; +#endif + + case _SC_NL_MSGMAX: +#ifdef NL_MSGMAX + return NL_MSGMAX; +#else + RETURN_NEG_1; +#endif + + case _SC_NL_NMAX: +#ifdef NL_NMAX + return NL_NMAX; +#else + RETURN_NEG_1; +#endif + + case _SC_NL_SETMAX: +#ifdef NL_SETMAX + return NL_SETMAX; +#else + RETURN_NEG_1; +#endif + + case _SC_NL_TEXTMAX: +#ifdef NL_TEXTMAX + return NL_TEXTMAX; +#else + RETURN_NEG_1; +#endif + + case _SC_XBS5_ILP32_OFF32: +#ifdef _XBS5_ILP32_OFF32 + return _XBS5_ILP32_OFF32; +#else + RETURN_NEG_1; +#endif + case _SC_XBS5_ILP32_OFFBIG: +#ifdef _XBS5_ILP32_OFFBIG + return _XBS5_ILP32_OFFBIG; +#else + RETURN_NEG_1; +#endif + case _SC_XBS5_LP64_OFF64: +#ifdef _XBS5_LP64_OFF64 + return _XBS5_LP64_OFF64; +#else + RETURN_NEG_1; +#endif + case _SC_XBS5_LPBIG_OFFBIG: +#ifdef _XBS5_LPBIG_OFFBIG + return _XBS5_LPBIG_OFFBIG; +#else + RETURN_NEG_1; +#endif + case _SC_V7_ILP32_OFF32: +#ifdef _POSIX_V7_ILP32_OFF32 + return _POSIX_V7_ILP32_OFF32; +#else + RETURN_NEG_1; +#endif + case _SC_V7_ILP32_OFFBIG: +#ifdef _POSIX_V7_ILP32_OFFBIG + return _POSIX_V7_ILP32_OFFBIG; +#else + RETURN_NEG_1; +#endif + case _SC_V7_LP64_OFF64: +#ifdef _POSIX_V7_LP64_OFF64 + return _POSIX_V7_LP64_OFF64; +#else + RETURN_NEG_1; +#endif + case _SC_V7_LPBIG_OFFBIG: +#ifdef _POSIX_V7_LPBIG_OFFBIG + return _POSIX_V7_LPBIG_OFFBIG; +#else + RETURN_NEG_1; +#endif + + case _SC_XOPEN_LEGACY: + return _XOPEN_LEGACY; + + case _SC_XOPEN_REALTIME: +#ifdef _XOPEN_REALTIME + return _XOPEN_REALTIME; +#else + RETURN_NEG_1; +#endif + case _SC_XOPEN_REALTIME_THREADS: +#ifdef _XOPEN_REALTIME_THREADS + return _XOPEN_REALTIME_THREADS; +#else + RETURN_NEG_1; +#endif + + case _SC_MONOTONIC_CLOCK: +#ifdef __NR_clock_getres + /* Check using the clock_getres system call. */ +# ifdef __UCLIBC_HAS_THREADS_NATIVE__ + { + struct timespec ts; + INTERNAL_SYSCALL_DECL (err); + int r; + r = INTERNAL_SYSCALL (clock_getres, err, 2, CLOCK_MONOTONIC, &ts); + return INTERNAL_SYSCALL_ERROR_P (r, err) ? -1 : _POSIX_VERSION; + } +# else + if (clock_getres(CLOCK_MONOTONIC, NULL) >= 0) + return _POSIX_VERSION; + + RETURN_NEG_1; +# endif +#endif + +#ifdef __UCLIBC_HAS_THREADS_NATIVE__ + case _SC_THREAD_CPUTIME: +# if _POSIX_THREAD_CPUTIME > 0 + return _POSIX_THREAD_CPUTIME; +# else + RETURN_NEG_1; +# endif +#endif + } +} +libc_hidden_def(sysconf) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/ualarm.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/ualarm.c new file mode 100644 index 00000000..82eb972b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/ualarm.c @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include + + +useconds_t ualarm(useconds_t value, useconds_t interval) +{ + struct itimerval otimer; + const struct itimerval itimer = { + { 0, interval }, + { 0, value} + }; + + if (setitimer(ITIMER_REAL, &itimer, &otimer) < 0) { + return -1; + } + return((otimer.it_value.tv_sec * 1000000) + otimer.it_value.tv_usec); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/usershell.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/usershell.c new file mode 100644 index 00000000..2a6b6650 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/usershell.c @@ -0,0 +1,74 @@ +/* setusershell(), getusershell(), endusershell() for uClibc. + * + * Copyright (C) 2010 Bernhard Reutner-Fischer + * + * Licensed under the LGPL v2.1 or later, see the file COPYING.LIB in + * this tarball. + */ +/* My manpage reads: + * The getusershell() function returns the next line from the file + * /etc/shells, opening the file if necessary. The line should contain + * the pathname of a valid user shell. If /etc/shells does not exist + * or is unreadable, getusershell() behaves as if /bin/sh and /bin/csh + * were listed in the file. + * The getusershell() function returns a NULL pointer on end-of-file. + */ +#include +#include +#include +#include +#include "internal/parse_config.h" + +#if defined __USE_BSD || (defined __USE_XOPEN && !defined __USE_UNIX98) + +static const char * const defaultsh[] = { _PATH_BSHELL, _PATH_CSHELL, NULL}; +static char *shellb, **shells; +static parser_t *shellp; + +void endusershell(void) +{ + if (shellp) { + shells = (char**) shellb; + while (shells && *shells) { + char*xxx = *shells++; + free(xxx); + } + config_close(shellp); + shellp = NULL; + } + free(shellb); + shellb = NULL; + shells = NULL; +} +void setusershell(void) +{ + endusershell(); + shellp = config_open(_PATH_SHELLS); + if (shellp == NULL) + shells = (char **)defaultsh; + else { + char **shell = NULL; + int pos = 0; + + while (config_read(shellp, &shell, 1, 1, "# \t", PARSE_NORMAL)) + { + shellb = realloc(shellb, (pos + 2) * sizeof(char*)); + shells = (char**) shellb + pos++; + *shells++ = strdup(*shell); + *shells = NULL; + + } + shells = (char **)shellb; + } +} +char *getusershell(void) +{ + char *sh; + if (shells == NULL) + setusershell(); + sh = *shells; + if (sh) + shells++; + return sh; +} +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/usleep.c b/l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/usleep.c new file mode 100644 index 00000000..8d01703e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libc/unistd/usleep.c @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include + +#if defined __USE_BSD || defined __USE_POSIX98 +#if defined __UCLIBC_HAS_REALTIME__ + +int usleep (__useconds_t usec) +{ + const struct timespec ts = { + .tv_sec = (long int) (usec / 1000000), + .tv_nsec = (long int) (usec % 1000000) * 1000ul + }; + return nanosleep(&ts, NULL); +} +#else /* __UCLIBC_HAS_REALTIME__ */ +int usleep (__useconds_t usec) +{ + struct timeval tv; + + tv.tv_sec = (long int) (usec / 1000000); + tv.tv_usec = (long int) (usec % 1000000); + return select(0, NULL, NULL, NULL, &tv); +} +#endif /* __UCLIBC_HAS_REALTIME__ */ +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libcrypt/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libcrypt/Makefile new file mode 100644 index 00000000..c8dc9b46 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libcrypt/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../ +top_builddir=../ +include $(top_builddir)Rules.mak +all: libs +include Makefile.in +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libcrypt/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/libcrypt/Makefile.in new file mode 100644 index 00000000..3cbf9d04 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libcrypt/Makefile.in @@ -0,0 +1,65 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +subdirs += libcrypt + +CFLAGS-libcrypt := -DNOT_IN_libc -DIS_IN_libcrypt $(SSP_ALL_CFLAGS) + +LDFLAGS-libcrypt.so := $(LDFLAGS) + +LIBS-libcrypt.so := $(LIBS) + +libcrypt_FULL_NAME := libcrypt-$(VERSION).so + +libcrypt_DIR := $(top_srcdir)libcrypt +libcrypt_OUT := $(top_builddir)libcrypt + +libcrypt_SRC-y := +libcrypt_SRC-$(UCLIBC_HAS_CRYPT_IMPL) += crypt.c des.c md5.c +libcrypt_SRC-$(UCLIBC_HAS_CRYPT_STUB) += crypt_stub.c + +libcrypt_SRC := $(addprefix $(libcrypt_DIR)/,$(libcrypt_SRC-y)) +libcrypt_OBJ := $(patsubst $(libcrypt_DIR)/%.c,$(libcrypt_OUT)/%.o,$(libcrypt_SRC)) + +ifeq ($(DOPIC),y) +libcrypt-a-y := $(libcrypt_OBJ:.o=.os) +else +libcrypt-a-y := $(libcrypt_OBJ) +endif +libcrypt-so-y := $(libcrypt_OBJ:.o=.os) + +lib-a-$(UCLIBC_HAS_CRYPT) += $(top_builddir)lib/libcrypt.a +lib-so-$(UCLIBC_HAS_CRYPT) += $(top_builddir)lib/libcrypt.so +objclean-y += CLEAN_libcrypt + +ifeq ($(DOMULTI),n) +ifeq ($(DOPIC),y) +$(top_builddir)lib/libcrypt.so: $(top_builddir)lib/libcrypt.a $(libc.depend) +else +$(top_builddir)lib/libcrypt.so: $(libcrypt_OUT)/libcrypt_so.a $(libc.depend) +endif + $(call link.so,$(libcrypt_FULL_NAME),$(ABI_VERSION)) +else +$(top_builddir)lib/libcrypt.so: $(libcrypt_OUT)/libcrypt.oS | $(libc.depend) + $(call linkm.so,$(libcrypt_FULL_NAME),$(ABI_VERSION)) +endif + +$(libcrypt_OUT)/libcrypt_so.a: $(libcrypt-so-y) + $(Q)$(RM) $@ + $(do_ar) + +$(libcrypt_OUT)/libcrypt.oS: $(libcrypt_SRC) + $(Q)$(RM) $@ + $(compile-m) + +$(top_builddir)lib/libcrypt.a: $(libcrypt-a-y) + $(Q)$(INSTALL) -d $(dir $@) + $(Q)$(RM) $@ + $(do_ar) + +CLEAN_libcrypt: + $(do_rm) $(addprefix $(libcrypt_OUT)/*., o os oS a) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libcrypt/crypt.c b/l4/pkg/uclibc/lib/contrib/uclibc/libcrypt/crypt.c new file mode 100644 index 00000000..8b361d39 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libcrypt/crypt.c @@ -0,0 +1,21 @@ +/* vi: set sw=4 ts=4: */ +/* + * crypt() for uClibc + * Copyright (C) 2000-2006 by Erik Andersen + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define __FORCE_GLIBC +#include +#include +#include "libcrypt.h" + +char *crypt(const char *key, const char *salt) +{ + /* First, check if we are supposed to be using the MD5 replacement + * instead of DES... */ + if (salt[0]=='$' && salt[1]=='1' && salt[2]=='$') + return __md5_crypt((unsigned char*)key, (unsigned char*)salt); + else + return __des_crypt((unsigned char*)key, (unsigned char*)salt); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libcrypt/crypt_stub.c b/l4/pkg/uclibc/lib/contrib/uclibc/libcrypt/crypt_stub.c new file mode 100644 index 00000000..76645a04 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libcrypt/crypt_stub.c @@ -0,0 +1,30 @@ +/* vi: set sw=4 ts=4: */ +/* + * crypt() for uClibc + * Copyright (C) 2008 by Erik Andersen + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#define __FORCE_GLIBC +#include +#include +#include "libcrypt.h" +#include + +char *crypt(const char *key attribute_unused, const char *salt attribute_unused) +{ + __set_errno(ENOSYS); + return NULL; +} + +void +setkey(const char *key attribute_unused) +{ + __set_errno(ENOSYS); +} + +void +encrypt(char *block attribute_unused, int flag attribute_unused) +{ + __set_errno(ENOSYS); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libcrypt/des.c b/l4/pkg/uclibc/lib/contrib/uclibc/libcrypt/des.c new file mode 100644 index 00000000..6af65b61 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libcrypt/des.c @@ -0,0 +1,739 @@ +/* + * FreeSec: libcrypt for NetBSD + * + * Copyright (c) 1994 David Burren + * All rights reserved. + * + * Adapted for FreeBSD-2.0 by Geoffrey M. Rehmet + * this file should now *only* export crypt(), in order to make + * binaries of libcrypt exportable from the USA + * + * Adapted for FreeBSD-4.0 by Mark R V Murray + * this file should now *only* export crypt_des(), in order to make + * a module that can be optionally included in libcrypt. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the names of other contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This is an original implementation of the DES and the crypt(3) interfaces + * by David Burren . + * + * An excellent reference on the underlying algorithm (and related + * algorithms) is: + * + * B. Schneier, Applied Cryptography: protocols, algorithms, + * and source code in C, John Wiley & Sons, 1994. + * + * Note that in that book's description of DES the lookups for the initial, + * pbox, and final permutations are inverted (this has been brought to the + * attention of the author). A list of errata for this book has been + * posted to the sci.crypt newsgroup by the author and is available for FTP. + * + * ARCHITECTURE ASSUMPTIONS: + * It is assumed that the 8-byte arrays passed by reference can be + * addressed as arrays of u_int32_t's (ie. the CPU is not picky about + * alignment). + */ + +#define __FORCE_GLIBC +#include +#include +#include +#include +#include +#include +#include +#include "libcrypt.h" + +/* Re-entrantify me -- all this junk needs to be in + * struct crypt_data to make this really reentrant... */ +static u_char inv_key_perm[64]; +static u_char inv_comp_perm[56]; +static u_char un_pbox[32]; +static u_int32_t en_keysl[16], en_keysr[16]; +static u_int32_t de_keysl[16], de_keysr[16]; +static u_int32_t ip_maskl[8][256], ip_maskr[8][256]; +static u_int32_t fp_maskl[8][256], fp_maskr[8][256]; +static u_int32_t key_perm_maskl[8][128], key_perm_maskr[8][128]; +static u_int32_t comp_maskl[8][128], comp_maskr[8][128]; +static u_int32_t saltbits; +static u_int32_t old_salt; +static u_int32_t old_rawkey0, old_rawkey1; + + +/* Static stuff that stays resident and doesn't change after + * being initialized, and therefore doesn't need to be made + * reentrant. */ +static u_char init_perm[64], final_perm[64]; +static u_char m_sbox[4][4096]; +static u_int32_t psbox[4][256]; + + + + +/* A pile of data */ +static const u_char ascii64[] = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + +static const u_char IP[64] = { + 58, 50, 42, 34, 26, 18, 10, 2, 60, 52, 44, 36, 28, 20, 12, 4, + 62, 54, 46, 38, 30, 22, 14, 6, 64, 56, 48, 40, 32, 24, 16, 8, + 57, 49, 41, 33, 25, 17, 9, 1, 59, 51, 43, 35, 27, 19, 11, 3, + 61, 53, 45, 37, 29, 21, 13, 5, 63, 55, 47, 39, 31, 23, 15, 7 +}; + +static const u_char key_perm[56] = { + 57, 49, 41, 33, 25, 17, 9, 1, 58, 50, 42, 34, 26, 18, + 10, 2, 59, 51, 43, 35, 27, 19, 11, 3, 60, 52, 44, 36, + 63, 55, 47, 39, 31, 23, 15, 7, 62, 54, 46, 38, 30, 22, + 14, 6, 61, 53, 45, 37, 29, 21, 13, 5, 28, 20, 12, 4 +}; + +static const u_char key_shifts[16] = { + 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 +}; + +static const u_char comp_perm[48] = { + 14, 17, 11, 24, 1, 5, 3, 28, 15, 6, 21, 10, + 23, 19, 12, 4, 26, 8, 16, 7, 27, 20, 13, 2, + 41, 52, 31, 37, 47, 55, 30, 40, 51, 45, 33, 48, + 44, 49, 39, 56, 34, 53, 46, 42, 50, 36, 29, 32 +}; + +/* + * No E box is used, as it's replaced by some ANDs, shifts, and ORs. + */ + +static const u_char sbox[8][64] = { + { + 14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7, + 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8, + 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0, + 15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13 + }, + { + 15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10, + 3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5, + 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15, + 13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9 + }, + { + 10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8, + 13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1, + 13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7, + 1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12 + }, + { + 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15, + 13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9, + 10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4, + 3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14 + }, + { + 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9, + 14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6, + 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14, + 11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3 + }, + { + 12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11, + 10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8, + 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6, + 4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13 + }, + { + 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1, + 13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6, + 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2, + 6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12 + }, + { + 13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7, + 1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2, + 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8, + 2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11 + } +}; + +static const u_char pbox[32] = { + 16, 7, 20, 21, 29, 12, 28, 17, 1, 15, 23, 26, 5, 18, 31, 10, + 2, 8, 24, 14, 32, 27, 3, 9, 19, 13, 30, 6, 22, 11, 4, 25 +}; + +static const u_int32_t bits32[32] = +{ + 0x80000000, 0x40000000, 0x20000000, 0x10000000, + 0x08000000, 0x04000000, 0x02000000, 0x01000000, + 0x00800000, 0x00400000, 0x00200000, 0x00100000, + 0x00080000, 0x00040000, 0x00020000, 0x00010000, + 0x00008000, 0x00004000, 0x00002000, 0x00001000, + 0x00000800, 0x00000400, 0x00000200, 0x00000100, + 0x00000080, 0x00000040, 0x00000020, 0x00000010, + 0x00000008, 0x00000004, 0x00000002, 0x00000001 +}; + +static const u_char bits8[8] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 }; + + +static int +ascii_to_bin(char ch) +{ + if (ch > 'z') + return(0); + if (ch >= 'a') + return(ch - 'a' + 38); + if (ch > 'Z') + return(0); + if (ch >= 'A') + return(ch - 'A' + 12); + if (ch > '9') + return(0); + if (ch >= '.') + return(ch - '.'); + return(0); +} + +static void +des_init(void) +{ + static int des_initialised = 0; + + int i, j, b, k, inbit, obit; + u_int32_t *p, *il, *ir, *fl, *fr; + const u_int32_t *bits28, *bits24; + u_char u_sbox[8][64]; + + if (des_initialised==1) + return; + + old_rawkey0 = old_rawkey1 = 0L; + saltbits = 0L; + old_salt = 0L; + bits24 = (bits28 = bits32 + 4) + 4; + + /* + * Invert the S-boxes, reordering the input bits. + */ + for (i = 0; i < 8; i++) + for (j = 0; j < 64; j++) { + b = (j & 0x20) | ((j & 1) << 4) | ((j >> 1) & 0xf); + u_sbox[i][j] = sbox[i][b]; + } + + /* + * Convert the inverted S-boxes into 4 arrays of 8 bits. + * Each will handle 12 bits of the S-box input. + */ + for (b = 0; b < 4; b++) + for (i = 0; i < 64; i++) + for (j = 0; j < 64; j++) + m_sbox[b][(i << 6) | j] = + (u_char)((u_sbox[(b << 1)][i] << 4) | + u_sbox[(b << 1) + 1][j]); + + /* + * Set up the initial & final permutations into a useful form, and + * initialise the inverted key permutation. + */ + for (i = 0; i < 64; i++) { + init_perm[final_perm[i] = IP[i] - 1] = (u_char)i; + inv_key_perm[i] = 255; + } + + /* + * Invert the key permutation and initialise the inverted key + * compression permutation. + */ + for (i = 0; i < 56; i++) { + inv_key_perm[key_perm[i] - 1] = (u_char)i; + inv_comp_perm[i] = 255; + } + + /* + * Invert the key compression permutation. + */ + for (i = 0; i < 48; i++) { + inv_comp_perm[comp_perm[i] - 1] = (u_char)i; + } + + /* + * Set up the OR-mask arrays for the initial and final permutations, + * and for the key initial and compression permutations. + */ + for (k = 0; k < 8; k++) { + for (i = 0; i < 256; i++) { + *(il = &ip_maskl[k][i]) = 0L; + *(ir = &ip_maskr[k][i]) = 0L; + *(fl = &fp_maskl[k][i]) = 0L; + *(fr = &fp_maskr[k][i]) = 0L; + for (j = 0; j < 8; j++) { + inbit = 8 * k + j; + if (i & bits8[j]) { + if ((obit = init_perm[inbit]) < 32) + *il |= bits32[obit]; + else + *ir |= bits32[obit-32]; + if ((obit = final_perm[inbit]) < 32) + *fl |= bits32[obit]; + else + *fr |= bits32[obit - 32]; + } + } + } + for (i = 0; i < 128; i++) { + *(il = &key_perm_maskl[k][i]) = 0L; + *(ir = &key_perm_maskr[k][i]) = 0L; + for (j = 0; j < 7; j++) { + inbit = 8 * k + j; + if (i & bits8[j + 1]) { + if ((obit = inv_key_perm[inbit]) == 255) + continue; + if (obit < 28) + *il |= bits28[obit]; + else + *ir |= bits28[obit - 28]; + } + } + *(il = &comp_maskl[k][i]) = 0L; + *(ir = &comp_maskr[k][i]) = 0L; + for (j = 0; j < 7; j++) { + inbit = 7 * k + j; + if (i & bits8[j + 1]) { + if ((obit=inv_comp_perm[inbit]) == 255) + continue; + if (obit < 24) + *il |= bits24[obit]; + else + *ir |= bits24[obit - 24]; + } + } + } + } + + /* + * Invert the P-box permutation, and convert into OR-masks for + * handling the output of the S-box arrays setup above. + */ + for (i = 0; i < 32; i++) + un_pbox[pbox[i] - 1] = (u_char)i; + + for (b = 0; b < 4; b++) + for (i = 0; i < 256; i++) { + *(p = &psbox[b][i]) = 0L; + for (j = 0; j < 8; j++) { + if (i & bits8[j]) + *p |= bits32[un_pbox[8 * b + j]]; + } + } + + des_initialised = 1; +} + + +static void +setup_salt(u_int32_t salt) +{ + u_int32_t obit, saltbit; + int i; + + if (salt == old_salt) + return; + old_salt = salt; + + saltbits = 0L; + saltbit = 1; + obit = 0x800000; + for (i = 0; i < 24; i++) { + if (salt & saltbit) + saltbits |= obit; + saltbit <<= 1; + obit >>= 1; + } +} + + +static void +des_setkey(const char *key) +{ + u_int32_t k0, k1, rawkey0, rawkey1; + int shifts, round; + + des_init(); + + rawkey0 = ntohl(*(const u_int32_t *) key); + rawkey1 = ntohl(*(const u_int32_t *) (key + 4)); + + if ((rawkey0 | rawkey1) + && rawkey0 == old_rawkey0 + && rawkey1 == old_rawkey1) { + /* + * Already setup for this key. + * This optimisation fails on a zero key (which is weak and + * has bad parity anyway) in order to simplify the starting + * conditions. + */ + return; + } + old_rawkey0 = rawkey0; + old_rawkey1 = rawkey1; + + /* + * Do key permutation and split into two 28-bit subkeys. + */ + k0 = key_perm_maskl[0][rawkey0 >> 25] + | key_perm_maskl[1][(rawkey0 >> 17) & 0x7f] + | key_perm_maskl[2][(rawkey0 >> 9) & 0x7f] + | key_perm_maskl[3][(rawkey0 >> 1) & 0x7f] + | key_perm_maskl[4][rawkey1 >> 25] + | key_perm_maskl[5][(rawkey1 >> 17) & 0x7f] + | key_perm_maskl[6][(rawkey1 >> 9) & 0x7f] + | key_perm_maskl[7][(rawkey1 >> 1) & 0x7f]; + k1 = key_perm_maskr[0][rawkey0 >> 25] + | key_perm_maskr[1][(rawkey0 >> 17) & 0x7f] + | key_perm_maskr[2][(rawkey0 >> 9) & 0x7f] + | key_perm_maskr[3][(rawkey0 >> 1) & 0x7f] + | key_perm_maskr[4][rawkey1 >> 25] + | key_perm_maskr[5][(rawkey1 >> 17) & 0x7f] + | key_perm_maskr[6][(rawkey1 >> 9) & 0x7f] + | key_perm_maskr[7][(rawkey1 >> 1) & 0x7f]; + /* + * Rotate subkeys and do compression permutation. + */ + shifts = 0; + for (round = 0; round < 16; round++) { + u_int32_t t0, t1; + + shifts += key_shifts[round]; + + t0 = (k0 << shifts) | (k0 >> (28 - shifts)); + t1 = (k1 << shifts) | (k1 >> (28 - shifts)); + + de_keysl[15 - round] = + en_keysl[round] = comp_maskl[0][(t0 >> 21) & 0x7f] + | comp_maskl[1][(t0 >> 14) & 0x7f] + | comp_maskl[2][(t0 >> 7) & 0x7f] + | comp_maskl[3][t0 & 0x7f] + | comp_maskl[4][(t1 >> 21) & 0x7f] + | comp_maskl[5][(t1 >> 14) & 0x7f] + | comp_maskl[6][(t1 >> 7) & 0x7f] + | comp_maskl[7][t1 & 0x7f]; + + de_keysr[15 - round] = + en_keysr[round] = comp_maskr[0][(t0 >> 21) & 0x7f] + | comp_maskr[1][(t0 >> 14) & 0x7f] + | comp_maskr[2][(t0 >> 7) & 0x7f] + | comp_maskr[3][t0 & 0x7f] + | comp_maskr[4][(t1 >> 21) & 0x7f] + | comp_maskr[5][(t1 >> 14) & 0x7f] + | comp_maskr[6][(t1 >> 7) & 0x7f] + | comp_maskr[7][t1 & 0x7f]; + } +} + + +static int +do_des( u_int32_t l_in, u_int32_t r_in, u_int32_t *l_out, u_int32_t *r_out, int count) +{ + /* l_in, r_in, l_out, and r_out are in pseudo-"big-endian" format. */ + u_int32_t l, r, *kl, *kr, *kl1, *kr1; + u_int32_t f, r48l, r48r; + int round; + + if (count == 0) { + return 1; + } + if (count > 0) { + /* Encrypting */ + kl1 = en_keysl; + kr1 = en_keysr; + } else { + /* Decrypting */ + count = -count; + kl1 = de_keysl; + kr1 = de_keysr; + } + + /* Do initial permutation (IP). */ + l = ip_maskl[0][l_in >> 24] + | ip_maskl[1][(l_in >> 16) & 0xff] + | ip_maskl[2][(l_in >> 8) & 0xff] + | ip_maskl[3][l_in & 0xff] + | ip_maskl[4][r_in >> 24] + | ip_maskl[5][(r_in >> 16) & 0xff] + | ip_maskl[6][(r_in >> 8) & 0xff] + | ip_maskl[7][r_in & 0xff]; + r = ip_maskr[0][l_in >> 24] + | ip_maskr[1][(l_in >> 16) & 0xff] + | ip_maskr[2][(l_in >> 8) & 0xff] + | ip_maskr[3][l_in & 0xff] + | ip_maskr[4][r_in >> 24] + | ip_maskr[5][(r_in >> 16) & 0xff] + | ip_maskr[6][(r_in >> 8) & 0xff] + | ip_maskr[7][r_in & 0xff]; + + while (count--) { + /* Do each round. */ + kl = kl1; + kr = kr1; + round = 16; + do { + /* Expand R to 48 bits (simulate the E-box). */ + r48l = ((r & 0x00000001) << 23) + | ((r & 0xf8000000) >> 9) + | ((r & 0x1f800000) >> 11) + | ((r & 0x01f80000) >> 13) + | ((r & 0x001f8000) >> 15); + r48r = ((r & 0x0001f800) << 7) + | ((r & 0x00001f80) << 5) + | ((r & 0x000001f8) << 3) + | ((r & 0x0000001f) << 1) + | ((r & 0x80000000) >> 31); + /* + * Do salting for crypt() and friends, and + * XOR with the permuted key. + */ + f = (r48l ^ r48r) & saltbits; + r48l ^= f ^ *kl++; + r48r ^= f ^ *kr++; + /* + * Do sbox lookups (which shrink it back to 32 bits) + * and do the pbox permutation at the same time. + */ + f = psbox[0][m_sbox[0][r48l >> 12]] + | psbox[1][m_sbox[1][r48l & 0xfff]] + | psbox[2][m_sbox[2][r48r >> 12]] + | psbox[3][m_sbox[3][r48r & 0xfff]]; + /* Now that we've permuted things, complete f(). */ + f ^= l; + l = r; + r = f; + } while (--round); + r = l; + l = f; + } + /* Do final permutation (inverse of IP). */ + *l_out = fp_maskl[0][l >> 24] + | fp_maskl[1][(l >> 16) & 0xff] + | fp_maskl[2][(l >> 8) & 0xff] + | fp_maskl[3][l & 0xff] + | fp_maskl[4][r >> 24] + | fp_maskl[5][(r >> 16) & 0xff] + | fp_maskl[6][(r >> 8) & 0xff] + | fp_maskl[7][r & 0xff]; + *r_out = fp_maskr[0][l >> 24] + | fp_maskr[1][(l >> 16) & 0xff] + | fp_maskr[2][(l >> 8) & 0xff] + | fp_maskr[3][l & 0xff] + | fp_maskr[4][r >> 24] + | fp_maskr[5][(r >> 16) & 0xff] + | fp_maskr[6][(r >> 8) & 0xff] + | fp_maskr[7][r & 0xff]; + return(0); +} + + +#if 0 +static int +des_cipher(const char *in, char *out, u_int32_t salt, int count) +{ + u_int32_t l_out, r_out, rawl, rawr; + int retval; + union { + u_int32_t *ui32; + const char *c; + } trans; + + des_init(); + + setup_salt(salt); + + trans.c = in; + rawl = ntohl(*trans.ui32++); + rawr = ntohl(*trans.ui32); + + retval = do_des(rawl, rawr, &l_out, &r_out, count); + + trans.c = out; + *trans.ui32++ = htonl(l_out); + *trans.ui32 = htonl(r_out); + return(retval); +} +#endif + + +void +setkey(const char *key) +{ + int i, j; + u_int32_t packed_keys[2]; + u_char *p; + + p = (u_char *) packed_keys; + + for (i = 0; i < 8; i++) { + p[i] = 0; + for (j = 0; j < 8; j++) + if (*key++ & 1) + p[i] |= bits8[j]; + } + des_setkey((char *)p); +} + + +void +encrypt(char *block, int flag) +{ + u_int32_t io[2]; + u_char *p; + int i, j; + + des_init(); + + setup_salt(0L); + p = (u_char*)block; + for (i = 0; i < 2; i++) { + io[i] = 0L; + for (j = 0; j < 32; j++) + if (*p++ & 1) + io[i] |= bits32[j]; + } + do_des(io[0], io[1], io, io + 1, flag ? -1 : 1); + for (i = 0; i < 2; i++) + for (j = 0; j < 32; j++) + block[(i << 5) | j] = (io[i] & bits32[j]) ? 1 : 0; +} + +char *__des_crypt(const unsigned char *key, const unsigned char *setting) +{ + u_int32_t count, salt, l, r0, r1, keybuf[2]; + u_char *p, *q; + static char output[21]; + + des_init(); + + /* + * Copy the key, shifting each character up by one bit + * and padding with zeros. + */ + q = (u_char *)keybuf; + while (q - (u_char *)keybuf - 8) { + *q++ = *key << 1; + if (*(q - 1)) + key++; + } + des_setkey((char *)keybuf); + +#if 0 + if (*setting == _PASSWORD_EFMT1) { + int i; + /* + * "new"-style: + * setting - underscore, 4 bytes of count, 4 bytes of salt + * key - unlimited characters + */ + for (i = 1, count = 0L; i < 5; i++) + count |= ascii_to_bin(setting[i]) << ((i - 1) * 6); + + for (i = 5, salt = 0L; i < 9; i++) + salt |= ascii_to_bin(setting[i]) << ((i - 5) * 6); + + while (*key) { + /* + * Encrypt the key with itself. + */ + if (des_cipher((char *)keybuf, (char *)keybuf, 0L, 1)) + return(NULL); + /* + * And XOR with the next 8 characters of the key. + */ + q = (u_char *)keybuf; + while (q - (u_char *)keybuf - 8 && *key) + *q++ ^= *key++ << 1; + + des_setkey((char *)keybuf); + } + strncpy(output, setting, 9); + + /* + * Double check that we weren't given a short setting. + * If we were, the above code will probably have created + * wierd values for count and salt, but we don't really care. + * Just make sure the output string doesn't have an extra + * NUL in it. + */ + output[9] = '\0'; + p = (u_char *)output + strlen(output); + } else +#endif + { + /* + * "old"-style: + * setting - 2 bytes of salt + * key - up to 8 characters + */ + count = 25; + + salt = (ascii_to_bin(setting[1]) << 6) + | ascii_to_bin(setting[0]); + + output[0] = setting[0]; + /* + * If the encrypted password that the salt was extracted from + * is only 1 character long, the salt will be corrupted. We + * need to ensure that the output string doesn't have an extra + * NUL in it! + */ + output[1] = setting[1] ? setting[1] : output[0]; + + p = (u_char *)output + 2; + } + setup_salt(salt); + /* + * Do it. + */ + if (do_des(0L, 0L, &r0, &r1, (int)count)) + return(NULL); + /* + * Now encode the result... + */ + l = (r0 >> 8); + *p++ = ascii64[(l >> 18) & 0x3f]; + *p++ = ascii64[(l >> 12) & 0x3f]; + *p++ = ascii64[(l >> 6) & 0x3f]; + *p++ = ascii64[l & 0x3f]; + + l = (r0 << 16) | ((r1 >> 16) & 0xffff); + *p++ = ascii64[(l >> 18) & 0x3f]; + *p++ = ascii64[(l >> 12) & 0x3f]; + *p++ = ascii64[(l >> 6) & 0x3f]; + *p++ = ascii64[l & 0x3f]; + + l = r1 << 2; + *p++ = ascii64[(l >> 12) & 0x3f]; + *p++ = ascii64[(l >> 6) & 0x3f]; + *p++ = ascii64[l & 0x3f]; + *p = 0; + + return(output); +} + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libcrypt/libcrypt.h b/l4/pkg/uclibc/lib/contrib/uclibc/libcrypt/libcrypt.h new file mode 100644 index 00000000..11866200 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libcrypt/libcrypt.h @@ -0,0 +1,20 @@ +/* prototypes for internal crypt functions + * + * Copyright (C) 2000-2006 by Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#ifndef __LIBCRYPT_H__ +#define __LIBCRYPT_H__ + +extern char *__md5_crypt(const unsigned char *pw, const unsigned char *salt) attribute_hidden; +extern char *__des_crypt(const unsigned char *pw, const unsigned char *salt) attribute_hidden; + +/* shut up gcc-4.x signed warnings */ +#define strcpy(dst,src) strcpy((char*)dst,(char*)src) +#define strlen(s) strlen((char*)s) +#define strncat(dst,src,n) strncat((char*)dst,(char*)src,n) +#define strncmp(s1,s2,n) strncmp((char*)s1,(char*)s2,n) + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libcrypt/md5.c b/l4/pkg/uclibc/lib/contrib/uclibc/libcrypt/md5.c new file mode 100644 index 00000000..1af11ed8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libcrypt/md5.c @@ -0,0 +1,637 @@ +/* + * MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm + * + * Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All + * rights reserved. + * + * License to copy and use this software is granted provided that it + * is identified as the "RSA Data Security, Inc. MD5 Message-Digest + * Algorithm" in all material mentioning or referencing this software + * or this function. + * + * License is also granted to make and use derivative works provided + * that such works are identified as "derived from the RSA Data + * Security, Inc. MD5 Message-Digest Algorithm" in all material + * mentioning or referencing the derived work. + * + * RSA Data Security, Inc. makes no representations concerning either + * the merchantability of this software or the suitability of this + * software for any particular purpose. It is provided "as is" + * without express or implied warranty of any kind. + * + * These notices must be retained in any copies of any part of this + * documentation and/or software. + * + * $FreeBSD: src/lib/libmd/md5c.c,v 1.9.2.1 1999/08/29 14:57:12 peter Exp $ + * + * This code is the same as the code published by RSA Inc. It has been + * edited for clarity and style only. + * + * ---------------------------------------------------------------------------- + * The md5_crypt() function was taken from freeBSD's libcrypt and contains + * this license: + * "THE BEER-WARE LICENSE" (Revision 42): + * wrote this file. As long as you retain this notice you + * can do whatever you want with this stuff. If we meet some day, and you think + * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp + * + * $FreeBSD: src/lib/libcrypt/crypt.c,v 1.7.2.1 1999/08/29 14:56:33 peter Exp $ + * + * ---------------------------------------------------------------------------- + * On April 19th, 2001 md5_crypt() was modified to make it reentrant + * by Erik Andersen + * + * + * June 28, 2001 Manuel Novoa III + * + * "Un-inlined" code using loops and static const tables in order to + * reduce generated code size (on i386 from approx 4k to approx 2.5k). + * + * June 29, 2001 Manuel Novoa III + * + * Completely removed static PADDING array. + * + * Reintroduced the loop unrolling in MD5_Transform and added the + * MD5_SIZE_OVER_SPEED option for configurability. Define below as: + * 0 fully unrolled loops + * 1 partially unrolled (4 ops per loop) + * 2 no unrolling -- introduces the need to swap 4 variables (slow) + * 3 no unrolling and all 4 loops merged into one with switch + * in each loop (glacial) + * On i386, sizes are roughly (-Os -fno-builtin): + * 0: 3k 1: 2.5k 2: 2.2k 3: 2k + * + * + * Since SuSv3 does not require crypt_r, modified again August 7, 2002 + * by Erik Andersen to remove reentrance stuff... + */ + +/* + * Valid values are 1 (fastest/largest) to 3 (smallest/slowest). + */ +#define MD5_SIZE_OVER_SPEED 3 + +/**********************************************************************/ + +#include +#include +#include +#include +#include +#include +#include "libcrypt.h" + +/* MD5 context. */ +struct MD5Context { + u_int32_t state[4]; /* state (ABCD) */ + u_int32_t count[2]; /* number of bits, modulo 2^64 (lsb first) */ + unsigned char buffer[64]; /* input buffer */ +}; + +static void __md5_Init (struct MD5Context *); +static void __md5_Update (struct MD5Context *, const unsigned char *, unsigned int); +static void __md5_Pad (struct MD5Context *); +static void __md5_Final (unsigned char [16], struct MD5Context *); +static void __md5_Transform __P((u_int32_t [4], const unsigned char [64])); + + +#define MD5_MAGIC_STR "$1$" +#define MD5_MAGIC_LEN (sizeof(MD5_MAGIC_STR) - 1) +static const unsigned char __md5__magic[] = MD5_MAGIC_STR; +static const unsigned char __md5_itoa64[] = /* 0 ... 63 => ascii - 64 */ + "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + + +#ifdef i386 +#define __md5_Encode memcpy +#define __md5_Decode memcpy +#else /* i386 */ + +/* + * __md5_Encodes input (u_int32_t) into output (unsigned char). Assumes len is + * a multiple of 4. + */ + +static void +__md5_Encode (unsigned char *output, u_int32_t *input, unsigned int len) +{ + unsigned int i, j; + + for (i = 0, j = 0; j < len; i++, j += 4) { + output[j] = (unsigned char)(input[i] & 0xff); + output[j+1] = (unsigned char)((input[i] >> 8) & 0xff); + output[j+2] = (unsigned char)((input[i] >> 16) & 0xff); + output[j+3] = (unsigned char)((input[i] >> 24) & 0xff); + } +} + +/* + * __md5_Decodes input (unsigned char) into output (u_int32_t). Assumes len is + * a multiple of 4. + */ + +static void +__md5_Decode (u_int32_t *output, const unsigned char *input, unsigned int len) +{ + unsigned int i, j; + + for (i = 0, j = 0; j < len; i++, j += 4) + output[i] = ((u_int32_t)input[j]) | (((u_int32_t)input[j+1]) << 8) | + (((u_int32_t)input[j+2]) << 16) | (((u_int32_t)input[j+3]) << 24); +} +#endif /* i386 */ + +/* F, G, H and I are basic MD5 functions. */ +#define F(x, y, z) (((x) & (y)) | ((~x) & (z))) +#define G(x, y, z) (((x) & (z)) | ((y) & (~z))) +#define H(x, y, z) ((x) ^ (y) ^ (z)) +#define I(x, y, z) ((y) ^ ((x) | (~z))) + +/* ROTATE_LEFT rotates x left n bits. */ +#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) + +/* + * FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. + * Rotation is separate from addition to prevent recomputation. + */ +#define FF(a, b, c, d, x, s, ac) { \ + (a) += F ((b), (c), (d)) + (x) + (u_int32_t)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } +#define GG(a, b, c, d, x, s, ac) { \ + (a) += G ((b), (c), (d)) + (x) + (u_int32_t)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } +#define HH(a, b, c, d, x, s, ac) { \ + (a) += H ((b), (c), (d)) + (x) + (u_int32_t)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } +#define II(a, b, c, d, x, s, ac) { \ + (a) += I ((b), (c), (d)) + (x) + (u_int32_t)(ac); \ + (a) = ROTATE_LEFT ((a), (s)); \ + (a) += (b); \ + } + +/* MD5 initialization. Begins an MD5 operation, writing a new context. */ + +static void __md5_Init (struct MD5Context *context) +{ + context->count[0] = context->count[1] = 0; + + /* Load magic initialization constants. */ + context->state[0] = 0x67452301; + context->state[1] = 0xefcdab89; + context->state[2] = 0x98badcfe; + context->state[3] = 0x10325476; +} + +/* + * MD5 block update operation. Continues an MD5 message-digest + * operation, processing another message block, and updating the + * context. + */ + +static void __md5_Update ( struct MD5Context *context, const unsigned char *input, unsigned int inputLen) +{ + unsigned int i, idx, partLen; + + /* Compute number of bytes mod 64 */ + idx = (unsigned int)((context->count[0] >> 3) & 0x3F); + + /* Update number of bits */ + if ((context->count[0] += ((u_int32_t)inputLen << 3)) + < ((u_int32_t)inputLen << 3)) + context->count[1]++; + context->count[1] += ((u_int32_t)inputLen >> 29); + + partLen = 64 - idx; + + /* Transform as many times as possible. */ + if (inputLen >= partLen) { + memcpy((void *)&context->buffer[idx], (const void *)input, + partLen); + __md5_Transform (context->state, context->buffer); + + for (i = partLen; i + 63 < inputLen; i += 64) + __md5_Transform (context->state, &input[i]); + + idx = 0; + } + else + i = 0; + + /* Buffer remaining input */ + memcpy ((void *)&context->buffer[idx], (const void *)&input[i], + inputLen-i); +} + +/* + * MD5 padding. Adds padding followed by original length. + */ + +static void __md5_Pad ( struct MD5Context *context) +{ + unsigned char bits[8]; + unsigned int idx, padLen; + unsigned char PADDING[64]; + + memset(PADDING, 0, sizeof(PADDING)); + PADDING[0] = 0x80; + + /* Save number of bits */ + __md5_Encode (bits, context->count, 8); + + /* Pad out to 56 mod 64. */ + idx = (unsigned int)((context->count[0] >> 3) & 0x3f); + padLen = (idx < 56) ? (56 - idx) : (120 - idx); + __md5_Update (context, PADDING, padLen); + + /* Append length (before padding) */ + __md5_Update (context, bits, 8); +} + +/* + * MD5 finalization. Ends an MD5 message-digest operation, writing the + * the message digest and zeroizing the context. + */ + +static void __md5_Final ( unsigned char digest[16], struct MD5Context *context) +{ + /* Do padding. */ + __md5_Pad (context); + + /* Store state in digest */ + __md5_Encode (digest, context->state, 16); + + /* Zeroize sensitive information. */ + memset ((void *)context, 0, sizeof (*context)); +} + +/* MD5 basic transformation. Transforms state based on block. */ + +static void __md5_Transform (u_int32_t state[4], const unsigned char block[64]) +{ + u_int32_t a, b, c, d, x[16]; +#if MD5_SIZE_OVER_SPEED > 1 + u_int32_t temp; + const char *ps; + + static const char S[] = { + 7, 12, 17, 22, + 5, 9, 14, 20, + 4, 11, 16, 23, + 6, 10, 15, 21 + }; +#endif /* MD5_SIZE_OVER_SPEED > 1 */ + +#if MD5_SIZE_OVER_SPEED > 0 + const u_int32_t *pc; + const char *pp; + int i; + + static const u_int32_t C[] = { + /* round 1 */ + 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, + 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, + 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, + 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, + /* round 2 */ + 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, + 0xd62f105d, 0x2441453, 0xd8a1e681, 0xe7d3fbc8, + 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, + 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a, + /* round 3 */ + 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, + 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, + 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x4881d05, + 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665, + /* round 4 */ + 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, + 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1, + 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, + 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391 + }; + + static const char P[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, /* 1 */ + 1, 6, 11, 0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12, /* 2 */ + 5, 8, 11, 14, 1, 4, 7, 10, 13, 0, 3, 6, 9, 12, 15, 2, /* 3 */ + 0, 7, 14, 5, 12, 3, 10, 1, 8, 15, 6, 13, 4, 11, 2, 9 /* 4 */ + }; + +#endif /* MD5_SIZE_OVER_SPEED > 0 */ + + __md5_Decode (x, block, 64); + + a = state[0]; b = state[1]; c = state[2]; d = state[3]; + +#if MD5_SIZE_OVER_SPEED > 2 + pc = C; pp = P; ps = S - 4; + + for ( i = 0 ; i < 64 ; i++ ) { + if ((i&0x0f) == 0) ps += 4; + temp = a; + switch (i>>4) { + case 0: + temp += F(b,c,d); + break; + case 1: + temp += G(b,c,d); + break; + case 2: + temp += H(b,c,d); + break; + case 3: + temp += I(b,c,d); + break; + } + temp += x[(int)(*pp++)] + *pc++; + temp = ROTATE_LEFT(temp, ps[i&3]); + temp += b; + a = d; d = c; c = b; b = temp; + } +#elif MD5_SIZE_OVER_SPEED > 1 + pc = C; pp = P; ps = S; + + /* Round 1 */ + for ( i = 0 ; i < 16 ; i++ ) { + FF (a, b, c, d, x[(int)(*pp++)], ps[i&0x3], *pc++); + temp = d; d = c; c = b; b = a; a = temp; + } + + /* Round 2 */ + ps += 4; + for ( ; i < 32 ; i++ ) { + GG (a, b, c, d, x[(int)(*pp++)], ps[i&0x3], *pc++); + temp = d; d = c; c = b; b = a; a = temp; + } + /* Round 3 */ + ps += 4; + for ( ; i < 48 ; i++ ) { + HH (a, b, c, d, x[(int)(*pp++)], ps[i&0x3], *pc++); + temp = d; d = c; c = b; b = a; a = temp; + } + + /* Round 4 */ + ps += 4; + for ( ; i < 64 ; i++ ) { + II (a, b, c, d, x[(int)(*pp++)], ps[i&0x3], *pc++); + temp = d; d = c; c = b; b = a; a = temp; + } +#elif MD5_SIZE_OVER_SPEED > 0 + pc = C; pp = P; + + /* Round 1 */ + for ( i = 0 ; i < 4 ; i++ ) { + FF (a, b, c, d, x[(int)(*pp++)], 7, *pc++); + FF (d, a, b, c, x[(int)(*pp++)], 12, *pc++); + FF (c, d, a, b, x[(int)(*pp++)], 17, *pc++); + FF (b, c, d, a, x[(int)(*pp++)], 22, *pc++); + } + + /* Round 2 */ + for ( i = 0 ; i < 4 ; i++ ) { + GG (a, b, c, d, x[(int)(*pp++)], 5, *pc++); + GG (d, a, b, c, x[(int)(*pp++)], 9, *pc++); + GG (c, d, a, b, x[(int)(*pp++)], 14, *pc++); + GG (b, c, d, a, x[(int)(*pp++)], 20, *pc++); + } + /* Round 3 */ + for ( i = 0 ; i < 4 ; i++ ) { + HH (a, b, c, d, x[(int)(*pp++)], 4, *pc++); + HH (d, a, b, c, x[(int)(*pp++)], 11, *pc++); + HH (c, d, a, b, x[(int)(*pp++)], 16, *pc++); + HH (b, c, d, a, x[(int)(*pp++)], 23, *pc++); + } + + /* Round 4 */ + for ( i = 0 ; i < 4 ; i++ ) { + II (a, b, c, d, x[(int)(*pp++)], 6, *pc++); + II (d, a, b, c, x[(int)(*pp++)], 10, *pc++); + II (c, d, a, b, x[(int)(*pp++)], 15, *pc++); + II (b, c, d, a, x[(int)(*pp++)], 21, *pc++); + } +#else + /* Round 1 */ +#define S11 7 +#define S12 12 +#define S13 17 +#define S14 22 + FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */ + FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */ + FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */ + FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */ + FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */ + FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */ + FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */ + FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */ + FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */ + FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */ + FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */ + FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */ + FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */ + FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */ + FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */ + FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */ + + /* Round 2 */ +#define S21 5 +#define S22 9 +#define S23 14 +#define S24 20 + GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */ + GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */ + GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */ + GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */ + GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */ + GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */ + GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */ + GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */ + GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */ + GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */ + GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */ + GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */ + GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */ + GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */ + GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */ + GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */ + + /* Round 3 */ +#define S31 4 +#define S32 11 +#define S33 16 +#define S34 23 + HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */ + HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */ + HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */ + HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */ + HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */ + HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */ + HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */ + HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */ + HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */ + HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */ + HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */ + HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */ + HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */ + HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */ + HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */ + HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */ + + /* Round 4 */ +#define S41 6 +#define S42 10 +#define S43 15 +#define S44 21 + II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */ + II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */ + II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */ + II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */ + II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */ + II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */ + II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */ + II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */ + II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */ + II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */ + II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */ + II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */ + II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */ + II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */ + II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */ + II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */ +#endif + + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + + /* Zeroize sensitive information. */ + memset ((void *)x, 0, sizeof (x)); +} + + +static void __md5_to64( char *s, unsigned long v, int n) +{ + while (--n >= 0) { + *s++ = __md5_itoa64[v&0x3f]; + v >>= 6; + } +} + +/* + * UNIX password + * + * Use MD5 for what it is best at... + */ + +char *__md5_crypt(const unsigned char *pw, const unsigned char *salt) +{ + /* Static stuff */ + /* "$1$" + salt_up_to_8_chars + "$" + 22_bytes_of_hash + NUL */ + static char passwd[3 + 8 + 1 + 22 + 1]; + + const unsigned char *sp, *ep; + char *p; + unsigned char final[17]; /* final[16] exists only to aid in looping */ + int sl,pl,i,pw_len; + struct MD5Context ctx,ctx1; + unsigned long l; + + /* Refine the Salt first */ + sp = salt; + + /* If it starts with the magic string, then skip that */ + if(!strncmp(sp,__md5__magic,MD5_MAGIC_LEN)) + sp += MD5_MAGIC_LEN; + + /* It stops at the first '$', max 8 chars */ + for(ep=sp;*ep && *ep != '$' && ep < (sp+8);ep++) + continue; + + /* get the length of the true salt */ + sl = ep - sp; + + __md5_Init(&ctx); + + /* The password first, since that is what is most unknown */ + pw_len = strlen(pw); + __md5_Update(&ctx,pw,pw_len); + + /* Then our magic string */ + __md5_Update(&ctx,__md5__magic,MD5_MAGIC_LEN); + + /* Then the raw salt */ + __md5_Update(&ctx,sp,sl); + + /* Then just as many characters of the MD5(pw,salt,pw) */ + __md5_Init(&ctx1); + __md5_Update(&ctx1,pw,pw_len); + __md5_Update(&ctx1,sp,sl); + __md5_Update(&ctx1,pw,pw_len); + __md5_Final(final,&ctx1); + for(pl = pw_len; pl > 0; pl -= 16) + __md5_Update(&ctx,final,pl>16 ? 16 : pl); + + /* Don't leave anything around in vm they could use. */ + memset(final,0,sizeof final); + + /* Then something really weird... */ + for (i = pw_len; i ; i >>= 1) { + __md5_Update(&ctx, ((i&1) ? final : (const unsigned char *) pw), 1); + } + + /* Now make the output string */ + strcpy(passwd,__md5__magic); /* 3 bytes */ + strncpy(passwd+MD5_MAGIC_LEN,(char*)sp,sl); /* 8 or less */ + passwd[MD5_MAGIC_LEN+sl] = '$'; + + __md5_Final(final,&ctx); + + /* + * and now, just to make sure things don't run too fast + * On a 60 Mhz Pentium this takes 34 msec, so you would + * need 30 seconds to build a 1000 entry dictionary... + */ + for(i=0;i<1000;i++) { + __md5_Init(&ctx1); + if(i & 1) + __md5_Update(&ctx1,pw,pw_len); + else + __md5_Update(&ctx1,final,16); + + if(i % 3) + __md5_Update(&ctx1,sp,sl); + + if(i % 7) + __md5_Update(&ctx1,pw,pw_len); + + if(i & 1) + __md5_Update(&ctx1,final,16); + else + __md5_Update(&ctx1,pw,pw_len); + __md5_Final(final,&ctx1); + } + + /* Add 5*4+2 = 22 bytes of hash, + NUL byte. */ + p = passwd + MD5_MAGIC_LEN + sl + 1; + final[16] = final[5]; + for ( i=0 ; i < 5 ; i++ ) { + l = (final[i]<<16) | (final[i+6]<<8) | final[i+12]; + __md5_to64(p,l,4); + p += 4; + } + l = final[11]; + __md5_to64(p,l,2); + p += 2; + *p = '\0'; + + /* Don't leave anything around in vm they could use. */ + memset(final,0,sizeof final); + + return passwd; +} + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libintl/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libintl/Makefile new file mode 100644 index 00000000..c8dc9b46 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libintl/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../ +top_builddir=../ +include $(top_builddir)Rules.mak +all: libs +include Makefile.in +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libintl/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/libintl/Makefile.in new file mode 100644 index 00000000..22ae70cf --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libintl/Makefile.in @@ -0,0 +1,76 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +subdirs += libintl + +CFLAGS-libintl := -DNOT_IN_libc -DIS_IN_libintl $(SSP_ALL_CFLAGS) + +LDFLAGS-libintl.so := $(LDFLAGS) + +LIBS-libintl.so := $(LIBS) + +libintl_FULL_NAME := libintl-$(VERSION).so + +MOBJ := \ + gettext.o ngettext.o dgettext.o dcgettext.o dngettext.o dcngettext.o \ + textdomain.o bindtextdomain.o bind_textdomain_codeset.o \ + _nl_expand_alias.o _nl_msg_cat_cntr.o # glibc-isms + +libintl_DIR := $(top_srcdir)libintl +libintl_OUT := $(top_builddir)libintl + +libintl_MSRC := $(libintl_DIR)/intl.c +libintl_MOBJ := $(patsubst %.o,$(libintl_OUT)/%.o,$(MOBJ)) + +ifneq ($(DOMULTI),n) +CFLAGS-libintl += $(patsubst %,-DL_%,$(subst .o,,$(notdir $(libintl_MOBJ)))) +endif + +ifeq ($(DOPIC),y) +libintl-a-y := $(libintl_MOBJ:.o=.os) +else +libintl-a-y := $(libintl_MOBJ) +endif +libintl-so-y := $(libintl_MOBJ:.o=.os) + +lib-a-$(UCLIBC_HAS_GETTEXT_AWARENESS) += $(top_builddir)lib/libintl.a +lib-so-$(UCLIBC_HAS_GETTEXT_AWARENESS) += $(top_builddir)lib/libintl.so +objclean-y += CLEAN_libintl + +ifeq ($(DOMULTI),n) +ifeq ($(DOPIC),y) +$(top_builddir)lib/libintl.so: $(top_builddir)lib/libintl.a $(libc.depend) +else +$(top_builddir)lib/libintl.so: $(libintl_OUT)/libintl_so.a $(libc.depend) +endif + $(call link.so,$(libintl_FULL_NAME),$(ABI_VERSION)) +else +$(top_builddir)lib/libintl.so: $(libintl_OUT)/libintl.oS | $(libc.depend) + $(call linkm.so,$(libintl_FULL_NAME),$(ABI_VERSION)) +endif + +$(libintl_OUT)/libintl_so.a: $(libintl-so-y) + $(Q)$(RM) $@ + $(do_ar) + +$(libintl_OUT)/libintl.oS: $(libintl_MSRC) + $(Q)$(RM) $@ + $(compile-m) + +$(top_builddir)lib/libintl.a: $(libintl-a-y) + $(Q)$(INSTALL) -d $(dir $@) + $(Q)$(RM) $@ + $(do_ar) + +$(libintl_MOBJ): $(libintl_MSRC) + $(compile.m) + +$(libintl_MOBJ:.o=.os): $(libintl_MSRC) + $(compile.m) + +CLEAN_libintl: + $(do_rm) $(addprefix $(libintl_OUT)/*., o os oS a) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libintl/intl.c b/l4/pkg/uclibc/lib/contrib/uclibc/libintl/intl.c new file mode 100644 index 00000000..e42a999c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libintl/intl.c @@ -0,0 +1,154 @@ +/* Copyright (C) 2003 Manuel Novoa III + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* + * Stub version of libintl. + * + * Aug 30, 2003 + * Add some hidden names to support locale-enabled libstd++. + */ + +#include +#include +#include + +#undef __OPTIMIZE__ +#include + +/**********************************************************************/ +#ifdef L_gettext + +char *gettext(const char *msgid) +{ + return (char *) msgid; +} + +#endif +/**********************************************************************/ +#ifdef L_dgettext + +char *dgettext(const char *domainname, + const char *msgid) +{ + return (char *) msgid; +} + +#endif +/**********************************************************************/ +#ifdef L_dcgettext + +char *dcgettext(const char *domainname, + const char *msgid, int category) +{ + return (char *) msgid; +} + +#endif +/**********************************************************************/ +#ifdef L_ngettext + +char *ngettext(const char *msgid1, const char *msgid2, + unsigned long int n) +{ + return (char *) ((n == 1) ? msgid1 : msgid2); +} + +#endif +/**********************************************************************/ +#ifdef L_dngettext + +char *dngettext(const char *domainname, const char *msgid1, + const char *msgid2, unsigned long int n) +{ + return (char *) ((n == 1) ? msgid1 : msgid2); +} + +#endif +/**********************************************************************/ +#ifdef L_dcngettext + +char *dcngettext(const char *domainname, const char *msgid1, + const char *msgid2, unsigned long int n, + int category) +{ + return (char *) ((n == 1) ? msgid1 : msgid2); +} + +#endif +/**********************************************************************/ +#ifdef L_textdomain + +char *textdomain(const char *domainname) +{ + static const char default_str[] = "messages"; + + if (domainname && *domainname && strcmp(domainname, default_str)) { + __set_errno(EINVAL); + return NULL; + } + return (char *) default_str; +} + +#endif +/**********************************************************************/ +#ifdef L_bindtextdomain + +char *bindtextdomain(const char *domainname, const char *dirname) +{ + static const char dir[] = "/"; + + if (!domainname || !*domainname + || (dirname +#if 1 + && ((dirname[0] != '/') || dirname[1]) +#else + && strcmp(dirname, dir) +#endif + ) + ) { + __set_errno(EINVAL); + return NULL; + } + + return (char *) dir; +} + +#endif +/**********************************************************************/ +#ifdef L_bind_textdomain_codeset + +/* Specify the character encoding in which the messages from the + DOMAINNAME message catalog will be returned. */ +char *bind_textdomain_codeset(const char *domainname, const char *codeset) +{ + if (!domainname || !*domainname || codeset) { + __set_errno(EINVAL); + } + return NULL; +} + +#endif +/**********************************************************************/ +#ifdef L__nl_expand_alias + +/* glibc-ism */ + +const char *_nl_expand_alias(const char * name); +const char *_nl_expand_alias(const char * name) +{ + return NULL; /* uClibc does not support locale aliases. */ +} + +#endif +/**********************************************************************/ +#ifdef L__nl_msg_cat_cntr + +/* glibc-ism */ + +int _nl_msg_cat_cntr = 0; + +#endif +/**********************************************************************/ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libm/Makefile new file mode 100644 index 00000000..c8dc9b46 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../ +top_builddir=../ +include $(top_builddir)Rules.mak +all: libs +include Makefile.in +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/libm/Makefile.in new file mode 100644 index 00000000..384365ca --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/Makefile.in @@ -0,0 +1,316 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# +# The routines included in this math library are derived from the +# math library for Apple's MacOS X/Darwin math library, which was +# itself swiped from FreeBSD. The original copyright information +# is as follows: +# +# Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. +# +# Developed at SunPro, a Sun Microsystems, Inc. business. +# Permission to use, copy, modify, and distribute this +# software is freely granted, provided that this notice +# is preserved. +# +# It has been ported to work with uClibc and generally behave +# by Erik Andersen +# + +subdirs += libm + +CFLAGS-libm := -DNOT_IN_libc -DIS_IN_libm $(SSP_ALL_CFLAGS) +CFLAGS-libm += -D_IEEE_LIBM + +LDFLAGS-libm.so := $(LDFLAGS) + +LIBS-libm.so := $(LIBS) + +libm_FULL_NAME := libm-$(VERSION).so + +libm_DIR:=$(top_srcdir)libm +libm_OUT:=$(top_builddir)libm + +libm_ARCH_DIR:=$(libm_DIR)/$(TARGET_ARCH) +libm_ARCH_OUT:=$(libm_OUT)/$(TARGET_ARCH) + +ifneq ($(TARGET_SUBARCH),) +libm_SUBARCH_DIR:=$(libm_DIR)/$(TARGET_ARCH)/$(TARGET_SUBARCH) +libm_SUBARCH_OUT:=$(libm_OUT)/$(TARGET_ARCH)/$(TARGET_SUBARCH) +endif + +ifeq ($(UCLIBC_HAS_FPU),y) +ifeq ($(DO_C99_MATH),y) +-include $(libm_ARCH_DIR)/Makefile.arch +-include $(libm_SUBARCH_DIR)/Makefile.arch +endif +endif + +FL_MSRC := float_wrappers.c +LD_MSRC := ldouble_wrappers.c + +ifeq ($(DO_C99_MATH),y) +libm_CSRC := \ + e_acos.c e_acosh.c e_asin.c e_atan2.c e_atanh.c e_cosh.c \ + e_exp.c e_fmod.c e_hypot.c \ + e_lgamma_r.c e_log.c e_log2.c e_log10.c \ + e_pow.c e_remainder.c e_rem_pio2.c e_scalb.c e_sinh.c \ + e_sqrt.c k_cos.c k_rem_pio2.c k_sin.c k_standard.c k_tan.c \ + s_asinh.c s_atan.c s_cbrt.c s_ceil.c s_copysign.c s_cos.c \ + s_erf.c s_expm1.c s_fabs.c s_finite.c s_floor.c s_frexp.c \ + s_ilogb.c s_ldexp.c s_lib_version.c s_lrint.c s_lround.c s_llround.c \ + s_log1p.c s_logb.c s_matherr.c s_modf.c s_nextafter.c \ + s_nextafterf.c s_round.c \ + s_rint.c s_scalbn.c s_signgam.c s_significand.c s_sin.c s_tan.c \ + s_tanh.c s_trunc.c \ + w_cabs.c \ + nan.c carg.c s_llrint.c \ + s_fpclassify.c s_fpclassifyf.c s_signbit.c s_signbitf.c \ + s_isnan.c s_isnanf.c s_isinf.c s_isinff.c s_finitef.c \ + s_fdim.c s_fma.c s_fmax.c s_fmin.c \ + s_remquo.c w_exp2.c + +# Not implemented [yet?], see comment in float_wrappers.c: +# fdimf.o fmaf.o fmaxf.o fminf.o +# nearbyintf.o remquof.o scalblnf.o tgammaf.o +FL_MOBJ := \ + acosf.o \ + acoshf.o \ + asinf.o \ + asinhf.o \ + atan2f.o \ + atanf.o \ + atanhf.o \ + cargf.o \ + cbrtf.o \ + ceilf.o \ + copysignf.o \ + cosf.o \ + coshf.o \ + erfcf.o \ + erff.o \ + exp2f.o \ + expf.o \ + expm1f.o \ + fabsf.o \ + floorf.o \ + fmodf.o \ + frexpf.o \ + gammaf.o \ + hypotf.o \ + ilogbf.o \ + ldexpf.o \ + lgammaf.o \ + llrintf.o \ + llroundf.o \ + log10f.o \ + log1pf.o \ + log2f.o \ + logbf.o \ + logf.o \ + lrintf.o \ + lroundf.o \ + modff.o \ + powf.o \ + remainderf.o \ + rintf.o \ + roundf.o \ + scalbf.o \ + scalbnf.o \ + significandf.o \ + sinf.o \ + sinhf.o \ + sqrtf.o \ + tanf.o \ + tanhf.o \ + truncf.o \ + +# Not implemented [yet?]: nexttowardl.o +LD_MOBJ := \ + __finitel.o \ + __fpclassifyl.o \ + __isinfl.o \ + __isnanl.o \ + __signbitl.o \ + acoshl.o \ + acosl.o \ + asinhl.o \ + asinl.o \ + atan2l.o \ + atanhl.o \ + atanl.o \ + cargl.o \ + cbrtl.o \ + ceill.o \ + copysignl.o \ + coshl.o \ + cosl.o \ + erfcl.o \ + erfl.o \ + exp2l.o \ + expl.o \ + expm1l.o \ + fabsl.o \ + fdiml.o \ + floorl.o \ + fmal.o \ + fmaxl.o \ + fminl.o \ + fmodl.o \ + frexpl.o \ + gammal.o \ + hypotl.o \ + ilogbl.o \ + ldexpl.o \ + lgammal.o \ + llrintl.o \ + llroundl.o \ + log10l.o \ + log1pl.o \ + log2l.o \ + logbl.o \ + logl.o \ + lrintl.o \ + lroundl.o \ + modfl.o \ + nearbyintl.o \ + nextafterl.o \ + powl.o \ + remainderl.o \ + remquol.o \ + rintl.o \ + roundl.o \ + scalblnl.o \ + scalbnl.o \ + significandl.o \ + sinhl.o \ + sinl.o \ + sqrtl.o \ + tanhl.o \ + tanl.o \ + tgammal.o \ + truncl.o \ + +else + +# This list of math functions was taken from POSIX/IEEE 1003.1b-1993 +libm_CSRC := \ + s_atan.c s_ceil.c s_cos.c \ + s_fabs.c s_floor.c s_frexp.c \ + s_ldexp.c s_modf.c s_sin.c \ + s_tan.c s_tanh.c \ + s_expm1.c s_scalbn.c s_copysign.c e_acos.c e_asin.c e_atan2.c \ + k_cos.c e_cosh.c e_exp.c e_fmod.c e_log.c e_log10.c e_pow.c \ + k_sin.c e_sinh.c e_sqrt.c k_tan.c e_rem_pio2.c k_rem_pio2.c \ + s_finite.c +# We'll add sqrtf to avoid problems with libstdc++ +FL_MOBJ := sqrtf.o +endif + +ifeq ($(DO_XSI_MATH),y) +libm_CSRC += e_j0.c e_j1.c e_jn.c +endif + +# assume that arch specific versions are provided as single sources/objects +ifeq ($(UCLIBC_HAS_FPU),y) +ifeq ($(DO_C99_MATH),y) +ifneq ($(strip $(libm_ARCH_OBJS)),) +CFLAGS-libm/$(TARGET_ARCH)/ := $(CFLAGS-libm) +CFLAGS-libm/$(TARGET_ARCH)/$(TARGET_SUBARCH)/ := $(CFLAGS-libm) + +# remove generic sources, if arch specific version is present +ifneq ($(strip $(libm_ARCH_SRC)),) +libm_CSRC := $(filter-out $(notdir $(libm_ARCH_SRC)),$(libm_CSRC)) +endif + +# remove generic objects built from multi-sources, if arch specific version is present +FL_MOBJ := $(filter-out $(notdir $(libm_ARCH_OBJS)),$(FL_MOBJ)) +LD_MOBJ := $(filter-out $(notdir $(libm_ARCH_OBJS)),$(LD_MOBJ)) + +# we also try to remove % if s_% is in arch specific subdir +FL_MOBJ := $(filter-out $(patsubst s_%.o,%.o,$(notdir $(libm_ARCH_OBJS))),$(FL_MOBJ)) +LD_MOBJ := $(filter-out $(patsubst s_%.o,%.o,$(notdir $(libm_ARCH_OBJS))),$(LD_MOBJ)) +endif +endif +endif + +libm_SRC := $(patsubst %.c,$(libm_DIR)/%.c,$(libm_CSRC)) +libm_OBJ := $(patsubst $(libm_DIR)/%.c,$(libm_OUT)/%.o,$(libm_SRC)) + +ifeq ($(strip $(UCLIBC_HAS_LONG_DOUBLE_MATH)),y) +libm_MSRC_LD := $(libm_DIR)/$(LD_MSRC) +libm_MOBJ_LD := $(patsubst %.o,$(libm_OUT)/%.o,$(LD_MOBJ)) +endif +libm_MSRC_FL := $(libm_DIR)/$(FL_MSRC) +libm_MOBJ_FL := $(patsubst %.o,$(libm_OUT)/%.o,$(FL_MOBJ)) + + +ifneq ($(DOMULTI),n) +CFLAGS-libm += $(patsubst %,-DL_%,$(subst .o,,$(notdir $(libm_MOBJ_FL)))) +ifeq ($(strip $(UCLIBC_HAS_LONG_DOUBLE_MATH)),y) +CFLAGS-libm += $(patsubst %,-DL_%,$(subst .o,,$(notdir $(libm_MOBJ_LD)))) +endif +endif + +libm_OBJS := $(libm_OBJ) $(libm_MOBJ_FL) $(libm_MOBJ_LD) + +ifeq ($(DOPIC),y) +libm-a-y += $(libm_OBJS:.o=.os) +else +libm-a-y += $(libm_OBJS) +endif +libm-so-y += $(libm_OBJS:.o=.os) + +lib-a-$(UCLIBC_HAS_FLOATS) += $(top_builddir)lib/libm.a +lib-so-$(UCLIBC_HAS_FLOATS) += $(top_builddir)lib/libm.so +objclean-y += CLEAN_libm + +ifeq ($(DOMULTI),n) +ifeq ($(DOPIC),y) +$(top_builddir)lib/libm.so: $(top_builddir)lib/libm.a $(libc.depend) +else +$(top_builddir)lib/libm.so: $(libm_OUT)/libm_so.a $(libc.depend) +endif + $(call link.so,$(libm_FULL_NAME),$(ABI_VERSION)) +else +$(top_builddir)lib/libm.so: $(libm_OUT)/libm.oS | $(libc.depend) + $(call linkm.so,$(libm_FULL_NAME),$(ABI_VERSION)) +endif + +$(libm_OUT)/libm_so.a: $(libm-so-y) + $(Q)$(RM) $@ + $(do_ar) + +$(libm_OUT)/libm.oS: $(libm_SRC) $(libm_MSRC_FL) $(libm_MSRC_LD) $(libm_ARCH_SRC) + $(Q)$(RM) $@ + $(compile-m) + +$(top_builddir)lib/libm.a: $(libm-a-y) + $(Q)$(INSTALL) -d $(dir $@) + $(Q)$(RM) $@ + $(do_ar) + +$(libm_MOBJ_FL): $(libm_MSRC_FL) + $(compile.m) + +$(libm_MOBJ_LD): $(libm_MSRC_LD) + $(compile.m) + +$(libm_MOBJ_FL:.o=.os): $(libm_MSRC_FL) + $(compile.m) + +$(libm_MOBJ_LD:.o=.os): $(libm_MSRC_LD) + $(compile.m) + +# spare us from adding a gazillion dummy two-liner files +$(libm_MOBJ_FL:.o=.i): $(libm_MSRC_FL) + $(compile.mi) + +$(libm_MOBJ_LD:.o=.i): $(libm_MSRC_LD) + $(compile.mi) + +CLEAN_libm: + $(do_rm) $(addprefix $(libm_OUT)/,$(foreach e, o os oS a,$(foreach d, *. */*. */*/*.,$(d)$(e)))) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/README b/l4/pkg/uclibc/lib/contrib/uclibc/libm/README new file mode 100644 index 00000000..306f03e4 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/README @@ -0,0 +1,15 @@ +The routines included in this math library are derived from the +math library for Apple's MacOS X/Darwin math library, which was +itself swiped from FreeBSD. The original copyright information +is as follows: + + Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + + Developed at SunPro, a Sun Microsystems, Inc. business. + Permission to use, copy, modify, and distribute this + software is freely granted, provided that this notice + is preserved. + +It has been ported to work with uClibc and generally behave +by Erik Andersen + 22 May, 2001 diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/carg.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/carg.c new file mode 100644 index 00000000..7b290b0b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/carg.c @@ -0,0 +1,29 @@ +/* Compute argument of complex double value. + Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +double +carg (__complex__ double x) +{ + return atan2 (__imag__ x, __real__ x); +} +libm_hidden_def(carg) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/e_acos.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/e_acos.c new file mode 100644 index 00000000..e64ac648 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/e_acos.c @@ -0,0 +1,115 @@ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* __ieee754_acos(x) + * Method : + * acos(x) = pi/2 - asin(x) + * acos(-x) = pi/2 + asin(x) + * For |x|<=0.5 + * acos(x) = pi/2 - (x + x*x^2*R(x^2)) (see asin.c) + * For x>0.5 + * acos(x) = pi/2 - (pi/2 - 2asin(sqrt((1-x)/2))) + * = 2asin(sqrt((1-x)/2)) + * = 2s + 2s*z*R(z) ...z=(1-x)/2, s=sqrt(z) + * = 2f + (2c + 2s*z*R(z)) + * where f=hi part of s, and c = (z-f*f)/(s+f) is the correction term + * for f so that f+c ~ sqrt(z). + * For x<-0.5 + * acos(x) = pi - 2asin(sqrt((1-|x|)/2)) + * = pi - 0.5*(s+s*z*R(z)), where z=(1-|x|)/2,s=sqrt(z) + * + * Special cases: + * if x is NaN, return x itself; + * if |x|>1, return NaN with invalid signal. + * + * Function needed: __ieee754_sqrt + */ + +#include "math.h" +#include "math_private.h" + +static const double +one= 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */ +pi = 3.14159265358979311600e+00, /* 0x400921FB, 0x54442D18 */ +pio2_hi = 1.57079632679489655800e+00, /* 0x3FF921FB, 0x54442D18 */ +pio2_lo = 6.12323399573676603587e-17, /* 0x3C91A626, 0x33145C07 */ +pS0 = 1.66666666666666657415e-01, /* 0x3FC55555, 0x55555555 */ +pS1 = -3.25565818622400915405e-01, /* 0xBFD4D612, 0x03EB6F7D */ +pS2 = 2.01212532134862925881e-01, /* 0x3FC9C155, 0x0E884455 */ +pS3 = -4.00555345006794114027e-02, /* 0xBFA48228, 0xB5688F3B */ +pS4 = 7.91534994289814532176e-04, /* 0x3F49EFE0, 0x7501B288 */ +pS5 = 3.47933107596021167570e-05, /* 0x3F023DE1, 0x0DFDF709 */ +qS1 = -2.40339491173441421878e+00, /* 0xC0033A27, 0x1C8A2D4B */ +qS2 = 2.02094576023350569471e+00, /* 0x40002AE5, 0x9C598AC8 */ +qS3 = -6.88283971605453293030e-01, /* 0xBFE6066C, 0x1B8D0159 */ +qS4 = 7.70381505559019352791e-02; /* 0x3FB3B8C5, 0xB12E9282 */ + +double attribute_hidden __ieee754_acos(double x) +{ + double z,p,q,r,w,s,c,df; + int32_t hx,ix; + GET_HIGH_WORD(hx,x); + ix = hx&0x7fffffff; + if(ix>=0x3ff00000) { /* |x| >= 1 */ + u_int32_t lx; + GET_LOW_WORD(lx,x); + if(((ix-0x3ff00000)|lx)==0) { /* |x|==1 */ + if(hx>0) return 0.0; /* acos(1) = 0 */ + else return pi+2.0*pio2_lo; /* acos(-1)= pi */ + } + return (x-x)/(x-x); /* acos(|x|>1) is NaN */ + } + if(ix<0x3fe00000) { /* |x| < 0.5 */ + if(ix<=0x3c600000) return pio2_hi+pio2_lo;/*if|x|<2**-57*/ + z = x*x; + p = z*(pS0+z*(pS1+z*(pS2+z*(pS3+z*(pS4+z*pS5))))); + q = one+z*(qS1+z*(qS2+z*(qS3+z*qS4))); + r = p/q; + return pio2_hi - (x - (pio2_lo-x*r)); + } else if (hx<0) { /* x < -0.5 */ + z = (one+x)*0.5; + p = z*(pS0+z*(pS1+z*(pS2+z*(pS3+z*(pS4+z*pS5))))); + q = one+z*(qS1+z*(qS2+z*(qS3+z*qS4))); + s = __ieee754_sqrt(z); + r = p/q; + w = r*s-pio2_lo; + return pi - 2.0*(s+w); + } else { /* x > 0.5 */ + z = (one-x)*0.5; + s = __ieee754_sqrt(z); + df = s; + SET_LOW_WORD(df,0); + c = (z-df*df)/(s+df); + p = z*(pS0+z*(pS1+z*(pS2+z*(pS3+z*(pS4+z*pS5))))); + q = one+z*(qS1+z*(qS2+z*(qS3+z*qS4))); + r = p/q; + w = r*s+c; + return 2.0*(df+w); + } +} + +/* + * wrap_acos(x) + */ +#ifndef _IEEE_LIBM +double acos(double x) +{ + double z = __ieee754_acos(x); + if (_LIB_VERSION == _IEEE_ || isnan(x)) + return z; + if (fabs(x) > 1.0) + return __kernel_standard(x, x, 1); /* acos(|x|>1) */ + return z; +} +#else +strong_alias(__ieee754_acos, acos) +#endif +libm_hidden_def(acos) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/e_acosh.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/e_acosh.c new file mode 100644 index 00000000..219b3d64 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/e_acosh.c @@ -0,0 +1,73 @@ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* __ieee754_acosh(x) + * Method : + * Based on + * acosh(x) = log [ x + sqrt(x*x-1) ] + * we have + * acosh(x) := log(x)+ln2, if x is large; else + * acosh(x) := log(2x-1/(sqrt(x*x-1)+x)) if x>2; else + * acosh(x) := log1p(t+sqrt(2.0*t+t*t)); where t=x-1. + * + * Special cases: + * acosh(x) is NaN with signal if x<1. + * acosh(NaN) is NaN without signal. + */ + +#include "math.h" +#include "math_private.h" + +static const double +one = 1.0, +ln2 = 6.93147180559945286227e-01; /* 0x3FE62E42, 0xFEFA39EF */ + +double attribute_hidden __ieee754_acosh(double x) +{ + double t; + int32_t hx; + u_int32_t lx; + EXTRACT_WORDS(hx,lx,x); + if(hx<0x3ff00000) { /* x < 1 */ + return (x-x)/(x-x); + } else if(hx >=0x41b00000) { /* x > 2**28 */ + if(hx >=0x7ff00000) { /* x is inf of NaN */ + return x+x; + } else + return __ieee754_log(x)+ln2; /* acosh(huge)=log(2x) */ + } else if(((hx-0x3ff00000)|lx)==0) { + return 0.0; /* acosh(1) = 0 */ + } else if (hx > 0x40000000) { /* 2**28 > x > 2 */ + t=x*x; + return __ieee754_log(2.0*x-one/(x+__ieee754_sqrt(t-one))); + } else { /* 10.98 + * asin(x) = pi/2 - 2*(s+s*z*R(z)) + * = pio2_hi - (2*(s+s*z*R(z)) - pio2_lo) + * For x<=0.98, let pio4_hi = pio2_hi/2, then + * f = hi part of s; + * c = sqrt(z) - f = (z-f*f)/(s+f) ...f+c=sqrt(z) + * and + * asin(x) = pi/2 - 2*(s+s*z*R(z)) + * = pio4_hi+(pio4-2s)-(2s*z*R(z)-pio2_lo) + * = pio4_hi+(pio4-2f)-(2s*z*R(z)-(pio2_lo+2c)) + * + * Special cases: + * if x is NaN, return x itself; + * if |x|>1, return NaN with invalid signal. + * + */ + +#include "math.h" +#include "math_private.h" + +static const double +one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */ +huge = 1.000e+300, +pio2_hi = 1.57079632679489655800e+00, /* 0x3FF921FB, 0x54442D18 */ +pio2_lo = 6.12323399573676603587e-17, /* 0x3C91A626, 0x33145C07 */ +pio4_hi = 7.85398163397448278999e-01, /* 0x3FE921FB, 0x54442D18 */ + /* coefficient for R(x^2) */ +pS0 = 1.66666666666666657415e-01, /* 0x3FC55555, 0x55555555 */ +pS1 = -3.25565818622400915405e-01, /* 0xBFD4D612, 0x03EB6F7D */ +pS2 = 2.01212532134862925881e-01, /* 0x3FC9C155, 0x0E884455 */ +pS3 = -4.00555345006794114027e-02, /* 0xBFA48228, 0xB5688F3B */ +pS4 = 7.91534994289814532176e-04, /* 0x3F49EFE0, 0x7501B288 */ +pS5 = 3.47933107596021167570e-05, /* 0x3F023DE1, 0x0DFDF709 */ +qS1 = -2.40339491173441421878e+00, /* 0xC0033A27, 0x1C8A2D4B */ +qS2 = 2.02094576023350569471e+00, /* 0x40002AE5, 0x9C598AC8 */ +qS3 = -6.88283971605453293030e-01, /* 0xBFE6066C, 0x1B8D0159 */ +qS4 = 7.70381505559019352791e-02; /* 0x3FB3B8C5, 0xB12E9282 */ + +double attribute_hidden __ieee754_asin(double x) +{ + double t=0.0,w,p,q,c,r,s; + int32_t hx,ix; + GET_HIGH_WORD(hx,x); + ix = hx&0x7fffffff; + if(ix>= 0x3ff00000) { /* |x|>= 1 */ + u_int32_t lx; + GET_LOW_WORD(lx,x); + if(((ix-0x3ff00000)|lx)==0) + /* asin(1)=+-pi/2 with inexact */ + return x*pio2_hi+x*pio2_lo; + return (x-x)/(x-x); /* asin(|x|>1) is NaN */ + } else if (ix<0x3fe00000) { /* |x|<0.5 */ + if(ix<0x3e400000) { /* if |x| < 2**-27 */ + if(huge+x>one) return x;/* return x with inexact if x!=0*/ + } else { + t = x*x; + p = t*(pS0+t*(pS1+t*(pS2+t*(pS3+t*(pS4+t*pS5))))); + q = one+t*(qS1+t*(qS2+t*(qS3+t*qS4))); + w = p/q; + return x+x*w; + } + } + /* 1> |x|>= 0.5 */ + w = one-fabs(x); + t = w*0.5; + p = t*(pS0+t*(pS1+t*(pS2+t*(pS3+t*(pS4+t*pS5))))); + q = one+t*(qS1+t*(qS2+t*(qS3+t*qS4))); + s = __ieee754_sqrt(t); + if(ix>=0x3FEF3333) { /* if |x| > 0.975 */ + w = p/q; + t = pio2_hi-(2.0*(s+s*w)-pio2_lo); + } else { + w = s; + SET_LOW_WORD(w,0); + c = (t-w*w)/(s+w); + r = p/q; + p = 2.0*s*r-(pio2_lo-2.0*c); + q = pio4_hi-2.0*w; + t = pio4_hi-(p-q); + } + if(hx>0) return t; else return -t; +} + +/* + * wrapper asin(x) + */ +#ifndef _IEEE_LIBM +double asin(double x) +{ + double z = __ieee754_asin(x); + if (_LIB_VERSION == _IEEE_ || isnan(x)) + return z; + if (fabs(x) > 1.0) + return __kernel_standard(x, x, 2); /* asin(|x|>1) */ + return z; +} +#else +strong_alias(__ieee754_asin, asin) +#endif +libm_hidden_def(asin) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/e_atan2.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/e_atan2.c new file mode 100644 index 00000000..eb9a7028 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/e_atan2.c @@ -0,0 +1,134 @@ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* __ieee754_atan2(y,x) + * Method : + * 1. Reduce y to positive by atan2(y,x)=-atan2(-y,x). + * 2. Reduce x to positive by (if x and y are unexceptional): + * ARG (x+iy) = arctan(y/x) ... if x > 0, + * ARG (x+iy) = pi - arctan[y/(-x)] ... if x < 0, + * + * Special cases: + * + * ATAN2((anything), NaN ) is NaN; + * ATAN2(NAN , (anything) ) is NaN; + * ATAN2(+-0, +(anything but NaN)) is +-0 ; + * ATAN2(+-0, -(anything but NaN)) is +-pi ; + * ATAN2(+-(anything but 0 and NaN), 0) is +-pi/2; + * ATAN2(+-(anything but INF and NaN), +INF) is +-0 ; + * ATAN2(+-(anything but INF and NaN), -INF) is +-pi; + * ATAN2(+-INF,+INF ) is +-pi/4 ; + * ATAN2(+-INF,-INF ) is +-3pi/4; + * ATAN2(+-INF, (anything but,0,NaN, and INF)) is +-pi/2; + * + * Constants: + * The hexadecimal values are the intended ones for the following + * constants. The decimal values may be used, provided that the + * compiler will convert from decimal to binary accurately enough + * to produce the hexadecimal values shown. + */ + +#include "math.h" +#include "math_private.h" + +static const double +tiny = 1.0e-300, +zero = 0.0, +pi_o_4 = 7.8539816339744827900E-01, /* 0x3FE921FB, 0x54442D18 */ +pi_o_2 = 1.5707963267948965580E+00, /* 0x3FF921FB, 0x54442D18 */ +pi = 3.1415926535897931160E+00, /* 0x400921FB, 0x54442D18 */ +pi_lo = 1.2246467991473531772E-16; /* 0x3CA1A626, 0x33145C07 */ + +double attribute_hidden __ieee754_atan2(double y, double x) +{ + double z; + int32_t k,m,hx,hy,ix,iy; + u_int32_t lx,ly; + + EXTRACT_WORDS(hx,lx,x); + ix = hx&0x7fffffff; + EXTRACT_WORDS(hy,ly,y); + iy = hy&0x7fffffff; + if(((ix|((lx|-lx)>>31))>0x7ff00000)|| + ((iy|((ly|-ly)>>31))>0x7ff00000)) /* x or y is NaN */ + return x+y; + if(((hx-0x3ff00000)|lx)==0) return atan(y); /* x=1.0 */ + m = ((hy>>31)&1)|((hx>>30)&2); /* 2*sign(x)+sign(y) */ + + /* when y = 0 */ + if((iy|ly)==0) { + switch(m) { + case 0: + case 1: return y; /* atan(+-0,+anything)=+-0 */ + case 2: return pi+tiny;/* atan(+0,-anything) = pi */ + case 3: return -pi-tiny;/* atan(-0,-anything) =-pi */ + } + } + /* when x = 0 */ + if((ix|lx)==0) return (hy<0)? -pi_o_2-tiny: pi_o_2+tiny; + + /* when x is INF */ + if(ix==0x7ff00000) { + if(iy==0x7ff00000) { + switch(m) { + case 0: return pi_o_4+tiny;/* atan(+INF,+INF) */ + case 1: return -pi_o_4-tiny;/* atan(-INF,+INF) */ + case 2: return 3.0*pi_o_4+tiny;/*atan(+INF,-INF)*/ + case 3: return -3.0*pi_o_4-tiny;/*atan(-INF,-INF)*/ + } + } else { + switch(m) { + case 0: return zero ; /* atan(+...,+INF) */ + case 1: return -zero ; /* atan(-...,+INF) */ + case 2: return pi+tiny ; /* atan(+...,-INF) */ + case 3: return -pi-tiny ; /* atan(-...,-INF) */ + } + } + } + /* when y is INF */ + if(iy==0x7ff00000) return (hy<0)? -pi_o_2-tiny: pi_o_2+tiny; + + /* compute y/x */ + k = (iy-ix)>>20; + if(k > 60) z=pi_o_2+0.5*pi_lo; /* |y/x| > 2**60 */ + else if(hx<0&&k<-60) z=0.0; /* |y|/x < -2**60 */ + else z=atan(fabs(y/x)); /* safe to do y/x */ + switch (m) { + case 0: return z ; /* atan(+,+) */ + case 1: { + u_int32_t zh; + GET_HIGH_WORD(zh,z); + SET_HIGH_WORD(z,zh ^ 0x80000000); + } + return z ; /* atan(-,+) */ + case 2: return pi-(z-pi_lo);/* atan(+,-) */ + default: /* case 3 */ + return (z-pi_lo)-pi;/* atan(-,-) */ + } +} + +/* + * wrapper atan2(y,x) + */ +#ifndef _IEEE_LIBM +double atan2(double y, double x) +{ + double z = __ieee754_atan2(y, x); + if (_LIB_VERSION == _IEEE_ || isnan(x) || isnan(y)) + return z; + if (x == 0.0 && y == 0.0) + return __kernel_standard(y,x,3); /* atan2(+-0,+-0) */ + return z; +} +#else +strong_alias(__ieee754_atan2, atan2) +#endif +libm_hidden_def(atan2) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/e_atanh.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/e_atanh.c new file mode 100644 index 00000000..5cf4da3b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/e_atanh.c @@ -0,0 +1,79 @@ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* __ieee754_atanh(x) + * Method : + * 1.Reduced x to positive by atanh(-x) = -atanh(x) + * 2.For x>=0.5 + * 1 2x x + * atanh(x) = --- * log(1 + -------) = 0.5 * log1p(2 * --------) + * 2 1 - x 1 - x + * + * For x<0.5 + * atanh(x) = 0.5*log1p(2x+2x*x/(1-x)) + * + * Special cases: + * atanh(x) is NaN if |x| > 1 with signal; + * atanh(NaN) is that NaN with no signal; + * atanh(+-1) is +-INF with signal. + * + */ + +#include "math.h" +#include "math_private.h" + +static const double one = 1.0, huge = 1e300; + +static const double zero = 0.0; + +double attribute_hidden __ieee754_atanh(double x) +{ + double t; + int32_t hx,ix; + u_int32_t lx; + EXTRACT_WORDS(hx,lx,x); + ix = hx&0x7fffffff; + if ((ix|((lx|(-lx))>>31))>0x3ff00000) /* |x|>1 */ + return (x-x)/(x-x); + if(ix==0x3ff00000) + return x/zero; + if(ix<0x3e300000&&(huge+x)>zero) return x; /* x<2**-28 */ + SET_HIGH_WORD(x,ix); + if(ix<0x3fe00000) { /* x < 0.5 */ + t = x+x; + t = 0.5*log1p(t+t*x/(one-x)); + } else + t = 0.5*log1p((x+x)/(one-x)); + if(hx>=0) return t; else return -t; +} + +/* + * wrapper atanh(x) + */ +#ifndef _IEEE_LIBM +double atanh(double x) +{ + double z, y; + z = __ieee754_atanh(x); + if (_LIB_VERSION == _IEEE_ || isnan(x)) + return z; + y = fabs(x); + if (y >= 1.0) { + if (y > 1.0) + return __kernel_standard(x, x, 30); /* atanh(|x|>1) */ + return __kernel_standard(x, x, 31); /* atanh(|x|==1) */ + } + return z; +} +#else +strong_alias(__ieee754_atanh, atanh) +#endif +libm_hidden_def(atanh) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/e_cosh.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/e_cosh.c new file mode 100644 index 00000000..1eb5b830 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/e_cosh.c @@ -0,0 +1,97 @@ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* __ieee754_cosh(x) + * Method : + * mathematically cosh(x) if defined to be (exp(x)+exp(-x))/2 + * 1. Replace x by |x| (cosh(x) = cosh(-x)). + * 2. + * [ exp(x) - 1 ]^2 + * 0 <= x <= ln2/2 : cosh(x) := 1 + ------------------- + * 2*exp(x) + * + * exp(x) + 1/exp(x) + * ln2/2 <= x <= 22 : cosh(x) := ------------------- + * 2 + * 22 <= x <= lnovft : cosh(x) := exp(x)/2 + * lnovft <= x <= ln2ovft: cosh(x) := exp(x/2)/2 * exp(x/2) + * ln2ovft < x : cosh(x) := huge*huge (overflow) + * + * Special cases: + * cosh(x) is |x| if x is +INF, -INF, or NaN. + * only cosh(0)=1 is exact for finite x. + */ + +#include "math.h" +#include "math_private.h" + +static const double one = 1.0, half=0.5, huge = 1.0e300; + +double attribute_hidden __ieee754_cosh(double x) +{ + double t,w; + int32_t ix; + u_int32_t lx; + + /* High word of |x|. */ + GET_HIGH_WORD(ix,x); + ix &= 0x7fffffff; + + /* x is INF or NaN */ + if(ix>=0x7ff00000) return x*x; + + /* |x| in [0,0.5*ln2], return 1+expm1(|x|)^2/(2*exp(|x|)) */ + if(ix<0x3fd62e43) { + t = expm1(fabs(x)); + w = one+t; + if (ix<0x3c800000) return w; /* cosh(tiny) = 1 */ + return one+(t*t)/(w+w); + } + + /* |x| in [0.5*ln2,22], return (exp(|x|)+1/exp(|x|)/2; */ + if (ix < 0x40360000) { + t = __ieee754_exp(fabs(x)); + return half*t+half/t; + } + + /* |x| in [22, log(maxdouble)] return half*exp(|x|) */ + if (ix < 0x40862E42) return half*__ieee754_exp(fabs(x)); + + /* |x| in [log(maxdouble), overflowthresold] */ + GET_LOW_WORD(lx,x); + if (ix<0x408633CE || + ((ix==0x408633ce)&&(lx<=(u_int32_t)0x8fb9f87d))) { + w = __ieee754_exp(half*fabs(x)); + t = half*w; + return t*w; + } + + /* |x| > overflowthresold, cosh(x) overflow */ + return huge*huge; +} + +/* + * wrapper cosh(x) + */ +#ifndef _IEEE_LIBM +double cosh(double x) +{ + double z = __ieee754_cosh(x); + if (_LIB_VERSION == _IEEE_ || isnan(x)) + return z; + if (fabs(x) > 7.10475860073943863426e+02) + return __kernel_standard(x, x, 5); /* cosh overflow */ + return z; +} +#else +strong_alias(__ieee754_cosh, cosh) +#endif +libm_hidden_def(cosh) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/e_exp.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/e_exp.c new file mode 100644 index 00000000..abfb1767 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/e_exp.c @@ -0,0 +1,182 @@ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* __ieee754_exp(x) + * Returns the exponential of x. + * + * Method + * 1. Argument reduction: + * Reduce x to an r so that |r| <= 0.5*ln2 ~ 0.34658. + * Given x, find r and integer k such that + * + * x = k*ln2 + r, |r| <= 0.5*ln2. + * + * Here r will be represented as r = hi-lo for better + * accuracy. + * + * 2. Approximation of exp(r) by a special rational function on + * the interval [0,0.34658]: + * Write + * R(r**2) = r*(exp(r)+1)/(exp(r)-1) = 2 + r*r/6 - r**4/360 + ... + * We use a special Reme algorithm on [0,0.34658] to generate + * a polynomial of degree 5 to approximate R. The maximum error + * of this polynomial approximation is bounded by 2**-59. In + * other words, + * R(z) ~ 2.0 + P1*z + P2*z**2 + P3*z**3 + P4*z**4 + P5*z**5 + * (where z=r*r, and the values of P1 to P5 are listed below) + * and + * | 5 | -59 + * | 2.0+P1*z+...+P5*z - R(z) | <= 2 + * | | + * The computation of exp(r) thus becomes + * 2*r + * exp(r) = 1 + ------- + * R - r + * r*R1(r) + * = 1 + r + ----------- (for better accuracy) + * 2 - R1(r) + * where + * 2 4 10 + * R1(r) = r - (P1*r + P2*r + ... + P5*r ). + * + * 3. Scale back to obtain exp(x): + * From step 1, we have + * exp(x) = 2^k * exp(r) + * + * Special cases: + * exp(INF) is INF, exp(NaN) is NaN; + * exp(-INF) is 0, and + * for finite argument, only exp(0)=1 is exact. + * + * Accuracy: + * according to an error analysis, the error is always less than + * 1 ulp (unit in the last place). + * + * Misc. info. + * For IEEE double + * if x > 7.09782712893383973096e+02 then exp(x) overflow + * if x < -7.45133219101941108420e+02 then exp(x) underflow + * + * Constants: + * The hexadecimal values are the intended ones for the following + * constants. The decimal values may be used, provided that the + * compiler will convert from decimal to binary accurately enough + * to produce the hexadecimal values shown. + */ + +#include "math.h" +#include "math_private.h" + +static const double +one = 1.0, +halF[2] = {0.5,-0.5,}, +huge = 1.0e+300, +twom1000= 9.33263618503218878990e-302, /* 2**-1000=0x01700000,0*/ +o_threshold= 7.09782712893383973096e+02, /* 0x40862E42, 0xFEFA39EF */ +u_threshold= -7.45133219101941108420e+02, /* 0xc0874910, 0xD52D3051 */ +ln2HI[2] ={ 6.93147180369123816490e-01, /* 0x3fe62e42, 0xfee00000 */ + -6.93147180369123816490e-01,},/* 0xbfe62e42, 0xfee00000 */ +ln2LO[2] ={ 1.90821492927058770002e-10, /* 0x3dea39ef, 0x35793c76 */ + -1.90821492927058770002e-10,},/* 0xbdea39ef, 0x35793c76 */ +invln2 = 1.44269504088896338700e+00, /* 0x3ff71547, 0x652b82fe */ +P1 = 1.66666666666666019037e-01, /* 0x3FC55555, 0x5555553E */ +P2 = -2.77777777770155933842e-03, /* 0xBF66C16C, 0x16BEBD93 */ +P3 = 6.61375632143793436117e-05, /* 0x3F11566A, 0xAF25DE2C */ +P4 = -1.65339022054652515390e-06, /* 0xBEBBBD41, 0xC5D26BF1 */ +P5 = 4.13813679705723846039e-08; /* 0x3E663769, 0x72BEA4D0 */ + +double attribute_hidden __ieee754_exp(double x) /* default IEEE double exp */ +{ + double y; + double hi = 0.0; + double lo = 0.0; + double c; + double t; + int32_t k=0; + int32_t xsb; + u_int32_t hx; + + GET_HIGH_WORD(hx,x); + xsb = (hx>>31)&1; /* sign bit of x */ + hx &= 0x7fffffff; /* high word of |x| */ + + /* filter out non-finite argument */ + if(hx >= 0x40862E42) { /* if |x|>=709.78... */ + if(hx>=0x7ff00000) { + u_int32_t lx; + GET_LOW_WORD(lx,x); + if(((hx&0xfffff)|lx)!=0) + return x+x; /* NaN */ + else return (xsb==0)? x:0.0; /* exp(+-inf)={inf,0} */ + } + if(x > o_threshold) return huge*huge; /* overflow */ + if(x < u_threshold) return twom1000*twom1000; /* underflow */ + } + + /* argument reduction */ + if(hx > 0x3fd62e42) { /* if |x| > 0.5 ln2 */ + if(hx < 0x3FF0A2B2) { /* and |x| < 1.5 ln2 */ + hi = x-ln2HI[xsb]; lo=ln2LO[xsb]; k = 1-xsb-xsb; + } else { + k = invln2*x+halF[xsb]; + t = k; + hi = x - t*ln2HI[0]; /* t*ln2HI is exact here */ + lo = t*ln2LO[0]; + } + x = hi - lo; + } + else if(hx < 0x3e300000) { /* when |x|<2**-28 */ + if(huge+x>one) return one+x;/* trigger inexact */ + } + else k = 0; + + /* x is now in primary range */ + t = x*x; + c = x - t*(P1+t*(P2+t*(P3+t*(P4+t*P5)))); + if(k==0) return one-((x*c)/(c-2.0)-x); + else y = one-((lo-(x*c)/(2.0-c))-hi); + if(k >= -1021) { + u_int32_t hy; + GET_HIGH_WORD(hy,y); + SET_HIGH_WORD(y,hy+(k<<20)); /* add k to y's exponent */ + return y; + } else { + u_int32_t hy; + GET_HIGH_WORD(hy,y); + SET_HIGH_WORD(y,hy+((k+1000)<<20)); /* add k to y's exponent */ + return y*twom1000; + } +} + +/* + * wrapper exp(x) + */ +#ifndef _IEEE_LIBM +double exp(double x) +{ + static const double o_threshold = 7.09782712893383973096e+02; /* 0x40862E42, 0xFEFA39EF */ + static const double u_threshold = -7.45133219101941108420e+02; /* 0xc0874910, 0xD52D3051 */ + + double z = __ieee754_exp(x); + if (_LIB_VERSION == _IEEE_) + return z; + if (isfinite(x)) { + if (x > o_threshold) + return __kernel_standard(x, x, 6); /* exp overflow */ + if (x < u_threshold) + return __kernel_standard(x, x, 7); /* exp underflow */ + } + return z; +} +#else +strong_alias(__ieee754_exp, exp) +#endif +libm_hidden_def(exp) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/e_fmod.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/e_fmod.c new file mode 100644 index 00000000..503ff925 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/e_fmod.c @@ -0,0 +1,144 @@ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* + * __ieee754_fmod(x,y) + * Return x mod y in exact arithmetic + * Method: shift and subtract + */ + +#include "math.h" +#include "math_private.h" + +static const double one = 1.0, Zero[] = {0.0, -0.0,}; + +double attribute_hidden __ieee754_fmod(double x, double y) +{ + int32_t n,hx,hy,hz,ix,iy,sx,i; + u_int32_t lx,ly,lz; + + EXTRACT_WORDS(hx,lx,x); + EXTRACT_WORDS(hy,ly,y); + sx = hx&0x80000000; /* sign of x */ + hx ^=sx; /* |x| */ + hy &= 0x7fffffff; /* |y| */ + + /* purge off exception values */ + if((hy|ly)==0||(hx>=0x7ff00000)|| /* y=0,or x not finite */ + ((hy|((ly|-ly)>>31))>0x7ff00000)) /* or y is NaN */ + return (x*y)/(x*y); + if(hx<=hy) { + if((hx>31]; /* |x|=|y| return x*0*/ + } + + /* determine ix = ilogb(x) */ + if(hx<0x00100000) { /* subnormal x */ + if(hx==0) { + for (ix = -1043, i=lx; i>0; i<<=1) ix -=1; + } else { + for (ix = -1022,i=(hx<<11); i>0; i<<=1) ix -=1; + } + } else ix = (hx>>20)-1023; + + /* determine iy = ilogb(y) */ + if(hy<0x00100000) { /* subnormal y */ + if(hy==0) { + for (iy = -1043, i=ly; i>0; i<<=1) iy -=1; + } else { + for (iy = -1022,i=(hy<<11); i>0; i<<=1) iy -=1; + } + } else iy = (hy>>20)-1023; + + /* set up {hx,lx}, {hy,ly} and align y to x */ + if(ix >= -1022) + hx = 0x00100000|(0x000fffff&hx); + else { /* subnormal x, shift x to normal */ + n = -1022-ix; + if(n<=31) { + hx = (hx<>(32-n)); + lx <<= n; + } else { + hx = lx<<(n-32); + lx = 0; + } + } + if(iy >= -1022) + hy = 0x00100000|(0x000fffff&hy); + else { /* subnormal y, shift y to normal */ + n = -1022-iy; + if(n<=31) { + hy = (hy<>(32-n)); + ly <<= n; + } else { + hy = ly<<(n-32); + ly = 0; + } + } + + /* fix point fmod */ + n = ix - iy; + while(n--) { + hz=hx-hy;lz=lx-ly; if(lx>31); lx = lx+lx;} + else { + if((hz|lz)==0) /* return sign(x)*0 */ + return Zero[(u_int32_t)sx>>31]; + hx = hz+hz+(lz>>31); lx = lz+lz; + } + } + hz=hx-hy;lz=lx-ly; if(lx=0) {hx=hz;lx=lz;} + + /* convert back to floating value and restore the sign */ + if((hx|lx)==0) /* return sign(x)*0 */ + return Zero[(u_int32_t)sx>>31]; + while(hx<0x00100000) { /* normalize x */ + hx = hx+hx+(lx>>31); lx = lx+lx; + iy -= 1; + } + if(iy>= -1022) { /* normalize output */ + hx = ((hx-0x00100000)|((iy+1023)<<20)); + INSERT_WORDS(x,hx|sx,lx); + } else { /* subnormal output */ + n = -1022 - iy; + if(n<=20) { + lx = (lx>>n)|((u_int32_t)hx<<(32-n)); + hx >>= n; + } else if (n<=31) { + lx = (hx<<(32-n))|(lx>>n); hx = sx; + } else { + lx = hx>>(n-32); hx = sx; + } + INSERT_WORDS(x,hx|sx,lx); + x *= one; /* create necessary signal */ + } + return x; /* exact output */ +} + +/* + * wrapper fmod(x,y) + */ +#ifndef _IEEE_LIBM +double fmod(double x, double y) +{ + double z = __ieee754_fmod(x, y); + if (_LIB_VERSION == _IEEE_ || isnan(y) || isnan(x)) + return z; + if (y == 0.0) + return __kernel_standard(x, y, 27); /* fmod(x,0) */ + return z; +} +#else +strong_alias(__ieee754_fmod, fmod) +#endif +libm_hidden_def(fmod) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/e_hypot.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/e_hypot.c new file mode 100644 index 00000000..26498251 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/e_hypot.c @@ -0,0 +1,136 @@ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* __ieee754_hypot(x,y) + * + * Method : + * If (assume round-to-nearest) z=x*x+y*y + * has error less than sqrt(2)/2 ulp, than + * sqrt(z) has error less than 1 ulp (exercise). + * + * So, compute sqrt(x*x+y*y) with some care as + * follows to get the error below 1 ulp: + * + * Assume x>y>0; + * (if possible, set rounding to round-to-nearest) + * 1. if x > 2y use + * x1*x1+(y*y+(x2*(x+x1))) for x*x+y*y + * where x1 = x with lower 32 bits cleared, x2 = x-x1; else + * 2. if x <= 2y use + * t1*y1+((x-y)*(x-y)+(t1*y2+t2*y)) + * where t1 = 2x with lower 32 bits cleared, t2 = 2x-t1, + * y1= y with lower 32 bits chopped, y2 = y-y1. + * + * NOTE: scaling may be necessary if some argument is too + * large or too tiny + * + * Special cases: + * hypot(x,y) is INF if x or y is +INF or -INF; else + * hypot(x,y) is NAN if x or y is NAN. + * + * Accuracy: + * hypot(x,y) returns sqrt(x^2+y^2) with error less + * than 1 ulps (units in the last place) + */ + +#include "math.h" +#include "math_private.h" + +double attribute_hidden __ieee754_hypot(double x, double y) +{ + double a=x,b=y,t1,t2,y1,y2,w; + int32_t j,k,ha,hb; + + GET_HIGH_WORD(ha,x); + ha &= 0x7fffffff; + GET_HIGH_WORD(hb,y); + hb &= 0x7fffffff; + if(hb > ha) {a=y;b=x;j=ha; ha=hb;hb=j;} else {a=x;b=y;} + SET_HIGH_WORD(a,ha); /* a <- |a| */ + SET_HIGH_WORD(b,hb); /* b <- |b| */ + if((ha-hb)>0x3c00000) {return a+b;} /* x/y > 2**60 */ + k=0; + if(ha > 0x5f300000) { /* a>2**500 */ + if(ha >= 0x7ff00000) { /* Inf or NaN */ + u_int32_t low; + w = a+b; /* for sNaN */ + GET_LOW_WORD(low,a); + if(((ha&0xfffff)|low)==0) w = a; + GET_LOW_WORD(low,b); + if(((hb^0x7ff00000)|low)==0) w = b; + return w; + } + /* scale a and b by 2**-600 */ + ha -= 0x25800000; hb -= 0x25800000; k += 600; + SET_HIGH_WORD(a,ha); + SET_HIGH_WORD(b,hb); + } + if(hb < 0x20b00000) { /* b < 2**-500 */ + if(hb <= 0x000fffff) { /* subnormal b or 0 */ + u_int32_t low; + GET_LOW_WORD(low,b); + if((hb|low)==0) return a; + t1=0; + SET_HIGH_WORD(t1,0x7fd00000); /* t1=2^1022 */ + b *= t1; + a *= t1; + k -= 1022; + } else { /* scale a and b by 2^600 */ + ha += 0x25800000; /* a *= 2^600 */ + hb += 0x25800000; /* b *= 2^600 */ + k -= 600; + SET_HIGH_WORD(a,ha); + SET_HIGH_WORD(b,hb); + } + } + /* medium size a and b */ + w = a-b; + if (w>b) { + t1 = 0; + SET_HIGH_WORD(t1,ha); + t2 = a-t1; + w = __ieee754_sqrt(t1*t1-(b*(-b)-t2*(a+t1))); + } else { + a = a+a; + y1 = 0; + SET_HIGH_WORD(y1,hb); + y2 = b - y1; + t1 = 0; + SET_HIGH_WORD(t1,ha+0x00100000); + t2 = a - t1; + w = __ieee754_sqrt(t1*y1-(w*(-w)-(t1*y2+t2*b))); + } + if(k!=0) { + u_int32_t high; + t1 = 1.0; + GET_HIGH_WORD(high,t1); + SET_HIGH_WORD(t1,high+(k<<20)); + return t1*w; + } else return w; +} + +/* + * wrapper hypot(x,y) + */ +#ifndef _IEEE_LIBM +double hypot(double x, double y) +{ + double z = __ieee754_hypot(x, y); + if (_LIB_VERSION == _IEEE_) + return z; + if ((!isfinite(z)) && isfinite(x) && isfinite(y)) + return __kernel_standard(x, y, 4); /* hypot overflow */ + return z; +} +#else +strong_alias(__ieee754_hypot, hypot) +#endif +libm_hidden_def(hypot) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/e_j0.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/e_j0.c new file mode 100644 index 00000000..ea37460c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/e_j0.c @@ -0,0 +1,415 @@ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* __ieee754_j0(x), __ieee754_y0(x) + * Bessel function of the first and second kinds of order zero. + * Method -- j0(x): + * 1. For tiny x, we use j0(x) = 1 - x^2/4 + x^4/64 - ... + * 2. Reduce x to |x| since j0(x)=j0(-x), and + * for x in (0,2) + * j0(x) = 1-z/4+ z^2*R0/S0, where z = x*x; + * (precision: |j0-1+z/4-z^2R0/S0 |<2**-63.67 ) + * for x in (2,inf) + * j0(x) = sqrt(2/(pi*x))*(p0(x)*cos(x0)-q0(x)*sin(x0)) + * where x0 = x-pi/4. It is better to compute sin(x0),cos(x0) + * as follow: + * cos(x0) = cos(x)cos(pi/4)+sin(x)sin(pi/4) + * = 1/sqrt(2) * (cos(x) + sin(x)) + * sin(x0) = sin(x)cos(pi/4)-cos(x)sin(pi/4) + * = 1/sqrt(2) * (sin(x) - cos(x)) + * (To avoid cancellation, use + * sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x)) + * to compute the worse one.) + * + * 3 Special cases + * j0(nan)= nan + * j0(0) = 1 + * j0(inf) = 0 + * + * Method -- y0(x): + * 1. For x<2. + * Since + * y0(x) = 2/pi*(j0(x)*(ln(x/2)+Euler) + x^2/4 - ...) + * therefore y0(x)-2/pi*j0(x)*ln(x) is an even function. + * We use the following function to approximate y0, + * y0(x) = U(z)/V(z) + (2/pi)*(j0(x)*ln(x)), z= x^2 + * where + * U(z) = u00 + u01*z + ... + u06*z^6 + * V(z) = 1 + v01*z + ... + v04*z^4 + * with absolute approximation error bounded by 2**-72. + * Note: For tiny x, U/V = u0 and j0(x)~1, hence + * y0(tiny) = u0 + (2/pi)*ln(tiny), (choose tiny<2**-27) + * 2. For x>=2. + * y0(x) = sqrt(2/(pi*x))*(p0(x)*cos(x0)+q0(x)*sin(x0)) + * where x0 = x-pi/4. It is better to compute sin(x0),cos(x0) + * by the method mentioned above. + * 3. Special cases: y0(0)=-inf, y0(x<0)=NaN, y0(inf)=0. + */ + +#include "math.h" +#include "math_private.h" + +static double pzero(double), qzero(double); + +static const double +huge = 1e300, +one = 1.0, +invsqrtpi= 5.64189583547756279280e-01, /* 0x3FE20DD7, 0x50429B6D */ +tpi = 6.36619772367581382433e-01, /* 0x3FE45F30, 0x6DC9C883 */ + /* R0/S0 on [0, 2.00] */ +R02 = 1.56249999999999947958e-02, /* 0x3F8FFFFF, 0xFFFFFFFD */ +R03 = -1.89979294238854721751e-04, /* 0xBF28E6A5, 0xB61AC6E9 */ +R04 = 1.82954049532700665670e-06, /* 0x3EBEB1D1, 0x0C503919 */ +R05 = -4.61832688532103189199e-09, /* 0xBE33D5E7, 0x73D63FCE */ +S01 = 1.56191029464890010492e-02, /* 0x3F8FFCE8, 0x82C8C2A4 */ +S02 = 1.16926784663337450260e-04, /* 0x3F1EA6D2, 0xDD57DBF4 */ +S03 = 5.13546550207318111446e-07, /* 0x3EA13B54, 0xCE84D5A9 */ +S04 = 1.16614003333790000205e-09; /* 0x3E1408BC, 0xF4745D8F */ + +static const double zero = 0.0; + +double attribute_hidden __ieee754_j0(double x) +{ + double z, s,c,ss,cc,r,u,v; + int32_t hx,ix; + + GET_HIGH_WORD(hx,x); + ix = hx&0x7fffffff; + if(ix>=0x7ff00000) return one/(x*x); + x = fabs(x); + if(ix >= 0x40000000) { /* |x| >= 2.0 */ + s = sin(x); + c = cos(x); + ss = s-c; + cc = s+c; + if(ix<0x7fe00000) { /* make sure x+x not overflow */ + z = -cos(x+x); + if ((s*c)0x48000000) z = (invsqrtpi*cc)/sqrt(x); + else { + u = pzero(x); v = qzero(x); + z = invsqrtpi*(u*cc-v*ss)/sqrt(x); + } + return z; + } + if(ix<0x3f200000) { /* |x| < 2**-13 */ + if(huge+x>one) { /* raise inexact if x != 0 */ + if(ix<0x3e400000) return one; /* |x|<2**-27 */ + else return one - 0.25*x*x; + } + } + z = x*x; + r = z*(R02+z*(R03+z*(R04+z*R05))); + s = one+z*(S01+z*(S02+z*(S03+z*S04))); + if(ix < 0x3FF00000) { /* |x| < 1.00 */ + return one + z*(-0.25+(r/s)); + } else { + u = 0.5*x; + return((one+u)*(one-u)+z*(r/s)); + } +} + +/* + * wrapper j0(double x) + */ +#ifndef _IEEE_LIBM +double j0(double x) +{ + double z = __ieee754_j0(x); + if (_LIB_VERSION == _IEEE_ || isnan(x)) + return z; + if (fabs(x) > X_TLOSS) + return __kernel_standard(x, x, 34); /* j0(|x|>X_TLOSS) */ + return z; +} +#else +strong_alias(__ieee754_j0, j0) +#endif + +static const double +u00 = -7.38042951086872317523e-02, /* 0xBFB2E4D6, 0x99CBD01F */ +u01 = 1.76666452509181115538e-01, /* 0x3FC69D01, 0x9DE9E3FC */ +u02 = -1.38185671945596898896e-02, /* 0xBF8C4CE8, 0xB16CFA97 */ +u03 = 3.47453432093683650238e-04, /* 0x3F36C54D, 0x20B29B6B */ +u04 = -3.81407053724364161125e-06, /* 0xBECFFEA7, 0x73D25CAD */ +u05 = 1.95590137035022920206e-08, /* 0x3E550057, 0x3B4EABD4 */ +u06 = -3.98205194132103398453e-11, /* 0xBDC5E43D, 0x693FB3C8 */ +v01 = 1.27304834834123699328e-02, /* 0x3F8A1270, 0x91C9C71A */ +v02 = 7.60068627350353253702e-05, /* 0x3F13ECBB, 0xF578C6C1 */ +v03 = 2.59150851840457805467e-07, /* 0x3E91642D, 0x7FF202FD */ +v04 = 4.41110311332675467403e-10; /* 0x3DFE5018, 0x3BD6D9EF */ + +double attribute_hidden __ieee754_y0(double x) +{ + double z, s,c,ss,cc,u,v; + int32_t hx,ix,lx; + + EXTRACT_WORDS(hx,lx,x); + ix = 0x7fffffff&hx; + /* Y0(NaN) is NaN, y0(-inf) is Nan, y0(inf) is 0 */ + if(ix>=0x7ff00000) return one/(x+x*x); + if((ix|lx)==0) return -one/zero; + if(hx<0) return zero/zero; + if(ix >= 0x40000000) { /* |x| >= 2.0 */ + /* y0(x) = sqrt(2/(pi*x))*(p0(x)*sin(x0)+q0(x)*cos(x0)) + * where x0 = x-pi/4 + * Better formula: + * cos(x0) = cos(x)cos(pi/4)+sin(x)sin(pi/4) + * = 1/sqrt(2) * (sin(x) + cos(x)) + * sin(x0) = sin(x)cos(3pi/4)-cos(x)sin(3pi/4) + * = 1/sqrt(2) * (sin(x) - cos(x)) + * To avoid cancellation, use + * sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x)) + * to compute the worse one. + */ + s = sin(x); + c = cos(x); + ss = s-c; + cc = s+c; + /* + * j0(x) = 1/sqrt(pi) * (P(0,x)*cc - Q(0,x)*ss) / sqrt(x) + * y0(x) = 1/sqrt(pi) * (P(0,x)*ss + Q(0,x)*cc) / sqrt(x) + */ + if(ix<0x7fe00000) { /* make sure x+x not overflow */ + z = -cos(x+x); + if ((s*c)0x48000000) z = (invsqrtpi*ss)/sqrt(x); + else { + u = pzero(x); v = qzero(x); + z = invsqrtpi*(u*ss+v*cc)/sqrt(x); + } + return z; + } + if(ix<=0x3e400000) { /* x < 2**-27 */ + return(u00 + tpi*__ieee754_log(x)); + } + z = x*x; + u = u00+z*(u01+z*(u02+z*(u03+z*(u04+z*(u05+z*u06))))); + v = one+z*(v01+z*(v02+z*(v03+z*v04))); + return(u/v + tpi*(__ieee754_j0(x)*__ieee754_log(x))); +} + +/* + * wrapper y0(double x) + */ +#ifndef _IEEE_LIBM +double y0(double x) +{ + double z = __ieee754_y0(x); + if (_LIB_VERSION == _IEEE_ || isnan(x)) + return z; + if (x <= 0.0) { + if (x == 0.0) /* d= -one/(x-x); */ + return __kernel_standard(x, x, 8); + /* d = zero/(x-x); */ + return __kernel_standard(x, x, 9); + } + if (x > X_TLOSS) + return __kernel_standard(x, x, 35); /* y0(x>X_TLOSS) */ + return z; +} +#else +strong_alias(__ieee754_y0, y0) +#endif + + +/* The asymptotic expansions of pzero is + * 1 - 9/128 s^2 + 11025/98304 s^4 - ..., where s = 1/x. + * For x >= 2, We approximate pzero by + * pzero(x) = 1 + (R/S) + * where R = pR0 + pR1*s^2 + pR2*s^4 + ... + pR5*s^10 + * S = 1 + pS0*s^2 + ... + pS4*s^10 + * and + * | pzero(x)-1-R/S | <= 2 ** ( -60.26) + */ +static const double pR8[6] = { /* for x in [inf, 8]=1/[0,0.125] */ + 0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */ + -7.03124999999900357484e-02, /* 0xBFB1FFFF, 0xFFFFFD32 */ + -8.08167041275349795626e+00, /* 0xC02029D0, 0xB44FA779 */ + -2.57063105679704847262e+02, /* 0xC0701102, 0x7B19E863 */ + -2.48521641009428822144e+03, /* 0xC0A36A6E, 0xCD4DCAFC */ + -5.25304380490729545272e+03, /* 0xC0B4850B, 0x36CC643D */ +}; +static const double pS8[5] = { + 1.16534364619668181717e+02, /* 0x405D2233, 0x07A96751 */ + 3.83374475364121826715e+03, /* 0x40ADF37D, 0x50596938 */ + 4.05978572648472545552e+04, /* 0x40E3D2BB, 0x6EB6B05F */ + 1.16752972564375915681e+05, /* 0x40FC810F, 0x8F9FA9BD */ + 4.76277284146730962675e+04, /* 0x40E74177, 0x4F2C49DC */ +}; + +static const double pR5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */ + -1.14125464691894502584e-11, /* 0xBDA918B1, 0x47E495CC */ + -7.03124940873599280078e-02, /* 0xBFB1FFFF, 0xE69AFBC6 */ + -4.15961064470587782438e+00, /* 0xC010A370, 0xF90C6BBF */ + -6.76747652265167261021e+01, /* 0xC050EB2F, 0x5A7D1783 */ + -3.31231299649172967747e+02, /* 0xC074B3B3, 0x6742CC63 */ + -3.46433388365604912451e+02, /* 0xC075A6EF, 0x28A38BD7 */ +}; +static const double pS5[5] = { + 6.07539382692300335975e+01, /* 0x404E6081, 0x0C98C5DE */ + 1.05125230595704579173e+03, /* 0x40906D02, 0x5C7E2864 */ + 5.97897094333855784498e+03, /* 0x40B75AF8, 0x8FBE1D60 */ + 9.62544514357774460223e+03, /* 0x40C2CCB8, 0xFA76FA38 */ + 2.40605815922939109441e+03, /* 0x40A2CC1D, 0xC70BE864 */ +}; + +static const double pR3[6] = {/* for x in [4.547,2.8571]=1/[0.2199,0.35001] */ + -2.54704601771951915620e-09, /* 0xBE25E103, 0x6FE1AA86 */ + -7.03119616381481654654e-02, /* 0xBFB1FFF6, 0xF7C0E24B */ + -2.40903221549529611423e+00, /* 0xC00345B2, 0xAEA48074 */ + -2.19659774734883086467e+01, /* 0xC035F74A, 0x4CB94E14 */ + -5.80791704701737572236e+01, /* 0xC04D0A22, 0x420A1A45 */ + -3.14479470594888503854e+01, /* 0xC03F72AC, 0xA892D80F */ +}; +static const double pS3[5] = { + 3.58560338055209726349e+01, /* 0x4041ED92, 0x84077DD3 */ + 3.61513983050303863820e+02, /* 0x40769839, 0x464A7C0E */ + 1.19360783792111533330e+03, /* 0x4092A66E, 0x6D1061D6 */ + 1.12799679856907414432e+03, /* 0x40919FFC, 0xB8C39B7E */ + 1.73580930813335754692e+02, /* 0x4065B296, 0xFC379081 */ +}; + +static const double pR2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */ + -8.87534333032526411254e-08, /* 0xBE77D316, 0xE927026D */ + -7.03030995483624743247e-02, /* 0xBFB1FF62, 0x495E1E42 */ + -1.45073846780952986357e+00, /* 0xBFF73639, 0x8A24A843 */ + -7.63569613823527770791e+00, /* 0xC01E8AF3, 0xEDAFA7F3 */ + -1.11931668860356747786e+01, /* 0xC02662E6, 0xC5246303 */ + -3.23364579351335335033e+00, /* 0xC009DE81, 0xAF8FE70F */ +}; +static const double pS2[5] = { + 2.22202997532088808441e+01, /* 0x40363865, 0x908B5959 */ + 1.36206794218215208048e+02, /* 0x4061069E, 0x0EE8878F */ + 2.70470278658083486789e+02, /* 0x4070E786, 0x42EA079B */ + 1.53875394208320329881e+02, /* 0x40633C03, 0x3AB6FAFF */ + 1.46576176948256193810e+01, /* 0x402D50B3, 0x44391809 */ +}; + +static double pzero(double x) +{ + const double *p = 0,*q = 0; + double z,r,s; + int32_t ix; + GET_HIGH_WORD(ix,x); + ix &= 0x7fffffff; + if(ix>=0x40200000) {p = pR8; q= pS8;} + else if(ix>=0x40122E8B){p = pR5; q= pS5;} + else if(ix>=0x4006DB6D){p = pR3; q= pS3;} + else if(ix>=0x40000000){p = pR2; q= pS2;} + z = one/(x*x); + r = p[0]+z*(p[1]+z*(p[2]+z*(p[3]+z*(p[4]+z*p[5])))); + s = one+z*(q[0]+z*(q[1]+z*(q[2]+z*(q[3]+z*q[4])))); + return one+ r/s; +} + + +/* For x >= 8, the asymptotic expansions of qzero is + * -1/8 s + 75/1024 s^3 - ..., where s = 1/x. + * We approximate pzero by + * qzero(x) = s*(-1.25 + (R/S)) + * where R = qR0 + qR1*s^2 + qR2*s^4 + ... + qR5*s^10 + * S = 1 + qS0*s^2 + ... + qS5*s^12 + * and + * | qzero(x)/s +1.25-R/S | <= 2 ** ( -61.22) + */ +static const double qR8[6] = { /* for x in [inf, 8]=1/[0,0.125] */ + 0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */ + 7.32421874999935051953e-02, /* 0x3FB2BFFF, 0xFFFFFE2C */ + 1.17682064682252693899e+01, /* 0x40278952, 0x5BB334D6 */ + 5.57673380256401856059e+02, /* 0x40816D63, 0x15301825 */ + 8.85919720756468632317e+03, /* 0x40C14D99, 0x3E18F46D */ + 3.70146267776887834771e+04, /* 0x40E212D4, 0x0E901566 */ +}; +static const double qS8[6] = { + 1.63776026895689824414e+02, /* 0x406478D5, 0x365B39BC */ + 8.09834494656449805916e+03, /* 0x40BFA258, 0x4E6B0563 */ + 1.42538291419120476348e+05, /* 0x41016652, 0x54D38C3F */ + 8.03309257119514397345e+05, /* 0x412883DA, 0x83A52B43 */ + 8.40501579819060512818e+05, /* 0x4129A66B, 0x28DE0B3D */ + -3.43899293537866615225e+05, /* 0xC114FD6D, 0x2C9530C5 */ +}; + +static const double qR5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */ + 1.84085963594515531381e-11, /* 0x3DB43D8F, 0x29CC8CD9 */ + 7.32421766612684765896e-02, /* 0x3FB2BFFF, 0xD172B04C */ + 5.83563508962056953777e+00, /* 0x401757B0, 0xB9953DD3 */ + 1.35111577286449829671e+02, /* 0x4060E392, 0x0A8788E9 */ + 1.02724376596164097464e+03, /* 0x40900CF9, 0x9DC8C481 */ + 1.98997785864605384631e+03, /* 0x409F17E9, 0x53C6E3A6 */ +}; +static const double qS5[6] = { + 8.27766102236537761883e+01, /* 0x4054B1B3, 0xFB5E1543 */ + 2.07781416421392987104e+03, /* 0x40A03BA0, 0xDA21C0CE */ + 1.88472887785718085070e+04, /* 0x40D267D2, 0x7B591E6D */ + 5.67511122894947329769e+04, /* 0x40EBB5E3, 0x97E02372 */ + 3.59767538425114471465e+04, /* 0x40E19118, 0x1F7A54A0 */ + -5.35434275601944773371e+03, /* 0xC0B4EA57, 0xBEDBC609 */ +}; + +static const double qR3[6] = {/* for x in [4.547,2.8571]=1/[0.2199,0.35001] */ + 4.37741014089738620906e-09, /* 0x3E32CD03, 0x6ADECB82 */ + 7.32411180042911447163e-02, /* 0x3FB2BFEE, 0x0E8D0842 */ + 3.34423137516170720929e+00, /* 0x400AC0FC, 0x61149CF5 */ + 4.26218440745412650017e+01, /* 0x40454F98, 0x962DAEDD */ + 1.70808091340565596283e+02, /* 0x406559DB, 0xE25EFD1F */ + 1.66733948696651168575e+02, /* 0x4064D77C, 0x81FA21E0 */ +}; +static const double qS3[6] = { + 4.87588729724587182091e+01, /* 0x40486122, 0xBFE343A6 */ + 7.09689221056606015736e+02, /* 0x40862D83, 0x86544EB3 */ + 3.70414822620111362994e+03, /* 0x40ACF04B, 0xE44DFC63 */ + 6.46042516752568917582e+03, /* 0x40B93C6C, 0xD7C76A28 */ + 2.51633368920368957333e+03, /* 0x40A3A8AA, 0xD94FB1C0 */ + -1.49247451836156386662e+02, /* 0xC062A7EB, 0x201CF40F */ +}; + +static const double qR2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */ + 1.50444444886983272379e-07, /* 0x3E84313B, 0x54F76BDB */ + 7.32234265963079278272e-02, /* 0x3FB2BEC5, 0x3E883E34 */ + 1.99819174093815998816e+00, /* 0x3FFFF897, 0xE727779C */ + 1.44956029347885735348e+01, /* 0x402CFDBF, 0xAAF96FE5 */ + 3.16662317504781540833e+01, /* 0x403FAA8E, 0x29FBDC4A */ + 1.62527075710929267416e+01, /* 0x403040B1, 0x71814BB4 */ +}; +static const double qS2[6] = { + 3.03655848355219184498e+01, /* 0x403E5D96, 0xF7C07AED */ + 2.69348118608049844624e+02, /* 0x4070D591, 0xE4D14B40 */ + 8.44783757595320139444e+02, /* 0x408A6645, 0x22B3BF22 */ + 8.82935845112488550512e+02, /* 0x408B977C, 0x9C5CC214 */ + 2.12666388511798828631e+02, /* 0x406A9553, 0x0E001365 */ + -5.31095493882666946917e+00, /* 0xC0153E6A, 0xF8B32931 */ +}; + +static double qzero(double x) +{ + const double *p=0,*q=0; + double s,r,z; + int32_t ix; + GET_HIGH_WORD(ix,x); + ix &= 0x7fffffff; + if(ix>=0x40200000) {p = qR8; q= qS8;} + else if(ix>=0x40122E8B){p = qR5; q= qS5;} + else if(ix>=0x4006DB6D){p = qR3; q= qS3;} + else if(ix>=0x40000000){p = qR2; q= qS2;} + z = one/(x*x); + r = p[0]+z*(p[1]+z*(p[2]+z*(p[3]+z*(p[4]+z*p[5])))); + s = one+z*(q[0]+z*(q[1]+z*(q[2]+z*(q[3]+z*(q[4]+z*q[5]))))); + return (-.125 + r/s)/x; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/e_j1.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/e_j1.c new file mode 100644 index 00000000..1f674e9c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/e_j1.c @@ -0,0 +1,409 @@ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* __ieee754_j1(x), __ieee754_y1(x) + * Bessel function of the first and second kinds of order zero. + * Method -- j1(x): + * 1. For tiny x, we use j1(x) = x/2 - x^3/16 + x^5/384 - ... + * 2. Reduce x to |x| since j1(x)=-j1(-x), and + * for x in (0,2) + * j1(x) = x/2 + x*z*R0/S0, where z = x*x; + * (precision: |j1/x - 1/2 - R0/S0 |<2**-61.51 ) + * for x in (2,inf) + * j1(x) = sqrt(2/(pi*x))*(p1(x)*cos(x1)-q1(x)*sin(x1)) + * y1(x) = sqrt(2/(pi*x))*(p1(x)*sin(x1)+q1(x)*cos(x1)) + * where x1 = x-3*pi/4. It is better to compute sin(x1),cos(x1) + * as follow: + * cos(x1) = cos(x)cos(3pi/4)+sin(x)sin(3pi/4) + * = 1/sqrt(2) * (sin(x) - cos(x)) + * sin(x1) = sin(x)cos(3pi/4)-cos(x)sin(3pi/4) + * = -1/sqrt(2) * (sin(x) + cos(x)) + * (To avoid cancellation, use + * sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x)) + * to compute the worse one.) + * + * 3 Special cases + * j1(nan)= nan + * j1(0) = 0 + * j1(inf) = 0 + * + * Method -- y1(x): + * 1. screen out x<=0 cases: y1(0)=-inf, y1(x<0)=NaN + * 2. For x<2. + * Since + * y1(x) = 2/pi*(j1(x)*(ln(x/2)+Euler)-1/x-x/2+5/64*x^3-...) + * therefore y1(x)-2/pi*j1(x)*ln(x)-1/x is an odd function. + * We use the following function to approximate y1, + * y1(x) = x*U(z)/V(z) + (2/pi)*(j1(x)*ln(x)-1/x), z= x^2 + * where for x in [0,2] (abs err less than 2**-65.89) + * U(z) = U0[0] + U0[1]*z + ... + U0[4]*z^4 + * V(z) = 1 + v0[0]*z + ... + v0[4]*z^5 + * Note: For tiny x, 1/x dominate y1 and hence + * y1(tiny) = -2/pi/tiny, (choose tiny<2**-54) + * 3. For x>=2. + * y1(x) = sqrt(2/(pi*x))*(p1(x)*sin(x1)+q1(x)*cos(x1)) + * where x1 = x-3*pi/4. It is better to compute sin(x1),cos(x1) + * by method mentioned above. + */ + +#include "math.h" +#include "math_private.h" + +static double pone(double), qone(double); + +static const double +huge = 1e300, +one = 1.0, +invsqrtpi= 5.64189583547756279280e-01, /* 0x3FE20DD7, 0x50429B6D */ +tpi = 6.36619772367581382433e-01, /* 0x3FE45F30, 0x6DC9C883 */ + /* R0/S0 on [0,2] */ +r00 = -6.25000000000000000000e-02, /* 0xBFB00000, 0x00000000 */ +r01 = 1.40705666955189706048e-03, /* 0x3F570D9F, 0x98472C61 */ +r02 = -1.59955631084035597520e-05, /* 0xBEF0C5C6, 0xBA169668 */ +r03 = 4.96727999609584448412e-08, /* 0x3E6AAAFA, 0x46CA0BD9 */ +s01 = 1.91537599538363460805e-02, /* 0x3F939D0B, 0x12637E53 */ +s02 = 1.85946785588630915560e-04, /* 0x3F285F56, 0xB9CDF664 */ +s03 = 1.17718464042623683263e-06, /* 0x3EB3BFF8, 0x333F8498 */ +s04 = 5.04636257076217042715e-09, /* 0x3E35AC88, 0xC97DFF2C */ +s05 = 1.23542274426137913908e-11; /* 0x3DAB2ACF, 0xCFB97ED8 */ + +static const double zero = 0.0; + +double attribute_hidden __ieee754_j1(double x) +{ + double z, s,c,ss,cc,r,u,v,y; + int32_t hx,ix; + + GET_HIGH_WORD(hx,x); + ix = hx&0x7fffffff; + if(ix>=0x7ff00000) return one/x; + y = fabs(x); + if(ix >= 0x40000000) { /* |x| >= 2.0 */ + s = sin(y); + c = cos(y); + ss = -s-c; + cc = s-c; + if(ix<0x7fe00000) { /* make sure y+y not overflow */ + z = cos(y+y); + if ((s*c)>zero) cc = z/ss; + else ss = z/cc; + } + /* + * j1(x) = 1/sqrt(pi) * (P(1,x)*cc - Q(1,x)*ss) / sqrt(x) + * y1(x) = 1/sqrt(pi) * (P(1,x)*ss + Q(1,x)*cc) / sqrt(x) + */ + if(ix>0x48000000) z = (invsqrtpi*cc)/sqrt(y); + else { + u = pone(y); v = qone(y); + z = invsqrtpi*(u*cc-v*ss)/sqrt(y); + } + if(hx<0) return -z; + else return z; + } + if(ix<0x3e400000) { /* |x|<2**-27 */ + if(huge+x>one) return 0.5*x;/* inexact if x!=0 necessary */ + } + z = x*x; + r = z*(r00+z*(r01+z*(r02+z*r03))); + s = one+z*(s01+z*(s02+z*(s03+z*(s04+z*s05)))); + r *= x; + return(x*0.5+r/s); +} + +/* + * wrapper of j1 + */ +#ifndef _IEEE_LIBM +double j1(double x) +{ + double z = __ieee754_j1(x); + if (_LIB_VERSION == _IEEE_ || isnan(x)) + return z; + if (fabs(x) > X_TLOSS) + return __kernel_standard(x, x, 36); /* j1(|x|>X_TLOSS) */ + return z; +} +#else +strong_alias(__ieee754_j1, j1) +#endif + +static const double U0[5] = { + -1.96057090646238940668e-01, /* 0xBFC91866, 0x143CBC8A */ + 5.04438716639811282616e-02, /* 0x3FA9D3C7, 0x76292CD1 */ + -1.91256895875763547298e-03, /* 0xBF5F55E5, 0x4844F50F */ + 2.35252600561610495928e-05, /* 0x3EF8AB03, 0x8FA6B88E */ + -9.19099158039878874504e-08, /* 0xBE78AC00, 0x569105B8 */ +}; +static const double V0[5] = { + 1.99167318236649903973e-02, /* 0x3F94650D, 0x3F4DA9F0 */ + 2.02552581025135171496e-04, /* 0x3F2A8C89, 0x6C257764 */ + 1.35608801097516229404e-06, /* 0x3EB6C05A, 0x894E8CA6 */ + 6.22741452364621501295e-09, /* 0x3E3ABF1D, 0x5BA69A86 */ + 1.66559246207992079114e-11, /* 0x3DB25039, 0xDACA772A */ +}; + +double attribute_hidden __ieee754_y1(double x) +{ + double z, s,c,ss,cc,u,v; + int32_t hx,ix,lx; + + EXTRACT_WORDS(hx,lx,x); + ix = 0x7fffffff&hx; + /* if Y1(NaN) is NaN, Y1(-inf) is NaN, Y1(inf) is 0 */ + if(ix>=0x7ff00000) return one/(x+x*x); + if((ix|lx)==0) return -one/zero; + if(hx<0) return zero/zero; + if(ix >= 0x40000000) { /* |x| >= 2.0 */ + s = sin(x); + c = cos(x); + ss = -s-c; + cc = s-c; + if(ix<0x7fe00000) { /* make sure x+x not overflow */ + z = cos(x+x); + if ((s*c)>zero) cc = z/ss; + else ss = z/cc; + } + /* y1(x) = sqrt(2/(pi*x))*(p1(x)*sin(x0)+q1(x)*cos(x0)) + * where x0 = x-3pi/4 + * Better formula: + * cos(x0) = cos(x)cos(3pi/4)+sin(x)sin(3pi/4) + * = 1/sqrt(2) * (sin(x) - cos(x)) + * sin(x0) = sin(x)cos(3pi/4)-cos(x)sin(3pi/4) + * = -1/sqrt(2) * (cos(x) + sin(x)) + * To avoid cancellation, use + * sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x)) + * to compute the worse one. + */ + if(ix>0x48000000) z = (invsqrtpi*ss)/sqrt(x); + else { + u = pone(x); v = qone(x); + z = invsqrtpi*(u*ss+v*cc)/sqrt(x); + } + return z; + } + if(ix<=0x3c900000) { /* x < 2**-54 */ + return(-tpi/x); + } + z = x*x; + u = U0[0]+z*(U0[1]+z*(U0[2]+z*(U0[3]+z*U0[4]))); + v = one+z*(V0[0]+z*(V0[1]+z*(V0[2]+z*(V0[3]+z*V0[4])))); + return(x*(u/v) + tpi*(__ieee754_j1(x)*__ieee754_log(x)-one/x)); +} + +/* + * wrapper of y1 + */ +#ifndef _IEEE_LIBM +double y1(double x) +{ + double z = __ieee754_y1(x); + if (_LIB_VERSION == _IEEE_ || isnan(x)) + return z; + if (x <= 0.0) { + if (x == 0.0) /* d = -one/(x-x); */ + return __kernel_standard(x, x, 10); + /* d = zero/(x-x); */ + return __kernel_standard(x, x, 11); + } + if (x > X_TLOSS) + return __kernel_standard(x, x, 37); /* y1(x>X_TLOSS) */ + return z; +} +#else +strong_alias(__ieee754_y1, y1) +#endif + +/* For x >= 8, the asymptotic expansions of pone is + * 1 + 15/128 s^2 - 4725/2^15 s^4 - ..., where s = 1/x. + * We approximate pone by + * pone(x) = 1 + (R/S) + * where R = pr0 + pr1*s^2 + pr2*s^4 + ... + pr5*s^10 + * S = 1 + ps0*s^2 + ... + ps4*s^10 + * and + * | pone(x)-1-R/S | <= 2 ** ( -60.06) + */ + +static const double pr8[6] = { /* for x in [inf, 8]=1/[0,0.125] */ + 0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */ + 1.17187499999988647970e-01, /* 0x3FBDFFFF, 0xFFFFFCCE */ + 1.32394806593073575129e+01, /* 0x402A7A9D, 0x357F7FCE */ + 4.12051854307378562225e+02, /* 0x4079C0D4, 0x652EA590 */ + 3.87474538913960532227e+03, /* 0x40AE457D, 0xA3A532CC */ + 7.91447954031891731574e+03, /* 0x40BEEA7A, 0xC32782DD */ +}; +static const double ps8[5] = { + 1.14207370375678408436e+02, /* 0x405C8D45, 0x8E656CAC */ + 3.65093083420853463394e+03, /* 0x40AC85DC, 0x964D274F */ + 3.69562060269033463555e+04, /* 0x40E20B86, 0x97C5BB7F */ + 9.76027935934950801311e+04, /* 0x40F7D42C, 0xB28F17BB */ + 3.08042720627888811578e+04, /* 0x40DE1511, 0x697A0B2D */ +}; + +static const double pr5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */ + 1.31990519556243522749e-11, /* 0x3DAD0667, 0xDAE1CA7D */ + 1.17187493190614097638e-01, /* 0x3FBDFFFF, 0xE2C10043 */ + 6.80275127868432871736e+00, /* 0x401B3604, 0x6E6315E3 */ + 1.08308182990189109773e+02, /* 0x405B13B9, 0x452602ED */ + 5.17636139533199752805e+02, /* 0x40802D16, 0xD052D649 */ + 5.28715201363337541807e+02, /* 0x408085B8, 0xBB7E0CB7 */ +}; +static const double ps5[5] = { + 5.92805987221131331921e+01, /* 0x404DA3EA, 0xA8AF633D */ + 9.91401418733614377743e+02, /* 0x408EFB36, 0x1B066701 */ + 5.35326695291487976647e+03, /* 0x40B4E944, 0x5706B6FB */ + 7.84469031749551231769e+03, /* 0x40BEA4B0, 0xB8A5BB15 */ + 1.50404688810361062679e+03, /* 0x40978030, 0x036F5E51 */ +}; + +static const double pr3[6] = { + 3.02503916137373618024e-09, /* 0x3E29FC21, 0xA7AD9EDD */ + 1.17186865567253592491e-01, /* 0x3FBDFFF5, 0x5B21D17B */ + 3.93297750033315640650e+00, /* 0x400F76BC, 0xE85EAD8A */ + 3.51194035591636932736e+01, /* 0x40418F48, 0x9DA6D129 */ + 9.10550110750781271918e+01, /* 0x4056C385, 0x4D2C1837 */ + 4.85590685197364919645e+01, /* 0x4048478F, 0x8EA83EE5 */ +}; +static const double ps3[5] = { + 3.47913095001251519989e+01, /* 0x40416549, 0xA134069C */ + 3.36762458747825746741e+02, /* 0x40750C33, 0x07F1A75F */ + 1.04687139975775130551e+03, /* 0x40905B7C, 0x5037D523 */ + 8.90811346398256432622e+02, /* 0x408BD67D, 0xA32E31E9 */ + 1.03787932439639277504e+02, /* 0x4059F26D, 0x7C2EED53 */ +}; + +static const double pr2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */ + 1.07710830106873743082e-07, /* 0x3E7CE9D4, 0xF65544F4 */ + 1.17176219462683348094e-01, /* 0x3FBDFF42, 0xBE760D83 */ + 2.36851496667608785174e+00, /* 0x4002F2B7, 0xF98FAEC0 */ + 1.22426109148261232917e+01, /* 0x40287C37, 0x7F71A964 */ + 1.76939711271687727390e+01, /* 0x4031B1A8, 0x177F8EE2 */ + 5.07352312588818499250e+00, /* 0x40144B49, 0xA574C1FE */ +}; +static const double ps2[5] = { + 2.14364859363821409488e+01, /* 0x40356FBD, 0x8AD5ECDC */ + 1.25290227168402751090e+02, /* 0x405F5293, 0x14F92CD5 */ + 2.32276469057162813669e+02, /* 0x406D08D8, 0xD5A2DBD9 */ + 1.17679373287147100768e+02, /* 0x405D6B7A, 0xDA1884A9 */ + 8.36463893371618283368e+00, /* 0x4020BAB1, 0xF44E5192 */ +}; + +static double pone(double x) +{ + const double *p=0,*q=0; + double z,r,s; + int32_t ix; + GET_HIGH_WORD(ix,x); + ix &= 0x7fffffff; + if(ix>=0x40200000) {p = pr8; q= ps8;} + else if(ix>=0x40122E8B){p = pr5; q= ps5;} + else if(ix>=0x4006DB6D){p = pr3; q= ps3;} + else if(ix>=0x40000000){p = pr2; q= ps2;} + z = one/(x*x); + r = p[0]+z*(p[1]+z*(p[2]+z*(p[3]+z*(p[4]+z*p[5])))); + s = one+z*(q[0]+z*(q[1]+z*(q[2]+z*(q[3]+z*q[4])))); + return one+ r/s; +} + + +/* For x >= 8, the asymptotic expansions of qone is + * 3/8 s - 105/1024 s^3 - ..., where s = 1/x. + * We approximate pone by + * qone(x) = s*(0.375 + (R/S)) + * where R = qr1*s^2 + qr2*s^4 + ... + qr5*s^10 + * S = 1 + qs1*s^2 + ... + qs6*s^12 + * and + * | qone(x)/s -0.375-R/S | <= 2 ** ( -61.13) + */ + +static const double qr8[6] = { /* for x in [inf, 8]=1/[0,0.125] */ + 0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */ + -1.02539062499992714161e-01, /* 0xBFBA3FFF, 0xFFFFFDF3 */ + -1.62717534544589987888e+01, /* 0xC0304591, 0xA26779F7 */ + -7.59601722513950107896e+02, /* 0xC087BCD0, 0x53E4B576 */ + -1.18498066702429587167e+04, /* 0xC0C724E7, 0x40F87415 */ + -4.84385124285750353010e+04, /* 0xC0E7A6D0, 0x65D09C6A */ +}; +static const double qs8[6] = { + 1.61395369700722909556e+02, /* 0x40642CA6, 0xDE5BCDE5 */ + 7.82538599923348465381e+03, /* 0x40BE9162, 0xD0D88419 */ + 1.33875336287249578163e+05, /* 0x4100579A, 0xB0B75E98 */ + 7.19657723683240939863e+05, /* 0x4125F653, 0x72869C19 */ + 6.66601232617776375264e+05, /* 0x412457D2, 0x7719AD5C */ + -2.94490264303834643215e+05, /* 0xC111F969, 0x0EA5AA18 */ +}; + +static const double qr5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */ + -2.08979931141764104297e-11, /* 0xBDB6FA43, 0x1AA1A098 */ + -1.02539050241375426231e-01, /* 0xBFBA3FFF, 0xCB597FEF */ + -8.05644828123936029840e+00, /* 0xC0201CE6, 0xCA03AD4B */ + -1.83669607474888380239e+02, /* 0xC066F56D, 0x6CA7B9B0 */ + -1.37319376065508163265e+03, /* 0xC09574C6, 0x6931734F */ + -2.61244440453215656817e+03, /* 0xC0A468E3, 0x88FDA79D */ +}; +static const double qs5[6] = { + 8.12765501384335777857e+01, /* 0x405451B2, 0xFF5A11B2 */ + 1.99179873460485964642e+03, /* 0x409F1F31, 0xE77BF839 */ + 1.74684851924908907677e+04, /* 0x40D10F1F, 0x0D64CE29 */ + 4.98514270910352279316e+04, /* 0x40E8576D, 0xAABAD197 */ + 2.79480751638918118260e+04, /* 0x40DB4B04, 0xCF7C364B */ + -4.71918354795128470869e+03, /* 0xC0B26F2E, 0xFCFFA004 */ +}; + +static const double qr3[6] = { + -5.07831226461766561369e-09, /* 0xBE35CFA9, 0xD38FC84F */ + -1.02537829820837089745e-01, /* 0xBFBA3FEB, 0x51AEED54 */ + -4.61011581139473403113e+00, /* 0xC01270C2, 0x3302D9FF */ + -5.78472216562783643212e+01, /* 0xC04CEC71, 0xC25D16DA */ + -2.28244540737631695038e+02, /* 0xC06C87D3, 0x4718D55F */ + -2.19210128478909325622e+02, /* 0xC06B66B9, 0x5F5C1BF6 */ +}; +static const double qs3[6] = { + 4.76651550323729509273e+01, /* 0x4047D523, 0xCCD367E4 */ + 6.73865112676699709482e+02, /* 0x40850EEB, 0xC031EE3E */ + 3.38015286679526343505e+03, /* 0x40AA684E, 0x448E7C9A */ + 5.54772909720722782367e+03, /* 0x40B5ABBA, 0xA61D54A6 */ + 1.90311919338810798763e+03, /* 0x409DBC7A, 0x0DD4DF4B */ + -1.35201191444307340817e+02, /* 0xC060E670, 0x290A311F */ +}; + +static const double qr2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */ + -1.78381727510958865572e-07, /* 0xBE87F126, 0x44C626D2 */ + -1.02517042607985553460e-01, /* 0xBFBA3E8E, 0x9148B010 */ + -2.75220568278187460720e+00, /* 0xC0060484, 0x69BB4EDA */ + -1.96636162643703720221e+01, /* 0xC033A9E2, 0xC168907F */ + -4.23253133372830490089e+01, /* 0xC04529A3, 0xDE104AAA */ + -2.13719211703704061733e+01, /* 0xC0355F36, 0x39CF6E52 */ +}; +static const double qs2[6] = { + 2.95333629060523854548e+01, /* 0x403D888A, 0x78AE64FF */ + 2.52981549982190529136e+02, /* 0x406F9F68, 0xDB821CBA */ + 7.57502834868645436472e+02, /* 0x4087AC05, 0xCE49A0F7 */ + 7.39393205320467245656e+02, /* 0x40871B25, 0x48D4C029 */ + 1.55949003336666123687e+02, /* 0x40637E5E, 0x3C3ED8D4 */ + -4.95949898822628210127e+00, /* 0xC013D686, 0xE71BE86B */ +}; + +static double qone(double x) +{ + const double *p=0,*q=0; + double s,r,z; + int32_t ix; + GET_HIGH_WORD(ix,x); + ix &= 0x7fffffff; + if(ix>=0x40200000) {p = qr8; q= qs8;} + else if(ix>=0x40122E8B){p = qr5; q= qs5;} + else if(ix>=0x4006DB6D){p = qr3; q= qs3;} + else if(ix>=0x40000000){p = qr2; q= qs2;} + z = one/(x*x); + r = p[0]+z*(p[1]+z*(p[2]+z*(p[3]+z*(p[4]+z*p[5])))); + s = one+z*(q[0]+z*(q[1]+z*(q[2]+z*(q[3]+z*(q[4]+z*q[5]))))); + return (.375 + r/s)/x; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/e_jn.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/e_jn.c new file mode 100644 index 00000000..3825bead --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/e_jn.c @@ -0,0 +1,298 @@ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* + * __ieee754_jn(n, x), __ieee754_yn(n, x) + * floating point Bessel's function of the 1st and 2nd kind + * of order n + * + * Special cases: + * y0(0)=y1(0)=yn(n,0) = -inf with division by zero signal; + * y0(-ve)=y1(-ve)=yn(n,-ve) are NaN with invalid signal. + * Note 2. About jn(n,x), yn(n,x) + * For n=0, j0(x) is called, + * for n=1, j1(x) is called, + * for nx, a continued fraction approximation to + * j(n,x)/j(n-1,x) is evaluated and then backward + * recursion is used starting from a supposed value + * for j(n,x). The resulting value of j(0,x) is + * compared with the actual value to correct the + * supposed value of j(n,x). + * + * yn(n,x) is similar in all respects, except + * that forward recursion is used for all + * values of n>1. + * + */ + +#include "math.h" +#include "math_private.h" + +static const double +invsqrtpi= 5.64189583547756279280e-01, /* 0x3FE20DD7, 0x50429B6D */ +two = 2.00000000000000000000e+00, /* 0x40000000, 0x00000000 */ +one = 1.00000000000000000000e+00; /* 0x3FF00000, 0x00000000 */ + +static const double zero = 0.00000000000000000000e+00; + +double attribute_hidden __ieee754_jn(int n, double x) +{ + int32_t i,hx,ix,lx, sgn; + double a, b, temp=0, di; + double z, w; + + /* J(-n,x) = (-1)^n * J(n, x), J(n, -x) = (-1)^n * J(n, x) + * Thus, J(-n,x) = J(n,-x) + */ + EXTRACT_WORDS(hx,lx,x); + ix = 0x7fffffff&hx; + /* if J(n,NaN) is NaN */ + if((ix|((u_int32_t)(lx|-lx))>>31)>0x7ff00000) return x+x; + if(n<0){ + n = -n; + x = -x; + hx ^= 0x80000000; + } + if(n==0) return(__ieee754_j0(x)); + if(n==1) return(__ieee754_j1(x)); + sgn = (n&1)&(hx>>31); /* even n -- 0, odd n -- sign(x) */ + x = fabs(x); + if((ix|lx)==0||ix>=0x7ff00000) /* if x is 0 or inf */ + b = zero; + else if((double)n<=x) { + /* Safe to use J(n+1,x)=2n/x *J(n,x)-J(n-1,x) */ + if(ix>=0x52D00000) { /* x > 2**302 */ + /* (x >> n**2) + * Jn(x) = cos(x-(2n+1)*pi/4)*sqrt(2/x*pi) + * Yn(x) = sin(x-(2n+1)*pi/4)*sqrt(2/x*pi) + * Let s=sin(x), c=cos(x), + * xn=x-(2n+1)*pi/4, sqt2 = sqrt(2),then + * + * n sin(xn)*sqt2 cos(xn)*sqt2 + * ---------------------------------- + * 0 s-c c+s + * 1 -s-c -c+s + * 2 -s+c -c-s + * 3 s+c c-s + */ + switch(n&3) { + case 0: temp = cos(x)+sin(x); break; + case 1: temp = -cos(x)+sin(x); break; + case 2: temp = -cos(x)-sin(x); break; + case 3: temp = cos(x)-sin(x); break; + } + b = invsqrtpi*temp/sqrt(x); + } else { + a = __ieee754_j0(x); + b = __ieee754_j1(x); + for(i=1;i33) /* underflow */ + b = zero; + else { + temp = x*0.5; b = temp; + for (a=one,i=2;i<=n;i++) { + a *= (double)i; /* a = n! */ + b *= temp; /* b = (x/2)^n */ + } + b = b/a; + } + } else { + /* use backward recurrence */ + /* x x^2 x^2 + * J(n,x)/J(n-1,x) = ---- ------ ------ ..... + * 2n - 2(n+1) - 2(n+2) + * + * 1 1 1 + * (for large x) = ---- ------ ------ ..... + * 2n 2(n+1) 2(n+2) + * -- - ------ - ------ - + * x x x + * + * Let w = 2n/x and h=2/x, then the above quotient + * is equal to the continued fraction: + * 1 + * = ----------------------- + * 1 + * w - ----------------- + * 1 + * w+h - --------- + * w+2h - ... + * + * To determine how many terms needed, let + * Q(0) = w, Q(1) = w(w+h) - 1, + * Q(k) = (w+k*h)*Q(k-1) - Q(k-2), + * When Q(k) > 1e4 good for single + * When Q(k) > 1e9 good for double + * When Q(k) > 1e17 good for quadruple + */ + /* determine k */ + double t,v; + double q0,q1,h,tmp; int32_t k,m; + w = (n+n)/(double)x; h = 2.0/(double)x; + q0 = w; z = w+h; q1 = w*z - 1.0; k=1; + while(q1<1.0e9) { + k += 1; z += h; + tmp = z*q1 - q0; + q0 = q1; + q1 = tmp; + } + m = n+n; + for(t=zero, i = 2*(n+k); i>=m; i -= 2) t = one/(i/x-t); + a = t; + b = one; + /* estimate log((2/x)^n*n!) = n*log(2/x)+n*ln(n) + * Hence, if n*(log(2n/x)) > ... + * single 8.8722839355e+01 + * double 7.09782712893383973096e+02 + * long double 1.1356523406294143949491931077970765006170e+04 + * then recurrent value may overflow and the result is + * likely underflow to zero + */ + tmp = n; + v = two/x; + tmp = tmp*__ieee754_log(fabs(v*tmp)); + if(tmp<7.09782712893383973096e+02) { + for(i=n-1,di=(double)(i+i);i>0;i--){ + temp = b; + b *= di; + b = b/x - a; + a = temp; + di -= two; + } + } else { + for(i=n-1,di=(double)(i+i);i>0;i--){ + temp = b; + b *= di; + b = b/x - a; + a = temp; + di -= two; + /* scale b to avoid spurious overflow */ + if(b>1e100) { + a /= b; + t /= b; + b = one; + } + } + } + b = (t*__ieee754_j0(x)/b); + } + } + if(sgn==1) return -b; else return b; +} + +/* + * wrapper jn(int n, double x) + */ +#ifndef _IEEE_LIBM +double jn(int n, double x) +{ + double z = __ieee754_jn(n, x); + if (_LIB_VERSION == _IEEE_ || isnan(x)) + return z; + if (fabs(x) > X_TLOSS) + return __kernel_standard((double)n, x, 38); /* jn(|x|>X_TLOSS,n) */ + return z; +} +#else +strong_alias(__ieee754_jn, jn) +#endif + +double attribute_hidden __ieee754_yn(int n, double x) +{ + int32_t i,hx,ix,lx; + int32_t sign; + double a, b, temp=0; + + EXTRACT_WORDS(hx,lx,x); + ix = 0x7fffffff&hx; + /* if Y(n,NaN) is NaN */ + if((ix|((u_int32_t)(lx|-lx))>>31)>0x7ff00000) return x+x; + if((ix|lx)==0) return -one/zero; + if(hx<0) return zero/zero; + sign = 1; + if(n<0){ + n = -n; + sign = 1 - ((n&1)<<1); + } + if(n==0) return(__ieee754_y0(x)); + if(n==1) return(sign*__ieee754_y1(x)); + if(ix==0x7ff00000) return zero; + if(ix>=0x52D00000) { /* x > 2**302 */ + /* (x >> n**2) + * Jn(x) = cos(x-(2n+1)*pi/4)*sqrt(2/x*pi) + * Yn(x) = sin(x-(2n+1)*pi/4)*sqrt(2/x*pi) + * Let s=sin(x), c=cos(x), + * xn=x-(2n+1)*pi/4, sqt2 = sqrt(2),then + * + * n sin(xn)*sqt2 cos(xn)*sqt2 + * ---------------------------------- + * 0 s-c c+s + * 1 -s-c -c+s + * 2 -s+c -c-s + * 3 s+c c-s + */ + switch(n&3) { + case 0: temp = sin(x)-cos(x); break; + case 1: temp = -sin(x)-cos(x); break; + case 2: temp = -sin(x)+cos(x); break; + case 3: temp = sin(x)+cos(x); break; + } + b = invsqrtpi*temp/sqrt(x); + } else { + u_int32_t high; + a = __ieee754_y0(x); + b = __ieee754_y1(x); + /* quit if b is -inf */ + GET_HIGH_WORD(high,b); + for(i=1;i0) return b; else return -b; +} + +/* + * wrapper yn(int n, double x) + */ +#ifndef _IEEE_LIBM +double yn(int n, double x) /* wrapper yn */ +{ + double z = __ieee754_yn(n, x); + if (_LIB_VERSION == _IEEE_ || isnan(x)) + return z; + if (x <= 0.0) { + if(x == 0.0) /* d= -one/(x-x); */ + return __kernel_standard((double)n, x, 12); + /* d = zero/(x-x); */ + return __kernel_standard((double)n, x, 13); + } + if (x > X_TLOSS) + return __kernel_standard((double)n, x, 39); /* yn(x>X_TLOSS,n) */ + return z; +} +#else +strong_alias(__ieee754_yn, yn) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/e_lgamma_r.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/e_lgamma_r.c new file mode 100644 index 00000000..dbb0a0d5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/e_lgamma_r.c @@ -0,0 +1,394 @@ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* __ieee754_lgamma_r(x, signgamp) + * Reentrant version of the logarithm of the Gamma function + * with user provide pointer for the sign of Gamma(x). + * + * Method: + * 1. Argument Reduction for 0 < x <= 8 + * Since gamma(1+s)=s*gamma(s), for x in [0,8], we may + * reduce x to a number in [1.5,2.5] by + * lgamma(1+s) = log(s) + lgamma(s) + * for example, + * lgamma(7.3) = log(6.3) + lgamma(6.3) + * = log(6.3*5.3) + lgamma(5.3) + * = log(6.3*5.3*4.3*3.3*2.3) + lgamma(2.3) + * 2. Polynomial approximation of lgamma around its + * minimun ymin=1.461632144968362245 to maintain monotonicity. + * On [ymin-0.23, ymin+0.27] (i.e., [1.23164,1.73163]), use + * Let z = x-ymin; + * lgamma(x) = -1.214862905358496078218 + z^2*poly(z) + * where + * poly(z) is a 14 degree polynomial. + * 2. Rational approximation in the primary interval [2,3] + * We use the following approximation: + * s = x-2.0; + * lgamma(x) = 0.5*s + s*P(s)/Q(s) + * with accuracy + * |P/Q - (lgamma(x)-0.5s)| < 2**-61.71 + * Our algorithms are based on the following observation + * + * zeta(2)-1 2 zeta(3)-1 3 + * lgamma(2+s) = s*(1-Euler) + --------- * s - --------- * s + ... + * 2 3 + * + * where Euler = 0.5771... is the Euler constant, which is very + * close to 0.5. + * + * 3. For x>=8, we have + * lgamma(x)~(x-0.5)log(x)-x+0.5*log(2pi)+1/(12x)-1/(360x**3)+.... + * (better formula: + * lgamma(x)~(x-0.5)*(log(x)-1)-.5*(log(2pi)-1) + ...) + * Let z = 1/x, then we approximation + * f(z) = lgamma(x) - (x-0.5)(log(x)-1) + * by + * 3 5 11 + * w = w0 + w1*z + w2*z + w3*z + ... + w6*z + * where + * |w - f(z)| < 2**-58.74 + * + * 4. For negative x, since (G is gamma function) + * -x*G(-x)*G(x) = pi/sin(pi*x), + * we have + * G(x) = pi/(sin(pi*x)*(-x)*G(-x)) + * since G(-x) is positive, sign(G(x)) = sign(sin(pi*x)) for x<0 + * Hence, for x<0, signgam = sign(sin(pi*x)) and + * lgamma(x) = log(|Gamma(x)|) + * = log(pi/(|x*sin(pi*x)|)) - lgamma(-x); + * Note: one should avoid compute pi*(-x) directly in the + * computation of sin(pi*(-x)). + * + * 5. Special Cases + * lgamma(2+s) ~ s*(1-Euler) for tiny s + * lgamma(1)=lgamma(2)=0 + * lgamma(x) ~ -log(x) for tiny x + * lgamma(0) = lgamma(inf) = inf + * lgamma(-integer) = +-inf + * + */ + +#include "math.h" +#include "math_private.h" + +static const double +two52= 4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */ +half= 5.00000000000000000000e-01, /* 0x3FE00000, 0x00000000 */ +one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */ +pi = 3.14159265358979311600e+00, /* 0x400921FB, 0x54442D18 */ +a0 = 7.72156649015328655494e-02, /* 0x3FB3C467, 0xE37DB0C8 */ +a1 = 3.22467033424113591611e-01, /* 0x3FD4A34C, 0xC4A60FAD */ +a2 = 6.73523010531292681824e-02, /* 0x3FB13E00, 0x1A5562A7 */ +a3 = 2.05808084325167332806e-02, /* 0x3F951322, 0xAC92547B */ +a4 = 7.38555086081402883957e-03, /* 0x3F7E404F, 0xB68FEFE8 */ +a5 = 2.89051383673415629091e-03, /* 0x3F67ADD8, 0xCCB7926B */ +a6 = 1.19270763183362067845e-03, /* 0x3F538A94, 0x116F3F5D */ +a7 = 5.10069792153511336608e-04, /* 0x3F40B6C6, 0x89B99C00 */ +a8 = 2.20862790713908385557e-04, /* 0x3F2CF2EC, 0xED10E54D */ +a9 = 1.08011567247583939954e-04, /* 0x3F1C5088, 0x987DFB07 */ +a10 = 2.52144565451257326939e-05, /* 0x3EFA7074, 0x428CFA52 */ +a11 = 4.48640949618915160150e-05, /* 0x3F07858E, 0x90A45837 */ +tc = 1.46163214496836224576e+00, /* 0x3FF762D8, 0x6356BE3F */ +tf = -1.21486290535849611461e-01, /* 0xBFBF19B9, 0xBCC38A42 */ +/* tt = -(tail of tf) */ +tt = -3.63867699703950536541e-18, /* 0xBC50C7CA, 0xA48A971F */ +t0 = 4.83836122723810047042e-01, /* 0x3FDEF72B, 0xC8EE38A2 */ +t1 = -1.47587722994593911752e-01, /* 0xBFC2E427, 0x8DC6C509 */ +t2 = 6.46249402391333854778e-02, /* 0x3FB08B42, 0x94D5419B */ +t3 = -3.27885410759859649565e-02, /* 0xBFA0C9A8, 0xDF35B713 */ +t4 = 1.79706750811820387126e-02, /* 0x3F9266E7, 0x970AF9EC */ +t5 = -1.03142241298341437450e-02, /* 0xBF851F9F, 0xBA91EC6A */ +t6 = 6.10053870246291332635e-03, /* 0x3F78FCE0, 0xE370E344 */ +t7 = -3.68452016781138256760e-03, /* 0xBF6E2EFF, 0xB3E914D7 */ +t8 = 2.25964780900612472250e-03, /* 0x3F6282D3, 0x2E15C915 */ +t9 = -1.40346469989232843813e-03, /* 0xBF56FE8E, 0xBF2D1AF1 */ +t10 = 8.81081882437654011382e-04, /* 0x3F4CDF0C, 0xEF61A8E9 */ +t11 = -5.38595305356740546715e-04, /* 0xBF41A610, 0x9C73E0EC */ +t12 = 3.15632070903625950361e-04, /* 0x3F34AF6D, 0x6C0EBBF7 */ +t13 = -3.12754168375120860518e-04, /* 0xBF347F24, 0xECC38C38 */ +t14 = 3.35529192635519073543e-04, /* 0x3F35FD3E, 0xE8C2D3F4 */ +u0 = -7.72156649015328655494e-02, /* 0xBFB3C467, 0xE37DB0C8 */ +u1 = 6.32827064025093366517e-01, /* 0x3FE4401E, 0x8B005DFF */ +u2 = 1.45492250137234768737e+00, /* 0x3FF7475C, 0xD119BD6F */ +u3 = 9.77717527963372745603e-01, /* 0x3FEF4976, 0x44EA8450 */ +u4 = 2.28963728064692451092e-01, /* 0x3FCD4EAE, 0xF6010924 */ +u5 = 1.33810918536787660377e-02, /* 0x3F8B678B, 0xBF2BAB09 */ +v1 = 2.45597793713041134822e+00, /* 0x4003A5D7, 0xC2BD619C */ +v2 = 2.12848976379893395361e+00, /* 0x40010725, 0xA42B18F5 */ +v3 = 7.69285150456672783825e-01, /* 0x3FE89DFB, 0xE45050AF */ +v4 = 1.04222645593369134254e-01, /* 0x3FBAAE55, 0xD6537C88 */ +v5 = 3.21709242282423911810e-03, /* 0x3F6A5ABB, 0x57D0CF61 */ +s0 = -7.72156649015328655494e-02, /* 0xBFB3C467, 0xE37DB0C8 */ +s1 = 2.14982415960608852501e-01, /* 0x3FCB848B, 0x36E20878 */ +s2 = 3.25778796408930981787e-01, /* 0x3FD4D98F, 0x4F139F59 */ +s3 = 1.46350472652464452805e-01, /* 0x3FC2BB9C, 0xBEE5F2F7 */ +s4 = 2.66422703033638609560e-02, /* 0x3F9B481C, 0x7E939961 */ +s5 = 1.84028451407337715652e-03, /* 0x3F5E26B6, 0x7368F239 */ +s6 = 3.19475326584100867617e-05, /* 0x3F00BFEC, 0xDD17E945 */ +r1 = 1.39200533467621045958e+00, /* 0x3FF645A7, 0x62C4AB74 */ +r2 = 7.21935547567138069525e-01, /* 0x3FE71A18, 0x93D3DCDC */ +r3 = 1.71933865632803078993e-01, /* 0x3FC601ED, 0xCCFBDF27 */ +r4 = 1.86459191715652901344e-02, /* 0x3F9317EA, 0x742ED475 */ +r5 = 7.77942496381893596434e-04, /* 0x3F497DDA, 0xCA41A95B */ +r6 = 7.32668430744625636189e-06, /* 0x3EDEBAF7, 0xA5B38140 */ +w0 = 4.18938533204672725052e-01, /* 0x3FDACFE3, 0x90C97D69 */ +w1 = 8.33333333333329678849e-02, /* 0x3FB55555, 0x5555553B */ +w2 = -2.77777777728775536470e-03, /* 0xBF66C16C, 0x16B02E5C */ +w3 = 7.93650558643019558500e-04, /* 0x3F4A019F, 0x98CF38B6 */ +w4 = -5.95187557450339963135e-04, /* 0xBF4380CB, 0x8C0FE741 */ +w5 = 8.36339918996282139126e-04, /* 0x3F4B67BA, 0x4CDAD5D1 */ +w6 = -1.63092934096575273989e-03; /* 0xBF5AB89D, 0x0B9E43E4 */ + +static const double zero= 0.00000000000000000000e+00; + +static +#ifdef __GNUC__ +__inline__ +#endif +double sin_pi(double x) +{ + double y,z; + int n,ix; + + GET_HIGH_WORD(ix,x); + ix &= 0x7fffffff; + + if(ix<0x3fd00000) return __kernel_sin(pi*x,zero,0); + y = -x; /* x is assume negative */ + + /* + * argument reduction, make sure inexact flag not raised if input + * is an integer + */ + z = floor(y); + if(z!=y) { /* inexact anyway */ + y *= 0.5; + y = 2.0*(y - floor(y)); /* y = |x| mod 2.0 */ + n = (int) (y*4.0); + } else { + if(ix>=0x43400000) { + y = zero; n = 0; /* y must be even */ + } else { + if(ix<0x43300000) z = y+two52; /* exact */ + GET_LOW_WORD(n,z); + n &= 1; + y = n; + n<<= 2; + } + } + switch (n) { + case 0: y = __kernel_sin(pi*y,zero,0); break; + case 1: + case 2: y = __kernel_cos(pi*(0.5-y),zero); break; + case 3: + case 4: y = __kernel_sin(pi*(one-y),zero,0); break; + case 5: + case 6: y = -__kernel_cos(pi*(y-1.5),zero); break; + default: y = __kernel_sin(pi*(y-2.0),zero,0); break; + } + return -y; +} + +double attribute_hidden __ieee754_lgamma_r(double x, int *signgamp) +{ + double t,y,z,nadj=0,p,p1,p2,p3,q,r,w; + int i,hx,lx,ix; + + EXTRACT_WORDS(hx,lx,x); + + /* purge off +-inf, NaN, +-0, and negative arguments */ + *signgamp = 1; + ix = hx&0x7fffffff; + if(ix>=0x7ff00000) return x*x; + if((ix|lx)==0) { + if (signbit(x)) + *signgamp = -1; + return one/zero; + } + if(ix<0x3b900000) { /* |x|<2**-70, return -log(|x|) */ + if(hx<0) { + *signgamp = -1; + return -__ieee754_log(-x); + } else return -__ieee754_log(x); + } + if(hx<0) { + if(ix>=0x43300000) /* |x|>=2**52, must be -integer */ + return one/zero; + t = sin_pi(x); + if(t==zero) return one/zero; /* -integer */ + nadj = __ieee754_log(pi/fabs(t*x)); + if(t=0x3FE76944) {y = one-x; i= 0;} + else if(ix>=0x3FCDA661) {y= x-(tc-one); i=1;} + else {y = x; i=2;} + } else { + r = zero; + if(ix>=0x3FFBB4C3) {y=2.0-x;i=0;} /* [1.7316,2] */ + else if(ix>=0x3FF3B4C4) {y=x-tc;i=1;} /* [1.23,1.73] */ + else {y=x-one;i=2;} + } + switch(i) { + case 0: + z = y*y; + p1 = a0+z*(a2+z*(a4+z*(a6+z*(a8+z*a10)))); + p2 = z*(a1+z*(a3+z*(a5+z*(a7+z*(a9+z*a11))))); + p = y*p1+p2; + r += (p-0.5*y); break; + case 1: + z = y*y; + w = z*y; + p1 = t0+w*(t3+w*(t6+w*(t9 +w*t12))); /* parallel comp */ + p2 = t1+w*(t4+w*(t7+w*(t10+w*t13))); + p3 = t2+w*(t5+w*(t8+w*(t11+w*t14))); + p = z*p1-(tt-w*(p2+y*p3)); + r += (tf + p); break; + case 2: + p1 = y*(u0+y*(u1+y*(u2+y*(u3+y*(u4+y*u5))))); + p2 = one+y*(v1+y*(v2+y*(v3+y*(v4+y*v5)))); + r += (-0.5*y + p1/p2); + } + } + else if(ix<0x40200000) { /* x < 8.0 */ + i = (int)x; + t = zero; + y = x-(double)i; + p = y*(s0+y*(s1+y*(s2+y*(s3+y*(s4+y*(s5+y*s6)))))); + q = one+y*(r1+y*(r2+y*(r3+y*(r4+y*(r5+y*r6))))); + r = half*y+p/q; + z = one; /* lgamma(1+s) = log(s) + lgamma(s) */ + switch(i) { + case 7: z *= (y+6.0); /* FALLTHRU */ + case 6: z *= (y+5.0); /* FALLTHRU */ + case 5: z *= (y+4.0); /* FALLTHRU */ + case 4: z *= (y+3.0); /* FALLTHRU */ + case 3: z *= (y+2.0); /* FALLTHRU */ + r += __ieee754_log(z); break; + } + /* 8.0 <= x < 2**58 */ + } else if (ix < 0x43900000) { + t = __ieee754_log(x); + z = one/x; + y = z*z; + w = w0+z*(w1+y*(w2+y*(w3+y*(w4+y*(w5+y*w6))))); + r = (x-half)*(t-one)+w; + } else + /* 2**58 <= x <= inf */ + r = x*(__ieee754_log(x)-one); + if(hx<0) r = nadj - r; + return r; +} + +/* + * wrapper double lgamma_r(double x, int *signgamp) + */ +#ifndef _IEEE_LIBM +double lgamma_r(double x, int *signgamp) +{ + double y = __ieee754_lgamma_r(x, signgamp); + if (_LIB_VERSION == _IEEE_) + return y; + if (!isfinite(y) && isfinite(x)) { + if (floor(x) == x && x <= 0.0) + return __kernel_standard(x, x, 15); /* lgamma pole */ + return __kernel_standard(x, x, 14); /* lgamma overflow */ + } + return y; +} +#else +strong_alias(__ieee754_lgamma_r, lgamma_r) +#endif + +/* __ieee754_lgamma(x) + * Return the logarithm of the Gamma function of x. + */ +double attribute_hidden __ieee754_lgamma(double x) +{ + return __ieee754_lgamma_r(x, &signgam); +} + +/* + * wrapper double lgamma(double x) + */ +#ifndef _IEEE_LIBM +double lgamma(double x) +{ + double y = __ieee754_lgamma_r(x, &signgam); + if (_LIB_VERSION == _IEEE_) + return y; + if (!isfinite(y) && isfinite(x)) { + if (floor(x) == x && x <= 0.0) + return __kernel_standard(x, x, 15); /* lgamma pole */ + return __kernel_standard(x, x, 14); /* lgamma overflow */ + } + return y; +} +#else +strong_alias(__ieee754_lgamma, lgamma); +#endif +libm_hidden_def(lgamma) + + +/* NB: gamma function is an old name for lgamma. + * It is deprecated. + * Some C math libraries redefine it as a "true gamma", i.e., + * not a ln(|Gamma(x)|) but just Gamma(x), but standards + * introduced tgamma name for that. + */ +#ifndef _IEEE_LIBM +strong_alias(lgamma_r, gamma_r) +strong_alias(lgamma, gamma) +#else +strong_alias(__ieee754_lgamma_r, gamma_r) +strong_alias(__ieee754_lgamma, gamma) +#endif + + +/* double tgamma(double x) + * Return the Gamma function of x. + */ +double tgamma(double x) +{ + int sign_of_gamma; + int32_t hx; + u_int32_t lx; + + /* We don't have a real gamma implementation now. We'll use lgamma + and the exp function. But due to the required boundary + conditions we must check some values separately. */ + + EXTRACT_WORDS(hx, lx, x); + + if (((hx & 0x7fffffff) | lx) == 0) { + /* Return value for x == 0 is Inf with divide by zero exception. */ + return 1.0 / x; + } + if (hx < 0 && (u_int32_t)hx < 0xfff00000 && rint(x) == x) { + /* Return value for integer x < 0 is NaN with invalid exception. */ + return (x - x) / (x - x); + } + if ((u_int32_t)hx == 0xfff00000 && lx == 0) { + /* x == -Inf. According to ISO this is NaN. */ + return x - x; + } + + x = exp(lgamma_r(x, &sign_of_gamma)); + return sign_of_gamma >= 0 ? x : -x; +} +libm_hidden_def(tgamma) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/e_log.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/e_log.c new file mode 100644 index 00000000..4a82b6e5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/e_log.c @@ -0,0 +1,147 @@ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* __ieee754_log(x) + * Return the logrithm of x + * + * Method : + * 1. Argument Reduction: find k and f such that + * x = 2^k * (1+f), + * where sqrt(2)/2 < 1+f < sqrt(2) . + * + * 2. Approximation of log(1+f). + * Let s = f/(2+f) ; based on log(1+f) = log(1+s) - log(1-s) + * = 2s + 2/3 s**3 + 2/5 s**5 + ....., + * = 2s + s*R + * We use a special Reme algorithm on [0,0.1716] to generate + * a polynomial of degree 14 to approximate R The maximum error + * of this polynomial approximation is bounded by 2**-58.45. In + * other words, + * 2 4 6 8 10 12 14 + * R(z) ~ Lg1*s +Lg2*s +Lg3*s +Lg4*s +Lg5*s +Lg6*s +Lg7*s + * (the values of Lg1 to Lg7 are listed in the program) + * and + * | 2 14 | -58.45 + * | Lg1*s +...+Lg7*s - R(z) | <= 2 + * | | + * Note that 2s = f - s*f = f - hfsq + s*hfsq, where hfsq = f*f/2. + * In order to guarantee error in log below 1ulp, we compute log + * by + * log(1+f) = f - s*(f - R) (if f is not too large) + * log(1+f) = f - (hfsq - s*(hfsq+R)). (better accuracy) + * + * 3. Finally, log(x) = k*ln2 + log(1+f). + * = k*ln2_hi+(f-(hfsq-(s*(hfsq+R)+k*ln2_lo))) + * Here ln2 is split into two floating point number: + * ln2_hi + ln2_lo, + * where n*ln2_hi is always exact for |n| < 2000. + * + * Special cases: + * log(x) is NaN with signal if x < 0 (including -INF) ; + * log(+INF) is +INF; log(0) is -INF with signal; + * log(NaN) is that NaN with no signal. + * + * Accuracy: + * according to an error analysis, the error is always less than + * 1 ulp (unit in the last place). + * + * Constants: + * The hexadecimal values are the intended ones for the following + * constants. The decimal values may be used, provided that the + * compiler will convert from decimal to binary accurately enough + * to produce the hexadecimal values shown. + */ + +#include "math.h" +#include "math_private.h" + +static const double +ln2_hi = 6.93147180369123816490e-01, /* 3fe62e42 fee00000 */ +ln2_lo = 1.90821492927058770002e-10, /* 3dea39ef 35793c76 */ +two54 = 1.80143985094819840000e+16, /* 43500000 00000000 */ +Lg1 = 6.666666666666735130e-01, /* 3FE55555 55555593 */ +Lg2 = 3.999999999940941908e-01, /* 3FD99999 9997FA04 */ +Lg3 = 2.857142874366239149e-01, /* 3FD24924 94229359 */ +Lg4 = 2.222219843214978396e-01, /* 3FCC71C5 1D8E78AF */ +Lg5 = 1.818357216161805012e-01, /* 3FC74664 96CB03DE */ +Lg6 = 1.531383769920937332e-01, /* 3FC39A09 D078C69F */ +Lg7 = 1.479819860511658591e-01; /* 3FC2F112 DF3E5244 */ + +static const double zero = 0.0; + +double attribute_hidden __ieee754_log(double x) +{ + double hfsq,f,s,z,R,w,t1,t2,dk; + int32_t k,hx,i,j; + u_int32_t lx; + + EXTRACT_WORDS(hx,lx,x); + + k=0; + if (hx < 0x00100000) { /* x < 2**-1022 */ + if (((hx&0x7fffffff)|lx)==0) + return -two54/zero; /* log(+-0)=-inf */ + if (hx<0) return (x-x)/zero; /* log(-#) = NaN */ + k -= 54; x *= two54; /* subnormal number, scale up x */ + GET_HIGH_WORD(hx,x); + } + if (hx >= 0x7ff00000) return x+x; + k += (hx>>20)-1023; + hx &= 0x000fffff; + i = (hx+0x95f64)&0x100000; + SET_HIGH_WORD(x,hx|(i^0x3ff00000)); /* normalize x or x/2 */ + k += (i>>20); + f = x-1.0; + if((0x000fffff&(2+hx))<3) { /* |f| < 2**-20 */ + if(f==zero) {if(k==0) return zero; else {dk=(double)k; + return dk*ln2_hi+dk*ln2_lo;} + } + R = f*f*(0.5-0.33333333333333333*f); + if(k==0) return f-R; else {dk=(double)k; + return dk*ln2_hi-((R-dk*ln2_lo)-f);} + } + s = f/(2.0+f); + dk = (double)k; + z = s*s; + i = hx-0x6147a; + w = z*z; + j = 0x6b851-hx; + t1= w*(Lg2+w*(Lg4+w*Lg6)); + t2= z*(Lg1+w*(Lg3+w*(Lg5+w*Lg7))); + i |= j; + R = t2+t1; + if(i>0) { + hfsq=0.5*f*f; + if(k==0) return f-(hfsq-s*(hfsq+R)); else + return dk*ln2_hi-((hfsq-(s*(hfsq+R)+dk*ln2_lo))-f); + } else { + if(k==0) return f-s*(f-R); else + return dk*ln2_hi-((s*(f-R)-dk*ln2_lo)-f); + } +} + +/* + * wrapper log(x) + */ +#ifndef _IEEE_LIBM +double log(double x) +{ + double z = __ieee754_log(x); + if (_LIB_VERSION == _IEEE_ || isnan(x) || x > 0.0) + return z; + if (x == 0.0) + return __kernel_standard(x, x, 16); /* log(0) */ + return __kernel_standard(x, x, 17); /* log(x<0) */ +} +#else +strong_alias(__ieee754_log, log) +#endif +libm_hidden_def(log) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/e_log10.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/e_log10.c new file mode 100644 index 00000000..ff2241e5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/e_log10.c @@ -0,0 +1,101 @@ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* __ieee754_log10(x) + * Return the base 10 logarithm of x + * + * Method : + * Let log10_2hi = leading 40 bits of log10(2) and + * log10_2lo = log10(2) - log10_2hi, + * ivln10 = 1/log(10) rounded. + * Then + * n = ilogb(x), + * if(n<0) n = n+1; + * x = scalbn(x,-n); + * log10(x) := n*log10_2hi + (n*log10_2lo + ivln10*log(x)) + * + * Note 1: + * To guarantee log10(10**n)=n, where 10**n is normal, the rounding + * mode must set to Round-to-Nearest. + * Note 2: + * [1/log(10)] rounded to 53 bits has error .198 ulps; + * log10 is monotonic at all binary break points. + * + * Special cases: + * log10(x) is NaN with signal if x < 0; + * log10(+INF) is +INF with no signal; log10(0) is -INF with signal; + * log10(NaN) is that NaN with no signal; + * log10(10**N) = N for N=0,1,...,22. + * + * Constants: + * The hexadecimal values are the intended ones for the following constants. + * The decimal values may be used, provided that the compiler will convert + * from decimal to binary accurately enough to produce the hexadecimal values + * shown. + */ + +#include "math.h" +#include "math_private.h" + +static const double +two54 = 1.80143985094819840000e+16, /* 0x43500000, 0x00000000 */ +ivln10 = 4.34294481903251816668e-01, /* 0x3FDBCB7B, 0x1526E50E */ +log10_2hi = 3.01029995663611771306e-01, /* 0x3FD34413, 0x509F6000 */ +log10_2lo = 3.69423907715893078616e-13; /* 0x3D59FEF3, 0x11F12B36 */ + +static const double zero = 0.0; + +double attribute_hidden __ieee754_log10(double x) +{ + double y,z; + int32_t i,k,hx; + u_int32_t lx; + + EXTRACT_WORDS(hx,lx,x); + + k=0; + if (hx < 0x00100000) { /* x < 2**-1022 */ + if (((hx&0x7fffffff)|lx)==0) + return -two54/zero; /* log(+-0)=-inf */ + if (hx<0) return (x-x)/zero; /* log(-#) = NaN */ + k -= 54; x *= two54; /* subnormal number, scale up x */ + GET_HIGH_WORD(hx,x); + } + if (hx >= 0x7ff00000) return x+x; + k += (hx>>20)-1023; + i = ((u_int32_t)k&0x80000000)>>31; + hx = (hx&0x000fffff)|((0x3ff-i)<<20); + y = (double)(k+i); + SET_HIGH_WORD(x,hx); + z = y*log10_2lo + ivln10*__ieee754_log(x); + return z+y*log10_2hi; +} + +/* + * wrapper log10(X) + */ +#ifndef _IEEE_LIBM +double log10(double x) +{ + double z = __ieee754_log10(x); + if (_LIB_VERSION == _IEEE_ || isnan(x)) + return z; + if (x <= 0.0) { + if(x == 0.0) + return __kernel_standard(x, x, 18); /* log10(0) */ + return __kernel_standard(x, x, 19); /* log10(x<0) */ + } + return z; +} +#else +strong_alias(__ieee754_log10, log10) +#endif +libm_hidden_def(log10) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/e_log2.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/e_log2.c new file mode 100644 index 00000000..70e604b3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/e_log2.c @@ -0,0 +1,118 @@ +/* Adapted for log2 by Ulrich Drepper . */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* __ieee754_log2(x) + * Return the logarithm to base 2 of x + * + * Method : + * 1. Argument Reduction: find k and f such that + * x = 2^k * (1+f), + * where sqrt(2)/2 < 1+f < sqrt(2) . + * + * 2. Approximation of log(1+f). + * Let s = f/(2+f) ; based on log(1+f) = log(1+s) - log(1-s) + * = 2s + 2/3 s**3 + 2/5 s**5 + ....., + * = 2s + s*R + * We use a special Reme algorithm on [0,0.1716] to generate + * a polynomial of degree 14 to approximate R The maximum error + * of this polynomial approximation is bounded by 2**-58.45. In + * other words, + * 2 4 6 8 10 12 14 + * R(z) ~ Lg1*s +Lg2*s +Lg3*s +Lg4*s +Lg5*s +Lg6*s +Lg7*s + * (the values of Lg1 to Lg7 are listed in the program) + * and + * | 2 14 | -58.45 + * | Lg1*s +...+Lg7*s - R(z) | <= 2 + * | | + * Note that 2s = f - s*f = f - hfsq + s*hfsq, where hfsq = f*f/2. + * In order to guarantee error in log below 1ulp, we compute log + * by + * log(1+f) = f - s*(f - R) (if f is not too large) + * log(1+f) = f - (hfsq - s*(hfsq+R)). (better accuracy) + * + * 3. Finally, log(x) = k + log(1+f). + * = k+(f-(hfsq-(s*(hfsq+R)))) + * + * Special cases: + * log2(x) is NaN with signal if x < 0 (including -INF) ; + * log2(+INF) is +INF; log(0) is -INF with signal; + * log2(NaN) is that NaN with no signal. + * + * Constants: + * The hexadecimal values are the intended ones for the following + * constants. The decimal values may be used, provided that the + * compiler will convert from decimal to binary accurately enough + * to produce the hexadecimal values shown. + */ + +#include "math.h" +#include "math_private.h" + +static const double +ln2 = 0.69314718055994530942, +two54 = 1.80143985094819840000e+16, /* 43500000 00000000 */ +Lg1 = 6.666666666666735130e-01, /* 3FE55555 55555593 */ +Lg2 = 3.999999999940941908e-01, /* 3FD99999 9997FA04 */ +Lg3 = 2.857142874366239149e-01, /* 3FD24924 94229359 */ +Lg4 = 2.222219843214978396e-01, /* 3FCC71C5 1D8E78AF */ +Lg5 = 1.818357216161805012e-01, /* 3FC74664 96CB03DE */ +Lg6 = 1.531383769920937332e-01, /* 3FC39A09 D078C69F */ +Lg7 = 1.479819860511658591e-01; /* 3FC2F112 DF3E5244 */ + +static const double zero = 0.0; + +double __ieee754_log2(double x) +{ + double hfsq,f,s,z,R,w,t1,t2,dk; + int32_t k,hx,i,j; + u_int32_t lx; + + EXTRACT_WORDS(hx,lx,x); + + k=0; + if (hx < 0x00100000) { /* x < 2**-1022 */ + if (((hx&0x7fffffff)|lx)==0) + return -two54/(x-x); /* log(+-0)=-inf */ + if (hx<0) return (x-x)/(x-x); /* log(-#) = NaN */ + k -= 54; x *= two54; /* subnormal number, scale up x */ + GET_HIGH_WORD(hx,x); + } + if (hx >= 0x7ff00000) return x+x; + k += (hx>>20)-1023; + hx &= 0x000fffff; + i = (hx+0x95f64)&0x100000; + SET_HIGH_WORD(x,hx|(i^0x3ff00000)); /* normalize x or x/2 */ + k += (i>>20); + dk = (double) k; + f = x-1.0; + if((0x000fffff&(2+hx))<3) { /* |f| < 2**-20 */ + if(f==zero) return dk; + R = f*f*(0.5-0.33333333333333333*f); + return dk-(R-f)/ln2; + } + s = f/(2.0+f); + z = s*s; + i = hx-0x6147a; + w = z*z; + j = 0x6b851-hx; + t1= w*(Lg2+w*(Lg4+w*Lg6)); + t2= z*(Lg1+w*(Lg3+w*(Lg5+w*Lg7))); + i |= j; + R = t2+t1; + if(i>0) { + hfsq=0.5*f*f; + return dk-((hfsq-(s*(hfsq+R)))-f)/ln2; + } else { + return dk-((s*(f-R))-f)/ln2; + } +} +strong_alias(__ieee754_log2,log2) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/e_pow.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/e_pow.c new file mode 100644 index 00000000..3be90038 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/e_pow.c @@ -0,0 +1,338 @@ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* __ieee754_pow(x,y) return x**y + * + * n + * Method: Let x = 2 * (1+f) + * 1. Compute and return log2(x) in two pieces: + * log2(x) = w1 + w2, + * where w1 has 53-24 = 29 bit trailing zeros. + * 2. Perform y*log2(x) = n+y' by simulating muti-precision + * arithmetic, where |y'|<=0.5. + * 3. Return x**y = 2**n*exp(y'*log2) + * + * Special cases: + * 1. +-1 ** anything is 1.0 + * 2. +-1 ** +-INF is 1.0 + * 3. (anything) ** 0 is 1 + * 4. (anything) ** 1 is itself + * 5. (anything) ** NAN is NAN + * 6. NAN ** (anything except 0) is NAN + * 7. +-(|x| > 1) ** +INF is +INF + * 8. +-(|x| > 1) ** -INF is +0 + * 9. +-(|x| < 1) ** +INF is +0 + * 10 +-(|x| < 1) ** -INF is +INF + * 11. +0 ** (+anything except 0, NAN) is +0 + * 12. -0 ** (+anything except 0, NAN, odd integer) is +0 + * 13. +0 ** (-anything except 0, NAN) is +INF + * 14. -0 ** (-anything except 0, NAN, odd integer) is +INF + * 15. -0 ** (odd integer) = -( +0 ** (odd integer) ) + * 16. +INF ** (+anything except 0,NAN) is +INF + * 17. +INF ** (-anything except 0,NAN) is +0 + * 18. -INF ** (anything) = -0 ** (-anything) + * 19. (-anything) ** (integer) is (-1)**(integer)*(+anything**integer) + * 20. (-anything except 0 and inf) ** (non-integer) is NAN + * + * Accuracy: + * pow(x,y) returns x**y nearly rounded. In particular + * pow(integer,integer) + * always returns the correct integer provided it is + * representable. + * + * Constants : + * The hexadecimal values are the intended ones for the following + * constants. The decimal values may be used, provided that the + * compiler will convert from decimal to binary accurately enough + * to produce the hexadecimal values shown. + */ + +#include "math.h" +#include "math_private.h" + +static const double +bp[] = {1.0, 1.5,}, +dp_h[] = { 0.0, 5.84962487220764160156e-01,}, /* 0x3FE2B803, 0x40000000 */ +dp_l[] = { 0.0, 1.35003920212974897128e-08,}, /* 0x3E4CFDEB, 0x43CFD006 */ +zero = 0.0, +one = 1.0, +two = 2.0, +two53 = 9007199254740992.0, /* 0x43400000, 0x00000000 */ +huge = 1.0e300, +tiny = 1.0e-300, + /* poly coefs for (3/2)*(log(x)-2s-2/3*s**3 */ +L1 = 5.99999999999994648725e-01, /* 0x3FE33333, 0x33333303 */ +L2 = 4.28571428578550184252e-01, /* 0x3FDB6DB6, 0xDB6FABFF */ +L3 = 3.33333329818377432918e-01, /* 0x3FD55555, 0x518F264D */ +L4 = 2.72728123808534006489e-01, /* 0x3FD17460, 0xA91D4101 */ +L5 = 2.30660745775561754067e-01, /* 0x3FCD864A, 0x93C9DB65 */ +L6 = 2.06975017800338417784e-01, /* 0x3FCA7E28, 0x4A454EEF */ +P1 = 1.66666666666666019037e-01, /* 0x3FC55555, 0x5555553E */ +P2 = -2.77777777770155933842e-03, /* 0xBF66C16C, 0x16BEBD93 */ +P3 = 6.61375632143793436117e-05, /* 0x3F11566A, 0xAF25DE2C */ +P4 = -1.65339022054652515390e-06, /* 0xBEBBBD41, 0xC5D26BF1 */ +P5 = 4.13813679705723846039e-08, /* 0x3E663769, 0x72BEA4D0 */ +lg2 = 6.93147180559945286227e-01, /* 0x3FE62E42, 0xFEFA39EF */ +lg2_h = 6.93147182464599609375e-01, /* 0x3FE62E43, 0x00000000 */ +lg2_l = -1.90465429995776804525e-09, /* 0xBE205C61, 0x0CA86C39 */ +ovt = 8.0085662595372944372e-0017, /* -(1024-log2(ovfl+.5ulp)) */ +cp = 9.61796693925975554329e-01, /* 0x3FEEC709, 0xDC3A03FD =2/(3ln2) */ +cp_h = 9.61796700954437255859e-01, /* 0x3FEEC709, 0xE0000000 =(float)cp */ +cp_l = -7.02846165095275826516e-09, /* 0xBE3E2FE0, 0x145B01F5 =tail of cp_h*/ +ivln2 = 1.44269504088896338700e+00, /* 0x3FF71547, 0x652B82FE =1/ln2 */ +ivln2_h = 1.44269502162933349609e+00, /* 0x3FF71547, 0x60000000 =24b 1/ln2*/ +ivln2_l = 1.92596299112661746887e-08; /* 0x3E54AE0B, 0xF85DDF44 =1/ln2 tail*/ + +double attribute_hidden __ieee754_pow(double x, double y) +{ + double z,ax,z_h,z_l,p_h,p_l; + double y1,t1,t2,r,s,t,u,v,w; + int32_t i,j,k,yisint,n; + int32_t hx,hy,ix,iy; + u_int32_t lx,ly; + + EXTRACT_WORDS(hx,lx,x); + /* x==1: 1**y = 1 (even if y is NaN) */ + if (hx==0x3ff00000 && lx==0) { + return x; + } + ix = hx&0x7fffffff; + + EXTRACT_WORDS(hy,ly,y); + iy = hy&0x7fffffff; + + /* y==zero: x**0 = 1 */ + if((iy|ly)==0) return one; + + /* +-NaN return x+y */ + if(ix > 0x7ff00000 || ((ix==0x7ff00000)&&(lx!=0)) || + iy > 0x7ff00000 || ((iy==0x7ff00000)&&(ly!=0))) + return x+y; + + /* determine if y is an odd int when x < 0 + * yisint = 0 ... y is not an integer + * yisint = 1 ... y is an odd int + * yisint = 2 ... y is an even int + */ + yisint = 0; + if(hx<0) { + if(iy>=0x43400000) yisint = 2; /* even integer y */ + else if(iy>=0x3ff00000) { + k = (iy>>20)-0x3ff; /* exponent */ + if(k>20) { + j = ly>>(52-k); + if((j<<(52-k))==ly) yisint = 2-(j&1); + } else if(ly==0) { + j = iy>>(20-k); + if((j<<(20-k))==iy) yisint = 2-(j&1); + } + } + } + + /* special value of y */ + if(ly==0) { + if (iy==0x7ff00000) { /* y is +-inf */ + if (((ix-0x3ff00000)|lx)==0) + return one; /* +-1**+-inf is 1 (yes, weird rule) */ + if (ix >= 0x3ff00000) /* (|x|>1)**+-inf = inf,0 */ + return (hy>=0) ? y : zero; + /* (|x|<1)**-,+inf = inf,0 */ + return (hy<0) ? -y : zero; + } + if(iy==0x3ff00000) { /* y is +-1 */ + if(hy<0) return one/x; else return x; + } + if(hy==0x40000000) return x*x; /* y is 2 */ + if(hy==0x3fe00000) { /* y is 0.5 */ + if(hx>=0) /* x >= +0 */ + return __ieee754_sqrt(x); + } + } + + ax = fabs(x); + /* special value of x */ + if(lx==0) { + if(ix==0x7ff00000||ix==0||ix==0x3ff00000){ + z = ax; /*x is +-0,+-inf,+-1*/ + if(hy<0) z = one/z; /* z = (1/|x|) */ + if(hx<0) { + if(((ix-0x3ff00000)|yisint)==0) { + z = (z-z)/(z-z); /* (-1)**non-int is NaN */ + } else if(yisint==1) + z = -z; /* (x<0)**odd = -(|x|**odd) */ + } + return z; + } + } + + /* (x<0)**(non-int) is NaN */ + if(((((u_int32_t)hx>>31)-1)|yisint)==0) return (x-x)/(x-x); + + /* |y| is huge */ + if(iy>0x41e00000) { /* if |y| > 2**31 */ + if(iy>0x43f00000){ /* if |y| > 2**64, must o/uflow */ + if(ix<=0x3fefffff) return (hy<0)? huge*huge:tiny*tiny; + if(ix>=0x3ff00000) return (hy>0)? huge*huge:tiny*tiny; + } + /* over/underflow if x is not close to one */ + if(ix<0x3fefffff) return (hy<0)? huge*huge:tiny*tiny; + if(ix>0x3ff00000) return (hy>0)? huge*huge:tiny*tiny; + /* now |1-x| is tiny <= 2**-20, suffice to compute + log(x) by x-x^2/2+x^3/3-x^4/4 */ + t = x-1; /* t has 20 trailing zeros */ + w = (t*t)*(0.5-t*(0.3333333333333333333333-t*0.25)); + u = ivln2_h*t; /* ivln2_h has 21 sig. bits */ + v = t*ivln2_l-w*ivln2; + t1 = u+v; + SET_LOW_WORD(t1,0); + t2 = v-(t1-u); + } else { + double s2,s_h,s_l,t_h,t_l; + n = 0; + /* take care subnormal number */ + if(ix<0x00100000) + {ax *= two53; n -= 53; GET_HIGH_WORD(ix,ax); } + n += ((ix)>>20)-0x3ff; + j = ix&0x000fffff; + /* determine interval */ + ix = j|0x3ff00000; /* normalize ix */ + if(j<=0x3988E) k=0; /* |x|>1)|0x20000000)+0x00080000+(k<<18)); + t_l = ax - (t_h-bp[k]); + s_l = v*((u-s_h*t_h)-s_h*t_l); + /* compute log(ax) */ + s2 = s*s; + r = s2*s2*(L1+s2*(L2+s2*(L3+s2*(L4+s2*(L5+s2*L6))))); + r += s_l*(s_h+s); + s2 = s_h*s_h; + t_h = 3.0+s2+r; + SET_LOW_WORD(t_h,0); + t_l = r-((t_h-3.0)-s2); + /* u+v = s*(1+...) */ + u = s_h*t_h; + v = s_l*t_h+t_l*s; + /* 2/(3log2)*(s+...) */ + p_h = u+v; + SET_LOW_WORD(p_h,0); + p_l = v-(p_h-u); + z_h = cp_h*p_h; /* cp_h+cp_l = 2/(3*log2) */ + z_l = cp_l*p_h+p_l*cp+dp_l[k]; + /* log2(ax) = (s+..)*2/(3*log2) = n + dp_h + z_h + z_l */ + t = (double)n; + t1 = (((z_h+z_l)+dp_h[k])+t); + SET_LOW_WORD(t1,0); + t2 = z_l-(((t1-t)-dp_h[k])-z_h); + } + + s = one; /* s (sign of result -ve**odd) = -1 else = 1 */ + if(((((u_int32_t)hx>>31)-1)|(yisint-1))==0) + s = -one;/* (-ve)**(odd int) */ + + /* split up y into y1+y2 and compute (y1+y2)*(t1+t2) */ + y1 = y; + SET_LOW_WORD(y1,0); + p_l = (y-y1)*t1+y*t2; + p_h = y1*t1; + z = p_l+p_h; + EXTRACT_WORDS(j,i,z); + if (j>=0x40900000) { /* z >= 1024 */ + if(((j-0x40900000)|i)!=0) /* if z > 1024 */ + return s*huge*huge; /* overflow */ + else { + if(p_l+ovt>z-p_h) return s*huge*huge; /* overflow */ + } + } else if((j&0x7fffffff)>=0x4090cc00 ) { /* z <= -1075 */ + if(((j-0xc090cc00)|i)!=0) /* z < -1075 */ + return s*tiny*tiny; /* underflow */ + else { + if(p_l<=z-p_h) return s*tiny*tiny; /* underflow */ + } + } + /* + * compute 2**(p_h+p_l) + */ + i = j&0x7fffffff; + k = (i>>20)-0x3ff; + n = 0; + if(i>0x3fe00000) { /* if |z| > 0.5, set n = [z+0.5] */ + n = j+(0x00100000>>(k+1)); + k = ((n&0x7fffffff)>>20)-0x3ff; /* new k for n */ + t = zero; + SET_HIGH_WORD(t,n&~(0x000fffff>>k)); + n = ((n&0x000fffff)|0x00100000)>>(20-k); + if(j<0) n = -n; + p_h -= t; + } + t = p_l+p_h; + SET_LOW_WORD(t,0); + u = t*lg2_h; + v = (p_l-(t-p_h))*lg2+t*lg2_l; + z = u+v; + w = v-(z-u); + t = z*z; + t1 = z - t*(P1+t*(P2+t*(P3+t*(P4+t*P5)))); + r = (z*t1)/(t1-two)-(w+z*w); + z = one-(r-z); + GET_HIGH_WORD(j,z); + j += (n<<20); + if((j>>20)<=0) z = scalbn(z,n); /* subnormal output */ + else SET_HIGH_WORD(z,j); + return s*z; +} + +/* + * wrapper pow(x,y) return x**y + */ +#ifndef _IEEE_LIBM +double pow(double x, double y) +{ + double z = __ieee754_pow(x, y); + if (_LIB_VERSION == _IEEE_|| isnan(y)) + return z; + if (isnan(x)) { + if (y == 0.0) + return __kernel_standard(x, y, 42); /* pow(NaN,0.0) */ + return z; + } + if (x == 0.0) { + if (y == 0.0) + return __kernel_standard(x, y, 20); /* pow(0.0,0.0) */ + if (isfinite(y) && y < 0.0) + return __kernel_standard(x,y,23); /* pow(0.0,negative) */ + return z; + } + if (!isfinite(z)) { + if (isfinite(x) && isfinite(y)) { + if (isnan(z)) + return __kernel_standard(x, y, 24); /* pow neg**non-int */ + return __kernel_standard(x, y, 21); /* pow overflow */ + } + } + if (z == 0.0 && isfinite(x) && isfinite(y)) + return __kernel_standard(x, y, 22); /* pow underflow */ + return z; +} +#else +strong_alias(__ieee754_pow, pow) +#endif +libm_hidden_def(pow) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/e_rem_pio2.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/e_rem_pio2.c new file mode 100644 index 00000000..bdc4235b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/e_rem_pio2.c @@ -0,0 +1,161 @@ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* __ieee754_rem_pio2(x,y) + * + * return the remainder of x rem pi/2 in y[0]+y[1] + * use __kernel_rem_pio2() + */ + +#include "math.h" +#include "math_private.h" + +/* + * Table of constants for 2/pi, 396 Hex digits (476 decimal) of 2/pi + */ +static const int32_t two_over_pi[] = { +0xA2F983, 0x6E4E44, 0x1529FC, 0x2757D1, 0xF534DD, 0xC0DB62, +0x95993C, 0x439041, 0xFE5163, 0xABDEBB, 0xC561B7, 0x246E3A, +0x424DD2, 0xE00649, 0x2EEA09, 0xD1921C, 0xFE1DEB, 0x1CB129, +0xA73EE8, 0x8235F5, 0x2EBB44, 0x84E99C, 0x7026B4, 0x5F7E41, +0x3991D6, 0x398353, 0x39F49C, 0x845F8B, 0xBDF928, 0x3B1FF8, +0x97FFDE, 0x05980F, 0xEF2F11, 0x8B5A0A, 0x6D1F6D, 0x367ECF, +0x27CB09, 0xB74F46, 0x3F669E, 0x5FEA2D, 0x7527BA, 0xC7EBE5, +0xF17B3D, 0x0739F7, 0x8A5292, 0xEA6BFB, 0x5FB11F, 0x8D5D08, +0x560330, 0x46FC7B, 0x6BABF0, 0xCFBC20, 0x9AF436, 0x1DA9E3, +0x91615E, 0xE61B08, 0x659985, 0x5F14A0, 0x68408D, 0xFFD880, +0x4D7327, 0x310606, 0x1556CA, 0x73A8C9, 0x60E27B, 0xC08C6B, +}; + +static const int32_t npio2_hw[] = { +0x3FF921FB, 0x400921FB, 0x4012D97C, 0x401921FB, 0x401F6A7A, 0x4022D97C, +0x4025FDBB, 0x402921FB, 0x402C463A, 0x402F6A7A, 0x4031475C, 0x4032D97C, +0x40346B9C, 0x4035FDBB, 0x40378FDB, 0x403921FB, 0x403AB41B, 0x403C463A, +0x403DD85A, 0x403F6A7A, 0x40407E4C, 0x4041475C, 0x4042106C, 0x4042D97C, +0x4043A28C, 0x40446B9C, 0x404534AC, 0x4045FDBB, 0x4046C6CB, 0x40478FDB, +0x404858EB, 0x404921FB, +}; + +/* + * invpio2: 53 bits of 2/pi + * pio2_1: first 33 bit of pi/2 + * pio2_1t: pi/2 - pio2_1 + * pio2_2: second 33 bit of pi/2 + * pio2_2t: pi/2 - (pio2_1+pio2_2) + * pio2_3: third 33 bit of pi/2 + * pio2_3t: pi/2 - (pio2_1+pio2_2+pio2_3) + */ + +static const double +zero = 0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */ +half = 5.00000000000000000000e-01, /* 0x3FE00000, 0x00000000 */ +two24 = 1.67772160000000000000e+07, /* 0x41700000, 0x00000000 */ +invpio2 = 6.36619772367581382433e-01, /* 0x3FE45F30, 0x6DC9C883 */ +pio2_1 = 1.57079632673412561417e+00, /* 0x3FF921FB, 0x54400000 */ +pio2_1t = 6.07710050650619224932e-11, /* 0x3DD0B461, 0x1A626331 */ +pio2_2 = 6.07710050630396597660e-11, /* 0x3DD0B461, 0x1A600000 */ +pio2_2t = 2.02226624879595063154e-21, /* 0x3BA3198A, 0x2E037073 */ +pio2_3 = 2.02226624871116645580e-21, /* 0x3BA3198A, 0x2E000000 */ +pio2_3t = 8.47842766036889956997e-32; /* 0x397B839A, 0x252049C1 */ + +int32_t attribute_hidden __ieee754_rem_pio2(double x, double *y) +{ + double z=0.0,w,t,r,fn; + double tx[3]; + int32_t e0,i,j,nx,n,ix,hx; + u_int32_t low; + + GET_HIGH_WORD(hx,x); /* high word of x */ + ix = hx&0x7fffffff; + if(ix<=0x3fe921fb) /* |x| ~<= pi/4 , no need for reduction */ + {y[0] = x; y[1] = 0; return 0;} + if(ix<0x4002d97c) { /* |x| < 3pi/4, special case with n=+-1 */ + if(hx>0) { + z = x - pio2_1; + if(ix!=0x3ff921fb) { /* 33+53 bit pi is good enough */ + y[0] = z - pio2_1t; + y[1] = (z-y[0])-pio2_1t; + } else { /* near pi/2, use 33+33+53 bit pi */ + z -= pio2_2; + y[0] = z - pio2_2t; + y[1] = (z-y[0])-pio2_2t; + } + return 1; + } else { /* negative x */ + z = x + pio2_1; + if(ix!=0x3ff921fb) { /* 33+53 bit pi is good enough */ + y[0] = z + pio2_1t; + y[1] = (z-y[0])+pio2_1t; + } else { /* near pi/2, use 33+33+53 bit pi */ + z += pio2_2; + y[0] = z + pio2_2t; + y[1] = (z-y[0])+pio2_2t; + } + return -1; + } + } + if(ix<=0x413921fb) { /* |x| ~<= 2^19*(pi/2), medium size */ + t = fabs(x); + n = (int32_t) (t*invpio2+half); + fn = (double)n; + r = t-fn*pio2_1; + w = fn*pio2_1t; /* 1st round good to 85 bit */ + if(n<32&&ix!=npio2_hw[n-1]) { + y[0] = r-w; /* quick check no cancellation */ + } else { + u_int32_t high; + j = ix>>20; + y[0] = r-w; + GET_HIGH_WORD(high,y[0]); + i = j-((high>>20)&0x7ff); + if(i>16) { /* 2nd iteration needed, good to 118 */ + t = r; + w = fn*pio2_2; + r = t-w; + w = fn*pio2_2t-((t-r)-w); + y[0] = r-w; + GET_HIGH_WORD(high,y[0]); + i = j-((high>>20)&0x7ff); + if(i>49) { /* 3rd iteration need, 151 bits acc */ + t = r; /* will cover all possible cases */ + w = fn*pio2_3; + r = t-w; + w = fn*pio2_3t-((t-r)-w); + y[0] = r-w; + } + } + } + y[1] = (r-y[0])-w; + if(hx<0) {y[0] = -y[0]; y[1] = -y[1]; return -n;} + else return n; + } + /* + * all other (large) arguments + */ + if(ix>=0x7ff00000) { /* x is inf or NaN */ + y[0]=y[1]=x-x; return 0; + } + /* set z = scalbn(|x|,ilogb(x)-23) */ + GET_LOW_WORD(low,x); + SET_LOW_WORD(z,low); + e0 = (ix>>20)-1046; /* e0 = ilogb(z)-23; */ + SET_HIGH_WORD(z, ix - ((int32_t)(e0<<20))); + for(i=0;i<2;i++) { + tx[i] = (double)((int32_t)(z)); + z = (z-tx[i])*two24; + } + tx[2] = z; + nx = 3; + while(tx[nx-1]==zero) nx--; /* skip zero term */ + n = __kernel_rem_pio2(tx,y,e0,nx,2,two_over_pi); + if(hx<0) {y[0] = -y[0]; y[1] = -y[1]; return -n;} + return n; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/e_remainder.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/e_remainder.c new file mode 100644 index 00000000..3d5ca772 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/e_remainder.c @@ -0,0 +1,85 @@ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* __ieee754_remainder(x,p) + * Return : + * returns x REM p = x - [x/p]*p as if in infinite + * precise arithmetic, where [x/p] is the (infinite bit) + * integer nearest x/p (in half way case choose the even one). + * Method : + * Based on fmod() return x-[x/p]chopped*p exactlp. + */ + +#include "math.h" +#include "math_private.h" + +static const double zero = 0.0; + +double attribute_hidden __ieee754_remainder(double x, double p) +{ + int32_t hx,hp; + u_int32_t sx,lx,lp; + double p_half; + + EXTRACT_WORDS(hx,lx,x); + EXTRACT_WORDS(hp,lp,p); + sx = hx&0x80000000; + hp &= 0x7fffffff; + hx &= 0x7fffffff; + + /* purge off exception values */ + if((hp|lp)==0) return (x*p)/(x*p); /* p = 0 */ + if((hx>=0x7ff00000)|| /* x not finite */ + ((hp>=0x7ff00000)&& /* p is NaN */ + (((hp-0x7ff00000)|lp)!=0))) + return (x*p)/(x*p); + + + if (hp<=0x7fdfffff) x = __ieee754_fmod(x,p+p); /* now x < 2p */ + if (((hx-hp)|(lx-lp))==0) return zero*x; + x = fabs(x); + p = fabs(p); + if (hp<0x00200000) { + if(x+x>p) { + x-=p; + if(x+x>=p) x -= p; + } + } else { + p_half = 0.5*p; + if(x>p_half) { + x-=p; + if(x>=p_half) x -= p; + } + } + GET_HIGH_WORD(hx,x); + SET_HIGH_WORD(x,hx^sx); + return x; +} + +/* + * wrapper remainder(x,p) + */ +#ifndef _IEEE_LIBM +double remainder(double x, double y) +{ + double z = __ieee754_remainder(x, y); + if (_LIB_VERSION == _IEEE_ || isnan(y)) + return z; + if (y == 0.0) + return __kernel_standard(x, y, 28); /* remainder(x,0) */ + return z; +} +strong_alias(remainder, drem) +#else +strong_alias(__ieee754_remainder, remainder) +strong_alias(__ieee754_remainder, drem) +#endif +libm_hidden_def(remainder) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/e_scalb.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/e_scalb.c new file mode 100644 index 00000000..3fd78a1c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/e_scalb.c @@ -0,0 +1,59 @@ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* + * __ieee754_scalb(x, fn) is provided for + * passing various standard test suites. + * One should use scalbn() instead. + */ + +#include "math.h" +#include "math_private.h" +#include + +double attribute_hidden __ieee754_scalb(double x, double fn) +{ + if (isnan(x)||isnan(fn)) return x*fn; + if (!isfinite(fn)) { + if(fn>0.0) return x*fn; + else return x/(-fn); + } + if (rint(fn)!=fn) return (fn-fn)/(fn-fn); + if ( fn > 65000.0) return scalbn(x, 65000); + if (-fn > 65000.0) return scalbn(x,-65000); + return scalbn(x,(int)fn); +} + +#if defined __UCLIBC_SUSV3_LEGACY__ +/* + * wrapper scalb(double x, double fn) is provided for + * passing various standard test suites. + * One should use scalbn() instead. + */ +#ifndef _IEEE_LIBM +double scalb(double x, double fn) +{ + double z = __ieee754_scalb(x, fn); + if (_LIB_VERSION == _IEEE_) + return z; + if (!(isfinite(z) || isnan(z)) && isfinite(x)) + return __kernel_standard(x, (double)fn, 32); /* scalb overflow */ + if (z == 0.0 && z != x) + return __kernel_standard(x, (double)fn, 33); /* scalb underflow */ + if (!isfinite(fn)) + errno = ERANGE; + return z; +} +#else +strong_alias(__ieee754_scalb, scalb) +#endif + +#endif /* UCLIBC_SUSV3_LEGACY */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/e_sinh.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/e_sinh.c new file mode 100644 index 00000000..972307e6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/e_sinh.c @@ -0,0 +1,90 @@ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* __ieee754_sinh(x) + * Method : + * mathematically sinh(x) if defined to be (exp(x)-exp(-x))/2 + * 1. Replace x by |x| (sinh(-x) = -sinh(x)). + * 2. + * E + E/(E+1) + * 0 <= x <= 22 : sinh(x) := --------------, E=expm1(x) + * 2 + * + * 22 <= x <= lnovft : sinh(x) := exp(x)/2 + * lnovft <= x <= ln2ovft: sinh(x) := exp(x/2)/2 * exp(x/2) + * ln2ovft < x : sinh(x) := x*shuge (overflow) + * + * Special cases: + * sinh(x) is |x| if x is +INF, -INF, or NaN. + * only sinh(0)=0 is exact for finite x. + */ + +#include "math.h" +#include "math_private.h" + +static const double one = 1.0, shuge = 1.0e307; + +double attribute_hidden __ieee754_sinh(double x) +{ + double t,w,h; + int32_t ix,jx; + u_int32_t lx; + + /* High word of |x|. */ + GET_HIGH_WORD(jx,x); + ix = jx&0x7fffffff; + + /* x is INF or NaN */ + if(ix>=0x7ff00000) return x+x; + + h = 0.5; + if (jx<0) h = -h; + /* |x| in [0,22], return sign(x)*0.5*(E+E/(E+1))) */ + if (ix < 0x40360000) { /* |x|<22 */ + if (ix<0x3e300000) /* |x|<2**-28 */ + if(shuge+x>one) return x;/* sinh(tiny) = tiny with inexact */ + t = expm1(fabs(x)); + if(ix<0x3ff00000) return h*(2.0*t-t*t/(t+one)); + return h*(t+t/(t+one)); + } + + /* |x| in [22, log(maxdouble)] return 0.5*exp(|x|) */ + if (ix < 0x40862E42) return h*__ieee754_exp(fabs(x)); + + /* |x| in [log(maxdouble), overflowthresold] */ + GET_LOW_WORD(lx,x); + if (ix<0x408633CE || ((ix==0x408633ce)&&(lx<=(u_int32_t)0x8fb9f87d))) { + w = __ieee754_exp(0.5*fabs(x)); + t = h*w; + return t*w; + } + + /* |x| > overflowthresold, sinh(x) overflow */ + return x*shuge; +} + +/* + * wrapper sinh(x) + */ +#ifndef _IEEE_LIBM +double sinh(double x) +{ + double z = __ieee754_sinh(x); + if (_LIB_VERSION == _IEEE_) + return z; + if (!isfinite(z) && isfinite(x)) + return __kernel_standard(x, x, 25); /* sinh overflow */ + return z; +} +#else +strong_alias(__ieee754_sinh, sinh) +#endif +libm_hidden_def(sinh) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/e_sqrt.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/e_sqrt.c new file mode 100644 index 00000000..05e255c2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/e_sqrt.c @@ -0,0 +1,457 @@ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* __ieee754_sqrt(x) + * Return correctly rounded sqrt. + * ------------------------------------------ + * | Use the hardware sqrt if you have one | + * ------------------------------------------ + * Method: + * Bit by bit method using integer arithmetic. (Slow, but portable) + * 1. Normalization + * Scale x to y in [1,4) with even powers of 2: + * find an integer k such that 1 <= (y=x*2^(2k)) < 4, then + * sqrt(x) = 2^k * sqrt(y) + * 2. Bit by bit computation + * Let q = sqrt(y) truncated to i bit after binary point (q = 1), + * i 0 + * i+1 2 + * s = 2*q , and y = 2 * ( y - q ). (1) + * i i i i + * + * To compute q from q , one checks whether + * i+1 i + * + * -(i+1) 2 + * (q + 2 ) <= y. (2) + * i + * -(i+1) + * If (2) is false, then q = q ; otherwise q = q + 2 . + * i+1 i i+1 i + * + * With some algebric manipulation, it is not difficult to see + * that (2) is equivalent to + * -(i+1) + * s + 2 <= y (3) + * i i + * + * The advantage of (3) is that s and y can be computed by + * i i + * the following recurrence formula: + * if (3) is false + * + * s = s , y = y ; (4) + * i+1 i i+1 i + * + * otherwise, + * -i -(i+1) + * s = s + 2 , y = y - s - 2 (5) + * i+1 i i+1 i i + * + * One may easily use induction to prove (4) and (5). + * Note. Since the left hand side of (3) contain only i+2 bits, + * it does not necessary to do a full (53-bit) comparison + * in (3). + * 3. Final rounding + * After generating the 53 bits result, we compute one more bit. + * Together with the remainder, we can decide whether the + * result is exact, bigger than 1/2ulp, or less than 1/2ulp + * (it will never equal to 1/2ulp). + * The rounding mode can be detected by checking whether + * huge + tiny is equal to huge, and whether huge - tiny is + * equal to huge for some floating point number "huge" and "tiny". + * + * Special cases: + * sqrt(+-0) = +-0 ... exact + * sqrt(inf) = inf + * sqrt(-ve) = NaN ... with invalid signal + * sqrt(NaN) = NaN ... with invalid signal for signaling NaN + * + * Other methods : see the appended file at the end of the program below. + *--------------- + */ + +#include "math.h" +#include "math_private.h" + +static const double one = 1.0, tiny = 1.0e-300; + +double attribute_hidden __ieee754_sqrt(double x) +{ + double z; + int32_t sign = (int)0x80000000; + int32_t ix0,s0,q,m,t,i; + u_int32_t r,t1,s1,ix1,q1; + + EXTRACT_WORDS(ix0,ix1,x); + + /* take care of Inf and NaN */ + if((ix0&0x7ff00000)==0x7ff00000) { + return x*x+x; /* sqrt(NaN)=NaN, sqrt(+inf)=+inf + sqrt(-inf)=sNaN */ + } + /* take care of zero */ + if(ix0<=0) { + if(((ix0&(~sign))|ix1)==0) return x;/* sqrt(+-0) = +-0 */ + else if(ix0<0) + return (x-x)/(x-x); /* sqrt(-ve) = sNaN */ + } + /* normalize x */ + m = (ix0>>20); + if(m==0) { /* subnormal x */ + while(ix0==0) { + m -= 21; + ix0 |= (ix1>>11); ix1 <<= 21; + } + for(i=0;(ix0&0x00100000)==0;i++) ix0<<=1; + m -= i-1; + ix0 |= (ix1>>(32-i)); + ix1 <<= i; + } + m -= 1023; /* unbias exponent */ + ix0 = (ix0&0x000fffff)|0x00100000; + if(m&1){ /* odd m, double x to make it even */ + ix0 += ix0 + ((ix1&sign)>>31); + ix1 += ix1; + } + m >>= 1; /* m = [m/2] */ + + /* generate sqrt(x) bit by bit */ + ix0 += ix0 + ((ix1&sign)>>31); + ix1 += ix1; + q = q1 = s0 = s1 = 0; /* [q,q1] = sqrt(x) */ + r = 0x00200000; /* r = moving bit from right to left */ + + while(r!=0) { + t = s0+r; + if(t<=ix0) { + s0 = t+r; + ix0 -= t; + q += r; + } + ix0 += ix0 + ((ix1&sign)>>31); + ix1 += ix1; + r>>=1; + } + + r = sign; + while(r!=0) { + t1 = s1+r; + t = s0; + if((t>31); + ix1 += ix1; + r>>=1; + } + + /* use floating add to find out rounding direction */ + if((ix0|ix1)!=0) { + z = one-tiny; /* trigger inexact flag */ + if (z>=one) { + z = one+tiny; + if (q1==(u_int32_t)0xffffffff) { q1=0; q += 1;} + else if (z>one) { + if (q1==(u_int32_t)0xfffffffe) q+=1; + q1+=2; + } else + q1 += (q1&1); + } + } + ix0 = (q>>1)+0x3fe00000; + ix1 = q1>>1; + if ((q&1)==1) ix1 |= sign; + ix0 += (m <<20); + INSERT_WORDS(z,ix0,ix1); + return z; +} + +/* + * wrapper sqrt(x) + */ +#ifndef _IEEE_LIBM +double sqrt(double x) +{ + double z = __ieee754_sqrt(x); + if (_LIB_VERSION == _IEEE_ || isnan(x)) + return z; + if (x < 0.0) + return __kernel_standard(x, x, 26); /* sqrt(negative) */ + return z; +} +#else +strong_alias(__ieee754_sqrt, sqrt) +#endif +libm_hidden_def(sqrt) + + +/* +Other methods (use floating-point arithmetic) +------------- +(This is a copy of a drafted paper by Prof W. Kahan +and K.C. Ng, written in May, 1986) + + Two algorithms are given here to implement sqrt(x) + (IEEE double precision arithmetic) in software. + Both supply sqrt(x) correctly rounded. The first algorithm (in + Section A) uses newton iterations and involves four divisions. + The second one uses reciproot iterations to avoid division, but + requires more multiplications. Both algorithms need the ability + to chop results of arithmetic operations instead of round them, + and the INEXACT flag to indicate when an arithmetic operation + is executed exactly with no roundoff error, all part of the + standard (IEEE 754-1985). The ability to perform shift, add, + subtract and logical AND operations upon 32-bit words is needed + too, though not part of the standard. + +A. sqrt(x) by Newton Iteration + + (1) Initial approximation + + Let x0 and x1 be the leading and the trailing 32-bit words of + a floating point number x (in IEEE double format) respectively + + 1 11 52 ...widths + ------------------------------------------------------ + x: |s| e | f | + ------------------------------------------------------ + msb lsb msb lsb ...order + + + ------------------------ ------------------------ + x0: |s| e | f1 | x1: | f2 | + ------------------------ ------------------------ + + By performing shifts and subtracts on x0 and x1 (both regarded + as integers), we obtain an 8-bit approximation of sqrt(x) as + follows. + + k := (x0>>1) + 0x1ff80000; + y0 := k - T1[31&(k>>15)]. ... y ~ sqrt(x) to 8 bits + Here k is a 32-bit integer and T1[] is an integer array containing + correction terms. Now magically the floating value of y (y's + leading 32-bit word is y0, the value of its trailing word is 0) + approximates sqrt(x) to almost 8-bit. + + Value of T1: + static int T1[32]= { + 0, 1024, 3062, 5746, 9193, 13348, 18162, 23592, + 29598, 36145, 43202, 50740, 58733, 67158, 75992, 85215, + 83599, 71378, 60428, 50647, 41945, 34246, 27478, 21581, + 16499, 12183, 8588, 5674, 3403, 1742, 661, 130,}; + + (2) Iterative refinement + + Apply Heron's rule three times to y, we have y approximates + sqrt(x) to within 1 ulp (Unit in the Last Place): + + y := (y+x/y)/2 ... almost 17 sig. bits + y := (y+x/y)/2 ... almost 35 sig. bits + y := y-(y-x/y)/2 ... within 1 ulp + + + Remark 1. + Another way to improve y to within 1 ulp is: + + y := (y+x/y) ... almost 17 sig. bits to 2*sqrt(x) + y := y - 0x00100006 ... almost 18 sig. bits to sqrt(x) + + 2 + (x-y )*y + y := y + 2* ---------- ...within 1 ulp + 2 + 3y + x + + + This formula has one division fewer than the one above; however, + it requires more multiplications and additions. Also x must be + scaled in advance to avoid spurious overflow in evaluating the + expression 3y*y+x. Hence it is not recommended uless division + is slow. If division is very slow, then one should use the + reciproot algorithm given in section B. + + (3) Final adjustment + + By twiddling y's last bit it is possible to force y to be + correctly rounded according to the prevailing rounding mode + as follows. Let r and i be copies of the rounding mode and + inexact flag before entering the square root program. Also we + use the expression y+-ulp for the next representable floating + numbers (up and down) of y. Note that y+-ulp = either fixed + point y+-1, or multiply y by nextafter(1,+-inf) in chopped + mode. + + I := FALSE; ... reset INEXACT flag I + R := RZ; ... set rounding mode to round-toward-zero + z := x/y; ... chopped quotient, possibly inexact + If(not I) then { ... if the quotient is exact + if(z=y) { + I := i; ... restore inexact flag + R := r; ... restore rounded mode + return sqrt(x):=y. + } else { + z := z - ulp; ... special rounding + } + } + i := TRUE; ... sqrt(x) is inexact + If (r=RN) then z=z+ulp ... rounded-to-nearest + If (r=RP) then { ... round-toward-+inf + y = y+ulp; z=z+ulp; + } + y := y+z; ... chopped sum + y0:=y0-0x00100000; ... y := y/2 is correctly rounded. + I := i; ... restore inexact flag + R := r; ... restore rounded mode + return sqrt(x):=y. + + (4) Special cases + + Square root of +inf, +-0, or NaN is itself; + Square root of a negative number is NaN with invalid signal. + + +B. sqrt(x) by Reciproot Iteration + + (1) Initial approximation + + Let x0 and x1 be the leading and the trailing 32-bit words of + a floating point number x (in IEEE double format) respectively + (see section A). By performing shifs and subtracts on x0 and y0, + we obtain a 7.8-bit approximation of 1/sqrt(x) as follows. + + k := 0x5fe80000 - (x0>>1); + y0:= k - T2[63&(k>>14)]. ... y ~ 1/sqrt(x) to 7.8 bits + + Here k is a 32-bit integer and T2[] is an integer array + containing correction terms. Now magically the floating + value of y (y's leading 32-bit word is y0, the value of + its trailing word y1 is set to zero) approximates 1/sqrt(x) + to almost 7.8-bit. + + Value of T2: + static int T2[64]= { + 0x1500, 0x2ef8, 0x4d67, 0x6b02, 0x87be, 0xa395, 0xbe7a, 0xd866, + 0xf14a, 0x1091b,0x11fcd,0x13552,0x14999,0x15c98,0x16e34,0x17e5f, + 0x18d03,0x19a01,0x1a545,0x1ae8a,0x1b5c4,0x1bb01,0x1bfde,0x1c28d, + 0x1c2de,0x1c0db,0x1ba73,0x1b11c,0x1a4b5,0x1953d,0x18266,0x16be0, + 0x1683e,0x179d8,0x18a4d,0x19992,0x1a789,0x1b445,0x1bf61,0x1c989, + 0x1d16d,0x1d77b,0x1dddf,0x1e2ad,0x1e5bf,0x1e6e8,0x1e654,0x1e3cd, + 0x1df2a,0x1d635,0x1cb16,0x1be2c,0x1ae4e,0x19bde,0x1868e,0x16e2e, + 0x1527f,0x1334a,0x11051,0xe951, 0xbe01, 0x8e0d, 0x5924, 0x1edd,}; + + (2) Iterative refinement + + Apply Reciproot iteration three times to y and multiply the + result by x to get an approximation z that matches sqrt(x) + to about 1 ulp. To be exact, we will have + -1ulp < sqrt(x)-z<1.0625ulp. + + ... set rounding mode to Round-to-nearest + y := y*(1.5-0.5*x*y*y) ... almost 15 sig. bits to 1/sqrt(x) + y := y*((1.5-2^-30)+0.5*x*y*y)... about 29 sig. bits to 1/sqrt(x) + ... special arrangement for better accuracy + z := x*y ... 29 bits to sqrt(x), with z*y<1 + z := z + 0.5*z*(1-z*y) ... about 1 ulp to sqrt(x) + + Remark 2. The constant 1.5-2^-30 is chosen to bias the error so that + (a) the term z*y in the final iteration is always less than 1; + (b) the error in the final result is biased upward so that + -1 ulp < sqrt(x) - z < 1.0625 ulp + instead of |sqrt(x)-z|<1.03125ulp. + + (3) Final adjustment + + By twiddling y's last bit it is possible to force y to be + correctly rounded according to the prevailing rounding mode + as follows. Let r and i be copies of the rounding mode and + inexact flag before entering the square root program. Also we + use the expression y+-ulp for the next representable floating + numbers (up and down) of y. Note that y+-ulp = either fixed + point y+-1, or multiply y by nextafter(1,+-inf) in chopped + mode. + + R := RZ; ... set rounding mode to round-toward-zero + switch(r) { + case RN: ... round-to-nearest + if(x<= z*(z-ulp)...chopped) z = z - ulp; else + if(x<= z*(z+ulp)...chopped) z = z; else z = z+ulp; + break; + case RZ:case RM: ... round-to-zero or round-to--inf + R:=RP; ... reset rounding mod to round-to-+inf + if(x=(z+ulp)*(z+ulp) ...rounded up) z = z+ulp; + break; + case RP: ... round-to-+inf + if(x>(z+ulp)*(z+ulp)...chopped) z = z+2*ulp; else + if(x>z*z ...chopped) z = z+ulp; + break; + } + + Remark 3. The above comparisons can be done in fixed point. For + example, to compare x and w=z*z chopped, it suffices to compare + x1 and w1 (the trailing parts of x and w), regarding them as + two's complement integers. + + ...Is z an exact square root? + To determine whether z is an exact square root of x, let z1 be the + trailing part of z, and also let x0 and x1 be the leading and + trailing parts of x. + + If ((z1&0x03ffffff)!=0) ... not exact if trailing 26 bits of z!=0 + I := 1; ... Raise Inexact flag: z is not exact + else { + j := 1 - [(x0>>20)&1] ... j = logb(x) mod 2 + k := z1 >> 26; ... get z's 25-th and 26-th + fraction bits + I := i or (k&j) or ((k&(j+j+1))!=(x1&3)); + } + R:= r ... restore rounded mode + return sqrt(x):=z. + + If multiplication is cheaper then the foregoing red tape, the + Inexact flag can be evaluated by + + I := i; + I := (z*z!=x) or I. + + Note that z*z can overwrite I; this value must be sensed if it is + True. + + Remark 4. If z*z = x exactly, then bit 25 to bit 0 of z1 must be + zero. + + -------------------- + z1: | f2 | + -------------------- + bit 31 bit 0 + + Further more, bit 27 and 26 of z1, bit 0 and 1 of x1, and the odd + or even of logb(x) have the following relations: + + ------------------------------------------------- + bit 27,26 of z1 bit 1,0 of x1 logb(x) + ------------------------------------------------- + 00 00 odd and even + 01 01 even + 10 10 odd + 10 00 even + 11 01 even + ------------------------------------------------- + + (4) Special cases (see (4) of Section A). + + */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/float_wrappers.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/float_wrappers.c new file mode 100644 index 00000000..82b7963e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/float_wrappers.c @@ -0,0 +1,404 @@ +/* vi: set sw=4 ts=4: */ +/* + * Wrapper functions implementing all the float math functions + * defined by SuSv3 by actually calling the double version of + * each function and then casting the result back to a float + * to return to the user. + * + * Copyright (C) 2005 by Erik Andersen + * + * GNU Lesser General Public License version 2.1 or later. + */ + +#include +/* Prevent math.h from defining colliding inlines */ +#undef __USE_EXTERN_INLINES +#include +#include + + +#define WRAPPER1(func) \ +float func##f (float x) \ +{ \ + return (float) func((double)x); \ +} +#define int_WRAPPER1(func) \ +int func##f (float x) \ +{ \ + return func((double)x); \ +} +#define long_WRAPPER1(func) \ +long func##f (float x) \ +{ \ + return func((double)x); \ +} +#define long_long_WRAPPER1(func) \ +long long func##f (float x) \ +{ \ + return func((double)x); \ +} + + +/* For the time being, do _NOT_ implement these functions + * that are defined by SuSv3 [because we don't need them + * and nobody asked to include them] */ +#undef L_fdimf /*float fdimf(float, float);*/ +#undef L_fmaf /*float fmaf(float, float, float);*/ +#undef L_fmaxf /*float fmaxf(float, float);*/ +#undef L_fminf /*float fminf(float, float);*/ +#undef L_nearbyintf /*float nearbyintf(float);*/ +#undef L_nexttowardf /*float nexttowardf(float, long double);*/ +#undef L_remquof /*float remquof(float, float, int *);*/ +#undef L_scalblnf /*float scalblnf(float, long);*/ +#undef L_tgammaf /*float tgammaf(float);*/ + +/* Implement the following, as defined by SuSv3 */ +#if 0 +float acosf(float); +float acoshf(float); +float asinf(float); +float asinhf(float); +float atan2f(float, float); +float atanf(float); +float atanhf(float); +float cargf(float complex); +float cbrtf(float); +float ceilf(float); +float copysignf(float, float); +float cosf(float); +float coshf(float); +float erfcf(float); +float erff(float); +float exp2f(float); +float expf(float); +float expm1f(float); +float fabsf(float); +float floorf(float); +float fmodf(float, float); +float frexpf(float value, int *); +float hypotf(float, float); +int ilogbf(float); +float ldexpf(float, int); +float lgammaf(float); +long long llroundf(float); +float log10f(float); +float log1pf(float); +float log2f(float); +float logbf(float); +float logf(float); +long lroundf(float); +float modff(float, float *); +float powf(float, float); +float remainderf(float, float); +float rintf(float); +float roundf(float); +float scalbnf(float, int); +float sinf(float); +float sinhf(float); +float sqrtf(float); +float tanf(float); +float tanhf(float); +#endif + +#ifdef L_acosf +WRAPPER1(acos) +#endif + +#ifdef L_acoshf +WRAPPER1(acosh) +#endif + +#ifdef L_asinf +WRAPPER1(asin) +#endif + +#ifdef L_asinhf +WRAPPER1(asinh) +#endif + +#ifdef L_atan2f +float atan2f (float x, float y) +{ + return (float) atan2( (double)x, (double)y ); +} +#endif + +#ifdef L_atanf +WRAPPER1(atan) +#endif + +#ifdef L_atanhf +WRAPPER1(atanh) +#endif + +#ifdef L_cargf +float cargf (float complex x) +{ + return (float) carg( (double complex)x ); +} +#endif + +#ifdef L_cbrtf +WRAPPER1(cbrt) +#endif + +#ifdef L_ceilf +WRAPPER1(ceil) +#endif + +#ifdef L_copysignf +float copysignf (float x, float y) +{ + return (float) copysign( (double)x, (double)y ); +} +#endif + +#ifdef L_cosf +WRAPPER1(cos) +#endif + +#ifdef L_coshf +WRAPPER1(cosh) +#endif + +#ifdef L_erfcf +WRAPPER1(erfc) +#endif + +#ifdef L_erff +WRAPPER1(erf) +#endif + +#ifdef L_exp2f +WRAPPER1(exp2) +#endif + +#ifdef L_expf +WRAPPER1(exp) +#endif + +#ifdef L_expm1f +WRAPPER1(expm1) +#endif + +#ifdef L_fabsf +WRAPPER1(fabs) +#endif + +#ifdef L_fdimf +float fdimf (float x, float y) +{ + return (float) fdim( (double)x, (double)y ); +} +#endif + +#ifdef L_floorf +WRAPPER1(floor) +#endif + +#ifdef L_fmaf +float fmaf (float x, float y, float z) +{ + return (float) fma( (double)x, (double)y, (double)z ); +} +#endif + +#ifdef L_fmaxf +float fmaxf (float x, float y) +{ + return (float) fmax( (double)x, (double)y ); +} +#endif + +#ifdef L_fminf +float fminf (float x, float y) +{ + return (float) fmin( (double)x, (double)y ); +} +#endif + +#ifdef L_fmodf +float fmodf (float x, float y) +{ + return (float) fmod( (double)x, (double)y ); +} +#endif + +#ifdef L_frexpf +float frexpf (float x, int *_exp) +{ + return (float) frexp( (double)x, _exp ); +} +#endif + +#ifdef L_hypotf +float hypotf (float x, float y) +{ + return (float) hypot( (double)x, (double)y ); +} +#endif + +#ifdef L_ilogbf +int_WRAPPER1(ilogb) +#endif + +#ifdef L_ldexpf +float ldexpf (float x, int _exp) +{ + return (float) ldexp( (double)x, _exp ); +} +#endif + +#ifdef L_lgammaf +WRAPPER1(lgamma) +#endif + +#ifdef L_llrintf +long_long_WRAPPER1(llrint) +#endif + +#ifdef L_llroundf +long_long_WRAPPER1(llround) +#endif + +#ifdef L_log10f +WRAPPER1(log10) +#endif + +#ifdef L_log1pf +WRAPPER1(log1p) +#endif + +#ifdef L_log2f +WRAPPER1(log2) +#endif + +#ifdef L_logbf +WRAPPER1(logb) +#endif + +#ifdef L_logf +WRAPPER1(log) +#endif + +#ifdef L_lrintf +long_WRAPPER1(lrint) +#endif + +#ifdef L_lroundf +long_WRAPPER1(lround) +#endif + +#ifdef L_modff +float modff (float x, float *iptr) +{ + double y, result; + result = modf( x, &y ); + *iptr = (float)y; + return (float) result; +} +#endif + +#ifdef L_nearbyintf +WRAPPER1(nearbyint) +#endif + +#ifdef L_nexttowardf +float nexttowardf (float x, long double y) +{ + return (float) nexttoward( (double)x, (double)y ); +} +#endif + +#ifdef L_powf +float powf (float x, float y) +{ + return (float) pow( (double)x, (double)y ); +} +#endif + +#ifdef L_remainderf +float remainderf (float x, float y) +{ + return (float) remainder( (double)x, (double)y ); +} +#endif + +#ifdef L_remquof +float remquof (float x, float y, int *quo) +{ + return (float) remquo( (double)x, (double)y, quo ); +} +#endif + +#ifdef L_rintf +WRAPPER1(rint) +#endif + +#ifdef L_roundf +WRAPPER1(round) +#endif + +#ifdef L_scalblnf +float scalblnf (float x, long _exp) +{ + return (float) scalbln( (double)x, _exp ); +} +#endif + +#ifdef L_scalbnf +float scalbnf (float x, int _exp) +{ + return (float) scalbn( (double)x, _exp ); +} +#endif + +#ifdef L_sinf +WRAPPER1(sin) +#endif + +#ifdef L_sinhf +WRAPPER1(sinh) +#endif + +#ifdef L_sqrtf +WRAPPER1(sqrt) +#endif + +#ifdef L_tanf +WRAPPER1(tan) +#endif + +#ifdef L_tanhf +WRAPPER1(tanh) +#endif + +#ifdef L_tgammaf +WRAPPER1(tgamma) +#endif + +#ifdef L_truncf +WRAPPER1(trunc) +#endif + +#ifdef L_fmaf +float fmaf (float x, float y, float z) +{ + return (float) fma( (double)x, (double)y, (double)z ); +} +#endif + +#if defined L_scalbf && defined __UCLIBC_SUSV3_LEGACY__ +float scalbf (float x, float y) +{ + return (float) scalb( (double)x, (double)y ); +} +#endif + +#ifdef L_gammaf +WRAPPER1(gamma) +#endif + +#ifdef L_significandf +WRAPPER1(significand) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/i386/Makefile.arch b/l4/pkg/uclibc/lib/contrib/uclibc/libm/i386/Makefile.arch new file mode 100644 index 00000000..e1be961f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/i386/Makefile.arch @@ -0,0 +1,24 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# +# The routines included in this math library are derived from +# glibc's libm. +# + +ifeq ($(UCLIBC_HAS_FENV),y) +libm_ARCH_SRC:=$(wildcard $(libm_ARCH_DIR)/*.c) +libm_ARCH_OBJ:=$(patsubst $(libm_ARCH_DIR)/%.c,$(libm_ARCH_OUT)/%.o,$(libm_ARCH_SRC)) +endif + +libm_ARCH_OBJS:=$(libm_ARCH_OBJ) + +ifeq ($(DOPIC),y) +libm-a-y+=$(libm_ARCH_OBJS:.o=.os) +else +libm-a-y+=$(libm_ARCH_OBJS) +endif +libm-so-y+=$(libm_ARCH_OBJS:.o=.os) + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/i386/fclrexcpt.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/i386/fclrexcpt.c new file mode 100644 index 00000000..a34060ce --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/i386/fclrexcpt.c @@ -0,0 +1,61 @@ +/* Clear given exceptions in current floating-point environment. + Copyright (C) 1997,99,2000, 2001, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +int +feclearexcept (int excepts) +{ + fenv_t temp; + + /* Mask out unsupported bits/exceptions. */ + excepts &= FE_ALL_EXCEPT; + + /* Bah, we have to clear selected exceptions. Since there is no + `fldsw' instruction we have to do it the hard way. */ + __asm__ ("fnstenv %0" : "=m" (*&temp)); + + /* Clear the relevant bits. */ + temp.__status_word &= excepts ^ FE_ALL_EXCEPT; + + /* Put the new data in effect. */ + __asm__ ("fldenv %0" : : "m" (*&temp)); + +#if 0 + /* If the CPU supports SSE, we clear the MXCSR as well. */ + if ((GLRO(dl_hwcap) & HWCAP_I386_XMM) != 0) + { + unsigned int xnew_exc; + + /* Get the current MXCSR. */ + __asm__ ("stmxcsr %0" : "=m" (*&xnew_exc)); + + /* Clear the relevant bits. */ + xnew_exc &= ~excepts; + + /* Put the new data in effect. */ + __asm__ ("ldmxcsr %0" : : "m" (*&xnew_exc)); + } +#endif + + /* Success. */ + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/i386/fedisblxcpt.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/i386/fedisblxcpt.c new file mode 100644 index 00000000..75dc1789 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/i386/fedisblxcpt.c @@ -0,0 +1,55 @@ +/* Disable floating-point exceptions. + Copyright (C) 1999, 2000, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Andreas Jaeger , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +int +fedisableexcept (int excepts) +{ + unsigned short int new_exc, old_exc; + + /* Get the current control word. */ + __asm__ ("fstcw %0" : "=m" (*&new_exc)); + + old_exc = (~new_exc) & FE_ALL_EXCEPT; + + excepts &= FE_ALL_EXCEPT; + + new_exc |= excepts; + __asm__ ("fldcw %0" : : "m" (*&new_exc)); + +#if 0 + /* If the CPU supports SSE we set the MXCSR as well. */ + if ((GLRO(dl_hwcap) & HWCAP_I386_XMM) != 0) + { + unsigned int xnew_exc; + + /* Get the current control word. */ + __asm__ ("stmxcsr %0" : "=m" (*&xnew_exc)); + + xnew_exc |= excepts << 7; + + __asm__ ("ldmxcsr %0" : : "m" (*&xnew_exc)); + } +#endif + + return old_exc; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/i386/feenablxcpt.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/i386/feenablxcpt.c new file mode 100644 index 00000000..174f9f1a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/i386/feenablxcpt.c @@ -0,0 +1,55 @@ +/* Enable floating-point exceptions. + Copyright (C) 1999, 2000, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Andreas Jaeger , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +int +feenableexcept (int excepts) +{ + unsigned short int new_exc; + unsigned short int old_exc; + + /* Get the current control word. */ + __asm__ ("fstcw %0" : "=m" (*&new_exc)); + + excepts &= FE_ALL_EXCEPT; + old_exc = (~new_exc) & FE_ALL_EXCEPT; + + new_exc &= ~excepts; + __asm__ ("fldcw %0" : : "m" (*&new_exc)); + +#if 0 + /* If the CPU supports SSE we set the MXCSR as well. */ + if ((GLRO(dl_hwcap) & HWCAP_I386_XMM) != 0) + { + unsigned int xnew_exc; + + /* Get the current control word. */ + __asm__ ("stmxcsr %0" : "=m" (*&xnew_exc)); + + xnew_exc &= ~(excepts << 7); + + __asm__ ("ldmxcsr %0" : : "m" (*&xnew_exc)); + } +#endif + + return old_exc; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/i386/fegetenv.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/i386/fegetenv.c new file mode 100644 index 00000000..abbf179e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/i386/fegetenv.c @@ -0,0 +1,34 @@ +/* Store current floating-point environment. + Copyright (C) 1997,1999,2000,2001,2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +int +fegetenv (fenv_t *envp) +{ + __asm__ ("fnstenv %0" : "=m" (*envp)); + /* And load it right back since the processor changes the mask. + Intel thought this opcode to be used in interrupt handlers which + would block all exceptions. */ + __asm__ ("fldenv %0" : : "m" (*envp)); + + /* Success. */ + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/i386/fegetexcept.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/i386/fegetexcept.c new file mode 100644 index 00000000..71bac788 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/i386/fegetexcept.c @@ -0,0 +1,32 @@ +/* Get enabled floating-point exceptions. + Copyright (C) 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Andreas Jaeger , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +int +fegetexcept (void) +{ + unsigned short int exc; + + /* Get the current control word. */ + __asm__ ("fstcw %0" : "=m" (*&exc)); + + return (~exc) & FE_ALL_EXCEPT; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/i386/fegetround.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/i386/fegetround.c new file mode 100644 index 00000000..8ae0c3af --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/i386/fegetround.c @@ -0,0 +1,31 @@ +/* Return current rounding direction. + Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +int +fegetround (void) +{ + int cw; + + __asm__ ("fnstcw %0" : "=m" (*&cw)); + + return cw & 0xc00; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/i386/feholdexcpt.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/i386/feholdexcpt.c new file mode 100644 index 00000000..d283e9e4 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/i386/feholdexcpt.c @@ -0,0 +1,59 @@ +/* Store current floating-point environment and clear exceptions. + Copyright (C) 1997, 1999, 2003, 2004, 2005, 2007 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +int +feholdexcept (fenv_t *envp) +{ + fenv_t temp; + + /* Store the environment. */ + __asm__ ("fnstenv %0" : "=m" (temp)); + *envp = temp; + + /* Now set all exceptions to non-stop. */ + temp.__control_word |= 0x3f; + + /* And clear all exceptions. */ + temp.__status_word &= ~0x3f; + + __asm__ ("fldenv %0" : : "m" (temp)); + +#if 0 + /* If the CPU supports SSE we set the MXCSR as well. */ + if ((GLRO(dl_hwcap) & HWCAP_I386_XMM) != 0) + { + unsigned int xwork; + + /* Get the current control word. */ + __asm__ ("stmxcsr %0" : "=m" (*&xwork)); + + /* Set all exceptions to non-stop and clear them. */ + xwork = (xwork | 0x1f80) & ~0x3f; + + __asm__ ("ldmxcsr %0" : : "m" (*&xwork)); + } +#endif + + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/i386/fesetenv.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/i386/fesetenv.c new file mode 100644 index 00000000..fdb4fcc9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/i386/fesetenv.c @@ -0,0 +1,80 @@ +/* Install given floating-point environment. + Copyright (C) 1997,98,99,2000,01,02 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +libm_hidden_proto(fesetenv) + +int +fesetenv (const fenv_t *envp) +{ + fenv_t temp; + + /* The memory block used by fstenv/fldenv has a size of 28 bytes. */ + assert (sizeof (fenv_t) == 28); + + /* Install the environment specified by ENVP. But there are a few + values which we do not want to come from the saved environment. + Therefore, we get the current environment and replace the values + we want to use from the environment specified by the parameter. */ + __asm__ ("fnstenv %0" : "=m" (*&temp)); + + if (envp == FE_DFL_ENV) + { + temp.__control_word |= FE_ALL_EXCEPT; + temp.__control_word &= ~FE_TOWARDZERO; + temp.__status_word &= ~FE_ALL_EXCEPT; + temp.__eip = 0; + temp.__cs_selector = 0; + temp.__opcode = 0; + temp.__data_offset = 0; + temp.__data_selector = 0; + } + else if (envp == FE_NOMASK_ENV) + { + temp.__control_word &= ~(FE_ALL_EXCEPT | FE_TOWARDZERO); + temp.__status_word &= ~FE_ALL_EXCEPT; + temp.__eip = 0; + temp.__cs_selector = 0; + temp.__opcode = 0; + temp.__data_offset = 0; + temp.__data_selector = 0; + } + else + { + temp.__control_word &= ~(FE_ALL_EXCEPT | FE_TOWARDZERO); + temp.__control_word |= (envp->__control_word + & (FE_ALL_EXCEPT | FE_TOWARDZERO)); + temp.__status_word &= ~FE_ALL_EXCEPT; + temp.__status_word |= envp->__status_word & FE_ALL_EXCEPT; + temp.__eip = envp->__eip; + temp.__cs_selector = envp->__cs_selector; + temp.__opcode = envp->__opcode; + temp.__data_offset = envp->__data_offset; + temp.__data_selector = envp->__data_selector; + } + + __asm__ ("fldenv %0" : : "m" (temp)); + + /* Success. */ + return 0; +} +libm_hidden_def(fesetenv) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/i386/fesetround.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/i386/fesetround.c new file mode 100644 index 00000000..e1ba1697 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/i386/fesetround.c @@ -0,0 +1,52 @@ +/* Set current rounding direction. + Copyright (C) 1997, 2003, 2004, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +int +fesetround (int round) +{ + unsigned short int cw; + + if ((round & ~0xc00) != 0) + /* ROUND is no valid rounding mode. */ + return 1; + + __asm__ ("fnstcw %0" : "=m" (*&cw)); + cw &= ~0xc00; + cw |= round; + __asm__ ("fldcw %0" : : "m" (*&cw)); + +#if 0 + /* If the CPU supports SSE we set the MXCSR as well. */ + if ((GLRO(dl_hwcap) & HWCAP_I386_XMM) != 0) + { + unsigned int xcw; + + __asm__ ("stmxcsr %0" : "=m" (*&xcw)); + xcw &= ~0x6000; + xcw |= round << 3; + __asm__ ("ldmxcsr %0" : : "m" (*&xcw)); + } +#endif + + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/i386/feupdateenv.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/i386/feupdateenv.c new file mode 100644 index 00000000..91b535dc --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/i386/feupdateenv.c @@ -0,0 +1,56 @@ +/* Install given floating-point environment and raise exceptions. + Copyright (C) 1997,99,2000,01,07 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +libm_hidden_proto(fesetenv) +libm_hidden_proto(feraiseexcept) + +int +feupdateenv (const fenv_t *envp) +{ + fexcept_t temp; + /* unsigned int xtemp = 0; */ + + /* Save current exceptions. */ + __asm__ ("fnstsw %0" : "=m" (*&temp)); + +#if 0 + /* If the CPU supports SSE we test the MXCSR as well. */ + if ((GLRO(dl_hwcap) & HWCAP_I386_XMM) != 0) + __asm__ ("stmxcsr %0" : "=m" (*&xtemp)); + + temp = (temp | xtemp) & FE_ALL_EXCEPT; +#else + temp &= FE_ALL_EXCEPT; +#endif + + /* Install new environment. */ + fesetenv (envp); + + /* Raise the saved exception. Incidently for us the implementation + defined format of the values in objects of type fexcept_t is the + same as the ones specified using the FE_* constants. */ + feraiseexcept ((int) temp); + + /* Success. */ + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/i386/fgetexcptflg.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/i386/fgetexcptflg.c new file mode 100644 index 00000000..f9912261 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/i386/fgetexcptflg.c @@ -0,0 +1,35 @@ +/* Store current representation for exceptions. + Copyright (C) 1997,99,2000,01 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +int +fegetexceptflag (fexcept_t *flagp, int excepts) +{ + fexcept_t temp; + + /* Get the current exceptions. */ + __asm__ ("fnstsw %0" : "=m" (*&temp)); + + *flagp = temp & excepts & FE_ALL_EXCEPT; + + /* Success. */ + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/i386/fraiseexcpt.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/i386/fraiseexcpt.c new file mode 100644 index 00000000..fcb3d0e8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/i386/fraiseexcpt.c @@ -0,0 +1,118 @@ +/* Raise given exceptions. + Copyright (C) 1997,99,2000,01,02 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +libm_hidden_proto(feraiseexcept) + +int +feraiseexcept (int excepts) +{ + /* Raise exceptions represented by EXPECTS. But we must raise only + one signal at a time. It is important that if the overflow/underflow + exception and the inexact exception are given at the same time, + the overflow/underflow exception follows the inexact exception. */ + + /* First: invalid exception. */ + if ((FE_INVALID & excepts) != 0) + { + /* One example of a invalid operation is 0.0 / 0.0. */ + double d; + __asm__ __volatile__ ("fldz; fdiv %%st, %%st(0); fwait" : "=t" (d)); + (void) &d; + } + + /* Next: division by zero. */ + if ((FE_DIVBYZERO & excepts) != 0) + { + double d; + __asm__ __volatile__ ("fldz; fld1; fdivp %%st, %%st(1); fwait" + : "=t" (d)); + (void) &d; + } + + /* Next: overflow. */ + if ((FE_OVERFLOW & excepts) != 0) + { + /* There is no way to raise only the overflow flag. Do it the + hard way. */ + fenv_t temp; + + /* Bah, we have to clear selected exceptions. Since there is no + `fldsw' instruction we have to do it the hard way. */ + __asm__ __volatile__ ("fnstenv %0" : "=m" (*&temp)); + + /* Set the relevant bits. */ + temp.__status_word |= FE_OVERFLOW; + + /* Put the new data in effect. */ + __asm__ __volatile__ ("fldenv %0" : : "m" (*&temp)); + + /* And raise the exception. */ + __asm__ __volatile__ ("fwait"); + } + + /* Next: underflow. */ + if ((FE_UNDERFLOW & excepts) != 0) + { + /* There is no way to raise only the underflow flag. Do it the + hard way. */ + fenv_t temp; + + /* Bah, we have to clear selected exceptions. Since there is no + `fldsw' instruction we have to do it the hard way. */ + __asm__ __volatile__ ("fnstenv %0" : "=m" (*&temp)); + + /* Set the relevant bits. */ + temp.__status_word |= FE_UNDERFLOW; + + /* Put the new data in effect. */ + __asm__ __volatile__ ("fldenv %0" : : "m" (*&temp)); + + /* And raise the exception. */ + __asm__ __volatile__ ("fwait"); + } + + /* Last: inexact. */ + if ((FE_INEXACT & excepts) != 0) + { + /* There is no way to raise only the inexact flag. Do it the + hard way. */ + fenv_t temp; + + /* Bah, we have to clear selected exceptions. Since there is no + `fldsw' instruction we have to do it the hard way. */ + __asm__ __volatile__ ("fnstenv %0" : "=m" (*&temp)); + + /* Set the relevant bits. */ + temp.__status_word |= FE_INEXACT; + + /* Put the new data in effect. */ + __asm__ __volatile__ ("fldenv %0" : : "m" (*&temp)); + + /* And raise the exception. */ + __asm__ __volatile__ ("fwait"); + } + + /* Success. */ + return 0; +} +libm_hidden_def(feraiseexcept) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/i386/fsetexcptflg.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/i386/fsetexcptflg.c new file mode 100644 index 00000000..bdd1dcca --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/i386/fsetexcptflg.c @@ -0,0 +1,62 @@ +/* Set floating-point environment exception handling. + Copyright (C) 1997,99,2000,01, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +int +fesetexceptflag (const fexcept_t *flagp, int excepts) +{ + fenv_t temp; + + /* Get the current environment. We have to do this since we cannot + separately set the status word. */ + __asm__ ("fnstenv %0" : "=m" (*&temp)); + + temp.__status_word &= ~(excepts & FE_ALL_EXCEPT); + temp.__status_word |= *flagp & excepts & FE_ALL_EXCEPT; + + /* Store the new status word (along with the rest of the environment. + Possibly new exceptions are set but they won't get executed unless + the next floating-point instruction. */ + __asm__ ("fldenv %0" : : "m" (*&temp)); + +#if 0 + /* If the CPU supports SSE, we set the MXCSR as well. */ + if ((GLRO(dl_hwcap) & HWCAP_I386_XMM) != 0) + { + unsigned int xnew_exc; + + /* Get the current MXCSR. */ + __asm__ ("stmxcsr %0" : "=m" (*&xnew_exc)); + + /* Set the relevant bits. */ + xnew_exc &= ~(excepts & FE_ALL_EXCEPT); + xnew_exc |= *flagp & excepts & FE_ALL_EXCEPT; + + /* Put the new data in effect. */ + __asm__ ("ldmxcsr %0" : : "m" (*&xnew_exc)); + } +#endif + + /* Success. */ + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/i386/ftestexcept.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/i386/ftestexcept.c new file mode 100644 index 00000000..f45beced --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/i386/ftestexcept.c @@ -0,0 +1,40 @@ +/* Test exception in current environment. + Copyright (C) 1997, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +int +fetestexcept (int excepts) +{ + short temp; + int xtemp = 0; + + /* Get current exceptions. */ + __asm__ ("fnstsw %0" : "=a" (temp)); + +#if 0 + /* If the CPU supports SSE we test the MXCSR as well. */ + if ((GLRO(dl_hwcap) & HWCAP_I386_XMM) != 0) + __asm__ ("stmxcsr %0" : "=m" (*&xtemp)); +#endif + + return (temp | xtemp) & excepts & FE_ALL_EXCEPT; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/k_cos.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/k_cos.c new file mode 100644 index 00000000..ededf253 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/k_cos.c @@ -0,0 +1,82 @@ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* + * __kernel_cos( x, y ) + * kernel cos function on [-pi/4, pi/4], pi/4 ~ 0.785398164 + * Input x is assumed to be bounded by ~pi/4 in magnitude. + * Input y is the tail of x. + * + * Algorithm + * 1. Since cos(-x) = cos(x), we need only to consider positive x. + * 2. if x < 2^-27 (hx<0x3e400000 0), return 1 with inexact if x!=0. + * 3. cos(x) is approximated by a polynomial of degree 14 on + * [0,pi/4] + * 4 14 + * cos(x) ~ 1 - x*x/2 + C1*x + ... + C6*x + * where the remez error is + * + * | 2 4 6 8 10 12 14 | -58 + * |cos(x)-(1-.5*x +C1*x +C2*x +C3*x +C4*x +C5*x +C6*x )| <= 2 + * | | + * + * 4 6 8 10 12 14 + * 4. let r = C1*x +C2*x +C3*x +C4*x +C5*x +C6*x , then + * cos(x) = 1 - x*x/2 + r + * since cos(x+y) ~ cos(x) - sin(x)*y + * ~ cos(x) - x*y, + * a correction term is necessary in cos(x) and hence + * cos(x+y) = 1 - (x*x/2 - (r - x*y)) + * For better accuracy when x > 0.3, let qx = |x|/4 with + * the last 32 bits mask off, and if x > 0.78125, let qx = 0.28125. + * Then + * cos(x+y) = (1-qx) - ((x*x/2-qx) - (r-x*y)). + * Note that 1-qx and (x*x/2-qx) is EXACT here, and the + * magnitude of the latter is at least a quarter of x*x/2, + * thus, reducing the rounding error in the subtraction. + */ + +#include "math.h" +#include "math_private.h" + +static const double +one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */ +C1 = 4.16666666666666019037e-02, /* 0x3FA55555, 0x5555554C */ +C2 = -1.38888888888741095749e-03, /* 0xBF56C16C, 0x16C15177 */ +C3 = 2.48015872894767294178e-05, /* 0x3EFA01A0, 0x19CB1590 */ +C4 = -2.75573143513906633035e-07, /* 0xBE927E4F, 0x809C52AD */ +C5 = 2.08757232129817482790e-09, /* 0x3E21EE9E, 0xBDB4B1C4 */ +C6 = -1.13596475577881948265e-11; /* 0xBDA8FAE9, 0xBE8838D4 */ + +double attribute_hidden __kernel_cos(double x, double y) +{ + double a,hz,z,r,qx; + int32_t ix; + GET_HIGH_WORD(ix,x); + ix &= 0x7fffffff; /* ix = |x|'s high word*/ + if(ix<0x3e400000) { /* if x < 2**27 */ + if(((int)x)==0) return one; /* generate inexact */ + } + z = x*x; + r = z*(C1+z*(C2+z*(C3+z*(C4+z*(C5+z*C6))))); + if(ix < 0x3FD33333) /* if |x| < 0.3 */ + return one - (0.5*z - (z*r - x*y)); + else { + if(ix > 0x3fe90000) { /* x > 0.78125 */ + qx = 0.28125; + } else { + INSERT_WORDS(qx,ix-0x00200000,0); /* x/4 */ + } + hz = 0.5*z-qx; + a = one-qx; + return a - (hz - (z*r-x*y)); + } +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/k_rem_pio2.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/k_rem_pio2.c new file mode 100644 index 00000000..e34b2c8d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/k_rem_pio2.c @@ -0,0 +1,298 @@ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* + * __kernel_rem_pio2(x,y,e0,nx,prec,ipio2) + * double x[],y[]; int e0,nx,prec; int ipio2[]; + * + * __kernel_rem_pio2 return the last three digits of N with + * y = x - N*pi/2 + * so that |y| < pi/2. + * + * The method is to compute the integer (mod 8) and fraction parts of + * (2/pi)*x without doing the full multiplication. In general we + * skip the part of the product that are known to be a huge integer ( + * more accurately, = 0 mod 8 ). Thus the number of operations are + * independent of the exponent of the input. + * + * (2/pi) is represented by an array of 24-bit integers in ipio2[]. + * + * Input parameters: + * x[] The input value (must be positive) is broken into nx + * pieces of 24-bit integers in double precision format. + * x[i] will be the i-th 24 bit of x. The scaled exponent + * of x[0] is given in input parameter e0 (i.e., x[0]*2^e0 + * match x's up to 24 bits. + * + * Example of breaking a double positive z into x[0]+x[1]+x[2]: + * e0 = ilogb(z)-23 + * z = scalbn(z,-e0) + * for i = 0,1,2 + * x[i] = floor(z) + * z = (z-x[i])*2**24 + * + * + * y[] ouput result in an array of double precision numbers. + * The dimension of y[] is: + * 24-bit precision 1 + * 53-bit precision 2 + * 64-bit precision 2 + * 113-bit precision 3 + * The actual value is the sum of them. Thus for 113-bit + * precison, one may have to do something like: + * + * long double t,w,r_head, r_tail; + * t = (long double)y[2] + (long double)y[1]; + * w = (long double)y[0]; + * r_head = t+w; + * r_tail = w - (r_head - t); + * + * e0 The exponent of x[0] + * + * nx dimension of x[] + * + * prec an integer indicating the precision: + * 0 24 bits (single) + * 1 53 bits (double) + * 2 64 bits (extended) + * 3 113 bits (quad) + * + * ipio2[] + * integer array, contains the (24*i)-th to (24*i+23)-th + * bit of 2/pi after binary point. The corresponding + * floating value is + * + * ipio2[i] * 2^(-24(i+1)). + * + * External function: + * double scalbn(), floor(); + * + * + * Here is the description of some local variables: + * + * jk jk+1 is the initial number of terms of ipio2[] needed + * in the computation. The recommended value is 2,3,4, + * 6 for single, double, extended,and quad. + * + * jz local integer variable indicating the number of + * terms of ipio2[] used. + * + * jx nx - 1 + * + * jv index for pointing to the suitable ipio2[] for the + * computation. In general, we want + * ( 2^e0*x[0] * ipio2[jv-1]*2^(-24jv) )/8 + * is an integer. Thus + * e0-3-24*jv >= 0 or (e0-3)/24 >= jv + * Hence jv = max(0,(e0-3)/24). + * + * jp jp+1 is the number of terms in PIo2[] needed, jp = jk. + * + * q[] double array with integral value, representing the + * 24-bits chunk of the product of x and 2/pi. + * + * q0 the corresponding exponent of q[0]. Note that the + * exponent for q[i] would be q0-24*i. + * + * PIo2[] double precision array, obtained by cutting pi/2 + * into 24 bits chunks. + * + * f[] ipio2[] in floating point + * + * iq[] integer array by breaking up q[] in 24-bits chunk. + * + * fq[] final product of x*(2/pi) in fq[0],..,fq[jk] + * + * ih integer. If >0 it indicates q[] is >= 0.5, hence + * it also indicates the *sign* of the result. + * + */ + + +/* + * Constants: + * The hexadecimal values are the intended ones for the following + * constants. The decimal values may be used, provided that the + * compiler will convert from decimal to binary accurately enough + * to produce the hexadecimal values shown. + */ + +#include "math.h" +#include "math_private.h" + +static const int init_jk[] = {2,3,4,6}; /* initial value for jk */ + +static const double PIo2[] = { + 1.57079625129699707031e+00, /* 0x3FF921FB, 0x40000000 */ + 7.54978941586159635335e-08, /* 0x3E74442D, 0x00000000 */ + 5.39030252995776476554e-15, /* 0x3CF84698, 0x80000000 */ + 3.28200341580791294123e-22, /* 0x3B78CC51, 0x60000000 */ + 1.27065575308067607349e-29, /* 0x39F01B83, 0x80000000 */ + 1.22933308981111328932e-36, /* 0x387A2520, 0x40000000 */ + 2.73370053816464559624e-44, /* 0x36E38222, 0x80000000 */ + 2.16741683877804819444e-51, /* 0x3569F31D, 0x00000000 */ +}; + +static const double +zero = 0.0, +one = 1.0, +two24 = 1.67772160000000000000e+07, /* 0x41700000, 0x00000000 */ +twon24 = 5.96046447753906250000e-08; /* 0x3E700000, 0x00000000 */ + +int attribute_hidden __kernel_rem_pio2(double *x, double *y, int e0, int nx, int prec, const int32_t *ipio2) +{ + int32_t jz,jx,jv,jp,jk,carry,n,iq[20],i,j,k,m,q0,ih; + double z,fw,f[20],fq[20],q[20]; + + /* initialize jk*/ + jk = init_jk[prec]; + jp = jk; + + /* determine jx,jv,q0, note that 3>q0 */ + jx = nx-1; + jv = (e0-3)/24; if(jv<0) jv=0; + q0 = e0-24*(jv+1); + + /* set up f[0] to f[jx+jk] where f[jx+jk] = ipio2[jv+jk] */ + j = jv-jx; m = jx+jk; + for(i=0;i<=m;i++,j++) f[i] = (j<0)? zero : (double) ipio2[j]; + + /* compute q[0],q[1],...q[jk] */ + for (i=0;i<=jk;i++) { + for(j=0,fw=0.0;j<=jx;j++) fw += x[j]*f[jx+i-j]; q[i] = fw; + } + + jz = jk; +recompute: + /* distill q[] into iq[] reversingly */ + for(i=0,j=jz,z=q[jz];j>0;i++,j--) { + fw = (double)((int32_t)(twon24* z)); + iq[i] = (int32_t)(z-two24*fw); + z = q[j-1]+fw; + } + + /* compute n */ + z = scalbn(z,q0); /* actual value of z */ + z -= 8.0*floor(z*0.125); /* trim off integer >= 8 */ + n = (int32_t) z; + z -= (double)n; + ih = 0; + if(q0>0) { /* need iq[jz-1] to determine n */ + i = (iq[jz-1]>>(24-q0)); n += i; + iq[jz-1] -= i<<(24-q0); + ih = iq[jz-1]>>(23-q0); + } + else if(q0==0) ih = iq[jz-1]>>23; + else if(z>=0.5) ih=2; + + if(ih>0) { /* q > 0.5 */ + n += 1; carry = 0; + for(i=0;i0) { /* rare case: chance is 1 in 12 */ + switch(q0) { + case 1: + iq[jz-1] &= 0x7fffff; break; + case 2: + iq[jz-1] &= 0x3fffff; break; + } + } + if(ih==2) { + z = one - z; + if(carry!=0) z -= scalbn(one,q0); + } + } + + /* check if recomputation is needed */ + if(z==zero) { + j = 0; + for (i=jz-1;i>=jk;i--) j |= iq[i]; + if(j==0) { /* need recomputation */ + for(k=1;iq[jk-k]==0;k++); /* k = no. of terms needed */ + + for(i=jz+1;i<=jz+k;i++) { /* add q[jz+1] to q[jz+k] */ + f[jx+i] = (double) ipio2[jv+i]; + for(j=0,fw=0.0;j<=jx;j++) fw += x[j]*f[jx+i-j]; + q[i] = fw; + } + jz += k; + goto recompute; + } + } + + /* chop off zero terms */ + if(z==0.0) { + jz -= 1; q0 -= 24; + while(iq[jz]==0) { jz--; q0-=24;} + } else { /* break z into 24-bit if necessary */ + z = scalbn(z,-q0); + if(z>=two24) { + fw = (double)((int32_t)(twon24*z)); + iq[jz] = (int32_t)(z-two24*fw); + jz += 1; q0 += 24; + iq[jz] = (int32_t) fw; + } else iq[jz] = (int32_t) z ; + } + + /* convert integer "bit" chunk to floating-point value */ + fw = scalbn(one,q0); + for(i=jz;i>=0;i--) { + q[i] = fw*(double)iq[i]; fw*=twon24; + } + + /* compute PIo2[0,...,jp]*q[jz,...,0] */ + for(i=jz;i>=0;i--) { + for(fw=0.0,k=0;k<=jp&&k<=jz-i;k++) fw += PIo2[k]*q[i+k]; + fq[jz-i] = fw; + } + + /* compress fq[] into y[] */ + switch(prec) { + case 0: + fw = 0.0; + for (i=jz;i>=0;i--) fw += fq[i]; + y[0] = (ih==0)? fw: -fw; + break; + case 1: + case 2: + fw = 0.0; + for (i=jz;i>=0;i--) fw += fq[i]; + y[0] = (ih==0)? fw: -fw; + fw = fq[0]-fw; + for (i=1;i<=jz;i++) fw += fq[i]; + y[1] = (ih==0)? fw: -fw; + break; + case 3: /* painful */ + for (i=jz;i>0;i--) { + fw = fq[i-1]+fq[i]; + fq[i] += fq[i-1]-fw; + fq[i-1] = fw; + } + for (i=jz;i>1;i--) { + fw = fq[i-1]+fq[i]; + fq[i] += fq[i-1]-fw; + fq[i-1] = fw; + } + for (fw=0.0,i=jz;i>=2;i--) fw += fq[i]; + if(ih==0) { + y[0] = fq[0]; y[1] = fq[1]; y[2] = fw; + } else { + y[0] = -fq[0]; y[1] = -fq[1]; y[2] = -fw; + } + } + return n&7; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/k_sin.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/k_sin.c new file mode 100644 index 00000000..39a1bea9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/k_sin.c @@ -0,0 +1,65 @@ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* __kernel_sin( x, y, iy) + * kernel sin function on [-pi/4, pi/4], pi/4 ~ 0.7854 + * Input x is assumed to be bounded by ~pi/4 in magnitude. + * Input y is the tail of x. + * Input iy indicates whether y is 0. (if iy=0, y assume to be 0). + * + * Algorithm + * 1. Since sin(-x) = -sin(x), we need only to consider positive x. + * 2. if x < 2^-27 (hx<0x3e400000 0), return x with inexact if x!=0. + * 3. sin(x) is approximated by a polynomial of degree 13 on + * [0,pi/4] + * 3 13 + * sin(x) ~ x + S1*x + ... + S6*x + * where + * + * |sin(x) 2 4 6 8 10 12 | -58 + * |----- - (1+S1*x +S2*x +S3*x +S4*x +S5*x +S6*x )| <= 2 + * | x | + * + * 4. sin(x+y) = sin(x) + sin'(x')*y + * ~ sin(x) + (1-x*x/2)*y + * For better accuracy, let + * 3 2 2 2 2 + * r = x *(S2+x *(S3+x *(S4+x *(S5+x *S6)))) + * then 3 2 + * sin(x) = x + (S1*x + (x *(r-y/2)+y)) + */ + +#include "math.h" +#include "math_private.h" + +static const double +half = 5.00000000000000000000e-01, /* 0x3FE00000, 0x00000000 */ +S1 = -1.66666666666666324348e-01, /* 0xBFC55555, 0x55555549 */ +S2 = 8.33333333332248946124e-03, /* 0x3F811111, 0x1110F8A6 */ +S3 = -1.98412698298579493134e-04, /* 0xBF2A01A0, 0x19C161D5 */ +S4 = 2.75573137070700676789e-06, /* 0x3EC71DE3, 0x57B1FE7D */ +S5 = -2.50507602534068634195e-08, /* 0xBE5AE5E6, 0x8A2B9CEB */ +S6 = 1.58969099521155010221e-10; /* 0x3DE5D93A, 0x5ACFD57C */ + +double attribute_hidden __kernel_sin(double x, double y, int iy) +{ + double z,r,v; + int32_t ix; + GET_HIGH_WORD(ix,x); + ix &= 0x7fffffff; /* high word of x */ + if(ix<0x3e400000) /* |x| < 2**-27 */ + {if((int)x==0) return x;} /* generate inexact */ + z = x*x; + v = z*x; + r = S2+z*(S3+z*(S4+z*(S5+z*S6))); + if(iy==0) return x+v*(S1+z*r); + else return x-((z*(half*y-v*r)-y)-v*S1); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/k_standard.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/k_standard.c new file mode 100644 index 00000000..d9ab7457 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/k_standard.c @@ -0,0 +1,770 @@ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +#include +#include "math_private.h" +#include + +#ifndef _IEEE_LIBM + +#ifndef _USE_WRITE +#include /* fputs(), stderr */ +#define WRITE2(u,v) fputs(u, stderr) +#else /* !defined(_USE_WRITE) */ +#include /* write */ +#define WRITE2(u,v) write(2, u, v) +#undef fflush +#endif /* !defined(_USE_WRITE) */ + +static const double zero = 0.0; /* used as const */ + +/* + * Standard conformance (non-IEEE) on exception cases. + * Mapping: + * 1 -- acos(|x|>1) + * 2 -- asin(|x|>1) + * 3 -- atan2(+-0,+-0) + * 4 -- hypot overflow + * 5 -- cosh overflow + * 6 -- exp overflow + * 7 -- exp underflow + * 8 -- y0(0) + * 9 -- y0(-ve) + * 10-- y1(0) + * 11-- y1(-ve) + * 12-- yn(0) + * 13-- yn(-ve) + * 14-- lgamma(finite) overflow + * 15-- lgamma(-integer) + * 16-- log(0) + * 17-- log(x<0) + * 18-- log10(0) + * 19-- log10(x<0) + * 20-- pow(0.0,0.0) + * 21-- pow(x,y) overflow + * 22-- pow(x,y) underflow + * 23-- pow(0,negative) + * 24-- pow(neg,non-integral) + * 25-- sinh(finite) overflow + * 26-- sqrt(negative) + * 27-- fmod(x,0) + * 28-- remainder(x,0) + * 29-- acosh(x<1) + * 30-- atanh(|x|>1) + * 31-- atanh(|x|=1) + * 32-- scalb overflow + * 33-- scalb underflow + * 34-- j0(|x|>X_TLOSS) + * 35-- y0(x>X_TLOSS) + * 36-- j1(|x|>X_TLOSS) + * 37-- y1(x>X_TLOSS) + * 38-- jn(|x|>X_TLOSS, n) + * 39-- yn(x>X_TLOSS, n) + * 40-- gamma(finite) overflow + * 41-- gamma(-integer) + * 42-- pow(NaN,0.0) + */ + +double __kernel_standard(double x, double y, int type) +{ + struct exception exc; +#ifndef HUGE_VAL /* this is the only routine that uses HUGE_VAL */ +#define HUGE_VAL inf + double inf = 0.0; + + SET_HIGH_WORD(inf,0x7ff00000); /* set inf to infinite */ +#endif + +#ifdef _USE_WRITE + (void) fflush(stdout); +#endif + exc.arg1 = x; + exc.arg2 = y; + switch(type) { + case 1: + case 101: + /* acos(|x|>1) */ + exc.type = DOMAIN; + exc.name = type < 100 ? "acos" : "acosf"; + exc.retval = zero; + if (_LIB_VERSION == _POSIX_) + errno = EDOM; + else if (!matherr(&exc)) { + if(_LIB_VERSION == _SVID_) { + (void) WRITE2("acos: DOMAIN error\n", 19); + } + errno = EDOM; + } + break; + case 2: + case 102: + /* asin(|x|>1) */ + exc.type = DOMAIN; + exc.name = type < 100 ? "asin" : "asinf"; + exc.retval = zero; + if(_LIB_VERSION == _POSIX_) + errno = EDOM; + else if (!matherr(&exc)) { + if(_LIB_VERSION == _SVID_) { + (void) WRITE2("asin: DOMAIN error\n", 19); + } + errno = EDOM; + } + break; + case 3: + case 103: + /* atan2(+-0,+-0) */ + exc.arg1 = y; + exc.arg2 = x; + exc.type = DOMAIN; + exc.name = type < 100 ? "atan2" : "atan2f"; + exc.retval = zero; + if(_LIB_VERSION == _POSIX_) + errno = EDOM; + else if (!matherr(&exc)) { + if(_LIB_VERSION == _SVID_) { + (void) WRITE2("atan2: DOMAIN error\n", 20); + } + errno = EDOM; + } + break; + case 4: + case 104: + /* hypot(finite,finite) overflow */ + exc.type = OVERFLOW; + exc.name = type < 100 ? "hypot" : "hypotf"; + if (_LIB_VERSION == _SVID_) + exc.retval = HUGE; + else + exc.retval = HUGE_VAL; + if (_LIB_VERSION == _POSIX_) + errno = ERANGE; + else if (!matherr(&exc)) { + errno = ERANGE; + } + break; + case 5: + case 105: + /* cosh(finite) overflow */ + exc.type = OVERFLOW; + exc.name = type < 100 ? "cosh" : "coshf"; + if (_LIB_VERSION == _SVID_) + exc.retval = HUGE; + else + exc.retval = HUGE_VAL; + if (_LIB_VERSION == _POSIX_) + errno = ERANGE; + else if (!matherr(&exc)) { + errno = ERANGE; + } + break; + case 6: + case 106: + /* exp(finite) overflow */ + exc.type = OVERFLOW; + exc.name = type < 100 ? "exp" : "expf"; + if (_LIB_VERSION == _SVID_) + exc.retval = HUGE; + else + exc.retval = HUGE_VAL; + if (_LIB_VERSION == _POSIX_) + errno = ERANGE; + else if (!matherr(&exc)) { + errno = ERANGE; + } + break; + case 7: + case 107: + /* exp(finite) underflow */ + exc.type = UNDERFLOW; + exc.name = type < 100 ? "exp" : "expf"; + exc.retval = zero; + if (_LIB_VERSION == _POSIX_) + errno = ERANGE; + else if (!matherr(&exc)) { + errno = ERANGE; + } + break; + case 8: + case 108: + /* y0(0) = -inf */ + exc.type = DOMAIN; /* should be SING for IEEE */ + exc.name = type < 100 ? "y0" : "y0f"; + if (_LIB_VERSION == _SVID_) + exc.retval = -HUGE; + else + exc.retval = -HUGE_VAL; + if (_LIB_VERSION == _POSIX_) + errno = EDOM; + else if (!matherr(&exc)) { + if (_LIB_VERSION == _SVID_) { + (void) WRITE2("y0: DOMAIN error\n", 17); + } + errno = EDOM; + } + break; + case 9: + case 109: + /* y0(x<0) = NaN */ + exc.type = DOMAIN; + exc.name = type < 100 ? "y0" : "y0f"; + if (_LIB_VERSION == _SVID_) + exc.retval = -HUGE; + else + exc.retval = -HUGE_VAL; + if (_LIB_VERSION == _POSIX_) + errno = EDOM; + else if (!matherr(&exc)) { + if (_LIB_VERSION == _SVID_) { + (void) WRITE2("y0: DOMAIN error\n", 17); + } + errno = EDOM; + } + break; + case 10: + case 110: + /* y1(0) = -inf */ + exc.type = DOMAIN; /* should be SING for IEEE */ + exc.name = type < 100 ? "y1" : "y1f"; + if (_LIB_VERSION == _SVID_) + exc.retval = -HUGE; + else + exc.retval = -HUGE_VAL; + if (_LIB_VERSION == _POSIX_) + errno = EDOM; + else if (!matherr(&exc)) { + if (_LIB_VERSION == _SVID_) { + (void) WRITE2("y1: DOMAIN error\n", 17); + } + errno = EDOM; + } + break; + case 11: + case 111: + /* y1(x<0) = NaN */ + exc.type = DOMAIN; + exc.name = type < 100 ? "y1" : "y1f"; + if (_LIB_VERSION == _SVID_) + exc.retval = -HUGE; + else + exc.retval = -HUGE_VAL; + if (_LIB_VERSION == _POSIX_) + errno = EDOM; + else if (!matherr(&exc)) { + if (_LIB_VERSION == _SVID_) { + (void) WRITE2("y1: DOMAIN error\n", 17); + } + errno = EDOM; + } + break; + case 12: + case 112: + /* yn(n,0) = -inf */ + exc.type = DOMAIN; /* should be SING for IEEE */ + exc.name = type < 100 ? "yn" : "ynf"; + if (_LIB_VERSION == _SVID_) + exc.retval = -HUGE; + else + exc.retval = -HUGE_VAL; + if (_LIB_VERSION == _POSIX_) + errno = EDOM; + else if (!matherr(&exc)) { + if (_LIB_VERSION == _SVID_) { + (void) WRITE2("yn: DOMAIN error\n", 17); + } + errno = EDOM; + } + break; + case 13: + case 113: + /* yn(x<0) = NaN */ + exc.type = DOMAIN; + exc.name = type < 100 ? "yn" : "ynf"; + if (_LIB_VERSION == _SVID_) + exc.retval = -HUGE; + else + exc.retval = -HUGE_VAL; + if (_LIB_VERSION == _POSIX_) + errno = EDOM; + else if (!matherr(&exc)) { + if (_LIB_VERSION == _SVID_) { + (void) WRITE2("yn: DOMAIN error\n", 17); + } + errno = EDOM; + } + break; + case 14: + case 114: + /* lgamma(finite) overflow */ + exc.type = OVERFLOW; + exc.name = type < 100 ? "lgamma" : "lgammaf"; + if (_LIB_VERSION == _SVID_) + exc.retval = HUGE; + else + exc.retval = HUGE_VAL; + if (_LIB_VERSION == _POSIX_) + errno = ERANGE; + else if (!matherr(&exc)) { + errno = ERANGE; + } + break; + case 15: + case 115: + /* lgamma(-integer) or lgamma(0) */ + exc.type = SING; + exc.name = type < 100 ? "lgamma" : "lgammaf"; + if (_LIB_VERSION == _SVID_) + exc.retval = HUGE; + else + exc.retval = HUGE_VAL; + if (_LIB_VERSION == _POSIX_) + errno = EDOM; + else if (!matherr(&exc)) { + if (_LIB_VERSION == _SVID_) { + (void) WRITE2("lgamma: SING error\n", 19); + } + errno = EDOM; + } + break; + case 16: + case 116: + /* log(0) */ + exc.type = SING; + exc.name = type < 100 ? "log" : "logf"; + if (_LIB_VERSION == _SVID_) + exc.retval = -HUGE; + else + exc.retval = -HUGE_VAL; + if (_LIB_VERSION == _POSIX_) + errno = ERANGE; + else if (!matherr(&exc)) { + if (_LIB_VERSION == _SVID_) { + (void) WRITE2("log: SING error\n", 16); + } + errno = EDOM; + } + break; + case 17: + case 117: + /* log(x<0) */ + exc.type = DOMAIN; + exc.name = type < 100 ? "log" : "logf"; + if (_LIB_VERSION == _SVID_) + exc.retval = -HUGE; + else + exc.retval = -HUGE_VAL; + if (_LIB_VERSION == _POSIX_) + errno = EDOM; + else if (!matherr(&exc)) { + if (_LIB_VERSION == _SVID_) { + (void) WRITE2("log: DOMAIN error\n", 18); + } + errno = EDOM; + } + break; + case 18: + case 118: + /* log10(0) */ + exc.type = SING; + exc.name = type < 100 ? "log10" : "log10f"; + if (_LIB_VERSION == _SVID_) + exc.retval = -HUGE; + else + exc.retval = -HUGE_VAL; + if (_LIB_VERSION == _POSIX_) + errno = ERANGE; + else if (!matherr(&exc)) { + if (_LIB_VERSION == _SVID_) { + (void) WRITE2("log10: SING error\n", 18); + } + errno = EDOM; + } + break; + case 19: + case 119: + /* log10(x<0) */ + exc.type = DOMAIN; + exc.name = type < 100 ? "log10" : "log10f"; + if (_LIB_VERSION == _SVID_) + exc.retval = -HUGE; + else + exc.retval = -HUGE_VAL; + if (_LIB_VERSION == _POSIX_) + errno = EDOM; + else if (!matherr(&exc)) { + if (_LIB_VERSION == _SVID_) { + (void) WRITE2("log10: DOMAIN error\n", 20); + } + errno = EDOM; + } + break; + case 20: + case 120: + /* pow(0.0,0.0) */ + /* error only if _LIB_VERSION == _SVID_ */ + exc.type = DOMAIN; + exc.name = type < 100 ? "pow" : "powf"; + exc.retval = zero; + if (_LIB_VERSION != _SVID_) exc.retval = 1.0; + else if (!matherr(&exc)) { + (void) WRITE2("pow(0,0): DOMAIN error\n", 23); + errno = EDOM; + } + break; + case 21: + case 121: + /* pow(x,y) overflow */ + exc.type = OVERFLOW; + exc.name = type < 100 ? "pow" : "powf"; + if (_LIB_VERSION == _SVID_) { + exc.retval = HUGE; + y *= 0.5; + if(xzero) ? HUGE : -HUGE); + else + exc.retval = ( (x>zero) ? HUGE_VAL : -HUGE_VAL); + if (_LIB_VERSION == _POSIX_) + errno = ERANGE; + else if (!matherr(&exc)) { + errno = ERANGE; + } + break; + case 26: + case 126: + /* sqrt(x<0) */ + exc.type = DOMAIN; + exc.name = type < 100 ? "sqrt" : "sqrtf"; + if (_LIB_VERSION == _SVID_) + exc.retval = zero; + else + exc.retval = zero/zero; + if (_LIB_VERSION == _POSIX_) + errno = EDOM; + else if (!matherr(&exc)) { + if (_LIB_VERSION == _SVID_) { + (void) WRITE2("sqrt: DOMAIN error\n", 19); + } + errno = EDOM; + } + break; + case 27: + case 127: + /* fmod(x,0) */ + exc.type = DOMAIN; + exc.name = type < 100 ? "fmod" : "fmodf"; + if (_LIB_VERSION == _SVID_) + exc.retval = x; + else + exc.retval = zero/zero; + if (_LIB_VERSION == _POSIX_) + errno = EDOM; + else if (!matherr(&exc)) { + if (_LIB_VERSION == _SVID_) { + (void) WRITE2("fmod: DOMAIN error\n", 20); + } + errno = EDOM; + } + break; + case 28: + case 128: + /* remainder(x,0) */ + exc.type = DOMAIN; + exc.name = type < 100 ? "remainder" : "remainderf"; + exc.retval = zero/zero; + if (_LIB_VERSION == _POSIX_) + errno = EDOM; + else if (!matherr(&exc)) { + if (_LIB_VERSION == _SVID_) { + (void) WRITE2("remainder: DOMAIN error\n", 24); + } + errno = EDOM; + } + break; + case 29: + case 129: + /* acosh(x<1) */ + exc.type = DOMAIN; + exc.name = type < 100 ? "acosh" : "acoshf"; + exc.retval = zero/zero; + if (_LIB_VERSION == _POSIX_) + errno = EDOM; + else if (!matherr(&exc)) { + if (_LIB_VERSION == _SVID_) { + (void) WRITE2("acosh: DOMAIN error\n", 20); + } + errno = EDOM; + } + break; + case 30: + case 130: + /* atanh(|x|>1) */ + exc.type = DOMAIN; + exc.name = type < 100 ? "atanh" : "atanhf"; + exc.retval = zero/zero; + if (_LIB_VERSION == _POSIX_) + errno = EDOM; + else if (!matherr(&exc)) { + if (_LIB_VERSION == _SVID_) { + (void) WRITE2("atanh: DOMAIN error\n", 20); + } + errno = EDOM; + } + break; + case 31: + case 131: + /* atanh(|x|=1) */ + exc.type = SING; + exc.name = type < 100 ? "atanh" : "atanhf"; + exc.retval = x/zero; /* sign(x)*inf */ + if (_LIB_VERSION == _POSIX_) + errno = EDOM; + else if (!matherr(&exc)) { + if (_LIB_VERSION == _SVID_) { + (void) WRITE2("atanh: SING error\n", 18); + } + errno = EDOM; + } + break; + case 32: + case 132: + /* scalb overflow; SVID also returns +-HUGE_VAL */ + exc.type = OVERFLOW; + exc.name = type < 100 ? "scalb" : "scalbf"; + exc.retval = x > zero ? HUGE_VAL : -HUGE_VAL; + if (_LIB_VERSION == _POSIX_) + errno = ERANGE; + else if (!matherr(&exc)) { + errno = ERANGE; + } + break; + case 33: + case 133: + /* scalb underflow */ + exc.type = UNDERFLOW; + exc.name = type < 100 ? "scalb" : "scalbf"; + exc.retval = copysign(zero,x); + if (_LIB_VERSION == _POSIX_) + errno = ERANGE; + else if (!matherr(&exc)) { + errno = ERANGE; + } + break; + case 34: + case 134: + /* j0(|x|>X_TLOSS) */ + exc.type = TLOSS; + exc.name = type < 100 ? "j0" : "j0f"; + exc.retval = zero; + if (_LIB_VERSION == _POSIX_) + errno = ERANGE; + else if (!matherr(&exc)) { + if (_LIB_VERSION == _SVID_) { + (void) WRITE2(exc.name, 2); + (void) WRITE2(": TLOSS error\n", 14); + } + errno = ERANGE; + } + break; + case 35: + case 135: + /* y0(x>X_TLOSS) */ + exc.type = TLOSS; + exc.name = type < 100 ? "y0" : "y0f"; + exc.retval = zero; + if (_LIB_VERSION == _POSIX_) + errno = ERANGE; + else if (!matherr(&exc)) { + if (_LIB_VERSION == _SVID_) { + (void) WRITE2(exc.name, 2); + (void) WRITE2(": TLOSS error\n", 14); + } + errno = ERANGE; + } + break; + case 36: + case 136: + /* j1(|x|>X_TLOSS) */ + exc.type = TLOSS; + exc.name = type < 100 ? "j1" : "j1f"; + exc.retval = zero; + if (_LIB_VERSION == _POSIX_) + errno = ERANGE; + else if (!matherr(&exc)) { + if (_LIB_VERSION == _SVID_) { + (void) WRITE2(exc.name, 2); + (void) WRITE2(": TLOSS error\n", 14); + } + errno = ERANGE; + } + break; + case 37: + case 137: + /* y1(x>X_TLOSS) */ + exc.type = TLOSS; + exc.name = type < 100 ? "y1" : "y1f"; + exc.retval = zero; + if (_LIB_VERSION == _POSIX_) + errno = ERANGE; + else if (!matherr(&exc)) { + if (_LIB_VERSION == _SVID_) { + (void) WRITE2(exc.name, 2); + (void) WRITE2(": TLOSS error\n", 14); + } + errno = ERANGE; + } + break; + case 38: + case 138: + /* jn(|x|>X_TLOSS) */ + exc.type = TLOSS; + exc.name = type < 100 ? "jn" : "jnf"; + exc.retval = zero; + if (_LIB_VERSION == _POSIX_) + errno = ERANGE; + else if (!matherr(&exc)) { + if (_LIB_VERSION == _SVID_) { + (void) WRITE2(exc.name, 2); + (void) WRITE2(": TLOSS error\n", 14); + } + errno = ERANGE; + } + break; + case 39: + case 139: + /* yn(x>X_TLOSS) */ + exc.type = TLOSS; + exc.name = type < 100 ? "yn" : "ynf"; + exc.retval = zero; + if (_LIB_VERSION == _POSIX_) + errno = ERANGE; + else if (!matherr(&exc)) { + if (_LIB_VERSION == _SVID_) { + (void) WRITE2(exc.name, 2); + (void) WRITE2(": TLOSS error\n", 14); + } + errno = ERANGE; + } + break; + case 40: + case 140: + /* gamma(finite) overflow */ + exc.type = OVERFLOW; + exc.name = type < 100 ? "gamma" : "gammaf"; + if (_LIB_VERSION == _SVID_) + exc.retval = HUGE; + else + exc.retval = HUGE_VAL; + if (_LIB_VERSION == _POSIX_) + errno = ERANGE; + else if (!matherr(&exc)) { + errno = ERANGE; + } + break; + case 41: + case 141: + /* gamma(-integer) or gamma(0) */ + exc.type = SING; + exc.name = type < 100 ? "gamma" : "gammaf"; + if (_LIB_VERSION == _SVID_) + exc.retval = HUGE; + else + exc.retval = HUGE_VAL; + if (_LIB_VERSION == _POSIX_) + errno = EDOM; + else if (!matherr(&exc)) { + if (_LIB_VERSION == _SVID_) { + (void) WRITE2("gamma: SING error\n", 18); + } + errno = EDOM; + } + break; + case 42: + case 142: + /* pow(NaN,0.0) */ + /* error only if _LIB_VERSION == _SVID_ & _XOPEN_ */ + exc.type = DOMAIN; + exc.name = type < 100 ? "pow" : "powf"; + exc.retval = x; + if (_LIB_VERSION == _IEEE_ || + _LIB_VERSION == _POSIX_) exc.retval = 1.0; + else if (!matherr(&exc)) { + errno = EDOM; + } + break; + } + return exc.retval; +} +#endif /* _IEEE_LIBM */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/k_tan.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/k_tan.c new file mode 100644 index 00000000..720b51f6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/k_tan.c @@ -0,0 +1,118 @@ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* __kernel_tan( x, y, k ) + * kernel tan function on [-pi/4, pi/4], pi/4 ~ 0.7854 + * Input x is assumed to be bounded by ~pi/4 in magnitude. + * Input y is the tail of x. + * Input k indicates whether tan (if k=1) or + * -1/tan (if k= -1) is returned. + * + * Algorithm + * 1. Since tan(-x) = -tan(x), we need only to consider positive x. + * 2. if x < 2^-28 (hx<0x3e300000 0), return x with inexact if x!=0. + * 3. tan(x) is approximated by a odd polynomial of degree 27 on + * [0,0.67434] + * 3 27 + * tan(x) ~ x + T1*x + ... + T13*x + * where + * + * |tan(x) 2 4 26 | -59.2 + * |----- - (1+T1*x +T2*x +.... +T13*x )| <= 2 + * | x | + * + * Note: tan(x+y) = tan(x) + tan'(x)*y + * ~ tan(x) + (1+x*x)*y + * Therefore, for better accuracy in computing tan(x+y), let + * 3 2 2 2 2 + * r = x *(T2+x *(T3+x *(...+x *(T12+x *T13)))) + * then + * 3 2 + * tan(x+y) = x + (T1*x + (x *(r+y)+y)) + * + * 4. For x in [0.67434,pi/4], let y = pi/4 - x, then + * tan(x) = tan(pi/4-y) = (1-tan(y))/(1+tan(y)) + * = 1 - 2*(tan(y) - (tan(y)^2)/(1+tan(y))) + */ + +#include "math.h" +#include "math_private.h" + +static const double +one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */ +pio4 = 7.85398163397448278999e-01, /* 0x3FE921FB, 0x54442D18 */ +pio4lo= 3.06161699786838301793e-17, /* 0x3C81A626, 0x33145C07 */ +T[] = { + 3.33333333333334091986e-01, /* 0x3FD55555, 0x55555563 */ + 1.33333333333201242699e-01, /* 0x3FC11111, 0x1110FE7A */ + 5.39682539762260521377e-02, /* 0x3FABA1BA, 0x1BB341FE */ + 2.18694882948595424599e-02, /* 0x3F9664F4, 0x8406D637 */ + 8.86323982359930005737e-03, /* 0x3F8226E3, 0xE96E8493 */ + 3.59207910759131235356e-03, /* 0x3F6D6D22, 0xC9560328 */ + 1.45620945432529025516e-03, /* 0x3F57DBC8, 0xFEE08315 */ + 5.88041240820264096874e-04, /* 0x3F4344D8, 0xF2F26501 */ + 2.46463134818469906812e-04, /* 0x3F3026F7, 0x1A8D1068 */ + 7.81794442939557092300e-05, /* 0x3F147E88, 0xA03792A6 */ + 7.14072491382608190305e-05, /* 0x3F12B80F, 0x32F0A7E9 */ + -1.85586374855275456654e-05, /* 0xBEF375CB, 0xDB605373 */ + 2.59073051863633712884e-05, /* 0x3EFB2A70, 0x74BF7AD4 */ +}; + +double attribute_hidden __kernel_tan(double x, double y, int iy) +{ + double z,r,v,w,s; + int32_t ix,hx; + GET_HIGH_WORD(hx,x); + ix = hx&0x7fffffff; /* high word of |x| */ + if(ix<0x3e300000) /* x < 2**-28 */ + {if((int)x==0) { /* generate inexact */ + u_int32_t low; + GET_LOW_WORD(low,x); + if(((ix|low)|(iy+1))==0) return one/fabs(x); + else return (iy==1)? x: -one/x; + } + } + if(ix>=0x3FE59428) { /* |x|>=0.6744 */ + if(hx<0) {x = -x; y = -y;} + z = pio4-x; + w = pio4lo-y; + x = z+w; y = 0.0; + } + z = x*x; + w = z*z; + /* Break x^5*(T[1]+x^2*T[2]+...) into + * x^5(T[1]+x^4*T[3]+...+x^20*T[11]) + + * x^5(x^2*(T[2]+x^4*T[4]+...+x^22*[T12])) + */ + r = T[1]+w*(T[3]+w*(T[5]+w*(T[7]+w*(T[9]+w*T[11])))); + v = z*(T[2]+w*(T[4]+w*(T[6]+w*(T[8]+w*(T[10]+w*T[12]))))); + s = z*x; + r = y + z*(s*(r+v)+y); + r += T[0]*s; + w = x+r; + if(ix>=0x3FE59428) { + v = (double)iy; + return (double)(1-((hx>>30)&2))*(v-2.0*(x-(w*w/(w+v)-r))); + } + if(iy==1) return w; + else { /* if allow error up to 2 ulp, + simply return -1.0/(x+r) here */ + /* compute -1.0/(x+r) accurately */ + double a,t; + z = w; + SET_LOW_WORD(z,0); + v = r-(z - x); /* z+v = r+x */ + t = a = -1.0/w; /* a = -1.0/w */ + SET_LOW_WORD(t,0); + s = 1.0+t*z; + return t+a*(s+t*v); + } +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/ldouble_wrappers.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/ldouble_wrappers.c new file mode 100644 index 00000000..118a78f6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/ldouble_wrappers.c @@ -0,0 +1,400 @@ +/* vi: set sw=4 ts=4: */ +/* + * Wrapper functions implementing all the long double math functions + * defined by SuSv3 by actually calling the double version of + * each function and then casting the result back to a long double + * to return to the user. + * + * Copyright (C) 2005 by Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +/* Prevent math.h from defining colliding inlines */ +#undef __USE_EXTERN_INLINES +#include "math.h" +#include + +#define WRAPPER1(func) \ +long double func##l(long double x) \ +{ \ + return (long double) func((double) x); \ +} +#define WRAPPER2(func) \ +long double func##l(long double x, long double y) \ +{ \ + return (long double) func((double) x, (double) y); \ +} +#define int_WRAPPER1(func) \ +int func##l(long double x) \ +{ \ + return func((double) x); \ +} +#define long_WRAPPER1(func) \ +long func##l(long double x) \ +{ \ + return func((double) x); \ +} +#define long_long_WRAPPER1(func) \ +long long func##l(long double x) \ +{ \ + return func((double) x); \ +} + +/* Implement the following, as defined by SuSv3 */ +#if 0 +long double acoshl(long double); +long double acosl(long double); +long double asinhl(long double); +long double asinl(long double); +long double atan2l(long double, long double); +long double atanhl(long double); +long double atanl(long double); +long double cargl(long double complex); +long double cbrtl(long double); +long double ceill(long double); +long double copysignl(long double, long double); +long double coshl(long double); +long double cosl(long double); +long double erfcl(long double); +long double erfl(long double); +long double exp2l(long double); +long double expl(long double); +long double expm1l(long double); +long double fabsl(long double); +long double fdiml(long double, long double); +long double floorl(long double); +long double fmal(long double, long double, long double); +long double fmaxl(long double, long double); +long double fminl(long double, long double); +long double fmodl(long double, long double); +long double frexpl(long double value, int *); +long double hypotl(long double, long double); +int ilogbl(long double); +long double ldexpl(long double, int); +long double lgammal(long double); +long long llrintl(long double); +long long llroundl(long double); +long double log10l(long double); +long double log1pl(long double); +long double log2l(long double); +long double logbl(long double); +long double logl(long double); +long lrintl(long double); +long lroundl(long double); +long double modfl(long double, long double *); +long double nearbyintl(long double); +long double nextafterl(long double, long double); +long double nexttowardl(long double, long double); +long double powl(long double, long double); +long double remainderl(long double, long double); +long double remquol(long double, long double, int *); +long double rintl(long double); +long double roundl(long double); +long double scalblnl(long double, long); +long double scalbnl(long double, int); +long double sinhl(long double); +long double sinl(long double); +long double sqrtl(long double); +long double tanhl(long double); +long double tanl(long double); +long double tgammal(long double); +long double truncl(long double); +#endif + +#ifdef L_acoshl +WRAPPER1(acosh) +#endif + +#ifdef L_acosl +WRAPPER1(acos) +#endif + +#ifdef L_asinhl +WRAPPER1(asinh) +#endif + +#ifdef L_asinl +WRAPPER1(asin) +#endif + +#ifdef L_atan2l +WRAPPER2(atan2) +#endif + +#ifdef L_atanhl +WRAPPER1(atanh) +#endif + +#ifdef L_atanl +WRAPPER1(atan) +#endif + +#ifdef L_cargl +long double cargl (long double complex x) +{ + return (long double) carg( (double complex)x ); +} +#endif + +#ifdef L_cbrtl +WRAPPER1(cbrt) +#endif + +#ifdef L_ceill +WRAPPER1(ceil) +#endif + +#ifdef L_copysignl +WRAPPER2(copysign) +#endif + +#ifdef L_coshl +WRAPPER1(cosh) +#endif + +#ifdef L_cosl +WRAPPER1(cos) +#endif + +#ifdef L_erfcl +WRAPPER1(erfc) +#endif + +#ifdef L_erfl +WRAPPER1(erf) +#endif + +#ifdef L_exp2l +WRAPPER1(exp2) +#endif + +#ifdef L_expl +WRAPPER1(exp) +#endif + +#ifdef L_expm1l +WRAPPER1(expm1) +#endif + +#ifdef L_fabsl +WRAPPER1(fabs) +#endif + +#ifdef L_fdiml +WRAPPER2(fdim) +#endif + +#ifdef L_floorl +WRAPPER1(floor) +#endif + +#ifdef L_fmal +long double fmal (long double x, long double y, long double z) +{ + return (long double) fma( (double)x, (double)y, (double)z ); +} +#endif + +#ifdef L_fmaxl +WRAPPER2(fmax) +#endif + +#ifdef L_fminl +WRAPPER2(fmin) +#endif + +#ifdef L_fmodl +WRAPPER2(fmod) +#endif + +#ifdef L_frexpl +long double frexpl (long double x, int *ex) +{ + return (long double) frexp( (double)x, ex ); +} +#endif + +#ifdef L_gammal +WRAPPER1(gamma) +#endif + +#ifdef L_hypotl +WRAPPER2(hypot) +#endif + +#ifdef L_ilogbl +int_WRAPPER1(ilogb) +#endif + +#ifdef L_ldexpl +long double ldexpl (long double x, int ex) +{ + return (long double) ldexp( (double)x, ex ); +} +#endif + +#ifdef L_lgammal +WRAPPER1(lgamma) +#endif + +#ifdef L_llrintl +long_long_WRAPPER1(llrint) +#endif + +#ifdef L_llroundl +long_long_WRAPPER1(llround) +#endif + +#ifdef L_log10l +WRAPPER1(log10) +#endif + +#ifdef L_log1pl +WRAPPER1(log1p) +#endif + +#ifdef L_log2l +WRAPPER1(log2) +#endif + +#ifdef L_logbl +WRAPPER1(logb) +#endif + +#ifdef L_logl +WRAPPER1(log) +#endif + +#ifdef L_lrintl +long_WRAPPER1(lrint) +#endif + +#ifdef L_lroundl +long_WRAPPER1(lround) +#endif + +#ifdef L_modfl +long double modfl (long double x, long double *iptr) +{ + double y, result; + result = modf ( x, &y ); + *iptr = (long double)y; + return (long double) result; +} +#endif + +#ifdef L_nearbyintl +WRAPPER1(nearbyint) +#endif + +#ifdef L_nextafterl +WRAPPER2(nextafter) +#endif + +/* Disabled in Makefile.in */ +#if 0 /* def L_nexttowardl */ +WRAPPER2(nexttoward) +libm_hidden_def(nexttowardl) +#endif + +#ifdef L_powl +WRAPPER2(pow) +#endif + +#ifdef L_remainderl +WRAPPER2(remainder) +#endif + +#ifdef L_remquol +long double remquol (long double x, long double y, int *quo) +{ + return (long double) remquo( (double)x, (double)y, quo ); +} +#endif + +#ifdef L_rintl +WRAPPER1(rint) +#endif + +#ifdef L_roundl +WRAPPER1(round) +#endif + +#ifdef L_scalblnl +long double scalblnl (long double x, long ex) +{ + return (long double) scalbln( (double)x, ex ); +} +#endif + +#ifdef L_scalbnl +long double scalbnl (long double x, int ex) +{ + return (long double) scalbn( (double)x, ex ); +} +#endif + +/* scalb is an obsolete function */ + +#ifdef L_sinhl +WRAPPER1(sinh) +#endif + +#ifdef L_sinl +WRAPPER1(sin) +#endif + +#ifdef L_sqrtl +WRAPPER1(sqrt) +#endif + +#ifdef L_tanhl +WRAPPER1(tanh) +#endif + +#ifdef L_tanl +WRAPPER1(tan) +#endif + +#ifdef L_tgammal +WRAPPER1(tgamma) +#endif + +#ifdef L_truncl +WRAPPER1(trunc) +#endif + +#ifdef L_significandl +WRAPPER1(significand) +#endif + +#if defined __DO_C99_MATH__ && !defined __NO_LONG_DOUBLE_MATH + +# ifdef L___fpclassifyl +int_WRAPPER1(__fpclassify) +libm_hidden_def(__fpclassifyl) +# endif + +# ifdef L___finitel +int_WRAPPER1(__finite) +libm_hidden_def(__finitel) +# endif + +# ifdef L___signbitl +int_WRAPPER1(__signbit) +libm_hidden_def(__signbitl) +# endif + +# ifdef L___isnanl +int_WRAPPER1(__isnan) +libm_hidden_def(__isnanl) +# endif + +# ifdef L___isinfl +int_WRAPPER1(__isinf) +libm_hidden_def(__isinfl) +# endif + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/math_private.h b/l4/pkg/uclibc/lib/contrib/uclibc/libm/math_private.h new file mode 100644 index 00000000..be8031ef --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/math_private.h @@ -0,0 +1,259 @@ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +#ifndef _MATH_PRIVATE_H_ +#define _MATH_PRIVATE_H_ + +#include +#include + +/* The original fdlibm code used statements like: + n0 = ((*(int*)&one)>>29)^1; * index of high word * + ix0 = *(n0+(int*)&x); * high word of x * + ix1 = *((1-n0)+(int*)&x); * low word of x * + to dig two 32 bit words out of the 64 bit IEEE floating point + value. That is non-ANSI, and, moreover, the gcc instruction + scheduler gets it wrong. We instead use the following macros. + Unlike the original code, we determine the endianness at compile + time, not at run time; I don't see much benefit to selecting + endianness at run time. */ + +/* A union which permits us to convert between a double and two 32 bit + ints. */ + +/* + * Math on arm is special (read: stupid): + * For FPA, float words are always big-endian. + * For VFP, float words follow the memory system mode. + * For Maverick, float words are always little-endian. + */ + +#if !defined(__MAVERICK__) && ((__BYTE_ORDER == __BIG_ENDIAN) || \ + (!defined(__VFP_FP__) && (defined(__arm__) || defined(__thumb__)))) + +typedef union +{ + double value; + struct + { + u_int32_t msw; + u_int32_t lsw; + } parts; +} ieee_double_shape_type; + +#else + +typedef union +{ + double value; + struct + { + u_int32_t lsw; + u_int32_t msw; + } parts; +} ieee_double_shape_type; + +#endif + +/* Get two 32 bit ints from a double. */ + +#define EXTRACT_WORDS(ix0,ix1,d) \ +do { \ + ieee_double_shape_type ew_u; \ + ew_u.value = (d); \ + (ix0) = ew_u.parts.msw; \ + (ix1) = ew_u.parts.lsw; \ +} while (0) + +/* Get the more significant 32 bit int from a double. */ + +#define GET_HIGH_WORD(i,d) \ +do { \ + ieee_double_shape_type gh_u; \ + gh_u.value = (d); \ + (i) = gh_u.parts.msw; \ +} while (0) + +/* Get the less significant 32 bit int from a double. */ + +#define GET_LOW_WORD(i,d) \ +do { \ + ieee_double_shape_type gl_u; \ + gl_u.value = (d); \ + (i) = gl_u.parts.lsw; \ +} while (0) + +/* Set a double from two 32 bit ints. */ + +#define INSERT_WORDS(d,ix0,ix1) \ +do { \ + ieee_double_shape_type iw_u; \ + iw_u.parts.msw = (ix0); \ + iw_u.parts.lsw = (ix1); \ + (d) = iw_u.value; \ +} while (0) + +/* Set the more significant 32 bits of a double from an int. */ + +#define SET_HIGH_WORD(d,v) \ +do { \ + ieee_double_shape_type sh_u; \ + sh_u.value = (d); \ + sh_u.parts.msw = (v); \ + (d) = sh_u.value; \ +} while (0) + +/* Set the less significant 32 bits of a double from an int. */ + +#define SET_LOW_WORD(d,v) \ +do { \ + ieee_double_shape_type sl_u; \ + sl_u.value = (d); \ + sl_u.parts.lsw = (v); \ + (d) = sl_u.value; \ +} while (0) + +/* A union which permits us to convert between a float and a 32 bit + int. */ + +typedef union +{ + float value; + u_int32_t word; +} ieee_float_shape_type; + +/* Get a 32 bit int from a float. */ + +#define GET_FLOAT_WORD(i,d) \ +do { \ + ieee_float_shape_type gf_u; \ + gf_u.value = (d); \ + (i) = gf_u.word; \ +} while (0) + +/* Set a float from a 32 bit int. */ + +#define SET_FLOAT_WORD(d,i) \ +do { \ + ieee_float_shape_type sf_u; \ + sf_u.word = (i); \ + (d) = sf_u.value; \ +} while (0) + +/* ieee style elementary functions */ +extern double __ieee754_sqrt (double) attribute_hidden; +extern double __ieee754_acos (double) attribute_hidden; +extern double __ieee754_acosh (double) attribute_hidden; +extern double __ieee754_log (double) attribute_hidden; +extern double __ieee754_log2 (double) attribute_hidden; +extern double __ieee754_atanh (double) attribute_hidden; +extern double __ieee754_asin (double) attribute_hidden; +extern double __ieee754_atan2 (double,double) attribute_hidden; +extern double __ieee754_exp (double) attribute_hidden; +extern double __ieee754_cosh (double) attribute_hidden; +extern double __ieee754_fmod (double,double) attribute_hidden; +extern double __ieee754_pow (double,double) attribute_hidden; +extern double __ieee754_lgamma_r (double,int *) attribute_hidden; +/*extern double __ieee754_gamma_r (double,int *) attribute_hidden;*/ +extern double __ieee754_lgamma (double) attribute_hidden; +/*extern double __ieee754_gamma (double) attribute_hidden;*/ +extern double __ieee754_log10 (double) attribute_hidden; +extern double __ieee754_sinh (double) attribute_hidden; +extern double __ieee754_hypot (double,double) attribute_hidden; +extern double __ieee754_j0 (double) attribute_hidden; +extern double __ieee754_j1 (double) attribute_hidden; +extern double __ieee754_y0 (double) attribute_hidden; +extern double __ieee754_y1 (double) attribute_hidden; +extern double __ieee754_jn (int,double) attribute_hidden; +extern double __ieee754_yn (int,double) attribute_hidden; +extern double __ieee754_remainder (double,double) attribute_hidden; +extern int __ieee754_rem_pio2 (double,double*) attribute_hidden; +extern double __ieee754_scalb (double,double) attribute_hidden; + +/* fdlibm kernel function */ +#ifndef _IEEE_LIBM +extern double __kernel_standard (double,double,int) attribute_hidden; +#endif +extern double __kernel_sin (double,double,int) attribute_hidden; +extern double __kernel_cos (double,double) attribute_hidden; +extern double __kernel_tan (double,double,int) attribute_hidden; +extern int __kernel_rem_pio2 (double*,double*,int,int,int,const int*) attribute_hidden; + +/* + * math_opt_barrier(x): safely load x, even if it was manipulated + * by non-floationg point operations. This macro returns the value of x. + * This ensures compiler does not (ab)use its knowledge about x value + * and don't optimize future operations. Example: + * float x; + * SET_FLOAT_WORD(x, 0x80000001); // sets a bit pattern + * y = math_opt_barrier(x); // "compiler, do not cheat!" + * y = y * y; // compiler can't optimize, must use real multiply insn + * + * math_force_eval(x): force expression x to be evaluated. + * Useful if otherwise compiler may eliminate the expression + * as unused. This macro returns no value. + * Example: "void fn(float f) { f = f * f; }" + * versus "void fn(float f) { f = f * f; math_force_eval(f); }" + * + * Currently, math_force_eval(x) stores x into + * a floating point register or memory *of the appropriate size*. + * There is no guarantee this will not change. + */ +#if defined(__i386__) +#define math_opt_barrier(x) ({ \ + __typeof(x) __x = (x); \ + /* "t": load x into top-of-stack fpreg */ \ + __asm__ ("" : "=t" (__x) : "0" (__x)); \ + __x; \ +}) +#define math_force_eval(x) do { \ + __typeof(x) __x = (x); \ + if (sizeof(__x) <= sizeof(double)) \ + /* "m": store x into a memory location */ \ + __asm__ __volatile__ ("" : : "m" (__x)); \ + else /* long double */ \ + /* "f": load x into (any) fpreg */ \ + __asm__ __volatile__ ("" : : "f" (__x)); \ +} while (0) +#endif + +#if defined(__x86_64__) +#define math_opt_barrier(x) ({ \ + __typeof(x) __x = (x); \ + if (sizeof(__x) <= sizeof(double)) \ + /* "x": load into XMM SSE register */ \ + __asm__ ("" : "=x" (__x) : "0" (__x)); \ + else /* long double */ \ + /* "t": load x into top-of-stack fpreg */ \ + __asm__ ("" : "=t" (__x) : "0" (__x)); \ + __x; \ +}) +#define math_force_eval(x) do { \ + __typeof(x) __x = (x); \ + if (sizeof(__x) <= sizeof(double)) \ + /* "x": load into XMM SSE register */ \ + __asm__ __volatile__ ("" : : "x" (__x)); \ + else /* long double */ \ + /* "f": load x into (any) fpreg */ \ + __asm__ __volatile__ ("" : : "f" (__x)); \ +} while (0) +#endif + +/* Default implementations force store to a memory location */ +#ifndef math_opt_barrier +#define math_opt_barrier(x) ({ __typeof(x) __x = (x); __asm__ ("" : "+m" (__x)); __x; }) +#endif +#ifndef math_force_eval +#define math_force_eval(x) do { __typeof(x) __x = (x); __asm__ __volatile__ ("" : : "m" (__x)); } while (0) +#endif + + +#endif /* _MATH_PRIVATE_H_ */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/nan.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/nan.c new file mode 100644 index 00000000..eee3b1cc --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/nan.c @@ -0,0 +1,60 @@ +/* vi: set sw=4 ts=4: */ +/* + * Copyright (C) 2002 by Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/*********************************************************************** + nan, nanf, nanl - return quiet NaN + + These functions shall return a quiet NaN, if available, with content + indicated through tagp. + + If the implementation does not support quiet NaNs, these functions + shall return zero. + + Calls: strlen(), sprintf(), strtod() + +***********************************************************************/ +#include +#include +#include +#include + +double nan (const char *tagp) +{ + if (tagp[0] != '\0') { + char buf[6 + strlen (tagp)]; + sprintf (buf, "NAN(%s)", tagp); + return strtod (buf, NULL); + } + return NAN; +} +libm_hidden_def(nan) + +libm_hidden_proto(nanf) +float nanf (const char *tagp) +{ + if (tagp[0] != '\0') { + char buf[6 + strlen (tagp)]; + sprintf (buf, "NAN(%s)", tagp); + return strtof (buf, NULL); + } + return NAN; +} +libm_hidden_def(nanf) + +#if defined __UCLIBC_HAS_LONG_DOUBLE_MATH__ && !defined __NO_LONG_DOUBLE_MATH +libm_hidden_proto(nanl) +long double nanl (const char *tagp) +{ + if (tagp[0] != '\0') { + char buf[6 + strlen (tagp)]; + sprintf (buf, "NAN(%s)", tagp); + return strtold (buf, NULL); + } + return NAN; +} +libm_hidden_def(nanl) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/powerpc/classic/Makefile.arch b/l4/pkg/uclibc/lib/contrib/uclibc/libm/powerpc/classic/Makefile.arch new file mode 100644 index 00000000..53c6d2ca --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/powerpc/classic/Makefile.arch @@ -0,0 +1,18 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2006 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +libm_ARCH_SRC:=$(wildcard $(libm_SUBARCH_DIR)/*.c) +libm_ARCH_OBJ:=$(patsubst $(libm_SUBARCH_DIR)/%.c,$(libm_SUBARCH_OUT)/%.o,$(libm_ARCH_SRC)) + +libm_ARCH_OBJS:=$(libm_ARCH_OBJ) + +ifeq ($(DOPIC),y) +libm-a-y+=$(libm_ARCH_OBJS:.o=.os) +else +libm-a-y+=$(libm_ARCH_OBJS) +endif +libm-so-y+=$(libm_ARCH_OBJS:.o=.os) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/powerpc/e500/Makefile.arch b/l4/pkg/uclibc/lib/contrib/uclibc/libm/powerpc/e500/Makefile.arch new file mode 100644 index 00000000..912ce7f1 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/powerpc/e500/Makefile.arch @@ -0,0 +1,10 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2006 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +libm_ARCH_fpu_DIR := $(libm_SUBARCH_DIR)/fpu +-include $(libm_ARCH_fpu_DIR)/Makefile.arch + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/powerpc/e500/README.txt b/l4/pkg/uclibc/lib/contrib/uclibc/libm/powerpc/e500/README.txt new file mode 100644 index 00000000..354d7921 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/powerpc/e500/README.txt @@ -0,0 +1,8 @@ +The routines this math library have been derived from the e500 math +library in eglibc. The original e500 port to glibc was done by +Aldy Hernandez, , and the port to eglibc was done by +Joseph S. Myers, + +It has been ported to uClibc by Steve Papacharalambous + 19 December, 2006 + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/powerpc/e500/fpu/Makefile.arch b/l4/pkg/uclibc/lib/contrib/uclibc/libm/powerpc/e500/fpu/Makefile.arch new file mode 100644 index 00000000..8f00e091 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/powerpc/e500/fpu/Makefile.arch @@ -0,0 +1,19 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2006 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + + +libm_ARCH_SRC:=$(wildcard $(libm_ARCH_fpu_DIR)/*.c) +libm_ARCH_OBJ:=$(patsubst $(libm_ARCH_fpu_DIR)/%.c,$(libm_ARCH_fpu_OUT)/%.o,$(libm_ARCH_SRC)) + +libm_ARCH_OBJS:=$(libm_ARCH_OBJ) + +ifeq ($(DOPIC),y) +libm-a-y+=$(libm_ARCH_OBJS:.o=.os) +else +libm-a-y+=$(libm_ARCH_OBJS) +endif +libm-so-y+=$(libm_ARCH_OBJS:.o=.os) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/powerpc/e500/fpu/fclrexcpt.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/powerpc/e500/fpu/fclrexcpt.c new file mode 100644 index 00000000..42e8b6ba --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/powerpc/e500/fpu/fclrexcpt.c @@ -0,0 +1,39 @@ +/* Clear given exceptions in current floating-point environment. + Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "fenv_libc.h" +#undef feclearexcept +int +__feclearexcept (int excepts) +{ + unsigned int fpescr; + + /* Get the current state. */ + fpescr = fegetenv_register (); + + /* Clear the relevant bits. */ + fpescr &= ~(excepts & FE_ALL_EXCEPT); + + /* Put the new state in effect. */ + fesetenv_register (fpescr); + + /* Success. */ + return 0; +} + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/powerpc/e500/fpu/fe_nomask.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/powerpc/e500/fpu/fe_nomask.c new file mode 100644 index 00000000..ad7b324c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/powerpc/e500/fpu/fe_nomask.c @@ -0,0 +1,32 @@ +/* Procedure definition for FE_NOMASK_ENV. + Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +/* This is presently a stub, until it's decided how the kernels should + support this. */ + +const fenv_t * +__fe_nomask_env(void) +{ + __set_errno (ENOSYS); + return FE_ENABLED_ENV; +} + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/powerpc/e500/fpu/fedisblxcpt.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/powerpc/e500/fpu/fedisblxcpt.c new file mode 100644 index 00000000..aeca87bc --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/powerpc/e500/fpu/fedisblxcpt.c @@ -0,0 +1,60 @@ +/* Disable floating-point exceptions. + Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Aldy Hernandez , 2004. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "fenv_libc.h" +#include +#include + +int +fedisableexcept (int excepts) +{ + unsigned int result = 0, pflags, r; + INTERNAL_SYSCALL_DECL (err); + + INTERNAL_SYSCALL (prctl, err, 2, PR_GET_FPEXC, &pflags); + + /* Save old enable bits. */ + if (pflags & PR_FP_EXC_OVF) + result |= FE_OVERFLOW; + if (pflags & PR_FP_EXC_UND) + result |= FE_UNDERFLOW; + if (pflags & PR_FP_EXC_INV) + result |= FE_INVALID; + if (pflags & PR_FP_EXC_DIV) + result |= FE_DIVBYZERO; + if (pflags & PR_FP_EXC_RES) + result |= FE_INEXACT; + + if (excepts & FE_INEXACT) + pflags &= ~PR_FP_EXC_RES; + if (excepts & FE_DIVBYZERO) + pflags &= ~PR_FP_EXC_DIV; + if (excepts & FE_UNDERFLOW) + pflags &= ~PR_FP_EXC_UND; + if (excepts & FE_OVERFLOW) + pflags &= ~PR_FP_EXC_OVF; + if (excepts & FE_INVALID) + pflags &= ~PR_FP_EXC_INV; + r = INTERNAL_SYSCALL (prctl, err, 2, PR_SET_FPEXC, pflags); + if (INTERNAL_SYSCALL_ERROR_P (r, err)) + return -1; + + return result; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/powerpc/e500/fpu/feenablxcpt.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/powerpc/e500/fpu/feenablxcpt.c new file mode 100644 index 00000000..999fdd73 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/powerpc/e500/fpu/feenablxcpt.c @@ -0,0 +1,60 @@ +/* Enable floating-point exceptions. + Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Aldy Hernandez , 2004. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "fenv_libc.h" +#include +#include + +int +feenableexcept (int excepts) +{ + unsigned int result = 0, pflags, r; + INTERNAL_SYSCALL_DECL (err); + + INTERNAL_SYSCALL (prctl, err, 2, PR_GET_FPEXC, &pflags); + + /* Save old enable bits. */ + if (pflags & PR_FP_EXC_OVF) + result |= FE_OVERFLOW; + if (pflags & PR_FP_EXC_UND) + result |= FE_UNDERFLOW; + if (pflags & PR_FP_EXC_INV) + result |= FE_INVALID; + if (pflags & PR_FP_EXC_DIV) + result |= FE_DIVBYZERO; + if (pflags & PR_FP_EXC_RES) + result |= FE_INEXACT; + + if (excepts & FE_INEXACT) + pflags |= PR_FP_EXC_RES; + if (excepts & FE_DIVBYZERO) + pflags |= PR_FP_EXC_DIV; + if (excepts & FE_UNDERFLOW) + pflags |= PR_FP_EXC_UND; + if (excepts & FE_OVERFLOW) + pflags |= PR_FP_EXC_OVF; + if (excepts & FE_INVALID) + pflags |= PR_FP_EXC_INV; + r = INTERNAL_SYSCALL (prctl, err, 2, PR_SET_FPEXC, pflags); + if (INTERNAL_SYSCALL_ERROR_P (r, err)) + return -1; + + return result; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/powerpc/e500/fpu/fegetenv.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/powerpc/e500/fpu/fegetenv.c new file mode 100644 index 00000000..fbafdc20 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/powerpc/e500/fpu/fegetenv.c @@ -0,0 +1,38 @@ +/* Store current floating-point environment. + Copyright (C) 2004 Free Software Foundation, Inc. + Contributed by Aldy Hernandez , 2004 + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "fenv_libc.h" +#include +#include + +int +__fegetenv (fenv_t *envp) +{ + fenv_union_t u; + INTERNAL_SYSCALL_DECL (err); + + INTERNAL_SYSCALL (prctl, err, 2, PR_GET_FPEXC, &u.l[0]); + u.l[1] = fegetenv_register (); + *envp = u.fenv; + + /* Success. */ + return 0; +} + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/powerpc/e500/fpu/fegetexcept.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/powerpc/e500/fpu/fegetexcept.c new file mode 100644 index 00000000..c0398461 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/powerpc/e500/fpu/fegetexcept.c @@ -0,0 +1,31 @@ +/* Get floating-point exceptions. + Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Aldy Hernandez , 2004. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "fenv_libc.h" + +int +fegetexcept (void) +{ + unsigned long fpescr; + + fpescr = fegetenv_register (); + + return fpescr & FE_ALL_EXCEPT; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/powerpc/e500/fpu/fegetround.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/powerpc/e500/fpu/fegetround.c new file mode 100644 index 00000000..6e568fa2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/powerpc/e500/fpu/fegetround.c @@ -0,0 +1,31 @@ +/* Return current rounding direction. + Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Aldy Hernandez , 2004. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "fenv_libc.h" + +#undef fegetround +int +fegetround (void) +{ + unsigned long fpescr; + + fpescr = fegetenv_register (); + return fpescr & 3; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/powerpc/e500/fpu/feholdexcpt.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/powerpc/e500/fpu/feholdexcpt.c new file mode 100644 index 00000000..eccde421 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/powerpc/e500/fpu/feholdexcpt.c @@ -0,0 +1,45 @@ +/* Store current floating-point environment and clear exceptions. + Copyright (C) 2004, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Aldy Hernandez , 2004. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "fenv_libc.h" +#include +#include + +int +feholdexcept (fenv_t *envp) +{ + fenv_union_t u; + INTERNAL_SYSCALL_DECL (err); + + + /* Get the current state. */ + INTERNAL_SYSCALL (prctl, err, 2, PR_GET_FPEXC, &u.l[0]); + u.l[1] = fegetenv_register (); + *envp = u.fenv; + + /* Clear everything except for the rounding mode. */ + u.l[1] &= 3; + + /* Put the new state in effect. */ + fesetenv_register (u.l[1]); + + return 0; +} +libm_hidden_def (feholdexcept) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/powerpc/e500/fpu/fenv_const.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/powerpc/e500/fpu/fenv_const.c new file mode 100644 index 00000000..073fc927 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/powerpc/e500/fpu/fenv_const.c @@ -0,0 +1,27 @@ +/* Constants for fenv_bits.h. + Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Aldy Hernandez , 2004. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* If the default argument is used we use this value. */ +const unsigned long long __fe_dfl_env __attribute__ ((aligned (8))) = +0x0ULL; + +/* Floating-point environment where none of the exceptions are masked. */ +const unsigned long long __fe_enabled_env __attribute__ ((aligned (8))) = +0xF00000000ULL; diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/powerpc/e500/fpu/fenv_libc.h b/l4/pkg/uclibc/lib/contrib/uclibc/libm/powerpc/e500/fpu/fenv_libc.h new file mode 100644 index 00000000..22c3f145 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/powerpc/e500/fpu/fenv_libc.h @@ -0,0 +1,77 @@ +/* Internal libc stuff for floating point environment routines. + Copyright (C) 2004 Free Software Foundation, Inc. + Contributed by Aldy Hernandez , 2004 + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _FENV_LIBC_H +#define _FENV_LIBC_H 1 + +#include + +extern int __feraiseexcept_internal (int __excepts); + +/* Equivalent to fegetenv, but returns a fenv_t instead of taking a + pointer. */ +#define fegetenv_register() \ + ({ unsigned fscr; __asm__ __volatile__ ("mfspefscr %0" : "=r" (fscr)); fscr; }) + +/* Equivalent to fesetenv, but takes a fenv_t instead of a pointer. */ +#define fesetenv_register(fscr) \ + ({ __asm__ __volatile__ ("mtspefscr %0" : : "r" (fscr)); }) + +typedef union +{ + fenv_t fenv; + unsigned int l[2]; +} fenv_union_t; + +/* Definitions of all the SPEFSCR bit numbers. */ +enum { + SPEFSCR_SOVH = 0x80000000, + SPEFSCR_OVH = 0x40000000, + SPEFSCR_FGH = 0x20000000, + SPEFSCR_FXH = 0x10000000, + SPEFSCR_FINVH = 0x08000000, + SPEFSCR_FDBZH = 0x04000000, + SPEFSCR_FUNFH = 0x02000000, + SPEFSCR_FOVFH = 0x01000000, + /* 2 unused bits. */ + SPEFSCR_FINXS = 0x00200000, + SPEFSCR_FINVS = 0x00100000, + SPEFSCR_FDBZS = 0x00080000, + SPEFSCR_FUNFS = 0x00040000, + SPEFSCR_FOVFS = 0x00020000, + SPEFSCR_MODE = 0x00010000, + SPEFSCR_SOV = 0x00008000, + SPEFSCR_OV = 0x00004000, + SPEFSCR_FG = 0x00002000, + SPEFSCR_FX = 0x00001000, + SPEFSCR_FINV = 0x00000800, + SPEFSCR_FDBZ = 0x00000400, + SPEFSCR_FUNF = 0x00000200, + SPEFSCR_FOVF = 0x00000100, + /* 1 unused bit. */ + SPEFSCR_FINXE = 0x00000040, + SPEFSCR_FINVE = 0x00000020, + SPEFSCR_FDBZE = 0x00000010, + SPEFSCR_FUNFE = 0x00000008, + SPEFSCR_FOVFE = 0x00000004, + SPEFSCR_FRMC = 0x00000003 +}; + +#endif /* fenv_libc.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/powerpc/e500/fpu/fesetenv.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/powerpc/e500/fpu/fesetenv.c new file mode 100644 index 00000000..cc0cc18b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/powerpc/e500/fpu/fesetenv.c @@ -0,0 +1,38 @@ +/* Install given floating-point environment. + Copyright (C) 1997,99,2000,01,02 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "fenv_libc.h" +#include +#include + +int +__fesetenv (const fenv_t *envp) +{ + fenv_union_t u; + INTERNAL_SYSCALL_DECL (err); + + u.fenv = *envp; + INTERNAL_SYSCALL (prctl, err, 2, PR_SET_FPEXC, &u.l[0]); + fesetenv_register (u.l[1]); + + /* Success. */ + return 0; +} + +libm_hidden_ver (__fesetenv, fesetenv) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/powerpc/e500/fpu/fesetround.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/powerpc/e500/fpu/fesetround.c new file mode 100644 index 00000000..0f29a91a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/powerpc/e500/fpu/fesetround.c @@ -0,0 +1,37 @@ +/* Set current rounding direction. + Copyright (C) 2004, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Aldy Hernandez , 2004. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "fenv_libc.h" + +int +fesetround (int round) +{ + unsigned long fpescr; + + if ((unsigned int) round > 3) + return 1; + + fpescr = fegetenv_register (); + fpescr = (fpescr & ~SPEFSCR_FRMC) | (round & 3); + fesetenv_register (fpescr); + + return 0; +} +libm_hidden_def (fesetround) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/powerpc/e500/fpu/feupdateenv.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/powerpc/e500/fpu/feupdateenv.c new file mode 100644 index 00000000..03f3af8d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/powerpc/e500/fpu/feupdateenv.c @@ -0,0 +1,49 @@ +/* Install given floating-point environment and raise exceptions. + Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Aldy Hernandez , 2004. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "fenv_libc.h" +#include +#include + +int +__feupdateenv (const fenv_t *envp) +{ + unsigned long fpescr, old, new, pflags; + fenv_union_t u; + INTERNAL_SYSCALL_DECL (err); + + /* Save the currently set exceptions. */ + u.fenv = *envp; + new = u.l[1]; + old = fegetenv_register (); + new |= (old & FE_ALL_EXCEPT); + + INTERNAL_SYSCALL (prctl, err, 2, PR_GET_FPEXC, &pflags); + pflags |= u.l[0]; + INTERNAL_SYSCALL (prctl, err, 2, PR_SET_FPEXC, pflags); + + /* Enable and raise (if appropriate) exceptions set in `new'. */ + fesetenv_register (new); + feraiseexcept (new & FE_ALL_EXCEPT); + + /* Success. */ + return 0; +} + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/powerpc/e500/fpu/fgetexcptflg.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/powerpc/e500/fpu/fgetexcptflg.c new file mode 100644 index 00000000..62d7f2c3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/powerpc/e500/fpu/fgetexcptflg.c @@ -0,0 +1,39 @@ +/* Store current representation for exceptions. + Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Aldy Hernandez , 2004. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "fenv_libc.h" + +int +__fegetexceptflag (fexcept_t *flagp, int excepts) +{ + unsigned long fpescr; + + /* Get the current state. */ + fpescr = fegetenv_register (); + + /* ?? Classic PPC doesn't do anything with `excepts', so we'll do + the same here. (We should really be ignoring exceptions in + excepts) ?? */ + *flagp = fpescr & FE_ALL_EXCEPT; + + /* Success. */ + return 0; +} + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/powerpc/e500/fpu/fraiseexcpt.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/powerpc/e500/fpu/fraiseexcpt.c new file mode 100644 index 00000000..39caf79d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/powerpc/e500/fpu/fraiseexcpt.c @@ -0,0 +1,29 @@ +/* Raise given exceptions. + Copyright (C) 2004, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Aldy Hernandez , 2004. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "fenv_libc.h" + +#undef feraiseexcept + +#define __FERAISEEXCEPT_INTERNAL feraiseexcept + +#include "../spe-raise.c" + +libm_hidden_def (feraiseexcept) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/powerpc/e500/fpu/fsetexcptflg.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/powerpc/e500/fpu/fsetexcptflg.c new file mode 100644 index 00000000..8e4bb895 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/powerpc/e500/fpu/fsetexcptflg.c @@ -0,0 +1,46 @@ +/* Set floating-point environment exception handling. + Copyright (C) 1997,99,2000,01,04 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "fenv_libc.h" + +int +__fesetexceptflag (const fexcept_t *flagp, int excepts) +{ + unsigned long spefscr; + fexcept_t flag; + + /* Get the current state. */ + spefscr = fegetenv_register (); + + /* Ignore exceptions not listed in 'excepts'. */ + flag = *flagp & excepts; + + /* Replace the exception status */ + spefscr = (spefscr & ~FE_ALL_EXCEPT) | flag; + + /* Store the new status word (along with the rest of the environment). + This may cause floating-point exceptions if the restored state + requests it. */ + fesetenv_register (spefscr); + feraiseexcept (spefscr & FE_ALL_EXCEPT); + + /* Success. */ + return 0; +} + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/powerpc/e500/fpu/ftestexcept.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/powerpc/e500/fpu/ftestexcept.c new file mode 100644 index 00000000..971c5196 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/powerpc/e500/fpu/ftestexcept.c @@ -0,0 +1,32 @@ +/* Test exception in current environment. + Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Aldy Hernandez , 2004. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "fenv_libc.h" + +int +fetestexcept (int excepts) +{ + unsigned long f; + + /* Get the current state. */ + f = fegetenv_register (); + + return f & excepts; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/powerpc/e500/spe-raise.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/powerpc/e500/spe-raise.c new file mode 100644 index 00000000..b83087fd --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/powerpc/e500/spe-raise.c @@ -0,0 +1,67 @@ +/* Raise given exceptions. + Copyright (C) 1997,99,2000,01,02,04 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "fpu/fenv_libc.h" + +int +__FERAISEEXCEPT_INTERNAL (int excepts) +{ + unsigned long f; + + f = fegetenv_register (); + f |= (excepts & FE_ALL_EXCEPT); + fesetenv_register (f); + + /* Force the operations that cause the exceptions. */ + if ((FE_INVALID & excepts) != 0) + { + /* ?? Does not set sticky bit ?? */ + /* 0 / 0 */ + __asm__ __volatile__ ("efsdiv %0,%0,%1" : : "r" (0), "r" (0)); + } + + if ((FE_DIVBYZERO & excepts) != 0) + { + /* 1.0 / 0.0 */ + __asm__ __volatile__ ("efsdiv %0,%0,%1" : : "r" (1.0F), "r" (0)); + } + + if ((FE_OVERFLOW & excepts) != 0) + { + /* ?? Does not set sticky bit ?? */ + /* Largest normalized number plus itself. */ + __asm__ __volatile__ ("efsadd %0,%0,%1" : : "r" (0x7f7fffff), "r" (0x7f7fffff)); + } + + if ((FE_UNDERFLOW & excepts) != 0) + { + /* ?? Does not set sticky bit ?? */ + /* Smallest normalized number times itself. */ + __asm__ __volatile__ ("efsmul %0,%0,%1" : : "r" (0x800000), "r" (0x800000)); + } + + if ((FE_INEXACT & excepts) != 0) + { + /* Smallest normalized minus 1.0 raises the inexact flag. */ + __asm__ __volatile__ ("efssub %0,%0,%1" : : "r" (0x00800000), "r" (1.0F)); + } + + /* Success. */ + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_asinh.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_asinh.c new file mode 100644 index 00000000..7c79d682 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_asinh.c @@ -0,0 +1,52 @@ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* asinh(x) + * Method : + * Based on + * asinh(x) = sign(x) * log [ |x| + sqrt(x*x+1) ] + * we have + * asinh(x) := x if 1+x*x=1, + * := sign(x)*(log(x)+ln2)) for large |x|, else + * := sign(x)*log(2|x|+1/(|x|+sqrt(x*x+1))) if|x|>2, else + * := sign(x)*log1p(|x| + x^2/(1 + sqrt(1+x^2))) + */ + +#include "math.h" +#include "math_private.h" + +static const double +one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */ +ln2 = 6.93147180559945286227e-01, /* 0x3FE62E42, 0xFEFA39EF */ +huge= 1.00000000000000000000e+300; + +double asinh(double x) +{ + double t,w; + int32_t hx,ix; + GET_HIGH_WORD(hx,x); + ix = hx&0x7fffffff; + if(ix>=0x7ff00000) return x+x; /* x is inf or NaN */ + if(ix< 0x3e300000) { /* |x|<2**-28 */ + if(huge+x>one) return x; /* return x inexact except 0 */ + } + if(ix>0x41b00000) { /* |x| > 2**28 */ + w = __ieee754_log(fabs(x))+ln2; + } else if (ix>0x40000000) { /* 2**28 > |x| > 2.0 */ + t = fabs(x); + w = __ieee754_log(2.0*t+one/(__ieee754_sqrt(x*x+one)+t)); + } else { /* 2.0 > |x| > 2**-28 */ + t = x*x; + w =log1p(fabs(x)+t/(one+__ieee754_sqrt(one+t))); + } + if(hx>0) return w; else return -w; +} +libm_hidden_def(asinh) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_atan.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_atan.c new file mode 100644 index 00000000..08cfb08e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_atan.c @@ -0,0 +1,114 @@ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* atan(x) + * Method + * 1. Reduce x to positive by atan(x) = -atan(-x). + * 2. According to the integer k=4t+0.25 chopped, t=x, the argument + * is further reduced to one of the following intervals and the + * arctangent of t is evaluated by the corresponding formula: + * + * [0,7/16] atan(x) = t-t^3*(a1+t^2*(a2+...(a10+t^2*a11)...) + * [7/16,11/16] atan(x) = atan(1/2) + atan( (t-0.5)/(1+t/2) ) + * [11/16.19/16] atan(x) = atan( 1 ) + atan( (t-1)/(1+t) ) + * [19/16,39/16] atan(x) = atan(3/2) + atan( (t-1.5)/(1+1.5t) ) + * [39/16,INF] atan(x) = atan(INF) + atan( -1/t ) + * + * Constants: + * The hexadecimal values are the intended ones for the following + * constants. The decimal values may be used, provided that the + * compiler will convert from decimal to binary accurately enough + * to produce the hexadecimal values shown. + */ + +#include "math.h" +#include "math_private.h" + +static const double atanhi[] = { + 4.63647609000806093515e-01, /* atan(0.5)hi 0x3FDDAC67, 0x0561BB4F */ + 7.85398163397448278999e-01, /* atan(1.0)hi 0x3FE921FB, 0x54442D18 */ + 9.82793723247329054082e-01, /* atan(1.5)hi 0x3FEF730B, 0xD281F69B */ + 1.57079632679489655800e+00, /* atan(inf)hi 0x3FF921FB, 0x54442D18 */ +}; + +static const double atanlo[] = { + 2.26987774529616870924e-17, /* atan(0.5)lo 0x3C7A2B7F, 0x222F65E2 */ + 3.06161699786838301793e-17, /* atan(1.0)lo 0x3C81A626, 0x33145C07 */ + 1.39033110312309984516e-17, /* atan(1.5)lo 0x3C700788, 0x7AF0CBBD */ + 6.12323399573676603587e-17, /* atan(inf)lo 0x3C91A626, 0x33145C07 */ +}; + +static const double aT[] = { + 3.33333333333329318027e-01, /* 0x3FD55555, 0x5555550D */ + -1.99999999998764832476e-01, /* 0xBFC99999, 0x9998EBC4 */ + 1.42857142725034663711e-01, /* 0x3FC24924, 0x920083FF */ + -1.11111104054623557880e-01, /* 0xBFBC71C6, 0xFE231671 */ + 9.09088713343650656196e-02, /* 0x3FB745CD, 0xC54C206E */ + -7.69187620504482999495e-02, /* 0xBFB3B0F2, 0xAF749A6D */ + 6.66107313738753120669e-02, /* 0x3FB10D66, 0xA0D03D51 */ + -5.83357013379057348645e-02, /* 0xBFADDE2D, 0x52DEFD9A */ + 4.97687799461593236017e-02, /* 0x3FA97B4B, 0x24760DEB */ + -3.65315727442169155270e-02, /* 0xBFA2B444, 0x2C6A6C2F */ + 1.62858201153657823623e-02, /* 0x3F90AD3A, 0xE322DA11 */ +}; + +static const double +one = 1.0, +huge = 1.0e300; + +double atan(double x) +{ + double w,s1,s2,z; + int32_t ix,hx,id; + + GET_HIGH_WORD(hx,x); + ix = hx&0x7fffffff; + if(ix>=0x44100000) { /* if |x| >= 2^66 */ + u_int32_t low; + GET_LOW_WORD(low,x); + if(ix>0x7ff00000|| + (ix==0x7ff00000&&(low!=0))) + return x+x; /* NaN */ + if(hx>0) return atanhi[3]+atanlo[3]; + else return -atanhi[3]-atanlo[3]; + } if (ix < 0x3fdc0000) { /* |x| < 0.4375 */ + if (ix < 0x3e200000) { /* |x| < 2^-29 */ + if(huge+x>one) return x; /* raise inexact */ + } + id = -1; + } else { + x = fabs(x); + if (ix < 0x3ff30000) { /* |x| < 1.1875 */ + if (ix < 0x3fe60000) { /* 7/16 <=|x|<11/16 */ + id = 0; x = (2.0*x-one)/(2.0+x); + } else { /* 11/16<=|x|< 19/16 */ + id = 1; x = (x-one)/(x+one); + } + } else { + if (ix < 0x40038000) { /* |x| < 2.4375 */ + id = 2; x = (x-1.5)/(one+1.5*x); + } else { /* 2.4375 <= |x| < 2^66 */ + id = 3; x = -1.0/x; + } + }} + /* end of argument reduction */ + z = x*x; + w = z*z; + /* break sum from i=0 to 10 aT[i]z**(i+1) into odd and even poly */ + s1 = z*(aT[0]+w*(aT[2]+w*(aT[4]+w*(aT[6]+w*(aT[8]+w*aT[10]))))); + s2 = w*(aT[1]+w*(aT[3]+w*(aT[5]+w*(aT[7]+w*aT[9])))); + if (id<0) return x - x*(s1+s2); + else { + z = atanhi[id] - ((x*(s1+s2) - atanlo[id]) - x); + return (hx<0)? -z:z; + } +} +libm_hidden_def(atan) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_cbrt.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_cbrt.c new file mode 100644 index 00000000..14e8ab02 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_cbrt.c @@ -0,0 +1,76 @@ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +#include "math.h" +#include "math_private.h" + +/* cbrt(x) + * Return cube root of x + */ +static const u_int32_t + B1 = 715094163, /* B1 = (682-0.03306235651)*2**20 */ + B2 = 696219795; /* B2 = (664-0.03306235651)*2**20 */ + +static const double +C = 5.42857142857142815906e-01, /* 19/35 = 0x3FE15F15, 0xF15F15F1 */ +D = -7.05306122448979611050e-01, /* -864/1225 = 0xBFE691DE, 0x2532C834 */ +E = 1.41428571428571436819e+00, /* 99/70 = 0x3FF6A0EA, 0x0EA0EA0F */ +F = 1.60714285714285720630e+00, /* 45/28 = 0x3FF9B6DB, 0x6DB6DB6E */ +G = 3.57142857142857150787e-01; /* 5/14 = 0x3FD6DB6D, 0xB6DB6DB7 */ + +double cbrt(double x) +{ + int32_t hx; + double r,s,t=0.0,w; + u_int32_t sign; + u_int32_t high,low; + + GET_HIGH_WORD(hx,x); + sign=hx&0x80000000; /* sign= sign(x) */ + hx ^=sign; + if(hx>=0x7ff00000) return(x+x); /* cbrt(NaN,INF) is itself */ + GET_LOW_WORD(low,x); + if((hx|low)==0) + return(x); /* cbrt(0) is itself */ + + SET_HIGH_WORD(x,hx); /* x <- |x| */ + /* rough cbrt to 5 bits */ + if(hx<0x00100000) /* subnormal number */ + {SET_HIGH_WORD(t,0x43500000); /* set t= 2**54 */ + t*=x; GET_HIGH_WORD(high,t); SET_HIGH_WORD(t,high/3+B2); + } + else + SET_HIGH_WORD(t,hx/3+B1); + + + /* new cbrt to 23 bits, may be implemented in single precision */ + r=t*t/x; + s=C+r*t; + t*=G+F/(s+E+D/s); + + /* chopped to 20 bits and make it larger than cbrt(x) */ + GET_HIGH_WORD(high,t); + INSERT_WORDS(t,high+0x00000001,0); + + + /* one step newton iteration to 53 bits with error less than 0.667 ulps */ + s=t*t; /* t*t is exact */ + r=x/s; + w=t+t; + r=(r-t)/(w+r); /* r-s is exact */ + t=t+t*r; + + /* retore the sign bit */ + GET_HIGH_WORD(high,t); + SET_HIGH_WORD(t,high|sign); + return(t); +} +libm_hidden_def(cbrt) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_ceil.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_ceil.c new file mode 100644 index 00000000..ad0916ea --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_ceil.c @@ -0,0 +1,70 @@ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* + * ceil(x) + * Return x rounded toward -inf to integral value + * Method: + * Bit twiddling. + * Exception: + * Inexact flag raised if x not equal to ceil(x). + */ + +#include +/* Prevent math.h from defining a colliding inline */ +#undef __USE_EXTERN_INLINES +#include "math.h" +#include "math_private.h" + +static const double huge = 1.0e300; + +double ceil(double x) +{ + int32_t i0,i1,j0; + u_int32_t i,j; + EXTRACT_WORDS(i0,i1,x); + j0 = ((i0>>20)&0x7ff)-0x3ff; + if(j0<20) { + if(j0<0) { /* raise inexact if x != 0 */ + if(huge+x>0.0) {/* return 0*sign(x) if |x|<1 */ + if(i0<0) {i0=0x80000000;i1=0;} + else if((i0|i1)!=0) { i0=0x3ff00000;i1=0;} + } + } else { + i = (0x000fffff)>>j0; + if(((i0&i)|i1)==0) return x; /* x is integral */ + if(huge+x>0.0) { /* raise inexact flag */ + if(i0>0) i0 += (0x00100000)>>j0; + i0 &= (~i); i1=0; + } + } + } else if (j0>51) { + if(j0==0x400) return x+x; /* inf or NaN */ + else return x; /* x is integral */ + } else { + i = ((u_int32_t)(0xffffffff))>>(j0-20); + if((i1&i)==0) return x; /* x is integral */ + if(huge+x>0.0) { /* raise inexact flag */ + if(i0>0) { + if(j0==20) i0+=1; + else { + j = i1 + (1<<(52-j0)); + if(j=0x7ff00000) return x-x; + + /* argument reduction needed */ + else { + n = __ieee754_rem_pio2(x,y); + switch(n&3) { + case 0: return __kernel_cos(y[0],y[1]); + case 1: return -__kernel_sin(y[0],y[1],1); + case 2: return -__kernel_cos(y[0],y[1]); + default: + return __kernel_sin(y[0],y[1],1); + } + } +} +libm_hidden_def(cos) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_erf.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_erf.c new file mode 100644 index 00000000..27083d24 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_erf.c @@ -0,0 +1,296 @@ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* double erf(double x) + * double erfc(double x) + * x + * 2 |\ + * erf(x) = --------- | exp(-t*t)dt + * sqrt(pi) \| + * 0 + * + * erfc(x) = 1-erf(x) + * Note that + * erf(-x) = -erf(x) + * erfc(-x) = 2 - erfc(x) + * + * Method: + * 1. For |x| in [0, 0.84375] + * erf(x) = x + x*R(x^2) + * erfc(x) = 1 - erf(x) if x in [-.84375,0.25] + * = 0.5 + ((0.5-x)-x*R) if x in [0.25,0.84375] + * where R = P/Q where P is an odd poly of degree 8 and + * Q is an odd poly of degree 10. + * -57.90 + * | R - (erf(x)-x)/x | <= 2 + * + * + * Remark. The formula is derived by noting + * erf(x) = (2/sqrt(pi))*(x - x^3/3 + x^5/10 - x^7/42 + ....) + * and that + * 2/sqrt(pi) = 1.128379167095512573896158903121545171688 + * is close to one. The interval is chosen because the fix + * point of erf(x) is near 0.6174 (i.e., erf(x)=x when x is + * near 0.6174), and by some experiment, 0.84375 is chosen to + * guarantee the error is less than one ulp for erf. + * + * 2. For |x| in [0.84375,1.25], let s = |x| - 1, and + * c = 0.84506291151 rounded to single (24 bits) + * erf(x) = sign(x) * (c + P1(s)/Q1(s)) + * erfc(x) = (1-c) - P1(s)/Q1(s) if x > 0 + * 1+(c+P1(s)/Q1(s)) if x < 0 + * |P1/Q1 - (erf(|x|)-c)| <= 2**-59.06 + * Remark: here we use the taylor series expansion at x=1. + * erf(1+s) = erf(1) + s*Poly(s) + * = 0.845.. + P1(s)/Q1(s) + * That is, we use rational approximation to approximate + * erf(1+s) - (c = (single)0.84506291151) + * Note that |P1/Q1|< 0.078 for x in [0.84375,1.25] + * where + * P1(s) = degree 6 poly in s + * Q1(s) = degree 6 poly in s + * + * 3. For x in [1.25,1/0.35(~2.857143)], + * erfc(x) = (1/x)*exp(-x*x-0.5625+R1/S1) + * erf(x) = 1 - erfc(x) + * where + * R1(z) = degree 7 poly in z, (z=1/x^2) + * S1(z) = degree 8 poly in z + * + * 4. For x in [1/0.35,28] + * erfc(x) = (1/x)*exp(-x*x-0.5625+R2/S2) if x > 0 + * = 2.0 - (1/x)*exp(-x*x-0.5625+R2/S2) if -6 x >= 28 + * erf(x) = sign(x) *(1 - tiny) (raise inexact) + * erfc(x) = tiny*tiny (raise underflow) if x > 0 + * = 2 - tiny if x<0 + * + * 7. Special case: + * erf(0) = 0, erf(inf) = 1, erf(-inf) = -1, + * erfc(0) = 1, erfc(inf) = 0, erfc(-inf) = 2, + * erfc/erf(NaN) is NaN + */ + +#include "math.h" +#include "math_private.h" + +static const double +tiny = 1e-300, +half= 5.00000000000000000000e-01, /* 0x3FE00000, 0x00000000 */ +one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */ +two = 2.00000000000000000000e+00, /* 0x40000000, 0x00000000 */ + /* c = (float)0.84506291151 */ +erx = 8.45062911510467529297e-01, /* 0x3FEB0AC1, 0x60000000 */ +/* + * Coefficients for approximation to erf on [0,0.84375] + */ +efx = 1.28379167095512586316e-01, /* 0x3FC06EBA, 0x8214DB69 */ +efx8= 1.02703333676410069053e+00, /* 0x3FF06EBA, 0x8214DB69 */ +pp0 = 1.28379167095512558561e-01, /* 0x3FC06EBA, 0x8214DB68 */ +pp1 = -3.25042107247001499370e-01, /* 0xBFD4CD7D, 0x691CB913 */ +pp2 = -2.84817495755985104766e-02, /* 0xBF9D2A51, 0xDBD7194F */ +pp3 = -5.77027029648944159157e-03, /* 0xBF77A291, 0x236668E4 */ +pp4 = -2.37630166566501626084e-05, /* 0xBEF8EAD6, 0x120016AC */ +qq1 = 3.97917223959155352819e-01, /* 0x3FD97779, 0xCDDADC09 */ +qq2 = 6.50222499887672944485e-02, /* 0x3FB0A54C, 0x5536CEBA */ +qq3 = 5.08130628187576562776e-03, /* 0x3F74D022, 0xC4D36B0F */ +qq4 = 1.32494738004321644526e-04, /* 0x3F215DC9, 0x221C1A10 */ +qq5 = -3.96022827877536812320e-06, /* 0xBED09C43, 0x42A26120 */ +/* + * Coefficients for approximation to erf in [0.84375,1.25] + */ +pa0 = -2.36211856075265944077e-03, /* 0xBF6359B8, 0xBEF77538 */ +pa1 = 4.14856118683748331666e-01, /* 0x3FDA8D00, 0xAD92B34D */ +pa2 = -3.72207876035701323847e-01, /* 0xBFD7D240, 0xFBB8C3F1 */ +pa3 = 3.18346619901161753674e-01, /* 0x3FD45FCA, 0x805120E4 */ +pa4 = -1.10894694282396677476e-01, /* 0xBFBC6398, 0x3D3E28EC */ +pa5 = 3.54783043256182359371e-02, /* 0x3FA22A36, 0x599795EB */ +pa6 = -2.16637559486879084300e-03, /* 0xBF61BF38, 0x0A96073F */ +qa1 = 1.06420880400844228286e-01, /* 0x3FBB3E66, 0x18EEE323 */ +qa2 = 5.40397917702171048937e-01, /* 0x3FE14AF0, 0x92EB6F33 */ +qa3 = 7.18286544141962662868e-02, /* 0x3FB2635C, 0xD99FE9A7 */ +qa4 = 1.26171219808761642112e-01, /* 0x3FC02660, 0xE763351F */ +qa5 = 1.36370839120290507362e-02, /* 0x3F8BEDC2, 0x6B51DD1C */ +qa6 = 1.19844998467991074170e-02, /* 0x3F888B54, 0x5735151D */ +/* + * Coefficients for approximation to erfc in [1.25,1/0.35] + */ +ra0 = -9.86494403484714822705e-03, /* 0xBF843412, 0x600D6435 */ +ra1 = -6.93858572707181764372e-01, /* 0xBFE63416, 0xE4BA7360 */ +ra2 = -1.05586262253232909814e+01, /* 0xC0251E04, 0x41B0E726 */ +ra3 = -6.23753324503260060396e+01, /* 0xC04F300A, 0xE4CBA38D */ +ra4 = -1.62396669462573470355e+02, /* 0xC0644CB1, 0x84282266 */ +ra5 = -1.84605092906711035994e+02, /* 0xC067135C, 0xEBCCABB2 */ +ra6 = -8.12874355063065934246e+01, /* 0xC0545265, 0x57E4D2F2 */ +ra7 = -9.81432934416914548592e+00, /* 0xC023A0EF, 0xC69AC25C */ +sa1 = 1.96512716674392571292e+01, /* 0x4033A6B9, 0xBD707687 */ +sa2 = 1.37657754143519042600e+02, /* 0x4061350C, 0x526AE721 */ +sa3 = 4.34565877475229228821e+02, /* 0x407B290D, 0xD58A1A71 */ +sa4 = 6.45387271733267880336e+02, /* 0x40842B19, 0x21EC2868 */ +sa5 = 4.29008140027567833386e+02, /* 0x407AD021, 0x57700314 */ +sa6 = 1.08635005541779435134e+02, /* 0x405B28A3, 0xEE48AE2C */ +sa7 = 6.57024977031928170135e+00, /* 0x401A47EF, 0x8E484A93 */ +sa8 = -6.04244152148580987438e-02, /* 0xBFAEEFF2, 0xEE749A62 */ +/* + * Coefficients for approximation to erfc in [1/.35,28] + */ +rb0 = -9.86494292470009928597e-03, /* 0xBF843412, 0x39E86F4A */ +rb1 = -7.99283237680523006574e-01, /* 0xBFE993BA, 0x70C285DE */ +rb2 = -1.77579549177547519889e+01, /* 0xC031C209, 0x555F995A */ +rb3 = -1.60636384855821916062e+02, /* 0xC064145D, 0x43C5ED98 */ +rb4 = -6.37566443368389627722e+02, /* 0xC083EC88, 0x1375F228 */ +rb5 = -1.02509513161107724954e+03, /* 0xC0900461, 0x6A2E5992 */ +rb6 = -4.83519191608651397019e+02, /* 0xC07E384E, 0x9BDC383F */ +sb1 = 3.03380607434824582924e+01, /* 0x403E568B, 0x261D5190 */ +sb2 = 3.25792512996573918826e+02, /* 0x40745CAE, 0x221B9F0A */ +sb3 = 1.53672958608443695994e+03, /* 0x409802EB, 0x189D5118 */ +sb4 = 3.19985821950859553908e+03, /* 0x40A8FFB7, 0x688C246A */ +sb5 = 2.55305040643316442583e+03, /* 0x40A3F219, 0xCEDF3BE6 */ +sb6 = 4.74528541206955367215e+02, /* 0x407DA874, 0xE79FE763 */ +sb7 = -2.24409524465858183362e+01; /* 0xC03670E2, 0x42712D62 */ + +double erf(double x) +{ + int32_t hx,ix,i; + double R,S,P,Q,s,y,z,r; + GET_HIGH_WORD(hx,x); + ix = hx&0x7fffffff; + if(ix>=0x7ff00000) { /* erf(nan)=nan */ + i = ((u_int32_t)hx>>31)<<1; + return (double)(1-i)+one/x; /* erf(+-inf)=+-1 */ + } + + if(ix < 0x3feb0000) { /* |x|<0.84375 */ + if(ix < 0x3e300000) { /* |x|<2**-28 */ + if (ix < 0x00800000) + return 0.125*(8.0*x+efx8*x); /*avoid underflow */ + return x + efx*x; + } + z = x*x; + r = pp0+z*(pp1+z*(pp2+z*(pp3+z*pp4))); + s = one+z*(qq1+z*(qq2+z*(qq3+z*(qq4+z*qq5)))); + y = r/s; + return x + x*y; + } + if(ix < 0x3ff40000) { /* 0.84375 <= |x| < 1.25 */ + s = fabs(x)-one; + P = pa0+s*(pa1+s*(pa2+s*(pa3+s*(pa4+s*(pa5+s*pa6))))); + Q = one+s*(qa1+s*(qa2+s*(qa3+s*(qa4+s*(qa5+s*qa6))))); + if(hx>=0) return erx + P/Q; else return -erx - P/Q; + } + if (ix >= 0x40180000) { /* inf>|x|>=6 */ + if(hx>=0) return one-tiny; else return tiny-one; + } + x = fabs(x); + s = one/(x*x); + if(ix< 0x4006DB6E) { /* |x| < 1/0.35 */ + R=ra0+s*(ra1+s*(ra2+s*(ra3+s*(ra4+s*( + ra5+s*(ra6+s*ra7)))))); + S=one+s*(sa1+s*(sa2+s*(sa3+s*(sa4+s*( + sa5+s*(sa6+s*(sa7+s*sa8))))))); + } else { /* |x| >= 1/0.35 */ + R=rb0+s*(rb1+s*(rb2+s*(rb3+s*(rb4+s*( + rb5+s*rb6))))); + S=one+s*(sb1+s*(sb2+s*(sb3+s*(sb4+s*( + sb5+s*(sb6+s*sb7)))))); + } + z = x; + SET_LOW_WORD(z,0); + r = __ieee754_exp(-z*z-0.5625)*__ieee754_exp((z-x)*(z+x)+R/S); + if(hx>=0) return one-r/x; else return r/x-one; +} +libm_hidden_def(erf) + +double erfc(double x) +{ + int32_t hx,ix; + double R,S,P,Q,s,y,z,r; + GET_HIGH_WORD(hx,x); + ix = hx&0x7fffffff; + if(ix>=0x7ff00000) { /* erfc(nan)=nan */ + /* erfc(+-inf)=0,2 */ + return (double)(((u_int32_t)hx>>31)<<1)+one/x; + } + + if(ix < 0x3feb0000) { /* |x|<0.84375 */ + if(ix < 0x3c700000) /* |x|<2**-56 */ + return one-x; + z = x*x; + r = pp0+z*(pp1+z*(pp2+z*(pp3+z*pp4))); + s = one+z*(qq1+z*(qq2+z*(qq3+z*(qq4+z*qq5)))); + y = r/s; + if(hx < 0x3fd00000) { /* x<1/4 */ + return one-(x+x*y); + } else { + r = x*y; + r += (x-half); + return half - r ; + } + } + if(ix < 0x3ff40000) { /* 0.84375 <= |x| < 1.25 */ + s = fabs(x)-one; + P = pa0+s*(pa1+s*(pa2+s*(pa3+s*(pa4+s*(pa5+s*pa6))))); + Q = one+s*(qa1+s*(qa2+s*(qa3+s*(qa4+s*(qa5+s*qa6))))); + if(hx>=0) { + z = one-erx; return z - P/Q; + } else { + z = erx+P/Q; return one+z; + } + } + if (ix < 0x403c0000) { /* |x|<28 */ + x = fabs(x); + s = one/(x*x); + if(ix< 0x4006DB6D) { /* |x| < 1/.35 ~ 2.857143*/ + R=ra0+s*(ra1+s*(ra2+s*(ra3+s*(ra4+s*( + ra5+s*(ra6+s*ra7)))))); + S=one+s*(sa1+s*(sa2+s*(sa3+s*(sa4+s*( + sa5+s*(sa6+s*(sa7+s*sa8))))))); + } else { /* |x| >= 1/.35 ~ 2.857143 */ + if(hx<0&&ix>=0x40180000) return two-tiny;/* x < -6 */ + R=rb0+s*(rb1+s*(rb2+s*(rb3+s*(rb4+s*( + rb5+s*rb6))))); + S=one+s*(sb1+s*(sb2+s*(sb3+s*(sb4+s*( + sb5+s*(sb6+s*sb7)))))); + } + z = x; + SET_LOW_WORD(z,0); + r = __ieee754_exp(-z*z-0.5625)* + __ieee754_exp((z-x)*(z+x)+R/S); + if(hx>0) return r/x; else return two-r/x; + } else { + if(hx>0) return tiny*tiny; else return two-tiny; + } +} +libm_hidden_def(erfc) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_expm1.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_expm1.c new file mode 100644 index 00000000..8e51ae74 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_expm1.c @@ -0,0 +1,216 @@ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* expm1(x) + * Returns exp(x)-1, the exponential of x minus 1. + * + * Method + * 1. Argument reduction: + * Given x, find r and integer k such that + * + * x = k*ln2 + r, |r| <= 0.5*ln2 ~ 0.34658 + * + * Here a correction term c will be computed to compensate + * the error in r when rounded to a floating-point number. + * + * 2. Approximating expm1(r) by a special rational function on + * the interval [0,0.34658]: + * Since + * r*(exp(r)+1)/(exp(r)-1) = 2+ r^2/6 - r^4/360 + ... + * we define R1(r*r) by + * r*(exp(r)+1)/(exp(r)-1) = 2+ r^2/6 * R1(r*r) + * That is, + * R1(r**2) = 6/r *((exp(r)+1)/(exp(r)-1) - 2/r) + * = 6/r * ( 1 + 2.0*(1/(exp(r)-1) - 1/r)) + * = 1 - r^2/60 + r^4/2520 - r^6/100800 + ... + * We use a special Reme algorithm on [0,0.347] to generate + * a polynomial of degree 5 in r*r to approximate R1. The + * maximum error of this polynomial approximation is bounded + * by 2**-61. In other words, + * R1(z) ~ 1.0 + Q1*z + Q2*z**2 + Q3*z**3 + Q4*z**4 + Q5*z**5 + * where Q1 = -1.6666666666666567384E-2, + * Q2 = 3.9682539681370365873E-4, + * Q3 = -9.9206344733435987357E-6, + * Q4 = 2.5051361420808517002E-7, + * Q5 = -6.2843505682382617102E-9; + * (where z=r*r, and the values of Q1 to Q5 are listed below) + * with error bounded by + * | 5 | -61 + * | 1.0+Q1*z+...+Q5*z - R1(z) | <= 2 + * | | + * + * expm1(r) = exp(r)-1 is then computed by the following + * specific way which minimize the accumulation rounding error: + * 2 3 + * r r [ 3 - (R1 + R1*r/2) ] + * expm1(r) = r + --- + --- * [--------------------] + * 2 2 [ 6 - r*(3 - R1*r/2) ] + * + * To compensate the error in the argument reduction, we use + * expm1(r+c) = expm1(r) + c + expm1(r)*c + * ~ expm1(r) + c + r*c + * Thus c+r*c will be added in as the correction terms for + * expm1(r+c). Now rearrange the term to avoid optimization + * screw up: + * ( 2 2 ) + * ({ ( r [ R1 - (3 - R1*r/2) ] ) } r ) + * expm1(r+c)~r - ({r*(--- * [--------------------]-c)-c} - --- ) + * ({ ( 2 [ 6 - r*(3 - R1*r/2) ] ) } 2 ) + * ( ) + * + * = r - E + * 3. Scale back to obtain expm1(x): + * From step 1, we have + * expm1(x) = either 2^k*[expm1(r)+1] - 1 + * = or 2^k*[expm1(r) + (1-2^-k)] + * 4. Implementation notes: + * (A). To save one multiplication, we scale the coefficient Qi + * to Qi*2^i, and replace z by (x^2)/2. + * (B). To achieve maximum accuracy, we compute expm1(x) by + * (i) if x < -56*ln2, return -1.0, (raise inexact if x!=inf) + * (ii) if k=0, return r-E + * (iii) if k=-1, return 0.5*(r-E)-0.5 + * (iv) if k=1 if r < -0.25, return 2*((r+0.5)- E) + * else return 1.0+2.0*(r-E); + * (v) if (k<-2||k>56) return 2^k(1-(E-r)) - 1 (or exp(x)-1) + * (vi) if k <= 20, return 2^k((1-2^-k)-(E-r)), else + * (vii) return 2^k(1-((E+2^-k)-r)) + * + * Special cases: + * expm1(INF) is INF, expm1(NaN) is NaN; + * expm1(-INF) is -1, and + * for finite argument, only expm1(0)=0 is exact. + * + * Accuracy: + * according to an error analysis, the error is always less than + * 1 ulp (unit in the last place). + * + * Misc. info. + * For IEEE double + * if x > 7.09782712893383973096e+02 then expm1(x) overflow + * + * Constants: + * The hexadecimal values are the intended ones for the following + * constants. The decimal values may be used, provided that the + * compiler will convert from decimal to binary accurately enough + * to produce the hexadecimal values shown. + */ + +#include "math.h" +#include "math_private.h" + +static const double +one = 1.0, +huge = 1.0e+300, +tiny = 1.0e-300, +o_threshold = 7.09782712893383973096e+02,/* 0x40862E42, 0xFEFA39EF */ +ln2_hi = 6.93147180369123816490e-01,/* 0x3fe62e42, 0xfee00000 */ +ln2_lo = 1.90821492927058770002e-10,/* 0x3dea39ef, 0x35793c76 */ +invln2 = 1.44269504088896338700e+00,/* 0x3ff71547, 0x652b82fe */ + /* scaled coefficients related to expm1 */ +Q1 = -3.33333333333331316428e-02, /* BFA11111 111110F4 */ +Q2 = 1.58730158725481460165e-03, /* 3F5A01A0 19FE5585 */ +Q3 = -7.93650757867487942473e-05, /* BF14CE19 9EAADBB7 */ +Q4 = 4.00821782732936239552e-06, /* 3ED0CFCA 86E65239 */ +Q5 = -2.01099218183624371326e-07; /* BE8AFDB7 6E09C32D */ + +double expm1(double x) +{ + double y,hi,lo,c=0.0,t,e,hxs,hfx,r1; + int32_t k,xsb; + u_int32_t hx; + + GET_HIGH_WORD(hx,x); + xsb = hx&0x80000000; /* sign bit of x */ + if(xsb==0) y=x; else y= -x; /* y = |x| */ + hx &= 0x7fffffff; /* high word of |x| */ + + /* filter out huge and non-finite argument */ + if(hx >= 0x4043687A) { /* if |x|>=56*ln2 */ + if(hx >= 0x40862E42) { /* if |x|>=709.78... */ + if(hx>=0x7ff00000) { + u_int32_t low; + GET_LOW_WORD(low,x); + if(((hx&0xfffff)|low)!=0) + return x+x; /* NaN */ + else return (xsb==0)? x:-1.0;/* exp(+-inf)={inf,-1} */ + } + if(x > o_threshold) return huge*huge; /* overflow */ + } + if(xsb!=0) { /* x < -56*ln2, return -1.0 with inexact */ + if(x+tiny<0.0) /* raise inexact */ + return tiny-one; /* return -1 */ + } + } + + /* argument reduction */ + if(hx > 0x3fd62e42) { /* if |x| > 0.5 ln2 */ + if(hx < 0x3FF0A2B2) { /* and |x| < 1.5 ln2 */ + if(xsb==0) + {hi = x - ln2_hi; lo = ln2_lo; k = 1;} + else + {hi = x + ln2_hi; lo = -ln2_lo; k = -1;} + } else { + k = invln2*x+((xsb==0)?0.5:-0.5); + t = k; + hi = x - t*ln2_hi; /* t*ln2_hi is exact here */ + lo = t*ln2_lo; + } + x = hi - lo; + c = (hi-x)-lo; + } + else if(hx < 0x3c900000) { /* when |x|<2**-54, return x */ + t = huge+x; /* return x with inexact flags when x!=0 */ + return x - (t-(huge+x)); + } + else k = 0; + + /* x is now in primary range */ + hfx = 0.5*x; + hxs = x*hfx; + r1 = one+hxs*(Q1+hxs*(Q2+hxs*(Q3+hxs*(Q4+hxs*Q5)))); + t = 3.0-r1*hfx; + e = hxs*((r1-t)/(6.0 - x*t)); + if(k==0) return x - (x*e-hxs); /* c is 0 */ + else { + e = (x*(e-c)-c); + e -= hxs; + if(k== -1) return 0.5*(x-e)-0.5; + if(k==1) { + if(x < -0.25) return -2.0*(e-(x+0.5)); + else return one+2.0*(x-e); + } + if (k <= -2 || k>56) { /* suffice to return exp(x)-1 */ + u_int32_t high; + y = one-(e-x); + GET_HIGH_WORD(high,y); + SET_HIGH_WORD(y,high+(k<<20)); /* add k to y's exponent */ + return y-one; + } + t = one; + if(k<20) { + u_int32_t high; + SET_HIGH_WORD(t,0x3ff00000 - (0x200000>>k)); /* t=1-2^-k */ + y = t-(e-x); + GET_HIGH_WORD(high,y); + SET_HIGH_WORD(y,high+(k<<20)); /* add k to y's exponent */ + } else { + u_int32_t high; + SET_HIGH_WORD(t,((0x3ff-k)<<20)); /* 2^-k */ + y = x-(e+t); + y += one; + GET_HIGH_WORD(high,y); + SET_HIGH_WORD(y,high+(k<<20)); /* add k to y's exponent */ + } + } + return y; +} +libm_hidden_def(expm1) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_fabs.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_fabs.c new file mode 100644 index 00000000..d2c647ff --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_fabs.c @@ -0,0 +1,29 @@ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* + * fabs(x) returns the absolute value of x. + */ + +#include +/* Prevent math.h from defining a colliding inline */ +#undef __USE_EXTERN_INLINES +#include "math.h" +#include "math_private.h" + +double fabs(double x) +{ + u_int32_t high; + GET_HIGH_WORD(high,x); + SET_HIGH_WORD(x,high&0x7fffffff); + return x; +} +libm_hidden_def(fabs) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_fdim.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_fdim.c new file mode 100644 index 00000000..6249219c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_fdim.c @@ -0,0 +1,18 @@ +/* Copyright (C) 2002 by Red Hat, Incorporated. All rights reserved. + * + * Permission to use, copy, modify, and distribute this software + * is freely granted, provided that this notice is preserved. + */ + +#include "math.h" +#include "math_private.h" + +double fdim(double x, double y) +{ + int c = __fpclassify(x); + if (c == FP_NAN || c == FP_INFINITE) + return HUGE_VAL; + + return x > y ? x - y : 0.0; +} +libm_hidden_def(fdim) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_finite.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_finite.c new file mode 100644 index 00000000..9bbc0028 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_finite.c @@ -0,0 +1,32 @@ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* + * finite(x) returns 1 is x is finite, else 0; + * no branching! + */ + +#include +/* Prevent math.h from defining a colliding inline */ +#undef __USE_EXTERN_INLINES +#include "math.h" +#include "math_private.h" + +int __finite(double x) +{ + u_int32_t hx; + + GET_HIGH_WORD(hx, x); + /* Finite numbers have at least one zero bit in exponent. */ + /* All other numbers will result in 0xffffffff after OR: */ + return (hx | 0x800fffff) != 0xffffffff; +} +libm_hidden_def(__finite) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_finitef.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_finitef.c new file mode 100644 index 00000000..b427ea69 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_finitef.c @@ -0,0 +1,33 @@ +/* s_finitef.c -- float version of s_finite.c. + * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. + */ + +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* + * finitef(x) returns 1 is x is finite, else 0; + * no branching! + */ + +#include "math.h" +#include "math_private.h" + +int __finitef(float x) +{ + u_int32_t ix; + + GET_FLOAT_WORD(ix, x); + /* Finite numbers have at least one zero bit in exponent. */ + /* All other numbers will result in 0xffffffff after OR: */ + return (ix | 0x807fffff) != 0xffffffff; +} +libm_hidden_def(__finitef) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_floor.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_floor.c new file mode 100644 index 00000000..91f1879b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_floor.c @@ -0,0 +1,71 @@ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* + * floor(x) + * Return x rounded toward -inf to integral value + * Method: + * Bit twiddling. + * Exception: + * Inexact flag raised if x not equal to floor(x). + */ + +#include +/* Prevent math.h from defining a colliding inline */ +#undef __USE_EXTERN_INLINES +#include "math.h" +#include "math_private.h" + +static const double huge = 1.0e300; + +double floor(double x) +{ + int32_t i0,i1,j0; + u_int32_t i,j; + EXTRACT_WORDS(i0,i1,x); + j0 = ((i0>>20)&0x7ff)-0x3ff; + if(j0<20) { + if(j0<0) { /* raise inexact if x != 0 */ + if(huge+x>0.0) {/* return 0*sign(x) if |x|<1 */ + if(i0>=0) {i0=i1=0;} + else if(((i0&0x7fffffff)|i1)!=0) + { i0=0xbff00000;i1=0;} + } + } else { + i = (0x000fffff)>>j0; + if(((i0&i)|i1)==0) return x; /* x is integral */ + if(huge+x>0.0) { /* raise inexact flag */ + if(i0<0) i0 += (0x00100000)>>j0; + i0 &= (~i); i1=0; + } + } + } else if (j0>51) { + if(j0==0x400) return x+x; /* inf or NaN */ + else return x; /* x is integral */ + } else { + i = ((u_int32_t)(0xffffffff))>>(j0-20); + if((i1&i)==0) return x; /* x is integral */ + if(huge+x>0.0) { /* raise inexact flag */ + if(i0<0) { + if(j0==20) i0+=1; + else { + j = i1+(1<<(52-j0)); + if(j, 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +double +fma (double x, double y, double z) +{ + return (x * y) + z; +} +libm_hidden_def(fma) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_fmax.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_fmax.c new file mode 100644 index 00000000..21dfaa98 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_fmax.c @@ -0,0 +1,19 @@ +/* Copyright (C) 2002 by Red Hat, Incorporated. All rights reserved. + * + * Permission to use, copy, modify, and distribute this software + * is freely granted, provided that this notice is preserved. + */ + +#include "math.h" +#include "math_private.h" + +double fmax(double x, double y) +{ + if (__fpclassify(x) == FP_NAN) + return x; + if (__fpclassify(y) == FP_NAN) + return y; + + return x > y ? x : y; +} +libm_hidden_def(fmax) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_fmin.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_fmin.c new file mode 100644 index 00000000..674d9a56 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_fmin.c @@ -0,0 +1,19 @@ +/* Copyright (C) 2002 by Red Hat, Incorporated. All rights reserved. + * + * Permission to use, copy, modify, and distribute this software + * is freely granted, provided that this notice is preserved. + */ + +#include "math.h" +#include "math_private.h" + +double fmin(double x, double y) +{ + if (__fpclassify(x) == FP_NAN) + return x; + if (__fpclassify(y) == FP_NAN) + return y; + + return x < y ? x : y; +} +libm_hidden_def(fmin) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_fpclassify.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_fpclassify.c new file mode 100644 index 00000000..a05cd563 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_fpclassify.c @@ -0,0 +1,42 @@ +/* Return classification value corresponding to argument. + Copyright (C) 1997, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#include "math_private.h" + +int __fpclassify(double x) +{ + u_int32_t hx, lx; + int retval = FP_NORMAL; + + EXTRACT_WORDS (hx, lx, x); + lx |= hx & 0xfffff; + hx &= 0x7ff00000; + if ((hx | lx) == 0) + retval = FP_ZERO; + else if (hx == 0) + retval = FP_SUBNORMAL; + else if (hx == 0x7ff00000) + retval = lx != 0 ? FP_NAN : FP_INFINITE; + + return retval; +} +libm_hidden_def(__fpclassify) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_fpclassifyf.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_fpclassifyf.c new file mode 100644 index 00000000..23ae59f1 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_fpclassifyf.c @@ -0,0 +1,40 @@ +/* Return classification value corresponding to argument. + Copyright (C) 1997, 2000, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include "math_private.h" + +int __fpclassifyf (float x) +{ + u_int32_t wx; + int retval = FP_NORMAL; + + GET_FLOAT_WORD (wx, x); + wx &= 0x7fffffff; + if (wx == 0) + retval = FP_ZERO; + else if (wx < 0x800000) + retval = FP_SUBNORMAL; + else if (wx >= 0x7f800000) + retval = wx > 0x7f800000 ? FP_NAN : FP_INFINITE; + + return retval; +} +libm_hidden_def(__fpclassifyf) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_frexp.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_frexp.c new file mode 100644 index 00000000..212ec47a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_frexp.c @@ -0,0 +1,46 @@ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* + * for non-zero x + * x = frexp(arg,&exp); + * return a double fp quantity x such that 0.5 <= |x| <1.0 + * and the corresponding binary exponent "exp". That is + * arg = x*2^exp. + * If arg is inf, 0.0, or NaN, then frexp(arg,&exp) returns arg + * with *exp=0. + */ + +#include "math.h" +#include "math_private.h" + +static const double +two54 = 1.80143985094819840000e+16; /* 0x43500000, 0x00000000 */ + +double frexp(double x, int *eptr) +{ + int32_t hx, ix, lx; + EXTRACT_WORDS(hx,lx,x); + ix = 0x7fffffff&hx; + *eptr = 0; + if(ix>=0x7ff00000||((ix|lx)==0)) return x; /* 0,inf,nan */ + if (ix<0x00100000) { /* subnormal */ + x *= two54; + GET_HIGH_WORD(hx,x); + ix = hx&0x7fffffff; + *eptr = -54; + } + *eptr += (ix>>20)-1022; + hx = (hx&0x800fffff)|0x3fe00000; + SET_HIGH_WORD(x,hx); + return x; +} +libm_hidden_def(frexp) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_ilogb.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_ilogb.c new file mode 100644 index 00000000..259ae7b5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_ilogb.c @@ -0,0 +1,57 @@ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* ilogb(double x) + * return the binary exponent of x + * ilogb(+-0) = FP_ILOGB0 + * ilogb(+-inf) = INT_MAX + * ilogb(NaN) = FP_ILOGBNAN (no signal is raised) + */ + +#include "math.h" +#include "math_private.h" + +int ilogb(double x) +{ + int32_t hx,lx,ix; + + GET_HIGH_WORD(hx, x); + hx &= 0x7fffffff; + + if (hx < 0x00100000) { + GET_LOW_WORD(lx, x); + if ((hx|lx)==0) /* +-0, ilogb(0) = FP_ILOGB0 */ + return FP_ILOGB0; + /* subnormal x */ + ix = -1043; + if (hx != 0) { + ix = -1022; + lx = (hx << 11); + } + /* each leading zero mantissa bit makes exponent smaller */ + for (; lx > 0; lx <<= 1) + ix--; + return ix; + } + + if (hx < 0x7ff00000) /* normal x */ + return (hx>>20) - 1023; + + if (FP_ILOGBNAN != (~0U >> 1)) { + GET_LOW_WORD(lx, x); + if (hx == 0x7ff00000 && lx == 0) /* +-inf */ + return ~0U >> 1; /* = INT_MAX */ + } + + /* NAN. ilogb(NAN) = FP_ILOGBNAN */ + return FP_ILOGBNAN; +} +libm_hidden_def(ilogb) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_isinf.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_isinf.c new file mode 100644 index 00000000..62e5263b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_isinf.c @@ -0,0 +1,23 @@ +/* + * Written by J.T. Conklin . + * Changed to return -1 for -Inf by Ulrich Drepper . + * Public domain. + */ + +/* + * isinf(x) returns 1 is x is inf, -1 if x is -inf, else 0; + * no branching! + */ + +#include "math.h" +#include "math_private.h" + +int __isinf(double x) +{ + int32_t hx,lx; + EXTRACT_WORDS(hx,lx,x); + lx |= (hx & 0x7fffffff) ^ 0x7ff00000; + lx |= -lx; + return ~(lx >> 31) & (hx >> 30); +} +libm_hidden_def(__isinf) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_isinff.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_isinff.c new file mode 100644 index 00000000..6727f046 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_isinff.c @@ -0,0 +1,23 @@ +/* + * Written by J.T. Conklin . + * Public domain. + */ + +/* + * isinff(x) returns 1 if x is inf, -1 if x is -inf, else 0; + * no branching! + */ + +#include "math.h" +#include "math_private.h" + +int __isinff (float x) +{ + int32_t ix,t; + GET_FLOAT_WORD(ix,x); + t = ix & 0x7fffffff; + t ^= 0x7f800000; + t |= -t; + return ~(t >> 31) & (ix >> 30); +} +libm_hidden_def(__isinff) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_isnan.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_isnan.c new file mode 100644 index 00000000..1bc49cb0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_isnan.c @@ -0,0 +1,29 @@ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* + * isnan(x) returns 1 is x is nan, else 0; + * no branching! + */ + +#include "math.h" +#include "math_private.h" + +int __isnan(double x) +{ + int32_t hx,lx; + EXTRACT_WORDS(hx,lx,x); + hx &= 0x7fffffff; + hx |= (u_int32_t)(lx|(-lx))>>31; + hx = 0x7ff00000 - hx; + return (int)(((u_int32_t)hx)>>31); +} +libm_hidden_def(__isnan) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_isnanf.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_isnanf.c new file mode 100644 index 00000000..d868264f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_isnanf.c @@ -0,0 +1,32 @@ +/* s_isnanf.c -- float version of s_isnan.c. + * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. + */ + +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* + * isnanf(x) returns 1 is x is nan, else 0; + * no branching! + */ + +#include "math.h" +#include "math_private.h" + +int __isnanf(float x) +{ + int32_t ix; + GET_FLOAT_WORD(ix,x); + ix &= 0x7fffffff; + ix = 0x7f800000 - ix; + return (int)(((u_int32_t)(ix))>>31); +} +libm_hidden_def(__isnanf) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_ldexp.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_ldexp.c new file mode 100644 index 00000000..bc0f08e9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_ldexp.c @@ -0,0 +1,39 @@ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +#include "math.h" +#include "math_private.h" +#include + +/* TODO: POSIX says: + * + * "If the integer expression (math_errhandling & MATH_ERRNO) is non-zero, + * then errno shall be set to [ERANGE]. If the integer expression + * (math_errhandling & MATH_ERREXCEPT) is non-zero, then the underflow + * floating-point exception shall be raised." + * + * *And it says the same about scalbn*! Thus these two functions + * are the same and can be just aliased. + * + * Currently, ldexp tries to be vaguely POSIX compliant while scalbn + * does not (it does not set ERRNO). + */ + +double ldexp(double value, int _exp) +{ + if (!isfinite(value) || value == 0.0) + return value; + value = scalbn(value, _exp); + if (!isfinite(value) || value == 0.0) + errno = ERANGE; + return value; +} +libm_hidden_def(ldexp) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_lib_version.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_lib_version.c new file mode 100644 index 00000000..e3119423 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_lib_version.c @@ -0,0 +1,34 @@ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* + * MACRO for standards + */ + +#include "math.h" +#include "math_private.h" + +/* + * define and initialize _LIB_VERSION + */ +#ifdef _POSIX_MODE +_LIB_VERSION_TYPE _LIB_VERSION = _POSIX_; +#else +#ifdef _XOPEN_MODE +_LIB_VERSION_TYPE _LIB_VERSION = _XOPEN_; +#else +#ifdef _SVID3_MODE +_LIB_VERSION_TYPE _LIB_VERSION = _SVID_; +#else /* default _IEEE_MODE */ +_LIB_VERSION_TYPE _LIB_VERSION = _IEEE_; +#endif +#endif +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_llrint.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_llrint.c new file mode 100644 index 00000000..b5f75c2e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_llrint.c @@ -0,0 +1,90 @@ +/* Round argument to nearest integral value according to current rounding + direction. + Copyright (C) 1997, 2004, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +/* Prevent math.h from defining a colliding inline */ +#undef __USE_EXTERN_INLINES +#include +#include "math_private.h" + +static const double two52[2] = +{ + 4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */ + -4.50359962737049600000e+15, /* 0xC3300000, 0x00000000 */ +}; + +long long int +llrint (double x) +{ + int32_t j0; + u_int32_t i1, i0; + long long int result; + volatile double w; + double t; + int sx; + + EXTRACT_WORDS (i0, i1, x); + j0 = ((i0 >> 20) & 0x7ff) - 0x3ff; + sx = i0 >> 31; + i0 &= 0xfffff; + i0 |= 0x100000; + + if (j0 < 20) + { + w = two52[sx] + x; + t = w - two52[sx]; + EXTRACT_WORDS (i0, i1, t); + j0 = ((i0 >> 20) & 0x7ff) - 0x3ff; + i0 &= 0xfffff; + i0 |= 0x100000; + + result = (j0 < 0 ? 0 : i0 >> (20 - j0)); + } + else if (j0 < (int32_t) (8 * sizeof (long long int)) - 1) + { + if (j0 >= 52) + result = (((long long int) i0 << 32) | i1) << (j0 - 52); + else + { + w = two52[sx] + x; + t = w - two52[sx]; + EXTRACT_WORDS (i0, i1, t); + j0 = ((i0 >> 20) & 0x7ff) - 0x3ff; + i0 &= 0xfffff; + i0 |= 0x100000; + + if (j0 == 20) + result = (long long int) i0; + else + result = ((long long int) i0 << (j0 - 20)) | (i1 >> (52 - j0)); + } + } + else + { + /* The number is too large. It is left implementation defined + what happens. */ + return (long long int) x; + } + + return sx ? -result : result; +} + +libm_hidden_def(llrint) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_llround.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_llround.c new file mode 100644 index 00000000..8263b03d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_llround.c @@ -0,0 +1,74 @@ +/* Round double value to long long int. + Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include "math_private.h" + +long long int +llround (double x) +{ + int32_t j0; + u_int32_t i1, i0; + long long int result; + int sign; + + EXTRACT_WORDS (i0, i1, x); + j0 = ((i0 >> 20) & 0x7ff) - 0x3ff; + sign = (i0 & 0x80000000) != 0 ? -1 : 1; + i0 &= 0xfffff; + i0 |= 0x100000; + + if (j0 < 20) + { + if (j0 < 0) + return j0 < -1 ? 0 : sign; + else + { + i0 += 0x80000 >> j0; + + result = i0 >> (20 - j0); + } + } + else if (j0 < (int32_t) (8 * sizeof (long long int)) - 1) + { + if (j0 >= 52) + result = (((long long int) i0 << 32) | i1) << (j0 - 52); + else + { + u_int32_t j = i1 + (0x80000000 >> (j0 - 20)); + if (j < i1) + ++i0; + + if (j0 == 20) + result = (long long int) i0; + else + result = ((long long int) i0 << (j0 - 20)) | (j >> (52 - j0)); + } + } + else + { + /* The number is too large. It is left implementation defined + what happens. */ + return (long long int) x; + } + + return sign * result; +} +libm_hidden_def(llround) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_log1p.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_log1p.c new file mode 100644 index 00000000..45405630 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_log1p.c @@ -0,0 +1,157 @@ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* double log1p(double x) + * + * Method : + * 1. Argument Reduction: find k and f such that + * 1+x = 2^k * (1+f), + * where sqrt(2)/2 < 1+f < sqrt(2) . + * + * Note. If k=0, then f=x is exact. However, if k!=0, then f + * may not be representable exactly. In that case, a correction + * term is need. Let u=1+x rounded. Let c = (1+x)-u, then + * log(1+x) - log(u) ~ c/u. Thus, we proceed to compute log(u), + * and add back the correction term c/u. + * (Note: when x > 2**53, one can simply return log(x)) + * + * 2. Approximation of log1p(f). + * Let s = f/(2+f) ; based on log(1+f) = log(1+s) - log(1-s) + * = 2s + 2/3 s**3 + 2/5 s**5 + ....., + * = 2s + s*R + * We use a special Reme algorithm on [0,0.1716] to generate + * a polynomial of degree 14 to approximate R The maximum error + * of this polynomial approximation is bounded by 2**-58.45. In + * other words, + * 2 4 6 8 10 12 14 + * R(z) ~ Lp1*s +Lp2*s +Lp3*s +Lp4*s +Lp5*s +Lp6*s +Lp7*s + * (the values of Lp1 to Lp7 are listed in the program) + * and + * | 2 14 | -58.45 + * | Lp1*s +...+Lp7*s - R(z) | <= 2 + * | | + * Note that 2s = f - s*f = f - hfsq + s*hfsq, where hfsq = f*f/2. + * In order to guarantee error in log below 1ulp, we compute log + * by + * log1p(f) = f - (hfsq - s*(hfsq+R)). + * + * 3. Finally, log1p(x) = k*ln2 + log1p(f). + * = k*ln2_hi+(f-(hfsq-(s*(hfsq+R)+k*ln2_lo))) + * Here ln2 is split into two floating point number: + * ln2_hi + ln2_lo, + * where n*ln2_hi is always exact for |n| < 2000. + * + * Special cases: + * log1p(x) is NaN with signal if x < -1 (including -INF) ; + * log1p(+INF) is +INF; log1p(-1) is -INF with signal; + * log1p(NaN) is that NaN with no signal. + * + * Accuracy: + * according to an error analysis, the error is always less than + * 1 ulp (unit in the last place). + * + * Constants: + * The hexadecimal values are the intended ones for the following + * constants. The decimal values may be used, provided that the + * compiler will convert from decimal to binary accurately enough + * to produce the hexadecimal values shown. + * + * Note: Assuming log() return accurate answer, the following + * algorithm can be used to compute log1p(x) to within a few ULP: + * + * u = 1+x; + * if(u==1.0) return x ; else + * return log(u)*(x/(u-1.0)); + * + * See HP-15C Advanced Functions Handbook, p.193. + */ + +#include "math.h" +#include "math_private.h" + +static const double +ln2_hi = 6.93147180369123816490e-01, /* 3fe62e42 fee00000 */ +ln2_lo = 1.90821492927058770002e-10, /* 3dea39ef 35793c76 */ +two54 = 1.80143985094819840000e+16, /* 43500000 00000000 */ +Lp1 = 6.666666666666735130e-01, /* 3FE55555 55555593 */ +Lp2 = 3.999999999940941908e-01, /* 3FD99999 9997FA04 */ +Lp3 = 2.857142874366239149e-01, /* 3FD24924 94229359 */ +Lp4 = 2.222219843214978396e-01, /* 3FCC71C5 1D8E78AF */ +Lp5 = 1.818357216161805012e-01, /* 3FC74664 96CB03DE */ +Lp6 = 1.531383769920937332e-01, /* 3FC39A09 D078C69F */ +Lp7 = 1.479819860511658591e-01; /* 3FC2F112 DF3E5244 */ + +static const double zero = 0.0; + +double log1p(double x) +{ + double hfsq,f=0,c=0,s,z,R,u; + int32_t k,hx,hu=0,ax; + + GET_HIGH_WORD(hx,x); + ax = hx&0x7fffffff; + + k = 1; + if (hx < 0x3FDA827A) { /* x < 0.41422 */ + if(ax>=0x3ff00000) { /* x <= -1.0 */ + if(x==-1.0) return -two54/zero; /* log1p(-1)=+inf */ + else return (x-x)/(x-x); /* log1p(x<-1)=NaN */ + } + if(ax<0x3e200000) { /* |x| < 2**-29 */ + if(two54+x>zero /* raise inexact */ + &&ax<0x3c900000) /* |x| < 2**-54 */ + return x; + else + return x - x*x*0.5; + } + if(hx>0||hx<=((int32_t)0xbfd2bec3)) { + k=0;f=x;hu=1;} /* -0.2929= 0x7ff00000) return x+x; + if(k!=0) { + if(hx<0x43400000) { + u = 1.0+x; + GET_HIGH_WORD(hu,u); + k = (hu>>20)-1023; + c = (k>0)? 1.0-(u-x):x-(u-1.0);/* correction term */ + c /= u; + } else { + u = x; + GET_HIGH_WORD(hu,u); + k = (hu>>20)-1023; + c = 0; + } + hu &= 0x000fffff; + if(hu<0x6a09e) { + SET_HIGH_WORD(u,hu|0x3ff00000); /* normalize u */ + } else { + k += 1; + SET_HIGH_WORD(u,hu|0x3fe00000); /* normalize u/2 */ + hu = (0x00100000-hu)>>2; + } + f = u-1.0; + } + hfsq=0.5*f*f; + if(hu==0) { /* |f| < 2**-20 */ + if(f==zero) {if(k==0) return zero; + else {c += k*ln2_lo; return k*ln2_hi+c;} + } + R = hfsq*(1.0-0.66666666666666666*f); + if(k==0) return f-R; else + return k*ln2_hi-((R-(k*ln2_lo+c))-f); + } + s = f/(2.0+f); + z = s*s; + R = z*(Lp1+z*(Lp2+z*(Lp3+z*(Lp4+z*(Lp5+z*(Lp6+z*Lp7)))))); + if(k==0) return f-(hfsq-s*(hfsq+R)); else + return k*ln2_hi-((hfsq-(s*(hfsq+R)+(k*ln2_lo+c)))-f); +} +libm_hidden_def(log1p) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_logb.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_logb.c new file mode 100644 index 00000000..9016b972 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_logb.c @@ -0,0 +1,33 @@ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* + * double logb(x) + * IEEE 754 logb. Included to pass IEEE test suite. Not recommend. + * Use ilogb instead. + */ + +#include "math.h" +#include "math_private.h" + +double logb(double x) +{ + int32_t lx,ix; + EXTRACT_WORDS(ix,lx,x); + ix &= 0x7fffffff; /* high |x| */ + if((ix|lx)==0) return -1.0/fabs(x); + if(ix>=0x7ff00000) return x*x; + if((ix>>=20)==0) /* IEEE 754 logb */ + return -1022.0; + else + return (double) (ix-1023); +} +libm_hidden_def(logb) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_lrint.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_lrint.c new file mode 100644 index 00000000..3cdc8a25 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_lrint.c @@ -0,0 +1,95 @@ +/* Round argument to nearest integral value according to current rounding + direction. + Copyright (C) 1997, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +/* Prevent math.h from defining a colliding inline */ +#undef __USE_EXTERN_INLINES +#include +#include "math_private.h" + +static const double two52[2] = +{ + 4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */ + -4.50359962737049600000e+15, /* 0xC3300000, 0x00000000 */ +}; + + +long int +lrint (double x) +{ + int32_t j0; + u_int32_t i0,i1; + volatile double w; + double t; + long int result; + int sx; + + EXTRACT_WORDS (i0, i1, x); + j0 = ((i0 >> 20) & 0x7ff) - 0x3ff; + sx = i0 >> 31; + i0 &= 0xfffff; + i0 |= 0x100000; + + if (j0 < 20) + { + if (j0 < -1) + return 0; + else + { + w = two52[sx] + x; + t = w - two52[sx]; + EXTRACT_WORDS (i0, i1, t); + j0 = ((i0 >> 20) & 0x7ff) - 0x3ff; + i0 &= 0xfffff; + i0 |= 0x100000; + + result = i0 >> (20 - j0); + } + } + else if (j0 < (int32_t) (8 * sizeof (long int)) - 1) + { + if (j0 >= 52) + result = ((long int) i0 << (j0 - 20)) | (i1 << (j0 - 52)); + else + { + w = two52[sx] + x; + t = w - two52[sx]; + EXTRACT_WORDS (i0, i1, t); + j0 = ((i0 >> 20) & 0x7ff) - 0x3ff; + i0 &= 0xfffff; + i0 |= 0x100000; + + if (j0 == 20) + result = (long int) i0; + else + result = ((long int) i0 << (j0 - 20)) | (i1 >> (52 - j0)); + } + } + else + { + /* The number is too large. It is left implementation defined + what happens. */ + return (long int) x; + } + + return sx ? -result : result; +} +libm_hidden_def(lrint) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_lround.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_lround.c new file mode 100644 index 00000000..acf8fb61 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_lround.c @@ -0,0 +1,74 @@ +/* Round double value to long int. + Copyright (C) 1997, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include "math_private.h" + +long int +lround (double x) +{ + int32_t j0; + u_int32_t i1, i0; + long int result; + int sign; + + EXTRACT_WORDS (i0, i1, x); + j0 = ((i0 >> 20) & 0x7ff) - 0x3ff; + sign = (i0 & 0x80000000) != 0 ? -1 : 1; + i0 &= 0xfffff; + i0 |= 0x100000; + + if (j0 < 20) + { + if (j0 < 0) + return j0 < -1 ? 0 : sign; + else + { + i0 += 0x80000 >> j0; + + result = i0 >> (20 - j0); + } + } + else if (j0 < (int32_t) (8 * sizeof (long int)) - 1) + { + if (j0 >= 52) + result = ((long int) i0 << (j0 - 20)) | (i1 << (j0 - 52)); + else + { + u_int32_t j = i1 + (0x80000000 >> (j0 - 20)); + if (j < i1) + ++i0; + + if (j0 == 20) + result = (long int) i0; + else + result = ((long int) i0 << (j0 - 20)) | (j >> (52 - j0)); + } + } + else + { + /* The number is too large. It is left implementation defined + what happens. */ + return (long int) x; + } + + return sign * result; +} +libm_hidden_def(lround) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_matherr.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_matherr.c new file mode 100644 index 00000000..9a50459c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_matherr.c @@ -0,0 +1,24 @@ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +#include "math.h" +#include "math_private.h" + +#ifndef _IEEE_LIBM + +int matherr(struct exception *x) +{ + int n=0; + if(x->arg1!=x->arg1) return 0; + return n; +} +libm_hidden_def(matherr) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_modf.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_modf.c new file mode 100644 index 00000000..f73d5fdd --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_modf.c @@ -0,0 +1,67 @@ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* + * modf(double x, double *iptr) + * return fraction part of x, and return x's integral part in *iptr. + * Method: + * Bit twiddling. + * + * Exception: + * No exception. + */ + +#include "math.h" +#include "math_private.h" + +static const double one = 1.0; + +double modf(double x, double *iptr) +{ + int32_t i0,i1,j0; + u_int32_t i; + EXTRACT_WORDS(i0,i1,x); + j0 = ((i0>>20)&0x7ff)-0x3ff; /* exponent of x */ + if(j0<20) { /* integer part in high x */ + if(j0<0) { /* |x|<1 */ + INSERT_WORDS(*iptr,i0&0x80000000,0); /* *iptr = +-0 */ + return x; + } else { + i = (0x000fffff)>>j0; + if(((i0&i)|i1)==0) { /* x is integral */ + *iptr = x; + INSERT_WORDS(x,i0&0x80000000,0); /* return +-0 */ + return x; + } else { + INSERT_WORDS(*iptr,i0&(~i),0); + return x - *iptr; + } + } + } else if (j0>51) { /* no fraction part */ + *iptr = x*one; + /* We must handle NaNs separately. */ + if (j0 == 0x400 && ((i0 & 0xfffff) | i1)) + return x*one; + INSERT_WORDS(x,i0&0x80000000,0); /* return +-0 */ + return x; + } else { /* fraction part in low x */ + i = ((u_int32_t)(0xffffffff))>>(j0-20); + if((i1&i)==0) { /* x is integral */ + *iptr = x; + INSERT_WORDS(x,i0&0x80000000,0); /* return +-0 */ + return x; + } else { + INSERT_WORDS(*iptr,i0,i1&(~i)); + return x - *iptr; + } + } +} +libm_hidden_def(modf) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_nextafter.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_nextafter.c new file mode 100644 index 00000000..ee4621cc --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_nextafter.c @@ -0,0 +1,70 @@ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* IEEE functions + * nextafter(x,y) + * return the next machine floating-point number of x in the + * direction toward y. + * Special cases: + */ + +#include "math.h" +#include "math_private.h" + +double nextafter(double x, double y) +{ + int32_t hx,hy,ix,iy; + u_int32_t lx,ly; + + EXTRACT_WORDS(hx,lx,x); + EXTRACT_WORDS(hy,ly,y); + ix = hx&0x7fffffff; /* |x| */ + iy = hy&0x7fffffff; /* |y| */ + + if(((ix>=0x7ff00000)&&((ix-0x7ff00000)|lx)!=0) || /* x is nan */ + ((iy>=0x7ff00000)&&((iy-0x7ff00000)|ly)!=0)) /* y is nan */ + return x+y; + if(x==y) return x; /* x=y, return x */ + if((ix|lx)==0) { /* x == 0 */ + INSERT_WORDS(x,hy&0x80000000,1); /* return +-minsubnormal */ + y = x*x; + if(y==x) return y; else return x; /* raise underflow flag */ + } + if(hx>=0) { /* x > 0 */ + if(hx>hy||((hx==hy)&&(lx>ly))) { /* x > y, x -= ulp */ + if(lx==0) hx -= 1; + lx -= 1; + } else { /* x < y, x += ulp */ + lx += 1; + if(lx==0) hx += 1; + } + } else { /* x < 0 */ + if(hy>=0||hx>hy||((hx==hy)&&(lx>ly))){/* x < y, x -= ulp */ + if(lx==0) hx -= 1; + lx -= 1; + } else { /* x > y, x += ulp */ + lx += 1; + if(lx==0) hx += 1; + } + } + hy = hx&0x7ff00000; + if(hy>=0x7ff00000) return x+x; /* overflow */ + if(hy<0x00100000) { /* underflow */ + y = x*x; + if(y!=x) { /* raise underflow flag */ + INSERT_WORDS(y,hx,lx); + return y; + } + } + INSERT_WORDS(x,hx,lx); + return x; +} +libm_hidden_def(nextafter) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_nextafterf.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_nextafterf.c new file mode 100644 index 00000000..e0cb8161 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_nextafterf.c @@ -0,0 +1,96 @@ +/* s_nextafterf.c -- float version of s_nextafter.c. + * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. + */ + +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +#include "math.h" +#include "math_private.h" + +float nextafterf(float x, float y) +{ + int32_t hx, hy, ix, iy; + + GET_FLOAT_WORD(hx, x); + GET_FLOAT_WORD(hy, y); + ix = hx & 0x7fffffff; /* |x| */ + iy = hy & 0x7fffffff; /* |y| */ + + /* x is nan or y is nan? */ + if ((ix > 0x7f800000) || (iy > 0x7f800000)) + return x + y; + + if (x == y) + return y; + + if (ix == 0) { /* x == 0? */ +/* glibc 2.4 does not seem to set underflow? */ +/* float u; */ + /* return +-minsubnormal */ + SET_FLOAT_WORD(x, (hy & 0x80000000) | 1); +/* u = x * x; raise underflow flag */ +/* math_force_eval(u); */ + return x; + } + + if (hx >= 0) { /* x > 0 */ + if (hx > hy) { /* x > y: x -= ulp */ + hx -= 1; + } else { /* x < y: x += ulp */ + hx += 1; + } + } else { /* x < 0 */ + if (hy >= 0 || hx > hy) { /* x < y: x -= ulp */ + hx -= 1; + } else { /* x > y: x += ulp */ + hx += 1; + } + } + hy = hx & 0x7f800000; + if (hy >= 0x7f800000) { + x = x + x; /* overflow */ + return x; /* overflow */ + } + if (hy < 0x00800000) { + float u = x * x; /* underflow */ + math_force_eval(u); /* raise underflow flag */ + } + SET_FLOAT_WORD(x, hx); + return x; +} + +#if 0 +/* "testprog N a b" + * calculates a = nextafterf(a, b) and prints a as float + * and as raw bytes; repeats it N times. + */ +#include +#include +#include +int main(int argc, char **argv) +{ + int cnt, i; + float a, b; + cnt = atoi(argv[1]); + a = strtod(argv[2], NULL); + b = strtod(argv[3], NULL); + while (cnt-- > 0) { + for (i = 0; i < sizeof(a); i++) { + unsigned char c = ((char*)(&a))[i]; + printf("%x%x", (c >> 4), (c & 0xf)); + } + printf(" %f\n", a); + a = nextafterf(a, b); + } + return 0; +} +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_remquo.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_remquo.c new file mode 100644 index 00000000..f72c56f3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_remquo.c @@ -0,0 +1,31 @@ +/* Copyright (C) 2002 by Red Hat, Incorporated. All rights reserved. + * + * Permission to use, copy, modify, and distribute this software + * is freely granted, provided that this notice is preserved. + */ + +#include "math.h" +#include "math_private.h" + +double remquo(double x, double y, int *quo) /* wrapper remquo */ +{ + int signx, signy, signres; + int mswx; + int mswy; + double x_over_y; + + GET_HIGH_WORD(mswx, x); + GET_HIGH_WORD(mswy, y); + + signx = (mswx & 0x80000000) >> 31; + signy = (mswy & 0x80000000) >> 31; + + signres = (signx ^ signy) ? -1 : 1; + + x_over_y = fabs(x / y); + + *quo = signres * (lrint(x_over_y) & 0x7f); + + return remainder(x,y); +} +libm_hidden_def(remquo) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_rint.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_rint.c new file mode 100644 index 00000000..06432c62 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_rint.c @@ -0,0 +1,92 @@ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* + * rint(x) + * Return x rounded to integral value according to the prevailing + * rounding mode. + * Method: + * Using floating addition. + * Exception: + * Inexact flag raised if x not equal to rint(x). + */ + +#include "math.h" +#include "math_private.h" + +static const double +TWO52[2]={ + 4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */ + -4.50359962737049600000e+15, /* 0xC3300000, 0x00000000 */ +}; + +double rint(double x) +{ + int32_t i0, j0, sx; + u_int32_t i,i1; + double t; + /* We use w = x + 2^52; t = w - 2^52; trick to round x to integer. + * This trick requires that compiler does not optimize it + * by keeping intermediate result w in a register wider than double. + * Declaring w volatile assures that value gets truncated to double + * (unfortunately, it also forces store+load): + */ + volatile double w; + + EXTRACT_WORDS(i0,i1,x); + /* Unbiased exponent */ + j0 = ((((u_int32_t)i0) >> 20)&0x7ff)-0x3ff; + + if (j0 > 51) { + //Why bother? Just returning x works too + //if (j0 == 0x400) /* inf or NaN */ + // return x+x; + return x; /* x is integral */ + } + + /* Sign */ + sx = ((u_int32_t)i0) >> 31; + + if (j0<20) { + if (j0<0) { /* |x| < 1 */ + if (((i0&0x7fffffff)|i1)==0) return x; + i1 |= (i0&0x0fffff); + i0 &= 0xfffe0000; + i0 |= ((i1|-i1)>>12)&0x80000; + SET_HIGH_WORD(x,i0); + w = TWO52[sx]+x; + t = w-TWO52[sx]; + GET_HIGH_WORD(i0,t); + SET_HIGH_WORD(t,(i0&0x7fffffff)|(sx<<31)); + return t; + } else { + i = (0x000fffff)>>j0; + if (((i0&i)|i1)==0) return x; /* x is integral */ + i>>=1; + if (((i0&i)|i1)!=0) { + if (j0==19) i1 = 0x40000000; + else i0 = (i0&(~i))|((0x20000)>>j0); + } + } + } else { + i = ((u_int32_t)(0xffffffff))>>(j0-20); + if ((i1&i)==0) return x; /* x is integral */ + i>>=1; + if ((i1&i)!=0) i1 = (i1&(~i))|((0x40000000)>>(j0-20)); + } + INSERT_WORDS(x,i0,i1); + w = TWO52[sx]+x; + return w-TWO52[sx]; +} +libm_hidden_def(rint) + +strong_alias(rint, nearbyint) +libm_hidden_def(nearbyint) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_round.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_round.c new file mode 100644 index 00000000..b3e22630 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_round.c @@ -0,0 +1,90 @@ +/* Round double to integer away from zero. + Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include "math_private.h" + +static const double huge = 1.0e300; + +double +round (double x) +{ + int32_t i0, j0; + u_int32_t i1; + + EXTRACT_WORDS (i0, i1, x); + j0 = ((i0 >> 20) & 0x7ff) - 0x3ff; + if (j0 < 20) + { + if (j0 < 0) + { + if (huge + x > 0.0) + { + i0 &= 0x80000000; + if (j0 == -1) + i0 |= 0x3ff00000; + i1 = 0; + } + } + else + { + u_int32_t i = 0x000fffff >> j0; + if (((i0 & i) | i1) == 0) + /* X is integral. */ + return x; + if (huge + x > 0.0) + { + /* Raise inexact if x != 0. */ + i0 += 0x00080000 >> j0; + i0 &= ~i; + i1 = 0; + } + } + } + else if (j0 > 51) + { + if (j0 == 0x400) + /* Inf or NaN. */ + return x + x; + else + return x; + } + else + { + u_int32_t i = 0xffffffff >> (j0 - 20); + if ((i1 & i) == 0) + /* X is integral. */ + return x; + + if (huge + x > 0.0) + { + /* Raise inexact if x != 0. */ + u_int32_t j = i1 + (1 << (51 - j0)); + if (j < i1) + i0 += 1; + i1 = j; + } + i1 &= ~i; + } + + INSERT_WORDS (x, i0, i1); + return x; +} +libm_hidden_def(round) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_scalbn.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_scalbn.c new file mode 100644 index 00000000..a3399b25 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_scalbn.c @@ -0,0 +1,77 @@ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* + * scalbln(double x, long n) + * scalbln(x,n) returns x * 2**n computed by exponent + * manipulation rather than by actually performing an + * exponentiation or a multiplication. + */ + +#include "math.h" +#include "math_private.h" +#include + +static const double +two54 = 1.80143985094819840000e+16, /* 0x43500000, 0x00000000 */ +twom54 = 5.55111512312578270212e-17, /* 0x3C900000, 0x00000000 */ +huge = 1.0e+300, +tiny = 1.0e-300; + +double scalbln(double x, long n) +{ + int32_t k, hx, lx; + + EXTRACT_WORDS(hx, lx, x); + k = (hx & 0x7ff00000) >> 20; /* extract exponent */ + if (k == 0) { /* 0 or subnormal x */ + if ((lx | (hx & 0x7fffffff)) == 0) + return x; /* +-0 */ + x *= two54; + GET_HIGH_WORD(hx, x); + k = ((hx & 0x7ff00000) >> 20) - 54; + } + if (k == 0x7ff) + return x + x; /* NaN or Inf */ + k = k + n; + if (k > 0x7fe) + return huge * copysign(huge, x); /* overflow */ + if (n < -50000) + return tiny * copysign(tiny, x); /* underflow */ + if (k > 0) { /* normal result */ + SET_HIGH_WORD(x, (hx & 0x800fffff) | (k << 20)); + return x; + } + if (k <= -54) { + if (n > 50000) /* in case integer overflow in n+k */ + return huge * copysign(huge, x); /* overflow */ + return tiny * copysign(tiny, x); /* underflow */ + } + k += 54; /* subnormal result */ + SET_HIGH_WORD(x, (hx & 0x800fffff) | (k << 20)); + return x * twom54; +} +libm_hidden_def(scalbln) + +#if LONG_MAX == INT_MAX +/* strong_alias(scalbln, scalbn) - "error: conflicting types for 'scalbn'" + * because it tries to declare "typeof(scalbln) scalbn;" + * which tries to give "long" parameter to scalbn. + * Doing it by hand: + */ +__typeof(scalbn) scalbn __attribute__((alias("scalbln"))); +#else +double scalbn(double x, int n) +{ + return scalbln(x, n); +} +#endif +libm_hidden_def(scalbn) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_signbit.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_signbit.c new file mode 100644 index 00000000..ee1b7c62 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_signbit.c @@ -0,0 +1,35 @@ +/* Return nonzero value if number is negative. + Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +/* Prevent math.h from defining a colliding inline */ +#undef __USE_EXTERN_INLINES +#include +#include "math_private.h" + +int +__signbit (double x) +{ + int32_t hx; + + GET_HIGH_WORD (hx, x); + return hx & 0x80000000; +} +libm_hidden_def(__signbit) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_signbitf.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_signbitf.c new file mode 100644 index 00000000..a15e26a0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_signbitf.c @@ -0,0 +1,35 @@ +/* Return nonzero value if number is negative. + Copyright (C) 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +/* Prevent math.h from defining a colliding inline */ +#undef __USE_EXTERN_INLINES +#include +#include "math_private.h" + +int +__signbitf (float x) +{ + int32_t hx; + + GET_FLOAT_WORD (hx, x); + return hx & 0x80000000; +} +libm_hidden_def(__signbitf) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_signgam.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_signgam.c new file mode 100644 index 00000000..d67d5918 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_signgam.c @@ -0,0 +1,3 @@ +#include "math.h" +#include "math_private.h" +int signgam = 0; diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_significand.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_significand.c new file mode 100644 index 00000000..8c74ce24 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_significand.c @@ -0,0 +1,24 @@ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* + * significand(x) computes just + * scalb(x, (double) -ilogb(x)), + * for exercising the fraction-part(F) IEEE 754-1985 test vector. + */ + +#include "math.h" +#include "math_private.h" + +double significand(double x) +{ + return __ieee754_scalb(x,(double) -ilogb(x)); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_sin.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_sin.c new file mode 100644 index 00000000..03867e77 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_sin.c @@ -0,0 +1,73 @@ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* sin(x) + * Return sine function of x. + * + * kernel function: + * __kernel_sin ... sine function on [-pi/4,pi/4] + * __kernel_cos ... cose function on [-pi/4,pi/4] + * __ieee754_rem_pio2 ... argument reduction routine + * + * Method. + * Let S,C and T denote the sin, cos and tan respectively on + * [-PI/4, +PI/4]. Reduce the argument x to y1+y2 = x-k*pi/2 + * in [-pi/4 , +pi/4], and let n = k mod 4. + * We have + * + * n sin(x) cos(x) tan(x) + * ---------------------------------------------------------- + * 0 S C T + * 1 C -S -1/T + * 2 -S -C T + * 3 -C S -1/T + * ---------------------------------------------------------- + * + * Special cases: + * Let trig be any of sin, cos, or tan. + * trig(+-INF) is NaN, with signals; + * trig(NaN) is that NaN; + * + * Accuracy: + * TRIG(x) returns trig(x) nearly rounded + */ + +#include "math.h" +#include "math_private.h" + +double sin(double x) +{ + double y[2],z=0.0; + int32_t n, ix; + + /* High word of x. */ + GET_HIGH_WORD(ix,x); + + /* |x| ~< pi/4 */ + ix &= 0x7fffffff; + if(ix <= 0x3fe921fb) return __kernel_sin(x,z,0); + + /* sin(Inf or NaN) is NaN */ + else if (ix>=0x7ff00000) return x-x; + + /* argument reduction needed */ + else { + n = __ieee754_rem_pio2(x,y); + switch(n&3) { + case 0: return __kernel_sin(y[0],y[1],1); + case 1: return __kernel_cos(y[0],y[1]); + case 2: return -__kernel_sin(y[0],y[1],1); + default: + return -__kernel_cos(y[0],y[1]); + } + } +} +libm_hidden_def(sin) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_tan.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_tan.c new file mode 100644 index 00000000..5a2bc930 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_tan.c @@ -0,0 +1,67 @@ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* tan(x) + * Return tangent function of x. + * + * kernel function: + * __kernel_tan ... tangent function on [-pi/4,pi/4] + * __ieee754_rem_pio2 ... argument reduction routine + * + * Method. + * Let S,C and T denote the sin, cos and tan respectively on + * [-PI/4, +PI/4]. Reduce the argument x to y1+y2 = x-k*pi/2 + * in [-pi/4 , +pi/4], and let n = k mod 4. + * We have + * + * n sin(x) cos(x) tan(x) + * ---------------------------------------------------------- + * 0 S C T + * 1 C -S -1/T + * 2 -S -C T + * 3 -C S -1/T + * ---------------------------------------------------------- + * + * Special cases: + * Let trig be any of sin, cos, or tan. + * trig(+-INF) is NaN, with signals; + * trig(NaN) is that NaN; + * + * Accuracy: + * TRIG(x) returns trig(x) nearly rounded + */ + +#include "math.h" +#include "math_private.h" + +double tan(double x) +{ + double y[2],z=0.0; + int32_t n, ix; + + /* High word of x. */ + GET_HIGH_WORD(ix,x); + + /* |x| ~< pi/4 */ + ix &= 0x7fffffff; + if(ix <= 0x3fe921fb) return __kernel_tan(x,z,1); + + /* tan(Inf or NaN) is NaN */ + else if (ix>=0x7ff00000) return x-x; /* NaN */ + + /* argument reduction needed */ + else { + n = __ieee754_rem_pio2(x,y); + return __kernel_tan(y[0],y[1],1-((n&1)<<1)); /* 1 -- n even + -1 -- n odd */ + } +} +libm_hidden_def(tan) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_tanh.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_tanh.c new file mode 100644 index 00000000..89ee2718 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_tanh.c @@ -0,0 +1,73 @@ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* Tanh(x) + * Return the Hyperbolic Tangent of x + * + * Method : + * x -x + * e - e + * 0. tanh(x) is defined to be ----------- + * x -x + * e + e + * 1. reduce x to non-negative by tanh(-x) = -tanh(x). + * 2. 0 <= x <= 2**-55 : tanh(x) := x*(one+x) + * -t + * 2**-55 < x <= 1 : tanh(x) := -----; t = expm1(-2x) + * t + 2 + * 2 + * 1 <= x <= 22.0 : tanh(x) := 1- ----- ; t=expm1(2x) + * t + 2 + * 22.0 < x <= INF : tanh(x) := 1. + * + * Special cases: + * tanh(NaN) is NaN; + * only tanh(0)=0 is exact for finite argument. + */ + +#include "math.h" +#include "math_private.h" + +static const double one=1.0, two=2.0, tiny = 1.0e-300; + +double tanh(double x) +{ + double t,z; + int32_t jx,ix; + + /* High word of |x|. */ + GET_HIGH_WORD(jx,x); + ix = jx&0x7fffffff; + + /* x is INF or NaN */ + if(ix>=0x7ff00000) { + if (jx>=0) return one/x+one; /* tanh(+-inf)=+-1 */ + else return one/x-one; /* tanh(NaN) = NaN */ + } + + /* |x| < 22 */ + if (ix < 0x40360000) { /* |x|<22 */ + if (ix<0x3c800000) /* |x|<2**-55 */ + return x*(one+x); /* tanh(small) = small */ + if (ix>=0x3ff00000) { /* |x|>=1 */ + t = expm1(two*fabs(x)); + z = one - two/(t+two); + } else { + t = expm1(-two*fabs(x)); + z= -t/(t+two); + } + /* |x| > 22, return +-1 */ + } else { + z = one - tiny; /* raised inexact flag */ + } + return (jx>=0)? z: -z; +} +libm_hidden_def(tanh) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_trunc.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_trunc.c new file mode 100644 index 00000000..eb4f6a8f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/s_trunc.c @@ -0,0 +1,55 @@ +/* Truncate argument to nearest integral value not larger than the argument. + Copyright (C) 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include "math_private.h" + +double +trunc (double x) +{ + int32_t i0, j0; + u_int32_t i1; + int sx; + + EXTRACT_WORDS (i0, i1, x); + sx = i0 & 0x80000000; + j0 = ((i0 >> 20) & 0x7ff) - 0x3ff; + if (j0 < 20) + { + if (j0 < 0) + /* The magnitude of the number is < 1 so the result is +-0. */ + INSERT_WORDS (x, sx, 0); + else + INSERT_WORDS (x, sx | (i0 & ~(0x000fffff >> j0)), 0); + } + else if (j0 > 51) + { + if (j0 == 0x400) + /* x is inf or NaN. */ + return x + x; + } + else + { + INSERT_WORDS (x, i0, i1 & ~(0xffffffffu >> (j0 - 20))); + } + + return x; +} +libm_hidden_def(trunc) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/sh/sh4/Makefile.arch b/l4/pkg/uclibc/lib/contrib/uclibc/libm/sh/sh4/Makefile.arch new file mode 100644 index 00000000..e38e99c1 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/sh/sh4/Makefile.arch @@ -0,0 +1,24 @@ +# Makefile for uClibc +# +# Copyright (c) 2007, 2010 STMicroelectronics Ltd +# +# Author(s): Carmelo Amoroso +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +ifeq ($(UCLIBC_HAS_FENV),y) +libm_ARCH_CSRC:=$(wildcard $(libm_SUBARCH_DIR)/*.c) +libm_ARCH_COBJ:=$(patsubst $(libm_SUBARCH_DIR)/%.c,$(libm_SUBARCH_OUT)/%.o,$(libm_ARCH_SRC)) +libm_ARCH_SSRC:=$(wildcard $(libm_SUBARCH_DIR)/*.S) +libm_ARCH_SOBJ:=$(patsubst $(libm_SUBARCH_DIR)/%.S,$(libm_SUBARCH_OUT)/%.o,$(libm_ARCH_SSRC)) +endif + +libm_ARCH_OBJS:=$(libm_ARCH_COBJ) $(libm_ARCH_SOBJ) + +ifeq ($(DOPIC),y) +libm-a-y+=$(libm_ARCH_OBJS:.o=.os) +else +libm-a-y+=$(libm_ARCH_OBJS) +endif +libm-so-y+=$(libm_ARCH_OBJS:.o=.os) + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/sh/sh4/feholdexcpt.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/sh/sh4/feholdexcpt.c new file mode 100644 index 00000000..70b51e8d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/sh/sh4/feholdexcpt.c @@ -0,0 +1,29 @@ +/* + * + * Copyright (c) 2007 STMicroelectronics Ltd + * Filippo Arcidiacono (filippo.arcidiacono@st.com) + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Taken from glibc 2.6 + * + */ + +#include +#include + +int +feholdexcept (fenv_t *envp) +{ + unsigned long int temp; + + /* Store the environment. */ + _FPU_GETCW (temp); + envp->__fpscr = temp; + + /* Now set all exceptions to non-stop. */ + temp &= ~FE_ALL_EXCEPT; + _FPU_SETCW (temp); + + return 1; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/sh/sh4/fesetenv.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/sh/sh4/fesetenv.c new file mode 100644 index 00000000..c5cfc1d5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/sh/sh4/fesetenv.c @@ -0,0 +1,26 @@ +/* + * + * Copyright (c) 2007 STMicroelectronics Ltd + * Filippo Arcidiacono (filippo.arcidiacono@st.com) + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + * Taken from glibc 2.6 + * + */ + +#include +#include + +int +fesetenv (const fenv_t *envp) +{ + if (envp == FE_DFL_ENV) + _FPU_SETCW (_FPU_DEFAULT); + else + { + unsigned long int temp = envp->__fpscr; + _FPU_SETCW (temp); + } + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/sh/sh4/s_lrintf.S b/l4/pkg/uclibc/lib/contrib/uclibc/libm/sh/sh4/s_lrintf.S new file mode 100644 index 00000000..d8cec329 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/sh/sh4/s_lrintf.S @@ -0,0 +1,52 @@ +/* Round argument to nearest integer value. SH4 version. + * According to ISO/IEC 9899:1999. This version doesn't handle range error. + * If arg is not finite or if the result cannot be represented into a long, + * return an unspecified value. No exception raised. + * + * Copyright (C) 2010 STMicroelectronics Ltd. + * + * Author: Christian Bruel + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +ENTRY(lrintf) + mov #0,r0 + sts fpscr,r3 + lds r0,fpscr + flds fr5,fpul + mov.l LOCAL(mask),r1 + sts fpul,r2 + and r2,r1 + mov.l LOCAL(midway),r2 + or r1,r2 + lds r2,fpul + fsts fpul,fr2 + fadd fr2,fr5 + ftrc fr5,fpul + sts fpul,r0 + float fpul,fr2 + fcmp/eq fr5,fr2 + bf/s 0f + mov #1,r2 + tst r1,r1 + and r0,r2 + movt r1 + shal r1 + tst r2,r2 + add #-1,r1 + bt 0f + sub r1,r0 +0: + rts + lds r3,fpscr + + .align 2 +LOCAL(mask): + .long 0x80000000 +LOCAL(midway): + .long 1056964608 + +END(lrintf) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/sh/sh4/s_lroundf.S b/l4/pkg/uclibc/lib/contrib/uclibc/libm/sh/sh4/s_lroundf.S new file mode 100644 index 00000000..fda3a4b9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/sh/sh4/s_lroundf.S @@ -0,0 +1,39 @@ +/* Round argument toward 0. SH4 version. + * According to ISO/IEC 9899:1999. This version doesn't handle range error. + * If arg is not finite or if the result cannot be represented into a long, + * return an unspecified value. No exception raised. + * + * Copyright (C) 2010 STMicroelectronics Ltd. + * + * Author: Christian Bruel + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +ENTRY(lroundf) + mov #0,r0 + sts fpscr,r3 + lds r0,fpscr + flds fr5,fpul + mov.l LOCAL(mask),r1 + sts fpul,r2 + and r2,r1 + mov.l LOCAL(midway),r2 + or r1,r2 + lds r2,fpul + fsts fpul,fr2 + fadd fr2,fr5 + ftrc fr5,fpul + sts fpul,r0 + rts + lds r3,fpscr + + .align 2 +LOCAL(mask): + .long 0x80000000 +LOCAL(midway): + .long 1056964608 + +END(lroundf) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/w_cabs.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/w_cabs.c new file mode 100644 index 00000000..4044f4bf --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/w_cabs.c @@ -0,0 +1,15 @@ +/* + * cabs() wrapper for hypot(). + * + * Written by J.T. Conklin, + * Placed into the Public Domain, 1994. + */ + +#include +#include + +double cabs(double _Complex z) +{ + return hypot(__real__ z, __imag__ z); +} +libm_hidden_def(cabs) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libm/w_exp2.c b/l4/pkg/uclibc/lib/contrib/uclibc/libm/w_exp2.c new file mode 100644 index 00000000..e00277ab --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libm/w_exp2.c @@ -0,0 +1,19 @@ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +#include "math.h" +#include "math_private.h" + +double exp2(double x) +{ + return pow(2.0, x); +} +libm_hidden_def(exp2) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libnsl/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libnsl/Makefile new file mode 100644 index 00000000..c8dc9b46 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libnsl/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../ +top_builddir=../ +include $(top_builddir)Rules.mak +all: libs +include Makefile.in +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libnsl/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/libnsl/Makefile.in new file mode 100644 index 00000000..3aa05a0f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libnsl/Makefile.in @@ -0,0 +1,52 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +subdirs += libnsl + +CFLAGS-libnsl := -DNOT_IN_libc -DIS_IN_libnsl $(SSP_ALL_CFLAGS) + +LDFLAGS-libnsl.so := $(LDFLAGS) $(call link.asneeded,-lc) + +LIBS-libnsl.so := $(LIBS) + +libnsl_FULL_NAME := libnsl-$(VERSION).so + +libnsl_DIR := $(top_srcdir)libnsl +libnsl_OUT := $(top_builddir)libnsl + +libnsl_SRC := $(libnsl_DIR)/nsl.c +libnsl_OBJ := $(patsubst $(libnsl_DIR)/%.c,$(libnsl_OUT)/%.o,$(libnsl_SRC)) + +ifeq ($(DOPIC),y) +libnsl-a-y := $(libnsl_OBJ:.o=.os) +else +libnsl-a-y := $(libnsl_OBJ) +endif +libnsl-so-y := $(libnsl_OBJ:.o=.os) + +lib-a-$(UCLIBC_HAS_LIBNSL_STUB) += $(top_builddir)lib/libnsl.a +lib-so-$(UCLIBC_HAS_LIBNSL_STUB) += $(top_builddir)lib/libnsl.so +objclean-y += CLEAN_libnsl + +ifeq ($(DOPIC),y) +$(top_builddir)lib/libnsl.so: $(top_builddir)lib/libnsl.a $(libc.depend) +else +$(top_builddir)lib/libnsl.so: $(libnsl_OUT)/libnsl_so.a $(libc.depend) +endif + $(call link.so,$(libnsl_FULL_NAME),$(ABI_VERSION)) + +$(libnsl_OUT)/libnsl_so.a: $(libnsl-so-y) + $(Q)$(RM) $@ + $(do_ar) + +$(top_builddir)lib/libnsl.a: $(libnsl-a-y) + $(Q)$(INSTALL) -d $(dir $@) + $(Q)$(RM) $@ + $(do_ar) + +CLEAN_libnsl: + $(do_rm) $(addprefix $(libnsl_OUT)/*., o os a) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libnsl/nsl.c b/l4/pkg/uclibc/lib/contrib/uclibc/libnsl/nsl.c new file mode 100644 index 00000000..37d5b936 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libnsl/nsl.c @@ -0,0 +1,17 @@ +/* vi: set sw=4 ts=4: */ +/* + * libnsl for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +void __stub2(void); +void __stub2(void) +{ + return; +} +link_warning (__stub2, "the `libnsl' library is a stub. Do you really need it?") diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/Makefile new file mode 100644 index 00000000..c8dc9b46 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../ +top_builddir=../ +include $(top_builddir)Rules.mak +all: libs +include Makefile.in +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/Makefile.in new file mode 100644 index 00000000..d1f8528a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/Makefile.in @@ -0,0 +1,11 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +ifneq ($(PTNAME),) +include $(top_srcdir)$(PTDIR)/Makefile.in +include $(top_srcdir)$(PTDIR)_db/Makefile.in +endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/Makefile new file mode 100644 index 00000000..f9100219 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../ +top_builddir=../../ +include $(top_builddir)Rules.mak +all: libs +include Makefile.in +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/Makefile.in new file mode 100644 index 00000000..d2e29c72 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/Makefile.in @@ -0,0 +1,126 @@ +# Makefile for uClibc +# +# Copyright (C) 2003 Paul Mundt +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +subdirs += libpthread/linuxthreads.old + +CFLAGS-dir_linuxthreads.old := -DNOT_IN_libc -DIS_IN_libpthread +CFLAGS-linuxthreads.old := $(CFLAGS-dir_linuxthreads.old) $(SSP_ALL_CFLAGS) + +CFLAGS-libpthread/linuxthreads.old/sysdeps/$(TARGET_ARCH)/ := $(CFLAGS-linuxthreads.old) + +ifeq ($(PTHREADS_DEBUG_SUPPORT),y) +LDFLAGS-libpthread.so := $(LDFLAGS_NOSTRIP) -Wl,-z,defs +else +LDFLAGS-libpthread.so := $(LDFLAGS) +endif + +LIBS-libpthread.so := $(LIBS) $(ldso) + +START_FILE-libpthread.so := $(SHARED_START_FILES) +END_FILE-libpthread.so := $(SHARED_END_FILES) + +libpthread_FULL_NAME := libpthread-$(VERSION).so + +libpthread_DIR := $(top_srcdir)libpthread/linuxthreads.old +libpthread_OUT := $(top_builddir)libpthread/linuxthreads.old + +-include $(libpthread_DIR)/sysdeps/$(TARGET_ARCH)/Makefile.arch + +libpthread_SRC := \ + attr.c cancel.c condvar.c errno.c events.c join.c lockfile.c manager.c \ + mutex.c oldsemaphore.c pt-machine.c ptfork.c ptlongjmp.c \ + rwlock.c semaphore.c signals.c specific.c spinlock.c wrapsyscall.c +ifeq ($(UCLIBC_HAS_XLOCALE),y) +libpthread_SRC += locale.c +endif + +libpthread_SPEC_SRC := pthread.c +libpthread_SPEC_SRC := $(patsubst %.c,$(libpthread_DIR)/%.c,$(libpthread_SPEC_SRC)) + +# remove generic sources, if arch specific version is present +ifneq ($(strip $(libpthread_ARCH_SRC)),) +libpthread_SRC := $(filter-out $(patsubst %.c,$(libpthread_DIR)/%.c,$(notdir $(libpthread_ARCH_SRC))),$(libpthread_SRC)) +endif + +libpthread_SRC := $(patsubst %,$(libpthread_DIR)/%,$(libpthread_SRC)) + +libpthread_OBJ := $(patsubst $(libpthread_DIR)/%.c,$(libpthread_OUT)/%.o,$(libpthread_SRC)) + +# +# Stuff that goes into libc.so, not libpthread.so +# +CFLAGS-OMIT-forward.c := $(CFLAGS-dir_linuxthreads.old) +CFLAGS-OMIT-libc_pthread_init.c := $(CFLAGS-dir_linuxthreads.old) +libpthread_libc_CSRC := forward.c libc_pthread_init.c +libpthread_libc_OBJ := $(patsubst %.c, $(libpthread_OUT)/%.o,$(libpthread_libc_CSRC)) +libc-static-y += $(libpthread_OUT)/libc_pthread_init.o +libc-shared-y += $(libpthread_libc_OBJ:.o=.oS) + +libpthread-static-y += $(patsubst $(libpthread_DIR)/%.c,$(libpthread_OUT)/%.o,$(libpthread_SPEC_SRC)) +libpthread-shared-y += $(patsubst $(libpthread_DIR)/%.c,$(libpthread_OUT)/%.oS,$(libpthread_SPEC_SRC)) + +ifeq ($(DOPIC),y) +libpthread-a-y += $(libpthread_OBJ:.o=.os) $(libpthread-static-y:.o=.os) +else +libpthread-a-y += $(libpthread_OBJ) $(libpthread-static-y) +endif +libpthread-so-y += $(libpthread_OBJ:.o=.os) $(libpthread-shared-y) + +lib-a-$(UCLIBC_HAS_THREADS) += $(top_builddir)lib/libpthread.a +lib-so-$(UCLIBC_HAS_THREADS) += $(top_builddir)lib/libpthread.so + +#ifeq ($(DOMULTI),n) +$(top_builddir)lib/libpthread.so: $(libpthread_OUT)/libpthread_so.a $(libc.depend) + $(call link.so,$(libpthread_FULL_NAME),$(ABI_VERSION)) +#else +#$(top_builddir)lib/libpthread.so: $(libpthread_OUT)/libpthread.oS | $(libc.depend) +# $(call linkm.so,$(libpthread_FULL_NAME),$(ABI_VERSION)) +#endif + +ifeq ($(PTHREADS_DEBUG_SUPPORT),y) +$(libpthread_OUT)/libpthread_so.a: STRIP_FLAGS:=$(STRIP_FLAGS:-x=-X --strip-debug) +endif +$(libpthread_OUT)/libpthread_so.a: $(libpthread-so-y) + $(Q)$(RM) $@ + $(do_ar) + +ifeq ($(PTHREADS_DEBUG_SUPPORT),y) +$(libpthread_OUT)/libpthread.oS: STRIP_FLAGS:=$(STRIP_FLAGS:-x=-X --strip-debug) +endif +$(libpthread_OUT)/libpthread.oS: $(libpthread_SRC) $(libpthread_SPEC_SRC) + $(Q)$(RM) $@ + $(compile-m) + +ifeq ($(PTHREADS_DEBUG_SUPPORT),y) +$(top_builddir)lib/libpthread.a: STRIP_FLAGS:=$(STRIP_FLAGS:-x=-X --strip-debug) +endif +$(top_builddir)lib/libpthread.a: $(libpthread-a-y) + $(Q)$(INSTALL) -d $(dir $@) + $(Q)$(RM) $@ + $(do_ar) + +$(top_builddir)include/pthread.h: + $(do_ln) $(call rel_srcdir)$(PTDIR)/sysdeps/pthread/$(@F) $@ +$(top_builddir)include/semaphore.h: + $(do_ln) $(call rel_srcdir)$(PTDIR)/$(@F) $@ +$(top_builddir)include/bits/pthreadtypes.h: | $(top_builddir)include/bits + $(do_ln) $(call rel_srcdir)$(PTDIR)/sysdeps/pthread/bits/$(@F) $@ + +linuxthreads_headers := $(top_builddir)include/pthread.h \ + $(top_builddir)include/semaphore.h \ + $(top_builddir)include/bits/pthreadtypes.h +$(linuxthreads_headers): $(wildcard $(addprefix $(top_builddir)include/config/linuxthreads/,old.h new.h)) +headers-$(UCLIBC_HAS_THREADS) += $(linuxthreads_headers) + +objclean-y += CLEAN_libpthread/linuxthreads.old +headers_clean-y += HEADERCLEAN_libpthread/linuxthreads.old +HEADERCLEAN_libpthread/linuxthreads.old: + $(do_rm) $(linuxthreads_headers) + +CLEAN_libpthread/linuxthreads.old: + $(do_rm) $(addprefix $(libpthread_OUT)/*., o os oS a) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/attr.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/attr.c new file mode 100644 index 00000000..8465c234 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/attr.c @@ -0,0 +1,240 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +/* changed for uClibc */ +#define __sched_get_priority_min sched_get_priority_min +#define __sched_get_priority_max sched_get_priority_max + +/* Handling of thread attributes */ + +#include +#include +#include +#include +#include "pthread.h" +#include "internals.h" + +libpthread_hidden_proto(pthread_attr_destroy) +libpthread_hidden_proto(pthread_attr_init) +libpthread_hidden_proto(pthread_attr_getdetachstate) +libpthread_hidden_proto(pthread_attr_setdetachstate) +libpthread_hidden_proto(pthread_attr_getinheritsched) +libpthread_hidden_proto(pthread_attr_setinheritsched) +libpthread_hidden_proto(pthread_attr_setschedparam) +libpthread_hidden_proto(pthread_attr_getschedparam) +libpthread_hidden_proto(pthread_attr_getschedpolicy) +libpthread_hidden_proto(pthread_attr_setschedpolicy) +libpthread_hidden_proto(pthread_attr_getscope) +libpthread_hidden_proto(pthread_attr_setscope) + +/* NOTE: With uClibc I don't think we need this versioning stuff. + * Therefore, define the function pthread_attr_init() here using + * a strong symbol. */ + +/*int __pthread_attr_init_2_1(pthread_attr_t *attr)*/ +int pthread_attr_init(pthread_attr_t *attr) +{ + size_t ps = getpagesize (); + + attr->__detachstate = PTHREAD_CREATE_JOINABLE; + attr->__schedpolicy = SCHED_OTHER; + attr->__schedparam.sched_priority = 0; + attr->__inheritsched = PTHREAD_EXPLICIT_SCHED; + attr->__scope = PTHREAD_SCOPE_SYSTEM; + attr->__guardsize = ps; + attr->__stackaddr = NULL; + attr->__stackaddr_set = 0; + attr->__stacksize = STACK_SIZE - ps; + return 0; +} +libpthread_hidden_def(pthread_attr_init) + +/* uClibc: leave out this for now. */ +#if defined DO_PTHREAD_VERSIONING_WITH_UCLIBC +#if defined __PIC__ && defined DO_VERSIONING +default_symbol_version (__pthread_attr_init_2_1, pthread_attr_init, GLIBC_2.1); + +int __pthread_attr_init_2_0(pthread_attr_t *attr) +{ + attr->__detachstate = PTHREAD_CREATE_JOINABLE; + attr->__schedpolicy = SCHED_OTHER; + attr->__schedparam.sched_priority = 0; + attr->__inheritsched = PTHREAD_EXPLICIT_SCHED; + attr->__scope = PTHREAD_SCOPE_SYSTEM; + return 0; +} +symbol_version (__pthread_attr_init_2_0, pthread_attr_init, GLIBC_2.0); +#else +strong_alias (__pthread_attr_init_2_1, pthread_attr_init) +#endif +#endif /* DO_PTHREAD_VERSIONING_WITH_UCLIBC */ + +int pthread_attr_destroy(pthread_attr_t *attr attribute_unused) +{ + return 0; +} +libpthread_hidden_def(pthread_attr_destroy) + + +int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate) +{ + if (detachstate < PTHREAD_CREATE_JOINABLE || + detachstate > PTHREAD_CREATE_DETACHED) + return EINVAL; + attr->__detachstate = detachstate; + return 0; +} +libpthread_hidden_def(pthread_attr_setdetachstate) + +int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate) +{ + *detachstate = attr->__detachstate; + return 0; +} +libpthread_hidden_def(pthread_attr_getdetachstate) + +int pthread_attr_setschedparam(pthread_attr_t *attr, + const struct sched_param *param) +{ + int max_prio = __sched_get_priority_max(attr->__schedpolicy); + int min_prio = __sched_get_priority_min(attr->__schedpolicy); + + if (param->sched_priority < min_prio || param->sched_priority > max_prio) + return EINVAL; + memcpy (&attr->__schedparam, param, sizeof (struct sched_param)); + return 0; +} +libpthread_hidden_def(pthread_attr_setschedparam) + +int pthread_attr_getschedparam(const pthread_attr_t *attr, + struct sched_param *param) +{ + memcpy (param, &attr->__schedparam, sizeof (struct sched_param)); + return 0; +} +libpthread_hidden_def(pthread_attr_getschedparam) + +int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy) +{ + if (policy != SCHED_OTHER && policy != SCHED_FIFO && policy != SCHED_RR) + return EINVAL; + attr->__schedpolicy = policy; + return 0; +} +libpthread_hidden_def(pthread_attr_setschedpolicy) + +int pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy) +{ + *policy = attr->__schedpolicy; + return 0; +} +libpthread_hidden_def(pthread_attr_getschedpolicy) + +int pthread_attr_setinheritsched(pthread_attr_t *attr, int inherit) +{ + if (inherit != PTHREAD_INHERIT_SCHED && inherit != PTHREAD_EXPLICIT_SCHED) + return EINVAL; + attr->__inheritsched = inherit; + return 0; +} +libpthread_hidden_def(pthread_attr_setinheritsched) + +int pthread_attr_getinheritsched(const pthread_attr_t *attr, int *inherit) +{ + *inherit = attr->__inheritsched; + return 0; +} +libpthread_hidden_def(pthread_attr_getinheritsched) + +int pthread_attr_setscope(pthread_attr_t *attr, int scope) +{ + switch (scope) { + case PTHREAD_SCOPE_SYSTEM: + attr->__scope = scope; + return 0; + case PTHREAD_SCOPE_PROCESS: + return ENOTSUP; + default: + return EINVAL; + } +} +libpthread_hidden_def(pthread_attr_setscope) + +int pthread_attr_getscope(const pthread_attr_t *attr, int *scope) +{ + *scope = attr->__scope; + return 0; +} +libpthread_hidden_def(pthread_attr_getscope) + +int __pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize) +{ + size_t ps = getpagesize (); + + /* First round up the guard size. */ + guardsize = roundup (guardsize, ps); + + /* The guard size must not be larger than the stack itself */ + if (guardsize >= attr->__stacksize) return EINVAL; + + attr->__guardsize = guardsize; + + return 0; +} +weak_alias (__pthread_attr_setguardsize, pthread_attr_setguardsize) + +int __pthread_attr_getguardsize(const pthread_attr_t *attr, size_t *guardsize) +{ + *guardsize = attr->__guardsize; + return 0; +} +weak_alias (__pthread_attr_getguardsize, pthread_attr_getguardsize) + +#if 0 /* uClibc: deprecated stuff disabled */ +int __pthread_attr_setstackaddr(pthread_attr_t *attr, void *stackaddr) +{ + attr->__stackaddr = stackaddr; + attr->__stackaddr_set = 1; + return 0; +} +weak_alias (__pthread_attr_setstackaddr, pthread_attr_setstackaddr) + +int __pthread_attr_getstackaddr(const pthread_attr_t *attr, void **stackaddr) +{ + /* XXX This function has a stupid definition. The standard specifies + no error value but what is if no stack address was set? We simply + return the value we have in the member. */ + *stackaddr = attr->__stackaddr; + return 0; +} +weak_alias (__pthread_attr_getstackaddr, pthread_attr_getstackaddr) +#endif + +int __pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize) +{ + /* We don't accept value smaller than PTHREAD_STACK_MIN. */ + if (stacksize < PTHREAD_STACK_MIN) + return EINVAL; + + attr->__stacksize = stacksize; + return 0; +} +weak_alias (__pthread_attr_setstacksize, pthread_attr_setstacksize) + +int __pthread_attr_getstacksize(const pthread_attr_t *attr, size_t *stacksize) +{ + *stacksize = attr->__stacksize; + return 0; +} +weak_alias (__pthread_attr_getstacksize, pthread_attr_getstacksize) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/cancel.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/cancel.c new file mode 100644 index 00000000..47534be6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/cancel.c @@ -0,0 +1,221 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +/* Thread cancellation */ + +#define __FORCE_GLIBC +#include +#include +#include "pthread.h" +#include "internals.h" +#include "spinlock.h" +#include "restart.h" +#ifdef __UCLIBC_HAS_RPC__ +#include +extern void __rpc_thread_destroy(void); +#endif +#include + +#include + +#ifdef _STACK_GROWS_DOWN +# define FRAME_LEFT(frame, other) ((char *) frame >= (char *) other) +#elif defined _STACK_GROWS_UP +# define FRAME_LEFT(frame, other) ((char *) frame <= (char *) other) +#else +# error "Define either _STACK_GROWS_DOWN or _STACK_GROWS_UP" +#endif + +libpthread_hidden_proto(pthread_setcancelstate) +libpthread_hidden_proto(pthread_setcanceltype) + +int pthread_setcancelstate(int state, int * oldstate) +{ + pthread_descr self = thread_self(); + if (state < PTHREAD_CANCEL_ENABLE || state > PTHREAD_CANCEL_DISABLE) + return EINVAL; + if (oldstate != NULL) *oldstate = THREAD_GETMEM(self, p_cancelstate); + THREAD_SETMEM(self, p_cancelstate, state); + if (THREAD_GETMEM(self, p_canceled) && + THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE && + THREAD_GETMEM(self, p_canceltype) == PTHREAD_CANCEL_ASYNCHRONOUS) + __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); + return 0; +} +libpthread_hidden_def(pthread_setcancelstate) + +int pthread_setcanceltype(int type, int * oldtype) +{ + pthread_descr self = thread_self(); + if (type < PTHREAD_CANCEL_DEFERRED || type > PTHREAD_CANCEL_ASYNCHRONOUS) + return EINVAL; + if (oldtype != NULL) *oldtype = THREAD_GETMEM(self, p_canceltype); + THREAD_SETMEM(self, p_canceltype, type); + if (THREAD_GETMEM(self, p_canceled) && + THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE && + THREAD_GETMEM(self, p_canceltype) == PTHREAD_CANCEL_ASYNCHRONOUS) + __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); + return 0; +} +libpthread_hidden_def(pthread_setcanceltype) + +int pthread_cancel(pthread_t thread) +{ + pthread_handle handle = thread_handle(thread); + int pid; + int dorestart = 0; + pthread_descr th; + pthread_extricate_if *pextricate; + int already_canceled; + + __pthread_lock(&handle->h_lock, NULL); + if (invalid_handle(handle, thread)) { + __pthread_unlock(&handle->h_lock); + return ESRCH; + } + + th = handle->h_descr; + + already_canceled = th->p_canceled; + th->p_canceled = 1; + + if (th->p_cancelstate == PTHREAD_CANCEL_DISABLE || already_canceled) { + __pthread_unlock(&handle->h_lock); + return 0; + } + + pextricate = th->p_extricate; + pid = th->p_pid; + + /* If the thread has registered an extrication interface, then + invoke the interface. If it returns 1, then we succeeded in + dequeuing the thread from whatever waiting object it was enqueued + with. In that case, it is our responsibility to wake it up. + And also to set the p_woken_by_cancel flag so the woken thread + can tell that it was woken by cancellation. */ + + if (pextricate != NULL) { + dorestart = pextricate->pu_extricate_func(pextricate->pu_object, th); + th->p_woken_by_cancel = dorestart; + } + + __pthread_unlock(&handle->h_lock); + + /* If the thread has suspended or is about to, then we unblock it by + issuing a restart, instead of a cancel signal. Otherwise we send + the cancel signal to unblock the thread from a cancellation point, + or to initiate asynchronous cancellation. The restart is needed so + we have proper accounting of restarts; suspend decrements the thread's + resume count, and restart() increments it. This also means that suspend's + handling of the cancel signal is obsolete. */ + + if (dorestart) + restart(th); + else + kill(pid, __pthread_sig_cancel); + + return 0; +} + +void pthread_testcancel(void) +{ + pthread_descr self = thread_self(); + if (THREAD_GETMEM(self, p_canceled) + && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) + __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); +} + +void _pthread_cleanup_push(struct _pthread_cleanup_buffer * buffer, + void (*routine)(void *), void * arg) +{ + pthread_descr self = thread_self(); + buffer->__routine = routine; + buffer->__arg = arg; + buffer->__prev = THREAD_GETMEM(self, p_cleanup); + if (buffer->__prev != NULL && FRAME_LEFT (buffer, buffer->__prev)) + buffer->__prev = NULL; + THREAD_SETMEM(self, p_cleanup, buffer); +} + +void _pthread_cleanup_pop(struct _pthread_cleanup_buffer * buffer, + int execute) +{ + pthread_descr self = thread_self(); + if (execute) buffer->__routine(buffer->__arg); + THREAD_SETMEM(self, p_cleanup, buffer->__prev); +} + +void _pthread_cleanup_push_defer(struct _pthread_cleanup_buffer * buffer, + void (*routine)(void *), void * arg) +{ + pthread_descr self = thread_self(); + buffer->__routine = routine; + buffer->__arg = arg; + buffer->__canceltype = THREAD_GETMEM(self, p_canceltype); + buffer->__prev = THREAD_GETMEM(self, p_cleanup); + if (buffer->__prev != NULL && FRAME_LEFT (buffer, buffer->__prev)) + buffer->__prev = NULL; + THREAD_SETMEM(self, p_canceltype, PTHREAD_CANCEL_DEFERRED); + THREAD_SETMEM(self, p_cleanup, buffer); +} +strong_alias(_pthread_cleanup_push_defer,__pthread_cleanup_push_defer) + +void _pthread_cleanup_pop_restore(struct _pthread_cleanup_buffer * buffer, + int execute) +{ + pthread_descr self = thread_self(); + if (execute) buffer->__routine(buffer->__arg); + THREAD_SETMEM(self, p_cleanup, buffer->__prev); + THREAD_SETMEM(self, p_canceltype, buffer->__canceltype); + if (THREAD_GETMEM(self, p_canceled) && + THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE && + THREAD_GETMEM(self, p_canceltype) == PTHREAD_CANCEL_ASYNCHRONOUS) + __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); +} +strong_alias(_pthread_cleanup_pop_restore,__pthread_cleanup_pop_restore) + + +void __pthread_perform_cleanup(char *currentframe) +{ + pthread_descr self = thread_self(); + struct _pthread_cleanup_buffer * c; + + for (c = THREAD_GETMEM(self, p_cleanup); c != NULL; c = c->__prev) + { +#ifdef _STACK_GROWS_DOWN + if ((char *) c <= currentframe) + break; +#elif defined _STACK_GROWS_UP + if ((char *) c >= currentframe) + break; +#else +# error "Define either _STACK_GROWS_DOWN or _STACK_GROWS_UP" +#endif + c->__routine(c->__arg); + } + +#ifdef __UCLIBC_HAS_RPC__ + /* And the TSD which needs special help. */ + if (THREAD_GETMEM(self, p_libc_specific[_LIBC_TSD_KEY_RPC_VARS]) != NULL) + __rpc_thread_destroy (); +#endif +} + +#ifndef __PIC__ +/* We need a hook to force the cancelation wrappers to be linked in when + static libpthread is used. */ +extern const char __pthread_provide_wrappers; +static const char *const __pthread_require_wrappers = + &__pthread_provide_wrappers; +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/condvar.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/condvar.c new file mode 100644 index 00000000..23e71393 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/condvar.c @@ -0,0 +1,314 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* and Pavel Krauz (krauz@fsid.cvut.cz). */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +/* Condition variables */ + +#include +#include +#include +#include +#include "pthread.h" +#include "internals.h" +#include "spinlock.h" +#include "queue.h" +#include "restart.h" + +libpthread_hidden_proto(pthread_cond_broadcast) +libpthread_hidden_proto(pthread_cond_destroy) +libpthread_hidden_proto(pthread_cond_init) +libpthread_hidden_proto(pthread_cond_signal) +libpthread_hidden_proto(pthread_cond_wait) +libpthread_hidden_proto(pthread_cond_timedwait) + +libpthread_hidden_proto(pthread_condattr_destroy) +libpthread_hidden_proto(pthread_condattr_init) + +int pthread_cond_init(pthread_cond_t *cond, + const pthread_condattr_t *cond_attr attribute_unused) +{ + __pthread_init_lock(&cond->__c_lock); + cond->__c_waiting = NULL; + return 0; +} +libpthread_hidden_def(pthread_cond_init) + +int pthread_cond_destroy(pthread_cond_t *cond) +{ + if (cond->__c_waiting != NULL) return EBUSY; + return 0; +} +libpthread_hidden_def(pthread_cond_destroy) + +/* Function called by pthread_cancel to remove the thread from + waiting on a condition variable queue. */ + +static int cond_extricate_func(void *obj, pthread_descr th) +{ + volatile pthread_descr self = thread_self(); + pthread_cond_t *cond = obj; + int did_remove = 0; + + __pthread_lock(&cond->__c_lock, self); + did_remove = remove_from_queue(&cond->__c_waiting, th); + __pthread_unlock(&cond->__c_lock); + + return did_remove; +} + +int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) +{ + volatile pthread_descr self = thread_self(); + pthread_extricate_if extr; + int already_canceled = 0; + int spurious_wakeup_count; + + /* Check whether the mutex is locked and owned by this thread. */ + if (mutex->__m_kind != PTHREAD_MUTEX_TIMED_NP + && mutex->__m_kind != PTHREAD_MUTEX_ADAPTIVE_NP + && mutex->__m_owner != self) + return EINVAL; + + /* Set up extrication interface */ + extr.pu_object = cond; + extr.pu_extricate_func = cond_extricate_func; + + /* Register extrication interface */ + THREAD_SETMEM(self, p_condvar_avail, 0); + __pthread_set_own_extricate_if(self, &extr); + + /* Atomically enqueue thread for waiting, but only if it is not + canceled. If the thread is canceled, then it will fall through the + suspend call below, and then call pthread_exit without + having to worry about whether it is still on the condition variable queue. + This depends on pthread_cancel setting p_canceled before calling the + extricate function. */ + + __pthread_lock(&cond->__c_lock, self); + if (!(THREAD_GETMEM(self, p_canceled) + && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE)) + enqueue(&cond->__c_waiting, self); + else + already_canceled = 1; + __pthread_unlock(&cond->__c_lock); + + if (already_canceled) { + __pthread_set_own_extricate_if(self, 0); + __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); + } + + __pthread_mutex_unlock(mutex); + + spurious_wakeup_count = 0; + while (1) + { + suspend(self); + if (THREAD_GETMEM(self, p_condvar_avail) == 0 + && (THREAD_GETMEM(self, p_woken_by_cancel) == 0 + || THREAD_GETMEM(self, p_cancelstate) != PTHREAD_CANCEL_ENABLE)) + { + /* Count resumes that don't belong to us. */ + spurious_wakeup_count++; + continue; + } + break; + } + + __pthread_set_own_extricate_if(self, 0); + + /* Check for cancellation again, to provide correct cancellation + point behavior */ + + if (THREAD_GETMEM(self, p_woken_by_cancel) + && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) { + THREAD_SETMEM(self, p_woken_by_cancel, 0); + __pthread_mutex_lock(mutex); + __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); + } + + /* Put back any resumes we caught that don't belong to us. */ + while (spurious_wakeup_count--) + restart(self); + + __pthread_mutex_lock(mutex); + return 0; +} +libpthread_hidden_def(pthread_cond_wait) + +static int +pthread_cond_timedwait_relative(pthread_cond_t *cond, + pthread_mutex_t *mutex, + const struct timespec * abstime) +{ + volatile pthread_descr self = thread_self(); + int already_canceled = 0; + pthread_extricate_if extr; + int spurious_wakeup_count; + + /* Check whether the mutex is locked and owned by this thread. */ + if (mutex->__m_kind != PTHREAD_MUTEX_TIMED_NP + && mutex->__m_kind != PTHREAD_MUTEX_ADAPTIVE_NP + && mutex->__m_owner != self) + return EINVAL; + + /* Set up extrication interface */ + extr.pu_object = cond; + extr.pu_extricate_func = cond_extricate_func; + + /* Register extrication interface */ + THREAD_SETMEM(self, p_condvar_avail, 0); + __pthread_set_own_extricate_if(self, &extr); + + /* Enqueue to wait on the condition and check for cancellation. */ + __pthread_lock(&cond->__c_lock, self); + if (!(THREAD_GETMEM(self, p_canceled) + && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE)) + enqueue(&cond->__c_waiting, self); + else + already_canceled = 1; + __pthread_unlock(&cond->__c_lock); + + if (already_canceled) { + __pthread_set_own_extricate_if(self, 0); + __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); + } + + __pthread_mutex_unlock(mutex); + + spurious_wakeup_count = 0; + while (1) + { + if (!timedsuspend(self, abstime)) { + int was_on_queue; + + /* __pthread_lock will queue back any spurious restarts that + may happen to it. */ + + __pthread_lock(&cond->__c_lock, self); + was_on_queue = remove_from_queue(&cond->__c_waiting, self); + __pthread_unlock(&cond->__c_lock); + + if (was_on_queue) { + __pthread_set_own_extricate_if(self, 0); + __pthread_mutex_lock(mutex); + return ETIMEDOUT; + } + + /* Eat the outstanding restart() from the signaller */ + suspend(self); + } + + if (THREAD_GETMEM(self, p_condvar_avail) == 0 + && (THREAD_GETMEM(self, p_woken_by_cancel) == 0 + || THREAD_GETMEM(self, p_cancelstate) != PTHREAD_CANCEL_ENABLE)) + { + /* Count resumes that don't belong to us. */ + spurious_wakeup_count++; + continue; + } + break; + } + + __pthread_set_own_extricate_if(self, 0); + + /* The remaining logic is the same as in other cancellable waits, + such as pthread_join sem_wait or pthread_cond wait. */ + + if (THREAD_GETMEM(self, p_woken_by_cancel) + && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) { + THREAD_SETMEM(self, p_woken_by_cancel, 0); + __pthread_mutex_lock(mutex); + __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); + } + + /* Put back any resumes we caught that don't belong to us. */ + while (spurious_wakeup_count--) + restart(self); + + __pthread_mutex_lock(mutex); + return 0; +} + +int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, + const struct timespec * abstime) +{ + /* Indirect call through pointer! */ + return pthread_cond_timedwait_relative(cond, mutex, abstime); +} +libpthread_hidden_def(pthread_cond_timedwait) + +int pthread_cond_signal(pthread_cond_t *cond) +{ + pthread_descr th; + + __pthread_lock(&cond->__c_lock, NULL); + th = dequeue(&cond->__c_waiting); + __pthread_unlock(&cond->__c_lock); + if (th != NULL) { + th->p_condvar_avail = 1; + WRITE_MEMORY_BARRIER(); + restart(th); + } + return 0; +} +libpthread_hidden_def(pthread_cond_signal) + +int pthread_cond_broadcast(pthread_cond_t *cond) +{ + pthread_descr tosignal, th; + + __pthread_lock(&cond->__c_lock, NULL); + /* Copy the current state of the waiting queue and empty it */ + tosignal = cond->__c_waiting; + cond->__c_waiting = NULL; + __pthread_unlock(&cond->__c_lock); + /* Now signal each process in the queue */ + while ((th = dequeue(&tosignal)) != NULL) { + th->p_condvar_avail = 1; + WRITE_MEMORY_BARRIER(); + restart(th); + } + return 0; +} +libpthread_hidden_def(pthread_cond_broadcast) + +int pthread_condattr_init(pthread_condattr_t *attr attribute_unused) +{ + return 0; +} +libpthread_hidden_def(pthread_condattr_init) + +int pthread_condattr_destroy(pthread_condattr_t *attr attribute_unused) +{ + return 0; +} +libpthread_hidden_def(pthread_condattr_destroy) + +int pthread_condattr_getpshared (const pthread_condattr_t *attr attribute_unused, int *pshared) +{ + *pshared = PTHREAD_PROCESS_PRIVATE; + return 0; +} + +int pthread_condattr_setpshared (pthread_condattr_t *attr attribute_unused, int pshared) +{ + if (pshared != PTHREAD_PROCESS_PRIVATE && pshared != PTHREAD_PROCESS_SHARED) + return EINVAL; + + /* For now it is not possible to shared a conditional variable. */ + if (pshared != PTHREAD_PROCESS_PRIVATE) + return ENOSYS; + + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/debug.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/debug.h new file mode 100644 index 00000000..76779dad --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/debug.h @@ -0,0 +1,40 @@ +/**************************************************************************** +** +** NAME: +** debug.h +** +** DESCRIPTION: +** This header file defines the debug macros used in pthreads. To turn +** debugging on, add -DDEBUG_PT to CFLAGS. It was added to the original +** distribution of linuxthreads. +** +** This program is free software; you can redistribute it and/or +** modify it under the terms of the GNU Library General Public License +** as published by the Free Software Foundation; either version 2 +** of the License, or (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU Library General Public License for more details. +** +****************************************************************************/ + +#ifndef _PT_DEBUG_H +#define _PT_DEBUG_H + +#include + +#ifdef __DODEBUG_PT__ +# define DEBUG_PT +#endif + +/* define the PDEBUG macro here */ +#undef PDEBUG +#ifdef DEBUG_PT +# define PDEBUG(fmt, args...) __pthread_message("%s: " fmt, __FUNCTION__, ## args) +#else +# define PDEBUG(fmt, args...) /* debug switched off */ +#endif + +#endif /* _PT_DEBUG_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/errno.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/errno.c new file mode 100644 index 00000000..f5778f98 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/errno.c @@ -0,0 +1,37 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +/* Define the location of errno for the remainder of the C library */ + +#define __FORCE_GLIBC +#include +#include +#include +#include "pthread.h" +#include "internals.h" +#include + +int * +__errno_location (void) +{ + pthread_descr self = thread_self(); + return THREAD_GETMEM (self, p_errnop); +} + +int * +__h_errno_location (void) +{ + pthread_descr self = thread_self(); + return THREAD_GETMEM (self, p_h_errnop); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/events.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/events.c new file mode 100644 index 00000000..a4bf1f89 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/events.c @@ -0,0 +1,37 @@ +/* Event functions used while debugging. + Copyright (C) 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* The functions contained here do nothing, they just return. */ + +#include "internals.h" + +void +__linuxthreads_create_event (void) +{ +} + +void +__linuxthreads_death_event (void) +{ +} + +void +__linuxthreads_reap_event (void) +{ +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/forward.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/forward.c new file mode 100644 index 00000000..402b1554 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/forward.c @@ -0,0 +1,170 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +/* psm: keep this before internals.h */ +#if 0 +vda: here is why: +headers contain libc_hidden_proto(foo). +In libpthread/linuxthreads.old/sysdeps/pthread/bits/libc-lock.h +adding libc_hidden_proto(foo) just before weak_extern (__pthread_initialize) +will not warn: + /* libc_hidden_proto(foo) */ + weak_extern (__pthread_initialize) + /* libc_hidden_proto(foo) */ +but adding after will! Which is extremely strange - +weak_extern expands into just "#pragma weak __pthread_initialize". +TODO: determine whether it is a gcc bug or what +(see gcc.gnu.org/PR36282). +For now, just include all headers before internals.h +(they are again included in internals.h - maybe remove them there later) +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "internals.h" + +/* Pointers to the libc functions. */ +struct pthread_functions __libc_pthread_functions attribute_hidden; + + +# define FORWARD2(name, rettype, decl, params, defaction) \ +rettype \ +name decl \ +{ \ + if (__libc_pthread_functions.ptr_##name == NULL) \ + defaction; \ + \ + return __libc_pthread_functions.ptr_##name params; \ +} + +# define FORWARD(name, decl, params, defretval) \ + FORWARD2 (name, int, decl, params, return defretval) + +FORWARD (pthread_attr_destroy, (pthread_attr_t *attr), (attr), 0) + +FORWARD (pthread_attr_init, (pthread_attr_t *attr), (attr), 0) + +FORWARD (pthread_attr_getdetachstate, + (const pthread_attr_t *attr, int *detachstate), (attr, detachstate), + 0) +FORWARD (pthread_attr_setdetachstate, (pthread_attr_t *attr, int detachstate), + (attr, detachstate), 0) + +FORWARD (pthread_attr_getinheritsched, + (const pthread_attr_t *attr, int *inherit), (attr, inherit), 0) +FORWARD (pthread_attr_setinheritsched, (pthread_attr_t *attr, int inherit), + (attr, inherit), 0) + +FORWARD (pthread_attr_getschedparam, + (const pthread_attr_t *attr, struct sched_param *param), + (attr, param), 0) +FORWARD (pthread_attr_setschedparam, + (pthread_attr_t *attr, const struct sched_param *param), + (attr, param), 0) + +FORWARD (pthread_attr_getschedpolicy, + (const pthread_attr_t *attr, int *policy), (attr, policy), 0) +FORWARD (pthread_attr_setschedpolicy, (pthread_attr_t *attr, int policy), + (attr, policy), 0) + +FORWARD (pthread_attr_getscope, + (const pthread_attr_t *attr, int *scope), (attr, scope), 0) +FORWARD (pthread_attr_setscope, (pthread_attr_t *attr, int scope), + (attr, scope), 0) + + +FORWARD (pthread_condattr_destroy, (pthread_condattr_t *attr), (attr), 0) +FORWARD (pthread_condattr_init, (pthread_condattr_t *attr), (attr), 0) + + +FORWARD (pthread_cond_broadcast, (pthread_cond_t *cond), (cond), 0) + +FORWARD (pthread_cond_destroy, (pthread_cond_t *cond), (cond), 0) + +FORWARD (pthread_cond_init, + (pthread_cond_t *cond, const pthread_condattr_t *cond_attr), + (cond, cond_attr), 0) + +FORWARD (pthread_cond_signal, (pthread_cond_t *cond), (cond), 0) + +FORWARD (pthread_cond_wait, (pthread_cond_t *cond, pthread_mutex_t *mutex), + (cond, mutex), 0) + +FORWARD (pthread_cond_timedwait, + (pthread_cond_t *cond, pthread_mutex_t *mutex, + const struct timespec *abstime), (cond, mutex, abstime), 0) + + +FORWARD (pthread_equal, (pthread_t thread1, pthread_t thread2), + (thread1, thread2), 1) + + +/* Use an alias to avoid warning, as pthread_exit is declared noreturn. */ +FORWARD2 (__pthread_exit, void, (void *retval), (retval), exit (EXIT_SUCCESS)) +strong_alias (__pthread_exit, pthread_exit) + + +FORWARD (pthread_getschedparam, + (pthread_t target_thread, int *policy, struct sched_param *param), + (target_thread, policy, param), 0) +FORWARD (pthread_setschedparam, + (pthread_t target_thread, int policy, + const struct sched_param *param), (target_thread, policy, param), 0) + + +FORWARD (pthread_mutex_destroy, (pthread_mutex_t *mutex), (mutex), 0) + +FORWARD (pthread_mutex_init, + (pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr), + (mutex, mutexattr), 0) +strong_alias(pthread_mutex_init, __pthread_mutex_init) + +FORWARD (pthread_mutex_lock, (pthread_mutex_t *mutex), (mutex), 0) +strong_alias(pthread_mutex_lock, __pthread_mutex_lock) + +FORWARD (pthread_mutex_trylock, (pthread_mutex_t *mutex), (mutex), 0) +strong_alias(pthread_mutex_trylock, __pthread_mutex_trylock) + +FORWARD (pthread_mutex_unlock, (pthread_mutex_t *mutex), (mutex), 0) +strong_alias(pthread_mutex_unlock, __pthread_mutex_unlock) + +FORWARD2 (pthread_self, pthread_t, (void), (), return 0) + + +FORWARD (pthread_setcancelstate, (int state, int *oldstate), (state, oldstate), + 0) + +FORWARD (pthread_setcanceltype, (int type, int *oldtype), (type, oldtype), 0) + +FORWARD2 (_pthread_cleanup_push, void, (struct _pthread_cleanup_buffer * buffer, void (*routine)(void *), void * arg), (buffer, routine, arg), return) +FORWARD2 (_pthread_cleanup_push_defer, void, (struct _pthread_cleanup_buffer * buffer, void (*routine)(void *), void * arg), (buffer, routine, arg), return) + +FORWARD2 (_pthread_cleanup_pop, void, (struct _pthread_cleanup_buffer * buffer, int execute), (buffer, execute), return) +FORWARD2 (_pthread_cleanup_pop_restore, void, (struct _pthread_cleanup_buffer * buffer, int execute), (buffer, execute), return) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/internals.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/internals.h new file mode 100644 index 00000000..637fcea6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/internals.h @@ -0,0 +1,525 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +#ifndef _INTERNALS_H +#define _INTERNALS_H 1 + +/* Internal data structures */ + +/* Includes */ + +#include /* for _LIBC_TSD_KEY_N */ +#include +#include +#include +#include +#include +#include +#include +#include "pt-machine.h" +#include "semaphore.h" +#include "../linuxthreads.old_db/thread_dbP.h" +#ifdef __UCLIBC_HAS_XLOCALE__ +#include +#endif /* __UCLIBC_HAS_XLOCALE__ */ + +/* Use a funky version in a probably vein attempt at preventing gdb + * from dlopen()'ing glibc's libthread_db library... */ +#define VERSION __stringify(__UCLIBC_MAJOR__) "." __stringify(__UCLIBC_MINOR__) "." __stringify(__UCLIBC_SUBLEVEL__) + +#ifndef THREAD_GETMEM +# define THREAD_GETMEM(descr, member) descr->member +#endif +#ifndef THREAD_GETMEM_NC +# define THREAD_GETMEM_NC(descr, member) descr->member +#endif +#ifndef THREAD_SETMEM +# define THREAD_SETMEM(descr, member, value) descr->member = (value) +#endif +#ifndef THREAD_SETMEM_NC +# define THREAD_SETMEM_NC(descr, member, value) descr->member = (value) +#endif + +/* Arguments passed to thread creation routine */ + +struct pthread_start_args { + void * (*start_routine)(void *); /* function to run */ + void * arg; /* its argument */ + sigset_t mask; /* initial signal mask for thread */ + int schedpolicy; /* initial scheduling policy (if any) */ + struct sched_param schedparam; /* initial scheduling parameters (if any) */ +}; + + +/* We keep thread specific data in a special data structure, a two-level + array. The top-level array contains pointers to dynamically allocated + arrays of a certain number of data pointers. So we can implement a + sparse array. Each dynamic second-level array has + PTHREAD_KEY_2NDLEVEL_SIZE + entries. This value shouldn't be too large. */ +#define PTHREAD_KEY_2NDLEVEL_SIZE 32 + +/* We need to address PTHREAD_KEYS_MAX key with PTHREAD_KEY_2NDLEVEL_SIZE + keys in each subarray. */ +#define PTHREAD_KEY_1STLEVEL_SIZE \ + ((PTHREAD_KEYS_MAX + PTHREAD_KEY_2NDLEVEL_SIZE - 1) \ + / PTHREAD_KEY_2NDLEVEL_SIZE) + +typedef void (*destr_function)(void *); + +struct pthread_key_struct { + int in_use; /* already allocated? */ + destr_function destr; /* destruction routine */ +}; + + +#define PTHREAD_START_ARGS_INITIALIZER { NULL, NULL, {{0, }}, 0, { 0 } } + +/* The type of thread descriptors */ + +typedef struct _pthread_descr_struct * pthread_descr; + +/* Callback interface for removing the thread from waiting on an + object if it is cancelled while waiting or about to wait. + This hold a pointer to the object, and a pointer to a function + which ``extricates'' the thread from its enqueued state. + The function takes two arguments: pointer to the wait object, + and a pointer to the thread. It returns 1 if an extrication + actually occured, and hence the thread must also be signalled. + It returns 0 if the thread had already been extricated. */ + +typedef struct _pthread_extricate_struct { + void *pu_object; + int (*pu_extricate_func)(void *, pthread_descr); +} pthread_extricate_if; + +/* Atomic counter made possible by compare_and_swap */ + +struct pthread_atomic { + long p_count; + int p_spinlock; +}; + +/* Context info for read write locks. The pthread_rwlock_info structure + is information about a lock that has been read-locked by the thread + in whose list this structure appears. The pthread_rwlock_context + is embedded in the thread context and contains a pointer to the + head of the list of lock info structures, as well as a count of + read locks that are untracked, because no info structure could be + allocated for them. */ + +struct _pthread_rwlock_t; + +typedef struct _pthread_rwlock_info { + struct _pthread_rwlock_info *pr_next; + struct _pthread_rwlock_t *pr_lock; + int pr_lock_count; +} pthread_readlock_info; + +struct _pthread_descr_struct { + pthread_descr p_nextlive, p_prevlive; + /* Double chaining of active threads */ + pthread_descr p_nextwaiting; /* Next element in the queue holding the thr */ + pthread_descr p_nextlock; /* can be on a queue and waiting on a lock */ + pthread_t p_tid; /* Thread identifier */ + int p_pid; /* PID of Unix process */ + int p_priority; /* Thread priority (== 0 if not realtime) */ + struct _pthread_fastlock * p_lock; /* Spinlock for synchronized accesses */ + int p_signal; /* last signal received */ + sigjmp_buf * p_signal_jmp; /* where to siglongjmp on a signal or NULL */ + sigjmp_buf * p_cancel_jmp; /* where to siglongjmp on a cancel or NULL */ + char p_terminated; /* true if terminated e.g. by pthread_exit */ + char p_detached; /* true if detached */ + char p_exited; /* true if the assoc. process terminated */ + void * p_retval; /* placeholder for return value */ + int p_retcode; /* placeholder for return code */ + pthread_descr p_joining; /* thread joining on that thread or NULL */ + struct _pthread_cleanup_buffer * p_cleanup; /* cleanup functions */ + char p_cancelstate; /* cancellation state */ + char p_canceltype; /* cancellation type (deferred/async) */ + char p_canceled; /* cancellation request pending */ + int * p_errnop; /* pointer to used errno variable */ + int p_errno; /* error returned by last system call */ + int * p_h_errnop; /* pointer to used h_errno variable */ + int p_h_errno; /* error returned by last netdb function */ + char * p_in_sighandler; /* stack address of sighandler, or NULL */ + char p_sigwaiting; /* true if a sigwait() is in progress */ + struct pthread_start_args p_start_args; /* arguments for thread creation */ + void ** p_specific[PTHREAD_KEY_1STLEVEL_SIZE]; /* thread-specific data */ + void * p_libc_specific[_LIBC_TSD_KEY_N]; /* thread-specific data for libc */ + int p_userstack; /* nonzero if the user provided the stack */ + void *p_guardaddr; /* address of guard area or NULL */ + size_t p_guardsize; /* size of guard area */ + pthread_descr p_self; /* Pointer to this structure */ + int p_nr; /* Index of descriptor in __pthread_handles */ + int p_report_events; /* Nonzero if events must be reported. */ + td_eventbuf_t p_eventbuf; /* Data for event. */ + struct pthread_atomic p_resume_count; /* number of times restart() was + called on thread */ + char p_woken_by_cancel; /* cancellation performed wakeup */ + char p_condvar_avail; /* flag if conditional variable became avail */ + char p_sem_avail; /* flag if semaphore became available */ + pthread_extricate_if *p_extricate; /* See above */ + pthread_readlock_info *p_readlock_list; /* List of readlock info structs */ + pthread_readlock_info *p_readlock_free; /* Free list of structs */ + int p_untracked_readlock_count; /* Readlocks not tracked by list */ + /* New elements must be added at the end. */ +#ifdef __UCLIBC_HAS_XLOCALE__ + __locale_t locale; /* thread-specific locale from uselocale() only! */ +#endif /* __UCLIBC_HAS_XLOCALE__ */ +} __attribute__ ((aligned(32))); /* We need to align the structure so that + doubles are aligned properly. This is 8 + bytes on MIPS and 16 bytes on MIPS64. + 32 bytes might give better cache + utilization. */ + +/* The type of thread handles. */ + +typedef struct pthread_handle_struct * pthread_handle; + +struct pthread_handle_struct { + struct _pthread_fastlock h_lock; /* Fast lock for sychronized access */ + pthread_descr h_descr; /* Thread descriptor or NULL if invalid */ + char * h_bottom; /* Lowest address in the stack thread */ +}; + +/* The type of messages sent to the thread manager thread */ + +struct pthread_request { + pthread_descr req_thread; /* Thread doing the request */ + enum { /* Request kind */ + REQ_CREATE, REQ_FREE, REQ_PROCESS_EXIT, REQ_MAIN_THREAD_EXIT, + REQ_POST, REQ_DEBUG, REQ_KICK + } req_kind; + union { /* Arguments for request */ + struct { /* For REQ_CREATE: */ + const pthread_attr_t * attr; /* thread attributes */ + void * (*fn)(void *); /* start function */ + void * arg; /* argument to start function */ + sigset_t mask; /* signal mask */ + } create; + struct { /* For REQ_FREE: */ + pthread_t thread_id; /* identifier of thread to free */ + } free; + struct { /* For REQ_PROCESS_EXIT: */ + int code; /* exit status */ + } exit; + void * post; /* For REQ_POST: the semaphore */ + } req_args; +}; + + +/* Signals used for suspend/restart and for cancellation notification. */ + +extern int __pthread_sig_restart; +extern int __pthread_sig_cancel; + +/* Signal used for interfacing with gdb */ + +extern int __pthread_sig_debug; + +/* Global array of thread handles, used for validating a thread id + and retrieving the corresponding thread descriptor. Also used for + mapping the available stack segments. */ + +extern struct pthread_handle_struct __pthread_handles[PTHREAD_THREADS_MAX]; + +/* Descriptor of the initial thread */ + +extern struct _pthread_descr_struct __pthread_initial_thread; + +/* Descriptor of the manager thread */ + +extern struct _pthread_descr_struct __pthread_manager_thread; + +/* Descriptor of the main thread */ + +extern pthread_descr __pthread_main_thread; + +/* Limit between the stack of the initial thread (above) and the + stacks of other threads (below). Aligned on a STACK_SIZE boundary. + Initially 0, meaning that the current thread is (by definition) + the initial thread. */ + +/* For non-MMU systems also remember to stack top of the initial thread. + * This is adapted when other stacks are malloc'ed since we don't know + * the bounds a-priori. -StS */ + +extern char *__pthread_initial_thread_bos; +#ifndef __ARCH_USE_MMU__ +extern char *__pthread_initial_thread_tos; +#define NOMMU_INITIAL_THREAD_BOUNDS(tos,bos) \ + if ((tos)>=__pthread_initial_thread_bos \ + && (bos)<__pthread_initial_thread_tos) \ + __pthread_initial_thread_bos = (tos)+1 +#else +#define NOMMU_INITIAL_THREAD_BOUNDS(tos,bos) /* empty */ +#endif /* __ARCH_USE_MMU__ */ + + +/* Indicate whether at least one thread has a user-defined stack (if 1), + or all threads have stacks supplied by LinuxThreads (if 0). */ + +extern int __pthread_nonstandard_stacks; + +/* File descriptor for sending requests to the thread manager. + Initially -1, meaning that __pthread_initialize_manager must be called. */ + +extern int __pthread_manager_request; + +/* Other end of the pipe for sending requests to the thread manager. */ + +extern int __pthread_manager_reader; + +/* Limits of the thread manager stack. */ + +extern char *__pthread_manager_thread_bos; +extern char *__pthread_manager_thread_tos; + +/* Pending request for a process-wide exit */ + +extern int __pthread_exit_requested, __pthread_exit_code; + +/* Set to 1 by gdb if we're debugging */ + +extern volatile int __pthread_threads_debug; + +/* Globally enabled events. */ +extern volatile td_thr_events_t __pthread_threads_events; + +/* Pointer to descriptor of thread with last event. */ +extern volatile pthread_descr __pthread_last_event; + +/* Return the handle corresponding to a thread id */ + +static __inline__ pthread_handle thread_handle(pthread_t id) +{ + return &__pthread_handles[id % PTHREAD_THREADS_MAX]; +} + +/* Validate a thread handle. Must have acquired h->h_spinlock before. */ + +static __inline__ int invalid_handle(pthread_handle h, pthread_t id) +{ + return h->h_descr == NULL || h->h_descr->p_tid != id; +} + +/* Fill in defaults left unspecified by pt-machine.h. */ + +/* The page size we can get from the system. This should likely not be + changed by the machine file but, you never know. */ +extern size_t __pagesize; +#include +#ifndef PAGE_SIZE +#define PAGE_SIZE (sysconf (_SC_PAGESIZE)) +#endif + +/* The max size of the thread stack segments. If the default + THREAD_SELF implementation is used, this must be a power of two and + a multiple of PAGE_SIZE. */ +#ifndef STACK_SIZE +#ifdef __ARCH_USE_MMU__ +#define STACK_SIZE (2 * 1024 * 1024) +#else +#define STACK_SIZE (4 * __pagesize) +#endif +#endif + +/* The initial size of the thread stack. Must be a multiple of PAGE_SIZE. */ +#ifndef INITIAL_STACK_SIZE +#define INITIAL_STACK_SIZE (4 * __pagesize) +#endif + +/* Size of the thread manager stack. The "- 32" avoids wasting space + with some malloc() implementations. */ +#ifndef THREAD_MANAGER_STACK_SIZE +#define THREAD_MANAGER_STACK_SIZE (2 * __pagesize - 32) +#endif + +/* The base of the "array" of thread stacks. The array will grow down from + here. Defaults to the calculated bottom of the initial application + stack. */ +#ifndef THREAD_STACK_START_ADDRESS +#define THREAD_STACK_START_ADDRESS __pthread_initial_thread_bos +#endif + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#ifndef CURRENT_STACK_FRAME +#define CURRENT_STACK_FRAME ({ char __csf; &__csf; }) +#endif + +/* If MEMORY_BARRIER isn't defined in pt-machine.h, assume the + architecture doesn't need a memory barrier instruction (e.g. Intel + x86). Still we need the compiler to respect the barrier and emit + all outstanding operations which modify memory. Some architectures + distinguish between full, read and write barriers. */ +#ifndef MEMORY_BARRIER +#define MEMORY_BARRIER() __asm__ ("" : : : "memory") +#endif +#ifndef READ_MEMORY_BARRIER +#define READ_MEMORY_BARRIER() MEMORY_BARRIER() +#endif +#ifndef WRITE_MEMORY_BARRIER +#define WRITE_MEMORY_BARRIER() MEMORY_BARRIER() +#endif + +/* Recover thread descriptor for the current thread */ + +extern pthread_descr __pthread_find_self (void) __attribute__ ((const)); + +static __inline__ pthread_descr thread_self (void) __attribute__ ((const)); +static __inline__ pthread_descr thread_self (void) +{ +#ifdef THREAD_SELF + return THREAD_SELF; +#else + char *sp = CURRENT_STACK_FRAME; +#ifdef __ARCH_USE_MMU__ + if (sp >= __pthread_initial_thread_bos) + return &__pthread_initial_thread; + else if (sp >= __pthread_manager_thread_bos + && sp < __pthread_manager_thread_tos) + return &__pthread_manager_thread; + else if (__pthread_nonstandard_stacks) + return __pthread_find_self(); + else + return (pthread_descr)(((unsigned long)sp | (STACK_SIZE-1))+1) - 1; +#else + /* For non-MMU we need to be more careful about the initial thread stack. + * We refine the initial thread stack bounds dynamically as we allocate + * the other stack frame such that it doesn't overlap with them. Then + * we can be sure to pick the right thread according to the current SP */ + + /* Since we allow other stack frames to be above or below, we need to + * treat this case special. When pthread_initialize() wasn't called yet, + * only the initial thread is there. */ + if (__pthread_initial_thread_bos == NULL) { + return &__pthread_initial_thread; + } + else if (sp >= __pthread_initial_thread_bos + && sp < __pthread_initial_thread_tos) { + return &__pthread_initial_thread; + } + else if (sp >= __pthread_manager_thread_bos + && sp < __pthread_manager_thread_tos) { + return &__pthread_manager_thread; + } + else { + return __pthread_find_self(); + } +#endif /* __ARCH_USE_MMU__ */ +#endif +} + +/* Max number of times we must spin on a spinlock calling sched_yield(). + After MAX_SPIN_COUNT iterations, we put the calling thread to sleep. */ + +#ifndef MAX_SPIN_COUNT +#define MAX_SPIN_COUNT 50 +#endif + +/* Duration of sleep (in nanoseconds) when we can't acquire a spinlock + after MAX_SPIN_COUNT iterations of sched_yield(). + With the 2.0 and 2.1 kernels, this MUST BE > 2ms. + (Otherwise the kernel does busy-waiting for realtime threads, + giving other threads no chance to run.) */ + +#ifndef SPIN_SLEEP_DURATION +#define SPIN_SLEEP_DURATION 2000001 +#endif + +/* Defined and used in libc.so. */ +extern int __libc_multiple_threads attribute_hidden; +extern int __librt_multiple_threads; + +/* Internal global functions */ + +void __pthread_do_exit (void *retval, char *currentframe) + __attribute__ ((__noreturn__)); +void __pthread_destroy_specifics(void); +void __pthread_perform_cleanup(char *currentframe); +int __pthread_initialize_manager(void); +void __pthread_message(char * fmt, ...) + __attribute__ ((__format__ (printf, 1, 2))); +int __pthread_manager(void *reqfd); +int __pthread_manager_event(void *reqfd); +void __pthread_manager_sighandler(int sig); +void __pthread_reset_main_thread(void); +void __fresetlockfiles(void); +void __pthread_manager_adjust_prio(int thread_prio); +void __pthread_initialize_minimal (void); + +extern void __pthread_exit (void *retval) +#if defined NOT_IN_libc && defined IS_IN_libpthread + attribute_noreturn +#endif + ; + +extern int __pthread_attr_setguardsize __P ((pthread_attr_t *__attr, + size_t __guardsize)); +extern int __pthread_attr_getguardsize __P ((__const pthread_attr_t *__attr, + size_t *__guardsize)); +extern int __pthread_attr_setstackaddr __P ((pthread_attr_t *__attr, + void *__stackaddr)); +extern int __pthread_attr_getstackaddr __P ((__const pthread_attr_t *__attr, + void **__stackaddr)); +extern int __pthread_attr_setstacksize __P ((pthread_attr_t *__attr, + size_t __stacksize)); +extern int __pthread_attr_getstacksize __P ((__const pthread_attr_t *__attr, + size_t *__stacksize)); +extern int __pthread_getconcurrency __P ((void)); +extern int __pthread_setconcurrency __P ((int __level)); +extern void __pthread_kill_other_threads_np __P ((void)); + +extern void __pthread_restart_old(pthread_descr th); +extern void __pthread_suspend_old(pthread_descr self); +extern int __pthread_timedsuspend_old(pthread_descr self, const struct timespec *abstime); + +extern void __pthread_restart_new(pthread_descr th); +extern void __pthread_suspend_new(pthread_descr self); +extern int __pthread_timedsuspend_new(pthread_descr self, const struct timespec *abstime); + +extern void __pthread_wait_for_restart_signal(pthread_descr self); + +/* Global pointers to old or new suspend functions */ + +extern void (*__pthread_restart)(pthread_descr); +extern void (*__pthread_suspend)(pthread_descr); + +extern __typeof(pthread_mutex_init) __pthread_mutex_init attribute_hidden; +extern __typeof(pthread_mutex_destroy) __pthread_mutex_destroy attribute_hidden; +extern __typeof(pthread_mutex_lock) __pthread_mutex_lock attribute_hidden; +extern __typeof(pthread_mutex_trylock) __pthread_mutex_trylock attribute_hidden; +extern __typeof(pthread_mutex_unlock) __pthread_mutex_attribute_hidden; + +/* Prototypes for some of the new semaphore functions. */ +extern int __new_sem_post (sem_t * sem); + +/* TSD. */ +extern int __pthread_internal_tsd_set (int key, const void * pointer); +extern void * __pthread_internal_tsd_get (int key); +extern void ** __attribute__ ((__const__)) + __pthread_internal_tsd_address (int key); + +/* The functions called the signal events. */ +extern void __linuxthreads_create_event (void); +extern void __linuxthreads_death_event (void); +extern void __linuxthreads_reap_event (void); + +#include + +extern int * __libc_pthread_init (const struct pthread_functions *functions); + +#endif /* internals.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/join.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/join.c new file mode 100644 index 00000000..4a7c0d8a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/join.c @@ -0,0 +1,231 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +/* Thread termination and joining */ + +#include +#include +#include +#include +#include +#include "pthread.h" +#include "internals.h" +#include "spinlock.h" +#include "restart.h" +#include "debug.h" /* PDEBUG, added by StS */ + +libpthread_hidden_proto(pthread_exit) +void pthread_exit(void * retval) +{ + __pthread_do_exit (retval, CURRENT_STACK_FRAME); +} +libpthread_hidden_def (pthread_exit) + +void __pthread_do_exit(void *retval, char *currentframe) +{ + pthread_descr self = thread_self(); + pthread_descr joining; + struct pthread_request request; + PDEBUG("self=%p, pid=%d\n", self, self->p_pid); + + /* obey POSIX behavior and prevent cancellation functions from + * being called more than once. + * http://sourceware.org/ml/libc-ports/2006-10/msg00043.html + */ + THREAD_SETMEM(self, p_cancelstate, PTHREAD_CANCEL_DISABLE); + THREAD_SETMEM(self, p_canceltype, PTHREAD_CANCEL_DEFERRED); + + /* Call cleanup functions and destroy the thread-specific data */ + __pthread_perform_cleanup(currentframe); + __pthread_destroy_specifics(); + /* Store return value */ + __pthread_lock(THREAD_GETMEM(self, p_lock), self); + THREAD_SETMEM(self, p_retval, retval); + /* See whether we have to signal the death. */ + if (THREAD_GETMEM(self, p_report_events)) + { + /* See whether TD_DEATH is in any of the mask. */ + int idx = __td_eventword (TD_DEATH); + uint32_t mask = __td_eventmask (TD_DEATH); + + if ((mask & (__pthread_threads_events.event_bits[idx] + | THREAD_GETMEM_NC(self, + p_eventbuf.eventmask).event_bits[idx])) + != 0) + { + /* Yep, we have to signal the death. */ + THREAD_SETMEM(self, p_eventbuf.eventnum, TD_DEATH); + THREAD_SETMEM(self, p_eventbuf.eventdata, self); + __pthread_last_event = self; + + /* Now call the function to signal the event. */ + __linuxthreads_death_event(); + } + } + /* Say that we've terminated */ + THREAD_SETMEM(self, p_terminated, 1); + /* See if someone is joining on us */ + joining = THREAD_GETMEM(self, p_joining); + PDEBUG("joining = %p, pid=%d\n", joining, joining ? joining->p_pid : 0); + __pthread_unlock(THREAD_GETMEM(self, p_lock)); + /* Restart joining thread if any */ + if (joining != NULL) restart(joining); + /* If this is the initial thread, block until all threads have terminated. + If another thread calls exit, we'll be terminated from our signal + handler. */ + if (self == __pthread_main_thread && __pthread_manager_request >= 0) { + request.req_thread = self; + request.req_kind = REQ_MAIN_THREAD_EXIT; + TEMP_FAILURE_RETRY(write(__pthread_manager_request, + (char *)&request, sizeof(request))); + suspend(self); + /* Main thread flushes stdio streams and runs atexit functions. + * It also calls a handler within LinuxThreads which sends a process exit + * request to the thread manager. */ + exit(0); + } + /* Exit the process (but don't flush stdio streams, and don't run + atexit functions). */ + _exit(0); +} + +/* Function called by pthread_cancel to remove the thread from + waiting on a condition variable queue. */ + +static int join_extricate_func(void *obj, pthread_descr th attribute_unused) +{ + volatile pthread_descr self = thread_self(); + pthread_handle handle = obj; + pthread_descr jo; + int did_remove = 0; + + __pthread_lock(&handle->h_lock, self); + jo = handle->h_descr; + did_remove = jo->p_joining != NULL; + jo->p_joining = NULL; + __pthread_unlock(&handle->h_lock); + + return did_remove; +} + +int pthread_join(pthread_t thread_id, void ** thread_return) +{ + volatile pthread_descr self = thread_self(); + struct pthread_request request; + pthread_handle handle = thread_handle(thread_id); + pthread_descr th; + pthread_extricate_if extr; + int already_canceled = 0; + PDEBUG("\n"); + + /* Set up extrication interface */ + extr.pu_object = handle; + extr.pu_extricate_func = join_extricate_func; + + __pthread_lock(&handle->h_lock, self); + if (invalid_handle(handle, thread_id)) { + __pthread_unlock(&handle->h_lock); + return ESRCH; + } + th = handle->h_descr; + if (th == self) { + __pthread_unlock(&handle->h_lock); + return EDEADLK; + } + /* If detached or already joined, error */ + if (th->p_detached || th->p_joining != NULL) { + __pthread_unlock(&handle->h_lock); + return EINVAL; + } + /* If not terminated yet, suspend ourselves. */ + if (! th->p_terminated) { + /* Register extrication interface */ + __pthread_set_own_extricate_if(self, &extr); + if (!(THREAD_GETMEM(self, p_canceled) + && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE)) + th->p_joining = self; + else + already_canceled = 1; + __pthread_unlock(&handle->h_lock); + + if (already_canceled) { + __pthread_set_own_extricate_if(self, 0); + __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); + } + + PDEBUG("before suspend\n"); + suspend(self); + PDEBUG("after suspend\n"); + /* Deregister extrication interface */ + __pthread_set_own_extricate_if(self, 0); + + /* This is a cancellation point */ + if (THREAD_GETMEM(self, p_woken_by_cancel) + && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) { + THREAD_SETMEM(self, p_woken_by_cancel, 0); + __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); + } + __pthread_lock(&handle->h_lock, self); + } + /* Get return value */ + if (thread_return != NULL) *thread_return = th->p_retval; + __pthread_unlock(&handle->h_lock); + /* Send notification to thread manager */ + if (__pthread_manager_request >= 0) { + request.req_thread = self; + request.req_kind = REQ_FREE; + request.req_args.free.thread_id = thread_id; + TEMP_FAILURE_RETRY(write(__pthread_manager_request, + (char *) &request, sizeof(request))); + } + return 0; +} + +int pthread_detach(pthread_t thread_id) +{ + int terminated; + struct pthread_request request; + pthread_handle handle = thread_handle(thread_id); + pthread_descr th; + + __pthread_lock(&handle->h_lock, NULL); + if (invalid_handle(handle, thread_id)) { + __pthread_unlock(&handle->h_lock); + return ESRCH; + } + th = handle->h_descr; + /* If already detached, error */ + if (th->p_detached) { + __pthread_unlock(&handle->h_lock); + return EINVAL; + } + /* If already joining, don't do anything. */ + if (th->p_joining != NULL) { + __pthread_unlock(&handle->h_lock); + return 0; + } + /* Mark as detached */ + th->p_detached = 1; + terminated = th->p_terminated; + __pthread_unlock(&handle->h_lock); + /* If already terminated, notify thread manager to reclaim resources */ + if (terminated && __pthread_manager_request >= 0) { + request.req_thread = thread_self(); + request.req_kind = REQ_FREE; + request.req_args.free.thread_id = thread_id; + TEMP_FAILURE_RETRY(write(__pthread_manager_request, + (char *) &request, sizeof(request))); + } + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/libc_pthread_init.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/libc_pthread_init.c new file mode 100644 index 00000000..b54162d6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/libc_pthread_init.c @@ -0,0 +1,58 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + +/* see comment in forward.c */ +#define GCC_RENAME_BUG 1 +#ifdef GCC_RENAME_BUG +# include +# include +# include +# include +# include +#endif + +#include "internals.h" +#include "sysdeps/pthread/pthread-functions.h" + + +int __libc_multiple_threads attribute_hidden __attribute__((nocommon)); + +int * __libc_pthread_init (const struct pthread_functions *functions) +{ +#ifdef SHARED + /* We copy the content of the variable pointed to by the FUNCTIONS + parameter to one in libc.so since this means access to the array + can be done with one memory access instead of two. */ + memcpy (&__libc_pthread_functions, functions, + sizeof (__libc_pthread_functions)); +#endif + +#if ! defined USE___THREAD && defined __UCLIBC_HAS_XLOCALE__ + /* Initialize thread-locale current locale to point to the global one. + With __thread support, the variable's initializer takes care of this. */ + uselocale (LC_GLOBAL_LOCALE); +#endif + + return &__libc_multiple_threads; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/linuxthreads.texi b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/linuxthreads.texi new file mode 100644 index 00000000..795fb709 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/linuxthreads.texi @@ -0,0 +1,1627 @@ +@node POSIX Threads +@c @node POSIX Threads, , Top, Top +@chapter POSIX Threads +@c %MENU% The standard threads library + +@c This chapter needs more work bigtime. -zw + +This chapter describes the pthreads (POSIX threads) library. This +library provides support functions for multithreaded programs: thread +primitives, synchronization objects, and so forth. It also implements +POSIX 1003.1b semaphores (not to be confused with System V semaphores). + +The threads operations (@samp{pthread_*}) do not use @var{errno}. +Instead they return an error code directly. The semaphore operations do +use @var{errno}. + +@menu +* Basic Thread Operations:: Creating, terminating, and waiting for threads. +* Thread Attributes:: Tuning thread scheduling. +* Cancellation:: Stopping a thread before it's done. +* Cleanup Handlers:: Deallocating resources when a thread is + canceled. +* Mutexes:: One way to synchronize threads. +* Condition Variables:: Another way. +* POSIX Semaphores:: And a third way. +* Thread-Specific Data:: Variables with different values in + different threads. +* Threads and Signal Handling:: Why you should avoid mixing the two, and + how to do it if you must. +* Threads and Fork:: Interactions between threads and the + @code{fork} function. +* Streams and Fork:: Interactions between stdio streams and + @code{fork}. +* Miscellaneous Thread Functions:: A grab bag of utility routines. +@end menu + +@node Basic Thread Operations +@section Basic Thread Operations + +These functions are the thread equivalents of @code{fork}, @code{exit}, +and @code{wait}. + +@comment pthread.h +@comment POSIX +@deftypefun int pthread_create (pthread_t * @var{thread}, pthread_attr_t * @var{attr}, void * (*@var{start_routine})(void *), void * @var{arg}) +@code{pthread_create} creates a new thread of control that executes +concurrently with the calling thread. The new thread calls the +function @var{start_routine}, passing it @var{arg} as first argument. The +new thread terminates either explicitly, by calling @code{pthread_exit}, +or implicitly, by returning from the @var{start_routine} function. The +latter case is equivalent to calling @code{pthread_exit} with the result +returned by @var{start_routine} as exit code. + +The @var{attr} argument specifies thread attributes to be applied to the +new thread. @xref{Thread Attributes}, for details. The @var{attr} +argument can also be @code{NULL}, in which case default attributes are +used: the created thread is joinable (not detached) and has an ordinary +(not realtime) scheduling policy. + +On success, the identifier of the newly created thread is stored in the +location pointed by the @var{thread} argument, and a 0 is returned. On +error, a non-zero error code is returned. + +This function may return the following errors: +@table @code +@item EAGAIN +Not enough system resources to create a process for the new thread, +or more than @code{PTHREAD_THREADS_MAX} threads are already active. +@end table +@end deftypefun + +@comment pthread.h +@comment POSIX +@deftypefun void pthread_exit (void *@var{retval}) +@code{pthread_exit} terminates the execution of the calling thread. All +cleanup handlers (@pxref{Cleanup Handlers}) that have been set for the +calling thread with @code{pthread_cleanup_push} are executed in reverse +order (the most recently pushed handler is executed first). Finalization +functions for thread-specific data are then called for all keys that +have non-@code{NULL} values associated with them in the calling thread +(@pxref{Thread-Specific Data}). Finally, execution of the calling +thread is stopped. + +The @var{retval} argument is the return value of the thread. It can be +retrieved from another thread using @code{pthread_join}. + +The @code{pthread_exit} function never returns. +@end deftypefun + +@comment pthread.h +@comment POSIX +@deftypefun int pthread_cancel (pthread_t @var{thread}) + +@code{pthread_cancel} sends a cancellation request to the thread denoted +by the @var{thread} argument. If there is no such thread, +@code{pthread_cancel} fails and returns @code{ESRCH}. Otherwise it +returns 0. @xref{Cancellation}, for details. +@end deftypefun + +@comment pthread.h +@comment POSIX +@deftypefun int pthread_join (pthread_t @var{th}, void **thread_@var{return}) +@code{pthread_join} suspends the execution of the calling thread until +the thread identified by @var{th} terminates, either by calling +@code{pthread_exit} or by being canceled. + +If @var{thread_return} is not @code{NULL}, the return value of @var{th} +is stored in the location pointed to by @var{thread_return}. The return +value of @var{th} is either the argument it gave to @code{pthread_exit}, +or @code{PTHREAD_CANCELED} if @var{th} was canceled. + +The joined thread @code{th} must be in the joinable state: it must not +have been detached using @code{pthread_detach} or the +@code{PTHREAD_CREATE_DETACHED} attribute to @code{pthread_create}. + +When a joinable thread terminates, its memory resources (thread +descriptor and stack) are not deallocated until another thread performs +@code{pthread_join} on it. Therefore, @code{pthread_join} must be called +once for each joinable thread created to avoid memory leaks. + +At most one thread can wait for the termination of a given +thread. Calling @code{pthread_join} on a thread @var{th} on which +another thread is already waiting for termination returns an error. + +@code{pthread_join} is a cancellation point. If a thread is canceled +while suspended in @code{pthread_join}, the thread execution resumes +immediately and the cancellation is executed without waiting for the +@var{th} thread to terminate. If cancellation occurs during +@code{pthread_join}, the @var{th} thread remains not joined. + +On success, the return value of @var{th} is stored in the location +pointed to by @var{thread_return}, and 0 is returned. On error, one of +the following values is returned: +@table @code +@item ESRCH +No thread could be found corresponding to that specified by @var{th}. +@item EINVAL +The @var{th} thread has been detached, or another thread is already +waiting on termination of @var{th}. +@item EDEADLK +The @var{th} argument refers to the calling thread. +@end table +@end deftypefun + +@node Thread Attributes +@section Thread Attributes + +@comment pthread.h +@comment POSIX + +Threads have a number of attributes that may be set at creation time. +This is done by filling a thread attribute object @var{attr} of type +@code{pthread_attr_t}, then passing it as second argument to +@code{pthread_create}. Passing @code{NULL} is equivalent to passing a +thread attribute object with all attributes set to their default values. + +Attribute objects are consulted only when creating a new thread. The +same attribute object can be used for creating several threads. +Modifying an attribute object after a call to @code{pthread_create} does +not change the attributes of the thread previously created. + +@comment pthread.h +@comment POSIX +@deftypefun int pthread_attr_init (pthread_attr_t *@var{attr}) +@code{pthread_attr_init} initializes the thread attribute object +@var{attr} and fills it with default values for the attributes. (The +default values are listed below for each attribute.) + +Each attribute @var{attrname} (see below for a list of all attributes) +can be individually set using the function +@code{pthread_attr_set@var{attrname}} and retrieved using the function +@code{pthread_attr_get@var{attrname}}. +@end deftypefun + +@comment pthread.h +@comment POSIX +@deftypefun int pthread_attr_destroy (pthread_attr_t *@var{attr}) +@code{pthread_attr_destroy} destroys the attribute object pointed to by +@var{attr} releasing any resources associated with it. @var{attr} is +left in an undefined state, and you must not use it again in a call to +any pthreads function until it has been reinitialized. +@end deftypefun + +@findex pthread_attr_setdetachstate +@findex pthread_attr_setguardsize +@findex pthread_attr_setinheritsched +@findex pthread_attr_setschedparam +@findex pthread_attr_setschedpolicy +@findex pthread_attr_setscope +@findex pthread_attr_setstack +@findex pthread_attr_setstackaddr +@findex pthread_attr_setstacksize +@comment pthread.h +@comment POSIX +@deftypefun int pthread_attr_setattr (pthread_attr_t *@var{obj}, int @var{value}) +Set attribute @var{attr} to @var{value} in the attribute object pointed +to by @var{obj}. See below for a list of possible attributes and the +values they can take. + +On success, these functions return 0. If @var{value} is not meaningful +for the @var{attr} being modified, they will return the error code +@code{EINVAL}. Some of the functions have other failure modes; see +below. +@end deftypefun + +@findex pthread_attr_getdetachstate +@findex pthread_attr_getguardsize +@findex pthread_attr_getinheritsched +@findex pthread_attr_getschedparam +@findex pthread_attr_getschedpolicy +@findex pthread_attr_getscope +@findex pthread_attr_getstack +@findex pthread_attr_getstackaddr +@findex pthread_attr_getstacksize +@comment pthread.h +@comment POSIX +@deftypefun int pthread_attr_getattr (const pthread_attr_t *@var{obj}, int *@var{value}) +Store the current setting of @var{attr} in @var{obj} into the variable +pointed to by @var{value}. + +These functions always return 0. +@end deftypefun + +The following thread attributes are supported: +@table @samp +@item detachstate +Choose whether the thread is created in the joinable state (value +@code{PTHREAD_CREATE_JOINABLE}) or in the detached state +(@code{PTHREAD_CREATE_DETACHED}). The default is +@code{PTHREAD_CREATE_JOINABLE}. + +In the joinable state, another thread can synchronize on the thread +termination and recover its termination code using @code{pthread_join}, +but some of the thread resources are kept allocated after the thread +terminates, and reclaimed only when another thread performs +@code{pthread_join} on that thread. + +In the detached state, the thread resources are immediately freed when +it terminates, but @code{pthread_join} cannot be used to synchronize on +the thread termination. + +A thread created in the joinable state can later be put in the detached +thread using @code{pthread_detach}. + +@item schedpolicy +Select the scheduling policy for the thread: one of @code{SCHED_OTHER} +(regular, non-realtime scheduling), @code{SCHED_RR} (realtime, +round-robin) or @code{SCHED_FIFO} (realtime, first-in first-out). +The default is @code{SCHED_OTHER}. +@c Not doc'd in our manual: FIXME. +@c See @code{sched_setpolicy} for more information on scheduling policies. + +The realtime scheduling policies @code{SCHED_RR} and @code{SCHED_FIFO} +are available only to processes with superuser privileges. +@code{pthread_attr_setschedparam} will fail and return @code{ENOTSUP} if +you try to set a realtime policy when you are unprivileged. + +The scheduling policy of a thread can be changed after creation with +@code{pthread_setschedparam}. + +@item schedparam +Change the scheduling parameter (the scheduling priority) +for the thread. The default is 0. + +This attribute is not significant if the scheduling policy is +@code{SCHED_OTHER}; it only matters for the realtime policies +@code{SCHED_RR} and @code{SCHED_FIFO}. + +The scheduling priority of a thread can be changed after creation with +@code{pthread_setschedparam}. + +@item inheritsched +Choose whether the scheduling policy and scheduling parameter for the +newly created thread are determined by the values of the +@var{schedpolicy} and @var{schedparam} attributes (value +@code{PTHREAD_EXPLICIT_SCHED}) or are inherited from the parent thread +(value @code{PTHREAD_INHERIT_SCHED}). The default is +@code{PTHREAD_EXPLICIT_SCHED}. + +@item scope +Choose the scheduling contention scope for the created thread. The +default is @code{PTHREAD_SCOPE_SYSTEM}, meaning that the threads contend +for CPU time with all processes running on the machine. In particular, +thread priorities are interpreted relative to the priorities of all +other processes on the machine. The other possibility, +@code{PTHREAD_SCOPE_PROCESS}, means that scheduling contention occurs +only between the threads of the running process: thread priorities are +interpreted relative to the priorities of the other threads of the +process, regardless of the priorities of other processes. + +@code{PTHREAD_SCOPE_PROCESS} is not supported in LinuxThreads. If you +try to set the scope to this value, @code{pthread_attr_setscope} will +fail and return @code{ENOTSUP}. + +@item stackaddr +Provide an address for an application managed stack. The size of the +stack must be at least @code{PTHREAD_STACK_MIN}. + +@item stacksize +Change the size of the stack created for the thread. The value defines +the minimum stack size, in bytes. + +If the value exceeds the system's maximum stack size, or is smaller +than @code{PTHREAD_STACK_MIN}, @code{pthread_attr_setstacksize} will +fail and return @code{EINVAL}. + +@item stack +Provide both the address and size of an application managed stack to +use for the new thread. The base of the memory area is @var{stackaddr} +with the size of the memory area, @var{stacksize}, measured in bytes. + +If the value of @var{stacksize} is less than @code{PTHREAD_STACK_MIN}, +or greater than the system's maximum stack size, or if the value of +@var{stackaddr} lacks the proper alignment, @code{pthread_attr_setstack} +will fail and return @code{EINVAL}. + +@item guardsize +Change the minimum size in bytes of the guard area for the thread's +stack. The default size is a single page. If this value is set, it +will be rounded up to the nearest page size. If the value is set to 0, +a guard area will not be created for this thread. The space allocated +for the guard area is used to catch stack overflow. Therefore, when +allocating large structures on the stack, a larger guard area may be +required to catch a stack overflow. + +If the caller is managing their own stacks (if the @code{stackaddr} +attribute has been set), then the @code{guardsize} attribute is ignored. + +If the value exceeds the @code{stacksize}, @code{pthread_atrr_setguardsize} +will fail and return @code{EINVAL}. +@end table + +@node Cancellation +@section Cancellation + +Cancellation is the mechanism by which a thread can terminate the +execution of another thread. More precisely, a thread can send a +cancellation request to another thread. Depending on its settings, the +target thread can then either ignore the request, honor it immediately, +or defer it till it reaches a cancellation point. When threads are +first created by @code{pthread_create}, they always defer cancellation +requests. + +When a thread eventually honors a cancellation request, it behaves as if +@code{pthread_exit(PTHREAD_CANCELED)} was called. All cleanup handlers +are executed in reverse order, finalization functions for +thread-specific data are called, and finally the thread stops executing. +If the canceled thread was joinable, the return value +@code{PTHREAD_CANCELED} is provided to whichever thread calls +@var{pthread_join} on it. See @code{pthread_exit} for more information. + +Cancellation points are the points where the thread checks for pending +cancellation requests and performs them. The POSIX threads functions +@code{pthread_join}, @code{pthread_cond_wait}, +@code{pthread_cond_timedwait}, @code{pthread_testcancel}, +@code{sem_wait}, and @code{sigwait} are cancellation points. In +addition, these system calls are cancellation points: + +@multitable @columnfractions .33 .33 .33 +@item @t{accept} @tab @t{open} @tab @t{sendmsg} +@item @t{close} @tab @t{pause} @tab @t{sendto} +@item @t{connect} @tab @t{read} @tab @t{system} +@item @t{fcntl} @tab @t{recv} @tab @t{tcdrain} +@item @t{fsync} @tab @t{recvfrom} @tab @t{wait} +@item @t{lseek} @tab @t{recvmsg} @tab @t{waitpid} +@item @t{msync} @tab @t{send} @tab @t{write} +@item @t{nanosleep} +@end multitable + +@noindent +All library functions that call these functions (such as +@code{printf}) are also cancellation points. + +@comment pthread.h +@comment POSIX +@deftypefun int pthread_setcancelstate (int @var{state}, int *@var{oldstate}) +@code{pthread_setcancelstate} changes the cancellation state for the +calling thread -- that is, whether cancellation requests are ignored or +not. The @var{state} argument is the new cancellation state: either +@code{PTHREAD_CANCEL_ENABLE} to enable cancellation, or +@code{PTHREAD_CANCEL_DISABLE} to disable cancellation (cancellation +requests are ignored). + +If @var{oldstate} is not @code{NULL}, the previous cancellation state is +stored in the location pointed to by @var{oldstate}, and can thus be +restored later by another call to @code{pthread_setcancelstate}. + +If the @var{state} argument is not @code{PTHREAD_CANCEL_ENABLE} or +@code{PTHREAD_CANCEL_DISABLE}, @code{pthread_setcancelstate} fails and +returns @code{EINVAL}. Otherwise it returns 0. +@end deftypefun + +@comment pthread.h +@comment POSIX +@deftypefun int pthread_setcanceltype (int @var{type}, int *@var{oldtype}) +@code{pthread_setcanceltype} changes the type of responses to +cancellation requests for the calling thread: asynchronous (immediate) +or deferred. The @var{type} argument is the new cancellation type: +either @code{PTHREAD_CANCEL_ASYNCHRONOUS} to cancel the calling thread +as soon as the cancellation request is received, or +@code{PTHREAD_CANCEL_DEFERRED} to keep the cancellation request pending +until the next cancellation point. If @var{oldtype} is not @code{NULL}, +the previous cancellation state is stored in the location pointed to by +@var{oldtype}, and can thus be restored later by another call to +@code{pthread_setcanceltype}. + +If the @var{type} argument is not @code{PTHREAD_CANCEL_DEFERRED} or +@code{PTHREAD_CANCEL_ASYNCHRONOUS}, @code{pthread_setcanceltype} fails +and returns @code{EINVAL}. Otherwise it returns 0. +@end deftypefun + +@comment pthread.h +@comment POSIX +@deftypefun void pthread_testcancel (@var{void}) +@code{pthread_testcancel} does nothing except testing for pending +cancellation and executing it. Its purpose is to introduce explicit +checks for cancellation in long sequences of code that do not call +cancellation point functions otherwise. +@end deftypefun + +@node Cleanup Handlers +@section Cleanup Handlers + +Cleanup handlers are functions that get called when a thread terminates, +either by calling @code{pthread_exit} or because of +cancellation. Cleanup handlers are installed and removed following a +stack-like discipline. + +The purpose of cleanup handlers is to free the resources that a thread +may hold at the time it terminates. In particular, if a thread exits or +is canceled while it owns a locked mutex, the mutex will remain locked +forever and prevent other threads from executing normally. The best way +to avoid this is, just before locking the mutex, to install a cleanup +handler whose effect is to unlock the mutex. Cleanup handlers can be +used similarly to free blocks allocated with @code{malloc} or close file +descriptors on thread termination. + +Here is how to lock a mutex @var{mut} in such a way that it will be +unlocked if the thread is canceled while @var{mut} is locked: + +@smallexample +pthread_cleanup_push(pthread_mutex_unlock, (void *) &mut); +pthread_mutex_lock(&mut); +/* do some work */ +pthread_mutex_unlock(&mut); +pthread_cleanup_pop(0); +@end smallexample + +Equivalently, the last two lines can be replaced by + +@smallexample +pthread_cleanup_pop(1); +@end smallexample + +Notice that the code above is safe only in deferred cancellation mode +(see @code{pthread_setcanceltype}). In asynchronous cancellation mode, a +cancellation can occur between @code{pthread_cleanup_push} and +@code{pthread_mutex_lock}, or between @code{pthread_mutex_unlock} and +@code{pthread_cleanup_pop}, resulting in both cases in the thread trying +to unlock a mutex not locked by the current thread. This is the main +reason why asynchronous cancellation is difficult to use. + +If the code above must also work in asynchronous cancellation mode, +then it must switch to deferred mode for locking and unlocking the +mutex: + +@smallexample +pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldtype); +pthread_cleanup_push(pthread_mutex_unlock, (void *) &mut); +pthread_mutex_lock(&mut); +/* do some work */ +pthread_cleanup_pop(1); +pthread_setcanceltype(oldtype, NULL); +@end smallexample + +The code above can be rewritten in a more compact and efficient way, +using the non-portable functions @code{pthread_cleanup_push_defer_np} +and @code{pthread_cleanup_pop_restore_np}: + +@smallexample +pthread_cleanup_push_defer_np(pthread_mutex_unlock, (void *) &mut); +pthread_mutex_lock(&mut); +/* do some work */ +pthread_cleanup_pop_restore_np(1); +@end smallexample + +@comment pthread.h +@comment POSIX +@deftypefun void pthread_cleanup_push (void (*@var{routine}) (void *), void *@var{arg}) + +@code{pthread_cleanup_push} installs the @var{routine} function with +argument @var{arg} as a cleanup handler. From this point on to the +matching @code{pthread_cleanup_pop}, the function @var{routine} will be +called with arguments @var{arg} when the thread terminates, either +through @code{pthread_exit} or by cancellation. If several cleanup +handlers are active at that point, they are called in LIFO order: the +most recently installed handler is called first. +@end deftypefun + +@comment pthread.h +@comment POSIX +@deftypefun void pthread_cleanup_pop (int @var{execute}) +@code{pthread_cleanup_pop} removes the most recently installed cleanup +handler. If the @var{execute} argument is not 0, it also executes the +handler, by calling the @var{routine} function with arguments +@var{arg}. If the @var{execute} argument is 0, the handler is only +removed but not executed. +@end deftypefun + +Matching pairs of @code{pthread_cleanup_push} and +@code{pthread_cleanup_pop} must occur in the same function, at the same +level of block nesting. Actually, @code{pthread_cleanup_push} and +@code{pthread_cleanup_pop} are macros, and the expansion of +@code{pthread_cleanup_push} introduces an open brace @code{@{} with the +matching closing brace @code{@}} being introduced by the expansion of the +matching @code{pthread_cleanup_pop}. + +@comment pthread.h +@comment GNU +@deftypefun void pthread_cleanup_push_defer_np (void (*@var{routine}) (void *), void *@var{arg}) +@code{pthread_cleanup_push_defer_np} is a non-portable extension that +combines @code{pthread_cleanup_push} and @code{pthread_setcanceltype}. +It pushes a cleanup handler just as @code{pthread_cleanup_push} does, +but also saves the current cancellation type and sets it to deferred +cancellation. This ensures that the cleanup mechanism is effective even +if the thread was initially in asynchronous cancellation mode. +@end deftypefun + +@comment pthread.h +@comment GNU +@deftypefun void pthread_cleanup_pop_restore_np (int @var{execute}) +@code{pthread_cleanup_pop_restore_np} pops a cleanup handler introduced +by @code{pthread_cleanup_push_defer_np}, and restores the cancellation +type to its value at the time @code{pthread_cleanup_push_defer_np} was +called. +@end deftypefun + +@code{pthread_cleanup_push_defer_np} and +@code{pthread_cleanup_pop_restore_np} must occur in matching pairs, at +the same level of block nesting. + +The sequence + +@smallexample +pthread_cleanup_push_defer_np(routine, arg); +... +pthread_cleanup_pop_restore_np(execute); +@end smallexample + +@noindent +is functionally equivalent to (but more compact and efficient than) + +@smallexample +@{ + int oldtype; + pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldtype); + pthread_cleanup_push(routine, arg); + ... + pthread_cleanup_pop(execute); + pthread_setcanceltype(oldtype, NULL); +@} +@end smallexample + + +@node Mutexes +@section Mutexes + +A mutex is a MUTual EXclusion device, and is useful for protecting +shared data structures from concurrent modifications, and implementing +critical sections and monitors. + +A mutex has two possible states: unlocked (not owned by any thread), +and locked (owned by one thread). A mutex can never be owned by two +different threads simultaneously. A thread attempting to lock a mutex +that is already locked by another thread is suspended until the owning +thread unlocks the mutex first. + +None of the mutex functions is a cancellation point, not even +@code{pthread_mutex_lock}, in spite of the fact that it can suspend a +thread for arbitrary durations. This way, the status of mutexes at +cancellation points is predictable, allowing cancellation handlers to +unlock precisely those mutexes that need to be unlocked before the +thread stops executing. Consequently, threads using deferred +cancellation should never hold a mutex for extended periods of time. + +It is not safe to call mutex functions from a signal handler. In +particular, calling @code{pthread_mutex_lock} or +@code{pthread_mutex_unlock} from a signal handler may deadlock the +calling thread. + +@comment pthread.h +@comment POSIX +@deftypefun int pthread_mutex_init (pthread_mutex_t *@var{mutex}, const pthread_mutexattr_t *@var{mutexattr}) + +@code{pthread_mutex_init} initializes the mutex object pointed to by +@var{mutex} according to the mutex attributes specified in @var{mutexattr}. +If @var{mutexattr} is @code{NULL}, default attributes are used instead. + +The LinuxThreads implementation supports only one mutex attribute, +the @var{mutex type}, which is either ``fast'', ``recursive'', or +``error checking''. The type of a mutex determines whether +it can be locked again by a thread that already owns it. +The default type is ``fast''. + +Variables of type @code{pthread_mutex_t} can also be initialized +statically, using the constants @code{PTHREAD_MUTEX_INITIALIZER} (for +timed mutexes), @code{PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP} (for +recursive mutexes), @code{PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP} +(for fast mutexes(, and @code{PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP} +(for error checking mutexes). + +@code{pthread_mutex_init} always returns 0. +@end deftypefun + +@comment pthread.h +@comment POSIX +@deftypefun int pthread_mutex_lock (pthread_mutex_t *mutex)) +@code{pthread_mutex_lock} locks the given mutex. If the mutex is +currently unlocked, it becomes locked and owned by the calling thread, +and @code{pthread_mutex_lock} returns immediately. If the mutex is +already locked by another thread, @code{pthread_mutex_lock} suspends the +calling thread until the mutex is unlocked. + +If the mutex is already locked by the calling thread, the behavior of +@code{pthread_mutex_lock} depends on the type of the mutex. If the mutex +is of the ``fast'' type, the calling thread is suspended. It will +remain suspended forever, because no other thread can unlock the mutex. +If the mutex is of the ``error checking'' type, @code{pthread_mutex_lock} +returns immediately with the error code @code{EDEADLK}. If the mutex is +of the ``recursive'' type, @code{pthread_mutex_lock} succeeds and +returns immediately, recording the number of times the calling thread +has locked the mutex. An equal number of @code{pthread_mutex_unlock} +operations must be performed before the mutex returns to the unlocked +state. +@c This doesn't discuss PTHREAD_MUTEX_TIMED_NP mutex attributes. FIXME +@end deftypefun + +@comment pthread.h +@comment POSIX +@deftypefun int pthread_mutex_trylock (pthread_mutex_t *@var{mutex}) +@code{pthread_mutex_trylock} behaves identically to +@code{pthread_mutex_lock}, except that it does not block the calling +thread if the mutex is already locked by another thread (or by the +calling thread in the case of a ``fast'' mutex). Instead, +@code{pthread_mutex_trylock} returns immediately with the error code +@code{EBUSY}. +@end deftypefun + +@comment pthread.h +@comment POSIX +@deftypefun int pthread_mutex_timedlock (pthread_mutex_t *@var{mutex}, const struct timespec *@var{abstime}) +The @code{pthread_mutex_timedlock} is similar to the +@code{pthread_mutex_lock} function but instead of blocking for in +indefinite time if the mutex is locked by another thread, it returns +when the time specified in @var{abstime} is reached. + +This function can only be used on standard (``timed'') and ``error +checking'' mutexes. It behaves just like @code{pthread_mutex_lock} for +all other types. + +If the mutex is successfully locked, the function returns zero. If the +time specified in @var{abstime} is reached without the mutex being locked, +@code{ETIMEDOUT} is returned. + +This function was introduced in the POSIX.1d revision of the POSIX standard. +@end deftypefun + +@comment pthread.h +@comment POSIX +@deftypefun int pthread_mutex_unlock (pthread_mutex_t *@var{mutex}) +@code{pthread_mutex_unlock} unlocks the given mutex. The mutex is +assumed to be locked and owned by the calling thread on entrance to +@code{pthread_mutex_unlock}. If the mutex is of the ``fast'' type, +@code{pthread_mutex_unlock} always returns it to the unlocked state. If +it is of the ``recursive'' type, it decrements the locking count of the +mutex (number of @code{pthread_mutex_lock} operations performed on it by +the calling thread), and only when this count reaches zero is the mutex +actually unlocked. + +On ``error checking'' mutexes, @code{pthread_mutex_unlock} actually +checks at run-time that the mutex is locked on entrance, and that it was +locked by the same thread that is now calling +@code{pthread_mutex_unlock}. If these conditions are not met, +@code{pthread_mutex_unlock} returns @code{EPERM}, and the mutex remains +unchanged. ``Fast'' and ``recursive'' mutexes perform no such checks, +thus allowing a locked mutex to be unlocked by a thread other than its +owner. This is non-portable behavior and must not be relied upon. +@end deftypefun + +@comment pthread.h +@comment POSIX +@deftypefun int pthread_mutex_destroy (pthread_mutex_t *@var{mutex}) +@code{pthread_mutex_destroy} destroys a mutex object, freeing the +resources it might hold. The mutex must be unlocked on entrance. In the +LinuxThreads implementation, no resources are associated with mutex +objects, thus @code{pthread_mutex_destroy} actually does nothing except +checking that the mutex is unlocked. + +If the mutex is locked by some thread, @code{pthread_mutex_destroy} +returns @code{EBUSY}. Otherwise it returns 0. +@end deftypefun + +If any of the above functions (except @code{pthread_mutex_init}) +is applied to an uninitialized mutex, they will simply return +@code{EINVAL} and do nothing. + +A shared global variable @var{x} can be protected by a mutex as follows: + +@smallexample +int x; +pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER; +@end smallexample + +All accesses and modifications to @var{x} should be bracketed by calls to +@code{pthread_mutex_lock} and @code{pthread_mutex_unlock} as follows: + +@smallexample +pthread_mutex_lock(&mut); +/* operate on x */ +pthread_mutex_unlock(&mut); +@end smallexample + +Mutex attributes can be specified at mutex creation time, by passing a +mutex attribute object as second argument to @code{pthread_mutex_init}. +Passing @code{NULL} is equivalent to passing a mutex attribute object +with all attributes set to their default values. + +@comment pthread.h +@comment POSIX +@deftypefun int pthread_mutexattr_init (pthread_mutexattr_t *@var{attr}) +@code{pthread_mutexattr_init} initializes the mutex attribute object +@var{attr} and fills it with default values for the attributes. + +This function always returns 0. +@end deftypefun + +@comment pthread.h +@comment POSIX +@deftypefun int pthread_mutexattr_destroy (pthread_mutexattr_t *@var{attr}) +@code{pthread_mutexattr_destroy} destroys a mutex attribute object, +which must not be reused until it is +reinitialized. @code{pthread_mutexattr_destroy} does nothing in the +LinuxThreads implementation. + +This function always returns 0. +@end deftypefun + +LinuxThreads supports only one mutex attribute: the mutex type, which is +either @code{PTHREAD_MUTEX_ADAPTIVE_NP} for ``fast'' mutexes, +@code{PTHREAD_MUTEX_RECURSIVE_NP} for ``recursive'' mutexes, +@code{PTHREAD_MUTEX_TIMED_NP} for ``timed'' mutexes, or +@code{PTHREAD_MUTEX_ERRORCHECK_NP} for ``error checking'' mutexes. As +the @code{NP} suffix indicates, this is a non-portable extension to the +POSIX standard and should not be employed in portable programs. + +The mutex type determines what happens if a thread attempts to lock a +mutex it already owns with @code{pthread_mutex_lock}. If the mutex is of +the ``fast'' type, @code{pthread_mutex_lock} simply suspends the calling +thread forever. If the mutex is of the ``error checking'' type, +@code{pthread_mutex_lock} returns immediately with the error code +@code{EDEADLK}. If the mutex is of the ``recursive'' type, the call to +@code{pthread_mutex_lock} returns immediately with a success return +code. The number of times the thread owning the mutex has locked it is +recorded in the mutex. The owning thread must call +@code{pthread_mutex_unlock} the same number of times before the mutex +returns to the unlocked state. + +The default mutex type is ``timed'', that is, @code{PTHREAD_MUTEX_TIMED_NP}. +@c This doesn't describe how a ``timed'' mutex behaves. FIXME + +@comment pthread.h +@comment POSIX +@deftypefun int pthread_mutexattr_settype (pthread_mutexattr_t *@var{attr}, int @var{type}) +@code{pthread_mutexattr_settype} sets the mutex type attribute in +@var{attr} to the value specified by @var{type}. + +If @var{type} is not @code{PTHREAD_MUTEX_ADAPTIVE_NP}, +@code{PTHREAD_MUTEX_RECURSIVE_NP}, @code{PTHREAD_MUTEX_TIMED_NP}, or +@code{PTHREAD_MUTEX_ERRORCHECK_NP}, this function will return +@code{EINVAL} and leave @var{attr} unchanged. + +The standard Unix98 identifiers @code{PTHREAD_MUTEX_DEFAULT}, +@code{PTHREAD_MUTEX_NORMAL}, @code{PTHREAD_MUTEX_RECURSIVE}, +and @code{PTHREAD_MUTEX_ERRORCHECK} are also permitted. + +@end deftypefun + +@comment pthread.h +@comment POSIX +@deftypefun int pthread_mutexattr_gettype (const pthread_mutexattr_t *@var{attr}, int *@var{type}) +@code{pthread_mutexattr_gettype} retrieves the current value of the +mutex type attribute in @var{attr} and stores it in the location pointed +to by @var{type}. + +This function always returns 0. +@end deftypefun + +@node Condition Variables +@section Condition Variables + +A condition (short for ``condition variable'') is a synchronization +device that allows threads to suspend execution until some predicate on +shared data is satisfied. The basic operations on conditions are: signal +the condition (when the predicate becomes true), and wait for the +condition, suspending the thread execution until another thread signals +the condition. + +A condition variable must always be associated with a mutex, to avoid +the race condition where a thread prepares to wait on a condition +variable and another thread signals the condition just before the first +thread actually waits on it. + +@comment pthread.h +@comment POSIX +@deftypefun int pthread_cond_init (pthread_cond_t *@var{cond}, pthread_condattr_t *cond_@var{attr}) + +@code{pthread_cond_init} initializes the condition variable @var{cond}, +using the condition attributes specified in @var{cond_attr}, or default +attributes if @var{cond_attr} is @code{NULL}. The LinuxThreads +implementation supports no attributes for conditions, hence the +@var{cond_attr} parameter is actually ignored. + +Variables of type @code{pthread_cond_t} can also be initialized +statically, using the constant @code{PTHREAD_COND_INITIALIZER}. + +This function always returns 0. +@end deftypefun + +@comment pthread.h +@comment POSIX +@deftypefun int pthread_cond_signal (pthread_cond_t *@var{cond}) +@code{pthread_cond_signal} restarts one of the threads that are waiting +on the condition variable @var{cond}. If no threads are waiting on +@var{cond}, nothing happens. If several threads are waiting on +@var{cond}, exactly one is restarted, but it is not specified which. + +This function always returns 0. +@end deftypefun + +@comment pthread.h +@comment POSIX +@deftypefun int pthread_cond_broadcast (pthread_cond_t *@var{cond}) +@code{pthread_cond_broadcast} restarts all the threads that are waiting +on the condition variable @var{cond}. Nothing happens if no threads are +waiting on @var{cond}. + +This function always returns 0. +@end deftypefun + +@comment pthread.h +@comment POSIX +@deftypefun int pthread_cond_wait (pthread_cond_t *@var{cond}, pthread_mutex_t *@var{mutex}) +@code{pthread_cond_wait} atomically unlocks the @var{mutex} (as per +@code{pthread_unlock_mutex}) and waits for the condition variable +@var{cond} to be signaled. The thread execution is suspended and does +not consume any CPU time until the condition variable is signaled. The +@var{mutex} must be locked by the calling thread on entrance to +@code{pthread_cond_wait}. Before returning to the calling thread, +@code{pthread_cond_wait} re-acquires @var{mutex} (as per +@code{pthread_lock_mutex}). + +Unlocking the mutex and suspending on the condition variable is done +atomically. Thus, if all threads always acquire the mutex before +signaling the condition, this guarantees that the condition cannot be +signaled (and thus ignored) between the time a thread locks the mutex +and the time it waits on the condition variable. + +This function always returns 0. +@end deftypefun + +@comment pthread.h +@comment POSIX +@deftypefun int pthread_cond_timedwait (pthread_cond_t *@var{cond}, pthread_mutex_t *@var{mutex}, const struct timespec *@var{abstime}) +@code{pthread_cond_timedwait} atomically unlocks @var{mutex} and waits +on @var{cond}, as @code{pthread_cond_wait} does, but it also bounds the +duration of the wait. If @var{cond} has not been signaled before time +@var{abstime}, the mutex @var{mutex} is re-acquired and +@code{pthread_cond_timedwait} returns the error code @code{ETIMEDOUT}. +The wait can also be interrupted by a signal; in that case +@code{pthread_cond_timedwait} returns @code{EINTR}. + +The @var{abstime} parameter specifies an absolute time, with the same +origin as @code{time} and @code{gettimeofday}: an @var{abstime} of 0 +corresponds to 00:00:00 GMT, January 1, 1970. +@end deftypefun + +@comment pthread.h +@comment POSIX +@deftypefun int pthread_cond_destroy (pthread_cond_t *@var{cond}) +@code{pthread_cond_destroy} destroys the condition variable @var{cond}, +freeing the resources it might hold. If any threads are waiting on the +condition variable, @code{pthread_cond_destroy} leaves @var{cond} +untouched and returns @code{EBUSY}. Otherwise it returns 0, and +@var{cond} must not be used again until it is reinitialized. + +In the LinuxThreads implementation, no resources are associated with +condition variables, so @code{pthread_cond_destroy} actually does +nothing. +@end deftypefun + +@code{pthread_cond_wait} and @code{pthread_cond_timedwait} are +cancellation points. If a thread is canceled while suspended in one of +these functions, the thread immediately resumes execution, relocks the +mutex specified by @var{mutex}, and finally executes the cancellation. +Consequently, cleanup handlers are assured that @var{mutex} is locked +when they are called. + +It is not safe to call the condition variable functions from a signal +handler. In particular, calling @code{pthread_cond_signal} or +@code{pthread_cond_broadcast} from a signal handler may deadlock the +calling thread. + +Consider two shared variables @var{x} and @var{y}, protected by the +mutex @var{mut}, and a condition variable @var{cond} that is to be +signaled whenever @var{x} becomes greater than @var{y}. + +@smallexample +int x,y; +pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER; +pthread_cond_t cond = PTHREAD_COND_INITIALIZER; +@end smallexample + +Waiting until @var{x} is greater than @var{y} is performed as follows: + +@smallexample +pthread_mutex_lock(&mut); +while (x <= y) @{ + pthread_cond_wait(&cond, &mut); +@} +/* operate on x and y */ +pthread_mutex_unlock(&mut); +@end smallexample + +Modifications on @var{x} and @var{y} that may cause @var{x} to become greater than +@var{y} should signal the condition if needed: + +@smallexample +pthread_mutex_lock(&mut); +/* modify x and y */ +if (x > y) pthread_cond_broadcast(&cond); +pthread_mutex_unlock(&mut); +@end smallexample + +If it can be proved that at most one waiting thread needs to be waken +up (for instance, if there are only two threads communicating through +@var{x} and @var{y}), @code{pthread_cond_signal} can be used as a slightly more +efficient alternative to @code{pthread_cond_broadcast}. In doubt, use +@code{pthread_cond_broadcast}. + +To wait for @var{x} to becomes greater than @var{y} with a timeout of 5 +seconds, do: + +@smallexample +struct timeval now; +struct timespec timeout; +int retcode; + +pthread_mutex_lock(&mut); +gettimeofday(&now); +timeout.tv_sec = now.tv_sec + 5; +timeout.tv_nsec = now.tv_usec * 1000; +retcode = 0; +while (x <= y && retcode != ETIMEDOUT) @{ + retcode = pthread_cond_timedwait(&cond, &mut, &timeout); +@} +if (retcode == ETIMEDOUT) @{ + /* timeout occurred */ +@} else @{ + /* operate on x and y */ +@} +pthread_mutex_unlock(&mut); +@end smallexample + +Condition attributes can be specified at condition creation time, by +passing a condition attribute object as second argument to +@code{pthread_cond_init}. Passing @code{NULL} is equivalent to passing +a condition attribute object with all attributes set to their default +values. + +The LinuxThreads implementation supports no attributes for +conditions. The functions on condition attributes are included only for +compliance with the POSIX standard. + +@comment pthread.h +@comment POSIX +@deftypefun int pthread_condattr_init (pthread_condattr_t *@var{attr}) +@deftypefunx int pthread_condattr_destroy (pthread_condattr_t *@var{attr}) +@code{pthread_condattr_init} initializes the condition attribute object +@var{attr} and fills it with default values for the attributes. +@code{pthread_condattr_destroy} destroys the condition attribute object +@var{attr}. + +Both functions do nothing in the LinuxThreads implementation. + +@code{pthread_condattr_init} and @code{pthread_condattr_destroy} always +return 0. +@end deftypefun + +@node POSIX Semaphores +@section POSIX Semaphores + +@vindex SEM_VALUE_MAX +Semaphores are counters for resources shared between threads. The +basic operations on semaphores are: increment the counter atomically, +and wait until the counter is non-null and decrement it atomically. + +Semaphores have a maximum value past which they cannot be incremented. +The macro @code{SEM_VALUE_MAX} is defined to be this maximum value. In +the GNU C library, @code{SEM_VALUE_MAX} is equal to @code{INT_MAX} +(@pxref{Range of Type}), but it may be much smaller on other systems. + +The pthreads library implements POSIX 1003.1b semaphores. These should +not be confused with System V semaphores (@code{ipc}, @code{semctl} and +@code{semop}). +@c !!! SysV IPC is not doc'd at all in our manual + +All the semaphore functions and macros are defined in @file{semaphore.h}. + +@comment semaphore.h +@comment POSIX +@deftypefun int sem_init (sem_t *@var{sem}, int @var{pshared}, unsigned int @var{value}) +@code{sem_init} initializes the semaphore object pointed to by +@var{sem}. The count associated with the semaphore is set initially to +@var{value}. The @var{pshared} argument indicates whether the semaphore +is local to the current process (@var{pshared} is zero) or is to be +shared between several processes (@var{pshared} is not zero). + +On success @code{sem_init} returns 0. On failure it returns -1 and sets +@var{errno} to one of the following values: + +@table @code +@item EINVAL +@var{value} exceeds the maximal counter value @code{SEM_VALUE_MAX} + +@item ENOSYS +@var{pshared} is not zero. LinuxThreads currently does not support +process-shared semaphores. (This will eventually change.) +@end table +@end deftypefun + +@comment semaphore.h +@comment POSIX +@deftypefun int sem_destroy (sem_t * @var{sem}) +@code{sem_destroy} destroys a semaphore object, freeing the resources it +might hold. If any threads are waiting on the semaphore when +@code{sem_destroy} is called, it fails and sets @var{errno} to +@code{EBUSY}. + +In the LinuxThreads implementation, no resources are associated with +semaphore objects, thus @code{sem_destroy} actually does nothing except +checking that no thread is waiting on the semaphore. This will change +when process-shared semaphores are implemented. +@end deftypefun + +@comment semaphore.h +@comment POSIX +@deftypefun int sem_wait (sem_t * @var{sem}) +@code{sem_wait} suspends the calling thread until the semaphore pointed +to by @var{sem} has non-zero count. It then atomically decreases the +semaphore count. + +@code{sem_wait} is a cancellation point. It always returns 0. +@end deftypefun + +@comment semaphore.h +@comment POSIX +@deftypefun int sem_trywait (sem_t * @var{sem}) +@code{sem_trywait} is a non-blocking variant of @code{sem_wait}. If the +semaphore pointed to by @var{sem} has non-zero count, the count is +atomically decreased and @code{sem_trywait} immediately returns 0. If +the semaphore count is zero, @code{sem_trywait} immediately returns -1 +and sets errno to @code{EAGAIN}. +@end deftypefun + +@comment semaphore.h +@comment POSIX +@deftypefun int sem_post (sem_t * @var{sem}) +@code{sem_post} atomically increases the count of the semaphore pointed to +by @var{sem}. This function never blocks. + +@c !!! This para appears not to agree with the code. +On processors supporting atomic compare-and-swap (Intel 486, Pentium and +later, Alpha, PowerPC, MIPS II, Motorola 68k, Ultrasparc), the +@code{sem_post} function is can safely be called from signal handlers. +This is the only thread synchronization function provided by POSIX +threads that is async-signal safe. On the Intel 386 and earlier Sparc +chips, the current LinuxThreads implementation of @code{sem_post} is not +async-signal safe, because the hardware does not support the required +atomic operations. + +@code{sem_post} always succeeds and returns 0, unless the semaphore +count would exceed @code{SEM_VALUE_MAX} after being incremented. In +that case @code{sem_post} returns -1 and sets @var{errno} to +@code{EINVAL}. The semaphore count is left unchanged. +@end deftypefun + +@comment semaphore.h +@comment POSIX +@deftypefun int sem_getvalue (sem_t * @var{sem}, int * @var{sval}) +@code{sem_getvalue} stores in the location pointed to by @var{sval} the +current count of the semaphore @var{sem}. It always returns 0. +@end deftypefun + +@node Thread-Specific Data +@section Thread-Specific Data + +Programs often need global or static variables that have different +values in different threads. Since threads share one memory space, this +cannot be achieved with regular variables. Thread-specific data is the +POSIX threads answer to this need. + +Each thread possesses a private memory block, the thread-specific data +area, or TSD area for short. This area is indexed by TSD keys. The TSD +area associates values of type @code{void *} to TSD keys. TSD keys are +common to all threads, but the value associated with a given TSD key can +be different in each thread. + +For concreteness, the TSD areas can be viewed as arrays of @code{void *} +pointers, TSD keys as integer indices into these arrays, and the value +of a TSD key as the value of the corresponding array element in the +calling thread. + +When a thread is created, its TSD area initially associates @code{NULL} +with all keys. + +@comment pthread.h +@comment POSIX +@deftypefun int pthread_key_create (pthread_key_t *@var{key}, void (*destr_function) (void *)) +@code{pthread_key_create} allocates a new TSD key. The key is stored in +the location pointed to by @var{key}. There is a limit of +@code{PTHREAD_KEYS_MAX} on the number of keys allocated at a given +time. The value initially associated with the returned key is +@code{NULL} in all currently executing threads. + +The @var{destr_function} argument, if not @code{NULL}, specifies a +destructor function associated with the key. When a thread terminates +via @code{pthread_exit} or by cancellation, @var{destr_function} is +called on the value associated with the key in that thread. The +@var{destr_function} is not called if a key is deleted with +@code{pthread_key_delete} or a value is changed with +@code{pthread_setspecific}. The order in which destructor functions are +called at thread termination time is unspecified. + +Before the destructor function is called, the @code{NULL} value is +associated with the key in the current thread. A destructor function +might, however, re-associate non-@code{NULL} values to that key or some +other key. To deal with this, if after all the destructors have been +called for all non-@code{NULL} values, there are still some +non-@code{NULL} values with associated destructors, then the process is +repeated. The LinuxThreads implementation stops the process after +@code{PTHREAD_DESTRUCTOR_ITERATIONS} iterations, even if some +non-@code{NULL} values with associated descriptors remain. Other +implementations may loop indefinitely. + +@code{pthread_key_create} returns 0 unless @code{PTHREAD_KEYS_MAX} keys +have already been allocated, in which case it fails and returns +@code{EAGAIN}. +@end deftypefun + + +@comment pthread.h +@comment POSIX +@deftypefun int pthread_key_delete (pthread_key_t @var{key}) +@code{pthread_key_delete} deallocates a TSD key. It does not check +whether non-@code{NULL} values are associated with that key in the +currently executing threads, nor call the destructor function associated +with the key. + +If there is no such key @var{key}, it returns @code{EINVAL}. Otherwise +it returns 0. +@end deftypefun + +@comment pthread.h +@comment POSIX +@deftypefun int pthread_setspecific (pthread_key_t @var{key}, const void *@var{pointer}) +@code{pthread_setspecific} changes the value associated with @var{key} +in the calling thread, storing the given @var{pointer} instead. + +If there is no such key @var{key}, it returns @code{EINVAL}. Otherwise +it returns 0. +@end deftypefun + +@comment pthread.h +@comment POSIX +@deftypefun {void *} pthread_getspecific (pthread_key_t @var{key}) +@code{pthread_getspecific} returns the value currently associated with +@var{key} in the calling thread. + +If there is no such key @var{key}, it returns @code{NULL}. +@end deftypefun + +The following code fragment allocates a thread-specific array of 100 +characters, with automatic reclaimation at thread exit: + +@smallexample +/* Key for the thread-specific buffer */ +static pthread_key_t buffer_key; + +/* Once-only initialisation of the key */ +static pthread_once_t buffer_key_once = PTHREAD_ONCE_INIT; + +/* Allocate the thread-specific buffer */ +void buffer_alloc(void) +@{ + pthread_once(&buffer_key_once, buffer_key_alloc); + pthread_setspecific(buffer_key, malloc(100)); +@} + +/* Return the thread-specific buffer */ +char * get_buffer(void) +@{ + return (char *) pthread_getspecific(buffer_key); +@} + +/* Allocate the key */ +static void buffer_key_alloc() +@{ + pthread_key_create(&buffer_key, buffer_destroy); +@} + +/* Free the thread-specific buffer */ +static void buffer_destroy(void * buf) +@{ + free(buf); +@} +@end smallexample + +@node Threads and Signal Handling +@section Threads and Signal Handling + +@comment pthread.h +@comment POSIX +@deftypefun int pthread_sigmask (int @var{how}, const sigset_t *@var{newmask}, sigset_t *@var{oldmask}) +@code{pthread_sigmask} changes the signal mask for the calling thread as +described by the @var{how} and @var{newmask} arguments. If @var{oldmask} +is not @code{NULL}, the previous signal mask is stored in the location +pointed to by @var{oldmask}. + +The meaning of the @var{how} and @var{newmask} arguments is the same as +for @code{sigprocmask}. If @var{how} is @code{SIG_SETMASK}, the signal +mask is set to @var{newmask}. If @var{how} is @code{SIG_BLOCK}, the +signals specified to @var{newmask} are added to the current signal mask. +If @var{how} is @code{SIG_UNBLOCK}, the signals specified to +@var{newmask} are removed from the current signal mask. + +Recall that signal masks are set on a per-thread basis, but signal +actions and signal handlers, as set with @code{sigaction}, are shared +between all threads. + +The @code{pthread_sigmask} function returns 0 on success, and one of the +following error codes on error: +@table @code +@item EINVAL +@var{how} is not one of @code{SIG_SETMASK}, @code{SIG_BLOCK}, or @code{SIG_UNBLOCK} + +@item EFAULT +@var{newmask} or @var{oldmask} point to invalid addresses +@end table +@end deftypefun + +@comment pthread.h +@comment POSIX +@deftypefun int pthread_kill (pthread_t @var{thread}, int @var{signo}) +@code{pthread_kill} sends signal number @var{signo} to the thread +@var{thread}. The signal is delivered and handled as described in +@ref{Signal Handling}. + +@code{pthread_kill} returns 0 on success, one of the following error codes +on error: +@table @code +@item EINVAL +@var{signo} is not a valid signal number + +@item ESRCH +The thread @var{thread} does not exist (e.g. it has already terminated) +@end table +@end deftypefun + +@comment pthread.h +@comment POSIX +@deftypefun int sigwait (const sigset_t *@var{set}, int *@var{sig}) +@code{sigwait} suspends the calling thread until one of the signals in +@var{set} is delivered to the calling thread. It then stores the number +of the signal received in the location pointed to by @var{sig} and +returns. The signals in @var{set} must be blocked and not ignored on +entrance to @code{sigwait}. If the delivered signal has a signal handler +function attached, that function is @emph{not} called. + +@code{sigwait} is a cancellation point. It always returns 0. +@end deftypefun + +For @code{sigwait} to work reliably, the signals being waited for must be +blocked in all threads, not only in the calling thread, since +otherwise the POSIX semantics for signal delivery do not guarantee +that it's the thread doing the @code{sigwait} that will receive the signal. +The best way to achieve this is block those signals before any threads +are created, and never unblock them in the program other than by +calling @code{sigwait}. + +Signal handling in LinuxThreads departs significantly from the POSIX +standard. According to the standard, ``asynchronous'' (external) signals +are addressed to the whole process (the collection of all threads), +which then delivers them to one particular thread. The thread that +actually receives the signal is any thread that does not currently block +the signal. + +In LinuxThreads, each thread is actually a kernel process with its own +PID, so external signals are always directed to one particular thread. +If, for instance, another thread is blocked in @code{sigwait} on that +signal, it will not be restarted. + +The LinuxThreads implementation of @code{sigwait} installs dummy signal +handlers for the signals in @var{set} for the duration of the +wait. Since signal handlers are shared between all threads, other +threads must not attach their own signal handlers to these signals, or +alternatively they should all block these signals (which is recommended +anyway). + +@node Threads and Fork +@section Threads and Fork + +It's not intuitively obvious what should happen when a multi-threaded POSIX +process calls @code{fork}. Not only are the semantics tricky, but you may +need to write code that does the right thing at fork time even if that code +doesn't use the @code{fork} function. Moreover, you need to be aware of +interaction between @code{fork} and some library features like +@code{pthread_once} and stdio streams. + +When @code{fork} is called by one of the threads of a process, it creates a new +process which is copy of the calling process. Effectively, in addition to +copying certain system objects, the function takes a snapshot of the memory +areas of the parent process, and creates identical areas in the child. +To make matters more complicated, with threads it's possible for two or more +threads to concurrently call fork to create two or more child processes. + +The child process has a copy of the address space of the parent, but it does +not inherit any of its threads. Execution of the child process is carried out +by a new thread which returns from @code{fork} function with a return value of +zero; it is the only thread in the child process. Because threads are not +inherited across fork, issues arise. At the time of the call to @code{fork}, +threads in the parent process other than the one calling @code{fork} may have +been executing critical regions of code. As a result, the child process may +get a copy of objects that are not in a well-defined state. This potential +problem affects all components of the program. + +Any program component which will continue being used in a child process must +correctly handle its state during @code{fork}. For this purpose, the POSIX +interface provides the special function @code{pthread_atfork} for installing +pointers to handler functions which are called from within @code{fork}. + +@comment pthread.h +@comment POSIX +@deftypefun int pthread_atfork (void (*@var{prepare})(void), void (*@var{parent})(void), void (*@var{child})(void)) + +@code{pthread_atfork} registers handler functions to be called just +before and just after a new process is created with @code{fork}. The +@var{prepare} handler will be called from the parent process, just +before the new process is created. The @var{parent} handler will be +called from the parent process, just before @code{fork} returns. The +@var{child} handler will be called from the child process, just before +@code{fork} returns. + +@code{pthread_atfork} returns 0 on success and a non-zero error code on +error. + +One or more of the three handlers @var{prepare}, @var{parent} and +@var{child} can be given as @code{NULL}, meaning that no handler needs +to be called at the corresponding point. + +@code{pthread_atfork} can be called several times to install several +sets of handlers. At @code{fork} time, the @var{prepare} handlers are +called in LIFO order (last added with @code{pthread_atfork}, first +called before @code{fork}), while the @var{parent} and @var{child} +handlers are called in FIFO order (first added, first called). + +If there is insufficient memory available to register the handlers, +@code{pthread_atfork} fails and returns @code{ENOMEM}. Otherwise it +returns 0. + +The functions @code{fork} and @code{pthread_atfork} must not be regarded as +reentrant from the context of the handlers. That is to say, if a +@code{pthread_atfork} handler invoked from within @code{fork} calls +@code{pthread_atfork} or @code{fork}, the behavior is undefined. + +Registering a triplet of handlers is an atomic operation with respect to fork. +If new handlers are registered at about the same time as a fork occurs, either +all three handlers will be called, or none of them will be called. + +The handlers are inherited by the child process, and there is no +way to remove them, short of using @code{exec} to load a new +pocess image. + +@end deftypefun + +To understand the purpose of @code{pthread_atfork}, recall that +@code{fork} duplicates the whole memory space, including mutexes in +their current locking state, but only the calling thread: other threads +are not running in the child process. The mutexes are not usable after +the @code{fork} and must be initialized with @code{pthread_mutex_init} +in the child process. This is a limitation of the current +implementation and might or might not be present in future versions. + +To avoid this, install handlers with @code{pthread_atfork} as follows: have the +@var{prepare} handler lock the mutexes (in locking order), and the +@var{parent} handler unlock the mutexes. The @var{child} handler should reset +the mutexes using @code{pthread_mutex_init}, as well as any other +synchronization objects such as condition variables. + +Locking the global mutexes before the fork ensures that all other threads are +locked out of the critical regions of code protected by those mutexes. Thus +when @code{fork} takes a snapshot of the parent's address space, that snapshot +will copy valid, stable data. Resetting the synchronization objects in the +child process will ensure they are properly cleansed of any artifacts from the +threading subsystem of the parent process. For example, a mutex may inherit +a wait queue of threads waiting for the lock; this wait queue makes no sense +in the child process. Initializing the mutex takes care of this. + +@node Streams and Fork +@section Streams and Fork + +The GNU standard I/O library has an internal mutex which guards the internal +linked list of all standard C FILE objects. This mutex is properly taken care +of during @code{fork} so that the child receives an intact copy of the list. +This allows the @code{fopen} function, and related stream-creating functions, +to work correctly in the child process, since these functions need to insert +into the list. + +However, the individual stream locks are not completely taken care of. Thus +unless the multithreaded application takes special precautions in its use of +@code{fork}, the child process might not be able to safely use the streams that +it inherited from the parent. In general, for any given open stream in the +parent that is to be used by the child process, the application must ensure +that that stream is not in use by another thread when @code{fork} is called. +Otherwise an inconsistent copy of the stream object be produced. An easy way to +ensure this is to use @code{flockfile} to lock the stream prior to calling +@code{fork} and then unlock it with @code{funlockfile} inside the parent +process, provided that the parent's threads properly honor these locks. +Nothing special needs to be done in the child process, since the library +internally resets all stream locks. + +Note that the stream locks are not shared between the parent and child. +For example, even if you ensure that, say, the stream @code{stdout} is properly +treated and can be safely used in the child, the stream locks do not provide +an exclusion mechanism between the parent and child. If both processes write +to @code{stdout}, strangely interleaved output may result regardless of +the explicit use of @code{flockfile} or implicit locks. + +Also note that these provisions are a GNU extension; other systems might not +provide any way for streams to be used in the child of a multithreaded process. +POSIX requires that such a child process confines itself to calling only +asynchronous safe functions, which excludes much of the library, including +standard I/O. + +@node Miscellaneous Thread Functions +@section Miscellaneous Thread Functions + +@comment pthread.h +@comment POSIX +@deftypefun {pthread_t} pthread_self (@var{void}) +@code{pthread_self} returns the thread identifier for the calling thread. +@end deftypefun + +@comment pthread.h +@comment POSIX +@deftypefun int pthread_equal (pthread_t thread1, pthread_t thread2) +@code{pthread_equal} determines if two thread identifiers refer to the same +thread. + +A non-zero value is returned if @var{thread1} and @var{thread2} refer to +the same thread. Otherwise, 0 is returned. +@end deftypefun + +@comment pthread.h +@comment POSIX +@deftypefun int pthread_detach (pthread_t @var{th}) +@code{pthread_detach} puts the thread @var{th} in the detached +state. This guarantees that the memory resources consumed by @var{th} +will be freed immediately when @var{th} terminates. However, this +prevents other threads from synchronizing on the termination of @var{th} +using @code{pthread_join}. + +A thread can be created initially in the detached state, using the +@code{detachstate} attribute to @code{pthread_create}. In contrast, +@code{pthread_detach} applies to threads created in the joinable state, +and which need to be put in the detached state later. + +After @code{pthread_detach} completes, subsequent attempts to perform +@code{pthread_join} on @var{th} will fail. If another thread is already +joining the thread @var{th} at the time @code{pthread_detach} is called, +@code{pthread_detach} does nothing and leaves @var{th} in the joinable +state. + +On success, 0 is returned. On error, one of the following codes is +returned: +@table @code +@item ESRCH +No thread could be found corresponding to that specified by @var{th} +@item EINVAL +The thread @var{th} is already in the detached state +@end table +@end deftypefun + +@comment pthread.h +@comment GNU +@deftypefun void pthread_kill_other_threads_np (@var{void}) +@code{pthread_kill_other_threads_np} is a non-portable LinuxThreads extension. +It causes all threads in the program to terminate immediately, except +the calling thread which proceeds normally. It is intended to be +called just before a thread calls one of the @code{exec} functions, +e.g. @code{execve}. + +Termination of the other threads is not performed through +@code{pthread_cancel} and completely bypasses the cancellation +mechanism. Hence, the current settings for cancellation state and +cancellation type are ignored, and the cleanup handlers are not +executed in the terminated threads. + +According to POSIX 1003.1c, a successful @code{exec*} in one of the +threads should automatically terminate all other threads in the program. +This behavior is not yet implemented in LinuxThreads. Calling +@code{pthread_kill_other_threads_np} before @code{exec*} achieves much +of the same behavior, except that if @code{exec*} ultimately fails, then +all other threads are already killed. +@end deftypefun + +@comment pthread.h +@comment POSIX +@deftypefun int pthread_once (pthread_once_t *once_@var{control}, void (*@var{init_routine}) (void)) + +The purpose of @code{pthread_once} is to ensure that a piece of +initialization code is executed at most once. The @var{once_control} +argument points to a static or extern variable statically initialized +to @code{PTHREAD_ONCE_INIT}. + +The first time @code{pthread_once} is called with a given +@var{once_control} argument, it calls @var{init_routine} with no +argument and changes the value of the @var{once_control} variable to +record that initialization has been performed. Subsequent calls to +@code{pthread_once} with the same @code{once_control} argument do +nothing. + +If a thread is cancelled while executing @var{init_routine} +the state of the @var{once_control} variable is reset so that +a future call to @code{pthread_once} will call the routine again. + +If the process forks while one or more threads are executing +@code{pthread_once} initialization routines, the states of their respective +@var{once_control} variables will appear to be reset in the child process so +that if the child calls @code{pthread_once}, the routines will be executed. + +@code{pthread_once} always returns 0. +@end deftypefun + +@comment pthread.h +@comment POSIX +@deftypefun int pthread_setschedparam (pthread_t target_@var{thread}, int @var{policy}, const struct sched_param *@var{param}) + +@code{pthread_setschedparam} sets the scheduling parameters for the +thread @var{target_thread} as indicated by @var{policy} and +@var{param}. @var{policy} can be either @code{SCHED_OTHER} (regular, +non-realtime scheduling), @code{SCHED_RR} (realtime, round-robin) or +@code{SCHED_FIFO} (realtime, first-in first-out). @var{param} specifies +the scheduling priority for the two realtime policies. See +@code{sched_setpolicy} for more information on scheduling policies. + +The realtime scheduling policies @code{SCHED_RR} and @code{SCHED_FIFO} +are available only to processes with superuser privileges. + +On success, @code{pthread_setschedparam} returns 0. On error it returns +one of the following codes: +@table @code +@item EINVAL +@var{policy} is not one of @code{SCHED_OTHER}, @code{SCHED_RR}, +@code{SCHED_FIFO}, or the priority value specified by @var{param} is not +valid for the specified policy + +@item EPERM +Realtime scheduling was requested but the calling process does not have +sufficient privileges. + +@item ESRCH +The @var{target_thread} is invalid or has already terminated + +@item EFAULT +@var{param} points outside the process memory space +@end table +@end deftypefun + +@comment pthread.h +@comment POSIX +@deftypefun int pthread_getschedparam (pthread_t target_@var{thread}, int *@var{policy}, struct sched_param *@var{param}) + +@code{pthread_getschedparam} retrieves the scheduling policy and +scheduling parameters for the thread @var{target_thread} and stores them +in the locations pointed to by @var{policy} and @var{param}, +respectively. + +@code{pthread_getschedparam} returns 0 on success, or one of the +following error codes on failure: +@table @code +@item ESRCH +The @var{target_thread} is invalid or has already terminated. + +@item EFAULT +@var{policy} or @var{param} point outside the process memory space. + +@end table +@end deftypefun + +@comment pthread.h +@comment POSIX +@deftypefun int pthread_setconcurrency (int @var{level}) +@code{pthread_setconcurrency} is unused in LinuxThreads due to the lack +of a mapping of user threads to kernel threads. It exists for source +compatibility. It does store the value @var{level} so that it can be +returned by a subsequent call to @code{pthread_getconcurrency}. It takes +no other action however. +@end deftypefun + +@comment pthread.h +@comment POSIX +@deftypefun int pthread_getconcurrency () +@code{pthread_getconcurrency} is unused in LinuxThreads due to the lack +of a mapping of user threads to kernel threads. It exists for source +compatibility. However, it will return the value that was set by the +last call to @code{pthread_setconcurrency}. +@end deftypefun diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/locale.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/locale.c new file mode 100644 index 00000000..c0879d0c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/locale.c @@ -0,0 +1,57 @@ +/* Copyright (C) 2003 Manuel Novoa III + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include "pthread.h" +#include "internals.h" +#include +#include +#include + +extern struct _pthread_descr_struct __pthread_initial_thread; + +__locale_t __curlocale(void) +{ + pthread_descr self = thread_self(); + +#ifdef NDEBUG + return THREAD_GETMEM (self, locale); +#else + { + __locale_t r = THREAD_GETMEM (self, locale); + + assert(r); + + return r; + } +#endif +} + +__locale_t __curlocale_set(__locale_t newloc) +{ + __locale_t oldloc; + pthread_descr self = thread_self(); + + oldloc = THREAD_GETMEM (self, locale); + + assert(newloc != LC_GLOBAL_LOCALE); + assert(oldloc); + + THREAD_SETMEM (self, locale, newloc); + + return oldloc; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/lockfile.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/lockfile.c new file mode 100644 index 00000000..d054b62c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/lockfile.c @@ -0,0 +1,43 @@ +/* lockfile - Handle locking and unlocking of stream. + Copyright (C) 1996, 1998, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +extern __typeof(pthread_mutexattr_init) __pthread_mutexattr_init attribute_hidden; +extern __typeof(pthread_mutexattr_settype) __pthread_mutexattr_settype attribute_hidden; +extern __typeof(pthread_mutexattr_destroy) __pthread_mutexattr_destroy attribute_hidden; + +/* Note: glibc puts flockfile, funlockfile, and ftrylockfile in both + * libc and libpthread. In uClibc, they are now in libc only. */ + +void __fresetlockfiles (void); +void __fresetlockfiles (void) +{ + FILE *fp; + pthread_mutexattr_t attr; + + __pthread_mutexattr_init(&attr); + __pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE_NP); + + for (fp = _stdio_openlist; fp != NULL; fp = fp->__nextopen) + __pthread_mutex_init(&fp->__lock, &attr); + + __pthread_mutexattr_destroy(&attr); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/manager.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/manager.c new file mode 100644 index 00000000..52c1ea9b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/manager.c @@ -0,0 +1,927 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +/* The "thread manager" thread: manages creation and termination of threads */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include /* for poll */ +#include /* for mmap */ +#include +#include +#include /* for waitpid macros */ + +#include "pthread.h" +#include "internals.h" +#include "spinlock.h" +#include "restart.h" +#include "semaphore.h" +#include "debug.h" /* PDEBUG, added by StS */ + + +/* poll() is not supported in kernel <= 2.0, therefore is __NR_poll is + * not available, we assume an old Linux kernel is in use and we will + * use select() instead. */ +#include +#ifndef __NR_poll +# define USE_SELECT +#endif + +libpthread_hidden_proto(waitpid) +libpthread_hidden_proto(raise) + +/* Array of active threads. Entry 0 is reserved for the initial thread. */ +struct pthread_handle_struct __pthread_handles[PTHREAD_THREADS_MAX] = +{ { __LOCK_INITIALIZER, &__pthread_initial_thread, 0}, + { __LOCK_INITIALIZER, &__pthread_manager_thread, 0}, /* All NULLs */ }; + +/* For debugging purposes put the maximum number of threads in a variable. */ +const int __linuxthreads_pthread_threads_max = PTHREAD_THREADS_MAX; + +/* Indicate whether at least one thread has a user-defined stack (if 1), + or if all threads have stacks supplied by LinuxThreads (if 0). */ +int __pthread_nonstandard_stacks; + +/* Number of active entries in __pthread_handles (used by gdb) */ +volatile int __pthread_handles_num = 2; + +/* Whether to use debugger additional actions for thread creation + (set to 1 by gdb) */ +volatile int __pthread_threads_debug; + +/* Globally enabled events. */ +volatile td_thr_events_t __pthread_threads_events; + +/* Pointer to thread descriptor with last event. */ +volatile pthread_descr __pthread_last_event; + +/* Mapping from stack segment to thread descriptor. */ +/* Stack segment numbers are also indices into the __pthread_handles array. */ +/* Stack segment number 0 is reserved for the initial thread. */ + +static __inline__ pthread_descr thread_segment(int seg) +{ + return (pthread_descr)(THREAD_STACK_START_ADDRESS - (seg - 1) * STACK_SIZE) + - 1; +} + +/* Flag set in signal handler to record child termination */ + +static volatile int terminated_children = 0; + +/* Flag set when the initial thread is blocked on pthread_exit waiting + for all other threads to terminate */ + +static int main_thread_exiting = 0; + +/* Counter used to generate unique thread identifier. + Thread identifier is pthread_threads_counter + segment. */ + +static pthread_t pthread_threads_counter = 0; + +/* Forward declarations */ + +static int pthread_handle_create(pthread_t *thread, const pthread_attr_t *attr, + void * (*start_routine)(void *), void *arg, + sigset_t *mask, int father_pid, + int report_events, + td_thr_events_t *event_maskp); +static void pthread_handle_free(pthread_t th_id); +static void pthread_handle_exit(pthread_descr issuing_thread, int exitcode) attribute_noreturn; +static void pthread_reap_children(void); +static void pthread_kill_all_threads(int sig, int main_thread_also); + +/* The server thread managing requests for thread creation and termination */ + +int attribute_noreturn __pthread_manager(void *arg) +{ + int reqfd = (int) (long int) arg; +#ifdef USE_SELECT + struct timeval tv; + fd_set fd; +#else + struct pollfd ufd; +#endif + sigset_t manager_mask; + int n; + struct pthread_request request; + + /* If we have special thread_self processing, initialize it. */ +#ifdef INIT_THREAD_SELF + INIT_THREAD_SELF(&__pthread_manager_thread, 1); +#endif + /* Set the error variable. */ + __pthread_manager_thread.p_errnop = &__pthread_manager_thread.p_errno; + __pthread_manager_thread.p_h_errnop = &__pthread_manager_thread.p_h_errno; + +#ifdef __UCLIBC_HAS_XLOCALE__ + /* Initialize thread's locale to the global locale. */ + __pthread_manager_thread.locale = __global_locale; +#endif /* __UCLIBC_HAS_XLOCALE__ */ + + /* Block all signals except __pthread_sig_cancel and SIGTRAP */ + __sigfillset(&manager_mask); + sigdelset(&manager_mask, __pthread_sig_cancel); /* for thread termination */ + sigdelset(&manager_mask, SIGTRAP); /* for debugging purposes */ + if (__pthread_threads_debug && __pthread_sig_debug > 0) + sigdelset(&manager_mask, __pthread_sig_debug); + sigprocmask(SIG_SETMASK, &manager_mask, NULL); + /* Raise our priority to match that of main thread */ + __pthread_manager_adjust_prio(__pthread_main_thread->p_priority); + /* Synchronize debugging of the thread manager */ + n = TEMP_FAILURE_RETRY(read(reqfd, (char *)&request, + sizeof(request))); +#ifndef USE_SELECT + ufd.fd = reqfd; + ufd.events = POLLIN; +#endif + /* Enter server loop */ + while(1) { +#ifdef USE_SELECT + tv.tv_sec = 2; + tv.tv_usec = 0; + FD_ZERO (&fd); + FD_SET (reqfd, &fd); + n = select (reqfd + 1, &fd, NULL, NULL, &tv); +#else + PDEBUG("before poll\n"); + n = poll(&ufd, 1, 2000); + PDEBUG("after poll\n"); +#endif + /* Check for termination of the main thread */ + if (getppid() == 1) { + pthread_kill_all_threads(SIGKILL, 0); + _exit(0); + } + /* Check for dead children */ + if (terminated_children) { + terminated_children = 0; + pthread_reap_children(); + } + /* Read and execute request */ +#ifdef USE_SELECT + if (n == 1) +#else + if (n == 1 && (ufd.revents & POLLIN)) +#endif + { + + PDEBUG("before read\n"); + n = read(reqfd, (char *)&request, sizeof(request)); + PDEBUG("after read, n=%d\n", n); + switch(request.req_kind) { + case REQ_CREATE: + PDEBUG("got REQ_CREATE\n"); + request.req_thread->p_retcode = + pthread_handle_create((pthread_t *) &request.req_thread->p_retval, + request.req_args.create.attr, + request.req_args.create.fn, + request.req_args.create.arg, + &request.req_args.create.mask, + request.req_thread->p_pid, + request.req_thread->p_report_events, + &request.req_thread->p_eventbuf.eventmask); + PDEBUG("restarting %p\n", request.req_thread); + restart(request.req_thread); + break; + case REQ_FREE: + PDEBUG("got REQ_FREE\n"); + pthread_handle_free(request.req_args.free.thread_id); + break; + case REQ_PROCESS_EXIT: + PDEBUG("got REQ_PROCESS_EXIT from %p, exit code = %d\n", + request.req_thread, request.req_args.exit.code); + pthread_handle_exit(request.req_thread, + request.req_args.exit.code); + break; + case REQ_MAIN_THREAD_EXIT: + PDEBUG("got REQ_MAIN_THREAD_EXIT\n"); + main_thread_exiting = 1; + /* Reap children in case all other threads died and the signal handler + went off before we set main_thread_exiting to 1, and therefore did + not do REQ_KICK. */ + pthread_reap_children(); + + if (__pthread_main_thread->p_nextlive == __pthread_main_thread) { + restart(__pthread_main_thread); + /* The main thread will now call exit() which will trigger an + __on_exit handler, which in turn will send REQ_PROCESS_EXIT + to the thread manager. In case you are wondering how the + manager terminates from its loop here. */ + } + break; + case REQ_POST: + PDEBUG("got REQ_POST\n"); + __new_sem_post(request.req_args.post); + break; + case REQ_DEBUG: + PDEBUG("got REQ_DEBUG\n"); + /* Make gdb aware of new thread and gdb will restart the + new thread when it is ready to handle the new thread. */ + if (__pthread_threads_debug && __pthread_sig_debug > 0) { + PDEBUG("about to call raise(__pthread_sig_debug)\n"); + raise(__pthread_sig_debug); + } + case REQ_KICK: + /* This is just a prod to get the manager to reap some + threads right away, avoiding a potential delay at shutdown. */ + break; + } + } + } +} + +int attribute_noreturn __pthread_manager_event(void *arg) +{ + /* If we have special thread_self processing, initialize it. */ +#ifdef INIT_THREAD_SELF + INIT_THREAD_SELF(&__pthread_manager_thread, 1); +#endif + + /* Get the lock the manager will free once all is correctly set up. */ + __pthread_lock (THREAD_GETMEM((&__pthread_manager_thread), p_lock), NULL); + /* Free it immediately. */ + __pthread_unlock (THREAD_GETMEM((&__pthread_manager_thread), p_lock)); + + __pthread_manager(arg); +} + +/* Process creation */ +static int +attribute_noreturn +pthread_start_thread(void *arg) +{ + pthread_descr self = (pthread_descr) arg; + struct pthread_request request; + void * outcome; + /* Initialize special thread_self processing, if any. */ +#ifdef INIT_THREAD_SELF + INIT_THREAD_SELF(self, self->p_nr); +#endif + PDEBUG("\n"); + /* Make sure our pid field is initialized, just in case we get there + before our father has initialized it. */ + THREAD_SETMEM(self, p_pid, getpid()); + /* Initial signal mask is that of the creating thread. (Otherwise, + we'd just inherit the mask of the thread manager.) */ + sigprocmask(SIG_SETMASK, &self->p_start_args.mask, NULL); + /* Set the scheduling policy and priority for the new thread, if needed */ + if (THREAD_GETMEM(self, p_start_args.schedpolicy) >= 0) + /* Explicit scheduling attributes were provided: apply them */ + sched_setscheduler(THREAD_GETMEM(self, p_pid), + THREAD_GETMEM(self, p_start_args.schedpolicy), + &self->p_start_args.schedparam); + else if (__pthread_manager_thread.p_priority > 0) + /* Default scheduling required, but thread manager runs in realtime + scheduling: switch new thread to SCHED_OTHER policy */ + { + struct sched_param default_params; + default_params.sched_priority = 0; + sched_setscheduler(THREAD_GETMEM(self, p_pid), + SCHED_OTHER, &default_params); + } + /* Make gdb aware of new thread */ + if (__pthread_threads_debug && __pthread_sig_debug > 0) { + request.req_thread = self; + request.req_kind = REQ_DEBUG; + TEMP_FAILURE_RETRY(write(__pthread_manager_request, + (char *) &request, sizeof(request))); + suspend(self); + } + /* Run the thread code */ + outcome = self->p_start_args.start_routine(THREAD_GETMEM(self, + p_start_args.arg)); + /* Exit with the given return value */ + __pthread_do_exit(outcome, CURRENT_STACK_FRAME); +} + +static int +attribute_noreturn +pthread_start_thread_event(void *arg) +{ + pthread_descr self = (pthread_descr) arg; + +#ifdef INIT_THREAD_SELF + INIT_THREAD_SELF(self, self->p_nr); +#endif + /* Make sure our pid field is initialized, just in case we get there + before our father has initialized it. */ + THREAD_SETMEM(self, p_pid, getpid()); + /* Get the lock the manager will free once all is correctly set up. */ + __pthread_lock (THREAD_GETMEM(self, p_lock), NULL); + /* Free it immediately. */ + __pthread_unlock (THREAD_GETMEM(self, p_lock)); + + /* Continue with the real function. */ + pthread_start_thread (arg); +} + +static int pthread_allocate_stack(const pthread_attr_t *attr, + pthread_descr default_new_thread, + int pagesize, + pthread_descr * out_new_thread, + char ** out_new_thread_bottom, + char ** out_guardaddr, + size_t * out_guardsize) +{ + pthread_descr new_thread; + char * new_thread_bottom; + char * guardaddr; + size_t stacksize, guardsize; + + if (attr != NULL && attr->__stackaddr_set) + { + /* The user provided a stack. */ + new_thread = (pthread_descr) ((long)(attr->__stackaddr) & -sizeof(void *)) - 1; + new_thread_bottom = (char *) attr->__stackaddr - attr->__stacksize; + guardaddr = NULL; + guardsize = 0; + __pthread_nonstandard_stacks = 1; +#ifndef __ARCH_USE_MMU__ + /* check the initial thread stack boundaries so they don't overlap */ + NOMMU_INITIAL_THREAD_BOUNDS((char *) new_thread, (char *) new_thread_bottom); + + PDEBUG("initial stack: bos=%p, tos=%p\n", __pthread_initial_thread_bos, + __pthread_initial_thread_tos); +#endif + } + else + { +#ifdef __ARCH_USE_MMU__ + stacksize = STACK_SIZE - pagesize; + if (attr != NULL) + stacksize = MIN(stacksize, roundup(attr->__stacksize, pagesize)); + /* Allocate space for stack and thread descriptor at default address */ + new_thread = default_new_thread; + new_thread_bottom = (char *) (new_thread + 1) - stacksize; + if (mmap((caddr_t)((char *)(new_thread + 1) - INITIAL_STACK_SIZE), + INITIAL_STACK_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, + MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED | MAP_GROWSDOWN, + -1, 0) == MAP_FAILED) + /* Bad luck, this segment is already mapped. */ + return -1; + /* We manage to get a stack. Now see whether we need a guard + and allocate it if necessary. Notice that the default + attributes (stack_size = STACK_SIZE - pagesize) do not need + a guard page, since the RLIMIT_STACK soft limit prevents stacks + from running into one another. */ + if (stacksize == (size_t) (STACK_SIZE - pagesize)) + { + /* We don't need a guard page. */ + guardaddr = NULL; + guardsize = 0; + } + else + { + /* Put a bad page at the bottom of the stack */ + guardsize = attr->__guardsize; + guardaddr = (void *)new_thread_bottom - guardsize; + if (mmap((caddr_t) guardaddr, guardsize, 0, MAP_FIXED, -1, 0) + == MAP_FAILED) + { + /* We don't make this an error. */ + guardaddr = NULL; + guardsize = 0; + } + } +#else + /* We cannot mmap to this huge chunk of stack space when we don't have + * an MMU. Pretend we are using a user provided stack even if there was + * none provided by the user. Thus, we get around the mmap and reservation + * of a huge stack segment. -StS */ + + stacksize = INITIAL_STACK_SIZE; + /* The user may want to use a non-default stacksize */ + if (attr != NULL) + { + stacksize = attr->__stacksize; + } + + /* malloc a stack - memory from the bottom up */ + if ((new_thread_bottom = malloc(stacksize)) == NULL) + { + /* bad luck, we cannot malloc any more */ + return -1 ; + } + PDEBUG("malloced chunk: base=%p, size=0x%04x\n", new_thread_bottom, stacksize); + + /* Set up the pointers. new_thread marks the TOP of the stack frame and + * the address of the pthread_descr struct at the same time. Therefore we + * must account for its size and fit it in the malloc()'ed block. The + * value of `new_thread' is then passed to clone() as the stack argument. + * + * ^ +------------------------+ + * | | pthread_descr struct | + * | +------------------------+ <- new_thread + * malloc block | | | + * | | thread stack | + * | | | + * v +------------------------+ <- new_thread_bottom + * + * Note: The calculated value of new_thread must be word aligned otherwise + * the kernel chokes on a non-aligned stack frame. Choose the lower + * available word boundary. + */ + new_thread = ((pthread_descr) ((int)(new_thread_bottom + stacksize) & -sizeof(void*))) - 1; + guardaddr = NULL; + guardsize = 0; + + PDEBUG("thread stack: bos=%p, tos=%p\n", new_thread_bottom, new_thread); + + /* check the initial thread stack boundaries so they don't overlap */ + NOMMU_INITIAL_THREAD_BOUNDS((char *) new_thread, (char *) new_thread_bottom); + + PDEBUG("initial stack: bos=%p, tos=%p\n", __pthread_initial_thread_bos, + __pthread_initial_thread_tos); + + /* on non-MMU systems we always have non-standard stack frames */ + __pthread_nonstandard_stacks = 1; + +#endif /* __ARCH_USE_MMU__ */ + } + + /* Clear the thread data structure. */ + memset (new_thread, '\0', sizeof (*new_thread)); + *out_new_thread = new_thread; + *out_new_thread_bottom = new_thread_bottom; + *out_guardaddr = guardaddr; + *out_guardsize = guardsize; + return 0; +} + +static int pthread_handle_create(pthread_t *thread, const pthread_attr_t *attr, + void * (*start_routine)(void *), void *arg, + sigset_t * mask, int father_pid, + int report_events, + td_thr_events_t *event_maskp) +{ + size_t sseg; + int pid; + pthread_descr new_thread; + char * new_thread_bottom; + pthread_t new_thread_id; + char *guardaddr = NULL; + size_t guardsize = 0; + int pagesize = getpagesize(); + int saved_errno = 0; + + /* First check whether we have to change the policy and if yes, whether + we can do this. Normally this should be done by examining the + return value of the sched_setscheduler call in pthread_start_thread + but this is hard to implement. FIXME */ + if (attr != NULL && attr->__schedpolicy != SCHED_OTHER && geteuid () != 0) + return EPERM; + /* Find a free segment for the thread, and allocate a stack if needed */ + for (sseg = 2; ; sseg++) + { + if (sseg >= PTHREAD_THREADS_MAX) + return EAGAIN; + if (__pthread_handles[sseg].h_descr != NULL) + continue; + if (pthread_allocate_stack(attr, thread_segment(sseg), pagesize, + &new_thread, &new_thread_bottom, + &guardaddr, &guardsize) == 0) + break; +#ifndef __ARCH_USE_MMU__ + else + /* When there is MMU, mmap () is used to allocate the stack. If one + * segment is already mapped, we should continue to see if we can + * use the next one. However, when there is no MMU, malloc () is used. + * It's waste of CPU cycles to continue to try if it fails. */ + return EAGAIN; +#endif + } + __pthread_handles_num++; + /* Allocate new thread identifier */ + pthread_threads_counter += PTHREAD_THREADS_MAX; + new_thread_id = sseg + pthread_threads_counter; + /* Initialize the thread descriptor. Elements which have to be + initialized to zero already have this value. */ + new_thread->p_tid = new_thread_id; + new_thread->p_lock = &(__pthread_handles[sseg].h_lock); + new_thread->p_cancelstate = PTHREAD_CANCEL_ENABLE; + new_thread->p_canceltype = PTHREAD_CANCEL_DEFERRED; + new_thread->p_errnop = &new_thread->p_errno; + new_thread->p_h_errnop = &new_thread->p_h_errno; +#ifdef __UCLIBC_HAS_XLOCALE__ + /* Initialize thread's locale to the global locale. */ + new_thread->locale = __global_locale; +#endif /* __UCLIBC_HAS_XLOCALE__ */ + new_thread->p_guardaddr = guardaddr; + new_thread->p_guardsize = guardsize; + new_thread->p_self = new_thread; + new_thread->p_nr = sseg; + /* Initialize the thread handle */ + __pthread_init_lock(&__pthread_handles[sseg].h_lock); + __pthread_handles[sseg].h_descr = new_thread; + __pthread_handles[sseg].h_bottom = new_thread_bottom; + /* Determine scheduling parameters for the thread */ + new_thread->p_start_args.schedpolicy = -1; + if (attr != NULL) { + new_thread->p_detached = attr->__detachstate; + new_thread->p_userstack = attr->__stackaddr_set; + + switch(attr->__inheritsched) { + case PTHREAD_EXPLICIT_SCHED: + new_thread->p_start_args.schedpolicy = attr->__schedpolicy; + memcpy (&new_thread->p_start_args.schedparam, &attr->__schedparam, + sizeof (struct sched_param)); + break; + case PTHREAD_INHERIT_SCHED: + new_thread->p_start_args.schedpolicy = sched_getscheduler(father_pid); + sched_getparam(father_pid, &new_thread->p_start_args.schedparam); + break; + } + new_thread->p_priority = + new_thread->p_start_args.schedparam.sched_priority; + } + /* Finish setting up arguments to pthread_start_thread */ + new_thread->p_start_args.start_routine = start_routine; + new_thread->p_start_args.arg = arg; + new_thread->p_start_args.mask = *mask; + /* Raise priority of thread manager if needed */ + __pthread_manager_adjust_prio(new_thread->p_priority); + /* Do the cloning. We have to use two different functions depending + on whether we are debugging or not. */ + pid = 0; /* Note that the thread never can have PID zero. */ + + + /* ******************************************************** */ + /* This code was moved from below to cope with running threads + * on uClinux systems. See comment below... + * Insert new thread in doubly linked list of active threads */ + new_thread->p_prevlive = __pthread_main_thread; + new_thread->p_nextlive = __pthread_main_thread->p_nextlive; + __pthread_main_thread->p_nextlive->p_prevlive = new_thread; + __pthread_main_thread->p_nextlive = new_thread; + /* ********************************************************* */ + + if (report_events) + { + /* See whether the TD_CREATE event bit is set in any of the + masks. */ + int idx = __td_eventword (TD_CREATE); + uint32_t m = __td_eventmask (TD_CREATE); + + if ((m & (__pthread_threads_events.event_bits[idx] + | event_maskp->event_bits[idx])) != 0) + { + /* Lock the mutex the child will use now so that it will stop. */ + __pthread_lock(new_thread->p_lock, NULL); + + /* We have to report this event. */ +#ifdef __ia64__ + pid = __clone2(pthread_start_thread_event, (void **) new_thread, + (char *)new_thread - new_thread_bottom, + CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | + __pthread_sig_cancel, new_thread); +#else + pid = clone(pthread_start_thread_event, (void **) new_thread, + CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | + __pthread_sig_cancel, new_thread); +#endif + + saved_errno = errno; + if (pid != -1) + { + /* Now fill in the information about the new thread in + the newly created thread's data structure. We cannot let + the new thread do this since we don't know whether it was + already scheduled when we send the event. */ + new_thread->p_eventbuf.eventdata = new_thread; + new_thread->p_eventbuf.eventnum = TD_CREATE; + __pthread_last_event = new_thread; + + /* We have to set the PID here since the callback function + in the debug library will need it and we cannot guarantee + the child got scheduled before the debugger. */ + new_thread->p_pid = pid; + + /* Now call the function which signals the event. */ + __linuxthreads_create_event (); + + /* Now restart the thread. */ + __pthread_unlock(new_thread->p_lock); + } + } + } + if (pid == 0) + { + PDEBUG("cloning new_thread = %p\n", new_thread); +#ifdef __ia64__ + pid = __clone2(pthread_start_thread, (void **) new_thread, + (char *)new_thread - new_thread_bottom, + CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | + __pthread_sig_cancel, new_thread); +#else + pid = clone(pthread_start_thread, (void **) new_thread, + CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | + __pthread_sig_cancel, new_thread); +#endif + saved_errno = errno; + } + /* Check if cloning succeeded */ + if (pid == -1) { + /******************************************************** + * Code inserted to remove the thread from our list of active + * threads in case of failure (needed to cope with uClinux), + * See comment below. */ + new_thread->p_nextlive->p_prevlive = new_thread->p_prevlive; + new_thread->p_prevlive->p_nextlive = new_thread->p_nextlive; + /********************************************************/ + + /* Free the stack if we allocated it */ + if (attr == NULL || !attr->__stackaddr_set) + { +#ifdef __ARCH_USE_MMU__ + if (new_thread->p_guardsize != 0) + munmap(new_thread->p_guardaddr, new_thread->p_guardsize); + munmap((caddr_t)((char *)(new_thread+1) - INITIAL_STACK_SIZE), + INITIAL_STACK_SIZE); +#else + free(new_thread_bottom); +#endif /* __ARCH_USE_MMU__ */ + } + __pthread_handles[sseg].h_descr = NULL; + __pthread_handles[sseg].h_bottom = NULL; + __pthread_handles_num--; + return errno; + } + PDEBUG("new thread pid = %d\n", pid); + +#if 0 + /* *********************************************************** + This code has been moved before the call to clone(). In uClinux, + the use of wait on a semaphore is dependant upon that the child so + the child must be in the active threads list. This list is used in + pthread_find_self() to get the pthread_descr of self. So, if the + child calls sem_wait before this code is executed , it will hang + forever and initial_thread will instead be posted by a sem_post + call. */ + + /* Insert new thread in doubly linked list of active threads */ + new_thread->p_prevlive = __pthread_main_thread; + new_thread->p_nextlive = __pthread_main_thread->p_nextlive; + __pthread_main_thread->p_nextlive->p_prevlive = new_thread; + __pthread_main_thread->p_nextlive = new_thread; + /************************************************************/ +#endif + + /* Set pid field of the new thread, in case we get there before the + child starts. */ + new_thread->p_pid = pid; + /* We're all set */ + *thread = new_thread_id; + return 0; +} + + +/* Try to free the resources of a thread when requested by pthread_join + or pthread_detach on a terminated thread. */ + +static void pthread_free(pthread_descr th) +{ + pthread_handle handle; + pthread_readlock_info *iter, *next; + char *h_bottom_save; + + /* Make the handle invalid */ + handle = thread_handle(th->p_tid); + __pthread_lock(&handle->h_lock, NULL); + h_bottom_save = handle->h_bottom; + handle->h_descr = NULL; + handle->h_bottom = (char *)(-1L); + __pthread_unlock(&handle->h_lock); +#ifdef FREE_THREAD_SELF + FREE_THREAD_SELF(th, th->p_nr); +#endif + /* One fewer threads in __pthread_handles */ + __pthread_handles_num--; + + /* Destroy read lock list, and list of free read lock structures. + If the former is not empty, it means the thread exited while + holding read locks! */ + + for (iter = th->p_readlock_list; iter != NULL; iter = next) + { + next = iter->pr_next; + free(iter); + } + + for (iter = th->p_readlock_free; iter != NULL; iter = next) + { + next = iter->pr_next; + free(iter); + } + + /* If initial thread, nothing to free */ + if (th == &__pthread_initial_thread) return; +#ifdef __ARCH_USE_MMU__ + if (!th->p_userstack) + { + /* Free the stack and thread descriptor area */ + if (th->p_guardsize != 0) + munmap(th->p_guardaddr, th->p_guardsize); + munmap((caddr_t) ((char *)(th+1) - STACK_SIZE), STACK_SIZE); + } +#else + /* For non-MMU systems we always malloc the stack, so free it here. -StS */ + if (!th->p_userstack) { + free(h_bottom_save); + } +#endif /* __ARCH_USE_MMU__ */ +} + +/* Handle threads that have exited */ + +static void pthread_exited(pid_t pid) +{ + pthread_descr th; + int detached; + /* Find thread with that pid */ + for (th = __pthread_main_thread->p_nextlive; + th != __pthread_main_thread; + th = th->p_nextlive) { + if (th->p_pid == pid) { + /* Remove thread from list of active threads */ + th->p_nextlive->p_prevlive = th->p_prevlive; + th->p_prevlive->p_nextlive = th->p_nextlive; + /* Mark thread as exited, and if detached, free its resources */ + __pthread_lock(th->p_lock, NULL); + th->p_exited = 1; + /* If we have to signal this event do it now. */ + if (th->p_report_events) + { + /* See whether TD_REAP is in any of the mask. */ + int idx = __td_eventword (TD_REAP); + uint32_t mask = __td_eventmask (TD_REAP); + + if ((mask & (__pthread_threads_events.event_bits[idx] + | th->p_eventbuf.eventmask.event_bits[idx])) != 0) + { + /* Yep, we have to signal the reapage. */ + th->p_eventbuf.eventnum = TD_REAP; + th->p_eventbuf.eventdata = th; + __pthread_last_event = th; + + /* Now call the function to signal the event. */ + __linuxthreads_reap_event(); + } + } + detached = th->p_detached; + __pthread_unlock(th->p_lock); + if (detached) + pthread_free(th); + break; + } + } + /* If all threads have exited and the main thread is pending on a + pthread_exit, wake up the main thread and terminate ourselves. */ + if (main_thread_exiting && + __pthread_main_thread->p_nextlive == __pthread_main_thread) { + restart(__pthread_main_thread); + /* Same logic as REQ_MAIN_THREAD_EXIT. */ + } +} + +static void pthread_reap_children(void) +{ + pid_t pid; + int status; + PDEBUG("\n"); + + while ((pid = waitpid(-1, &status, WNOHANG | __WCLONE)) > 0) { + pthread_exited(pid); + if (WIFSIGNALED(status)) { + /* If a thread died due to a signal, send the same signal to + all other threads, including the main thread. */ + pthread_kill_all_threads(WTERMSIG(status), 1); + _exit(0); + } + } +} + +/* Try to free the resources of a thread when requested by pthread_join + or pthread_detach on a terminated thread. */ + +static void pthread_handle_free(pthread_t th_id) +{ + pthread_handle handle = thread_handle(th_id); + pthread_descr th; + + __pthread_lock(&handle->h_lock, NULL); + if (invalid_handle(handle, th_id)) { + /* pthread_reap_children has deallocated the thread already, + nothing needs to be done */ + __pthread_unlock(&handle->h_lock); + return; + } + th = handle->h_descr; + if (th->p_exited) { + __pthread_unlock(&handle->h_lock); + pthread_free(th); + } else { + /* The Unix process of the thread is still running. + Mark the thread as detached so that the thread manager will + deallocate its resources when the Unix process exits. */ + th->p_detached = 1; + __pthread_unlock(&handle->h_lock); + } +} + +/* Send a signal to all running threads */ + +static void pthread_kill_all_threads(int sig, int main_thread_also) +{ + pthread_descr th; + for (th = __pthread_main_thread->p_nextlive; + th != __pthread_main_thread; + th = th->p_nextlive) { + kill(th->p_pid, sig); + } + if (main_thread_also) { + kill(__pthread_main_thread->p_pid, sig); + } +} + +/* Process-wide exit() */ + +static void pthread_handle_exit(pthread_descr issuing_thread, int exitcode) +{ + pthread_descr th; + __pthread_exit_requested = 1; + __pthread_exit_code = exitcode; + /* Send the CANCEL signal to all running threads, including the main + thread, but excluding the thread from which the exit request originated + (that thread must complete the exit, e.g. calling atexit functions + and flushing stdio buffers). */ + for (th = issuing_thread->p_nextlive; + th != issuing_thread; + th = th->p_nextlive) { + kill(th->p_pid, __pthread_sig_cancel); + } + /* Now, wait for all these threads, so that they don't become zombies + and their times are properly added to the thread manager's times. */ + for (th = issuing_thread->p_nextlive; + th != issuing_thread; + th = th->p_nextlive) { + waitpid(th->p_pid, NULL, __WCLONE); + } + restart(issuing_thread); + _exit(0); +} + +/* Handler for __pthread_sig_cancel in thread manager thread */ + +void __pthread_manager_sighandler(int sig attribute_unused) +{ + int kick_manager = terminated_children == 0 && main_thread_exiting; + terminated_children = 1; + + /* If the main thread is terminating, kick the thread manager loop + each time some threads terminate. This eliminates a two second + shutdown delay caused by the thread manager sleeping in the + call to __poll(). Instead, the thread manager is kicked into + action, reaps the outstanding threads and resumes the main thread + so that it can complete the shutdown. */ + + if (kick_manager) { + struct pthread_request request; + request.req_thread = 0; + request.req_kind = REQ_KICK; + TEMP_FAILURE_RETRY(write(__pthread_manager_request, + (char *) &request, sizeof(request))); + } +} + +/* Adjust priority of thread manager so that it always run at a priority + higher than all threads */ + +void __pthread_manager_adjust_prio(int thread_prio) +{ + struct sched_param param; + + if (thread_prio <= __pthread_manager_thread.p_priority) return; + param.sched_priority = + thread_prio < sched_get_priority_max(SCHED_FIFO) + ? thread_prio + 1 : thread_prio; + sched_setscheduler(__pthread_manager_thread.p_pid, SCHED_FIFO, ¶m); + __pthread_manager_thread.p_priority = thread_prio; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/mutex.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/mutex.c new file mode 100644 index 00000000..89084145 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/mutex.c @@ -0,0 +1,362 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +/* Mutexes */ + +#include +#include +#include +#include +#include "pthread.h" +#include "internals.h" +#include "spinlock.h" +#include "queue.h" +#include "restart.h" + +int attribute_hidden __pthread_mutex_init(pthread_mutex_t * mutex, + const pthread_mutexattr_t * mutex_attr) +{ + __pthread_init_lock(&mutex->__m_lock); + mutex->__m_kind = + mutex_attr == NULL ? PTHREAD_MUTEX_TIMED_NP : mutex_attr->__mutexkind; + mutex->__m_count = 0; + mutex->__m_owner = NULL; + return 0; +} +strong_alias (__pthread_mutex_init, pthread_mutex_init) + +int attribute_hidden __pthread_mutex_destroy(pthread_mutex_t * mutex) +{ + switch (mutex->__m_kind) { + case PTHREAD_MUTEX_ADAPTIVE_NP: + case PTHREAD_MUTEX_RECURSIVE_NP: + if ((mutex->__m_lock.__status & 1) != 0) + return EBUSY; + return 0; + case PTHREAD_MUTEX_ERRORCHECK_NP: + case PTHREAD_MUTEX_TIMED_NP: + if (mutex->__m_lock.__status != 0) + return EBUSY; + return 0; + default: + return EINVAL; + } +} +strong_alias (__pthread_mutex_destroy, pthread_mutex_destroy) + +int attribute_hidden __pthread_mutex_trylock(pthread_mutex_t * mutex) +{ + pthread_descr self; + int retcode; + + switch(mutex->__m_kind) { + case PTHREAD_MUTEX_ADAPTIVE_NP: + retcode = __pthread_trylock(&mutex->__m_lock); + return retcode; + case PTHREAD_MUTEX_RECURSIVE_NP: + self = thread_self(); + if (mutex->__m_owner == self) { + mutex->__m_count++; + return 0; + } + retcode = __pthread_trylock(&mutex->__m_lock); + if (retcode == 0) { + mutex->__m_owner = self; + mutex->__m_count = 0; + } + return retcode; + case PTHREAD_MUTEX_ERRORCHECK_NP: + retcode = __pthread_alt_trylock(&mutex->__m_lock); + if (retcode == 0) { + mutex->__m_owner = thread_self(); + } + return retcode; + case PTHREAD_MUTEX_TIMED_NP: + retcode = __pthread_alt_trylock(&mutex->__m_lock); + return retcode; + default: + return EINVAL; + } +} +strong_alias (__pthread_mutex_trylock, pthread_mutex_trylock) + +int attribute_hidden __pthread_mutex_lock(pthread_mutex_t * mutex) +{ + pthread_descr self; + + switch(mutex->__m_kind) { + case PTHREAD_MUTEX_ADAPTIVE_NP: + __pthread_lock(&mutex->__m_lock, NULL); + return 0; + case PTHREAD_MUTEX_RECURSIVE_NP: + self = thread_self(); + if (mutex->__m_owner == self) { + mutex->__m_count++; + return 0; + } + __pthread_lock(&mutex->__m_lock, self); + mutex->__m_owner = self; + mutex->__m_count = 0; + return 0; + case PTHREAD_MUTEX_ERRORCHECK_NP: + self = thread_self(); + if (mutex->__m_owner == self) return EDEADLK; + __pthread_alt_lock(&mutex->__m_lock, self); + mutex->__m_owner = self; + return 0; + case PTHREAD_MUTEX_TIMED_NP: + __pthread_alt_lock(&mutex->__m_lock, NULL); + return 0; + default: + return EINVAL; + } +} +strong_alias (__pthread_mutex_lock, pthread_mutex_lock) + +int pthread_mutex_timedlock (pthread_mutex_t *mutex, + const struct timespec *abstime) +{ + pthread_descr self; + int res; + + if (__builtin_expect (abstime->tv_nsec, 0) < 0 + || __builtin_expect (abstime->tv_nsec, 0) >= 1000000000) + return EINVAL; + + switch(mutex->__m_kind) { + case PTHREAD_MUTEX_ADAPTIVE_NP: + __pthread_lock(&mutex->__m_lock, NULL); + return 0; + case PTHREAD_MUTEX_RECURSIVE_NP: + self = thread_self(); + if (mutex->__m_owner == self) { + mutex->__m_count++; + return 0; + } + __pthread_lock(&mutex->__m_lock, self); + mutex->__m_owner = self; + mutex->__m_count = 0; + return 0; + case PTHREAD_MUTEX_ERRORCHECK_NP: + self = thread_self(); + if (mutex->__m_owner == self) return EDEADLK; + res = __pthread_alt_timedlock(&mutex->__m_lock, self, abstime); + if (res != 0) + { + mutex->__m_owner = self; + return 0; + } + return ETIMEDOUT; + case PTHREAD_MUTEX_TIMED_NP: + /* Only this type supports timed out lock. */ + return (__pthread_alt_timedlock(&mutex->__m_lock, NULL, abstime) + ? 0 : ETIMEDOUT); + default: + return EINVAL; + } +} + +int attribute_hidden __pthread_mutex_unlock(pthread_mutex_t * mutex) +{ + switch (mutex->__m_kind) { + case PTHREAD_MUTEX_ADAPTIVE_NP: + __pthread_unlock(&mutex->__m_lock); + return 0; + case PTHREAD_MUTEX_RECURSIVE_NP: + if (mutex->__m_owner != thread_self()) + return EPERM; + if (mutex->__m_count > 0) { + mutex->__m_count--; + return 0; + } + mutex->__m_owner = NULL; + __pthread_unlock(&mutex->__m_lock); + return 0; + case PTHREAD_MUTEX_ERRORCHECK_NP: + if (mutex->__m_owner != thread_self() || mutex->__m_lock.__status == 0) + return EPERM; + mutex->__m_owner = NULL; + __pthread_alt_unlock(&mutex->__m_lock); + return 0; + case PTHREAD_MUTEX_TIMED_NP: + __pthread_alt_unlock(&mutex->__m_lock); + return 0; + default: + return EINVAL; + } +} +strong_alias (__pthread_mutex_unlock, pthread_mutex_unlock) + +int attribute_hidden __pthread_mutexattr_init(pthread_mutexattr_t *attr) +{ + attr->__mutexkind = PTHREAD_MUTEX_TIMED_NP; + return 0; +} +strong_alias(__pthread_mutexattr_init,pthread_mutexattr_init) + +int attribute_hidden __pthread_mutexattr_destroy(pthread_mutexattr_t *attr attribute_unused) +{ + return 0; +} +strong_alias(__pthread_mutexattr_destroy,pthread_mutexattr_destroy) + +int attribute_hidden __pthread_mutexattr_settype(pthread_mutexattr_t *attr, int kind) +{ + if (kind != PTHREAD_MUTEX_ADAPTIVE_NP + && kind != PTHREAD_MUTEX_RECURSIVE_NP + && kind != PTHREAD_MUTEX_ERRORCHECK_NP + && kind != PTHREAD_MUTEX_TIMED_NP) + return EINVAL; + attr->__mutexkind = kind; + return 0; +} +strong_alias(__pthread_mutexattr_settype,pthread_mutexattr_settype) +strong_alias (__pthread_mutexattr_settype, __pthread_mutexattr_setkind_np) +weak_alias (__pthread_mutexattr_setkind_np, pthread_mutexattr_setkind_np) + +int __pthread_mutexattr_gettype(const pthread_mutexattr_t *attr, int *kind) attribute_hidden; +int __pthread_mutexattr_gettype(const pthread_mutexattr_t *attr, int *kind) +{ + *kind = attr->__mutexkind; + return 0; +} +weak_alias (__pthread_mutexattr_gettype, pthread_mutexattr_gettype) +strong_alias (__pthread_mutexattr_gettype, __pthread_mutexattr_getkind_np) +weak_alias (__pthread_mutexattr_getkind_np, pthread_mutexattr_getkind_np) + +int __pthread_mutexattr_getpshared (const pthread_mutexattr_t *attr attribute_unused, + int *pshared) attribute_hidden; +int __pthread_mutexattr_getpshared (const pthread_mutexattr_t *attr attribute_unused, + int *pshared) +{ + *pshared = PTHREAD_PROCESS_PRIVATE; + return 0; +} +weak_alias (__pthread_mutexattr_getpshared, pthread_mutexattr_getpshared) + +int __pthread_mutexattr_setpshared (pthread_mutexattr_t *attr attribute_unused, int pshared) attribute_hidden; +int __pthread_mutexattr_setpshared (pthread_mutexattr_t *attr attribute_unused, int pshared) +{ + if (pshared != PTHREAD_PROCESS_PRIVATE && pshared != PTHREAD_PROCESS_SHARED) + return EINVAL; + + /* For now it is not possible to shared a conditional variable. */ + if (pshared != PTHREAD_PROCESS_PRIVATE) + return ENOSYS; + + return 0; +} +weak_alias (__pthread_mutexattr_setpshared, pthread_mutexattr_setpshared) + +/* Once-only execution */ + +static pthread_mutex_t once_masterlock = PTHREAD_MUTEX_INITIALIZER; +static pthread_cond_t once_finished = PTHREAD_COND_INITIALIZER; +static int fork_generation = 0; /* Child process increments this after fork. */ + +enum { NEVER = 0, IN_PROGRESS = 1, DONE = 2 }; + +/* If a thread is canceled while calling the init_routine out of + pthread once, this handler will reset the once_control variable + to the NEVER state. */ + +static void pthread_once_cancelhandler(void *arg) +{ + pthread_once_t *once_control = arg; + + __pthread_mutex_lock(&once_masterlock); + *once_control = NEVER; + __pthread_mutex_unlock(&once_masterlock); + pthread_cond_broadcast(&once_finished); +} + +int __pthread_once(pthread_once_t * once_control, void (*init_routine)(void)) +{ + /* flag for doing the condition broadcast outside of mutex */ + int state_changed; + + /* Test without locking first for speed */ + if (*once_control == DONE) { + READ_MEMORY_BARRIER(); + return 0; + } + /* Lock and test again */ + + state_changed = 0; + + __pthread_mutex_lock(&once_masterlock); + + /* If this object was left in an IN_PROGRESS state in a parent + process (indicated by stale generation field), reset it to NEVER. */ + if ((*once_control & 3) == IN_PROGRESS && (*once_control & ~3) != fork_generation) + *once_control = NEVER; + + /* If init_routine is being called from another routine, wait until + it completes. */ + while ((*once_control & 3) == IN_PROGRESS) { + pthread_cond_wait(&once_finished, &once_masterlock); + } + /* Here *once_control is stable and either NEVER or DONE. */ + if (*once_control == NEVER) { + *once_control = IN_PROGRESS | fork_generation; + __pthread_mutex_unlock(&once_masterlock); + pthread_cleanup_push(pthread_once_cancelhandler, once_control); + init_routine(); + pthread_cleanup_pop(0); + __pthread_mutex_lock(&once_masterlock); + WRITE_MEMORY_BARRIER(); + *once_control = DONE; + state_changed = 1; + } + __pthread_mutex_unlock(&once_masterlock); + + if (state_changed) + pthread_cond_broadcast(&once_finished); + + return 0; +} +strong_alias (__pthread_once, pthread_once) + +/* + * Handle the state of the pthread_once mechanism across forks. The + * once_masterlock is acquired in the parent process prior to a fork to ensure + * that no thread is in the critical region protected by the lock. After the + * fork, the lock is released. In the child, the lock and the condition + * variable are simply reset. The child also increments its generation + * counter which lets pthread_once calls detect stale IN_PROGRESS states + * and reset them back to NEVER. + */ + +void __pthread_once_fork_prepare(void); +void __pthread_once_fork_prepare(void) +{ + __pthread_mutex_lock(&once_masterlock); +} + +void __pthread_once_fork_parent(void); +void __pthread_once_fork_parent(void) +{ + __pthread_mutex_unlock(&once_masterlock); +} + +void __pthread_once_fork_child(void); +void __pthread_once_fork_child(void) +{ + __pthread_mutex_init(&once_masterlock, NULL); + pthread_cond_init(&once_finished, NULL); + if (fork_generation <= INT_MAX - 4) + fork_generation += 4; /* leave least significant two bits zero */ + else + fork_generation = 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/oldsemaphore.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/oldsemaphore.c new file mode 100644 index 00000000..2a7b40ac --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/oldsemaphore.c @@ -0,0 +1,241 @@ +/* + * This file contains the old semaphore code that we need to + * preserve for glibc-2.0 backwards compatibility. Port to glibc 2.1 + * done by Cristian Gafton. + */ + +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +/* Semaphores a la POSIX 1003.1b */ + +#include +#include "pthread.h" +#include "internals.h" +#include "spinlock.h" +#include "restart.h" +#include "queue.h" + +typedef struct { + long int sem_status; + int sem_spinlock; +} old_sem_t; + +/* Maximum value the semaphore can have. */ +#define SEM_VALUE_MAX ((int) ((~0u) >> 1)) + +static __inline__ int sem_compare_and_swap(old_sem_t *sem, long oldval, long newval) +{ + return compare_and_swap(&sem->sem_status, oldval, newval, &sem->sem_spinlock); +} + +/* The state of a semaphore is represented by a long int encoding + either the semaphore count if >= 0 and no thread is waiting on it, + or the head of the list of threads waiting for the semaphore. + To distinguish the two cases, we encode the semaphore count N + as 2N+1, so that it has the lowest bit set. + + A sequence of sem_wait operations on a semaphore initialized to N + result in the following successive states: + 2N+1, 2N-1, ..., 3, 1, &first_waiting_thread, &second_waiting_thread, ... +*/ + +static void sem_restart_list(pthread_descr waiting); + +int __old_sem_init(old_sem_t *sem, int pshared, unsigned int value); +int __old_sem_init(old_sem_t *sem, int pshared, unsigned int value) +{ + if (value > SEM_VALUE_MAX) { + errno = EINVAL; + return -1; + } + if (pshared) { + errno = ENOSYS; + return -1; + } + sem->sem_spinlock = 0; + sem->sem_status = ((long)value << 1) + 1; + return 0; +} + +/* Function called by pthread_cancel to remove the thread from + waiting inside __old_sem_wait. Here we simply unconditionally + indicate that the thread is to be woken, by returning 1. */ + +static int old_sem_extricate_func(void *obj attribute_unused, pthread_descr th attribute_unused) +{ + return 1; +} + +int __old_sem_wait(old_sem_t * sem); +int __old_sem_wait(old_sem_t * sem) +{ + long oldstatus, newstatus; + volatile pthread_descr self = thread_self(); + pthread_descr * th; + pthread_extricate_if extr; + + /* Set up extrication interface */ + extr.pu_object = 0; + extr.pu_extricate_func = old_sem_extricate_func; + + while (1) { + /* Register extrication interface */ + __pthread_set_own_extricate_if(self, &extr); + do { + oldstatus = sem->sem_status; + if ((oldstatus & 1) && (oldstatus != 1)) + newstatus = oldstatus - 2; + else { + newstatus = (long) self; + self->p_nextwaiting = (pthread_descr) oldstatus; + } + } + while (! sem_compare_and_swap(sem, oldstatus, newstatus)); + if (newstatus & 1) { + /* We got the semaphore. */ + __pthread_set_own_extricate_if(self, 0); + return 0; + } + /* Wait for sem_post or cancellation */ + suspend(self); + __pthread_set_own_extricate_if(self, 0); + + /* This is a cancellation point */ + if (self->p_canceled && self->p_cancelstate == PTHREAD_CANCEL_ENABLE) { + /* Remove ourselves from the waiting list if we're still on it */ + /* First check if we're at the head of the list. */ + do { + oldstatus = sem->sem_status; + if (oldstatus != (long) self) break; + newstatus = (long) self->p_nextwaiting; + } + while (! sem_compare_and_swap(sem, oldstatus, newstatus)); + /* Now, check if we're somewhere in the list. + There's a race condition with sem_post here, but it does not matter: + the net result is that at the time pthread_exit is called, + self is no longer reachable from sem->sem_status. */ + if (oldstatus != (long) self && (oldstatus & 1) == 0) { + for (th = &(((pthread_descr) oldstatus)->p_nextwaiting); + *th != NULL && *th != (pthread_descr) 1; + th = &((*th)->p_nextwaiting)) { + if (*th == self) { + *th = self->p_nextwaiting; + break; + } + } + } + __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); + } + } +} + +int __old_sem_trywait(old_sem_t * sem); +int __old_sem_trywait(old_sem_t * sem) +{ + long oldstatus, newstatus; + + do { + oldstatus = sem->sem_status; + if ((oldstatus & 1) == 0 || (oldstatus == 1)) { + errno = EAGAIN; + return -1; + } + newstatus = oldstatus - 2; + } + while (! sem_compare_and_swap(sem, oldstatus, newstatus)); + return 0; +} + +int __old_sem_post(old_sem_t * sem); +int __old_sem_post(old_sem_t * sem) +{ + long oldstatus, newstatus; + + do { + oldstatus = sem->sem_status; + if ((oldstatus & 1) == 0) + newstatus = 3; + else { + if (oldstatus >= SEM_VALUE_MAX) { + /* Overflow */ + errno = ERANGE; + return -1; + } + newstatus = oldstatus + 2; + } + } + while (! sem_compare_and_swap(sem, oldstatus, newstatus)); + if ((oldstatus & 1) == 0) + sem_restart_list((pthread_descr) oldstatus); + return 0; +} + +int __old_sem_getvalue(old_sem_t * sem, int * sval); +int __old_sem_getvalue(old_sem_t * sem, int * sval) +{ + long status = sem->sem_status; + if (status & 1) + *sval = (int)((unsigned long) status >> 1); + else + *sval = 0; + return 0; +} + +int __old_sem_destroy(old_sem_t * sem); +int __old_sem_destroy(old_sem_t * sem) +{ + if ((sem->sem_status & 1) == 0) { + errno = EBUSY; + return -1; + } + return 0; +} + +/* Auxiliary function for restarting all threads on a waiting list, + in priority order. */ + +static void sem_restart_list(pthread_descr waiting) +{ + pthread_descr th, towake, *p; + + /* Sort list of waiting threads by decreasing priority (insertion sort) */ + towake = NULL; + while (waiting != (pthread_descr) 1) { + th = waiting; + waiting = waiting->p_nextwaiting; + p = &towake; + while (*p != NULL && th->p_priority < (*p)->p_priority) + p = &((*p)->p_nextwaiting); + th->p_nextwaiting = *p; + *p = th; + } + /* Wake up threads in priority order */ + while (towake != NULL) { + th = towake; + towake = towake->p_nextwaiting; + th->p_nextwaiting = NULL; + restart(th); + } +} + +#if defined __PIC__ && defined DO_VERSIONING +symbol_version (__old_sem_init, sem_init, GLIBC_2.0); +symbol_version (__old_sem_wait, sem_wait, GLIBC_2.0); +symbol_version (__old_sem_trywait, sem_trywait, GLIBC_2.0); +symbol_version (__old_sem_post, sem_post, GLIBC_2.0); +symbol_version (__old_sem_getvalue, sem_getvalue, GLIBC_2.0); +symbol_version (__old_sem_destroy, sem_destroy, GLIBC_2.0); +#endif + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/pt-machine.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/pt-machine.c new file mode 100644 index 00000000..438008d5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/pt-machine.c @@ -0,0 +1,22 @@ +/* "Instantiation of machine-dependent pthreads inline functions. + Copyright (C) 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#define PT_EI + +#include diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/ptfork.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/ptfork.c new file mode 100644 index 00000000..47a567d2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/ptfork.c @@ -0,0 +1,174 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +/* mods for uClibc: removed strong alias and defined funcs properly */ + +/* The "atfork" stuff */ + +#include + +#ifdef __ARCH_USE_MMU__ + +#include +#include +#include +#include +#include "pthread.h" +#include "internals.h" + +struct handler_list { + void (*handler)(void); + struct handler_list * next; +}; + +static pthread_mutex_t pthread_atfork_lock = PTHREAD_MUTEX_INITIALIZER; +static struct handler_list * pthread_atfork_prepare = NULL; +static struct handler_list * pthread_atfork_parent = NULL; +static struct handler_list * pthread_atfork_child = NULL; + +#ifdef __MALLOC__ +__UCLIBC_MUTEX_EXTERN(__malloc_heap_lock); +__UCLIBC_MUTEX_EXTERN(__malloc_sbrk_lock); +#ifdef __UCLIBC_UCLINUX_BROKEN_MUNMAP__ +__UCLIBC_MUTEX_EXTERN(__malloc_mmb_heap_lock); +#endif +#elif defined(__MALLOC_STANDARD__) || defined(__MALLOC_SIMPLE__) +__UCLIBC_MUTEX_EXTERN(__malloc_lock); +#endif + +static void pthread_insert_list(struct handler_list ** list, + void (*handler)(void), + struct handler_list * newlist, + int at_end) +{ + if (handler == NULL) return; + if (at_end) { + while(*list != NULL) list = &((*list)->next); + } + newlist->handler = handler; + newlist->next = *list; + *list = newlist; +} + +struct handler_list_block { + struct handler_list prepare, parent, child; +}; + +int pthread_atfork(void (*prepare)(void), + void (*parent)(void), + void (*child)(void)) +{ + struct handler_list_block * block = + (struct handler_list_block *) malloc(sizeof(struct handler_list_block)); + if (block == NULL) return ENOMEM; + __pthread_mutex_lock(&pthread_atfork_lock); + /* "prepare" handlers are called in LIFO */ + pthread_insert_list(&pthread_atfork_prepare, prepare, &block->prepare, 0); + /* "parent" handlers are called in FIFO */ + pthread_insert_list(&pthread_atfork_parent, parent, &block->parent, 1); + /* "child" handlers are called in FIFO */ + pthread_insert_list(&pthread_atfork_child, child, &block->child, 1); + __pthread_mutex_unlock(&pthread_atfork_lock); + return 0; +} +/*strong_alias (__pthread_atfork, pthread_atfork)*/ + +static __inline__ void pthread_call_handlers(struct handler_list * list) +{ + for (/*nothing*/; list != NULL; list = list->next) (list->handler)(); +} + +void __pthread_once_fork_prepare(void); +void __pthread_once_fork_child(void); +void __pthread_once_fork_parent(void); + +extern __typeof(fork) __libc_fork; + +pid_t __fork(void) attribute_hidden; +pid_t __fork(void) +{ + pid_t pid; + struct handler_list * prepare, * child, * parent; + + __pthread_mutex_lock(&pthread_atfork_lock); + prepare = pthread_atfork_prepare; + child = pthread_atfork_child; + parent = pthread_atfork_parent; + pthread_call_handlers(prepare); + + __pthread_once_fork_prepare(); +#ifdef __MALLOC__ + __pthread_mutex_lock(&__malloc_sbrk_lock); + __pthread_mutex_lock(&__malloc_heap_lock); +#ifdef __UCLIBC_UCLINUX_BROKEN_MUNMAP__ + __pthread_mutex_lock(&__malloc_mmb_heap_lock); +#endif +#elif defined(__MALLOC_STANDARD__) || defined(__MALLOC_SIMPLE__) + __pthread_mutex_lock(&__malloc_lock); +#endif + + pid = __libc_fork(); + if (pid == 0) { +#if defined(__MALLOC_STANDARD__) || defined(__MALLOC_SIMPLE__) + __libc_lock_init_recursive(__malloc_lock); +#elif defined(__MALLOC__) +#ifdef __UCLIBC_UCLINUX_BROKEN_MUNMAP__ + __libc_lock_init_adaptive(__malloc_mmb_heap_lock); +#endif + __libc_lock_init_adaptive(__malloc_heap_lock); + __libc_lock_init(__malloc_sbrk_lock); +#endif + __libc_lock_init_adaptive(pthread_atfork_lock); + __pthread_reset_main_thread(); + __fresetlockfiles(); + __pthread_once_fork_child(); + pthread_call_handlers(child); + } else { +#if defined(__MALLOC_STANDARD__) || defined(__MALLOC_SIMPLE__) + __pthread_mutex_unlock(&__malloc_lock); +#elif defined(__MALLOC__) +#ifdef __UCLIBC_UCLINUX_BROKEN_MUNMAP__ + __pthread_mutex_unlock(&__malloc_mmb_heap_lock); +#endif + __pthread_mutex_unlock(&__malloc_heap_lock); + __pthread_mutex_unlock(&__malloc_sbrk_lock); +#endif + __pthread_mutex_unlock(&pthread_atfork_lock); + __pthread_once_fork_parent(); + pthread_call_handlers(parent); + } + return pid; +} +strong_alias(__fork,fork) + +pid_t vfork(void) +{ + return __fork(); +} + +#else + +/* We can't support pthread_atfork without MMU, since we don't have + fork(), and we can't offer the correct semantics for vfork(). */ +int pthread_atfork(void (*prepare)(void), + void (*parent)(void), + void (*child)(void)) +{ + /* ENOMEM is probably pushing it a little bit. + Take it as `no *virtual* memory' :-) */ + errno = ENOMEM; + return -1; +} + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/pthread.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/pthread.c new file mode 100644 index 00000000..ad392e34 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/pthread.c @@ -0,0 +1,1162 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +/* Thread creation, initialization, and basic low-level routines */ + +#define __FORCE_GLIBC +#include +#include +#include /* for h_errno */ +#include +#include +#include +#include +#include +#include +#include +#include +#include "pthread.h" +#include "internals.h" +#include "spinlock.h" +#include "restart.h" +#include "debug.h" /* added to linuxthreads -StS */ + + +/* Mods for uClibc: Some includes */ +#include +#include +#include + +/* mods for uClibc: __libc_sigaction is not in any standard headers */ +extern __typeof(sigaction) __libc_sigaction; +libpthread_hidden_proto(waitpid) +libpthread_hidden_proto(raise) + +/* These variables are used by the setup code. */ +extern int _errno; +extern int _h_errno; + + +/* Descriptor of the initial thread */ + +struct _pthread_descr_struct __pthread_initial_thread = { + &__pthread_initial_thread, /* pthread_descr p_nextlive */ + &__pthread_initial_thread, /* pthread_descr p_prevlive */ + NULL, /* pthread_descr p_nextwaiting */ + NULL, /* pthread_descr p_nextlock */ + PTHREAD_THREADS_MAX, /* pthread_t p_tid */ + 0, /* int p_pid */ + 0, /* int p_priority */ + &__pthread_handles[0].h_lock, /* struct _pthread_fastlock * p_lock */ + 0, /* int p_signal */ + NULL, /* sigjmp_buf * p_signal_buf */ + NULL, /* sigjmp_buf * p_cancel_buf */ + 0, /* char p_terminated */ + 0, /* char p_detached */ + 0, /* char p_exited */ + NULL, /* void * p_retval */ + 0, /* int p_retval */ + NULL, /* pthread_descr p_joining */ + NULL, /* struct _pthread_cleanup_buffer * p_cleanup */ + 0, /* char p_cancelstate */ + 0, /* char p_canceltype */ + 0, /* char p_canceled */ + &_errno, /* int *p_errnop */ + 0, /* int p_errno */ + &_h_errno, /* int *p_h_errnop */ + 0, /* int p_h_errno */ + NULL, /* char * p_in_sighandler */ + 0, /* char p_sigwaiting */ + PTHREAD_START_ARGS_INITIALIZER, /* struct pthread_start_args p_start_args */ + {NULL}, /* void ** p_specific[PTHREAD_KEY_1STLEVEL_SIZE] */ + {NULL}, /* void * p_libc_specific[_LIBC_TSD_KEY_N] */ + 0, /* int p_userstack */ + NULL, /* void * p_guardaddr */ + 0, /* size_t p_guardsize */ + &__pthread_initial_thread, /* pthread_descr p_self */ + 0, /* Always index 0 */ + 0, /* int p_report_events */ + {{{0, }}, 0, NULL}, /* td_eventbuf_t p_eventbuf */ + __ATOMIC_INITIALIZER, /* struct pthread_atomic p_resume_count */ + 0, /* char p_woken_by_cancel */ + 0, /* char p_condvar_avail */ + 0, /* char p_sem_avail */ + NULL, /* struct pthread_extricate_if *p_extricate */ + NULL, /* pthread_readlock_info *p_readlock_list; */ + NULL, /* pthread_readlock_info *p_readlock_free; */ + 0 /* int p_untracked_readlock_count; */ +#ifdef __UCLIBC_HAS_XLOCALE__ + , + &__global_locale_data, /* __locale_t locale; */ +#endif /* __UCLIBC_HAS_XLOCALE__ */ +}; + +/* Descriptor of the manager thread; none of this is used but the error + variables, the p_pid and p_priority fields, + and the address for identification. */ +#define manager_thread (&__pthread_manager_thread) +struct _pthread_descr_struct __pthread_manager_thread = { + NULL, /* pthread_descr p_nextlive */ + NULL, /* pthread_descr p_prevlive */ + NULL, /* pthread_descr p_nextwaiting */ + NULL, /* pthread_descr p_nextlock */ + 0, /* int p_tid */ + 0, /* int p_pid */ + 0, /* int p_priority */ + &__pthread_handles[1].h_lock, /* struct _pthread_fastlock * p_lock */ + 0, /* int p_signal */ + NULL, /* sigjmp_buf * p_signal_buf */ + NULL, /* sigjmp_buf * p_cancel_buf */ + 0, /* char p_terminated */ + 0, /* char p_detached */ + 0, /* char p_exited */ + NULL, /* void * p_retval */ + 0, /* int p_retval */ + NULL, /* pthread_descr p_joining */ + NULL, /* struct _pthread_cleanup_buffer * p_cleanup */ + 0, /* char p_cancelstate */ + 0, /* char p_canceltype */ + 0, /* char p_canceled */ + &__pthread_manager_thread.p_errno, /* int *p_errnop */ + 0, /* int p_errno */ + NULL, /* int *p_h_errnop */ + 0, /* int p_h_errno */ + NULL, /* char * p_in_sighandler */ + 0, /* char p_sigwaiting */ + PTHREAD_START_ARGS_INITIALIZER, /* struct pthread_start_args p_start_args */ + {NULL}, /* void ** p_specific[PTHREAD_KEY_1STLEVEL_SIZE] */ + {NULL}, /* void * p_libc_specific[_LIBC_TSD_KEY_N] */ + 0, /* int p_userstack */ + NULL, /* void * p_guardaddr */ + 0, /* size_t p_guardsize */ + &__pthread_manager_thread, /* pthread_descr p_self */ + 1, /* Always index 1 */ + 0, /* int p_report_events */ + {{{0, }}, 0, NULL}, /* td_eventbuf_t p_eventbuf */ + __ATOMIC_INITIALIZER, /* struct pthread_atomic p_resume_count */ + 0, /* char p_woken_by_cancel */ + 0, /* char p_condvar_avail */ + 0, /* char p_sem_avail */ + NULL, /* struct pthread_extricate_if *p_extricate */ + NULL, /* pthread_readlock_info *p_readlock_list; */ + NULL, /* pthread_readlock_info *p_readlock_free; */ + 0 /* int p_untracked_readlock_count; */ +#ifdef __UCLIBC_HAS_XLOCALE__ + , + &__global_locale_data, /* __locale_t locale; */ +#endif /* __UCLIBC_HAS_XLOCALE__ */ +}; + +/* Pointer to the main thread (the father of the thread manager thread) */ +/* Originally, this is the initial thread, but this changes after fork() */ + +pthread_descr __pthread_main_thread = &__pthread_initial_thread; + +/* Limit between the stack of the initial thread (above) and the + stacks of other threads (below). Aligned on a STACK_SIZE boundary. */ + +char *__pthread_initial_thread_bos = NULL; + +/* For non-MMU systems also remember to stack top of the initial thread. + * This is adapted when other stacks are malloc'ed since we don't know + * the bounds a-priori. -StS */ + +#ifndef __ARCH_USE_MMU__ +char *__pthread_initial_thread_tos = NULL; +#endif /* __ARCH_USE_MMU__ */ + +/* File descriptor for sending requests to the thread manager. */ +/* Initially -1, meaning that the thread manager is not running. */ + +int __pthread_manager_request = -1; + +/* Other end of the pipe for sending requests to the thread manager. */ + +int __pthread_manager_reader; + +/* Limits of the thread manager stack */ + +char *__pthread_manager_thread_bos = NULL; +char *__pthread_manager_thread_tos = NULL; + +/* For process-wide exit() */ + +int __pthread_exit_requested = 0; +int __pthread_exit_code = 0; + +/* Communicate relevant LinuxThreads constants to gdb */ + +const int __pthread_threads_max = PTHREAD_THREADS_MAX; +const int __pthread_sizeof_handle = sizeof(struct pthread_handle_struct); +const int __pthread_offsetof_descr = offsetof(struct pthread_handle_struct, h_descr); +const int __pthread_offsetof_pid = offsetof(struct _pthread_descr_struct, + p_pid); +const int __linuxthreads_pthread_sizeof_descr + = sizeof(struct _pthread_descr_struct); + +const int __linuxthreads_initial_report_events; + +const char __linuxthreads_version[] = VERSION; + +/* Forward declarations */ +static void pthread_onexit_process(int retcode, void *arg); +static void pthread_handle_sigcancel(int sig); +static void pthread_handle_sigrestart(int sig); +static void pthread_handle_sigdebug(int sig); +int __pthread_timedsuspend_new(pthread_descr self, const struct timespec *abstime); + +/* Signal numbers used for the communication. + In these variables we keep track of the used variables. If the + platform does not support any real-time signals we will define the + values to some unreasonable value which will signal failing of all + the functions below. */ +#ifndef __NR_rt_sigaction +static int current_rtmin = -1; +static int current_rtmax = -1; +int __pthread_sig_restart = SIGUSR1; +int __pthread_sig_cancel = SIGUSR2; +int __pthread_sig_debug; +#else + +#if __SIGRTMAX - __SIGRTMIN >= 3 +static int current_rtmin = __SIGRTMIN + 3; +static int current_rtmax = __SIGRTMAX; +int __pthread_sig_restart = __SIGRTMIN; +int __pthread_sig_cancel = __SIGRTMIN + 1; +int __pthread_sig_debug = __SIGRTMIN + 2; +void (*__pthread_restart)(pthread_descr) = __pthread_restart_new; +void (*__pthread_suspend)(pthread_descr) = __pthread_wait_for_restart_signal; +int (*__pthread_timedsuspend)(pthread_descr, const struct timespec *) = __pthread_timedsuspend_new; +#else +static int current_rtmin = __SIGRTMIN; +static int current_rtmax = __SIGRTMAX; +int __pthread_sig_restart = SIGUSR1; +int __pthread_sig_cancel = SIGUSR2; +int __pthread_sig_debug; +void (*__pthread_restart)(pthread_descr) = __pthread_restart_old; +void (*__pthread_suspend)(pthread_descr) = __pthread_suspend_old; +int (*__pthread_timedsuspend)(pthread_descr, const struct timespec *) = __pthread_timedsuspend_old; + +#endif + +/* Return number of available real-time signal with highest priority. */ +int __libc_current_sigrtmin (void) +{ + return current_rtmin; +} + +/* Return number of available real-time signal with lowest priority. */ +int __libc_current_sigrtmax (void) +{ + return current_rtmax; +} + +/* Allocate real-time signal with highest/lowest available + priority. Please note that we don't use a lock since we assume + this function to be called at program start. */ +int __libc_allocate_rtsig (int high); +int __libc_allocate_rtsig (int high) +{ + if (current_rtmin == -1 || current_rtmin > current_rtmax) + /* We don't have anymore signal available. */ + return -1; + return high ? current_rtmin++ : current_rtmax--; +} +#endif + +/* Initialize the pthread library. + Initialization is split in two functions: + - a constructor function that blocks the __pthread_sig_restart signal + (must do this very early, since the program could capture the signal + mask with e.g. sigsetjmp before creating the first thread); + - a regular function called from pthread_create when needed. */ + +static void pthread_initialize(void) __attribute__((constructor)); + +libpthread_hidden_proto(pthread_attr_destroy) +libpthread_hidden_proto(pthread_attr_init) +libpthread_hidden_proto(pthread_attr_getdetachstate) +libpthread_hidden_proto(pthread_attr_setdetachstate) +libpthread_hidden_proto(pthread_attr_getinheritsched) +libpthread_hidden_proto(pthread_attr_setinheritsched) +libpthread_hidden_proto(pthread_attr_setschedparam) +libpthread_hidden_proto(pthread_attr_getschedparam) +libpthread_hidden_proto(pthread_attr_getschedpolicy) +libpthread_hidden_proto(pthread_attr_setschedpolicy) +libpthread_hidden_proto(pthread_attr_getscope) +libpthread_hidden_proto(pthread_attr_setscope) + +libpthread_hidden_proto(pthread_exit) + +libpthread_hidden_proto(pthread_equal) +libpthread_hidden_proto(pthread_self) +libpthread_hidden_proto(pthread_getschedparam) +libpthread_hidden_proto(pthread_setschedparam) + +libpthread_hidden_proto(pthread_setcancelstate) +libpthread_hidden_proto(pthread_setcanceltype) +libpthread_hidden_proto(_pthread_cleanup_push_defer) +libpthread_hidden_proto(_pthread_cleanup_pop_restore) + +libpthread_hidden_proto(pthread_cond_broadcast) +libpthread_hidden_proto(pthread_cond_destroy) +libpthread_hidden_proto(pthread_cond_init) +libpthread_hidden_proto(pthread_cond_signal) +libpthread_hidden_proto(pthread_cond_wait) +libpthread_hidden_proto(pthread_cond_timedwait) + +libpthread_hidden_proto(pthread_condattr_destroy) +libpthread_hidden_proto(pthread_condattr_init) + +struct pthread_functions __pthread_functions = + { +#ifndef USE___THREAD + .ptr_pthread_internal_tsd_set = __pthread_internal_tsd_set, + .ptr_pthread_internal_tsd_get = __pthread_internal_tsd_get, + .ptr_pthread_internal_tsd_address = __pthread_internal_tsd_address, +#endif +/* + .ptr_pthread_fork = __pthread_fork, +*/ + .ptr_pthread_attr_destroy = pthread_attr_destroy, + .ptr_pthread_attr_init = pthread_attr_init, + .ptr_pthread_attr_getdetachstate = pthread_attr_getdetachstate, + .ptr_pthread_attr_setdetachstate = pthread_attr_setdetachstate, + .ptr_pthread_attr_getinheritsched = pthread_attr_getinheritsched, + .ptr_pthread_attr_setinheritsched = pthread_attr_setinheritsched, + .ptr_pthread_attr_getschedparam = pthread_attr_getschedparam, + .ptr_pthread_attr_setschedparam = pthread_attr_setschedparam, + .ptr_pthread_attr_getschedpolicy = pthread_attr_getschedpolicy, + .ptr_pthread_attr_setschedpolicy = pthread_attr_setschedpolicy, + .ptr_pthread_attr_getscope = pthread_attr_getscope, + .ptr_pthread_attr_setscope = pthread_attr_setscope, + .ptr_pthread_condattr_destroy = pthread_condattr_destroy, + .ptr_pthread_condattr_init = pthread_condattr_init, + .ptr_pthread_cond_broadcast = pthread_cond_broadcast, + .ptr_pthread_cond_destroy = pthread_cond_destroy, + .ptr_pthread_cond_init = pthread_cond_init, + .ptr_pthread_cond_signal = pthread_cond_signal, + .ptr_pthread_cond_wait = pthread_cond_wait, + .ptr_pthread_cond_timedwait = pthread_cond_timedwait, + .ptr_pthread_equal = pthread_equal, + .ptr___pthread_exit = pthread_exit, + .ptr_pthread_getschedparam = pthread_getschedparam, + .ptr_pthread_setschedparam = pthread_setschedparam, + .ptr_pthread_mutex_destroy = __pthread_mutex_destroy, + .ptr_pthread_mutex_init = __pthread_mutex_init, + .ptr_pthread_mutex_lock = __pthread_mutex_lock, + .ptr_pthread_mutex_trylock = __pthread_mutex_trylock, + .ptr_pthread_mutex_unlock = __pthread_mutex_unlock, + .ptr_pthread_self = pthread_self, + .ptr_pthread_setcancelstate = pthread_setcancelstate, + .ptr_pthread_setcanceltype = pthread_setcanceltype, +/* + .ptr_pthread_do_exit = pthread_do_exit, + .ptr_pthread_thread_self = pthread_thread_self, + .ptr_pthread_cleanup_upto = pthread_cleanup_upto, + .ptr_pthread_sigaction = pthread_sigaction, + .ptr_pthread_sigwait = pthread_sigwait, + .ptr_pthread_raise = pthread_raise, + .ptr__pthread_cleanup_push = _pthread_cleanup_push, + .ptr__pthread_cleanup_pop = _pthread_cleanup_pop +*/ + .ptr__pthread_cleanup_push_defer = __pthread_cleanup_push_defer, + .ptr__pthread_cleanup_pop_restore = __pthread_cleanup_pop_restore, + }; +#ifdef SHARED +# define ptr_pthread_functions &__pthread_functions +#else +# define ptr_pthread_functions NULL +#endif + +static int *__libc_multiple_threads_ptr; + + /* Do some minimal initialization which has to be done during the + startup of the C library. */ +void __pthread_initialize_minimal(void) +{ + /* If we have special thread_self processing, initialize + * that for the main thread now. */ +#ifdef INIT_THREAD_SELF + INIT_THREAD_SELF(&__pthread_initial_thread, 0); +#endif + + __libc_multiple_threads_ptr = __libc_pthread_init (ptr_pthread_functions); +} + + +static void pthread_initialize(void) +{ + struct sigaction sa; + sigset_t mask; +#ifdef __ARCH_USE_MMU__ + struct rlimit limit; + rlim_t max_stack; +#endif + + /* If already done (e.g. by a constructor called earlier!), bail out */ + if (__pthread_initial_thread_bos != NULL) return; +#ifdef TEST_FOR_COMPARE_AND_SWAP + /* Test if compare-and-swap is available */ + __pthread_has_cas = compare_and_swap_is_available(); +#endif + /* For the initial stack, reserve at least STACK_SIZE bytes of stack + below the current stack address, and align that on a + STACK_SIZE boundary. */ + __pthread_initial_thread_bos = + (char *)(((long)CURRENT_STACK_FRAME - 2 * STACK_SIZE) & ~(STACK_SIZE - 1)); + /* Update the descriptor for the initial thread. */ + __pthread_initial_thread.p_pid = getpid(); + /* If we have special thread_self processing, initialize that for the + main thread now. */ +#ifdef INIT_THREAD_SELF + INIT_THREAD_SELF(&__pthread_initial_thread, 0); +#endif + /* The errno/h_errno variable of the main thread are the global ones. */ + __pthread_initial_thread.p_errnop = &_errno; + __pthread_initial_thread.p_h_errnop = &_h_errno; + +#ifdef __UCLIBC_HAS_XLOCALE__ + /* The locale of the main thread is the current locale in use. */ + __pthread_initial_thread.locale = __curlocale_var; +#endif /* __UCLIBC_HAS_XLOCALE__ */ + + { /* uClibc-specific stdio initialization for threads. */ + FILE *fp; + + _stdio_user_locking = 0; /* 2 if threading not initialized */ + for (fp = _stdio_openlist; fp != NULL; fp = fp->__nextopen) { + if (fp->__user_locking != 1) { + fp->__user_locking = 0; + } + } + } + + /* Play with the stack size limit to make sure that no stack ever grows + beyond STACK_SIZE minus two pages (one page for the thread descriptor + immediately beyond, and one page to act as a guard page). */ + +#ifdef __ARCH_USE_MMU__ + /* We cannot allocate a huge chunk of memory to mmap all thread stacks later + * on a non-MMU system. Thus, we don't need the rlimit either. -StS */ + getrlimit(RLIMIT_STACK, &limit); + max_stack = STACK_SIZE - 2 * getpagesize(); + if (limit.rlim_cur > max_stack) { + limit.rlim_cur = max_stack; + setrlimit(RLIMIT_STACK, &limit); + } +#else + /* For non-MMU assume __pthread_initial_thread_tos at upper page boundary, and + * __pthread_initial_thread_bos at address 0. These bounds are refined as we + * malloc other stack frames such that they don't overlap. -StS + */ + __pthread_initial_thread_tos = + (char *)(((long)CURRENT_STACK_FRAME + getpagesize()) & ~(getpagesize() - 1)); + __pthread_initial_thread_bos = (char *) 1; /* set it non-zero so we know we have been here */ + PDEBUG("initial thread stack bounds: bos=%p, tos=%p\n", + __pthread_initial_thread_bos, __pthread_initial_thread_tos); +#endif /* __ARCH_USE_MMU__ */ + + /* Setup signal handlers for the initial thread. + Since signal handlers are shared between threads, these settings + will be inherited by all other threads. */ + memset(&sa, 0, sizeof(sa)); + sa.sa_handler = pthread_handle_sigrestart; + __libc_sigaction(__pthread_sig_restart, &sa, NULL); + sa.sa_handler = pthread_handle_sigcancel; + sigaddset(&sa.sa_mask, __pthread_sig_restart); + __libc_sigaction(__pthread_sig_cancel, &sa, NULL); + if (__pthread_sig_debug > 0) { + sa.sa_handler = pthread_handle_sigdebug; + __sigemptyset(&sa.sa_mask); + __libc_sigaction(__pthread_sig_debug, &sa, NULL); + } + /* Initially, block __pthread_sig_restart. Will be unblocked on demand. */ + __sigemptyset(&mask); + sigaddset(&mask, __pthread_sig_restart); + sigprocmask(SIG_BLOCK, &mask, NULL); + /* And unblock __pthread_sig_cancel if it has been blocked. */ + sigdelset(&mask, __pthread_sig_restart); + sigaddset(&mask, __pthread_sig_cancel); + sigprocmask(SIG_UNBLOCK, &mask, NULL); + /* Register an exit function to kill all other threads. */ + /* Do it early so that user-registered atexit functions are called + before pthread_onexit_process. */ + on_exit(pthread_onexit_process, NULL); +} + +void __pthread_initialize(void); +void __pthread_initialize(void) +{ + pthread_initialize(); +} + +int __pthread_initialize_manager(void) +{ + int manager_pipe[2]; + int pid; + int report_events; + struct pthread_request request; + + *__libc_multiple_threads_ptr = 1; + + /* If basic initialization not done yet (e.g. we're called from a + constructor run before our constructor), do it now */ + if (__pthread_initial_thread_bos == NULL) pthread_initialize(); + /* Setup stack for thread manager */ + __pthread_manager_thread_bos = malloc(THREAD_MANAGER_STACK_SIZE); + if (__pthread_manager_thread_bos == NULL) return -1; + __pthread_manager_thread_tos = + __pthread_manager_thread_bos + THREAD_MANAGER_STACK_SIZE; + + /* On non-MMU systems we make sure that the initial thread bounds don't overlap + * with the manager stack frame */ + NOMMU_INITIAL_THREAD_BOUNDS(__pthread_manager_thread_tos,__pthread_manager_thread_bos); + PDEBUG("manager stack: size=%d, bos=%p, tos=%p\n", THREAD_MANAGER_STACK_SIZE, + __pthread_manager_thread_bos, __pthread_manager_thread_tos); +#if 0 + PDEBUG("initial stack: estimate bos=%p, tos=%p\n", + __pthread_initial_thread_bos, __pthread_initial_thread_tos); +#endif + + /* Setup pipe to communicate with thread manager */ + if (pipe(manager_pipe) == -1) { + free(__pthread_manager_thread_bos); + return -1; + } + /* Start the thread manager */ + pid = 0; +#if defined(USE_TLS) && USE_TLS + if (__linuxthreads_initial_report_events != 0) + THREAD_SETMEM (((pthread_descr) NULL), p_report_events, + __linuxthreads_initial_report_events); + report_events = THREAD_GETMEM (((pthread_descr) NULL), p_report_events); +#else + if (__linuxthreads_initial_report_events != 0) + __pthread_initial_thread.p_report_events + = __linuxthreads_initial_report_events; + report_events = __pthread_initial_thread.p_report_events; +#endif + if (__builtin_expect (report_events, 0)) + { + /* It's a bit more complicated. We have to report the creation of + the manager thread. */ + int idx = __td_eventword (TD_CREATE); + uint32_t mask = __td_eventmask (TD_CREATE); + + if ((mask & (__pthread_threads_events.event_bits[idx] + | __pthread_initial_thread.p_eventbuf.eventmask.event_bits[idx])) + != 0) + { + + __pthread_lock(__pthread_manager_thread.p_lock, NULL); + +#ifdef __ia64__ + pid = __clone2(__pthread_manager_event, + (void **) __pthread_manager_thread_tos, + THREAD_MANAGER_STACK_SIZE, + CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND, + (void *)(long)manager_pipe[0]); +#else + pid = clone(__pthread_manager_event, + (void **) __pthread_manager_thread_tos, + CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND, + (void *)(long)manager_pipe[0]); +#endif + + if (pid != -1) + { + /* Now fill in the information about the new thread in + the newly created thread's data structure. We cannot let + the new thread do this since we don't know whether it was + already scheduled when we send the event. */ + __pthread_manager_thread.p_eventbuf.eventdata = + &__pthread_manager_thread; + __pthread_manager_thread.p_eventbuf.eventnum = TD_CREATE; + __pthread_last_event = &__pthread_manager_thread; + __pthread_manager_thread.p_tid = 2* PTHREAD_THREADS_MAX + 1; + __pthread_manager_thread.p_pid = pid; + + /* Now call the function which signals the event. */ + __linuxthreads_create_event (); + } + /* Now restart the thread. */ + __pthread_unlock(__pthread_manager_thread.p_lock); + } + } + + if (pid == 0) { +#ifdef __ia64__ + pid = __clone2(__pthread_manager, (void **) __pthread_manager_thread_tos, + THREAD_MANAGER_STACK_SIZE, + CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND, + (void *)(long)manager_pipe[0]); +#else + pid = clone(__pthread_manager, (void **) __pthread_manager_thread_tos, + CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND, + (void *)(long)manager_pipe[0]); +#endif + } + if (pid == -1) { + free(__pthread_manager_thread_bos); + close(manager_pipe[0]); + close(manager_pipe[1]); + return -1; + } + __pthread_manager_request = manager_pipe[1]; /* writing end */ + __pthread_manager_reader = manager_pipe[0]; /* reading end */ + __pthread_manager_thread.p_tid = 2* PTHREAD_THREADS_MAX + 1; + __pthread_manager_thread.p_pid = pid; + + /* Make gdb aware of new thread manager */ + if (__pthread_threads_debug && __pthread_sig_debug > 0) + { + raise(__pthread_sig_debug); + /* We suspend ourself and gdb will wake us up when it is + ready to handle us. */ + __pthread_wait_for_restart_signal(thread_self()); + } + /* Synchronize debugging of the thread manager */ + PDEBUG("send REQ_DEBUG to manager thread\n"); + request.req_kind = REQ_DEBUG; + TEMP_FAILURE_RETRY(write(__pthread_manager_request, + (char *) &request, sizeof(request))); + return 0; +} + +/* Thread creation */ + +int pthread_create(pthread_t *thread, const pthread_attr_t *attr, + void * (*start_routine)(void *), void *arg) +{ + pthread_descr self = thread_self(); + struct pthread_request request; + if (__pthread_manager_request < 0) { + if (__pthread_initialize_manager() < 0) return EAGAIN; + } + request.req_thread = self; + request.req_kind = REQ_CREATE; + request.req_args.create.attr = attr; + request.req_args.create.fn = start_routine; + request.req_args.create.arg = arg; + sigprocmask(SIG_SETMASK, NULL, &request.req_args.create.mask); + PDEBUG("write REQ_CREATE to manager thread\n"); + TEMP_FAILURE_RETRY(write(__pthread_manager_request, + (char *) &request, sizeof(request))); + PDEBUG("before suspend(self)\n"); + suspend(self); + PDEBUG("after suspend(self)\n"); + if (THREAD_GETMEM(self, p_retcode) == 0) + *thread = (pthread_t) THREAD_GETMEM(self, p_retval); + return THREAD_GETMEM(self, p_retcode); +} + +/* Simple operations on thread identifiers */ + +pthread_t pthread_self(void) +{ + pthread_descr self = thread_self(); + return THREAD_GETMEM(self, p_tid); +} +libpthread_hidden_def (pthread_self) + +int pthread_equal(pthread_t thread1, pthread_t thread2) +{ + return thread1 == thread2; +} +libpthread_hidden_def (pthread_equal) + +/* Helper function for thread_self in the case of user-provided stacks */ + +#ifndef THREAD_SELF + +pthread_descr __pthread_find_self(void) +{ + char * sp = CURRENT_STACK_FRAME; + pthread_handle h; + + /* __pthread_handles[0] is the initial thread, __pthread_handles[1] is + the manager threads handled specially in thread_self(), so start at 2 */ + h = __pthread_handles + 2; + while (! (sp <= (char *) h->h_descr && sp >= h->h_bottom)) h++; + +#ifdef DEBUG_PT + if (h->h_descr == NULL) { + printf("*** %s ERROR descriptor is NULL!!!!! ***\n\n", __FUNCTION__); + _exit(1); + } +#endif + + return h->h_descr; +} +#else + +static pthread_descr thread_self_stack(void) +{ + char *sp = CURRENT_STACK_FRAME; + pthread_handle h; + + if (sp >= __pthread_manager_thread_bos && sp < __pthread_manager_thread_tos) + return manager_thread; + h = __pthread_handles + 2; +# if defined(USE_TLS) && USE_TLS + while (h->h_descr == NULL + || ! (sp <= (char *) h->h_descr->p_stackaddr && sp >= h->h_bottom)) + h++; +# else + while (! (sp <= (char *) h->h_descr && sp >= h->h_bottom)) + h++; +# endif + return h->h_descr; +} + +#endif + +/* Thread scheduling */ + +int pthread_setschedparam(pthread_t thread, int policy, + const struct sched_param *param) +{ + pthread_handle handle = thread_handle(thread); + pthread_descr th; + + __pthread_lock(&handle->h_lock, NULL); + if (invalid_handle(handle, thread)) { + __pthread_unlock(&handle->h_lock); + return ESRCH; + } + th = handle->h_descr; + if (sched_setscheduler(th->p_pid, policy, param) == -1) { + __pthread_unlock(&handle->h_lock); + return errno; + } + th->p_priority = policy == SCHED_OTHER ? 0 : param->sched_priority; + __pthread_unlock(&handle->h_lock); + if (__pthread_manager_request >= 0) + __pthread_manager_adjust_prio(th->p_priority); + return 0; +} +libpthread_hidden_def(pthread_setschedparam) + +int pthread_getschedparam(pthread_t thread, int *policy, + struct sched_param *param) +{ + pthread_handle handle = thread_handle(thread); + int pid, pol; + + __pthread_lock(&handle->h_lock, NULL); + if (invalid_handle(handle, thread)) { + __pthread_unlock(&handle->h_lock); + return ESRCH; + } + pid = handle->h_descr->p_pid; + __pthread_unlock(&handle->h_lock); + pol = sched_getscheduler(pid); + if (pol == -1) return errno; + if (sched_getparam(pid, param) == -1) return errno; + *policy = pol; + return 0; +} +libpthread_hidden_def(pthread_getschedparam) + +/* Process-wide exit() request */ + +static void pthread_onexit_process(int retcode, void *arg attribute_unused) +{ + struct pthread_request request; + pthread_descr self = thread_self(); + + if (__pthread_manager_request >= 0) { + request.req_thread = self; + request.req_kind = REQ_PROCESS_EXIT; + request.req_args.exit.code = retcode; + TEMP_FAILURE_RETRY(write(__pthread_manager_request, + (char *) &request, sizeof(request))); + suspend(self); + /* Main thread should accumulate times for thread manager and its + children, so that timings for main thread account for all threads. */ + if (self == __pthread_main_thread) { + waitpid(__pthread_manager_thread.p_pid, NULL, __WCLONE); + /* Since all threads have been asynchronously terminated + * (possibly holding locks), free cannot be used any more. */ + __pthread_manager_thread_bos = __pthread_manager_thread_tos = NULL; + } + } +} + +/* The handler for the RESTART signal just records the signal received + in the thread descriptor, and optionally performs a siglongjmp + (for pthread_cond_timedwait). */ + +static void pthread_handle_sigrestart(int sig) +{ + pthread_descr self = thread_self(); + THREAD_SETMEM(self, p_signal, sig); + if (THREAD_GETMEM(self, p_signal_jmp) != NULL) + siglongjmp(*THREAD_GETMEM(self, p_signal_jmp), 1); +} + +/* The handler for the CANCEL signal checks for cancellation + (in asynchronous mode), for process-wide exit and exec requests. + For the thread manager thread, redirect the signal to + __pthread_manager_sighandler. */ + +static void pthread_handle_sigcancel(int sig) +{ + pthread_descr self = thread_self(); + sigjmp_buf * jmpbuf; + + + if (self == &__pthread_manager_thread) + { +#ifdef THREAD_SELF + /* A new thread might get a cancel signal before it is fully + initialized, so that the thread register might still point to the + manager thread. Double check that this is really the manager + thread. */ + pthread_descr real_self = thread_self_stack(); + if (real_self == &__pthread_manager_thread) + { + __pthread_manager_sighandler(sig); + return; + } + /* Oops, thread_self() isn't working yet.. */ + self = real_self; +# ifdef INIT_THREAD_SELF + INIT_THREAD_SELF(self, self->p_nr); +# endif +#else + __pthread_manager_sighandler(sig); + return; +#endif + } + if (__builtin_expect (__pthread_exit_requested, 0)) { + /* Main thread should accumulate times for thread manager and its + children, so that timings for main thread account for all threads. */ + if (self == __pthread_main_thread) { +#if defined(USE_TLS) && USE_TLS + waitpid(__pthread_manager_thread->p_pid, NULL, __WCLONE); +#else + waitpid(__pthread_manager_thread.p_pid, NULL, __WCLONE); +#endif + } + _exit(__pthread_exit_code); + } + if (__builtin_expect (THREAD_GETMEM(self, p_canceled), 0) + && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) { + if (THREAD_GETMEM(self, p_canceltype) == PTHREAD_CANCEL_ASYNCHRONOUS) + __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); + jmpbuf = THREAD_GETMEM(self, p_cancel_jmp); + if (jmpbuf != NULL) { + THREAD_SETMEM(self, p_cancel_jmp, NULL); + siglongjmp(*jmpbuf, 1); + } + } +} + +/* Handler for the DEBUG signal. + The debugging strategy is as follows: + On reception of a REQ_DEBUG request (sent by new threads created to + the thread manager under debugging mode), the thread manager throws + __pthread_sig_debug to itself. The debugger (if active) intercepts + this signal, takes into account new threads and continue execution + of the thread manager by propagating the signal because it doesn't + know what it is specifically done for. In the current implementation, + the thread manager simply discards it. */ + +static void pthread_handle_sigdebug(int sig attribute_unused) +{ + /* Nothing */ +} + +/* Reset the state of the thread machinery after a fork(). + Close the pipe used for requests and set the main thread to the forked + thread. + Notice that we can't free the stack segments, as the forked thread + may hold pointers into them. */ + +void __pthread_reset_main_thread(void) +{ + pthread_descr self = thread_self(); + + if (__pthread_manager_request != -1) { + /* Free the thread manager stack */ + free(__pthread_manager_thread_bos); + __pthread_manager_thread_bos = __pthread_manager_thread_tos = NULL; + /* Close the two ends of the pipe */ + close(__pthread_manager_request); + close(__pthread_manager_reader); + __pthread_manager_request = __pthread_manager_reader = -1; + } + + /* Update the pid of the main thread */ + THREAD_SETMEM(self, p_pid, getpid()); + /* Make the forked thread the main thread */ + __pthread_main_thread = self; + THREAD_SETMEM(self, p_nextlive, self); + THREAD_SETMEM(self, p_prevlive, self); + /* Now this thread modifies the global variables. */ + THREAD_SETMEM(self, p_errnop, &_errno); + THREAD_SETMEM(self, p_h_errnop, &_h_errno); +} + +/* Process-wide exec() request */ + +void __pthread_kill_other_threads_np(void) +{ + struct sigaction sa; + /* Terminate all other threads and thread manager */ + pthread_onexit_process(0, NULL); + /* Make current thread the main thread in case the calling thread + changes its mind, does not exec(), and creates new threads instead. */ + __pthread_reset_main_thread(); + /* Reset the signal handlers behaviour for the signals the + implementation uses since this would be passed to the new + process. */ + memset(&sa, 0, sizeof(sa)); + if (SIG_DFL) /* if it's constant zero, it's already done */ + sa.sa_handler = SIG_DFL; + __libc_sigaction(__pthread_sig_restart, &sa, NULL); + __libc_sigaction(__pthread_sig_cancel, &sa, NULL); + if (__pthread_sig_debug > 0) + __libc_sigaction(__pthread_sig_debug, &sa, NULL); +} +weak_alias (__pthread_kill_other_threads_np, pthread_kill_other_threads_np) + +/* Concurrency symbol level. */ +static int current_level; + +int __pthread_setconcurrency(int level) +{ + /* We don't do anything unless we have found a useful interpretation. */ + current_level = level; + return 0; +} +weak_alias (__pthread_setconcurrency, pthread_setconcurrency) + +int __pthread_getconcurrency(void) +{ + return current_level; +} +weak_alias (__pthread_getconcurrency, pthread_getconcurrency) + + +/* Primitives for controlling thread execution */ + +void __pthread_wait_for_restart_signal(pthread_descr self) +{ + sigset_t mask; + + sigprocmask(SIG_SETMASK, NULL, &mask); /* Get current signal mask */ + sigdelset(&mask, __pthread_sig_restart); /* Unblock the restart signal */ + THREAD_SETMEM(self, p_signal, 0); + do { + sigsuspend(&mask); /* Wait for signal */ + } while (THREAD_GETMEM(self, p_signal) !=__pthread_sig_restart); + + READ_MEMORY_BARRIER(); /* See comment in __pthread_restart_new */ +} + +#ifndef __NR_rt_sigaction +/* The _old variants are for 2.0 and early 2.1 kernels which don't have RT + signals. + On these kernels, we use SIGUSR1 and SIGUSR2 for restart and cancellation. + Since the restart signal does not queue, we use an atomic counter to create + queuing semantics. This is needed to resolve a rare race condition in + pthread_cond_timedwait_relative. */ + +void __pthread_restart_old(pthread_descr th) +{ + if (atomic_increment(&th->p_resume_count) == -1) + kill(th->p_pid, __pthread_sig_restart); +} + +void __pthread_suspend_old(pthread_descr self) +{ + if (atomic_decrement(&self->p_resume_count) <= 0) + __pthread_wait_for_restart_signal(self); +} + +int +__pthread_timedsuspend_old(pthread_descr self, const struct timespec *abstime) +{ + sigset_t unblock, initial_mask; + int was_signalled = 0; + sigjmp_buf jmpbuf; + + if (atomic_decrement(&self->p_resume_count) == 0) { + /* Set up a longjmp handler for the restart signal, unblock + the signal and sleep. */ + + if (sigsetjmp(jmpbuf, 1) == 0) { + THREAD_SETMEM(self, p_signal_jmp, &jmpbuf); + THREAD_SETMEM(self, p_signal, 0); + /* Unblock the restart signal */ + __sigemptyset(&unblock); + sigaddset(&unblock, __pthread_sig_restart); + sigprocmask(SIG_UNBLOCK, &unblock, &initial_mask); + + while (1) { + struct timeval now; + struct timespec reltime; + + /* Compute a time offset relative to now. */ + gettimeofday (&now, NULL); + reltime.tv_nsec = abstime->tv_nsec - now.tv_usec * 1000; + reltime.tv_sec = abstime->tv_sec - now.tv_sec; + if (reltime.tv_nsec < 0) { + reltime.tv_nsec += 1000000000; + reltime.tv_sec -= 1; + } + + /* Sleep for the required duration. If woken by a signal, + resume waiting as required by Single Unix Specification. */ + if (reltime.tv_sec < 0 || nanosleep(&reltime, NULL) == 0) + break; + } + + /* Block the restart signal again */ + sigprocmask(SIG_SETMASK, &initial_mask, NULL); + was_signalled = 0; + } else { + was_signalled = 1; + } + THREAD_SETMEM(self, p_signal_jmp, NULL); + } + + /* Now was_signalled is true if we exited the above code + due to the delivery of a restart signal. In that case, + we know we have been dequeued and resumed and that the + resume count is balanced. Otherwise, there are some + cases to consider. First, try to bump up the resume count + back to zero. If it goes to 1, it means restart() was + invoked on this thread. The signal must be consumed + and the count bumped down and everything is cool. We + can return a 1 to the caller. + Otherwise, no restart was delivered yet, so a potential + race exists; we return a 0 to the caller which must deal + with this race in an appropriate way; for example by + atomically removing the thread from consideration for a + wakeup---if such a thing fails, it means a restart is + being delivered. */ + + if (!was_signalled) { + if (atomic_increment(&self->p_resume_count) != -1) { + __pthread_wait_for_restart_signal(self); + atomic_decrement(&self->p_resume_count); /* should be zero now! */ + /* woke spontaneously and consumed restart signal */ + return 1; + } + /* woke spontaneously but did not consume restart---caller must resolve */ + return 0; + } + /* woken due to restart signal */ + return 1; +} +#endif /* __NR_rt_sigaction */ + + +#ifdef __NR_rt_sigaction +void __pthread_restart_new(pthread_descr th) +{ + /* The barrier is proabably not needed, in which case it still documents + our assumptions. The intent is to commit previous writes to shared + memory so the woken thread will have a consistent view. Complementary + read barriers are present to the suspend functions. */ + WRITE_MEMORY_BARRIER(); + kill(th->p_pid, __pthread_sig_restart); +} + +int __pthread_timedsuspend_new(pthread_descr self, const struct timespec *abstime) +{ + sigset_t unblock, initial_mask; + int was_signalled = 0; + sigjmp_buf jmpbuf; + + if (sigsetjmp(jmpbuf, 1) == 0) { + THREAD_SETMEM(self, p_signal_jmp, &jmpbuf); + THREAD_SETMEM(self, p_signal, 0); + /* Unblock the restart signal */ + __sigemptyset(&unblock); + sigaddset(&unblock, __pthread_sig_restart); + sigprocmask(SIG_UNBLOCK, &unblock, &initial_mask); + + while (1) { + struct timeval now; + struct timespec reltime; + + /* Compute a time offset relative to now. */ + gettimeofday (&now, NULL); + reltime.tv_nsec = abstime->tv_nsec - now.tv_usec * 1000; + reltime.tv_sec = abstime->tv_sec - now.tv_sec; + if (reltime.tv_nsec < 0) { + reltime.tv_nsec += 1000000000; + reltime.tv_sec -= 1; + } + + /* Sleep for the required duration. If woken by a signal, + resume waiting as required by Single Unix Specification. */ + if (reltime.tv_sec < 0 || nanosleep(&reltime, NULL) == 0) + break; + } + + /* Block the restart signal again */ + sigprocmask(SIG_SETMASK, &initial_mask, NULL); + was_signalled = 0; + } else { + was_signalled = 1; + } + THREAD_SETMEM(self, p_signal_jmp, NULL); + + /* Now was_signalled is true if we exited the above code + due to the delivery of a restart signal. In that case, + everything is cool. We have been removed from whatever + we were waiting on by the other thread, and consumed its signal. + + Otherwise we this thread woke up spontaneously, or due to a signal other + than restart. This is an ambiguous case that must be resolved by + the caller; the thread is still eligible for a restart wakeup + so there is a race. */ + + READ_MEMORY_BARRIER(); /* See comment in __pthread_restart_new */ + return was_signalled; +} +#endif + +/* Debugging aid */ + +#ifdef DEBUG_PT +#include + +void __pthread_message(char * fmt, ...) +{ + char buffer[1024]; + va_list args; + sprintf(buffer, "%05d : ", getpid()); + va_start(args, fmt); + vsnprintf(buffer + 8, sizeof(buffer) - 8, fmt, args); + va_end(args); + TEMP_FAILURE_RETRY(write(2, buffer, strlen(buffer))); +} + +#endif + + +#ifndef __PIC__ +/* We need a hook to force the cancelation wrappers to be linked in when + static libpthread is used. */ +extern const char __pthread_provide_wrappers; +static const char *const __pthread_require_wrappers = + &__pthread_provide_wrappers; +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/ptlongjmp.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/ptlongjmp.c new file mode 100644 index 00000000..5213a4de --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/ptlongjmp.c @@ -0,0 +1,71 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1998 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +/* Redefine siglongjmp and longjmp so that they interact correctly + with cleanup handlers */ + +#include +#include "pthread.h" +#include "internals.h" +#include + +/* These functions are not declared anywhere since they shouldn't be + used at another place but here. */ +extern __typeof(siglongjmp) __libc_siglongjmp attribute_noreturn; +extern __typeof(longjmp) __libc_longjmp attribute_noreturn; + +static void pthread_cleanup_upto(__jmp_buf target) +{ + pthread_descr self = thread_self(); + struct _pthread_cleanup_buffer * c; + char *currentframe = CURRENT_STACK_FRAME; + + for (c = THREAD_GETMEM(self, p_cleanup); + c != NULL && _JMPBUF_UNWINDS(target, c); + c = c->__prev) + { +#ifdef _STACK_GROWS_DOWN + if ((char *) c <= currentframe) + { + c = NULL; + break; + } +#elif defined _STACK_GROWS_UP + if ((char *) c >= currentframe) + { + c = NULL; + break; + } +#else +# error "Define either _STACK_GROWS_DOWN or _STACK_GROWS_UP" +#endif + c->__routine(c->__arg); + } + THREAD_SETMEM(self, p_cleanup, c); + if (THREAD_GETMEM(self, p_in_sighandler) + && _JMPBUF_UNWINDS(target, THREAD_GETMEM(self, p_in_sighandler))) + THREAD_SETMEM(self, p_in_sighandler, NULL); +} + +void attribute_noreturn siglongjmp(sigjmp_buf env, int val) +{ + pthread_cleanup_upto(env->__jmpbuf); + __libc_siglongjmp(env, val); +} + +void attribute_noreturn longjmp(jmp_buf env, int val) +{ + pthread_cleanup_upto(env->__jmpbuf); + __libc_longjmp(env, val); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/queue.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/queue.h new file mode 100644 index 00000000..01d18d16 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/queue.h @@ -0,0 +1,60 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +/* Waiting queues */ + +/* Waiting queues are represented by lists of thread descriptors + linked through their p_nextwaiting field. The lists are kept + sorted by decreasing priority, and then decreasing waiting time. */ + +static __inline__ void enqueue(pthread_descr * q, pthread_descr th) +{ + int prio = th->p_priority; + for (; *q != NULL; q = &((*q)->p_nextwaiting)) { + if (prio > (*q)->p_priority) { + th->p_nextwaiting = *q; + *q = th; + return; + } + } + *q = th; +} + +static __inline__ pthread_descr dequeue(pthread_descr * q) +{ + pthread_descr th; + th = *q; + if (th != NULL) { + *q = th->p_nextwaiting; + th->p_nextwaiting = NULL; + } + return th; +} + +static __inline__ int remove_from_queue(pthread_descr * q, pthread_descr th) +{ + for (; *q != NULL; q = &((*q)->p_nextwaiting)) { + if (*q == th) { + *q = th->p_nextwaiting; + th->p_nextwaiting = NULL; + return 1; + } + } + return 0; +} + +static __inline__ int queue_is_empty(pthread_descr * q) +{ + return *q == NULL; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/restart.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/restart.h new file mode 100644 index 00000000..7d63a702 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/restart.h @@ -0,0 +1,50 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +#include +#include +#define __ASSUME_REALTIME_SIGNALS defined(__NR_rt_sigaction) + +/* Primitives for controlling thread execution */ + +static __inline__ void restart(pthread_descr th) +{ + /* See pthread.c */ +#if __ASSUME_REALTIME_SIGNALS + __pthread_restart_new(th); +#else + __pthread_restart(th); +#endif +} + +static __inline__ void suspend(pthread_descr self) +{ + /* See pthread.c */ +#if __ASSUME_REALTIME_SIGNALS + __pthread_wait_for_restart_signal(self); +#else + __pthread_suspend(self); +#endif +} + +static __inline__ int timedsuspend(pthread_descr self, + const struct timespec *abstime) +{ + /* See pthread.c */ +#if __ASSUME_REALTIME_SIGNALS + return __pthread_timedsuspend_new(self, abstime); +#else + return __pthread_timedsuspend(self, abstime); +#endif +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/rwlock.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/rwlock.c new file mode 100644 index 00000000..eaf71e77 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/rwlock.c @@ -0,0 +1,486 @@ +/* Read-write lock implementation. + Copyright (C) 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Xavier Leroy + and Ulrich Drepper , 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include "internals.h" +#include "queue.h" +#include "spinlock.h" +#include "restart.h" + +/* + * Check whether the calling thread already owns one or more read locks on the + * specified lock. If so, return a pointer to the read lock info structure + * corresponding to that lock. + */ + +static pthread_readlock_info * +rwlock_is_in_list(pthread_descr self, pthread_rwlock_t *rwlock) +{ + pthread_readlock_info *info; + + for (info = self->p_readlock_list; info != NULL; info = info->pr_next) + { + if (info->pr_lock == rwlock) + return info; + } + + return NULL; +} + +/* + * Add a new lock to the thread's list of locks for which it has a read lock. + * A new info node must be allocated for this, which is taken from the thread's + * free list, or by calling malloc. If malloc fails, a null pointer is + * returned. Otherwise the lock info structure is initialized and pushed + * onto the thread's list. + */ + +static pthread_readlock_info * +rwlock_add_to_list(pthread_descr self, pthread_rwlock_t *rwlock) +{ + pthread_readlock_info *info = self->p_readlock_free; + + if (info != NULL) + self->p_readlock_free = info->pr_next; + else + info = malloc(sizeof *info); + + if (info == NULL) + return NULL; + + info->pr_lock_count = 1; + info->pr_lock = rwlock; + info->pr_next = self->p_readlock_list; + self->p_readlock_list = info; + + return info; +} + +/* + * If the thread owns a read lock over the given pthread_rwlock_t, + * and this read lock is tracked in the thread's lock list, + * this function returns a pointer to the info node in that list. + * It also decrements the lock count within that node, and if + * it reaches zero, it removes the node from the list. + * If nothing is found, it returns a null pointer. + */ + +static pthread_readlock_info * +rwlock_remove_from_list(pthread_descr self, pthread_rwlock_t *rwlock) +{ + pthread_readlock_info **pinfo; + + for (pinfo = &self->p_readlock_list; *pinfo != NULL; pinfo = &(*pinfo)->pr_next) + { + if ((*pinfo)->pr_lock == rwlock) + { + pthread_readlock_info *info = *pinfo; + if (--info->pr_lock_count == 0) + *pinfo = info->pr_next; + return info; + } + } + + return NULL; +} + +/* + * This function checks whether the conditions are right to place a read lock. + * It returns 1 if so, otherwise zero. The rwlock's internal lock must be + * locked upon entry. + */ + +static int +rwlock_can_rdlock(pthread_rwlock_t *rwlock, int have_lock_already) +{ + /* Can't readlock; it is write locked. */ + if (rwlock->__rw_writer != NULL) + return 0; + + /* Lock prefers readers; get it. */ + if (rwlock->__rw_kind == PTHREAD_RWLOCK_PREFER_READER_NP) + return 1; + + /* Lock prefers writers, but none are waiting. */ + if (queue_is_empty(&rwlock->__rw_write_waiting)) + return 1; + + /* Writers are waiting, but this thread already has a read lock */ + if (have_lock_already) + return 1; + + /* Writers are waiting, and this is a new lock */ + return 0; +} + +/* + * This function helps support brain-damaged recursive read locking + * semantics required by Unix 98, while maintaining write priority. + * This basically determines whether this thread already holds a read lock + * already. It returns 1 if so, otherwise it returns 0. + * + * If the thread has any ``untracked read locks'' then it just assumes + * that this lock is among them, just to be safe, and returns 1. + * + * Also, if it finds the thread's lock in the list, it sets the pointer + * referenced by pexisting to refer to the list entry. + * + * If the thread has no untracked locks, and the lock is not found + * in its list, then it is added to the list. If this fails, + * then *pout_of_mem is set to 1. + */ + +static int +rwlock_have_already(pthread_descr *pself, pthread_rwlock_t *rwlock, + pthread_readlock_info **pexisting, int *pout_of_mem) +{ + pthread_readlock_info *existing = NULL; + int out_of_mem = 0, have_lock_already = 0; + pthread_descr self = *pself; + + if (rwlock->__rw_kind == PTHREAD_RWLOCK_PREFER_WRITER_NP) + { + if (!self) + self = thread_self(); + + existing = rwlock_is_in_list(self, rwlock); + + if (existing != NULL || self->p_untracked_readlock_count > 0) + have_lock_already = 1; + else + { + existing = rwlock_add_to_list(self, rwlock); + if (existing == NULL) + out_of_mem = 1; + } + } + + *pout_of_mem = out_of_mem; + *pexisting = existing; + *pself = self; + + return have_lock_already; +} + +int +pthread_rwlock_init (pthread_rwlock_t *rwlock, + const pthread_rwlockattr_t *attr) +{ + __pthread_init_lock(&rwlock->__rw_lock); + rwlock->__rw_readers = 0; + rwlock->__rw_writer = NULL; + rwlock->__rw_read_waiting = NULL; + rwlock->__rw_write_waiting = NULL; + + if (attr == NULL) + { + rwlock->__rw_kind = PTHREAD_RWLOCK_DEFAULT_NP; + rwlock->__rw_pshared = PTHREAD_PROCESS_PRIVATE; + } + else + { + rwlock->__rw_kind = attr->__lockkind; + rwlock->__rw_pshared = attr->__pshared; + } + + return 0; +} + + +int +pthread_rwlock_destroy (pthread_rwlock_t *rwlock) +{ + int readers; + _pthread_descr writer; + + __pthread_lock (&rwlock->__rw_lock, NULL); + readers = rwlock->__rw_readers; + writer = rwlock->__rw_writer; + __pthread_unlock (&rwlock->__rw_lock); + + if (readers > 0 || writer != NULL) + return EBUSY; + + return 0; +} + +int +pthread_rwlock_rdlock (pthread_rwlock_t *rwlock) +{ + pthread_descr self = NULL; + pthread_readlock_info *existing; + int out_of_mem, have_lock_already; + + have_lock_already = rwlock_have_already(&self, rwlock, + &existing, &out_of_mem); + + for (;;) + { + if (self == NULL) + self = thread_self (); + + __pthread_lock (&rwlock->__rw_lock, self); + + if (rwlock_can_rdlock(rwlock, have_lock_already)) + break; + + enqueue (&rwlock->__rw_read_waiting, self); + __pthread_unlock (&rwlock->__rw_lock); + suspend (self); /* This is not a cancellation point */ + } + + ++rwlock->__rw_readers; + __pthread_unlock (&rwlock->__rw_lock); + + if (have_lock_already || out_of_mem) + { + if (existing != NULL) + existing->pr_lock_count++; + else + self->p_untracked_readlock_count++; + } + + return 0; +} + +int +pthread_rwlock_tryrdlock (pthread_rwlock_t *rwlock) +{ + pthread_descr self = thread_self(); + pthread_readlock_info *existing; + int out_of_mem, have_lock_already; + int retval = EBUSY; + + have_lock_already = rwlock_have_already(&self, rwlock, + &existing, &out_of_mem); + + __pthread_lock (&rwlock->__rw_lock, self); + + /* 0 is passed to here instead of have_lock_already. + This is to meet Single Unix Spec requirements: + if writers are waiting, pthread_rwlock_tryrdlock + does not acquire a read lock, even if the caller has + one or more read locks already. */ + + if (rwlock_can_rdlock(rwlock, 0)) + { + ++rwlock->__rw_readers; + retval = 0; + } + + __pthread_unlock (&rwlock->__rw_lock); + + if (retval == 0) + { + if (have_lock_already || out_of_mem) + { + if (existing != NULL) + existing->pr_lock_count++; + else + self->p_untracked_readlock_count++; + } + } + + return retval; +} + + +int +pthread_rwlock_wrlock (pthread_rwlock_t *rwlock) +{ + pthread_descr self = thread_self (); + + while(1) + { + __pthread_lock (&rwlock->__rw_lock, self); + if (rwlock->__rw_readers == 0 && rwlock->__rw_writer == NULL) + { + rwlock->__rw_writer = self; + __pthread_unlock (&rwlock->__rw_lock); + return 0; + } + + /* Suspend ourselves, then try again */ + enqueue (&rwlock->__rw_write_waiting, self); + __pthread_unlock (&rwlock->__rw_lock); + suspend (self); /* This is not a cancellation point */ + } +} + + +int +pthread_rwlock_trywrlock (pthread_rwlock_t *rwlock) +{ + int result = EBUSY; + + __pthread_lock (&rwlock->__rw_lock, NULL); + if (rwlock->__rw_readers == 0 && rwlock->__rw_writer == NULL) + { + rwlock->__rw_writer = thread_self (); + result = 0; + } + __pthread_unlock (&rwlock->__rw_lock); + + return result; +} + + +int +pthread_rwlock_unlock (pthread_rwlock_t *rwlock) +{ + pthread_descr torestart; + pthread_descr th; + + __pthread_lock (&rwlock->__rw_lock, NULL); + if (rwlock->__rw_writer != NULL) + { + /* Unlocking a write lock. */ + if (rwlock->__rw_writer != thread_self ()) + { + __pthread_unlock (&rwlock->__rw_lock); + return EPERM; + } + rwlock->__rw_writer = NULL; + + if (rwlock->__rw_kind == PTHREAD_RWLOCK_PREFER_READER_NP + || (th = dequeue (&rwlock->__rw_write_waiting)) == NULL) + { + /* Restart all waiting readers. */ + torestart = rwlock->__rw_read_waiting; + rwlock->__rw_read_waiting = NULL; + __pthread_unlock (&rwlock->__rw_lock); + while ((th = dequeue (&torestart)) != NULL) + restart (th); + } + else + { + /* Restart one waiting writer. */ + __pthread_unlock (&rwlock->__rw_lock); + restart (th); + } + } + else + { + /* Unlocking a read lock. */ + if (rwlock->__rw_readers == 0) + { + __pthread_unlock (&rwlock->__rw_lock); + return EPERM; + } + + --rwlock->__rw_readers; + if (rwlock->__rw_readers == 0) + /* Restart one waiting writer, if any. */ + th = dequeue (&rwlock->__rw_write_waiting); + else + th = NULL; + + __pthread_unlock (&rwlock->__rw_lock); + if (th != NULL) + restart (th); + + /* Recursive lock fixup */ + + if (rwlock->__rw_kind == PTHREAD_RWLOCK_PREFER_WRITER_NP) + { + pthread_descr self = thread_self(); + pthread_readlock_info *victim = rwlock_remove_from_list(self, rwlock); + + if (victim != NULL) + { + if (victim->pr_lock_count == 0) + { + victim->pr_next = self->p_readlock_free; + self->p_readlock_free = victim; + } + } + else + { + if (self->p_untracked_readlock_count > 0) + self->p_untracked_readlock_count--; + } + } + } + + return 0; +} + + + +int +pthread_rwlockattr_init (pthread_rwlockattr_t *attr) +{ + attr->__lockkind = 0; + attr->__pshared = 0; + + return 0; +} + + +int +pthread_rwlockattr_destroy (pthread_rwlockattr_t *attr attribute_unused) +{ + return 0; +} + + +int +pthread_rwlockattr_getpshared (const pthread_rwlockattr_t *attr, int *pshared) +{ + *pshared = attr->__pshared; + return 0; +} + + +int +pthread_rwlockattr_setpshared (pthread_rwlockattr_t *attr, int pshared) +{ + if (pshared != PTHREAD_PROCESS_PRIVATE && pshared != PTHREAD_PROCESS_SHARED) + return EINVAL; + + attr->__pshared = pshared; + + return 0; +} + + +int +pthread_rwlockattr_getkind_np (const pthread_rwlockattr_t *attr, int *pref) +{ + *pref = attr->__lockkind; + return 0; +} + + +int +pthread_rwlockattr_setkind_np (pthread_rwlockattr_t *attr, int pref) +{ + if (pref != PTHREAD_RWLOCK_PREFER_READER_NP + && pref != PTHREAD_RWLOCK_PREFER_WRITER_NP + && pref != PTHREAD_RWLOCK_DEFAULT_NP) + return EINVAL; + + attr->__lockkind = pref; + + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/semaphore.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/semaphore.c new file mode 100644 index 00000000..c892a601 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/semaphore.c @@ -0,0 +1,313 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +/* Semaphores a la POSIX 1003.1b */ + +#include +#include +#include "pthread.h" +#include "semaphore.h" +#include "internals.h" +#include "spinlock.h" +#include "restart.h" +#include "queue.h" + +int __new_sem_init(sem_t *sem, int pshared, unsigned int value); +int __new_sem_init(sem_t *sem, int pshared, unsigned int value) +{ + if (value > SEM_VALUE_MAX) { + errno = EINVAL; + return -1; + } + if (pshared) { + errno = ENOSYS; + return -1; + } + __pthread_init_lock(&sem->__sem_lock); + sem->__sem_value = value; + sem->__sem_waiting = NULL; + return 0; +} + +/* Function called by pthread_cancel to remove the thread from + waiting inside __new_sem_wait. */ + +static int new_sem_extricate_func(void *obj, pthread_descr th) +{ + volatile pthread_descr self = thread_self(); + sem_t *sem = obj; + int did_remove = 0; + + __pthread_lock(&sem->__sem_lock, self); + did_remove = remove_from_queue(&sem->__sem_waiting, th); + __pthread_unlock(&sem->__sem_lock); + + return did_remove; +} + +int __new_sem_wait(sem_t * sem); +int __new_sem_wait(sem_t * sem) +{ + volatile pthread_descr self = thread_self(); + pthread_extricate_if extr; + int already_canceled = 0; + int spurious_wakeup_count; + + /* Set up extrication interface */ + extr.pu_object = sem; + extr.pu_extricate_func = new_sem_extricate_func; + + __pthread_lock(&sem->__sem_lock, self); + if (sem->__sem_value > 0) { + sem->__sem_value--; + __pthread_unlock(&sem->__sem_lock); + return 0; + } + /* Register extrication interface */ + THREAD_SETMEM(self, p_sem_avail, 0); + __pthread_set_own_extricate_if(self, &extr); + /* Enqueue only if not already cancelled. */ + if (!(THREAD_GETMEM(self, p_canceled) + && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE)) + enqueue(&sem->__sem_waiting, self); + else + already_canceled = 1; + __pthread_unlock(&sem->__sem_lock); + + if (already_canceled) { + __pthread_set_own_extricate_if(self, 0); + __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); + } + + /* Wait for sem_post or cancellation, or fall through if already canceled */ + spurious_wakeup_count = 0; + while (1) + { + suspend(self); + if (THREAD_GETMEM(self, p_sem_avail) == 0 + && (THREAD_GETMEM(self, p_woken_by_cancel) == 0 + || THREAD_GETMEM(self, p_cancelstate) != PTHREAD_CANCEL_ENABLE)) + { + /* Count resumes that don't belong to us. */ + spurious_wakeup_count++; + continue; + } + break; + } + __pthread_set_own_extricate_if(self, 0); + + /* Terminate only if the wakeup came from cancellation. */ + /* Otherwise ignore cancellation because we got the semaphore. */ + + if (THREAD_GETMEM(self, p_woken_by_cancel) + && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) { + THREAD_SETMEM(self, p_woken_by_cancel, 0); + __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); + } + /* We got the semaphore */ + return 0; +} + +int __new_sem_trywait(sem_t * sem); +int __new_sem_trywait(sem_t * sem) +{ + int retval; + + __pthread_lock(&sem->__sem_lock, NULL); + if (sem->__sem_value == 0) { + errno = EAGAIN; + retval = -1; + } else { + sem->__sem_value--; + retval = 0; + } + __pthread_unlock(&sem->__sem_lock); + return retval; +} + +int __new_sem_post(sem_t * sem); +int __new_sem_post(sem_t * sem) +{ + pthread_descr self = thread_self(); + pthread_descr th; + struct pthread_request request; + + if (THREAD_GETMEM(self, p_in_sighandler) == NULL) { + __pthread_lock(&sem->__sem_lock, self); + if (sem->__sem_waiting == NULL) { + if (sem->__sem_value >= SEM_VALUE_MAX) { + /* Overflow */ + errno = ERANGE; + __pthread_unlock(&sem->__sem_lock); + return -1; + } + sem->__sem_value++; + __pthread_unlock(&sem->__sem_lock); + } else { + th = dequeue(&sem->__sem_waiting); + __pthread_unlock(&sem->__sem_lock); + th->p_sem_avail = 1; + WRITE_MEMORY_BARRIER(); + restart(th); + } + } else { + /* If we're in signal handler, delegate post operation to + the thread manager. */ + if (__pthread_manager_request < 0) { + if (__pthread_initialize_manager() < 0) { + errno = EAGAIN; + return -1; + } + } + request.req_kind = REQ_POST; + request.req_args.post = sem; + TEMP_FAILURE_RETRY(write(__pthread_manager_request, + (char *) &request, sizeof(request))); + } + return 0; +} + +int __new_sem_getvalue(sem_t * sem, int * sval); +int __new_sem_getvalue(sem_t * sem, int * sval) +{ + *sval = sem->__sem_value; + return 0; +} + +int __new_sem_destroy(sem_t * sem); +int __new_sem_destroy(sem_t * sem) +{ + if (sem->__sem_waiting != NULL) { + __set_errno (EBUSY); + return -1; + } + return 0; +} + +sem_t *sem_open(const char *name attribute_unused, int oflag attribute_unused, ...) +{ + __set_errno (ENOSYS); + return SEM_FAILED; +} + +int sem_close(sem_t *sem attribute_unused) +{ + __set_errno (ENOSYS); + return -1; +} + +int sem_unlink(const char *name attribute_unused) +{ + __set_errno (ENOSYS); + return -1; +} + +int sem_timedwait(sem_t *sem, const struct timespec *abstime) +{ + pthread_descr self = thread_self(); + pthread_extricate_if extr; + int already_canceled = 0; + int spurious_wakeup_count; + + __pthread_lock(&sem->__sem_lock, self); + if (sem->__sem_value > 0) { + --sem->__sem_value; + __pthread_unlock(&sem->__sem_lock); + return 0; + } + + if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) { + /* The standard requires that if the function would block and the + time value is illegal, the function returns with an error. */ + __pthread_unlock(&sem->__sem_lock); + __set_errno (EINVAL); + return -1; + } + + /* Set up extrication interface */ + extr.pu_object = sem; + extr.pu_extricate_func = new_sem_extricate_func; + + /* Register extrication interface */ + THREAD_SETMEM(self, p_sem_avail, 0); + __pthread_set_own_extricate_if(self, &extr); + /* Enqueue only if not already cancelled. */ + if (!(THREAD_GETMEM(self, p_canceled) + && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE)) + enqueue(&sem->__sem_waiting, self); + else + already_canceled = 1; + __pthread_unlock(&sem->__sem_lock); + + if (already_canceled) { + __pthread_set_own_extricate_if(self, 0); + __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); + } + + spurious_wakeup_count = 0; + while (1) + { + if (timedsuspend(self, abstime) == 0) { + int was_on_queue; + + /* __pthread_lock will queue back any spurious restarts that + may happen to it. */ + + __pthread_lock(&sem->__sem_lock, self); + was_on_queue = remove_from_queue(&sem->__sem_waiting, self); + __pthread_unlock(&sem->__sem_lock); + + if (was_on_queue) { + __pthread_set_own_extricate_if(self, 0); + __set_errno (ETIMEDOUT); + return -1; + } + + /* Eat the outstanding restart() from the signaller */ + suspend(self); + } + + if (THREAD_GETMEM(self, p_sem_avail) == 0 + && (THREAD_GETMEM(self, p_woken_by_cancel) == 0 + || THREAD_GETMEM(self, p_cancelstate) != PTHREAD_CANCEL_ENABLE)) + { + /* Count resumes that don't belong to us. */ + spurious_wakeup_count++; + continue; + } + break; + } + + __pthread_set_own_extricate_if(self, 0); + + /* Terminate only if the wakeup came from cancellation. */ + /* Otherwise ignore cancellation because we got the semaphore. */ + + if (THREAD_GETMEM(self, p_woken_by_cancel) + && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) { + THREAD_SETMEM(self, p_woken_by_cancel, 0); + __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); + } + /* We got the semaphore */ + return 0; +} + + +weak_alias (__new_sem_init, sem_init) +weak_alias (__new_sem_wait, sem_wait) +weak_alias (__new_sem_trywait, sem_trywait) +weak_alias (__new_sem_post, sem_post) +weak_alias (__new_sem_getvalue, sem_getvalue) +weak_alias (__new_sem_destroy, sem_destroy) + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/semaphore.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/semaphore.h new file mode 100644 index 00000000..fea127b1 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/semaphore.h @@ -0,0 +1,94 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +#ifndef _SEMAPHORE_H +#define _SEMAPHORE_H 1 + +#include +#include +#ifdef __USE_XOPEN2K +# define __need_timespec +# include +#endif + +#ifndef _PTHREAD_DESCR_DEFINED +/* Thread descriptors. Needed for `sem_t' definition. */ +typedef struct _pthread_descr_struct *_pthread_descr; +# define _PTHREAD_DESCR_DEFINED +#endif + +/* System specific semaphore definition. */ +typedef struct +{ + struct _pthread_fastlock __sem_lock; + int __sem_value; + _pthread_descr __sem_waiting; +} sem_t; + + + +/* Value returned if `sem_open' failed. */ +#define SEM_FAILED ((sem_t *) 0) + +/* Maximum value the semaphore can have. */ +#define SEM_VALUE_MAX ((int) ((~0u) >> 1)) + + +__BEGIN_DECLS + +/* Initialize semaphore object SEM to VALUE. If PSHARED then share it + with other processes. */ +extern int sem_init (sem_t *__sem, int __pshared, unsigned int __value) __THROW; + +/* Free resources associated with semaphore object SEM. */ +extern int sem_destroy (sem_t *__sem) __THROW; + +/* Open a named semaphore NAME with open flags OFLAG. */ +extern sem_t *sem_open (__const char *__name, int __oflag, ...) __THROW; + +/* Close descriptor for named semaphore SEM. */ +extern int sem_close (sem_t *__sem) __THROW; + +/* Remove named semaphore NAME. */ +extern int sem_unlink (__const char *__name) __THROW; + +/* Wait for SEM being posted. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern int sem_wait (sem_t *__sem); + +#ifdef __USE_XOPEN2K +/* Similar to `sem_wait' but wait only until ABSTIME. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern int sem_timedwait (sem_t *__restrict __sem, + __const struct timespec *__restrict __abstime); +#endif + +/* Test whether SEM is posted. */ +extern int sem_trywait (sem_t *__sem) __THROW; + +/* Post SEM. */ +extern int sem_post (sem_t *__sem) __THROW; + +/* Get current value of SEM and store it in *SVAL. */ +extern int sem_getvalue (sem_t *__restrict __sem, int *__restrict __sval) + __THROW; + + +__END_DECLS + +#endif /* semaphore.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/signals.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/signals.c new file mode 100644 index 00000000..2a451f3d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/signals.c @@ -0,0 +1,250 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +/* Handling of signals */ + +#include +#include +#include +#include "pthread.h" +#include "internals.h" +#include "spinlock.h" +#include +#include + +/* mods for uClibc: __libc_sigaction is not in any standard headers */ +extern __typeof(sigaction) __libc_sigaction; + +int pthread_sigmask(int how, const sigset_t * newmask, sigset_t * oldmask) +{ + sigset_t mask; + + if (newmask != NULL) { + mask = *newmask; + /* Don't allow __pthread_sig_restart to be unmasked. + Don't allow __pthread_sig_cancel to be masked. */ + switch(how) { + case SIG_SETMASK: + sigaddset(&mask, __pthread_sig_restart); + sigdelset(&mask, __pthread_sig_cancel); + if (__pthread_sig_debug > 0) + sigdelset(&mask, __pthread_sig_debug); + break; + case SIG_BLOCK: + sigdelset(&mask, __pthread_sig_cancel); + if (__pthread_sig_debug > 0) + sigdelset(&mask, __pthread_sig_debug); + break; + case SIG_UNBLOCK: + sigdelset(&mask, __pthread_sig_restart); + break; + } + newmask = &mask; + } + if (sigprocmask(how, newmask, oldmask) == -1) + return errno; + else + return 0; +} + +int pthread_kill(pthread_t thread, int signo) +{ + pthread_handle handle = thread_handle(thread); + int pid; + + __pthread_lock(&handle->h_lock, NULL); + if (invalid_handle(handle, thread)) { + __pthread_unlock(&handle->h_lock); + return ESRCH; + } + pid = handle->h_descr->p_pid; + __pthread_unlock(&handle->h_lock); + if (kill(pid, signo) == -1) + return errno; + else + return 0; +} + +/* User-provided signal handlers */ +typedef void (*arch_sighandler_t) __PMT ((int, SIGCONTEXT)); +static union +{ + arch_sighandler_t old; + void (*rt) (int, struct siginfo *, struct ucontext *); +} sighandler[NSIG]; + +/* The wrapper around user-provided signal handlers */ +static void pthread_sighandler(int signo, SIGCONTEXT ctx) +{ + pthread_descr self = thread_self(); + char * in_sighandler; + /* If we're in a sigwait operation, just record the signal received + and return without calling the user's handler */ + if (THREAD_GETMEM(self, p_sigwaiting)) { + THREAD_SETMEM(self, p_sigwaiting, 0); + THREAD_SETMEM(self, p_signal, signo); + return; + } + /* Record that we're in a signal handler and call the user's + handler function */ + in_sighandler = THREAD_GETMEM(self, p_in_sighandler); + if (in_sighandler == NULL) + THREAD_SETMEM(self, p_in_sighandler, CURRENT_STACK_FRAME); + sighandler[signo].old(signo, SIGCONTEXT_EXTRA_ARGS ctx); + if (in_sighandler == NULL) + THREAD_SETMEM(self, p_in_sighandler, NULL); +} + +/* The same, this time for real-time signals. */ +static void pthread_sighandler_rt(int signo, struct siginfo *si, + struct ucontext *uc) +{ + pthread_descr self = thread_self(); + char * in_sighandler; + /* If we're in a sigwait operation, just record the signal received + and return without calling the user's handler */ + if (THREAD_GETMEM(self, p_sigwaiting)) { + THREAD_SETMEM(self, p_sigwaiting, 0); + THREAD_SETMEM(self, p_signal, signo); + return; + } + /* Record that we're in a signal handler and call the user's + handler function */ + in_sighandler = THREAD_GETMEM(self, p_in_sighandler); + if (in_sighandler == NULL) + THREAD_SETMEM(self, p_in_sighandler, CURRENT_STACK_FRAME); + sighandler[signo].rt(signo, si, uc); + if (in_sighandler == NULL) + THREAD_SETMEM(self, p_in_sighandler, NULL); +} + +/* The wrapper around sigaction. Install our own signal handler + around the signal. */ +libpthread_hidden_proto(sigaction) +int sigaction(int sig, const struct sigaction * act, + struct sigaction * oact) +{ + struct sigaction newact; + struct sigaction *newactp; + +#ifdef DEBUG_PT +printf(__FUNCTION__": pthreads wrapper!\n"); +#endif + if (sig == __pthread_sig_restart || + sig == __pthread_sig_cancel || + (sig == __pthread_sig_debug && __pthread_sig_debug > 0)) + return EINVAL; + if (act) + { + newact = *act; + if (act->sa_handler != SIG_IGN && act->sa_handler != SIG_DFL + && sig > 0 && sig < NSIG) + { + if (act->sa_flags & SA_SIGINFO) + newact.sa_handler = (__sighandler_t) pthread_sighandler_rt; + else + newact.sa_handler = (__sighandler_t) pthread_sighandler; + } + newactp = &newact; + } + else + newactp = NULL; + if (__libc_sigaction(sig, newactp, oact) == -1) + return -1; +#ifdef DEBUG_PT +printf(__FUNCTION__": sighandler installed, sigaction successful\n"); +#endif + if (sig > 0 && sig < NSIG) + { + if (oact != NULL) + oact->sa_handler = (__sighandler_t) sighandler[sig].old; + if (act) + /* For the assignment is does not matter whether it's a normal + or real-time signal. */ + sighandler[sig].old = (arch_sighandler_t) act->sa_handler; + } + return 0; +} +libpthread_hidden_def(sigaction) + +/* A signal handler that does nothing */ +static void pthread_null_sighandler(int sig attribute_unused) { } + +/* sigwait -- synchronously wait for a signal */ +int sigwait(const sigset_t * set, int * sig) +{ + volatile pthread_descr self = thread_self(); + sigset_t mask; + int s; + sigjmp_buf jmpbuf; + struct sigaction sa; + + /* Get ready to block all signals except those in set + and the cancellation signal. + Also check that handlers are installed on all signals in set, + and if not, install our dummy handler. This is conformant to + POSIX: "The effect of sigwait() on the signal actions for the + signals in set is unspecified." */ + __sigfillset(&mask); + sigdelset(&mask, __pthread_sig_cancel); + for (s = 1; s <= NSIG; s++) { + if (sigismember(set, s) && + s != __pthread_sig_restart && + s != __pthread_sig_cancel && + s != __pthread_sig_debug) { + sigdelset(&mask, s); + if (sighandler[s].old == NULL || + sighandler[s].old == (arch_sighandler_t) SIG_DFL || + sighandler[s].old == (arch_sighandler_t) SIG_IGN) { + memset(&sa, 0, sizeof(sa)); + sa.sa_handler = pthread_null_sighandler; + sigaction(s, &sa, NULL); + } + } + } + /* Test for cancellation */ + if (sigsetjmp(jmpbuf, 1) == 0) { + THREAD_SETMEM(self, p_cancel_jmp, &jmpbuf); + if (! (THREAD_GETMEM(self, p_canceled) + && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE)) { + /* Reset the signal count */ + THREAD_SETMEM(self, p_signal, 0); + /* Say we're in sigwait */ + THREAD_SETMEM(self, p_sigwaiting, 1); + /* Unblock the signals and wait for them */ + sigsuspend(&mask); + } + } + THREAD_SETMEM(self, p_cancel_jmp, NULL); + /* The signals are now reblocked. Check for cancellation */ + pthread_testcancel(); + /* We should have self->p_signal != 0 and equal to the signal received */ + *sig = THREAD_GETMEM(self, p_signal); + return 0; +} + +/* Redefine raise() to send signal to calling thread only, + as per POSIX 1003.1c */ +libpthread_hidden_proto(raise) +int raise (int sig) +{ + int retcode = pthread_kill(pthread_self(), sig); + if (retcode == 0) + return 0; + else { + errno = retcode; + return -1; + } +} +libpthread_hidden_def(raise) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/specific.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/specific.c new file mode 100644 index 00000000..8e08aa4d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/specific.c @@ -0,0 +1,198 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +/* Thread-specific data */ + +#include +#include +#include +#include +#include "pthread.h" +#include "internals.h" +#include "spinlock.h" +#include "restart.h" + +/* Table of keys. */ + +static struct pthread_key_struct pthread_keys[PTHREAD_KEYS_MAX] = + { { 0, NULL } }; + +/* For debugging purposes put the maximum number of keys in a variable. */ +const int __linuxthreads_pthread_keys_max = PTHREAD_KEYS_MAX; +const int __linuxthreads_pthread_key_2ndlevel_size = PTHREAD_KEY_2NDLEVEL_SIZE; + +/* Mutex to protect access to pthread_keys */ + +static pthread_mutex_t pthread_keys_mutex = PTHREAD_MUTEX_INITIALIZER; + +/* Create a new key */ + +int pthread_key_create(pthread_key_t * key, destr_function destr) +{ + int i; + + __pthread_mutex_lock(&pthread_keys_mutex); + for (i = 0; i < PTHREAD_KEYS_MAX; i++) { + if (! pthread_keys[i].in_use) { + /* Mark key in use */ + pthread_keys[i].in_use = 1; + pthread_keys[i].destr = destr; + __pthread_mutex_unlock(&pthread_keys_mutex); + *key = i; + return 0; + } + } + __pthread_mutex_unlock(&pthread_keys_mutex); + return EAGAIN; +} + +/* Delete a key */ +int pthread_key_delete(pthread_key_t key) +{ + pthread_descr self = thread_self(); + + __pthread_mutex_lock(&pthread_keys_mutex); + if (key >= PTHREAD_KEYS_MAX || !pthread_keys[key].in_use) { + __pthread_mutex_unlock(&pthread_keys_mutex); + return EINVAL; + } + pthread_keys[key].in_use = 0; + pthread_keys[key].destr = NULL; + + /* Set the value of the key to NULL in all running threads, so + that if the key is reallocated later by pthread_key_create, its + associated values will be NULL in all threads. + Do nothing if no threads have been created yet. */ + if (__pthread_manager_request != -1) + { + pthread_descr th; + unsigned int idx1st, idx2nd; + + idx1st = key / PTHREAD_KEY_2NDLEVEL_SIZE; + idx2nd = key % PTHREAD_KEY_2NDLEVEL_SIZE; + th = self; + do { + /* If the thread already is terminated don't modify the memory. */ + if (!th->p_terminated && th->p_specific[idx1st] != NULL) + th->p_specific[idx1st][idx2nd] = NULL; + th = th->p_nextlive; + } while (th != self); + } + + __pthread_mutex_unlock(&pthread_keys_mutex); + return 0; +} + +/* Set the value of a key */ + +int pthread_setspecific(pthread_key_t key, const void * pointer) +{ + pthread_descr self = thread_self(); + unsigned int idx1st, idx2nd; + + if (key >= PTHREAD_KEYS_MAX || !pthread_keys[key].in_use) + return EINVAL; + idx1st = key / PTHREAD_KEY_2NDLEVEL_SIZE; + idx2nd = key % PTHREAD_KEY_2NDLEVEL_SIZE; + if (THREAD_GETMEM_NC(self, p_specific[idx1st]) == NULL) { + void *newp = calloc(PTHREAD_KEY_2NDLEVEL_SIZE, sizeof (void *)); + if (newp == NULL) + return ENOMEM; + THREAD_SETMEM_NC(self, p_specific[idx1st], newp); + } + THREAD_GETMEM_NC(self, p_specific[idx1st])[idx2nd] = (void *) pointer; + return 0; +} + +/* Get the value of a key */ + +void * pthread_getspecific(pthread_key_t key) +{ + pthread_descr self = thread_self(); + unsigned int idx1st, idx2nd; + + if (key >= PTHREAD_KEYS_MAX) + return NULL; + idx1st = key / PTHREAD_KEY_2NDLEVEL_SIZE; + idx2nd = key % PTHREAD_KEY_2NDLEVEL_SIZE; + if (THREAD_GETMEM_NC(self, p_specific[idx1st]) == NULL + || !pthread_keys[key].in_use) + return NULL; + return THREAD_GETMEM_NC(self, p_specific[idx1st])[idx2nd]; +} + +/* Call the destruction routines on all keys */ + +void __pthread_destroy_specifics(void) +{ + pthread_descr self = thread_self(); + int i, j, round, found_nonzero; + destr_function destr; + void * data; + + for (round = 0, found_nonzero = 1; + found_nonzero && round < PTHREAD_DESTRUCTOR_ITERATIONS; + round++) { + found_nonzero = 0; + for (i = 0; i < PTHREAD_KEY_1STLEVEL_SIZE; i++) + if (THREAD_GETMEM_NC(self, p_specific[i]) != NULL) + for (j = 0; j < PTHREAD_KEY_2NDLEVEL_SIZE; j++) { + destr = pthread_keys[i * PTHREAD_KEY_2NDLEVEL_SIZE + j].destr; + data = THREAD_GETMEM_NC(self, p_specific[i])[j]; + if (destr != NULL && data != NULL) { + THREAD_GETMEM_NC(self, p_specific[i])[j] = NULL; + destr(data); + found_nonzero = 1; + } + } + } + __pthread_lock(THREAD_GETMEM(self, p_lock), self); + for (i = 0; i < PTHREAD_KEY_1STLEVEL_SIZE; i++) { + if (THREAD_GETMEM_NC(self, p_specific[i]) != NULL) { + free(THREAD_GETMEM_NC(self, p_specific[i])); + THREAD_SETMEM_NC(self, p_specific[i], NULL); + } + } + __pthread_unlock(THREAD_GETMEM(self, p_lock)); +} + +#ifndef USE___THREAD + +/* Thread-specific data for libc. */ + +int +__pthread_internal_tsd_set (int key, const void * pointer) +{ + pthread_descr self = thread_self(); + + THREAD_SETMEM_NC(self, p_libc_specific[key], (void *) pointer); + return 0; +} + +void * +__pthread_internal_tsd_get (int key) +{ + pthread_descr self = thread_self(); + + return THREAD_GETMEM_NC(self, p_libc_specific[key]); +} + +void ** __attribute__ ((__const__)) +__pthread_internal_tsd_address (int key) +{ + pthread_descr self = thread_self(); + return &self->p_libc_specific[key]; +} + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/spinlock.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/spinlock.c new file mode 100644 index 00000000..24c81d47 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/spinlock.c @@ -0,0 +1,723 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1998 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +/* Internal locks */ + +#define __FORCE_GLIBC +#include +#include +#include +#include +#include +#include +#include "pthread.h" +#include "internals.h" +#include "spinlock.h" +#include "restart.h" + +libpthread_hidden_proto(nanosleep) + +static void __pthread_acquire(int * spinlock); + +static __inline__ void __pthread_release(int * spinlock) +{ + WRITE_MEMORY_BARRIER(); + *spinlock = __LT_SPINLOCK_INIT; + __asm__ __volatile__ ("" : "=m" (*spinlock) : "m" (*spinlock)); +} + + +/* The status field of a spinlock is a pointer whose least significant + bit is a locked flag. + + Thus the field values have the following meanings: + + status == 0: spinlock is free + status == 1: spinlock is taken; no thread is waiting on it + + (status & 1) == 1: spinlock is taken and (status & ~1L) is a + pointer to the first waiting thread; other + waiting threads are linked via the p_nextlock + field. + (status & 1) == 0: same as above, but spinlock is not taken. + + The waiting list is not sorted by priority order. + Actually, we always insert at top of list (sole insertion mode + that can be performed without locking). + For __pthread_unlock, we perform a linear search in the list + to find the highest-priority, oldest waiting thread. + This is safe because there are no concurrent __pthread_unlock + operations -- only the thread that locked the mutex can unlock it. */ + + +void internal_function __pthread_lock(struct _pthread_fastlock * lock, + pthread_descr self) +{ +#if defined HAS_COMPARE_AND_SWAP + long oldstatus, newstatus; + int successful_seizure, spurious_wakeup_count; + int spin_count; +#endif + +#if defined TEST_FOR_COMPARE_AND_SWAP + if (!__pthread_has_cas) +#endif +#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP + { + __pthread_acquire(&lock->__spinlock); + return; + } +#endif + +#if defined HAS_COMPARE_AND_SWAP + /* First try it without preparation. Maybe it's a completely + uncontested lock. */ + if (lock->__status == 0 && __compare_and_swap (&lock->__status, 0, 1)) + return; + + spurious_wakeup_count = 0; + spin_count = 0; + + /* On SMP, try spinning to get the lock. */ +#if 0 + if (__pthread_smp_kernel) { + int max_count = lock->__spinlock * 2 + 10; + + if (max_count > MAX_ADAPTIVE_SPIN_COUNT) + max_count = MAX_ADAPTIVE_SPIN_COUNT; + + for (spin_count = 0; spin_count < max_count; spin_count++) { + if (((oldstatus = lock->__status) & 1) == 0) { + if(__compare_and_swap(&lock->__status, oldstatus, oldstatus | 1)) + { + if (spin_count) + lock->__spinlock += (spin_count - lock->__spinlock) / 8; + READ_MEMORY_BARRIER(); + return; + } + } +#ifdef BUSY_WAIT_NOP + BUSY_WAIT_NOP; +#endif + __asm__ __volatile__ ("" : "=m" (lock->__status) : "m" (lock->__status)); + } + + lock->__spinlock += (spin_count - lock->__spinlock) / 8; + } +#endif + +again: + + /* No luck, try once more or suspend. */ + + do { + oldstatus = lock->__status; + successful_seizure = 0; + + if ((oldstatus & 1) == 0) { + newstatus = oldstatus | 1; + successful_seizure = 1; + } else { + if (self == NULL) + self = thread_self(); + newstatus = (long) self | 1; + } + + if (self != NULL) { + THREAD_SETMEM(self, p_nextlock, (pthread_descr) (oldstatus)); + /* Make sure the store in p_nextlock completes before performing + the compare-and-swap */ + MEMORY_BARRIER(); + } + } while(! __compare_and_swap(&lock->__status, oldstatus, newstatus)); + + /* Suspend with guard against spurious wakeup. + This can happen in pthread_cond_timedwait_relative, when the thread + wakes up due to timeout and is still on the condvar queue, and then + locks the queue to remove itself. At that point it may still be on the + queue, and may be resumed by a condition signal. */ + + if (!successful_seizure) { + for (;;) { + suspend(self); + if (self->p_nextlock != NULL) { + /* Count resumes that don't belong to us. */ + spurious_wakeup_count++; + continue; + } + break; + } + goto again; + } + + /* Put back any resumes we caught that don't belong to us. */ + while (spurious_wakeup_count--) + restart(self); + + READ_MEMORY_BARRIER(); +#endif +} + +int __pthread_unlock(struct _pthread_fastlock * lock) +{ +#if defined HAS_COMPARE_AND_SWAP + long oldstatus; + pthread_descr thr, * ptr, * maxptr; + int maxprio; +#endif + +#if defined TEST_FOR_COMPARE_AND_SWAP + if (!__pthread_has_cas) +#endif +#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP + { + __pthread_release(&lock->__spinlock); + return 0; + } +#endif + +#if defined HAS_COMPARE_AND_SWAP + WRITE_MEMORY_BARRIER(); + +again: + while ((oldstatus = lock->__status) == 1) { + if (__compare_and_swap_with_release_semantics(&lock->__status, + oldstatus, 0)) + return 0; + } + + /* Find thread in waiting queue with maximal priority */ + ptr = (pthread_descr *) &lock->__status; + thr = (pthread_descr) (oldstatus & ~1L); + maxprio = 0; + maxptr = ptr; + + /* Before we iterate over the wait queue, we need to execute + a read barrier, otherwise we may read stale contents of nodes that may + just have been inserted by other processors. One read barrier is enough to + ensure we have a stable list; we don't need one for each pointer chase + through the list, because we are the owner of the lock; other threads + can only add nodes at the front; if a front node is consistent, + the ones behind it must also be. */ + + READ_MEMORY_BARRIER(); + + while (thr != 0) { + if (thr->p_priority >= maxprio) { + maxptr = ptr; + maxprio = thr->p_priority; + } + ptr = &(thr->p_nextlock); + thr = (pthread_descr)((long)(thr->p_nextlock) & ~1L); + } + + /* Remove max prio thread from waiting list. */ + if (maxptr == (pthread_descr *) &lock->__status) { + /* If max prio thread is at head, remove it with compare-and-swap + to guard against concurrent lock operation. This removal + also has the side effect of marking the lock as released + because the new status comes from thr->p_nextlock whose + least significant bit is clear. */ + thr = (pthread_descr) (oldstatus & ~1L); + if (! __compare_and_swap_with_release_semantics + (&lock->__status, oldstatus, (long)(thr->p_nextlock) & ~1L)) + goto again; + } else { + /* No risk of concurrent access, remove max prio thread normally. + But in this case we must also flip the least significant bit + of the status to mark the lock as released. */ + thr = (pthread_descr)((long)*maxptr & ~1L); + *maxptr = thr->p_nextlock; + + /* Ensure deletion from linked list completes before we + release the lock. */ + WRITE_MEMORY_BARRIER(); + + do { + oldstatus = lock->__status; + } while (!__compare_and_swap_with_release_semantics(&lock->__status, + oldstatus, oldstatus & ~1L)); + } + + /* Wake up the selected waiting thread. Woken thread can check + its own p_nextlock field for NULL to detect that it has been removed. No + barrier is needed here, since restart() and suspend() take + care of memory synchronization. */ + + thr->p_nextlock = NULL; + restart(thr); + + return 0; +#endif +} + +/* + * Alternate fastlocks do not queue threads directly. Instead, they queue + * these wait queue node structures. When a timed wait wakes up due to + * a timeout, it can leave its wait node in the queue (because there + * is no safe way to remove from the quue). Some other thread will + * deallocate the abandoned node. + */ + + +struct wait_node { + struct wait_node *next; /* Next node in null terminated linked list */ + pthread_descr thr; /* The thread waiting with this node */ + int abandoned; /* Atomic flag */ +}; + +static long wait_node_free_list; +static int wait_node_free_list_spinlock; + +/* Allocate a new node from the head of the free list using an atomic + operation, or else using malloc if that list is empty. A fundamental + assumption here is that we can safely access wait_node_free_list->next. + That's because we never free nodes once we allocate them, so a pointer to a + node remains valid indefinitely. */ + +static struct wait_node *wait_node_alloc(void) +{ + struct wait_node *new_node = 0; + + __pthread_acquire(&wait_node_free_list_spinlock); + if (wait_node_free_list != 0) { + new_node = (struct wait_node *) wait_node_free_list; + wait_node_free_list = (long) new_node->next; + } + WRITE_MEMORY_BARRIER(); + __pthread_release(&wait_node_free_list_spinlock); + + if (new_node == 0) + return malloc(sizeof *wait_node_alloc()); + + return new_node; +} + +/* Return a node to the head of the free list using an atomic + operation. */ + +static void wait_node_free(struct wait_node *wn) +{ + __pthread_acquire(&wait_node_free_list_spinlock); + wn->next = (struct wait_node *) wait_node_free_list; + wait_node_free_list = (long) wn; + WRITE_MEMORY_BARRIER(); + __pthread_release(&wait_node_free_list_spinlock); + return; +} + +#if defined HAS_COMPARE_AND_SWAP + +/* Remove a wait node from the specified queue. It is assumed + that the removal takes place concurrently with only atomic insertions at the + head of the queue. */ + +static void wait_node_dequeue(struct wait_node **pp_head, + struct wait_node **pp_node, + struct wait_node *p_node) +{ + /* If the node is being deleted from the head of the + list, it must be deleted using atomic compare-and-swap. + Otherwise it can be deleted in the straightforward way. */ + + if (pp_node == pp_head) { + /* We don't need a read barrier between these next two loads, + because it is assumed that the caller has already ensured + the stability of *p_node with respect to p_node. */ + + long oldvalue = (long) p_node; + long newvalue = (long) p_node->next; + + if (__compare_and_swap((long *) pp_node, oldvalue, newvalue)) + return; + + /* Oops! Compare and swap failed, which means the node is + no longer first. We delete it using the ordinary method. But we don't + know the identity of the node which now holds the pointer to the node + being deleted, so we must search from the beginning. */ + + for (pp_node = pp_head; p_node != *pp_node; ) { + pp_node = &(*pp_node)->next; + READ_MEMORY_BARRIER(); /* Stabilize *pp_node for next iteration. */ + } + } + + *pp_node = p_node->next; + return; +} + +#endif + +void __pthread_alt_lock(struct _pthread_fastlock * lock, + pthread_descr self) +{ +#if defined HAS_COMPARE_AND_SWAP + long oldstatus, newstatus; +#endif + struct wait_node wait_node; + +#if defined TEST_FOR_COMPARE_AND_SWAP + if (!__pthread_has_cas) +#endif +#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP + { + int suspend_needed = 0; + __pthread_acquire(&lock->__spinlock); + + if (lock->__status == 0) + lock->__status = 1; + else { + if (self == NULL) + self = thread_self(); + + wait_node.abandoned = 0; + wait_node.next = (struct wait_node *) lock->__status; + wait_node.thr = self; + lock->__status = (long) &wait_node; + suspend_needed = 1; + } + + __pthread_release(&lock->__spinlock); + + if (suspend_needed) + suspend (self); + return; + } +#endif + +#if defined HAS_COMPARE_AND_SWAP + do { + oldstatus = lock->__status; + if (oldstatus == 0) { + newstatus = 1; + } else { + if (self == NULL) + self = thread_self(); + wait_node.thr = self; + newstatus = (long) &wait_node; + } + wait_node.abandoned = 0; + wait_node.next = (struct wait_node *) oldstatus; + /* Make sure the store in wait_node.next completes before performing + the compare-and-swap */ + MEMORY_BARRIER(); + } while(! __compare_and_swap(&lock->__status, oldstatus, newstatus)); + + /* Suspend. Note that unlike in __pthread_lock, we don't worry + here about spurious wakeup. That's because this lock is not + used in situations where that can happen; the restart can + only come from the previous lock owner. */ + + if (oldstatus != 0) + suspend(self); + + READ_MEMORY_BARRIER(); +#endif +} + +/* Timed-out lock operation; returns 0 to indicate timeout. */ + +int __pthread_alt_timedlock(struct _pthread_fastlock * lock, + pthread_descr self, const struct timespec *abstime) +{ + long oldstatus = 0; +#if defined HAS_COMPARE_AND_SWAP + long newstatus; +#endif + struct wait_node *p_wait_node = wait_node_alloc(); + + /* Out of memory, just give up and do ordinary lock. */ + if (p_wait_node == 0) { + __pthread_alt_lock(lock, self); + return 1; + } + +#if defined TEST_FOR_COMPARE_AND_SWAP + if (!__pthread_has_cas) +#endif +#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP + { + __pthread_acquire(&lock->__spinlock); + + if (lock->__status == 0) + lock->__status = 1; + else { + if (self == NULL) + self = thread_self(); + + p_wait_node->abandoned = 0; + p_wait_node->next = (struct wait_node *) lock->__status; + p_wait_node->thr = self; + lock->__status = (long) p_wait_node; + oldstatus = 1; /* force suspend */ + } + + __pthread_release(&lock->__spinlock); + goto suspend; + } +#endif + +#if defined HAS_COMPARE_AND_SWAP + do { + oldstatus = lock->__status; + if (oldstatus == 0) { + newstatus = 1; + } else { + if (self == NULL) + self = thread_self(); + p_wait_node->thr = self; + newstatus = (long) p_wait_node; + } + p_wait_node->abandoned = 0; + p_wait_node->next = (struct wait_node *) oldstatus; + /* Make sure the store in wait_node.next completes before performing + the compare-and-swap */ + MEMORY_BARRIER(); + } while(! __compare_and_swap(&lock->__status, oldstatus, newstatus)); +#endif + +#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP + suspend: +#endif + + /* If we did not get the lock, do a timed suspend. If we wake up due + to a timeout, then there is a race; the old lock owner may try + to remove us from the queue. This race is resolved by us and the owner + doing an atomic testandset() to change the state of the wait node from 0 + to 1. If we succeed, then it's a timeout and we abandon the node in the + queue. If we fail, it means the owner gave us the lock. */ + + if (oldstatus != 0) { + if (timedsuspend(self, abstime) == 0) { + if (!testandset(&p_wait_node->abandoned)) + return 0; /* Timeout! */ + + /* Eat oustanding resume from owner, otherwise wait_node_free() below + will race with owner's wait_node_dequeue(). */ + suspend(self); + } + } + + wait_node_free(p_wait_node); + + READ_MEMORY_BARRIER(); + + return 1; /* Got the lock! */ +} + +void __pthread_alt_unlock(struct _pthread_fastlock *lock) +{ + struct wait_node *p_node, **pp_node, *p_max_prio, **pp_max_prio; + struct wait_node ** const pp_head = (struct wait_node **) &lock->__status; + int maxprio; + + WRITE_MEMORY_BARRIER(); + +#if defined TEST_FOR_COMPARE_AND_SWAP + if (!__pthread_has_cas) +#endif +#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP + { + __pthread_acquire(&lock->__spinlock); + } +#endif + + while (1) { + + /* If no threads are waiting for this lock, try to just + atomically release it. */ +#if defined TEST_FOR_COMPARE_AND_SWAP + if (!__pthread_has_cas) +#endif +#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP + { + if (lock->__status == 0 || lock->__status == 1) { + lock->__status = 0; + break; + } + } +#endif + +#if defined TEST_FOR_COMPARE_AND_SWAP + else +#endif + +#if defined HAS_COMPARE_AND_SWAP + { + long oldstatus = lock->__status; + if (oldstatus == 0 || oldstatus == 1) { + if (__compare_and_swap_with_release_semantics (&lock->__status, oldstatus, 0)) + break; + else + continue; + } + } +#endif + + /* Process the entire queue of wait nodes. Remove all abandoned + wait nodes and put them into the global free queue, and + remember the one unabandoned node which refers to the thread + having the highest priority. */ + + pp_max_prio = pp_node = pp_head; + p_max_prio = p_node = *pp_head; + maxprio = INT_MIN; + + READ_MEMORY_BARRIER(); /* Prevent access to stale data through p_node */ + + while (p_node != (struct wait_node *) 1) { + int prio; + + if (p_node->abandoned) { + /* Remove abandoned node. */ +#if defined TEST_FOR_COMPARE_AND_SWAP + if (!__pthread_has_cas) +#endif +#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP + *pp_node = p_node->next; +#endif +#if defined TEST_FOR_COMPARE_AND_SWAP + else +#endif +#if defined HAS_COMPARE_AND_SWAP + wait_node_dequeue(pp_head, pp_node, p_node); +#endif + wait_node_free(p_node); + /* Note that the next assignment may take us to the beginning + of the queue, to newly inserted nodes, if pp_node == pp_head. + In that case we need a memory barrier to stabilize the first of + these new nodes. */ + p_node = *pp_node; + if (pp_node == pp_head) + READ_MEMORY_BARRIER(); /* No stale reads through p_node */ + continue; + } else if ((prio = p_node->thr->p_priority) >= maxprio) { + /* Otherwise remember it if its thread has a higher or equal priority + compared to that of any node seen thus far. */ + maxprio = prio; + pp_max_prio = pp_node; + p_max_prio = p_node; + } + + /* This canno6 jump backward in the list, so no further read + barrier is needed. */ + pp_node = &p_node->next; + p_node = *pp_node; + } + + /* If all threads abandoned, go back to top */ + if (maxprio == INT_MIN) + continue; + + /* Now we want to to remove the max priority thread's wait node from + the list. Before we can do this, we must atomically try to change the + node's abandon state from zero to nonzero. If we succeed, that means we + have the node that we will wake up. If we failed, then it means the + thread timed out and abandoned the node in which case we repeat the + whole unlock operation. */ + + if (!testandset(&p_max_prio->abandoned)) { +#if defined TEST_FOR_COMPARE_AND_SWAP + if (!__pthread_has_cas) +#endif +#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP + *pp_max_prio = p_max_prio->next; +#endif +#if defined TEST_FOR_COMPARE_AND_SWAP + else +#endif +#if defined HAS_COMPARE_AND_SWAP + wait_node_dequeue(pp_head, pp_max_prio, p_max_prio); +#endif + restart(p_max_prio->thr); + break; + } + } + +#if defined TEST_FOR_COMPARE_AND_SWAP + if (!__pthread_has_cas) +#endif +#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP + { + __pthread_release(&lock->__spinlock); + } +#endif +} + + +/* Compare-and-swap emulation with a spinlock */ + +#ifdef TEST_FOR_COMPARE_AND_SWAP +int __pthread_has_cas = 0; +#endif + +#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP + +int __pthread_compare_and_swap(long * ptr, long oldval, long newval, + int * spinlock) +{ + int res; + + __pthread_acquire(spinlock); + + if (*ptr == oldval) { + *ptr = newval; res = 1; + } else { + res = 0; + } + + __pthread_release(spinlock); + + return res; +} + +#endif + +/* The retry strategy is as follows: + - We test and set the spinlock MAX_SPIN_COUNT times, calling + sched_yield() each time. This gives ample opportunity for other + threads with priority >= our priority to make progress and + release the spinlock. + - If a thread with priority < our priority owns the spinlock, + calling sched_yield() repeatedly is useless, since we're preventing + the owning thread from making progress and releasing the spinlock. + So, after MAX_SPIN_LOCK attemps, we suspend the calling thread + using nanosleep(). This again should give time to the owning thread + for releasing the spinlock. + Notice that the nanosleep() interval must not be too small, + since the kernel does busy-waiting for short intervals in a realtime + process (!). The smallest duration that guarantees thread + suspension is currently 2ms. + - When nanosleep() returns, we try again, doing MAX_SPIN_COUNT + sched_yield(), then sleeping again if needed. */ + +static void __pthread_acquire(int * spinlock) +{ + int cnt = 0; + struct timespec tm; + + READ_MEMORY_BARRIER(); + + while (testandset(spinlock)) { + if (cnt < MAX_SPIN_COUNT) { + sched_yield(); + cnt++; + } else { + tm.tv_sec = 0; + tm.tv_nsec = SPIN_SLEEP_DURATION; + nanosleep(&tm, NULL); + cnt = 0; + } + } +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/spinlock.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/spinlock.h new file mode 100644 index 00000000..7117898f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/spinlock.h @@ -0,0 +1,218 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1998 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +#include + + +/* There are 2 compare and swap synchronization primitives with + different semantics: + + 1. compare_and_swap, which has acquire semantics (i.e. it + completes befor subsequent writes.) + 2. compare_and_swap_with_release_semantics, which has release + semantics (it completes after previous writes.) + + For those platforms on which they are the same. HAS_COMPARE_AND_SWAP + should be defined. For those platforms on which they are different, + HAS_COMPARE_AND_SWAP_WITH_RELEASE_SEMANTICS has to be defined. */ + +#ifndef HAS_COMPARE_AND_SWAP +#ifdef HAS_COMPARE_AND_SWAP_WITH_RELEASE_SEMANTICS +#define HAS_COMPARE_AND_SWAP +#endif +#endif + +#if defined(TEST_FOR_COMPARE_AND_SWAP) + +extern int __pthread_has_cas; +extern int __pthread_compare_and_swap(long * ptr, long oldval, long newval, + int * spinlock); + +static __inline__ int compare_and_swap(long * ptr, long oldval, long newval, + int * spinlock) +{ + if (__builtin_expect (__pthread_has_cas, 1)) + return __compare_and_swap(ptr, oldval, newval); + else + return __pthread_compare_and_swap(ptr, oldval, newval, spinlock); +} + +#elif defined(HAS_COMPARE_AND_SWAP) + +#ifdef IMPLEMENT_TAS_WITH_CAS +#define testandset(p) !__compare_and_swap((long int *) p, 0, 1) +#endif + +#ifdef HAS_COMPARE_AND_SWAP_WITH_RELEASE_SEMANTICS + +static __inline__ int +compare_and_swap_with_release_semantics (long * ptr, long oldval, + long newval, int * spinlock) +{ + return __compare_and_swap_with_release_semantics (ptr, oldval, + newval); +} + +#endif + +static __inline__ int compare_and_swap(long * ptr, long oldval, long newval, + int * spinlock) +{ + return __compare_and_swap(ptr, oldval, newval); +} + +#else + +extern int __pthread_compare_and_swap(long * ptr, long oldval, long newval, + int * spinlock); + +static __inline__ int compare_and_swap(long * ptr, long oldval, long newval, + int * spinlock) +{ + return __pthread_compare_and_swap(ptr, oldval, newval, spinlock); +} + +#endif + +#ifndef HAS_COMPARE_AND_SWAP_WITH_RELEASE_SEMANTICS +#define compare_and_swap_with_release_semantics compare_and_swap +#define __compare_and_swap_with_release_semantics __compare_and_swap +#endif + +/* Internal locks */ + +extern void internal_function __pthread_lock(struct _pthread_fastlock * lock, + pthread_descr self); +extern int __pthread_unlock(struct _pthread_fastlock *lock); + +static __inline__ void __pthread_init_lock(struct _pthread_fastlock * lock) +{ + lock->__status = 0; + lock->__spinlock = __LT_SPINLOCK_INIT; +} + +static __inline__ int __pthread_trylock (struct _pthread_fastlock * lock) +{ +#if defined TEST_FOR_COMPARE_AND_SWAP + if (!__pthread_has_cas) +#endif +#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP + { + return (testandset(&lock->__spinlock) ? EBUSY : 0); + } +#endif + +#if defined HAS_COMPARE_AND_SWAP + do { + if (lock->__status != 0) return EBUSY; + } while(! __compare_and_swap(&lock->__status, 0, 1)); + return 0; +#endif +} + +/* Variation of internal lock used for pthread_mutex_t, supporting + timed-out waits. Warning: do not mix these operations with the above ones + over the same lock object! */ + +extern void __pthread_alt_lock(struct _pthread_fastlock * lock, + pthread_descr self); + +extern int __pthread_alt_timedlock(struct _pthread_fastlock * lock, + pthread_descr self, const struct timespec *abstime); + +extern void __pthread_alt_unlock(struct _pthread_fastlock *lock); + +static __inline__ void __pthread_alt_init_lock(struct _pthread_fastlock * lock) +{ + lock->__status = 0; + lock->__spinlock = __LT_SPINLOCK_INIT; +} + +static __inline__ int __pthread_alt_trylock (struct _pthread_fastlock * lock) +{ +#if defined TEST_FOR_COMPARE_AND_SWAP + if (!__pthread_has_cas) +#endif +#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP + { + int res = EBUSY; + + if (testandset(&lock->__spinlock) == 0) + { + if (lock->__status == 0) + { + lock->__status = 1; + WRITE_MEMORY_BARRIER(); + res = 0; + } + lock->__spinlock = __LT_SPINLOCK_INIT; + } + return res; + } +#endif + +#if defined HAS_COMPARE_AND_SWAP + do { + if (lock->__status != 0) return EBUSY; + } while(! compare_and_swap(&lock->__status, 0, 1, &lock->__spinlock)); + return 0; +#endif +} + +/* Operations on pthread_atomic, which is defined in internals.h */ + +static __inline__ long atomic_increment(struct pthread_atomic *pa) +{ + long oldval; + + do { + oldval = pa->p_count; + } while (!compare_and_swap(&pa->p_count, oldval, oldval + 1, &pa->p_spinlock)); + + return oldval; +} + + +static __inline__ long atomic_decrement(struct pthread_atomic *pa) +{ + long oldval; + + do { + oldval = pa->p_count; + } while (!compare_and_swap(&pa->p_count, oldval, oldval - 1, &pa->p_spinlock)); + + return oldval; +} + + +static __inline__ void +__pthread_set_own_extricate_if (pthread_descr self, pthread_extricate_if *peif) +{ + /* Only store a non-null peif if the thread has cancellation enabled. + Otherwise pthread_cancel will unconditionally call the extricate handler, + and restart the thread giving rise to forbidden spurious wakeups. */ + if (peif == NULL + || THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) + { + /* If we are removing the extricate interface, we need to synchronize + against pthread_cancel so that it does not continue with a pointer + to a deallocated pthread_extricate_if struct! The thread lock + is (ab)used for this synchronization purpose. */ + if (peif == NULL) + __pthread_lock (THREAD_GETMEM(self, p_lock), self); + THREAD_SETMEM(self, p_extricate, peif); + if (peif == NULL) + __pthread_unlock (THREAD_GETMEM(self, p_lock)); + } +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/alpha/pt-machine.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/alpha/pt-machine.h new file mode 100644 index 00000000..97c38394 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/alpha/pt-machine.h @@ -0,0 +1,127 @@ +/* Machine-dependent pthreads configuration and inline functions. + Alpha version. + Copyright (C) 1996, 1997, 1998, 2000, 2002, 2003 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _PT_MACHINE_H +#define _PT_MACHINE_H 1 + +#include + +#ifndef PT_EI +# define PT_EI __extern_always_inline +#endif + +#ifdef __linux__ +# include +#else +# include +#endif + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#define CURRENT_STACK_FRAME stack_pointer +register char *stack_pointer __asm__("$30"); + + +/* Memory barrier; default is to do nothing */ +#define MEMORY_BARRIER() __asm__ __volatile__("mb" : : : "memory") +/* Write barrier. */ +#define WRITE_MEMORY_BARRIER() __asm__ __volatile__("wmb" : : : "memory") + + +/* Spinlock implementation; required. */ +PT_EI long int +testandset (int *spinlock) +{ + long int ret, temp; + + __asm__ __volatile__( + "/* Inline spinlock test & set */\n" + "1:\t" + "ldl_l %0,%3\n\t" + "bne %0,2f\n\t" + "or $31,1,%1\n\t" + "stl_c %1,%2\n\t" + "beq %1,1b\n" + "2:\tmb\n" + "/* End spinlock test & set */" + : "=&r"(ret), "=&r"(temp), "=m"(*spinlock) + : "m"(*spinlock) + : "memory"); + + return ret; +} + + +/* Begin allocating thread stacks at this address. Default is to allocate + them just below the initial program stack. */ +#define THREAD_STACK_START_ADDRESS 0x40000000000 + + +/* Return the thread descriptor for the current thread. */ +#define THREAD_SELF \ +({ \ + register pthread_descr __self __asm__("$0"); \ + __asm__ ("call_pal %1" : "=r"(__self) : "i"(PAL_rduniq)); \ + __self; \ +}) + +/* Initialize the thread-unique value. */ +#define INIT_THREAD_SELF(descr, nr) \ +{ \ + register pthread_descr __self __asm__("$16") = (descr); \ + __asm__ __volatile__ ("call_pal %1" : : "r"(__self), "i"(PAL_wruniq)); \ +} + + +/* Compare-and-swap for semaphores. */ + +#define HAS_COMPARE_AND_SWAP +PT_EI int +__compare_and_swap (long int *p, long int oldval, long int newval) +{ + long int ret; + + __asm__ __volatile__ ( + "/* Inline compare & swap */\n" + "1:\t" + "ldq_l %0,%4\n\t" + "cmpeq %0,%2,%0\n\t" + "beq %0,2f\n\t" + "mov %3,%0\n\t" + "stq_c %0,%1\n\t" + "beq %0,1b\n\t" + "2:\tmb\n" + "/* End compare & swap */" + : "=&r"(ret), "=m"(*p) + : "r"(oldval), "r"(newval), "m"(*p) + : "memory"); + + return ret; +} + +/* We want the OS to assign stack addresses. */ +#define FLOATING_STACKS 1 + +/* Maximum size of the stack if the rlimit is unlimited. */ +#define ARCH_STACK_MAX_SIZE 32*1024*1024 + +#endif /* pt-machine.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/arm/pt-machine.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/arm/pt-machine.h new file mode 100644 index 00000000..583eb687 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/arm/pt-machine.h @@ -0,0 +1,69 @@ +/* Machine-dependent pthreads configuration and inline functions. + ARM version. + Copyright (C) 1997, 1998, 2000, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Philip Blundell . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _PT_MACHINE_H +#define _PT_MACHINE_H 1 + +#include + +#ifndef PT_EI +# define PT_EI __extern_always_inline +#endif + +/* This will not work on ARM1 or ARM2 because SWP is lacking on those + machines. Unfortunately we have no way to detect this at compile + time; let's hope nobody tries to use one. */ + +/* Spinlock implementation; required. */ +PT_EI long int testandset (int *spinlock); +PT_EI long int testandset (int *spinlock) +{ + register unsigned int ret; + +#if defined(__thumb__) + void *pc; + __asm__ __volatile__( + ".align 0\n" + "\tbx pc\n" + "\tnop\n" + "\t.arm\n" + "\tswp %0, %2, [%3]\n" + "\torr %1, pc, #1\n" + "\tbx %1\n" + "\t.force_thumb" + : "=r"(ret), "=r"(pc) + : "0"(1), "r"(spinlock)); +#else + __asm__ __volatile__("swp %0, %1, [%2]" + : "=r"(ret) + : "0"(1), "r"(spinlock)); +#endif + + return ret; +} + + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#define CURRENT_STACK_FRAME stack_pointer +register char * stack_pointer __asm__ ("sp"); + +#endif /* pt-machine.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/avr32/pt-machine.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/avr32/pt-machine.h new file mode 100644 index 00000000..5735d0ea --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/avr32/pt-machine.h @@ -0,0 +1,73 @@ +/* Machine-dependent pthreads configuration and inline functions. + * + * Copyright (C) 2005-2007 Atmel Corporation + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License. See the file "COPYING.LIB" in the main directory of this + * archive for more details. + */ +#ifndef _PT_MACHINE_H +#define _PT_MACHINE_H 1 + +#include + +#ifndef PT_EI +# define PT_EI __extern_always_inline +#endif + +static __inline__ int +_test_and_set (int *p, int v) +{ + int result; + + __asm__ __volatile__( + "/* Inline test and set */\n" + " xchg %[old], %[mem], %[new]" + : [old] "=&r"(result) + : [mem] "r"(p), [new] "r"(v) + : "memory"); + + return result; +} + +extern long int testandset (int *spinlock); +extern int __compare_and_swap (long int *p, long int oldval, long int newval); + +/* Spinlock implementation; required. */ +PT_EI long int +testandset (int *spinlock) +{ + return _test_and_set(spinlock, 1); +} + + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#define CURRENT_STACK_FRAME stack_pointer +register char * stack_pointer __asm__ ("sp"); + +/* Compare-and-swap for semaphores. */ + +#define HAS_COMPARE_AND_SWAP +PT_EI int +__compare_and_swap(long int *p, long int oldval, long int newval) +{ + long int result; + + __asm__ __volatile__( + "/* Inline compare and swap */\n" + "1: ssrf 5\n" + " ld.w %[result], %[mem]\n" + " eor %[result], %[old]\n" + " brne 2f\n" + " stcond %[mem], %[new]\n" + " brne 1b\n" + "2:" + : [result] "=&r"(result), [mem] "=m"(*p) + : "m"(*p), [new] "r"(newval), [old] "r"(oldval) + : "cc", "memory"); + + return result == 0; +} + +#endif /* pt-machine.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/bfin/pt-machine.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/bfin/pt-machine.h new file mode 100644 index 00000000..e81ecffb --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/bfin/pt-machine.h @@ -0,0 +1,76 @@ +/* Machine-dependent pthreads configuration and inline functions. + Copyright (C) 1996, 1998, 2000, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If + not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef _PT_MACHINE_H +#define _PT_MACHINE_H 1 + +#include + +#ifndef PT_EI +# define PT_EI __extern_always_inline +#endif + +#include + +/* Spinlock implementation; required. */ +/* The semantics of the TESTSET instruction cannot be guaranteed. We cannot + easily move all locks used by linux kernel to non-cacheable memory. + EXCPT 0x4 is used to trap into kernel to do the atomic testandset. + It's ugly. But it's the only thing we can do now. + The handler of EXCPT 0x4 expects the address of the lock is passed through + R0. And the result is returned by R0. */ +PT_EI long int +testandset (int *spinlock) +{ + long int res; + + __asm__ __volatile__ ( + "CALL (%4);" + : "=q0" (res), "=m" (*spinlock) + : "qA" (spinlock), "m" (*spinlock), "a" (ATOMIC_XCHG32), "q1" (1) + : "RETS", "cc", "memory"); + + return res; +} + +#define HAS_COMPARE_AND_SWAP +PT_EI int +__compare_and_swap (long int *p, long int oldval, long int newval) +{ + long int readval; + __asm__ __volatile__ ( + "CALL (%5);" + : "=q0" (readval), "=m" (*p) + : "qA" (p), + "q1" (oldval), + "q2" (newval), + "a" (ATOMIC_CAS32), + "m" (*p) + : "RETS", "memory", "cc"); + return readval == oldval; +} + +#ifdef SHARED +# define PTHREAD_STATIC_FN_REQUIRE(name) +#else +# define PTHREAD_STATIC_FN_REQUIRE(name) __asm__ (".globl " "_"#name); +#endif + +#endif /* pt-machine.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/cris/pt-machine.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/cris/pt-machine.h new file mode 100644 index 00000000..6d626fb4 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/cris/pt-machine.h @@ -0,0 +1,70 @@ +/* Machine-dependent pthreads configuration and inline functions. + CRIS version. + Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ +#ifndef _PT_MACHINE_H +#define _PT_MACHINE_H 1 + +#include + +#ifndef PT_EI +# define PT_EI __extern_always_inline +#endif + +PT_EI long int +testandset (int *spinlock) +{ + register unsigned long int ret; + + /* Note the use of a dummy output of *spinlock to expose the write. The + memory barrier is to stop *other* writes being moved past this code. */ + +#ifdef __arch_v32 + __asm__ __volatile__("clearf p\n" + "0:\n\t" + "movu.b [%2],%0\n\t" + "ax\n\t" + "move.b %3,[%2]\n\t" + "bcs 0b\n\t" + "clearf p" + : "=&r" (ret), "=m" (*spinlock) + : "r" (spinlock), "r" ((int) 1), "m" (*spinlock) + : "memory"); +#else /* not __arch_v32 */ + __asm__ __volatile__("clearf\n" + "0:\n\t" + "movu.b [%2],%0\n\t" + "ax\n\t" + "move.b %3,[%2]\n\t" + "bwf 0b\n\t" + "clearf" + : "=&r" (ret), "=m" (*spinlock) + : "r" (spinlock), "r" ((int) 1), "m" (*spinlock) + : "memory"); +#endif /* __arch_v32 */ + return ret; +} + + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. + I don't trust register variables, so let's do this the safe way. */ +#define CURRENT_STACK_FRAME \ + ({ char *sp; __asm__ ("move.d $sp,%0" : "=rm" (sp)); sp; }) + +#endif /* pt-machine.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/frv/pt-machine.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/frv/pt-machine.h new file mode 100644 index 00000000..9c9d0d76 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/frv/pt-machine.h @@ -0,0 +1,70 @@ +/* Machine-dependent pthreads configuration and inline functions. + FR-V version. + Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Alexandre Oliva + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If + not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef _PT_MACHINE_H +#define _PT_MACHINE_H 1 + +#include + +#ifndef __ASSEMBLER__ + +#ifndef PT_EI +# define PT_EI __extern_always_inline +#endif + +/* Spinlock implementation; required. */ +PT_EI long int +testandset (int *spinlock) +{ + int i = 1; + __asm__ ("swap%I0 %M0, %1" : "+m"(*(volatile int *)spinlock), "+r"(i)); + return i; +} + +/* We want the OS to assign stack addresses. */ +#define FLOATING_STACKS 1 + +/* This symbol is defined by the ABI as the stack size requested by + the main program. */ +extern char __stacksize; +#define ARCH_STACK_MAX_SIZE ((unsigned long)&__stacksize) + +/* Memory barrier; default is to do nothing */ +#define MEMORY_BARRIER() __asm__ __volatile__("membar" : : : "memory") +/* Write barrier. */ +#define WRITE_MEMORY_BARRIER() __asm__ __volatile__("membar" : : : "memory") + +/* Return the thread descriptor for the current thread. */ +register struct _pthread_descr_struct *THREAD_SELF __asm__ ("gr29"); +#define THREAD_SELF THREAD_SELF + +/* Initialize the thread-unique value. */ +#define INIT_THREAD_SELF(descr, nr) \ + (THREAD_SELF = descr) + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#define CURRENT_STACK_FRAME stack_pointer +register char * stack_pointer __asm__ ("sp"); + +#endif + +#endif /* pt-machine.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/h8300/pt-machine.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/h8300/pt-machine.h new file mode 100644 index 00000000..121f496d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/h8300/pt-machine.h @@ -0,0 +1,58 @@ +/* Machine-dependent pthreads configuration and inline functions. + H8/300 version. + Copyright (C) 1996, 1998, 2000, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If + not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef _PT_MACHINE_H +#define _PT_MACHINE_H 1 + +#include + +#ifndef PT_EI +# define PT_EI __extern_always_inline +#endif + +/* Spinlock implementation; required. */ +PT_EI long int +testandset (int *spinlock) +{ + char ret; + + __asm__ __volatile__( + "sub.w %0,%0\n\t" + "stc ccr,@-sp\n\t" + "orc #0x80,ccr\n\t" + "bld #0,@%2\n\t" + "bset #0,@%2\n\t" + "rotxl.w %0\n\t" + "ldc @sp+,ccr\n\t" + :"=r"(ret),"=m"(*spinlock) + :"g"(spinlock) + :"cc"); + + return ret; +} + + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#define CURRENT_STACK_FRAME stack_pointer +register char * stack_pointer __asm__ ("%sp"); + +#endif /* pt-machine.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/i386/pt-machine.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/i386/pt-machine.h new file mode 100644 index 00000000..a6256c58 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/i386/pt-machine.h @@ -0,0 +1,147 @@ +/* Machine-dependent pthreads configuration and inline functions. + i386 version. + Copyright (C) 1996-2001, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _PT_MACHINE_H +#define _PT_MACHINE_H 1 + +#include + +#ifndef __ASSEMBLER__ +#ifndef PT_EI +# define PT_EI __extern_always_inline __attribute__((visibility("hidden"))) +#endif + +extern long int testandset (int *spinlock); +extern int __compare_and_swap (long int *p, long int oldval, long int newval); + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#define CURRENT_STACK_FRAME __builtin_frame_address (0) + + +/* See if we can optimize for newer cpus... */ +#if defined __GNUC__ && __GNUC__ >= 2 && \ + (defined __i486__ || defined __pentium__ || defined __pentiumpro__ || defined __pentium4__ || \ + defined __athlon__ || defined __k8__) + +/* Spinlock implementation; required. */ +PT_EI long int +testandset (int *spinlock) +{ + long int ret; + + __asm__ __volatile__ ( + "xchgl %0, %1" + : "=r" (ret), "=m" (*spinlock) + : "0" (1), "m" (*spinlock) + : "memory"); + + return ret; +} + +/* Compare-and-swap for semaphores. It's always available on i686. */ +#define HAS_COMPARE_AND_SWAP + +PT_EI int +__compare_and_swap (long int *p, long int oldval, long int newval) +{ + char ret; + long int readval; + + __asm__ __volatile__ ("lock; cmpxchgl %3, %1; sete %0" + : "=q" (ret), "=m" (*p), "=a" (readval) + : "r" (newval), "m" (*p), "a" (oldval) + : "memory"); + return ret; +} + +#if defined(__ASSUME_LDT_WORKS) && __ASSUME_LDT_WORKS > 0 +#include "useldt.h" +#endif + +/* The P4 and above really want some help to prevent overheating. */ +#define BUSY_WAIT_NOP __asm__ ("rep; nop") + + +#else /* Generic i386 implementation */ + +extern int compare_and_swap_is_available (void); + +/* Spinlock implementation; required. */ +PT_EI long int +testandset (int *spinlock) +{ + long int ret; + + __asm__ __volatile__( + "xchgl %0, %1" + : "=r"(ret), "=m"(*spinlock) + : "0"(1), "m"(*spinlock) + : "memory"); + + return ret; +} + + +/* Compare-and-swap for semaphores. + Available on the 486 and above, but not on the 386. + We test dynamically whether it's available or not. */ + +#define HAS_COMPARE_AND_SWAP +#define TEST_FOR_COMPARE_AND_SWAP + +PT_EI int +__compare_and_swap (long int *p, long int oldval, long int newval) +{ + char ret; + long int readval; + + __asm__ __volatile__ ("lock; cmpxchgl %3, %1; sete %0" + : "=q" (ret), "=m" (*p), "=a" (readval) + : "r" (newval), "m" (*p), "a" (oldval) + : "memory"); + return ret; +} + +PT_EI int +compare_and_swap_is_available (void) +{ + int changed; + int oldflags; + /* get EFLAGS */ + __asm__ __volatile__ ("pushfl; popl %0" : "=r" (oldflags) : ); + /* Flip AC bit in EFLAGS. */ + __asm__ __volatile__ ("pushl %0; popfl" : : "r" (oldflags ^ 0x40000) : "cc"); + /* reread EFLAGS */ + __asm__ __volatile__ ("pushfl; popl %0" : "=r" (changed) : ); + /* See if bit changed. */ + changed = (changed ^ oldflags) & 0x40000; + /* Restore EFLAGS. */ + __asm__ __volatile__ ("pushl %0; popfl" : : "r" (oldflags) : "cc"); + /* If the AC flag did not change, it's a 386 and it lacks cmpxchg. + Otherwise, it's a 486 or above and it has cmpxchg. */ + return changed != 0; +} +#endif /* Generic i386 implementation */ + +#endif /* __ASSEMBLER__ */ + +#endif /* pt-machine.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/i386/tls.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/i386/tls.h new file mode 100644 index 00000000..8534cab8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/i386/tls.h @@ -0,0 +1,185 @@ +/* Definition for thread-local data handling. linuxthreads/i386 version. + Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _TLS_H +#define _TLS_H + +# include + +#ifndef __ASSEMBLER__ +# include +# include +# include + +/* Type for the dtv. */ +typedef union dtv +{ + size_t counter; + void *pointer; +} dtv_t; + + +typedef struct +{ + void *tcb; /* Pointer to the TCB. Not necessary the + thread descriptor used by libpthread. */ + dtv_t *dtv; + void *self; /* Pointer to the thread descriptor. */ +} tcbhead_t; +#endif + + +/* We can support TLS only if the floating-stack support is available. */ +#if defined FLOATING_STACKS && defined HAVE_TLS_SUPPORT + +/* Signal that TLS support is available. */ +//# define USE_TLS 1 + +# ifndef __ASSEMBLER__ +/* Get system call information. */ +# include + + +/* Get the thread descriptor definition. */ +# include + +/* This is the size of the initial TCB. */ +# define TLS_INIT_TCB_SIZE sizeof (tcbhead_t) + +/* Alignment requirements for the initial TCB. */ +# define TLS_INIT_TCB_ALIGN __alignof__ (tcbhead_t) + +/* This is the size of the TCB. */ +# define TLS_TCB_SIZE sizeof (struct _pthread_descr_struct) + +/* Alignment requirements for the TCB. */ +# define TLS_TCB_ALIGN __alignof__ (struct _pthread_descr_struct) + +/* The TCB can have any size and the memory following the address the + thread pointer points to is unspecified. Allocate the TCB there. */ +# define TLS_TCB_AT_TP 1 + + +/* Install the dtv pointer. The pointer passed is to the element with + index -1 which contain the length. */ +# define INSTALL_DTV(descr, dtvp) \ + ((tcbhead_t *) (descr))->dtv = (dtvp) + 1 + +/* Install new dtv for current thread. */ +# define INSTALL_NEW_DTV(dtv) \ + ({ struct _pthread_descr_struct *__descr; \ + THREAD_SETMEM (__descr, p_header.data.dtvp, (dtv)); }) + +/* Return dtv of given thread descriptor. */ +# define GET_DTV(descr) \ + (((tcbhead_t *) (descr))->dtv) + +# ifdef __PIC__ +# define TLS_EBX_ARG "r" +# define TLS_LOAD_EBX "xchgl %3, %%ebx\n\t" +# else +# define TLS_EBX_ARG "b" +# define TLS_LOAD_EBX +# endif + +# define TLS_DO_MODIFY_LDT(descr, nr) \ +({ \ + struct modify_ldt_ldt_s ldt_entry = \ + { nr, (unsigned long int) (descr), 0xfffff /* 4GB in pages */, \ + 1, 0, 0, 1, 0, 1, 0 }; \ + int result; \ + __asm__ __volatile__ (TLS_LOAD_EBX \ + "int $0x80\n\t" \ + TLS_LOAD_EBX \ + : "=a" (result) \ + : "0" (__NR_modify_ldt), \ + /* The extra argument with the "m" constraint is necessary \ + to let the compiler know that we are accessing LDT_ENTRY \ + here. */ \ + "m" (ldt_entry), TLS_EBX_ARG (1), "c" (&ldt_entry), \ + "d" (sizeof (ldt_entry))); \ + __builtin_expect (result, 0) != 0 ? -1 : nr * 8 + 7; \ +}) + +# define TLS_DO_SET_THREAD_AREA(descr, secondcall) \ +({ \ + struct modify_ldt_ldt_s ldt_entry = \ + { -1, (unsigned long int) (descr), 0xfffff /* 4GB in pages */, \ + 1, 0, 0, 1, 0, 1, 0 }; \ + int result; \ + if (secondcall) \ + ldt_entry.entry_number = ({ int _gs; \ + __asm__ ("movw %%gs, %w0" : "=q" (_gs)); \ + (_gs & 0xffff) >> 3; }); \ + __asm__ __volatile__ (TLS_LOAD_EBX \ + "int $0x80\n\t" \ + TLS_LOAD_EBX \ + : "=a" (result), "=m" (ldt_entry.entry_number) \ + : "0" (__NR_set_thread_area), \ + /* The extra argument with the "m" constraint is necessary \ + to let the compiler know that we are accessing LDT_ENTRY \ + here. */ \ + TLS_EBX_ARG (&ldt_entry), "m" (ldt_entry)); \ + __builtin_expect (result, 0) == 0 ? ldt_entry.entry_number * 8 + 3 : -1; \ +}) + +# ifdef __ASSUME_SET_THREAD_AREA_SYSCALL +# define TLS_SETUP_GS_SEGMENT(descr, secondcall) \ + TLS_DO_SET_THREAD_AREA (descr, firstcall) +# elif defined __NR_set_thread_area +# define TLS_SETUP_GS_SEGMENT(descr, secondcall) \ + ({ int __seg = TLS_DO_SET_THREAD_AREA (descr, secondcall); \ + __seg == -1 ? TLS_DO_MODIFY_LDT (descr, 0) : __seg; }) +# else +# define TLS_SETUP_GS_SEGMENT(descr, secondcall) \ + TLS_DO_MODIFY_LDT ((descr), 0) +# endif + +/* Code to initially initialize the thread pointer. This might need + special attention since 'errno' is not yet available and if the + operation can cause a failure 'errno' must not be touched. */ +# define TLS_INIT_TP(descr, secondcall) \ + ({ \ + void *_descr = (descr); \ + tcbhead_t *head = _descr; \ + int __gs; \ + \ + head->tcb = _descr; \ + /* For now the thread descriptor is at the same address. */ \ + head->self = _descr; \ + \ + __gs = TLS_SETUP_GS_SEGMENT (_descr, secondcall); \ + if (__builtin_expect (__gs, 7) != -1) \ + { \ + __asm__ ("movw %w0, %%gs" : : "q" (__gs)); \ + __gs = 0; \ + } \ + __gs; \ + }) + + +/* Return the address of the dtv for the current thread. */ +# define THREAD_DTV() \ + ({ struct _pthread_descr_struct *__descr; \ + THREAD_GETMEM (__descr, p_header.data.dtvp); }) + +# endif /* FLOATING_STACKS && HAVE_TLS_SUPPORT */ +#endif /* __ASSEMBLER__ */ + +#endif /* tls.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/i386/useldt.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/i386/useldt.h new file mode 100644 index 00000000..ca5677cc --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/i386/useldt.h @@ -0,0 +1,307 @@ +/* Special definitions for ix86 machine using segment register based + thread descriptor. + Copyright (C) 1998, 2000, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef __ASSEMBLER__ +#include /* For offsetof. */ +#include /* For abort(). */ + + +/* We don't want to include the kernel header. So duplicate the + information. */ + +/* Structure passed on `modify_ldt' call. */ +struct modify_ldt_ldt_s +{ + unsigned int entry_number; + unsigned long int base_addr; + unsigned int limit; + unsigned int seg_32bit:1; + unsigned int contents:2; + unsigned int read_exec_only:1; + unsigned int limit_in_pages:1; + unsigned int seg_not_present:1; + unsigned int useable:1; + unsigned int empty:25; +}; + +/* System call to set LDT entry. */ +extern int __modify_ldt (int, struct modify_ldt_ldt_s *, size_t); + + +/* Return the thread descriptor for the current thread. + + The contained asm must *not* be marked volatile since otherwise + assignments like + pthread_descr self = thread_self(); + do not get optimized away. */ +#define THREAD_SELF \ +({ \ + register pthread_descr __self; \ + __asm__ ("movl %%gs:%c1,%0" : "=r" (__self) \ + : "i" (offsetof (struct _pthread_descr_struct, \ + p_header.data.self))); \ + __self; \ +}) + + +/* Initialize the thread-unique value. Two possible ways to do it. */ + +#define DO_MODIFY_LDT(descr, nr) \ +({ \ + struct modify_ldt_ldt_s ldt_entry = \ + { nr, (unsigned long int) (descr), 0xfffff /* 4GB in pages */, \ + 1, 0, 0, 1, 0, 1, 0 }; \ + if (__modify_ldt (1, &ldt_entry, sizeof (ldt_entry)) != 0) \ + abort (); \ + __asm__ ("movw %w0, %%gs" : : "q" (nr * 8 + 7)); \ +}) + +#ifdef __PIC__ +# define USETLS_EBX_ARG "r" +# define USETLS_LOAD_EBX "xchgl %3, %%ebx\n\t" +#else +# define USETLS_EBX_ARG "b" +# define USETLS_LOAD_EBX +#endif + +/* When using the new set_thread_area call, we don't need to change %gs + because we inherited the value set up in the main thread by TLS setup. + We need to extract that value and set up the same segment in this + thread. */ +#if USE_TLS +# define DO_SET_THREAD_AREA_REUSE(nr) 1 +#else +/* Without TLS, we do the initialization of the main thread, where NR == 0. */ +# define DO_SET_THREAD_AREA_REUSE(nr) (!__builtin_constant_p (nr) || (nr)) +#endif +#define DO_SET_THREAD_AREA(descr, nr) \ +({ \ + int __gs; \ + if (DO_SET_THREAD_AREA_REUSE (nr)) \ + { \ + __asm__ ("movw %%gs, %w0" : "=q" (__gs)); \ + struct modify_ldt_ldt_s ldt_entry = \ + { (__gs & 0xffff) >> 3, \ + (unsigned long int) (descr), 0xfffff /* 4GB in pages */, \ + 1, 0, 0, 1, 0, 1, 0 }; \ + \ + int __result; \ + __asm__ (USETLS_LOAD_EBX \ + "movl %2, %%eax\n\t" \ + "int $0x80\n\t" \ + USETLS_LOAD_EBX \ + : "&a" (__result) \ + : USETLS_EBX_ARG (&ldt_entry), "i" (__NR_set_thread_area)); \ + if (__result == 0) \ + __asm__ ("movw %w0, %%gs" :: "q" (__gs)); \ + else \ + __gs = -1; \ + } \ + else \ + { \ + struct modify_ldt_ldt_s ldt_entry = \ + { -1, \ + (unsigned long int) (descr), 0xfffff /* 4GB in pages */, \ + 1, 0, 0, 1, 0, 1, 0 }; \ + int __result; \ + __asm__ (USETLS_LOAD_EBX \ + "movl %2, %%eax\n\t" \ + "int $0x80\n\t" \ + USETLS_LOAD_EBX \ + : "&a" (__result) \ + : USETLS_EBX_ARG (&ldt_entry), "i" (__NR_set_thread_area)); \ + if (__result == 0) \ + { \ + __gs = (ldt_entry.entry_number << 3) + 3; \ + __asm__ ("movw %w0, %%gs" : : "q" (__gs)); \ + } \ + else \ + __gs = -1; \ + } \ + __gs; \ +}) + +#if defined __ASSUME_SET_THREAD_AREA_SYSCALL +# define INIT_THREAD_SELF(descr, nr) DO_SET_THREAD_AREA (descr, nr) +#elif defined __NR_set_thread_area +# define INIT_THREAD_SELF(descr, nr) \ +({ \ + if (__builtin_expect (__have_no_set_thread_area, 0) \ + || (DO_SET_THREAD_AREA (descr, DO_SET_THREAD_AREA_REUSE (nr)) == -1 \ + && (__have_no_set_thread_area = 1))) \ + DO_MODIFY_LDT (descr, nr); \ +}) +/* Defined in pspinlock.c. */ +extern int __have_no_set_thread_area; +#else +# define INIT_THREAD_SELF(descr, nr) DO_MODIFY_LDT (descr, nr) +#endif + +/* Free resources associated with thread descriptor. */ +#ifdef __ASSUME_SET_THREAD_AREA_SYSCALL +#define FREE_THREAD(descr, nr) do { } while (0) +#elif defined __NR_set_thread_area +#define FREE_THREAD(descr, nr) \ +{ \ + int __gs; \ + __asm__ __volatile__ ("movw %%gs, %w0" : "=q" (__gs)); \ + if (__builtin_expect (__gs & 4, 0)) \ + { \ + struct modify_ldt_ldt_s ldt_entry = \ + { nr, 0, 0, 0, 0, 1, 0, 1, 0, 0 }; \ + __modify_ldt (1, &ldt_entry, sizeof (ldt_entry)); \ + } \ +} +#else +#define FREE_THREAD(descr, nr) \ +{ \ + struct modify_ldt_ldt_s ldt_entry = \ + { nr, 0, 0, 0, 0, 1, 0, 1, 0, 0 }; \ + __modify_ldt (1, &ldt_entry, sizeof (ldt_entry)); \ +} +#endif + +/* Read member of the thread descriptor directly. */ +#define THREAD_GETMEM(descr, member) \ +({ \ + __typeof__ (descr->member) __value; \ + if (sizeof (__value) == 1) \ + __asm__ __volatile__ ("movb %%gs:%P2,%b0" \ + : "=q" (__value) \ + : "0" (0), \ + "i" (offsetof (struct _pthread_descr_struct, \ + member))); \ + else if (sizeof (__value) == 4) \ + __asm__ __volatile__ ("movl %%gs:%P1,%0" \ + : "=r" (__value) \ + : "i" (offsetof (struct _pthread_descr_struct, \ + member))); \ + else \ + { \ + if (sizeof (__value) != 8) \ + /* There should not be any value with a size other than 1, 4 or 8. */\ + abort (); \ + \ + __asm__ __volatile__ ("movl %%gs:%P1,%%eax\n\t" \ + "movl %%gs:%P2,%%edx" \ + : "=A" (__value) \ + : "i" (offsetof (struct _pthread_descr_struct, \ + member)), \ + "i" (offsetof (struct _pthread_descr_struct, \ + member) + 4)); \ + } \ + __value; \ +}) + +/* Same as THREAD_GETMEM, but the member offset can be non-constant. */ +#define THREAD_GETMEM_NC(descr, member) \ +({ \ + __typeof__ (descr->member) __value; \ + if (sizeof (__value) == 1) \ + __asm__ __volatile__ ("movb %%gs:(%2),%b0" \ + : "=q" (__value) \ + : "0" (0), \ + "r" (offsetof (struct _pthread_descr_struct, \ + member))); \ + else if (sizeof (__value) == 4) \ + __asm__ __volatile__ ("movl %%gs:(%1),%0" \ + : "=r" (__value) \ + : "r" (offsetof (struct _pthread_descr_struct, \ + member))); \ + else \ + { \ + if (sizeof (__value) != 8) \ + /* There should not be any value with a size other than 1, 4 or 8. */\ + abort (); \ + \ + __asm__ __volatile__ ("movl %%gs:(%1),%%eax\n\t" \ + "movl %%gs:4(%1),%%edx" \ + : "=&A" (__value) \ + : "r" (offsetof (struct _pthread_descr_struct, \ + member))); \ + } \ + __value; \ +}) + +/* Same as THREAD_SETMEM, but the member offset can be non-constant. */ +#define THREAD_SETMEM(descr, member, value) \ +({ \ + __typeof__ (descr->member) __value = (value); \ + if (sizeof (__value) == 1) \ + __asm__ __volatile__ ("movb %0,%%gs:%P1" : \ + : "q" (__value), \ + "i" (offsetof (struct _pthread_descr_struct, \ + member))); \ + else if (sizeof (__value) == 4) \ + __asm__ __volatile__ ("movl %0,%%gs:%P1" : \ + : "r" (__value), \ + "i" (offsetof (struct _pthread_descr_struct, \ + member))); \ + else \ + { \ + if (sizeof (__value) != 8) \ + /* There should not be any value with a size other than 1, 4 or 8. */\ + abort (); \ + \ + __asm__ __volatile__ ("movl %%eax,%%gs:%P1\n\n" \ + "movl %%edx,%%gs:%P2" : \ + : "A" (__value), \ + "i" (offsetof (struct _pthread_descr_struct, \ + member)), \ + "i" (offsetof (struct _pthread_descr_struct, \ + member) + 4)); \ + } \ +}) + +/* Set member of the thread descriptor directly. */ +#define THREAD_SETMEM_NC(descr, member, value) \ +({ \ + __typeof__ (descr->member) __value = (value); \ + if (sizeof (__value) == 1) \ + __asm__ __volatile__ ("movb %0,%%gs:(%1)" : \ + : "q" (__value), \ + "r" (offsetof (struct _pthread_descr_struct, \ + member))); \ + else if (sizeof (__value) == 4) \ + __asm__ __volatile__ ("movl %0,%%gs:(%1)" : \ + : "r" (__value), \ + "r" (offsetof (struct _pthread_descr_struct, \ + member))); \ + else \ + { \ + if (sizeof (__value) != 8) \ + /* There should not be any value with a size other than 1, 4 or 8. */\ + abort (); \ + \ + __asm__ __volatile__ ("movl %%eax,%%gs:(%1)\n\t" \ + "movl %%edx,%%gs:4(%1)" : \ + : "A" (__value), \ + "r" (offsetof (struct _pthread_descr_struct, \ + member))); \ + } \ +}) +#endif + +/* We want the OS to assign stack addresses. */ +#define FLOATING_STACKS 1 + +/* Maximum size of the stack if the rlimit is unlimited. */ +#define ARCH_STACK_MAX_SIZE 8*1024*1024 diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/ia64/pt-machine.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/ia64/pt-machine.h new file mode 100644 index 00000000..668057a2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/ia64/pt-machine.h @@ -0,0 +1,135 @@ +/* Machine-dependent pthreads configuration and inline functions. + IA-64 version. + Copyright (C) 1999, 2000, 2002, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _PT_MACHINE_H +#define _PT_MACHINE_H 1 + +#include +#include + +#include +extern int __clone2 (int (*__fn) (void *__arg), void *__child_stack_base, + size_t __child_stack_size, int __flags, void *__arg, ...); + +#ifndef PT_EI +# define PT_EI __extern_always_inline +#endif + +/* Make sure gcc doesn't try to be clever and move things around on + us. We need to use _exactly_ the address the user gave us, not some + alias that contains the same information. */ +#define __atomic_fool_gcc(x) (*(volatile struct { int a[100]; } *)x) + +#ifndef ELF_MACHINE_NAME + +#define NEED_SEPARATE_REGISTER_STACK + +/* We want the OS to assign stack addresses. */ +#define FLOATING_STACKS 1 + +/* Maximum size of the stack if the rlimit is unlimited. */ +#define ARCH_STACK_MAX_SIZE 32*1024*1024 + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. + r12 (sp) is the stack pointer. */ +#define CURRENT_STACK_FRAME stack_pointer +register char *stack_pointer __asm__ ("sp"); + + +/* Register r13 (tp) is reserved by the ABI as "thread pointer". */ +struct _pthread_descr_struct; +register struct _pthread_descr_struct *__thread_self __asm__("r13"); + +/* Return the thread descriptor for the current thread. */ +#define THREAD_SELF __thread_self + +/* Initialize the thread-unique value. */ +#define INIT_THREAD_SELF(descr, nr) (__thread_self = (descr)) + + +/* Access to data in the thread descriptor is easy. */ +#define THREAD_GETMEM(descr, member) \ + ((void) sizeof (descr), THREAD_SELF->member) +#define THREAD_GETMEM_NC(descr, member) \ + ((void) sizeof (descr), THREAD_SELF->member) +#define THREAD_SETMEM(descr, member, value) \ + ((void) sizeof (descr), THREAD_SELF->member = (value)) +#define THREAD_SETMEM_NC(descr, member, value) \ + ((void) sizeof (descr), THREAD_SELF->member = (value)) + + +/* Memory barrier */ +#define MEMORY_BARRIER() __sync_synchronize () + + +#define HAS_COMPARE_AND_SWAP_WITH_RELEASE_SEMANTICS + +PT_EI int +__compare_and_swap (long int *p, long int oldval, long int newval) +{ + long int readval; + + __asm__ __volatile__ + ("mov ar.ccv=%4;;\n\t" + "cmpxchg8.acq %0=%1,%2,ar.ccv" + : "=r" (readval), "=m" (__atomic_fool_gcc (p)) + : "r"(newval), "m" (__atomic_fool_gcc (p)), "r" (oldval) + : "memory"); + return readval == oldval; +} + +PT_EI int +__compare_and_swap_with_release_semantics (long int *p, + long int oldval, + long int newval) +{ + long int readval; + + __asm__ __volatile__ + ("mov ar.ccv=%4;;\n\t" + "cmpxchg8.rel %0=%1,%2,ar.ccv" + : "=r" (readval), "=m" (__atomic_fool_gcc (p)) + : "r"(newval), "m" (__atomic_fool_gcc (p)), "r" (oldval) + : "memory"); + return readval == oldval; +} + +#endif /* ELF_MACHINE_NAME */ + +/* Spinlock implementation; required. */ +PT_EI long int +testandset (int *spinlock) +{ + long int ret; + + __asm__ __volatile__( + "xchg4 %0=%1,%2" + : "=r"(ret), "=m"(__atomic_fool_gcc (spinlock)) + : "r"(1), "m"(__atomic_fool_gcc (spinlock)) + : "memory"); + + return ret; +} + +/* Indicate that we are looping. */ +#define BUSY_WAIT_NOP __asm__ ("hint @pause") + +#endif /* pt-machine.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/ia64/tls.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/ia64/tls.h new file mode 100644 index 00000000..81b41eb7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/ia64/tls.h @@ -0,0 +1,139 @@ +/* Definitions for thread-local data handling. linuxthreads/IA-64 version. + Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _TLS_H +#define _TLS_H + +#ifndef __ASSEMBLER__ + +# include +# include +# include + +/* Type for the dtv. */ +typedef union dtv +{ + size_t counter; + struct + { + void *val; + bool is_static; + } pointer; +} dtv_t; + +#else /* __ASSEMBLER__ */ +# include +#endif /* __ASSEMBLER__ */ + +#ifdef HAVE_TLS_SUPPORT + +/* Signal that TLS support is available. */ +# define USE_TLS 1 + +# ifndef __ASSEMBLER__ + +typedef struct +{ + dtv_t *dtv; + void *private; +} tcbhead_t; + +/* This is the size of the initial TCB. */ +# define TLS_INIT_TCB_SIZE sizeof (tcbhead_t) + +/* Alignment requirements for the initial TCB. */ +# define TLS_INIT_TCB_ALIGN __alignof__ (tcbhead_t) + +/* This is the size of the TCB. */ +# define TLS_TCB_SIZE sizeof (tcbhead_t) + +/* This is the size we need before TCB. */ +# define TLS_PRE_TCB_SIZE sizeof (struct _pthread_descr_struct) + +/* Alignment requirements for the TCB. */ +# define TLS_TCB_ALIGN __alignof__ (struct _pthread_descr_struct) + +/* The DTV is allocated at the TP; the TCB is placed elsewhere. */ +# define TLS_DTV_AT_TP 1 + +/* Install the dtv pointer. The pointer passed is to the element with + index -1 which contain the length. */ +# define INSTALL_DTV(tcbp, dtvp) \ + ((tcbhead_t *) (tcbp))->dtv = (dtvp) + 1 + +/* Install new dtv for current thread. */ +# define INSTALL_NEW_DTV(DTV) \ + (((tcbhead_t *)__thread_self)->dtv = (DTV)) + +/* Return dtv of given thread descriptor. */ +# define GET_DTV(tcbp) \ + (((tcbhead_t *) (tcbp))->dtv) + +#if defined NEED_DL_SYSINFO +# define INIT_SYSINFO \ + (((tcbhead_t *) __thread_self)->private = (void *) GLRO(dl_sysinfo)) +#else +# define INIT_SYSINFO 0 +#endif + +/* Code to initially initialize the thread pointer. This might need + special attention since 'errno' is not yet available and if the + operation can cause a failure 'errno' must not be touched. */ +# define TLS_INIT_TP(tcbp, secondcall) \ + (__thread_self = (__typeof (__thread_self)) (tcbp), INIT_SYSINFO, NULL) + +/* Return the address of the dtv for the current thread. */ +# define THREAD_DTV() \ + (((tcbhead_t *)__thread_self)->dtv) + +/* Return the thread descriptor for the current thread. */ +# undef THREAD_SELF +# define THREAD_SELF (__thread_self - 1) + +# undef INIT_THREAD_SELF +# define INIT_THREAD_SELF(descr, nr) \ + (__thread_self = (struct _pthread_descr_struct *)(descr) + 1) + +# define TLS_MULTIPLE_THREADS_IN_TCB 1 + +# endif + +#else + +# ifndef __ASSEMBLER__ + +typedef struct +{ + void *tcb; + dtv_t *dtv; + void *self; + int multiple_threads; +} tcbhead_t; + +# define NONTLS_INIT_TP \ + do { \ + static const tcbhead_t nontls_init_tp = { .multiple_threads = 0 }; \ + __thread_self = (__typeof (__thread_self)) &nontls_init_tp; \ + } while (0) + +#endif + +#endif /* USE_TLS */ + +#endif /* tls.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/m68k/pt-machine.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/m68k/pt-machine.h new file mode 100644 index 00000000..f9cf5304 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/m68k/pt-machine.h @@ -0,0 +1,75 @@ +/* Machine-dependent pthreads configuration and inline functions. + m68k version. + Copyright (C) 1996, 1998, 2000, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If + not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef _PT_MACHINE_H +#define _PT_MACHINE_H 1 + +#include + +#ifndef PT_EI +# define PT_EI __extern_always_inline +#endif + +/* Spinlock implementation; required. */ +PT_EI long int +testandset (int *spinlock) +{ + char ret; + + __asm__ __volatile__( +#if !defined(__mcoldfire__) && !defined(__mcf5200__) && !defined(__m68000) + "tas %1; sne %0" +#else + "bset #7,%1; sne %0" +#endif + : "=&dm"(ret), "=m"(*spinlock) + : "m"(*spinlock) + : "cc"); + + return ret; +} + + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#define CURRENT_STACK_FRAME stack_pointer +register char * stack_pointer __asm__ ("%sp"); + + +/* Compare-and-swap for semaphores. */ + +#if !defined(__mcoldfire__) && !defined(__mcf5200__) && !defined(__mc68000) +#define HAS_COMPARE_AND_SWAP +PT_EI int +__compare_and_swap (long int *p, long int oldval, long int newval) +{ + char ret; + long int readval; + + __asm__ __volatile__ ("casl %2, %3, %1; seq %0" + : "=dm" (ret), "=m" (*p), "=d" (readval) + : "d" (newval), "m" (*p), "2" (oldval)); + + return ret; +} +#endif + +#endif /* pt-machine.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/microblaze/pt-machine.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/microblaze/pt-machine.h new file mode 100644 index 00000000..e8c03f9e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/microblaze/pt-machine.h @@ -0,0 +1,106 @@ +/* + * sysdeps/microblaze/pt-machine.h -- microblaze-specific pthread definitions + * + * Copyright (C) 2003 John Williams + * Copyright (C) 2002 NEC Electronics Corporation + * Copyright (C) 2002 Miles Bader + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + * + * Written by Miles Bader + */ + +#ifndef _PT_MACHINE_H +#define _PT_MACHINE_H 1 + +#include + +#ifndef PT_EI +# define PT_EI extern inline +#endif + +extern long int testandset (int *spinlock); +extern int __compare_and_swap (long *ptr, long old, long new); + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#define CURRENT_STACK_FRAME __stack_pointer +register char *__stack_pointer __asm__ ("r1"); + +#define HAS_COMPARE_AND_SWAP +#define HAS_COMPARE_AND_SWAP_WITH_RELEASE_SEMANTICS +#define IMPLEMENT_TAS_WITH_CAS + +/* Atomically: If *PTR == OLD, set *PTR to NEW and return true, + otherwise do nothing and return false. */ +PT_EI int __compare_and_swap (long *ptr, long old, long new) +{ + unsigned long psw; + + /* disable interrupts */ + /* This is ugly ugly ugly! */ + __asm__ __volatile__ ("mfs %0, rmsr;" + "andi r3, %0, ~2;" + "mts rmsr, r3;" + : "=&r" (psw) + : + : "r3"); + + if (likely (*ptr == old)) + { + *ptr = new; + __asm__ __volatile__ ("mts rmsr, %0;" :: "r" (psw)); /* re-enable */ + return 1; + } + else + { + __asm__ __volatile__ ("mts rmsr, %0;" :: "r" (psw)); /* re-enable */ + return 0; + } +} + +/* like above's __compare_and_swap() but it first syncs the memory + (This is also the difference between both functions in e.g. + ../powerpc/pt-machine.h) + Doing this additional sync fixes a hang of __pthread_alt_unlock() + (Falk Brettschneider ) */ +PT_EI int +__compare_and_swap_with_release_semantics (long *p, + long oldval, long newval) +{ + __asm__ __volatile__ ("" : : : "memory"); /*MEMORY_BARRIER ();*/ + return __compare_and_swap (p, oldval, newval); +} + + +#ifndef IMPLEMENT_TAS_WITH_CAS +/* Spinlock implementation; required. */ +PT_EI long int testandset (int *spinlock) +{ + unsigned psw; + + /* disable interrupts */ + __asm__ __volatile__ ("mfs %0, rmsr;" + "andi r3, %0, ~2;" + "mts rmsr, r3;" + : "=&r" (psw) + : + : "r3"); + + if (*spinlock) + { + /* Enable ints */ + __asm__ __volatile__ ("mts rmsr, %0;" :: "r" (psw)); + return 1; + } else { + *spinlock=1; + /* Enable ints */ + __asm__ __volatile__ ("mts rmsr, %0;" :: "r" (psw)); + return 0; + } +} + +#endif +#endif /* pt-machine.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/microblaze/sigcontextinfo.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/microblaze/sigcontextinfo.h new file mode 100644 index 00000000..de450ff8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/microblaze/sigcontextinfo.h @@ -0,0 +1,17 @@ +/* + * sysdeps/v850/sigcontextinfo.h -- v850-specific pthread signal definitions + * + * Copyright (C) 2002 NEC Electronics Corporation + * Copyright (C) 2002 Miles Bader + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + * + * Written by Miles Bader + */ + +#include + +#define SIGCONTEXT struct sigcontext * +#define SIGCONTEXT_EXTRA_ARGS diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/mips/pt-machine.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/mips/pt-machine.h new file mode 100644 index 00000000..fb1cc0e6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/mips/pt-machine.h @@ -0,0 +1,106 @@ +/* Machine-dependent pthreads configuration and inline functions. + + Copyright (C) 1996, 1997, 1998, 2000, 2002, 2003, 2004 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ralf Baechle . + Based on the Alpha version by Richard Henderson . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If + not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef _PT_MACHINE_H +#define _PT_MACHINE_H 1 + +#include + +#ifndef PT_EI +# define PT_EI __extern_always_inline +#endif + +/* Copyright (C) 2000, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Maciej W. Rozycki , 2000. */ +static __inline__ int +__NTH (_test_and_set (int *p, int v)) +{ + int r, t; + + __asm__ __volatile__ + ("/* Inline test and set */\n" + "1:\n\t" + ".set push\n\t" + ".set mips2\n\t" + "ll %0,%3\n\t" + "move %1,%4\n\t" + "beq %0,%4,2f\n\t" + "sc %1,%2\n\t" + ".set pop\n\t" + "beqz %1,1b\n" + "2:\n\t" + "/* End test and set */" + : "=&r" (r), "=&r" (t), "=m" (*p) + : "m" (*p), "r" (v) + : "memory"); + + return r; +} + + +/* Spinlock implementation; required. */ + +PT_EI long int +testandset (int *spinlock) +{ + return _test_and_set (spinlock, 1); +} + + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#define CURRENT_STACK_FRAME stack_pointer +register char * stack_pointer __asm__ ("$29"); + + +/* Compare-and-swap for semaphores. */ + +#define HAS_COMPARE_AND_SWAP +PT_EI int +__compare_and_swap (long int *p, long int oldval, long int newval) +{ + long int ret, temp; + + __asm__ __volatile__ + ("/* Inline compare & swap */\n" + "1:\n\t" + ".set push\n\t" + ".set mips2\n\t" + "ll %1,%5\n\t" + "move %0,$0\n\t" + "bne %1,%3,2f\n\t" + "move %0,%4\n\t" + "sc %0,%2\n\t" + ".set pop\n\t" + "beqz %0,1b\n" + "2:\n\t" + "/* End compare & swap */" + : "=&r" (ret), "=&r" (temp), "=m" (*p) + : "r" (oldval), "r" (newval), "m" (*p) + : "memory"); + + return ret; +} + +#endif /* pt-machine.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/nios/pt-machine.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/nios/pt-machine.h new file mode 100644 index 00000000..14045501 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/nios/pt-machine.h @@ -0,0 +1,68 @@ +/* Machine-dependent pthreads configuration and inline functions. + ARM version. + Copyright (C) 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Philip Blundell . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _PT_MACHINE_H +#define _PT_MACHINE_H 1 + +#include + +#ifndef PT_EI +# define PT_EI __extern_always_inline +#endif + +/* Spinlock implementation; required. */ +/* it is weird and dangerous to disable interrupt in userspace, but for nios + what else we can do before we have a swap like instruction? This is better + than nothing + */ +PT_EI long int +testandset (int *spinlock) +{ + unsigned int ret; + + __asm__ __volatile__("pfx 8\n\t" + "wrctl %1 ; disable interrupt\n\t" + "nop\n\t" + "nop\n\t" + "ld %0, [%2]\n\t" + "st [%2], %1\n\t" + "pfx 9\n\t" + "wrctl %1 ; enable interrupt\n\t" + "nop\n\t" + "nop\n\t" + : "=&r"(ret) + : "r"(1), "r"(spinlock) + : "memory"); + + return ret; +} + + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#define CURRENT_STACK_FRAME stack_pointer +register char * stack_pointer __asm__ ("%sp"); + +/* nios needs more because of reg windows */ +#define THREAD_MANAGER_STACK_SIZE (32*1024) +#define STACK_SIZE (32*1024) + +#endif /* pt-machine.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/nios2/pt-machine.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/nios2/pt-machine.h new file mode 100644 index 00000000..061fa735 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/nios2/pt-machine.h @@ -0,0 +1,58 @@ +/* Machine-dependent pthreads configuration and inline functions. + nios2 version. + Copyright (C) 1996, 1998, 2000, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If + not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef _PT_MACHINE_H +#define _PT_MACHINE_H 1 + +#include + +#ifndef PT_EI +# define PT_EI __extern_always_inline +#endif + +/* Spinlock implementation; required. */ +PT_EI long int +testandset (int *spinlock) +{ + unsigned int scratch; + long int ret=-2; + + __asm__ __volatile__( + "rdctl %0, status\n\t" + "and %0, %0, %1\n\t" + "wrctl status, %0 #disable interrupts\n\t" + "ldw %1, 0(%4)\n\t" + "stw %3, 0(%4)\n\t" + "ori %0, %0, 1\n\t" + "wrctl status, %0 #enable interrupts\n\t" + : "=&r"(scratch), "=r"(ret) + : "1"(ret), "r"(1), "r"(spinlock) + : "memory"); + + return ret; +} + + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#define CURRENT_STACK_FRAME stack_pointer +register char * stack_pointer __asm__ ("%sp"); + +#endif /* pt-machine.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/powerpc/pt-machine.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/powerpc/pt-machine.h new file mode 100644 index 00000000..561f8958 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/powerpc/pt-machine.h @@ -0,0 +1,102 @@ +/* Machine-dependent pthreads configuration and inline functions. + powerpc version. + Copyright (C) 1996, 1997, 1998, 2000, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If + not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* These routines are from Appendix G of the 'PowerPC 601 RISC Microprocessor + User's Manual', by IBM and Motorola. */ + +#ifndef _PT_MACHINE_H +#define _PT_MACHINE_H 1 + +#include + +#ifndef PT_EI +# define PT_EI __extern_always_inline +#endif + +/* For multiprocessor systems, we want to ensure all memory accesses + are completed before we reset a lock. On other systems, we still + need to make sure that the compiler has flushed everything to memory. */ +#define MEMORY_BARRIER() __asm__ __volatile__ ("sync" : : : "memory") + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#define CURRENT_STACK_FRAME stack_pointer +register char * stack_pointer __asm__ ("r1"); + +/* Register r2 (tp) is reserved by the ABI as "thread pointer". */ +struct _pthread_descr_struct; +register struct _pthread_descr_struct *__thread_self __asm__("r2"); + +/* Return the thread descriptor for the current thread. */ +#define THREAD_SELF __thread_self + +/* Initialize the thread-unique value. */ +#define INIT_THREAD_SELF(descr, nr) (__thread_self = (descr)) + +/* Compare-and-swap for semaphores. */ +/* note that test-and-set(x) is the same as !compare-and-swap(x, 0, 1) */ + +#define HAS_COMPARE_AND_SWAP_WITH_RELEASE_SEMANTICS +#define IMPLEMENT_TAS_WITH_CAS + +PT_EI int +__compare_and_swap (long int *p, long int oldval, long int newval) +{ + int ret; + + __asm__ __volatile__ ( + "0: lwarx %0,0,%1 ;" + " xor. %0,%3,%0;" + " bne 1f;" + " stwcx. %2,0,%1;" + " bne- 0b;" + "1: " + : "=&r"(ret) + : "r"(p), "r"(newval), "r"(oldval) + : "cr0", "memory"); + /* This version of __compare_and_swap is to be used when acquiring + a lock, so we don't need to worry about whether other memory + operations have completed, but we do need to be sure that any loads + after this point really occur after we have acquired the lock. */ + __asm__ __volatile__ ("isync" : : : "memory"); + return ret == 0; +} + +PT_EI int +__compare_and_swap_with_release_semantics (long int *p, + long int oldval, long int newval) +{ + int ret; + + MEMORY_BARRIER (); + __asm__ __volatile__ ( + "0: lwarx %0,0,%1 ;" + " xor. %0,%3,%0;" + " bne 1f;" + " stwcx. %2,0,%1;" + " bne- 0b;" + "1: " + : "=&r"(ret) + : "r"(p), "r"(newval), "r"(oldval) + : "cr0", "memory"); + return ret == 0; +} + +#endif /* pt-machine.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/pthread/bits/libc-lock.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/pthread/bits/libc-lock.h new file mode 100644 index 00000000..78593ac1 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/pthread/bits/libc-lock.h @@ -0,0 +1,416 @@ +/* libc-internal interface for mutex locks. LinuxThreads version. + Copyright (C) 1996,1997,1998,1999,2000,2001,2002,2003 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _BITS_LIBC_LOCK_H +#define _BITS_LIBC_LOCK_H 1 + +#include + +#if defined _LIBC && !defined NOT_IN_libc +#include +#endif + +/* Mutex type. */ +#if defined(_LIBC) || defined(_IO_MTSAFE_IO) +typedef pthread_mutex_t __libc_lock_t; +typedef pthread_mutex_t __libc_lock_recursive_t; +# ifdef __USE_UNIX98 +typedef pthread_rwlock_t __libc_rwlock_t; +# else +typedef struct __libc_rwlock_opaque__ __libc_rwlock_t; +# endif +typedef __libc_lock_recursive_t __rtld_lock_recursive_t; +#else +typedef struct __libc_lock_opaque__ __libc_lock_t; +typedef struct __libc_lock_recursive_opaque__ __libc_lock_recursive_t; +typedef struct __libc_rwlock_opaque__ __libc_rwlock_t; +#endif + +/* Type for key to thread-specific data. */ +typedef pthread_key_t __libc_key_t; + +/* Define a lock variable NAME with storage class CLASS. The lock must be + initialized with __libc_lock_init before it can be used (or define it + with __libc_lock_define_initialized, below). Use `extern' for CLASS to + declare a lock defined in another module. In public structure + definitions you must use a pointer to the lock structure (i.e., NAME + begins with a `*'), because its storage size will not be known outside + of libc. */ +#define __libc_lock_define(CLASS,NAME) \ + CLASS __libc_lock_t NAME; +#define __libc_rwlock_define(CLASS,NAME) \ + CLASS __libc_rwlock_t NAME; +#define __libc_lock_define_recursive(CLASS,NAME) \ + CLASS __libc_lock_recursive_t NAME; +#define __rtld_lock_define_recursive(CLASS,NAME) \ + CLASS __rtld_lock_recursive_t NAME; + +/* Define an initialized lock variable NAME with storage class CLASS. + + For the C library we take a deeper look at the initializer. For + this implementation all fields are initialized to zero. Therefore + we don't initialize the variable which allows putting it into the + BSS section. (Except on PA-RISC and other odd architectures, where + initialized locks must be set to one due to the lack of normal + atomic operations.) */ + +#if __LT_SPINLOCK_INIT == 0 +# define __libc_lock_define_initialized(CLASS,NAME) \ + CLASS __libc_lock_t NAME; +#else +# define __libc_lock_define_initialized(CLASS,NAME) \ + CLASS __libc_lock_t NAME = PTHREAD_MUTEX_INITIALIZER; +#endif + +#define __libc_rwlock_define_initialized(CLASS,NAME) \ + CLASS __libc_rwlock_t NAME = PTHREAD_RWLOCK_INITIALIZER; + +/* Define an initialized recursive lock variable NAME with storage + class CLASS. */ +#define __libc_lock_define_initialized_recursive(CLASS,NAME) \ + CLASS __libc_lock_recursive_t NAME = _LIBC_LOCK_RECURSIVE_INITIALIZER; +#define _LIBC_LOCK_RECURSIVE_INITIALIZER \ + {PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP} + +#define __rtld_lock_define_initialized_recursive(CLASS,NAME) \ + CLASS __rtld_lock_recursive_t NAME = _RTLD_LOCK_RECURSIVE_INITIALIZER; +#define _RTLD_LOCK_RECURSIVE_INITIALIZER \ + {PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP} + +#if defined _LIBC && defined IS_IN_libpthread +# define __libc_maybe_call(FUNC, ARGS, ELSE) FUNC ARGS +#else +# if defined __PIC__ || (defined _LIBC && defined SHARED) +# define __libc_maybe_call(FUNC, ARGS, ELSE) \ + (__extension__ ({ __typeof (FUNC) *_fn = (FUNC); \ + _fn != NULL ? (*_fn) ARGS : ELSE; })) +# else +# define __libc_maybe_call(FUNC, ARGS, ELSE) \ + (FUNC != NULL ? FUNC ARGS : ELSE) +# endif +#endif +#if defined _LIBC && !defined NOT_IN_libc && defined SHARED +# define __libc_maybe_call2(FUNC, ARGS, ELSE) \ + ({__builtin_expect (__libc_pthread_functions.ptr_##FUNC != NULL, 0) \ + ? __libc_pthread_functions.ptr_##FUNC ARGS : ELSE; }) +#else +# define __libc_maybe_call2(FUNC, ARGS, ELSE) __libc_maybe_call (__##FUNC, ARGS, ELSE) +#endif + +/* Initialize the named lock variable, leaving it in a consistent, unlocked + state. */ +#if defined _LIBC && !defined NOT_IN_libc && defined SHARED +#define __libc_lock_init(NAME) \ + ({ \ + (NAME).__m_count = 0; \ + (NAME).__m_owner = NULL; \ + (NAME).__m_kind = PTHREAD_MUTEX_TIMED_NP; \ + (NAME).__m_lock.__status = 0; \ + (NAME).__m_lock.__spinlock = __LT_SPINLOCK_INIT; \ + 0; }) +#else +#define __libc_lock_init(NAME) \ + (__libc_maybe_call2 (pthread_mutex_init, (&(NAME), NULL), 0)) +#endif +#define __libc_rwlock_init(NAME) \ + (__libc_maybe_call (__pthread_rwlock_init, (&(NAME), NULL), 0)); + +/* Same as last but this time we initialize an adaptive mutex. */ +#if defined _LIBC && !defined NOT_IN_libc && defined SHARED +#define __libc_lock_init_adaptive(NAME) \ + ({ \ + (NAME).__m_count = 0; \ + (NAME).__m_owner = NULL; \ + (NAME).__m_kind = PTHREAD_MUTEX_ADAPTIVE_NP; \ + (NAME).__m_lock.__status = 0; \ + (NAME).__m_lock.__spinlock = __LT_SPINLOCK_INIT; \ + 0; }) +#else +#define __libc_lock_init_adaptive(NAME) \ + do { \ + if (__pthread_mutex_init != NULL) \ + { \ + pthread_mutexattr_t __attr; \ + __pthread_mutexattr_init (&__attr); \ + __pthread_mutexattr_settype (&__attr, PTHREAD_MUTEX_ADAPTIVE_NP); \ + __pthread_mutex_init (&(NAME), &__attr); \ + __pthread_mutexattr_destroy (&__attr); \ + } \ + } while (0); +#endif + +/* Same as last but this time we initialize a recursive mutex. */ +#if defined _LIBC && !defined NOT_IN_libc && defined SHARED +#define __libc_lock_init_recursive(NAME) \ + ({ \ + (NAME).__m_count = 0; \ + (NAME).__m_owner = NULL; \ + (NAME).__m_kind = PTHREAD_MUTEX_RECURSIVE_NP; \ + (NAME).__m_lock.__status = 0; \ + (NAME).__m_lock.__spinlock = __LT_SPINLOCK_INIT; \ + 0; }) +#else +#define __libc_lock_init_recursive(NAME) \ + do { \ + if (__pthread_mutex_init != NULL) \ + { \ + pthread_mutexattr_t __attr; \ + __pthread_mutexattr_init (&__attr); \ + __pthread_mutexattr_settype (&__attr, PTHREAD_MUTEX_RECURSIVE_NP); \ + __pthread_mutex_init (&(NAME), &__attr); \ + __pthread_mutexattr_destroy (&__attr); \ + } \ + } while (0); +#endif +#define __rtld_lock_init_recursive(NAME) \ + __libc_lock_init_recursive (NAME) + +/* Finalize the named lock variable, which must be locked. It cannot be + used again until __libc_lock_init is called again on it. This must be + called on a lock variable before the containing storage is reused. */ +#define __libc_lock_fini(NAME) \ + (__libc_maybe_call2 (pthread_mutex_destroy, (&(NAME)), 0)); +#define __libc_rwlock_fini(NAME) \ + (__libc_maybe_call (__pthread_rwlock_destroy, (&(NAME)), 0)); + +/* Finalize recursive named lock. */ +#define __libc_lock_fini_recursive(NAME) __libc_lock_fini ((NAME).mutex) +#define __rtld_lock_fini_recursive(NAME) __libc_lock_fini_recursive (NAME) + +/* Lock the named lock variable. */ +#define __libc_lock_lock(NAME) \ + (__libc_maybe_call2 (pthread_mutex_lock, (&(NAME)), 0)); +#define __libc_rwlock_rdlock(NAME) \ + (__libc_maybe_call (__pthread_rwlock_rdlock, (&(NAME)), 0)); +#define __libc_rwlock_wrlock(NAME) \ + (__libc_maybe_call (__pthread_rwlock_wrlock, (&(NAME)), 0)); + +/* Lock the recursive named lock variable. */ +#define __libc_lock_lock_recursive(NAME) __libc_lock_lock ((NAME).mutex) + +/* Try to lock the named lock variable. */ +#define __libc_lock_trylock(NAME) \ + (__libc_maybe_call2 (pthread_mutex_trylock, (&(NAME)), 0)) +#define __libc_rwlock_tryrdlock(NAME) \ + (__libc_maybe_call (__pthread_rwlock_tryrdlock, (&(NAME)), 0)) +#define __libc_rwlock_trywrlock(NAME) \ + (__libc_maybe_call (__pthread_rwlock_trywrlock, (&(NAME)), 0)) + +/* Try to lock the recursive named lock variable. */ +#define __libc_lock_trylock_recursive(NAME) __libc_lock_trylock ((NAME).mutex) +#define __rtld_lock_trylock_recursive(NAME) \ + __libc_lock_trylock_recursive (NAME) + +/* Unlock the named lock variable. */ +#define __libc_lock_unlock(NAME) \ + (__libc_maybe_call2 (pthread_mutex_unlock, (&(NAME)), 0)); +#define __libc_rwlock_unlock(NAME) \ + (__libc_maybe_call (__pthread_rwlock_unlock, (&(NAME)), 0)); + +/* Unlock the recursive named lock variable. */ +#define __libc_lock_unlock_recursive(NAME) __libc_lock_unlock ((NAME).mutex) + +/* Define once control variable. */ +#if PTHREAD_ONCE_INIT == 0 +/* Special case for static variables where we can avoid the initialization + if it is zero. */ +# define __libc_once_define(CLASS, NAME) \ + CLASS pthread_once_t NAME +#else +# define __libc_once_define(CLASS, NAME) \ + CLASS pthread_once_t NAME = PTHREAD_ONCE_INIT +#endif + +/* Call handler iff the first call. */ +#define __libc_once(ONCE_CONTROL, INIT_FUNCTION) \ + do { \ + if (__pthread_once != NULL) \ + __pthread_once (&(ONCE_CONTROL), (INIT_FUNCTION)); \ + else if ((ONCE_CONTROL) == PTHREAD_ONCE_INIT) { \ + INIT_FUNCTION (); \ + (ONCE_CONTROL) = !PTHREAD_ONCE_INIT; \ + } \ + } while (0) + + +/* Start critical region with cleanup. */ +#define __libc_cleanup_region_start(DOIT, FCT, ARG) \ + { struct _pthread_cleanup_buffer _buffer; \ + int _avail = (DOIT) && _pthread_cleanup_push_defer != NULL; \ + if (_avail) { \ + _pthread_cleanup_push_defer (&_buffer, (FCT), (ARG)); \ + } + +/* End critical region with cleanup. */ +#define __libc_cleanup_region_end(DOIT) \ + if (_avail) { \ + _pthread_cleanup_pop_restore (&_buffer, (DOIT)); \ + } \ + } + +/* Sometimes we have to exit the block in the middle. */ +#define __libc_cleanup_end(DOIT) \ + if (_avail) { \ + _pthread_cleanup_pop_restore (&_buffer, (DOIT)); \ + } + +#define __libc_cleanup_push(fct, arg) \ + { struct _pthread_cleanup_buffer _buffer; \ + __libc_maybe_call (_pthread_cleanup_push, (&_buffer, (fct), (arg)), 0) + +#define __libc_cleanup_pop(execute) \ + __libc_maybe_call (_pthread_cleanup_pop, (&_buffer, execute), 0); \ + } + +/* Create thread-specific key. */ +#define __libc_key_create(KEY, DESTRUCTOR) \ + (__libc_maybe_call (__pthread_key_create, (KEY, DESTRUCTOR), 1)) + +/* Get thread-specific data. */ +#define __libc_getspecific(KEY) \ + (__libc_maybe_call (__pthread_getspecific, (KEY), NULL)) + +/* Set thread-specific data. */ +#define __libc_setspecific(KEY, VALUE) \ + (__libc_maybe_call (__pthread_setspecific, (KEY, VALUE), 0)) + + +/* Register handlers to execute before and after `fork'. */ +#define __libc_atfork(PREPARE, PARENT, CHILD) \ + (__libc_maybe_call (__pthread_atfork, (PREPARE, PARENT, CHILD), 0)) + +/* Functions that are used by this file and are internal to the GNU C + library. */ + +extern int __pthread_mutex_init (pthread_mutex_t *__mutex, + __const pthread_mutexattr_t *__mutex_attr); + +extern int __pthread_mutex_destroy (pthread_mutex_t *__mutex); + +extern int __pthread_mutex_trylock (pthread_mutex_t *__mutex); + +extern int __pthread_mutex_lock (pthread_mutex_t *__mutex); + +extern int __pthread_mutex_unlock (pthread_mutex_t *__mutex); + +extern int __pthread_mutexattr_init (pthread_mutexattr_t *__attr); + +extern int __pthread_mutexattr_destroy (pthread_mutexattr_t *__attr); + +extern int __pthread_mutexattr_settype (pthread_mutexattr_t *__attr, + int __kind); + +#ifdef __USE_UNIX98 +extern int __pthread_rwlock_init (pthread_rwlock_t *__rwlock, + __const pthread_rwlockattr_t *__attr); + +extern int __pthread_rwlock_destroy (pthread_rwlock_t *__rwlock); + +extern int __pthread_rwlock_rdlock (pthread_rwlock_t *__rwlock); + +extern int __pthread_rwlock_tryrdlock (pthread_rwlock_t *__rwlock); + +extern int __pthread_rwlock_wrlock (pthread_rwlock_t *__rwlock); + +extern int __pthread_rwlock_trywrlock (pthread_rwlock_t *__rwlock); + +extern int __pthread_rwlock_unlock (pthread_rwlock_t *__rwlock); +#endif + +extern int __pthread_key_create (pthread_key_t *__key, + void (*__destr_function) (void *)); + +extern int __pthread_setspecific (pthread_key_t __key, + __const void *__pointer); + +extern void *__pthread_getspecific (pthread_key_t __key); + +extern int __pthread_once (pthread_once_t *__once_control, + void (*__init_routine) (void)); + +extern int __pthread_atfork (void (*__prepare) (void), + void (*__parent) (void), + void (*__child) (void)); + + + +/* Make the pthread functions weak so that we can elide them from + single-threaded processes. */ +#ifndef __NO_WEAK_PTHREAD_ALIASES +# ifdef weak_extern +# define BP_SYM(sym) sym +weak_extern (BP_SYM (__pthread_mutex_init)) +weak_extern (BP_SYM (__pthread_mutex_destroy)) +weak_extern (BP_SYM (__pthread_mutex_lock)) +weak_extern (BP_SYM (__pthread_mutex_trylock)) +weak_extern (BP_SYM (__pthread_mutex_unlock)) +weak_extern (BP_SYM (__pthread_mutexattr_init)) +weak_extern (BP_SYM (__pthread_mutexattr_destroy)) +weak_extern (BP_SYM (__pthread_mutexattr_settype)) +weak_extern (BP_SYM (__pthread_rwlock_init)) +weak_extern (BP_SYM (__pthread_rwlock_destroy)) +weak_extern (BP_SYM (__pthread_rwlock_rdlock)) +weak_extern (BP_SYM (__pthread_rwlock_tryrdlock)) +weak_extern (BP_SYM (__pthread_rwlock_wrlock)) +weak_extern (BP_SYM (__pthread_rwlock_trywrlock)) +weak_extern (BP_SYM (__pthread_rwlock_unlock)) +weak_extern (BP_SYM (__pthread_key_create)) +weak_extern (BP_SYM (__pthread_setspecific)) +weak_extern (BP_SYM (__pthread_getspecific)) +weak_extern (BP_SYM (__pthread_once)) +weak_extern (__pthread_initialize) +weak_extern (__pthread_atfork) +weak_extern (BP_SYM (_pthread_cleanup_push)) +weak_extern (BP_SYM (_pthread_cleanup_pop)) +weak_extern (BP_SYM (_pthread_cleanup_push_defer)) +weak_extern (BP_SYM (_pthread_cleanup_pop_restore)) +# else +# pragma weak __pthread_mutex_init +# pragma weak __pthread_mutex_destroy +# pragma weak __pthread_mutex_lock +# pragma weak __pthread_mutex_trylock +# pragma weak __pthread_mutex_unlock +# pragma weak __pthread_mutexattr_init +# pragma weak __pthread_mutexattr_destroy +# pragma weak __pthread_mutexattr_settype +# pragma weak __pthread_rwlock_destroy +# pragma weak __pthread_rwlock_rdlock +# pragma weak __pthread_rwlock_tryrdlock +# pragma weak __pthread_rwlock_wrlock +# pragma weak __pthread_rwlock_trywrlock +# pragma weak __pthread_rwlock_unlock +# pragma weak __pthread_key_create +# pragma weak __pthread_setspecific +# pragma weak __pthread_getspecific +# pragma weak __pthread_once +# pragma weak __pthread_initialize +# pragma weak __pthread_atfork +# pragma weak _pthread_cleanup_push_defer +# pragma weak _pthread_cleanup_pop_restore +# pragma weak _pthread_cleanup_push +# pragma weak _pthread_cleanup_pop +# endif +#endif + +/* We need portable names for some functions. E.g., when they are + used as argument to __libc_cleanup_region_start. */ +#define __libc_mutex_unlock __pthread_mutex_unlock + +#endif /* bits/libc-lock.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/pthread/bits/libc-tsd.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/pthread/bits/libc-tsd.h new file mode 100644 index 00000000..2b889e62 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/pthread/bits/libc-tsd.h @@ -0,0 +1,73 @@ +/* libc-internal interface for thread-specific data. LinuxThreads version. + Copyright (C) 1997-2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _BITS_LIBC_TSD_H +#define _BITS_LIBC_TSD_H 1 + +#include + +/* Fast thread-specific data internal to libc. */ +enum __libc_tsd_key_t { _LIBC_TSD_KEY_MALLOC = 0, + _LIBC_TSD_KEY_DL_ERROR, + _LIBC_TSD_KEY_RPC_VARS, + _LIBC_TSD_KEY_LOCALE, + _LIBC_TSD_KEY_CTYPE_B, + _LIBC_TSD_KEY_CTYPE_TOLOWER, + _LIBC_TSD_KEY_CTYPE_TOUPPER, + _LIBC_TSD_KEY_N }; + +#include +#include + +#include + +#if defined(USE_TLS) && USE_TLS && HAVE___THREAD + +/* When __thread works, the generic definition is what we want. */ +# include + +#else + +# include + +# ifndef SHARED +extern void ** __pthread_internal_tsd_address (int); +extern void *__pthread_internal_tsd_get (int); +extern int __pthread_internal_tsd_set (int, const void *); + +weak_extern (__pthread_internal_tsd_address) +weak_extern (__pthread_internal_tsd_get) +weak_extern (__pthread_internal_tsd_set) +# endif + +#define __libc_tsd_define(CLASS, KEY) CLASS void *__libc_tsd_##KEY##_data; +#define __libc_tsd_address(KEY) \ + __libc_maybe_call2 (pthread_internal_tsd_address, \ + (_LIBC_TSD_KEY_##KEY), &__libc_tsd_##KEY##_data) +#define __libc_tsd_get(KEY) \ + __libc_maybe_call2 (pthread_internal_tsd_get, \ + (_LIBC_TSD_KEY_##KEY), __libc_tsd_##KEY##_data) +#define __libc_tsd_set(KEY, VALUE) \ + __libc_maybe_call2 (pthread_internal_tsd_set, \ + (_LIBC_TSD_KEY_##KEY, (VALUE)), \ + (__libc_tsd_##KEY##_data = (VALUE), 0)) + +#endif + +#endif /* bits/libc-tsd.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/pthread/bits/pthreadtypes.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/pthread/bits/pthreadtypes.h new file mode 100644 index 00000000..faec63b0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/pthread/bits/pthreadtypes.h @@ -0,0 +1,142 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +#if !defined _BITS_TYPES_H && !defined _PTHREAD_H +# error "Never include directly; use instead." +#endif + +#ifndef _BITS_PTHREADTYPES_H +#define _BITS_PTHREADTYPES_H 1 + +#define __need_schedparam +#include + +/* Fast locks (not abstract because mutexes and conditions aren't abstract). */ +struct _pthread_fastlock +{ + long int __status; /* "Free" or "taken" or head of waiting list */ + int __spinlock; /* Used by compare_and_swap emulation. Also, + adaptive SMP lock stores spin count here. */ +}; + +#ifndef _PTHREAD_DESCR_DEFINED +/* Thread descriptors */ +typedef struct _pthread_descr_struct *_pthread_descr; +# define _PTHREAD_DESCR_DEFINED +#endif + + +/* Attributes for threads. */ +typedef struct __pthread_attr_s +{ + int __detachstate; + int __schedpolicy; + struct __sched_param __schedparam; + int __inheritsched; + int __scope; + size_t __guardsize; + int __stackaddr_set; + void *__stackaddr; + size_t __stacksize; +} pthread_attr_t; + + +/* Conditions (not abstract because of PTHREAD_COND_INITIALIZER */ +typedef struct +{ + struct _pthread_fastlock __c_lock; /* Protect against concurrent access */ + _pthread_descr __c_waiting; /* Threads waiting on this condition */ +} pthread_cond_t; + + +/* Attribute for conditionally variables. */ +typedef struct +{ + int __dummy; +} pthread_condattr_t; + +/* Keys for thread-specific data */ +typedef unsigned int pthread_key_t; + + +/* Mutexes (not abstract because of PTHREAD_MUTEX_INITIALIZER). */ +/* (The layout is unnatural to maintain binary compatibility + with earlier releases of LinuxThreads.) */ +typedef struct +{ + int __m_reserved; /* Reserved for future use */ + int __m_count; /* Depth of recursive locking */ + _pthread_descr __m_owner; /* Owner thread (if recursive or errcheck) */ + int __m_kind; /* Mutex kind: fast, recursive or errcheck */ + struct _pthread_fastlock __m_lock; /* Underlying fast lock */ +} pthread_mutex_t; + + +/* Attribute for mutex. */ +typedef struct +{ + int __mutexkind; +} pthread_mutexattr_t; + + +/* Once-only execution */ +typedef int pthread_once_t; + + +#if defined __USE_UNIX98 || defined __USE_XOPEN2K +/* Read-write locks. */ +typedef struct _pthread_rwlock_t +{ + struct _pthread_fastlock __rw_lock; /* Lock to guarantee mutual exclusion */ + int __rw_readers; /* Number of readers */ + _pthread_descr __rw_writer; /* Identity of writer, or NULL if none */ + _pthread_descr __rw_read_waiting; /* Threads waiting for reading */ + _pthread_descr __rw_write_waiting; /* Threads waiting for writing */ + int __rw_kind; /* Reader/Writer preference selection */ + int __rw_pshared; /* Shared between processes or not */ +} pthread_rwlock_t; + + +/* Attribute for read-write locks. */ +typedef struct +{ + int __lockkind; + int __pshared; +} pthread_rwlockattr_t; +#endif + +#ifdef __USE_XOPEN2K +/* POSIX spinlock data type. */ +typedef volatile int pthread_spinlock_t; + +/* POSIX barrier. */ +typedef struct { + struct _pthread_fastlock __ba_lock; /* Lock to guarantee mutual exclusion */ + int __ba_required; /* Threads needed for completion */ + int __ba_present; /* Threads waiting */ + _pthread_descr __ba_waiting; /* Queue of waiting threads */ +} pthread_barrier_t; + +/* barrier attribute */ +typedef struct { + int __pshared; +} pthread_barrierattr_t; + +#endif + + +/* Thread identifiers */ +typedef unsigned long int pthread_t; + +#endif /* bits/pthreadtypes.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/pthread/not-cancel.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/pthread/not-cancel.h new file mode 100644 index 00000000..80d33be2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/pthread/not-cancel.h @@ -0,0 +1,105 @@ +/* Uncancelable versions of cancelable interfaces. Linux version. + Copyright (C) 2003, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +/* Uncancelable open. */ +#define open_not_cancel(name, flags, mode) \ + INLINE_SYSCALL (open, 3, (const char *) (name), (flags), (mode)) +#define open_not_cancel_2(name, flags) \ + INLINE_SYSCALL (open, 2, (const char *) (name), (flags)) + +/* Uncancelable openat. */ +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt +extern int __openat_nocancel (int fd, const char *fname, int oflag, + mode_t mode) attribute_hidden; +extern int __openat64_nocancel (int fd, const char *fname, int oflag, + mode_t mode) attribute_hidden; +#else +# define __openat_nocancel(fd, fname, oflag, mode) \ + openat (fd, fname, oflag, mode) +# define __openat64_nocancel(fd, fname, oflag, mode) \ + openat64 (fd, fname, oflag, mode) +#endif + +#define openat_not_cancel(fd, fname, oflag, mode) \ + __openat_nocancel (fd, fname, oflag, mode) +#define openat_not_cancel_3(fd, fname, oflag) \ + __openat_nocancel (fd, fname, oflag, 0) +#define openat64_not_cancel(fd, fname, oflag, mode) \ + __openat64_nocancel (fd, fname, oflag, mode) +#define openat64_not_cancel_3(fd, fname, oflag) \ + __openat64_nocancel (fd, fname, oflag, 0) + +/* Uncancelable close. */ +#define close_not_cancel(fd) \ + INLINE_SYSCALL (close, 1, fd) +#define close_not_cancel_no_status(fd) \ + (void) ({ INTERNAL_SYSCALL_DECL (err); \ + INTERNAL_SYSCALL (close, err, 1, (fd)); }) + +/* Uncancelable read. */ +#define read_not_cancel(fd, buf, n) \ + INLINE_SYSCALL (read, 3, (fd), (buf), (n)) + +/* Uncancelable write. */ +#define write_not_cancel(fd, buf, n) \ + INLINE_SYSCALL (write, 3, (fd), (buf), (n)) + +/* Uncancelable writev. */ +#define writev_not_cancel_no_status(fd, iov, n) \ + (void) ({ INTERNAL_SYSCALL_DECL (err); \ + INTERNAL_SYSCALL (writev, err, 3, (fd), (iov), (n)); }) + +/* Uncancelable fcntl. */ +#define fcntl_not_cancel(fd, cmd, val) \ + __fcntl_nocancel (fd, cmd, val) + +/* Uncancelable waitpid. */ +#ifdef __NR_waitpid +# define waitpid_not_cancel(pid, stat_loc, options) \ + INLINE_SYSCALL (waitpid, 3, pid, stat_loc, options) +#else +# define waitpid_not_cancel(pid, stat_loc, options) \ + INLINE_SYSCALL (wait4, 4, pid, stat_loc, options, NULL) +#endif + +/* Uncancelable pause. */ +#ifdef __NR_pause +# define pause_not_cancel() \ + INLINE_SYSCALL (pause, 0) +#else +# define pause_not_cancel() \ + __pause_nocancel () +#endif + +/* Uncancelable nanosleep. */ +#ifdef __NR_nanosleep +# define nanosleep_not_cancel(requested_time, remaining) \ + INLINE_SYSCALL (nanosleep, 2, requested_time, remaining) +#else +# define nanosleep_not_cancel(requested_time, remaining) \ + __nanosleep_nocancel (requested_time, remaining) +#endif + +/* Uncancelable sigsuspend. */ +#define sigsuspend_not_cancel(set) \ + __sigsuspend_nocancel (set) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/pthread/pthread-functions.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/pthread/pthread-functions.h new file mode 100644 index 00000000..ce6d10fb --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/pthread/pthread-functions.h @@ -0,0 +1,98 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _PTHREAD_FUNCTIONS_H +#define _PTHREAD_FUNCTIONS_H 1 + +#include +#include +#include + +struct fork_block; + +/* Data type shared with libc. The libc uses it to pass on calls to + the thread functions. Wine pokes directly into this structure, + so if possible avoid breaking it and append new hooks to the end. */ +struct pthread_functions +{ + pid_t (*ptr_pthread_fork) (struct fork_block *); + int (*ptr_pthread_attr_destroy) (pthread_attr_t *); + int (*ptr_pthread_attr_init) (pthread_attr_t *); + int (*ptr_pthread_attr_getdetachstate) (const pthread_attr_t *, int *); + int (*ptr_pthread_attr_setdetachstate) (pthread_attr_t *, int); + int (*ptr_pthread_attr_getinheritsched) (const pthread_attr_t *, int *); + int (*ptr_pthread_attr_setinheritsched) (pthread_attr_t *, int); + int (*ptr_pthread_attr_getschedparam) (const pthread_attr_t *, + struct sched_param *); + int (*ptr_pthread_attr_setschedparam) (pthread_attr_t *, + const struct sched_param *); + int (*ptr_pthread_attr_getschedpolicy) (const pthread_attr_t *, int *); + int (*ptr_pthread_attr_setschedpolicy) (pthread_attr_t *, int); + int (*ptr_pthread_attr_getscope) (const pthread_attr_t *, int *); + int (*ptr_pthread_attr_setscope) (pthread_attr_t *, int); + int (*ptr_pthread_condattr_destroy) (pthread_condattr_t *); + int (*ptr_pthread_condattr_init) (pthread_condattr_t *); + int (*ptr_pthread_cond_broadcast) (pthread_cond_t *); + int (*ptr_pthread_cond_destroy) (pthread_cond_t *); + int (*ptr_pthread_cond_init) (pthread_cond_t *, + const pthread_condattr_t *); + int (*ptr_pthread_cond_signal) (pthread_cond_t *); + int (*ptr_pthread_cond_wait) (pthread_cond_t *, pthread_mutex_t *); + int (*ptr_pthread_equal) (pthread_t, pthread_t); + void (*ptr___pthread_exit) (void *); + int (*ptr_pthread_getschedparam) (pthread_t, int *, struct sched_param *); + int (*ptr_pthread_setschedparam) (pthread_t, int, + const struct sched_param *); + int (*ptr_pthread_mutex_destroy) (pthread_mutex_t *); + int (*ptr_pthread_mutex_init) (pthread_mutex_t *, + const pthread_mutexattr_t *); + int (*ptr_pthread_mutex_lock) (pthread_mutex_t *); + int (*ptr_pthread_mutex_trylock) (pthread_mutex_t *); + int (*ptr_pthread_mutex_unlock) (pthread_mutex_t *); + pthread_t (*ptr_pthread_self) (void); + int (*ptr_pthread_setcancelstate) (int, int *); + int (*ptr_pthread_setcanceltype) (int, int *); + void (*ptr_pthread_do_exit) (void *retval, char *currentframe); + void (*ptr_pthread_cleanup_upto) (__jmp_buf target, + char *targetframe); + pthread_descr (*ptr_pthread_thread_self) (void); + int (*ptr_pthread_internal_tsd_set) (int key, const void *pointer); + void * (*ptr_pthread_internal_tsd_get) (int key); + void ** __attribute__ ((__const__)) + (*ptr_pthread_internal_tsd_address) (int key); + int (*ptr_pthread_sigaction) (int sig, const struct sigaction * act, + struct sigaction *oact); + int (*ptr_pthread_sigwait) (const sigset_t *set, int *sig); + int (*ptr_pthread_raise) (int sig); + int (*ptr_pthread_cond_timedwait) (pthread_cond_t *, pthread_mutex_t *, + const struct timespec *); + void (*ptr__pthread_cleanup_push) (struct _pthread_cleanup_buffer * buffer, + void (*routine)(void *), void * arg); + void (*ptr__pthread_cleanup_push_defer) (struct _pthread_cleanup_buffer * buffer, + void (*routine)(void *), void * arg); + void (*ptr__pthread_cleanup_pop) (struct _pthread_cleanup_buffer * buffer, + int execute); + void (*ptr__pthread_cleanup_pop_restore) (struct _pthread_cleanup_buffer * buffer, + int execute); +}; + +/* Variable in libc.so. */ +extern struct pthread_functions __libc_pthread_functions attribute_hidden; + +#endif /* pthread-functions.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/pthread/pthread.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/pthread/pthread.h new file mode 100644 index 00000000..38d56673 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/pthread/pthread.h @@ -0,0 +1,702 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +#ifndef _PTHREAD_H +#define _PTHREAD_H 1 + +#include + +#include +#include + +#define __need_sigset_t +#include +#include +#include + + +__BEGIN_DECLS + +/* Initializers. */ + +#define PTHREAD_MUTEX_INITIALIZER \ + {0, 0, 0, PTHREAD_MUTEX_ADAPTIVE_NP, __LOCK_INITIALIZER} +#ifdef __USE_GNU +# define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP \ + {0, 0, 0, PTHREAD_MUTEX_RECURSIVE_NP, __LOCK_INITIALIZER} +# define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP \ + {0, 0, 0, PTHREAD_MUTEX_ERRORCHECK_NP, __LOCK_INITIALIZER} +# define PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP \ + {0, 0, 0, PTHREAD_MUTEX_ADAPTIVE_NP, __LOCK_INITIALIZER} +#endif + +#define PTHREAD_COND_INITIALIZER {__LOCK_INITIALIZER, 0} + +#if defined __USE_UNIX98 || defined __USE_XOPEN2K +# define PTHREAD_RWLOCK_INITIALIZER \ + { __LOCK_INITIALIZER, 0, NULL, NULL, NULL, \ + PTHREAD_RWLOCK_DEFAULT_NP, PTHREAD_PROCESS_PRIVATE } +#endif +#ifdef __USE_GNU +# define PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP \ + { __LOCK_INITIALIZER, 0, NULL, NULL, NULL, \ + PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP, PTHREAD_PROCESS_PRIVATE } +#endif + +/* Values for attributes. */ + +enum +{ + PTHREAD_CREATE_JOINABLE, +#define PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_JOINABLE + PTHREAD_CREATE_DETACHED +#define PTHREAD_CREATE_DETACHED PTHREAD_CREATE_DETACHED +}; + +enum +{ + PTHREAD_INHERIT_SCHED, +#define PTHREAD_INHERIT_SCHED PTHREAD_INHERIT_SCHED + PTHREAD_EXPLICIT_SCHED +#define PTHREAD_EXPLICIT_SCHED PTHREAD_EXPLICIT_SCHED +}; + +enum +{ + PTHREAD_SCOPE_SYSTEM, +#define PTHREAD_SCOPE_SYSTEM PTHREAD_SCOPE_SYSTEM + PTHREAD_SCOPE_PROCESS +#define PTHREAD_SCOPE_PROCESS PTHREAD_SCOPE_PROCESS +}; + +enum +{ + PTHREAD_MUTEX_ADAPTIVE_NP, + PTHREAD_MUTEX_RECURSIVE_NP, + PTHREAD_MUTEX_ERRORCHECK_NP, + PTHREAD_MUTEX_TIMED_NP +#ifdef __USE_UNIX98 + , + PTHREAD_MUTEX_NORMAL = PTHREAD_MUTEX_ADAPTIVE_NP, + PTHREAD_MUTEX_RECURSIVE = PTHREAD_MUTEX_RECURSIVE_NP, + PTHREAD_MUTEX_ERRORCHECK = PTHREAD_MUTEX_ERRORCHECK_NP, + PTHREAD_MUTEX_DEFAULT = PTHREAD_MUTEX_NORMAL +#endif +#ifdef __USE_GNU + /* For compatibility. */ + , PTHREAD_MUTEX_FAST_NP = PTHREAD_MUTEX_ADAPTIVE_NP +#endif +}; + +enum +{ + PTHREAD_PROCESS_PRIVATE, +#define PTHREAD_PROCESS_PRIVATE PTHREAD_PROCESS_PRIVATE + PTHREAD_PROCESS_SHARED +#define PTHREAD_PROCESS_SHARED PTHREAD_PROCESS_SHARED +}; + +#if defined __USE_UNIX98 || defined __USE_XOPEN2K +enum +{ + PTHREAD_RWLOCK_PREFER_READER_NP, + PTHREAD_RWLOCK_PREFER_WRITER_NP, + PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP, + PTHREAD_RWLOCK_DEFAULT_NP = PTHREAD_RWLOCK_PREFER_WRITER_NP +}; +#endif /* Unix98 */ + +#define PTHREAD_ONCE_INIT 0 + +/* Special constants */ + +#ifdef __USE_XOPEN2K +/* -1 is distinct from 0 and all errno constants */ +# define PTHREAD_BARRIER_SERIAL_THREAD -1 +#endif + +/* Cleanup buffers */ + +struct _pthread_cleanup_buffer +{ + void (*__routine) (void *); /* Function to call. */ + void *__arg; /* Its argument. */ + int __canceltype; /* Saved cancellation type. */ + struct _pthread_cleanup_buffer *__prev; /* Chaining of cleanup functions. */ +}; + +/* Cancellation */ + +enum +{ + PTHREAD_CANCEL_ENABLE, +#define PTHREAD_CANCEL_ENABLE PTHREAD_CANCEL_ENABLE + PTHREAD_CANCEL_DISABLE +#define PTHREAD_CANCEL_DISABLE PTHREAD_CANCEL_DISABLE +}; +enum +{ + PTHREAD_CANCEL_DEFERRED, +#define PTHREAD_CANCEL_DEFERRED PTHREAD_CANCEL_DEFERRED + PTHREAD_CANCEL_ASYNCHRONOUS +#define PTHREAD_CANCEL_ASYNCHRONOUS PTHREAD_CANCEL_ASYNCHRONOUS +}; +#define PTHREAD_CANCELED ((void *) -1) + + +/* Function for handling threads. */ + +/* Create a thread with given attributes ATTR (or default attributes + if ATTR is NULL), and call function START_ROUTINE with given + arguments ARG. */ +extern int pthread_create (pthread_t *__restrict __threadp, + __const pthread_attr_t *__restrict __attr, + void *(*__start_routine) (void *), + void *__restrict __arg) __THROW; + +/* Obtain the identifier of the current thread. */ +extern pthread_t pthread_self (void) __THROW; + +/* Compare two thread identifiers. */ +extern int pthread_equal (pthread_t __thread1, pthread_t __thread2) __THROW; + +/* Terminate calling thread. */ +extern void pthread_exit (void *__retval) __attribute__ ((__noreturn__)); + +/* Make calling thread wait for termination of the thread TH. The + exit status of the thread is stored in *THREAD_RETURN, if THREAD_RETURN + is not NULL. */ +extern int pthread_join (pthread_t __th, void **__thread_return); + +/* Indicate that the thread TH is never to be joined with PTHREAD_JOIN. + The resources of TH will therefore be freed immediately when it + terminates, instead of waiting for another thread to perform PTHREAD_JOIN + on it. */ +extern int pthread_detach (pthread_t __th) __THROW; + + +/* Functions for handling attributes. */ + +/* Initialize thread attribute *ATTR with default attributes + (detachstate is PTHREAD_JOINABLE, scheduling policy is SCHED_OTHER, + no user-provided stack). */ +extern int pthread_attr_init (pthread_attr_t *__attr) __THROW; + +/* Destroy thread attribute *ATTR. */ +extern int pthread_attr_destroy (pthread_attr_t *__attr) __THROW; + +/* Set the `detachstate' attribute in *ATTR according to DETACHSTATE. */ +extern int pthread_attr_setdetachstate (pthread_attr_t *__attr, + int __detachstate) __THROW; + +/* Return in *DETACHSTATE the `detachstate' attribute in *ATTR. */ +extern int pthread_attr_getdetachstate (__const pthread_attr_t *__attr, + int *__detachstate) __THROW; + +/* Set scheduling parameters (priority, etc) in *ATTR according to PARAM. */ +extern int pthread_attr_setschedparam (pthread_attr_t *__restrict __attr, + __const struct sched_param *__restrict + __param) __THROW; + +/* Return in *PARAM the scheduling parameters of *ATTR. */ +extern int pthread_attr_getschedparam (__const pthread_attr_t *__restrict + __attr, + struct sched_param *__restrict __param) + __THROW; + +/* Set scheduling policy in *ATTR according to POLICY. */ +extern int pthread_attr_setschedpolicy (pthread_attr_t *__attr, int __policy) + __THROW; + +/* Return in *POLICY the scheduling policy of *ATTR. */ +extern int pthread_attr_getschedpolicy (__const pthread_attr_t *__restrict + __attr, int *__restrict __policy) + __THROW; + +/* Set scheduling inheritance mode in *ATTR according to INHERIT. */ +extern int pthread_attr_setinheritsched (pthread_attr_t *__attr, + int __inherit) __THROW; + +/* Return in *INHERIT the scheduling inheritance mode of *ATTR. */ +extern int pthread_attr_getinheritsched (__const pthread_attr_t *__restrict + __attr, int *__restrict __inherit) + __THROW; + +/* Set scheduling contention scope in *ATTR according to SCOPE. */ +extern int pthread_attr_setscope (pthread_attr_t *__attr, int __scope) + __THROW; + +/* Return in *SCOPE the scheduling contention scope of *ATTR. */ +extern int pthread_attr_getscope (__const pthread_attr_t *__restrict __attr, + int *__restrict __scope) __THROW; + +#ifdef __USE_UNIX98 +/* Set the size of the guard area at the bottom of the thread. */ +extern int pthread_attr_setguardsize (pthread_attr_t *__attr, + size_t __guardsize) __THROW; + +/* Get the size of the guard area at the bottom of the thread. */ +extern int pthread_attr_getguardsize (__const pthread_attr_t *__restrict + __attr, size_t *__restrict __guardsize) + __THROW; +#endif + +#if 0 /* uClibc: deprecated stuff disabled. def __UCLIBC_SUSV3_LEGACY__ */ +/* Set the starting address of the stack of the thread to be created. + Depending on whether the stack grows up or down the value must either + be higher or lower than all the address in the memory block. The + minimal size of the block must be PTHREAD_STACK_SIZE. */ +extern int pthread_attr_setstackaddr (pthread_attr_t *__attr, + void *__stackaddr) __THROW; + +/* Return the previously set address for the stack. */ +extern int pthread_attr_getstackaddr (__const pthread_attr_t *__restrict + __attr, void **__restrict __stackaddr) + __THROW; +#endif + +#ifdef __USE_XOPEN2K +/* The following two interfaces are intended to replace the last two. They + require setting the address as well as the size since only setting the + address will make the implementation on some architectures impossible. */ +extern int pthread_attr_setstack (pthread_attr_t *__attr, void *__stackaddr, + size_t __stacksize) __THROW; + +/* Return the previously set address for the stack. */ +extern int pthread_attr_getstack (__const pthread_attr_t *__restrict __attr, + void **__restrict __stackaddr, + size_t *__restrict __stacksize) __THROW; +#endif + +/* Add information about the minimum stack size needed for the thread + to be started. This size must never be less than PTHREAD_STACK_SIZE + and must also not exceed the system limits. */ +extern int pthread_attr_setstacksize (pthread_attr_t *__attr, + size_t __stacksize) __THROW; + +/* Return the currently used minimal stack size. */ +extern int pthread_attr_getstacksize (__const pthread_attr_t *__restrict + __attr, size_t *__restrict __stacksize) + __THROW; + +#if 0 +/* Not yet implemented in uClibc! */ + +#ifdef __USE_GNU +/* Initialize thread attribute *ATTR with attributes corresponding to the + already running thread TH. It shall be called on uninitialized ATTR + and destroyed with pthread_attr_destroy when no longer needed. */ +extern int pthread_getattr_np (pthread_t __th, pthread_attr_t *__attr) __THROW; +#endif +#endif + +/* Functions for scheduling control. */ + +/* Set the scheduling parameters for TARGET_THREAD according to POLICY + and *PARAM. */ +extern int pthread_setschedparam (pthread_t __target_thread, int __policy, + __const struct sched_param *__param) + __THROW; + +/* Return in *POLICY and *PARAM the scheduling parameters for TARGET_THREAD. */ +extern int pthread_getschedparam (pthread_t __target_thread, + int *__restrict __policy, + struct sched_param *__restrict __param) + __THROW; + +#ifdef __USE_UNIX98 +/* Determine level of concurrency. */ +extern int pthread_getconcurrency (void) __THROW; + +/* Set new concurrency level to LEVEL. */ +extern int pthread_setconcurrency (int __level) __THROW; +#endif + +#ifdef __USE_GNU +/* Same thing, different name */ +#define pthread_yield() sched_yield() +#endif + +/* Functions for mutex handling. */ + +/* Initialize MUTEX using attributes in *MUTEX_ATTR, or use the + default values if later is NULL. */ +extern int pthread_mutex_init (pthread_mutex_t *__restrict __mutex, + __const pthread_mutexattr_t *__restrict + __mutex_attr) __THROW; + +/* Destroy MUTEX. */ +extern int pthread_mutex_destroy (pthread_mutex_t *__mutex) __THROW; + +/* Try to lock MUTEX. */ +extern int pthread_mutex_trylock (pthread_mutex_t *__mutex) __THROW; + +/* Wait until lock for MUTEX becomes available and lock it. */ +extern int pthread_mutex_lock (pthread_mutex_t *__mutex) __THROW; + +#ifdef __USE_XOPEN2K +/* Wait until lock becomes available, or specified time passes. */ +extern int pthread_mutex_timedlock (pthread_mutex_t *__restrict __mutex, + __const struct timespec *__restrict + __abstime) __THROW; +#endif + +/* Unlock MUTEX. */ +extern int pthread_mutex_unlock (pthread_mutex_t *__mutex) __THROW; + + +/* Functions for handling mutex attributes. */ + +/* Initialize mutex attribute object ATTR with default attributes + (kind is PTHREAD_MUTEX_TIMED_NP). */ +extern int pthread_mutexattr_init (pthread_mutexattr_t *__attr) __THROW; + +/* Destroy mutex attribute object ATTR. */ +extern int pthread_mutexattr_destroy (pthread_mutexattr_t *__attr) __THROW; + +/* Get the process-shared flag of the mutex attribute ATTR. */ +extern int pthread_mutexattr_getpshared (__const pthread_mutexattr_t * + __restrict __attr, + int *__restrict __pshared) __THROW; + +/* Set the process-shared flag of the mutex attribute ATTR. */ +extern int pthread_mutexattr_setpshared (pthread_mutexattr_t *__attr, + int __pshared) __THROW; + +#ifdef __USE_UNIX98 +/* Set the mutex kind attribute in *ATTR to KIND (either PTHREAD_MUTEX_NORMAL, + PTHREAD_MUTEX_RECURSIVE, PTHREAD_MUTEX_ERRORCHECK, or + PTHREAD_MUTEX_DEFAULT). */ +extern int pthread_mutexattr_settype (pthread_mutexattr_t *__attr, int __kind) + __THROW; + +/* Return in *KIND the mutex kind attribute in *ATTR. */ +extern int pthread_mutexattr_gettype (__const pthread_mutexattr_t *__restrict + __attr, int *__restrict __kind) __THROW; +#endif + + +/* Functions for handling conditional variables. */ + +/* Initialize condition variable COND using attributes ATTR, or use + the default values if later is NULL. */ +extern int pthread_cond_init (pthread_cond_t *__restrict __cond, + __const pthread_condattr_t *__restrict + __cond_attr) __THROW; + +/* Destroy condition variable COND. */ +extern int pthread_cond_destroy (pthread_cond_t *__cond) __THROW; + +/* Wake up one thread waiting for condition variable COND. */ +extern int pthread_cond_signal (pthread_cond_t *__cond) __THROW; + +/* Wake up all threads waiting for condition variables COND. */ +extern int pthread_cond_broadcast (pthread_cond_t *__cond) __THROW; + +/* Wait for condition variable COND to be signaled or broadcast. + MUTEX is assumed to be locked before. */ +extern int pthread_cond_wait (pthread_cond_t *__restrict __cond, + pthread_mutex_t *__restrict __mutex); + +/* Wait for condition variable COND to be signaled or broadcast until + ABSTIME. MUTEX is assumed to be locked before. ABSTIME is an + absolute time specification; zero is the beginning of the epoch + (00:00:00 GMT, January 1, 1970). */ +extern int pthread_cond_timedwait (pthread_cond_t *__restrict __cond, + pthread_mutex_t *__restrict __mutex, + __const struct timespec *__restrict + __abstime); + +/* Functions for handling condition variable attributes. */ + +/* Initialize condition variable attribute ATTR. */ +extern int pthread_condattr_init (pthread_condattr_t *__attr) __THROW; + +/* Destroy condition variable attribute ATTR. */ +extern int pthread_condattr_destroy (pthread_condattr_t *__attr) __THROW; + +/* Get the process-shared flag of the condition variable attribute ATTR. */ +extern int pthread_condattr_getpshared (__const pthread_condattr_t * + __restrict __attr, + int *__restrict __pshared) __THROW; + +/* Set the process-shared flag of the condition variable attribute ATTR. */ +extern int pthread_condattr_setpshared (pthread_condattr_t *__attr, + int __pshared) __THROW; + + +#if defined __USE_UNIX98 || defined __USE_XOPEN2K +/* Functions for handling read-write locks. */ + +/* Initialize read-write lock RWLOCK using attributes ATTR, or use + the default values if later is NULL. */ +extern int pthread_rwlock_init (pthread_rwlock_t *__restrict __rwlock, + __const pthread_rwlockattr_t *__restrict + __attr) __THROW; + +/* Destroy read-write lock RWLOCK. */ +extern int pthread_rwlock_destroy (pthread_rwlock_t *__rwlock) __THROW; + +/* Acquire read lock for RWLOCK. */ +extern int pthread_rwlock_rdlock (pthread_rwlock_t *__rwlock) __THROW; + +/* Try to acquire read lock for RWLOCK. */ +extern int pthread_rwlock_tryrdlock (pthread_rwlock_t *__rwlock) __THROW; + +# ifdef __USE_XOPEN2K +/* Try to acquire read lock for RWLOCK or return after specfied time. */ +extern int pthread_rwlock_timedrdlock (pthread_rwlock_t *__restrict __rwlock, + __const struct timespec *__restrict + __abstime) __THROW; +# endif + +/* Acquire write lock for RWLOCK. */ +extern int pthread_rwlock_wrlock (pthread_rwlock_t *__rwlock) __THROW; + +/* Try to acquire write lock for RWLOCK. */ +extern int pthread_rwlock_trywrlock (pthread_rwlock_t *__rwlock) __THROW; + +# ifdef __USE_XOPEN2K +/* Try to acquire write lock for RWLOCK or return after specfied time. */ +extern int pthread_rwlock_timedwrlock (pthread_rwlock_t *__restrict __rwlock, + __const struct timespec *__restrict + __abstime) __THROW; +# endif + +/* Unlock RWLOCK. */ +extern int pthread_rwlock_unlock (pthread_rwlock_t *__rwlock) __THROW; + + +/* Functions for handling read-write lock attributes. */ + +/* Initialize attribute object ATTR with default values. */ +extern int pthread_rwlockattr_init (pthread_rwlockattr_t *__attr) __THROW; + +/* Destroy attribute object ATTR. */ +extern int pthread_rwlockattr_destroy (pthread_rwlockattr_t *__attr) __THROW; + +/* Return current setting of process-shared attribute of ATTR in PSHARED. */ +extern int pthread_rwlockattr_getpshared (__const pthread_rwlockattr_t * + __restrict __attr, + int *__restrict __pshared) __THROW; + +/* Set process-shared attribute of ATTR to PSHARED. */ +extern int pthread_rwlockattr_setpshared (pthread_rwlockattr_t *__attr, + int __pshared) __THROW; + +/* Return current setting of reader/writer preference. */ +extern int pthread_rwlockattr_getkind_np (__const pthread_rwlockattr_t *__attr, + int *__pref) __THROW; + +/* Set reader/write preference. */ +extern int pthread_rwlockattr_setkind_np (pthread_rwlockattr_t *__attr, + int __pref) __THROW; +#endif + +#if 0 +/* Not yet implemented in uClibc! */ + +#ifdef __USE_XOPEN2K +/* The IEEE Std. 1003.1j-2000 introduces functions to implement + spinlocks. */ + +/* Initialize the spinlock LOCK. If PSHARED is nonzero the spinlock can + be shared between different processes. */ +extern int pthread_spin_init (pthread_spinlock_t *__lock, int __pshared) + __THROW; + +/* Destroy the spinlock LOCK. */ +extern int pthread_spin_destroy (pthread_spinlock_t *__lock) __THROW; + +/* Wait until spinlock LOCK is retrieved. */ +extern int pthread_spin_lock (pthread_spinlock_t *__lock) __THROW; + +/* Try to lock spinlock LOCK. */ +extern int pthread_spin_trylock (pthread_spinlock_t *__lock) __THROW; + +/* Release spinlock LOCK. */ +extern int pthread_spin_unlock (pthread_spinlock_t *__lock) __THROW; + + +/* Barriers are a also a new feature in 1003.1j-2000. */ + +extern int pthread_barrier_init (pthread_barrier_t *__restrict __barrier, + __const pthread_barrierattr_t *__restrict + __attr, unsigned int __count) __THROW; + +extern int pthread_barrier_destroy (pthread_barrier_t *__barrier) __THROW; + +extern int pthread_barrierattr_init (pthread_barrierattr_t *__attr) __THROW; + +extern int pthread_barrierattr_destroy (pthread_barrierattr_t *__attr) __THROW; + +extern int pthread_barrierattr_getpshared (__const pthread_barrierattr_t * + __restrict __attr, + int *__restrict __pshared) __THROW; + +extern int pthread_barrierattr_setpshared (pthread_barrierattr_t *__attr, + int __pshared) __THROW; + +extern int pthread_barrier_wait (pthread_barrier_t *__barrier) __THROW; +#endif +#endif + + +/* Functions for handling thread-specific data. */ + +/* Create a key value identifying a location in the thread-specific + data area. Each thread maintains a distinct thread-specific data + area. DESTR_FUNCTION, if non-NULL, is called with the value + associated to that key when the key is destroyed. + DESTR_FUNCTION is not called if the value associated is NULL when + the key is destroyed. */ +extern int pthread_key_create (pthread_key_t *__key, + void (*__destr_function) (void *)) __THROW; + +/* Destroy KEY. */ +extern int pthread_key_delete (pthread_key_t __key) __THROW; + +/* Store POINTER in the thread-specific data slot identified by KEY. */ +extern int pthread_setspecific (pthread_key_t __key, + __const void *__pointer) __THROW; + +/* Return current value of the thread-specific data slot identified by KEY. */ +extern void *pthread_getspecific (pthread_key_t __key) __THROW; + + +/* Functions for handling initialization. */ + +/* Guarantee that the initialization function INIT_ROUTINE will be called + only once, even if pthread_once is executed several times with the + same ONCE_CONTROL argument. ONCE_CONTROL must point to a static or + extern variable initialized to PTHREAD_ONCE_INIT. + + The initialization functions might throw exception which is why + this function is not marked with __THROW. */ +extern int pthread_once (pthread_once_t *__once_control, + void (*__init_routine) (void)); + + +/* Functions for handling cancellation. */ + +/* Set cancelability state of current thread to STATE, returning old + state in *OLDSTATE if OLDSTATE is not NULL. */ +extern int pthread_setcancelstate (int __state, int *__oldstate); + +/* Set cancellation state of current thread to TYPE, returning the old + type in *OLDTYPE if OLDTYPE is not NULL. */ +extern int pthread_setcanceltype (int __type, int *__oldtype); + +/* Cancel THREAD immediately or at the next possibility. */ +extern int pthread_cancel (pthread_t __cancelthread); + +/* Test for pending cancellation for the current thread and terminate + the thread as per pthread_exit(PTHREAD_CANCELED) if it has been + cancelled. */ +extern void pthread_testcancel (void); + + +/* Install a cleanup handler: ROUTINE will be called with arguments ARG + when the thread is cancelled or calls pthread_exit. ROUTINE will also + be called with arguments ARG when the matching pthread_cleanup_pop + is executed with non-zero EXECUTE argument. + pthread_cleanup_push and pthread_cleanup_pop are macros and must always + be used in matching pairs at the same nesting level of braces. */ + +#define pthread_cleanup_push(routine,arg) \ + { struct _pthread_cleanup_buffer _buffer; \ + _pthread_cleanup_push (&_buffer, (routine), (arg)); + +extern void _pthread_cleanup_push (struct _pthread_cleanup_buffer *__buffer, + void (*__routine) (void *), + void *__arg) __THROW; + +/* Remove a cleanup handler installed by the matching pthread_cleanup_push. + If EXECUTE is non-zero, the handler function is called. */ + +#define pthread_cleanup_pop(execute) \ + _pthread_cleanup_pop (&_buffer, (execute)); } + +extern void _pthread_cleanup_pop (struct _pthread_cleanup_buffer *__buffer, + int __execute) __THROW; + +/* Install a cleanup handler as pthread_cleanup_push does, but also + saves the current cancellation type and set it to deferred cancellation. */ + +#ifdef __USE_GNU +# define pthread_cleanup_push_defer_np(routine,arg) \ + { struct _pthread_cleanup_buffer _buffer; \ + _pthread_cleanup_push_defer (&_buffer, (routine), (arg)); + +extern void _pthread_cleanup_push_defer (struct _pthread_cleanup_buffer *__buffer, + void (*__routine) (void *), + void *__arg) __THROW; +extern void __pthread_cleanup_push_defer (struct _pthread_cleanup_buffer *__buffer, + void (*__routine) (void *), + void *__arg) __THROW; + +/* Remove a cleanup handler as pthread_cleanup_pop does, but also + restores the cancellation type that was in effect when the matching + pthread_cleanup_push_defer was called. */ + +# define pthread_cleanup_pop_restore_np(execute) \ + _pthread_cleanup_pop_restore (&_buffer, (execute)); } + +extern void _pthread_cleanup_pop_restore (struct _pthread_cleanup_buffer *__buffer, + int __execute) __THROW; +extern void __pthread_cleanup_pop_restore (struct _pthread_cleanup_buffer *__buffer, + int __execute) __THROW; +#endif + + +#if 0 +/* Not yet implemented in uClibc! */ + +#ifdef __USE_XOPEN2K +/* Get ID of CPU-time clock for thread THREAD_ID. */ +extern int pthread_getcpuclockid (pthread_t __thread_id, + clockid_t *__clock_id) __THROW; +#endif +#endif + + +/* Functions for handling signals. */ +#include + + +/* Functions for handling process creation and process execution. */ + +/* Install handlers to be called when a new process is created with FORK. + The PREPARE handler is called in the parent process just before performing + FORK. The PARENT handler is called in the parent process just after FORK. + The CHILD handler is called in the child process. Each of the three + handlers can be NULL, meaning that no handler needs to be called at that + point. + PTHREAD_ATFORK can be called several times, in which case the PREPARE + handlers are called in LIFO order (last added with PTHREAD_ATFORK, + first called before FORK), and the PARENT and CHILD handlers are called + in FIFO (first added, first called). */ + +extern int pthread_atfork (void (*__prepare) (void), + void (*__parent) (void), + void (*__child) (void)) __THROW; + +/* Terminate all threads in the program except the calling process. + Should be called just before invoking one of the exec*() functions. */ + +extern void pthread_kill_other_threads_np (void) __THROW; + +__END_DECLS + +#endif /* pthread.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/pthread/tls.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/pthread/tls.h new file mode 100644 index 00000000..6a23ec05 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/pthread/tls.h @@ -0,0 +1,81 @@ +/* Definition for thread-local data handling. Generic version. + Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* By default no TLS support is available. This is signaled by the + absence of the symbol USE_TLS. */ +#undef USE_TLS + + +/* An architecture-specific version of this file has to defined a + number of symbols: + + TLS_TCB_AT_TP or TLS_DTV_AT_TP + + The presence of one of these symbols signals which variant of + the TLS ABI is used. There are in the moment two variants + available: + + * the thread pointer points to a thread control block + + * the thread pointer points to the dynamic thread vector + + + TLS_TCB_SIZE + + This is the size of the thread control block structure. How + this is actually defined depends on the ABI. The thread control + block could be internal descriptor of the thread library or + just a data structure which allows finding the DTV. + + TLS_INIT_TCB_SIZE + + Similarly, but this value is only used at startup and in the + dynamic linker itself. There are no threads in use at that time. + + + TLS_TCB_ALIGN + + Alignment requirements for the TCB structure. + + TLS_INIT_TCB_ALIGN + + Similarly, but for the structure used at startup time. + + + INSTALL_DTV(tcb, init_dtv) + + This macro must install the given initial DTV into the thread control + block TCB. The normal runtime functionality must then be able to + use the value. + + + TLS_INIT_TP(tcb, firstcall) + + This macro must initialize the thread pointer to enable normal TLS + operation. The first parameter is a pointer to the thread control + block. The second parameter specifies whether this is the first + call for the TCB. ld.so calls this macro more than once. + + + THREAD_DTV() + + This macro returns the address of the DTV of the current thread. + This normally is done using the the thread register which points + to the dtv or the TCB (from which the DTV can found). + */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/sh/pt-machine.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/sh/pt-machine.h new file mode 100644 index 00000000..793f80b2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/sh/pt-machine.h @@ -0,0 +1,82 @@ +/* Machine-dependent pthreads configuration and inline functions. + SuperH version. + Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Niibe Yutaka . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _PT_MACHINE_H +#define _PT_MACHINE_H 1 + +#include + +#ifndef __ASSEMBLER__ +#ifndef PT_EI +# define PT_EI __extern_always_inline +#endif + +extern long int testandset (int *spinlock); + +/* Spinlock implementation; required. */ +PT_EI long int +testandset (int *spinlock) +{ + int ret; + + __asm__ __volatile__( + "tas.b @%1\n\t" + "movt %0" + : "=r" (ret) + : "r" (spinlock) + : "memory", "cc"); + + return (ret == 0); +} + +/* We want the OS to assign stack addresses. */ +#define FLOATING_STACKS 1 + +/* Maximum size of the stack if the rlimit is unlimited. */ +#define ARCH_STACK_MAX_SIZE 32*1024*1024 + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#define CURRENT_STACK_FRAME stack_pointer +register char * stack_pointer __asm__ ("r15"); + +/* Return the thread descriptor for the current thread. */ +struct _pthread_descr_struct; +#define THREAD_SELF \ + ({ struct _pthread_descr_struct *self; \ + __asm__("stc gbr,%0" : "=r" (self)); self;}) + +/* Initialize the thread-unique value. */ +#define INIT_THREAD_SELF(descr, nr) \ + ({ __asm__ __volatile__("ldc %0,gbr" : : "r" (descr));}) + +/* Access to data in the thread descriptor is easy. */ +#define THREAD_GETMEM(descr, member) \ + ((void) sizeof (descr), THREAD_SELF->member) +#define THREAD_GETMEM_NC(descr, member) \ + ((void) sizeof (descr), THREAD_SELF->member) +#define THREAD_SETMEM(descr, member, value) \ + ((void) sizeof (descr), THREAD_SELF->member = (value)) +#define THREAD_SETMEM_NC(descr, member, value) \ + ((void) sizeof (descr), THREAD_SELF->member = (value)) +#endif /* __ASSEMBLER__ */ + +#endif /* pt-machine.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/sh/tls.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/sh/tls.h new file mode 100644 index 00000000..7bc29800 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/sh/tls.h @@ -0,0 +1,117 @@ +/* Definition for thread-local data handling. linuxthreads/SH version. + Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _TLS_H +#define _TLS_H + +# include + +#ifndef __ASSEMBLER__ +# include +# include +# include + +/* Type for the dtv. */ +typedef union dtv +{ + size_t counter; + void *pointer; +} dtv_t; + + +typedef struct +{ + void *tcb; /* Pointer to the TCB. Not necessary the + thread descriptor used by libpthread. */ + dtv_t *dtv; + void *self; /* Pointer to the thread descriptor. */ +} tcbhead_t; + + +/* We can support TLS only if the floating-stack support is available. */ +#if defined FLOATING_STACKS && defined HAVE_TLS_SUPPORT + +/* Get system call information. */ +# include + +/* Signal that TLS support is available. */ +//# define USE_TLS 1 + + +/* Get the thread descriptor definition. */ +# include + +/* This is the size of the initial TCB. */ +# define TLS_INIT_TCB_SIZE sizeof (tcbhead_t) + +/* Alignment requirements for the initial TCB. */ +# define TLS_INIT_TCB_ALIGN __alignof__ (tcbhead_t) + +/* This is the size of the TCB. */ +# define TLS_TCB_SIZE sizeof (struct _pthread_descr_struct) + +/* Alignment requirements for the TCB. */ +# define TLS_TCB_ALIGN __alignof__ (struct _pthread_descr_struct) + +/* The TLS blocks start right after the TCB. */ +# define TLS_DTV_AT_TP 1 + + +/* Install the dtv pointer. The pointer passed is to the element with + index -1 which contain the length. */ +# define INSTALL_DTV(descr, dtvp) \ + ((tcbhead_t *) (descr))->dtv = dtvp + 1 + +/* Install new dtv for current thread. */ +# define INSTALL_NEW_DTV(dtv) \ + ({ struct _pthread_descr_struct *__descr; \ + THREAD_SETMEM (__descr, p_header.data.dtvp, (dtv)); }) + +/* Return dtv of given thread descriptor. */ +# define GET_DTV(descr) \ + (((tcbhead_t *) (descr))->dtv) + +/* Code to initially initialize the thread pointer. This might need + special attention since 'errno' is not yet available and if the + operation can cause a failure 'errno' must not be touched. */ +# define TLS_INIT_TP(descr, secondcall) \ + ({ \ + void *_descr = (descr); \ + int result; \ + tcbhead_t *head = _descr; \ + \ + head->tcb = _descr; \ + /* For now the thread descriptor is at the same address. */ \ + head->self = _descr; \ + \ + __asm__ ("ldc %0,gbr" : : "r" (_descr)); \ + \ + 0; \ + }) + + +/* Return the address of the dtv for the current thread. */ +# define THREAD_DTV() \ + ({ struct _pthread_descr_struct *__descr; \ + THREAD_GETMEM (__descr, p_header.data.dtvp); }) + +#endif /* FLOATING_STACKS && HAVE_TLS_SUPPORT */ +#endif /* __ASSEMBLER__ */ + +#endif /* tls.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/sh64/Makefile.arch b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/sh64/Makefile.arch new file mode 100644 index 00000000..ddb56645 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/sh64/Makefile.arch @@ -0,0 +1,30 @@ +# Makefile for uClibc +# +# Copyright (C) 2003 Paul Mundt +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +libpthread_ARCH_DIR:=$(top_srcdir)libpthread/linuxthreads.old/sysdeps/sh64 +libpthread_ARCH_OUT:=$(top_builddir)libpthread/linuxthreads.old/sysdeps/sh64 + +libpthread_ARCH_SRC:=$(wildcard $(libpthread_ARCH_DIR)/*.c) +libpthread_ARCH_OBJ:=$(patsubst $(libpthread_ARCH_DIR)/%.c,$(libpthread_ARCH_OUT)/%.o,$(libpthread_ARCH_SRC)) + +libpthread-a-y+=$(libpthread_ARCH_OBJ) +libpthread-so-y+=$(libpthread_ARCH_OBJ:.o=.os) + +libpthread-multi-y+=$(libpthread_ARCH_SRC) + +objclean-y += CLEAN_$($(top_builddir),,$(libpthread_ARCH_OUT)) + +# We need to build as SHcompact for tas.. +$(libpthread_ARCH_OBJ): %.o : %.c + $(compile.c:32media=compact) + +$(libpthread_ARCH_OBJ:.o=.os): %.os : %.c + $(compile.c:32media=compact) + +CLEAN_$($(top_builddir),,$(libpthread_ARCH_OUT)): + $(do_rm) $(addprefix $(libpthread_ARCH_OUT)/*., o os) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/sh64/pt-machine.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/sh64/pt-machine.c new file mode 100644 index 00000000..bd2c401f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/sh64/pt-machine.c @@ -0,0 +1,47 @@ +/* Cloned for uClibc by Paul Mundt, December 2003 */ +/* Modified by SuperH, Inc. September 2003 */ + +/* Machine-dependent pthreads configuration and inline functions. + SH5 version. + Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Niibe Yutaka . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include "pt-machine.h" + +/* Spinlock implementation; required. */ + +/* The SH5 does not have a suitable test-and-set instruction (SWAP only + operates on an aligned quad word). So we use the SH4 version instead. + This must be seperately compiled in SHcompact mode, so it cannot be + inline. */ + +long int testandset (int *spinlock) +{ + int ret; + + __asm__ __volatile__( + "tas.b @%1\n\t" + "movt %0" + : "=r" (ret) + : "r" (spinlock) + : "memory", "cc"); + + return (ret == 0); +} + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/sh64/pt-machine.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/sh64/pt-machine.h new file mode 100644 index 00000000..b87448a7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/sh64/pt-machine.h @@ -0,0 +1,39 @@ +/* Cloned for uClibc by Paul Mundt, December 2003 */ +/* Modified by SuperH, Inc. September 2003 */ + +/* Machine-dependent pthreads configuration and inline functions. + SuperH version. + Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Niibe Yutaka . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _PT_MACHINE_H +#define _PT_MACHINE_H 1 + +#include + +#ifndef PT_EI +# define PT_EI __extern_always_inline +#endif + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#define CURRENT_STACK_FRAME stack_pointer +register char * stack_pointer __asm__ ("r15"); + +#endif /* pt-machine.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/sparc/pt-machine.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/sparc/pt-machine.h new file mode 100644 index 00000000..ab90810f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/sparc/pt-machine.h @@ -0,0 +1,8 @@ +#include +#include + +#if __WORDSIZE == 32 +# include "sparc32/pt-machine.h" +#else +# include "sparc64/pt-machine.h" +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/sparc/sparc32/pt-machine.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/sparc/sparc32/pt-machine.h new file mode 100644 index 00000000..43c05f2a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/sparc/sparc32/pt-machine.h @@ -0,0 +1,83 @@ +/* Machine-dependent pthreads configuration and inline functions. + sparc version. + Copyright (C) 1996-1998, 2000-2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _PT_MACHINE_H +#define _PT_MACHINE_H 1 + +#ifndef PT_EI +# define PT_EI __extern_always_inline +#endif + +extern long int testandset (int *spinlock); +extern int __compare_and_swap (long int *p, long int oldval, long int newval); + +/* Spinlock implementation; required. */ +PT_EI long int +testandset (int *spinlock) +{ + int ret; + + __asm__ __volatile__("ldstub %1,%0" + : "=r"(ret), "=m"(*spinlock) + : "m"(*spinlock)); + + return ret; +} + + +/* Memory barrier; default is to do nothing */ +#define MEMORY_BARRIER() __asm__ __volatile__("stbar" : : : "memory") + + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#define CURRENT_STACK_FRAME (stack_pointer + (2 * 64)) +register char *stack_pointer __asm__("%sp"); + + +/* Registers %g6 and %g7 are reserved by the ABI for "system use". + %g7 is specified in the TLS ABI as thread pointer -- we do the same. */ +struct _pthread_descr_struct; +register struct _pthread_descr_struct *__thread_self __asm__("%g7"); + +/* Return the thread descriptor for the current thread. */ +#define THREAD_SELF __thread_self + +/* Initialize the thread-unique value. */ +#define INIT_THREAD_SELF(descr, nr) (__thread_self = (descr)) + +/* Access to data in the thread descriptor is easy. */ +#define THREAD_GETMEM(descr, member) \ + ((void) sizeof (descr), THREAD_SELF->member) +#define THREAD_GETMEM_NC(descr, member) \ + ((void) sizeof (descr), THREAD_SELF->member) +#define THREAD_SETMEM(descr, member, value) \ + ((void) sizeof (descr), THREAD_SELF->member = (value)) +#define THREAD_SETMEM_NC(descr, member, value) \ + ((void) sizeof (descr), THREAD_SELF->member = (value)) + +/* We want the OS to assign stack addresses. */ +#define FLOATING_STACKS 1 + +/* Maximum size of the stack if the rlimit is unlimited. */ +#define ARCH_STACK_MAX_SIZE 8*1024*1024 + +#endif /* pt-machine.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/sparc/sparc64/pt-machine.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/sparc/sparc64/pt-machine.h new file mode 100644 index 00000000..815d70e8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/sparc/sparc64/pt-machine.h @@ -0,0 +1,105 @@ +/* Machine-dependent pthreads configuration and inline functions. + Sparc v9 version. + Copyright (C) 1997-2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If + not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef _PT_MACHINE_H +#define _PT_MACHINE_H 1 + +#ifndef PT_EI +# define PT_EI __extern_always_inline +#endif + +extern long int testandset (int *spinlock); +extern int __compare_and_swap (long int *p, long int oldval, long int newval); + +/* Spinlock implementation; required. */ +PT_EI long int +testandset (int *spinlock) +{ + int ret; + + __asm__ __volatile__("ldstub %1,%0" + : "=r" (ret), "=m" (*spinlock) : "m" (*spinlock)); + + return ret; +} + + +/* Memory barrier; default is to do nothing */ +#define MEMORY_BARRIER() \ + __asm__ __volatile__("membar #LoadLoad | #LoadStore | #StoreLoad | #StoreStore" : : : "memory") +/* Read barrier. */ +#define READ_MEMORY_BARRIER() \ + __asm__ __volatile__("membar #LoadLoad | #LoadStore" : : : "memory") +/* Write barrier. */ +#define WRITE_MEMORY_BARRIER() \ + __asm__ __volatile__("membar #StoreLoad | #StoreStore" : : : "memory") + + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#define CURRENT_STACK_FRAME (stack_pointer + (2 * 128)) +register char *stack_pointer __asm__ ("%sp"); + + +/* Registers %g6 and %g7 are reserved by the ABI for "system use". The + TLS ABI specifies %g7 as the thread pointer. */ +struct _pthread_descr_struct; +register struct _pthread_descr_struct *__thread_self __asm__ ("%g7"); + +/* Return the thread descriptor for the current thread. */ +#define THREAD_SELF __thread_self + +/* Initialize the thread-unique value. */ +#define INIT_THREAD_SELF(descr, nr) (__thread_self = (descr)) + + +/* Compare-and-swap for semaphores. */ + +#define HAS_COMPARE_AND_SWAP +PT_EI int +__compare_and_swap (long int *p, long int oldval, long int newval) +{ + long int readval; + + __asm__ __volatile__ ("casx [%4], %2, %0" + : "=r"(readval), "=m"(*p) + : "r"(oldval), "m"(*p), "r"(p), "0"(newval)); + MEMORY_BARRIER(); + return readval == oldval; +} + +/* Access to data in the thread descriptor is easy. */ +#define THREAD_GETMEM(descr, member) \ + ((void) sizeof (descr), THREAD_SELF->member) +#define THREAD_GETMEM_NC(descr, member) \ + ((void) sizeof (descr), THREAD_SELF->member) +#define THREAD_SETMEM(descr, member, value) \ + ((void) sizeof (descr), THREAD_SELF->member = (value)) +#define THREAD_SETMEM_NC(descr, member, value) \ + ((void) sizeof (descr), THREAD_SELF->member = (value)) + +/* We want the OS to assign stack addresses. */ +#define FLOATING_STACKS 1 + +/* Maximum size of the stack if the rlimit is unlimited. */ +#define ARCH_STACK_MAX_SIZE 32*1024*1024 + +#endif /* pt-machine.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/v850/pt-machine.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/v850/pt-machine.h new file mode 100644 index 00000000..34de63b9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/v850/pt-machine.h @@ -0,0 +1,52 @@ +/* + * sysdeps/v850/pt-machine.h -- v850-specific pthread definitions + * + * Copyright (C) 2002 NEC Electronics Corporation + * Copyright (C) 2002 Miles Bader + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License. See the file COPYING.LIB in the main + * directory of this archive for more details. + * + * Written by Miles Bader + */ + +#ifndef _PT_MACHINE_H +#define _PT_MACHINE_H 1 + +#include + +#ifndef PT_EI +# define PT_EI __extern_always_inline +#endif + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#define CURRENT_STACK_FRAME __stack_pointer +register char *__stack_pointer __asm__ ("sp"); + +#define HAS_COMPARE_AND_SWAP + +/* Atomically: If *PTR == OLD, set *PTR to NEW and return true, + otherwise do nothing and return false. */ +PT_EI int +__compare_and_swap (long *ptr, long old, long new) +{ + unsigned long psw; + + /* disable interrupts */ + __asm__ __volatile__ ("stsr psw, %0; di" : "=&r" (psw)); + + if (likely (*ptr == old)) + { + *ptr = new; + __asm__ __volatile__ ("ldsr %0, psw" :: "r" (psw)); /* re-enable */ + return 1; + } + else + { + __asm__ __volatile__ ("ldsr %0, psw" :: "r" (psw)); /* re-enable */ + return 0; + } +} +#endif /* pt-machine.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/x86_64/pt-machine.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/x86_64/pt-machine.h new file mode 100644 index 00000000..ce07bbb0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/x86_64/pt-machine.h @@ -0,0 +1,85 @@ +/* Machine-dependent pthreads configuration and inline functions. + x86-64 version. + Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _PT_MACHINE_H +#define _PT_MACHINE_H 1 + +#include + +#ifndef __ASSEMBLER__ +# include /* For offsetof. */ +# include /* For abort(). */ +# include + + +# ifndef PT_EI +# define PT_EI __extern_always_inline +# endif + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +# define CURRENT_STACK_FRAME stack_pointer +register char * stack_pointer __asm__ ("%rsp") __attribute_used__; + + +/* Spinlock implementation; required. */ +PT_EI long int +testandset (int *__spinlock) +{ + long int ret; + + __asm__ __volatile__ ( + "xchgl %k0, %1" + : "=r"(ret), "=m"(*__spinlock) + : "0"(1), "m"(*__spinlock) + : "memory"); + + return ret; +} + + +/* Compare-and-swap for semaphores. */ +# define HAS_COMPARE_AND_SWAP + +PT_EI int +__compare_and_swap (long int *__p, long int __oldval, long int __newval) +{ + char ret; + long int readval; + + __asm__ __volatile__ ("lock; cmpxchgq %3, %1; sete %0" + : "=q" (ret), "=m" (*__p), "=a" (readval) + : "r" (__newval), "m" (*__p), "a" (__oldval) + : "memory"); + return ret; +} + +#endif /* !__ASSEMBLER__ */ + +/* We want the OS to assign stack addresses. */ +#define FLOATING_STACKS 1 + +/* Maximum size of the stack if the rlimit is unlimited. */ +#define ARCH_STACK_MAX_SIZE 32*1024*1024 + +/* The ia32e really want some help to prevent overheating. */ +#define BUSY_WAIT_NOP __asm__ ("rep; nop") + +#endif /* pt-machine.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/x86_64/tls.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/x86_64/tls.h new file mode 100644 index 00000000..5e7239d1 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/x86_64/tls.h @@ -0,0 +1,134 @@ +/* Definitions for thread-local data handling. linuxthreads/x86-64 version. + Copyright (C) 2002, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _TLS_H +#define _TLS_H + +#ifndef __ASSEMBLER__ + +# include +# include +# include + +/* Type for the dtv. */ +typedef union dtv +{ + size_t counter; + struct + { + void *val; + bool is_static; + } pointer; +} dtv_t; + + +typedef struct +{ + void *tcb; /* Pointer to the TCB. Not necessary the + thread descriptor used by libpthread. */ + dtv_t *dtv; + void *self; /* Pointer to the thread descriptor. */ + int multiple_threads; +} tcbhead_t; + +#else /* __ASSEMBLER__ */ +# include +#endif + + +#ifdef HAVE_TLS_SUPPORT + +/* Signal that TLS support is available. */ +# define USE_TLS 1 + +# ifndef __ASSEMBLER__ +/* Get system call information. */ +# include + +/* Get the thread descriptor definition. */ +# include + +/* This is the size of the initial TCB. */ +# define TLS_INIT_TCB_SIZE sizeof (tcbhead_t) + +/* Alignment requirements for the initial TCB. */ +# define TLS_INIT_TCB_ALIGN __alignof__ (tcbhead_t) + +/* This is the size of the TCB. */ +# define TLS_TCB_SIZE sizeof (struct _pthread_descr_struct) + +/* Alignment requirements for the TCB. */ +# define TLS_TCB_ALIGN __alignof__ (struct _pthread_descr_struct) + +/* The TCB can have any size and the memory following the address the + thread pointer points to is unspecified. Allocate the TCB there. */ +# define TLS_TCB_AT_TP 1 + + +/* Install the dtv pointer. The pointer passed is to the element with + index -1 which contain the length. */ +# define INSTALL_DTV(descr, dtvp) \ + ((tcbhead_t *) (descr))->dtv = (dtvp) + 1 + +/* Install new dtv for current thread. */ +# define INSTALL_NEW_DTV(dtv) \ + ({ struct _pthread_descr_struct *__descr; \ + THREAD_SETMEM (__descr, p_header.data.dtvp, (dtv)); }) + +/* Return dtv of given thread descriptor. */ +# define GET_DTV(descr) \ + (((tcbhead_t *) (descr))->dtv) + +/* Code to initially initialize the thread pointer. This might need + special attention since 'errno' is not yet available and if the + operation can cause a failure 'errno' must not be touched. */ +# define TLS_INIT_TP(descr, secondcall) \ + ({ \ + void *_descr = (descr); \ + tcbhead_t *head = _descr; \ + long int _result; \ + \ + head->tcb = _descr; \ + /* For now the thread descriptor is at the same address. */ \ + head->self = _descr; \ + \ + __asm__ __volatile__ ("syscall" \ + : "=a" (_result) \ + : "0" ((unsigned long int) __NR_arch_prctl), \ + "D" ((unsigned long int) ARCH_SET_FS), \ + "S" (_descr) \ + : "memory", "cc", "r11", "cx"); \ + \ + _result ? "cannot set %fs base address for thread-local storage" : 0; \ + }) + +/* Indicate that dynamic linker shouldn't try to initialize TLS even + when no PT_TLS segments are found in the program and libraries + it is linked against. */ +# define TLS_INIT_TP_EXPENSIVE 1 + +/* Return the address of the dtv for the current thread. */ +# define THREAD_DTV() \ + ({ struct _pthread_descr_struct *__descr; \ + THREAD_GETMEM (__descr, p_header.data.dtvp); }) + +# endif /* HAVE_TLS_SUPPORT */ +#endif /* __ASSEMBLER__ */ + +#endif /* tls.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/xtensa/pt-machine.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/xtensa/pt-machine.h new file mode 100644 index 00000000..acd4d109 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/sysdeps/xtensa/pt-machine.h @@ -0,0 +1,48 @@ +/* Machine-dependent pthreads configuration and inline functions. + Xtensa version. + + Copyright (C) 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street - Fifth Floor, + Boston, MA 02110-1301, USA. */ + +#ifndef _PT_MACHINE_H +#define _PT_MACHINE_H 1 + +#include +#include + +#ifndef PT_EI +# define PT_EI __extern_always_inline +#endif + +/* Memory barrier. */ +#define MEMORY_BARRIER() __asm__ ("memw" : : : "memory") + +/* Spinlock implementation; required. */ +PT_EI long int +testandset (int *spinlock) +{ + int unused = 0; + return INTERNAL_SYSCALL (xtensa, , 4, SYS_XTENSA_ATOMIC_SET, + spinlock, 1, unused); +} + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#define CURRENT_STACK_FRAME __builtin_frame_address (0) + +#endif /* _PT_MACHINE_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/wrapsyscall.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/wrapsyscall.c new file mode 100644 index 00000000..6e18388c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old/wrapsyscall.c @@ -0,0 +1,229 @@ +/* Wrapper arpund system calls to provide cancelation points. + Copyright (C) 1996,1997,1998,1999,2000,2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1996. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#define __FORCE_GLIBC +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#ifndef __PIC__ +/* We need a hook to force this file to be linked in when static + libpthread is used. */ +const char __pthread_provide_wrappers = 0; +#endif + +/* Using private interface to libc (__libc_foo) to implement + * cancellable versions of some libc functions */ +#define CANCELABLE_SYSCALL(res_type, name, param_list, params) \ +res_type __libc_##name param_list; \ +res_type \ +__attribute__ ((weak)) \ +name param_list \ +{ \ + res_type result; \ + int oldtype; \ + pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype); \ + result = __libc_##name params; \ + pthread_setcanceltype (oldtype, NULL); \ + return result; \ +} + +#define CANCELABLE_SYSCALL_VA(res_type, name, param_list, params, last_arg) \ +res_type __libc_##name param_list; \ +res_type \ +__attribute__ ((weak)) \ +name param_list \ +{ \ + res_type result; \ + int oldtype; \ + va_list ap; \ + pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype); \ + va_start (ap, last_arg); \ + result = __libc_##name params; \ + va_end (ap); \ + pthread_setcanceltype (oldtype, NULL); \ + return result; \ +} + + +/* close(2). */ +CANCELABLE_SYSCALL (int, close, (int fd), (fd)) + + +/* fcntl(2). */ +CANCELABLE_SYSCALL_VA (int, fcntl, (int fd, int cmd, ...), + (fd, cmd, va_arg (ap, long int)), cmd) + + +/* fsync(2). */ +CANCELABLE_SYSCALL (int, fsync, (int fd), (fd)) + + +/* lseek(2). */ +CANCELABLE_SYSCALL (off_t, lseek, (int fd, off_t offset, int whence), + (fd, offset, whence)) + +#ifdef __UCLIBC_HAS_LFS__ +/* lseek64(2). */ +CANCELABLE_SYSCALL (off64_t, lseek64, (int fd, off64_t offset, int whence), + (fd, offset, whence)) +#endif + +#if defined(__NR_msync) && defined(__ARCH_USE_MMU__) + +/* msync(2). */ +CANCELABLE_SYSCALL (int, msync, (void *addr, size_t length, int flags), + (addr, length, flags)) +#endif + + +/* nanosleep(2). */ +libpthread_hidden_proto(nanosleep) +CANCELABLE_SYSCALL (int, nanosleep, (const struct timespec *requested_time, + struct timespec *remaining), + (requested_time, remaining)) +libpthread_hidden_def(nanosleep) + + +/* open(2). */ +CANCELABLE_SYSCALL_VA (int, open, (const char *pathname, int flags, ...), + (pathname, flags, va_arg (ap, mode_t)), flags) + + +#ifdef __UCLIBC_HAS_LFS__ +/* open64(3). */ +CANCELABLE_SYSCALL_VA (int, open64, (const char *pathname, int flags, ...), + (pathname, flags, va_arg (ap, mode_t)), flags) +#endif + +/* pause(2). */ +CANCELABLE_SYSCALL (int, pause, (void), ()) + + +/* Enable this if enabling these in syscalls.c */ +/* pread(3). */ +CANCELABLE_SYSCALL (ssize_t, pread, (int fd, void *buf, size_t count, + off_t offset), + (fd, buf, count, offset)) + + +#if defined __UCLIBC_HAS_LFS__ && defined __NR_pread64 +/* pread64(3). */ +CANCELABLE_SYSCALL (ssize_t, pread64, (int fd, void *buf, size_t count, + off64_t offset), + (fd, buf, count, offset)) +#endif + +/* pwrite(3). */ +CANCELABLE_SYSCALL (ssize_t, pwrite, (int fd, const void *buf, size_t n, + off_t offset), + (fd, buf, n, offset)) + + +#if defined __UCLIBC_HAS_LFS__ && defined __NR_pwrited64 +/* pwrite64(3). */ +CANCELABLE_SYSCALL (ssize_t, pwrite64, (int fd, const void *buf, size_t n, + off64_t offset), + (fd, buf, n, offset)) +#endif + +/* read(2). */ +CANCELABLE_SYSCALL (ssize_t, read, (int fd, void *buf, size_t count), + (fd, buf, count)) + + +/* system(3). */ +CANCELABLE_SYSCALL (int, system, (const char *line), (line)) + + +/* tcdrain(2). */ +CANCELABLE_SYSCALL (int, tcdrain, (int fd), (fd)) + + +/* wait(2). */ +CANCELABLE_SYSCALL (__pid_t, wait, (__WAIT_STATUS_DEFN stat_loc), (stat_loc)) + + +/* waitpid(2). */ +libpthread_hidden_proto(waitpid) +CANCELABLE_SYSCALL (__pid_t, waitpid, (__pid_t pid, int *stat_loc, + int options), + (pid, stat_loc, options)) +libpthread_hidden_def(waitpid) + + +/* write(2). */ +CANCELABLE_SYSCALL (ssize_t, write, (int fd, const void *buf, size_t n), + (fd, buf, n)) + +#if defined __UCLIBC_HAS_SOCKET__ +/* The following system calls are thread cancellation points specified + in XNS. */ + +/* accept(2). */ +CANCELABLE_SYSCALL (int, accept, (int fd, __SOCKADDR_ARG addr, + socklen_t *addr_len), + (fd, addr, addr_len)) + +/* connect(2). */ +CANCELABLE_SYSCALL (int, connect, (int fd, __CONST_SOCKADDR_ARG addr, + socklen_t len), + (fd, addr, len)) + +/* recv(2). */ +CANCELABLE_SYSCALL (ssize_t, recv, (int fd, __ptr_t buf, size_t n, int flags), + (fd, buf, n, flags)) + +/* recvfrom(2). */ +CANCELABLE_SYSCALL (ssize_t, recvfrom, (int fd, __ptr_t buf, size_t n, int flags, + __SOCKADDR_ARG addr, socklen_t *addr_len), + (fd, buf, n, flags, addr, addr_len)) + +/* recvmsg(2). */ +CANCELABLE_SYSCALL (ssize_t, recvmsg, (int fd, struct msghdr *message, int flags), + (fd, message, flags)) + +/* send(2). */ +CANCELABLE_SYSCALL (ssize_t, send, (int fd, const __ptr_t buf, size_t n, + int flags), + (fd, buf, n, flags)) + +/* sendmsg(2). */ +CANCELABLE_SYSCALL (ssize_t, sendmsg, (int fd, const struct msghdr *message, + int flags), + (fd, message, flags)) + +/* sendto(2). */ +CANCELABLE_SYSCALL (ssize_t, sendto, (int fd, const __ptr_t buf, size_t n, + int flags, __CONST_SOCKADDR_ARG addr, + socklen_t addr_len), + (fd, buf, n, flags, addr, addr_len)) +#endif /* __UCLIBC_HAS_SOCKET__ */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/Banner b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/Banner new file mode 100644 index 00000000..6f4f3f81 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/Banner @@ -0,0 +1 @@ +libthread_db work sponsored by Alpha Processor Inc diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/Makefile new file mode 100644 index 00000000..f9100219 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../ +top_builddir=../../ +include $(top_builddir)Rules.mak +all: libs +include Makefile.in +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/Makefile.in new file mode 100644 index 00000000..8741eab7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/Makefile.in @@ -0,0 +1,78 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +subdirs += libpthread/linuxthreads.old_db + +# Get the thread include dependencies and shared object name +CFLAGS-linuxthreads.old_db := -DNOT_IN_libc -DLIBPTHREAD_SO="\"libpthread.so.$(ABI_VERSION)\"" + +LDFLAGS-libthread_db.so := $(LDFLAGS_NOSTRIP) $(if $(call check_ld,--warn-unresolved-symbols),-Wl$(comma)--warn-unresolved-symbols) +ifeq ($(DOSTRIP),y) +LDFLAGS-libthread_db.so += -Wl,-s +endif + +LIBS-libthread_db.so := $(LIBS) + +libthread_db_FULL_NAME := libthread_db-$(VERSION).so + +libthread_db_DIR := $(top_srcdir)libpthread/linuxthreads.old_db +libthread_db_OUT := $(top_builddir)libpthread/linuxthreads.old_db + +libthread_db_SRC := $(wildcard $(libthread_db_DIR)/*.c) + +libthread_db_OBJ := $(patsubst $(libthread_db_DIR)/%.c,$(libthread_db_OUT)/%.o,$(libthread_db_SRC)) + +libthread_db-so-y := $(libthread_db_OBJ:.o=.os) +ifeq ($(DOPIC),y) +libthread_db-a-y := $(libthread_db-so-y) +else +libthread_db-a-y := $(libthread_db_OBJ) +endif + +lib-a-$(PTHREADS_DEBUG_SUPPORT) += $(top_builddir)lib/libthread_db.a +lib-so-$(PTHREADS_DEBUG_SUPPORT) += $(top_builddir)lib/libthread_db.so + +#ifeq ($(DOMULTI),n) +ifeq ($(DOPIC),y) +$(top_builddir)lib/libthread_db.so: $(top_builddir)lib/libthread_db.a $(libc.depend) +else +$(top_builddir)lib/libthread_db.so: $(libthread_db_OUT)/libthread_db_so.a $(libc.depend) +endif + $(call link.so,$(libthread_db_FULL_NAME),1) +#else +#$(top_builddir)lib/libthread_db.so: $(libthread_db_OUT)/libthread_db.oS | $(libc.depend) +# $(call linkm.so,$(libthread_db_FULL_NAME),1) +#endif + +$(libthread_db_OUT)/libthread_db_so.a: $(libthread_db-so-y) + $(Q)$(RM) $@ + $(do_ar) + +$(libthread_db_OUT)/libthread_db.oS: $(libthread_db_SRC) + $(Q)$(RM) $@ + $(compile-m) + +$(top_builddir)lib/libthread_db.a: $(libthread_db-a-y) + $(Q)$(INSTALL) -d $(dir $@) + $(Q)$(RM) $@ + $(do_ar) + +$(top_builddir)include/thread_db.h: + $(do_ln) $(call rel_srcdir)$(PTDIR)_db/$(@F) $@ + +linuxthreads_db_headers := $(top_builddir)include/thread_db.h +$(linuxthreads_db_headers): $(wildcard $(addprefix $(top_builddir)include/config/linuxthreads/,old.h new.h)) +headers-$(PTHREADS_DEBUG_SUPPORT) += $(linuxthreads_db_headers) + +objclean-y += CLEAN_libpthread/linuxthreads.old_db +headers_clean-y += HEADERCLEAN_libpthread/linuxthreads.old_db + +HEADERCLEAN_libpthread/linuxthreads.old_db: + $(do_rm) $(linuxthreads_db_headers) + +CLEAN_libpthread/linuxthreads.old_db: + $(do_rm) $(addprefix $(libthread_db_OUT)/*., o os oS a) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/Versions b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/Versions new file mode 100644 index 00000000..063493c6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/Versions @@ -0,0 +1,24 @@ +libthread_db { + GLIBC_2.1.3 { + # t* + td_init; td_log; td_ta_clear_event; td_ta_delete; td_ta_enable_stats; + td_ta_event_addr; td_ta_event_getmsg; td_ta_get_nthreads; td_ta_get_ph; + td_ta_get_stats; td_ta_map_id2thr; td_ta_map_lwp2thr; td_ta_new; + td_ta_reset_stats; td_ta_set_event; td_ta_setconcurrency; + td_ta_thr_iter; td_ta_tsd_iter; td_thr_clear_event; td_thr_dbresume; + td_thr_dbsuspend; td_thr_event_enable; td_thr_event_getmsg; + td_thr_get_info; td_thr_getfpregs; td_thr_getgregs; td_thr_getxregs; + td_thr_getxregsize; td_thr_set_event; td_thr_setfpregs; td_thr_setgregs; + td_thr_setprio; td_thr_setsigpending; td_thr_setxregs; td_thr_sigsetmask; + td_thr_tsd; td_thr_validate; + } + GLIBC_2.2.3 { + td_symbol_list; + } + GLIBC_2.3 { + td_thr_tls_get_addr; + } + GLIBC_2.3.3 { + td_thr_tlsbase; + } +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/proc_service.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/proc_service.h new file mode 100644 index 00000000..74136c03 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/proc_service.h @@ -0,0 +1,70 @@ +/* Copyright (C) 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* The definitions in this file must correspond to those in the debugger. */ +#include + +typedef enum +{ + PS_OK, /* generic "call succeeded" */ + PS_ERR, /* generic. */ + PS_BADPID, /* bad process handle */ + PS_BADLID, /* bad lwp identifier */ + PS_BADADDR, /* bad address */ + PS_NOSYM, /* p_lookup() could not find given symbol */ + PS_NOFREGS + /* + * FPU register set not available for given + * lwp + */ +} ps_err_e; + + +struct ps_prochandle; /* user defined. */ + + +extern ps_err_e ps_pdread(struct ps_prochandle *, + psaddr_t, void *, size_t); +extern ps_err_e ps_pdwrite(struct ps_prochandle *, + psaddr_t, const void *, size_t); +extern ps_err_e ps_ptread(struct ps_prochandle *, + psaddr_t, void *, size_t); +extern ps_err_e ps_ptwrite(struct ps_prochandle *, + psaddr_t, const void *, size_t); + +extern ps_err_e ps_pglobal_lookup(struct ps_prochandle *, + const char *object_name, const char *sym_name, psaddr_t *sym_addr); + + +extern ps_err_e ps_lgetregs(struct ps_prochandle *, + lwpid_t, prgregset_t); +extern ps_err_e ps_lsetregs(struct ps_prochandle *, + lwpid_t, const prgregset_t); +extern ps_err_e ps_lgetfpregs(struct ps_prochandle *, + lwpid_t, prfpregset_t *); +extern ps_err_e ps_lsetfpregs(struct ps_prochandle *, + lwpid_t, const prfpregset_t *); + +extern pid_t ps_getpid (struct ps_prochandle *); + + +extern ps_err_e ps_pstop (const struct ps_prochandle *); +extern ps_err_e ps_pcontinue (const struct ps_prochandle *); + +extern ps_err_e ps_lstop (const struct ps_prochandle *, lwpid_t); +extern ps_err_e ps_lcontinue (const struct ps_prochandle *, lwpid_t); diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_init.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_init.c new file mode 100644 index 00000000..6f0e1584 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_init.c @@ -0,0 +1,33 @@ +/* Initialization function of thread debugger support library. + Copyright (C) 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + +#ifndef NDEBUG +int __td_debug; +#endif + +td_err_e +td_init (void) +{ + /* XXX We have to figure out what has to be done. */ + LOG ("td_init"); + return TD_OK; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_log.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_log.c new file mode 100644 index 00000000..025273a6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_log.c @@ -0,0 +1,32 @@ +/* Noop, left for historical reasons. + Copyright (C) 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_log (void) +{ + /* This interface is deprecated in the Sun interface. We provide it + for compatibility but don't do anything ourself. We might in + future do some logging if this seems reasonable. */ + LOG ("td_log"); + return TD_OK; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_symbol_list.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_symbol_list.c new file mode 100644 index 00000000..599c0459 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_symbol_list.c @@ -0,0 +1,61 @@ +/* Return list of symbols the library can request. + Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2001. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include "thread_dbP.h" + +#ifdef HAVE_ASM_GLOBAL_DOT_NAME +# define DOT "." /* PPC64 requires . prefix on code symbols. */ +#else +# define DOT /* No prefix. */ +#endif + +static const char *symbol_list_arr[] = +{ + [PTHREAD_THREADS_EVENTS] = "__pthread_threads_events", + [PTHREAD_LAST_EVENT] = "__pthread_last_event", + [PTHREAD_HANDLES_NUM] = "__pthread_handles_num", + [PTHREAD_HANDLES] = "__pthread_handles", + [PTHREAD_KEYS] = "pthread_keys", + [LINUXTHREADS_PTHREAD_THREADS_MAX] = "__linuxthreads_pthread_threads_max", + [LINUXTHREADS_PTHREAD_KEYS_MAX] = "__linuxthreads_pthread_keys_max", + [LINUXTHREADS_PTHREAD_SIZEOF_DESCR] = "__linuxthreads_pthread_sizeof_descr", + [LINUXTHREADS_CREATE_EVENT] = DOT "__linuxthreads_create_event", + [LINUXTHREADS_DEATH_EVENT] = DOT "__linuxthreads_death_event", + [LINUXTHREADS_REAP_EVENT] = DOT "__linuxthreads_reap_event", + [LINUXTHREADS_INITIAL_REPORT_EVENTS] = "__linuxthreads_initial_report_events", + [LINUXTHREADS_VERSION] = "__linuxthreads_version", + [NUM_MESSAGES] = NULL +}; + + +const char ** +td_symbol_list (void) +{ + return symbol_list_arr; +} + + +int +td_lookup (struct ps_prochandle *ps, int idx, psaddr_t *sym_addr) +{ + assert (idx >= 0 && idx < NUM_MESSAGES); + return ps_pglobal_lookup (ps, LIBPTHREAD_SO, symbol_list_arr[idx], sym_addr); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_ta_clear_event.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_ta_clear_event.c new file mode 100644 index 00000000..cbb7ddc9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_ta_clear_event.c @@ -0,0 +1,53 @@ +/* Globally disable events. + Copyright (C) 1999, 2001, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_ta_clear_event (ta, event) + const td_thragent_t *ta; + td_thr_events_t *event; +{ + td_thr_events_t old_event; + int i; + + LOG ("td_ta_clear_event"); + + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + + /* Write the new value into the thread data structure. */ + if (ps_pdread (ta->ph, ta->pthread_threads_eventsp, + &old_event, sizeof (td_thr_events_t)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + /* Remove the set bits in. */ + for (i = 0; i < TD_EVENTSIZE; ++i) + old_event.event_bits[i] &= ~event->event_bits[i]; + + /* Write the new value into the thread data structure. */ + if (ps_pdwrite (ta->ph, ta->pthread_threads_eventsp, + &old_event, sizeof (td_thr_events_t)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + return TD_OK; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_ta_delete.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_ta_delete.c new file mode 100644 index 00000000..0e6ec17d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_ta_delete.c @@ -0,0 +1,58 @@ +/* Detach to target process. + Copyright (C) 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#include "thread_dbP.h" + + +td_err_e +td_ta_delete (td_thragent_t *ta) +{ + LOG ("td_ta_delete"); + + /* Safety check. */ + if (ta == NULL || __td_agent_list == NULL) + return TD_BADTA; + + /* Remove the handle from the list. */ + if (ta == __td_agent_list->ta) + /* It's the first element of the list. */ + __td_agent_list = __td_agent_list->next; + else + { + /* We have to search for it. */ + struct agent_list *runp = __td_agent_list; + + while (runp->next != NULL && runp->next->ta != ta) + runp = runp->next; + + if (runp->next == NULL) + /* It's not a valid decriptor since it is not in the list. */ + return TD_BADTA; + + runp->next = runp->next->next; + } + + /* The handle was allocated in `td_ta_new'. */ + free (ta); + + return TD_OK; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_ta_enable_stats.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_ta_enable_stats.c new file mode 100644 index 00000000..1d4c34a8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_ta_enable_stats.c @@ -0,0 +1,35 @@ +/* Enable collection of statistics for process. + Copyright (C) 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_ta_enable_stats (const td_thragent_t *ta, int enable) +{ + /* XXX We have to figure out what has to be done. */ + LOG ("td_ta_enable_stats"); + + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + + return TD_OK; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_ta_event_addr.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_ta_event_addr.c new file mode 100644 index 00000000..8bce35ae --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_ta_event_addr.c @@ -0,0 +1,73 @@ +/* Get event address. + Copyright (C) 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_ta_event_addr (const td_thragent_t *ta, td_event_e event, td_notify_t *addr) +{ + td_err_e res = TD_NOEVENT; + int idx = -1; + + LOG ("td_ta_event_addr"); + + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + + switch (event) + { + case TD_CREATE: + idx = LINUXTHREADS_CREATE_EVENT; + break; + + case TD_DEATH: + idx = LINUXTHREADS_DEATH_EVENT; + break; + + case TD_REAP: + idx = LINUXTHREADS_REAP_EVENT; + break; + + default: + /* Event cannot be handled. */ + break; + } + + /* Now get the address. */ + if (idx != -1) + { + psaddr_t taddr; + + if (td_lookup (ta->ph, idx, &taddr) == PS_OK) + { + /* Success, we got the address. */ + addr->type = NOTIFY_BPT; + addr->u.bptaddr = taddr; + + res = TD_OK; + } + else + res = TD_ERR; + } + + return res; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_ta_event_getmsg.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_ta_event_getmsg.c new file mode 100644 index 00000000..ba535da7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_ta_event_getmsg.c @@ -0,0 +1,128 @@ +/* Retrieve event. + Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +#include "thread_dbP.h" + + +td_err_e +td_ta_event_getmsg (const td_thragent_t *ta, td_event_msg_t *msg) +{ + /* XXX I cannot think of another way but using a static variable. */ + static td_thrhandle_t th; + td_eventbuf_t event; + psaddr_t addr; + + LOG ("td_ta_event_getmsg"); + + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + + /* Get the pointer to the thread descriptor with the last event. */ + if (ps_pdread (ta->ph, ta->pthread_last_event, + &addr, sizeof (void *)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + /* If the pointer is NULL no event occurred. */ + if (addr == 0) + return TD_NOMSG; + + /* Read the even structure from the target. */ + if (ps_pdread (ta->ph, + ((char *) addr + + offsetof (struct _pthread_descr_struct, p_eventbuf)), + &event, sizeof (td_eventbuf_t)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + /* Check whether an event occurred. */ + if (event.eventnum == TD_EVENT_NONE) + { + /* Oh well, this means the last event was already read. So + we have to look for any other event. */ + struct pthread_handle_struct handles[ta->pthread_threads_max]; + int num; + int i; + + /* Read the number of currently active threads. */ + if (ps_pdread (ta->ph, ta->pthread_handles_num, &num, sizeof (int)) + != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + /* Now read the handles. */ + if (ps_pdread (ta->ph, ta->handles, handles, + ta->pthread_threads_max * sizeof (handles[0])) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + for (i = 0; i < ta->pthread_threads_max && num > 0; ++i) + { + if (handles[i].h_descr == NULL) + /* No entry here. */ + continue; + + /* First count this active thread. */ + --num; + + if (handles[i].h_descr == addr) + /* We already handled this. */ + continue; + + /* Read the event data for this thread. */ + if (ps_pdread (ta->ph, + ((char *) handles[i].h_descr + + offsetof (struct _pthread_descr_struct, + p_eventbuf)), + &event, sizeof (td_eventbuf_t)) != PS_OK) + return TD_ERR; + + if (event.eventnum != TD_EVENT_NONE) + { + /* We found a thread with an unreported event. */ + addr = handles[i].h_descr; + break; + } + } + + /* If we haven't found any other event signal this to the user. */ + if (event.eventnum == TD_EVENT_NONE) + return TD_NOMSG; + } + + /* Generate the thread descriptor. */ + th.th_ta_p = (td_thragent_t *) ta; + th.th_unique = addr; + + /* Fill the user's data structure. */ + msg->event = event.eventnum; + msg->th_p = &th; + msg->msg.data = (uintptr_t) event.eventdata; + + /* And clear the event message in the target. */ + memset (&event, '\0', sizeof (td_eventbuf_t)); + if (ps_pdwrite (ta->ph, + ((char *) addr + + offsetof (struct _pthread_descr_struct, p_eventbuf)), + &event, sizeof (td_eventbuf_t)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + return TD_OK; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_ta_get_nthreads.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_ta_get_nthreads.c new file mode 100644 index 00000000..839b56be --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_ta_get_nthreads.c @@ -0,0 +1,42 @@ +/* Get the number of threads in the process. + Copyright (C) 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + +td_err_e +td_ta_get_nthreads (const td_thragent_t *ta, int *np) +{ + psaddr_t addr; + + LOG ("td_ta_get_nthreads"); + + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + + /* Access the variable `__pthread_handles_num'. */ + if (td_lookup (ta->ph, PTHREAD_HANDLES_NUM, &addr) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + if (ps_pdread (ta->ph, addr, np, sizeof (int)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + return TD_OK; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_ta_get_ph.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_ta_get_ph.c new file mode 100644 index 00000000..23d32850 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_ta_get_ph.c @@ -0,0 +1,36 @@ +/* Get external process handle. + Copyright (C) 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_ta_get_ph (const td_thragent_t *ta, struct ps_prochandle **ph) +{ + LOG ("td_ta_get_ph"); + + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + + *ph = ta->ph; + + return TD_OK; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_ta_get_stats.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_ta_get_stats.c new file mode 100644 index 00000000..6bf2f535 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_ta_get_stats.c @@ -0,0 +1,35 @@ +/* Retrieve statistics for process. + Copyright (C) 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_ta_get_stats (const td_thragent_t *ta, td_ta_stats_t *statsp) +{ + /* XXX We have to figure out what has to be done. */ + LOG ("td_ta_get_stats"); + + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + + return TD_OK; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_ta_map_id2thr.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_ta_map_id2thr.c new file mode 100644 index 00000000..c57f25a5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_ta_map_id2thr.c @@ -0,0 +1,78 @@ +/* Map thread ID to thread handle. + Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_ta_map_id2thr (const td_thragent_t *ta, pthread_t pt, td_thrhandle_t *th) +{ + struct pthread_handle_struct phc; + struct _pthread_descr_struct pds; + int pthread_threads_max; + + LOG ("td_ta_map_id2thr"); + + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + + /* Make the following expression a bit smaller. */ + pthread_threads_max = ta->pthread_threads_max; + + /* We can compute the entry in the handle array we want. */ + if (ps_pdread (ta->ph, ta->handles + pt % pthread_threads_max, &phc, + sizeof (struct pthread_handle_struct)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + /* Test whether this entry is in use. */ + if (phc.h_descr == NULL) + { + if (pt % pthread_threads_max == 0) + { + /* The initial thread always exists but the thread library + might not yet be initialized. */ + th->th_ta_p = (td_thragent_t *) ta; + th->th_unique = NULL; + + return TD_OK; + } + + return TD_BADTH; + } + + /* Next test: get the descriptor to see whether this is not an old + thread handle. */ + if (ps_pdread (ta->ph, phc.h_descr, &pds, + sizeof (struct _pthread_descr_struct)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + if (pds.p_tid != pt) + return TD_BADTH; + + if (pds.p_terminated != 0) + return TD_NOTHR; + + /* Create the `td_thrhandle_t' object. */ + th->th_ta_p = (td_thragent_t *) ta; + th->th_unique = phc.h_descr; + + return TD_OK; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_ta_map_lwp2thr.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_ta_map_lwp2thr.c new file mode 100644 index 00000000..2be1e3de --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_ta_map_lwp2thr.c @@ -0,0 +1,90 @@ +/* Which thread is running on an lwp? + Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_ta_map_lwp2thr (const td_thragent_t *ta, lwpid_t lwpid, td_thrhandle_t *th) +{ + int pthread_threads_max = ta->pthread_threads_max; + size_t sizeof_descr = ta->sizeof_descr; + struct pthread_handle_struct phc[pthread_threads_max]; + size_t cnt; +#ifdef ALL_THREADS_STOPPED + int num; +#else +# define num 1 +#endif + + LOG ("td_ta_map_lwp2thr"); + + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + + /* Read all the descriptors. */ + if (ps_pdread (ta->ph, ta->handles, phc, + sizeof (struct pthread_handle_struct) * pthread_threads_max) + != PS_OK) + return TD_ERR; /* XXX Other error value? */ + +#ifdef ALL_THREADS_STOPPED + /* Read the number of currently active threads. */ + if (ps_pdread (ta->ph, ta->pthread_handles_num, &num, sizeof (int)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ +#endif + + /* Get the entries one after the other and find out whether the ID + matches. */ + for (cnt = 0; cnt < pthread_threads_max && num > 0; ++cnt) + if (phc[cnt].h_descr != NULL) + { + struct _pthread_descr_struct pds; + +#ifdef ALL_THREADS_STOPPED + /* First count this active thread. */ + --num; +#endif + + if (ps_pdread (ta->ph, phc[cnt].h_descr, &pds, sizeof_descr) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + if ((pds.p_pid ?: ps_getpid (ta->ph)) == lwpid) + { + /* Found it. Now fill in the `td_thrhandle_t' object. */ + th->th_ta_p = (td_thragent_t *) ta; + th->th_unique = phc[cnt].h_descr; + + return TD_OK; + } + } + else if (cnt == 0) + { + /* The initial thread always exists. But it might not yet be + initialized. Construct a value. */ + th->th_ta_p = (td_thragent_t *) ta; + th->th_unique = NULL; + + return TD_OK; + } + + return TD_NOLWP; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_ta_new.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_ta_new.c new file mode 100644 index 00000000..2b0b68bf --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_ta_new.c @@ -0,0 +1,149 @@ +/* Attach to target process. + Copyright (C) 1999, 2001, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +#include "thread_dbP.h" + + +/* Datatype for the list of known thread agents. Normally there will + be exactly one so we don't spend much though on making it fast. */ +struct agent_list *__td_agent_list; + + +td_err_e +td_ta_new (struct ps_prochandle *ps, td_thragent_t **ta) +{ + psaddr_t addr; + psaddr_t versaddr; + char versbuf[sizeof (VERSION)]; + struct agent_list *elemp; + + LOG ("td_ta_new"); + + /* Get the global event mask. This is one of the variables which + are new in the thread library to enable debugging. If it is + not available we cannot debug. */ + if (td_lookup (ps, PTHREAD_THREADS_EVENTS, &addr) != PS_OK) + return TD_NOLIBTHREAD; + + /* Check whether the versions match. */ + if (td_lookup (ps, LINUXTHREADS_VERSION, &versaddr) != PS_OK) + return TD_VERSION; + if (ps_pdread (ps, versaddr, versbuf, sizeof (versbuf)) != PS_OK) + return TD_ERR; + + versbuf[sizeof (versbuf) - 1] = '\0'; + if (strcmp (versbuf, VERSION) != 0) + /* Not the right version. */ + return TD_VERSION; + + /* Fill in the appropriate information. */ + *ta = (td_thragent_t *) malloc (sizeof (td_thragent_t)); + if (*ta == NULL) + return TD_MALLOC; + + /* Store the proc handle which we will pass to the callback functions + back into the debugger. */ + (*ta)->ph = ps; + + /* Remember the address. */ + (*ta)->pthread_threads_eventsp = (td_thr_events_t *) addr; + + /* Get the pointer to the variable pointing to the thread descriptor + with the last event. */ + if (td_lookup (ps, PTHREAD_LAST_EVENT, &(*ta)->pthread_last_event) != PS_OK) + { + free_return: + free (*ta); + return TD_ERR; + } + + /* Get the pointer to the variable containing the number of active + threads. */ + if (td_lookup (ps, PTHREAD_HANDLES_NUM, &(*ta)->pthread_handles_num) + != PS_OK) + goto free_return; + + /* See whether the library contains the necessary symbols. */ + if (td_lookup (ps, PTHREAD_HANDLES, &addr) != PS_OK) + goto free_return; + + (*ta)->handles = (struct pthread_handle_struct *) addr; + + + if (td_lookup (ps, PTHREAD_KEYS, &addr) != PS_OK) + goto free_return; + + /* Cast to the right type. */ + (*ta)->keys = (struct pthread_key_struct *) addr; + + /* Find out about the maximum number of threads. Old implementations + don't provide this information. In this case we assume that the + debug library is compiled with the same values. */ + if (td_lookup (ps, LINUXTHREADS_PTHREAD_THREADS_MAX, &addr) != PS_OK) + (*ta)->pthread_threads_max = PTHREAD_THREADS_MAX; + else + { + if (ps_pdread (ps, addr, &(*ta)->pthread_threads_max, sizeof (int)) + != PS_OK) + goto free_return; + } + + /* Similar for the maximum number of thread local data keys. */ + if (td_lookup (ps, LINUXTHREADS_PTHREAD_KEYS_MAX, &addr) != PS_OK) + (*ta)->pthread_keys_max = PTHREAD_KEYS_MAX; + else + { + if (ps_pdread (ps, addr, &(*ta)->pthread_keys_max, sizeof (int)) + != PS_OK) + goto free_return; + } + + /* And for the size of the second level arrays for the keys. */ + if (td_lookup (ps, LINUXTHREADS_PTHREAD_SIZEOF_DESCR, &addr) != PS_OK) + (*ta)->sizeof_descr = sizeof (struct _pthread_descr_struct); + else + { + if (ps_pdread (ps, addr, &(*ta)->sizeof_descr, sizeof (int)) != PS_OK) + goto free_return; + /* Don't let bogons in the inferior make us mess ourselves. */ + if ((*ta)->sizeof_descr > sizeof (struct _pthread_descr_struct)) + (*ta)->sizeof_descr = sizeof (struct _pthread_descr_struct); + } + + /* Now add the new agent descriptor to the list. */ + elemp = (struct agent_list *) malloc (sizeof (struct agent_list)); + if (elemp == NULL) + { + /* Argh, now that everything else worked... */ + free (*ta); + return TD_MALLOC; + } + + /* We don't care for thread-safety here. */ + elemp->ta = *ta; + elemp->next = __td_agent_list; + __td_agent_list = elemp; + + return TD_OK; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_ta_reset_stats.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_ta_reset_stats.c new file mode 100644 index 00000000..b3ddbd07 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_ta_reset_stats.c @@ -0,0 +1,35 @@ +/* Reset statistics. + Copyright (C) 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_ta_reset_stats (const td_thragent_t *ta) +{ + /* XXX We have to figure out what has to be done. */ + LOG ("td_ta_reset_stats"); + + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + + return TD_OK; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_ta_set_event.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_ta_set_event.c new file mode 100644 index 00000000..6edb38e5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_ta_set_event.c @@ -0,0 +1,53 @@ +/* Globally enable events. + Copyright (C) 1999, 2001, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_ta_set_event (ta, event) + const td_thragent_t *ta; + td_thr_events_t *event; +{ + td_thr_events_t old_event; + int i; + + LOG ("td_ta_set_event"); + + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + + /* Write the new value into the thread data structure. */ + if (ps_pdread (ta->ph, ta->pthread_threads_eventsp, + &old_event, sizeof (td_thr_events_t)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + /* Or the new bits in. */ + for (i = 0; i < TD_EVENTSIZE; ++i) + old_event.event_bits[i] |= event->event_bits[i]; + + /* Write the new value into the thread data structure. */ + if (ps_pdwrite (ta->ph, ta->pthread_threads_eventsp, + &old_event, sizeof (td_thr_events_t)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + return TD_OK; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_ta_setconcurrency.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_ta_setconcurrency.c new file mode 100644 index 00000000..408e7630 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_ta_setconcurrency.c @@ -0,0 +1,35 @@ +/* Set suggested concurrency level for process. + Copyright (C) 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_ta_setconcurrency (const td_thragent_t *ta, int level) +{ + /* This is something LinuxThreads does not support. */ + LOG ("td_ta_setconcurrency"); + + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + + return TD_NOCAPAB; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_ta_thr_iter.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_ta_thr_iter.c new file mode 100644 index 00000000..771a12de --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_ta_thr_iter.c @@ -0,0 +1,173 @@ +/* Iterate over a process's threads. + Copyright (C) 1999,2000,2001,2002,2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" +#include + +static int +handle_descr (const td_thragent_t *ta, td_thr_iter_f *callback, + void *cbdata_p, td_thr_state_e state, int ti_pri, + size_t cnt, pthread_descr descr) +{ + struct _pthread_descr_struct pds; + size_t sizeof_descr = ta->sizeof_descr; + td_thrhandle_t th; + + if (descr == NULL) + { + /* No descriptor (yet). */ + if (cnt == 0) + { + /* This is the main thread. Create a fake descriptor. */ + memset (&pds, '\0', sizeof (pds)); + + /* Empty thread descriptor the thread library would create. */ + pds.p_self = &pds; + pds.p_nextlive = pds.p_prevlive = &pds; + pds.p_tid = PTHREAD_THREADS_MAX; + /* The init code also sets up p_lock, p_errnop, p_herrnop, and + p_userstack but this should not be necessary here. */ + + th.th_ta_p = (td_thragent_t *) ta; + th.th_unique = NULL; + if (callback (&th, cbdata_p) != 0) + return TD_DBERR; + + /* All done successfully. */ + return TD_OK; + } + else if (cnt == 1) + /* The manager is not yet started. No big deal. */ + return TD_OK; + else + /* For every other thread this should not happen. */ + return TD_ERR; + } + + if (ps_pdread (ta->ph, descr, &pds, sizeof_descr) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + /* The manager thread must be handled special. The descriptor + exists but the thread only gets created when the first + `pthread_create' call is issued. A clear indication that this + happened is when the p_pid field is non-zero. */ + if (cnt == 1 && pds.p_pid == 0) + return TD_OK; + + /* Now test whether this thread matches the specified + conditions. */ + + /* Only if the priority level is as high or higher. */ + if (pds.p_priority < ti_pri) + return TD_OK; + + /* Test the state. + XXX This is incomplete. */ + if (state != TD_THR_ANY_STATE) + return TD_OK; + + /* XXX For now we ignore threads which are not running anymore. + The reason is that gdb tries to get the registers and fails. + In future we should have a special mode of the thread library + in which we keep the process around until the actual join + operation happened. */ + if (pds.p_exited != 0) + return TD_OK; + + /* Yep, it matches. Call the callback function. */ + th.th_ta_p = (td_thragent_t *) ta; + th.th_unique = descr; + if (callback (&th, cbdata_p) != 0) + return TD_DBERR; + + /* All done successfully. */ + return TD_OK; +} + + +td_err_e +td_ta_thr_iter (const td_thragent_t *ta, td_thr_iter_f *callback, + void *cbdata_p, td_thr_state_e state, int ti_pri, + sigset_t *ti_sigmask_p, unsigned int ti_user_flags) +{ + int pthread_threads_max; + struct pthread_handle_struct *phc; + td_err_e result = TD_OK; + int cnt; +#ifdef ALL_THREADS_STOPPED + int num; +#else +# define num 1 +#endif + + LOG ("td_ta_thr_iter"); + + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + + pthread_threads_max = ta->pthread_threads_max; + phc = (struct pthread_handle_struct *) alloca (sizeof (phc[0]) + * pthread_threads_max); + + /* First read only the main thread and manager thread information. */ + if (ps_pdread (ta->ph, ta->handles, phc, + sizeof (struct pthread_handle_struct) * 2) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + /* Now handle these descriptors. */ + result = handle_descr (ta, callback, cbdata_p, state, ti_pri, 0, + phc[0].h_descr); + if (result != TD_OK) + return result; + result = handle_descr (ta, callback, cbdata_p, state, ti_pri, 1, + phc[1].h_descr); + if (result != TD_OK) + return result; + + /* Read all the descriptors. */ + if (ps_pdread (ta->ph, ta->handles + 2, &phc[2], + (sizeof (struct pthread_handle_struct) + * (pthread_threads_max - 2))) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + +#ifdef ALL_THREADS_STOPPED + /* Read the number of currently active threads. */ + if (ps_pdread (ta->ph, ta->pthread_handles_num, &num, sizeof (int)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ +#endif + + /* Now get all descriptors, one after the other. */ + for (cnt = 2; cnt < pthread_threads_max && num > 0; ++cnt) + if (phc[cnt].h_descr != NULL) + { +#ifdef ALL_THREADS_STOPPED + /* First count this active thread. */ + --num; +#endif + + result = handle_descr (ta, callback, cbdata_p, state, ti_pri, cnt, + phc[cnt].h_descr); + if (result != TD_OK) + break; + } + + return result; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_ta_tsd_iter.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_ta_tsd_iter.c new file mode 100644 index 00000000..7ad98dd9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_ta_tsd_iter.c @@ -0,0 +1,55 @@ +/* Iterate over a process's thread-specific data. + Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" +#include + +td_err_e +td_ta_tsd_iter (const td_thragent_t *ta, td_key_iter_f *callback, + void *cbdata_p) +{ + struct pthread_key_struct *keys; + int pthread_keys_max; + int cnt; + + LOG ("td_ta_tsd_iter"); + + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + + pthread_keys_max = ta->pthread_keys_max; + keys = (struct pthread_key_struct *) alloca (sizeof (keys[0]) + * pthread_keys_max); + + /* Read all the information about the keys. */ + if (ps_pdread (ta->ph, ta->keys, keys, + sizeof (keys[0]) * pthread_keys_max) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + /* Now get all descriptors, one after the other. */ + for (cnt = 0; cnt < pthread_keys_max; ++cnt) + if (keys[cnt].in_use + /* Return with an error if the callback returns a nonzero value. */ + && callback (cnt, keys[cnt].destr, cbdata_p) != 0) + return TD_DBERR; + + return TD_OK; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_thr_clear_event.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_thr_clear_event.c new file mode 100644 index 00000000..147d1803 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_thr_clear_event.c @@ -0,0 +1,62 @@ +/* Disable specific event for thread. + Copyright (C) 1999, 2001, 2002, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#include "thread_dbP.h" + + +td_err_e +td_thr_clear_event (th, event) + const td_thrhandle_t *th; + td_thr_events_t *event; +{ + td_thr_events_t old_event; + int i; + + LOG ("td_thr_clear_event"); + + /* If the thread descriptor has not yet been constructed do not do + anything. */ + if (th->th_unique == NULL) + return TD_OK; + + /* Write the new value into the thread data structure. */ + if (ps_pdread (th->th_ta_p->ph, + ((char *) th->th_unique + + offsetof (struct _pthread_descr_struct, + p_eventbuf.eventmask)), + &old_event, sizeof (td_thr_events_t)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + /* Remove the set bits in. */ + for (i = 0; i < TD_EVENTSIZE; ++i) + old_event.event_bits[i] &= ~event->event_bits[i]; + + /* Write the new value into the thread data structure. */ + if (ps_pdwrite (th->th_ta_p->ph, + ((char *) th->th_unique + + offsetof (struct _pthread_descr_struct, + p_eventbuf.eventmask)), + &old_event, sizeof (td_thr_events_t)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + return TD_OK; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_thr_dbresume.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_thr_dbresume.c new file mode 100644 index 00000000..7b7f6eef --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_thr_dbresume.c @@ -0,0 +1,30 @@ +/* Resume execution of given thread. + Copyright (C) 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_thr_dbresume (const td_thrhandle_t *th) +{ + /* XXX We have to figure out what has to be done. */ + LOG ("td_thr_dbresume"); + return TD_NOCAPAB; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_thr_dbsuspend.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_thr_dbsuspend.c new file mode 100644 index 00000000..ef668023 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_thr_dbsuspend.c @@ -0,0 +1,30 @@ +/* Suspend execution of given thread. + Copyright (C) 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_thr_dbsuspend (const td_thrhandle_t *th) +{ + /* XXX We have to figure out what has to be done. */ + LOG ("td_thr_dbsuspend"); + return TD_NOCAPAB; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_thr_event_enable.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_thr_event_enable.c new file mode 100644 index 00000000..407f3fc4 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_thr_event_enable.c @@ -0,0 +1,57 @@ +/* Enable event process-wide. + Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#include "thread_dbP.h" + + +td_err_e +td_thr_event_enable (th, onoff) + const td_thrhandle_t *th; + int onoff; +{ + LOG ("td_thr_event_enable"); + + /* Write the new value into the thread data structure. */ + if (th->th_unique == NULL) + { + psaddr_t addr; + + if (td_lookup (th->th_ta_p->ph, LINUXTHREADS_INITIAL_REPORT_EVENTS, + &addr) != PS_OK) + /* Cannot read the symbol. This should not happen. */ + return TD_ERR; + + if (ps_pdwrite (th->th_ta_p->ph, addr, &onoff, sizeof (int)) != PS_OK) + return TD_ERR; + + return TD_OK; + } + + if (ps_pdwrite (th->th_ta_p->ph, + ((char *) th->th_unique + + offsetof (struct _pthread_descr_struct, + p_report_events)), + &onoff, sizeof (int)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + return TD_OK; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_thr_event_getmsg.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_thr_event_getmsg.c new file mode 100644 index 00000000..bf4ddd4a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_thr_event_getmsg.c @@ -0,0 +1,65 @@ +/* Retrieve event. + Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +#include "thread_dbP.h" + + +td_err_e +td_thr_event_getmsg (const td_thrhandle_t *th, td_event_msg_t *msg) +{ + td_eventbuf_t event; + + LOG ("td_thr_event_getmsg"); + + /* If the thread descriptor has not yet been created there cannot be + any event. */ + if (th->th_unique == NULL) + return TD_NOMSG; + + /* Read the even structure from the target. */ + if (ps_pdread (th->th_ta_p->ph, + ((char *) th->th_unique + + offsetof (struct _pthread_descr_struct, p_eventbuf)), + &event, sizeof (td_eventbuf_t)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + /* Check whether an event occurred. */ + if (event.eventnum == TD_EVENT_NONE) + /* Nothing. */ + return TD_NOMSG; + + /* Fill the user's data structure. */ + msg->event = event.eventnum; + msg->th_p = th; + msg->msg.data = (uintptr_t) event.eventdata; + + /* And clear the event message in the target. */ + memset (&event, '\0', sizeof (td_eventbuf_t)); + if (ps_pdwrite (th->th_ta_p->ph, + ((char *) th->th_unique + + offsetof (struct _pthread_descr_struct, p_eventbuf)), + &event, sizeof (td_eventbuf_t)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + return TD_OK; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_thr_get_info.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_thr_get_info.c new file mode 100644 index 00000000..4666bda9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_thr_get_info.c @@ -0,0 +1,83 @@ +/* Get thread information. + Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +#include "thread_dbP.h" + + +td_err_e +td_thr_get_info (const td_thrhandle_t *th, td_thrinfo_t *infop) +{ + struct _pthread_descr_struct pds; + + LOG ("td_thr_get_info"); + + /* Handle the case when the thread library is not yet initialized. */ + if (th->th_unique == NULL) + { + memset (&pds, '\0', sizeof (pds)); + pds.p_tid = PTHREAD_THREADS_MAX; + } + else + /* Get the thread descriptor. */ + if (ps_pdread (th->th_ta_p->ph, th->th_unique, &pds, + th->th_ta_p->sizeof_descr) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + /* Fill in information. Clear first to provide reproducable + results for the fields we do not fill in. */ + memset (infop, '\0', sizeof (td_thrinfo_t)); + + /* We have to handle the manager thread special since the thread + descriptor in older versions is not fully initialized. */ + if (pds.p_nr == 1) + { + infop->ti_tid = th->th_ta_p->pthread_threads_max * 2 + 1; + infop->ti_type = TD_THR_SYSTEM; + infop->ti_state = TD_THR_ACTIVE; + } + else + { + infop->ti_tid = pds.p_tid; + infop->ti_tls = (char *) pds.p_specific; + infop->ti_pri = pds.p_priority; + infop->ti_type = TD_THR_USER; + + if (! pds.p_terminated) + /* XXX For now there is no way to get more information. */ + infop->ti_state = TD_THR_ACTIVE; + else if (! pds.p_detached) + infop->ti_state = TD_THR_ZOMBIE; + else + infop->ti_state = TD_THR_UNKNOWN; + } + + /* Initialization which are the same in both cases. */ + infop->ti_lid = pds.p_pid ?: ps_getpid (th->th_ta_p->ph); + infop->ti_ta_p = th->th_ta_p; + infop->ti_startfunc = pds.p_start_args.start_routine; + memcpy (&infop->ti_events, &pds.p_eventbuf.eventmask, + sizeof (td_thr_events_t)); + infop->ti_traceme = pds.p_report_events != 0; + + return TD_OK; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_thr_getfpregs.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_thr_getfpregs.c new file mode 100644 index 00000000..31c55c87 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_thr_getfpregs.c @@ -0,0 +1,58 @@ +/* Get a thread's floating-point register set. + Copyright (C) 1999, 2001, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_thr_getfpregs (const td_thrhandle_t *th, prfpregset_t *regset) +{ + struct _pthread_descr_struct pds; + + LOG ("td_thr_getfpregs"); + + if (th->th_unique == NULL) + { + /* No data yet. Use the main thread. */ + pid_t pid = ps_getpid (th->th_ta_p->ph); + if (ps_lgetfpregs (th->th_ta_p->ph, pid, regset) != PS_OK) + return TD_ERR; + return TD_OK; + } + + /* We have to get the state and the PID for this thread. */ + if (ps_pdread (th->th_ta_p->ph, th->th_unique, &pds, + sizeof (struct _pthread_descr_struct)) != PS_OK) + return TD_ERR; + + /* If the thread already terminated we return all zeroes. */ + if (pds.p_terminated) + memset (regset, '\0', sizeof (*regset)); + /* Otherwise get the register content through the callback. */ + else + { + pid_t pid = pds.p_pid ?: ps_getpid (th->th_ta_p->ph); + + if (ps_lgetfpregs (th->th_ta_p->ph, pid, regset) != PS_OK) + return TD_ERR; + } + + return TD_OK; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_thr_getgregs.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_thr_getgregs.c new file mode 100644 index 00000000..a9ec6a37 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_thr_getgregs.c @@ -0,0 +1,58 @@ +/* Get a thread's general register set. + Copyright (C) 1999, 2000, 2001, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_thr_getgregs (const td_thrhandle_t *th, prgregset_t gregs) +{ + struct _pthread_descr_struct pds; + + LOG ("td_thr_getgregs"); + + if (th->th_unique == NULL) + { + /* No data yet. Use the main thread. */ + pid_t pid = ps_getpid (th->th_ta_p->ph); + if (ps_lgetregs (th->th_ta_p->ph, pid, gregs) != PS_OK) + return TD_ERR; + return TD_OK; + } + + /* We have to get the state and the PID for this thread. */ + if (ps_pdread (th->th_ta_p->ph, th->th_unique, &pds, + sizeof (struct _pthread_descr_struct)) != PS_OK) + return TD_ERR; + + /* If the thread already terminated we return all zeroes. */ + if (pds.p_terminated) + memset (gregs, '\0', sizeof (prgregset_t)); + /* Otherwise get the register content through the callback. */ + else + { + pid_t pid = pds.p_pid ?: ps_getpid (th->th_ta_p->ph); + + if (ps_lgetregs (th->th_ta_p->ph, pid, gregs) != PS_OK) + return TD_ERR; + } + + return TD_OK; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_thr_getxregs.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_thr_getxregs.c new file mode 100644 index 00000000..39cd73cf --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_thr_getxregs.c @@ -0,0 +1,30 @@ +/* Get a thread's extra state register set. + Copyright (C) 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_thr_getxregs (const td_thrhandle_t *th, void *xregs) +{ + /* XXX This might be platform specific. */ + LOG ("td_thr_getxregs"); + return TD_NOXREGS; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_thr_getxregsize.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_thr_getxregsize.c new file mode 100644 index 00000000..5d8ac288 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_thr_getxregsize.c @@ -0,0 +1,30 @@ +/* Get the size of the extra state register set for this architecture. + Copyright (C) 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_thr_getxregsize (const td_thrhandle_t *th, int *sizep) +{ + /* XXX This might be platform specific. */ + LOG ("td_thr_getxregsize"); + return TD_NOXREGS; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_thr_set_event.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_thr_set_event.c new file mode 100644 index 00000000..1e1def51 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_thr_set_event.c @@ -0,0 +1,62 @@ +/* Enable specific event for thread. + Copyright (C) 1999, 2001, 2002, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#include "thread_dbP.h" + + +td_err_e +td_thr_set_event (th, event) + const td_thrhandle_t *th; + td_thr_events_t *event; +{ + td_thr_events_t old_event; + int i; + + LOG ("td_thr_set_event"); + + /* What shall we do if no thread descriptor exists but the user + wants to set an event? */ + if (th->th_unique == NULL) + return TD_NOTALLOC; + + /* Write the new value into the thread data structure. */ + if (ps_pdread (th->th_ta_p->ph, + ((char *) th->th_unique + + offsetof (struct _pthread_descr_struct, + p_eventbuf.eventmask)), + &old_event, sizeof (td_thr_events_t)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + /* Or the new bits in. */ + for (i = 0; i < TD_EVENTSIZE; ++i) + old_event.event_bits[i] |= event->event_bits[i]; + + /* Write the new value into the thread data structure. */ + if (ps_pdwrite (th->th_ta_p->ph, + ((char *) th->th_unique + + offsetof (struct _pthread_descr_struct, + p_eventbuf.eventmask)), + &old_event, sizeof (td_thr_events_t)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + return TD_OK; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_thr_setfpregs.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_thr_setfpregs.c new file mode 100644 index 00000000..e4d9ec65 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_thr_setfpregs.c @@ -0,0 +1,47 @@ +/* Set a thread's floating-point register set. + Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_thr_setfpregs (const td_thrhandle_t *th, const prfpregset_t *fpregs) +{ + struct _pthread_descr_struct pds = { .p_terminated = 0, .p_pid = 0 }; + + LOG ("td_thr_setfpregs"); + + /* We have to get the state and the PID for this thread. */ + if (th->th_unique != NULL + && ps_pdread (th->th_ta_p->ph, th->th_unique, &pds, + sizeof (struct _pthread_descr_struct)) != PS_OK) + return TD_ERR; + + /* Only set the registers if the thread hasn't yet terminated. */ + if (pds.p_terminated == 0) + { + pid_t pid = pds.p_pid ?: ps_getpid (th->th_ta_p->ph); + + if (ps_lsetfpregs (th->th_ta_p->ph, pid, fpregs) != PS_OK) + return TD_ERR; + } + + return TD_OK; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_thr_setgregs.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_thr_setgregs.c new file mode 100644 index 00000000..8c021a47 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_thr_setgregs.c @@ -0,0 +1,47 @@ +/* Set a thread's general register set. + Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_thr_setgregs (const td_thrhandle_t *th, prgregset_t gregs) +{ + struct _pthread_descr_struct pds = { .p_terminated = 0, .p_pid = 0 }; + + LOG ("td_thr_setgregs"); + + /* We have to get the state and the PID for this thread. */ + if (th->th_unique != NULL + && ps_pdread (th->th_ta_p->ph, th->th_unique, &pds, + sizeof (struct _pthread_descr_struct)) != PS_OK) + return TD_ERR; + + /* Only set the registers if the thread hasn't yet terminated. */ + if (pds.p_terminated == 0) + { + pid_t pid = pds.p_pid ?: ps_getpid (th->th_ta_p->ph); + + if (ps_lsetregs (th->th_ta_p->ph, pid, gregs) != PS_OK) + return TD_ERR; + } + + return TD_OK; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_thr_setprio.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_thr_setprio.c new file mode 100644 index 00000000..98d202df --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_thr_setprio.c @@ -0,0 +1,30 @@ +/* Set a thread's priority. + Copyright (C) 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_thr_setprio (const td_thrhandle_t *th, int prio) +{ + /* XXX We have to figure out what has to be done. */ + LOG ("td_thr_setprio"); + return TD_OK; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_thr_setsigpending.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_thr_setsigpending.c new file mode 100644 index 00000000..98e30140 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_thr_setsigpending.c @@ -0,0 +1,31 @@ +/* Raise a signal for a thread. + Copyright (C) 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_thr_setsigpending (const td_thrhandle_t *th, unsigned char n, + const sigset_t *ss) +{ + /* XXX We have to figure out what has to be done. */ + LOG ("td_thr_setsigpending"); + return TD_OK; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_thr_setxregs.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_thr_setxregs.c new file mode 100644 index 00000000..da77ab3b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_thr_setxregs.c @@ -0,0 +1,30 @@ +/* Set a thread's extra state register set. + Copyright (C) 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_thr_setxregs (const td_thrhandle_t *ta, const void *addr) +{ + /* XXX This might have to be platform specific. */ + LOG ("td_thr_setxregs"); + return TD_NOXREGS; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_thr_sigsetmask.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_thr_sigsetmask.c new file mode 100644 index 00000000..8b0eb818 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_thr_sigsetmask.c @@ -0,0 +1,30 @@ +/* Set a thread's signal mask. + Copyright (C) 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_thr_sigsetmask (const td_thrhandle_t *th, const sigset_t *ss) +{ + /* XXX We have to figure out what has to be done. */ + LOG ("td_thr_sigsetmask"); + return TD_OK; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_thr_tls_get_addr.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_thr_tls_get_addr.c new file mode 100644 index 00000000..8e38b690 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_thr_tls_get_addr.c @@ -0,0 +1,69 @@ +/* Get address of thread local variable. + Copyright (C) 2002,2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include "thread_dbP.h" + +/* Value used for dtv entries for which the allocation is delayed. */ +# define TLS_DTV_UNALLOCATED ((void *) -1l) + + +td_err_e +td_thr_tls_get_addr (const td_thrhandle_t *th __attribute__ ((unused)), + void *map_address __attribute__ ((unused)), + size_t offset __attribute__ ((unused)), + void **address __attribute__ ((unused))) +{ +#if defined(USE_TLS) && USE_TLS + size_t modid; + union dtv pdtv, *dtvp; + + LOG ("td_thr_tls_get_addr"); + + /* Get the DTV pointer from the thread descriptor. */ + if (ps_pdread (th->th_ta_p->ph, + &((struct _pthread_descr_struct *) th->th_unique)->p_header.data.dtvp, + &dtvp, sizeof dtvp) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + /* Read the module ID from the link_map. */ + if (ps_pdread (th->th_ta_p->ph, + &((struct link_map *) map_address)->l_tls_modid, + &modid, sizeof modid) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + /* Get the corresponding entry in the DTV. */ + if (ps_pdread (th->th_ta_p->ph, dtvp + modid, + &pdtv, sizeof (union dtv)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + /* It could be that the memory for this module is not allocated for + the given thread. */ + if (pdtv.pointer == TLS_DTV_UNALLOCATED) + /* There is not much we can do. */ + return TD_NOTALLOC; + + *address = (char *) pdtv.pointer + offset; + + return TD_OK; +#else + return TD_ERR; +#endif +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_thr_tsd.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_thr_tsd.c new file mode 100644 index 00000000..2ab71c58 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_thr_tsd.c @@ -0,0 +1,81 @@ +/* Get a thread-specific data pointer for a thread. + Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_thr_tsd (const td_thrhandle_t *th, const thread_key_t tk, void **data) +{ + struct _pthread_descr_struct pds; + struct pthread_key_struct *keys = th->th_ta_p->keys; + struct pthread_key_struct key; + int pthread_keys_max = th->th_ta_p->pthread_keys_max; + int pthread_key_2ndlevel_size = th->th_ta_p->pthread_key_2ndlevel_size; + unsigned int idx1st; + unsigned int idx2nd; + void *p; + + LOG ("td_thr_tsd"); + + /* If there is no thread descriptor there cannot be any thread + specific data. */ + if (th->th_unique == NULL) + return TD_BADKEY; + + /* Get the thread descriptor. */ + if (ps_pdread (th->th_ta_p->ph, th->th_unique, &pds, + sizeof (struct _pthread_descr_struct)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + /* Check correct value of key. */ + if (tk >= pthread_keys_max) + return TD_BADKEY; + + /* Get the key entry. */ + if (ps_pdread (th->th_ta_p->ph, &keys[tk], &key, + sizeof (struct pthread_key_struct)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + /* Fail if this key is not at all used. */ + if (! key.in_use) + return TD_BADKEY; + + /* Compute the indeces. */ + idx1st = tk / pthread_key_2ndlevel_size; + idx2nd = tk % pthread_key_2ndlevel_size; + + /* Check the pointer to the second level array. */ + if (pds.p_specific[idx1st] == NULL) + return TD_NOTSD; + + /* Now get the real key. + XXX I don't know whether it's correct but there is currently no + easy way to determine whether a key was never set or the value + is NULL. We return an error whenever the value is NULL. */ + if (ps_pdread (th->th_ta_p->ph, &pds.p_specific[idx1st][idx2nd], &p, + sizeof (void *)) != PS_OK) + return TD_ERR; + + if (p != NULL) + *data = p; + + return p != NULL ? TD_OK : TD_NOTSD; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_thr_validate.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_thr_validate.c new file mode 100644 index 00000000..2cf7727b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/td_thr_validate.c @@ -0,0 +1,69 @@ +/* Validate a thread handle. + Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_thr_validate (const td_thrhandle_t *th) +{ + struct pthread_handle_struct *handles = th->th_ta_p->handles; + int pthread_threads_max = th->th_ta_p->pthread_threads_max; + int cnt; + struct pthread_handle_struct phc; + + LOG ("td_thr_validate"); + + /* A special case: if the program just starts up the handle is + NULL. */ + if (th->th_unique == NULL) + { + /* Read the first handle. If the pointer to the thread + descriptor is not NULL this is an error. */ + if (ps_pdread (th->th_ta_p->ph, handles, &phc, + sizeof (struct pthread_handle_struct)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + return phc.h_descr == NULL ? TD_OK : TD_NOTHR; + } + + /* Now get all descriptors, one after the other. */ + for (cnt = 0; cnt < pthread_threads_max; ++cnt, ++handles) + { + if (ps_pdread (th->th_ta_p->ph, handles, &phc, + sizeof (struct pthread_handle_struct)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + if (phc.h_descr != NULL && phc.h_descr == th->th_unique) + { + struct _pthread_descr_struct pds; + + if (ps_pdread (th->th_ta_p->ph, phc.h_descr, &pds, + th->th_ta_p->sizeof_descr) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + /* XXX There should be another test using the TID but this is + currently not available. */ + return pds.p_terminated != 0 ? TD_NOTHR : TD_OK; + } + } + + return TD_ERR; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/thread_db.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/thread_db.h new file mode 100644 index 00000000..c115399a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/thread_db.h @@ -0,0 +1,459 @@ +/* thread_db.h -- interface to libthread_db.so library for debugging -lpthread + Copyright (C) 1999,2001,2002,2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _THREAD_DB_H +#define _THREAD_DB_H 1 + +/* This is the debugger interface for the LinuxThreads library. It is + modelled closely after the interface with same names in Solaris with + the goal to share the same code in the debugger. */ +#include +#include +#include +#include + + +/* Error codes of the library. */ +typedef enum +{ + TD_OK, /* No error. */ + TD_ERR, /* No further specified error. */ + TD_NOTHR, /* No matching thread found. */ + TD_NOSV, /* No matching synchronization handle found. */ + TD_NOLWP, /* No matching light-weighted process found. */ + TD_BADPH, /* Invalid process handle. */ + TD_BADTH, /* Invalid thread handle. */ + TD_BADSH, /* Invalid synchronization handle. */ + TD_BADTA, /* Invalid thread agent. */ + TD_BADKEY, /* Invalid key. */ + TD_NOMSG, /* No event available. */ + TD_NOFPREGS, /* No floating-point register content available. */ + TD_NOLIBTHREAD, /* Application not linked with thread library. */ + TD_NOEVENT, /* Requested event is not supported. */ + TD_NOCAPAB, /* Capability not available. */ + TD_DBERR, /* Internal debug library error. */ + TD_NOAPLIC, /* Operation is not applicable. */ + TD_NOTSD, /* No thread-specific data available. */ + TD_MALLOC, /* Out of memory. */ + TD_PARTIALREG, /* Not entire register set was read or written. */ + TD_NOXREGS, /* X register set not available for given thread. */ + TD_TLSDEFER, /* Thread has not yet allocated TLS for given module. */ + TD_NOTALLOC = TD_TLSDEFER, + TD_VERSION, /* Version if libpthread and libthread_db do not match. */ + TD_NOTLS /* There is TLS segment in the given module. */ +} td_err_e; + + +/* Possible thread states. TD_THR_ANY_STATE is a pseudo-state used to + select threads regardless of state in td_ta_thr_iter(). */ +typedef enum +{ + TD_THR_ANY_STATE, + TD_THR_UNKNOWN, + TD_THR_STOPPED, + TD_THR_RUN, + TD_THR_ACTIVE, + TD_THR_ZOMBIE, + TD_THR_SLEEP, + TD_THR_STOPPED_ASLEEP +} td_thr_state_e; + +/* Thread type: user or system. TD_THR_ANY_TYPE is a pseudo-type used + to select threads regardless of type in td_ta_thr_iter(). */ +typedef enum +{ + TD_THR_ANY_TYPE, + TD_THR_USER, + TD_THR_SYSTEM +} td_thr_type_e; + + +/* Types of the debugging library. */ + +/* Handle for a process. This type is opaque. */ +typedef struct td_thragent td_thragent_t; + +/* The actual thread handle type. This is also opaque. */ +typedef struct td_thrhandle +{ + td_thragent_t *th_ta_p; + psaddr_t th_unique; +} td_thrhandle_t; + + +/* Forward declaration of a type defined by and for the dynamic linker. */ +struct link_map; + + +/* Flags for `td_ta_thr_iter'. */ +#define TD_THR_ANY_USER_FLAGS 0xffffffff +#define TD_THR_LOWEST_PRIORITY -20 +#define TD_SIGNO_MASK NULL + + +#define TD_EVENTSIZE 2 +#define BT_UISHIFT 5 /* log base 2 of BT_NBIPUI, to extract word index */ +#define BT_NBIPUI (1 << BT_UISHIFT) /* n bits per uint */ +#define BT_UIMASK (BT_NBIPUI - 1) /* to extract bit index */ + +/* Bitmask of enabled events. */ +typedef struct td_thr_events +{ + uint32_t event_bits[TD_EVENTSIZE]; +} td_thr_events_t; + +/* Event set manipulation macros. */ +#define __td_eventmask(n) \ + (UINT32_C (1) << (((n) - 1) & BT_UIMASK)) +#define __td_eventword(n) \ + ((UINT32_C ((n) - 1)) >> BT_UISHIFT) + +#define td_event_emptyset(setp) \ + do { \ + int __i; \ + for (__i = TD_EVENTSIZE; __i > 0; --__i) \ + (setp)->event_bits[__i - 1] = 0; \ + } while (0) + +#define td_event_fillset(setp) \ + do { \ + int __i; \ + for (__i = TD_EVENTSIZE; __i > 0; --__i) \ + (setp)->event_bits[__i - 1] = UINT32_C (0xffffffff); \ + } while (0) + +#define td_event_addset(setp, n) \ + (((setp)->event_bits[__td_eventword (n)]) |= __td_eventmask (n)) +#define td_event_delset(setp, n) \ + (((setp)->event_bits[__td_eventword (n)]) &= ~__td_eventmask (n)) +#define td_eventismember(setp, n) \ + (__td_eventmask (n) & ((setp)->event_bits[__td_eventword (n)])) +#if TD_EVENTSIZE == 2 +# define td_eventisempty(setp) \ + (!((setp)->event_bits[0]) && !((setp)->event_bits[1])) +#else +# error "td_eventisempty must be changed to match TD_EVENTSIZE" +#endif + +/* Events reportable by the thread implementation. */ +typedef enum +{ + TD_ALL_EVENTS, /* Pseudo-event number. */ + TD_EVENT_NONE = TD_ALL_EVENTS, /* Depends on context. */ + TD_READY, /* Is executable now. */ + TD_SLEEP, /* Blocked in a synchronization obj. */ + TD_SWITCHTO, /* Now assigned to a process. */ + TD_SWITCHFROM, /* Not anymore assigned to a process. */ + TD_LOCK_TRY, /* Trying to get an unavailable lock. */ + TD_CATCHSIG, /* Signal posted to the thread. */ + TD_IDLE, /* Process getting idle. */ + TD_CREATE, /* New thread created. */ + TD_DEATH, /* Thread terminated. */ + TD_PREEMPT, /* Preempted. */ + TD_PRI_INHERIT, /* Inherited elevated priority. */ + TD_REAP, /* Reaped. */ + TD_CONCURRENCY, /* Number of processes changing. */ + TD_TIMEOUT, /* Conditional variable wait timed out. */ + TD_MIN_EVENT_NUM = TD_READY, + TD_MAX_EVENT_NUM = TD_TIMEOUT, + TD_EVENTS_ENABLE = 31 /* Event reporting enabled. */ +} td_event_e; + +/* Values representing the different ways events are reported. */ +typedef enum +{ + NOTIFY_BPT, /* User must insert breakpoint at u.bptaddr. */ + NOTIFY_AUTOBPT, /* Breakpoint at u.bptaddr is automatically + inserted. */ + NOTIFY_SYSCALL /* System call u.syscallno will be invoked. */ +} td_notify_e; + +/* Description how event type is reported. */ +typedef struct td_notify +{ + td_notify_e type; /* Way the event is reported. */ + union + { + psaddr_t bptaddr; /* Address of breakpoint. */ + int syscallno; /* Number of system call used. */ + } u; +} td_notify_t; + +/* Structure used to report event. */ +typedef struct td_event_msg +{ + td_event_e event; /* Event type being reported. */ + const td_thrhandle_t *th_p; /* Thread reporting the event. */ + union + { +# if 0 + td_synchandle_t *sh; /* Handle of synchronization object. */ +#endif + uintptr_t data; /* Event specific data. */ + } msg; +} td_event_msg_t; + +/* Structure containing event data available in each thread structure. */ +typedef struct +{ + td_thr_events_t eventmask; /* Mask of enabled events. */ + td_event_e eventnum; /* Number of last event. */ + void *eventdata; /* Data associated with event. */ +} td_eventbuf_t; + + +/* Gathered statistics about the process. */ +typedef struct td_ta_stats +{ + int nthreads; /* Total number of threads in use. */ + int r_concurrency; /* Concurrency level requested by user. */ + int nrunnable_num; /* Average runnable threads, numerator. */ + int nrunnable_den; /* Average runnable threads, denominator. */ + int a_concurrency_num; /* Achieved concurrency level, numerator. */ + int a_concurrency_den; /* Achieved concurrency level, denominator. */ + int nlwps_num; /* Average number of processes in use, + numerator. */ + int nlwps_den; /* Average number of processes in use, + denominator. */ + int nidle_num; /* Average number of idling processes, + numerator. */ + int nidle_den; /* Average number of idling processes, + denominator. */ +} td_ta_stats_t; + + +/* Since Sun's library is based on Solaris threads we have to define a few + types to map them to POSIX threads. */ +typedef pthread_t thread_t; +typedef pthread_key_t thread_key_t; + + +/* Callback for iteration over threads. */ +typedef int td_thr_iter_f (const td_thrhandle_t *, void *); + +/* Callback for iteration over thread local data. */ +typedef int td_key_iter_f (thread_key_t, void (*) (void *), void *); + + + +/* Forward declaration. This has to be defined by the user. */ +struct ps_prochandle; + + +/* Information about the thread. */ +typedef struct td_thrinfo +{ + td_thragent_t *ti_ta_p; /* Process handle. */ + unsigned int ti_user_flags; /* Unused. */ + thread_t ti_tid; /* Thread ID returned by + pthread_create(). */ + char *ti_tls; /* Pointer to thread-local data. */ + psaddr_t ti_startfunc; /* Start function passed to + pthread_create(). */ + psaddr_t ti_stkbase; /* Base of thread's stack. */ + long int ti_stksize; /* Size of thread's stack. */ + psaddr_t ti_ro_area; /* Unused. */ + int ti_ro_size; /* Unused. */ + td_thr_state_e ti_state; /* Thread state. */ + unsigned char ti_db_suspended; /* Nonzero if suspended by debugger. */ + td_thr_type_e ti_type; /* Type of the thread (system vs + user thread). */ + intptr_t ti_pc; /* Unused. */ + intptr_t ti_sp; /* Unused. */ + short int ti_flags; /* Unused. */ + int ti_pri; /* Thread priority. */ + lwpid_t ti_lid; /* Unused. */ + sigset_t ti_sigmask; /* Signal mask. */ + unsigned char ti_traceme; /* Nonzero if event reporting + enabled. */ + unsigned char ti_preemptflag; /* Unused. */ + unsigned char ti_pirecflag; /* Unused. */ + sigset_t ti_pending; /* Set of pending signals. */ + td_thr_events_t ti_events; /* Set of enabled events. */ +} td_thrinfo_t; + + + +/* Prototypes for exported library functions. */ + +/* Initialize the thread debug support library. */ +extern td_err_e td_init (void); + +/* Historical relict. Should not be used anymore. */ +extern td_err_e td_log (void); + +/* Return list of symbols the library can request. */ +extern const char **td_symbol_list (void); + +/* Generate new thread debug library handle for process PS. */ +extern td_err_e td_ta_new (struct ps_prochandle *__ps, td_thragent_t **__ta); + +/* Free resources allocated for TA. */ +extern td_err_e td_ta_delete (td_thragent_t *__ta); + +/* Get number of currently running threads in process associated with TA. */ +extern td_err_e td_ta_get_nthreads (const td_thragent_t *__ta, int *__np); + +/* Return process handle passed in `td_ta_new' for process associated with + TA. */ +extern td_err_e td_ta_get_ph (const td_thragent_t *__ta, + struct ps_prochandle **__ph); + +/* Map thread library handle PT to thread debug library handle for process + associated with TA and store result in *TH. */ +extern td_err_e td_ta_map_id2thr (const td_thragent_t *__ta, pthread_t __pt, + td_thrhandle_t *__th); + +/* Map process ID LWPID to thread debug library handle for process + associated with TA and store result in *TH. */ +extern td_err_e td_ta_map_lwp2thr (const td_thragent_t *__ta, lwpid_t __lwpid, + td_thrhandle_t *__th); + + +/* Call for each thread in a process associated with TA the callback function + CALLBACK. */ +extern td_err_e td_ta_thr_iter (const td_thragent_t *__ta, + td_thr_iter_f *__callback, void *__cbdata_p, + td_thr_state_e __state, int __ti_pri, + sigset_t *__ti_sigmask_p, + unsigned int __ti_user_flags); + +/* Call for each defined thread local data entry the callback function KI. */ +extern td_err_e td_ta_tsd_iter (const td_thragent_t *__ta, td_key_iter_f *__ki, + void *__p); + + +/* Get event address for EVENT. */ +extern td_err_e td_ta_event_addr (const td_thragent_t *__ta, + td_event_e __event, td_notify_t *__ptr); + +/* Enable EVENT in global mask. */ +extern td_err_e td_ta_set_event (const td_thragent_t *__ta, + td_thr_events_t *__event); + +/* Disable EVENT in global mask. */ +extern td_err_e td_ta_clear_event (const td_thragent_t *__ta, + td_thr_events_t *__event); + +/* Return information about last event. */ +extern td_err_e td_ta_event_getmsg (const td_thragent_t *__ta, + td_event_msg_t *__msg); + + +/* Set suggested concurrency level for process associated with TA. */ +extern td_err_e td_ta_setconcurrency (const td_thragent_t *__ta, int __level); + + +/* Enable collecting statistics for process associated with TA. */ +extern td_err_e td_ta_enable_stats (const td_thragent_t *__ta, int __enable); + +/* Reset statistics. */ +extern td_err_e td_ta_reset_stats (const td_thragent_t *__ta); + +/* Retrieve statistics from process associated with TA. */ +extern td_err_e td_ta_get_stats (const td_thragent_t *__ta, + td_ta_stats_t *__statsp); + + +/* Validate that TH is a thread handle. */ +extern td_err_e td_thr_validate (const td_thrhandle_t *__th); + +/* Return information about thread TH. */ +extern td_err_e td_thr_get_info (const td_thrhandle_t *__th, + td_thrinfo_t *__infop); + +/* Retrieve floating-point register contents of process running thread TH. */ +extern td_err_e td_thr_getfpregs (const td_thrhandle_t *__th, + prfpregset_t *__regset); + +/* Retrieve general register contents of process running thread TH. */ +extern td_err_e td_thr_getgregs (const td_thrhandle_t *__th, + prgregset_t __gregs); + +/* Retrieve extended register contents of process running thread TH. */ +extern td_err_e td_thr_getxregs (const td_thrhandle_t *__th, void *__xregs); + +/* Get size of extended register set of process running thread TH. */ +extern td_err_e td_thr_getxregsize (const td_thrhandle_t *__th, int *__sizep); + +/* Set floating-point register contents of process running thread TH. */ +extern td_err_e td_thr_setfpregs (const td_thrhandle_t *__th, + const prfpregset_t *__fpregs); + +/* Set general register contents of process running thread TH. */ +extern td_err_e td_thr_setgregs (const td_thrhandle_t *__th, + prgregset_t __gregs); + +/* Set extended register contents of process running thread TH. */ +extern td_err_e td_thr_setxregs (const td_thrhandle_t *__th, + const void *__addr); + + +/* Get address of the given module's TLS storage area for the given thread. */ +extern td_err_e td_thr_tlsbase (const td_thrhandle_t *__th, + unsigned long int __modid, + psaddr_t *__base); + +/* Get address of thread local variable. */ +extern td_err_e td_thr_tls_get_addr (const td_thrhandle_t *__th, + void *__map_address, size_t __offset, + void **__address); + + +/* Enable reporting for EVENT for thread TH. */ +extern td_err_e td_thr_event_enable (const td_thrhandle_t *__th, int __event); + +/* Enable EVENT for thread TH. */ +extern td_err_e td_thr_set_event (const td_thrhandle_t *__th, + td_thr_events_t *__event); + +/* Disable EVENT for thread TH. */ +extern td_err_e td_thr_clear_event (const td_thrhandle_t *__th, + td_thr_events_t *__event); + +/* Get event message for thread TH. */ +extern td_err_e td_thr_event_getmsg (const td_thrhandle_t *__th, + td_event_msg_t *__msg); + + +/* Set priority of thread TH. */ +extern td_err_e td_thr_setprio (const td_thrhandle_t *__th, int __prio); + + +/* Set pending signals for thread TH. */ +extern td_err_e td_thr_setsigpending (const td_thrhandle_t *__th, + unsigned char __n, const sigset_t *__ss); + +/* Set signal mask for thread TH. */ +extern td_err_e td_thr_sigsetmask (const td_thrhandle_t *__th, + const sigset_t *__ss); + + +/* Return thread local data associated with key TK in thread TH. */ +extern td_err_e td_thr_tsd (const td_thrhandle_t *__th, + const thread_key_t __tk, void **__data); + + +/* Suspend execution of thread TH. */ +extern td_err_e td_thr_dbsuspend (const td_thrhandle_t *__th); + +/* Resume execution of thread TH. */ +extern td_err_e td_thr_dbresume (const td_thrhandle_t *__th); + +#endif /* thread_db.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/thread_dbP.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/thread_dbP.h new file mode 100644 index 00000000..b120c42b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads.old_db/thread_dbP.h @@ -0,0 +1,110 @@ +/* Private header for thread debug library. */ +#ifndef _THREAD_DBP_H +#define _THREAD_DBP_H 1 + +#define __FORCE_GLIBC +#include +#include +#include +#include "proc_service.h" +#include "thread_db.h" +#include "internals.h" + + +/* Indices for the symbol names. */ +enum + { + PTHREAD_THREADS_EVENTS = 0, + PTHREAD_LAST_EVENT, + PTHREAD_HANDLES_NUM, + PTHREAD_HANDLES, + PTHREAD_KEYS, + LINUXTHREADS_PTHREAD_THREADS_MAX, + LINUXTHREADS_PTHREAD_KEYS_MAX, + LINUXTHREADS_PTHREAD_SIZEOF_DESCR, + LINUXTHREADS_CREATE_EVENT, + LINUXTHREADS_DEATH_EVENT, + LINUXTHREADS_REAP_EVENT, + LINUXTHREADS_INITIAL_REPORT_EVENTS, + LINUXTHREADS_VERSION, + NUM_MESSAGES + }; + + +/* Comment out the following for less verbose output. */ +#ifndef NDEBUG +# define LOG(c) if (__td_debug) write (2, c "\n", strlen (c "\n")) +extern int __td_debug attribute_hidden; +#else +# define LOG(c) +#endif + + +/* Handle for a process. This type is opaque. */ +struct td_thragent +{ + /* Delivered by the debugger and we have to pass it back in the + proc callbacks. */ + struct ps_prochandle *ph; + + /* Some cached information. */ + + /* Address of the `__pthread_handles' array. */ + struct pthread_handle_struct *handles; + + /* Address of the `pthread_kyes' array. */ + struct pthread_key_struct *keys; + + /* Maximum number of threads. */ + int pthread_threads_max; + + /* Maximum number of thread-local data keys. */ + int pthread_keys_max; + + /* Size of 2nd level array for thread-local data keys. */ + int pthread_key_2ndlevel_size; + + /* Sizeof struct _pthread_descr_struct. */ + int sizeof_descr; + + /* Pointer to the `__pthread_threads_events' variable in the target. */ + psaddr_t pthread_threads_eventsp; + + /* Pointer to the `__pthread_last_event' variable in the target. */ + psaddr_t pthread_last_event; + + /* Pointer to the `__pthread_handles_num' variable. */ + psaddr_t pthread_handles_num; +}; + + +/* Type used internally to keep track of thread agent descriptors. */ +struct agent_list +{ + td_thragent_t *ta; + struct agent_list *next; +}; + +/* List of all known descriptors. */ +extern struct agent_list *__td_agent_list attribute_hidden; + +/* Function used to test for correct thread agent pointer. */ +static __inline__ int +ta_ok (const td_thragent_t *ta) +{ + struct agent_list *runp = __td_agent_list; + + if (ta == NULL) + return 0; + + while (runp != NULL && runp->ta != ta) + runp = runp->next; + + return runp != NULL; +} + + +/* Internal wrapper around ps_pglobal_lookup. */ +extern int td_lookup (struct ps_prochandle *ps, int idx, psaddr_t *sym_addr) attribute_hidden; + +#endif /* thread_dbP.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/.cvsignore b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/.cvsignore new file mode 100644 index 00000000..688daf41 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/.cvsignore @@ -0,0 +1,3 @@ +.cvsignore +*.os +Makefile.in diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/Makefile new file mode 100644 index 00000000..f9100219 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../ +top_builddir=../../ +include $(top_builddir)Rules.mak +all: libs +include Makefile.in +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/Makefile.in new file mode 100644 index 00000000..697371b0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/Makefile.in @@ -0,0 +1,142 @@ +# Makefile for uClibc +# +# Copyright (C) 2003 Paul Mundt +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +subdirs += libpthread/linuxthreads/sysdeps/$(TARGET_ARCH) +subdirs += libpthread/linuxthreads/sysdeps/unix/sysv/linux +subdirs += libpthread/linuxthreads/sysdeps/pthread + +CFLAGS-dir_linuxthreads := -DNOT_IN_libc -DIS_IN_libpthread +CFLAGS-linuxthreads := $(CFLAGS-dir_linuxthreads) $(SSP_ALL_CFLAGS) + +CFLAGS-libpthread/linuxthreads/sysdeps/$(TARGET_ARCH)/ := $(CFLAGS-linuxthreads) +CFLAGS-libpthread/linuxthreads/sysdeps/unix/sysv/linux/ := $(CFLAGS-linuxthreads) +CFLAGS-libpthread/linuxthreads/sysdeps/pthread/ := $(CFLAGS-linuxthreads) + +# This stuff will not compile without at least -O1 +# psm: can't handle this here, could maybe search for -O0 in CFLAGS +# and append -O1 if found +#CFLAGS:=$(CFLAGS:-O0=-O1) + +ifeq ($(PTHREADS_DEBUG_SUPPORT),y) +LDFLAGS-libpthread.so := $(LDFLAGS_NOSTRIP) -Wl,-z,defs +else +LDFLAGS-libpthread.so := $(LDFLAGS) +endif + +LIBS-libpthread.so := $(LIBS) $(ldso) + +START_FILE-libpthread.so := $(SHARED_START_FILES) +END_FILE-libpthread.so := $(SHARED_END_FILES) + +libpthread_FULL_NAME := libpthread-$(VERSION).so + +libpthread_DIR := $(top_srcdir)libpthread/linuxthreads +libpthread_OUT := $(top_builddir)libpthread/linuxthreads + +-include $(libpthread_DIR)/sysdeps/$(TARGET_ARCH)/Makefile.arch + +pthread_arch_SRC := pspinlock +pthread_arch_SRC := $(patsubst %,$(libpthread_DIR)/sysdeps/$(TARGET_ARCH)/%.c,$(pthread_arch_SRC)) +pthread_linux_SRC := fork pt-sigsuspend register-atfork unregister-atfork +pthread_linux_SRC := $(patsubst %,$(libpthread_DIR)/sysdeps/unix/sysv/linux/%.c,$(pthread_linux_SRC)) +pthread_sysdep_SRC := errno-loc herrno-loc ptlongjmp +pthread_sysdep_SRC := $(patsubst %,$(libpthread_DIR)/sysdeps/pthread/%.c,$(pthread_sysdep_SRC)) +pthread_SRC := \ + attr barrier cancel condvar errno events join pthread \ + lockfile manager mutex pt-machine ptcleanup \ + ptclock_gettime ptclock_settime ptfork pthandles \ + pthread_setegid pthread_seteuid pthread_setgid pthread_setregid \ + pthread_setresgid pthread_setresuid pthread_setreuid pthread_setuid \ + rwlock semaphore sighandler signals specific spinlock +pthread_SRC := $(patsubst %,$(libpthread_DIR)/%.c,$(pthread_SRC)) + +libpthread_static_SRC := pthread_atfork +libpthread_SRC := $(pthread_arch_SRC) $(pthread_linux_SRC) $(pthread_sysdep_SRC) $(pthread_SRC) +libpthread_OBJ := $(patsubst $(libpthread_DIR)/%.c,$(libpthread_OUT)/%.o,$(libpthread_SRC)) + +# +# Stuff that goes into libc.so, not libpthread.so +# +#CFLAGS-OMIT-alloca_cutoff.c := $(CFLAGS-dir_linuxthreads) +CFLAGS-OMIT-forward.c := $(CFLAGS-dir_linuxthreads) +CFLAGS-OMIT-libc-cancellation.c := $(CFLAGS-dir_linuxthreads) +CFLAGS-OMIT-libc_pthread_init.c := $(CFLAGS-dir_linuxthreads) +libpthread_libc_CSRC := \ + forward.c libc-cancellation.c libc_pthread_init.c # alloca_cutoff.c +libpthread_libc_OBJ := $(patsubst %.c, $(libpthread_OUT)/%.o,$(libpthread_libc_CSRC)) +libc-static-y += $(libpthread_OUT)/libc_pthread_init.o +libc-shared-y += $(libpthread_libc_OBJ:.o=.oS) + +libpthread-static-y += $(patsubst %,$(libpthread_OUT)/%.o,$(libpthread_static_SRC)) + +libpthread-nonshared-y += $(patsubst %,$(libpthread_OUT)/%.oS,$(libpthread_static_SRC)) + +ifeq ($(DOPIC),y) +libpthread-a-y += $(libpthread_OBJ:.o=.os) $(libpthread-static-y:.o=.os) +else +libpthread-a-y += $(libpthread_OBJ) $(libpthread-static-y) +endif +libpthread-so-y += $(libpthread_OBJ:.o=.oS) + +lib-a-$(UCLIBC_HAS_THREADS) += $(top_builddir)lib/libpthread.a +lib-so-$(UCLIBC_HAS_THREADS) += $(top_builddir)lib/libpthread.so + +#ifeq ($(DOMULTI),n) +$(top_builddir)lib/libpthread.so: $(libpthread_OUT)/libpthread_so.a $(libc.depend) $(top_builddir)lib/libpthread_nonshared.a + $(call link.so,$(libpthread_FULL_NAME),$(ABI_VERSION)) +#else +#$(top_builddir)lib/libpthread.so: $(libpthread_OUT)/libpthread.oS | $(libc.depend) $(top_builddir)lib/libpthread_nonshared.a +# $(call linkm.so,$(libpthread_FULL_NAME),$(ABI_VERSION)) +#endif + $(Q)$(RM) $@ + $(Q)cat $(top_srcdir)extra/scripts/format.lds > $@.tmp + $(Q)echo "GROUP ( $(notdir $@).$(ABI_VERSION) libpthread_nonshared.a )" >> $@.tmp + $(Q)mv $@.tmp $@ + +ifeq ($(PTHREADS_DEBUG_SUPPORT),y) +$(libpthread_OUT)/libpthread_so.a: STRIP_FLAGS:=$(STRIP_FLAGS:-x=-X --strip-debug) +endif +$(libpthread_OUT)/libpthread_so.a: $(libpthread-so-y) + $(Q)$(RM) $@ + $(do_ar) + +ifeq ($(PTHREADS_DEBUG_SUPPORT),y) +$(libpthread_OUT)/libpthread.oS: STRIP_FLAGS:=$(STRIP_FLAGS:-x=-X --strip-debug) +endif +$(libpthread_OUT)/libpthread.oS: $(libpthread_SRC) + $(Q)$(RM) $@ + $(compile-m) + +ifeq ($(PTHREADS_DEBUG_SUPPORT),y) +$(top_builddir)lib/libpthread.a: STRIP_FLAGS:=$(STRIP_FLAGS:-x=-X --strip-debug) +endif +$(top_builddir)lib/libpthread.a: $(libpthread-a-y) + $(Q)$(INSTALL) -d $(dir $@) + $(Q)$(RM) $@ + $(do_ar) + +$(top_builddir)include/pthread.h: + $(do_ln) $(call rel_srcdir)$(PTDIR)/sysdeps/pthread/$(@F) $@ +$(top_builddir)include/semaphore.h: + $(do_ln) $(call rel_srcdir)$(PTDIR)/$(@F) $@ +$(top_builddir)include/bits/pthreadtypes.h: | $(top_builddir)include/bits + $(do_ln) $(call rel_srcdir)$(PTDIR)/sysdeps/pthread/bits/$(@F) $@ + +linuxthreads_headers := $(top_builddir)include/pthread.h \ + $(top_builddir)include/semaphore.h \ + $(top_builddir)include/bits/pthreadtypes.h +$(linuxthreads_headers): $(wildcard $(addprefix $(top_builddir)include/config/linuxthreads/,old.h new.h)) +headers-$(UCLIBC_HAS_THREADS) += $(linuxthreads_headers) + +objclean-y += CLEAN_libpthread/linuxthreads +headers_clean-y += HEADERCLEAN_libpthread/linuxthreads +HEADERCLEAN_libpthread/linuxthreads: + $(do_rm) $(linuxthreads_headers) + +CLEAN_libpthread/linuxthreads: + $(do_rm) $(addprefix $(libpthread_OUT)/,$(foreach e, o os oS a,$(foreach d, *. */*. */*/*. */*/*/*.,$(d)$(e)))) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/alloca_cutoff.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/alloca_cutoff.c new file mode 100644 index 00000000..ca064b3b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/alloca_cutoff.c @@ -0,0 +1,36 @@ +/* Determine whether block of given size can be allocated on the stack or not. + Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include "internals.h" +#include + +int +__libc_alloca_cutoff (size_t size) +{ + if (! SINGLE_THREAD_P) + { + pthread_descr self = thread_self (); + return size <= LIBC_THREAD_GETMEM (self, p_alloca_cutoff); + } + + return size <= __MAX_ALLOCA_CUTOFF; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/attr.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/attr.c new file mode 100644 index 00000000..52e115c8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/attr.c @@ -0,0 +1,469 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +/* Handling of thread attributes */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "pthread.h" +#include "internals.h" + + +int __pthread_attr_init(pthread_attr_t *attr) +{ + size_t ps = __getpagesize (); + + attr->__detachstate = PTHREAD_CREATE_JOINABLE; + attr->__schedpolicy = SCHED_OTHER; + attr->__schedparam.sched_priority = 0; + attr->__inheritsched = PTHREAD_EXPLICIT_SCHED; + attr->__scope = PTHREAD_SCOPE_SYSTEM; +#ifdef NEED_SEPARATE_REGISTER_STACK + attr->__guardsize = ps + ps; +#else + attr->__guardsize = ps; +#endif + attr->__stackaddr = NULL; + attr->__stackaddr_set = 0; + attr->__stacksize = STACK_SIZE - ps; + return 0; +} +strong_alias (__pthread_attr_init, pthread_attr_init) + +int __pthread_attr_destroy(pthread_attr_t *attr) +{ + return 0; +} +strong_alias (__pthread_attr_destroy, pthread_attr_destroy) + +int __pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate) +{ + if (detachstate < PTHREAD_CREATE_JOINABLE || + detachstate > PTHREAD_CREATE_DETACHED) + return EINVAL; + attr->__detachstate = detachstate; + return 0; +} +strong_alias (__pthread_attr_setdetachstate, pthread_attr_setdetachstate) + +int __pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate) +{ + *detachstate = attr->__detachstate; + return 0; +} +strong_alias (__pthread_attr_getdetachstate, pthread_attr_getdetachstate) + +int __pthread_attr_setschedparam(pthread_attr_t *attr, + const struct sched_param *param) +{ + int max_prio = __sched_get_priority_max(attr->__schedpolicy); + int min_prio = __sched_get_priority_min(attr->__schedpolicy); + + if (param->sched_priority < min_prio || param->sched_priority > max_prio) + return EINVAL; + memcpy (&attr->__schedparam, param, sizeof (struct sched_param)); + return 0; +} +strong_alias (__pthread_attr_setschedparam, pthread_attr_setschedparam) + +int __pthread_attr_getschedparam(const pthread_attr_t *attr, + struct sched_param *param) +{ + memcpy (param, &attr->__schedparam, sizeof (struct sched_param)); + return 0; +} +strong_alias (__pthread_attr_getschedparam, pthread_attr_getschedparam) + +int __pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy) +{ + if (policy != SCHED_OTHER && policy != SCHED_FIFO && policy != SCHED_RR) + return EINVAL; + attr->__schedpolicy = policy; + return 0; +} +strong_alias (__pthread_attr_setschedpolicy, pthread_attr_setschedpolicy) + +int __pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy) +{ + *policy = attr->__schedpolicy; + return 0; +} +strong_alias (__pthread_attr_getschedpolicy, pthread_attr_getschedpolicy) + +int __pthread_attr_setinheritsched(pthread_attr_t *attr, int inherit) +{ + if (inherit != PTHREAD_INHERIT_SCHED && inherit != PTHREAD_EXPLICIT_SCHED) + return EINVAL; + attr->__inheritsched = inherit; + return 0; +} +strong_alias (__pthread_attr_setinheritsched, pthread_attr_setinheritsched) + +int __pthread_attr_getinheritsched(const pthread_attr_t *attr, int *inherit) +{ + *inherit = attr->__inheritsched; + return 0; +} +strong_alias (__pthread_attr_getinheritsched, pthread_attr_getinheritsched) + +int __pthread_attr_setscope(pthread_attr_t *attr, int scope) +{ + switch (scope) { + case PTHREAD_SCOPE_SYSTEM: + attr->__scope = scope; + return 0; + case PTHREAD_SCOPE_PROCESS: + return ENOTSUP; + default: + return EINVAL; + } +} +strong_alias (__pthread_attr_setscope, pthread_attr_setscope) + +int __pthread_attr_getscope(const pthread_attr_t *attr, int *scope) +{ + *scope = attr->__scope; + return 0; +} +strong_alias (__pthread_attr_getscope, pthread_attr_getscope) + +int __pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize) +{ + /* The guard size must not be larger than the stack itself */ + if (guardsize >= attr->__stacksize) return EINVAL; + + attr->__guardsize = guardsize; + + return 0; +} +weak_alias (__pthread_attr_setguardsize, pthread_attr_setguardsize) + +int __pthread_attr_getguardsize(const pthread_attr_t *attr, size_t *guardsize) +{ + *guardsize = attr->__guardsize; + return 0; +} +weak_alias (__pthread_attr_getguardsize, pthread_attr_getguardsize) + +#if 0 /* uClibc: deprecated stuff disabled */ +int __pthread_attr_setstackaddr(pthread_attr_t *attr, void *stackaddr) +{ + attr->__stackaddr = stackaddr; + attr->__stackaddr_set = 1; + return 0; +} +weak_alias (__pthread_attr_setstackaddr, pthread_attr_setstackaddr) + +link_warning (pthread_attr_setstackaddr, + "the use of `pthread_attr_setstackaddr' is deprecated, use `pthread_attr_setstack'") + +int __pthread_attr_getstackaddr(const pthread_attr_t *attr, void **stackaddr) +{ + /* XXX This function has a stupid definition. The standard specifies + no error value but what is if no stack address was set? We simply + return the value we have in the member. */ + *stackaddr = attr->__stackaddr; + return 0; +} +weak_alias (__pthread_attr_getstackaddr, pthread_attr_getstackaddr) + +link_warning (pthread_attr_getstackaddr, + "the use of `pthread_attr_getstackaddr' is deprecated, use `pthread_attr_getstack'") +#endif + + +int __pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize) +{ +#ifdef FLOATING_STACKS + /* We have to check against the maximum allowed stack size. This is no + problem if the manager is already started and we determined it. If + this hasn't happened, we have to find the limit outself. */ + if (__pthread_max_stacksize == 0) + __pthread_init_max_stacksize (); + + if (stacksize > __pthread_max_stacksize) + return EINVAL; +#else + /* We have a fixed size limit. */ + if (stacksize > STACK_SIZE) + return EINVAL; +#endif + + /* We don't accept value smaller than PTHREAD_STACK_MIN. */ + if (stacksize < PTHREAD_STACK_MIN) + return EINVAL; + + attr->__stacksize = stacksize; + return 0; +} + +#if PTHREAD_STACK_MIN == 16384 || defined __UCLIBC__ +weak_alias (__pthread_attr_setstacksize, pthread_attr_setstacksize) +#else +versioned_symbol (libpthread, __pthread_attr_setstacksize, + pthread_attr_setstacksize, GLIBC_2_3_3); + +# if SHLIB_COMPAT(libpthread, GLIBC_2_1, GLIBC_2_3_3) + +int __old_pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize) +{ +# ifdef FLOATING_STACKS + /* We have to check against the maximum allowed stack size. This is no + problem if the manager is already started and we determined it. If + this hasn't happened, we have to find the limit outself. */ + if (__pthread_max_stacksize == 0) + __pthread_init_max_stacksize (); + + if (stacksize > __pthread_max_stacksize) + return EINVAL; +# else + /* We have a fixed size limit. */ + if (stacksize > STACK_SIZE) + return EINVAL; +# endif + + /* We don't accept value smaller than old PTHREAD_STACK_MIN. */ + if (stacksize < 16384) + return EINVAL; + + attr->__stacksize = stacksize; + return 0; +} +compat_symbol (libpthread, __old_pthread_attr_setstacksize, + pthread_attr_setstacksize, GLIBC_2_1); +# endif +#endif + + +int __pthread_attr_getstacksize(const pthread_attr_t *attr, size_t *stacksize) +{ + *stacksize = attr->__stacksize; + return 0; +} +weak_alias (__pthread_attr_getstacksize, pthread_attr_getstacksize) + +int __pthread_attr_setstack (pthread_attr_t *attr, void *stackaddr, + size_t stacksize) +{ + int err; + + if ((((uintptr_t) stackaddr) + & (__alignof__ (struct _pthread_descr_struct) - 1)) != 0) + err = EINVAL; + else + err = __pthread_attr_setstacksize (attr, stacksize); + if (err == 0) + { +#ifndef _STACK_GROWS_UP + attr->__stackaddr = (char *) stackaddr + stacksize; +#else + attr->__stackaddr = stackaddr; +#endif + attr->__stackaddr_set = 1; + } + + return err; +} + +#if PTHREAD_STACK_MIN == 16384 || defined __UCLIBC__ +weak_alias (__pthread_attr_setstack, pthread_attr_setstack) +#else +versioned_symbol (libpthread, __pthread_attr_setstack, pthread_attr_setstack, + GLIBC_2_3_3); +# if SHLIB_COMPAT(libpthread, GLIBC_2_2, GLIBC_2_3_3) +int __old_pthread_attr_setstack (pthread_attr_t *attr, void *stackaddr, + size_t stacksize) +{ + int err; + + if ((((uintptr_t) stackaddr) + & (__alignof__ (struct _pthread_descr_struct) - 1)) != 0) + err = EINVAL; + else + err = __old_pthread_attr_setstacksize (attr, stacksize); + if (err == 0) + { +# ifndef _STACK_GROWS_UP + attr->__stackaddr = (char *) stackaddr + stacksize; +# else + attr->__stackaddr = stackaddr; +# endif + attr->__stackaddr_set = 1; + } + + return err; +} + +compat_symbol (libpthread, __old_pthread_attr_setstack, pthread_attr_setstack, + GLIBC_2_2); + +# endif +#endif + +int __pthread_attr_getstack (const pthread_attr_t *attr, void **stackaddr, + size_t *stacksize) +{ + /* XXX This function has a stupid definition. The standard specifies + no error value but what is if no stack address was set? We simply + return the value we have in the member. */ +#ifndef _STACK_GROWS_UP + *stackaddr = (char *) attr->__stackaddr - attr->__stacksize; +#else + *stackaddr = attr->__stackaddr; +#endif + *stacksize = attr->__stacksize; + return 0; +} +weak_alias (__pthread_attr_getstack, pthread_attr_getstack) + +int pthread_getattr_np (pthread_t thread, pthread_attr_t *attr) +{ + pthread_handle handle = thread_handle (thread); + pthread_descr descr; + int ret = 0; + + if (handle == NULL) + return ENOENT; + + descr = handle->h_descr; + + attr->__detachstate = (descr->p_detached + ? PTHREAD_CREATE_DETACHED + : PTHREAD_CREATE_JOINABLE); + + attr->__schedpolicy = __sched_getscheduler (descr->p_pid); + if (attr->__schedpolicy == -1) + return errno; + + if (__sched_getparam (descr->p_pid, + (struct sched_param *) &attr->__schedparam) != 0) + return errno; + + attr->__inheritsched = descr->p_inheritsched; + attr->__scope = PTHREAD_SCOPE_SYSTEM; + +#ifdef _STACK_GROWS_DOWN +# ifdef USE_TLS + attr->__stacksize = descr->p_stackaddr - (char *)descr->p_guardaddr + - descr->p_guardsize; +# else + attr->__stacksize = (char *)(descr + 1) - (char *)descr->p_guardaddr + - descr->p_guardsize; +# endif +#else +# ifdef USE_TLS + attr->__stacksize = (char *)descr->p_guardaddr - descr->p_stackaddr; +# else + attr->__stacksize = (char *)descr->p_guardaddr - (char *)descr; +# endif +#endif + attr->__guardsize = descr->p_guardsize; + attr->__stackaddr_set = descr->p_userstack; +#ifdef NEED_SEPARATE_REGISTER_STACK + if (descr->p_userstack == 0) + attr->__stacksize *= 2; + /* XXX This is awkward. The guard pages are in the middle of the + two stacks. We must count the guard size in the stack size since + otherwise the range of the stack area cannot be computed. */ + attr->__stacksize += attr->__guardsize; +#endif +#ifdef USE_TLS + attr->__stackaddr = descr->p_stackaddr; +#else +# ifndef _STACK_GROWS_UP + attr->__stackaddr = (char *)(descr + 1); +# else + attr->__stackaddr = (char *)descr; +# endif +#endif + +#ifdef USE_TLS + if (attr->__stackaddr == NULL) +#else + if (descr == &__pthread_initial_thread) +#endif + { + /* Stack size limit. */ + struct rlimit rl; + + /* The safest way to get the top of the stack is to read + /proc/self/maps and locate the line into which + __libc_stack_end falls. */ + FILE *fp = fopen ("/proc/self/maps", "rc"); + if (fp == NULL) + ret = errno; + /* We need the limit of the stack in any case. */ + else if (getrlimit (RLIMIT_STACK, &rl) != 0) + ret = errno; + else + { + /* We need no locking. */ + __fsetlocking (fp, FSETLOCKING_BYCALLER); + + /* Until we found an entry (which should always be the case) + mark the result as a failure. */ + ret = ENOENT; + + char *line = NULL; + size_t linelen = 0; + uintptr_t last_to = 0; + + while (! feof_unlocked (fp)) + { + if (getdelim (&line, &linelen, '\n', fp) <= 0) + break; + + uintptr_t from; + uintptr_t to; + if (sscanf (line, "%" SCNxPTR "-%" SCNxPTR, &from, &to) != 2) + continue; + if (from <= (uintptr_t) __libc_stack_end + && (uintptr_t) __libc_stack_end < to) + { + /* Found the entry. Now we have the info we need. */ + attr->__stacksize = rl.rlim_cur; +#ifdef _STACK_GROWS_UP + /* Don't check to enforce a limit on the __stacksize */ + attr->__stackaddr = (void *) from; +#else + attr->__stackaddr = (void *) to; + + /* The limit might be too high. */ + if ((size_t) attr->__stacksize + > (size_t) attr->__stackaddr - last_to) + attr->__stacksize = (size_t) attr->__stackaddr - last_to; +#endif + + /* We succeed and no need to look further. */ + ret = 0; + break; + } + last_to = to; + } + + fclose (fp); + free (line); + } + } + + return 0; + +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/barrier.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/barrier.c new file mode 100644 index 00000000..37d997cf --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/barrier.c @@ -0,0 +1,128 @@ +/* POSIX barrier implementation for LinuxThreads. + Copyright (C) 2000, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Kaz Kylheku , 2000. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include "pthread.h" +#include "internals.h" +#include "spinlock.h" +#include "queue.h" +#include "restart.h" + +int +pthread_barrier_wait(pthread_barrier_t *barrier) +{ + pthread_descr self = thread_self(); + pthread_descr temp_wake_queue, th; + int result = 0; + + __pthread_lock(&barrier->__ba_lock, self); + + /* If the required number of threads have achieved rendezvous... */ + if (barrier->__ba_present >= barrier->__ba_required - 1) + { + /* ... then this last caller shall be the serial thread */ + result = PTHREAD_BARRIER_SERIAL_THREAD; + /* Copy and clear wait queue and reset barrier. */ + temp_wake_queue = barrier->__ba_waiting; + barrier->__ba_waiting = NULL; + barrier->__ba_present = 0; + } + else + { + result = 0; + barrier->__ba_present++; + enqueue(&barrier->__ba_waiting, self); + } + + __pthread_unlock(&barrier->__ba_lock); + + if (result == 0) + { + /* Non-serial threads have to suspend */ + suspend(self); + /* We don't bother dealing with cancellation because the POSIX + spec for barriers doesn't mention that pthread_barrier_wait + is a cancellation point. */ + } + else + { + /* Serial thread wakes up all others. */ + while ((th = dequeue(&temp_wake_queue)) != NULL) + restart(th); + } + + return result; +} + +int +pthread_barrier_init(pthread_barrier_t *barrier, + const pthread_barrierattr_t *attr, + unsigned int count) +{ + if (count == 0) + return EINVAL; + + __pthread_init_lock(&barrier->__ba_lock); + barrier->__ba_required = count; + barrier->__ba_present = 0; + barrier->__ba_waiting = NULL; + return 0; +} + +int +pthread_barrier_destroy(pthread_barrier_t *barrier) +{ + if (barrier->__ba_waiting != NULL) return EBUSY; + return 0; +} + +int +pthread_barrierattr_init(pthread_barrierattr_t *attr) +{ + attr->__pshared = PTHREAD_PROCESS_PRIVATE; + return 0; +} + +int +pthread_barrierattr_destroy(pthread_barrierattr_t *attr) +{ + return 0; +} + +int +__pthread_barrierattr_getpshared(const pthread_barrierattr_t *attr, + int *pshared) +{ + *pshared = PTHREAD_PROCESS_PRIVATE; + return 0; +} + +int +pthread_barrierattr_setpshared(pthread_barrierattr_t *attr, int pshared) +{ + if (pshared != PTHREAD_PROCESS_PRIVATE && pshared != PTHREAD_PROCESS_SHARED) + return EINVAL; + + /* For now it is not possible to shared a conditional variable. */ + if (pshared != PTHREAD_PROCESS_PRIVATE) + return ENOSYS; + + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/cancel.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/cancel.c new file mode 100644 index 00000000..34356801 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/cancel.c @@ -0,0 +1,238 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +/* Thread cancellation */ + +#include +#include +#include "pthread.h" +#include "internals.h" +#include "spinlock.h" +#include "restart.h" + +#ifdef _STACK_GROWS_DOWN +# define FRAME_LEFT(frame, other) ((char *) frame >= (char *) other) +#elif _STACK_GROWS_UP +# define FRAME_LEFT(frame, other) ((char *) frame <= (char *) other) +#else +# error "Define either _STACK_GROWS_DOWN or _STACK_GROWS_UP" +#endif + + +int __pthread_setcancelstate(int state, int * oldstate) +{ + pthread_descr self = thread_self(); + if (state < PTHREAD_CANCEL_ENABLE || state > PTHREAD_CANCEL_DISABLE) + return EINVAL; + if (oldstate != NULL) *oldstate = THREAD_GETMEM(self, p_cancelstate); + THREAD_SETMEM(self, p_cancelstate, state); + if (THREAD_GETMEM(self, p_canceled) && + THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE && + THREAD_GETMEM(self, p_canceltype) == PTHREAD_CANCEL_ASYNCHRONOUS) + __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); + return 0; +} +strong_alias (__pthread_setcancelstate, pthread_setcancelstate) + +int __pthread_setcanceltype(int type, int * oldtype) +{ + pthread_descr self = thread_self(); + if (type < PTHREAD_CANCEL_DEFERRED || type > PTHREAD_CANCEL_ASYNCHRONOUS) + return EINVAL; + if (oldtype != NULL) *oldtype = THREAD_GETMEM(self, p_canceltype); + THREAD_SETMEM(self, p_canceltype, type); + if (THREAD_GETMEM(self, p_canceled) && + THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE && + THREAD_GETMEM(self, p_canceltype) == PTHREAD_CANCEL_ASYNCHRONOUS) + __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); + return 0; +} +strong_alias (__pthread_setcanceltype, pthread_setcanceltype) + + +/* The next two functions are similar to pthread_setcanceltype() but + more specialized for the use in the cancelable functions like write(). + They do not need to check parameters etc. */ +int +attribute_hidden +__pthread_enable_asynccancel (void) +{ + pthread_descr self = thread_self(); + int oldtype = THREAD_GETMEM(self, p_canceltype); + THREAD_SETMEM(self, p_canceltype, PTHREAD_CANCEL_ASYNCHRONOUS); + if (__builtin_expect (THREAD_GETMEM(self, p_canceled), 0) && + THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) + __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); + return oldtype; +} + +void +internal_function attribute_hidden +__pthread_disable_asynccancel (int oldtype) +{ + pthread_descr self = thread_self(); + THREAD_SETMEM(self, p_canceltype, oldtype); +} + + +int pthread_cancel(pthread_t thread) +{ + pthread_handle handle = thread_handle(thread); + int pid; + int dorestart = 0; + pthread_descr th; + pthread_extricate_if *pextricate; + int already_canceled; + + __pthread_lock(&handle->h_lock, NULL); + if (invalid_handle(handle, thread)) { + __pthread_unlock(&handle->h_lock); + return ESRCH; + } + + th = handle->h_descr; + + already_canceled = th->p_canceled; + th->p_canceled = 1; + + if (th->p_cancelstate == PTHREAD_CANCEL_DISABLE || already_canceled) { + __pthread_unlock(&handle->h_lock); + return 0; + } + + pextricate = th->p_extricate; + pid = th->p_pid; + + /* If the thread has registered an extrication interface, then + invoke the interface. If it returns 1, then we succeeded in + dequeuing the thread from whatever waiting object it was enqueued + with. In that case, it is our responsibility to wake it up. + And also to set the p_woken_by_cancel flag so the woken thread + can tell that it was woken by cancellation. */ + + if (pextricate != NULL) { + dorestart = pextricate->pu_extricate_func(pextricate->pu_object, th); + th->p_woken_by_cancel = dorestart; + } + + __pthread_unlock(&handle->h_lock); + + /* If the thread has suspended or is about to, then we unblock it by + issuing a restart, instead of a cancel signal. Otherwise we send + the cancel signal to unblock the thread from a cancellation point, + or to initiate asynchronous cancellation. The restart is needed so + we have proper accounting of restarts; suspend decrements the thread's + resume count, and restart() increments it. This also means that suspend's + handling of the cancel signal is obsolete. */ + + if (dorestart) + restart(th); + else + kill(pid, __pthread_sig_cancel); + + return 0; +} + +void pthread_testcancel(void) +{ + pthread_descr self = thread_self(); + if (THREAD_GETMEM(self, p_canceled) + && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) + __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); +} + +void _pthread_cleanup_push(struct _pthread_cleanup_buffer * buffer, + void (*routine)(void *), void * arg) +{ + pthread_descr self = thread_self(); + buffer->__routine = routine; + buffer->__arg = arg; + buffer->__prev = THREAD_GETMEM(self, p_cleanup); + if (buffer->__prev != NULL && FRAME_LEFT (buffer, buffer->__prev)) + buffer->__prev = NULL; + THREAD_SETMEM(self, p_cleanup, buffer); +} + +void _pthread_cleanup_pop(struct _pthread_cleanup_buffer * buffer, + int execute) +{ + pthread_descr self = thread_self(); + if (execute) buffer->__routine(buffer->__arg); + THREAD_SETMEM(self, p_cleanup, buffer->__prev); +} + +void _pthread_cleanup_push_defer(struct _pthread_cleanup_buffer * buffer, + void (*routine)(void *), void * arg) +{ + pthread_descr self = thread_self(); + buffer->__routine = routine; + buffer->__arg = arg; + buffer->__canceltype = THREAD_GETMEM(self, p_canceltype); + buffer->__prev = THREAD_GETMEM(self, p_cleanup); + if (buffer->__prev != NULL && FRAME_LEFT (buffer, buffer->__prev)) + buffer->__prev = NULL; + THREAD_SETMEM(self, p_canceltype, PTHREAD_CANCEL_DEFERRED); + THREAD_SETMEM(self, p_cleanup, buffer); +} + +void _pthread_cleanup_pop_restore(struct _pthread_cleanup_buffer * buffer, + int execute) +{ + pthread_descr self = thread_self(); + if (execute) buffer->__routine(buffer->__arg); + THREAD_SETMEM(self, p_cleanup, buffer->__prev); + THREAD_SETMEM(self, p_canceltype, buffer->__canceltype); + if (THREAD_GETMEM(self, p_canceled) && + THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE && + THREAD_GETMEM(self, p_canceltype) == PTHREAD_CANCEL_ASYNCHRONOUS) + __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); +} + +extern void __rpc_thread_destroy(void); +void __pthread_perform_cleanup(char *currentframe) +{ + pthread_descr self = thread_self(); + struct _pthread_cleanup_buffer *c = THREAD_GETMEM(self, p_cleanup); + struct _pthread_cleanup_buffer *last; + + if (c != NULL) + while (FRAME_LEFT (currentframe, c)) + { + last = c; + c = c->__prev; + + if (c == NULL || FRAME_LEFT (last, c)) + { + c = NULL; + break; + } + } + + while (c != NULL) + { + c->__routine(c->__arg); + + last = c; + c = c->__prev; + + if (FRAME_LEFT (last, c)) + break; + } + +#ifdef __UCLIBC_HAS_RPC__ + /* And the TSD which needs special help. */ + if (THREAD_GETMEM(self, p_libc_specific[_LIBC_TSD_KEY_RPC_VARS]) != NULL) + __rpc_thread_destroy (); +#endif +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/condvar.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/condvar.c new file mode 100644 index 00000000..d7b2e988 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/condvar.c @@ -0,0 +1,304 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* and Pavel Krauz (krauz@fsid.cvut.cz). */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +/* Condition variables */ + +#include +#include +#include +#include +#include "pthread.h" +#include "internals.h" +#include "spinlock.h" +#include "queue.h" +#include "restart.h" + +int __pthread_cond_init(pthread_cond_t *cond, + const pthread_condattr_t *cond_attr) +{ + __pthread_init_lock(&cond->__c_lock); + cond->__c_waiting = NULL; + return 0; +} +strong_alias (__pthread_cond_init, pthread_cond_init) + +int __pthread_cond_destroy(pthread_cond_t *cond) +{ + if (cond->__c_waiting != NULL) return EBUSY; + return 0; +} +strong_alias (__pthread_cond_destroy, pthread_cond_destroy) + +/* Function called by pthread_cancel to remove the thread from + waiting on a condition variable queue. */ + +static int cond_extricate_func(void *obj, pthread_descr th) +{ + __volatile__ pthread_descr self = thread_self(); + pthread_cond_t *cond = obj; + int did_remove = 0; + + __pthread_lock(&cond->__c_lock, self); + did_remove = remove_from_queue(&cond->__c_waiting, th); + __pthread_unlock(&cond->__c_lock); + + return did_remove; +} + +int __pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) +{ + __volatile__ pthread_descr self = thread_self(); + pthread_extricate_if extr; + int already_canceled = 0; + int spurious_wakeup_count; + + /* Check whether the mutex is locked and owned by this thread. */ + if (mutex->__m_kind != PTHREAD_MUTEX_TIMED_NP + && mutex->__m_kind != PTHREAD_MUTEX_ADAPTIVE_NP + && mutex->__m_owner != self) + return EINVAL; + + /* Set up extrication interface */ + extr.pu_object = cond; + extr.pu_extricate_func = cond_extricate_func; + + /* Register extrication interface */ + THREAD_SETMEM(self, p_condvar_avail, 0); + __pthread_set_own_extricate_if(self, &extr); + + /* Atomically enqueue thread for waiting, but only if it is not + canceled. If the thread is canceled, then it will fall through the + suspend call below, and then call pthread_exit without + having to worry about whether it is still on the condition variable queue. + This depends on pthread_cancel setting p_canceled before calling the + extricate function. */ + + __pthread_lock(&cond->__c_lock, self); + if (!(THREAD_GETMEM(self, p_canceled) + && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE)) + enqueue(&cond->__c_waiting, self); + else + already_canceled = 1; + __pthread_unlock(&cond->__c_lock); + + if (already_canceled) { + __pthread_set_own_extricate_if(self, 0); + __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); + } + + pthread_mutex_unlock(mutex); + + spurious_wakeup_count = 0; + while (1) + { + suspend(self); + if (THREAD_GETMEM(self, p_condvar_avail) == 0 + && (THREAD_GETMEM(self, p_woken_by_cancel) == 0 + || THREAD_GETMEM(self, p_cancelstate) != PTHREAD_CANCEL_ENABLE)) + { + /* Count resumes that don't belong to us. */ + spurious_wakeup_count++; + continue; + } + break; + } + + __pthread_set_own_extricate_if(self, 0); + + /* Check for cancellation again, to provide correct cancellation + point behavior */ + + if (THREAD_GETMEM(self, p_woken_by_cancel) + && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) { + THREAD_SETMEM(self, p_woken_by_cancel, 0); + pthread_mutex_lock(mutex); + __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); + } + + /* Put back any resumes we caught that don't belong to us. */ + while (spurious_wakeup_count--) + restart(self); + + pthread_mutex_lock(mutex); + return 0; +} +strong_alias (__pthread_cond_wait, pthread_cond_wait) + +static int +pthread_cond_timedwait_relative(pthread_cond_t *cond, + pthread_mutex_t *mutex, + const struct timespec * abstime) +{ + __volatile__ pthread_descr self = thread_self(); + int already_canceled = 0; + pthread_extricate_if extr; + int spurious_wakeup_count; + + /* Check whether the mutex is locked and owned by this thread. */ + if (mutex->__m_kind != PTHREAD_MUTEX_TIMED_NP + && mutex->__m_kind != PTHREAD_MUTEX_ADAPTIVE_NP + && mutex->__m_owner != self) + return EINVAL; + + /* Set up extrication interface */ + extr.pu_object = cond; + extr.pu_extricate_func = cond_extricate_func; + + /* Register extrication interface */ + THREAD_SETMEM(self, p_condvar_avail, 0); + __pthread_set_own_extricate_if(self, &extr); + + /* Enqueue to wait on the condition and check for cancellation. */ + __pthread_lock(&cond->__c_lock, self); + if (!(THREAD_GETMEM(self, p_canceled) + && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE)) + enqueue(&cond->__c_waiting, self); + else + already_canceled = 1; + __pthread_unlock(&cond->__c_lock); + + if (already_canceled) { + __pthread_set_own_extricate_if(self, 0); + __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); + } + + pthread_mutex_unlock(mutex); + + spurious_wakeup_count = 0; + while (1) + { + if (!timedsuspend(self, abstime)) { + int was_on_queue; + + /* __pthread_lock will queue back any spurious restarts that + may happen to it. */ + + __pthread_lock(&cond->__c_lock, self); + was_on_queue = remove_from_queue(&cond->__c_waiting, self); + __pthread_unlock(&cond->__c_lock); + + if (was_on_queue) { + __pthread_set_own_extricate_if(self, 0); + pthread_mutex_lock(mutex); + return ETIMEDOUT; + } + + /* Eat the outstanding restart() from the signaller */ + suspend(self); + } + + if (THREAD_GETMEM(self, p_condvar_avail) == 0 + && (THREAD_GETMEM(self, p_woken_by_cancel) == 0 + || THREAD_GETMEM(self, p_cancelstate) != PTHREAD_CANCEL_ENABLE)) + { + /* Count resumes that don't belong to us. */ + spurious_wakeup_count++; + continue; + } + break; + } + + __pthread_set_own_extricate_if(self, 0); + + /* The remaining logic is the same as in other cancellable waits, + such as pthread_join sem_wait or pthread_cond wait. */ + + if (THREAD_GETMEM(self, p_woken_by_cancel) + && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) { + THREAD_SETMEM(self, p_woken_by_cancel, 0); + pthread_mutex_lock(mutex); + __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); + } + + /* Put back any resumes we caught that don't belong to us. */ + while (spurious_wakeup_count--) + restart(self); + + pthread_mutex_lock(mutex); + return 0; +} + +int __pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, + const struct timespec * abstime) +{ + /* Indirect call through pointer! */ + return pthread_cond_timedwait_relative(cond, mutex, abstime); +} +strong_alias (__pthread_cond_timedwait, pthread_cond_timedwait) + +int __pthread_cond_signal(pthread_cond_t *cond) +{ + pthread_descr th; + + __pthread_lock(&cond->__c_lock, NULL); + th = dequeue(&cond->__c_waiting); + __pthread_unlock(&cond->__c_lock); + if (th != NULL) { + th->p_condvar_avail = 1; + WRITE_MEMORY_BARRIER(); + restart(th); + } + return 0; +} +strong_alias (__pthread_cond_signal, pthread_cond_signal) + +int __pthread_cond_broadcast(pthread_cond_t *cond) +{ + pthread_descr tosignal, th; + + __pthread_lock(&cond->__c_lock, NULL); + /* Copy the current state of the waiting queue and empty it */ + tosignal = cond->__c_waiting; + cond->__c_waiting = NULL; + __pthread_unlock(&cond->__c_lock); + /* Now signal each process in the queue */ + while ((th = dequeue(&tosignal)) != NULL) { + th->p_condvar_avail = 1; + WRITE_MEMORY_BARRIER(); + restart(th); + } + return 0; +} +strong_alias (__pthread_cond_broadcast, pthread_cond_broadcast) + +int __pthread_condattr_init(pthread_condattr_t *attr) +{ + return 0; +} +strong_alias (__pthread_condattr_init, pthread_condattr_init) + +int __pthread_condattr_destroy(pthread_condattr_t *attr) +{ + return 0; +} +strong_alias (__pthread_condattr_destroy, pthread_condattr_destroy) + +int pthread_condattr_getpshared (const pthread_condattr_t *attr, int *pshared) +{ + *pshared = PTHREAD_PROCESS_PRIVATE; + return 0; +} + +int pthread_condattr_setpshared (pthread_condattr_t *attr, int pshared) +{ + if (pshared != PTHREAD_PROCESS_PRIVATE && pshared != PTHREAD_PROCESS_SHARED) + return EINVAL; + + /* For now it is not possible to shared a conditional variable. */ + if (pshared != PTHREAD_PROCESS_PRIVATE) + return ENOSYS; + + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/descr.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/descr.h new file mode 100644 index 00000000..47a9acd9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/descr.h @@ -0,0 +1,268 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +#ifndef _DESCR_H +#define _DESCR_H 1 + +#define __need_res_state +#include +#include +#include +#include +#include +#include +#include +#ifdef USE_TLS +#include +#endif +#include "uClibc-glue.h" + +/* Fast thread-specific data internal to libc. */ +enum __libc_tsd_key_t { _LIBC_TSD_KEY_MALLOC = 0, + _LIBC_TSD_KEY_DL_ERROR, + _LIBC_TSD_KEY_RPC_VARS, + _LIBC_TSD_KEY_LOCALE, + _LIBC_TSD_KEY_CTYPE_B, + _LIBC_TSD_KEY_CTYPE_TOLOWER, + _LIBC_TSD_KEY_CTYPE_TOUPPER, + _LIBC_TSD_KEY_N }; + +/* The type of thread descriptors */ +typedef struct _pthread_descr_struct *pthread_descr; + + +/* Some more includes. */ +#include +#include + + +/* Arguments passed to thread creation routine */ +struct pthread_start_args { + void *(*start_routine)(void *); /* function to run */ + void *arg; /* its argument */ + sigset_t mask; /* initial signal mask for thread */ + int schedpolicy; /* initial scheduling policy (if any) */ + struct sched_param schedparam; /* initial scheduling parameters (if any) */ +}; + + +/* Callback interface for removing the thread from waiting on an + object if it is cancelled while waiting or about to wait. + This hold a pointer to the object, and a pointer to a function + which ``extricates'' the thread from its enqueued state. + The function takes two arguments: pointer to the wait object, + and a pointer to the thread. It returns 1 if an extrication + actually occured, and hence the thread must also be signalled. + It returns 0 if the thread had already been extricated. */ +typedef struct _pthread_extricate_struct { + void *pu_object; + int (*pu_extricate_func)(void *, pthread_descr); +} pthread_extricate_if; + + +/* Atomic counter made possible by compare_and_swap */ +struct pthread_atomic { + long p_count; + int p_spinlock; +}; + + +/* Context info for read write locks. The pthread_rwlock_info structure + is information about a lock that has been read-locked by the thread + in whose list this structure appears. The pthread_rwlock_context + is embedded in the thread context and contains a pointer to the + head of the list of lock info structures, as well as a count of + read locks that are untracked, because no info structure could be + allocated for them. */ +struct _pthread_rwlock_t; +typedef struct _pthread_rwlock_info { + struct _pthread_rwlock_info *pr_next; + struct _pthread_rwlock_t *pr_lock; + int pr_lock_count; +} pthread_readlock_info; + + +/* We keep thread specific data in a special data structure, a two-level + array. The top-level array contains pointers to dynamically allocated + arrays of a certain number of data pointers. So we can implement a + sparse array. Each dynamic second-level array has + PTHREAD_KEY_2NDLEVEL_SIZE + entries. This value shouldn't be too large. */ +#define PTHREAD_KEY_2NDLEVEL_SIZE 32 + +/* We need to address PTHREAD_KEYS_MAX key with PTHREAD_KEY_2NDLEVEL_SIZE + keys in each subarray. */ +#define PTHREAD_KEY_1STLEVEL_SIZE \ + ((PTHREAD_KEYS_MAX + PTHREAD_KEY_2NDLEVEL_SIZE - 1) \ + / PTHREAD_KEY_2NDLEVEL_SIZE) + + +union dtv; + +struct _pthread_descr_struct +{ +#if !defined USE_TLS || !TLS_DTV_AT_TP || INCLUDE_TLS_PADDING + /* This overlaps tcbhead_t (see tls.h), as used for TLS without threads. */ + union + { + struct + { + void *tcb; /* Pointer to the TCB. This is not always + the address of this thread descriptor. */ + union dtv *dtvp; + pthread_descr self; /* Pointer to this structure */ + int multiple_threads; + uintptr_t sysinfo; + } data; + void *__padding[16]; + } p_header; +# define p_multiple_threads p_header.data.multiple_threads +#elif defined TLS_MULTIPLE_THREADS_IN_TCB && TLS_MULTIPLE_THREADS_IN_TCB + int p_multiple_threads; +#endif + + pthread_descr p_nextlive, p_prevlive; + /* Double chaining of active threads */ + pthread_descr p_nextwaiting; /* Next element in the queue holding the thr */ + pthread_descr p_nextlock; /* can be on a queue and waiting on a lock */ + pthread_t p_tid; /* Thread identifier */ + int p_pid; /* PID of Unix process */ + int p_priority; /* Thread priority (== 0 if not realtime) */ + struct _pthread_fastlock * p_lock; /* Spinlock for synchronized accesses */ + int p_signal; /* last signal received */ + sigjmp_buf * p_signal_jmp; /* where to siglongjmp on a signal or NULL */ + sigjmp_buf * p_cancel_jmp; /* where to siglongjmp on a cancel or NULL */ + char p_terminated; /* true if terminated e.g. by pthread_exit */ + char p_detached; /* true if detached */ + char p_exited; /* true if the assoc. process terminated */ + void * p_retval; /* placeholder for return value */ + int p_retcode; /* placeholder for return code */ + pthread_descr p_joining; /* thread joining on that thread or NULL */ + struct _pthread_cleanup_buffer * p_cleanup; /* cleanup functions */ + char p_cancelstate; /* cancellation state */ + char p_canceltype; /* cancellation type (deferred/async) */ + char p_canceled; /* cancellation request pending */ + char * p_in_sighandler; /* stack address of sighandler, or NULL */ + char p_sigwaiting; /* true if a sigwait() is in progress */ + struct pthread_start_args p_start_args; /* arguments for thread creation */ + void ** p_specific[PTHREAD_KEY_1STLEVEL_SIZE]; /* thread-specific data */ +#if !(USE_TLS && HAVE___THREAD) + void * p_libc_specific[_LIBC_TSD_KEY_N]; /* thread-specific data for libc */ + int * p_errnop; /* pointer to used errno variable */ + int p_errno; /* error returned by last system call */ + int * p_h_errnop; /* pointer to used h_errno variable */ + int p_h_errno; /* error returned by last netdb function */ + struct __res_state *p_resp; /* Pointer to resolver state */ +#endif + struct __res_state p_res; /* per-thread resolver state */ + int p_userstack; /* nonzero if the user provided the stack */ + void *p_guardaddr; /* address of guard area or NULL */ + size_t p_guardsize; /* size of guard area */ + int p_nr; /* Index of descriptor in __pthread_handles */ + int p_report_events; /* Nonzero if events must be reported. */ + td_eventbuf_t p_eventbuf; /* Data for event. */ + struct pthread_atomic p_resume_count; /* number of times restart() was + called on thread */ + char p_woken_by_cancel; /* cancellation performed wakeup */ + char p_condvar_avail; /* flag if conditional variable became avail */ + char p_sem_avail; /* flag if semaphore became available */ + pthread_extricate_if *p_extricate; /* See above */ + pthread_readlock_info *p_readlock_list; /* List of readlock info structs */ + pthread_readlock_info *p_readlock_free; /* Free list of structs */ + int p_untracked_readlock_count; /* Readlocks not tracked by list */ + int p_inheritsched; /* copied from the thread attribute */ +#if HP_TIMING_AVAIL + hp_timing_t p_cpuclock_offset; /* Initial CPU clock for thread. */ +#endif +#ifdef USE_TLS + char *p_stackaddr; /* Stack address. */ +#endif + size_t p_alloca_cutoff; /* Maximum size which should be allocated + using alloca() instead of malloc(). */ + /* New elements must be added at the end. */ +} __attribute__ ((aligned(32))); /* We need to align the structure so that + doubles are aligned properly. This is 8 + bytes on MIPS and 16 bytes on MIPS64. + 32 bytes might give better cache + utilization. */ + + + +/* Limit between the stack of the initial thread (above) and the + stacks of other threads (below). Aligned on a STACK_SIZE boundary. + Initially 0, meaning that the current thread is (by definition) + the initial thread. */ + +extern char *__pthread_initial_thread_bos; + +/* Descriptor of the initial thread */ + +extern struct _pthread_descr_struct __pthread_initial_thread; + +/* Limits of the thread manager stack. */ + +extern char *__pthread_manager_thread_bos; +extern char *__pthread_manager_thread_tos; + +/* Descriptor of the manager thread */ + +extern struct _pthread_descr_struct __pthread_manager_thread; +extern pthread_descr __pthread_manager_threadp attribute_hidden; + +/* Indicate whether at least one thread has a user-defined stack (if 1), + or all threads have stacks supplied by LinuxThreads (if 0). */ + +extern int __pthread_nonstandard_stacks; + +/* The max size of the thread stack segments. If the default + THREAD_SELF implementation is used, this must be a power of two and + a multiple of PAGE_SIZE. */ +#ifndef STACK_SIZE +#define STACK_SIZE (2 * 1024 * 1024) +#endif + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#ifndef CURRENT_STACK_FRAME +#define CURRENT_STACK_FRAME ({ char __csf; &__csf; }) +#endif + +/* Recover thread descriptor for the current thread */ + +extern pthread_descr __pthread_find_self (void) __attribute__ ((pure)); + +static __inline__ pthread_descr thread_self (void) __attribute__ ((pure)); +static __inline__ pthread_descr thread_self (void) +{ +#ifdef THREAD_SELF + return THREAD_SELF; +#else + char *sp = CURRENT_STACK_FRAME; + if (sp >= __pthread_initial_thread_bos) + return &__pthread_initial_thread; + else if (sp >= __pthread_manager_thread_bos + && sp < __pthread_manager_thread_tos) + return &__pthread_manager_thread; + else if (__pthread_nonstandard_stacks) + return __pthread_find_self(); + else +#ifdef _STACK_GROWS_DOWN + return (pthread_descr)(((unsigned long)sp | (STACK_SIZE-1))+1) - 1; +#else + return (pthread_descr)((unsigned long)sp &~ (STACK_SIZE-1)); +#endif +#endif +} + +#endif /* descr.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/errno.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/errno.c new file mode 100644 index 00000000..03c23f86 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/errno.c @@ -0,0 +1,48 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +/* Define the location of errno for the remainder of the C library */ + +#include +#include +#include +#include "pthread.h" +#include "internals.h" + +#if !USE_TLS || !HAVE___THREAD +/* The definition in libc is sufficient if we use TLS. */ +int * +__errno_location (void) +{ + pthread_descr self = thread_self(); + return THREAD_GETMEM (self, p_errnop); +} + +int * +__h_errno_location (void) +{ + pthread_descr self = thread_self(); + return THREAD_GETMEM (self, p_h_errnop); +} + +#if 0 +/* Return thread specific resolver state. */ +struct __res_state * +__res_state (void) +{ + pthread_descr self = thread_self(); + return THREAD_GETMEM (self, p_resp); +} +#endif +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/events.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/events.c new file mode 100644 index 00000000..b4ca3846 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/events.c @@ -0,0 +1,37 @@ +/* Event functions used while debugging. + Copyright (C) 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* The functions contained here do nothing, they just return. */ + +#include "internals.h" + +void +__linuxthreads_create_event (void) +{ +} + +void +__linuxthreads_death_event (void) +{ +} + +void +__linuxthreads_reap_event (void) +{ +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/forward.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/forward.c new file mode 100644 index 00000000..9d25d9a0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/forward.c @@ -0,0 +1,145 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +/* psm: keep this before internals.h */ + +#include "internals.h" + +/* Pointers to the libc functions. */ +struct pthread_functions __libc_pthread_functions attribute_hidden; + + +# define FORWARD2(name, rettype, decl, params, defaction) \ +rettype \ +name decl \ +{ \ + if (__libc_pthread_functions.ptr_##name == NULL) \ + defaction; \ + \ + return __libc_pthread_functions.ptr_##name params; \ +} + +# define FORWARD(name, decl, params, defretval) \ + FORWARD2 (name, int, decl, params, return defretval) + +FORWARD (pthread_attr_destroy, (pthread_attr_t *attr), (attr), 0) + +FORWARD (pthread_attr_init, (pthread_attr_t *attr), (attr), 0) + +FORWARD (pthread_attr_getdetachstate, + (const pthread_attr_t *attr, int *detachstate), (attr, detachstate), + 0) +FORWARD (pthread_attr_setdetachstate, (pthread_attr_t *attr, int detachstate), + (attr, detachstate), 0) + +FORWARD (pthread_attr_getinheritsched, + (const pthread_attr_t *attr, int *inherit), (attr, inherit), 0) +FORWARD (pthread_attr_setinheritsched, (pthread_attr_t *attr, int inherit), + (attr, inherit), 0) + +FORWARD (pthread_attr_getschedparam, + (const pthread_attr_t *attr, struct sched_param *param), + (attr, param), 0) +FORWARD (pthread_attr_setschedparam, + (pthread_attr_t *attr, const struct sched_param *param), + (attr, param), 0) + +FORWARD (pthread_attr_getschedpolicy, + (const pthread_attr_t *attr, int *policy), (attr, policy), 0) +FORWARD (pthread_attr_setschedpolicy, (pthread_attr_t *attr, int policy), + (attr, policy), 0) + +FORWARD (pthread_attr_getscope, + (const pthread_attr_t *attr, int *scope), (attr, scope), 0) +FORWARD (pthread_attr_setscope, (pthread_attr_t *attr, int scope), + (attr, scope), 0) + + +FORWARD (pthread_condattr_destroy, (pthread_condattr_t *attr), (attr), 0) +FORWARD (pthread_condattr_init, (pthread_condattr_t *attr), (attr), 0) + + +FORWARD (pthread_cond_broadcast, (pthread_cond_t *cond), (cond), 0) + +FORWARD (pthread_cond_destroy, (pthread_cond_t *cond), (cond), 0) + +FORWARD (pthread_cond_init, + (pthread_cond_t *cond, const pthread_condattr_t *cond_attr), + (cond, cond_attr), 0) + +FORWARD (pthread_cond_signal, (pthread_cond_t *cond), (cond), 0) + +FORWARD (pthread_cond_wait, (pthread_cond_t *cond, pthread_mutex_t *mutex), + (cond, mutex), 0) + +FORWARD (pthread_cond_timedwait, + (pthread_cond_t *cond, pthread_mutex_t *mutex, + const struct timespec *abstime), (cond, mutex, abstime), 0) + + +FORWARD (pthread_equal, (pthread_t thread1, pthread_t thread2), + (thread1, thread2), 1) + + +/* Use an alias to avoid warning, as pthread_exit is declared noreturn. */ +FORWARD2 (__pthread_exit, void, (void *retval), (retval), exit (EXIT_SUCCESS)) +strong_alias (__pthread_exit, pthread_exit) + + +FORWARD (pthread_getschedparam, + (pthread_t target_thread, int *policy, struct sched_param *param), + (target_thread, policy, param), 0) +FORWARD (pthread_setschedparam, + (pthread_t target_thread, int policy, + const struct sched_param *param), (target_thread, policy, param), 0) + + +FORWARD (pthread_mutex_destroy, (pthread_mutex_t *mutex), (mutex), 0) + +FORWARD (pthread_mutex_init, + (pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr), + (mutex, mutexattr), 0) +strong_alias(pthread_mutex_init, __pthread_mutex_init) + +FORWARD (pthread_mutex_lock, (pthread_mutex_t *mutex), (mutex), 0) +strong_alias(pthread_mutex_lock, __pthread_mutex_lock) + +FORWARD (pthread_mutex_trylock, (pthread_mutex_t *mutex), (mutex), 0) +strong_alias(pthread_mutex_trylock, __pthread_mutex_trylock) + +FORWARD (pthread_mutex_unlock, (pthread_mutex_t *mutex), (mutex), 0) +strong_alias(pthread_mutex_unlock, __pthread_mutex_unlock) + +FORWARD2 (pthread_self, pthread_t, (void), (), return 0) + + +FORWARD (pthread_setcancelstate, (int state, int *oldstate), (state, oldstate), + 0) + +FORWARD (pthread_setcanceltype, (int type, int *oldtype), (type, oldtype), 0) + +FORWARD2 (_pthread_cleanup_push, void, (struct _pthread_cleanup_buffer * buffer, void (*routine)(void *), void * arg), (buffer, routine, arg), return) +FORWARD2 (_pthread_cleanup_push_defer, void, (struct _pthread_cleanup_buffer * buffer, void (*routine)(void *), void * arg), (buffer, routine, arg), return) + +FORWARD2 (_pthread_cleanup_pop, void, (struct _pthread_cleanup_buffer * buffer, int execute), (buffer, execute), return) +FORWARD2 (_pthread_cleanup_pop_restore, void, (struct _pthread_cleanup_buffer * buffer, int execute), (buffer, execute), return) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/internals.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/internals.h new file mode 100644 index 00000000..eb0a5198 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/internals.h @@ -0,0 +1,551 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +#ifndef _INTERNALS_H +#define _INTERNALS_H 1 + +#include "uClibc-glue.h" + +/* Internal data structures */ + +/* Includes */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef USE_TLS +#include +#endif +#include "descr.h" + +#include "semaphore.h" +#include + +#ifndef THREAD_GETMEM +# define THREAD_GETMEM(descr, member) descr->member +#endif +#ifndef THREAD_GETMEM_NC +# define THREAD_GETMEM_NC(descr, member) descr->member +#endif +#ifndef THREAD_SETMEM +# define THREAD_SETMEM(descr, member, value) descr->member = (value) +#endif +#ifndef THREAD_SETMEM_NC +# define THREAD_SETMEM_NC(descr, member, value) descr->member = (value) +#endif + +#if !defined NOT_IN_libc && defined FLOATING_STACKS +# define LIBC_THREAD_GETMEM(descr, member) THREAD_GETMEM (descr, member) +# define LIBC_THREAD_SETMEM(descr, member, value) \ + THREAD_SETMEM (descr, member, value) +#else +# define LIBC_THREAD_GETMEM(descr, member) descr->member +# define LIBC_THREAD_SETMEM(descr, member, value) descr->member = (value) +#endif + +typedef void (*destr_function)(void *); + +struct pthread_key_struct { + int in_use; /* already allocated? */ + destr_function destr; /* destruction routine */ +}; + + +#define PTHREAD_START_ARGS_INITIALIZER(fct) \ + { (void *(*) (void *)) fct, NULL, {{0, }}, 0, { 0 } } + + +/* The type of thread handles. */ + +typedef struct pthread_handle_struct * pthread_handle; + +struct pthread_handle_struct { + struct _pthread_fastlock h_lock; /* Fast lock for sychronized access */ + pthread_descr h_descr; /* Thread descriptor or NULL if invalid */ + char * h_bottom; /* Lowest address in the stack thread */ +}; + +/* The type of messages sent to the thread manager thread */ + +struct pthread_request { + pthread_descr req_thread; /* Thread doing the request */ + enum { /* Request kind */ + REQ_CREATE, REQ_FREE, REQ_PROCESS_EXIT, REQ_MAIN_THREAD_EXIT, + REQ_POST, REQ_DEBUG, REQ_KICK, REQ_FOR_EACH_THREAD + } req_kind; + union { /* Arguments for request */ + struct { /* For REQ_CREATE: */ + const pthread_attr_t * attr; /* thread attributes */ + void * (*fn)(void *); /* start function */ + void * arg; /* argument to start function */ + sigset_t mask; /* signal mask */ + } create; + struct { /* For REQ_FREE: */ + pthread_t thread_id; /* identifier of thread to free */ + } free; + struct { /* For REQ_PROCESS_EXIT: */ + int code; /* exit status */ + } exit; + void * post; /* For REQ_POST: the semaphore */ + struct { /* For REQ_FOR_EACH_THREAD: callback */ + void (*fn)(void *, pthread_descr); + void *arg; + } for_each; + } req_args; +}; + + + +typedef void (*arch_sighandler_t) (int, SIGCONTEXT); +union sighandler +{ + arch_sighandler_t old; + void (*rt) (int, struct siginfo *, struct ucontext *); +}; +extern union sighandler __sighandler[NSIG]; + + +/* Signals used for suspend/restart and for cancellation notification. */ + +extern int __pthread_sig_restart; +extern int __pthread_sig_cancel; + +/* Signal used for interfacing with gdb */ + +extern int __pthread_sig_debug; + +/* Global array of thread handles, used for validating a thread id + and retrieving the corresponding thread descriptor. Also used for + mapping the available stack segments. */ + +extern struct pthread_handle_struct __pthread_handles[PTHREAD_THREADS_MAX]; + +/* Descriptor of the main thread */ + +extern pthread_descr __pthread_main_thread; + +/* File descriptor for sending requests to the thread manager. + Initially -1, meaning that __pthread_initialize_manager must be called. */ + +extern int __pthread_manager_request; + +/* Other end of the pipe for sending requests to the thread manager. */ + +extern int __pthread_manager_reader; + +#ifdef FLOATING_STACKS +/* Maximum stack size. */ +extern size_t __pthread_max_stacksize; +#endif + +/* Pending request for a process-wide exit */ + +extern int __pthread_exit_requested, __pthread_exit_code; + +/* Set to 1 by gdb if we're debugging */ + +extern __volatile__ int __pthread_threads_debug; + +/* Globally enabled events. */ +extern __volatile__ td_thr_events_t __pthread_threads_events; + +/* Pointer to descriptor of thread with last event. */ +extern __volatile__ pthread_descr __pthread_last_event; + +/* Flag which tells whether we are executing on SMP kernel. */ +extern int __pthread_smp_kernel; + +/* Return the handle corresponding to a thread id */ + +static __inline__ pthread_handle thread_handle(pthread_t id) +{ + return &__pthread_handles[id % PTHREAD_THREADS_MAX]; +} + +/* Validate a thread handle. Must have acquired h->h_spinlock before. */ + +static __inline__ int invalid_handle(pthread_handle h, pthread_t id) +{ + return h->h_descr == NULL || h->h_descr->p_tid != id || h->h_descr->p_terminated; +} + +static __inline__ int nonexisting_handle(pthread_handle h, pthread_t id) +{ + return h->h_descr == NULL || h->h_descr->p_tid != id; +} + +/* Fill in defaults left unspecified by pt-machine.h. */ + +/* We round up a value with page size. */ +#ifndef page_roundup +#define page_roundup(v,p) ((((size_t) (v)) + (p) - 1) & ~((p) - 1)) +#endif + +/* The page size we can get from the system. This should likely not be + changed by the machine file but, you never know. */ +#ifndef PAGE_SIZE +#define PAGE_SIZE (sysconf (_SC_PAGE_SIZE)) +#endif + +/* The initial size of the thread stack. Must be a multiple of PAGE_SIZE. */ +#ifndef INITIAL_STACK_SIZE +#define INITIAL_STACK_SIZE (4 * PAGE_SIZE) +#endif + +/* Size of the thread manager stack. The "- 32" avoids wasting space + with some malloc() implementations. */ +#ifndef THREAD_MANAGER_STACK_SIZE +#define THREAD_MANAGER_STACK_SIZE (2 * PAGE_SIZE - 32) +#endif + +/* The base of the "array" of thread stacks. The array will grow down from + here. Defaults to the calculated bottom of the initial application + stack. */ +#ifndef THREAD_STACK_START_ADDRESS +#define THREAD_STACK_START_ADDRESS __pthread_initial_thread_bos +#endif + +/* If MEMORY_BARRIER isn't defined in pt-machine.h, assume the + architecture doesn't need a memory barrier instruction (e.g. Intel + x86). Still we need the compiler to respect the barrier and emit + all outstanding operations which modify memory. Some architectures + distinguish between full, read and write barriers. */ + +#ifndef MEMORY_BARRIER +#define MEMORY_BARRIER() __asm__ ("" : : : "memory") +#endif +#ifndef READ_MEMORY_BARRIER +#define READ_MEMORY_BARRIER() MEMORY_BARRIER() +#endif +#ifndef WRITE_MEMORY_BARRIER +#define WRITE_MEMORY_BARRIER() MEMORY_BARRIER() +#endif + +/* Max number of times we must spin on a spinlock calling sched_yield(). + After MAX_SPIN_COUNT iterations, we put the calling thread to sleep. */ + +#ifndef MAX_SPIN_COUNT +#define MAX_SPIN_COUNT 50 +#endif + +/* Max number of times the spinlock in the adaptive mutex implementation + spins actively on SMP systems. */ + +#ifndef MAX_ADAPTIVE_SPIN_COUNT +#define MAX_ADAPTIVE_SPIN_COUNT 100 +#endif + +/* Duration of sleep (in nanoseconds) when we can't acquire a spinlock + after MAX_SPIN_COUNT iterations of sched_yield(). + With the 2.0 and 2.1 kernels, this MUST BE > 2ms. + (Otherwise the kernel does busy-waiting for realtime threads, + giving other threads no chance to run.) */ + +#ifndef SPIN_SLEEP_DURATION +#define SPIN_SLEEP_DURATION 2000001 +#endif + +/* Defined and used in libc.so. */ +extern int __libc_multiple_threads attribute_hidden; +extern int __librt_multiple_threads; + +/* Debugging */ + +#ifdef DEBUG +#include +#define ASSERT assert +#define MSG __pthread_message +#else +#define ASSERT(x) +#define MSG(msg,arg...) +#endif + +/* Internal global functions */ + +extern void __pthread_do_exit (void *retval, char *currentframe) + __attribute__ ((__noreturn__)); +extern void __pthread_destroy_specifics (void); +extern void __pthread_perform_cleanup (char *currentframe); +extern void __pthread_init_max_stacksize (void); +extern int __pthread_initialize_manager (void); +extern void __pthread_message (const char * fmt, ...); +extern int __pthread_manager (void *reqfd); +extern int __pthread_manager_event (void *reqfd); +extern void __pthread_manager_sighandler (int sig); +extern void __pthread_reset_main_thread (void); +extern void __pthread_once_fork_prepare (void); +extern void __pthread_once_fork_parent (void); +extern void __pthread_once_fork_child (void); +extern void __flockfilelist (void); +extern void __funlockfilelist (void); +extern void __fresetlockfiles (void); +extern void __pthread_manager_adjust_prio (int thread_prio); +extern void __pthread_initialize_minimal (void); + +extern int __pthread_attr_setguardsize (pthread_attr_t *__attr, + size_t __guardsize); +extern int __pthread_attr_getguardsize (const pthread_attr_t *__attr, + size_t *__guardsize); +#if 0 /* uClibc: deprecated stuff disabled */ +extern int __pthread_attr_setstackaddr (pthread_attr_t *__attr, + void *__stackaddr); +extern int __pthread_attr_getstackaddr (const pthread_attr_t *__attr, + void **__stackaddr); +#endif +extern int __pthread_attr_setstacksize (pthread_attr_t *__attr, + size_t __stacksize); +extern int __pthread_attr_getstacksize (const pthread_attr_t *__attr, + size_t *__stacksize); +extern int __pthread_attr_setstack (pthread_attr_t *__attr, void *__stackaddr, + size_t __stacksize); +extern int __pthread_attr_getstack (const pthread_attr_t *__attr, void **__stackaddr, + size_t *__stacksize); +extern int __pthread_attr_destroy (pthread_attr_t *attr); +extern int __pthread_attr_setdetachstate (pthread_attr_t *attr, + int detachstate); +extern int __pthread_attr_getdetachstate (const pthread_attr_t *attr, + int *detachstate); +extern int __pthread_attr_setschedparam (pthread_attr_t *attr, + const struct sched_param *param); +extern int __pthread_attr_getschedparam (const pthread_attr_t *attr, + struct sched_param *param); +extern int __pthread_attr_setschedpolicy (pthread_attr_t *attr, int policy); +extern int __pthread_attr_getschedpolicy (const pthread_attr_t *attr, + int *policy); +extern int __pthread_attr_setinheritsched (pthread_attr_t *attr, int inherit); +extern int __pthread_attr_getinheritsched (const pthread_attr_t *attr, + int *inherit); +extern int __pthread_attr_setscope (pthread_attr_t *attr, int scope); +extern int __pthread_attr_getscope (const pthread_attr_t *attr, int *scope); + +extern int __pthread_getconcurrency (void); +extern int __pthread_setconcurrency (int __level); +extern int __pthread_mutex_timedlock (pthread_mutex_t *__mutex, + const struct timespec *__abstime); +extern int __pthread_mutexattr_getpshared (const pthread_mutexattr_t *__attr, + int *__pshared); +extern int __pthread_mutexattr_setpshared (pthread_mutexattr_t *__attr, + int __pshared); +extern int __pthread_mutexattr_gettype (const pthread_mutexattr_t *__attr, + int *__kind); +extern void __pthread_kill_other_threads_np (void); +extern int __pthread_mutex_init (pthread_mutex_t *__mutex, + __const pthread_mutexattr_t *__mutex_attr); +extern int __pthread_mutex_destroy (pthread_mutex_t *__mutex); +extern int __pthread_mutex_lock (pthread_mutex_t *__mutex); +extern int __pthread_mutex_trylock (pthread_mutex_t *__mutex); +extern int __pthread_mutex_unlock (pthread_mutex_t *__mutex); + +extern int __pthread_cond_init (pthread_cond_t *cond, + const pthread_condattr_t *cond_attr); +extern int __pthread_cond_destroy (pthread_cond_t *cond); +extern int __pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex); +extern int __pthread_cond_timedwait (pthread_cond_t *cond, + pthread_mutex_t *mutex, + const struct timespec *abstime); +extern int __pthread_cond_signal (pthread_cond_t *cond); +extern int __pthread_cond_broadcast (pthread_cond_t *cond); +extern int __pthread_condattr_init (pthread_condattr_t *attr); +extern int __pthread_condattr_destroy (pthread_condattr_t *attr); +extern pthread_t __pthread_self (void); +extern pthread_descr __pthread_thread_self (void); +extern pthread_descr __pthread_self_stack (void) attribute_hidden; +extern int __pthread_equal (pthread_t thread1, pthread_t thread2); +extern void __pthread_exit (void *retval) +#if defined NOT_IN_libc && defined IS_IN_libpthread + attribute_noreturn +#endif + ; +extern int __pthread_getschedparam (pthread_t thread, int *policy, + struct sched_param *param); +extern int __pthread_setschedparam (pthread_t thread, int policy, + const struct sched_param *param); +extern int __pthread_setcancelstate (int state, int * oldstate); +extern int __pthread_setcanceltype (int type, int * oldtype); + +extern void __pthread_restart_old(pthread_descr th); +extern void __pthread_suspend_old(pthread_descr self); +extern int __pthread_timedsuspend_old(pthread_descr self, const struct timespec *abstime); + +extern void __pthread_restart_new(pthread_descr th); +extern void __pthread_suspend_new(pthread_descr self); +extern int __pthread_timedsuspend_new(pthread_descr self, const struct timespec *abstime); + +extern void __pthread_wait_for_restart_signal(pthread_descr self); + +extern void __pthread_sigsuspend (const sigset_t *mask) attribute_hidden; + +extern int __pthread_rwlock_timedrdlock (pthread_rwlock_t *__restrict __rwlock, + __const struct timespec *__restrict + __abstime); +extern int __pthread_rwlock_timedwrlock (pthread_rwlock_t *__restrict __rwlock, + __const struct timespec *__restrict + __abstime); +extern int __pthread_rwlockattr_destroy (pthread_rwlockattr_t *__attr); + +extern int __pthread_barrierattr_getpshared (__const pthread_barrierattr_t * + __restrict __attr, + int *__restrict __pshared); + +extern int __pthread_spin_lock (pthread_spinlock_t *__lock); +extern int __pthread_spin_trylock (pthread_spinlock_t *__lock); +extern int __pthread_spin_unlock (pthread_spinlock_t *__lock); +extern int __pthread_spin_init (pthread_spinlock_t *__lock, int __pshared); +extern int __pthread_spin_destroy (pthread_spinlock_t *__lock); + +/* Global pointers to old or new suspend functions */ + +extern void (*__pthread_restart)(pthread_descr); +extern void (*__pthread_suspend)(pthread_descr); +extern int (*__pthread_timedsuspend)(pthread_descr, const struct timespec *); + +/* Prototypes for some of the new semaphore functions. */ +extern int sem_post (sem_t * sem); +extern int sem_init (sem_t *__sem, int __pshared, unsigned int __value); +extern int sem_wait (sem_t *__sem); +extern int sem_trywait (sem_t *__sem); +extern int sem_getvalue (sem_t *__restrict __sem, int *__restrict __sval); +extern int sem_destroy (sem_t *__sem); + +/* Prototypes for compatibility functions. */ +extern int __pthread_attr_init (pthread_attr_t *__attr); +extern int __pthread_create (pthread_t *__restrict __threadp, + const pthread_attr_t *__attr, + void *(*__start_routine) (void *), + void *__restrict __arg); + +/* The functions called the signal events. */ +extern void __linuxthreads_create_event (void); +extern void __linuxthreads_death_event (void); +extern void __linuxthreads_reap_event (void); + +/* This function is called to initialize the pthread library. */ +extern void __pthread_initialize (void); + +/* TSD. */ +extern int __pthread_internal_tsd_set (int key, const void * pointer); +extern void * __pthread_internal_tsd_get (int key); +extern void ** __attribute__ ((__const__)) + __pthread_internal_tsd_address (int key); + +/* Sighandler wrappers. */ +extern void __pthread_sighandler(int signo, SIGCONTEXT ctx); +extern void __pthread_sighandler_rt(int signo, struct siginfo *si, + struct ucontext *uc); +extern void __pthread_null_sighandler(int sig); +extern int __pthread_sigaction (int sig, const struct sigaction *act, + struct sigaction *oact); +extern int __pthread_sigwait (const sigset_t *set, int *sig); +extern int __pthread_raise (int sig); + +/* Cancellation. */ +extern int __pthread_enable_asynccancel (void) attribute_hidden; +extern void __pthread_disable_asynccancel (int oldtype) + internal_function attribute_hidden; + +/* The two functions are in libc.so and not exported. */ +extern int __libc_enable_asynccancel (void) attribute_hidden; +extern void __libc_disable_asynccancel (int oldtype) + internal_function attribute_hidden; + +/* The two functions are in libc.so and are exported. */ +extern int __librt_enable_asynccancel (void); +extern void __librt_disable_asynccancel (int oldtype) internal_function; + +extern void __pthread_cleanup_upto (__jmp_buf target, + char *targetframe) attribute_hidden; +extern pid_t __pthread_fork (struct fork_block *b) attribute_hidden; + +#define asm_handle(name) _asm_handle(name) +#define _asm_handle(name) #name +#define ASM_GLOBAL asm_handle(ASM_GLOBAL_DIRECTIVE) +#define ASM_CANCEL(name) asm_handle(C_SYMBOL_NAME(name)) + +#if !defined NOT_IN_libc +# define LIBC_CANCEL_ASYNC() \ + __libc_enable_asynccancel () +# define LIBC_CANCEL_RESET(oldtype) \ + __libc_disable_asynccancel (oldtype) +# define LIBC_CANCEL_HANDLED() \ + __asm__ (ASM_GLOBAL " " ASM_CANCEL(__libc_enable_asynccancel)); \ + __asm__ (ASM_GLOBAL " " ASM_CANCEL(__libc_disable_asynccancel)) +#elif defined IS_IN_libpthread +# define LIBC_CANCEL_ASYNC() \ + __pthread_enable_asynccancel () +# define LIBC_CANCEL_RESET(oldtype) \ + __pthread_disable_asynccancel (oldtype) +# define LIBC_CANCEL_HANDLED() \ + __asm__ (ASM_GLOBAL " " ASM_CANCEL(__pthread_enable_asynccancel)); \ + __asm__ (ASM_GLOBAL " " ASM_CANCEL(__pthread_disable_asynccancel)) +#elif defined IS_IN_librt +# define LIBC_CANCEL_ASYNC() \ + __librt_enable_asynccancel () +# define LIBC_CANCEL_RESET(oldtype) \ + __librt_disable_asynccancel (oldtype) +# define LIBC_CANCEL_HANDLED() \ + __asm__ (ASM_GLOBAL " " ASM_CANCEL(__librt_enable_asynccancel)); \ + __asm__ (ASM_GLOBAL " " ASM_CANCEL(__librt_disable_asynccancel)) +#else +# define LIBC_CANCEL_ASYNC() 0 /* Just a dummy value. */ +# define LIBC_CANCEL_RESET(val) ((void)(val)) /* Nothing, but evaluate it. */ +# define LIBC_CANCEL_HANDLED() /* Nothing. */ +#endif + +extern int * __libc_pthread_init (const struct pthread_functions *functions); + +#if !defined NOT_IN_libc && !defined FLOATING_STACKS +# ifdef SHARED +# define thread_self() \ + (*__libc_pthread_functions.ptr_pthread_thread_self) () +# else +weak_extern (__pthread_thread_self) +# define thread_self() __pthread_thread_self () +# endif +#endif + +#ifndef USE_TLS +# define __manager_thread (&__pthread_manager_thread) +#else +# define __manager_thread __pthread_manager_threadp +#endif + +static __always_inline pthread_descr +check_thread_self (void); +static __always_inline pthread_descr +check_thread_self (void) +{ + pthread_descr self = thread_self (); +#if defined THREAD_SELF && defined INIT_THREAD_SELF + if (self == __manager_thread) + { + /* A new thread might get a cancel signal before it is fully + initialized, so that the thread register might still point to the + manager thread. Double check that this is really the manager + thread. */ + self = __pthread_self_stack(); + if (self != __manager_thread) + /* Oops, thread_self() isn't working yet.. */ + INIT_THREAD_SELF(self, self->p_nr); + } +#endif + return self; +} + +#endif /* internals.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/join.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/join.c new file mode 100644 index 00000000..57ea54e3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/join.c @@ -0,0 +1,220 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +/* Thread termination and joining */ + +#include +#include +#include +#include +#include "pthread.h" +#include "internals.h" +#include "spinlock.h" +#include "restart.h" +#include + +void __pthread_exit(void * retval) +{ + __pthread_do_exit (retval, CURRENT_STACK_FRAME); +} +strong_alias (__pthread_exit, pthread_exit) + +void __pthread_do_exit(void *retval, char *currentframe) +{ + pthread_descr self = thread_self(); + pthread_descr joining; + struct pthread_request request; + + /* Reset the cancellation flag to avoid looping if the cleanup handlers + contain cancellation points */ + THREAD_SETMEM(self, p_canceled, 0); + /* Call cleanup functions and destroy the thread-specific data */ + __pthread_perform_cleanup(currentframe); + __pthread_destroy_specifics(); + /* Store return value */ + __pthread_lock(THREAD_GETMEM(self, p_lock), self); + THREAD_SETMEM(self, p_retval, retval); + /* See whether we have to signal the death. */ + if (THREAD_GETMEM(self, p_report_events)) + { + /* See whether TD_DEATH is in any of the mask. */ + int idx = __td_eventword (TD_DEATH); + uint32_t mask = __td_eventmask (TD_DEATH); + + if ((mask & (__pthread_threads_events.event_bits[idx] + | THREAD_GETMEM_NC(self, + p_eventbuf.eventmask.event_bits[idx]))) + != 0) + { + /* Yep, we have to signal the death. */ + THREAD_SETMEM(self, p_eventbuf.eventnum, TD_DEATH); + THREAD_SETMEM(self, p_eventbuf.eventdata, self); + __pthread_last_event = self; + + /* Now call the function to signal the event. */ + __linuxthreads_death_event(); + } + } + /* Say that we've terminated */ + THREAD_SETMEM(self, p_terminated, 1); + /* See if someone is joining on us */ + joining = THREAD_GETMEM(self, p_joining); + __pthread_unlock(THREAD_GETMEM(self, p_lock)); + /* Restart joining thread if any */ + if (joining != NULL) restart(joining); + /* If this is the initial thread, block until all threads have terminated. + If another thread calls exit, we'll be terminated from our signal + handler. */ + if (self == __pthread_main_thread && __pthread_manager_request >= 0) { + request.req_thread = self; + request.req_kind = REQ_MAIN_THREAD_EXIT; + TEMP_FAILURE_RETRY(write_not_cancel(__pthread_manager_request, + (char *)&request, sizeof(request))); + suspend(self); + /* Main thread flushes stdio streams and runs atexit functions. + It also calls a handler within LinuxThreads which sends a process exit + request to the thread manager. */ + exit(0); + } + /* Threads other than the main one terminate without flushing stdio streams + or running atexit functions. */ + _exit(0); +} + +/* Function called by pthread_cancel to remove the thread from + waiting on a condition variable queue. */ + +static int join_extricate_func(void *obj, pthread_descr th) +{ + __volatile__ pthread_descr self = thread_self(); + pthread_handle handle = obj; + pthread_descr jo; + int did_remove = 0; + + __pthread_lock(&handle->h_lock, self); + jo = handle->h_descr; + did_remove = jo->p_joining != NULL; + jo->p_joining = NULL; + __pthread_unlock(&handle->h_lock); + + return did_remove; +} + +int pthread_join(pthread_t thread_id, void ** thread_return) +{ + __volatile__ pthread_descr self = thread_self(); + struct pthread_request request; + pthread_handle handle = thread_handle(thread_id); + pthread_descr th; + pthread_extricate_if extr; + int already_canceled = 0; + + /* Set up extrication interface */ + extr.pu_object = handle; + extr.pu_extricate_func = join_extricate_func; + + __pthread_lock(&handle->h_lock, self); + if (nonexisting_handle(handle, thread_id)) { + __pthread_unlock(&handle->h_lock); + return ESRCH; + } + th = handle->h_descr; + if (th == self) { + __pthread_unlock(&handle->h_lock); + return EDEADLK; + } + /* If detached or already joined, error */ + if (th->p_detached || th->p_joining != NULL) { + __pthread_unlock(&handle->h_lock); + return EINVAL; + } + /* If not terminated yet, suspend ourselves. */ + if (! th->p_terminated) { + /* Register extrication interface */ + __pthread_set_own_extricate_if(self, &extr); + if (!(THREAD_GETMEM(self, p_canceled) + && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE)) + th->p_joining = self; + else + already_canceled = 1; + __pthread_unlock(&handle->h_lock); + + if (already_canceled) { + __pthread_set_own_extricate_if(self, 0); + __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); + } + + suspend(self); + /* Deregister extrication interface */ + __pthread_set_own_extricate_if(self, 0); + + /* This is a cancellation point */ + if (THREAD_GETMEM(self, p_woken_by_cancel) + && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) { + THREAD_SETMEM(self, p_woken_by_cancel, 0); + __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); + } + __pthread_lock(&handle->h_lock, self); + } + /* Get return value */ + if (thread_return != NULL) *thread_return = th->p_retval; + __pthread_unlock(&handle->h_lock); + /* Send notification to thread manager */ + if (__pthread_manager_request >= 0) { + request.req_thread = self; + request.req_kind = REQ_FREE; + request.req_args.free.thread_id = thread_id; + TEMP_FAILURE_RETRY(write_not_cancel(__pthread_manager_request, + (char *) &request, sizeof(request))); + } + return 0; +} + +int pthread_detach(pthread_t thread_id) +{ + int terminated; + struct pthread_request request; + pthread_handle handle = thread_handle(thread_id); + pthread_descr th; + + __pthread_lock(&handle->h_lock, NULL); + if (nonexisting_handle(handle, thread_id)) { + __pthread_unlock(&handle->h_lock); + return ESRCH; + } + th = handle->h_descr; + /* If already detached, error */ + if (th->p_detached) { + __pthread_unlock(&handle->h_lock); + return EINVAL; + } + /* If already joining, don't do anything. */ + if (th->p_joining != NULL) { + __pthread_unlock(&handle->h_lock); + return 0; + } + /* Mark as detached */ + th->p_detached = 1; + terminated = th->p_terminated; + __pthread_unlock(&handle->h_lock); + /* If already terminated, notify thread manager to reclaim resources */ + if (terminated && __pthread_manager_request >= 0) { + request.req_thread = thread_self(); + request.req_kind = REQ_FREE; + request.req_args.free.thread_id = thread_id; + TEMP_FAILURE_RETRY(write_not_cancel(__pthread_manager_request, + (char *) &request, sizeof(request))); + } + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/libc-cancellation.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/libc-cancellation.c new file mode 100644 index 00000000..23bb2a5b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/libc-cancellation.c @@ -0,0 +1,61 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include "pthread.h" +#include "internals.h" +#include "spinlock.h" +#include "restart.h" +#include + +#if !defined NOT_IN_libc + +# ifndef SHARED +weak_extern (__pthread_do_exit) +# endif + +/* The next two functions are similar to pthread_setcanceltype() but + more specialized for the use in the cancelable functions like write(). + They do not need to check parameters etc. */ +int +attribute_hidden +__libc_enable_asynccancel (void) +{ + pthread_descr self = thread_self(); + int oldtype = LIBC_THREAD_GETMEM(self, p_canceltype); + LIBC_THREAD_SETMEM(self, p_canceltype, PTHREAD_CANCEL_ASYNCHRONOUS); + if (__builtin_expect (LIBC_THREAD_GETMEM(self, p_canceled), 0) && + LIBC_THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) + __libc_maybe_call2 (pthread_do_exit, + (PTHREAD_CANCELED, CURRENT_STACK_FRAME), 0); + return oldtype; +} +strong_alias (__libc_enable_asynccancel, __librt_enable_asynccancel) + +void +internal_function attribute_hidden +__libc_disable_asynccancel (int oldtype) +{ + pthread_descr self = thread_self(); + LIBC_THREAD_SETMEM(self, p_canceltype, oldtype); +} +strong_alias (__libc_disable_asynccancel, __librt_disable_asynccancel) + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/libc_pthread_init.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/libc_pthread_init.c new file mode 100644 index 00000000..afe995ae --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/libc_pthread_init.c @@ -0,0 +1,52 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#ifdef USE_TLS +#include +#endif +#include "internals.h" + + +int __libc_multiple_threads attribute_hidden __attribute__((nocommon)); +strong_alias (__libc_multiple_threads, __librt_multiple_threads) + + +int * +__libc_pthread_init (functions) + const struct pthread_functions *functions; +{ +#ifdef SHARED + /* We copy the content of the variable pointed to by the FUNCTIONS + parameter to one in libc.so since this means access to the array + can be done with one memory access instead of two. */ + memcpy (&__libc_pthread_functions, functions, + sizeof (__libc_pthread_functions)); +#endif + +#if !(USE_TLS && HAVE___THREAD) + /* Initialize thread-locale current locale to point to the global one. + With __thread support, the variable's initializer takes care of this. */ + __uselocale (LC_GLOBAL_LOCALE); +#endif + + return &__libc_multiple_threads; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/lockfile.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/lockfile.c new file mode 100644 index 00000000..5266b184 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/lockfile.c @@ -0,0 +1,52 @@ +/* lockfile - Handle locking and unlocking of stream. + Copyright (C) 1996, 1998, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include "internals.h" + +/* Note: glibc puts flockfile, funlockfile, and ftrylockfile in both + * libc and libpthread. In uClibc, they are now in libc only. */ + +void +__flockfilelist(void) +{ +} + +void +__funlockfilelist(void) +{ +} + +void +__fresetlockfiles (void) +{ + FILE *fp; + + pthread_mutexattr_t attr; + + __pthread_mutexattr_init (&attr); + __pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE_NP); + + for (fp = _stdio_openlist; fp != NULL; fp = fp->__nextopen) + pthread_mutex_init (&fp->__lock, &attr); + + pthread_mutexattr_destroy(&attr); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/manager.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/manager.c new file mode 100644 index 00000000..4293741a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/manager.c @@ -0,0 +1,1122 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +/* The "thread manager" thread: manages creation and termination of threads */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include /* for poll */ +#include /* for mmap */ +#include +#include +#include /* for waitpid macros */ +#include /* for __uselocale */ +#include /* for __resp */ + +#include "pthread.h" +#include "internals.h" +#include "spinlock.h" +#include "restart.h" +#include "semaphore.h" +#include + +/* For debugging purposes put the maximum number of threads in a variable. */ +const int __linuxthreads_pthread_threads_max = PTHREAD_THREADS_MAX; + +#ifndef THREAD_SELF +/* Indicate whether at least one thread has a user-defined stack (if 1), + or if all threads have stacks supplied by LinuxThreads (if 0). */ +int __pthread_nonstandard_stacks; +#endif + +/* Number of active entries in __pthread_handles (used by gdb) */ +__volatile__ int __pthread_handles_num = 2; + +/* Whether to use debugger additional actions for thread creation + (set to 1 by gdb) */ +__volatile__ int __pthread_threads_debug; + +/* Globally enabled events. */ +__volatile__ td_thr_events_t __pthread_threads_events; + +/* Pointer to thread descriptor with last event. */ +__volatile__ pthread_descr __pthread_last_event; + +static pthread_descr manager_thread; + +/* Mapping from stack segment to thread descriptor. */ +/* Stack segment numbers are also indices into the __pthread_handles array. */ +/* Stack segment number 0 is reserved for the initial thread. */ + +#if FLOATING_STACKS +# define thread_segment(seq) NULL +#else +static __inline__ pthread_descr thread_segment(int seg) +{ +# ifdef _STACK_GROWS_UP + return (pthread_descr)(THREAD_STACK_START_ADDRESS + (seg - 1) * STACK_SIZE) + + 1; +# else + return (pthread_descr)(THREAD_STACK_START_ADDRESS - (seg - 1) * STACK_SIZE) + - 1; +# endif +} +#endif + +/* Flag set in signal handler to record child termination */ + +static __volatile__ int terminated_children; + +/* Flag set when the initial thread is blocked on pthread_exit waiting + for all other threads to terminate */ + +static int main_thread_exiting; + +/* Counter used to generate unique thread identifier. + Thread identifier is pthread_threads_counter + segment. */ + +static pthread_t pthread_threads_counter; + +/* Forward declarations */ + +static int pthread_handle_create(pthread_t *thread, const pthread_attr_t *attr, + void * (*start_routine)(void *), void *arg, + sigset_t *mask, int father_pid, + int report_events, + td_thr_events_t *event_maskp); +static void pthread_handle_free(pthread_t th_id); +static void pthread_handle_exit(pthread_descr issuing_thread, int exitcode) + __attribute__ ((noreturn)); +static void pthread_reap_children(void); +static void pthread_kill_all_threads(int sig, int main_thread_also); +static void pthread_for_each_thread(void *arg, + void (*fn)(void *, pthread_descr)); + +/* The server thread managing requests for thread creation and termination */ + +int +__attribute__ ((noreturn)) +__pthread_manager(void *arg) +{ + pthread_descr self = manager_thread = arg; + int reqfd = __pthread_manager_reader; + struct pollfd ufd; + sigset_t manager_mask; + int n; + struct pthread_request request; + + /* If we have special thread_self processing, initialize it. */ +#ifdef INIT_THREAD_SELF + INIT_THREAD_SELF(self, 1); +#endif +#if !(USE_TLS && HAVE___THREAD) + /* Set the error variable. */ + self->p_errnop = &self->p_errno; + self->p_h_errnop = &self->p_h_errno; +#endif + /* Block all signals except __pthread_sig_cancel and SIGTRAP */ + __sigfillset(&manager_mask); + sigdelset(&manager_mask, __pthread_sig_cancel); /* for thread termination */ + sigdelset(&manager_mask, SIGTRAP); /* for debugging purposes */ + if (__pthread_threads_debug && __pthread_sig_debug > 0) + sigdelset(&manager_mask, __pthread_sig_debug); + sigprocmask(SIG_SETMASK, &manager_mask, NULL); + /* Raise our priority to match that of main thread */ + __pthread_manager_adjust_prio(__pthread_main_thread->p_priority); + /* Synchronize debugging of the thread manager */ + n = TEMP_FAILURE_RETRY(read_not_cancel(reqfd, (char *)&request, + sizeof(request))); + ASSERT(n == sizeof(request) && request.req_kind == REQ_DEBUG); + ufd.fd = reqfd; + ufd.events = POLLIN; + /* Enter server loop */ + while(1) { + n = __poll(&ufd, 1, 2000); + + /* Check for termination of the main thread */ + if (getppid() == 1) { + pthread_kill_all_threads(SIGKILL, 0); + _exit(0); + } + /* Check for dead children */ + if (terminated_children) { + terminated_children = 0; + pthread_reap_children(); + } + /* Read and execute request */ + if (n == 1 && (ufd.revents & POLLIN)) { + n = TEMP_FAILURE_RETRY(read_not_cancel(reqfd, (char *)&request, + sizeof(request))); +#ifdef DEBUG + if (n < 0) { + char d[64]; + write(STDERR_FILENO, d, snprintf(d, sizeof(d), "*** read err %m\n")); + } else if (n != sizeof(request)) { + write(STDERR_FILENO, "*** short read in manager\n", 26); + } +#endif + + switch(request.req_kind) { + case REQ_CREATE: + request.req_thread->p_retcode = + pthread_handle_create((pthread_t *) &request.req_thread->p_retval, + request.req_args.create.attr, + request.req_args.create.fn, + request.req_args.create.arg, + &request.req_args.create.mask, + request.req_thread->p_pid, + request.req_thread->p_report_events, + &request.req_thread->p_eventbuf.eventmask); + restart(request.req_thread); + break; + case REQ_FREE: + pthread_handle_free(request.req_args.free.thread_id); + break; + case REQ_PROCESS_EXIT: + pthread_handle_exit(request.req_thread, + request.req_args.exit.code); + /* NOTREACHED */ + break; + case REQ_MAIN_THREAD_EXIT: + main_thread_exiting = 1; + /* Reap children in case all other threads died and the signal handler + went off before we set main_thread_exiting to 1, and therefore did + not do REQ_KICK. */ + pthread_reap_children(); + + if (__pthread_main_thread->p_nextlive == __pthread_main_thread) { + restart(__pthread_main_thread); + /* The main thread will now call exit() which will trigger an + __on_exit handler, which in turn will send REQ_PROCESS_EXIT + to the thread manager. In case you are wondering how the + manager terminates from its loop here. */ + } + break; + case REQ_POST: + sem_post(request.req_args.post); + break; + case REQ_DEBUG: + /* Make gdb aware of new thread and gdb will restart the + new thread when it is ready to handle the new thread. */ + if (__pthread_threads_debug && __pthread_sig_debug > 0) + raise(__pthread_sig_debug); + break; + case REQ_KICK: + /* This is just a prod to get the manager to reap some + threads right away, avoiding a potential delay at shutdown. */ + break; + case REQ_FOR_EACH_THREAD: + pthread_for_each_thread(request.req_args.for_each.arg, + request.req_args.for_each.fn); + restart(request.req_thread); + break; + } + } + } +} + +int __pthread_manager_event(void *arg) +{ + pthread_descr self = arg; + /* If we have special thread_self processing, initialize it. */ +#ifdef INIT_THREAD_SELF + INIT_THREAD_SELF(self, 1); +#endif + + /* Get the lock the manager will free once all is correctly set up. */ + __pthread_lock (THREAD_GETMEM(self, p_lock), NULL); + /* Free it immediately. */ + __pthread_unlock (THREAD_GETMEM(self, p_lock)); + + return __pthread_manager(arg); +} + +/* Process creation */ + +static int +__attribute__ ((noreturn)) +pthread_start_thread(void *arg) +{ + pthread_descr self = (pthread_descr) arg; + struct pthread_request request; + void * outcome; +#if HP_TIMING_AVAIL + hp_timing_t tmpclock; +#endif + /* Initialize special thread_self processing, if any. */ +#ifdef INIT_THREAD_SELF + INIT_THREAD_SELF(self, self->p_nr); +#endif +#if HP_TIMING_AVAIL + HP_TIMING_NOW (tmpclock); + THREAD_SETMEM (self, p_cpuclock_offset, tmpclock); +#endif + /* Make sure our pid field is initialized, just in case we get there + before our father has initialized it. */ + THREAD_SETMEM(self, p_pid, __getpid()); + /* Initial signal mask is that of the creating thread. (Otherwise, + we'd just inherit the mask of the thread manager.) */ + sigprocmask(SIG_SETMASK, &self->p_start_args.mask, NULL); + /* Set the scheduling policy and priority for the new thread, if needed */ + if (THREAD_GETMEM(self, p_start_args.schedpolicy) >= 0) + /* Explicit scheduling attributes were provided: apply them */ + __sched_setscheduler(THREAD_GETMEM(self, p_pid), + THREAD_GETMEM(self, p_start_args.schedpolicy), + &self->p_start_args.schedparam); + else if (manager_thread->p_priority > 0) + /* Default scheduling required, but thread manager runs in realtime + scheduling: switch new thread to SCHED_OTHER policy */ + { + struct sched_param default_params; + default_params.sched_priority = 0; + __sched_setscheduler(THREAD_GETMEM(self, p_pid), + SCHED_OTHER, &default_params); + } +#if !(USE_TLS && HAVE___THREAD) + /* Initialize thread-locale current locale to point to the global one. + With __thread support, the variable's initializer takes care of this. */ + __uselocale (LC_GLOBAL_LOCALE); +#else + /* Initialize __resp. */ + __resp = &self->p_res; +#endif + /* Make gdb aware of new thread */ + if (__pthread_threads_debug && __pthread_sig_debug > 0) { + request.req_thread = self; + request.req_kind = REQ_DEBUG; + TEMP_FAILURE_RETRY(write_not_cancel(__pthread_manager_request, + (char *) &request, sizeof(request))); + suspend(self); + } + /* Run the thread code */ + outcome = self->p_start_args.start_routine(THREAD_GETMEM(self, + p_start_args.arg)); + /* Exit with the given return value */ + __pthread_do_exit(outcome, CURRENT_STACK_FRAME); +} + +static int +__attribute__ ((noreturn)) +pthread_start_thread_event(void *arg) +{ + pthread_descr self = (pthread_descr) arg; + +#ifdef INIT_THREAD_SELF + INIT_THREAD_SELF(self, self->p_nr); +#endif + /* Make sure our pid field is initialized, just in case we get there + before our father has initialized it. */ + THREAD_SETMEM(self, p_pid, __getpid()); + /* Get the lock the manager will free once all is correctly set up. */ + __pthread_lock (THREAD_GETMEM(self, p_lock), NULL); + /* Free it immediately. */ + __pthread_unlock (THREAD_GETMEM(self, p_lock)); + + /* Continue with the real function. */ + pthread_start_thread (arg); +} + +#if defined USE_TLS && !FLOATING_STACKS +# error "TLS can only work with floating stacks" +#endif + +static int pthread_allocate_stack(const pthread_attr_t *attr, + pthread_descr default_new_thread, + int pagesize, + char ** out_new_thread, + char ** out_new_thread_bottom, + char ** out_guardaddr, + size_t * out_guardsize, + size_t * out_stacksize) +{ + pthread_descr new_thread; + char * new_thread_bottom; + char * guardaddr; + size_t stacksize, guardsize; + +#ifdef USE_TLS + /* TLS cannot work with fixed thread descriptor addresses. */ + assert (default_new_thread == NULL); +#endif + + if (attr != NULL && attr->__stackaddr_set) + { +#ifdef _STACK_GROWS_UP + /* The user provided a stack. */ +# ifdef USE_TLS + /* This value is not needed. */ + new_thread = (pthread_descr) attr->__stackaddr; + new_thread_bottom = (char *) new_thread; +# else + new_thread = (pthread_descr) attr->__stackaddr; + new_thread_bottom = (char *) (new_thread + 1); +# endif + guardaddr = attr->__stackaddr + attr->__stacksize; + guardsize = 0; +#else + /* The user provided a stack. For now we interpret the supplied + address as 1 + the highest addr. in the stack segment. If a + separate register stack is needed, we place it at the low end + of the segment, relying on the associated stacksize to + determine the low end of the segment. This differs from many + (but not all) other pthreads implementations. The intent is + that on machines with a single stack growing toward higher + addresses, stackaddr would be the lowest address in the stack + segment, so that it is consistently close to the initial sp + value. */ +# ifdef USE_TLS + new_thread = (pthread_descr) attr->__stackaddr; +# else + new_thread = + (pthread_descr) ((long)(attr->__stackaddr) & -sizeof(void *)) - 1; +# endif + new_thread_bottom = (char *) attr->__stackaddr - attr->__stacksize; + guardaddr = new_thread_bottom; + guardsize = 0; +#endif +#ifndef THREAD_SELF + __pthread_nonstandard_stacks = 1; +#endif +#ifndef USE_TLS + /* Clear the thread data structure. */ + memset (new_thread, '\0', sizeof (*new_thread)); +#endif + stacksize = attr->__stacksize; + } + else + { +#ifdef NEED_SEPARATE_REGISTER_STACK + const size_t granularity = 2 * pagesize; + /* Try to make stacksize/2 a multiple of pagesize */ +#else + const size_t granularity = pagesize; +#endif + void *map_addr; + + /* Allocate space for stack and thread descriptor at default address */ +#if FLOATING_STACKS + if (attr != NULL) + { + guardsize = page_roundup (attr->__guardsize, granularity); + stacksize = __pthread_max_stacksize - guardsize; + stacksize = MIN (stacksize, + page_roundup (attr->__stacksize, granularity)); + } + else + { + guardsize = granularity; + stacksize = __pthread_max_stacksize - guardsize; + } + + map_addr = mmap(NULL, stacksize + guardsize, + PROT_READ | PROT_WRITE | PROT_EXEC, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (map_addr == MAP_FAILED) + /* No more memory available. */ + return -1; + +# ifdef NEED_SEPARATE_REGISTER_STACK + guardaddr = map_addr + stacksize / 2; + if (guardsize > 0) + mprotect (guardaddr, guardsize, PROT_NONE); + + new_thread_bottom = (char *) map_addr; +# ifdef USE_TLS + new_thread = ((pthread_descr) (new_thread_bottom + stacksize + + guardsize)); +# else + new_thread = ((pthread_descr) (new_thread_bottom + stacksize + + guardsize)) - 1; +# endif +# elif _STACK_GROWS_DOWN + guardaddr = map_addr; + if (guardsize > 0) + mprotect (guardaddr, guardsize, PROT_NONE); + + new_thread_bottom = (char *) map_addr + guardsize; +# ifdef USE_TLS + new_thread = ((pthread_descr) (new_thread_bottom + stacksize)); +# else + new_thread = ((pthread_descr) (new_thread_bottom + stacksize)) - 1; +# endif +# elif _STACK_GROWS_UP + guardaddr = map_addr + stacksize; + if (guardsize > 0) + mprotect (guardaddr, guardsize, PROT_NONE); + + new_thread = (pthread_descr) map_addr; +# ifdef USE_TLS + new_thread_bottom = (char *) new_thread; +# else + new_thread_bottom = (char *) (new_thread + 1); +# endif +# else +# error You must define a stack direction +# endif /* Stack direction */ +#else /* !FLOATING_STACKS */ +# if !defined NEED_SEPARATE_REGISTER_STACK && defined _STACK_GROWS_DOWN + void *res_addr; +# endif + + if (attr != NULL) + { + guardsize = page_roundup (attr->__guardsize, granularity); + stacksize = STACK_SIZE - guardsize; + stacksize = MIN (stacksize, + page_roundup (attr->__stacksize, granularity)); + } + else + { + guardsize = granularity; + stacksize = STACK_SIZE - granularity; + } + +# ifdef NEED_SEPARATE_REGISTER_STACK + new_thread = default_new_thread; + new_thread_bottom = (char *) (new_thread + 1) - stacksize - guardsize; + /* Includes guard area, unlike the normal case. Use the bottom + end of the segment as backing store for the register stack. + Needed on IA64. In this case, we also map the entire stack at + once. According to David Mosberger, that's cheaper. It also + avoids the risk of intermittent failures due to other mappings + in the same region. The cost is that we might be able to map + slightly fewer stacks. */ + + /* First the main stack: */ + map_addr = (caddr_t)((char *)(new_thread + 1) - stacksize / 2); + res_addr = mmap(map_addr, stacksize / 2, + PROT_READ | PROT_WRITE | PROT_EXEC, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (res_addr != map_addr) + { + /* Bad luck, this segment is already mapped. */ + if (res_addr != MAP_FAILED) + munmap(res_addr, stacksize / 2); + return -1; + } + /* Then the register stack: */ + map_addr = (caddr_t)new_thread_bottom; + res_addr = mmap(map_addr, stacksize/2, + PROT_READ | PROT_WRITE | PROT_EXEC, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (res_addr != map_addr) + { + if (res_addr != MAP_FAILED) + munmap(res_addr, stacksize / 2); + munmap((caddr_t)((char *)(new_thread + 1) - stacksize/2), + stacksize/2); + return -1; + } + + guardaddr = new_thread_bottom + stacksize/2; + /* We leave the guard area in the middle unmapped. */ +# else /* !NEED_SEPARATE_REGISTER_STACK */ +# ifdef _STACK_GROWS_DOWN + new_thread = default_new_thread; + new_thread_bottom = (char *) (new_thread + 1) - stacksize; + map_addr = new_thread_bottom - guardsize; + res_addr = mmap(map_addr, stacksize + guardsize, + PROT_READ | PROT_WRITE | PROT_EXEC, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (res_addr != map_addr) + { + /* Bad luck, this segment is already mapped. */ + if (res_addr != MAP_FAILED) + munmap (res_addr, stacksize + guardsize); + return -1; + } + + /* We manage to get a stack. Protect the guard area pages if + necessary. */ + guardaddr = map_addr; + if (guardsize > 0) + mprotect (guardaddr, guardsize, PROT_NONE); +# else + /* The thread description goes at the bottom of this area, and + * the stack starts directly above it. + */ + new_thread = (pthread_descr)((unsigned long)default_new_thread &~ (STACK_SIZE - 1)); + map_addr = mmap(new_thread, stacksize + guardsize, + PROT_READ | PROT_WRITE | PROT_EXEC, + MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (map_addr == MAP_FAILED) + return -1; + + new_thread_bottom = map_addr + sizeof(*new_thread); + guardaddr = map_addr + stacksize; + if (guardsize > 0) + mprotect (guardaddr, guardsize, PROT_NONE); + +# endif /* stack direction */ +# endif /* !NEED_SEPARATE_REGISTER_STACK */ +#endif /* !FLOATING_STACKS */ + } + *out_new_thread = (char *) new_thread; + *out_new_thread_bottom = new_thread_bottom; + *out_guardaddr = guardaddr; + *out_guardsize = guardsize; +#ifdef NEED_SEPARATE_REGISTER_STACK + *out_stacksize = stacksize / 2; +#else + *out_stacksize = stacksize; +#endif + return 0; +} + +static int pthread_handle_create(pthread_t *thread, const pthread_attr_t *attr, + void * (*start_routine)(void *), void *arg, + sigset_t * mask, int father_pid, + int report_events, + td_thr_events_t *event_maskp) +{ + size_t sseg; + int pid; + pthread_descr new_thread; + char *stack_addr; + char * new_thread_bottom; + pthread_t new_thread_id; + char *guardaddr = NULL; + size_t guardsize = 0, stksize = 0; + int pagesize = __getpagesize(); + int saved_errno = 0; + +#ifdef USE_TLS + new_thread = _dl_allocate_tls (NULL); + if (new_thread == NULL) + return EAGAIN; +# if defined(TLS_DTV_AT_TP) + /* pthread_descr is below TP. */ + new_thread = (pthread_descr) ((char *) new_thread - TLS_PRE_TCB_SIZE); +# endif +#else + /* Prevent warnings. */ + new_thread = NULL; +#endif + + /* First check whether we have to change the policy and if yes, whether + we can do this. Normally this should be done by examining the + return value of the __sched_setscheduler call in pthread_start_thread + but this is hard to implement. FIXME */ + if (attr != NULL && attr->__schedpolicy != SCHED_OTHER && geteuid () != 0) + return EPERM; + /* Find a free segment for the thread, and allocate a stack if needed */ + for (sseg = 2; ; sseg++) + { + if (sseg >= PTHREAD_THREADS_MAX) + { +#ifdef USE_TLS +# if defined(TLS_DTV_AT_TP) + new_thread = (pthread_descr) ((char *) new_thread + TLS_PRE_TCB_SIZE); +# endif + _dl_deallocate_tls (new_thread, true); +#endif + return EAGAIN; + } + if (__pthread_handles[sseg].h_descr != NULL) + continue; + if (pthread_allocate_stack(attr, thread_segment(sseg), + pagesize, &stack_addr, &new_thread_bottom, + &guardaddr, &guardsize, &stksize) == 0) + { +#ifdef USE_TLS + new_thread->p_stackaddr = stack_addr; +#else + new_thread = (pthread_descr) stack_addr; +#endif + break; +#ifndef __ARCH_USE_MMU__ + } else { + /* When there is MMU, mmap () is used to allocate the stack. If one + * segment is already mapped, we should continue to see if we can + * use the next one. However, when there is no MMU, malloc () is used. + * It's waste of CPU cycles to continue to try if it fails. */ + return EAGAIN; +#endif + } + } + __pthread_handles_num++; + /* Allocate new thread identifier */ + pthread_threads_counter += PTHREAD_THREADS_MAX; + new_thread_id = sseg + pthread_threads_counter; + /* Initialize the thread descriptor. Elements which have to be + initialized to zero already have this value. */ +#if !defined USE_TLS || !TLS_DTV_AT_TP + new_thread->p_header.data.tcb = new_thread; + new_thread->p_header.data.self = new_thread; +#endif +#if TLS_MULTIPLE_THREADS_IN_TCB || !defined USE_TLS || !TLS_DTV_AT_TP + new_thread->p_multiple_threads = 1; +#endif + new_thread->p_tid = new_thread_id; + new_thread->p_lock = &(__pthread_handles[sseg].h_lock); + new_thread->p_cancelstate = PTHREAD_CANCEL_ENABLE; + new_thread->p_canceltype = PTHREAD_CANCEL_DEFERRED; +#if !(USE_TLS && HAVE___THREAD) + new_thread->p_errnop = &new_thread->p_errno; + new_thread->p_h_errnop = &new_thread->p_h_errno; + new_thread->p_resp = &new_thread->p_res; +#endif + new_thread->p_guardaddr = guardaddr; + new_thread->p_guardsize = guardsize; + new_thread->p_nr = sseg; + new_thread->p_inheritsched = attr ? attr->__inheritsched : 0; + new_thread->p_alloca_cutoff = stksize / 4 > __MAX_ALLOCA_CUTOFF + ? __MAX_ALLOCA_CUTOFF : stksize / 4; + /* Initialize the thread handle */ + __pthread_init_lock(&__pthread_handles[sseg].h_lock); + __pthread_handles[sseg].h_descr = new_thread; + __pthread_handles[sseg].h_bottom = new_thread_bottom; + /* Determine scheduling parameters for the thread */ + new_thread->p_start_args.schedpolicy = -1; + if (attr != NULL) { + new_thread->p_detached = attr->__detachstate; + new_thread->p_userstack = attr->__stackaddr_set; + + switch(attr->__inheritsched) { + case PTHREAD_EXPLICIT_SCHED: + new_thread->p_start_args.schedpolicy = attr->__schedpolicy; + memcpy (&new_thread->p_start_args.schedparam, &attr->__schedparam, + sizeof (struct sched_param)); + break; + case PTHREAD_INHERIT_SCHED: + new_thread->p_start_args.schedpolicy = __sched_getscheduler(father_pid); + __sched_getparam(father_pid, &new_thread->p_start_args.schedparam); + break; + } + new_thread->p_priority = + new_thread->p_start_args.schedparam.sched_priority; + } + /* Finish setting up arguments to pthread_start_thread */ + new_thread->p_start_args.start_routine = start_routine; + new_thread->p_start_args.arg = arg; + new_thread->p_start_args.mask = *mask; + /* Make the new thread ID available already now. If any of the later + functions fail we return an error value and the caller must not use + the stored thread ID. */ + *thread = new_thread_id; + /* Raise priority of thread manager if needed */ + __pthread_manager_adjust_prio(new_thread->p_priority); + /* Do the cloning. We have to use two different functions depending + on whether we are debugging or not. */ + pid = 0; /* Note that the thread never can have PID zero. */ + if (report_events) + { + /* See whether the TD_CREATE event bit is set in any of the + masks. */ + int idx = __td_eventword (TD_CREATE); + uint32_t mask = __td_eventmask (TD_CREATE); + + if ((mask & (__pthread_threads_events.event_bits[idx] + | event_maskp->event_bits[idx])) != 0) + { + /* Lock the mutex the child will use now so that it will stop. */ + __pthread_lock(new_thread->p_lock, NULL); + + /* We have to report this event. */ +#ifdef NEED_SEPARATE_REGISTER_STACK + /* Perhaps this version should be used on all platforms. But + this requires that __clone2 be uniformly supported + everywhere. + + And there is some argument for changing the __clone2 + interface to pass sp and bsp instead, making it more IA64 + specific, but allowing stacks to grow outward from each + other, to get less paging and fewer mmaps. */ + pid = __clone2(pthread_start_thread_event, + (void **)new_thread_bottom, + (char *)stack_addr - new_thread_bottom, + CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_SYSVSEM | + __pthread_sig_cancel, new_thread); +#elif _STACK_GROWS_UP + pid = __clone(pthread_start_thread_event, (void *) new_thread_bottom, + CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_SYSVSEM | + __pthread_sig_cancel, new_thread); +#else + pid = __clone(pthread_start_thread_event, stack_addr, + CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_SYSVSEM | + __pthread_sig_cancel, new_thread); +#endif + saved_errno = errno; + if (pid != -1) + { + /* Now fill in the information about the new thread in + the newly created thread's data structure. We cannot let + the new thread do this since we don't know whether it was + already scheduled when we send the event. */ + new_thread->p_eventbuf.eventdata = new_thread; + new_thread->p_eventbuf.eventnum = TD_CREATE; + __pthread_last_event = new_thread; + + /* We have to set the PID here since the callback function + in the debug library will need it and we cannot guarantee + the child got scheduled before the debugger. */ + new_thread->p_pid = pid; + + /* Now call the function which signals the event. */ + __linuxthreads_create_event (); + + /* Now restart the thread. */ + __pthread_unlock(new_thread->p_lock); + } + } + } + if (pid == 0) + { +#ifdef NEED_SEPARATE_REGISTER_STACK + pid = __clone2(pthread_start_thread, + (void **)new_thread_bottom, + (char *)stack_addr - new_thread_bottom, + CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_SYSVSEM | + __pthread_sig_cancel, new_thread); +#elif _STACK_GROWS_UP + pid = __clone(pthread_start_thread, (void *) new_thread_bottom, + CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_SYSVSEM | + __pthread_sig_cancel, new_thread); +#else + pid = __clone(pthread_start_thread, stack_addr, + CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_SYSVSEM | + __pthread_sig_cancel, new_thread); +#endif /* !NEED_SEPARATE_REGISTER_STACK */ + saved_errno = errno; + } + /* Check if cloning succeeded */ + if (pid == -1) { + /* Free the stack if we allocated it */ + if (attr == NULL || !attr->__stackaddr_set) + { +#ifdef NEED_SEPARATE_REGISTER_STACK + size_t stacksize = ((char *)(new_thread->p_guardaddr) + - new_thread_bottom); + munmap((caddr_t)new_thread_bottom, + 2 * stacksize + new_thread->p_guardsize); +#elif _STACK_GROWS_UP +# ifdef USE_TLS + size_t stacksize = guardaddr - stack_addr; + munmap(stack_addr, stacksize + guardsize); +# else + size_t stacksize = guardaddr - (char *)new_thread; + munmap(new_thread, stacksize + guardsize); +# endif +#else +# ifdef USE_TLS + size_t stacksize = stack_addr - new_thread_bottom; +# else + size_t stacksize = (char *)(new_thread+1) - new_thread_bottom; +# endif + munmap(new_thread_bottom - guardsize, guardsize + stacksize); +#endif + } +#ifdef USE_TLS +# if defined(TLS_DTV_AT_TP) + new_thread = (pthread_descr) ((char *) new_thread + TLS_PRE_TCB_SIZE); +# endif + _dl_deallocate_tls (new_thread, true); +#endif + __pthread_handles[sseg].h_descr = NULL; + __pthread_handles[sseg].h_bottom = NULL; + __pthread_handles_num--; + return saved_errno; + } + /* Insert new thread in doubly linked list of active threads */ + new_thread->p_prevlive = __pthread_main_thread; + new_thread->p_nextlive = __pthread_main_thread->p_nextlive; + __pthread_main_thread->p_nextlive->p_prevlive = new_thread; + __pthread_main_thread->p_nextlive = new_thread; + /* Set pid field of the new thread, in case we get there before the + child starts. */ + new_thread->p_pid = pid; + return 0; +} + + +/* Try to free the resources of a thread when requested by pthread_join + or pthread_detach on a terminated thread. */ + +static void pthread_free(pthread_descr th) +{ + pthread_handle handle; + pthread_readlock_info *iter, *next; + + ASSERT(th->p_exited); + /* Make the handle invalid */ + handle = thread_handle(th->p_tid); + __pthread_lock(&handle->h_lock, NULL); + handle->h_descr = NULL; + handle->h_bottom = (char *)(-1L); + __pthread_unlock(&handle->h_lock); +#ifdef FREE_THREAD + FREE_THREAD(th, th->p_nr); +#endif + /* One fewer threads in __pthread_handles */ + __pthread_handles_num--; + + /* Destroy read lock list, and list of free read lock structures. + If the former is not empty, it means the thread exited while + holding read locks! */ + + for (iter = th->p_readlock_list; iter != NULL; iter = next) + { + next = iter->pr_next; + free(iter); + } + + for (iter = th->p_readlock_free; iter != NULL; iter = next) + { + next = iter->pr_next; + free(iter); + } + + /* If initial thread, nothing to free */ + if (!th->p_userstack) + { + size_t guardsize = th->p_guardsize; + /* Free the stack and thread descriptor area */ + char *guardaddr = th->p_guardaddr; +#ifdef _STACK_GROWS_UP +# ifdef USE_TLS + size_t stacksize = guardaddr - th->p_stackaddr; + guardaddr = th->p_stackaddr; +# else + size_t stacksize = guardaddr - (char *)th; + guardaddr = (char *)th; +# endif +#else + /* Guardaddr is always set, even if guardsize is 0. This allows + us to compute everything else. */ +# ifdef USE_TLS + size_t stacksize = th->p_stackaddr - guardaddr - guardsize; +# else + size_t stacksize = (char *)(th+1) - guardaddr - guardsize; +# endif +# ifdef NEED_SEPARATE_REGISTER_STACK + /* Take account of the register stack, which is below guardaddr. */ + guardaddr -= stacksize; + stacksize *= 2; +# endif +#endif + /* Unmap the stack. */ + munmap(guardaddr, stacksize + guardsize); + + } + +#ifdef USE_TLS +# if defined(TLS_DTV_AT_TP) + th = (pthread_descr) ((char *) th + TLS_PRE_TCB_SIZE); +# endif + _dl_deallocate_tls (th, true); +#endif +} + +/* Handle threads that have exited */ + +static void pthread_exited(pid_t pid) +{ + pthread_descr th; + int detached; + /* Find thread with that pid */ + for (th = __pthread_main_thread->p_nextlive; + th != __pthread_main_thread; + th = th->p_nextlive) { + if (th->p_pid == pid) { + /* Remove thread from list of active threads */ + th->p_nextlive->p_prevlive = th->p_prevlive; + th->p_prevlive->p_nextlive = th->p_nextlive; + /* Mark thread as exited, and if detached, free its resources */ + __pthread_lock(th->p_lock, NULL); + th->p_exited = 1; + /* If we have to signal this event do it now. */ + if (th->p_report_events) + { + /* See whether TD_REAP is in any of the mask. */ + int idx = __td_eventword (TD_REAP); + uint32_t mask = __td_eventmask (TD_REAP); + + if ((mask & (__pthread_threads_events.event_bits[idx] + | th->p_eventbuf.eventmask.event_bits[idx])) != 0) + { + /* Yep, we have to signal the reapage. */ + th->p_eventbuf.eventnum = TD_REAP; + th->p_eventbuf.eventdata = th; + __pthread_last_event = th; + + /* Now call the function to signal the event. */ + __linuxthreads_reap_event(); + } + } + detached = th->p_detached; + __pthread_unlock(th->p_lock); + if (detached) + pthread_free(th); + break; + } + } + /* If all threads have exited and the main thread is pending on a + pthread_exit, wake up the main thread and terminate ourselves. */ + if (main_thread_exiting && + __pthread_main_thread->p_nextlive == __pthread_main_thread) { + restart(__pthread_main_thread); + /* Same logic as REQ_MAIN_THREAD_EXIT. */ + } +} + +static void pthread_reap_children(void) +{ + pid_t pid; + int status; + + while ((pid = waitpid_not_cancel(-1, &status, WNOHANG | __WCLONE)) > 0) { + pthread_exited(pid); + if (WIFSIGNALED(status)) { + /* If a thread died due to a signal, send the same signal to + all other threads, including the main thread. */ + pthread_kill_all_threads(WTERMSIG(status), 1); + _exit(0); + } + } +} + +/* Try to free the resources of a thread when requested by pthread_join + or pthread_detach on a terminated thread. */ + +static void pthread_handle_free(pthread_t th_id) +{ + pthread_handle handle = thread_handle(th_id); + pthread_descr th; + + __pthread_lock(&handle->h_lock, NULL); + if (nonexisting_handle(handle, th_id)) { + /* pthread_reap_children has deallocated the thread already, + nothing needs to be done */ + __pthread_unlock(&handle->h_lock); + return; + } + th = handle->h_descr; + if (th->p_exited) { + __pthread_unlock(&handle->h_lock); + pthread_free(th); + } else { + /* The Unix process of the thread is still running. + Mark the thread as detached so that the thread manager will + deallocate its resources when the Unix process exits. */ + th->p_detached = 1; + __pthread_unlock(&handle->h_lock); + } +} + +/* Send a signal to all running threads */ + +static void pthread_kill_all_threads(int sig, int main_thread_also) +{ + pthread_descr th; + for (th = __pthread_main_thread->p_nextlive; + th != __pthread_main_thread; + th = th->p_nextlive) { + kill(th->p_pid, sig); + } + if (main_thread_also) { + kill(__pthread_main_thread->p_pid, sig); + } +} + +static void pthread_for_each_thread(void *arg, + void (*fn)(void *, pthread_descr)) +{ + pthread_descr th; + + for (th = __pthread_main_thread->p_nextlive; + th != __pthread_main_thread; + th = th->p_nextlive) { + fn(arg, th); + } + + fn(arg, __pthread_main_thread); +} + +/* Process-wide exit() */ + +static void pthread_handle_exit(pthread_descr issuing_thread, int exitcode) +{ + pthread_descr th; + __pthread_exit_requested = 1; + __pthread_exit_code = exitcode; + /* A forced asynchronous cancellation follows. Make sure we won't + get stuck later in the main thread with a system lock being held + by one of the cancelled threads. Ideally one would use the same + code as in pthread_atfork(), but we can't distinguish system and + user handlers there. */ + __flockfilelist(); + /* Send the CANCEL signal to all running threads, including the main + thread, but excluding the thread from which the exit request originated + (that thread must complete the exit, e.g. calling atexit functions + and flushing stdio buffers). */ + for (th = issuing_thread->p_nextlive; + th != issuing_thread; + th = th->p_nextlive) { + kill(th->p_pid, __pthread_sig_cancel); + } + /* Now, wait for all these threads, so that they don't become zombies + and their times are properly added to the thread manager's times. */ + for (th = issuing_thread->p_nextlive; + th != issuing_thread; + th = th->p_nextlive) { + waitpid(th->p_pid, NULL, __WCLONE); + } + __fresetlockfiles(); + restart(issuing_thread); + _exit(0); +} + +/* Handler for __pthread_sig_cancel in thread manager thread */ + +void __pthread_manager_sighandler(int sig) +{ + int kick_manager = terminated_children == 0 && main_thread_exiting; + terminated_children = 1; + + /* If the main thread is terminating, kick the thread manager loop + each time some threads terminate. This eliminates a two second + shutdown delay caused by the thread manager sleeping in the + call to __poll(). Instead, the thread manager is kicked into + action, reaps the outstanding threads and resumes the main thread + so that it can complete the shutdown. */ + + if (kick_manager) { + struct pthread_request request; + request.req_thread = 0; + request.req_kind = REQ_KICK; + TEMP_FAILURE_RETRY(write_not_cancel(__pthread_manager_request, + (char *) &request, sizeof(request))); + } +} + +/* Adjust priority of thread manager so that it always run at a priority + higher than all threads */ + +void __pthread_manager_adjust_prio(int thread_prio) +{ + struct sched_param param; + + if (thread_prio <= manager_thread->p_priority) return; + param.sched_priority = + thread_prio < __sched_get_priority_max(SCHED_FIFO) + ? thread_prio + 1 : thread_prio; + __sched_setscheduler(manager_thread->p_pid, SCHED_FIFO, ¶m); + manager_thread->p_priority = thread_prio; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/mutex.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/mutex.c new file mode 100644 index 00000000..3c97ea7d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/mutex.c @@ -0,0 +1,357 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +/* Mutexes */ + +#include +#include +#include +#include +#include +#include "pthread.h" +#include "internals.h" +#include "spinlock.h" +#include "queue.h" +#include "restart.h" + +int __pthread_mutex_init(pthread_mutex_t * mutex, + const pthread_mutexattr_t * mutex_attr) +{ + __pthread_init_lock(&mutex->__m_lock); + mutex->__m_kind = + mutex_attr == NULL ? PTHREAD_MUTEX_TIMED_NP : mutex_attr->__mutexkind; + mutex->__m_count = 0; + mutex->__m_owner = NULL; + return 0; +} +strong_alias (__pthread_mutex_init, pthread_mutex_init) + +int __pthread_mutex_destroy(pthread_mutex_t * mutex) +{ + switch (mutex->__m_kind) { + case PTHREAD_MUTEX_ADAPTIVE_NP: + case PTHREAD_MUTEX_RECURSIVE_NP: + if ((mutex->__m_lock.__status & 1) != 0) + return EBUSY; + return 0; + case PTHREAD_MUTEX_ERRORCHECK_NP: + case PTHREAD_MUTEX_TIMED_NP: + if (mutex->__m_lock.__status != 0) + return EBUSY; + return 0; + default: + return EINVAL; + } +} +strong_alias (__pthread_mutex_destroy, pthread_mutex_destroy) + +int __pthread_mutex_trylock(pthread_mutex_t * mutex) +{ + pthread_descr self; + int retcode; + + switch(mutex->__m_kind) { + case PTHREAD_MUTEX_ADAPTIVE_NP: + retcode = __pthread_trylock(&mutex->__m_lock); + return retcode; + case PTHREAD_MUTEX_RECURSIVE_NP: + self = thread_self(); + if (mutex->__m_owner == self) { + mutex->__m_count++; + return 0; + } + retcode = __pthread_trylock(&mutex->__m_lock); + if (retcode == 0) { + mutex->__m_owner = self; + mutex->__m_count = 0; + } + return retcode; + case PTHREAD_MUTEX_ERRORCHECK_NP: + retcode = __pthread_alt_trylock(&mutex->__m_lock); + if (retcode == 0) { + mutex->__m_owner = thread_self(); + } + return retcode; + case PTHREAD_MUTEX_TIMED_NP: + retcode = __pthread_alt_trylock(&mutex->__m_lock); + return retcode; + default: + return EINVAL; + } +} +strong_alias (__pthread_mutex_trylock, pthread_mutex_trylock) + +int __pthread_mutex_lock(pthread_mutex_t * mutex) +{ + pthread_descr self; + + switch(mutex->__m_kind) { + case PTHREAD_MUTEX_ADAPTIVE_NP: + __pthread_lock(&mutex->__m_lock, NULL); + return 0; + case PTHREAD_MUTEX_RECURSIVE_NP: + self = thread_self(); + if (mutex->__m_owner == self) { + mutex->__m_count++; + return 0; + } + __pthread_lock(&mutex->__m_lock, self); + mutex->__m_owner = self; + mutex->__m_count = 0; + return 0; + case PTHREAD_MUTEX_ERRORCHECK_NP: + self = thread_self(); + if (mutex->__m_owner == self) return EDEADLK; + __pthread_alt_lock(&mutex->__m_lock, self); + mutex->__m_owner = self; + return 0; + case PTHREAD_MUTEX_TIMED_NP: + __pthread_alt_lock(&mutex->__m_lock, NULL); + return 0; + default: + return EINVAL; + } +} +strong_alias (__pthread_mutex_lock, pthread_mutex_lock) + +int __pthread_mutex_timedlock (pthread_mutex_t *mutex, + const struct timespec *abstime) +{ + pthread_descr self; + int res; + + if (__builtin_expect (abstime->tv_nsec, 0) < 0 + || __builtin_expect (abstime->tv_nsec, 0) >= 1000000000) + return EINVAL; + + switch(mutex->__m_kind) { + case PTHREAD_MUTEX_ADAPTIVE_NP: + __pthread_lock(&mutex->__m_lock, NULL); + return 0; + case PTHREAD_MUTEX_RECURSIVE_NP: + self = thread_self(); + if (mutex->__m_owner == self) { + mutex->__m_count++; + return 0; + } + __pthread_lock(&mutex->__m_lock, self); + mutex->__m_owner = self; + mutex->__m_count = 0; + return 0; + case PTHREAD_MUTEX_ERRORCHECK_NP: + self = thread_self(); + if (mutex->__m_owner == self) return EDEADLK; + res = __pthread_alt_timedlock(&mutex->__m_lock, self, abstime); + if (res != 0) + { + mutex->__m_owner = self; + return 0; + } + return ETIMEDOUT; + case PTHREAD_MUTEX_TIMED_NP: + /* Only this type supports timed out lock. */ + return (__pthread_alt_timedlock(&mutex->__m_lock, NULL, abstime) + ? 0 : ETIMEDOUT); + default: + return EINVAL; + } +} +strong_alias (__pthread_mutex_timedlock, pthread_mutex_timedlock) + +int __pthread_mutex_unlock(pthread_mutex_t * mutex) +{ + switch (mutex->__m_kind) { + case PTHREAD_MUTEX_ADAPTIVE_NP: + __pthread_unlock(&mutex->__m_lock); + return 0; + case PTHREAD_MUTEX_RECURSIVE_NP: + if (mutex->__m_owner != thread_self()) + return EPERM; + if (mutex->__m_count > 0) { + mutex->__m_count--; + return 0; + } + mutex->__m_owner = NULL; + __pthread_unlock(&mutex->__m_lock); + return 0; + case PTHREAD_MUTEX_ERRORCHECK_NP: + if (mutex->__m_owner != thread_self() || mutex->__m_lock.__status == 0) + return EPERM; + mutex->__m_owner = NULL; + __pthread_alt_unlock(&mutex->__m_lock); + return 0; + case PTHREAD_MUTEX_TIMED_NP: + __pthread_alt_unlock(&mutex->__m_lock); + return 0; + default: + return EINVAL; + } +} +strong_alias (__pthread_mutex_unlock, pthread_mutex_unlock) + +int __pthread_mutexattr_init(pthread_mutexattr_t *attr) +{ + attr->__mutexkind = PTHREAD_MUTEX_TIMED_NP; + return 0; +} +strong_alias (__pthread_mutexattr_init, pthread_mutexattr_init) + +int __pthread_mutexattr_destroy(pthread_mutexattr_t *attr) +{ + return 0; +} +strong_alias (__pthread_mutexattr_destroy, pthread_mutexattr_destroy) + +int __pthread_mutexattr_settype(pthread_mutexattr_t *attr, int kind) +{ + if (kind != PTHREAD_MUTEX_ADAPTIVE_NP + && kind != PTHREAD_MUTEX_RECURSIVE_NP + && kind != PTHREAD_MUTEX_ERRORCHECK_NP + && kind != PTHREAD_MUTEX_TIMED_NP) + return EINVAL; + attr->__mutexkind = kind; + return 0; +} +weak_alias (__pthread_mutexattr_settype, pthread_mutexattr_settype) +strong_alias ( __pthread_mutexattr_settype, __pthread_mutexattr_setkind_np) +weak_alias (__pthread_mutexattr_setkind_np, pthread_mutexattr_setkind_np) + +int __pthread_mutexattr_gettype(const pthread_mutexattr_t *attr, int *kind) +{ + *kind = attr->__mutexkind; + return 0; +} +weak_alias (__pthread_mutexattr_gettype, pthread_mutexattr_gettype) +strong_alias (__pthread_mutexattr_gettype, __pthread_mutexattr_getkind_np) +weak_alias (__pthread_mutexattr_getkind_np, pthread_mutexattr_getkind_np) + +int __pthread_mutexattr_getpshared (const pthread_mutexattr_t *attr, + int *pshared) +{ + *pshared = PTHREAD_PROCESS_PRIVATE; + return 0; +} +weak_alias (__pthread_mutexattr_getpshared, pthread_mutexattr_getpshared) + +int __pthread_mutexattr_setpshared (pthread_mutexattr_t *attr, int pshared) +{ + if (pshared != PTHREAD_PROCESS_PRIVATE && pshared != PTHREAD_PROCESS_SHARED) + return EINVAL; + + /* For now it is not possible to shared a conditional variable. */ + if (pshared != PTHREAD_PROCESS_PRIVATE) + return ENOSYS; + + return 0; +} +weak_alias (__pthread_mutexattr_setpshared, pthread_mutexattr_setpshared) + +/* Once-only execution */ + +static pthread_mutex_t once_masterlock = PTHREAD_MUTEX_INITIALIZER; +static pthread_cond_t once_finished = PTHREAD_COND_INITIALIZER; +static int fork_generation = 0; /* Child process increments this after fork. */ + +enum { NEVER = 0, IN_PROGRESS = 1, DONE = 2 }; + +/* If a thread is canceled while calling the init_routine out of + pthread once, this handler will reset the once_control variable + to the NEVER state. */ + +static void pthread_once_cancelhandler(void *arg) +{ + pthread_once_t *once_control = arg; + + pthread_mutex_lock(&once_masterlock); + *once_control = NEVER; + pthread_mutex_unlock(&once_masterlock); + pthread_cond_broadcast(&once_finished); +} + +int __pthread_once(pthread_once_t * once_control, void (*init_routine)(void)) +{ + /* flag for doing the condition broadcast outside of mutex */ + int state_changed; + + /* Test without locking first for speed */ + if (*once_control == DONE) { + READ_MEMORY_BARRIER(); + return 0; + } + /* Lock and test again */ + + state_changed = 0; + + pthread_mutex_lock(&once_masterlock); + + /* If this object was left in an IN_PROGRESS state in a parent + process (indicated by stale generation field), reset it to NEVER. */ + if ((*once_control & 3) == IN_PROGRESS && (*once_control & ~3) != fork_generation) + *once_control = NEVER; + + /* If init_routine is being called from another routine, wait until + it completes. */ + while ((*once_control & 3) == IN_PROGRESS) { + pthread_cond_wait(&once_finished, &once_masterlock); + } + /* Here *once_control is stable and either NEVER or DONE. */ + if (*once_control == NEVER) { + *once_control = IN_PROGRESS | fork_generation; + pthread_mutex_unlock(&once_masterlock); + pthread_cleanup_push(pthread_once_cancelhandler, once_control); + init_routine(); + pthread_cleanup_pop(0); + pthread_mutex_lock(&once_masterlock); + WRITE_MEMORY_BARRIER(); + *once_control = DONE; + state_changed = 1; + } + pthread_mutex_unlock(&once_masterlock); + + if (state_changed) + pthread_cond_broadcast(&once_finished); + + return 0; +} +strong_alias (__pthread_once, pthread_once) + +/* + * Handle the state of the pthread_once mechanism across forks. The + * once_masterlock is acquired in the parent process prior to a fork to ensure + * that no thread is in the critical region protected by the lock. After the + * fork, the lock is released. In the child, the lock and the condition + * variable are simply reset. The child also increments its generation + * counter which lets pthread_once calls detect stale IN_PROGRESS states + * and reset them back to NEVER. + */ + +void __pthread_once_fork_prepare(void) +{ + pthread_mutex_lock(&once_masterlock); +} + +void __pthread_once_fork_parent(void) +{ + pthread_mutex_unlock(&once_masterlock); +} + +void __pthread_once_fork_child(void) +{ + pthread_mutex_init(&once_masterlock, NULL); + pthread_cond_init(&once_finished, NULL); + if (fork_generation <= INT_MAX - 4) + fork_generation += 4; /* leave least significant two bits zero */ + else + fork_generation = 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/pt-machine.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/pt-machine.c new file mode 100644 index 00000000..5cd477ce --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/pt-machine.c @@ -0,0 +1,25 @@ +/* "Instantiation of machine-dependent pthreads inline functions. + Copyright (C) 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#define PT_EI + +extern long int testandset (int *spinlock); +extern int __compare_and_swap (long int *p, long int oldval, long int newval); + +#include diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/ptcleanup.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/ptcleanup.c new file mode 100644 index 00000000..6213b56f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/ptcleanup.c @@ -0,0 +1,74 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1998 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +/* Redefine siglongjmp and longjmp so that they interact correctly + with cleanup handlers */ + +#define NO_PTR_DEMANGLE + +#include +#include "pthread.h" +#include "internals.h" +#ifndef NO_PTR_DEMANGLE +#include +#define __JMPBUF_UNWINDS(a,b,c) _JMPBUF_UNWINDS(a,b,c) +#else +#define __JMPBUF_UNWINDS(a,b,c) _JMPBUF_UNWINDS(a,b) +#endif + +#ifndef NO_PTR_DEMANGLE +static __inline__ uintptr_t +demangle_ptr (uintptr_t x) +{ +#ifdef PTR_DEMANGLE + PTR_DEMANGLE (x); +#endif + return x; +} +#else +#define demangle_ptr(x) x +#endif + +void __pthread_cleanup_upto (__jmp_buf target, char *targetframe) +{ + pthread_descr self = thread_self(); + struct _pthread_cleanup_buffer * c; + + for (c = THREAD_GETMEM(self, p_cleanup); + c != NULL && __JMPBUF_UNWINDS(target, c, demangle_ptr); + c = c->__prev) + { +#if _STACK_GROWS_DOWN + if ((char *) c <= targetframe) + { + c = NULL; + break; + } +#elif _STACK_GROWS_UP + if ((char *) c >= targetframe) + { + c = NULL; + break; + } +#else +# error "Define either _STACK_GROWS_DOWN or _STACK_GROWS_UP" +#endif + c->__routine(c->__arg); + } + THREAD_SETMEM(self, p_cleanup, c); + if (THREAD_GETMEM(self, p_in_sighandler) + && __JMPBUF_UNWINDS(target, THREAD_GETMEM(self, p_in_sighandler), + demangle_ptr)) + THREAD_SETMEM(self, p_in_sighandler, NULL); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/ptclock_gettime.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/ptclock_gettime.c new file mode 100644 index 00000000..755f83d1 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/ptclock_gettime.c @@ -0,0 +1,69 @@ +/* Copyright (C) 2001, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include "internals.h" +#include "spinlock.h" + + +#if HP_TIMING_AVAIL +int +__pthread_clock_gettime (clockid_t clock_id, hp_timing_t freq, + struct timespec *tp) +{ + hp_timing_t tsc, cpuclock_offset; + pthread_descr self = thread_self (); + pthread_t thread = ((unsigned int) clock_id) >> CLOCK_IDFIELD_SIZE; + const unsigned int mask = ~0U >> CLOCK_IDFIELD_SIZE; + + if (thread == 0 || (THREAD_GETMEM (self, p_tid) & mask) == thread) + cpuclock_offset = THREAD_GETMEM (self, p_cpuclock_offset); + else + { + pthread_descr th; + pthread_handle handle = thread_handle (thread); + __pthread_lock (&handle->h_lock, NULL); + th = handle->h_descr; + if (th == NULL || (th->p_tid & mask) != thread || th->p_terminated) + { + __pthread_unlock (&handle->h_lock); + __set_errno (EINVAL); + return -1; + } + cpuclock_offset = th->p_cpuclock_offset; + __pthread_unlock (&handle->h_lock); + } + + /* Get the current counter. */ + HP_TIMING_NOW (tsc); + + /* Compute the offset since the start time of the process. */ + tsc -= cpuclock_offset; + + /* Compute the seconds. */ + tp->tv_sec = tsc / freq; + + /* And the nanoseconds. This computation should be stable until + we get machines with about 16GHz frequency. */ + tp->tv_nsec = ((tsc % freq) * 1000000000ull) / freq; + + return 0; +} +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/ptclock_settime.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/ptclock_settime.c new file mode 100644 index 00000000..a4f218c7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/ptclock_settime.c @@ -0,0 +1,55 @@ +/* Copyright (C) 2001, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include "internals.h" +#include "spinlock.h" + + +#if HP_TIMING_AVAIL +int +__pthread_clock_settime (clockid_t clock_id, hp_timing_t offset) +{ + pthread_descr self = thread_self (); + pthread_t thread = ((unsigned int) clock_id) >> CLOCK_IDFIELD_SIZE; + const unsigned int mask = ~0U >> CLOCK_IDFIELD_SIZE; + + if (thread == 0 || (THREAD_GETMEM (self, p_tid) & mask) == thread) + /* Our own clock. */ + THREAD_SETMEM (self, p_cpuclock_offset, offset); + else + { + pthread_descr th; + pthread_handle handle = thread_handle (thread); + __pthread_lock (&handle->h_lock, NULL); + th = handle->h_descr; + if (th == NULL || (th->p_tid & mask) != thread || th->p_terminated) + { + __pthread_unlock (&handle->h_lock); + __set_errno (EINVAL); + return -1; + } + th->p_cpuclock_offset = offset; + __pthread_unlock (&handle->h_lock); + } + + return 0; +} +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/ptfork.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/ptfork.c new file mode 100644 index 00000000..853aeea9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/ptfork.c @@ -0,0 +1,94 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +/* The "atfork" stuff */ + +#include +#include +#include +#include +#include "pthread.h" +#include "internals.h" +#include +#include "fork.h" + +extern int __libc_fork (void); + +pid_t __pthread_fork (struct fork_block *b) +{ + pid_t pid; + list_t *runp; + + __libc_lock_lock (b->lock); + + /* Run all the registered preparation handlers. In reverse order. */ + list_for_each_prev (runp, &b->prepare_list) + { + struct fork_handler *curp; + curp = list_entry (runp, struct fork_handler, list); + curp->handler (); + } + + __pthread_once_fork_prepare(); + __flockfilelist(); + + pid = ARCH_FORK (); + + if (pid == 0) { + __pthread_reset_main_thread(); + + __fresetlockfiles(); + __pthread_once_fork_child(); + + /* Run the handlers registered for the child. */ + list_for_each (runp, &b->child_list) + { + struct fork_handler *curp; + curp = list_entry (runp, struct fork_handler, list); + curp->handler (); + } + + __libc_lock_init (b->lock); + } else { + __funlockfilelist(); + __pthread_once_fork_parent(); + + /* Run the handlers registered for the parent. */ + list_for_each (runp, &b->parent_list) + { + struct fork_handler *curp; + curp = list_entry (runp, struct fork_handler, list); + curp->handler (); + } + + __libc_lock_unlock (b->lock); + } + + return pid; +} + +/* psm: have no idea why these are here, sjhill? */ +#if 0 /*def SHARED*/ +pid_t __fork (void) +{ + return __libc_fork (); +} +weak_alias (__fork, fork) + +pid_t __vfork(void) +{ + return __libc_fork (); +} +weak_alias (__vfork, vfork) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/pthandles.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/pthandles.c new file mode 100644 index 00000000..acc47e28 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/pthandles.c @@ -0,0 +1,5 @@ +#include "pthread.h" +#include "internals.h" + +/* Array of active threads. Entry 0 is reserved for the initial thread. */ +struct pthread_handle_struct __pthread_handles[PTHREAD_THREADS_MAX]; diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/pthread.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/pthread.c new file mode 100644 index 00000000..db436342 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/pthread.c @@ -0,0 +1,1390 @@ + +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +/* Thread creation, initialization, and basic low-level routines */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "pthread.h" +#include "internals.h" +#include "spinlock.h" +#include "restart.h" +#include "smp.h" +#include + +/* Sanity check. */ +#if !defined __SIGRTMIN || (__SIGRTMAX - __SIGRTMIN) < 3 +# error "This must not happen" +#endif + +/* mods for uClibc: __libc_sigaction is not in any standard headers */ +extern __typeof(sigaction) __libc_sigaction; + +#if !(USE_TLS && HAVE___THREAD) +/* These variables are used by the setup code. */ +extern int _errno; +extern int _h_errno; + +# if defined __UCLIBC_HAS_IPv4__ || defined __UCLIBC_HAS_IPV6__ +/* We need the global/static resolver state here. */ +# include +# undef _res +extern struct __res_state *__resp; +# endif +#endif + +#ifdef USE_TLS + +/* We need only a few variables. */ +#define manager_thread __pthread_manager_threadp +pthread_descr __pthread_manager_threadp attribute_hidden; + +#else + +/* Descriptor of the initial thread */ + +struct _pthread_descr_struct __pthread_initial_thread = { + .p_header.data.self = &__pthread_initial_thread, + .p_nextlive = &__pthread_initial_thread, + .p_prevlive = &__pthread_initial_thread, + .p_tid = PTHREAD_THREADS_MAX, + .p_lock = &__pthread_handles[0].h_lock, + .p_start_args = PTHREAD_START_ARGS_INITIALIZER(NULL), +#if !(USE_TLS && HAVE___THREAD) + .p_errnop = &_errno, + .p_h_errnop = &_h_errno, +#endif + .p_userstack = 1, + .p_resume_count = __ATOMIC_INITIALIZER, + .p_alloca_cutoff = __MAX_ALLOCA_CUTOFF +}; + +/* Descriptor of the manager thread; none of this is used but the error + variables, the p_pid and p_priority fields, + and the address for identification. */ + +#define manager_thread (&__pthread_manager_thread) +struct _pthread_descr_struct __pthread_manager_thread = { + .p_header.data.self = &__pthread_manager_thread, + .p_header.data.multiple_threads = 1, + .p_lock = &__pthread_handles[1].h_lock, + .p_start_args = PTHREAD_START_ARGS_INITIALIZER(__pthread_manager), +#if !(USE_TLS && HAVE___THREAD) + .p_errnop = &__pthread_manager_thread.p_errno, +#endif + .p_nr = 1, + .p_resume_count = __ATOMIC_INITIALIZER, + .p_alloca_cutoff = PTHREAD_STACK_MIN / 4 +}; +#endif + +/* Pointer to the main thread (the father of the thread manager thread) */ +/* Originally, this is the initial thread, but this changes after fork() */ + +#ifdef USE_TLS +pthread_descr __pthread_main_thread; +#else +pthread_descr __pthread_main_thread = &__pthread_initial_thread; +#endif + +/* Limit between the stack of the initial thread (above) and the + stacks of other threads (below). Aligned on a STACK_SIZE boundary. */ + +char *__pthread_initial_thread_bos; + +/* File descriptor for sending requests to the thread manager. */ +/* Initially -1, meaning that the thread manager is not running. */ + +int __pthread_manager_request = -1; + +int __pthread_multiple_threads attribute_hidden; + +/* Other end of the pipe for sending requests to the thread manager. */ + +int __pthread_manager_reader; + +/* Limits of the thread manager stack */ + +char *__pthread_manager_thread_bos; +char *__pthread_manager_thread_tos; + +/* For process-wide exit() */ + +int __pthread_exit_requested; +int __pthread_exit_code; + +/* Maximum stack size. */ +size_t __pthread_max_stacksize; + +/* Nozero if the machine has more than one processor. */ +int __pthread_smp_kernel; + + +#if !__ASSUME_REALTIME_SIGNALS +/* Pointers that select new or old suspend/resume functions + based on availability of rt signals. */ + +void (*__pthread_restart)(pthread_descr) = __pthread_restart_old; +void (*__pthread_suspend)(pthread_descr) = __pthread_suspend_old; +int (*__pthread_timedsuspend)(pthread_descr, const struct timespec *) = __pthread_timedsuspend_old; +#endif /* __ASSUME_REALTIME_SIGNALS */ + +/* Communicate relevant LinuxThreads constants to gdb */ + +const int __pthread_threads_max = PTHREAD_THREADS_MAX; +const int __pthread_sizeof_handle = sizeof(struct pthread_handle_struct); +const int __pthread_offsetof_descr = offsetof(struct pthread_handle_struct, + h_descr); +const int __pthread_offsetof_pid = offsetof(struct _pthread_descr_struct, + p_pid); +const int __linuxthreads_pthread_sizeof_descr + = sizeof(struct _pthread_descr_struct); + +const int __linuxthreads_initial_report_events; + +const char __linuxthreads_version[] = VERSION; + +/* Forward declarations */ + +static void pthread_onexit_process(int retcode, void *arg); +#ifndef HAVE_Z_NODELETE +static void pthread_atexit_process(void *arg, int retcode); +static void pthread_atexit_retcode(void *arg, int retcode); +#endif +static void pthread_handle_sigcancel(int sig); +static void pthread_handle_sigrestart(int sig); +static void pthread_handle_sigdebug(int sig); + +/* Signal numbers used for the communication. + In these variables we keep track of the used variables. If the + platform does not support any real-time signals we will define the + values to some unreasonable value which will signal failing of all + the functions below. */ +int __pthread_sig_restart = __SIGRTMIN; +int __pthread_sig_cancel = __SIGRTMIN + 1; +int __pthread_sig_debug = __SIGRTMIN + 2; + +extern int __libc_current_sigrtmin_private (void); + +#if !__ASSUME_REALTIME_SIGNALS +static int rtsigs_initialized; + +static void +init_rtsigs (void) +{ + if (rtsigs_initialized) + return; + + if (__libc_current_sigrtmin_private () == -1) + { + __pthread_sig_restart = SIGUSR1; + __pthread_sig_cancel = SIGUSR2; + __pthread_sig_debug = 0; + } + else + { + __pthread_restart = __pthread_restart_new; + __pthread_suspend = __pthread_wait_for_restart_signal; + __pthread_timedsuspend = __pthread_timedsuspend_new; + } + + rtsigs_initialized = 1; +} +#endif + + +/* Initialize the pthread library. + Initialization is split in two functions: + - a constructor function that blocks the __pthread_sig_restart signal + (must do this very early, since the program could capture the signal + mask with e.g. sigsetjmp before creating the first thread); + - a regular function called from pthread_create when needed. */ + +static void pthread_initialize(void) __attribute__((constructor)); + +#ifndef HAVE_Z_NODELETE +extern void *__dso_handle __attribute__ ((weak)); +#endif + + +#if defined USE_TLS && !defined SHARED +extern void __libc_setup_tls (size_t tcbsize, size_t tcbalign); +#endif + +struct pthread_functions __pthread_functions = + { +#if !(USE_TLS && HAVE___THREAD) + .ptr_pthread_internal_tsd_set = __pthread_internal_tsd_set, + .ptr_pthread_internal_tsd_get = __pthread_internal_tsd_get, + .ptr_pthread_internal_tsd_address = __pthread_internal_tsd_address, +#endif + .ptr_pthread_fork = __pthread_fork, + .ptr_pthread_attr_destroy = __pthread_attr_destroy, + .ptr_pthread_attr_init = __pthread_attr_init, + .ptr_pthread_attr_getdetachstate = __pthread_attr_getdetachstate, + .ptr_pthread_attr_setdetachstate = __pthread_attr_setdetachstate, + .ptr_pthread_attr_getinheritsched = __pthread_attr_getinheritsched, + .ptr_pthread_attr_setinheritsched = __pthread_attr_setinheritsched, + .ptr_pthread_attr_getschedparam = __pthread_attr_getschedparam, + .ptr_pthread_attr_setschedparam = __pthread_attr_setschedparam, + .ptr_pthread_attr_getschedpolicy = __pthread_attr_getschedpolicy, + .ptr_pthread_attr_setschedpolicy = __pthread_attr_setschedpolicy, + .ptr_pthread_attr_getscope = __pthread_attr_getscope, + .ptr_pthread_attr_setscope = __pthread_attr_setscope, + .ptr_pthread_condattr_destroy = __pthread_condattr_destroy, + .ptr_pthread_condattr_init = __pthread_condattr_init, + .ptr_pthread_cond_broadcast = __pthread_cond_broadcast, + .ptr_pthread_cond_destroy = __pthread_cond_destroy, + .ptr_pthread_cond_init = __pthread_cond_init, + .ptr_pthread_cond_signal = __pthread_cond_signal, + .ptr_pthread_cond_wait = __pthread_cond_wait, + .ptr_pthread_cond_timedwait = __pthread_cond_timedwait, + .ptr_pthread_equal = __pthread_equal, + .ptr___pthread_exit = __pthread_exit, + .ptr_pthread_getschedparam = __pthread_getschedparam, + .ptr_pthread_setschedparam = __pthread_setschedparam, + .ptr_pthread_mutex_destroy = __pthread_mutex_destroy, + .ptr_pthread_mutex_init = __pthread_mutex_init, + .ptr_pthread_mutex_lock = __pthread_mutex_lock, + .ptr_pthread_mutex_trylock = __pthread_mutex_trylock, + .ptr_pthread_mutex_unlock = __pthread_mutex_unlock, + .ptr_pthread_self = __pthread_self, + .ptr_pthread_setcancelstate = __pthread_setcancelstate, + .ptr_pthread_setcanceltype = __pthread_setcanceltype, + .ptr_pthread_do_exit = __pthread_do_exit, + .ptr_pthread_thread_self = __pthread_thread_self, + .ptr_pthread_cleanup_upto = __pthread_cleanup_upto, + .ptr_pthread_sigaction = __pthread_sigaction, + .ptr_pthread_sigwait = __pthread_sigwait, + .ptr_pthread_raise = __pthread_raise, + .ptr__pthread_cleanup_push = _pthread_cleanup_push, + .ptr__pthread_cleanup_push_defer = _pthread_cleanup_push_defer, + .ptr__pthread_cleanup_pop = _pthread_cleanup_pop, + .ptr__pthread_cleanup_pop_restore = _pthread_cleanup_pop_restore, + }; +#ifdef SHARED +# define ptr_pthread_functions &__pthread_functions +#else +# define ptr_pthread_functions NULL +#endif + +static int *__libc_multiple_threads_ptr; + +/* Do some minimal initialization which has to be done during the + startup of the C library. */ +void +__pthread_initialize_minimal(void) +{ +#ifdef USE_TLS + pthread_descr self; + + /* First of all init __pthread_handles[0] and [1] if needed. */ +# if __LT_SPINLOCK_INIT != 0 + __pthread_handles[0].h_lock = __LOCK_INITIALIZER; + __pthread_handles[1].h_lock = __LOCK_INITIALIZER; +# endif +# ifndef SHARED + /* Unlike in the dynamically linked case the dynamic linker has not + taken care of initializing the TLS data structures. */ + __libc_setup_tls (TLS_TCB_SIZE, TLS_TCB_ALIGN); +# elif !USE___THREAD + if (__builtin_expect (GL(dl_tls_dtv_slotinfo_list) == NULL, 0)) + { + tcbhead_t *tcbp; + + /* There is no actual TLS being used, so the thread register + was not initialized in the dynamic linker. */ + + /* We need to install special hooks so that the malloc and memalign + calls in _dl_tls_setup and _dl_allocate_tls won't cause full + malloc initialization that will try to set up its thread state. */ + + extern void __libc_malloc_pthread_startup (bool first_time); + __libc_malloc_pthread_startup (true); + + if (__builtin_expect (_dl_tls_setup (), 0) + || __builtin_expect ((tcbp = _dl_allocate_tls (NULL)) == NULL, 0)) + { + static const char msg[] = "\ +cannot allocate TLS data structures for initial thread\n"; + TEMP_FAILURE_RETRY (write_not_cancel (STDERR_FILENO, + msg, sizeof msg - 1)); + abort (); + } + const char *lossage = TLS_INIT_TP (tcbp, 0); + if (__builtin_expect (lossage != NULL, 0)) + { + static const char msg[] = "cannot set up thread-local storage: "; + const char nl = '\n'; + TEMP_FAILURE_RETRY (write_not_cancel (STDERR_FILENO, + msg, sizeof msg - 1)); + TEMP_FAILURE_RETRY (write_not_cancel (STDERR_FILENO, + lossage, strlen (lossage))); + TEMP_FAILURE_RETRY (write_not_cancel (STDERR_FILENO, &nl, 1)); + } + + /* Though it was allocated with libc's malloc, that was done without + the user's __malloc_hook installed. A later realloc that uses + the hooks might not work with that block from the plain malloc. + So we record this block as unfreeable just as the dynamic linker + does when it allocates the DTV before the libc malloc exists. */ + GL(dl_initial_dtv) = GET_DTV (tcbp); + + __libc_malloc_pthread_startup (false); + } +# endif + + self = THREAD_SELF; + + /* The memory for the thread descriptor was allocated elsewhere as + part of the TLS allocation. We have to initialize the data + structure by hand. This initialization must mirror the struct + definition above. */ + self->p_nextlive = self->p_prevlive = self; + self->p_tid = PTHREAD_THREADS_MAX; + self->p_lock = &__pthread_handles[0].h_lock; +# ifndef HAVE___THREAD + self->p_errnop = &_errno; + self->p_h_errnop = &_h_errno; +# endif + /* self->p_start_args need not be initialized, it's all zero. */ + self->p_userstack = 1; +# if __LT_SPINLOCK_INIT != 0 + self->p_resume_count = (struct pthread_atomic) __ATOMIC_INITIALIZER; +# endif + self->p_alloca_cutoff = __MAX_ALLOCA_CUTOFF; + + /* Another variable which points to the thread descriptor. */ + __pthread_main_thread = self; + + /* And fill in the pointer the the thread __pthread_handles array. */ + __pthread_handles[0].h_descr = self; + +#else /* USE_TLS */ + + /* First of all init __pthread_handles[0] and [1]. */ +# if __LT_SPINLOCK_INIT != 0 + __pthread_handles[0].h_lock = __LOCK_INITIALIZER; + __pthread_handles[1].h_lock = __LOCK_INITIALIZER; +# endif + __pthread_handles[0].h_descr = &__pthread_initial_thread; + __pthread_handles[1].h_descr = &__pthread_manager_thread; + + /* If we have special thread_self processing, initialize that for the + main thread now. */ +# ifdef INIT_THREAD_SELF + INIT_THREAD_SELF(&__pthread_initial_thread, 0); +# endif +#endif + +#if HP_TIMING_AVAIL +# ifdef USE_TLS + self->p_cpuclock_offset = GL(dl_cpuclock_offset); +# else + __pthread_initial_thread.p_cpuclock_offset = GL(dl_cpuclock_offset); +# endif +#endif + + __libc_multiple_threads_ptr = __libc_pthread_init (ptr_pthread_functions); +} + + +void +__pthread_init_max_stacksize(void) +{ + struct rlimit limit; + size_t max_stack; + + getrlimit(RLIMIT_STACK, &limit); +#ifdef FLOATING_STACKS + if (limit.rlim_cur == RLIM_INFINITY) + limit.rlim_cur = ARCH_STACK_MAX_SIZE; +# ifdef NEED_SEPARATE_REGISTER_STACK + max_stack = limit.rlim_cur / 2; +# else + max_stack = limit.rlim_cur; +# endif +#else + /* Play with the stack size limit to make sure that no stack ever grows + beyond STACK_SIZE minus one page (to act as a guard page). */ +# ifdef NEED_SEPARATE_REGISTER_STACK + /* STACK_SIZE bytes hold both the main stack and register backing + store. The rlimit value applies to each individually. */ + max_stack = STACK_SIZE/2 - __getpagesize (); +# else + max_stack = STACK_SIZE - __getpagesize(); +# endif + if (limit.rlim_cur > max_stack) { + limit.rlim_cur = max_stack; + setrlimit(RLIMIT_STACK, &limit); + } +#endif + __pthread_max_stacksize = max_stack; + if (max_stack / 4 < __MAX_ALLOCA_CUTOFF) + { +#ifdef USE_TLS + pthread_descr self = THREAD_SELF; + self->p_alloca_cutoff = max_stack / 4; +#else + __pthread_initial_thread.p_alloca_cutoff = max_stack / 4; +#endif + } +} + +/* psm: we do not have any ld.so support yet + * remove the USE_TLS guard if nptl is added */ +#if defined SHARED && defined USE_TLS +# if USE___THREAD +/* When using __thread for this, we do it in libc so as not + to give libpthread its own TLS segment just for this. */ +extern void **__libc_dl_error_tsd (void) __attribute__ ((const)); +# else +static void ** __attribute__ ((const)) +__libc_dl_error_tsd (void) +{ + return &thread_self ()->p_libc_specific[_LIBC_TSD_KEY_DL_ERROR]; +} +# endif +#endif + +#ifdef USE_TLS +static __inline__ void __attribute__((always_inline)) +init_one_static_tls (pthread_descr descr, struct link_map *map) +{ +# if defined(TLS_TCB_AT_TP) + dtv_t *dtv = GET_DTV (descr); + void *dest = (char *) descr - map->l_tls_offset; +# elif defined(TLS_DTV_AT_TP) + dtv_t *dtv = GET_DTV ((pthread_descr) ((char *) descr + TLS_PRE_TCB_SIZE)); + void *dest = (char *) descr + map->l_tls_offset + TLS_PRE_TCB_SIZE; +# else +# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined" +# endif + + /* Fill in the DTV slot so that a later LD/GD access will find it. */ + dtv[map->l_tls_modid].pointer.val = dest; + dtv[map->l_tls_modid].pointer.is_static = true; + + /* Initialize the memory. */ + memset (__mempcpy (dest, map->l_tls_initimage, map->l_tls_initimage_size), + '\0', map->l_tls_blocksize - map->l_tls_initimage_size); +} + +static void +__pthread_init_static_tls (struct link_map *map) +{ + size_t i; + + for (i = 0; i < PTHREAD_THREADS_MAX; ++i) + if (__pthread_handles[i].h_descr != NULL && i != 1) + { + __pthread_lock (&__pthread_handles[i].h_lock, NULL); + if (__pthread_handles[i].h_descr != NULL) + init_one_static_tls (__pthread_handles[i].h_descr, map); + __pthread_unlock (&__pthread_handles[i].h_lock); + } +} +#endif + +static void pthread_initialize(void) +{ + struct sigaction sa; + sigset_t mask; + + /* If already done (e.g. by a constructor called earlier!), bail out */ + if (__pthread_initial_thread_bos != NULL) return; +#ifdef TEST_FOR_COMPARE_AND_SWAP + /* Test if compare-and-swap is available */ + __pthread_has_cas = compare_and_swap_is_available(); +#endif +#ifdef FLOATING_STACKS + /* We don't need to know the bottom of the stack. Give the pointer some + value to signal that initialization happened. */ + __pthread_initial_thread_bos = (void *) -1l; +#else + /* Determine stack size limits . */ + __pthread_init_max_stacksize (); +# ifdef _STACK_GROWS_UP + /* The initial thread already has all the stack it needs */ + __pthread_initial_thread_bos = (char *) + ((long)CURRENT_STACK_FRAME &~ (STACK_SIZE - 1)); +# else + /* For the initial stack, reserve at least STACK_SIZE bytes of stack + below the current stack address, and align that on a + STACK_SIZE boundary. */ + __pthread_initial_thread_bos = + (char *)(((long)CURRENT_STACK_FRAME - 2 * STACK_SIZE) & ~(STACK_SIZE - 1)); +# endif +#endif +#ifdef USE_TLS + /* Update the descriptor for the initial thread. */ + THREAD_SETMEM (((pthread_descr) NULL), p_pid, __getpid()); +# if !defined HAVE___THREAD && (defined __UCLIBC_HAS_IPv4__ || defined __UCLIBC_HAS_IPV6__) + /* Likewise for the resolver state _res. */ + THREAD_SETMEM (((pthread_descr) NULL), p_resp, __resp); +# endif +#else + /* Update the descriptor for the initial thread. */ + __pthread_initial_thread.p_pid = __getpid(); +# if defined __UCLIBC_HAS_IPv4__ || defined __UCLIBC_HAS_IPV6__ + /* Likewise for the resolver state _res. */ + __pthread_initial_thread.p_resp = __resp; +# endif +#endif +#if !__ASSUME_REALTIME_SIGNALS + /* Initialize real-time signals. */ + init_rtsigs (); +#endif + /* Setup signal handlers for the initial thread. + Since signal handlers are shared between threads, these settings + will be inherited by all other threads. */ + memset(&sa, 0, sizeof(sa)); + sa.sa_handler = pthread_handle_sigrestart; + __libc_sigaction(__pthread_sig_restart, &sa, NULL); + sa.sa_handler = pthread_handle_sigcancel; + sigaddset(&sa.sa_mask, __pthread_sig_restart); + __libc_sigaction(__pthread_sig_cancel, &sa, NULL); + if (__pthread_sig_debug > 0) { + sa.sa_handler = pthread_handle_sigdebug; + __sigemptyset(&sa.sa_mask); + __libc_sigaction(__pthread_sig_debug, &sa, NULL); + } + /* Initially, block __pthread_sig_restart. Will be unblocked on demand. */ + __sigemptyset(&mask); + sigaddset(&mask, __pthread_sig_restart); + sigprocmask(SIG_BLOCK, &mask, NULL); + /* And unblock __pthread_sig_cancel if it has been blocked. */ + sigdelset(&mask, __pthread_sig_restart); + sigaddset(&mask, __pthread_sig_cancel); + sigprocmask(SIG_UNBLOCK, &mask, NULL); + /* Register an exit function to kill all other threads. */ + /* Do it early so that user-registered atexit functions are called + before pthread_*exit_process. */ +#ifndef HAVE_Z_NODELETE + if (__builtin_expect (&__dso_handle != NULL, 1)) + __cxa_atexit ((void (*) (void *)) pthread_atexit_process, NULL, + __dso_handle); + else +#endif + __on_exit (pthread_onexit_process, NULL); + /* How many processors. */ + __pthread_smp_kernel = is_smp_system (); + +/* psm: we do not have any ld.so support yet + * remove the USE_TLS guard if nptl is added */ +#if defined SHARED && defined USE_TLS + /* Transfer the old value from the dynamic linker's internal location. */ + *__libc_dl_error_tsd () = *(*GL(dl_error_catch_tsd)) (); + GL(dl_error_catch_tsd) = &__libc_dl_error_tsd; + + /* Make __rtld_lock_{,un}lock_recursive use pthread_mutex_{,un}lock, + keep the lock count from the ld.so implementation. */ + GL(dl_rtld_lock_recursive) = (void *) __pthread_mutex_lock; + GL(dl_rtld_unlock_recursive) = (void *) __pthread_mutex_unlock; + unsigned int rtld_lock_count = GL(dl_load_lock).mutex.__m_count; + GL(dl_load_lock).mutex.__m_count = 0; + while (rtld_lock_count-- > 0) + __pthread_mutex_lock (&GL(dl_load_lock).mutex); +#endif + +#ifdef USE_TLS + GL(dl_init_static_tls) = &__pthread_init_static_tls; +#endif + + /* uClibc-specific stdio initialization for threads. */ + { + FILE *fp; + _stdio_user_locking = 0; /* 2 if threading not initialized */ + for (fp = _stdio_openlist; fp != NULL; fp = fp->__nextopen) { + if (fp->__user_locking != 1) { + fp->__user_locking = 0; + } + } + } +} + +void __pthread_initialize(void) +{ + pthread_initialize(); +} + +int __pthread_initialize_manager(void) +{ + int manager_pipe[2]; + int pid; + struct pthread_request request; + int report_events; + pthread_descr mgr; +#ifdef USE_TLS + tcbhead_t *tcbp; +#endif + + __pthread_multiple_threads = 1; +#if TLS_MULTIPLE_THREADS_IN_TCB || !defined USE_TLS || !TLS_DTV_AT_TP + __pthread_main_thread->p_multiple_threads = 1; +#endif + *__libc_multiple_threads_ptr = 1; + +#ifndef HAVE_Z_NODELETE + if (__builtin_expect (&__dso_handle != NULL, 1)) + __cxa_atexit ((void (*) (void *)) pthread_atexit_retcode, NULL, + __dso_handle); +#endif + + if (__pthread_max_stacksize == 0) + __pthread_init_max_stacksize (); + /* If basic initialization not done yet (e.g. we're called from a + constructor run before our constructor), do it now */ + if (__pthread_initial_thread_bos == NULL) pthread_initialize(); + /* Setup stack for thread manager */ + __pthread_manager_thread_bos = malloc(THREAD_MANAGER_STACK_SIZE); + if (__pthread_manager_thread_bos == NULL) return -1; + __pthread_manager_thread_tos = + __pthread_manager_thread_bos + THREAD_MANAGER_STACK_SIZE; + /* Setup pipe to communicate with thread manager */ + if (pipe(manager_pipe) == -1) { + free(__pthread_manager_thread_bos); + return -1; + } + +#ifdef USE_TLS + /* Allocate memory for the thread descriptor and the dtv. */ + tcbp = _dl_allocate_tls (NULL); + if (tcbp == NULL) { + free(__pthread_manager_thread_bos); + close_not_cancel(manager_pipe[0]); + close_not_cancel(manager_pipe[1]); + return -1; + } + +# if defined(TLS_TCB_AT_TP) + mgr = (pthread_descr) tcbp; +# elif defined(TLS_DTV_AT_TP) + /* pthread_descr is located right below tcbhead_t which _dl_allocate_tls + returns. */ + mgr = (pthread_descr) ((char *) tcbp - TLS_PRE_TCB_SIZE); +# endif + __pthread_handles[1].h_descr = manager_thread = mgr; + + /* Initialize the descriptor. */ +#if !defined USE_TLS || !TLS_DTV_AT_TP + mgr->p_header.data.tcb = tcbp; + mgr->p_header.data.self = mgr; + mgr->p_header.data.multiple_threads = 1; +#elif TLS_MULTIPLE_THREADS_IN_TCB + mgr->p_multiple_threads = 1; +#endif + mgr->p_lock = &__pthread_handles[1].h_lock; +# ifndef HAVE___THREAD + mgr->p_errnop = &mgr->p_errno; +# endif + mgr->p_start_args = (struct pthread_start_args) PTHREAD_START_ARGS_INITIALIZER(__pthread_manager); + mgr->p_nr = 1; +# if __LT_SPINLOCK_INIT != 0 + self->p_resume_count = (struct pthread_atomic) __ATOMIC_INITIALIZER; +# endif + mgr->p_alloca_cutoff = PTHREAD_STACK_MIN / 4; +#else + mgr = &__pthread_manager_thread; +#endif + + __pthread_manager_request = manager_pipe[1]; /* writing end */ + __pthread_manager_reader = manager_pipe[0]; /* reading end */ + + /* Start the thread manager */ + pid = 0; +#ifdef USE_TLS + if (__linuxthreads_initial_report_events != 0) + THREAD_SETMEM (((pthread_descr) NULL), p_report_events, + __linuxthreads_initial_report_events); + report_events = THREAD_GETMEM (((pthread_descr) NULL), p_report_events); +#else + if (__linuxthreads_initial_report_events != 0) + __pthread_initial_thread.p_report_events + = __linuxthreads_initial_report_events; + report_events = __pthread_initial_thread.p_report_events; +#endif + if (__builtin_expect (report_events, 0)) + { + /* It's a bit more complicated. We have to report the creation of + the manager thread. */ + int idx = __td_eventword (TD_CREATE); + uint32_t mask = __td_eventmask (TD_CREATE); + uint32_t event_bits; + +#ifdef USE_TLS + event_bits = THREAD_GETMEM_NC (((pthread_descr) NULL), + p_eventbuf.eventmask.event_bits[idx]); +#else + event_bits = __pthread_initial_thread.p_eventbuf.eventmask.event_bits[idx]; +#endif + + if ((mask & (__pthread_threads_events.event_bits[idx] | event_bits)) + != 0) + { + __pthread_lock(mgr->p_lock, NULL); + +#ifdef NEED_SEPARATE_REGISTER_STACK + pid = __clone2(__pthread_manager_event, + (void **) __pthread_manager_thread_bos, + THREAD_MANAGER_STACK_SIZE, + CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_SYSVSEM, + mgr); +#elif _STACK_GROWS_UP + pid = __clone(__pthread_manager_event, + (void **) __pthread_manager_thread_bos, + CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_SYSVSEM, + mgr); +#else + pid = __clone(__pthread_manager_event, + (void **) __pthread_manager_thread_tos, + CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_SYSVSEM, + mgr); +#endif + + if (pid != -1) + { + /* Now fill in the information about the new thread in + the newly created thread's data structure. We cannot let + the new thread do this since we don't know whether it was + already scheduled when we send the event. */ + mgr->p_eventbuf.eventdata = mgr; + mgr->p_eventbuf.eventnum = TD_CREATE; + __pthread_last_event = mgr; + mgr->p_tid = 2* PTHREAD_THREADS_MAX + 1; + mgr->p_pid = pid; + + /* Now call the function which signals the event. */ + __linuxthreads_create_event (); + } + + /* Now restart the thread. */ + __pthread_unlock(mgr->p_lock); + } + } + + if (__builtin_expect (pid, 0) == 0) + { +#ifdef NEED_SEPARATE_REGISTER_STACK + pid = __clone2(__pthread_manager, (void **) __pthread_manager_thread_bos, + THREAD_MANAGER_STACK_SIZE, + CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_SYSVSEM, mgr); +#elif _STACK_GROWS_UP + pid = __clone(__pthread_manager, (void **) __pthread_manager_thread_bos, + CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_SYSVSEM, mgr); +#else + pid = __clone(__pthread_manager, (void **) __pthread_manager_thread_tos, + CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_SYSVSEM, mgr); +#endif + } + if (__builtin_expect (pid, 0) == -1) { +#ifdef USE_TLS + _dl_deallocate_tls (tcbp, true); +#endif + free(__pthread_manager_thread_bos); + close_not_cancel(manager_pipe[0]); + close_not_cancel(manager_pipe[1]); + return -1; + } + mgr->p_tid = 2* PTHREAD_THREADS_MAX + 1; + mgr->p_pid = pid; + /* Make gdb aware of new thread manager */ + if (__builtin_expect (__pthread_threads_debug, 0) && __pthread_sig_debug > 0) + { + raise(__pthread_sig_debug); + /* We suspend ourself and gdb will wake us up when it is + ready to handle us. */ + __pthread_wait_for_restart_signal(thread_self()); + } + /* Synchronize debugging of the thread manager */ + request.req_kind = REQ_DEBUG; + TEMP_FAILURE_RETRY(write_not_cancel(__pthread_manager_request, + (char *) &request, sizeof(request))); + return 0; +} + +/* Thread creation */ + +int __pthread_create(pthread_t *thread, const pthread_attr_t *attr, + void * (*start_routine)(void *), void *arg) +{ + pthread_descr self = thread_self(); + struct pthread_request request; + int retval; + if (__builtin_expect (__pthread_manager_request, 0) < 0) { + if (__pthread_initialize_manager() < 0) return EAGAIN; + } + request.req_thread = self; + request.req_kind = REQ_CREATE; + request.req_args.create.attr = attr; + request.req_args.create.fn = start_routine; + request.req_args.create.arg = arg; + sigprocmask(SIG_SETMASK, NULL, &request.req_args.create.mask); + TEMP_FAILURE_RETRY(write_not_cancel(__pthread_manager_request, + (char *) &request, sizeof(request))); + suspend(self); + retval = THREAD_GETMEM(self, p_retcode); + if (__builtin_expect (retval, 0) == 0) + *thread = (pthread_t) THREAD_GETMEM(self, p_retval); + return retval; +} +strong_alias (__pthread_create, pthread_create) + +/* Simple operations on thread identifiers */ + +pthread_descr __pthread_thread_self(void) +{ + return thread_self(); +} + +pthread_t __pthread_self(void) +{ + pthread_descr self = thread_self(); + return THREAD_GETMEM(self, p_tid); +} +strong_alias (__pthread_self, pthread_self) + +int __pthread_equal(pthread_t thread1, pthread_t thread2) +{ + return thread1 == thread2; +} +strong_alias (__pthread_equal, pthread_equal) + +/* Helper function for thread_self in the case of user-provided stacks */ + +#ifndef THREAD_SELF + +pthread_descr __pthread_find_self(void) +{ + char * sp = CURRENT_STACK_FRAME; + pthread_handle h; + + /* __pthread_handles[0] is the initial thread, __pthread_handles[1] is + the manager threads handled specially in thread_self(), so start at 2 */ + h = __pthread_handles + 2; +# ifdef _STACK_GROWS_UP + while (! (sp >= (char *) h->h_descr && sp < (char *) h->h_descr->p_guardaddr)) h++; +# else + while (! (sp <= (char *) h->h_descr && sp >= h->h_bottom)) h++; +# endif + return h->h_descr; +} + +#else + +pthread_descr __pthread_self_stack(void) +{ + char *sp = CURRENT_STACK_FRAME; + pthread_handle h; + + if (sp >= __pthread_manager_thread_bos && sp < __pthread_manager_thread_tos) + return manager_thread; + h = __pthread_handles + 2; +# ifdef USE_TLS +# ifdef _STACK_GROWS_UP + while (h->h_descr == NULL + || ! (sp >= h->h_descr->p_stackaddr && sp < h->h_descr->p_guardaddr)) + h++; +# else + while (h->h_descr == NULL + || ! (sp <= (char *) h->h_descr->p_stackaddr && sp >= h->h_bottom)) + h++; +# endif +# else +# ifdef _STACK_GROWS_UP + while (! (sp >= (char *) h->h_descr && sp < h->h_descr->p_guardaddr)) + h++; +# else + while (! (sp <= (char *) h->h_descr && sp >= h->h_bottom)) + h++; +# endif +# endif + return h->h_descr; +} + +#endif + +/* Thread scheduling */ + +int __pthread_setschedparam(pthread_t thread, int policy, + const struct sched_param *param) +{ + pthread_handle handle = thread_handle(thread); + pthread_descr th; + + __pthread_lock(&handle->h_lock, NULL); + if (__builtin_expect (invalid_handle(handle, thread), 0)) { + __pthread_unlock(&handle->h_lock); + return ESRCH; + } + th = handle->h_descr; + if (__builtin_expect (__sched_setscheduler(th->p_pid, policy, param) == -1, + 0)) { + __pthread_unlock(&handle->h_lock); + return errno; + } + th->p_priority = policy == SCHED_OTHER ? 0 : param->sched_priority; + __pthread_unlock(&handle->h_lock); + if (__pthread_manager_request >= 0) + __pthread_manager_adjust_prio(th->p_priority); + return 0; +} +strong_alias (__pthread_setschedparam, pthread_setschedparam) + +int __pthread_getschedparam(pthread_t thread, int *policy, + struct sched_param *param) +{ + pthread_handle handle = thread_handle(thread); + int pid, pol; + + __pthread_lock(&handle->h_lock, NULL); + if (__builtin_expect (invalid_handle(handle, thread), 0)) { + __pthread_unlock(&handle->h_lock); + return ESRCH; + } + pid = handle->h_descr->p_pid; + __pthread_unlock(&handle->h_lock); + pol = __sched_getscheduler(pid); + if (__builtin_expect (pol, 0) == -1) return errno; + if (__sched_getparam(pid, param) == -1) return errno; + *policy = pol; + return 0; +} +strong_alias (__pthread_getschedparam, pthread_getschedparam) + +/* Process-wide exit() request */ + +static void pthread_onexit_process(int retcode, void *arg) +{ + if (__builtin_expect (__pthread_manager_request, 0) >= 0) { + struct pthread_request request; + pthread_descr self = thread_self(); + + /* Make sure we come back here after suspend(), in case we entered + from a signal handler. */ + THREAD_SETMEM(self, p_signal_jmp, NULL); + + request.req_thread = self; + request.req_kind = REQ_PROCESS_EXIT; + request.req_args.exit.code = retcode; + TEMP_FAILURE_RETRY(write_not_cancel(__pthread_manager_request, + (char *) &request, sizeof(request))); + suspend(self); + /* Main thread should accumulate times for thread manager and its + children, so that timings for main thread account for all threads. */ + if (self == __pthread_main_thread) + { +#ifdef USE_TLS + waitpid(manager_thread->p_pid, NULL, __WCLONE); +#else + waitpid(__pthread_manager_thread.p_pid, NULL, __WCLONE); +#endif + /* Since all threads have been asynchronously terminated + (possibly holding locks), free cannot be used any more. + For mtrace, we'd like to print something though. */ + /* #ifdef USE_TLS + tcbhead_t *tcbp = (tcbhead_t *) manager_thread; + # if defined(TLS_DTV_AT_TP) + tcbp = (tcbhead_t) ((char *) tcbp + TLS_PRE_TCB_SIZE); + # endif + _dl_deallocate_tls (tcbp, true); + #endif + free (__pthread_manager_thread_bos); */ + __pthread_manager_thread_bos = __pthread_manager_thread_tos = NULL; + } + } +} + +#ifndef HAVE_Z_NODELETE +static int __pthread_atexit_retcode; + +static void pthread_atexit_process(void *arg, int retcode) +{ + pthread_onexit_process (retcode ?: __pthread_atexit_retcode, arg); +} + +static void pthread_atexit_retcode(void *arg, int retcode) +{ + __pthread_atexit_retcode = retcode; +} +#endif + +/* The handler for the RESTART signal just records the signal received + in the thread descriptor, and optionally performs a siglongjmp + (for pthread_cond_timedwait). */ + +static void pthread_handle_sigrestart(int sig) +{ + pthread_descr self = check_thread_self(); + THREAD_SETMEM(self, p_signal, sig); + if (THREAD_GETMEM(self, p_signal_jmp) != NULL) + siglongjmp(*THREAD_GETMEM(self, p_signal_jmp), 1); +} + +/* The handler for the CANCEL signal checks for cancellation + (in asynchronous mode), for process-wide exit and exec requests. + For the thread manager thread, redirect the signal to + __pthread_manager_sighandler. */ + +static void pthread_handle_sigcancel(int sig) +{ + pthread_descr self = check_thread_self(); + sigjmp_buf * jmpbuf; + + if (self == manager_thread) + { + __pthread_manager_sighandler(sig); + return; + } + if (__builtin_expect (__pthread_exit_requested, 0)) { + /* Main thread should accumulate times for thread manager and its + children, so that timings for main thread account for all threads. */ + if (self == __pthread_main_thread) { +#ifdef USE_TLS + waitpid(manager_thread->p_pid, NULL, __WCLONE); +#else + waitpid(__pthread_manager_thread.p_pid, NULL, __WCLONE); +#endif + } + _exit(__pthread_exit_code); + } + if (__builtin_expect (THREAD_GETMEM(self, p_canceled), 0) + && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) { + if (THREAD_GETMEM(self, p_canceltype) == PTHREAD_CANCEL_ASYNCHRONOUS) + __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); + jmpbuf = THREAD_GETMEM(self, p_cancel_jmp); + if (jmpbuf != NULL) { + THREAD_SETMEM(self, p_cancel_jmp, NULL); + siglongjmp(*jmpbuf, 1); + } + } +} + +/* Handler for the DEBUG signal. + The debugging strategy is as follows: + On reception of a REQ_DEBUG request (sent by new threads created to + the thread manager under debugging mode), the thread manager throws + __pthread_sig_debug to itself. The debugger (if active) intercepts + this signal, takes into account new threads and continue execution + of the thread manager by propagating the signal because it doesn't + know what it is specifically done for. In the current implementation, + the thread manager simply discards it. */ + +static void pthread_handle_sigdebug(int sig) +{ + /* Nothing */ +} + +/* Reset the state of the thread machinery after a fork(). + Close the pipe used for requests and set the main thread to the forked + thread. + Notice that we can't free the stack segments, as the forked thread + may hold pointers into them. */ + +void __pthread_reset_main_thread(void) +{ + pthread_descr self = thread_self(); + + if (__pthread_manager_request != -1) { + /* Free the thread manager stack */ + free(__pthread_manager_thread_bos); + __pthread_manager_thread_bos = __pthread_manager_thread_tos = NULL; + /* Close the two ends of the pipe */ + close_not_cancel(__pthread_manager_request); + close_not_cancel(__pthread_manager_reader); + __pthread_manager_request = __pthread_manager_reader = -1; + } + + /* Update the pid of the main thread */ + THREAD_SETMEM(self, p_pid, __getpid()); + /* Make the forked thread the main thread */ + __pthread_main_thread = self; + THREAD_SETMEM(self, p_nextlive, self); + THREAD_SETMEM(self, p_prevlive, self); +#if !(USE_TLS && HAVE___THREAD) + /* Now this thread modifies the global variables. */ + THREAD_SETMEM(self, p_errnop, &_errno); + THREAD_SETMEM(self, p_h_errnop, &_h_errno); +# if defined __UCLIBC_HAS_IPv4__ || defined __UCLIBC_HAS_IPV6__ + THREAD_SETMEM(self, p_resp, __resp); +# endif +#endif + +#ifndef FLOATING_STACKS + /* This is to undo the setrlimit call in __pthread_init_max_stacksize. + XXX This can be wrong if the user set the limit during the run. */ + { + struct rlimit limit; + if (getrlimit (RLIMIT_STACK, &limit) == 0 + && limit.rlim_cur != limit.rlim_max) + { + limit.rlim_cur = limit.rlim_max; + setrlimit(RLIMIT_STACK, &limit); + } + } +#endif +} + +/* Process-wide exec() request */ + +void __pthread_kill_other_threads_np(void) +{ + struct sigaction sa; + /* Terminate all other threads and thread manager */ + pthread_onexit_process(0, NULL); + /* Make current thread the main thread in case the calling thread + changes its mind, does not exec(), and creates new threads instead. */ + __pthread_reset_main_thread(); + + /* Reset the signal handlers behaviour for the signals the + implementation uses since this would be passed to the new + process. */ + memset(&sa, 0, sizeof(sa)); + if (SIG_DFL) /* if it's constant zero, it's already done */ + sa.sa_handler = SIG_DFL; + __libc_sigaction(__pthread_sig_restart, &sa, NULL); + __libc_sigaction(__pthread_sig_cancel, &sa, NULL); + if (__pthread_sig_debug > 0) + __libc_sigaction(__pthread_sig_debug, &sa, NULL); +} +weak_alias (__pthread_kill_other_threads_np, pthread_kill_other_threads_np) + +/* Concurrency symbol level. */ +static int current_level; + +int __pthread_setconcurrency(int level) +{ + /* We don't do anything unless we have found a useful interpretation. */ + current_level = level; + return 0; +} +weak_alias (__pthread_setconcurrency, pthread_setconcurrency) + +int __pthread_getconcurrency(void) +{ + return current_level; +} +weak_alias (__pthread_getconcurrency, pthread_getconcurrency) + +/* Primitives for controlling thread execution */ + +void __pthread_wait_for_restart_signal(pthread_descr self) +{ + sigset_t mask; + + sigprocmask(SIG_SETMASK, NULL, &mask); /* Get current signal mask */ + sigdelset(&mask, __pthread_sig_restart); /* Unblock the restart signal */ + THREAD_SETMEM(self, p_signal, 0); + do { + __pthread_sigsuspend(&mask); /* Wait for signal. Must not be a + cancellation point. */ + } while (THREAD_GETMEM(self, p_signal) !=__pthread_sig_restart); + + READ_MEMORY_BARRIER(); /* See comment in __pthread_restart_new */ +} + +#if !__ASSUME_REALTIME_SIGNALS +/* The _old variants are for 2.0 and early 2.1 kernels which don't have RT + signals. + On these kernels, we use SIGUSR1 and SIGUSR2 for restart and cancellation. + Since the restart signal does not queue, we use an atomic counter to create + queuing semantics. This is needed to resolve a rare race condition in + pthread_cond_timedwait_relative. */ + +void __pthread_restart_old(pthread_descr th) +{ + if (pthread_atomic_increment(&th->p_resume_count) == -1) + kill(th->p_pid, __pthread_sig_restart); +} + +void __pthread_suspend_old(pthread_descr self) +{ + if (pthread_atomic_decrement(&self->p_resume_count) <= 0) + __pthread_wait_for_restart_signal(self); +} + +int +__pthread_timedsuspend_old(pthread_descr self, const struct timespec *abstime) +{ + sigset_t unblock, initial_mask; + int was_signalled = 0; + sigjmp_buf jmpbuf; + + if (pthread_atomic_decrement(&self->p_resume_count) == 0) { + /* Set up a longjmp handler for the restart signal, unblock + the signal and sleep. */ + + if (sigsetjmp(jmpbuf, 1) == 0) { + THREAD_SETMEM(self, p_signal_jmp, &jmpbuf); + THREAD_SETMEM(self, p_signal, 0); + /* Unblock the restart signal */ + __sigemptyset(&unblock); + sigaddset(&unblock, __pthread_sig_restart); + sigprocmask(SIG_UNBLOCK, &unblock, &initial_mask); + + while (1) { + struct timeval now; + struct timespec reltime; + + /* Compute a time offset relative to now. */ + __gettimeofday (&now, NULL); + reltime.tv_nsec = abstime->tv_nsec - now.tv_usec * 1000; + reltime.tv_sec = abstime->tv_sec - now.tv_sec; + if (reltime.tv_nsec < 0) { + reltime.tv_nsec += 1000000000; + reltime.tv_sec -= 1; + } + + /* Sleep for the required duration. If woken by a signal, + resume waiting as required by Single Unix Specification. */ + if (reltime.tv_sec < 0 || nanosleep(&reltime, NULL) == 0) + break; + } + + /* Block the restart signal again */ + sigprocmask(SIG_SETMASK, &initial_mask, NULL); + was_signalled = 0; + } else { + was_signalled = 1; + } + THREAD_SETMEM(self, p_signal_jmp, NULL); + } + + /* Now was_signalled is true if we exited the above code + due to the delivery of a restart signal. In that case, + we know we have been dequeued and resumed and that the + resume count is balanced. Otherwise, there are some + cases to consider. First, try to bump up the resume count + back to zero. If it goes to 1, it means restart() was + invoked on this thread. The signal must be consumed + and the count bumped down and everything is cool. We + can return a 1 to the caller. + Otherwise, no restart was delivered yet, so a potential + race exists; we return a 0 to the caller which must deal + with this race in an appropriate way; for example by + atomically removing the thread from consideration for a + wakeup---if such a thing fails, it means a restart is + being delivered. */ + + if (!was_signalled) { + if (pthread_atomic_increment(&self->p_resume_count) != -1) { + __pthread_wait_for_restart_signal(self); + pthread_atomic_decrement(&self->p_resume_count); /* should be zero now! */ + /* woke spontaneously and consumed restart signal */ + return 1; + } + /* woke spontaneously but did not consume restart---caller must resolve */ + return 0; + } + /* woken due to restart signal */ + return 1; +} +#endif /* __ASSUME_REALTIME_SIGNALS */ + +void __pthread_restart_new(pthread_descr th) +{ + /* The barrier is proabably not needed, in which case it still documents + our assumptions. The intent is to commit previous writes to shared + memory so the woken thread will have a consistent view. Complementary + read barriers are present to the suspend functions. */ + WRITE_MEMORY_BARRIER(); + kill(th->p_pid, __pthread_sig_restart); +} + +/* There is no __pthread_suspend_new because it would just + be a wasteful wrapper for __pthread_wait_for_restart_signal */ + +int +__pthread_timedsuspend_new(pthread_descr self, const struct timespec *abstime) +{ + sigset_t unblock, initial_mask; + int was_signalled = 0; + sigjmp_buf jmpbuf; + + if (sigsetjmp(jmpbuf, 1) == 0) { + THREAD_SETMEM(self, p_signal_jmp, &jmpbuf); + THREAD_SETMEM(self, p_signal, 0); + /* Unblock the restart signal */ + __sigemptyset(&unblock); + sigaddset(&unblock, __pthread_sig_restart); + sigprocmask(SIG_UNBLOCK, &unblock, &initial_mask); + + while (1) { + struct timeval now; + struct timespec reltime; + + /* Compute a time offset relative to now. */ + __gettimeofday (&now, NULL); + reltime.tv_nsec = abstime->tv_nsec - now.tv_usec * 1000; + reltime.tv_sec = abstime->tv_sec - now.tv_sec; + if (reltime.tv_nsec < 0) { + reltime.tv_nsec += 1000000000; + reltime.tv_sec -= 1; + } + + /* Sleep for the required duration. If woken by a signal, + resume waiting as required by Single Unix Specification. */ + if (reltime.tv_sec < 0 || nanosleep(&reltime, NULL) == 0) + break; + } + + /* Block the restart signal again */ + sigprocmask(SIG_SETMASK, &initial_mask, NULL); + was_signalled = 0; + } else { + was_signalled = 1; + } + THREAD_SETMEM(self, p_signal_jmp, NULL); + + /* Now was_signalled is true if we exited the above code + due to the delivery of a restart signal. In that case, + everything is cool. We have been removed from whatever + we were waiting on by the other thread, and consumed its signal. + + Otherwise we this thread woke up spontaneously, or due to a signal other + than restart. This is an ambiguous case that must be resolved by + the caller; the thread is still eligible for a restart wakeup + so there is a race. */ + + READ_MEMORY_BARRIER(); /* See comment in __pthread_restart_new */ + return was_signalled; +} + + +/* Debugging aid */ + +#ifdef DEBUG +#include + +void __pthread_message(const char * fmt, ...) +{ + char buffer[1024]; + va_list args; + sprintf(buffer, "%05d : ", __getpid()); + va_start(args, fmt); + vsnprintf(buffer + 8, sizeof(buffer) - 8, fmt, args); + va_end(args); + TEMP_FAILURE_RETRY(write_not_cancel(2, buffer, strlen(buffer))); +} + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/pthread_atfork.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/pthread_atfork.c new file mode 100644 index 00000000..2464acb6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/pthread_atfork.c @@ -0,0 +1,63 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file with other + programs, and to distribute those programs without any restriction + coming from the use of this file. (The GNU Lesser General Public + License restrictions do apply in other respects; for example, they + cover modification of the file, and distribution when not linked + into another program.) + + Note that people who make modified versions of this file are not + obligated to grant this special exception for their modified + versions; it is their choice whether to do so. The GNU Lesser + General Public License gives permission to release a modified + version without this exception; this exception also makes it + possible to release a modified version which carries forward this + exception. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "internals.h" +#include + +/* This is defined by newer gcc version unique for each module. */ +extern void *__dso_handle __attribute__ ((__weak__)); + + +/* Hide the symbol so that no definition but the one locally in the + executable or DSO is used. */ +int +#ifndef __pthread_atfork +/* Don't mark the compatibility function as hidden. */ +attribute_hidden +#endif +__pthread_atfork (prepare, parent, child) + void (*prepare) (void); + void (*parent) (void); + void (*child) (void); +{ + return __register_atfork (prepare, parent, child, + &__dso_handle == NULL ? NULL : __dso_handle); +} +#ifndef __pthread_atfork +extern int pthread_atfork (void (*prepare) (void), void (*parent) (void), + void (*child) (void)) attribute_hidden; +strong_alias (__pthread_atfork, pthread_atfork) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/pthread_setegid.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/pthread_setegid.c new file mode 100644 index 00000000..e357bb9e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/pthread_setegid.c @@ -0,0 +1,28 @@ +/* Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + + +int pthread_setegid_np (gid_t gid); +int +pthread_setegid_np (gid_t gid) +{ + return setegid (gid); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/pthread_seteuid.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/pthread_seteuid.c new file mode 100644 index 00000000..6a1464c5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/pthread_seteuid.c @@ -0,0 +1,28 @@ +/* Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + + +int pthread_seteuid_np (uid_t uid); +int +pthread_seteuid_np (uid_t uid) +{ + return seteuid (uid); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/pthread_setgid.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/pthread_setgid.c new file mode 100644 index 00000000..31b5a595 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/pthread_setgid.c @@ -0,0 +1,28 @@ +/* Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + + +int pthread_setgid_np (gid_t gid); +int +pthread_setgid_np (gid_t gid) +{ + return setgid (gid); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/pthread_setregid.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/pthread_setregid.c new file mode 100644 index 00000000..8964eb77 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/pthread_setregid.c @@ -0,0 +1,28 @@ +/* Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + + +int pthread_setregid_np (gid_t rgid, gid_t egid); +int +pthread_setregid_np (gid_t rgid, gid_t egid) +{ + return setregid (rgid, egid); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/pthread_setresgid.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/pthread_setresgid.c new file mode 100644 index 00000000..a330afcd --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/pthread_setresgid.c @@ -0,0 +1,28 @@ +/* Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + + +int pthread_setresgid_np (gid_t rgid, gid_t egid, gid_t sgid); +int +pthread_setresgid_np (gid_t rgid, gid_t egid, gid_t sgid) +{ + return setresgid (rgid, egid, sgid); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/pthread_setresuid.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/pthread_setresuid.c new file mode 100644 index 00000000..0fa28954 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/pthread_setresuid.c @@ -0,0 +1,28 @@ +/* Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + + +int pthread_setresuid_np (uid_t ruid, uid_t euid, uid_t suid); +int +pthread_setresuid_np (uid_t ruid, uid_t euid, uid_t suid) +{ + return setresuid (ruid, euid, suid); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/pthread_setreuid.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/pthread_setreuid.c new file mode 100644 index 00000000..78738e3c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/pthread_setreuid.c @@ -0,0 +1,28 @@ +/* Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + + +int pthread_setreuid_np (uid_t ruid, uid_t euid); +int +pthread_setreuid_np (uid_t ruid, uid_t euid) +{ + return setreuid (ruid, euid); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/pthread_setuid.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/pthread_setuid.c new file mode 100644 index 00000000..107001e2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/pthread_setuid.c @@ -0,0 +1,28 @@ +/* Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + + +int pthread_setuid_np (uid_t uid); +int +pthread_setuid_np (uid_t uid) +{ + return setuid (uid); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/queue.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/queue.h new file mode 100644 index 00000000..e50517f7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/queue.h @@ -0,0 +1,61 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +/* Waiting queues */ + +/* Waiting queues are represented by lists of thread descriptors + linked through their p_nextwaiting field. The lists are kept + sorted by decreasing priority, and then decreasing waiting time. */ + +static __inline__ void enqueue(pthread_descr * q, pthread_descr th) +{ + int prio = th->p_priority; + ASSERT(th->p_nextwaiting == NULL); + for (; *q != NULL; q = &((*q)->p_nextwaiting)) { + if (prio > (*q)->p_priority) { + th->p_nextwaiting = *q; + *q = th; + return; + } + } + *q = th; +} + +static __inline__ pthread_descr dequeue(pthread_descr * q) +{ + pthread_descr th; + th = *q; + if (th != NULL) { + *q = th->p_nextwaiting; + th->p_nextwaiting = NULL; + } + return th; +} + +static __inline__ int remove_from_queue(pthread_descr * q, pthread_descr th) +{ + for (; *q != NULL; q = &((*q)->p_nextwaiting)) { + if (*q == th) { + *q = th->p_nextwaiting; + th->p_nextwaiting = NULL; + return 1; + } + } + return 0; +} + +static __inline__ int queue_is_empty(pthread_descr * q) +{ + return *q == NULL; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/restart.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/restart.h new file mode 100644 index 00000000..694ec48c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/restart.h @@ -0,0 +1,49 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +#include +#include + +/* Primitives for controlling thread execution */ + +static __inline__ void restart(pthread_descr th) +{ + /* See pthread.c */ +#if __ASSUME_REALTIME_SIGNALS + __pthread_restart_new(th); +#else + __pthread_restart(th); +#endif +} + +static __inline__ void suspend(pthread_descr self) +{ + /* See pthread.c */ +#if __ASSUME_REALTIME_SIGNALS + __pthread_wait_for_restart_signal(self); +#else + __pthread_suspend(self); +#endif +} + +static __inline__ int timedsuspend(pthread_descr self, + const struct timespec *abstime) +{ + /* See pthread.c */ +#if __ASSUME_REALTIME_SIGNALS + return __pthread_timedsuspend_new(self, abstime); +#else + return __pthread_timedsuspend(self, abstime); +#endif +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/rwlock.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/rwlock.c new file mode 100644 index 00000000..f565f187 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/rwlock.c @@ -0,0 +1,658 @@ +/* Read-write lock implementation. + Copyright (C) 1998, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Xavier Leroy + and Ulrich Drepper , 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include +#include "internals.h" +#include "queue.h" +#include "spinlock.h" +#include "restart.h" + +/* Function called by pthread_cancel to remove the thread from + waiting inside pthread_rwlock_timedrdlock or pthread_rwlock_timedwrlock. */ + +static int rwlock_rd_extricate_func(void *obj, pthread_descr th) +{ + pthread_rwlock_t *rwlock = obj; + int did_remove = 0; + + __pthread_lock(&rwlock->__rw_lock, NULL); + did_remove = remove_from_queue(&rwlock->__rw_read_waiting, th); + __pthread_unlock(&rwlock->__rw_lock); + + return did_remove; +} + +static int rwlock_wr_extricate_func(void *obj, pthread_descr th) +{ + pthread_rwlock_t *rwlock = obj; + int did_remove = 0; + + __pthread_lock(&rwlock->__rw_lock, NULL); + did_remove = remove_from_queue(&rwlock->__rw_write_waiting, th); + __pthread_unlock(&rwlock->__rw_lock); + + return did_remove; +} + +/* + * Check whether the calling thread already owns one or more read locks on the + * specified lock. If so, return a pointer to the read lock info structure + * corresponding to that lock. + */ + +static pthread_readlock_info * +rwlock_is_in_list(pthread_descr self, pthread_rwlock_t *rwlock) +{ + pthread_readlock_info *info; + + for (info = THREAD_GETMEM (self, p_readlock_list); info != NULL; + info = info->pr_next) + { + if (info->pr_lock == rwlock) + return info; + } + + return NULL; +} + +/* + * Add a new lock to the thread's list of locks for which it has a read lock. + * A new info node must be allocated for this, which is taken from the thread's + * free list, or by calling malloc. If malloc fails, a null pointer is + * returned. Otherwise the lock info structure is initialized and pushed + * onto the thread's list. + */ + +static pthread_readlock_info * +rwlock_add_to_list(pthread_descr self, pthread_rwlock_t *rwlock) +{ + pthread_readlock_info *info = THREAD_GETMEM (self, p_readlock_free); + + if (info != NULL) + THREAD_SETMEM (self, p_readlock_free, info->pr_next); + else + info = malloc(sizeof *info); + + if (info == NULL) + return NULL; + + info->pr_lock_count = 1; + info->pr_lock = rwlock; + info->pr_next = THREAD_GETMEM (self, p_readlock_list); + THREAD_SETMEM (self, p_readlock_list, info); + + return info; +} + +/* + * If the thread owns a read lock over the given pthread_rwlock_t, + * and this read lock is tracked in the thread's lock list, + * this function returns a pointer to the info node in that list. + * It also decrements the lock count within that node, and if + * it reaches zero, it removes the node from the list. + * If nothing is found, it returns a null pointer. + */ + +static pthread_readlock_info * +rwlock_remove_from_list(pthread_descr self, pthread_rwlock_t *rwlock) +{ + pthread_readlock_info **pinfo; + + for (pinfo = &self->p_readlock_list; *pinfo != NULL; pinfo = &(*pinfo)->pr_next) + { + if ((*pinfo)->pr_lock == rwlock) + { + pthread_readlock_info *info = *pinfo; + if (--info->pr_lock_count == 0) + *pinfo = info->pr_next; + return info; + } + } + + return NULL; +} + +/* + * This function checks whether the conditions are right to place a read lock. + * It returns 1 if so, otherwise zero. The rwlock's internal lock must be + * locked upon entry. + */ + +static int +rwlock_can_rdlock(pthread_rwlock_t *rwlock, int have_lock_already) +{ + /* Can't readlock; it is write locked. */ + if (rwlock->__rw_writer != NULL) + return 0; + + /* Lock prefers readers; get it. */ + if (rwlock->__rw_kind == PTHREAD_RWLOCK_PREFER_READER_NP) + return 1; + + /* Lock prefers writers, but none are waiting. */ + if (queue_is_empty(&rwlock->__rw_write_waiting)) + return 1; + + /* Writers are waiting, but this thread already has a read lock */ + if (have_lock_already) + return 1; + + /* Writers are waiting, and this is a new lock */ + return 0; +} + +/* + * This function helps support brain-damaged recursive read locking + * semantics required by Unix 98, while maintaining write priority. + * This basically determines whether this thread already holds a read lock + * already. It returns 1 if so, otherwise it returns 0. + * + * If the thread has any ``untracked read locks'' then it just assumes + * that this lock is among them, just to be safe, and returns 1. + * + * Also, if it finds the thread's lock in the list, it sets the pointer + * referenced by pexisting to refer to the list entry. + * + * If the thread has no untracked locks, and the lock is not found + * in its list, then it is added to the list. If this fails, + * then *pout_of_mem is set to 1. + */ + +static int +rwlock_have_already(pthread_descr *pself, pthread_rwlock_t *rwlock, + pthread_readlock_info **pexisting, int *pout_of_mem) +{ + pthread_readlock_info *existing = NULL; + int out_of_mem = 0, have_lock_already = 0; + pthread_descr self = *pself; + + if (rwlock->__rw_kind == PTHREAD_RWLOCK_PREFER_WRITER_NP) + { + if (!self) + *pself = self = thread_self(); + + existing = rwlock_is_in_list(self, rwlock); + + if (existing != NULL + || THREAD_GETMEM (self, p_untracked_readlock_count) > 0) + have_lock_already = 1; + else + { + existing = rwlock_add_to_list(self, rwlock); + if (existing == NULL) + out_of_mem = 1; + } + } + + *pout_of_mem = out_of_mem; + *pexisting = existing; + + return have_lock_already; +} + +int +__pthread_rwlock_init (pthread_rwlock_t *rwlock, + const pthread_rwlockattr_t *attr) +{ + __pthread_init_lock(&rwlock->__rw_lock); + rwlock->__rw_readers = 0; + rwlock->__rw_writer = NULL; + rwlock->__rw_read_waiting = NULL; + rwlock->__rw_write_waiting = NULL; + + if (attr == NULL) + { + rwlock->__rw_kind = PTHREAD_RWLOCK_DEFAULT_NP; + rwlock->__rw_pshared = PTHREAD_PROCESS_PRIVATE; + } + else + { + rwlock->__rw_kind = attr->__lockkind; + rwlock->__rw_pshared = attr->__pshared; + } + + return 0; +} +strong_alias (__pthread_rwlock_init, pthread_rwlock_init) + + +int +__pthread_rwlock_destroy (pthread_rwlock_t *rwlock) +{ + int readers; + _pthread_descr writer; + + __pthread_lock (&rwlock->__rw_lock, NULL); + readers = rwlock->__rw_readers; + writer = rwlock->__rw_writer; + __pthread_unlock (&rwlock->__rw_lock); + + if (readers > 0 || writer != NULL) + return EBUSY; + + return 0; +} +strong_alias (__pthread_rwlock_destroy, pthread_rwlock_destroy) + +int +__pthread_rwlock_rdlock (pthread_rwlock_t *rwlock) +{ + pthread_descr self = NULL; + pthread_readlock_info *existing; + int out_of_mem, have_lock_already; + + have_lock_already = rwlock_have_already(&self, rwlock, + &existing, &out_of_mem); + + if (self == NULL) + self = thread_self (); + + for (;;) + { + __pthread_lock (&rwlock->__rw_lock, self); + + if (rwlock_can_rdlock(rwlock, have_lock_already)) + break; + + enqueue (&rwlock->__rw_read_waiting, self); + __pthread_unlock (&rwlock->__rw_lock); + suspend (self); /* This is not a cancellation point */ + } + + ++rwlock->__rw_readers; + __pthread_unlock (&rwlock->__rw_lock); + + if (have_lock_already || out_of_mem) + { + if (existing != NULL) + ++existing->pr_lock_count; + else + ++self->p_untracked_readlock_count; + } + + return 0; +} +strong_alias (__pthread_rwlock_rdlock, pthread_rwlock_rdlock) + +int +__pthread_rwlock_timedrdlock (pthread_rwlock_t *rwlock, + const struct timespec *abstime) +{ + pthread_descr self = NULL; + pthread_readlock_info *existing; + int out_of_mem, have_lock_already; + pthread_extricate_if extr; + + if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) + return EINVAL; + + have_lock_already = rwlock_have_already(&self, rwlock, + &existing, &out_of_mem); + + if (self == NULL) + self = thread_self (); + + /* Set up extrication interface */ + extr.pu_object = rwlock; + extr.pu_extricate_func = rwlock_rd_extricate_func; + + /* Register extrication interface */ + __pthread_set_own_extricate_if (self, &extr); + + for (;;) + { + __pthread_lock (&rwlock->__rw_lock, self); + + if (rwlock_can_rdlock(rwlock, have_lock_already)) + break; + + enqueue (&rwlock->__rw_read_waiting, self); + __pthread_unlock (&rwlock->__rw_lock); + /* This is not a cancellation point */ + if (timedsuspend (self, abstime) == 0) + { + int was_on_queue; + + __pthread_lock (&rwlock->__rw_lock, self); + was_on_queue = remove_from_queue (&rwlock->__rw_read_waiting, self); + __pthread_unlock (&rwlock->__rw_lock); + + if (was_on_queue) + { + __pthread_set_own_extricate_if (self, 0); + return ETIMEDOUT; + } + + /* Eat the outstanding restart() from the signaller */ + suspend (self); + } + } + + __pthread_set_own_extricate_if (self, 0); + + ++rwlock->__rw_readers; + __pthread_unlock (&rwlock->__rw_lock); + + if (have_lock_already || out_of_mem) + { + if (existing != NULL) + ++existing->pr_lock_count; + else + ++self->p_untracked_readlock_count; + } + + return 0; +} +strong_alias (__pthread_rwlock_timedrdlock, pthread_rwlock_timedrdlock) + +int +__pthread_rwlock_tryrdlock (pthread_rwlock_t *rwlock) +{ + pthread_descr self = thread_self(); + pthread_readlock_info *existing; + int out_of_mem, have_lock_already; + int retval = EBUSY; + + have_lock_already = rwlock_have_already(&self, rwlock, + &existing, &out_of_mem); + + __pthread_lock (&rwlock->__rw_lock, self); + + /* 0 is passed to here instead of have_lock_already. + This is to meet Single Unix Spec requirements: + if writers are waiting, pthread_rwlock_tryrdlock + does not acquire a read lock, even if the caller has + one or more read locks already. */ + + if (rwlock_can_rdlock(rwlock, 0)) + { + ++rwlock->__rw_readers; + retval = 0; + } + + __pthread_unlock (&rwlock->__rw_lock); + + if (retval == 0) + { + if (have_lock_already || out_of_mem) + { + if (existing != NULL) + ++existing->pr_lock_count; + else + ++self->p_untracked_readlock_count; + } + } + + return retval; +} +strong_alias (__pthread_rwlock_tryrdlock, pthread_rwlock_tryrdlock) + + +int +__pthread_rwlock_wrlock (pthread_rwlock_t *rwlock) +{ + pthread_descr self = thread_self (); + + while(1) + { + __pthread_lock (&rwlock->__rw_lock, self); + if (rwlock->__rw_readers == 0 && rwlock->__rw_writer == NULL) + { + rwlock->__rw_writer = self; + __pthread_unlock (&rwlock->__rw_lock); + return 0; + } + + /* Suspend ourselves, then try again */ + enqueue (&rwlock->__rw_write_waiting, self); + __pthread_unlock (&rwlock->__rw_lock); + suspend (self); /* This is not a cancellation point */ + } +} +strong_alias (__pthread_rwlock_wrlock, pthread_rwlock_wrlock) + + +int +__pthread_rwlock_timedwrlock (pthread_rwlock_t *rwlock, + const struct timespec *abstime) +{ + pthread_descr self; + pthread_extricate_if extr; + + if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) + return EINVAL; + + self = thread_self (); + + /* Set up extrication interface */ + extr.pu_object = rwlock; + extr.pu_extricate_func = rwlock_wr_extricate_func; + + /* Register extrication interface */ + __pthread_set_own_extricate_if (self, &extr); + + while(1) + { + __pthread_lock (&rwlock->__rw_lock, self); + + if (rwlock->__rw_readers == 0 && rwlock->__rw_writer == NULL) + { + rwlock->__rw_writer = self; + __pthread_set_own_extricate_if (self, 0); + __pthread_unlock (&rwlock->__rw_lock); + return 0; + } + + /* Suspend ourselves, then try again */ + enqueue (&rwlock->__rw_write_waiting, self); + __pthread_unlock (&rwlock->__rw_lock); + /* This is not a cancellation point */ + if (timedsuspend (self, abstime) == 0) + { + int was_on_queue; + + __pthread_lock (&rwlock->__rw_lock, self); + was_on_queue = remove_from_queue (&rwlock->__rw_write_waiting, self); + __pthread_unlock (&rwlock->__rw_lock); + + if (was_on_queue) + { + __pthread_set_own_extricate_if (self, 0); + return ETIMEDOUT; + } + + /* Eat the outstanding restart() from the signaller */ + suspend (self); + } + } +} +strong_alias (__pthread_rwlock_timedwrlock, pthread_rwlock_timedwrlock) + + +int +__pthread_rwlock_trywrlock (pthread_rwlock_t *rwlock) +{ + int result = EBUSY; + + __pthread_lock (&rwlock->__rw_lock, NULL); + if (rwlock->__rw_readers == 0 && rwlock->__rw_writer == NULL) + { + rwlock->__rw_writer = thread_self (); + result = 0; + } + __pthread_unlock (&rwlock->__rw_lock); + + return result; +} +strong_alias (__pthread_rwlock_trywrlock, pthread_rwlock_trywrlock) + + +int +__pthread_rwlock_unlock (pthread_rwlock_t *rwlock) +{ + pthread_descr torestart; + pthread_descr th; + + __pthread_lock (&rwlock->__rw_lock, NULL); + if (rwlock->__rw_writer != NULL) + { + /* Unlocking a write lock. */ + if (rwlock->__rw_writer != thread_self ()) + { + __pthread_unlock (&rwlock->__rw_lock); + return EPERM; + } + rwlock->__rw_writer = NULL; + + if ((rwlock->__rw_kind == PTHREAD_RWLOCK_PREFER_READER_NP + && !queue_is_empty(&rwlock->__rw_read_waiting)) + || (th = dequeue(&rwlock->__rw_write_waiting)) == NULL) + { + /* Restart all waiting readers. */ + torestart = rwlock->__rw_read_waiting; + rwlock->__rw_read_waiting = NULL; + __pthread_unlock (&rwlock->__rw_lock); + while ((th = dequeue (&torestart)) != NULL) + restart (th); + } + else + { + /* Restart one waiting writer. */ + __pthread_unlock (&rwlock->__rw_lock); + restart (th); + } + } + else + { + /* Unlocking a read lock. */ + if (rwlock->__rw_readers == 0) + { + __pthread_unlock (&rwlock->__rw_lock); + return EPERM; + } + + --rwlock->__rw_readers; + if (rwlock->__rw_readers == 0) + /* Restart one waiting writer, if any. */ + th = dequeue (&rwlock->__rw_write_waiting); + else + th = NULL; + + __pthread_unlock (&rwlock->__rw_lock); + if (th != NULL) + restart (th); + + /* Recursive lock fixup */ + + if (rwlock->__rw_kind == PTHREAD_RWLOCK_PREFER_WRITER_NP) + { + pthread_descr self = thread_self(); + pthread_readlock_info *victim = rwlock_remove_from_list(self, rwlock); + + if (victim != NULL) + { + if (victim->pr_lock_count == 0) + { + victim->pr_next = THREAD_GETMEM (self, p_readlock_free); + THREAD_SETMEM (self, p_readlock_free, victim); + } + } + else + { + int val = THREAD_GETMEM (self, p_untracked_readlock_count); + if (val > 0) + THREAD_SETMEM (self, p_untracked_readlock_count, val - 1); + } + } + } + + return 0; +} +strong_alias (__pthread_rwlock_unlock, pthread_rwlock_unlock) + + + +int +pthread_rwlockattr_init (pthread_rwlockattr_t *attr) +{ + attr->__lockkind = 0; + attr->__pshared = PTHREAD_PROCESS_PRIVATE; + + return 0; +} + + +int +__pthread_rwlockattr_destroy (pthread_rwlockattr_t *attr) +{ + return 0; +} +strong_alias (__pthread_rwlockattr_destroy, pthread_rwlockattr_destroy) + + +int +pthread_rwlockattr_getpshared (const pthread_rwlockattr_t *attr, int *pshared) +{ + *pshared = attr->__pshared; + return 0; +} + + +int +pthread_rwlockattr_setpshared (pthread_rwlockattr_t *attr, int pshared) +{ + if (pshared != PTHREAD_PROCESS_PRIVATE && pshared != PTHREAD_PROCESS_SHARED) + return EINVAL; + + /* For now it is not possible to shared a conditional variable. */ + if (pshared != PTHREAD_PROCESS_PRIVATE) + return ENOSYS; + + attr->__pshared = pshared; + + return 0; +} + + +int +pthread_rwlockattr_getkind_np (const pthread_rwlockattr_t *attr, int *pref) +{ + *pref = attr->__lockkind; + return 0; +} + + +int +pthread_rwlockattr_setkind_np (pthread_rwlockattr_t *attr, int pref) +{ + if (pref != PTHREAD_RWLOCK_PREFER_READER_NP + && pref != PTHREAD_RWLOCK_PREFER_WRITER_NP + && pref != PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP + && pref != PTHREAD_RWLOCK_DEFAULT_NP) + return EINVAL; + + attr->__lockkind = pref; + + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/semaphore.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/semaphore.c new file mode 100644 index 00000000..392c37bf --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/semaphore.c @@ -0,0 +1,298 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +/* Semaphores a la POSIX 1003.1b */ + +#include +#include "pthread.h" +#include "semaphore.h" +#include "internals.h" +#include "spinlock.h" +#include "restart.h" +#include "queue.h" +#include + +int sem_init(sem_t *sem, int pshared, unsigned int value) +{ + if (value > SEM_VALUE_MAX) { + errno = EINVAL; + return -1; + } + if (pshared) { + errno = ENOSYS; + return -1; + } + __pthread_init_lock(&sem->__sem_lock); + sem->__sem_value = value; + sem->__sem_waiting = NULL; + return 0; +} + +/* Function called by pthread_cancel to remove the thread from + waiting inside sem_wait. */ + +static int new_sem_extricate_func(void *obj, pthread_descr th) +{ + __volatile__ pthread_descr self = thread_self(); + sem_t *sem = obj; + int did_remove = 0; + + __pthread_lock(&sem->__sem_lock, self); + did_remove = remove_from_queue(&sem->__sem_waiting, th); + __pthread_unlock(&sem->__sem_lock); + + return did_remove; +} + +int sem_wait(sem_t * sem) +{ + __volatile__ pthread_descr self = thread_self(); + pthread_extricate_if extr; + int already_canceled = 0; + int spurious_wakeup_count; + + /* Set up extrication interface */ + extr.pu_object = sem; + extr.pu_extricate_func = new_sem_extricate_func; + + __pthread_lock(&sem->__sem_lock, self); + if (sem->__sem_value > 0) { + sem->__sem_value--; + __pthread_unlock(&sem->__sem_lock); + return 0; + } + /* Register extrication interface */ + THREAD_SETMEM(self, p_sem_avail, 0); + __pthread_set_own_extricate_if(self, &extr); + /* Enqueue only if not already cancelled. */ + if (!(THREAD_GETMEM(self, p_canceled) + && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE)) + enqueue(&sem->__sem_waiting, self); + else + already_canceled = 1; + __pthread_unlock(&sem->__sem_lock); + + if (already_canceled) { + __pthread_set_own_extricate_if(self, 0); + __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); + } + + /* Wait for sem_post or cancellation, or fall through if already canceled */ + spurious_wakeup_count = 0; + while (1) + { + suspend(self); + if (THREAD_GETMEM(self, p_sem_avail) == 0 + && (THREAD_GETMEM(self, p_woken_by_cancel) == 0 + || THREAD_GETMEM(self, p_cancelstate) != PTHREAD_CANCEL_ENABLE)) + { + /* Count resumes that don't belong to us. */ + spurious_wakeup_count++; + continue; + } + break; + } + __pthread_set_own_extricate_if(self, 0); + + /* Terminate only if the wakeup came from cancellation. */ + /* Otherwise ignore cancellation because we got the semaphore. */ + + if (THREAD_GETMEM(self, p_woken_by_cancel) + && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) { + THREAD_SETMEM(self, p_woken_by_cancel, 0); + __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); + } + /* We got the semaphore */ + return 0; +} + +int sem_trywait(sem_t * sem) +{ + int retval; + + __pthread_lock(&sem->__sem_lock, NULL); + if (sem->__sem_value == 0) { + errno = EAGAIN; + retval = -1; + } else { + sem->__sem_value--; + retval = 0; + } + __pthread_unlock(&sem->__sem_lock); + return retval; +} + +int sem_post(sem_t * sem) +{ + pthread_descr self = thread_self(); + pthread_descr th; + struct pthread_request request; + + if (THREAD_GETMEM(self, p_in_sighandler) == NULL) { + __pthread_lock(&sem->__sem_lock, self); + if (sem->__sem_waiting == NULL) { + if (sem->__sem_value >= SEM_VALUE_MAX) { + /* Overflow */ + errno = ERANGE; + __pthread_unlock(&sem->__sem_lock); + return -1; + } + sem->__sem_value++; + __pthread_unlock(&sem->__sem_lock); + } else { + th = dequeue(&sem->__sem_waiting); + __pthread_unlock(&sem->__sem_lock); + th->p_sem_avail = 1; + WRITE_MEMORY_BARRIER(); + restart(th); + } + } else { + /* If we're in signal handler, delegate post operation to + the thread manager. */ + if (__pthread_manager_request < 0) { + if (__pthread_initialize_manager() < 0) { + errno = EAGAIN; + return -1; + } + } + request.req_kind = REQ_POST; + request.req_args.post = sem; + TEMP_FAILURE_RETRY(write_not_cancel(__pthread_manager_request, + (char *) &request, sizeof(request))); + } + return 0; +} + +int sem_getvalue(sem_t * sem, int * sval) +{ + *sval = sem->__sem_value; + return 0; +} + +int sem_destroy(sem_t * sem) +{ + if (sem->__sem_waiting != NULL) { + __set_errno (EBUSY); + return -1; + } + return 0; +} + +sem_t *sem_open(const char *name, int oflag, ...) +{ + __set_errno (ENOSYS); + return SEM_FAILED; +} + +int sem_close(sem_t *sem) +{ + __set_errno (ENOSYS); + return -1; +} + +int sem_unlink(const char *name) +{ + __set_errno (ENOSYS); + return -1; +} + +int sem_timedwait(sem_t *sem, const struct timespec *abstime) +{ + pthread_descr self = thread_self(); + pthread_extricate_if extr; + int already_canceled = 0; + int spurious_wakeup_count; + + __pthread_lock(&sem->__sem_lock, self); + if (sem->__sem_value > 0) { + --sem->__sem_value; + __pthread_unlock(&sem->__sem_lock); + return 0; + } + + if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) { + /* The standard requires that if the function would block and the + time value is illegal, the function returns with an error. */ + __pthread_unlock(&sem->__sem_lock); + __set_errno (EINVAL); + return -1; + } + + /* Set up extrication interface */ + extr.pu_object = sem; + extr.pu_extricate_func = new_sem_extricate_func; + + /* Register extrication interface */ + THREAD_SETMEM(self, p_sem_avail, 0); + __pthread_set_own_extricate_if(self, &extr); + /* Enqueue only if not already cancelled. */ + if (!(THREAD_GETMEM(self, p_canceled) + && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE)) + enqueue(&sem->__sem_waiting, self); + else + already_canceled = 1; + __pthread_unlock(&sem->__sem_lock); + + if (already_canceled) { + __pthread_set_own_extricate_if(self, 0); + __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); + } + + spurious_wakeup_count = 0; + while (1) + { + if (timedsuspend(self, abstime) == 0) { + int was_on_queue; + + /* __pthread_lock will queue back any spurious restarts that + may happen to it. */ + + __pthread_lock(&sem->__sem_lock, self); + was_on_queue = remove_from_queue(&sem->__sem_waiting, self); + __pthread_unlock(&sem->__sem_lock); + + if (was_on_queue) { + __pthread_set_own_extricate_if(self, 0); + __set_errno (ETIMEDOUT); + return -1; + } + + /* Eat the outstanding restart() from the signaller */ + suspend(self); + } + + if (THREAD_GETMEM(self, p_sem_avail) == 0 + && (THREAD_GETMEM(self, p_woken_by_cancel) == 0 + || THREAD_GETMEM(self, p_cancelstate) != PTHREAD_CANCEL_ENABLE)) + { + /* Count resumes that don't belong to us. */ + spurious_wakeup_count++; + continue; + } + break; + } + + __pthread_set_own_extricate_if(self, 0); + + /* Terminate only if the wakeup came from cancellation. */ + /* Otherwise ignore cancellation because we got the semaphore. */ + + if (THREAD_GETMEM(self, p_woken_by_cancel) + && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) { + THREAD_SETMEM(self, p_woken_by_cancel, 0); + __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); + } + /* We got the semaphore */ + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/semaphore.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/semaphore.h new file mode 100644 index 00000000..3084209f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/semaphore.h @@ -0,0 +1,94 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +#ifndef _SEMAPHORE_H +#define _SEMAPHORE_H 1 + +#include +#include +#ifdef __USE_XOPEN2K +# define __need_timespec +# include +#endif + +#ifndef _PTHREAD_DESCR_DEFINED +/* Thread descriptors. Needed for `sem_t' definition. */ +typedef struct _pthread_descr_struct *_pthread_descr; +# define _PTHREAD_DESCR_DEFINED +#endif + +/* System specific semaphore definition. */ +typedef struct +{ + struct _pthread_fastlock __sem_lock; + int __sem_value; + _pthread_descr __sem_waiting; +} sem_t; + + + +/* Value returned if `sem_open' failed. */ +#define SEM_FAILED ((sem_t *) 0) + +/* Maximum value the semaphore can have. */ +#define SEM_VALUE_MAX (2147483647) + + +__BEGIN_DECLS + +/* Initialize semaphore object SEM to VALUE. If PSHARED then share it + with other processes. */ +extern int sem_init (sem_t *__sem, int __pshared, unsigned int __value) __THROW; + +/* Free resources associated with semaphore object SEM. */ +extern int sem_destroy (sem_t *__sem) __THROW; + +/* Open a named semaphore NAME with open flags OFLAG. */ +extern sem_t *sem_open (__const char *__name, int __oflag, ...) __THROW; + +/* Close descriptor for named semaphore SEM. */ +extern int sem_close (sem_t *__sem) __THROW; + +/* Remove named semaphore NAME. */ +extern int sem_unlink (__const char *__name) __THROW; + +/* Wait for SEM being posted. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern int sem_wait (sem_t *__sem); + +#ifdef __USE_XOPEN2K +/* Similar to `sem_wait' but wait only until ABSTIME. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern int sem_timedwait (sem_t *__restrict __sem, + __const struct timespec *__restrict __abstime); +#endif + +/* Test whether SEM is posted. */ +extern int sem_trywait (sem_t *__sem) __THROW; + +/* Post SEM. */ +extern int sem_post (sem_t *__sem) __THROW; + +/* Get current value of SEM and store it in *SVAL. */ +extern int sem_getvalue (sem_t *__restrict __sem, int *__restrict __sval) + __THROW; + + +__END_DECLS + +#endif /* semaphore.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sighandler.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sighandler.c new file mode 100644 index 00000000..9dd3e228 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sighandler.c @@ -0,0 +1,71 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +/* Signal handlers */ + +#include "internals.h" + + +/* The wrapper around user-provided signal handlers */ +void __pthread_sighandler(int signo, SIGCONTEXT ctx) +{ + pthread_descr self; + char * in_sighandler; + self = check_thread_self(); + + /* If we're in a sigwait operation, just record the signal received + and return without calling the user's handler */ + if (THREAD_GETMEM(self, p_sigwaiting)) { + THREAD_SETMEM(self, p_sigwaiting, 0); + THREAD_SETMEM(self, p_signal, signo); + return; + } + /* Record that we're in a signal handler and call the user's + handler function */ + in_sighandler = THREAD_GETMEM(self, p_in_sighandler); + if (in_sighandler == NULL) + THREAD_SETMEM(self, p_in_sighandler, CURRENT_STACK_FRAME); + CALL_SIGHANDLER(__sighandler[signo].old, signo, ctx); + if (in_sighandler == NULL) + THREAD_SETMEM(self, p_in_sighandler, NULL); +} + +/* The same, this time for real-time signals. */ +void __pthread_sighandler_rt(int signo, struct siginfo *si, + struct ucontext *uc) +{ + pthread_descr self; + char * in_sighandler; + self = check_thread_self(); + + /* If we're in a sigwait operation, just record the signal received + and return without calling the user's handler */ + if (THREAD_GETMEM(self, p_sigwaiting)) { + THREAD_SETMEM(self, p_sigwaiting, 0); + THREAD_SETMEM(self, p_signal, signo); + return; + } + /* Record that we're in a signal handler and call the user's + handler function */ + in_sighandler = THREAD_GETMEM(self, p_in_sighandler); + if (in_sighandler == NULL) + THREAD_SETMEM(self, p_in_sighandler, CURRENT_STACK_FRAME); + __sighandler[signo].rt(signo, si, uc); + if (in_sighandler == NULL) + THREAD_SETMEM(self, p_in_sighandler, NULL); +} + + +/* A signal handler that does nothing */ +void __pthread_null_sighandler(int sig) { } diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/signals.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/signals.c new file mode 100644 index 00000000..02bf1c64 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/signals.c @@ -0,0 +1,215 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +/* Handling of signals */ + +#include +#include +#include "pthread.h" +#include "internals.h" +#include "spinlock.h" +#include + +/* mods for uClibc: __libc_sigaction is not in any standard headers */ +extern __typeof(sigaction) __libc_sigaction; + +int pthread_sigmask(int how, const sigset_t * newmask, sigset_t * oldmask) +{ + sigset_t mask; + + if (newmask != NULL) { + mask = *newmask; + /* Don't allow __pthread_sig_restart to be unmasked. + Don't allow __pthread_sig_cancel to be masked. */ + switch(how) { + case SIG_SETMASK: + sigaddset(&mask, __pthread_sig_restart); + sigdelset(&mask, __pthread_sig_cancel); + if (__pthread_sig_debug > 0) + sigdelset(&mask, __pthread_sig_debug); + break; + case SIG_BLOCK: + sigdelset(&mask, __pthread_sig_cancel); + if (__pthread_sig_debug > 0) + sigdelset(&mask, __pthread_sig_debug); + break; + case SIG_UNBLOCK: + sigdelset(&mask, __pthread_sig_restart); + break; + } + newmask = &mask; + } + if (sigprocmask(how, newmask, oldmask) == -1) + return errno; + else + return 0; +} + +int pthread_kill(pthread_t thread, int signo) +{ + pthread_handle handle = thread_handle(thread); + int pid; + + __pthread_lock(&handle->h_lock, NULL); + if (invalid_handle(handle, thread)) { + __pthread_unlock(&handle->h_lock); + return ESRCH; + } + pid = handle->h_descr->p_pid; + __pthread_unlock(&handle->h_lock); + if (kill(pid, signo) == -1) + return errno; + else + return 0; +} + +union sighandler __sighandler[NSIG] = + { [1 ... NSIG - 1] = { (arch_sighandler_t) SIG_ERR } }; + +/* The wrapper around sigaction. Install our own signal handler + around the signal. */ +int __pthread_sigaction(int sig, const struct sigaction * act, + struct sigaction * oact) +{ + struct sigaction newact; + struct sigaction *newactp; + __sighandler_t old = SIG_DFL; + + if (sig == __pthread_sig_restart || + sig == __pthread_sig_cancel || + (sig == __pthread_sig_debug && __pthread_sig_debug > 0)) + { + __set_errno (EINVAL); + return -1; + } + if (sig > 0 && sig < NSIG) + old = (__sighandler_t) __sighandler[sig].old; + if (act) + { + newact = *act; + if (act->sa_handler != SIG_IGN && act->sa_handler != SIG_DFL + && sig > 0 && sig < NSIG) + { + if (act->sa_flags & SA_SIGINFO) + newact.sa_handler = (__sighandler_t) __pthread_sighandler_rt; + else + newact.sa_handler = (__sighandler_t) __pthread_sighandler; + if (old == SIG_IGN || old == SIG_DFL || old == SIG_ERR) + __sighandler[sig].old = (arch_sighandler_t) act->sa_handler; + } + newactp = &newact; + } + else + newactp = NULL; + if (__libc_sigaction(sig, newactp, oact) == -1) + { + if (act) + __sighandler[sig].old = (arch_sighandler_t) old; + return -1; + } + if (sig > 0 && sig < NSIG) + { + if (oact != NULL + /* We may have inherited SIG_IGN from the parent, so return the + kernel's idea of the signal handler the first time + through. */ + && old != SIG_ERR) + oact->sa_handler = old; + if (act) + /* For the assignment it does not matter whether it's a normal + or real-time signal. */ + __sighandler[sig].old = (arch_sighandler_t) act->sa_handler; + } + return 0; +} +#ifdef SHARED +strong_alias(__pthread_sigaction, __sigaction) +strong_alias(__pthread_sigaction, sigaction) +#endif + +/* sigwait -- synchronously wait for a signal */ +int __pthread_sigwait(const sigset_t * set, int * sig) +{ + __volatile__ pthread_descr self = thread_self(); + sigset_t mask; + int s; + sigjmp_buf jmpbuf; + struct sigaction sa; + + /* Get ready to block all signals except those in set + and the cancellation signal. + Also check that handlers are installed on all signals in set, + and if not, install our dummy handler. This is conformant to + POSIX: "The effect of sigwait() on the signal actions for the + signals in set is unspecified." */ + __sigfillset(&mask); + sigdelset(&mask, __pthread_sig_cancel); + for (s = 1; s < NSIG; s++) { + if (sigismember(set, s) && + s != __pthread_sig_restart && + s != __pthread_sig_cancel && + s != __pthread_sig_debug) { + sigdelset(&mask, s); + if (__sighandler[s].old == (arch_sighandler_t) SIG_ERR || + __sighandler[s].old == (arch_sighandler_t) SIG_DFL || + __sighandler[s].old == (arch_sighandler_t) SIG_IGN) { + sa.sa_handler = __pthread_null_sighandler; + __sigfillset(&sa.sa_mask); + sa.sa_flags = 0; + sigaction(s, &sa, NULL); + } + } + } + /* Test for cancellation */ + if (sigsetjmp(jmpbuf, 1) == 0) { + THREAD_SETMEM(self, p_cancel_jmp, &jmpbuf); + if (! (THREAD_GETMEM(self, p_canceled) + && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE)) { + /* Reset the signal count */ + THREAD_SETMEM(self, p_signal, 0); + /* Say we're in sigwait */ + THREAD_SETMEM(self, p_sigwaiting, 1); + /* Unblock the signals and wait for them */ + sigsuspend(&mask); + } + } + THREAD_SETMEM(self, p_cancel_jmp, NULL); + /* The signals are now reblocked. Check for cancellation */ + pthread_testcancel(); + /* We should have self->p_signal != 0 and equal to the signal received */ + *sig = THREAD_GETMEM(self, p_signal); + return 0; +} +#ifdef SHARED +strong_alias (__pthread_sigwait, sigwait) +#endif + +/* Redefine raise() to send signal to calling thread only, + as per POSIX 1003.1c */ +int __pthread_raise (int sig) +{ + int retcode = pthread_kill(pthread_self(), sig); + if (retcode == 0) + return 0; + else { + errno = retcode; + return -1; + } +} +#ifdef SHARED +strong_alias (__pthread_raise, raise) +#endif + +/* This files handles cancellation internally. */ +LIBC_CANCEL_HANDLED (); diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/specific.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/specific.c new file mode 100644 index 00000000..764bf1e9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/specific.c @@ -0,0 +1,243 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +/* Thread-specific data */ + +#include +#include +#include +#include "pthread.h" +#include "internals.h" +#include "spinlock.h" +#include "restart.h" +#include +#include + +/* Table of keys. */ + +static struct pthread_key_struct pthread_keys[PTHREAD_KEYS_MAX] = + { { 0, NULL } }; + +/* For debugging purposes put the maximum number of keys in a variable. */ +const int __linuxthreads_pthread_keys_max = PTHREAD_KEYS_MAX; +const int __linuxthreads_pthread_key_2ndlevel_size = PTHREAD_KEY_2NDLEVEL_SIZE; + +/* Mutex to protect access to pthread_keys */ + +static pthread_mutex_t pthread_keys_mutex = PTHREAD_MUTEX_INITIALIZER; + +/* Create a new key */ + +int __pthread_key_create(pthread_key_t * key, destr_function destr) +{ + int i; + + pthread_mutex_lock(&pthread_keys_mutex); + for (i = 0; i < PTHREAD_KEYS_MAX; i++) { + if (! pthread_keys[i].in_use) { + /* Mark key in use */ + pthread_keys[i].in_use = 1; + pthread_keys[i].destr = destr; + pthread_mutex_unlock(&pthread_keys_mutex); + *key = i; + return 0; + } + } + pthread_mutex_unlock(&pthread_keys_mutex); + return EAGAIN; +} +strong_alias (__pthread_key_create, pthread_key_create) + +/* Reset deleted key's value to NULL in each live thread. + * NOTE: this executes in the context of the thread manager! */ + +struct pthread_key_delete_helper_args { + /* Damn, we need lexical closures in C! ;) */ + unsigned int idx1st, idx2nd; + pthread_descr self; +}; + +static void pthread_key_delete_helper(void *arg, pthread_descr th) +{ + struct pthread_key_delete_helper_args *args = arg; + unsigned int idx1st = args->idx1st; + unsigned int idx2nd = args->idx2nd; + pthread_descr self = args->self; + + if (self == 0) + self = args->self = thread_self(); + + if (!th->p_terminated) { + /* pthread_exit() may try to free th->p_specific[idx1st] concurrently. */ + __pthread_lock(th->p_lock, self); + if (th->p_specific[idx1st] != NULL) + th->p_specific[idx1st][idx2nd] = NULL; + __pthread_unlock(th->p_lock); + } +} + +/* Delete a key */ +int pthread_key_delete(pthread_key_t key) +{ + pthread_descr self = thread_self(); + + pthread_mutex_lock(&pthread_keys_mutex); + if (key >= PTHREAD_KEYS_MAX || !pthread_keys[key].in_use) { + pthread_mutex_unlock(&pthread_keys_mutex); + return EINVAL; + } + pthread_keys[key].in_use = 0; + pthread_keys[key].destr = NULL; + + /* Set the value of the key to NULL in all running threads, so + that if the key is reallocated later by pthread_key_create, its + associated values will be NULL in all threads. + + If no threads have been created yet, or if we are exiting, clear + it just in the current thread. */ + + struct pthread_key_delete_helper_args args; + args.idx1st = key / PTHREAD_KEY_2NDLEVEL_SIZE; + args.idx2nd = key % PTHREAD_KEY_2NDLEVEL_SIZE; + if (__pthread_manager_request != -1 + && !(__builtin_expect (__pthread_exit_requested, 0))) + { + struct pthread_request request; + + args.self = 0; + + request.req_thread = self; + request.req_kind = REQ_FOR_EACH_THREAD; + request.req_args.for_each.arg = &args; + request.req_args.for_each.fn = pthread_key_delete_helper; + + TEMP_FAILURE_RETRY(write_not_cancel(__pthread_manager_request, + (char *) &request, sizeof(request))); + suspend(self); + } + else + { + if (self->p_specific[args.idx1st] != NULL) + self->p_specific[args.idx1st][args.idx2nd] = NULL; + } + + pthread_mutex_unlock(&pthread_keys_mutex); + return 0; +} + +/* Set the value of a key */ + +int __pthread_setspecific(pthread_key_t key, const void * pointer) +{ + pthread_descr self = thread_self(); + unsigned int idx1st, idx2nd; + + if (key >= PTHREAD_KEYS_MAX || !pthread_keys[key].in_use) + return EINVAL; + idx1st = key / PTHREAD_KEY_2NDLEVEL_SIZE; + idx2nd = key % PTHREAD_KEY_2NDLEVEL_SIZE; + if (THREAD_GETMEM_NC(self, p_specific[idx1st]) == NULL) { + void *newp = calloc(PTHREAD_KEY_2NDLEVEL_SIZE, sizeof (void *)); + if (newp == NULL) + return ENOMEM; + THREAD_SETMEM_NC(self, p_specific[idx1st], newp); + } + THREAD_GETMEM_NC(self, p_specific[idx1st])[idx2nd] = (void *) pointer; + return 0; +} +strong_alias (__pthread_setspecific, pthread_setspecific) + +/* Get the value of a key */ + +void * __pthread_getspecific(pthread_key_t key) +{ + pthread_descr self = thread_self(); + unsigned int idx1st, idx2nd; + + if (key >= PTHREAD_KEYS_MAX) + return NULL; + idx1st = key / PTHREAD_KEY_2NDLEVEL_SIZE; + idx2nd = key % PTHREAD_KEY_2NDLEVEL_SIZE; + if (THREAD_GETMEM_NC(self, p_specific[idx1st]) == NULL + || !pthread_keys[key].in_use) + return NULL; + return THREAD_GETMEM_NC(self, p_specific[idx1st])[idx2nd]; +} +strong_alias (__pthread_getspecific, pthread_getspecific) + +/* Call the destruction routines on all keys */ + +void __pthread_destroy_specifics() +{ + pthread_descr self = thread_self(); + int i, j, round, found_nonzero; + destr_function destr; + void * data; + + for (round = 0, found_nonzero = 1; + found_nonzero && round < PTHREAD_DESTRUCTOR_ITERATIONS; + round++) { + found_nonzero = 0; + for (i = 0; i < PTHREAD_KEY_1STLEVEL_SIZE; i++) + if (THREAD_GETMEM_NC(self, p_specific[i]) != NULL) + for (j = 0; j < PTHREAD_KEY_2NDLEVEL_SIZE; j++) { + destr = pthread_keys[i * PTHREAD_KEY_2NDLEVEL_SIZE + j].destr; + data = THREAD_GETMEM_NC(self, p_specific[i])[j]; + if (destr != NULL && data != NULL) { + THREAD_GETMEM_NC(self, p_specific[i])[j] = NULL; + destr(data); + found_nonzero = 1; + } + } + } + __pthread_lock(THREAD_GETMEM(self, p_lock), self); + for (i = 0; i < PTHREAD_KEY_1STLEVEL_SIZE; i++) { + if (THREAD_GETMEM_NC(self, p_specific[i]) != NULL) { + void *p = THREAD_GETMEM_NC(self, p_specific[i]); + THREAD_SETMEM_NC(self, p_specific[i], NULL); + free(p); + } + } + __pthread_unlock(THREAD_GETMEM(self, p_lock)); +} + +#if !(USE_TLS && HAVE___THREAD) + +/* Thread-specific data for libc. */ + +int +__pthread_internal_tsd_set (int key, const void * pointer) +{ + pthread_descr self = thread_self(); + + THREAD_SETMEM_NC(self, p_libc_specific[key], (void *) pointer); + return 0; +} + +void * +__pthread_internal_tsd_get (int key) +{ + pthread_descr self = thread_self(); + + return THREAD_GETMEM_NC(self, p_libc_specific[key]); +} + +void ** __attribute__ ((__const__)) +__pthread_internal_tsd_address (int key) +{ + pthread_descr self = thread_self(); + return &self->p_libc_specific[key]; +} + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/spinlock.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/spinlock.c new file mode 100644 index 00000000..f0cf19c5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/spinlock.c @@ -0,0 +1,732 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1998 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +/* Internal locks */ + +#include +#include +#include +#include +#include +#include "pthread.h" +#include "internals.h" +#include "spinlock.h" +#include "restart.h" + +static void __pthread_acquire(int * spinlock); + +static __inline__ void __pthread_release(int * spinlock) +{ + WRITE_MEMORY_BARRIER(); + *spinlock = __LT_SPINLOCK_INIT; + __asm__ __volatile__ ("" : "=m" (*spinlock) : "m" (*spinlock)); +} + + +/* The status field of a spinlock is a pointer whose least significant + bit is a locked flag. + + Thus the field values have the following meanings: + + status == 0: spinlock is free + status == 1: spinlock is taken; no thread is waiting on it + + (status & 1) == 1: spinlock is taken and (status & ~1L) is a + pointer to the first waiting thread; other + waiting threads are linked via the p_nextlock + field. + (status & 1) == 0: same as above, but spinlock is not taken. + + The waiting list is not sorted by priority order. + Actually, we always insert at top of list (sole insertion mode + that can be performed without locking). + For __pthread_unlock, we perform a linear search in the list + to find the highest-priority, oldest waiting thread. + This is safe because there are no concurrent __pthread_unlock + operations -- only the thread that locked the mutex can unlock it. */ + + +void internal_function __pthread_lock(struct _pthread_fastlock * lock, + pthread_descr self) +{ +#if defined HAS_COMPARE_AND_SWAP + long oldstatus, newstatus; + int successful_seizure, spurious_wakeup_count; + int spin_count; +#endif + +#if defined TEST_FOR_COMPARE_AND_SWAP + if (!__pthread_has_cas) +#endif +#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP + { + __pthread_acquire(&lock->__spinlock); + return; + } +#endif + +#if defined HAS_COMPARE_AND_SWAP + /* First try it without preparation. Maybe it's a completely + uncontested lock. */ + if (lock->__status == 0 && __compare_and_swap (&lock->__status, 0, 1)) + return; + + spurious_wakeup_count = 0; + spin_count = 0; + + /* On SMP, try spinning to get the lock. */ + + if (__pthread_smp_kernel) { + int max_count = lock->__spinlock * 2 + 10; + + if (max_count > MAX_ADAPTIVE_SPIN_COUNT) + max_count = MAX_ADAPTIVE_SPIN_COUNT; + + for (spin_count = 0; spin_count < max_count; spin_count++) { + if (((oldstatus = lock->__status) & 1) == 0) { + if(__compare_and_swap(&lock->__status, oldstatus, oldstatus | 1)) + { + if (spin_count) + lock->__spinlock += (spin_count - lock->__spinlock) / 8; + READ_MEMORY_BARRIER(); + return; + } + } +#ifdef BUSY_WAIT_NOP + BUSY_WAIT_NOP; +#endif + __asm__ __volatile__ ("" : "=m" (lock->__status) : "m" (lock->__status)); + } + + lock->__spinlock += (spin_count - lock->__spinlock) / 8; + } + +again: + + /* No luck, try once more or suspend. */ + + do { + oldstatus = lock->__status; + successful_seizure = 0; + + if ((oldstatus & 1) == 0) { + newstatus = oldstatus | 1; + successful_seizure = 1; + } else { + if (self == NULL) + self = thread_self(); + newstatus = (long) self | 1; + } + + if (self != NULL) { + THREAD_SETMEM(self, p_nextlock, (pthread_descr) (oldstatus)); + /* Make sure the store in p_nextlock completes before performing + the compare-and-swap */ + MEMORY_BARRIER(); + } + } while(! __compare_and_swap(&lock->__status, oldstatus, newstatus)); + + /* Suspend with guard against spurious wakeup. + This can happen in pthread_cond_timedwait_relative, when the thread + wakes up due to timeout and is still on the condvar queue, and then + locks the queue to remove itself. At that point it may still be on the + queue, and may be resumed by a condition signal. */ + + if (!successful_seizure) { + for (;;) { + suspend(self); + if (self->p_nextlock != NULL) { + /* Count resumes that don't belong to us. */ + spurious_wakeup_count++; + continue; + } + break; + } + goto again; + } + + /* Put back any resumes we caught that don't belong to us. */ + while (spurious_wakeup_count--) + restart(self); + + READ_MEMORY_BARRIER(); +#endif +} + +int __pthread_unlock(struct _pthread_fastlock * lock) +{ +#if defined HAS_COMPARE_AND_SWAP + long oldstatus; + pthread_descr thr, * ptr, * maxptr; + int maxprio; +#endif + +#if defined TEST_FOR_COMPARE_AND_SWAP + if (!__pthread_has_cas) +#endif +#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP + { + __pthread_release(&lock->__spinlock); + return 0; + } +#endif + +#if defined HAS_COMPARE_AND_SWAP + WRITE_MEMORY_BARRIER(); + +again: + while ((oldstatus = lock->__status) == 1) { + if (__compare_and_swap_with_release_semantics(&lock->__status, + oldstatus, 0)) + return 0; + } + + /* Find thread in waiting queue with maximal priority */ + ptr = (pthread_descr *) &lock->__status; + thr = (pthread_descr) (oldstatus & ~1L); + maxprio = 0; + maxptr = ptr; + + /* Before we iterate over the wait queue, we need to execute + a read barrier, otherwise we may read stale contents of nodes that may + just have been inserted by other processors. One read barrier is enough to + ensure we have a stable list; we don't need one for each pointer chase + through the list, because we are the owner of the lock; other threads + can only add nodes at the front; if a front node is consistent, + the ones behind it must also be. */ + + READ_MEMORY_BARRIER(); + + while (thr != 0) { + if (thr->p_priority >= maxprio) { + maxptr = ptr; + maxprio = thr->p_priority; + } + ptr = &(thr->p_nextlock); + thr = (pthread_descr)((long)(thr->p_nextlock) & ~1L); + } + + /* Remove max prio thread from waiting list. */ + if (maxptr == (pthread_descr *) &lock->__status) { + /* If max prio thread is at head, remove it with compare-and-swap + to guard against concurrent lock operation. This removal + also has the side effect of marking the lock as released + because the new status comes from thr->p_nextlock whose + least significant bit is clear. */ + thr = (pthread_descr) (oldstatus & ~1L); + if (! __compare_and_swap_with_release_semantics + (&lock->__status, oldstatus, (long)(thr->p_nextlock) & ~1L)) + goto again; + } else { + /* No risk of concurrent access, remove max prio thread normally. + But in this case we must also flip the least significant bit + of the status to mark the lock as released. */ + thr = (pthread_descr)((long)*maxptr & ~1L); + *maxptr = thr->p_nextlock; + + /* Ensure deletion from linked list completes before we + release the lock. */ + WRITE_MEMORY_BARRIER(); + + do { + oldstatus = lock->__status; + } while (!__compare_and_swap_with_release_semantics(&lock->__status, + oldstatus, oldstatus & ~1L)); + } + + /* Wake up the selected waiting thread. Woken thread can check + its own p_nextlock field for NULL to detect that it has been removed. No + barrier is needed here, since restart() and suspend() take + care of memory synchronization. */ + + thr->p_nextlock = NULL; + restart(thr); + + return 0; +#endif +} + +/* + * Alternate fastlocks do not queue threads directly. Instead, they queue + * these wait queue node structures. When a timed wait wakes up due to + * a timeout, it can leave its wait node in the queue (because there + * is no safe way to remove from the quue). Some other thread will + * deallocate the abandoned node. + */ + + +struct wait_node { + struct wait_node *next; /* Next node in null terminated linked list */ + pthread_descr thr; /* The thread waiting with this node */ + int abandoned; /* Atomic flag */ +}; + +static long wait_node_free_list; +static int wait_node_free_list_spinlock; + +/* Allocate a new node from the head of the free list using an atomic + operation, or else using malloc if that list is empty. A fundamental + assumption here is that we can safely access wait_node_free_list->next. + That's because we never free nodes once we allocate them, so a pointer to a + node remains valid indefinitely. */ + +static struct wait_node *wait_node_alloc(void) +{ + struct wait_node *new_node = 0; + + __pthread_acquire(&wait_node_free_list_spinlock); + if (wait_node_free_list != 0) { + new_node = (struct wait_node *) wait_node_free_list; + wait_node_free_list = (long) new_node->next; + } + WRITE_MEMORY_BARRIER(); + __pthread_release(&wait_node_free_list_spinlock); + + if (new_node == 0) + return malloc(sizeof *wait_node_alloc()); + + return new_node; +} + +/* Return a node to the head of the free list using an atomic + operation. */ + +static void wait_node_free(struct wait_node *wn) +{ + __pthread_acquire(&wait_node_free_list_spinlock); + wn->next = (struct wait_node *) wait_node_free_list; + wait_node_free_list = (long) wn; + WRITE_MEMORY_BARRIER(); + __pthread_release(&wait_node_free_list_spinlock); + return; +} + +#if defined HAS_COMPARE_AND_SWAP + +/* Remove a wait node from the specified queue. It is assumed + that the removal takes place concurrently with only atomic insertions at the + head of the queue. */ + +static void wait_node_dequeue(struct wait_node **pp_head, + struct wait_node **pp_node, + struct wait_node *p_node) +{ + /* If the node is being deleted from the head of the + list, it must be deleted using atomic compare-and-swap. + Otherwise it can be deleted in the straightforward way. */ + + if (pp_node == pp_head) { + /* We don't need a read barrier between these next two loads, + because it is assumed that the caller has already ensured + the stability of *p_node with respect to p_node. */ + + long oldvalue = (long) p_node; + long newvalue = (long) p_node->next; + + if (__compare_and_swap((long *) pp_node, oldvalue, newvalue)) + return; + + /* Oops! Compare and swap failed, which means the node is + no longer first. We delete it using the ordinary method. But we don't + know the identity of the node which now holds the pointer to the node + being deleted, so we must search from the beginning. */ + + for (pp_node = pp_head; p_node != *pp_node; ) { + pp_node = &(*pp_node)->next; + READ_MEMORY_BARRIER(); /* Stabilize *pp_node for next iteration. */ + } + } + + *pp_node = p_node->next; + return; +} + +#endif + +void __pthread_alt_lock(struct _pthread_fastlock * lock, + pthread_descr self) +{ +#if defined HAS_COMPARE_AND_SWAP + long oldstatus, newstatus; +#endif + struct wait_node wait_node; + +#if defined TEST_FOR_COMPARE_AND_SWAP + if (!__pthread_has_cas) +#endif +#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP + { + int suspend_needed = 0; + __pthread_acquire(&lock->__spinlock); + + if (lock->__status == 0) + lock->__status = 1; + else { + if (self == NULL) + self = thread_self(); + + wait_node.abandoned = 0; + wait_node.next = (struct wait_node *) lock->__status; + wait_node.thr = self; + lock->__status = (long) &wait_node; + suspend_needed = 1; + } + + __pthread_release(&lock->__spinlock); + + if (suspend_needed) + suspend (self); + return; + } +#endif + +#if defined HAS_COMPARE_AND_SWAP + do { + oldstatus = lock->__status; + if (oldstatus == 0) { + newstatus = 1; + } else { + if (self == NULL) + self = thread_self(); + wait_node.thr = self; + newstatus = (long) &wait_node; + } + wait_node.abandoned = 0; + wait_node.next = (struct wait_node *) oldstatus; + /* Make sure the store in wait_node.next completes before performing + the compare-and-swap */ + MEMORY_BARRIER(); + } while(! __compare_and_swap(&lock->__status, oldstatus, newstatus)); + + /* Suspend. Note that unlike in __pthread_lock, we don't worry + here about spurious wakeup. That's because this lock is not + used in situations where that can happen; the restart can + only come from the previous lock owner. */ + + if (oldstatus != 0) + suspend(self); + + READ_MEMORY_BARRIER(); +#endif +} + +/* Timed-out lock operation; returns 0 to indicate timeout. */ + +int __pthread_alt_timedlock(struct _pthread_fastlock * lock, + pthread_descr self, const struct timespec *abstime) +{ + long oldstatus = 0; +#if defined HAS_COMPARE_AND_SWAP + long newstatus; +#endif + struct wait_node *p_wait_node = wait_node_alloc(); + + /* Out of memory, just give up and do ordinary lock. */ + if (p_wait_node == 0) { + __pthread_alt_lock(lock, self); + return 1; + } + +#if defined TEST_FOR_COMPARE_AND_SWAP + if (!__pthread_has_cas) +#endif +#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP + { + __pthread_acquire(&lock->__spinlock); + + if (lock->__status == 0) + lock->__status = 1; + else { + if (self == NULL) + self = thread_self(); + + p_wait_node->abandoned = 0; + p_wait_node->next = (struct wait_node *) lock->__status; + p_wait_node->thr = self; + lock->__status = (long) p_wait_node; + oldstatus = 1; /* force suspend */ + } + + __pthread_release(&lock->__spinlock); + goto suspend; + } +#endif + +#if defined HAS_COMPARE_AND_SWAP + do { + oldstatus = lock->__status; + if (oldstatus == 0) { + newstatus = 1; + } else { + if (self == NULL) + self = thread_self(); + p_wait_node->thr = self; + newstatus = (long) p_wait_node; + } + p_wait_node->abandoned = 0; + p_wait_node->next = (struct wait_node *) oldstatus; + /* Make sure the store in wait_node.next completes before performing + the compare-and-swap */ + MEMORY_BARRIER(); + } while(! __compare_and_swap(&lock->__status, oldstatus, newstatus)); +#endif + +#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP + suspend: +#endif + + /* If we did not get the lock, do a timed suspend. If we wake up due + to a timeout, then there is a race; the old lock owner may try + to remove us from the queue. This race is resolved by us and the owner + doing an atomic testandset() to change the state of the wait node from 0 + to 1. If we succeed, then it's a timeout and we abandon the node in the + queue. If we fail, it means the owner gave us the lock. */ + + if (oldstatus != 0) { + if (timedsuspend(self, abstime) == 0) { + if (!testandset(&p_wait_node->abandoned)) + return 0; /* Timeout! */ + + /* Eat oustanding resume from owner, otherwise wait_node_free() below + will race with owner's wait_node_dequeue(). */ + suspend(self); + } + } + + wait_node_free(p_wait_node); + + READ_MEMORY_BARRIER(); + + return 1; /* Got the lock! */ +} + +void __pthread_alt_unlock(struct _pthread_fastlock *lock) +{ + struct wait_node *p_node, **pp_node, *p_max_prio, **pp_max_prio; + struct wait_node ** const pp_head = (struct wait_node **) &lock->__status; + int maxprio; + + WRITE_MEMORY_BARRIER(); + +#if defined TEST_FOR_COMPARE_AND_SWAP + if (!__pthread_has_cas) +#endif +#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP + { + __pthread_acquire(&lock->__spinlock); + } +#endif + + while (1) { + + /* If no threads are waiting for this lock, try to just + atomically release it. */ +#if defined TEST_FOR_COMPARE_AND_SWAP + if (!__pthread_has_cas) +#endif +#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP + { + if (lock->__status == 0 || lock->__status == 1) { + lock->__status = 0; + break; + } + } +#endif + +#if defined TEST_FOR_COMPARE_AND_SWAP + else +#endif + +#if defined HAS_COMPARE_AND_SWAP + { + long oldstatus = lock->__status; + if (oldstatus == 0 || oldstatus == 1) { + if (__compare_and_swap_with_release_semantics (&lock->__status, oldstatus, 0)) + break; + else + continue; + } + } +#endif + + /* Process the entire queue of wait nodes. Remove all abandoned + wait nodes and put them into the global free queue, and + remember the one unabandoned node which refers to the thread + having the highest priority. */ + + pp_max_prio = pp_node = pp_head; + p_max_prio = p_node = *pp_head; + maxprio = INT_MIN; + + READ_MEMORY_BARRIER(); /* Prevent access to stale data through p_node */ + + while (p_node != (struct wait_node *) 1) { + int prio; + + if (p_node->abandoned) { + /* Remove abandoned node. */ +#if defined TEST_FOR_COMPARE_AND_SWAP + if (!__pthread_has_cas) +#endif +#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP + *pp_node = p_node->next; +#endif +#if defined TEST_FOR_COMPARE_AND_SWAP + else +#endif +#if defined HAS_COMPARE_AND_SWAP + wait_node_dequeue(pp_head, pp_node, p_node); +#endif + wait_node_free(p_node); + /* Note that the next assignment may take us to the beginning + of the queue, to newly inserted nodes, if pp_node == pp_head. + In that case we need a memory barrier to stabilize the first of + these new nodes. */ + p_node = *pp_node; + if (pp_node == pp_head) + READ_MEMORY_BARRIER(); /* No stale reads through p_node */ + continue; + } else if ((prio = p_node->thr->p_priority) >= maxprio) { + /* Otherwise remember it if its thread has a higher or equal priority + compared to that of any node seen thus far. */ + maxprio = prio; + pp_max_prio = pp_node; + p_max_prio = p_node; + } + + /* This canno6 jump backward in the list, so no further read + barrier is needed. */ + pp_node = &p_node->next; + p_node = *pp_node; + } + + /* If all threads abandoned, go back to top */ + if (maxprio == INT_MIN) + continue; + + ASSERT (p_max_prio != (struct wait_node *) 1); + + /* Now we want to to remove the max priority thread's wait node from + the list. Before we can do this, we must atomically try to change the + node's abandon state from zero to nonzero. If we succeed, that means we + have the node that we will wake up. If we failed, then it means the + thread timed out and abandoned the node in which case we repeat the + whole unlock operation. */ + + if (!testandset(&p_max_prio->abandoned)) { +#if defined TEST_FOR_COMPARE_AND_SWAP + if (!__pthread_has_cas) +#endif +#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP + *pp_max_prio = p_max_prio->next; +#endif +#if defined TEST_FOR_COMPARE_AND_SWAP + else +#endif +#if defined HAS_COMPARE_AND_SWAP + wait_node_dequeue(pp_head, pp_max_prio, p_max_prio); +#endif + + /* Release the spinlock *before* restarting. */ +#if defined TEST_FOR_COMPARE_AND_SWAP + if (!__pthread_has_cas) +#endif +#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP + { + __pthread_release(&lock->__spinlock); + } +#endif + + restart(p_max_prio->thr); + + return; + } + } + +#if defined TEST_FOR_COMPARE_AND_SWAP + if (!__pthread_has_cas) +#endif +#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP + { + __pthread_release(&lock->__spinlock); + } +#endif +} + + +/* Compare-and-swap emulation with a spinlock */ + +#ifdef TEST_FOR_COMPARE_AND_SWAP +int __pthread_has_cas = 0; +#endif + +#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP + +int __pthread_compare_and_swap(long * ptr, long oldval, long newval, + int * spinlock) +{ + int res; + + __pthread_acquire(spinlock); + + if (*ptr == oldval) { + *ptr = newval; res = 1; + } else { + res = 0; + } + + __pthread_release(spinlock); + + return res; +} + +#endif + +/* The retry strategy is as follows: + - We test and set the spinlock MAX_SPIN_COUNT times, calling + sched_yield() each time. This gives ample opportunity for other + threads with priority >= our priority to make progress and + release the spinlock. + - If a thread with priority < our priority owns the spinlock, + calling sched_yield() repeatedly is useless, since we're preventing + the owning thread from making progress and releasing the spinlock. + So, after MAX_SPIN_LOCK attemps, we suspend the calling thread + using nanosleep(). This again should give time to the owning thread + for releasing the spinlock. + Notice that the nanosleep() interval must not be too small, + since the kernel does busy-waiting for short intervals in a realtime + process (!). The smallest duration that guarantees thread + suspension is currently 2ms. + - When nanosleep() returns, we try again, doing MAX_SPIN_COUNT + sched_yield(), then sleeping again if needed. */ + +static void __pthread_acquire(int * spinlock) +{ + int cnt = 0; + struct timespec tm; + + READ_MEMORY_BARRIER(); + + while (testandset(spinlock)) { + if (cnt < MAX_SPIN_COUNT) { + sched_yield(); + cnt++; + } else { + tm.tv_sec = 0; + tm.tv_nsec = SPIN_SLEEP_DURATION; + nanosleep(&tm, NULL); + cnt = 0; + } + } +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/spinlock.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/spinlock.h new file mode 100644 index 00000000..2a3c2277 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/spinlock.h @@ -0,0 +1,220 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1998 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +#include + + +/* There are 2 compare and swap synchronization primitives with + different semantics: + + 1. compare_and_swap, which has acquire semantics (i.e. it + completes befor subsequent writes.) + 2. compare_and_swap_with_release_semantics, which has release + semantics (it completes after previous writes.) + + For those platforms on which they are the same. HAS_COMPARE_AND_SWAP + should be defined. For those platforms on which they are different, + HAS_COMPARE_AND_SWAP_WITH_RELEASE_SEMANTICS has to be defined. */ + +#ifndef HAS_COMPARE_AND_SWAP +#ifdef HAS_COMPARE_AND_SWAP_WITH_RELEASE_SEMANTICS +#define HAS_COMPARE_AND_SWAP +#endif +#endif + +#if defined(TEST_FOR_COMPARE_AND_SWAP) + +extern int __pthread_has_cas; +extern int __pthread_compare_and_swap(long * ptr, long oldval, long newval, + int * spinlock); + +static __inline__ int compare_and_swap(long * ptr, long oldval, long newval, + int * spinlock) +{ + if (__builtin_expect (__pthread_has_cas, 1)) + return __compare_and_swap(ptr, oldval, newval); + else + return __pthread_compare_and_swap(ptr, oldval, newval, spinlock); +} + +#elif defined(HAS_COMPARE_AND_SWAP) + +#ifdef IMPLEMENT_TAS_WITH_CAS +#define testandset(p) !__compare_and_swap((long int *) p, 0, 1) +#endif + +#ifdef HAS_COMPARE_AND_SWAP_WITH_RELEASE_SEMANTICS + +static __inline__ int +compare_and_swap_with_release_semantics (long * ptr, long oldval, + long newval, int * spinlock) +{ + return __compare_and_swap_with_release_semantics (ptr, oldval, + newval); +} + +#endif + +static __inline__ int compare_and_swap(long * ptr, long oldval, long newval, + int * spinlock) +{ + return __compare_and_swap(ptr, oldval, newval); +} + +#else + +extern int __pthread_compare_and_swap(long * ptr, long oldval, long newval, + int * spinlock); + +static __inline__ int compare_and_swap(long * ptr, long oldval, long newval, + int * spinlock) +{ + return __pthread_compare_and_swap(ptr, oldval, newval, spinlock); +} + +#endif + +#ifndef HAS_COMPARE_AND_SWAP_WITH_RELEASE_SEMANTICS +#define compare_and_swap_with_release_semantics compare_and_swap +#define __compare_and_swap_with_release_semantics __compare_and_swap +#endif + +/* Internal locks */ + +extern void internal_function __pthread_lock(struct _pthread_fastlock * lock, + pthread_descr self); +extern int __pthread_unlock(struct _pthread_fastlock *lock); + +static __inline__ void __pthread_init_lock(struct _pthread_fastlock * lock) +{ + lock->__status = 0; + lock->__spinlock = __LT_SPINLOCK_INIT; +} + +static __inline__ int __pthread_trylock (struct _pthread_fastlock * lock) +{ +#if defined TEST_FOR_COMPARE_AND_SWAP + if (!__pthread_has_cas) +#endif +#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP + { + return (testandset(&lock->__spinlock) ? EBUSY : 0); + } +#endif + +#if defined HAS_COMPARE_AND_SWAP + do { + if (lock->__status != 0) return EBUSY; + } while(! __compare_and_swap(&lock->__status, 0, 1)); + return 0; +#endif +} + +/* Variation of internal lock used for pthread_mutex_t, supporting + timed-out waits. Warning: do not mix these operations with the above ones + over the same lock object! */ + +extern void __pthread_alt_lock(struct _pthread_fastlock * lock, + pthread_descr self); + +extern int __pthread_alt_timedlock(struct _pthread_fastlock * lock, + pthread_descr self, const struct timespec *abstime); + +extern void __pthread_alt_unlock(struct _pthread_fastlock *lock); + +static __inline__ void __pthread_alt_init_lock(struct _pthread_fastlock * lock) +{ + lock->__status = 0; + lock->__spinlock = __LT_SPINLOCK_INIT; +} + +static __inline__ int __pthread_alt_trylock (struct _pthread_fastlock * lock) +{ +#if defined TEST_FOR_COMPARE_AND_SWAP + if (!__pthread_has_cas) +#endif +#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP + { + int res = EBUSY; + + if (testandset(&lock->__spinlock) == 0) + { + if (lock->__status == 0) + { + lock->__status = 1; + WRITE_MEMORY_BARRIER(); + res = 0; + } + lock->__spinlock = __LT_SPINLOCK_INIT; + } + return res; + } +#endif + +#if defined HAS_COMPARE_AND_SWAP + do { + if (lock->__status != 0) return EBUSY; + } while(! compare_and_swap(&lock->__status, 0, 1, &lock->__spinlock)); + return 0; +#endif +} + +/* Operations on pthread_atomic, which is defined in internals.h */ + +static __inline__ long +pthread_atomic_increment (struct pthread_atomic *pa) +{ + long oldval; + + do { + oldval = pa->p_count; + } while (!compare_and_swap(&pa->p_count, oldval, oldval + 1, &pa->p_spinlock)); + + return oldval; +} + + +static __inline__ long +pthread_atomic_decrement (struct pthread_atomic *pa) +{ + long oldval; + + do { + oldval = pa->p_count; + } while (!compare_and_swap(&pa->p_count, oldval, oldval - 1, &pa->p_spinlock)); + + return oldval; +} + + +static __inline__ __attribute__((always_inline)) void +__pthread_set_own_extricate_if (pthread_descr self, pthread_extricate_if *peif) +{ + /* Only store a non-null peif if the thread has cancellation enabled. + Otherwise pthread_cancel will unconditionally call the extricate handler, + and restart the thread giving rise to forbidden spurious wakeups. */ + if (peif == NULL + || THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) + { + /* If we are removing the extricate interface, we need to synchronize + against pthread_cancel so that it does not continue with a pointer + to a deallocated pthread_extricate_if struct! The thread lock + is (ab)used for this synchronization purpose. */ + if (peif == NULL) + __pthread_lock (THREAD_GETMEM(self, p_lock), self); + THREAD_SETMEM(self, p_extricate, peif); + if (peif == NULL) + __pthread_unlock (THREAD_GETMEM(self, p_lock)); + } +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/alpha/elf/pt-initfini.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/alpha/elf/pt-initfini.c new file mode 100644 index 00000000..ee255821 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/alpha/elf/pt-initfini.c @@ -0,0 +1,90 @@ +/* Special .init and .fini section support for Alpha. Linuxthreads version. + Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This file is compiled into assembly code which is then munged by a sed + script into two files: crti.s and crtn.s. + + * crti.s puts a function prologue at the beginning of the .init and .fini + sections and defines global symbols for those addresses, so they can be + called as functions. + + * crtn.s puts the corresponding function epilogues in the .init and .fini + sections. + + This differs from what would be generated by the generic code in that + we save and restore the GP within the function. In order for linker + relaxation to work, the value in the GP register on exit from a function + must be valid for the function entry point. Normally, a function is + contained within one object file and this is not an issue, provided + that the function reloads the gp after making any function calls. + However, _init and _fini are constructed from pieces of many object + files, all of which may have different GP values. So we must reload + the GP value from crti.o in crtn.o. */ + +__asm__ (" \n\ +#include \"defs.h\" \n\ + \n\ +/*@HEADER_ENDS*/ \n\ + \n\ +/*@_init_PROLOG_BEGINS*/ \n\ + .section .init, \"ax\", @progbits \n\ + .globl _init \n\ + .type _init,@function \n\ + .usepv _init,std \n\ +_init: \n\ + ldgp $29, 0($27) \n\ + subq $30, 16, $30 \n\ + stq $26, 0($30) \n\ + stq $29, 8($30) \n\ + jsr $26, __pthread_initialize_minimal \n\ + ldq $29, 8($30) \n\ + .align 3 \n\ +/*@_init_PROLOG_ENDS*/ \n\ + \n\ +/*@_init_EPILOG_BEGINS*/ \n\ + .section .init, \"ax\", @progbits \n\ + ldq $26, 0($30) \n\ + ldq $29, 8($30) \n\ + addq $30, 16, $30 \n\ + ret \n\ +/*@_init_EPILOG_ENDS*/ \n\ + \n\ +/*@_fini_PROLOG_BEGINS*/ \n\ + .section .fini, \"ax\", @progbits \n\ + .globl _fini \n\ + .type _fini,@function \n\ + .usepv _fini,std \n\ +_fini: \n\ + ldgp $29, 0($27) \n\ + subq $30, 16, $30 \n\ + stq $26, 0($30) \n\ + stq $29, 8($30) \n\ + .align 3 \n\ +/*@_fini_PROLOG_ENDS*/ \n\ + \n\ +/*@_fini_EPILOG_BEGINS*/ \n\ + .section .fini, \"ax\", @progbits \n\ + ldq $26, 0($30) \n\ + ldq $29, 8($30) \n\ + addq $30, 16, $30 \n\ + ret \n\ +/*@_fini_EPILOG_ENDS*/ \n\ + \n\ +/*@TRAILER_BEGINS*/ \n\ +"); diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/alpha/pspinlock.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/alpha/pspinlock.c new file mode 100644 index 00000000..d54a2a98 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/alpha/pspinlock.c @@ -0,0 +1,110 @@ +/* POSIX spinlock implementation. Alpha version. + Copyright (C) 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include "internals.h" + + +/* This implementation is similar to the one used in the Linux kernel. + But the kernel is byte instructions for the memory access. This is + faster but unusable here. The problem is that only 128 + threads/processes could use the spinlock at the same time. If (by + a design error in the program) a thread/process would hold the + spinlock for a time long enough to accumulate 128 waiting + processes, the next one will find a positive value in the spinlock + and assume it is unlocked. We cannot accept that. */ + +int +__pthread_spin_lock (pthread_spinlock_t *lock) +{ + unsigned int tmp; + __asm__ __volatile__ + ("1: ldl_l %0,%1\n" + " blbs %0,2f\n" + " or %0,1,%0\n" + " stl_c %0,%1\n" + " beq %0,2f\n" + " mb\n" + ".subsection 2\n" + "2: ldl %0,%1\n" + " blbs %0,2b\n" + " br 1b\n" + ".previous" + : "=r" (tmp), "=m" (lock) + : "m" (lock)); + return 0; +} +weak_alias (__pthread_spin_lock, pthread_spin_lock) + + +int +__pthread_spin_trylock (pthread_spinlock_t *lock) +{ + unsigned long int oldval; + unsigned long int temp; + + __asm__ __volatile__ + ("1: ldl_l %0,%1\n" + " and %0,%3,%2\n" + " bne %2,2f\n" + " xor %0,%3,%0\n" + " stl_c %0,%1\n" + " beq %0,3f\n" + " mb\n" + "2:\n" + ".subsection 2\n" + "3: br 1b\n" + ".previous" + : "=&r" (temp), "=m" (*lock), "=&r" (oldval) + : "Ir" (1UL), "m" (*lock)); + + return oldval == 0 ? 0 : EBUSY; +} +weak_alias (__pthread_spin_trylock, pthread_spin_trylock) + + +int +__pthread_spin_unlock (pthread_spinlock_t *lock) +{ + __asm__ __volatile__ ("mb"); + return *lock = 0; +} +weak_alias (__pthread_spin_unlock, pthread_spin_unlock) + + +int +__pthread_spin_init (pthread_spinlock_t *lock, int pshared) +{ + /* We can ignore the `pshared' parameter. Since we are busy-waiting + all processes which can access the memory location `lock' points + to can use the spinlock. */ + *lock = 0; + return 0; +} +weak_alias (__pthread_spin_init, pthread_spin_init) + + +int +__pthread_spin_destroy (pthread_spinlock_t *lock) +{ + /* Nothing to do. */ + return 0; +} +weak_alias (__pthread_spin_destroy, pthread_spin_destroy) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/alpha/pt-machine.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/alpha/pt-machine.h new file mode 100644 index 00000000..97c38394 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/alpha/pt-machine.h @@ -0,0 +1,127 @@ +/* Machine-dependent pthreads configuration and inline functions. + Alpha version. + Copyright (C) 1996, 1997, 1998, 2000, 2002, 2003 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _PT_MACHINE_H +#define _PT_MACHINE_H 1 + +#include + +#ifndef PT_EI +# define PT_EI __extern_always_inline +#endif + +#ifdef __linux__ +# include +#else +# include +#endif + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#define CURRENT_STACK_FRAME stack_pointer +register char *stack_pointer __asm__("$30"); + + +/* Memory barrier; default is to do nothing */ +#define MEMORY_BARRIER() __asm__ __volatile__("mb" : : : "memory") +/* Write barrier. */ +#define WRITE_MEMORY_BARRIER() __asm__ __volatile__("wmb" : : : "memory") + + +/* Spinlock implementation; required. */ +PT_EI long int +testandset (int *spinlock) +{ + long int ret, temp; + + __asm__ __volatile__( + "/* Inline spinlock test & set */\n" + "1:\t" + "ldl_l %0,%3\n\t" + "bne %0,2f\n\t" + "or $31,1,%1\n\t" + "stl_c %1,%2\n\t" + "beq %1,1b\n" + "2:\tmb\n" + "/* End spinlock test & set */" + : "=&r"(ret), "=&r"(temp), "=m"(*spinlock) + : "m"(*spinlock) + : "memory"); + + return ret; +} + + +/* Begin allocating thread stacks at this address. Default is to allocate + them just below the initial program stack. */ +#define THREAD_STACK_START_ADDRESS 0x40000000000 + + +/* Return the thread descriptor for the current thread. */ +#define THREAD_SELF \ +({ \ + register pthread_descr __self __asm__("$0"); \ + __asm__ ("call_pal %1" : "=r"(__self) : "i"(PAL_rduniq)); \ + __self; \ +}) + +/* Initialize the thread-unique value. */ +#define INIT_THREAD_SELF(descr, nr) \ +{ \ + register pthread_descr __self __asm__("$16") = (descr); \ + __asm__ __volatile__ ("call_pal %1" : : "r"(__self), "i"(PAL_wruniq)); \ +} + + +/* Compare-and-swap for semaphores. */ + +#define HAS_COMPARE_AND_SWAP +PT_EI int +__compare_and_swap (long int *p, long int oldval, long int newval) +{ + long int ret; + + __asm__ __volatile__ ( + "/* Inline compare & swap */\n" + "1:\t" + "ldq_l %0,%4\n\t" + "cmpeq %0,%2,%0\n\t" + "beq %0,2f\n\t" + "mov %3,%0\n\t" + "stq_c %0,%1\n\t" + "beq %0,1b\n\t" + "2:\tmb\n" + "/* End compare & swap */" + : "=&r"(ret), "=m"(*p) + : "r"(oldval), "r"(newval), "m"(*p) + : "memory"); + + return ret; +} + +/* We want the OS to assign stack addresses. */ +#define FLOATING_STACKS 1 + +/* Maximum size of the stack if the rlimit is unlimited. */ +#define ARCH_STACK_MAX_SIZE 32*1024*1024 + +#endif /* pt-machine.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/alpha/tls.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/alpha/tls.h new file mode 100644 index 00000000..3eb9438c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/alpha/tls.h @@ -0,0 +1,134 @@ +/* Definitions for thread-local data handling. linuxthreads/Alpha version. + Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _TLS_H +#define _TLS_H + +#ifndef __ASSEMBLER__ + +# include +# include +# include + +/* Type for the dtv. */ +typedef union dtv +{ + size_t counter; + struct + { + void *val; + bool is_static; + } pointer; +} dtv_t; + + +typedef struct +{ + dtv_t *dtv; + + /* Reserved for the thread implementation. Unused in LinuxThreads. */ + void *private; +} tcbhead_t; +#endif + + +#ifdef HAVE_TLS_SUPPORT + +/* Signal that TLS support is available. */ +# define USE_TLS 1 + +# ifndef __ASSEMBLER__ +/* Get system call information. */ +# include + +/* This is the size of the initial TCB. */ +# define TLS_INIT_TCB_SIZE sizeof (tcbhead_t) + +/* Alignment requirements for the initial TCB. */ +# define TLS_INIT_TCB_ALIGN __alignof__ (tcbhead_t) + +/* This is the size of the TCB. */ +# define TLS_TCB_SIZE sizeof (tcbhead_t) + +/* Alignment requirements for the TCB. */ +# define TLS_TCB_ALIGN __alignof__ (tcbhead_t) + +/* This is the size we need before TCB. */ +# define TLS_PRE_TCB_SIZE sizeof (struct _pthread_descr_struct) + +/* The DTV is allocated at the TP; the TCB is placed elsewhere. */ +# define TLS_DTV_AT_TP 1 + +/* Install the dtv pointer. The pointer passed is to the element with + index -1 which contain the length. */ +# define INSTALL_DTV(TCBP, DTVP) \ + (((tcbhead_t *) (TCBP))->dtv = (DTVP) + 1) + +/* Install new dtv for current thread. */ +# define INSTALL_NEW_DTV(DTV) \ + (((tcbhead_t *)__builtin_thread_pointer ())->dtv = (DTV)) + +/* Return dtv of given thread descriptor. */ +# define GET_DTV(TCBP) \ + (((tcbhead_t *) (TCBP))->dtv) + +/* Code to initially initialize the thread pointer. This might need + special attention since 'errno' is not yet available and if the + operation can cause a failure 'errno' must not be touched. */ +# define TLS_INIT_TP(TCBP, SECONDCALL) \ + (__builtin_set_thread_pointer (TCBP), 0) + +/* Return the address of the dtv for the current thread. */ +# define THREAD_DTV() \ + (((tcbhead_t *)__builtin_thread_pointer ())->dtv) + +/* Return the thread descriptor for the current thread. */ +# undef THREAD_SELF +# define THREAD_SELF \ + ((pthread_descr)__builtin_thread_pointer () - 1) + +# undef INIT_THREAD_SELF +# define INIT_THREAD_SELF(DESCR, NR) \ + __builtin_set_thread_pointer ((struct _pthread_descr_struct *)(DESCR) + 1) + +/* Get the thread descriptor definition. */ +# include + +/* ??? Generic bits of LinuxThreads may call these macros with + DESCR set to NULL. We are expected to be able to reference + the "current" value. + + In our case, we'd really prefer to use DESCR, since lots of + PAL_code calls would be expensive. We can only trust that + the compiler does its job and unifies the multiple + __builtin_thread_pointer instances. */ + +#define THREAD_GETMEM(descr, member) \ + ((void) sizeof (descr), THREAD_SELF->member) +#define THREAD_GETMEM_NC(descr, member) \ + ((void) sizeof (descr), THREAD_SELF->member) +#define THREAD_SETMEM(descr, member, value) \ + ((void) sizeof (descr), THREAD_SELF->member = (value)) +#define THREAD_SETMEM_NC(descr, member, value) \ + ((void) sizeof (descr), THREAD_SELF->member = (value)) + +# endif /* HAVE_TLS_SUPPORT */ +#endif /* __ASSEMBLER__ */ + +#endif /* tls.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/arm/pspinlock.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/arm/pspinlock.c new file mode 100644 index 00000000..9deb0b1b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/arm/pspinlock.c @@ -0,0 +1,82 @@ +/* POSIX spinlock implementation. Arm version. + Copyright (C) 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include "internals.h" + + +int +__pthread_spin_lock (pthread_spinlock_t *lock) +{ + unsigned int val; + + do + __asm__ __volatile__ ("swp %0, %1, [%2]" + : "=r" (val) + : "0" (1), "r" (lock) + : "memory"); + while (val != 0); + + return 0; +} +weak_alias (__pthread_spin_lock, pthread_spin_lock) + + +int +__pthread_spin_trylock (pthread_spinlock_t *lock) +{ + unsigned int val; + + __asm__ __volatile__ ("swp %0, %1, [%2]" + : "=r" (val) + : "0" (1), "r" (lock) + : "memory"); + + return val ? EBUSY : 0; +} +weak_alias (__pthread_spin_trylock, pthread_spin_trylock) + + +int +__pthread_spin_unlock (pthread_spinlock_t *lock) +{ + return *lock = 0; +} +weak_alias (__pthread_spin_unlock, pthread_spin_unlock) + + +int +__pthread_spin_init (pthread_spinlock_t *lock, int pshared) +{ + /* We can ignore the `pshared' parameter. Since we are busy-waiting + all processes which can access the memory location `lock' points + to can use the spinlock. */ + return *lock = 0; +} +weak_alias (__pthread_spin_init, pthread_spin_init) + + +int +__pthread_spin_destroy (pthread_spinlock_t *lock) +{ + /* Nothing to do. */ + return 0; +} +weak_alias (__pthread_spin_destroy, pthread_spin_destroy) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/arm/pt-machine.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/arm/pt-machine.h new file mode 100644 index 00000000..9ffc8bdc --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/arm/pt-machine.h @@ -0,0 +1,54 @@ +/* Machine-dependent pthreads configuration and inline functions. + ARM version. + Copyright (C) 1997, 1998, 2000, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Philip Blundell . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _PT_MACHINE_H +#define _PT_MACHINE_H 1 + +#include + +#ifndef PT_EI +# define PT_EI __extern_always_inline +#endif + +/* This will not work on ARM1 or ARM2 because SWP is lacking on those + machines. Unfortunately we have no way to detect this at compile + time; let's hope nobody tries to use one. */ + +/* Spinlock implementation; required. */ +PT_EI long int +testandset (int *spinlock) +{ + register unsigned int ret; + + __asm__ __volatile__("swp %0, %1, [%2]" + : "=r"(ret) + : "0"(1), "r"(spinlock)); + + return ret; +} + + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#define CURRENT_STACK_FRAME stack_pointer +register char * stack_pointer __asm__ ("sp"); + +#endif /* pt-machine.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/arm/sysdep-cancel.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/arm/sysdep-cancel.h new file mode 100644 index 00000000..ba6a1e04 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/arm/sysdep-cancel.h @@ -0,0 +1,8 @@ +#include + +/* No multi-thread handling enabled. */ +#define SINGLE_THREAD_P (1) +#define RTLD_SINGLE_THREAD_P (1) +#define LIBC_CANCEL_ASYNC() 0 /* Just a dummy value. */ +#define LIBC_CANCEL_RESET(val) ((void)(val)) /* Nothing, but evaluate it. */ +#define LIBC_CANCEL_HANDLED() /* Nothing. */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/arm/sysdep.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/arm/sysdep.h new file mode 100644 index 00000000..15d951c7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/arm/sysdep.h @@ -0,0 +1,137 @@ +/* Generic asm macros used on many machines. + Copyright (C) 1991,92,93,96,98,2002,2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef C_LABEL + +/* Define a macro we can use to construct the asm name for a C symbol. */ +#ifdef NO_UNDERSCORES +#ifdef __STDC__ +#define C_LABEL(name) name##: +#else +#define C_LABEL(name) name/**/: +#endif +#else +#ifdef __STDC__ +#define C_LABEL(name) _##name##: +#else +#define C_LABEL(name) _/**/name/**/: +#endif +#endif + +#endif + +#ifdef __ASSEMBLER__ +/* Mark the end of function named SYM. This is used on some platforms + to generate correct debugging information. */ +#ifndef END +#define END(sym) +#endif + +#ifndef JUMPTARGET +#define JUMPTARGET(sym) sym +#endif + +/* Makros to generate eh_frame unwind information. */ +# ifdef HAVE_ASM_CFI_DIRECTIVES +# define cfi_startproc .cfi_startproc +# define cfi_endproc .cfi_endproc +# define cfi_def_cfa(reg, off) .cfi_def_cfa reg, off +# define cfi_def_cfa_register(reg) .cfi_def_cfa_register reg +# define cfi_def_cfa_offset(off) .cfi_def_cfa_offset off +# define cfi_adjust_cfa_offset(off) .cfi_adjust_cfa_offset off +# define cfi_offset(reg, off) .cfi_offset reg, off +# define cfi_rel_offset(reg, off) .cfi_rel_offset reg, off +# define cfi_register(r1, r2) .cfi_register r1, r2 +# define cfi_return_column(reg) .cfi_return_column reg +# define cfi_restore(reg) .cfi_restore reg +# define cfi_same_value(reg) .cfi_same_value reg +# define cfi_undefined(reg) .cfi_undefined reg +# define cfi_remember_state .cfi_remember_state +# define cfi_restore_state .cfi_restore_state +# define cfi_window_save .cfi_window_save +# else +# define cfi_startproc +# define cfi_endproc +# define cfi_def_cfa(reg, off) +# define cfi_def_cfa_register(reg) +# define cfi_def_cfa_offset(off) +# define cfi_adjust_cfa_offset(off) +# define cfi_offset(reg, off) +# define cfi_rel_offset(reg, off) +# define cfi_register(r1, r2) +# define cfi_return_column(reg) +# define cfi_restore(reg) +# define cfi_same_value(reg) +# define cfi_undefined(reg) +# define cfi_remember_state +# define cfi_restore_state +# define cfi_window_save +# endif + +#else /* ! ASSEMBLER */ +# ifdef HAVE_ASM_CFI_DIRECTIVES +# define CFI_STRINGIFY(Name) CFI_STRINGIFY2 (Name) +# define CFI_STRINGIFY2(Name) #Name +# define CFI_STARTPROC ".cfi_startproc" +# define CFI_ENDPROC ".cfi_endproc" +# define CFI_DEF_CFA(reg, off) \ + ".cfi_def_cfa " CFI_STRINGIFY(reg) "," CFI_STRINGIFY(off) +# define CFI_DEF_CFA_REGISTER(reg) \ + ".cfi_def_cfa_register " CFI_STRINGIFY(reg) +# define CFI_DEF_CFA_OFFSET(off) \ + ".cfi_def_cfa_offset " CFI_STRINGIFY(off) +# define CFI_ADJUST_CFA_OFFSET(off) \ + ".cfi_adjust_cfa_offset " CFI_STRINGIFY(off) +# define CFI_OFFSET(reg, off) \ + ".cfi_offset " CFI_STRINGIFY(reg) "," CFI_STRINGIFY(off) +# define CFI_REL_OFFSET(reg, off) \ + ".cfi_rel_offset " CFI_STRINGIFY(reg) "," CFI_STRINGIFY(off) +# define CFI_REGISTER(r1, r2) \ + ".cfi_register " CFI_STRINGIFY(r1) "," CFI_STRINGIFY(r2) +# define CFI_RETURN_COLUMN(reg) \ + ".cfi_return_column " CFI_STRINGIFY(reg) +# define CFI_RESTORE(reg) \ + ".cfi_restore " CFI_STRINGIFY(reg) +# define CFI_UNDEFINED(reg) \ + ".cfi_undefined " CFI_STRINGIFY(reg) +# define CFI_REMEMBER_STATE \ + ".cfi_remember_state" +# define CFI_RESTORE_STATE \ + ".cfi_restore_state" +# define CFI_WINDOW_SAVE \ + ".cfi_window_save" +# else +# define CFI_STARTPROC +# define CFI_ENDPROC +# define CFI_DEF_CFA(reg, off) +# define CFI_DEF_CFA_REGISTER(reg) +# define CFI_DEF_CFA_OFFSET(off) +# define CFI_ADJUST_CFA_OFFSET(off) +# define CFI_OFFSET(reg, off) +# define CFI_REL_OFFSET(reg, off) +# define CFI_REGISTER(r1, r2) +# define CFI_RETURN_COLUMN(reg) +# define CFI_RESTORE(reg) +# define CFI_UNDEFINED(reg) +# define CFI_REMEMBER_STATE +# define CFI_RESTORE_STATE +# define CFI_WINDOW_SAVE +# endif + +#endif /* __ASSEMBLER__ */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/arm/tls.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/arm/tls.h new file mode 100644 index 00000000..8057a541 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/arm/tls.h @@ -0,0 +1,172 @@ +/* Definitions for thread-local data handling. linuxthreads/ARM version. + Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _TLS_H +#define _TLS_H + +#ifndef __ASSEMBLER__ + +# include +# include +# include + +/* Type for the dtv. */ +typedef union dtv +{ + size_t counter; + struct + { + void *val; + bool is_static; + } pointer; +} dtv_t; + +typedef struct +{ + dtv_t *dtv; + + /* Reserved for the thread implementation. Unused in LinuxThreads. */ + void *private; +} tcbhead_t; +#endif + + +/* We can support TLS only if the floating-stack support is available. + However, we want to compile in the support and test at runtime whether + the running kernel can support it or not. To avoid bothering with the + TLS support code at all, use configure --without-tls. + + We need USE_TLS to be consistently defined, for ldsodefs.h conditionals. + But some of the code below can cause problems in building libpthread + (e.g. useldt.h will defined FLOATING_STACKS when it shouldn't). */ + +/* LinuxThreads can only support TLS if both floating stacks and support + from the tools are available. + + We have to define USE_TLS consistently, or ldsodefs.h will lay out types + differently between an NPTL build and a LinuxThreads build. It can be set + for libc.so and not libpthread.so, but only if we provide appropriate padding + in the _pthread_descr_struct. + + Currently nothing defines FLOATING_STACKS. We could assume this based on + kernel version once the TLS patches are available in kernel.org. + + To avoid bothering with the TLS support code at all, use configure + --without-tls. */ + +#if defined HAVE_TLS_SUPPORT \ + && (defined FLOATING_STACKS || !defined IS_IN_libpthread) + +/* Signal that TLS support is available. */ +# define USE_TLS 1 + +/* Include padding in _pthread_descr_struct so that libc can find p_errno, + if libpthread will only include the padding because of the !IS_IN_libpthread + check. */ +#ifndef FLOATING_STACKS +# define INCLUDE_TLS_PADDING 1 +#endif + +# ifndef __ASSEMBLER__ +/* Get system call information. */ +# include + +/* This is the size of the initial TCB. */ +# define TLS_INIT_TCB_SIZE sizeof (tcbhead_t) + +/* Alignment requirements for the initial TCB. */ +# define TLS_INIT_TCB_ALIGN __alignof__ (tcbhead_t) + +/* This is the size of the TCB. */ +# define TLS_TCB_SIZE sizeof (tcbhead_t) + +/* Alignment requirements for the TCB. */ +# define TLS_TCB_ALIGN __alignof__ (tcbhead_t) + +/* This is the size we need before TCB. */ +# define TLS_PRE_TCB_SIZE sizeof (struct _pthread_descr_struct) + +/* The DTV is allocated at the TP; the TCB is placed elsewhere. */ +# define TLS_DTV_AT_TP 1 + +/* Install the dtv pointer. The pointer passed is to the element with + index -1 which contain the length. */ +# define INSTALL_DTV(TCBP, DTVP) \ + (((tcbhead_t *) (TCBP))->dtv = (DTVP) + 1) + +/* Install new dtv for current thread. */ +# define INSTALL_NEW_DTV(DTV) \ + (((tcbhead_t *)__builtin_thread_pointer ())->dtv = (DTV)) + +/* Return dtv of given thread descriptor. */ +# define GET_DTV(TCBP) \ + (((tcbhead_t *) (TCBP))->dtv) + +/* Code to initially initialize the thread pointer. This might need + special attention since 'errno' is not yet available and if the + operation can cause a failure 'errno' must not be touched. */ +# define TLS_INIT_TP(TCBP, SECONDCALL) \ + ({ INTERNAL_SYSCALL_DECL (err); \ + long result_var; \ + result_var = INTERNAL_SYSCALL_ARM (set_tls, err, 1, (TCBP)); \ + INTERNAL_SYSCALL_ERROR_P (result_var, err) \ + ? "unknown error" : NULL; }) + +/* Return the address of the dtv for the current thread. */ +# define THREAD_DTV() \ + (((tcbhead_t *)__builtin_thread_pointer ())->dtv) + +/* Return the thread descriptor for the current thread. */ +# undef THREAD_SELF +# define THREAD_SELF \ + ((pthread_descr)__builtin_thread_pointer () - 1) + +# undef INIT_THREAD_SELF +# define INIT_THREAD_SELF(DESCR, NR) \ + TLS_INIT_TP ((struct _pthread_descr_struct *)(DESCR) + 1, 0) + +/* Get the thread descriptor definition. */ +# include + +/* ??? Generic bits of LinuxThreads may call these macros with + DESCR set to NULL. We are expected to be able to reference + the "current" value. + + In our case, we'd really prefer to use DESCR, since lots of + PAL_code calls would be expensive. We can only trust that + the compiler does its job and unifies the multiple + __builtin_thread_pointer instances. */ + +#define THREAD_GETMEM(descr, member) \ + ((void) sizeof (descr), THREAD_SELF->member) +#define THREAD_GETMEM_NC(descr, member) \ + ((void) sizeof (descr), THREAD_SELF->member) +#define THREAD_SETMEM(descr, member, value) \ + ((void) sizeof (descr), THREAD_SELF->member = (value)) +#define THREAD_SETMEM_NC(descr, member, value) \ + ((void) sizeof (descr), THREAD_SELF->member = (value)) + +/* Initializing the thread pointer will generate a SIGILL if the syscall + is not available. */ +#define TLS_INIT_TP_EXPENSIVE 1 + +# endif /* HAVE_TLS_SUPPORT */ +#endif /* __ASSEMBLER__ */ + +#endif /* tls.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/avr32/pt-machine.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/avr32/pt-machine.h new file mode 100644 index 00000000..5735d0ea --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/avr32/pt-machine.h @@ -0,0 +1,73 @@ +/* Machine-dependent pthreads configuration and inline functions. + * + * Copyright (C) 2005-2007 Atmel Corporation + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License. See the file "COPYING.LIB" in the main directory of this + * archive for more details. + */ +#ifndef _PT_MACHINE_H +#define _PT_MACHINE_H 1 + +#include + +#ifndef PT_EI +# define PT_EI __extern_always_inline +#endif + +static __inline__ int +_test_and_set (int *p, int v) +{ + int result; + + __asm__ __volatile__( + "/* Inline test and set */\n" + " xchg %[old], %[mem], %[new]" + : [old] "=&r"(result) + : [mem] "r"(p), [new] "r"(v) + : "memory"); + + return result; +} + +extern long int testandset (int *spinlock); +extern int __compare_and_swap (long int *p, long int oldval, long int newval); + +/* Spinlock implementation; required. */ +PT_EI long int +testandset (int *spinlock) +{ + return _test_and_set(spinlock, 1); +} + + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#define CURRENT_STACK_FRAME stack_pointer +register char * stack_pointer __asm__ ("sp"); + +/* Compare-and-swap for semaphores. */ + +#define HAS_COMPARE_AND_SWAP +PT_EI int +__compare_and_swap(long int *p, long int oldval, long int newval) +{ + long int result; + + __asm__ __volatile__( + "/* Inline compare and swap */\n" + "1: ssrf 5\n" + " ld.w %[result], %[mem]\n" + " eor %[result], %[old]\n" + " brne 2f\n" + " stcond %[mem], %[new]\n" + " brne 1b\n" + "2:" + : [result] "=&r"(result), [mem] "=m"(*p) + : "m"(*p), [new] "r"(newval), [old] "r"(oldval) + : "cc", "memory"); + + return result == 0; +} + +#endif /* pt-machine.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/cris/pspinlock.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/cris/pspinlock.c new file mode 100644 index 00000000..402e838c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/cris/pspinlock.c @@ -0,0 +1,72 @@ +/* POSIX spinlock implementation. CRIS version. + Copyright (C) 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include "internals.h" + +/* FIXME: These are just dummies. I don't know why or if they're needed; + configury should default to these definitions. We just follow the + crowd here. */ + +int +__pthread_spin_lock (pthread_spinlock_t *lock) +{ + while (testandset (lock) != 0) + ; + + return 0; +} +weak_alias (__pthread_spin_lock, pthread_spin_lock) + + +int +__pthread_spin_trylock (pthread_spinlock_t *lock) +{ + return testandset (lock) != 0 ? EBUSY : 0; +} +weak_alias (__pthread_spin_trylock, pthread_spin_trylock) + + +int +__pthread_spin_unlock (pthread_spinlock_t *lock) +{ + return *lock = 0; +} +weak_alias (__pthread_spin_unlock, pthread_spin_unlock) + + +int +__pthread_spin_init (pthread_spinlock_t *lock, int pshared) +{ + /* We can ignore the `pshared' parameter. Since we are busy-waiting + all processes which can access the memory location `lock' points + to can use the spinlock. */ + return *lock = 0; +} +weak_alias (__pthread_spin_init, pthread_spin_init) + + +int +__pthread_spin_destroy (pthread_spinlock_t *lock) +{ + /* Nothing to do. */ + return 0; +} +weak_alias (__pthread_spin_destroy, pthread_spin_destroy) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/cris/pt-machine.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/cris/pt-machine.h new file mode 100644 index 00000000..33cf5790 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/cris/pt-machine.h @@ -0,0 +1,57 @@ +/* Machine-dependent pthreads configuration and inline functions. + CRIS version. + Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _PT_MACHINE_H +#define _PT_MACHINE_H 1 + +#include + +#ifndef PT_EI +# define PT_EI __extern_always_inline +#endif + +PT_EI long int +testandset (int *spinlock) +{ + register unsigned long int ret; + + /* Note the use of a dummy output of *spinlock to expose the write. The + memory barrier is to stop *other* writes being moved past this code. */ + __asm__ __volatile__("clearf\n" + "0:\n\t" + "movu.b [%2],%0\n\t" + "ax\n\t" + "move.b %3,[%2]\n\t" + "bwf 0b\n\t" + "clearf" + : "=&r" (ret), "=m" (*spinlock) + : "r" (spinlock), "r" ((int) 1) + : "memory"); + return ret; +} + + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. + I don't trust register variables, so let's do this the safe way. */ +#define CURRENT_STACK_FRAME \ + ({ char *sp; __asm__ ("move.d $sp,%0" : "=rm" (sp)); sp; }) + +#endif /* pt-machine.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/hppa/pspinlock.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/hppa/pspinlock.c new file mode 100644 index 00000000..71a537fd --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/hppa/pspinlock.c @@ -0,0 +1,81 @@ +/* POSIX spinlock implementation. hppa version. + Copyright (C) 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include "internals.h" + +int +__pthread_spin_lock (pthread_spinlock_t *lock) +{ + unsigned int val; + + do + __asm__ __volatile__ ("ldcw %1,%0" + : "=r" (val), "=m" (*lock) + : "m" (*lock)); + while (!val); + + return 0; +} +weak_alias (__pthread_spin_lock, pthread_spin_lock) + + +int +__pthread_spin_trylock (pthread_spinlock_t *lock) +{ + unsigned int val; + + __asm__ __volatile__ ("ldcw %1,%0" + : "=r" (val), "=m" (*lock) + : "m" (*lock)); + + return val ? 0 : EBUSY; +} +weak_alias (__pthread_spin_trylock, pthread_spin_trylock) + + +int +__pthread_spin_unlock (pthread_spinlock_t *lock) +{ + *lock = 1; + return 0; +} +weak_alias (__pthread_spin_unlock, pthread_spin_unlock) + + +int +__pthread_spin_init (pthread_spinlock_t *lock, int pshared) +{ + /* We can ignore the `pshared' parameter. Since we are busy-waiting + all processes which can access the memory location `lock' points + to can use the spinlock. */ + *lock = 1; + return 0; +} +weak_alias (__pthread_spin_init, pthread_spin_init) + + +int +__pthread_spin_destroy (pthread_spinlock_t *lock) +{ + /* Nothing to do. */ + return 0; +} +weak_alias (__pthread_spin_destroy, pthread_spin_destroy) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/hppa/pt-machine.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/hppa/pt-machine.h new file mode 100644 index 00000000..780af7b9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/hppa/pt-machine.h @@ -0,0 +1,60 @@ +/* Machine-dependent pthreads configuration and inline functions. + hppa version. + Copyright (C) 2000, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _PT_MACHINE_H +#define _PT_MACHINE_H 1 + +#include +#include + +#ifndef PT_EI +# define PT_EI __extern_always_inline +#endif + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#define CURRENT_STACK_FRAME stack_pointer +register char * stack_pointer __asm__ ("%r30"); + + +/* The hppa only has one atomic read and modify memory operation, + load and clear, so hppa spinlocks must use zero to signify that + someone is holding the lock. */ + +#define xstr(s) str(s) +#define str(s) #s +/* Spinlock implementation; required. */ +PT_EI long int +testandset (int *spinlock) +{ + int ret; + + __asm__ __volatile__( + "ldcw 0(%2),%0" + : "=r"(ret), "=m"(*spinlock) + : "r"(spinlock)); + + return ret == 0; +} +#undef str +#undef xstr + +#endif /* pt-machine.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/i386/i686/pt-machine.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/i386/i686/pt-machine.h new file mode 100644 index 00000000..2958c76f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/i386/i686/pt-machine.h @@ -0,0 +1,79 @@ +/* Machine-dependent pthreads configuration and inline functions. + i686 version. + Copyright (C) 1996-2001, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _PT_MACHINE_H +#define _PT_MACHINE_H 1 + +#ifndef PT_EI +# define PT_EI __extern_always_inline +#endif +#include + +#ifndef __ASSEMBLER__ +extern long int testandset (int *spinlock); +extern int __compare_and_swap (long int *p, long int oldval, long int newval); + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#define CURRENT_STACK_FRAME __builtin_frame_address (0) + + +/* Spinlock implementation; required. */ +PT_EI long int +testandset (int *spinlock) +{ + long int ret; + + __asm__ __volatile__ ( + "xchgl %0, %1" + : "=r" (ret), "=m" (*spinlock) + : "0" (1), "m" (*spinlock) + : "memory"); + + return ret; +} + + +/* Compare-and-swap for semaphores. It's always available on i686. */ +#define HAS_COMPARE_AND_SWAP + +PT_EI int +__compare_and_swap (long int *p, long int oldval, long int newval) +{ + char ret; + long int readval; + + __asm__ __volatile__ ("lock; cmpxchgl %3, %1; sete %0" + : "=q" (ret), "=m" (*p), "=a" (readval) + : "r" (newval), "m" (*p), "a" (oldval) + : "memory"); + return ret; +} +#endif + +#if __ASSUME_LDT_WORKS > 0 +#include "../useldt.h" +#endif + +/* The P4 and above really want some help to prevent overheating. */ +#define BUSY_WAIT_NOP __asm__ ("rep; nop") + +#endif /* pt-machine.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/i386/pspinlock.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/i386/pspinlock.c new file mode 100644 index 00000000..64b59252 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/i386/pspinlock.c @@ -0,0 +1,103 @@ +/* POSIX spinlock implementation. x86 version. + Copyright (C) 2000, 2002, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include "internals.h" +#include + + +/* This implementation is similar to the one used in the Linux kernel. + But the kernel is byte instructions for the memory access. This is + faster but unusable here. The problem is that only 128 + threads/processes could use the spinlock at the same time. If (by + a design error in the program) a thread/process would hold the + spinlock for a time long enough to accumulate 128 waiting + processes, the next one will find a positive value in the spinlock + and assume it is unlocked. We cannot accept that. */ + +int +__pthread_spin_lock (pthread_spinlock_t *lock) +{ + __asm__ __volatile__ + ("\n" + "1:\n\t" + "lock; decl %0\n\t" + "js 2f\n\t" + ".section .text.spinlock,\"ax\"\n" + "2:\n\t" + "cmpl $0,%0\n\t" + "rep; nop\n\t" + "jle 2b\n\t" + "jmp 1b\n\t" + ".previous" + : "=m" (*lock)); + return 0; +} +weak_alias (__pthread_spin_lock, pthread_spin_lock) + + +int +__pthread_spin_trylock (pthread_spinlock_t *lock) +{ + int oldval; + + __asm__ __volatile__ + ("xchgl %0,%1" + : "=r" (oldval), "=m" (*lock) + : "0" (0)); + return oldval > 0 ? 0 : EBUSY; +} +weak_alias (__pthread_spin_trylock, pthread_spin_trylock) + + +int +__pthread_spin_unlock (pthread_spinlock_t *lock) +{ + __asm__ __volatile__ + ("movl $1,%0" + : "=m" (*lock)); + return 0; +} +weak_alias (__pthread_spin_unlock, pthread_spin_unlock) + + +int +__pthread_spin_init (pthread_spinlock_t *lock, int pshared) +{ + /* We can ignore the `pshared' parameter. Since we are busy-waiting + all processes which can access the memory location `lock' points + to can use the spinlock. */ + *lock = 1; + return 0; +} +weak_alias (__pthread_spin_init, pthread_spin_init) + + +int +__pthread_spin_destroy (pthread_spinlock_t *lock) +{ + /* Nothing to do. */ + return 0; +} +weak_alias (__pthread_spin_destroy, pthread_spin_destroy) + +#ifndef __ASSUME_SET_THREAD_AREA_SYSCALL +int __have_no_set_thread_area; +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/i386/pt-machine.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/i386/pt-machine.h new file mode 100644 index 00000000..a4557891 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/i386/pt-machine.h @@ -0,0 +1,118 @@ +/* Machine-dependent pthreads configuration and inline functions. + i386 version. + Copyright (C) 1996-2001, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#if defined __pentiumpro__ || defined __pentium4__ || defined __athlon__ || \ + defined __k8__ +# include "i686/pt-machine.h" +#else + +#ifndef _PT_MACHINE_H +#define _PT_MACHINE_H 1 + +#ifndef __ASSEMBLER__ +#ifndef PT_EI +# define PT_EI __extern_always_inline +#endif + +extern long int testandset (int *spinlock); +extern int __compare_and_swap (long int *p, long int oldval, long int newval); + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#define CURRENT_STACK_FRAME __builtin_frame_address (0) + + +/* Spinlock implementation; required. */ +PT_EI long int +testandset (int *spinlock) +{ + long int ret; + + __asm__ __volatile__( + "xchgl %0, %1" + : "=r"(ret), "=m"(*spinlock) + : "0"(1), "m"(*spinlock) + : "memory"); + + return ret; +} + + +/* Compare-and-swap for semaphores. + Available on the 486 and above, but not on the 386. + We test dynamically whether it's available or not. */ + +#define HAS_COMPARE_AND_SWAP +#define TEST_FOR_COMPARE_AND_SWAP + +PT_EI int +__compare_and_swap (long int *p, long int oldval, long int newval) +{ + char ret; + long int readval; + + __asm__ __volatile__ ("lock; cmpxchgl %3, %1; sete %0" + : "=q" (ret), "=m" (*p), "=a" (readval) + : "r" (newval), "m" (*p), "a" (oldval) + : "memory"); + return ret; +} + + +PT_EI int get_eflags (void); +PT_EI int +get_eflags (void) +{ + int res; + __asm__ __volatile__ ("pushfl; popl %0" : "=r" (res) : ); + return res; +} + + +PT_EI void set_eflags (int newflags); +PT_EI void +set_eflags (int newflags) +{ + __asm__ __volatile__ ("pushl %0; popfl" : : "r" (newflags) : "cc"); +} + + +PT_EI int compare_and_swap_is_available (void); +PT_EI int +compare_and_swap_is_available (void) +{ + int oldflags = get_eflags (); + int changed; + /* Flip AC bit in EFLAGS. */ + set_eflags (oldflags ^ 0x40000); + /* See if bit changed. */ + changed = (get_eflags () ^ oldflags) & 0x40000; + /* Restore EFLAGS. */ + set_eflags (oldflags); + /* If the AC flag did not change, it's a 386 and it lacks cmpxchg. + Otherwise, it's a 486 or above and it has cmpxchg. */ + return changed != 0; +} +#endif /* __ASSEMBLER__ */ + +#endif /* pt-machine.h */ + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/i386/tcb-offsets.sym b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/i386/tcb-offsets.sym new file mode 100644 index 00000000..69a5018d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/i386/tcb-offsets.sym @@ -0,0 +1,7 @@ +#include +#include + +MULTIPLE_THREADS_OFFSET offsetof (tcbhead_t, multiple_threads) +#ifdef NEED_DL_SYSINFO +SYSINFO_OFFSET offsetof (tcbhead_t, sysinfo) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/i386/tls.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/i386/tls.h new file mode 100644 index 00000000..4c9b6809 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/i386/tls.h @@ -0,0 +1,227 @@ +/* Definition for thread-local data handling. linuxthreads/i386 version. + Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _TLS_H +#define _TLS_H + +# include + +#ifndef __ASSEMBLER__ +# include +# include +# include + +/* Type for the dtv. */ +typedef union dtv +{ + size_t counter; + struct + { + void *val; + bool is_static; + } pointer; +} dtv_t; + + +typedef struct +{ + void *tcb; /* Pointer to the TCB. Not necessary the + thread descriptor used by libpthread. */ + dtv_t *dtv; + void *self; /* Pointer to the thread descriptor. */ + int multiple_threads; + uintptr_t sysinfo; +} tcbhead_t; + +#else /* __ASSEMBLER__ */ +# include +#endif + +/* We can support TLS only if the floating-stack support is available. + However, we want to compile in the support and test at runtime whether + the running kernel can support it or not. To avoid bothering with the + TLS support code at all, use configure --without-tls. + + We need USE_TLS to be consistently defined, for ldsodefs.h conditionals. + But some of the code below can cause problems in building libpthread + (e.g. useldt.h will defined FLOATING_STACKS when it shouldn't). */ + +#if defined HAVE_TLS_SUPPORT \ + && (defined FLOATING_STACKS || !defined IS_IN_libpthread) + +/* Signal that TLS support is available. */ +# define USE_TLS 1 + +# ifndef __ASSEMBLER__ +/* Get system call information. */ +# include + + +/* Get the thread descriptor definition. */ +# include + +/* This is the size of the initial TCB. */ +# define TLS_INIT_TCB_SIZE sizeof (tcbhead_t) + +/* Alignment requirements for the initial TCB. */ +# define TLS_INIT_TCB_ALIGN __alignof__ (tcbhead_t) + +/* This is the size of the TCB. */ +# define TLS_TCB_SIZE sizeof (struct _pthread_descr_struct) + +/* Alignment requirements for the TCB. */ +# define TLS_TCB_ALIGN __alignof__ (struct _pthread_descr_struct) + +/* The TCB can have any size and the memory following the address the + thread pointer points to is unspecified. Allocate the TCB there. */ +# define TLS_TCB_AT_TP 1 + + +/* Install the dtv pointer. The pointer passed is to the element with + index -1 which contain the length. */ +# define INSTALL_DTV(descr, dtvp) \ + ((tcbhead_t *) (descr))->dtv = (dtvp) + 1 + +/* Install new dtv for current thread. */ +# define INSTALL_NEW_DTV(dtv) \ + ({ struct _pthread_descr_struct *__descr; \ + THREAD_SETMEM (__descr, p_header.data.dtvp, (dtv)); }) + +/* Return dtv of given thread descriptor. */ +# define GET_DTV(descr) \ + (((tcbhead_t *) (descr))->dtv) + +# ifdef __PIC__ +# define TLS_EBX_ARG "r" +# define TLS_LOAD_EBX "xchgl %3, %%ebx\n\t" +# else +# define TLS_EBX_ARG "b" +# define TLS_LOAD_EBX +# endif + +# if !defined IS_IN_libpthread && !defined DO_MODIFY_LDT +# include "useldt.h" /* For the structure. */ +# endif +# if __ASSUME_LDT_WORKS > 0 +# define TLS_DO_MODIFY_LDT_KERNEL_CHECK(doit) (doit) /* Nothing to check. */ +# else +# define TLS_DO_MODIFY_LDT_KERNEL_CHECK(doit) \ + (__builtin_expect (GLRO(dl_osversion) < 131939, 0) \ + ? "kernel too old for thread-local storage support\n" \ + : (doit)) +# endif + +# define TLS_DO_MODIFY_LDT(descr, nr) \ +TLS_DO_MODIFY_LDT_KERNEL_CHECK( \ +({ \ + struct modify_ldt_ldt_s ldt_entry = \ + { nr, (unsigned long int) (descr), 0xfffff /* 4GB in pages */, \ + 1, 0, 0, 1, 0, 1, 0 }; \ + int result; \ + __asm__ __volatile__ (TLS_LOAD_EBX \ + "int $0x80\n\t" \ + TLS_LOAD_EBX \ + : "=a" (result) \ + : "0" (__NR_modify_ldt), \ + /* The extra argument with the "m" constraint is necessary \ + to let the compiler know that we are accessing LDT_ENTRY \ + here. */ \ + "m" (ldt_entry), TLS_EBX_ARG (1), "c" (&ldt_entry), \ + "d" (sizeof (ldt_entry))); \ + __builtin_expect (result, 0) == 0 \ + ? ({ __asm__ ("movw %w0, %%gs" : : "q" ((nr) * 8 + 7)); NULL; }) \ + : "cannot set up LDT for thread-local storage\n"; \ +})) + +# define TLS_DO_SET_THREAD_AREA(descr, secondcall) \ +({ \ + struct modify_ldt_ldt_s ldt_entry = \ + { -1, (unsigned long int) (descr), 0xfffff /* 4GB in pages */, \ + 1, 0, 0, 1, 0, 1, 0 }; \ + int result; \ + if (secondcall) \ + ldt_entry.entry_number = ({ int _gs; \ + __asm__ ("movw %%gs, %w0" : "=q" (_gs)); \ + (_gs & 0xffff) >> 3; }); \ + __asm__ __volatile__ (TLS_LOAD_EBX \ + "int $0x80\n\t" \ + TLS_LOAD_EBX \ + : "=a" (result), "=m" (ldt_entry.entry_number) \ + : "0" (__NR_set_thread_area), \ + /* The extra argument with the "m" constraint is necessary \ + to let the compiler know that we are accessing LDT_ENTRY \ + here. */ \ + TLS_EBX_ARG (&ldt_entry), "m" (ldt_entry)); \ + if (__builtin_expect (result, 0) == 0) \ + __asm__ ("movw %w0, %%gs" : : "q" (ldt_entry.entry_number * 8 + 3)); \ + result; \ +}) + +# ifdef __ASSUME_SET_THREAD_AREA_SYSCALL +# define TLS_SETUP_GS_SEGMENT(descr, secondcall) \ + (TLS_DO_SET_THREAD_AREA (descr, secondcall) \ + ? "set_thread_area failed when setting up thread-local storage\n" : NULL) +# elif defined __NR_set_thread_area +# define TLS_SETUP_GS_SEGMENT(descr, secondcall) \ + (TLS_DO_SET_THREAD_AREA (descr, secondcall) \ + ? TLS_DO_MODIFY_LDT (descr, 0) : NULL) +# else +# define TLS_SETUP_GS_SEGMENT(descr, secondcall) \ + TLS_DO_MODIFY_LDT ((descr), 0) +# endif + +#if defined NEED_DL_SYSINFO +# define INIT_SYSINFO \ + head->sysinfo = GLRO(dl_sysinfo) +#else +# define INIT_SYSINFO +#endif + +/* Code to initially initialize the thread pointer. This might need + special attention since 'errno' is not yet available and if the + operation can cause a failure 'errno' must not be touched. + + The value of this macro is null if successful, or an error string. */ +# define TLS_INIT_TP(descr, secondcall) \ + ({ \ + void *_descr = (descr); \ + tcbhead_t *head = _descr; \ + \ + head->tcb = _descr; \ + /* For now the thread descriptor is at the same address. */ \ + head->self = _descr; \ + \ + INIT_SYSINFO; \ + TLS_SETUP_GS_SEGMENT (_descr, secondcall); \ + }) + +/* Indicate that dynamic linker shouldn't try to initialize TLS even + when no PT_TLS segments are found in the program and libraries + it is linked against. */ +# define TLS_INIT_TP_EXPENSIVE 1 + +/* Return the address of the dtv for the current thread. */ +# define THREAD_DTV() \ + ({ struct _pthread_descr_struct *__descr; \ + THREAD_GETMEM (__descr, p_header.data.dtvp); }) + +# endif /* HAVE_TLS_SUPPORT && (FLOATING_STACKS || !IS_IN_libpthread) */ +#endif /* __ASSEMBLER__ */ + +#endif /* tls.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/i386/useldt.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/i386/useldt.h new file mode 100644 index 00000000..fa9a2a52 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/i386/useldt.h @@ -0,0 +1,314 @@ +/* Special definitions for ix86 machine using segment register based + thread descriptor. + Copyright (C) 1998, 2000, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef __ASSEMBLER__ +#include /* For offsetof. */ +#include /* For abort(). */ +#include + + +/* We don't want to include the kernel header. So duplicate the + information. */ + +/* Structure passed on `modify_ldt' call. */ +struct modify_ldt_ldt_s +{ + unsigned int entry_number; + unsigned long int base_addr; + unsigned int limit; + unsigned int seg_32bit:1; + unsigned int contents:2; + unsigned int read_exec_only:1; + unsigned int limit_in_pages:1; + unsigned int seg_not_present:1; + unsigned int useable:1; + unsigned int empty:25; +}; + +/* System call to set LDT entry. */ +extern int __modify_ldt (int, struct modify_ldt_ldt_s *, size_t); + + +/* Return the thread descriptor for the current thread. + + The contained asm must *not* be marked volatile since otherwise + assignments like + pthread_descr self = thread_self(); + do not get optimized away. */ +#define THREAD_SELF \ +({ \ + register pthread_descr __self; \ + __asm__ ("movl %%gs:%c1,%0" : "=r" (__self) \ + : "i" (offsetof (struct _pthread_descr_struct, \ + p_header.data.self))); \ + __self; \ +}) + + +/* Initialize the thread-unique value. Two possible ways to do it. */ + +#define DO_MODIFY_LDT(descr, nr) \ +({ \ + struct modify_ldt_ldt_s ldt_entry = \ + { nr, (unsigned long int) (descr), 0xfffff /* 4GB in pages */, \ + 1, 0, 0, 1, 0, 1, 0 }; \ + if (__modify_ldt (1, &ldt_entry, sizeof (ldt_entry)) != 0) \ + abort (); \ + __asm__ ("movw %w0, %%gs" : : "q" (nr * 8 + 7)); \ +}) + +#ifdef __PIC__ +# define USETLS_EBX_ARG "r" +# define USETLS_LOAD_EBX "xchgl %1, %%ebx\n\t" +#else +# define USETLS_EBX_ARG "b" +# define USETLS_LOAD_EBX +#endif + +/* When using the new set_thread_area call, we don't need to change %gs + because we inherited the value set up in the main thread by TLS setup. + We need to extract that value and set up the same segment in this + thread. */ +#if defined (USE_TLS) && USE_TLS +# define DO_SET_THREAD_AREA_REUSE(nr) 1 +#else +/* Without TLS, we do the initialization of the main thread, where NR == 0. */ +# define DO_SET_THREAD_AREA_REUSE(nr) (!__builtin_constant_p (nr) || (nr)) +#endif +#define DO_SET_THREAD_AREA(descr, nr) \ +({ \ + int __gs; \ + if (DO_SET_THREAD_AREA_REUSE (nr)) \ + { \ + __asm__ ("movw %%gs, %w0" : "=q" (__gs)); \ + struct modify_ldt_ldt_s ldt_entry = \ + { (__gs & 0xffff) >> 3, \ + (unsigned long int) (descr), 0xfffff /* 4GB in pages */, \ + 1, 0, 0, 1, 0, 1, 0 }; \ + \ + int __result; \ + __asm__ (USETLS_LOAD_EBX \ + "movl %2, %%eax\n\t" \ + "int $0x80\n\t" \ + USETLS_LOAD_EBX \ + : "=&a" (__result) \ + : USETLS_EBX_ARG (&ldt_entry), "i" (__NR_set_thread_area), \ + "m" (ldt_entry) \ + : "memory"); \ + if (__result == 0) \ + __asm__ ("movw %w0, %%gs" :: "q" (__gs)); \ + else \ + __gs = -1; \ + } \ + else \ + { \ + struct modify_ldt_ldt_s ldt_entry = \ + { -1, \ + (unsigned long int) (descr), 0xfffff /* 4GB in pages */, \ + 1, 0, 0, 1, 0, 1, 0 }; \ + int __result; \ + __asm__ (USETLS_LOAD_EBX \ + "movl %2, %%eax\n\t" \ + "int $0x80\n\t" \ + USETLS_LOAD_EBX \ + : "=&a" (__result) \ + : USETLS_EBX_ARG (&ldt_entry), "i" (__NR_set_thread_area), \ + "m" (ldt_entry) \ + : "memory"); \ + if (__result == 0) \ + { \ + __gs = (ldt_entry.entry_number << 3) + 3; \ + __asm__ ("movw %w0, %%gs" : : "q" (__gs)); \ + } \ + else \ + __gs = -1; \ + } \ + __gs; \ +}) + +#if defined __ASSUME_SET_THREAD_AREA_SYSCALL +# define INIT_THREAD_SELF(descr, nr) DO_SET_THREAD_AREA (descr, nr) +#elif defined __NR_set_thread_area +# define INIT_THREAD_SELF(descr, nr) \ +({ \ + if (__builtin_expect (__have_no_set_thread_area, 0) \ + || (DO_SET_THREAD_AREA (descr, DO_SET_THREAD_AREA_REUSE (nr)) == -1 \ + && (__have_no_set_thread_area = 1))) \ + DO_MODIFY_LDT (descr, nr); \ +}) +/* Defined in pspinlock.c. */ +extern int __have_no_set_thread_area; +#else +# define INIT_THREAD_SELF(descr, nr) DO_MODIFY_LDT (descr, nr) +#endif + +/* Free resources associated with thread descriptor. */ +#ifdef __ASSUME_SET_THREAD_AREA_SYSCALL +#define FREE_THREAD(descr, nr) do { } while (0) +#elif defined __NR_set_thread_area +#define FREE_THREAD(descr, nr) \ +{ \ + int __gs; \ + __asm__ __volatile__ ("movw %%gs, %w0" : "=q" (__gs)); \ + if (__builtin_expect (__gs & 4, 0)) \ + { \ + struct modify_ldt_ldt_s ldt_entry = \ + { nr, 0, 0, 0, 0, 1, 0, 1, 0, 0 }; \ + __modify_ldt (1, &ldt_entry, sizeof (ldt_entry)); \ + } \ +} +#else +#define FREE_THREAD(descr, nr) \ +{ \ + struct modify_ldt_ldt_s ldt_entry = \ + { nr, 0, 0, 0, 0, 1, 0, 1, 0, 0 }; \ + __modify_ldt (1, &ldt_entry, sizeof (ldt_entry)); \ +} +#endif + +/* Read member of the thread descriptor directly. */ +#define THREAD_GETMEM(descr, member) \ +({ \ + __typeof__ (descr->member) __value; \ + if (sizeof (__value) == 1) \ + __asm__ __volatile__ ("movb %%gs:%P2,%b0" \ + : "=q" (__value) \ + : "0" (0), \ + "i" (offsetof (struct _pthread_descr_struct, \ + member))); \ + else if (sizeof (__value) == 4) \ + __asm__ __volatile__ ("movl %%gs:%P1,%0" \ + : "=r" (__value) \ + : "i" (offsetof (struct _pthread_descr_struct, \ + member))); \ + else \ + { \ + if (sizeof (__value) != 8) \ + /* There should not be any value with a size other than 1, 4 or 8. */\ + abort (); \ + \ + __asm__ __volatile__ ("movl %%gs:%P1,%%eax\n\t" \ + "movl %%gs:%P2,%%edx" \ + : "=A" (__value) \ + : "i" (offsetof (struct _pthread_descr_struct, \ + member)), \ + "i" (offsetof (struct _pthread_descr_struct, \ + member) + 4)); \ + } \ + __value; \ +}) + +/* Same as THREAD_GETMEM, but the member offset can be non-constant. */ +#define THREAD_GETMEM_NC(descr, member) \ +({ \ + __typeof__ (descr->member) __value; \ + if (sizeof (__value) == 1) \ + __asm__ __volatile__ ("movb %%gs:(%2),%b0" \ + : "=q" (__value) \ + : "0" (0), \ + "r" (offsetof (struct _pthread_descr_struct, \ + member))); \ + else if (sizeof (__value) == 4) \ + __asm__ __volatile__ ("movl %%gs:(%1),%0" \ + : "=r" (__value) \ + : "r" (offsetof (struct _pthread_descr_struct, \ + member))); \ + else \ + { \ + if (sizeof (__value) != 8) \ + /* There should not be any value with a size other than 1, 4 or 8. */\ + abort (); \ + \ + __asm__ __volatile__ ("movl %%gs:(%1),%%eax\n\t" \ + "movl %%gs:4(%1),%%edx" \ + : "=&A" (__value) \ + : "r" (offsetof (struct _pthread_descr_struct, \ + member))); \ + } \ + __value; \ +}) + +/* Same as THREAD_SETMEM, but the member offset can be non-constant. */ +#define THREAD_SETMEM(descr, member, value) \ +({ \ + __typeof__ (descr->member) __value = (value); \ + if (sizeof (__value) == 1) \ + __asm__ __volatile__ ("movb %0,%%gs:%P1" : \ + : "q" (__value), \ + "i" (offsetof (struct _pthread_descr_struct, \ + member))); \ + else if (sizeof (__value) == 4) \ + __asm__ __volatile__ ("movl %0,%%gs:%P1" : \ + : "r" (__value), \ + "i" (offsetof (struct _pthread_descr_struct, \ + member))); \ + else \ + { \ + if (sizeof (__value) != 8) \ + /* There should not be any value with a size other than 1, 4 or 8. */\ + abort (); \ + \ + __asm__ __volatile__ ("movl %%eax,%%gs:%P1\n\n" \ + "movl %%edx,%%gs:%P2" : \ + : "A" (__value), \ + "i" (offsetof (struct _pthread_descr_struct, \ + member)), \ + "i" (offsetof (struct _pthread_descr_struct, \ + member) + 4)); \ + } \ +}) + +/* Set member of the thread descriptor directly. */ +#define THREAD_SETMEM_NC(descr, member, value) \ +({ \ + __typeof__ (descr->member) __value = (value); \ + if (sizeof (__value) == 1) \ + __asm__ __volatile__ ("movb %0,%%gs:(%1)" : \ + : "q" (__value), \ + "r" (offsetof (struct _pthread_descr_struct, \ + member))); \ + else if (sizeof (__value) == 4) \ + __asm__ __volatile__ ("movl %0,%%gs:(%1)" : \ + : "r" (__value), \ + "r" (offsetof (struct _pthread_descr_struct, \ + member))); \ + else \ + { \ + if (sizeof (__value) != 8) \ + /* There should not be any value with a size other than 1, 4 or 8. */\ + abort (); \ + \ + __asm__ __volatile__ ("movl %%eax,%%gs:(%1)\n\t" \ + "movl %%edx,%%gs:4(%1)" : \ + : "A" (__value), \ + "r" (offsetof (struct _pthread_descr_struct, \ + member))); \ + } \ +}) +#endif + +#if __ASSUME_LDT_WORKS > 0 +/* We want the OS to assign stack addresses. */ +#define FLOATING_STACKS 1 + +/* Maximum size of the stack if the rlimit is unlimited. */ +#define ARCH_STACK_MAX_SIZE 8*1024*1024 +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/ia64/pspinlock.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/ia64/pspinlock.c new file mode 100644 index 00000000..fa10c7b3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/ia64/pspinlock.c @@ -0,0 +1,79 @@ +/* POSIX spinlock implementation. ia64 version. + Copyright (C) 2000, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jes Sorensen + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include "internals.h" +#include + +/* This implementation is inspired by the implementation used in the + Linux kernel. */ + +int +__pthread_spin_lock (pthread_spinlock_t *lock) +{ + int *p = (int *) lock; + + while (__builtin_expect (__sync_val_compare_and_swap (p, 0, 1), 0)) + { + /* Spin without using the atomic instruction. */ + do + __asm__ __volatile__ ("" : : : "memory"); + while (*p); + } + return 0; +} +weak_alias (__pthread_spin_lock, pthread_spin_lock) + + +int +__pthread_spin_trylock (pthread_spinlock_t *lock) +{ + return __sync_val_compare_and_swap ((int *) lock, 0, 1) == 0 ? 0 : EBUSY; +} +weak_alias (__pthread_spin_trylock, pthread_spin_trylock) + + +int +__pthread_spin_unlock (pthread_spinlock_t *lock) +{ + return *lock = 0; +} +weak_alias (__pthread_spin_unlock, pthread_spin_unlock) + + +int +__pthread_spin_init (pthread_spinlock_t *lock, int pshared) +{ + /* We can ignore the `pshared' parameter. Since we are busy-waiting + all processes which can access the memory location `lock' points + to can use the spinlock. */ + return *lock = 0; +} +weak_alias (__pthread_spin_init, pthread_spin_init) + + +int +__pthread_spin_destroy (pthread_spinlock_t *lock) +{ + /* Nothing to do. */ + return 0; +} +weak_alias (__pthread_spin_destroy, pthread_spin_destroy) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/ia64/pt-machine.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/ia64/pt-machine.h new file mode 100644 index 00000000..e36468a7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/ia64/pt-machine.h @@ -0,0 +1,131 @@ +/* Machine-dependent pthreads configuration and inline functions. + IA-64 version. + Copyright (C) 1999, 2000, 2002, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _PT_MACHINE_H +#define _PT_MACHINE_H 1 + +#include +#include + +#ifndef PT_EI +# define PT_EI __extern_always_inline +#endif + +/* Make sure gcc doesn't try to be clever and move things around on + us. We need to use _exactly_ the address the user gave us, not some + alias that contains the same information. */ +#define __atomic_fool_gcc(x) (*(__volatile__ struct { int a[100]; } *)x) + +#ifndef ELF_MACHINE_NAME + +#define NEED_SEPARATE_REGISTER_STACK + +/* We want the OS to assign stack addresses. */ +#define FLOATING_STACKS 1 + +/* Maximum size of the stack if the rlimit is unlimited. */ +#define ARCH_STACK_MAX_SIZE 32*1024*1024 + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. + r12 (sp) is the stack pointer. */ +#define CURRENT_STACK_FRAME stack_pointer +register char *stack_pointer __asm__ ("sp"); + + +/* Register r13 (tp) is reserved by the ABI as "thread pointer". */ +struct _pthread_descr_struct; +register struct _pthread_descr_struct *__thread_self __asm__("r13"); + +/* Return the thread descriptor for the current thread. */ +#define THREAD_SELF __thread_self + +/* Initialize the thread-unique value. */ +#define INIT_THREAD_SELF(descr, nr) (__thread_self = (descr)) + + +/* Access to data in the thread descriptor is easy. */ +#define THREAD_GETMEM(descr, member) \ + ((void) sizeof (descr), THREAD_SELF->member) +#define THREAD_GETMEM_NC(descr, member) \ + ((void) sizeof (descr), THREAD_SELF->member) +#define THREAD_SETMEM(descr, member, value) \ + ((void) sizeof (descr), THREAD_SELF->member = (value)) +#define THREAD_SETMEM_NC(descr, member, value) \ + ((void) sizeof (descr), THREAD_SELF->member = (value)) + + +/* Memory barrier */ +#define MEMORY_BARRIER() __sync_synchronize () + + +#define HAS_COMPARE_AND_SWAP_WITH_RELEASE_SEMANTICS + +PT_EI int +__compare_and_swap (long int *p, long int oldval, long int newval) +{ + long int readval; + + __asm__ __volatile__ + ("mov ar.ccv=%4;;\n\t" + "cmpxchg8.acq %0=%1,%2,ar.ccv" + : "=r" (readval), "=m" (__atomic_fool_gcc (p)) + : "r"(newval), "m" (__atomic_fool_gcc (p)), "r" (oldval) + : "memory"); + return readval == oldval; +} + +PT_EI int +__compare_and_swap_with_release_semantics (long int *p, + long int oldval, + long int newval) +{ + long int readval; + + __asm__ __volatile__ + ("mov ar.ccv=%4;;\n\t" + "cmpxchg8.rel %0=%1,%2,ar.ccv" + : "=r" (readval), "=m" (__atomic_fool_gcc (p)) + : "r"(newval), "m" (__atomic_fool_gcc (p)), "r" (oldval) + : "memory"); + return readval == oldval; +} + +#endif /* ELF_MACHINE_NAME */ + +/* Spinlock implementation; required. */ +PT_EI long int +testandset (int *spinlock) +{ + long int ret; + + __asm__ __volatile__( + "xchg4 %0=%1,%2" + : "=r"(ret), "=m"(__atomic_fool_gcc (spinlock)) + : "r"(1), "m"(__atomic_fool_gcc (spinlock)) + : "memory"); + + return ret; +} + +/* Indicate that we are looping. */ +#define BUSY_WAIT_NOP __asm__ ("hint @pause") + +#endif /* pt-machine.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/ia64/tcb-offsets.sym b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/ia64/tcb-offsets.sym new file mode 100644 index 00000000..f7793f76 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/ia64/tcb-offsets.sym @@ -0,0 +1,9 @@ +#include +#include + +-- +#ifdef USE_TLS +MULTIPLE_THREADS_OFFSET offsetof (struct _pthread_descr_struct, p_multiple_threads) - sizeof (struct _pthread_descr_struct) +#else +MULTIPLE_THREADS_OFFSET offsetof (tcbhead_t, multiple_threads) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/ia64/tls.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/ia64/tls.h new file mode 100644 index 00000000..0311a9cc --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/ia64/tls.h @@ -0,0 +1,145 @@ +/* Definitions for thread-local data handling. linuxthreads/IA-64 version. + Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _TLS_H +#define _TLS_H + +#ifndef __ASSEMBLER__ + +# include +# include +# include + +/* Type for the dtv. */ +typedef union dtv +{ + size_t counter; + struct + { + void *val; + bool is_static; + } pointer; +} dtv_t; + +#else /* __ASSEMBLER__ */ +# include +#endif /* __ASSEMBLER__ */ + +#ifdef HAVE_TLS_SUPPORT + +/* Signal that TLS support is available. */ +# define USE_TLS 1 + +# ifndef __ASSEMBLER__ + +typedef struct +{ + dtv_t *dtv; + void *private; +} tcbhead_t; + +/* This is the size of the initial TCB. */ +# define TLS_INIT_TCB_SIZE sizeof (tcbhead_t) + +/* Alignment requirements for the initial TCB. */ +# define TLS_INIT_TCB_ALIGN __alignof__ (tcbhead_t) + +/* This is the size of the TCB. */ +# define TLS_TCB_SIZE sizeof (tcbhead_t) + +/* This is the size we need before TCB. */ +# define TLS_PRE_TCB_SIZE sizeof (struct _pthread_descr_struct) + +/* Alignment requirements for the TCB. */ +# define TLS_TCB_ALIGN __alignof__ (struct _pthread_descr_struct) + +/* The DTV is allocated at the TP; the TCB is placed elsewhere. */ +# define TLS_DTV_AT_TP 1 + +/* Install the dtv pointer. The pointer passed is to the element with + index -1 which contain the length. */ +# define INSTALL_DTV(tcbp, dtvp) \ + ((tcbhead_t *) (tcbp))->dtv = (dtvp) + 1 + +/* Install new dtv for current thread. */ +# define INSTALL_NEW_DTV(DTV) \ + (((tcbhead_t *)__thread_self)->dtv = (DTV)) + +/* Return dtv of given thread descriptor. */ +# define GET_DTV(tcbp) \ + (((tcbhead_t *) (tcbp))->dtv) + +#if defined NEED_DL_SYSINFO +# define INIT_SYSINFO \ + (((tcbhead_t *) __thread_self)->private = (void *) GLRO(dl_sysinfo)) +#else +# define INIT_SYSINFO 0 +#endif + +/* Code to initially initialize the thread pointer. This might need + special attention since 'errno' is not yet available and if the + operation can cause a failure 'errno' must not be touched. */ +# define TLS_INIT_TP(tcbp, secondcall) \ + (__thread_self = (__typeof (__thread_self)) (tcbp), INIT_SYSINFO, NULL) + +/* Return the address of the dtv for the current thread. */ +# define THREAD_DTV() \ + (((tcbhead_t *)__thread_self)->dtv) + +/* Return the thread descriptor for the current thread. */ +# undef THREAD_SELF +# define THREAD_SELF (__thread_self - 1) + +# undef INIT_THREAD_SELF +# define INIT_THREAD_SELF(descr, nr) \ + (__thread_self = (struct _pthread_descr_struct *)(descr) + 1) + +# define TLS_MULTIPLE_THREADS_IN_TCB 1 + +/* Get the thread descriptor definition. */ +# include + +# endif + +#else + +# ifndef __ASSEMBLER__ + +typedef struct +{ + void *tcb; + dtv_t *dtv; + void *self; + int multiple_threads; +} tcbhead_t; + +/* Get the thread descriptor definition. */ +# include + +# define NONTLS_INIT_TP \ + do { \ + static const tcbhead_t nontls_init_tp = { .multiple_threads = 0 }; \ + __thread_self = (__typeof (__thread_self)) &nontls_init_tp; \ + } while (0) + +#endif + +#endif /* USE_TLS */ + +#endif /* tls.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/m68k/pspinlock.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/m68k/pspinlock.c new file mode 100644 index 00000000..35b851fa --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/m68k/pspinlock.c @@ -0,0 +1,82 @@ +/* POSIX spinlock implementation. M68k version. + Copyright (C) 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include "internals.h" + + +int +__pthread_spin_lock (pthread_spinlock_t *lock) +{ + unsigned int val; + + do + __asm__ __volatile__ ("tas %1; sne %0" + : "=dm" (val), "=m" (*lock) + : "m" (*lock) + : "cc"); + while (val); + + return 0; +} +weak_alias (__pthread_spin_lock, pthread_spin_lock) + + +int +__pthread_spin_trylock (pthread_spinlock_t *lock) +{ + unsigned int val; + + __asm__ __volatile__ ("tas %1; sne %0" + : "=dm" (val), "=m" (*lock) + : "m" (*lock) + : "cc"); + + return val ? EBUSY : 0; +} +weak_alias (__pthread_spin_trylock, pthread_spin_trylock) + + +int +__pthread_spin_unlock (pthread_spinlock_t *lock) +{ + return *lock = 0; +} +weak_alias (__pthread_spin_unlock, pthread_spin_unlock) + + +int +__pthread_spin_init (pthread_spinlock_t *lock, int pshared) +{ + /* We can ignore the `pshared' parameter. Since we are busy-waiting + all processes which can access the memory location `lock' points + to can use the spinlock. */ + return *lock = 0; +} +weak_alias (__pthread_spin_init, pthread_spin_init) + + +int +__pthread_spin_destroy (pthread_spinlock_t *lock) +{ + /* Nothing to do. */ + return 0; +} +weak_alias (__pthread_spin_destroy, pthread_spin_destroy) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/m68k/pt-machine.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/m68k/pt-machine.h new file mode 100644 index 00000000..a13c0694 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/m68k/pt-machine.h @@ -0,0 +1,68 @@ +/* Machine-dependent pthreads configuration and inline functions. + m68k version. + Copyright (C) 1996, 1998, 2000, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If + not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef _PT_MACHINE_H +#define _PT_MACHINE_H 1 + +#include + +#ifndef PT_EI +# define PT_EI __extern_always_inline +#endif + +/* Spinlock implementation; required. */ +PT_EI long int +testandset (int *spinlock) +{ + char ret; + + __asm__ __volatile__("tas %1; sne %0" + : "=dm"(ret), "=m"(*spinlock) + : "m"(*spinlock) + : "cc"); + + return ret; +} + + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#define CURRENT_STACK_FRAME stack_pointer +register char * stack_pointer __asm__ ("%sp"); + + +/* Compare-and-swap for semaphores. */ + +#define HAS_COMPARE_AND_SWAP +PT_EI int +__compare_and_swap (long int *p, long int oldval, long int newval) +{ + char ret; + long int readval; + + __asm__ __volatile__ ("casl %2, %3, %1; seq %0" + : "=dm" (ret), "=m" (*p), "=d" (readval) + : "d" (newval), "m" (*p), "2" (oldval)); + + return ret; +} + +#endif /* pt-machine.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/mips/pspinlock.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/mips/pspinlock.c new file mode 100644 index 00000000..4d6617e1 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/mips/pspinlock.c @@ -0,0 +1,96 @@ +/* POSIX spinlock implementation. MIPS version. + Copyright (C) 2000, 2002, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include +#include "internals.h" + +/* This implementation is similar to the one used in the Linux kernel. */ +int +__pthread_spin_lock (pthread_spinlock_t *lock) +{ + unsigned int tmp1, tmp2; + + __asm__ __volatile__ + ("\t\t\t# spin_lock\n" + "1:\n\t" + ".set push\n\t" +#if _MIPS_SIM == _ABIO32 + ".set mips2\n\t" +#endif + "ll %1,%3\n\t" + "li %2,1\n\t" + "bnez %1,1b\n\t" + "sc %2,%0\n\t" + ".set pop\n\t" + "beqz %2,1b" + : "=m" (*lock), "=&r" (tmp1), "=&r" (tmp2) + : "m" (*lock) + : "memory"); + + return 0; +} + +weak_alias (__pthread_spin_lock, pthread_spin_lock) + + +int +__pthread_spin_trylock (pthread_spinlock_t *lock) +{ + /* To be done. */ + return 0; +} +weak_alias (__pthread_spin_trylock, pthread_spin_trylock) + + +int +__pthread_spin_unlock (pthread_spinlock_t *lock) +{ + __asm__ __volatile__ + ("\t\t\t# spin_unlock\n\t" + "sw $0,%0" + : "=m" (*lock) + : + : "memory"); + return 0; +} +weak_alias (__pthread_spin_unlock, pthread_spin_unlock) + + +int +__pthread_spin_init (pthread_spinlock_t *lock, int pshared) +{ + /* We can ignore the `pshared' parameter. Since we are busy-waiting + all processes which can access the memory location `lock' points + to can use the spinlock. */ + *lock = 0; + return 0; +} +weak_alias (__pthread_spin_init, pthread_spin_init) + + +int +__pthread_spin_destroy (pthread_spinlock_t *lock) +{ + /* Nothing to do. */ + return 0; +} +weak_alias (__pthread_spin_destroy, pthread_spin_destroy) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/mips/pt-machine.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/mips/pt-machine.h new file mode 100644 index 00000000..0ab7ac13 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/mips/pt-machine.h @@ -0,0 +1,89 @@ +/* Machine-dependent pthreads configuration and inline functions. + + Copyright (C) 1996, 1997, 1998, 2000, 2002, 2003, 2004 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ralf Baechle . + Based on the Alpha version by Richard Henderson . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If + not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef _PT_MACHINE_H +#define _PT_MACHINE_H 1 + +#include +#include +#include + +#ifndef PT_EI +# define PT_EI __extern_always_inline +#endif + +/* Spinlock implementation; required. */ + +PT_EI long int +testandset (int *spinlock) +{ + return _test_and_set (spinlock, 1); +} + + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#define CURRENT_STACK_FRAME stack_pointer +register char * stack_pointer __asm__ ("$29"); + + +/* Compare-and-swap for semaphores. */ + +#define HAS_COMPARE_AND_SWAP +PT_EI int +__compare_and_swap (long int *p, long int oldval, long int newval) +{ + long int ret, temp; + + __asm__ __volatile__ + ("/* Inline compare & swap */\n" + "1:\n\t" + ".set push\n\t" +#if _MIPS_SIM == _ABIO32 + ".set mips2\n\t" +#endif +#if _MIPS_SIM == _ABI64 + "lld %1,%5\n\t" +#else + "ll %1,%5\n\t" +#endif + "move %0,$0\n\t" + "bne %1,%3,2f\n\t" + "move %0,%4\n\t" +#if _MIPS_SIM == _ABI64 + "scd %0,%2\n\t" +#else + "sc %0,%2\n\t" +#endif + ".set pop\n\t" + "beqz %0,1b\n" + "2:\n\t" + "/* End compare & swap */" + : "=&r" (ret), "=&r" (temp), "=m" (*p) + : "r" (oldval), "r" (newval), "m" (*p) + : "memory"); + + return ret; +} + +#endif /* pt-machine.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/mips/tls.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/mips/tls.h new file mode 100644 index 00000000..15dda696 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/mips/tls.h @@ -0,0 +1,170 @@ +/* Definitions for thread-local data handling. linuxthreads/MIPS version. + Copyright (C) 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _TLS_H +#define _TLS_H + +#ifndef __ASSEMBLER__ + +# include +# include +# include + +/* Type for the dtv. */ +typedef union dtv +{ + size_t counter; + struct + { + void *val; + bool is_static; + } pointer; +} dtv_t; + +# define READ_THREAD_POINTER() \ + ({ void *__result; \ + __asm__ __volatile__ (".set\tpush\n\t.set\tmips32r2\n\t" \ + "rdhwr\t%0, $29\n\t.set\tpop" : "=v" (__result)); \ + __result; }) + +#else /* __ASSEMBLER__ */ +# include + +/* Note: rd must be $v1 to be ABI-conformant. */ +# define READ_THREAD_POINTER(rd) \ + .set push; \ + .set mips32r2; \ + rdhwr rd, $29; \ + .set pop +#endif /* __ASSEMBLER__ */ + +/* LinuxThreads can only use TLS if both floating stacks (in the MIPS case, + that means support for "rdhwr") and support from the tools are available. + + We have to define USE_TLS consistently, or ldsodefs.h will lay out types + differently between an NPTL build and a LinuxThreads build. It can be set + for libc.so and not libpthread.so, but only if we provide appropriate padding + in the _pthread_descr_struct. + + Currently nothing defines FLOATING_STACKS. We could assume this based on + kernel version once the TLS patches are available in kernel.org, but + it hardly seems worth it. Use NPTL if you can. + + To avoid bothering with the TLS support code at all, use configure + --without-tls. */ + +#if defined HAVE_TLS_SUPPORT \ + && (defined FLOATING_STACKS || !defined IS_IN_libpthread) + +/* Signal that TLS support is available. */ +# define USE_TLS 1 + +/* Include padding in _pthread_descr_struct so that libc can find p_errno, + if libpthread will only include the padding because of the !IS_IN_libpthread + check. */ +#ifndef FLOATING_STACKS +# define INCLUDE_TLS_PADDING 1 +#endif + +# ifndef __ASSEMBLER__ + +/* This layout is actually wholly private and not affected by the ABI. + Nor does it overlap the pthread data structure, so we need nothing + extra here at all. */ +typedef struct +{ + dtv_t *dtv; + void *private; +} tcbhead_t; + +/* This is the size of the initial TCB. */ +# define TLS_INIT_TCB_SIZE 0 + +/* Alignment requirements for the initial TCB. */ +# define TLS_INIT_TCB_ALIGN __alignof__ (struct _pthread_descr_struct) + +/* This is the size of the TCB. */ +# define TLS_TCB_SIZE 0 + +/* Alignment requirements for the TCB. */ +# define TLS_TCB_ALIGN __alignof__ (struct _pthread_descr_struct) + +/* This is the size we need before TCB. */ +# define TLS_PRE_TCB_SIZE \ + (sizeof (struct _pthread_descr_struct) \ + + ((sizeof (tcbhead_t) + TLS_TCB_ALIGN - 1) & ~(TLS_TCB_ALIGN - 1))) + +/* The thread pointer (in hardware register $29) points to the end of + the TCB + 0x7000, as for PowerPC. The pthread_descr structure is + immediately in front of the TCB. */ +#define TLS_TCB_OFFSET 0x7000 + +/* The DTV is allocated at the TP; the TCB is placed elsewhere. */ +/* This is not really true for powerpc64. We are following alpha + where the DTV pointer is first doubleword in the TCB. */ +# define TLS_DTV_AT_TP 1 + +/* Install the dtv pointer. The pointer passed is to the element with + index -1 which contain the length. */ +# define INSTALL_DTV(TCBP, DTVP) \ + (((tcbhead_t *) (TCBP))[-1].dtv = (DTVP) + 1) + +/* Install new dtv for current thread. */ +# define INSTALL_NEW_DTV(DTV) (THREAD_DTV() = (DTV)) + +/* Return dtv of given thread descriptor. */ +# define GET_DTV(TCBP) (((tcbhead_t *) (TCBP))[-1].dtv) + +/* Code to initially initialize the thread pointer. This might need + special attention since 'errno' is not yet available and if the + operation can cause a failure 'errno' must not be touched. */ +# define TLS_INIT_TP(tcbp, secondcall) \ + ({ INTERNAL_SYSCALL_DECL (err); \ + long result_var; \ + result_var = INTERNAL_SYSCALL (set_thread_area, err, 1, \ + (char *) (tcbp) + TLS_TCB_OFFSET); \ + INTERNAL_SYSCALL_ERROR_P (result_var, err) \ + ? "unknown error" : NULL; }) + +/* Return the address of the dtv for the current thread. */ +# define THREAD_DTV() \ + (((tcbhead_t *) (READ_THREAD_POINTER () - TLS_TCB_OFFSET))[-1].dtv) + +/* Return the thread descriptor for the current thread. */ +# undef THREAD_SELF +# define THREAD_SELF \ + ((pthread_descr) (READ_THREAD_POINTER () \ + - TLS_TCB_OFFSET - TLS_PRE_TCB_SIZE)) + +/* Get the thread descriptor definition. */ +# include + +/* l_tls_offset == 0 is perfectly valid on MIPS, so we have to use some + different value to mean unset l_tls_offset. */ +# define NO_TLS_OFFSET -1 + +/* Initializing the thread pointer requires a syscall which may not be + available, so don't do it if we don't need to. */ +# define TLS_INIT_TP_EXPENSIVE 1 + +# endif /* __ASSEMBLER__ */ + +#endif /* HAVE_TLS_SUPPORT */ + +#endif /* tls.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/powerpc/powerpc32/pspinlock.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/powerpc/powerpc32/pspinlock.c new file mode 100644 index 00000000..15fd545c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/powerpc/powerpc32/pspinlock.c @@ -0,0 +1,70 @@ +/* POSIX spinlock implementation. PowerPC version. + Copyright (C) 2000, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include "internals.h" + +int +__pthread_spin_lock (pthread_spinlock_t *lock) +{ + while (! __compare_and_swap ((long int *)lock, 0, 1)) + ; + return 0; +} +weak_alias (__pthread_spin_lock, pthread_spin_lock) + + +int +__pthread_spin_trylock (pthread_spinlock_t *lock) +{ + return __compare_and_swap ((long int *)lock, 0, 1) ? 0 : EBUSY; +} +weak_alias (__pthread_spin_trylock, pthread_spin_trylock) + + +int +__pthread_spin_unlock (pthread_spinlock_t *lock) +{ + MEMORY_BARRIER (); + *lock = 0; + return 0; +} +weak_alias (__pthread_spin_unlock, pthread_spin_unlock) + + +int +__pthread_spin_init (pthread_spinlock_t *lock, int pshared) +{ + /* We can ignore the `pshared' parameter. Since we are busy-waiting + all processes which can access the memory location `lock' points + to can use the spinlock. */ + *lock = 0; + return 0; +} +weak_alias (__pthread_spin_init, pthread_spin_init) + + +int +__pthread_spin_destroy (pthread_spinlock_t *lock) +{ + /* Nothing to do. */ + return 0; +} +weak_alias (__pthread_spin_destroy, pthread_spin_destroy) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/powerpc/powerpc32/pt-machine.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/powerpc/powerpc32/pt-machine.h new file mode 100644 index 00000000..bfb13df6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/powerpc/powerpc32/pt-machine.h @@ -0,0 +1,120 @@ +/* Machine-dependent pthreads configuration and inline functions. + powerpc version. + Copyright (C) 1996, 1997, 1998, 2000, 2001, 2002, 2003 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If + not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* These routines are from Appendix G of the 'PowerPC 601 RISC Microprocessor + User's Manual', by IBM and Motorola. */ + +#ifndef _PT_MACHINE_H +#define _PT_MACHINE_H 1 + +#ifndef PT_EI +# define PT_EI __extern_always_inline +#endif + +extern long int testandset (int *spinlock); +extern int __compare_and_swap (long int *p, long int oldval, long int newval); + +/* For multiprocessor systems, we want to ensure all memory accesses + are completed before we reset a lock. On other systems, we still + need to make sure that the compiler has flushed everything to memory. */ +#define MEMORY_BARRIER() __asm__ __volatile__ ("sync" : : : "memory") + +/* We want the OS to assign stack addresses. */ +#define FLOATING_STACKS 1 + +/* Maximum size of the stack if the rlimit is unlimited. */ +#define ARCH_STACK_MAX_SIZE 8*1024*1024 + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#define CURRENT_STACK_FRAME stack_pointer +register char * stack_pointer __asm__ ("r1"); + +/* Register r2 (tp) is reserved by the ABI as "thread pointer". */ +struct _pthread_descr_struct; +register struct _pthread_descr_struct *__thread_self __asm__("r2"); + +/* Return the thread descriptor for the current thread. */ +#define THREAD_SELF __thread_self + +/* Initialize the thread-unique value. */ +#define INIT_THREAD_SELF(descr, nr) (__thread_self = (descr)) + +/* Access to data in the thread descriptor is easy. */ +#define THREAD_GETMEM(descr, member) \ + ((void) (descr), THREAD_SELF->member) +#define THREAD_GETMEM_NC(descr, member) \ + ((void) (descr), THREAD_SELF->member) +#define THREAD_SETMEM(descr, member, value) \ + ((void) (descr), THREAD_SELF->member = (value)) +#define THREAD_SETMEM_NC(descr, member, value) \ + ((void) (descr), THREAD_SELF->member = (value)) + +/* Compare-and-swap for semaphores. */ +/* note that test-and-set(x) is the same as !compare-and-swap(x, 0, 1) */ + +#define HAS_COMPARE_AND_SWAP_WITH_RELEASE_SEMANTICS +#define IMPLEMENT_TAS_WITH_CAS + +PT_EI int +__compare_and_swap (long int *p, long int oldval, long int newval) +{ + int ret; + + __asm__ __volatile__ ( + "0: lwarx %0,0,%1 ;" + " xor. %0,%3,%0;" + " bne 1f;" + " stwcx. %2,0,%1;" + " bne- 0b;" + "1: " + : "=&r"(ret) + : "r"(p), "r"(newval), "r"(oldval) + : "cr0", "memory"); + /* This version of __compare_and_swap is to be used when acquiring + a lock, so we don't need to worry about whether other memory + operations have completed, but we do need to be sure that any loads + after this point really occur after we have acquired the lock. */ + __asm__ __volatile__ ("isync" : : : "memory"); + return ret == 0; +} + +PT_EI int +__compare_and_swap_with_release_semantics (long int *p, + long int oldval, long int newval) +{ + int ret; + + MEMORY_BARRIER (); + __asm__ __volatile__ ( + "0: lwarx %0,0,%1 ;" + " xor. %0,%3,%0;" + " bne 1f;" + " stwcx. %2,0,%1;" + " bne- 0b;" + "1: " + : "=&r"(ret) + : "r"(p), "r"(newval), "r"(oldval) + : "cr0", "memory"); + return ret == 0; +} + +#endif /* pt-machine.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/powerpc/powerpc64/pspinlock.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/powerpc/powerpc64/pspinlock.c new file mode 100644 index 00000000..19161c6e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/powerpc/powerpc64/pspinlock.c @@ -0,0 +1,70 @@ +/* POSIX spinlock implementation. PowerPC version. + Copyright (C) 2000, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include "internals.h" + +int +__pthread_spin_lock (pthread_spinlock_t *lock) +{ + while (! __compare_and_swap32 ((int *)lock, 0, 1)) + ; + return 0; +} +weak_alias (__pthread_spin_lock, pthread_spin_lock) + + +int +__pthread_spin_trylock (pthread_spinlock_t *lock) +{ + return __compare_and_swap32 ((int *)lock, 0, 1) ? 0 : EBUSY; +} +weak_alias (__pthread_spin_trylock, pthread_spin_trylock) + + +int +__pthread_spin_unlock (pthread_spinlock_t *lock) +{ + MEMORY_BARRIER (); + *lock = 0; + return 0; +} +weak_alias (__pthread_spin_unlock, pthread_spin_unlock) + + +int +__pthread_spin_init (pthread_spinlock_t *lock, int pshared) +{ + /* We can ignore the `pshared' parameter. Since we are busy-waiting + all processes which can access the memory location `lock' points + to can use the spinlock. */ + *lock = 0; + return 0; +} +weak_alias (__pthread_spin_init, pthread_spin_init) + + +int +__pthread_spin_destroy (pthread_spinlock_t *lock) +{ + /* Nothing to do. */ + return 0; +} +weak_alias (__pthread_spin_destroy, pthread_spin_destroy) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/powerpc/powerpc64/pt-machine.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/powerpc/powerpc64/pt-machine.h new file mode 100644 index 00000000..d7ed8410 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/powerpc/powerpc64/pt-machine.h @@ -0,0 +1,185 @@ +/* Machine-dependent pthreads configuration and inline functions. + powerpc version. + Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If + not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* These routines are from Appendix G of the 'PowerPC 601 RISC Microprocessor + User's Manual', by IBM and Motorola. */ + +#ifndef _PT_MACHINE_H +#define _PT_MACHINE_H 1 + +#ifndef PT_EI +# define PT_EI __extern_always_inline +#endif + +extern long int testandset (int *spinlock); +extern int __compare_and_swap (long int *p, long int oldval, long int newval); +extern int __compare_and_swap32 (int *p, int oldval, int newval); + +/* For multiprocessor systems, we want to ensure all memory accesses + are completed before we reset a lock. On other systems, we still + need to make sure that the compiler has flushed everything to memory. */ +#define MEMORY_BARRIER() __asm__ __volatile__ ("lwsync" : : : "memory") +#define READ_MEMORY_BARRIER() __asm__ __volatile__ ("lwsync" : : : "memory") +#define WRITE_MEMORY_BARRIER() __asm__ __volatile__ ("eieio" : : : "memory") + +/* We want the OS to assign stack addresses. */ +#define FLOATING_STACKS 1 + +/* Maximum size of the stack if the rlimit is unlimited. */ +#define ARCH_STACK_MAX_SIZE 16*1024*1024 + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#define CURRENT_STACK_FRAME stack_pointer +register char * stack_pointer __asm__ ("r1"); + +/* Register r13 (tp) is reserved by the ABI as "thread pointer". */ +struct _pthread_descr_struct; +register struct _pthread_descr_struct *__thread_self __asm__("r13"); + +/* Return the thread descriptor for the current thread. */ +#define THREAD_SELF __thread_self + +/* Initialize the thread-unique value. */ +#define INIT_THREAD_SELF(descr, nr) (__thread_self = (descr)) + +/* Access to data in the thread descriptor is easy. */ +#define THREAD_GETMEM(descr, member) \ + ((void) (descr), THREAD_SELF->member) +#define THREAD_GETMEM_NC(descr, member) \ + ((void) (descr), THREAD_SELF->member) +#define THREAD_SETMEM(descr, member, value) \ + ((void) (descr), THREAD_SELF->member = (value)) +#define THREAD_SETMEM_NC(descr, member, value) \ + ((void) (descr), THREAD_SELF->member = (value)) + +/* Compare-and-swap for semaphores. */ +/* note that test-and-set(x) is the same as !compare-and-swap(x, 0, 1) */ + +#define HAS_COMPARE_AND_SWAP +#define HAS_COMPARE_AND_SWAP_WITH_RELEASE_SEMANTICS + +PT_EI int +__compare_and_swap (long int *p, long int oldval, long int newval) +{ + long int ret; + + __asm__ __volatile__ ( + "0: ldarx %0,0,%1 ;" + " xor. %0,%3,%0;" + " bne 1f;" + " stdcx. %2,0,%1;" + " bne- 0b;" + "1: " + : "=&r"(ret) + : "r"(p), "r"(newval), "r"(oldval) + : "cr0", "memory"); + /* This version of __compare_and_swap is to be used when acquiring + a lock, so we don't need to worry about whether other memory + operations have completed, but we do need to be sure that any loads + after this point really occur after we have acquired the lock. */ + __asm__ __volatile__ ("isync" : : : "memory"); + return (int)(ret == 0); +} + +PT_EI int +__compare_and_swap_with_release_semantics (long int *p, + long int oldval, long int newval) +{ + long int ret; + + MEMORY_BARRIER (); + __asm__ __volatile__ ( + "0: ldarx %0,0,%1 ;" + " xor. %0,%3,%0;" + " bne 1f;" + " stdcx. %2,0,%1;" + " bne- 0b;" + "1: " + : "=&r"(ret) + : "r"(p), "r"(newval), "r"(oldval) + : "cr0", "memory"); + return (int)(ret == 0); +} + +PT_EI int +__compare_and_swap32 (int *p, int oldval, int newval) +{ + int ret; + + __asm__ __volatile__ ( + "0: lwarx %0,0,%1 ;" + " xor. %0,%3,%0;" + " bne 1f;" + " stwcx. %2,0,%1;" + " bne- 0b;" + "1: " + : "=&r"(ret) + : "r"(p), "r"(newval), "r"(oldval) + : "cr0", "memory"); + /* This version of __compare_and_swap is to be used when acquiring + a lock, so we don't need to worry about whether other memory + operations have completed, but we do need to be sure that any loads + after this point really occur after we have acquired the lock. */ + __asm__ __volatile__ ("isync" : : : "memory"); + return (int)(ret == 0); +} + +PT_EI int +__compare_and_swap32_with_release_semantics (long int *p, + long int oldval, long int newval) +{ + long int ret; + + MEMORY_BARRIER (); + __asm__ __volatile__ ( + "0: lwarx %0,0,%1 ;" + " xor. %0,%3,%0;" + " bne 1f;" + " stwcx. %2,0,%1;" + " bne- 0b;" + "1: " + : "=&r"(ret) + : "r"(p), "r"(newval), "r"(oldval) + : "cr0", "memory"); + return (int)(ret == 0); +} + +PT_EI long int +testandset (int *p) +{ + long int ret, val = 1; + + MEMORY_BARRIER (); + __asm__ __volatile__ ( + "0: lwarx %0,0,%1 ;" + " cmpwi 0,%0,0;" + " bne 1f;" + " stwcx. %2,0,%1;" + " bne- 0b;" + "1: " + : "=&r"(ret) + : "r"(p), "r" (val) + : "cr0", "memory"); + MEMORY_BARRIER (); + return ret != 0; +} + +#endif /* pt-machine.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/powerpc/pspinlock.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/powerpc/pspinlock.c new file mode 100644 index 00000000..bb88a069 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/powerpc/pspinlock.c @@ -0,0 +1,8 @@ +#include +#include + +#if __WORDSIZE == 32 +# include "powerpc32/pspinlock.c" +#else +# include "powerpc64/pspinlock.c" +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/powerpc/pt-machine.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/powerpc/pt-machine.h new file mode 100644 index 00000000..55e922ef --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/powerpc/pt-machine.h @@ -0,0 +1,8 @@ +#include +#include + +#if __WORDSIZE == 32 +# include "powerpc32/pt-machine.h" +#else +# include "powerpc64/pt-machine.h" +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/powerpc/tcb-offsets.sym b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/powerpc/tcb-offsets.sym new file mode 100644 index 00000000..7c5cca01 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/powerpc/tcb-offsets.sym @@ -0,0 +1,19 @@ +#include +#include + +-- This line separates the #include lines from conditionals. + +# ifdef USE_TLS + +-- Abuse tls.h macros to derive offsets relative to the thread register. +# undef __thread_register +# define __thread_register ((void *) 0) +# define thread_offsetof(mem) ((ptrdiff_t) THREAD_SELF + offsetof (struct _pthread_descr_struct, p_##mem)) + +# else + +# define thread_offsetof(mem) offsetof (tcbhead_t, mem) + +# endif + +MULTIPLE_THREADS_OFFSET thread_offsetof (multiple_threads) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/powerpc/tls.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/powerpc/tls.h new file mode 100644 index 00000000..1ae0b60f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/powerpc/tls.h @@ -0,0 +1,165 @@ +/* Definitions for thread-local data handling. linuxthreads/PPC version. + Copyright (C) 2003, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _TLS_H +#define _TLS_H + +#ifndef __ASSEMBLER__ + +# include +# include +# include + +/* Type for the dtv. */ +typedef union dtv +{ + size_t counter; + struct + { + void *val; + bool is_static; + } pointer; +} dtv_t; + +#else /* __ASSEMBLER__ */ +# include +#endif /* __ASSEMBLER__ */ + +#ifdef HAVE_TLS_SUPPORT + +/* Signal that TLS support is available. */ +# define USE_TLS 1 + +# ifndef __ASSEMBLER__ + +/* This layout is actually wholly private and not affected by the ABI. + Nor does it overlap the pthread data structure, so we need nothing + extra here at all. */ +typedef struct +{ + dtv_t *dtv; +} tcbhead_t; + +/* This is the size of the initial TCB. */ +# define TLS_INIT_TCB_SIZE 0 + +/* Alignment requirements for the initial TCB. */ +# define TLS_INIT_TCB_ALIGN __alignof__ (struct _pthread_descr_struct) + +/* This is the size of the TCB. */ +# define TLS_TCB_SIZE 0 + +/* Alignment requirements for the TCB. */ +# define TLS_TCB_ALIGN __alignof__ (struct _pthread_descr_struct) + +/* This is the size we need before TCB. */ +# define TLS_PRE_TCB_SIZE \ + (sizeof (struct _pthread_descr_struct) \ + + ((sizeof (tcbhead_t) + TLS_TCB_ALIGN - 1) & ~(TLS_TCB_ALIGN - 1))) + +/* The following assumes that TP (R2 or R13) is points to the end of the + TCB + 0x7000 (per the ABI). This implies that TCB address is + TP - 0x7000. As we define TLS_DTV_AT_TP we can + assume that the pthread_descr is allocated immediately ahead of the + TCB. This implies that the pthread_descr address is + TP - (TLS_PRE_TCB_SIZE + 0x7000). */ +#define TLS_TCB_OFFSET 0x7000 + +/* The DTV is allocated at the TP; the TCB is placed elsewhere. */ +/* This is not really true for powerpc64. We are following alpha + where the DTV pointer is first doubleword in the TCB. */ +# define TLS_DTV_AT_TP 1 + +/* Install the dtv pointer. The pointer passed is to the element with + index -1 which contain the length. */ +# define INSTALL_DTV(TCBP, DTVP) \ + (((tcbhead_t *) (TCBP))[-1].dtv = (DTVP) + 1) + +/* Install new dtv for current thread. */ +# define INSTALL_NEW_DTV(DTV) (THREAD_DTV() = (DTV)) + +/* Return dtv of given thread descriptor. */ +# define GET_DTV(TCBP) (((tcbhead_t *) (TCBP))[-1].dtv) + +/* We still need this define so that tcb-offsets.sym can override it and + use THREAD_SELF to generate MULTIPLE_THREADS_OFFSET. */ +# define __thread_register ((void *) __thread_self) + +/* Code to initially initialize the thread pointer. This might need + special attention since 'errno' is not yet available and if the + operation can cause a failure 'errno' must not be touched. + + The global register variable is declared in pt-machine.h with the + wrong type, so we need some extra casts to get the desired result. + This avoids a lvalue cast that gcc-3.4 does not like. */ +# define TLS_INIT_TP(TCBP, SECONDCALL) \ + (__thread_self = (struct _pthread_descr_struct *) \ + ((void *) (TCBP) + TLS_TCB_OFFSET), NULL) + +/* Return the address of the dtv for the current thread. */ +# define THREAD_DTV() \ + (((tcbhead_t *) ((void *) __thread_self - TLS_TCB_OFFSET))[-1].dtv) + +/* Return the thread descriptor for the current thread. */ +# undef THREAD_SELF +# define THREAD_SELF \ + ((pthread_descr) (__thread_register \ + - TLS_TCB_OFFSET - TLS_PRE_TCB_SIZE)) + +# undef INIT_THREAD_SELF +# define INIT_THREAD_SELF(DESCR, NR) \ + (__thread_self = (struct _pthread_descr_struct *)((void *) (DESCR) \ + + TLS_TCB_OFFSET + TLS_PRE_TCB_SIZE)) + +/* Make sure we have the p_multiple_threads member in the thread structure. + See below. */ +# define TLS_MULTIPLE_THREADS_IN_TCB 1 + +/* Get the thread descriptor definition. */ +# include + +/* l_tls_offset == 0 is perfectly valid on PPC, so we have to use some + different value to mean unset l_tls_offset. */ +# define NO_TLS_OFFSET -1 + +# endif /* __ASSEMBLER__ */ + +#elif !defined __ASSEMBLER__ + +/* This overlaps the start of the pthread_descr. System calls + and such use this to find the multiple_threads flag and need + to use the same offset relative to the thread register in both + single-threaded and multi-threaded code. */ +typedef struct +{ + void *tcb; /* Never used. */ + dtv_t *dtv; /* Never used. */ + void *self; /* Used only if multithreaded, and rarely. */ + int multiple_threads; /* Only this member is really used. */ +} tcbhead_t; + +#define NONTLS_INIT_TP \ + do { \ + static const tcbhead_t nontls_init_tp = { .multiple_threads = 0 }; \ + __thread_self = (__typeof (__thread_self)) &nontls_init_tp; \ + } while (0) + +#endif /* HAVE_TLS_SUPPORT */ + +#endif /* tls.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/.cvsignore b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/.cvsignore new file mode 100644 index 00000000..7ee8f596 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/.cvsignore @@ -0,0 +1,2 @@ +.cvsignore +*.os diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/bits/initspin.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/bits/initspin.h new file mode 100644 index 00000000..a19ec077 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/bits/initspin.h @@ -0,0 +1,28 @@ +/* Generic definitions for spinlock initializers. + Copyright (C) 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* Initial value of a spinlock. Most platforms should use zero, + unless they only implement a "test and clear" operation instead of + the usual "test and set". */ +#define __LT_SPINLOCK_INIT 0 + +/* Macros for lock initializers, using the above definition. */ +#define __LOCK_INITIALIZER { 0, __LT_SPINLOCK_INIT } +#define __ALT_LOCK_INITIALIZER { 0, __LT_SPINLOCK_INIT } +#define __ATOMIC_INITIALIZER { 0, __LT_SPINLOCK_INIT } diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/bits/libc-lock.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/bits/libc-lock.h new file mode 100644 index 00000000..2299b3af --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/bits/libc-lock.h @@ -0,0 +1,409 @@ +/* libc-internal interface for mutex locks. LinuxThreads version. + Copyright (C) 1996,1997,1998,1999,2000,2001,2002,2003,2006 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _BITS_LIBC_LOCK_H +#define _BITS_LIBC_LOCK_H 1 + +#include + +#if defined _LIBC && !defined NOT_IN_libc +#include +#endif + +/* Mutex type. */ +#if defined(_LIBC) || defined(_IO_MTSAFE_IO) +typedef pthread_mutex_t __libc_lock_t; +typedef struct { pthread_mutex_t mutex; } __libc_lock_recursive_t; +# ifdef __USE_UNIX98 +typedef pthread_rwlock_t __libc_rwlock_t; +# else +typedef struct __libc_rwlock_opaque__ __libc_rwlock_t; +# endif +typedef __libc_lock_recursive_t __rtld_lock_recursive_t; +#else +typedef struct __libc_lock_opaque__ __libc_lock_t; +typedef struct __libc_lock_recursive_opaque__ __libc_lock_recursive_t; +typedef struct __libc_rwlock_opaque__ __libc_rwlock_t; +#endif + +/* Type for key to thread-specific data. */ +typedef pthread_key_t __libc_key_t; + +/* Define a lock variable NAME with storage class CLASS. The lock must be + initialized with __libc_lock_init before it can be used (or define it + with __libc_lock_define_initialized, below). Use `extern' for CLASS to + declare a lock defined in another module. In public structure + definitions you must use a pointer to the lock structure (i.e., NAME + begins with a `*'), because its storage size will not be known outside + of libc. */ +#define __libc_lock_define(CLASS,NAME) \ + CLASS __libc_lock_t NAME; +#define __libc_rwlock_define(CLASS,NAME) \ + CLASS __libc_rwlock_t NAME; +#define __libc_lock_define_recursive(CLASS,NAME) \ + CLASS __libc_lock_recursive_t NAME; +#define __rtld_lock_define_recursive(CLASS,NAME) \ + CLASS __rtld_lock_recursive_t NAME; + +/* Define an initialized lock variable NAME with storage class CLASS. + + For the C library we take a deeper look at the initializer. For + this implementation all fields are initialized to zero. Therefore + we don't initialize the variable which allows putting it into the + BSS section. (Except on PA-RISC and other odd architectures, where + initialized locks must be set to one due to the lack of normal + atomic operations.) */ + +#if __LT_SPINLOCK_INIT == 0 +# define __libc_lock_define_initialized(CLASS,NAME) \ + CLASS __libc_lock_t NAME; +#else +# define __libc_lock_define_initialized(CLASS,NAME) \ + CLASS __libc_lock_t NAME = PTHREAD_MUTEX_INITIALIZER; +#endif + +#define __libc_rwlock_define_initialized(CLASS,NAME) \ + CLASS __libc_rwlock_t NAME = PTHREAD_RWLOCK_INITIALIZER; + +/* Define an initialized recursive lock variable NAME with storage + class CLASS. */ +#define __libc_lock_define_initialized_recursive(CLASS,NAME) \ + CLASS __libc_lock_recursive_t NAME = _LIBC_LOCK_RECURSIVE_INITIALIZER; +#define _LIBC_LOCK_RECURSIVE_INITIALIZER \ + {PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP} + +#define __rtld_lock_define_initialized_recursive(CLASS,NAME) \ + CLASS __rtld_lock_recursive_t NAME = _RTLD_LOCK_RECURSIVE_INITIALIZER; +#define _RTLD_LOCK_RECURSIVE_INITIALIZER \ + {PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP} + +#if defined _LIBC && defined IS_IN_libpthread +# define __libc_maybe_call(FUNC, ARGS, ELSE) FUNC ARGS +#else +# if defined __PIC__ || (defined _LIBC && defined SHARED) +# define __libc_maybe_call(FUNC, ARGS, ELSE) \ + (__extension__ ({ __typeof (FUNC) *_fn = (FUNC); \ + _fn != NULL ? (*_fn) ARGS : ELSE; })) +# else +# define __libc_maybe_call(FUNC, ARGS, ELSE) \ + (FUNC != NULL ? FUNC ARGS : ELSE) +# endif +#endif +#if defined _LIBC && !defined NOT_IN_libc && defined SHARED +# define __libc_maybe_call2(FUNC, ARGS, ELSE) \ + ({__builtin_expect (__libc_pthread_functions.ptr_##FUNC != NULL, 0) \ + ? __libc_pthread_functions.ptr_##FUNC ARGS : ELSE; }) +#else +# define __libc_maybe_call2(FUNC, ARGS, ELSE) __libc_maybe_call (__##FUNC, ARGS, ELSE) +#endif + +/* Initialize the named lock variable, leaving it in a consistent, unlocked + state. */ +#if defined _LIBC && !defined NOT_IN_libc && defined SHARED +#define __libc_lock_init(NAME) \ + ({ \ + (NAME).__m_count = 0; \ + (NAME).__m_owner = NULL; \ + (NAME).__m_kind = PTHREAD_MUTEX_TIMED_NP; \ + (NAME).__m_lock.__status = 0; \ + (NAME).__m_lock.__spinlock = __LT_SPINLOCK_INIT; \ + 0; }) +#else +#define __libc_lock_init(NAME) \ + (__libc_maybe_call2 (pthread_mutex_init, (&(NAME), NULL), 0)) +#endif +#define __libc_rwlock_init(NAME) \ + (__libc_maybe_call (__pthread_rwlock_init, (&(NAME), NULL), 0)); + +/* Same as last but this time we initialize a recursive mutex. */ +#if defined _LIBC && !defined NOT_IN_libc && defined SHARED +#define __libc_lock_init_recursive(NAME) \ + ({ \ + (NAME).mutex.__m_count = 0; \ + (NAME).mutex.__m_owner = NULL; \ + (NAME).mutex.__m_kind = PTHREAD_MUTEX_RECURSIVE_NP; \ + (NAME).mutex.__m_lock.__status = 0; \ + (NAME).mutex.__m_lock.__spinlock = __LT_SPINLOCK_INIT; \ + 0; }) +#else +#define __libc_lock_init_recursive(NAME) \ + do { \ + if (__pthread_mutex_init != NULL) \ + { \ + pthread_mutexattr_t __attr; \ + __pthread_mutexattr_init (&__attr); \ + __pthread_mutexattr_settype (&__attr, PTHREAD_MUTEX_RECURSIVE_NP); \ + __pthread_mutex_init (&(NAME).mutex, &__attr); \ + __pthread_mutexattr_destroy (&__attr); \ + } \ + } while (0); +#endif +#define __rtld_lock_init_recursive(NAME) \ + __libc_lock_init_recursive (NAME) + +/* Finalize the named lock variable, which must be locked. It cannot be + used again until __libc_lock_init is called again on it. This must be + called on a lock variable before the containing storage is reused. */ +#define __libc_lock_fini(NAME) \ + (__libc_maybe_call2 (pthread_mutex_destroy, (&(NAME)), 0)); +#define __libc_rwlock_fini(NAME) \ + (__libc_maybe_call (__pthread_rwlock_destroy, (&(NAME)), 0)); + +/* Finalize recursive named lock. */ +#define __libc_lock_fini_recursive(NAME) __libc_lock_fini ((NAME).mutex) +#define __rtld_lock_fini_recursive(NAME) __libc_lock_fini_recursive (NAME) + +/* Lock the named lock variable. */ +#define __libc_lock_lock(NAME) \ + (__libc_maybe_call2 (pthread_mutex_lock, (&(NAME)), 0)); +#define __libc_rwlock_rdlock(NAME) \ + (__libc_maybe_call (__pthread_rwlock_rdlock, (&(NAME)), 0)); +#define __libc_rwlock_wrlock(NAME) \ + (__libc_maybe_call (__pthread_rwlock_wrlock, (&(NAME)), 0)); + +/* Lock the recursive named lock variable. */ +#define __libc_lock_lock_recursive(NAME) __libc_lock_lock ((NAME).mutex) + +/* Try to lock the named lock variable. */ +#define __libc_lock_trylock(NAME) \ + (__libc_maybe_call2 (pthread_mutex_trylock, (&(NAME)), 0)) +#define __libc_rwlock_tryrdlock(NAME) \ + (__libc_maybe_call (__pthread_rwlock_tryrdlock, (&(NAME)), 0)) +#define __libc_rwlock_trywrlock(NAME) \ + (__libc_maybe_call (__pthread_rwlock_trywrlock, (&(NAME)), 0)) + +/* Try to lock the recursive named lock variable. */ +#define __libc_lock_trylock_recursive(NAME) __libc_lock_trylock ((NAME).mutex) +#define __rtld_lock_trylock_recursive(NAME) \ + __libc_lock_trylock_recursive (NAME) + +/* Unlock the named lock variable. */ +#define __libc_lock_unlock(NAME) \ + (__libc_maybe_call2 (pthread_mutex_unlock, (&(NAME)), 0)); +#define __libc_rwlock_unlock(NAME) \ + (__libc_maybe_call (__pthread_rwlock_unlock, (&(NAME)), 0)); + +/* Unlock the recursive named lock variable. */ +#define __libc_lock_unlock_recursive(NAME) __libc_lock_unlock ((NAME).mutex) + +#if defined _LIBC && defined SHARED +# define __rtld_lock_default_lock_recursive(lock) \ + ++((pthread_mutex_t *)(lock))->__m_count; + +# define __rtld_lock_default_unlock_recursive(lock) \ + --((pthread_mutex_t *)(lock))->__m_count; + +# define __rtld_lock_lock_recursive(NAME) \ + GL(dl_rtld_lock_recursive) (&(NAME).mutex) + +# define __rtld_lock_unlock_recursive(NAME) \ + GL(dl_rtld_unlock_recursive) (&(NAME).mutex) +#else +#define __rtld_lock_lock_recursive(NAME) __libc_lock_lock_recursive (NAME) +#define __rtld_lock_unlock_recursive(NAME) __libc_lock_unlock_recursive (NAME) +#endif + +/* Define once control variable. */ +#if PTHREAD_ONCE_INIT == 0 +/* Special case for static variables where we can avoid the initialization + if it is zero. */ +# define __libc_once_define(CLASS, NAME) \ + CLASS pthread_once_t NAME +#else +# define __libc_once_define(CLASS, NAME) \ + CLASS pthread_once_t NAME = PTHREAD_ONCE_INIT +#endif + +/* Call handler iff the first call. */ +#define __libc_once(ONCE_CONTROL, INIT_FUNCTION) \ + do { \ + if (__pthread_once != NULL) \ + __pthread_once (&(ONCE_CONTROL), (INIT_FUNCTION)); \ + else if ((ONCE_CONTROL) == PTHREAD_ONCE_INIT) { \ + INIT_FUNCTION (); \ + (ONCE_CONTROL) = 2; \ + } \ + } while (0) + + +/* Start critical region with cleanup. */ +#define __libc_cleanup_region_start(DOIT, FCT, ARG) \ + { struct _pthread_cleanup_buffer _buffer; \ + int _avail = (DOIT) && _pthread_cleanup_push_defer != NULL; \ + if (_avail) { \ + _pthread_cleanup_push_defer (&_buffer, (FCT), (ARG)); \ + } + +/* End critical region with cleanup. */ +#define __libc_cleanup_region_end(DOIT) \ + if (_avail) { \ + _pthread_cleanup_pop_restore (&_buffer, (DOIT)); \ + } \ + } + +/* Sometimes we have to exit the block in the middle. */ +#define __libc_cleanup_end(DOIT) \ + if (_avail) { \ + _pthread_cleanup_pop_restore (&_buffer, (DOIT)); \ + } + +#define __libc_cleanup_push(fct, arg) \ + { struct _pthread_cleanup_buffer _buffer; \ + __libc_maybe_call (_pthread_cleanup_push, (&_buffer, (fct), (arg)), 0) + +#define __libc_cleanup_pop(execute) \ + __libc_maybe_call (_pthread_cleanup_pop, (&_buffer, execute), 0); \ + } + +/* Create thread-specific key. */ +#define __libc_key_create(KEY, DESTRUCTOR) \ + (__libc_maybe_call (__pthread_key_create, (KEY, DESTRUCTOR), 1)) + +/* Get thread-specific data. */ +#define __libc_getspecific(KEY) \ + (__libc_maybe_call (__pthread_getspecific, (KEY), NULL)) + +/* Set thread-specific data. */ +#define __libc_setspecific(KEY, VALUE) \ + (__libc_maybe_call (__pthread_setspecific, (KEY, VALUE), 0)) + + +/* Register handlers to execute before and after `fork'. */ +#define __libc_atfork(PREPARE, PARENT, CHILD) \ + (__libc_maybe_call (__pthread_atfork, (PREPARE, PARENT, CHILD), 0)) + +/* Functions that are used by this file and are internal to the GNU C + library. */ + +extern int __pthread_mutex_init (pthread_mutex_t *__mutex, + __const pthread_mutexattr_t *__mutex_attr); + +extern int __pthread_mutex_destroy (pthread_mutex_t *__mutex); + +extern int __pthread_mutex_trylock (pthread_mutex_t *__mutex); + +extern int __pthread_mutex_lock (pthread_mutex_t *__mutex); + +extern int __pthread_mutex_unlock (pthread_mutex_t *__mutex); + +extern int __pthread_mutexattr_init (pthread_mutexattr_t *__attr); + +extern int __pthread_mutexattr_destroy (pthread_mutexattr_t *__attr); + +extern int __pthread_mutexattr_settype (pthread_mutexattr_t *__attr, + int __kind); + +#ifdef __USE_UNIX98 +extern int __pthread_rwlock_init (pthread_rwlock_t *__rwlock, + __const pthread_rwlockattr_t *__attr); + +extern int __pthread_rwlock_destroy (pthread_rwlock_t *__rwlock); + +extern int __pthread_rwlock_rdlock (pthread_rwlock_t *__rwlock); + +extern int __pthread_rwlock_tryrdlock (pthread_rwlock_t *__rwlock); + +extern int __pthread_rwlock_wrlock (pthread_rwlock_t *__rwlock); + +extern int __pthread_rwlock_trywrlock (pthread_rwlock_t *__rwlock); + +extern int __pthread_rwlock_unlock (pthread_rwlock_t *__rwlock); +#endif + +extern int __pthread_key_create (pthread_key_t *__key, + void (*__destr_function) (void *)); + +extern int __pthread_setspecific (pthread_key_t __key, + __const void *__pointer); + +extern void *__pthread_getspecific (pthread_key_t __key); + +extern int __pthread_once (pthread_once_t *__once_control, + void (*__init_routine) (void)); + +extern int __pthread_atfork (void (*__prepare) (void), + void (*__parent) (void), + void (*__child) (void)); + + + +/* Make the pthread functions weak so that we can elide them from + single-threaded processes. */ +#ifndef __NO_WEAK_PTHREAD_ALIASES +# ifdef weak_extern +# define BP_SYM(sym) sym +weak_extern (BP_SYM (__pthread_mutex_init)) +weak_extern (BP_SYM (__pthread_mutex_destroy)) +weak_extern (BP_SYM (__pthread_mutex_lock)) +weak_extern (BP_SYM (__pthread_mutex_trylock)) +weak_extern (BP_SYM (__pthread_mutex_unlock)) +weak_extern (BP_SYM (__pthread_mutexattr_init)) +weak_extern (BP_SYM (__pthread_mutexattr_destroy)) +weak_extern (BP_SYM (__pthread_mutexattr_settype)) +weak_extern (BP_SYM (__pthread_rwlock_init)) +weak_extern (BP_SYM (__pthread_rwlock_destroy)) +weak_extern (BP_SYM (__pthread_rwlock_rdlock)) +weak_extern (BP_SYM (__pthread_rwlock_tryrdlock)) +weak_extern (BP_SYM (__pthread_rwlock_wrlock)) +weak_extern (BP_SYM (__pthread_rwlock_trywrlock)) +weak_extern (BP_SYM (__pthread_rwlock_unlock)) +weak_extern (BP_SYM (__pthread_key_create)) +weak_extern (BP_SYM (__pthread_setspecific)) +weak_extern (BP_SYM (__pthread_getspecific)) +weak_extern (BP_SYM (__pthread_once)) +weak_extern (__pthread_initialize) +weak_extern (__pthread_atfork) +weak_extern (BP_SYM (_pthread_cleanup_push)) +weak_extern (BP_SYM (_pthread_cleanup_pop)) +weak_extern (BP_SYM (_pthread_cleanup_push_defer)) +weak_extern (BP_SYM (_pthread_cleanup_pop_restore)) +# else +# pragma weak __pthread_mutex_init +# pragma weak __pthread_mutex_destroy +# pragma weak __pthread_mutex_lock +# pragma weak __pthread_mutex_trylock +# pragma weak __pthread_mutex_unlock +# pragma weak __pthread_mutexattr_init +# pragma weak __pthread_mutexattr_destroy +# pragma weak __pthread_mutexattr_settype +# pragma weak __pthread_rwlock_destroy +# pragma weak __pthread_rwlock_rdlock +# pragma weak __pthread_rwlock_tryrdlock +# pragma weak __pthread_rwlock_wrlock +# pragma weak __pthread_rwlock_trywrlock +# pragma weak __pthread_rwlock_unlock +# pragma weak __pthread_key_create +# pragma weak __pthread_setspecific +# pragma weak __pthread_getspecific +# pragma weak __pthread_once +# pragma weak __pthread_initialize +# pragma weak __pthread_atfork +# pragma weak _pthread_cleanup_push_defer +# pragma weak _pthread_cleanup_pop_restore +# pragma weak _pthread_cleanup_push +# pragma weak _pthread_cleanup_pop +# endif +#endif + +/* We need portable names for some functions. E.g., when they are + used as argument to __libc_cleanup_region_start. */ +#define __libc_mutex_unlock __pthread_mutex_unlock + +#endif /* bits/libc-lock.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/bits/libc-tsd.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/bits/libc-tsd.h new file mode 100644 index 00000000..fa6eb4be --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/bits/libc-tsd.h @@ -0,0 +1,59 @@ +/* libc-internal interface for thread-specific data. LinuxThreads version. + Copyright (C) 1997-2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _BITS_LIBC_TSD_H +#define _BITS_LIBC_TSD_H 1 + +#include +#include + +#if USE_TLS && HAVE___THREAD + +/* When __thread works, the generic definition is what we want. */ +# include + +#else + +# include + +# ifndef SHARED +extern void ** __pthread_internal_tsd_address (int); +extern void *__pthread_internal_tsd_get (int); +extern int __pthread_internal_tsd_set (int, const void *); + +weak_extern (__pthread_internal_tsd_address) +weak_extern (__pthread_internal_tsd_get) +weak_extern (__pthread_internal_tsd_set) +# endif + +#define __libc_tsd_define(CLASS, KEY) CLASS void *__libc_tsd_##KEY##_data; +#define __libc_tsd_address(KEY) \ + __libc_maybe_call2 (pthread_internal_tsd_address, \ + (_LIBC_TSD_KEY_##KEY), &__libc_tsd_##KEY##_data) +#define __libc_tsd_get(KEY) \ + __libc_maybe_call2 (pthread_internal_tsd_get, \ + (_LIBC_TSD_KEY_##KEY), __libc_tsd_##KEY##_data) +#define __libc_tsd_set(KEY, VALUE) \ + __libc_maybe_call2 (pthread_internal_tsd_set, \ + (_LIBC_TSD_KEY_##KEY, (VALUE)), \ + (__libc_tsd_##KEY##_data = (VALUE), 0)) + +#endif + +#endif /* bits/libc-tsd.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/bits/pthreadtypes.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/bits/pthreadtypes.h new file mode 100644 index 00000000..4ea6d8ac --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/bits/pthreadtypes.h @@ -0,0 +1,152 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +#if !defined _BITS_TYPES_H && !defined _PTHREAD_H +# error "Never include directly; use instead." +#endif + +#ifndef _BITS_PTHREADTYPES_H +#define _BITS_PTHREADTYPES_H 1 + +#define __need_schedparam +#include + +/* Fast locks (not abstract because mutexes and conditions aren't abstract). */ +struct _pthread_fastlock +{ + long int __status; /* "Free" or "taken" or head of waiting list */ + int __spinlock; /* Used by compare_and_swap emulation. Also, + adaptive SMP lock stores spin count here. */ +}; + +#ifndef _PTHREAD_DESCR_DEFINED +/* Thread descriptors */ +typedef struct _pthread_descr_struct *_pthread_descr; +# define _PTHREAD_DESCR_DEFINED +#endif + + +/* Attributes for threads. */ +typedef struct __pthread_attr_s +{ + int __detachstate; + int __schedpolicy; + struct __sched_param __schedparam; + int __inheritsched; + int __scope; + size_t __guardsize; + int __stackaddr_set; + void *__stackaddr; + size_t __stacksize; +} pthread_attr_t; + + +/* Conditions (not abstract because of PTHREAD_COND_INITIALIZER */ + +#ifdef __GLIBC_HAVE_LONG_LONG +__extension__ typedef long long __pthread_cond_align_t; +#else +typedef long __pthread_cond_align_t; +#endif + +typedef struct +{ + struct _pthread_fastlock __c_lock; /* Protect against concurrent access */ + _pthread_descr __c_waiting; /* Threads waiting on this condition */ + char __padding[48 - sizeof (struct _pthread_fastlock) + - sizeof (_pthread_descr) - sizeof (__pthread_cond_align_t)]; + __pthread_cond_align_t __align; +} pthread_cond_t; + + +/* Attribute for conditionally variables. */ +typedef struct +{ + int __dummy; +} pthread_condattr_t; + +/* Keys for thread-specific data */ +typedef unsigned int pthread_key_t; + + +/* Mutexes (not abstract because of PTHREAD_MUTEX_INITIALIZER). */ +/* (The layout is unnatural to maintain binary compatibility + with earlier releases of LinuxThreads.) */ +typedef struct +{ + int __m_reserved; /* Reserved for future use */ + int __m_count; /* Depth of recursive locking */ + _pthread_descr __m_owner; /* Owner thread (if recursive or errcheck) */ + int __m_kind; /* Mutex kind: fast, recursive or errcheck */ + struct _pthread_fastlock __m_lock; /* Underlying fast lock */ +} pthread_mutex_t; + + +/* Attribute for mutex. */ +typedef struct +{ + int __mutexkind; +} pthread_mutexattr_t; + + +/* Once-only execution */ +typedef int pthread_once_t; + + +#if defined __USE_UNIX98 || defined __USE_XOPEN2K +/* Read-write locks. */ +typedef struct _pthread_rwlock_t +{ + struct _pthread_fastlock __rw_lock; /* Lock to guarantee mutual exclusion */ + int __rw_readers; /* Number of readers */ + _pthread_descr __rw_writer; /* Identity of writer, or NULL if none */ + _pthread_descr __rw_read_waiting; /* Threads waiting for reading */ + _pthread_descr __rw_write_waiting; /* Threads waiting for writing */ + int __rw_kind; /* Reader/Writer preference selection */ + int __rw_pshared; /* Shared between processes or not */ +} pthread_rwlock_t; + + +/* Attribute for read-write locks. */ +typedef struct +{ + int __lockkind; + int __pshared; +} pthread_rwlockattr_t; +#endif + +#ifdef __USE_XOPEN2K +/* POSIX spinlock data type. */ +typedef __volatile__ int pthread_spinlock_t; + +/* POSIX barrier. */ +typedef struct { + struct _pthread_fastlock __ba_lock; /* Lock to guarantee mutual exclusion */ + int __ba_required; /* Threads needed for completion */ + int __ba_present; /* Threads waiting */ + _pthread_descr __ba_waiting; /* Queue of waiting threads */ +} pthread_barrier_t; + +/* barrier attribute */ +typedef struct { + int __pshared; +} pthread_barrierattr_t; + +#endif + + +/* Thread identifiers */ +typedef unsigned long int pthread_t; + +#endif /* bits/pthreadtypes.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/bits/typesizes.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/bits/typesizes.h new file mode 100644 index 00000000..45264ac9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/bits/typesizes.h @@ -0,0 +1,66 @@ +/* bits/typesizes.h -- underlying types for *_t. Generic version. + Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _BITS_TYPES_H +# error "Never include directly; use instead." +#endif + +#ifndef _BITS_TYPESIZES_H +#define _BITS_TYPESIZES_H 1 + +/* See for the meaning of these macros. This file exists so + that need not vary across different GNU platforms. */ + +#define __DEV_T_TYPE __UQUAD_TYPE +#define __UID_T_TYPE __U32_TYPE +#define __GID_T_TYPE __U32_TYPE +#define __INO_T_TYPE __ULONGWORD_TYPE +#define __INO64_T_TYPE __UQUAD_TYPE +#define __MODE_T_TYPE __U32_TYPE +#define __NLINK_T_TYPE __UWORD_TYPE +#define __OFF_T_TYPE __SLONGWORD_TYPE +#define __OFF64_T_TYPE __SQUAD_TYPE +#define __PID_T_TYPE __S32_TYPE +#define __RLIM_T_TYPE __ULONGWORD_TYPE +#define __RLIM64_T_TYPE __UQUAD_TYPE +#define __BLKCNT_T_TYPE __SLONGWORD_TYPE +#define __BLKCNT64_T_TYPE __SQUAD_TYPE +#define __FSBLKCNT_T_TYPE __ULONGWORD_TYPE +#define __FSBLKCNT64_T_TYPE __UQUAD_TYPE +#define __FSFILCNT_T_TYPE __ULONGWORD_TYPE +#define __FSFILCNT64_T_TYPE __UQUAD_TYPE +#define __ID_T_TYPE __U32_TYPE +#define __CLOCK_T_TYPE __SLONGWORD_TYPE +#define __TIME_T_TYPE __SLONGWORD_TYPE +#define __USECONDS_T_TYPE __U32_TYPE +#define __SUSECONDS_T_TYPE __SLONGWORD_TYPE +#define __DADDR_T_TYPE __S32_TYPE +#define __SWBLK_T_TYPE __SLONGWORD_TYPE +#define __KEY_T_TYPE __S32_TYPE +#define __CLOCKID_T_TYPE __S32_TYPE +#define __TIMER_T_TYPE __S32_TYPE +#define __BLKSIZE_T_TYPE __SLONGWORD_TYPE +#define __FSID_T_TYPE struct { int __val[2]; } +#define __SSIZE_T_TYPE __SWORD_TYPE + +/* Number of descriptors that can fit in an `fd_set'. */ +#define __FD_SETSIZE 1024 + + +#endif /* bits/typesizes.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/errno-loc.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/errno-loc.c new file mode 100644 index 00000000..c3b3087e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/errno-loc.c @@ -0,0 +1,45 @@ +/* MT support function to get address of `errno' variable, linuxthreads + version. + Copyright (C) 1996, 1998, 2002, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +#if ! USE___THREAD && !RTLD_PRIVATE_ERRNO +#undef errno +extern int errno; +#endif + +int * +#if ! USE___THREAD +weak_const_function +#endif +__errno_location (void) +{ +#if ! USE___THREAD && !defined NOT_IN_libc + if (! SINGLE_THREAD_P) + { + pthread_descr self = thread_self(); + return LIBC_THREAD_GETMEM (self, p_errnop); + } +#endif + return &errno; +} +libc_hidden_def (__errno_location) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/flockfile.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/flockfile.c new file mode 100644 index 00000000..918cb84f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/flockfile.c @@ -0,0 +1,33 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + + +void +__flockfile (stream) + FILE *stream; +{ + _IO_lock_lock (*stream->_lock); +} +strong_alias (__flockfile, _IO_flockfile) +weak_alias (__flockfile, flockfile) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/ftrylockfile.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/ftrylockfile.c new file mode 100644 index 00000000..21c1ea01 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/ftrylockfile.c @@ -0,0 +1,33 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + + +int +__ftrylockfile (stream) + FILE *stream; +{ + return _IO_lock_trylock (*stream->_lock); +} +strong_alias (__ftrylockfile, _IO_ftrylockfile) +weak_alias (__ftrylockfile, ftrylockfile) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/funlockfile.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/funlockfile.c new file mode 100644 index 00000000..f941fc98 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/funlockfile.c @@ -0,0 +1,33 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + + +void +__funlockfile (stream) + FILE *stream; +{ + _IO_lock_unlock (*stream->_lock); +} +strong_alias (__funlockfile, _IO_funlockfile) +weak_alias (__funlockfile, funlockfile) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/getcpuclockid.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/getcpuclockid.c new file mode 100644 index 00000000..cefbd554 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/getcpuclockid.c @@ -0,0 +1,117 @@ +/* pthread_getcpuclockid -- Get POSIX clockid_t for a pthread_t. Linux version + Copyright (C) 2000, 2001, 2004, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include +#include +#include +#include +#include + + +#if !(__ASSUME_POSIX_CPU_TIMERS > 0) +int __libc_missing_posix_cpu_timers attribute_hidden; +#endif +#if !(__ASSUME_POSIX_TIMERS > 0) +int __libc_missing_posix_timers attribute_hidden; +#endif + +int +pthread_getcpuclockid (pthread_t thread_id, clockid_t *clock_id) +{ +#ifdef __NR_clock_getres + pthread_handle handle = thread_handle(thread_id); + int pid; + + __pthread_lock (&handle->h_lock, NULL); + if (nonexisting_handle (handle, thread_id)) + { + __pthread_unlock (&handle->h_lock); + return ESRCH; + } + pid = handle->h_descr->p_pid; + __pthread_unlock (&handle->h_lock); + + /* The clockid_t value is a simple computation from the PID. + But we do a clock_getres call to validate it if we aren't + yet sure we have the kernel support. */ + + const clockid_t pidclock = MAKE_PROCESS_CPUCLOCK (pid, CPUCLOCK_SCHED); + +# if !(__ASSUME_POSIX_CPU_TIMERS > 0) +# if !(__ASSUME_POSIX_TIMERS > 0) + if (__libc_missing_posix_timers && !__libc_missing_posix_cpu_timers) + __libc_missing_posix_cpu_timers = 1; +# endif + if (!__libc_missing_posix_cpu_timers) + { + INTERNAL_SYSCALL_DECL (err); + int r = INTERNAL_SYSCALL (clock_getres, err, 2, pidclock, NULL); + if (!INTERNAL_SYSCALL_ERROR_P (r, err)) +# endif + { + *clock_id = pidclock; + return 0; + } + +# if !(__ASSUME_POSIX_CPU_TIMERS > 0) +# if !(__ASSUME_POSIX_TIMERS > 0) + if (INTERNAL_SYSCALL_ERRNO (r, err) == ENOSYS) + { + /* The kernel doesn't support these calls at all. */ + __libc_missing_posix_timers = 1; + __libc_missing_posix_cpu_timers = 1; + } + else +# endif + if (INTERNAL_SYSCALL_ERRNO (r, err) == EINVAL) + { + /* The kernel doesn't support these clocks at all. */ + __libc_missing_posix_cpu_timers = 1; + } + else + return INTERNAL_SYSCALL_ERRNO (r, err); + } +# endif +#endif + +#ifdef CLOCK_THREAD_CPUTIME_ID + /* We need to store the thread ID in the CLOCKID variable together + with a number identifying the clock. We reserve the low 3 bits + for the clock ID and the rest for the thread ID. This is + problematic if the thread ID is too large. But 29 bits should be + fine. + + If some day more clock IDs are needed the ID part can be + enlarged. The IDs are entirely internal. */ + if (2 * PTHREAD_THREADS_MAX + >= 1 << (8 * sizeof (*clock_id) - CLOCK_IDFIELD_SIZE)) + return ERANGE; + + /* Store the number. */ + *clock_id = CLOCK_THREAD_CPUTIME_ID | (thread_id << CLOCK_IDFIELD_SIZE); + + return 0; +#else + /* We don't have a timer for that. */ + return ENOENT; +#endif +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/herrno-loc.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/herrno-loc.c new file mode 100644 index 00000000..fbc55761 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/herrno-loc.c @@ -0,0 +1,43 @@ +/* Copyright (C) 1996, 97, 98, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + +#if ! USE___THREAD +# undef h_errno +extern int h_errno; +#endif + +/* When threaded, h_errno may be a per-thread variable. */ +int * +weak_const_function +__h_errno_location (void) +{ +#if ! USE___THREAD + if (! SINGLE_THREAD_P) + { + pthread_descr self = thread_self(); + return LIBC_THREAD_GETMEM (self, p_h_errnop); + } +#endif + return &h_errno; +} +libc_hidden_def (__h_errno_location) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/list.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/list.h new file mode 100644 index 00000000..75decfbb --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/list.h @@ -0,0 +1,114 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _LIST_H +#define _LIST_H 1 + +/* The definitions of this file are adopted from those which can be + found in the Linux kernel headers to enable people familiar with + the latter find their way in these sources as well. */ + + +/* Basic type for the double-link list. */ +typedef struct list_head +{ + struct list_head *next; + struct list_head *prev; +} list_t; + + +/* Define a variable with the head and tail of the list. */ +#define LIST_HEAD(name) \ + list_t name = { &(name), &(name) } + +/* Initialize a new list head. */ +#define INIT_LIST_HEAD(ptr) \ + (ptr)->next = (ptr)->prev = (ptr) + + +/* Add new element at the head of the list. */ +static __inline__ void +list_add (list_t *newp, list_t *head) +{ + head->next->prev = newp; + newp->next = head->next; + newp->prev = head; + head->next = newp; +} + + +/* Add new element at the tail of the list. */ +static __inline__ void +list_add_tail (list_t *newp, list_t *head) +{ + head->prev->next = newp; + newp->next = head; + newp->prev = head->prev; + head->prev = newp; +} + + +/* Remove element from list. */ +static __inline__ void +list_del (list_t *elem) +{ + elem->next->prev = elem->prev; + elem->prev->next = elem->next; +} + + +/* Join two lists. */ +static __inline__ void +list_splice (list_t *add, list_t *head) +{ + /* Do nothing if the list which gets added is empty. */ + if (add != add->next) + { + add->next->prev = head; + add->prev->next = head->next; + head->next->prev = add->prev; + head->next = add->next; + } +} + + +/* Get typed element from list at a given position. */ +#define list_entry(ptr, type, member) \ + ((type *) ((char *) (ptr) - (unsigned long) (&((type *) 0)->member))) + + + +/* Iterate forward over the elements of the list. */ +#define list_for_each(pos, head) \ + for (pos = (head)->next; pos != (head); pos = pos->next) + + +/* Iterate forward over the elements of the list. */ +#define list_for_each_prev(pos, head) \ + for (pos = (head)->prev; pos != (head); pos = pos->prev) + + +/* Iterate backwards over the elements list. The list elements can be + removed from the list while doing this. */ +#define list_for_each_prev_safe(pos, p, head) \ + for (pos = (head)->prev, p = pos->prev; \ + pos != (head); \ + pos = p, p = pos->prev) + +#endif /* list.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/malloc-machine.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/malloc-machine.h new file mode 100644 index 00000000..5191f8c7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/malloc-machine.h @@ -0,0 +1,67 @@ +/* Basic platform-independent macro definitions for mutexes, + thread-specific data and parameters for malloc. + Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _MALLOC_MACHINE_H +#define _MALLOC_MACHINE_H + +#undef thread_atfork_static + +#include +#include + +__libc_lock_define (typedef, mutex_t) + +#define mutex_init(m) \ + __libc_maybe_call2 (pthread_mutex_init, (m, NULL), (*(int *)(m) = 0)) +#define mutex_lock(m) \ + __libc_maybe_call2 (pthread_mutex_lock, (m), ((*(int *)(m) = 1), 0)) +#define mutex_trylock(m) \ + __libc_maybe_call2 (pthread_mutex_trylock, (m), \ + (*(int *)(m) ? 1 : ((*(int *)(m) = 1), 0))) +#define mutex_unlock(m) \ + __libc_maybe_call2 (pthread_mutex_unlock, (m), (*(int *)(m) = 0)) + +/* This is defined by newer gcc version unique for each module. */ +extern void *__dso_handle __attribute__ ((__weak__)); + +#include + +#ifdef SHARED +# define thread_atfork(prepare, parent, child) \ + __register_atfork (prepare, parent, child, __dso_handle) +#else +# define thread_atfork(prepare, parent, child) \ + __register_atfork (prepare, parent, child, \ + &__dso_handle == NULL ? NULL : __dso_handle) +#endif + +/* thread specific data for glibc */ + +#include + +typedef int tsd_key_t[1]; /* no key data structure, libc magic does it */ +__libc_tsd_define (static, MALLOC) /* declaration/common definition */ +#define tsd_key_create(key, destr) ((void) (key)) +#define tsd_setspecific(key, data) __libc_tsd_set (MALLOC, (data)) +#define tsd_getspecific(key, vptr) ((vptr) = __libc_tsd_get (MALLOC)) + +#include + +#endif /* !defined(_MALLOC_MACHINE_H) */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/not-cancel.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/not-cancel.h new file mode 100644 index 00000000..80d33be2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/not-cancel.h @@ -0,0 +1,105 @@ +/* Uncancelable versions of cancelable interfaces. Linux version. + Copyright (C) 2003, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +/* Uncancelable open. */ +#define open_not_cancel(name, flags, mode) \ + INLINE_SYSCALL (open, 3, (const char *) (name), (flags), (mode)) +#define open_not_cancel_2(name, flags) \ + INLINE_SYSCALL (open, 2, (const char *) (name), (flags)) + +/* Uncancelable openat. */ +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt +extern int __openat_nocancel (int fd, const char *fname, int oflag, + mode_t mode) attribute_hidden; +extern int __openat64_nocancel (int fd, const char *fname, int oflag, + mode_t mode) attribute_hidden; +#else +# define __openat_nocancel(fd, fname, oflag, mode) \ + openat (fd, fname, oflag, mode) +# define __openat64_nocancel(fd, fname, oflag, mode) \ + openat64 (fd, fname, oflag, mode) +#endif + +#define openat_not_cancel(fd, fname, oflag, mode) \ + __openat_nocancel (fd, fname, oflag, mode) +#define openat_not_cancel_3(fd, fname, oflag) \ + __openat_nocancel (fd, fname, oflag, 0) +#define openat64_not_cancel(fd, fname, oflag, mode) \ + __openat64_nocancel (fd, fname, oflag, mode) +#define openat64_not_cancel_3(fd, fname, oflag) \ + __openat64_nocancel (fd, fname, oflag, 0) + +/* Uncancelable close. */ +#define close_not_cancel(fd) \ + INLINE_SYSCALL (close, 1, fd) +#define close_not_cancel_no_status(fd) \ + (void) ({ INTERNAL_SYSCALL_DECL (err); \ + INTERNAL_SYSCALL (close, err, 1, (fd)); }) + +/* Uncancelable read. */ +#define read_not_cancel(fd, buf, n) \ + INLINE_SYSCALL (read, 3, (fd), (buf), (n)) + +/* Uncancelable write. */ +#define write_not_cancel(fd, buf, n) \ + INLINE_SYSCALL (write, 3, (fd), (buf), (n)) + +/* Uncancelable writev. */ +#define writev_not_cancel_no_status(fd, iov, n) \ + (void) ({ INTERNAL_SYSCALL_DECL (err); \ + INTERNAL_SYSCALL (writev, err, 3, (fd), (iov), (n)); }) + +/* Uncancelable fcntl. */ +#define fcntl_not_cancel(fd, cmd, val) \ + __fcntl_nocancel (fd, cmd, val) + +/* Uncancelable waitpid. */ +#ifdef __NR_waitpid +# define waitpid_not_cancel(pid, stat_loc, options) \ + INLINE_SYSCALL (waitpid, 3, pid, stat_loc, options) +#else +# define waitpid_not_cancel(pid, stat_loc, options) \ + INLINE_SYSCALL (wait4, 4, pid, stat_loc, options, NULL) +#endif + +/* Uncancelable pause. */ +#ifdef __NR_pause +# define pause_not_cancel() \ + INLINE_SYSCALL (pause, 0) +#else +# define pause_not_cancel() \ + __pause_nocancel () +#endif + +/* Uncancelable nanosleep. */ +#ifdef __NR_nanosleep +# define nanosleep_not_cancel(requested_time, remaining) \ + INLINE_SYSCALL (nanosleep, 2, requested_time, remaining) +#else +# define nanosleep_not_cancel(requested_time, remaining) \ + __nanosleep_nocancel (requested_time, remaining) +#endif + +/* Uncancelable sigsuspend. */ +#define sigsuspend_not_cancel(set) \ + __sigsuspend_nocancel (set) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/posix-timer.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/posix-timer.h new file mode 100644 index 00000000..5486f7d6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/posix-timer.h @@ -0,0 +1,204 @@ +/* Definitions for POSIX timer implementation on top of LinuxThreads. + Copyright (C) 2000, 2002, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Kaz Kylheku . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +/* Double linked list. */ +struct list_links +{ + struct list_links *next; + struct list_links *prev; +}; + + +/* Forward declaration. */ +struct timer_node; + + +/* Definitions for an internal thread of the POSIX timer implementation. */ +struct thread_node +{ + struct list_links links; + pthread_attr_t attr; + pthread_t id; + unsigned int exists; + struct list_links timer_queue; + pthread_cond_t cond; + struct timer_node *current_timer; + pthread_t captured; + clockid_t clock_id; +}; + + +/* Internal representation of a timer. */ +struct timer_node +{ + struct list_links links; + struct sigevent event; + clockid_t clock; + struct itimerspec value; + struct timespec expirytime; + pthread_attr_t attr; + unsigned int abstime; + unsigned int armed; + enum { + TIMER_FREE, TIMER_INUSE, TIMER_DELETED + } inuse; + struct thread_node *thread; + pid_t creator_pid; + int refcount; + int overrun_count; +}; + + +/* Static array with the structures for all the timers. */ +extern struct timer_node __timer_array[TIMER_MAX]; + +/* Global lock to protect operation on the lists. */ +extern pthread_mutex_t __timer_mutex; + +/* Variable to protext initialization. */ +extern pthread_once_t __timer_init_once_control; + +/* Nonzero if initialization of timer implementation failed. */ +extern int __timer_init_failed; + +/* Nodes for the threads used to deliver signals. */ +/* A distinct thread is used for each clock type. */ + +extern struct thread_node __timer_signal_thread_rclk; + + +/* Return pointer to timer structure corresponding to ID. */ +static __inline__ struct timer_node * +timer_id2ptr (timer_t timerid) +{ + if (timerid >= 0 && timerid < TIMER_MAX) + return &__timer_array[timerid]; + + return NULL; +} + +/* Return ID of TIMER. */ +static __inline__ int +timer_ptr2id (struct timer_node *timer) +{ + return timer - __timer_array; +} + +/* Check whether timer is valid; global mutex must be held. */ +static __inline__ int +timer_valid (struct timer_node *timer) +{ + return timer && timer->inuse == TIMER_INUSE; +} + +/* Timer refcount functions; need global mutex. */ +extern void __timer_dealloc (struct timer_node *timer); + +static __inline__ void +timer_addref (struct timer_node *timer) +{ + timer->refcount++; +} + +static __inline__ void +timer_delref (struct timer_node *timer) +{ + if (--timer->refcount == 0) + __timer_dealloc (timer); +} + +/* Timespec helper routines. */ +static __inline__ int +timespec_compare (const struct timespec *left, const struct timespec *right) +{ + if (left->tv_sec < right->tv_sec) + return -1; + if (left->tv_sec > right->tv_sec) + return 1; + + if (left->tv_nsec < right->tv_nsec) + return -1; + if (left->tv_nsec > right->tv_nsec) + return 1; + + return 0; +} + +static __inline__ void +timespec_add (struct timespec *sum, const struct timespec *left, + const struct timespec *right) +{ + sum->tv_sec = left->tv_sec + right->tv_sec; + sum->tv_nsec = left->tv_nsec + right->tv_nsec; + + if (sum->tv_nsec >= 1000000000) + { + ++sum->tv_sec; + sum->tv_nsec -= 1000000000; + } +} + +static __inline__ void +timespec_sub (struct timespec *diff, const struct timespec *left, + const struct timespec *right) +{ + diff->tv_sec = left->tv_sec - right->tv_sec; + diff->tv_nsec = left->tv_nsec - right->tv_nsec; + + if (diff->tv_nsec < 0) + { + --diff->tv_sec; + diff->tv_nsec += 1000000000; + } +} + + +/* We need one of the list functions in the other modules. */ +static __inline__ void +list_unlink_ip (struct list_links *list) +{ + struct list_links *lnext = list->next, *lprev = list->prev; + + lnext->prev = lprev; + lprev->next = lnext; + + /* The suffix ip means idempotent; list_unlink_ip can be called + * two or more times on the same node. + */ + + list->next = list; + list->prev = list; +} + + +/* Functions in the helper file. */ +extern void __timer_mutex_cancel_handler (void *arg); +extern void __timer_init_once (void); +extern struct timer_node *__timer_alloc (void); +extern int __timer_thread_start (struct thread_node *thread); +extern struct thread_node *__timer_thread_find_matching (const pthread_attr_t *desired_attr, clockid_t); +extern struct thread_node *__timer_thread_alloc (const pthread_attr_t *desired_attr, clockid_t); +extern void __timer_thread_dealloc (struct thread_node *thread); +extern int __timer_thread_queue_timer (struct thread_node *thread, + struct timer_node *insert); +extern void __timer_thread_wakeup (struct thread_node *thread); diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/pt-initfini.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/pt-initfini.c new file mode 100644 index 00000000..15aeb216 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/pt-initfini.c @@ -0,0 +1,124 @@ +/* Special .init and .fini section support. Linuxthread version. + Copyright (C) 1995, 1996, 1997, 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it + and/or modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file with other + programs, and to distribute those programs without any restriction + coming from the use of this file. (The Lesser General Public + License restrictions do apply in other respects; for example, they + cover modification of the file, and distribution when not linked + into another program.) + + The GNU C Library is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* This file is compiled into assembly code which is then munged by a sed + script into two files: crti.s and crtn.s. + + * crti.s puts a function prologue at the beginning of the + .init and .fini sections and defines global symbols for + those addresses, so they can be called as functions. + + * crtn.s puts the corresponding function epilogues + in the .init and .fini sections. */ + +#include + +/* We use embedded asm for .section unconditionally, as this makes it + easier to insert the necessary directives into crtn.S. */ +#define SECTION(x) __asm__ (".section " x ) + +/* Embed an #include to pull in the alignment and .end directives. */ +__asm__ ("\n#include \"defs.h\""); + +/* The initial common code ends here. */ +__asm__ ("\n/*@HEADER_ENDS*/"); + +/* To determine whether we need .end and .align: */ +__asm__ ("\n/*@TESTS_BEGIN*/"); +extern void dummy (void (*foo) (void)); +void +dummy (void (*foo) (void)) +{ + if (foo) + (*foo) (); +} +__asm__ ("\n/*@TESTS_END*/"); + +/* The beginning of _init: */ +__asm__ ("\n/*@_init_PROLOG_BEGINS*/"); + +static void +call_initialize_minimal (void) +{ + extern void __pthread_initialize_minimal (void); + + __pthread_initialize_minimal (); +} + +SECTION (".init"); +extern void _init (void); +void +_init (void) +{ + /* The very first thing we must do is to set up the registers. */ + call_initialize_minimal (); + + __asm__ ("ALIGN"); + __asm__("END_INIT"); + /* Now the epilog. */ + __asm__ ("\n/*@_init_PROLOG_ENDS*/"); + __asm__ ("\n/*@_init_EPILOG_BEGINS*/"); + SECTION(".init"); +} +__asm__ ("END_INIT"); + +/* End of the _init epilog, beginning of the _fini prolog. */ +__asm__ ("\n/*@_init_EPILOG_ENDS*/"); +__asm__ ("\n/*@_fini_PROLOG_BEGINS*/"); + +SECTION (".fini"); +extern void _fini (void); +void +_fini (void) +{ + + /* End of the _fini prolog. */ + __asm__ ("ALIGN"); + __asm__ ("END_FINI"); + __asm__ ("\n/*@_fini_PROLOG_ENDS*/"); + + { + /* Let GCC know that _fini is not a leaf function by having a dummy + function call here. We arrange for this call to be omitted from + either crt file. */ + extern void i_am_not_a_leaf (void); + i_am_not_a_leaf (); + } + + /* Beginning of the _fini epilog. */ + __asm__ ("\n/*@_fini_EPILOG_BEGINS*/"); + SECTION (".fini"); +} +__asm__ ("END_FINI"); + +/* End of the _fini epilog. Any further generated assembly (e.g. .ident) + is shared between both crt files. */ +__asm__ ("\n/*@_fini_EPILOG_ENDS*/"); +__asm__ ("\n/*@TRAILER_BEGINS*/"); + +/* End of file. */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/pthread-functions.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/pthread-functions.h new file mode 100644 index 00000000..258e1fc2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/pthread-functions.h @@ -0,0 +1,98 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _PTHREAD_FUNCTIONS_H +#define _PTHREAD_FUNCTIONS_H 1 + +#include +#include +#include + +struct fork_block; + +/* Data type shared with libc. The libc uses it to pass on calls to + the thread functions. Wine pokes directly into this structure, + so if possible avoid breaking it and append new hooks to the end. */ +struct pthread_functions +{ + pid_t (*ptr_pthread_fork) (struct fork_block *); + int (*ptr_pthread_attr_destroy) (pthread_attr_t *); + int (*ptr_pthread_attr_init) (pthread_attr_t *); + int (*ptr_pthread_attr_getdetachstate) (const pthread_attr_t *, int *); + int (*ptr_pthread_attr_setdetachstate) (pthread_attr_t *, int); + int (*ptr_pthread_attr_getinheritsched) (const pthread_attr_t *, int *); + int (*ptr_pthread_attr_setinheritsched) (pthread_attr_t *, int); + int (*ptr_pthread_attr_getschedparam) (const pthread_attr_t *, + struct sched_param *); + int (*ptr_pthread_attr_setschedparam) (pthread_attr_t *, + const struct sched_param *); + int (*ptr_pthread_attr_getschedpolicy) (const pthread_attr_t *, int *); + int (*ptr_pthread_attr_setschedpolicy) (pthread_attr_t *, int); + int (*ptr_pthread_attr_getscope) (const pthread_attr_t *, int *); + int (*ptr_pthread_attr_setscope) (pthread_attr_t *, int); + int (*ptr_pthread_condattr_destroy) (pthread_condattr_t *); + int (*ptr_pthread_condattr_init) (pthread_condattr_t *); + int (*ptr_pthread_cond_broadcast) (pthread_cond_t *); + int (*ptr_pthread_cond_destroy) (pthread_cond_t *); + int (*ptr_pthread_cond_init) (pthread_cond_t *, + const pthread_condattr_t *); + int (*ptr_pthread_cond_signal) (pthread_cond_t *); + int (*ptr_pthread_cond_wait) (pthread_cond_t *, pthread_mutex_t *); + int (*ptr_pthread_equal) (pthread_t, pthread_t); + void (*ptr___pthread_exit) (void *); + int (*ptr_pthread_getschedparam) (pthread_t, int *, struct sched_param *); + int (*ptr_pthread_setschedparam) (pthread_t, int, + const struct sched_param *); + int (*ptr_pthread_mutex_destroy) (pthread_mutex_t *); + int (*ptr_pthread_mutex_init) (pthread_mutex_t *, + const pthread_mutexattr_t *); + int (*ptr_pthread_mutex_lock) (pthread_mutex_t *); + int (*ptr_pthread_mutex_trylock) (pthread_mutex_t *); + int (*ptr_pthread_mutex_unlock) (pthread_mutex_t *); + pthread_t (*ptr_pthread_self) (void); + int (*ptr_pthread_setcancelstate) (int, int *); + int (*ptr_pthread_setcanceltype) (int, int *); + void (*ptr_pthread_do_exit) (void *retval, char *currentframe); + void (*ptr_pthread_cleanup_upto) (__jmp_buf target, + char *targetframe); + pthread_descr (*ptr_pthread_thread_self) (void); + int (*ptr_pthread_internal_tsd_set) (int key, const void *pointer); + void * (*ptr_pthread_internal_tsd_get) (int key); + void ** __attribute__ ((__const__)) + (*ptr_pthread_internal_tsd_address) (int key); + int (*ptr_pthread_sigaction) (int sig, const struct sigaction * act, + struct sigaction *oact); + int (*ptr_pthread_sigwait) (const sigset_t *set, int *sig); + int (*ptr_pthread_raise) (int sig); + int (*ptr_pthread_cond_timedwait) (pthread_cond_t *, pthread_mutex_t *, + const struct timespec *); + void (*ptr__pthread_cleanup_push) (struct _pthread_cleanup_buffer * buffer, + void (*routine)(void *), void * arg); + void (*ptr__pthread_cleanup_push_defer) (struct _pthread_cleanup_buffer * buffer, + void (*routine)(void *), void * arg); + void (*ptr__pthread_cleanup_pop) (struct _pthread_cleanup_buffer * buffer, + int execute); + void (*ptr__pthread_cleanup_pop_restore) (struct _pthread_cleanup_buffer * buffer, + int execute); +}; + +/* Variable in libc.so. */ +extern struct pthread_functions __libc_pthread_functions attribute_hidden; + +#endif /* pthread-functions.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/pthread.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/pthread.h new file mode 100644 index 00000000..947f911a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/pthread.h @@ -0,0 +1,680 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +#ifndef _PTHREAD_H +#define _PTHREAD_H 1 + +#include + +#include +#include + +#define __need_sigset_t +#include +#include +#include + + +__BEGIN_DECLS + +/* Initializers. */ + +#define PTHREAD_MUTEX_INITIALIZER \ + {0, 0, 0, PTHREAD_MUTEX_TIMED_NP, __LOCK_INITIALIZER} +#ifdef __USE_GNU +# define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP \ + {0, 0, 0, PTHREAD_MUTEX_RECURSIVE_NP, __LOCK_INITIALIZER} +# define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP \ + {0, 0, 0, PTHREAD_MUTEX_ERRORCHECK_NP, __LOCK_INITIALIZER} +# define PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP \ + {0, 0, 0, PTHREAD_MUTEX_ADAPTIVE_NP, __LOCK_INITIALIZER} +#endif + +#define PTHREAD_COND_INITIALIZER {__LOCK_INITIALIZER, 0, "", 0} + +#if defined __USE_UNIX98 || defined __USE_XOPEN2K +# define PTHREAD_RWLOCK_INITIALIZER \ + { __LOCK_INITIALIZER, 0, NULL, NULL, NULL, \ + PTHREAD_RWLOCK_DEFAULT_NP, PTHREAD_PROCESS_PRIVATE } +#endif +#ifdef __USE_GNU +# define PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP \ + { __LOCK_INITIALIZER, 0, NULL, NULL, NULL, \ + PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP, PTHREAD_PROCESS_PRIVATE } +#endif + +/* Values for attributes. */ + +enum +{ + PTHREAD_CREATE_JOINABLE, +#define PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_JOINABLE + PTHREAD_CREATE_DETACHED +#define PTHREAD_CREATE_DETACHED PTHREAD_CREATE_DETACHED +}; + +enum +{ + PTHREAD_INHERIT_SCHED, +#define PTHREAD_INHERIT_SCHED PTHREAD_INHERIT_SCHED + PTHREAD_EXPLICIT_SCHED +#define PTHREAD_EXPLICIT_SCHED PTHREAD_EXPLICIT_SCHED +}; + +enum +{ + PTHREAD_SCOPE_SYSTEM, +#define PTHREAD_SCOPE_SYSTEM PTHREAD_SCOPE_SYSTEM + PTHREAD_SCOPE_PROCESS +#define PTHREAD_SCOPE_PROCESS PTHREAD_SCOPE_PROCESS +}; + +enum +{ + PTHREAD_MUTEX_TIMED_NP, + PTHREAD_MUTEX_RECURSIVE_NP, + PTHREAD_MUTEX_ERRORCHECK_NP, + PTHREAD_MUTEX_ADAPTIVE_NP +#ifdef __USE_UNIX98 + , + PTHREAD_MUTEX_NORMAL = PTHREAD_MUTEX_TIMED_NP, + PTHREAD_MUTEX_RECURSIVE = PTHREAD_MUTEX_RECURSIVE_NP, + PTHREAD_MUTEX_ERRORCHECK = PTHREAD_MUTEX_ERRORCHECK_NP, + PTHREAD_MUTEX_DEFAULT = PTHREAD_MUTEX_NORMAL +#endif +#ifdef __USE_GNU + /* For compatibility. */ + , PTHREAD_MUTEX_FAST_NP = PTHREAD_MUTEX_ADAPTIVE_NP +#endif +}; + +enum +{ + PTHREAD_PROCESS_PRIVATE, +#define PTHREAD_PROCESS_PRIVATE PTHREAD_PROCESS_PRIVATE + PTHREAD_PROCESS_SHARED +#define PTHREAD_PROCESS_SHARED PTHREAD_PROCESS_SHARED +}; + +#if defined __USE_UNIX98 || defined __USE_XOPEN2K +enum +{ + PTHREAD_RWLOCK_PREFER_READER_NP, + PTHREAD_RWLOCK_PREFER_WRITER_NP, + PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP, + PTHREAD_RWLOCK_DEFAULT_NP = PTHREAD_RWLOCK_PREFER_WRITER_NP +}; +#endif /* Unix98 */ + +#define PTHREAD_ONCE_INIT 0 + +/* Special constants */ + +#ifdef __USE_XOPEN2K +/* -1 is distinct from 0 and all errno constants */ +# define PTHREAD_BARRIER_SERIAL_THREAD -1 +#endif + +/* Cleanup buffers */ + +struct _pthread_cleanup_buffer +{ + void (*__routine) (void *); /* Function to call. */ + void *__arg; /* Its argument. */ + int __canceltype; /* Saved cancellation type. */ + struct _pthread_cleanup_buffer *__prev; /* Chaining of cleanup functions. */ +}; + +/* Cancellation */ + +enum +{ + PTHREAD_CANCEL_ENABLE, +#define PTHREAD_CANCEL_ENABLE PTHREAD_CANCEL_ENABLE + PTHREAD_CANCEL_DISABLE +#define PTHREAD_CANCEL_DISABLE PTHREAD_CANCEL_DISABLE +}; +enum +{ + PTHREAD_CANCEL_DEFERRED, +#define PTHREAD_CANCEL_DEFERRED PTHREAD_CANCEL_DEFERRED + PTHREAD_CANCEL_ASYNCHRONOUS +#define PTHREAD_CANCEL_ASYNCHRONOUS PTHREAD_CANCEL_ASYNCHRONOUS +}; +#define PTHREAD_CANCELED ((void *) -1) + + +/* Function for handling threads. */ + +/* Create a thread with given attributes ATTR (or default attributes + if ATTR is NULL), and call function START_ROUTINE with given + arguments ARG. */ +extern int pthread_create (pthread_t *__restrict __threadp, + __const pthread_attr_t *__restrict __attr, + void *(*__start_routine) (void *), + void *__restrict __arg) __THROW; + +/* Obtain the identifier of the current thread. */ +extern pthread_t pthread_self (void) __THROW; + +/* Compare two thread identifiers. */ +extern int pthread_equal (pthread_t __thread1, pthread_t __thread2) __THROW; + +/* Terminate calling thread. */ +extern void pthread_exit (void *__retval) __attribute__ ((__noreturn__)); + +/* Make calling thread wait for termination of the thread TH. The + exit status of the thread is stored in *THREAD_RETURN, if THREAD_RETURN + is not NULL. */ +extern int pthread_join (pthread_t __th, void **__thread_return); + +/* Indicate that the thread TH is never to be joined with PTHREAD_JOIN. + The resources of TH will therefore be freed immediately when it + terminates, instead of waiting for another thread to perform PTHREAD_JOIN + on it. */ +extern int pthread_detach (pthread_t __th) __THROW; + + +/* Functions for handling attributes. */ + +/* Initialize thread attribute *ATTR with default attributes + (detachstate is PTHREAD_JOINABLE, scheduling policy is SCHED_OTHER, + no user-provided stack). */ +extern int pthread_attr_init (pthread_attr_t *__attr) __THROW; + +/* Destroy thread attribute *ATTR. */ +extern int pthread_attr_destroy (pthread_attr_t *__attr) __THROW; + +/* Set the `detachstate' attribute in *ATTR according to DETACHSTATE. */ +extern int pthread_attr_setdetachstate (pthread_attr_t *__attr, + int __detachstate) __THROW; + +/* Return in *DETACHSTATE the `detachstate' attribute in *ATTR. */ +extern int pthread_attr_getdetachstate (__const pthread_attr_t *__attr, + int *__detachstate) __THROW; + +/* Set scheduling parameters (priority, etc) in *ATTR according to PARAM. */ +extern int pthread_attr_setschedparam (pthread_attr_t *__restrict __attr, + __const struct sched_param *__restrict + __param) __THROW; + +/* Return in *PARAM the scheduling parameters of *ATTR. */ +extern int pthread_attr_getschedparam (__const pthread_attr_t *__restrict + __attr, + struct sched_param *__restrict __param) + __THROW; + +/* Set scheduling policy in *ATTR according to POLICY. */ +extern int pthread_attr_setschedpolicy (pthread_attr_t *__attr, int __policy) + __THROW; + +/* Return in *POLICY the scheduling policy of *ATTR. */ +extern int pthread_attr_getschedpolicy (__const pthread_attr_t *__restrict + __attr, int *__restrict __policy) + __THROW; + +/* Set scheduling inheritance mode in *ATTR according to INHERIT. */ +extern int pthread_attr_setinheritsched (pthread_attr_t *__attr, + int __inherit) __THROW; + +/* Return in *INHERIT the scheduling inheritance mode of *ATTR. */ +extern int pthread_attr_getinheritsched (__const pthread_attr_t *__restrict + __attr, int *__restrict __inherit) + __THROW; + +/* Set scheduling contention scope in *ATTR according to SCOPE. */ +extern int pthread_attr_setscope (pthread_attr_t *__attr, int __scope) + __THROW; + +/* Return in *SCOPE the scheduling contention scope of *ATTR. */ +extern int pthread_attr_getscope (__const pthread_attr_t *__restrict __attr, + int *__restrict __scope) __THROW; + +#ifdef __USE_UNIX98 +/* Set the size of the guard area at the bottom of the thread. */ +extern int pthread_attr_setguardsize (pthread_attr_t *__attr, + size_t __guardsize) __THROW; + +/* Get the size of the guard area at the bottom of the thread. */ +extern int pthread_attr_getguardsize (__const pthread_attr_t *__restrict + __attr, size_t *__restrict __guardsize) + __THROW; +#endif + +#if 0 /* uClibc: deprecated stuff disabled. def __UCLIBC_SUSV3_LEGACY__ */ +/* Set the starting address of the stack of the thread to be created. + Depending on whether the stack grows up or down the value must either + be higher or lower than all the address in the memory block. The + minimal size of the block must be PTHREAD_STACK_MIN. */ +extern int pthread_attr_setstackaddr (pthread_attr_t *__attr, + void *__stackaddr) __THROW; + +/* Return the previously set address for the stack. */ +extern int pthread_attr_getstackaddr (__const pthread_attr_t *__restrict + __attr, void **__restrict __stackaddr) + __THROW; +#endif + +#ifdef __USE_XOPEN2K +/* The following two interfaces are intended to replace the last two. They + require setting the address as well as the size since only setting the + address will make the implementation on some architectures impossible. */ +extern int pthread_attr_setstack (pthread_attr_t *__attr, void *__stackaddr, + size_t __stacksize) __THROW; + +/* Return the previously set address for the stack. */ +extern int pthread_attr_getstack (__const pthread_attr_t *__restrict __attr, + void **__restrict __stackaddr, + size_t *__restrict __stacksize) __THROW; +#endif + +/* Add information about the minimum stack size needed for the thread + to be started. This size must never be less than PTHREAD_STACK_MIN + and must also not exceed the system limits. */ +extern int pthread_attr_setstacksize (pthread_attr_t *__attr, + size_t __stacksize) __THROW; + +/* Return the currently used minimal stack size. */ +extern int pthread_attr_getstacksize (__const pthread_attr_t *__restrict + __attr, size_t *__restrict __stacksize) + __THROW; + +#ifdef __USE_GNU +/* Initialize thread attribute *ATTR with attributes corresponding to the + already running thread TH. It shall be called on uninitialized ATTR + and destroyed with pthread_attr_destroy when no longer needed. */ +extern int pthread_getattr_np (pthread_t __th, pthread_attr_t *__attr) __THROW; +#endif + +/* Functions for scheduling control. */ + +/* Set the scheduling parameters for TARGET_THREAD according to POLICY + and *PARAM. */ +extern int pthread_setschedparam (pthread_t __target_thread, int __policy, + __const struct sched_param *__param) + __THROW; + +/* Return in *POLICY and *PARAM the scheduling parameters for TARGET_THREAD. */ +extern int pthread_getschedparam (pthread_t __target_thread, + int *__restrict __policy, + struct sched_param *__restrict __param) + __THROW; + +#ifdef __USE_UNIX98 +/* Determine level of concurrency. */ +extern int pthread_getconcurrency (void) __THROW; + +/* Set new concurrency level to LEVEL. */ +extern int pthread_setconcurrency (int __level) __THROW; +#endif + +/* Functions for mutex handling. */ + +/* Initialize MUTEX using attributes in *MUTEX_ATTR, or use the + default values if later is NULL. */ +extern int pthread_mutex_init (pthread_mutex_t *__restrict __mutex, + __const pthread_mutexattr_t *__restrict + __mutex_attr) __THROW; + +/* Destroy MUTEX. */ +extern int pthread_mutex_destroy (pthread_mutex_t *__mutex) __THROW; + +/* Try to lock MUTEX. */ +extern int pthread_mutex_trylock (pthread_mutex_t *__mutex) __THROW; + +/* Wait until lock for MUTEX becomes available and lock it. */ +extern int pthread_mutex_lock (pthread_mutex_t *__mutex) __THROW; + +#ifdef __USE_XOPEN2K +/* Wait until lock becomes available, or specified time passes. */ +extern int pthread_mutex_timedlock (pthread_mutex_t *__restrict __mutex, + __const struct timespec *__restrict + __abstime) __THROW; +#endif + +/* Unlock MUTEX. */ +extern int pthread_mutex_unlock (pthread_mutex_t *__mutex) __THROW; + + +/* Functions for handling mutex attributes. */ + +/* Initialize mutex attribute object ATTR with default attributes + (kind is PTHREAD_MUTEX_TIMED_NP). */ +extern int pthread_mutexattr_init (pthread_mutexattr_t *__attr) __THROW; + +/* Destroy mutex attribute object ATTR. */ +extern int pthread_mutexattr_destroy (pthread_mutexattr_t *__attr) __THROW; + +/* Get the process-shared flag of the mutex attribute ATTR. */ +extern int pthread_mutexattr_getpshared (__const pthread_mutexattr_t * + __restrict __attr, + int *__restrict __pshared) __THROW; + +/* Set the process-shared flag of the mutex attribute ATTR. */ +extern int pthread_mutexattr_setpshared (pthread_mutexattr_t *__attr, + int __pshared) __THROW; + +#ifdef __USE_UNIX98 +/* Set the mutex kind attribute in *ATTR to KIND (either PTHREAD_MUTEX_NORMAL, + PTHREAD_MUTEX_RECURSIVE, PTHREAD_MUTEX_ERRORCHECK, or + PTHREAD_MUTEX_DEFAULT). */ +extern int pthread_mutexattr_settype (pthread_mutexattr_t *__attr, int __kind) + __THROW; + +/* Return in *KIND the mutex kind attribute in *ATTR. */ +extern int pthread_mutexattr_gettype (__const pthread_mutexattr_t *__restrict + __attr, int *__restrict __kind) __THROW; +#endif + + +/* Functions for handling conditional variables. */ + +/* Initialize condition variable COND using attributes ATTR, or use + the default values if later is NULL. */ +extern int pthread_cond_init (pthread_cond_t *__restrict __cond, + __const pthread_condattr_t *__restrict + __cond_attr) __THROW; + +/* Destroy condition variable COND. */ +extern int pthread_cond_destroy (pthread_cond_t *__cond) __THROW; + +/* Wake up one thread waiting for condition variable COND. */ +extern int pthread_cond_signal (pthread_cond_t *__cond) __THROW; + +/* Wake up all threads waiting for condition variables COND. */ +extern int pthread_cond_broadcast (pthread_cond_t *__cond) __THROW; + +/* Wait for condition variable COND to be signaled or broadcast. + MUTEX is assumed to be locked before. */ +extern int pthread_cond_wait (pthread_cond_t *__restrict __cond, + pthread_mutex_t *__restrict __mutex); + +/* Wait for condition variable COND to be signaled or broadcast until + ABSTIME. MUTEX is assumed to be locked before. ABSTIME is an + absolute time specification; zero is the beginning of the epoch + (00:00:00 GMT, January 1, 1970). */ +extern int pthread_cond_timedwait (pthread_cond_t *__restrict __cond, + pthread_mutex_t *__restrict __mutex, + __const struct timespec *__restrict + __abstime); + +/* Functions for handling condition variable attributes. */ + +/* Initialize condition variable attribute ATTR. */ +extern int pthread_condattr_init (pthread_condattr_t *__attr) __THROW; + +/* Destroy condition variable attribute ATTR. */ +extern int pthread_condattr_destroy (pthread_condattr_t *__attr) __THROW; + +/* Get the process-shared flag of the condition variable attribute ATTR. */ +extern int pthread_condattr_getpshared (__const pthread_condattr_t * + __restrict __attr, + int *__restrict __pshared) __THROW; + +/* Set the process-shared flag of the condition variable attribute ATTR. */ +extern int pthread_condattr_setpshared (pthread_condattr_t *__attr, + int __pshared) __THROW; + + +#if defined __USE_UNIX98 || defined __USE_XOPEN2K +/* Functions for handling read-write locks. */ + +/* Initialize read-write lock RWLOCK using attributes ATTR, or use + the default values if later is NULL. */ +extern int pthread_rwlock_init (pthread_rwlock_t *__restrict __rwlock, + __const pthread_rwlockattr_t *__restrict + __attr) __THROW; + +/* Destroy read-write lock RWLOCK. */ +extern int pthread_rwlock_destroy (pthread_rwlock_t *__rwlock) __THROW; + +/* Acquire read lock for RWLOCK. */ +extern int pthread_rwlock_rdlock (pthread_rwlock_t *__rwlock) __THROW; + +/* Try to acquire read lock for RWLOCK. */ +extern int pthread_rwlock_tryrdlock (pthread_rwlock_t *__rwlock) __THROW; + +# ifdef __USE_XOPEN2K +/* Try to acquire read lock for RWLOCK or return after specfied time. */ +extern int pthread_rwlock_timedrdlock (pthread_rwlock_t *__restrict __rwlock, + __const struct timespec *__restrict + __abstime) __THROW; +# endif + +/* Acquire write lock for RWLOCK. */ +extern int pthread_rwlock_wrlock (pthread_rwlock_t *__rwlock) __THROW; + +/* Try to acquire write lock for RWLOCK. */ +extern int pthread_rwlock_trywrlock (pthread_rwlock_t *__rwlock) __THROW; + +# ifdef __USE_XOPEN2K +/* Try to acquire write lock for RWLOCK or return after specfied time. */ +extern int pthread_rwlock_timedwrlock (pthread_rwlock_t *__restrict __rwlock, + __const struct timespec *__restrict + __abstime) __THROW; +# endif + +/* Unlock RWLOCK. */ +extern int pthread_rwlock_unlock (pthread_rwlock_t *__rwlock) __THROW; + + +/* Functions for handling read-write lock attributes. */ + +/* Initialize attribute object ATTR with default values. */ +extern int pthread_rwlockattr_init (pthread_rwlockattr_t *__attr) __THROW; + +/* Destroy attribute object ATTR. */ +extern int pthread_rwlockattr_destroy (pthread_rwlockattr_t *__attr) __THROW; + +/* Return current setting of process-shared attribute of ATTR in PSHARED. */ +extern int pthread_rwlockattr_getpshared (__const pthread_rwlockattr_t * + __restrict __attr, + int *__restrict __pshared) __THROW; + +/* Set process-shared attribute of ATTR to PSHARED. */ +extern int pthread_rwlockattr_setpshared (pthread_rwlockattr_t *__attr, + int __pshared) __THROW; + +/* Return current setting of reader/writer preference. */ +extern int pthread_rwlockattr_getkind_np (__const pthread_rwlockattr_t *__attr, + int *__pref) __THROW; + +/* Set reader/write preference. */ +extern int pthread_rwlockattr_setkind_np (pthread_rwlockattr_t *__attr, + int __pref) __THROW; +#endif + +#ifdef __USE_XOPEN2K +/* The IEEE Std. 1003.1j-2000 introduces functions to implement + spinlocks. */ + +/* Initialize the spinlock LOCK. If PSHARED is nonzero the spinlock can + be shared between different processes. */ +extern int pthread_spin_init (pthread_spinlock_t *__lock, int __pshared) + __THROW; + +/* Destroy the spinlock LOCK. */ +extern int pthread_spin_destroy (pthread_spinlock_t *__lock) __THROW; + +/* Wait until spinlock LOCK is retrieved. */ +extern int pthread_spin_lock (pthread_spinlock_t *__lock) __THROW; + +/* Try to lock spinlock LOCK. */ +extern int pthread_spin_trylock (pthread_spinlock_t *__lock) __THROW; + +/* Release spinlock LOCK. */ +extern int pthread_spin_unlock (pthread_spinlock_t *__lock) __THROW; + + +/* Barriers are a also a new feature in 1003.1j-2000. */ + +extern int pthread_barrier_init (pthread_barrier_t *__restrict __barrier, + __const pthread_barrierattr_t *__restrict + __attr, unsigned int __count) __THROW; + +extern int pthread_barrier_destroy (pthread_barrier_t *__barrier) __THROW; + +extern int pthread_barrierattr_init (pthread_barrierattr_t *__attr) __THROW; + +extern int pthread_barrierattr_destroy (pthread_barrierattr_t *__attr) __THROW; + +extern int pthread_barrierattr_getpshared (__const pthread_barrierattr_t * + __restrict __attr, + int *__restrict __pshared) __THROW; + +extern int pthread_barrierattr_setpshared (pthread_barrierattr_t *__attr, + int __pshared) __THROW; + +extern int pthread_barrier_wait (pthread_barrier_t *__barrier) __THROW; +#endif + + +/* Functions for handling thread-specific data. */ + +/* Create a key value identifying a location in the thread-specific + data area. Each thread maintains a distinct thread-specific data + area. DESTR_FUNCTION, if non-NULL, is called with the value + associated to that key when the key is destroyed. + DESTR_FUNCTION is not called if the value associated is NULL when + the key is destroyed. */ +extern int pthread_key_create (pthread_key_t *__key, + void (*__destr_function) (void *)) __THROW; + +/* Destroy KEY. */ +extern int pthread_key_delete (pthread_key_t __key) __THROW; + +/* Store POINTER in the thread-specific data slot identified by KEY. */ +extern int pthread_setspecific (pthread_key_t __key, + __const void *__pointer) __THROW; + +/* Return current value of the thread-specific data slot identified by KEY. */ +extern void *pthread_getspecific (pthread_key_t __key) __THROW; + + +/* Functions for handling initialization. */ + +/* Guarantee that the initialization function INIT_ROUTINE will be called + only once, even if pthread_once is executed several times with the + same ONCE_CONTROL argument. ONCE_CONTROL must point to a static or + extern variable initialized to PTHREAD_ONCE_INIT. + + The initialization functions might throw exception which is why + this function is not marked with __THROW. */ +extern int pthread_once (pthread_once_t *__once_control, + void (*__init_routine) (void)); + + +/* Functions for handling cancellation. */ + +/* Set cancelability state of current thread to STATE, returning old + state in *OLDSTATE if OLDSTATE is not NULL. */ +extern int pthread_setcancelstate (int __state, int *__oldstate); + +/* Set cancellation state of current thread to TYPE, returning the old + type in *OLDTYPE if OLDTYPE is not NULL. */ +extern int pthread_setcanceltype (int __type, int *__oldtype); + +/* Cancel THREAD immediately or at the next possibility. */ +extern int pthread_cancel (pthread_t __cancelthread); + +/* Test for pending cancellation for the current thread and terminate + the thread as per pthread_exit(PTHREAD_CANCELED) if it has been + cancelled. */ +extern void pthread_testcancel (void); + + +/* Install a cleanup handler: ROUTINE will be called with arguments ARG + when the thread is cancelled or calls pthread_exit. ROUTINE will also + be called with arguments ARG when the matching pthread_cleanup_pop + is executed with non-zero EXECUTE argument. + pthread_cleanup_push and pthread_cleanup_pop are macros and must always + be used in matching pairs at the same nesting level of braces. */ + +#define pthread_cleanup_push(routine,arg) \ + { struct _pthread_cleanup_buffer _buffer; \ + _pthread_cleanup_push (&_buffer, (routine), (arg)); + +extern void _pthread_cleanup_push (struct _pthread_cleanup_buffer *__buffer, + void (*__routine) (void *), + void *__arg) __THROW; + +/* Remove a cleanup handler installed by the matching pthread_cleanup_push. + If EXECUTE is non-zero, the handler function is called. */ + +#define pthread_cleanup_pop(execute) \ + _pthread_cleanup_pop (&_buffer, (execute)); } + +extern void _pthread_cleanup_pop (struct _pthread_cleanup_buffer *__buffer, + int __execute) __THROW; + +/* Install a cleanup handler as pthread_cleanup_push does, but also + saves the current cancellation type and set it to deferred cancellation. */ + +#ifdef __USE_GNU +# define pthread_cleanup_push_defer_np(routine,arg) \ + { struct _pthread_cleanup_buffer _buffer; \ + _pthread_cleanup_push_defer (&_buffer, (routine), (arg)); + +extern void _pthread_cleanup_push_defer (struct _pthread_cleanup_buffer *__buffer, + void (*__routine) (void *), + void *__arg) __THROW; + +/* Remove a cleanup handler as pthread_cleanup_pop does, but also + restores the cancellation type that was in effect when the matching + pthread_cleanup_push_defer was called. */ + +# define pthread_cleanup_pop_restore_np(execute) \ + _pthread_cleanup_pop_restore (&_buffer, (execute)); } + +extern void _pthread_cleanup_pop_restore (struct _pthread_cleanup_buffer *__buffer, + int __execute) __THROW; +#endif + + +#ifdef __USE_XOPEN2K +/* Get ID of CPU-time clock for thread THREAD_ID. */ +extern int pthread_getcpuclockid (pthread_t __thread_id, + __clockid_t *__clock_id) __THROW; +#endif + + +/* Functions for handling signals. */ +#include + + +/* Functions for handling process creation and process execution. */ + +/* Install handlers to be called when a new process is created with FORK. + The PREPARE handler is called in the parent process just before performing + FORK. The PARENT handler is called in the parent process just after FORK. + The CHILD handler is called in the child process. Each of the three + handlers can be NULL, meaning that no handler needs to be called at that + point. + PTHREAD_ATFORK can be called several times, in which case the PREPARE + handlers are called in LIFO order (last added with PTHREAD_ATFORK, + first called before FORK), and the PARENT and CHILD handlers are called + in FIFO (first added, first called). */ + +extern int pthread_atfork (void (*__prepare) (void), + void (*__parent) (void), + void (*__child) (void)) __THROW; + +/* Terminate all threads in the program except the calling process. + Should be called just before invoking one of the exec*() functions. */ + +extern void pthread_kill_other_threads_np (void) __THROW; + +__END_DECLS + +#endif /* pthread.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/ptlongjmp.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/ptlongjmp.c new file mode 100644 index 00000000..a2a56b8d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/ptlongjmp.c @@ -0,0 +1,39 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1998 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +/* Redefine siglongjmp and longjmp so that they interact correctly + with cleanup handlers */ + +#include +#include "pthread.h" +#include "internals.h" + +/* These functions are not declared anywhere since they shouldn't be + used at another place but here. */ +extern void __libc_siglongjmp (sigjmp_buf env, int val) + __attribute__ ((noreturn)); +extern void __libc_longjmp (sigjmp_buf env, int val) + __attribute__ ((noreturn)); + +#ifdef SHARED +void siglongjmp (sigjmp_buf env, int val) +{ + __libc_siglongjmp (env, val); +} + +void longjmp (jmp_buf env, int val) +{ + __libc_longjmp (env, val); +} +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/res-state.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/res-state.c new file mode 100644 index 00000000..016e20b4 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/res-state.c @@ -0,0 +1,47 @@ +/* Copyright (C) 1996, 97, 98, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + +#if ! USE___THREAD +# undef _res +extern struct __res_state _res; +#endif + +/* When threaded, _res may be a per-thread variable. */ +struct __res_state * +#if ! USE___THREAD +weak_const_function +#endif +__res_state (void) +{ +#if ! USE___THREAD + if (! SINGLE_THREAD_P) + { + pthread_descr self = thread_self(); + return LIBC_THREAD_GETMEM (self, p_resp); + } + return &_res; +#else + return __resp; +#endif +} +libc_hidden_def (__res_state) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/semaphore.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/semaphore.h new file mode 100644 index 00000000..8793768a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/semaphore.h @@ -0,0 +1 @@ +#include diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/sigaction.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/sigaction.c new file mode 100644 index 00000000..2f2a85ca --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/sigaction.c @@ -0,0 +1,57 @@ +/* Copyright (C) 2003, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Somebody please explain what's going on here. --vda */ + +/* This is tricky. GCC doesn't like #include_next in the primary + source file and even if it did, the first #include_next is this + exact file anyway. */ +#ifndef LIBC_SIGACTION + +# include + +# define LIBC_SIGACTION 1 + +# include "sigaction.c" + +# ifndef NOT_IN_libc +# ifndef SHARED +weak_extern (__pthread_sigaction) +# endif + +int +__sigaction (sig, act, oact) + int sig; + const struct sigaction *act; + struct sigaction *oact; +{ + return __libc_maybe_call2 (pthread_sigaction, (sig, act, oact), + __libc_sigaction (sig, act, oact)); +} +# else +weak_alias (__libc_sigaction, __sigaction) +# endif +libc_hidden_weak (__sigaction) +weak_alias (__sigaction, sigaction) + +#else + +# include_next + +#endif /* LIBC_SIGACTION */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/tcb-offsets.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/tcb-offsets.h new file mode 100644 index 00000000..3fe13702 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/tcb-offsets.h @@ -0,0 +1 @@ +/* This is overridden by generated tcb-offsets.h on arches which need it. */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/timer_create.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/timer_create.c new file mode 100644 index 00000000..7f7e886c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/timer_create.c @@ -0,0 +1,170 @@ +/* Copyright (C) 2000, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Kaz Kylheku . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include +#include + +#include "posix-timer.h" + + +/* Create new per-process timer using CLOCK. */ +int +timer_create (clock_id, evp, timerid) + clockid_t clock_id; + struct sigevent *evp; + timer_t *timerid; +{ + int retval = -1; + struct timer_node *newtimer = NULL; + struct thread_node *thread = NULL; + + if (0 +#ifdef _POSIX_CPUTIME + || clock_id == CLOCK_PROCESS_CPUTIME_ID +#endif +#ifdef _POSIX_THREAD_CPUTIME + || clock_id == CLOCK_THREAD_CPUTIME_ID +#endif + ) + { + /* We don't allow timers for CPU clocks. At least not in the + moment. */ + __set_errno (ENOTSUP); + return -1; + } + + if (clock_id != CLOCK_REALTIME) + { + __set_errno (EINVAL); + return -1; + } + + pthread_once (&__timer_init_once_control, __timer_init_once); + + if (__timer_init_failed) + { + __set_errno (ENOMEM); + return -1; + } + + pthread_mutex_lock (&__timer_mutex); + + newtimer = __timer_alloc (); + if (__builtin_expect (newtimer == NULL, 0)) + { + __set_errno (EAGAIN); + goto unlock_bail; + } + + if (evp != NULL) + newtimer->event = *evp; + else + { + newtimer->event.sigev_notify = SIGEV_SIGNAL; + newtimer->event.sigev_signo = SIGALRM; + newtimer->event.sigev_value.sival_int = timer_ptr2id (newtimer); + newtimer->event.sigev_notify_function = 0; + } + + newtimer->event.sigev_notify_attributes = &newtimer->attr; + newtimer->creator_pid = getpid (); + + switch (__builtin_expect (newtimer->event.sigev_notify, SIGEV_SIGNAL)) + { + case SIGEV_NONE: + case SIGEV_SIGNAL: + /* We have a global thread for delivering timed signals. + If it is not running, try to start it up. */ + thread = &__timer_signal_thread_rclk; + if (! thread->exists) + { + if (__builtin_expect (__timer_thread_start (thread), + 1) < 0) + { + __set_errno (EAGAIN); + goto unlock_bail; + } + } + break; + + case SIGEV_THREAD: + /* Copy over thread attributes or set up default ones. */ + if (evp->sigev_notify_attributes) + newtimer->attr = *(pthread_attr_t *) evp->sigev_notify_attributes; + else + pthread_attr_init (&newtimer->attr); + + /* Ensure thread attributes call for deatched thread. */ + pthread_attr_setdetachstate (&newtimer->attr, PTHREAD_CREATE_DETACHED); + + /* Try to find existing thread having the right attributes. */ + thread = __timer_thread_find_matching (&newtimer->attr, clock_id); + + /* If no existing thread has these attributes, try to allocate one. */ + if (thread == NULL) + thread = __timer_thread_alloc (&newtimer->attr, clock_id); + + /* Out of luck; no threads are available. */ + if (__builtin_expect (thread == NULL, 0)) + { + __set_errno (EAGAIN); + goto unlock_bail; + } + + /* If the thread is not running already, try to start it. */ + if (! thread->exists + && __builtin_expect (! __timer_thread_start (thread), 0)) + { + __set_errno (EAGAIN); + goto unlock_bail; + } + break; + + default: + __set_errno (EINVAL); + goto unlock_bail; + } + + newtimer->clock = clock_id; + newtimer->abstime = 0; + newtimer->armed = 0; + newtimer->thread = thread; + + *timerid = timer_ptr2id (newtimer); + retval = 0; + + if (__builtin_expect (retval, 0) == -1) + { + unlock_bail: + if (thread != NULL) + __timer_thread_dealloc (thread); + if (newtimer != NULL) + { + timer_delref (newtimer); + __timer_dealloc (newtimer); + } + } + + pthread_mutex_unlock (&__timer_mutex); + + return retval; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/timer_delete.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/timer_delete.c new file mode 100644 index 00000000..48ba1f27 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/timer_delete.c @@ -0,0 +1,70 @@ +/* Copyright (C) 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Kaz Kylheku . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include + +#include "posix-timer.h" + + +/* Delete timer TIMERID. */ +int +timer_delete (timerid) + timer_t timerid; +{ + struct timer_node *timer; + int retval = -1; + + pthread_mutex_lock (&__timer_mutex); + + timer = timer_id2ptr (timerid); + if (! timer_valid (timer)) + /* Invalid timer ID or the timer is not in use. */ + __set_errno (EINVAL); + else + { + if (timer->armed && timer->thread != NULL) + { + struct thread_node *thread = timer->thread; + assert (thread != NULL); + + /* If thread is cancelled while waiting for handler to terminate, + the mutex is unlocked and timer_delete is aborted. */ + pthread_cleanup_push (__timer_mutex_cancel_handler, &__timer_mutex); + + /* If timer is currently being serviced, wait for it to finish. */ + while (thread->current_timer == timer) + pthread_cond_wait (&thread->cond, &__timer_mutex); + + pthread_cleanup_pop (0); + } + + /* Remove timer from whatever queue it may be on and deallocate it. */ + timer->inuse = TIMER_DELETED; + list_unlink_ip (&timer->links); + timer_delref (timer); + retval = 0; + } + + pthread_mutex_unlock (&__timer_mutex); + + return retval; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/timer_getoverr.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/timer_getoverr.c new file mode 100644 index 00000000..f3e22215 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/timer_getoverr.c @@ -0,0 +1,45 @@ +/* Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Kaz Kylheku . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include + +#include "posix-timer.h" + + +/* Get expiration overrun for timer TIMERID. */ +int +timer_getoverrun (timerid) + timer_t timerid; +{ + struct timer_node *timer; + int retval = -1; + + pthread_mutex_lock (&__timer_mutex); + + if (! timer_valid (timer = timer_id2ptr (timerid))) + __set_errno (EINVAL); + else + retval = timer->overrun_count; + + pthread_mutex_unlock (&__timer_mutex); + + return retval; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/timer_gettime.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/timer_gettime.c new file mode 100644 index 00000000..723a6163 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/timer_gettime.c @@ -0,0 +1,77 @@ +/* Copyright (C) 2000, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Kaz Kylheku . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include + +#include "posix-timer.h" + + +/* Get current value of timer TIMERID and store it in VLAUE. */ +int +timer_gettime (timerid, value) + timer_t timerid; + struct itimerspec *value; +{ + struct timer_node *timer; + struct timespec now, expiry; + int retval = -1, armed = 0, valid; + clock_t clock = 0; + + pthread_mutex_lock (&__timer_mutex); + + timer = timer_id2ptr (timerid); + valid = timer_valid (timer); + + if (valid) { + armed = timer->armed; + expiry = timer->expirytime; + clock = timer->clock; + value->it_interval = timer->value.it_interval; + } + + pthread_mutex_unlock (&__timer_mutex); + + if (valid) + { + if (armed) + { + clock_gettime (clock, &now); + if (timespec_compare (&now, &expiry) < 0) + timespec_sub (&value->it_value, &expiry, &now); + else + { + value->it_value.tv_sec = 0; + value->it_value.tv_nsec = 0; + } + } + else + { + value->it_value.tv_sec = 0; + value->it_value.tv_nsec = 0; + } + + retval = 0; + } + else + __set_errno (EINVAL); + + return retval; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/timer_routines.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/timer_routines.c new file mode 100644 index 00000000..25b4630e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/timer_routines.c @@ -0,0 +1,573 @@ +/* Helper code for POSIX timer implementation on LinuxThreads. + Copyright (C) 2000, 2001, 2002, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Kaz Kylheku . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "posix-timer.h" + + +/* Number of threads used. */ +#define THREAD_MAXNODES 16 + +/* Array containing the descriptors for the used threads. */ +static struct thread_node thread_array[THREAD_MAXNODES]; + +/* Static array with the structures for all the timers. */ +struct timer_node __timer_array[TIMER_MAX]; + +/* Global lock to protect operation on the lists. */ +pthread_mutex_t __timer_mutex = PTHREAD_MUTEX_INITIALIZER; + +/* Variable to protext initialization. */ +pthread_once_t __timer_init_once_control = PTHREAD_ONCE_INIT; + +/* Nonzero if initialization of timer implementation failed. */ +int __timer_init_failed; + +/* Node for the thread used to deliver signals. */ +struct thread_node __timer_signal_thread_rclk; + +/* Lists to keep free and used timers and threads. */ +struct list_links timer_free_list; +struct list_links thread_free_list; +struct list_links thread_active_list; + + +#ifdef __NR_rt_sigqueueinfo +extern int __syscall_rt_sigqueueinfo (int, int, siginfo_t *); +#endif + + +/* List handling functions. */ +static __inline__ void +list_init (struct list_links *list) +{ + list->next = list->prev = list; +} + +static __inline__ void +list_append (struct list_links *list, struct list_links *newp) +{ + newp->prev = list->prev; + newp->next = list; + list->prev->next = newp; + list->prev = newp; +} + +static __inline__ void +list_insbefore (struct list_links *list, struct list_links *newp) +{ + list_append (list, newp); +} + +/* + * Like list_unlink_ip, except that calling it on a node that + * is already unlinked is disastrous rather than a noop. + */ + +static __inline__ void +list_unlink (struct list_links *list) +{ + struct list_links *lnext = list->next, *lprev = list->prev; + + lnext->prev = lprev; + lprev->next = lnext; +} + +static __inline__ struct list_links * +list_first (struct list_links *list) +{ + return list->next; +} + +static __inline__ struct list_links * +list_null (struct list_links *list) +{ + return list; +} + +static __inline__ struct list_links * +list_next (struct list_links *list) +{ + return list->next; +} + +static __inline__ int +list_isempty (struct list_links *list) +{ + return list->next == list; +} + + +/* Functions build on top of the list functions. */ +static __inline__ struct thread_node * +thread_links2ptr (struct list_links *list) +{ + return (struct thread_node *) ((char *) list + - offsetof (struct thread_node, links)); +} + +static __inline__ struct timer_node * +timer_links2ptr (struct list_links *list) +{ + return (struct timer_node *) ((char *) list + - offsetof (struct timer_node, links)); +} + + +/* Initialize a newly allocated thread structure. */ +static void +thread_init (struct thread_node *thread, const pthread_attr_t *attr, clockid_t clock_id) +{ + if (attr != NULL) + thread->attr = *attr; + else + { + pthread_attr_init (&thread->attr); + pthread_attr_setdetachstate (&thread->attr, PTHREAD_CREATE_DETACHED); + } + + thread->exists = 0; + list_init (&thread->timer_queue); + pthread_cond_init (&thread->cond, 0); + thread->current_timer = 0; + thread->captured = pthread_self (); + thread->clock_id = clock_id; +} + + +/* Initialize the global lists, and acquire global resources. Error + reporting is done by storing a non-zero value to the global variable + timer_init_failed. */ +static void +init_module (void) +{ + int i; + + list_init (&timer_free_list); + list_init (&thread_free_list); + list_init (&thread_active_list); + + for (i = 0; i < TIMER_MAX; ++i) + { + list_append (&timer_free_list, &__timer_array[i].links); + __timer_array[i].inuse = TIMER_FREE; + } + + for (i = 0; i < THREAD_MAXNODES; ++i) + list_append (&thread_free_list, &thread_array[i].links); + + thread_init (&__timer_signal_thread_rclk, 0, CLOCK_REALTIME); +} + + +/* This is a handler executed in a child process after a fork() + occurs. It reinitializes the module, resetting all of the data + structures to their initial state. The mutex is initialized in + case it was locked in the parent process. */ +static void +reinit_after_fork (void) +{ + init_module (); + pthread_mutex_init (&__timer_mutex, 0); +} + + +/* Called once form pthread_once in timer_init. This initializes the + module and ensures that reinit_after_fork will be executed in any + child process. */ +void +__timer_init_once (void) +{ + init_module (); + pthread_atfork (0, 0, reinit_after_fork); +} + + +/* Deinitialize a thread that is about to be deallocated. */ +static void +thread_deinit (struct thread_node *thread) +{ + assert (list_isempty (&thread->timer_queue)); + pthread_cond_destroy (&thread->cond); +} + + +/* Allocate a thread structure from the global free list. Global + mutex lock must be held by caller. The thread is moved to + the active list. */ +struct thread_node * +__timer_thread_alloc (const pthread_attr_t *desired_attr, clockid_t clock_id) +{ + struct list_links *node = list_first (&thread_free_list); + + if (node != list_null (&thread_free_list)) + { + struct thread_node *thread = thread_links2ptr (node); + list_unlink (node); + thread_init (thread, desired_attr, clock_id); + list_append (&thread_active_list, node); + return thread; + } + + return 0; +} + + +/* Return a thread structure to the global free list. Global lock + must be held by caller. */ +void +__timer_thread_dealloc (struct thread_node *thread) +{ + thread_deinit (thread); + list_unlink (&thread->links); + list_append (&thread_free_list, &thread->links); +} + + +/* Each of our threads which terminates executes this cleanup + handler. We never terminate threads ourselves; if a thread gets here + it means that the evil application has killed it. If the thread has + timers, these require servicing and so we must hire a replacement + thread right away. We must also unblock another thread that may + have been waiting for this thread to finish servicing a timer (see + timer_delete()). */ + +static void +thread_cleanup (void *val) +{ + if (val != NULL) + { + struct thread_node *thread = val; + + /* How did the signal thread get killed? */ + assert (thread != &__timer_signal_thread_rclk); + + pthread_mutex_lock (&__timer_mutex); + + thread->exists = 0; + + /* We are no longer processing a timer event. */ + thread->current_timer = 0; + + if (list_isempty (&thread->timer_queue)) + __timer_thread_dealloc (thread); + else + (void) __timer_thread_start (thread); + + pthread_mutex_unlock (&__timer_mutex); + + /* Unblock potentially blocked timer_delete(). */ + pthread_cond_broadcast (&thread->cond); + } +} + + +/* Handle a timer which is supposed to go off now. */ +static void +thread_expire_timer (struct thread_node *self, struct timer_node *timer) +{ + self->current_timer = timer; /* Lets timer_delete know timer is running. */ + + pthread_mutex_unlock (&__timer_mutex); + + switch (__builtin_expect (timer->event.sigev_notify, SIGEV_SIGNAL)) + { + case SIGEV_NONE: + break; + + case SIGEV_SIGNAL: +#ifdef __NR_rt_sigqueueinfo + { + siginfo_t info; + + /* First, clear the siginfo_t structure, so that we don't pass our + stack content to other tasks. */ + memset (&info, 0, sizeof (siginfo_t)); + /* We must pass the information about the data in a siginfo_t + value. */ + info.si_signo = timer->event.sigev_signo; + info.si_code = SI_TIMER; + info.si_pid = timer->creator_pid; + info.si_uid = getuid (); + info.si_value = timer->event.sigev_value; + + INLINE_SYSCALL (rt_sigqueueinfo, 3, info.si_pid, info.si_signo, &info); + } +#else + if (pthread_kill (self->captured, timer->event.sigev_signo) != 0) + { + if (pthread_kill (self->id, timer->event.sigev_signo) != 0) + abort (); + } +#endif + break; + + case SIGEV_THREAD: + timer->event.sigev_notify_function (timer->event.sigev_value); + break; + + default: + assert (! "unknown event"); + break; + } + + pthread_mutex_lock (&__timer_mutex); + + self->current_timer = 0; + + pthread_cond_broadcast (&self->cond); +} + + +/* Thread function; executed by each timer thread. The job of this + function is to wait on the thread's timer queue and expire the + timers in chronological order as close to their scheduled time as + possible. */ +static void +__attribute__ ((noreturn)) +thread_func (void *arg) +{ + struct thread_node *self = arg; + + /* Register cleanup handler, in case rogue application terminates + this thread. (This cannot happen to __timer_signal_thread, which + doesn't invoke application callbacks). */ + + pthread_cleanup_push (thread_cleanup, self); + + pthread_mutex_lock (&__timer_mutex); + + while (1) + { + struct list_links *first; + struct timer_node *timer = NULL; + + /* While the timer queue is not empty, inspect the first node. */ + first = list_first (&self->timer_queue); + if (first != list_null (&self->timer_queue)) + { + struct timespec now; + + timer = timer_links2ptr (first); + + /* This assumes that the elements of the list of one thread + are all for the same clock. */ + clock_gettime (timer->clock, &now); + + while (1) + { + /* If the timer is due or overdue, remove it from the queue. + If it's a periodic timer, re-compute its new time and + requeue it. Either way, perform the timer expiry. */ + if (timespec_compare (&now, &timer->expirytime) < 0) + break; + + list_unlink_ip (first); + + if (__builtin_expect (timer->value.it_interval.tv_sec, 0) != 0 + || timer->value.it_interval.tv_nsec != 0) + { + timer->overrun_count = 0; + timespec_add (&timer->expirytime, &timer->expirytime, + &timer->value.it_interval); + while (timespec_compare (&timer->expirytime, &now) < 0) + { + timespec_add (&timer->expirytime, &timer->expirytime, + &timer->value.it_interval); + if (timer->overrun_count < DELAYTIMER_MAX) + ++timer->overrun_count; + } + __timer_thread_queue_timer (self, timer); + } + + thread_expire_timer (self, timer); + + first = list_first (&self->timer_queue); + if (first == list_null (&self->timer_queue)) + break; + + timer = timer_links2ptr (first); + } + } + + /* If the queue is not empty, wait until the expiry time of the + first node. Otherwise wait indefinitely. Insertions at the + head of the queue must wake up the thread by broadcasting + this condition variable. */ + if (timer != NULL) + pthread_cond_timedwait (&self->cond, &__timer_mutex, + &timer->expirytime); + else + pthread_cond_wait (&self->cond, &__timer_mutex); + } + /* This macro will never be executed since the while loop loops + forever - but we have to add it for proper nesting. */ + pthread_cleanup_pop (1); +} + + +/* Enqueue a timer in wakeup order in the thread's timer queue. + Returns 1 if the timer was inserted at the head of the queue, + causing the queue's next wakeup time to change. */ + +int +__timer_thread_queue_timer (struct thread_node *thread, + struct timer_node *insert) +{ + struct list_links *iter; + int athead = 1; + + for (iter = list_first (&thread->timer_queue); + iter != list_null (&thread->timer_queue); + iter = list_next (iter)) + { + struct timer_node *timer = timer_links2ptr (iter); + + if (timespec_compare (&insert->expirytime, &timer->expirytime) < 0) + break; + athead = 0; + } + + list_insbefore (iter, &insert->links); + return athead; +} + + +/* Start a thread and associate it with the given thread node. Global + lock must be held by caller. */ +int +__timer_thread_start (struct thread_node *thread) +{ + int retval = 1; + + assert (!thread->exists); + thread->exists = 1; + + if (pthread_create (&thread->id, &thread->attr, + (void *(*) (void *)) thread_func, thread) != 0) + { + thread->exists = 0; + retval = -1; + } + + return retval; +} + + +void +__timer_thread_wakeup (struct thread_node *thread) +{ + pthread_cond_broadcast (&thread->cond); +} + + +/* Compare two pthread_attr_t thread attributes for exact equality. + Returns 1 if they are equal, otherwise zero if they are not equal or + contain illegal values. This version is LinuxThreads-specific for + performance reason. One could use the access functions to get the + values of all the fields of the attribute structure. */ +static int +thread_attr_compare (const pthread_attr_t *left, const pthread_attr_t *right) +{ + return (left->__detachstate == right->__detachstate + && left->__schedpolicy == right->__schedpolicy + && left->__guardsize == right->__guardsize + && (left->__schedparam.sched_priority + == right->__schedparam.sched_priority) + && left->__inheritsched == right->__inheritsched + && left->__scope == right->__scope + && left->__stacksize == right->__stacksize + && left->__stackaddr_set == right->__stackaddr_set + && (left->__stackaddr_set + || left->__stackaddr == right->__stackaddr)); +} + + +/* Search the list of active threads and find one which has matching + attributes. Global mutex lock must be held by caller. */ +struct thread_node * +__timer_thread_find_matching (const pthread_attr_t *desired_attr, + clockid_t desired_clock_id) +{ + struct list_links *iter = list_first (&thread_active_list); + + while (iter != list_null (&thread_active_list)) + { + struct thread_node *candidate = thread_links2ptr (iter); + + if (thread_attr_compare (desired_attr, &candidate->attr) + && desired_clock_id == candidate->clock_id) + return candidate; + + iter = list_next (iter); + } + + return NULL; +} + + +/* Grab a free timer structure from the global free list. The global + lock must be held by the caller. */ +struct timer_node * +__timer_alloc (void) +{ + struct list_links *node = list_first (&timer_free_list); + + if (node != list_null (&timer_free_list)) + { + struct timer_node *timer = timer_links2ptr (node); + list_unlink_ip (node); + timer->inuse = TIMER_INUSE; + timer->refcount = 1; + return timer; + } + + return NULL; +} + + +/* Return a timer structure to the global free list. The global lock + must be held by the caller. */ +void +__timer_dealloc (struct timer_node *timer) +{ + assert (timer->refcount == 0); + timer->thread = NULL; /* Break association between timer and thread. */ + timer->inuse = TIMER_FREE; + list_append (&timer_free_list, &timer->links); +} + + +/* Thread cancellation handler which unlocks a mutex. */ +void +__timer_mutex_cancel_handler (void *arg) +{ + pthread_mutex_unlock (arg); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/timer_settime.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/timer_settime.c new file mode 100644 index 00000000..592b5271 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/timer_settime.c @@ -0,0 +1,137 @@ +/* Copyright (C) 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Kaz Kylheku . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include + +#include "posix-timer.h" + + +/* Set timer TIMERID to VALUE, returning old value in OVLAUE. */ +int +timer_settime (timerid, flags, value, ovalue) + timer_t timerid; + int flags; + const struct itimerspec *value; + struct itimerspec *ovalue; +{ + struct timer_node *timer; + struct thread_node *thread = NULL; + struct timespec now; + int have_now = 0, need_wakeup = 0; + int retval = -1; + + timer = timer_id2ptr (timerid); + if (timer == NULL) + { + __set_errno (EINVAL); + goto bail; + } + + if (value->it_interval.tv_nsec < 0 + || value->it_interval.tv_nsec >= 1000000000 + || value->it_value.tv_nsec < 0 + || value->it_value.tv_nsec >= 1000000000) + { + __set_errno (EINVAL); + goto bail; + } + + /* Will need to know current time since this is a relative timer; + might as well make the system call outside of the lock now! */ + + if ((flags & TIMER_ABSTIME) == 0) + { + clock_gettime (timer->clock, &now); + have_now = 1; + } + + pthread_mutex_lock (&__timer_mutex); + timer_addref (timer); + + /* One final check of timer validity; this one is possible only + until we have the mutex, because it accesses the inuse flag. */ + + if (! timer_valid(timer)) + { + __set_errno (EINVAL); + goto unlock_bail; + } + + if (ovalue != NULL) + { + ovalue->it_interval = timer->value.it_interval; + + if (timer->armed) + { + if (! have_now) + { + pthread_mutex_unlock (&__timer_mutex); + clock_gettime (timer->clock, &now); + have_now = 1; + pthread_mutex_lock (&__timer_mutex); + timer_addref (timer); + } + + timespec_sub (&ovalue->it_value, &timer->expirytime, &now); + } + else + { + ovalue->it_value.tv_sec = 0; + ovalue->it_value.tv_nsec = 0; + } + } + + timer->value = *value; + + list_unlink_ip (&timer->links); + timer->armed = 0; + + thread = timer->thread; + + /* A value of { 0, 0 } causes the timer to be stopped. */ + if (value->it_value.tv_sec != 0 + || __builtin_expect (value->it_value.tv_nsec != 0, 1)) + { + if ((flags & TIMER_ABSTIME) != 0) + /* The user specified the expiration time. */ + timer->expirytime = value->it_value; + else + timespec_add (&timer->expirytime, &now, &value->it_value); + + /* Only need to wake up the thread if timer is inserted + at the head of the queue. */ + if (thread != NULL) + need_wakeup = __timer_thread_queue_timer (thread, timer); + timer->armed = 1; + } + + retval = 0; + +unlock_bail: + timer_delref (timer); + pthread_mutex_unlock (&__timer_mutex); + +bail: + if (thread != NULL && need_wakeup) + __timer_thread_wakeup (thread); + + return retval; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/tst-timer.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/tst-timer.c new file mode 100644 index 00000000..7417bcd5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/tst-timer.c @@ -0,0 +1,114 @@ +/* Tests for POSIX timer implementation. + Copyright (C) 2000, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Kaz Kylheku . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include +#include + + +static void +notify_func (union sigval sigval) +{ + puts ("notify_func"); +} + + +static void +signal_func (int sig) +{ + static const char text[] = "signal_func\n"; + signal (sig, signal_func); + write (STDOUT_FILENO, text, sizeof text - 1); +} + +static void +intr_sleep (int sec) +{ + struct timespec ts; + + ts.tv_sec = sec; + ts.tv_nsec = 0; + + while (nanosleep (&ts, &ts) == -1 && errno == EINTR) + ; +} + +#define ZSIGALRM 14 + + +int +main (void) +{ + struct timespec ts; + timer_t timer_sig, timer_thr1, timer_thr2; + int retval; + struct sigevent sigev1 = + { + .sigev_notify = SIGEV_SIGNAL, + .sigev_signo = ZSIGALRM + }; + struct sigevent sigev2; + struct itimerspec itimer1 = { { 0, 200000000 }, { 0, 200000000 } }; + struct itimerspec itimer2 = { { 0, 100000000 }, { 0, 500000000 } }; + struct itimerspec itimer3 = { { 0, 150000000 }, { 0, 300000000 } }; + struct itimerspec old; + + retval = clock_gettime (CLOCK_REALTIME, &ts); + + sigev2.sigev_notify = SIGEV_THREAD; + sigev2.sigev_notify_function = notify_func; + sigev2.sigev_notify_attributes = NULL; + + setvbuf (stdout, 0, _IOLBF, 0); + + printf ("clock_gettime returned %d, timespec = { %ld, %ld }\n", + retval, ts.tv_sec, ts.tv_nsec); + + retval = clock_getres (CLOCK_REALTIME, &ts); + + printf ("clock_getres returned %d, timespec = { %ld, %ld }\n", + retval, ts.tv_sec, ts.tv_nsec); + + timer_create (CLOCK_REALTIME, &sigev1, &timer_sig); + timer_create (CLOCK_REALTIME, &sigev2, &timer_thr1); + timer_create (CLOCK_REALTIME, &sigev2, &timer_thr2); + + timer_settime (timer_thr1, 0, &itimer2, &old); + timer_settime (timer_thr2, 0, &itimer3, &old); + + signal (ZSIGALRM, signal_func); + + timer_settime (timer_sig, 0, &itimer1, &old); + + timer_delete (-1); + + intr_sleep (3); + + timer_delete (timer_sig); + timer_delete (timer_thr1); + + intr_sleep (3); + + timer_delete (timer_thr2); + + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/uClibc-glue.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/uClibc-glue.h new file mode 100644 index 00000000..b957dedc --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/pthread/uClibc-glue.h @@ -0,0 +1,47 @@ +#ifndef _UCLIBC_GLUE_H +#define _UCLIBC_GLUE_H 1 + +#include +#include +#include + +#ifdef IS_IN_libpthread +#include + +#ifndef __GLIBC_HAVE_LONG_LONG +# define __GLIBC_HAVE_LONG_LONG +#endif + +#define __getpagesize getpagesize +#define __sched_get_priority_max sched_get_priority_max +#define __sched_get_priority_min sched_get_priority_min +#define __sched_getscheduler sched_getscheduler +#define __sched_setscheduler sched_setscheduler +#define __sched_getparam sched_getparam +#define __getpid getpid +#define __gettimeofday gettimeofday +#define __poll poll +#define __sysctl sysctl +#define __open open +#define __read read +#define __close close +#define __on_exit on_exit +#define __libc_current_sigrtmin_private __libc_current_sigrtmin +#define __clone clone + +extern void *__libc_stack_end; +extern int __cxa_atexit (void (*func) (void *), void *arg, void *d); + +#endif /* IS_IN_libpthread */ + +#ifdef __UCLIBC_HAS_XLOCALE__ +# define __uselocale(x) uselocale(x) +#else +# define __uselocale(x) ((void)0) +#endif + +/* Use a funky version in a probably vein attempt at preventing gdb + * from dlopen()'ing glibc's libthread_db library... */ +#define VERSION __stringify(__UCLIBC_MAJOR__) "." __stringify(__UCLIBC_MINOR__) "." __stringify(__UCLIBC_SUBLEVEL__) + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/s390/pspinlock.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/s390/pspinlock.c new file mode 100644 index 00000000..98be504e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/s390/pspinlock.c @@ -0,0 +1,91 @@ +/* POSIX spinlock implementation. S/390 version. + Copyright (C) 2000, 2004 Free Software Foundation, Inc. + Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com). + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include "internals.h" + +/* This implementation is similar to the one used in the Linux kernel. + But the kernel is byte instructions for the memory access. This is + faster but unusable here. The problem is that only 128 + threads/processes could use the spinlock at the same time. If (by + a design error in the program) a thread/process would hold the + spinlock for a time long enough to accumulate 128 waiting + processes, the next one will find a positive value in the spinlock + and assume it is unlocked. We cannot accept that. */ + +int +__pthread_spin_lock (pthread_spinlock_t *lock) +{ + __asm__ __volatile__(" basr 1,0\n" + "0: slr 0,0\n" + " cs 0,1,%1\n" + " jl 0b\n" + : "=m" (*lock) + : "m" (*lock) : "0", "1", "cc" ); + return 0; +} +weak_alias (__pthread_spin_lock, pthread_spin_lock) + +int +__pthread_spin_trylock (pthread_spinlock_t *lock) +{ + int oldval; + + __asm__ __volatile__(" slr %1,%1\n" + " basr 1,0\n" + "0: cs %1,1,%0" + : "=m" (*lock), "=&d" (oldval) + : "m" (*lock) : "1", "cc" ); + return oldval == 0 ? 0 : EBUSY; +} +weak_alias (__pthread_spin_trylock, pthread_spin_trylock) + + +int +__pthread_spin_unlock (pthread_spinlock_t *lock) +{ + __asm__ __volatile__(" xc 0(4,%0),0(%0)\n" + " bcr 15,0" + : : "a" (lock) : "memory" ); + return 0; +} +weak_alias (__pthread_spin_unlock, pthread_spin_unlock) + + +int +__pthread_spin_init (pthread_spinlock_t *lock, int pshared) +{ + /* We can ignore the `pshared' parameter. Since we are busy-waiting + all processes which can access the memory location `lock' points + to can use the spinlock. */ + *lock = 0; + return 0; +} +weak_alias (__pthread_spin_init, pthread_spin_init) + + +int +__pthread_spin_destroy (pthread_spinlock_t *lock) +{ + /* Nothing to do. */ + return 0; +} +weak_alias (__pthread_spin_destroy, pthread_spin_destroy) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/s390/s390-32/pt-machine.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/s390/s390-32/pt-machine.h new file mode 100644 index 00000000..d52d600a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/s390/s390-32/pt-machine.h @@ -0,0 +1,120 @@ +/* Machine-dependent pthreads configuration and inline functions. + S390 version. + Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. + Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com). + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _PT_MACHINE_H +#define _PT_MACHINE_H 1 + +#ifndef PT_EI +# define PT_EI __extern_always_inline +#endif + +extern long int testandset (int *spinlock); +extern int __compare_and_swap (long int *p, long int oldval, long int newval); + +/* For multiprocessor systems, we want to ensure all memory accesses + are completed before we reset a lock. On other systems, we still + need to make sure that the compiler has flushed everything to memory. */ +#define MEMORY_BARRIER() __asm__ __volatile__ ("bcr 15,0" : : : "memory") + +/* Spinlock implementation; required. */ +PT_EI long int +testandset (int *spinlock) +{ + int ret; + + __asm__ __volatile__( + " la 1,%1\n" + " lhi 0,1\n" + " l %0,%1\n" + "0: cs %0,0,0(1)\n" + " jl 0b" + : "=&d" (ret), "+m" (*spinlock) + : : "0", "1", "cc"); + + return ret; +} + + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#define CURRENT_STACK_FRAME stack_pointer +register char * stack_pointer __asm__ ("15"); + +#ifdef USE_TLS +/* Return the thread descriptor for the current thread. */ +# define THREAD_SELF ((pthread_descr) __builtin_thread_pointer ()) + +/* Initialize the thread-unique value. */ +#define INIT_THREAD_SELF(descr, nr) __builtin_set_thread_pointer (descr) +#else +/* Return the thread descriptor for the current thread. + S/390 registers uses access register 0 as "thread register". */ +#define THREAD_SELF ({ \ + register pthread_descr __self; \ + __asm__ ("ear %0,%%a0" : "=d" (__self) ); \ + __self; \ +}) + +/* Initialize the thread-unique value. */ +#define INIT_THREAD_SELF(descr, nr) ({ \ + __asm__ ("sar %%a0,%0" : : "d" (descr) ); \ +}) +#endif + +/* Access to data in the thread descriptor is easy. */ +#define THREAD_GETMEM(descr, member) \ + ((void) sizeof (descr), THREAD_SELF->member) +#define THREAD_GETMEM_NC(descr, member) \ + ((void) sizeof (descr), THREAD_SELF->member) +#define THREAD_SETMEM(descr, member, value) \ + ((void) sizeof (descr), THREAD_SELF->member = (value)) +#define THREAD_SETMEM_NC(descr, member, value) \ + ((void) sizeof (descr), THREAD_SELF->member = (value)) + +/* We want the OS to assign stack addresses. */ +#define FLOATING_STACKS 1 + +/* Maximum size of the stack if the rlimit is unlimited. */ +#define ARCH_STACK_MAX_SIZE 8*1024*1024 + +/* Compare-and-swap for semaphores. */ + +#define HAS_COMPARE_AND_SWAP + +PT_EI int +__compare_and_swap(long int *p, long int oldval, long int newval) +{ + int retval; + + __asm__ __volatile__( + " la 1,%1\n" + " lr 0,%2\n" + " cs 0,%3,0(1)\n" + " ipm %0\n" + " srl %0,28\n" + "0:" + : "=&d" (retval), "+m" (*p) + : "d" (oldval) , "d" (newval) + : "cc", "0", "1" ); + return retval == 0; +} + +#endif /* pt-machine.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/s390/s390-64/pt-machine.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/s390/s390-64/pt-machine.h new file mode 100644 index 00000000..187e1f87 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/s390/s390-64/pt-machine.h @@ -0,0 +1,125 @@ +/* Machine-dependent pthreads configuration and inline functions. + 64 bit S/390 version. + Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. + Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com). + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _PT_MACHINE_H +#define _PT_MACHINE_H 1 + +#ifndef PT_EI +# define PT_EI __extern_always_inline +#endif + +extern long int testandset (int *spinlock); +extern int __compare_and_swap (long int *p, long int oldval, long int newval); + +/* For multiprocessor systems, we want to ensure all memory accesses + are completed before we reset a lock. On other systems, we still + need to make sure that the compiler has flushed everything to memory. */ +#define MEMORY_BARRIER() __asm__ __volatile__ ("bcr 15,0" : : : "memory") + +/* Spinlock implementation; required. */ +PT_EI long int +testandset (int *spinlock) +{ + int ret; + + __asm__ __volatile__( + " la 1,%1\n" + " lhi 0,1\n" + " l %0,%1\n" + "0: cs %0,0,0(1)\n" + " jl 0b" + : "=&d" (ret), "+m" (*spinlock) + : : "0", "1", "cc"); + + return ret; +} + + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#define CURRENT_STACK_FRAME stack_pointer +register char * stack_pointer __asm__ ("15"); + +#ifdef USE_TLS +/* Return the thread descriptor for the current thread. */ +# define THREAD_SELF ((pthread_descr) __builtin_thread_pointer ()) + +/* Initialize the thread-unique value. */ +#define INIT_THREAD_SELF(descr, nr) __builtin_set_thread_pointer (descr) +#else +/* Return the thread descriptor for the current thread. + 64 bit S/390 uses access register 0 and 1 as "thread register". */ +#define THREAD_SELF ({ \ + register pthread_descr __self; \ + __asm__ (" ear %0,%%a0\n" \ + " sllg %0,%0,32\n" \ + " ear %0,%%a1\n" \ + : "=d" (__self) ); \ + __self; \ +}) + +/* Initialize the thread-unique value. */ +#define INIT_THREAD_SELF(descr, nr) ({ \ + __asm__ (" sar %%a1,%0\n" \ + " srlg 0,%0,32\n" \ + " sar %%a0,0\n" \ + : : "d" (descr) : "0" ); \ +}) +#endif + +/* Access to data in the thread descriptor is easy. */ +#define THREAD_GETMEM(descr, member) \ + ((void) sizeof (descr), THREAD_SELF->member) +#define THREAD_GETMEM_NC(descr, member) \ + ((void) sizeof (descr), THREAD_SELF->member) +#define THREAD_SETMEM(descr, member, value) \ + ((void) sizeof (descr), THREAD_SELF->member = (value)) +#define THREAD_SETMEM_NC(descr, member, value) \ + ((void) sizeof (descr), THREAD_SELF->member = (value)) + +/* We want the OS to assign stack addresses. */ +#define FLOATING_STACKS 1 + +/* Maximum size of the stack if the rlimit is unlimited. */ +#define ARCH_STACK_MAX_SIZE 8*1024*1024 + +/* Compare-and-swap for semaphores. */ + +#define HAS_COMPARE_AND_SWAP + +PT_EI int +__compare_and_swap(long int *p, long int oldval, long int newval) +{ + int retval; + + __asm__ __volatile__( + " lgr 0,%2\n" + " csg 0,%3,%1\n" + " ipm %0\n" + " srl %0,28\n" + "0:" + : "=&d" (retval), "+m" (*p) + : "d" (oldval) , "d" (newval) + : "cc", "0"); + return retval == 0; +} + +#endif /* pt-machine.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/s390/tcb-offsets.sym b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/s390/tcb-offsets.sym new file mode 100644 index 00000000..aee6be25 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/s390/tcb-offsets.sym @@ -0,0 +1,4 @@ +#include +#include + +MULTIPLE_THREADS_OFFSET offsetof (tcbhead_t, multiple_threads) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/s390/tls.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/s390/tls.h new file mode 100644 index 00000000..f750f2d6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/s390/tls.h @@ -0,0 +1,145 @@ +/* Definitions for thread-local data handling. linuxthreads/s390 version. + Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _TLS_H +#define _TLS_H + +#ifndef __ASSEMBLER__ + +# include +# include +# include + +/* Type for the dtv. */ +typedef union dtv +{ + size_t counter; + struct + { + void *val; + bool is_static; + } pointer; +} dtv_t; + +typedef struct +{ + void *tcb; /* Pointer to the TCB. Not necessary the + thread descriptor used by libpthread. */ + dtv_t *dtv; + void *self; /* Pointer to the thread descriptor. */ + int multiple_threads; +} tcbhead_t; + +#else /* __ASSEMBLER__ */ +# include +#endif /* __ASSEMBLER__ */ + +/* TLS is always supported if the tools support it. There are no + kernel dependencies. To avoid bothering with the TLS support code + at all, use configure --without-tls. + + We need USE_TLS to be consistently defined, for ldsodefs.h + conditionals. */ + +#ifdef HAVE_TLS_SUPPORT + +/* Signal that TLS support is available. */ +# define USE_TLS 1 + +# ifndef __ASSEMBLER__ +/* Get system call information. */ +# include + + +/* Get the thread descriptor definition. */ +# include + +/* This is the size of the initial TCB. */ +# define TLS_INIT_TCB_SIZE sizeof (tcbhead_t) + +/* Alignment requirements for the initial TCB. */ +# define TLS_INIT_TCB_ALIGN __alignof__ (tcbhead_t) + +/* This is the size of the TCB. */ +# define TLS_TCB_SIZE sizeof (struct _pthread_descr_struct) + +/* Alignment requirements for the TCB. */ +# define TLS_TCB_ALIGN __alignof__ (struct _pthread_descr_struct) + +/* The TCB can have any size and the memory following the address the + thread pointer points to is unspecified. Allocate the TCB there. */ +# define TLS_TCB_AT_TP 1 + + +/* Install the dtv pointer. The pointer passed is to the element with + index -1 which contain the length. */ +# define INSTALL_DTV(descr, dtvp) \ + ((tcbhead_t *) (descr))->dtv = (dtvp) + 1 + +/* Install new dtv for current thread. */ +# define INSTALL_NEW_DTV(dtv) \ + (((tcbhead_t *) __builtin_thread_pointer ())->dtv = (dtv)) + +/* Return dtv of given thread descriptor. */ +# define GET_DTV(descr) \ + (((tcbhead_t *) (descr))->dtv) + +/* Code to initially initialize the thread pointer. This might need + special attention since 'errno' is not yet available and if the + operation can cause a failure 'errno' must not be touched. + + The value of this macro is null if successful, or an error string. */ +# define TLS_INIT_TP(descr, secondcall) \ + ({ \ + void *_descr = (descr); \ + tcbhead_t *head = _descr; \ + \ + head->tcb = _descr; \ + /* For now the thread descriptor is at the same address. */ \ + head->self = _descr; \ + \ + __builtin_set_thread_pointer (_descr); \ + NULL; \ + }) + +/* Return the address of the dtv for the current thread. */ +# define THREAD_DTV() \ + (((tcbhead_t *) __builtin_thread_pointer ())->dtv) + +# endif /* __ASSEMBLER__ */ + +#else /* HAVE_TLS_SUPPORT && (FLOATING_STACKS || !IS_IN_libpthread) */ + +# ifndef __ASSEMBLER__ + +/* Get the thread descriptor definition. */ +# include + +# define NONTLS_INIT_TP \ + do { \ + static const tcbhead_t nontls_init_tp \ + = { .multiple_threads = 0 }; \ + INIT_THREAD_SELF (&nontls_init_tp, 0); \ + } while (0) + +# endif /* __ASSEMBLER__ */ + +#endif /* HAVE_TLS_SUPPORT && (FLOATING_STACKS || !IS_IN_libpthread) */ + +#endif /* tls.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/sh/pspinlock.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/sh/pspinlock.c new file mode 100644 index 00000000..c4e333a7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/sh/pspinlock.c @@ -0,0 +1,80 @@ +/* POSIX spinlock implementation. SH version. + Copyright (C) 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include "internals.h" + +int +__pthread_spin_lock (pthread_spinlock_t *lock) +{ + unsigned int val; + + do + __asm__ __volatile__ ("tas.b @%1; movt %0" + : "=r" (val) + : "r" (lock) + : "memory"); + while (val == 0); + + return 0; +} +weak_alias (__pthread_spin_lock, pthread_spin_lock) + + +int +__pthread_spin_trylock (pthread_spinlock_t *lock) +{ + unsigned int val; + + __asm__ __volatile__ ("tas.b @%1; movt %0" + : "=r" (val) + : "r" (lock) + : "memory"); + return val ? 0 : EBUSY; +} +weak_alias (__pthread_spin_trylock, pthread_spin_trylock) + + +int +__pthread_spin_unlock (pthread_spinlock_t *lock) +{ + return *lock = 0; +} +weak_alias (__pthread_spin_unlock, pthread_spin_unlock) + + +int +__pthread_spin_init (pthread_spinlock_t *lock, int pshared) +{ + /* We can ignore the `pshared' parameter. Since we are busy-waiting + all processes which can access the memory location `lock' points + to can use the spinlock. */ + return *lock = 0; +} +weak_alias (__pthread_spin_init, pthread_spin_init) + + +int +__pthread_spin_destroy (pthread_spinlock_t *lock) +{ + /* Nothing to do. */ + return 0; +} +weak_alias (__pthread_spin_destroy, pthread_spin_destroy) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/sh/pt-machine.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/sh/pt-machine.h new file mode 100644 index 00000000..793f80b2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/sh/pt-machine.h @@ -0,0 +1,82 @@ +/* Machine-dependent pthreads configuration and inline functions. + SuperH version. + Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Niibe Yutaka . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _PT_MACHINE_H +#define _PT_MACHINE_H 1 + +#include + +#ifndef __ASSEMBLER__ +#ifndef PT_EI +# define PT_EI __extern_always_inline +#endif + +extern long int testandset (int *spinlock); + +/* Spinlock implementation; required. */ +PT_EI long int +testandset (int *spinlock) +{ + int ret; + + __asm__ __volatile__( + "tas.b @%1\n\t" + "movt %0" + : "=r" (ret) + : "r" (spinlock) + : "memory", "cc"); + + return (ret == 0); +} + +/* We want the OS to assign stack addresses. */ +#define FLOATING_STACKS 1 + +/* Maximum size of the stack if the rlimit is unlimited. */ +#define ARCH_STACK_MAX_SIZE 32*1024*1024 + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#define CURRENT_STACK_FRAME stack_pointer +register char * stack_pointer __asm__ ("r15"); + +/* Return the thread descriptor for the current thread. */ +struct _pthread_descr_struct; +#define THREAD_SELF \ + ({ struct _pthread_descr_struct *self; \ + __asm__("stc gbr,%0" : "=r" (self)); self;}) + +/* Initialize the thread-unique value. */ +#define INIT_THREAD_SELF(descr, nr) \ + ({ __asm__ __volatile__("ldc %0,gbr" : : "r" (descr));}) + +/* Access to data in the thread descriptor is easy. */ +#define THREAD_GETMEM(descr, member) \ + ((void) sizeof (descr), THREAD_SELF->member) +#define THREAD_GETMEM_NC(descr, member) \ + ((void) sizeof (descr), THREAD_SELF->member) +#define THREAD_SETMEM(descr, member, value) \ + ((void) sizeof (descr), THREAD_SELF->member = (value)) +#define THREAD_SETMEM_NC(descr, member, value) \ + ((void) sizeof (descr), THREAD_SELF->member = (value)) +#endif /* __ASSEMBLER__ */ + +#endif /* pt-machine.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/sh/tcb-offsets.sym b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/sh/tcb-offsets.sym new file mode 100644 index 00000000..328eb057 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/sh/tcb-offsets.sym @@ -0,0 +1,10 @@ +#include +#include + +-- +#ifdef USE_TLS +MULTIPLE_THREADS_OFFSET offsetof (struct _pthread_descr_struct, p_multiple_threads) +TLS_PRE_TCB_SIZE sizeof (struct _pthread_descr_struct) +#else +MULTIPLE_THREADS_OFFSET offsetof (tcbhead_t, multiple_threads) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/sh/tls.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/sh/tls.h new file mode 100644 index 00000000..350d129d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/sh/tls.h @@ -0,0 +1,159 @@ +/* Definition for thread-local data handling. linuxthreads/SH version. + Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _TLS_H +#define _TLS_H + +# include + +#ifndef __ASSEMBLER__ +# include +# include +# include + +/* Type for the dtv. */ +typedef union dtv +{ + size_t counter; + struct + { + void *val; + bool is_static; + } pointer; +} dtv_t; + +#else /* __ASSEMBLER__ */ +# include +#endif /* __ASSEMBLER__ */ + + +/* We can support TLS only if the floating-stack support is available. */ +#if defined HAVE_TLS_SUPPORT \ + && (defined FLOATING_STACKS || !defined IS_IN_libpthread) + +/* Signal that TLS support is available. */ +# define USE_TLS 1 + +/* Include padding in _pthread_descr_struct so that libc can find p_errno, + if libpthread will only include the padding because of the !IS_IN_libpthread + check. */ +#ifndef FLOATING_STACKS +# define INCLUDE_TLS_PADDING 1 +#endif + +# ifndef __ASSEMBLER__ + +typedef struct +{ + dtv_t *dtv; + void *private; +} tcbhead_t; + +/* This is the size of the initial TCB. */ +# define TLS_INIT_TCB_SIZE sizeof (tcbhead_t) + +/* Alignment requirements for the initial TCB. */ +# define TLS_INIT_TCB_ALIGN __alignof__ (tcbhead_t) + +/* This is the size of the TCB. */ +# define TLS_TCB_SIZE sizeof (tcbhead_t) + +/* This is the size we need before TCB. */ +# define TLS_PRE_TCB_SIZE sizeof (struct _pthread_descr_struct) + +/* Alignment requirements for the TCB. */ +# define TLS_TCB_ALIGN __alignof__ (struct _pthread_descr_struct) + +/* The TLS blocks start right after the TCB. */ +# define TLS_DTV_AT_TP 1 + +/* Install the dtv pointer. The pointer passed is to the element with + index -1 which contain the length. */ +# define INSTALL_DTV(tcbp, dtvp) \ + ((tcbhead_t *) (tcbp))->dtv = dtvp + 1 + +/* Install new dtv for current thread. */ +# define INSTALL_NEW_DTV(dtv) \ + ({ tcbhead_t *__tcbp; \ + __asm__ __volatile__ ("stc gbr,%0" : "=r" (__tcbp)); \ + __tcbp->dtv = (dtv);}) + +/* Return dtv of given thread descriptor. */ +# define GET_DTV(tcbp) \ + (((tcbhead_t *) (tcbp))->dtv) + +/* Code to initially initialize the thread pointer. This might need + special attention since 'errno' is not yet available and if the + operation can cause a failure 'errno' must not be touched. */ +# define TLS_INIT_TP(tcbp, secondcall) \ + ({ __asm__ __volatile__ ("ldc %0,gbr" : : "r" (tcbp)); 0; }) + +/* Return the address of the dtv for the current thread. */ +# define THREAD_DTV() \ + ({ tcbhead_t *__tcbp; \ + __asm__ __volatile__ ("stc gbr,%0" : "=r" (__tcbp)); \ + __tcbp->dtv;}) + +/* Return the thread descriptor for the current thread. */ +# undef THREAD_SELF +# define THREAD_SELF \ + ({ struct _pthread_descr_struct *__self; \ + __asm__ ("stc gbr,%0" : "=r" (__self)); \ + __self - 1;}) + +# undef INIT_THREAD_SELF +# define INIT_THREAD_SELF(descr, nr) \ + ({ struct _pthread_descr_struct *__self = (void *) descr; \ + __asm__ __volatile__ ("ldc %0,gbr" : : "r" (__self + 1)); \ + 0; }) + +# define TLS_MULTIPLE_THREADS_IN_TCB 1 + +/* Get the thread descriptor definition. This must be after the + the definition of THREAD_SELF for TLS. */ +# include + +# endif /* __ASSEMBLER__ */ + +#else + +# ifndef __ASSEMBLER__ + +typedef struct +{ + void *tcb; + dtv_t *dtv; + void *self; + int multiple_threads; +} tcbhead_t; + +/* Get the thread descriptor definition. */ +# include + +# define NONTLS_INIT_TP \ + do { \ + static const tcbhead_t nontls_init_tp = { .multiple_threads = 0 }; \ + __asm__ __volatile__ ("ldc %0,gbr" : : "r" (&nontls_init_tp)); \ + } while (0) + +# endif /* __ASSEMBLER__ */ + +#endif /* HAVE_TLS_SUPPORT && (FLOATING_STACKS || !IS_IN_libpthread) */ + +#endif /* tls.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/sparc/pspinlock.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/sparc/pspinlock.c new file mode 100644 index 00000000..72a9af5b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/sparc/pspinlock.c @@ -0,0 +1,14 @@ +#include +#include + +#if __WORDSIZE == 32 + +# if defined(__CONFIG_SPARC_V9B__) +# include "sparc32/sparcv9b/pspinlock.c" +# else +# include "sparc32/pspinlock.c" +# endif + +#else +# include "sparc64/pspinlock.c" +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/sparc/pt-machine.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/sparc/pt-machine.h new file mode 100644 index 00000000..ab90810f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/sparc/pt-machine.h @@ -0,0 +1,8 @@ +#include +#include + +#if __WORDSIZE == 32 +# include "sparc32/pt-machine.h" +#else +# include "sparc64/pt-machine.h" +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/sparc/sparc32/pspinlock.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/sparc/sparc32/pspinlock.c new file mode 100644 index 00000000..812c7ff2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/sparc/sparc32/pspinlock.c @@ -0,0 +1,88 @@ +/* POSIX spinlock implementation. SPARC32 version. + Copyright (C) 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include "internals.h" + +/* This implementation is similar to the one used in the Linux kernel. */ +int +__pthread_spin_lock (pthread_spinlock_t *lock) +{ + __asm__ __volatile__ + ("1: ldstub [%0], %%g2\n" + " orcc %%g2, 0x0, %%g0\n" + " bne,a 2f\n" + " ldub [%0], %%g2\n" + ".subsection 2\n" + "2: orcc %%g2, 0x0, %%g0\n" + " bne,a 2b\n" + " ldub [%0], %%g2\n" + " b,a 1b\n" + ".previous" + : /* no outputs */ + : "r" (lock) + : "g2", "memory", "cc"); + return 0; +} +weak_alias (__pthread_spin_lock, pthread_spin_lock) + + +int +__pthread_spin_trylock (pthread_spinlock_t *lock) +{ + int result; + __asm__ __volatile__ + ("ldstub [%1], %0" + : "=r" (result) + : "r" (lock) + : "memory"); + return result == 0 ? 0 : EBUSY; +} +weak_alias (__pthread_spin_trylock, pthread_spin_trylock) + + +int +__pthread_spin_unlock (pthread_spinlock_t *lock) +{ + *lock = 0; + return 0; +} +weak_alias (__pthread_spin_unlock, pthread_spin_unlock) + + +int +__pthread_spin_init (pthread_spinlock_t *lock, int pshared) +{ + /* We can ignore the `pshared' parameter. Since we are busy-waiting + all processes which can access the memory location `lock' points + to can use the spinlock. */ + *lock = 0; + return 0; +} +weak_alias (__pthread_spin_init, pthread_spin_init) + + +int +__pthread_spin_destroy (pthread_spinlock_t *lock) +{ + /* Nothing to do. */ + return 0; +} +weak_alias (__pthread_spin_destroy, pthread_spin_destroy) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/sparc/sparc32/pt-machine.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/sparc/sparc32/pt-machine.h new file mode 100644 index 00000000..43c05f2a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/sparc/sparc32/pt-machine.h @@ -0,0 +1,83 @@ +/* Machine-dependent pthreads configuration and inline functions. + sparc version. + Copyright (C) 1996-1998, 2000-2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _PT_MACHINE_H +#define _PT_MACHINE_H 1 + +#ifndef PT_EI +# define PT_EI __extern_always_inline +#endif + +extern long int testandset (int *spinlock); +extern int __compare_and_swap (long int *p, long int oldval, long int newval); + +/* Spinlock implementation; required. */ +PT_EI long int +testandset (int *spinlock) +{ + int ret; + + __asm__ __volatile__("ldstub %1,%0" + : "=r"(ret), "=m"(*spinlock) + : "m"(*spinlock)); + + return ret; +} + + +/* Memory barrier; default is to do nothing */ +#define MEMORY_BARRIER() __asm__ __volatile__("stbar" : : : "memory") + + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#define CURRENT_STACK_FRAME (stack_pointer + (2 * 64)) +register char *stack_pointer __asm__("%sp"); + + +/* Registers %g6 and %g7 are reserved by the ABI for "system use". + %g7 is specified in the TLS ABI as thread pointer -- we do the same. */ +struct _pthread_descr_struct; +register struct _pthread_descr_struct *__thread_self __asm__("%g7"); + +/* Return the thread descriptor for the current thread. */ +#define THREAD_SELF __thread_self + +/* Initialize the thread-unique value. */ +#define INIT_THREAD_SELF(descr, nr) (__thread_self = (descr)) + +/* Access to data in the thread descriptor is easy. */ +#define THREAD_GETMEM(descr, member) \ + ((void) sizeof (descr), THREAD_SELF->member) +#define THREAD_GETMEM_NC(descr, member) \ + ((void) sizeof (descr), THREAD_SELF->member) +#define THREAD_SETMEM(descr, member, value) \ + ((void) sizeof (descr), THREAD_SELF->member = (value)) +#define THREAD_SETMEM_NC(descr, member, value) \ + ((void) sizeof (descr), THREAD_SELF->member = (value)) + +/* We want the OS to assign stack addresses. */ +#define FLOATING_STACKS 1 + +/* Maximum size of the stack if the rlimit is unlimited. */ +#define ARCH_STACK_MAX_SIZE 8*1024*1024 + +#endif /* pt-machine.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/sparc/sparc32/sparcv9/pspinlock.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/sparc/sparc32/sparcv9/pspinlock.c new file mode 100644 index 00000000..7e55df41 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/sparc/sparc32/sparcv9/pspinlock.c @@ -0,0 +1,94 @@ +/* POSIX spinlock implementation. SPARC v9 version. + Copyright (C) 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include "internals.h" + + +/* This implementation is similar to the one used in the Linux kernel. */ +int +__pthread_spin_lock (pthread_spinlock_t *lock) +{ + __asm__ __volatile__ + ("1: ldstub [%0], %%g2\n" + " brnz,pn %%g2, 2f\n" + " membar #StoreLoad | #StoreStore\n" + ".subsection 2\n" + "2: ldub [%0], %%g2\n" + " brnz,pt %%g2, 2b\n" + " membar #LoadLoad\n" + " b,a,pt %%xcc, 1b\n" + ".previous" + : /* no outputs */ + : "r" (lock) + : "g2", "memory"); + return 0; +} +weak_alias (__pthread_spin_lock, pthread_spin_lock) + + +int +__pthread_spin_trylock (pthread_spinlock_t *lock) +{ + int result; + __asm__ __volatile__ + ("ldstub [%1], %0\n" + "membar #StoreLoad | #StoreStore" + : "=r" (result) + : "r" (lock) + : "memory"); + return result == 0 ? 0 : EBUSY; +} +weak_alias (__pthread_spin_trylock, pthread_spin_trylock) + + +int +__pthread_spin_unlock (pthread_spinlock_t *lock) +{ + __asm__ __volatile__ + ("membar #StoreStore | #LoadStore\n" + "stb %%g0, [%0]" + : + : "r" (lock) + : "memory"); + return 0; +} +weak_alias (__pthread_spin_unlock, pthread_spin_unlock) + + +int +__pthread_spin_init (pthread_spinlock_t *lock, int pshared) +{ + /* We can ignore the `pshared' parameter. Since we are busy-waiting + all processes which can access the memory location `lock' points + to can use the spinlock. */ + *lock = 0; + return 0; +} +weak_alias (__pthread_spin_init, pthread_spin_init) + + +int +__pthread_spin_destroy (pthread_spinlock_t *lock) +{ + /* Nothing to do. */ + return 0; +} +weak_alias (__pthread_spin_destroy, pthread_spin_destroy) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/sparc/sparc64/pspinlock.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/sparc/sparc64/pspinlock.c new file mode 100644 index 00000000..e0c350e6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/sparc/sparc64/pspinlock.c @@ -0,0 +1,93 @@ +/* POSIX spinlock implementation. SPARC64 version. + Copyright (C) 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include "internals.h" + +/* This implementation is similar to the one used in the Linux kernel. */ +int +__pthread_spin_lock (pthread_spinlock_t *lock) +{ + __asm__ __volatile__ + ("1: ldstub [%0], %%g5\n" + " brnz,pn %%g5, 2f\n" + " membar #StoreLoad | #StoreStore\n" + ".subsection 2\n" + "2: ldub [%0], %%g5\n" + " brnz,pt %%g5, 2b\n" + " membar #LoadLoad\n" + " b,a,pt %%xcc, 1b\n" + ".previous" + : /* no outputs */ + : "r" (lock) + : "g5", "memory"); + return 0; +} +weak_alias (__pthread_spin_lock, pthread_spin_lock) + + +int +__pthread_spin_trylock (pthread_spinlock_t *lock) +{ + int result; + __asm__ __volatile__ + ("ldstub [%1], %0\n" + "membar #StoreLoad | #StoreStore" + : "=r" (result) + : "r" (lock) + : "memory"); + return result == 0 ? 0 : EBUSY; +} +weak_alias (__pthread_spin_trylock, pthread_spin_trylock) + + +int +__pthread_spin_unlock (pthread_spinlock_t *lock) +{ + __asm__ __volatile__ + ("membar #StoreStore | #LoadStore\n" + "stb %%g0, [%0]" + : + : "r" (lock) + : "memory"); + return 0; +} +weak_alias (__pthread_spin_unlock, pthread_spin_unlock) + + +int +__pthread_spin_init (pthread_spinlock_t *lock, int pshared) +{ + /* We can ignore the `pshared' parameter. Since we are busy-waiting + all processes which can access the memory location `lock' points + to can use the spinlock. */ + *lock = 0; + return 0; +} +weak_alias (__pthread_spin_init, pthread_spin_init) + + +int +__pthread_spin_destroy (pthread_spinlock_t *lock) +{ + /* Nothing to do. */ + return 0; +} +weak_alias (__pthread_spin_destroy, pthread_spin_destroy) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/sparc/sparc64/pt-machine.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/sparc/sparc64/pt-machine.h new file mode 100644 index 00000000..815d70e8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/sparc/sparc64/pt-machine.h @@ -0,0 +1,105 @@ +/* Machine-dependent pthreads configuration and inline functions. + Sparc v9 version. + Copyright (C) 1997-2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If + not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef _PT_MACHINE_H +#define _PT_MACHINE_H 1 + +#ifndef PT_EI +# define PT_EI __extern_always_inline +#endif + +extern long int testandset (int *spinlock); +extern int __compare_and_swap (long int *p, long int oldval, long int newval); + +/* Spinlock implementation; required. */ +PT_EI long int +testandset (int *spinlock) +{ + int ret; + + __asm__ __volatile__("ldstub %1,%0" + : "=r" (ret), "=m" (*spinlock) : "m" (*spinlock)); + + return ret; +} + + +/* Memory barrier; default is to do nothing */ +#define MEMORY_BARRIER() \ + __asm__ __volatile__("membar #LoadLoad | #LoadStore | #StoreLoad | #StoreStore" : : : "memory") +/* Read barrier. */ +#define READ_MEMORY_BARRIER() \ + __asm__ __volatile__("membar #LoadLoad | #LoadStore" : : : "memory") +/* Write barrier. */ +#define WRITE_MEMORY_BARRIER() \ + __asm__ __volatile__("membar #StoreLoad | #StoreStore" : : : "memory") + + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#define CURRENT_STACK_FRAME (stack_pointer + (2 * 128)) +register char *stack_pointer __asm__ ("%sp"); + + +/* Registers %g6 and %g7 are reserved by the ABI for "system use". The + TLS ABI specifies %g7 as the thread pointer. */ +struct _pthread_descr_struct; +register struct _pthread_descr_struct *__thread_self __asm__ ("%g7"); + +/* Return the thread descriptor for the current thread. */ +#define THREAD_SELF __thread_self + +/* Initialize the thread-unique value. */ +#define INIT_THREAD_SELF(descr, nr) (__thread_self = (descr)) + + +/* Compare-and-swap for semaphores. */ + +#define HAS_COMPARE_AND_SWAP +PT_EI int +__compare_and_swap (long int *p, long int oldval, long int newval) +{ + long int readval; + + __asm__ __volatile__ ("casx [%4], %2, %0" + : "=r"(readval), "=m"(*p) + : "r"(oldval), "m"(*p), "r"(p), "0"(newval)); + MEMORY_BARRIER(); + return readval == oldval; +} + +/* Access to data in the thread descriptor is easy. */ +#define THREAD_GETMEM(descr, member) \ + ((void) sizeof (descr), THREAD_SELF->member) +#define THREAD_GETMEM_NC(descr, member) \ + ((void) sizeof (descr), THREAD_SELF->member) +#define THREAD_SETMEM(descr, member, value) \ + ((void) sizeof (descr), THREAD_SELF->member = (value)) +#define THREAD_SETMEM_NC(descr, member, value) \ + ((void) sizeof (descr), THREAD_SELF->member = (value)) + +/* We want the OS to assign stack addresses. */ +#define FLOATING_STACKS 1 + +/* Maximum size of the stack if the rlimit is unlimited. */ +#define ARCH_STACK_MAX_SIZE 32*1024*1024 + +#endif /* pt-machine.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/sparc/tcb-offsets.sym b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/sparc/tcb-offsets.sym new file mode 100644 index 00000000..aee6be25 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/sparc/tcb-offsets.sym @@ -0,0 +1,4 @@ +#include +#include + +MULTIPLE_THREADS_OFFSET offsetof (tcbhead_t, multiple_threads) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/sparc/tls.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/sparc/tls.h new file mode 100644 index 00000000..2df97d61 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/sparc/tls.h @@ -0,0 +1,115 @@ +/* Definitions for thread-local data handling. linuxthreads/sparc version. + Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _TLS_H +#define _TLS_H + +#ifndef __ASSEMBLER__ + +# include +# include +# include + +/* Type for the dtv. */ +typedef union dtv +{ + size_t counter; + struct + { + void *val; + bool is_static; + } pointer; +} dtv_t; + +typedef struct +{ + void *tcb; /* Pointer to the TCB. Not necessary the + thread descriptor used by libpthread. */ + dtv_t *dtv; + void *self; /* Pointer to the thread descriptor. */ + int multiple_threads; +} tcbhead_t; + +#else /* __ASSEMBLER__ */ +# include +#endif /* __ASSEMBLER__ */ + +#ifdef HAVE_TLS_SUPPORT + +/* Signal that TLS support is available. */ +# define USE_TLS 1 + +# ifndef __ASSEMBLER__ +/* Get system call information. */ +# include + +/* Get the thread descriptor definition. */ +# include + +/* This is the size of the initial TCB. */ +# define TLS_INIT_TCB_SIZE sizeof (tcbhead_t) + +/* Alignment requirements for the initial TCB. */ +# define TLS_INIT_TCB_ALIGN __alignof__ (tcbhead_t) + +/* This is the size of the TCB. */ +# define TLS_TCB_SIZE sizeof (struct _pthread_descr_struct) + +/* Alignment requirements for the TCB. */ +# define TLS_TCB_ALIGN __alignof__ (struct _pthread_descr_struct) + +/* The TCB can have any size and the memory following the address the + thread pointer points to is unspecified. Allocate the TCB there. */ +# define TLS_TCB_AT_TP 1 + +/* Install the dtv pointer. The pointer passed is to the element with + index -1 which contain the length. */ +# define INSTALL_DTV(descr, dtvp) \ + ((tcbhead_t *) (descr))->dtv = (dtvp) + 1 + +/* Install new dtv for current thread. */ +# define INSTALL_NEW_DTV(DTV) \ + (((tcbhead_t *) __thread_self)->dtv = (DTV)) + +/* Return dtv of given thread descriptor. */ +# define GET_DTV(descr) \ + (((tcbhead_t *) (descr))->dtv) + +/* Code to initially initialize the thread pointer. */ +# define TLS_INIT_TP(descr, secondcall) \ + (__thread_self = (__typeof (__thread_self)) (descr), NULL) + +/* Return the address of the dtv for the current thread. */ +# define THREAD_DTV() \ + (((tcbhead_t *) __thread_self)->dtv) + +# endif + +#else + +# define NONTLS_INIT_TP \ + do { \ + static const tcbhead_t nontls_init_tp \ + = { .multiple_threads = 0 }; \ + __thread_self = (__typeof (__thread_self)) &nontls_init_tp; \ + } while (0) + +#endif /* USE_TLS */ + +#endif /* tls.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/.cvsignore b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/.cvsignore new file mode 100644 index 00000000..7ee8f596 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/.cvsignore @@ -0,0 +1,2 @@ +.cvsignore +*.os diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/allocalim.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/allocalim.h new file mode 100644 index 00000000..a3f303ca --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/allocalim.h @@ -0,0 +1,26 @@ +/* Determine whether block of given size can be allocated on the stack or not. + Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + +__extern_always_inline int __libc_use_alloca (size_t size) +{ + return (__builtin_expect (size <= PTHREAD_STACK_MIN / 4, 1) + || __libc_alloca_cutoff (size)); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/allocrtsig.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/allocrtsig.c new file mode 100644 index 00000000..b9ada641 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/allocrtsig.c @@ -0,0 +1,87 @@ +/* Handle real-time signal allocation. + Copyright (C) 1997,98,99,2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +/* Sanity check. */ +#if !defined __SIGRTMIN || (__SIGRTMAX - __SIGRTMIN) < 3 +# error "This must not happen" +#endif + +static int current_rtmin; +static int current_rtmax; + +static int initialized; + +#include + +static void +init (void) +{ + if (!kernel_has_rtsig ()) + { + current_rtmin = -1; + current_rtmax = -1; + } + else + { + current_rtmin = __SIGRTMIN + 3; + current_rtmax = __SIGRTMAX; + } + initialized = 1; +} + +/* Return number of available real-time signal with highest priority. */ +int +__libc_current_sigrtmin (void) +{ + if (!initialized) + init (); + return current_rtmin; +} +strong_alias (__libc_current_sigrtmin, __libc_current_sigrtmin_private) +libc_hidden_def (__libc_current_sigrtmin) + +/* Return number of available real-time signal with lowest priority. */ +int +__libc_current_sigrtmax (void) +{ + if (!initialized) + init (); + return current_rtmax; +} +strong_alias (__libc_current_sigrtmax, __libc_current_sigrtmax_private) +libc_hidden_def (__libc_current_sigrtmax) + +/* Allocate real-time signal with highest/lowest available + priority. Please note that we don't use a lock since we assume + this function to be called at program start. */ +int +__libc_allocate_rtsig (int high) +{ + if (!initialized) + init (); + if (current_rtmin == -1 || current_rtmin > current_rtmax) + /* We don't have anymore signal available. */ + return -1; + + return high ? current_rtmin++ : current_rtmax--; +} +strong_alias (__libc_allocate_rtsig, __libc_allocate_rtsig_private) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/alpha/aio_cancel.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/alpha/aio_cancel.c new file mode 100644 index 00000000..0d6da829 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/alpha/aio_cancel.c @@ -0,0 +1,33 @@ +#include + +#define aio_cancel64 XXX +#include +#undef aio_cancel64 +#include + +extern __typeof (aio_cancel) __new_aio_cancel; +extern __typeof (aio_cancel) __old_aio_cancel; + +#define aio_cancel __new_aio_cancel + +#include + +#undef aio_cancel +strong_alias (__new_aio_cancel, __new_aio_cancel64); +versioned_symbol (librt, __new_aio_cancel, aio_cancel, GLIBC_2_3); +versioned_symbol (librt, __new_aio_cancel64, aio_cancel64, GLIBC_2_3); + +#if SHLIB_COMPAT (librt, GLIBC_2_1, GLIBC_2_3) + +#undef ECANCELED +#define aio_cancel __old_aio_cancel +#define ECANCELED 125 + +#include + +#undef aio_cancel +strong_alias (__old_aio_cancel, __old_aio_cancel64); +compat_symbol (librt, __old_aio_cancel, aio_cancel, GLIBC_2_1); +compat_symbol (librt, __old_aio_cancel64, aio_cancel64, GLIBC_2_1); + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/alpha/bits/local_lim.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/alpha/bits/local_lim.h new file mode 100644 index 00000000..96893c59 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/alpha/bits/local_lim.h @@ -0,0 +1,92 @@ +/* Minimum guaranteed maximum values for system limits. Linux/Alpha version. + Copyright (C) 1993-1998,2000,2002,2003,2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* The kernel header pollutes the namespace with the NR_OPEN symbol + and defines LINK_MAX although filesystems have different maxima. A + similar thing is true for OPEN_MAX: the limit can be changed at + runtime and therefore the macro must not be defined. Remove this + after including the header if necessary. */ +#ifndef NR_OPEN +# define __undef_NR_OPEN +#endif +#ifndef LINK_MAX +# define __undef_LINK_MAX +#endif +#ifndef OPEN_MAX +# define __undef_OPEN_MAX +#endif + +/* The kernel sources contain a file with all the needed information. */ +#include + +/* Have to remove NR_OPEN? */ +#ifdef __undef_NR_OPEN +# undef NR_OPEN +# undef __undef_NR_OPEN +#endif +/* Have to remove LINK_MAX? */ +#ifdef __undef_LINK_MAX +# undef LINK_MAX +# undef __undef_LINK_MAX +#endif +/* Have to remove OPEN_MAX? */ +#ifdef __undef_OPEN_MAX +# undef OPEN_MAX +# undef __undef_OPEN_MAX +#endif + +/* The number of data keys per process. */ +#define _POSIX_THREAD_KEYS_MAX 128 +/* This is the value this implementation supports. */ +#define PTHREAD_KEYS_MAX 1024 + +/* Controlling the iterations of destructors for thread-specific data. */ +#define _POSIX_THREAD_DESTRUCTOR_ITERATIONS 4 +/* Number of iterations this implementation does. */ +#define PTHREAD_DESTRUCTOR_ITERATIONS _POSIX_THREAD_DESTRUCTOR_ITERATIONS + +/* The number of threads per process. */ +#define _POSIX_THREAD_THREADS_MAX 64 +/* This is the value this implementation supports. */ +#define PTHREAD_THREADS_MAX 16384 + +/* Maximum amount by which a process can descrease its asynchronous I/O + priority level. */ +#define AIO_PRIO_DELTA_MAX 20 + +/* Minimum size for a thread. We are free to choose a reasonable value. */ +#define PTHREAD_STACK_MIN 24576 + +/* Maximum number of POSIX timers available. */ +#define TIMER_MAX 256 + +/* Maximum number of timer expiration overruns. */ +#define DELAYTIMER_MAX 2147483647 + +/* Maximum tty name length. */ +#define TTY_NAME_MAX 32 + +/* Maximum login name length. This is arbitrary. */ +#define LOGIN_NAME_MAX 256 + +/* Maximum host name length. */ +#define HOST_NAME_MAX 64 + +/* Maximum message queue priority level. */ +#define MQ_PRIO_MAX 32768 diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/alpha/bits/typesizes.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/alpha/bits/typesizes.h new file mode 100644 index 00000000..a2724885 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/alpha/bits/typesizes.h @@ -0,0 +1,66 @@ +/* bits/typesizes.h -- underlying types for *_t. Linux/Alpha version. + Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _BITS_TYPES_H +# error "Never include directly; use instead." +#endif + +#ifndef _BITS_TYPESIZES_H +#define _BITS_TYPESIZES_H 1 + +/* See for the meaning of these macros. This file exists so + that need not vary across different GNU platforms. */ + +#define __DEV_T_TYPE __U64_TYPE +#define __UID_T_TYPE __U32_TYPE +#define __GID_T_TYPE __U32_TYPE +#define __INO_T_TYPE __U32_TYPE +#define __INO64_T_TYPE __U64_TYPE +#define __MODE_T_TYPE __U32_TYPE +#define __NLINK_T_TYPE __U32_TYPE +#define __OFF_T_TYPE __SLONGWORD_TYPE +#define __OFF64_T_TYPE __S64_TYPE +#define __PID_T_TYPE __S32_TYPE +#define __RLIM_T_TYPE __ULONGWORD_TYPE +#define __RLIM64_T_TYPE __U64_TYPE +#define __BLKCNT_T_TYPE __U32_TYPE +#define __BLKCNT64_T_TYPE __U64_TYPE +#define __FSBLKCNT_T_TYPE __S32_TYPE +#define __FSBLKCNT64_T_TYPE __S64_TYPE +#define __FSFILCNT_T_TYPE __U32_TYPE +#define __FSFILCNT64_T_TYPE __U64_TYPE +#define __ID_T_TYPE __U32_TYPE +#define __CLOCK_T_TYPE __SLONGWORD_TYPE +#define __TIME_T_TYPE __SLONGWORD_TYPE +#define __USECONDS_T_TYPE __U32_TYPE +#define __SUSECONDS_T_TYPE __S64_TYPE +#define __DADDR_T_TYPE __S32_TYPE +#define __SWBLK_T_TYPE __SLONGWORD_TYPE +#define __KEY_T_TYPE __S32_TYPE +#define __CLOCKID_T_TYPE __S32_TYPE +#define __TIMER_T_TYPE __S32_TYPE +#define __BLKSIZE_T_TYPE __U32_TYPE +#define __FSID_T_TYPE struct { int __val[2]; } +#define __SSIZE_T_TYPE __SWORD_TYPE + +/* Number of descriptors that can fit in an `fd_set'. */ +#define __FD_SETSIZE 1024 + + +#endif /* bits/typesizes.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/alpha/pt-sigsuspend.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/alpha/pt-sigsuspend.S new file mode 100644 index 00000000..91e5c867 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/alpha/pt-sigsuspend.S @@ -0,0 +1,28 @@ +/* Internal sigsuspend system call for LinuxThreads. Alpha version. + Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#undef PSEUDO_PREPARE_ARGS +#define PSEUDO_PREPARE_ARGS ldq a0, 0(a0); + + .hidden __pthread_sigsuspend +PSEUDO_NOERRNO(__pthread_sigsuspend, sigsuspend, 1) + ret +PSEUDO_END_NOERRNO(__pthread_sigsuspend) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/alpha/sysdep-cancel.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/alpha/sysdep-cancel.h new file mode 100644 index 00000000..5d686299 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/alpha/sysdep-cancel.h @@ -0,0 +1,146 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#ifndef __ASSEMBLER__ +# include +#endif + +#if !defined NOT_IN_libc || defined IS_IN_libpthread + +# ifdef PROF +# define PSEUDO_PROF \ + .set noat; \ + lda AT, _mcount; \ + jsr AT, (AT), _mcount; \ + .set at +# else +# define PSEUDO_PROF +# endif + +/* ??? Assumes that nothing comes between PSEUDO and PSEUDO_END + besides "ret". */ + +# undef PSEUDO +# define PSEUDO(name, syscall_name, args) \ + .globl name; \ + .align 4; \ + .type name, @function; \ + .usepv name, std; \ + cfi_startproc; \ +__LABEL(name) \ + ldgp gp, 0(pv); \ + PSEUDO_PROF; \ + PSEUDO_PREPARE_ARGS \ + SINGLE_THREAD_P(t0); \ + bne t0, $pseudo_cancel; \ + lda v0, SYS_ify(syscall_name); \ + call_pal PAL_callsys; \ + bne a3, SYSCALL_ERROR_LABEL; \ +__LABEL($pseudo_ret) \ + .subsection 2; \ +__LABEL($pseudo_cancel) \ + subq sp, 64, sp; \ + cfi_def_cfa_offset(64); \ + stq ra, 0(sp); \ + cfi_offset(ra, -64); \ + SAVE_ARGS_##args; \ + CENABLE; \ + LOAD_ARGS_##args; \ + lda v0, SYS_ify(syscall_name); \ + call_pal PAL_callsys; \ + stq v0, 8(sp); \ + bne a3, $multi_error; \ + CDISABLE; \ + ldq ra, 0(sp); \ + ldq v0, 8(sp); \ + addq sp, 64, sp; \ + cfi_remember_state; \ + cfi_restore(ra); \ + cfi_def_cfa_offset(0); \ + ret; \ + cfi_restore_state; \ +__LABEL($multi_error) \ + CDISABLE; \ + ldq ra, 0(sp); \ + ldq v0, 8(sp); \ + addq sp, 64, sp; \ + cfi_restore(ra); \ + cfi_def_cfa_offset(0); \ +__LABEL($syscall_error) \ + SYSCALL_ERROR_HANDLER; \ + .previous + +# undef PSEUDO_END +# define PSEUDO_END(sym) \ + .subsection 2; \ + cfi_endproc; \ + .size sym, .-sym + +# define SAVE_ARGS_0 /* Nothing. */ +# define SAVE_ARGS_1 SAVE_ARGS_0; stq a0, 8(sp) +# define SAVE_ARGS_2 SAVE_ARGS_1; stq a1, 16(sp) +# define SAVE_ARGS_3 SAVE_ARGS_2; stq a2, 24(sp) +# define SAVE_ARGS_4 SAVE_ARGS_3; stq a3, 32(sp) +# define SAVE_ARGS_5 SAVE_ARGS_4; stq a4, 40(sp) +# define SAVE_ARGS_6 SAVE_ARGS_5; stq a5, 48(sp) + +# define LOAD_ARGS_0 /* Nothing. */ +# define LOAD_ARGS_1 LOAD_ARGS_0; ldq a0, 8(sp) +# define LOAD_ARGS_2 LOAD_ARGS_1; ldq a1, 16(sp) +# define LOAD_ARGS_3 LOAD_ARGS_2; ldq a2, 24(sp) +# define LOAD_ARGS_4 LOAD_ARGS_3; ldq a3, 32(sp) +# define LOAD_ARGS_5 LOAD_ARGS_4; ldq a4, 40(sp) +# define LOAD_ARGS_6 LOAD_ARGS_5; ldq a5, 48(sp) + +# ifdef IS_IN_libpthread +# define __local_enable_asynccancel __pthread_enable_asynccancel +# define __local_disable_asynccancel __pthread_disable_asynccancel +# define __local_multiple_threads __pthread_multiple_threads +# else +# define __local_enable_asynccancel __libc_enable_asynccancel +# define __local_disable_asynccancel __libc_disable_asynccancel +# define __local_multiple_threads __libc_multiple_threads +# endif + +# ifdef __PIC__ +# define CENABLE bsr ra, __local_enable_asynccancel !samegp +# define CDISABLE bsr ra, __local_disable_asynccancel !samegp +# else +# define CENABLE jsr ra, __local_enable_asynccancel; ldgp ra, 0(gp) +# define CDISABLE jsr ra, __local_disable_asynccancel; ldgp ra, 0(gp) +# endif + +# ifndef __ASSEMBLER__ +extern int __local_multiple_threads attribute_hidden; +# define SINGLE_THREAD_P \ + __builtin_expect (__local_multiple_threads == 0, 1) +# elif defined(__PIC__) +# define SINGLE_THREAD_P(reg) ldl reg, __local_multiple_threads(gp) !gprel +# else +# define SINGLE_THREAD_P(reg) \ + ldah reg, __local_multiple_threads(gp) !gprelhigh; \ + ldl reg, __local_multiple_threads(reg) !gprellow +# endif + +#elif !defined __ASSEMBLER__ + +/* This code should never be used but we define it anyhow. */ +# define SINGLE_THREAD_P (1) + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/alpha/vfork.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/alpha/vfork.S new file mode 100644 index 00000000..cfaae106 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/alpha/vfork.S @@ -0,0 +1,70 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + + +#include + + .align 4 + .globl __vfork + .type __vfork, @function + .usepv __vfork, std + cfi_startproc +__vfork: + ldgp gp, 0(pv) + PSEUDO_PROF + +#ifdef SHARED + ldq t0, __libc_pthread_functions(gp) !gprel + bne t0, HIDDEN_JUMPTARGET (__fork) !samegp +#else + .weak pthread_create + ldq t0, pthread_create(gp) !literal + bne t0, $do_fork +#endif + + lda v0, SYS_ify(vfork) + call_pal PAL_callsys + bne a3, SYSCALL_ERROR_LABEL + ret + +#ifndef SHARED + /* Can't tail-call due to possible mismatch between GP in + fork and vfork object files. */ +$do_fork: + subq sp, 16, sp + cfi_adjust_cfa_offset(16) + stq ra, 0(sp) + cfi_offset(ra, -16) + jsr ra, HIDDEN_JUMPTARGET (__fork) + ldgp gp, 0(ra) + ldq ra, 0(sp) + addq sp, 16, sp + cfi_restore(ra) + cfi_adjust_cfa_offset(-16) + ret + +$syscall_error: + SYSCALL_ERROR_HANDLER +#endif + + cfi_endproc + .size __vfork, .-__vfork + +libc_hidden_def (__vfork) + +weak_alias (__vfork, vfork) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/arm/sysdep-cancel.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/arm/sysdep-cancel.h new file mode 100644 index 00000000..3937808d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/arm/sysdep-cancel.h @@ -0,0 +1,130 @@ +/* Copyright (C) 2003, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Phil Blundell , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#ifndef __ASSEMBLER__ +# include +#endif + +#if !defined NOT_IN_libc || defined IS_IN_libpthread + +/* We push lr onto the stack, so we have to use ldmib instead of ldmia + to find the saved arguments. */ +# ifdef __PIC__ +# undef DOARGS_5 +# undef DOARGS_6 +# undef DOARGS_7 +# define DOARGS_5 str r4, [sp, $-4]!; ldr r4, [sp, $8]; +# define DOARGS_6 mov ip, sp; stmfd sp!, {r4, r5}; ldmib ip, {r4, r5}; +# define DOARGS_7 mov ip, sp; stmfd sp!, {r4, r5, r6}; ldmib ip, {r4, r5, r6}; +# endif + +# undef PSEUDO_RET +# define PSEUDO_RET \ + ldrcc pc, [sp], $4; \ + ldr lr, [sp], $4; \ + b PLTJMP(SYSCALL_ERROR) + +# undef PSEUDO +# define PSEUDO(name, syscall_name, args) \ + .section ".text"; \ + PSEUDO_PROLOGUE; \ + ENTRY (name); \ + SINGLE_THREAD_P; \ + bne .Lpseudo_cancel; \ + DO_CALL (syscall_name, args); \ + cmn r0, $4096; \ + RETINSTR(cc, lr); \ + b PLTJMP(SYSCALL_ERROR); \ + .Lpseudo_cancel: \ + str lr, [sp, $-4]!; \ + DOCARGS_##args; /* save syscall args around CENABLE. */ \ + CENABLE; \ + mov ip, r0; /* put mask in safe place. */ \ + UNDOCARGS_##args; /* restore syscall args. */ \ + swi SYS_ify (syscall_name); /* do the call. */ \ + str r0, [sp, $-4]!; /* save syscall return value. */ \ + mov r0, ip; /* get mask back. */ \ + CDISABLE; \ + ldr r0, [sp], $4; /* retrieve return value. */ \ + UNDOC2ARGS_##args; /* fix register damage. */ \ + cmn r0, $4096; + +# define DOCARGS_0 +# define UNDOCARGS_0 +# define UNDOC2ARGS_0 + +# define DOCARGS_1 str r0, [sp, #-4]!; +# define UNDOCARGS_1 ldr r0, [sp], #4; +# define UNDOC2ARGS_1 + +# define DOCARGS_2 str r1, [sp, #-4]!; str r0, [sp, #-4]!; +# define UNDOCARGS_2 ldr r0, [sp], #4; ldr r1, [sp], #4; +# define UNDOC2ARGS_2 + +# define DOCARGS_3 str r2, [sp, #-4]!; str r1, [sp, #-4]!; str r0, [sp, #-4]!; +# define UNDOCARGS_3 ldr r0, [sp], #4; ldr r1, [sp], #4; ldr r2, [sp], #4 +# define UNDOC2ARGS_3 + +# define DOCARGS_4 stmfd sp!, {r0-r3} +# define UNDOCARGS_4 ldmfd sp!, {r0-r3} +# define UNDOC2ARGS_4 + +# define DOCARGS_5 stmfd sp!, {r0-r3} +# define UNDOCARGS_5 ldmfd sp, {r0-r3}; str r4, [sp, #-4]!; ldr r4, [sp, #24] +# define UNDOC2ARGS_5 ldr r4, [sp], #20 + +# ifdef IS_IN_libpthread +# define CENABLE bl PLTJMP(__pthread_enable_asynccancel) +# define CDISABLE bl PLTJMP(__pthread_disable_asynccancel) +# define __local_multiple_threads __pthread_multiple_threads +# else +# define CENABLE bl PLTJMP(__libc_enable_asynccancel) +# define CDISABLE bl PLTJMP(__libc_disable_asynccancel) +# define __local_multiple_threads __libc_multiple_threads +# endif + +# ifndef __ASSEMBLER__ +extern int __local_multiple_threads attribute_hidden; +# define SINGLE_THREAD_P __builtin_expect (__local_multiple_threads == 0, 1) +# else +# if !defined __PIC__ +# define SINGLE_THREAD_P \ + ldr ip, =__local_multiple_threads; \ + ldr ip, [ip]; \ + teq ip, #0; +# define PSEUDO_PROLOGUE +# else +# define SINGLE_THREAD_P \ + ldr ip, 1b; \ +2: \ + ldr ip, [pc, ip]; \ + teq ip, #0; +# define PSEUDO_PROLOGUE \ + 1: .word __local_multiple_threads - 2f - 8; +# endif +# endif + +#elif !defined __ASSEMBLER__ + +/* This code should never be used but we define it anyhow. */ +# define SINGLE_THREAD_P (1) + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/arm/vfork.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/arm/vfork.S new file mode 100644 index 00000000..2543f578 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/arm/vfork.S @@ -0,0 +1,78 @@ +/* Copyright (C) 1999, 2002, 2003, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Philip Blundell . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#define _ERRNO_H 1 +#include +#include + +/* Clone the calling process, but without copying the whole address space. + The calling process is suspended until the new process exits or is + replaced by a call to `execve'. Return -1 for errors, 0 to the new process, + and the process ID of the new process to the old process. */ + +ENTRY (__vfork) + +#ifdef __NR_vfork + +#ifdef SHARED + ldr ip, 1f + ldr r0, 2f +3: add ip, pc, ip + ldr r0, [ip, r0] +#else + ldr r0, 1f +#endif + movs r0, r0 + bne HIDDEN_JUMPTARGET (__fork) + + DO_CALL (vfork, 0) + cmn a1, #4096 + RETINSTR(cc, lr) + +#ifndef __ASSUME_VFORK_SYSCALL + /* Check if vfork syscall is known at all. */ + cmn a1, #ENOSYS + bne PLTJMP(C_SYMBOL_NAME(__syscall_error)) +#endif + +#endif + +#ifndef __ASSUME_VFORK_SYSCALL + /* If we don't have vfork, fork is close enough. */ + DO_CALL (fork, 0) + cmn a1, #4096 + RETINSTR(cc, lr) +#elif !defined __NR_vfork +# error "__NR_vfork not available and __ASSUME_VFORK_SYSCALL defined" +#endif + b PLTJMP(C_SYMBOL_NAME(__syscall_error)) + +#ifdef SHARED +1: .word _GLOBAL_OFFSET_TABLE_ - 3b - 8 +2: .word __libc_pthread_functions(GOTOFF) +#else + .weak pthread_create +1: .word pthread_create +#endif + +PSEUDO_END (__vfork) +libc_hidden_def (__vfork) + +weak_alias (__vfork, vfork) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/execve.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/execve.c new file mode 100644 index 00000000..b6a6a018 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/execve.c @@ -0,0 +1,40 @@ +/* Copyright (C) 1999, 2000, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +#include +#include +#include + +extern int __syscall_execve(const char *file, + char *const *argv, + char *const *envp); +extern void __pthread_kill_other_threads_np(void); +weak_extern(__pthread_kill_other_threads_np) + +int +__execve(const char *file, char *const argv[], char *const envp[]) +{ + /* If this is a threaded application kill all other threads. */ + if (__pthread_kill_other_threads_np) + __pthread_kill_other_threads_np(); + return INLINE_SYSCALL(execve, 3, file, argv, envp); +} +weak_alias(__execve, execve) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/fork.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/fork.c new file mode 100644 index 00000000..e15b99b8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/fork.c @@ -0,0 +1,30 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +struct fork_block __fork_block = +{ + .lock = PTHREAD_MUTEX_INITIALIZER, + .prepare_list = { &__fork_block.prepare_list, &__fork_block.prepare_list }, + .parent_list = { &__fork_block.parent_list, &__fork_block.parent_list }, + .child_list = { &__fork_block.child_list, &__fork_block.child_list } +}; diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/fork.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/fork.h new file mode 100644 index 00000000..85477eb4 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/fork.h @@ -0,0 +1,58 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +struct fork_block +{ + /* Lock to protect handling of fork handlers. */ + __libc_lock_define (, lock); + + /* Lists of registered fork handlers. */ + list_t prepare_list; + list_t parent_list; + list_t child_list; +}; + +extern struct fork_block __fork_block attribute_hidden; + +/* Elements of the fork handler lists. */ +struct fork_handler +{ + list_t list; + void (*handler) (void); + void *dso_handle; +}; + + +/* Function to call to unregister fork handlers. */ +extern void __unregister_atfork (void *dso_handle) attribute_hidden; +#define UNREGISTER_ATFORK(dso_handle) __unregister_atfork (dso_handle) + + +/* C library side function to register new fork handlers. */ +extern int __register_atfork (void (*__prepare) (void), + void (*__parent) (void), + void (*__child) (void), + void *dso_handle); + +#ifndef ARCH_FORK +# define ARCH_FORK() __libc_fork() +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/hppa/aio_cancel.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/hppa/aio_cancel.c new file mode 100644 index 00000000..0d6da829 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/hppa/aio_cancel.c @@ -0,0 +1,33 @@ +#include + +#define aio_cancel64 XXX +#include +#undef aio_cancel64 +#include + +extern __typeof (aio_cancel) __new_aio_cancel; +extern __typeof (aio_cancel) __old_aio_cancel; + +#define aio_cancel __new_aio_cancel + +#include + +#undef aio_cancel +strong_alias (__new_aio_cancel, __new_aio_cancel64); +versioned_symbol (librt, __new_aio_cancel, aio_cancel, GLIBC_2_3); +versioned_symbol (librt, __new_aio_cancel64, aio_cancel64, GLIBC_2_3); + +#if SHLIB_COMPAT (librt, GLIBC_2_1, GLIBC_2_3) + +#undef ECANCELED +#define aio_cancel __old_aio_cancel +#define ECANCELED 125 + +#include + +#undef aio_cancel +strong_alias (__old_aio_cancel, __old_aio_cancel64); +compat_symbol (librt, __old_aio_cancel, aio_cancel, GLIBC_2_1); +compat_symbol (librt, __old_aio_cancel64, aio_cancel64, GLIBC_2_1); + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/hppa/bits/initspin.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/hppa/bits/initspin.h new file mode 100644 index 00000000..9b134002 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/hppa/bits/initspin.h @@ -0,0 +1,27 @@ +/* PA-RISC specific definitions for spinlock initializers. + Copyright (C) 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* Initial value of a spinlock. PA-RISC only implements atomic load + and clear so this must be non-zero. */ +#define __LT_SPINLOCK_INIT 1 + +/* Macros for lock initializers, using the above definition. */ +#define __LOCK_INITIALIZER { 0, __LT_SPINLOCK_INIT } +#define __ALT_LOCK_INITIALIZER { 0, __LT_SPINLOCK_INIT } +#define __ATOMIC_INITIALIZER { 0, __LT_SPINLOCK_INIT } diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/hppa/malloc-machine.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/hppa/malloc-machine.h new file mode 100644 index 00000000..6a53da2a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/hppa/malloc-machine.h @@ -0,0 +1,73 @@ +/* HP-PARISC macro definitions for mutexes, thread-specific data + and parameters for malloc. + Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Carlos O'Donell , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _MALLOC_MACHINE_H +#define _MALLOC_MACHINE_H + +#undef thread_atfork_static + +#include +#include + +__libc_lock_define (typedef, mutex_t) + +/* Since our lock structure does not tolerate being initialized to zero, we must + modify the standard function calls made by malloc */ +# define mutex_init(m) \ + __libc_maybe_call (__pthread_mutex_init, (m, NULL), \ + (((m)->__m_lock.__spinlock = __LT_SPINLOCK_INIT),(*(int *)(m))) ) +# define mutex_lock(m) \ + __libc_maybe_call (__pthread_mutex_lock, (m), \ + (__load_and_clear(&((m)->__m_lock.__spinlock)), 0)) +# define mutex_trylock(m) \ + __libc_maybe_call (__pthread_mutex_trylock, (m), \ + (*(int *)(m) ? 1 : (__load_and_clear(&((m)->__m_lock.__spinlock)), 0))) +# define mutex_unlock(m) \ + __libc_maybe_call (__pthread_mutex_unlock, (m), \ + (((m)->__m_lock.__spinlock = __LT_SPINLOCK_INIT), (*(int *)(m))) ) + +/* This is defined by newer gcc version unique for each module. */ +extern void *__dso_handle __attribute__ ((__weak__)); + +#include + +#ifdef SHARED +# define thread_atfork(prepare, parent, child) \ + __register_atfork (prepare, parent, child, __dso_handle) +#else +# define thread_atfork(prepare, parent, child) \ + __register_atfork (prepare, parent, child, \ + &__dso_handle == NULL ? NULL : __dso_handle) +#endif + +/* thread specific data for glibc */ + +#include + +typedef int tsd_key_t[1]; /* no key data structure, libc magic does it */ +__libc_tsd_define (static, MALLOC) /* declaration/common definition */ +#define tsd_key_create(key, destr) ((void) (key)) +#define tsd_setspecific(key, data) __libc_tsd_set (MALLOC, (data)) +#define tsd_getspecific(key, vptr) ((vptr) = __libc_tsd_get (MALLOC)) + +#include + +#endif /* !defined(_MALLOC_MACHINE_H) */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/hppa/pt-initfini.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/hppa/pt-initfini.c new file mode 100644 index 00000000..27f850cf --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/hppa/pt-initfini.c @@ -0,0 +1,109 @@ +/* Special .init and .fini section support for HPPA. Linuxthreads version. + Copyright (C) 2001, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it + and/or modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file with other + programs, and to distribute those programs without any restriction + coming from the use of this file. (The Lesser General Public + License restrictions do apply in other respects; for example, they + cover modification of the file, and distribution when not linked + into another program.) + + The GNU C Library is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* This file is compiled into assembly code which is then munged by a sed + script into two files: crti.s and crtn.s. + + * crti.s puts a function prologue at the beginning of the + .init and .fini sections and defines global symbols for + those addresses, so they can be called as functions. + + * crtn.s puts the corresponding function epilogues + in the .init and .fini sections. */ + +/* If we use the standard C version, the linkage table pointer won't + be properly preserved due to the splitting up of function prologues + and epilogues. Therefore we write these in assembly to make sure + they do the right thing. */ + +__asm__ ( +"#include \"defs.h\"\n" +"\n" +"/*@HEADER_ENDS*/\n" +"\n" +"/*@_init_PROLOG_BEGINS*/\n" +" .section .init\n" +" .align 4\n" +" .globl _init\n" +" .type _init,@function\n" +"_init:\n" +" stw %rp,-20(%sp)\n" +" stwm %r4,64(%sp)\n" +" stw %r19,-32(%sp)\n" +" bl __pthread_initialize_minimal,%rp\n" +" copy %r19,%r4 /* delay slot */\n" +" copy %r4,%r19\n" +"/*@_init_PROLOG_ENDS*/\n" +"\n" +"/*@_init_EPILOG_BEGINS*/\n" +"/* Here is the tail end of _init. */\n" +" .section .init\n" +" ldw -84(%sp),%rp\n" +" copy %r4,%r19\n" +" bv %r0(%rp)\n" +"_end_init:\n" +" ldwm -64(%sp),%r4\n" +"\n" +"/* Our very own unwind info, because the assembler can't handle\n" +" functions split into two or more pieces. */\n" +" .section .PARISC.unwind,\"a\",@progbits\n" +" .extern _init\n" +" .word _init, _end_init\n" +" .byte 0x08, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08\n" +"\n" +"/*@_init_EPILOG_ENDS*/\n" +"\n" +"/*@_fini_PROLOG_BEGINS*/\n" +" .section .fini\n" +" .align 4\n" +" .globl _fini\n" +" .type _fini,@function\n" +"_fini:\n" +" stw %rp,-20(%sp)\n" +" stwm %r4,64(%sp)\n" +" stw %r19,-32(%sp)\n" +" copy %r19,%r4\n" +"/*@_fini_PROLOG_ENDS*/\n" +"\n" +"/*@_fini_EPILOG_BEGINS*/\n" +" .section .fini\n" +" ldw -84(%sp),%rp\n" +" copy %r4,%r19\n" +" bv %r0(%rp)\n" +"_end_fini:\n" +" ldwm -64(%sp),%r4\n" +"\n" +" .section .PARISC.unwind,\"a\",@progbits\n" +" .extern _fini\n" +" .word _fini, _end_fini\n" +" .byte 0x08, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08\n" +"\n" +"/*@_fini_EPILOG_ENDS*/\n" +"\n" +"/*@TRAILER_BEGINS*/\n" +); diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/hppa/sysdep-cancel.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/hppa/sysdep-cancel.h new file mode 100644 index 00000000..7b210ff1 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/hppa/sysdep-cancel.h @@ -0,0 +1,189 @@ +/* cancellable system calls for Linux/HPPA. + Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Carlos O'Donell , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#ifndef __ASSEMBLER__ +# include +#endif + +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + +# ifndef NO_ERROR +# define NO_ERROR -0x1000 +# endif + +# undef PSEUDO +# define PSEUDO(name, syscall_name, args) \ + ENTRY (name) \ + SINGLE_THREAD_P ASM_LINE_SEP \ + cmpib,<> 0,%ret0,Lpseudo_cancel ASM_LINE_SEP \ + nop ASM_LINE_SEP \ + DO_CALL(syscall_name, args) ASM_LINE_SEP \ + /* DONE! */ ASM_LINE_SEP \ + bv 0(2) ASM_LINE_SEP \ + nop ASM_LINE_SEP \ + Lpseudo_cancel: ASM_LINE_SEP \ + /* store return ptr */ ASM_LINE_SEP \ + stw %rp, -20(%sr0,%sp) ASM_LINE_SEP \ + /* save syscall args */ ASM_LINE_SEP \ + PUSHARGS_##args /* MACRO */ ASM_LINE_SEP \ + STW_PIC ASM_LINE_SEP \ + CENABLE /* FUNC CALL */ ASM_LINE_SEP \ + ldo 64(%sp), %sp ASM_LINE_SEP \ + ldo -64(%sp), %sp ASM_LINE_SEP \ + LDW_PIC ASM_LINE_SEP \ + /* restore syscall args */ ASM_LINE_SEP \ + POPARGS_##args ASM_LINE_SEP \ + /* save r4 in arg0 stack slot */ ASM_LINE_SEP \ + stw %r4, -36(%sr0,%sp) ASM_LINE_SEP \ + /* save mask from cenable */ ASM_LINE_SEP \ + copy %ret0, %r4 ASM_LINE_SEP \ + ble 0x100(%sr2,%r0) ASM_LINE_SEP \ + ldi SYS_ify (syscall_name), %r20 ASM_LINE_SEP \ + LDW_PIC ASM_LINE_SEP \ + /* pass mask as arg0 to cdisable */ ASM_LINE_SEP \ + copy %r4, %r26 ASM_LINE_SEP \ + copy %ret0, %r4 ASM_LINE_SEP \ + CDISABLE ASM_LINE_SEP \ + ldo 64(%sp), %sp ASM_LINE_SEP \ + ldo -64(%sp), %sp ASM_LINE_SEP \ + LDW_PIC ASM_LINE_SEP \ + /* compare error */ ASM_LINE_SEP \ + ldi NO_ERROR,%r1 ASM_LINE_SEP \ + /* branch if no error */ ASM_LINE_SEP \ + cmpb,>>=,n %r1,%r4,Lpre_end ASM_LINE_SEP \ + nop ASM_LINE_SEP \ + SYSCALL_ERROR_HANDLER ASM_LINE_SEP \ + ldo 64(%sp), %sp ASM_LINE_SEP \ + ldo -64(%sp), %sp ASM_LINE_SEP \ + /* No need to LDW_PIC */ ASM_LINE_SEP \ + /* make syscall res value positive */ ASM_LINE_SEP \ + sub %r0, %r4, %r4 ASM_LINE_SEP \ + /* store into errno location */ ASM_LINE_SEP \ + stw %r4, 0(%sr0,%ret0) ASM_LINE_SEP \ + /* return -1 */ ASM_LINE_SEP \ + ldo -1(%r0), %ret0 ASM_LINE_SEP \ + Lpre_end: ASM_LINE_SEP \ + ldw -20(%sr0,%sp), %rp ASM_LINE_SEP \ + /* No need to LDW_PIC */ ASM_LINE_SEP \ + ldw -36(%sr0,%sp), %r4 ASM_LINE_SEP + +/* Save arguments into our frame */ +# define PUSHARGS_0 /* nothing to do */ +# define PUSHARGS_1 PUSHARGS_0 stw %r26, -36(%sr0,%sp) ASM_LINE_SEP +# define PUSHARGS_2 PUSHARGS_1 stw %r25, -40(%sr0,%sp) ASM_LINE_SEP +# define PUSHARGS_3 PUSHARGS_2 stw %r24, -44(%sr0,%sp) ASM_LINE_SEP +# define PUSHARGS_4 PUSHARGS_3 stw %r23, -48(%sr0,%sp) ASM_LINE_SEP +# define PUSHARGS_5 PUSHARGS_4 /* Args are on the stack... */ +# define PUSHARGS_6 PUSHARGS_5 + +/* Bring them back from the stack */ +# define POPARGS_0 /* nothing to do */ +# define POPARGS_1 POPARGS_0 ldw -36(%sr0,%sp), %r26 ASM_LINE_SEP +# define POPARGS_2 POPARGS_1 ldw -40(%sr0,%sp), %r25 ASM_LINE_SEP +# define POPARGS_3 POPARGS_2 ldw -44(%sr0,%sp), %r24 ASM_LINE_SEP +# define POPARGS_4 POPARGS_3 ldw -48(%sr0,%sp), %r23 ASM_LINE_SEP +# define POPARGS_5 POPARGS_4 ldw -52(%sr0,%sp), %r22 ASM_LINE_SEP +# define POPARGS_6 POPARGS_5 ldw -54(%sr0,%sp), %r21 ASM_LINE_SEP + +# ifdef IS_IN_libpthread +# ifdef __PIC__ +# define CENABLE .import __pthread_enable_asynccancel,code ASM_LINE_SEP \ + bl __pthread_enable_asynccancel,%r2 ASM_LINE_SEP +# define CDISABLE .import __pthread_disable_asynccancel,code ASM_LINE_SEP \ + bl __pthread_disable_asynccancel,%r2 ASM_LINE_SEP +# else +# define CENABLE .import __pthread_enable_asynccancel,code ASM_LINE_SEP \ + bl __pthread_enable_asynccancel,%r2 ASM_LINE_SEP +# define CDISABLE .import __pthread_disable_asynccancel,code ASM_LINE_SEP \ + bl __pthread_disable_asynccancel,%r2 ASM_LINE_SEP +# endif +# elif !defined NOT_IN_libc +# ifdef __PIC__ +# define CENABLE .import __libc_enable_asynccancel,code ASM_LINE_SEP \ + bl __libc_enable_asynccancel,%r2 ASM_LINE_SEP +# define CDISABLE .import __libc_disable_asynccancel,code ASM_LINE_SEP \ + bl __libc_disable_asynccancel,%r2 ASM_LINE_SEP +# else +# define CENABLE .import __libc_enable_asynccancel,code ASM_LINE_SEP \ + bl __libc_enable_asynccancel,%r2 ASM_LINE_SEP +# define CDISABLE .import __libc_disable_asynccancel,code ASM_LINE_SEP \ + bl __libc_disable_asynccancel,%r2 ASM_LINE_SEP +# endif +# else +# ifdef __PIC__ +# define CENABLE .import __librt_enable_asynccancel,code ASM_LINE_SEP \ + bl __librt_enable_asynccancel,%r2 ASM_LINE_SEP +# define CDISABLE .import __librt_disable_asynccancel,code ASM_LINE_SEP \ + bl __librt_disable_asynccancel,%r2 ASM_LINE_SEP +# else +# define CENABLE .import __librt_enable_asynccancel,code ASM_LINE_SEP \ + bl __librt_enable_asynccancel,%r2 ASM_LINE_SEP +# define CDISABLE .import __librt_disable_asynccancel,code ASM_LINE_SEP \ + bl __librt_disable_asynccancel,%r2 ASM_LINE_SEP +# endif +# endif + +/* p_header.multiple_threads is +12 from the pthread_descr struct start, + We could have called __get_cr27() but we really want less overhead */ +# define MULTIPLE_THREADS_OFFSET 0xC + +/* cr27 has been initialized to 0x0 by kernel */ +# define NO_THREAD_CR27 0x0 + +# ifdef IS_IN_libpthread +# define __local_multiple_threads __pthread_multiple_threads +# elif !defined NOT_IN_libc +# define __local_multiple_threads __libc_multiple_threads +# else +# define __local_multiple_threads __librt_multiple_threads +# endif + +# ifndef __ASSEMBLER__ + extern int __local_multiple_threads attribute_hidden; +# define SINGLE_THREAD_P __builtin_expect (__local_multiple_threads == 0, 1) +# else +/* This ALT version requires newer kernel support */ +# define SINGLE_THREAD_P_MFCTL \ + mfctl %cr27, %ret0 ASM_LINE_SEP \ + cmpib,= NO_THREAD_CR27,%ret0,Lstp ASM_LINE_SEP \ + nop ASM_LINE_SEP \ + ldw MULTIPLE_THREADS_OFFSET(%sr0,%ret0),%ret0 ASM_LINE_SEP \ + Lstp: ASM_LINE_SEP +# ifdef __PIC__ +/* Slower version uses GOT to get value of __local_multiple_threads */ +# define SINGLE_THREAD_P \ + addil LT%__local_multiple_threads, %r19 ASM_LINE_SEP \ + ldw RT%__local_multiple_threads(%sr0,%r1), %ret0 ASM_LINE_SEP \ + ldw 0(%sr0,%ret0), %ret0 ASM_LINE_SEP +# else + /* Slow non-pic version using DP */ +# define SINGLE_THREAD_P \ + addil LR%__local_multiple_threads-$global$,%r27 ASM_LINE_SEP \ + ldw RR%__local_multiple_threads-$global$(%sr0,%r1),%ret0 ASM_LINE_SEP +# endif +# endif +#elif !defined __ASSEMBLER__ + +/* This code should never be used but we define it anyhow. */ +# define SINGLE_THREAD_P (1) + +#endif +/* !defined NOT_IN_libc || defined IS_IN_libpthread */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/i386/sysdep-cancel.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/i386/sysdep-cancel.h new file mode 100644 index 00000000..0bb16e45 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/i386/sysdep-cancel.h @@ -0,0 +1,187 @@ +/* Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#ifndef __ASSEMBLER__ +# include +#endif + +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + +# undef PSEUDO +# define PSEUDO(name, syscall_name, args) \ + .text; \ + ENTRY (name) \ + SINGLE_THREAD_P; \ + jne L(pseudo_cancel); \ + DO_CALL (syscall_name, args); \ + cmpl $-4095, %eax; \ + jae SYSCALL_ERROR_LABEL; \ + ret; \ + L(pseudo_cancel): \ + CENABLE \ + SAVE_OLDTYPE_##args \ + PUSHCARGS_##args \ + DOCARGS_##args \ + movl $SYS_ify (syscall_name), %eax; \ + int $0x80 \ + POPCARGS_##args; \ + POPSTATE_##args \ + cmpl $-4095, %eax; \ + jae SYSCALL_ERROR_LABEL; \ + L(pseudo_end): + +# define SAVE_OLDTYPE_0 movl %eax, %ecx; +# define SAVE_OLDTYPE_1 SAVE_OLDTYPE_0 +# define SAVE_OLDTYPE_2 pushl %eax; cfi_adjust_cfa_offset (4); +# define SAVE_OLDTYPE_3 SAVE_OLDTYPE_2 +# define SAVE_OLDTYPE_4 SAVE_OLDTYPE_2 +# define SAVE_OLDTYPE_5 SAVE_OLDTYPE_2 + +# define PUSHCARGS_0 /* No arguments to push. */ +# define DOCARGS_0 /* No arguments to frob. */ +# define POPCARGS_0 /* No arguments to pop. */ +# define _PUSHCARGS_0 /* No arguments to push. */ +# define _POPCARGS_0 /* No arguments to pop. */ + +# define PUSHCARGS_1 movl %ebx, %edx; cfi_register (ebx, edx); PUSHCARGS_0 +# define DOCARGS_1 _DOARGS_1 (4) +# define POPCARGS_1 POPCARGS_0; movl %edx, %ebx; cfi_restore (ebx); +# define _PUSHCARGS_1 pushl %ebx; cfi_adjust_cfa_offset (4); \ + cfi_rel_offset (ebx, 0); _PUSHCARGS_0 +# define _POPCARGS_1 _POPCARGS_0; popl %ebx; \ + cfi_adjust_cfa_offset (-4); cfi_restore (ebx); + +# define PUSHCARGS_2 PUSHCARGS_1 +# define DOCARGS_2 _DOARGS_2 (12) +# define POPCARGS_2 POPCARGS_1 +# define _PUSHCARGS_2 _PUSHCARGS_1 +# define _POPCARGS_2 _POPCARGS_1 + +# define PUSHCARGS_3 _PUSHCARGS_2 +# define DOCARGS_3 _DOARGS_3 (20) +# define POPCARGS_3 _POPCARGS_3 +# define _PUSHCARGS_3 _PUSHCARGS_2 +# define _POPCARGS_3 _POPCARGS_2 + +# define PUSHCARGS_4 _PUSHCARGS_4 +# define DOCARGS_4 _DOARGS_4 (28) +# define POPCARGS_4 _POPCARGS_4 +# define _PUSHCARGS_4 pushl %esi; cfi_adjust_cfa_offset (4); \ + cfi_rel_offset (esi, 0); _PUSHCARGS_3 +# define _POPCARGS_4 _POPCARGS_3; popl %esi; \ + cfi_adjust_cfa_offset (-4); cfi_restore (esi); + +# define PUSHCARGS_5 _PUSHCARGS_5 +# define DOCARGS_5 _DOARGS_5 (36) +# define POPCARGS_5 _POPCARGS_5 +# define _PUSHCARGS_5 pushl %edi; cfi_adjust_cfa_offset (4); \ + cfi_rel_offset (edi, 0); _PUSHCARGS_4 +# define _POPCARGS_5 _POPCARGS_4; popl %edi; \ + cfi_adjust_cfa_offset (-4); cfi_restore (edi); + +# ifdef IS_IN_libpthread +# define CENABLE call __pthread_enable_asynccancel; +# define CDISABLE call __pthread_disable_asynccancel +# elif defined IS_IN_librt +# ifdef __PIC__ +# define CENABLE pushl %ebx; \ + call __i686.get_pc_thunk.bx; \ + addl $_GLOBAL_OFFSET_TABLE_, %ebx; \ + call __librt_enable_asynccancel@PLT; \ + popl %ebx; +# define CDISABLE pushl %ebx; \ + call __i686.get_pc_thunk.bx; \ + addl $_GLOBAL_OFFSET_TABLE_, %ebx; \ + call __librt_disable_asynccancel@PLT; \ + popl %ebx; +# else +# define CENABLE call __librt_enable_asynccancel; +# define CDISABLE call __librt_disable_asynccancel +# endif +# else +# define CENABLE call __libc_enable_asynccancel; +# define CDISABLE call __libc_disable_asynccancel +# endif +# define POPSTATE_0 \ + pushl %eax; cfi_adjust_cfa_offset (4); movl %ecx, %eax; \ + CDISABLE; popl %eax; cfi_adjust_cfa_offset (-4); +# define POPSTATE_1 POPSTATE_0 +# define POPSTATE_2 xchgl (%esp), %eax; CDISABLE; popl %eax; \ + cfi_adjust_cfa_offset (-4); +# define POPSTATE_3 POPSTATE_2 +# define POPSTATE_4 POPSTATE_3 +# define POPSTATE_5 POPSTATE_4 + +#if !defined NOT_IN_libc +# define __local_multiple_threads __libc_multiple_threads +#elif defined IS_IN_libpthread +# define __local_multiple_threads __pthread_multiple_threads +#else +# define __local_multiple_threads __librt_multiple_threads +#endif + +# ifndef __ASSEMBLER__ +# if defined FLOATING_STACKS && USE___THREAD && defined __PIC__ +# define SINGLE_THREAD_P \ + __builtin_expect (THREAD_GETMEM (THREAD_SELF, \ + p_header.data.multiple_threads) == 0, 1) +# else +extern int __local_multiple_threads +# if !defined NOT_IN_libc || defined IS_IN_libpthread + attribute_hidden; +# else + ; +# endif +# define SINGLE_THREAD_P __builtin_expect (__local_multiple_threads == 0, 1) +# endif +# else +# if !defined __PIC__ +# define SINGLE_THREAD_P cmpl $0, __local_multiple_threads +# elif defined FLOATING_STACKS && USE___THREAD +# define SINGLE_THREAD_P cmpl $0, %gs:MULTIPLE_THREADS_OFFSET +# else +# if !defined NOT_IN_libc || defined IS_IN_libpthread +# define __SINGLE_THREAD_CMP cmpl $0, __local_multiple_threads@GOTOFF(%ecx) +# else +# define __SINGLE_THREAD_CMP \ + movl __local_multiple_threads@GOT(%ecx), %ecx;\ + cmpl $0, (%ecx) +# endif +# if !defined HAVE_HIDDEN || !USE___THREAD +# define SINGLE_THREAD_P \ + SETUP_PIC_REG (cx); \ + addl $_GLOBAL_OFFSET_TABLE_, %ecx; \ + __SINGLE_THREAD_CMP +# else +# define SINGLE_THREAD_P \ + call __i686.get_pc_thunk.cx; \ + addl $_GLOBAL_OFFSET_TABLE_, %ecx; \ + __SINGLE_THREAD_CMP +# endif +# endif +# endif + +#elif !defined __ASSEMBLER__ + +/* This code should never be used but we define it anyhow. */ +# define SINGLE_THREAD_P (1) + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/i386/vfork.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/i386/vfork.S new file mode 100644 index 00000000..78eeabf5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/i386/vfork.S @@ -0,0 +1,95 @@ +/* Copyright (C) 1999, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Andreas Schwab . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#define _ERRNO_H 1 +#include +#include + +/* Clone the calling process, but without copying the whole address space. + The calling process is suspended until the new process exits or is + replaced by a call to `execve'. Return -1 for errors, 0 to the new process, + and the process ID of the new process to the old process. */ + +ENTRY (__vfork) + +#ifdef __NR_vfork + +# ifdef SHARED +# if !defined HAVE_HIDDEN || !USE___THREAD + SETUP_PIC_REG (cx) +# else + call __i686.get_pc_thunk.cx +# endif + addl $_GLOBAL_OFFSET_TABLE_, %ecx + cmpl $0, __libc_pthread_functions@GOTOFF(%ecx) +# else + .weak pthread_create + movl $pthread_create, %eax + testl %eax, %eax +# endif + jne HIDDEN_JUMPTARGET (__fork) + + /* Pop the return PC value into ECX. */ + popl %ecx + + /* Stuff the syscall number in EAX and enter into the kernel. */ + movl $SYS_ify (vfork), %eax + int $0x80 + + /* Jump to the return PC. Don't jump directly since this + disturbs the branch target cache. Instead push the return + address back on the stack. */ + pushl %ecx + + cmpl $-4095, %eax + /* Branch forward if it failed. */ +# ifdef __ASSUME_VFORK_SYSCALL + jae SYSCALL_ERROR_LABEL +.Lpseudo_end: +# else + jae .Lerror +# endif + + ret + +# ifndef __ASSUME_VFORK_SYSCALL +.Lerror: + /* Check if vfork syscall is known at all. */ + cmpl $-ENOSYS, %eax + jne SYSCALL_ERROR_LABEL +# endif +#endif + +#ifndef __ASSUME_VFORK_SYSCALL + /* If we don't have vfork, fork is close enough. */ + + movl $SYS_ify (fork), %eax + int $0x80 + cmpl $-4095, %eax + jae SYSCALL_ERROR_LABEL +.Lpseudo_end: + ret +#elif !defined __NR_vfork +# error "__NR_vfork not available and __ASSUME_VFORK_SYSCALL defined" +#endif +PSEUDO_END (__vfork) +libc_hidden_def (__vfork) + +weak_alias (__vfork, vfork) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/ia64/bits/local_lim.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/ia64/bits/local_lim.h new file mode 100644 index 00000000..629b1f89 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/ia64/bits/local_lim.h @@ -0,0 +1,92 @@ +/* Minimum guaranteed maximum values for system limits. Linux/Alpha version. + Copyright (C) 1993-1998,2000,2002,2003,2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* The kernel header pollutes the namespace with the NR_OPEN symbol + and defines LINK_MAX although filesystems have different maxima. A + similar thing is true for OPEN_MAX: the limit can be changed at + runtime and therefore the macro must not be defined. Remove this + after including the header if necessary. */ +#ifndef NR_OPEN +# define __undef_NR_OPEN +#endif +#ifndef LINK_MAX +# define __undef_LINK_MAX +#endif +#ifndef OPEN_MAX +# define __undef_OPEN_MAX +#endif + +/* The kernel sources contain a file with all the needed information. */ +#include + +/* Have to remove NR_OPEN? */ +#ifdef __undef_NR_OPEN +# undef NR_OPEN +# undef __undef_NR_OPEN +#endif +/* Have to remove LINK_MAX? */ +#ifdef __undef_LINK_MAX +# undef LINK_MAX +# undef __undef_LINK_MAX +#endif +/* Have to remove OPEN_MAX? */ +#ifdef __undef_OPEN_MAX +# undef OPEN_MAX +# undef __undef_OPEN_MAX +#endif + +/* The number of data keys per process. */ +#define _POSIX_THREAD_KEYS_MAX 128 +/* This is the value this implementation supports. */ +#define PTHREAD_KEYS_MAX 1024 + +/* Controlling the iterations of destructors for thread-specific data. */ +#define _POSIX_THREAD_DESTRUCTOR_ITERATIONS 4 +/* Number of iterations this implementation does. */ +#define PTHREAD_DESTRUCTOR_ITERATIONS _POSIX_THREAD_DESTRUCTOR_ITERATIONS + +/* The number of threads per process. */ +#define _POSIX_THREAD_THREADS_MAX 64 +/* This is the value this implementation supports. */ +#define PTHREAD_THREADS_MAX 16384 + +/* Maximum amount by which a process can descrease its asynchronous I/O + priority level. */ +#define AIO_PRIO_DELTA_MAX 20 + +/* Minimum size for a thread. We are free to choose a reasonable value. */ +#define PTHREAD_STACK_MIN 196608 + +/* Maximum number of POSIX timers available. */ +#define TIMER_MAX 256 + +/* Maximum number of timer expiration overruns. */ +#define DELAYTIMER_MAX 2147483647 + +/* Maximum tty name length. */ +#define TTY_NAME_MAX 32 + +/* Maximum login name length. This is arbitrary. */ +#define LOGIN_NAME_MAX 256 + +/* Maximum host name length. */ +#define HOST_NAME_MAX 64 + +/* Maximum message queue priority level. */ +#define MQ_PRIO_MAX 32768 diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/ia64/fork.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/ia64/fork.h new file mode 100644 index 00000000..30a0cc19 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/ia64/fork.h @@ -0,0 +1,25 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +#define ARCH_FORK() INLINE_SYSCALL (clone, 2, SIGCHLD, 0) + +#include_next diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/ia64/pt-initfini.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/ia64/pt-initfini.c new file mode 100644 index 00000000..af8a63c1 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/ia64/pt-initfini.c @@ -0,0 +1,142 @@ +/* Special .init and .fini section support for ia64. LinuxThreads version. + Copyright (C) 2000, 2001, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it + and/or modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file with other + programs, and to distribute those programs without any restriction + coming from the use of this file. (The Lesser General Public + License restrictions do apply in other respects; for example, they + cover modification of the file, and distribution when not linked + into another program.) + + The GNU C Library is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* This file is compiled into assembly code which is then munged by a sed + script into two files: crti.s and crtn.s. + + * crti.s puts a function prologue at the beginning of the + .init and .fini sections and defines global symbols for + those addresses, so they can be called as functions. + + * crtn.s puts the corresponding function epilogues + in the .init and .fini sections. */ + +#include + +#ifdef HAVE_INITFINI_ARRAY + +# define INIT_NEW_WAY \ + ".xdata8 \".init_array\", @fptr(__pthread_initialize_minimal)\n" +# define INIT_OLD_WAY "" +#else +# define INIT_NEW_WAY "" +# define INIT_OLD_WAY \ + "\n\ + st8 [r12] = gp, -16\n\ + br.call.sptk.many b0 = __pthread_initialize_minimal# ;;\n\ + ;;\n\ + adds r12 = 16, r12\n\ + ;;\n\ + ld8 gp = [r12]\n\ + ;;\n" +#endif + +__asm__ ("\n\ +\n\ +#include \"defs.h\"\n\ +\n\ +/*@HEADER_ENDS*/\n\ +\n\ +/*@_init_PROLOG_BEGINS*/\n" + INIT_NEW_WAY + ".section .init\n\ + .align 16\n\ + .global _init#\n\ + .proc _init#\n\ +_init:\n\ + .prologue\n\ + .save ar.pfs, r34\n\ + alloc r34 = ar.pfs, 0, 3, 0, 0\n\ + .vframe r32\n\ + mov r32 = r12\n\ + .save rp, r33\n\ + mov r33 = b0\n\ + .body\n\ + adds r12 = -16, r12\n\ + ;;\n" + INIT_OLD_WAY + ".endp _init#\n\ +\n\ +/*@_init_PROLOG_ENDS*/\n\ +\n\ +/*@_init_EPILOG_BEGINS*/\n\ + .section .init\n\ + .proc _init#\n\ +_init:\n\ + .prologue\n\ + .save ar.pfs, r34\n\ + .vframe r32\n\ + .save rp, r33\n\ + .body\n\ + mov r12 = r32\n\ + mov ar.pfs = r34\n\ + mov b0 = r33\n\ + br.ret.sptk.many b0\n\ + .endp _init#\n\ +/*@_init_EPILOG_ENDS*/\n\ +\n\ +/*@_fini_PROLOG_BEGINS*/\n\ + .section .fini\n\ + .align 16\n\ + .global _fini#\n\ + .proc _fini#\n\ +_fini:\n\ + .prologue\n\ + .save ar.pfs, r34\n\ + alloc r34 = ar.pfs, 0, 3, 0, 0\n\ + .vframe r32\n\ + mov r32 = r12\n\ + .save rp, r33\n\ + mov r33 = b0\n\ + .body\n\ + adds r12 = -16, r12\n\ + ;;\n\ + .endp _fini#\n\ +\n\ +/*@_fini_PROLOG_ENDS*/\n\ +\n\ +/*@_fini_EPILOG_BEGINS*/\n\ + .section .fini\n\ + .proc _fini#\n\ +_fini:\n\ + .prologue\n\ + .save ar.pfs, r34\n\ + .vframe r32\n\ + .save rp, r33\n\ + .body\n\ + mov r12 = r32\n\ + mov ar.pfs = r34\n\ + mov b0 = r33\n\ + br.ret.sptk.many b0\n\ + .endp _fini#\n\ +\n\ +/*@_fini_EPILOG_ENDS*/\n\ +\n\ +/*@TRAILER_BEGINS*/\n\ + .weak __gmon_start__#\n\ +"); diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/ia64/pt-sigsuspend.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/ia64/pt-sigsuspend.c new file mode 100644 index 00000000..0b96e3d5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/ia64/pt-sigsuspend.c @@ -0,0 +1,33 @@ +/* Internal sigsuspend system call for LinuxThreads. IA64 version. + Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +#include +#include +#include + +void +__pthread_sigsuspend (const sigset_t *set) +{ + INTERNAL_SYSCALL_DECL (err); + INTERNAL_SYSCALL (rt_sigsuspend, err, 2, set, _NSIG / 8); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/ia64/sysdep-cancel.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/ia64/sysdep-cancel.h new file mode 100644 index 00000000..dd9637d2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/ia64/sysdep-cancel.h @@ -0,0 +1,144 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#ifndef __ASSEMBLER__ +# include +#endif + +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + +# ifdef IS_IN_librt +# define PSEUDO_NLOCAL 6 +# define PSEUDO_SAVE_GP mov loc5 = gp +# define PSEUDO_RESTORE_GP mov gp = loc5 +# define PSEUDO_SAVE_GP_1 +# define PSEUDO_RESTORE_GP_1 mov gp = loc5 +# else +# define PSEUDO_NLOCAL 5 +# define PSEUDO_SAVE_GP +# define PSEUDO_RESTORE_GP +# define PSEUDO_SAVE_GP_1 mov loc4 = gp;; +# define PSEUDO_RESTORE_GP_1 mov gp = loc4 +# endif + +# undef PSEUDO +# define PSEUDO(name, syscall_name, args) \ +.text; \ +ENTRY (name) \ + adds r14 = MULTIPLE_THREADS_OFFSET, r13;; \ + ld4 r14 = [r14]; \ + mov r15 = SYS_ify(syscall_name);; \ + cmp4.ne p6, p7 = 0, r14; \ +(p6) br.cond.spnt .Lpseudo_cancel;; \ + break __BREAK_SYSCALL;; \ + cmp.eq p6,p0=-1,r10; \ +(p6) br.cond.spnt.few __syscall_error; \ + ret;; \ + .endp name; \ + .proc __GC_##name; \ + .globl __GC_##name; \ + .hidden __GC_##name; \ +__GC_##name: \ +.Lpseudo_cancel: \ + .prologue; \ + .regstk args, PSEUDO_NLOCAL, args, 0; \ + .save ar.pfs, loc0; \ + alloc loc0 = ar.pfs, args, PSEUDO_NLOCAL, args, 0; \ + .save rp, loc1; \ + mov loc1 = rp; \ + PSEUDO_SAVE_GP;; \ + .body; \ + CENABLE;; \ + PSEUDO_RESTORE_GP; \ + mov loc2 = r8; \ + COPY_ARGS_##args \ + mov r15 = SYS_ify(syscall_name); \ + break __BREAK_SYSCALL;; \ + mov loc3 = r8; \ + mov loc4 = r10; \ + mov out0 = loc2; \ + CDISABLE;; \ + PSEUDO_RESTORE_GP; \ + cmp.eq p6,p0=-1,loc4; \ +(p6) br.cond.spnt.few __syscall_error_##args; \ + mov r8 = loc3; \ + mov rp = loc1; \ + mov ar.pfs = loc0; \ +.Lpseudo_end: \ + ret; \ + .endp __GC_##name; \ +.section .gnu.linkonce.t.__syscall_error_##args, "ax"; \ + .align 32; \ + .proc __syscall_error_##args; \ + .global __syscall_error_##args; \ + .hidden __syscall_error_##args; \ + .size __syscall_error_##args, 64; \ +__syscall_error_##args: \ + .prologue; \ + .regstk args, PSEUDO_NLOCAL, args, 0; \ + .save ar.pfs, loc0; \ + .save rp, loc1; \ + .body; \ + PSEUDO_SAVE_GP_1; \ + br.call.sptk.many b0 = __errno_location;; \ + st4 [r8] = loc3; \ + PSEUDO_RESTORE_GP_1; \ + mov rp = loc1; \ + mov r8 = -1; \ + mov ar.pfs = loc0 + +#undef PSEUDO_END +#define PSEUDO_END(name) .endp + +# ifdef IS_IN_libpthread +# define CENABLE br.call.sptk.many b0 = __pthread_enable_asynccancel +# define CDISABLE br.call.sptk.many b0 = __pthread_disable_asynccancel +# elif !defined NOT_IN_libc +# define CENABLE br.call.sptk.many b0 = __libc_enable_asynccancel +# define CDISABLE br.call.sptk.many b0 = __libc_disable_asynccancel +# else +# define CENABLE br.call.sptk.many b0 = __librt_enable_asynccancel +# define CDISABLE br.call.sptk.many b0 = __librt_disable_asynccancel +# endif + +#define COPY_ARGS_0 /* Nothing */ +#define COPY_ARGS_1 COPY_ARGS_0 mov out0 = in0; +#define COPY_ARGS_2 COPY_ARGS_1 mov out1 = in1; +#define COPY_ARGS_3 COPY_ARGS_2 mov out2 = in2; +#define COPY_ARGS_4 COPY_ARGS_3 mov out3 = in3; +#define COPY_ARGS_5 COPY_ARGS_4 mov out4 = in4; +#define COPY_ARGS_6 COPY_ARGS_5 mov out5 = in5; +#define COPY_ARGS_7 COPY_ARGS_6 mov out6 = in6; + +# ifndef __ASSEMBLER__ +# define SINGLE_THREAD_P \ + __builtin_expect (THREAD_GETMEM (THREAD_SELF, p_multiple_threads) == 0, 1) +# else +# define SINGLE_THREAD_P \ + adds r14 = MULTIPLE_THREADS_OFFSET, r13 ;; ld4 r14 = [r14] ;; cmp4.ne p6, p7 = 0, r14 +# endif + +#elif !defined __ASSEMBLER__ + +/* This code should never be used but we define it anyhow. */ +# define SINGLE_THREAD_P (1) + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/ia64/vfork.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/ia64/vfork.S new file mode 100644 index 00000000..54acedad --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/ia64/vfork.S @@ -0,0 +1,54 @@ +/* Copyright (C) 2000, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + + +#include +#define _SIGNAL_H +#include + +/* The following are defined in linux/sched.h, which unfortunately */ +/* is not safe for inclusion in an assembly file. */ +#define CLONE_VM 0x00000100 /* set if VM shared between processes */ +#define CLONE_VFORK 0x00004000 /* set if the parent wants the child to wake it up on mm_release */ + +/* pid_t vfork(void); */ +/* Implemented as __clone_syscall(CLONE_VFORK | CLONE_VM | SIGCHLD, 0) */ + +ENTRY(__vfork) +#ifdef SHARED + addl r14 = @gprel(__libc_pthread_functions#), gp;; +#else + .weak pthread_create + addl r14 = @ltoff(@fptr(pthread_create#)), gp;; +#endif + ld8 r14 = [r14];; + cmp.ne p6, p7 = 0, r14 +(p6) br.cond.spnt.few HIDDEN_JUMPTARGET (__fork);; + alloc r2=ar.pfs,0,0,2,0 + mov out0=CLONE_VM+CLONE_VFORK+SIGCHLD + mov out1=0 /* Standard sp value. */ + ;; + DO_CALL (SYS_ify (clone)) + cmp.eq p6,p0=-1,r10 + ;; +(p6) br.cond.spnt.few __syscall_error + ret +PSEUDO_END(__vfork) +libc_hidden_def (__vfork) + +weak_alias (__vfork, vfork) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/jmp-unwind.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/jmp-unwind.c new file mode 100644 index 00000000..4b903157 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/jmp-unwind.c @@ -0,0 +1,34 @@ +/* _longjmp_unwind -- Clean up stack frames unwound by longjmp. + Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +#ifndef SHARED +weak_extern (__pthread_cleanup_upto); +#endif + +void +_longjmp_unwind (jmp_buf env, int val) +{ + __libc_maybe_call2 (pthread_cleanup_upto, + (env->__jmpbuf, __builtin_frame_address (0)), + (void) 0); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/m68k/sysdep-cancel.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/m68k/sysdep-cancel.h new file mode 100644 index 00000000..9cd56755 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/m68k/sysdep-cancel.h @@ -0,0 +1,129 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Andreas Schwab , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#ifndef __ASSEMBLER__ +# include +#endif + +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + +# undef PSEUDO +# define PSEUDO(name, syscall_name, args) \ + .text; \ + ENTRY (name) \ + SINGLE_THREAD_P; \ + jne .Lpseudo_cancel; \ + DO_CALL (syscall_name, args); \ + cmp.l &-4095, %d0; \ + jcc SYSCALL_ERROR_LABEL; \ + rts; \ + .Lpseudo_cancel: \ + CENABLE; \ + DOCARGS_##args \ + move.l %d0, -(%sp); \ + move.l &SYS_ify (syscall_name), %d0; \ + trap &0; \ + move.l %d0, %d2; \ + CDISABLE; \ + addq.l &4, %sp; \ + move.l %d2, %d0; \ + UNDOCARGS_##args \ + cmp.l &-4095, %d0; \ + jcc SYSCALL_ERROR_LABEL + +# define DOCARGS_0 move.l %d2, -(%sp); +# define _DOCARGS_0(n) +# define UNDOCARGS_0 move.l (%sp)+, %d2; + +# define DOCARGS_1 _DOCARGS_1 (4); DOCARGS_0 +# define _DOCARGS_1(n) move.l n(%sp), %d1; _DOARGS_0 (n) +# define UNDOCARGS_1 UNDOCARGS_0 + +# define DOCARGS_2 _DOCARGS_2 (8) +# define _DOCARGS_2(n) move.l %d2, -(%sp); move.l n+4(%sp), %d2; \ + _DOCARGS_1 (n) +# define UNDOCARGS_2 UNDOCARGS_1 + +# define DOCARGS_3 _DOCARGS_3 (12) +# define _DOCARGS_3(n) move.l %d3, -(%sp); move.l n+4(%sp), %d3; \ + _DOCARGS_2 (n) +# define UNDOCARGS_3 UNDOCARGS_2; move.l (%sp)+, %d3; + +# define DOCARGS_4 _DOCARGS_4 (16) +# define _DOCARGS_4(n) move.l %d4, -(%sp); move.l n+4(%sp), %d4; \ + _DOCARGS_3 (n) +# define UNDOCARGS_4 UNDOCARGS_3; move.l (%sp)+, %d4; + +# define DOCARGS_5 _DOCARGS_5 (20) +# define _DOCARGS_5(n) move.l %d5, -(%sp); move.l n+4(%sp), %d5; \ + _DOCARGS_4 (n) +# define UNDOCARGS_5 UNDOCARGS_4; move.l (%sp)+, %d5; + +# ifdef IS_IN_libpthread +# ifdef __PIC__ +# define CENABLE jbsr __pthread_enable_asynccancel@PLTPC +# define CDISABLE jbsr __pthread_disable_asynccancel@PLTPC +# else +# define CENABLE jbsr __pthread_enable_asynccancel +# define CDISABLE jbsr __pthread_disable_asynccancel +# endif +# elif !defined NOT_IN_libc +# ifdef __PIC__ +# define CENABLE jbsr __libc_enable_asynccancel@PLTPC +# define CDISABLE jbsr __libc_disable_asynccancel@PLTPC +# else +# define CENABLE jbsr __libc_enable_asynccancel +# define CDISABLE jbsr __libc_disable_asynccancel +# endif +# else +# ifdef __PIC__ +# define CENABLE jbsr __librt_enable_asynccancel@PLTPC +# define CDISABLE jbsr __librt_disable_asynccancel@PLTPC +# else +# define CENABLE jbsr __librt_enable_asynccancel +# define CDISABLE jbsr __librt_disable_asynccancel +# endif +# endif + +# if !defined NOT_IN_libc +# define __local_multiple_threads __libc_multiple_threads +# elif defined IS_IN_libpthread +# define __local_multiple_threads __pthread_multiple_threads +# else +# define __local_multiple_threads __librt_multiple_threads +# endif + +# ifndef __ASSEMBLER__ +extern int __local_multiple_threads attribute_hidden; +# define SINGLE_THREAD_P __builtin_expect (__local_multiple_threads == 0, 1) +# else +# if !defined __PIC__ +# define SINGLE_THREAD_P tst.l __local_multiple_threads +# else +# define SINGLE_THREAD_P tst.l (__local_multiple_threads, %pc) +# endif +# endif + +#elif !defined __ASSEMBLER__ + +/* This code should never be used but we define it anyhow. */ +# define SINGLE_THREAD_P (1) + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/m68k/vfork.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/m68k/vfork.S new file mode 100644 index 00000000..8a43ea0d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/m68k/vfork.S @@ -0,0 +1,84 @@ +/* Copyright (C) 1999, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Andreas Schwab . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#define _ERRNO_H 1 +#include +#include + +/* Clone the calling process, but without copying the whole address space. + The calling process is suspended until the new process exits or is + replaced by a call to `execve'. Return -1 for errors, 0 to the new process, + and the process ID of the new process to the old process. */ + +ENTRY (__vfork) + +#ifdef SHARED + tstl (__libc_pthread_functions@GOTPC, %pc) +#else + .weak pthread_create + movel #pthread_create, %d0 +#endif + jbne HIDDEN_JUMPTARGET (__fork) + +#ifdef __NR_vfork + + /* Pop the return PC value into A0. */ + movel %sp@+, %a0 + + /* Stuff the syscall number in D0 and trap into the kernel. */ + movel #SYS_ify (vfork), %d0 + trap #0 + tstl %d0 + jmi .Lerror /* Branch forward if it failed. */ + + /* Jump to the return PC. */ + jmp %a0@ + +.Lerror: + /* Push back the return PC. */ + movel %a0,%sp@- + +# ifdef __ASSUME_VFORK_SYSCALL +# ifndef __PIC__ + jbra SYSCALL_ERROR_LABEL +# endif +# else + /* Check if vfork syscall is known at all. */ + movel #-ENOSYS,%d1 + cmpl %d0,%d1 + jne SYSCALL_ERROR_LABEL + +# endif +#endif + +#ifndef __ASSUME_VFORK_SYSCALL + /* If we don't have vfork, fork is close enough. */ + + movel #SYS_ify (fork), %d0 + trap #0 + tstl %d0 + jmi SYSCALL_ERROR_LABEL + rts +#endif + +PSEUDO_END (__vfork) +libc_hidden_def (__vfork) + +weak_alias (__vfork, vfork) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/mips/mips64/sysdep-cancel.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/mips/mips64/sysdep-cancel.h new file mode 100644 index 00000000..fc517742 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/mips/mips64/sysdep-cancel.h @@ -0,0 +1,144 @@ +/* system call stubs with cancellation handling. Linux/MIPS version. + Copyright (C) 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Chris Demetriou of Broadcom Corporation, + based on work by Guido Guenther . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#ifndef __ASSEMBLER__ +# include +#endif +#include + +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + +#ifdef __PIC__ +# undef PSEUDO +# define PSEUDO(name, syscall_name, args) \ + .align 2; \ + 99: \ + PTR_LA t9,__syscall_error; \ + /* manual cpreturn. */ \ + REG_L gp, STKOFF_GP(sp); \ + RESTORESTK ; \ + jr t9; \ + ENTRY (name) \ + SAVESTK ; \ + .cpsetup t9, STKOFF_GP, name ; \ + .set reorder; \ + SINGLE_THREAD_P(t0); \ + bne zero, t0, L(pseudo_cancel); \ + .set noreorder; \ + li v0, SYS_ify(syscall_name); \ + syscall; \ + .set reorder; \ + bne a3, zero, SYSCALL_ERROR_LABEL; \ + /* manual cpreturn. */ \ + REG_L gp, STKOFF_GP(sp); \ + RESTORESTK ; \ + ret; \ + L(pseudo_cancel): \ + REG_S ra, STKOFF_RA(sp); \ + PUSHARGS_##args; /* save syscall args */ \ + CENABLE; \ + REG_S v0, STKOFF_SVMSK(sp); /* save mask */ \ + POPARGS_##args; /* restore syscall args */ \ + .set noreorder; \ + li v0, SYS_ify (syscall_name); \ + syscall; \ + .set reorder; \ + REG_S v0, STKOFF_SC_V0(sp); /* save syscall result */ \ + REG_S a3, STKOFF_SC_ERR(sp); /* save syscall error flag */ \ + REG_L a0, STKOFF_SVMSK(sp); /* pass mask as arg1 */ \ + CDISABLE; \ + REG_L a3, STKOFF_SC_ERR(sp); /* restore syscall error flag */ \ + REG_L ra, STKOFF_RA(sp); /* restore return address */ \ + REG_L v0, STKOFF_SC_V0(sp); /* restore syscall result */ \ + bne a3, zero, SYSCALL_ERROR_LABEL; \ + /* manual cpreturn. */ \ + REG_L gp, STKOFF_GP(sp); \ + RESTORESTK ; \ + L(pseudo_end): +#endif + +# define PUSHARGS_0 /* nothing to do */ +# define PUSHARGS_1 PUSHARGS_0 REG_S a0, STKOFF_A0(sp); +# define PUSHARGS_2 PUSHARGS_1 REG_S a1, STKOFF_A1(sp); +# define PUSHARGS_3 PUSHARGS_2 REG_S a2, STKOFF_A2(sp); +# define PUSHARGS_4 PUSHARGS_3 REG_S a3, STKOFF_A3(sp); +# define PUSHARGS_5 PUSHARGS_4 REG_S a4, STKOFF_A4(sp); +# define PUSHARGS_6 PUSHARGS_5 REG_S a5, STKOFF_A5(sp); + +# define POPARGS_0 /* nothing to do */ +# define POPARGS_1 POPARGS_0 REG_L a0, STKOFF_A0(sp); +# define POPARGS_2 POPARGS_1 REG_L a1, STKOFF_A1(sp); +# define POPARGS_3 POPARGS_2 REG_L a2, STKOFF_A2(sp); +# define POPARGS_4 POPARGS_3 REG_L a3, STKOFF_A3(sp); +# define POPARGS_5 POPARGS_4 REG_L a4, STKOFF_A4(sp); +# define POPARGS_6 POPARGS_5 REG_L a5, STKOFF_A5(sp); + +/* Save an even number of slots. Should be 0 if an even number of slots + are used below, or SZREG if an odd number are used. */ +# define STK_PAD SZREG + +/* Place values that we are more likely to use later in this sequence, i.e. + closer to the SP at function entry. If you do that, the are more + likely to already be in your d-cache. */ +# define STKOFF_A5 (STK_PAD) +# define STKOFF_A4 (STKOFF_A5 + SZREG) +# define STKOFF_A3 (STKOFF_A4 + SZREG) +# define STKOFF_A2 (STKOFF_A3 + SZREG) /* MT and more args. */ +# define STKOFF_A1 (STKOFF_A2 + SZREG) /* MT and 2 args. */ +# define STKOFF_A0 (STKOFF_A1 + SZREG) /* MT and 1 arg. */ +# define STKOFF_RA (STKOFF_A0 + SZREG) /* Used if MT. */ +# define STKOFF_SC_V0 (STKOFF_RA + SZREG) /* Used if MT. */ +# define STKOFF_SC_ERR (STKOFF_SC_V0 + SZREG) /* Used if MT. */ +# define STKOFF_SVMSK (STKOFF_SC_ERR + SZREG) /* Used if MT. */ +# define STKOFF_GP (STKOFF_SVMSK + SZREG) /* Always used. */ + +# define STKSPACE (STKOFF_GP + SZREG) +# define SAVESTK PTR_SUBU sp, STKSPACE +# define RESTORESTK PTR_ADDU sp, STKSPACE + +# ifdef IS_IN_libpthread +# define CENABLE PTR_LA t9, __pthread_enable_asynccancel; jalr t9; +# define CDISABLE PTR_LA t9, __pthread_disable_asynccancel; jalr t9; +# define __local_multiple_threads __pthread_multiple_threads +# elif defined IS_IN_librt +# define CENABLE PTR_LA t9, __librt_enable_asynccancel; jalr t9; +# define CDISABLE PTR_LA t9, __librt_disable_asynccancel; jalr t9; +# define __local_multiple_threads __librt_multiple_threads +# else +# define CENABLE PTR_LA t9, __libc_enable_asynccancel; jalr t9; +# define CDISABLE PTR_LA t9, __libc_disable_asynccancel; jalr t9; +# define __local_multiple_threads __libc_multiple_threads +# endif + +# ifndef __ASSEMBLER__ +extern int __local_multiple_threads attribute_hidden; +# define SINGLE_THREAD_P __builtin_expect (__local_multiple_threads == 0, 1) +# else +# define SINGLE_THREAD_P(reg) lw reg, __local_multiple_threads +#endif + +#elif !defined __ASSEMBLER__ + +/* This code should never be used but we define it anyhow. */ +# define SINGLE_THREAD_P (1) + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/mips/sysdep-cancel.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/mips/sysdep-cancel.h new file mode 100644 index 00000000..b2c0dfe8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/mips/sysdep-cancel.h @@ -0,0 +1,144 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Guido Guenther , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#ifndef __ASSEMBLER__ +# include +#endif + +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + +#ifdef __PIC__ +# undef PSEUDO +# define PSEUDO(name, syscall_name, args) \ + .align 2; \ + 99: move a0, v0; \ + la t9,__syscall_error; \ + jr t9; \ + ENTRY (name) \ + .set noreorder; \ + .cpload t9; \ + .set reorder; \ + SINGLE_THREAD_P(t0); \ + bne zero, t0, L(pseudo_cancel); \ + .set noreorder; \ + li v0, SYS_ify(syscall_name); \ + syscall; \ + .set reorder; \ + bne a3, zero, SYSCALL_ERROR_LABEL; \ + ret; \ + L(pseudo_cancel): \ + SAVESTK_##args; \ + sw ra, 28(sp); \ + sw gp, 32(sp); \ + PUSHARGS_##args; /* save syscall args */ \ + CENABLE; \ + lw gp, 32(sp); \ + sw v0, 44(sp); /* save mask */ \ + POPARGS_##args; /* restore syscall args */ \ + .set noreorder; \ + li v0, SYS_ify (syscall_name); \ + syscall; \ + .set reorder; \ + sw v0, 36(sp); /* save syscall result */ \ + sw a3, 40(sp); /* save syscall error flag */ \ + lw a0, 44(sp); /* pass mask as arg1 */ \ + CDISABLE; \ + lw gp, 32(sp); \ + lw v0, 36(sp); /* restore syscall result */ \ + lw a3, 40(sp); /* restore syscall error flag */ \ + lw ra, 28(sp); /* restore return address */ \ + RESTORESTK; \ + bne a3, zero, SYSCALL_ERROR_LABEL; \ + L(pseudo_end): +#endif + +# define PUSHARGS_0 /* nothing to do */ +# define PUSHARGS_1 PUSHARGS_0 sw a0, 0(sp); +# define PUSHARGS_2 PUSHARGS_1 sw a1, 4(sp); +# define PUSHARGS_3 PUSHARGS_2 sw a2, 8(sp); +# define PUSHARGS_4 PUSHARGS_3 sw a3, 12(sp); +# define PUSHARGS_5 PUSHARGS_4 /* handeld by SAVESTK_## */ +# define PUSHARGS_6 PUSHARGS_5 +# define PUSHARGS_7 PUSHARGS_6 + +# define POPARGS_0 /* nothing to do */ +# define POPARGS_1 POPARGS_0 lw a0, 0(sp); +# define POPARGS_2 POPARGS_1 lw a1, 4(sp); +# define POPARGS_3 POPARGS_2 lw a2, 8(sp); +# define POPARGS_4 POPARGS_3 lw a3, 12(sp); +# define POPARGS_5 POPARGS_4 /* args already in new stackframe */ +# define POPARGS_6 POPARGS_5 +# define POPARGS_7 POPARGS_6 + + +# define STKSPACE 48 +# define SAVESTK_0 subu sp, STKSPACE +# define SAVESTK_1 SAVESTK_0 +# define SAVESTK_2 SAVESTK_1 +# define SAVESTK_3 SAVESTK_2 +# define SAVESTK_4 SAVESTK_3 +# define SAVESTK_5 lw t0, 16(sp); \ + subu sp, STKSPACE; \ + sw t0, 16(sp) + +# define SAVESTK_6 lw t0, 16(sp); \ + lw t1, 20(sp); \ + subu sp, STKSPACE; \ + sw t0, 16(sp); \ + sw t1, 20(sp) + +# define SAVESTK_7 lw t0, 16(sp); \ + lw t1, 20(sp); \ + lw t2, 24(sp); \ + subu sp, STKSPACE; \ + sw t0, 16(sp); \ + sw t1, 20(sp); \ + sw t2, 24(sp) + +# define RESTORESTK addu sp, STKSPACE + + +# ifdef IS_IN_libpthread +# define CENABLE la t9, __pthread_enable_asynccancel; jalr t9; +# define CDISABLE la t9, __pthread_disable_asynccancel; jalr t9; +# define __local_multiple_threads __pthread_multiple_threads +# elif defined IS_IN_librt +# define CENABLE la t9, __librt_enable_asynccancel; jalr t9; +# define CDISABLE la t9, __librt_disable_asynccancel; jalr t9; +# define __local_multiple_threads __librt_multiple_threads +# else +# define CENABLE la t9, __libc_enable_asynccancel; jalr t9; +# define CDISABLE la t9, __libc_disable_asynccancel; jalr t9; +# define __local_multiple_threads __libc_multiple_threads +# endif + +# ifndef __ASSEMBLER__ +extern int __local_multiple_threads attribute_hidden; +# define SINGLE_THREAD_P __builtin_expect (__local_multiple_threads == 0, 1) +# else +# define SINGLE_THREAD_P(reg) lw reg, __local_multiple_threads +#endif + +#elif !defined __ASSEMBLER__ + +/* This code should never be used but we define it anyhow. */ +# define SINGLE_THREAD_P (1) + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/mips/vfork.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/mips/vfork.S new file mode 100644 index 00000000..7bbab5c5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/mips/vfork.S @@ -0,0 +1,104 @@ +/* Copyright (C) 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* vfork() is just a special case of clone(). */ + +#include +#include +#include + +/* int vfork() */ + + .text +LOCALSZ= 1 +FRAMESZ= (((NARGSAVE+LOCALSZ)*SZREG)+ALSZ)&ALMASK +GPOFF= FRAMESZ-(1*SZREG) +NESTED(__vfork,FRAMESZ,sp) +#ifdef __PIC__ + SETUP_GP +#endif + PTR_SUBU sp, FRAMESZ + SETUP_GP64 (a5, __vfork) +#ifdef __PIC__ + SAVE_GP (GPOFF) +#endif +#ifdef PROF +# if (_MIPS_SIM != _ABIO32) + PTR_S a5, GPOFF(sp) +# endif + .set noat + move $1, ra +# if (_MIPS_SIM == _ABIO32) + subu sp,sp,8 +# endif + jal _mcount + .set at +# if (_MIPS_SIM != _ABIO32) + PTR_L a5, GPOFF(sp) +# endif +#endif + + /* If libpthread is loaded, we need to call fork instead. */ +#ifdef SHARED + PTR_L a0, __libc_pthread_functions +#else + .weak pthread_create + PTR_LA a0, pthread_create +#endif + + PTR_ADDU sp, FRAMESZ + + bnez a0, L(call_fork) + + li a0, 0x4112 /* CLONE_VM | CLONE_VFORK | SIGCHLD */ + move a1, sp + + /* Do the system call */ + li v0,__NR_clone + syscall + + bnez a3,L(error) + + /* Successful return from the parent or child. */ + RESTORE_GP64 + ret + + /* Something bad happened -- no child created. */ +L(error): +#ifdef __PIC__ + PTR_LA t9, __syscall_error + RESTORE_GP64 + jr t9 +#else + RESTORE_GP64 + j __syscall_error +#endif + +L(call_fork): +#ifdef __PIC__ + PTR_LA t9, fork + RESTORE_GP64 + jr t9 +#else + RESTORE_GP64 + j fork +#endif + END(__vfork) + +libc_hidden_def(__vfork) +weak_alias (__vfork, vfork) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/mq_notify.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/mq_notify.c new file mode 100644 index 00000000..a44d0513 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/mq_notify.c @@ -0,0 +1,285 @@ +/* Copyright (C) 2004, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contribute by Ulrich Drepper , 2004. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#ifdef __NR_mq_notify + +/* Defined in the kernel headers: */ +#define NOTIFY_COOKIE_LEN 32 /* Length of the cookie used. */ +#define NOTIFY_WOKENUP 1 /* Code for notifcation. */ +#define NOTIFY_REMOVED 2 /* Code for closed message queue + of de-notifcation. */ + + +/* Data structure for the queued notification requests. */ +union notify_data +{ + struct + { + void (*fct) (union sigval); /* The function to run. */ + union sigval param; /* The parameter to pass. */ + pthread_attr_t *attr; /* Attributes to create the thread with. */ + /* NB: on 64-bit machines the struct as a size of 24 bytes. Which means + byte 31 can still be used for returning the status. */ + }; + char raw[NOTIFY_COOKIE_LEN]; +}; + + +/* Keep track of the initialization. */ +static pthread_once_t once = PTHREAD_ONCE_INIT; + + +/* The netlink socket. */ +static int netlink_socket = -1; + + +/* Barrier used to make sure data passed to the new thread is not + resused by the parent. */ +static pthread_barrier_t notify_barrier; + + +/* Modify the signal mask. We move this into a separate function so + that the stack space needed for sigset_t is not deducted from what + the thread can use. */ +static int +__attribute__ ((noinline)) +change_sigmask (int how, sigset_t *oss) +{ + sigset_t ss; + __sigfillset (&ss); + return pthread_sigmask (how, &ss, oss); +} + + +/* The function used for the notification. */ +static void * +notification_function (void *arg) +{ + /* Copy the function and parameter so that the parent thread can go + on with its life. */ + __volatile__ union notify_data *data = (__volatile__ union notify_data *) arg; + void (*fct) (union sigval) = data->fct; + union sigval param = data->param; + + /* Let the parent go. */ + (void) pthread_barrier_wait (¬ify_barrier); + + /* Make the thread detached. */ + (void) pthread_detach (pthread_self ()); + + /* The parent thread has all signals blocked. This is probably a + bit surprising for this thread. So we unblock all of them. */ + (void) change_sigmask (SIG_UNBLOCK, NULL); + + /* Now run the user code. */ + fct (param); + + /* And we are done. */ + return NULL; +} + + +/* Helper thread. */ +static void * +helper_thread (void *arg) +{ + while (1) + { + union notify_data data; + + ssize_t n = recv (netlink_socket, &data, sizeof (data), + MSG_NOSIGNAL | MSG_WAITALL); + if (n < NOTIFY_COOKIE_LEN) + continue; + + if (data.raw[NOTIFY_COOKIE_LEN - 1] == NOTIFY_WOKENUP) + { + /* Just create the thread as instructed. There is no way to + report a problem with creating a thread. */ + pthread_t th; + if (__builtin_expect (pthread_create (&th, data.attr, + notification_function, &data) + == 0, 0)) + /* Since we passed a pointer to DATA to the new thread we have + to wait until it is done with it. */ + (void) pthread_barrier_wait (¬ify_barrier); + } + else if (data.raw[NOTIFY_COOKIE_LEN - 1] == NOTIFY_REMOVED) + /* The only state we keep is the copy of the thread attributes. */ + free (data.attr); + } + return NULL; +} + + +static void +reset_once (void) +{ + once = PTHREAD_ONCE_INIT; +} + + +static void +init_mq_netlink (void) +{ + /* This code might be called a second time after fork(). The file + descriptor is inherited from the parent. */ + if (netlink_socket == -1) + { + /* Just a normal netlink socket, not bound. */ + netlink_socket = socket (AF_NETLINK, SOCK_RAW, 0); + /* No need to do more if we have no socket. */ + if (netlink_socket == -1) + return; + + /* Make sure the descriptor is closed on exec. */ + fcntl (netlink_socket, F_SETFD, FD_CLOEXEC); + } + + int err = 1; + + /* Initialize the barrier. */ + if (__builtin_expect (pthread_barrier_init (¬ify_barrier, NULL, 2) == 0, + 0)) + { + /* Create the helper thread. */ + pthread_attr_t attr; + (void) pthread_attr_init (&attr); + (void) pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED); + /* We do not need much stack space, the bare minimum will be enough. */ + (void) pthread_attr_setstacksize (&attr, PTHREAD_STACK_MIN); + + /* Temporarily block all signals so that the newly created + thread inherits the mask. */ + sigset_t oss; + int have_no_oss = change_sigmask (SIG_BLOCK, &oss); + + pthread_t th; + err = pthread_create (&th, &attr, helper_thread, NULL); + + /* Reset the signal mask. */ + if (!have_no_oss) + pthread_sigmask (SIG_SETMASK, &oss, NULL); + + (void) pthread_attr_destroy (&attr); + + if (err == 0) + { + static smallint added_atfork; + + if (added_atfork == 0 + && pthread_atfork (NULL, NULL, reset_once) != 0) + { + /* The child thread will call recv() which is a + cancellation point. */ + (void) pthread_cancel (th); + err = 1; + } + else + added_atfork = 1; + } + } + + if (err != 0) + { + close_not_cancel_no_status (netlink_socket); + netlink_socket = -1; + } +} + + +/* Register notification upon message arrival to an empty message queue + MQDES. */ +int +mq_notify (mqd_t mqdes, const struct sigevent *notification) +{ + /* Make sure the type is correctly defined. */ + assert (sizeof (union notify_data) == NOTIFY_COOKIE_LEN); + + /* Special treatment needed for SIGEV_THREAD. */ + if (notification == NULL || notification->sigev_notify != SIGEV_THREAD) + return INLINE_SYSCALL (mq_notify, 2, mqdes, notification); + + /* The kernel cannot directly start threads. This will have to be + done at userlevel. Since we cannot start threads from signal + handlers we have to create a dedicated thread which waits for + notifications for arriving messages and creates threads in + response. */ + + /* Initialize only once. */ + pthread_once (&once, init_mq_netlink); + + /* If we cannot create the netlink socket we cannot provide + SIGEV_THREAD support. */ + if (__builtin_expect (netlink_socket == -1, 0)) + { + __set_errno (ENOSYS); + return -1; + } + + /* Create the cookie. It will hold almost all the state. */ + union notify_data data; + memset (&data, '\0', sizeof (data)); + data.fct = notification->sigev_notify_function; + data.param = notification->sigev_value; + + if (notification->sigev_notify_attributes != NULL) + { + /* The thread attribute has to be allocated separately. */ + data.attr = (pthread_attr_t *) malloc (sizeof (pthread_attr_t)); + if (data.attr == NULL) + return -1; + + memcpy (data.attr, notification->sigev_notify_attributes, + sizeof (pthread_attr_t)); + } + + /* Construct the new request. */ + struct sigevent se; + se.sigev_notify = SIGEV_THREAD; + se.sigev_signo = netlink_socket; + se.sigev_value.sival_ptr = &data; + + /* Tell the kernel. */ + int retval = INLINE_SYSCALL (mq_notify, 2, mqdes, &se); + + /* If it failed, free the allocated memory. */ + if (__builtin_expect (retval != 0, 0)) + free (data.attr); + + return retval; +} + +#else +# include +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h new file mode 100644 index 00000000..9925a2f5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h @@ -0,0 +1,159 @@ +/* Copyright (C) 2003, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Franz Sirl , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#ifndef __ASSEMBLER__ +# include +#endif + +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + +# undef PSEUDO +# define PSEUDO(name, syscall_name, args) \ + .section ".text"; \ + ENTRY (name) \ + SINGLE_THREAD_P; \ + bne- .Lpseudo_cancel; \ + DO_CALL (SYS_ify (syscall_name)); \ + PSEUDO_RET; \ + .Lpseudo_cancel: \ + stwu 1,-48(1); \ + mflr 9; \ + stw 9,52(1); \ + CGOTSETUP; \ + DOCARGS_##args; /* save syscall args around CENABLE. */ \ + CENABLE; \ + stw 3,16(1); /* store CENABLE return value (MASK). */ \ + UNDOCARGS_##args; /* restore syscall args. */ \ + DO_CALL (SYS_ify (syscall_name)); \ + mfcr 0; /* save CR/R3 around CDISABLE. */ \ + stw 3,8(1); \ + stw 0,12(1); \ + lwz 3,16(1); /* pass MASK to CDISABLE. */ \ + CDISABLE; \ + lwz 4,52(1); \ + lwz 0,12(1); /* restore CR/R3. */ \ + lwz 3,8(1); \ + CGOTRESTORE; \ + mtlr 4; \ + mtcr 0; \ + addi 1,1,48; + +# define DOCARGS_0 +# define UNDOCARGS_0 + +# define DOCARGS_1 stw 3,20(1); DOCARGS_0 +# define UNDOCARGS_1 lwz 3,20(1); UNDOCARGS_0 + +# define DOCARGS_2 stw 4,24(1); DOCARGS_1 +# define UNDOCARGS_2 lwz 4,24(1); UNDOCARGS_1 + +# define DOCARGS_3 stw 5,28(1); DOCARGS_2 +# define UNDOCARGS_3 lwz 5,28(1); UNDOCARGS_2 + +# define DOCARGS_4 stw 6,32(1); DOCARGS_3 +# define UNDOCARGS_4 lwz 6,32(1); UNDOCARGS_3 + +# define DOCARGS_5 stw 7,36(1); DOCARGS_4 +# define UNDOCARGS_5 lwz 7,36(1); UNDOCARGS_4 + +# define DOCARGS_6 stw 8,40(1); DOCARGS_5 +# define UNDOCARGS_6 lwz 8,40(1); UNDOCARGS_5 + +# define CGOTSETUP +# define CGOTRESTORE + +# ifdef IS_IN_libpthread +# define CENABLE bl __pthread_enable_asynccancel@local +# define CDISABLE bl __pthread_disable_asynccancel@local +# elif !defined NOT_IN_libc +# define CENABLE bl __libc_enable_asynccancel@local +# define CDISABLE bl __libc_disable_asynccancel@local +# else +# define CENABLE bl JUMPTARGET(__librt_enable_asynccancel) +# define CDISABLE bl JUMPTARGET(__librt_disable_asynccancel) +# if defined HAVE_AS_REL16 && defined __PIC__ +# undef CGOTSETUP +# define CGOTSETUP \ + bcl 20,31,1f; \ + 1: stw 30,44(1); \ + mflr 30; \ + addis 30,30,_GLOBAL_OFFSET_TABLE-1b@ha; \ + addi 30,30,_GLOBAL_OFFSET_TABLE-1b@l +# undef CGOTRESTORE +# define CGOTRESTORE \ + lwz 30,44(1) +# endif +# endif + +# ifdef HAVE_TLS_SUPPORT +# ifndef __ASSEMBLER__ +# define SINGLE_THREAD_P \ + __builtin_expect (THREAD_GETMEM (THREAD_SELF, p_multiple_threads) == 0, 1) +# else +# define SINGLE_THREAD_P \ + lwz 10,MULTIPLE_THREADS_OFFSET(2); \ + cmpwi 10,0 +# endif +# else +# if !defined NOT_IN_libc +# define __local_multiple_threads __libc_multiple_threads +# else +# define __local_multiple_threads __librt_multiple_threads +# endif +# ifndef __ASSEMBLER__ +extern int __local_multiple_threads attribute_hidden; +# define SINGLE_THREAD_P __builtin_expect (__local_multiple_threads == 0, 1) +# else +# if !defined __PIC__ +# define SINGLE_THREAD_P \ + lis 10,__local_multiple_threads@ha; \ + lwz 10,__local_multiple_threads@l(10); \ + cmpwi 10,0 +# else +# ifdef HAVE_ASM_PPC_REL16 +# define SINGLE_THREAD_P \ + mflr 9; \ + bcl 20,31,1f; \ +1:mflr 10; \ + addis 10,10,__local_multiple_threads-1b@ha; \ + lwz 10,__local_multiple_threads-1b@l(10); \ + mtlr 9; \ + cmpwi 10,0 +# else +# define SINGLE_THREAD_P \ + mflr 9; \ + bl _GLOBAL_OFFSET_TABLE_@local-4; \ + mflr 10; \ + mtlr 9; \ + lwz 10,__local_multiple_threads@got(10); \ + lwz 10,0(10); \ + cmpwi 10,0 +# endif +# endif +# endif +# endif + +#elif !defined __ASSEMBLER__ + +/* This code should never be used but we define it anyhow. */ +# define SINGLE_THREAD_P (1) + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/powerpc/powerpc32/vfork.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/powerpc/powerpc32/vfork.S new file mode 100644 index 00000000..353c7d07 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/powerpc/powerpc32/vfork.S @@ -0,0 +1,86 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#define _ERRNO_H 1 +#include +#include + +/* Clone the calling process, but without copying the whole address space. + The calling process is suspended until the new process exits or is + replaced by a call to `execve'. Return -1 for errors, 0 to the new process, + and the process ID of the new process to the old process. */ + +ENTRY (__vfork) + +#ifdef __NR_vfork +# ifdef SHARED + mflr 9 +# ifdef HAVE_ASM_PPC_REL16 + bcl 20,31,1f +1: mflr 10 + addis 10,10,__libc_pthread_functions-1b@ha + lwz 10,__libc_pthread_functions-1b@l(10) + mtlr 9 +# else + bl _GLOBAL_OFFSET_TABLE_@local-4 + mflr 10 + mtlr 9 + lwz 10,__libc_pthread_functions@got(10) + lwz 10,0(10) +# endif +# else + .weak pthread_create + lis 10,pthread_create@ha + la 10,pthread_create@l(10) +# endif + + cmpwi 10,0 + bne- .Lhidden_fork + + DO_CALL (SYS_ify (vfork)); + +# ifdef __ASSUME_VFORK_SYSCALL + PSEUDO_RET +# else + bnslr+ + /* Check if vfork syscall is known at all. */ + cmpwi r3,ENOSYS + bne- .Lsyscall_error + +# endif + +.Lhidden_fork: + b HIDDEN_JUMPTARGET(__fork) + +#endif + +#ifndef __ASSUME_VFORK_SYSCALL + /* If we don't have vfork, fork is close enough. */ + + DO_CALL (SYS_ify (fork)); + bnslr+ + +.Lsyscall_error: + b __syscall_error@local +#endif + +PSEUDO_END (__vfork) +libc_hidden_def (__vfork) + +weak_alias (__vfork, vfork) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h new file mode 100644 index 00000000..0c746767 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h @@ -0,0 +1,127 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Franz Sirl , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#ifndef __ASSEMBLER__ +# include +#endif + +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + +# undef PSEUDO +# define PSEUDO(name, syscall_name, args) \ + .section ".text"; \ + ENTRY (name) \ + SINGLE_THREAD_P; \ + bne- .Lpseudo_cancel; \ + DO_CALL (SYS_ify (syscall_name)); \ + PSEUDO_RET; \ + .Lpseudo_cancel: \ + stdu 1,-128(1); \ + mflr 9; \ + std 9,128+16(1); \ + DOCARGS_##args; /* save syscall args around CENABLE. */ \ + CENABLE; \ + std 3,72(1); /* store CENABLE return value (MASK). */ \ + UNDOCARGS_##args; /* restore syscall args. */ \ + DO_CALL (SYS_ify (syscall_name)); \ + mfcr 0; /* save CR/R3 around CDISABLE. */ \ + std 3,64(1); \ + std 0,8(1); \ + ld 3,72(1); /* pass MASK to CDISABLE. */ \ + CDISABLE; \ + ld 9,128+16(1); \ + ld 0,8(1); /* restore CR/R3. */ \ + ld 3,64(1); \ + mtlr 9; \ + mtcr 0; \ + addi 1,1,128; + +# define DOCARGS_0 +# define UNDOCARGS_0 + +# define DOCARGS_1 std 3,80(1); DOCARGS_0 +# define UNDOCARGS_1 ld 3,80(1); UNDOCARGS_0 + +# define DOCARGS_2 std 4,88(1); DOCARGS_1 +# define UNDOCARGS_2 ld 4,88(1); UNDOCARGS_1 + +# define DOCARGS_3 std 5,96(1); DOCARGS_2 +# define UNDOCARGS_3 ld 5,96(1); UNDOCARGS_2 + +# define DOCARGS_4 std 6,104(1); DOCARGS_3 +# define UNDOCARGS_4 ld 6,104(1); UNDOCARGS_3 + +# define DOCARGS_5 std 7,112(1); DOCARGS_4 +# define UNDOCARGS_5 ld 7,112(1); UNDOCARGS_4 + +# define DOCARGS_6 std 8,120(1); DOCARGS_5 +# define UNDOCARGS_6 ld 8,120(1); UNDOCARGS_5 + +# ifdef IS_IN_libpthread +# define CENABLE bl JUMPTARGET(__pthread_enable_asynccancel) +# define CDISABLE bl JUMPTARGET(__pthread_disable_asynccancel) +# define __local_multiple_threads __pthread_multiple_threads +# elif !defined NOT_IN_libc +# define CENABLE bl JUMPTARGET(__libc_enable_asynccancel) +# define CDISABLE bl JUMPTARGET(__libc_disable_asynccancel) +# define __local_multiple_threads __libc_multiple_threads +# else +# define CENABLE bl JUMPTARGET(__librt_enable_asynccancel); nop +# define CDISABLE bl JUMPTARGET(__librt_disable_asynccancel); nop +# define __local_multiple_threads __librt_multiple_threads +# endif + +# ifdef HAVE_TLS_SUPPORT +# ifndef __ASSEMBLER__ +# define SINGLE_THREAD_P \ + __builtin_expect (THREAD_GETMEM (THREAD_SELF, p_multiple_threads) == 0, 1) +# else +# define SINGLE_THREAD_P \ + lwz 10,MULTIPLE_THREADS_OFFSET(13); \ + cmpwi 10,0 +# endif +# else /* !HAVE_TLS_SUPPORT */ +# ifndef __ASSEMBLER__ +extern int __local_multiple_threads +# if !defined NOT_IN_libc || defined IS_IN_libpthread + attribute_hidden; +# else + ; +# endif +# define SINGLE_THREAD_P __builtin_expect (__local_multiple_threads == 0, 1) +# else +# define SINGLE_THREAD_P \ + .section ".toc","aw"; \ +.LC__local_multiple_threads:; \ + .tc __local_multiple_threads[TC],__local_multiple_threads; \ + .previous; \ + ld 10,.LC__local_multiple_threads@toc(2); \ + lwz 10,0(10); \ + cmpwi 10,0 +# endif +# endif + +#elif !defined __ASSEMBLER__ + +/* This code should never be used but we define it anyhow. */ +# define SINGLE_THREAD_P (1) + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/powerpc/powerpc64/vfork.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/powerpc/powerpc64/vfork.S new file mode 100644 index 00000000..7a3cb82c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/powerpc/powerpc64/vfork.S @@ -0,0 +1,91 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#define _ERRNO_H 1 +#include +#include + +/* Clone the calling process, but without copying the whole address space. + The calling process is suspended until the new process exits or is + replaced by a call to `execve'. Return -1 for errors, 0 to the new process, + and the process ID of the new process to the old process. */ + +#ifdef SHARED + .section ".toc","aw" +.LC0: + .tc __libc_pthread_functions[TC],__libc_pthread_functions + .section ".text" + .align 2 +#endif + +ENTRY (__vfork) + +#ifdef __NR_vfork + +# ifdef SHARED + ld 10,.LC0@toc(2) + ld 10,0(10) + cmpwi 10,0 + bne- HIDDEN_JUMPTARGET(__fork) +# else + .weak pthread_create + lis 10,pthread_create@highest + ori 10,10,pthread_create@higher + sldi 10,10,32 + oris 10,10,pthread_create@h + ori 10,10,pthread_create@l + cmpwi 10,0 + bne- .Lhidden_fork +# endif + + DO_CALL (SYS_ify (vfork)); + +# ifdef __ASSUME_VFORK_SYSCALL + PSEUDO_RET +# else + bnslr+ + /* Check if vfork syscall is known at all. */ + cmpdi r3,ENOSYS +# ifdef SHARED + bne JUMPTARGET(__syscall_error) +# else + bne- .Lsyscall_error +# endif + +# endif +#endif + +#ifndef __ASSUME_VFORK_SYSCALL + /* If we don't have vfork, fork is close enough. */ + + DO_CALL (SYS_ify (fork)); + PSEUDO_RET +#endif + +# ifndef SHARED +.Lhidden_fork: + b HIDDEN_JUMPTARGET(__fork) +.Lsyscall_error: + b JUMPTARGET(__syscall_error) +# endif + +PSEUDO_END (__vfork) +libc_hidden_def (__vfork) + +weak_alias (__vfork, vfork) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/powerpc/ptlongjmp.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/powerpc/ptlongjmp.c new file mode 100644 index 00000000..177256c7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/powerpc/ptlongjmp.c @@ -0,0 +1,70 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1998 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +/* Redefine siglongjmp and longjmp so that they interact correctly + with cleanup handlers */ +/* Derived from linuxthreads/ptlongjmp.c & added AltiVec/VMX versioning. */ +#include "pthread.h" +#include +#include +#include +#if defined SHARED +# if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_3_4) + +/* These functions are not declared anywhere since they shouldn't be + used at another place but here. */ +extern void __novmx__libc_siglongjmp (sigjmp_buf env, int val) + __attribute__ ((noreturn)); +extern void __novmx__libc_longjmp (sigjmp_buf env, int val) + __attribute__ ((noreturn)); + + +void __novmx_siglongjmp (sigjmp_buf env, int val) +{ + __novmx__libc_siglongjmp (env, val); +} + +void __novmx_longjmp (jmp_buf env, int val) +{ + __novmx__libc_longjmp (env, val); +} + +# if __WORDSIZE == 64 +symbol_version (__novmx_longjmp,longjmp,GLIBC_2.3); +symbol_version (__novmx_siglongjmp,siglongjmp,GLIBC_2.3); +# else +symbol_version (__novmx_longjmp,longjmp,GLIBC_2.0); +symbol_version (__novmx_siglongjmp,siglongjmp,GLIBC_2.0); +# endif +# endif /* SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_3_4) ) */ + +/* These functions are not declared anywhere since they shouldn't be + used at another place but here. */ +extern void __vmx__libc_siglongjmp (sigjmp_buf env, int val) + __attribute__ ((noreturn)); +extern void __vmx__libc_longjmp (sigjmp_buf env, int val) + __attribute__ ((noreturn)); + +void __vmx_siglongjmp (sigjmp_buf env, int val) +{ + __vmx__libc_siglongjmp (env, val); +} + +void __vmx_longjmp (jmp_buf env, int val) +{ + __vmx__libc_longjmp (env, val); +} +default_symbol_version (__vmx_longjmp,longjmp,GLIBC_2.3.4); +default_symbol_version (__vmx_siglongjmp,siglongjmp,GLIBC_2.3.4); +#endif /* SHARED */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/pt-sigsuspend.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/pt-sigsuspend.c new file mode 100644 index 00000000..61398059 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/pt-sigsuspend.c @@ -0,0 +1,33 @@ +/* Internal sigsuspend system call for LinuxThreads. Generic Linux version. + Copyright (C) 2003, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +#include +#include + +#include + +void +__pthread_sigsuspend (const sigset_t *set) +{ + sigsuspend(set); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/raise.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/raise.c new file mode 100644 index 00000000..61209cfa --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/raise.c @@ -0,0 +1,43 @@ +/* Copyright (C) 1991, 1996, 2002, 2003, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +#ifndef IS_IN_rtld +# include + +# ifndef SHARED +weak_extern (__pthread_raise) +# endif +#endif + +/* Raise the signal SIG. */ +int +raise (sig) + int sig; +{ +#ifdef IS_IN_rtld + return __kill (__getpid (), sig); +#else + return __libc_maybe_call2 (pthread_raise, (sig), + __kill (__getpid (), sig)); +#endif +} +libc_hidden_def (raise) +weak_alias (raise, gsignal) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/register-atfork.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/register-atfork.c new file mode 100644 index 00000000..2dce262a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/register-atfork.c @@ -0,0 +1,87 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include "fork.h" + + +int +__register_atfork (prepare, parent, child, dso_handle) + void (*prepare) (void); + void (*parent) (void); + void (*child) (void); + void *dso_handle; +{ + struct fork_handler *new_prepare = NULL; + struct fork_handler *new_parent = NULL; + struct fork_handler *new_child = NULL; + + if (prepare != NULL) + { + new_prepare = (struct fork_handler *) malloc (sizeof (*new_prepare)); + if (new_prepare == NULL) + goto out1; + + new_prepare->handler = prepare; + new_prepare->dso_handle = dso_handle; + } + + if (parent != NULL) + { + new_parent = (struct fork_handler *) malloc (sizeof (*new_parent)); + if (new_parent == NULL) + goto out2; + + new_parent->handler = parent; + new_parent->dso_handle = dso_handle; + } + + if (child != NULL) + { + new_child = (struct fork_handler *) malloc (sizeof (*new_child)); + if (new_child == NULL) + { + free (new_parent); + out2: + free (new_prepare); + out1: + return errno; + } + + new_child->handler = child; + new_child->dso_handle = dso_handle; + } + + /* Get the lock to not conflict with running forks. */ + __libc_lock_lock (__fork_block.lock); + + /* Now that we have all the handlers allocate enqueue them. */ + if (new_prepare != NULL) + list_add_tail (&new_prepare->list, &__fork_block.prepare_list); + if (new_parent != NULL) + list_add_tail (&new_parent->list, &__fork_block.parent_list); + if (new_child != NULL) + list_add_tail (&new_child->list, &__fork_block.child_list); + + /* Release the lock. */ + __libc_lock_unlock (__fork_block.lock); + + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/s390/bits/typesizes.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/s390/bits/typesizes.h new file mode 100644 index 00000000..bee7639f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/s390/bits/typesizes.h @@ -0,0 +1,72 @@ +/* bits/typesizes.h -- underlying types for *_t. Linux/s390 version. + Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _BITS_TYPES_H +# error "Never include directly; use instead." +#endif + +#ifndef _BITS_TYPESIZES_H +#define _BITS_TYPESIZES_H 1 + +/* See for the meaning of these macros. This file exists so + that need not vary across different GNU platforms. */ + +#define __DEV_T_TYPE __UQUAD_TYPE +#define __UID_T_TYPE __U32_TYPE +#define __GID_T_TYPE __U32_TYPE +#define __INO_T_TYPE __ULONGWORD_TYPE +#define __INO64_T_TYPE __UQUAD_TYPE +#define __MODE_T_TYPE __U32_TYPE +#define __NLINK_T_TYPE __UWORD_TYPE +#define __OFF_T_TYPE __SLONGWORD_TYPE +#define __OFF64_T_TYPE __SQUAD_TYPE +#define __PID_T_TYPE __S32_TYPE +#define __RLIM_T_TYPE __ULONGWORD_TYPE +#define __RLIM64_T_TYPE __UQUAD_TYPE +#define __BLKCNT_T_TYPE __SLONGWORD_TYPE +#define __BLKCNT64_T_TYPE __SQUAD_TYPE +#define __FSBLKCNT_T_TYPE __ULONGWORD_TYPE +#define __FSBLKCNT64_T_TYPE __UQUAD_TYPE +#define __FSFILCNT_T_TYPE __ULONGWORD_TYPE +#define __FSFILCNT64_T_TYPE __UQUAD_TYPE +#define __ID_T_TYPE __U32_TYPE +#define __CLOCK_T_TYPE __SLONGWORD_TYPE +#define __TIME_T_TYPE __SLONGWORD_TYPE +#define __USECONDS_T_TYPE __U32_TYPE +#define __SUSECONDS_T_TYPE __SLONGWORD_TYPE +#define __DADDR_T_TYPE __S32_TYPE +#define __SWBLK_T_TYPE __SLONGWORD_TYPE +#define __KEY_T_TYPE __S32_TYPE +#define __CLOCKID_T_TYPE __S32_TYPE +#define __TIMER_T_TYPE __S32_TYPE +#define __BLKSIZE_T_TYPE __SLONGWORD_TYPE +#define __FSID_T_TYPE struct { int __val[2]; } +#if defined __GNUC__ && __GNUC__ <= 2 +/* Compatibility with g++ 2.95.x. */ +#define __SSIZE_T_TYPE __SWORD_TYPE +#else +/* size_t is unsigned long int on s390 -m31. */ +#define __SSIZE_T_TYPE __SLONGWORD_TYPE +#endif + +/* Number of descriptors that can fit in an `fd_set'. */ +#define __FD_SETSIZE 1024 + + +#endif /* bits/typesizes.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-32/pt-initfini.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-32/pt-initfini.c new file mode 100644 index 00000000..b7d901c4 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-32/pt-initfini.c @@ -0,0 +1,154 @@ +/* Special .init and .fini section support for S/390. + Copyright (C) 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it + and/or modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file with other + programs, and to distribute those programs without any restriction + coming from the use of this file. (The Lesser General Public + License restrictions do apply in other respects; for example, they + cover modification of the file, and distribution when not linked + into another program.) + + The GNU C Library is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* This file is compiled into assembly code which is then munged by a sed + script into two files: crti.s and crtn.s. + + * crti.s puts a function prologue at the beginning of the + .init and .fini sections and defines global symbols for + those addresses, so they can be called as functions. + + * crtn.s puts the corresponding function epilogues + in the .init and .fini sections. */ + +__asm__ ("\ +\n\ +#include \"defs.h\"\n\ +\n\ +/*@HEADER_ENDS*/\n\ +\n\ +/*@TESTS_BEGIN*/\n\ +\n\ +/*@TESTS_END*/\n\ +\n\ +/*@_init_PROLOG_BEGINS*/\n\ +\n\ + .section .init\n\ +#NO_APP\n\ + .align 4\n\ +.globl _init\n\ + .type _init,@function\n\ +_init:\n\ +# leaf function 0\n\ +# automatics 0\n\ +# outgoing args 0\n\ +# need frame pointer 0\n\ +# call alloca 0\n\ +# has varargs 0\n\ +# incoming args (stack) 0\n\ +# function length 36\n\ + STM 6,15,24(15)\n\ + BRAS 13,.LTN1_0\n\ +.LT1_0:\n\ +.LC13:\n\ + .long __pthread_initialize_minimal@PLT-.LT1_0\n\ +.LC14:\n\ + .long __gmon_start__@GOT\n\ +.LC15:\n\ + .long _GLOBAL_OFFSET_TABLE_-.LT1_0\n\ +.LTN1_0:\n\ + LR 1,15\n\ + AHI 15,-96\n\ + ST 1,0(15)\n\ + L 12,.LC15-.LT1_0(13)\n\ + AR 12,13\n\ + L 1,.LC13-.LT1_0(13)\n\ + LA 1,0(1,13)\n\ + BASR 14,1\n\ + L 1,.LC14-.LT1_0(13)\n\ + L 1,0(1,12)\n\ + LTR 1,1\n\ + JE .L22\n\ + BASR 14,1\n\ +.L22:\n\ +#APP\n\ + .align 4,0x07\n\ + END_INIT\n\ +\n\ +/*@_init_PROLOG_ENDS*/\n\ +\n\ +/*@_init_EPILOG_BEGINS*/\n\ + .align 4\n\ + .section .init\n\ +#NO_APP\n\ + .align 4\n\ + L 4,152(15)\n\ + LM 6,15,120(15)\n\ + BR 4\n\ +#APP\n\ + END_INIT\n\ +\n\ +/*@_init_EPILOG_ENDS*/\n\ +\n\ +/*@_fini_PROLOG_BEGINS*/\n\ + .section .fini\n\ +#NO_APP\n\ + .align 4\n\ +.globl _fini\n\ + .type _fini,@function\n\ +_fini:\n\ +# leaf function 0\n\ +# automatics 0\n\ +# outgoing args 0\n\ +# need frame pointer 0\n\ +# call alloca 0\n\ +# has varargs 0\n\ +# incoming args (stack) 0\n\ +# function length 30\n\ + STM 6,15,24(15)\n\ + BRAS 13,.LTN2_0\n\ +.LT2_0:\n\ +.LC17:\n\ + .long _GLOBAL_OFFSET_TABLE_-.LT2_0\n\ +.LTN2_0:\n\ + LR 1,15\n\ + AHI 15,-96\n\ + ST 1,0(15)\n\ + L 12,.LC17-.LT2_0(13)\n\ + AR 12,13\n\ +#APP\n\ + .align 4,0x07\n\ + END_FINI\n\ +\n\ +/*@_fini_PROLOG_ENDS*/\n\ +\n\ +/*@_fini_EPILOG_BEGINS*/\n\ + .align 4\n\ + .section .fini\n\ +#NO_APP\n\ + .align 4\n\ + L 4,152(15)\n\ + LM 6,15,120(15)\n\ + BR 4\n\ +#APP\n\ + END_FINI\n\ +\n\ +/*@_fini_EPILOG_ENDS*/\n\ +\n\ +/*@TRAILER_BEGINS*/\ +"); diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-32/sysdep-cancel.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-32/sysdep-cancel.h new file mode 100644 index 00000000..06f7aed7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-32/sysdep-cancel.h @@ -0,0 +1,137 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#ifndef __ASSEMBLER__ +# include +#endif + +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + +# if !defined NOT_IN_libc || defined IS_IN_libpthread + +# define PSEUDO_CANCEL(name, syscall_name, args) \ +L(pseudo_cancel): \ + STM_##args \ + stm %r12,%r15,48(%r15); \ + lr %r14,%r15; \ + ahi %r15,-96; \ + st %r14,0(%r15); \ + basr %r13,0; \ +0: l %r1,1f-0b(%r13); \ + bas %r14,0(%r1,%r13); \ + lr %r0,%r2; \ + LM_##args \ + DO_CALL(syscall_name, args); \ + l %r1,2f-0b(%r13); \ + lr %r12,%r2; \ + lr %r2,%r0; \ + bas %r14,0(%r1,%r13); \ + lr %r2,%r12; \ + lm %r12,%r15,48+96(%r15); \ + j L(pseudo_check); \ +1: .long CENABLE-0b; \ +2: .long CDISABLE-0b; + +# else /* !libc.so && !libpthread.so */ + +# define PSEUDO_CANCEL(name, syscall_name, args) \ +L(pseudo_cancel): \ + STM_##args \ + stm %r11,%r15,44(%r15); \ + lr %r14,%r15; \ + ahi %r15,-96; \ + st %r14,0(%r15); \ + basr %r13,0; \ +0: l %r12,3f-0b(%r13); \ + l %r1,1f-0b(%r13); \ + la %r12,0(%r12,%r13); \ + bas %r14,0(%r1,%r13); \ + lr %r0,%r2; \ + LM_##args \ + DO_CALL(syscall_name, args); \ + l %r1,2f-0b(%r13); \ + lr %r11,%r2; \ + lr %r2,%r0; \ + bas %r14,0(%r1,%r13); \ + lr %r2,%r11; \ + lm %r11,%r15,44+96(%r15); \ + j L(pseudo_check); \ +1: .long CENABLE@PLT-0b; \ +2: .long CDISABLE@PLT-0b; \ +3: .long _GLOBAL_OFFSET_TABLE_-0b; + +# endif + +# undef PSEUDO +# define PSEUDO(name, syscall_name, args) \ + .text; \ +PSEUDO_CANCEL(name, syscall_name, args) \ +ENTRY(name) \ + SINGLE_THREAD_P(%r1) \ + jne L(pseudo_cancel); \ + DO_CALL(syscall_name, args); \ +L(pseudo_check): \ + lhi %r4,-4095; \ + clr %r2,%r4; \ + jnl SYSCALL_ERROR_LABEL; \ +L(pseudo_end): + +# ifdef IS_IN_libpthread +# define CENABLE __pthread_enable_asynccancel +# define CDISABLE __pthread_disable_asynccancel +# elif !defined NOT_IN_libc +# define CENABLE __libc_enable_asynccancel +# define CDISABLE __libc_disable_asynccancel +# else +# define CENABLE __librt_enable_asynccancel +# define CDISABLE __librt_disable_asynccancel +# endif + +#define STM_0 /* Nothing */ +#define STM_1 st %r2,8(%r15); +#define STM_2 stm %r2,%r3,8(%r15); +#define STM_3 stm %r2,%r4,8(%r15); +#define STM_4 stm %r2,%r5,8(%r15); +#define STM_5 stm %r2,%r5,8(%r15); + +#define LM_0 /* Nothing */ +#define LM_1 l %r2,8+96(%r15); +#define LM_2 lm %r2,%r3,8+96(%r15); +#define LM_3 lm %r2,%r4,8+96(%r15); +#define LM_4 lm %r2,%r5,8+96(%r15); +#define LM_5 lm %r2,%r5,8+96(%r15); + +# ifndef __ASSEMBLER__ +# define SINGLE_THREAD_P \ + __builtin_expect (THREAD_GETMEM (THREAD_SELF, \ + p_header.data.multiple_threads) == 0, 1) +# else +# define SINGLE_THREAD_P(reg) \ + ear reg,%a0; \ + icm reg,15,MULTIPLE_THREADS_OFFSET(reg); +# endif + +#elif !defined __ASSEMBLER__ + +/* This code should never be used but we define it anyhow. */ +# define SINGLE_THREAD_P (1) + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-32/vfork.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-32/vfork.S new file mode 100644 index 00000000..6dfeca86 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-32/vfork.S @@ -0,0 +1,69 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Martin Schwidefsky + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#define _ERRNO_H 1 +#include + +/* Clone the calling process, but without copying the whole address space. + The calling process is suspended until the new process exits or is + replaced by a call to `execve'. Return -1 for errors, 0 to the new process, + and the process ID of the new process to the old process. */ + +ENTRY (__vfork) + basr %r1,0 +0: +#ifdef SHARED + al %r1,4f-0b(%r1) + l %r1,0(%r1) + ltr %r1,%r1 +#else + icm %r1,15,4f-0b(%r1) +#endif + jne 1f + + /* Do vfork system call. */ + svc SYS_ify (vfork) + + /* Check for error. */ + lhi %r4,-4095 + clr %r2,%r4 + jnl SYSCALL_ERROR_LABEL + + /* Normal return. */ + br %r14 +1: + basr %r1,0 +2: + al %r1,3f-2b(%r1) + br %r1 +3: + .long HIDDEN_JUMPTARGET(__fork)-2b +4: +#ifdef SHARED + .long __libc_pthread_functions-0b +#else + .weak pthread_create + .long pthread_create +#endif +PSEUDO_END(__vfork) + +libc_hidden_def (__vfork) + +weak_alias (__vfork, vfork) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-64/pt-initfini.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-64/pt-initfini.c new file mode 100644 index 00000000..540443e6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-64/pt-initfini.c @@ -0,0 +1,137 @@ +/* Special .init and .fini section support for 64 bit S/390. + Copyright (C) 2001 Free Software Foundation, Inc. + Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com). + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it + and/or modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file with other + programs, and to distribute those programs without any restriction + coming from the use of this file. (The Lesser General Public + License restrictions do apply in other respects; for example, they + cover modification of the file, and distribution when not linked + into another program.) + + The GNU C Library is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* This file is compiled into assembly code which is then munged by a sed + script into two files: crti.s and crtn.s. + + * crti.s puts a function prologue at the beginning of the + .init and .fini sections and defines global symbols for + those addresses, so they can be called as functions. + + * crtn.s puts the corresponding function epilogues + in the .init and .fini sections. */ + +__asm__ ("\ +\n\ +#include \"defs.h\"\n\ +\n\ +/*@HEADER_ENDS*/\n\ +\n\ +/*@TESTS_BEGIN*/\n\ +\n\ +/*@TESTS_END*/\n\ +\n\ +/*@_init_PROLOG_BEGINS*/\n\ +\n\ + .section .init\n\ +#NO_APP\n\ + .align 4\n\ +.globl _init\n\ + .type _init,@function\n\ +_init:\n\ +# leaf function 0\n\ +# automatics 0\n\ +# outgoing args 0\n\ +# need frame pointer 0\n\ +# call alloca 0\n\ +# has varargs 0\n\ +# incoming args (stack) 0\n\ +# function length 36\n\ + STMG 6,15,48(15)\n\ + LGR 1,15\n\ + AGHI 15,-160\n\ + STG 1,0(15)\n\ + LARL 12,_GLOBAL_OFFSET_TABLE_\n\ + BRASL 14,__pthread_initialize_minimal@PLT\n\ + LARL 1,__gmon_start__@GOTENT\n\ + LG 1,0(1)\n\ + LTGR 1,1\n\ + JE .L22\n\ + BASR 14,1\n\ +.L22:\n\ +#APP\n\ + .align 4,0x07\n\ + END_INIT\n\ +\n\ +/*@_init_PROLOG_ENDS*/\n\ +\n\ +/*@_init_EPILOG_BEGINS*/\n\ + .align 4\n\ + .section .init\n\ +#NO_APP\n\ + .align 4\n\ + LG 4,272(15)\n\ + LMG 6,15,208(15)\n\ + BR 4\n\ +#APP\n\ + END_INIT\n\ +\n\ +/*@_init_EPILOG_ENDS*/\n\ +\n\ +/*@_fini_PROLOG_BEGINS*/\n\ + .section .fini\n\ +#NO_APP\n\ + .align 4\n\ +.globl _fini\n\ + .type _fini,@function\n\ +_fini:\n\ +# leaf function 0\n\ +# automatics 0\n\ +# outgoing args 0\n\ +# need frame pointer 0\n\ +# call alloca 0\n\ +# has varargs 0\n\ +# incoming args (stack) 0\n\ +# function length 30\n\ + STMG 6,15,48(15)\n\ + LGR 1,15\n\ + AGHI 15,-160\n\ + STG 1,0(15)\n\ + LARL 12,_GLOBAL_OFFSET_TABLE_\n\ +#APP\n\ + .align 4,0x07\n\ + END_FINI\n\ +\n\ +/*@_fini_PROLOG_ENDS*/\n\ +\n\ +/*@_fini_EPILOG_BEGINS*/\n\ + .align 4\n\ + .section .fini\n\ +#NO_APP\n\ + .align 4\n\ + LG 4,272(15)\n\ + LMG 6,15,208(15)\n\ + BR 4\n\ +#APP\n\ + END_FINI\n\ +\n\ +/*@_fini_EPILOG_ENDS*/\n\ +\n\ +/*@TRAILER_BEGINS*/\n\ + "); diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-64/pt-sigsuspend.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-64/pt-sigsuspend.c new file mode 100644 index 00000000..d57283ad --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-64/pt-sigsuspend.c @@ -0,0 +1 @@ +#include "../../ia64/pt-sigsuspend.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h new file mode 100644 index 00000000..f71ef3f6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h @@ -0,0 +1,116 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#ifndef __ASSEMBLER__ +# include +#endif + +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + +# undef PSEUDO +# define PSEUDO(name, syscall_name, args) \ + .text; \ +L(pseudo_cancel): \ + STM_##args \ + stmg %r13,%r15,104(%r15); \ + lgr %r14,%r15; \ + aghi %r15,-160; \ + stg %r14,0(%r15); \ + brasl %r14,CENABLE; \ + lgr %r0,%r2; \ + LM_##args \ + DO_CALL(syscall_name, args); \ + lgr %r13,%r2; \ + lgr %r2,%r0; \ + brasl %r14,CDISABLE; \ + lgr %r2,%r13; \ + lmg %r13,%r15,104+160(%r15); \ + j L(pseudo_check); \ +ENTRY(name) \ + SINGLE_THREAD_P \ + jne L(pseudo_cancel); \ + DO_CALL(syscall_name, args); \ +L(pseudo_check): \ + lghi %r4,-4095; \ + clgr %r2,%r4; \ + jgnl SYSCALL_ERROR_LABEL; \ +L(pseudo_end): + +# ifdef IS_IN_libpthread +# define CENABLE __pthread_enable_asynccancel +# define CDISABLE __pthread_disable_asynccancel +# define __local_multiple_threads __pthread_multiple_threads +# elif !defined NOT_IN_libc +# define CENABLE __libc_enable_asynccancel +# define CDISABLE __libc_disable_asynccancel +# define __local_multiple_threads __libc_multiple_threads +# else +# define CENABLE __librt_enable_asynccancel@PLT +# define CDISABLE __librt_disable_asynccancel@PLT +# endif + +#define STM_0 /* Nothing */ +#define STM_1 stg %r2,16(%r15); +#define STM_2 stmg %r2,%r3,16(%r15); +#define STM_3 stmg %r2,%r4,16(%r15); +#define STM_4 stmg %r2,%r5,16(%r15); +#define STM_5 stmg %r2,%r5,16(%r15); + +#define LM_0 /* Nothing */ +#define LM_1 lg %r2,16+160(%r15); +#define LM_2 lmg %r2,%r3,16+160(%r15); +#define LM_3 lmg %r2,%r4,16+160(%r15); +#define LM_4 lmg %r2,%r5,16+160(%r15); +#define LM_5 lmg %r2,%r5,16+160(%r15); + +# if !defined NOT_IN_libc || defined IS_IN_libpthread +# ifndef __ASSEMBLER__ +extern int __local_multiple_threads attribute_hidden; +# define SINGLE_THREAD_P \ + __builtin_expect (__local_multiple_threads == 0, 1) +# else +# define SINGLE_THREAD_P \ + larl %r1,__local_multiple_threads; \ + icm %r0,15,0(%r1); +# endif + +# else + +# ifndef __ASSEMBLER__ +# define SINGLE_THREAD_P \ + __builtin_expect (THREAD_GETMEM (THREAD_SELF, \ + p_header.data.multiple_threads) == 0, 1) +# else +# define SINGLE_THREAD_P \ + ear %r1,%a0; \ + sllg %r1,%r1,32; \ + ear %r1,%a1; \ + icm %r1,15,MULTIPLE_THREADS_OFFSET(%r1); +# endif + +# endif + +#elif !defined __ASSEMBLER__ + +/* This code should never be used but we define it anyhow. */ +# define SINGLE_THREAD_P (1) + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-64/vfork.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-64/vfork.S new file mode 100644 index 00000000..199f0017 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-64/vfork.S @@ -0,0 +1,54 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Martin Schwidefsky + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#define _ERRNO_H 1 +#include + +/* Clone the calling process, but without copying the whole address space. + The calling process is suspended until the new process exits or is + replaced by a call to `execve'. Return -1 for errors, 0 to the new process, + and the process ID of the new process to the old process. */ + +ENTRY (__vfork) +#ifdef SHARED + larl %r1,__libc_pthread_functions + lg %r1,0(%r1) +#else + .weak pthread_create + larl %r1,pthread_create +#endif + ltgr %r1,%r1 + jgne HIDDEN_JUMPTARGET(__fork) + + /* Do vfork system call. */ + svc SYS_ify (vfork) + + /* Check for error. */ + lghi %r4,-4095 + clgr %r2,%r4 + jgnl SYSCALL_ERROR_LABEL + + /* Normal return. */ + br %r14 +PSEUDO_END(__vfork) + +libc_hidden_def (__vfork) + +weak_alias (__vfork, vfork) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sh/pt-initfini.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sh/pt-initfini.c new file mode 100644 index 00000000..1cdb98f0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sh/pt-initfini.c @@ -0,0 +1,143 @@ +/* Special .init and .fini section support for SH. Linuxthread version. + Copyright (C) 2000, 2001, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it + and/or modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file with other + programs, and to distribute those programs without any restriction + coming from the use of this file. (The Lesser General Public + License restrictions do apply in other respects; for example, they + cover modification of the file, and distribution when not linked + into another program.) + + The GNU C Library is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* This file is compiled into assembly code which is then munged by a sed + script into two files: crti.s and crtn.s. + + * crti.s puts a function prologue at the beginning of the + .init and .fini sections and defines global symbols for + those addresses, so they can be called as functions. + + * crtn.s puts the corresponding function epilogues + in the .init and .fini sections. */ + +__asm__ ("\n\ +\n\ +#include \"defs.h\"\n\ +\n\ +/*@HEADER_ENDS*/\n\ +\n\ +/*@TESTS_BEGIN*/\n\ +\n\ +/*@TESTS_END*/\n\ +\n\ +/*@_init_PROLOG_BEGINS*/\n\ + .section .init\n\ + .align 5\n\ + .global _init\n\ + .type _init,@function\n\ +_init:\n\ + mov.l r12,@-r15\n\ + mov.l r14,@-r15\n\ + sts.l pr,@-r15\n\ + mova .L22,r0\n\ + mov.l .L22,r12\n\ + add r0,r12\n\ + mova .L24,r0\n\ + mov.l .L24,r1\n\ + add r0,r1\n\ + jsr @r1\n\ + nop\n\ + mova .L23,r0\n\ + mov.l .L23,r1\n\ + add r0,r1\n\ + jsr @r1\n\ + mov r15,r14\n\ + bra 1f\n\ + nop\n\ + .align 2\n\ +.L22:\n\ + .long _GLOBAL_OFFSET_TABLE_\n\ +.L23:\n\ + .long __gmon_start__@PLT\n\ +.L24:\n\ + .long __pthread_initialize_minimal@PLT\n\ +1:\n\ + ALIGN\n\ + END_INIT\n\ +\n\ +/*@_init_PROLOG_ENDS*/\n\ +\n\ +/*@_init_EPILOG_BEGINS*/\n\ + .section .init\n\ + mov r14,r15\n\ + lds.l @r15+,pr\n\ + mov.l @r15+,r14\n\ + rts \n\ + mov.l @r15+,r12\n\ + END_INIT\n\ + .section .text\n\ + .align 5\n\ + .weak __gmon_start__\n\ + .type __gmon_start__,@function\n\ +__gmon_start__:\n\ + mov.l r14,@-r15\n\ + mov r15,r14\n\ + mov r14,r15\n\ + rts \n\ + mov.l @r15+,r14\n\ + \n\ +/*@_init_EPILOG_ENDS*/\n\ +\n\ +/*@_fini_PROLOG_BEGINS*/\n\ + .section .fini\n\ + .align 5\n\ + .global _fini\n\ + .type _fini,@function\n\ +_fini:\n\ + mov.l r12,@-r15\n\ + mov.l r14,@-r15\n\ + sts.l pr,@-r15\n\ + mova .L27,r0\n\ + mov.l .L27,r12\n\ + add r0,r12\n\ + mov r15,r14\n\ + ALIGN\n\ + END_FINI\n\ + bra 1f\n\ + nop\n\ + .align 2\n\ +.L27:\n\ + .long _GLOBAL_OFFSET_TABLE_\n\ +1:\n\ +/*@_fini_PROLOG_ENDS*/\n\ +\n\ +/*@_fini_EPILOG_BEGINS*/\n\ + .section .fini\n\ + mov r14,r15\n\ + lds.l @r15+,pr\n\ + mov.l @r15+,r14\n\ + rts \n\ + mov.l @r15+,r12\n\ +\n\ + END_FINI\n\ + \n\ +/*@_fini_EPILOG_ENDS*/\n\ +\n\ +/*@TRAILER_BEGINS*/\n\ +"); diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sh/smp.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sh/smp.h new file mode 100644 index 00000000..5e2f43cd --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sh/smp.h @@ -0,0 +1,24 @@ +/* Determine whether the host has multiple processors. SH version. + Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +static __inline__ int +is_smp_system (void) +{ + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sh/sysdep-cancel.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sh/sysdep-cancel.h new file mode 100644 index 00000000..48b2caad --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sh/sysdep-cancel.h @@ -0,0 +1,227 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#ifndef __ASSEMBLER__ +# include +#endif + +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + +# define _IMM12 #-12 +# define _IMM16 #-16 +# define _IMP16 #16 +# undef PSEUDO +# define PSEUDO(name, syscall_name, args) \ + .text; \ + ENTRY (name); \ + SINGLE_THREAD_P; \ + bf .Lpseudo_cancel; \ + DO_CALL (syscall_name, args); \ + mov r0,r1; \ + mov _IMM12,r2; \ + shad r2,r1; \ + not r1,r1; \ + tst r1,r1; \ + bt .Lsyscall_error; \ + bra .Lpseudo_end; \ + nop; \ + .Lpseudo_cancel: \ + sts.l pr,@-r15; \ + add _IMM16,r15; \ + SAVE_ARGS_##args; \ + CENABLE; \ + LOAD_ARGS_##args; \ + add _IMP16,r15; \ + lds.l @r15+,pr; \ + DO_CALL(syscall_name, args); \ + SYSCALL_INST_PAD; \ + sts.l pr,@-r15; \ + mov.l r0,@-r15; \ + CDISABLE; \ + mov.l @r15+,r0; \ + lds.l @r15+,pr; \ + mov r0,r1; \ + mov _IMM12,r2; \ + shad r2,r1; \ + not r1,r1; \ + tst r1,r1; \ + bf .Lpseudo_end; \ + .Lsyscall_error: \ + SYSCALL_ERROR_HANDLER; \ + .Lpseudo_end: + +# undef PSEUDO_END +# define PSEUDO_END(sym) \ + END (sym) + +# define SAVE_ARGS_0 /* Nothing. */ +# define SAVE_ARGS_1 SAVE_ARGS_0; mov.l r4,@(0,r15) +# define SAVE_ARGS_2 SAVE_ARGS_1; mov.l r5,@(4,r15) +# define SAVE_ARGS_3 SAVE_ARGS_2; mov.l r6,@(8,r15) +# define SAVE_ARGS_4 SAVE_ARGS_3; mov.l r7,@(12,r15) +# define SAVE_ARGS_5 SAVE_ARGS_4 +# define SAVE_ARGS_6 SAVE_ARGS_5 + +# define LOAD_ARGS_0 /* Nothing. */ +# define LOAD_ARGS_1 LOAD_ARGS_0; mov.l @(0,r15),r4 +# define LOAD_ARGS_2 LOAD_ARGS_1; mov.l @(4,r15),r5 +# define LOAD_ARGS_3 LOAD_ARGS_2; mov.l @(8,r15),r6 +# define LOAD_ARGS_4 LOAD_ARGS_3; mov.l @(12,r15),r7 +# define LOAD_ARGS_5 LOAD_ARGS_4 +# define LOAD_ARGS_6 LOAD_ARGS_5 + +# ifdef IS_IN_libpthread +# define __local_enable_asynccancel __pthread_enable_asynccancel +# define __local_disable_asynccancel __pthread_disable_asynccancel +# define __local_multiple_threads __pthread_multiple_threads +# elif !defined NOT_IN_libc +# define __local_enable_asynccancel __libc_enable_asynccancel +# define __local_disable_asynccancel __libc_disable_asynccancel +# define __local_multiple_threads __libc_multiple_threads +# else +# define __local_enable_asynccancel __librt_enable_asynccancel +# define __local_disable_asynccancel __librt_disable_asynccancel +# define __local_multiple_threads __librt_multiple_threads +# endif + +# if defined IS_IN_librt && defined __PIC__ +# define CENABLE \ + mov.l r12,@-r15; \ + mov.l 1f,r12; \ + mova 1f,r0; \ + add r0,r12; \ + mov.l 2f,r0; \ + bsrf r0; \ + nop; \ + 0: bra 3f; \ + mov r0,r2; \ + .align 2; \ + 1: .long _GLOBAL_OFFSET_TABLE_; \ + 2: .long __local_enable_asynccancel@PLT - (0b-.); \ + 3: mov.l @r15+,r12 + +# define CDISABLE \ + mov.l r12,@-r15; \ + mov.l 1f,r12; \ + mova 1f,r0; \ + add r0,r12; \ + mov.l 2f,r0; \ + bsrf r0; \ + mov r2,r4; \ + 0: bra 3f; \ + nop; \ + .align 2; \ + 1: .long _GLOBAL_OFFSET_TABLE_; \ + 2: .long __local_disable_asynccancel@PLT - (0b-.); \ + 3: mov.l @r15+,r12 +# else +# define CENABLE \ + mov.l 1f,r0; \ + bsrf r0; \ + nop; \ + 0: bra 2f; \ + mov r0,r2; \ + .align 2; \ + 1: .long __local_enable_asynccancel - 0b; \ + 2: + +# define CDISABLE \ + mov.l 1f,r0; \ + bsrf r0; \ + mov r2,r4; \ + 0: bra 2f; \ + nop; \ + .align 2; \ + 1: .long __local_disable_asynccancel - 0b; \ + 2: +# endif + +# ifndef __ASSEMBLER__ +# if defined FLOATING_STACKS && USE___THREAD && defined __PIC__ +# define SINGLE_THREAD_P \ + __builtin_expect (THREAD_GETMEM (THREAD_SELF, p_multiple_threads) == 0, 1) +# else +extern int __local_multiple_threads attribute_hidden; +# define SINGLE_THREAD_P __builtin_expect (__local_multiple_threads == 0, 1) +# endif +# else +# if !defined __PIC__ +# define SINGLE_THREAD_P \ + mov.l 1f,r0; \ + mov.l @r0,r0; \ + bra 2f; \ + tst r0,r0; \ + .align 2; \ + 1: .long __local_multiple_threads; \ + 2: +# elif defined FLOATING_STACKS && USE___THREAD +# define SINGLE_THREAD_P \ + stc gbr,r0; \ + mov.w 0f,r1; \ + sub r1,r0; \ + mov.l @(MULTIPLE_THREADS_OFFSET,r0),r0; \ + bra 1f; \ + tst r0,r0; \ + 0: .word TLS_PRE_TCB_SIZE; \ + 1: + +# else +# if !defined NOT_IN_libc || defined IS_IN_libpthread +# define SINGLE_THREAD_P \ + mov r12,r2; \ + mov.l 0f,r12; \ + mova 0f,r0; \ + add r0,r12; \ + mov.l 1f,r0; \ + mov.l @(r0,r12),r0; \ + mov r2,r12; \ + bra 2f; \ + tst r0,r0; \ + .align 2; \ + 0: .long _GLOBAL_OFFSET_TABLE_; \ + 1: .long __local_multiple_threads@GOTOFF; \ + 2: +# else +# define SINGLE_THREAD_P \ + mov r12,r2; \ + mov.l 0f,r12; \ + mova 0f,r0; \ + add r0,r12; \ + mov.l 1f,r0; \ + mov.l @(r0,r12),r0; \ + mov.l @r0,r0; \ + mov r2,r12; \ + bra 2f; \ + tst r0,r0; \ + .align 2; \ + 0: .long _GLOBAL_OFFSET_TABLE_; \ + 1: .long __local_multiple_threads@GOT; \ + 2: +# endif +# endif +# endif + +#elif !defined __ASSEMBLER__ + +/* This code should never be used but we define it anyhow. */ +# define SINGLE_THREAD_P (1) + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sh/vfork.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sh/vfork.S new file mode 100644 index 00000000..e933eefd --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sh/vfork.S @@ -0,0 +1,78 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#define _ERRNO_H 1 +#include +#include + +/* Clone the calling process, but without copying the whole address space. + The calling process is suspended until the new process exits or is + replaced by a call to `execve'. Return -1 for errors, 0 to the new process, + and the process ID of the new process to the old process. */ + +ENTRY (__vfork) +#ifdef SHARED + mov.l .Lgot, r1 + mova .Lgot, r0 + add r0, r1 + mov.l .Lpthread_func, r0 + mov.l @(r0,r1), r0 +#else + mov.l .Lpthread_create, r0 +#endif + tst r0, r0 + bf .Lhidden_fork + + mov.w .L1, r3 + trapa #__SH_SYSCALL_TRAP_BASE + mov r0, r1 + mov #-12, r2 + shad r2, r1 + not r1, r1 /* r1=0 means r0 = -1 to -4095 */ + tst r1, r1 /* i.e. error in linux */ + bf .Lpseudo_end + SYSCALL_ERROR_HANDLER +.Lpseudo_end: + rts + nop +.L1: .word __NR_vfork + .align 2 +#ifdef SHARED +.Lgot: + .long _GLOBAL_OFFSET_TABLE_ +.Lpthread_func: + .long __libc_pthread_functions@GOTOFF +#else +.Lpthread_create: + .weak pthread_create + .long pthread_create +#endif + +.Lhidden_fork: + mov.l .L2, r1 + braf r1 + nop +1: + .align 2 +.L2: .long HIDDEN_JUMPTARGET(__fork)-1b + +PSEUDO_END (__vfork) +libc_hidden_def (__vfork) + +weak_alias (__vfork, vfork) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sigwait.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sigwait.c new file mode 100644 index 00000000..859cad5e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sigwait.c @@ -0,0 +1,83 @@ +/* Copyright (C) 1997, 1998, 2000, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#define __need_NULL +#include + +#include +#include +#include + +extern int __syscall_rt_sigtimedwait (const sigset_t *, siginfo_t *, + const struct timespec *, size_t); + + +/* Return any pending signal or wait for one for the given time. */ +static __inline__ int +do_sigwait (const sigset_t *set, int *sig) +{ + int ret; + + /* XXX The size argument hopefully will have to be changed to the + real size of the user-level sigset_t. */ +#ifdef INTERNAL_SYSCALL + INTERNAL_SYSCALL_DECL (err); + ret = INTERNAL_SYSCALL (rt_sigtimedwait, err, 4, set, + NULL, NULL, _NSIG / 8); + if (! INTERNAL_SYSCALL_ERROR_P (ret, err)) + { + *sig = ret; + ret = 0; + } + else + ret = INTERNAL_SYSCALL_ERRNO (ret, err); +#else + ret = INLINE_SYSCALL (rt_sigtimedwait, 4, set, + NULL, NULL, _NSIG / 8); + if (ret != -1) + { + *sig = ret; + ret = 0; + } + else + ret = errno; +#endif + + return ret; +} + +#ifndef SHARED +weak_extern (__pthread_sigwait) +#endif + +int +sigwait (const sigset_t *set, int *sig) +{ +#ifndef NOT_IN_libc + return __libc_maybe_call2 (pthread_sigwait, (set, sig), + do_sigwait (set, sig)); +#else + return do_sigwait (set, sig); +#endif +} +strong_alias(sigwait, __libc_sigwait) + +/* Cancellation is handled in __pthread_sigwait. */ +LIBC_CANCEL_HANDLED (); diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/smp.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/smp.h new file mode 100644 index 00000000..9ab75e8e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/smp.h @@ -0,0 +1,48 @@ +/* Determine whether the host has multiple processors. Linux version. + Copyright (C) 1996, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include + +/* Test whether the machine has more than one processor. This is not the + best test but good enough. More complicated tests would require `malloc' + which is not available at that time. */ +static __inline__ int +is_smp_system (void) +{ + static const int sysctl_args[] = { CTL_KERN, KERN_VERSION }; + char buf[512]; + size_t reslen = sizeof (buf); + + /* Try reading the number using `sysctl' first. */ + if (__sysctl ((int *) sysctl_args, + sizeof (sysctl_args) / sizeof (sysctl_args[0]), + buf, &reslen, NULL, 0) < 0) + { + /* This was not successful. Now try reading the /proc filesystem. */ + int fd = __open ("/proc/sys/kernel/version", O_RDONLY); + if (__builtin_expect (fd, 0) == -1 + || (reslen = __read (fd, buf, sizeof (buf))) <= 0) + /* This also didn't work. We give up and say it's a UP machine. */ + buf[0] = '\0'; + + __close (fd); + } + + return strstr (buf, "SMP") != NULL; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sparc/aio_cancel.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sparc/aio_cancel.c new file mode 100644 index 00000000..0d6da829 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sparc/aio_cancel.c @@ -0,0 +1,33 @@ +#include + +#define aio_cancel64 XXX +#include +#undef aio_cancel64 +#include + +extern __typeof (aio_cancel) __new_aio_cancel; +extern __typeof (aio_cancel) __old_aio_cancel; + +#define aio_cancel __new_aio_cancel + +#include + +#undef aio_cancel +strong_alias (__new_aio_cancel, __new_aio_cancel64); +versioned_symbol (librt, __new_aio_cancel, aio_cancel, GLIBC_2_3); +versioned_symbol (librt, __new_aio_cancel64, aio_cancel64, GLIBC_2_3); + +#if SHLIB_COMPAT (librt, GLIBC_2_1, GLIBC_2_3) + +#undef ECANCELED +#define aio_cancel __old_aio_cancel +#define ECANCELED 125 + +#include + +#undef aio_cancel +strong_alias (__old_aio_cancel, __old_aio_cancel64); +compat_symbol (librt, __old_aio_cancel, aio_cancel, GLIBC_2_1); +compat_symbol (librt, __old_aio_cancel64, aio_cancel64, GLIBC_2_1); + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sparc/bits/local_lim.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sparc/bits/local_lim.h new file mode 100644 index 00000000..27ffa668 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sparc/bits/local_lim.h @@ -0,0 +1,92 @@ +/* Minimum guaranteed maximum values for system limits. Linux/SPARC version. + Copyright (C) 1993-1998,2000,2002,2003,2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* The kernel header pollutes the namespace with the NR_OPEN symbol + and defines LINK_MAX although filesystems have different maxima. A + similar thing is true for OPEN_MAX: the limit can be changed at + runtime and therefore the macro must not be defined. Remove this + after including the header if necessary. */ +#ifndef NR_OPEN +# define __undef_NR_OPEN +#endif +#ifndef LINK_MAX +# define __undef_LINK_MAX +#endif +#ifndef OPEN_MAX +# define __undef_OPEN_MAX +#endif + +/* The kernel sources contain a file with all the needed information. */ +#include + +/* Have to remove NR_OPEN? */ +#ifdef __undef_NR_OPEN +# undef NR_OPEN +# undef __undef_NR_OPEN +#endif +/* Have to remove LINK_MAX? */ +#ifdef __undef_LINK_MAX +# undef LINK_MAX +# undef __undef_LINK_MAX +#endif +/* Have to remove OPEN_MAX? */ +#ifdef __undef_OPEN_MAX +# undef OPEN_MAX +# undef __undef_OPEN_MAX +#endif + +/* The number of data keys per process. */ +#define _POSIX_THREAD_KEYS_MAX 128 +/* This is the value this implementation supports. */ +#define PTHREAD_KEYS_MAX 1024 + +/* Controlling the iterations of destructors for thread-specific data. */ +#define _POSIX_THREAD_DESTRUCTOR_ITERATIONS 4 +/* Number of iterations this implementation does. */ +#define PTHREAD_DESTRUCTOR_ITERATIONS _POSIX_THREAD_DESTRUCTOR_ITERATIONS + +/* The number of threads per process. */ +#define _POSIX_THREAD_THREADS_MAX 64 +/* This is the value this implementation supports. */ +#define PTHREAD_THREADS_MAX 16384 + +/* Maximum amount by which a process can descrease its asynchronous I/O + priority level. */ +#define AIO_PRIO_DELTA_MAX 20 + +/* Minimum size for a thread. We are free to choose a reasonable value. */ +#define PTHREAD_STACK_MIN 24576 + +/* Maximum number of POSIX timers available. */ +#define TIMER_MAX 256 + +/* Maximum number of timer expiration overruns. */ +#define DELAYTIMER_MAX 2147483647 + +/* Maximum tty name length. */ +#define TTY_NAME_MAX 32 + +/* Maximum login name length. This is arbitrary. */ +#define LOGIN_NAME_MAX 256 + +/* Maximum host name length. */ +#define HOST_NAME_MAX 64 + +/* Maximum message queue priority level. */ +#define MQ_PRIO_MAX 32768 diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sparc/bits/typesizes.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sparc/bits/typesizes.h new file mode 100644 index 00000000..7e425378 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sparc/bits/typesizes.h @@ -0,0 +1,66 @@ +/* bits/typesizes.h -- underlying types for *_t. Linux/SPARC version. + Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _BITS_TYPES_H +# error "Never include directly; use instead." +#endif + +#ifndef _BITS_TYPESIZES_H +#define _BITS_TYPESIZES_H 1 + +/* See for the meaning of these macros. This file exists so + that need not vary across different GNU platforms. */ + +#define __DEV_T_TYPE __UQUAD_TYPE +#define __UID_T_TYPE __U32_TYPE +#define __GID_T_TYPE __U32_TYPE +#define __INO_T_TYPE __ULONGWORD_TYPE +#define __INO64_T_TYPE __UQUAD_TYPE +#define __MODE_T_TYPE __U32_TYPE +#define __NLINK_T_TYPE __U32_TYPE +#define __OFF_T_TYPE __SLONGWORD_TYPE +#define __OFF64_T_TYPE __SQUAD_TYPE +#define __PID_T_TYPE __S32_TYPE +#define __RLIM_T_TYPE __ULONGWORD_TYPE +#define __RLIM64_T_TYPE __UQUAD_TYPE +#define __BLKCNT_T_TYPE __SLONGWORD_TYPE +#define __BLKCNT64_T_TYPE __SQUAD_TYPE +#define __FSBLKCNT_T_TYPE __ULONGWORD_TYPE +#define __FSBLKCNT64_T_TYPE __UQUAD_TYPE +#define __FSFILCNT_T_TYPE __ULONGWORD_TYPE +#define __FSFILCNT64_T_TYPE __UQUAD_TYPE +#define __ID_T_TYPE __U32_TYPE +#define __CLOCK_T_TYPE __SLONGWORD_TYPE +#define __TIME_T_TYPE __SLONGWORD_TYPE +#define __USECONDS_T_TYPE __U32_TYPE +#define __SUSECONDS_T_TYPE __S32_TYPE +#define __DADDR_T_TYPE __S32_TYPE +#define __SWBLK_T_TYPE __SLONGWORD_TYPE +#define __KEY_T_TYPE __S32_TYPE +#define __CLOCKID_T_TYPE __S32_TYPE +#define __TIMER_T_TYPE __S32_TYPE +#define __BLKSIZE_T_TYPE __SLONGWORD_TYPE +#define __FSID_T_TYPE struct { int __val[2]; } +#define __SSIZE_T_TYPE __SWORD_TYPE + +/* Number of descriptors that can fit in an `fd_set'. */ +#define __FD_SETSIZE 1024 + + +#endif /* bits/typesizes.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sparc/fork.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sparc/fork.h new file mode 100644 index 00000000..5af3bdac --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sparc/fork.h @@ -0,0 +1,21 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include_next + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc32/sysdep-cancel.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc32/sysdep-cancel.h new file mode 100644 index 00000000..7bab35ee --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc32/sysdep-cancel.h @@ -0,0 +1,101 @@ +/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#ifndef __ASSEMBLER__ +# include +#endif + +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + +# undef PSEUDO +# define PSEUDO(name, syscall_name, args) \ + .text; \ +ENTRY(name) \ + ld [%g7 + MULTIPLE_THREADS_OFFSET], %g1; \ + cmp %g1, 0; \ + bne 1f; \ + mov SYS_ify(syscall_name), %g1; \ + ta 0x10; \ + bcs __syscall_error_handler; \ + nop; \ + .subsection 2; \ +1: save %sp, -96, %sp; \ + CENABLE; \ + nop; \ + mov %o0, %l0; \ + COPY_ARGS_##args \ + mov SYS_ify(syscall_name), %g1; \ + ta 0x10; \ + bcs __syscall_error_handler2; \ + mov %o0, %l1; \ + CDISABLE; \ + mov %l0, %o0; \ + jmpl %i7 + 8, %g0; \ + restore %g0, %l1, %o0; \ + .previous; \ + SYSCALL_ERROR_HANDLER \ + SYSCALL_ERROR_HANDLER2 + +#define SYSCALL_ERROR_HANDLER2 \ +SYSCALL_ERROR_HANDLER_ENTRY(__syscall_error_handler2) \ + .global __errno_location; \ + .type __errno_location,@function; \ + CDISABLE; \ + mov %l0, %o0; \ + call __errno_location; \ + nop; \ + st %l1, [%o0]; \ + jmpl %i7 + 8, %g0; \ + restore %g0, -1, %o0; \ + .previous; + +# ifdef IS_IN_libpthread +# define CENABLE call __pthread_enable_asynccancel +# define CDISABLE call __pthread_disable_asynccancel +# elif !defined NOT_IN_libc +# define CENABLE call __libc_enable_asynccancel +# define CDISABLE call __libc_disable_asynccancel +# else +# define CENABLE call __librt_enable_asynccancel +# define CDISABLE call __librt_disable_asynccancel +# endif + +#define COPY_ARGS_0 /* Nothing */ +#define COPY_ARGS_1 COPY_ARGS_0 mov %i0, %o0; +#define COPY_ARGS_2 COPY_ARGS_1 mov %i1, %o1; +#define COPY_ARGS_3 COPY_ARGS_2 mov %i2, %o2; +#define COPY_ARGS_4 COPY_ARGS_3 mov %i3, %o3; +#define COPY_ARGS_5 COPY_ARGS_4 mov %i4, %o4; +#define COPY_ARGS_6 COPY_ARGS_5 mov %i5, %o5; + +# ifndef __ASSEMBLER__ +# define SINGLE_THREAD_P \ + __builtin_expect (THREAD_GETMEM (THREAD_SELF, \ + p_header.data.multiple_threads) == 0, 1) +# else +# define SINGLE_THREAD_P ld [%g7 + MULTIPLE_THREADS_OFFSET], %g1 +# endif + +#elif !defined __ASSEMBLER__ + +/* This code should never be used but we define it anyhow. */ +# define SINGLE_THREAD_P (1) + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc32/vfork.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc32/vfork.S new file mode 100644 index 00000000..132da67a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc32/vfork.S @@ -0,0 +1,65 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + + .text +#ifdef SHARED +.LLGETPC0: + retl + add %o7, %o0, %o0 +#endif +ENTRY(__vfork) +#ifdef SHARED + mov %o7, %o1 + sethi %hi(_GLOBAL_OFFSET_TABLE_-4), %o0 + call .LLGETPC0 + add %o0, %lo(_GLOBAL_OFFSET_TABLE_+4), %o0 + sethi %hi(__libc_pthread_functions), %o2 + mov %o1, %o7 + or %o2, %lo(__libc_pthread_functions), %o2 + ld [%o0 + %o2], %o2 + ld [%o2], %o2 + cmp %o2, 0 +#else + .weak pthread_create + sethi %hi(pthread_create), %o0 + orcc %o0, %lo(pthread_create), %o0 +#endif +#if defined SHARED && !defined BROKEN_SPARC_WDISP22 + bne HIDDEN_JUMPTARGET(__fork) +#else + bne 1f +#endif + mov __NR_vfork, %g1 + ta 0x10 + bcs __syscall_error_handler + nop + sub %o1, 1, %o1 + retl + and %o0, %o1, %o0 +#if !defined SHARED || defined BROKEN_SPARC_WDISP22 +1: mov %o7, %g1 + call HIDDEN_JUMPTARGET(__fork) + mov %g1, %o7 +#endif + SYSCALL_ERROR_HANDLER +PSEUDO_END (__vfork) +libc_hidden_def (__vfork) +weak_alias (__vfork, vfork) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc64/pt-sigsuspend.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc64/pt-sigsuspend.c new file mode 100644 index 00000000..d57283ad --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc64/pt-sigsuspend.c @@ -0,0 +1 @@ +#include "../../ia64/pt-sigsuspend.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc64/sysdep-cancel.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc64/sysdep-cancel.h new file mode 100644 index 00000000..62eec71a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc64/sysdep-cancel.h @@ -0,0 +1,100 @@ +/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#ifndef __ASSEMBLER__ +# include +#endif + +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + +# undef PSEUDO +# define PSEUDO(name, syscall_name, args) \ + .text; \ +ENTRY(name) \ + ld [%g7 + MULTIPLE_THREADS_OFFSET], %g1; \ + brnz,pn %g1, 1f; \ + mov SYS_ify(syscall_name), %g1; \ + ta 0x6d; \ + bcs,pn %xcc, __syscall_error_handler; \ + nop; \ + .subsection 2; \ +1: save %sp, -192, %sp; \ + CENABLE; \ + nop; \ + mov %o0, %l0; \ + COPY_ARGS_##args \ + mov SYS_ify(syscall_name), %g1; \ + ta 0x6d; \ + bcs,pn %xcc, __syscall_error_handler2; \ + mov %o0, %l1; \ + CDISABLE; \ + mov %l0, %o0; \ + jmpl %i7 + 8, %g0; \ + restore %g0, %l1, %o0; \ + .previous; \ + SYSCALL_ERROR_HANDLER \ + SYSCALL_ERROR_HANDLER2 + +#define SYSCALL_ERROR_HANDLER2 \ +SYSCALL_ERROR_HANDLER_ENTRY(__syscall_error_handler2) \ + .global __errno_location; \ + .type __errno_location,@function; \ + CDISABLE; \ + mov %l0, %o0; \ + call __errno_location; \ + nop; \ + st %l1, [%o0]; \ + jmpl %i7 + 8, %g0; \ + restore %g0, -1, %o0; \ + .previous; + +# ifdef IS_IN_libpthread +# define CENABLE call __pthread_enable_asynccancel +# define CDISABLE call __pthread_disable_asynccancel +# elif !defined NOT_IN_libc +# define CENABLE call __libc_enable_asynccancel +# define CDISABLE call __libc_disable_asynccancel +# else +# define CENABLE call __librt_enable_asynccancel +# define CDISABLE call __librt_disable_asynccancel +# endif + +#define COPY_ARGS_0 /* Nothing */ +#define COPY_ARGS_1 COPY_ARGS_0 mov %i0, %o0; +#define COPY_ARGS_2 COPY_ARGS_1 mov %i1, %o1; +#define COPY_ARGS_3 COPY_ARGS_2 mov %i2, %o2; +#define COPY_ARGS_4 COPY_ARGS_3 mov %i3, %o3; +#define COPY_ARGS_5 COPY_ARGS_4 mov %i4, %o4; +#define COPY_ARGS_6 COPY_ARGS_5 mov %i5, %o5; + +# ifndef __ASSEMBLER__ +# define SINGLE_THREAD_P \ + __builtin_expect (THREAD_GETMEM (THREAD_SELF, \ + p_header.data.multiple_threads) == 0, 1) +# else +# define SINGLE_THREAD_P ld [%g7 + MULTIPLE_THREADS_OFFSET], %g1 +# endif + +#elif !defined __ASSEMBLER__ + +/* This code should never be used but we define it anyhow. */ +# define SINGLE_THREAD_P (1) + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc64/vfork.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc64/vfork.S new file mode 100644 index 00000000..8a6d2771 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sparc/sparc64/vfork.S @@ -0,0 +1,64 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#ifdef SHARED +.LLGETPC0: + retl + add %o7, %o0, %o0 +#endif +ENTRY(__vfork) +#ifdef SHARED + mov %o7, %o1 + sethi %hi(_GLOBAL_OFFSET_TABLE_-4), %o0 + call .LLGETPC0 + add %o0, %lo(_GLOBAL_OFFSET_TABLE_+4), %o0 + sethi %hi(__libc_pthread_functions), %o2 + mov %o1, %o7 + or %o2, %lo(__libc_pthread_functions), %o2 + ldx [%o0 + %o2], %o2 + ldx [%o2], %o0 +#else + .weak pthread_create + sethi %hi(pthread_create), %o0 + or %o0, %lo(pthread_create), %o0 +#endif +#if defined SHARED && !defined BROKEN_SPARC_WDISP22 + cmp %o0, 0 + bne HIDDEN_JUMPTARGET(__fork) +#else + brnz,pn %o0, 1f +#endif + mov __NR_vfork, %g1 + ta 0x6d + bcs,pn %xcc, __syscall_error_handler + nop + sub %o1, 1, %o1 + retl + and %o0, %o1, %o0 +#if !defined SHARED || defined BROKEN_SPARC_WDISP22 +1: mov %o7, %g1 + call HIDDEN_JUMPTARGET(__fork) + mov %g1, %o7 +#endif + SYSCALL_ERROR_HANDLER +PSEUDO_END (__vfork) +libc_hidden_def (__vfork) +weak_alias (__vfork, vfork) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sparc/sysdep-cancel.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sparc/sysdep-cancel.h new file mode 100644 index 00000000..fa656b34 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/sparc/sysdep-cancel.h @@ -0,0 +1,10 @@ +#ifndef SPARC_SYSDEP_CANCEL_H +#define SPARC_SYSDEP_CANCEL_H + +#if defined(__arch64__) +#include +#else +#include +#endif + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/unregister-atfork.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/unregister-atfork.c new file mode 100644 index 00000000..dad273fd --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/unregister-atfork.c @@ -0,0 +1,49 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include "fork.h" + + +void +__unregister_atfork (dso_handle) + void *dso_handle; +{ + /* Get the lock to not conflict with running forks. */ + __libc_lock_lock (__fork_block.lock); + + list_t *runp; + list_t *prevp; + + list_for_each_prev_safe (runp, prevp, &__fork_block.prepare_list) + if (list_entry (runp, struct fork_handler, list)->dso_handle == dso_handle) + list_del (runp); + + list_for_each_prev_safe (runp, prevp, &__fork_block.parent_list) + if (list_entry (runp, struct fork_handler, list)->dso_handle == dso_handle) + list_del (runp); + + list_for_each_prev_safe (runp, prevp, &__fork_block.child_list) + if (list_entry (runp, struct fork_handler, list)->dso_handle == dso_handle) + list_del (runp); + + /* Release the lock. */ + __libc_lock_unlock (__fork_block.lock); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/x86_64/pt-sigsuspend.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/x86_64/pt-sigsuspend.c new file mode 100644 index 00000000..3a0c2afc --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/x86_64/pt-sigsuspend.c @@ -0,0 +1 @@ +#include "../ia64/pt-sigsuspend.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h new file mode 100644 index 00000000..e82e6dfd --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h @@ -0,0 +1,132 @@ +/* Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#ifndef __ASSEMBLER__ +# include +#endif + +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + +# undef PSEUDO +# define PSEUDO(name, syscall_name, args) \ + .text; \ + ENTRY (name) \ + SINGLE_THREAD_P; \ + jne L(pseudo_cancel); \ + DO_CALL (syscall_name, args); \ + cmpq $-4095, %rax; \ + jae SYSCALL_ERROR_LABEL; \ + ret; \ + L(pseudo_cancel): \ + /* Save registers that might get destroyed. */ \ + SAVESTK_##args \ + PUSHARGS_##args \ + CENABLE \ + /* Restore registers. */ \ + POPARGS_##args \ + /* The return value from CENABLE is argument for CDISABLE. */ \ + movq %rax, (%rsp); \ + movl $SYS_ify (syscall_name), %eax; \ + syscall; \ + movq (%rsp), %rdi; \ + /* Save %rax since it's the error code from the syscall. */ \ + movq %rax, 8(%rsp); \ + CDISABLE \ + movq 8(%rsp), %rax; \ + RESTSTK_##args \ + cmpq $-4095, %rax; \ + jae SYSCALL_ERROR_LABEL; \ + L(pseudo_end): + +# define PUSHARGS_0 /* Nothing. */ +# define PUSHARGS_1 PUSHARGS_0 movq %rdi, 8(%rsp); +# define PUSHARGS_2 PUSHARGS_1 movq %rsi, 16(%rsp); +# define PUSHARGS_3 PUSHARGS_2 movq %rdx, 24(%rsp); +# define PUSHARGS_4 PUSHARGS_3 movq %rcx, 32(%rsp); +# define PUSHARGS_5 PUSHARGS_4 movq %r8, 40(%rsp); +# define PUSHARGS_6 PUSHARGS_5 movq %r9, 48(%rsp); + +# define POPARGS_0 /* Nothing. */ +# define POPARGS_1 POPARGS_0 movq 8(%rsp), %rdi; +# define POPARGS_2 POPARGS_1 movq 16(%rsp), %rsi; +# define POPARGS_3 POPARGS_2 movq 24(%rsp), %rdx; +# define POPARGS_4 POPARGS_3 movq 32(%rsp), %r10; +# define POPARGS_5 POPARGS_4 movq 40(%rsp), %r8; +# define POPARGS_6 POPARGS_5 movq 48(%rsp), %r9; + +/* We always have to align the stack before calling a function. */ +# define SAVESTK_0 subq $24, %rsp;cfi_adjust_cfa_offset(24); +# define SAVESTK_1 SAVESTK_0 +# define SAVESTK_2 SAVESTK_1 +# define SAVESTK_3 subq $40, %rsp;cfi_adjust_cfa_offset(40); +# define SAVESTK_4 SAVESTK_3 +# define SAVESTK_5 subq $56, %rsp;cfi_adjust_cfa_offset(56); +# define SAVESTK_6 SAVESTK_5 + +# define RESTSTK_0 addq $24,%rsp;cfi_adjust_cfa_offset(-24); +# define RESTSTK_1 RESTSTK_0 +# define RESTSTK_2 RESTSTK_1 +# define RESTSTK_3 addq $40, %rsp;cfi_adjust_cfa_offset(-40); +# define RESTSTK_4 RESTSTK_3 +# define RESTSTK_5 addq $56, %rsp;cfi_adjust_cfa_offset(-56); +# define RESTSTK_6 RESTSTK_5 + +# ifdef IS_IN_libpthread +# define CENABLE call __pthread_enable_asynccancel; +# define CDISABLE call __pthread_disable_asynccancel; +# define __local_multiple_threads __pthread_multiple_threads +# elif !defined NOT_IN_libc +# define CENABLE call __libc_enable_asynccancel; +# define CDISABLE call __libc_disable_asynccancel; +# define __local_multiple_threads __libc_multiple_threads +# else +# define CENABLE call __librt_enable_asynccancel@plt; +# define CDISABLE call __librt_disable_asynccancel@plt; +# endif + +# if defined IS_IN_libpthread || !defined NOT_IN_libc +# ifndef __ASSEMBLER__ +extern int __local_multiple_threads attribute_hidden; +# define SINGLE_THREAD_P \ + __builtin_expect (__local_multiple_threads == 0, 1) +# else +# define SINGLE_THREAD_P cmpl $0, __local_multiple_threads(%rip) +# endif + +# else + +# ifndef __ASSEMBLER__ +# define SINGLE_THREAD_P \ + __builtin_expect (THREAD_GETMEM (THREAD_SELF, \ + p_header.data.multiple_threads) == 0, 1) +# else +# define SINGLE_THREAD_P cmpl $0, %fs:MULTIPLE_THREADS_OFFSET +# endif + +# endif + +#elif !defined __ASSEMBLER__ + +/* This code should never be used but we define it anyhow. */ +# define SINGLE_THREAD_P (1) + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/x86_64/vfork.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/x86_64/vfork.S new file mode 100644 index 00000000..25d1d3f9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/unix/sysv/linux/x86_64/vfork.S @@ -0,0 +1,62 @@ +/* Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#define _ERRNO_H 1 +#include + +/* Clone the calling process, but without copying the whole address space. + The calling process is suspended until the new process exits or is + replaced by a call to `execve'. Return -1 for errors, 0 to the new process, + and the process ID of the new process to the old process. */ + +ENTRY (__vfork) + +#ifdef SHARED + cmpq $0, __libc_pthread_functions(%rip) +#else + .weak pthread_create + movq $pthread_create, %rax + testq %rax, %rax +#endif + jne HIDDEN_JUMPTARGET (__fork) + + /* Pop the return PC value into RDI. We need a register that + is preserved by the syscall and that we're allowed to destroy. */ + popq %rdi + cfi_adjust_cfa_offset(-8) + + /* Stuff the syscall number in RAX and enter into the kernel. */ + movl $SYS_ify (vfork), %eax + syscall + + /* Push back the return PC. */ + pushq %rdi + cfi_adjust_cfa_offset(8) + + cmpl $-4095, %eax + jae SYSCALL_ERROR_LABEL /* Branch forward if it failed. */ + + /* Normal return. */ +.Lpseudo_end: + ret + +PSEUDO_END (__vfork) +libc_hidden_def (__vfork) + +weak_alias (__vfork, vfork) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/x86_64/pspinlock.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/x86_64/pspinlock.c new file mode 100644 index 00000000..b43d4ac8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/x86_64/pspinlock.c @@ -0,0 +1,97 @@ +/* POSIX spinlock implementation. x86-64 version. + Copyright (C) 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include "internals.h" + +/* This implementation is similar to the one used in the Linux kernel. + But the kernel is byte instructions for the memory access. This is + faster but unusable here. The problem is that only 128 + threads/processes could use the spinlock at the same time. If (by + a design error in the program) a thread/process would hold the + spinlock for a time long enough to accumulate 128 waiting + processes, the next one will find a positive value in the spinlock + and assume it is unlocked. We cannot accept that. */ + +int +__pthread_spin_lock (pthread_spinlock_t *lock) +{ + __asm__ __volatile__ + ("\n" + "1:\n\t" + "lock; decl %0\n\t" + "js 2f\n\t" + ".section .text.spinlock,\"ax\"\n" + "2:\n\t" + "cmpl $0,%0\n\t" + "rep; nop\n\t" + "jle 2b\n\t" + "jmp 1b\n\t" + ".previous" + : "=m" (*lock)); + return 0; +} +weak_alias (__pthread_spin_lock, pthread_spin_lock) + + +int +__pthread_spin_trylock (pthread_spinlock_t *lock) +{ + int oldval; + + __asm__ __volatile__ + ("xchgl %0,%1" + : "=r" (oldval), "=m" (*lock) + : "0" (0)); + return oldval > 0 ? 0 : EBUSY; +} +weak_alias (__pthread_spin_trylock, pthread_spin_trylock) + + +int +__pthread_spin_unlock (pthread_spinlock_t *lock) +{ + __asm__ __volatile__ + ("movl $1,%0" + : "=m" (*lock)); + return 0; +} +weak_alias (__pthread_spin_unlock, pthread_spin_unlock) + + +int +__pthread_spin_init (pthread_spinlock_t *lock, int pshared) +{ + /* We can ignore the `pshared' parameter. Since we are busy-waiting + all processes which can access the memory location `lock' points + to can use the spinlock. */ + *lock = 1; + return 0; +} +weak_alias (__pthread_spin_init, pthread_spin_init) + + +int +__pthread_spin_destroy (pthread_spinlock_t *lock) +{ + /* Nothing to do. */ + return 0; +} +weak_alias (__pthread_spin_destroy, pthread_spin_destroy) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/x86_64/pt-machine.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/x86_64/pt-machine.h new file mode 100644 index 00000000..23615dbd --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/x86_64/pt-machine.h @@ -0,0 +1,224 @@ +/* Machine-dependent pthreads configuration and inline functions. + x86-64 version. + Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _PT_MACHINE_H +#define _PT_MACHINE_H 1 + +# include + +#ifndef __ASSEMBLER__ +# include /* For offsetof. */ +# include /* For abort(). */ +# include + + +# ifndef PT_EI +# define PT_EI __extern_always_inline +# endif + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +# define CURRENT_STACK_FRAME stack_pointer +register char * stack_pointer __asm__ ("%rsp") __attribute_used__; + + +/* Spinlock implementation; required. */ +PT_EI long int +testandset (int *spinlock) +{ + long int ret; + + __asm__ __volatile__ ( + "xchgl %k0, %1" + : "=r"(ret), "=m"(*spinlock) + : "0"(1), "m"(*spinlock) + : "memory"); + + return ret; +} + + +/* Compare-and-swap for semaphores. */ +# define HAS_COMPARE_AND_SWAP + +PT_EI int +__compare_and_swap (long int *p, long int oldval, long int newval) +{ + char ret; + long int readval; + + __asm__ __volatile__ ("lock; cmpxchgq %3, %1; sete %0" + : "=q" (ret), "=m" (*p), "=a" (readval) + : "r" (newval), "m" (*p), "a" (oldval) + : "memory"); + return ret; +} + +/* Return the thread descriptor for the current thread. + + The contained asm must *not* be marked volatile since otherwise + assignments like + pthread_descr self = thread_self(); + do not get optimized away. */ +# define THREAD_SELF \ +({ \ + register pthread_descr __self; \ + __asm__ ("movq %%fs:%c1,%0" : "=r" (__self) \ + : "i" (offsetof (struct _pthread_descr_struct, \ + p_header.data.self))); \ + __self; \ +}) + +/* Prototype for the system call. */ +extern int arch_prctl (int __code, unsigned long __addr); + +/* Initialize the thread-unique value. */ +# define INIT_THREAD_SELF(descr, nr) \ +{ \ + if (arch_prctl (ARCH_SET_FS, (unsigned long)descr) != 0) \ + abort (); \ +} + +/* Read member of the thread descriptor directly. */ +# define THREAD_GETMEM(descr, member) \ +({ \ + __typeof__ (descr->member) __value; \ + if (sizeof (__value) == 1) \ + __asm__ __volatile__ ("movb %%fs:%P2,%b0" \ + : "=q" (__value) \ + : "0" (0), \ + "i" (offsetof (struct _pthread_descr_struct, \ + member))); \ + else if (sizeof (__value) == 4) \ + __asm__ __volatile__ ("movl %%fs:%P2,%k0" \ + : "=r" (__value) \ + : "0" (0), \ + "i" (offsetof (struct _pthread_descr_struct, \ + member))); \ + else \ + { \ + if (sizeof (__value) != 8) \ + /* There should not be any value with a size other than 1, 4 or 8. */\ + abort (); \ + \ + __asm__ __volatile__ ("movq %%fs:%P1,%0" \ + : "=r" (__value) \ + : "i" (offsetof (struct _pthread_descr_struct, \ + member))); \ + } \ + __value; \ +}) + +/* Same as THREAD_GETMEM, but the member offset can be non-constant. */ +# define THREAD_GETMEM_NC(descr, member) \ +({ \ + __typeof__ (descr->member) __value; \ + if (sizeof (__value) == 1) \ + __asm__ __volatile__ ("movb %%fs:(%2),%b0" \ + : "=q" (__value) \ + : "0" (0), \ + "r" (offsetof (struct _pthread_descr_struct, \ + member))); \ + else if (sizeof (__value) == 4) \ + __asm__ __volatile__ ("movl %%fs:(%2),%k0" \ + : "=r" (__value) \ + : "0" (0), \ + "r" (offsetof (struct _pthread_descr_struct, \ + member))); \ + else \ + { \ + if (sizeof (__value) != 8) \ + /* There should not be any value with a size other than 1, 4 or 8. */\ + abort (); \ + \ + __asm__ __volatile__ ("movq %%fs:(%1),%0" \ + : "=r" (__value) \ + : "r" (offsetof (struct _pthread_descr_struct, \ + member))); \ + } \ + __value; \ +}) + +/* Set member of the thread descriptor directly. */ +# define THREAD_SETMEM(descr, member, value) \ +({ \ + __typeof__ (descr->member) __value = (value); \ + if (sizeof (__value) == 1) \ + __asm__ __volatile__ ("movb %0,%%fs:%P1" : \ + : "q" (__value), \ + "i" (offsetof (struct _pthread_descr_struct, \ + member))); \ + else if (sizeof (__value) == 4) \ + __asm__ __volatile__ ("movl %k0,%%fs:%P1" : \ + : "r" (__value), \ + "i" (offsetof (struct _pthread_descr_struct, \ + member))); \ + else \ + { \ + if (sizeof (__value) != 8) \ + /* There should not be any value with a size other than 1, 4 or 8. */\ + abort (); \ + \ + __asm__ __volatile__ ("movq %0,%%fs:%P1" : \ + : "r" (__value), \ + "i" (offsetof (struct _pthread_descr_struct, \ + member))); \ + } \ +}) + +/* Same as THREAD_SETMEM, but the member offset can be non-constant. */ +# define THREAD_SETMEM_NC(descr, member, value) \ +({ \ + __typeof__ (descr->member) __value = (value); \ + if (sizeof (__value) == 1) \ + __asm__ __volatile__ ("movb %0,%%fs:(%1)" : \ + : "q" (__value), \ + "r" (offsetof (struct _pthread_descr_struct, \ + member))); \ + else if (sizeof (__value) == 4) \ + __asm__ __volatile__ ("movl %k0,%%fs:(%1)" : \ + : "r" (__value), \ + "r" (offsetof (struct _pthread_descr_struct, \ + member))); \ + else \ + { \ + if (sizeof (__value) != 8) \ + /* There should not be any value with a size other than 1, 4 or 8. */\ + abort (); \ + \ + __asm__ __volatile__ ("movq %0,%%fs:(%1)" : \ + : "r" (__value), \ + "r" (offsetof (struct _pthread_descr_struct, \ + member))); \ + } \ +}) + +#endif /* !__ASSEMBLER__ */ + +/* We want the OS to assign stack addresses. */ +#define FLOATING_STACKS 1 + +/* Maximum size of the stack if the rlimit is unlimited. */ +#define ARCH_STACK_MAX_SIZE 32*1024*1024 + +/* The ia32e really want some help to prevent overheating. */ +#define BUSY_WAIT_NOP __asm__ ("rep; nop") + +#endif /* pt-machine.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/x86_64/tcb-offsets.sym b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/x86_64/tcb-offsets.sym new file mode 100644 index 00000000..aee6be25 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/x86_64/tcb-offsets.sym @@ -0,0 +1,4 @@ +#include +#include + +MULTIPLE_THREADS_OFFSET offsetof (tcbhead_t, multiple_threads) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/x86_64/tls.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/x86_64/tls.h new file mode 100644 index 00000000..5e7239d1 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads/sysdeps/x86_64/tls.h @@ -0,0 +1,134 @@ +/* Definitions for thread-local data handling. linuxthreads/x86-64 version. + Copyright (C) 2002, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _TLS_H +#define _TLS_H + +#ifndef __ASSEMBLER__ + +# include +# include +# include + +/* Type for the dtv. */ +typedef union dtv +{ + size_t counter; + struct + { + void *val; + bool is_static; + } pointer; +} dtv_t; + + +typedef struct +{ + void *tcb; /* Pointer to the TCB. Not necessary the + thread descriptor used by libpthread. */ + dtv_t *dtv; + void *self; /* Pointer to the thread descriptor. */ + int multiple_threads; +} tcbhead_t; + +#else /* __ASSEMBLER__ */ +# include +#endif + + +#ifdef HAVE_TLS_SUPPORT + +/* Signal that TLS support is available. */ +# define USE_TLS 1 + +# ifndef __ASSEMBLER__ +/* Get system call information. */ +# include + +/* Get the thread descriptor definition. */ +# include + +/* This is the size of the initial TCB. */ +# define TLS_INIT_TCB_SIZE sizeof (tcbhead_t) + +/* Alignment requirements for the initial TCB. */ +# define TLS_INIT_TCB_ALIGN __alignof__ (tcbhead_t) + +/* This is the size of the TCB. */ +# define TLS_TCB_SIZE sizeof (struct _pthread_descr_struct) + +/* Alignment requirements for the TCB. */ +# define TLS_TCB_ALIGN __alignof__ (struct _pthread_descr_struct) + +/* The TCB can have any size and the memory following the address the + thread pointer points to is unspecified. Allocate the TCB there. */ +# define TLS_TCB_AT_TP 1 + + +/* Install the dtv pointer. The pointer passed is to the element with + index -1 which contain the length. */ +# define INSTALL_DTV(descr, dtvp) \ + ((tcbhead_t *) (descr))->dtv = (dtvp) + 1 + +/* Install new dtv for current thread. */ +# define INSTALL_NEW_DTV(dtv) \ + ({ struct _pthread_descr_struct *__descr; \ + THREAD_SETMEM (__descr, p_header.data.dtvp, (dtv)); }) + +/* Return dtv of given thread descriptor. */ +# define GET_DTV(descr) \ + (((tcbhead_t *) (descr))->dtv) + +/* Code to initially initialize the thread pointer. This might need + special attention since 'errno' is not yet available and if the + operation can cause a failure 'errno' must not be touched. */ +# define TLS_INIT_TP(descr, secondcall) \ + ({ \ + void *_descr = (descr); \ + tcbhead_t *head = _descr; \ + long int _result; \ + \ + head->tcb = _descr; \ + /* For now the thread descriptor is at the same address. */ \ + head->self = _descr; \ + \ + __asm__ __volatile__ ("syscall" \ + : "=a" (_result) \ + : "0" ((unsigned long int) __NR_arch_prctl), \ + "D" ((unsigned long int) ARCH_SET_FS), \ + "S" (_descr) \ + : "memory", "cc", "r11", "cx"); \ + \ + _result ? "cannot set %fs base address for thread-local storage" : 0; \ + }) + +/* Indicate that dynamic linker shouldn't try to initialize TLS even + when no PT_TLS segments are found in the program and libraries + it is linked against. */ +# define TLS_INIT_TP_EXPENSIVE 1 + +/* Return the address of the dtv for the current thread. */ +# define THREAD_DTV() \ + ({ struct _pthread_descr_struct *__descr; \ + THREAD_GETMEM (__descr, p_header.data.dtvp); }) + +# endif /* HAVE_TLS_SUPPORT */ +#endif /* __ASSEMBLER__ */ + +#endif /* tls.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/.cvsignore b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/.cvsignore new file mode 100644 index 00000000..e60a14bd --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/.cvsignore @@ -0,0 +1,5 @@ +.cvsignore +.svn +*.os +Makefile +Makefile.in diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/Banner b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/Banner new file mode 100644 index 00000000..6f4f3f81 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/Banner @@ -0,0 +1 @@ +libthread_db work sponsored by Alpha Processor Inc diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/ChangeLog b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/ChangeLog new file mode 100644 index 00000000..9964b4dd --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/ChangeLog @@ -0,0 +1,467 @@ +2006-04-25 Bernhard Fischer + + * td_init.c (__td_debug): Only declare when NDEBUG is undefined. + +2006-04-25 Bernhard Fischer + + * thread_dbP.h: Fix Indices typo in comment. + +2005-11-02 Daniel Jacobowitz + + * td_ta_clear_event.c (td_ta_clear_event): Correct arguments to + sizeof. + * td_ta_set_event.c (td_ta_set_event): Likewise. + * td_thr_clear_event.c (td_thr_clear_event): Likewise. + * td_thr_set_event.c (td_thr_set_event): Likewise. + +2005-01-09 Andreas Jaeger + + * td_thr_tlsbase.c (td_thr_tlsbase): Adjust for dtv change. + +2004-05-01 Jakub Jelinek + + * thread_dbP.h (LOG): Use write instead of __libc_write. + +2004-03-13 Jakub Jelinek + + * td_thr_tlsbase.c: Remove dl-tls.h include. Don't use + TLS_TP_OFFSET in the #if, but TLS_TCB_SIZE == 0 ?:. + +2004-03-12 Roland McGrath + + * td_thr_tlsbase.c [TLS_DTV_AT_TP && TLS_TP_OFFSET > 0]: Handle this + case (PowerPC) differently. + +2003-11-25 Roland McGrath + + * td_symbol_list.c (symbol_list_arr) [HAVE_ASM_GLOBAL_DOT_NAME]: + Prepend "." to symbol names for functions. + +2003-08-18 Daniel Jacobowitz + + * td_thr_getfpregs.c (td_thr_getfpregs): Use the main thread if + the descriptor is uninitialized. + * td_thr_getgregs.c (td_thr_getgregs): Likewise. + +2003-03-15 Roland McGrath + + * thread_db.h (td_err_e): Add TD_NOTLS and TD_TLSDEFER. + (td_thr_tlsbase): Declare it. + * td_thr_tlsbase.c: New file. + * Makefile (libthread_db-routines): Add it. + * Versions (libthread_db: GLIBC_2.3.3): New set, add td_thr_tlsbase. + * td_thr_tls_get_addr.c (td_thr_tls_get_addr): Use td_thr_tlsbase. + +2003-02-27 Roland McGrath + + * td_thr_tls_get_addr.c (td_thr_tls_get_addr): Handle TLS_DTV_AT_TP. + + * td_ta_thr_iter.c (handle_descr) [!defined USE_TLS || !TLS_DTV_AT_TP]: + Conditionalize p_header use on this. + +2003-01-29 Roland McGrath + + * td_ta_new.c (td_ta_new): Cap the `sizeof_descr' value read from the + inferior at `sizeof (struct _pthread_descr_struct)', since we use it + as a length in copies to our own structures. + +2003-01-05 Ulrich Drepper + + * Makefile (libthread_db.so-no-z-defs): Define. + +2002-09-29 Ulrich Drepper + + * td_thr_tsd.c (td_thr_tsd): Read correct entry from pthread_keys + array. + +2002-09-28 Andreas Jaeger + + * td_thr_tls_get_addr.c (td_thr_tls_get_addr): Fix reference to dtv. + +2002-09-24 Roland McGrath + + * td_thr_tls_get_addr.c (td_thr_tls_get_addr): Fetch just the + individual members we need, not the whole structures. + +2002-09-24 Ulrich Drepper + + * td_thr_tls_get_addr.c (td_thr_tls_get_addr): Change second + parameter to be the address of the link map in the inferior process. + * thread_db.h: Update prototype for td_thr_tls_get_addr. + +2002-08-23 Ulrich Drepper + + * thread_dbP.h: Define LINUXTHREADS_VERSION. + * td_symbol_list.c (symbol_list_arr): Add LINUXTHREADS_VERSION string. + * td_ta_new.c (td_ta_new): After verifying the thread library is + there check version. + * thread_db.h: Add new error TD_VERSION. + +2002-08-21 Roland McGrath + + * td_thr_tls_get_addr.c (td_thr_tls_get_addr): __attribute_used__ -> + __attribute__ ((unused)) for arguments. + +2002-08-07 Ulrich Drepper + + * thread_dbP.h: Define LINUXTHREADS_INITIAL_REPORT_EVENTS. + * td_thr_event_enable.c (td_thr_event_enable): If th->th_unique is + null write to __linuxthreads_initial_report_events. + * td_symbol_list.c (symbol_list_arr): Add + __linuxthreads_initial_report_events. + +2002-07-16 Ulrich Drepper + + * td_thr_clear_event.c: Yet more changes to help with TLS-enabled + libpthread. + * td_thr_event_enable.c: Likewise. + * td_thr_event_getmsg.c: Likewise. + * td_thr_set_event.c: Likewise. + * td_thr_setfpregs.c: Likewise. + * td_thr_setgregs.c: Likewise. + * td_thr_tsd.c: Likewise. + * td_thr_validate.c: Likewise. + +2002-07-15 Ulrich Drepper + + * td_ta_thr_iter.c: Some more changes to enable using TLS-enabled + libpthread. + * td_thr_event_enable.c: Likewise. + * td_thr_getfpregs.c: Likewise. + * td_thr_getgregs.c: Likewise. + +2002-07-14 Ulrich Drepper + + * td_ta_map_id2thr.c: Begin fixing implementation for libpthread with + TLS support. + * td_ta_map_lwp2thr.c: Likewise. + * td_ta_thr_iter.c: Likewise. + * td_thr_get_info.c: Likewise. + +2002-07-10 Ulrich Drepper + + * Versions [libthread_db] (GLIBC_2.3): Add td_thr_tls_get_addr. + +2002-06-14 H.J. Lu + + * td_thr_tls_get_addr.c (td_thr_tls_get_addr): Don't include + "tls.h". Return TD_ERR if USE_TLS is not defined. + +2002-06-12 Ulrich Drepper + + * td_thr_tls_get_addr.c: New file. + * thread_db.h: Add prototype for td_thr_tls_get_addr. + * Makefile (libthread_db-routines): Add td_thr_tls_get_addr. + +2002-03-03 Andreas Jaeger + + * thread_dbP.h: Include for prototypes of __libc_write. + +2002-02-04 Ulrich Drepper + + * thread_dbP.h: Include descr.h instead of internals.h. + * td_ta_event_getmsg.c: Also include . + * td_ta_map_id2thr.c: Likewise. + * td_ta_map_lwp2thr.c: Likewise. + * td_ta_thr_iter.c: Likewise. + * td_ta_tsd_iter.c: Likewise. + * td_thr_tsd.c: Likewise. + * td_thr_validate.c: Likewise. + +2001-12-28 Andreas Jaeger + + * td_init.c (td_init): Don't use __FUNCTION__ as literal. + * td_log.c (td_log): Likewise. + * td_ta_delete.c (td_ta_delete): Likewise. + * td_ta_get_nthreads.c (td_ta_get_nthreads): Likewise. + * td_ta_get_ph.c (td_ta_get_ph): Likewise. + * td_ta_map_id2thr.c (td_ta_map_id2thr): Likewise. + * td_ta_map_lwp2thr.c (td_ta_map_lwp2thr): Likewise. + * td_ta_new.c (td_ta_new): Likewise. + * td_ta_clear_event.c (td_ta_clear_event): Likewise. + * td_ta_enable_stats.c (td_ta_enable_stats): Likewise. + * td_ta_event_addr.c (td_ta_event_addr): Likewise. + * td_ta_event_getmsg.c (td_ta_event_getmsg): Likewise. + * td_ta_get_stats.c (td_ta_get_stats): Likewise. + * td_ta_reset_stats.c (td_ta_reset_stats): Likewise. + * td_ta_set_event.c (td_ta_set_event): Likewise. + * td_ta_setconcurrency.c (td_ta_setconcurrency): Likewise. + * td_ta_thr_iter.c (td_ta_thr_iter): Likewise. + * td_ta_tsd_iter.c (td_ta_tsd_iter): Likewise. + * td_thr_clear_event.c (td_thr_clear_event): Likewise. + * td_thr_dbresume.c (td_thr_dbresume): Likewise. + * td_thr_dbsuspend.c (td_thr_dbsuspend): Likewise. + * td_thr_event_enable.c (td_thr_event_enable): Likewise. + * td_thr_event_getmsg.c (td_thr_event_getmsg): Likewise. + * td_thr_get_info.c (td_thr_get_info): Likewise. + * td_thr_getfpregs.c (td_thr_getfpregs): Likewise. + * td_thr_getgregs.c (td_thr_getgregs): Likewise. + * td_thr_getxregs.c (td_thr_getxregs): Likewise. + * td_thr_getxregsize.c (td_thr_getxregsize): Likewise. + * td_thr_set_event.c (td_thr_set_event): Likewise. + * td_thr_setfpregs.c (td_thr_setfpregs): Likewise. + * td_thr_setgregs.c (td_thr_setgregs): Likewise. + * td_thr_setprio.c (td_thr_setprio): Likewise. + * td_thr_setsigpending.c (td_thr_setsigpending): Likewise. + * td_thr_setxregs.c (td_thr_setxregs): Likewise. + * td_thr_sigsetmask.c (td_thr_sigsetmask): Likewise. + * td_thr_tsd.c (td_thr_tsd): Likewise. + * td_thr_validate.c (td_thr_validate): Likewise. + +2001-04-12 Ulrich Drepper + + * td_ta_map_id2thr.c: If thread terminated return TD_NOTHR. + * td_thr_validate.c: Likewise. + +2001-04-04 Ulrich Drepper + + * td_thr_getfpregs.c: If p_pid is zero use ps_getpid(). + * td_thr_getgregs.c: Likewise. + * td_thr_setfpregs.c: Likewise. + * td_thr_setgregs.c: Likewise. + +2001-03-20 Ulrich Drepper + + * Makefile (libthread_db-routines): Add td_symbol_list. + * Versions [libthread_db] (GLIBC_2.2.3): Add td_symbol_list. + * td_symbol_list.c: New file. + * thread_db.h: Add prototype for td_symbol_list. + * thread_dbP.h: Define symbol name indices. + Add prototype for td_lookup. + * td_ta_event_addr.c: Use td_lookup instead of directly using + ps_pglobal_lookup to find symbol address. + * td_ta_get_nthreads.c: Likewise. + * td_ta_new.c: Likewise. + +2001-03-18 Ulrich Drepper + + * Makefile: When generating DSO link with libc_nonshared.a. + +2000-08-01 Andreas Jaeger + + * Makefile (distribute): Add missing files. + +2000-04-24 Mark Kettenis + + * td_thr_get_info.c (td_thr_get_info): Set ti_state to + TD_THR_ACTIVE instead of TD_THR_RUN. If the thread is no longer + running but is still joinable, set it to TD_THR_ZOMBIE. Otherwise + set it to TD_THR_UNKNOWN. + +2000-02-25 Andreas Jaeger + + * td_ta_thr_iter.c: Include for prototype declaration. + * td_ta_tsd_iter.c: Likewise. + +2000-01-20 Andreas Jaeger + + * td_thr_getgregs.c (td_thr_getgregs): Fix typo. + +2000-01-19 Ulrich Drepper + + * td_thr_getgregs.c: Correct size parameter of memset call. + +1999-12-02 Ulrich Drepper + + * proc_service.h: Fix typos in last added declaractions. + +1999-12-01 Ulrich Drepper + + * proc_service.h: Add ps_pstop, ps_pcontinue, ps_lstop, and + ps_lcontinue prototypes. + +1999-11-23 Ulrich Drepper + + * Makefile: Correct dependency for shared object. + +1999-11-22 Ulrich Drepper + + * td_ta_map_lwp2thr.c: Add missing brace in comparison. + + * thread_dbP.h (LOG): Only print message if __td_debug is nonzero. + * td_init.c: Add __td_debug. + +1999-11-12 Ulrich Drepper + + * td_ta_thr_iter.c: Start copying list of descriptors from right + position in target process. + + * td_ta_thr_iter.c: Fix loop starting point over all but main and + manager thread. + + * td_ta_thr_iter.c: Read descriptors for main and manager thread + special since after this we can assume that no new threads will be + created anymore (at least in the gdb implementation). + + * Makefile: Define version correctly. + +1999-11-10 Ulrich Drepper + + * td_ta_map_lwp2thr.c: If p_pid field is zero, this is before the + thread library is initialized and we get the PID from the + debugger. + +1999-11-08 Ulrich Drepper + + * td_thr_get_info.c: Make sure ti_lid is never zero. + + * proc_service.h: Add ps_getpid prototype. + +1999-11-03 Ulrich Drepper + + * thread_dbP.h (ta_ok): New function. + * td_ta_new.c: Add new handle to list. + * td_ta_delete.c: Remove handle from list. + * td_ta_clear_event.c: Use ta_ok to check for correct ta parameter. + * td_ta_enable_stats.c: Likewise. + * td_ta_event_addr.c: Likewise. + * td_ta_event_getmsg.c: Likewise. + * td_ta_get_nthreads.c: Likewise. + * td_ta_get_ph.c: Likewise. + * td_ta_get_stats.c: Likewise. + * td_ta_map_id2thr.c: Likewise. + * td_ta_map_lwp2thr.c: Likewise. + * td_ta_reset_stats.c: Likewise. + * td_ta_set_event.c: Likewise. + * td_ta_setconcurrency.c: Likewise. + * td_ta_thr_iter.c: Likewise. + + * td_ta_tsd_iter.c: Optimize memory retrieving. + + * Versions: New file. + + * td_thr_get_info.c (td_thr_get_info): Initialize ti_traceme. + +1999-11-02 Ulrich Drepper + + * td_ta_thr_iter.c (td_ta_thr_iter): Optimize a bit. Read all + handles at once. + + * thread_dbP.h (struct th_thragent): Add pthread_handle_num. + * td_ta_new.c: Initialize pthread_handle_num. + * td_ta_event_getmsg.c: If last event was already reported search + for another unreported event. + + * td_thr_get_info.c (td_thr_get_info): Initialize ti_events. + + * Makefile (libthread_db-routines): Add td_ta_set_event, + td_ta_event_getmsg, and td_ta_clear_event. + * td_ta_clear_event.c: New file. + * td_ta_event_getmsg.c: New file. + * td_ta_new.c: Get address of __pthread_last_event in target. + * td_ta_set_event.c: Don't overwrite old mask, set additional bits. + * td_thr_set_event.c: Likewise. + * td_thr_clear_event.c: Implement. + * thread_db.h: Declare td_ta_clear_event and td_ta_event_getmsg. + * thread_dbP.h (struct td_thragent): Add pthread_last_event. + + * td_ta_new.c: Don't test for __pthread_threads_debug. Get address + of __pthread_threads_events and fail if this is not possible. + * td_ta_event_addr.c: Implement. + * td_thr_event_enable.c: Implement. + * td_thr_event_getmsg.c: Implement. + * td_thr_set_event.c: Implement. + * td_ta_set_event.c: New file. + * thread_db.h (td_eventbuf_t): Define. + Declare td_ta_set_event. + * thread_dbP.h (struct td_thragent): Add pthread_threads_eventsp. + + * td_thr_getfpregs.c: For terminated threads return empty structure. + * td_thr_getgregs.c: Likewise. + * td_thr_setfpregs.c: Likewise. + * td_thr_setgregs.c: Likewise. + +1999-11-01 Ulrich Drepper + + * thread_db.h: Shuffle types around to make things work for gdb. + * thread_dbP.h: Include proc_service.h before thread_db.h. + + * thread_db.h: It's TD_NOLIBTHREAD, not TD_LIBTHREAD. + * td_ta_new.c: Likewise. + +1999-10-14 Ulrich Drepper + + * td_ta_new.c: p_startfct does not exist anymore. + + * td_thr_get_info.c: Always initialize start function. + + * td_ta_thr_iter.c: Don't return threads which exited (but are not + joined). + + * td_thr_validate.c: Don't skip manager thread. + +1999-10-13 Ulrich Drepper + + * td_ta_thr_iter.c: Use size of descriptor from *TA. + Don't return manager thread before it's actually running. + Actually use state parameter to distingusih at least a few states. + + * td_thr_get_info.c: Handle manager thread special. Fill in ti_lid, + ti_state, and ti_startfunc fields. + +1999-10-12 Andreas Jaeger + + * thread_dbP.h: Include for strlen declaration. Remove + __libc_write prototype since this is already declared in + linuxthreads/internals.h. + +1999-10-11 Ulrich Drepper + + * thread_db.h: Fix comment for ti_type. + + * td_thr_get_info.c: Initialize ti_type field. + + * td_ta_thr_iter.c: Also report the manager thread. + +1999-10-08 Andreas Jaeger + + * thread_db.h: Fix typos in comments. + + * td_ta_get_nthreads.c (td_ta_get_nthreads): Don't hardcode + libpthread library name, get it from instead. + * td_ta_new.c (td_ta_new): Likewise. + +1999-10-08 Ulrich Drepper + + * shlib-versions: New file. + +1999-10-07 Ulrich Drepper + + * Makefile: New file. + * proc_service.h: New file. + * td_init.c: New file. + * td_log.c: New file. + * td_ta_delete.c: New file. + * td_ta_enable_stats.c: New file. + * td_ta_event_addr.c: New file. + * td_ta_get_nthreads.c: New file. + * td_ta_get_ph.c: New file. + * td_ta_get_stats.c: New file. + * td_ta_map_id2thr.c: New file. + * td_ta_map_lwp2thr.c: New file. + * td_ta_new.c: New file. + * td_ta_reset_stats.c: New file. + * td_ta_setconcurrency.c: New file. + * td_ta_thr_iter.c: New file. + * td_ta_tsd_iter.c: New file. + * td_thr_clear_event.c: New file. + * td_thr_dbresume.c: New file. + * td_thr_dbsuspend.c: New file. + * td_thr_event_enable.c: New file. + * td_thr_event_getmsg.c: New file. + * td_thr_get_info.c: New file. + * td_thr_getfpregs.c: New file. + * td_thr_getgregs.c: New file. + * td_thr_getxregs.c: New file. + * td_thr_getxregsize.c: New file. + * td_thr_set_event.c: New file. + * td_thr_setfpregs.c: New file. + * td_thr_setgregs.c: New file. + * td_thr_setprio.c: New file. + * td_thr_setsigpending.c: New file. + * td_thr_setxregs.c: New file. + * td_thr_sigsetmask.c: New file. + * td_thr_tsd.c: New file. + * td_thr_validate.c: New file. + * thread_db.h: New file. + * thread_dbP.h: New file. diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/Makefile new file mode 100644 index 00000000..f9100219 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../ +top_builddir=../../ +include $(top_builddir)Rules.mak +all: libs +include Makefile.in +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/Makefile.in new file mode 100644 index 00000000..060bea3a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/Makefile.in @@ -0,0 +1,78 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +subdirs += libpthread/linuxthreads_db + +# Get the thread include dependencies and shared object name +CFLAGS-linuxthreads_db := -DNOT_IN_libc -DLIBPTHREAD_SO="\"libpthread.so.$(ABI_VERSION)\"" + +LDFLAGS-libthread_db.so := $(LDFLAGS_NOSTRIP) $(if $(call check_ld,--warn-unresolved-symbols),-Wl$(comma)--warn-unresolved-symbols) +ifeq ($(DOSTRIP),y) +LDFLAGS-libthread_db.so += -Wl,-s +endif + +LIBS-libthread_db.so := $(LIBS) + +libthread_db_FULL_NAME := libthread_db-$(VERSION).so + +libthread_db_DIR := $(top_srcdir)libpthread/linuxthreads_db +libthread_db_OUT := $(top_builddir)libpthread/linuxthreads_db + +libthread_db_SRC := $(wildcard $(libthread_db_DIR)/*.c) + +libthread_db_OBJ := $(patsubst $(libthread_db_DIR)/%.c,$(libthread_db_OUT)/%.o,$(libthread_db_SRC)) + +libthread_db-so-y := $(libthread_db_OBJ:.o=.os) +ifeq ($(DOPIC),y) +libthread_db-a-y := $(libthread_db-so-y) +else +libthread_db-a-y := $(libthread_db_OBJ) +endif + +lib-a-$(PTHREADS_DEBUG_SUPPORT) += $(top_builddir)lib/libthread_db.a +lib-so-$(PTHREADS_DEBUG_SUPPORT) += $(top_builddir)lib/libthread_db.so + +#ifeq ($(DOMULTI),n) +ifeq ($(DOPIC),y) +$(top_builddir)lib/libthread_db.so: $(top_builddir)lib/libthread_db.a $(libc.depend) +else +$(top_builddir)lib/libthread_db.so: $(libthread_db_OUT)/libthread_db_so.a $(libc.depend) +endif + $(call link.so,$(libthread_db_FULL_NAME),1) +#else +#$(top_builddir)lib/libthread_db.so: $(libthread_db_OUT)/libthread_db.oS | $(libc.depend) +# $(call linkm.so,$(libthread_db_FULL_NAME),1) +#endif + +$(libthread_db_OUT)/libthread_db_so.a: $(libthread_db-so-y) + $(Q)$(RM) $@ + $(do_ar) + +$(libthread_db_OUT)/libthread_db.oS: $(libthread_db_SRC) + $(Q)$(RM) $@ + $(compile-m) + +$(top_builddir)lib/libthread_db.a: $(libthread_db-a-y) + $(Q)$(INSTALL) -d $(dir $@) + $(Q)$(RM) $@ + $(do_ar) + +$(top_builddir)include/thread_db.h: + $(do_ln) $(call rel_srcdir)$(PTDIR)_db/$(@F) $@ + +linuxthreads_db_headers := $(top_builddir)include/thread_db.h +$(linuxthreads_db_headers): $(wildcard $(addprefix $(top_builddir)include/config/linuxthreads/,old.h new.h)) +headers-$(PTHREADS_DEBUG_SUPPORT) += $(linuxthreads_db_headers) + +objclean-y += CLEAN_libpthread/linuxthreads_db +headers_clean-y += HEADERCLEAN_libpthread/linuxthreads_db + +HEADERCLEAN_libpthread/linuxthreads_db: + $(do_rm) $(linuxthreads_db_headers) + +CLEAN_libpthread/linuxthreads_db: + $(do_rm) $(addprefix $(libthread_db_OUT)/*., o os oS a) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/Makefile.old b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/Makefile.old new file mode 100644 index 00000000..53e46f77 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/Makefile.old @@ -0,0 +1,57 @@ +# Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. +# This file is part of the GNU C Library. + +# The GNU C Library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. + +# The GNU C Library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. + +# You should have received a copy of the GNU Lesser General Public +# License along with the GNU C Library; if not, write to the Free +# Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +# 02111-1307 USA. + +# Makefile for linuxthreads debug library subdirectory of GNU C Library. + +subdir := linuxthreads_db + +linuxthreads_db-version = 1.0 + +extra-libs = libthread_db +extra-libs-others := $(extra-libs) + +headers = thread_db.h +libthread_db-routines = td_init td_log td_ta_delete td_ta_get_nthreads \ + td_ta_get_ph td_ta_map_id2thr td_ta_map_lwp2thr \ + td_ta_new td_ta_thr_iter td_ta_tsd_iter \ + td_thr_get_info td_thr_getfpregs td_thr_getgregs \ + td_thr_getxregs td_thr_getxregsize td_thr_setfpregs \ + td_thr_setgregs td_thr_setprio td_thr_setsigpending \ + td_thr_setxregs td_thr_sigsetmask td_thr_tsd \ + td_thr_validate td_thr_dbsuspend td_thr_dbresume \ + td_ta_setconcurrency td_ta_enable_stats \ + td_ta_reset_stats td_ta_get_stats td_ta_event_addr \ + td_thr_event_enable td_thr_set_event \ + td_thr_clear_event td_thr_event_getmsg \ + td_ta_set_event td_ta_event_getmsg \ + td_ta_clear_event td_symbol_list \ + td_thr_tlsbase td_thr_tls_get_addr + +libthread_db-inhibit-o = $(filter-out .os,$(object-suffixes)) + +# The ps_* callback functions are not defined. +libthread_db.so-no-z-defs = yes + +distribute = thread_dbP.h shlib-versions proc_service.h +include ../Rules + +# Depend on libc.so so a DT_NEEDED is generated in the shared objects. +# This ensures they will load libc.so for needed symbols if loaded by +# a statically-linked program that hasn't already loaded it. +$(objpfx)libthread_db.so: $(common-objpfx)libc.so \ + $(common-objpfx)libc_nonshared.a diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/Versions b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/Versions new file mode 100644 index 00000000..063493c6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/Versions @@ -0,0 +1,24 @@ +libthread_db { + GLIBC_2.1.3 { + # t* + td_init; td_log; td_ta_clear_event; td_ta_delete; td_ta_enable_stats; + td_ta_event_addr; td_ta_event_getmsg; td_ta_get_nthreads; td_ta_get_ph; + td_ta_get_stats; td_ta_map_id2thr; td_ta_map_lwp2thr; td_ta_new; + td_ta_reset_stats; td_ta_set_event; td_ta_setconcurrency; + td_ta_thr_iter; td_ta_tsd_iter; td_thr_clear_event; td_thr_dbresume; + td_thr_dbsuspend; td_thr_event_enable; td_thr_event_getmsg; + td_thr_get_info; td_thr_getfpregs; td_thr_getgregs; td_thr_getxregs; + td_thr_getxregsize; td_thr_set_event; td_thr_setfpregs; td_thr_setgregs; + td_thr_setprio; td_thr_setsigpending; td_thr_setxregs; td_thr_sigsetmask; + td_thr_tsd; td_thr_validate; + } + GLIBC_2.2.3 { + td_symbol_list; + } + GLIBC_2.3 { + td_thr_tls_get_addr; + } + GLIBC_2.3.3 { + td_thr_tlsbase; + } +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/proc_service.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/proc_service.h new file mode 100644 index 00000000..74136c03 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/proc_service.h @@ -0,0 +1,70 @@ +/* Copyright (C) 1999 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* The definitions in this file must correspond to those in the debugger. */ +#include + +typedef enum +{ + PS_OK, /* generic "call succeeded" */ + PS_ERR, /* generic. */ + PS_BADPID, /* bad process handle */ + PS_BADLID, /* bad lwp identifier */ + PS_BADADDR, /* bad address */ + PS_NOSYM, /* p_lookup() could not find given symbol */ + PS_NOFREGS + /* + * FPU register set not available for given + * lwp + */ +} ps_err_e; + + +struct ps_prochandle; /* user defined. */ + + +extern ps_err_e ps_pdread(struct ps_prochandle *, + psaddr_t, void *, size_t); +extern ps_err_e ps_pdwrite(struct ps_prochandle *, + psaddr_t, const void *, size_t); +extern ps_err_e ps_ptread(struct ps_prochandle *, + psaddr_t, void *, size_t); +extern ps_err_e ps_ptwrite(struct ps_prochandle *, + psaddr_t, const void *, size_t); + +extern ps_err_e ps_pglobal_lookup(struct ps_prochandle *, + const char *object_name, const char *sym_name, psaddr_t *sym_addr); + + +extern ps_err_e ps_lgetregs(struct ps_prochandle *, + lwpid_t, prgregset_t); +extern ps_err_e ps_lsetregs(struct ps_prochandle *, + lwpid_t, const prgregset_t); +extern ps_err_e ps_lgetfpregs(struct ps_prochandle *, + lwpid_t, prfpregset_t *); +extern ps_err_e ps_lsetfpregs(struct ps_prochandle *, + lwpid_t, const prfpregset_t *); + +extern pid_t ps_getpid (struct ps_prochandle *); + + +extern ps_err_e ps_pstop (const struct ps_prochandle *); +extern ps_err_e ps_pcontinue (const struct ps_prochandle *); + +extern ps_err_e ps_lstop (const struct ps_prochandle *, lwpid_t); +extern ps_err_e ps_lcontinue (const struct ps_prochandle *, lwpid_t); diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/shlib-versions b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/shlib-versions new file mode 100644 index 00000000..592f7fa2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/shlib-versions @@ -0,0 +1,2 @@ +# The thread debug library +.*-.*-linux.* libthread_db=1 diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_init.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_init.c new file mode 100644 index 00000000..66e9849b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_init.c @@ -0,0 +1,34 @@ +/* Initialization function of thread debugger support library. + Copyright (C) 1999, 2001, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + +#ifndef NDEBUG +int __td_debug; +#endif + + +td_err_e +td_init (void) +{ + /* XXX We have to figure out what has to be done. */ + LOG ("td_init"); + return TD_OK; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_log.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_log.c new file mode 100644 index 00000000..025273a6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_log.c @@ -0,0 +1,32 @@ +/* Noop, left for historical reasons. + Copyright (C) 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_log (void) +{ + /* This interface is deprecated in the Sun interface. We provide it + for compatibility but don't do anything ourself. We might in + future do some logging if this seems reasonable. */ + LOG ("td_log"); + return TD_OK; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_symbol_list.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_symbol_list.c new file mode 100644 index 00000000..599c0459 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_symbol_list.c @@ -0,0 +1,61 @@ +/* Return list of symbols the library can request. + Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2001. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include "thread_dbP.h" + +#ifdef HAVE_ASM_GLOBAL_DOT_NAME +# define DOT "." /* PPC64 requires . prefix on code symbols. */ +#else +# define DOT /* No prefix. */ +#endif + +static const char *symbol_list_arr[] = +{ + [PTHREAD_THREADS_EVENTS] = "__pthread_threads_events", + [PTHREAD_LAST_EVENT] = "__pthread_last_event", + [PTHREAD_HANDLES_NUM] = "__pthread_handles_num", + [PTHREAD_HANDLES] = "__pthread_handles", + [PTHREAD_KEYS] = "pthread_keys", + [LINUXTHREADS_PTHREAD_THREADS_MAX] = "__linuxthreads_pthread_threads_max", + [LINUXTHREADS_PTHREAD_KEYS_MAX] = "__linuxthreads_pthread_keys_max", + [LINUXTHREADS_PTHREAD_SIZEOF_DESCR] = "__linuxthreads_pthread_sizeof_descr", + [LINUXTHREADS_CREATE_EVENT] = DOT "__linuxthreads_create_event", + [LINUXTHREADS_DEATH_EVENT] = DOT "__linuxthreads_death_event", + [LINUXTHREADS_REAP_EVENT] = DOT "__linuxthreads_reap_event", + [LINUXTHREADS_INITIAL_REPORT_EVENTS] = "__linuxthreads_initial_report_events", + [LINUXTHREADS_VERSION] = "__linuxthreads_version", + [NUM_MESSAGES] = NULL +}; + + +const char ** +td_symbol_list (void) +{ + return symbol_list_arr; +} + + +int +td_lookup (struct ps_prochandle *ps, int idx, psaddr_t *sym_addr) +{ + assert (idx >= 0 && idx < NUM_MESSAGES); + return ps_pglobal_lookup (ps, LIBPTHREAD_SO, symbol_list_arr[idx], sym_addr); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_ta_clear_event.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_ta_clear_event.c new file mode 100644 index 00000000..cbb7ddc9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_ta_clear_event.c @@ -0,0 +1,53 @@ +/* Globally disable events. + Copyright (C) 1999, 2001, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_ta_clear_event (ta, event) + const td_thragent_t *ta; + td_thr_events_t *event; +{ + td_thr_events_t old_event; + int i; + + LOG ("td_ta_clear_event"); + + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + + /* Write the new value into the thread data structure. */ + if (ps_pdread (ta->ph, ta->pthread_threads_eventsp, + &old_event, sizeof (td_thr_events_t)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + /* Remove the set bits in. */ + for (i = 0; i < TD_EVENTSIZE; ++i) + old_event.event_bits[i] &= ~event->event_bits[i]; + + /* Write the new value into the thread data structure. */ + if (ps_pdwrite (ta->ph, ta->pthread_threads_eventsp, + &old_event, sizeof (td_thr_events_t)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + return TD_OK; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_ta_delete.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_ta_delete.c new file mode 100644 index 00000000..0e6ec17d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_ta_delete.c @@ -0,0 +1,58 @@ +/* Detach to target process. + Copyright (C) 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#include "thread_dbP.h" + + +td_err_e +td_ta_delete (td_thragent_t *ta) +{ + LOG ("td_ta_delete"); + + /* Safety check. */ + if (ta == NULL || __td_agent_list == NULL) + return TD_BADTA; + + /* Remove the handle from the list. */ + if (ta == __td_agent_list->ta) + /* It's the first element of the list. */ + __td_agent_list = __td_agent_list->next; + else + { + /* We have to search for it. */ + struct agent_list *runp = __td_agent_list; + + while (runp->next != NULL && runp->next->ta != ta) + runp = runp->next; + + if (runp->next == NULL) + /* It's not a valid decriptor since it is not in the list. */ + return TD_BADTA; + + runp->next = runp->next->next; + } + + /* The handle was allocated in `td_ta_new'. */ + free (ta); + + return TD_OK; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_ta_enable_stats.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_ta_enable_stats.c new file mode 100644 index 00000000..1d4c34a8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_ta_enable_stats.c @@ -0,0 +1,35 @@ +/* Enable collection of statistics for process. + Copyright (C) 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_ta_enable_stats (const td_thragent_t *ta, int enable) +{ + /* XXX We have to figure out what has to be done. */ + LOG ("td_ta_enable_stats"); + + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + + return TD_OK; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_ta_event_addr.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_ta_event_addr.c new file mode 100644 index 00000000..8bce35ae --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_ta_event_addr.c @@ -0,0 +1,73 @@ +/* Get event address. + Copyright (C) 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_ta_event_addr (const td_thragent_t *ta, td_event_e event, td_notify_t *addr) +{ + td_err_e res = TD_NOEVENT; + int idx = -1; + + LOG ("td_ta_event_addr"); + + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + + switch (event) + { + case TD_CREATE: + idx = LINUXTHREADS_CREATE_EVENT; + break; + + case TD_DEATH: + idx = LINUXTHREADS_DEATH_EVENT; + break; + + case TD_REAP: + idx = LINUXTHREADS_REAP_EVENT; + break; + + default: + /* Event cannot be handled. */ + break; + } + + /* Now get the address. */ + if (idx != -1) + { + psaddr_t taddr; + + if (td_lookup (ta->ph, idx, &taddr) == PS_OK) + { + /* Success, we got the address. */ + addr->type = NOTIFY_BPT; + addr->u.bptaddr = taddr; + + res = TD_OK; + } + else + res = TD_ERR; + } + + return res; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_ta_event_getmsg.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_ta_event_getmsg.c new file mode 100644 index 00000000..c3a4492a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_ta_event_getmsg.c @@ -0,0 +1,129 @@ +/* Retrieve event. + Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +#include "thread_dbP.h" +#include + + +td_err_e +td_ta_event_getmsg (const td_thragent_t *ta, td_event_msg_t *msg) +{ + /* XXX I cannot think of another way but using a static variable. */ + static td_thrhandle_t th; + td_eventbuf_t event; + psaddr_t addr; + + LOG ("td_ta_event_getmsg"); + + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + + /* Get the pointer to the thread descriptor with the last event. */ + if (ps_pdread (ta->ph, ta->pthread_last_event, + &addr, sizeof (void *)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + /* If the pointer is NULL no event occurred. */ + if (addr == 0) + return TD_NOMSG; + + /* Read the even structure from the target. */ + if (ps_pdread (ta->ph, + ((char *) addr + + offsetof (struct _pthread_descr_struct, p_eventbuf)), + &event, sizeof (td_eventbuf_t)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + /* Check whether an event occurred. */ + if (event.eventnum == TD_EVENT_NONE) + { + /* Oh well, this means the last event was already read. So + we have to look for any other event. */ + struct pthread_handle_struct handles[ta->pthread_threads_max]; + int num; + int i; + + /* Read the number of currently active threads. */ + if (ps_pdread (ta->ph, ta->pthread_handles_num, &num, sizeof (int)) + != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + /* Now read the handles. */ + if (ps_pdread (ta->ph, ta->handles, handles, + ta->pthread_threads_max * sizeof (handles[0])) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + for (i = 0; i < ta->pthread_threads_max && num > 0; ++i) + { + if (handles[i].h_descr == NULL) + /* No entry here. */ + continue; + + /* First count this active thread. */ + --num; + + if (handles[i].h_descr == addr) + /* We already handled this. */ + continue; + + /* Read the event data for this thread. */ + if (ps_pdread (ta->ph, + ((char *) handles[i].h_descr + + offsetof (struct _pthread_descr_struct, + p_eventbuf)), + &event, sizeof (td_eventbuf_t)) != PS_OK) + return TD_ERR; + + if (event.eventnum != TD_EVENT_NONE) + { + /* We found a thread with an unreported event. */ + addr = handles[i].h_descr; + break; + } + } + + /* If we haven't found any other event signal this to the user. */ + if (event.eventnum == TD_EVENT_NONE) + return TD_NOMSG; + } + + /* Generate the thread descriptor. */ + th.th_ta_p = (td_thragent_t *) ta; + th.th_unique = addr; + + /* Fill the user's data structure. */ + msg->event = event.eventnum; + msg->th_p = &th; + msg->msg.data = (uintptr_t) event.eventdata; + + /* And clear the event message in the target. */ + memset (&event, '\0', sizeof (td_eventbuf_t)); + if (ps_pdwrite (ta->ph, + ((char *) addr + + offsetof (struct _pthread_descr_struct, p_eventbuf)), + &event, sizeof (td_eventbuf_t)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + return TD_OK; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_ta_get_nthreads.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_ta_get_nthreads.c new file mode 100644 index 00000000..839b56be --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_ta_get_nthreads.c @@ -0,0 +1,42 @@ +/* Get the number of threads in the process. + Copyright (C) 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + +td_err_e +td_ta_get_nthreads (const td_thragent_t *ta, int *np) +{ + psaddr_t addr; + + LOG ("td_ta_get_nthreads"); + + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + + /* Access the variable `__pthread_handles_num'. */ + if (td_lookup (ta->ph, PTHREAD_HANDLES_NUM, &addr) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + if (ps_pdread (ta->ph, addr, np, sizeof (int)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + return TD_OK; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_ta_get_ph.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_ta_get_ph.c new file mode 100644 index 00000000..23d32850 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_ta_get_ph.c @@ -0,0 +1,36 @@ +/* Get external process handle. + Copyright (C) 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_ta_get_ph (const td_thragent_t *ta, struct ps_prochandle **ph) +{ + LOG ("td_ta_get_ph"); + + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + + *ph = ta->ph; + + return TD_OK; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_ta_get_stats.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_ta_get_stats.c new file mode 100644 index 00000000..6bf2f535 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_ta_get_stats.c @@ -0,0 +1,35 @@ +/* Retrieve statistics for process. + Copyright (C) 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_ta_get_stats (const td_thragent_t *ta, td_ta_stats_t *statsp) +{ + /* XXX We have to figure out what has to be done. */ + LOG ("td_ta_get_stats"); + + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + + return TD_OK; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_ta_map_id2thr.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_ta_map_id2thr.c new file mode 100644 index 00000000..ddeb2d3c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_ta_map_id2thr.c @@ -0,0 +1,79 @@ +/* Map thread ID to thread handle. + Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" +#include + + +td_err_e +td_ta_map_id2thr (const td_thragent_t *ta, pthread_t pt, td_thrhandle_t *th) +{ + struct pthread_handle_struct phc; + struct _pthread_descr_struct pds; + int pthread_threads_max; + + LOG ("td_ta_map_id2thr"); + + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + + /* Make the following expression a bit smaller. */ + pthread_threads_max = ta->pthread_threads_max; + + /* We can compute the entry in the handle array we want. */ + if (ps_pdread (ta->ph, ta->handles + pt % pthread_threads_max, &phc, + sizeof (struct pthread_handle_struct)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + /* Test whether this entry is in use. */ + if (phc.h_descr == NULL) + { + if (pt % pthread_threads_max == 0) + { + /* The initial thread always exists but the thread library + might not yet be initialized. */ + th->th_ta_p = (td_thragent_t *) ta; + th->th_unique = NULL; + + return TD_OK; + } + + return TD_BADTH; + } + + /* Next test: get the descriptor to see whether this is not an old + thread handle. */ + if (ps_pdread (ta->ph, phc.h_descr, &pds, + sizeof (struct _pthread_descr_struct)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + if (pds.p_tid != pt) + return TD_BADTH; + + if (pds.p_terminated != 0) + return TD_NOTHR; + + /* Create the `td_thrhandle_t' object. */ + th->th_ta_p = (td_thragent_t *) ta; + th->th_unique = phc.h_descr; + + return TD_OK; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_ta_map_lwp2thr.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_ta_map_lwp2thr.c new file mode 100644 index 00000000..dd2fcbfe --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_ta_map_lwp2thr.c @@ -0,0 +1,91 @@ +/* Which thread is running on an lwp? + Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" +#include + + +td_err_e +td_ta_map_lwp2thr (const td_thragent_t *ta, lwpid_t lwpid, td_thrhandle_t *th) +{ + int pthread_threads_max = ta->pthread_threads_max; + size_t sizeof_descr = ta->sizeof_descr; + struct pthread_handle_struct phc[pthread_threads_max]; + size_t cnt; +#ifdef ALL_THREADS_STOPPED + int num; +#else +# define num 1 +#endif + + LOG ("td_ta_map_lwp2thr"); + + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + + /* Read all the descriptors. */ + if (ps_pdread (ta->ph, ta->handles, phc, + sizeof (struct pthread_handle_struct) * pthread_threads_max) + != PS_OK) + return TD_ERR; /* XXX Other error value? */ + +#ifdef ALL_THREADS_STOPPED + /* Read the number of currently active threads. */ + if (ps_pdread (ta->ph, ta->pthread_handles_num, &num, sizeof (int)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ +#endif + + /* Get the entries one after the other and find out whether the ID + matches. */ + for (cnt = 0; cnt < pthread_threads_max && num > 0; ++cnt) + if (phc[cnt].h_descr != NULL) + { + struct _pthread_descr_struct pds; + +#ifdef ALL_THREADS_STOPPED + /* First count this active thread. */ + --num; +#endif + + if (ps_pdread (ta->ph, phc[cnt].h_descr, &pds, sizeof_descr) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + if ((pds.p_pid ?: ps_getpid (ta->ph)) == lwpid) + { + /* Found it. Now fill in the `td_thrhandle_t' object. */ + th->th_ta_p = (td_thragent_t *) ta; + th->th_unique = phc[cnt].h_descr; + + return TD_OK; + } + } + else if (cnt == 0) + { + /* The initial thread always exists. But it might not yet be + initialized. Construct a value. */ + th->th_ta_p = (td_thragent_t *) ta; + th->th_unique = NULL; + + return TD_OK; + } + + return TD_NOLWP; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_ta_new.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_ta_new.c new file mode 100644 index 00000000..2b0b68bf --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_ta_new.c @@ -0,0 +1,149 @@ +/* Attach to target process. + Copyright (C) 1999, 2001, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +#include "thread_dbP.h" + + +/* Datatype for the list of known thread agents. Normally there will + be exactly one so we don't spend much though on making it fast. */ +struct agent_list *__td_agent_list; + + +td_err_e +td_ta_new (struct ps_prochandle *ps, td_thragent_t **ta) +{ + psaddr_t addr; + psaddr_t versaddr; + char versbuf[sizeof (VERSION)]; + struct agent_list *elemp; + + LOG ("td_ta_new"); + + /* Get the global event mask. This is one of the variables which + are new in the thread library to enable debugging. If it is + not available we cannot debug. */ + if (td_lookup (ps, PTHREAD_THREADS_EVENTS, &addr) != PS_OK) + return TD_NOLIBTHREAD; + + /* Check whether the versions match. */ + if (td_lookup (ps, LINUXTHREADS_VERSION, &versaddr) != PS_OK) + return TD_VERSION; + if (ps_pdread (ps, versaddr, versbuf, sizeof (versbuf)) != PS_OK) + return TD_ERR; + + versbuf[sizeof (versbuf) - 1] = '\0'; + if (strcmp (versbuf, VERSION) != 0) + /* Not the right version. */ + return TD_VERSION; + + /* Fill in the appropriate information. */ + *ta = (td_thragent_t *) malloc (sizeof (td_thragent_t)); + if (*ta == NULL) + return TD_MALLOC; + + /* Store the proc handle which we will pass to the callback functions + back into the debugger. */ + (*ta)->ph = ps; + + /* Remember the address. */ + (*ta)->pthread_threads_eventsp = (td_thr_events_t *) addr; + + /* Get the pointer to the variable pointing to the thread descriptor + with the last event. */ + if (td_lookup (ps, PTHREAD_LAST_EVENT, &(*ta)->pthread_last_event) != PS_OK) + { + free_return: + free (*ta); + return TD_ERR; + } + + /* Get the pointer to the variable containing the number of active + threads. */ + if (td_lookup (ps, PTHREAD_HANDLES_NUM, &(*ta)->pthread_handles_num) + != PS_OK) + goto free_return; + + /* See whether the library contains the necessary symbols. */ + if (td_lookup (ps, PTHREAD_HANDLES, &addr) != PS_OK) + goto free_return; + + (*ta)->handles = (struct pthread_handle_struct *) addr; + + + if (td_lookup (ps, PTHREAD_KEYS, &addr) != PS_OK) + goto free_return; + + /* Cast to the right type. */ + (*ta)->keys = (struct pthread_key_struct *) addr; + + /* Find out about the maximum number of threads. Old implementations + don't provide this information. In this case we assume that the + debug library is compiled with the same values. */ + if (td_lookup (ps, LINUXTHREADS_PTHREAD_THREADS_MAX, &addr) != PS_OK) + (*ta)->pthread_threads_max = PTHREAD_THREADS_MAX; + else + { + if (ps_pdread (ps, addr, &(*ta)->pthread_threads_max, sizeof (int)) + != PS_OK) + goto free_return; + } + + /* Similar for the maximum number of thread local data keys. */ + if (td_lookup (ps, LINUXTHREADS_PTHREAD_KEYS_MAX, &addr) != PS_OK) + (*ta)->pthread_keys_max = PTHREAD_KEYS_MAX; + else + { + if (ps_pdread (ps, addr, &(*ta)->pthread_keys_max, sizeof (int)) + != PS_OK) + goto free_return; + } + + /* And for the size of the second level arrays for the keys. */ + if (td_lookup (ps, LINUXTHREADS_PTHREAD_SIZEOF_DESCR, &addr) != PS_OK) + (*ta)->sizeof_descr = sizeof (struct _pthread_descr_struct); + else + { + if (ps_pdread (ps, addr, &(*ta)->sizeof_descr, sizeof (int)) != PS_OK) + goto free_return; + /* Don't let bogons in the inferior make us mess ourselves. */ + if ((*ta)->sizeof_descr > sizeof (struct _pthread_descr_struct)) + (*ta)->sizeof_descr = sizeof (struct _pthread_descr_struct); + } + + /* Now add the new agent descriptor to the list. */ + elemp = (struct agent_list *) malloc (sizeof (struct agent_list)); + if (elemp == NULL) + { + /* Argh, now that everything else worked... */ + free (*ta); + return TD_MALLOC; + } + + /* We don't care for thread-safety here. */ + elemp->ta = *ta; + elemp->next = __td_agent_list; + __td_agent_list = elemp; + + return TD_OK; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_ta_reset_stats.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_ta_reset_stats.c new file mode 100644 index 00000000..b3ddbd07 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_ta_reset_stats.c @@ -0,0 +1,35 @@ +/* Reset statistics. + Copyright (C) 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_ta_reset_stats (const td_thragent_t *ta) +{ + /* XXX We have to figure out what has to be done. */ + LOG ("td_ta_reset_stats"); + + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + + return TD_OK; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_ta_set_event.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_ta_set_event.c new file mode 100644 index 00000000..6edb38e5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_ta_set_event.c @@ -0,0 +1,53 @@ +/* Globally enable events. + Copyright (C) 1999, 2001, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_ta_set_event (ta, event) + const td_thragent_t *ta; + td_thr_events_t *event; +{ + td_thr_events_t old_event; + int i; + + LOG ("td_ta_set_event"); + + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + + /* Write the new value into the thread data structure. */ + if (ps_pdread (ta->ph, ta->pthread_threads_eventsp, + &old_event, sizeof (td_thr_events_t)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + /* Or the new bits in. */ + for (i = 0; i < TD_EVENTSIZE; ++i) + old_event.event_bits[i] |= event->event_bits[i]; + + /* Write the new value into the thread data structure. */ + if (ps_pdwrite (ta->ph, ta->pthread_threads_eventsp, + &old_event, sizeof (td_thr_events_t)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + return TD_OK; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_ta_setconcurrency.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_ta_setconcurrency.c new file mode 100644 index 00000000..408e7630 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_ta_setconcurrency.c @@ -0,0 +1,35 @@ +/* Set suggested concurrency level for process. + Copyright (C) 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_ta_setconcurrency (const td_thragent_t *ta, int level) +{ + /* This is something LinuxThreads does not support. */ + LOG ("td_ta_setconcurrency"); + + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + + return TD_NOCAPAB; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_ta_thr_iter.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_ta_thr_iter.c new file mode 100644 index 00000000..9ab04e14 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_ta_thr_iter.c @@ -0,0 +1,176 @@ +/* Iterate over a process's threads. + Copyright (C) 1999,2000,2001,2002,2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" +#include +#include + +static int +handle_descr (const td_thragent_t *ta, td_thr_iter_f *callback, + void *cbdata_p, td_thr_state_e state, int ti_pri, + size_t cnt, pthread_descr descr) +{ + struct _pthread_descr_struct pds; + size_t sizeof_descr = ta->sizeof_descr; + td_thrhandle_t th; + + if (descr == NULL) + { + /* No descriptor (yet). */ + if (cnt == 0) + { + /* This is the main thread. Create a fake descriptor. */ + memset (&pds, '\0', sizeof (pds)); + + /* Empty thread descriptor the thread library would create. */ +#if !defined USE_TLS || !TLS_DTV_AT_TP + pds.p_header.data.self = &pds; +#endif + pds.p_nextlive = pds.p_prevlive = &pds; + pds.p_tid = PTHREAD_THREADS_MAX; + /* The init code also sets up p_lock, p_errnop, p_herrnop, and + p_userstack but this should not be necessary here. */ + + th.th_ta_p = (td_thragent_t *) ta; + th.th_unique = NULL; + if (callback (&th, cbdata_p) != 0) + return TD_DBERR; + + /* All done successfully. */ + return TD_OK; + } + else if (cnt == 1) + /* The manager is not yet started. No big deal. */ + return TD_OK; + else + /* For every other thread this should not happen. */ + return TD_ERR; + } + + if (ps_pdread (ta->ph, descr, &pds, sizeof_descr) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + /* The manager thread must be handled special. The descriptor + exists but the thread only gets created when the first + `pthread_create' call is issued. A clear indication that this + happened is when the p_pid field is non-zero. */ + if (cnt == 1 && pds.p_pid == 0) + return TD_OK; + + /* Now test whether this thread matches the specified + conditions. */ + + /* Only if the priority level is as high or higher. */ + if (pds.p_priority < ti_pri) + return TD_OK; + + /* Test the state. + XXX This is incomplete. */ + if (state != TD_THR_ANY_STATE) + return TD_OK; + + /* XXX For now we ignore threads which are not running anymore. + The reason is that gdb tries to get the registers and fails. + In future we should have a special mode of the thread library + in which we keep the process around until the actual join + operation happened. */ + if (pds.p_exited != 0) + return TD_OK; + + /* Yep, it matches. Call the callback function. */ + th.th_ta_p = (td_thragent_t *) ta; + th.th_unique = descr; + if (callback (&th, cbdata_p) != 0) + return TD_DBERR; + + /* All done successfully. */ + return TD_OK; +} + + +td_err_e +td_ta_thr_iter (const td_thragent_t *ta, td_thr_iter_f *callback, + void *cbdata_p, td_thr_state_e state, int ti_pri, + sigset_t *ti_sigmask_p, unsigned int ti_user_flags) +{ + int pthread_threads_max; + struct pthread_handle_struct *phc; + td_err_e result = TD_OK; + int cnt; +#ifdef ALL_THREADS_STOPPED + int num; +#else +# define num 1 +#endif + + LOG ("td_ta_thr_iter"); + + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + + pthread_threads_max = ta->pthread_threads_max; + phc = (struct pthread_handle_struct *) alloca (sizeof (phc[0]) + * pthread_threads_max); + + /* First read only the main thread and manager thread information. */ + if (ps_pdread (ta->ph, ta->handles, phc, + sizeof (struct pthread_handle_struct) * 2) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + /* Now handle these descriptors. */ + result = handle_descr (ta, callback, cbdata_p, state, ti_pri, 0, + phc[0].h_descr); + if (result != TD_OK) + return result; + result = handle_descr (ta, callback, cbdata_p, state, ti_pri, 1, + phc[1].h_descr); + if (result != TD_OK) + return result; + + /* Read all the descriptors. */ + if (ps_pdread (ta->ph, ta->handles + 2, &phc[2], + (sizeof (struct pthread_handle_struct) + * (pthread_threads_max - 2))) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + +#ifdef ALL_THREADS_STOPPED + /* Read the number of currently active threads. */ + if (ps_pdread (ta->ph, ta->pthread_handles_num, &num, sizeof (int)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ +#endif + + /* Now get all descriptors, one after the other. */ + for (cnt = 2; cnt < pthread_threads_max && num > 0; ++cnt) + if (phc[cnt].h_descr != NULL) + { +#ifdef ALL_THREADS_STOPPED + /* First count this active thread. */ + --num; +#endif + + result = handle_descr (ta, callback, cbdata_p, state, ti_pri, cnt, + phc[cnt].h_descr); + if (result != TD_OK) + break; + } + + return result; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_ta_tsd_iter.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_ta_tsd_iter.c new file mode 100644 index 00000000..2eb41f6a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_ta_tsd_iter.c @@ -0,0 +1,56 @@ +/* Iterate over a process's thread-specific data. + Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" +#include +#include + +td_err_e +td_ta_tsd_iter (const td_thragent_t *ta, td_key_iter_f *callback, + void *cbdata_p) +{ + struct pthread_key_struct *keys; + int pthread_keys_max; + int cnt; + + LOG ("td_ta_tsd_iter"); + + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + + pthread_keys_max = ta->pthread_keys_max; + keys = (struct pthread_key_struct *) alloca (sizeof (keys[0]) + * pthread_keys_max); + + /* Read all the information about the keys. */ + if (ps_pdread (ta->ph, ta->keys, keys, + sizeof (keys[0]) * pthread_keys_max) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + /* Now get all descriptors, one after the other. */ + for (cnt = 0; cnt < pthread_keys_max; ++cnt) + if (keys[cnt].in_use + /* Return with an error if the callback returns a nonzero value. */ + && callback (cnt, keys[cnt].destr, cbdata_p) != 0) + return TD_DBERR; + + return TD_OK; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_thr_clear_event.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_thr_clear_event.c new file mode 100644 index 00000000..147d1803 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_thr_clear_event.c @@ -0,0 +1,62 @@ +/* Disable specific event for thread. + Copyright (C) 1999, 2001, 2002, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#include "thread_dbP.h" + + +td_err_e +td_thr_clear_event (th, event) + const td_thrhandle_t *th; + td_thr_events_t *event; +{ + td_thr_events_t old_event; + int i; + + LOG ("td_thr_clear_event"); + + /* If the thread descriptor has not yet been constructed do not do + anything. */ + if (th->th_unique == NULL) + return TD_OK; + + /* Write the new value into the thread data structure. */ + if (ps_pdread (th->th_ta_p->ph, + ((char *) th->th_unique + + offsetof (struct _pthread_descr_struct, + p_eventbuf.eventmask)), + &old_event, sizeof (td_thr_events_t)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + /* Remove the set bits in. */ + for (i = 0; i < TD_EVENTSIZE; ++i) + old_event.event_bits[i] &= ~event->event_bits[i]; + + /* Write the new value into the thread data structure. */ + if (ps_pdwrite (th->th_ta_p->ph, + ((char *) th->th_unique + + offsetof (struct _pthread_descr_struct, + p_eventbuf.eventmask)), + &old_event, sizeof (td_thr_events_t)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + return TD_OK; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_thr_dbresume.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_thr_dbresume.c new file mode 100644 index 00000000..7b7f6eef --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_thr_dbresume.c @@ -0,0 +1,30 @@ +/* Resume execution of given thread. + Copyright (C) 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_thr_dbresume (const td_thrhandle_t *th) +{ + /* XXX We have to figure out what has to be done. */ + LOG ("td_thr_dbresume"); + return TD_NOCAPAB; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_thr_dbsuspend.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_thr_dbsuspend.c new file mode 100644 index 00000000..ef668023 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_thr_dbsuspend.c @@ -0,0 +1,30 @@ +/* Suspend execution of given thread. + Copyright (C) 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_thr_dbsuspend (const td_thrhandle_t *th) +{ + /* XXX We have to figure out what has to be done. */ + LOG ("td_thr_dbsuspend"); + return TD_NOCAPAB; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_thr_event_enable.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_thr_event_enable.c new file mode 100644 index 00000000..407f3fc4 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_thr_event_enable.c @@ -0,0 +1,57 @@ +/* Enable event process-wide. + Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#include "thread_dbP.h" + + +td_err_e +td_thr_event_enable (th, onoff) + const td_thrhandle_t *th; + int onoff; +{ + LOG ("td_thr_event_enable"); + + /* Write the new value into the thread data structure. */ + if (th->th_unique == NULL) + { + psaddr_t addr; + + if (td_lookup (th->th_ta_p->ph, LINUXTHREADS_INITIAL_REPORT_EVENTS, + &addr) != PS_OK) + /* Cannot read the symbol. This should not happen. */ + return TD_ERR; + + if (ps_pdwrite (th->th_ta_p->ph, addr, &onoff, sizeof (int)) != PS_OK) + return TD_ERR; + + return TD_OK; + } + + if (ps_pdwrite (th->th_ta_p->ph, + ((char *) th->th_unique + + offsetof (struct _pthread_descr_struct, + p_report_events)), + &onoff, sizeof (int)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + return TD_OK; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_thr_event_getmsg.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_thr_event_getmsg.c new file mode 100644 index 00000000..bf4ddd4a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_thr_event_getmsg.c @@ -0,0 +1,65 @@ +/* Retrieve event. + Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +#include "thread_dbP.h" + + +td_err_e +td_thr_event_getmsg (const td_thrhandle_t *th, td_event_msg_t *msg) +{ + td_eventbuf_t event; + + LOG ("td_thr_event_getmsg"); + + /* If the thread descriptor has not yet been created there cannot be + any event. */ + if (th->th_unique == NULL) + return TD_NOMSG; + + /* Read the even structure from the target. */ + if (ps_pdread (th->th_ta_p->ph, + ((char *) th->th_unique + + offsetof (struct _pthread_descr_struct, p_eventbuf)), + &event, sizeof (td_eventbuf_t)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + /* Check whether an event occurred. */ + if (event.eventnum == TD_EVENT_NONE) + /* Nothing. */ + return TD_NOMSG; + + /* Fill the user's data structure. */ + msg->event = event.eventnum; + msg->th_p = th; + msg->msg.data = (uintptr_t) event.eventdata; + + /* And clear the event message in the target. */ + memset (&event, '\0', sizeof (td_eventbuf_t)); + if (ps_pdwrite (th->th_ta_p->ph, + ((char *) th->th_unique + + offsetof (struct _pthread_descr_struct, p_eventbuf)), + &event, sizeof (td_eventbuf_t)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + return TD_OK; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_thr_get_info.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_thr_get_info.c new file mode 100644 index 00000000..4666bda9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_thr_get_info.c @@ -0,0 +1,83 @@ +/* Get thread information. + Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +#include "thread_dbP.h" + + +td_err_e +td_thr_get_info (const td_thrhandle_t *th, td_thrinfo_t *infop) +{ + struct _pthread_descr_struct pds; + + LOG ("td_thr_get_info"); + + /* Handle the case when the thread library is not yet initialized. */ + if (th->th_unique == NULL) + { + memset (&pds, '\0', sizeof (pds)); + pds.p_tid = PTHREAD_THREADS_MAX; + } + else + /* Get the thread descriptor. */ + if (ps_pdread (th->th_ta_p->ph, th->th_unique, &pds, + th->th_ta_p->sizeof_descr) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + /* Fill in information. Clear first to provide reproducable + results for the fields we do not fill in. */ + memset (infop, '\0', sizeof (td_thrinfo_t)); + + /* We have to handle the manager thread special since the thread + descriptor in older versions is not fully initialized. */ + if (pds.p_nr == 1) + { + infop->ti_tid = th->th_ta_p->pthread_threads_max * 2 + 1; + infop->ti_type = TD_THR_SYSTEM; + infop->ti_state = TD_THR_ACTIVE; + } + else + { + infop->ti_tid = pds.p_tid; + infop->ti_tls = (char *) pds.p_specific; + infop->ti_pri = pds.p_priority; + infop->ti_type = TD_THR_USER; + + if (! pds.p_terminated) + /* XXX For now there is no way to get more information. */ + infop->ti_state = TD_THR_ACTIVE; + else if (! pds.p_detached) + infop->ti_state = TD_THR_ZOMBIE; + else + infop->ti_state = TD_THR_UNKNOWN; + } + + /* Initialization which are the same in both cases. */ + infop->ti_lid = pds.p_pid ?: ps_getpid (th->th_ta_p->ph); + infop->ti_ta_p = th->th_ta_p; + infop->ti_startfunc = pds.p_start_args.start_routine; + memcpy (&infop->ti_events, &pds.p_eventbuf.eventmask, + sizeof (td_thr_events_t)); + infop->ti_traceme = pds.p_report_events != 0; + + return TD_OK; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_thr_getfpregs.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_thr_getfpregs.c new file mode 100644 index 00000000..31c55c87 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_thr_getfpregs.c @@ -0,0 +1,58 @@ +/* Get a thread's floating-point register set. + Copyright (C) 1999, 2001, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_thr_getfpregs (const td_thrhandle_t *th, prfpregset_t *regset) +{ + struct _pthread_descr_struct pds; + + LOG ("td_thr_getfpregs"); + + if (th->th_unique == NULL) + { + /* No data yet. Use the main thread. */ + pid_t pid = ps_getpid (th->th_ta_p->ph); + if (ps_lgetfpregs (th->th_ta_p->ph, pid, regset) != PS_OK) + return TD_ERR; + return TD_OK; + } + + /* We have to get the state and the PID for this thread. */ + if (ps_pdread (th->th_ta_p->ph, th->th_unique, &pds, + sizeof (struct _pthread_descr_struct)) != PS_OK) + return TD_ERR; + + /* If the thread already terminated we return all zeroes. */ + if (pds.p_terminated) + memset (regset, '\0', sizeof (*regset)); + /* Otherwise get the register content through the callback. */ + else + { + pid_t pid = pds.p_pid ?: ps_getpid (th->th_ta_p->ph); + + if (ps_lgetfpregs (th->th_ta_p->ph, pid, regset) != PS_OK) + return TD_ERR; + } + + return TD_OK; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_thr_getgregs.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_thr_getgregs.c new file mode 100644 index 00000000..a9ec6a37 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_thr_getgregs.c @@ -0,0 +1,58 @@ +/* Get a thread's general register set. + Copyright (C) 1999, 2000, 2001, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_thr_getgregs (const td_thrhandle_t *th, prgregset_t gregs) +{ + struct _pthread_descr_struct pds; + + LOG ("td_thr_getgregs"); + + if (th->th_unique == NULL) + { + /* No data yet. Use the main thread. */ + pid_t pid = ps_getpid (th->th_ta_p->ph); + if (ps_lgetregs (th->th_ta_p->ph, pid, gregs) != PS_OK) + return TD_ERR; + return TD_OK; + } + + /* We have to get the state and the PID for this thread. */ + if (ps_pdread (th->th_ta_p->ph, th->th_unique, &pds, + sizeof (struct _pthread_descr_struct)) != PS_OK) + return TD_ERR; + + /* If the thread already terminated we return all zeroes. */ + if (pds.p_terminated) + memset (gregs, '\0', sizeof (prgregset_t)); + /* Otherwise get the register content through the callback. */ + else + { + pid_t pid = pds.p_pid ?: ps_getpid (th->th_ta_p->ph); + + if (ps_lgetregs (th->th_ta_p->ph, pid, gregs) != PS_OK) + return TD_ERR; + } + + return TD_OK; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_thr_getxregs.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_thr_getxregs.c new file mode 100644 index 00000000..39cd73cf --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_thr_getxregs.c @@ -0,0 +1,30 @@ +/* Get a thread's extra state register set. + Copyright (C) 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_thr_getxregs (const td_thrhandle_t *th, void *xregs) +{ + /* XXX This might be platform specific. */ + LOG ("td_thr_getxregs"); + return TD_NOXREGS; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_thr_getxregsize.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_thr_getxregsize.c new file mode 100644 index 00000000..5d8ac288 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_thr_getxregsize.c @@ -0,0 +1,30 @@ +/* Get the size of the extra state register set for this architecture. + Copyright (C) 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_thr_getxregsize (const td_thrhandle_t *th, int *sizep) +{ + /* XXX This might be platform specific. */ + LOG ("td_thr_getxregsize"); + return TD_NOXREGS; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_thr_set_event.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_thr_set_event.c new file mode 100644 index 00000000..1e1def51 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_thr_set_event.c @@ -0,0 +1,62 @@ +/* Enable specific event for thread. + Copyright (C) 1999, 2001, 2002, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#include "thread_dbP.h" + + +td_err_e +td_thr_set_event (th, event) + const td_thrhandle_t *th; + td_thr_events_t *event; +{ + td_thr_events_t old_event; + int i; + + LOG ("td_thr_set_event"); + + /* What shall we do if no thread descriptor exists but the user + wants to set an event? */ + if (th->th_unique == NULL) + return TD_NOTALLOC; + + /* Write the new value into the thread data structure. */ + if (ps_pdread (th->th_ta_p->ph, + ((char *) th->th_unique + + offsetof (struct _pthread_descr_struct, + p_eventbuf.eventmask)), + &old_event, sizeof (td_thr_events_t)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + /* Or the new bits in. */ + for (i = 0; i < TD_EVENTSIZE; ++i) + old_event.event_bits[i] |= event->event_bits[i]; + + /* Write the new value into the thread data structure. */ + if (ps_pdwrite (th->th_ta_p->ph, + ((char *) th->th_unique + + offsetof (struct _pthread_descr_struct, + p_eventbuf.eventmask)), + &old_event, sizeof (td_thr_events_t)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + return TD_OK; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_thr_setfpregs.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_thr_setfpregs.c new file mode 100644 index 00000000..e4d9ec65 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_thr_setfpregs.c @@ -0,0 +1,47 @@ +/* Set a thread's floating-point register set. + Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_thr_setfpregs (const td_thrhandle_t *th, const prfpregset_t *fpregs) +{ + struct _pthread_descr_struct pds = { .p_terminated = 0, .p_pid = 0 }; + + LOG ("td_thr_setfpregs"); + + /* We have to get the state and the PID for this thread. */ + if (th->th_unique != NULL + && ps_pdread (th->th_ta_p->ph, th->th_unique, &pds, + sizeof (struct _pthread_descr_struct)) != PS_OK) + return TD_ERR; + + /* Only set the registers if the thread hasn't yet terminated. */ + if (pds.p_terminated == 0) + { + pid_t pid = pds.p_pid ?: ps_getpid (th->th_ta_p->ph); + + if (ps_lsetfpregs (th->th_ta_p->ph, pid, fpregs) != PS_OK) + return TD_ERR; + } + + return TD_OK; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_thr_setgregs.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_thr_setgregs.c new file mode 100644 index 00000000..8c021a47 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_thr_setgregs.c @@ -0,0 +1,47 @@ +/* Set a thread's general register set. + Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_thr_setgregs (const td_thrhandle_t *th, prgregset_t gregs) +{ + struct _pthread_descr_struct pds = { .p_terminated = 0, .p_pid = 0 }; + + LOG ("td_thr_setgregs"); + + /* We have to get the state and the PID for this thread. */ + if (th->th_unique != NULL + && ps_pdread (th->th_ta_p->ph, th->th_unique, &pds, + sizeof (struct _pthread_descr_struct)) != PS_OK) + return TD_ERR; + + /* Only set the registers if the thread hasn't yet terminated. */ + if (pds.p_terminated == 0) + { + pid_t pid = pds.p_pid ?: ps_getpid (th->th_ta_p->ph); + + if (ps_lsetregs (th->th_ta_p->ph, pid, gregs) != PS_OK) + return TD_ERR; + } + + return TD_OK; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_thr_setprio.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_thr_setprio.c new file mode 100644 index 00000000..98d202df --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_thr_setprio.c @@ -0,0 +1,30 @@ +/* Set a thread's priority. + Copyright (C) 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_thr_setprio (const td_thrhandle_t *th, int prio) +{ + /* XXX We have to figure out what has to be done. */ + LOG ("td_thr_setprio"); + return TD_OK; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_thr_setsigpending.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_thr_setsigpending.c new file mode 100644 index 00000000..98e30140 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_thr_setsigpending.c @@ -0,0 +1,31 @@ +/* Raise a signal for a thread. + Copyright (C) 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_thr_setsigpending (const td_thrhandle_t *th, unsigned char n, + const sigset_t *ss) +{ + /* XXX We have to figure out what has to be done. */ + LOG ("td_thr_setsigpending"); + return TD_OK; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_thr_setxregs.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_thr_setxregs.c new file mode 100644 index 00000000..da77ab3b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_thr_setxregs.c @@ -0,0 +1,30 @@ +/* Set a thread's extra state register set. + Copyright (C) 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_thr_setxregs (const td_thrhandle_t *ta, const void *addr) +{ + /* XXX This might have to be platform specific. */ + LOG ("td_thr_setxregs"); + return TD_NOXREGS; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_thr_sigsetmask.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_thr_sigsetmask.c new file mode 100644 index 00000000..8b0eb818 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_thr_sigsetmask.c @@ -0,0 +1,30 @@ +/* Set a thread's signal mask. + Copyright (C) 1999, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_thr_sigsetmask (const td_thrhandle_t *th, const sigset_t *ss) +{ + /* XXX We have to figure out what has to be done. */ + LOG ("td_thr_sigsetmask"); + return TD_OK; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_thr_tls_get_addr.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_thr_tls_get_addr.c new file mode 100644 index 00000000..c900cac8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_thr_tls_get_addr.c @@ -0,0 +1,45 @@ +/* Get address of thread local variable. + Copyright (C) 2002,2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include "thread_dbP.h" + +td_err_e +td_thr_tls_get_addr (const td_thrhandle_t *th __attribute__ ((unused)), + void *map_address __attribute__ ((unused)), + size_t offset __attribute__ ((unused)), + void **address __attribute__ ((unused))) +{ +#if USE_TLS + /* Read the module ID from the link_map. */ + size_t modid; + if (ps_pdread (th->th_ta_p->ph, + &((struct link_map *) map_address)->l_tls_modid, + &modid, sizeof modid) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + td_err_e result = td_thr_tlsbase (th, modid, address); + if (result == TD_OK) + *address += offset; + return result; +#else + return TD_ERR; +#endif +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_thr_tlsbase.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_thr_tlsbase.c new file mode 100644 index 00000000..00c863de --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_thr_tlsbase.c @@ -0,0 +1,71 @@ +/* Locate TLS data for a thread. + Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + +/* Value used for dtv entries for which the allocation is delayed. */ +# define TLS_DTV_UNALLOCATED ((void *) -1l) + +td_err_e +td_thr_tlsbase (const td_thrhandle_t *th, + unsigned long int modid, + psaddr_t *base) +{ + if (modid < 1) + return TD_NOTLS; + +#if USE_TLS + union dtv pdtv, *dtvp; + + LOG ("td_thr_tlsbase"); + + psaddr_t dtvpp = th->th_unique; +#if defined(TLS_TCB_AT_TP) + dtvpp += offsetof (struct _pthread_descr_struct, p_header.data.dtvp); +#elif defined(TLS_DTV_AT_TP) +/* Special case hack. If TLS_TCB_SIZE == 0 (on PowerPC), there is no TCB + containing the DTV at the TP, but actually the TCB lies behind the TP, + i.e. at the very end of the area covered by TLS_PRE_TCB_SIZE. */ + dtvpp += TLS_PRE_TCB_SIZE + offsetof (tcbhead_t, dtv) + - (TLS_TCB_SIZE == 0 ? sizeof (tcbhead_t) : 0); +#else +# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined." +#endif + + /* Get the DTV pointer from the thread descriptor. */ + if (ps_pdread (th->th_ta_p->ph, dtvpp, &dtvp, sizeof dtvp) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + /* Get the corresponding entry in the DTV. */ + if (ps_pdread (th->th_ta_p->ph, dtvp + modid, + &pdtv, sizeof (union dtv)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + /* It could be that the memory for this module is not allocated for + the given thread. */ + if (pdtv.pointer.val == TLS_DTV_UNALLOCATED) + return TD_TLSDEFER; + + *base = (char *) pdtv.pointer.val; + + return TD_OK; +#else + return TD_ERR; +#endif +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_thr_tsd.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_thr_tsd.c new file mode 100644 index 00000000..978dc5e5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_thr_tsd.c @@ -0,0 +1,82 @@ +/* Get a thread-specific data pointer for a thread. + Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" +#include + + +td_err_e +td_thr_tsd (const td_thrhandle_t *th, const thread_key_t tk, void **data) +{ + struct _pthread_descr_struct pds; + struct pthread_key_struct *keys = th->th_ta_p->keys; + struct pthread_key_struct key; + int pthread_keys_max = th->th_ta_p->pthread_keys_max; + int pthread_key_2ndlevel_size = th->th_ta_p->pthread_key_2ndlevel_size; + unsigned int idx1st; + unsigned int idx2nd; + void *p; + + LOG ("td_thr_tsd"); + + /* If there is no thread descriptor there cannot be any thread + specific data. */ + if (th->th_unique == NULL) + return TD_BADKEY; + + /* Get the thread descriptor. */ + if (ps_pdread (th->th_ta_p->ph, th->th_unique, &pds, + sizeof (struct _pthread_descr_struct)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + /* Check correct value of key. */ + if (tk >= pthread_keys_max) + return TD_BADKEY; + + /* Get the key entry. */ + if (ps_pdread (th->th_ta_p->ph, &keys[tk], &key, + sizeof (struct pthread_key_struct)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + /* Fail if this key is not at all used. */ + if (! key.in_use) + return TD_BADKEY; + + /* Compute the indeces. */ + idx1st = tk / pthread_key_2ndlevel_size; + idx2nd = tk % pthread_key_2ndlevel_size; + + /* Check the pointer to the second level array. */ + if (pds.p_specific[idx1st] == NULL) + return TD_NOTSD; + + /* Now get the real key. + XXX I don't know whether it's correct but there is currently no + easy way to determine whether a key was never set or the value + is NULL. We return an error whenever the value is NULL. */ + if (ps_pdread (th->th_ta_p->ph, &pds.p_specific[idx1st][idx2nd], &p, + sizeof (void *)) != PS_OK) + return TD_ERR; + + if (p != NULL) + *data = p; + + return p != NULL ? TD_OK : TD_NOTSD; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_thr_validate.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_thr_validate.c new file mode 100644 index 00000000..6f893d3f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/td_thr_validate.c @@ -0,0 +1,70 @@ +/* Validate a thread handle. + Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" +#include + + +td_err_e +td_thr_validate (const td_thrhandle_t *th) +{ + struct pthread_handle_struct *handles = th->th_ta_p->handles; + int pthread_threads_max = th->th_ta_p->pthread_threads_max; + int cnt; + struct pthread_handle_struct phc; + + LOG ("td_thr_validate"); + + /* A special case: if the program just starts up the handle is + NULL. */ + if (th->th_unique == NULL) + { + /* Read the first handle. If the pointer to the thread + descriptor is not NULL this is an error. */ + if (ps_pdread (th->th_ta_p->ph, handles, &phc, + sizeof (struct pthread_handle_struct)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + return phc.h_descr == NULL ? TD_OK : TD_NOTHR; + } + + /* Now get all descriptors, one after the other. */ + for (cnt = 0; cnt < pthread_threads_max; ++cnt, ++handles) + { + if (ps_pdread (th->th_ta_p->ph, handles, &phc, + sizeof (struct pthread_handle_struct)) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + if (phc.h_descr != NULL && phc.h_descr == th->th_unique) + { + struct _pthread_descr_struct pds; + + if (ps_pdread (th->th_ta_p->ph, phc.h_descr, &pds, + th->th_ta_p->sizeof_descr) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + + /* XXX There should be another test using the TID but this is + currently not available. */ + return pds.p_terminated != 0 ? TD_NOTHR : TD_OK; + } + } + + return TD_ERR; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/thread_db.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/thread_db.h new file mode 100644 index 00000000..c115399a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/thread_db.h @@ -0,0 +1,459 @@ +/* thread_db.h -- interface to libthread_db.so library for debugging -lpthread + Copyright (C) 1999,2001,2002,2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _THREAD_DB_H +#define _THREAD_DB_H 1 + +/* This is the debugger interface for the LinuxThreads library. It is + modelled closely after the interface with same names in Solaris with + the goal to share the same code in the debugger. */ +#include +#include +#include +#include + + +/* Error codes of the library. */ +typedef enum +{ + TD_OK, /* No error. */ + TD_ERR, /* No further specified error. */ + TD_NOTHR, /* No matching thread found. */ + TD_NOSV, /* No matching synchronization handle found. */ + TD_NOLWP, /* No matching light-weighted process found. */ + TD_BADPH, /* Invalid process handle. */ + TD_BADTH, /* Invalid thread handle. */ + TD_BADSH, /* Invalid synchronization handle. */ + TD_BADTA, /* Invalid thread agent. */ + TD_BADKEY, /* Invalid key. */ + TD_NOMSG, /* No event available. */ + TD_NOFPREGS, /* No floating-point register content available. */ + TD_NOLIBTHREAD, /* Application not linked with thread library. */ + TD_NOEVENT, /* Requested event is not supported. */ + TD_NOCAPAB, /* Capability not available. */ + TD_DBERR, /* Internal debug library error. */ + TD_NOAPLIC, /* Operation is not applicable. */ + TD_NOTSD, /* No thread-specific data available. */ + TD_MALLOC, /* Out of memory. */ + TD_PARTIALREG, /* Not entire register set was read or written. */ + TD_NOXREGS, /* X register set not available for given thread. */ + TD_TLSDEFER, /* Thread has not yet allocated TLS for given module. */ + TD_NOTALLOC = TD_TLSDEFER, + TD_VERSION, /* Version if libpthread and libthread_db do not match. */ + TD_NOTLS /* There is TLS segment in the given module. */ +} td_err_e; + + +/* Possible thread states. TD_THR_ANY_STATE is a pseudo-state used to + select threads regardless of state in td_ta_thr_iter(). */ +typedef enum +{ + TD_THR_ANY_STATE, + TD_THR_UNKNOWN, + TD_THR_STOPPED, + TD_THR_RUN, + TD_THR_ACTIVE, + TD_THR_ZOMBIE, + TD_THR_SLEEP, + TD_THR_STOPPED_ASLEEP +} td_thr_state_e; + +/* Thread type: user or system. TD_THR_ANY_TYPE is a pseudo-type used + to select threads regardless of type in td_ta_thr_iter(). */ +typedef enum +{ + TD_THR_ANY_TYPE, + TD_THR_USER, + TD_THR_SYSTEM +} td_thr_type_e; + + +/* Types of the debugging library. */ + +/* Handle for a process. This type is opaque. */ +typedef struct td_thragent td_thragent_t; + +/* The actual thread handle type. This is also opaque. */ +typedef struct td_thrhandle +{ + td_thragent_t *th_ta_p; + psaddr_t th_unique; +} td_thrhandle_t; + + +/* Forward declaration of a type defined by and for the dynamic linker. */ +struct link_map; + + +/* Flags for `td_ta_thr_iter'. */ +#define TD_THR_ANY_USER_FLAGS 0xffffffff +#define TD_THR_LOWEST_PRIORITY -20 +#define TD_SIGNO_MASK NULL + + +#define TD_EVENTSIZE 2 +#define BT_UISHIFT 5 /* log base 2 of BT_NBIPUI, to extract word index */ +#define BT_NBIPUI (1 << BT_UISHIFT) /* n bits per uint */ +#define BT_UIMASK (BT_NBIPUI - 1) /* to extract bit index */ + +/* Bitmask of enabled events. */ +typedef struct td_thr_events +{ + uint32_t event_bits[TD_EVENTSIZE]; +} td_thr_events_t; + +/* Event set manipulation macros. */ +#define __td_eventmask(n) \ + (UINT32_C (1) << (((n) - 1) & BT_UIMASK)) +#define __td_eventword(n) \ + ((UINT32_C ((n) - 1)) >> BT_UISHIFT) + +#define td_event_emptyset(setp) \ + do { \ + int __i; \ + for (__i = TD_EVENTSIZE; __i > 0; --__i) \ + (setp)->event_bits[__i - 1] = 0; \ + } while (0) + +#define td_event_fillset(setp) \ + do { \ + int __i; \ + for (__i = TD_EVENTSIZE; __i > 0; --__i) \ + (setp)->event_bits[__i - 1] = UINT32_C (0xffffffff); \ + } while (0) + +#define td_event_addset(setp, n) \ + (((setp)->event_bits[__td_eventword (n)]) |= __td_eventmask (n)) +#define td_event_delset(setp, n) \ + (((setp)->event_bits[__td_eventword (n)]) &= ~__td_eventmask (n)) +#define td_eventismember(setp, n) \ + (__td_eventmask (n) & ((setp)->event_bits[__td_eventword (n)])) +#if TD_EVENTSIZE == 2 +# define td_eventisempty(setp) \ + (!((setp)->event_bits[0]) && !((setp)->event_bits[1])) +#else +# error "td_eventisempty must be changed to match TD_EVENTSIZE" +#endif + +/* Events reportable by the thread implementation. */ +typedef enum +{ + TD_ALL_EVENTS, /* Pseudo-event number. */ + TD_EVENT_NONE = TD_ALL_EVENTS, /* Depends on context. */ + TD_READY, /* Is executable now. */ + TD_SLEEP, /* Blocked in a synchronization obj. */ + TD_SWITCHTO, /* Now assigned to a process. */ + TD_SWITCHFROM, /* Not anymore assigned to a process. */ + TD_LOCK_TRY, /* Trying to get an unavailable lock. */ + TD_CATCHSIG, /* Signal posted to the thread. */ + TD_IDLE, /* Process getting idle. */ + TD_CREATE, /* New thread created. */ + TD_DEATH, /* Thread terminated. */ + TD_PREEMPT, /* Preempted. */ + TD_PRI_INHERIT, /* Inherited elevated priority. */ + TD_REAP, /* Reaped. */ + TD_CONCURRENCY, /* Number of processes changing. */ + TD_TIMEOUT, /* Conditional variable wait timed out. */ + TD_MIN_EVENT_NUM = TD_READY, + TD_MAX_EVENT_NUM = TD_TIMEOUT, + TD_EVENTS_ENABLE = 31 /* Event reporting enabled. */ +} td_event_e; + +/* Values representing the different ways events are reported. */ +typedef enum +{ + NOTIFY_BPT, /* User must insert breakpoint at u.bptaddr. */ + NOTIFY_AUTOBPT, /* Breakpoint at u.bptaddr is automatically + inserted. */ + NOTIFY_SYSCALL /* System call u.syscallno will be invoked. */ +} td_notify_e; + +/* Description how event type is reported. */ +typedef struct td_notify +{ + td_notify_e type; /* Way the event is reported. */ + union + { + psaddr_t bptaddr; /* Address of breakpoint. */ + int syscallno; /* Number of system call used. */ + } u; +} td_notify_t; + +/* Structure used to report event. */ +typedef struct td_event_msg +{ + td_event_e event; /* Event type being reported. */ + const td_thrhandle_t *th_p; /* Thread reporting the event. */ + union + { +# if 0 + td_synchandle_t *sh; /* Handle of synchronization object. */ +#endif + uintptr_t data; /* Event specific data. */ + } msg; +} td_event_msg_t; + +/* Structure containing event data available in each thread structure. */ +typedef struct +{ + td_thr_events_t eventmask; /* Mask of enabled events. */ + td_event_e eventnum; /* Number of last event. */ + void *eventdata; /* Data associated with event. */ +} td_eventbuf_t; + + +/* Gathered statistics about the process. */ +typedef struct td_ta_stats +{ + int nthreads; /* Total number of threads in use. */ + int r_concurrency; /* Concurrency level requested by user. */ + int nrunnable_num; /* Average runnable threads, numerator. */ + int nrunnable_den; /* Average runnable threads, denominator. */ + int a_concurrency_num; /* Achieved concurrency level, numerator. */ + int a_concurrency_den; /* Achieved concurrency level, denominator. */ + int nlwps_num; /* Average number of processes in use, + numerator. */ + int nlwps_den; /* Average number of processes in use, + denominator. */ + int nidle_num; /* Average number of idling processes, + numerator. */ + int nidle_den; /* Average number of idling processes, + denominator. */ +} td_ta_stats_t; + + +/* Since Sun's library is based on Solaris threads we have to define a few + types to map them to POSIX threads. */ +typedef pthread_t thread_t; +typedef pthread_key_t thread_key_t; + + +/* Callback for iteration over threads. */ +typedef int td_thr_iter_f (const td_thrhandle_t *, void *); + +/* Callback for iteration over thread local data. */ +typedef int td_key_iter_f (thread_key_t, void (*) (void *), void *); + + + +/* Forward declaration. This has to be defined by the user. */ +struct ps_prochandle; + + +/* Information about the thread. */ +typedef struct td_thrinfo +{ + td_thragent_t *ti_ta_p; /* Process handle. */ + unsigned int ti_user_flags; /* Unused. */ + thread_t ti_tid; /* Thread ID returned by + pthread_create(). */ + char *ti_tls; /* Pointer to thread-local data. */ + psaddr_t ti_startfunc; /* Start function passed to + pthread_create(). */ + psaddr_t ti_stkbase; /* Base of thread's stack. */ + long int ti_stksize; /* Size of thread's stack. */ + psaddr_t ti_ro_area; /* Unused. */ + int ti_ro_size; /* Unused. */ + td_thr_state_e ti_state; /* Thread state. */ + unsigned char ti_db_suspended; /* Nonzero if suspended by debugger. */ + td_thr_type_e ti_type; /* Type of the thread (system vs + user thread). */ + intptr_t ti_pc; /* Unused. */ + intptr_t ti_sp; /* Unused. */ + short int ti_flags; /* Unused. */ + int ti_pri; /* Thread priority. */ + lwpid_t ti_lid; /* Unused. */ + sigset_t ti_sigmask; /* Signal mask. */ + unsigned char ti_traceme; /* Nonzero if event reporting + enabled. */ + unsigned char ti_preemptflag; /* Unused. */ + unsigned char ti_pirecflag; /* Unused. */ + sigset_t ti_pending; /* Set of pending signals. */ + td_thr_events_t ti_events; /* Set of enabled events. */ +} td_thrinfo_t; + + + +/* Prototypes for exported library functions. */ + +/* Initialize the thread debug support library. */ +extern td_err_e td_init (void); + +/* Historical relict. Should not be used anymore. */ +extern td_err_e td_log (void); + +/* Return list of symbols the library can request. */ +extern const char **td_symbol_list (void); + +/* Generate new thread debug library handle for process PS. */ +extern td_err_e td_ta_new (struct ps_prochandle *__ps, td_thragent_t **__ta); + +/* Free resources allocated for TA. */ +extern td_err_e td_ta_delete (td_thragent_t *__ta); + +/* Get number of currently running threads in process associated with TA. */ +extern td_err_e td_ta_get_nthreads (const td_thragent_t *__ta, int *__np); + +/* Return process handle passed in `td_ta_new' for process associated with + TA. */ +extern td_err_e td_ta_get_ph (const td_thragent_t *__ta, + struct ps_prochandle **__ph); + +/* Map thread library handle PT to thread debug library handle for process + associated with TA and store result in *TH. */ +extern td_err_e td_ta_map_id2thr (const td_thragent_t *__ta, pthread_t __pt, + td_thrhandle_t *__th); + +/* Map process ID LWPID to thread debug library handle for process + associated with TA and store result in *TH. */ +extern td_err_e td_ta_map_lwp2thr (const td_thragent_t *__ta, lwpid_t __lwpid, + td_thrhandle_t *__th); + + +/* Call for each thread in a process associated with TA the callback function + CALLBACK. */ +extern td_err_e td_ta_thr_iter (const td_thragent_t *__ta, + td_thr_iter_f *__callback, void *__cbdata_p, + td_thr_state_e __state, int __ti_pri, + sigset_t *__ti_sigmask_p, + unsigned int __ti_user_flags); + +/* Call for each defined thread local data entry the callback function KI. */ +extern td_err_e td_ta_tsd_iter (const td_thragent_t *__ta, td_key_iter_f *__ki, + void *__p); + + +/* Get event address for EVENT. */ +extern td_err_e td_ta_event_addr (const td_thragent_t *__ta, + td_event_e __event, td_notify_t *__ptr); + +/* Enable EVENT in global mask. */ +extern td_err_e td_ta_set_event (const td_thragent_t *__ta, + td_thr_events_t *__event); + +/* Disable EVENT in global mask. */ +extern td_err_e td_ta_clear_event (const td_thragent_t *__ta, + td_thr_events_t *__event); + +/* Return information about last event. */ +extern td_err_e td_ta_event_getmsg (const td_thragent_t *__ta, + td_event_msg_t *__msg); + + +/* Set suggested concurrency level for process associated with TA. */ +extern td_err_e td_ta_setconcurrency (const td_thragent_t *__ta, int __level); + + +/* Enable collecting statistics for process associated with TA. */ +extern td_err_e td_ta_enable_stats (const td_thragent_t *__ta, int __enable); + +/* Reset statistics. */ +extern td_err_e td_ta_reset_stats (const td_thragent_t *__ta); + +/* Retrieve statistics from process associated with TA. */ +extern td_err_e td_ta_get_stats (const td_thragent_t *__ta, + td_ta_stats_t *__statsp); + + +/* Validate that TH is a thread handle. */ +extern td_err_e td_thr_validate (const td_thrhandle_t *__th); + +/* Return information about thread TH. */ +extern td_err_e td_thr_get_info (const td_thrhandle_t *__th, + td_thrinfo_t *__infop); + +/* Retrieve floating-point register contents of process running thread TH. */ +extern td_err_e td_thr_getfpregs (const td_thrhandle_t *__th, + prfpregset_t *__regset); + +/* Retrieve general register contents of process running thread TH. */ +extern td_err_e td_thr_getgregs (const td_thrhandle_t *__th, + prgregset_t __gregs); + +/* Retrieve extended register contents of process running thread TH. */ +extern td_err_e td_thr_getxregs (const td_thrhandle_t *__th, void *__xregs); + +/* Get size of extended register set of process running thread TH. */ +extern td_err_e td_thr_getxregsize (const td_thrhandle_t *__th, int *__sizep); + +/* Set floating-point register contents of process running thread TH. */ +extern td_err_e td_thr_setfpregs (const td_thrhandle_t *__th, + const prfpregset_t *__fpregs); + +/* Set general register contents of process running thread TH. */ +extern td_err_e td_thr_setgregs (const td_thrhandle_t *__th, + prgregset_t __gregs); + +/* Set extended register contents of process running thread TH. */ +extern td_err_e td_thr_setxregs (const td_thrhandle_t *__th, + const void *__addr); + + +/* Get address of the given module's TLS storage area for the given thread. */ +extern td_err_e td_thr_tlsbase (const td_thrhandle_t *__th, + unsigned long int __modid, + psaddr_t *__base); + +/* Get address of thread local variable. */ +extern td_err_e td_thr_tls_get_addr (const td_thrhandle_t *__th, + void *__map_address, size_t __offset, + void **__address); + + +/* Enable reporting for EVENT for thread TH. */ +extern td_err_e td_thr_event_enable (const td_thrhandle_t *__th, int __event); + +/* Enable EVENT for thread TH. */ +extern td_err_e td_thr_set_event (const td_thrhandle_t *__th, + td_thr_events_t *__event); + +/* Disable EVENT for thread TH. */ +extern td_err_e td_thr_clear_event (const td_thrhandle_t *__th, + td_thr_events_t *__event); + +/* Get event message for thread TH. */ +extern td_err_e td_thr_event_getmsg (const td_thrhandle_t *__th, + td_event_msg_t *__msg); + + +/* Set priority of thread TH. */ +extern td_err_e td_thr_setprio (const td_thrhandle_t *__th, int __prio); + + +/* Set pending signals for thread TH. */ +extern td_err_e td_thr_setsigpending (const td_thrhandle_t *__th, + unsigned char __n, const sigset_t *__ss); + +/* Set signal mask for thread TH. */ +extern td_err_e td_thr_sigsetmask (const td_thrhandle_t *__th, + const sigset_t *__ss); + + +/* Return thread local data associated with key TK in thread TH. */ +extern td_err_e td_thr_tsd (const td_thrhandle_t *__th, + const thread_key_t __tk, void **__data); + + +/* Suspend execution of thread TH. */ +extern td_err_e td_thr_dbsuspend (const td_thrhandle_t *__th); + +/* Resume execution of thread TH. */ +extern td_err_e td_thr_dbresume (const td_thrhandle_t *__th); + +#endif /* thread_db.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/thread_dbP.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/thread_dbP.h new file mode 100644 index 00000000..407f3063 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/linuxthreads_db/thread_dbP.h @@ -0,0 +1,108 @@ +/* Private header for thread debug library. */ +#ifndef _THREAD_DBP_H +#define _THREAD_DBP_H 1 + +#include +#include +#include "proc_service.h" +#include "thread_db.h" +#include "../linuxthreads/descr.h" + + +/* Indices for the symbol names. */ +enum + { + PTHREAD_THREADS_EVENTS = 0, + PTHREAD_LAST_EVENT, + PTHREAD_HANDLES_NUM, + PTHREAD_HANDLES, + PTHREAD_KEYS, + LINUXTHREADS_PTHREAD_THREADS_MAX, + LINUXTHREADS_PTHREAD_KEYS_MAX, + LINUXTHREADS_PTHREAD_SIZEOF_DESCR, + LINUXTHREADS_CREATE_EVENT, + LINUXTHREADS_DEATH_EVENT, + LINUXTHREADS_REAP_EVENT, + LINUXTHREADS_INITIAL_REPORT_EVENTS, + LINUXTHREADS_VERSION, + NUM_MESSAGES + }; + + +/* Comment out the following for less verbose output. */ +#ifndef NDEBUG +# define LOG(c) if (__td_debug) write (2, c "\n", strlen (c "\n")) +extern int __td_debug attribute_hidden; +#else +# define LOG(c) +#endif + + +/* Handle for a process. This type is opaque. */ +struct td_thragent +{ + /* Delivered by the debugger and we have to pass it back in the + proc callbacks. */ + struct ps_prochandle *ph; + + /* Some cached information. */ + + /* Address of the `__pthread_handles' array. */ + struct pthread_handle_struct *handles; + + /* Address of the `pthread_kyes' array. */ + struct pthread_key_struct *keys; + + /* Maximum number of threads. */ + int pthread_threads_max; + + /* Maximum number of thread-local data keys. */ + int pthread_keys_max; + + /* Size of 2nd level array for thread-local data keys. */ + int pthread_key_2ndlevel_size; + + /* Sizeof struct _pthread_descr_struct. */ + int sizeof_descr; + + /* Pointer to the `__pthread_threads_events' variable in the target. */ + psaddr_t pthread_threads_eventsp; + + /* Pointer to the `__pthread_last_event' variable in the target. */ + psaddr_t pthread_last_event; + + /* Pointer to the `__pthread_handles_num' variable. */ + psaddr_t pthread_handles_num; +}; + + +/* Type used internally to keep track of thread agent descriptors. */ +struct agent_list +{ + td_thragent_t *ta; + struct agent_list *next; +}; + +/* List of all known descriptors. */ +extern struct agent_list *__td_agent_list attribute_hidden; + +/* Function used to test for correct thread agent pointer. */ +static __inline__ int +ta_ok (const td_thragent_t *ta) +{ + struct agent_list *runp = __td_agent_list; + + if (ta == NULL) + return 0; + + while (runp != NULL && runp->ta != ta) + runp = runp->next; + + return runp != NULL; +} + + +/* Internal wrapper around ps_pglobal_lookup. */ +extern int td_lookup (struct ps_prochandle *ps, int idx, psaddr_t *sym_addr) attribute_hidden; + +#endif /* thread_dbP.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/.gitignore b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/.gitignore new file mode 100644 index 00000000..ac44e0c5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/.gitignore @@ -0,0 +1,26 @@ +# +# Never ignore these +# +!.gitignore +# +# Generated files +# +/pthread-errnos.h +/gen_pthread-errnos.[cs] +!sysdeps/pthread/tcb-offsets.h +sysdeps/*/tcb-offsets.h +sysdeps/*/gen_tcb-offsets.[cs] +sysdeps/unix/sysv/linux/gen_*.[cs] +sysdeps/unix/sysv/linux/lowlevelbarrier.h +sysdeps/unix/sysv/linux/lowlevelcond.h +sysdeps/unix/sysv/linux/lowlevelrwlock.h +sysdeps/unix/sysv/linux/lowlevelrobustlock.h +sysdeps/unix/sysv/linux/structsem.h +sysdeps/unix/sysv/linux/unwindbuf.h +sysdeps/unix/sysv/linux/pthread-pi-defines.h +# +# symlinks +# +sysdeps/pthread/pt-sigaction.c +sysdeps/pthread/pt-sigfillset.c +sysdeps/pthread/pt-sigprocmask.c diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/ChangeLog b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/ChangeLog new file mode 100644 index 00000000..c81eb03b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/ChangeLog @@ -0,0 +1,11100 @@ +2010-01-15 Ulrich Drepper + + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: + Fix unwind info. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S: Likewise. + +2010-01-15 Michal Schmidt + + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: + Fix pthread_cond_timedwait with requeue-PI. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S: + Fix pthread_cond_wait with requeue-PI. + +2010-01-14 Ulrich Drepper + + * Versions: Add pthread_mutex_consistent, pthread_mutexattr_getrobust, + and pthread_mutexattr_setrobust for GLIBC_2.12. + * pthread_mutex_consistent.c: Define alias pthread_mutex_consistent. + * pthread_mutexattr_getrobust.c: Define alias + pthread_mutexattr_getrobust. + * pthread_mutexattr_setrobust.c: Define alias + pthread_mutexattr_setrobust. + +2010-01-12 Ulrich Drepper + + * sysdeps/pthread/pthread.h: Cleanup. Fix up for XPG7. + +2010-01-08 Ulrich Drepper + + * sysdeps/pthread/pthread.h: Fix pthread_mutex_consistent declaration. + +2009-12-18 Thomas Schwinge + + * sysdeps/unix/sysv/linux/s390/s390-32/pt-initfini.c (_init): Don't + call __gmon_start__. + * sysdeps/unix/sysv/linux/s390/s390-64/pt-initfini.c (_init): Likewise. + +2009-12-17 Ulrich Drepper + + * pthread_rwlock_init.c (__pthread_rwlock_init): Simplify code by + using memset. + +2009-12-01 Dinakar Guniguntala + + * sysdeps/unix/sysv/linux/i386/i486/lowlevellock.h: Define + FUTEX_WAIT_REQUEUE_PI and FUTEX_CMP_REQUEUE_PI. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.S: If mutex + is a non robust PI mutex, then use FUTEX_CMP_REQUEUE_PI. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_signal.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: If mutex + is a non robust PI mutex, then use FUTEX_WAIT_REQUEUE_PI. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S: Likewise. + +2009-12-12 Ulrich Drepper + + * sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S (sem_timedwait): + Don't update nwaiters after invalid timeout is recognized. + +2009-11-27 Thomas Schwinge + + * sysdeps/unix/sysv/linux/sh/pt-initfini.c (_init): Don't call + __gmon_start__. + +2009-11-27 Andreas Schwab + + * sysdeps/unix/sysv/linux/x86_64/cancellation.S: Reload + THREAD_SELF->cancelhandling after returning from futex call. + +2009-11-24 Ulrich Drepper + + * tst-sem13.c: New file. + * Makefile (tests): Add tst-sem13. + +2009-11-22 Roland McGrath + + * sysdeps/unix/sysv/linux/i386/dl-sysdep.h: # include "i686/dl-sysdep.h" + instead of recapitulating its contents. + +2009-11-18 Ulrich Drepper + + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.S: Minor + optimizations and cleanups. + +2009-11-18 Dinakar Guniguntala + + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.S: + Remove redundant code. Fix cfi offsets. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_signal.S: + Fix cfi offsets. + +2009-11-17 Ulrich Drepper + + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S: Minimally + reduce size of unwind info. + + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S: Convert to use + cfi directives. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: Likewise. + Based on a patch by Dinakar Guniguntala . + +2009-11-03 Andreas Schwab + + [BZ #4457] + * sysdeps/pthread/unwind-resume.c: Include and use + LIBGCC_S_SO. + * sysdeps/pthread/unwind-forcedunwind.c: Likewise. + +2009-10-30 Ulrich Drepper + + * tst-sem11.c (main): Rewrite to avoid aliasing problems. + + [BZ #3270] + * allocatestack.c (__nptl_setxid): Perform the operation in multiple + steps to avoid races with creation and terminations. + * nptl-init.c (sighandler_setxid): Adjust. + Patch by Daniel Jacobowitz. + +2009-09-07 Andreas Schwab + + * sysdeps/pthread/bits/libc-lock.h (BP_SYM): Remove space before paren. + +2009-09-02 Suzuki K P + Joseph Myers + + [BZ #7094] + * sysdeps/unix/sysv/linux/timer_create.c (timer_create): + Initialize the sigev_notify field for newly created timer to make sure + the timer gets deleted from the active timer's list upon timer_delete. + +2009-08-27 Andrew Stubbs + + * sysdeps/unix/sysv/linux/sh/lowlevellock.S (__lll_timedlock_wait): + Correct a logic error. + +2009-08-25 Ulrich Drepper + + * sysdeps/x86_64/tls.h (RTLD_ENABLE_FOREIGN_CALL): Store old value + of the field in local variables. + (RTLD_FINALIZE_FOREIGN_CALL): Restore rtld_must_xmm_save from local + variable and don't unconditionally clear it. + +2009-08-24 Ulrich Drepper + + * pthread_create.c (start_thread): Hint to the kernel that memory for + the stack can be reused. We do not mark all the memory. The part + still in use and some reserve are kept. + +2009-08-23 Ulrich Drepper + + * sysdeps/unix/sysv/linux/bits/posix_opt.h: Clean up namespace. + +2009-08-11 Ulrich Drepper + + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_unlock.S: Add CFI + directives. + +2009-08-10 Ulrich Drepper + + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_rdlock.S: Add CFI + directives. + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_wrlock.S: Likewise. + +2009-08-10 Andreas Schwab + + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.S + (__pthread_cond_signal): Don't clobber register used for syscall + number. + +2009-08-08 Ulrich Drepper + + * sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S (sem_timedwait): + Optimize code path used when FUTEX_CLOCK_REALTIME is supported. + + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S + (__pthread_cond_wait): Optimize by avoiding use of callee-safe + register. + +2009-08-07 Ulrich Drepper + + * sysdeps/unix/sysv/linux/x86_64/sem_wait.S: Little optimizations + enabled by the special *_asynccancel functions. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S: Likewise. + + * sysdeps/unix/sysv/linux/x86_64/cancellation.S: Include lowlevellock.h. + +2009-08-04 Ulrich Drepper + + * sysdeps/unix/sysv/linux/x86_64/cancellation.S: New file. + * sysdeps/unix/sysv/linux/x86_64/libc-cancellation.S: New file. + * sysdeps/unix/sysv/linux/x86_64/librt-cancellation.S: New file. + * sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h (PSEUDO): Optimize + since we can assume the special __*_{en,dis}able_asynccancel + functions. + (PUSHARGS_*, POPARGS_*, SAVESTK_*, RESTSTK_*): Removed. + * sysdeps/x86_64/tcb-offsets.sym: Add cancellation-related bits + and PTHREAD_CANCELED. + +2009-07-31 Ulrich Drepper + + * descr.h: Better definition of *_BITMASK macros for cancellation. + +2009-07-29 Ulrich Drepper + + * sysdeps/x86_64/tls.h (TLS_TCB_ALIGN): Define explicitly to 32. + + * sysdeps/x86_64/tls.h (tcbhead_t): Add room for SSE registers the + dynamic linker might have to save. + Define RTLD_CHECK_FOREIGN_CALL, RTLD_ENABLE_FOREIGN_CALL, + RTLD_PREPARE_FOREIGN_CALL, and RTLD_FINALIZE_FOREIGN_CALL. Pretty + printing. + + * sysdeps/x86_64/tcb-offsets.sym: Add RTLD_SAVESPACE_SSE. + +2009-07-28 Ulrich Drepper + + * pthread_mutex_lock.c [NO_INCR] (__pthread_mutex_cond_lock_adjust): + New function. + * pthreadP.h: Declare __pthread_mutex_cond_lock_adjust. + * sysdeps/unix/sysv/linux/pthread-pi-defines.sym: Add ROBUST_BIT. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S: Don't use + requeue_pi for robust mutexes. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S: Likewise. + Don't only skip __pthread_mutex_cond_lock. Call instead + __pthread_mutex_cond_lock_adjust. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S: Likewise. + + * pthread_mutex_unlock.c (__pthread_mutex_unlock_full): Minor + optimization of PI mutex handling. + +2009-07-27 Ulrich Drepper + + [BZ #10418] + * pthread_mutex_unlock.c (__pthread_mutex_unlock_full): Use _rel + instead of of _acq variants of cmpxchg. + +2009-07-23 Ulrich Drepper + + * sysdeps/x86_64/configure.in: New file. + + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S: Fix error + path when not using absolute timeout futex. + +2009-07-20 Ulrich Drepper + + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S: Minor + optimizations of last changes. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S: Likewise. + +2009-07-19 Ulrich Drepper + + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.h: Define + FUTEX_WAIT_REQUEUE_PI and FUTEX_CMP_REQUEUE_PI. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S: If mutex + is a PI mutex, then use FUTEX_CMP_REQUEUE_PI. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S: If mutex + is a PI mutex, then use FUTEX_WAIT_REQUEUE_PI. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S: Likewise. + + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S + (__pthread_cond_timedwait): Make more robust. + +2009-07-18 Ulrich Drepper + + * sysdeps/unix/sysv/linux/x86_64/lowlevelrobustlock.S + (__lll_robust_timedlock_wait): If possible use FUTEX_WAIT_BITSET to + directly use absolute timeout. + + * tst-sem5.c (do_test): Add test for premature timeout. + * Makefile: Linu tst-sem5 with librt. + + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedwrlock.S + (pthread_rwlock_timedwrlock): If possible use FUTEX_WAIT_BITSET to + directly use absolute timeout. + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedrdlock.S + (pthread_rwlock_timedrdlock): Likewise. + + * tst-cond11.c (run_test): Add test to check that the timeout is + long enough. + + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S + (__pthread_cond_timedwait): If possible use FUTEX_WAIT_BITSET to + directly use absolute timeout. + + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S + (__pthread_cond_wait): Convert to using exception handler instead of + registered unwind buffer. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S + (__pthread_cond_timedwait): Likewise. + +2009-07-17 Ulrich Drepper + + * sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S (sem_timedwait): + If possible use FUTEX_WAIT_BITSET|FUTEX_CLOCK_REALTIME to directly + use absolute timeout. + + * sysdeps/unix/sysv/linux/x86_64/sem_wait.S (sem_wait): Optimize + handling of uncontested semaphore. + + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S + (__condvar_cleanup): Rewrite to use cfi directives instead of + hand-coded unwind tables. + * sysdeps/unix/sysv/linux/x86_64/pthread_once.S (__pthread_once): + Likewise. + * sysdeps/unix/sysv/linux/x86_64/sem_wait.S (sem_wait): Likewise. + * sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S (sem_timedwait): + Likewise. + +2009-06-12 Ulrich Drepper + + * Makefile (libpthread-routines): Add pthread_sigqueue. + * Versions: Add pthread_sigqueue for GLIBC_2.11. + * sysdeps/pthread/bits/sigthread.h: Declare pthread_sigqueue. + * sysdeps/unix/sysv/linux/pthread_sigqueue.c: New file. + +2009-06-11 Ulrich Drepper + + [BZ #10262] + * sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S + (LOAD_FUTEX_WAIT_ABS): Fix futex parameter in case private futexes + cannot be assumed. + Patch by Bryan Kadzban . + +2009-05-16 Ulrich Drepper + + * libc-cancellation.c: Move __libc_cleanup_routine to... + * libc-cleanup.c: ...here. New file. + * Makefile (routines): Add libc-cleanup. + + * cancellation.c (__pthread_disable_asynccancel): Remove unnecessary + test. + * libc-cancellation.c: Use + + * cancellation.c (__pthread_disable_asynccancel): Correct the bits + to test when deciding on the delay. + * libc-cancellation.c (__libc_disable_asynccancel): Likewise. + * pthread_cancel.c: Close race between deciding on sending a signal + and setting the CANCELING_BIT bit. + + * cancellation.c (__pthread_disable_asynccancel): Don't return if + thread is canceled. + * libc-cancellation.c (__libc_disable_asynccancel): Likewise. + +2009-04-27 Ulrich Drepper + + * cancellation.c (__pthread_disable_asynccancel): Use THREAD_ATOMIC_AND + is available. + * libc-cancellation.c (__libc_disable_asynccancel): Likewise. + * sysdeps/x86_64/tls.h: Define THREAD_ATOMIC_AND. + * sysdeps/i386/tls.h: Likewise. + (tcbhead_t): Add __private_tm member. + +2009-04-26 Ulrich Drepper + + * sem_open.c (sem_open): Rewrite initialization of initsem to + avoid warnings. + + * sysdeps/unix/sysv/linux/libc_pthread_init.c (__libc_pthread_init): + Avoid warning by using may_alias attribute on ptrhack. + +2009-04-22 Ulrich Drepper + + [BZ #10090] + * pthread_attr_setschedparam.c (__pthread_attr_setschedparam): + Check policy and priority for validity. + Patch mostly by Zhang Xiliang . + +2009-03-15 Ulrich Drepper + + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S + (__pthread_cond_timedwait): Change to use cfi directives instead of + hand-coded unwind sections. + +2009-03-10 Ulrich Drepper + + * init.c (nptl_freeres): Compile only for SHARED. + +2009-03-09 Jakub Jelinek + + * sysdeps/unix/sysv/linux/sparc/lowlevellock.h: Define + FUTEX_WAIT_BITSET, FUTEX_WAKE_BITSET, FUTEX_CLOCK_REALTIME and + FUTEX_BITSET_MATCH_ANY. + +2009-02-27 Roland McGrath + + * init.c (__nptl_initial_report_events): Mark __attribute_used__. + * pthread_create.c (__nptl_threads_events, __nptl_last_event): Likewise. + +2009-02-26 Ulrich Drepper + + * sysdeps/unix/sysv/linux/bits/posix_opt.h: Define + _POSIX_THREAD_ROBUST_PRIO_INHERIT and + _POSIX_THREAD_ROBUST_PRIO_PROTECT. Reset value of macros from + 200112L to 200809L. + +2009-02-25 Ulrich Drepper + + * sysdeps/pthread/pthread.h: The robust mutex functions are in + POSIX 2008. + +2009-02-24 Ulrich Drepper + + * sysdeps/unix/sysv/linux/bits/posix_opt.h (_BITS_POSIX_OPT_H): + Unify name of include protector macro. + +2009-02-14 SUGIOKA Toshinobu + + * sysdeps/unix/sysv/linux/sh/lowlevellock.S: Define + LOAD_FUTEX_WAIT_ABS even if (FUTEX_WAIT == 0). + +2009-01-29 Ulrich Drepper + + * sysdeps/pthread/unwind-forcedunwind.c: Encrypt all function + pointer variables. + + * allocatestack.c (__free_stacks): Renamed from free_stacks. + (__free_stack_cache): Removed. Change callers to call __free_stacks. + * init.c (nptl_freeres): New function. + (pthread_functions): Initialize ptr_freeres to nptl_freeres. + * pthreadP.h: Don't declare __free_stack_cache. Declare __free_stacks. + * sysdeps/pthread/unwind-forcedunwind.c (libgcc_s_handle): New + variable. + (pthread_cancel_init): Depend in libgcc_s_handle for decision to + load DSO. Assign last. + (__unwind_freeres): New function. + + * allocatestack.c (__reclaim_stacks): Reset in_flight_stack later + for better debugging. No need to use stack_list_add here. + +2009-01-14 Kaz Kojima + + * sysdeps/unix/sysv/linux/sh/lowlevellock.S + (__lll_timedlock_wait): Use FUTEX_WAIT_BITSET|FUTEX_CLOCK_REALTIME + instead of computing relative timeout. + * sysdeps/unix/sysv/linux/sh/lowlevellock.h: Define + FUTEX_CLOCK_REALTIME and FUTEX_BITSET_MATCH_ANY. + +2009-01-25 Ulrich Drepper + + * pthread_mutex_lock.c (__pthread_mutex_lock): Remove unused label out. + +2009-01-08 Ulrich Drepper + + * sysdeps/pthread/list.h (list_add): Initialize new element first. + (list_add_tail): Removed. + +2009-01-07 Ulrich Drepper + + * (in_flight_stack): New variable. + (stack_list_del): New function. Use instead of list_del. + (stack_list_add): New function. Use instead of list_add when adding to + stack_cache and stack_used lists. + (__reclaim_stacks): Complete operations on stack_cache and stack_used lists + when the fork call interrupted another thread. + +2009-01-04 Ulrich Drepper + + * init.c (__pthread_initialize_minimal_internal): Optimize test + FUTEX_CLOCK_REALTIME a bit. + +2009-01-03 Ulrich Drepper + + * init.c (__pthread_initialize_minimal_internal): Cheat a bit by + only passing five parameters to FUTEX_WAIT_BITSET call. + + * sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S + (__lll_timedlock_wait): Use FUTEX_WAIT_BITSET|FUTEX_CLOCK_REALTIME + instead of computing relative timeout. + +2009-01-02 Ulrich Drepper + + * init.c (__pthread_initialize_minimal_internal): Check for + FUTEX_CLOCK_REALTIME flag. + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.S (__lll_timedlock_wait): + Use FUTEX_WAIT_BITSET|FUTEX_CLOCK_REALTIME instead of computing + relative timeout. + + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.h: Define + FUTEX_CLOCK_REALTIME and FUTEX_BITSET_MATCH_ANY. + * sysdeps/unix/sysv/linux/i386/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/ia64/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/powerpc/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/s390/lowlevellock.h: Likewise. + +2008-12-09 Ulrich Drepper + + * sysdeps/pthread/pthread.h (pthread_cleanup_pop): Use { } as empty + loop body instead of ; to avoid gcc warnings. + (pthread_cleanup_pop_restore_np): Likewise. + Patch by Caolán McNamara . + +2008-12-09 Jakub Jelinek + + * pthread_mutex_lock.c (__pthread_mutex_lock): Handle only the + fast path here, for robust/PI/PP mutexes call + __pthread_mutex_lock_full. Don't use switch, instead use a series + of ifs according to their probability. + (__pthread_mutex_lock_full): New function. + * pthread_mutex_unlock.c: Include assert.h. + (__pthread_mutex_unlock_usercnt): Handle only the + fast path here, for robust/PI/PP mutexes call + __pthread_mutex_unlock_full. Don't use switch, instead use a series + of ifs according to their probability. + (__pthread_mutex_unlock_full): New function. + * sysdeps/unix/sysv/linux/pthread_mutex_cond_lock.c + (__pthread_mutex_lock_full): Define. + +2008-12-08 Ulrich Drepper + + * sysdeps/x86_64/tls.h (tcbhead_t): Add fields reserved for TM + implementation. Add necessary padding and. + * descr.h (struct pthread): Increase padding for tcbhead_t to 24 + words. + +2008-12-04 Kaz Kojima + + * sysdeps/unix/sysv/linux/sh/lowlevellock.h: Define FUTEX_WAIT_BITSET + and FUTEX_WAKE_BITSET. + +2008-12-02 Ulrich Drepper + + * sysdeps/unix/sysv/linux/i386/lowlevellock.h: Define FUTEX_WAIT_BITSET + and FUTEX_WAKE_BITSET. + * sysdeps/unix/sysv/linux/ia64/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/powerpc/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/s390/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.h: Likewise. + +2008-11-25 Roland McGrath + + * sysdeps/alpha, sysdeps/unix/sysv/linux/alpha: + Subdirectories moved to ports repository as + sysdeps/.../nptl subdirectories. + +2008-11-12 Jakub Jelinek + + [BZ #7008] + * pthread_condattr_setclock.c (pthread_condattr_setclock): Fix masking + of old value. + * pthread_cond_init.c (__pthread_cond_init): Fix + cond->__data.__nwaiters initialization. + * Makefile (tests): Add tst-cond23. + * tst-cond23.c: New test. + +2008-11-07 Jakub Jelinek + + * sysdeps/pthread/malloc-machine.h (MALLOC): Adjust __libc_tsd_define + arguments. + (tsd_setspecific, tsd_getspecific): Adjust __libc_tsd_{set,get} + arguments. + +2008-11-01 Ulrich Drepper + + [BZ #6955] + * pthread_mutex_lock.c: Add support for private PI mutexes. + * pthread_mutex_timedlock.c: Likewise. + * pthread_mutex_trylock.c: Likewise. + * pthread_mutex_unlock.c: Likewise. + Patch mostly by Ben Jackson . + +2008-10-31 Ulrich Drepper + + [BZ #6843] + * sysdeps/pthread/gai_misc.h (__gai_create_helper_thread): + Increase stack size for helper thread. + +2008-10-06 Martin Schwidefsky + + * sysdeps/s390/tls.h (THREAD_SET_STACK_GUARD): Add empty inline + assembly with a clobber list for access registers a0 and a1. + +2008-09-11 Martin Schwidefsky + + * sysdeps/unix/sysv/linux/fork.c (__libc_fork): Add memory barrier + to force runp->refcntr to be read from memory. + +2008-09-08 Richard Guenther + + * sysdeps/unix/sysv/linux/i386/lowlevellock.h (lll_lock, + lll_robust_lock, lll_cond_lock, lll_robust_cond_lock, + lll_timedlock, lll_robust_timedlock, lll_unlock, + lll_robust_unlock): Promote private to int. + +2008-08-15 Ulrich Drepper + + * sysdeps/x86_64/pthreaddef.h: Remove ARCH_MAP_FLAGS and + ARCH_RETRY_MMAP definitions. + * allocatestack.c: Remove definition of ARCH_MAP_FLAGS. + Define MAP_STACK when not defined. + (allocate_stack): Use MAP_STACK instead of ARCH_MAP_FLAGS. Remove + handling of ARCH_RETRY_MMAP. + +2008-07-30 Ulrich Drepper + + * tst-align2.c (f): Print message that f is reached. + +2008-04-28 Hiroki Kaminaga + + [BZ #6740] + * sysdeps/powerpc/tcb-offsets.sym (PRIVATE_FUTEX_OFFSET): Guard symbol + definition with #ifndef __ASSUME_PRIVATE_FUTEX. + +2008-07-25 Ulrich Drepper + + * sysdeps/unix/sysv/linux/mq_notify.c (init_mq_netlink): Use + SOCK_CLOEXEC if possible. + +2008-05-29 Ulrich Drepper + + * Makefile (tests): Add tst-rwlock2a. + * tst-rwlock2.c: Use TYPE macro to decide what rwlock type to use. + * tst-rwlock2a.c: New file. + +2008-06-12 Ulrich Drepper + + * sysdeps/pthread/pthread.h: Remove inadvertant checkin. + +2008-05-17 Samuel Thibault + + * sysdeps/pthread/pthread.h: Fix typo in comment. + +2008-05-28 Ulrich Drepper + + * sysdeps/pthread/createthread.c (do_clone): Pass accurate length + of CPU set to the kernel. + +2008-05-23 Paul Pluzhnikov + + * sysdeps/unix/sysv/linux/i386/i486/pthread_barrier_wait.S: Add + cfi directives. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_signal.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_rdlock.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_unlock.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_wrlock.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/sem_post.S: Likewise. + +2008-05-22 Paul Pluzhnikov + + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedrdlock.S: Add + cfi directives. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedwrlock.S: + Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedrdlock.S: + Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedwrlock.S: + Likewise. + +2008-05-26 Ulrich Drepper + + * tst-typesizes.c: Explicitly check __SIZEOF_PTHREAD_* constants. + +2008-05-20 Jakub Jelinek + + David S. Miller + + * sysdeps/unix/sysv/linux/sparc/sparc64/Makefile: New file. + +2008-05-10 Ulrich Drepper + + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_rdlock.S: Access + __pshared correctly. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedrdlock.S: + Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedwrlock.S: + Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_unlock.S: + Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_wrlock.S: + Likewise. + Reported by Clemens Kolbitsch . + +2008-04-14 David S. Miller + + * sysdeps/unix/sysv/linux/sparc/sparc32/sem_wait.c + (__old_sem_wait): Fix argument to lll_futex_wait(). + +2007-11-26 Daniel Jacobowitz + + * pthread_create.c: Require pthread_mutex_trylock and + pthread_key_delete for libgcc. + +2008-04-08 Jakub Jelinek + + [BZ #6020] + * sysdeps/unix/sysv/linux/sparc/lowlevellock.h + (lll_futex_wake_unlock): Add private argument to the pre-v9 macro. + Patch by Sunil Amitkumar Janki . + +2008-03-27 Ulrich Drepper + + * sysdeps/unix/sysv/linux/bits/local_lim.h: Undefine ARG_MAX if + has defined it. + * sysdeps/unix/sysv/linux/alpha/bits/local_lim.h: Likewise. + * sysdeps/unix/sysv/linux/ia64/bits/local_lim.h: Likewise. + * sysdeps/unix/sysv/linux/powerpc/bits/local_lim.h: Likewise. + * sysdeps/unix/sysv/linux/sparc/bits/local_lim.h: Likewise. + +2008-03-18 Jakub Jelinek + + * sysdeps/unix/sysv/linux/ia64/dl-sysdep.h: Use __ASSEMBLER__ instead + of ASSEMBLER. + * sysdeps/unix/sysv/linux/i386/i686/dl-sysdep.h: Likewise. + * sysdeps/unix/sysv/linux/i386/dl-sysdep.h: Likewise. + +2008-03-14 Ulrich Drepper + + * sysdeps/unix/sysv/linux/i386/dl-sysdep.h: Define + HAVE_DL_DISCOVER_OSVERSION. + * sysdeps/unix/sysv/linux/i386/i686/dl-sysdep.h: Likewise. + * sysdeps/unix/sysv/linux/ia64/dl-sysdep.h: Likewise. + +2008-03-07 Ulrich Drepper + + [BZ #5778] + * sysdeps/unix/sysv/linux/bits/posix_opt.h: Change + _POSIX_CHOWN_RESTRICTED value to zero. + +2008-01-31 Roland McGrath + + * Makefile (omit-deps): Variable removed. + +2008-01-30 Ulrich Drepper + + * sysdeps/unix/sysv/linux/x86_64/sem_post.S (sem_post): Avoid + unnecessary addr32 prefix. + +2008-01-29 Roland McGrath + + * Makeconfig (ptw-CPPFLAGS, sysd-rules-patterns): New variables. + +2008-01-22 Kaz Kojima + + * sysdeps/unix/sysv/linux/sh/sem_post.S: Don't overflow value field. + +2008-01-21 Kaz Kojima + + * sysdeps/unix/sysv/linux/sh/lowlevel-atomic.h (XADD): Use + a scratch register. + * sysdeps/unix/sysv/linux/sh/lowlevellock.S + (__lll_lock_wait_private): Fix typo. + * sysdeps/unix/sysv/linux/sh/pthread_barrier_wait.S + (pthread_barrier_wait): Likewise. Adjust XADD use. + * sysdeps/unix/sysv/linux/sh/sem_post.S (__new_sem_post): + Adjust XADD use. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedrdlock.S + (pthread_rwlock_timedrdlock): Return correct return value. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedwrlock.S + (pthread_rwlock_timedwrlock): Likewise. + +2008-01-15 Ulrich Drepper + + * tst-eintr2.c (do_test): make sure that if mutex_lock in main + thread returns the program exits with an error code. + +2008-01-10 Ulrich Drepper + + * pthread-errnos.sym: Add EOVERFLOW. + * sysdeps/unix/sysv/linux/structsem.sym: Add SEM_VALUE_MAX. + * sysdeps/unix/sysv/linux/sem_post.c: Don't overflow value field. + * sysdeps/unix/sysv/linux/i386/i486/sem_post.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/sem_post.S: Likewise. + +2007-12-14 Ulrich Drepper + + * sysdeps/x86_64/pthreaddef.h (ARCH_RETRY_MMAP): Take additional + parameter. Passed it as permission to mmap. + * allocatestack.c (allocate_stack): Pass prot as second parameter + to ARCH_RETRY_MMAP. + +2007-12-12 Ulrich Drepper + + * tst-basic7.c: Allocate memory for the stack. + + [BZ #5465] + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S [!SHARED] + (__pthread_cond_timedwait): Don't use VDSO. + Patch by Michal Januszewski. + +2007-12-07 Ulrich Drepper + + [BZ #5455] + * sysdeps/pthread/pthread.h [!__EXCEPTIONS] (pthread_cleanup_pop): + Allow label before pthread_cleanup_pop. + (pthread_cleanup_pop_restore_np): Likewise. + +2007-12-04 Kaz Kojima + + * sysdeps/unix/sysv/linux/sh/lowlevellock.S (__lll_timedlock_wait): + Store 2 before returning ETIMEDOUT. + +2007-11-23 Ulrich Drepper + + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.S (__lll_timedlock_wait): + Store 2 before returning ETIMEDOUT. + * sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S: Likewise + * sysdeps/unix/sysv/linux/lowlevellock.c: Likewise. + (__lll_lock_wait_private): Optimize. + (__lll_lock_wait): Likewise. + +2007-11-20 Jakub Jelinek + + * sysdeps/pthread/pthread.h (pthread_cleanup_push, + pthread_cleanup_push_defer_np): Add extra (void *) cast to shut up + g++ 4.1 and 4.2 -Wstrict-aliasing warnings. + +2007-11-08 Ulrich Drepper + + [BZ #5240] + * sysdeps/unix/sysv/linux/lowlevellock.c (__lll_timedlock_wait): + If we time out, try one last time to lock the futex to avoid + losing a wakeup signal. + * sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.S: Likewise. + + [BZ #5245] + * sysdeps/pthread/createthread.c (do_clone): Translate clone error + if necessary. + +2007-11-07 Ulrich Drepper + + [BZ #5245] + * allocatestack.c (allocate_stack): Change ENOMEM error in case + mmap failed to EAGAIN. + * Makefile (tests): Add tst-basic7. + * tst-basic7.c: New file. + +2007-11-05 Ulrich Drepper + + * sysdeps/unix/sysv/linux/register-atfork.c (__register_atfork): + Use __linkin_atfork. + +2007-11-03 Mike Frysinger + + * sysdeps/unix/sysv/linux/sh/lowlevellock.S (LOAD_FUTEX_WAIT): Add + missing line continuations. + * sysdeps/unix/sysv/linux/sh/lowlevelrobustlock.S (LOAD_FUTEX_WAIT, + LOAD_FUTEX_WAKE): Likewise. Also add missing 3rd parameter. + +2007-10-28 Ulrich Drepper + + [BZ #5220] + * sysdeps/unix/sysv/linux/kernel-posix-timers.h: Declare + __active_timer_sigev_thread and __active_timer_sigev_thread_lock. + (struct timer): Add next element. + * sysdeps/unix/sysv/linux/timer_create.c: For SIGEV_THREAD timers, + enqueue timer structure into __active_timer_sigev_thread list. + * sysdeps/unix/sysv/linux/timer_delete.c: For SIGEV_THREAD timers, + remove timer struct from __active_timer_sigev_thread. + * sysdeps/unix/sysv/linux/timer_routines.c (timer_helper_thread): + Before using timer structure make sure it is still on the + __active_timer_sigev_thread list. Keep lock until done. + Define __active_timer_sigev_thread and + __active_timer_sigev_thread_lock. + +2007-10-27 Ulrich Drepper + + * sysdeps/pthread/malloc-machine.h: Define ATFORK_MEM. + Redefine thread_atfork for use of ATFORK_MEM. + * sysdeps/unix/sysv/linux/fork.h: Define __linkin_atfork. + * sysdeps/unix/sysv/linux/register-atfork.c (__linkin_atfork): New + function. + * sysdeps/unix/sysv/linux/unregister-atfork.c (__unregister_atfork): + Use atomic operation when removing first element of list. + +2007-10-17 Jakub Jelinek + + * sysdeps/unix/sysv/linux/i386/i486/sem_post.S (__old_sem_post): New + routine instead of an alias to __new_sem_post. + +2007-10-15 Jakub Jelinek + + * init.c (__pthread_initialize_minimal): Initialize word to appease + valgrind. + +2007-10-10 Jakub Jelinek + + * sysdeps/pthread/bits/libc-lock.h (__libc_rwlock_init): Inside of + libc.so just clear NAME. + (__libc_rwlock_fini): Nop inside of libc.so. + * tst-initializers1.c (main): Test if PTHREAD_RWLOCK_INITIALIZER is + all zeros. + +2007-09-02 Ulrich Drepper + + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S + (__pthread_cond_wait): Fix unlocking of internal lock after mutex + unlocking failed. + Patch by Luca Barbieri . + +2007-08-21 Ulrich Drepper + + [BZ #4938] + * allocatestack.c (__reclaim_stacks): Clear the TSD in the + reclaimed stack if necessary. + * Makefile (tests): Add tst-tsd6. + * tst-tsd6.c: New file. + +2007-08-21 Jakub Jelinek + + * sysdeps/unix/sysv/linux/alpha/lowlevellock.h (lll_robust_dead): + Add private argument. + +2007-08-20 Ulrich Drepper + + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S + (__pthread_cond_timedwait): Use clock_gettime from VDSO if possible. + +2007-08-16 Jakub Jelinek + + * sysdeps/unix/sysv/linux/alpha/lowlevellock.h + (__lll_robust_timedlock): Pass private as last argument to + __lll_robust_timedlock_wait. + (__lll_unlock): Fix a pasto. + +2007-08-15 Jakub Jelinek + + * sysdeps/unix/sysv/linux/sparc/internaltypes.h (sparc_new_sem, + sparc_old_sem): New structs. + * sysdeps/unix/sysv/linux/sparc/sparc32/sem_wait.c + (__sem_wait_cleanup): New function. + (__new_sem_wait): Use sparc_new_sem structure. Bump and afterwards + decrease nwaiters. Register __sem_wait_cleanup as cleanup handler. + Pass isem->private ^ FUTEX_PRIVATE_FLAG as last argument to + lll_futex_wait. + (__old_sem_wait): New function. + * sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_wait.c: Include + nptl/sysdeps/unix/sysv/linux/sparc version. + * sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_timedwait.c: + Likewise. + * sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_post.c: Likewise. + * sysdeps/unix/sysv/linux/sparc/sparc32/sem_trywait.c + (__new_sem_trywait): Use sparc_old_sem structure. + * sysdeps/unix/sysv/linux/sparc/sparc32/sem_timedwait.c + (sem_timedwait): Use sparc_new_sem structure. Bump and afterwards + decrease nwaiters. Register __sem_wait_cleanup as cleanup handler. + Pass isem->private ^ FUTEX_PRIVATE_FLAG as last argument to + lll_futex_timed_wait. + * sysdeps/unix/sysv/linux/sparc/sparc32/sem_post.c (__new_sem_post): + Use sparc_new_sem structure. Only wake if nwaiters > 0. Pass + isem->private ^ FUTEX_PRIVATE_FLAG as last argument to + lll_futex_wake. + (__old_sem_post): New function. + * sysdeps/unix/sysv/linux/sparc/sem_wait.c: New file. + * sysdeps/unix/sysv/linux/sparc/sem_init.c: New file. + * sysdeps/unix/sysv/linux/sparc/sem_timedwait.c: New file. + * sysdeps/unix/sysv/linux/sparc/sem_post.c: New file. + * sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_init.c: Remove. + * sysdeps/unix/sysv/linux/sparc/sparc32/sem_init.c: Remove. + +2007-08-14 Kaz Kojima + + * sysdeps/unix/sysv/linux/sh/pthread_cond_broadcast.S + (__pthread_cond_broadcast): Pass LLL_PRIVATE to lll_* and or + FUTEX_PRIVATE_FLAG into SYS_futex op if cv is process private. + Don't use FUTEX_CMP_REQUEUE if dep_mutex is not process private. + * sysdeps/unix/sysv/linux/shpthread_cond_signal.S + (__pthread_cond_signal): Pass LLL_PRIVATE to lll_* and or + FUTEX_PRIVATE_FLAG into SYS_futex op if cv is process private. + Use FUTEX_WAKE_OP. + * sysdeps/unix/sysv/linux/sh/pthread_cond_wait.S: Include + kernel-features.h and tcb-offsets.h. + (__pthread_cond_wait, __condvar_w_cleanup): Pass LLL_PRIVATE to + lll_* and or FUTEX_PRIVATE_FLAG into SYS_futex op if cv is + process private. + * sysdeps/unix/sysv/linux/sh/pthread_cond_timedwait.S: Include + tcb-offsets.h. + (__pthread_cond_timedwait, __condvar_tw_cleanup): Pass LLL_PRIVATE + to lll_* and or FUTEX_PRIVATE_FLAG into SYS_futex op if cv is + process private. + * sysdeps/unix/sysv/linux/sh/pthread_once.S: Use #ifdef + __ASSUME_PRIVATE_FUTEX instead of #if __ASSUME_PRIVATE_FUTEX. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_rdlock.S: Likewise. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedrdlock.S: Likewise. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedwrlock.S: Likewise. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_unlock.S: Likewise. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_wrlock.S: Likewise. + +2007-08-14 Jakub Jelinek + + * sysdeps/unix/sysv/linux/lowlevellock.c: Comment fix. + * sysdeps/unix/sysv/linux/sparc/sparc32/lowlevellock.c + (__lll_timedwait_tid): Pass LLL_SHARED as 4th argument to + lll_futex_timed_wait. + + * sysdeps/unix/sysv/linux/alpha/lowlevellock.h (__lll_unlock, + __lll_robust_unlock): Rewrite as macros instead of inline functions. + * sysdeps/unix/sysv/linux/s390/lowlevellock.h (__lll_unlock, + __lll_robust_unlock, __lll_wait_tid): Likewise. + +2007-08-13 Jakub Jelinek + + * sysdeps/unix/sysv/linux/i386/lowlevellock.h (__lll_private_flag): + Fix a pasto. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.S + (__pthread_cond_broadcast): Pass LLL_PRIVATE to lll_* and or + FUTEX_PRIVATE_FLAG into SYS_futex op if cv is process private. + Don't use FUTEX_CMP_REQUEUE if dep_mutex is not process private. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_signal.S + (__pthread_cond_signal): Pass LLL_PRIVATE to lll_* and or + FUTEX_PRIVATE_FLAG into SYS_futex op if cv is process private. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S: Include + kernel-features.h. + (__pthread_cond_wait, __condvar_w_cleanup): Pass LLL_PRIVATE to + lll_* and or FUTEX_PRIVATE_FLAG into SYS_futex op if cv is + process private. Switch DW_CFA_advance_loc1 and some + DW_CFA_advance_loc .eh_frame opcodes to DW_CFA_advance_loc4. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S + (__pthread_cond_timedwait, __condvar_tw_cleanup): Pass LLL_PRIVATE to + lll_* and or FUTEX_PRIVATE_FLAG into SYS_futex op if cv is + process private. Switch DW_CFA_advance_loc{1,2} and some + DW_CFA_advance_loc .eh_frame opcodes to DW_CFA_advance_loc4. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_rdlock.S: Use + #ifdef __ASSUME_PRIVATE_FUTEX instead of #if __ASSUME_PRIVATE_FUTEX. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedwrlock.S: + Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_unlock.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_wrlock.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedrdlock.S: + Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S + (__pthread_cond_broadcast): Compare %r8 instead of + dep_mutex-cond_*(%rdi) with $-1. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.S + (__pthread_cond_signal): Xor FUTEX_WAKE_OP with FUTEX_WAKE instead + of oring. + +2007-08-13 Ulrich Drepper + + * sysdeps/unix/sysv/linux/i386/i786/Implies: New file. + +2007-08-13 Jakub Jelinek + + * allocatestack.c: Include kernel-features.h. + * pthread_create.c: Likewise. + * pthread_mutex_init.c: Likewise. + * init.c: Likewise. + * pthread_cond_timedwait.c: Likewise. + * sysdeps/unix/sysv/linux/alpha/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/ia64/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_wrlock.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_rdlock.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_unlock.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedwrlock.S: + Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedrdlock.S: + Likewise. + * sysdeps/unix/sysv/linux/s390/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/powerpc/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/sparc/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/sh/pthread_cond_timedwait.S: Likewise. + +2007-08-12 Jakub Jelinek + + * sysdeps/unix/sysv/linux/sparc/bits/pthreadtypes.h + [__WORDSIZE=32] (pthread_rwlock_t): Split __flags element into four + byte elements. One of them is the new __shared element. + [__WORDSIZE=64] (pthread_rwlock_t): Renamed __pad1 element to __shared, + adjust names of other padding elements. + * sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h + [__WORDSIZE=32] (pthread_rwlock_t): Split __flags element into four + byte elements. One of them is the new __shared element. + [__WORDSIZE=64] (pthread_rwlock_t): Renamed __pad1 element to __shared, + adjust names of other padding elements. + * sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h (pthread_rwlock_t): + Renamed __pad1 element to __shared, adjust names of other padding + elements. + * sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h + (pthread_rwlock_t): Likewise. + * sysdeps/unix/sysv/linux/ia64/lowlevellock.h (__lll_lock): Fix a + typo. + +2007-08-09 Anton Blanchard + + * sysdeps/unix/sysv/linux/powerpc/pthread_spin_unlock.c: New file. + +2007-08-12 Ulrich Drepper + + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S: Include + . + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S: Likewise. + +2007-08-11 Ulrich Drepper + + * pthreadP.h (PTHREAD_ROBUST_MUTEX_PSHARED): Define. + * pthread_mutex_lock.c: Use it instead of PTHREAD_MUTEX_PSHARED when + dealing with robust mutexes. + * pthread_mutex_timedlock.c: Likewise. + * pthread_mutex_trylock.c: Likewise. + * pthread_mutex_unlock.c: Likewise. + * sysdeps/unix/sysv/linux/pthread_mutex_cond_lock.c: Likewise. + +2007-08-06 Jakub Jelinek + + * pthreadP.h (PTHREAD_MUTEX_PSHARED_BIT): Define. + (PTHREAD_MUTEX_TYPE): Mask __kind with 127. + (PTHREAD_MUTEX_PSHARED): Define. + * pthread_mutex_init.c (__pthread_mutex_init): Set + PTHREAD_MUTEX_PSHARED_BIT for pshared or robust + mutexes. + * pthread_mutex_lock.c (LLL_MUTEX_LOCK): Take mutex as argument + instead of its __data.__lock field, pass PTHREAD_MUTEX_PSHARED + as second argument to lll_lock. + (LLL_MUTEX_TRYLOCK): Take mutex as argument + instead of its __data.__lock field. + (LLL_ROBUST_MUTEX_LOCK): Take mutex as argument instead of its + __data.__lock field, pass PTHREAD_MUTEX_PSHARED as second argument + to lll_robust_lock. + (__pthread_mutex_lock): Update LLL_MUTEX_LOCK, LLL_MUTEX_TRYLOCK, + LLL_ROBUST_MUTEX_LOCK users, use PTHREAD_MUTEX_TYPE (mutex) + instead of mutex->__data.__kind directly, pass + PTHREAD_MUTEX_PSHARED (mutex) to lll_unlock and lll_futex_wait. + * pthread_mutex_trylock.c (__pthread_mutex_trylock): Use + PTHREAD_MUTEX_TYPE (mutex) instead of mutex->__data.__kind + directly, pass PTHREAD_MUTEX_PSHARED (mutex) to lll_unlock. + (pthread_mutex_timedlock): Pass PTHREAD_MUTEX_PSHARED (mutex) + to lll_timedlock, lll_robust_timedlock, lll_unlock and + lll_futex_timed_wait. Use PTHREAD_MUTEX_TYPE (mutex) instead + of mutex->__data.__kind directly. + * pthread_mutex_timedlock.c (pthread_mutex_timedlock): Pass + PTHREAD_MUTEX_PSHARED (mutex) to lll_timedlock, + lll_robust_timedlock, lll_unlock and lll_futex_timed_wait. Use + PTHREAD_MUTEX_TYPE (mutex) instead of mutex->__data.__kind directly. + * pthread_mutex_unlock.c (__pthread_mutex_unlock_usercnt): Pass + PTHREAD_MUTEX_PSHARED (mutex) to lll_unlock, lll_robust_unlock + and lll_futex_wake. + * pthread_mutex_setprioceiling.c (pthread_mutex_setprioceiling): Pass + PTHREAD_MUTEX_PSHARED (mutex) to lll_futex_wait and lll_futex_wake. + Use PTHREAD_MUTEX_TYPE (mutex) instead of mutex->__data.__kind + directly. + * sysdeps/unix/sysv/linux/pthread_mutex_cond_lock.c (LLL_MUTEX_LOCK): + Take mutex as argument instead of its __data.__lock field, pass + PTHREAD_MUTEX_PSHARED as second argument to lll_cond_lock. + (LLL_MUTEX_TRYLOCK): Take mutex as argument instead of its + __data.__lock field. + (LLL_ROBUST_MUTEX_LOCK): Take mutex as argument instead of its + __data.__lock field, pass PTHREAD_MUTEX_PSHARED as second argument + to lll_robust_cond_lock. + * pthread_cond_broadcast.c (__pthread_cond_broadcast): Add pshared + variable, pass it to lll_lock, lll_unlock, lll_futex_requeue and + lll_futex_wake. Don't use lll_futex_requeue if dependent mutex + has PTHREAD_MUTEX_PSHARED_BIT bit set in its __data.__kind. + * pthread_cond_destroy.c (__pthread_cond_destroy): Add pshared + variable, pass it to lll_lock, lll_unlock, lll_futex_wake and + lll_futex_wait. + * pthread_cond_signal.c (__pthread_cond_signal): Add pshared + variable, pass it to lll_lock, lll_unlock, lll_futex_wake_unlock and + lll_futex_wake. + * pthread_cond_timedwait.c (__pthread_cond_wait): Add + pshared variable, pass it to lll_lock, lll_unlock, + lll_futex_timedwait and lll_futex_wake. + * pthread_cond_wait.c (__condvar_cleanup, __pthread_cond_wait): Add + pshared variable, pass it to lll_lock, lll_unlock, lll_futex_wait + and lll_futex_wake. + * sysdeps/unix/sysv/linux/alpha/lowlevellock.h (lll_futex_requeue, + lll_futex_wake_unlock): Add private argument, use __lll_private_flag + macro. + * sysdeps/unix/sysv/linux/ia64/lowlevellock.h (lll_futex_requeue, + lll_futex_wake_unlock): Likewise. + * sysdeps/unix/sysv/linux/powerpc/lowlevellock.h (lll_futex_requeue): + Likewise. + * sysdeps/unix/sysv/linux/sparc/lowlevellock.h (lll_futex_requeue, + lll_futex_wake_unlock): Likewise. + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.h (lll_futex_requeue): + Likewise. + * sysdeps/unix/sysv/linux/s390/lowlevellock.h (lll_futex_requeue, + lll_futex_wake_unlock): Likewise. + (lll_futex_wake): Fix a typo. + * sysdeps/unix/sysv/linux/pthread-pi-defines.sym (PS_BIT): Add. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S + (__pthread_cond_broadcast): Pass LLL_PRIVATE to lll_* and or + FUTEX_PRIVATE_FLAG into SYS_futex op if cv is process private. + Don't use FUTEX_CMP_REQUEUE if dep_mutex is not process private. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.S + (__pthread_cond_signal): Pass LLL_PRIVATE to lll_* and or + FUTEX_PRIVATE_FLAG into SYS_futex op if cv is process private. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S + (__pthread_cond_timedwait): Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S: + (__condvar_cleanup, __pthread_cond_wait): Likewise. + +2007-08-05 Jakub Jelinek + + * sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h (PSEUDO): + Don't use CGOTSETUP and CGOTRESTORE macros. + (CGOTSETUP, CGOTRESTORE): Remove. + (CENABLE, CDISABLE): Don't use JUMPTARGET, branch to + @local symbol. + +2007-08-01 Kaz Kojima + + * sysdeps/unix/sysv/linux/sh/libc-lowlevellock.S: Remove + definitions for private futexes. + * sysdeps/unix/sysv/linux/sh/lowlevellock.S: Include + kernel-features.h and lowlevellock.h. Use private futexes if + they are available. + (__lll_lock_wait_private, __lll_unlock_wake_private): New. + (__lll_mutex_lock_wait): Rename to + (__lll_lock_wait): ... this. Don't compile in for libc.so. + (__lll_mutex_timedlock_wait): Rename to ... + (__lll_timedlock_wait): ... this. Use __NR_gettimeofday. + Don't compile in for libc.so. + (__lll_mutex_unlock_wake): Rename to ... + (__lll_unlock_wake): ... this. Don't compile in for libc.so. + (__lll_timedwait_tid): Use __NR_gettimeofday. + * sysdeps/unix/sysv/linux/sh/lowlevellock.h: Allow including + the header from assembler. Renamed all lll_mutex_* resp. + lll_robust_mutex_* macros to lll_* resp. lll_robust_*. + Renamed all LLL_MUTEX_LOCK_* macros to LLL_LOCK_*. + (FUTEX_CMP_REQUEUE, FUTEX_WAKE_OP, FUTEX_OP_CLEAR_WAKE_IF_GT_ONE): + Define. + (__lll_lock_wait_private): Add prototype. + (__lll_lock_wait, __lll_timedlock_wait, __lll_robust_lock_wait, + __lll_robust_timedlock_wait, __lll_unlock_wake_private, + __lll_unlock_wake): Likewise. + (lll_lock): Add private argument. Call __lll_lock_wait_private + if private is constant LLL_PRIVATE. + (lll_robust_lock, lll_cond_lock, lll_robust_cond_lock, + lll_timedlock, lll_robust_timedlock): Add private argument. + (lll_unlock): Add private argument. Call __lll_unlock_wake_private + if private is constant LLL_PRIVATE. + (lll_robust_unlock, lll_robust_dead): Add private argument. + (lll_lock_t): Remove. + (__lll_cond_wait, __lll_cond_timedwait, __lll_cond_wake, + __lll_cond_broadcast, lll_cond_wait, lll_cond_timedwait, + lll_cond_wake, lll_cond_broadcast): Remove. + * sysdeps/unix/sysv/linux/sh/lowlevelrobustlock.S: Include + kernel-features.h and lowlevellock.h. + (SYS_gettimeofday, SYS_futex, FUTEX_WAIT, FUTEX_WAKE): Remove. + (LOAD_FUTEX_WAIT): Define. + (__lll_robust_mutex_lock_wait): Rename to ... + (__lll_robust_lock_wait): ... this. Add private argument. + Use LOAD_FUTEX_WAIT macro. + (__lll_robust_mutex_timedlock_wait): Rename to ... + (__lll_robust_timedlock_wait): ... this. Add private argument. + Use __NR_gettimeofday. Use LOAD_FUTEX_WAIT macro. + * sysdeps/unix/sysv/linux/sh/pthread_barrier_wait.S: Include + lowlevellock.h. + (SYS_futex, FUTEX_WAIT, FUTEX_WAKE): Remove. + (pthread_barrier_wait): Use __lll_{lock,unlock}_* instead of + __lll_mutex_{lock,unlock}_*. + * sysdeps/unix/sysv/linux/sh/pthread_cond_broadcast.S: Include + lowlevellock.h and pthread-errnos.h. + (SYS_futex, FUTEX_WAIT, FUTEX_WAKE, FUTEX_REQUEUE, + FUTEX_CMP_REQUEUE, EINVAL): Remove. + (__pthread_cond_broadcast): Use __lll_{lock,unlock}_* instead of + __lll_mutex_{lock,unlock}_*. + * sysdeps/unix/sysv/linux/sh/pthread_cond_signal.S: Include + lowlevellock.h and pthread-errnos.h. + (SYS_futex, FUTEX_WAIT, FUTEX_WAKE, FUTEX_REQUEUE, EINVAL): Remove. + (__pthread_cond_signal): Use __lll_{lock,unlock}_* instead of + __lll_mutex_{lock,unlock}_*. + * sysdeps/unix/sysv/linux/sh/pthread_cond_timedwait.S: Include + lowlevellock.h. + (SYS_futex, SYS_gettimeofday, FUTEX_WAIT, FUTEX_WAKE): Remove. + (__pthread_cond_timedwait): Use __lll_{lock,unlock}_* instead of + __lll_mutex_{lock,unlock}_*. Use __NR_gettimeofday. + (__condvar_tw_cleanup): Likewise. + * sysdeps/unix/sysv/linux/sh/pthread_cond_wait.S: Include + lowlevellock.h. + (SYS_futex, FUTEX_WAIT, FUTEX_WAKE): Remove. + (__pthread_cond_wait): Use __lll_{lock,unlock}_* instead of + __lll_mutex_{lock,unlock}_*. + ( __condvar_w_cleanup): Likewise. + * sysdeps/unix/sysv/linux/sh/pthread_once.S: Include lowlevellock.h. + (SYS_futex, FUTEX_WAIT, FUTEX_WAKE, FUTEX_PRIVATE_FLAG): Remove. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_rdlock.S: Include + lowlevellock.h. + (SYS_futex, FUTEX_WAIT, FUTEX_WAKE, FUTEX_PRIVATE_FLAG): Remove. + (__pthread_rwlock_rdlock): Use __lll_{lock,unlock}_* instead of + __lll_mutex_{lock,unlock}_*. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedrdlock.S: Include + lowlevellock.h. + (SYS_gettimeofday, SYS_futex, FUTEX_WAIT, FUTEX_WAKE, + FUTEX_PRIVATE_FLAG): Remove. + (pthread_rwlock_timedrdlock): Use __lll_{lock,unlock}_* instead of + __lll_mutex_{lock,unlock}_*. Use __NR_gettimeofday. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedwrlock.S: Include + lowlevellock.h. + (SYS_gettimeofday, SYS_futex, FUTEX_WAIT, FUTEX_WAKE, + FUTEX_PRIVATE_FLAG): Remove. + (pthread_rwlock_timedwrlock): Use __lll_{lock,unlock}_* instead of + __lll_mutex_{lock,unlock}_*. Use __NR_gettimeofday. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_unlock.S: Include + lowlevellock.h. + (SYS_futex, FUTEX_WAIT, FUTEX_WAKE, FUTEX_PRIVATE_FLAG): Remove. + (__pthread_rwlock_unlock): Use __lll_{lock,unlock}_* instead of + __lll_mutex_{lock,unlock}_*. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_wrlock.S: Include + lowlevellock.h. + (SYS_futex, FUTEX_WAIT, FUTEX_WAKE, FUTEX_PRIVATE_FLAG): Remove. + (__pthread_rwlock_wrlock): Use __lll_{lock,unlock}_* instead of + __lll_mutex_{lock,unlock}_*. + * sysdeps/unix/sysv/linux/sh/sem_post.S: Include lowlevellock.h. + (SYS_futex, FUTEX_WAIT, FUTEX_WAKE, FUTEX_PRIVATE_FLAG): Remove. + (__new_sem_post): Use standard initial exec code sequences. + * sysdeps/unix/sysv/linux/sh/sem_timedwait.S: Include + lowlevellock.h. + (SYS_gettimeofday, SYS_futex, FUTEX_WAIT, FUTEX_WAKE, + FUTEX_PRIVATE_FLAG): Remove. + (sem_timedwait): Use __NR_gettimeofday. Use standard initial + exec code sequences. + * sysdeps/unix/sysv/linux/sh/sem_trywait.S: Include lowlevellock.h. + (__new_sem_trywait): Use standard initial exec code sequences. + * sysdeps/unix/sysv/linux/sh/sem_wait.S: Include lowlevellock.h. + (__new_sem_wait): Use standard initial exec code sequences. + +2007-07-31 Anton Blanchard + + * sysdeps/unix/sysv/linux/powerpc/sem_post.c (__new_sem_post): + Use __asm __volatile (__lll_acq_instr ::: "memory") instead of + atomic_full_barrier. + +2007-07-31 Jakub Jelinek + + * allocatestack.c (stack_cache_lock): Change type to int. + (get_cached_stack, allocate_stack, __deallocate_stack, + __make_stacks_executable, __find_thread_by_id, __nptl_setxid, + __pthread_init_static_tls, __wait_lookup_done): Add LLL_PRIVATE + as second argument to lll_lock and lll_unlock macros on + stack_cache_lock. + * pthread_create.c (__find_in_stack_list): Likewise. + (start_thread): Similarly with pd->lock. Use lll_robust_dead + macro instead of lll_robust_mutex_dead, pass LLL_SHARED to it + as second argument. + * descr.h (struct pthread): Change lock and setxid_futex field + type to int. + * old_pthread_cond_broadcast.c (__pthread_cond_broadcast_2_0): Use + LLL_LOCK_INITIALIZER instead of LLL_MUTEX_LOCK_INITIALIZER. + * old_pthread_cond_signal.c (__pthread_cond_signal_2_0): Likewise. + * old_pthread_cond_timedwait.c (__pthread_cond_timedwait_2_0): + Likewise. + * old_pthread_cond_wait.c (__pthread_cond_wait_2_0): Likewise. + * pthread_cond_init.c (__pthread_cond_init): Likewise. + * pthreadP.h (__attr_list_lock): Change type to int. + * pthread_attr_init.c (__attr_list_lock): Likewise. + * pthread_barrier_destroy.c (pthread_barrier_destroy): Pass + ibarrier->private ^ FUTEX_PRIVATE_FLAG as second argument to + lll_{,un}lock. + * pthread_barrier_wait.c (pthread_barrier_wait): Likewise and + also for lll_futex_{wake,wait}. + * pthread_barrier_init.c (pthread_barrier_init): Make iattr + a pointer to const. + * pthread_cond_broadcast.c (__pthread_cond_broadcast): Pass + LLL_SHARED as second argument to lll_{,un}lock. + * pthread_cond_destroy.c (__pthread_cond_destroy): Likewise. + * pthread_cond_signal.c (__pthread_cond_singal): Likewise. + * pthread_cond_timedwait.c (__pthread_cond_timedwait): Likewise. + * pthread_cond_wait.c (__condvar_cleanup, __pthread_cond_wait): + Likewise. + * pthread_getattr_np.c (pthread_getattr_np): Add LLL_PRIVATE + as second argument to lll_{,un}lock macros on pd->lock. + * pthread_getschedparam.c (__pthread_getschedparam): Likewise. + * pthread_setschedparam.c (__pthread_setschedparam): Likewise. + * pthread_setschedprio.c (pthread_setschedprio): Likewise. + * tpp.c (__pthread_tpp_change_priority, __pthread_current_priority): + Likewise. + * sysdeps/pthread/createthread.c (do_clone, create_thread): + Likewise. + * pthread_once.c (once_lock): Change type to int. + (__pthread_once): Pass LLL_PRIVATE as second argument to + lll_{,un}lock macros on once_lock. + * pthread_rwlock_rdlock.c (__pthread_rwlock_rdlock): Use + lll_{,un}lock macros instead of lll_mutex_{,un}lock, pass + rwlock->__data.__shared as second argument to them and similarly + for lll_futex_w*. + * pthread_rwlock_timedrdlock.c (pthread_rwlock_timedrdlock): + Likewise. + * pthread_rwlock_timedwrlock.c (pthread_rwlock_timedwrlock): + Likewise. + * pthread_rwlock_tryrdlock.c (__pthread_rwlock_tryrdlock): Likewise. + * pthread_rwlock_trywrlock.c (__pthread_rwlock_trywrlock): Likewise. + * pthread_rwlock_unlock.c (__pthread_rwlock_unlock): Likewise. + * pthread_rwlock_wrlock.c (__pthread_rwlock_wrlock): Likewise. + * sem_close.c (sem_close): Pass LLL_PRIVATE as second argument + to lll_{,un}lock macros on __sem_mappings_lock. + * sem_open.c (check_add_mapping): Likewise. + (__sem_mappings_lock): Change type to int. + * semaphoreP.h (__sem_mappings_lock): Likewise. + * pthread_mutex_lock.c (LLL_MUTEX_LOCK, LLL_MUTEX_TRYLOCK, + LLL_ROBUST_MUTEX_LOCK): Use lll_{,try,robust_}lock macros + instead of lll_*mutex_*, pass LLL_SHARED as last + argument. + (__pthread_mutex_lock): Use lll_unlock instead of lll_mutex_unlock, + pass LLL_SHARED as last argument. + * sysdeps/unix/sysv/linux/pthread_mutex_cond_lock.c (LLL_MUTEX_LOCK, + LLL_MUTEX_TRYLOCK, LLL_ROBUST_MUTEX_LOCK): Use + lll_{cond_,cond_try,robust_cond}lock macros instead of lll_*mutex_*, + pass LLL_SHARED as last argument. + * pthread_mutex_timedlock.c (pthread_mutex_timedlock): Use + lll_{timed,try,robust_timed,un}lock instead of lll_*mutex*, pass + LLL_SHARED as last argument. + * pthread_mutex_trylock.c (__pthread_mutex_trylock): Similarly. + * pthread_mutex_unlock.c (__pthread_mutex_unlock_usercnt): + Similarly. + * sysdeps/pthread/bits/libc-lock.h (__libc_lock_lock, + __libc_lock_lock_recursive, __libc_lock_unlock, + __libc_lock_unlock_recursive): Pass LLL_PRIVATE as second + argument to lll_{,un}lock. + * sysdeps/pthread/bits/stdio-lock.h (_IO_lock_lock, + _IO_lock_unlock): Likewise. + * sysdeps/unix/sysv/linux/fork.c (__libc_fork): Don't use + compound literal. + * sysdeps/unix/sysv/linux/unregister-atfork.c (__unregister_atfork): + Pass LLL_PRIVATE as second argument to lll_{,un}lock macros on + __fork_lock. + * sysdeps/unix/sysv/linux/register-atfork.c (__register_atfork, + free_mem): Likewise. + (__fork_lock): Change type to int. + * sysdeps/unix/sysv/linux/fork.h (__fork_lock): Likewise. + * sysdeps/unix/sysv/linux/sem_post.c (__new_sem_post): Pass + isem->private ^ FUTEX_PRIVATE_FLAG as second argument to + lll_futex_wake. + * sysdeps/unix/sysv/linux/sem_timedwait.c (sem_timedwait): Likewise. + * sysdeps/unix/sysv/linux/sem_wait.c (__new_sem_wait): Likewise. + * sysdeps/unix/sysv/linux/lowlevellock.c (__lll_lock_wait_private): + New function. + (__lll_lock_wait, __lll_timedlock_wait): Add private argument and + pass it through to lll_futex_*wait, only compile in when + IS_IN_libpthread. + * sysdeps/unix/sysv/linux/lowlevelrobustlock.c + (__lll_robust_lock_wait, __lll_robust_timedlock_wait): Add private + argument and pass it through to lll_futex_*wait. + * sysdeps/unix/sysv/linux/alpha/lowlevellock.h: Renamed all + lll_mutex_* resp. lll_robust_mutex_* macros to lll_* resp. + lll_robust_*. Renamed all __lll_mutex_* resp. __lll_robust_mutex_* + inline functions to __lll_* resp. __lll_robust_*. + (LLL_MUTEX_LOCK_INITIALIZER): Remove. + (lll_mutex_dead): Add private argument. + (__lll_lock_wait_private): New prototype. + (__lll_lock_wait, __lll_robust_lock_wait, __lll_lock_timedwait, + __lll_robust_lock_timedwait): Add private argument to prototypes. + (__lll_lock): Add private argument, if it is constant LLL_PRIVATE, + call __lll_lock_wait_private, otherwise pass private to + __lll_lock_wait. + (__lll_robust_lock, __lll_cond_lock, __lll_timedlock, + __lll_robust_timedlock): Add private argument, pass it to + __lll_*wait functions. + (__lll_unlock): Add private argument, if it is constant LLL_PRIVATE, + call __lll_unlock_wake_private, otherwise pass private to + __lll_unlock_wake. + (__lll_robust_unlock): Add private argument, pass it to + __lll_robust_unlock_wake. + (lll_lock, lll_robust_lock, lll_cond_lock, lll_timedlock, + lll_robust_timedlock, lll_unlock, lll_robust_unlock): Add private + argument, pass it through to __lll_* inline function. + (__lll_mutex_unlock_force, lll_mutex_unlock_force): Remove. + (lll_lock_t): Remove. + (__lll_cond_wait, __lll_cond_timedwait, __lll_cond_wake, + __lll_cond_broadcast, lll_cond_wait, lll_cond_timedwait, + lll_cond_wake, lll_cond_broadcast): Remove. + * sysdeps/unix/sysv/linux/ia64/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/powerpc/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/s390/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/sparc/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/i386/lowlevellock.h: Allow including + the header from assembler. Renamed all lll_mutex_* resp. + lll_robust_mutex_* macros to lll_* resp. lll_robust_*. + (LOCK, FUTEX_CMP_REQUEUE, FUTEX_WAKE_OP, + FUTEX_OP_CLEAR_WAKE_IF_GT_ONE): Define. + (LLL_MUTEX_LOCK_INITIALIZER, LLL_MUTEX_LOCK_INITIALIZER_LOCKED, + LLL_MUTEX_LOCK_INITIALIZER_WAITERS): Remove. + (__lll_mutex_lock_wait, __lll_mutex_timedlock_wait, + __lll_mutex_unlock_wake, __lll_lock_wait, __lll_unlock_wake): + Remove prototype. + (__lll_trylock_asm, __lll_lock_asm_start, __lll_unlock_asm): Define. + (lll_robust_trylock, lll_cond_trylock): Use LLL_LOCK_INITIALIZER* + rather than LLL_MUTEX_LOCK_INITIALIZER* macros. + (lll_trylock): Likewise, use __lll_trylock_asm, pass + MULTIPLE_THREADS_OFFSET as another asm operand. + (lll_lock): Add private argument, use __lll_lock_asm_start, pass + MULTIPLE_THREADS_OFFSET as last asm operand, call + __lll_lock_wait_private if private is constant LLL_PRIVATE, + otherwise pass private as another argument to __lll_lock_wait. + (lll_robust_lock, lll_cond_lock, lll_robust_cond_lock, + lll_timedlock, lll_robust_timedlock): Add private argument, pass + private as another argument to __lll_*lock_wait call. + (lll_unlock): Add private argument, use __lll_unlock_asm, pass + MULTIPLE_THREADS_OFFSET as another asm operand, call + __lll_unlock_wake_private if private is constant LLL_PRIVATE, + otherwise pass private as another argument to __lll_unlock_wake. + (lll_robust_unlock): Add private argument, pass private as another + argument to __lll_unlock_wake. + (lll_robust_dead): Add private argument, use __lll_private_flag + macro. + (lll_islocked): Use LLL_LOCK_INITIALIZER instead of + LLL_MUTEX_LOCK_INITIALIZER. + (lll_lock_t): Remove. + (LLL_LOCK_INITIALIZER_WAITERS): Define. + (__lll_cond_wait, __lll_cond_timedwait, __lll_cond_wake, + __lll_cond_broadcast, lll_cond_wait, lll_cond_timedwait, + lll_cond_wake, lll_cond_broadcast): Remove. + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/libc-lowlevellock.S: Revert + 2007-05-2{3,9} changes. + * sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S: Include + kernel-features.h and lowlevellock.h. + (LOAD_PRIVATE_FUTEX_WAIT): Define. + (LOAD_FUTEX_WAIT): Rewritten. + (LOCK, SYS_gettimeofday, SYS_futex, FUTEX_WAIT, FUTEX_WAKE): Don't + define. + (__lll_lock_wait_private, __lll_unlock_wake_private): New functions. + (__lll_mutex_lock_wait): Rename to ... + (__lll_lock_wait): ... this. Take futex addr from %edx instead of + %ecx, %ecx is now private argument. Don't compile in for libc.so. + (__lll_mutex_timedlock_wait): Rename to ... + (__lll_timedlock_wait): ... this. Use __NR_gettimeofday. %esi + contains private argument. Don't compile in for libc.so. + (__lll_mutex_unlock_wake): Rename to ... + (__lll_unlock_wake): ... this. %ecx contains private argument. + Don't compile in for libc.so. + (__lll_timedwait_tid): Use __NR_gettimeofday. + * sysdeps/unix/sysv/linux/i386/i486/lowlevelrobustlock.S: Include + kernel-features.h and lowlevellock.h. + (LOAD_FUTEX_WAIT): Define. + (LOCK, SYS_gettimeofday, SYS_futex, FUTEX_WAIT, FUTEX_WAKE): Don't + define. + (__lll_robust_mutex_lock_wait): Rename to ... + (__lll_robust_lock_wait): ... this. Futex addr is now in %edx + argument, %ecx argument contains private. Use LOAD_FUTEX_WAIT + macro. + (__lll_robust_mutex_timedlock_wait): Rename to ... + (__lll_robust_timedlock_wait): ... this. Use __NR_gettimeofday. + %esi argument contains private, use LOAD_FUTEX_WAIT macro. + * sysdeps/unix/sysv/linux/i386/i486/pthread_barrier_wait.S: Include + lowlevellock.h. + (SYS_futex, FUTEX_WAIT, FUTEX_WAKE, LOCK): Don't define. + (pthread_barrier_wait): Rename __lll_mutex_* to __lll_*, pass + PRIVATE(%ebx) ^ LLL_SHARED as private argument in %ecx to + __lll_lock_wait and __lll_unlock_wake, pass MUTEX(%ebx) address + to __lll_lock_wait in %edx. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.S: + Include lowlevellock.h and pthread-errnos.h. + (SYS_futex, FUTEX_WAIT, FUTEX_WAKE, FUTEX_REQUEUE, + FUTEX_CMP_REQUEUE, EINVAL, LOCK): Don't define. + (__pthread_cond_broadcast): Rename __lll_mutex_* to __lll_*, pass + cond_lock address in %edx rather than %ecx to __lll_lock_wait, + pass LLL_SHARED in %ecx to both __lll_lock_wait and + __lll_unlock_wake. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_signal.S: + Include lowlevellock.h and pthread-errnos.h. + (SYS_futex, FUTEX_WAIT, FUTEX_WAKE, FUTEX_WAKE_OP, + FUTEX_OP_CLEAR_WAKE_IF_GT_ONE, EINVAL, LOCK): Don't define. + (__pthread_cond_signal): Rename __lll_mutex_* to __lll_*, pass + cond_lock address in %edx rather than %ecx to __lll_lock_wait, + pass LLL_SHARED in %ecx to both __lll_lock_wait and + __lll_unlock_wake. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: + Include lowlevellock.h. + (SYS_futex, SYS_gettimeofday, FUTEX_WAIT, FUTEX_WAKE, LOCK): + Don't define. + (__pthread_cond_timedwait): Rename __lll_mutex_* to __lll_*, pass + cond_lock address in %edx rather than %ecx to __lll_lock_wait, + pass LLL_SHARED in %ecx to both __lll_lock_wait and + __lll_unlock_wake. Use __NR_gettimeofday. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S: + Include lowlevellock.h. + (SYS_futex, FUTEX_WAIT, FUTEX_WAKE, LOCK): Don't define. + (__pthread_cond_wait, __condvar_w_cleanup): Rename __lll_mutex_* + to __lll_*, pass cond_lock address in %edx rather than %ecx to + __lll_lock_wait, pass LLL_SHARED in %ecx to both __lll_lock_wait + and __lll_unlock_wake. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_rdlock.S: + Include lowlevellock.h. + (SYS_futex, FUTEX_WAIT, FUTEX_WAKE, LOCK): Don't define. + (__pthread_rwlock_rdlock): Rename __lll_mutex_* to __lll_*, pass + MUTEX(%ebx) address in %edx rather than %ecx to + __lll_lock_wait, pass PSHARED(%ebx) in %ecx to both __lll_lock_wait + and __lll_unlock_wake. Move return value from %ecx to %edx + register. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedrdlock.S: + Include lowlevellock.h. + (SYS_futex, SYS_gettimeofday, FUTEX_WAIT, FUTEX_WAKE, LOCK): + Don't define. + (__pthread_rwlock_wrlock): Rename __lll_mutex_* to __lll_*, pass + MUTEX(%ebp) address in %edx rather than %ecx to + __lll_lock_wait, pass PSHARED(%ebp) in %ecx to both __lll_lock_wait + and __lll_unlock_wake. Move return value from %ecx to %edx + register. Use __NR_gettimeofday. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedwrlock.S: + Include lowlevellock.h. + (SYS_futex, SYS_gettimeofday, FUTEX_WAIT, FUTEX_WAKE, LOCK): + Don't define. + (__pthread_rwlock_wrlock): Rename __lll_mutex_* to __lll_*, pass + MUTEX(%ebp) address in %edx rather than %ecx to + __lll_lock_wait, pass PSHARED(%ebp) in %ecx to both __lll_lock_wait + and __lll_unlock_wake. Move return value from %ecx to %edx + register. Use __NR_gettimeofday. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_unlock.S: + Include lowlevellock.h. + (SYS_futex, FUTEX_WAIT, FUTEX_WAKE, LOCK): Don't define. + (__pthread_rwlock_unlock): Rename __lll_mutex_* to __lll_*, pass + MUTEX(%edi) address in %edx rather than %ecx to + __lll_lock_wait, pass PSHARED(%edi) in %ecx to both __lll_lock_wait + and __lll_unlock_wake. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_wrlock.S: + Include lowlevellock.h. + (SYS_futex, FUTEX_WAIT, FUTEX_WAKE, LOCK): Don't define. + (__pthread_rwlock_wrlock): Rename __lll_mutex_* to __lll_*, pass + MUTEX(%ebx) address in %edx rather than %ecx to + __lll_lock_wait, pass PSHARED(%ebx) in %ecx to both __lll_lock_wait + and __lll_unlock_wake. Move return value from %ecx to %edx + register. + * sysdeps/unix/sysv/linux/i386/pthread_once.S: Include + lowlevellock.h. + (LOCK, SYS_futex, FUTEX_WAIT, FUTEX_WAKE, FUTEX_PRIVATE_FLAG): Don't + define. + * sysdeps/unix/sysv/linux/i386/i486/sem_post.S: Include lowlevellock.h. + (LOCK, SYS_futex, FUTEX_WAKE): Don't define. + * sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S: Include + lowlevellock.h. + (LOCK, SYS_futex, SYS_gettimeofday, FUTEX_WAIT): Don't define. + (sem_timedwait): Use __NR_gettimeofday. + * sysdeps/unix/sysv/linux/i386/i486/sem_trywait.S: Include + lowlevellock.h. + (LOCK): Don't define. + * sysdeps/unix/sysv/linux/i386/i486/sem_wait.S: Include + lowlevellock.h. + (LOCK, SYS_futex, FUTEX_WAIT): Don't define. + * sysdeps/unix/sysv/linux/powerpc/sem_post.c: Wake only when there + are waiters. + * sysdeps/unix/sysv/linux/x86_64/libc-lowlevellock.S: Revert + 2007-05-2{3,9} changes. + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.S: Include + kernel-features.h and lowlevellock.h. + (LOAD_PRIVATE_FUTEX_WAIT): Define. + (LOAD_FUTEX_WAIT): Rewritten. + (LOCK, SYS_futex, FUTEX_WAIT, FUTEX_WAKE): Don't define. + (__lll_lock_wait_private, __lll_unlock_wake_private): New functions. + (__lll_mutex_lock_wait): Rename to ... + (__lll_lock_wait): ... this. %esi is now private argument. + Don't compile in for libc.so. + (__lll_mutex_timedlock_wait): Rename to ... + (__lll_timedlock_wait): ... this. %esi contains private argument. + Don't compile in for libc.so. + (__lll_mutex_unlock_wake): Rename to ... + (__lll_unlock_wake): ... this. %esi contains private argument. + Don't compile in for libc.so. + * sysdeps/unix/sysv/linux/x86_64/lowlevelrobustlock.S: Include + kernel-features.h and lowlevellock.h. + (LOAD_FUTEX_WAIT): Define. + (LOCK, SYS_futex, FUTEX_WAIT, FUTEX_WAKE): Don't define. + (__lll_robust_mutex_lock_wait): Rename to ... + (__lll_robust_lock_wait): ... this. %esi argument contains private. + Use LOAD_FUTEX_WAIT macro. + (__lll_robust_mutex_timedlock_wait): Rename to ... + (__lll_robust_timedlock_wait): ... this. %esi argument contains + private, use LOAD_FUTEX_WAIT macro. + * sysdeps/unix/sysv/linux/x86_64/pthread_barrier_wait.S: Include + lowlevellock.h. + (SYS_futex, FUTEX_WAIT, FUTEX_WAKE, LOCK): Don't define. + (pthread_barrier_wait): Rename __lll_mutex_* to __lll_*, pass + PRIVATE(%rdi) ^ LLL_SHARED as private argument in %esi to + __lll_lock_wait and __lll_unlock_wake. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S: + Include lowlevellock.h and pthread-errnos.h. + (SYS_futex, FUTEX_WAIT, FUTEX_WAKE, FUTEX_REQUEUE, + FUTEX_CMP_REQUEUE, EINVAL, LOCK): Don't define. + (__pthread_cond_broadcast): Rename __lll_mutex_* to __lll_*, + pass LLL_SHARED in %esi to both __lll_lock_wait and + __lll_unlock_wake. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.S: + Include lowlevellock.h and pthread-errnos.h. + (SYS_futex, FUTEX_WAIT, FUTEX_WAKE, FUTEX_WAKE_OP, + FUTEX_OP_CLEAR_WAKE_IF_GT_ONE, EINVAL, LOCK): Don't define. + (__pthread_cond_signal): Rename __lll_mutex_* to __lll_*, + pass LLL_SHARED in %esi to both __lll_lock_wait and + __lll_unlock_wake. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S: + Include lowlevellock.h. + (SYS_futex, FUTEX_WAIT, FUTEX_WAKE, LOCK): Don't define. + (__pthread_cond_timedwait): Rename __lll_mutex_* to __lll_*, + pass LLL_SHARED in %esi to both __lll_lock_wait and + __lll_unlock_wake. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S: + Include lowlevellock.h. + (SYS_futex, FUTEX_WAIT, FUTEX_WAKE, LOCK): Don't define. + (__pthread_cond_wait, __condvar_cleanup): Rename __lll_mutex_* + to __lll_*, pass LLL_SHARED in %esi to both __lll_lock_wait + and __lll_unlock_wake. + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_rdlock.S: + Include lowlevellock.h. + (SYS_futex, FUTEX_WAIT, FUTEX_WAKE, FUTEX_PRIVATE_FLAG, LOCK): + Don't define. + (__pthread_rwlock_rdlock): Rename __lll_mutex_* to __lll_*, + pass PSHARED(%rdi) in %esi to both __lll_lock_wait + and __lll_unlock_wake. + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedrdlock.S: + Include lowlevellock.h. + (SYS_futex, FUTEX_WAIT, FUTEX_WAKE, FUTEX_PRIVATE_FLAG, LOCK): + Don't define. + (__pthread_rwlock_wrlock): Rename __lll_mutex_* to __lll_*, + pass PSHARED(%rdi) in %esi to both __lll_lock_wait + and __lll_unlock_wake. + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedwrlock.S: + Include lowlevellock.h. + (SYS_futex, FUTEX_WAIT, FUTEX_WAKE, FUTEX_PRIVATE_FLAG, LOCK): + Don't define. + (__pthread_rwlock_wrlock): Rename __lll_mutex_* to __lll_*, + pass PSHARED(%rdi) in %esi to both __lll_lock_wait + and __lll_unlock_wake. + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_unlock.S: + Include lowlevellock.h. + (SYS_futex, FUTEX_WAIT, FUTEX_WAKE, FUTEX_PRIVATE_FLAG, LOCK): + Don't define. + (__pthread_rwlock_unlock): Rename __lll_mutex_* to __lll_*, + pass PSHARED(%rdi) in %esi to both __lll_lock_wait + and __lll_unlock_wake. + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_wrlock.S: + Include lowlevellock.h. + (SYS_futex, FUTEX_WAIT, FUTEX_WAKE, FUTEX_PRIVATE_FLAG, LOCK): + Don't define. + (__pthread_rwlock_wrlock): Rename __lll_mutex_* to __lll_*, + pass PSHARED(%rdi) in %ecx to both __lll_lock_wait + and __lll_unlock_wake. + * sysdeps/unix/sysv/linux/x86_64/pthread_once.S: Include + lowlevellock.h. + (LOCK, SYS_futex, FUTEX_WAIT, FUTEX_WAKE, FUTEX_PRIVATE_FLAG): Don't + define. + * sysdeps/unix/sysv/linux/x86_64/sem_post.S: Include lowlevellock.h. + (LOCK, SYS_futex, FUTEX_WAKE): Don't define. + * sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S: Include + lowlevellock.h. + (LOCK, SYS_futex, FUTEX_WAIT): Don't define. + * sysdeps/unix/sysv/linux/x86_64/sem_trywait.S: Include + lowlevellock.h. + (LOCK): Don't define. + * sysdeps/unix/sysv/linux/x86_64/sem_wait.S: Include + lowlevellock.h. + (LOCK, SYS_futex, FUTEX_WAIT): Don't define. + * sysdeps/unix/sysv/linux/sparc/internaltypes.h: New file. + * sysdeps/unix/sysv/linux/sparc/pthread_barrier_destroy.c: New file. + * sysdeps/unix/sysv/linux/sparc/pthread_barrier_init.c: New file. + * sysdeps/unix/sysv/linux/sparc/pthread_barrier_wait.c: New file. + * sysdeps/unix/sysv/linux/sparc/sparc32/lowlevellock.c + (__lll_lock_wait_private): New function. + (__lll_lock_wait, __lll_timedlock_wait): Add private argument, pass + it to lll_futex_*wait. Don't compile in for libc.so. + * sysdeps/unix/sysv/linux/sparc/sparc32/pthread_barrier_init.c: + Remove. + * sysdeps/unix/sysv/linux/sparc/sparc32/pthread_barrier_wait.c + (struct sparc_pthread_barrier): Remove. + (pthread_barrier_wait): Use union sparc_pthread_barrier instead of + struct sparc_pthread_barrier. Pass + ibarrier->s.pshared ? LLL_SHARED : LLL_PRIVATE to lll_{,un}lock + and lll_futex_wait macros. + * sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/pthread_barrier_init.c: + Remove. + * sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/pthread_barrier_wait.c: + Include sparc pthread_barrier_wait.c instead of generic one. + +2007-07-30 Jakub Jelinek + + * tst-rwlock14.c (do_test): Avoid warnings on 32-bit arches. + + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedrdlock.S + (pthread_rwlock_timedrdlock): Copy futex retval to %esi rather than + %ecx. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedwrlock.S + (pthread_rwlock_timedwrlock): Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_unlock.S + (__pthread_rwlock_unlock): Fix MUTEX != 0 args to __lll_*. + +2007-07-31 Jakub Jelinek + + * sysdeps/sparc/tls.h (tcbhead_t): Add private_futex field. + +2007-07-26 Jakub Jelinek + + * tst-locale2.c (useless): Add return statement. + +2007-07-24 Jakub Jelinek + + * allocatestack.c (__nptl_setxid, __wait_lookup_done): Replace + lll_private_futex_* (*) with lll_futex_* (*, LLL_PRIVATE). + * pthread_create.c (start_thread): Likewise. + * init.c (sighandler_setxid): Likewise. + * sysdeps/alpha/tls.h (THREAD_GSCOPE_RESET_FLAG): Likewise. + * sysdeps/ia64/tls.h (THREAD_GSCOPE_RESET_FLAG): Likewise. + * sysdeps/i386/tls.h (THREAD_GSCOPE_RESET_FLAG): Likewise. + * sysdeps/s390/tls.h (THREAD_GSCOPE_RESET_FLAG): Likewise. + * sysdeps/powerpc/tls.h (THREAD_GSCOPE_RESET_FLAG): Likewise. + * sysdeps/x86_64/tls.h (THREAD_GSCOPE_RESET_FLAG): Likewise. + * sysdeps/sparc/tls.h (THREAD_GSCOPE_RESET_FLAG): Likewise. + * sysdeps/sh/tls.h (THREAD_GSCOPE_RESET_FLAG): Likewise. + * sysdeps/pthread/aio_misc.h (AIO_MISC_NOTIFY, AIO_MISC_WAIT): + Likewise. + * sysdeps/pthread/gai_misc.h (GAI_MISC_NOTIFY, GAI_MISC_WAIT): + Likewise. + * sysdeps/unix/sysv/linux/unregister-atfork.c (__unregister_atfork): + Likewise. + * sysdeps/unix/sysv/linux/rtld-lowlevel.h (__rtld_waitzero, + __rtld_notify): Likewise. + * sysdeps/unix/sysv/linux/fork.c (__libc_fork): Likewise. + * sysdeps/unix/sysv/linux/powerpc/pthread_once.c (clear_once_control, + __pthread_once): Likewise. + * sysdeps/unix/sysv/linux/alpha/pthread_once.c (clear_once_control, + __pthread_once): Add LLL_PRIVATE as last argument to lll_futex_*. + * sysdeps/unix/sysv/linux/alpha/lowlevellock.h (FUTEX_PRIVATE_FLAG, + LLL_PRIVATE, LLL_SHARED, __lll_private_flag): Define. + (lll_futex_wait): Add private argument, define as wrapper around + lll_futex_timed_wait. + (lll_futex_timed_wait, lll_futex_wake): Add private argument, + use __lll_private_flag macro. + (lll_robust_mutex_dead, __lll_mutex_unlock, __lll_robust_mutex_unlock, + __lll_mutex_unlock_force): Pass LLL_SHARED as last arg to lll_futex_*. + * sysdeps/unix/sysv/linux/ia64/pthread_once.c (clear_once_control, + __pthread_once): Add LLL_PRIVATE as last argument to lll_futex_*. + * sysdeps/unix/sysv/linux/ia64/lowlevellock.h (FUTEX_PRIVATE_FLAG, + LLL_PRIVATE, LLL_SHARED, __lll_private_flag): Define. + (lll_futex_wait): Add private argument, define as wrapper around + lll_futex_timed_wait. + (lll_futex_timed_wait, lll_futex_wake): Add private argument, + use __lll_private_flag macro. + (__lll_mutex_unlock, __lll_robust_mutex_unlock, lll_wait_tid, + __lll_mutex_unlock_force): Pass LLL_SHARED as last arg to lll_futex_*. + * sysdeps/unix/sysv/linux/i386/lowlevellock.h (__lll_private_flag): + Define. + (lll_futex_timed_wait, lll_futex_wake): Use it. + (lll_private_futex_wait, lll_private_futex_timed_wait, + lll_private_futex_wake): Removed. + * sysdeps/unix/sysv/linux/s390/pthread_once.c (clear_once_control, + __pthread_once): Add LLL_PRIVATE as last argument to lll_futex_*. + * sysdeps/unix/sysv/linux/s390/lowlevellock.h (FUTEX_PRIVATE_FLAG, + LLL_PRIVATE, LLL_SHARED, __lll_private_flag): Define. + (lll_futex_wait): Add private argument, define as wrapper around + lll_futex_timed_wait. + (lll_futex_timed_wait, lll_futex_wake): Add private argument, + use __lll_private_flag macro. + (lll_robust_mutex_dead, __lll_mutex_unlock, __lll_robust_mutex_unlock, + lll_wait_tid, __lll_mutex_unlock_force): Pass LLL_SHARED as last arg + to lll_futex_*. + * sysdeps/unix/sysv/linux/powerpc/lowlevellock.h + (lll_private_futex_wait, lll_private_futex_timed_wait, + lll_private_futex_wake): Removed. + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.h (__lll_private_flag): + Fix !__ASSUME_PRIVATE_FUTEX non-constant private case. + (lll_private_futex_wait, lll_private_futex_timed_wait, + lll_private_futex_wake): Removed. + * sysdeps/unix/sysv/linux/sparc/pthread_once.c (clear_once_control, + __pthread_once): Add LLL_PRIVATE as last argument to lll_futex_*. + * sysdeps/unix/sysv/linux/sparc/lowlevellock.h (FUTEX_PRIVATE_FLAG, + LLL_PRIVATE, LLL_SHARED, __lll_private_flag): Define. + (lll_futex_wait): Add private argument, define as wrapper around + lll_futex_timed_wait. + (lll_futex_timed_wait, lll_futex_wake): Add private argument, + use __lll_private_flag macro. + (lll_robust_mutex_dead, __lll_mutex_unlock, __lll_robust_mutex_unlock, + lll_wait_tid, __lll_mutex_unlock_force): Pass LLL_SHARED as last arg + to lll_futex_*. + * sysdeps/unix/sysv/linux/sh/lowlevellock.h (__lll_private_flag): + Define. + (lll_futex_timed_wait, lll_futex_wake): Use it. + (lll_private_futex_wait, lll_private_futex_timed_wait, + lll_private_futex_wake): Removed. + +2007-07-27 Jakub Jelinek + + * sysdeps/sparc/tls.h (tcbhead_t): Move gscope_flag to the end + of the structure for sparc32. + +2007-07-26 Aurelien Jarno + + * sysdeps/sparc/tls.h (tcbhead_t): Add gscope_flag. + +2007-07-23 Ulrich Drepper + + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedrdlock.S: Fix + code used when private futexes are assumed. + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedwrlock.S: + Likewise. + +2007-07-23 Jakub Jelinek + + * sysdeps/unix/sysv/linux/powerpc/lowlevellock.h + (__lll_private_flag): Define. + (lll_futex_wait): Define as a wrapper around lll_futex_timed_wait. + (lll_futex_timed_wait, lll_futex_wake, lll_futex_wake_unlock): Use + __lll_private_flag. + (lll_private_futex_wait, lll_private_futex_timedwait, + lll_private_futex_wake): Define as wrapper around non-_private + macros. + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.h + (__lll_private_flag): Define. + (lll_futex_timed_wait, lll_futex_wake): Use __lll_private_flag. + (lll_private_futex_wait, lll_private_futex_timedwait, + lll_private_futex_wake): Define as wrapper around non-_private + macros. + +2007-07-10 Steven Munroe + + * pthread_rwlock_rdlock.c (__pthread_rwlock_rdlock): Add LLL_SHARED + parameter to lll_futex_wait call. + * pthread_rwlock_wrlock.c (__pthread_rwlock_wrlock): Likewise. + + * sysdeps/unix/sysv/linux/powerpc/pthread_once.c (__pthread_once): + Replace lll_futex_wait with lll_private_futex_wait. + * sysdeps/unix/sysv/linux/powerpc/sem_post.c (__new_sem_post): + Add LLL_SHARED parameter to lll_futex_wake(). + + * sysdeps/unix/sysv/linux/powerpc/lowlevellock.h: Define LLL_PRIVATE + LLL_SHARED, lll_private_futex_wait, lll_private_futex_timed_wait and + lll_private_futex_wake. + (lll_futex_wait): Add private parameter. Adjust FUTEX_PRIVATE_FLAG + bit from private parm before syscall. + (lll_futex_timed_wait): Likewise. + (lll_futex_wake): Likewise. + (lll_futex_wake_unlock): Likewise. + (lll_mutex_unlock): Add LLL_SHARED parm to lll_futex_wake call. + (lll_robust_mutex_unlock): Likewise. + (lll_mutex_unlock_force): Likewise. + (lll_wait_tid): Add LLL_SHARED parm to lll_futex_wait call. + +2007-07-23 Ulrich Drepper + + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedrdlock.S: Fix + compilation when unconditionally using private futexes. + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_rdlock.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedwrlock.S: + Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_unlock.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_wrlock.S: Likewise. + +2007-07-17 Jakub Jelinek + + * sysdeps/pthread/bits/stdio-lock.h (_IO_acquire_lock_clear_flags2): + Define. + +2007-07-06 Kaz Kojima + + * sysdeps/sh/tls.h: Include stdlib.h, list.h, sysdep.h and + kernel-features.h. + +2007-05-16 Roland McGrath + + * init.c (__nptl_initial_report_events): New variable. + (__pthread_initialize_minimal_internal): Initialize pd->report_events + to that. + +2007-06-22 Jakub Jelinek + + * pthread_getattr_np.c (pthread_getattr_np): Clear cpuset and + cpusetsize if pthread_getaffinity_np failed with ENOSYS. + +2007-06-19 Ulrich Drepper + + * sysdeps/unix/sysv/linux/rtld-lowlevel.h: Remove mrlock + implementation. + +2007-06-18 Ulrich Drepper + + * pthreadP.h: Define PTHREAD_MUTEX_TYPE. + * phtread_mutex_lock.c: Use PTHREAD_MUTEX_TYPE. + * pthread_mutex_timedlock.c: Likewise. + * pthread_mutex_trylock.c: Likewise. + * pthread_mutex_unlock.c: Likewise. + +2007-06-17 Andreas Schwab + + * sysdeps/pthread/pt-initfini.c: Tell gcc about the nonstandard + sections. + +2007-06-17 Ulrich Drepper + + * allocatestack.c (allocate_stack): Make code compile if + __ASSUME_PRIVATE_FUTEX is set. + +2007-06-17 Kaz Kojima + + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_rdlock.S: + (__pthread_rwlock_rdlock): Don't use non SH-3/4 instruction. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_wrlock.S: + (__pthread_rwlock_wrlock): Likewise. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedrdlock.S: + (pthread_rwlock_timedrdlock): Likewise. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedwrlock.S: + (pthread_rwlock_timedwrlock): Likewise. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_unlock.S: + (__pthread_rwlock_unlock): Likewise. + +2007-06-10 Kaz Kojima + + * sysdeps/sh/tcb-offsets.sym: Add PRIVATE_FUTEX. + * sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h: Include endian.h. + Split __flags into __flags, __shared, __pad1 and __pad2. + * sysdeps/unix/sysv/linux/sh/libc-lowlevellock.S: Use private + futexes if they are available. + * sysdeps/unix/sysv/linux/sh/lowlevellock.S: Adjust so that change + in libc-lowlevellock.S allow using private futexes. + * sysdeps/unix/sysv/linux/sh/lowlevellock.h: Define + FUTEX_PRIVATE_FLAG. Add additional parameter to lll_futex_wait, + lll_futex_timed_wait and lll_futex_wake. Change lll_futex_wait + to call lll_futex_timed_wait. Add lll_private_futex_wait, + lll_private_futex_timed_wait and lll_private_futex_wake. + (lll_robust_mutex_unlock): Fix typo. + * sysdeps/unix/sysv/linux/sh/pthread_barrier_wait.S: Use private + field in futex command setup. + * sysdeps/unix/sysv/linux/sh/pthread_cond_timedwait.S: Use + COND_NWAITERS_SHIFT instead of COND_CLOCK_BITS. + * sysdeps/unix/sysv/linux/sh/pthread_cond_wait.S: Likewise. + * sysdeps/unix/sysv/linux/sh/pthread_once.S: Use private futexes + if they are available. Remove clear_once_control. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_rdlock.S: Use private + futexes if they are available. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedrdlock.S: Likewise. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedwrlock.S: Likewise. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_unlock.S: Likewise. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_wrlock.S: Likewise. + * sysdeps/unix/sysv/linux/sh/sem_post.S: Add private futex support. + Wake only when there are waiters. + * sysdeps/unix/sysv/linux/sh/sem_wait.S: Add private futex + support. Indicate that there are waiters. Remove unnecessary + extra cancellation test. + * sysdeps/unix/sysv/linux/sh/sem_timedwait.S: Likewise. Removed + left-over duplication of __sem_wait_cleanup. + +2007-06-07 Ulrich Drepper + + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.h: Add additional + parameter to lll_futex_wait, lll_futex_timed_wait, and + lll_futex_wake. Change lll_futex_wait to call lll_futex_timed_wait. + Add lll_private_futex_wait, lll_private_futex_timed_wait, and + lll_private_futex_wake. + * sysdeps/unix/sysv/linux/i386/lowlevellock.h: Likewise. + * allocatestack.c: Adjust use of lll_futex_* macros. + * init.c: Likewise. + * lowlevellock.h: Likewise. + * pthread_barrier_wait.c: Likewise. + * pthread_cond_broadcast.c: Likewise. + * pthread_cond_destroy.c: Likewise. + * pthread_cond_signal.c: Likewise. + * pthread_cond_timedwait.c: Likewise. + * pthread_cond_wait.c: Likewise. + * pthread_create.c: Likewise. + * pthread_mutex_lock.c: Likewise. + * pthread_mutex_setprioceiling.c: Likewise. + * pthread_mutex_timedlock.c: Likewise. + * pthread_mutex_unlock.c: Likewise. + * pthread_rwlock_timedrdlock.c: Likewise. + * pthread_rwlock_timedwrlock.c: Likewise. + * pthread_rwlock_unlock.c: Likewise. + * sysdeps/alpha/tls.h: Likewise. + * sysdeps/i386/tls.h: Likewise. + * sysdeps/ia64/tls.h: Likewise. + * sysdeps/powerpc/tls.h: Likewise. + * sysdeps/pthread/aio_misc.h: Likewise. + * sysdeps/pthread/gai_misc.h: Likewise. + * sysdeps/s390/tls.h: Likewise. + * sysdeps/sh/tls.h: Likewise. + * sysdeps/sparc/tls.h: Likewise. + * sysdeps/unix/sysv/linux/fork.c: Likewise. + * sysdeps/unix/sysv/linux/lowlevellock.c: Likewise. + * sysdeps/unix/sysv/linux/lowlevelrobustlock.c: Likewise. + * sysdeps/unix/sysv/linux/rtld-lowlevel.h: Likewise. + * sysdeps/unix/sysv/linux/sem_post.c: Likewise. + * sysdeps/unix/sysv/linux/sem_timedwait.c: Likewise. + * sysdeps/unix/sysv/linux/sem_wait.c: Likewise. + * sysdeps/unix/sysv/linux/unregister-atfork.c: Likewise. + * sysdeps/unix/sysv/linux/sparc/pthread_once.c: Likewise. + * sysdeps/unix/sysv/linux/sparc/sparc32/pthread_barrier_wait.c: + Likewise. + * sysdeps/unix/sysv/linux/sparc/sparc32/sem_post.c: Likewise. + * sysdeps/x86_64/tls.h: Likewise. + +2007-05-29 Ulrich Drepper + + * pthread_getattr_np.c: No need to install a cancellation handler, + this is no cancellation point. + * pthread_getschedparam.c: Likewise. + * pthread_setschedparam.c: Likewise. + * pthread_setschedprio.c: Likewise. + * sysdeps/unix/sysv/linux/lowlevellock.c: Remove all traces of + lll_unlock_wake_cb. + * sysdeps/unix/sysv/linux/alpha/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/i386/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S: Likewise. + * sysdeps/unix/sysv/linux/ia64/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/powerpc/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/s390/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/sh/lowlevellock.S: Likewise. + * sysdeps/unix/sysv/linux/sh/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/sparc/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/sparc/sparc32/lowlevellock.c: Likewise. + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.h: Likewise. + + * sysdeps/unix/sysv/linux/i386/i486/libc-lowlevellock.S: Checking + whether there are more than one thread makes no sense here since + we only call the slow path if the locks are taken. + * sysdeps/unix/sysv/linux/x86_64/libc-lowlevellock.S: Likewise. + + * sysdeps/unix/sysv/linux/internaltypes.h: Introduce + COND_NWAITERS_SHIFT. + * pthread_cond_destroy.c: Use COND_NWAITERS_SHIFT instead of + COND_CLOCK_BITS. + * pthread_cond_init.c: Likewise. + * pthread_cond_timedwait.c: Likewise. + * pthread_cond_wait.c: Likewise. + * pthread_condattr_getclock.c: Likewise. + * pthread_condattr_setclock.c: Likewise. + * sysdeps/unix/sysv/linux/lowlevelcond.sym: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S: Likewise. + +2007-05-28 Jakub Jelinek + + * sysdeps/unix/sysv/linux/powerpc/pthread_attr_setstacksize.c: Include + unistd.h. + + * sysdeps/i386/tls.h (THREAD_GSCOPE_RESET_FLAG): Use explicit + insn suffix. + (THREAD_GSCOPE_GET_FLAG): Remove. + * sysdeps/x86_64/tls.h (THREAD_GSCOPE_GET_FLAG): Remove. + * allocatestack.c (__wait_lookup_done): Revert 2007-05-24 + changes. + * sysdeps/powerpc/tls.h (tcbhead_t): Remove gscope_flag. + (THREAD_GSCOPE_GET_FLAG): Remove. + (THREAD_GSCOPE_RESET_FLAG): Use THREAD_SELF->header.gscope_flag + instead of THREAD_GSCOPE_GET_FLAG. + (THREAD_GSCOPE_SET_FLAG): Likewise. Add atomic_write_barrier after + it. + * sysdeps/s390/tls.h (THREAD_GSCOPE_FLAG_UNUSED, + THREAD_GSCOPE_FLAG_USED, THREAD_GSCOPE_FLAG_WAIT, + THREAD_GSCOPE_RESET_FLAG, THREAD_GSCOPE_SET_FLAG, + THREAD_GSCOPE_WAIT): Define. + * sysdeps/sparc/tls.h (THREAD_GSCOPE_FLAG_UNUSED, + THREAD_GSCOPE_FLAG_USED, THREAD_GSCOPE_FLAG_WAIT, + THREAD_GSCOPE_RESET_FLAG, THREAD_GSCOPE_SET_FLAG, + THREAD_GSCOPE_WAIT): Define. + * sysdeps/sh/tls.h (THREAD_GSCOPE_FLAG_UNUSED, + THREAD_GSCOPE_FLAG_USED, THREAD_GSCOPE_FLAG_WAIT, + THREAD_GSCOPE_RESET_FLAG, THREAD_GSCOPE_SET_FLAG, + THREAD_GSCOPE_WAIT): Define. + * sysdeps/ia64/tls.h (THREAD_GSCOPE_FLAG_UNUSED, + THREAD_GSCOPE_FLAG_USED, THREAD_GSCOPE_FLAG_WAIT, + THREAD_GSCOPE_RESET_FLAG, THREAD_GSCOPE_SET_FLAG, + THREAD_GSCOPE_WAIT): Define. + +2007-05-24 Richard Henderson + + * descr.h (struct pthread): Add header.gscope_flag. + * sysdeps/alpha/tls.h (THREAD_GSCOPE_FLAG_UNUSED, + THREAD_GSCOPE_FLAG_USED, THREAD_GSCOPE_FLAG_WAIT, + THREAD_GSCOPE_RESET_FLAG, THREAD_GSCOPE_SET_FLAG, + THREAD_GSCOPE_WAIT): Define. + +2007-05-27 Ulrich Drepper + + * init.c: Make it compile with older kernel headers. + + * tst-initializers1.c: Show through exit code which test failed. + + * pthread_rwlock_init.c: Also initialize __shared field. + * sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h: Split __flags + element in rwlock structure into four byte elements. One of them is + the new __shared element. + * sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h [__WORDSIZE=32]: + Likewise. + [__WORDSIZE=64]: Renamed __pad1 element int rwlock structure to + __shared, adjust names of other padding elements. + * sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h: Likewise. + * sysdeps/pthread/pthread.h: Adjust rwlock initializers. + * sysdeps/unix/sysv/linux/lowlevelrwlock.sym: Add PSHARED. + * sysdeps/unix/sysv/linux/powerpc/lowlevellock.h: Define + FUTEX_PRIVATE_FLAG. + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_rdlock.S: Change main + futex to use private operations if possible. + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedrdlock.S: + Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedwrlock.S: + Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_unlock.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_wrlock.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_rdlock.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedrdlock.S: + Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedwrlock.S: + Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_unlock.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_wrlock.S: Likewise. + +2007-05-26 Ulrich Drepper + + * pthreadP.h (PTHREAD_RWLOCK_PREFER_READER_P): Define. + * pthread_rwlock_rdlock.c: Use PTHREAD_RWLOCK_PREFER_READER_P. + * pthread_rwlock_timedrdlock.c: Likewise. + * pthread_rwlock_tryrdlock.c: Likewise. + + * sysdeps/unix/sysv/linux/x86_64/sem_trywait.S (sem_trywait): Tiny + optimization. + + * sysdeps/unix/sysv/linux/sem_wait.c: Add missing break. + * sysdeps/unix/sysv/linux/sem_timedwait.c: Removed left-over + duplication of __sem_wait_cleanup. + + * allocatestack.c: Revert last change. + * init.c: Likewise. + * sysdeps/i386/tls.h: Likewise. + * sysdeps/x86_64/tls.h: Likewise. + * descr.h [TLS_DTV_AT_TP] (struct pthread): Add private_futex field to + header structure. + * sysdeps/powerpc/tcb-offsets.sym: Add PRIVATE_FUTEX_OFFSET. + + * sysdeps/unix/sysv/linux/internaltypes.h (struct pthread_barrier): + Add private field. + * sysdeps/unix/sysv/linux/lowlevelbarrier.sym: Add PRIVATE definition. + * pthread_barrier_init.c: Set private flag if pshared and private + futexes are supported. + * sysdeps/unix/sysv/linux/i386/i486/pthread_barrier_wait.S: Use + private field in futex command setup. + * sysdeps/unix/sysv/linux/x86_64/pthread_barrier_wait.S: Likewise. + +2007-05-25 Ulrich Drepper + + * sysdeps/unix/sysv/linux/i386/i486/sem_post.S: Add private futex + support. + * sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/sem_wait.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/sem_post.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/sem_wait.S: Likewise. + + * semaphoreP.h: Declare __old_sem_init and __old_sem_wait. + * sem_init.c (__new_sem_init): Rewrite to initialize all three + fields in the structure. + (__old_sem_init): New function. + * sem_open.c: Initialize all fields of the structure. + * sem_getvalue.c: Adjust for renamed element. + * sysdeps/unix/sysv/linux/Makefile [subdir=nptl] + (gen-as-const-headers): Add structsem.sym. + * sysdeps/unix/sysv/linux/structsem.sym: New file. + * sysdeps/unix/sysv/linux/internaltypes.h: Rename struct sem to + struct new_sem. Add struct old_sem. + * sysdeps/unix/sysv/linux/sem_post.c: Wake only when there are waiters. + * sysdeps/unix/sysv/linux/i386/i486/sem_post.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/sem_post.S: Likewise. + * sysdeps/unix/sysv/linux/sem_wait.c: Indicate that there are waiters. + * sysdeps/unix/sysv/linux/i386/i486/sem_wait.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/sem_wait.S: Likewise. + * sysdeps/unix/sysv/linux/sem_timedwait.c: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S: Likewise. + * Makefile (tests): Add tst-sem10, tst-sem11, tst-sem12. + * tst-sem10.c: New file. + * tst-sem11.c: New file. + * tst-sem12.c: New file. + * tst-typesizes.c: Test struct new_sem and struct old_sem instead + of struct sem. + +2007-05-25 Ulrich Drepper + Jakub Jelinek + + * sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S (sem_timedwait): + Move __pthread_enable_asynccancel right before futex syscall. + * sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S (sem_timedwait): + Likewise. + +2007-05-24 Jakub Jelinek + + * sysdeps/i386/tls.h (THREAD_SET_PRIVATE_FUTEX, + THREAD_COPY_PRIVATE_FUTEX): Define. + * sysdeps/x86_64/tls.h (THREAD_SET_PRIVATE_FUTEX, + THREAD_COPY_PRIVATE_FUTEX): Define. + * allocatestack.c (allocate_stack): Use THREAD_COPY_PRIVATE_FUTEX. + * init.c (__pthread_initialize_minimal_internal): Use + THREAD_SET_PRIVATE_FUTEX. + + * sysdeps/powerpc/tls.h (tcbhead_t): Add gscope_flag. + (THREAD_GSCOPE_FLAG_UNUSED, THREAD_GSCOPE_FLAG_USED, + THREAD_GSCOPE_FLAG_WAIT): Define. + (THREAD_GSCOPE_GET_FLAG, THREAD_GSCOPE_SET_FLAG, + THREAD_GSCOPE_RESET_FLAG, THREAD_GSCOPE_WAIT): Define. + * sysdeps/i386/tls.h (THREAD_GSCOPE_WAIT): Don't use + PTR_DEMANGLE. + (THREAD_GSCOPE_GET_FLAG): Define. + * sysdeps/x86_64/tls.h (THREAD_GSCOPE_GET_FLAG): Define. + * allocatestack.c (__wait_lookup_done): Use THREAD_GSCOPE_GET_FLAG + instead of ->header.gscope_flag directly. + +2007-05-23 Ulrich Drepper + + * init.c (__pthread_initialize_minimal_internal): Check whether + private futexes are available. + * allocatestack.c (allocate_stack): Copy private_futex field from + current thread into the new stack. + * sysdeps/unix/sysv/linux/x86_64/libc-lowlevellock.S: Use private + futexes if they are available. + * sysdeps/unix/sysv/linux/i386/i486/libc-lowlevellock.S: Likewise + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.S: Adjust so that change + in libc-lowlevellock.S allow using private futexes. + * sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.h: Define + FUTEX_PRIVATE_FLAG. + * sysdeps/unix/sysv/linux/i386/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_once.S: Use private futexes + if they are available. + * sysdeps/unix/sysv/linux/i386/pthread_once.S: Likewise. + * sysdeps/x86_64/tcb-offsets.sym: Add PRIVATE_FUTEX. + * sysdeps/i386/tcb-offsets.sym: Likewise. + * sysdeps/x86_64/tls.h (tcbhead_t): Add private_futex field. + * sysdeps/i386/tls.h (tcbhead_t): Likewise. + +2007-05-21 Ulrich Drepper + + * sysdeps/pthread/pthread-functions.h (struct pthread_functions): + Remove ptr_wait_lookup_done again. + * init.c (pthread_functions): Don't add .ptr_wait_lookup_done here. + (__pthread_initialize_minimal_internal): Initialize + _dl_wait_lookup_done pointer in _rtld_global directly. + * sysdeps/unix/sysv/linux/libc_pthread_init.c (__libc_pthread_init): + Remove code to code _dl_wait_lookup_done. + * sysdeps/x86_64/tls.h (THREAD_GSCOPE_WAIT): The pointer is not + encrypted for now. + +2007-05-21 Jakub Jelinek + + * tst-robust9.c (do_test): Don't fail if ENABLE_PI and + pthread_mutex_init failed with ENOTSUP. + +2007-05-19 Ulrich Drepper + + * allocatestack.c (__wait_lookup_done): New function. + * sysdeps/pthread/pthread-functions.h (struct pthread_functions): + Add ptr_wait_lookup_done. + * init.c (pthread_functions): Initialize .ptr_wait_lookup_done. + * pthreadP.h: Declare __wait_lookup_done. + * sysdeps/i386/tls.h (tcbhead_t): Add gscope_flag. + Define macros to implement reference handling of global scope. + * sysdeps/x86_64/tls.h: Likewise. + * sysdeps/unix/sysv/linux/libc_pthread_init.c (__libc_pthread_init): + Initialize GL(dl_wait_lookup_done). + +2007-05-17 Ulrich Drepper + + [BZ #4512] + * pthread_mutex_lock.c: Preserve FUTEX_WAITERS bit when dead owner + is detected. + * pthread_mutex_timedlock.c: Likewise. + * pthread_mutex_trylock.c: Likewise. + Patch in part by Atsushi Nemoto . + + * Makefile (tests): Add tst-robust9 and tst-robustpi9. + * tst-robust9.c: New file. + * tst-robustpi9.c: New file. + + * sysdeps/unix/sysv/linux/sem_wait.c (__new_sem_wait): Remove + unnecessary extra cancellation test. + +2007-05-14 Ulrich Drepper + + * sysdeps/unix/sysv/linux/x86_64/sem_wait.S: Remove unnecessary + extra cancellation test. + * sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S: Likewise. + +2007-05-10 Ulrich Drepper + + * descr.h (struct pthread): Rearrange members to fill hole in + 64-bit layout. + + * sysdeps/unix/sysv/linux/pthread_setaffinity.c + (__pthread_setaffinity_new): If syscall was successful and + RESET_VGETCPU_CACHE is defined, use it before returning. + * sysdeps/unix/sysv/linux/x86_64/pthread_setaffinity.c: New file. + +2007-05-10 Jakub Jelinek + + [BZ #4455] + * tst-align2.c: Include stackinfo.h. + * tst-getpid1.c: Likewise. + +2007-05-02 Carlos O'Donell + + [BZ #4455] + * tst-align2.c (do_test): Add _STACK_GROWS_UP case. + * tst-getpid1.c (do_test): Likewise. + + [BZ #4456] + * allocatestack.c (change_stack_perm): Add _STACK_GROWS_UP case. + (allocate_stack): Likewise. + +2007-05-07 Ulrich Drepper + + * sysdeps/unix/sysv/linux/lowlevelrobustlock.c + (__lll_robust_lock_wait): Fix race caused by reloading of futex value. + (__lll_robust_timedlock_wait): Likewise. + Reported by Alexey Kuznetsov . + +2007-05-06 Mike Frysinger + + [BZ #4465] + * tst-cancel-wrappers.sh: Set C["fdatasync"] to 1. + * tst-cancel4.c (tf_fdatasync): New test. + +2007-04-27 Ulrich Drepper + + [BZ #4392] + * pthread_mutex_trylock.c (__pthread_mutex_trylock): Treat error + check mutexes like normal mutexes. + + [BZ #4306] + * sysdeps/unix/sysv/linux/timer_create.c (timer_create): + Initialize the whole sigevent structure to appease valgrind. + +2007-04-25 Ulrich Drepper + + * sysdeps/x86_64/tls.h (tcbhead_t): Add vgetcpu_cache. + * sysdeps/x86_64/tcb-offsets.sym: Add VGETCPU_CACHE_OFFSET. + +2007-04-06 Ulrich Drepper + + * tst-locale1.c: Avoid warnings. + * tst-locale2.c: Likewise. + +2007-03-19 Steven Munroe + + * sysdeps/unix/sysv/linux/powerpc/lowlevellock.h + (__lll_robust_trylock): Add MUTEX_HINT_ACQ to lwarx instruction. + +2007-03-16 Jakub Jelinek + + * sysdeps/pthread/bits/libc-lock.h: Use __extern_inline and + __extern_always_inline where appropriate. + * sysdeps/pthread/pthread.h: Likewise. + +2007-03-13 Richard Henderson + + * sysdeps/unix/sysv/linux/alpha/sysdep-cancel.h (PSEUDO): Use two + separate cfi regions for the two subsections. + +2007-02-25 Ulrich Drepper + + * sysdeps/unix/sysv/linux/fork.c (__libc_fork): Reset refcntr in + new thread, don't just decrement it. + Patch by Suzuki K P . + +2007-02-21 Ulrich Drepper + + * sysdeps/pthread/pthread-functions.h: Correct last patch, correct + PTHFCT_CALL definition. + +2007-02-18 Ulrich Drepper + + * sysdeps/pthread/pthread-functions.h: If PTR_DEMANGLE is not + available, don't use it. + +2007-02-09 Jakub Jelinek + + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.S + (__lll_mutex_timedlock_wait): Use correct pointer when we don't + call into the kernel to delay. + +2007-01-18 Ulrich Drepper + + * tst-initializers1.c: We want to test the initializers as seen + outside of libc, so undefined _LIBC. + + * pthread_join.c (cleanup): Avoid warning. + +2007-01-17 Ulrich Drepper + + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.S + (__lll_timedwait_tid): Add unwind info. + + * sysdeps/unix/sysv/linux/libc_pthread_init.c: Don't just copy the + function table, mangle the pointers. + * sysdeps/pthread/pthread-functions.h: Define PTHFCT_CALL. + * forward.c: Use PTHFCT_CALL and __libc_pthread_functions_init. + * sysdeps/pthread/bits/libc-lock.h: When using __libc_pthread_functions + demangle pointers before use. + * sysdeps/unix/sysv/linux/s390/jmp-unwind.c: Use PTHFCT_CALL to + demangle pointer. + * sysdeps/unix/sysv/linux/jmp-unwind.c: Likewise. + * sysdeps/pthread/setxid.h: Likewise. + +2007-01-12 Ulrich Drepper + + * tst-rwlock7.c: Show some more information in case of correct + behavior. + +2007-01-11 Ulrich Drepper + + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.h + (lll_futex_timed_wait): Undo part of last change, don't negate + return value. + +2007-01-10 Ulrich Drepper + + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.h: Cleanups. Define + FUTEX_CMP_REQUEUE and lll_futex_requeue. + +2006-12-28 David S. Miller + + * shlib-versions: Fix sparc64 linux target specification. + +2007-01-10 Jakub Jelinek + + * sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/pthread_barrier_wait.c: + Adjust include path for pthread_barrier_wait.c move. + +2006-12-21 Jakub Jelinek + + * sysdeps/unix/sysv/linux/pthread_kill.c (pthread_kill): Make sure + tid isn't reread from pd->tid in between ESRCH test and the syscall. + +2006-12-06 Jakub Jelinek + + * sysdeps/unix/sysv/linux/s390/s390-32/sysdep-cancel.h (PSEUDO): Handle + 6 argument cancellable syscalls. + (STM_6, LM_6, LR7_0, LR7_1, LR7_2, LR7_3, LR7_4, LR7_5, LR7_6): Define. + * sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h (PSEUDO): Handle + 6 argument cancellable syscalls. + (STM_6, LM_6, LR7_0, LR7_1, LR7_2, LR7_3, LR7_4, LR7_5, LR7_6): Define. + +2006-12-09 Ulrich Drepper + + * sysdeps/unix/sysv/linux/rtld-lowlevel.h + (__rtld_mrlock_initialize): Add missing closing parenthesis. + +2006-10-30 Jakub Jelinek + + * sysdeps/ia64/pthread_spin_unlock.c (pthread_spin_unlock): Use + __sync_lock_release instead of __sync_lock_release_si. + +2006-10-29 Jakub Jelinek + + * sysdeps/unix/sysv/linux/i386/sysdep-cancel.h (RTLD_SINGLE_THREAD_P): + Define. + (SINGLE_THREAD_P): Define to 1 if IS_IN_rtld. + * sysdeps/unix/sysv/linux/alpha/sysdep-cancel.h: Likewise. + * sysdeps/unix/sysv/linux/ia64/sysdep-cancel.h: Likewise. + * sysdeps/unix/sysv/linux/s390/s390-32/sysdep-cancel.h: Likewise. + * sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h: Likewise. + * sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h: Likewise. + * sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h: Likewise. + * sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h: Likewise. + * sysdeps/unix/sysv/linux/sparc/sparc32/sysdep-cancel.h: Likewise. + * sysdeps/unix/sysv/linux/sparc/sparc64/sysdep-cancel.h: Likewise. + * sysdeps/unix/sysv/linux/sh/sysdep-cancel.h: Likewise. + +2006-10-27 Ulrich Drepper + + * sysdeps/pthread/pthread_barrier_wait.c: Move to... + * pthread_barrier_wait.c: ...here. + * sysdeps/pthread/pthread_cond_broadcast.c: Move to... + * pthread_cond_broadcast.c: ...here. + * sysdeps/pthread/pthread_cond_signal.c: Move to... + * pthread_cond_signal.c: ...here. + * sysdeps/pthread/pthread_cond_timedwait.c: Move to... + * pthread_cond_timedwait.c: ...here. + * sysdeps/pthread/pthread_cond_wait.c: Move to... + * pthread_cond_wait.c: ...here. + * sysdeps/pthread/pthread_once.c: Move to... + * pthread_once.c: ...here. + * sysdeps/pthread/pthread_rwlock_rdlock.c: Move to... + * pthread_rwlock_rdlock.c: ...here. + * sysdeps/pthread/pthread_rwlock_timedrdlock.c: Move to... + * pthread_rwlock_timedrdlock.c: ...here. + * sysdeps/pthread/pthread_rwlock_timedwrlock.c: Move to... + * pthread_rwlock_timedwrlock.c: ...here. + * sysdeps/pthread/pthread_rwlock_unlock.c: Move to... + * pthread_rwlock_unlock.c: ...here. + * sysdeps/pthread/pthread_rwlock_wrlock.c: Move to... + * pthread_rwlock_wrlock.c: ...here. + * sysdeps/pthread/pthread_spin_destroy.c: Move to... + * pthread_spin_destroy.c: ...here. + * sysdeps/pthread/pthread_spin_init.c: Move to... + * pthread_spin_init.c: ...here. + * sysdeps/pthread/pthread_spin_unlock.c: Move to... + * pthread_spin_unlock.c: ...here. + * sysdeps/pthread/pthread_getcpuclockid.c: Move to... + * pthread_getcpuclockid.c: ...here. + + * init.c: USE_TLS support is now always enabled. + * tst-tls5.h: Likewise. + * sysdeps/alpha/tls.h: Likewise. + * sysdeps/i386/tls.h: Likewise. + * sysdeps/ia64/tls.h: Likewise. + * sysdeps/powerpc/tls.h: Likewise. + * sysdeps/s390/tls.h: Likewise. + * sysdeps/sh/tls.h: Likewise. + * sysdeps/sparc/tls.h: Likewise. + * sysdeps/x86_64/tls.h: Likewise. + +2006-10-27 Jakub Jelinek + + * sysdeps/unix/sysv/linux/rtld-lowlevel.h (__rtld_mrlock_lock, + __rtld_mrlock_change): Update oldval if atomic compare and exchange + failed. + + * sysdeps/unix/sysv/linux/alpha/sysdep-cancel.h (SINGLE_THREAD_P): + Define to THREAD_SELF->header.multiple_threads. + * sysdeps/unix/sysv/linux/ia64/sysdep-cancel.h (SINGLE_THREAD_P): + Likewise. + * sysdeps/unix/sysv/linux/i386/sysdep-cancel.h (SINGLE_THREAD_P): + Likewise. + * sysdeps/unix/sysv/linux/s390/s390-32/sysdep-cancel.h + (SINGLE_THREAD_P): Likewise. + * sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h + (SINGLE_THREAD_P): Likewise. + * sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h + (SINGLE_THREAD_P): Likewise. + * sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h + (SINGLE_THREAD_P): Likewise. + * sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h (SINGLE_THREAD_P): + Likewise. + * sysdeps/unix/sysv/linux/sparc/sparc32/sysdep-cancel.h + (SINGLE_THREAD_P): Likewise. + * sysdeps/unix/sysv/linux/sparc/sparc64/sysdep-cancel.h + (SINGLE_THREAD_P): Likewise. + * sysdeps/unix/sysv/linux/sh/sysdep-cancel.h (SINGLE_THREAD_P): + Likewise. + +2006-10-26 Jakub Jelinek + + * pthread_attr_setstacksize.c (NEW_VERNUM): Define to GLIBC_2_3_3 + by default rather than 2_3_3. + +2006-10-17 Jakub Jelinek + + * sysdeps/unix/sysv/linux/rtld-lowlevel.h (__rtld_mrlock_lock, + __rtld_mrlock_unlock, __rtld_mrlock_change, __rtld_mrlock_done): Use + atomic_* instead of catomic_* macros. + +2006-10-12 Ulrich Drepper + + [BZ #3285] + * sysdeps/unix/sysv/linux/bits/local_lim.h: Add SEM_VALUE_MAX. + * sysdeps/unix/sysv/linux/powerpc/bits/local_lim.h: Likewise. + * sysdeps/unix/sysv/linux/sparc/bits/local_lim.h: Likewise. + * sysdeps/unix/sysv/linux/alpha/bits/local_lim.h: Likewise. + * sysdeps/unix/sysv/linux/ia64/bits/local_lim.h: Likewise. + * sysdeps/unix/sysv/linux/i386/bits/semaphore.h: Remove SEM_VALUE_MAX. + * sysdeps/unix/sysv/linux/powerpc/bits/semaphore.h: Likewise. + * sysdeps/unix/sysv/linux/x86_64/bits/semaphore.h: Likewise. + * sysdeps/unix/sysv/linux/sparc/bits/semaphore.h: Likewise. + * sysdeps/unix/sysv/linux/alpha/bits/semaphore.h: Likewise. + * sysdeps/unix/sysv/linux/sh/bits/semaphore.h: Likewise. + * sysdeps/unix/sysv/linux/ia64/bits/semaphore.h: Likewise. + * sysdeps/unix/sysv/linux/s390/bits/semaphore.h: Likewise. + +2006-10-11 Ulrich Drepper + + * sysdeps/unix/sysv/linux/i386/sysdep-cancel.h: Add support for + cancelable syscalls with six parameters. + + * sysdeps/unix/sysv/linux/rtld-lowlevel.h: Use catomic_* + operations instead of atomic_*. + +2006-10-09 Ulrich Drepper + + * sysdeps/unix/sysv/linux/rtld-lowlevel.h: New file.. + +2006-10-07 Ulrich Drepper + + * sysdeps/unix/sysv/linux/powerpc/bits/local_lim.h: New file. + * sysdeps/unix/sysv/linux/powerpc/pthread_attr_setstack.c: New file. + * sysdeps/unix/sysv/linux/powerpc/pthread_attr_setstacksize.c: + New file. + * pthread_attr_setstack.c: Allow overwriting the version number of the + new symbol. + * pthread_attr_setstacksize.c: Likewise. + (__old_pthread_attr_setstacksize): If STACKSIZE_ADJUST is defined use + it. + * sysdeps/unix/sysv/linux/powerpc/Versions (libpthread): Add + pthread_attr_setstack and pthread_attr_setstacksize to GLIBC_2.6. + +2006-09-24 Ulrich Drepper + + [BZ #3251] + * descr.h (ENQUEUE_MUTEX_BOTH): Add cast to avoid warning. + Patch by Petr Baudis. + +2006-09-18 Jakub Jelinek + + * tst-kill4.c (do_test): Explicitly set tf thread's stack size. + + * tst-cancel2.c (tf): Loop as long as something was written. + +2006-09-12 Kaz Kojima + + * sysdeps/unix/sysv/linux/sh/pthread_cond_broadcast.S: For PI + mutexes wake all mutexes. + * sysdeps/unix/sysv/linux/sh/pthread_cond_wait.S: Don't increment + WAKEUP_SEQ if this would increase the value beyond TOTAL_SEQ. + * sysdeps/unix/sysv/linux/sh/pthread_cond_timedwait.S: Likewise. + +2006-09-12 Ulrich Drepper + + * tst-cond22.c (tf): Slight changes to the pthread_cond_wait use + to guarantee the thread is always canceled. + +2006-09-08 Jakub Jelinek + + * tst-cond22.c: Include pthread.h instead of pthreadP.h. + Include stdlib.h. + * sysdeps/pthread/pthread_cond_wait.c (__condvar_cleanup): Only + increase FUTEX if increasing WAKEUP_SEQ. Fix comment typo. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S: Likewise. + +2006-09-08 Ulrich Drepper + + [BZ #3123] + * sysdeps/pthread/pthread_cond_wait.c (__condvar_cleanup): Don't + increment WAKEUP_SEQ if this would increase the value beyond TOTAL_SEQ. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S: Likewise. + * Makefile (tests): Add tst-cond22. + * tst-cond22.c: New file. + +2006-09-05 Ulrich Drepper + + [BZ #3124] + * descr.h (struct pthread): Add parent_cancelhandling. + * sysdeps/pthread/createthread.c (create_thread): Pass parent + cancelhandling value to child. + * pthread_create.c (start_thread): If parent thread was canceled + reset the SIGCANCEL mask. + * Makefile (tests): Add tst-cancel25. + * tst-cancel25.c: New file. + +2006-09-05 Jakub Jelinek + Ulrich Drepper + + * sysdeps/pthread/gai_misc.h (GAI_MISC_NOTIFY): Don't decrement + counterp if it is already zero. + * sysdeps/pthread/aio_misc.h (AIO_MISC_NOTIFY): Likewise.. + +2006-03-04 Jakub Jelinek + Roland McGrath + + * sysdeps/unix/sysv/linux/i386/lowlevellock.h + (LLL_STUB_UNWIND_INFO_START, LLL_STUB_UNWIND_INFO_END, + LLL_STUB_UNWIND_INFO_3, LLL_STUB_UNWIND_INFO_4): Define. + (lll_mutex_lock, lll_robust_mutex_lock, lll_mutex_cond_lock, + lll_robust_mutex_cond_lock, lll_mutex_timedlock, + lll_robust_mutex_timedlock, lll_mutex_unlock, + lll_robust_mutex_unlock, lll_lock, lll_unlock): Use them. + Add _L_*_ symbols around the subsection. + * sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S: Add unwind info. + * sysdeps/unix/sysv/linux/i386/i486/lowlevelrobustlock.S: Likewise. + +2006-03-03 Jakub Jelinek + Roland McGrath + + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.h + (LLL_STUB_UNWIND_INFO_START, LLL_STUB_UNWIND_INFO_END, + LLL_STUB_UNWIND_INFO_5, LLL_STUB_UNWIND_INFO_6): Define. + (lll_mutex_lock, lll_robust_mutex_lock, lll_mutex_cond_lock, + lll_robust_mutex_cond_lock, lll_mutex_timedlock, + lll_robust_mutex_timedlock, lll_mutex_unlock, + lll_robust_mutex_unlock, lll_lock, lll_unlock): Use them. + Add _L_*_ symbols around the subsection. + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.S: Add unwind info. + * sysdeps/unix/sysv/linux/x86_64/lowlevelrobustlock.S: Likewise. + +2006-08-31 Ulrich Drepper + + * pthread_rwlock_trywrlock.c (__pthread_rwlock_trywrlock): Undo last + change because it can disturb too much existing code. If real hard + reader preference is needed we'll introduce another type. + * sysdeps/pthread/pthread_rwlock_timedwrlock.c + (pthread_rwlock_timedwrlock): Likewise. + * sysdeps/pthread/pthread_rwlock_wrlock.c (__pthread_rwlock_wrlock): + Likewise. + +2006-08-30 Ulrich Drepper + + * pthread_rwlock_trywrlock.c (__pthread_rwlock_trywrlock): Respect + reader preference. + * sysdeps/pthread/pthread_rwlock_timedwrlock.c + (pthread_rwlock_timedwrlock): Likewise. + * sysdeps/pthread/pthread_rwlock_wrlock.c (__pthread_rwlock_wrlock): + Likewise. + +2006-08-25 Jakub Jelinek + + * sysdeps/unix/sysv/linux/libc_pthread_init.c (freeres_libpthread): + Only define ifdef SHARED. + +2006-08-23 Ulrich Drepper + + * allocatestack.c (queue_stack): Move freeing of surplus stacks to... + (free_stacks): ...here. + (__free_stack_cache): New function. + * pthreadP.h: Declare __free_stack_cache. + * sysdeps/pthread/pthread-functions.h (pthread_functions): Add + ptr_freeres. + * init.c (pthread_functions): Initialize ptr_freeres. + * sysdeps/unix/sysv/linux/libc_pthread_init.c (freeres_libptread): + New freeres function. + +2006-07-30 Joseph S. Myers + + [BZ #3018] + * Makefile (extra-objs): Add modules to extra-test-objs instead. + +2006-08-20 Ulrich Drepper + + * sysdeps/unix/sysv/linux/bits/posix_opt.h: Define + _XOPEN_REALTIME_THREADS. + +2006-08-15 Jakub Jelinek + + * sysdeps/unix/sysv/linux/clock_settime.c (INTERNAL_VSYSCALL): Use + HAVE_CLOCK_GETRES_VSYSCALL as guard macro rather than + HAVE_CLOCK_GETTIME_VSYSCALL. + (maybe_syscall_settime_cpu): Use plain INTERNAL_VSYSCALL here. + +2006-08-14 Jakub Jelinek + + * sysdeps/unix/sysv/linux/bits/posix_opt.h + (_POSIX_THREAD_PRIO_PROTECT): Define to 200112L. + * descr.h (struct priority_protection_data): New type. + (struct pthread): Add tpp field. + * pthreadP.h (PTHREAD_MUTEX_PP_NORMAL_NP, + PTHREAD_MUTEX_PP_RECURSIVE_NP, PTHREAD_MUTEX_PP_ERRORCHECK_NP, + PTHREAD_MUTEX_PP_ADAPTIVE_NP): New enum values. + * pthread_mutex_init.c (__pthread_mutex_init): Handle non-robust + TPP mutexes. + * pthread_mutex_lock.c (__pthread_mutex_lock): Handle TPP mutexes. + * pthread_mutex_trylock.c (__pthread_mutex_trylock): Likewise. + * pthread_mutex_timedlock.c (pthread_mutex_timedlock): Likewise. + * pthread_mutex_unlock.c (__pthread_mutex_unlock_usercnt): Likewise. + * tpp.c: New file. + * pthread_setschedparam.c (__pthread_setschedparam): Handle priority + boosted by TPP. + * pthread_setschedprio.c (pthread_setschedprio): Likewise. + * pthread_mutexattr_getprioceiling.c + (pthread_mutexattr_getprioceiling): If ceiling is 0, ensure it is + in the SCHED_FIFO priority range. + * pthread_mutexattr_setprioceiling.c + (pthread_mutexattr_setprioceiling): Fix prioceiling validation. + * pthread_mutex_getprioceiling.c (pthread_mutex_getprioceiling): Fail + if mutex is not TPP. Ceiling is now in __data.__lock. + * pthread_mutex_setprioceiling.c: Include stdbool.h. + (pthread_mutex_setprioceiling): Fix prioceiling validation. Ceiling + is now in __data.__lock. Add locking. + * pthread_create.c (__free_tcb): Free pd->tpp structure. + * Makefile (libpthread-routines): Add tpp. + (xtests): Add tst-mutexpp1, tst-mutexpp6 and tst-mutexpp10. + * tst-tpp.h: New file. + * tst-mutexpp1.c: New file. + * tst-mutexpp6.c: New file. + * tst-mutexpp10.c: New file. + * tst-mutex1.c (TEST_FUNCTION): Don't redefine if already defined. + * tst-mutex6.c (TEST_FUNCTION): Likewise. + +2006-08-12 Ulrich Drepper + + [BZ #2843] + * pthread_join.c (pthread_join): Account for self being canceled + when checking for deadlocks. + * tst-join5.c: Cleanups. Allow to be used in tst-join6. + (tf1): Don't print anything after pthread_join returns, this would be + another cancellation point. + (tf2): Likewise. + * tst-join6.c: New file. + * Makefile (tests): Add tst-join6. + +2006-08-03 Ulrich Drepper + + [BZ #2892] + * pthread_setspecific.c (__pthread_setspecific): Check + out-of-range index before checking for unused key. + + * sysdeps/pthread/gai_misc.h: New file. + +2006-08-01 Ulrich Drepper + + * sysdeps/unix/sysv/linux/i386/smp.h: New file. Old Linux-specific + file. Don't use sysctl. + * sysdeps/unix/sysv/linux/smp.h: Always assume SMP. Archs can + overwrite the file if this is likely not true. + +2006-07-31 Daniel Jacobowitz + + * allocatestack.c (__reclaim_stacks): Reset the PID on cached stacks. + * Makefile (tests): Add tst-getpid3. + * tst-getpid3.c: New file. + +2006-07-30 Roland McGrath + + * Makefile (libpthread-routines): Add ptw-sigsuspend. + + * sysdeps/unix/sysv/linux/i386/not-cancel.h + (pause_not_cancel): New macro. + (nanosleep_not_cancel): New macro. + (sigsuspend_not_cancel): New macro. + * pthread_mutex_timedlock.c (pthread_mutex_timedlock): Use + nanosleep_not_cancel macro from . + * pthread_mutex_lock.c (__pthread_mutex_lock): Use pause_not_cancel + macro from . + +2006-07-28 Ulrich Drepper + Jakub Jelinek + + * descr.h: Change ENQUEUE_MUTEX and DEQUEUE_MUTEX for bit 0 + notification of PI mutex. Add ENQUEUE_MUTEX_PI. + * pthreadP.h: Define PTHREAD_MUTEX_PI_* macros for PI mutex types. + * pthread_mutex_setprioceilining.c: Adjust for mutex type name change. + * pthread_mutex_init.c: Add support for priority inheritance mutex. + * pthread_mutex_lock.c: Likewise. + * pthread_mutex_timedlock.c: Likewise. + * pthread_mutex_trylock.c: Likewise. + * pthread_mutex_unlock.c: Likewise. + * sysdeps/pthread/pthread_cond_broadcast.c: For PI mutexes wake + all mutexes. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.c: Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.c: Likewise. + * sysdeps/unix/sysv/linux/pthread-pi-defines.sym: New file. + * sysdeps/unix/sysv/linux/Makefile (gen-as-const-header): Add + pthread-pi-defines.sym. + * sysdeps/unix/sysv/linux/i386/lowlevellock.h: Define FUTEX_LOCK_PI, + FUTEX_UNLOCK_PI, and FUTEX_TRYLOCK_PI. + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/alpha/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/ia64/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/powerpc/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/s390/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/sh/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/sparc/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/bits/posix_opt.h: Define + _POSIX_THREAD_PRIO_INHERIT to 200112L. + * tst-mutex1.c: Adjust to allow use in PI mutex test. + * tst-mutex2.c: Likewise. + * tst-mutex3.c: Likewise. + * tst-mutex4.c: Likewise. + * tst-mutex5.c: Likewise. + * tst-mutex6.c: Likewise. + * tst-mutex7.c: Likewise. + * tst-mutex7a.c: Likewise. + * tst-mutex8.c: Likewise. + * tst-mutex9.c: Likewise. + * tst-robust1.c: Likewise. + * tst-robust7.c: Likewise. + * tst-robust8.c: Likewise. + * tst-mutexpi1.c: New file. + * tst-mutexpi2.c: New file. + * tst-mutexpi3.c: New file. + * tst-mutexpi4.c: New file. + * tst-mutexpi5.c: New file. + * tst-mutexpi6.c: New file. + * tst-mutexpi7.c: New file. + * tst-mutexpi7a.c: New file. + * tst-mutexpi8.c: New file. + * tst-mutexpi9.c: New file. + * tst-robust1.c: New file. + * tst-robust2.c: New file. + * tst-robust3.c: New file. + * tst-robust4.c: New file. + * tst-robust5.c: New file. + * tst-robust6.c: New file. + * tst-robust7.c: New file. + * tst-robust8.c: New file. + * Makefile (tests): Add the new tests. + + * pthread_create.c (start_thread): Add some casts to avoid warnings. + * pthread_mutex_destroy.c: Remove unneeded label. + +2006-07-01 Ulrich Drepper + + * pthread_mutex_init.c (__pthread_mutex_init): Move some + computations to compile time. + +2006-06-04 Ulrich Drepper + + * sysdeps/pthread/pthread.h: Add pthread_equal inline version. + +2006-05-15 Ulrich Drepper + + * sysdeps/unix/sysv/linux/fork.h: Mark __fork_handlers as hidden. + +2006-05-11 Ulrich Drepper + + * pthread_key_create.c (__pthread_key_create): Do away with + __pthread_keys_lock. + + * sysdeps/unix/sysv/linux/pthread_setaffinity.c + (__kernel_cpumask_size): Mark as hidden. + * sysdeps/unix/sysv/linux/pthread_attr_setaffinity.c: Likewise. + + * sem_open.c (__sem_mappings_lock): Mark as hidden. + * semaphoreP.h (__sem_mappings_lock): Likewise. + +2006-05-10 Ulrich Drepper + + * pthread_atfork.c: Mark __dso_handle as hidden. + +2006-05-09 Ulrich Drepper + + [BZ #2644] + * sysdeps/pthread/unwind-forcedunwind.c: Different solution for + the reload problem. Change the one path in pthread_cancel_init + which causes the problem. Force gcc to reload. Simplify callers. + * sysdeps/unix/sysv/linux/ia64/unwind-forcedunwind.c + (_Unwind_GetBSP): Undo last patch. + +2006-05-07 Ulrich Drepper + + * sysdeps/unix/sysv/linux/ia64/unwind-forcedunwind.c: Make sure the + function pointer is reloaded after pthread_cancel_init calls. + + [BZ #2644] + * sysdeps/pthread/unwind-forcedunwind.c: Make sure functions + pointers are reloaded after pthread_cancel_init calls. + +2006-05-01 Ulrich Drepper + + * sysdeps/pthread/allocalim.h (__libc_use_alloca): Mark with + __always_inline. + +2006-04-27 Ulrich Drepper + + * sysdeps/unix/sysv/linux/timer_routines.c (timer_helper_thread): + Allocate new object which is passed to timer_sigev_thread so that + the timer can be deleted before the new thread is scheduled. + +2006-04-26 Roland McGrath + + * sysdeps/x86_64/tls.h: Include inside [! __ASSEMBLER__]. + +2006-04-08 Ulrich Drepper + + * sysdeps/unix/sysv/linux/i386/lowlevellock.h: Remove branch predicion + suffix for conditional jumps. + * sysdeps/unix/sysv/linux/i386/i486/sem_trywait.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/libc-lowlevellock.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_barrier_wait.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/sem_wait.S: Likewise. + + * init.c (sigcancel_handler): Compare with correct PID even if the + thread is in the middle of a fork call. + (sighandler_setxid): Likewise. + Reported by Suzuki K P . + +2006-04-07 Jakub Jelinek + + * pthreadP.h (FUTEX_TID_MASK): Sync with kernel. + +2006-04-06 Ulrich Drepper + + * pthread_getattr_np.c (pthread_getattr_np): Close fp if getrlimit + fails [Coverity CID 105]. + +2006-04-05 Ulrich Drepper + + * sysdeps/pthread/pthread.h: Add nonnull attributes. + +2006-04-03 Steven Munroe + + [BZ #2505] + * sysdeps/unix/sysv/linux/powerpc/lowlevellock.h [_ARCH_PWR4]: + Define __lll_rel_instr using lwsync. + +2006-03-27 Ulrich Drepper + + * allocatestack.c (allocate_stack): Always initialize robust_head. + * descr.h: Define struct robust_list_head. + (struct pthread): Use robust_list_head in robust mutex list definition. + Adjust ENQUEUE_MUTEX and DEQUEUE_MUTEX. + * init.c [!__ASSUME_SET_ROBUST_LIST] (__set_robust_list_avail): Define. + (__pthread_initialize_minimal_internal): Register robust_list with + the kernel. + * pthreadP.h: Remove PRIVATE_ from PTHREAD_MUTEX_ROBUST_* names. + Declare __set_robust_list_avail. + * pthread_create.c (start_thread): Register robust_list of new thread. + [!__ASSUME_SET_ROBUST_LIST]: If robust_list is not empty wake up + waiters. + * pthread_mutex_destroy.c: For robust mutexes don't look at the + number of users, it's unreliable. + * pthread_mutex_init.c: Allow use of pshared robust mutexes if + set_robust_list syscall is available. + * pthread_mutex_consistent.c: Adjust for PTHREAD_MUTEX_ROBUST_* rename. + * pthread_mutex_lock.c: Simplify robust mutex code a bit. + Set robust_head.list_op_pending before trying to lock a robust mutex. + * pthread_mutex_timedlock.c: Likewise. + * pthread_mutex_trylock.c: Likewise. + * pthread_mutex_unlock.c: Likewise for unlocking. + * Makefile (tests): Add tst-robust8. + * tst-robust8.c: New file. + +2006-03-08 Andreas Schwab + + * sysdeps/unix/sysv/linux/ia64/dl-sysdep.h + (DL_SYSINFO_IMPLEMENTATION): Add missing newline. + +2006-03-05 Roland McGrath + + * configure (libc_add_on): Disable add-on when $add_ons_automatic = yes + and $config_os doesn't match *linux*. + +2006-03-05 David S. Miller + + * sysdeps/unix/sysv/linux/sparc/sparc32/pt-vfork.S: + Use __syscall_error. + * sysdeps/unix/sysv/linux/sparc/sparc32/sysdep-cancel.h: Likewise. + * sysdeps/unix/sysv/linux/sparc/sparc32/vfork.S: Likewise. + * sysdeps/unix/sysv/linux/sparc/sparc64/pt-vfork.S: Likewise. + * sysdeps/unix/sysv/linux/sparc/sparc64/sysdep-cancel.h: Likewise. + * sysdeps/unix/sysv/linux/sparc/sparc64/vfork.S: Likewise. + * sysdeps/unix/sysv/linux/sparc/Makefile: New file. + +2006-03-02 Ulrich Drepper + + * sysdeps/unix/sysv/linux/aio_misc.h: Various cleanups. + +2006-03-01 Ulrich Drepper + + * sysdeps/unix/sysv/linux/x86_64/lowlevelrobustlock.S + (__lll_robust_lock_wait): Also set FUTEX_WAITERS bit if we got the + mutex. + (__lll_robust_timedlock_wait): Likewise. + * sysdeps/unix/sysv/linux/i386/i486/lowlevelrobustlock.S + (__lll_robust_lock_wait): Likewise. + (__lll_robust_timedlock_wait): Likewise. + * sysdeps/unix/sysv/linux/lowlevelrobustlock.c + (__lll_robust_lock_wait): Likewise. + (__lll_robust_timedlock_wait): Likewise. + +2006-03-01 Jakub Jelinek + + * sysdeps/unix/sysv/linux/sparc/lowlevellock.h (lll_robust_mutex_dead, + lll_robust_mutex_trylock, lll_robust_mutex_lock, + lll_robust_mutex_cond_lock, lll_robust_mutex_timedlock, + lll_robust_mutex_unlock): Define. + (__lll_robust_lock_wait, __lll_robust_timedlock_wait): New prototypes. + +2006-02-28 H.J. Lu + + * sysdeps/unix/sysv/linux/ia64/clone2.S: Include + instead of . + +2006-02-27 Jakub Jelinek + + * Makefile (libpthread-routines): Add + pthread_mutexattr_[sg]etprotocol, pthread_mutexattr_[sg]etprioceiling + and pthread_mutex_[sg]etprioceiling. + * Versions (GLIBC_2.4): Export pthread_mutexattr_getprotocol, + pthread_mutexattr_setprotocol, pthread_mutexattr_getprioceiling, + pthread_mutexattr_setprioceiling, pthread_mutex_getprioceiling and + pthread_mutex_setprioceiling. + * sysdeps/pthread/pthread.h (PTHREAD_PRIO_NONE, PTHREAD_PRIO_INHERIT, + PTHREAD_PRIO_PROTECT): New enum values. + (pthread_mutexattr_getprotocol, pthread_mutexattr_setprotocol, + pthread_mutexattr_getprioceiling, pthread_mutexattr_setprioceiling, + pthread_mutex_getprioceiling, pthread_mutex_setprioceiling): New + prototypes. + * pthreadP.h (PTHREAD_MUTEX_PRIO_INHERIT_PRIVATE_NP, + PTHREAD_MUTEX_PRIO_PROTECT_PRIVATE_NP): New enum values. + (PTHREAD_MUTEX_PRIO_CEILING_SHIFT, PTHREAD_MUTEX_PRIO_CEILING_MASK): + Define. + (PTHREAD_MUTEXATTR_PROTOCOL_SHIFT, PTHREAD_MUTEXATTR_PROTOCOL_MASK, + PTHREAD_MUTEXATTR_PRIO_CEILING_SHIFT, + PTHREAD_MUTEXATTR_PRIO_CEILING_MASK): Define. + (PTHREAD_MUTEXATTR_FLAG_BITS): Or in PTHREAD_MUTEXATTR_PROTOCOL_MASK + and PTHREAD_MUTEXATTR_PRIO_CEILING_MASK. + * pthread_mutex_init.c (__pthread_mutex_init): For the time being + return ENOTSUP for PTHREAD_PRIO_INHERIT or PTHREAD_PRIO_PROTECT + protocol mutexes. + * pthread_mutex_getprioceiling.c: New file. + * pthread_mutex_setprioceiling.c: New file. + * pthread_mutexattr_getprioceiling.c: New file. + * pthread_mutexattr_setprioceiling.c: New file. + * pthread_mutexattr_getprotocol.c: New file. + * pthread_mutexattr_setprotocol.c: New file. + +2006-02-27 Daniel Jacobowitz + + * sysdeps/unix/sysv/linux/aio_misc.h: Include . + +2006-02-27 Roland McGrath + + * sysdeps/pthread/Subdirs: List nptl here too. + * configure (libc_add_on_canonical): New variable. + + * sysdeps/unix/sysv/linux/sh/sh4/lowlevellock.h: Use #include_next. + + * sysdeps/unix/sysv/linux/sleep.c: Use #include_next after #include of + self to get main source tree's file. + * sysdeps/unix/sysv/linux/alpha/clone.S: Likewise. + * sysdeps/unix/sysv/linux/i386/clone.S: Likewise. + * sysdeps/unix/sysv/linux/i386/vfork.S: Likewise. + * sysdeps/unix/sysv/linux/ia64/clone2.S: Likewise. + * sysdeps/unix/sysv/linux/powerpc/powerpc32/clone.S: Likewise. + * sysdeps/unix/sysv/linux/powerpc/powerpc64/clone.S: Likewise. + * sysdeps/unix/sysv/linux/s390/s390-32/clone.S: Likewise. + * sysdeps/unix/sysv/linux/s390/s390-64/clone.S: Likewise. + * sysdeps/unix/sysv/linux/sh/clone.S: Likewise. + * sysdeps/unix/sysv/linux/sparc/sparc32/clone.S: Likewise. + * sysdeps/unix/sysv/linux/sparc/sparc64/clone.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/clone.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/vfork.S: Likewise. + + * Makefile: Use $(sysdirs) in vpath directive. + + * sysdeps/pthread/Makefile (CFLAGS-libc-start.c): Variable removed. + (CPPFLAGS-timer_routines.c): Likewise. + + * Makeconfig (includes): Variable removed. + +2006-02-26 Roland McGrath + + * sysdeps/generic/pt-raise.c: Moved to ... + * pt-raise.c: ... here. + * sysdeps/generic/lowlevellock.h: Moved to ... + * lowlevellock.h: ... here. + +2006-02-23 Roland McGrath + + * descr.h (struct pthread): Add final member `end_padding'. + (PTHREAD_STRUCT_END_PADDING): Use it. + +2006-02-20 Roland McGrath + + * sysdeps/mips: Directory removed, saved in ports repository. + * sysdeps/unix/sysv/linux/mips: Likewise. + +2006-02-18 Ulrich Drepper + + * tst-robust1.c: Add second mutex to check that the mutex list is + handled correctly. + +2006-02-17 Jakub Jelinek + + * sysdeps/unix/sysv/linux/alpha/lowlevellock.h (lll_robust_mutex_dead, + lll_robust_mutex_trylock, lll_robust_mutex_lock, + lll_robust_mutex_cond_lock, lll_robust_mutex_timedlock, + lll_robust_mutex_unlock): New macros. + (__lll_robust_lock_wait, __lll_robust_timedlock_wait): New prototypes. + * sysdeps/unix/sysv/linux/s390/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/powerpc/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/ia64/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/lowlevelrobustlock.c: New file. + +2006-02-17 Kaz Kojima + + * sysdeps/unix/sysv/linux/sh/lowlevellock.h: Add lll_robust_mutex_* + definitions. + * sysdeps/unix/sysv/linux/sh/lowlevelrobustlock.S: New file. + +2006-02-17 Ulrich Drepper + + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.h + (lll_robust_mutex_unlock): Avoid unnecessary wakeups. + * sysdeps/unix/sysv/linux/i386/lowlevellock.h + (lll_robust_mutex_unlock): Likewise. + +2006-02-13 Jakub Jelinek + + * descr.h [!__PTHREAD_MUTEX_HAVE_PREV] (DEQUEUE_MUTEX): + Set robust_list.__next rather than robust_list. + * sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h + (__pthread_list_t): New typedef. + (pthread_mutex_t): Replace __next and __prev fields with __list. + * sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h + (__pthread_list_t): New typedef. + (pthread_mutex_t): Replace __next and __prev fields with __list. + * sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h + (__pthread_list_t, __pthread_slist_t): New typedefs. + (pthread_mutex_t): Replace __next and __prev fields with __list. + * sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h + (__pthread_list_t, __pthread_slist_t): New typedefs. + (pthread_mutex_t): Replace __next and __prev fields with __list. + * sysdeps/unix/sysv/linux/sparc/bits/pthreadtypes.h + (__pthread_list_t, __pthread_slist_t): New typedefs. + (pthread_mutex_t): Replace __next and __prev fields with __list. + * sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h + (__pthread_slist_t): New typedef. + (pthread_mutex_t): Replace __next field with __list. + +2006-02-15 Ulrich Drepper + + * pthreadP.h: Define PTHREAD_MUTEX_INCONSISTENT instead of + PTHREAD_MUTEX_OWNERDEAD. + (PTHREAD_MUTEX_ROBUST_PRIVATE_NP): Define as 16, not 256. + Define FUTEX_WAITERS, FUTEX_OWNER_DIED, FUTEX_TID_MASK. + * Makefile (libpthread-routines): Add lowlevelrobustlock. + * pthread_create.c (start_thread): Very much simplify robust_list loop. + * pthread_mutex_consistent.c: Inconsistent mutex have __owner now set + to PTHREAD_MUTEX_INCONSISTENT. + * pthread_mutex_destroy.c: Allow destroying of inconsistent mutexes. + * pthread_mutex_lock.c: Reimplement robust mutex handling. + * pthread_mutex_trylock.c: Likewise. + * pthread_mutex_timedlock.c: Likewise. + * pthread_mutex_unlock.c: Likewise. + * sysdeps/unix/sysv/linux/pthread_mutex_cond_lock.c: Likewise. + * sysdeps/unix/sysv/linux/Makefile (gen-as-const-headers): Add + lowlevelrobustlock.sym. + * sysdeps/unix/sysv/linux/lowlevelrobustlock.sym: New file. + * sysdeps/unix/sysv/linux/i386/lowlevellock.h: Add lll_robust_mutex_* + definitions. + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/lowlevelrobustlock.S: New file. + * sysdeps/unix/sysv/linux/i386/i586/lowlevelrobustlock.S: New file. + * sysdeps/unix/sysv/linux/i386/i686/lowlevelrobustlock.S: New file. + * sysdeps/unix/sysv/linux/x86_64/lowlevelrobustlock.S: New file. + +2006-02-12 Ulrich Drepper + + * allocatestack.c (allocate_stack): Initialize robust_list. + * init.c (__pthread_initialize_minimal_internal): Likewise. + * descr.h (struct xid_command): Pretty printing. + (struct pthread): Use __pthread_list_t or __pthread_slist_t for + robust_list. Adjust macros. + * pthread_create.c (start_thread): Adjust robust_list handling. + * phtread_mutex_unlock.c: Don't allow unlocking from any thread + but the owner for all robust mutex types. + * sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h: Define + __pthread_list_t and __pthread_slist_t. Use them in pthread_mutex_t. + * sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h: Likewise. + * sysdeps/pthread/pthread.h: Adjust mutex initializers. + + * sysdeps/unix/sysv/linux/i386/not-cancel.h: Define openat_not_cancel, + openat_not_cancel_3, openat64_not_cancel, and openat64_not_cancel_3. + +2006-02-08 Jakub Jelinek + + * sysdeps/unix/sysv/linux/i386/lowlevellock.h (lll_futex_wait, + lll_futex_timedwait, lll_wait_tid): Add "memory" clobber. + +2006-01-20 Kaz Kojima + + * sysdeps/unix/sysv/linux/sh/lowlevellock.h (lll_futex_wait): + Return status. + (lll_futex_timed_wait): Define. + +2006-01-19 Ulrich Drepper + + * tst-cancel4.c: Test ppoll. + +2006-01-18 Andreas Jaeger + + [BZ #2167] + * sysdeps/unix/sysv/linux/mips/bits/pthreadtypes.h + (pthread_mutex_t): Follow changes for other archs. Based on patch + by Jim Gifford . + +2006-01-13 Richard Henderson + + * sysdeps/alpha/tls.h (tcbhead_t): Rename member to __private. + +2006-01-10 Roland McGrath + + * sysdeps/alpha/jmpbuf-unwind.h: File moved to main source tree. + * sysdeps/i386/jmpbuf-unwind.h: Likewise. + * sysdeps/mips/jmpbuf-unwind.h: Likewise. + * sysdeps/powerpc/jmpbuf-unwind.h: Likewise. + * sysdeps/s390/jmpbuf-unwind.h: Likewise. + * sysdeps/sh/jmpbuf-unwind.h: Likewise. + * sysdeps/sparc/sparc32/jmpbuf-unwind.h: Likewise. + * sysdeps/sparc/sparc64/jmpbuf-unwind.h: Likewise. + * sysdeps/x86_64/jmpbuf-unwind.h: Likewise. + * sysdeps/unix/sysv/linux/ia64/jmpbuf-unwind.h: Likewise. + +2006-01-09 Roland McGrath + + * tst-initializers1-c89.c: New file. + * tst-initializers1-c99.c: New file. + * tst-initializers1-gnu89.c: New file. + * tst-initializers1-gnu99.c: New file. + * Makefile (tests): Add them. + (CFLAGS-tst-initializers1-c89.c): New variable. + (CFLAGS-tst-initializers1-c99.c): New variable. + (CFLAGS-tst-initializers1-gnu89.c): New variable. + (CFLAGS-tst-initializers1-gnu99.c): New variable. + + * sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h (pthread_mutex_t): + Use __extension__ on anonymous union definition. + * sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/sparc/bits/pthreadtypes.h: Likewise. + +2006-01-08 Jakub Jelinek + + * sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h (pthread_mutex_t): + Don't give the union a name because it changes the mangled name. + Instead name the struct for __data. + * sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h (pthread_mutex_t): + Likewise. + * sysdeps/unix/sysv/linux/sparc/bits/pthreadtypes.h (pthread_mutex_t): + Likewise. + +2006-01-09 Jakub Jelinek + + * sysdeps/sparc/sparc64/jmpbuf-unwind.h (_JMPBUF_UNWINDS_ADJ): Add + stack bias to mc_ftp field. + +2006-01-07 Ulrich Drepper + + * sysdeps/pthread/aio_misc.h (AIO_MISC_WAIT): Work around gcc + being too clever and reloading the futex value where it shouldn't. + +2006-01-06 Ulrich Drepper + + * descr.h [!__PTHREAD_MUTEX_HAVE_PREV] (DEQUEUE_MUTEX): Use + correct type. + +2006-01-06 Jakub Jelinek + + * sysdeps/unix/sysv/linux/sparc/sparc64/sysdep-cancel.h (PSEUDO): + Add cfi directives. + +2006-01-06 Ulrich Drepper + + * sysdeps/ia64/tls.h (tcbhead_t): Rename private member to __private. + * sysdeps/ia64/tcb-offsets.sym: Adjust for private->__private + rename in tcbhead_t. + + * sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h (pthread_mutex_t): + Don't give the union a name because it changes the mangled name. + Instead name the struct for __data. + * sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h: Likewise. + * pthread_create.c (start_thread): Adjust robust mutex free loop. + * descr.h (ENQUEUE_MUTEX, DEQUEUE_MUTEX): Adjust. + +2006-01-05 Ulrich Drepper + + * sysdeps/unix/sysv/linux/i386/lowlevellock.h (lll_futex_wait): + Return status. + (lll_futex_timed_wait): Define. + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.h: Likewise. + * sysdeps/pthread/aio_misc.h: New file. + +2006-01-03 Joseph S. Myers + + * Makefile ($(objpfx)$(multidir)): Use mkdir -p. + +2006-01-03 Steven Munroe + + * sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h + (PSEUDO): Remove redundant cfi_startproc and cfi_endproc directives. + * sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h: Likewise. + +2006-01-04 Ulrich Drepper + + * tst-cancel24.cc: Use C headers instead of C++ headers. + +2006-01-03 Jakub Jelinek + + * sysdeps/unix/sysv/linux/sparc/lowlevellock.h: Remove #error for + sparc-linux configured glibc. + (lll_futex_wake_unlock): Define to 1 for sparc-linux configured glibc. + (__lll_mutex_trylock, __lll_mutex_cond_trylock, __lll_mutex_lock, + __lll_mutex_cond_lock, __lll_mutex_timedlock): Use + atomic_compare_and_exchange_val_24_acq instead of + atomic_compare_and_exchange_val_acq. + (lll_mutex_unlock, lll_mutex_unlock_force): Use atomic_exchange_24_rel + instead of atomic_exchange_rel. + * sysdeps/unix/sysv/linux/sparc/sparc32/lowlevellock.c: New file. + * sysdeps/unix/sysv/linux/sparc/sparc32/pthread_barrier_init.c: New + file. + * sysdeps/unix/sysv/linux/sparc/sparc32/pthread_barrier_wait.c: New + file. + * sysdeps/unix/sysv/linux/sparc/sparc32/sem_init.c: New file. + * sysdeps/unix/sysv/linux/sparc/sparc32/sem_post.c: New file. + * sysdeps/unix/sysv/linux/sparc/sparc32/sem_timedwait.c: New file. + * sysdeps/unix/sysv/linux/sparc/sparc32/sem_trywait.c: New file. + * sysdeps/unix/sysv/linux/sparc/sparc32/sem_wait.c: New file. + * sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/pthread_barrier_init.c: + New file. + * sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/pthread_barrier_wait.c: + New file. + * sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_init.c: New file. + * sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_post.c: New file. + * sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_timedwait.c: New + file. + * sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_trywait.c: New + file. + * sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/sem_wait.c: New file. + +2006-01-03 Ulrich Drepper + + * sysdeps/pthread/pthread.h [__WORDSIZE==64]: Don't use cast in + mutex initializers. + +2006-01-02 Jakub Jelinek + + * sysdeps/sparc/tls.h (tcbhead_t): Add pointer_guard field. + (THREAD_GET_POINTER_GUARD, THREAD_SET_POINTER_GUARD, + THREAD_COPY_POINTER_GUARD): Define. + * sysdeps/sparc/tcb-offsets.sym (POINTER_GUARD): Define. + * sysdeps/sparc/sparc64/jmpbuf-unwind.h: Revert 2005-12-27 changes. + +2006-01-01 Ulrich Drepper + + * version.c: Update copyright year. + +2005-12-29 Kaz Kojima + + * sysdeps/unix/sysv/linux/sh/sysdep-cancel.h: Remove explicit + .eh_frame section, use cfi_* directives. + * sysdeps/unix/sysv/linux/sh/lowlevellock.S: Add cfi instrumentation. + +2005-12-30 Ulrich Drepper + + * sysdeps/unix/sysv/linux/ia64/jmpbuf-unwind.h: Undo last change for + now. + +2005-12-29 Ulrich Drepper + + * sysdeps/pthread/sigaction.c: Removed. + * sigaction.c: New file. + * sysdeps/unix/sysv/linux/Makefile: Define CFLAGS-sigaction.c. + +2005-12-28 Ulrich Drepper + + * Makefile (tests): Add tst-signal7. + * tst-signal7.c: New file. + +2005-12-27 Roland McGrath + + * sysdeps/x86_64/jmpbuf-unwind.h (_jmpbuf_sp): New inline function. + (_JMPBUF_UNWINDS_ADJ): Use it, to PTR_DEMANGLE before comparison. + * sysdeps/alpha/jmpbuf-unwind.h: Likewise. + * sysdeps/i386/jmpbuf-unwind.h: Likewise. + * sysdeps/mips/jmpbuf-unwind.h: Likewise. + * sysdeps/powerpc/jmpbuf-unwind.h: Likewise. + * sysdeps/s390/jmpbuf-unwind.h: Likewise. + * sysdeps/sh/jmpbuf-unwind.h: Likewise. + * sysdeps/sparc/sparc32/jmpbuf-unwind.h: Likewise. + * sysdeps/sparc/sparc64/jmpbuf-unwind.h: Likewise. + * sysdeps/unix/sysv/linux/ia64/jmpbuf-unwind.h: Likewise. + +2005-12-27 Jakub Jelinek + + * sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h: Add __next + and __prev field to pthread_mutex_t. + * sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/sparc/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h: Add __next field + to pthread_mutex_t. + +2005-12-26 Ulrich Drepper + + * pthreadP.h: Define PTHREAD_MUTEX_ROBUST_PRIVATE_NP, + PTHREAD_MUTEX_ROBUST_PRIVATE_RECURSIVE_NP, + PTHREAD_MUTEX_ROBUST_PRIVATE_ERRORCHECK_NP, + PTHREAD_MUTEX_ROBUST_PRIVATE_ADAPTIVE_NP, + PTHREAD_MUTEXATTR_FLAG_ROBUST, PTHREAD_MUTEXATTR_FLAG_PSHARED, + and PTHREAD_MUTEXATTR_FLAG_BITS. + * descr.h (struct pthread): Add robust_list field and define + ENQUEUE_MUTEX and DEQUEUE_MUTEX macros. + * pthread_mutexattr_getrobust.c: New file. + * pthread_mutexattr_setrobust.c: New file. + * pthread_mutex_consistent.c: New file. + * sysdeps/pthread/pthread.h: Declare pthread_mutexattr_getrobust, + pthread_mutexattr_setrobust, and pthread_mutex_consistent. + Define PTHREAD_MUTEX_STALLED_NP and PTHREAD_MUTEX_ROBUST_NP. + Adjust pthread_mutex_t initializers. + * nptl/sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h: Add __next + field to pthread_mutex_t. + * nptl/sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h: Add __next + and __prev field to pthread_mutex_t. + * Versions [GLIBC_2.4]: Export pthread_mutexattr_getrobust_np, + pthread_mutexattr_setrobust_np, and pthread_mutex_consistent_np. + * pthread_mutexattr_getpshared.c: Use PTHREAD_MUTEXATTR_FLAG_PSHARED + and PTHREAD_MUTEXATTR_FLAG_BITS macros instead of magic numbers. + * pthread_mutexattr_gettype.c: Likewise. + * pthread_mutexattr_setpshared.c: Likewise. + * pthread_mutexattr_settype.c: Likewise. + * pthread_mutex_init.c: Reject robust+pshared attribute for now. + Initialize mutex kind according to robust flag. + * pthread_mutex_lock.c: Implement local robust mutex. + * pthread_mutex_timedlock.c: Likewise. + * pthread_mutex_trylock.c: Likewise. + * pthread_mutex_unlock.c: Likewise. + * pthread_create.c (start_thread): Mark robust mutexes which remained + locked as dead. + * tst-robust1.c: New file. + * tst-robust2.c: New file. + * tst-robust3.c: New file. + * tst-robust4.c: New file. + * tst-robust5.c: New file. + * tst-robust6.c: New file. + * tst-robust7.c: New file. + * Makefile (libpthread-routines): Add pthread_mutexattr_getrobust, + pthread_mutexattr_setrobust, and pthread_mutex_consistent. + (tests): Add tst-robust1, tst-robust2, tst-robust3, tst-robust4, + tst-robust5, tst-robust6, and tst-robust7. + + * tst-typesizes.c: New file. + * Makefile (tests): Add tst-typesizes. + + * tst-once3.c: More debug output. + +2005-12-24 Ulrich Drepper + + * pthread_mutex_trylock.c (__pthread_mutex_trylock): Add break + missing after last change. + + * version.c: Update copyright year. + +2005-12-23 Ulrich Drepper + + * pthread_mutex_destroy.c: Set mutex type to an invalid value. + * pthread_mutex_lock.c: Return EINVAL for invalid mutex type. + * pthread_mutex_trylock.c: Likewise. + * pthread_mutex_timedlock.c: Likewise. + * pthread_mutex_unlock.c: Likewise. + +2005-12-22 Roland McGrath + + * sysdeps/pthread/sigaction.c: Use "" instead of <> to include self, + so that #include_next's search location is not reset to the -I.. + directory where can be found. + +2005-12-22 Ulrich Drepper + + [BZ #1913] + * sysdeps/unix/sysv/linux/i386/i486/sem_wait.S (__new_sem_wait): + Fix unwind info. Remove useless branch prediction prefix. + * tst-cancel24.cc: New file. + * Makefile: Add rules to build and run tst-cancel24. + +2005-12-21 Roland McGrath + + * libc-cancellation.c: Use <> rather than "" #includes. + * pt-cleanup.c: Likewise. + * pthread_create.c: Likewise. + * pthread_join.c: Likewise. + * pthread_timedjoin.c: Likewise. + * pthread_tryjoin.c: Likewise. + * sysdeps/unix/sysv/linux/libc_pthread_init.c: Likewise. + * sysdeps/unix/sysv/linux/register-atfork.c: Likewise. + * sysdeps/unix/sysv/linux/unregister-atfork.c: Likewise. + * unwind.c: Likewise. + +2005-12-19 Kaz Kojima + + * sysdeps/sh/tcb-offsets.sym: Add POINTER_GUARD. + * sysdeps/sh/tls.h (tcbhead_t): Remove private and add pointer_guard. + (THREAD_GET_POINTER_GUARD, THREAD_SET_POINTER_GUARD, + THREAD_COPY_POINTER_GUARD): Define. + +2005-12-19 Jakub Jelinek + + * sysdeps/ia64/tls.h (TLS_PRE_TCB_SIZE): Make room for 2 uintptr_t's + rather than one. + (THREAD_GET_POINTER_GUARD, THREAD_SET_POINTER_GUARD, + THREAD_COPY_POINTER_GUARD): Define. + * sysdeps/powerpc/tcb-offsets.sym (POINTER_GUARD): Add. + * sysdeps/powerpc/tls.h (tcbhead_t): Add pointer_guard field. + (THREAD_GET_POINTER_GUARD, THREAD_SET_POINTER_GUARD, + THREAD_COPY_POINTER_GUARD): Define. + * sysdeps/s390/tcb-offsets.sym (STACK_GUARD): Add. + * sysdeps/s390/tls.h (THREAD_GET_POINTER_GUARD, + THREAD_SET_POINTER_GUARD, THREAD_COPY_POINTER_GUARD): Define. + * sysdeps/unix/sysv/linux/ia64/__ia64_longjmp.S (__ia64_longjmp): + Use PTR_DEMANGLE for B0 if defined. + +2005-12-17 Ulrich Drepper + + * pthread_create.c (__pthread_create_2_1): Use + THREAD_COPY_POINTER_GUARD if available. + * sysdeps/i386/tcb-offsets.sym: Add POINTER_GUARD. + * sysdeps/x86_64/tcb-offsets.sym: Likewise. + * sysdeps/i386/tls.h (tcbhead_t): Add pointer_guard. + Define THREAD_SET_POINTER_GUARD and THREAD_COPY_POINTER_GUARD. + * sysdeps/x86_64/tls.h: Likewise. + +2005-12-15 Roland McGrath + + * sysdeps/unix/sysv/linux/mq_notify.c: Don't use sysdeps/generic. + +2005-12-13 Ulrich Drepper + + * sysdeps/pthread/sigfillset.c: Adjust for files moved out of + sysdeps/generic. + * errno-loc.c: New file. + +2005-12-12 Roland McGrath + + * init.c (__pthread_initialize_minimal_internal): Do __static_tls_size + adjustments before choosing stack size. Update minimum stack size + calculation to match allocate_stack change. + +2005-12-12 Ulrich Drepper + + * allocatestack.c (allocate_stack): Don't demand that there is an + additional full page available on the stack beside guard, TLS, the + minimum stack. + +2005-11-24 Ulrich Drepper + + * sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h + (__cleanup_fct_attribute): Use __regparm__ not regparm. + + * sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h: When + compiling 32-bit code we must define __cleanup_fct_attribute. + +005-11-24 Jakub Jelinek + + [BZ #1920] + * sysdeps/pthread/pthread.h (__pthread_unwind_next): Use + __attribute__ instead of __attribute. + * sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h + (__cleanup_fct_attribute): Likewise. + +2005-11-17 Jakub Jelinek + + * sysdeps/pthread/unwind-forcedunwind.c (pthread_cancel_init): Put + a write barrier before writing libgcc_s_getcfa. + +2005-11-06 Ulrich Drepper + + * sysdeps/unix/sysv/linux/configure: Removed. + +2005-11-05 Ulrich Drepper + + * sysdeps/unix/sysv/linux/ia64/pt-initfini.c: Remove trace of + optional init_array/fini_array support. + +2005-10-24 Roland McGrath + + * sysdeps/unix/sysv/linux/x86_64/sem_trywait.S: Remove unnecessary + versioned_symbol use. + +2005-10-16 Roland McGrath + + * init.c (__pthread_initialize_minimal_internal): Even when using a + compile-time default stack size, apply the minimum that allocate_stack + will require, and round up to page size. + +2005-10-10 Daniel Jacobowitz + + * Makefile ($(test-modules)): Remove static pattern rule. + +2005-10-14 Jakub Jelinek + Ulrich Drepper + + * sysdeps/unix/sysv/linux/x86_64/pthread_once.S: Fix stack + alignment in callback function. + * Makefile: Add rules to build and run tst-align3. + * tst-align3.c: New file. + +2005-10-03 Jakub Jelinek + + * allocatestack.c (setxid_signal_thread): Add + INTERNAL_SYSCALL_DECL (err). + +2005-10-02 Jakub Jelinek + + * allocatestack.c (setxid_signal_thread): Need to use + atomic_compare_and_exchange_bool_acq. + +2005-10-01 Ulrich Drepper + Jakub Jelinek + + * descr.h: Define SETXID_BIT and SETXID_BITMASK. Adjust + CANCEL_RESTMASK. + (struct pthread): Move specific_used field to avoid padding. + Add setxid_futex field. + * init.c (sighandler_setxid): Reset setxid flag and release the + setxid futex. + * allocatestack.c (setxid_signal_thread): New function. Broken + out of the bodies of the two loops in __nptl_setxid. For undetached + threads check whether they are exiting and if yes, don't send a signal. + (__nptl_setxid): Simplify loops by using setxid_signal_thread. + * pthread_create.c (start_thread): For undetached threads, check + whether setxid bit is set. If yes, wait until signal has been + processed. + + * allocatestack.c (STACK_VARIABLES): Initialize them. + * pthread_create.c (__pthread_create_2_1): Initialize pd. + +2004-09-02 Jakub Jelinek + + * pthread_cond_destroy.c (__pthread_cond_destroy): If there are + waiters, awake all waiters on the associated mutex. + +2005-09-22 Roland McGrath + + * perf.c [__x86_64__] (HP_TIMING_NOW): New macro (copied from + ../sysdeps/x86_64/hp-timing.h). + +2005-08-29 Jakub Jelinek + + * sysdeps/unix/sysv/linux/powerpc/lowlevellock.h (FUTEX_WAKE_OP, + FUTEX_OP_CLEAR_WAKE_IF_GT_ONE): Define. + (lll_futex_wake_unlock): Define. + * sysdeps/unix/sysv/linux/alpha/lowlevellock.h (FUTEX_WAKE_OP, + FUTEX_OP_CLEAR_WAKE_IF_GT_ONE): Define. + (lll_futex_wake_unlock): Define. + * sysdeps/unix/sysv/linux/ia64/lowlevellock.h (FUTEX_WAKE_OP, + FUTEX_OP_CLEAR_WAKE_IF_GT_ONE): Define. + (lll_futex_wake_unlock): Define. + * sysdeps/unix/sysv/linux/s390/lowlevellock.h (FUTEX_WAKE_OP, + FUTEX_OP_CLEAR_WAKE_IF_GT_ONE): Define. + (lll_futex_wake_unlock): Define. + * sysdeps/unix/sysv/linux/sparc/lowlevellock.h (FUTEX_WAKE_OP, + FUTEX_OP_CLEAR_WAKE_IF_GT_ONE): Define. + (lll_futex_wake_unlock): Define. + * sysdeps/pthread/pthread_cond_signal.c (__pthread_cond_signal): Use + lll_futex_wake_unlock. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_signal.S + (FUTEX_WAKE_OP, FUTEX_OP_CLEAR_WAKE_IF_GT_ONE): Define. + (__pthread_cond_signal): Use FUTEX_WAKE_OP. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.S + (FUTEX_WAKE_OP, FUTEX_OP_CLEAR_WAKE_IF_GT_ONE): Define. + (__pthread_cond_signal): Use FUTEX_WAKE_OP. + +2005-09-05 Kaz Kojima + + * sysdeps/unix/sysv/linux/sh/lowlevellock.S (__lll_mutex_lock_wait): + Fix typo in register name. + +2005-08-23 Ulrich Drepper + + * sysdeps/unix/sysv/linux/timer_routines.c (timer_helper_thread): + Use __sigfillset. Document that sigfillset does the right thing wrt + to SIGSETXID. + +2005-07-11 Jakub Jelinek + + [BZ #1102] + * sysdeps/pthread/pthread.h (PTHREAD_MUTEX_INITIALIZER, + PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP, + PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP, + PTHREAD_MUTEX_ADAPTIVE_NP, PTHREAD_RWLOCK_INITIALIZER, + PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP, + PTHREAD_COND_INITIALIZER): Supply zeros for all fields + in the structure. + * Makefile (tests): Add tst-initializers1. + (CFLAGS-tst-initializers1.c): Set. + * tst-initializers1.c: New test. + +2005-07-11 Jakub Jelinek + + * sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h (pthread_rwlock_t): + Make sure __flags are located at offset 48 from the start of the + structure. + +2005-07-02 Roland McGrath + + * Makeconfig: Comment fix. + +2005-07-05 Jakub Jelinek + + * descr.h (PTHREAD_STRUCT_END_PADDING): Define. + * sysdeps/ia64/tls.h (TLS_PRE_TCB_SIZE): If PTHREAD_STRUCT_END_PADDING + is smaller than 8 bytes, increase TLS_PRE_TCB_SIZE by 16 bytes. + (THREAD_SYSINFO, THREAD_SELF, DB_THREAD_SELF): Don't assume + TLS_PRE_TCB_SIZE is sizeof (struct pthread). + (THREAD_SET_STACK_GUARD, THREAD_COPY_STACK_GUARD): Define. + * sysdeps/ia64/tcb-offsets.sym (PID, TID, MULTIPLE_THREADS_OFFSET): + Use TLS_PRE_TCB_SIZE instead of sizeof (struct pthread). + * sysdeps/unix/sysv/linux/ia64/createthread.c (TLS_VALUE): Don't + assume TLS_PRE_TCB_SIZE is sizeof (struct pthread). + +2005-06-25 Jakub Jelinek + + * sysdeps/i386/tls.h (tcbhead_t): Add stack_guard field. + (THREAD_SET_STACK_GUARD, THREAD_COPY_STACK_GUARD): Define. + * sysdeps/x86_64/tls.h (tcbhead_t): Add sysinfo and stack_guard + fields. + (THREAD_SET_STACK_GUARD, THREAD_COPY_STACK_GUARD): Define. + * sysdeps/s390/tls.h (tcbhead_t): Add stack_guard + field. Put in sysinfo field unconditionally. + (THREAD_SET_STACK_GUARD, THREAD_COPY_STACK_GUARD): Define. + * sysdeps/powerpc/tls.h (tcbhead_t): Add stack_guard field. + (THREAD_SET_STACK_GUARD, THREAD_COPY_STACK_GUARD): Define. + * sysdeps/sparc/tls.h (tcbhead_t): Add sysinfo and stack_guard + fields. + (THREAD_SET_STACK_GUARD, THREAD_COPY_STACK_GUARD): Define. + * pthread_create.c (__pthread_create_2_1): Use + THREAD_COPY_STACK_GUARD macro. + * Makefile: Add rules to build and run tst-stackguard1{,-static} + tests. + * tst-stackguard1.c: New file. + * tst-stackguard1-static.c: New file. + +2005-06-14 Alan Modra + + * sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h (PSEUDO): + Invoke CGOTSETUP and CGOTRESTORE. + (CGOTSETUP, CGOTRESTORE): Define. + +2005-05-29 Richard Henderson + + * tst-cancel4.c (WRITE_BUFFER_SIZE): New. + (tf_write, tf_writev): Use it. + (do_test): Use socketpair instead of pipe. Set SO_SNDBUF to + the system minimum. + +2005-05-23 Jakub Jelinek + + * sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h + [IS_IN_librt] (CENABLE, CDISABLE): Use JUMPTARGET instead of + __librt_*_asynccancel@local. + +2005-05-17 Alan Modra + + * sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h: Delete + all occurrences of JUMPTARGET. Instead append @local to labels. + +2005-05-20 Jakub Jelinek + + * sysdeps/i386/tls.h (TLS_INIT_TCB_SIZE, TLS_INIT_TCB_ALIGN): Define to + size/alignment of struct pthread rather than tcbhead_t. + * sysdeps/x86_64/tls.h (TLS_INIT_TCB_SIZE, TLS_INIT_TCB_ALIGN): + Likewise. + * sysdeps/s390/tls.h (TLS_INIT_TCB_SIZE, TLS_INIT_TCB_ALIGN): + Likewise. + * sysdeps/sparc/tls.h (TLS_INIT_TCB_SIZE, TLS_INIT_TCB_ALIGN): + Likewise. + +2005-05-19 Richard Henderson + + * sysdeps/ia64/pthread_spin_lock.c (pthread_spin_lock): Use + __sync_val_compare_and_swap, not explicit _si variant. + * sysdeps/ia64/pthread_spin_trylock.c (pthread_spin_trylock): Likewise. + +2005-05-03 Ulrich Drepper + + [BZ #915] + * sysdeps/pthread/pthread.h: Avoid empty initializers. + +2005-05-03 Jakub Jelinek + + * sysdeps/unix/sysv/linux/i386/sysdep-cancel.h: Remove explicit + .eh_frame section, use cfi_* directives. + +2005-04-27 Jakub Jelinek + + * sysdeps/unix/sysv/linux/pthread_getcpuclockid.c: Use <> instead + of "" includes. + +2005-04-27 Ulrich Drepper + + [BZ #1075] + * tst-cancel17.c (do_test): Add arbitrary factor to make sure + aio_write blocks. + +2005-04-27 Roland McGrath + + * Makefile (tests): Remove tst-clock2. + + * sysdeps/unix/sysv/linux/timer_create.c (timer_create): Handle + CLOCK_PROCESS_CPUTIME_ID and CLOCK_PROCESS_THREAD_ID specially, + translating to the kernel clockid_t for our own process/thread clock. + + * sysdeps/unix/sysv/linux/pthread_getcpuclockid.c: New file. + +2005-04-15 Jakub Jelinek + + * old_pthread_cond_init.c: Include . + (__pthread_cond_init_2_0): Fail with EINVAL if COND_ATTR is + process shared or uses clock other than CLOCK_REALTIME. + * pthread_cond_init.c (__pthread_cond_init): Remove bogus comment. + +2005-04-13 David S. Miller + + * sysdeps/sparc/sparc64/jmpbuf-unwind.h: New file. + * sysdeps/sparc/sparc64/clone.S: New file. + +2005-04-05 Jakub Jelinek + + [BZ #1102] + * sysdeps/pthread/pthread.h (__pthread_cleanup_routine): Use + __inline instead of inline. + * sysdeps/pthread/bits/libc-lock.h (__libc_cleanup_routine): Likewise. + +2005-03-31 Jakub Jelinek + + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_unlock.S: Use + functionally equivalent, but shorter instructions. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h: Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedrdlock.S: + Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_barrier_wait.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_rdlock.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/sem_wait.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_wrlock.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_once.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedwrlock.S: + Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/sem_post.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S: Likewise. + +2005-03-28 Daniel Jacobowitz + + * sysdeps/mips/Makefile: New file. + * sysdeps/mips/nptl-sysdep.S: New file. + * sysdeps/mips/tcb-offsets.sym: New file. + * sysdeps/mips/pthread_spin_lock.S: New file. + * sysdeps/mips/pthread_spin_trylock.S: New file. + * sysdeps/mips/pthreaddef.h: New file. + * sysdeps/mips/tls.h: New file. + * sysdeps/mips/jmpbuf-unwind.h: New file. + * sysdeps/unix/sysv/linux/mips/lowlevellock.h: New file. + * sysdeps/unix/sysv/linux/mips/bits/pthreadtypes.h: New file. + * sysdeps/unix/sysv/linux/mips/bits/semaphore.h: New file. + * sysdeps/unix/sysv/linux/mips/pthread_once.c: New file. + * sysdeps/unix/sysv/linux/mips/fork.c: New file. + * sysdeps/unix/sysv/linux/mips/pt-vfork.S: New file. + * sysdeps/unix/sysv/linux/mips/vfork.S: New file. + * sysdeps/unix/sysv/linux/mips/clone.S: New file. + * sysdeps/unix/sysv/linux/mips/createthread.c: New file. + * sysdeps/unix/sysv/linux/mips/sysdep-cancel.h: New file. + +2005-03-23 Ulrich Drepper + + [BZ #1112] + * pthread_create.c (__pthread_create_2_1): Rename syscall error + variable to scerr. + +2005-03-10 Jakub Jelinek + + * tst-getpid1.c (do_test): Align stack passed to clone{2,}. + +2005-02-25 Roland McGrath + + * alloca_cutoff.c: Correct license text. + * tst-unload.c: Likewise. + * sysdeps/pthread/allocalim.h: Likewise. + * sysdeps/pthread/pt-initfini.c: Likewise. + * sysdeps/pthread/bits/libc-lock.h: Likewise. + * sysdeps/pthread/bits/sigthread.h: Likewise. + * sysdeps/unix/sysv/linux/bits/local_lim.h: Likewise. + * sysdeps/unix/sysv/linux/bits/posix_opt.h: Likewise. + +2005-02-16 Roland McGrath + + * sysdeps/pthread/pthread-functions.h (struct pthread_functions): + Use unsigned int * for ptr_nthreads. + +2005-02-14 Alan Modra + + [BZ #721] + * sysdeps/powerpc/tcb-offsets.sym (thread_offsetof): Redefine to suit + gcc4. + +2005-02-07 Richard Henderson + + [BZ #787] + * sysdeps/pthread/pthread.h (__sigsetjmp): Use pointer as first + argument. + +2004-11-03 Marcus Brinkmann + + * sysdeps/generic/lowlevellock.h (__generic_mutex_unlock): Fix + order of arguments in invocation of atomic_add_zero. + +2005-01-26 Jakub Jelinek + + [BZ #737] + * sysdeps/unix/sysv/linux/i386/i486/sem_trywait.S (__new_sem_trywait): + Use direct %gs segment access or, if NO_TLS_DIRECT_SEG_REFS, + at least gotntpoff relocation and addition. + * sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S (sem_timedwait): + Likewise. + * sysdeps/unix/sysv/linux/i386/i486/sem_post.S (__new_sem_post): + Likewise. + * sysdeps/unix/sysv/linux/i386/i486/sem_wait.S (__new_sem_wait): + Likewise. + +2005-01-06 Ulrich Drepper + + * allocatestack.c (init_one_static_tls): Adjust initialization of DTV + entry for static tls deallocation fix. + * sysdeps/alpha/tls.h (dtv_t): Change pointer type to be struct which + also contains information whether the memory pointed to is static + TLS or not. + * sysdeps/i386/tls.h: Likewise. + * sysdeps/ia64/tls.h: Likewise. + * sysdeps/powerpc/tls.h: Likewise. + * sysdeps/s390/tls.h: Likewise. + * sysdeps/sh/tls.h: Likewise. + * sysdeps/sparc/tls.h: Likewise. + * sysdeps/x86_64/tls.h: Likewise. + +2004-12-27 Ulrich Drepper + + * init.c (__pthread_initialize_minimal_internal): Use __sigemptyset. + +2004-12-21 Jakub Jelinek + + * sysdeps/i386/tls.h (CALL_THREAD_FCT): Maintain 16 byte alignment of + %esp. + * Makefile (tests): Add tst-align2. + * tst-align2.c: New test. + * sysdeps/i386/Makefile (CFLAGS-tst-align{,2}.c): Add + -mpreferred-stack-boundary=4. + +2004-12-18 Roland McGrath + + * sysdeps/unix/sysv/linux/powerpc/powerpc64/bits/local_lim.h: + New file removed withdrawn for the moment. + +2004-12-17 Richard Henderson + + * sysdeps/unix/sysv/linux/alpha/clone.S: New file. + * sysdeps/alpha/tcb-offsets.sym (TID_OFFSET): New. + +2004-12-16 Ulrich Drepper + + * sysdeps/unix/sysv/linux/powerpc/powerpc64/bits/local_lim.h: New file. + Increased PTHREAD_STACK_MIN. + + * tst-context1.c (stacks): Use bigger stack size. + +2004-12-16 Jakub Jelinek + + * sysdeps/unix/sysv/linux/sparc/sparc32/clone.S: New file. + * sysdeps/sparc/tcb-offsets.sym: Add TID. + +2004-12-15 Jakub Jelinek + + * sysdeps/unix/sysv/linux/s390/s390-32/clone.S: New file. + * sysdeps/unix/sysv/linux/s390/s390-64/clone.S: New file. + * sysdeps/s390/tcb-offsets.sym (TID): Add. + +2004-12-15 Ulrich Drepper + + * sysdeps/unix/sysv/linux/powerpc/powerpc32/clone.S: New file. + +2004-12-14 Ulrich Drepper + + * sysdeps/powerpc/tcb-offsets.sym: Add TID. + * sysdeps/unix/sysv/linux/powerpc/powerpc64/clone.S: New file. + + * tst-getpid1.c: If child crashes, report this first. Print which + signal. + +2004-12-09 Ulrich Drepper + + * init.c (__pthread_initialize_minimal_internal): Also unblock + SIGSETXID. + +2004-12-01 Jakub Jelinek + + * sysdeps/unix/sysv/linux/bits/posix_opt.h (_POSIX_CPUTIME, + _POSIX_THREAD_CPUTIME): Define to 0. + * sysdeps/pthread/timer_create.c (timer_create): Remove unused code + handling CLOCK_PROCESS_CPUTIME_ID and CLOCK_THREAD_CPUTIME_ID. + * sysdeps/pthread/timer_routines.c (__timer_signal_thread_pclk, + __timer_signal_thread_tclk): Remove. + (init_module): Remove their initialization. + (thread_cleanup): Remove their cleanup assertions. + * sysdeps/pthread/posix-timer.h (__timer_signal_thread_pclk, + __timer_signal_thread_tclk): Remove. + * sysdeps/unix/sysv/linux/i386/bits/posix_opt.h: Removed. + * sysdeps/unix/sysv/linux/ia64/bits/posix_opt.h: Removed. + * sysdeps/unix/sysv/linux/x86_64/bits/posix_opt.h: Removed. + +2004-12-07 Jakub Jelinek + + * sysdeps/ia64/tcb-offsets.sym (TID): Add. + * sysdeps/unix/sysv/linux/ia64/clone2.S: New file. + + * Makefile (tests): Add tst-getpid2. + * tst-getpid1.c (TEST_CLONE_FLAGS): Define. + (do_test): Use it. Use __clone2 instead of clone on ia64. + * tst-getpid2.c: New test. + +2004-12-07 Kaz Kojima + + * sysdeps/unix/sysv/linux/sh/clone.S: New file. + +2004-12-04 Ulrich Drepper + + * Makefile (tests): Add tst-getpid1. + * tst-getpid1.c: New file. + * sysdeps/unix/sysv/linux/i386/clone.S: New file. + * sysdeps/unix/sysv/linux/x86_64/clone.S: New file. + +2004-12-02 Roland McGrath + + * Makefile (libpthread-nonshared): Variable removed. + ($(objpfx)libpthread_nonshared.a): Target removed. + ($(inst_libdir)/libpthread_nonshared.a): Likewise. + These are now handled by generic magic from + libpthread-static-only-routines being set. + +2004-11-27 Ulrich Drepper + + * sysdeps/unix/sysv/linux/bits/posix_opt.h (_POSIX_PRIORITIZED_IO, + _POSIX2_CHAR_TERM, _POSIX_THREAD_PRIO_INHERIT, + _POSIX_THREAD_PRIO_PROTECT): Define. + * sysdeps/unix/sysv/linux/i386/bits/posix_opt.h: Likewise. + * sysdeps/unix/sysv/linux/ia64/bits/posix_opt.h: Likewise. + * sysdeps/unix/sysv/linux/x86_64/bits/posix_opt.h: Likewise. + +2004-11-26 Jakub Jelinek + + * sysdeps/unix/sysv/linux/bits/posix_opt.h (_POSIX_ADVISORY_INFO, + _POSIX_SPORADIC_SERVER, _POSIX_THREAD_SPORADIC_SERVER, _POSIX_TRACE, + _POSIX_TRACE_EVENT_FILTER, _POSIX_TRACE_INHERIT, _POSIX_TRACE_LOG, + _POSIX_TYPED_MEMORY_OBJECTS, _POSIX_IPV6, _POSIX_RAW_SOCKETS): Define. + * sysdeps/unix/sysv/linux/i386/bits/posix_opt.h: Likewise. + * sysdeps/unix/sysv/linux/ia64/bits/posix_opt.h: Likewise. + * sysdeps/unix/sysv/linux/x86_64/bits/posix_opt.h: Likewise. + +2004-11-24 Ulrich Drepper + + * sysdeps/x86_64/Makefile [nptl]: Define CFLAGS-pthread_create.c. + + * Makefile (libpthread-routines): Add pthread_setschedprio. + * Versions [libpthread, GLIBC_2.3.4]: Add pthread_setschedprio. + * sysdeps/pthread/pthread.h: Declare pthread_setschedprio. + * pthread_setschedprio.c: New file. + +2004-11-20 Jakub Jelinek + + * pthread_create.c (pthread_cancel): Add PTHREAD_STATIC_FN_REQUIRE. + * pthread_cancel.c (pthread_create): Likewise. + + * Makefile (libpthread-routines): Add vars. + * sysdeps/pthread/createthread.c (__pthread_multiple_threads): Remove. + * init.c (__default_stacksize, __is_smp): Remove. + * vars.c: New file. + * pthreadP.h (__find_thread_by_id): If !SHARED, add weak_function + and define a wrapper macro. + (PTHREAD_STATIC_FN_REQUIRE): Define. + * allocatestack.c (__find_thread_by_id): Undefine. + * pthread_create (__pthread_keys): Remove. + (pthread_mutex_lock, pthread_mutex_unlock, pthread_once, + pthread_key_create, pthread_setspecific, pthread_getspecific): Add + PTHREAD_STATIC_FN_REQUIRE. + +2004-11-18 Kaz Kojima + + * sysdeps/sh/tls.h (DB_THREAD_SELF): Set the correct bias + parameter to REGISTER macro. + +2004-11-17 Roland McGrath + + * sysdeps/unix/sysv/linux/timer_routines.c (__start_helper_thread): + Make sure SIGCANCEL is blocked as well. + +2004-11-10 Jakub Jelinek + + * sysdeps/pthread/setxid.h: New file. + * sysdeps/pthread/pthread-functions.h (HAVE_PTR__NPTL_SETXID): Remove. + (struct xid_command): Add forward decl. + (struct pthread_functions): Change return type of __nptl_setxid hook + to int. + * pthreadP.h (__nptl_setxid): Change return type to int. + * allocatestack.c (__nptl_setxid): Call INTERNAL_SYSCALL_NCS in the + calling thread, return its return value and set errno on failure. + * descr.h (struct xid_command): Change id type to long array. + + * Makefile: Add rules to build and test tst-setuid1 and + tst-setuid1-static. + * tst-setuid1.c: New test. + * tst-setuid1-static.c: New test. + +2004-11-10 Jakub Jelinek + + * Makefile (tests): Add tst-exit3. + * tst-exit3.c: New test. + +2004-11-09 Ulrich Drepper + + * Makefile (tests): Add tst-exit2. + * tst-exit2.c: New file. + +2004-11-09 Roland McGrath + + [BZ #530] + * sysdeps/pthread/createthread.c (do_clone): Increment __nptl_nthreads + here, before calling clone. + * pthread_create.c (start_thread): Don't do it here. + +2004-11-02 Jakub Jelinek + + * sysdeps/unix/sysv/linux/smp.h: Include . + +2004-10-29 Kaz Kojima + + * sysdeps/unix/sysv/linux/sh/sem_timedwait.S (sem_timedwait): + Set ETIMEDOUT to errno when time is up. Tweak to avoid + assembler warning. + +2004-10-28 Jakub Jelinek + + * pthread_create.c (__pthread_create_2_1): Avoid leaking stacks + if sched_priority is not between minprio and maxprio. + +2004-10-25 Kaz Kojima + + * sysdeps/unix/sysv/linux/sh/pthread_cond_timedwait.S + (__pthread_cond_timedwait): Use clock_gettime syscall if exists. + + * sysdeps/unix/sysv/linux/sh/lowlevellock.S + (__lll_mutex_timedlock_wait): Fix a bad branch condition. + +2004-10-24 Ulrich Drepper + + * sysdeps/unix/sysv/linux/smp.h (is_smp_system): Use + not-cancelable I/O functions. + +2004-10-21 Kaz Kojima + + * sysdeps/unix/sysv/linux/sh/lowlevellock.S + (__lll_mutex_timedlock_wait): If woken but cannot get the lock, + make sure 2 is stored in the futex and we looked at the old value. + Fix a few other problems to return the correct value. + +2004-10-14 Richard Henderson + + * sysdeps/alpha/tcb-offsets.sym (thread_offsetof): Redefine to + make gcc4 happy. + +2004-10-06 Jakub Jelinek + + * sysdeps/unix/sysv/linux/jmp-unwind.c: Include pthreadP.h instead + of pthread-functions.h and pthreaddef.h. + * sysdeps/unix/sysv/linux/s390/jmp-unwind.c: Likewise. + + * sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h (pthread_cond_t): + Change __data.__nwaiters from int to unsigned int. + + * tst-clock2.c (do_test): Don't fail if _POSIX_THREAD_CPUTIME == 0 and + sysconf (_SC_THREAD_CPUTIME) returns negative value. + + * allocatestack.c (__find_thread_by_id): Move attribute_hidden + before return type. + + * sysdeps/s390/jmpbuf-unwind.h: Include bits/wordsize.h. + (JMPBUF_CFA_UNWINDS_ADJ): Subtract 96 resp. 160 bytes from CFA. + +2004-10-06 Ulrich Drepper + + * tst-cancel4.c (tf_msgrcv): Check for failure in msgget. If the + test fails, remove message queue. + (tf_msgsnd): Likewise. + +2004-10-05 Jakub Jelinek + + * tst-clock1.c: Change #ifdef to #if defined. + * tst-clock2.c: Likewise. + * tst-cond11.c: Likewise. + + * sysdeps/pthread/timer_create.c (timer_create): Use + defined _POSIX_CPUTIME && _POSIX_CPUTIME >= 0 instead of + defined CLOCK_PROCESS_CPUTIME_ID #ifs and similarly for + THREAD_CPUTIME. + +2004-10-05 Jakub Jelinek + + * sysdeps/unix/sysv/linux/x86_64/bits/posix_opt.h (_POSIX_CPUTIME, + _POSIX_THREAD_CPUTIME): Define to 0. + +2004-10-04 Ulrich Drepper + + * sysdeps/unix/sysv/linux/i386/bits/posix_opt.h: Define _POSIX_CPUTIME + and _POSIX_THREAD_CPUTIME to zero. + * sysdeps/unix/sysv/linux/ia64/bits/posix_opt.h: Likewise. + * tst-barrier2.c: Fix testing for POSIX feature. + * tst-clock1.c: Likewise. + * tst-clock2.c: Likewise. + * tst-cond11.c: Likewise. + * tst-cond4.c: Likewise. + * tst-cond6.c: Likewise. + * tst-flock2.c: Likewise. + * tst-mutex4.c: Likewise. + * tst-mutex9.c: Likewise. + * tst-rwlock12.c: Likewise. + * tst-rwlock4.c: Likewise. + * tst-signal1.c: Likewise. + * tst-spin2.c: Likewise. + * sysdeps/pthread/posix-timer.h: Likewise. + * sysdeps/pthread/timer_create.c: Likewise. + * sysdeps/pthread/timer_routines.c: Likewise. + +2004-10-01 Ulrich Drepper + + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.S + (__lll_mutex_timedlock_wait): Address futex correctly. + + * sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S + (__lll_mutex_timedlock_wait): If woken but cannot get the lock, + make sure 2 is stored in the futex and we looked at the old value. + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.S + (__lll_mutex_timedlock_wait): Likewise. Fix a few other problems + which might very well made the code not working at all before. + [BZ #417] + +2004-09-28 Ulrich Drepper + + * sysdeps/unix/sysv/linux/pthread_kill.c (__pthread_kill): Don't + allow SIGSETXID to be sent. + * sysdeps/pthread/sigaction.c (__sigaction): Don't allow action + for SIGSETXID to be defined. + * sysdeps/pthread/pthread_sigmask.c (pthread_sigmask): Make sure + SIGSETXID cannot be blocked. + + * sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h (pthread_cond_t): + Add __extension__ to long long types. + * sysdeps/unix/sysv/linux/sparc/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h: Likewise. + +2004-09-25 Ulrich Drepper + + * descr.h (struct pthread): Add stopped_start field. + * sysdeps/pthread/createthread.c (create_thread): Set + start_stopped flag in descriptor for new thread appropriately. + * pthread_create.c (start_thread): Only take lock to be stopped on + startup if stopped_start flag says so. + +2004-09-24 Ulrich Drepper + + * pthread_create.c (__pthread_create_2_1): Remember whether thread + is created detached and if yes, do not try to free the stack in case + the thread creation failed. + * sysdeps/pthread/createthread.c (do_clone): Free stack here if clone + call fails. Don't depend on INTERNAL_SYSCALL_ERRNO return zero in + case there has been no error. [BZ #405] + + * pthread_create.c (start_thread): Don't wait for scheduler data + etc to be set at the beginning of the function. The cancellation + infrastructure must have been set up. And enable async + cancellation before potentially going to sleep. [BZ #401] + +2004-09-20 Ulrich Drepper + + * Versions: Remove exports for pthread_set*id_np functions. + * sysdeps/pthread/pthread.h: Remove pthread_set*id_np prototypes + for now. + * Makefile: Don't build pthread_set*id code for now. + +2004-09-19 Ulrich Drepper + + * sysdeps/unix/sysv/linux/allocrtsig.c: Allocate second signal for + internal use. + * allocatestack.c (__nptl_setxid): New function. + * descr.h (struct xid_command): Define type. + * init.c (pthread_functions): Add ptr__nptl_setxid initialization. + (sighandler_setxid): New function. + (__pthread_initialize_minimal): Register sighandler_setxid for + SIGCANCEL. + * pt-allocrtsig.c: Update comment. + * pthreadP.h: Define SIGSETXID. Declare __xidcmd variable. + Declare __nptl_setxid. + * sysdeps/pthread/pthread-functions.h: Add ptr__nptl_setxid. + * sysdeps/pthread/pthread.h: Declare pthread_setgid_np, + pthread_setuid_np, pthread_setegid_np, pthread_seteuid_np, + pthread_setregid_np, pthread_setreuid_np, pthread_setresgid_np, + and pthread_setresuid_np. + * pthread_setgid_np.c: New file. + * pthread_setuid_np.c: New file. + * pthread_setegid_np.c: New file. + * pthread_seteuid_np.c: New file. + * pthread_setregid_np.c: New file. + * pthread_setreuid_np.c: New file. + * pthread_setresgid_np.c: New file. + * pthread_setresuid_np.c: New file. + * Versions [libpthread, GLIBC_2.3.4]: Add pthread_setgid_np, + pthread_setuid_np, pthread_setegid_np, pthread_seteuid_np, + pthread_setregid_np, pthread_setreuid_np, pthread_setresgid_np, + and pthread_setresuid_np. + * Makefile (libpthread-routines): Add pthread_setuid, pthread_seteuid, + pthread_setreuid, pthread_setresuid, pthread_setgid, pthread_setegid, + pthread_setregid, and pthread_setresgid. + +2004-09-18 Ulrich Drepper + + * allocatestack.c (allocate_stack): Return EAGAIN instead of + ENOMEM when out of memory. + +2004-09-10 Roland McGrath + + [BZ #379] + * allocatestack.c (allocate_stack): Remove [__ASSUME_CLONE_STOPPED] + code, since we don't try to use the broken CLONE_STOPPED any more. + * pthread_create.c (start_thread): Likewise. + +2004-09-15 Richard Henderson + + * sysdeps/unix/sysv/linux/alpha/vfork.S: Use libc_hidden_def. + +2004-09-01 David Mosberger + + * sysdeps/unix/sysv/linux/ia64/jmpbuf-unwind.h + (__libc_unwind_longjmp): Delete macro and declare as function. + * sysdeps/unix/sysv/linux/ia64/Makefile (sysdep_routines): Mention + __ia64_longjmp, sigstack_longjmp, and __sigstack_longjmp for + nptl directory. + * sysdeps/unix/sysv/linux/ia64/__ia64_longjmp.S: New file. + * sysdeps/unix/sysv/linux/ia64/__sigstack_longjmp.c: New file. + * sysdeps/unix/sysv/linux/ia64/unwind_longjmp.c: New file. + +2004-09-12 Ulrich Drepper + + * sysdeps/pthread/pthread.h: Make rwlock prototypes available also + for __USE_XOPEN2K. + * sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h: Define rwlock + types also for __USE_XOPEN2K. + * sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/sparc/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h: Likewise. + [BZ #320] + +2004-09-08 Ulrich Drepper + + * sysdeps/pthread/pthread.h + (PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP): Make safe for C++. + (PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP): Likewise. + (PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP): Likewise. + (PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP): Likewise. + [BZ #375] + +2004-09-07 Ulrich Drepper + + * sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h: Allow + PSEUDO to be used with . prefix. + + * sysdeps/unix/sysv/linux/alpha/pthread_once.c (__pthread_once): + Use atomic_increment instead of atomic_exchange_and_add. + * sysdeps/unix/sysv/linux/sparc/pthread_once.c (__pthread_once): + Likewise. + * sysdeps/unix/sysv/linux/ia64/pthread_once.c (__pthread_once): + Likewise. + * sysdeps/unix/sysv/linux/powerpc/pthread_once.c (__pthread_once): + Likewise. + + * allocatestack.c (allocate_stack): Use atomic_increment_val + instead of atomic_exchange_and_add. + * sysdeps/unix/sysv/linux/sem_post.c (__new_sem_post): Likewise. + * sysdeps/unix/sysv/linux/powerpc/sem_post.c (__new_sem_post): + Likewise. + * sysdeps/pthread/pthread_barrier_wait.c (pthread_barrier_wait): + Likewise. + + * sysdeps/pthread/pthread.h (pthread_once): Remove __THROW since + the initialization function might throw. + +2005-09-05 Richard Henderson + + * sysdeps/unix/sysv/linux/alpha/sysdep-cancel.h (SINGLE_THREAD_P): + Move definition inside libpthread, libc, librt check. Provide + definition for rtld. + +2004-09-02 Ulrich Drepper + + * sysdeps/alpha/jmpbuf-unwind.h: Define __libc_unwind_longjmp. + * sysdeps/i386/jmpbuf-unwind.h: Likewise + * sysdeps/powerpc/jmpbuf-unwind.h: Likewise. + * sysdeps/s390/jmpbuf-unwind.h: Likewise. + * sysdeps/sh/jmpbuf-unwind.h: Likewise. + * sysdeps/sparc/sparc32/jmpbuf-unwind.h: Likewise. + * sysdeps/unix/sysv/linux/ia64/jmpbuf-unwind.h: Likewise. + * sysdeps/x86_64/jmpbuf-unwind.h: Likewise. + * unwind.c: Use it. + + * sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h (pthread_cond_t): + Rename __data.__clock to __data.__nwaiters, make it unsigned int. + * sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h (pthread_cond_t): + Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S: + Decrement __nwaiters. If pthread_cond_destroy has been called and + this is the last waiter, signal pthread_cond_destroy caller and + avoid using the pthread_cond_t structure after unlock. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: Likewise. + Read clock type from the least significant bits of __nwaiters instead + of __clock. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S: Likewise. + * sysdeps/unix/sysv/linux/internaltypes.h: Define COND_CLOCK_BITS. + +2004-08-31 Jakub Jelinek + + [BZ #342] + * Makefile (tests): Add tst-cond20 and tst-cond21. + * tst-cond20.c: New test. + * tst-cond21.c: New test. + * sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h + (pthread_cond_t): Rename __data.__clock to __data.__nwaiters, make + it unsigned int. + * sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h (pthread_cond_t): + Likewise. + * sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h + (pthread_cond_t): Likewise. + * sysdeps/unix/sysv/linux/sparc/bits/pthreadtypes.h (pthread_cond_t): + Likewise. + * sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h (pthread_cond_t): + Likewise. + * sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h (pthread_cond_t): + Likewise. + * sysdeps/unix/sysv/linux/lowlevelcond.sym (cond_clock): Remove. + (cond_nwaiters): New. + (clock_bits): New. + * pthread_cond_destroy.c (__pthread_cond_destroy): Return EBUSY + if there are waiters not signalled yet. + Wait until all already signalled waiters wake up. + * sysdeps/pthread/pthread_cond_wait.c (__condvar_cleanup): Decrement + __nwaiters. If pthread_cond_destroy has been called and this is the + last waiter, signal pthread_cond_destroy caller and avoid using + the pthread_cond_t structure after unlock. + (__pthread_cond_wait): Increment __nwaiters in the beginning, + decrement it when leaving. If pthread_cond_destroy has been called + and this is the last waiter, signal pthread_cond_destroy caller. + * sysdeps/pthread/pthread_cond_timedwait.c (__pthread_cond_timedwait): + Likewise. Read clock type from the least significant bits of + __nwaiters instead of __clock. + * pthread_condattr_setclock.c (pthread_condattr_setclock): Check + whether clock ID can be encoded in COND_CLOCK_BITS bits. + * pthread_condattr_getclock.c (pthread_condattr_getclock): Decode + clock type just from the last COND_CLOCK_BITS bits of value. + * pthread_cond_init.c (__pthread_cond_init): Initialize __nwaiters + instead of __clock, just from second bit of condattr's value. + +2004-08-30 Jakub Jelinek + + * sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h: Include + bits/wordsize.h. Make the header match i386 header when __WORDSIZE + != 64. + * sysdeps/unix/sysv/linux/x86_64/bits/semaphore.h: Likewise. + +2004-08-15 Roland McGrath + + * pthread_atfork.c: Update copyright terms including special exception + for these trivial files, which are statically linked into executables + that use dynamic linking for the significant library code. + +2004-08-09 Jakub Jelinek + + * DESIGN-rwlock.txt: Add decreasing of nr_readers_queued to + pthread_rwlock_rdlock. + * sysdeps/pthread/pthread_rwlock_rdlock (__pthread_rwlock_rdlock): + Decrease __nr_readers_queued after reacquiring lock. + * sysdeps/pthread/pthread_rwlock_timedrdlock + (pthread_rwlock_timedrdlock): Likewise. + Reported by Bob Cook . + +2004-08-11 Jakub Jelinek + + * tst-rwlock14.c (tf): Read main thread handle from *ARG + before pthread_barrier_wait. + +2004-08-07 Ulrich Drepper + + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: + Remove unnecessary exception handling data. + +2004-07-23 Jakub Jelinek + + [BZ #284] + * sysdeps/pthread/pthread.h (pthread_getcpuclockid): Use __clockid_t + instead of clockid_t. + +2004-07-21 Roland McGrath + + * Makefile ($(objpfx)multidir.mk): Use $(make-target-directory). + +2004-07-19 Roland McGrath + + * tst-cancel4.c (tf_waitid): Use WEXITED flag bit if available. + +2004-07-02 Roland McGrath + + * configure: Don't exit. + +2004-07-14 Kaz Kojima + + * sysdeps/unix/sysv/linux/sh/pthread_cond_timedwait.S + (__pthread_cond_timedwait): Check for invalid nanosecond in + timeout value. + +2004-07-07 Ulrich Drepper + + * Makefile: Add rules to build and run tst-fini1. + * tst-fini1.c: New file. + * tst-fini1mod.c: New file. + +2004-07-05 Ulrich Drepper + + * sysdeps/unix/sysv/linux/i386/sysdep-cancel.h: Define NO_CANCELLATION + if no cancellation support is needed. + * sysdeps/unix/sysv/linux/ia64/sysdep-cancel.h: Likewise. + * sysdeps/unix/sysv/linux/sh/sysdep-cancel.h: Likewise. + * sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h: Likewise. + * sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h: Likewise. + * sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h: Likewise. + * sysdeps/unix/sysv/linux/s390/s390-32/sysdep-cancel.h: Likewise. + * sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h: Likewise. + * sysdeps/unix/sysv/linux/sparc/sparc32/sysdep-cancel.h: Likewise. + * sysdeps/unix/sysv/linux/sparc/sparc64/sysdep-cancel.h: Likewise. + + * sysdeps/unix/sysv/linux/powerpc/lowlevellock.h: Define __NR_futex + only if not already defined. + +2004-07-05 Jakub Jelinek + + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.h (lll_unlock): Use + constraint "m" instead of "0" for futex. + + * shlib-versions: Add powerpc64-.*-linux.*. + +2004-07-04 Jakub Jelinek + + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedrdlock.S + (pthread_rwlock_timedrdlock): Use cmpq instead of cmpl to check + for valid tv_nsec. + * tst-rwlock14.c (do_test): Test for invalid tv_nsec equal to + 1 billion and 64-bit tv_nsec which is valid when truncated to 32 + bits. + +2004-06-29 Roland McGrath + + * Banner: NPTL no longer has its own version number. + * Makefile (nptl-version): Variable removed. + * sysdeps/pthread/Makefile (CFLAGS-confstr.c): Set LIBPTHREAD_VERSION + using $(version), the glibc version number. + +2004-06-29 Kaz Kojima + + * sysdeps/unix/sysv/linux/sh/pthread_once.S (__pthread_once): + Fix branch offset for a PLT entry. + * sysdeps/unix/sysv/linux/sh/sem_post.S (__new_sem_post): + Likewise. + * sysdeps/unix/sysv/linux/sh/sem_timedwait.S (sem_timedwait): + Likewise. + * sysdeps/unix/sysv/linux/sh/sem_trywait.S (__new_sem_trywait): + Likewise. + * sysdeps/unix/sysv/linux/sh/sem_wait.S (__new_sem_wait): + Likewise. + +2004-06-28 Jakub Jelinek + + * sysdeps/alpha/tcb-offsets.sym (MULTIPLE_THREADS_OFFSET): Define + unconditionally. + +2004-06-28 Jakub Jelinek + + * sysdeps/pthread/pthread_rwlock_timedwrlock.c + (pthread_rwlock_timedwrlock): Return EINVAL if tv_nsec is negative, + instead of tv_sec. + * sysdeps/pthread/pthread_rwlock_timedrdlock.c + (pthread_rwlock_timedrdlock): Likewise. + +2004-06-22 Jakub Jelinek + + * sysdeps/unix/sysv/linux/s390/lowlevellock.h (lll_futex_requeue): + Set __r7 to val, not mutex. + +2004-06-27 Ulrich Drepper + + * Makefile: Add rules to build tst-rwlock14. + * tst-rwlock14.c: New file. + +2004-06-24 Boris Hu + + * sysdeps/pthread/pthread_rwlock_timedrdlock.c: Add timeout validation + check. + * sysdeps/pthread/pthread_rwlock_timedwrlock.c: Likewise. + +2004-06-19 Andreas Jaeger + + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S: Fix + assembler in last patch. + +2004-06-17 Ulrich Drepper + + * sysdeps/pthread/pthread_cond_timedwait.c + (__pthread_cond_timedwait): Also check for negativ nanoseconds. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S + (__pthread_cond_timedwait): Check for invalid nanosecond in + timeout value. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S: Likewise. + * tst-cond19.c: New file. + * Makefile: Add rules to build and run tst-cond19. + +2004-06-15 Steven Munroe + + * tst-context1.c (GUARD_PATTERN): Defined. + (tst_context_t): Define struct containing ucontext_t & guard words. + (ctx): Declare as an array of tst_context_t. + (fct): Verify uc_link & guard words are still valid. + (tf): Initialize guard words in ctx. Adjust ctx refs for new struct. + +2004-06-13 Kaz Kojima + + * sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h (pthread_cond_t): + Add __data.__futex field, reshuffle __data.__clock. + * sysdeps/unix/sysv/linux/sh/pthread_cond_signal.S + (__pthread_cond_signal): Increment __futex at the same time as + __wakeup_seq or __total_seq. Pass address of __futex instead of + address of low 32-bits of __wakeup_seq to futex syscall. + * sysdeps/unix/sysv/linux/sh/pthread_cond_wait.S + (__pthread_cond_wait): Likewise. Pass __futex value from before + releasing internal lock to FUTEX_WAIT. + * sysdeps/unix/sysv/linux/sh/pthread_cond_timedwait.S + (__pthread_cond_timedwait): Likewise. + * sysdeps/unix/sysv/linux/sh/pthread_cond_broadcast.S + (FUTEX_CMP_REQUEUE): Define. + (__pthread_cond_broadcast): Set __futex to 2 * __total_seq. + Use FUTEX_CMP_REQUEUE operation instead of FUTEX_REQUEUE. + Pass __futex value from before the unlock and __futex address instead + of address of low 32-bits of __wakeup_seq to futex syscall. + Fallback to FUTEX_WAKE all on any errors. + +2004-06-08 Jakub Jelinek + + * pthread_mutexattr_getpshared.c (pthread_mutex_getpshared): Fix + comment typo. + * pthread_mutexattr_gettype.c (pthread_mutexattr_gettype): Likewise. + * pthread_mutexattr_init.c (__pthread_mutexattr_init): Likewise. + * pthread_mutexattr_settype.c (__pthread_mutexattr_settype): Likewise. + * pthread_mutexattr_setpshared.c (pthread_mutexattr_setpshared): + Likewise. Reported by Bob Cook . + +2004-06-11 Martin Schwidefsky + + * sysdeps/unix/sysv/linux/s390/lowlevellock.h (lll_compare_and_swap): + Add memory clobber to inline assembly. + (__lll_mutex_trylock): Likewise. + (__lll_mutex_cond_trylock): Likewise. + +2004-06-07 Martin Schwidefsky + + * sysdeps/unix/sysv/linux/s390/lowlevellock.h (lll_futex_requeue): + Pass val argument as 6th system call argument in %r7. + +2004-05-21 Jakub Jelinek + + * Makefile (tests): Add tst-cond16. + * sysdeps/unix/sysv/linux/lowlevelcond.sym (cond_futex): Add. + * pthread_cond_init.c (__pthread_cond_init): Clear __data.__futex. + * sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h (pthread_cond_t): + Add __data.__futex field, reshuffle __data.__clock. + * sysdeps/unix/sysv/linux/i386/pthread_cond_signal.S + (__pthread_cond_signal): Increment __futex at the same time as + __wakeup_seq or __total_seq. Pass address of __futex instead of + address of low 32-bits of __wakeup_seq to futex syscall. + * sysdeps/unix/sysv/linux/i386/pthread_cond_wait.S + (__pthread_cond_wait): Likewise. Pass __futex value from before + releasing internal lock to FUTEX_WAIT. + * sysdeps/unix/sysv/linux/i386/pthread_cond_timedwait.S + (__pthread_cond_timedwait): Likewise. + * sysdeps/unix/sysv/linux/i386/pthread_cond_broadcast.S + (FUTEX_CMP_REQUEUE): Define. + (__pthread_cond_broadcast): Set __futex to 2 * __total_seq. + Use FUTEX_CMP_REQUEUE operation instead of FUTEX_REQUEUE. + Pass __futex value from before the unlock and __futex address instead + of address of low 32-bits of __wakeup_seq to futex syscall. + Fallback to FUTEX_WAKE all on any errors. + * sysdeps/unix/sysv/linux/alpha/lowlevellock.h (FUTEX_CMP_REQUEUE): + Define. + (lll_futex_requeue): Add val argument, use FUTEX_CMP_REQUEUE + internally. Return non-zero if error, zero if success. + * sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h (pthread_cond_t): + Add __data.__futex field, reshuffle __data.__clock. + * sysdeps/unix/sysv/linux/s390/lowlevellock.h (FUTEX_CMP_REQUEUE): + Define. + (lll_futex_requeue): Add val argument, return 1 unconditionally + for the time being. + * sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h (pthread_cond_t): + Add __data.__futex field, reshuffle __data.__clock. + * sysdeps/unix/sysv/linux/powerpc/lowlevellock.h (FUTEX_CMP_REQUEUE): + Define. + (lll_futex_requeue): Add val argument, use FUTEX_CMP_REQUEUE + internally. Return non-zero if error, zero if success. + * sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h + (pthread_cond_t): Add __data.__futex field, reshuffle __data.__clock. + * sysdeps/unix/sysv/linux/sparc/lowlevellock.h (FUTEX_CMP_REQUEUE): + Define. + (lll_futex_requeue): Add val argument, use FUTEX_CMP_REQUEUE + internally. Return non-zero if error, zero if success. + * sysdeps/unix/sysv/linux/sparc/bits/pthreadtypes.h (pthread_cond_t): + Add __data.__futex field, reshuffle __data.__clock. + * sysdeps/unix/sysv/linux/ia64/lowlevellock.h (FUTEX_CMP_REQUEUE): + Define. + (lll_futex_requeue): Add val argument, use FUTEX_CMP_REQUEUE + internally. Return non-zero if error, zero if success. + * sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h (pthread_cond_t): + Add __data.__futex field, reshuffle __data.__clock. + * sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h (pthread_cond_t): + Add __data.__futex field, reshuffle __data.__clock. + * sysdeps/pthread/pthread_cond_signal.c (__pthread_cond_signal): + Increment __futex at the same time as __wakeup_seq or __total_seq. + Pass address of __futex instead of address of low 32-bits of + __wakeup_seq to futex syscall. + * sysdeps/pthread/pthread_cond_wait.c (__pthread_cond_wait): Likewise. + Pass __futex value from before releasing internal lock + to FUTEX_WAIT. + * sysdeps/pthread/pthread_cond_timedwait.c (__pthread_cond_timedwait): + Likewise. Avoid unnecessary shadowing of variables. + * sysdeps/pthread/pthread_cond_broadcast.c (__pthread_cond_broadcast): + Set __futex to 2 * __total_seq. Pass __futex value from before the + unlock and __futex address instead of address of low 32-bits of + __wakeup_seq to futex_requeue macro, adjust for new return value + meaning. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.S + (__pthread_cond_signal): Increment __futex at the same time as + __wakeup_seq or __total_seq. Pass address of __futex instead of + address of low 32-bits of __wakeup_seq to futex syscall. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S + (__pthread_cond_wait): Likewise. Pass __futex value from before + releasing internal lock to FUTEX_WAIT. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S + (__pthread_cond_timedwait): Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S + (FUTEX_CMP_REQUEUE): Define. + (__pthread_cond_broadcast): Set __futex to 2 * __total_seq. + Use FUTEX_CMP_REQUEUE operation instead of FUTEX_REQUEUE. + Pass __futex value from before the unlock and __futex address instead + of address of low 32-bits of __wakeup_seq to futex syscall. + Fallback to FUTEX_WAKE all on any errors. + +2004-06-03 Kaz Kojima + + * sysdeps/unix/sysv/linux/sh/lowlevellock.h (lll_mutex_lock): + Add nop to align the end of critical section. + (lll_mutex_cond_lock, lll_mutex_timedlock): Likewise. + +2004-06-01 Kaz Kojima + + * sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h (pthread_cond_t): + Add __broadcast_seq field. + * sysdeps/unix/sysv/linux/sh/pthread_cond_broadcast.S: Mark + all waiters as woken with woken_seq and bump broadcast counter. + * sysdeps/unix/sysv/linux/sh/pthread_cond_wait.S: Use new + __broadcast_seq. Increment __woken_seq correctly when cleanuped. + * sysdeps/unix/sysv/linux/sh/pthread_cond_timedwait.S: Likewise. + Comment typo fixes. Avoid returning -ETIMEDOUT. + +2004-06-01 Ulrich Drepper + + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S + (__condvar_tw_cleanup): Fix access to saved broadcast_seq value. + Reported by Kaz Kojima. + +2004-05-25 Jakub Jelinek + + * sysdeps/unix/sysv/linux/aio_misc.h: New file. + +2004-05-21 Jakub Jelinek + + * sysdeps/pthread/pthread_cond_wait.c (__pthread_cond_wait): Compare + __broadcast_seq with bc_seq after acquiring internal lock instead of + before it. + +2004-05-18 Jakub Jelinek + + * Makefile (.NOTPARALLEL): Only serialize make check/xcheck, not + compilation. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S + (__pthread_cond_timedwait): Avoid returning -ETIMEDOUT. + * sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h + (pthread_cond_t): Add __data.__broadcast_seq field. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S + (FRAME_SIZE): Define. + (__pthread_cond_timedwait): Use it. Store/check broadcast_seq. + Comment typo fixes. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S (FRAME_SIZE): + Define. + (__pthread_cond_wait): Use it. Store/check broadcast_seq. Comment + typo fixes. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S + (__pthread_cond_broadcast): Increment broadcast_seq. Comment typo + fixes. + +2004-05-18 Ulrich Drepper + + * sysdeps/unix/sysv/linux/lowlevelcond.sym: Add broadcast_seq entry. + * sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h (pthread_cond_t): + Add __broadcast_seq field. + * sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/sparc/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.S: Mark + all waiters as woken with woken_seq and bump broadcast counter. + * sysdeps/pthread/pthread_cond_broadcast.c: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S: Use new + __broadcast_seq field. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: Likewise. + * sysdeps/pthread/pthread_cond_wait.c: Likewise. + * sysdeps/pthread/pthread_cond_timedwait.c: Likewise. + * pthread_cond_init.c: Initialize __broadcast_seq field. + * Makefile (tests): Add tst-cond17 and tst-cond18. + Add .NOTPARALLEL goal. + * tst-cond16.c: New file. From Jakub. + * tst-cond17.c: New file. From Jakub. + * tst-cond18.c: New file. From Jakub. + +2004-05-16 Ulrich Drepper + + * sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S: Correct some + unwind info. + + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S: + Parametrize frame size. Correct some unwind info. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: Likewise. + +2004-05-04 Jakub Jelinek + + * tst-stack3.c: Note testing functionality beyond POSIX. + +2004-05-04 Jakub Jelinek + + * sysdeps/unix/sysv/linux/ia64/sysdep-cancel.h (USE___THREAD): + Change conditional from ifdef to if. + +2004-04-23 Jakub Jelinek + + * sysdeps/unix/sysv/linux/ia64/sysdep-cancel.h (SYSDEP_CANCEL_ERRNO, + SYSDEP_CANCEL_ERROR): Define. + (PSEUDO): Use it. + +2004-05-01 Jakub Jelinek + + * Versions (libpthread): Remove __pthread_cleanup_upto@@GLIBC_PRIVATE. + +2004-04-20 Jakub Jelinek + + * sem_unlink.c (sem_unlink): Change EPERM into EACCES. + +2004-04-19 Kaz Kojima + + * sysdeps/unix/sysv/linux/sh/sem_timedwait.S: Add frame info. + Use HIDDEN_JUMPTARGET to jump to __pthread_unwind. + * sysdeps/unix/sysv/linux/sh/sem_wait.S: Remove unneeded frame + info. Use HIDDEN_JUMPTARGET to jump to __pthread_unwind. + +2004-04-19 Ulrich Drepper + + * sysdeps/unix/sysv/linux/timer_routines.c: Make sure helper + thread has all signals blocked. + +2004-04-18 Andreas Jaeger + + * sysdeps/unix/sysv/linux/x86_64/bits/semaphore.h + (SEM_VALUE_MAX): Add missing brace. + +2004-04-17 Jakub Jelinek + + * sysdeps/pthread/Makefile (tests): Add tst-mqueue8x + in rt subdir. + (CFLAGS-tst-mqueue8x.c): Add -fexceptions. + * sysdeps/pthread/tst-mqueue8x.c: New test. + * tst-cancel4.c: Update comment about message queues. + + * sysdeps/pthread/timer_gettime.c (timer_gettime): For expired timer + return it_value { 0, 0 }. + * sysdeps/pthread/timer_create.c (timer_create): Handle SIGEV_NONE + like SIGEV_SIGNAL. + * sysdeps/pthread/timer_routines.c (thread_expire_timer): Remove + assertion for SIGEV_NONE. + (thread_attr_compare): Compare all attributes, not just a partial + subset. + +2004-04-17 Jakub Jelinek + + * sysdeps/unix/sysv/linux/mq_notify.c: Include stdlib.h. + +2004-04-17 Ulrich Drepper + + * sysdeps/unix/sysv/linux/alpha/bits/semaphore.h (SEM_VALUE_MAX): + Just use a plain number. + * sysdeps/unix/sysv/linux/i386/bits/semaphore.h: Likewise. + * sysdeps/unix/sysv/linux/ia64/bits/semaphore.h: Likewise. + * sysdeps/unix/sysv/linux/powerpc/bits/semaphore.h: Likewise. + * sysdeps/unix/sysv/linux/s390/bits/semaphore.h: Likewise. + * sysdeps/unix/sysv/linux/sh/bits/semaphore.h: Likewise. + * sysdeps/unix/sysv/linux/sparc/bits/semaphore.h: Likewise. + * sysdeps/unix/sysv/linux/x86_64/bits/semaphore.h: Likewise. + +2004-04-16 Kaz Kojima + + * sysdeps/unix/sysv/linux/sh/pthread_cond_wait.S: Remove unneeded + frame info. + * sysdeps/unix/sysv/linux/sh/pthread_cond_timedwait.S: Likewise. + +2004-04-15 Jakub Jelinek + + * sysdeps/unix/sysv/linux/timer_routines.c: Include errno.h. + (timer_helper_thread): Use inline rt_sigtimedwait syscall instead + of calling sigwaitinfo. + +2004-04-16 Ulrich Drepper + + * allocatestack.c (allocate_stack): Set reported_guardsize + unconditionally. + * pthread_getattr_np.c (pthread_getattr_np): Use + reported_guardsize instead of guardsize. + * descr.h (struct pthread): Add reported_guardsize field. + +2004-04-13 Jakub Jelinek + + * sysdeps/unix/sysv/linux/mq_notify.c: Shut up GCC warning. + +2004-04-12 Ulrich Drepper + + * sysdeps/unix/sysv/linux/mq-notify.c: New file. + +2004-04-08 Jakub Jelinek + + * sysdeps/unix/sysv/linux/bits/local_lim.h (MQ_PRIO_MAX): Define. + * sysdeps/unix/sysv/linux/alpha/bits/local_lim.h (MQ_PRIO_MAX): Define. + * sysdeps/unix/sysv/linux/ia64/bits/local_lim.h (MQ_PRIO_MAX): Define. + * sysdeps/unix/sysv/linux/sparc/bits/local_lim.h (MQ_PRIO_MAX): Define. + * sysdeps/unix/sysv/linux/bits/posix_opt.h (_POSIX_MESSAGE_PASSING): + Define. + * sysdeps/unix/sysv/linux/i386/bits/posix_opt.h + (_POSIX_MESSAGE_PASSING): Define. + * sysdeps/unix/sysv/linux/ia64/bits/posix_opt.h + (_POSIX_MESSAGE_PASSING): Define. + * sysdeps/unix/sysv/linux/x86_64/bits/posix_opt.h + (_POSIX_MESSAGE_PASSING): Define. + +2004-04-04 Ulrich Drepper + + * tst-context1.c (fct): Check whether correct stack is used. + +2004-04-03 Ulrich Drepper + + * sysdeps/unix/sysv/linux/powerpc/lowlevellock.h: Never use + matching constraints for asm mem parameters. + + * tst-clock2.c (tf): Don't define unless needed. + +2004-03-30 H.J. Lu + + * Makefile (link-libc-static): Use $(static-gnulib) instead of + $(gnulib). + +2004-03-30 Ulrich Drepper + + * sysdeps/pthread/pthread-functions.h: Add ptr__nptl_deallocate_tsd. + * init.c (pthread_functions): Add ptr__nptl_deallocate_tsd. + * pthreadP.h: Declare __nptl_deallocate_tsd. + * pthread_create.c (deallocate_tsd): Remove to __nptl_deallocate_tsd. + Adjust caller. + + * Makefile (tests): Add tst-tsd5. + * tst-tsd5.c: New file. + +2004-03-29 Ulrich Drepper + + * sysdeps/unix/sysv/linux/pthread_attr_setaffinity.c + (__pthread_attr_setaffinity_old): Prepend GLIBC_ to version names + is SHLIB_COMPAT check. + * sysdeps/unix/sysv/linux/pthread_attr_getaffinity.c + (__pthread_attr_getaffinity_old): Likewise. + * sysdeps/unix/sysv/linux/pthread_getaffinity.c + (__pthread_getaffinity_old): Likewise. + * sysdeps/unix/sysv/linux/pthread_setaffinity.c + (__pthread_setaffinity_old): Likewise. + +2004-03-26 Ulrich Drepper + + * allocatestack.c (_make_stacks_executable): Call + _dl_make_stack_executable first. + +2004-03-24 Roland McGrath + + * sysdeps/i386/pthread_spin_lock.c (pthread_spin_lock): Use "m" + constraint instead of "0". + +2004-03-24 Ulrich Drepper + + * sysdeps/unix/sysv/linux/powerpc/lowlevellock.h + (lll_mutex_cond_trylock): Define as wrapper around __lll_cond_trylock. + + * sysdeps/unix/sysv/linux/getpid.c (really_getpid): Reorganize + code to avoid warning. + +2004-03-24 Andreas Jaeger + + * sysdeps/unix/sysv/linux/pthread_attr_setaffinity.c + (__pthread_attr_setaffinity_old): Remove const. + +2004-03-23 Ulrich Drepper + + * sysdeps/unix/sysv/linux/smp.h: New file. + * sysdeps/unix/sysv/linux/sh/smp.h: New file. + * init.c: Define __is_smp. + (__pthread_initialize_minimal_internal): Call is_smp_system to + initialize __is_smp. + * pthreadP.h: Declare __is_smp. + Define MAX_ADAPTIVE_COUNT is necessary. + * pthread_mutex_init.c: Add comment regarding __spins field. + * pthread_mutex_lock.c: Implement adaptive mutex type. + * pthread_mutex_timedlock.c: Likewise. + * sysdeps/unix/sysv/linux/pthread_mutex_cond_lock.c: Likewise. + * sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h (pthread_mutex_t): + Add __spins field. + * sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/sparc/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h: Define + lll_mutex_cond_trylock. + * sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/sparc/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h: Likewise. + Define BUSY_WAIT_NOP. + * sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h: Likewise. + + * tst-mutex5.c: Add support for testing adaptive mutexes. + * tst-mutex7.c: Likewise. + * tst-mutex5a.c: New file. + * tst-mutex7a.c: New file. + * Makefile (tests): Add tst-mutex5a and tst-mutex7a. + + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.S + (__lll_mutex_timedlock_wait): Preserve r8 and r9 since the + vgettimeofday call might destroy the content. + + * sysdeps/ia64/pthread_spin_lock.c (pthread_spin_lock): Use hint + @pause in the loop. + + * sysdeps/unix/sysv/linux/i386/lowlevellock.h (lll_mutex_trylock): + No need to restrict type of ret. Make it int. Add comment. + + * sysdeps/unix/sysv/linux/i386/lowlevellock.h (lll_mutex_trylock): + Remove unnecessary setne instruction. + +2004-03-22 Jakub Jelinek + + * sysdeps/unix/sysv/linux/pthread_getaffinity.c + (__pthread_getaffinity_new): Use INT_MAX instead of UINT_MAX. + * pthread_getattr_np.c (pthread_getattr_np): Double size every cycle. + If realloc fails, break out of the loop. + +2004-03-20 Andreas Jaeger + + * sysdeps/unix/sysv/linux/pthread_setaffinity.c + (__pthread_setaffinity_old): Fix interface. + * sysdeps/unix/sysv/linux/pthread_getaffinity.c + (__pthread_getaffinity_old): Likewise. + + * sysdeps/unix/sysv/linux/pthread_setaffinity.c + (__pthread_setaffinity_new): Remove duplicate declaration. + +2004-03-20 Kaz Kojima + + * sysdeps/unix/sysv/linux/sh/sysdep-cancel.h (CENABLE): Save + the return value to a safe register. + (CDISABLE): Set the function argument correctly. + +2004-03-17 Kaz Kojima + + * sysdeps/unix/sysv/linux/sh/lowlevel-atomic.h (XCHG): Define. + * sysdeps/unix/sysv/linux/sh/lowlevellock.S (__lll_mutex_lock_wait): + Rewrite so that only one locked memory operation per round is needed. + * sysdeps/unix/sysv/linux/sh/pthread_barrier_wait.S + (pthread_barrier_wait): After wakeup, release lock only when the + last thread stopped using the barrier object. + * sysdeps/unix/sysv/linux/sh/pthread_cond_wait.S + (__pthread_cond_wait): Don't store mutex address if the current + value is ~0l. Add correct cleanup support and unwind info. + * sysdeps/unix/sysv/linux/sh/pthread_cond_timedwait.S: Likewise. + * sysdeps/unix/sysv/linux/sh/pthread_cond_broadcast.S + (__pthread_cond_broadcast): Don't use requeue for pshared condvars. + * sysdeps/unix/sysv/linux/sh/pthread_cond_signal.S: Update comment. + * sysdeps/unix/sysv/linux/sh/pthread_once.S (__pthread_once): + Add correct cleanup support and unwind info. + * sysdeps/unix/sysv/linux/sh/sem_wait.S (__new_sem_wait): Likewise. + * sysdeps/unix/sysv/linux/sh/sysdep-cancel.h: Add unwind + information for syscall wrappers. + +2004-03-18 Ulrich Drepper + + * sysdeps/unix/sysv/linux/internaltypes.h (struct pthread_attr): Add + cpusetsize field, remove next. + * sysdeps/pthread/pthread.h (pthread_getaffinity_np): Add new second + parameter for size of the CPU set. + (pthread_setaffinity_np): Likewise. + (pthread_attr_getaffinity_np): Likewise. + (pthread_attr_setaffinity_np): Likewise. + * sysdeps/unix/sysv/linux/pthread_attr_getaffinity.c: Implement + interface change, keep compatibility code. + * sysdeps/unix/sysv/linux/pthread_attr_setaffinity.c: Likewise. + * sysdeps/unix/sysv/linux/pthread_getaffinity.c: Likewise. + * sysdeps/unix/sysv/linux/pthread_setaffinity.c: Likewise. + * pthreadP.h: Remove hidden_proto for pthread_getaffinity_np. Declare + __pthread_getaffinity_np. + * Versions: Add version for changed interfaces. + * tst-attr3.c: Adjust test for interface change. + * pthread_getattr_np.c: Query the kernel about the affinity mask with + increasing buffer sizes. + * pthread_attr_destroy.c: Remove unused list handling. + * pthread_attr_init.c: Likewise. + +2004-03-17 Roland McGrath + + * sysdeps/unix/sysv/linux/timer_create.c (timer_create): Pass missing + first argument to clock_getres so we ever enable kernel timers. + +2004-03-15 Ulrich Weigand + + * init.c (nptl_version): Add __attribute_used__ to nptl_version. + +2004-03-12 Richard Henderson + + * sysdeps/unix/sysv/linux/alpha/sysdep-cancel.h: Propagate + oldvalue from CENABLE to CDISABLE. + +2004-03-12 Ulrich Drepper + + * sysdeps/unix/sysv/linux/bits/local_lim.h: Define HOST_NAME_MAX. + * sysdeps/unix/sysv/linux/alpha/bits/local_lim.h: Likewise. + * sysdeps/unix/sysv/linux/ia64/bits/local_lim.h: Likewise. + * sysdeps/unix/sysv/linux/sparc/bits/local_lim.h: Likewise. + +2004-03-11 Richard Henderson + + * sysdeps/alpha/tcb-offsets.sym (PID_OFFSET): New. + * sysdeps/unix/sysv/linux/alpha/pt-vfork.S: Save/restore PID. + * sysdeps/unix/sysv/linux/alpha/vfork.S: New file. + +2004-03-11 Jakub Jelinek + + * sysdeps/unix/sysv/linux/s390/s390-64/vfork.S (__vfork): Use jgnl + instead of jnl instruction to jump to SYSCALL_ERROR_LABEL. + * sysdeps/unix/sysv/linux/s390/s390-64/pt-vfork.S (__vfork): Likewise. + +2004-03-11 Jakub Jelinek + + * forward.c (__pthread_cond_broadcast_2_0, + __pthread_cond_destroy_2_0, __pthread_cond_init_2_0, + __pthread_cond_signal_2_0, __pthread_cond_wait_2_0, + __pthread_cond_timedwait_2_0): Use return 0 as defaction instead of 0. + +2004-03-11 Kaz Kojima + + * sysdeps/sh/tcb-offsets.sym: Add PID. + * sysdeps/unix/sysv/linux/sh/pt-vfork.S: Properly handle PID cache. + * sysdeps/unix/sysv/linux/sh/vfork.S: New file. + +2004-03-10 Ulrich Drepper + + * sysdeps/unix/sysv/linux/powerpc/powerpc32/vfork.S: No need to + include , vfork is no cancellation point. + * sysdeps/unix/sysv/linux/powerpc/powerpc64/vfork.S: Likewise. + * sysdeps/unix/sysv/linux/powerpc/powerpc64/pt-vfork.S: Likewise. + * sysdeps/unix/sysv/linux/powerpc/powerpc32/pt-vfork.S: Likewise. + +2004-03-10 Jakub Jelinek + + * sysdeps/unix/sysv/linux/s390/s390-32/vfork.S (__vfork): Add + libc_hidden_def. + * sysdeps/unix/sysv/linux/s390/s390-64/vfork.S (__vfork): Likewise. + * sysdeps/unix/sysv/linux/powerpc/powerpc32/vfork.S (__vfork): + Likewise. + * sysdeps/unix/sysv/linux/powerpc/powerpc64/vfork.S (__vfork): + Likewise. + * sysdeps/unix/sysv/linux/sparc/sparc32/vfork.S (__vfork): Likewise. + * sysdeps/unix/sysv/linux/sparc/sparc64/vfork.S (__vfork): Likewise. + * sysdeps/unix/sysv/linux/ia64/pt-vfork.S: Include tcb-offsets.h. + * sysdeps/unix/sysv/linux/ia64/vfork.S (__vfork): Use DO_CALL instead + of DO_CALL_VIA_BREAK. Work around a gas problem. + + * sysdeps/unix/sysv/linux/powerpc/pt-vfork.S: Remove. + * sysdeps/unix/sysv/linux/powerpc/powerpc32/vfork.S: New file. + * sysdeps/unix/sysv/linux/powerpc/powerpc32/pt-vfork.S: New file. + * sysdeps/unix/sysv/linux/powerpc/powerpc64/vfork.S: New file. + * sysdeps/unix/sysv/linux/powerpc/powerpc64/pt-vfork.S: New file. + * sysdeps/powerpc/tcb-offsets.sym: Add PID. + + * sysdeps/unix/sysv/linux/ia64/pt-vfork.S (__vfork): Don't use + a local register for saving old PID. Negate PID in parent upon exit. + + * sysdeps/unix/sysv/linux/s390/s390-32/pt-vfork.S: Include + tcb-offsets.h. + (__vfork): Negate PID if non-zero and set to INT_MIN if zero + before syscall, set to the old value in the parent afterwards. + * sysdeps/unix/sysv/linux/s390/s390-32/vfork.S: New file. + * sysdeps/unix/sysv/linux/s390/s390-64/pt-vfork.S: Include + tcb-offsets.h. + (__vfork): Negate PID if non-zero and set to INT_MIN if zero + before syscall, set to the old value in the parent afterwards. + * sysdeps/unix/sysv/linux/s390/s390-64/vfork.S: New file. + * sysdeps/s390/tcb-offsets.sym: Add PID. + + * sysdeps/unix/sysv/linux/sparc/pt-vfork.S: Remove. + * sysdeps/unix/sysv/linux/sparc/sparc32/vfork.S: New file. + * sysdeps/unix/sysv/linux/sparc/sparc32/pt-vfork.S: New file. + * sysdeps/unix/sysv/linux/sparc/sparc64/vfork.S: New file. + * sysdeps/unix/sysv/linux/sparc/sparc64/pt-vfork.S: New file. + * sysdeps/sparc/tcb-offsets.sym: Add PID. + +2004-03-10 Andreas Schwab + + * sysdeps/ia64/tcb-offsets.sym: Add PID. + * sysdeps/unix/sysv/linux/ia64/vfork.S: New file. + * sysdeps/unix/sysv/linux/ia64/pt-vfork.S: Properly handle PID cache. + +2004-03-09 Jakub Jelinek + + * tst-cancel20.c (do_one_test): Clear in_sh_body first. + * tst-cancel21.c (do_one_test): Likewise. + Reported by Gordon Jin . + +2004-02-09 Jakub Jelinek + + * sysdeps/unix/sysv/linux/i386/vfork.S (SAVE_PID): Negate PID + if non-zero and set to INT_MIN if zero. + * sysdeps/unix/sysv/linux/x86_64/vfork.S (SAVE_PID): Likewise. + * sysdeps/unix/sysv/linux/i386/pt-vfork.S: Include tcb-offsets.h. + (SAVE_PID, RESTORE_PID): Define. + (__vfork): Use it. + * sysdeps/unix/sysv/linux/x86_64/pt-vfork.S: Include tcb-offsets.h. + Use relative path to avoid including NPTL i386/vfork.S. + (SAVE_PID, RESTORE_PID): Define. + * sysdeps/unix/sysv/linux/raise.c: Include limits.h. + (raise): Handle THREAD_SELF->pid INT_MIN the same as 0. + * Makefile (tests): Add tst-vfork1, tst-vfork2, tst-vfork1x and + tst-vfork2x. + (tests-reverse): Add tst-vfork1x and tst-vfork2x. + * tst-vfork1.c: New test. + * tst-vfork2.c: New test. + * tst-vfork1x.c: New test. + * tst-vfork2x.c: New test. + +2004-03-08 Ulrich Drepper + + * sysdeps/i386/tcb-offsets.sym: Add PID. + * sysdeps/x86_64/tcb-offsets.sym: Likewise. + * sysdeps/unix/sysv/linux/i386/vfork.S: New file. + * sysdeps/unix/sysv/linux/x86_64/vfork.S: New file. + +2004-03-08 Steven Munroe + + * sysdeps/unix/sysv/linux/powerpc/Versions: Remove leading tabs. + +2004-03-08 H.J. Lu + + * sysdeps/s390/tls.h (INIT_SYSINFO): _dl_sysinfo is now in + _rtld_global_ro. + +2004-03-07 Ulrich Drepper + + * sysdeps/ia64/tls.h (INIT_SYSINFO): _dl_sysinfo is now in + _rtld_global_ro. + + * tst-once4.c: Remove unnecessary macro definition. + + * tst-mutex7.c (do_test): Limit thread stack size. + * tst-once2.c (do_test): Likewise. + * tst-tls3.c (do_test): Likewise. + * tst-tls1.c (do_test): Likewise. + * tst-signal3.c (do_test): Likewise. + * tst-kill6.c (do_test): Likewise. + * tst-key4.c (do_test): Likewise. + * tst-join4.c (do_test): Likewise. + * tst-fork1.c (do_test): Likewise. + * tst-context1.c (do_test): Likewise. + * tst-cond2.c (do_test): Likewise. + * tst-cond10.c (do_test): Likewise. + * tst-clock2.c (do_test): Likewise. + * tst-cancel10.c (do_test): Likewise. + * tst-basic2.c (do_test): Likewise. + * tst-barrier4.c (do_test): Likewise. + +2004-03-05 Ulrich Drepper + + * sysdeps/i386/tls.h: Use GLRO instead of GL where appropriate. + +2004-03-01 Ulrich Drepper + + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S + (__pthread_cond_timedwait): Optimize wakeup test. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S + (__pthread_cond_wait): Likewise. + * sysdeps/pthread/pthread_cond_wait.c (__pthread_cond_wait): Likewise. + * sysdeps/pthread/pthread_cond_timedwait.c (__pthread_cond_timedwait): + Likewise. + +2004-02-29 Ulrich Drepper + + * sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S + (__lll_mutex_lock_wait): Optimize a bit more. Just one copy of + the atomic instruction needed. + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.S + (__lll_mutex_lock_wait): Likewise. + +2004-02-28 Ulrich Drepper + + * Makefile (tests): Add tst-cond14 and tst-cond15. + * tst-cond14.c: New file. + * tst-cond15.c: New file. + +2004-02-27 Ulrich Drepper + + * sysdeps/pthread/createthread.c (create_thread): Remove use of + CLONE_STOPPED. We cannot use SIGCONT which means CLONE_STOPPED + needs to be implemented differently to be useful. + +2004-02-26 Ulrich Drepper + + * pthread_attr_setschedparam.c: Don't test priority against limits + here. Set ATTR_FLAG_SCHED_SET flag. + * pthread_attr_setschedpolicy.c: Set ATTR_FLAG_POLICY_SET flag. + * pthread_create.c (__pthread_create_2_1): Copy scheduling attributes + from parent thread to child. If attribute is used and scheduling + parameters are not inherited, copy parameters from attribute or + compute them. Check priority value. + * pthread_getschedparam.c: If the parameters aren't known yet get + them from the kernel. + * pthread_setschedparam.c: Set ATTR_FLAG_SCHED_SET and + ATTR_FLAG_POLICY_SET flag for thread. + * sysdeps/unix/sysv/linux/internaltypes.h: Define ATTR_FLAG_SCHED_SET + and ATTR_FLAG_POLICY_SET. + + * sysdeps/pthread/createthread.c: Use tgkill if possible. + + * pthread_attr_getstackaddr.c (__pthread_attr_getstackaddr): Don't + fail if stack address hasn't been set. Just return 0. + +2004-02-25 Ulrich Drepper + + * Makefile (tests-nolibpthread): Add tst-unload. Don't link with + libpthread for the files in this list. + (CFLAGS-tst-unload): Removed. + * tst-unload.c (do_test): Don't use complete path for + LIBPHREAD_SO. + + * Makefile: Define sonames for tst-tls5mod, tst-_res1mod1, and + tst-_res1mod2. + +2004-02-22 Ulrich Drepper + + * sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S + (__lll_mutex_lock_wait): Rewrite so that only one locked memory + operation per round is needed. + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.S + (__lll_mutex_lock_wait): Likewise. + +2004-02-20 Ulrich Drepper + + * tst-cancel9.c (cleanup): Don't print to stderr. + +2004-02-20 Kaz Kojima + + * sysdeps/sh/jmpbuf-unwind.h (_JMPBUF_UNWINDS_ADJ): Fix variable name. + +2004-02-20 Jakub Jelinek + + * sysdeps/unix/sysv/linux/sparc/sparc32/sysdep-cancel.h + (__syscall_error_handler2): Call CDISABLE. + * sysdeps/unix/sysv/linux/sparc/sparc64/sysdep-cancel.h + (__syscall_error_handler2): Call CDISABLE. + + * sysdeps/pthread/pthread_barrier_wait.c (pthread_barrier_wait): + Release lock before the loop, don't reacquire it. + + * sysdeps/unix/sysv/linux/ia64/dl-sysdep.h (DL_ARGV_NOT_RELRO): Define. + +2004-02-19 Andreas Schwab + + * sysdeps/pthread/pthread_barrier_wait.c (pthread_barrier_wait): + Fix last change. + +2004-02-18 Ulrich Drepper + + * sysdeps/unix/sysv/linux/i386/i486/pthread_barrier_wait.S + (pthread_barrier_wait): After wakeup, release lock only when the + last thread stopped using the barrier object. + * sysdeps/unix/sysv/linux/x86_64/pthread_barrier_wait.S + (pthread_barrier_wait): Likewise. + * sysdeps/pthread/pthread_barrier_wait.c (pthread_barrier_wait): + Likewise. + * Makefile (tests): Add tst-barrier4. + * tst-barrier4.c: New file. + + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S + (__pthread_cond_timedwait): Perform timeout test while holding + internal lock to prevent wakeup race. + Patch by Dinakar Guniguntala . + * sysdeps/pthread/pthread_cond_timedwait.c + (__pthread_cond_timedwait): Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S + (__pthread_cond_timedwait): Likewise. + +2004-02-18 Jakub Jelinek + + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_unlock.S + (__pthread_rwlock_unlock): Access WRITER as 32-bit value. + * Makefile (tests): Add tst-rwlock13. + * tst-rwlock13.c: New test. + +2004-02-16 Ulrich Drepper + + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S + (__condvar_tw_cleanup): Little optimization. + Patch by Dinakar Guniguntala . + +2004-02-16 Steven Munroe + + * sysdeps/unix/sysv/linux/powerpc/pt-longjmp.c: Replace libc with + libpthread as "lib" parameter to SHLIB_COMPAT. + (__novmx_siglongjmp): Fix typo in function name. + (__novmx_longjmp): Fix typo in function name. + +2004-02-13 Ulrich Drepper + + * sysdeps/pthread/pthread_cond_wait.c (__pthread_cond_wait): Add a + __builtin_expect. + + * sysdeps/generic/pt-longjmp.c: Moved to... + * sysdeps/pthread/pt-longjmp.c: ...here. New file. + +2004-01-29 Steven Munroe + + * Makefile (libpthread-routines): Add pt-cleanup. + * pt-longjmp.c: Removed. + * pt-cleanup.c: Copied __pthread_cleanup_upto to here. New file. + * sysdeps/generic/pt-longjmp.c: Copied longjmp to here. New file. + * sysdeps/unix/sysv/linux/powerpc/Versions: New file. + Version longjmp, siglongjmp for GLIBC_2.3.4. + * sysdeps/unix/sysv/linux/powerpc/pt-longjmp.c: New File. + +2004-02-13 Ulrich Drepper + + * sysdeps/pthread/pthread_cond_timedwait.c + (__pthread_cond_timedwait): Optimize. Drop internal lock earlier. + Reuse code. Add __builtin_expects. + + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S + (__pthread_cond_timedwait): Get internal lock in case timeout has + passed before the futex syscall. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S: Likewise. + +2004-01-20 Ulrich Drepper + + * allocatestack.c: Pretty printing. + + * sysdeps/pthread/createthread.c (create_thread): Don't add + CLONE_DETACHED bit if it is not necessary. + +2004-01-16 Ulrich Drepper + + * pthread_getattr_np.c: Include ldsodefs.h. + +2004-01-16 Richard Henderson + + * allocatestack.c: Don't declare __libc_stack_end. + * init.c (__pthread_initialize_minimal_internal): Likewise. + * pthread_getattr_np.c (pthread_getattr_np): Likewise. + +2004-01-15 Richard Henderson + + * sysdeps/alpha/tls.h (tcbhead_t): Add private. + (TLS_INIT_TCB_SIZE, TLS_INIT_TCB_ALIGN, TLS_TCB_SIZE, + TLS_PRE_TCB_SIZE, TLS_TCB_ALIGN, INSTALL_DTV, INSTALL_NEW_DTV, + GET_DTV, THREAD_DTV, THREAD_SELF, DB_THREAD_SELF): Match ia64. + (TLS_TCB_OFFSET, THREAD_ID, NO_TLS_OFFSET): Remove. + (THREAD_GETMEM, THREAD_GETMEM_NC): Simplify. + (THREAD_SETMEM, THREAD_SETMEM_NC): Likewise. + * sysdeps/unix/sysv/linux/alpha/createthread.c (TLS_VALUE): Match ia64. + +2004-01-14 Ulrich Drepper + + * init.c (pthread_functions): Make array const. + +2004-01-13 Ulrich Drepper + + * allocatestack.c (__make_stacks_executable): Change interface. + Check parameters. Pass parameter on to libc counterpart. + * pthreadP.h: Change declaration. + +2004-01-13 Richard Henderson + + * pthread_attr_setstack.c (__old_pthread_attr_setstack): Use + prototype form. + * pthread_attr_setstacksize.c (__old_pthread_attr_setstacksize): + Likewise. + + * sysdeps/alpha/Makefile: New file. + * sysdeps/alpha/tcb-offsets.sym: New file. + * sysdeps/unix/sysv/linux/alpha/sysdep-cancel.h (SINGLE_THREAD_P): + Use MULTIPLE_THREADS_OFFSET to implement !libpthread !libc version. + + * sysdeps/unix/sysv/linux/alpha/lowlevellock.h: Rewrite based + on powerpc version. + +2004-01-08 Jakub Jelinek + + * Makefile (tests): Add tst-backtrace1. + * tst-backtrace1.c: New test. + +2003-12-11 Ulrich Weigand + + * sysdeps/alpha/tls.h (DB_THREAD_SELF): Pass bit size of thread + register as second parameter to the REGISTER macro. + * sysdeps/ia64/tls.h (DB_THREAD_SELF): Likewise. + * sysdeps/powerpc/tls.h (DB_THREAD_SELF): Likewise. + * sysdeps/sh/tls.h (DB_THREAD_SELF): Likewise. + * sysdeps/sparc/tls.h (DB_THREAD_SELF): Likewise. + * sysdeps/s390/tls.h (DB_THREAD_SELF): Pass __WORDSIZE as bit size + of thread register as second parameter to REGISTER macro in 64 case. + +2004-01-03 Ulrich Drepper + + * sysdeps/unix/sysv/linux/Makefile (CFLAGS-getpid.c): Removed. + (CFLAGS-getpid.o): Defined. + (CFLAGS-getpid.os): Defined. + +2003-12-31 Ulrich Drepper + + * pthread_getattr_np.c (pthread_getattr_np): Make sure stack info + returned for main thread does not overlap with any other VMA. + Patch by Jakub Jelinek. + +2003-12-29 Jakub Jelinek + + * tst-raise1.c: Include stdio.h. + +2003-12-23 Jakub Jelinek + + * sysdeps/unix/sysv/linux/raise.c (raise): Protect pid = selftid + setting with __ASSUME_TGKILL || defined __NR_tgkill. + If pid is 0, set it to selftid. + * sysdeps/unix/sysv/linux/getpid.c (really_getpid): Make inline. + Don't set self->pid but self->tid. If self->pid == 0 and self->tid + != 0, return self->tid without doing a syscall. + * descr.h (struct pthread): Move pid field after tid. + + * Makefile (tests): Add tst-raise1. + * tst-raise1.c: New file. + +2003-12-23 Roland McGrath + + * tst-oddstacklimit.c: New file. + * Makefile (tests): Add it. + (tst-oddstacklimit-ENV): New variable. + + * init.c (__pthread_initialize_minimal_internal): Round stack rlimit + value up to page size for __default_stacksize. + +2003-12-21 Ulrich Drepper + + * Makefile (tests): Add tst-eintr5. + * tst-eintr5.c: New file. + + * eintr.c (eintr_source): Prevent sending signal to self. + + * tst-eintr2.c (tf1): Improve error message. + +2003-12-20 Ulrich Drepper + + * sysdeps/unix/sysv/linux/Makefile (CFLAGS-getpid.c): Define. + * sysdeps/unix/sysv/linux/getpid.c: New file. + * pthread_cancel.c: Add comment explaining use of PID field. + * sysdeps/unix/sysv/linux/pthread_kill.c: Likewise. + * pthread_getattr_np.c: Use abs() when comparing PID and TID fields. + * sysdeps/unix/sysv/linux/fork.c: Negate PID field of parent + temporarily to signal the field must not be relied on and updated + by getpid(). + * sysdeps/unix/sysv/linux/pt-raise.c: Handle case where PID is + temporarily negative. + * sysdeps/unix/sysv/linux/raise.c: Likewise. + +2003-12-19 Ulrich Drepper + + * eintr.c (setup_eintr): Add new parameter. Pass to thread function. + (eintr_source): If ARG != NULL, use pthread_kill. + * tst-eintr1.c: Adjust for this change. + * tst-eintr2.c: Likewise. + * Makefile (tests): Add tst-eintr3 and tst-eintr4. + * tst-eintr3.c: New file. + * tst-eintr4.c: New file. + +2003-12-19 Jakub Jelinek + + * libc-cancellation.c (__libc_enable_asynccancel): Don't cancel + if CANCELSTATE_BITMASK is set. + * sysdeps/pthread/librt-cancellation.c (__librt_enable_asynccancel): + Likewise. + + * Makefile (tests): Add tst-cancel22 and tst-cancel23. + (tests-reverse): Add tst-cancel23. + * tst-cancel22.c: New test. + * tst-cancel23.c: New test. + +2003-12-18 Ulrich Drepper + + * tst-eintr1.c: Better error messages. + + * Makefile (tests): Add tst-eintr2. + * tst-eintr2.c: New file. + +2003-12-18 Jakub Jelinek + + * Makefile (tests): Add tst-cancel21 and tst-cancelx21. + (CFLAGS-tst-cancelx21.c): Set. + * tst-cancel21.c: New test. + * tst-cancelx21.c: New test. + + * unwind.c (FRAME_LEFT): Add adj argument. Subtract it from each + comparison operand. + (unwind_stop): Use _JMPBUF_CFA_UNWINDS_ADJ macro instead of + _JMPBUF_CFA_UNWINDS. Adjust FRAME_LEFT invocations. + * pt-longjmp.c: Include jmpbuf-unwind.h. + (__pthread_cleanup_upto): Use _JMPBUF_UNWINDS_ADJ macro instead of + _JMPBUF_UNWINDS. Adjust compared pointers. + * init.c (__pthread_initialize_minimal_internal): Initialize + pd->stackblock_size. + * sysdeps/pthread/jmpbuf-unwind.h: Removed. + * sysdeps/alpha/jmpbuf-unwind.h: New file. + * sysdeps/i386/jmpbuf-unwind.h: New file. + * sysdeps/powerpc/jmpbuf-unwind.h: New file. + * sysdeps/s390/jmpbuf-unwind.h: New file. + * sysdeps/sh/jmpbuf-unwind.h: New file. + * sysdeps/sparc/sparc32/jmpbuf-unwind.h: New file. + * sysdeps/x86_64/jmpbuf-unwind.h: New file. + * sysdeps/unix/sysv/linux/ia64/jmpbuf-unwind.h: Include stdint.h. + (_JMPBUF_CFA_UNWINDS): Remove. + (_JMPBUF_CFA_UNWINDS_ADJ, _JMPBUF_UNWINDS_ADJ): Define. + +2003-12-12 Jakub Jelinek + + * Makefile (tests): Add tst-cancel20 and tst-cancelx20. + (CFLAGS-tst-cancelx20.c): Set. + * tst-cancel20.c: New test. + * tst-cancelx20.c: New test. + +2003-12-17 Ulrich Drepper + + * init.c (__pthread_initialize_minimal_internal): Don't treat + architectures with separate register stack special here when + computing default stack size. + +2003-12-17 Roland McGrath + + * Makefile (tst-cancelx7-ARGS): New variable. + Reportd by Greg Schafer . + +2003-12-17 Jakub Jelinek + + * Makefile (tests): Add tst-stack3. Depend on $(objpfx)tst-stack3-mem. + (generated): Add tst-stack3.mtrace and tst-stack3-mem. + (tst-stack3-ENV): Set. + ($(objpfx)tst-stack3-mem): New. + * tst-stack3.c: New test. + +2003-12-10 David Mosberger + + * sysdeps/unix/sysv/linux/ia64/pt-initfini.c (_init_EPILOG_BEGINS): + Add unwind directives. Drop unused .regstk directive. + (_fini_EPILOG_BEGINS): Add unwind directives. + +2003-12-11 Ulrich Drepper + + * sysdeps/unix/sysv/linux/i386/lowlevellock.h (lll_futex_wait): + Assume parameter is a pointer. + (lll_futex_wake): Likewise. + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.h (lll_futex_wait): + Likewise. + (lll_futex_wake): Likewise. + Reported by Boris Hu. + * sysdeps/unix/sysv/linux/unregister-atfork.c + (__unregister_atfork): Pass pointer to refcntr to lll_futex_wait. + + * sysdeps/unix/sysv/linux/sem_wait.c (__new_sem_wait): Simplify a bit. + +2003-12-10 Ulrich Drepper + + * sysdeps/pthread/bits/libc-lock.h (__rtld_lock_initialize): Define. + * sysdeps/unix/sysv/linux/fork.c (__libc_fork): Call + __rtld_lock_initialize for ld.so lock. + Patch in part by Adam Li . + +2003-12-02 David Mosberger + + * Makefile (link-libc-static): Remove -lgcc_eh---it's already mentioned + in $(gnulib). Also, remove stale comment. + +2003-11-12 David Mosberger + + * sysdeps/unix/sysv/linux/ia64/sysdep-cancel.h (PSEUDO): Take + advantage of new syscall stub and optimize accordingly. + + * sysdeps/unix/sysv/linux/ia64/lowlevellock.h (__NR_futex): Rename + from SYS_futex, to match expectations of + sysdep.h:DO_INLINE_SYSCALL. + (lll_futex_clobbers): Remove. + (lll_futex_timed_wait): Rewrite in terms of DO_INLINE_SYSCALL. + (lll_futex_wake): Likewise. + (lll_futex_requeue): Likewise. + (__lll_mutex_trylock): Rewrite to a macro, so we can include this + file before DO_INLINE_SYSCALL is defined (proposed by Jakub + Jelinek). + (__lll_mutex_lock): Likewise. + (__lll_mutex_cond_lock): Likewise. + (__lll_mutex_timed_lock): Likewise. + (__lll_mutex_unlock): Likewise. + (__lll_mutex_unlock_force): Likewise. + + * sysdeps/ia64/tls.h: Move declaration of __thread_self up so it + comes before the include of . + (THREAD_SELF_SYSINFO): New macro. + (THREAD_SYSINFO): Likewise. + (INIT_SYSINFO): New macro. + (TLS_INIT_TP): Call INIT_SYSINFO. + + * sysdeps/ia64/tcb-offsets.sym: Add SYSINFO_OFFSET. + + * sysdeps/pthread/createthread.c (create_thread): Use + THREAD_SELF_SYSINFO and THREAD_SYSINFO instead of open code. + * allocatestack.c (allocate_stack): Use THREAD_SYSINFO and + THREAD_SELF_SYSINFO instead of open code. + * sysdeps/i386/tls.h (THREAD_SELF_SYSINFO): New macro. + (THREAD_SYSINFO): Likewise. + + * sysdeps/unix/sysv/linux/ia64/dl-sysdep.h: New file. + + * sysdeps/unix/sysv/linux/ia64/pt-vfork.S: Work around gas problem. + +2003-12-06 Ulrich Drepper + + * sysdeps/unix/sysv/linux/ia64/pt-initfini.c: Use .init_array + instead of .init. Patch by David Mosberger. + +2003-11-30 Thorsten Kukuk + + * sysdeps/pthread/configure.in: Remove broken declaration in C + cleanup handling check. + +2003-11-30 Andreas Jaeger + + * Makefile (CFLAGS-pt-initfini.s): Add $(fno_unit_at_a_time). + * sysdeps/unix/sysv/linux/x86_64/Makefile (CFLAGS-pt-initfini.s): + Likewise. + +2003-11-27 Jakub Jelinek + + * sysdeps/unix/sysv/linux/internaltypes.h (ATTR_FLAG_OLDATTR): Define. + * pthread_attr_destroy.c: Include shlib-compat.h. + (__pthread_attr_destroy): Return immediately if ATTR_FLAG_OLDATTR + is set in iattr->flags. + * pthread_attr_init.c (__pthread_attr_init_2_0): Set ATTR_FLAG_OLDATTR. + +2003-11-21 Jakub Jelinek + + * Makefile (distribute): Add tst-cleanup4aux.c. + + * tst-cond12.c (prepare): Add prototype. Move after test-skeleton.c + include. + +2003-11-21 Ulrich Drepper + + * tst-cond12.c (do_test): If USE_COND_SIGNAL is defined, use + pthread_cond_signal. + + * sysdeps/pthread/pthread_cond_wait.c (__pthread_cond_wait): Don't + store mutex address if the current value is ~0l. + * sysdeps/pthread/pthread_cond_timedwait.c + (__pthread_cond_timedwait): Likewise. + * sysdeps/pthread/pthread_cond_broadcast.c + (__pthread_cond_broadcast): Don't use requeue for pshared + condvars. + + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S + (__pthread_cond_wait): Don't store mutex address if the current + value is ~0l. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S + (__pthread_cond_timedwait): Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S + (__pthread_cond_broadcast): Don't use requeue for pshared + condvars. + + * pthread_cond_init.c (__pthread_cond_init): Initialize __mutex + element with ~0l for pshared condvars, with NULL otherwise. + + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S + (__pthread_cond_wait): Don't store mutex address if the current + value is ~0l. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S + (__pthread_cond_timedwait): Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.S + (__pthread_cond_broadcast): Don't use requeue for pshared + condvars. + + * Makefile: Add rules to build and run tst-cond12 and tst-cond13. + * tst-cond12.c: New file. + * tst-cond13.c: New file. + +2003-11-17 Ulrich Drepper + + * sysdeps/pthread/configure.in: Make missing forced unwind support + fatal. + +2003-11-11 Ulrich Drepper + + * pthreadP.h: Don't declare __pthread_unwind as weak inside libpthread. + +2003-11-06 Ulrich Drepper + + * Makefile: Add magic to clean up correctly. + +2003-11-05 Jakub Jelinek + + * unwind.c (FRAME_LEFT): Define. + (unwind_stop): Handle old style cleanups here. + (__pthread_unwind): Handle old style cleanups only if + !HAVE_FORCED_UNWIND. + * Makefile (tests): Add tst-cleanup4 and tst-cleanupx4. + (CFLAGS-tst-cleanupx4.c): Add -fexceptions. + ($(objpfx)tst-cleanup4): Depend on $(objpfx)tst-cleanup4aux.o. + ($(objpfx)tst-cleanupx4): Likewise. + * tst-cleanup4.c: New test. + * tst-cleanup4aux.c: New. + * tst-cleanupx4.c: New test. + +2003-11-04 Ulrich Drepper + + * sysdeps/pthread/bits/stdio-lock.h: Use lll_*lock instead of + lll_mutex_*lock macros to skip atomic operations on some archs. + +2003-11-03 Ulrich Drepper + + * sysdeps/pthread/tst-timer.c (main): Initialize + sigev2.sigev_value as well. + +2003-10-15 Roland McGrath + + * sysdeps/pthread/configure.in: Barf if visibility attribute support + is missing. + * sysdeps/pthread/configure: Regenerated. + +2003-10-09 Kaz Kojima + + * sysdeps/unix/sysv/linux/sh/lowlevellock.h: Completely revamp the + locking macros. No distinction between normal and mutex locking + anymore. + * sysdeps/unix/sysv/linux/sh/lowlevellock.S: Rewrite mutex locking. + Merge bits from lowlevelmutex.S we still need. + * sysdeps/unix/sysv/linux/sh/libc-lowlevelmutex.S: Remove. + * sysdeps/unix/sysv/linux/sh/lowlevelmutex.S: Likewise. + * sysdeps/unix/sysv/linux/sh/not-cancel.h: New file. + * sysdeps/unix/sysv/linux/sh/pthread_barrier_wait.S: Adjust for + new mutex implementation. + * sysdeps/unix/sysv/linux/sh/pthread_cond_broadcast.S: Likewise. + * sysdeps/unix/sysv/linux/sh/pthread_cond_signal.S: Likewise. + * sysdeps/unix/sysv/linux/sh/pthread_cond_timedwait.S: Likewise. + * sysdeps/unix/sysv/linux/sh/pthread_cond_wait.S: Likewise. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_rdlock.S: Likewise. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedrdlock.S: Likewise. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedwrlock.S: Likewise. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_unlock.S: Likewise. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_wrlock.S: Likewise. + * sysdeps/unix/sysv/linux/sh/sysdep-cancel.h (PSEUDO): Also defined + symbol for entry point to avoid cancellation. + +2003-10-07 Jakub Jelinek + + * sysdeps/unix/sysv/linux/i386/sysdep-cancel.h: Backout 2003-10-02 + changes. + (SAVE_OLDTYPE_0): Fix a typo. + +2003-10-03 Ulrich Drepper + + * sysdeps/unix/sysv/linux/i386/pthread_once.S (__pthread_once): + Check __sigsetjmp return value. Reported by Daniel Jacobowitz. + +2003-10-02 Ulrich Drepper + + * sysdeps/unix/sysv/linux/i386/sysdep-cancel.h (DOCARGS_1): Use + correct offset. + +2003-10-02 Jakub Jelinek + + * Makefile (tests): Add tst-cancel19. + * tst-cancel19.c: New test. + +2003-10-02 Ulrich Drepper + + * sysdeps/unix/sysv/linux/i386/sysdep-cancel.h: Fix saving and + restoring of the old cancellation type. + +2003-09-30 Jakub Jelinek + + * sysdeps/pthread/malloc-machine.h: Remove misleading comment. + +2003-09-27 Wolfram Gloger + + * sysdeps/pthread/malloc-machine.h: New file + +2003-09-24 Roland McGrath + + * allocatestack.c (__make_stacks_executable): Don't ignore return + value from _dl_make_stack_executable. + +2003-09-24 Ulrich Drepper + + * allocatestack.c (__make_stacks_executable): Also change + permission of the currently unused stacks. + + * allocatestack.c (change_stack_perm): Split out from + __make_stacks_executable. + (allocate_stack): If the required permission changed between the time + we started preparing the stack and queueing it, change the permission. + (__make_stacks_executable): Call change_stack_perm. + + * Makefile: Build tst-execstack-mod locally. + * tst-execstack-mod.c: New file. + +2003-09-23 Jakub Jelinek + + * Makefile (tests): Only add tst-execstack if have-z-execstack is yes. + +2003-09-23 Roland McGrath + + * tst-execstack.c: New file. + * Makefile (tests): Add it. + ($(objpfx)tst-execstack, $(objpfx)tst-execstack.out): New targets. + (LDFLAGS-tst-execstack): New variable. + + * allocatestack.c (allocate_stack): Use GL(dl_stack_flags) to decide + whether to use PROT_EXEC for stack mmap. + (__make_stacks_executable): New function. + * pthreadP.h: Declare it. + * init.c (__pthread_initialize_minimal_internal): Set + GL(dl_make_stack_executable_hook) to that. + +2003-09-22 Ulrich Drepper + + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.h: Adjust for latest + recommendation from AMD re avoidance of lock prefix. + +2003-09-22 Jakub Jelinek + + * sysdeps/unix/sysv/linux/lowlevellock.c (__lll_timedlock_wait): Use + lll_futex_timed_wait instead of lll_futex_wait. + * sysdeps/unix/sysv/linux/s390/lowlevellock.c: Removed. + * sysdeps/unix/sysv/linux/s390/lowlevelmutex.c: Removed. + * sysdeps/unix/sysv/linux/s390/libc-lowlevellock.c: Removed. + * sysdeps/unix/sysv/linux/s390/libc-lowlevelmutex.c: Removed. + * sysdeps/unix/sysv/linux/s390/sem_trywait.c: Removed. + * sysdeps/unix/sysv/linux/s390/sem_wait.c: Removed. + * sysdeps/unix/sysv/linux/s390/sem_post.c: Removed. + * sysdeps/unix/sysv/linux/s390/sem_timedwait.c: Removed. + * sysdeps/unix/sysv/linux/s390/lowlevellock.h: Include atomic.h. + Completely revamp the locking macros. No distinction between + normal and mutex locking anymore. + * sysdeps/unix/sysv/linux/sparc/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/ia64/lowlevellock.h (__lll_lock_wait, + __lll_lock_timedwait): Fix prototypes. + * sysdeps/unix/sysv/linux/powerpc/lowlevellock.h (__lll_lock_wait, + __lll_lock_timedwait): Likewise. + (lll_mutex_lock, lll_mutex_cond_lock): Use _val instead of _bool + macros, add __builtin_expect. + (lll_mutex_timedlock): Likewise. Fix return value. + * sysdeps/unix/sysv/linux/i386/i486/libc-lowlevelmutex.S: Removed. + * sysdeps/unix/sysv/linux/i386/i586/libc-lowlevelmutex.S: Removed. + * sysdeps/unix/sysv/linux/i386/i586/lowlevelmutex.S: Removed. + * sysdeps/unix/sysv/linux/i386/i686/libc-lowlevelmutex.S: Removed. + * sysdeps/unix/sysv/linux/i386/i686/lowlevelmutex.S: Removed. + * sysdeps/unix/sysv/linux/x86_64/libc-lowlevelmutex.S: Removed. + * sysdeps/unix/sysv/linux/lowlevelmutex.c: Removed. + * sysdeps/unix/sysv/linux/libc-lowlevelmutex.c: Removed. + +2003-09-22 Ulrich Drepper + + * sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S + (__lll_mutex_lock_wait): Minor optimization to avoid one atomic + operation if possible. + + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.h: Don't play tricks + like jumping over the lock prefix. + +2003-09-21 Ulrich Drepper + + * sysdeps/unix/sysv/linux/i386/lowlevellock.h: Completely revamp the + locking macros. No distinction between normal and mutex locking + anymore. + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/ia64/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/powerpc/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S: Rewrite mutex + locking. Merge bits from lowlevelmutex.S we still need. + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.S: Likewise. + * sysdeps/unix/sysv/linux/lowlevellock.c: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/lowlevelmutex.S: Removed. + * sysdeps/unix/sysv/linux/x86_64/lowlevelmutex.S: Removed. + * Makefile (routines): Remove libc-lowlevelmutex. + (libpthread-rountines): Remove lowlevelmutex. + * sysdeps/unix/sysv/linux/i386/i486/pthread_barrier_wait.S: Adjust + for new mutex implementation. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_rdlock.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedrdlock.S: + Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedwrlock.S: + Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_unlock.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_wrlock.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_barrier_wait.S: Likewise + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_rdlock.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedrdlock.S: + Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedwrlock.S: + Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_unlock.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_wrlock.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_signal.S: Likewise. + Don't use requeue. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.S: Likewise. + * sysdeps/pthread/pthread_cond_signal.c: Don't use requeue. + +2003-09-20 Ulrich Drepper + + * sysdeps/unix/sysv/linux/i386/lowlevellock.h: Don't match memory + in parameters of asm with output parameters. + + * pthread_mutex_unlock.c (__pthread_mutex_unlock_usercnt): Change + type of DECR parameter to int. + * pthreadP.h: Adjust prototype of __pthread_mutex_unlock_usercnt. + +2003-09-18 Jakub Jelinek + + * tst-attr3.c (tf, do_test): Print stack start/end/size and + guardsize for each thread. + +2003-09-17 Jakub Jelinek + + * sysdeps/pthread/pthread.h (pthread_getattr_np): Clarify usage. + * sysdeps/unix/sysv/linux/pthread_attr_setaffinity.c + (pthread_attr_setaffinity_np): Handle cpuset == NULL. + + * sysdeps/unix/sysv/linux/pthread_attr_getaffinity.c + (pthread_attr_getaffinity_np): Don't segfault if iattr->cpuset is + NULL. + * pthread_getattr_np.c: Set cpuset using pthread_getaffinity_np. + * pthreadP.h (pthread_getaffinity_np): Add hidden_proto. + * sysdeps/unix/sysv/linux/pthread_getaffinity.c + (pthread_getaffinity_np): Add hidden_def. + + * Makefile (tests): Add tst-attr3. + * tst-attr3.c: New test. + + * sysdeps/i386/Makefile (CFLAGS-tst-align.c): Remove. + +2003-09-15 Jakub Jelinek + + * sysdeps/i386/Makefile (CFLAGS-pthread_create.c, + CFLAGS-tst-align.c): Add -mpreferred-stack-boundary=4. + +2003-09-17 Jakub Jelinek + + * Makefile (CFLAGS-tst-align.c): Add $(stack-align-test-flags). + * tst-align.c: Include tst-stack-align.h. + (tf, do_test): Use TEST_STACK_ALIGN macro. + +2003-09-17 Ulrich Drepper + + * pthread_attr_init.c (__pthread_attr_init_2_0): Remove unused + variable. + +2003-09-16 Ulrich Drepper + + * pthread_getattr_np.c (pthread_getattr_np): Correctly fill in the + stack-related values for the initial thread. + +2003-09-15 Jakub Jelinek + + * Makefile (CFLAGS-pthread_once.c): Add $(uses-callbacks). + +2003-09-11 Ulrich Drepper + + * pthread_mutex_lock.c: Minor code rearrangements. + +2003-09-05 Roland McGrath + + * pthread_create.c (__pthread_pthread_sizeof_descr): Removed. + Instead, include ../nptl_db/db_info.c to do its magic. + * pthread_key_create.c (__pthread_pthread_keys_max): Removed. + (__pthread_pthread_key_2ndlevel_size): Likewise. + * sysdeps/alpha/tls.h (DB_THREAD_SELF): New macro. + * sysdeps/i386/tls.h (DB_THREAD_SELF): New macro. + * sysdeps/ia64/tls.h (DB_THREAD_SELF): New macro. + * sysdeps/powerpc/tls.h (DB_THREAD_SELF): New macro. + * sysdeps/s390/tls.h (DB_THREAD_SELF): New macro. + * sysdeps/sh/tls.h (DB_THREAD_SELF): New macro. + * sysdeps/sparc/tls.h (DB_THREAD_SELF): New macro. + * sysdeps/x86_64/tls.h (DB_THREAD_SELF): New macro. + * sysdeps/alpha/td_ta_map_lwp2thr.c: File removed. + * sysdeps/generic/td_ta_map_lwp2thr.c: File removed. + * sysdeps/i386/td_ta_map_lwp2thr.c: File removed. + * sysdeps/ia64/td_ta_map_lwp2thr.c: File removed. + * sysdeps/powerpc/td_ta_map_lwp2thr.c: File removed. + * sysdeps/s390/td_ta_map_lwp2thr.c: File removed. + * sysdeps/sh/td_ta_map_lwp2thr.c: File removed. + * sysdeps/sparc/td_ta_map_lwp2thr.c: File removed. + * sysdeps/x86_64/td_ta_map_lwp2thr.c: File removed. + +2003-09-08 Ulrich Drepper + + * sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h: Change type + of pthread_t to be compatible with LT. + * sysdeps/unix/sysv/linux/sparc/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h: Likewise. + +2003-09-04 Ulrich Drepper + + * sysdeps/unix/sysv/linux/i386/not-cancel.h (fcntl_not_cancel): Define. + +2003-09-04 Jakub Jelinek + + * unwind-forcedunwind.c: Move to... + * sysdeps/pthread/unwind-forcedunwind.c: ...here. + (pthread_cancel_init): Use ARCH_CANCEL_INIT if defined. + * sysdeps/pthread/jmpbuf-unwind.h: New file. + * sysdeps/unix/sysv/linux/ia64/unwind-forcedunwind.c: New file. + * sysdeps/unix/sysv/linux/ia64/jmpbuf-unwind.h: New file. + * unwind.c: Include jmpbuf-unwind.h. + (unwind_stop): Use _JMPBUF_CFA_UNWINDS macro. + +2003-09-02 Jakub Jelinek + + * sysdeps/unix/sysv/linux/ia64/bits/local_lim.h: New file. + * sysdeps/unix/sysv/linux/ia64/Versions (libpthread): Export + pthread_attr_setstack and pthread_attr_setstacksize @@GLIBC_2.3.3. + * sysdeps/unix/sysv/linux/alpha/bits/local_lim.h: New file. + * sysdeps/unix/sysv/linux/alpha/Versions: New file. + * sysdeps/unix/sysv/linux/sparc/bits/local_lim.h: New file. + * sysdeps/unix/sysv/linux/sparc/Versions: New file. + * pthread_attr_setstack.c (__old_pthread_attr_setstack): New function. + (pthread_attr_setstack): If PTHREAD_STACK_MIN != 16384, export + as @@GLIBC_2.3.2 and also export compatibility @GLIBC_2.2. + * pthread_attr_setstacksize.c (__old_pthread_attr_setstacksize): New + function. + (pthread_attr_setstacksize): If PTHREAD_STACK_MIN != 16384, export + as @@GLIBC_2.3.2 and also export compatibility @GLIBC_2.1. + * Makefile (tests): Add tst-stack2. + * tst-stack2.c: New test. + * tst-stack1.c: Include limits.h and sys/param.h. + (do_test): Set size to MAX (4 * getpagesize (), PTHREAD_STACK_MIN). + + * pthread_condattr_setpshared.c: Include errno.h. + (pthread_condattr_setpshared): Return EINVAL if pshared + is neither PTHREAD_PROCESS_PRIVATE nor PTHREAD_PROCESS_SHARED. + + * sysdeps/unix/sysv/linux/s390/s390-32/sysdep-cancel.h (PSEUDO): Also + defined symbol for entry point to avoid cancellation. + * sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h (PSEUDO): + Likewise. + * sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h (PSEUDO): + Likewise. + * sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h (PSEUDO): + Likewise. + * sysdeps/unix/sysv/linux/sparc/sparc32/sysdep-cancel.h (PSEUDO): + Likewise. + * sysdeps/unix/sysv/linux/sparc/sparc64/sysdep-cancel.h (PSEUDO): + Likewise. + * sysdeps/unix/sysv/linux/i386/not-cancel.h (__open_nocancel, + __close_nocancel, __read_nocancel, __write_nocancel, + __waitpid_nocancel): Add attribute_hidden. If not in libc.so, + libpthread.so or librt.so, define to corresponding function + without _nocancel suffix. + * sysdeps/unix/sysv/linux/s390/not-cancel.h: New file. + * sysdeps/unix/sysv/linux/powerpc/not-cancel.h: New file. + * sysdeps/unix/sysv/linux/sparc/not-cancel.h: New file. + + * sysdeps/unix/sysv/linux/x86_64/not-cancel.h: Fix a typo. + +2003-09-02 Ulrich Drepper + + * sysdeps/unix/sysv/linux/i386/not-cancel.h: New file. + * sysdeps/unix/sysv/linux/x86_64/not-cancel.h: New file. + + * sysdeps/unix/sysv/linux/i386/lowlevellock.h: Make sure the code + in subsections has a symbol associated with it. + + * sysdeps/unix/sysv/linux/i386/sysdep-cancel.h (PSEUDO): Also + defined symbol for entry point to avoid cancellation. + * sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h (PSEUDO): Likewise. + +2003-09-01 Jakub Jelinek + + * Makefile (tests): Add tst-tls5. + (module-names): Add tst-tls5mod{,a,b,c,d,e,f}. + ($(objpfx)tst-tls5mod{,a,b,c,d,e,f}.so-no-z-defs): Set to yes. + ($(objpfx)tst-tls5): New. + ($(objpfx)tst-tls6.out): Likewise. + (tests): Depend on $(objpfx)tst-tls6.out. + * tst-tls3.c: Include stdint.h and pthreaddef.h. + (do_test): Check pthread_self () return value alignment. + * tst-tls3mod.c: Include stdint.h and pthreaddef.h. + (tf): Check pthread_self () return value alignment. + * tst-tls5.c: New test. + * tst-tls5.h: New. + * tst-tls5mod.c: New. + * tst-tls5moda.c: New. + * tst-tls5modb.c: New. + * tst-tls5modc.c: New. + * tst-tls5modd.c: New. + * tst-tls5mode.c: New. + * tst-tls5modf.c: New. + * tst-tls6.sh: New test. + + * sysdeps/pthread/pthread-functions.h (struct pthread_functions): Add + ptr___pthread_cond_timedwait and ptr___pthread_cond_timedwait_2_0. + * init.c (pthread_functions): Initialize them. + * forward.c (pthread_cond_timedwait@GLIBC_2.0, + pthread_cond_timedwait@@GLIBC_2.3.2): New forwards. + * Versions (libc): Export pthread_cond_timedwait@GLIBC_2.0, + pthread_cond_timedwait@@GLIBC_2.3.2. + +2003-09-01 Jakub Jelinek + + * sysdeps/unix/sysv/linux/alpha/timer_create.c: New file. + * sysdeps/unix/sysv/linux/alpha/timer_delete.c: New file. + * sysdeps/unix/sysv/linux/alpha/timer_getoverr.c: New file. + * sysdeps/unix/sysv/linux/alpha/timer_gettime.c: New file. + * sysdeps/unix/sysv/linux/alpha/timer_settime.c: New file. + * sysdeps/unix/sysv/linux/alpha/Versions: New file. + + * sysdeps/unix/sysv/linux/alpha/aio_cancel.c: New file. + + * sysdeps/unix/sysv/linux/ia64/bits/posix_opt.h: Define + _POSIX_THREAD_PRIORITY_SCHEDULING. + * sysdeps/unix/sysv/linux/x86_64/bits/posix_opt.h: Likewise. + +2003-08-31 Ulrich Drepper + + * sysdeps/pthread/bits/stdio-lock.h (_IO_acquire_lock): Avoid + nested function, use static inline function from libio.h. + Code by Richard Henderson. + + * sysdeps/pthread/bits/libc-lock.h: Mark pthread_setcancelstate as + weak. + +2003-08-30 Jakub Jelinek + + * sysdeps/unix/sysv/linux/sparc/sparc64/Versions: New file. + * sysdeps/unix/sysv/linux/sparc/sparc64/timer_create.c: New file. + * sysdeps/unix/sysv/linux/sparc/sparc64/timer_delete.c: New file. + * sysdeps/unix/sysv/linux/sparc/sparc64/timer_getoverr.c: New file. + * sysdeps/unix/sysv/linux/sparc/sparc64/timer_gettime.c: New file. + * sysdeps/unix/sysv/linux/sparc/sparc64/timer_settime.c: New file. + * sysdeps/unix/sysv/linux/sparc/sparc64/sysdep-cancel.h: New file. + * sysdeps/unix/sysv/linux/sparc/sparc32/sysdep-cancel.h: New file. + * sysdeps/unix/sysv/linux/sparc/bits/pthreadtypes.h: New file. + * sysdeps/unix/sysv/linux/sparc/bits/semaphore.h: New file. + * sysdeps/unix/sysv/linux/sparc/lowlevellock.h: New file. + * sysdeps/unix/sysv/linux/sparc/pthread_once.c: New file. + * sysdeps/unix/sysv/linux/sparc/pt-vfork.S: New file. + * sysdeps/unix/sysv/linux/sparc/fork.c: New file. + * sysdeps/unix/sysv/linux/sparc/aio_cancel.c: New file. + * sysdeps/sparc/sparc32/sparcv9/pthread_spin_lock.c: New file. + * sysdeps/sparc/sparc32/sparcv9/pthread_spin_trylock.c: New file. + * sysdeps/sparc/sparc32/sparcv9/pthread_spin_unlock.c: New file. + * sysdeps/sparc/sparc32/pthread_spin_lock.c: New file. + * sysdeps/sparc/sparc32/pthread_spin_trylock.c: New file. + * sysdeps/sparc/sparc32/pthreaddef.h: New file. + * sysdeps/sparc/sparc64/pthread_spin_lock.c: New file. + * sysdeps/sparc/sparc64/pthread_spin_trylock.c: New file. + * sysdeps/sparc/sparc64/pthread_spin_unlock.c: New file. + * sysdeps/sparc/sparc64/pthreaddef.h: New file. + * sysdeps/sparc/tls.h: New file. + * sysdeps/sparc/tcb-offsets.sym: New file. + * sysdeps/sparc/Makefile: New file. + * sysdeps/sparc/td_ta_map_lwp2thr.c: New file. + * init.c [__sparc__] (__NR_set_tid_address): Define. + +2003-08-29 Jakub Jelinek + + * sysdeps/pthread/bits/stdio-lock.h (_IO_acquire_lock, + _IO_release_lock): Define. + +2003-08-29 Jakub Jelinek + + * tst-cancel4.c (tf_sigwait, tf_sigwaitinfo, tf_sigtimedwait): Add + sigemptyset before sigaddset. Reported by jreiser@BitWagon.com. + +2003-08-27 Ulrich Drepper + + * sysdeps/pthread/pthread.h (pthread_exit): Remove __THROW. + (__pthread_cleanup_class): Add missing return types of member + functions. + +2003-08-26 Steven Munroe + + * sysdeps/unix/sysv/linux/powerpc/lowlevellock.h + (lll_mutex_unlock_force): Add memory barrier between store and futex + syscall. + +2003-08-25 Ulrich Drepper + + * tst-cancel4.c (do_test): Also unlink tempfname and remove + tempmsg in first loop. + +2003-08-18 Ulrich Drepper + + * sysdeps/unix/sysv/linux/bits/posix_opt.h: Define + _POSIX_THREAD_PRIORITY_SCHEDULING. + * sysdeps/unix/sysv/linux/i386/bits/posix_opt.h: Likewise. + +2003-08-07 Jakub Jelinek + + * sysdeps/pthread/bits/libc-lock.h [_LIBC && SHARED] + (__rtld_lock_default_lock_recursive, + __rtld_lock_default_unlock_recursive): Define. + [_LIBC && SHARED] (__rtld_lock_lock_recursive, + __rtld_lock_unlock_recursive): Define using + GL(_dl_rtld_*lock_recursive). + * init.c (__pthread_initialize_minimal_internal): Initialize + _dl_rtld_lock_recursive and _dl_rtld_unlock_recursive. + Lock GL(_dl_load_lock) the same number of times as + GL(_dl_load_lock) using non-mt implementation was nested. + + * pthreadP.h (__pthread_cleanup_upto): Add hidden_proto. + * pt-longjmp.c (__pthread_cleanup_upto): Add hidden_def. + +2003-08-06 Jakub Jelinek + + * tst-cancel17.c (do_test): Make len2 maximum of page size and + PIPE_BUF. + +2003-08-07 Jakub Jelinek + + * pthread_create.c (__pthread_create_2_0): Clear new_attr.cpuset. + +2003-08-03 Jakub Jelinek + + * sysdeps/pthread/createthread.c (do_clone): Move error handling + to first syscall error check. Move syscall error check for tkill + into __ASSUME_CLONE_STOPPED #ifdef. + +2003-08-02 Ulrich Drepper + + * sysdeps/pthread/createthread.c (do_clone): If __ASSUME_CLONE_STOPPED + is not defined, do explicit synchronization. + (create_thread): Do not lock pd->lock here. If __ASSUME_CLONE_STOPPED + is not defined also unlock pd->lock for non-debugging case in case + it is necessary. + * pthread_create.c (start_thread): Always get and release pd->lock + if __ASSUME_CLONE_STOPPED is not defined. + (start_thread_debug): Removed. Adjust users. + * allocatestack.c (allocate_stack): Always initialize lock if + __ASSUME_CLONE_STOPPED is not defined. + * Makefile (tests): Add tst-sched1. + * tst-sched1.c: New file. + + * sysdeps/pthread/createthread.c (do_clone): Only use + sched_setschduler and pass correct parameters. + +2003-07-31 Jakub Jelinek + + * sysdeps/pthread/pthread.h (pthread_attr_setstackaddr, + pthread_attr_setstacksize): Change PTHREAD_STACK_SIZE to + PTHREAD_STACK_MIN in comments. + +2003-07-31 Jakub Jelinek + + * sysdeps/pthread/pthread_cond_timedwait.c (__pthread_cond_timedwait): + Shut up warnings if INTERNAL_SYSCALL_ERROR_P does not use its first + argument. + * sysdeps/unix/sysv/linux/timer_create.c (timer_create): Likewise. + * pthread_condattr_setclock.c (pthread_condattr_setclock): Likewise. + * sysdeps/unix/sysv/linux/s390/jmp-unwind.c: Include pthreaddef.h. + (__pthread_cleanup_upto): Fix prototype. + (_longjmp_unwind): Adjust caller. + * sysdeps/unix/sysv/linux/s390/lowlevellock.h (__lll_mutex_timedlock): + Change second argument to const struct pointer. + * tst-sem8.c (main): Remove unused s2 and s3 variables. + * tst-sem9.c (main): Likewise. + * unwind.c: Include string.h for strlen prototype. + +2003-07-31 Ulrich Drepper + + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S + (__pthread_cond_timedwait): Don't use cmov unless HAVE_CMOV is defined. + * sysdeps/unix/sysv/linux/i386/i686/pthread_cond_timedwait.S: + Define HAVE_CMOV. + Patch by Nicholas Miell . + +2003-07-30 Jakub Jelinek + + * init.c (__pthread_initialize_minimal_internal): Initialize + GL(dl_init_static_tls). + * pthreadP.h (__pthread_init_static_tls): New prototype. + * allocatestack.c (init_one_static_tls, __pthread_init_static_tls): + New functions. + * Makefile (tests): Add tst-tls4. + (modules-names): Add tst-tls4moda and tst-tls4modb. + ($(objpfx)tst-tls4): Link against libdl and libpthread. + ($(objpfx)tst-tls4.out): Depend on tst-tls4moda.so and + tst-tls4modb.so. + * tst-tls4.c: New file. + * tst-tls4moda.c: New file. + * tst-tls4modb.c: New file. + +2003-06-19 Daniel Jacobowitz + + * sysdeps/pthread/timer_create.c (timer_create): Call timer_delref + before __timer_dealloc. + * sysdeps/pthread/timer_routines.c (__timer_thread_find_matching): + Don't call list_unlink. + +2003-07-29 Roland McGrath + + * Makefile [$(build-shared) = yes] (tests): Depend on $(test-modules). + +2003-07-25 Jakub Jelinek + + * tst-cancel17.c (do_test): Check if aio_cancel failed. + Don't reuse struct aiocb A if it failed. + Write fpathconf (fds[1], _PC_PIPE_BUF) + 2 bytes using aio_write, + not just one byte, as that does not block. + +2003-07-22 Jakub Jelinek + + * sysdeps/pthread/unwind-resume.c: New file. + * sysdeps/pthread/Makefile (routines, shared-only-routines): Add + unwind-resume in csu subdir. + (CFLAGS-unwind-resume.c, CFLAGS-rt-unwind-resume.c): Compile with + exceptions. + (librt-sysdep_routines, librt-shared-only-routines): Add + rt-unwind-resume. + * sysdeps/pthread/rt-unwind-resume.c: New file. + * unwind-forcedunwind.c: New file. + * Makefile (libpthread-routines): Add unwind-forcedunwind. + (libpthread-shared-only-routines): Likewise. + (CFLAGS-unwind-forcedunwind.c): Compile with exceptions. + * pthreadP.h (pthread_cancel_init): New prototype. + * pthread_cancel.c (pthread_cancel): Call pthread_cancel_init. + + * sysdeps/pthread/createthread.c (do_thread, create_thread): Make + attr argument const struct pthread_attr *. + + * res.c (__res_state): Return __resp. + * descr.h: Include resolv.h. + (struct pthread): Add res field. + * pthread_create.c: Include resolv.h. + (start_thread): Initialize __resp. + * Makefile (tests): Add tst-_res1. + (module-names): Add tst-_res1mod1, tst-_res1mod2. + ($(objpfx)tst-_res1mod2.so): Depend on $(objpfx)tst-_res1mod1.so. + ($(objpfx)tst-_res1): Depend on $(objpfx)tst-_res1mod2.so and + libpthread. + * tst-_res1.c: New file. + * tst-_res1mod1.c: New file. + * tst-_res1mod2.c: New file. + +2003-07-21 Ulrich Drepper + + * sysdeps/pthread/createthread.c: Don't define CLONE_STOPPED. + + * Makefile: Define various *-no-z-defs variables for test DSOs + which has undefined symbols. + +2003-07-21 Steven Munroe + + * sysdeps/unix/sysv/linux/powerpc/pthread_once.c (__pthread_once): + Retry if the stwcx fails to store once_control. + +2003-07-20 Ulrich Drepper + + * Makefile (libpthread-routines): Add pthread_attr_getaffinity and + pthread_attr_setaffinity. + * Versions [libpthread] (GLIBC_2.3.3): Likewise. + * sysdeps/unix/sysv/linux/pthread_attr_getaffinity.c: New file. + * sysdeps/unix/sysv/linux/pthread_attr_setaffinity.c: New file. + * pthread_attr_destroy.c: Free cpuset element if allocated. + * pthread_create.c: Pass iattr as additional parameter to + create_thread. + * sysdeps/pthread/createthread.c: If attribute is provided and + a new thread is created with affinity set or scheduling parameters, + start thread with CLONE_STOPPED. + * sysdeps/pthread/pthread.h: Declare pthread_attr_getaffinity and + pthread_attr_setaffinity. + * sysdeps/unix/sysv/linux/internaltypes.h (struct pthread_attr): Add + cpuset element. + +2003-07-15 Ulrich Drepper + + * tst-tcancel-wrappers.sh: lseek and llseek are not cancelation points. + +2003-07-14 Ulrich Drepper + + * sysdeps/pthread/configure.in: Require CFI directives also for + ppc and s390. + +2003-07-15 Jakub Jelinek + + * sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h (PSEUDO): + Add cfi directives. + +2003-07-12 Kaz Kojima + + * sysdeps/sh/tcb-offsets.sym: Add RESULT, TID, CANCELHANDLING and + CLEANUP_JMP_BUF. + * sysdeps/unix/sysv/linux/sh/pthread_cond_wait.S: Use more + registers as variables. Call __pthread_mutex_unlock_usercnt. + * sysdeps/unix/sysv/linux/sh/pthread_cond_timedwait.S: Likewise. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_rdlock.S: Store TID + not self pointer in __writer. Compare with TID to determine + deadlocks. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_wrlock.S: Likewise. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedrdlock.S: + Likewise. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedwrlock.S: + Likewise. + * sysdeps/unix/sysv/linux/sh/sem_wait.S: Add cancellation support. + * sysdeps/unix/sysv/linux/sh/sem_timedwait.S: Likewise. + * sysdeps/unix/sysv/linux/sh/sysdep-cancel.h: Define all the nice + macros also when compiling librt. + +2003-07-11 Jakub Jelinek + + * Makefile (CFLAGS-pthread_once.c): Add -fexceptions + -fasynchronous-unwind-tables. + * sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h + (PSEUDO): Add cfi directives. + * sysdeps/unix/sysv/linux/s390/s390-32/sysdep-cancel.h (PSEUDO): + Likewise. + * sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h (PSEUDO): + Likewise. + +2003-07-08 Jakub Jelinek + + * pthreadP.h (__pthread_unwind_next, __pthread_register_cancel, + __pthread_unregister_cancel): Add prototypes and hidden_proto. + * unwind.c (__pthread_unwind_next): Add hidden_def. + * cleanup.c (__pthread_register_cancel, __pthread_unregister_cancel): + Likewise. + * sysdeps/unix/sysv/linux/i386/i486/sem_wait.S (__new_sem_wait): + Use HIDDEN_JUMPTARGET to jump to __pthread_unwind. + * sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S (sem_timedwait): + Likewise. + * sysdeps/unix/sysv/linux/x86_64/sem_wait.S (sem_wait): Likewise. + * sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S (sem_timedwait): + Likewise. + * sysdeps/unix/sysv/linux/i386/pthread_once.S (__pthread_once): Use + HIDDEN_JUMPTARGET to call __pthread_register_cancel, + __pthread_unregister_cancel and __pthread_unwind_next. + +2003-07-04 Jakub Jelinek + + * sysdeps/unix/sysv/linux/ia64/sysdep-cancel.h (PSEUDO): Use + different symbol for the cancellation syscall wrapper and + non-cancellation syscall wrapper. + (PSEUDO_END): Define. + +2003-07-05 Richard Henderson + + * sysdeps/alpha/elf/pt-initfini.c: Avoid .ent/.end. + * sysdeps/unix/sysv/linux/alpha/lowlevellock.h (lll_futex_wait, + lll_futex_timed_wait, lll_futex_wake, lll_futex_requeue): On success + return actual return value from the syscall, not 0. + +2003-07-07 Ulrich Drepper + + * descr.h (struct pthread): Add pid field. + * allocatestack.c (allocate_stack): Initialize pid field in descriptor. + (__reclaim_stacks): Likewise. + * init.c (sigcancel_handler): If __ASSUME_CORRECT_SI_PID is defined + also check for PID of the signal source. + (__pthread_initialize_minimal_internal): Also initialize pid field + of initial thread's descriptor. + * pthread_cancel.c: Use tgkill instead of tkill if possible. + * sysdeps/unix/sysv/linux/fork.c: Likewise. + * sysdeps/unix/sysv/linux/pt-raise.c: Likewise. + * sysdeps/unix/sysv/linux/pthread_kill.c: Likewise. + * sysdeps/unix/sysv/linux/raise.c: Likewise. + +2003-07-05 Ulrich Drepper + + * sysdeps/pthread/bits/libc-lock.h (__libc_cleanup_push): Renamed. + Fix use of parameter. + (__libc_cleanup_pop): Likewise. + +2003-07-04 Ulrich Drepper + + * init.c (sigcancel_handler): Change parameters to match handler + for SA_SIGACTION. Check signal number and code to recognize + invalid invocations. + +2003-07-03 Roland McGrath + + * sysdeps/ia64/td_ta_map_lwp2thr.c (td_ta_map_lwp2thr): + Apply sizeof (struct pthread) bias to r13 value. + +2003-07-03 Ulrich Drepper + + * sysdeps/pthread/configure.in: Require CFI directives. + + * sysdeps/pthread/librt-cancellation.c (__pthread_unwind): Remove + definition. + * pthreadP.h (__pthread_unwind): Add hidden_proto if used in + libpthread compilation. + * unwind.c (__pthread_unwind): Add hidden_def. + * Versions (libpthread) [GLIBC_PRIVATE]: Add __pthread_unwind. + +2003-07-01 Ulrich Drepper + + * libc-cancellation.c (__libc_cleanup_routine): Define. + * sysdeps/pthread/bits/libc-lock.h (__pthread_cleanup_push): Define. + (__pthread_cleanup_pop): Define. + +2003-07-01 Richard Henderson + + * sysdeps/alpha/elf/pt-initfini.c: New file. + * sysdeps/alpha/pthread_spin_lock.S: New file. + * sysdeps/alpha/pthread_spin_trylock.S: New file. + * sysdeps/alpha/pthreaddef.h: New file. + * sysdeps/alpha/td_ta_map_lwp2thr.c: New file. + * sysdeps/alpha/tls.h: New file. + * sysdeps/unix/sysv/linux/alpha/Makefile: New file. + * sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h: New file. + * sysdeps/unix/sysv/linux/alpha/bits/semaphore.h: New file. + * sysdeps/unix/sysv/linux/alpha/createthread.c: New file. + * sysdeps/unix/sysv/linux/alpha/fork.c: New file. + * sysdeps/unix/sysv/linux/alpha/lowlevellock.h: New file. + * sysdeps/unix/sysv/linux/alpha/pt-vfork.S: New file. + * sysdeps/unix/sysv/linux/alpha/pthread_once.c: New file. + * sysdeps/unix/sysv/linux/alpha/sem_post.c: New file. + * sysdeps/unix/sysv/linux/alpha/sysdep-cancel.h: New file. + +2003-07-01 Ulrich Drepper + + * sysdeps/unix/sysv/linux/x86_64/pthread_once.S: Add correct + cleanup support and unwind info. + +2003-06-30 Ulrich Drepper + + * sysdeps/unix/sysv/linux/i386/pthread_once.S (__pthread_once): + Use correct cleanup handler registration. Add unwind info. + * sysdeps/unix/sysv/linux/unwindbuf.sym: New file. + * sysdeps/unix/sysv/linux/Makefile: Add rule to build unwindbuf.h. + * tst-once3.c: Add cleanup handler and check it is called. + * tst-once4.c: Likewise. + * tst-oncex3.c: New file. + * tst-oncex4.c: New file. + * Makefile: Add rules to build and run tst-oncex3 and tst-oncex4. + +2003-06-29 Ulrich Drepper + + * sysdeps/pthread/configure.in: Check for C cleanup handling in gcc. + +2003-06-27 Ulrich Drepper + + * tst-cancel4.c (tf_msgrcv): Use IPC_PRIVATE in msgget call. + (tf_msgsnd): Likewise. + + * tst-cancel4.c (tf_msgrcv): Strengthen test against valid + premature returns a bit more. + +2003-06-26 Ulrich Drepper + + * sysdeps/pthread/librt-cancellation.c: Move __pthread_unwind + definition to the front. + + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: Rename + the cleanup functions to make the names unique. Fix dwarf opcode + un unwind table. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S: Rename cleanup + functions to make the names unique. Fix CFA offset for two blocks. + +2003-06-25 Ulrich Drepper + + * sysdeps/pthread/pthread.h (class __pthread_cleanup_class): Add + missing closing braces. + Patch by Christophe Saout . + +2003-06-24 Roland McGrath + + * pthread_mutex_trylock.c (__pthread_mutex_trylock): Typo fix. + +2003-06-24 Ulrich Drepper + + * sysdeps/unix/sysv/linux/ia64/bits/posix_opt.h: New file. + * sysdeps/unix/sysv/linux/x86_64/bits/posix_opt.h: New file. + + * pthreadP.h: Declare __find_thread_by_id. + * allocatestack.c [HP_TIMING_AVAIL]: Define __find_thread_by_id. + * pthread_clock_gettime.c: Allow using other thread's clock. + * pthread_clock_settime.c: Likewise. + * sysdeps/pthread/pthread_getcpuclockid.c: Likewise. + * Makefile: Add rules to build and run tst-clock2. + * tst-clock2.c: New file. + +2003-06-23 Ulrich Drepper + + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: Rewrite + to use exception-based cleanup handler. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S: Likewise. + + * tst-cond8.c (ch): Announce that we are done. + + * pthreadP.h (__pthread_mutex_cond_lock): Mark with internal_function. + + * tst-cancel17.c (tf): Retry aio_suspend in case of EINTR. + Also test aio_suspend with timeout value. + +2003-06-22 Ulrich Drepper + + * pthreadP.h: Mark __pthread_mutex_unlock_usercnt also hidden. + * pthread_mutex_unlock.c (__pthread_mutex_unlock_usercnt): Add + attribute_hidden. + + * pthreadP.h (__pthread_mutex_init_internal): Mark hidden. + (__pthread_mutex_lock_internal): Likewise. + (__pthread_mutex_unlock_internal): Likewise. + (__pthread_mutex_unlock_usercnt): Declare. + * pthread_mutex_destroy.c: Always fail if used in any way. + * pthread_mutex_init.c: Update comment. + * pthread_mutex_lock.c: If NO_INCR is not defined adjust __nusers. + * pthread_mutex_timedlock.c: Adjust __nusers. + * pthread_mutex_trylock.c: Adjust __nusers. + * pthread_mutex_unlock.c: Old code is in __pthread_mutex_unlock_usercnt + and public interfaces are wrapper with pass additional parameter. + __pthread_mutex_unlock_usercnt does not adjust __nusers if second + parameter zero. + * tst-mutex8.c: New file. + * Makefile (tests): Add tst-mutex8. + * sysdeps/pthread/pthread_cond_timedwait.c: Call + __pthread_mutex_unlock_usercnt. + * sysdeps/pthread/pthread_cond_wait.c: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S: Likewise. + * sysdeps/unix/sysv/linux/pthread_mutex_cond_lock.c: Define NO_INCR. + * sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h (pthread_mutex_t): + Add __nusers. + * sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h: Likewise. + + * pthread_mutex_lock.c: Don't store THREAD_ID in __owner, use TID. + * pthread_mutex_timedlock.c: Likewise. + * pthread_mutex_trylock.c: Adjust __nusers. + * pthread_mutex_unlock.c: Compare with TID not THREAD_ID. + * tst-mutex9.c: New file. + * Makefile (tests): Add tst-mutex9. + * sysdeps/i386/tls.h: Remove THREAD_ID definition. + * sysdeps/ia64/tls.h: Likewise. + * sysdeps/powerpc/tls.h: Likewise. + * sysdeps/s390/tls.h: Likewise. + * sysdeps/sh/tls.h: Likewise. + * sysdeps/x86_64/tls.h: Likewise. + * sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h (pthread_mutex_t): + Change type of __owner. + * sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h: Likewise. + +2003-06-19 Jakub Jelinek + + * sysdeps/unix/sysv/linux/ia64/sem_post.c: Move to... + * sysdeps/unix/sysv/linux/sem_post.c: ...here. + + * sysdeps/unix/sysv/linux/sem_post.c: Move to... + * sysdeps/unix/sysv/linux/powerpc/sem_post.c: ... here. Pass nr + 1 + instead of nr to lll_futex_wake. Only set errno and return -1 + if err < 0. + + * sysdeps/unix/sysv/linux/powerpc/lowlevellock.h (lll_futex_wait, + lll_futex_timed_wait, lll_futex_wake, lll_futex_requeue): On success + return actual return value from the syscall, not 0. + +2003-06-18 Ulrich Drepper + + * tst-cancel4.c (tf_msgsnd): Don't always use 100 as the type, + find a random value. + (tf_msgrcv): Likewise. Also don't report msgrcv returns if + errno==EIDRM. + + * sysdeps/unix/sysv/linux/timer_settime.c: Add prototype for + compat_timer_settime. + * sysdeps/unix/sysv/linux/timer_gettime.c: Add prototype for + compat_timer_gettime. + * sysdeps/unix/sysv/linux/timer_getoverr.c: Add prototype for + compat_timer_getoverrun. + * sysdeps/unix/sysv/linux/timer_delete.c: Add prototype for + compat_timer_delete. + + * pthread_mutex_destroy.c (__pthread_mutex_destroy): For + error-checking mutex detect busy mutexes. + +2003-06-17 Ulrich Drepper + + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.h (lll_mutex_lock): + Add ax to clobber list. + (lll_mutex_cond_lock): Likewise. + (lll_mutex_unlock): Likewise. + (lll_lock): Likewise. + (lll_unlock): Likewise. + + * Makefile: Add rules to build and run tst-cancel18 and tst-cancelx18. + * tst-cancel18.c: New file. + * tst-cancelx18.c: New file. + + * tst-cancel4.c: Test connect, creat, msgrcv, msgsnd, sendmsg, sendto, + and tcdrain. + + * Makefile: Add rules to build and run tst-cancel17 and tst-cancel17x. + * tst-cancel17.c: New file. + * tst-cancelx17.c: New file. + + * sysdeps/unix/sysv/linux/sigtimedwait.c: New file. + * sysdeps/unix/sysv/linux/sigwait.c: New file. + * sysdeps/unix/sysv/linux/sigwaitinfo.c: New file. + + * tst-cancel4.c: Test open, close, pread, pwrite, fsync, and msync. + +2003-06-16 Jakub Jelinek + + * sysdeps/pthread/createthread.c (create_thread): Set + header.multiple_threads unconditionally. + * allocatestack.c (allocate_stack): Likewise. + * descr.h (struct pthread): Add header.multiple_threads + unconditionally. + * sysdeps/unix/sysv/linux/i386/sysdep-cancel.h (CENABLE, CDISABLE): + Define for librt. #error if neither libpthread, libc nor librt. + * sysdeps/unix/sysv/linux/ia64/sysdep-cancel.h (CENABLE, CDISABLE): + Likewise. + * sysdeps/unix/sysv/linux/s390/s390-32/sysdep-cancel.h (CENABLE, + CDISABLE): Likewise. + * sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h (CENABLE, + CDISABLE): Likewise. + * sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h (CENABLE, + CDISABLE): Likewise. + * sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h (CENABLE, + CDISABLE): Likewise. Access header.multiple_threads outside of + libc and libpthread. + * sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h (CENABLE, CDISABLE): + Likewise. + * sysdeps/x86_64/tls.h (tcbhead_t): Add multiple_threads. + * sysdeps/x86_64/tcb-offsets.sym (MULTIPLE_THREADS_OFFSET): Define. + +2003-06-17 Ulrich Drepper + + * tst-cancel4.c: Add tests for the socket and signal functions, pause. + Also test early cancellation before the thread reaches the cancellation + point. + + * Makefile: Compile forward.c with exceptions. + + * sysdeps/unix/sysv/linux/sleep.c: New file. + +2003-06-16 Ulrich Drepper + + * Makefile: Add CFLAGS definition to compile function wrappers + duplicated from libc with exceptions. + * tst-cancel4.c: Also check cancellation handlers. + + * Makefile: Add rules to build and run tst-cancel16 and + tst-cancelx16. Add missing CFLAGS definitions. + * tst-cancel16.c: New file. + * tst-cancelx16.c: New file. + +2003-06-15 Ulrich Drepper + + * sysdeps/unix/sysv/linux/i386/dl-sysdep.h + (DL_SYSINFO_IMPLEMENTATION): Use CFI opcodes. + * sysdeps/unix/sysv/linux/i386/i686/dl-sysdep.h + (DL_SYSINFO_IMPLEMENTATION): Likewise. + + * pthreadP.h (LIBC_CANCEL_ASYNC): Also define for librt. + (LIBC_CANCEL_RESET): Likewise. + Declare __librt_enable_asynccancel and __librt_disable_asynccancel. + * sysdeps/pthread/Makefile (librt-sysdep_routines): Add + librt-cancellation. + (CFLAGS-libcrt-cancellation.c): Define. + * sysdeps/pthread/librt-cancellation.c: New file. + * sysdeps/unix/sysv/linux/i386/sysdep-cancel.h: Define all the nice + macros also when compiling librt. + * sysdeps/unix/sysv/linux/ia64/sysdep-cancel.h: Likewise. + * sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h: Likewise. + * sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h: Likewise. + * sysdeps/unix/sysv/linux/s390/s390-32/sysdep-cancel.h: Likewise. + * sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h: Likewise. + * sysdeps/unix/sysv/linux/sh/sysdep-cancel.h: Likewise. + * sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h: Likewise. + + * sysdeps/unix/sysv/linux/timer_create.c: Add prototype for + compat_timer_create. + +2003-06-14 Ulrich Drepper + + * sysdeps/pthread/posix-timer.h (timespec_compare): Always inline. + + * sysdeps/unix/sysv/linux/fork.h: Add libc_hidden_proto for + __register_atfork. + * sysdeps/unix/sysv/linux/register-atfork.c (__register_atfork): + Add libc_hidden_def. + +2003-06-13 Roland McGrath + + * sysdeps/x86_64/td_ta_map_lwp2thr.c (td_ta_map_lwp2thr): Pass FS + constant from to ps_get_thread_area, not register contents. + +2003-06-11 Ulrich Drepper + + * allocatestack.c (queue_stack): Always inline. + * ptreadhP.h (__do_cancel): Likewise. + +2003-06-10 Jakub Jelinek + + * sysdeps/unix/sysv/linux/s390/sem_timedwait.c (sem_timedwait): Fix + a typo. + +2003-06-10 Ulrich Drepper + + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_signal.S + (__pthread_cond_signal): Remove incorrect second addition for + cond_lock!=0. + +2003-06-09 Ulrich Drepper + + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_signal.S + (__pthread_cond_signal): Use correct futex pointer in + __lll_mutex_lock_wait call. + + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_signal.S + (__pthread_cond_signal): Some more tweaks to handle cond_lock!=0. + +2003-06-08 Ulrich Drepper + + * sysdeps/unix/sysv/linux/s390/sem_wait.c (__new_sem_wait): Make + cancelable. + * sysdeps/unix/sysv/linux/s390/sem_timedwait.c (sem_timedwait): + Likewise. + + * sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h: Remove + hand-written CFI generation code. Since ENTRY/END also initiated + CFI frames this caused two CFI sets to be generated. + +2003-06-07 Ulrich Drepper + + * cleanup_routine.c: New file. + * Versions (libpthread) [GLIBC_2.3.3]: Add __pthread_cleanup_routine. + * sysdeps/pthread/pthread.h: Add support for fully exception-based + cleanup handling. + * Makefile (libpthread-routines): Add cleanup_routine. + Add more CFLAGS variables to compile with exceptions. Add comments + why which file needs unwind tables. + (tests) [have-forced-unwind==yes]: Add tst-cancelx* and tst-cleanupx* + tests. + * tst-cancelx1.c: New file. + * tst-cancelx2.c: New file. + * tst-cancelx3.c: New file. + * tst-cancelx4.c: New file. + * tst-cancelx5.c: New file. + * tst-cancelx6.c: New file. + * tst-cancelx7.c: New file. + * tst-cancelx8.c: New file. + * tst-cancelx9.c: New file. + * tst-cancelx10.c: New file. + * tst-cancelx11.c: New file. + * tst-cancelx12.c: New file. + * tst-cancelx13.c: New file. + * tst-cancelx14.c: New file. + * tst-cancelx15.c: New file. + * tst-cleanupx0.c: New file. + * tst-cleanupx0.expect: New file. + * tst-cleanupx1.c: New file. + * tst-cleanupx2.c: New file. + * tst-cleanupx3.c: New file. + + * tst-cleanup0.c: Make standard compliant. + * tst-cleanup1.c: Likewise. + + * sysdeps/unix/sysv/linux/sem_timedwait.c: Add cancellation support. + * sysdeps/unix/sysv/linux/sem_wait.c: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/sem_wait.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/sem_wait.S: Likewise. + * sysdeps/i386/tcb-offsets.sym: Add RESULT, CANCELHANDLING, and + CLEANUP_JMP_BUF. + * sysdeps/x86_64/tcb-offsets.sym: Likewise. + * tst-cancel12.c: New file. + * tst-cancel13.c: New file. + * tst-cancel14.c: New file. + * tst-cancel15.c: New file. + * Makefile (tests): Add tst-cancel12, tst-cancel13, tst-cancel14, + and tst-cancel15. + + * tst-cancel1.c: Add some comments. + + * sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S: Compute relative + timeout correctly. + +2003-06-06 Ulrich Drepper + + * Makefile (CFLAGS-pthread_cancel.c): Define. + +2003-06-05 Ulrich Drepper + + * sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h (pthread_rwlock_t): + Change type of __writer element to int. + * sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h: Likewise. + * sysdeps/i386/tcb-offsets.sym: Replace SELF entry with TID entry. + * sysdeps/x86_64/tcb-offsets.sym: Likewise. + * pthread_rwlock_trywrlock.c: Store TID not self pointer in __writer. + Compare with TID to determine deadlocks. + * sysdeps/pthread/pthread_rwlock_rdlock.c: Likewise. + * sysdeps/pthread/pthread_rwlock_timedrdlock.c: Likewise. + * sysdeps/pthread/pthread_rwlock_timedwrlock.: Likewise. + * sysdeps/pthread/pthread_rwlock_wrlock.c: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_rdlock.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedrdlock.S: + Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedwrlock.S: + Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_wrlock.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_rdlock.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedrdlock.S: + Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedwrlock.S: + Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_wrlock.S: Likewise. + * Makefile (tests): Add tst-rwlock12. + * tst-rwlock12.c: New file. + +2003-06-05 Jakub Jelinek + + * sysdeps/unix/sysv/linux/lowlevellock.c (__lll_lock_wait, + __lll_timedlock_wait, lll_unlock_wake_cb, __lll_timedwait_tid): + Remove bogus hidden_proto. + * sysdeps/unix/sysv/linux/s390/libc-lowlevellock.c (___lll_lock): + Likewise. + * sysdeps/unix/sysv/linux/s390/lowlevellock.c (___lll_lock, + lll_unlock_wake_cb, ___lll_timedwait_tid): Likewise. + * sysdeps/unix/sysv/linux/s390/lowlevelmutex.c (___lll_mutex_lock, + ___lll_mutex_timedlock): Likewise. + +2003-06-04 Ulrich Drepper + + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_signal.S + (__pthread_cond_signal): Add some code to eventually handle + cond_lock!=0. + +2003-06-01 Ulrich Drepper + + * Makefile (tests): Add tst-exec4. + (tst-exec4-ARGS): Define. + * tst-exec4.c: New file. + +2003-05-31 Ulrich Drepper + + * sysdeps/unix/sysv/linux/lowlevellock.c (__lll_timedlock_wait): + Also fail if tv_nsec < 0. + (__lll_timedwait_tid): Likewise. + * sysdeps/unix/sysv/linux/sem_timedwait.c (sem_timedwait): Likewise. + * sysdeps/unix/sysv/linux/i386/lowlevellock.h (lll_timedwait_tid): + Likewise. + * sysdeps/unix/sysv/linux/s390/lowlevellock.c (___lll_timedwait_tid): + Likewise. + * sysdeps/unix/sysv/linux/s390/lowlevelmutex.c (__lll_mutex_timedlock): + Likewise. + * sysdeps/unix/sysv/linux/s390/sem_timedwait.c (sem_timedwait): + Likewise. + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.h (lll_timedwait_tid): + Likewise. + * sysdeps/unix/sysv/linux/sh/lowlevellock.h (lll_timedwait_tid): + Likewise. + + * Makefile (tests): Add tst-sem8 and tst-sem9. + * tst-sem8.c: New file. + * tst-sem9.c: New file. + * sem_open.c: Fix creation of in_use record if the file exists but + no internal record. + + * posix-timer.h: Remove old, unused timer_id2ptr and timer_ptr2id + definitions. + + * sysdeps/pthread/timer_create.c (timer_create): In case + evp==NULL, assign timer ID to sival_ptr. + + * descr.h (struct pthread_unwind_buf): Change type of prev element to + struct pthread_unwind_buf *. + (struct pthread): Likewise for cleanup_jmp_buf element. + + * cleanup.c (__pthread_register_cancel): Add cast to avoid warning. + * cleanup_defer.c (__pthread_register_cancel_defer): Likewise. + * unwind.c (__pthread_unwind_next): Likewise. + +2003-05-30 Ulrich Drepper + + * sysdeps/unix/sysv/linux/ia64/lowlevellock.h + (lll_futex_timed_wait): Use int for futex value parameter. + (lll_futex_wake): Likewise. + (lll_futex_requeue): Likewise. + + * sysdeps/unix/sysv/linux/lowlevellock.c (__lll_lock_wait): + Replace one memory operation with one register operation. + + * tst-join4.c (do_test): Fix error message. + + * tst-rwlock6.c (do_test): Use correct format specifier. + + * sysdeps/unix/sysv/linux/i386/i486/lowlevelmutex.S + (__lll_mutex_lock_wait): Replace one memory operation with one + register operation. + * sysdeps/unix/sysv/linux/x86_64/lowlevelmutex.S + (__lll_mutex_lock_wait): Likewise. + + * sysdeps/unix/sysv/linux/ia64/lowlevellock.h + (__lll_mutex_cond_lock): Add one to value parameter of + __lll_lock_wait to reflect reality in the futex syscall. + * sysdeps/unix/sysv/linux/powerpc/lowlevellock.h + (lll_mutex_cond_lock): Likewise. + +2003-05-30 Jakub Jelinek + + * sysdeps/unix/sysv/linux/s390/lowlevellock.h (__lll_mutex_cond_lock): + New function. + (lll_mutex_cond_lock): Define. + +2003-05-29 Ulrich Drepper + + * Makefile (tests): Add tst-signal6. + * tst-signal6.c: New file. + + * sysdeps/unix/sysv/linux/s390/lowlevellock.h + (__lll_mutex_unlock_force): New function + (lll_mutex_unlock_force): Use __lll_mutex_unlock_force. + + * sysdeps/unix/sysv/linux/ia64/lowlevellock.h + (__lll_mutex_unlock_force): New function. + (lll_mutex_unlock_force): Use __lll_mutex_unlock_force. + + * tst-rwlock7.c (do_test): Use correct format specifier. + + * sysdeps/unix/sysv/linux/ia64/lowlevellock.h (lll_futex_requeue): + Find break parameter in correct asm argument. + +2003-05-27 Jakub Jelinek + + * sysdeps/unix/sysv/linux/ia64/lowlevellock.h (lll_futex_clobbers): + Remove out4. + (lll_futex_requeue): Fix __o3 constraint, return negative errno if + error occured. + * sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h (pthread_cond_t): + Add __mutex. + * sysdeps/unix/sysv/linux/s390/lowlevellock.h (FUTEX_REQUEUE, + lll_futex_requeue, lll_mutex_unlock_force): Define. + +2003-05-30 Jakub Jelinek + + * sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h + (pthread_cond_t): Add __mutex. + * sysdeps/unix/sysv/linux/powerpc/lowlevellock.h (FUTEX_REQUEUE, + lll_futex_requeue, lll_mutex_unlock_force): Define. + +2003-05-28 Kaz Kojima + + * sysdeps/sh/tcb-offsets.sym: Define MUTEX_FUTEX. + * sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h (pthread_cond_t): + Add __mutex field. + * sysdeps/unix/sysv/linux/sh/lowlevellock.h (SYSCALL_WITH_INST_PAD): + Define. + (lll_futex_wait, lll_futex_wake): Define. + * sysdeps/unix/sysv/linux/sh/sh4/lowlevellock.h: New file. + * sysdeps/unix/sysv/linux/sh/pthread_cond_broadcast.S: Try using + FUTEX_REQUEUE instead of FUTEX_WAIT. + * sysdeps/unix/sysv/linux/sh/pthread_cond_signal.S: Likewise. + * sysdeps/unix/sysv/linux/sh/pthread_cond_timedwait.S: Remember + mutex which was used in condvar structure. Call + __pthread_mutex_cond_lock instead of __pthread_mutex_lock_internal. + * sysdeps/unix/sysv/linux/sh/pthread_cond_wait.S: Likewise. + + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_rdlock.S: Don't + include tcb-offsets.h. Read wakeup value in locked region. + Use the value of gbr register as THREAD_ID. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_wrlock.S: Likewise. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedrdlock.S: Likewise. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedwrlock.S: Likewise. + + * sysdeps/unix/sysv/linux/sh/sem_trywait.S: Remove futex related + macros. + +2003-05-28 Ulrich Drepper + + * sysdeps/pthread/pthread_cond_broadcast.c + (__pthread_cond_broadcast): Fix typo: MAX_INT -> INT_MAX. + +2003-05-26 Ulrich Drepper + + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S: Fix + typo in register name. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.S: Use parameters + correctly. Actually use requeue. Little optimization. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S: Store + mutex address early. Handle cancellation state as 32-bit value. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S: Likewise. + Remove unnecessary label. + +2003-05-25 Ulrich Drepper + + * sysdeps/pthread/pthread_cond_broadcast.c: Try using FUTEX_REQUEUE + instead of FUTEX_WAIT. + * sysdeps/pthread/pthread_cond_signal.c: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_signal.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.S: Likewise. + * sysdeps/pthread/pthread_cond_timedwait.c: Remember mutex which was + used in condvar structure. Call __pthread_mutex_cond_lock instead + of __pthread_mutex_lock_internal. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S: Likewise. + * sysdeps/pthread/pthread_cond_wait.c: Likewise. + (__condvar_cleanup): Always call __pthread_mutex_cond_lock. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S: Likewise. + * sysdeps/unix/sysv/linux/Makefile (libpthread-sysdep_routines): + Add pthread_mutex_cond_lock. + * sysdeps/unix/sysv/linux/lowlevelcond.sym: Add dep_mutex. + * sysdeps/unix/sysv/linux/pthread_cond_mutex_lock.c: New file. + * sysdeps/unix/sysv/linux/i386/lowlevellock.h: Define + lll_mutex_cond_lock. + * sysdeps/unix/sysv/linux/ia64/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h (pthread_cond_t): + Add __mutex field. + * sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h: Likewise. + + * sysdeps/i386/tcb-offsets.sym: Define MUTEX_FUTEX. + * sysdeps/x86_64/tcb-offsets.sym: Likewise. + + * pthreadP.h: Declare __pthread_mutex_cond_lock. + * pthread_mutex_lock.c: Define LLL_MUTEX_LOCK if not already defined. + Use it instead of lll_mutex_lock. If __pthread_mutex_lock is a + macro don't define aliases. + + * cancellation.c: Remove __pthread_enable_asynccancel_2. + * pthreadP.h: Remove declaration of __pthread_enable_asynccancel_2. + * sysdeps/pthread/pthread_cond_timedwait.c: Use + __pthread_enable_asynccancel instead of __pthread_enable_asynccancel_2. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S: Likewise. + * sysdeps/pthread/pthread_cond_wait.c: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S: Likewise. + +2003-05-17 Ulrich Drepper + + * sem_open.c: Fix one endless loop. Implement correct semantics + wrt opening the same semaphore more then once. + * sem_close.c: Adjust for sem_open change. + * semaphoreP.h: Include . Define struct inuse_sem. + Declare __sem_mappings, __sem_mappings_lock, __sem_search. + * Makefile (tests): Add tst-sem7. + * tst-sem7.c: New file. + +2003-05-16 Roland McGrath + + * sysdeps/unix/sysv/linux/register-atfork.c (libc_freeres_fn): Fix + uninitialized variable braino. + +2003-05-16 Ulrich Drepper + + * sysdeps/unix/sysv/linux/timer_gettime.c (timer_gettime): Correct + test for syscall availability. + + * sysdeps/unix/sysv/linux/timer_settime.c (timer_settime): Set + __no_posix_timers to -1 if the syscalls don't exist. + + * pthread_join.c (pthread_join): Set tid field of the joined + thread to -1. This isn't necessary but helps to recognize some + error conditions with almost no cost. + + * allocatestack.c (FREE_P): Also negative values indicate an + unused stack. + + * unwind.c: Include . + +2003-05-14 Ulrich Drepper + + * Makefile ($(objpfx)$(multidir)): Add rule to create the directory. + +2003-05-14 Jakub Jelinek + + * Makefile (crti-objs, crtn-objs): New variables. + (omit-deps, extra-objs): Add crtn. + ($(objpfx)libpthread.so): Depend on both crti and crtn + and links to them in multidir. + ($(objpfx)crtn.S, $(objpfx)crtn.o): New rules. + +2003-05-12 Steven Munroe + + * sysdeps/unix/sysv/linux/powerpc/lowlevellock.h + (lll_mutex_unlock): Use atomic_exchange_rel. + +2003-05-11 Ulrich Drepper + + * cond-perf.c (cons): Add missing locking around setting of alldone. + +2003-05-10 Ulrich Drepper + + * sysdeps/unix/sysv/linux/i386/i486/sem_trywait.S: Remove futex + related macros. + * sysdeps/unix/sysv/linux/x86_64/sem_trywait.S: Likewise. + +2003-05-09 Ulrich Drepper + + * tst-sem6.c: New file. + * Makefile (tests): Add tst-sem6. + + * sysdeps/unix/sysv/linux/ia64/lowlevellock.h (___lll_mutex_unlock): + Use atomic_exchange_rel instead of atomic_exchange. + * sysdeps/unix/sysv/linux/lowlevellock.c (lll_unlock_wake_cb): + Likewise. + + * sysdeps/unix/sysv/linux/i386/lowlevellock.h: Improve quality of + code for lll_futex_wait and lll_futex_wake in static apps. Use + vsyscall is possible. + + * sysdeps/unix/sysv/linux/pthread_getaffinity.c: New file. + * sysdeps/unix/sysv/linux/pthread_setaffinity.c: New file. + * sysdeps/pthread/pthread.h: Declare pthread_getaffinity_np and + pthread_setaffinity_np. + * Versions [libpthread] (GLIBC_2.3.3): Add pthread_getaffinity_np + and pthread_setaffinity_np. + * Makefile (libpthread-routines): Add pthread_getaffinity and + pthread_setaffinity. + + * allocatestack.c (allocate_stack): If ARCH_RETRY_MMAP is defined, + use it in case mmap to allocate the stack fails. + * sysdeps/unix/sysv/linux/x86_64/Makefile: Don't define + ARCH_MAP_FLAGS here. + * sysdeps/x86_64/pthreaddef.h: Define ARCH_MAP_FLAGS and + ARCH_RETRY_MMAP. + +2003-05-08 Ulrich Drepper + + * sysdeps/unix/sysv/linux/fork.c: Complete rewrite of the atfork + handler implementation. It is now lockless in fork(). + * sysdeps/unix/sysv/linux/register-atfork.c: Likewise. + * sysdeps/unix/sysv/linux/unregister-atfork.c: Likewise. + * sysdeps/unix/sysv/linux/fork.h: Don't include . Don't + declare the __fork_*_lists. + (struct fork_handler): Include pointers to all three functions. + Add next, refcntr and need_signal elements. + (__fork_handlers): New declaration. + (__register_atfork_malloc): Remove declaration. + (HAVE_register_atfork_malloc): Remove definition. + * sysdeps/unix/sysv/linux/libc_pthread_init.c: Remove + __pthread_child_handler variable. + (__libc_pthread_init): Use __register_atfork instead of explicitly + adding to the list. + * sysdeps/unix/sysv/linux/i386/lowlevellock.h: Define lll_futex_wait + and lll_futex_wake. + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.h: Likewise. + + * unwind.c (unwind_cleanup): Print error message and then abort. This + function must never be reached. + + * cond-perf.c: New file. + +2003-05-05 Ulrich Drepper + + * sysdeps/i386/tls.h (TLS_INIT_TP): Include \n in error message. + +2003-05-04 Roland McGrath + + * Makefile ($(objpfx)../libc.so): New target. + +2003-05-02 Ulrich Drepper + + * sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h + (pthread_condattr_t): Size is only an int, don't use long for + alignment. + (pthread_mutexattr_t): Likewise. + * sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h: Likewise. + +2003-05-01 Ulrich Drepper + + * sysdeps/i386/tls.h: Define THREAD_ID. + * sysdeps/ia64/tls.h: Likewise. + * sysdeps/powerpc/tls.h: Likewise. + * sysdeps/s390/tls.h: Likewise. + * sysdeps/sh/tls.h: Likewise. + * sysdeps/x86_64/tls.h: Likewise. + * pthread_mutex_lock.c: Use THREAD_ID instead of THREAD_SELF to + record ownership. + * pthread_mutex_timedlock.c: Likewise. + * pthread_mutex_trylock.c: Likewise. + * pthread_mutex_unlock.c: Likewise. + * pthread_rwlock_trywrlock.c: Likewise. + * sysdeps/pthread/pthread_rwlocklock_rdlock.c: Likewise. + * sysdeps/pthread/pthread_rwlock_timedrdlock.c: Likewise. + * sysdeps/pthread/pthread_rwlock_timedwrlock.c: Likewise. + * sysdeps/pthread/pthread_rwlock_wrlock.c: Likewise. + + * sysdeps/pthread/createthread.c (create_thread): Use CLONE_SYSVSEM + flag. + +2003-04-29 Jakub Jelinek + + * sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h + (__SIZEOF_PTHREAD_COND_T): Define to 48. + (pthread_rwlock_t): Add 16 bytes of pad instead of 8 before __flags. + * sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h (pthread_cond_t): + Make __align long long instead of long. + (pthread_rwlock_t): Formatting. + * sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h + (pthread_rwlock_t): Formatting. + * sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h + (pthread_cond_t): Make __align long long instead of long. + (pthread_rwlock_t): Move __flags field to the same position as in + linuxthreads. + +2003-04-30 Ulrich Drepper + + * tst-rwlock6.c (do_test): Use correct printf format specifiers. + * tst-rwlock7.c (do_test): Likewise. + +2003-04-26 Roland McGrath + + * Makefile ($(test-modules)): Depend on $(common-objpfx)shlib.lds. + +2003-04-22 Jakub Jelinek + + * allocatestack.c (TLS_TPADJ): Add TLS_PRE_TCB_SIZE instead of + sizeof (struct pthread). + (allocate_stack): Subtract TLS_PRE_TCB_SIZE bytes instead of + 1 struct pthread. + * sysdeps/powerpc/tls.h (TLS_INIT_TCB_SIZE, TLS_TCB_SIZE): Define + to 0. + (TLS_INIT_TCB_ALIGN, TLS_TCB_ALIGN): Define to alignment of + struct pthread. + (TLS_PRE_TCB_SIZE): Increase to cover tcbhead_t preceeded by pad + to 32-bit bytes. + (INSTALL_DTV, GET_DTV, THREAD_DTV): tcbhead_t is immediately before + tcbp. + (TLS_INIT_TP, THREAD_SELF, INIT_THREAD_SELF): Don't add TLS_TCB_SIZE + unneccessarily. + (NO_TLS_OFFSET): Define. + * sysdeps/unix/sysv/linux/powerpc/createthread.c (TLS_VALUE): Don't + add TLS_TCB_SIZE unnecessarily. + +2003-04-22 Roland McGrath + + * Makeconfig (shared-thread-library): Reverse link order to work + around linker bug. + +2003-04-22 Ulrich Drepper + + * semaphore.h: Fix typo in comment. + +2003-04-21 Ulrich Drepper + + * sysdeps/pthread/sigfillset.c: New file. + + * init.c (__pthread_initialize_minimal): Don't block SIGTIMER. + * pthreadP.h: Make SIGTIMER and SIGCANCEL the same. + * sysdeps/pthread/pthread_sigmask.c: Remove handling of SIGTIMER. + * sysdeps/pthread/sigaction.c: Likewise. + * sysdeps/pthread/sigprocmask.c: New file. + * sysdeps/unix/sysv/linux/allocrtsig.c (current_rtmin): Define as + __SIGRTMIN+1. + * sysdeps/unix/sysv/linux/timer_routines.c (timer_helper_thread): + Block SIGTIMER. Also handle SI_TKILL events and terminate thread + in this case. + +2003-04-19 Ulrich Drepper + + * sysdeps/unix/sysv/linux/i386/dl-sysdep.h + (DL_SYSINFO_IMPLEMENTATION): Add .eh_frame information. + + * sysdeps/unix/sysv/linux/unregister-atfork.c + (__unregister_atfork): Don't free memory not allocated dynamically. + + * semaphore.h: Remove __THROW marker from cancellation points. + * nptl/sysdeps/pthread/pthread.h: Likewise. + +2003-04-18 Ulrich Drepper + + * sysdeps/pthread/pthread.h: Don't mark pthread_testcancel, + pthread_cancel, pthread_setcancelstate, and pthread_setcanceltype with + __THROW. + +2003-04-16 Jakub Jelinek + + * tst-cancel4.c (do_test): Use %zd instead of %d when printing cnt. + +2003-04-15 Roland McGrath + + * forward.c (__pthread_unwind): Tweak to avoid warning. + +2003-04-15 Ulrich Drepper + + * pthreadP.h: Move THREAD_ATOMIC_* replacements to the top. + +2003-04-14 Ulrich Drepper + + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S: Don't + overflow CFA advance instructions. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S: Likewise. + +2003-04-14 Jakub Jelinek + + * sysdeps/i386/tls.h: Rename LOCK to LOCK_PREFIX. + * sysdeps/i386/pthread_spin_lock.c: Likewise. + * sysdeps/x86_64/tls.h: Likewise. Define LOCK_PREFIX if not already + defined. + + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: Use + DW_CFA_advance_loc2 for .Laddl-.Lsubl. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S: Use + DW_CFA_advance_loc for .Laddl-.Lsubl. + +2003-04-13 Ulrich Drepper + + * sysdeps/unix/sysv/linux/i386/sysdep-cancel.h: Don't use + position-independent unwind data for static libraries. + Add missing unwind info. Add comments. + + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S: Add unwind info. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: Likewise. + +2003-04-12 Ulrich Drepper + + * Makefile: Make sure all cancellation points are compiled with + exception and asynchronous unwind tables. + + * sysdeps/x86_64/tls.h (THREAD_SETMEM): Word around compiler bug + which mishandles loading of global object addresses in PIC. + (THREAD_SETMEM_NC): Likewise. + +2003-04-11 Ulrich Drepper + + * pthread.h: Define new data structure for cleanup buffer. Declare + new cleanup handler interfaces. + * descr.h: Include if necessary. Define pthread_unwind_buf. + (struct pthread): Add cleanup_jmp_buf pointer. Define + HAVE_CLEANUP_JMP_BUF and not HAVE_CANCELBUF. + * pthreadP.h: Declare __pthread_unwind. Define __do_cancel to use + it. Declare old cleanup handler installation functions. + * cleanup.c: Rewrite. Install handler for unwind-based cleanup + handling. + * cleanup_defer.c: Likewise. + * cleanup_compat.c: New file. Old cleanup code. + * cleanup_def_compat.c: New file. Old cleanup code. + * pthread_create.c (start_thread): Initialize cleanup_jmp_buf element + if own thread descriptor. + * unwind.c: New file. + * forward.c: Add __pthread_unwind. + * init.c (pthread_functions): Add __pthread_unwind. + * sysdeps/pthread/pthread-functions.s (struct pthread_functions): + Add ptr___pthread_unwind. + * Versions [GLIBC_2.3.3] (libpthread): Export new cleanup handling + and unwind function. + * Makefile (libpthread-routines): Add cleanup_compat, + cleanup_def_compat, and unwind. Define CFLAGS to enable unwind + table generation if necessary. + * version.c: Record whether unwind support is compiled in. + * sysdeps/pthread/configure.in: Add checks for unwind unterfaces. + * sysdeps/pthread/bits/libc-lock.h: Add prototypes of the old cleanup + handler interfaces. + * sysdeps/unix/sysv/linux/i386/sysdep-cancel.h: Add quite a bit of + complication to generate unwind information for syscall wrappers. + * sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h: Likewise. + * sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h: Define + __cleanup_fct_attribute. + + * Makefile: Add rules to build and run tst-cleanup0. + * tst-cleanup0.c: New file. + * tst-cleanup0.expect: New file. + + * pthread_create.c (deallocate_tsd): Don't take parameter. Adjust + caller. Optimize to avoid often unecessary local variable. + +2003-04-11 Roland McGrath + + * Makefile ($(objpfx)multidir.mk): New target, generated makefile that + sets variable `multidir'; include that. + (generated): Add it. + ($(objpfx)$(multidir)/crti.o): New target. + [$(multidir) != .] (generated-dirs, extra-objs, omit-deps): Add it. + +2003-04-11 Ulrich Drepper + + * tst-attr2.c (do_test): Add cast to avoid warning. + * tst-mutex4.c (do_test): Likewise. + +2003-04-10 Ulrich Drepper + + * sysdeps/unix/sysv/linux/fork.c (__libc_fork): Reset CPU clocks + in child. + +2003-04-09 Ulrich Drepper + + * Makefile (tests): Add tst-detach1. + * tst-detach1.c: New file. + +2003-04-08 Ulrich Drepper + + * sysdeps/pthread/pthread.h: Remove duplicate + pthread_cleanup_{push,pop} definitions. + + * tst-barrier2.c: Eliminate warnings. + * tst-cancel4.c: Likewise. + * tst-cond4.c: Likewise. + * tst-cond6.c: Likewise. + * tst-detach1.c: Likewise. + * tst-rwlock4.c: Likewise. + * tst-rwlock6.c: Likewise. + * tst-rwlock7.c: Likewise. + * tst-sem3.c: Likewise. + * tst-spin2.c: Likewise. + * tst-umask1.c: Likewise. + +2003-04-07 Ulrich Drepper + + * pthread_detach.c (pthread_detach): Fix test for invalid TID. + +2003-04-06 Ulrich Drepper + + * descr.h (struct pthread): Move cancelhandling member to the front. + +2003-04-05 Ulrich Drepper + + * sysdeps/unix/sysv/linux/register-atfork.c: Define malloc_prepare, + malloc_parent, and malloc_child statically. + (__register_atfork_malloc): New function. + (free_mem): Don't free any of the malloc_* variables on the list. + * sysdeps/unix/sysv/linux/fork.h: Declare __register_atfork_malloc. + Define HAVE_register_atfork_malloc. + +2003-04-04 Ulrich Drepper + + * sysdeps/pthread/createthread.c (create_thread): Add some more + comments explaining when to set multiple_threads and when not. + + * pthreadP.h: Define THREAD_ATOMIC_CMPXCHG_VAL and + THREAD_ATOMIC_BIT_SET if not already defined. + * sysdeps/i386/tls.h: Define THREAD_ATOMIC_CMPXCHG_VAL and + THREAD_ATOMIC_BIT_SET: + * sysdeps/x86_64/tls.h: Likewise. + * cleanup_defer.c (_pthread_cleanup_push_defer): Rewrite to use + THREAD_ATOMIC_CMPXCHG_VAL. + (_pthread_cleanup_pop_restore): Likewise. + * cancellation.c (__pthread_enable_asynccancel): Likewise. + (__pthread_enable_asynccancel_2): Likewise. + (__pthread_disable_asynccancel): Likewise. + * libc-cancellation.c (__libc_enable_asynccancel): Likewise. + (__libc_disable_asynccancel): Likewise. + * init.c (sigcancel_handler): Likewise. + * pthread_setcancelstate.c (__pthread_setcancelstate): Likewise. + * pthread_setcanceltype.c (__pthread_setcanceltype): Likewise. + +2003-04-03 Ulrich Drepper + + * init.c (sigcancel_handler): Don't set EXITING_BIT here. + * libc-cancellation.c (__libc_enable_asynccancel): Likewise. + * pthreadP.h (__do_cancel): Set EXITING_BIT here. + * Makefile (tests): Add tst-cancel11. + * tst-cancel11.c: New file. + +2003-04-01 Ulrich Drepper + + * pthread_create.c (deallocate_tsd): Clear/free memory after the last + round, not the first. Use specific_used flag instead of local + found_nonzero variable. Use THREAD_[SG]ETMEM where possible. + (__free_tcb): Don't call deallocate_tsd here. + (start_thread): Call deallocate_tsd here. + * pthread_setspecific.c: Set specific_used flag really only when + needed. + * Makefile (tests): Add tst-tsd3.c and tst-tsd4. + * tst-tsd3.c: New file. + * tst-tsd4.c: New file. + +2003-03-31 Ulrich Drepper + + * sysdeps/unix/sysv/linux/ia64/lowlevellock.h (__lll_mutex_lock): + Use atomic_exchange_and_add instead of __lll_add. + (__lll_mutex_timedlock): Likewise. + Patch by Ian Wienand. + +2003-03-24 Steven Munroe + + * sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h + (SINGLE_THREAD_P): Fix typo. + * tst-cancel-wrappers.sh: Handle '.'ed symbols. + +2003-03-31 Ulrich Drepper + + * Makefile (tests): Add tst-align. + * tst-align.c: New file. + * sysdeps/i386/Makefile: Define CFLAGS-tst-align. + + * sysdeps/i386/tls.h (CALL_THREAD_FCT): Align stack of called + function correctly. + + * tst-tsd2.c: Add casts to avoid warnings. + +2003-03-30 Ulrich Drepper + + * descr.h (struct pthread): Move most often used elements to the front. + +2003-03-29 Ulrich Drepper + + * Makefile (libpthread-routines): Add pthread_atfork. + (libpthread-static-only-routines): Add pthread_atfork. + +2003-03-28 Kaz Kojima + + * sysdeps/sh/tls.h: Include nptl/descr.h after the definition + of TLS_DTV_AT_TP. + (INSTALL_DTV): Add parens. + (THREAD_GETMEM, THREAD_GETMEM_NC, THREAD_SETMEM, THREAD_SETMEM_NC): + Use passed descr instead of THREAD_SELF. + * sysdeps/unix/sysv/linux/sh/lowlevelmutex.S + (__lll_mutex_timedlock_wait): Correct expected value after + spurious wakeup. + * sysdeps/unix/sysv/linux/sh/pthread_cond_broadcast.S: + Release lock before waking up the waiters. + * sysdeps/unix/sysv/linux/sh/pthread_cond_wait.S: Correct exit + criteria. Reorderstruct passed to cleanup handler. Fix + handling of cancellation and failung pthread_mutex_unlock call. + Use __pthread_enable_asynccancel_2 instead of + __pthread_enable_asynccancel. + * sysdeps/unix/sysv/linux/sh/pthread_cond_timedwait.S: Likewise. + Return result of lock re-get if it fails. + * sysdeps/unix/sysv/linux/sh/pthread_once.S: Fix wrong argument + for __pthread_cleanup_push. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_rdlock.S: Fix + completely broken rwlock implementation. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_wrlock.S: Likewise. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedrdlock.S: Likewise. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedwrlock.S: Likewise. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_unlock.S: Likewise. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_wrlock.S: Likewise. + * sysdeps/unix/sysv/linux/sh/sem_post.S: Fix error value. Use + versioned_symbol macro. + * sysdeps/unix/sysv/linux/sh/sem_trywait.S: Use versioned_symbol macro. + * sysdeps/unix/sysv/linux/sh/sem_wait.S: Likewise. + +2003-03-27 Ulrich Drepper + + * sysdeps/unix/sysv/linux/kernel-posix-timers.h: Don't declare + __timer_helper_thread. Declare __start_helper_thread, __helper_once, + and __helper_tid. + (struct timer): Remove th and bar field. + * sysdeps/unix/sysv/linux/timer_create.c (timer_create): Remove + debugging code. Create only one helper thread. + * sysdeps/unix/sysv/linux/timer_delete.c (timer_delete): Don't kill + helper thread. + * sysdeps/unix/sysv/linux/timer_routines.c (timer_helper_thread): + Renamed. Define statically. Use thread info from siginfo. + (__helper_once): New variable. + (__helper_tid): New variable. + (__reset_helper_control): New function. + (__start_helper_thread): New function. + + * pthread_create.c (start_thread): Don't use setjmp inside + __builtin_expect to work around gcc bug. + + * sysdeps/unix/sysv/linux/timer_delete.c (timer_delete): Even if + timer_delete syscall fails, but not with ENOSYS, set + __no_posix_timers. + + * sysdeps/unix/sysv/linux/timer_settime.c [!__ASSUME_POSIX_TIMERS] + (timer_settime): Fix typo. + * sysdeps/unix/sysv/linux/timer_getoverr.c + [!__ASSUME_POSIX_TIMERS] (timer_getoverrun): Likewise. + +2003-03-27 Jakub Jelinek + + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: Fix + offset of cleanupbuf.__prev. + +2003-03-26 Jakub Jelinek + + * sysdeps/unix/sysv/linux/timer_getoverr.c: Fix typo in name + of included file. + +2003-03-26 Ulrich Drepper + + * sysdeps/unix/sysv/linux/timer_create.c (timer_create): If EVP == + NULL provide default definition to syscall. + +2003-03-25 Roland McGrath + + * sysdeps/pthread/posix-timer.h (TIMER_MAX): Define if not defined. + (timer_id2ptr): Fix typo. + +2003-03-25 Ulrich Drepper + + * pthreadP.h: Define SIGCANCEL and SIGTIMER. + * sysdeps/i386/pthreaddef.h: Remove SIGCANCEL definition. + * sysdeps/ia64/pthreaddef.h: Likewise. + * sysdeps/powerpc/pthreaddef.h: Likewise. + * sysdeps/s390/pthreaddef.h: Likewise. + * sysdeps/sh/pthreaddef.h: Likewise. + * sysdeps/x86_64/pthreaddef.h: Likewise. + * init.c (__pthread_initialize_minimal): Block SIGTIMER. + * sysdeps/pthread/sigaction.c: Also prevent SIGTIMER handler from + being changed. + * sysdeps/pthread/pthread_sigmask.c (pthread_sigmask): Make sure + SIGTIMER is not unblocked. + * sysdeps/unix/sysv/linux/allocrtsig.c (current_rtmin): One more + RT signal taken. + * sysdeps/unix/sysv/linux/pthread_kill.c: Do not allow SIGTIMER to + be send. + * sysdeps/pthread/posix-timer.h (timer_id2ptr, timer_ptr2id): Just + pass pointer through as ID. + * sysdeps/unix/sysv/linux/bits/local_lim.h (TIMER_MAX): Removed. + * sysdeps/unix/sysv/linux/kernel-posix-timers.h: New file. + * sysdeps/unix/sysv/linux/timer_create.c: New file. + * sysdeps/unix/sysv/linux/timer_delete.c: New file. + * sysdeps/unix/sysv/linux/timer_getoverr.c: New file. + * sysdeps/unix/sysv/linux/timer_gettime.c: New file. + * sysdeps/unix/sysv/linux/timer_routines.c: New file. + * sysdeps/unix/sysv/linux/timer_settime.c: New file. + * sysdeps/unix/sysv/linux/ia64/Versions: New file. + * sysdeps/unix/sysv/linux/ia64/timer_create.c: New file. + * sysdeps/unix/sysv/linux/ia64/timer_delete.c: New file. + * sysdeps/unix/sysv/linux/ia64/timer_getoverr.c: New file. + * sysdeps/unix/sysv/linux/ia64/timer_gettime.c: New file. + * sysdeps/unix/sysv/linux/ia64/timer_settime.c: New file. + * sysdeps/unix/sysv/linux/powerpc/powerpc64/Versions: New file. + * sysdeps/unix/sysv/linux/powerpc/powerpc64/timer_create.c: New file. + * sysdeps/unix/sysv/linux/powerpc/powerpc64/timer_delete.c: New file. + * sysdeps/unix/sysv/linux/powerpc/powerpc64/timer_getoverr.c: New file. + * sysdeps/unix/sysv/linux/powerpc/powerpc64/timer_gettime.c: New file. + * sysdeps/unix/sysv/linux/powerpc/powerpc64/timer_settime.c: New file. + * sysdeps/unix/sysv/linux/s390/s390-64/Versions: New file. + * sysdeps/unix/sysv/linux/s390/s390-64/timer_create.c: New file. + * sysdeps/unix/sysv/linux/s390/s390-64/timer_delete.c: New file. + * sysdeps/unix/sysv/linux/s390/s390-64/timer_getoverr.c: New file. + * sysdeps/unix/sysv/linux/s390/s390-64/timer_gettime.c: New file. + * sysdeps/unix/sysv/linux/s390/s390-64/timer_settime.c: New file. + * sysdeps/unix/sysv/linux/x86_64/Versions: New file. + * sysdeps/unix/sysv/linux/x86_64/compat-timer.h: New file. + * sysdeps/unix/sysv/linux/x86_64/timer_create.c: New file. + * sysdeps/unix/sysv/linux/x86_64/timer_delete.c: New file. + * sysdeps/unix/sysv/linux/x86_64/timer_getoverr.c: New file. + * sysdeps/unix/sysv/linux/x86_64/timer_gettime.c: New file. + * sysdeps/unix/sysv/linux/x86_64/timer_settime.c: New file. + + * pthreadP.h: Remove FRAME_LEFT definition. + * cleanup.c (_pthread_cleanup_push): Don't check for reference to + already left frame. Programs which have this problem are not POSIX + compliant. + * cleanup_defer.c (_pthread_cleanup_push_defer): Likewise. + +2003-03-24 Ulrich Drepper + + * sysdeps/pthread/tst-timer.c: Check return values of the + functions we test. + +2003-03-23 Roland McGrath + + * tst-tls3.c (do_test) [! HAVE___THREAD]: Don't test anything. + * tst-tls3mod.c: Likewise. + * tst-tls1.c: Likewise. + * tst-tls2.c: Likewise. + + * tst-mutex5.c (do_test): Unlock before destroy, otherwise we invoke + undefined behavior. + + * tst-join5.c (tf1, tf2): Add a cast. + + * Makeconfig (includes): Append -I$(..)nptl to this variable. + + * tst-barrier2.c (do_test) [! _POSIX_THREAD_PROCESS_SHARED]: + Don't test anything. + * tst-cond4.c: Likewise. + * tst-cond6.c: Likewise. + * tst-flock2.c: Likewise. + * tst-mutex4.c: Likewise. + * tst-rwlock4.c: Likewise. + * tst-signal1.c: Likewise. + * tst-spin2.c: Likewise. + * tst-cond11.c [! _POSIX_CLOCK_SELECTION]: Likewise. + + * tst-mutex4.c: Use test-skeleton.c. + * tst-spin2.c: Likewise. + * tst-sysconf.c: Likewise. + * tst-barrier2.c: Likewise. + * tst-cond4.c: Likewise. + * tst-cond6.c: Likewise. + * tst-rwlock4.c: Likewise. + * tst-unload.c: Likewise. + * tst-flock2.c (do_test): Use return instead of exit. + +2003-03-22 Jakub Jelinek + + * sysdeps/unix/sysv/linux/fork.c (__fork): Add libc_hidden_def. + +2003-03-21 Ulrich Drepper + + * sysdeps/unix/sysv/linux/ia64/lowlevellock.h + (__lll_mutex_trylock): Use atomic_compare_and_exchange_val_acq + instead of __lll_compare_and_swap. + * sysdeps/unix/sysv/linux/ia64/pthread_once.c (__pthread_once): + Likewise. + Removed definition if __lll_compare_and_swap. + + * cancellation.c: Adjust for new form of compare&exchange macros. + * cleanup_defer.c: Likewise. + * init.c: Likewise. + * libc-cancellation.c: Likewise. + * old_pthread_cond_broadcast.c: Likewise. + * old_pthread_cond_signal.c: Likewise. + * old_pthread_cond_timedwait.c: Likewise. + * old_pthread_cond_wait.c: Likewise. + * pthread_cancel.c: Likewise. + * pthread_create.c: Likewise. + * pthread_detach.c: Likewise. + * pthread_join.c: Likewise. + * pthread_key_delete.c: Likewise. + * pthread_setcancelstate.c: Likewise. + * pthread_setcanceltype.c: Likewise. + * pthread_timedjoin.c: Likewise. + * pthread_tryjoin.c: Likewise. + * sysdeps/pthread/createthread.c: Likewise. + +2003-03-20 Ulrich Drepper + + * sysdeps/unix/sysv/linux/ia64/lowlevellock.h: Include . + Remove __lll_add, __lll_dec_if_positive, and __lll_test_and_set + definitions. Replace uses with calls to atomic_* functions. + * sysdeps/unix/sysv/linux/powerpc/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/lowlevellock.c: Replace __lll_add and + __lll_test_and_set calls with atomic_exchange_and_add and + atomic_exchange calls respectively. + * sysdeps/unix/sysv/linux/sem_post.c: Likewise. + * sysdeps/unix/sysv/linux/sem_timedwait.c: Likewise. + * sysdeps/unix/sysv/linux/sem_trywait.c: Likewise. + * sysdeps/unix/sysv/linux/sem_wait.c: Likewise. + * sysdeps/unix/sysv/linux/ia64/pthread_once.c: Likewise. + * sysdeps/unix/sysv/linux/ia64/sem_port.c: Likewise. + * sysdeps/unix/sysv/linux/powerpc/pthread_once.c: Likewise. + + * allocatestack.c (allocate_stack): Assume atomic_exchange_and_add + returns the old value. + +2003-03-20 Martin Schwidefsky + + * sysdeps/s390/pthread_spin_lock.c (pthread_spin_lock): Use type + int for variable OLDVAL and correct inline assembler contraint. + * sysdeps/s390/pthread_spin_trylock.c (pthread_spin_trylock): Use + type int for variable OLD. + + * sysdeps/s390/tls.h (TLS_MULTIPLE_THREADS_IN_TCB): Define it + only for s390-32. + * sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h + (SINGLE_THREAD_P): Use global variable __local_multiple_threads + instead of multiple_threads field in the TCB. + +2003-03-19 Ulrich Drepper + + * sysdeps/i386/i686/bits/atomic.h: Removed. + * sysdeps/i386/i586/bits/atomic.h: Removed. + * sysdeps/i386/i486/bits/atomic.h: Removed. Moved to glibc. + * sysdeps/x86_64/bits/atomic.h: Removed. Moved to glibc. + * sysdeps/s390/bits/atomic.h: Removed. Moved to glibc. + * sysdeps/sh/bits/atomic.h: Removed. Moved to glibc. + * sysdeps/ia64/bits/atomic.h: Removed. Moved to glibc. + * sysdeps/powerpc/bits/atomic.h: Removed. Moved to glibc. + * atomic.h: Removed. Moved to glibc. + + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S: Add + support for clock selection. + + * sysdeps/pthread/pthread_cond_broadcast.c: Release lock before + signalling waiters. + +2003-03-18 Roland McGrath + + * sysdeps/unix/sysv/linux/powerpc/lowlevellock.h (__lll_test_and_set): + Add __lll_rel_instr first. Add memory clobber. + (lll_mutex_unlock): Use __lll_test_and_set. + From Paul Mackerras . + + * sysdeps/powerpc/tls.h (TLS_MULTIPLE_THREADS_IN_TCB): Define + unconditionally. + * sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h + (SINGLE_THREAD_P): Add `header.' prefix. + From Paul Mackerras . + + * Versions (libpthread: GLIBC_2.3.2): Move pthread_tryjoin_np and + pthread_timedjoin_np to ... + (libpthread: GLIBC_2.3.3): ... here. + (libpthread: GLIBC_2.2): Move pthread_barrierattr_getpshared there too. + + * sysdeps/pthread/pthread_cond_timedwait.c (__pthread_cond_timedwait): + Avoid shadowing VAL variable. + + * sysdeps/unix/sysv/linux/powerpc/lowlevellock.h (__lll_test_and_set): + New macro. + +2003-03-18 Ulrich Drepper + + * Makefile (tests): Add tst-cond11. + * tst-cond11.c: New file. + + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S: Reorder + struct passed to cleanup handler to eliminate one more + instruction. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: Likewise. + + * sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h + (pthrad_cond_t): Replace __unused field with __clock. + + * sysdeps/pthread/pthread_cond_wait.c: Release condvar lock before + waken all waiters in cleanup handler. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S: Likewise. + + * pthread_condattr_getclock.c: New file. + * pthread_condattr_setclock.c: New file. + * sysdeps/pthread/pthread.h: Declare these new functions. + * Versions [GLIBC_2.3.3] (libpthread): Add the new functions. + * Makefile (libpthread-routines): Add the new functions. + * sysdeps/unix/sysv/linux/internaltypes.h (struct pthread_condattr): + Renamed field to value. Document use of the bits. + * pthread_condattr_getpshared.c: Adjust for struct pthread_condattr + change. + * pthread_condattr_setpshared.c: Likewise. + * pthread_cond_init.c (__pthread_cond_init): Initialized __clock field. + * sysdeps/unix/sysv/linux/lowlevelcond.sym: Add cond_clock symbol. + * sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h (pthread_cond_t): + Add __clock field. + * sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: + Implement clock selection. + * sysdeps/pthread/pthread_cond_timedwait.c: Likewise. + * pthread-errnos.sym: Add ENOSYS. + * sysdeps/unix/sysv/linux/bits/posix_opt.h: Define + _POSIX_CLOCK_SELECTION. + * sysdeps/unix/sysv/linux/i386/bits/posix_opt.h: Likewise. + + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S: Remove + invalid .size directive. + +2003-03-17 Roland McGrath + + * sysdeps/unix/sysv/linux/lowlevellock.c (__lll_lock_wait): + Formatting tweaks. + +2003-03-17 Ulrich Drepper + + * sysdeps/unix/sysv/linux/ia64/pthread_once.c: Use __builtin_expect. + Use __lll_add instead of spelling it out. Use protected symbol names. + * sysdeps/unix/sysv/linux/ia64/sem_post.c: Use __builtin_expect. + Use __lll_add. + * sysdeps/unix/sysv/linux/ia64/lowlevellock.h (__lll_compare_and_swap): + Renamed from lll_compare_and_swap. Use new name where necessary. + (__lll_add): Defined. + (__lll_dec_if_positive): Defined. + (__lll_test_and_set): Defined. + * sysdeps/ia64/pthread_spin_init.c: Removed. + * sysdeps/unix/sysv/linux/ia64/lowlevelmutex.c: Removed. + * sysdeps/unix/sysv/linux/ia64/sem_trywait.c: Removed. + * sysdeps/unix/sysv/linux/ia64/sem_wait.c: Removed. + * sysdeps/unix/sysv/linux/ia64/lowlevellock.c: Removed. + * sysdeps/unix/sysv/linux/ia64/libc-lowlevellock.c: Removed. + * sysdeps/unix/sysv/linux/ia64/libc-lowlevelmutex.c: Removed. + * sysdeps/unix/sysv/linux/ia64/sem_timedwait.c: Removed. + * sysdeps/ia64/bits/atomic.h: Add __builtin_expect where appropriate. + * sysdeps/ia64/pthread_spin_unlock.c (pthread_spin_unlock): Use + __sync_lock_release_si. + Patch by Jakub Jelinek. + + * sysdeps/unix/sysv/linux/lowlevellock.c (__lll_timedlock_wait): + Fix timeout handling. + (__lll_timedwait_tid): Likewise. + (lll_unlock_wake_cb): Wake up other waiters if necessary. + Patch by Jakub Jelinek. + + * sysdeps/unix/sysv/linux/powerpc/lowlevellock.h: Pretty printing. + +2003-03-17 Roland McGrath + + PowerPC port contributed by Paul Mackerras . + * sysdeps/pthread/pthread_spin_init.c: New file. + * sysdeps/pthread/pthread_spin_unlock.c: New file. + * sysdeps/powerpc/Makefile: New file. + * sysdeps/powerpc/pthread_spin_lock.c: New file. + * sysdeps/powerpc/pthread_spin_trylock.c: New file. + * sysdeps/powerpc/pthreaddef.h: New file. + * sysdeps/powerpc/tcb-offsets.sym: New file. + * sysdeps/powerpc/td_ta_map_lwp2thr.c: New file. + * sysdeps/powerpc/tls.h: New file. + * sysdeps/powerpc/bits/atomic.h: New file. + * sysdeps/unix/sysv/linux/libc-lowlevelmutex.c: New file. + * sysdeps/unix/sysv/linux/libc-lowlevellock.c: New file. + * sysdeps/unix/sysv/linux/lowlevellock.c: New file. + + * sysdeps/unix/sysv/linux/lowlevelmutex.c: New file. + * sysdeps/unix/sysv/linux/sem_post.c: New file. + * sysdeps/unix/sysv/linux/sem_timedwait.c: New file. + * sysdeps/unix/sysv/linux/sem_trywait.c: New file. + * sysdeps/unix/sysv/linux/sem_wait.c: New file. + * sysdeps/unix/sysv/linux/powerpc/Makefile: New file. + * sysdeps/unix/sysv/linux/powerpc/createthread.c: New file. + * sysdeps/unix/sysv/linux/powerpc/fork.c: New file. + * sysdeps/unix/sysv/linux/powerpc/lowlevellock.h: New file. + * sysdeps/unix/sysv/linux/powerpc/pt-vfork.S: New file. + * sysdeps/unix/sysv/linux/powerpc/pthread_once.c: New file. + * sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h: New file. + * sysdeps/unix/sysv/linux/powerpc/bits/semaphore.h: New file. + * sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h: New file. + * sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h: New file. + + * sysdeps/unix/sysv/linux/ia64/lowlevellock.c: Use __gettimeofday, + not gettimeofday. + * sysdeps/unix/sysv/linux/ia64/lowlevelmutex.c: Likewise. + * sysdeps/unix/sysv/linux/ia64/sem_timedwait.c: Likewise. + * sysdeps/unix/sysv/linux/s390/lowlevellock.c: Likewise. + * sysdeps/unix/sysv/linux/s390/lowlevelmutex.c: Likewise. + * sysdeps/unix/sysv/linux/s390/sem_timedwait.c: Likewise. + +2003-03-17 Ulrich Drepper + + * sysdeps/pthread/pthread_cond_wait.c: Correct exit criteria. + * sysdeps/pthread/pthread_cond_timedwait.c: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S: Likewise. + Patch by Ewald Snel . + +2003-03-16 Roland McGrath + + * tst-fork4.c: Include . + * tst-signal2.c: Likewise. + * tst-mutex5.c (do_test): exit -> return. + * tst-mutex2.c: Include . + +2003-03-16 Ulrich Drepper + + * sysdeps/unix/sysv/linux/i386/i486/lowlevelmutex.S + (__lll_mutex_timedlock_wait): Correct expected value after + spurious wakeup. Otherwise we would never wait again. + + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.h: Work around red + zone versus inline asm stupidity. Use correct instructions. + + * tst-rwlock6.c: Add some more status output. + +2003-03-15 Roland McGrath + + * sysdeps/pthread/configure.in: New file. + * sysdeps/pthread/configure: New file (generated). + +2003-03-15 Ulrich Drepper + + * allocatestack.c (allocate_stack): Store the exact stack size of + user allocated stacks. + +2003-03-15 Jakub Jelinek + + * sysdeps/unix/sysv/linux/s390/s390-32/sysdep-cancel.h + (SINGLE_THREAD): Use `header' prefix instead of `header.data'. + * sysdeps/sh/tcb-offsets.sym (MULTIPLE_THREADS_OFFSET): Likewise. + * sysdeps/sh/tls.h (TLS_MULTIPLE_THREADS_IN_TCB): Define. + * sysdeps/unix/sysv/linux/ia64/sysdep-cancel.h (SINGLE_THREAD_P): + Use `header.' prefix. + * sysdeps/ia64/tcb-offsets.sym (MULTIPLE_THREADS_OFFSET): Likewise. + +2003-03-15 Ulrich Drepper + + * sysdeps/x86_64/pthreaddef.h (CURRENT_STACK_FRAME): Don't use + __builtin_frame_address, use stack pointer. + + * sysdeps/unix/sysv/linux/jmp-unwind.c: Use CURRENT_STACK_FRAME + instead of __builtin_frame_pointer. + +2003-03-14 Ulrich Drepper + + * tst-basic1.c (do_test): Add cast to avoid warning. + * tst-basic2.c (do_test): Likewise. + + * sysdeps/unix/sysv/linux/x86_64/pthread_once.S: Use correct + amount of stack correction. + + * tst-fork4.c: Use test-skeleton.c. + +2003-03-14 Roland McGrath + + * init.c: Fix typo "#eli" for "#else". + +2003-03-14 Steven Munroe + + * allocatestack.c (__stack_user): Use hidden_data_def. + * pthread_create.c (__pthread_keys): Likewise. + + * init.c [__powerpc__] (__NR_set_tid_address): Define it. + +2003-03-14 Roland McGrath + + * tst-fork4.c: New file. + * Makefile (tests): Add it. + + * descr.h (struct pthread): Move the union out of [!TLS_DTV_AT_TP], so + we always define the padding space. + [!TLS_DTV_AT_TP]: Give tcbhead_t field a name, `header', since GCC + stopped supporting its own extensions fully. + [TLS_MULTIPLE_THREADS_IN_TCB]: Put `multiple_threads' inside a wrapper + struct also called `header', so `header.multiple_threads' is the field + name to use on all machines. + * allocatestack.c (allocate_stack): Use `header.' prefix. + * sysdeps/pthread/createthread.c (create_thread): Likewise. + * pthread_create.c (__pthread_create_2_1): Likewise. + * sysdeps/i386/tls.h (INSTALL_NEW_DTV, THREAD_DTV): Likewise. + (THREAD_SELF): Likewise. + * sysdeps/x86_64/tls.h: Likewise. + * sysdeps/unix/sysv/linux/i386/sysdep-cancel.h + (SINGLE_THREAD_P): Likewise. + * sysdeps/unix/sysv/linux/sh/sysdep-cancel.h + (SINGLE_THREAD_P): Likewise. + * sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h + (SINGLE_THREAD_P): Likewise. + + * sysdeps/s390/td_ta_map_lwp2thr.c (td_ta_map_lwp2thr): Use REGS[18] + value directly. + +2003-03-14 Ulrich Drepper + + * pthread_create.c (start_thread): Use CALL_THREAD_FCT if defined. + * sysdeps/i386/tls.h: Define CALL_THREAD_FCT. + + * pthread_create.c (start_thread): setjmp is expected to return 0. + + * sysdeps/x86_64/tls.h (THREAD_GETMEM): Mark asms volatile. + (THREAD_GETMEM_NC): Likewise. + +2003-03-13 Ulrich Drepper + + * allocatestack.c (allocate_stack): If MULTI_PAGE_ALIASING is defined + and the size of the stack which must be allocated is a multiple, + allocate one more page. + * sysdeps/i386/i686/Makefile: Don't define COLORING_INCREMENT, but + MULTI_PAGE_ALIASING. + +2003-03-13 Roland McGrath + + * pthread_create.c (start_thread): Set EXITING_BIT after the + event-reporting (and destructors), not before. + +2003-03-13 Jakub Jelinek + + * sysdeps/unix/sysv/linux/ia64/lowlevellock.h (lll_futex_timed_wait, + lll_futex_wake): Declare register variables as long int instead of + unsigned long int. Patch by Ian Wienand . + Make syscall arguments clobbered by the syscall. + (lll_futex_wait): Define using lll_futex_timed_wait. + + * sysdeps/ia64/td_ta_map_lwp2thr.c (td_ta_map_lwp2thr): Cast regs[13] + to void *. + + * sysdeps/unix/sysv/linux/fork.c (__libc_fork): Only declare and set + PPID if [! NDEBUG]. + + * allocatestack.c (nptl_ncreated): Only declare if + COLORING_INCREMENT != 0. + + * pthreadP.h (__pthread_enable_asynccancel_2): New prototype. + (__libc_enable_asynccancel_2): Remove prototype. + + * sysdeps/unix/sysv/linux/ia64/fork.c (ARCH_FORK): Swap ptid and + ctid to match kernel. + +2003-03-12 Ulrich Drepper + + * sysdeps/unix/sysv/linux/Makefile (sysdep_routines): Add + libc_multiple_threads. + * sysdeps/unix/sysv/linux/libc_pthread_init.c: Move definition of + __libc_multiple_threads to... + * sysdeps/unix/sysv/linux/libc_multiple_threads.c: ...here. New file. + + * sysdeps/unix/sysv/linux/x86_64/sem_post.S: Remove unnecessary + versioning. + * sysdeps/unix/sysv/linux/x86_64/sem_trywait.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/sem_wait.S: Likewise. + + * sysdeps/unix/sysv/linux/x86_64/pthread_once.S + (__pthread_once_internal): Define. + + * sysdeps/unix/sysv/linux/i386/i486/sem_post.S: Use shlib-compat.h + macros instead of .symver directly. + * sysdeps/unix/sysv/linux/i386/i486/sem_trywait.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/sem_wait.S: Likewise. + + * sysdeps/x86_64/tls.h [__ASSEMBLER__]: Include tcb-offsets.h. + * sysdeps/x86_64/tcb-offsets.sym: New file. + * sysdeps/x86_64/Makefile: New file. + + * sysdeps/i386/tcb-offsets.sym: Add SELF. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_rdlock.S: Use SELF + to access own pthread_t in TCB. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedrdlock.S: + Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedwrlock.S: + Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_wrlock.S: Likewise. + +2003-03-12 Roland McGrath + + * pthread-errnos.sym: New file. + * Makefile (gen-as-const-headers): New variable, list that file. + * sysdeps/unix/sysv/linux/i386/i486/sem_wait.S: Include generated + header instead of defining errno values here. + * sysdeps/unix/sysv/linux/i386/i486/sem_trywait.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/sem_post.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_wrlock.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedwrlock.S: + Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedrdlock.S: + Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_rdlock.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/lowlevelmutex.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/sem_wait.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/sem_trywait.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/sem_post.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/lowlevelmutex.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.S: Likewise. + * sysdeps/unix/sysv/linux/sh/sem_trywait.S: Likewise. + * sysdeps/unix/sysv/linux/sh/sem_timedwait.S: Likewise. + * sysdeps/unix/sysv/linux/sh/sem_post.S: Likewise. + * sysdeps/unix/sysv/linux/sh/sem_wait.S: Likewise. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_wrlock.S: Likewise. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedwrlock.S: Likewise. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedrdlock.S: Likewise. + * sysdeps/unix/sysv/linux/sh/pthread_cond_timedwait.S: Likewise. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_rdlock.S: Likewise. + * sysdeps/unix/sysv/linux/sh/lowlevellock.S: Likewise. + * sysdeps/unix/sysv/linux/sh/lowlevelmutex.S: Likewise. + * sysdeps/i386/i486/pthread_spin_trylock.S: Likewise. + * sysdeps/x86_64/pthread_spin_trylock.S: Likewise. + * sysdeps/sh/pthread_spin_trylock.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_rdlock.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_wrlock.S: Likewise. + + * sysdeps/unix/sysv/linux/fork.c: Add an assert to check that + CLONE_CHILD_SETTID worked. + +2003-03-12 Ulrich Drepper + + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedrdlock.S: New + file. + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedwrlock.S: New + file. + + * sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h + (pthread_cond_t): Add padding. + + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_rdlock.S: New file. + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_wrlock.S: New file. + * sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_unlock.S: New file. + + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedwrlock.S + (__pthread_rwlock_timedwrlock): Add missing opcode suffix. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedrdlock.S + (__pthread_rwlock_timedrdlock): Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_wrlock.S + (__pthread_rwlock_wrlock): Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_rdlock.S + (__pthread_rwlock_rdlock): Likewise. + + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S: New file. + + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: Return + result of lock re-get if it fails. + +2003-03-11 Ulrich Drepper + + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.S: Fix asm syntax. + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/x86_64/lowlevelmutex.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_once.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/sem_post.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/sem_trywait.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/sem_wait.S: Likewise. + + * sysdeps/x86_64/tls.h (THREAD_SELF, THREAD_GETMEM, THREAD_GETMEM_NC, + THREAD_SETMEM, THREAD_SETMEM_NC): Correct asm syntax. + + * allocatestack.c [! TLS_MULTIPLE_THREADS_IN_TCB] (allocate_stack): + Initialize *__libc_multiple_threads_ptr not __libc_multiple_threads. + * sysdeps/pthread/createthread.c [! TLS_MULTIPLE_THREADS_IN_TCB] + (create_thread): Likewise. + Define __pthread_multiple_threads and __libc_multiple_threads_ptr. + * init.c (__pthread_initialize_minimal_internal): Initialize + __libc_multiple_threads_ptr if necessary. + * pthreadP.h: Adjust prototype for __libc_pthread_init. Declare + __pthread_multiple_threads and __libc_multiple_threads_ptr. + * sysdeps/unix/sysv/linux/libc_pthread_init.c: Define + __libc_multiple_threads. + (__libc_pthread_init): Return pointer to __libc_pthread_init if + necessary. + + * sysdeps/i386/tls.h (THREAD_SETMEM): Fix one-byte variant. + (THREAD_SETMEM_NC): Likewise. + + * sysdeps/x86_64/pthread_spin_trylock.c: Removed. + * sysdeps/x86_64/pthread_spin_trylock.S: New file. + * sysdeps/x86_64/pthread_spin_unlock.c: Removed. + * sysdeps/x86_64/pthread_spin_unlock.S: New file. + + * sysdeps/i386/i486/pthread_spin_trylock.S (pthread_spin_trylock): + Eliminate one entire instruction. + + * cancellation.c (__pthread_enable_asynccancel_2): New function. + * pthreadP.h: Declare __pthread_enable_asynccancel_2. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S + (__pthread_cond_timedwait): Use __pthread_enable_asynccancel_2 + instead of __pthread_enable_asynccancel. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S + (__pthread_cond_wait): Likewise. + * sysdeps/pthread/pthread_cond_timedwait.c + (__pthread_cond_timedwait): Likewise. + * sysdeps/pthread/pthread_cond_wait.c (__pthread_cond_wait): Likewise. + + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S + (__condvar_cleanup): Wake up all waiters in case we got signaled + after being woken up but before disabling asynchronous + cancellation. + * sysdeps/pthread/pthread_cond_wait.c (__condvar_cleanup): Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S + (__condvar_cleanup): Likewise. + + * init.c (__NR_set_tid_address): If already defined, don't redefine. + Make it an error if architecture has no #if case. Add x86-64. + + * sysdeps/unix/sysv/linux/x86_64/Makefile: Add flags for + pt-initfini.s generation. + + * sysdeps/x86_64/tls.h: Include . + (TLS_INIT_TP): Fix typo. + +2003-03-11 Jakub Jelinek + + * sysdeps/ia64/bits/atomic.h (atomic_exchange_and_add): Swap 2nd and + 3rd argument of __arch_compare_and_exchange_{32,64}_val_acq. + + * sysdeps/unix/sysv/linux/ia64/sem_post.c: Include semaphore.h. + * sysdeps/unix/sysv/linux/ia64/sem_timedwait.c: Likewise. + * sysdeps/unix/sysv/linux/ia64/sem_trywait.c: Likewise. + * sysdeps/unix/sysv/linux/ia64/sem_wait.c: Likewise. + * sysdeps/unix/sysv/linux/s390/sem_post.c: Likewise. + * sysdeps/unix/sysv/linux/s390/sem_timedwait.c: Likewise. + * sysdeps/unix/sysv/linux/s390/sem_trywait.c: Likewise. + * sysdeps/unix/sysv/linux/s390/sem_wait.c: Likewise. + +2003-03-11 Ulrich Drepper + + * sysdeps/pthread/pthread_cond_timedwait.c + (__pthread_cond_timedwait): Return the result of the final + locking. If it succeeds, the regular function return value. + + * sysdeps/pthread/pthread_cond_wait.c (__pthread_cond_wait): + Return result of the final locking. + * version.c (__nptl_main): Work around problems with the strange + INTERNAL_SYSCALL macro on ppc32. + * init.c (__pthread_initialize_minimal_internal): Unblock + SIGCANCEL in case the parent blocked it. + Reported by Paul Mackerras . + + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S: New file. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.S: New file. + * sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S: New file. + +2003-03-11 Jakub Jelinek + + * sysdeps/pthread/pthread_cond_timedwait.c + (__pthread_cond_timedwait): Unlock and fail if + __pthread_mutex_unlock_internal failed. + + * sysdeps/pthread/createthread.c (ARCH_CLONE): Define if not defined. + (create_thread): Only assert PD->tcb != NULL under [TLS_TCB_AT_TP]. + Use ARCH_CLONE. + * allocatestack.c (ALLOCATE_STACK_PARMS): New macro. + [NEED_SEPARATE_REGISTER_STACK] (STACK_VARIABLES, + STACK_VARIABLES_ARGS, STACK_VARIABLES_PARMS, ALLOCATE_STACK_PARMS, + ALLOCATE_STACK): New macros. + (TLS_TPADJ): New macro. + (get_cached_stack, queue_stack, __deallocate_stack): Use TLS_TPADJ. + (allocate_stack): Handle TLS_DTV_AT_TP and + NEED_SEPARATE_REGISTER_STACK. Use TLS_TPADJ. + * pthread_create.c (__pthread_create_2_1) [! TLS_TCB_AT_TP]: + Don't set PD->self. + * init.c [__ia64__] (__NR_set_tid_address): Define. + + * sysdeps/unix/sysv/linux/ia64/bits/pthreadtypes.h: New file. + * sysdeps/unix/sysv/linux/ia64/bits/semaphore.h: New file. + * sysdeps/unix/sysv/linux/ia64/fork.c: New file. + * sysdeps/unix/sysv/linux/ia64/createthread.c: New file. + * sysdeps/unix/sysv/linux/ia64/libc-lowlevellock.c: New file. + * sysdeps/unix/sysv/linux/ia64/libc-lowlevelmutex.c: New file. + * sysdeps/unix/sysv/linux/ia64/lowlevellock.c: New file. + * sysdeps/unix/sysv/linux/ia64/lowlevellock.h: New file. + * sysdeps/unix/sysv/linux/ia64/lowlevelmutex.c: New file. + * sysdeps/unix/sysv/linux/ia64/pt-initfini.c: New file. + * sysdeps/unix/sysv/linux/ia64/pt-vfork.S: New file. + * sysdeps/unix/sysv/linux/ia64/pthread_once.c: New file. + * sysdeps/unix/sysv/linux/ia64/sem_post.c: New file. + * sysdeps/unix/sysv/linux/ia64/sem_timedwait.c: New file. + * sysdeps/unix/sysv/linux/ia64/sem_trywait.c: New file. + * sysdeps/unix/sysv/linux/ia64/sem_wait.c: New file. + * sysdeps/unix/sysv/linux/ia64/sysdep-cancel.h: New file. + * sysdeps/ia64/bits/atomic.h: New file. + * sysdeps/ia64/Makefile: New file. + * sysdeps/ia64/pthread_spin_init.c: New file. + * sysdeps/ia64/pthread_spin_lock.c: New file. + * sysdeps/ia64/pthread_spin_trylock.c: New file. + * sysdeps/ia64/pthread_spin_unlock.c: New file. + * sysdeps/ia64/pthreaddef.h: New file. + * sysdeps/ia64/tcb-offsets.sym: New file. + * sysdeps/ia64/td_ta_map_lwp2thr.c: New file. + * sysdeps/ia64/tls.h: New file. + + * sysdeps/s390/pthreaddef.h (__exit_thread_inline): Pass 1 argument + to syscall instead of no arguments. + +2003-03-10 Ulrich Drepper + + * sysdeps/unix/sysv/linux/x86_64/sem_post.S: New file. + * sysdeps/unix/sysv/linux/x86_64/sem_trywait.S: New file. + * sysdeps/unix/sysv/linux/x86_64/sem_wait.S: New file. + * sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S: New file. + + * sysdeps/unix/sysv/linux/i386/i486/sem_post.S: Fix error value in + unused code. + + * sysdeps/unix/sysv/linux/x86_64/pthread_barrier_wait.S: New file + + * sysdeps/unix/sysv/linux/Makefile (gen-as-const-headers): Add + lowlevelbarrier.sym. + * sysdeps/unix/sysv/linux/lowlevelbarrier.sym: New file. + * sysdeps/unix/sysv/linux/i386/i486/pthread_barrier_wait.S: + Include lowlevelbarrier.h and don't define offsets locally. + * sysdeps/unix/sysv/linux/sh/pthread_barrier_wait.S: Likewise. + + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.h + (__lll_mutex_lock_wait): Reverse order of first two parameters. + (__lll_mutex_timedlock_wait): Likewise. + (lll_mutex_lock): Adjust asm for that. + (lll_mutex_timedlock): Likewise. Mark cx, cc, r10 as clobbered. + (lll_lock): Adjust asm for operand order change. + * sysdeps/unix/sysv/linux/x86_64/lowlevelmutex.S: New file. + * sysdeps/unix/sysv/linux/x86_64/libc-lowlevelmutex.S: New file. + + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.h (__lll_lock_wait): + Reverse order of parameters. + (__lll_timedwait_tid): Remove regparms attribute. + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.S: New file. + * sysdeps/unix/sysv/linux/x86_64/libc-lowlevellock.S: New file. + + * sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S + (__lll_timedwait_tid): Remove one unnecessary instruction. + + * sysdeps/unix/sysv/linux/sh/lowlevelmutex.S: Define + __lll_mutex_timedlock_wait only for NOT_IN_libc. + * sysdeps/unix/sysv/linux/sh/libc-lowlevelmutex.S: Include + lowlevelmutex.S. + + * sysdeps/unix/sysv/linux/sh/lowlevellock.S: Define + lll_unlock_wake_cb, __lll_wait_tid, and __lll_timedwait_tid only + for NOT_IN_libc. + * sysdeps/unix/sysv/linux/sh/libc-lowlevellock.S: Include + lowlevellock.S. + + * sysdeps/unix/sysv/linux/i386/i486/lowlevelmutex.S: Don't define + LOCK is already defined. Don't define __lll_mutex_timedlock_wait + for libc.so. + * sysdeps/unix/sysv/linux/i386/i486/libc-lowlevelmutex.S: Only + define LOCK here (if UP is not defined). The actual code is in + lowlevelmutex.S. + + * sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S: Don't define + LOCK is already defined. Don't define lll_unlock_wake_cb and + __lll_timedwait_tid for libc.so. + * sysdeps/unix/sysv/linux/i386/i486/libc-lowlevellock.S: Only + define LOCK here (if UP is not defined). The actual code is in + lowlevellock.S. + + * sysdeps/unix/sysv/linux/i386/lowlevelsem.h: Not needed anymore. + * sysdeps/unix/sysv/linux/s390/lowlevelsem.h: Likewise. + * sysdeps/unix/sysv/linux/s390/sem_post.c: Include lowlevellock.h + instead of lowlevelsem.h. + * sysdeps/unix/sysv/linux/s390/sem_timedwait.c: Likewise. + * sysdeps/unix/sysv/linux/s390/sem_trywait.c: Likewise. + * sysdeps/unix/sysv/linux/s390/sem_wait.c: Likewise. + + * sysdeps/unix/sysv/linux/Makefile (gen-as-const-headers): Add + lowlevelrwlock.sym. + * sysdeps/unix/sysv/linux/lowlevelrwlock.sym: New file. + * sysdeps/unix/sysv/linux/i386/lowlevelrwlock.h: Removed. + * sysdeps/unix/sysv/linux/sh/lowlevelrwlock.h: Removed. + + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.h (lll_trylock): Fix + register loading. + * sysdeps/unix/sysv/linux/i386/lowlevellock.h (lll_trylock): Undo + last changed. D'oh. + + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.h: New file. + + * sysdeps/unix/sysv/linux/i386/lowlevellock.h: Remove declaration + of __libc_locking_needed. + (lll_trylock): Initialize %eax to zero. + + * sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h: Update + pthread_cond_t definition. + +2003-03-10 Roland McGrath + + * sysdeps/unix/sysv/linux/lowlevelcond.sym: New file. + * sysdeps/unix/sysv/linux/Makefile (gen-as-const-headers): Add it. + * sysdeps/unix/sysv/linux/sh/lowlevelcond.h: File removed. + * sysdeps/unix/sysv/linux/i386/lowlevelcond.h: Likewise. + * sysdeps/unix/sysv/linux/x86_64/lowlevelcond.h: Likewise. + + * allocatestack.c (allocate_stack) [!TLS_MULTIPLE_THREADS_IN_TCB]: + Instead of setting PD->multiple_threads, set globals + __pthread_multiple_threads and __libc_multiple_threads. + * sysdeps/pthread/createthread.c (create_thread): Likewise. + * sysdeps/i386/tls.h (TLS_MULTIPLE_THREADS_IN_TCB): Define it. + * sysdeps/s390/tls.h (TLS_MULTIPLE_THREADS_IN_TCB): Likewise. + + * descr.h (struct pthread): Conditionalize first member on + [!TLS_DTV_AT_TP]. Replace the `header' member with an anonymous union + containing an anonymous tcbhead_t. Move `list' member out. + [TLS_MULTIPLE_THREADS_IN_TCB]: Define a `multiple_threads' member. + * allocatestack.c: Remove use of `header.data.' prefix. + * pthread_create.c: Likewise. + * init.c (__pthread_initialize_minimal_internal): Likewise. + * sysdeps/pthread/createthread.c (create_thread): Likewise. + * sysdeps/i386/tls.h (INSTALL_DTV): Add parens. + (THREAD_SELF, THREAD_DTV, INSTALL_NEW_DTV): No `header.data.' prefix. + * sysdeps/x86_64/tls.h: Likewise. + * sysdeps/unix/sysv/linux/i386/sysdep-cancel.h + (SINGLE_THREAD_P): Likewise. + * sysdeps/unix/sysv/linux/sh/sysdep-cancel.h + (SINGLE_THREAD_P): Likewise. + * sysdeps/i386/tls.h (tcbhead_t): Remove `list' member. + * sysdeps/s390/tls.h (tcbhead_t): Likewise. + +2003-03-09 Ulrich Drepper + + * sysdeps/unix/sysv/linux/x86_64/lowlevelcond.h: New file. + + * sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h: New file. + * sysdeps/unix/sysv/linux/x86_64/fork.c: New file. + + * sysdeps/unix/sysv/linux/x86_64/pthread_once.S: Fix many + leftovers from the ia32 code. + + * sysdeps/unix/sysv/linux/i386/pthread_once.S: Remove unneccessary + memory load. + (clear_once_control): Don't load %esi. + + * sysdeps/x86_64/tls.h: Remove all traces of segment descriptor + handling. + + * sysdeps/unix/sysv/linux/x86_64/fork.c: New file. + + * sysdeps/unix/sysv/linux/s390/createthread.c: Moved to... + * sysdeps/unix/sysv/linux/createthread.c: ...here. + + * Makefile (tests): Add tst-cond10. + * tst-cond10.c: New file. + +2003-03-08 Ulrich Drepper + + * tst-tls2.c (do_test): Add TEMP_FAILURE_RETRY around sem_wait call. + * tst-signal3.c (do_test): Likewise. + * tst-sem5.c (do_test): Likewise. + * tst-kill6.c (do_test): Likewise. + * tst-tls3.c (do_test): Likewise. Include . + + * sysdeps/unix/sysv/linux/i386/lowlevellock.h: Use add/sub instead + of inc/dec. + * sysdeps/unix/sysv/linux/i386/lowlevelsem.h: Likewise. + * sysdeps/unix/sysv/linux/i386/pthread_once.S: Likewise + * sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/sem_post.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_wrlock.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_unlock.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedwrlock.S: + Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedrdlock.S: + Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_rdlock.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_signal.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_barrier_wait.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/lowlevelmutex.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S: Likewise. + + * allocatestack.c (allocate_stack): If mprotect() fails free the + TLS memory. + +2003-03-07 Ulrich Drepper + + * sysdeps/i386/i486/bits/atomic.h: Fix a few unused definitions. + + * sysdeps/unix/sysv/linux/i386/lowlevellock.h: Remove all trace of + lll_wake_tid. This was used only to work around kernel limits in + the early days. + * sysdeps/unix/sysv/linux/s390/lowlevellock.h: Likewise. + * sysdeps/unix/sysv/linux/sh/libc-lowlevellock.S: Likewise. + * sysdeps/unix/sysv/linux/sh/lowlevellock.S: Likewise. + * sysdeps/unix/sysv/linux/sh/lowlevellock.h: Likewise. + + * init.c (__static_tls_align_m1): Renamed from __static_tls_align. + (__pthread_initialize_minimal_internal): Change initialization of + __static_tls_align_m1 appropriately. + * pthreadP.h (__static_tls_align_m1): Renamed from + __static_tls_align. + * allocatestack.c (allocate_stack): Use __static_tls_align_m1 + instead of __static_tls_align-1. + +2003-03-04 Ulrich Drepper + + * sysdeps/unix/sysv/linux/x86_64/Makefile: New file. + + * pthread_create.c: Define __pthread_keys using nocommon + attribute, not by placing it explicitly in bss. + Remove DEFINE_DEALLOC definition. Not needed anymore. + + * allocatestack.c: Define ARCH_MAP_FLAGS if not already defined. + Use it in mmap call to allocate stacks. + + * sysdeps/pthread/createthread.c (create_thread): Fix comment. + + * pthread_create.c (start_thread): Use THREAD_SETMEM to store + result of the thread function. + +2003-03-03 Ulrich Drepper + + * sysdeps/unix/sysv/linux/s390/dl-sysdep.h: Removed. The generic + version is just fine. + + * sysdeps/unix/sysv/linux/libc_pthread_init.c + (__pthread_child_handler): Renamed from pthread_child_handler, + exported, and marked hidden. Change all users. + * sysdeps/unix/sysv/linux/register-atfork.c (free_mem): Do not + free __pthread_child_handler from child list. + +2003-03-03 Martin Schwidefsky + + * atomic.h (atomic_exchange_and_add): Return newval, not oldval. + + * sysdeps/pthread/pthread_cond_timedwait.c (__pthread_cond_timedwait): + Fix handling of cancellation and failing pthread_mutex_unlock call. + * sysdeps/pthread/pthread_cond_wait.c (__condvar_cleanup): Likewise. + (__pthread_cond_wait): Likewise. + + * sysdeps/pthread/pthread_rwlock_timedrdlock.c + (pthread_rwlock_timedrdlock): Fix clobber of result variable by + lll_futex_timed_wait call. + * sysdeps/pthread/pthread_rwlock_timedwrlock.c + (pthread_rwlock_timedwrlock): Likewise. + + * sysdeps/unix/sysv/linux/s390/libc-lowlevellock.c (___lll_lock): + Don't define lll_unlock_wake_cb and ___lll_timedwait_tid in libc.so. + * sysdeps/unix/sysv/linux/s390/lowlevellock.c: Remove XXX comments. + + * sysdeps/unix/sysv/linux/s390/sem_post.c (__new_sem_post): Fix + check of lll_futex_wake return value. + +2003-03-03 Roland McGrath + + * forward.c: Fix typo in __pthread_attr_init_2_0 compat_symbol decl. + + * sysdeps/pthread/pthread-functions.h (struct pthread_functions): + Argument to ptr___pthread_cleanup_upto is __jmp_buf, not jmp_buf. + * sysdeps/unix/sysv/linux/jmp-unwind.c: Likewise. + +2003-03-02 Ulrich Drepper + + * sysdeps/pthread/timer_create.c (timer_create): Return correct + error for CPU clocks. + + * sysdeps/unix/sysv/linux/bits/posix_opt.h: Define + _POSIX_MONOTONIC_CLOCK. + * sysdeps/unix/sysv/linux/i386/bits/posix_opt.h: Likewise. + + * tst-cancel4.c (tf_sleep): Lower sleep time a bit to not upset + recent kernels. + +2003-03-01 Ulrich Drepper + + * descr.h (struct pthread): Move cleanup field to the front. + +2003-03-01 Roland McGrath + + * sem_open.c (sem_open): Braino fix. + +2003-03-01 Ulrich Drepper + + * sysdeps/i386/tcb-offsets.sym: Add CLEANUP and CLEANUP_PREV. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S: Inline + __pthread_cleanup_pop functionality. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: Likewise. + + * descr.h (struct pthread): Move tid field to the front now that + it is often used. + + * sysdeps/unix/sysv/linux/i386/i486/libc-lowlevelmutex.S + (__lll_mutex_timedlock_wait): Remove. + (__lll_mutex_unlock_wake): Don't save, load, and restore %esi. + * sysdeps/unix/sysv/linux/i386/i486/lowlevelmutex.S + (__lll_mutex_unlock_wake): Don't save, load, and restore %esi. + * sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S + (lll_unlock_wake_cb): Don't save and restore %esi. + (__lll_unlock_wake): Add alignment. Don't save, load, and restore + %esi. + (__lll_timedwait_tid): Add alignment. + * sysdeps/unix/sysv/linux/i386/i486/libc-lowlevellock.S + (__lll_unlock_wake): Add alignment. Don't save, load, and restore + %esi. + (__lll_timedwait_tid): Removed. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.S + (__pthread_cond_broadcast): Don't save, load, and restore %esi. + * sysdeps/unix/sysv/linux/i386/i486/pthread_barrier_wait.S + (pthread_barrier_wait): Don't save, load, and restore %esi for + last thread. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_signal.S + (__pthread_cond_signal): Don't save, load, and restore %esi. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_unlock.S + (__pthread_rwlock_unlock): Don't save, load, and restore %esi. + * sysdeps/unix/sysv/linux/i386/i486/sem_post.S (__new_sem_post): + Don't save, load, and restore %esi. + +2003-02-27 Ulrich Drepper + + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.S: + Release lock before waking up the waiters. + + * tst-exit1.c (do_test): Don't start more than one thread in parallel. + + * tst-rwlock9.c (writer_thread): Correct adding TIMEOUT. + (reader_thread): Likewise. + + * sysdeps/pthread/pthread_rwlock_unlock.c + (__pthread_rwlock_unlock): Release internal lock early. Don't try + to wake up readers if there are none. + + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_unlock.S: + Release internal lock before wake threads. + +2003-02-26 Ulrich Drepper + + * Makefile (tests): Add tst-rwlock10 and tst-rwlock11. + * tst-rwlock8.c: Initialize lock with INIT. Allow INIT to be + predefined. + * tst-rwlock9.c: Likewise. + * tst-rwlock10.c: New file. + * tst-rwlock11.c: New file. + + * Makefile (tests): Add tst-dlsym1. + * tst-dlsym1.c: New file. + + * init.c (__pthread_initialize_minimal_internal): Set + GL(dl_error_catch_tsd) to __libc_dl_error_tsd. + * Versions (libc:GLIBC_PRIVATE): Export __libc_dl_error_tsd. + +2003-02-24 Ulrich Drepper + + * sem_open.c (sem_open): Fix handling of O_CREAT without O_EXCL. + + * tst-cond2.c: Fix sychronization with child. + + * tst-rwlock8.c (reader_thread): Remove unused variable. + + * Makefile: Add rules to build and run tst-tls3. + * tst-tls3.c: New file. + * tst-tls3mod.c: New file. + + * Makefile (tests): Add tst-rwlock8 and tst-rwlock9. + * tst-rwlock8.c: New file. + * tst-rwlock9.c: New file. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_rdlock.S: Fix + complete broken rwlock implementation. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedrdlock.S: + Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedwrlock.S: + Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_unlock.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_wrlock.S: Likewise. + * sysdeps/pthread/pthread_rwlock_rdlock.c: Likewise. + * sysdeps/pthread/pthread_rwlock_timedrdlock.c: Likewise. + * sysdeps/pthread/pthread_rwlock_timedwrlock.c: Likewise. + * sysdeps/pthread/pthread_rwlock_unlock.c: Likewise. + * sysdeps/pthread/pthread_rwlock_wrlock.c: Likewise. + +2003-02-23 Roland McGrath + + * Makefile (nptl-version): Change regexp so case sensitivity is ok. + +2003-02-23 Ulrich Drepper + + * Makefile (tests): Add tst-context1. + * tst-context1.c: New file. + + * Makefile (tests): Add tst-tls1 and tst-tls2. + * tst-tls1.c: New file. + * tst-tls2.c: New file. + + * libc-cancellation.c (__libc_enable_asynccancel): Correct test + for failed cmpxchg. + + * pthread_create.c (start_thread): Set EXITING_BIT early. + + * sysdeps/i386/tls.h (THREAD_GETMEM): Mark asm as volatile. + (THREAD_GETMEM_NC): Likewise. + +2003-02-22 Ulrich Drepper + + * sysdeps/unix/sysv/linux/i386/i486/pthread_barrier_wait.S: Shave + off 3 more bytes by using offset-less instructions when possible. + + * Makefile: Add dependency for $(objpfx)version.d. + + * eintr.c (eintr_source): Add unnecessary return but the compiler + insists. + + * tst-kill3.c: Include . + +2003-02-21 Roland McGrath + + * pthread_create.c (start_thread): Call __libc_thread_freeres. + +2003-02-21 Ulrich Drepper + + * Makefile (tests): Add tst-eintr1. + (distribute): Add eintr.c. + * tst-eintr1.c: New file. + * eintr.c: New file. + + * pthread_cancel.c (pthread_cancel): Use tkill directly. + + * sysdeps/unix/sysv/linux/pthread_kill.c (__pthread_kill): + Disallow sending SIGCANCEL. + + * Makefile (tests): Remove tst-basic7. Add tst-kill1, tst-kill2, + tst-kill3, tst-kill4, tst-kill5, tst-kill6. + * tst-kill1.c: New file. + * tst-kill2.c: New file. + * tst-kill3.c: New file. + * tst-kill5.c: New file. + * tst-kill6.c: New file. + * tst-basic7.c: Renamed to... + * tst-kill4.c: ...this. + +2003-02-21 Roland McGrath + + * Makefile (install-lib-ldscripts): New variable. + +2003-02-21 Ulrich Drepper + + * pthreadP.h: Define INVALID_TD_P and INVALID_NOT_TERMINATED_TD_P. + * pthread_cancel.c: Use INVALID_TD_P. + * pthread_detach.c: Likewise. + * pthread_getschedparam.c: Likewise. + * pthread_setschedparam.c: Likewise. + * sysdeps/pthread/pthread_getcpuclockid.c: Likewise. + * sysdeps/unix/sysv/linux/pthread_kill.c: Likewise. + * pthread_join.c: Use INVALID_NOT_TERMINATED_TD_P. + * pthread_timedjoin.c: Likewise. + + * tst-basic7.c: Include . + + * pthread_join.c (pthread_join): Limited checking for invalid + descriptors. + * pthread_timedjoin.c (pthread_timedjoin_np): Likewise. + +2003-02-20 Ulrich Drepper + + * pthread_create.c (deallocate_tsd): Reset found_nonzero at the + beginning of the loop. Clear the entire first block of TSD. + * Makefile (tests): Add tst-key4. + * tst-key4.c: New file. + +2003-02-18 Ulrich Drepper + + * Makefile (tests): Add tst-basic7. + * tst-basic7.c: New file. + + * pthread_create.c (deallocate_tsd): Mark as internal_function. + Add some more __builtin_expect. + + * pthreadP.h: Define dummy version of DEBUGGING_P. + +2003-02-17 Ulrich Drepper + + * sysdeps/unix/sysv/linux/i386/bits/posix_opt.h: Remnove + _POSIX_THREAD_PRIORITY_SCHEDULING. + * sysdeps/unix/sysv/linux/i386/bits/posix_opt.h: Remove + _XOPEN_REALTIME_THREADS. + * sysdeps/unix/sysv/linux/bits/posix_opt.h: Likewise. + + * sysdeps/unix/sysv/linux/pthread_kill.c (__pthread_kill): The + kernel returns EINVAL for PID <= 0, work around it. + + * Makefile (tests): Add tst-signal5. + * tst-signal5.c: New file. + + * sysdeps/unix/sysv/linux/bits/local_lim.h: Define TTY_NAME_MAX + and LOGIN_NAME_MAX. + + * tst-cancel1.c (tf): Block all signals. + + * Makefile (tests): Add tst-basic6. + * tst-basic6.c: New file. + + * tst-basic1.c: Add test for process ID. + + * Makefile (tests): Add tst-cancel10. + * tst-cancel10.c: New file. + + * Makefile (tests): Add tst-signal4. + * tst-signal4.c: New file. + + * sysdeps/pthread/pthread_sigmask.c (pthread_sigmask): Use + __sigismember instead of sigismember. Add __builtin_expect. + +2003-02-16 Ulrich Drepper + + * tst-attr1.c (do_test): Add tests for pthread_setcanceltype, + pthread_setcancelstate, and pthread_rwlock_setpshared. + + * tst-cancel7.c (do_test): Make sure the pid file exists before + canceling the thread. + + * tst-rwlock6.c: More pthread_rwlock_timedwrlock and + pthread_rwlock_timedrdlock tests. + * tst-rwlock7.c: More pthread_rwlock_timedwrlock tests. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedrdlock.S: + Check for invalid tv_nsec field. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedwrlock.S: + Likewise. + + * pthread_mutex_trylock.c (__pthread_mutex_trylock): Protect + recursive mutex of overflow. + + * tst-attr1.c (do_test): Add test for pthread_mutexattr_setpshared. + + * libc-cancellation.c (__libc_enable_asynccancel): Rewrite to avoid + going into an endless loop. + * Makefile (tests): Add tst-cancel9. + * tst-cancel9.c: New file. + + * pthread_cancel.c (pthread_cancel): Use the result of __pthread_kill. + +2003-02-15 Ulrich Drepper + + * tst-mutex5.c (do_test): Add more timedlock tests. + + * tst-mutex2.c: Tests of trylock and unlock with ERROR mutexes. + * tst-mutex3.c (do_test): Add tests for trylock with RECURSIVE mutexes. + + * sysdeps/unix/sysv/linux/pthread_kill.c (__pthread_kill): Don't + use INLINE_SYSCALL. Error number is returned, not -1. + + * pthreadP.h: Mark declarations of __find_in_stack_list, __free_tcb, + and __deallocate_stack with internal_function. + * pthread_create.c: Adjust definitions appropriately. + * allocatestack.c: Likewise. + + * pthread_join.c: Add one more __builtin_expect. + * pthread_timedjoin.c: Likewise. + + * pthread_getspecific.c (__pthread_getspecific): Clear data->data + not data of sequence number does not match. + Add one __builtin_expect. + + * Makefile (tests): Add tst-clock1. + * tst-clock1.c: New file. + + * pthread_setconcurrency.c (pthread_setconcurrency): Fail for + negative arguments. + * Makefile (tests): Add tst-basic5. + * tst-basic5.c: New file. + +2003-02-14 Ulrich Drepper + + * Makefile (tests): Add tst-basic4. + * tst-basic4.c: New file. + + * pthreadP.h: Add declaraction for __nptl_nthreads. + * pthread_create.c: Define __nptl_nthreads + (start_thread): Increment __nptl_nthreads at beginning. Decrement + after thread is done. If then zero, call exit(0). + * sysdeps/pthread/pthread-functions.h (struct pthread_functions): + Add ptr_nthreads. Define HAVE_PTR_NTHREADS. + * init.c (pthread_functions): Initialize ptr_nthreads. + * allocatestack.c (nptl_nthreads): Remove definition and all uses. + (__reclaim_stacks): Decrement __nptl_nthreads. + * sysdeps/pthread/Makefile [$(subdir)==csu] (CFLAGS-libc-start.c): + Define. + * Makefile (tests): Add tst-basic3. + * tst-basic3.c: New file. + + * descr.h: Define CANCELING_BIT and CANCELING_BITMASK. Introduce + after CANCELTYPE_BIT, move the other bits up. Update CANCEL_RESTMASK. + * init.c (sigcancel_handler): Also set CANCELING_BITMASK bit in newval. + * pthread_cancel.c (pthread_cancel): Likewise. Also set CANCELING_BIT + if asynchronous canceling is enabled. + * pthread_join.c (pthread_join): When recognizing circular joins, + take into account the other thread might be already canceled. + * Makefile (tests): Add tst-join5. + * tst-join5.c: New file. + + * Makefile (tests): Add tst-join4. + * tst-join4.c: New file. + +2003-02-13 Ulrich Drepper + + * tst-cond4.c (main): Add test of pthread_attr_getpshared. + +2003-02-13 Martin Schwidefsky + + * sysdeps/s390/tls.h (THREAD_GETMEM, THREAD_GETMEM_NC, THREAD_SETMEM, + THREAD_SETMEM_NC): Use passed descr instead of THREAD_SELF. + * sysdeps/unix/sysv/linux/s390/jmp-unwind.c (_longjmp_unwind): Avoid + warning. + * sysdeps/unix/sysv/linux/s390/lowlevellock.c: Include + to avoid warning. + * sysdeps/unix/sysv/linux/s390/sem_post.c (__new_sem_post): Return + error if lll_futex_wake failed. + +2003-02-13 Ulrich Drepper + + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S: Fix + handling of cancellation and failung pthread_mutex_unlock call. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: Likewise. + * Makefile (tests): Add tst-cond8 and tst-cond9. + * tst-cond8.c: New file. + * tst-cond9.c: New file. + + * tst-cond7.c (do_test): Unlock the mutex before canceling the thread. + + * sysdeps/pthread/pthread.h: Add missing initializers. Protect + non-standard initializers with __USE_GNU. + + * Makefile (tests): Add tst-cleanup3. + * tst-cleanup3.c: New file. + +2003-02-12 Ulrich Drepper + + * Makefile (tests): Add tst-attr1 and tst-attr2. + * tst-attr1.c: New file. + * tst-attr2.c: New file. + + * Makefile: Add rules to build and run tst-atfork2 test. + * tst-atfork2.c: New file. + * tst-atfork2mod.c: New file. + + * sysdeps/unix/sysv/linux/unregister-atfork.c + (__unregister_atfork): Free the memory allocated for the handlers + after removing them from the lists. + + * sysdeps/unix/sysv/linux/register-atfork.c: Define memeory + cleanup function. + + * tst-atfork1.c (do_test): Wait for the child we forked. + Report error in child. + + * sysdeps/unix/sysv/linux/fork.c (__libc_fork): Fix comment. + + * sysdeps/pthread/Makefile: Define CFLAGS-confstr.c. + +2003-02-10 Ulrich Drepper + + * Makefile (tests): Add tst-cancel8. + * tst-cancel8.c: New file. + + * sysdeps/unix/sysv/linux/i386/pthread_once.S (clear_once_control): Fix + clearing of control variable. + * Makefile (tests): Add tst-once3 and tst-once4. + * tst-once3.c: New file. + * tst-once4.c: New file. + +2003-02-08 kaz Kojima + + * sysdeps/sh/Makefile: New file. + * sysdeps/sh/bits/atomic.h: New file. + * sysdeps/sh/pthread_spin_init.c: New file. + * sysdeps/sh/pthread_spin_lock.c: New file. + * sysdeps/sh/pthread_spin_trylock.S: New file. + * sysdeps/sh/pthread_spin_unlock.S: New file. + * sysdeps/sh/pthreaddef.h: New file. + * sysdeps/sh/tcb-offsets.sym: New file. + * sysdeps/sh/td_ta_map_lwp2thr.c: New file. + * sysdeps/sh/tls.h: New file. + * sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h: New file. + * sysdeps/unix/sysv/linux/sh/bits/semaphore.h: New file. + * sysdeps/unix/sysv/linux/sh/createthread.c: New file. + * sysdeps/unix/sysv/linux/sh/fork.c: New file. + * sysdeps/unix/sysv/linux/sh/libc-lowlevellock.S: New file. + * sysdeps/unix/sysv/linux/sh/libc-lowlevelmutex.S: New file. + * sysdeps/unix/sysv/linux/sh/lowlevel-atomic.h: New file. + * sysdeps/unix/sysv/linux/sh/lowlevelcond.h: New file. + * sysdeps/unix/sysv/linux/sh/lowlevellock.S: New file. + * sysdeps/unix/sysv/linux/sh/lowlevellock.h: New file. + * sysdeps/unix/sysv/linux/sh/lowlevelmutex.S: New file. + * sysdeps/unix/sysv/linux/sh/lowlevelrwlock.h: New file. + * sysdeps/unix/sysv/linux/sh/pt-initfini.c: New file. + * sysdeps/unix/sysv/linux/sh/pt-vfork.S: New file. + * sysdeps/unix/sysv/linux/sh/pthread_barrier_wait.S: New file. + * sysdeps/unix/sysv/linux/sh/pthread_cond_broadcast.S: New file. + * sysdeps/unix/sysv/linux/sh/pthread_cond_signal.S: New file. + * sysdeps/unix/sysv/linux/sh/pthread_cond_timedwait.S: New file. + * sysdeps/unix/sysv/linux/sh/pthread_cond_wait.S: New file. + * sysdeps/unix/sysv/linux/sh/pthread_once.S: New file. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_rdlock.S: New file. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedrdlock.S: New file. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedwrlock.S: New file. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_unlock.S: New file. + * sysdeps/unix/sysv/linux/sh/pthread_rwlock_wrlock.S: New file. + * sysdeps/unix/sysv/linux/sh/sem_post.S: New file. + * sysdeps/unix/sysv/linux/sh/sem_timedwait.S: New file. + * sysdeps/unix/sysv/linux/sh/sem_trywait.S: New file. + * sysdeps/unix/sysv/linux/sh/sem_wait.S: New file. + * sysdeps/unix/sysv/linux/sh/sysdep-cancel.h: New file. + +2003-02-08 Ulrich Drepper + + * tst-cond2.c: Rearrange code to not rely on behavior undefined + according to POSIX. + + * tst-basic2.c (do_test): Lock mutex before creating the thread. + +2003-02-07 Ulrich Drepper + + * sysdeps/x86_64/tls.h: Remove unnecessary macros, left over from x86. + (TLS_GET_FS): New #define. + (TLS_SET_FS): New #define. + Correct value of __NR_set_thread_area. + + * sysdeps/x86_64/td_ta_map_lwp2thr.c: New file. + +2003-02-06 Ulrich Drepper + + * Makefile (tests): Add tst-popen1. + * tst-popen1.c: New file. + + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S: Remove wrong + but inactive generalization. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_signal.S: Likewise. + Minor optimization, remove one instruction. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.S: Likewise. + +2003-02-04 Martin Schwidefsky + + * sysdeps/unix/sysv/linux/s390/fork.c: Correct order of parameters. + +2003-01-31 Martin Schwidefsky + + * init.c (__NR_set_tid_address): Add #ifdef for s390. + * sysdeps/pthread/pthread_barrier_wait.c: New file. + * sysdeps/pthread/pthread_cond_broadcast.c: New file. + * sysdeps/pthread/pthread_cond_signal.c: New file. + * sysdeps/pthread/pthread_cond_timedwait.c: New file. + * sysdeps/pthread/pthread_cond_wait.c: New file. + * sysdeps/pthread/pthread_rwlock_rdlock.c: New file. + * sysdeps/pthread/pthread_rwlock_timedrdlock.c: New file. + * sysdeps/pthread/pthread_rwlock_timedwrlock.c: New file. + * sysdeps/pthread/pthread_rwlock_unlock.c: New file. + * sysdeps/pthread/pthread_rwlock_wrlock.c: New file. + * sysdeps/s390/Makefile: New file. + * sysdeps/s390/bits/atomic.h: New file. + * sysdeps/s390/pthread_spin_init.c: New file. + * sysdeps/s390/pthread_spin_lock.c: New file. + * sysdeps/s390/pthread_spin_trylock.c: New file. + * sysdeps/s390/pthread_spin_unlock.c: New file. + * sysdeps/s390/pthreaddef.h: New file. + * sysdeps/s390/tcb-offsets.sym: New file. + * sysdeps/s390/td_ta_map_lwp2thr.c: New file. + * sysdeps/s390/tls.h: New file. + * sysdeps/unix/sysv/linux/s390/bits/pthreadtypes.h: New file. + * sysdeps/unix/sysv/linux/s390/bits/semaphore.h: New file. + * sysdeps/unix/sysv/linux/s390/createthread.c: New file. + * sysdeps/unix/sysv/linux/s390/dl-sysdep.h: New file. + * sysdeps/unix/sysv/linux/s390/fork.c: New file. + * sysdeps/unix/sysv/linux/s390/jmp-unwind.c: New file. + * sysdeps/unix/sysv/linux/s390/libc-lowlevellock.c: New file. + * sysdeps/unix/sysv/linux/s390/libc-lowlevelmutex.c: New file. + * sysdeps/unix/sysv/linux/s390/lowlevellock.c: New file. + * sysdeps/unix/sysv/linux/s390/lowlevellock.h: New file. + * sysdeps/unix/sysv/linux/s390/lowlevelmutex.c: New file. + * sysdeps/unix/sysv/linux/s390/lowlevelsem.h: New file. + * sysdeps/unix/sysv/linux/s390/pthread_once.c: New file. + * sysdeps/unix/sysv/linux/s390/s390-32/pt-initfini.c: New file. + * sysdeps/unix/sysv/linux/s390/s390-32/pt-vfork.S: New file. + * sysdeps/unix/sysv/linux/s390/s390-32/sysdep-cancel.h: New file. + * sysdeps/unix/sysv/linux/s390/s390-64/pt-initfini.c: New file. + * sysdeps/unix/sysv/linux/s390/s390-64/pt-vfork.S: New file. + * sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h: New file. + * sysdeps/unix/sysv/linux/s390/sem_post.c: New file. + * sysdeps/unix/sysv/linux/s390/sem_timedwait.c: New file. + * sysdeps/unix/sysv/linux/s390/libc-lowlevellock.c: New file. + * sysdeps/unix/sysv/linux/s390/sem_wait.c: New file. + +2003-02-04 Ulrich Drepper + + * atomic.h: Add a couple more default implementations. + (atomic_compare_and_exchange_acq): Use + __arch_compare_and_exchange_32_acq in return value definition. It + always exists. + (atomic_bit_set): Renamed from atomic_set_bit. + Add missing atomic_ prefixes. + + * sysdeps/pthread/bits/libc-lock.h (__libc_once): In case no + thread library is available, use correct value to mark initialized + once variable. + +2003-02-03 Ulrich Drepper + + * allocatestack.c (allocate_stack): Use __getpagesize instead of + __sysconf to determine pagesize. + + * pthread_create.c: Include . + * allocatestack.c (allocate_stack): Implement coloring of the + allocated stack memory. Rename pagesize to pagesize_m1. It's the + size minus one. Adjust users. + * sysdeps/i386/i686/Makefile: New file. + +2003-02-02 Ulrich Drepper + + * allocatestack.c: Improve comment throughout the file. + + * sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S + (__lll_lock_wait): Add branch prediction. + * sysdeps/unix/sysv/linux/i386/i486/libc-lowlevellock.S + (__lll_lock_wait): Likewise. + (lll_unlock_wake_cb): Removed. + +2003-01-31 Ulrich Drepper + + * sysdeps/unix/sysv/linux/bits/posix_opt.h: Remove + _POSIX_THREAD_PRIORITY_SCHEDULING. + +2003-01-30 Jakub Jelinek + + * sysdeps/pthread/pthread-functions.h (struct pthread_functions): + Fix return type of ptr___pthread_getspecific. + +2003-01-29 Ulrich Drepper + + * Makefile (tests): Add tst-umask1. + (tst-umask1-ARGS): Define. + * tst-umask1.c: New file. + +2003-01-28 Ulrich Drepper + + * Makefile (libpthread-routines): Remove lowlevelrwlock. Add + pthread_rwlock_rdlock, pthread_rwlock_timedrdlock, + pthread_rwlock_wrlock, pthread_rwlock_timedwrlock, and + pthread_rwlock_unlock. + * sysdeps/unix/sysv/linux/i386/i486/lowlevelrwlock.S: Removed + * sysdeps/unix/sysv/linux/i386/i586/lowlevelrwlock.S: Removed + * sysdeps/unix/sysv/linux/i386/i686/lowlevelrwlock.S: Removed + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_rdlock.S: New file. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedrdlock.S: + New file. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_wrlock.S: New file. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedwrlock.S: + New file. + * sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_unlock.S: New file. + * sysdeps/unix/sysv/linux/i386/i586/pthread_rwlock_rdlock.S: New file. + * sysdeps/unix/sysv/linux/i386/i586/pthread_rwlock_timedrdlock.S: + New file. + * sysdeps/unix/sysv/linux/i386/i586/pthread_rwlock_wrlock.S: New file. + * sysdeps/unix/sysv/linux/i386/i586/pthread_rwlock_timedwrlock.S: + New file. + * sysdeps/unix/sysv/linux/i386/i586/pthread_rwlock_unlock.S: New file. + * sysdeps/unix/sysv/linux/i386/i686/pthread_rwlock_rdlock.S: New file. + * sysdeps/unix/sysv/linux/i386/i686/pthread_rwlock_timedrdlock.S: + New file. + * sysdeps/unix/sysv/linux/i386/i686/pthread_rwlock_wrlock.S: New file. + * sysdeps/unix/sysv/linux/i386/i686/pthread_rwlock_timedwrlock.S: + New file. + * sysdeps/unix/sysv/linux/i386/i686/pthread_rwlock_unlock.S: New file. + + * Makefile (libpthread-routines): Remove lowlevelcond and + lowlevelsem. Add sem_wait, sem_trywait, sem_timedwait, sem_post, + pthread_cond_wait, pthread_cond_timedwait, pthread_cond_signal, + and pthread_cond_broadcast. + * sysdeps/unix/sysv/linux/i386/i486/lowlevelsem.S: Removed + * sysdeps/unix/sysv/linux/i386/i486/lowlevelcond.S: Removed + * sysdeps/unix/sysv/linux/i386/i586/lowlevelsem.S: Removed + * sysdeps/unix/sysv/linux/i386/i586/lowlevelcond.S: Removed + * sysdeps/unix/sysv/linux/i386/i686/lowlevelsem.S: Removed + * sysdeps/unix/sysv/linux/i386/i686/lowlevelcond.S: Removed + * sysdeps/unix/sysv/linux/i386/i486/sem_wait.S: New file. + * sysdeps/unix/sysv/linux/i386/i486/sem_trywait.S: New file. + * sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S: New file. + * sysdeps/unix/sysv/linux/i386/i486/sem_post.S: New file. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S: New file. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S: New file. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_signal.S: New file. + * sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.S: New file. + * sysdeps/unix/sysv/linux/i386/i586/sem_wait.S: New file. + * sysdeps/unix/sysv/linux/i386/i586/sem_trywait.S: New file. + * sysdeps/unix/sysv/linux/i386/i586/sem_timedwait.S: New file. + * sysdeps/unix/sysv/linux/i386/i586/sem_post.S: New file. + * sysdeps/unix/sysv/linux/i386/i586/pthread_cond_wait.S: New file. + * sysdeps/unix/sysv/linux/i386/i586/pthread_cond_timedwait.S: New file. + * sysdeps/unix/sysv/linux/i386/i586/pthread_cond_signal.S: New file. + * sysdeps/unix/sysv/linux/i386/i586/pthread_cond_broadcast.S: New file. + * sysdeps/unix/sysv/linux/i386/i686/sem_wait.S: New file. + * sysdeps/unix/sysv/linux/i386/i686/sem_trywait.S: New file. + * sysdeps/unix/sysv/linux/i386/i686/sem_timedwait.S: New file. + * sysdeps/unix/sysv/linux/i386/i686/sem_post.S: New file. + * sysdeps/unix/sysv/linux/i386/i686/pthread_cond_wait.S: New file. + * sysdeps/unix/sysv/linux/i386/i686/pthread_cond_timedwait.S: New file. + * sysdeps/unix/sysv/linux/i386/i686/pthread_cond_signal.S: New file. + * sysdeps/unix/sysv/linux/i386/i686/pthread_cond_broadcast.S: New file. + * sysdeps/unix/sysv/linux/i386/lowlevelcond.h: New file. + + * sysdeps/unix/sysv/linux/i386/createthread.c: Define + PREPARE_CREATE and TLS_VALUE with x86-specific bits. All the rest + of the code is moved to ... + * sysdeps/pthread/createthread.c: ...here. New file. + +2003-01-27 Ulrich Drepper + + * sysdeps/unix/sysv/linux/i386/i486/lowlevelsem.S + (__new_sem_post): Clear %eax before returning. + Reported by MAEDA Naoaki . + + * Makefile (tests): Add tst-cleanup2. + * tst-cleanup2.c: New file. + + * sysdeps/pthread/bits/libc-lock.h (__libc_cleanup_region_start): + Interpret first parameter correctly. + +2003-01-17 Ulrich Drepper + + * Makefile (headers): Add bits/semaphore.h. + +2003-01-16 Jakub Jelinek + + * sysdeps/i386/tls.h (INIT_SYSINFO): Initialize _head->sysinfo even + if not SHARED. + +2003-01-14 Ulrich Drepper + + * sem_open.c (sem_open): Return SEM_FAILED if existing semaphore + must be used and mapping failed. + Reported by Luke Elliott . + + * Makefile (CFLAGS-pthread_self.os): Define this, not + CFLAGS-pthread_self.c. + +2003-01-13 Ulrich Drepper + + * sysdeps/unix/sysv/linux/i386/i486/libc-lowlevellock.S: Don't export + lll_unlock_wake_cb. + + * Makefile (libpthread-routines): Add version. Add rules to build + version.os and banner.h. + * version.c: New file. + +2003-01-13 Jakub Jelinek + + * pthread_mutex_lock.c (__pthread_mutex_lock_internal): Make + the alias unconditional. + * pthread_mutex_unlock.c (__pthread_mutex_unlock_internal): Likewise. + +2003-01-13 Ulrich Drepper + + * Makefile (CFLAGS-pthread_self.c): New definition. + +2003-01-06 Jakub Jelinek + + * sysdeps/pthread/pthread_sigmask.c (pthread_sigmask): Add + INTERNAL_SYSCALL_DECL, add err argument to INTERNAL_SYSCALL* macros. + * sysdeps/unix/sysv/linux/raise.c (raise): Likewise. + * init.c (__pthread_initialize_minimal_internal): Likewise. + +2003-01-07 Jakub Jelinek + + * pthreadP.h (__pthread_cond_timedwait): Add prototype. + + * sysdeps/unix/sysv/linux/i386/dl-sysdep.h + (RTLD_CORRECT_DYNAMIC_WEAK): Remove. + (DL_SYSINFO_IMPLEMENTATION): Change into .text section and back. + * sysdeps/unix/sysv/linux/i386/i686/dl-sysdep.h + (RTLD_CORRECT_DYNAMIC_WEAK): Remove. + (DL_SYSINFO_IMPLEMENTATION): Change into .text section and back. + +2003-01-06 Jakub Jelinek + + * pthreadP.h (LIBC_CANCEL_HANDLED): Define. + * pt-system.c (LIBC_CANCEL_HANDLED): Add. + * tst-cancel-wrappers.sh: Remove all exceptions. + +2003-01-05 Ulrich Drepper + + * tst-cancel-wrappers.sh: Invoke gawk not awk since we use GNU awk + features. Reported by Marijn Ros . + + * sysdeps/unix/sysv/linux/jmp-unwind.c: Include . + Use __libc_pthread_functions array if SHARED. + + * pthreadP.h: Move pthread_cond_2_0_t definition to... + * sysdeps/unix/sysv/linux/internaltypes.h: ...here. + + * sysdeps/pthread/bits/libc-lock.h (__libc_ptf_call): New #define. + (__libc_rwlock_rdlock, __libc_rwlock_wrlock, __libc_rwlock_unlock, + __libc_key_create, __libc_getspecific, __libc_setspecific): Use + __libc_ptf_call instead of __libc_maybe_call. + (PTF): New #define. + (__libc_cleanup_region_start): Wrap function name with PTF call. + (__libc_cleanup_region_end): Likewise. + (__libc_cleanup_end): Likewise. + + * pthread_getspecific.c: Add __pthread_getspecific_internal alias. + * pthread_setspecific.c: Add __pthread_setspecific_internal alias. + * pthread_key_create.c: Add __pthread_key_create_internal alias. + * pthreadP.h: Add prototypes. + + * sysdeps/unix/sysv/linux/i386/i486/lowlevelrwlock.S: Add + __pthread_rwlock_rdlock, __pthread_rwlock_wrlock, and + __pthread_rwlock_unlock aliases. + * pthreadP.h: Add prototypes for new aliases. + + * pthreadP.h (struct pthead_functions): Moved to... + * sysdeps/pthread/pthread-functions.h: ...here. New file. + * init.c (pthread_functions): Add initializers for new elements. + + * cleanup_defer.c: Add __pthread_cleanup_push_defer and + __pthread_cleanup_pop_restore aliases. + * pthreadP.h: Add prototypes. + + * cleanup.c: Rename _GI_pthread_cleanup_push to __pthread_cleanup_push + and _GI_pthread_cleanup_pop to __pthread_cleanup_pop. + * sysdeps/unix/sysv/linux/i386/i486/lowlevelcond.S: Adjust caller. + * sysdeps/unix/sysv/linux/i386/pthread_once.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/pthread_once.S: Likewise. + * pthreadP.h: Adjust prototypes and callers. + +2003-01-04 Ulrich Drepper + + * Makefile (tests): Add tst-cancel7. + (tst-cancel7-ARGS): New variable. + * tst-cancel7.c: New file. + + * old_pthread_cond_broadcast.c: Optimize initialization a bit to work + around gcc defficiencies. + * old_pthread_cond_signal.c: Likewise. + * old_pthread_cond_timedwait.c: Likewise. + * old_pthread_cond_wait.c: Likewise. + + * pthreadP.h (pthread_cond_2_0_t): Remove unneeded lock element. + +2003-01-03 Ulrich Drepper + + * Makefile (tests): Add tst-cond7. + * tst-cond7.c: New file. + + * sysdeps/unix/sysv/linux/i386/i486/lowlevelcond.S + (condvar_cleanup): Get condvar address from the right place. + + * atomic.h: Correct definitions of atomic_full_barrier, + atomic_read_barrier, atomic_write_barrier. + + * old_pthread_cond_broadcast.c: Make memory allocate and initialization + race-free. + * old_pthread_cond_signal.c: Likewise. + * old_pthread_cond_timedwait.c: Likewise. + * old_pthread_cond_wait.c: Likewise. + +2003-01-03 Jakub Jelinek + + * Makefile ($(objpfx)libpthread.so): Depend on ld.so. + +2003-01-03 Ulrich Drepper + + * pthreadP.h (pthread_cond_2_0_t): New type. + (struct pthread_functions): Use new type for 2.0 condvar callbacks. + Use new type for the 2.0 condvar function prototypes. + * forward.c: Use pthread_cond_2_0_t for 2.0 condvar functions. + * old_pthread_cond_init.c: Use pthread_cond_2_0_t for condvar + parameter. + * old_pthread_cond_destroy.c: Likewise. + * old_pthread_cond_broadcast.c: Likewise. Lock appropriately. + * old_pthread_cond_signal.c: Likewise. + * old_pthread_cond_timedwait.c: Likewise. + * old_pthread_cond_wait.c: Likewise. + + * sysdeps/unix/sysv/linux/i386/i486/lowlevelcond.S + (__pthread_cond_wait): Don't save cancellation mode and seq value + in same location. + + * herrno.c (__h_errno_location): Don't define as weak. + +2003-01-02 Jakub Jelinek + + * Versions [libc] (GLIBC_2.3.2): Export pthread_cond_broadcast, + pthread_cond_destroy, pthread_cond_init, pthread_cond_signal + and pthread_cond_wait. + * old_pthread_cond_broadcast.c (__old_pthread_cond_broadcast): + Renamed to... + (__pthread_cond_broadcast_2_0): ... this. + * old_pthread_cond_destroy.c (__old_pthread_cond_destroy): + Renamed to... + (__pthread_cond_destroy_2_0): ... this. + * old_pthread_cond_init.c (__old_pthread_cond_init): + Renamed to... + (__pthread_cond_init_2_0): ... this. + * old_pthread_cond_signal.c (__old_pthread_cond_signal): + Renamed to... + (__pthread_cond_signal_2_0): ... this. + * old_pthread_cond_wait.c (__old_pthread_cond_wait): + Renamed to... + (__pthread_cond_wait_2_0): ... this. + * pthread_cond_destroy.c: Include shlib-compat.h. + (pthread_cond_destroy): Change strong_alias into versioned_symbol. + * pthread_cond_init.c: Include shlib-compat.h. + (pthread_cond_init): Change strong_alias into versioned_symbol. + * pthreadP.h (struct pthread_functions): Rename ptr_pthread_cond_* + fields to ptr___pthread_cond_* and add ptr___pthread_cond_*_2_0 + fields. + (__pthread_cond_broadcast_2_0, __pthread_cond_destroy_2_0, + __pthread_cond_init_2_0, __pthread_cond_signal_2_0, + __pthread_cond_wait_2_0): New prototypes. + (__old_pthread_cond_broadcast, __old_pthread_cond_destroy, + __old_pthread_cond_init, __old_pthread_cond_signal, + __old_pthread_cond_wait): Removed. + * init.c: Include shlib-compat.h. + (pthread_functions): Guard ptr___pthread_attr_init_2_0 + initialization with SHLIB_COMPAT (GLIBC_2_0, GLIBC_2_1). + Rename ptr_pthread_cond_* to ptr___pthread_cond_*, initialize + ptr___pthread_cond_*_2_0 fields. + * forward.c: Export both pthread_cond_*@@GLIBC_2.3.2 and + pthread_cond_*@GLIBC_2.0 compatibility symbols. + + * sysdeps/pthread/sigaction.c (SIGCANCEL): Only define if + LIBC_SIGACTION was not yet defined. + [!defined LIBC_SIGACTION]: Define LIBC_SIGACTION, #include self. + [!defined LIBC_SIGACTION] (__sigaction): New function and + libc_hidden_weak. + [!defined LIBC_SIGACTION] (sigaction): New weak_alias. + [defined LIBC_SIGACTION]: #include_next . + +2003-01-02 Jakub Jelinek + + * Makefile (CFLAGS-pthread_atfork.c): Add -DNOT_IN_libc. + +2003-01-02 Ulrich Drepper + + * sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h (pthread_cond_t): + New, larger type definition. + * sysdeps/unix/sysv/linux/i386/i486/lowlevelcond.S: New condvar + implementation. + * Versions [libpthread]: Add definitions for new pthread_cond_* + interfaces for version GLIBC_2.3.2. + * pthread_cond_init.c: Update initialization for new type definition. + * Makefile (libpthread-routines): Remove pthread_cond_wait, + pthread_cond_timedwait, pthread_cond_signal, and + pthread_cond_broadcast. Add old_pthread_cond_init, + old_pthread_cond_destroy, old_pthread_cond_wait, + old_pthread_cond_timedwait, old_pthread_cond_signal, and + old_pthread_cond_broadcast. + * old_pthread_cond_broadcast.c: New file. + * old_pthread_cond_destroy.c: New file. + * old_pthread_cond_init.c: New file. + * old_pthread_cond_signal.c: New file. + * old_pthread_cond_timedwait.c: New file. + * old_pthread_cond_wait.c: New file. + * pthreadP.h: Add prototypes for the compatibility interfaces. + + * pthread_cond_destroy.c: Don't include . + +2003-01-01 Ulrich Drepper + + * sysdeps/unix/sysv/linux/i386/i486/lowlevelrwlock.S: Avoid + unnecessary zero offset when addressing MUTEX. + +2002-12-31 Ulrich Drepper + + * sysdeps/unix/sysv/linux/fork.h: Add libc_hidden_proto for + __register_atfork. + * sysdeps/unix/sysv/linux/register-atfork.c: Add libc_hidden_def + for __register_atfork. + +2002-12-31 Jakub Jelinek + + * sysdeps/unix/sysv/linux/i386/sysdep-cancel.h: Use __ASSEMBLER__ + instead of ASSEMBLER test macro. + + * sysdeps/unix/sysv/linux/allocrtsig.c (__libc_current_sigrtmin, + __libc_current_sigrtmax): Add libc_hidden_def. + + * sysdeps/pthread/list.h: Remove assert.h include. + +2002-12-31 Ulrich Drepper + + * sysdeps/pthread/pt-initfini.c (call_initialize_minimal): Use + __pthread_initialize_minimal_internal not + __pthread_initialize_minimal. + +2002-12-30 Ulrich Drepper + + * sysdeps/pthread/pt-initfini.c (call_initialize_minimal): Mark + __pthread_initialize_minimal as hidden. + + * init.c (__pthread_initialize_minimal_internal): Don't mark as + constructor. + +2002-12-31 Jakub Jelinek + + * Makefile ($(inst_libdir)/libpthread.so): Depend on + $(common-objpfx)format.lds, include that into the output script. + Fix comment. + (extra-B-pthread.so): Change linuxthreads/ into nptl/. + +2002-12-28 Andreas Jaeger + + * sysdeps/unix/sysv/linux/xstatconv.c (xstat_conv): Adjust for + nsec resolution changes. + (xstat64_conv): Likewise. + (xstat32_conv): Likewise. + * sysdeps/unix/sysv/linux/kernel_stat.h: Add nsec resolution for + struct kernel_stat. + * sysdeps/unix/sysv/linux/bits/stat.h: Add nsec resolution for + structs stat and stat64. + * time/time.h (__timespec_defined): Define for __USE_MISC. + * io/sys/stat.h [__USE_MISC]: Define __need_timespec for struct stat. + +2002-12-30 Jakub Jelinek + + * forward.c (FORWARD2): Renamed from FORWARD3. Remove unused export + argument. + (pthread_attr_init_2_0, pthread_attr_init_2_1): Use FORWARD macro. + (pthread_exit): Use strong_alias to avoid warnings. + * pthreadP.h (struct pthread_functions): Rename ptr_pthread_exit + and ptr_pthread_attr_init_2_* to ptr___pthread_exit and + ptr___pthread_attr_init_2_*. + * init.c (pthread_functions): Adjust. + +2002-12-29 Ulrich Drepper + + * forward.c: Make all functions available by default again. It + caused too much trouble. + + * pt-siglongjmp.c: Removed. + +2002-12-28 Jakub Jelinek + + * sysdeps/i386/tls.h: Include tcb-offsets.h in assembler. + (SYSINFO_OFFSET, MULTIPLE_THREADS_OFFSET): Remove. + * sysdeps/i386/Makefile: New file. + * sysdeps/i386/tcb-offsets.sym: New file. + * sysdeps/pthread/tcb-offsets.h: New file. + * sysdeps/unix/sysv/linux/libc_pthread_init.c (__libc_pthread_init): + Remove MULTIPLE_THREADS_OFFSET and SYSINFO_OFFSET checks. + + * sysdeps/unix/sysv/linux/Versions [libc] (GLIBC_PRIVATE): Move + __register_atfork... + (GLIBC_2.3.2): ...here. + +2002-12-28 Ulrich Drepper + + * sysdeps/pthread/pthread.h: Mark pthread_attr_getstackaddr and + pthread_attr_setstackaddr with __attribute_deprecated__. + +2002-12-27 Jakub Jelinek + + * pt-system.c (system): Remove cancellation handling. + * tst-cancel-wrappers.sh: Allow pt-system.o* to not use the + cancellation routines. + +2002-12-28 Ulrich Drepper + + * descr.h: Include . + (struct pthread): Move header.data.list to the back of the struct. + * sysdeps/i386/tls.h (tcbhead_t): Move list to the back of the struct. + (MULTIPLE_THREADS_OFFSET): Adjust offset. + (SYSINFO_OFFSEET): Likewise. + +2002-12-27 Jakub Jelinek + + * sysdeps/unix/sysv/linux/i386/i686/dl-sysdep.h (USE_DL_SYSINFO): + Define. + (DL_SYSINFO_DEFAULT): Cast to uintptr_t to avoid warnings. + * sysdeps/unix/sysv/linux/i386/dl-sysdep.h (NEED_DL_SYSINFO, + DL_SYSINFO_DEFAULT, DL_SYSINFO_IMPLEMENTATION): Define. + (USE_DL_SYSINFO): Undef. + +2002-12-22 Jakub Jelinek + + * Makefile (tests-reverse): Use $(objpfx)../libc.so instead of + $(common-objpfx)libc.so. + * tst-cancel4.c (tf_write, tf_writev): Increase buf sizes so that + it is bigger than pipe buffer size even on arches with bigger + page size. + (tf_usleep): Cast usleep argument to useconds_t to avoid warnings. + +2002-12-25 Ulrich Drepper + + * sysdeps/unix/sysv/linux/i386/i486/lowlevelsem.S: Implement + correct errno access for case that USE___THREAD is not defined. + +2002-12-24 Ulrich Drepper + + * sysdeps/unix/sysv/linux/i386/dl-sysdep.h: Add missing #endif. + Patch by Marijn Ros . + +2002-12-22 Roland McGrath + + * Makefile (omit-deps): Add $(unix-syscalls:%=ptw-%). + +2002-12-20 Ulrich Drepper + + * sysdeps/pthread/bits/stdio-lock.h (_IO_lock_inexpensive): Define. + +2002-12-19 Ulrich Drepper + + * sysdeps/unix/sysv/linux/i386/dl-sysdep.h: Don't define + NEED_DL_SYSINFO since no processor < i686 had the sysenter opcode. + * sysdeps/unix/sysv/linux/i386/i686/dl-sysdep.h: New file. + + * sysdeps/unix/sysv/linux/i386/pthread_once.S: Use ENTER_KERNEL instead + of int $0x80. + * sysdeps/unix/sysv/linux/i386/i486/libc-lowlevellock.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/libc-lowlevelmutex.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/lowlevelcond.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/lowlevelmutex.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/lowlevelrwlock.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/lowlevelsem.S: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/pthread_barrier_wait.S: Likewise. + + * sysdeps/unix/sysv/linux/i386/lowlevellock.h: Add support for using + sysenter. + * sysdeps/unix/sysv/linux/i386/lowlevelsem.h: Likewise. + + * sysdeps/i386/tls.h: Unconditionally include . + + * allocatestack.c (allocate_stack) [NEED_DL_SYSINFO]: Set sysinfo + in new TCB. + * sysdeps/unix/sysv/linux/i386/createthread.c (create_thread): Check + that sysinfo is properly initialized. + * sysdeps/unix/sysv/linux/i386/dl-sysdep.h: Define RTLD_PRIVATE_ERRNO + to 1 only for ld.so. + + * sysdeps/unix/sysv/linux/i386/dl-sysdep.h: Define + RTLD_CORRECT_DYNAMIC_WEAK. + +2002-12-19 Jakub Jelinek + + * forward.c (pthread_attr_init_2_0, pthread_attr_init_2_1): + Use return 0 as 6th argument to FORWARD4. + * pthread_equal.c: Include pthreadP.h instead of pthread.h. + +2002-12-18 Ulrich Drepper + + * descr.h (struct pthread) [NEED_DL_SYSINFO]: Add sysinfo member. + * sysdeps/i386/tls.h (tcbhead_t): Add sysinfo member. + Define SYSINFO_OFFSEET if NEED_DL_SYSINFO is defined. + (INIT_SYSINFO): New #define. + (TLS_TP_INIT): Use INIT_SYSINFO. + * sysdeps/unix/sysv/linux/libc_pthread_init.c (__libc_pthread_init): + At test to make sure SYSINFO_OFFSET value is correct. + * sysdeps/unix/sysv/linux/i386/dl-sysdep.h: New file. + +2002-12-18 Jakub Jelinek + + * sysdeps/pthread/flockfile.c (flockfile): Change into weak alias. + * sysdeps/unix/sysv/linux/raise.c (gsignal): Add weak alias to raise. + * Versions [libc: GLIBC_2.0]: Add pthread_attr_init. + [libpthread: GLIBC_2.1]: Remove __pthread_rwlock_init, + __pthread_rwlock_destroy, __pthread_rwlock_rdlock, + __pthread_rwlock_wrlock, __pthread_rwlock_unlock, + __pthread_rwlock_tryrdlock and __pthread_rwlock_trywrlock. + +2002-12-18 Ulrich Drepper + + * sysdeps/unix/sysv/linux/i386/sysdep-cancel.h: Use ENTER_KERNEL + macro instead of using int $0x80 directly. + + * sysdeps/pthread/bits/stdio-lock.h: New file. + * sysdeps/unix/sysv/linux/i386/i486/libc-lowlevelmutex.S: New file. + * sysdeps/unix/sysv/linux/i386/i586/libc-lowlevelmutex.S: New file. + * sysdeps/unix/sysv/linux/i386/i686/libc-lowlevelmutex.S: New file. + * Makefile (routines): Add libc-lowlevelmutex. + + * sysdeps/unix/sysv/linux/i386/i486/libc-lowlevellock.S: Remove + __i686.get_pc_thunk.dx. + +2002-12-17 Jakub Jelinek + + * Makefile (libpthread-shared-only-routines): Add pt-allocrtsig. + (tests): Depend on $(objpfx)tst-cancel-wrappers.out. + ($(objpfx)tst-cancel-wrappers.out): New rule. + * tst-cancel-wrappers.sh: New test. + * tst-locale1.c: Include signal.h. + (uselocale): Test static linking of __libc_current_sigrt*. + +2002-12-17 Ulrich Drepper + + * Makefile (tests): Add tst-cancel6. + * tst-cancel6.c: New file + +2002-12-17 Jakub Jelinek + + * sysdeps/unix/sysv/linux/i386/sysdep-cancel.h (SINGLE_THREAD_P): + Define meaningfully for assembler as well. + * pthreadP.h (struct pthread_functions): Remove + ptr_pthread_attr_init field. Add ptr_pthread_attr_init_2_0 + and ptr_pthread_attr_init_2_1 fields. + * init.c (pthread_functions): Initialize ptr_pthread_attr_init_2_0 + and ptr_pthread_attr_init_2_1 instead of ptr_pthread_attr_init. + * forward.c (FORWARD4): Renamed from FORWARD3. Add export argument. + (FORWARD3): Define using FORWARD4. + (pthread_attr_init): Provide both @GLIBC_2.0 and @@GLIBC_2.1 + versions. + * pt-system.c: Remove duplicate stdlib.h include. + +2002-12-16 Ulrich Drepper + + * sem_init.c: Define sem_init@GLIBC_2.0. + * sem_destroy.c: Define sem_destroy@GLIBC_2.0. + * sem_getvalue.c: Define sem_getvalue@GLIBC_2.0. + + * flockfile.c: Moved to... + * sysdeps/pthread/flockfile.c: ...here. New file. + * funlockfile.c: Moved to... + * sysdeps/pthread/funlockfile.c: ...here. New file. + * ftrylockfile.c: Moved to... + * sysdeps/pthread/ftrylockfile.c: ...here. New file. + +2002-12-16 Jakub Jelinek + + * libc-cancellation.c: Guard both function with + #if !defined NOT_IN_libc. + * Makefile (libpthread-routines): Use ptw-, not pt- prefix for the + automatically provided pthread wrappers. + * pthreadP.h (LIBC_CANCEL_ASYNC, LIBC_CANCEL_RESET): Define to + CANCEL_* if IS_IN_libpthread and to dummy versions if not in libc + nor in libpthread. + * pt-open.c: Removed. + * pt-fcntl.c: Removed. + * pt-fsync.c: Removed. + * pt-lseek.c: Removed. + * pt-msgrcv.c: Removed. + * pt-msgsnd.c: Removed. + * pt-msync.c: Removed. + * pt-nanosleep.c: Removed. + * pt-open64.c: Removed. + * pt-pause.c: Removed. + * pt-pread.c: Removed. + * pt-pread64.c: Removed. + * pt-pwrite.c: Removed. + * pt-pwrite64.c: Removed. + * pt-read.c: Removed. + * pt-recv.c: Removed. + * pt-recvfrom.c: Removed. + * pt-recvmsg.c: Removed. + * pt-send.c: Removed. + * pt-sendto.c: Removed. + * pt-sigtimedwait.c: Removed. + * pt-sigwait.c: Removed. + * pt-wait.c: Removed. + * pt-waitpid.c: Removed. + * pt-write.c: Removed. + * pt-accept.c: Removed. + * pt-close.c: Removed. + * pt-connect.c: Removed. + * pt-lseek64.c: Removed. + * pt-sendmsg.c: Removed. + * pt-tcdrain.c: Removed. + +2002-12-15 Ulrich Drepper + + * init.c (__pthread_initialize_minimal_internal): Renamed from + __pthread_initialize_minimal. Make old name an alias. This + converts a normal relocation into a relative relocation. + + * pt-fcntl.c (__fcntl): Use fcntl64 syscall, not fcntl. + + * Versions [libpthread: GLIBC_2.3.2]: Remove creat, poll, pselect, + readv, select, sigpause, sigsuspend, sigwaitinfo, waitid, writev. + * Makefile (libpthread-routines): Remove pt-creat, pt-poll, + pt-pselect, pt-readv, pt-select, pt-sigpause, pt-sigsuspend, + pt-sigwaitinfo, pt-waitid, and pt-writev. + * pt-creat.c: Removed. + * pt-poll.c: Removed. + * pt-pselect.c: Removed. + * pt-readv.c: Removed. + * pt-select.c: Removed. + * pt-sigpause.c: Removed. + * pt-sigsuspend.c: Removed. + * pt-sigwaitinfo.c: Removed. + * pt-waitid.c: Removed. + * pt-writev.c: Removed. + + * init.c (pthread_functions): New variable. + (__pthread_initialize_minimal): Pass pointer to pthread_functions + (or NULL) to __libc_pthread_init. + * forward.c: Rewrite to use __libc:pthread_functions array to get + function addresses. + * sysdeps/unix/sysv/linux/fork.h: Remove __libc_pthread_init + prototype. + * sysdeps/unix/sysv/linux/libc_pthread_init.c (__libc_pthread_init): + Take new parameter. Copy content of variable pointed to by it + to __libc_pthread_init. + + * pthreadP.h (struct pthread_functions): New type. + (__libc_pthread_init): Declare. + + * pthread_attr_destroy.c: Add namespace protected alias. + * pthread_attr_getdetachstate.c: Likewise. + * pthread_attr_getinheritsched.c: Likewise. + * pthread_attr_getschedparam.c: Likewise. + * pthread_attr_getschedpolicy.c: Likewise. + * pthread_attr_getscope.c: Likewise. + * pthread_attr_setdetachstate.c: Likewise. + * pthread_attr_setinheritsched.c: Likewise. + * pthread_attr_setschedparam.c: Likewise. + * pthread_attr_setschedpolicy.c: Likewise. + * pthread_attr_setscope.c: Likewise. + * pthread_cond_broadcast.c: Likewise. + * pthread_cond_destroy.c: Likewise. + * pthread_cond_init.c: Likewise. + * pthread_cond_signal.c: Likewise. + * pthread_cond_wait.c: Likewise. + * pthread_condattr_destroy.c: Likewise. + * pthread_condattr_init.c: Likewise. + * pthread_equal.c: Likewise. + * pthread_exit.c: Likewise. + * pthread_getschedparam.c: Likewise. + * pthread_self.c: Likewise. + * pthread_setcancelstate.c: Likewise. + * pthread_setschedparam.c: Likewise. + * pthread_mutex_destroy.c: Likewise. + * pthread_mutex_init.c: Likewise. + * pthreadP.h: Add prototypes for the aliases. + + * sysdeps/unix/sysv/linux/i386/createthread.c (create_thread): Set + multiple_threads member in correct TCB to 1. + + * sysdeps/unix/sysv/linux/i386/sysdep-cancel.h: Define + SINGLE_THREAD_P. If in libc or libpthread examine multiple_thread + member of thread decriptor, otherwise return unconditionally 1. + +2002-12-14 Ulrich Drepper + + * sysdeps/unix/sysv/linux/i386/pt-socket.S: Changes folded into the + regular Linux version. Remove file. + * sysdeps/unix/sysv/linux/connect.S: Likewise. Remove file. + * sysdeps/unix/sysv/linux/llseek.c: Likewise. Remove file. + * sysdeps/unix/sysv/linux/msgrcv.c: Likewise. Remove file. + * sysdeps/unix/sysv/linux/msgsnd.c: Likewise. Remove file. + * sysdeps/unix/sysv/linux/open64.c: Likewise. Remove file. + * sysdeps/unix/sysv/linux/poll.c: Likewise. Remove file. + * sysdeps/unix/sysv/linux/pread.c: Likewise. Remove file. + * sysdeps/unix/sysv/linux/pread64.c: Likewise. Remove file. + * sysdeps/unix/sysv/linux/pselect.c: Likewise. Remove file. + * sysdeps/unix/sysv/linux/pwrite.c: Likewise. Remove file. + * sysdeps/unix/sysv/linux/pwrite64.c: Likewise. Remove file. + * sysdeps/unix/sysv/linux/readv.c: Likewise. Remove file. + * sysdeps/unix/sysv/linux/recv.S: Likewise. Remove file. + * sysdeps/unix/sysv/linux/recvfrom.S: Likewise. Remove file. + * sysdeps/unix/sysv/linux/recvmsg.S: Likewise. Remove file. + * sysdeps/unix/sysv/linux/send.S: Likewise. Remove file. + * sysdeps/unix/sysv/linux/sendmsg.S: Likewise. Remove file. + * sysdeps/unix/sysv/linux/sendto.S: Likewise. Remove file. + * sysdeps/unix/sysv/linux/sigpause.c: Likewise. Remove file. + * sysdeps/unix/sysv/linux/sigsuspend.c: Likewise. Remove file. + * sysdeps/unix/sysv/linux/sigtimedwait.c: Likewise. Remove file. + * sysdeps/unix/sysv/linux/sigwait.c: Likewise. Remove file. + * sysdeps/unix/sysv/linux/sigwaitinfo.c: Likewise. Remove file. + * sysdeps/unix/sysv/linux/system.c: Likewise. Remove file. + * sysdeps/unix/sysv/linux/tcdrain.c: Likewise. Remove file. + * sysdeps/unix/sysv/linux/wait.c: Likewise. Remove file. + * sysdeps/unix/sysv/linux/waitid.c: Likewise. Remove file. + * sysdeps/unix/sysv/linux/waitpid.c: Likewise. Remove file. + * sysdeps/unix/sysv/linux/writev.c: Likewise. Remove file. + * sysdeps/unix/sysv/linux/i386/fcntl.c: Likewise. Remove file. + +2002-12-14 Jakub Jelinek + + * sysdeps/unix/sysv/linux/i386/sysdep-cancel.h: New file. + * sysdeps/unix/sysv/linux/open.c: Removed. + * sysdeps/unix/sysv/linux/fsync.c: Removed. + * sysdeps/unix/sysv/linux/lseek.c: Removed. + * sysdeps/unix/sysv/linux/msync.c: Removed. + * sysdeps/unix/sysv/linux/read.c: Removed. + * sysdeps/unix/sysv/linux/close.c: Removed. + * sysdeps/unix/sysv/linux/creat.c: Removed. + * sysdeps/unix/sysv/linux/nanosleep.c: Removed. + * sysdeps/unix/sysv/linux/pause.c: Removed. + * sysdeps/unix/sysv/linux/select.c: Removed. + * sysdeps/unix/sysv/linux/write.c: Removed. + +2002-12-14 Ulrich Drepper + + * sysdeps/unix/sysv/linux/i386/pt-socket.S: Check multiple_threads + element in TCB to see whether locking is needed. + + * sysdeps/unix/sysv/linux/libc_pthread_init.c: Check that + MULTIPLE_THREADS_OFFSET value is correct. + + * sysdeps/unix/sysv/linux/close.c: New file. + * sysdeps/unix/sysv/linux/connect.S: New file. + * sysdeps/unix/sysv/linux/creat.c: New file. + * sysdeps/unix/sysv/linux/fsync.c: New file. + * sysdeps/unix/sysv/linux/llseek.c: New file. + * sysdeps/unix/sysv/linux/lseek.c: New file. + * sysdeps/unix/sysv/linux/msgrcv.c: New file. + * sysdeps/unix/sysv/linux/msgsnd.c: New file. + * sysdeps/unix/sysv/linux/msync.c: New file. + * sysdeps/unix/sysv/linux/nanosleep.c: New file. + * sysdeps/unix/sysv/linux/open.c: New file. + * sysdeps/unix/sysv/linux/open64.c: New file. + * sysdeps/unix/sysv/linux/pause.c: New file. + * sysdeps/unix/sysv/linux/poll.c: New file. + * sysdeps/unix/sysv/linux/pread.c: New file. + * sysdeps/unix/sysv/linux/pread64.c: New file. + * sysdeps/unix/sysv/linux/pselect.c: New file. + * sysdeps/unix/sysv/linux/pwrite.c: New file. + * sysdeps/unix/sysv/linux/pwrite64.c: New file. + * sysdeps/unix/sysv/linux/readv.c: New file. + * sysdeps/unix/sysv/linux/recv.S: New file. + * sysdeps/unix/sysv/linux/recvfrom.S: New file. + * sysdeps/unix/sysv/linux/recvmsg.S: New file. + * sysdeps/unix/sysv/linux/select.c: New file. + * sysdeps/unix/sysv/linux/send.S: New file. + * sysdeps/unix/sysv/linux/sendmsg.S: New file. + * sysdeps/unix/sysv/linux/sendto.S: New file. + * sysdeps/unix/sysv/linux/sigpause.c: New file. + * sysdeps/unix/sysv/linux/sigsuspend.c: New file. + * sysdeps/unix/sysv/linux/sigtimedwait.c: New file. + * sysdeps/unix/sysv/linux/sigwait.c: New file. + * sysdeps/unix/sysv/linux/sigwaitinfo.c: New file. + * sysdeps/unix/sysv/linux/system.c: New file. + * sysdeps/unix/sysv/linux/tcdrain.c: New file. + * sysdeps/unix/sysv/linux/wait.c: New file. + * sysdeps/unix/sysv/linux/waitid.c: New file. + * sysdeps/unix/sysv/linux/waitpid.c: New file. + * sysdeps/unix/sysv/linux/writev.c: New file. + * sysdeps/unix/sysv/linux/i386/fcntl.c: New file. + + * pt-readv.c: Fix comment. + +2002-12-14 Jakub Jelinek + + * tst-cleanup1.c: Include stdlib.h. + + * tst-cancel5.c: New test. + * Makefile (tests): Add tst-cancel5. + (tst-cancel5): Link against libc.so libpthread.so in that order. + +2002-12-13 Ulrich Drepper + + * forward.c (test_loaded): Prevent recursive calls. + + * Makefile (routines): Add libc-cancellation. + * libc-cancellation.c: New file. + * descr.h (struct pthread): Add multiple_threads field. + * allocatestack.c (allocate_stack): Initialize multiple_header field of + new thread descriptor to 1. + * sysdeps/unix/sysv/linux/i386/createthread.c (create_thread): + Initialize multiple_thread field after successful thread creation. + * cancellation.c (__do_cancel): Move to pthreadP.h. + (__pthread_enable_asynccancel): Remove parameter from __do_cancel call. + (__pthread_disable_asynccancel): Add internal_function attribute. + * init.c (sigcancel_handler): Remove parameter from __do_cancel call. + * pthread_setcancelstate.c: Likewise. + * pthread_setcanceltype.c: Likewise. + * pthread_exit.c: Likewise. + * pthreadP.h (CANCELLATION_P): Likewise. + (__do_cancel): Define as static inline. + (LIBC_CANCEL_ASYNC, LIBC_CANCEL_RESET): New #defines. + (__libc_enable_asynccancel, __libc_disable_asynccancel): New + declarations. + * sysdeps/i386/tls.h (tcbhead_t): Add list and multiple_threads + fields. Define MULTIPLE_THREADS_OFFSET. + * sysdeps/pthread/bits/libc-lock.h: Remove __libc_locking_needed + declaration. + * sysdeps/unix/sysv/linux/accept.S: New file. + * sysdeps/unix/sysv/linux/read.c: New file. + * sysdeps/unix/sysv/linux/write.c: New file. + * sysdeps/unix/sysv/linux/i386/pt-socket.S: New file. + * sysdeps/unix/sysv/linux/libc_pthread_init.c: Remove definition and + initialization of __libc_locking_needed. + * sysdeps/unix/sysv/linux/i386/lowlevellock.h: Don't use + __libc_locking_needed, use multiple_threads field in TCB. + * sysdeps/unix/sysv/linux/i386/i486/libc-lowlevellock.S: Likewise. + +2002-12-12 Ulrich Drepper + + * sysdeps/unix/sysv/linux/i386/i686/libc-lowlevellock.S: Use i486 + version. + * sysdeps/unix/sysv/linux/i386/i586/libc-lowlevellock.S: Likewise. + + * sysdeps/unix/sysv/linux/i386/i486/libc-lowlevellock.S: Correct + access to __libc_locking_needed for PIC. + +2002-12-12 Jakub Jelinek + + * sysdeps/pthread/bits/libc-lock.h (__libc_locking_needed): Only + declare for libc.so. + (__libc_lock_init, __libc_lock_init_recursive): Change into comma + expression. + (__libc_lock_lock): Put into statement expression. + (__libc_lock_unlock): Remove trailing semicolon. + * sysdeps/unix/sysv/linux/fork.h (__libc_pthread_init): Fix typo. + +2002-12-12 Roland McGrath + + * sysdeps/unix/sysv/linux/i386/lowlevellock.h: Use asm operand with + "m" constraint to refer to __libc_locking_needed. Declare it here. + +2002-12-12 Ulrich Drepper + + * sysdeps/unix/sysv/linux/fork-gen.c: Renamed to... + * sysdeps/unix/sysv/linux/libc_pthread_init.c: ...this. + Initialize __libc_locking_needed. + * init.c (__pthread_initialize_minimal): Call __libc_pthread_init + instead of __register_pthread_fork_handler. + * sysdeps/pthread/bits/libc-lock.h: Declare __libc_locking_needed. + * sysdeps/unix/sysv/linux/Makefile (sysdep_routimes): Replace + fork-gen with libc_pthread_init. + * sysdeps/unix/sysv/linux/Versions: Use __libc_pthread_init instead + of __register_pthread_fork_handler. + * sysdeps/unix/sysv/linux/fork.h: Declare __libc_pthread_init instead + of __register_pthread_fork_handler. + * sysdeps/unix/sysv/linux/i386/lowlevellock.h: Use + __libc_locking_needed to determine whether lock prefix can be avoided. + * sysdeps/unix/sysv/linux/i386/i486/libc-lowlevellock.S: Likewise. + +2002-12-11 Ulrich Drepper + + * Makefile (tests): Add tst-cleanup1. + * tst-cleanup1.c: New file. + * cancellation.c (__cleanup_thread): Removed. + (__do_cancel): Remove call to __cleanup_thread. + * pthreadP.h: Remove __cleanup_thread prorotype. + + * sysdeps/pthread/bits/libc-lock.h (__libc_cleanup_region_start): + Remember function and argument even if cancellation handler + function is not available. + (__libc_cleanup_region_end): Execute registered function directly if + pthread functions are not available. + (__libc_cleanup_end): Likewise. + + * init.c (__pthread_initialize_minimal): Fix initialization in + static lib by preventing gcc from being too clever. + +2002-12-10 Ulrich Drepper + + * init.c (__pthread_initialize_minimal): Remove unneccesary + sigaddset call. + + * Makefile (tests): We can run tst-locale2 now. + +2002-12-09 Ulrich Drepper + + * Versions: Remove duplicated sigwait entry. + +2002-12-08 Ulrich Drepper + + * pthreadP.h: Enable pthread_cleanup_{push,pop} optimizations only + inside libpthread. + + * pt-fcntl.c (__fcntl): Initialize oldtype to avoid warning. + + * pthreadP.h: Declare __pthread_enable_asynccancel and + __pthread_disable_asynccancel. + (CANCEL_ASYNC): Use __pthread_enable_asynccancel. + (CANCEL_RESET): Use __pthread_disable_asynccancel. + * cancellation.c (__pthread_enable_asynccancel): New function. + (__pthread_disable_asynccancel): New function. + * pt-accept.c: Adjust for CANCEL_ASYNC and CANCEL_RESET change. + * pt-close.c: Likewise. + * pt-connect.c: Likewise. + * pt-creat.c: Likewise. + * pt-fcntl.c: Likewise. + * pt-fsync.c: Likewise. + * pt-lseek.c: Likewise. + * pt-lseek64.c: Likewise. + * pt-msgrcv.c: Likewise. + * pt-msgsnd.c: Likewise. + * pt-msync.c: Likewise. + * pt-nanosleep.c: Likewise. + * pt-open.c: Likewise. + * pt-open64.c: Likewise. + * pt-pause.c: Likewise. + * pt-poll.c: Likewise. + * pt-pread.c: Likewise. + * pt-pread64.c: Likewise. + * pt-pselect.c: Likewise. + * pt-pwrite.c: Likewise. + * pt-pwrite64.c: Likewise. + * pt-read.c: Likewise. + * pt-readv.c: Likewise. + * pt-recv.c: Likewise. + * pt-recvfrom.c: Likewise. + * pt-recvmsg.c: Likewise. + * pt-select.c: Likewise. + * pt-send.c: Likewise. + * pt-sendmsg.c: Likewise. + * pt-sendto.c: Likewise. + * pt-sigpause.c: Likewise. + * pt-sigsuspend.c: Likewise. + * pt-sigtimedwait.c: Likewise. + * pt-sigwait.c: Likewise. + * pt-sigwaitinfo.c: Likewise. + * pt-system.c: Likewise. + * pt-tcdrain.c: Likewise. + * pt-wait.c: Likewise. + * pt-waitid.c: Likewise. + * pt-waitpid.c: Likewise. + * pt-write.c: Likewise. + * pt-writev.c: Likewise. + * pthread_join.c: Likewise. + * pthread_timedjoin.c: Likewise. + + * pt-sigpause.c (sigsuspend): Call __sigsuspend. + (__xpg_sigpause): New function. + * Versions (libpthread:GLIBC_2.3.2): Add __xpg_sigpause. + +2002-12-07 Ulrich Drepper + + * Makefile (CFLAGS-ftrylockfile.c): Add -D_IO_MTSAFE_IO. + + * cleanup.c: Move declarations of _GI_pthread_cleanup_push and + _GI_pthread_cleanup_pop to pthreadP.h. + + * ftrylockfile.c: Use _IO_lock_trylock instead of + pthread_mutex_trylock. + + * pthreadP.h (CANCEL_ASYNC): Use __pthread_setcanceltype. + (CANCEL_RESET): Likewise. + (__pthread_setcanceltype_): Declare. + (__pthread_mutex_lock_internal): Declare. + (__pthread_mutex_unlock_internal): Declare. + (__pthread_once_internal): Declare. + (pthread_cleanup_push): Redefine using _GI_pthread_cleanup_push. + (pthread_cleanup_pop): Redefine using _GI_pthread_cleanup_pop. + + * pthread_cond_timedwait.c: Use INTUSE is calls to pthread_mutex_lock + and pthread_mutex_unlock. + * pthread_cond_wait.c: Likewise. + * pthread_mutex_lock.c: Use INTDEF to define alias if needed. + * pthread_mutex_unlock.c: Likewise. + + * pthread_setcanceltype.c: Add additional alias + __pthread_setcanceltype. + + * sem_unlink.c (sem_unlink): Use __pthread_once with INTDEF. + * sem_open.c (sem_open): Likewise. + Use __libc_open, __libc_write, and __libc_close instead of + open, write, and close respectively. + + * sysdeps/pthread/bits/libc-lock.h (__libc_lock_trylock_internal): + Rewrite as statement expression since it must return a value. + + * pthread_cancel.c: Use __pthread_kill instead of pthread_kill. + * sysdeps/unix/sysv/linux/pthread_kill.c: Define additional alias + __pthread_kill. + + * sysdeps/unix/sysv/linux/i386/pthread_once.S: Define additional + alias __pthread_once_internal. + + * sysdeps/unix/sysv/linux/raise.c: Use libc_hidden_def for raise. + +2002-12-06 Ulrich Drepper + + * Makefile (tests): Add tst-stdio1 and tst-stdio2. + * tst-stdio1.c: New file. + * tst-stdio2.c: New file. + + * init.c (__pthread_initialize_minimal): Correct INIT_LIST_HEAD use. + + * Makefile (tests): Comment out tst-locale2 for now. + (CFLAGS-flockfile.c, CFLAGS-funlockfile.c): Define to -D_IO_MTSAFE_IO. + + * sysdeps/unix/sysv/linux/Makefile: Define CFLAGS-fork.c to + -D_IO_MTSAFE_IO. + * sysdeps/unix/sysv/linux/fork.c: Include . + Use _IO_lock_init instead of explicit assignment. + + * sysdeps/pthread/bits/libc-lock.h: Define __rtld_lock_* macros. + Define __libc_lock_* and __libc_lock_recursive macros with + lowlevellock macros, not pthread mutexes. + + * flockfile.c: Include . Use _IO_lock_lock instead + of pthread_mutex_lock. + * funlockfile.c: Include . Use _IO_lock_unlock + instead of pthread_mutex_unlock. + +2002-12-06 Roland McGrath + + * allocatestack.c (__stack_user): Use uninitialized defn. + * init.c (__pthread_initialize_minimal): Initialize it here. + +2002-12-05 Roland McGrath + + * sysdeps/i386/tls.h (TLS_INIT_TP): Make it return zero or an error + string. + * sysdeps/x86_64/tls.h (TLS_INIT_TP): Likewise. + + * sysdeps/unix/sysv/linux/i386/createthread.c (create_thread): Add + missing & here too. + +2002-12-05 Ulrich Drepper + + * sysdeps/unix/sysv/linux/Makefile (sysdep_routines): Remove + lowlevellock. + * sysdeps/unix/sysv/linux/i386/i486/libc-lowlevellock.S: New file. + * sysdeps/unix/sysv/linux/i386/i586/libc-lowlevellock.S: New file. + * sysdeps/unix/sysv/linux/i386/i686/libc-lowlevellock.S: New file. + * sysdeps/pthread/bits/libc-lock.h: Use lowlevellock implementation + for __libc_lock_* macros. + * Makefile (routines): Add libc-lowlevellock. + +2002-10-09 Roland McGrath + + * sysdeps/pthread/bits/libc-lock.h (__libc_maybe_call): New macro. + Under [__PIC__], call the function via the pointer fetched for + comparison rather than a call by name that uses the PLT. + (__libc_lock_init, __libc_rwlock_init, __libc_lock_fini) + (__libc_rwlock_fini, __libc_lock_lock, __libc_rwlock_rdlock) + (__libc_rwlock_wrlock, __libc_lock_trylock, __libc_rwlock_tryrdlock) + (__libc_rwlock_trywrlock, __libc_lock_unlock, __libc_rwlock_unlock) + (__libc_key_create, __libc_getspecific, __libc_setspecific): Use it. + +2002-12-04 Roland McGrath + + * forward.c (pthread_self): Use FORWARD3 macro to correct return type. + + * sysdeps/i386/td_ta_map_lwp2thr.c: Moved from ../nptl_db. + * sysdeps/generic/td_ta_map_lwp2thr.c: New file. + + * pthread_create.c (start_thread): Add missing & on __nptl_last_event. + +2002-12-04 Ulrich Drepper + + * sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h: Make pthread_t + a completely opaque, non-integer type. + * sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h: Likewise. + +2002-12-05 Jakub Jelinek + + * sysdeps/i386/tls.h: Include stdlib.h. + * sysdeps/x86_64/tls.h: Likewise. + +2002-12-04 Ulrich Drepper + + * Makefile (tests): Add tst-locale2. + (tests-static): Likewise. + * tst-locale2.c: New file. + + * sysdeps/unix/sysv/linux/i386/lowlevellock.h: Mark asms as + volatile and add memory clobbers to lock operations. + +2002-12-03 Ulrich Drepper + + * sysdeps/i386/i686/bits/atomic.h: Use i486 version. + * sysdeps/i386/i486/bits/atomic.h: New file. + * sysdeps/i386/i586/bits/atomic.h: New file. + * sysdeps/i386/i686/pthread_spin_trylock.S: Define HAVE_CMOV and + include i486 version. + * sysdeps/i386/i486/pthread_spin_trylock.S: New file. + * sysdeps/i386/i586/pthread_spin_trylock.S: New file. + Patch by Marijn Ros . + + * allocatestack.c (get_cached_stack): Don't crash if we first + found a stack with a larger size then needed. + Reported by Hui Huang . + + * Makefile (tests): Add tst-sysconf. + * tst-sysconf.c: New file. + + * sysdeps/unix/sysv/linux/bits/local_lim.h: Undefine + PTHREAD_THREADS_MAX. + +2002-12-02 Roland McGrath + + * pthreadP.h (__stack_user, __nptl_create_event, __nptl_death_event): + Declare using hidden_proto instead of attribute_hidden, so there are + non-.hidden static symbols for gdb to find. + (__pthread_keys): Likewise. + * events.c (__nptl_create_event, __nptl_death_event): Add hidden_def. + * allocatestack.c (__stack_user): Likewise. + * pthread_create.c (__pthread_keys): Likewise. + (__nptl_threads_events, __nptl_last_event): Make these static instead + of hidden. + * pthread_key_create.c (__pthread_pthread_keys_max, + __pthread_pthread_key_2ndlevel_size): Renamed from __linuxthreads_*. + +2002-12-02 Ulrich Drepper + + * Makefile (tests): Add tst-locale1. If buid-static is yes link + statically. + * tst-locale1.c: New file. + + * pthread_cond_timedwait.c: Include . + + * Makefile (tests): Add tst-fork2 and tst-fork3. + * tst-fork2.c: New file. + * tst-fork3.c: New file. + +2002-11-28 Ulrich Drepper + + * sysdeps/unix/sysv/linux/i386/bits/posix_opt.h: New file. + + * sysdeps/unix/sysv/linux/bits/posix_opt.h: Define macros which + require it to 200112L. + + * sysdeps/unix/sysv/linux/i386/i486/lowlevelrwlock.S: Use cmov + instruction only if HAVE_CMOV is defined. + * sysdeps/unix/sysv/linux/i386/i686/lowlevelrwlock.S: Define HAVE_CMOV. + + * sysdeps/unix/sysv/linux/x86_64/bits/semaphore.h: New file. + + * sysdeps/unix/sysv/linux/x86_64/pthread_once.S: New file. + + * sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h: New file. + + * sysdeps/unix/sysv/linux/x86_64/pt-vfork.S: New file. + +2002-11-27 Ulrich Drepper + + * sysdeps/x86_64/bits/atomic.h: New file. + + * sysdeps/i386/i686/bits/atomic.h: Fix asm syntax for 8- and + 16-bit operations. + + * sysdeps/unix/sysv/linux/raise.c (raise): Use INTERNAL_SYSCALL if + possible since gettid cannot fail. + + * sysdeps/x86_64/pthreaddef.h: New file. + + * sysdeps/i386/pthreaddef.h (gettid): Removed. + + * sysdeps/x86_64/pthread_spin_init.c: New file. + * sysdeps/x86_64/pthread_spin_lock.c: New file. + * sysdeps/x86_64/pthread_spin_trylock.c: New file. + * sysdeps/x86_64/pthread_spin_unlock.c: New file. + + * sysdeps/i386/i686/pthread_spin_trylock.S (pthread_spin_trylock): + Add missing lock prefix. Minute optimization. + + * tst-spin2.c (main): Also check successful trylock call. + + * sysdeps/pthread/pthread_sigmask.c (pthread_sigmask): Use correct + syscall. Fix typo in case INTERNAL_SYSCALL is not used. + + * sysdeps/i386/pthread_spin_destroy.c: Moved to... + * sysdeps/pthread/pthread_spin_destroy.c: ...here. New file. + + * sysdeps/i386/pthread_sigmask.c: Removed. Use the generic code. + * sysdeps/pthread/pthread_sigmask.c (pthread_sigmask): Return correct + value in case of an error. Add support for INTERNAL_SYSCALL. + + * sysdeps/i386/pthread_sigmask.c (pthread_sigmask): Return correct + value in case of an error. + + * sysdeps/x86_64/tls.h: New file. + +2002-11-26 Ulrich Drepper + + * sysdeps/i386/tls.h (THREAD_GETMEM_NC): Change interface. It now + takes the array member name and the index as parameters. + (THREAD_SETMEM_NC): Likewise. + * pthread_getspecific.c: Use new THREAD_GETMEM_NC interface. + * pthread_setspecific.c: Use new THREAD_GETMEM_NC and THREAD_SETMEM_NC + interfaces. + + * sysdeps/i386/tls.h (THREAD_SETMEM): Use size of member element + to decide which code to use. + (THREAD_SETMEM_NC): Likewise. + + * allocatestack.c (queue_stack): Don't remove stack from list here. + Do it in the caller. Correct condition to prematurely terminate + loop to free stacks. + (__deallocate_stack): Remove stack from list here. + +2002-11-26 Ulrich Drepper + + * Makefile (tests): Add tst-stack1. + * tst-stack1.c: New file. + + * allocatestack.c (allocate_stack): Initialize the TCB on a user + provided stack. + + * pthread_attr_getstack.c: Return bottom of the thread area. + +2002-11-25 Ulrich Drepper + + * Makefile (libpthread-routines): Add pt-allocrtsig and + pthread_kill_other_threads. + * pt-allocrtsig.c: New file. + * pthread_kill_other_threads.c: New file. + * sysdeps/unix/sysv/linux/allocrtsig.c: Add additional aliases for + all three functions. + * sysdeps/unix/sysv/linux/Makefile (sysdep_routines): Remove + allocrtsig. + * sysdeps/unix/sysv/linux/Versions (libc:GLIBC_PRIVATE): Export + __libc_current_sigrtmin_private, __libc_current_sigrtmax_private, + and __libc_allocate_rtsig_private. + * Versions (libpthread): Export pthread_kill_other_threads_np, + __libc_current_sigrtmin, and __libc_current_sigrtmax. + +2002-11-24 Ulrich Drepper + + * allocatestack.c (allocate_stack): stackaddr in attribute points to + the end of the stack. Adjust computations. + When mprotect call fails dequeue stack and free it. + * pthread_attr_setstack.c: Store top of the stack in stackaddr + attribute. + * pthread_getattr_np.c: Likewise. + + * descr.h (IS_DETACHED): Add some more parenthesis to prevent + surprises. + +2002-11-23 Ulrich Drepper + + * sysdeps/pthread/pthread.h (pthread_self): __THROW must come before + attribute definitions. Patch by Luca Barbieri . + +2002-11-22 Ulrich Drepper + + * pthread_getspecific.c: Optimize access to first 2nd-level array. + * pthread_setspecific.c: Likewise. + +2002-11-21 Ulrich Drepper + + * sysdeps/unix/sysv/linux/i386/createthread.c: Remove CLONE_ flags + definitions. Get them from the official place. + * sysdeps/unix/sysv/linux/i386/fork.c: Likewise. + + * sysdeps/unix/sysv/linux/i386/createthread.c: Update CLONE_* flags. + Use new CLONE_ flags in clone() calls. + + * sysdeps/unix/sysv/linux/fork.c: Use ARCH_FORK to actually fork. + * sysdeps/unix/sysv/linux/i386/fork.c: New file. + + * Versions: Add pthread_* functions for libc. + * forward.c: New file. + + * sysdeps/pthread/Makefile (libpthread-sysdeps_routines): Add + errno-loc. + * herrno.c: New file. + * res.c: New file. + + * Makefile (libpthread-routines): Remove sem_post, sem_wait, + sem_trywait, and sem_timedwait. Add herrno and res. + * sem_init.c: Don't initialize lock and waiters members. + * sem_open.c: Likewise. + * sem_post.c: Removed. + * sem_wait.c: Removed. + * sem_trywait.c: Removed. + * sem_timedwait.c: Removed. + * sysdeps/unix/sysv/linux/i386/i486/lowlevelsem.S: Complete rewrite. + Includes full implementations of sem_post, sem_wait, sem_trywait, + and sem_timedwait. + * sysdeps/unix/sysv/linux/i386/lowlevelsem.h (lll_sem_post): Adjust + for new implementation. + * sysdeps/unix/sysv/linux/internaltypes.h (struct sem): Remove lock + and waiters fields. + + * tst-sem3.c: Improve error message. + * tst-signal3.c: Likewise. + + * init.c (__pthread_initialize_minimal): Use set_tid_address syscall + to tell the kernel about the termination futex and to initialize tid + member. Don't initialize main_thread. + * descr.h (struct pthread): Remove main_thread member. + * cancelllation.c (__do_cancel): Remove code handling main thread. + The main thread is not special anymore. + + * allocatestack.c (__reclaim_stacks): Mark stacks as unused. Add + size of the stacks to stack_cache_actsize. + + * pt-readv.c: Add missing "defined". + * pt-sigwait.c: Likewise. + * pt-writev.c: Likewise. + +2002-11-09 Ulrich Drepper + + * Versions: Export __connect from libpthread. + Patch by Luca Barbieri . + + * Makefile (libpthread-routines): Add pt-raise. + * sysdeps/unix/sysv/linux/raise.c: New file. + * sysdeps/unix/sysv/linux/pt-raise.c: New file. + * sysdeps/generic/pt-raise.c: New file. + + * pthread_cond_init.c: Initialize all data elements of the condvar + structure. Patch by Luca Barbieri . + + * pthread_attr_init.c: Actually implement 2.0 compatibility version. + * pthread_create.c: Likewise. + + * Makefile (tests): Add tst-key1, tst-key2, tst-key3. + * tst-key1.c: New file. + * tst-key2.c: New file. + * tst-key3.c: New file. + + * Versions: Export pthread_detach for version GLIBC_2.0. + Reported by Saurabh Desai . + +2002-11-08 Ulrich Drepper + + * pthread_key_create.c: Terminate search after an unused key was found. + Patch by Luca Barbieri . + + * sysdeps/unix/sysv/linux/i386/pthread_once.S: Return zero. + Patch by Luca Barbieri . + +2002-10-10 Ulrich Drepper + + * sysdeps/unix/sysv/linux/i386/i486/lowlevelsem.S: Use slow generic + dynamic lookup for errno in PIC. + + * allocatestack.c (get_cached_stack): Rearrange code slightly to + release the stack lock as soon as possible. + Call _dl_allocate_tls_init for TCB from the cache to re-initialize + the static TLS block. + (allocate_stack): Call _dl_allocate_tls_init for user-provided stack. + + * cancellation.c: Renamed from cancelation.c. + * Makefile: Adjust accordingly. + * pthreadP.h (CANCELLATION_P): Renamed from CANCELATION_P. + * cleanup_defer.c: Use CANCELLATION_P. + * pthread_testcancel.c: Likewise. + * descr.h: Fix spelling in comments. + * init.c: Likewise. + * pthread_getattr_np.c: Likewise. + * pthread_getschedparam.c: Likewise. + * pthread_setschedparam.c: Likewise. + * Versions: Likewise. + + * pt-pselect.c: New file. + * Makefile (libpthread-routines): Add pt-pselect. + * Versions: Add pselect. + + * tst-cancel4.c: New file. + * Makefile (tests): Add tst-cancel4. + +2002-10-09 Ulrich Drepper + + * pthread_mutex_lock.c: Always record lock ownership. + * pthread_mutex_timedlock.c: Likewise. + * pthread_mutex_trylock.c: Likewise. + + * pt-readv.c: New file. + * pt-writev.c: New file. + * pt-creat.c: New file. + * pt-msgrcv.c: New file. + * pt-msgsnd.c: New file. + * pt-poll.c: New file. + * pt-select.c: New file. + * pt-sigpause.c: New file. + * pt-sigsuspend.c: New file. + * pt-sigwait.c: New file. + * pt-sigwaitinfo.c: New file. + * pt-waitid.c: New file. + * Makefile (libpthread-routines): Add pt-readv, pt-writev, pt-creat, + pt-msgrcv, pt-msgsnd, pt-poll, pt-select, pt-sigpause, pt-sigsuspend, + pt-sigwait, pt-sigwaitinfo, and pt-waitid. + * Versions: Add all the new functions. + + * tst-exit1.c: New file. + * Makefile (tests): Add tst-exit1. + + * sem_timedwait.c: Minor optimization for more optimal fastpath. + +2002-10-08 Ulrich Drepper + + * pt-fcntl.c: Only enable asynchronous cancellation for F_SETLKW. + + * pthread_join.c: Enable asynchronous cancellation around lll_wait_tid + call. pthread_join is an official cancellation point. + * pthread_timedjoin.c: Likewise. + + * pthread_cond_wait.c: Revert order in which internal lock are dropped + and the condvar's mutex are retrieved. + * pthread_cond_timedwait.c: Likewise. + Reported by dice@saros.East.Sun.COM. + +2002-10-07 Ulrich Drepper + + * pthreadP.h: Cut out all type definitions and move them... + * sysdeps/unix/sysv/linux/internaltypes.h: ...here. New file. + * pthreadP.h: Include . + + * sysdeps/unix/sysv/linux/i386/lowlevelsem.h (lll_sem_post): Little + performance tweaks. + + * sem_trywait.c: Shuffle #includes around to get right order. + * sem_timedwait.c: Likewise. + * sem_post.c: Likewise. + * sem_wait.c: Likewise. + + * nptl 0.3 released. + + * Makefile (tests): Add tst-signal3. + * tst-signal3.c: New file. + +2002-10-05 Ulrich Drepper + + * sysdeps/unix/sysv/linux/i386/lowlevelsem.h: Tell the compiler that + the asms modify the sem object. + (__lll_sem_timedwait): Now takes struct sem* as first parameter. + + * sysdeps/unix/sysv/linux/i386/bits/semaphore.h (sem_t): Don't expose + the actual members. + * pthreadP.h (struct sem): New type. Actual semaphore type. + * semaphoreP.h: Include pthreadP.h. + * sem_getvalue.c: Adjust to sem_t change. + * sem_init.c: Likewise. + * sem_open.c: Likewise. + * sem_post.c: Likewise. + * sem_timedwait.c: Likewise. + * sem_trywait.c: Likewise. + * sem_wait.c: Likewise. + +2002-10-04 Ulrich Drepper + + * Makefile (tests): Add tst-basic2, tst-exec1, tst-exec3, tst-exec3. + * tst-basic2.c: New file. + * tst-exec1.c: New file. + * tst-exec2.c: New file. + * tst-exec3.c: New file. + + * tst-fork1.c: Remove extra */. + + * nptl 0.2 released. The API for IA-32 is complete. diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/DESIGN-barrier.txt b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/DESIGN-barrier.txt new file mode 100644 index 00000000..23463c6b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/DESIGN-barrier.txt @@ -0,0 +1,44 @@ +Barriers pseudocode +=================== + + int pthread_barrier_wait(barrier_t *barrier); + +struct barrier_t { + + unsigned int lock: + - internal mutex + + unsigned int left; + - current barrier count, # of threads still needed. + + unsigned int init_count; + - number of threads needed for the barrier to continue. + + unsigned int curr_event; + - generation count +} + +pthread_barrier_wait(barrier_t *barrier) +{ + unsigned int event; + result = 0; + + lll_lock(barrier->lock); + if (!--barrier->left) { + barrier->curr_event++; + futex_wake(&barrier->curr_event, INT_MAX) + + result = BARRIER_SERIAL_THREAD; + } else { + event = barrier->curr_event; + lll_unlock(barrier->lock); + do { + futex_wait(&barrier->curr_event, event) + } while (event == barrier->curr_event); + } + + if (atomic_increment_val (barrier->left) == barrier->init_count) + lll_unlock(barrier->lock); + + return result; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/DESIGN-condvar.txt b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/DESIGN-condvar.txt new file mode 100644 index 00000000..4845251c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/DESIGN-condvar.txt @@ -0,0 +1,134 @@ +Conditional Variable pseudocode. +================================ + + int pthread_cond_timedwait (pthread_cond_t *cv, pthread_mutex_t *mutex); + int pthread_cond_signal (pthread_cond_t *cv); + int pthread_cond_broadcast (pthread_cond_t *cv); + +struct pthread_cond_t { + + unsigned int cond_lock; + + internal mutex + + uint64_t total_seq; + + Total number of threads using the conditional variable. + + uint64_t wakeup_seq; + + sequence number for next wakeup. + + uint64_t woken_seq; + + sequence number of last woken thread. + + uint32_t broadcast_seq; + +} + + +struct cv_data { + + pthread_cond_t *cv; + + uint32_t bc_seq + +} + + + +cleanup_handler(cv_data) +{ + cv = cv_data->cv; + lll_lock(cv->lock); + + if (cv_data->bc_seq == cv->broadcast_seq) { + ++cv->wakeup_seq; + ++cv->woken_seq; + } + + /* make sure no signal gets lost. */ + FUTEX_WAKE(cv->wakeup_seq, ALL); + + lll_unlock(cv->lock); +} + + +cond_timedwait(cv, mutex, timeout): +{ + lll_lock(cv->lock); + mutex_unlock(mutex); + + cleanup_push + + ++cv->total_seq; + val = seq = cv->wakeup_seq; + cv_data.bc = cv->broadcast_seq; + cv_data.cv = cv; + + while (1) { + + lll_unlock(cv->lock); + + enable_async(&cv_data); + + ret = FUTEX_WAIT(cv->wakeup_seq, val, timeout); + + restore_async + + lll_lock(cv->lock); + + if (bc != cv->broadcast_seq) + goto bc_out; + + val = cv->wakeup_seq; + + if (val != seq && cv->woken_seq != val) { + ret = 0; + break; + } + + if (ret == TIMEDOUT) { + ++cv->wakeup_seq; + break; + } + } + + ++cv->woken_seq; + + bc_out: + lll_unlock(cv->lock); + + cleanup_pop + + mutex_lock(mutex); + + return ret; +} + +cond_signal(cv) +{ + lll_lock(cv->lock); + + if (cv->total_seq > cv->wakeup_seq) { + ++cv->wakeup_seq; + FUTEX_WAKE(cv->wakeup_seq, 1); + } + + lll_unlock(cv->lock); +} + +cond_broadcast(cv) +{ + lll_lock(cv->lock); + + if (cv->total_seq > cv->wakeup_seq) { + cv->wakeup_seq = cv->total_seq; + cv->woken_seq = cv->total_seq; + ++cv->broadcast_seq; + FUTEX_WAKE(cv->wakeup_seq, ALL); + } + + lll_unlock(cv->lock); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/DESIGN-rwlock.txt b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/DESIGN-rwlock.txt new file mode 100644 index 00000000..810d1b8f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/DESIGN-rwlock.txt @@ -0,0 +1,113 @@ +Reader Writer Locks pseudocode +============================== + + pthread_rwlock_rdlock(pthread_rwlock_t *rwlock); + pthread_rwlock_unlock(pthread_rwlock_t *rwlock); + pthread_rwlock_wrlock(pthread_rwlock_t *rwlock); + +struct pthread_rwlock_t { + + unsigned int lock: + - internal mutex + + unsigned int writers_preferred; + - locking mode: 0 recursive, readers preferred + 1 nonrecursive, writers preferred + + unsigned int readers; + - number of read-only references various threads have + + pthread_t writer; + - descriptor of the writer or 0 + + unsigned int readers_wakeup; + - 'all readers should wake up' futex. + + unsigned int writer_wakeup; + - 'one writer should wake up' futex. + + unsigned int nr_readers_queued; + - number of readers queued up. + + unsigned int nr_writers_queued; + - number of writers queued up. +} + +pthread_rwlock_rdlock(pthread_rwlock_t *rwlock) +{ + lll_lock(rwlock->lock); + for (;;) { + if (!rwlock->writer && (!rwlock->nr_writers_queued || + !rwlock->writers_preferred)) + break; + + rwlock->nr_readers_queued++; + val = rwlock->readers_wakeup; + lll_unlock(rwlock->lock); + + futex_wait(&rwlock->readers_wakeup, val) + + lll_lock(rwlock->lock); + rwlock->nr_readers_queued--; + } + rwlock->readers++; + lll_unlock(rwlock->lock); +} + +pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock) +{ + int result = EBUSY; + lll_lock(rwlock->lock); + if (!rwlock->writer && (!rwlock->nr_writers_queued || + !rwlock->writers_preferred)) + rwlock->readers++; + lll_unlock(rwlock->lock); + return result; +} + +pthread_rwlock_wrlock(pthread_rwlock_t *rwlock) +{ + lll_lock(rwlock->lock); + for (;;) { + if (!rwlock->writer && !rwlock->readers) + break; + + rwlock->nr_writers_queued++; + val = rwlock->writer_wakeup; + lll_unlock(rwlock->lock); + + futex_wait(&rwlock->writer_wakeup, val); + + lll_lock(rwlock->lock); + rwlock->nr_writers_queued--; + } + rwlock->writer = pthread_self(); + lll_unlock(rwlock->lock); +} + +pthread_rwlock_unlock(pthread_rwlock_t *rwlock) +{ + lll_lock(rwlock->lock); + + if (rwlock->writer) + rwlock->writer = 0; + else + rwlock->readers--; + + if (!rwlock->readers) { + if (rwlock->nr_writers_queued) { + ++rwlock->writer_wakeup; + lll_unlock(rwlock->lock); + futex_wake(&rwlock->writer_wakeup, 1); + return; + } else + if (rwlock->nr_readers_queued) { + ++rwlock->readers_wakeup; + lll_unlock(rwlock->lock); + futex_wake(&rwlock->readers_wakeup, MAX_INT); + return; + } + } + + lll_unlock(rwlock->lock); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/DESIGN-sem.txt b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/DESIGN-sem.txt new file mode 100644 index 00000000..17eb0c11 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/DESIGN-sem.txt @@ -0,0 +1,46 @@ +Semaphores pseudocode +============================== + + int sem_wait(sem_t * sem); + int sem_trywait(sem_t * sem); + int sem_post(sem_t * sem); + int sem_getvalue(sem_t * sem, int * sval); + +struct sem_t { + + unsigned int count; + - current semaphore count, also used as a futex +} + +sem_wait(sem_t *sem) +{ + for (;;) { + + if (atomic_decrement_if_positive(sem->count)) + break; + + futex_wait(&sem->count, 0) + } +} + +sem_post(sem_t *sem) +{ + n = atomic_increment(sem->count); + // Pass the new value of sem->count + futex_wake(&sem->count, n + 1); +} + +sem_trywait(sem_t *sem) +{ + if (atomic_decrement_if_positive(sem->count)) { + return 0; + } else { + return EAGAIN; + } +} + +sem_getvalue(sem_t *sem, int *sval) +{ + *sval = sem->count; + read_barrier(); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/Makefile new file mode 100644 index 00000000..f9100219 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../ +top_builddir=../../ +include $(top_builddir)Rules.mak +all: libs +include Makefile.in +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/Makefile.in new file mode 100644 index 00000000..3e9676ac --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/Makefile.in @@ -0,0 +1,224 @@ +# Makefile for uClibc NPTL +# +# Copyright (C) 2005-2006 Steven J. Hill +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +subdirs += libpthread/nptl + +libpthread_DIR = $(top_srcdir)libpthread/nptl +libpthread_OUT = $(top_builddir)libpthread/nptl + +include $(libpthread_DIR)/sysdeps/Makefile.in + +libc-shared-routines-y = forward.c libc-cancellation.c +libc-static-routines-y = alloca_cutoff.c libc-cancellation.c +libpthread-shared-only-routines-y = version.c +libpthread-static-only-routines-y = pthread_atfork.c +libpthread-routines- += $(notdir $(wildcard $(libpthread_DIR)/gen_*.c)) # dummy generated files +libpthread-routines- += allocatestack.c # dummy included by pthread_create.c +libpthread-routines- += pthread_mutex_getprioceiling.c pthread_mutex_setprioceiling.c # XXX: delete those or use them! +libpthread-routines-$(findstring y,$(UCLIBC_HAS_IPV4)$(UCLIBC_HAS_IPV6)) += res.c +libpthread-routines-$(UCLIBC_SUSV4_LEGACY) += pthread_getconcurrency.c \ + pthread_setconcurrency +libpthread_CSRC = $(filter-out $(libpthread-routines-) \ + $(libc-shared-routines-y) \ + $(libc-static-routines-y) \ + $(libpthread-shared-only-routines-y) \ + $(libpthread-static-only-routines-y) \ + $(notdir $(libpthread_OBJS:.o=.c)), \ + $(notdir $(wildcard $(libpthread_DIR)/*.c))) + +libpthread_OBJS += $(addprefix $(libpthread_OUT)/,$(libpthread_CSRC:.c=.o)) +libpthread-so-y += $(addprefix $(libpthread_OUT)/,$(libpthread-shared-only-routines-y:.c=.oS)) +libpthread-so-y += $(libpthread_OBJS:.o=.oS) +libpthread-nonshared-y := $(addprefix $(libpthread_OUT)/,$(libpthread-static-only-routines-y:.c=.oS)) +libpthread-static-y := $(addprefix $(libpthread_OUT)/,$(libpthread-static-only-routines-y:.c=.o)) +libpthread-static-y += $(libpthread_OBJS) +ifeq ($(DOPIC),y) +libpthread-a-y := $(libpthread-static-y:.o=.os) +else +libpthread-a-y := $(libpthread-static-y) +endif + +libc-shared-routines-y := $(filter-out $(notdir $(libpthread_libc_OBJS:.o=.c)), $(libc-shared-routines-y)) +libc-static-routines-y := $(filter-out $(notdir $(libpthread_libc_OBJS:.o=.c)), $(libc-static-routines-y)) +libc-shared-routines-y := $(addprefix $(libpthread_OUT)/,$(libc-shared-routines-y:.c=.oS)) +libc-static-routines-y := $(addprefix $(libpthread_OUT)/,$(libc-static-routines-y:.c=.o)) +libc-shared-y += $(libc-shared-routines-y) $(libpthread_libc_OBJS:.o=.oS) +ifeq ($(DOPIC),y) +libc-static-y += $(libc-static-routines-y:.o=.os) $(libpthread_libc_a_OBJS:.o=.os) $(libpthread_ld_tls_COBJ:.o=.os) +else +libc-static-y += $(libc-static-routines-y) $(libpthread_libc_a_OBJS) $(libpthread_ld_tls_COBJ) +endif + +librt-pt-routines-y := $(patsubst %.c,$(libpthread_pthread_OUT)/%.o,$(filter-out $(notdir $(libpthread_librt_OBJS:.o=.c)), $(librt-pt-routines-y))) +librt-pt-shared-only-routines-y := $(patsubst %.c,$(libpthread_pthread_OUT)/%.o,$(filter-out $(notdir $(libpthread_librt_OBJS:.o=.c)), $(librt-pt-shared-only-routines-y))) +librt_OBJS = $(libpthread_librt_OBJS) $(librt-pt-routines-y) +ifeq ($(DOPIC),y) +librt-a-y += $(librt_OBJS:.o=.os) +else +librt-a-y += $(librt_OBJS) +endif +librt-so-y += $(librt_OBJS:.o=.oS) $(librt-pt-shared-only-routines-y:.o=.oS) + +ifneq ($(UCLIBC_CTOR_DTOR),y) +START_FILE-libpthread.so := $(top_builddir)/libpthread/nptl/sysdeps/pthread/crti.o $(SHARED_START_FILES) +END_FILE-libpthread.so := $(SHARED_END_FILES) $(top_builddir)/libpthread/nptl/sysdeps/pthread/crtn.o +endif + +libpthread_FULL_NAME := libpthread-$(VERSION).so +lib-a-$(UCLIBC_HAS_THREADS) += $(top_builddir)lib/libpthread.a +lib-so-$(UCLIBC_HAS_THREADS) += $(top_builddir)lib/libpthread.so + +$(top_builddir)lib/libpthread.so: $(libpthread_OUT)/libpthread_so.a $(libc.depend) $(libdl.depend) $(top_builddir)lib/libpthread_nonshared.a + $(call link.so,$(libpthread_FULL_NAME),$(ABI_VERSION)) + $(Q)cat $(top_srcdir)extra/scripts/format.lds > $@.tmp + $(Q)echo "GROUP ( $(notdir $@).$(ABI_VERSION) libpthread_nonshared.a )" >> $@.tmp + $(Q)mv $@.tmp $@ + +ifeq ($(PTHREADS_DEBUG_SUPPORT),y) +$(libpthread_OUT)/libpthread_so.a: STRIP_FLAGS:=$(STRIP_FLAGS:-x=-X --strip-debug) +endif +$(libpthread_OUT)/libpthread_so.a: $(libpthread-so-y) + $(Q)$(RM) $@ + $(do_ar) + +$(top_builddir)lib/libpthread.a: $(libpthread-a-y) + $(Q)$(INSTALL) -d $(dir $@) + $(Q)$(RM) $@ + $(do_ar) + +# +# Create 'pthread-errnos.h' header file. +# +CFLAGS-gen_pthread-errnos.c = -S + +$(libpthread_OUT)/gen_pthread-errnos.c: $(libpthread_DIR)/pthread-errnos.sym | $(libpthread_OUT) + $(do_awk) $(top_srcdir)extra/scripts/gen-as-const.awk $< > $@ + +$(libpthread_OUT)/gen_pthread-errnos.s: $(libpthread_OUT)/gen_pthread-errnos.c | headers + $(compile.c) +libpthread-generated-y += $(libpthread_OUT)/gen_pthread-errnos.s +$(libpthread_OUT)/pthread-errnos.h: $(libpthread_OUT)/gen_pthread-errnos.s + $(do_sed) $(PTHREAD_GENERATE_MANGLE) $< > $@ + @if test ! -s $@ ; then rm -f $@ ; false ; fi + +pregen-headers-$(UCLIBC_HAS_THREADS_NATIVE) += $(libpthread_OUT)/pthread-errnos.h + +headers-$(UCLIBC_HAS_THREADS_NATIVE) += $(nptl_headers_bootstrap) + +libpthread_H := $(addprefix $(top_builddir)include/,semaphore.h) +libpthread_include_H := $(addprefix $(top_builddir)include/,pthread.h) +libpthread_include_BITS_H := $(addprefix $(top_builddir)include/bits/,libc-lock.h stdio-lock.h) +libpthread_include_STD_IMPL_OS_ARCH_BITS_H := $(addprefix $(top_builddir)include/bits/,pthreadtypes.h semaphore.h) + +$(libpthread_include_STD_IMPL_OS_ARCH_BITS_H): $(top_builddir)include/bits/%: + $(do_ln) $(call rel_srcdir)$(PTDIR)/sysdeps/unix/sysv/linux/$(TARGET_ARCH)/bits/$(@F) $@ +$(libpthread_include_BITS_H): $(top_builddir)include/bits/%: + $(do_ln) $(call rel_srcdir)$(PTDIR)/sysdeps/pthread/bits/$(@F) $@ +$(libpthread_include_H): $(top_builddir)include/%: + $(do_ln) $(call rel_srcdir)$(PTDIR)/sysdeps/pthread/$(@F) $@ +$(libpthread_H): $(top_builddir)include/%: + $(do_ln) $(call rel_srcdir)$(PTDIR)/$(@F) $@ + +nptl_headers_bootstrap = $(libpthread_H) $(libpthread_include_H) $(libpthread_include_BITS_H) $(libpthread_include_STD_IMPL_OS_ARCH_BITS_H) + +objclean-y += CLEAN_libpthread/nptl +headers_clean-y += HEADERCLEAN_libpthread/nptl + +HEADERCLEAN_libpthread/nptl: + $(do_rm) $(nptl_headers_bootstrap) \ + $(addprefix $(libpthread_OUT)/gen_pthread-errnos., c s) \ + $(libpthread_OUT)/pthread-errnos.h + +CLEAN_libpthread/nptl: + $(do_rm) $(addprefix $(libpthread_OUT)/*., o os oS a) + +ifeq ($(PTHREADS_DEBUG_SUPPORT),y) +LDFLAGS-libpthread.so := $(LDFLAGS_NOSTRIP) -Wl,-z,defs +else +LDFLAGS-libpthread.so := $(LDFLAGS) +endif + +LDFLAGS-libpthread.so += $(top_builddir)lib/$(UCLIBC_LDSO_NAME)-$(VERSION).so $(top_builddir)lib/libdl-$(VERSION).so \ + -Wl,-z,nodelete,-z,initfirst,-init=__pthread_initialize_minimal_internal + +LIBS-libpthread.so := $(LIBS) + +CFLAGS-nptl = -DNOT_IN_libc -DIS_IN_libpthread $(SSP_ALL_CFLAGS) + +# Since cancellation handling is in large parts handled using exceptions +# we have to compile some files with exception handling enabled, some +# even with asynchronous unwind tables. + +# init.c contains sigcancel_handler(). +CFLAGS-init.c = -fexceptions -fasynchronous-unwind-tables +# The unwind code itself, +CFLAGS-unwind.c = -fexceptions +CFLAGS-unwind-forcedunwind.c = -fexceptions -fasynchronous-unwind-tables + +# The following three functions must be async-cancel safe. +CFLAGS-pthread_cancel.c = -fexceptions -fasynchronous-unwind-tables +CFLAGS-pthread_setcancelstate.c = -fexceptions -fasynchronous-unwind-tables +CFLAGS-pthread_setcanceltype.c = -fexceptions -fasynchronous-unwind-tables + +# These are internal functions which similar functionality as setcancelstate +# and setcanceltype. +CFLAGS-cancellation.c = -fasynchronous-unwind-tables +CFLAGS-libc-cancellation.c = -fasynchronous-unwind-tables + +# Calling pthread_exit() must cause the registered cancel handlers to +# be executed. Therefore exceptions have to be thrown through this +# function. +CFLAGS-pthread_exit.c = -fexceptions + +# Among others, __pthread_unwind is forwarded. This function must handle +# exceptions. +CFLAGS-forward.c = -fexceptions + +# The following are cancellation points. Some of the functions can +# block and therefore temporarily enable asynchronous cancellation. +# Those must be compiled asynchronous unwind tables. +CFLAGS-pthread_testcancel.c = -fexceptions +CFLAGS-pthread_join.c = -fexceptions -fasynchronous-unwind-tables +CFLAGS-pthread_timedjoin.c = -fexceptions -fasynchronous-unwind-tables +CFLAGS-pthread_once.c = $(uses-callbacks) -fexceptions \ + -fasynchronous-unwind-tables +CFLAGS-pthread_cond_wait.c = -fexceptions -fasynchronous-unwind-tables +CFLAGS-pthread_cond_timedwait.c = -fexceptions -fasynchronous-unwind-tables +CFLAGS-sem_wait.c = -fexceptions -fasynchronous-unwind-tables +CFLAGS-sem_timedwait.c = -fexceptions -fasynchronous-unwind-tables + +# These are the function wrappers we have to duplicate here. +CFLAGS-fcntl.c = -fexceptions -fasynchronous-unwind-tables +CFLAGS-lockf.c = -fexceptions +CFLAGS-pread.c = -fexceptions -fasynchronous-unwind-tables +CFLAGS-pread64.c = -fexceptions -fasynchronous-unwind-tables +CFLAGS-pwrite.c = -fexceptions -fasynchronous-unwind-tables +CFLAGS-pwrite64.c = -fexceptions -fasynchronous-unwind-tables +CFLAGS-wait.c = -fexceptions -fasynchronous-unwind-tables +CFLAGS-waitpid.c = -fexceptions -fasynchronous-unwind-tables +CFLAGS-sigwait.c = -fexceptions -fasynchronous-unwind-tables +CFLAGS-msgrcv.c = -fexceptions -fasynchronous-unwind-tables +CFLAGS-msgsnd.c = -fexceptions -fasynchronous-unwind-tables +CFLAGS-tcdrain.c = -fexceptions -fasynchronous-unwind-tables + +CFLAGS-pt-system.c = -fexceptions -I$(top_srcdir)libc/stdlib + +# +# The rest of this file is uClibc specific. +# +CFLAGS-pthread_barrier_init.c = -D_GNU_SOURCE +CFLAGS-pthread_barrier_destroy.c = -D_GNU_SOURCE +CFLAGS-pthread_barrierattr_init.c = -D_GNU_SOURCE +CFLAGS-pthread_barrierattr_destroy.c = -D_GNU_SOURCE +CFLAGS-pthread_barrierattr_getpshared.c = -D_GNU_SOURCE +CFLAGS-pthread_barrierattr_setpshared.c = -D_GNU_SOURCE +CFLAGS-sem_open.c = -D_GNU_SOURCE + +CFLAGS-OMIT-alloca_cutoff.c = $(CFLAGS-nptl) +CFLAGS-OMIT-forward.c = $(CFLAGS-nptl) +CFLAGS-OMIT-libc-lowlevelock.c = $(CFLAGS-nptl) +CFLAGS-OMIT-libc-cancellation.c = $(CFLAGS-nptl) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/README.NPTL b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/README.NPTL new file mode 100644 index 00000000..7e50984c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/README.NPTL @@ -0,0 +1,307 @@ +The base NPTL code for uClibc is from the glibc project located at +. The starting version was the HEAD of +the glibc CVS repository dated 2005-05-06. Important changes from +glibc will continue to be brought in as necessary until the version +for uClibc is standing on its own. All of the files were originally +brought over verbatim with no modifications. Obviously, these will +undergo any necessary changes needed for integration into uClibc. +Additionally (or subtractingly), the files and directories below +were removed and not imported. + +-- Steven J. Hill on 2005-05-06 + + +nptl/Makeconfig +nptl/configure +nptl/shlib-versions +nptl/sysdeps/generic +nptl/sysdeps/ia64 +nptl/sysdeps/pthread/Makefile +nptl/sysdeps/pthread/Subdirs +nptl/sysdeps/pthread/allocalim.h +nptl/sysdeps/pthread/configure +nptl/sysdeps/pthread/configure.in +nptl/sysdeps/pthread/createthread.c +nptl/sysdeps/pthread/flockfile.c +nptl/sysdeps/pthread/ftrylockfile.c +nptl/sysdeps/pthread/funlockfile.c +nptl/sysdeps/pthread/librt-cancellation.c +nptl/sysdeps/pthread/list.h +nptl/sysdeps/pthread/malloc-machine.h +nptl/sysdeps/pthread/posix-timer.h +nptl/sysdeps/pthread/pt-initfini.c +nptl/sysdeps/pthread/pt-longjmp.c +nptl/sysdeps/pthread/pthread-functions.h +nptl/sysdeps/pthread/pthread.h +nptl/sysdeps/pthread/pthread_barrier_wait.c +nptl/sysdeps/pthread/pthread_cond_broadcast.c +nptl/sysdeps/pthread/pthread_cond_signal.c +nptl/sysdeps/pthread/pthread_cond_timedwait.c +nptl/sysdeps/pthread/pthread_cond_wait.c +nptl/sysdeps/pthread/pthread_getcpuclockid.c +nptl/sysdeps/pthread/pthread_once.c +nptl/sysdeps/pthread/pthread_rwlock_rdlock.c +nptl/sysdeps/pthread/pthread_rwlock_timedrdlock.c +nptl/sysdeps/pthread/pthread_rwlock_timedwrlock.c +nptl/sysdeps/pthread/pthread_rwlock_unlock.c +nptl/sysdeps/pthread/pthread_rwlock_wrlock.c +nptl/sysdeps/pthread/pthread_sigmask.c +nptl/sysdeps/pthread/pthread_spin_destroy.c +nptl/sysdeps/pthread/pthread_spin_init.c +nptl/sysdeps/pthread/pthread_spin_unlock.c +nptl/sysdeps/pthread/rt-unwind-resume.c +nptl/sysdeps/pthread/setxid.h +nptl/sysdeps/pthread/sigaction.c +nptl/sysdeps/pthread/sigfillset.c +nptl/sysdeps/pthread/sigprocmask.c +nptl/sysdeps/pthread/tcb-offsets.h +nptl/sysdeps/pthread/timer_create.c +nptl/sysdeps/pthread/timer_delete.c +nptl/sysdeps/pthread/timer_getoverr.c +nptl/sysdeps/pthread/timer_gettime.c +nptl/sysdeps/pthread/timer_routines.c +nptl/sysdeps/pthread/timer_settime.c +nptl/sysdeps/pthread/tst-mqueue8x.c +nptl/sysdeps/pthread/tst-timer.c +nptl/sysdeps/pthread/unwind-forcedunwind.c +nptl/sysdeps/pthread/unwind-resume.c +nptl/sysdeps/s390 +nptl/sysdeps/unix +nptl/tst-_res1.c +nptl/tst-_res1mod1.c +nptl/tst-_res1mod2.c +nptl/tst-align.c +nptl/tst-align2.c +nptl/tst-atfork1.c +nptl/tst-atfork2.c +nptl/tst-atfork2mod.c +nptl/tst-attr1.c +nptl/tst-attr2.c +nptl/tst-attr3.c +nptl/tst-backtrace1.c +nptl/tst-barrier1.c +nptl/tst-barrier2.c +nptl/tst-barrier3.c +nptl/tst-barrier4.c +nptl/tst-basic1.c +nptl/tst-basic2.c +nptl/tst-basic3.c +nptl/tst-basic4.c +nptl/tst-basic5.c +nptl/tst-basic6.c +nptl/tst-cancel-wrappers.sh +nptl/tst-cancel1.c +nptl/tst-cancel10.c +nptl/tst-cancel11.c +nptl/tst-cancel12.c +nptl/tst-cancel13.c +nptl/tst-cancel14.c +nptl/tst-cancel15.c +nptl/tst-cancel16.c +nptl/tst-cancel17.c +nptl/tst-cancel18.c +nptl/tst-cancel19.c +nptl/tst-cancel2.c +nptl/tst-cancel20.c +nptl/tst-cancel21.c +nptl/tst-cancel22.c +nptl/tst-cancel23.c +nptl/tst-cancel3.c +nptl/tst-cancel4.c +nptl/tst-cancel5.c +nptl/tst-cancel6.c +nptl/tst-cancel7.c +nptl/tst-cancel8.c +nptl/tst-cancel9.c +nptl/tst-cancelx1.c +nptl/tst-cancelx10.c +nptl/tst-cancelx11.c +nptl/tst-cancelx12.c +nptl/tst-cancelx13.c +nptl/tst-cancelx14.c +nptl/tst-cancelx15.c +nptl/tst-cancelx16.c +nptl/tst-cancelx17.c +nptl/tst-cancelx18.c +nptl/tst-cancelx2.c +nptl/tst-cancelx20.c +nptl/tst-cancelx21.c +nptl/tst-cancelx3.c +nptl/tst-cancelx4.c +nptl/tst-cancelx5.c +nptl/tst-cancelx6.c +nptl/tst-cancelx7.c +nptl/tst-cancelx8.c +nptl/tst-cancelx9.c +nptl/tst-cleanup0.c +nptl/tst-cleanup0.expect +nptl/tst-cleanup1.c +nptl/tst-cleanup2.c +nptl/tst-cleanup3.c +nptl/tst-cleanup4.c +nptl/tst-cleanup4aux.c +nptl/tst-cleanupx0.c +nptl/tst-cleanupx0.expect +nptl/tst-cleanupx1.c +nptl/tst-cleanupx2.c +nptl/tst-cleanupx3.c +nptl/tst-cleanupx4.c +nptl/tst-clock1.c +nptl/tst-clock2.c +nptl/tst-cond1.c +nptl/tst-cond10.c +nptl/tst-cond11.c +nptl/tst-cond12.c +nptl/tst-cond13.c +nptl/tst-cond14.c +nptl/tst-cond15.c +nptl/tst-cond16.c +nptl/tst-cond17.c +nptl/tst-cond18.c +nptl/tst-cond19.c +nptl/tst-cond2.c +nptl/tst-cond20.c +nptl/tst-cond21.c +nptl/tst-cond3.c +nptl/tst-cond4.c +nptl/tst-cond5.c +nptl/tst-cond6.c +nptl/tst-cond7.c +nptl/tst-cond8.c +nptl/tst-cond9.c +nptl/tst-context1.c +nptl/tst-detach1.c +nptl/tst-dlsym1.c +nptl/tst-eintr1.c +nptl/tst-eintr2.c +nptl/tst-eintr3.c +nptl/tst-eintr4.c +nptl/tst-eintr5.c +nptl/tst-exec1.c +nptl/tst-exec2.c +nptl/tst-exec3.c +nptl/tst-exec4.c +nptl/tst-execstack-mod.c +nptl/tst-execstack.c +nptl/tst-exit1.c +nptl/tst-exit2.c +nptl/tst-exit3.c +nptl/tst-fini1.c +nptl/tst-fini1mod.c +nptl/tst-flock1.c +nptl/tst-flock2.c +nptl/tst-fork1.c +nptl/tst-fork2.c +nptl/tst-fork3.c +nptl/tst-fork4.c +nptl/tst-getpid1.c +nptl/tst-getpid2.c +nptl/tst-join1.c +nptl/tst-join2.c +nptl/tst-join3.c +nptl/tst-join4.c +nptl/tst-join5.c +nptl/tst-key1.c +nptl/tst-key2.c +nptl/tst-key3.c +nptl/tst-key4.c +nptl/tst-kill1.c +nptl/tst-kill2.c +nptl/tst-kill3.c +nptl/tst-kill4.c +nptl/tst-kill5.c +nptl/tst-kill6.c +nptl/tst-locale1.c +nptl/tst-locale2.c +nptl/tst-mutex1.c +nptl/tst-mutex2.c +nptl/tst-mutex3.c +nptl/tst-mutex4.c +nptl/tst-mutex5.c +nptl/tst-mutex5a.c +nptl/tst-mutex6.c +nptl/tst-mutex7.c +nptl/tst-mutex7a.c +nptl/tst-mutex8.c +nptl/tst-mutex9.c +nptl/tst-oddstacklimit.c +nptl/tst-once1.c +nptl/tst-once2.c +nptl/tst-once3.c +nptl/tst-once4.c +nptl/tst-oncex3.c +nptl/tst-oncex4.c +nptl/tst-popen1.c +nptl/tst-raise1.c +nptl/tst-rwlock1.c +nptl/tst-rwlock10.c +nptl/tst-rwlock11.c +nptl/tst-rwlock12.c +nptl/tst-rwlock13.c +nptl/tst-rwlock14.c +nptl/tst-rwlock2.c +nptl/tst-rwlock3.c +nptl/tst-rwlock4.c +nptl/tst-rwlock5.c +nptl/tst-rwlock6.c +nptl/tst-rwlock7.c +nptl/tst-rwlock8.c +nptl/tst-rwlock9.c +nptl/tst-sched1.c +nptl/tst-sem1.c +nptl/tst-sem2.c +nptl/tst-sem3.c +nptl/tst-sem4.c +nptl/tst-sem5.c +nptl/tst-sem6.c +nptl/tst-sem7.c +nptl/tst-sem8.c +nptl/tst-sem9.c +nptl/tst-setuid1-static.c +nptl/tst-setuid1.c +nptl/tst-signal1.c +nptl/tst-signal2.c +nptl/tst-signal3.c +nptl/tst-signal4.c +nptl/tst-signal5.c +nptl/tst-signal6.c +nptl/tst-spin1.c +nptl/tst-spin2.c +nptl/tst-spin3.c +nptl/tst-stack1.c +nptl/tst-stack2.c +nptl/tst-stack3.c +nptl/tst-stdio1.c +nptl/tst-stdio2.c +nptl/tst-sysconf.c +nptl/tst-tls1.c +nptl/tst-tls2.c +nptl/tst-tls3.c +nptl/tst-tls3mod.c +nptl/tst-tls4.c +nptl/tst-tls4moda.c +nptl/tst-tls4modb.c +nptl/tst-tls5.c +nptl/tst-tls5.h +nptl/tst-tls5mod.c +nptl/tst-tls5moda.c +nptl/tst-tls5modb.c +nptl/tst-tls5modc.c +nptl/tst-tls5modd.c +nptl/tst-tls5mode.c +nptl/tst-tls5modf.c +nptl/tst-tls6.sh +nptl/tst-tsd1.c +nptl/tst-tsd2.c +nptl/tst-tsd3.c +nptl/tst-tsd4.c +nptl/tst-tsd5.c +nptl/tst-umask1.c +nptl/tst-unload.c +nptl/tst-vfork1.c +nptl/tst-vfork1x.c +nptl/tst-vfork2.c +nptl/tst-vfork2x.c +nptl/version.c +nptl_db/ChangeLog +nptl_db/shlib-versions diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/TODO b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/TODO new file mode 100644 index 00000000..70b8fe4f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/TODO @@ -0,0 +1,31 @@ +- we should probably extend pthread_mutexattr_t with a field to create a + single linked list of all instances. This requires changing the + pthread_mutexattr_* functions. + + +- a new attribute for mutexes: number of times we spin before calling +sys_futex + +- for adaptive mutexes: when releasing, determine whether somebody spins. +If yes, for a short time release lock. If someone else locks no wakeup +syscall needed. + + + +- test with threaded process terminating and semadj (?) being applied + only after all threads are gone + + + +- semaphore changes: + + - sem_post should only wake one thread and only when the state of + the semaphore changed from 0 to 1 + + this also requires that sem_wait and sem_timedwait don't drop the + post if they get canceled. + + - possibly add counter field. This requires reviving the + differences between old and new semaphose funtions. The old ones + stay as they are now. The new once can use an additional field + wich is the counter for the number of waiters diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/TODO-kernel b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/TODO-kernel new file mode 100644 index 00000000..ad6d2a4b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/TODO-kernel @@ -0,0 +1,20 @@ +- setuid/setgid must effect process + + test syscalls (getuid) afterwards + + test core file content + + + use UID/GID in access(2), chmod(2), chown(2), link(2) + +- nice level is process property + +- rlimit should be process-wide and SIGXCPU should be sent if all threads + together exceed the limit + +- getrusage() must return resource utilization for the process + + + +The following are possible optimizations and in no way required: + + +- the scheduler should be thread group-aware, i.e., it has to give time to + the thread group not proportional to the number of threads. diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/TODO-testing b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/TODO-testing new file mode 100644 index 00000000..e076e562 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/TODO-testing @@ -0,0 +1,20 @@ +pthread_attr_setguardsize + + test effectiveness + +pthread_attr_[sg]etschedparam + + what to test? + +pthread_attr_[sg]etstack + + some more tests needed + +pthread_getcpuclockid + + check that value is reset -> rt subdir + +pthread_getschedparam +pthread_setschedparam + + what to test? diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/alloca_cutoff.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/alloca_cutoff.c new file mode 100644 index 00000000..ba26ceba --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/alloca_cutoff.c @@ -0,0 +1,36 @@ +/* Determine whether block of given size can be allocated on the stack or not. + Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include + + +int +__libc_alloca_cutoff (size_t size) +{ + return size <= (MIN (__MAX_ALLOCA_CUTOFF, + THREAD_GETMEM (THREAD_SELF, stackblock_size) / 4 + /* The main thread, before the thread library is + initialized, has zero in the stackblock_size + element. Since it is the main thread we can + assume the maximum available stack space. */ + ?: __MAX_ALLOCA_CUTOFF * 4)); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/allocatestack.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/allocatestack.c new file mode 100644 index 00000000..9ffa7e7e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/allocatestack.c @@ -0,0 +1,1217 @@ +/* Copyright (C) 2002-2007, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#ifndef NEED_SEPARATE_REGISTER_STACK + +/* Most architectures have exactly one stack pointer. Some have more. */ +# define STACK_VARIABLES void *stackaddr = NULL + +/* How to pass the values to the 'create_thread' function. */ +# define STACK_VARIABLES_ARGS stackaddr + +/* How to declare function which gets there parameters. */ +# define STACK_VARIABLES_PARMS void *stackaddr + +/* How to declare allocate_stack. */ +# define ALLOCATE_STACK_PARMS void **stack + +/* This is how the function is called. We do it this way to allow + other variants of the function to have more parameters. */ +# define ALLOCATE_STACK(attr, pd) allocate_stack (attr, pd, &stackaddr) + +#else + +/* We need two stacks. The kernel will place them but we have to tell + the kernel about the size of the reserved address space. */ +# define STACK_VARIABLES void *stackaddr = NULL; size_t stacksize = 0 + +/* How to pass the values to the 'create_thread' function. */ +# define STACK_VARIABLES_ARGS stackaddr, stacksize + +/* How to declare function which gets there parameters. */ +# define STACK_VARIABLES_PARMS void *stackaddr, size_t stacksize + +/* How to declare allocate_stack. */ +# define ALLOCATE_STACK_PARMS void **stack, size_t *stacksize + +/* This is how the function is called. We do it this way to allow + other variants of the function to have more parameters. */ +# define ALLOCATE_STACK(attr, pd) \ + allocate_stack (attr, pd, &stackaddr, &stacksize) + +#endif + + +/* Default alignment of stack. */ +#ifndef STACK_ALIGN +# define STACK_ALIGN __alignof__ (long double) +#endif + +/* Default value for minimal stack size after allocating thread + descriptor and guard. */ +#ifndef MINIMAL_REST_STACK +# define MINIMAL_REST_STACK 4096 +#endif + + +/* Newer kernels have the MAP_STACK flag to indicate a mapping is used for + a stack. Use it when possible. */ +#ifndef MAP_STACK +# define MAP_STACK 0 +#endif + +/* This yields the pointer that TLS support code calls the thread pointer. */ +#if defined(TLS_TCB_AT_TP) +# define TLS_TPADJ(pd) (pd) +#elif defined(TLS_DTV_AT_TP) +# define TLS_TPADJ(pd) ((struct pthread *)((char *) (pd) + TLS_PRE_TCB_SIZE)) +#endif + +/* Cache handling for not-yet free stacks. */ + +/* Maximum size in kB of cache. */ +static size_t stack_cache_maxsize = 40 * 1024 * 1024; /* 40MiBi by default. */ +static size_t stack_cache_actsize; + +/* Mutex protecting this variable. */ +static int stack_cache_lock = LLL_LOCK_INITIALIZER; + +/* List of queued stack frames. */ +static LIST_HEAD (stack_cache); + +/* List of the stacks in use. */ +static LIST_HEAD (stack_used); + +/* We need to record what list operations we are going to do so that, + in case of an asynchronous interruption due to a fork() call, we + can correct for the work. */ +static uintptr_t in_flight_stack; + +/* List of the threads with user provided stacks in use. No need to + initialize this, since it's done in __pthread_initialize_minimal. */ +list_t __stack_user __attribute__ ((nocommon)); +hidden_data_def (__stack_user) + +#if COLORING_INCREMENT != 0 +/* Number of threads created. */ +static unsigned int nptl_ncreated; +#endif + + +/* Check whether the stack is still used or not. */ +#define FREE_P(descr) ((descr)->tid <= 0) + + +static void +stack_list_del (list_t *elem) +{ + in_flight_stack = (uintptr_t) elem; + + atomic_write_barrier (); + + list_del (elem); + + atomic_write_barrier (); + + in_flight_stack = 0; +} + + +static void +stack_list_add (list_t *elem, list_t *list) +{ + in_flight_stack = (uintptr_t) elem | 1; + + atomic_write_barrier (); + + list_add (elem, list); + + atomic_write_barrier (); + + in_flight_stack = 0; +} + + +/* We create a double linked list of all cache entries. Double linked + because this allows removing entries from the end. */ + + +/* Get a stack frame from the cache. We have to match by size since + some blocks might be too small or far too large. */ +static struct pthread * +get_cached_stack (size_t *sizep, void **memp) +{ + size_t size = *sizep; + struct pthread *result = NULL; + list_t *entry; + + lll_lock (stack_cache_lock, LLL_PRIVATE); + + /* Search the cache for a matching entry. We search for the + smallest stack which has at least the required size. Note that + in normal situations the size of all allocated stacks is the + same. As the very least there are only a few different sizes. + Therefore this loop will exit early most of the time with an + exact match. */ + list_for_each (entry, &stack_cache) + { + struct pthread *curr; + + curr = list_entry (entry, struct pthread, list); + if (FREE_P (curr) && curr->stackblock_size >= size) + { + if (curr->stackblock_size == size) + { + result = curr; + break; + } + + if (result == NULL + || result->stackblock_size > curr->stackblock_size) + result = curr; + } + } + + if (__builtin_expect (result == NULL, 0) + /* Make sure the size difference is not too excessive. In that + case we do not use the block. */ + || __builtin_expect (result->stackblock_size > 4 * size, 0)) + { + /* Release the lock. */ + lll_unlock (stack_cache_lock, LLL_PRIVATE); + + return NULL; + } + + /* Dequeue the entry. */ + stack_list_del (&result->list); + + /* And add to the list of stacks in use. */ + stack_list_add (&result->list, &stack_used); + + /* And decrease the cache size. */ + stack_cache_actsize -= result->stackblock_size; + + /* Release the lock early. */ + lll_unlock (stack_cache_lock, LLL_PRIVATE); + + /* Report size and location of the stack to the caller. */ + *sizep = result->stackblock_size; + *memp = result->stackblock; + + /* Cancellation handling is back to the default. */ + result->cancelhandling = 0; + result->cleanup = NULL; + + /* No pending event. */ + result->nextevent = NULL; + + /* Clear the DTV. */ + dtv_t *dtv = GET_DTV (TLS_TPADJ (result)); + memset (dtv, '\0', (dtv[-1].counter + 1) * sizeof (dtv_t)); + + /* Re-initialize the TLS. */ + _dl_allocate_tls_init (TLS_TPADJ (result)); + + return result; +} + + +/* Free stacks until cache size is lower than LIMIT. */ +void +__free_stacks (size_t limit) +{ + /* We reduce the size of the cache. Remove the last entries until + the size is below the limit. */ + list_t *entry; + list_t *prev; + + /* Search from the end of the list. */ + list_for_each_prev_safe (entry, prev, &stack_cache) + { + struct pthread *curr; + + curr = list_entry (entry, struct pthread, list); + if (FREE_P (curr)) + { + /* Unlink the block. */ + stack_list_del (entry); + + /* Account for the freed memory. */ + stack_cache_actsize -= curr->stackblock_size; + + /* Free the memory associated with the ELF TLS. */ + _dl_deallocate_tls (TLS_TPADJ (curr), false); + + /* Remove this block. This should never fail. If it does + something is really wrong. */ + if (munmap (curr->stackblock, curr->stackblock_size) != 0) + abort (); + + /* Maybe we have freed enough. */ + if (stack_cache_actsize <= limit) + break; + } + } +} + + +/* Add a stack frame which is not used anymore to the stack. Must be + called with the cache lock held. */ +static inline void +__attribute ((always_inline)) +queue_stack (struct pthread *stack) +{ + /* We unconditionally add the stack to the list. The memory may + still be in use but it will not be reused until the kernel marks + the stack as not used anymore. */ + stack_list_add (&stack->list, &stack_cache); + + stack_cache_actsize += stack->stackblock_size; + if (__builtin_expect (stack_cache_actsize > stack_cache_maxsize, 0)) + __free_stacks (stack_cache_maxsize); +} + + +static int +internal_function +change_stack_perm (struct pthread *pd +#ifdef NEED_SEPARATE_REGISTER_STACK + , size_t pagemask +#endif + ) +{ +#ifdef NEED_SEPARATE_REGISTER_STACK + void *stack = (pd->stackblock + + (((((pd->stackblock_size - pd->guardsize) / 2) + & pagemask) + pd->guardsize) & pagemask)); + size_t len = pd->stackblock + pd->stackblock_size - stack; +#elif _STACK_GROWS_DOWN + void *stack = pd->stackblock + pd->guardsize; + size_t len = pd->stackblock_size - pd->guardsize; +#elif _STACK_GROWS_UP + void *stack = pd->stackblock; + size_t len = (uintptr_t) pd - pd->guardsize - (uintptr_t) pd->stackblock; +#else +# error "Define either _STACK_GROWS_DOWN or _STACK_GROWS_UP" +#endif + if (mprotect (stack, len, PROT_READ | PROT_WRITE | PROT_EXEC) != 0) + return errno; + + return 0; +} + + +static int +allocate_stack (const struct pthread_attr *attr, struct pthread **pdp, + ALLOCATE_STACK_PARMS) +{ + struct pthread *pd; + size_t size; + size_t pagesize_m1 = __getpagesize () - 1; + void *stacktop; + + assert (attr != NULL); + assert (powerof2 (pagesize_m1 + 1)); + assert (TCB_ALIGNMENT >= STACK_ALIGN); + + /* Get the stack size from the attribute if it is set. Otherwise we + use the default we determined at start time. */ + size = attr->stacksize ?: __default_stacksize; + + /* Get memory for the stack. */ + if (__builtin_expect (attr->flags & ATTR_FLAG_STACKADDR, 0)) + { + uintptr_t adj; + + /* If the user also specified the size of the stack make sure it + is large enough. */ + if (attr->stacksize != 0 + && attr->stacksize < (__static_tls_size + MINIMAL_REST_STACK)) + return EINVAL; + + /* Adjust stack size for alignment of the TLS block. */ +#if defined(TLS_TCB_AT_TP) + adj = ((uintptr_t) attr->stackaddr - TLS_TCB_SIZE) + & __static_tls_align_m1; + assert (size > adj + TLS_TCB_SIZE); +#elif defined(TLS_DTV_AT_TP) + adj = ((uintptr_t) attr->stackaddr - __static_tls_size) + & __static_tls_align_m1; + assert (size > adj); +#endif + + /* The user provided some memory. Let's hope it matches the + size... We do not allocate guard pages if the user provided + the stack. It is the user's responsibility to do this if it + is wanted. */ +#if defined(TLS_TCB_AT_TP) + pd = (struct pthread *) ((uintptr_t) attr->stackaddr + - TLS_TCB_SIZE - adj); +#elif defined(TLS_DTV_AT_TP) + pd = (struct pthread *) (((uintptr_t) attr->stackaddr + - __static_tls_size - adj) + - TLS_PRE_TCB_SIZE); +#endif + + /* The user provided stack memory needs to be cleared. */ + memset (pd, '\0', sizeof (struct pthread)); + + /* The first TSD block is included in the TCB. */ + pd->specific[0] = pd->specific_1stblock; + + /* Remember the stack-related values. */ + pd->stackblock = (char *) attr->stackaddr - size; + pd->stackblock_size = size; + + /* This is a user-provided stack. It will not be queued in the + stack cache nor will the memory (except the TLS memory) be freed. */ + pd->user_stack = true; + + /* This is at least the second thread. */ + pd->header.multiple_threads = 1; +#ifndef TLS_MULTIPLE_THREADS_IN_TCB + __pthread_multiple_threads = *__libc_multiple_threads_ptr = 1; +#endif + +#ifndef __ASSUME_PRIVATE_FUTEX + /* The thread must know when private futexes are supported. */ + pd->header.private_futex = THREAD_GETMEM (THREAD_SELF, + header.private_futex); +#endif + +#ifdef NEED_DL_SYSINFO + /* Copy the sysinfo value from the parent. */ + THREAD_SYSINFO(pd) = THREAD_SELF_SYSINFO; +#endif + + /* The process ID is also the same as that of the caller. */ + pd->pid = THREAD_GETMEM (THREAD_SELF, pid); + + /* Allocate the DTV for this thread. */ + if (_dl_allocate_tls (TLS_TPADJ (pd)) == NULL) + { + /* Something went wrong. */ + assert (errno == ENOMEM); + return EAGAIN; + } + + + /* Prepare to modify global data. */ + lll_lock (stack_cache_lock, LLL_PRIVATE); + + /* And add to the list of stacks in use. */ + list_add (&pd->list, &__stack_user); + + lll_unlock (stack_cache_lock, LLL_PRIVATE); + } + else + { + /* Allocate some anonymous memory. If possible use the cache. */ + size_t guardsize; + size_t reqsize; + void *mem = 0; + const int prot = (PROT_READ | PROT_WRITE); + +#if COLORING_INCREMENT != 0 + /* Add one more page for stack coloring. Don't do it for stacks + with 16 times pagesize or larger. This might just cause + unnecessary misalignment. */ + if (size <= 16 * pagesize_m1) + size += pagesize_m1 + 1; +#endif + + /* Adjust the stack size for alignment. */ + size &= ~__static_tls_align_m1; + assert (size != 0); + + /* Make sure the size of the stack is enough for the guard and + eventually the thread descriptor. */ + guardsize = (attr->guardsize + pagesize_m1) & ~pagesize_m1; + if (__builtin_expect (size < ((guardsize + __static_tls_size + + MINIMAL_REST_STACK + pagesize_m1) + & ~pagesize_m1), + 0)) + /* The stack is too small (or the guard too large). */ + return EINVAL; + + /* Try to get a stack from the cache. */ + reqsize = size; + pd = get_cached_stack (&size, &mem); + if (pd == NULL) + { + /* To avoid aliasing effects on a larger scale than pages we + adjust the allocated stack size if necessary. This way + allocations directly following each other will not have + aliasing problems. */ +#if MULTI_PAGE_ALIASING != 0 + if ((size % MULTI_PAGE_ALIASING) == 0) + size += pagesize_m1 + 1; +#endif + + mem = mmap (NULL, size, prot, + MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0); + + if (__builtin_expect (mem == MAP_FAILED, 0)) + { + if (errno == ENOMEM) + __set_errno (EAGAIN); + + return errno; + } + + /* SIZE is guaranteed to be greater than zero. + So we can never get a null pointer back from mmap. */ + assert (mem != NULL); + +#if COLORING_INCREMENT != 0 + /* Atomically increment NCREATED. */ + unsigned int ncreated = atomic_increment_val (&nptl_ncreated); + + /* We chose the offset for coloring by incrementing it for + every new thread by a fixed amount. The offset used + module the page size. Even if coloring would be better + relative to higher alignment values it makes no sense to + do it since the mmap() interface does not allow us to + specify any alignment for the returned memory block. */ + size_t coloring = (ncreated * COLORING_INCREMENT) & pagesize_m1; + + /* Make sure the coloring offsets does not disturb the alignment + of the TCB and static TLS block. */ + if (__builtin_expect ((coloring & __static_tls_align_m1) != 0, 0)) + coloring = (((coloring + __static_tls_align_m1) + & ~(__static_tls_align_m1)) + & ~pagesize_m1); +#else + /* Unless specified we do not make any adjustments. */ +# define coloring 0 +#endif + + /* Place the thread descriptor at the end of the stack. */ +#if defined(TLS_TCB_AT_TP) + pd = (struct pthread *) ((char *) mem + size - coloring) - 1; +#elif defined(TLS_DTV_AT_TP) + pd = (struct pthread *) ((((uintptr_t) mem + size - coloring + - __static_tls_size) + & ~__static_tls_align_m1) + - TLS_PRE_TCB_SIZE); +#endif + + /* Remember the stack-related values. */ + pd->stackblock = mem; + pd->stackblock_size = size; + + /* We allocated the first block thread-specific data array. + This address will not change for the lifetime of this + descriptor. */ + pd->specific[0] = pd->specific_1stblock; + + /* This is at least the second thread. */ + pd->header.multiple_threads = 1; +#ifndef TLS_MULTIPLE_THREADS_IN_TCB + __pthread_multiple_threads = *__libc_multiple_threads_ptr = 1; +#endif + +#ifndef __ASSUME_PRIVATE_FUTEX + /* The thread must know when private futexes are supported. */ + pd->header.private_futex = THREAD_GETMEM (THREAD_SELF, + header.private_futex); +#endif + +#ifdef NEED_DL_SYSINFO + /* Copy the sysinfo value from the parent. */ + THREAD_SYSINFO(pd) = THREAD_SELF_SYSINFO; +#endif + + /* The process ID is also the same as that of the caller. */ + pd->pid = THREAD_GETMEM (THREAD_SELF, pid); + + /* Allocate the DTV for this thread. */ + if (_dl_allocate_tls (TLS_TPADJ (pd)) == NULL) + { + /* Something went wrong. */ + assert (errno == ENOMEM); + + /* Free the stack memory we just allocated. */ + (void) munmap (mem, size); + + return EAGAIN; + } + + + /* Prepare to modify global data. */ + lll_lock (stack_cache_lock, LLL_PRIVATE); + + /* And add to the list of stacks in use. */ + stack_list_add (&pd->list, &stack_used); + + lll_unlock (stack_cache_lock, LLL_PRIVATE); + + + /* Note that all of the stack and the thread descriptor is + zeroed. This means we do not have to initialize fields + with initial value zero. This is specifically true for + the 'tid' field which is always set back to zero once the + stack is not used anymore and for the 'guardsize' field + which will be read next. */ + } + + /* Create or resize the guard area if necessary. */ + if (__builtin_expect (guardsize > pd->guardsize, 0)) + { +#ifdef NEED_SEPARATE_REGISTER_STACK + char *guard = mem + (((size - guardsize) / 2) & ~pagesize_m1); +#elif _STACK_GROWS_DOWN + char *guard = mem; +# elif _STACK_GROWS_UP + char *guard = (char *) (((uintptr_t) pd - guardsize) & ~pagesize_m1); +#endif + if (mprotect (guard, guardsize, PROT_NONE) != 0) + { + int err; + mprot_error: + err = errno; + + lll_lock (stack_cache_lock, LLL_PRIVATE); + + /* Remove the thread from the list. */ + stack_list_del (&pd->list); + + lll_unlock (stack_cache_lock, LLL_PRIVATE); + + /* Get rid of the TLS block we allocated. */ + _dl_deallocate_tls (TLS_TPADJ (pd), false); + + /* Free the stack memory regardless of whether the size + of the cache is over the limit or not. If this piece + of memory caused problems we better do not use it + anymore. Uh, and we ignore possible errors. There + is nothing we could do. */ + (void) munmap (mem, size); + + return err; + } + + pd->guardsize = guardsize; + } + else if (__builtin_expect (pd->guardsize - guardsize > size - reqsize, + 0)) + { + /* The old guard area is too large. */ + +#ifdef NEED_SEPARATE_REGISTER_STACK + char *guard = mem + (((size - guardsize) / 2) & ~pagesize_m1); + char *oldguard = mem + (((size - pd->guardsize) / 2) & ~pagesize_m1); + + if (oldguard < guard + && mprotect (oldguard, guard - oldguard, prot) != 0) + goto mprot_error; + + if (mprotect (guard + guardsize, + oldguard + pd->guardsize - guard - guardsize, + prot) != 0) + goto mprot_error; +#elif _STACK_GROWS_DOWN + if (mprotect ((char *) mem + guardsize, pd->guardsize - guardsize, + prot) != 0) + goto mprot_error; +#elif _STACK_GROWS_UP + if (mprotect ((char *) pd - pd->guardsize, + pd->guardsize - guardsize, prot) != 0) + goto mprot_error; +#endif + + pd->guardsize = guardsize; + } + /* The pthread_getattr_np() calls need to get passed the size + requested in the attribute, regardless of how large the + actually used guardsize is. */ + pd->reported_guardsize = guardsize; + } + + /* Initialize the lock. We have to do this unconditionally since the + stillborn thread could be canceled while the lock is taken. */ + pd->lock = LLL_LOCK_INITIALIZER; + + /* The robust mutex lists also need to be initialized + unconditionally because the cleanup for the previous stack owner + might have happened in the kernel. */ + pd->robust_head.futex_offset = (offsetof (pthread_mutex_t, __data.__lock) + - offsetof (pthread_mutex_t, + __data.__list.__next)); + pd->robust_head.list_op_pending = NULL; +#ifdef __PTHREAD_MUTEX_HAVE_PREV + pd->robust_prev = &pd->robust_head; +#endif + pd->robust_head.list = &pd->robust_head; + + /* We place the thread descriptor at the end of the stack. */ + *pdp = pd; + +#if defined(TLS_TCB_AT_TP) + /* The stack begins before the TCB and the static TLS block. */ + stacktop = ((char *) (pd + 1) - __static_tls_size); +#elif defined(TLS_DTV_AT_TP) + stacktop = (char *) (pd - 1); +#endif + +#ifdef NEED_SEPARATE_REGISTER_STACK + *stack = pd->stackblock; + *stacksize = stacktop - *stack; +#elif _STACK_GROWS_DOWN + *stack = stacktop; +#elif _STACK_GROWS_UP + *stack = pd->stackblock; + assert (*stack > 0); +#endif + + return 0; +} + + +void +internal_function +__deallocate_stack (struct pthread *pd) +{ + lll_lock (stack_cache_lock, LLL_PRIVATE); + + /* Remove the thread from the list of threads with user defined + stacks. */ + stack_list_del (&pd->list); + + /* Not much to do. Just free the mmap()ed memory. Note that we do + not reset the 'used' flag in the 'tid' field. This is done by + the kernel. If no thread has been created yet this field is + still zero. */ + if (__builtin_expect (! pd->user_stack, 1)) + (void) queue_stack (pd); + else + /* Free the memory associated with the ELF TLS. */ + _dl_deallocate_tls (TLS_TPADJ (pd), false); + + lll_unlock (stack_cache_lock, LLL_PRIVATE); +} + + +int +internal_function +__make_stacks_executable (void **stack_endp) +{ + /* First the main thread's stack. */ + int err = EPERM; + if (err != 0) + return err; + +#ifdef NEED_SEPARATE_REGISTER_STACK + const size_t pagemask = ~(__getpagesize () - 1); +#endif + + lll_lock (stack_cache_lock, LLL_PRIVATE); + + list_t *runp; + list_for_each (runp, &stack_used) + { + err = change_stack_perm (list_entry (runp, struct pthread, list) +#ifdef NEED_SEPARATE_REGISTER_STACK + , pagemask +#endif + ); + if (err != 0) + break; + } + + /* Also change the permission for the currently unused stacks. This + might be wasted time but better spend it here than adding a check + in the fast path. */ + if (err == 0) + list_for_each (runp, &stack_cache) + { + err = change_stack_perm (list_entry (runp, struct pthread, list) +#ifdef NEED_SEPARATE_REGISTER_STACK + , pagemask +#endif + ); + if (err != 0) + break; + } + + lll_unlock (stack_cache_lock, LLL_PRIVATE); + + return err; +} + + +/* In case of a fork() call the memory allocation in the child will be + the same but only one thread is running. All stacks except that of + the one running thread are not used anymore. We have to recycle + them. */ +void +__reclaim_stacks (void) +{ + struct pthread *self = (struct pthread *) THREAD_SELF; + + /* No locking necessary. The caller is the only stack in use. But + we have to be aware that we might have interrupted a list + operation. */ + + if (in_flight_stack != 0) + { + bool add_p = in_flight_stack & 1; + list_t *elem = (list_t *) (in_flight_stack & ~UINTMAX_C (1)); + + if (add_p) + { + /* We always add at the beginning of the list. So in this + case we only need to check the beginning of these lists. */ + int check_list (list_t *l) + { + if (l->next->prev != l) + { + assert (l->next->prev == elem); + + elem->next = l->next; + elem->prev = l; + l->next = elem; + + return 1; + } + + return 0; + } + + if (check_list (&stack_used) == 0) + (void) check_list (&stack_cache); + } + else + { + /* We can simply always replay the delete operation. */ + elem->next->prev = elem->prev; + elem->prev->next = elem->next; + } + } + + /* Mark all stacks except the still running one as free. */ + list_t *runp; + list_for_each (runp, &stack_used) + { + struct pthread *curp = list_entry (runp, struct pthread, list); + if (curp != self) + { + /* This marks the stack as free. */ + curp->tid = 0; + + /* The PID field must be initialized for the new process. */ + curp->pid = self->pid; + + /* Account for the size of the stack. */ + stack_cache_actsize += curp->stackblock_size; + + if (curp->specific_used) + { + /* Clear the thread-specific data. */ + memset (curp->specific_1stblock, '\0', + sizeof (curp->specific_1stblock)); + + curp->specific_used = false; + + size_t cnt; + for (cnt = 1; cnt < PTHREAD_KEY_1STLEVEL_SIZE; ++cnt) + if (curp->specific[cnt] != NULL) + { + memset (curp->specific[cnt], '\0', + sizeof (curp->specific_1stblock)); + + /* We have allocated the block which we do not + free here so re-set the bit. */ + curp->specific_used = true; + } + } + } + } + + /* Reset the PIDs in any cached stacks. */ + list_for_each (runp, &stack_cache) + { + struct pthread *curp = list_entry (runp, struct pthread, list); + curp->pid = self->pid; + } + + /* Add the stack of all running threads to the cache. */ + list_splice (&stack_used, &stack_cache); + + /* Remove the entry for the current thread to from the cache list + and add it to the list of running threads. Which of the two + lists is decided by the user_stack flag. */ + stack_list_del (&self->list); + + /* Re-initialize the lists for all the threads. */ + INIT_LIST_HEAD (&stack_used); + INIT_LIST_HEAD (&__stack_user); + + if (__builtin_expect (THREAD_GETMEM (self, user_stack), 0)) + list_add (&self->list, &__stack_user); + else + list_add (&self->list, &stack_used); + + /* There is one thread running. */ + __nptl_nthreads = 1; + + in_flight_stack = 0; + + /* Initialize the lock. */ + stack_cache_lock = LLL_LOCK_INITIALIZER; +} + + +#if HP_TIMING_AVAIL +# undef __find_thread_by_id +/* Find a thread given the thread ID. */ +attribute_hidden +struct pthread * +__find_thread_by_id (pid_t tid) +{ + struct pthread *result = NULL; + + lll_lock (stack_cache_lock, LLL_PRIVATE); + + /* Iterate over the list with system-allocated threads first. */ + list_t *runp; + list_for_each (runp, &stack_used) + { + struct pthread *curp; + + curp = list_entry (runp, struct pthread, list); + + if (curp->tid == tid) + { + result = curp; + goto out; + } + } + + /* Now the list with threads using user-allocated stacks. */ + list_for_each (runp, &__stack_user) + { + struct pthread *curp; + + curp = list_entry (runp, struct pthread, list); + + if (curp->tid == tid) + { + result = curp; + goto out; + } + } + + out: + lll_unlock (stack_cache_lock, LLL_PRIVATE); + + return result; +} +#endif + + +static void +internal_function +setxid_mark_thread (struct xid_command *cmdp, struct pthread *t) +{ + int ch; + + /* Don't let the thread exit before the setxid handler runs. */ + t->setxid_futex = 0; + + do + { + ch = t->cancelhandling; + + /* If the thread is exiting right now, ignore it. */ + if ((ch & EXITING_BITMASK) != 0) + return; + } + while (atomic_compare_and_exchange_bool_acq (&t->cancelhandling, + ch | SETXID_BITMASK, ch)); +} + + +static void +internal_function +setxid_unmark_thread (struct xid_command *cmdp, struct pthread *t) +{ + int ch; + + do + { + ch = t->cancelhandling; + if ((ch & SETXID_BITMASK) == 0) + return; + } + while (atomic_compare_and_exchange_bool_acq (&t->cancelhandling, + ch & ~SETXID_BITMASK, ch)); + + /* Release the futex just in case. */ + t->setxid_futex = 1; + lll_futex_wake (&t->setxid_futex, 1, LLL_PRIVATE); +} + + +static int +internal_function +setxid_signal_thread (struct xid_command *cmdp, struct pthread *t) +{ + if ((t->cancelhandling & SETXID_BITMASK) == 0) + return 0; + + int val; + INTERNAL_SYSCALL_DECL (err); +#if __ASSUME_TGKILL + val = INTERNAL_SYSCALL (tgkill, err, 3, THREAD_GETMEM (THREAD_SELF, pid), + t->tid, SIGSETXID); +#else +# ifdef __NR_tgkill + val = INTERNAL_SYSCALL (tgkill, err, 3, THREAD_GETMEM (THREAD_SELF, pid), + t->tid, SIGSETXID); + if (INTERNAL_SYSCALL_ERROR_P (val, err) + && INTERNAL_SYSCALL_ERRNO (val, err) == ENOSYS) +# endif + val = INTERNAL_SYSCALL (tkill, err, 2, t->tid, SIGSETXID); +#endif + + /* If this failed, it must have had not started yet or else exited. */ + if (!INTERNAL_SYSCALL_ERROR_P (val, err)) + { + atomic_increment (&cmdp->cntr); + return 1; + } + else + return 0; +} + + +int +attribute_hidden +__nptl_setxid (struct xid_command *cmdp) +{ + int signalled; + int result; + lll_lock (stack_cache_lock, LLL_PRIVATE); + + __xidcmd = cmdp; + cmdp->cntr = 0; + + struct pthread *self = THREAD_SELF; + + /* Iterate over the list with system-allocated threads first. */ + list_t *runp; + list_for_each (runp, &stack_used) + { + struct pthread *t = list_entry (runp, struct pthread, list); + if (t == self) + continue; + + setxid_mark_thread (cmdp, t); + } + + /* Now the list with threads using user-allocated stacks. */ + list_for_each (runp, &__stack_user) + { + struct pthread *t = list_entry (runp, struct pthread, list); + if (t == self) + continue; + + setxid_mark_thread (cmdp, t); + } + + /* Iterate until we don't succeed in signalling anyone. That means + we have gotten all running threads, and their children will be + automatically correct once started. */ + do + { + signalled = 0; + + list_for_each (runp, &stack_used) + { + struct pthread *t = list_entry (runp, struct pthread, list); + if (t == self) + continue; + + signalled += setxid_signal_thread (cmdp, t); + } + + list_for_each (runp, &__stack_user) + { + struct pthread *t = list_entry (runp, struct pthread, list); + if (t == self) + continue; + + signalled += setxid_signal_thread (cmdp, t); + } + + int cur = cmdp->cntr; + while (cur != 0) + { + lll_futex_wait (&cmdp->cntr, cur, LLL_PRIVATE); + cur = cmdp->cntr; + } + } + while (signalled != 0); + + /* Clean up flags, so that no thread blocks during exit waiting + for a signal which will never come. */ + list_for_each (runp, &stack_used) + { + struct pthread *t = list_entry (runp, struct pthread, list); + if (t == self) + continue; + + setxid_unmark_thread (cmdp, t); + } + + list_for_each (runp, &__stack_user) + { + struct pthread *t = list_entry (runp, struct pthread, list); + if (t == self) + continue; + + setxid_unmark_thread (cmdp, t); + } + + /* This must be last, otherwise the current thread might not have + permissions to send SIGSETXID syscall to the other threads. */ + INTERNAL_SYSCALL_DECL (err); + result = INTERNAL_SYSCALL_NCS (cmdp->syscall_no, err, 3, + cmdp->id[0], cmdp->id[1], cmdp->id[2]); + if (INTERNAL_SYSCALL_ERROR_P (result, err)) + { + __set_errno (INTERNAL_SYSCALL_ERRNO (result, err)); + result = -1; + } + + lll_unlock (stack_cache_lock, LLL_PRIVATE); + return result; +} + +static inline void __attribute__((always_inline)) +init_one_static_tls (struct pthread *curp, struct link_map *map) +{ + dtv_t *dtv = GET_DTV (TLS_TPADJ (curp)); +# if defined(TLS_TCB_AT_TP) + void *dest = (char *) curp - map->l_tls_offset; +# elif defined(TLS_DTV_AT_TP) + void *dest = (char *) curp + map->l_tls_offset + TLS_PRE_TCB_SIZE; +# else +# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined" +# endif + + /* Fill in the DTV slot so that a later LD/GD access will find it. */ + dtv[map->l_tls_modid].pointer.val = dest; + dtv[map->l_tls_modid].pointer.is_static = true; + + /* Initialize the memory. */ + memset (mempcpy (dest, map->l_tls_initimage, map->l_tls_initimage_size), + '\0', map->l_tls_blocksize - map->l_tls_initimage_size); +} + +void +attribute_hidden +__pthread_init_static_tls (struct link_map *map) +{ + lll_lock (stack_cache_lock, LLL_PRIVATE); + + /* Iterate over the list with system-allocated threads first. */ + list_t *runp; + list_for_each (runp, &stack_used) + init_one_static_tls (list_entry (runp, struct pthread, list), map); + + /* Now the list with threads using user-allocated stacks. */ + list_for_each (runp, &__stack_user) + init_one_static_tls (list_entry (runp, struct pthread, list), map); + + lll_unlock (stack_cache_lock, LLL_PRIVATE); +} + + +void +attribute_hidden +__wait_lookup_done (void) +{ + lll_lock (stack_cache_lock, LLL_PRIVATE); + + struct pthread *self = THREAD_SELF; + + /* Iterate over the list with system-allocated threads first. */ + list_t *runp; + list_for_each (runp, &stack_used) + { + struct pthread *t = list_entry (runp, struct pthread, list); + if (t == self || t->header.gscope_flag == THREAD_GSCOPE_FLAG_UNUSED) + continue; + + int *const gscope_flagp = &t->header.gscope_flag; + + /* We have to wait until this thread is done with the global + scope. First tell the thread that we are waiting and + possibly have to be woken. */ + if (atomic_compare_and_exchange_bool_acq (gscope_flagp, + THREAD_GSCOPE_FLAG_WAIT, + THREAD_GSCOPE_FLAG_USED)) + continue; + + do + lll_futex_wait (gscope_flagp, THREAD_GSCOPE_FLAG_WAIT, LLL_PRIVATE); + while (*gscope_flagp == THREAD_GSCOPE_FLAG_WAIT); + } + + /* Now the list with threads using user-allocated stacks. */ + list_for_each (runp, &__stack_user) + { + struct pthread *t = list_entry (runp, struct pthread, list); + if (t == self || t->header.gscope_flag == THREAD_GSCOPE_FLAG_UNUSED) + continue; + + int *const gscope_flagp = &t->header.gscope_flag; + + /* We have to wait until this thread is done with the global + scope. First tell the thread that we are waiting and + possibly have to be woken. */ + if (atomic_compare_and_exchange_bool_acq (gscope_flagp, + THREAD_GSCOPE_FLAG_WAIT, + THREAD_GSCOPE_FLAG_USED)) + continue; + + do + lll_futex_wait (gscope_flagp, THREAD_GSCOPE_FLAG_WAIT, LLL_PRIVATE); + while (*gscope_flagp == THREAD_GSCOPE_FLAG_WAIT); + } + + lll_unlock (stack_cache_lock, LLL_PRIVATE); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/banner.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/banner.h new file mode 100644 index 00000000..9982f428 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/banner.h @@ -0,0 +1 @@ +"Native POSIX Threads Library by Ulrich Drepper et al, uClibc port by Steven Hill\n" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/cancellation.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/cancellation.c new file mode 100644 index 00000000..eac7973d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/cancellation.c @@ -0,0 +1,100 @@ +/* Copyright (C) 2002, 2003, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include "pthreadP.h" + + +/* The next two functions are similar to pthread_setcanceltype() but + more specialized for the use in the cancelable functions like write(). + They do not need to check parameters etc. */ +int +attribute_hidden +__pthread_enable_asynccancel (void) +{ + struct pthread *self = THREAD_SELF; + int oldval = THREAD_GETMEM (self, cancelhandling); + + while (1) + { + int newval = oldval | CANCELTYPE_BITMASK; + + if (newval == oldval) + break; + + int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling, newval, + oldval); + if (__builtin_expect (curval == oldval, 1)) + { + if (CANCEL_ENABLED_AND_CANCELED_AND_ASYNCHRONOUS (newval)) + { + THREAD_SETMEM (self, result, PTHREAD_CANCELED); + __do_cancel (); + } + + break; + } + + /* Prepare the next round. */ + oldval = curval; + } + + return oldval; +} + + +void +internal_function attribute_hidden +__pthread_disable_asynccancel (int oldtype) +{ + /* If asynchronous cancellation was enabled before we do not have + anything to do. */ + if (oldtype & CANCELTYPE_BITMASK) + return; + + struct pthread *self = THREAD_SELF; + int newval; + + int oldval = THREAD_GETMEM (self, cancelhandling); + + while (1) + { + newval = oldval & ~CANCELTYPE_BITMASK; + + int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling, newval, + oldval); + if (__builtin_expect (curval == oldval, 1)) + break; + + /* Prepare the next round. */ + oldval = curval; + } + + /* We cannot return when we are being canceled. Upon return the + thread might be things which would have to be undone. The + following loop should loop until the cancellation signal is + delivered. */ + while (__builtin_expect ((newval & (CANCELING_BITMASK | CANCELED_BITMASK)) + == CANCELING_BITMASK, 0)) + { + lll_futex_wait (&self->cancelhandling, newval, LLL_PRIVATE); + newval = THREAD_GETMEM (self, cancelhandling); + } +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/cleanup.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/cleanup.c new file mode 100644 index 00000000..af828c49 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/cleanup.c @@ -0,0 +1,49 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include "pthreadP.h" + + +void +__cleanup_fct_attribute +__pthread_register_cancel (__pthread_unwind_buf_t *buf) +{ + struct pthread_unwind_buf *ibuf = (struct pthread_unwind_buf *) buf; + struct pthread *self = THREAD_SELF; + + /* Store old info. */ + ibuf->priv.data.prev = THREAD_GETMEM (self, cleanup_jmp_buf); + ibuf->priv.data.cleanup = THREAD_GETMEM (self, cleanup); + + /* Store the new cleanup handler info. */ + THREAD_SETMEM (self, cleanup_jmp_buf, (struct pthread_unwind_buf *) buf); +} +hidden_def (__pthread_register_cancel) + + +void +__cleanup_fct_attribute +__pthread_unregister_cancel (__pthread_unwind_buf_t *buf) +{ + struct pthread_unwind_buf *ibuf = (struct pthread_unwind_buf *) buf; + + THREAD_SETMEM (THREAD_SELF, cleanup_jmp_buf, ibuf->priv.data.prev); +} +hidden_def (__pthread_unregister_cancel) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/cleanup_compat.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/cleanup_compat.c new file mode 100644 index 00000000..77d714f7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/cleanup_compat.c @@ -0,0 +1,55 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include "pthreadP.h" + + +void +_pthread_cleanup_push ( + struct _pthread_cleanup_buffer *buffer, + void (*routine) (void *), + void *arg) +{ + struct pthread *self = THREAD_SELF; + + buffer->__routine = routine; + buffer->__arg = arg; + buffer->__prev = THREAD_GETMEM (self, cleanup); + + THREAD_SETMEM (self, cleanup, buffer); +} +strong_alias (_pthread_cleanup_push, __pthread_cleanup_push) + + +void +_pthread_cleanup_pop ( + struct _pthread_cleanup_buffer *buffer, + int execute) +{ + struct pthread *self __attribute ((unused)) = THREAD_SELF; + + THREAD_SETMEM (self, cleanup, buffer->__prev); + + /* If necessary call the cleanup routine after we removed the + current cleanup block from the list. */ + if (execute) + buffer->__routine (buffer->__arg); +} +strong_alias (_pthread_cleanup_pop, __pthread_cleanup_pop) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/cleanup_defer.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/cleanup_defer.c new file mode 100644 index 00000000..498d9557 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/cleanup_defer.c @@ -0,0 +1,92 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include "pthreadP.h" + + +void +__cleanup_fct_attribute +__pthread_register_cancel_defer (__pthread_unwind_buf_t *buf) +{ + struct pthread_unwind_buf *ibuf = (struct pthread_unwind_buf *) buf; + struct pthread *self = THREAD_SELF; + + /* Store old info. */ + ibuf->priv.data.prev = THREAD_GETMEM (self, cleanup_jmp_buf); + ibuf->priv.data.cleanup = THREAD_GETMEM (self, cleanup); + + int cancelhandling = THREAD_GETMEM (self, cancelhandling); + + /* Disable asynchronous cancellation for now. */ + if (__builtin_expect (cancelhandling & CANCELTYPE_BITMASK, 0)) + while (1) + { + int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling, + cancelhandling + & ~CANCELTYPE_BITMASK, + cancelhandling); + if (__builtin_expect (curval == cancelhandling, 1)) + /* Successfully replaced the value. */ + break; + + /* Prepare for the next round. */ + cancelhandling = curval; + } + + ibuf->priv.data.canceltype = (cancelhandling & CANCELTYPE_BITMASK + ? PTHREAD_CANCEL_ASYNCHRONOUS + : PTHREAD_CANCEL_DEFERRED); + + /* Store the new cleanup handler info. */ + THREAD_SETMEM (self, cleanup_jmp_buf, (struct pthread_unwind_buf *) buf); +} + + +void +__cleanup_fct_attribute +__pthread_unregister_cancel_restore (__pthread_unwind_buf_t *buf) +{ + struct pthread *self = THREAD_SELF; + struct pthread_unwind_buf *ibuf = (struct pthread_unwind_buf *) buf; + + THREAD_SETMEM (self, cleanup_jmp_buf, ibuf->priv.data.prev); + + int cancelhandling; + if (ibuf->priv.data.canceltype != PTHREAD_CANCEL_DEFERRED + && ((cancelhandling = THREAD_GETMEM (self, cancelhandling)) + & CANCELTYPE_BITMASK) == 0) + { + while (1) + { + int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling, + cancelhandling + | CANCELTYPE_BITMASK, + cancelhandling); + if (__builtin_expect (curval == cancelhandling, 1)) + /* Successfully replaced the value. */ + break; + + /* Prepare for the next round. */ + cancelhandling = curval; + } + + CANCELLATION_P (self); + } +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/cleanup_defer_compat.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/cleanup_defer_compat.c new file mode 100644 index 00000000..95fa4a06 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/cleanup_defer_compat.c @@ -0,0 +1,100 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "pthreadP.h" + + +void +attribute_protected +_pthread_cleanup_push_defer ( + struct _pthread_cleanup_buffer *buffer, + void (*routine) (void *), + void *arg) +{ + struct pthread *self = THREAD_SELF; + + buffer->__routine = routine; + buffer->__arg = arg; + buffer->__prev = THREAD_GETMEM (self, cleanup); + + int cancelhandling = THREAD_GETMEM (self, cancelhandling); + + /* Disable asynchronous cancellation for now. */ + if (__builtin_expect (cancelhandling & CANCELTYPE_BITMASK, 0)) + while (1) + { + int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling, + cancelhandling + & ~CANCELTYPE_BITMASK, + cancelhandling); + if (__builtin_expect (curval == cancelhandling, 1)) + /* Successfully replaced the value. */ + break; + + /* Prepare for the next round. */ + cancelhandling = curval; + } + + buffer->__canceltype = (cancelhandling & CANCELTYPE_BITMASK + ? PTHREAD_CANCEL_ASYNCHRONOUS + : PTHREAD_CANCEL_DEFERRED); + + THREAD_SETMEM (self, cleanup, buffer); +} +strong_alias (_pthread_cleanup_push_defer, __pthread_cleanup_push_defer) + + +void +attribute_protected +_pthread_cleanup_pop_restore ( + struct _pthread_cleanup_buffer *buffer, + int execute) +{ + struct pthread *self = THREAD_SELF; + + THREAD_SETMEM (self, cleanup, buffer->__prev); + + int cancelhandling; + if (__builtin_expect (buffer->__canceltype != PTHREAD_CANCEL_DEFERRED, 0) + && ((cancelhandling = THREAD_GETMEM (self, cancelhandling)) + & CANCELTYPE_BITMASK) == 0) + { + while (1) + { + int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling, + cancelhandling + | CANCELTYPE_BITMASK, + cancelhandling); + if (__builtin_expect (curval == cancelhandling, 1)) + /* Successfully replaced the value. */ + break; + + /* Prepare for the next round. */ + cancelhandling = curval; + } + + CANCELLATION_P (self); + } + + /* If necessary call the cleanup routine after we removed the + current cleanup block from the list. */ + if (execute) + buffer->__routine (buffer->__arg); +} +strong_alias (_pthread_cleanup_pop_restore, __pthread_cleanup_pop_restore) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/cleanup_routine.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/cleanup_routine.c new file mode 100644 index 00000000..cbf23183 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/cleanup_routine.c @@ -0,0 +1,28 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + + +void +__pthread_cleanup_routine (struct __pthread_cleanup_frame *f) +{ + if (f->__do_it) + f->__cancel_routine (f->__cancel_arg); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/descr.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/descr.h new file mode 100644 index 00000000..40f552d6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/descr.h @@ -0,0 +1,377 @@ +/* Copyright (C) 2002-2006, 2007, 2008, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _DESCR_H +#define _DESCR_H 1 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../nptl_db/thread_db.h" +#include +#ifdef HAVE_FORCED_UNWIND +# include +#endif +#define __need_res_state +#include +#include +#include "uClibc-glue.h" + +#ifndef TCB_ALIGNMENT +# define TCB_ALIGNMENT sizeof (double) +#endif + + +/* We keep thread specific data in a special data structure, a two-level + array. The top-level array contains pointers to dynamically allocated + arrays of a certain number of data pointers. So we can implement a + sparse array. Each dynamic second-level array has + PTHREAD_KEY_2NDLEVEL_SIZE + entries. This value shouldn't be too large. */ +#define PTHREAD_KEY_2NDLEVEL_SIZE 32 + +/* We need to address PTHREAD_KEYS_MAX key with PTHREAD_KEY_2NDLEVEL_SIZE + keys in each subarray. */ +#define PTHREAD_KEY_1STLEVEL_SIZE \ + ((PTHREAD_KEYS_MAX + PTHREAD_KEY_2NDLEVEL_SIZE - 1) \ + / PTHREAD_KEY_2NDLEVEL_SIZE) + + + + +/* Internal version of the buffer to store cancellation handler + information. */ +struct pthread_unwind_buf +{ + struct + { + __jmp_buf jmp_buf; + int mask_was_saved; + } cancel_jmp_buf[1]; + + union + { + /* This is the placeholder of the public version. */ + void *pad[4]; + + struct + { + /* Pointer to the previous cleanup buffer. */ + struct pthread_unwind_buf *prev; + + /* Backward compatibility: state of the old-style cleanup + handler at the time of the previous new-style cleanup handler + installment. */ + struct _pthread_cleanup_buffer *cleanup; + + /* Cancellation type before the push call. */ + int canceltype; + } data; + } priv; +}; + + +/* Opcodes and data types for communication with the signal handler to + change user/group IDs. */ +struct xid_command +{ + int syscall_no; + long int id[3]; + volatile int cntr; +}; + + +/* Data structure used by the kernel to find robust futexes. */ +struct robust_list_head +{ + void *list; + long int futex_offset; + void *list_op_pending; +}; + + +/* Data strcture used to handle thread priority protection. */ +struct priority_protection_data +{ + int priomax; + unsigned int priomap[]; +}; + + +/* Thread descriptor data structure. */ +struct pthread +{ + union + { +#if !defined(TLS_DTV_AT_TP) + /* This overlaps the TCB as used for TLS without threads (see tls.h). */ + tcbhead_t header; +#else + struct + { + int multiple_threads; + int gscope_flag; +# ifndef __ASSUME_PRIVATE_FUTEX + int private_futex; +# endif + } header; +#endif + + /* This extra padding has no special purpose, and this structure layout + is private and subject to change without affecting the official ABI. + We just have it here in case it might be convenient for some + implementation-specific instrumentation hack or suchlike. */ + void *__padding[24]; + }; + + /* This descriptor's link on the `stack_used' or `__stack_user' list. */ + list_t list; + + /* Thread ID - which is also a 'is this thread descriptor (and + therefore stack) used' flag. */ + pid_t tid; + + /* Process ID - thread group ID in kernel speak. */ + pid_t pid; + + /* List of robust mutexes the thread is holding. */ +#ifdef __PTHREAD_MUTEX_HAVE_PREV + void *robust_prev; + struct robust_list_head robust_head; + + /* The list above is strange. It is basically a double linked list + but the pointer to the next/previous element of the list points + in the middle of the object, the __next element. Whenever + casting to __pthread_list_t we need to adjust the pointer + first. */ +# define QUEUE_PTR_ADJUST (offsetof (__pthread_list_t, __next)) + +# define ENQUEUE_MUTEX_BOTH(mutex, val) \ + do { \ + __pthread_list_t *next = (__pthread_list_t *) \ + ((((uintptr_t) THREAD_GETMEM (THREAD_SELF, robust_head.list)) & ~1ul) \ + - QUEUE_PTR_ADJUST); \ + next->__prev = (void *) &mutex->__data.__list.__next; \ + mutex->__data.__list.__next = THREAD_GETMEM (THREAD_SELF, \ + robust_head.list); \ + mutex->__data.__list.__prev = (void *) &THREAD_SELF->robust_head; \ + THREAD_SETMEM (THREAD_SELF, robust_head.list, \ + (void *) (((uintptr_t) &mutex->__data.__list.__next) \ + | val)); \ + } while (0) +# define DEQUEUE_MUTEX(mutex) \ + do { \ + __pthread_list_t *next = (__pthread_list_t *) \ + ((char *) (((uintptr_t) mutex->__data.__list.__next) & ~1ul) \ + - QUEUE_PTR_ADJUST); \ + next->__prev = mutex->__data.__list.__prev; \ + __pthread_list_t *prev = (__pthread_list_t *) \ + ((char *) (((uintptr_t) mutex->__data.__list.__prev) & ~1ul) \ + - QUEUE_PTR_ADJUST); \ + prev->__next = mutex->__data.__list.__next; \ + mutex->__data.__list.__prev = NULL; \ + mutex->__data.__list.__next = NULL; \ + } while (0) +#else + union + { + __pthread_slist_t robust_list; + struct robust_list_head robust_head; + }; + +# define ENQUEUE_MUTEX_BOTH(mutex, val) \ + do { \ + mutex->__data.__list.__next \ + = THREAD_GETMEM (THREAD_SELF, robust_list.__next); \ + THREAD_SETMEM (THREAD_SELF, robust_list.__next, \ + (void *) (((uintptr_t) &mutex->__data.__list) | val)); \ + } while (0) +# define DEQUEUE_MUTEX(mutex) \ + do { \ + __pthread_slist_t *runp = (__pthread_slist_t *) \ + (((uintptr_t) THREAD_GETMEM (THREAD_SELF, robust_list.__next)) & ~1ul); \ + if (runp == &mutex->__data.__list) \ + THREAD_SETMEM (THREAD_SELF, robust_list.__next, runp->__next); \ + else \ + { \ + __pthread_slist_t *next = (__pthread_slist_t *) \ + (((uintptr_t) runp->__next) & ~1ul); \ + while (next != &mutex->__data.__list) \ + { \ + runp = next; \ + next = (__pthread_slist_t *) (((uintptr_t) runp->__next) & ~1ul); \ + } \ + \ + runp->__next = next->__next; \ + mutex->__data.__list.__next = NULL; \ + } \ + } while (0) +#endif +#define ENQUEUE_MUTEX(mutex) ENQUEUE_MUTEX_BOTH (mutex, 0) +#define ENQUEUE_MUTEX_PI(mutex) ENQUEUE_MUTEX_BOTH (mutex, 1) + + /* List of cleanup buffers. */ + struct _pthread_cleanup_buffer *cleanup; + + /* Unwind information. */ + struct pthread_unwind_buf *cleanup_jmp_buf; +#define HAVE_CLEANUP_JMP_BUF + + /* Flags determining processing of cancellation. */ + int cancelhandling; + /* Bit set if cancellation is disabled. */ +#define CANCELSTATE_BIT 0 +#define CANCELSTATE_BITMASK (0x01 << CANCELSTATE_BIT) + /* Bit set if asynchronous cancellation mode is selected. */ +#define CANCELTYPE_BIT 1 +#define CANCELTYPE_BITMASK (0x01 << CANCELTYPE_BIT) + /* Bit set if canceling has been initiated. */ +#define CANCELING_BIT 2 +#define CANCELING_BITMASK (0x01 << CANCELING_BIT) + /* Bit set if canceled. */ +#define CANCELED_BIT 3 +#define CANCELED_BITMASK (0x01 << CANCELED_BIT) + /* Bit set if thread is exiting. */ +#define EXITING_BIT 4 +#define EXITING_BITMASK (0x01 << EXITING_BIT) + /* Bit set if thread terminated and TCB is freed. */ +#define TERMINATED_BIT 5 +#define TERMINATED_BITMASK (0x01 << TERMINATED_BIT) + /* Bit set if thread is supposed to change XID. */ +#define SETXID_BIT 6 +#define SETXID_BITMASK (0x01 << SETXID_BIT) + /* Mask for the rest. Helps the compiler to optimize. */ +#define CANCEL_RESTMASK 0xffffff80 + +#define CANCEL_ENABLED_AND_CANCELED(value) \ + (((value) & (CANCELSTATE_BITMASK | CANCELED_BITMASK | EXITING_BITMASK \ + | CANCEL_RESTMASK | TERMINATED_BITMASK)) == CANCELED_BITMASK) +#define CANCEL_ENABLED_AND_CANCELED_AND_ASYNCHRONOUS(value) \ + (((value) & (CANCELSTATE_BITMASK | CANCELTYPE_BITMASK | CANCELED_BITMASK \ + | EXITING_BITMASK | CANCEL_RESTMASK | TERMINATED_BITMASK)) \ + == (CANCELTYPE_BITMASK | CANCELED_BITMASK)) + + /* Flags. Including those copied from the thread attribute. */ + int flags; + + /* We allocate one block of references here. This should be enough + to avoid allocating any memory dynamically for most applications. */ + struct pthread_key_data + { + /* Sequence number. We use uintptr_t to not require padding on + 32- and 64-bit machines. On 64-bit machines it helps to avoid + wrapping, too. */ + uintptr_t seq; + + /* Data pointer. */ + void *data; + } specific_1stblock[PTHREAD_KEY_2NDLEVEL_SIZE]; + + /* Two-level array for the thread-specific data. */ + struct pthread_key_data *specific[PTHREAD_KEY_1STLEVEL_SIZE]; + + /* Flag which is set when specific data is set. */ + bool specific_used; + + /* True if events must be reported. */ + bool report_events; + + /* True if the user provided the stack. */ + bool user_stack; + + /* True if thread must stop at startup time. */ + bool stopped_start; + + /* The parent's cancel handling at the time of the pthread_create + call. This might be needed to undo the effects of a cancellation. */ + int parent_cancelhandling; + + /* Lock to synchronize access to the descriptor. */ + int lock; + + /* Lock for synchronizing setxid calls. */ + int setxid_futex; + +#if HP_TIMING_AVAIL + /* Offset of the CPU clock at start thread start time. */ + hp_timing_t cpuclock_offset; +#endif + + /* If the thread waits to join another one the ID of the latter is + stored here. + + In case a thread is detached this field contains a pointer of the + TCB if the thread itself. This is something which cannot happen + in normal operation. */ + struct pthread *joinid; + /* Check whether a thread is detached. */ +#define IS_DETACHED(pd) ((pd)->joinid == (pd)) + + /* The result of the thread function. */ + void *result; + + /* Scheduling parameters for the new thread. */ + struct sched_param schedparam; + int schedpolicy; + + /* Start position of the code to be executed and the argument passed + to the function. */ + void *(*start_routine) (void *); + void *arg; + + /* Debug state. */ + td_eventbuf_t eventbuf; + /* Next descriptor with a pending event. */ + struct pthread *nextevent; + +#ifdef HAVE_FORCED_UNWIND + /* Machine-specific unwind info. */ + struct _Unwind_Exception exc; +#endif + + /* If nonzero pointer to area allocated for the stack and its + size. */ + void *stackblock; + size_t stackblock_size; + /* Size of the included guard area. */ + size_t guardsize; + /* This is what the user specified and what we will report. */ + size_t reported_guardsize; + + /* Thread Priority Protection data. */ + struct priority_protection_data *tpp; + + /* Resolver state. */ + struct __res_state res; + + /* This member must be last. */ + char end_padding[]; + +#define PTHREAD_STRUCT_END_PADDING \ + (sizeof (struct pthread) - offsetof (struct pthread, end_padding)) +} __attribute ((aligned (TCB_ALIGNMENT))); + + +#endif /* descr.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/errno_location.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/errno_location.c new file mode 100644 index 00000000..74589389 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/errno_location.c @@ -0,0 +1 @@ +#include diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/events.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/events.c new file mode 100644 index 00000000..df97e54f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/events.c @@ -0,0 +1,34 @@ +/* Event functions used while debugging. + Copyright (C) 1999, 2000, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* The functions contained here do nothing, they just return. */ + +#include "pthreadP.h" + +void +__nptl_create_event (void) +{ +} +hidden_def (__nptl_create_event) + +void +__nptl_death_event (void) +{ +} +hidden_def (__nptl_death_event) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/forward.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/forward.c new file mode 100644 index 00000000..7878334a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/forward.c @@ -0,0 +1,165 @@ +/* Copyright (C) 2002, 2003, 2004, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + +#include +#include + + +/* Pointers to the libc functions. */ +struct pthread_functions __libc_pthread_functions attribute_hidden; +int __libc_pthread_functions_init attribute_hidden; + + +#define FORWARD2(name, rettype, decl, params, defaction) \ +rettype \ +name decl \ +{ \ + if (!__libc_pthread_functions_init) { \ + defaction; \ + } else { \ + return PTHFCT_CALL (ptr_##name, params); \ + } \ +} + +#define FORWARD(name, decl, params, defretval) \ + FORWARD2 (name, int, decl, params, return defretval) + + +FORWARD (pthread_attr_destroy, (pthread_attr_t *attr), (attr), 0) + +FORWARD (__pthread_attr_init_2_1, (pthread_attr_t *attr), (attr), 0) +weak_alias(__pthread_attr_init_2_1, pthread_attr_init) + +FORWARD (pthread_attr_getdetachstate, + (const pthread_attr_t *attr, int *detachstate), (attr, detachstate), + 0) +FORWARD (pthread_attr_setdetachstate, (pthread_attr_t *attr, int detachstate), + (attr, detachstate), 0) + +FORWARD (pthread_attr_getinheritsched, + (const pthread_attr_t *attr, int *inherit), (attr, inherit), 0) +FORWARD (pthread_attr_setinheritsched, (pthread_attr_t *attr, int inherit), + (attr, inherit), 0) + +FORWARD (pthread_attr_getschedparam, + (const pthread_attr_t *attr, struct sched_param *param), + (attr, param), 0) +FORWARD (pthread_attr_setschedparam, + (pthread_attr_t *attr, const struct sched_param *param), + (attr, param), 0) + +FORWARD (pthread_attr_getschedpolicy, + (const pthread_attr_t *attr, int *policy), (attr, policy), 0) +FORWARD (pthread_attr_setschedpolicy, (pthread_attr_t *attr, int policy), + (attr, policy), 0) + +FORWARD (pthread_attr_getscope, + (const pthread_attr_t *attr, int *scope), (attr, scope), 0) +FORWARD (pthread_attr_setscope, (pthread_attr_t *attr, int scope), + (attr, scope), 0) + + +FORWARD (pthread_condattr_destroy, (pthread_condattr_t *attr), (attr), 0) +FORWARD (pthread_condattr_init, (pthread_condattr_t *attr), (attr), 0) + +FORWARD (__pthread_cond_broadcast, (pthread_cond_t *cond), (cond), 0) +weak_alias(__pthread_cond_broadcast, pthread_cond_broadcast) + +FORWARD (__pthread_cond_destroy, (pthread_cond_t *cond), (cond), 0) +weak_alias(__pthread_cond_destroy, pthread_cond_destroy) + +FORWARD (__pthread_cond_init, + (pthread_cond_t *cond, const pthread_condattr_t *cond_attr), + (cond, cond_attr), 0) +weak_alias(__pthread_cond_init, pthread_cond_init) + +FORWARD (__pthread_cond_signal, (pthread_cond_t *cond), (cond), 0) +weak_alias(__pthread_cond_signal, pthread_cond_signal) + +FORWARD (__pthread_cond_wait, (pthread_cond_t *cond, pthread_mutex_t *mutex), + (cond, mutex), 0) +weak_alias(__pthread_cond_wait, pthread_cond_wait) + +FORWARD (__pthread_cond_timedwait, + (pthread_cond_t *cond, pthread_mutex_t *mutex, + const struct timespec *abstime), (cond, mutex, abstime), 0) +weak_alias(__pthread_cond_timedwait, pthread_cond_timedwait) + + +FORWARD (pthread_equal, (pthread_t thread1, pthread_t thread2), + (thread1, thread2), 1) + + +/* Use an alias to avoid warning, as pthread_exit is declared noreturn. */ +FORWARD2 (__pthread_exit, void, (void *retval), (retval), exit (EXIT_SUCCESS)) +strong_alias (__pthread_exit, pthread_exit); + + +FORWARD (pthread_getschedparam, + (pthread_t target_thread, int *policy, struct sched_param *param), + (target_thread, policy, param), 0) +FORWARD (pthread_setschedparam, + (pthread_t target_thread, int policy, + const struct sched_param *param), (target_thread, policy, param), 0) + + +FORWARD (pthread_mutex_destroy, (pthread_mutex_t *mutex), (mutex), 0) + +FORWARD (pthread_mutex_init, + (pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr), + (mutex, mutexattr), 0) + +FORWARD (pthread_mutex_lock, (pthread_mutex_t *mutex), (mutex), 0) +weak_alias (pthread_mutex_lock, __pthread_mutex_lock) + +FORWARD (pthread_mutex_unlock, (pthread_mutex_t *mutex), (mutex), 0) +weak_alias (pthread_mutex_unlock, __pthread_mutex_unlock) + +FORWARD2 (pthread_self, pthread_t, (void), (), return 0) + + +FORWARD (pthread_setcancelstate, (int state, int *oldstate), (state, oldstate), + 0) + +FORWARD (pthread_setcanceltype, (int type, int *oldtype), (type, oldtype), 0) + +#define return /* value is void */ +FORWARD2(_pthread_cleanup_push_defer, + void, (struct _pthread_cleanup_buffer *buffer, void (*routine)(void *), void *arg), + (buffer, routine, arg), + { buffer->__routine = routine; buffer->__arg = arg; }); + +FORWARD2(_pthread_cleanup_pop_restore, + void, (struct _pthread_cleanup_buffer *buffer, int execute), + (buffer, execute), + if (execute) { buffer->__routine(buffer->__arg); }); + +FORWARD2(__pthread_unwind, + void attribute_hidden __attribute ((noreturn)) __cleanup_fct_attribute, + (__pthread_unwind_buf_t *buf), (buf), { + /* We cannot call abort() here. */ + INTERNAL_SYSCALL_DECL (err); + INTERNAL_SYSCALL (kill, err, 1, SIGKILL); + }) +#undef return diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/herrno.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/herrno.c new file mode 100644 index 00000000..6e8339d4 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/herrno.c @@ -0,0 +1,35 @@ +/* Copyright (C) 1996,97,98,2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#undef h_errno + +#include + +/* We need to have the error status variable of the resolver + accessible in the libc. */ +extern __thread int h_errno; + + +/* When threaded, h_errno may be a per-thread variable. */ +int * +__h_errno_location (void) +{ + return &h_errno; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/init.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/init.c new file mode 100644 index 00000000..911293a6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/init.c @@ -0,0 +1,446 @@ +/* Copyright (C) 2002-2007, 2008, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +extern __typeof(sigaction) __libc_sigaction; + +/* Size and alignment of static TLS block. */ +size_t __static_tls_size; +size_t __static_tls_align_m1; + +#ifndef __ASSUME_SET_ROBUST_LIST +/* Negative if we do not have the system call and we can use it. */ +int __set_robust_list_avail; +# define set_robust_list_not_avail() \ + __set_robust_list_avail = -1 +#else +# define set_robust_list_not_avail() do { } while (0) +#endif + +#ifndef __ASSUME_FUTEX_CLOCK_REALTIME +/* Nonzero if we do not have FUTEX_CLOCK_REALTIME. */ +int __have_futex_clock_realtime; +# define __set_futex_clock_realtime() \ + __have_futex_clock_realtime = 1 +#else +#define __set_futex_clock_realtime() do { } while (0) +#endif + +/* Version of the library, used in libthread_db to detect mismatches. */ +static const char nptl_version[] __attribute_used__ = VERSION; + + +#ifndef SHARED +extern void __libc_setup_tls (size_t tcbsize, size_t tcbalign); +#endif + +#ifdef SHARED +static void nptl_freeres (void); + + +static const struct pthread_functions pthread_functions = + { + .ptr_pthread_attr_destroy = __pthread_attr_destroy, + .ptr___pthread_attr_init_2_1 = __pthread_attr_init_2_1, + .ptr_pthread_attr_getdetachstate = __pthread_attr_getdetachstate, + .ptr_pthread_attr_setdetachstate = __pthread_attr_setdetachstate, + .ptr_pthread_attr_getinheritsched = __pthread_attr_getinheritsched, + .ptr_pthread_attr_setinheritsched = __pthread_attr_setinheritsched, + .ptr_pthread_attr_getschedparam = __pthread_attr_getschedparam, + .ptr_pthread_attr_setschedparam = __pthread_attr_setschedparam, + .ptr_pthread_attr_getschedpolicy = __pthread_attr_getschedpolicy, + .ptr_pthread_attr_setschedpolicy = __pthread_attr_setschedpolicy, + .ptr_pthread_attr_getscope = __pthread_attr_getscope, + .ptr_pthread_attr_setscope = __pthread_attr_setscope, + .ptr_pthread_condattr_destroy = __pthread_condattr_destroy, + .ptr_pthread_condattr_init = __pthread_condattr_init, + .ptr___pthread_cond_broadcast = __pthread_cond_broadcast, + .ptr___pthread_cond_destroy = __pthread_cond_destroy, + .ptr___pthread_cond_init = __pthread_cond_init, + .ptr___pthread_cond_signal = __pthread_cond_signal, + .ptr___pthread_cond_wait = __pthread_cond_wait, + .ptr___pthread_cond_timedwait = __pthread_cond_timedwait, + .ptr_pthread_equal = __pthread_equal, + .ptr___pthread_exit = __pthread_exit, + .ptr_pthread_getschedparam = __pthread_getschedparam, + .ptr_pthread_setschedparam = __pthread_setschedparam, + .ptr_pthread_mutex_destroy = INTUSE(__pthread_mutex_destroy), + .ptr_pthread_mutex_init = INTUSE(__pthread_mutex_init), + .ptr_pthread_mutex_lock = INTUSE(__pthread_mutex_lock), + .ptr_pthread_mutex_unlock = INTUSE(__pthread_mutex_unlock), + .ptr_pthread_self = __pthread_self, + .ptr_pthread_setcancelstate = __pthread_setcancelstate, + .ptr_pthread_setcanceltype = __pthread_setcanceltype, + .ptr___pthread_cleanup_upto = __pthread_cleanup_upto, + .ptr___pthread_once = __pthread_once_internal, + .ptr___pthread_rwlock_rdlock = __pthread_rwlock_rdlock_internal, + .ptr___pthread_rwlock_wrlock = __pthread_rwlock_wrlock_internal, + .ptr___pthread_rwlock_unlock = __pthread_rwlock_unlock_internal, + .ptr___pthread_key_create = __pthread_key_create_internal, + .ptr___pthread_getspecific = __pthread_getspecific_internal, + .ptr___pthread_setspecific = __pthread_setspecific_internal, + .ptr__pthread_cleanup_push_defer = _pthread_cleanup_push_defer, + .ptr__pthread_cleanup_pop_restore = _pthread_cleanup_pop_restore, + .ptr_nthreads = &__nptl_nthreads, + .ptr___pthread_unwind = &__pthread_unwind, + .ptr__nptl_deallocate_tsd = __nptl_deallocate_tsd, + .ptr__nptl_setxid = __nptl_setxid, + /* For now only the stack cache needs to be freed. */ + .ptr_freeres = nptl_freeres + }; +# define ptr_pthread_functions &pthread_functions +#else +# define ptr_pthread_functions NULL +#endif + + +#ifdef SHARED +/* This function is called indirectly from the freeres code in libc. */ +static void +__libc_freeres_fn_section +nptl_freeres (void) +{ + __unwind_freeres (); + __free_stacks (0); +} +#endif + + +/* For asynchronous cancellation we use a signal. This is the handler. */ +static void +sigcancel_handler (int sig, siginfo_t *si, void *ctx) +{ +#ifdef __ASSUME_CORRECT_SI_PID + /* Determine the process ID. It might be negative if the thread is + in the middle of a fork() call. */ + pid_t pid = THREAD_GETMEM (THREAD_SELF, pid); + if (__builtin_expect (pid < 0, 0)) + pid = -pid; +#endif + + /* Safety check. It would be possible to call this function for + other signals and send a signal from another process. This is not + correct and might even be a security problem. Try to catch as + many incorrect invocations as possible. */ + if (sig != SIGCANCEL +#ifdef __ASSUME_CORRECT_SI_PID + /* Kernels before 2.5.75 stored the thread ID and not the process + ID in si_pid so we skip this test. */ + || si->si_pid != pid +#endif + || si->si_code != SI_TKILL) + return; + + struct pthread *self = THREAD_SELF; + + int oldval = THREAD_GETMEM (self, cancelhandling); + while (1) + { + /* We are canceled now. When canceled by another thread this flag + is already set but if the signal is directly send (internally or + from another process) is has to be done here. */ + int newval = oldval | CANCELING_BITMASK | CANCELED_BITMASK; + + if (oldval == newval || (oldval & EXITING_BITMASK) != 0) + /* Already canceled or exiting. */ + break; + + int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling, newval, + oldval); + if (curval == oldval) + { + /* Set the return value. */ + THREAD_SETMEM (self, result, PTHREAD_CANCELED); + + /* Make sure asynchronous cancellation is still enabled. */ + if ((newval & CANCELTYPE_BITMASK) != 0) + /* Run the registered destructors and terminate the thread. */ + __do_cancel (); + + break; + } + + oldval = curval; + } +} + + +struct xid_command *__xidcmd attribute_hidden; + +/* For asynchronous cancellation we use a signal. This is the handler. */ +static void +sighandler_setxid (int sig, siginfo_t *si, void *ctx) +{ +#ifdef __ASSUME_CORRECT_SI_PID + /* Determine the process ID. It might be negative if the thread is + in the middle of a fork() call. */ + pid_t pid = THREAD_GETMEM (THREAD_SELF, pid); + if (__builtin_expect (pid < 0, 0)) + pid = -pid; +#endif + + /* Safety check. It would be possible to call this function for + other signals and send a signal from another process. This is not + correct and might even be a security problem. Try to catch as + many incorrect invocations as possible. */ + if (sig != SIGSETXID +#ifdef __ASSUME_CORRECT_SI_PID + /* Kernels before 2.5.75 stored the thread ID and not the process + ID in si_pid so we skip this test. */ + || si->si_pid != pid +#endif + || si->si_code != SI_TKILL) + return; + + INTERNAL_SYSCALL_DECL (err); + INTERNAL_SYSCALL_NCS (__xidcmd->syscall_no, err, 3, __xidcmd->id[0], + __xidcmd->id[1], __xidcmd->id[2]); + + /* Reset the SETXID flag. */ + struct pthread *self = THREAD_SELF; + int flags, newval; + do + { + flags = THREAD_GETMEM (self, cancelhandling); + newval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling, + flags & ~SETXID_BITMASK, flags); + } + while (flags != newval); + + /* And release the futex. */ + self->setxid_futex = 1; + lll_futex_wake (&self->setxid_futex, 1, LLL_PRIVATE); + + if (atomic_decrement_val (&__xidcmd->cntr) == 0) + lll_futex_wake (&__xidcmd->cntr, 1, LLL_PRIVATE); +} + + +/* When using __thread for this, we do it in libc so as not + to give libpthread its own TLS segment just for this. */ +extern void **__libc_dl_error_tsd (void) __attribute__ ((const)); + + +/* This can be set by the debugger before initialization is complete. */ +static bool __nptl_initial_report_events __attribute_used__; + +void +__pthread_initialize_minimal_internal (void) +{ + static int initialized = 0; + + if (initialized) + return; + initialized = 1; + +#ifndef SHARED + /* Unlike in the dynamically linked case the dynamic linker has not + taken care of initializing the TLS data structures. */ + __libc_setup_tls (TLS_TCB_SIZE, TLS_TCB_ALIGN); + + /* We must prevent gcc from being clever and move any of the + following code ahead of the __libc_setup_tls call. This function + will initialize the thread register which is subsequently + used. */ + __asm__ __volatile__ (""); +#endif + + /* Minimal initialization of the thread descriptor. */ + struct pthread *pd = THREAD_SELF; + INTERNAL_SYSCALL_DECL (err); + pd->pid = pd->tid = INTERNAL_SYSCALL (set_tid_address, err, 1, &pd->tid); + THREAD_SETMEM (pd, specific[0], &pd->specific_1stblock[0]); + THREAD_SETMEM (pd, user_stack, true); + if (LLL_LOCK_INITIALIZER != 0) + THREAD_SETMEM (pd, lock, LLL_LOCK_INITIALIZER); +#if HP_TIMING_AVAIL + THREAD_SETMEM (pd, cpuclock_offset, GL(dl_cpuclock_offset)); +#endif + + /* Initialize the robust mutex data. */ +#ifdef __PTHREAD_MUTEX_HAVE_PREV + pd->robust_prev = &pd->robust_head; +#endif + pd->robust_head.list = &pd->robust_head; +#ifdef __NR_set_robust_list + pd->robust_head.futex_offset = (offsetof (pthread_mutex_t, __data.__lock) + - offsetof (pthread_mutex_t, + __data.__list.__next)); + int res = INTERNAL_SYSCALL (set_robust_list, err, 2, &pd->robust_head, + sizeof (struct robust_list_head)); + if (INTERNAL_SYSCALL_ERROR_P (res, err)) +#endif + set_robust_list_not_avail (); + +#ifndef __ASSUME_PRIVATE_FUTEX + /* Private futexes are always used (at least internally) so that + doing the test once this early is beneficial. */ + { + int word = 0; + word = INTERNAL_SYSCALL (futex, err, 3, &word, + FUTEX_WAKE | FUTEX_PRIVATE_FLAG, 1); + if (!INTERNAL_SYSCALL_ERROR_P (word, err)) + THREAD_SETMEM (pd, header.private_futex, FUTEX_PRIVATE_FLAG); + } + + /* Private futexes have been introduced earlier than the + FUTEX_CLOCK_REALTIME flag. We don't have to run the test if we + know the former are not supported. This also means we know the + kernel will return ENOSYS for unknown operations. */ + if (THREAD_GETMEM (pd, header.private_futex) != 0) +#endif +#ifndef __ASSUME_FUTEX_CLOCK_REALTIME + { + int word = 0; + /* NB: the syscall actually takes six parameters. The last is the + bit mask. But since we will not actually wait at all the value + is irrelevant. Given that passing six parameters is difficult + on some architectures we just pass whatever random value the + calling convention calls for to the kernel. It causes no harm. */ + word = INTERNAL_SYSCALL (futex, err, 5, &word, + FUTEX_WAIT_BITSET | FUTEX_CLOCK_REALTIME + | FUTEX_PRIVATE_FLAG, 1, NULL, 0); + assert (INTERNAL_SYSCALL_ERROR_P (word, err)); + if (INTERNAL_SYSCALL_ERRNO (word, err) != ENOSYS) + __set_futex_clock_realtime (); + } +#endif + + /* Set initial thread's stack block from 0 up to __libc_stack_end. + It will be bigger than it actually is, but for unwind.c/pt-longjmp.c + purposes this is good enough. */ + THREAD_SETMEM (pd, stackblock_size, (size_t) __libc_stack_end); + + /* Initialize the list of all running threads with the main thread. */ + INIT_LIST_HEAD (&__stack_user); + list_add (&pd->list, &__stack_user); + + /* Before initializing __stack_user, the debugger could not find us and + had to set __nptl_initial_report_events. Propagate its setting. */ + THREAD_SETMEM (pd, report_events, __nptl_initial_report_events); + + /* Install the cancellation signal handler. If for some reason we + cannot install the handler we do not abort. Maybe we should, but + it is only asynchronous cancellation which is affected. */ + struct sigaction sa; + sa.sa_sigaction = sigcancel_handler; + sa.sa_flags = SA_SIGINFO; + __sigemptyset (&sa.sa_mask); + + (void) __libc_sigaction (SIGCANCEL, &sa, NULL); + + /* Install the handle to change the threads' uid/gid. */ + sa.sa_sigaction = sighandler_setxid; + sa.sa_flags = SA_SIGINFO | SA_RESTART; + + (void) __libc_sigaction (SIGSETXID, &sa, NULL); + + /* The parent process might have left the signals blocked. Just in + case, unblock it. We reuse the signal mask in the sigaction + structure. It is already cleared. */ + __sigaddset (&sa.sa_mask, SIGCANCEL); + __sigaddset (&sa.sa_mask, SIGSETXID); + (void) INTERNAL_SYSCALL (rt_sigprocmask, err, 4, SIG_UNBLOCK, &sa.sa_mask, + NULL, _NSIG / 8); + + /* Get the size of the static and alignment requirements for the TLS + block. */ + size_t static_tls_align; + _dl_get_tls_static_info (&__static_tls_size, &static_tls_align); + + /* Make sure the size takes all the alignments into account. */ + if (STACK_ALIGN > static_tls_align) + static_tls_align = STACK_ALIGN; + __static_tls_align_m1 = static_tls_align - 1; + + __static_tls_size = roundup (__static_tls_size, static_tls_align); + + /* Determine the default allowed stack size. This is the size used + in case the user does not specify one. */ + struct rlimit limit; + if (getrlimit (RLIMIT_STACK, &limit) != 0 + || limit.rlim_cur == RLIM_INFINITY) + /* The system limit is not usable. Use an architecture-specific + default. */ + limit.rlim_cur = ARCH_STACK_DEFAULT_SIZE; + else if (limit.rlim_cur < PTHREAD_STACK_MIN) + /* The system limit is unusably small. + Use the minimal size acceptable. */ + limit.rlim_cur = PTHREAD_STACK_MIN; + + /* Make sure it meets the minimum size that allocate_stack + (allocatestack.c) will demand, which depends on the page size. */ + const uintptr_t pagesz = sysconf (_SC_PAGESIZE); + const size_t minstack = pagesz + __static_tls_size + MINIMAL_REST_STACK; + if (limit.rlim_cur < minstack) + limit.rlim_cur = minstack; + + /* Round the resource limit up to page size. */ + limit.rlim_cur = (limit.rlim_cur + pagesz - 1) & -pagesz; + __default_stacksize = limit.rlim_cur; + +#ifdef SHARED + /* Transfer the old value from the dynamic linker's internal location. */ + *__libc_dl_error_tsd () = *(*GL(dl_error_catch_tsd)) (); + GL(dl_error_catch_tsd) = &__libc_dl_error_tsd; + +#endif + + GL(dl_init_static_tls) = &__pthread_init_static_tls; + + /* Register the fork generation counter with the libc. */ +#ifndef TLS_MULTIPLE_THREADS_IN_TCB + __libc_multiple_threads_ptr = +#endif + __libc_pthread_init (&__fork_generation, __reclaim_stacks, + ptr_pthread_functions); + + /* Determine whether the machine is SMP or not. */ + __is_smp = is_smp_system (); + + /* uClibc-specific stdio initialization for threads. */ + { + FILE *fp; + _stdio_user_locking = 0; /* 2 if threading not initialized */ + for (fp = _stdio_openlist; fp != NULL; fp = fp->__nextopen) { + if (fp->__user_locking != 1) { + fp->__user_locking = 0; + } + } + } +} +strong_alias (__pthread_initialize_minimal_internal, + __pthread_initialize_minimal) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/libc-cancellation.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/libc-cancellation.c new file mode 100644 index 00000000..e9334a4c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/libc-cancellation.c @@ -0,0 +1,25 @@ +/* Copyright (C) 2002, 2003, 2005, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "pthreadP.h" + + +#define __pthread_enable_asynccancel __libc_enable_asynccancel +#define __pthread_disable_asynccancel __libc_disable_asynccancel +#include "cancellation.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/linux_fsinfo.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/linux_fsinfo.h new file mode 100644 index 00000000..13c38562 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/linux_fsinfo.h @@ -0,0 +1,153 @@ +/* Constants from kernel header for various FSes. + Copyright (C) 1998,1999,2000,2001,2002,2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _LINUX_FSINFO_H +#define _LINUX_FSINFO_H 1 + +/* These definitions come from the kernel headers. But we cannot + include the headers here because of type clashes. If new + filesystem types will become available we have to add the + appropriate definitions here.*/ + +/* Constants that identify the `adfs' filesystem. */ +#define ADFS_SUPER_MAGIC 0xadf5 + +/* Constants that identify the `affs' filesystem. */ +#define AFFS_SUPER_MAGIC 0xadff + +/* Constants that identify the `autofs' filesystem. */ +#define AUTOFS_SUPER_MAGIC 0x187 + +/* Constants that identify the `bfs' filesystem. */ +#define BFS_MAGIC 0x1BADFACE + +/* Constants that identify the `coda' filesystem. */ +#define CODA_SUPER_MAGIC 0x73757245 + +/* Constants that identify the `coherent' filesystem. */ +#define COH_SUPER_MAGIC 0x012ff7b7 + +/* Constant that identifies the `ramfs' filesystem. */ +#define CRAMFS_MAGIC 0x28cd3d45 + +/* Constant that identifies the `devfs' filesystem. */ +#define DEVFS_SUPER_MAGIC 0x1373 + +/* Constant that identifies the `devpts' filesystem. */ +#define DEVPTS_SUPER_MAGIC 0x1cd1 + +/* Constant that identifies the `efs' filesystem. */ +#define EFS_SUPER_MAGIC 0x414A53 +#define EFS_MAGIC 0x072959 + +/* Constant that identifies the `ext2' and `ext3' filesystems. */ +#define EXT2_SUPER_MAGIC 0xef53 + +/* Constant that identifies the `hpfs' filesystem. */ +#define HPFS_SUPER_MAGIC 0xf995e849 + +/* Constant that identifies the `iso9660' filesystem. */ +#define ISOFS_SUPER_MAGIC 0x9660 + +/* Constant that identifies the `jffs' filesystem. */ +#define JFFS_SUPER_MAGIC 0x07c0 + +/* Constant that identifies the `jffs2' filesystem. */ +#define JFFS2_SUPER_MAGIC 0x72b6 + +/* Constant that identifies the `jfs' filesystem. */ +#define JFS_SUPER_MAGIC 0x3153464a + +/* Constants that identify the `minix2' filesystem. */ +#define MINIX2_SUPER_MAGIC 0x2468 +#define MINIX2_SUPER_MAGIC2 0x2478 + +/* Constants that identify the `minix' filesystem. */ +#define MINIX_SUPER_MAGIC 0x137f +#define MINIX_SUPER_MAGIC2 0x138F + +/* Constants that identify the `msdos' filesystem. */ +#define MSDOS_SUPER_MAGIC 0x4d44 + +/* Constants that identify the `ncp' filesystem. */ +#define NCP_SUPER_MAGIC 0x564c + +/* Constants that identify the `nfs' filesystem. */ +#define NFS_SUPER_MAGIC 0x6969 + +/* Constants that identify the `ntfs' filesystem. */ +#define NTFS_SUPER_MAGIC 0x5346544e + +/* Constants that identify the `proc' filesystem. */ +#define PROC_SUPER_MAGIC 0x9fa0 + +/* Constant that identifies the `usbdevfs' filesystem. */ +#define USBDEVFS_SUPER_MAGIC 0x9fa2 + +/* Constants that identify the `qnx4' filesystem. */ +#define QNX4_SUPER_MAGIC 0x002f + +/* Constants that identify the `reiser' filesystem. */ +#define REISERFS_SUPER_MAGIC 0x52654973 + +/* Constant that identifies the `romfs' filesystem. */ +#define ROMFS_SUPER_MAGIC 0x7275 + +/* Constants that identify the `smb' filesystem. */ +#define SMB_SUPER_MAGIC 0x517b + +/* Constants that identify the `sysV' filesystem. */ +#define SYSV2_SUPER_MAGIC 0x012ff7b6 +#define SYSV4_SUPER_MAGIC 0x012ff7b5 + +/* Constants that identify the `udf' filesystem. */ +#define UDF_SUPER_MAGIC 0x15013346 + +/* Constants that identify the `ufs' filesystem. */ +#define UFS_MAGIC 0x00011954 +#define UFS_CIGAM 0x54190100 /* byteswapped MAGIC */ + +/* Constants that identify the `xenix' filesystem. */ +#define XENIX_SUPER_MAGIC 0x012ff7b4 + +/* Constant that identifies the `shm' filesystem. */ +#define SHMFS_SUPER_MAGIC 0x01021994 + +/* Constants that identify the `xfs' filesystem. */ +#define XFS_SUPER_MAGIC 0x58465342 + +/* Constants that identify the `vxfs' filesystem. */ +#define VXFS_SUPER_MAGIC 0xa501fcf5 + +/* Maximum link counts. */ +#define COH_LINK_MAX 10000 +#define EXT2_LINK_MAX 32000 +#define MINIX2_LINK_MAX 65530 +#define MINIX_LINK_MAX 250 +#define REISERFS_LINK_MAX 64535 +#define SYSV_LINK_MAX 126 /* 127? 251? */ +#define UFS_LINK_MAX EXT2_LINK_MAX +#define XENIX_LINK_MAX 126 /* ?? */ +#define XFS_LINK_MAX 2147483647 + +/* The Linux kernel header mentioned this as a kind of generic value. */ +#define LINUX_LINK_MAX 127 + + +#endif /* linux_fsinfo.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pt-cleanup.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pt-cleanup.c new file mode 100644 index 00000000..97673b6c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pt-cleanup.c @@ -0,0 +1,64 @@ +/* Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include "pthreadP.h" +#include + +void +attribute_protected +__pthread_cleanup_upto (__jmp_buf target, char *targetframe) +{ + struct pthread *self = THREAD_SELF; + struct _pthread_cleanup_buffer *cbuf; + + /* Adjust all pointers used in comparisons, so that top of thread's + stack is at the top of address space. Without that, things break + if stack is allocated above the main stack. */ + uintptr_t adj = (uintptr_t) self->stackblock + self->stackblock_size; + uintptr_t targetframe_adj = (uintptr_t) targetframe - adj; + + for (cbuf = THREAD_GETMEM (self, cleanup); + cbuf != NULL && _JMPBUF_UNWINDS_ADJ (target, cbuf, adj); + cbuf = cbuf->__prev) + { +#if _STACK_GROWS_DOWN + if ((uintptr_t) cbuf - adj <= targetframe_adj) + { + cbuf = NULL; + break; + } +#elif _STACK_GROWS_UP + if ((uintptr_t) cbuf - adj >= targetframe_adj) + { + cbuf = NULL; + break; + } +#else +# error "Define either _STACK_GROWS_DOWN or _STACK_GROWS_UP" +#endif + + /* Call the cleanup code. */ + cbuf->__routine (cbuf->__arg); + } + + THREAD_SETMEM (self, cleanup, cbuf); +} +hidden_def (__pthread_cleanup_upto) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pt-system.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pt-system.c new file mode 100644 index 00000000..4728a7c0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pt-system.c @@ -0,0 +1,36 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include "pthreadP.h" + +extern __typeof(system) __libc_system; +#include + + +int +system (const char *line) +{ + return __libc_system (line); +} + +/* __libc_system in libc.so handles cancellation. */ +LIBC_CANCEL_HANDLED (); diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread-errnos.sym b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread-errnos.sym new file mode 100644 index 00000000..0975b7a3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread-errnos.sym @@ -0,0 +1,13 @@ +#include + +-- These errno codes are used by some assembly code. + +EAGAIN EAGAIN +EBUSY EBUSY +EDEADLK EDEADLK +EINTR EINTR +EINVAL EINVAL +ENOSYS ENOSYS +EOVERFLOW EOVERFLOW +ETIMEDOUT ETIMEDOUT +EWOULDBLOCK EWOULDBLOCK diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthreadP.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthreadP.h new file mode 100644 index 00000000..c45bd117 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthreadP.h @@ -0,0 +1,589 @@ +/* Copyright (C) 2002-2007, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _PTHREADP_H +#define _PTHREADP_H 1 + +#include +#include +#include +#include +#include "descr.h" +#include +#include +#include +#include +#include +#include +#include + + +/* Atomic operations on TLS memory. */ +#ifndef THREAD_ATOMIC_CMPXCHG_VAL +# define THREAD_ATOMIC_CMPXCHG_VAL(descr, member, new, old) \ + atomic_compare_and_exchange_val_acq (&(descr)->member, new, old) +#endif + +#ifndef THREAD_ATOMIC_BIT_SET +# define THREAD_ATOMIC_BIT_SET(descr, member, bit) \ + atomic_bit_set (&(descr)->member, bit) +#endif + + +/* Adaptive mutex definitions. */ +#ifndef MAX_ADAPTIVE_COUNT +# define MAX_ADAPTIVE_COUNT 100 +#endif + + +/* Magic cookie representing robust mutex with dead owner. */ +#define PTHREAD_MUTEX_INCONSISTENT INT_MAX +/* Magic cookie representing not recoverable robust mutex. */ +#define PTHREAD_MUTEX_NOTRECOVERABLE (INT_MAX - 1) + + +/* Internal mutex type value. */ +enum +{ + PTHREAD_MUTEX_KIND_MASK_NP = 3, + PTHREAD_MUTEX_ROBUST_NORMAL_NP = 16, + PTHREAD_MUTEX_ROBUST_RECURSIVE_NP + = PTHREAD_MUTEX_ROBUST_NORMAL_NP | PTHREAD_MUTEX_RECURSIVE_NP, + PTHREAD_MUTEX_ROBUST_ERRORCHECK_NP + = PTHREAD_MUTEX_ROBUST_NORMAL_NP | PTHREAD_MUTEX_ERRORCHECK_NP, + PTHREAD_MUTEX_ROBUST_ADAPTIVE_NP + = PTHREAD_MUTEX_ROBUST_NORMAL_NP | PTHREAD_MUTEX_ADAPTIVE_NP, + PTHREAD_MUTEX_PRIO_INHERIT_NP = 32, + PTHREAD_MUTEX_PI_NORMAL_NP + = PTHREAD_MUTEX_PRIO_INHERIT_NP | PTHREAD_MUTEX_NORMAL, + PTHREAD_MUTEX_PI_RECURSIVE_NP + = PTHREAD_MUTEX_PRIO_INHERIT_NP | PTHREAD_MUTEX_RECURSIVE_NP, + PTHREAD_MUTEX_PI_ERRORCHECK_NP + = PTHREAD_MUTEX_PRIO_INHERIT_NP | PTHREAD_MUTEX_ERRORCHECK_NP, + PTHREAD_MUTEX_PI_ADAPTIVE_NP + = PTHREAD_MUTEX_PRIO_INHERIT_NP | PTHREAD_MUTEX_ADAPTIVE_NP, + PTHREAD_MUTEX_PI_ROBUST_NORMAL_NP + = PTHREAD_MUTEX_PRIO_INHERIT_NP | PTHREAD_MUTEX_ROBUST_NORMAL_NP, + PTHREAD_MUTEX_PI_ROBUST_RECURSIVE_NP + = PTHREAD_MUTEX_PRIO_INHERIT_NP | PTHREAD_MUTEX_ROBUST_RECURSIVE_NP, + PTHREAD_MUTEX_PI_ROBUST_ERRORCHECK_NP + = PTHREAD_MUTEX_PRIO_INHERIT_NP | PTHREAD_MUTEX_ROBUST_ERRORCHECK_NP, + PTHREAD_MUTEX_PI_ROBUST_ADAPTIVE_NP + = PTHREAD_MUTEX_PRIO_INHERIT_NP | PTHREAD_MUTEX_ROBUST_ADAPTIVE_NP, + PTHREAD_MUTEX_PRIO_PROTECT_NP = 64, + PTHREAD_MUTEX_PP_NORMAL_NP + = PTHREAD_MUTEX_PRIO_PROTECT_NP | PTHREAD_MUTEX_NORMAL, + PTHREAD_MUTEX_PP_RECURSIVE_NP + = PTHREAD_MUTEX_PRIO_PROTECT_NP | PTHREAD_MUTEX_RECURSIVE_NP, + PTHREAD_MUTEX_PP_ERRORCHECK_NP + = PTHREAD_MUTEX_PRIO_PROTECT_NP | PTHREAD_MUTEX_ERRORCHECK_NP, + PTHREAD_MUTEX_PP_ADAPTIVE_NP + = PTHREAD_MUTEX_PRIO_PROTECT_NP | PTHREAD_MUTEX_ADAPTIVE_NP +}; +#define PTHREAD_MUTEX_PSHARED_BIT 128 + +#define PTHREAD_MUTEX_TYPE(m) \ + ((m)->__data.__kind & 127) + +#if LLL_PRIVATE == 0 && LLL_SHARED == 128 +# define PTHREAD_MUTEX_PSHARED(m) \ + ((m)->__data.__kind & 128) +#else +# define PTHREAD_MUTEX_PSHARED(m) \ + (((m)->__data.__kind & 128) ? LLL_SHARED : LLL_PRIVATE) +#endif + +/* The kernel when waking robust mutexes on exit never uses + FUTEX_PRIVATE_FLAG FUTEX_WAKE. */ +#define PTHREAD_ROBUST_MUTEX_PSHARED(m) LLL_SHARED + +/* Ceiling in __data.__lock. __data.__lock is signed, so don't + use the MSB bit in there, but in the mask also include that bit, + so that the compiler can optimize & PTHREAD_MUTEX_PRIO_CEILING_MASK + masking if the value is then shifted down by + PTHREAD_MUTEX_PRIO_CEILING_SHIFT. */ +#define PTHREAD_MUTEX_PRIO_CEILING_SHIFT 19 +#define PTHREAD_MUTEX_PRIO_CEILING_MASK 0xfff80000 + + +/* Flags in mutex attr. */ +#define PTHREAD_MUTEXATTR_PROTOCOL_SHIFT 28 +#define PTHREAD_MUTEXATTR_PROTOCOL_MASK 0x30000000 +#define PTHREAD_MUTEXATTR_PRIO_CEILING_SHIFT 12 +#define PTHREAD_MUTEXATTR_PRIO_CEILING_MASK 0x00fff000 +#define PTHREAD_MUTEXATTR_FLAG_ROBUST 0x40000000 +#define PTHREAD_MUTEXATTR_FLAG_PSHARED 0x80000000 +#define PTHREAD_MUTEXATTR_FLAG_BITS \ + (PTHREAD_MUTEXATTR_FLAG_ROBUST | PTHREAD_MUTEXATTR_FLAG_PSHARED \ + | PTHREAD_MUTEXATTR_PROTOCOL_MASK | PTHREAD_MUTEXATTR_PRIO_CEILING_MASK) + + +/* Check whether rwlock prefers readers. */ +#define PTHREAD_RWLOCK_PREFER_READER_P(rwlock) \ + ((rwlock)->__data.__flags == 0) + + +/* Bits used in robust mutex implementation. */ +#define FUTEX_WAITERS 0x80000000 +#define FUTEX_OWNER_DIED 0x40000000 +#define FUTEX_TID_MASK 0x3fffffff + + +/* Internal variables. */ + + +/* Default stack size. */ +extern size_t __default_stacksize attribute_hidden; + +/* Size and alignment of static TLS block. */ +extern size_t __static_tls_size attribute_hidden; +extern size_t __static_tls_align_m1 attribute_hidden; + +/* Flag whether the machine is SMP or not. */ +extern int __is_smp attribute_hidden; + +/* Thread descriptor handling. */ +extern list_t __stack_user; +hidden_proto (__stack_user) + +/* Attribute handling. */ +extern struct pthread_attr *__attr_list attribute_hidden; +extern int __attr_list_lock attribute_hidden; + +/* First available RT signal. */ +extern int __current_sigrtmin attribute_hidden; +/* Last available RT signal. */ +extern int __current_sigrtmax attribute_hidden; + +/* Concurrency handling. */ +extern int __concurrency_level attribute_hidden; + +/* Thread-local data key handling. */ +extern struct pthread_key_struct __pthread_keys[PTHREAD_KEYS_MAX]; +hidden_proto (__pthread_keys) + +/* Number of threads running. */ +extern unsigned int __nptl_nthreads attribute_hidden; + +#ifndef __ASSUME_SET_ROBUST_LIST +/* Negative if we do not have the system call and we can use it. */ +extern int __set_robust_list_avail attribute_hidden; +#endif + +/* Thread Priority Protection. */ +extern int __sched_fifo_min_prio attribute_hidden; +extern int __sched_fifo_max_prio attribute_hidden; +extern void __init_sched_fifo_prio (void) attribute_hidden; +extern int __pthread_tpp_change_priority (int prev_prio, int new_prio) + attribute_hidden; +extern int __pthread_current_priority (void) attribute_hidden; + +/* The library can run in debugging mode where it performs a lot more + tests. */ +extern int __pthread_debug attribute_hidden; +/** For now disable debugging support. */ +#if 0 +# define DEBUGGING_P __builtin_expect (__pthread_debug, 0) +# define INVALID_TD_P(pd) (DEBUGGING_P && __find_in_stack_list (pd) == NULL) +# define INVALID_NOT_TERMINATED_TD_P(pd) INVALID_TD_P (pd) +#else +# define DEBUGGING_P 0 +/* Simplified test. This will not catch all invalid descriptors but + is better than nothing. And if the test triggers the thread + descriptor is guaranteed to be invalid. */ +# define INVALID_TD_P(pd) __builtin_expect ((pd)->tid <= 0, 0) +# define INVALID_NOT_TERMINATED_TD_P(pd) __builtin_expect ((pd)->tid < 0, 0) +#endif + + +/* Cancellation test. */ +#define CANCELLATION_P(self) \ + do { \ + int cancelhandling = THREAD_GETMEM (self, cancelhandling); \ + if (CANCEL_ENABLED_AND_CANCELED (cancelhandling)) \ + { \ + THREAD_SETMEM (self, result, PTHREAD_CANCELED); \ + __do_cancel (); \ + } \ + } while (0) + + +extern void __pthread_unwind (__pthread_unwind_buf_t *__buf) + __cleanup_fct_attribute __attribute ((__noreturn__)) +#if !defined SHARED && !defined IS_IN_libpthread + weak_function +#endif + ; +extern void __pthread_unwind_next (__pthread_unwind_buf_t *__buf) + __cleanup_fct_attribute __attribute ((__noreturn__)) +#ifndef SHARED + weak_function +#endif + ; +extern void __pthread_register_cancel (__pthread_unwind_buf_t *__buf) + __cleanup_fct_attribute; +extern void __pthread_unregister_cancel (__pthread_unwind_buf_t *__buf) + __cleanup_fct_attribute; +#if defined NOT_IN_libc && defined IS_IN_libpthread +hidden_proto (__pthread_unwind) +hidden_proto (__pthread_unwind_next) +hidden_proto (__pthread_register_cancel) +hidden_proto (__pthread_unregister_cancel) +# ifdef SHARED +extern void attribute_hidden pthread_cancel_init (void); +extern void __unwind_freeres (void); +# endif +#endif + + +/* Called when a thread reacts on a cancellation request. */ +static inline void +__attribute ((noreturn, always_inline)) +__do_cancel (void) +{ + struct pthread *self = THREAD_SELF; + + /* Make sure we get no more cancellations. */ + THREAD_ATOMIC_BIT_SET (self, cancelhandling, EXITING_BIT); + + __pthread_unwind ((__pthread_unwind_buf_t *) + THREAD_GETMEM (self, cleanup_jmp_buf)); +} + + +/* Set cancellation mode to asynchronous. */ +#define CANCEL_ASYNC() \ + __pthread_enable_asynccancel () +/* Reset to previous cancellation mode. */ +#define CANCEL_RESET(oldtype) \ + __pthread_disable_asynccancel (oldtype) + +#if !defined NOT_IN_libc +/* Same as CANCEL_ASYNC, but for use in libc.so. */ +# define LIBC_CANCEL_ASYNC() \ + __libc_enable_asynccancel () +/* Same as CANCEL_RESET, but for use in libc.so. */ +# define LIBC_CANCEL_RESET(oldtype) \ + __libc_disable_asynccancel (oldtype) +# define LIBC_CANCEL_HANDLED() \ + __asm__ (".globl " __USER_LABEL_PREFIX__ "__libc_enable_asynccancel"); \ + __asm__ (".globl " __USER_LABEL_PREFIX__ "__libc_disable_asynccancel") +#elif defined NOT_IN_libc && defined IS_IN_libpthread +# define LIBC_CANCEL_ASYNC() CANCEL_ASYNC () +# define LIBC_CANCEL_RESET(val) CANCEL_RESET (val) +# define LIBC_CANCEL_HANDLED() \ + __asm__ (".globl " __USER_LABEL_PREFIX__ "__pthread_enable_asynccancel"); \ + __asm__ (".globl " __USER_LABEL_PREFIX__ "__pthread_disable_asynccancel") +#elif defined NOT_IN_libc && defined IS_IN_librt +# define LIBC_CANCEL_ASYNC() \ + __librt_enable_asynccancel () +# define LIBC_CANCEL_RESET(val) \ + __librt_disable_asynccancel (val) +# define LIBC_CANCEL_HANDLED() \ + __asm__ (".globl " __USER_LABEL_PREFIX__ "__librt_enable_asynccancel"); \ + __asm__ (".globl " __USER_LABEL_PREFIX__ "__librt_disable_asynccancel") +#else +# define LIBC_CANCEL_ASYNC() 0 /* Just a dummy value. */ +# define LIBC_CANCEL_RESET(val) ((void)(val)) /* Nothing, but evaluate it. */ +# define LIBC_CANCEL_HANDLED() /* Nothing. */ +#endif + +/* The signal used for asynchronous cancelation. */ +#define SIGCANCEL __SIGRTMIN + + +/* Signal needed for the kernel-supported POSIX timer implementation. + We can reuse the cancellation signal since we can distinguish + cancellation from timer expirations. */ +#define SIGTIMER SIGCANCEL + + +/* Signal used to implement the setuid et.al. functions. */ +#define SIGSETXID (__SIGRTMIN + 1) + +/* Used to communicate with signal handler. */ +extern struct xid_command *__xidcmd attribute_hidden; + + +/* Internal prototypes. */ + +/* Thread list handling. */ +extern struct pthread *__find_in_stack_list (struct pthread *pd) + attribute_hidden internal_function; + +/* Deallocate a thread's stack after optionally making sure the thread + descriptor is still valid. */ +extern void __free_tcb (struct pthread *pd) attribute_hidden internal_function; + +/* Free allocated stack. */ +extern void __deallocate_stack (struct pthread *pd) + attribute_hidden internal_function; + +/* Mark all the stacks except for the current one as available. This + function also re-initializes the lock for the stack cache. */ +extern void __reclaim_stacks (void) attribute_hidden; + +/* Make all threads's stacks executable. */ +extern int __make_stacks_executable (void **stack_endp) + internal_function attribute_hidden; + +/* longjmp handling. */ +extern void __pthread_cleanup_upto (__jmp_buf target, char *targetframe); +#if defined NOT_IN_libc && defined IS_IN_libpthread +hidden_proto (__pthread_cleanup_upto) +#endif + + +/* Functions with versioned interfaces. */ +extern int __pthread_create_2_1 (pthread_t *newthread, + const pthread_attr_t *attr, + void *(*start_routine) (void *), void *arg); +extern int __pthread_create_2_0 (pthread_t *newthread, + const pthread_attr_t *attr, + void *(*start_routine) (void *), void *arg); +extern int __pthread_attr_init_2_1 (pthread_attr_t *attr); +extern int __pthread_attr_init_2_0 (pthread_attr_t *attr); + + +/* Event handlers for libthread_db interface. */ +extern void __nptl_create_event (void); +extern void __nptl_death_event (void); +hidden_proto (__nptl_create_event) +hidden_proto (__nptl_death_event) + +/* Register the generation counter in the libpthread with the libc. */ +#ifdef TLS_MULTIPLE_THREADS_IN_TCB +extern void __libc_pthread_init (unsigned long int *ptr, + void (*reclaim) (void), + const struct pthread_functions *functions); +#else +extern int *__libc_pthread_init (unsigned long int *ptr, + void (*reclaim) (void), + const struct pthread_functions *functions); + +/* Variable set to a nonzero value if more than one thread runs or ran. */ +extern int __pthread_multiple_threads attribute_hidden; +/* Pointer to the corresponding variable in libc. */ +extern int *__libc_multiple_threads_ptr attribute_hidden; +#endif + +/* Find a thread given its TID. */ +extern struct pthread *__find_thread_by_id (pid_t tid) attribute_hidden +#ifdef SHARED +; +#else +weak_function; +#define __find_thread_by_id(tid) \ + (__find_thread_by_id ? (__find_thread_by_id) (tid) : (struct pthread *) NULL) +#endif + +extern void __pthread_init_static_tls (struct link_map *) attribute_hidden; + + +/* Namespace save aliases. */ +extern int __pthread_getschedparam (pthread_t thread_id, int *policy, + struct sched_param *param); +extern int __pthread_setschedparam (pthread_t thread_id, int policy, + const struct sched_param *param); +extern int __pthread_setcancelstate (int state, int *oldstate); +extern int __pthread_mutex_init (pthread_mutex_t *__mutex, + __const pthread_mutexattr_t *__mutexattr); +extern int __pthread_mutex_init_internal (pthread_mutex_t *__mutex, + __const pthread_mutexattr_t *__mutexattr) + attribute_hidden; +extern int __pthread_mutex_destroy (pthread_mutex_t *__mutex); +extern int __pthread_mutex_destroy_internal (pthread_mutex_t *__mutex) + attribute_hidden; +extern int __pthread_mutex_trylock (pthread_mutex_t *_mutex); +extern int __pthread_mutex_lock (pthread_mutex_t *__mutex); +extern int __pthread_mutex_lock_internal (pthread_mutex_t *__mutex) + attribute_hidden; +extern int __pthread_mutex_cond_lock (pthread_mutex_t *__mutex) + attribute_hidden internal_function; +extern void __pthread_mutex_cond_lock_adjust (pthread_mutex_t *__mutex) + attribute_hidden internal_function; +extern int __pthread_mutex_unlock (pthread_mutex_t *__mutex); +extern int __pthread_mutex_unlock_internal (pthread_mutex_t *__mutex) + attribute_hidden; +extern int __pthread_mutex_unlock_usercnt (pthread_mutex_t *__mutex, + int __decr) + attribute_hidden internal_function; +extern int __pthread_mutexattr_init (pthread_mutexattr_t *attr); +extern int __pthread_mutexattr_destroy (pthread_mutexattr_t *attr); +extern int __pthread_mutexattr_settype (pthread_mutexattr_t *attr, int kind); +extern int __pthread_attr_destroy (pthread_attr_t *attr); +extern int __pthread_attr_getdetachstate (const pthread_attr_t *attr, + int *detachstate); +extern int __pthread_attr_setdetachstate (pthread_attr_t *attr, + int detachstate); +extern int __pthread_attr_getinheritsched (const pthread_attr_t *attr, + int *inherit); +extern int __pthread_attr_setinheritsched (pthread_attr_t *attr, int inherit); +extern int __pthread_attr_getschedparam (const pthread_attr_t *attr, + struct sched_param *param); +extern int __pthread_attr_setschedparam (pthread_attr_t *attr, + const struct sched_param *param); +extern int __pthread_attr_getschedpolicy (const pthread_attr_t *attr, + int *policy); +extern int __pthread_attr_setschedpolicy (pthread_attr_t *attr, int policy); +extern int __pthread_attr_getscope (const pthread_attr_t *attr, int *scope); +extern int __pthread_attr_setscope (pthread_attr_t *attr, int scope); +extern int __pthread_attr_getstackaddr (__const pthread_attr_t *__restrict + __attr, void **__restrict __stackaddr); +extern int __pthread_attr_setstackaddr (pthread_attr_t *__attr, + void *__stackaddr); +extern int __pthread_attr_getstacksize (__const pthread_attr_t *__restrict + __attr, + size_t *__restrict __stacksize); +extern int __pthread_attr_setstacksize (pthread_attr_t *__attr, + size_t __stacksize); +extern int __pthread_attr_getstack (__const pthread_attr_t *__restrict __attr, + void **__restrict __stackaddr, + size_t *__restrict __stacksize); +extern int __pthread_attr_setstack (pthread_attr_t *__attr, void *__stackaddr, + size_t __stacksize); +extern int __pthread_rwlock_init (pthread_rwlock_t *__restrict __rwlock, + __const pthread_rwlockattr_t *__restrict + __attr); +extern int __pthread_rwlock_destroy (pthread_rwlock_t *__rwlock); +extern int __pthread_rwlock_rdlock (pthread_rwlock_t *__rwlock); +extern int __pthread_rwlock_rdlock_internal (pthread_rwlock_t *__rwlock); +extern int __pthread_rwlock_tryrdlock (pthread_rwlock_t *__rwlock); +extern int __pthread_rwlock_wrlock (pthread_rwlock_t *__rwlock); +extern int __pthread_rwlock_wrlock_internal (pthread_rwlock_t *__rwlock); +extern int __pthread_rwlock_trywrlock (pthread_rwlock_t *__rwlock); +extern int __pthread_rwlock_unlock (pthread_rwlock_t *__rwlock); +extern int __pthread_rwlock_unlock_internal (pthread_rwlock_t *__rwlock); +extern int __pthread_cond_broadcast (pthread_cond_t *cond); +extern int __pthread_cond_destroy (pthread_cond_t *cond); +extern int __pthread_cond_init (pthread_cond_t *cond, + const pthread_condattr_t *cond_attr); +extern int __pthread_cond_signal (pthread_cond_t *cond); +extern int __pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex); +extern int __pthread_cond_timedwait (pthread_cond_t *cond, + pthread_mutex_t *mutex, + const struct timespec *abstime); +extern int __pthread_condattr_destroy (pthread_condattr_t *attr); +extern int __pthread_condattr_init (pthread_condattr_t *attr); +extern int __pthread_key_create (pthread_key_t *key, void (*destr) (void *)); +extern int __pthread_key_create_internal (pthread_key_t *key, + void (*destr) (void *)); +extern void *__pthread_getspecific (pthread_key_t key); +extern void *__pthread_getspecific_internal (pthread_key_t key); +extern int __pthread_setspecific (pthread_key_t key, const void *value); +extern int __pthread_setspecific_internal (pthread_key_t key, + const void *value); +extern int __pthread_once (pthread_once_t *once_control, + void (*init_routine) (void)); +extern int __pthread_once_internal (pthread_once_t *once_control, + void (*init_routine) (void)); +extern int __pthread_atfork (void (*prepare) (void), void (*parent) (void), + void (*child) (void)); +extern pthread_t __pthread_self (void); +extern int __pthread_equal (pthread_t thread1, pthread_t thread2); +extern int __pthread_kill (pthread_t threadid, int signo); +extern void __pthread_exit (void *value); +extern int __pthread_setcanceltype (int type, int *oldtype); +extern int __pthread_enable_asynccancel (void) attribute_hidden; +extern void __pthread_disable_asynccancel (int oldtype) + internal_function attribute_hidden; + +extern int __pthread_cond_broadcast_2_0 (pthread_cond_2_0_t *cond); +extern int __pthread_cond_destroy_2_0 (pthread_cond_2_0_t *cond); +extern int __pthread_cond_init_2_0 (pthread_cond_2_0_t *cond, + const pthread_condattr_t *cond_attr); +extern int __pthread_cond_signal_2_0 (pthread_cond_2_0_t *cond); +extern int __pthread_cond_timedwait_2_0 (pthread_cond_2_0_t *cond, + pthread_mutex_t *mutex, + const struct timespec *abstime); +extern int __pthread_cond_wait_2_0 (pthread_cond_2_0_t *cond, + pthread_mutex_t *mutex); + +extern int __pthread_getaffinity_np (pthread_t th, size_t cpusetsize, + cpu_set_t *cpuset); + +/* The two functions are in libc.so and not exported. */ +extern int __libc_enable_asynccancel (void) attribute_hidden; +extern void __libc_disable_asynccancel (int oldtype) + internal_function attribute_hidden; + + +/* The two functions are in librt.so and not exported. */ +extern int __librt_enable_asynccancel (void) attribute_hidden; +extern void __librt_disable_asynccancel (int oldtype) + internal_function attribute_hidden; + +#ifdef IS_IN_libpthread +/* Special versions which use non-exported functions. */ +extern void __pthread_cleanup_push (struct _pthread_cleanup_buffer *buffer, + void (*routine) (void *), void *arg) + attribute_hidden; +# undef pthread_cleanup_push +# define pthread_cleanup_push(routine,arg) \ + { struct _pthread_cleanup_buffer _buffer; \ + __pthread_cleanup_push (&_buffer, (routine), (arg)); + +extern void __pthread_cleanup_pop (struct _pthread_cleanup_buffer *buffer, + int execute) attribute_hidden; +# undef pthread_cleanup_pop +# define pthread_cleanup_pop(execute) \ + __pthread_cleanup_pop (&_buffer, (execute)); } +#endif + +extern void __pthread_cleanup_push_defer (struct _pthread_cleanup_buffer *buffer, + void (*routine) (void *), void *arg); +extern void __pthread_cleanup_pop_restore (struct _pthread_cleanup_buffer *buffer, + int execute); + +/* Old cleanup interfaces, still used in libc.so. */ +extern void _pthread_cleanup_push (struct _pthread_cleanup_buffer *buffer, + void (*routine) (void *), void *arg); +extern void _pthread_cleanup_pop (struct _pthread_cleanup_buffer *buffer, + int execute); +extern void _pthread_cleanup_push_defer (struct _pthread_cleanup_buffer *buffer, + void (*routine) (void *), void *arg); +extern void _pthread_cleanup_pop_restore (struct _pthread_cleanup_buffer *buffer, + int execute); + +extern void __nptl_deallocate_tsd (void) attribute_hidden; + +extern int __nptl_setxid (struct xid_command *cmdp) attribute_hidden; + +extern void __free_stacks (size_t limit) attribute_hidden; + +extern void __wait_lookup_done (void) attribute_hidden; + +#ifdef SHARED +# define PTHREAD_STATIC_FN_REQUIRE(name) +#else +# define PTHREAD_STATIC_FN_REQUIRE(name) __asm__ (".globl " #name); +#endif + + +#ifndef __NR_set_robust_list +/* XXX For the time being... Once we can rely on the kernel headers + having the definition remove these lines. */ +# if defined __i386__ +# define __NR_set_robust_list 311 +# elif defined __x86_64__ +# define __NR_set_robust_list 273 +# endif +#endif + +#endif /* pthreadP.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_atfork.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_atfork.c new file mode 100644 index 00000000..e607d496 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_atfork.c @@ -0,0 +1,56 @@ +/* Copyright (C) 2002, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file with other + programs, and to distribute those programs without any restriction + coming from the use of this file. (The GNU Lesser General Public + License restrictions do apply in other respects; for example, they + cover modification of the file, and distribution when not linked + into another program.) + + Note that people who make modified versions of this file are not + obligated to grant this special exception for their modified + versions; it is their choice whether to do so. The GNU Lesser + General Public License gives permission to release a modified + version without this exception; this exception also makes it + possible to release a modified version which carries forward this + exception. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "pthreadP.h" +#include + +/* This is defined by newer gcc version unique for each module. */ +extern void *__dso_handle __attribute__ ((__weak__)); + //,__visibility__ ("hidden"))); + + +/* Hide the symbol so that no definition but the one locally in the + executable or DSO is used. */ +int +__pthread_atfork ( + void (*prepare) (void), + void (*parent) (void), + void (*child) (void)) +{ + return __register_atfork (prepare, parent, child, + &__dso_handle == NULL ? NULL : __dso_handle); +} +strong_alias (__pthread_atfork, pthread_atfork) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_attr_destroy.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_attr_destroy.c new file mode 100644 index 00000000..52bffaf8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_attr_destroy.c @@ -0,0 +1,41 @@ +/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include "pthreadP.h" + +int +attribute_protected +__pthread_attr_destroy ( + pthread_attr_t *attr) +{ + struct pthread_attr *iattr; + + assert (sizeof (*attr) >= sizeof (struct pthread_attr)); + iattr = (struct pthread_attr *) attr; + + /* The affinity CPU set might be allocated dynamically. */ + free (iattr->cpuset); + + return 0; +} +strong_alias (__pthread_attr_destroy, pthread_attr_destroy) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_attr_getdetachstate.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_attr_getdetachstate.c new file mode 100644 index 00000000..a55d5167 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_attr_getdetachstate.c @@ -0,0 +1,40 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include "pthreadP.h" + + +int +attribute_protected +__pthread_attr_getdetachstate ( + const pthread_attr_t *attr, + int *detachstate) +{ + struct pthread_attr *iattr; + + assert (sizeof (*attr) >= sizeof (struct pthread_attr)); + iattr = (struct pthread_attr *) attr; + + *detachstate = (iattr->flags & ATTR_FLAG_DETACHSTATE + ? PTHREAD_CREATE_DETACHED : PTHREAD_CREATE_JOINABLE); + + return 0; +} +strong_alias (__pthread_attr_getdetachstate, pthread_attr_getdetachstate) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_attr_getguardsize.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_attr_getguardsize.c new file mode 100644 index 00000000..6fc3e6af --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_attr_getguardsize.c @@ -0,0 +1,35 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include "pthreadP.h" + + +int +pthread_attr_getguardsize (const pthread_attr_t *attr, size_t *guardsize) +{ + struct pthread_attr *iattr; + + assert (sizeof (*attr) >= sizeof (struct pthread_attr)); + iattr = (struct pthread_attr *) attr; + + *guardsize = iattr->guardsize; + + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_attr_getinheritsched.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_attr_getinheritsched.c new file mode 100644 index 00000000..f94f6b07 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_attr_getinheritsched.c @@ -0,0 +1,41 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include "pthreadP.h" + + +int +attribute_protected +__pthread_attr_getinheritsched ( + const pthread_attr_t *attr, + int *inherit) +{ + struct pthread_attr *iattr; + + assert (sizeof (*attr) >= sizeof (struct pthread_attr)); + iattr = (struct pthread_attr *) attr; + + /* Store the current values. */ + *inherit = (iattr->flags & ATTR_FLAG_NOTINHERITSCHED + ? PTHREAD_EXPLICIT_SCHED : PTHREAD_INHERIT_SCHED); + + return 0; +} +strong_alias (__pthread_attr_getinheritsched, pthread_attr_getinheritsched) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_attr_getschedparam.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_attr_getschedparam.c new file mode 100644 index 00000000..2f515b13 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_attr_getschedparam.c @@ -0,0 +1,41 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include "pthreadP.h" + + +int +attribute_protected +__pthread_attr_getschedparam ( + const pthread_attr_t *attr, + struct sched_param *param) +{ + struct pthread_attr *iattr; + + assert (sizeof (*attr) >= sizeof (struct pthread_attr)); + iattr = (struct pthread_attr *) attr; + + /* Copy the current values. */ + memcpy (param, &iattr->schedparam, sizeof (struct sched_param)); + + return 0; +} +strong_alias (__pthread_attr_getschedparam, pthread_attr_getschedparam) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_attr_getschedpolicy.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_attr_getschedpolicy.c new file mode 100644 index 00000000..924a4628 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_attr_getschedpolicy.c @@ -0,0 +1,40 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include "pthreadP.h" + + +int +attribute_protected +__pthread_attr_getschedpolicy ( + const pthread_attr_t *attr, + int *policy) +{ + struct pthread_attr *iattr; + + assert (sizeof (*attr) >= sizeof (struct pthread_attr)); + iattr = (struct pthread_attr *) attr; + + /* Store the current values. */ + *policy = iattr->schedpolicy; + + return 0; +} +strong_alias (__pthread_attr_getschedpolicy, pthread_attr_getschedpolicy) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_attr_getscope.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_attr_getscope.c new file mode 100644 index 00000000..aaaf6b9f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_attr_getscope.c @@ -0,0 +1,41 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include "pthreadP.h" + + +int +attribute_protected +__pthread_attr_getscope ( + const pthread_attr_t *attr, + int *scope) +{ + struct pthread_attr *iattr; + + assert (sizeof (*attr) >= sizeof (struct pthread_attr)); + iattr = (struct pthread_attr *) attr; + + /* Store the current values. */ + *scope = (iattr->flags & ATTR_FLAG_SCOPEPROCESS + ? PTHREAD_SCOPE_PROCESS : PTHREAD_SCOPE_SYSTEM); + + return 0; +} +strong_alias (__pthread_attr_getscope, pthread_attr_getscope) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_attr_getstack.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_attr_getstack.c new file mode 100644 index 00000000..cb745368 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_attr_getstack.c @@ -0,0 +1,41 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include "pthreadP.h" + + +int +__pthread_attr_getstack ( + const pthread_attr_t *attr, + void **stackaddr, + size_t *stacksize) +{ + struct pthread_attr *iattr; + + assert (sizeof (*attr) >= sizeof (struct pthread_attr)); + iattr = (struct pthread_attr *) attr; + + /* Store the result. */ + *stackaddr = (char *) iattr->stackaddr - iattr->stacksize; + *stacksize = iattr->stacksize; + + return 0; +} +strong_alias (__pthread_attr_getstack, pthread_attr_getstack) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_attr_getstackaddr.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_attr_getstackaddr.c new file mode 100644 index 00000000..305910c1 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_attr_getstackaddr.c @@ -0,0 +1,45 @@ +/* Copyright (C) 2002, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include "pthreadP.h" + + +int +__pthread_attr_getstackaddr ( + const pthread_attr_t *attr, + void **stackaddr) +{ + struct pthread_attr *iattr; + + assert (sizeof (*attr) >= sizeof (struct pthread_attr)); + iattr = (struct pthread_attr *) attr; + + /* Some code assumes this function to work even if no stack address + has been set. Let them figure it out for themselves what the + value means. Simply store the result. */ + *stackaddr = iattr->stackaddr; + + return 0; +} +strong_alias (__pthread_attr_getstackaddr, pthread_attr_getstackaddr) + +link_warning (pthread_attr_getstackaddr, + "the use of `pthread_attr_getstackaddr' is deprecated, use `pthread_attr_getstack'") diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_attr_getstacksize.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_attr_getstacksize.c new file mode 100644 index 00000000..ec20f6b9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_attr_getstacksize.c @@ -0,0 +1,40 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include "pthreadP.h" + + +int +__pthread_attr_getstacksize ( + const pthread_attr_t *attr, + size_t *stacksize) +{ + struct pthread_attr *iattr; + + assert (sizeof (*attr) >= sizeof (struct pthread_attr)); + iattr = (struct pthread_attr *) attr; + + /* If the user has not set a stack size we return what the system + will use as the default. */ + *stacksize = iattr->stacksize ?: __default_stacksize; + + return 0; +} +strong_alias (__pthread_attr_getstacksize, pthread_attr_getstacksize) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_attr_init.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_attr_init.c new file mode 100644 index 00000000..6de309d8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_attr_init.c @@ -0,0 +1,51 @@ +/* Copyright (C) 2002, 2003, 2004, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include "pthreadP.h" + + +struct pthread_attr *__attr_list; +int __attr_list_lock = LLL_LOCK_INITIALIZER; + + +int +attribute_protected +__pthread_attr_init_2_1 ( + pthread_attr_t *attr) +{ + struct pthread_attr *iattr; + + /* Many elements are initialized to zero so let us do it all at + once. This also takes care of clearing the bytes which are not + internally used. */ + memset (attr, '\0', __SIZEOF_PTHREAD_ATTR_T); + + assert (sizeof (*attr) >= sizeof (struct pthread_attr)); + iattr = (struct pthread_attr *) attr; + + /* Default guard size specified by the standard. */ + iattr->guardsize = getpagesize (); + + return 0; +} +weak_alias(__pthread_attr_init_2_1, pthread_attr_init) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_attr_setdetachstate.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_attr_setdetachstate.c new file mode 100644 index 00000000..a038cbd5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_attr_setdetachstate.c @@ -0,0 +1,47 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include "pthreadP.h" + + +int +attribute_protected +__pthread_attr_setdetachstate (pthread_attr_t *attr, int detachstate) +{ + struct pthread_attr *iattr; + + assert (sizeof (*attr) >= sizeof (struct pthread_attr)); + iattr = (struct pthread_attr *) attr; + + /* Catch invalid values. */ + if (detachstate != PTHREAD_CREATE_DETACHED + && __builtin_expect (detachstate != PTHREAD_CREATE_JOINABLE, 0)) + return EINVAL; + + /* Set the flag. It is nonzero if threads are created detached. */ + if (detachstate == PTHREAD_CREATE_DETACHED) + iattr->flags |= ATTR_FLAG_DETACHSTATE; + else + iattr->flags &= ~ATTR_FLAG_DETACHSTATE; + + return 0; +} +strong_alias (__pthread_attr_setdetachstate, pthread_attr_setdetachstate) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_attr_setguardsize.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_attr_setguardsize.c new file mode 100644 index 00000000..a424312f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_attr_setguardsize.c @@ -0,0 +1,38 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include "pthreadP.h" + + +int +pthread_attr_setguardsize (pthread_attr_t* attr, size_t guardsize) +{ + struct pthread_attr *iattr; + + assert (sizeof (*attr) >= sizeof (struct pthread_attr)); + iattr = (struct pthread_attr *) attr; + + /* Note that we don't round the value here. The standard requires + that subsequent pthread_attr_getguardsize calls return the value + set by the user. */ + iattr->guardsize = guardsize; + + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_attr_setinheritsched.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_attr_setinheritsched.c new file mode 100644 index 00000000..3fc92e5a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_attr_setinheritsched.c @@ -0,0 +1,48 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include "pthreadP.h" + + +int +attribute_protected +__pthread_attr_setinheritsched ( + pthread_attr_t *attr, + int inherit) +{ + struct pthread_attr *iattr; + + assert (sizeof (*attr) >= sizeof (struct pthread_attr)); + iattr = (struct pthread_attr *) attr; + + /* Catch invalid values. */ + if (inherit != PTHREAD_INHERIT_SCHED && inherit != PTHREAD_EXPLICIT_SCHED) + return EINVAL; + + /* Store the new values. */ + if (inherit != PTHREAD_INHERIT_SCHED) + iattr->flags |= ATTR_FLAG_NOTINHERITSCHED; + else + iattr->flags &= ~ATTR_FLAG_NOTINHERITSCHED; + + return 0; +} +strong_alias (__pthread_attr_setinheritsched, pthread_attr_setinheritsched) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_attr_setschedparam.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_attr_setschedparam.c new file mode 100644 index 00000000..13f7313b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_attr_setschedparam.c @@ -0,0 +1,49 @@ +/* Copyright (C) 2002, 2004, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include "pthreadP.h" + + +int +attribute_protected +__pthread_attr_setschedparam ( + pthread_attr_t *attr, + const struct sched_param *param) +{ + assert (sizeof (*attr) >= sizeof (struct pthread_attr)); + struct pthread_attr *iattr = (struct pthread_attr *) attr; + + int min = sched_get_priority_min (iattr->schedpolicy); + int max = sched_get_priority_max (iattr->schedpolicy); + if (min == -1 || max == -1 + || param->sched_priority > max || param->sched_priority < min) + return EINVAL; + + /* Copy the new values. */ + memcpy (&iattr->schedparam, param, sizeof (struct sched_param)); + + /* Remember we set the value. */ + iattr->flags |= ATTR_FLAG_SCHED_SET; + + return 0; +} +strong_alias (__pthread_attr_setschedparam, pthread_attr_setschedparam) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_attr_setschedpolicy.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_attr_setschedpolicy.c new file mode 100644 index 00000000..bcc69ba3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_attr_setschedpolicy.c @@ -0,0 +1,48 @@ +/* Copyright (C) 2002, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include "pthreadP.h" + + +int +attribute_protected +__pthread_attr_setschedpolicy ( + pthread_attr_t *attr, + int policy) +{ + struct pthread_attr *iattr; + + assert (sizeof (*attr) >= sizeof (struct pthread_attr)); + iattr = (struct pthread_attr *) attr; + + /* Catch invalid values. */ + if (policy != SCHED_OTHER && policy != SCHED_FIFO && policy != SCHED_RR) + return EINVAL; + + /* Store the new values. */ + iattr->schedpolicy = policy; + + /* Remember we set the value. */ + iattr->flags |= ATTR_FLAG_POLICY_SET; + + return 0; +} +strong_alias (__pthread_attr_setschedpolicy, pthread_attr_setschedpolicy) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_attr_setscope.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_attr_setscope.c new file mode 100644 index 00000000..b9b752f8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_attr_setscope.c @@ -0,0 +1,52 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include "pthreadP.h" + + +int +attribute_protected +__pthread_attr_setscope ( + pthread_attr_t *attr, + int scope) +{ + struct pthread_attr *iattr; + + assert (sizeof (*attr) >= sizeof (struct pthread_attr)); + iattr = (struct pthread_attr *) attr; + + /* Catch invalid values. */ + switch (scope) + { + case PTHREAD_SCOPE_SYSTEM: + iattr->flags &= ~ATTR_FLAG_SCOPEPROCESS; + break; + + case PTHREAD_SCOPE_PROCESS: + return ENOTSUP; + + default: + return EINVAL; + } + + return 0; +} +strong_alias (__pthread_attr_setscope, pthread_attr_setscope) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_attr_setstack.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_attr_setstack.c new file mode 100644 index 00000000..d400f3db --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_attr_setstack.c @@ -0,0 +1,56 @@ +/* Copyright (C) 2002, 2003, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include "pthreadP.h" + + +int +__pthread_attr_setstack ( + pthread_attr_t *attr, + void *stackaddr, + size_t stacksize) +{ + struct pthread_attr *iattr; + + assert (sizeof (*attr) >= sizeof (struct pthread_attr)); + iattr = (struct pthread_attr *) attr; + + /* Catch invalid sizes. */ + if (stacksize < PTHREAD_STACK_MIN) + return EINVAL; + +#ifdef EXTRA_PARAM_CHECKS + EXTRA_PARAM_CHECKS; +#endif + + iattr->stacksize = stacksize; + iattr->stackaddr = (char *) stackaddr + stacksize; + iattr->flags |= ATTR_FLAG_STACKADDR; + + return 0; +} + +#if PTHREAD_STACK_MIN == 16384 +strong_alias(__pthread_attr_setstack, pthread_attr_setstack) +#else +weak_alias(__pthread_attr_setstack, pthread_attr_setstack) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_attr_setstackaddr.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_attr_setstackaddr.c new file mode 100644 index 00000000..ead54baf --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_attr_setstackaddr.c @@ -0,0 +1,47 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include "pthreadP.h" + + +int +__pthread_attr_setstackaddr ( + pthread_attr_t *attr, + void *stackaddr) +{ + struct pthread_attr *iattr; + +#ifdef EXTRA_PARAM_CHECKS + EXTRA_PARAM_CHECKS; +#endif + + assert (sizeof (*attr) >= sizeof (struct pthread_attr)); + iattr = (struct pthread_attr *) attr; + + iattr->stackaddr = stackaddr; + iattr->flags |= ATTR_FLAG_STACKADDR; + + return 0; +} +strong_alias (__pthread_attr_setstackaddr, pthread_attr_setstackaddr) + +link_warning (pthread_attr_setstackaddr, + "the use of `pthread_attr_setstackaddr' is deprecated, use `pthread_attr_setstack'") diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_attr_setstacksize.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_attr_setstacksize.c new file mode 100644 index 00000000..24e5b0a7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_attr_setstacksize.c @@ -0,0 +1,49 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include "pthreadP.h" + + +int +__pthread_attr_setstacksize ( + pthread_attr_t *attr, + size_t stacksize) +{ + struct pthread_attr *iattr; + + assert (sizeof (*attr) >= sizeof (struct pthread_attr)); + iattr = (struct pthread_attr *) attr; + + /* Catch invalid sizes. */ + if (stacksize < PTHREAD_STACK_MIN) + return EINVAL; + + iattr->stacksize = stacksize; + + return 0; +} + +#if PTHREAD_STACK_MIN == 16384 +strong_alias(__pthread_attr_setstacksize, pthread_attr_setstacksize) +#else +weak_alias(__pthread_attr_setstacksize, pthread_attr_setstacksize) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_barrierattr_destroy.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_barrierattr_destroy.c new file mode 100644 index 00000000..5cdcb76f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_barrierattr_destroy.c @@ -0,0 +1,29 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "pthreadP.h" + + +int +pthread_barrierattr_destroy (pthread_barrierattr_t *attr) +{ + /* Nothing to do. */ + + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_barrierattr_getpshared.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_barrierattr_getpshared.c new file mode 100644 index 00000000..ee96c022 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_barrierattr_getpshared.c @@ -0,0 +1,31 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "pthreadP.h" + + +int +pthread_barrierattr_getpshared ( + const pthread_barrierattr_t *attr, + int *pshared) +{ + *pshared = ((const struct pthread_barrierattr *) attr)->pshared; + + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_barrierattr_init.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_barrierattr_init.c new file mode 100644 index 00000000..17391f91 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_barrierattr_init.c @@ -0,0 +1,29 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "pthreadP.h" + + +int +pthread_barrierattr_init (pthread_barrierattr_t *attr) +{ + ((struct pthread_barrierattr *) attr)->pshared = PTHREAD_PROCESS_PRIVATE; + + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_barrierattr_setpshared.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_barrierattr_setpshared.c new file mode 100644 index 00000000..fbf6fcb2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_barrierattr_setpshared.c @@ -0,0 +1,40 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include "pthreadP.h" + + +int +pthread_barrierattr_setpshared ( + pthread_barrierattr_t *attr, + int pshared) +{ + struct pthread_barrierattr *iattr; + + if (pshared != PTHREAD_PROCESS_PRIVATE + && __builtin_expect (pshared != PTHREAD_PROCESS_SHARED, 0)) + return EINVAL; + + iattr = (struct pthread_barrierattr *) attr; + + iattr->pshared = pshared; + + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_cancel.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_cancel.c new file mode 100644 index 00000000..4a958bcd --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_cancel.c @@ -0,0 +1,108 @@ +/* Copyright (C) 2002, 2003, 2004, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include "pthreadP.h" +#include "atomic.h" +#include +#include + + +int +pthread_cancel ( + pthread_t th) +{ + volatile struct pthread *pd = (volatile struct pthread *) th; + + /* Make sure the descriptor is valid. */ + if (INVALID_TD_P (pd)) + /* Not a valid thread handle. */ + return ESRCH; + +#ifdef SHARED + pthread_cancel_init (); +#endif + int result = 0; + int oldval; + int newval; + do + { + again: + oldval = pd->cancelhandling; + newval = oldval | CANCELING_BITMASK | CANCELED_BITMASK; + + /* Avoid doing unnecessary work. The atomic operation can + potentially be expensive if the bug has to be locked and + remote cache lines have to be invalidated. */ + if (oldval == newval) + break; + + /* If the cancellation is handled asynchronously just send a + signal. We avoid this if possible since it's more + expensive. */ + if (CANCEL_ENABLED_AND_CANCELED_AND_ASYNCHRONOUS (newval)) + { + /* Mark the cancellation as "in progress". */ + if (atomic_compare_and_exchange_bool_acq (&pd->cancelhandling, + oldval | CANCELING_BITMASK, + oldval)) + goto again; + + /* The cancellation handler will take care of marking the + thread as canceled. */ + INTERNAL_SYSCALL_DECL (err); + + /* One comment: The PID field in the TCB can temporarily be + changed (in fork). But this must not affect this code + here. Since this function would have to be called while + the thread is executing fork, it would have to happen in + a signal handler. But this is no allowed, pthread_cancel + is not guaranteed to be async-safe. */ + int val; +#if __ASSUME_TGKILL + val = INTERNAL_SYSCALL (tgkill, err, 3, + THREAD_GETMEM (THREAD_SELF, pid), pd->tid, + SIGCANCEL); +#else +# ifdef __NR_tgkill + val = INTERNAL_SYSCALL (tgkill, err, 3, + THREAD_GETMEM (THREAD_SELF, pid), pd->tid, + SIGCANCEL); + if (INTERNAL_SYSCALL_ERROR_P (val, err) + && INTERNAL_SYSCALL_ERRNO (val, err) == ENOSYS) +# endif + val = INTERNAL_SYSCALL (tkill, err, 2, pd->tid, SIGCANCEL); +#endif + + if (INTERNAL_SYSCALL_ERROR_P (val, err)) + result = INTERNAL_SYSCALL_ERRNO (val, err); + + break; + } + } + /* Mark the thread as canceled. This has to be done + atomically since other bits could be modified as well. */ + while (atomic_compare_and_exchange_bool_acq (&pd->cancelhandling, newval, + oldval)); + + return result; +} + +PTHREAD_STATIC_FN_REQUIRE (pthread_create) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_clock_gettime.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_clock_gettime.c new file mode 100644 index 00000000..a71174c9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_clock_gettime.c @@ -0,0 +1,69 @@ +/* Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include +#include "pthreadP.h" + + +#if HP_TIMING_AVAIL +int +__pthread_clock_gettime (clockid_t clock_id, hp_timing_t freq, + struct timespec *tp) +{ + hp_timing_t tsc; + + /* Get the current counter. */ + HP_TIMING_NOW (tsc); + + /* This is the ID of the thread we are looking for. */ + pid_t tid = ((unsigned int) clock_id) >> CLOCK_IDFIELD_SIZE; + + /* Compute the offset since the start time of the process. */ + if (tid == 0 || tid == THREAD_GETMEM (THREAD_SELF, tid)) + /* Our own clock. */ + tsc -= THREAD_GETMEM (THREAD_SELF, cpuclock_offset); + else + { + /* This is more complicated. We have to locate the thread based + on the ID. This means walking the list of existing + threads. */ + struct pthread *thread = __find_thread_by_id (tid); + if (thread == NULL) + { + __set_errno (EINVAL); + return -1; + } + + /* There is a race here. The thread might terminate and the stack + become unusable. But this is the user's problem. */ + tsc -= thread->cpuclock_offset; + } + + /* Compute the seconds. */ + tp->tv_sec = tsc / freq; + + /* And the nanoseconds. This computation should be stable until + we get machines with about 16GHz frequency. */ + tp->tv_nsec = ((tsc % freq) * 1000000000ull) / freq; + + return 0; +} +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_clock_settime.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_clock_settime.c new file mode 100644 index 00000000..61002a8f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_clock_settime.c @@ -0,0 +1,56 @@ +/* Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include +#include "pthreadP.h" + + +#if HP_TIMING_AVAIL +int +__pthread_clock_settime (clockid_t clock_id, hp_timing_t offset) +{ + /* This is the ID of the thread we are looking for. */ + pid_t tid = ((unsigned int) clock_id) >> CLOCK_IDFIELD_SIZE; + + /* Compute the offset since the start time of the process. */ + if (tid == 0 || tid == THREAD_GETMEM (THREAD_SELF, tid)) + /* Our own clock. */ + THREAD_SETMEM (THREAD_SELF, cpuclock_offset, offset); + else + { + /* This is more complicated. We have to locate the thread based + on the ID. This means walking the list of existing + threads. */ + struct pthread *thread = __find_thread_by_id (tid); + if (thread == NULL) + { + __set_errno (EINVAL); + return -1; + } + + /* There is a race here. The thread might terminate and the stack + become unusable. But this is the user's problem. */ + thread->cpuclock_offset = offset; + } + + return 0; +} +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_cond_destroy.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_cond_destroy.c new file mode 100644 index 00000000..cb49ce1d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_cond_destroy.c @@ -0,0 +1,84 @@ +/* Copyright (C) 2002, 2003, 2004, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include "pthreadP.h" + + +int +attribute_protected +__pthread_cond_destroy ( + pthread_cond_t *cond) +{ + int pshared = (cond->__data.__mutex == (void *) ~0l) + ? LLL_SHARED : LLL_PRIVATE; + + /* Make sure we are alone. */ + lll_lock (cond->__data.__lock, pshared); + + if (cond->__data.__total_seq > cond->__data.__wakeup_seq) + { + /* If there are still some waiters which have not been + woken up, this is an application bug. */ + lll_unlock (cond->__data.__lock, pshared); + return EBUSY; + } + + /* Tell pthread_cond_*wait that this condvar is being destroyed. */ + cond->__data.__total_seq = -1ULL; + + /* If there are waiters which have been already signalled or + broadcasted, but still are using the pthread_cond_t structure, + pthread_cond_destroy needs to wait for them. */ + unsigned int nwaiters = cond->__data.__nwaiters; + + if (nwaiters >= (1 << COND_NWAITERS_SHIFT)) + { + /* Wake everybody on the associated mutex in case there are + threads that have been requeued to it. + Without this, pthread_cond_destroy could block potentially + for a long time or forever, as it would depend on other + thread's using the mutex. + When all threads waiting on the mutex are woken up, pthread_cond_wait + only waits for threads to acquire and release the internal + condvar lock. */ + if (cond->__data.__mutex != NULL + && cond->__data.__mutex != (void *) ~0l) + { + pthread_mutex_t *mut = (pthread_mutex_t *) cond->__data.__mutex; + lll_futex_wake (&mut->__data.__lock, INT_MAX, + PTHREAD_MUTEX_PSHARED (mut)); + } + + do + { + lll_unlock (cond->__data.__lock, pshared); + + lll_futex_wait (&cond->__data.__nwaiters, nwaiters, pshared); + + lll_lock (cond->__data.__lock, pshared); + + nwaiters = cond->__data.__nwaiters; + } + while (nwaiters >= (1 << COND_NWAITERS_SHIFT)); + } + + return 0; +} +weak_alias(__pthread_cond_destroy, pthread_cond_destroy) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_cond_init.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_cond_init.c new file mode 100644 index 00000000..f7187a39 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_cond_init.c @@ -0,0 +1,47 @@ +/* Copyright (C) 2002, 2003, 2004, 2005, 2007, 2008 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "pthreadP.h" + + +int +attribute_protected +__pthread_cond_init ( + pthread_cond_t *cond, + const pthread_condattr_t *cond_attr) +{ + struct pthread_condattr *icond_attr = (struct pthread_condattr *) cond_attr; + + cond->__data.__lock = LLL_LOCK_INITIALIZER; + cond->__data.__futex = 0; + cond->__data.__nwaiters = (icond_attr != NULL + ? ((icond_attr->value >> 1) + & ((1 << COND_NWAITERS_SHIFT) - 1)) + : CLOCK_REALTIME); + cond->__data.__total_seq = 0; + cond->__data.__wakeup_seq = 0; + cond->__data.__woken_seq = 0; + cond->__data.__mutex = (icond_attr == NULL || (icond_attr->value & 1) == 0 + ? NULL : (void *) ~0l); + cond->__data.__broadcast_seq = 0; + + return 0; +} +weak_alias(__pthread_cond_init, pthread_cond_init) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_condattr_destroy.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_condattr_destroy.c new file mode 100644 index 00000000..dcaaa0fd --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_condattr_destroy.c @@ -0,0 +1,30 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "pthreadP.h" + + +int +attribute_protected +__pthread_condattr_destroy (pthread_condattr_t *attr) +{ + /* Nothing to be done. */ + return 0; +} +strong_alias (__pthread_condattr_destroy, pthread_condattr_destroy) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_condattr_getclock.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_condattr_getclock.c new file mode 100644 index 00000000..3603f848 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_condattr_getclock.c @@ -0,0 +1,31 @@ +/* Copyright (C) 2003, 2004, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "pthreadP.h" + + +int +pthread_condattr_getclock ( + const pthread_condattr_t *attr, + clockid_t *clock_id) +{ + *clock_id = (((((const struct pthread_condattr *) attr)->value) >> 1) + & ((1 << COND_NWAITERS_SHIFT) - 1)); + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_condattr_getpshared.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_condattr_getpshared.c new file mode 100644 index 00000000..a558fdb8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_condattr_getpshared.c @@ -0,0 +1,31 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "pthreadP.h" + + +int +pthread_condattr_getpshared ( + const pthread_condattr_t *attr, + int *pshared) +{ + *pshared = ((const struct pthread_condattr *) attr)->value & 1; + + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_condattr_init.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_condattr_init.c new file mode 100644 index 00000000..7cd82a82 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_condattr_init.c @@ -0,0 +1,32 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include "pthreadP.h" + + +int +attribute_protected +__pthread_condattr_init (pthread_condattr_t *attr) +{ + memset (attr, '\0', sizeof (*attr)); + + return 0; +} +strong_alias (__pthread_condattr_init, pthread_condattr_init) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_condattr_setclock.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_condattr_setclock.c new file mode 100644 index 00000000..87597c8b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_condattr_setclock.c @@ -0,0 +1,73 @@ +/* Copyright (C) 2003, 2004, 2007, 2008 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include "pthreadP.h" +#include + + +int +pthread_condattr_setclock ( + pthread_condattr_t *attr, + clockid_t clock_id) +{ + /* Only a few clocks are allowed. CLOCK_REALTIME is always allowed. + CLOCK_MONOTONIC only if the kernel has the necessary support. */ + if (clock_id == CLOCK_MONOTONIC) + { +#ifndef __ASSUME_POSIX_TIMERS +# ifdef __NR_clock_getres + /* Check whether the clock is available. */ + static int avail; + + if (avail == 0) + { + struct timespec ts; + + INTERNAL_SYSCALL_DECL (err); + int val; + val = INTERNAL_SYSCALL (clock_getres, err, 2, CLOCK_MONOTONIC, &ts); + avail = INTERNAL_SYSCALL_ERROR_P (val, err) ? -1 : 1; + } + + if (avail < 0) +# endif + /* Not available. */ + return EINVAL; +#endif + } + else if (clock_id != CLOCK_REALTIME) + /* If more clocks are allowed some day the storing of the clock ID + in the pthread_cond_t structure needs to be adjusted. */ + return EINVAL; + + /* Make sure the value fits in the bits we reserved. */ + assert (clock_id < (1 << COND_NWAITERS_SHIFT)); + + int *valuep = &((struct pthread_condattr *) attr)->value; + + *valuep = ((*valuep & ~(((1 << COND_NWAITERS_SHIFT) - 1) << 1)) + | (clock_id << 1)); + + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_condattr_setpshared.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_condattr_setpshared.c new file mode 100644 index 00000000..f3d39aa2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_condattr_setpshared.c @@ -0,0 +1,37 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +int +pthread_condattr_setpshared ( + pthread_condattr_t *attr, + int pshared) +{ + if (pshared != PTHREAD_PROCESS_PRIVATE + && __builtin_expect (pshared != PTHREAD_PROCESS_SHARED, 0)) + return EINVAL; + + int *valuep = &((struct pthread_condattr *) attr)->value; + + *valuep = (*valuep & ~1) | (pshared != PTHREAD_PROCESS_PRIVATE); + + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_create.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_create.c new file mode 100644 index 00000000..63e5588d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_create.c @@ -0,0 +1,586 @@ +/* Copyright (C) 2002-2007,2008,2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include "pthreadP.h" +#include +#include +#include +#include +#include +#include + + +/* Local function to start thread and handle cleanup. */ +static int start_thread (void *arg); + + +/* Nozero if debugging mode is enabled. */ +int __pthread_debug; + +/* Globally enabled events. */ +static td_thr_events_t __nptl_threads_events __attribute_used__; + +/* Pointer to descriptor with the last event. */ +static struct pthread *__nptl_last_event __attribute_used__; + +/* Number of threads running. */ +unsigned int __nptl_nthreads = 1; + + +/* Code to allocate and deallocate a stack. */ +#include "allocatestack.c" + +/* Code to create the thread. */ +#include + + +struct pthread * +internal_function +__find_in_stack_list ( + struct pthread *pd) +{ + list_t *entry; + struct pthread *result = NULL; + + lll_lock (stack_cache_lock, LLL_PRIVATE); + + list_for_each (entry, &stack_used) + { + struct pthread *curp; + + curp = list_entry (entry, struct pthread, list); + if (curp == pd) + { + result = curp; + break; + } + } + + if (result == NULL) + list_for_each (entry, &__stack_user) + { + struct pthread *curp; + + curp = list_entry (entry, struct pthread, list); + if (curp == pd) + { + result = curp; + break; + } + } + + lll_unlock (stack_cache_lock, LLL_PRIVATE); + + return result; +} + + +/* Deallocate POSIX thread-local-storage. */ +void +attribute_hidden +__nptl_deallocate_tsd (void) +{ + struct pthread *self = THREAD_SELF; + + /* Maybe no data was ever allocated. This happens often so we have + a flag for this. */ + if (THREAD_GETMEM (self, specific_used)) + { + size_t round; + size_t cnt; + + round = 0; + do + { + size_t idx; + + /* So far no new nonzero data entry. */ + THREAD_SETMEM (self, specific_used, false); + + for (cnt = idx = 0; cnt < PTHREAD_KEY_1STLEVEL_SIZE; ++cnt) + { + struct pthread_key_data *level2; + + level2 = THREAD_GETMEM_NC (self, specific, cnt); + + if (level2 != NULL) + { + size_t inner; + + for (inner = 0; inner < PTHREAD_KEY_2NDLEVEL_SIZE; + ++inner, ++idx) + { + void *data = level2[inner].data; + + if (data != NULL) + { + /* Always clear the data. */ + level2[inner].data = NULL; + + /* Make sure the data corresponds to a valid + key. This test fails if the key was + deallocated and also if it was + re-allocated. It is the user's + responsibility to free the memory in this + case. */ + if (level2[inner].seq + == __pthread_keys[idx].seq + /* It is not necessary to register a destructor + function. */ + && __pthread_keys[idx].destr != NULL) + /* Call the user-provided destructor. */ + __pthread_keys[idx].destr (data); + } + } + } + else + idx += PTHREAD_KEY_1STLEVEL_SIZE; + } + + if (THREAD_GETMEM (self, specific_used) == 0) + /* No data has been modified. */ + goto just_free; + } + /* We only repeat the process a fixed number of times. */ + while (__builtin_expect (++round < PTHREAD_DESTRUCTOR_ITERATIONS, 0)); + + /* Just clear the memory of the first block for reuse. */ + memset (&THREAD_SELF->specific_1stblock, '\0', + sizeof (self->specific_1stblock)); + + just_free: + /* Free the memory for the other blocks. */ + for (cnt = 1; cnt < PTHREAD_KEY_1STLEVEL_SIZE; ++cnt) + { + struct pthread_key_data *level2; + + level2 = THREAD_GETMEM_NC (self, specific, cnt); + if (level2 != NULL) + { + /* The first block is allocated as part of the thread + descriptor. */ + free (level2); + THREAD_SETMEM_NC (self, specific, cnt, NULL); + } + } + + THREAD_SETMEM (self, specific_used, false); + } +} + + +/* Deallocate a thread's stack after optionally making sure the thread + descriptor is still valid. */ +void +internal_function +__free_tcb (struct pthread *pd) +{ + /* The thread is exiting now. */ + if (__builtin_expect (atomic_bit_test_set (&pd->cancelhandling, + TERMINATED_BIT) == 0, 1)) + { + /* Remove the descriptor from the list. */ + if (DEBUGGING_P && __find_in_stack_list (pd) == NULL) + /* Something is really wrong. The descriptor for a still + running thread is gone. */ + abort (); + + /* Free TPP data. */ + if (__builtin_expect (pd->tpp != NULL, 0)) + { + struct priority_protection_data *tpp = pd->tpp; + + pd->tpp = NULL; + free (tpp); + } + + /* Queue the stack memory block for reuse and exit the process. The + kernel will signal via writing to the address returned by + QUEUE-STACK when the stack is available. */ + __deallocate_stack (pd); + } +} + + +static int +start_thread (void *arg) +{ + struct pthread *pd = (struct pthread *) arg; + +#if HP_TIMING_AVAIL + /* Remember the time when the thread was started. */ + hp_timing_t now; + HP_TIMING_NOW (now); + THREAD_SETMEM (pd, cpuclock_offset, now); +#endif +#if defined __UCLIBC_HAS_IPV4__ || defined __UCLIBC_HAS_IPV6__ + /* Initialize resolver state pointer. */ + __resp = &pd->res; +#endif +#ifdef __NR_set_robust_list +# ifndef __ASSUME_SET_ROBUST_LIST + if (__set_robust_list_avail >= 0) +# endif + { + INTERNAL_SYSCALL_DECL (err); + /* This call should never fail because the initial call in init.c + succeeded. */ + INTERNAL_SYSCALL (set_robust_list, err, 2, &pd->robust_head, + sizeof (struct robust_list_head)); + } +#endif + + /* If the parent was running cancellation handlers while creating + the thread the new thread inherited the signal mask. Reset the + cancellation signal mask. */ + if (__builtin_expect (pd->parent_cancelhandling & CANCELING_BITMASK, 0)) + { + INTERNAL_SYSCALL_DECL (err); + sigset_t mask; + __sigemptyset (&mask); + __sigaddset (&mask, SIGCANCEL); + (void) INTERNAL_SYSCALL (rt_sigprocmask, err, 4, SIG_UNBLOCK, &mask, + NULL, _NSIG / 8); + } + + /* This is where the try/finally block should be created. For + compilers without that support we do use setjmp. */ + struct pthread_unwind_buf unwind_buf; + + /* No previous handlers. */ + unwind_buf.priv.data.prev = NULL; + unwind_buf.priv.data.cleanup = NULL; + + int not_first_call; + not_first_call = setjmp ((struct __jmp_buf_tag *) unwind_buf.cancel_jmp_buf); + if (__builtin_expect (! not_first_call, 1)) + { + /* Store the new cleanup handler info. */ + THREAD_SETMEM (pd, cleanup_jmp_buf, &unwind_buf); + + if (__builtin_expect (pd->stopped_start, 0)) + { + int oldtype = CANCEL_ASYNC (); + + /* Get the lock the parent locked to force synchronization. */ + lll_lock (pd->lock, LLL_PRIVATE); + /* And give it up right away. */ + lll_unlock (pd->lock, LLL_PRIVATE); + + CANCEL_RESET (oldtype); + } + + /* Run the code the user provided. */ +#ifdef CALL_THREAD_FCT + THREAD_SETMEM (pd, result, CALL_THREAD_FCT (pd)); +#else + THREAD_SETMEM (pd, result, pd->start_routine (pd->arg)); +#endif + } + + /* Run the destructor for the thread-local data. */ + __nptl_deallocate_tsd (); + + /* Clean up any state libc stored in thread-local variables. */ + /* disable for now + __libc_thread_freeres (); + */ + /* If this is the last thread we terminate the process now. We + do not notify the debugger, it might just irritate it if there + is no thread left. */ + if (__builtin_expect (atomic_decrement_and_test (&__nptl_nthreads), 0)) + /* This was the last thread. */ + exit (0); + + /* Report the death of the thread if this is wanted. */ + if (__builtin_expect (pd->report_events, 0)) + { + /* See whether TD_DEATH is in any of the mask. */ + const int idx = __td_eventword (TD_DEATH); + const uint32_t mask = __td_eventmask (TD_DEATH); + + if ((mask & (__nptl_threads_events.event_bits[idx] + | pd->eventbuf.eventmask.event_bits[idx])) != 0) + { + /* Yep, we have to signal the death. Add the descriptor to + the list but only if it is not already on it. */ + if (pd->nextevent == NULL) + { + pd->eventbuf.eventnum = TD_DEATH; + pd->eventbuf.eventdata = pd; + + do + pd->nextevent = __nptl_last_event; + while (atomic_compare_and_exchange_bool_acq (&__nptl_last_event, + pd, pd->nextevent)); + } + + /* Now call the function to signal the event. */ + __nptl_death_event (); + } + } + + /* The thread is exiting now. Don't set this bit until after we've hit + the event-reporting breakpoint, so that td_thr_get_info on us while at + the breakpoint reports TD_THR_RUN state rather than TD_THR_ZOMBIE. */ + atomic_bit_set (&pd->cancelhandling, EXITING_BIT); + +#ifndef __ASSUME_SET_ROBUST_LIST + /* If this thread has any robust mutexes locked, handle them now. */ +# if __WORDSIZE == 64 + void *robust = pd->robust_head.list; +# else + __pthread_slist_t *robust = pd->robust_list.__next; +# endif + /* We let the kernel do the notification if it is able to do so. + If we have to do it here there for sure are no PI mutexes involved + since the kernel support for them is even more recent. */ + if (__set_robust_list_avail < 0 + && __builtin_expect (robust != (void *) &pd->robust_head, 0)) + { + do + { + struct __pthread_mutex_s *this = (struct __pthread_mutex_s *) + ((char *) robust - offsetof (struct __pthread_mutex_s, + __list.__next)); + robust = *((void **) robust); + +# ifdef __PTHREAD_MUTEX_HAVE_PREV + this->__list.__prev = NULL; +# endif + this->__list.__next = NULL; + + lll_robust_dead (this->__lock, /* XYZ */ LLL_SHARED); + } + while (robust != (void *) &pd->robust_head); + } +#endif + + /* Mark the memory of the stack as usable to the kernel. We free + everything except for the space used for the TCB itself. */ + size_t pagesize_m1 = __getpagesize () - 1; +#ifdef _STACK_GROWS_DOWN + char *sp = CURRENT_STACK_FRAME; + size_t freesize = (sp - (char *) pd->stackblock) & ~pagesize_m1; +#else +# error "to do" +#endif + assert (freesize < pd->stackblock_size); + if (freesize > PTHREAD_STACK_MIN) + madvise (pd->stackblock, freesize - PTHREAD_STACK_MIN, MADV_DONTNEED); + + /* If the thread is detached free the TCB. */ + if (IS_DETACHED (pd)) + /* Free the TCB. */ + __free_tcb (pd); + else if (__builtin_expect (pd->cancelhandling & SETXID_BITMASK, 0)) + { + /* Some other thread might call any of the setXid functions and expect + us to reply. In this case wait until we did that. */ + do + lll_futex_wait (&pd->setxid_futex, 0, LLL_PRIVATE); + while (pd->cancelhandling & SETXID_BITMASK); + + /* Reset the value so that the stack can be reused. */ + pd->setxid_futex = 0; + } + + /* We cannot call '_exit' here. '_exit' will terminate the process. + + The 'exit' implementation in the kernel will signal when the + process is really dead since 'clone' got passed the CLONE_CLEARTID + flag. The 'tid' field in the TCB will be set to zero. + + The exit code is zero since in case all threads exit by calling + 'pthread_exit' the exit status must be 0 (zero). */ + __exit_thread_inline (0); + + /* NOTREACHED */ + return 0; +} + + +/* Default thread attributes for the case when the user does not + provide any. */ +static const struct pthread_attr default_attr = + { + /* Just some value > 0 which gets rounded to the nearest page size. */ + .guardsize = 1, + }; + + +int +__pthread_create_2_1 ( + pthread_t *newthread, + const pthread_attr_t *attr, + void *(*start_routine) (void *), + void *arg) +{ + STACK_VARIABLES; + + const struct pthread_attr *iattr = (struct pthread_attr *) attr; + if (iattr == NULL) + /* Is this the best idea? On NUMA machines this could mean + accessing far-away memory. */ + iattr = &default_attr; + + struct pthread *pd = NULL; + int err = ALLOCATE_STACK (iattr, &pd); + if (__builtin_expect (err != 0, 0)) + /* Something went wrong. Maybe a parameter of the attributes is + invalid or we could not allocate memory. */ + return err; + + + /* Initialize the TCB. All initializations with zero should be + performed in 'get_cached_stack'. This way we avoid doing this if + the stack freshly allocated with 'mmap'. */ + +#ifdef TLS_TCB_AT_TP + /* Reference to the TCB itself. */ + pd->header.self = pd; + + /* Self-reference for TLS. */ + pd->header.tcb = pd; +#endif + + /* Store the address of the start routine and the parameter. Since + we do not start the function directly the stillborn thread will + get the information from its thread descriptor. */ + pd->start_routine = start_routine; + pd->arg = arg; + + /* Copy the thread attribute flags. */ + struct pthread *self = THREAD_SELF; + pd->flags = ((iattr->flags & ~(ATTR_FLAG_SCHED_SET | ATTR_FLAG_POLICY_SET)) + | (self->flags & (ATTR_FLAG_SCHED_SET | ATTR_FLAG_POLICY_SET))); + + /* Initialize the field for the ID of the thread which is waiting + for us. This is a self-reference in case the thread is created + detached. */ + pd->joinid = iattr->flags & ATTR_FLAG_DETACHSTATE ? pd : NULL; + + /* The debug events are inherited from the parent. */ + pd->eventbuf = self->eventbuf; + + + /* Copy the parent's scheduling parameters. The flags will say what + is valid and what is not. */ + pd->schedpolicy = self->schedpolicy; + pd->schedparam = self->schedparam; + + /* Copy the stack guard canary. */ +#ifdef THREAD_COPY_STACK_GUARD + THREAD_COPY_STACK_GUARD (pd); +#endif + + /* Copy the pointer guard value. */ +#ifdef THREAD_COPY_POINTER_GUARD + THREAD_COPY_POINTER_GUARD (pd); +#endif + + /* Determine scheduling parameters for the thread. */ + if (attr != NULL + && __builtin_expect ((iattr->flags & ATTR_FLAG_NOTINHERITSCHED) != 0, 0) + && (iattr->flags & (ATTR_FLAG_SCHED_SET | ATTR_FLAG_POLICY_SET)) != 0) + { + INTERNAL_SYSCALL_DECL (scerr); + + /* Use the scheduling parameters the user provided. */ + if (iattr->flags & ATTR_FLAG_POLICY_SET) + pd->schedpolicy = iattr->schedpolicy; + else if ((pd->flags & ATTR_FLAG_POLICY_SET) == 0) + { + pd->schedpolicy = INTERNAL_SYSCALL (sched_getscheduler, scerr, 1, 0); + pd->flags |= ATTR_FLAG_POLICY_SET; + } + + if (iattr->flags & ATTR_FLAG_SCHED_SET) + memcpy (&pd->schedparam, &iattr->schedparam, + sizeof (struct sched_param)); + else if ((pd->flags & ATTR_FLAG_SCHED_SET) == 0) + { + INTERNAL_SYSCALL (sched_getparam, scerr, 2, 0, &pd->schedparam); + pd->flags |= ATTR_FLAG_SCHED_SET; + } + + /* Check for valid priorities. */ + int minprio = INTERNAL_SYSCALL (sched_get_priority_min, scerr, 1, + iattr->schedpolicy); + int maxprio = INTERNAL_SYSCALL (sched_get_priority_max, scerr, 1, + iattr->schedpolicy); + if (pd->schedparam.sched_priority < minprio + || pd->schedparam.sched_priority > maxprio) + { + err = EINVAL; + goto errout; + } + } + + /* Pass the descriptor to the caller. */ + *newthread = (pthread_t) pd; + + /* Remember whether the thread is detached or not. In case of an + error we have to free the stacks of non-detached stillborn + threads. */ + bool is_detached = IS_DETACHED (pd); + + /* Start the thread. */ + err = create_thread (pd, iattr, STACK_VARIABLES_ARGS); + if (err != 0) + { + /* Something went wrong. Free the resources. */ + if (!is_detached) + { + errout: + __deallocate_stack (pd); + } + return err; + } + + return 0; +} +weak_alias(__pthread_create_2_1, pthread_create) + +/* Information for libthread_db. */ + +#include "../nptl_db/db_info.c" + +/* If pthread_create is present, libgcc_eh.a and libsupc++.a expects some other POSIX thread + functions to be present as well. */ +PTHREAD_STATIC_FN_REQUIRE (pthread_mutex_lock) +PTHREAD_STATIC_FN_REQUIRE (pthread_mutex_trylock) +PTHREAD_STATIC_FN_REQUIRE (pthread_mutex_unlock) + +PTHREAD_STATIC_FN_REQUIRE (pthread_once) +PTHREAD_STATIC_FN_REQUIRE (pthread_cancel) + +PTHREAD_STATIC_FN_REQUIRE (pthread_key_create) +PTHREAD_STATIC_FN_REQUIRE (pthread_key_delete) +PTHREAD_STATIC_FN_REQUIRE (pthread_setspecific) +PTHREAD_STATIC_FN_REQUIRE (pthread_getspecific) + +/* UCLIBC_MUTEX_xxx macros expects to have these as well */ +PTHREAD_STATIC_FN_REQUIRE (pthread_mutex_init) +PTHREAD_STATIC_FN_REQUIRE (_pthread_cleanup_push_defer) +PTHREAD_STATIC_FN_REQUIRE (_pthread_cleanup_pop_restore) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_detach.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_detach.c new file mode 100644 index 00000000..054d7793 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_detach.c @@ -0,0 +1,56 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include "pthreadP.h" +#include + + +int +pthread_detach (pthread_t th) +{ + struct pthread *pd = (struct pthread *) th; + + /* Make sure the descriptor is valid. */ + if (INVALID_NOT_TERMINATED_TD_P (pd)) + /* Not a valid thread handle. */ + return ESRCH; + + int result = 0; + + /* Mark the thread as detached. */ + if (atomic_compare_and_exchange_bool_acq (&pd->joinid, pd, NULL)) + { + /* There are two possibilities here. First, the thread might + already be detached. In this case we return EINVAL. + Otherwise there might already be a waiter. The standard does + not mention what happens in this case. */ + if (IS_DETACHED (pd)) + result = EINVAL; + } + else + /* Check whether the thread terminated meanwhile. In this case we + will just free the TCB. */ + if ((pd->cancelhandling & EXITING_BITMASK) != 0) + /* Note that the code in __free_tcb makes sure each thread + control block is freed only once. */ + __free_tcb (pd); + + return result; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_equal.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_equal.c new file mode 100644 index 00000000..c454a482 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_equal.c @@ -0,0 +1,29 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "pthreadP.h" + + +int +attribute_protected +__pthread_equal (pthread_t thread1, pthread_t thread2) +{ + return thread1 == thread2; +} +strong_alias (__pthread_equal, pthread_equal) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_exit.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_exit.c new file mode 100644 index 00000000..88d3859b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_exit.c @@ -0,0 +1,32 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include "pthreadP.h" + + +void +attribute_protected +__pthread_exit (void* value) +{ + THREAD_SETMEM (THREAD_SELF, result, value); + + __do_cancel (); +} +strong_alias (__pthread_exit, pthread_exit) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_getattr_np.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_getattr_np.c new file mode 100644 index 00000000..86a43853 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_getattr_np.c @@ -0,0 +1,179 @@ +/* Copyright (C) 2002, 2003, 2004, 2006, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "pthreadP.h" +#include +#include + + +int +pthread_getattr_np ( + pthread_t thread_id, + pthread_attr_t *attr) +{ + struct pthread *thread = (struct pthread *) thread_id; + struct pthread_attr *iattr = (struct pthread_attr *) attr; + int ret = 0; + + lll_lock (thread->lock, LLL_PRIVATE); + + /* The thread library is responsible for keeping the values in the + thread desriptor up-to-date in case the user changes them. */ + memcpy (&iattr->schedparam, &thread->schedparam, + sizeof (struct sched_param)); + iattr->schedpolicy = thread->schedpolicy; + + /* Clear the flags work. */ + iattr->flags = thread->flags; + + /* The thread might be detached by now. */ + if (IS_DETACHED (thread)) + iattr->flags |= ATTR_FLAG_DETACHSTATE; + + /* This is the guardsize after adjusting it. */ + iattr->guardsize = thread->reported_guardsize; + + /* The sizes are subject to alignment. */ + if (__builtin_expect (thread->stackblock != NULL, 1)) + { + iattr->stacksize = thread->stackblock_size; + iattr->stackaddr = (char *) thread->stackblock + iattr->stacksize; + } + else + { + /* No stack information available. This must be for the initial + thread. Get the info in some magical way. */ + assert (abs (thread->pid) == thread->tid); + + /* Stack size limit. */ + struct rlimit rl; + + /* The safest way to get the top of the stack is to read + /proc/self/maps and locate the line into which + __libc_stack_end falls. */ + FILE *fp = fopen ("/proc/self/maps", "rc"); + if (fp == NULL) + ret = errno; + /* We need the limit of the stack in any case. */ + else + { + if (getrlimit (RLIMIT_STACK, &rl) != 0) + ret = errno; + else + { + /* We need no locking. */ + __fsetlocking (fp, FSETLOCKING_BYCALLER); + + /* Until we found an entry (which should always be the case) + mark the result as a failure. */ + ret = ENOENT; + + char *line = NULL; + size_t linelen = 0; + uintptr_t last_to = 0; + + while (! feof_unlocked (fp)) + { + if (getdelim (&line, &linelen, '\n', fp) <= 0) + break; + + uintptr_t from; + uintptr_t to; + if (sscanf (line, "%" SCNxPTR "-%" SCNxPTR, &from, &to) != 2) + continue; + if (from <= (uintptr_t) __libc_stack_end + && (uintptr_t) __libc_stack_end < to) + { + /* Found the entry. Now we have the info we need. */ + iattr->stacksize = rl.rlim_cur; + iattr->stackaddr = (void *) to; + + /* The limit might be too high. */ + if ((size_t) iattr->stacksize + > (size_t) iattr->stackaddr - last_to) + iattr->stacksize = (size_t) iattr->stackaddr - last_to; + + /* We succeed and no need to look further. */ + ret = 0; + break; + } + last_to = to; + } + + free (line); + } + + fclose (fp); + } + } + + iattr->flags |= ATTR_FLAG_STACKADDR; + + if (ret == 0) + { + size_t size = 16; + cpu_set_t *cpuset = NULL; + + do + { + size <<= 1; + + void *newp = realloc (cpuset, size); + if (newp == NULL) + { + ret = ENOMEM; + break; + } + cpuset = (cpu_set_t *) newp; + + ret = __pthread_getaffinity_np (thread_id, size, cpuset); + } + /* Pick some ridiculous upper limit. Is 8 million CPUs enough? */ + while (ret == EINVAL && size < 1024 * 1024); + + if (ret == 0) + { + iattr->cpuset = cpuset; + iattr->cpusetsize = size; + } + else + { + free (cpuset); + if (ret == ENOSYS) + { + /* There is no such functionality. */ + ret = 0; + iattr->cpuset = NULL; + iattr->cpusetsize = 0; + } + } + } + + lll_unlock (thread->lock, LLL_PRIVATE); + + return ret; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_getconcurrency.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_getconcurrency.c new file mode 100644 index 00000000..52c0c7cb --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_getconcurrency.c @@ -0,0 +1,27 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "pthreadP.h" + + +int +pthread_getconcurrency (void) +{ + return __concurrency_level; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_getschedparam.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_getschedparam.c new file mode 100644 index 00000000..53dc4113 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_getschedparam.c @@ -0,0 +1,76 @@ +/* Copyright (C) 2002, 2003, 2004, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include "pthreadP.h" +#include + + +int +attribute_protected +__pthread_getschedparam ( + pthread_t threadid, + int *policy, + struct sched_param *param) +{ + struct pthread *pd = (struct pthread *) threadid; + + /* Make sure the descriptor is valid. */ + if (INVALID_TD_P (pd)) + /* Not a valid thread handle. */ + return ESRCH; + + int result = 0; + + lll_lock (pd->lock, LLL_PRIVATE); + + /* The library is responsible for maintaining the values at all + times. If the user uses a interface other than + pthread_setschedparam to modify the scheduler setting it is not + the library's problem. In case the descriptor's values have + not yet been retrieved do it now. */ + if ((pd->flags & ATTR_FLAG_SCHED_SET) == 0) + { + if (sched_getparam (pd->tid, &pd->schedparam) != 0) + result = 1; + else + pd->flags |= ATTR_FLAG_SCHED_SET; + } + + if ((pd->flags & ATTR_FLAG_POLICY_SET) == 0) + { + pd->schedpolicy = sched_getscheduler (pd->tid); + if (pd->schedpolicy == -1) + result = 1; + else + pd->flags |= ATTR_FLAG_POLICY_SET; + } + + if (result == 0) + { + *policy = pd->schedpolicy; + memcpy (param, &pd->schedparam, sizeof (struct sched_param)); + } + + lll_unlock (pd->lock, LLL_PRIVATE); + + return result; +} +strong_alias (__pthread_getschedparam, pthread_getschedparam) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_getspecific.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_getspecific.c new file mode 100644 index 00000000..639a4fde --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_getspecific.c @@ -0,0 +1,69 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include "pthreadP.h" + + +void * +attribute_protected +__pthread_getspecific (pthread_key_t key) +{ + struct pthread_key_data *data; + + /* Special case access to the first 2nd-level block. This is the + usual case. */ + if (__builtin_expect (key < PTHREAD_KEY_2NDLEVEL_SIZE, 1)) + data = &THREAD_SELF->specific_1stblock[key]; + else + { + /* Verify the key is sane. */ + if (key >= PTHREAD_KEYS_MAX) + /* Not valid. */ + return NULL; + + unsigned int idx1st = key / PTHREAD_KEY_2NDLEVEL_SIZE; + unsigned int idx2nd = key % PTHREAD_KEY_2NDLEVEL_SIZE; + + /* If the sequence number doesn't match or the key cannot be defined + for this thread since the second level array is not allocated + return NULL, too. */ + struct pthread_key_data *level2 = THREAD_GETMEM_NC (THREAD_SELF, + specific, idx1st); + if (level2 == NULL) + /* Not allocated, therefore no data. */ + return NULL; + + /* There is data. */ + data = &level2[idx2nd]; + } + + void *result = data->data; + if (result != NULL) + { + uintptr_t seq = data->seq; + + if (__builtin_expect (seq != __pthread_keys[key].seq, 0)) + result = data->data = NULL; + } + + return result; +} +strong_alias (__pthread_getspecific, pthread_getspecific) +strong_alias (__pthread_getspecific, __pthread_getspecific_internal) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_join.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_join.c new file mode 100644 index 00000000..ce6cf6fb --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_join.c @@ -0,0 +1,114 @@ +/* Copyright (C) 2002, 2003, 2005, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +#include +#include "pthreadP.h" + + +static void +cleanup (void *arg) +{ + /* If we already changed the waiter ID, reset it. The call cannot + fail for any reason but the thread not having done that yet so + there is no reason for a loop. */ + (void) atomic_compare_and_exchange_bool_acq ((struct pthread **) arg, NULL, + THREAD_SELF); +} + + +int +pthread_join ( + pthread_t threadid, + void **thread_return) +{ + struct pthread *pd = (struct pthread *) threadid; + + /* Make sure the descriptor is valid. */ + if (INVALID_NOT_TERMINATED_TD_P (pd)) + /* Not a valid thread handle. */ + return ESRCH; + + /* Is the thread joinable?. */ + if (IS_DETACHED (pd)) + /* We cannot wait for the thread. */ + return EINVAL; + + struct pthread *self = THREAD_SELF; + int result = 0; + + /* During the wait we change to asynchronous cancellation. If we + are canceled the thread we are waiting for must be marked as + un-wait-ed for again. */ + pthread_cleanup_push (cleanup, &pd->joinid); + + /* Switch to asynchronous cancellation. */ + int oldtype = CANCEL_ASYNC (); + + if ((pd == self + || (self->joinid == pd + && (pd->cancelhandling + & (CANCELING_BITMASK | CANCELED_BITMASK | EXITING_BITMASK + | TERMINATED_BITMASK)) == 0)) + && !CANCEL_ENABLED_AND_CANCELED (self->cancelhandling)) + /* This is a deadlock situation. The threads are waiting for each + other to finish. Note that this is a "may" error. To be 100% + sure we catch this error we would have to lock the data + structures but it is not necessary. In the unlikely case that + two threads are really caught in this situation they will + deadlock. It is the programmer's problem to figure this + out. */ + result = EDEADLK; + /* Wait for the thread to finish. If it is already locked something + is wrong. There can only be one waiter. */ + else if (__builtin_expect (atomic_compare_and_exchange_bool_acq (&pd->joinid, + self, + NULL), 0)) + /* There is already somebody waiting for the thread. */ + result = EINVAL; + else + /* Wait for the child. */ + lll_wait_tid (pd->tid); + + + /* Restore cancellation mode. */ + CANCEL_RESET (oldtype); + + /* Remove the handler. */ + pthread_cleanup_pop (0); + + + if (__builtin_expect (result == 0, 1)) + { + /* We mark the thread as terminated and as joined. */ + pd->tid = -1; + + /* Store the return value if the caller is interested. */ + if (thread_return != NULL) + *thread_return = pd->result; + + + /* Free the TCB. */ + __free_tcb (pd); + } + + return result; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_key_create.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_key_create.c new file mode 100644 index 00000000..be32517e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_key_create.c @@ -0,0 +1,56 @@ +/* Copyright (C) 2002, 2003, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include "pthreadP.h" +#include + + +int +attribute_protected +__pthread_key_create ( + pthread_key_t *key, + void (*destr) (void *)) +{ + /* Find a slot in __pthread_kyes which is unused. */ + size_t cnt; + for (cnt = 0; cnt < PTHREAD_KEYS_MAX; ++cnt) + { + uintptr_t seq = __pthread_keys[cnt].seq; + + if (KEY_UNUSED (seq) && KEY_USABLE (seq) + /* We found an unused slot. Try to allocate it. */ + && ! atomic_compare_and_exchange_bool_acq (&__pthread_keys[cnt].seq, + seq + 1, seq)) + { + /* Remember the destructor. */ + __pthread_keys[cnt].destr = destr; + + /* Return the key to the caller. */ + *key = cnt; + + /* The call succeeded. */ + return 0; + } + } + + return EAGAIN; +} +strong_alias (__pthread_key_create, pthread_key_create) +strong_alias (__pthread_key_create, __pthread_key_create_internal) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_key_delete.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_key_delete.c new file mode 100644 index 00000000..cb408f09 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_key_delete.c @@ -0,0 +1,42 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include "pthreadP.h" +#include + + +int +pthread_key_delete (pthread_key_t key) +{ + int result = EINVAL; + + if (__builtin_expect (key < PTHREAD_KEYS_MAX, 1)) + { + unsigned int seq = __pthread_keys[key].seq; + + if (__builtin_expect (! KEY_UNUSED (seq), 1) + && ! atomic_compare_and_exchange_bool_acq (&__pthread_keys[key].seq, + seq + 1, seq)) + /* We deleted a valid key. */ + result = 0; + } + + return result; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_kill_other_threads.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_kill_other_threads.c new file mode 100644 index 00000000..09401aab --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_kill_other_threads.c @@ -0,0 +1,32 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifdef SHARED +/* This function does not serve a useful purpose in the thread library + implementation anymore. It used to be necessary when then kernel + could not shut down "processes" but this is not the case anymore. + + We could theoretically provide an equivalent implementation but + this is not necessary since the kernel already does a much better + job than we ever could. */ +void +__pthread_kill_other_threads_np (void) +{ +} +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_mutex_consistent.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_mutex_consistent.c new file mode 100644 index 00000000..1e8f0747 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_mutex_consistent.c @@ -0,0 +1,37 @@ +/* Copyright (C) 2005, 2006, 2010 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2005. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + + +int +pthread_mutex_consistent ( + pthread_mutex_t *mutex) +{ + /* Test whether this is a robust mutex with a dead owner. */ + if ((mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP) == 0 + || mutex->__data.__owner != PTHREAD_MUTEX_INCONSISTENT) + return EINVAL; + + mutex->__data.__owner = THREAD_GETMEM (THREAD_SELF, tid); + + return 0; +} +weak_alias (pthread_mutex_consistent, pthread_mutex_consistent_np) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_mutex_destroy.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_mutex_destroy.c new file mode 100644 index 00000000..756e8bbe --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_mutex_destroy.c @@ -0,0 +1,39 @@ +/* Copyright (C) 2002, 2003, 2005, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include "pthreadP.h" + + +int +attribute_protected +__pthread_mutex_destroy ( + pthread_mutex_t *mutex) +{ + if ((mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP) == 0 + && mutex->__data.__nusers != 0) + return EBUSY; + + /* Set to an invalid value. */ + mutex->__data.__kind = -1; + + return 0; +} +strong_alias (__pthread_mutex_destroy, pthread_mutex_destroy) +INTDEF(__pthread_mutex_destroy) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_mutex_getprioceiling.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_mutex_getprioceiling.c new file mode 100644 index 00000000..1ce5eaeb --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_mutex_getprioceiling.c @@ -0,0 +1,38 @@ +/* Get current priority ceiling of pthread_mutex_t. + Copyright (C) 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2006. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + + +int +pthread_mutex_getprioceiling (mutex, prioceiling) + const pthread_mutex_t *mutex; + int *prioceiling; +{ + if (__builtin_expect ((mutex->__data.__kind + & PTHREAD_MUTEX_PRIO_PROTECT_NP) == 0, 0)) + return EINVAL; + + *prioceiling = (mutex->__data.__lock & PTHREAD_MUTEX_PRIO_CEILING_MASK) + >> PTHREAD_MUTEX_PRIO_CEILING_SHIFT; + + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_mutex_init.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_mutex_init.c new file mode 100644 index 00000000..e942c1b7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_mutex_init.c @@ -0,0 +1,142 @@ +/* Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include "pthreadP.h" + +static const struct pthread_mutexattr default_attr = + { + /* Default is a normal mutex, not shared between processes. */ + .mutexkind = PTHREAD_MUTEX_NORMAL + }; + + +#ifndef __ASSUME_FUTEX_LOCK_PI +static int tpi_supported; +#endif + + +int +attribute_protected +__pthread_mutex_init ( + pthread_mutex_t *mutex, + const pthread_mutexattr_t *mutexattr) +{ + const struct pthread_mutexattr *imutexattr; + + assert (sizeof (pthread_mutex_t) <= __SIZEOF_PTHREAD_MUTEX_T); + + imutexattr = (const struct pthread_mutexattr *) mutexattr ?: &default_attr; + + /* Sanity checks. */ + switch (__builtin_expect (imutexattr->mutexkind + & PTHREAD_MUTEXATTR_PROTOCOL_MASK, + PTHREAD_PRIO_NONE + << PTHREAD_MUTEXATTR_PROTOCOL_SHIFT)) + { + case PTHREAD_PRIO_NONE << PTHREAD_MUTEXATTR_PROTOCOL_SHIFT: + break; + + case PTHREAD_PRIO_INHERIT << PTHREAD_MUTEXATTR_PROTOCOL_SHIFT: +#ifndef __ASSUME_FUTEX_LOCK_PI + if (__builtin_expect (tpi_supported == 0, 0)) + { + int lock = 0; + INTERNAL_SYSCALL_DECL (err); + int ret = INTERNAL_SYSCALL (futex, err, 4, &lock, FUTEX_UNLOCK_PI, + 0, 0); + assert (INTERNAL_SYSCALL_ERROR_P (ret, err)); + tpi_supported = INTERNAL_SYSCALL_ERRNO (ret, err) == ENOSYS ? -1 : 1; + } + if (__builtin_expect (tpi_supported < 0, 0)) + return ENOTSUP; +#endif + break; + + default: + /* XXX: For now we don't support robust priority protected mutexes. */ + if (imutexattr->mutexkind & PTHREAD_MUTEXATTR_FLAG_ROBUST) + return ENOTSUP; + break; + } + + /* Clear the whole variable. */ + memset (mutex, '\0', __SIZEOF_PTHREAD_MUTEX_T); + + /* Copy the values from the attribute. */ + mutex->__data.__kind = imutexattr->mutexkind & ~PTHREAD_MUTEXATTR_FLAG_BITS; + + if ((imutexattr->mutexkind & PTHREAD_MUTEXATTR_FLAG_ROBUST) != 0) + { +#ifndef __ASSUME_SET_ROBUST_LIST + if ((imutexattr->mutexkind & PTHREAD_MUTEXATTR_FLAG_PSHARED) != 0 + && __set_robust_list_avail < 0) + return ENOTSUP; +#endif + + mutex->__data.__kind |= PTHREAD_MUTEX_ROBUST_NORMAL_NP; + } + + switch (imutexattr->mutexkind & PTHREAD_MUTEXATTR_PROTOCOL_MASK) + { + case PTHREAD_PRIO_INHERIT << PTHREAD_MUTEXATTR_PROTOCOL_SHIFT: + mutex->__data.__kind |= PTHREAD_MUTEX_PRIO_INHERIT_NP; + break; + + case PTHREAD_PRIO_PROTECT << PTHREAD_MUTEXATTR_PROTOCOL_SHIFT: + mutex->__data.__kind |= PTHREAD_MUTEX_PRIO_PROTECT_NP; + + int ceiling = (imutexattr->mutexkind + & PTHREAD_MUTEXATTR_PRIO_CEILING_MASK) + >> PTHREAD_MUTEXATTR_PRIO_CEILING_SHIFT; + if (! ceiling) + { + if (__sched_fifo_min_prio == -1) + __init_sched_fifo_prio (); + if (ceiling < __sched_fifo_min_prio) + ceiling = __sched_fifo_min_prio; + } + mutex->__data.__lock = ceiling << PTHREAD_MUTEX_PRIO_CEILING_SHIFT; + break; + + default: + break; + } + + /* The kernel when waking robust mutexes on exit never uses + FUTEX_PRIVATE_FLAG FUTEX_WAKE. */ + if ((imutexattr->mutexkind & (PTHREAD_MUTEXATTR_FLAG_PSHARED + | PTHREAD_MUTEXATTR_FLAG_ROBUST)) != 0) + mutex->__data.__kind |= PTHREAD_MUTEX_PSHARED_BIT; + + /* Default values: mutex not used yet. */ + // mutex->__count = 0; already done by memset + // mutex->__owner = 0; already done by memset + // mutex->__nusers = 0; already done by memset + // mutex->__spins = 0; already done by memset + // mutex->__next = NULL; already done by memset + + return 0; +} +strong_alias (__pthread_mutex_init, pthread_mutex_init) +INTDEF(__pthread_mutex_init) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_mutex_lock.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_mutex_lock.c new file mode 100644 index 00000000..77147dbe --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_mutex_lock.c @@ -0,0 +1,500 @@ +/* Copyright (C) 2002-2007, 2008, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include "pthreadP.h" +#include + + +#ifndef LLL_MUTEX_LOCK +# define LLL_MUTEX_LOCK(mutex) \ + lll_lock ((mutex)->__data.__lock, PTHREAD_MUTEX_PSHARED (mutex)) +# define LLL_MUTEX_TRYLOCK(mutex) \ + lll_trylock ((mutex)->__data.__lock) +# define LLL_ROBUST_MUTEX_LOCK(mutex, id) \ + lll_robust_lock ((mutex)->__data.__lock, id, \ + PTHREAD_ROBUST_MUTEX_PSHARED (mutex)) +#endif + + +static int __pthread_mutex_lock_full (pthread_mutex_t *mutex) + __attribute_noinline__; + + +int +#ifdef NO_INCR +attribute_hidden internal_function +#else +attribute_protected +#endif +__pthread_mutex_lock ( + pthread_mutex_t *mutex) +{ + assert (sizeof (mutex->__size) >= sizeof (mutex->__data)); + + unsigned int type = PTHREAD_MUTEX_TYPE (mutex); + if (__builtin_expect (type & ~PTHREAD_MUTEX_KIND_MASK_NP, 0)) + return __pthread_mutex_lock_full (mutex); + + pid_t id = THREAD_GETMEM (THREAD_SELF, tid); + + if (__builtin_expect (type, PTHREAD_MUTEX_TIMED_NP) + == PTHREAD_MUTEX_TIMED_NP) + { + simple: + /* Normal mutex. */ + LLL_MUTEX_LOCK (mutex); + assert (mutex->__data.__owner == 0); + } + else if (__builtin_expect (type == PTHREAD_MUTEX_RECURSIVE_NP, 1)) + { + /* Recursive mutex. */ + + /* Check whether we already hold the mutex. */ + if (mutex->__data.__owner == id) + { + /* Just bump the counter. */ + if (__builtin_expect (mutex->__data.__count + 1 == 0, 0)) + /* Overflow of the counter. */ + return EAGAIN; + + ++mutex->__data.__count; + + return 0; + } + + /* We have to get the mutex. */ + LLL_MUTEX_LOCK (mutex); + + assert (mutex->__data.__owner == 0); + mutex->__data.__count = 1; + } + else if (__builtin_expect (type == PTHREAD_MUTEX_ADAPTIVE_NP, 1)) + { + if (! __is_smp) + goto simple; + + if (LLL_MUTEX_TRYLOCK (mutex) != 0) + { + int cnt = 0; + int max_cnt = MIN (MAX_ADAPTIVE_COUNT, + mutex->__data.__spins * 2 + 10); + do + { + if (cnt++ >= max_cnt) + { + LLL_MUTEX_LOCK (mutex); + break; + } + +#ifdef BUSY_WAIT_NOP + BUSY_WAIT_NOP; +#endif + } + while (LLL_MUTEX_TRYLOCK (mutex) != 0); + + mutex->__data.__spins += (cnt - mutex->__data.__spins) / 8; + } + assert (mutex->__data.__owner == 0); + } + else + { + assert (type == PTHREAD_MUTEX_ERRORCHECK_NP); + /* Check whether we already hold the mutex. */ + if (__builtin_expect (mutex->__data.__owner == id, 0)) + return EDEADLK; + goto simple; + } + + /* Record the ownership. */ + mutex->__data.__owner = id; +#ifndef NO_INCR + ++mutex->__data.__nusers; +#endif + + return 0; +} + +static int +__pthread_mutex_lock_full (pthread_mutex_t *mutex) +{ + int oldval; + pid_t id = THREAD_GETMEM (THREAD_SELF, tid); + + switch (PTHREAD_MUTEX_TYPE (mutex)) + { + case PTHREAD_MUTEX_ROBUST_RECURSIVE_NP: + case PTHREAD_MUTEX_ROBUST_ERRORCHECK_NP: + case PTHREAD_MUTEX_ROBUST_NORMAL_NP: + case PTHREAD_MUTEX_ROBUST_ADAPTIVE_NP: + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, + &mutex->__data.__list.__next); + + oldval = mutex->__data.__lock; + do + { + again: + if ((oldval & FUTEX_OWNER_DIED) != 0) + { + /* The previous owner died. Try locking the mutex. */ + int newval = id; +#ifdef NO_INCR + newval |= FUTEX_WAITERS; +#else + newval |= (oldval & FUTEX_WAITERS); +#endif + + newval + = atomic_compare_and_exchange_val_acq (&mutex->__data.__lock, + newval, oldval); + + if (newval != oldval) + { + oldval = newval; + goto again; + } + + /* We got the mutex. */ + mutex->__data.__count = 1; + /* But it is inconsistent unless marked otherwise. */ + mutex->__data.__owner = PTHREAD_MUTEX_INCONSISTENT; + + ENQUEUE_MUTEX (mutex); + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); + + /* Note that we deliberately exit here. If we fall + through to the end of the function __nusers would be + incremented which is not correct because the old + owner has to be discounted. If we are not supposed + to increment __nusers we actually have to decrement + it here. */ +#ifdef NO_INCR + --mutex->__data.__nusers; +#endif + + return EOWNERDEAD; + } + + /* Check whether we already hold the mutex. */ + if (__builtin_expect ((oldval & FUTEX_TID_MASK) == id, 0)) + { + int kind = PTHREAD_MUTEX_TYPE (mutex); + if (kind == PTHREAD_MUTEX_ROBUST_ERRORCHECK_NP) + { + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, + NULL); + return EDEADLK; + } + + if (kind == PTHREAD_MUTEX_ROBUST_RECURSIVE_NP) + { + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, + NULL); + + /* Just bump the counter. */ + if (__builtin_expect (mutex->__data.__count + 1 == 0, 0)) + /* Overflow of the counter. */ + return EAGAIN; + + ++mutex->__data.__count; + + return 0; + } + } + + oldval = LLL_ROBUST_MUTEX_LOCK (mutex, id); + + if (__builtin_expect (mutex->__data.__owner + == PTHREAD_MUTEX_NOTRECOVERABLE, 0)) + { + /* This mutex is now not recoverable. */ + mutex->__data.__count = 0; + lll_unlock (mutex->__data.__lock, + PTHREAD_ROBUST_MUTEX_PSHARED (mutex)); + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); + return ENOTRECOVERABLE; + } + } + while ((oldval & FUTEX_OWNER_DIED) != 0); + + mutex->__data.__count = 1; + ENQUEUE_MUTEX (mutex); + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); + break; + + case PTHREAD_MUTEX_PI_RECURSIVE_NP: + case PTHREAD_MUTEX_PI_ERRORCHECK_NP: + case PTHREAD_MUTEX_PI_NORMAL_NP: + case PTHREAD_MUTEX_PI_ADAPTIVE_NP: + case PTHREAD_MUTEX_PI_ROBUST_RECURSIVE_NP: + case PTHREAD_MUTEX_PI_ROBUST_ERRORCHECK_NP: + case PTHREAD_MUTEX_PI_ROBUST_NORMAL_NP: + case PTHREAD_MUTEX_PI_ROBUST_ADAPTIVE_NP: + { + int kind = mutex->__data.__kind & PTHREAD_MUTEX_KIND_MASK_NP; + int robust = mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP; + + if (robust) + /* Note: robust PI futexes are signaled by setting bit 0. */ + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, + (void *) (((uintptr_t) &mutex->__data.__list.__next) + | 1)); + + oldval = mutex->__data.__lock; + + /* Check whether we already hold the mutex. */ + if (__builtin_expect ((oldval & FUTEX_TID_MASK) == id, 0)) + { + if (kind == PTHREAD_MUTEX_ERRORCHECK_NP) + { + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); + return EDEADLK; + } + + if (kind == PTHREAD_MUTEX_RECURSIVE_NP) + { + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); + + /* Just bump the counter. */ + if (__builtin_expect (mutex->__data.__count + 1 == 0, 0)) + /* Overflow of the counter. */ + return EAGAIN; + + ++mutex->__data.__count; + + return 0; + } + } + + int newval = id; +#ifdef NO_INCR + newval |= FUTEX_WAITERS; +#endif + oldval = atomic_compare_and_exchange_val_acq (&mutex->__data.__lock, + newval, 0); + + if (oldval != 0) + { + /* The mutex is locked. The kernel will now take care of + everything. */ + int private = (robust + ? PTHREAD_ROBUST_MUTEX_PSHARED (mutex) + : PTHREAD_MUTEX_PSHARED (mutex)); + INTERNAL_SYSCALL_DECL (__err); + int e = INTERNAL_SYSCALL (futex, __err, 4, &mutex->__data.__lock, + __lll_private_flag (FUTEX_LOCK_PI, + private), 1, 0); + + if (INTERNAL_SYSCALL_ERROR_P (e, __err) + && (INTERNAL_SYSCALL_ERRNO (e, __err) == ESRCH + || INTERNAL_SYSCALL_ERRNO (e, __err) == EDEADLK)) + { + assert (INTERNAL_SYSCALL_ERRNO (e, __err) != EDEADLK + || (kind != PTHREAD_MUTEX_ERRORCHECK_NP + && kind != PTHREAD_MUTEX_RECURSIVE_NP)); + /* ESRCH can happen only for non-robust PI mutexes where + the owner of the lock died. */ + assert (INTERNAL_SYSCALL_ERRNO (e, __err) != ESRCH || !robust); + + /* Delay the thread indefinitely. */ + while (1) + pause_not_cancel (); + } + + oldval = mutex->__data.__lock; + + assert (robust || (oldval & FUTEX_OWNER_DIED) == 0); + } + + if (__builtin_expect (oldval & FUTEX_OWNER_DIED, 0)) + { + atomic_and (&mutex->__data.__lock, ~FUTEX_OWNER_DIED); + + /* We got the mutex. */ + mutex->__data.__count = 1; + /* But it is inconsistent unless marked otherwise. */ + mutex->__data.__owner = PTHREAD_MUTEX_INCONSISTENT; + + ENQUEUE_MUTEX_PI (mutex); + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); + + /* Note that we deliberately exit here. If we fall + through to the end of the function __nusers would be + incremented which is not correct because the old owner + has to be discounted. If we are not supposed to + increment __nusers we actually have to decrement it here. */ +#ifdef NO_INCR + --mutex->__data.__nusers; +#endif + + return EOWNERDEAD; + } + + if (robust + && __builtin_expect (mutex->__data.__owner + == PTHREAD_MUTEX_NOTRECOVERABLE, 0)) + { + /* This mutex is now not recoverable. */ + mutex->__data.__count = 0; + + INTERNAL_SYSCALL_DECL (__err); + INTERNAL_SYSCALL (futex, __err, 4, &mutex->__data.__lock, + __lll_private_flag (FUTEX_UNLOCK_PI, + PTHREAD_ROBUST_MUTEX_PSHARED (mutex)), + 0, 0); + + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); + return ENOTRECOVERABLE; + } + + mutex->__data.__count = 1; + if (robust) + { + ENQUEUE_MUTEX_PI (mutex); + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); + } + } + break; + + case PTHREAD_MUTEX_PP_RECURSIVE_NP: + case PTHREAD_MUTEX_PP_ERRORCHECK_NP: + case PTHREAD_MUTEX_PP_NORMAL_NP: + case PTHREAD_MUTEX_PP_ADAPTIVE_NP: + { + int kind = mutex->__data.__kind & PTHREAD_MUTEX_KIND_MASK_NP; + + oldval = mutex->__data.__lock; + + /* Check whether we already hold the mutex. */ + if (mutex->__data.__owner == id) + { + if (kind == PTHREAD_MUTEX_ERRORCHECK_NP) + return EDEADLK; + + if (kind == PTHREAD_MUTEX_RECURSIVE_NP) + { + /* Just bump the counter. */ + if (__builtin_expect (mutex->__data.__count + 1 == 0, 0)) + /* Overflow of the counter. */ + return EAGAIN; + + ++mutex->__data.__count; + + return 0; + } + } + + int oldprio = -1, ceilval; + do + { + int ceiling = (oldval & PTHREAD_MUTEX_PRIO_CEILING_MASK) + >> PTHREAD_MUTEX_PRIO_CEILING_SHIFT; + + if (__pthread_current_priority () > ceiling) + { + if (oldprio != -1) + __pthread_tpp_change_priority (oldprio, -1); + return EINVAL; + } + + int retval = __pthread_tpp_change_priority (oldprio, ceiling); + if (retval) + return retval; + + ceilval = ceiling << PTHREAD_MUTEX_PRIO_CEILING_SHIFT; + oldprio = ceiling; + + oldval + = atomic_compare_and_exchange_val_acq (&mutex->__data.__lock, +#ifdef NO_INCR + ceilval | 2, +#else + ceilval | 1, +#endif + ceilval); + + if (oldval == ceilval) + break; + + do + { + oldval + = atomic_compare_and_exchange_val_acq (&mutex->__data.__lock, + ceilval | 2, + ceilval | 1); + + if ((oldval & PTHREAD_MUTEX_PRIO_CEILING_MASK) != ceilval) + break; + + if (oldval != ceilval) + lll_futex_wait (&mutex->__data.__lock, ceilval | 2, + PTHREAD_MUTEX_PSHARED (mutex)); + } + while (atomic_compare_and_exchange_val_acq (&mutex->__data.__lock, + ceilval | 2, ceilval) + != ceilval); + } + while ((oldval & PTHREAD_MUTEX_PRIO_CEILING_MASK) != ceilval); + + assert (mutex->__data.__owner == 0); + mutex->__data.__count = 1; + } + break; + + default: + /* Correct code cannot set any other type. */ + return EINVAL; + } + + /* Record the ownership. */ + mutex->__data.__owner = id; +#ifndef NO_INCR + ++mutex->__data.__nusers; +#endif + + return 0; +} +#ifndef __pthread_mutex_lock +strong_alias (__pthread_mutex_lock, pthread_mutex_lock) +strong_alias (__pthread_mutex_lock, __pthread_mutex_lock_internal) +#endif + + +#ifdef NO_INCR +void +attribute_hidden internal_function +__pthread_mutex_cond_lock_adjust ( + pthread_mutex_t *mutex) +{ + assert ((mutex->__data.__kind & PTHREAD_MUTEX_PRIO_INHERIT_NP) != 0); + assert ((mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP) == 0); + assert ((mutex->__data.__kind & PTHREAD_MUTEX_PSHARED_BIT) == 0); + + /* Record the ownership. */ + pid_t id = THREAD_GETMEM (THREAD_SELF, tid); + mutex->__data.__owner = id; + + if (mutex->__data.__kind == PTHREAD_MUTEX_PI_RECURSIVE_NP) + ++mutex->__data.__count; +} +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_mutex_setprioceiling.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_mutex_setprioceiling.c new file mode 100644 index 00000000..836c9a3e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_mutex_setprioceiling.c @@ -0,0 +1,119 @@ +/* Set current priority ceiling of pthread_mutex_t. + Copyright (C) 2006, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2006. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + + +int +pthread_mutex_setprioceiling (mutex, prioceiling, old_ceiling) + pthread_mutex_t *mutex; + int prioceiling; + int *old_ceiling; +{ + /* The low bits of __kind aren't ever changed after pthread_mutex_init, + so we don't need a lock yet. */ + if ((mutex->__data.__kind & PTHREAD_MUTEX_PRIO_PROTECT_NP) == 0) + return EINVAL; + + if (__sched_fifo_min_prio == -1) + __init_sched_fifo_prio (); + + if (__builtin_expect (prioceiling < __sched_fifo_min_prio, 0) + || __builtin_expect (prioceiling > __sched_fifo_max_prio, 0) + || __builtin_expect ((prioceiling + & (PTHREAD_MUTEXATTR_PRIO_CEILING_MASK + >> PTHREAD_MUTEXATTR_PRIO_CEILING_SHIFT)) + != prioceiling, 0)) + return EINVAL; + + /* Check whether we already hold the mutex. */ + bool locked = false; + int kind = PTHREAD_MUTEX_TYPE (mutex); + if (mutex->__data.__owner == THREAD_GETMEM (THREAD_SELF, tid)) + { + if (kind == PTHREAD_MUTEX_PP_ERRORCHECK_NP) + return EDEADLK; + + if (kind == PTHREAD_MUTEX_PP_RECURSIVE_NP) + locked = true; + } + + int oldval = mutex->__data.__lock; + if (! locked) + do + { + /* Need to lock the mutex, but without obeying the priority + protect protocol. */ + int ceilval = (oldval & PTHREAD_MUTEX_PRIO_CEILING_MASK); + + oldval = atomic_compare_and_exchange_val_acq (&mutex->__data.__lock, + ceilval | 1, ceilval); + if (oldval == ceilval) + break; + + do + { + oldval + = atomic_compare_and_exchange_val_acq (&mutex->__data.__lock, + ceilval | 2, + ceilval | 1); + + if ((oldval & PTHREAD_MUTEX_PRIO_CEILING_MASK) != ceilval) + break; + + if (oldval != ceilval) + lll_futex_wait (&mutex->__data.__lock, ceilval | 2, + PTHREAD_MUTEX_PSHARED (mutex)); + } + while (atomic_compare_and_exchange_val_acq (&mutex->__data.__lock, + ceilval | 2, ceilval) + != ceilval); + + if ((oldval & PTHREAD_MUTEX_PRIO_CEILING_MASK) != ceilval) + continue; + } + while (0); + + int oldprio = (oldval & PTHREAD_MUTEX_PRIO_CEILING_MASK) + >> PTHREAD_MUTEX_PRIO_CEILING_SHIFT; + if (locked) + { + int ret = __pthread_tpp_change_priority (oldprio, prioceiling); + if (ret) + return ret; + } + + if (old_ceiling != NULL) + *old_ceiling = oldprio; + + int newlock = 0; + if (locked) + newlock = (mutex->__data.__lock & ~PTHREAD_MUTEX_PRIO_CEILING_MASK); + mutex->__data.__lock = newlock + | (prioceiling << PTHREAD_MUTEX_PRIO_CEILING_SHIFT); + atomic_full_barrier (); + + lll_futex_wake (&mutex->__data.__lock, INT_MAX, + PTHREAD_MUTEX_PSHARED (mutex)); + + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_mutex_timedlock.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_mutex_timedlock.c new file mode 100644 index 00000000..d6ab60ec --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_mutex_timedlock.c @@ -0,0 +1,488 @@ +/* Copyright (C) 2002-2007, 2008 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include "pthreadP.h" +#include +#include + +/* We need to build this function with optimization to avoid + * lll_timedlock erroring out with + * error: can't find a register in class ‘GENERAL_REGS’ while reloading ‘asm’ + */ +int +attribute_optimize("Os") +pthread_mutex_timedlock ( + pthread_mutex_t *mutex, + const struct timespec *abstime) +{ + int oldval; + pid_t id = THREAD_GETMEM (THREAD_SELF, tid); + int result = 0; + + /* We must not check ABSTIME here. If the thread does not block + abstime must not be checked for a valid value. */ + + switch (__builtin_expect (PTHREAD_MUTEX_TYPE (mutex), + PTHREAD_MUTEX_TIMED_NP)) + { + /* Recursive mutex. */ + case PTHREAD_MUTEX_RECURSIVE_NP: + /* Check whether we already hold the mutex. */ + if (mutex->__data.__owner == id) + { + /* Just bump the counter. */ + if (__builtin_expect (mutex->__data.__count + 1 == 0, 0)) + /* Overflow of the counter. */ + return EAGAIN; + + ++mutex->__data.__count; + + goto out; + } + + /* We have to get the mutex. */ + result = lll_timedlock (mutex->__data.__lock, abstime, + PTHREAD_MUTEX_PSHARED (mutex)); + + if (result != 0) + goto out; + + /* Only locked once so far. */ + mutex->__data.__count = 1; + break; + + /* Error checking mutex. */ + case PTHREAD_MUTEX_ERRORCHECK_NP: + /* Check whether we already hold the mutex. */ + if (__builtin_expect (mutex->__data.__owner == id, 0)) + return EDEADLK; + + /* FALLTHROUGH */ + + case PTHREAD_MUTEX_TIMED_NP: + simple: + /* Normal mutex. */ + result = lll_timedlock (mutex->__data.__lock, abstime, + PTHREAD_MUTEX_PSHARED (mutex)); + break; + + case PTHREAD_MUTEX_ADAPTIVE_NP: + if (! __is_smp) + goto simple; + + if (lll_trylock (mutex->__data.__lock) != 0) + { + int cnt = 0; + int max_cnt = MIN (MAX_ADAPTIVE_COUNT, + mutex->__data.__spins * 2 + 10); + do + { + if (cnt++ >= max_cnt) + { + result = lll_timedlock (mutex->__data.__lock, abstime, + PTHREAD_MUTEX_PSHARED (mutex)); + break; + } + +#ifdef BUSY_WAIT_NOP + BUSY_WAIT_NOP; +#endif + } + while (lll_trylock (mutex->__data.__lock) != 0); + + mutex->__data.__spins += (cnt - mutex->__data.__spins) / 8; + } + break; + + case PTHREAD_MUTEX_ROBUST_RECURSIVE_NP: + case PTHREAD_MUTEX_ROBUST_ERRORCHECK_NP: + case PTHREAD_MUTEX_ROBUST_NORMAL_NP: + case PTHREAD_MUTEX_ROBUST_ADAPTIVE_NP: + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, + &mutex->__data.__list.__next); + + oldval = mutex->__data.__lock; + do + { + again: + if ((oldval & FUTEX_OWNER_DIED) != 0) + { + /* The previous owner died. Try locking the mutex. */ + int newval = id | (oldval & FUTEX_WAITERS); + + newval + = atomic_compare_and_exchange_val_acq (&mutex->__data.__lock, + newval, oldval); + if (newval != oldval) + { + oldval = newval; + goto again; + } + + /* We got the mutex. */ + mutex->__data.__count = 1; + /* But it is inconsistent unless marked otherwise. */ + mutex->__data.__owner = PTHREAD_MUTEX_INCONSISTENT; + + ENQUEUE_MUTEX (mutex); + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); + + /* Note that we deliberately exit here. If we fall + through to the end of the function __nusers would be + incremented which is not correct because the old + owner has to be discounted. */ + return EOWNERDEAD; + } + + /* Check whether we already hold the mutex. */ + if (__builtin_expect ((oldval & FUTEX_TID_MASK) == id, 0)) + { + int kind = PTHREAD_MUTEX_TYPE (mutex); + if (kind == PTHREAD_MUTEX_ROBUST_ERRORCHECK_NP) + { + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, + NULL); + return EDEADLK; + } + + if (kind == PTHREAD_MUTEX_ROBUST_RECURSIVE_NP) + { + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, + NULL); + + /* Just bump the counter. */ + if (__builtin_expect (mutex->__data.__count + 1 == 0, 0)) + /* Overflow of the counter. */ + return EAGAIN; + + ++mutex->__data.__count; + + return 0; + } + } + + result = lll_robust_timedlock (mutex->__data.__lock, abstime, id, + PTHREAD_ROBUST_MUTEX_PSHARED (mutex)); + + if (__builtin_expect (mutex->__data.__owner + == PTHREAD_MUTEX_NOTRECOVERABLE, 0)) + { + /* This mutex is now not recoverable. */ + mutex->__data.__count = 0; + lll_unlock (mutex->__data.__lock, + PTHREAD_ROBUST_MUTEX_PSHARED (mutex)); + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); + return ENOTRECOVERABLE; + } + + if (result == ETIMEDOUT || result == EINVAL) + goto out; + + oldval = result; + } + while ((oldval & FUTEX_OWNER_DIED) != 0); + + mutex->__data.__count = 1; + ENQUEUE_MUTEX (mutex); + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); + break; + + case PTHREAD_MUTEX_PI_RECURSIVE_NP: + case PTHREAD_MUTEX_PI_ERRORCHECK_NP: + case PTHREAD_MUTEX_PI_NORMAL_NP: + case PTHREAD_MUTEX_PI_ADAPTIVE_NP: + case PTHREAD_MUTEX_PI_ROBUST_RECURSIVE_NP: + case PTHREAD_MUTEX_PI_ROBUST_ERRORCHECK_NP: + case PTHREAD_MUTEX_PI_ROBUST_NORMAL_NP: + case PTHREAD_MUTEX_PI_ROBUST_ADAPTIVE_NP: + { + int kind = mutex->__data.__kind & PTHREAD_MUTEX_KIND_MASK_NP; + int robust = mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP; + + if (robust) + /* Note: robust PI futexes are signaled by setting bit 0. */ + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, + (void *) (((uintptr_t) &mutex->__data.__list.__next) + | 1)); + + oldval = mutex->__data.__lock; + + /* Check whether we already hold the mutex. */ + if (__builtin_expect ((oldval & FUTEX_TID_MASK) == id, 0)) + { + if (kind == PTHREAD_MUTEX_ERRORCHECK_NP) + { + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); + return EDEADLK; + } + + if (kind == PTHREAD_MUTEX_RECURSIVE_NP) + { + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); + + /* Just bump the counter. */ + if (__builtin_expect (mutex->__data.__count + 1 == 0, 0)) + /* Overflow of the counter. */ + return EAGAIN; + + ++mutex->__data.__count; + + return 0; + } + } + + oldval = atomic_compare_and_exchange_val_acq (&mutex->__data.__lock, + id, 0); + + if (oldval != 0) + { + /* The mutex is locked. The kernel will now take care of + everything. The timeout value must be a relative value. + Convert it. */ + int private = (robust + ? PTHREAD_ROBUST_MUTEX_PSHARED (mutex) + : PTHREAD_MUTEX_PSHARED (mutex)); + INTERNAL_SYSCALL_DECL (__err); + + int e = INTERNAL_SYSCALL (futex, __err, 4, &mutex->__data.__lock, + __lll_private_flag (FUTEX_LOCK_PI, + private), 1, + abstime); + if (INTERNAL_SYSCALL_ERROR_P (e, __err)) + { + if (INTERNAL_SYSCALL_ERRNO (e, __err) == ETIMEDOUT) + return ETIMEDOUT; + + if (INTERNAL_SYSCALL_ERRNO (e, __err) == ESRCH + || INTERNAL_SYSCALL_ERRNO (e, __err) == EDEADLK) + { + assert (INTERNAL_SYSCALL_ERRNO (e, __err) != EDEADLK + || (kind != PTHREAD_MUTEX_ERRORCHECK_NP + && kind != PTHREAD_MUTEX_RECURSIVE_NP)); + /* ESRCH can happen only for non-robust PI mutexes where + the owner of the lock died. */ + assert (INTERNAL_SYSCALL_ERRNO (e, __err) != ESRCH + || !robust); + + /* Delay the thread until the timeout is reached. + Then return ETIMEDOUT. */ + struct timespec reltime; + struct timespec now; + + INTERNAL_SYSCALL (clock_gettime, __err, 2, CLOCK_REALTIME, + &now); + reltime.tv_sec = abstime->tv_sec - now.tv_sec; + reltime.tv_nsec = abstime->tv_nsec - now.tv_nsec; + if (reltime.tv_nsec < 0) + { + reltime.tv_nsec += 1000000000; + --reltime.tv_sec; + } + if (reltime.tv_sec >= 0) + while (nanosleep_not_cancel (&reltime, &reltime) != 0) + continue; + + return ETIMEDOUT; + } + + return INTERNAL_SYSCALL_ERRNO (e, __err); + } + + oldval = mutex->__data.__lock; + + assert (robust || (oldval & FUTEX_OWNER_DIED) == 0); + } + + if (__builtin_expect (oldval & FUTEX_OWNER_DIED, 0)) + { + atomic_and (&mutex->__data.__lock, ~FUTEX_OWNER_DIED); + + /* We got the mutex. */ + mutex->__data.__count = 1; + /* But it is inconsistent unless marked otherwise. */ + mutex->__data.__owner = PTHREAD_MUTEX_INCONSISTENT; + + ENQUEUE_MUTEX_PI (mutex); + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); + + /* Note that we deliberately exit here. If we fall + through to the end of the function __nusers would be + incremented which is not correct because the old owner + has to be discounted. */ + return EOWNERDEAD; + } + + if (robust + && __builtin_expect (mutex->__data.__owner + == PTHREAD_MUTEX_NOTRECOVERABLE, 0)) + { + /* This mutex is now not recoverable. */ + mutex->__data.__count = 0; + + INTERNAL_SYSCALL_DECL (__err); + INTERNAL_SYSCALL (futex, __err, 4, &mutex->__data.__lock, + __lll_private_flag (FUTEX_UNLOCK_PI, + PTHREAD_ROBUST_MUTEX_PSHARED (mutex)), + 0, 0); + + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); + return ENOTRECOVERABLE; + } + + mutex->__data.__count = 1; + if (robust) + { + ENQUEUE_MUTEX_PI (mutex); + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); + } + } + break; + + case PTHREAD_MUTEX_PP_RECURSIVE_NP: + case PTHREAD_MUTEX_PP_ERRORCHECK_NP: + case PTHREAD_MUTEX_PP_NORMAL_NP: + case PTHREAD_MUTEX_PP_ADAPTIVE_NP: + { + int kind = mutex->__data.__kind & PTHREAD_MUTEX_KIND_MASK_NP; + + oldval = mutex->__data.__lock; + + /* Check whether we already hold the mutex. */ + if (mutex->__data.__owner == id) + { + if (kind == PTHREAD_MUTEX_ERRORCHECK_NP) + return EDEADLK; + + if (kind == PTHREAD_MUTEX_RECURSIVE_NP) + { + /* Just bump the counter. */ + if (__builtin_expect (mutex->__data.__count + 1 == 0, 0)) + /* Overflow of the counter. */ + return EAGAIN; + + ++mutex->__data.__count; + + return 0; + } + } + + int oldprio = -1, ceilval; + do + { + int ceiling = (oldval & PTHREAD_MUTEX_PRIO_CEILING_MASK) + >> PTHREAD_MUTEX_PRIO_CEILING_SHIFT; + + if (__pthread_current_priority () > ceiling) + { + result = EINVAL; + failpp: + if (oldprio != -1) + __pthread_tpp_change_priority (oldprio, -1); + return result; + } + + result = __pthread_tpp_change_priority (oldprio, ceiling); + if (result) + return result; + + ceilval = ceiling << PTHREAD_MUTEX_PRIO_CEILING_SHIFT; + oldprio = ceiling; + + oldval + = atomic_compare_and_exchange_val_acq (&mutex->__data.__lock, + ceilval | 1, ceilval); + + if (oldval == ceilval) + break; + + do + { + oldval + = atomic_compare_and_exchange_val_acq (&mutex->__data.__lock, + ceilval | 2, + ceilval | 1); + + if ((oldval & PTHREAD_MUTEX_PRIO_CEILING_MASK) != ceilval) + break; + + if (oldval != ceilval) + { + /* Reject invalid timeouts. */ + if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) + { + result = EINVAL; + goto failpp; + } + + struct timeval tv; + struct timespec rt; + + /* Get the current time. */ + (void) gettimeofday (&tv, NULL); + + /* Compute relative timeout. */ + rt.tv_sec = abstime->tv_sec - tv.tv_sec; + rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000; + if (rt.tv_nsec < 0) + { + rt.tv_nsec += 1000000000; + --rt.tv_sec; + } + + /* Already timed out? */ + if (rt.tv_sec < 0) + { + result = ETIMEDOUT; + goto failpp; + } + + lll_futex_timed_wait (&mutex->__data.__lock, + ceilval | 2, &rt, + PTHREAD_MUTEX_PSHARED (mutex)); + } + } + while (atomic_compare_and_exchange_val_acq (&mutex->__data.__lock, + ceilval | 2, ceilval) + != ceilval); + } + while ((oldval & PTHREAD_MUTEX_PRIO_CEILING_MASK) != ceilval); + + assert (mutex->__data.__owner == 0); + mutex->__data.__count = 1; + } + break; + + default: + /* Correct code cannot set any other type. */ + return EINVAL; + } + + if (result == 0) + { + /* Record the ownership. */ + mutex->__data.__owner = id; + ++mutex->__data.__nusers; + } + + out: + return result; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_mutex_trylock.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_mutex_trylock.c new file mode 100644 index 00000000..5555afcb --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_mutex_trylock.c @@ -0,0 +1,382 @@ +/* Copyright (C) 2002, 2003, 2005-2007, 2008 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include "pthreadP.h" +#include + + +int +__pthread_mutex_trylock ( + pthread_mutex_t *mutex) +{ + int oldval; + pid_t id = THREAD_GETMEM (THREAD_SELF, tid); + + switch (__builtin_expect (PTHREAD_MUTEX_TYPE (mutex), + PTHREAD_MUTEX_TIMED_NP)) + { + /* Recursive mutex. */ + case PTHREAD_MUTEX_RECURSIVE_NP: + /* Check whether we already hold the mutex. */ + if (mutex->__data.__owner == id) + { + /* Just bump the counter. */ + if (__builtin_expect (mutex->__data.__count + 1 == 0, 0)) + /* Overflow of the counter. */ + return EAGAIN; + + ++mutex->__data.__count; + return 0; + } + + if (lll_trylock (mutex->__data.__lock) == 0) + { + /* Record the ownership. */ + mutex->__data.__owner = id; + mutex->__data.__count = 1; + ++mutex->__data.__nusers; + return 0; + } + break; + + case PTHREAD_MUTEX_ERRORCHECK_NP: + case PTHREAD_MUTEX_TIMED_NP: + case PTHREAD_MUTEX_ADAPTIVE_NP: + /* Normal mutex. */ + if (lll_trylock (mutex->__data.__lock) != 0) + break; + + /* Record the ownership. */ + mutex->__data.__owner = id; + ++mutex->__data.__nusers; + + return 0; + + case PTHREAD_MUTEX_ROBUST_RECURSIVE_NP: + case PTHREAD_MUTEX_ROBUST_ERRORCHECK_NP: + case PTHREAD_MUTEX_ROBUST_NORMAL_NP: + case PTHREAD_MUTEX_ROBUST_ADAPTIVE_NP: + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, + &mutex->__data.__list.__next); + + oldval = mutex->__data.__lock; + do + { + again: + if ((oldval & FUTEX_OWNER_DIED) != 0) + { + /* The previous owner died. Try locking the mutex. */ + int newval = id | (oldval & FUTEX_WAITERS); + + newval + = atomic_compare_and_exchange_val_acq (&mutex->__data.__lock, + newval, oldval); + + if (newval != oldval) + { + oldval = newval; + goto again; + } + + /* We got the mutex. */ + mutex->__data.__count = 1; + /* But it is inconsistent unless marked otherwise. */ + mutex->__data.__owner = PTHREAD_MUTEX_INCONSISTENT; + + ENQUEUE_MUTEX (mutex); + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); + + /* Note that we deliberately exist here. If we fall + through to the end of the function __nusers would be + incremented which is not correct because the old + owner has to be discounted. */ + return EOWNERDEAD; + } + + /* Check whether we already hold the mutex. */ + if (__builtin_expect ((oldval & FUTEX_TID_MASK) == id, 0)) + { + int kind = PTHREAD_MUTEX_TYPE (mutex); + if (kind == PTHREAD_MUTEX_ROBUST_ERRORCHECK_NP) + { + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, + NULL); + return EDEADLK; + } + + if (kind == PTHREAD_MUTEX_ROBUST_RECURSIVE_NP) + { + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, + NULL); + + /* Just bump the counter. */ + if (__builtin_expect (mutex->__data.__count + 1 == 0, 0)) + /* Overflow of the counter. */ + return EAGAIN; + + ++mutex->__data.__count; + + return 0; + } + } + + oldval = lll_robust_trylock (mutex->__data.__lock, id); + if (oldval != 0 && (oldval & FUTEX_OWNER_DIED) == 0) + { + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); + + return EBUSY; + } + + if (__builtin_expect (mutex->__data.__owner + == PTHREAD_MUTEX_NOTRECOVERABLE, 0)) + { + /* This mutex is now not recoverable. */ + mutex->__data.__count = 0; + if (oldval == id) + lll_unlock (mutex->__data.__lock, + PTHREAD_ROBUST_MUTEX_PSHARED (mutex)); + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); + return ENOTRECOVERABLE; + } + } + while ((oldval & FUTEX_OWNER_DIED) != 0); + + ENQUEUE_MUTEX (mutex); + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); + + mutex->__data.__owner = id; + ++mutex->__data.__nusers; + mutex->__data.__count = 1; + + return 0; + + case PTHREAD_MUTEX_PI_RECURSIVE_NP: + case PTHREAD_MUTEX_PI_ERRORCHECK_NP: + case PTHREAD_MUTEX_PI_NORMAL_NP: + case PTHREAD_MUTEX_PI_ADAPTIVE_NP: + case PTHREAD_MUTEX_PI_ROBUST_RECURSIVE_NP: + case PTHREAD_MUTEX_PI_ROBUST_ERRORCHECK_NP: + case PTHREAD_MUTEX_PI_ROBUST_NORMAL_NP: + case PTHREAD_MUTEX_PI_ROBUST_ADAPTIVE_NP: + { + int kind = mutex->__data.__kind & PTHREAD_MUTEX_KIND_MASK_NP; + int robust = mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP; + + if (robust) + /* Note: robust PI futexes are signaled by setting bit 0. */ + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, + (void *) (((uintptr_t) &mutex->__data.__list.__next) + | 1)); + + oldval = mutex->__data.__lock; + + /* Check whether we already hold the mutex. */ + if (__builtin_expect ((oldval & FUTEX_TID_MASK) == id, 0)) + { + if (kind == PTHREAD_MUTEX_ERRORCHECK_NP) + { + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); + return EDEADLK; + } + + if (kind == PTHREAD_MUTEX_RECURSIVE_NP) + { + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); + + /* Just bump the counter. */ + if (__builtin_expect (mutex->__data.__count + 1 == 0, 0)) + /* Overflow of the counter. */ + return EAGAIN; + + ++mutex->__data.__count; + + return 0; + } + } + + oldval + = atomic_compare_and_exchange_val_acq (&mutex->__data.__lock, + id, 0); + + if (oldval != 0) + { + if ((oldval & FUTEX_OWNER_DIED) == 0) + { + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); + + return EBUSY; + } + + assert (robust); + + /* The mutex owner died. The kernel will now take care of + everything. */ + int private = (robust + ? PTHREAD_ROBUST_MUTEX_PSHARED (mutex) + : PTHREAD_MUTEX_PSHARED (mutex)); + INTERNAL_SYSCALL_DECL (__err); + int e = INTERNAL_SYSCALL (futex, __err, 4, &mutex->__data.__lock, + __lll_private_flag (FUTEX_TRYLOCK_PI, + private), 0, 0); + + if (INTERNAL_SYSCALL_ERROR_P (e, __err) + && INTERNAL_SYSCALL_ERRNO (e, __err) == EWOULDBLOCK) + { + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); + + return EBUSY; + } + + oldval = mutex->__data.__lock; + } + + if (__builtin_expect (oldval & FUTEX_OWNER_DIED, 0)) + { + atomic_and (&mutex->__data.__lock, ~FUTEX_OWNER_DIED); + + /* We got the mutex. */ + mutex->__data.__count = 1; + /* But it is inconsistent unless marked otherwise. */ + mutex->__data.__owner = PTHREAD_MUTEX_INCONSISTENT; + + ENQUEUE_MUTEX (mutex); + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); + + /* Note that we deliberately exit here. If we fall + through to the end of the function __nusers would be + incremented which is not correct because the old owner + has to be discounted. */ + return EOWNERDEAD; + } + + if (robust + && __builtin_expect (mutex->__data.__owner + == PTHREAD_MUTEX_NOTRECOVERABLE, 0)) + { + /* This mutex is now not recoverable. */ + mutex->__data.__count = 0; + + INTERNAL_SYSCALL_DECL (__err); + INTERNAL_SYSCALL (futex, __err, 4, &mutex->__data.__lock, + __lll_private_flag (FUTEX_UNLOCK_PI, + PTHREAD_ROBUST_MUTEX_PSHARED (mutex)), + 0, 0); + + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); + return ENOTRECOVERABLE; + } + + if (robust) + { + ENQUEUE_MUTEX_PI (mutex); + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); + } + + mutex->__data.__owner = id; + ++mutex->__data.__nusers; + mutex->__data.__count = 1; + + return 0; + } + + case PTHREAD_MUTEX_PP_RECURSIVE_NP: + case PTHREAD_MUTEX_PP_ERRORCHECK_NP: + case PTHREAD_MUTEX_PP_NORMAL_NP: + case PTHREAD_MUTEX_PP_ADAPTIVE_NP: + { + int kind = mutex->__data.__kind & PTHREAD_MUTEX_KIND_MASK_NP; + + oldval = mutex->__data.__lock; + + /* Check whether we already hold the mutex. */ + if (mutex->__data.__owner == id) + { + if (kind == PTHREAD_MUTEX_ERRORCHECK_NP) + return EDEADLK; + + if (kind == PTHREAD_MUTEX_RECURSIVE_NP) + { + /* Just bump the counter. */ + if (__builtin_expect (mutex->__data.__count + 1 == 0, 0)) + /* Overflow of the counter. */ + return EAGAIN; + + ++mutex->__data.__count; + + return 0; + } + } + + int oldprio = -1, ceilval; + do + { + int ceiling = (oldval & PTHREAD_MUTEX_PRIO_CEILING_MASK) + >> PTHREAD_MUTEX_PRIO_CEILING_SHIFT; + + if (__pthread_current_priority () > ceiling) + { + if (oldprio != -1) + __pthread_tpp_change_priority (oldprio, -1); + return EINVAL; + } + + int retval = __pthread_tpp_change_priority (oldprio, ceiling); + if (retval) + return retval; + + ceilval = ceiling << PTHREAD_MUTEX_PRIO_CEILING_SHIFT; + oldprio = ceiling; + + oldval + = atomic_compare_and_exchange_val_acq (&mutex->__data.__lock, + ceilval | 1, ceilval); + + if (oldval == ceilval) + break; + } + while ((oldval & PTHREAD_MUTEX_PRIO_CEILING_MASK) != ceilval); + + if (oldval != ceilval) + { + __pthread_tpp_change_priority (oldprio, -1); + break; + } + + assert (mutex->__data.__owner == 0); + /* Record the ownership. */ + mutex->__data.__owner = id; + ++mutex->__data.__nusers; + mutex->__data.__count = 1; + + return 0; + } + break; + + default: + /* Correct code cannot set any other type. */ + return EINVAL; + } + + return EBUSY; +} +strong_alias (__pthread_mutex_trylock, pthread_mutex_trylock) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_mutex_unlock.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_mutex_unlock.c new file mode 100644 index 00000000..3abada23 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_mutex_unlock.c @@ -0,0 +1,294 @@ +/* Copyright (C) 2002, 2003, 2005-2008, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include "pthreadP.h" +#include + +static int +internal_function +__pthread_mutex_unlock_full (pthread_mutex_t *mutex, int decr) + __attribute_noinline__; + +int +internal_function attribute_hidden +__pthread_mutex_unlock_usercnt ( + pthread_mutex_t *mutex, + int decr) +{ + int type = PTHREAD_MUTEX_TYPE (mutex); + if (__builtin_expect (type & ~PTHREAD_MUTEX_KIND_MASK_NP, 0)) + return __pthread_mutex_unlock_full (mutex, decr); + + if (__builtin_expect (type, PTHREAD_MUTEX_TIMED_NP) + == PTHREAD_MUTEX_TIMED_NP) + { + /* Always reset the owner field. */ + normal: + mutex->__data.__owner = 0; + if (decr) + /* One less user. */ + --mutex->__data.__nusers; + + /* Unlock. */ + lll_unlock (mutex->__data.__lock, PTHREAD_MUTEX_PSHARED (mutex)); + return 0; + } + else if (__builtin_expect (type == PTHREAD_MUTEX_RECURSIVE_NP, 1)) + { + /* Recursive mutex. */ + if (mutex->__data.__owner != THREAD_GETMEM (THREAD_SELF, tid)) + return EPERM; + + if (--mutex->__data.__count != 0) + /* We still hold the mutex. */ + return 0; + goto normal; + } + else if (__builtin_expect (type == PTHREAD_MUTEX_ADAPTIVE_NP, 1)) + goto normal; + else + { + /* Error checking mutex. */ + assert (type == PTHREAD_MUTEX_ERRORCHECK_NP); + if (mutex->__data.__owner != THREAD_GETMEM (THREAD_SELF, tid) + || ! lll_islocked (mutex->__data.__lock)) + return EPERM; + goto normal; + } +} + + +static int +internal_function +__pthread_mutex_unlock_full (pthread_mutex_t *mutex, int decr) +{ + int newowner = 0; + + switch (PTHREAD_MUTEX_TYPE (mutex)) + { + case PTHREAD_MUTEX_ROBUST_RECURSIVE_NP: + /* Recursive mutex. */ + if ((mutex->__data.__lock & FUTEX_TID_MASK) + == THREAD_GETMEM (THREAD_SELF, tid) + && __builtin_expect (mutex->__data.__owner + == PTHREAD_MUTEX_INCONSISTENT, 0)) + { + if (--mutex->__data.__count != 0) + /* We still hold the mutex. */ + return ENOTRECOVERABLE; + + goto notrecoverable; + } + + if (mutex->__data.__owner != THREAD_GETMEM (THREAD_SELF, tid)) + return EPERM; + + if (--mutex->__data.__count != 0) + /* We still hold the mutex. */ + return 0; + + goto robust; + + case PTHREAD_MUTEX_ROBUST_ERRORCHECK_NP: + case PTHREAD_MUTEX_ROBUST_NORMAL_NP: + case PTHREAD_MUTEX_ROBUST_ADAPTIVE_NP: + if ((mutex->__data.__lock & FUTEX_TID_MASK) + != THREAD_GETMEM (THREAD_SELF, tid) + || ! lll_islocked (mutex->__data.__lock)) + return EPERM; + + /* If the previous owner died and the caller did not succeed in + making the state consistent, mark the mutex as unrecoverable + and make all waiters. */ + if (__builtin_expect (mutex->__data.__owner + == PTHREAD_MUTEX_INCONSISTENT, 0)) + notrecoverable: + newowner = PTHREAD_MUTEX_NOTRECOVERABLE; + + robust: + /* Remove mutex from the list. */ + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, + &mutex->__data.__list.__next); + DEQUEUE_MUTEX (mutex); + + mutex->__data.__owner = newowner; + if (decr) + /* One less user. */ + --mutex->__data.__nusers; + + /* Unlock. */ + lll_robust_unlock (mutex->__data.__lock, + PTHREAD_ROBUST_MUTEX_PSHARED (mutex)); + + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); + break; + + case PTHREAD_MUTEX_PI_RECURSIVE_NP: + /* Recursive mutex. */ + if (mutex->__data.__owner != THREAD_GETMEM (THREAD_SELF, tid)) + return EPERM; + + if (--mutex->__data.__count != 0) + /* We still hold the mutex. */ + return 0; + goto continue_pi_non_robust; + + case PTHREAD_MUTEX_PI_ROBUST_RECURSIVE_NP: + /* Recursive mutex. */ + if ((mutex->__data.__lock & FUTEX_TID_MASK) + == THREAD_GETMEM (THREAD_SELF, tid) + && __builtin_expect (mutex->__data.__owner + == PTHREAD_MUTEX_INCONSISTENT, 0)) + { + if (--mutex->__data.__count != 0) + /* We still hold the mutex. */ + return ENOTRECOVERABLE; + + goto pi_notrecoverable; + } + + if (mutex->__data.__owner != THREAD_GETMEM (THREAD_SELF, tid)) + return EPERM; + + if (--mutex->__data.__count != 0) + /* We still hold the mutex. */ + return 0; + + goto continue_pi_robust; + + case PTHREAD_MUTEX_PI_ERRORCHECK_NP: + case PTHREAD_MUTEX_PI_NORMAL_NP: + case PTHREAD_MUTEX_PI_ADAPTIVE_NP: + case PTHREAD_MUTEX_PI_ROBUST_ERRORCHECK_NP: + case PTHREAD_MUTEX_PI_ROBUST_NORMAL_NP: + case PTHREAD_MUTEX_PI_ROBUST_ADAPTIVE_NP: + if ((mutex->__data.__lock & FUTEX_TID_MASK) + != THREAD_GETMEM (THREAD_SELF, tid) + || ! lll_islocked (mutex->__data.__lock)) + return EPERM; + + /* If the previous owner died and the caller did not succeed in + making the state consistent, mark the mutex as unrecoverable + and make all waiters. */ + if ((mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP) != 0 + && __builtin_expect (mutex->__data.__owner + == PTHREAD_MUTEX_INCONSISTENT, 0)) + pi_notrecoverable: + newowner = PTHREAD_MUTEX_NOTRECOVERABLE; + + if ((mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP) != 0) + { + continue_pi_robust: + /* Remove mutex from the list. + Note: robust PI futexes are signaled by setting bit 0. */ + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, + (void *) (((uintptr_t) &mutex->__data.__list.__next) + | 1)); + DEQUEUE_MUTEX (mutex); + } + + continue_pi_non_robust: + mutex->__data.__owner = newowner; + if (decr) + /* One less user. */ + --mutex->__data.__nusers; + + /* Unlock. */ + if ((mutex->__data.__lock & FUTEX_WAITERS) != 0 + || atomic_compare_and_exchange_bool_rel (&mutex->__data.__lock, 0, + THREAD_GETMEM (THREAD_SELF, + tid))) + { + int robust = mutex->__data.__kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP; + int private = (robust + ? PTHREAD_ROBUST_MUTEX_PSHARED (mutex) + : PTHREAD_MUTEX_PSHARED (mutex)); + INTERNAL_SYSCALL_DECL (__err); + INTERNAL_SYSCALL (futex, __err, 2, &mutex->__data.__lock, + __lll_private_flag (FUTEX_UNLOCK_PI, private)); + } + + THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL); + break; + + case PTHREAD_MUTEX_PP_RECURSIVE_NP: + /* Recursive mutex. */ + if (mutex->__data.__owner != THREAD_GETMEM (THREAD_SELF, tid)) + return EPERM; + + if (--mutex->__data.__count != 0) + /* We still hold the mutex. */ + return 0; + goto pp; + + case PTHREAD_MUTEX_PP_ERRORCHECK_NP: + /* Error checking mutex. */ + if (mutex->__data.__owner != THREAD_GETMEM (THREAD_SELF, tid) + || (mutex->__data.__lock & ~ PTHREAD_MUTEX_PRIO_CEILING_MASK) == 0) + return EPERM; + /* FALLTHROUGH */ + + case PTHREAD_MUTEX_PP_NORMAL_NP: + case PTHREAD_MUTEX_PP_ADAPTIVE_NP: + /* Always reset the owner field. */ + pp: + mutex->__data.__owner = 0; + + if (decr) + /* One less user. */ + --mutex->__data.__nusers; + + /* Unlock. */ + int newval, oldval; + do + { + oldval = mutex->__data.__lock; + newval = oldval & PTHREAD_MUTEX_PRIO_CEILING_MASK; + } + while (atomic_compare_and_exchange_bool_rel (&mutex->__data.__lock, + newval, oldval)); + + if ((oldval & ~PTHREAD_MUTEX_PRIO_CEILING_MASK) > 1) + lll_futex_wake (&mutex->__data.__lock, 1, + PTHREAD_MUTEX_PSHARED (mutex)); + + int oldprio = newval >> PTHREAD_MUTEX_PRIO_CEILING_SHIFT; + return __pthread_tpp_change_priority (oldprio, -1); + + default: + /* Correct code cannot set any other type. */ + return EINVAL; + } + + return 0; +} + + +int +attribute_protected +__pthread_mutex_unlock ( + pthread_mutex_t *mutex) +{ + return __pthread_mutex_unlock_usercnt (mutex, 1); +} +strong_alias (__pthread_mutex_unlock, pthread_mutex_unlock) +strong_alias (__pthread_mutex_unlock, __pthread_mutex_unlock_internal) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_mutexattr_destroy.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_mutexattr_destroy.c new file mode 100644 index 00000000..adf2884b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_mutexattr_destroy.c @@ -0,0 +1,28 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + + +int +__pthread_mutexattr_destroy (pthread_mutexattr_t *attr) +{ + return 0; +} +strong_alias (__pthread_mutexattr_destroy, pthread_mutexattr_destroy) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_mutexattr_getprioceiling.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_mutexattr_getprioceiling.c new file mode 100644 index 00000000..29e3eb21 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_mutexattr_getprioceiling.c @@ -0,0 +1,48 @@ +/* Get priority ceiling setting from pthread_mutexattr_t. + Copyright (C) 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2006. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + + +int +pthread_mutexattr_getprioceiling ( + const pthread_mutexattr_t *attr, + int *prioceiling) +{ + const struct pthread_mutexattr *iattr; + int ceiling; + + iattr = (const struct pthread_mutexattr *) attr; + + ceiling = ((iattr->mutexkind & PTHREAD_MUTEXATTR_PRIO_CEILING_MASK) + >> PTHREAD_MUTEXATTR_PRIO_CEILING_SHIFT); + + if (! ceiling) + { + if (__sched_fifo_min_prio == -1) + __init_sched_fifo_prio (); + if (ceiling < __sched_fifo_min_prio) + ceiling = __sched_fifo_min_prio; + } + + *prioceiling = ceiling; + + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_mutexattr_getprotocol.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_mutexattr_getprotocol.c new file mode 100644 index 00000000..49c5157f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_mutexattr_getprotocol.c @@ -0,0 +1,37 @@ +/* Get priority protocol setting from pthread_mutexattr_t. + Copyright (C) 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2006. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + + +int +pthread_mutexattr_getprotocol ( + const pthread_mutexattr_t *attr, + int *protocol) +{ + const struct pthread_mutexattr *iattr; + + iattr = (const struct pthread_mutexattr *) attr; + + *protocol = ((iattr->mutexkind & PTHREAD_MUTEXATTR_PROTOCOL_MASK) + >> PTHREAD_MUTEXATTR_PROTOCOL_SHIFT); + + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_mutexattr_getpshared.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_mutexattr_getpshared.c new file mode 100644 index 00000000..e67cf15c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_mutexattr_getpshared.c @@ -0,0 +1,36 @@ +/* Copyright (C) 2002, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + + +int +pthread_mutexattr_getpshared ( + const pthread_mutexattr_t *attr, + int *pshared) +{ + const struct pthread_mutexattr *iattr; + + iattr = (const struct pthread_mutexattr *) attr; + + *pshared = ((iattr->mutexkind & PTHREAD_MUTEXATTR_FLAG_PSHARED) != 0 + ? PTHREAD_PROCESS_SHARED : PTHREAD_PROCESS_PRIVATE); + + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_mutexattr_getrobust.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_mutexattr_getrobust.c new file mode 100644 index 00000000..7d495f8f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_mutexattr_getrobust.c @@ -0,0 +1,37 @@ +/* Copyright (C) 2005, 2010 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2005. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + + +int +pthread_mutexattr_getrobust ( + const pthread_mutexattr_t *attr, + int *robustness) +{ + const struct pthread_mutexattr *iattr; + + iattr = (const struct pthread_mutexattr *) attr; + + *robustness = ((iattr->mutexkind & PTHREAD_MUTEXATTR_FLAG_ROBUST) != 0 + ? PTHREAD_MUTEX_ROBUST_NP : PTHREAD_MUTEX_STALLED_NP); + + return 0; +} +weak_alias (pthread_mutexattr_getrobust, pthread_mutexattr_getrobust_np) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_mutexattr_gettype.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_mutexattr_gettype.c new file mode 100644 index 00000000..25434861 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_mutexattr_gettype.c @@ -0,0 +1,36 @@ +/* Copyright (C) 2002, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + + +int +pthread_mutexattr_gettype ( + const pthread_mutexattr_t *attr, + int *kind) +{ + const struct pthread_mutexattr *iattr; + + iattr = (const struct pthread_mutexattr *) attr; + + *kind = iattr->mutexkind & ~PTHREAD_MUTEXATTR_FLAG_BITS; + + return 0; +} +weak_alias (pthread_mutexattr_gettype, pthread_mutexattr_getkind_np) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_mutexattr_init.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_mutexattr_init.c new file mode 100644 index 00000000..1b672846 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_mutexattr_init.c @@ -0,0 +1,38 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + + +int +__pthread_mutexattr_init ( + pthread_mutexattr_t *attr) +{ + if (sizeof (struct pthread_mutexattr) != sizeof (pthread_mutexattr_t)) + memset (attr, '\0', sizeof (*attr)); + + /* We use bit 31 to signal whether the mutex is going to be + process-shared or not. By default it is zero, i.e., the mutex is + not process-shared. */ + ((struct pthread_mutexattr *) attr)->mutexkind = PTHREAD_MUTEX_NORMAL; + + return 0; +} +strong_alias (__pthread_mutexattr_init, pthread_mutexattr_init) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_mutexattr_setprioceiling.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_mutexattr_setprioceiling.c new file mode 100644 index 00000000..3a13fb8e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_mutexattr_setprioceiling.c @@ -0,0 +1,47 @@ +/* Change priority ceiling setting in pthread_mutexattr_t. + Copyright (C) 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2006. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + + +int +pthread_mutexattr_setprioceiling ( + pthread_mutexattr_t *attr, + int prioceiling) +{ + if (__sched_fifo_min_prio == -1) + __init_sched_fifo_prio (); + + if (__builtin_expect (prioceiling < __sched_fifo_min_prio, 0) + || __builtin_expect (prioceiling > __sched_fifo_max_prio, 0) + || __builtin_expect ((prioceiling + & (PTHREAD_MUTEXATTR_PRIO_CEILING_MASK + >> PTHREAD_MUTEXATTR_PRIO_CEILING_SHIFT)) + != prioceiling, 0)) + return EINVAL; + + struct pthread_mutexattr *iattr = (struct pthread_mutexattr *) attr; + + iattr->mutexkind = ((iattr->mutexkind & ~PTHREAD_MUTEXATTR_PRIO_CEILING_MASK) + | (prioceiling << PTHREAD_MUTEXATTR_PRIO_CEILING_SHIFT)); + + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_mutexattr_setprotocol.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_mutexattr_setprotocol.c new file mode 100644 index 00000000..1ffcaf63 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_mutexattr_setprotocol.c @@ -0,0 +1,41 @@ +/* Change priority protocol setting in pthread_mutexattr_t. + Copyright (C) 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2006. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + + +int +pthread_mutexattr_setprotocol ( + pthread_mutexattr_t *attr, + int protocol) +{ + if (protocol != PTHREAD_PRIO_NONE + && protocol != PTHREAD_PRIO_INHERIT + && __builtin_expect (protocol != PTHREAD_PRIO_PROTECT, 0)) + return EINVAL; + + struct pthread_mutexattr *iattr = (struct pthread_mutexattr *) attr; + + iattr->mutexkind = ((iattr->mutexkind & ~PTHREAD_MUTEXATTR_PROTOCOL_MASK) + | (protocol << PTHREAD_MUTEXATTR_PROTOCOL_SHIFT)); + + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_mutexattr_setpshared.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_mutexattr_setpshared.c new file mode 100644 index 00000000..d84a92ea --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_mutexattr_setpshared.c @@ -0,0 +1,43 @@ +/* Copyright (C) 2002, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + + +int +pthread_mutexattr_setpshared ( + pthread_mutexattr_t *attr, + int pshared) +{ + struct pthread_mutexattr *iattr; + + if (pshared != PTHREAD_PROCESS_PRIVATE + && __builtin_expect (pshared != PTHREAD_PROCESS_SHARED, 0)) + return EINVAL; + + iattr = (struct pthread_mutexattr *) attr; + + if (pshared == PTHREAD_PROCESS_PRIVATE) + iattr->mutexkind &= ~PTHREAD_MUTEXATTR_FLAG_PSHARED; + else + iattr->mutexkind |= PTHREAD_MUTEXATTR_FLAG_PSHARED; + + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_mutexattr_setrobust.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_mutexattr_setrobust.c new file mode 100644 index 00000000..fe94fd26 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_mutexattr_setrobust.c @@ -0,0 +1,44 @@ +/* Copyright (C) 2005, 2010 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2005. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + + +int +pthread_mutexattr_setrobust ( + pthread_mutexattr_t *attr, + int robustness) +{ + if (robustness != PTHREAD_MUTEX_STALLED_NP + && __builtin_expect (robustness != PTHREAD_MUTEX_ROBUST_NP, 0)) + return EINVAL; + + struct pthread_mutexattr *iattr = (struct pthread_mutexattr *) attr; + + /* We use bit 30 to signal whether the mutex is going to be + robust or not. */ + if (robustness == PTHREAD_MUTEX_STALLED_NP) + iattr->mutexkind &= ~PTHREAD_MUTEXATTR_FLAG_ROBUST; + else + iattr->mutexkind |= PTHREAD_MUTEXATTR_FLAG_ROBUST; + + return 0; +} +weak_alias (pthread_mutexattr_setrobust, pthread_mutexattr_setrobust_np) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_mutexattr_settype.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_mutexattr_settype.c new file mode 100644 index 00000000..f86dd63a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_mutexattr_settype.c @@ -0,0 +1,41 @@ +/* Copyright (C) 2002, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + + +int +__pthread_mutexattr_settype ( + pthread_mutexattr_t *attr, + int kind) +{ + struct pthread_mutexattr *iattr; + + if (kind < PTHREAD_MUTEX_NORMAL || kind > PTHREAD_MUTEX_ADAPTIVE_NP) + return EINVAL; + + iattr = (struct pthread_mutexattr *) attr; + + iattr->mutexkind = (iattr->mutexkind & PTHREAD_MUTEXATTR_FLAG_BITS) | kind; + + return 0; +} +weak_alias (__pthread_mutexattr_settype, pthread_mutexattr_setkind_np) +strong_alias (__pthread_mutexattr_settype, pthread_mutexattr_settype) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_rwlock_destroy.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_rwlock_destroy.c new file mode 100644 index 00000000..d38202b4 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_rwlock_destroy.c @@ -0,0 +1,29 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "pthreadP.h" + + +int +__pthread_rwlock_destroy (pthread_rwlock_t *rwlock) +{ + /* Nothing to be done. For now. */ + return 0; +} +strong_alias (__pthread_rwlock_destroy, pthread_rwlock_destroy) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_rwlock_init.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_rwlock_init.c new file mode 100644 index 00000000..6cbdd975 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_rwlock_init.c @@ -0,0 +1,73 @@ +/* Copyright (C) 2002, 2007, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "pthreadP.h" +#include +#include + +static const struct pthread_rwlockattr default_attr = + { + .lockkind = PTHREAD_RWLOCK_DEFAULT_NP, + .pshared = PTHREAD_PROCESS_PRIVATE + }; + + +int +__pthread_rwlock_init ( + pthread_rwlock_t *rwlock, + const pthread_rwlockattr_t *attr) +{ + const struct pthread_rwlockattr *iattr; + + iattr = ((const struct pthread_rwlockattr *) attr) ?: &default_attr; + + memset (rwlock, '\0', sizeof (*rwlock)); + + rwlock->__data.__flags + = iattr->lockkind == PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP; + + /* The __SHARED field is computed to minimize the work that needs to + be done while handling the futex. There are two inputs: the + availability of private futexes and whether the rwlock is shared + or private. Unfortunately the value of a private rwlock is + fixed: it must be zero. The PRIVATE_FUTEX flag has the value + 0x80 in case private futexes are available and zero otherwise. + This leads to the following table: + + | pshared | result + | shared private | shared private | + ------------+-----------------+-----------------+ + !avail 0 | 0 0 | 0 0 | + avail 0x80 | 0x80 0 | 0 0x80 | + + If the pshared value is in locking functions XORed with avail + we get the expected result. */ +#ifdef __ASSUME_PRIVATE_FUTEX + rwlock->__data.__shared = (iattr->pshared == PTHREAD_PROCESS_PRIVATE + ? 0 : FUTEX_PRIVATE_FLAG); +#else + rwlock->__data.__shared = (iattr->pshared == PTHREAD_PROCESS_PRIVATE + ? 0 + : THREAD_GETMEM (THREAD_SELF, + header.private_futex)); +#endif + + return 0; +} +strong_alias (__pthread_rwlock_init, pthread_rwlock_init) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_rwlock_tryrdlock.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_rwlock_tryrdlock.c new file mode 100644 index 00000000..30e6dc5a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_rwlock_tryrdlock.c @@ -0,0 +1,50 @@ +/* Copyright (C) 2002, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include "pthreadP.h" +#include + + +int +__pthread_rwlock_tryrdlock ( + pthread_rwlock_t *rwlock) +{ + int result = EBUSY; + + lll_lock (rwlock->__data.__lock, rwlock->__data.__shared); + + if (rwlock->__data.__writer == 0 + && (rwlock->__data.__nr_writers_queued == 0 + || PTHREAD_RWLOCK_PREFER_READER_P (rwlock))) + { + if (__builtin_expect (++rwlock->__data.__nr_readers == 0, 0)) + { + --rwlock->__data.__nr_readers; + result = EAGAIN; + } + else + result = 0; + } + + lll_unlock (rwlock->__data.__lock, rwlock->__data.__shared); + + return result; +} +strong_alias (__pthread_rwlock_tryrdlock, pthread_rwlock_tryrdlock) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_rwlock_trywrlock.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_rwlock_trywrlock.c new file mode 100644 index 00000000..a6f9ee43 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_rwlock_trywrlock.c @@ -0,0 +1,43 @@ +/* Copyright (C) 2002, 2003, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include "pthreadP.h" +#include + + +int +__pthread_rwlock_trywrlock ( + pthread_rwlock_t *rwlock) +{ + int result = EBUSY; + + lll_lock (rwlock->__data.__lock, rwlock->__data.__shared); + + if (rwlock->__data.__writer == 0 && rwlock->__data.__nr_readers == 0) + { + rwlock->__data.__writer = THREAD_GETMEM (THREAD_SELF, tid); + result = 0; + } + + lll_unlock (rwlock->__data.__lock, rwlock->__data.__shared); + + return result; +} +strong_alias (__pthread_rwlock_trywrlock, pthread_rwlock_trywrlock) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_rwlockattr_destroy.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_rwlockattr_destroy.c new file mode 100644 index 00000000..db187041 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_rwlockattr_destroy.c @@ -0,0 +1,29 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "pthreadP.h" + + +int +pthread_rwlockattr_destroy (pthread_rwlockattr_t *attr) +{ + /* Nothing to do. For now. */ + + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_rwlockattr_getkind_np.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_rwlockattr_getkind_np.c new file mode 100644 index 00000000..b15275c4 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_rwlockattr_getkind_np.c @@ -0,0 +1,31 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "pthreadP.h" + + +int +pthread_rwlockattr_getkind_np ( + const pthread_rwlockattr_t *attr, + int *pref) +{ + *pref = ((const struct pthread_rwlockattr *) attr)->lockkind; + + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_rwlockattr_getpshared.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_rwlockattr_getpshared.c new file mode 100644 index 00000000..2e0437c7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_rwlockattr_getpshared.c @@ -0,0 +1,31 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "pthreadP.h" + + +int +pthread_rwlockattr_getpshared ( + const pthread_rwlockattr_t *attr, + int *pshared) +{ + *pshared = ((const struct pthread_rwlockattr *) attr)->pshared; + + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_rwlockattr_init.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_rwlockattr_init.c new file mode 100644 index 00000000..b33ae5bf --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_rwlockattr_init.c @@ -0,0 +1,34 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "pthreadP.h" + + +int +pthread_rwlockattr_init (pthread_rwlockattr_t *attr) +{ + struct pthread_rwlockattr *iattr; + + iattr = (struct pthread_rwlockattr *) attr; + + iattr->lockkind = PTHREAD_RWLOCK_DEFAULT_NP; + iattr->pshared = PTHREAD_PROCESS_PRIVATE; + + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_rwlockattr_setkind_np.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_rwlockattr_setkind_np.c new file mode 100644 index 00000000..186bf737 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_rwlockattr_setkind_np.c @@ -0,0 +1,41 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include "pthreadP.h" + + +int +pthread_rwlockattr_setkind_np ( + pthread_rwlockattr_t *attr, + int pref) +{ + struct pthread_rwlockattr *iattr; + + if (pref != PTHREAD_RWLOCK_PREFER_READER_NP + && pref != PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP + && __builtin_expect (pref != PTHREAD_RWLOCK_PREFER_WRITER_NP, 0)) + return EINVAL; + + iattr = (struct pthread_rwlockattr *) attr; + + iattr->lockkind = pref; + + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_rwlockattr_setpshared.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_rwlockattr_setpshared.c new file mode 100644 index 00000000..a30de0ee --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_rwlockattr_setpshared.c @@ -0,0 +1,40 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include "pthreadP.h" + + +int +pthread_rwlockattr_setpshared ( + pthread_rwlockattr_t *attr, + int pshared) +{ + struct pthread_rwlockattr *iattr; + + if (pshared != PTHREAD_PROCESS_SHARED + && __builtin_expect (pshared != PTHREAD_PROCESS_PRIVATE, 0)) + return EINVAL; + + iattr = (struct pthread_rwlockattr *) attr; + + iattr->pshared = pshared; + + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_self.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_self.c new file mode 100644 index 00000000..1ad52836 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_self.c @@ -0,0 +1,30 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "pthreadP.h" +#include + + +pthread_t +attribute_protected +__pthread_self (void) +{ + return (pthread_t) THREAD_SELF; +} +strong_alias (__pthread_self, pthread_self) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_setcancelstate.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_setcancelstate.c new file mode 100644 index 00000000..ed697358 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_setcancelstate.c @@ -0,0 +1,74 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include "pthreadP.h" +#include + + +int +attribute_protected +__pthread_setcancelstate ( + int state, + int *oldstate) +{ + volatile struct pthread *self; + + if (state < PTHREAD_CANCEL_ENABLE || state > PTHREAD_CANCEL_DISABLE) + return EINVAL; + + self = THREAD_SELF; + + int oldval = THREAD_GETMEM (self, cancelhandling); + while (1) + { + int newval = (state == PTHREAD_CANCEL_DISABLE + ? oldval | CANCELSTATE_BITMASK + : oldval & ~CANCELSTATE_BITMASK); + + /* Store the old value. */ + if (oldstate != NULL) + *oldstate = ((oldval & CANCELSTATE_BITMASK) + ? PTHREAD_CANCEL_DISABLE : PTHREAD_CANCEL_ENABLE); + + /* Avoid doing unnecessary work. The atomic operation can + potentially be expensive if the memory has to be locked and + remote cache lines have to be invalidated. */ + if (oldval == newval) + break; + + /* Update the cancel handling word. This has to be done + atomically since other bits could be modified as well. */ + int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling, newval, + oldval); + if (__builtin_expect (curval == oldval, 1)) + { + if (CANCEL_ENABLED_AND_CANCELED_AND_ASYNCHRONOUS (newval)) + __do_cancel (); + + break; + } + + /* Prepare for the next round. */ + oldval = curval; + } + + return 0; +} +strong_alias (__pthread_setcancelstate, pthread_setcancelstate) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_setcanceltype.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_setcanceltype.c new file mode 100644 index 00000000..8ac0df30 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_setcanceltype.c @@ -0,0 +1,77 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include "pthreadP.h" +#include + + +int +attribute_protected +__pthread_setcanceltype ( + int type, + int *oldtype) +{ + volatile struct pthread *self; + + if (type < PTHREAD_CANCEL_DEFERRED || type > PTHREAD_CANCEL_ASYNCHRONOUS) + return EINVAL; + + self = THREAD_SELF; + + int oldval = THREAD_GETMEM (self, cancelhandling); + while (1) + { + int newval = (type == PTHREAD_CANCEL_ASYNCHRONOUS + ? oldval | CANCELTYPE_BITMASK + : oldval & ~CANCELTYPE_BITMASK); + + /* Store the old value. */ + if (oldtype != NULL) + *oldtype = ((oldval & CANCELTYPE_BITMASK) + ? PTHREAD_CANCEL_ASYNCHRONOUS : PTHREAD_CANCEL_DEFERRED); + + /* Avoid doing unnecessary work. The atomic operation can + potentially be expensive if the memory has to be locked and + remote cache lines have to be invalidated. */ + if (oldval == newval) + break; + + /* Update the cancel handling word. This has to be done + atomically since other bits could be modified as well. */ + int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling, newval, + oldval); + if (__builtin_expect (curval == oldval, 1)) + { + if (CANCEL_ENABLED_AND_CANCELED_AND_ASYNCHRONOUS (newval)) + { + THREAD_SETMEM (self, result, PTHREAD_CANCELED); + __do_cancel (); + } + + break; + } + + /* Prepare for the next round. */ + oldval = curval; + } + + return 0; +} +strong_alias (__pthread_setcanceltype, pthread_setcanceltype) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_setconcurrency.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_setconcurrency.c new file mode 100644 index 00000000..754fe3f2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_setconcurrency.c @@ -0,0 +1,40 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include "pthreadP.h" + + +/* Global definition. Needed in pthread_getconcurrency as well. */ +int __concurrency_level; + + +int +pthread_setconcurrency (int level) +{ + if (level < 0) + return EINVAL; + + __concurrency_level = level; + + /* XXX For ports which actually need to handle the concurrency level + some more code is probably needed here. */ + + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_setegid.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_setegid.c new file mode 100644 index 00000000..9252dfac --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_setegid.c @@ -0,0 +1,3 @@ +#define SINGLE_THREAD +#define setegid pthread_setegid_np +#include diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_seteuid.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_seteuid.c new file mode 100644 index 00000000..47bb6980 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_seteuid.c @@ -0,0 +1,3 @@ +#define SINGLE_THREAD +#define seteuid pthread_seteuid_np +#include diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_setgid.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_setgid.c new file mode 100644 index 00000000..b06bffbf --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_setgid.c @@ -0,0 +1,3 @@ +#define SINGLE_THREAD +#define __setgid pthread_setgid_np +#include diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_setregid.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_setregid.c new file mode 100644 index 00000000..7461d2b7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_setregid.c @@ -0,0 +1,3 @@ +#define SINGLE_THREAD +#define __setregid pthread_setregid_np +#include diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_setresgid.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_setresgid.c new file mode 100644 index 00000000..369fae26 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_setresgid.c @@ -0,0 +1,3 @@ +#define SINGLE_THREAD +#define __setresgid pthread_setresgid_np +#include diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_setresuid.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_setresuid.c new file mode 100644 index 00000000..ac57c0fa --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_setresuid.c @@ -0,0 +1,3 @@ +#define SINGLE_THREAD +#define __setresuid pthread_setresuid_np +#include diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_setreuid.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_setreuid.c new file mode 100644 index 00000000..aa804ab0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_setreuid.c @@ -0,0 +1,3 @@ +#define SINGLE_THREAD +#define __setreuid pthread_setreuid_np +#include diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_setschedparam.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_setschedparam.c new file mode 100644 index 00000000..c97de7d8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_setschedparam.c @@ -0,0 +1,75 @@ +/* Copyright (C) 2002, 2003, 2004, 2006, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include "pthreadP.h" +#include + + +int +attribute_protected +__pthread_setschedparam ( + pthread_t threadid, + int policy, + const struct sched_param *param) +{ + struct pthread *pd = (struct pthread *) threadid; + + /* Make sure the descriptor is valid. */ + if (INVALID_TD_P (pd)) + /* Not a valid thread handle. */ + return ESRCH; + + int result = 0; + + lll_lock (pd->lock, LLL_PRIVATE); + + struct sched_param p; + const struct sched_param *orig_param = param; + + /* If the thread should have higher priority because of some + PTHREAD_PRIO_PROTECT mutexes it holds, adjust the priority. */ + if (__builtin_expect (pd->tpp != NULL, 0) + && pd->tpp->priomax > param->sched_priority) + { + p = *param; + p.sched_priority = pd->tpp->priomax; + param = &p; + } + + /* Try to set the scheduler information. */ + if (__builtin_expect (__sched_setscheduler (pd->tid, policy, + param) == -1, 0)) + result = errno; + else + { + /* We succeeded changing the kernel information. Reflect this + change in the thread descriptor. */ + pd->schedpolicy = policy; + memcpy (&pd->schedparam, orig_param, sizeof (struct sched_param)); + pd->flags |= ATTR_FLAG_SCHED_SET | ATTR_FLAG_POLICY_SET; + } + + lll_unlock (pd->lock, LLL_PRIVATE); + + return result; +} +strong_alias (__pthread_setschedparam, pthread_setschedparam) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_setschedprio.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_setschedprio.c new file mode 100644 index 00000000..7951460d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_setschedprio.c @@ -0,0 +1,66 @@ +/* Copyright (C) 2002, 2003, 2004, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include "pthreadP.h" +#include + + +int +pthread_setschedprio ( + pthread_t threadid, + int prio) +{ + struct pthread *pd = (struct pthread *) threadid; + + /* Make sure the descriptor is valid. */ + if (INVALID_TD_P (pd)) + /* Not a valid thread handle. */ + return ESRCH; + + int result = 0; + struct sched_param param; + param.sched_priority = prio; + + lll_lock (pd->lock, LLL_PRIVATE); + + /* If the thread should have higher priority because of some + PTHREAD_PRIO_PROTECT mutexes it holds, adjust the priority. */ + if (__builtin_expect (pd->tpp != NULL, 0) && pd->tpp->priomax > prio) + param.sched_priority = pd->tpp->priomax; + + /* Try to set the scheduler information. */ + if (__builtin_expect (sched_setparam (pd->tid, ¶m) == -1, 0)) + result = errno; + else + { + /* We succeeded changing the kernel information. Reflect this + change in the thread descriptor. */ + param.sched_priority = prio; + memcpy (&pd->schedparam, ¶m, sizeof (struct sched_param)); + pd->flags |= ATTR_FLAG_SCHED_SET; + } + + lll_unlock (pd->lock, LLL_PRIVATE); + + return result; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_setspecific.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_setspecific.c new file mode 100644 index 00000000..13b24dcf --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_setspecific.c @@ -0,0 +1,97 @@ +/* Copyright (C) 2002, 2003, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include "pthreadP.h" + + +int +attribute_protected +__pthread_setspecific ( + pthread_key_t key, + const void *value) +{ + struct pthread *self; + unsigned int idx1st; + unsigned int idx2nd; + struct pthread_key_data *level2; + unsigned int seq; + + self = THREAD_SELF; + + /* Special case access to the first 2nd-level block. This is the + usual case. */ + if (__builtin_expect (key < PTHREAD_KEY_2NDLEVEL_SIZE, 1)) + { + /* Verify the key is sane. */ + if (KEY_UNUSED ((seq = __pthread_keys[key].seq))) + /* Not valid. */ + return EINVAL; + + level2 = &self->specific_1stblock[key]; + + /* Remember that we stored at least one set of data. */ + if (value != NULL) + THREAD_SETMEM (self, specific_used, true); + } + else + { + if (key >= PTHREAD_KEYS_MAX + || KEY_UNUSED ((seq = __pthread_keys[key].seq))) + /* Not valid. */ + return EINVAL; + + idx1st = key / PTHREAD_KEY_2NDLEVEL_SIZE; + idx2nd = key % PTHREAD_KEY_2NDLEVEL_SIZE; + + /* This is the second level array. Allocate it if necessary. */ + level2 = THREAD_GETMEM_NC (self, specific, idx1st); + if (level2 == NULL) + { + if (value == NULL) + /* We don't have to do anything. The value would in any case + be NULL. We can save the memory allocation. */ + return 0; + + level2 + = (struct pthread_key_data *) calloc (PTHREAD_KEY_2NDLEVEL_SIZE, + sizeof (*level2)); + if (level2 == NULL) + return ENOMEM; + + THREAD_SETMEM_NC (self, specific, idx1st, level2); + } + + /* Pointer to the right array element. */ + level2 = &level2[idx2nd]; + + /* Remember that we stored at least one set of data. */ + THREAD_SETMEM (self, specific_used, true); + } + + /* Store the data and the sequence number so that we can recognize + stale data. */ + level2->seq = seq; + level2->data = (void *) value; + + return 0; +} +strong_alias (__pthread_setspecific, pthread_setspecific) +strong_alias (__pthread_setspecific, __pthread_setspecific_internal) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_setuid.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_setuid.c new file mode 100644 index 00000000..ff949c85 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_setuid.c @@ -0,0 +1,3 @@ +#define SINGLE_THREAD +#define __setuid pthread_setuid_np +#include diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_testcancel.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_testcancel.c new file mode 100644 index 00000000..e9b17b49 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_testcancel.c @@ -0,0 +1,28 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include "pthreadP.h" + + +void +pthread_testcancel (void) +{ + CANCELLATION_P (THREAD_SELF); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_timedjoin.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_timedjoin.c new file mode 100644 index 00000000..4098a737 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_timedjoin.c @@ -0,0 +1,107 @@ +/* Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include "pthreadP.h" + + +static void +cleanup (void *arg) +{ + *(void **) arg = NULL; +} + + +int +pthread_timedjoin_np ( + pthread_t threadid, + void **thread_return, + const struct timespec *abstime) +{ + struct pthread *self; + struct pthread *pd = (struct pthread *) threadid; + int result; + + /* Make sure the descriptor is valid. */ + if (INVALID_NOT_TERMINATED_TD_P (pd)) + /* Not a valid thread handle. */ + return ESRCH; + + /* Is the thread joinable?. */ + if (IS_DETACHED (pd)) + /* We cannot wait for the thread. */ + return EINVAL; + + self = THREAD_SELF; + if (pd == self || self->joinid == pd) + /* This is a deadlock situation. The threads are waiting for each + other to finish. Note that this is a "may" error. To be 100% + sure we catch this error we would have to lock the data + structures but it is not necessary. In the unlikely case that + two threads are really caught in this situation they will + deadlock. It is the programmer's problem to figure this + out. */ + return EDEADLK; + + /* Wait for the thread to finish. If it is already locked something + is wrong. There can only be one waiter. */ + if (__builtin_expect (atomic_compare_and_exchange_bool_acq (&pd->joinid, + self, NULL), 0)) + /* There is already somebody waiting for the thread. */ + return EINVAL; + + + /* During the wait we change to asynchronous cancellation. If we + are cancelled the thread we are waiting for must be marked as + un-wait-ed for again. */ + pthread_cleanup_push (cleanup, &pd->joinid); + + /* Switch to asynchronous cancellation. */ + int oldtype = CANCEL_ASYNC (); + + + /* Wait for the child. */ + result = lll_timedwait_tid (pd->tid, abstime); + + + /* Restore cancellation mode. */ + CANCEL_RESET (oldtype); + + /* Remove the handler. */ + pthread_cleanup_pop (0); + + + /* We might have timed out. */ + if (result == 0) + { + /* Store the return value if the caller is interested. */ + if (thread_return != NULL) + *thread_return = pd->result; + + + /* Free the TCB. */ + __free_tcb (pd); + } + else + pd->joinid = NULL; + + return result; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_tryjoin.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_tryjoin.c new file mode 100644 index 00000000..5746a9e9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/pthread_tryjoin.c @@ -0,0 +1,75 @@ +/* Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +#include +#include "pthreadP.h" + + +int +pthread_tryjoin_np ( + pthread_t threadid, + void **thread_return) +{ + struct pthread *self; + struct pthread *pd = (struct pthread *) threadid; + + /* Make sure the descriptor is valid. */ + if (DEBUGGING_P && __find_in_stack_list (pd) == NULL) + /* Not a valid thread handle. */ + return ESRCH; + + /* Is the thread joinable?. */ + if (IS_DETACHED (pd)) + /* We cannot wait for the thread. */ + return EINVAL; + + self = THREAD_SELF; + if (pd == self || self->joinid == pd) + /* This is a deadlock situation. The threads are waiting for each + other to finish. Note that this is a "may" error. To be 100% + sure we catch this error we would have to lock the data + structures but it is not necessary. In the unlikely case that + two threads are really caught in this situation they will + deadlock. It is the programmer's problem to figure this + out. */ + return EDEADLK; + + /* Return right away if the thread hasn't terminated yet. */ + if (pd->tid != 0) + return EBUSY; + + /* Wait for the thread to finish. If it is already locked something + is wrong. There can only be one waiter. */ + if (atomic_compare_and_exchange_bool_acq (&pd->joinid, self, NULL)) + /* There is already somebody waiting for the thread. */ + return EINVAL; + + /* Store the return value if the caller is interested. */ + if (thread_return != NULL) + *thread_return = pd->result; + + + /* Free the TCB. */ + __free_tcb (pd); + + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/res.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/res.c new file mode 100644 index 00000000..6a4d18b1 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/res.c @@ -0,0 +1,27 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +struct __res_state * +__res_state (void) +{ + return __resp; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sem_close.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sem_close.c new file mode 100644 index 00000000..dcf30f7b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sem_close.c @@ -0,0 +1,81 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include "semaphoreP.h" + + +/* Global variables to parametrize the walk function. This works + since we always have to use locks. And we have to use the twalk + function since the entries are not sorted wrt the mapping + address. */ +static sem_t *the_sem; +static struct inuse_sem *rec; + +static void +walker (const void *inodep, const VISIT which, const int depth) +{ + struct inuse_sem *nodep = *(struct inuse_sem **) inodep; + + if (nodep->sem == the_sem) + rec = nodep; +} + + +int +sem_close ( + sem_t *sem) +{ + int result = 0; + + /* Get the lock. */ + lll_lock (__sem_mappings_lock, LLL_PRIVATE); + + /* Locate the entry for the mapping the caller provided. */ + rec = NULL; + the_sem = sem; + twalk (__sem_mappings, walker); + if (rec != NULL) + { + /* Check the reference counter. If it is going to be zero, free + all the resources. */ + if (--rec->refcnt == 0) + { + /* Remove the record from the tree. */ + (void) tdelete (rec, &__sem_mappings, __sem_search); + + result = munmap (rec->sem, sizeof (sem_t)); + + free (rec); + } + } + else + { + /* This is no valid semaphore. */ + result = -1; + __set_errno (EINVAL); + } + + /* Release the lock. */ + lll_unlock (__sem_mappings_lock, LLL_PRIVATE); + + return result; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sem_destroy.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sem_destroy.c new file mode 100644 index 00000000..6362c0e3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sem_destroy.c @@ -0,0 +1,33 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include "semaphoreP.h" + + +int +__new_sem_destroy ( + sem_t *sem) +{ + /* XXX Check for valid parameter. */ + + /* Nothing to do. */ + return 0; +} +weak_alias(__new_sem_destroy, sem_destroy) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sem_getvalue.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sem_getvalue.c new file mode 100644 index 00000000..928026fc --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sem_getvalue.c @@ -0,0 +1,37 @@ +/* Copyright (C) 2002, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include "semaphoreP.h" + + +int +__new_sem_getvalue ( + sem_t *sem, + int *sval) +{ + struct new_sem *isem = (struct new_sem *) sem; + + /* XXX Check for valid SEM parameter. */ + + *sval = isem->value; + + return 0; +} +weak_alias(__new_sem_getvalue, sem_getvalue) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sem_init.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sem_init.c new file mode 100644 index 00000000..0a224f3a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sem_init.c @@ -0,0 +1,56 @@ +/* Copyright (C) 2002, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include "semaphoreP.h" +#include + + +int +__new_sem_init ( + sem_t *sem, + int pshared, + unsigned int value) +{ + /* Parameter sanity check. */ + if (__builtin_expect (value > SEM_VALUE_MAX, 0)) + { + __set_errno (EINVAL); + return -1; + } + + /* Map to the internal type. */ + struct new_sem *isem = (struct new_sem *) sem; + + /* Use the values the user provided. */ + isem->value = value; +#ifdef __ASSUME_PRIVATE_FUTEX + isem->private = pshared ? 0 : FUTEX_PRIVATE_FLAG; +#else + isem->private = pshared ? 0 : THREAD_GETMEM (THREAD_SELF, + header.private_futex); +#endif + + isem->nwaiters = 0; + + return 0; +} +weak_alias(__new_sem_init, sem_init) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sem_open.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sem_open.c new file mode 100644 index 00000000..71bebb00 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sem_open.c @@ -0,0 +1,397 @@ +/* Copyright (C) 2002, 2003, 2006, 2007, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "semaphoreP.h" +#include "../../libc/misc/internals/tempname.h" + + +/* Compatibility defines. */ +#define __endmntent endmntent +#define __fxstat64(vers, fd, buf) fstat64(fd, buf) +#define __getmntent_r getmntent_r +#define __setmntent setmntent +#define __statfs statfs +#define __libc_close close +#define __libc_open open +#define __libc_write write + + +/* Information about the mount point. */ +struct mountpoint_info mountpoint attribute_hidden; + +/* This is the default mount point. */ +static const char defaultmount[] = "/dev/shm"; +/* This is the default directory. */ +static const char defaultdir[] = "/dev/shm/sem."; + +/* Protect the `mountpoint' variable above. */ +pthread_once_t __namedsem_once attribute_hidden = PTHREAD_ONCE_INIT; + + +/* Determine where the shmfs is mounted (if at all). */ +void +attribute_hidden +__where_is_shmfs (void) +{ + char buf[512]; + struct statfs f; + struct mntent resmem; + struct mntent *mp; + FILE *fp; + + /* The canonical place is /dev/shm. This is at least what the + documentation tells everybody to do. */ + if (__statfs (defaultmount, &f) == 0 && f.f_type == SHMFS_SUPER_MAGIC) + { + /* It is in the normal place. */ + mountpoint.dir = (char *) defaultdir; + mountpoint.dirlen = sizeof (defaultdir) - 1; + + return; + } + + /* OK, do it the hard way. Look through the /proc/mounts file and if + this does not exist through /etc/fstab to find the mount point. */ + fp = __setmntent ("/proc/mounts", "r"); + if (__builtin_expect (fp == NULL, 0)) + { + fp = __setmntent (_PATH_MNTTAB, "r"); + if (__builtin_expect (fp == NULL, 0)) + /* There is nothing we can do. Blind guesses are not helpful. */ + return; + } + + /* Now read the entries. */ + while ((mp = __getmntent_r (fp, &resmem, buf, sizeof buf)) != NULL) + /* The original name is "shm" but this got changed in early Linux + 2.4.x to "tmpfs". */ + if (strcmp (mp->mnt_type, "tmpfs") == 0 + || strcmp (mp->mnt_type, "shm") == 0) + { + /* Found it. There might be more than one place where the + filesystem is mounted but one is enough for us. */ + size_t namelen; + + /* First make sure this really is the correct entry. At least + some versions of the kernel give wrong information because + of the implicit mount of the shmfs for SysV IPC. */ + if (__statfs (mp->mnt_dir, &f) != 0 || f.f_type != SHMFS_SUPER_MAGIC) + continue; + + namelen = strlen (mp->mnt_dir); + + if (namelen == 0) + /* Hum, maybe some crippled entry. Keep on searching. */ + continue; + + mountpoint.dir = (char *) malloc (namelen + 4 + 2); + if (mountpoint.dir != NULL) + { + char *cp = mempcpy (mountpoint.dir, mp->mnt_dir, namelen); + if (cp[-1] != '/') + *cp++ = '/'; + cp = stpcpy (cp, "sem."); + mountpoint.dirlen = cp - mountpoint.dir; + } + + break; + } + + /* Close the stream. */ + __endmntent (fp); +} + + +/* Comparison function for search of existing mapping. */ +int +attribute_hidden +__sem_search (const void *a, const void *b) +{ + const struct inuse_sem *as = (const struct inuse_sem *) a; + const struct inuse_sem *bs = (const struct inuse_sem *) b; + + if (as->ino != bs->ino) + /* Cannot return the difference the type is larger than int. */ + return as->ino < bs->ino ? -1 : (as->ino == bs->ino ? 0 : 1); + + if (as->dev != bs->dev) + /* Cannot return the difference the type is larger than int. */ + return as->dev < bs->dev ? -1 : (as->dev == bs->dev ? 0 : 1); + + return strcmp (as->name, bs->name); +} + + +/* The search tree for existing mappings. */ +void *__sem_mappings attribute_hidden; + +/* Lock to protect the search tree. */ +int __sem_mappings_lock attribute_hidden = LLL_LOCK_INITIALIZER; + + +/* Search for existing mapping and if possible add the one provided. */ +static sem_t * +check_add_mapping (const char *name, size_t namelen, int fd, sem_t *existing) +{ + sem_t *result = SEM_FAILED; + + /* Get the information about the file. */ +#ifdef __UCLIBC_HAS_LFS__ + struct stat64 st; + if (__fxstat64 (_STAT_VER, fd, &st) == 0) +#else + struct stat st; + if (fstat (fd, &st) == 0) +#endif + { + /* Get the lock. */ + lll_lock (__sem_mappings_lock, LLL_PRIVATE); + + /* Search for an existing mapping given the information we have. */ + struct inuse_sem *fake; + fake = (struct inuse_sem *) alloca (sizeof (*fake) + namelen); + memcpy (fake->name, name, namelen); + fake->dev = st.st_dev; + fake->ino = st.st_ino; + + struct inuse_sem **foundp = tfind (fake, &__sem_mappings, __sem_search); + if (foundp != NULL) + { + /* There is already a mapping. Use it. */ + result = (*foundp)->sem; + ++(*foundp)->refcnt; + } + else + { + /* We haven't found a mapping. Install ione. */ + struct inuse_sem *newp; + + newp = (struct inuse_sem *) malloc (sizeof (*newp) + namelen); + if (newp != NULL) + { + /* If the caller hasn't provided any map it now. */ + if (existing == SEM_FAILED) + existing = (sem_t *) mmap (NULL, sizeof (sem_t), + PROT_READ | PROT_WRITE, MAP_SHARED, + fd, 0); + + newp->dev = st.st_dev; + newp->ino = st.st_ino; + newp->refcnt = 1; + newp->sem = existing; + memcpy (newp->name, name, namelen); + + /* Insert the new value. */ + if (existing != MAP_FAILED + && tsearch (newp, &__sem_mappings, __sem_search) != NULL) + /* Successful. */ + result = existing; + else + /* Something went wrong while inserting the new + value. We fail completely. */ + free (newp); + } + } + + /* Release the lock. */ + lll_unlock (__sem_mappings_lock, LLL_PRIVATE); + } + + if (result != existing && existing != SEM_FAILED && existing != MAP_FAILED) + { + /* Do not disturb errno. */ + INTERNAL_SYSCALL_DECL (err); + INTERNAL_SYSCALL (munmap, err, 2, existing, sizeof (sem_t)); + } + + return result; +} + + +sem_t * +sem_open (const char *name, int oflag, ...) +{ + char *finalname; + sem_t *result = SEM_FAILED; + int fd; + + /* Determine where the shmfs is mounted. */ + INTUSE(__pthread_once) (&__namedsem_once, __where_is_shmfs); + + /* If we don't know the mount points there is nothing we can do. Ever. */ + if (mountpoint.dir == NULL) + { + __set_errno (ENOSYS); + return SEM_FAILED; + } + + /* Construct the filename. */ + while (name[0] == '/') + ++name; + + if (name[0] == '\0') + { + /* The name "/" is not supported. */ + __set_errno (EINVAL); + return SEM_FAILED; + } + size_t namelen = strlen (name) + 1; + + /* Create the name of the final file. */ + finalname = (char *) alloca (mountpoint.dirlen + namelen); + mempcpy (mempcpy (finalname, mountpoint.dir, mountpoint.dirlen), + name, namelen); + + /* If the semaphore object has to exist simply open it. */ + if ((oflag & O_CREAT) == 0 || (oflag & O_EXCL) == 0) + { + try_again: + fd = __libc_open (finalname, + (oflag & ~(O_CREAT|O_ACCMODE)) | O_NOFOLLOW | O_RDWR); + + if (fd == -1) + { + /* If we are supposed to create the file try this next. */ + if ((oflag & O_CREAT) != 0 && errno == ENOENT) + goto try_create; + + /* Return. errno is already set. */ + } + else + /* Check whether we already have this semaphore mapped and + create one if necessary. */ + result = check_add_mapping (name, namelen, fd, SEM_FAILED); + } + else + { + /* We have to open a temporary file first since it must have the + correct form before we can start using it. */ + char *tmpfname; + mode_t mode; + unsigned int value; + va_list ap; + + try_create: + va_start (ap, oflag); + + mode = va_arg (ap, mode_t); + value = va_arg (ap, unsigned int); + + va_end (ap); + + if (value > SEM_VALUE_MAX) + { + __set_errno (EINVAL); + return SEM_FAILED; + } + + /* Create the initial file content. */ + union + { + sem_t initsem; + struct new_sem newsem; + } sem; + + sem.newsem.value = value; + sem.newsem.private = 0; + sem.newsem.nwaiters = 0; + + /* Initialize the remaining bytes as well. */ + memset ((char *) &sem.initsem + sizeof (struct new_sem), '\0', + sizeof (sem_t) - sizeof (struct new_sem)); + + tmpfname = (char *) alloca (mountpoint.dirlen + 6 + 1); + mempcpy (mempcpy (tmpfname, mountpoint.dir, mountpoint.dirlen), + "XXXXXX", 7); + + fd = __gen_tempname (tmpfname, __GT_FILE, mode); + if (fd == -1) + return SEM_FAILED; + + if (TEMP_FAILURE_RETRY (__libc_write (fd, &sem.initsem, sizeof (sem_t))) + == sizeof (sem_t) + /* Map the sem_t structure from the file. */ + && (result = (sem_t *) mmap (NULL, sizeof (sem_t), + PROT_READ | PROT_WRITE, MAP_SHARED, + fd, 0)) != MAP_FAILED) + { + /* Create the file. Don't overwrite an existing file. */ + if (link (tmpfname, finalname) != 0) + { + /* Undo the mapping. */ + (void) munmap (result, sizeof (sem_t)); + + /* Reinitialize 'result'. */ + result = SEM_FAILED; + + /* This failed. If O_EXCL is not set and the problem was + that the file exists, try again. */ + if ((oflag & O_EXCL) == 0 && errno == EEXIST) + { + /* Remove the file. */ + (void) unlink (tmpfname); + + /* Close the file. */ + (void) __libc_close (fd); + + goto try_again; + } + } + else + /* Insert the mapping into the search tree. This also + determines whether another thread sneaked by and already + added such a mapping despite the fact that we created it. */ + result = check_add_mapping (name, namelen, fd, result); + } + + /* Now remove the temporary name. This should never fail. If + it fails we leak a file name. Better fix the kernel. */ + (void) unlink (tmpfname); + } + + /* Map the mmap error to the error we need. */ + if (MAP_FAILED != (void *) SEM_FAILED && result == MAP_FAILED) + result = SEM_FAILED; + + /* We don't need the file descriptor anymore. */ + if (fd != -1) + { + /* Do not disturb errno. */ + INTERNAL_SYSCALL_DECL (err); + INTERNAL_SYSCALL (close, err, 1, fd); + } + + return result; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sem_unlink.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sem_unlink.c new file mode 100644 index 00000000..f3e7f1a7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sem_unlink.c @@ -0,0 +1,67 @@ +/* Copyright (C) 2002, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include "semaphoreP.h" + + +int +sem_unlink ( + const char *name) +{ + char *fname; + size_t namelen; + + /* Determine where the shmfs is mounted. */ + INTUSE(__pthread_once) (&__namedsem_once, __where_is_shmfs); + + /* If we don't know the mount points there is nothing we can do. Ever. */ + if (mountpoint.dir == NULL) + { + __set_errno (ENOSYS); + return -1; + } + + /* Construct the filename. */ + while (name[0] == '/') + ++name; + + if (name[0] == '\0') + { + /* The name "/" is not supported. */ + __set_errno (ENOENT); + return -1; + } + namelen = strlen (name); + + /* Create the name of the file. */ + fname = (char *) alloca (mountpoint.dirlen + namelen + 1); + mempcpy (mempcpy (fname, mountpoint.dir, mountpoint.dirlen), + name, namelen + 1); + + /* Now try removing it. */ + int ret = unlink (fname); + if (ret < 0 && errno == EPERM) + __set_errno (EACCES); + return ret; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/semaphore.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/semaphore.h new file mode 100644 index 00000000..4f13725b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/semaphore.h @@ -0,0 +1,79 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SEMAPHORE_H +#define _SEMAPHORE_H 1 + +#include +#include +#ifdef __USE_XOPEN2K +# define __need_timespec +# include +#endif + +/* Get the definition for sem_t. */ +#include + + +__BEGIN_DECLS + +/* Initialize semaphore object SEM to VALUE. If PSHARED then share it + with other processes. */ +extern int sem_init (sem_t *__sem, int __pshared, unsigned int __value) + __THROW; +/* Free resources associated with semaphore object SEM. */ +extern int sem_destroy (sem_t *__sem) __THROW; + +/* Open a named semaphore NAME with open flags OFLAG. */ +extern sem_t *sem_open (__const char *__name, int __oflag, ...) __THROW; + +/* Close descriptor for named semaphore SEM. */ +extern int sem_close (sem_t *__sem) __THROW; + +/* Remove named semaphore NAME. */ +extern int sem_unlink (__const char *__name) __THROW; + +/* Wait for SEM being posted. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern int sem_wait (sem_t *__sem); + +#ifdef __USE_XOPEN2K +/* Similar to `sem_wait' but wait only until ABSTIME. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern int sem_timedwait (sem_t *__restrict __sem, + __const struct timespec *__restrict __abstime); +#endif + +/* Test whether SEM is posted. */ +extern int sem_trywait (sem_t *__sem) __THROW; + +/* Post SEM. */ +extern int sem_post (sem_t *__sem) __THROW; + +/* Get current value of SEM and store it in *SVAL. */ +extern int sem_getvalue (sem_t *__restrict __sem, int *__restrict __sval) + __THROW; + + +__END_DECLS + +#endif /* semaphore.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/semaphoreP.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/semaphoreP.h new file mode 100644 index 00000000..7d6fd252 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/semaphoreP.h @@ -0,0 +1,69 @@ +/* Copyright (C) 2002, 2003, 2006, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include "pthreadP.h" + + +/* Mount point of the shared memory filesystem. */ +struct mountpoint_info +{ + char *dir; + size_t dirlen; +}; + +/* Keeping track of currently used mappings. */ +struct inuse_sem +{ + dev_t dev; + ino_t ino; + int refcnt; + sem_t *sem; + char name[0]; +}; + + +/* Variables used in multiple interfaces. */ +extern struct mountpoint_info mountpoint attribute_hidden; + +extern pthread_once_t __namedsem_once attribute_hidden; + +/* The search tree for existing mappings. */ +extern void *__sem_mappings attribute_hidden; + +/* Lock to protect the search tree. */ +extern int __sem_mappings_lock attribute_hidden; + + +/* Initializer for mountpoint. */ +extern void __where_is_shmfs (void) attribute_hidden; + +/* Comparison function for search in tree with existing mappings. */ +extern int __sem_search (const void *a, const void *b) attribute_hidden; + + +/* Prototypes of functions with multiple interfaces. */ +extern int __new_sem_init (sem_t *sem, int pshared, unsigned int value); +extern int __old_sem_init (sem_t *sem, int pshared, unsigned int value); +extern int __new_sem_destroy (sem_t *sem); +extern int __new_sem_post (sem_t *sem); +extern int __new_sem_wait (sem_t *sem); +extern int __old_sem_wait (sem_t *sem); +extern int __new_sem_trywait (sem_t *sem); +extern int __new_sem_getvalue (sem_t *sem, int *sval); diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/Makefile new file mode 100644 index 00000000..4a8f4a07 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../ +top_builddir=../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/Makefile.commonarch b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/Makefile.commonarch new file mode 100644 index 00000000..0c192169 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/Makefile.commonarch @@ -0,0 +1,69 @@ +# Makefile template to be included by libpthread/nptl/sysdeps//Makefile.arch +# +# Copyright (C) 2010 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# +subdirs += libpthread/nptl/sysdeps/$(TARGET_ARCH) +libpthread_arch_DIR := $(top_srcdir)libpthread/nptl/sysdeps/$(TARGET_ARCH) +libpthread_arch_OUT := $(top_builddir)libpthread/nptl/sysdeps/$(TARGET_ARCH) + +ifneq ($(abspath libpthread/nptl/sysdeps/$(TARGET_ARCH)),$(abspath libpthread/nptl/sysdeps/$(TARGET_ARCH)/$(TARGET_SUBARCH))) +subdirs += libpthread/nptl/sysdeps/$(TARGET_ARCH)/$(TARGET_SUBARCH) +libpthread_subarch_DIR := $(libpthread_arch_DIR)/$(TARGET_SUBARCH) +libpthread_subarch_OUT := $(libpthread_arch_OUT)/$(TARGET_SUBARCH) +endif + +-include $(libpthread_arch_DIR)/Makefile.arch +libpthread_arch_SSRC := $(filter-out librt-%,$(filter-out libc-%,$(notdir $(wildcard $(libpthread_arch_DIR)/*.S)))) +libpthread_arch_CSRC := $(filter-out librt-%,$(filter-out libc-%,$(notdir $(wildcard $(libpthread_arch_DIR)/*.c)))) +libpthread_arch_CSRC := $(filter-out gen_%,$(libpthread_arch_CSRC)) + +ifneq ($(TARGET_SUBARCH),) +libpthread_subarch_SSRC := $(notdir $(wildcard $(libpthread_subarch_DIR)/*.S)) +libpthread_arch_SSRC := $(filter-out $(libpthread_subarch_SSRC),$(libpthread_arch_SSRC)) +libpthread_arch_CSRC := $(filter-out $(libpthread_subarch_SSRC:.S=.c),$(libpthread_arch_CSRC)) +libpthread_subarch_OBJS := $(patsubst %.S,$(libpthread_subarch_OUT)/%.o,$(libpthread_subarch_SSRC)) +endif + +libpthread_arch_COBJ = $(patsubst %.c,$(libpthread_arch_OUT)/%.o,$(libpthread_arch_CSRC)) +libpthread_arch_SOBJ = $(patsubst %.S,$(libpthread_arch_OUT)/%.o,$(libpthread_arch_SSRC)) +libpthread_arch_OBJS = $(libpthread_subarch_OBJS) $(libpthread_arch_COBJ) $(libpthread_arch_SOBJ) + +libc_arch_COBJ = $(patsubst %.c,$(libpthread_arch_OUT)/%.o,$(libc_arch_CSRC)) +libc_arch_SOBJ = $(patsubst %.c,$(libpthread_arch_OUT)/%.o,$(libc_arch_SSRC)) +libc_arch_OBJS = $(libc_arch_COBJ) $(libc_arch_SOBJ) +libc_arch_a_COBJ = $(patsubst %.c,$(libpthread_arch_OUT)/%.o,$(libc_arch_a_CSRC)) +libc_arch_a_OBJS = $(libc_arch_a_COBJ) + +librt_arch_COBJ = $(patsubst %.c,$(libpthread_arch_OUT)/%.o,$(librt_arch_CSRC)) +librt_arch_SOBJ = $(patsubst %.S,$(libpthread_arch_OUT)/%.o,$(librt_arch_SSRC)) +librt_arch_OBJS = $(librt_arch_COBJ) $(librt_arch_SOBJ) + +CFLAGS-gen_tcb-offsets.c = -S +$(libpthread_arch_OUT)/gen_tcb-offsets.c: $(libpthread_arch_DIR)/tcb-offsets.sym | $(libpthread_arch_OUT) + $(do_awk) $(top_srcdir)extra/scripts/gen-as-const.awk $< > $@ + +$(libpthread_arch_OUT)/gen_tcb-offsets.s: $(libpthread_arch_OUT)/gen_tcb-offsets.c | headers + $(compile.c) +libpthread-generated-y += $(libpthread_arch_OUT)/gen_tcb-offsets.s +PTHREAD_TCB_OFFSET_MANGLE ?= -n "s/^.*@@@name@@@\([^@]*\)@@@value@@@[^0-9Xxa-fA-F-]*\([0-9Xxa-fA-F-][0-9Xxa-fA-F-]*\).*@@@end@@@.*\$$/\#define \1 \2/p" +$(libpthread_arch_OUT)/tcb-offsets.h: $(libpthread_arch_OUT)/gen_tcb-offsets.s + $(do_sed) $(PTHREAD_TCB_OFFSET_MANGLE) $< > $@ + @if test ! -s $@ ; then rm -f $@ ; false ; fi + +pregen-headers-$(UCLIBC_HAS_THREADS_NATIVE) += $(libpthread_arch_OUT)/tcb-offsets.h + +objclean-y += CLEAN_$(subst $(top_builddir),,$(libpthread_arch_OUT)) +headers_clean-y+= HEADERCLEAN_$(subst $(top_builddir),,$(libpthread_arch_OUT)) + +CLEAN_$(subst $(top_builddir),,$(libpthread_arch_OUT)): + $(do_rm) $(addprefix $(libpthread_arch_OUT)/*., o os oS) +HEADERCLEAN_$(subst $(top_builddir),,$(libpthread_arch_OUT)): + $(do_rm) $(libpthread_arch_OUT)/tcb-offsets.h \ + $(addprefix $(libpthread_arch_OUT)/gen_tcb-offsets., c h s) +ifneq ($(TARGET_SUBARCH),) +objclean-y += CLEAN_$(subst $(top_builddir),,$(libpthread_subarch_OUT)) +CLEAN_$(subst $(top_builddir),,$(libpthread_subarch_OUT)): + $(do_rm) $(addprefix $(libpthread_subarch_OUT)/*., o os oS) +endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/Makefile.in new file mode 100644 index 00000000..5296f4a7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/Makefile.in @@ -0,0 +1,29 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +subdirs += libpthread/nptl/sysdeps + +define arch_and_subarch + $(addprefix $(1)/,$(notdir $(2))) $(if $(TARGET_SUBARCH),$(addprefix $(1)/$(TARGET_SUBARCH)/,$(notdir $(2)))) +endef +define base_and_arch_and_subarch + $(addprefix $(1)/,$(notdir $(2))) $(addprefix $(1)/$(TARGET_ARCH)/,$(notdir $(2))) $(if $(TARGET_SUBARCH),$(addprefix $(1)/$(TARGET_ARCH)/$(TARGET_SUBARCH)/,$(notdir $(2)))) +endef + +include $(libpthread_DIR)/sysdeps/unix/sysv/linux/Makefile.commonarch +include $(libpthread_DIR)/sysdeps/generic/Makefile.in +include $(libpthread_DIR)/sysdeps/Makefile.commonarch +libpthread_generic_libc_a_CSRC := $(filter-out $(notdir $(libc_arch_a_OBJS:.o=.c)),$(libpthread_generic_libc_a_CSRC)) +libpthread_arch_OBJS := $(filter-out $(call base_and_arch_and_subarch,$(libpthread_arch_OUT),$(libpthread_linux_OBJS)),$(libpthread_arch_OBJS)) +include $(libpthread_DIR)/sysdeps/pthread/Makefile.in +libpthread_pthread_CSRC := $(filter-out $(notdir $(libpthread_linux_OBJS:.o=.c) $(libpthread_arch_OBJS:.o=.c)),$(libpthread_pthread_CSRC)) +libpthread-so-y := $(filter-out $(call base_and_arch_and_subarch,$(libpthread_pthread_OUT),$(libpthread_linux_OBJS) $(libpthread_arch_OBJS)),$(libpthread-so-y)) + +libpthread_OBJS := $(libpthread_linux_OBJS) $(libpthread_arch_OBJS) $(libpthread_pthread_COBJ) +libpthread_libc_OBJS = $(libc_linux_OBJS) $(libc_arch_OBJS) +libpthread_libc_a_OBJS = $(libc_arch_a_OBJS) $(libpthread_generic_libc_a_OBJS) +libpthread_librt_OBJS = $(librt_linux_OBJS) $(librt_arch_OBJS) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/alpha/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/alpha/Makefile new file mode 100644 index 00000000..88c106bb --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/alpha/Makefile @@ -0,0 +1,21 @@ +# Copyright (C) 2003 Free Software Foundation, Inc. +# This file is part of the GNU C Library. +# +# The GNU C Library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# The GNU C Library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with the GNU C Library; if not, write to the Free +# Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +# 02111-1307 USA. + +ifeq ($(subdir),csu) +gen-as-const-headers += tcb-offsets.sym +endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/alpha/dl-tls.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/alpha/dl-tls.h new file mode 100644 index 00000000..f81f95d7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/alpha/dl-tls.h @@ -0,0 +1,29 @@ +/* Thread-local storage handling in the ELF dynamic linker. Alpha version. + Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + + +/* Type used for the representation of TLS information in the GOT. */ +typedef struct +{ + unsigned long int ti_module; + unsigned long int ti_offset; +} tls_index; + + +extern void *__tls_get_addr (tls_index *ti); diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/alpha/elf/pt-initfini.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/alpha/elf/pt-initfini.c new file mode 100644 index 00000000..ba2e419d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/alpha/elf/pt-initfini.c @@ -0,0 +1,89 @@ +/* Special .init and .fini section support for Alpha. NPTL version. + Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This file is compiled into assembly code which is then munged by a sed + script into two files: crti.s and crtn.s. + + * crti.s puts a function prologue at the beginning of the .init and .fini + sections and defines global symbols for those addresses, so they can be + called as functions. + + * crtn.s puts the corresponding function epilogues in the .init and .fini + sections. + + This differs from what would be generated by the generic code in that + we save and restore the GP within the function. In order for linker + relaxation to work, the value in the GP register on exit from a function + must be valid for the function entry point. Normally, a function is + contained within one object file and this is not an issue, provided + that the function reloads the gp after making any function calls. + However, _init and _fini are constructed from pieces of many object + files, all of which may have different GP values. So we must reload + the GP value from crti.o in crtn.o. */ + +__asm__ (" \n\ +#include \"defs.h\" \n\ + \n\ +/*@HEADER_ENDS*/ \n\ + \n\ +/*@_init_PROLOG_BEGINS*/ \n\ + .section .init, \"ax\", @progbits \n\ + .globl _init \n\ + .type _init,@function \n\ + .usepv _init,std \n\ +_init: \n\ + ldgp $29, 0($27) \n\ + subq $30, 16, $30 \n\ + stq $26, 0($30) \n\ + stq $29, 8($30) \n\ + bsr $26, __pthread_initialize_minimal_internal !samegp \n\ + .align 3 \n\ +/*@_init_PROLOG_ENDS*/ \n\ + \n\ +/*@_init_EPILOG_BEGINS*/ \n\ + .section .init, \"ax\", @progbits \n\ + ldq $26, 0($30) \n\ + ldq $29, 8($30) \n\ + addq $30, 16, $30 \n\ + ret \n\ +/*@_init_EPILOG_ENDS*/ \n\ + \n\ +/*@_fini_PROLOG_BEGINS*/ \n\ + .section .fini, \"ax\", @progbits \n\ + .globl _fini \n\ + .type _fini,@function \n\ + .usepv _fini,std \n\ +_fini: \n\ + ldgp $29, 0($27) \n\ + subq $30, 16, $30 \n\ + stq $26, 0($30) \n\ + stq $29, 8($30) \n\ + .align 3 \n\ +/*@_fini_PROLOG_ENDS*/ \n\ + \n\ +/*@_fini_EPILOG_BEGINS*/ \n\ + .section .fini, \"ax\", @progbits \n\ + ldq $26, 0($30) \n\ + ldq $29, 8($30) \n\ + addq $30, 16, $30 \n\ + ret \n\ +/*@_fini_EPILOG_ENDS*/ \n\ + \n\ +/*@TRAILER_BEGINS*/ \n\ +"); diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/alpha/jmpbuf-unwind.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/alpha/jmpbuf-unwind.h new file mode 100644 index 00000000..5cef8b1c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/alpha/jmpbuf-unwind.h @@ -0,0 +1,31 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +#define _JMPBUF_CFA_UNWINDS_ADJ(_jmpbuf, _context, _adj) \ + _JMPBUF_UNWINDS_ADJ (_jmpbuf, (void *) _Unwind_GetCFA (_context), _adj) + +#define _JMPBUF_UNWINDS_ADJ(_jmpbuf, _address, _adj) \ + ((uintptr_t) (_address) - (_adj) < (uintptr_t) (_jmpbuf)[JB_SP] - (_adj)) + +/* We use the normal lobngjmp for unwinding. */ +#define __libc_unwind_longjmp(buf, val) __libc_longjmp (buf, val) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/alpha/libc-tls.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/alpha/libc-tls.c new file mode 100644 index 00000000..a3b68e92 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/alpha/libc-tls.c @@ -0,0 +1,37 @@ +/* Thread-local storage handling in the ELF dynamic linker. Alpha version. + Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +#if USE_TLS + +/* On Alpha, linker optimizations are not required, so __tls_get_addr + can be called even in statically linked binaries. In this case module + must be always 1 and PT_TLS segment exist in the binary, otherwise it + would not link. */ + +void * +__tls_get_addr (tls_index *ti) +{ + dtv_t *dtv = THREAD_DTV (); + return (char *) dtv[1].pointer.val + ti->ti_offset; +} + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/alpha/pthread_spin_lock.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/alpha/pthread_spin_lock.S new file mode 100644 index 00000000..ce6cd41a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/alpha/pthread_spin_lock.S @@ -0,0 +1,45 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + + + .text + .align 4 + + .globl pthread_spin_lock + .ent pthread_spin_lock +pthread_spin_lock: + .frame $sp, 0, $26, 0 + .prologue 0 + +0: ldl_l $1, 0($16) + lda $2, 1 + lda $0, 0 + bne $1, 1f + + stl_c $2, 0($16) + beq $2, 1f + mb + ret + +1: ldl $1, 0($16) + bne $1, 1b + unop + br 0b + + .end pthread_spin_lock diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/alpha/pthread_spin_trylock.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/alpha/pthread_spin_trylock.S new file mode 100644 index 00000000..0948da69 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/alpha/pthread_spin_trylock.S @@ -0,0 +1,46 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + + +#define _ERRNO_H 1 +#include + + .text + .align 4 + + .globl pthread_spin_trylock + .ent pthread_spin_trylock +pthread_spin_trylock: + .frame $sp, 0, $26, 0 + .prologue 0 + +0: ldl_l $1, 0($16) + lda $2, 1 + lda $0, EBUSY + bne $1, 1f + + stl_c $2, 0($16) + beq $2, 2f + mb + lda $0, 0 + +1: ret +2: br 0b + + .end pthread_spin_trylock diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/alpha/pthreaddef.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/alpha/pthreaddef.h new file mode 100644 index 00000000..26c4daf7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/alpha/pthreaddef.h @@ -0,0 +1,38 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Default stack size. */ +#define ARCH_STACK_DEFAULT_SIZE (4 * 1024 * 1024) + +/* Required stack pointer alignment at beginning. The ABI requires 16. */ +#define STACK_ALIGN 16 + +/* Minimal stack size after allocating thread descriptor and guard size. */ +#define MINIMAL_REST_STACK 4096 + +/* Alignment requirement for TCB. */ +#define TCB_ALIGNMENT 16 + +/* Location of current stack frame. */ +#define CURRENT_STACK_FRAME __builtin_frame_address (0) + +/* XXX Until we have a better place keep the definitions here. */ + +/* While there is no such syscall. */ +#define __exit_thread_inline(val) \ + INLINE_SYSCALL (exit, 1, (val)) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/alpha/tcb-offsets.sym b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/alpha/tcb-offsets.sym new file mode 100644 index 00000000..c21a7910 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/alpha/tcb-offsets.sym @@ -0,0 +1,14 @@ +#include +#include + +-- + +-- Abuse tls.h macros to derive offsets relative to the thread register. +-- # define __builtin_thread_pointer() ((void *) 0) +-- # define thread_offsetof(mem) ((void *) &THREAD_SELF->mem - (void *) 0) +-- Ho hum, this doesn't work in gcc4, so Know Things about THREAD_SELF +#define thread_offsetof(mem) (long)(offsetof(struct pthread, mem) - sizeof(struct pthread)) + +MULTIPLE_THREADS_OFFSET thread_offsetof (header.multiple_threads) +PID_OFFSET thread_offsetof (pid) +TID_OFFSET thread_offsetof (tid) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/alpha/tls.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/alpha/tls.h new file mode 100644 index 00000000..99cd27a0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/alpha/tls.h @@ -0,0 +1,127 @@ +/* Definition for thread-local data handling. NPTL/Alpha version. + Copyright (C) 2003, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _TLS_H +#define _TLS_H 1 + +#ifndef __ASSEMBLER__ +# include +# include +# include + +/* Type for the dtv. */ +typedef union dtv +{ + size_t counter; + struct + { + void *val; + bool is_static; + } pointer; +} dtv_t; + +#else /* __ASSEMBLER__ */ +# include +#endif /* __ASSEMBLER__ */ + + +/* We require TLS support in the tools. */ +#ifndef HAVE_TLS_SUPPORT +# error "TLS support is required." +#endif + +/* Signal that TLS support is available. */ +# define USE_TLS 1 + +#ifndef __ASSEMBLER__ + +/* Get system call information. */ +# include + +/* The TP points to the start of the thread blocks. */ +# define TLS_DTV_AT_TP 1 + +/* Get the thread descriptor definition. */ +# include + +typedef struct +{ + dtv_t *dtv; + void *private; +} tcbhead_t; + +/* This is the size of the initial TCB. */ +# define TLS_INIT_TCB_SIZE sizeof (tcbhead_t) + +/* Alignment requirements for the initial TCB. */ +# define TLS_INIT_TCB_ALIGN 16 + +/* This is the size of the TCB. */ +# define TLS_TCB_SIZE sizeof (tcbhead_t) + +/* This is the size we need before TCB. */ +# define TLS_PRE_TCB_SIZE sizeof (struct pthread) + +/* Alignment requirements for the TCB. */ +# define TLS_TCB_ALIGN 16 + +/* Install the dtv pointer. The pointer passed is to the element with + index -1 which contain the length. */ +# define INSTALL_DTV(tcbp, dtvp) \ + (((tcbhead_t *) (tcbp))->dtv = (dtvp) + 1) + +/* Install new dtv for current thread. */ +# define INSTALL_NEW_DTV(dtv) \ + (THREAD_DTV() = (dtv)) + +/* Return dtv of given thread descriptor. */ +# define GET_DTV(tcbp) \ + (((tcbhead_t *) (tcbp))->dtv) + +/* Code to initially initialize the thread pointer. This might need + special attention since 'errno' is not yet available and if the + operation can cause a failure 'errno' must not be touched. */ +# define TLS_INIT_TP(tcbp, secondcall) \ + (__builtin_set_thread_pointer ((void *)(tcbp)), NULL) + +/* Return the address of the dtv for the current thread. */ +# define THREAD_DTV() \ + (((tcbhead_t *) __builtin_thread_pointer ())->dtv) + +/* Return the thread descriptor for the current thread. */ +# define THREAD_SELF \ + ((struct pthread *)__builtin_thread_pointer () - 1) + +/* Magic for libthread_db to know how to do THREAD_SELF. */ +# define DB_THREAD_SELF \ + REGISTER (64, 64, 32 * 8, -sizeof (struct pthread)) + +/* Access to data in the thread descriptor is easy. */ +#define THREAD_GETMEM(descr, member) \ + descr->member +#define THREAD_GETMEM_NC(descr, member, idx) \ + descr->member[idx] +#define THREAD_SETMEM(descr, member, value) \ + descr->member = (value) +#define THREAD_SETMEM_NC(descr, member, idx, value) \ + descr->member[idx] = (value) + +#endif /* __ASSEMBLER__ */ + +#endif /* tls.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/arm/Makefile.arch b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/arm/Makefile.arch new file mode 100644 index 00000000..a8bc1aad --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/arm/Makefile.arch @@ -0,0 +1,17 @@ +# Makefile for uClibc NPTL +# +# Copyright (C) 2005 Steven J. Hill +# Portions Copyright (C) 2006 CodeSourcery +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +librt_arch_SSRC = aeabi_read_tp.S thumb_atomics.S +librt_arch_CSRC = aeabi_unwind_cpp_pr1.c + +CFLAGS-pt-raise.c = -DNOT_IN_libc -DIS_IN_libpthread + +ASFLAGS-pthread_spin_lock.S = -DNOT_IN_libc -DIS_IN_libpthread +ASFLAGS-pthread_spin_trylock.S = -DNOT_IN_libc -DIS_IN_libpthread +ASFLAGS-aeabi_read_tp.S = -DNOT_IN_libc=1 + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/arm/aeabi_read_tp.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/arm/aeabi_read_tp.S new file mode 100644 index 00000000..af640d62 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/arm/aeabi_read_tp.S @@ -0,0 +1 @@ +#include <../../../../ldso/ldso/arm/aeabi_read_tp.S> diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/arm/aeabi_unwind_cpp_pr1.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/arm/aeabi_unwind_cpp_pr1.c new file mode 100644 index 00000000..84683627 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/arm/aeabi_unwind_cpp_pr1.c @@ -0,0 +1 @@ +#include <../../../../libc/sysdeps/linux/arm/aeabi_unwind_cpp_pr1.c> diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/arm/dl-tls.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/arm/dl-tls.h new file mode 100644 index 00000000..e0324a7b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/arm/dl-tls.h @@ -0,0 +1,29 @@ +/* Thread-local storage handling in the ELF dynamic linker. ARM version. + Copyright (C) 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + + +/* Type used for the representation of TLS information in the GOT. */ +typedef struct +{ + unsigned long int ti_module; + unsigned long int ti_offset; +} tls_index; + + +extern void *__tls_get_addr (tls_index *ti); diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/arm/jmpbuf-unwind.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/arm/jmpbuf-unwind.h new file mode 100644 index 00000000..6e8f01d1 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/arm/jmpbuf-unwind.h @@ -0,0 +1,36 @@ +/* Copyright (C) 2005,2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +/* Test if longjmp to JMPBUF would unwind the frame + containing a local variable at ADDRESS. */ +#undef _JMPBUF_UNWINDS +#define _JMPBUF_UNWINDS(jmpbuf, address, demangle) \ + ((void *) (address) < (void *) demangle (jmpbuf[__JMP_BUF_SP])) + +#define _JMPBUF_CFA_UNWINDS_ADJ(_jmpbuf, _context, _adj) \ + _JMPBUF_UNWINDS_ADJ (_jmpbuf, (void *) _Unwind_GetCFA (_context), _adj) + +#define _JMPBUF_UNWINDS_ADJ(_jmpbuf, _address, _adj) \ + ((uintptr_t) (_address) - (_adj) < (uintptr_t) (_jmpbuf)[__JMP_BUF_SP] - (_adj)) + +/* We use the normal longjmp for unwinding. */ +#define __libc_unwind_longjmp(buf, val) longjmp (buf, val) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/arm/pthread_spin_lock.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/arm/pthread_spin_lock.S new file mode 100644 index 00000000..bd6adf79 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/arm/pthread_spin_lock.S @@ -0,0 +1,31 @@ +/* Copyright (C) 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + + .text + .align 4 + +ENTRY (pthread_spin_lock) + mov r1, #1 +1: swp r2, r1, [r0] + teq r2, #0 + bne 1b + mov r0, #0 + PSEUDO_RET_NOERRNO +END (pthread_spin_lock) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/arm/pthread_spin_trylock.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/arm/pthread_spin_trylock.S new file mode 100644 index 00000000..85931507 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/arm/pthread_spin_trylock.S @@ -0,0 +1,34 @@ +/* Copyright (C) 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define _ERRNO_H 1 +#include + +#include + + .text + .align 4 + +ENTRY (pthread_spin_trylock) + mov r1, #1 + swp r2, r1, [r0] + teq r2, #0 + moveq r0, #0 + movne r0, #EBUSY + PSEUDO_RET_NOERRNO +END (pthread_spin_trylock) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/arm/pthreaddef.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/arm/pthreaddef.h new file mode 100644 index 00000000..783828a4 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/arm/pthreaddef.h @@ -0,0 +1,39 @@ +/* Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Default stack size. */ +#define ARCH_STACK_DEFAULT_SIZE (2 * 1024 * 1024) + +/* Required stack pointer alignment at beginning. SSE requires 16 + bytes. */ +#define STACK_ALIGN 16 + +/* Minimal stack size after allocating thread descriptor and guard size. */ +#define MINIMAL_REST_STACK 2048 + +/* Alignment requirement for TCB. */ +#define TCB_ALIGNMENT 16 + + +/* Location of current stack frame. */ +#define CURRENT_STACK_FRAME __builtin_frame_address (0) + + +/* XXX Until we have a better place keep the definitions here. */ +#define __exit_thread_inline(val) \ + INLINE_SYSCALL (exit, 1, (val)) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/arm/tcb-offsets.sym b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/arm/tcb-offsets.sym new file mode 100644 index 00000000..92cc441d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/arm/tcb-offsets.sym @@ -0,0 +1,11 @@ +#include +#include + +-- + +-- Derive offsets relative to the thread register. +#define thread_offsetof(mem) (long)(offsetof(struct pthread, mem) - sizeof(struct pthread)) + +MULTIPLE_THREADS_OFFSET thread_offsetof (header.multiple_threads) +PID_OFFSET thread_offsetof (pid) +TID_OFFSET thread_offsetof (tid) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/arm/thumb_atomics.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/arm/thumb_atomics.S new file mode 100644 index 00000000..aaa7a3d8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/arm/thumb_atomics.S @@ -0,0 +1 @@ +#include <../../../../ldso/ldso/arm/thumb_atomics.S> diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/arm/tls.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/arm/tls.h new file mode 100644 index 00000000..0ca597ac --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/arm/tls.h @@ -0,0 +1,159 @@ +/* Definition for thread-local data handling. NPTL/ARM version. + Copyright (C) 2005,2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _TLS_H +#define _TLS_H 1 + +#ifndef __ASSEMBLER__ + +# include +# include +# include + +/* Type for the dtv. */ +typedef union dtv +{ + size_t counter; + struct + { + void *val; + bool is_static; + } pointer; +} dtv_t; + +#else /* __ASSEMBLER__ */ +# include +#endif /* __ASSEMBLER__ */ + + +/* We require TLS support in the tools. */ +#define HAVE_TLS_SUPPORT 1 +#define HAVE_TLS_MODEL_ATTRIBUTE 1 +#define HAVE___THREAD 1 + +/* Signal that TLS support is available. */ +#define USE_TLS 1 + +#ifndef __ASSEMBLER__ + +/* Get system call information. */ +# include + +/* The TP points to the start of the thread blocks. */ +# define TLS_DTV_AT_TP 1 + +/* Get the thread descriptor definition. */ +# include <../../descr.h> + +typedef struct +{ + dtv_t *dtv; + void *private; +} tcbhead_t; + +/* This is the size of the initial TCB. */ +# define TLS_INIT_TCB_SIZE sizeof (tcbhead_t) + +/* Alignment requirements for the initial TCB. */ +# define TLS_INIT_TCB_ALIGN 16 + +/* This is the size of the TCB. */ +# define TLS_TCB_SIZE sizeof (tcbhead_t) + +/* This is the size we need before TCB. */ +# define TLS_PRE_TCB_SIZE sizeof (struct pthread) + +/* Alignment requirements for the TCB. */ +# define TLS_TCB_ALIGN 16 + +/* Install the dtv pointer. The pointer passed is to the element with + index -1 which contain the length. */ +# define INSTALL_DTV(tcbp, dtvp) \ + (((tcbhead_t *) (tcbp))->dtv = (dtvp) + 1) + +/* Install new dtv for current thread. */ +# define INSTALL_NEW_DTV(dtv) \ + (THREAD_DTV() = (dtv)) + +/* Return dtv of given thread descriptor. */ +# define GET_DTV(tcbp) \ + (((tcbhead_t *) (tcbp))->dtv) + +/* Code to initially initialize the thread pointer. This might need + special attention since 'errno' is not yet available and if the + operation can cause a failure 'errno' must not be touched. */ +# define TLS_INIT_TP(tcbp, secondcall) \ + ({ INTERNAL_SYSCALL_DECL (err); \ + long result_var; \ + result_var = INTERNAL_SYSCALL_ARM (set_tls, err, 1, (tcbp)); \ + INTERNAL_SYSCALL_ERROR_P (result_var, err) \ + ? "unknown error" : NULL; }) + +/* Return the address of the dtv for the current thread. */ +# define THREAD_DTV() \ + (((tcbhead_t *) __builtin_thread_pointer ())->dtv) + +/* Return the thread descriptor for the current thread. */ +# define THREAD_SELF \ + ((struct pthread *)__builtin_thread_pointer () - 1) + +/* Magic for libthread_db to know how to do THREAD_SELF. */ +# define DB_THREAD_SELF \ + CONST_THREAD_AREA (32, sizeof (struct pthread)) + +/* Access to data in the thread descriptor is easy. */ +#define THREAD_GETMEM(descr, member) \ + descr->member +#define THREAD_GETMEM_NC(descr, member, idx) \ + descr->member[idx] +#define THREAD_SETMEM(descr, member, value) \ + descr->member = (value) +#define THREAD_SETMEM_NC(descr, member, idx, value) \ + descr->member[idx] = (value) + +/* Initializing the thread pointer will generate a SIGILL if the syscall + is not available. */ +#define TLS_INIT_TP_EXPENSIVE 1 + +/* Get and set the global scope generation counter in struct pthread. */ +#define THREAD_GSCOPE_FLAG_UNUSED 0 +#define THREAD_GSCOPE_FLAG_USED 1 +#define THREAD_GSCOPE_FLAG_WAIT 2 +#define THREAD_GSCOPE_RESET_FLAG() \ + do \ + { int __res \ + = atomic_exchange_rel (&THREAD_SELF->header.gscope_flag, \ + THREAD_GSCOPE_FLAG_UNUSED); \ + if (__res == THREAD_GSCOPE_FLAG_WAIT) \ + lll_futex_wake (&THREAD_SELF->header.gscope_flag, 1, LLL_PRIVATE); \ + } \ + while (0) +#define THREAD_GSCOPE_SET_FLAG() \ + do \ + { \ + THREAD_SELF->header.gscope_flag = THREAD_GSCOPE_FLAG_USED; \ + atomic_write_barrier (); \ + } \ + while (0) +#define THREAD_GSCOPE_WAIT() \ + GL(dl_wait_lookup_done) () + +#endif /* __ASSEMBLER__ */ + +#endif /* tls.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/generic/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/generic/Makefile new file mode 100644 index 00000000..582661fd --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/generic/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc NPTL +# +# Copyright (C) 2006 Steven J. Hill +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../../ +top_builddir=../../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/generic/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/generic/Makefile.in new file mode 100644 index 00000000..eb656ee1 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/generic/Makefile.in @@ -0,0 +1,25 @@ +# Makefile for uClibc NPTL +# +# Copyright (C) 2006 Steven J. Hill +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# +subdirs += libpthread/nptl/sysdeps/generic +# +# NOTE: Alpha and MIPS have their own versions of 'libc-tls.c' in +# their architecture specific directory which will override +# the one here. +# +libpthread_generic_DIR := $(top_srcdir)libpthread/nptl/sysdeps/generic +libpthread_generic_OUT := $(top_builddir)libpthread/nptl/sysdeps/generic + +libpthread_generic_libc_a_CSRC = libc-tls.c +libpthread_generic_libc_a_COBJ = $(patsubst %.c,$(libpthread_generic_OUT)/%.o,$(libpthread_generic_libc_a_CSRC)) +libpthread_generic_libc_a_OBJS = $(libpthread_generic_libc_a_COBJ) +libpthread_ld_tls_CSRC = dl-tls.c +libpthread_ld_tls_COBJ = $(patsubst %.c,$(libpthread_generic_OUT)/%.o,$(libpthread_ld_tls_CSRC)) + +objclean-y += CLEAN_libpthread/nptl/sysdeps/generic + +CLEAN_libpthread/nptl/sysdeps/generic: + $(do_rm) $(addprefix $(libpthread_generic_OUT)/*., o os oS) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/generic/dl-tls.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/generic/dl-tls.c new file mode 100644 index 00000000..4acfa4ba --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/generic/dl-tls.c @@ -0,0 +1,899 @@ +/* Thread-local storage handling in the ELF dynamic linker. Generic version. + Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#if defined SHARED || defined NOT_IN_libc +# error in buildsystem: This file is for libc.a +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#define _dl_malloc malloc +#define _dl_memset memset +#define _dl_mempcpy mempcpy +#define _dl_dprintf fprintf +#define _dl_debug_file stderr +#define _dl_exit exit + +/* Amount of excess space to allocate in the static TLS area + to allow dynamic loading of modules defining IE-model TLS data. */ +# define TLS_STATIC_SURPLUS 64 + DL_NNS * 100 + +/* Value used for dtv entries for which the allocation is delayed. */ +# define TLS_DTV_UNALLOCATED ((void *) -1l) + + +/* Out-of-memory handler. */ +# ifdef SHARED +static void +__attribute__ ((__noreturn__)) +oom (void) +{ + do { + _dl_dprintf (_dl_debug_file, + "cannot allocate thread-local memory: ABORT\n"); + _dl_exit (127); + } while (1); +} +# endif + + +void *_dl_memalign(size_t alignment, size_t bytes) +{ + return _dl_malloc(bytes); +} + + +/* + * We are trying to perform a static TLS relocation in MAP, but it was + * dynamically loaded. This can only work if there is enough surplus in + * the static TLS area already allocated for each running thread. If this + * object's TLS segment is too big to fit, we fail. If it fits, + * we set MAP->l_tls_offset and return. + * This function intentionally does not return any value but signals error + * directly, as static TLS should be rare and code handling it should + * not be inlined as much as possible. + */ + + +void +internal_function __attribute_noinline__ +_dl_allocate_static_tls (struct link_map *map) +{ + /* If the alignment requirements are too high fail. */ + if (map->l_tls_align > _dl_tls_static_align) + { +fail: + _dl_dprintf(_dl_debug_file, "cannot allocate memory in static TLS block"); + _dl_exit(30); + } + +# if defined(TLS_TCB_AT_TP) + size_t freebytes; + size_t n; + size_t blsize; + + freebytes = _dl_tls_static_size - _dl_tls_static_used - TLS_TCB_SIZE; + + blsize = map->l_tls_blocksize + map->l_tls_firstbyte_offset; + if (freebytes < blsize) + goto fail; + + n = (freebytes - blsize) / map->l_tls_align; + + size_t offset = _dl_tls_static_used + (freebytes - n * map->l_tls_align + - map->l_tls_firstbyte_offset); + + map->l_tls_offset = _dl_tls_static_used = offset; +# elif defined(TLS_DTV_AT_TP) + size_t used; + size_t check; + + size_t offset = roundup (_dl_tls_static_used, map->l_tls_align); + used = offset + map->l_tls_blocksize; + check = used; + + /* dl_tls_static_used includes the TCB at the beginning. */ + if (check > _dl_tls_static_size) + goto fail; + + map->l_tls_offset = offset; + _dl_tls_static_used = used; +# else +# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined" +# endif + + /* + * If the object is not yet relocated we cannot initialize the + * static TLS region. Delay it. + */ + if (((struct elf_resolve *) map)->init_flag & RELOCS_DONE) + { +#ifdef SHARED + /* + * Update the slot information data for at least the generation of + * the DSO we are allocating data for. + */ + if (__builtin_expect (THREAD_DTV()[0].counter != _dl_tls_generation, 0)) + (void) _dl_update_slotinfo (map->l_tls_modid); +#endif + _dl_init_static_tls (map); + } + else + map->l_need_tls_init = 1; +} + +size_t +internal_function +_dl_next_tls_modid (void) +{ + size_t result; + + if (__builtin_expect (GL(dl_tls_dtv_gaps), false)) + { + size_t disp = 0; + struct dtv_slotinfo_list *runp = GL(dl_tls_dtv_slotinfo_list); + + /* Note that this branch will never be executed during program + start since there are no gaps at that time. Therefore it + does not matter that the dl_tls_dtv_slotinfo is not allocated + yet when the function is called for the first times. + + NB: the offset +1 is due to the fact that DTV[0] is used + for something else. */ + result = GL(dl_tls_static_nelem) + 1; + if (result <= GL(dl_tls_max_dtv_idx)) + do + { + while (result - disp < runp->len) + { + if (runp->slotinfo[result - disp].map == NULL) + break; + + ++result; + assert (result <= GL(dl_tls_max_dtv_idx) + 1); + } + + if (result - disp < runp->len) + break; + + disp += runp->len; + } + while ((runp = runp->next) != NULL); + + if (result > GL(dl_tls_max_dtv_idx)) + { + /* The new index must indeed be exactly one higher than the + previous high. */ + assert (result == GL(dl_tls_max_dtv_idx) + 1); + /* There is no gap anymore. */ + GL(dl_tls_dtv_gaps) = false; + + goto nogaps; + } + } + else + { + /* No gaps, allocate a new entry. */ + nogaps: + + result = ++GL(dl_tls_max_dtv_idx); + } + + return result; +} + + +# ifdef SHARED +void +internal_function +_dl_determine_tlsoffset (void) +{ + size_t max_align = TLS_TCB_ALIGN; + size_t freetop = 0; + size_t freebottom = 0; + + /* The first element of the dtv slot info list is allocated. */ + assert (GL(dl_tls_dtv_slotinfo_list) != NULL); + /* There is at this point only one element in the + dl_tls_dtv_slotinfo_list list. */ + assert (GL(dl_tls_dtv_slotinfo_list)->next == NULL); + + struct dtv_slotinfo *slotinfo = GL(dl_tls_dtv_slotinfo_list)->slotinfo; + + /* Determining the offset of the various parts of the static TLS + block has several dependencies. In addition we have to work + around bugs in some toolchains. + + Each TLS block from the objects available at link time has a size + and an alignment requirement. The GNU ld computes the alignment + requirements for the data at the positions *in the file*, though. + I.e, it is not simply possible to allocate a block with the size + of the TLS program header entry. The data is layed out assuming + that the first byte of the TLS block fulfills + + p_vaddr mod p_align == &TLS_BLOCK mod p_align + + This means we have to add artificial padding at the beginning of + the TLS block. These bytes are never used for the TLS data in + this module but the first byte allocated must be aligned + according to mod p_align == 0 so that the first byte of the TLS + block is aligned according to p_vaddr mod p_align. This is ugly + and the linker can help by computing the offsets in the TLS block + assuming the first byte of the TLS block is aligned according to + p_align. + + The extra space which might be allocated before the first byte of + the TLS block need not go unused. The code below tries to use + that memory for the next TLS block. This can work if the total + memory requirement for the next TLS block is smaller than the + gap. */ + +# if defined(TLS_TCB_AT_TP) + /* We simply start with zero. */ + size_t offset = 0; + + size_t cnt; + for (cnt = 0; slotinfo[cnt].map != NULL; ++cnt) + { + assert (cnt < GL(dl_tls_dtv_slotinfo_list)->len); + + size_t firstbyte = (-slotinfo[cnt].map->l_tls_firstbyte_offset + & (slotinfo[cnt].map->l_tls_align - 1)); + size_t off; + max_align = MAX (max_align, slotinfo[cnt].map->l_tls_align); + + if (freebottom - freetop >= slotinfo[cnt].map->l_tls_blocksize) + { + off = roundup (freetop + slotinfo[cnt].map->l_tls_blocksize + - firstbyte, slotinfo[cnt].map->l_tls_align) + + firstbyte; + if (off <= freebottom) + { + freetop = off; + + /* XXX For some architectures we perhaps should store the + negative offset. */ + slotinfo[cnt].map->l_tls_offset = off; + continue; + } + } + + off = roundup (offset + slotinfo[cnt].map->l_tls_blocksize - firstbyte, + slotinfo[cnt].map->l_tls_align) + firstbyte; + if (off > offset + slotinfo[cnt].map->l_tls_blocksize + + (freebottom - freetop)) + { + freetop = offset; + freebottom = off - slotinfo[cnt].map->l_tls_blocksize; + } + offset = off; + + /* XXX For some architectures we perhaps should store the + negative offset. */ + slotinfo[cnt].map->l_tls_offset = off; + } + + GL(dl_tls_static_used) = offset; + GL(dl_tls_static_size) = (roundup (offset + TLS_STATIC_SURPLUS, max_align) + + TLS_TCB_SIZE); +# elif defined(TLS_DTV_AT_TP) + /* The TLS blocks start right after the TCB. */ + size_t offset = TLS_TCB_SIZE; + size_t cnt; + + for (cnt = 0; slotinfo[cnt].map != NULL; ++cnt) + { + assert (cnt < GL(dl_tls_dtv_slotinfo_list)->len); + + size_t firstbyte = (-slotinfo[cnt].map->l_tls_firstbyte_offset + & (slotinfo[cnt].map->l_tls_align - 1)); + size_t off; + max_align = MAX (max_align, slotinfo[cnt].map->l_tls_align); + + if (slotinfo[cnt].map->l_tls_blocksize <= freetop - freebottom) + { + off = roundup (freebottom, slotinfo[cnt].map->l_tls_align); + if (off - freebottom < firstbyte) + off += slotinfo[cnt].map->l_tls_align; + if (off + slotinfo[cnt].map->l_tls_blocksize - firstbyte <= freetop) + { + slotinfo[cnt].map->l_tls_offset = off - firstbyte; + freebottom = (off + slotinfo[cnt].map->l_tls_blocksize + - firstbyte); + continue; + } + } + + off = roundup (offset, slotinfo[cnt].map->l_tls_align); + if (off - offset < firstbyte) + off += slotinfo[cnt].map->l_tls_align; + + slotinfo[cnt].map->l_tls_offset = off - firstbyte; + if (off - firstbyte - offset > freetop - freebottom) + { + freebottom = offset; + freetop = off - firstbyte; + } + + offset = off + slotinfo[cnt].map->l_tls_blocksize - firstbyte; + } + + GL(dl_tls_static_used) = offset; + GL(dl_tls_static_size) = roundup (offset + TLS_STATIC_SURPLUS, + TLS_TCB_ALIGN); +# else +# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined" +# endif + + /* The alignment requirement for the static TLS block. */ + GL(dl_tls_static_align) = max_align; +} + + +/* This is called only when the data structure setup was skipped at startup, + when there was no need for it then. Now we have dynamically loaded + something needing TLS, or libpthread needs it. */ +int +internal_function +_dl_tls_setup (void) +{ + assert (GL(dl_tls_dtv_slotinfo_list) == NULL); + assert (GL(dl_tls_max_dtv_idx) == 0); + + const size_t nelem = 2 + TLS_SLOTINFO_SURPLUS; + + GL(dl_tls_dtv_slotinfo_list) + = calloc (1, (sizeof (struct dtv_slotinfo_list) + + nelem * sizeof (struct dtv_slotinfo))); + if (GL(dl_tls_dtv_slotinfo_list) == NULL) + return -1; + + GL(dl_tls_dtv_slotinfo_list)->len = nelem; + + /* Number of elements in the static TLS block. It can't be zero + because of various assumptions. The one element is null. */ + GL(dl_tls_static_nelem) = GL(dl_tls_max_dtv_idx) = 1; + + /* This initializes more variables for us. */ + _dl_determine_tlsoffset (); + + return 0; +} +# endif + +static void * +internal_function +allocate_dtv (void *result) +{ + dtv_t *dtv; + size_t dtv_length; + + /* We allocate a few more elements in the dtv than are needed for the + initial set of modules. This should avoid in most cases expansions + of the dtv. */ + dtv_length = GL(dl_tls_max_dtv_idx) + DTV_SURPLUS; + dtv = calloc (dtv_length + 2, sizeof (dtv_t)); + if (dtv != NULL) + { + /* This is the initial length of the dtv. */ + dtv[0].counter = dtv_length; + + /* The rest of the dtv (including the generation counter) is + Initialize with zero to indicate nothing there. */ + + /* Add the dtv to the thread data structures. */ + INSTALL_DTV (result, dtv); + } + else + result = NULL; + + return result; +} + + +/* Get size and alignment requirements of the static TLS block. */ +void +internal_function +_dl_get_tls_static_info (size_t *sizep, size_t *alignp) +{ + *sizep = GL(dl_tls_static_size); + *alignp = GL(dl_tls_static_align); +} + + +void * +internal_function +_dl_allocate_tls_storage (void) +{ + void *result; + size_t size = GL(dl_tls_static_size); + +# if defined(TLS_DTV_AT_TP) + /* Memory layout is: + [ TLS_PRE_TCB_SIZE ] [ TLS_TCB_SIZE ] [ TLS blocks ] + ^ This should be returned. */ + size += (TLS_PRE_TCB_SIZE + GL(dl_tls_static_align) - 1) + & ~(GL(dl_tls_static_align) - 1); +# endif + + /* Allocate a correctly aligned chunk of memory. */ + result = _dl_memalign (GL(dl_tls_static_align), size); + if (__builtin_expect (result != NULL, 1)) + { + /* Allocate the DTV. */ + void *allocated = result; + +# if defined(TLS_TCB_AT_TP) + /* The TCB follows the TLS blocks. */ + result = (char *) result + size - TLS_TCB_SIZE; + + /* Clear the TCB data structure. We can't ask the caller (i.e. + libpthread) to do it, because we will initialize the DTV et al. */ + _dl_memset (result, '\0', TLS_TCB_SIZE); +# elif defined(TLS_DTV_AT_TP) + result = (char *) result + size - GL(dl_tls_static_size); + + /* Clear the TCB data structure and TLS_PRE_TCB_SIZE bytes before it. + We can't ask the caller (i.e. libpthread) to do it, because we will + initialize the DTV et al. */ + _dl_memset ((char *) result - TLS_PRE_TCB_SIZE, '\0', + TLS_PRE_TCB_SIZE + TLS_TCB_SIZE); +# endif + + result = allocate_dtv (result); + if (result == NULL) + free (allocated); + } + + return result; +} + + +void * +internal_function +_dl_allocate_tls_init (void *result) +{ + if (result == NULL) + /* The memory allocation failed. */ + return NULL; + + dtv_t *dtv = GET_DTV (result); + struct dtv_slotinfo_list *listp; + size_t total = 0; + size_t maxgen = 0; + + /* We have to prepare the dtv for all currently loaded modules using + TLS. For those which are dynamically loaded we add the values + indicating deferred allocation. */ + listp = GL(dl_tls_dtv_slotinfo_list); + while (1) + { + size_t cnt; + + for (cnt = total == 0 ? 1 : 0; cnt < listp->len; ++cnt) + { + struct link_map *map; + void *dest; + + /* Check for the total number of used slots. */ + if (total + cnt > GL(dl_tls_max_dtv_idx)) + break; + + map = listp->slotinfo[cnt].map; + if (map == NULL) + /* Unused entry. */ + continue; + + /* Keep track of the maximum generation number. This might + not be the generation counter. */ + maxgen = MAX (maxgen, listp->slotinfo[cnt].gen); + + if (map->l_tls_offset == NO_TLS_OFFSET) + { + /* For dynamically loaded modules we simply store + the value indicating deferred allocation. */ + dtv[map->l_tls_modid].pointer.val = TLS_DTV_UNALLOCATED; + dtv[map->l_tls_modid].pointer.is_static = false; + continue; + } + + assert (map->l_tls_modid == cnt); + assert (map->l_tls_blocksize >= map->l_tls_initimage_size); +# if defined(TLS_TCB_AT_TP) + assert ((size_t) map->l_tls_offset >= map->l_tls_blocksize); + dest = (char *) result - map->l_tls_offset; +# elif defined(TLS_DTV_AT_TP) + dest = (char *) result + map->l_tls_offset; +# else +# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined" +# endif + + /* Copy the initialization image and clear the BSS part. */ + dtv[map->l_tls_modid].pointer.val = dest; + dtv[map->l_tls_modid].pointer.is_static = true; + _dl_memset (_dl_mempcpy (dest, map->l_tls_initimage, + map->l_tls_initimage_size), '\0', + map->l_tls_blocksize - map->l_tls_initimage_size); + } + + total += cnt; + if (total >= GL(dl_tls_max_dtv_idx)) + break; + + listp = listp->next; + assert (listp != NULL); + } + + /* The DTV version is up-to-date now. */ + dtv[0].counter = maxgen; + + return result; +} + +void * +internal_function +_dl_allocate_tls (void *mem) +{ + return _dl_allocate_tls_init (mem == NULL + ? _dl_allocate_tls_storage () + : allocate_dtv (mem)); +} + + +void +internal_function +_dl_deallocate_tls (void *tcb, bool dealloc_tcb) +{ + dtv_t *dtv = GET_DTV (tcb); + size_t cnt; + + /* We need to free the memory allocated for non-static TLS. */ + for (cnt = 0; cnt < dtv[-1].counter; ++cnt) + if (! dtv[1 + cnt].pointer.is_static + && dtv[1 + cnt].pointer.val != TLS_DTV_UNALLOCATED) + free (dtv[1 + cnt].pointer.val); + + /* The array starts with dtv[-1]. */ +#ifdef SHARED + if (dtv != GL(dl_initial_dtv)) +#endif + free (dtv - 1); + + if (dealloc_tcb) + { +# if defined(TLS_TCB_AT_TP) + /* The TCB follows the TLS blocks. Back up to free the whole block. */ + tcb -= GL(dl_tls_static_size) - TLS_TCB_SIZE; +# elif defined(TLS_DTV_AT_TP) + /* Back up the TLS_PRE_TCB_SIZE bytes. */ + tcb -= (TLS_PRE_TCB_SIZE + GL(dl_tls_static_align) - 1) + & ~(GL(dl_tls_static_align) - 1); +# endif + free (tcb); + } +} + + +# ifdef SHARED +/* The __tls_get_addr function has two basic forms which differ in the + arguments. The IA-64 form takes two parameters, the module ID and + offset. The form used, among others, on IA-32 takes a reference to + a special structure which contain the same information. The second + form seems to be more often used (in the moment) so we default to + it. Users of the IA-64 form have to provide adequate definitions + of the following macros. */ +# ifndef GET_ADDR_ARGS +# define GET_ADDR_ARGS tls_index *ti +# endif +# ifndef GET_ADDR_MODULE +# define GET_ADDR_MODULE ti->ti_module +# endif +# ifndef GET_ADDR_OFFSET +# define GET_ADDR_OFFSET ti->ti_offset +# endif + + +static void * +allocate_and_init (struct link_map *map) +{ + void *newp; + + newp = _dl_memalign (map->l_tls_align, map->l_tls_blocksize); + if (newp == NULL) + oom (); + + /* Initialize the memory. */ + _dl_memset (_dl_mempcpy (newp, map->l_tls_initimage, map->l_tls_initimage_size), + '\0', map->l_tls_blocksize - map->l_tls_initimage_size); + + return newp; +} + + +struct link_map * +_dl_update_slotinfo (unsigned long int req_modid) +{ + struct link_map *the_map = NULL; + dtv_t *dtv = THREAD_DTV (); + + /* The global dl_tls_dtv_slotinfo array contains for each module + index the generation counter current when the entry was created. + This array never shrinks so that all module indices which were + valid at some time can be used to access it. Before the first + use of a new module index in this function the array was extended + appropriately. Access also does not have to be guarded against + modifications of the array. It is assumed that pointer-size + values can be read atomically even in SMP environments. It is + possible that other threads at the same time dynamically load + code and therefore add to the slotinfo list. This is a problem + since we must not pick up any information about incomplete work. + The solution to this is to ignore all dtv slots which were + created after the one we are currently interested. We know that + dynamic loading for this module is completed and this is the last + load operation we know finished. */ + unsigned long int idx = req_modid; + struct dtv_slotinfo_list *listp = GL(dl_tls_dtv_slotinfo_list); + + while (idx >= listp->len) + { + idx -= listp->len; + listp = listp->next; + } + + if (dtv[0].counter < listp->slotinfo[idx].gen) + { + /* The generation counter for the slot is higher than what the + current dtv implements. We have to update the whole dtv but + only those entries with a generation counter <= the one for + the entry we need. */ + size_t new_gen = listp->slotinfo[idx].gen; + size_t total = 0; + + /* We have to look through the entire dtv slotinfo list. */ + listp = GL(dl_tls_dtv_slotinfo_list); + do + { + size_t cnt; + + for (cnt = total == 0 ? 1 : 0; cnt < listp->len; ++cnt) + { + size_t gen = listp->slotinfo[cnt].gen; + + if (gen > new_gen) + /* This is a slot for a generation younger than the + one we are handling now. It might be incompletely + set up so ignore it. */ + continue; + + /* If the entry is older than the current dtv layout we + know we don't have to handle it. */ + if (gen <= dtv[0].counter) + continue; + + /* If there is no map this means the entry is empty. */ + struct link_map *map = listp->slotinfo[cnt].map; + if (map == NULL) + { + /* If this modid was used at some point the memory + might still be allocated. */ + if (! dtv[total + cnt].pointer.is_static + && dtv[total + cnt].pointer.val != TLS_DTV_UNALLOCATED) + { + free (dtv[total + cnt].pointer.val); + dtv[total + cnt].pointer.val = TLS_DTV_UNALLOCATED; + } + + continue; + } + + /* Check whether the current dtv array is large enough. */ + size_t modid = map->l_tls_modid; + assert (total + cnt == modid); + if (dtv[-1].counter < modid) + { + /* Reallocate the dtv. */ + dtv_t *newp; + size_t newsize = GL(dl_tls_max_dtv_idx) + DTV_SURPLUS; + size_t oldsize = dtv[-1].counter; + + assert (map->l_tls_modid <= newsize); + + if (dtv == GL(dl_initial_dtv)) + { + /* This is the initial dtv that was allocated + during rtld startup using the dl-minimal.c + malloc instead of the real malloc. We can't + free it, we have to abandon the old storage. */ + + newp = malloc ((2 + newsize) * sizeof (dtv_t)); + if (newp == NULL) + oom (); + _dl_memcpy (newp, &dtv[-1], oldsize * sizeof (dtv_t)); + } + else + { + newp = realloc (&dtv[-1], + (2 + newsize) * sizeof (dtv_t)); + if (newp == NULL) + oom (); + } + + newp[0].counter = newsize; + + /* Clear the newly allocated part. */ + _dl_memset (newp + 2 + oldsize, '\0', + (newsize - oldsize) * sizeof (dtv_t)); + + /* Point dtv to the generation counter. */ + dtv = &newp[1]; + + /* Install this new dtv in the thread data + structures. */ + INSTALL_NEW_DTV (dtv); + } + + /* If there is currently memory allocate for this + dtv entry free it. */ + /* XXX Ideally we will at some point create a memory + pool. */ + if (! dtv[modid].pointer.is_static + && dtv[modid].pointer.val != TLS_DTV_UNALLOCATED) + /* Note that free is called for NULL is well. We + deallocate even if it is this dtv entry we are + supposed to load. The reason is that we call + memalign and not malloc. */ + free (dtv[modid].pointer.val); + + /* This module is loaded dynamically- We defer memory + allocation. */ + dtv[modid].pointer.is_static = false; + dtv[modid].pointer.val = TLS_DTV_UNALLOCATED; + + if (modid == req_modid) + the_map = map; + } + + total += listp->len; + } + while ((listp = listp->next) != NULL); + + /* This will be the new maximum generation counter. */ + dtv[0].counter = new_gen; + } + + return the_map; +} + + +/* The generic dynamic and local dynamic model cannot be used in + statically linked applications. */ +void * +__tls_get_addr (GET_ADDR_ARGS) +{ + dtv_t *dtv = THREAD_DTV (); + struct link_map *the_map = NULL; + void *p; + + if (__builtin_expect (dtv[0].counter != GL(dl_tls_generation), 0)) + the_map = _dl_update_slotinfo (GET_ADDR_MODULE); + + p = dtv[GET_ADDR_MODULE].pointer.val; + + if (__builtin_expect (p == TLS_DTV_UNALLOCATED, 0)) + { + /* The allocation was deferred. Do it now. */ + if (the_map == NULL) + { + /* Find the link map for this module. */ + size_t idx = GET_ADDR_MODULE; + struct dtv_slotinfo_list *listp = GL(dl_tls_dtv_slotinfo_list); + + while (idx >= listp->len) + { + idx -= listp->len; + listp = listp->next; + } + + the_map = listp->slotinfo[idx].map; + } + + p = dtv[GET_ADDR_MODULE].pointer.val = allocate_and_init (the_map); + dtv[GET_ADDR_MODULE].pointer.is_static = false; + } + + return (char *) p + GET_ADDR_OFFSET; +} +# endif + + + +void +_dl_add_to_slotinfo (struct link_map *l) +{ + /* Now that we know the object is loaded successfully add + modules containing TLS data to the dtv info table. We + might have to increase its size. */ + struct dtv_slotinfo_list *listp; + struct dtv_slotinfo_list *prevp; + size_t idx = l->l_tls_modid; + + /* Find the place in the dtv slotinfo list. */ + listp = GL(dl_tls_dtv_slotinfo_list); + prevp = NULL; /* Needed to shut up gcc. */ + do + { + /* Does it fit in the array of this list element? */ + if (idx < listp->len) + break; + idx -= listp->len; + prevp = listp; + listp = listp->next; + } + while (listp != NULL); + + if (listp == NULL) + { + /* When we come here it means we have to add a new element + to the slotinfo list. And the new module must be in + the first slot. */ + assert (idx == 0); + + listp = prevp->next = (struct dtv_slotinfo_list *) + malloc (sizeof (struct dtv_slotinfo_list) + + TLS_SLOTINFO_SURPLUS * sizeof (struct dtv_slotinfo)); + if (listp == NULL) + { + /* We ran out of memory. We will simply fail this + call but don't undo anything we did so far. The + application will crash or be terminated anyway very + soon. */ + + /* We have to do this since some entries in the dtv + slotinfo array might already point to this + generation. */ + ++GL(dl_tls_generation); + + _dl_dprintf (_dl_debug_file, + "cannot create TLS data structures: ABORT\n"); + _dl_exit (127); + } + + listp->len = TLS_SLOTINFO_SURPLUS; + listp->next = NULL; + _dl_memset (listp->slotinfo, '\0', + TLS_SLOTINFO_SURPLUS * sizeof (struct dtv_slotinfo)); + } + + /* Add the information into the slotinfo data structure. */ + listp->slotinfo[idx].map = l; + listp->slotinfo[idx].gen = GL(dl_tls_generation) + 1; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/generic/dl-tls.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/generic/dl-tls.h new file mode 100644 index 00000000..7703a975 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/generic/dl-tls.h @@ -0,0 +1,2 @@ +/* There has to be an architecture specific version of this file. */ +#error "architecture-specific version of missing" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/generic/libc-tls.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/generic/libc-tls.c new file mode 100644 index 00000000..b78d9648 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/generic/libc-tls.c @@ -0,0 +1,265 @@ +/* Initialization code for TLS in statically linked application. + Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#ifdef SHARED + #error makefile bug, this file is for static only +#endif + +#if USE_TLS +extern ElfW(Phdr) *_dl_phdr; +extern size_t _dl_phnum; + + +static dtv_t static_dtv[2 + TLS_SLOTINFO_SURPLUS]; + + +static struct +{ + struct dtv_slotinfo_list si; + /* The dtv_slotinfo_list data structure does not include the actual + information since it is defined as an array of size zero. We define + here the necessary entries. Note that it is not important whether + there is padding or not since we will always access the information + through the 'si' element. */ + struct dtv_slotinfo info[2 + TLS_SLOTINFO_SURPLUS]; +} static_slotinfo; + +/* Fake link map for the application. */ +static struct link_map static_map; + + +/* Highest dtv index currently needed. */ +size_t _dl_tls_max_dtv_idx; +/* Flag signalling whether there are gaps in the module ID allocation. */ +bool _dl_tls_dtv_gaps; +/* Information about the dtv slots. */ +struct dtv_slotinfo_list *_dl_tls_dtv_slotinfo_list; +/* Number of modules in the static TLS block. */ +size_t _dl_tls_static_nelem; +/* Size of the static TLS block. */ +size_t _dl_tls_static_size; +/* Size actually allocated in the static TLS block. */ +size_t _dl_tls_static_used; +/* Alignment requirement of the static TLS block. */ +size_t _dl_tls_static_align; + +/* Generation counter for the dtv. */ +size_t _dl_tls_generation; + + +/* Additional definitions needed by TLS initialization. */ +#ifdef TLS_INIT_HELPER +TLS_INIT_HELPER +#endif + +static inline void +init_slotinfo (void) +{ + /* Create the slotinfo list. */ + static_slotinfo.si.len = (((char *) (&static_slotinfo + 1) + - (char *) &static_slotinfo.si.slotinfo[0]) + / sizeof static_slotinfo.si.slotinfo[0]); + // static_slotinfo.si.next = NULL; already zero + + /* The slotinfo list. Will be extended by the code doing dynamic + linking. */ + GL(dl_tls_max_dtv_idx) = 1; + GL(dl_tls_dtv_slotinfo_list) = &static_slotinfo.si; +} + +static inline void +init_static_tls (size_t memsz, size_t align) +{ + /* That is the size of the TLS memory for this object. The initialized + value of _dl_tls_static_size is provided by dl-open.c to request some + surplus that permits dynamic loading of modules with IE-model TLS. */ + GL(dl_tls_static_size) = roundup (memsz + GL(dl_tls_static_size), + TLS_TCB_ALIGN); + GL(dl_tls_static_used) = memsz; + /* The alignment requirement for the static TLS block. */ + GL(dl_tls_static_align) = align; + /* Number of elements in the static TLS block. */ + GL(dl_tls_static_nelem) = GL(dl_tls_max_dtv_idx); +} + +void +__libc_setup_tls (size_t tcbsize, size_t tcbalign) +{ + void *tlsblock; + size_t memsz = 0; + size_t filesz = 0; + void *initimage = NULL; + size_t align = 0; + size_t max_align = tcbalign; + size_t tcb_offset; + ElfW(Phdr) *phdr; + + /* Look through the TLS segment if there is any. */ + if (_dl_phdr != NULL) + for (phdr = _dl_phdr; phdr < &_dl_phdr[_dl_phnum]; ++phdr) + if (phdr->p_type == PT_TLS) + { + /* Remember the values we need. */ + memsz = phdr->p_memsz; + filesz = phdr->p_filesz; + initimage = (void *) phdr->p_vaddr; + align = phdr->p_align; + if (phdr->p_align > max_align) + max_align = phdr->p_align; + break; + } + + /* We have to set up the TCB block which also (possibly) contains + 'errno'. Therefore we avoid 'malloc' which might touch 'errno'. + Instead we use 'sbrk' which would only uses 'errno' if it fails. + In this case we are right away out of memory and the user gets + what she/he deserves. + + The initialized value of _dl_tls_static_size is provided by dl-open.c + to request some surplus that permits dynamic loading of modules with + IE-model TLS. */ +# if defined(TLS_TCB_AT_TP) + tcb_offset = roundup (memsz + GL(dl_tls_static_size), tcbalign); + tlsblock = sbrk (tcb_offset + tcbsize + max_align); +# elif defined(TLS_DTV_AT_TP) + tcb_offset = roundup (tcbsize, align ?: 1); + tlsblock = sbrk (tcb_offset + memsz + max_align + + TLS_PRE_TCB_SIZE + GL(dl_tls_static_size)); + tlsblock += TLS_PRE_TCB_SIZE; +# else + /* In case a model with a different layout for the TCB and DTV + is defined add another #elif here and in the following #ifs. */ +# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined" +# endif + + /* Align the TLS block. */ + tlsblock = (void *) (((uintptr_t) tlsblock + max_align - 1) + & ~(max_align - 1)); + + /* Initialize the dtv. [0] is the length, [1] the generation counter. */ + static_dtv[0].counter = (sizeof (static_dtv) / sizeof (static_dtv[0])) - 2; + // static_dtv[1].counter = 0; would be needed if not already done + + /* Initialize the TLS block. */ +# if defined(TLS_TCB_AT_TP) + static_dtv[2].pointer.val = ((char *) tlsblock + tcb_offset + - roundup (memsz, align ?: 1)); + static_map.l_tls_offset = roundup (memsz, align ?: 1); +# elif defined(TLS_DTV_AT_TP) + static_dtv[2].pointer.val = (char *) tlsblock + tcb_offset; + static_map.l_tls_offset = tcb_offset; +# else +# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined" +# endif + static_dtv[2].pointer.is_static = true; + /* sbrk gives us zero'd memory, so we don't need to clear the remainder. */ + memcpy (static_dtv[2].pointer.val, initimage, filesz); + + /* Install the pointer to the dtv. */ + + /* Initialize the thread pointer. */ +# if defined(TLS_TCB_AT_TP) + INSTALL_DTV ((char *) tlsblock + tcb_offset, static_dtv); + + const char *lossage = TLS_INIT_TP ((char *) tlsblock + tcb_offset, 0); +# elif defined(TLS_DTV_AT_TP) + INSTALL_DTV (tlsblock, static_dtv); + const char *lossage = (char *)TLS_INIT_TP (tlsblock, 0); +# else +# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined" +# endif + if (__builtin_expect (lossage != NULL, 0)) + abort(); + + /* We have to create a fake link map which normally would be created + by the dynamic linker. It just has to have enough information to + make the TLS routines happy. */ + static_map.l_tls_align = align; + static_map.l_tls_blocksize = memsz; + static_map.l_tls_initimage = initimage; + static_map.l_tls_initimage_size = filesz; + static_map.l_tls_modid = 1; + + init_slotinfo (); + // static_slotinfo.si.slotinfo[1].gen = 0; already zero + static_slotinfo.si.slotinfo[1].map = &static_map; + + memsz = roundup (memsz, align ?: 1); + +# if defined(TLS_TCB_AT_TP) + memsz += tcbsize; +# elif defined(TLS_DTV_AT_TP) + memsz += tcb_offset; +# endif + + init_static_tls (memsz, MAX (TLS_TCB_ALIGN, max_align)); +} + +/* This is called only when the data structure setup was skipped at startup, + when there was no need for it then. Now we have dynamically loaded + something needing TLS, or libpthread needs it. */ +int +internal_function +_dl_tls_setup (void) +{ + init_slotinfo (); + init_static_tls ( +# if defined(TLS_TCB_AT_TP) + TLS_TCB_SIZE, +# else + 0, +# endif + TLS_TCB_ALIGN); + return 0; +} + + +/* This is the minimal initialization function used when libpthread is + not used. */ +void +__attribute__ ((weak)) +__pthread_initialize_minimal (void) +{ + __libc_setup_tls (TLS_INIT_TCB_SIZE, TLS_INIT_TCB_ALIGN); +} + +#elif defined NONTLS_INIT_TP + +/* This is the minimal initialization function used when libpthread is + not used. */ +void +__attribute__ ((weak)) +__pthread_initialize_minimal (void) +{ + NONTLS_INIT_TP; +} + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/generic/lowlevellock.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/generic/lowlevellock.h new file mode 100644 index 00000000..0600e179 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/generic/lowlevellock.h @@ -0,0 +1,84 @@ +/* Low level locking macros used in NPTL implementation. Stub version. + Copyright (C) 2002, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + + +/* Mutex lock counter: + bit 31 clear means unlocked; + bit 31 set means locked. + + All code that looks at bit 31 first increases the 'number of + interested threads' usage counter, which is in bits 0-30. + + All negative mutex values indicate that the mutex is still locked. */ + + +static inline void +__generic_mutex_lock (int *mutex) +{ + unsigned int v; + + /* Bit 31 was clear, we got the mutex. (this is the fastpath). */ + if (atomic_bit_test_set (mutex, 31) == 0) + return; + + atomic_increment (mutex); + + while (1) + { + if (atomic_bit_test_set (mutex, 31) == 0) + { + atomic_decrement (mutex); + return; + } + + /* We have to wait now. First make sure the futex value we are + monitoring is truly negative (i.e. locked). */ + v = *mutex; + if (v >= 0) + continue; + + lll_futex_wait (mutex, v, + // XYZ check mutex flag + LLL_SHARED); + } +} + + +static inline void +__generic_mutex_unlock (int *mutex) +{ + /* Adding 0x80000000 to the counter results in 0 if and only if + there are not other interested threads - we can return (this is + the fastpath). */ + if (atomic_add_zero (mutex, 0x80000000)) + return; + + /* There are other threads waiting for this mutex, wake one of them + up. */ + lll_futex_wake (mutex, 1, + // XYZ check mutex flag + LLL_SHARED); +} + + +#define lll_mutex_lock(futex) __generic_mutex_lock (&(futex)) +#define lll_mutex_unlock(futex) __generic_mutex_unlock (&(futex)) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/generic/unwind.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/generic/unwind.h new file mode 100644 index 00000000..81fc4db5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/generic/unwind.h @@ -0,0 +1,220 @@ +/* Exception handling and frame unwind runtime interface routines. + Copyright (C) 2001, 2003 Free Software Foundation, Inc. + + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This is derived from the C++ ABI for IA-64. Where we diverge + for cross-architecture compatibility are noted with "@@@". */ + +#ifndef _UNWIND_H +#define _UNWIND_H 1 + +#ifdef __cplusplus +extern "C" { +#endif + +/* Level 1: Base ABI */ + +/* @@@ The IA-64 ABI uses uint64 throughout. Most places this is + inefficient for 32-bit and smaller machines. */ +typedef unsigned _Unwind_Word __attribute__((__mode__(__word__))); +typedef signed _Unwind_Sword __attribute__((__mode__(__word__))); +#if defined(__ia64__) && defined(__hpux__) +typedef unsigned _Unwind_Ptr __attribute__((__mode__(__word__))); +#else +typedef unsigned _Unwind_Ptr __attribute__((__mode__(__pointer__))); +#endif +typedef unsigned _Unwind_Internal_Ptr __attribute__((__mode__(__pointer__))); + +/* @@@ The IA-64 ABI uses a 64-bit word to identify the producer and + consumer of an exception. We'll go along with this for now even on + 32-bit machines. We'll need to provide some other option for + 16-bit machines and for machines with > 8 bits per byte. */ +typedef unsigned _Unwind_Exception_Class __attribute__((__mode__(__DI__))); + +/* The unwind interface uses reason codes in several contexts to + identify the reasons for failures or other actions. */ +typedef enum +{ + _URC_NO_REASON = 0, + _URC_FOREIGN_EXCEPTION_CAUGHT = 1, + _URC_FATAL_PHASE2_ERROR = 2, + _URC_FATAL_PHASE1_ERROR = 3, + _URC_NORMAL_STOP = 4, + _URC_END_OF_STACK = 5, + _URC_HANDLER_FOUND = 6, + _URC_INSTALL_CONTEXT = 7, + _URC_CONTINUE_UNWIND = 8 +} _Unwind_Reason_Code; + + +/* The unwind interface uses a pointer to an exception header object + as its representation of an exception being thrown. In general, the + full representation of an exception object is language- and + implementation-specific, but it will be prefixed by a header + understood by the unwind interface. */ + +struct _Unwind_Exception; + +typedef void (*_Unwind_Exception_Cleanup_Fn) (_Unwind_Reason_Code, + struct _Unwind_Exception *); + +struct _Unwind_Exception +{ + _Unwind_Exception_Class exception_class; + _Unwind_Exception_Cleanup_Fn exception_cleanup; + _Unwind_Word private_1; + _Unwind_Word private_2; + + /* @@@ The IA-64 ABI says that this structure must be double-word aligned. + Taking that literally does not make much sense generically. Instead we + provide the maximum alignment required by any type for the machine. */ +} __attribute__((__aligned__)); + + +/* The ACTIONS argument to the personality routine is a bitwise OR of one + or more of the following constants. */ +typedef int _Unwind_Action; + +#define _UA_SEARCH_PHASE 1 +#define _UA_CLEANUP_PHASE 2 +#define _UA_HANDLER_FRAME 4 +#define _UA_FORCE_UNWIND 8 +#define _UA_END_OF_STACK 16 + +/* This is an opaque type used to refer to a system-specific data + structure used by the system unwinder. This context is created and + destroyed by the system, and passed to the personality routine + during unwinding. */ +struct _Unwind_Context; + +/* Raise an exception, passing along the given exception object. */ +extern _Unwind_Reason_Code _Unwind_RaiseException (struct _Unwind_Exception *); + +/* Raise an exception for forced unwinding. */ + +typedef _Unwind_Reason_Code (*_Unwind_Stop_Fn) + (int, _Unwind_Action, _Unwind_Exception_Class, + struct _Unwind_Exception *, struct _Unwind_Context *, void *); + +extern _Unwind_Reason_Code _Unwind_ForcedUnwind (struct _Unwind_Exception *, + _Unwind_Stop_Fn, + void *); + +/* Helper to invoke the exception_cleanup routine. */ +extern void _Unwind_DeleteException (struct _Unwind_Exception *); + +/* Resume propagation of an existing exception. This is used after + e.g. executing cleanup code, and not to implement rethrowing. */ +extern void _Unwind_Resume (struct _Unwind_Exception *); + +/* @@@ Use unwind data to perform a stack backtrace. The trace callback + is called for every stack frame in the call chain, but no cleanup + actions are performed. */ +typedef _Unwind_Reason_Code (*_Unwind_Trace_Fn) + (struct _Unwind_Context *, void *); + +extern _Unwind_Reason_Code _Unwind_Backtrace (_Unwind_Trace_Fn, void *); + +/* These functions are used for communicating information about the unwind + context (i.e. the unwind descriptors and the user register state) between + the unwind library and the personality routine and landing pad. Only + selected registers maybe manipulated. */ + +extern _Unwind_Word _Unwind_GetGR (struct _Unwind_Context *, int); +extern void _Unwind_SetGR (struct _Unwind_Context *, int, _Unwind_Word); + +extern _Unwind_Ptr _Unwind_GetIP (struct _Unwind_Context *); +extern void _Unwind_SetIP (struct _Unwind_Context *, _Unwind_Ptr); + +/* @@@ Retrieve the CFA of the given context. */ +extern _Unwind_Word _Unwind_GetCFA (struct _Unwind_Context *); + +extern void *_Unwind_GetLanguageSpecificData (struct _Unwind_Context *); + +extern _Unwind_Ptr _Unwind_GetRegionStart (struct _Unwind_Context *); + + +/* The personality routine is the function in the C++ (or other language) + runtime library which serves as an interface between the system unwind + library and language-specific exception handling semantics. It is + specific to the code fragment described by an unwind info block, and + it is always referenced via the pointer in the unwind info block, and + hence it has no ABI-specified name. + + Note that this implies that two different C++ implementations can + use different names, and have different contents in the language + specific data area. Moreover, that the language specific data + area contains no version info because name of the function invoked + provides more effective versioning by detecting at link time the + lack of code to handle the different data format. */ + +typedef _Unwind_Reason_Code (*_Unwind_Personality_Fn) + (int, _Unwind_Action, _Unwind_Exception_Class, + struct _Unwind_Exception *, struct _Unwind_Context *); + +/* @@@ The following alternate entry points are for setjmp/longjmp + based unwinding. */ + +struct SjLj_Function_Context; +extern void _Unwind_SjLj_Register (struct SjLj_Function_Context *); +extern void _Unwind_SjLj_Unregister (struct SjLj_Function_Context *); + +extern _Unwind_Reason_Code _Unwind_SjLj_RaiseException + (struct _Unwind_Exception *); +extern _Unwind_Reason_Code _Unwind_SjLj_ForcedUnwind + (struct _Unwind_Exception *, _Unwind_Stop_Fn, void *); +extern void _Unwind_SjLj_Resume (struct _Unwind_Exception *); + +/* @@@ The following provide access to the base addresses for text + and data-relative addressing in the LDSA. In order to stay link + compatible with the standard ABI for IA-64, we inline these. */ + +#ifdef __ia64__ +#include + +static inline _Unwind_Ptr +_Unwind_GetDataRelBase (struct _Unwind_Context *_C) +{ + /* The GP is stored in R1. */ + return _Unwind_GetGR (_C, 1); +} + +static inline _Unwind_Ptr +_Unwind_GetTextRelBase (struct _Unwind_Context *_C) +{ + abort (); + return 0; +} + +/* @@@ Retrieve the Backing Store Pointer of the given context. */ +extern _Unwind_Word _Unwind_GetBSP (struct _Unwind_Context *); +#else +extern _Unwind_Ptr _Unwind_GetDataRelBase (struct _Unwind_Context *); +extern _Unwind_Ptr _Unwind_GetTextRelBase (struct _Unwind_Context *); +#endif + +/* @@@ Given an address, return the entry point of the function that + contains it. */ +extern void * _Unwind_FindEnclosingFunction (void *pc); + +#ifdef __cplusplus +} +#endif + +#endif /* unwind.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/i386/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/i386/Makefile new file mode 100644 index 00000000..2f0d88f3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/i386/Makefile @@ -0,0 +1,27 @@ +# Copyright (C) 2002, 2003 Free Software Foundation, Inc. +# This file is part of the GNU C Library. + +# The GNU C Library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. + +# The GNU C Library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. + +# You should have received a copy of the GNU Lesser General Public +# License along with the GNU C Library; if not, write to the Free +# Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +# 02111-1307 USA. + +ifeq ($(subdir),csu) +gen-as-const-headers += tcb-offsets.sym +endif + +ifeq ($(subdir),nptl) +CFLAGS-pthread_create.c += -mpreferred-stack-boundary=4 +CFLAGS-tst-align.c += -mpreferred-stack-boundary=4 +CFLAGS-tst-align2.c += -mpreferred-stack-boundary=4 +endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/i386/Makefile.arch b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/i386/Makefile.arch new file mode 100644 index 00000000..95723038 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/i386/Makefile.arch @@ -0,0 +1,10 @@ +# Makefile for uClibc NPTL +# +# Copyright (C) 2005 Steven J. Hill +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +CFLAGS-pthread_spin_lock.c += -D_GNU_SOURCE +CFLAGS-pthread_create.c += -mpreferred-stack-boundary=4 + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/i386/dl-tls.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/i386/dl-tls.h new file mode 100644 index 00000000..e94f9654 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/i386/dl-tls.h @@ -0,0 +1,62 @@ +/* Thread-local storage handling in the ELF dynamic linker. i386 version. + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + + +/* Type used for the representation of TLS information in the GOT. */ +typedef struct +{ + unsigned long int ti_module; + unsigned long int ti_offset; +} tls_index; + + +extern void *__tls_get_addr (tls_index *ti); + +#ifdef SHARED +/* This is the prototype for the GNU version. */ +extern void *___tls_get_addr (tls_index *ti) + __attribute__ ((__regparm__ (1))); +extern void *___tls_get_addr_internal (tls_index *ti) + __attribute__ ((__regparm__ (1))) attribute_hidden; + +# ifdef IS_IN_rtld +/* The special thing about the x86 TLS ABI is that we have two + variants of the __tls_get_addr function with different calling + conventions. The GNU version, which we are mostly concerned here, + takes the parameter in a register. The name is changed by adding + an additional underscore at the beginning. The Sun version uses + the normal calling convention. */ +void * +__tls_get_addr (tls_index *ti) +{ + return ___tls_get_addr_internal (ti); +} + + +/* Prepare using the definition of __tls_get_addr in the generic + version of this file. */ +# define __tls_get_addr __attribute__ ((__regparm__ (1))) ___tls_get_addr +strong_alias (___tls_get_addr, ___tls_get_addr_internal) +#else + +/* Users should get the better interface. */ +# define __tls_get_addr ___tls_get_addr + +# endif +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/i386/i486/pthread_spin_trylock.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/i386/i486/pthread_spin_trylock.S new file mode 100644 index 00000000..e30072c3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/i386/i486/pthread_spin_trylock.S @@ -0,0 +1,47 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + + +#ifdef UP +# define LOCK +#else +# define LOCK lock +#endif + + .globl pthread_spin_trylock + .type pthread_spin_trylock,@function + .align 16 +pthread_spin_trylock: + movl 4(%esp), %edx + movl $1, %eax + xorl %ecx, %ecx + LOCK + cmpxchgl %ecx, (%edx) + movl $EBUSY, %eax +#ifdef HAVE_CMOV + cmovel %ecx, %eax +#else + jne 0f + movl %ecx, %eax +0: +#endif + ret + .size pthread_spin_trylock,.-pthread_spin_trylock diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/i386/i586/pthread_spin_trylock.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/i386/i586/pthread_spin_trylock.S new file mode 100644 index 00000000..ffe3d456 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/i386/i586/pthread_spin_trylock.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "../i486/pthread_spin_trylock.S" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/i386/i686/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/i386/i686/Makefile new file mode 100644 index 00000000..137c0a2f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/i386/i686/Makefile @@ -0,0 +1,32 @@ +# Copyright (C) 2003 Free Software Foundation, Inc. +# This file is part of the GNU C Library. +# Contributed by Ulrich Drepper , 2002. + +# The GNU C Library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. + +# The GNU C Library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. + +# You should have received a copy of the GNU Lesser General Public +# License along with the GNU C Library; if not, write to the Free +# Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +# 02111-1307 USA. + +ifeq ($(subdir),nptl) +# It turns out that stack coloring is in general not good on P4s. Some +# applications will benefit. We will probably have a configuration option +# at some point. Enabling coloring can be done with +# +# -DCOLORING_INCREMENT=128 +# +# What is useful is to avoid the 64k aliasing problem which reliably +# happens if all stacks use sizes which are a multiple of 64k. Tell +# the stack allocator to disturb this by allocation one more page if +# necessary. +CFLAGS-pthread_create.c += -DMULTI_PAGE_ALIASING=65536 +endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/i386/i686/pthread_spin_trylock.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/i386/i686/pthread_spin_trylock.S new file mode 100644 index 00000000..a5d861f9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/i386/i686/pthread_spin_trylock.S @@ -0,0 +1,21 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define HAVE_CMOV 1 +#include "../i486/pthread_spin_trylock.S" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/i386/i686/tls.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/i386/i686/tls.h new file mode 100644 index 00000000..928d269d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/i386/i686/tls.h @@ -0,0 +1,36 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _TLS_H + +/* Additional definitions for on i686 and up. */ + + +/* Macros to load from and store into segment registers. We can use + the 32-bit instructions. */ +#define TLS_GET_GS() \ + ({ int __seg; __asm__ ("movl %%gs, %0" : "=q" (__seg)); __seg; }) +#define TLS_SET_GS(val) \ + __asm__ ("movl %0, %%gs" :: "q" (val)) + + +/* Get the full set of definitions. */ +#include "../tls.h" + +#endif /* tls.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/i386/jmpbuf-unwind.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/i386/jmpbuf-unwind.h new file mode 100644 index 00000000..b9528f36 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/i386/jmpbuf-unwind.h @@ -0,0 +1,32 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +#define _JMPBUF_CFA_UNWINDS_ADJ(_jmpbuf, _context, _adj) \ + _JMPBUF_UNWINDS_ADJ (_jmpbuf, (void *) _Unwind_GetCFA (_context), _adj) + +#define _JMPBUF_UNWINDS_ADJ(_jmpbuf, _address, _adj) \ + ((uintptr_t) (_address) - (_adj) < (uintptr_t) (_jmpbuf)[JB_SP] - (_adj)) + +/* We use the normal lobngjmp for unwinding. */ +extern __typeof(longjmp) __libc_longjmp attribute_noreturn; +#define __libc_unwind_longjmp(buf, val) __libc_longjmp (buf, val) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/i386/pthread_spin_init.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/i386/pthread_spin_init.c new file mode 100644 index 00000000..0a47981a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/i386/pthread_spin_init.c @@ -0,0 +1,20 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Not needed. pthread_spin_init is an alias for pthread_spin_unlock. */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/i386/pthread_spin_lock.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/i386/pthread_spin_lock.c new file mode 100644 index 00000000..34cd525d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/i386/pthread_spin_lock.c @@ -0,0 +1,49 @@ +/* Copyright (C) 2002,2003,2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "pthreadP.h" + +#ifndef LOCK_PREFIX +# ifdef UP +# define LOCK_PREFIX /* nothing */ +# else +# define LOCK_PREFIX "lock;" +# endif +#endif + + +int +pthread_spin_lock ( + pthread_spinlock_t *lock) +{ + __asm__ ("\n" + "1:\t" LOCK_PREFIX "decl %0\n\t" + "jne 2f\n\t" + ".subsection 1\n\t" + ".align 16\n" + "2:\trep; nop\n\t" + "cmpl $0, %0\n\t" + "jg 1b\n\t" + "jmp 2b\n\t" + ".previous" + : "=m" (*lock) + : "m" (*lock)); + + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/i386/pthread_spin_unlock.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/i386/pthread_spin_unlock.S new file mode 100644 index 00000000..d94f1e7b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/i386/pthread_spin_unlock.S @@ -0,0 +1,32 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + + .globl pthread_spin_unlock + .type pthread_spin_unlock,@function + .align 16 +pthread_spin_unlock: + movl 4(%esp), %eax + movl $1, (%eax) + xorl %eax, %eax + ret + .size pthread_spin_unlock,.-pthread_spin_unlock + + /* The implementation of pthread_spin_init is identical. */ + .globl pthread_spin_init +pthread_spin_init = pthread_spin_unlock diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/i386/pthreaddef.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/i386/pthreaddef.h new file mode 100644 index 00000000..f9f5645d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/i386/pthreaddef.h @@ -0,0 +1,48 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Default stack size. */ +#define ARCH_STACK_DEFAULT_SIZE (2 * 1024 * 1024) + +/* Required stack pointer alignment at beginning. SSE requires 16 + bytes. */ +#define STACK_ALIGN 16 + +/* Minimal stack size after allocating thread descriptor and guard size. */ +#define MINIMAL_REST_STACK 2048 + +/* Alignment requirement for TCB. */ +#define TCB_ALIGNMENT 16 + + +/* Location of current stack frame. */ +#define CURRENT_STACK_FRAME __builtin_frame_address (0) + + +/* XXX Until we have a better place keep the definitions here. */ + +/* While there is no such syscall. */ +#define __exit_thread_inline(val) \ + while (1) { \ + if (__builtin_constant_p (val) && (val) == 0) \ + __asm__ __volatile__ ("xorl %%ebx, %%ebx; int $0x80" :: "a" (__NR_exit)); \ + else \ + __asm__ __volatile__ ("movl %1, %%ebx; int $0x80" \ + :: "a" (__NR_exit), "r" (val)); \ + } diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/i386/tcb-offsets.sym b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/i386/tcb-offsets.sym new file mode 100644 index 00000000..69f9deb3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/i386/tcb-offsets.sym @@ -0,0 +1,17 @@ +#include +#include + +RESULT offsetof (struct pthread, result) +TID offsetof (struct pthread, tid) +PID offsetof (struct pthread, pid) +CANCELHANDLING offsetof (struct pthread, cancelhandling) +CLEANUP_JMP_BUF offsetof (struct pthread, cleanup_jmp_buf) +MULTIPLE_THREADS_OFFSET offsetof (tcbhead_t, multiple_threads) +SYSINFO_OFFSET offsetof (tcbhead_t, sysinfo) +CLEANUP offsetof (struct pthread, cleanup) +CLEANUP_PREV offsetof (struct _pthread_cleanup_buffer, __prev) +MUTEX_FUTEX offsetof (pthread_mutex_t, __data.__lock) +POINTER_GUARD offsetof (tcbhead_t, pointer_guard) +#ifndef __ASSUME_PRIVATE_FUTEX +PRIVATE_FUTEX offsetof (tcbhead_t, private_futex) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/i386/tls.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/i386/tls.h new file mode 100644 index 00000000..ac547953 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/i386/tls.h @@ -0,0 +1,480 @@ +/* Definition for thread-local data handling. nptl/i386 version. + Copyright (C) 2002-2007, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _TLS_H +#define _TLS_H 1 + +#ifndef __ASSEMBLER__ +# include +# include +# include +# include +# include +# include +# include + + +/* Type for the dtv. */ +typedef union dtv +{ + size_t counter; + struct + { + void *val; + bool is_static; + } pointer; +} dtv_t; + + +typedef struct +{ + void *tcb; /* Pointer to the TCB. Not necessarily the + thread descriptor used by libpthread. */ + dtv_t *dtv; + void *self; /* Pointer to the thread descriptor. */ + int multiple_threads; + uintptr_t sysinfo; + uintptr_t stack_guard; + uintptr_t pointer_guard; + int gscope_flag; +#ifndef __ASSUME_PRIVATE_FUTEX + int private_futex; +#else + int __unused1; +#endif + /* Reservation of some values for the TM ABI. */ + void *__private_tm[5]; +} tcbhead_t; + +# define TLS_MULTIPLE_THREADS_IN_TCB 1 + +#else /* __ASSEMBLER__ */ +# include +#endif + + +/* We require TLS support in the tools. */ +#define HAVE_TLS_SUPPORT +#define HAVE___THREAD 1 +#define HAVE_TLS_MODEL_ATTRIBUTE 1 + +/* Signal that TLS support is available. */ +#define USE_TLS 1 + + +/* Alignment requirement for the stack. For IA-32 this is governed by + the SSE memory functions. */ +#define STACK_ALIGN 16 + +#ifndef __ASSEMBLER__ +/* Get system call information. */ +# include + +/* The old way: using LDT. */ + +/* Structure passed to `modify_ldt', 'set_thread_area', and 'clone' calls. */ +struct user_desc +{ + unsigned int entry_number; + unsigned long int base_addr; + unsigned int limit; + unsigned int seg_32bit:1; + unsigned int contents:2; + unsigned int read_exec_only:1; + unsigned int limit_in_pages:1; + unsigned int seg_not_present:1; + unsigned int useable:1; + unsigned int empty:25; +}; + +/* Initializing bit fields is slow. We speed it up by using a union. */ +union user_desc_init +{ + struct user_desc desc; + unsigned int vals[4]; +}; + + +/* Get the thread descriptor definition. */ +# include + +/* This is the size of the initial TCB. Can't be just sizeof (tcbhead_t), + because NPTL getpid, __libc_alloca_cutoff etc. need (almost) the whole + struct pthread even when not linked with -lpthread. */ +# define TLS_INIT_TCB_SIZE sizeof (struct pthread) + +/* Alignment requirements for the initial TCB. */ +# define TLS_INIT_TCB_ALIGN __alignof__ (struct pthread) + +/* This is the size of the TCB. */ +# define TLS_TCB_SIZE sizeof (struct pthread) + +/* Alignment requirements for the TCB. */ +# define TLS_TCB_ALIGN __alignof__ (struct pthread) + +/* The TCB can have any size and the memory following the address the + thread pointer points to is unspecified. Allocate the TCB there. */ +# define TLS_TCB_AT_TP 1 + + +/* Install the dtv pointer. The pointer passed is to the element with + index -1 which contain the length. */ +# define INSTALL_DTV(descr, dtvp) \ + ((tcbhead_t *) (descr))->dtv = (dtvp) + 1 + +/* Install new dtv for current thread. */ +# define INSTALL_NEW_DTV(dtvp) \ + ({ struct pthread *__pd; \ + THREAD_SETMEM (__pd, header.dtv, (dtvp)); }) + +/* Return dtv of given thread descriptor. */ +# define GET_DTV(descr) \ + (((tcbhead_t *) (descr))->dtv) + +#define THREAD_SELF_SYSINFO THREAD_GETMEM (THREAD_SELF, header.sysinfo) +#define THREAD_SYSINFO(pd) ((pd)->header.sysinfo) + +/* Macros to load from and store into segment registers. */ +# ifndef TLS_GET_GS +# define TLS_GET_GS() \ + ({ int __seg; __asm__ ("movw %%gs, %w0" : "=q" (__seg)); __seg & 0xffff; }) +# endif +# ifndef TLS_SET_GS +# define TLS_SET_GS(val) \ + __asm__ ("movw %w0, %%gs" :: "q" (val)) +# endif + + +# ifndef __NR_set_thread_area +# define __NR_set_thread_area 243 +# endif +# ifndef TLS_FLAG_WRITABLE +# define TLS_FLAG_WRITABLE 0x00000001 +# endif + +// XXX Enable for the real world. +#if 0 +# ifndef __ASSUME_SET_THREAD_AREA +# error "we need set_thread_area" +# endif +#endif + +# ifdef __PIC__ +# define TLS_EBX_ARG "r" +# define TLS_LOAD_EBX "xchgl %3, %%ebx\n\t" +# else +# define TLS_EBX_ARG "b" +# define TLS_LOAD_EBX +# endif + +#if defined NEED_DL_SYSINFO +# define INIT_SYSINFO \ + _head->sysinfo = GLRO(dl_sysinfo) +#else +# define INIT_SYSINFO +#endif + +#ifndef LOCK_PREFIX +# ifdef UP +# define LOCK_PREFIX /* nothing */ +# else +# define LOCK_PREFIX "lock;" +# endif +#endif + +/* Code to initially initialize the thread pointer. This might need + special attention since 'errno' is not yet available and if the + operation can cause a failure 'errno' must not be touched. */ +# define TLS_INIT_TP(thrdescr, secondcall) \ + ({ void *_thrdescr = (thrdescr); \ + tcbhead_t *_head = _thrdescr; \ + union user_desc_init _segdescr; \ + int _result; \ + \ + _head->tcb = _thrdescr; \ + /* For now the thread descriptor is at the same address. */ \ + _head->self = _thrdescr; \ + /* New syscall handling support. */ \ + INIT_SYSINFO; \ + \ + /* The 'entry_number' field. Let the kernel pick a value. */ \ + if (secondcall) \ + _segdescr.vals[0] = TLS_GET_GS () >> 3; \ + else \ + _segdescr.vals[0] = -1; \ + /* The 'base_addr' field. Pointer to the TCB. */ \ + _segdescr.vals[1] = (unsigned long int) _thrdescr; \ + /* The 'limit' field. We use 4GB which is 0xfffff pages. */ \ + _segdescr.vals[2] = 0xfffff; \ + /* Collapsed value of the bitfield: \ + .seg_32bit = 1 \ + .contents = 0 \ + .read_exec_only = 0 \ + .limit_in_pages = 1 \ + .seg_not_present = 0 \ + .useable = 1 */ \ + _segdescr.vals[3] = 0x51; \ + \ + /* Install the TLS. */ \ + __asm__ __volatile__ (TLS_LOAD_EBX \ + "int $0x80\n\t" \ + TLS_LOAD_EBX \ + : "=a" (_result), "=m" (_segdescr.desc.entry_number) \ + : "0" (__NR_set_thread_area), \ + TLS_EBX_ARG (&_segdescr.desc), "m" (_segdescr.desc)); \ + \ + if (_result == 0) \ + /* We know the index in the GDT, now load the segment register. \ + The use of the GDT is described by the value 3 in the lower \ + three bits of the segment descriptor value. \ + \ + Note that we have to do this even if the numeric value of \ + the descriptor does not change. Loading the segment register \ + causes the segment information from the GDT to be loaded \ + which is necessary since we have changed it. */ \ + TLS_SET_GS (_segdescr.desc.entry_number * 8 + 3); \ + \ + _result == 0 ? NULL \ + : "set_thread_area failed when setting up thread-local storage\n"; }) + + +/* Return the address of the dtv for the current thread. */ +# define THREAD_DTV() \ + ({ struct pthread *__pd; \ + THREAD_GETMEM (__pd, header.dtv); }) + + +/* Return the thread descriptor for the current thread. + + The contained asm must *not* be marked __volatile__ since otherwise + assignments like + pthread_descr self = thread_self(); + do not get optimized away. */ +# define THREAD_SELF \ + ({ struct pthread *__self; \ + __asm__ ("movl %%gs:%c1,%0" : "=r" (__self) \ + : "i" (offsetof (struct pthread, header.self))); \ + __self;}) + +/* Magic for libthread_db to know how to do THREAD_SELF. */ +# define DB_THREAD_SELF \ + REGISTER_THREAD_AREA (32, offsetof (struct user_regs_struct, xgs), 3) \ + REGISTER_THREAD_AREA (64, 26 * 8, 3) /* x86-64's user_regs_struct->gs */ + + +/* Read member of the thread descriptor directly. */ +# define THREAD_GETMEM(descr, member) \ + ({ __typeof (descr->member) __value; \ + if (sizeof (__value) == 1) \ + __asm__ __volatile__ ("movb %%gs:%P2,%b0" \ + : "=q" (__value) \ + : "0" (0), "i" (offsetof (struct pthread, member))); \ + else if (sizeof (__value) == 4) \ + __asm__ __volatile__ ("movl %%gs:%P1,%0" \ + : "=r" (__value) \ + : "i" (offsetof (struct pthread, member))); \ + else \ + { \ + if (sizeof (__value) != 8) \ + /* There should not be any value with a size other than 1, \ + 4 or 8. */ \ + abort (); \ + \ + __asm__ __volatile__ ("movl %%gs:%P1,%%eax\n\t" \ + "movl %%gs:%P2,%%edx" \ + : "=A" (__value) \ + : "i" (offsetof (struct pthread, member)), \ + "i" (offsetof (struct pthread, member) + 4)); \ + } \ + __value; }) + + +/* Same as THREAD_GETMEM, but the member offset can be non-constant. */ +# define THREAD_GETMEM_NC(descr, member, idx) \ + ({ __typeof (descr->member[0]) __value; \ + if (sizeof (__value) == 1) \ + __asm__ __volatile__ ("movb %%gs:%P2(%3),%b0" \ + : "=q" (__value) \ + : "0" (0), "i" (offsetof (struct pthread, member[0])), \ + "r" (idx)); \ + else if (sizeof (__value) == 4) \ + __asm__ __volatile__ ("movl %%gs:%P1(,%2,4),%0" \ + : "=r" (__value) \ + : "i" (offsetof (struct pthread, member[0])), \ + "r" (idx)); \ + else \ + { \ + if (sizeof (__value) != 8) \ + /* There should not be any value with a size other than 1, \ + 4 or 8. */ \ + abort (); \ + \ + __asm__ __volatile__ ("movl %%gs:%P1(,%2,8),%%eax\n\t" \ + "movl %%gs:4+%P1(,%2,8),%%edx" \ + : "=&A" (__value) \ + : "i" (offsetof (struct pthread, member[0])), \ + "r" (idx)); \ + } \ + __value; }) + + +/* Same as THREAD_SETMEM, but the member offset can be non-constant. */ +# define THREAD_SETMEM(descr, member, value) \ + ({ if (sizeof (descr->member) == 1) \ + __asm__ __volatile__ ("movb %b0,%%gs:%P1" : \ + : "iq" (value), \ + "i" (offsetof (struct pthread, member))); \ + else if (sizeof (descr->member) == 4) \ + __asm__ __volatile__ ("movl %0,%%gs:%P1" : \ + : "ir" (value), \ + "i" (offsetof (struct pthread, member))); \ + else \ + { \ + if (sizeof (descr->member) != 8) \ + /* There should not be any value with a size other than 1, \ + 4 or 8. */ \ + abort (); \ + \ + __asm__ __volatile__ ("movl %%eax,%%gs:%P1\n\t" \ + "movl %%edx,%%gs:%P2" : \ + : "A" (value), \ + "i" (offsetof (struct pthread, member)), \ + "i" (offsetof (struct pthread, member) + 4)); \ + }}) + + +/* Set member of the thread descriptor directly. */ +# define THREAD_SETMEM_NC(descr, member, idx, value) \ + ({ if (sizeof (descr->member[0]) == 1) \ + __asm__ __volatile__ ("movb %b0,%%gs:%P1(%2)" : \ + : "iq" (value), \ + "i" (offsetof (struct pthread, member)), \ + "r" (idx)); \ + else if (sizeof (descr->member[0]) == 4) \ + __asm__ __volatile__ ("movl %0,%%gs:%P1(,%2,4)" : \ + : "ir" (value), \ + "i" (offsetof (struct pthread, member)), \ + "r" (idx)); \ + else \ + { \ + if (sizeof (descr->member[0]) != 8) \ + /* There should not be any value with a size other than 1, \ + 4 or 8. */ \ + abort (); \ + \ + __asm__ __volatile__ ("movl %%eax,%%gs:%P1(,%2,8)\n\t" \ + "movl %%edx,%%gs:4+%P1(,%2,8)" : \ + : "A" (value), \ + "i" (offsetof (struct pthread, member)), \ + "r" (idx)); \ + }}) + + +/* Atomic compare and exchange on TLS, returning old value. */ +#define THREAD_ATOMIC_CMPXCHG_VAL(descr, member, newval, oldval) \ + ({ __typeof (descr->member) __ret; \ + __typeof (oldval) __old = (oldval); \ + if (sizeof (descr->member) == 4) \ + __asm__ __volatile__ (LOCK_PREFIX "cmpxchgl %2, %%gs:%P3" \ + : "=a" (__ret) \ + : "0" (__old), "r" (newval), \ + "i" (offsetof (struct pthread, member))); \ + else \ + /* Not necessary for other sizes in the moment. */ \ + abort (); \ + __ret; }) + + +/* Atomic logical and. */ +#define THREAD_ATOMIC_AND(descr, member, val) \ + (void) ({ if (sizeof ((descr)->member) == 4) \ + __asm__ __volatile__ (LOCK_PREFIX "andl %1, %%gs:%P0" \ + :: "i" (offsetof (struct pthread, member)), \ + "ir" (val)); \ + else \ + /* Not necessary for other sizes in the moment. */ \ + abort (); }) + + +/* Atomic set bit. */ +#define THREAD_ATOMIC_BIT_SET(descr, member, bit) \ + (void) ({ if (sizeof ((descr)->member) == 4) \ + __asm__ __volatile__ (LOCK_PREFIX "orl %1, %%gs:%P0" \ + :: "i" (offsetof (struct pthread, member)), \ + "ir" (1 << (bit))); \ + else \ + /* Not necessary for other sizes in the moment. */ \ + abort (); }) + + +/* Call the user-provided thread function. */ +#define CALL_THREAD_FCT(descr) \ + ({ void *__res; \ + int __ignore1, __ignore2; \ + __asm__ __volatile__ ("pushl %%eax\n\t" \ + "pushl %%eax\n\t" \ + "pushl %%eax\n\t" \ + "pushl %%gs:%P4\n\t" \ + "call *%%gs:%P3\n\t" \ + "addl $16, %%esp" \ + : "=a" (__res), "=c" (__ignore1), "=d" (__ignore2) \ + : "i" (offsetof (struct pthread, start_routine)), \ + "i" (offsetof (struct pthread, arg))); \ + __res; }) + + +/* Set the stack guard field in TCB head. */ +#define THREAD_SET_STACK_GUARD(value) \ + THREAD_SETMEM (THREAD_SELF, header.stack_guard, value) +#define THREAD_COPY_STACK_GUARD(descr) \ + ((descr)->header.stack_guard \ + = THREAD_GETMEM (THREAD_SELF, header.stack_guard)) + + +/* Set the pointer guard field in the TCB head. */ +#define THREAD_SET_POINTER_GUARD(value) \ + THREAD_SETMEM (THREAD_SELF, header.pointer_guard, value) +#define THREAD_COPY_POINTER_GUARD(descr) \ + ((descr)->header.pointer_guard \ + = THREAD_GETMEM (THREAD_SELF, header.pointer_guard)) + + +/* Get and set the global scope generation counter in the TCB head. */ +#define THREAD_GSCOPE_FLAG_UNUSED 0 +#define THREAD_GSCOPE_FLAG_USED 1 +#define THREAD_GSCOPE_FLAG_WAIT 2 +#define THREAD_GSCOPE_RESET_FLAG() \ + do \ + { int __res; \ + __asm__ __volatile__ ("xchgl %0, %%gs:%P1" \ + : "=r" (__res) \ + : "i" (offsetof (struct pthread, header.gscope_flag)), \ + "0" (THREAD_GSCOPE_FLAG_UNUSED)); \ + if (__res == THREAD_GSCOPE_FLAG_WAIT) \ + lll_futex_wake (&THREAD_SELF->header.gscope_flag, 1, LLL_PRIVATE); \ + } \ + while (0) +#define THREAD_GSCOPE_SET_FLAG() \ + THREAD_SETMEM (THREAD_SELF, header.gscope_flag, THREAD_GSCOPE_FLAG_USED) +#define THREAD_GSCOPE_WAIT() \ + GL(dl_wait_lookup_done) () + +#endif /* __ASSEMBLER__ */ + +#endif /* tls.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/mips/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/mips/Makefile new file mode 100644 index 00000000..6371d287 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/mips/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc NPTL +# +# Copyright (C) 2005 Steven J. Hill +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../../ +top_builddir=../../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.arch +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/mips/Makefile.arch b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/mips/Makefile.arch new file mode 100644 index 00000000..2762a2fe --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/mips/Makefile.arch @@ -0,0 +1,17 @@ +# Makefile for uClibc NPTL +# +# Copyright (C) 2005 Steven J. Hill +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +CFLAGS-pt-raise.c = -DNOT_IN_libc -DIS_IN_libpthread + +ASFLAGS-pthread_spin_lock.S = -DNOT_IN_libc -DIS_IN_libpthread +ASFLAGS-pthread_spin_trylock.S = -DNOT_IN_libc -DIS_IN_libpthread +ASFLAGS-nptl-sysdep.S = -DNOT_IN_libc -DIS_IN_libpthread \ + -D_LIBC_REENTRANT \ + -I$(top_srcdir)libc/sysdeps/linux/mips + +libc_arch_a_CSRC = libc-tls.c + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/mips/dl-tls.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/mips/dl-tls.h new file mode 100644 index 00000000..3ad3b2bc --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/mips/dl-tls.h @@ -0,0 +1,46 @@ +/* Thread-local storage handling in the ELF dynamic linker. MIPS version. + Copyright (C) 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + + +/* Type used for the representation of TLS information in the GOT. */ +typedef struct +{ + unsigned long int ti_module; + unsigned long int ti_offset; +} tls_index; + +/* The thread pointer points 0x7000 past the first static TLS block. */ +#define TLS_TP_OFFSET 0x7000 + +/* Dynamic thread vector pointers point 0x8000 past the start of each + TLS block. */ +#define TLS_DTV_OFFSET 0x8000 + +/* Compute the value for a GOTTPREL reloc. */ +#define TLS_TPREL_VALUE(sym_map, sym_val) \ + ((sym_map)->l_tls_offset + sym_val - TLS_TP_OFFSET) + +/* Compute the value for a DTPREL reloc. */ +#define TLS_DTPREL_VALUE(sym_val) \ + (sym_val - TLS_DTV_OFFSET) + +extern void *__tls_get_addr (tls_index *ti); + +# define GET_ADDR_OFFSET (ti->ti_offset + TLS_DTV_OFFSET) +# define __TLS_GET_ADDR(__ti) (__tls_get_addr (__ti) - TLS_DTV_OFFSET) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/mips/jmpbuf-unwind.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/mips/jmpbuf-unwind.h new file mode 100644 index 00000000..a9cfe43b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/mips/jmpbuf-unwind.h @@ -0,0 +1,30 @@ +/* Copyright (C) 2003, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +#define _JMPBUF_CFA_UNWINDS_ADJ(_jmpbuf, _context, _adj) \ + _JMPBUF_UNWINDS_ADJ (_jmpbuf, (void *) _Unwind_GetCFA (_context), _adj) + +#define _JMPBUF_UNWINDS_ADJ(_jmpbuf, _address, _adj) \ + ((uintptr_t) (_address) - (_adj) < (uintptr_t) (_jmpbuf)[0].__sp - (_adj)) + +/* We use the normal longjmp for unwinding. */ +#define __libc_unwind_longjmp(buf, val) longjmp (buf, val) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/mips/libc-tls.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/mips/libc-tls.c new file mode 100644 index 00000000..157ba338 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/mips/libc-tls.c @@ -0,0 +1,37 @@ +/* Thread-local storage handling in the ELF dynamic linker. MIPS version. + Copyright (C) 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +#if USE_TLS + +/* On MIPS, linker optimizations are not required, so __tls_get_addr + can be called even in statically linked binaries. In this case module + must be always 1 and PT_TLS segment exist in the binary, otherwise it + would not link. */ + +void * +__tls_get_addr (tls_index *ti) +{ + dtv_t *dtv = THREAD_DTV (); + return (char *) dtv[1].pointer.val + GET_ADDR_OFFSET; +} + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/mips/nptl-sysdep.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/mips/nptl-sysdep.S new file mode 100644 index 00000000..7a4a8d31 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/mips/nptl-sysdep.S @@ -0,0 +1,2 @@ +/* Pull in __syscall_error. */ +#include diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/mips/pthread_spin_lock.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/mips/pthread_spin_lock.S new file mode 100644 index 00000000..e35c381e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/mips/pthread_spin_lock.S @@ -0,0 +1,38 @@ +/* Copyright (C) 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +ENTRY (pthread_spin_lock) + .set push +#if _MIPS_SIM == _ABIO32 + .set mips2 +#endif +1: ll a2, 0(a0) + li a1, 1 + bnez a2, 1b + sc a1, 0(a0) + beqz a1, 1b + MIPS_SYNC + .set pop + li v0, 0 + j ra + nop +END (pthread_spin_lock) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/mips/pthread_spin_trylock.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/mips/pthread_spin_trylock.S new file mode 100644 index 00000000..b5473286 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/mips/pthread_spin_trylock.S @@ -0,0 +1,43 @@ +/* Copyright (C) 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#define _ERRNO_H 1 +#include +#include + +ENTRY (pthread_spin_trylock) + .set push +#if _MIPS_SIM == _ABIO32 + .set mips2 +#endif + ll a2, 0(a0) + li a1, 1 + bnez a2, 1f + sc a1, 0(a0) + beqz a1, 1f + MIPS_SYNC + .set pop + li v0, 0 + j ra + nop +1: li v0, EBUSY + j ra + nop +END (pthread_spin_trylock) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/mips/pthreaddef.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/mips/pthreaddef.h new file mode 100644 index 00000000..e72b4bc5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/mips/pthreaddef.h @@ -0,0 +1,39 @@ +/* Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Default stack size. */ +#define ARCH_STACK_DEFAULT_SIZE (2 * 1024 * 1024) + +/* Required stack pointer alignment at beginning. */ +#define STACK_ALIGN 16 + +/* Minimal stack size after allocating thread descriptor and guard size. */ +#define MINIMAL_REST_STACK 2048 + +/* Alignment requirement for TCB. */ +#define TCB_ALIGNMENT 16 + + +/* Location of current stack frame. */ +#define CURRENT_STACK_FRAME __builtin_frame_address (0) + + +/* XXX Until we have a better place keep the definitions here. */ + +#define __exit_thread_inline(val) \ + INLINE_SYSCALL (exit, 1, (val)) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/mips/regdef.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/mips/regdef.h new file mode 100644 index 00000000..a462d512 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/mips/regdef.h @@ -0,0 +1,26 @@ +/* Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ralf Baechle . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _REGDEF_H +#define _REGDEF_H + +#include +#include + +#endif /* _REGDEF_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/mips/tcb-offsets.sym b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/mips/tcb-offsets.sym new file mode 100644 index 00000000..e0e71dc4 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/mips/tcb-offsets.sym @@ -0,0 +1,11 @@ +#include +#include + +-- + +-- Abuse tls.h macros to derive offsets relative to the thread register. +#define thread_offsetof(mem) (long)(offsetof(struct pthread, mem) - TLS_TCB_OFFSET - TLS_PRE_TCB_SIZE) + +MULTIPLE_THREADS_OFFSET thread_offsetof (header.multiple_threads) +PID_OFFSET thread_offsetof (pid) +TID_OFFSET thread_offsetof (tid) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/mips/tls.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/mips/tls.h new file mode 100644 index 00000000..27b1c15d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/mips/tls.h @@ -0,0 +1,181 @@ +/* Definition for thread-local data handling. NPTL/MIPS version. + Copyright (C) 2005, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _TLS_H +#define _TLS_H 1 + +#ifndef __ASSEMBLER__ +# include +# include +# include + +/* Type for the dtv. */ +typedef union dtv +{ + size_t counter; + struct + { + void *val; + bool is_static; + } pointer; +} dtv_t; + +/* Note: rd must be $v1 to be ABI-conformant. */ +# define READ_THREAD_POINTER() \ + ({ void *__result; \ + __asm__ __volatile__ (".set\tpush\n\t.set\tmips32r2\n\t" \ + "rdhwr\t%0, $29\n\t.set\tpop" : "=v" (__result)); \ + __result; }) + +#else /* __ASSEMBLER__ */ +# include + +# define READ_THREAD_POINTER(rd) \ + .set push; \ + .set mips32r2; \ + rdhwr rd, $29; \ + .set pop +#endif /* __ASSEMBLER__ */ + + +/* We require TLS support in the tools. */ +#define HAVE_TLS_SUPPORT 1 +#define HAVE_TLS_MODEL_ATTRIBUTE 1 +#define HAVE___THREAD 1 + +/* Signal that TLS support is available. */ +#define USE_TLS 1 + +#ifndef __ASSEMBLER__ + +/* Get system call information. */ +# include + +/* The TP points to the start of the thread blocks. */ +# define TLS_DTV_AT_TP 1 + +/* Get the thread descriptor definition. */ +#include <../../descr.h> + +typedef struct +{ + dtv_t *dtv; + void *private; +} tcbhead_t; + +/* This is the size of the initial TCB. Because our TCB is before the thread + pointer, we don't need this. */ +# define TLS_INIT_TCB_SIZE 0 + +/* Alignment requirements for the initial TCB. */ +# define TLS_INIT_TCB_ALIGN __alignof__ (struct pthread) + +/* This is the size of the TCB. Because our TCB is before the thread + pointer, we don't need this. */ +# define TLS_TCB_SIZE 0 + +/* Alignment requirements for the TCB. */ +# define TLS_TCB_ALIGN __alignof__ (struct pthread) + +/* This is the size we need before TCB - actually, it includes the TCB. */ +# define TLS_PRE_TCB_SIZE \ + (sizeof (struct pthread) \ + + ((sizeof (tcbhead_t) + TLS_TCB_ALIGN - 1) & ~(TLS_TCB_ALIGN - 1))) + +/* The thread pointer (in hardware register $29) points to the end of + the TCB + 0x7000, as for PowerPC. The pthread_descr structure is + immediately in front of the TCB. */ +# define TLS_TCB_OFFSET 0x7000 + +/* Install the dtv pointer. The pointer passed is to the element with + index -1 which contain the length. */ +# define INSTALL_DTV(tcbp, dtvp) \ + (((tcbhead_t *) (tcbp))[-1].dtv = (dtvp) + 1) + +/* Install new dtv for current thread. */ +# define INSTALL_NEW_DTV(dtv) \ + (THREAD_DTV() = (dtv)) + +/* Return dtv of given thread descriptor. */ +# define GET_DTV(tcbp) \ + (((tcbhead_t *) (tcbp))[-1].dtv) + +/* Code to initially initialize the thread pointer. This might need + special attention since 'errno' is not yet available and if the + operation can cause a failure 'errno' must not be touched. */ +# define TLS_INIT_TP(tcbp, secondcall) \ + ({ INTERNAL_SYSCALL_DECL (err); \ + long result_var; \ + result_var = INTERNAL_SYSCALL (set_thread_area, err, 1, \ + (char *) (tcbp) + TLS_TCB_OFFSET); \ + INTERNAL_SYSCALL_ERROR_P (result_var, err) \ + ? "unknown error" : NULL; }) + +/* Return the address of the dtv for the current thread. */ +# define THREAD_DTV() \ + (((tcbhead_t *) (READ_THREAD_POINTER () - TLS_TCB_OFFSET))[-1].dtv) + +/* Return the thread descriptor for the current thread. */ +# define THREAD_SELF \ + ((struct pthread *) (READ_THREAD_POINTER () \ + - TLS_TCB_OFFSET - TLS_PRE_TCB_SIZE)) + +/* Magic for libthread_db to know how to do THREAD_SELF. */ +# define DB_THREAD_SELF \ + CONST_THREAD_AREA (32, TLS_TCB_OFFSET + TLS_PRE_TCB_SIZE) + +/* Access to data in the thread descriptor is easy. */ +# define THREAD_GETMEM(descr, member) \ + descr->member +# define THREAD_GETMEM_NC(descr, member, idx) \ + descr->member[idx] +# define THREAD_SETMEM(descr, member, value) \ + descr->member = (value) +# define THREAD_SETMEM_NC(descr, member, idx, value) \ + descr->member[idx] = (value) + +/* l_tls_offset == 0 is perfectly valid on MIPS, so we have to use some + different value to mean unset l_tls_offset. */ +# define NO_TLS_OFFSET -1 +/* Get and set the global scope generation counter in struct pthread. */ +#define THREAD_GSCOPE_FLAG_UNUSED 0 +#define THREAD_GSCOPE_FLAG_USED 1 +#define THREAD_GSCOPE_FLAG_WAIT 2 +#define THREAD_GSCOPE_RESET_FLAG() \ + do \ + { int __res \ + = atomic_exchange_rel (&THREAD_SELF->header.gscope_flag, \ + THREAD_GSCOPE_FLAG_UNUSED); \ + if (__res == THREAD_GSCOPE_FLAG_WAIT) \ + lll_futex_wake (&THREAD_SELF->header.gscope_flag, 1, LLL_PRIVATE); \ + } \ + while (0) +#define THREAD_GSCOPE_SET_FLAG() \ + do \ + { \ + THREAD_SELF->header.gscope_flag = THREAD_GSCOPE_FLAG_USED; \ + atomic_write_barrier (); \ + } \ + while (0) +#define THREAD_GSCOPE_WAIT() \ + GL(dl_wait_lookup_done) () + +#endif /* __ASSEMBLER__ */ + +#endif /* tls.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/powerpc/Makefile.arch b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/powerpc/Makefile.arch new file mode 100644 index 00000000..18ddc28e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/powerpc/Makefile.arch @@ -0,0 +1,7 @@ +# Makefile for uClibc NPTL +# +# Copyright (C) 2009 Bernhard Reutner-Fischer +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/powerpc/dl-tls.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/powerpc/dl-tls.h new file mode 100644 index 00000000..957d4b4b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/powerpc/dl-tls.h @@ -0,0 +1,49 @@ +/* Thread-local storage handling in the ELF dynamic linker. PowerPC version. + Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + + +/* Type used for the representation of TLS information in the TOC. */ +typedef struct +{ + unsigned long int ti_module; + unsigned long int ti_offset; +} tls_index; + +/* The thread pointer points 0x7000 past the first static TLS block. */ +#define TLS_TP_OFFSET 0x7000 + +/* Dynamic thread vector pointers point 0x8000 past the start of each + TLS block. */ +#define TLS_DTV_OFFSET 0x8000 + +/* Compute the value for a @tprel reloc. */ +#define TLS_TPREL_VALUE(sym_map, sym, reloc) \ + ((sym_map)->l_tls_offset + (sym)->st_value + (reloc)->r_addend \ + - TLS_TP_OFFSET) + +/* Compute the value for a @dtprel reloc. */ +#define TLS_DTPREL_VALUE(sym, reloc) \ + ((sym)->st_value + (reloc)->r_addend - TLS_DTV_OFFSET) + +#ifdef SHARED +extern void *__tls_get_addr (tls_index *ti); + +# define GET_ADDR_OFFSET (ti->ti_offset + TLS_DTV_OFFSET) +# define __TLS_GET_ADDR(__ti) (__tls_get_addr (__ti) - TLS_DTV_OFFSET) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/powerpc/jmpbuf-unwind.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/powerpc/jmpbuf-unwind.h new file mode 100644 index 00000000..0b817160 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/powerpc/jmpbuf-unwind.h @@ -0,0 +1,31 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +#define _JMPBUF_CFA_UNWINDS_ADJ(_jmpbuf, _context, _adj) \ + _JMPBUF_UNWINDS_ADJ (_jmpbuf, (void *) _Unwind_GetCFA (_context), _adj) + +#define _JMPBUF_UNWINDS_ADJ(_jmpbuf, _address, _adj) \ + ((uintptr_t) (_address) - (_adj) < (uintptr_t) (_jmpbuf)[JB_GPR1] - (_adj)) + +/* We use the normal lobngjmp for unwinding. */ +#define __libc_unwind_longjmp(buf, val) __libc_longjmp (buf, val) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/powerpc/pthread_spin_lock.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/powerpc/pthread_spin_lock.c new file mode 100644 index 00000000..9334d421 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/powerpc/pthread_spin_lock.c @@ -0,0 +1,44 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Paul Mackerras , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "pthreadP.h" + +int +pthread_spin_lock (pthread_spinlock_t *lock) +{ + unsigned int __tmp; + + __asm__ __volatile__ ( + "1: lwarx %0,0,%1\n" + " cmpwi 0,%0,0\n" + " bne- 2f\n" + " stwcx. %2,0,%1\n" + " bne- 2f\n" + " isync\n" + " .subsection 1\n" + "2: lwzx %0,0,%1\n" + " cmpwi 0,%0,0\n" + " bne 2b\n" + " b 1b\n" + " .previous" + : "=&r" (__tmp) + : "r" (lock), "r" (1) + : "cr0", "memory"); + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/powerpc/pthread_spin_trylock.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/powerpc/pthread_spin_trylock.c new file mode 100644 index 00000000..a2757e20 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/powerpc/pthread_spin_trylock.c @@ -0,0 +1,42 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Paul Mackerras , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include "pthreadP.h" + +int +pthread_spin_trylock (pthread_spinlock_t *lock) +{ + unsigned int old; + int err = EBUSY; + + __asm__ ("1: lwarx %0,0,%2\n" + " cmpwi 0,%0,0\n" + " bne 2f\n" + " stwcx. %3,0,%2\n" + " bne- 1b\n" + " li %1,0\n" + " isync\n" + "2: " + : "=&r" (old), "=&r" (err) + : "r" (lock), "r" (1), "1" (err) + : "cr0", "memory"); + + return err; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/powerpc/pthreaddef.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/powerpc/pthreaddef.h new file mode 100644 index 00000000..342c15c6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/powerpc/pthreaddef.h @@ -0,0 +1,41 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Default stack size. */ +#define ARCH_STACK_DEFAULT_SIZE (4 * 1024 * 1024) + +/* Required stack pointer alignment at beginning. The ABI requires 16 + bytes (for both 32-bit and 64-bit PowerPC). */ +#define STACK_ALIGN 16 + +/* Minimal stack size after allocating thread descriptor and guard size. */ +#define MINIMAL_REST_STACK 4096 + +/* Alignment requirement for TCB. */ +#define TCB_ALIGNMENT 16 + + +/* Location of current stack frame. */ +#define CURRENT_STACK_FRAME __builtin_frame_address (0) + + +/* XXX Until we have a better place keep the definitions here. */ + +/* While there is no such syscall. */ +#define __exit_thread_inline(val) \ + INLINE_SYSCALL (exit, 1, (val)) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/powerpc/tcb-offsets.sym b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/powerpc/tcb-offsets.sym new file mode 100644 index 00000000..8ac133df --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/powerpc/tcb-offsets.sym @@ -0,0 +1,20 @@ +#include +#include + +-- + +-- Abuse tls.h macros to derive offsets relative to the thread register. +# undef __thread_register +# define __thread_register ((void *) 0) +# define thread_offsetof(mem) ((ptrdiff_t) THREAD_SELF + offsetof (struct pthread, mem)) + + +#if TLS_MULTIPLE_THREADS_IN_TCB +MULTIPLE_THREADS_OFFSET thread_offsetof (header.multiple_threads) +#endif +PID thread_offsetof (pid) +TID thread_offsetof (tid) +POINTER_GUARD (offsetof (tcbhead_t, pointer_guard) - TLS_TCB_OFFSET - sizeof (tcbhead_t)) +#ifndef __ASSUME_PRIVATE_FUTEX +PRIVATE_FUTEX_OFFSET thread_offsetof (header.private_futex) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/powerpc/tls.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/powerpc/tls.h new file mode 100644 index 00000000..990972ea --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/powerpc/tls.h @@ -0,0 +1,216 @@ +/* Definition for thread-local data handling. NPTL/PowerPC version. + Copyright (C) 2003, 2005, 2006, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _TLS_H +#define _TLS_H 1 + +#ifndef __ASSEMBLER__ +# include +# include +# include + +/* Type for the dtv. */ +typedef union dtv +{ + size_t counter; + struct + { + void *val; + bool is_static; + } pointer; +} dtv_t; + +#else /* __ASSEMBLER__ */ +# include +#endif /* __ASSEMBLER__ */ + +/* We require TLS support in the tools. */ +#define HAVE_TLS_SUPPORT 1 +#define HAVE_TLS_MODEL_ATTRIBUTE 1 +#define HAVE___THREAD 1 + +/* Signal that TLS support is available. */ +#define USE_TLS 1 + +/* We require TLS support in the tools. */ +#ifndef HAVE_TLS_SUPPORT +# error "TLS support is required." +#endif + +/* Signal that TLS support is available. */ +# define USE_TLS 1 + +#ifndef __ASSEMBLER__ + +/* Get system call information. */ +# include + +/* The TP points to the start of the thread blocks. */ +# define TLS_DTV_AT_TP 1 + +/* We use the multiple_threads field in the pthread struct */ +#define TLS_MULTIPLE_THREADS_IN_TCB 1 + +/* Get the thread descriptor definition. */ +# include <../../descr.h> + +/* The stack_guard is accessed directly by GCC -fstack-protector code, + so it is a part of public ABI. The dtv and pointer_guard fields + are private. */ +typedef struct +{ + uintptr_t pointer_guard; + uintptr_t stack_guard; + dtv_t *dtv; +} tcbhead_t; + +/* This is the size of the initial TCB. */ +# define TLS_INIT_TCB_SIZE 0 + +/* Alignment requirements for the initial TCB. */ +# define TLS_INIT_TCB_ALIGN __alignof__ (struct pthread) + +/* This is the size of the TCB. */ +# define TLS_TCB_SIZE 0 + +/* Alignment requirements for the TCB. */ +# define TLS_TCB_ALIGN __alignof__ (struct pthread) + +/* This is the size we need before TCB. */ +# define TLS_PRE_TCB_SIZE \ + (sizeof (struct pthread) \ + + ((sizeof (tcbhead_t) + TLS_TCB_ALIGN - 1) & ~(TLS_TCB_ALIGN - 1))) + +# ifndef __powerpc64__ +/* Register r2 (tp) is reserved by the ABI as "thread pointer". */ +register void *__thread_register __asm__ ("r2"); +# define PT_THREAD_POINTER PT_R2 +# else +/* Register r13 (tp) is reserved by the ABI as "thread pointer". */ +register void *__thread_register __asm__ ("r13"); +# define PT_THREAD_POINTER PT_R13 +# endif + +/* The following assumes that TP (R2 or R13) points to the end of the + TCB + 0x7000 (per the ABI). This implies that TCB address is + TP - 0x7000. As we define TLS_DTV_AT_TP we can + assume that the pthread struct is allocated immediately ahead of the + TCB. This implies that the pthread_descr address is + TP - (TLS_PRE_TCB_SIZE + 0x7000). */ +# define TLS_TCB_OFFSET 0x7000 + +/* Install the dtv pointer. The pointer passed is to the element with + index -1 which contain the length. */ +# define INSTALL_DTV(tcbp, dtvp) \ + ((tcbhead_t *) (tcbp))[-1].dtv = dtvp + 1 + +/* Install new dtv for current thread. */ +# define INSTALL_NEW_DTV(dtv) (THREAD_DTV() = (dtv)) + +/* Return dtv of given thread descriptor. */ +# define GET_DTV(tcbp) (((tcbhead_t *) (tcbp))[-1].dtv) + +/* Code to initially initialize the thread pointer. This might need + special attention since 'errno' is not yet available and if the + operation can cause a failure 'errno' must not be touched. */ +# define TLS_INIT_TP(tcbp, secondcall) \ + (__thread_register = (void *) (tcbp) + TLS_TCB_OFFSET, NULL) + +/* Return the address of the dtv for the current thread. */ +# define THREAD_DTV() \ + (((tcbhead_t *) (__thread_register - TLS_TCB_OFFSET))[-1].dtv) + +/* Return the thread descriptor for the current thread. */ +# define THREAD_SELF \ + ((struct pthread *) (__thread_register \ + - TLS_TCB_OFFSET - TLS_PRE_TCB_SIZE)) + +/* Magic for libthread_db to know how to do THREAD_SELF. */ +# define DB_THREAD_SELF \ + REGISTER (32, 32, PT_THREAD_POINTER * 4, \ + - TLS_TCB_OFFSET - TLS_PRE_TCB_SIZE) \ + REGISTER (64, 64, PT_THREAD_POINTER * 8, \ + - TLS_TCB_OFFSET - TLS_PRE_TCB_SIZE) + +/* Read member of the thread descriptor directly. */ +# define THREAD_GETMEM(descr, member) ((void)(descr), (THREAD_SELF)->member) + +/* Same as THREAD_GETMEM, but the member offset can be non-constant. */ +# define THREAD_GETMEM_NC(descr, member, idx) \ + ((void)(descr), (THREAD_SELF)->member[idx]) + +/* Set member of the thread descriptor directly. */ +# define THREAD_SETMEM(descr, member, value) \ + ((void)(descr), (THREAD_SELF)->member = (value)) + +/* Same as THREAD_SETMEM, but the member offset can be non-constant. */ +# define THREAD_SETMEM_NC(descr, member, idx, value) \ + ((void)(descr), (THREAD_SELF)->member[idx] = (value)) + +/* Set the stack guard field in TCB head. */ +# define THREAD_SET_STACK_GUARD(value) \ + (((tcbhead_t *) ((char *) __thread_register \ + - TLS_TCB_OFFSET))[-1].stack_guard = (value)) +# define THREAD_COPY_STACK_GUARD(descr) \ + (((tcbhead_t *) ((char *) (descr) \ + + TLS_PRE_TCB_SIZE))[-1].stack_guard \ + = ((tcbhead_t *) ((char *) __thread_register \ + - TLS_TCB_OFFSET))[-1].stack_guard) + +/* Set the stack guard field in TCB head. */ +# define THREAD_GET_POINTER_GUARD() \ + (((tcbhead_t *) ((char *) __thread_register \ + - TLS_TCB_OFFSET))[-1].pointer_guard) +# define THREAD_SET_POINTER_GUARD(value) \ + (THREAD_GET_POINTER_GUARD () = (value)) +# define THREAD_COPY_POINTER_GUARD(descr) \ + (((tcbhead_t *) ((char *) (descr) \ + + TLS_PRE_TCB_SIZE))[-1].pointer_guard \ + = THREAD_GET_POINTER_GUARD()) + +/* l_tls_offset == 0 is perfectly valid on PPC, so we have to use some + different value to mean unset l_tls_offset. */ +# define NO_TLS_OFFSET -1 + +/* Get and set the global scope generation counter in struct pthread. */ +#define THREAD_GSCOPE_FLAG_UNUSED 0 +#define THREAD_GSCOPE_FLAG_USED 1 +#define THREAD_GSCOPE_FLAG_WAIT 2 +#define THREAD_GSCOPE_RESET_FLAG() \ + do \ + { int __res \ + = atomic_exchange_rel (&THREAD_SELF->header.gscope_flag, \ + THREAD_GSCOPE_FLAG_UNUSED); \ + if (__res == THREAD_GSCOPE_FLAG_WAIT) \ + lll_futex_wake (&THREAD_SELF->header.gscope_flag, 1, LLL_PRIVATE); \ + } \ + while (0) +#define THREAD_GSCOPE_SET_FLAG() \ + do \ + { \ + THREAD_SELF->header.gscope_flag = THREAD_GSCOPE_FLAG_USED; \ + atomic_write_barrier (); \ + } \ + while (0) +#define THREAD_GSCOPE_WAIT() \ + GL(dl_wait_lookup_done) () + +#endif /* __ASSEMBLER__ */ + +#endif /* tls.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/Makefile new file mode 100644 index 00000000..a30ded52 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc NPTL +# +# Copyright (C) 2005 Steven J. Hill +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../../ +top_builddir=../../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/Makefile.in new file mode 100644 index 00000000..fc0c6ac3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/Makefile.in @@ -0,0 +1,109 @@ +# Makefile for uClibc NPTL +# +# Copyright (C) 2005-2006 Steven J. Hill +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +subdirs += libpthread/nptl/sysdeps/pthread +# +# NOTE: glibc puts flockfile.c, ftrylockfile.c, funlockfile.c, and +# pt-longjmp.c in libc and libpthread. For uClibc, they are +# in libc only. +# +libpthread_pthread_DIR = $(top_srcdir)libpthread/nptl/sysdeps/pthread +libpthread_pthread_OUT = $(top_builddir)libpthread/nptl/sysdeps/pthread + +libpthread_pthread_COBJ = $(patsubst %.c,$(libpthread_pthread_OUT)/%.o,$(libpthread_pthread_CSRC)) +libpthread_pthread_CSRC = \ + pthread_barrier_destroy.c \ + pthread_barrier_init.c \ + pthread_barrier_wait.c \ + pthread_cond_broadcast.c \ + pthread_cond_signal.c \ + pthread_cond_timedwait.c \ + pthread_cond_wait.c \ + pthread_rwlock_rdlock.c \ + pthread_rwlock_timedrdlock.c \ + pthread_rwlock_timedwrlock.c \ + pthread_rwlock_unlock.c \ + pthread_rwlock_wrlock.c \ + pthread_sigmask.c \ + pthread_spin_destroy.c \ + pthread_spin_init.c \ + pthread_spin_unlock.c \ + pt-longjmp.c \ + pt-sigaction.c \ + pt-sigfillset.c \ + pt-sigprocmask.c \ + tpp.c +CFLAGS-pthread = $(SSP_ALL_CFLAGS) -DNOT_IN_libc -DIS_IN_libpthread +CFLAGS-pthread_barrier_wait.c = -D_GNU_SOURCE +CFLAGS-pthread_spin_destroy.c = -D_GNU_SOURCE +CFLAGS-pthread_spin_init.c = -D_GNU_SOURCE +CFLAGS-pthread_spin_unlock.c = -D_GNU_SOURCE +CFLAGS-pt-sigaction.c = -I$(top_srcdir)libc/sysdeps/linux/$(TARGET_ARCH) \ + -I$(top_srcdir)libc/signal +CFLAGS-pt-sigfillset.c = -I$(top_srcdir)libc/signal +CFLAGS-pt-sigprocmask.c = -I$(top_srcdir)libc/sysdeps/linux/common +CFLAGS-unwind-forcedunwind.c = -fexceptions -fasynchronous-unwind-tables + +CFLAGS-OMIT-librt-cancellation.c = -DIS_IN_libpthread +CFLAGS-OMIT-rt-unwind-resume.c = -DIS_IN_libpthread +CFLAGS-librt-cancellation.c = -DIS_IN_librt \ + -fexceptions -fasynchronous-unwind-tables +CFLAGS-rt-unwind-resume.c = -DIS_IN_librt \ + -fexceptions -fasynchronous-unwind-tables + +libpthread-so-y += $(patsubst %,$(libpthread_pthread_OUT)/%.oS, \ + pt-sigaction pt-sigprocmask unwind-forcedunwind) + +CFLAGS-OMIT-sigaction.c = $(CFLAGS-pthread) +CFLAGS-sigaction.c = -I$(top_srcdir)libc/signal +libc-y += $(libpthread_pthread_OUT)/sigaction.o + +librt-pt-routines-y = librt-cancellation.c +librt-pt-shared-only-routines-y = rt-unwind-resume.c + +ifeq ($(UCLIBC_CTOR_DTOR),y) +CFLAGS-OMIT-pt-initfini.c = $(CFLAGS-pthread) +CFLAGS-pt-initfini.c = -S -g0 -fPIC -fno-inline-functions \ + $(call check_gcc,-fno-unit-at-a-time,) \ + -finhibit-size-directive \ + $(patsubst -f%,-fno-%,$(call check_gcc,-fexceptions,)) +ASFLAGS-crti.S = -g0 +ASFLAGS-crtn.S = -g0 + +$(libpthread_pthread_OUT)/pt-initfini.s: $(libpthread_pthread_DIR)/pt-initfini.c + $(compile.c) + $(do_sed) '/@TESTS_BEGIN/,/@TESTS_END/p' $< | \ + $(do_awk) $(libpthread_pthread_DIR)/defs.awk > $(libpthread_pthread_OUT)/defs.h + +$(libpthread_pthread_OUT)/crti.S $(libpthread_pthread_OUT)/crtn.S: $(libpthread_pthread_OUT)/pt-initfini.s + $(do_sed) -e '1,/@HEADER_ENDS/p' \ + -e '/@_.*_PROLOG_BEGINS/,/@_.*_PROLOG_ENDS/p' \ + -e '/@TRAILER_BEGINS/,$$p' $< > $@ +endif +# It would have been easier to just add dummy files that include the real +# impl, but ok. +# Special rules needed since we do objdir->objdir compilation for these 3. +# First symlink them, then build them. Rob would freak out on these. Sheesh! ;) +pthread-lc-fwd = sigaction sigfillset sigprocmask +$(patsubst %,$(libpthread_pthread_OUT)/pt-%.c,$(pthread-lc-fwd)): | $(libpthread_pthread_OUT) + $(do_ln) $(call rel_srcdir)$(patsubst pt-%,$(libpthread_pthread_DIR)/%,$(@F)) $@ +$(patsubst %,$(libpthread_pthread_OUT)/pt-%.oS,$(pthread-lc-fwd)): $(libpthread_pthread_OUT)/pt-%.oS: $(libpthread_pthread_OUT)/pt-%.c + $(compile.c) +$(patsubst %,$(libpthread_pthread_OUT)/pt-%.o,$(pthread-lc-fwd)): $(libpthread_pthread_OUT)/pt-%.o: $(libpthread_pthread_OUT)/pt-%.c + $(compile.c) +ifeq ($(DOPIC),y) +$(patsubst %,$(libpthread_pthread_OUT)/pt-%.os,$(pthread-lc-fwd)): $(libpthread_pthread_OUT)/pt-%.os: $(libpthread_pthread_OUT)/pt-%.c + $(compile.c) +endif + +objclean-y += CLEAN_libpthread/nptl/sysdeps/pthread + +CLEAN_libpthread/nptl/sysdeps/pthread: + $(do_rm) $(addprefix $(libpthread_pthread_OUT)/*., o os oS s S) \ + $(libpthread_pthread_OUT)/defs.h \ + $(addprefix $(libpthread_pthread_DIR)/,pt-sigaction.c \ + pt-sigfillset.c pt-sigprocmask.c) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/allocalim.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/allocalim.h new file mode 100644 index 00000000..f13c3a33 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/allocalim.h @@ -0,0 +1,30 @@ +/* Determine whether block of given size can be allocated on the stack or not. + Copyright (C) 2002, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + + +extern int +__always_inline +__libc_use_alloca (size_t size) +{ + return (__builtin_expect (size <= PTHREAD_STACK_MIN / 4, 1) + || __libc_alloca_cutoff (size)); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/bits/libc-lock.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/bits/libc-lock.h new file mode 100644 index 00000000..52627b41 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/bits/libc-lock.h @@ -0,0 +1,584 @@ +/* libc-internal interface for mutex locks. NPTL version. + Copyright (C) 1996-2003, 2005, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _BITS_LIBC_LOCK_H +#define _BITS_LIBC_LOCK_H 1 + +#include +#include +#define __need_NULL +#include + + +/* Fortunately Linux now has a mean to do locking which is realtime + safe without the aid of the thread library. We also need no fancy + options like error checking mutexes etc. We only need simple + locks, maybe recursive. This can be easily and cheaply implemented + using futexes. We will use them everywhere except in ld.so since + ld.so might be used on old kernels with a different libc.so. */ +#ifdef _LIBC +# include +# include +# include +#endif + +/* Mutex type. */ +#if defined _LIBC || defined _IO_MTSAFE_IO +# if (defined NOT_IN_libc && !defined IS_IN_libpthread) || !defined _LIBC +typedef pthread_mutex_t __libc_lock_t; +typedef struct { pthread_mutex_t mutex; } __libc_lock_recursive_t; +# else +typedef int __libc_lock_t; +typedef struct { int lock; int cnt; void *owner; } __libc_lock_recursive_t; +# endif +typedef struct { pthread_mutex_t mutex; } __rtld_lock_recursive_t; +# ifdef __USE_UNIX98 +typedef pthread_rwlock_t __libc_rwlock_t; +# else +typedef struct __libc_rwlock_opaque__ __libc_rwlock_t; +# endif +#else +typedef struct __libc_lock_opaque__ __libc_lock_t; +typedef struct __libc_lock_recursive_opaque__ __libc_lock_recursive_t; +typedef struct __libc_rwlock_opaque__ __libc_rwlock_t; +#endif + +/* Type for key to thread-specific data. */ +typedef pthread_key_t __libc_key_t; + +# define __libc_freeres_fn_section \ + __attribute__ ((section ("__libc_freeres_fn"))) + + +/* Define a lock variable NAME with storage class CLASS. The lock must be + initialized with __libc_lock_init before it can be used (or define it + with __libc_lock_define_initialized, below). Use `extern' for CLASS to + declare a lock defined in another module. In public structure + definitions you must use a pointer to the lock structure (i.e., NAME + begins with a `*'), because its storage size will not be known outside + of libc. */ +#define __libc_lock_define(CLASS,NAME) \ + CLASS __libc_lock_t NAME; +#define __libc_rwlock_define(CLASS,NAME) \ + CLASS __libc_rwlock_t NAME; +#define __libc_lock_define_recursive(CLASS,NAME) \ + CLASS __libc_lock_recursive_t NAME; +#define __rtld_lock_define_recursive(CLASS,NAME) \ + CLASS __rtld_lock_recursive_t NAME; + +/* Define an initialized lock variable NAME with storage class CLASS. + + For the C library we take a deeper look at the initializer. For + this implementation all fields are initialized to zero. Therefore + we don't initialize the variable which allows putting it into the + BSS section. (Except on PA-RISC and other odd architectures, where + initialized locks must be set to one due to the lack of normal + atomic operations.) */ + +#if defined _LIBC && (!defined NOT_IN_libc || defined IS_IN_libpthread) +# if LLL_LOCK_INITIALIZER == 0 +# define __libc_lock_define_initialized(CLASS,NAME) \ + CLASS __libc_lock_t NAME; +# else +# define __libc_lock_define_initialized(CLASS,NAME) \ + CLASS __libc_lock_t NAME = LLL_LOCK_INITIALIZER; +# endif +#else +# if __LT_SPINLOCK_INIT == 0 +# define __libc_lock_define_initialized(CLASS,NAME) \ + CLASS __libc_lock_t NAME; +# else +# define __libc_lock_define_initialized(CLASS,NAME) \ + CLASS __libc_lock_t NAME = PTHREAD_MUTEX_INITIALIZER; +# endif +#endif + +#define __libc_rwlock_define_initialized(CLASS,NAME) \ + CLASS __libc_rwlock_t NAME = PTHREAD_RWLOCK_INITIALIZER; + +/* Define an initialized recursive lock variable NAME with storage + class CLASS. */ +#if defined _LIBC && (!defined NOT_IN_libc || defined IS_IN_libpthread) +# if LLL_LOCK_INITIALIZER == 0 +# define __libc_lock_define_initialized_recursive(CLASS,NAME) \ + CLASS __libc_lock_recursive_t NAME; +# else +# define __libc_lock_define_initialized_recursive(CLASS,NAME) \ + CLASS __libc_lock_recursive_t NAME = _LIBC_LOCK_RECURSIVE_INITIALIZER; +# endif +# define _LIBC_LOCK_RECURSIVE_INITIALIZER \ + { LLL_LOCK_INITIALIZER, 0, NULL } +#else +# define __libc_lock_define_initialized_recursive(CLASS,NAME) \ + CLASS __libc_lock_recursive_t NAME = _LIBC_LOCK_RECURSIVE_INITIALIZER; +# define _LIBC_LOCK_RECURSIVE_INITIALIZER \ + {PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP} +#endif + +#define __rtld_lock_define_initialized_recursive(CLASS,NAME) \ + CLASS __rtld_lock_recursive_t NAME = _RTLD_LOCK_RECURSIVE_INITIALIZER; +#define _RTLD_LOCK_RECURSIVE_INITIALIZER \ + {PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP} + +#define __rtld_lock_initialize(NAME) \ + (void) ((NAME) = (__rtld_lock_recursive_t) _RTLD_LOCK_RECURSIVE_INITIALIZER) + +/* If we check for a weakly referenced symbol and then perform a + normal jump to it te code generated for some platforms in case of + PIC is unnecessarily slow. What would happen is that the function + is first referenced as data and then it is called indirectly + through the PLT. We can make this a direct jump. */ +#ifdef __PIC__ +# define __libc_maybe_call(FUNC, ARGS, ELSE) \ + (__extension__ ({ __typeof (FUNC) *_fn = (FUNC); \ + _fn != NULL ? (*_fn) ARGS : ELSE; })) +#else +# define __libc_maybe_call(FUNC, ARGS, ELSE) \ + (FUNC != NULL ? FUNC ARGS : ELSE) +#endif + +/* Call thread functions through the function pointer table. */ +#if defined SHARED && !defined NOT_IN_libc +# define PTFAVAIL(NAME) __libc_pthread_functions_init +# define __libc_ptf_call(FUNC, ARGS, ELSE) \ + (__libc_pthread_functions_init ? PTHFCT_CALL (ptr_##FUNC, ARGS) : ELSE) +# define __libc_ptf_call_always(FUNC, ARGS) \ + PTHFCT_CALL (ptr_##FUNC, ARGS) +#else +# define PTFAVAIL(NAME) (NAME != NULL) +# define __libc_ptf_call(FUNC, ARGS, ELSE) \ + __libc_maybe_call (FUNC, ARGS, ELSE) +# define __libc_ptf_call_always(FUNC, ARGS) \ + FUNC ARGS +#endif + + +/* Initialize the named lock variable, leaving it in a consistent, unlocked + state. */ +#if defined _LIBC && (!defined NOT_IN_libc || defined IS_IN_libpthread) +# define __libc_lock_init(NAME) ((NAME) = LLL_LOCK_INITIALIZER, 0) +#else +# define __libc_lock_init(NAME) \ + __libc_maybe_call (__pthread_mutex_init, (&(NAME), NULL), 0) +#endif +#if defined SHARED && !defined NOT_IN_libc +/* ((NAME) = (__libc_rwlock_t) PTHREAD_RWLOCK_INITIALIZER, 0) is + inefficient. */ +# define __libc_rwlock_init(NAME) \ + (__builtin_memset (&(NAME), '\0', sizeof (NAME)), 0) +#else +# define __libc_rwlock_init(NAME) \ + __libc_maybe_call (__pthread_rwlock_init, (&(NAME), NULL), 0) +#endif + +/* Same as last but this time we initialize a recursive mutex. */ +#if defined _LIBC && (!defined NOT_IN_libc || defined IS_IN_libpthread) +# define __libc_lock_init_recursive(NAME) \ + ((NAME) = (__libc_lock_recursive_t) _LIBC_LOCK_RECURSIVE_INITIALIZER, 0) +#else +# define __libc_lock_init_recursive(NAME) \ + do { \ + if (__pthread_mutex_init != NULL) \ + { \ + pthread_mutexattr_t __attr; \ + __pthread_mutexattr_init (&__attr); \ + __pthread_mutexattr_settype (&__attr, PTHREAD_MUTEX_RECURSIVE_NP); \ + __pthread_mutex_init (&(NAME).mutex, &__attr); \ + __pthread_mutexattr_destroy (&__attr); \ + } \ + } while (0) +#endif + +#define __rtld_lock_init_recursive(NAME) \ + do { \ + if (__pthread_mutex_init != NULL) \ + { \ + pthread_mutexattr_t __attr; \ + __pthread_mutexattr_init (&__attr); \ + __pthread_mutexattr_settype (&__attr, PTHREAD_MUTEX_RECURSIVE_NP); \ + __pthread_mutex_init (&(NAME).mutex, &__attr); \ + __pthread_mutexattr_destroy (&__attr); \ + } \ + } while (0) + +/* Finalize the named lock variable, which must be locked. It cannot be + used again until __libc_lock_init is called again on it. This must be + called on a lock variable before the containing storage is reused. */ +#if defined _LIBC && (!defined NOT_IN_libc || defined IS_IN_libpthread) +# define __libc_lock_fini(NAME) ((void) 0) +#else +# define __libc_lock_fini(NAME) \ + __libc_maybe_call (__pthread_mutex_destroy, (&(NAME)), 0) +#endif +#if defined SHARED && !defined NOT_IN_libc +# define __libc_rwlock_fini(NAME) ((void) 0) +#else +# define __libc_rwlock_fini(NAME) \ + __libc_maybe_call (__pthread_rwlock_destroy, (&(NAME)), 0) +#endif + +/* Finalize recursive named lock. */ +#if defined _LIBC && (!defined NOT_IN_libc || defined IS_IN_libpthread) +# define __libc_lock_fini_recursive(NAME) ((void) 0) +#else +# define __libc_lock_fini_recursive(NAME) \ + __libc_maybe_call (__pthread_mutex_destroy, (&(NAME)), 0) +#endif + +/* Lock the named lock variable. */ +#if defined _LIBC && (!defined NOT_IN_libc || defined IS_IN_libpthread) +# define __libc_lock_lock(NAME) \ + ({ lll_lock (NAME, LLL_PRIVATE); 0; }) +#else +# define __libc_lock_lock(NAME) \ + __libc_maybe_call (__pthread_mutex_lock, (&(NAME)), 0) +#endif +#define __libc_rwlock_rdlock(NAME) \ + __libc_ptf_call (__pthread_rwlock_rdlock, (&(NAME)), 0) +#define __libc_rwlock_wrlock(NAME) \ + __libc_ptf_call (__pthread_rwlock_wrlock, (&(NAME)), 0) + +/* Lock the recursive named lock variable. */ +#if defined _LIBC && (!defined NOT_IN_libc || defined IS_IN_libpthread) +# define __libc_lock_lock_recursive(NAME) \ + do { \ + void *self = THREAD_SELF; \ + if ((NAME).owner != self) \ + { \ + lll_lock ((NAME).lock, LLL_PRIVATE); \ + (NAME).owner = self; \ + } \ + ++(NAME).cnt; \ + } while (0) +#else +# define __libc_lock_lock_recursive(NAME) \ + __libc_maybe_call (__pthread_mutex_lock, (&(NAME).mutex), 0) +#endif + +/* Try to lock the named lock variable. */ +#if defined _LIBC && (!defined NOT_IN_libc || defined IS_IN_libpthread) +# define __libc_lock_trylock(NAME) \ + lll_trylock (NAME) +#else +# define __libc_lock_trylock(NAME) \ + __libc_maybe_call (__pthread_mutex_trylock, (&(NAME)), 0) +#endif +#define __libc_rwlock_tryrdlock(NAME) \ + __libc_maybe_call (__pthread_rwlock_tryrdlock, (&(NAME)), 0) +#define __libc_rwlock_trywrlock(NAME) \ + __libc_maybe_call (__pthread_rwlock_trywrlock, (&(NAME)), 0) + +/* Try to lock the recursive named lock variable. */ +#if defined _LIBC && (!defined NOT_IN_libc || defined IS_IN_libpthread) +# define __libc_lock_trylock_recursive(NAME) \ + ({ \ + int result = 0; \ + void *self = THREAD_SELF; \ + if ((NAME).owner != self) \ + { \ + if (lll_trylock ((NAME).lock) == 0) \ + { \ + (NAME).owner = self; \ + (NAME).cnt = 1; \ + } \ + else \ + result = EBUSY; \ + } \ + else \ + ++(NAME).cnt; \ + result; \ + }) +#else +# define __libc_lock_trylock_recursive(NAME) \ + __libc_maybe_call (__pthread_mutex_trylock, (&(NAME)), 0) +#endif + +#define __rtld_lock_trylock_recursive(NAME) \ + __libc_maybe_call (__pthread_mutex_trylock, (&(NAME).mutex), 0) + +/* Unlock the named lock variable. */ +#if defined _LIBC && (!defined NOT_IN_libc || defined IS_IN_libpthread) +# define __libc_lock_unlock(NAME) \ + lll_unlock (NAME, LLL_PRIVATE) +#else +# define __libc_lock_unlock(NAME) \ + __libc_maybe_call (__pthread_mutex_unlock, (&(NAME)), 0) +#endif +#define __libc_rwlock_unlock(NAME) \ + __libc_ptf_call (__pthread_rwlock_unlock, (&(NAME)), 0) + +/* Unlock the recursive named lock variable. */ +#if defined _LIBC && (!defined NOT_IN_libc || defined IS_IN_libpthread) +/* We do no error checking here. */ +# define __libc_lock_unlock_recursive(NAME) \ + do { \ + if (--(NAME).cnt == 0) \ + { \ + (NAME).owner = NULL; \ + lll_unlock ((NAME).lock, LLL_PRIVATE); \ + } \ + } while (0) +#else +# define __libc_lock_unlock_recursive(NAME) \ + __libc_maybe_call (__pthread_mutex_unlock, (&(NAME)), 0) +#endif + +#if defined _LIBC && defined SHARED +# define __rtld_lock_default_lock_recursive(lock) \ + ++((pthread_mutex_t *)(lock))->__data.__count; + +# define __rtld_lock_default_unlock_recursive(lock) \ + --((pthread_mutex_t *)(lock))->__data.__count; + +# define __rtld_lock_lock_recursive(NAME) \ + GL(dl_rtld_lock_recursive) (&(NAME).mutex) + +# define __rtld_lock_unlock_recursive(NAME) \ + GL(dl_rtld_unlock_recursive) (&(NAME).mutex) +#else +# define __rtld_lock_lock_recursive(NAME) \ + __libc_maybe_call (__pthread_mutex_lock, (&(NAME).mutex), 0) + +# define __rtld_lock_unlock_recursive(NAME) \ + __libc_maybe_call (__pthread_mutex_unlock, (&(NAME).mutex), 0) +#endif + +/* Define once control variable. */ +#if PTHREAD_ONCE_INIT == 0 +/* Special case for static variables where we can avoid the initialization + if it is zero. */ +# define __libc_once_define(CLASS, NAME) \ + CLASS pthread_once_t NAME +#else +# define __libc_once_define(CLASS, NAME) \ + CLASS pthread_once_t NAME = PTHREAD_ONCE_INIT +#endif + +/* Call handler iff the first call. */ +#define __libc_once(ONCE_CONTROL, INIT_FUNCTION) \ + do { \ + if (PTFAVAIL (__pthread_once)) \ + __libc_ptf_call_always (__pthread_once, (&(ONCE_CONTROL), \ + INIT_FUNCTION)); \ + else if ((ONCE_CONTROL) == PTHREAD_ONCE_INIT) { \ + INIT_FUNCTION (); \ + (ONCE_CONTROL) |= 2; \ + } \ + } while (0) + + +/* Note that for I/O cleanup handling we are using the old-style + cancel handling. It does not have to be integrated with C++ snce + no C++ code is called in the middle. The old-style handling is + faster and the support is not going away. */ +extern void _pthread_cleanup_push (struct _pthread_cleanup_buffer *buffer, + void (*routine) (void *), void *arg); +extern void _pthread_cleanup_pop (struct _pthread_cleanup_buffer *buffer, + int execute); +extern void _pthread_cleanup_push_defer (struct _pthread_cleanup_buffer *buffer, + void (*routine) (void *), void *arg); +extern void _pthread_cleanup_pop_restore (struct _pthread_cleanup_buffer *buffer, + int execute); + +/* Start critical region with cleanup. */ +#define __libc_cleanup_region_start(DOIT, FCT, ARG) \ + { struct _pthread_cleanup_buffer _buffer; \ + int _avail; \ + if (DOIT) { \ + _avail = PTFAVAIL (_pthread_cleanup_push_defer); \ + if (_avail) { \ + __libc_ptf_call_always (_pthread_cleanup_push_defer, (&_buffer, FCT, \ + ARG)); \ + } else { \ + _buffer.__routine = (FCT); \ + _buffer.__arg = (ARG); \ + } \ + } else { \ + _avail = 0; \ + } + +/* End critical region with cleanup. */ +#define __libc_cleanup_region_end(DOIT) \ + if (_avail) { \ + __libc_ptf_call_always (_pthread_cleanup_pop_restore, (&_buffer, DOIT));\ + } else if (DOIT) \ + _buffer.__routine (_buffer.__arg); \ + } + +/* Sometimes we have to exit the block in the middle. */ +#define __libc_cleanup_end(DOIT) \ + if (_avail) { \ + __libc_ptf_call_always (_pthread_cleanup_pop_restore, (&_buffer, DOIT));\ + } else if (DOIT) \ + _buffer.__routine (_buffer.__arg) + + +/* Normal cleanup handling, based on C cleanup attribute. */ +static inline void +__libc_cleanup_routine (struct __pthread_cleanup_frame *f) +{ + if (f->__do_it) + f->__cancel_routine (f->__cancel_arg); +} + +#define __libc_cleanup_push(fct, arg) \ + do { \ + struct __pthread_cleanup_frame __clframe \ + __attribute__ ((__cleanup__ (__libc_cleanup_routine))) \ + = { .__cancel_routine = (fct), .__cancel_arg = (arg), \ + .__do_it = 1 }; + +#define __libc_cleanup_pop(execute) \ + __clframe.__do_it = (execute); \ + } while (0) + + +/* Create thread-specific key. */ +#define __libc_key_create(KEY, DESTRUCTOR) \ + __libc_ptf_call (__pthread_key_create, (KEY, DESTRUCTOR), 1) + +/* Get thread-specific data. */ +#define __libc_getspecific(KEY) \ + __libc_ptf_call (__pthread_getspecific, (KEY), NULL) + +/* Set thread-specific data. */ +#define __libc_setspecific(KEY, VALUE) \ + __libc_ptf_call (__pthread_setspecific, (KEY, VALUE), 0) + +/* Register handlers to execute before and after `fork'. Note that the + last parameter is NULL. The handlers registered by the libc are + never removed so this is OK. */ +#define __libc_atfork(PREPARE, PARENT, CHILD) \ + __register_atfork (PREPARE, PARENT, CHILD, NULL) +extern int __register_atfork (void (*__prepare) (void), + void (*__parent) (void), + void (*__child) (void), + void *__dso_handle); + +/* Functions that are used by this file and are internal to the GNU C + library. */ + +extern int __pthread_mutex_init (pthread_mutex_t *__mutex, + __const pthread_mutexattr_t *__mutex_attr); + +extern int __pthread_mutex_destroy (pthread_mutex_t *__mutex); + +extern int __pthread_mutex_trylock (pthread_mutex_t *__mutex); + +extern int __pthread_mutex_lock (pthread_mutex_t *__mutex); + +extern int __pthread_mutex_unlock (pthread_mutex_t *__mutex); + +extern int __pthread_mutexattr_init (pthread_mutexattr_t *__attr); + +extern int __pthread_mutexattr_destroy (pthread_mutexattr_t *__attr); + +extern int __pthread_mutexattr_settype (pthread_mutexattr_t *__attr, + int __kind); + +#ifdef __USE_UNIX98 +extern int __pthread_rwlock_init (pthread_rwlock_t *__rwlock, + __const pthread_rwlockattr_t *__attr); + +extern int __pthread_rwlock_destroy (pthread_rwlock_t *__rwlock); + +extern int __pthread_rwlock_rdlock (pthread_rwlock_t *__rwlock); + +extern int __pthread_rwlock_tryrdlock (pthread_rwlock_t *__rwlock); + +extern int __pthread_rwlock_wrlock (pthread_rwlock_t *__rwlock); + +extern int __pthread_rwlock_trywrlock (pthread_rwlock_t *__rwlock); + +extern int __pthread_rwlock_unlock (pthread_rwlock_t *__rwlock); +#endif + +extern int __pthread_key_create (pthread_key_t *__key, + void (*__destr_function) (void *)); + +extern int __pthread_setspecific (pthread_key_t __key, + __const void *__pointer); + +extern void *__pthread_getspecific (pthread_key_t __key); + +extern int __pthread_once (pthread_once_t *__once_control, + void (*__init_routine) (void)); + +extern int __pthread_atfork (void (*__prepare) (void), + void (*__parent) (void), + void (*__child) (void)); + + + +/* Make the pthread functions weak so that we can elide them from + single-threaded processes. */ +#ifndef __NO_WEAK_PTHREAD_ALIASES +# ifdef weak_extern +weak_extern (__pthread_mutex_init) +weak_extern (__pthread_mutex_destroy) +weak_extern (__pthread_mutex_lock) +weak_extern (__pthread_mutex_trylock) +weak_extern (__pthread_mutex_unlock) +weak_extern (__pthread_mutexattr_init) +weak_extern (__pthread_mutexattr_destroy) +weak_extern (__pthread_mutexattr_settype) +weak_extern (__pthread_rwlock_init) +weak_extern (__pthread_rwlock_destroy) +weak_extern (__pthread_rwlock_rdlock) +weak_extern (__pthread_rwlock_tryrdlock) +weak_extern (__pthread_rwlock_wrlock) +weak_extern (__pthread_rwlock_trywrlock) +weak_extern (__pthread_rwlock_unlock) +weak_extern (__pthread_key_create) +weak_extern (__pthread_setspecific) +weak_extern (__pthread_getspecific) +weak_extern (__pthread_once) +//weak_extern (__pthread_initialize) +weak_extern (__pthread_atfork) +weak_extern (_pthread_cleanup_push_defer) +weak_extern (_pthread_cleanup_pop_restore) +weak_extern (pthread_setcancelstate) +# else +# pragma weak __pthread_mutex_init +# pragma weak __pthread_mutex_destroy +# pragma weak __pthread_mutex_lock +# pragma weak __pthread_mutex_trylock +# pragma weak __pthread_mutex_unlock +# pragma weak __pthread_mutexattr_init +# pragma weak __pthread_mutexattr_destroy +# pragma weak __pthread_mutexattr_settype +# pragma weak __pthread_rwlock_destroy +# pragma weak __pthread_rwlock_rdlock +# pragma weak __pthread_rwlock_tryrdlock +# pragma weak __pthread_rwlock_wrlock +# pragma weak __pthread_rwlock_trywrlock +# pragma weak __pthread_rwlock_unlock +# pragma weak __pthread_key_create +# pragma weak __pthread_setspecific +# pragma weak __pthread_getspecific +# pragma weak __pthread_once +//# pragma weak __pthread_initialize +# pragma weak __pthread_atfork +# pragma weak _pthread_cleanup_push_defer +# pragma weak _pthread_cleanup_pop_restore +# pragma weak pthread_setcancelstate +# endif +#endif + +#endif /* bits/libc-lock.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/bits/libc-tsd.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/bits/libc-tsd.h new file mode 100644 index 00000000..3f1676b3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/bits/libc-tsd.h @@ -0,0 +1,69 @@ +/* libc-internal interface for thread-specific data. Stub or TLS version. + Copyright (C) 1998,2001,02 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _GENERIC_BITS_LIBC_TSD_H +#define _GENERIC_BITS_LIBC_TSD_H 1 + +/* This file defines the following macros for accessing a small fixed + set of thread-specific `void *' data used only internally by libc. + + __libc_tsd_define(CLASS, KEY) -- Define or declare a `void *' datum + for KEY. CLASS can be `static' for + keys used in only one source file, + empty for global definitions, or + `extern' for global declarations. + __libc_tsd_address(KEY) -- Return the `void **' pointing to + the current thread's datum for KEY. + __libc_tsd_get(KEY) -- Return the `void *' datum for KEY. + __libc_tsd_set(KEY, VALUE) -- Set the datum for KEY to VALUE. + + The set of available KEY's will usually be provided as an enum, + and contains (at least): + _LIBC_TSD_KEY_MALLOC + _LIBC_TSD_KEY_DL_ERROR + _LIBC_TSD_KEY_RPC_VARS + All uses must be the literal _LIBC_TSD_* name in the __libc_tsd_* macros. + Some implementations may not provide any enum at all and instead + using string pasting in the macros. */ + +#include + +/* When full support for __thread variables is available, this interface is + just a trivial wrapper for it. Without TLS, this is the generic/stub + implementation for wholly single-threaded systems. + + We don't define an enum for the possible key values, because the KEYs + translate directly into variables by macro magic. */ + +#if USE___THREAD +# define __libc_tsd_define(CLASS, KEY) \ + CLASS __thread void *__libc_tsd_##KEY attribute_tls_model_ie; + +# define __libc_tsd_address(KEY) (&__libc_tsd_##KEY) +# define __libc_tsd_get(KEY) (__libc_tsd_##KEY) +# define __libc_tsd_set(KEY, VALUE) (__libc_tsd_##KEY = (VALUE)) +#else +# define __libc_tsd_define(CLASS, KEY) CLASS void *__libc_tsd_##KEY##_data; + +# define __libc_tsd_address(KEY) (&__libc_tsd_##KEY##_data) +# define __libc_tsd_get(KEY) (__libc_tsd_##KEY##_data) +# define __libc_tsd_set(KEY, VALUE) (__libc_tsd_##KEY##_data = (VALUE)) +#endif + +#endif /* bits/libc-tsd.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/bits/sigthread.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/bits/sigthread.h new file mode 100644 index 00000000..9a524e57 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/bits/sigthread.h @@ -0,0 +1,44 @@ +/* Signal handling function for threaded programs. + Copyright (C) 1998, 1999, 2000, 2002, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _BITS_SIGTHREAD_H +#define _BITS_SIGTHREAD_H 1 + +#if !defined _SIGNAL_H && !defined _PTHREAD_H +# error "Never include this file directly. Use instead" +#endif + +/* Functions for handling signals. */ + +/* Modify the signal mask for the calling thread. The arguments have + the same meaning as for sigprocmask(2). */ +extern int pthread_sigmask (int __how, + __const __sigset_t *__restrict __newmask, + __sigset_t *__restrict __oldmask)__THROW; + +/* Send signal SIGNO to the given thread. */ +extern int pthread_kill (pthread_t __threadid, int __signo) __THROW; + +#ifdef __USE_GNU +/* Queue signal and data to a thread. */ +extern int pthread_sigqueue (pthread_t __threadid, int __signo, + const union sigval __value) __THROW; +#endif + +#endif /* bits/sigthread.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/bits/stdio-lock.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/bits/stdio-lock.h new file mode 100644 index 00000000..3437e616 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/bits/stdio-lock.h @@ -0,0 +1,111 @@ +/* Thread package specific definitions of stream lock type. NPTL version. + Copyright (C) 2000, 2001, 2002, 2003, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _BITS_STDIO_LOCK_H +#define _BITS_STDIO_LOCK_H 1 + +#include +#include + + +/* The locking here is very inexpensive, even for inlining. */ +#define _IO_lock_inexpensive 1 + +typedef struct { int lock; int cnt; void *owner; } _IO_lock_t; + +#define _IO_lock_initializer { LLL_LOCK_INITIALIZER, 0, NULL } + +#define _IO_lock_init(_name) \ + ((_name) = (_IO_lock_t) _IO_lock_initializer , 0) + +#define _IO_lock_fini(_name) \ + ((void) 0) + +#define _IO_lock_lock(_name) \ + do { \ + void *__meself = THREAD_SELF; \ + if ((_name).owner != __meself) \ + { \ + lll_lock ((_name).lock, LLL_PRIVATE); \ + (_name).owner = __meself; \ + } \ + ++(_name).cnt; \ + } while (0) + +#define _IO_lock_trylock(_name) \ + ({ \ + int __result = 0; \ + void *__meself = THREAD_SELF; \ + if ((_name).owner != __meself) \ + { \ + if (lll_trylock ((_name).lock) == 0) \ + { \ + (_name).owner = __meself; \ + (_name).cnt = 1; \ + } \ + else \ + __result = EBUSY; \ + } \ + else \ + ++(_name).cnt; \ + __result; \ + }) + +#define _IO_lock_unlock(_name) \ + do { \ + if (--(_name).cnt == 0) \ + { \ + (_name).owner = NULL; \ + lll_unlock ((_name).lock, LLL_PRIVATE); \ + } \ + } while (0) + + + +#define _IO_cleanup_region_start(_fct, _fp) \ + __libc_cleanup_region_start (((_fp)->_flags & _IO_USER_LOCK) == 0, _fct, _fp) +#define _IO_cleanup_region_start_noarg(_fct) \ + __libc_cleanup_region_start (1, _fct, NULL) +#define _IO_cleanup_region_end(_doit) \ + __libc_cleanup_region_end (_doit) + +#if defined _LIBC && !defined NOT_IN_libc + +# ifdef __EXCEPTIONS +# define _IO_acquire_lock(_fp) \ + do { \ + _IO_FILE *_IO_acquire_lock_file \ + __attribute__((cleanup (_IO_acquire_lock_fct))) \ + = (_fp); \ + _IO_flockfile (_IO_acquire_lock_file); +# define _IO_acquire_lock_clear_flags2(_fp) \ + do { \ + _IO_FILE *_IO_acquire_lock_file \ + __attribute__((cleanup (_IO_acquire_lock_clear_flags2_fct))) \ + = (_fp); \ + _IO_flockfile (_IO_acquire_lock_file); +# else +# define _IO_acquire_lock(_fp) _IO_acquire_lock_needs_exceptions_enabled +# define _IO_acquire_lock_clear_flags2(_fp) _IO_acquire_lock (_fp) +# endif +# define _IO_release_lock(_fp) ; } while (0) + +#endif + +#endif /* bits/stdio-lock.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/createthread.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/createthread.c new file mode 100644 index 00000000..a676e277 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/createthread.c @@ -0,0 +1,257 @@ +/* Copyright (C) 2002-2007, 2008 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include +#include + +#include + + +#define CLONE_SIGNAL (CLONE_SIGHAND | CLONE_THREAD) + +/* Unless otherwise specified, the thread "register" is going to be + initialized with a pointer to the TCB. */ +#ifndef TLS_VALUE +# define TLS_VALUE pd +#endif + +#ifndef ARCH_CLONE +# define ARCH_CLONE __clone +#endif + + +#ifndef TLS_MULTIPLE_THREADS_IN_TCB +/* Pointer to the corresponding variable in libc. */ +int *__libc_multiple_threads_ptr attribute_hidden; +#endif + + +static int +do_clone (struct pthread *pd, const struct pthread_attr *attr, + int clone_flags, int (*fct) (void *), STACK_VARIABLES_PARMS, + int stopped) +{ +#ifdef PREPARE_CREATE + PREPARE_CREATE; +#endif + + if (__builtin_expect (stopped != 0, 0)) + /* We make sure the thread does not run far by forcing it to get a + lock. We lock it here too so that the new thread cannot continue + until we tell it to. */ + lll_lock (pd->lock, LLL_PRIVATE); + + /* One more thread. We cannot have the thread do this itself, since it + might exist but not have been scheduled yet by the time we've returned + and need to check the value to behave correctly. We must do it before + creating the thread, in case it does get scheduled first and then + might mistakenly think it was the only thread. In the failure case, + we momentarily store a false value; this doesn't matter because there + is no kosher thing a signal handler interrupting us right here can do + that cares whether the thread count is correct. */ + atomic_increment (&__nptl_nthreads); + + if (ARCH_CLONE (fct, STACK_VARIABLES_ARGS, clone_flags, + pd, &pd->tid, TLS_VALUE, &pd->tid) == -1) + { + atomic_decrement (&__nptl_nthreads); /* Oops, we lied for a second. */ + + /* Failed. If the thread is detached, remove the TCB here since + the caller cannot do this. The caller remembered the thread + as detached and cannot reverify that it is not since it must + not access the thread descriptor again. */ + if (IS_DETACHED (pd)) + __deallocate_stack (pd); + + /* We have to translate error codes. */ + return errno == ENOMEM ? EAGAIN : errno; + } + + /* Now we have the possibility to set scheduling parameters etc. */ + if (__builtin_expect (stopped != 0, 0)) + { + INTERNAL_SYSCALL_DECL (err); + int res = 0; + + /* Set the affinity mask if necessary. */ + if (attr->cpuset != NULL) + { + res = INTERNAL_SYSCALL (sched_setaffinity, err, 3, pd->tid, + attr->cpusetsize, attr->cpuset); + + if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (res, err), 0)) + { + /* The operation failed. We have to kill the thread. First + send it the cancellation signal. */ + INTERNAL_SYSCALL_DECL (err2); + err_out: +#if __ASSUME_TGKILL + (void) INTERNAL_SYSCALL (tgkill, err2, 3, + THREAD_GETMEM (THREAD_SELF, pid), + pd->tid, SIGCANCEL); +#else + (void) INTERNAL_SYSCALL (tkill, err2, 2, pd->tid, SIGCANCEL); +#endif + + return (INTERNAL_SYSCALL_ERROR_P (res, err) + ? INTERNAL_SYSCALL_ERRNO (res, err) + : 0); + } + } + + /* Set the scheduling parameters. */ + if ((attr->flags & ATTR_FLAG_NOTINHERITSCHED) != 0) + { + res = INTERNAL_SYSCALL (sched_setscheduler, err, 3, pd->tid, + pd->schedpolicy, &pd->schedparam); + + if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (res, err), 0)) + goto err_out; + } + } + + /* We now have for sure more than one thread. The main thread might + not yet have the flag set. No need to set the global variable + again if this is what we use. */ + THREAD_SETMEM (THREAD_SELF, header.multiple_threads, 1); + + return 0; +} + + +static int +create_thread (struct pthread *pd, const struct pthread_attr *attr, + STACK_VARIABLES_PARMS) +{ +#ifdef TLS_TCB_AT_TP + assert (pd->header.tcb != NULL); +#endif + + /* We rely heavily on various flags the CLONE function understands: + + CLONE_VM, CLONE_FS, CLONE_FILES + These flags select semantics with shared address space and + file descriptors according to what POSIX requires. + + CLONE_SIGNAL + This flag selects the POSIX signal semantics. + + CLONE_SETTLS + The sixth parameter to CLONE determines the TLS area for the + new thread. + + CLONE_PARENT_SETTID + The kernels writes the thread ID of the newly created thread + into the location pointed to by the fifth parameters to CLONE. + + Note that it would be semantically equivalent to use + CLONE_CHILD_SETTID but it is be more expensive in the kernel. + + CLONE_CHILD_CLEARTID + The kernels clears the thread ID of a thread that has called + sys_exit() in the location pointed to by the seventh parameter + to CLONE. + + CLONE_DETACHED + No signal is generated if the thread exists and it is + automatically reaped. + + The termination signal is chosen to be zero which means no signal + is sent. */ + int clone_flags = (CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGNAL + | CLONE_SETTLS | CLONE_PARENT_SETTID + | CLONE_CHILD_CLEARTID | CLONE_SYSVSEM +#if __ASSUME_NO_CLONE_DETACHED == 0 + | CLONE_DETACHED +#endif + | 0); + + if (__builtin_expect (THREAD_GETMEM (THREAD_SELF, report_events), 0)) + { + /* The parent thread is supposed to report events. Check whether + the TD_CREATE event is needed, too. */ + const int _idx = __td_eventword (TD_CREATE); + const uint32_t _mask = __td_eventmask (TD_CREATE); + + if ((_mask & (__nptl_threads_events.event_bits[_idx] + | pd->eventbuf.eventmask.event_bits[_idx])) != 0) + { + /* We always must have the thread start stopped. */ + pd->stopped_start = true; + + /* Create the thread. We always create the thread stopped + so that it does not get far before we tell the debugger. */ + int res = do_clone (pd, attr, clone_flags, start_thread, + STACK_VARIABLES_ARGS, 1); + if (res == 0) + { + /* Now fill in the information about the new thread in + the newly created thread's data structure. We cannot let + the new thread do this since we don't know whether it was + already scheduled when we send the event. */ + pd->eventbuf.eventnum = TD_CREATE; + pd->eventbuf.eventdata = pd; + + /* Enqueue the descriptor. */ + do + pd->nextevent = __nptl_last_event; + while (atomic_compare_and_exchange_bool_acq (&__nptl_last_event, + pd, pd->nextevent) + != 0); + + /* Now call the function which signals the event. */ + __nptl_create_event (); + + /* And finally restart the new thread. */ + lll_unlock (pd->lock, LLL_PRIVATE); + } + + return res; + } + } + +#ifdef NEED_DL_SYSINFO + assert (THREAD_SELF_SYSINFO == THREAD_SYSINFO (pd)); +#endif + + /* Determine whether the newly created threads has to be started + stopped since we have to set the scheduling parameters or set the + affinity. */ + bool stopped = false; + if (attr != NULL && (attr->cpuset != NULL + || (attr->flags & ATTR_FLAG_NOTINHERITSCHED) != 0)) + stopped = true; + pd->stopped_start = stopped; + pd->parent_cancelhandling = THREAD_GETMEM (THREAD_SELF, cancelhandling); + + /* Actually create the thread. */ + int res = do_clone (pd, attr, clone_flags, start_thread, + STACK_VARIABLES_ARGS, stopped); + + if (res == 0 && stopped) + /* And finally restart the new thread. */ + lll_unlock (pd->lock, LLL_PRIVATE); + + return res; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/defs.awk b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/defs.awk new file mode 100644 index 00000000..d41d57bd --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/defs.awk @@ -0,0 +1,24 @@ +/^[ ]*\.endp/ { need_endp = 1 } +/^[ ]*\.end/ { need_end = 1 } +/^[ ]*\.align/ { if($2 > max) max = $2; } + +END { + if(need_endp) + { + print "#define END_INIT .endp _init"; + print "#define END_FINI .endp _fini"; + } else if(need_end) + { + print "#define END_INIT .end _init"; + print "#define END_FINI .end _fini"; + } + else + { + print "#define END_INIT"; + print "#define END_FINI"; + } + if(max) + print "#define ALIGN .align", max; + else + print "#define ALIGN"; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/librt-cancellation.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/librt-cancellation.c new file mode 100644 index 00000000..ad189e81 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/librt-cancellation.c @@ -0,0 +1,25 @@ +/* Copyright (C) 2002, 2003, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "pthreadP.h" + + +#define __pthread_enable_asynccancel __librt_enable_asynccancel +#define __pthread_disable_asynccancel __librt_disable_asynccancel +#include "cancellation.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/list.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/list.h new file mode 100644 index 00000000..6ddccb9f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/list.h @@ -0,0 +1,103 @@ +/* Copyright (C) 2002, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _LIST_H +#define _LIST_H 1 + +/* The definitions of this file are adopted from those which can be + found in the Linux kernel headers to enable people familiar with + the latter find their way in these sources as well. */ + + +/* Basic type for the double-link list. */ +typedef struct list_head +{ + struct list_head *next; + struct list_head *prev; +} list_t; + + +/* Define a variable with the head and tail of the list. */ +#define LIST_HEAD(name) \ + list_t name = { &(name), &(name) } + +/* Initialize a new list head. */ +#define INIT_LIST_HEAD(ptr) \ + (ptr)->next = (ptr)->prev = (ptr) + + +/* Add new element at the head of the list. */ +static inline void +list_add (list_t *newp, list_t *head) +{ + newp->next = head->next; + newp->prev = head; + head->next->prev = newp; + head->next = newp; +} + + +/* Remove element from list. */ +static inline void +list_del (list_t *elem) +{ + elem->next->prev = elem->prev; + elem->prev->next = elem->next; +} + + +/* Join two lists. */ +static inline void +list_splice (list_t *add, list_t *head) +{ + /* Do nothing if the list which gets added is empty. */ + if (add != add->next) + { + add->next->prev = head; + add->prev->next = head->next; + head->next->prev = add->prev; + head->next = add->next; + } +} + + +/* Get typed element from list at a given position. */ +#define list_entry(ptr, type, member) \ + ((type *) ((char *) (ptr) - (unsigned long) (&((type *) 0)->member))) + + + +/* Iterate forward over the elements of the list. */ +#define list_for_each(pos, head) \ + for (pos = (head)->next; pos != (head); pos = pos->next) + + +/* Iterate forward over the elements of the list. */ +#define list_for_each_prev(pos, head) \ + for (pos = (head)->prev; pos != (head); pos = pos->prev) + + +/* Iterate backwards over the elements list. The list elements can be + removed from the list while doing this. */ +#define list_for_each_prev_safe(pos, p, head) \ + for (pos = (head)->prev, p = pos->prev; \ + pos != (head); \ + pos = p, p = pos->prev) + +#endif /* list.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/malloc-machine.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/malloc-machine.h new file mode 100644 index 00000000..e99aaa78 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/malloc-machine.h @@ -0,0 +1,73 @@ +/* Basic platform-independent macro definitions for mutexes, + thread-specific data and parameters for malloc. + Copyright (C) 2003, 2007, 2008 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _MALLOC_MACHINE_H +#define _MALLOC_MACHINE_H + +#undef thread_atfork_static + +#include +#include + +__libc_lock_define (typedef, mutex_t) + +#define mutex_init(m) __libc_lock_init (*(m)) +#define mutex_lock(m) __libc_lock_lock (*(m)) +#define mutex_trylock(m) __libc_lock_trylock (*(m)) +#define mutex_unlock(m) __libc_lock_unlock (*(m)) + +/* This is defined by newer gcc version unique for each module. */ +extern void *__dso_handle __attribute__ ((__weak__)); + +#include + +#define ATFORK_MEM static struct fork_handler atfork_mem + +#ifdef SHARED +# define thread_atfork(prepare, parent, child) \ + atfork_mem.prepare_handler = prepare; \ + atfork_mem.parent_handler = parent; \ + atfork_mem.child_handler = child; \ + atfork_mem.dso_handle = __dso_handle; \ + atfork_mem.refcntr = 1; \ + __linkin_atfork (&atfork_mem) +#else +# define thread_atfork(prepare, parent, child) \ + atfork_mem.prepare_handler = prepare; \ + atfork_mem.parent_handler = parent; \ + atfork_mem.child_handler = child; \ + atfork_mem.dso_handle = &__dso_handle == NULL ? NULL : __dso_handle; \ + atfork_mem.refcntr = 1; \ + __linkin_atfork (&atfork_mem) +#endif + +/* thread specific data for glibc */ + +#include + +typedef int tsd_key_t[1]; /* no key data structure, libc magic does it */ +__libc_tsd_define (static, void *, MALLOC) /* declaration/common definition */ +#define tsd_key_create(key, destr) ((void) (key)) +#define tsd_setspecific(key, data) __libc_tsd_set (void *, MALLOC, (data)) +#define tsd_getspecific(key, vptr) ((vptr) = __libc_tsd_get (void *, MALLOC)) + +#include + +#endif /* !defined(_MALLOC_MACHINE_H) */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/posix-timer.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/posix-timer.h new file mode 100644 index 00000000..8b4cbc8c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/posix-timer.h @@ -0,0 +1,197 @@ +/* Definitions for POSIX timer implementation on top of NPTL. + Copyright (C) 2000, 2002, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Kaz Kylheku . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include + +/* Double linked list. */ +struct list_links +{ + struct list_links *next; + struct list_links *prev; +}; + + +/* Forward declaration. */ +struct timer_node; + + +/* Definitions for an internal thread of the POSIX timer implementation. */ +struct thread_node +{ + struct list_links links; + pthread_attr_t attr; + pthread_t id; + unsigned int exists; + struct list_links timer_queue; + pthread_cond_t cond; + struct timer_node *current_timer; + pthread_t captured; + clockid_t clock_id; +}; + + +/* Internal representation of a timer. */ +struct timer_node +{ + struct list_links links; + struct sigevent event; + clockid_t clock; + struct itimerspec value; + struct timespec expirytime; + pthread_attr_t attr; + unsigned int abstime; + unsigned int armed; + enum { + TIMER_FREE, TIMER_INUSE, TIMER_DELETED + } inuse; + struct thread_node *thread; + pid_t creator_pid; + int refcount; + int overrun_count; +}; + + +/* The limit is not published if we are compiled with kernel timer support. + But we still compiled in this implementation with its limit unless built + to require the kernel support. */ +#ifndef TIMER_MAX +# define TIMER_MAX 256 +#endif + +/* Static array with the structures for all the timers. */ +extern struct timer_node __timer_array[TIMER_MAX]; + +/* Global lock to protect operation on the lists. */ +extern pthread_mutex_t __timer_mutex; + +/* Variable to protext initialization. */ +extern pthread_once_t __timer_init_once_control; + +/* Nonzero if initialization of timer implementation failed. */ +extern int __timer_init_failed; + +/* Node for the thread used to deliver signals. */ +extern struct thread_node __timer_signal_thread_rclk; + + +/* Return pointer to timer structure corresponding to ID. */ +#define timer_id2ptr(timerid) ((struct timer_node *) timerid) +#define timer_ptr2id(timerid) ((void *) timerid) + +/* Check whether timer is valid; global mutex must be held. */ +static inline int +timer_valid (struct timer_node *timer) +{ + return timer && timer->inuse == TIMER_INUSE; +} + +/* Timer refcount functions; need global mutex. */ +extern void __timer_dealloc (struct timer_node *timer); + +static inline void +timer_addref (struct timer_node *timer) +{ + timer->refcount++; +} + +static inline void +timer_delref (struct timer_node *timer) +{ + if (--timer->refcount == 0) + __timer_dealloc (timer); +} + +/* Timespec helper routines. */ +static inline int +__attribute ((always_inline)) +timespec_compare (const struct timespec *left, const struct timespec *right) +{ + if (left->tv_sec < right->tv_sec) + return -1; + if (left->tv_sec > right->tv_sec) + return 1; + + if (left->tv_nsec < right->tv_nsec) + return -1; + if (left->tv_nsec > right->tv_nsec) + return 1; + + return 0; +} + +static inline void +timespec_add (struct timespec *sum, const struct timespec *left, + const struct timespec *right) +{ + sum->tv_sec = left->tv_sec + right->tv_sec; + sum->tv_nsec = left->tv_nsec + right->tv_nsec; + + if (sum->tv_nsec >= 1000000000) + { + ++sum->tv_sec; + sum->tv_nsec -= 1000000000; + } +} + +static inline void +timespec_sub (struct timespec *diff, const struct timespec *left, + const struct timespec *right) +{ + diff->tv_sec = left->tv_sec - right->tv_sec; + diff->tv_nsec = left->tv_nsec - right->tv_nsec; + + if (diff->tv_nsec < 0) + { + --diff->tv_sec; + diff->tv_nsec += 1000000000; + } +} + + +/* We need one of the list functions in the other modules. */ +static inline void +list_unlink_ip (struct list_links *list) +{ + struct list_links *lnext = list->next, *lprev = list->prev; + + lnext->prev = lprev; + lprev->next = lnext; + + /* The suffix ip means idempotent; list_unlink_ip can be called + * two or more times on the same node. + */ + + list->next = list; + list->prev = list; +} + + +/* Functions in the helper file. */ +extern void __timer_mutex_cancel_handler (void *arg); +extern void __timer_init_once (void); +extern struct timer_node *__timer_alloc (void); +extern int __timer_thread_start (struct thread_node *thread); +extern struct thread_node *__timer_thread_find_matching (const pthread_attr_t *desired_attr, clockid_t); +extern struct thread_node *__timer_thread_alloc (const pthread_attr_t *desired_attr, clockid_t); +extern void __timer_thread_dealloc (struct thread_node *thread); +extern int __timer_thread_queue_timer (struct thread_node *thread, + struct timer_node *insert); +extern void __timer_thread_wakeup (struct thread_node *thread); diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/pt-initfini.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/pt-initfini.c new file mode 100644 index 00000000..1f81144d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/pt-initfini.c @@ -0,0 +1,125 @@ +/* Special .init and .fini section support. Linuxthread version. + Copyright (C) 1995,1996,1997,2000,2001,2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it + and/or modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file with other + programs, and to distribute those programs without any restriction + coming from the use of this file. (The Library General Public + License restrictions do apply in other respects; for example, they + cover modification of the file, and distribution when not linked + into another program.) + + The GNU C Library is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* This file is compiled into assembly code which is then munged by a sed + script into two files: crti.s and crtn.s. + + * crti.s puts a function prologue at the beginning of the + .init and .fini sections and defines global symbols for + those addresses, so they can be called as functions. + + * crtn.s puts the corresponding function epilogues + in the .init and .fini sections. */ + +#include + +/* We use embedded asm for .section unconditionally, as this makes it + easier to insert the necessary directives into crtn.S. */ +#define SECTION(x) __asm__ (".section " x ) + +/* Embed an #include to pull in the alignment and .end directives. */ +__asm__ ("\n#include \"defs.h\""); + +/* The initial common code ends here. */ +__asm__ ("\n/*@HEADER_ENDS*/"); + +/* To determine whether we need .end and .align: */ +__asm__ ("\n/*@TESTS_BEGIN*/"); +extern void dummy (void (*foo) (void)); +void +dummy (void (*foo) (void)) +{ + if (foo) + (*foo) (); +} +__asm__ ("\n/*@TESTS_END*/"); + +/* The beginning of _init: */ +__asm__ ("\n/*@_init_PROLOG_BEGINS*/"); + +static void +call_initialize_minimal (void) +{ + extern void __pthread_initialize_minimal_internal (void) + __attribute ((visibility ("hidden"))); + + __pthread_initialize_minimal_internal (); +} + +SECTION (".init"); +extern void __attribute__ ((section (".init"))) _init (void); +void +_init (void) +{ + /* The very first thing we must do is to set up the registers. */ + call_initialize_minimal (); + + __asm__ ("ALIGN"); + __asm__("END_INIT"); + /* Now the epilog. */ + __asm__ ("\n/*@_init_PROLOG_ENDS*/"); + __asm__ ("\n/*@_init_EPILOG_BEGINS*/"); + SECTION(".init"); +} +__asm__ ("END_INIT"); + +/* End of the _init epilog, beginning of the _fini prolog. */ +__asm__ ("\n/*@_init_EPILOG_ENDS*/"); +__asm__ ("\n/*@_fini_PROLOG_BEGINS*/"); + +SECTION (".fini"); +extern void __attribute__ ((section (".fini"))) _fini (void); +void +_fini (void) +{ + + /* End of the _fini prolog. */ + __asm__ ("ALIGN"); + __asm__ ("END_FINI"); + __asm__ ("\n/*@_fini_PROLOG_ENDS*/"); + + { + /* Let GCC know that _fini is not a leaf function by having a dummy + function call here. We arrange for this call to be omitted from + either crt file. */ + extern void i_am_not_a_leaf (void); + i_am_not_a_leaf (); + } + + /* Beginning of the _fini epilog. */ + __asm__ ("\n/*@_fini_EPILOG_BEGINS*/"); + SECTION (".fini"); +} +__asm__ ("END_FINI"); + +/* End of the _fini epilog. Any further generated assembly (e.g. .ident) + is shared between both crt files. */ +__asm__ ("\n/*@_fini_EPILOG_ENDS*/"); +__asm__ ("\n/*@TRAILER_BEGINS*/"); + +/* End of file. */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/pt-longjmp.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/pt-longjmp.c new file mode 100644 index 00000000..f161380e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/pt-longjmp.c @@ -0,0 +1,29 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include "pthreadP.h" + +void +longjmp (jmp_buf env, int val) +{ + __libc_longjmp (env, val); +} +weak_alias (longjmp, siglongjmp) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/pthread-functions.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/pthread-functions.h new file mode 100644 index 00000000..0ee39e00 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/pthread-functions.h @@ -0,0 +1,117 @@ +/* Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _PTHREAD_FUNCTIONS_H +#define _PTHREAD_FUNCTIONS_H 1 + +#include +#include +#include +#include + +struct xid_command; + +/* Data type shared with libc. The libc uses it to pass on calls to + the thread functions. */ +struct pthread_functions +{ + int (*ptr_pthread_attr_destroy) (pthread_attr_t *); + int (*ptr___pthread_attr_init_2_0) (pthread_attr_t *); + int (*ptr___pthread_attr_init_2_1) (pthread_attr_t *); + int (*ptr_pthread_attr_getdetachstate) (const pthread_attr_t *, int *); + int (*ptr_pthread_attr_setdetachstate) (pthread_attr_t *, int); + int (*ptr_pthread_attr_getinheritsched) (const pthread_attr_t *, int *); + int (*ptr_pthread_attr_setinheritsched) (pthread_attr_t *, int); + int (*ptr_pthread_attr_getschedparam) (const pthread_attr_t *, + struct sched_param *); + int (*ptr_pthread_attr_setschedparam) (pthread_attr_t *, + const struct sched_param *); + int (*ptr_pthread_attr_getschedpolicy) (const pthread_attr_t *, int *); + int (*ptr_pthread_attr_setschedpolicy) (pthread_attr_t *, int); + int (*ptr_pthread_attr_getscope) (const pthread_attr_t *, int *); + int (*ptr_pthread_attr_setscope) (pthread_attr_t *, int); + int (*ptr_pthread_condattr_destroy) (pthread_condattr_t *); + int (*ptr_pthread_condattr_init) (pthread_condattr_t *); + int (*ptr___pthread_cond_broadcast) (pthread_cond_t *); + int (*ptr___pthread_cond_destroy) (pthread_cond_t *); + int (*ptr___pthread_cond_init) (pthread_cond_t *, + const pthread_condattr_t *); + int (*ptr___pthread_cond_signal) (pthread_cond_t *); + int (*ptr___pthread_cond_wait) (pthread_cond_t *, pthread_mutex_t *); + int (*ptr___pthread_cond_timedwait) (pthread_cond_t *, pthread_mutex_t *, + const struct timespec *); + int (*ptr___pthread_cond_broadcast_2_0) (pthread_cond_2_0_t *); + int (*ptr___pthread_cond_destroy_2_0) (pthread_cond_2_0_t *); + int (*ptr___pthread_cond_init_2_0) (pthread_cond_2_0_t *, + const pthread_condattr_t *); + int (*ptr___pthread_cond_signal_2_0) (pthread_cond_2_0_t *); + int (*ptr___pthread_cond_wait_2_0) (pthread_cond_2_0_t *, pthread_mutex_t *); + int (*ptr___pthread_cond_timedwait_2_0) (pthread_cond_2_0_t *, + pthread_mutex_t *, + const struct timespec *); + int (*ptr_pthread_equal) (pthread_t, pthread_t); + void (*ptr___pthread_exit) (void *); + int (*ptr_pthread_getschedparam) (pthread_t, int *, struct sched_param *); + int (*ptr_pthread_setschedparam) (pthread_t, int, + const struct sched_param *); + int (*ptr_pthread_mutex_destroy) (pthread_mutex_t *); + int (*ptr_pthread_mutex_init) (pthread_mutex_t *, + const pthread_mutexattr_t *); + int (*ptr_pthread_mutex_lock) (pthread_mutex_t *); + int (*ptr_pthread_mutex_unlock) (pthread_mutex_t *); + pthread_t (*ptr_pthread_self) (void); + int (*ptr_pthread_setcancelstate) (int, int *); + int (*ptr_pthread_setcanceltype) (int, int *); + void (*ptr___pthread_cleanup_upto) (__jmp_buf, char *); + int (*ptr___pthread_once) (pthread_once_t *, void (*) (void)); + int (*ptr___pthread_rwlock_rdlock) (pthread_rwlock_t *); + int (*ptr___pthread_rwlock_wrlock) (pthread_rwlock_t *); + int (*ptr___pthread_rwlock_unlock) (pthread_rwlock_t *); + int (*ptr___pthread_key_create) (pthread_key_t *, void (*) (void *)); + void *(*ptr___pthread_getspecific) (pthread_key_t); + int (*ptr___pthread_setspecific) (pthread_key_t, const void *); + void (*ptr__pthread_cleanup_push_defer) (struct _pthread_cleanup_buffer *, + void (*) (void *), void *); + void (*ptr__pthread_cleanup_pop_restore) (struct _pthread_cleanup_buffer *, + int); +#define HAVE_PTR_NTHREADS + unsigned int *ptr_nthreads; + void (*ptr___pthread_unwind) (__pthread_unwind_buf_t *) + __attribute ((noreturn)) __cleanup_fct_attribute; + void (*ptr__nptl_deallocate_tsd) (void); + int (*ptr__nptl_setxid) (struct xid_command *); + void (*ptr_freeres) (void); +}; + +/* Variable in libc.so. */ +extern struct pthread_functions __libc_pthread_functions attribute_hidden; +extern int __libc_pthread_functions_init attribute_hidden; + +#if 0 /* def PTR_DEMANGLE */ /* we did not mangle, so do not demangle */ +# define PTHFCT_CALL(fct, params) \ + ({ __typeof (__libc_pthread_functions.fct) __p; \ + __p = __libc_pthread_functions.fct; \ + PTR_DEMANGLE (__p); \ + __p params; }) +#else +# define PTHFCT_CALL(fct, params) \ + __libc_pthread_functions.fct params +#endif + +#endif /* pthread-functions.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/pthread.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/pthread.h new file mode 100644 index 00000000..deb74309 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/pthread.h @@ -0,0 +1,1138 @@ +/* Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _PTHREAD_H +#define _PTHREAD_H 1 + +#include +#include +#include +#include + +#define __need_sigset_t +#include +#include +#include +#include +#if defined _LIBC && ( defined IS_IN_libc || defined NOT_IN_libc ) +#include +#endif + + +/* Detach state. */ +enum +{ + PTHREAD_CREATE_JOINABLE, +#define PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_JOINABLE + PTHREAD_CREATE_DETACHED +#define PTHREAD_CREATE_DETACHED PTHREAD_CREATE_DETACHED +}; + + +/* Mutex types. */ +enum +{ + PTHREAD_MUTEX_TIMED_NP, + PTHREAD_MUTEX_RECURSIVE_NP, + PTHREAD_MUTEX_ERRORCHECK_NP, + PTHREAD_MUTEX_ADAPTIVE_NP +#if defined __USE_UNIX98 || defined __USE_XOPEN2K8 + , + PTHREAD_MUTEX_NORMAL = PTHREAD_MUTEX_TIMED_NP, + PTHREAD_MUTEX_RECURSIVE = PTHREAD_MUTEX_RECURSIVE_NP, + PTHREAD_MUTEX_ERRORCHECK = PTHREAD_MUTEX_ERRORCHECK_NP, + PTHREAD_MUTEX_DEFAULT = PTHREAD_MUTEX_NORMAL +#endif +#ifdef __USE_GNU + /* For compatibility. */ + , PTHREAD_MUTEX_FAST_NP = PTHREAD_MUTEX_TIMED_NP +#endif +}; + + +#ifdef __USE_XOPEN2K +/* Robust mutex or not flags. */ +enum +{ + PTHREAD_MUTEX_STALLED, + PTHREAD_MUTEX_STALLED_NP = PTHREAD_MUTEX_STALLED, + PTHREAD_MUTEX_ROBUST, + PTHREAD_MUTEX_ROBUST_NP = PTHREAD_MUTEX_ROBUST +}; +#endif + + +#ifdef __USE_UNIX98 +/* Mutex protocols. */ +enum +{ + PTHREAD_PRIO_NONE, + PTHREAD_PRIO_INHERIT, + PTHREAD_PRIO_PROTECT +}; +#endif + + +/* Mutex initializers. */ +#if __WORDSIZE == 64 +# define PTHREAD_MUTEX_INITIALIZER \ + { { 0, 0, 0, 0, 0, 0, { 0, 0 } } } +# ifdef __USE_GNU +# define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP \ + { { 0, 0, 0, 0, PTHREAD_MUTEX_RECURSIVE_NP, 0, { 0, 0 } } } +# define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP \ + { { 0, 0, 0, 0, PTHREAD_MUTEX_ERRORCHECK_NP, 0, { 0, 0 } } } +# define PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP \ + { { 0, 0, 0, 0, PTHREAD_MUTEX_ADAPTIVE_NP, 0, { 0, 0 } } } +# endif +#else +# define PTHREAD_MUTEX_INITIALIZER \ + { { 0, 0, 0, 0, 0, { 0 } } } +# ifdef __USE_GNU +# define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP \ + { { 0, 0, 0, PTHREAD_MUTEX_RECURSIVE_NP, 0, { 0 } } } +# define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP \ + { { 0, 0, 0, PTHREAD_MUTEX_ERRORCHECK_NP, 0, { 0 } } } +# define PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP \ + { { 0, 0, 0, PTHREAD_MUTEX_ADAPTIVE_NP, 0, { 0 } } } +# endif +#endif + + +/* Read-write lock types. */ +#if defined __USE_UNIX98 || defined __USE_XOPEN2K +enum +{ + PTHREAD_RWLOCK_PREFER_READER_NP, + PTHREAD_RWLOCK_PREFER_WRITER_NP, + PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP, + PTHREAD_RWLOCK_DEFAULT_NP = PTHREAD_RWLOCK_PREFER_READER_NP +}; + +/* Read-write lock initializers. */ +# define PTHREAD_RWLOCK_INITIALIZER \ + { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } } +# ifdef __USE_GNU +# if __WORDSIZE == 64 +# define PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP \ + { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ + PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP } } +# else +# if __BYTE_ORDER == __LITTLE_ENDIAN +# define PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP \ + { { 0, 0, 0, 0, 0, 0, PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP, \ + 0, 0, 0, 0 } } +# else +# define PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP \ + { { 0, 0, 0, 0, 0, 0, 0, 0, 0, PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP,\ + 0 } } +# endif +# endif +# endif +#endif /* Unix98 or XOpen2K */ + + +/* Scheduler inheritance. */ +enum +{ + PTHREAD_INHERIT_SCHED, +#define PTHREAD_INHERIT_SCHED PTHREAD_INHERIT_SCHED + PTHREAD_EXPLICIT_SCHED +#define PTHREAD_EXPLICIT_SCHED PTHREAD_EXPLICIT_SCHED +}; + + +/* Scope handling. */ +enum +{ + PTHREAD_SCOPE_SYSTEM, +#define PTHREAD_SCOPE_SYSTEM PTHREAD_SCOPE_SYSTEM + PTHREAD_SCOPE_PROCESS +#define PTHREAD_SCOPE_PROCESS PTHREAD_SCOPE_PROCESS +}; + + +/* Process shared or private flag. */ +enum +{ + PTHREAD_PROCESS_PRIVATE, +#define PTHREAD_PROCESS_PRIVATE PTHREAD_PROCESS_PRIVATE + PTHREAD_PROCESS_SHARED +#define PTHREAD_PROCESS_SHARED PTHREAD_PROCESS_SHARED +}; + + + +/* Conditional variable handling. */ +#define PTHREAD_COND_INITIALIZER { { 0, 0, 0, 0, 0, (void *) 0, 0, 0 } } + + +/* Cleanup buffers */ +struct _pthread_cleanup_buffer +{ + void (*__routine) (void *); /* Function to call. */ + void *__arg; /* Its argument. */ + int __canceltype; /* Saved cancellation type. */ + struct _pthread_cleanup_buffer *__prev; /* Chaining of cleanup functions. */ +}; + +/* Cancellation */ +enum +{ + PTHREAD_CANCEL_ENABLE, +#define PTHREAD_CANCEL_ENABLE PTHREAD_CANCEL_ENABLE + PTHREAD_CANCEL_DISABLE +#define PTHREAD_CANCEL_DISABLE PTHREAD_CANCEL_DISABLE +}; +enum +{ + PTHREAD_CANCEL_DEFERRED, +#define PTHREAD_CANCEL_DEFERRED PTHREAD_CANCEL_DEFERRED + PTHREAD_CANCEL_ASYNCHRONOUS +#define PTHREAD_CANCEL_ASYNCHRONOUS PTHREAD_CANCEL_ASYNCHRONOUS +}; +#define PTHREAD_CANCELED ((void *) -1) + + +/* Single execution handling. */ +#define PTHREAD_ONCE_INIT 0 + + +#ifdef __USE_XOPEN2K +/* Value returned by 'pthread_barrier_wait' for one of the threads after + the required number of threads have called this function. + -1 is distinct from 0 and all errno constants */ +# define PTHREAD_BARRIER_SERIAL_THREAD -1 +#endif + + +__BEGIN_DECLS + +/* Create a new thread, starting with execution of START-ROUTINE + getting passed ARG. Creation attributed come from ATTR. The new + handle is stored in *NEWTHREAD. */ +extern int pthread_create (pthread_t *__restrict __newthread, + __const pthread_attr_t *__restrict __attr, + void *(*__start_routine) (void *), + void *__restrict __arg) __THROW __nonnull ((1, 3)); + +/* Terminate calling thread. + + The registered cleanup handlers are called via exception handling + so we cannot mark this function with __THROW.*/ +extern void pthread_exit (void *__retval) __attribute__ ((__noreturn__)); + +/* Make calling thread wait for termination of the thread TH. The + exit status of the thread is stored in *THREAD_RETURN, if THREAD_RETURN + is not NULL. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern int pthread_join (pthread_t __th, void **__thread_return); + +#ifdef __USE_GNU +/* Check whether thread TH has terminated. If yes return the status of + the thread in *THREAD_RETURN, if THREAD_RETURN is not NULL. */ +extern int pthread_tryjoin_np (pthread_t __th, void **__thread_return) __THROW; + +/* Make calling thread wait for termination of the thread TH, but only + until TIMEOUT. The exit status of the thread is stored in + *THREAD_RETURN, if THREAD_RETURN is not NULL. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern int pthread_timedjoin_np (pthread_t __th, void **__thread_return, + __const struct timespec *__abstime); +#endif + +/* Indicate that the thread TH is never to be joined with PTHREAD_JOIN. + The resources of TH will therefore be freed immediately when it + terminates, instead of waiting for another thread to perform PTHREAD_JOIN + on it. */ +extern int pthread_detach (pthread_t __th) __THROW; + + +/* Obtain the identifier of the current thread. */ +extern pthread_t pthread_self (void) __THROW __attribute__ ((__const__)); + +/* Compare two thread identifiers. */ +extern int pthread_equal (pthread_t __thread1, pthread_t __thread2) __THROW; + + +/* Thread attribute handling. */ + +/* Initialize thread attribute *ATTR with default attributes + (detachstate is PTHREAD_JOINABLE, scheduling policy is SCHED_OTHER, + no user-provided stack). */ +extern int pthread_attr_init (pthread_attr_t *__attr) __THROW __nonnull ((1)); + +/* Destroy thread attribute *ATTR. */ +extern int pthread_attr_destroy (pthread_attr_t *__attr) + __THROW __nonnull ((1)); + +/* Get detach state attribute. */ +extern int pthread_attr_getdetachstate (__const pthread_attr_t *__attr, + int *__detachstate) + __THROW __nonnull ((1, 2)); + +/* Set detach state attribute. */ +extern int pthread_attr_setdetachstate (pthread_attr_t *__attr, + int __detachstate) + __THROW __nonnull ((1)); + + +/* Get the size of the guard area created for stack overflow protection. */ +extern int pthread_attr_getguardsize (__const pthread_attr_t *__attr, + size_t *__guardsize) + __THROW __nonnull ((1, 2)); + +/* Set the size of the guard area created for stack overflow protection. */ +extern int pthread_attr_setguardsize (pthread_attr_t *__attr, + size_t __guardsize) + __THROW __nonnull ((1)); + + +/* Return in *PARAM the scheduling parameters of *ATTR. */ +extern int pthread_attr_getschedparam (__const pthread_attr_t *__restrict + __attr, + struct sched_param *__restrict __param) + __THROW __nonnull ((1, 2)); + +/* Set scheduling parameters (priority, etc) in *ATTR according to PARAM. */ +extern int pthread_attr_setschedparam (pthread_attr_t *__restrict __attr, + __const struct sched_param *__restrict + __param) __THROW __nonnull ((1, 2)); + +/* Return in *POLICY the scheduling policy of *ATTR. */ +extern int pthread_attr_getschedpolicy (__const pthread_attr_t *__restrict + __attr, int *__restrict __policy) + __THROW __nonnull ((1, 2)); + +/* Set scheduling policy in *ATTR according to POLICY. */ +extern int pthread_attr_setschedpolicy (pthread_attr_t *__attr, int __policy) + __THROW __nonnull ((1)); + +/* Return in *INHERIT the scheduling inheritance mode of *ATTR. */ +extern int pthread_attr_getinheritsched (__const pthread_attr_t *__restrict + __attr, int *__restrict __inherit) + __THROW __nonnull ((1, 2)); + +/* Set scheduling inheritance mode in *ATTR according to INHERIT. */ +extern int pthread_attr_setinheritsched (pthread_attr_t *__attr, + int __inherit) + __THROW __nonnull ((1)); + + +/* Return in *SCOPE the scheduling contention scope of *ATTR. */ +extern int pthread_attr_getscope (__const pthread_attr_t *__restrict __attr, + int *__restrict __scope) + __THROW __nonnull ((1, 2)); + +/* Set scheduling contention scope in *ATTR according to SCOPE. */ +extern int pthread_attr_setscope (pthread_attr_t *__attr, int __scope) + __THROW __nonnull ((1)); + +/* Return the previously set address for the stack. */ +extern int pthread_attr_getstackaddr (__const pthread_attr_t *__restrict + __attr, void **__restrict __stackaddr) + __THROW __nonnull ((1, 2)) __attribute_deprecated__; + +/* Set the starting address of the stack of the thread to be created. + Depending on whether the stack grows up or down the value must either + be higher or lower than all the address in the memory block. The + minimal size of the block must be PTHREAD_STACK_MIN. */ +extern int pthread_attr_setstackaddr (pthread_attr_t *__attr, + void *__stackaddr) + __THROW __nonnull ((1)) __attribute_deprecated__; + +/* Return the currently used minimal stack size. */ +extern int pthread_attr_getstacksize (__const pthread_attr_t *__restrict + __attr, size_t *__restrict __stacksize) + __THROW __nonnull ((1, 2)); + +/* Add information about the minimum stack size needed for the thread + to be started. This size must never be less than PTHREAD_STACK_MIN + and must also not exceed the system limits. */ +extern int pthread_attr_setstacksize (pthread_attr_t *__attr, + size_t __stacksize) + __THROW __nonnull ((1)); + +#ifdef __USE_XOPEN2K +/* Return the previously set address for the stack. */ +extern int pthread_attr_getstack (__const pthread_attr_t *__restrict __attr, + void **__restrict __stackaddr, + size_t *__restrict __stacksize) + __THROW __nonnull ((1, 2, 3)); + +/* The following two interfaces are intended to replace the last two. They + require setting the address as well as the size since only setting the + address will make the implementation on some architectures impossible. */ +extern int pthread_attr_setstack (pthread_attr_t *__attr, void *__stackaddr, + size_t __stacksize) __THROW __nonnull ((1)); +#endif + +#ifdef __USE_GNU +/* Thread created with attribute ATTR will be limited to run only on + the processors represented in CPUSET. */ +extern int pthread_attr_setaffinity_np (pthread_attr_t *__attr, + size_t __cpusetsize, + __const cpu_set_t *__cpuset) + __THROW __nonnull ((1, 3)); + +/* Get bit set in CPUSET representing the processors threads created with + ATTR can run on. */ +extern int pthread_attr_getaffinity_np (__const pthread_attr_t *__attr, + size_t __cpusetsize, + cpu_set_t *__cpuset) + __THROW __nonnull ((1, 3)); + + +/* Initialize thread attribute *ATTR with attributes corresponding to the + already running thread TH. It shall be called on uninitialized ATTR + and destroyed with pthread_attr_destroy when no longer needed. */ +extern int pthread_getattr_np (pthread_t __th, pthread_attr_t *__attr) + __THROW __nonnull ((2)); +#endif + + +/* Functions for scheduling control. */ + +/* Set the scheduling parameters for TARGET_THREAD according to POLICY + and *PARAM. */ +extern int pthread_setschedparam (pthread_t __target_thread, int __policy, + __const struct sched_param *__param) + __THROW __nonnull ((3)); + +/* Return in *POLICY and *PARAM the scheduling parameters for TARGET_THREAD. */ +extern int pthread_getschedparam (pthread_t __target_thread, + int *__restrict __policy, + struct sched_param *__restrict __param) + __THROW __nonnull ((2, 3)); + +/* Set the scheduling priority for TARGET_THREAD. */ +extern int pthread_setschedprio (pthread_t __target_thread, int __prio) + __THROW; + + +#ifdef __USE_UNIX98 +/* Determine level of concurrency. */ +extern int pthread_getconcurrency (void) __THROW; + +/* Set new concurrency level to LEVEL. */ +extern int pthread_setconcurrency (int __level) __THROW; +#endif + +#ifdef __USE_GNU +/* Yield the processor to another thread or process. + This function is similar to the POSIX `sched_yield' function but + might be differently implemented in the case of a m-on-n thread + implementation. */ +extern int pthread_yield (void) __THROW; + + +/* Limit specified thread TH to run only on the processors represented + in CPUSET. */ +extern int pthread_setaffinity_np (pthread_t __th, size_t __cpusetsize, + __const cpu_set_t *__cpuset) + __THROW __nonnull ((3)); + +/* Get bit set in CPUSET representing the processors TH can run on. */ +extern int pthread_getaffinity_np (pthread_t __th, size_t __cpusetsize, + cpu_set_t *__cpuset) + __THROW __nonnull ((3)); +#endif + + +/* Functions for handling initialization. */ + +/* Guarantee that the initialization function INIT_ROUTINE will be called + only once, even if pthread_once is executed several times with the + same ONCE_CONTROL argument. ONCE_CONTROL must point to a static or + extern variable initialized to PTHREAD_ONCE_INIT. + + The initialization functions might throw exception which is why + this function is not marked with __THROW. */ +extern int pthread_once (pthread_once_t *__once_control, + void (*__init_routine) (void)) __nonnull ((1, 2)); + + +/* Functions for handling cancellation. + + Note that these functions are explicitly not marked to not throw an + exception in C++ code. If cancellation is implemented by unwinding + this is necessary to have the compiler generate the unwind information. */ + +/* Set cancelability state of current thread to STATE, returning old + state in *OLDSTATE if OLDSTATE is not NULL. */ +extern int pthread_setcancelstate (int __state, int *__oldstate); + +/* Set cancellation state of current thread to TYPE, returning the old + type in *OLDTYPE if OLDTYPE is not NULL. */ +extern int pthread_setcanceltype (int __type, int *__oldtype); + +/* Cancel THREAD immediately or at the next possibility. */ +extern int pthread_cancel (pthread_t __th); + +/* Test for pending cancellation for the current thread and terminate + the thread as per pthread_exit(PTHREAD_CANCELED) if it has been + cancelled. */ +extern void pthread_testcancel (void); + + +/* Cancellation handling with integration into exception handling. */ + +typedef struct +{ + struct + { + __jmp_buf __cancel_jmp_buf; + int __mask_was_saved; + } __cancel_jmp_buf[1]; + void *__pad[4]; +} __pthread_unwind_buf_t __attribute__ ((__aligned__)); + +/* No special attributes by default. */ +#ifndef __cleanup_fct_attribute +# define __cleanup_fct_attribute +#endif + + +/* Structure to hold the cleanup handler information. */ +struct __pthread_cleanup_frame +{ + void (*__cancel_routine) (void *); + void *__cancel_arg; + int __do_it; + int __cancel_type; +}; + +#if defined __GNUC__ && defined __EXCEPTIONS +# ifdef __cplusplus +/* Class to handle cancellation handler invocation. */ +class __pthread_cleanup_class +{ + void (*__cancel_routine) (void *); + void *__cancel_arg; + int __do_it; + int __cancel_type; + + public: + __pthread_cleanup_class (void (*__fct) (void *), void *__arg) + : __cancel_routine (__fct), __cancel_arg (__arg), __do_it (1) { } + ~__pthread_cleanup_class () { if (__do_it) __cancel_routine (__cancel_arg); } + void __setdoit (int __newval) { __do_it = __newval; } + void __defer () { pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, + &__cancel_type); } + void __restore () const { pthread_setcanceltype (__cancel_type, 0); } +}; + +/* Install a cleanup handler: ROUTINE will be called with arguments ARG + when the thread is canceled or calls pthread_exit. ROUTINE will also + be called with arguments ARG when the matching pthread_cleanup_pop + is executed with non-zero EXECUTE argument. + + pthread_cleanup_push and pthread_cleanup_pop are macros and must always + be used in matching pairs at the same nesting level of braces. */ +# define pthread_cleanup_push(routine, arg) \ + do { \ + __pthread_cleanup_class __clframe (routine, arg) + +/* Remove a cleanup handler installed by the matching pthread_cleanup_push. + If EXECUTE is non-zero, the handler function is called. */ +# define pthread_cleanup_pop(execute) \ + __clframe.__setdoit (execute); \ + } while (0) + +# ifdef __USE_GNU +/* Install a cleanup handler as pthread_cleanup_push does, but also + saves the current cancellation type and sets it to deferred + cancellation. */ +# define pthread_cleanup_push_defer_np(routine, arg) \ + do { \ + __pthread_cleanup_class __clframe (routine, arg); \ + __clframe.__defer () + +/* Remove a cleanup handler as pthread_cleanup_pop does, but also + restores the cancellation type that was in effect when the matching + pthread_cleanup_push_defer was called. */ +# define pthread_cleanup_pop_restore_np(execute) \ + __clframe.__restore (); \ + __clframe.__setdoit (execute); \ + } while (0) +# endif +# else +/* Function called to call the cleanup handler. As an extern inline + function the compiler is free to decide inlining the change when + needed or fall back on the copy which must exist somewhere + else. */ +__extern_inline void +__pthread_cleanup_routine (struct __pthread_cleanup_frame *__frame) +{ + if (__frame->__do_it) + __frame->__cancel_routine (__frame->__cancel_arg); +} + +/* Install a cleanup handler: ROUTINE will be called with arguments ARG + when the thread is canceled or calls pthread_exit. ROUTINE will also + be called with arguments ARG when the matching pthread_cleanup_pop + is executed with non-zero EXECUTE argument. + + pthread_cleanup_push and pthread_cleanup_pop are macros and must always + be used in matching pairs at the same nesting level of braces. */ +# define pthread_cleanup_push(routine, arg) \ + do { \ + struct __pthread_cleanup_frame __clframe \ + __attribute__ ((__cleanup__ (__pthread_cleanup_routine))) \ + = { .__cancel_routine = (routine), .__cancel_arg = (arg), \ + .__do_it = 1 }; + +/* Remove a cleanup handler installed by the matching pthread_cleanup_push. + If EXECUTE is non-zero, the handler function is called. */ +# define pthread_cleanup_pop(execute) \ + __clframe.__do_it = (execute); \ + } while (0) + +# ifdef __USE_GNU +/* Install a cleanup handler as pthread_cleanup_push does, but also + saves the current cancellation type and sets it to deferred + cancellation. */ +# define pthread_cleanup_push_defer_np(routine, arg) \ + do { \ + struct __pthread_cleanup_frame __clframe \ + __attribute__ ((__cleanup__ (__pthread_cleanup_routine))) \ + = { .__cancel_routine = (routine), .__cancel_arg = (arg), \ + .__do_it = 1 }; \ + (void) pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, \ + &__clframe.__cancel_type) + +/* Remove a cleanup handler as pthread_cleanup_pop does, but also + restores the cancellation type that was in effect when the matching + pthread_cleanup_push_defer was called. */ +# define pthread_cleanup_pop_restore_np(execute) \ + (void) pthread_setcanceltype (__clframe.__cancel_type, NULL); \ + __clframe.__do_it = (execute); \ + } while (0) +# endif +# endif +#else +/* Install a cleanup handler: ROUTINE will be called with arguments ARG + when the thread is canceled or calls pthread_exit. ROUTINE will also + be called with arguments ARG when the matching pthread_cleanup_pop + is executed with non-zero EXECUTE argument. + + pthread_cleanup_push and pthread_cleanup_pop are macros and must always + be used in matching pairs at the same nesting level of braces. */ +# define pthread_cleanup_push(routine, arg) \ + do { \ + __pthread_unwind_buf_t __cancel_buf; \ + void (*__cancel_routine) (void *) = (routine); \ + void *__cancel_arg = (arg); \ + int not_first_call = __sigsetjmp ((struct __jmp_buf_tag *) (void *) \ + __cancel_buf.__cancel_jmp_buf, 0); \ + if (__builtin_expect (not_first_call, 0)) \ + { \ + __cancel_routine (__cancel_arg); \ + __pthread_unwind_next (&__cancel_buf); \ + /* NOTREACHED */ \ + } \ + \ + __pthread_register_cancel (&__cancel_buf); \ + do { +extern void __pthread_register_cancel (__pthread_unwind_buf_t *__buf) + __cleanup_fct_attribute; + +/* Remove a cleanup handler installed by the matching pthread_cleanup_push. + If EXECUTE is non-zero, the handler function is called. */ +# define pthread_cleanup_pop(execute) \ + do { } while (0);/* Empty to allow label before pthread_cleanup_pop. */\ + } while (0); \ + __pthread_unregister_cancel (&__cancel_buf); \ + if (execute) \ + __cancel_routine (__cancel_arg); \ + } while (0) +extern void __pthread_unregister_cancel (__pthread_unwind_buf_t *__buf) + __cleanup_fct_attribute; + +# ifdef __USE_GNU +/* Install a cleanup handler as pthread_cleanup_push does, but also + saves the current cancellation type and sets it to deferred + cancellation. */ +# define pthread_cleanup_push_defer_np(routine, arg) \ + do { \ + __pthread_unwind_buf_t __cancel_buf; \ + void (*__cancel_routine) (void *) = (routine); \ + void *__cancel_arg = (arg); \ + int not_first_call = __sigsetjmp ((struct __jmp_buf_tag *) (void *) \ + __cancel_buf.__cancel_jmp_buf, 0); \ + if (__builtin_expect (not_first_call, 0)) \ + { \ + __cancel_routine (__cancel_arg); \ + __pthread_unwind_next (&__cancel_buf); \ + /* NOTREACHED */ \ + } \ + \ + __pthread_register_cancel_defer (&__cancel_buf); \ + do { +extern void __pthread_register_cancel_defer (__pthread_unwind_buf_t *__buf) + __cleanup_fct_attribute; + +/* Remove a cleanup handler as pthread_cleanup_pop does, but also + restores the cancellation type that was in effect when the matching + pthread_cleanup_push_defer was called. */ +# define pthread_cleanup_pop_restore_np(execute) \ + do { } while (0);/* Empty to allow label before pthread_cleanup_pop. */\ + } while (0); \ + __pthread_unregister_cancel_restore (&__cancel_buf); \ + if (execute) \ + __cancel_routine (__cancel_arg); \ + } while (0) +extern void __pthread_unregister_cancel_restore (__pthread_unwind_buf_t *__buf) + __cleanup_fct_attribute; +# endif + +/* Internal interface to initiate cleanup. */ +extern void __pthread_unwind_next (__pthread_unwind_buf_t *__buf) + __cleanup_fct_attribute __attribute__ ((__noreturn__)) +# ifndef SHARED + __attribute__ ((__weak__)) +# endif + ; +#endif + +/* Function used in the macros. */ +struct __jmp_buf_tag; +extern int __sigsetjmp (struct __jmp_buf_tag *__env, int __savemask) __THROW; + + +/* Mutex handling. */ + +/* Initialize a mutex. */ +extern int pthread_mutex_init (pthread_mutex_t *__mutex, + __const pthread_mutexattr_t *__mutexattr) + __THROW __nonnull ((1)); + +/* Destroy a mutex. */ +extern int pthread_mutex_destroy (pthread_mutex_t *__mutex) + __THROW __nonnull ((1)); + +/* Try locking a mutex. */ +extern int pthread_mutex_trylock (pthread_mutex_t *__mutex) + __THROW __nonnull ((1)); + +/* Lock a mutex. */ +extern int pthread_mutex_lock (pthread_mutex_t *__mutex) + __THROW __nonnull ((1)); + +#ifdef __USE_XOPEN2K +/* Wait until lock becomes available, or specified time passes. */ +extern int pthread_mutex_timedlock (pthread_mutex_t *__restrict __mutex, + __const struct timespec *__restrict + __abstime) __THROW __nonnull ((1, 2)); +#endif + +/* Unlock a mutex. */ +extern int pthread_mutex_unlock (pthread_mutex_t *__mutex) + __THROW __nonnull ((1)); + + +/* Get the priority ceiling of MUTEX. */ +extern int pthread_mutex_getprioceiling (__const pthread_mutex_t * + __restrict __mutex, + int *__restrict __prioceiling) + __THROW __nonnull ((1, 2)); + +/* Set the priority ceiling of MUTEX to PRIOCEILING, return old + priority ceiling value in *OLD_CEILING. */ +extern int pthread_mutex_setprioceiling (pthread_mutex_t *__restrict __mutex, + int __prioceiling, + int *__restrict __old_ceiling) + __THROW __nonnull ((1, 3)); + + +#ifdef __USE_XOPEN2K8 +/* Declare the state protected by MUTEX as consistent. */ +extern int pthread_mutex_consistent (pthread_mutex_t *__mutex) + __THROW __nonnull ((1)); +# ifdef __USE_GNU +extern int pthread_mutex_consistent_np (pthread_mutex_t *__mutex) + __THROW __nonnull ((1)); +# endif +#endif + + +/* Functions for handling mutex attributes. */ + +/* Initialize mutex attribute object ATTR with default attributes + (kind is PTHREAD_MUTEX_TIMED_NP). */ +extern int pthread_mutexattr_init (pthread_mutexattr_t *__attr) + __THROW __nonnull ((1)); + +/* Destroy mutex attribute object ATTR. */ +extern int pthread_mutexattr_destroy (pthread_mutexattr_t *__attr) + __THROW __nonnull ((1)); + +/* Get the process-shared flag of the mutex attribute ATTR. */ +extern int pthread_mutexattr_getpshared (__const pthread_mutexattr_t * + __restrict __attr, + int *__restrict __pshared) + __THROW __nonnull ((1, 2)); + +/* Set the process-shared flag of the mutex attribute ATTR. */ +extern int pthread_mutexattr_setpshared (pthread_mutexattr_t *__attr, + int __pshared) + __THROW __nonnull ((1)); + +#if defined __USE_UNIX98 || defined __USE_XOPEN2K8 +/* Return in *KIND the mutex kind attribute in *ATTR. */ +extern int pthread_mutexattr_gettype (__const pthread_mutexattr_t *__restrict + __attr, int *__restrict __kind) + __THROW __nonnull ((1, 2)); + +/* Set the mutex kind attribute in *ATTR to KIND (either PTHREAD_MUTEX_NORMAL, + PTHREAD_MUTEX_RECURSIVE, PTHREAD_MUTEX_ERRORCHECK, or + PTHREAD_MUTEX_DEFAULT). */ +extern int pthread_mutexattr_settype (pthread_mutexattr_t *__attr, int __kind) + __THROW __nonnull ((1)); +#endif + +/* Return in *PROTOCOL the mutex protocol attribute in *ATTR. */ +extern int pthread_mutexattr_getprotocol (__const pthread_mutexattr_t * + __restrict __attr, + int *__restrict __protocol) + __THROW __nonnull ((1, 2)); + +/* Set the mutex protocol attribute in *ATTR to PROTOCOL (either + PTHREAD_PRIO_NONE, PTHREAD_PRIO_INHERIT, or PTHREAD_PRIO_PROTECT). */ +extern int pthread_mutexattr_setprotocol (pthread_mutexattr_t *__attr, + int __protocol) + __THROW __nonnull ((1)); + +/* Return in *PRIOCEILING the mutex prioceiling attribute in *ATTR. */ +extern int pthread_mutexattr_getprioceiling (__const pthread_mutexattr_t * + __restrict __attr, + int *__restrict __prioceiling) + __THROW __nonnull ((1, 2)); + +/* Set the mutex prioceiling attribute in *ATTR to PRIOCEILING. */ +extern int pthread_mutexattr_setprioceiling (pthread_mutexattr_t *__attr, + int __prioceiling) + __THROW __nonnull ((1)); + +#ifdef __USE_XOPEN2K +/* Get the robustness flag of the mutex attribute ATTR. */ +extern int pthread_mutexattr_getrobust (__const pthread_mutexattr_t *__attr, + int *__robustness) + __THROW __nonnull ((1, 2)); +# ifdef __USE_GNU +extern int pthread_mutexattr_getrobust_np (__const pthread_mutexattr_t *__attr, + int *__robustness) + __THROW __nonnull ((1, 2)); +# endif + +/* Set the robustness flag of the mutex attribute ATTR. */ +extern int pthread_mutexattr_setrobust (pthread_mutexattr_t *__attr, + int __robustness) + __THROW __nonnull ((1)); +# ifdef __USE_GNU +extern int pthread_mutexattr_setrobust_np (pthread_mutexattr_t *__attr, + int __robustness) + __THROW __nonnull ((1)); +# endif +#endif + + +#if defined __USE_UNIX98 || defined __USE_XOPEN2K +/* Functions for handling read-write locks. */ + +/* Initialize read-write lock RWLOCK using attributes ATTR, or use + the default values if later is NULL. */ +extern int pthread_rwlock_init (pthread_rwlock_t *__restrict __rwlock, + __const pthread_rwlockattr_t *__restrict + __attr) __THROW __nonnull ((1)); + +/* Destroy read-write lock RWLOCK. */ +extern int pthread_rwlock_destroy (pthread_rwlock_t *__rwlock) + __THROW __nonnull ((1)); + +/* Acquire read lock for RWLOCK. */ +extern int pthread_rwlock_rdlock (pthread_rwlock_t *__rwlock) + __THROW __nonnull ((1)); + +/* Try to acquire read lock for RWLOCK. */ +extern int pthread_rwlock_tryrdlock (pthread_rwlock_t *__rwlock) + __THROW __nonnull ((1)); + +# ifdef __USE_XOPEN2K +/* Try to acquire read lock for RWLOCK or return after specfied time. */ +extern int pthread_rwlock_timedrdlock (pthread_rwlock_t *__restrict __rwlock, + __const struct timespec *__restrict + __abstime) __THROW __nonnull ((1, 2)); +# endif + +/* Acquire write lock for RWLOCK. */ +extern int pthread_rwlock_wrlock (pthread_rwlock_t *__rwlock) + __THROW __nonnull ((1)); + +/* Try to acquire write lock for RWLOCK. */ +extern int pthread_rwlock_trywrlock (pthread_rwlock_t *__rwlock) + __THROW __nonnull ((1)); + +# ifdef __USE_XOPEN2K +/* Try to acquire write lock for RWLOCK or return after specfied time. */ +extern int pthread_rwlock_timedwrlock (pthread_rwlock_t *__restrict __rwlock, + __const struct timespec *__restrict + __abstime) __THROW __nonnull ((1, 2)); +# endif + +/* Unlock RWLOCK. */ +extern int pthread_rwlock_unlock (pthread_rwlock_t *__rwlock) + __THROW __nonnull ((1)); + + +/* Functions for handling read-write lock attributes. */ + +/* Initialize attribute object ATTR with default values. */ +extern int pthread_rwlockattr_init (pthread_rwlockattr_t *__attr) + __THROW __nonnull ((1)); + +/* Destroy attribute object ATTR. */ +extern int pthread_rwlockattr_destroy (pthread_rwlockattr_t *__attr) + __THROW __nonnull ((1)); + +/* Return current setting of process-shared attribute of ATTR in PSHARED. */ +extern int pthread_rwlockattr_getpshared (__const pthread_rwlockattr_t * + __restrict __attr, + int *__restrict __pshared) + __THROW __nonnull ((1, 2)); + +/* Set process-shared attribute of ATTR to PSHARED. */ +extern int pthread_rwlockattr_setpshared (pthread_rwlockattr_t *__attr, + int __pshared) + __THROW __nonnull ((1)); + +/* Return current setting of reader/writer preference. */ +extern int pthread_rwlockattr_getkind_np (__const pthread_rwlockattr_t * + __restrict __attr, + int *__restrict __pref) + __THROW __nonnull ((1, 2)); + +/* Set reader/write preference. */ +extern int pthread_rwlockattr_setkind_np (pthread_rwlockattr_t *__attr, + int __pref) __THROW __nonnull ((1)); +#endif + + +/* Functions for handling conditional variables. */ + +/* Initialize condition variable COND using attributes ATTR, or use + the default values if later is NULL. */ +extern int pthread_cond_init (pthread_cond_t *__restrict __cond, + __const pthread_condattr_t *__restrict + __cond_attr) __THROW __nonnull ((1)); + +/* Destroy condition variable COND. */ +extern int pthread_cond_destroy (pthread_cond_t *__cond) + __THROW __nonnull ((1)); + +/* Wake up one thread waiting for condition variable COND. */ +extern int pthread_cond_signal (pthread_cond_t *__cond) + __THROW __nonnull ((1)); + +/* Wake up all threads waiting for condition variables COND. */ +extern int pthread_cond_broadcast (pthread_cond_t *__cond) + __THROW __nonnull ((1)); + +/* Wait for condition variable COND to be signaled or broadcast. + MUTEX is assumed to be locked before. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern int pthread_cond_wait (pthread_cond_t *__restrict __cond, + pthread_mutex_t *__restrict __mutex) + __nonnull ((1, 2)); + +/* Wait for condition variable COND to be signaled or broadcast until + ABSTIME. MUTEX is assumed to be locked before. ABSTIME is an + absolute time specification; zero is the beginning of the epoch + (00:00:00 GMT, January 1, 1970). + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern int pthread_cond_timedwait (pthread_cond_t *__restrict __cond, + pthread_mutex_t *__restrict __mutex, + __const struct timespec *__restrict + __abstime) __nonnull ((1, 2, 3)); + +/* Functions for handling condition variable attributes. */ + +/* Initialize condition variable attribute ATTR. */ +extern int pthread_condattr_init (pthread_condattr_t *__attr) + __THROW __nonnull ((1)); + +/* Destroy condition variable attribute ATTR. */ +extern int pthread_condattr_destroy (pthread_condattr_t *__attr) + __THROW __nonnull ((1)); + +/* Get the process-shared flag of the condition variable attribute ATTR. */ +extern int pthread_condattr_getpshared (__const pthread_condattr_t * + __restrict __attr, + int *__restrict __pshared) + __THROW __nonnull ((1, 2)); + +/* Set the process-shared flag of the condition variable attribute ATTR. */ +extern int pthread_condattr_setpshared (pthread_condattr_t *__attr, + int __pshared) __THROW __nonnull ((1)); + +#ifdef __USE_XOPEN2K +/* Get the clock selected for the conditon variable attribute ATTR. */ +extern int pthread_condattr_getclock (__const pthread_condattr_t * + __restrict __attr, + __clockid_t *__restrict __clock_id) + __THROW __nonnull ((1, 2)); + +/* Set the clock selected for the conditon variable attribute ATTR. */ +extern int pthread_condattr_setclock (pthread_condattr_t *__attr, + __clockid_t __clock_id) + __THROW __nonnull ((1)); +#endif + + +#ifdef __USE_XOPEN2K +/* Functions to handle spinlocks. */ + +/* Initialize the spinlock LOCK. If PSHARED is nonzero the spinlock can + be shared between different processes. */ +extern int pthread_spin_init (pthread_spinlock_t *__lock, int __pshared) + __THROW __nonnull ((1)); + +/* Destroy the spinlock LOCK. */ +extern int pthread_spin_destroy (pthread_spinlock_t *__lock) + __THROW __nonnull ((1)); + +/* Wait until spinlock LOCK is retrieved. */ +extern int pthread_spin_lock (pthread_spinlock_t *__lock) + __THROW __nonnull ((1)); + +/* Try to lock spinlock LOCK. */ +extern int pthread_spin_trylock (pthread_spinlock_t *__lock) + __THROW __nonnull ((1)); + +/* Release spinlock LOCK. */ +extern int pthread_spin_unlock (pthread_spinlock_t *__lock) + __THROW __nonnull ((1)); + + +/* Functions to handle barriers. */ + +/* Initialize BARRIER with the attributes in ATTR. The barrier is + opened when COUNT waiters arrived. */ +extern int pthread_barrier_init (pthread_barrier_t *__restrict __barrier, + __const pthread_barrierattr_t *__restrict + __attr, unsigned int __count) + __THROW __nonnull ((1)); + +/* Destroy a previously dynamically initialized barrier BARRIER. */ +extern int pthread_barrier_destroy (pthread_barrier_t *__barrier) + __THROW __nonnull ((1)); + +/* Wait on barrier BARRIER. */ +extern int pthread_barrier_wait (pthread_barrier_t *__barrier) + __THROW __nonnull ((1)); + + +/* Initialize barrier attribute ATTR. */ +extern int pthread_barrierattr_init (pthread_barrierattr_t *__attr) + __THROW __nonnull ((1)); + +/* Destroy previously dynamically initialized barrier attribute ATTR. */ +extern int pthread_barrierattr_destroy (pthread_barrierattr_t *__attr) + __THROW __nonnull ((1)); + +/* Get the process-shared flag of the barrier attribute ATTR. */ +extern int pthread_barrierattr_getpshared (__const pthread_barrierattr_t * + __restrict __attr, + int *__restrict __pshared) + __THROW __nonnull ((1, 2)); + +/* Set the process-shared flag of the barrier attribute ATTR. */ +extern int pthread_barrierattr_setpshared (pthread_barrierattr_t *__attr, + int __pshared) + __THROW __nonnull ((1)); +#endif + + +/* Functions for handling thread-specific data. */ + +/* Create a key value identifying a location in the thread-specific + data area. Each thread maintains a distinct thread-specific data + area. DESTR_FUNCTION, if non-NULL, is called with the value + associated to that key when the key is destroyed. + DESTR_FUNCTION is not called if the value associated is NULL when + the key is destroyed. */ +extern int pthread_key_create (pthread_key_t *__key, + void (*__destr_function) (void *)) + __THROW __nonnull ((1)); + +/* Destroy KEY. */ +extern int pthread_key_delete (pthread_key_t __key) __THROW; + +/* Return current value of the thread-specific data slot identified by KEY. */ +extern void *pthread_getspecific (pthread_key_t __key) __THROW; + +/* Store POINTER in the thread-specific data slot identified by KEY. */ +extern int pthread_setspecific (pthread_key_t __key, + __const void *__pointer) __THROW ; + + +#ifdef __USE_XOPEN2K +/* Get ID of CPU-time clock for thread THREAD_ID. */ +extern int pthread_getcpuclockid (pthread_t __thread_id, + __clockid_t *__clock_id) + __THROW __nonnull ((2)); +#endif + + +/* Install handlers to be called when a new process is created with FORK. + The PREPARE handler is called in the parent process just before performing + FORK. The PARENT handler is called in the parent process just after FORK. + The CHILD handler is called in the child process. Each of the three + handlers can be NULL, meaning that no handler needs to be called at that + point. + PTHREAD_ATFORK can be called several times, in which case the PREPARE + handlers are called in LIFO order (last added with PTHREAD_ATFORK, + first called before FORK), and the PARENT and CHILD handlers are called + in FIFO (first added, first called). */ + +extern int pthread_atfork (void (*__prepare) (void), + void (*__parent) (void), + void (*__child) (void)) __THROW; + + +#ifdef __USE_EXTERN_INLINES +/* Optimizations. */ +__extern_inline int +__NTH (pthread_equal (pthread_t __thread1, pthread_t __thread2)) +{ + return __thread1 == __thread2; +} +#endif + +__END_DECLS + +#endif /* pthread.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/pthread_barrier_destroy.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/pthread_barrier_destroy.c new file mode 100644 index 00000000..2afe5b3c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/pthread_barrier_destroy.c @@ -0,0 +1,44 @@ +/* Copyright (C) 2002, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include "pthreadP.h" +#include + + +int +pthread_barrier_destroy ( + pthread_barrier_t *barrier) +{ + struct pthread_barrier *ibarrier; + int result = EBUSY; + + ibarrier = (struct pthread_barrier *) barrier; + + lll_lock (ibarrier->lock, ibarrier->private ^ FUTEX_PRIVATE_FLAG); + + if (__builtin_expect (ibarrier->left == ibarrier->init_count, 1)) + /* The barrier is not used anymore. */ + result = 0; + else + /* Still used, return with an error. */ + lll_unlock (ibarrier->lock, ibarrier->private ^ FUTEX_PRIVATE_FLAG); + + return result; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/pthread_barrier_init.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/pthread_barrier_init.c new file mode 100644 index 00000000..f0396f92 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/pthread_barrier_init.c @@ -0,0 +1,71 @@ +/* Copyright (C) 2002, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include "pthreadP.h" +#include +#include + + +static const struct pthread_barrierattr default_attr = + { + .pshared = PTHREAD_PROCESS_PRIVATE + }; + + +int +pthread_barrier_init ( + pthread_barrier_t *barrier, + const pthread_barrierattr_t *attr, + unsigned int count) +{ + struct pthread_barrier *ibarrier; + + if (__builtin_expect (count == 0, 0)) + return EINVAL; + + const struct pthread_barrierattr *iattr + = (attr != NULL + ? iattr = (struct pthread_barrierattr *) attr + : &default_attr); + + if (iattr->pshared != PTHREAD_PROCESS_PRIVATE + && __builtin_expect (iattr->pshared != PTHREAD_PROCESS_SHARED, 0)) + /* Invalid attribute. */ + return EINVAL; + + ibarrier = (struct pthread_barrier *) barrier; + + /* Initialize the individual fields. */ + ibarrier->lock = LLL_LOCK_INITIALIZER; + ibarrier->left = count; + ibarrier->init_count = count; + ibarrier->curr_event = 0; + +#ifdef __ASSUME_PRIVATE_FUTEX + ibarrier->private = (iattr->pshared != PTHREAD_PROCESS_PRIVATE + ? 0 : FUTEX_PRIVATE_FLAG); +#else + ibarrier->private = (iattr->pshared != PTHREAD_PROCESS_PRIVATE + ? 0 : THREAD_GETMEM (THREAD_SELF, + header.private_futex)); +#endif + + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/pthread_barrier_wait.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/pthread_barrier_wait.c new file mode 100644 index 00000000..d1135391 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/pthread_barrier_wait.c @@ -0,0 +1,79 @@ +/* Copyright (C) 2003, 2004, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Martin Schwidefsky , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + + +/* Wait on barrier. */ +int +pthread_barrier_wait ( + pthread_barrier_t *barrier) +{ + struct pthread_barrier *ibarrier = (struct pthread_barrier *) barrier; + int result = 0; + + /* Make sure we are alone. */ + lll_lock (ibarrier->lock, ibarrier->private ^ FUTEX_PRIVATE_FLAG); + + /* One more arrival. */ + --ibarrier->left; + + /* Are these all? */ + if (ibarrier->left == 0) + { + /* Yes. Increment the event counter to avoid invalid wake-ups and + tell the current waiters that it is their turn. */ + ++ibarrier->curr_event; + + /* Wake up everybody. */ + lll_futex_wake (&ibarrier->curr_event, INT_MAX, + ibarrier->private ^ FUTEX_PRIVATE_FLAG); + + /* This is the thread which finished the serialization. */ + result = PTHREAD_BARRIER_SERIAL_THREAD; + } + else + { + /* The number of the event we are waiting for. The barrier's event + number must be bumped before we continue. */ + unsigned int event = ibarrier->curr_event; + + /* Before suspending, make the barrier available to others. */ + lll_unlock (ibarrier->lock, ibarrier->private ^ FUTEX_PRIVATE_FLAG); + + /* Wait for the event counter of the barrier to change. */ + do + lll_futex_wait (&ibarrier->curr_event, event, + ibarrier->private ^ FUTEX_PRIVATE_FLAG); + while (event == ibarrier->curr_event); + } + + /* Make sure the init_count is stored locally or in a register. */ + unsigned int init_count = ibarrier->init_count; + + /* If this was the last woken thread, unlock. */ + if (atomic_increment_val (&ibarrier->left) == init_count) + /* We are done. */ + lll_unlock (ibarrier->lock, ibarrier->private ^ FUTEX_PRIVATE_FLAG); + + return result; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/pthread_cond_broadcast.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/pthread_cond_broadcast.c new file mode 100644 index 00000000..df915523 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/pthread_cond_broadcast.c @@ -0,0 +1,90 @@ +/* Copyright (C) 2003, 2004, 2006, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Martin Schwidefsky , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include + +#include + + +int +attribute_protected +__pthread_cond_broadcast ( + pthread_cond_t *cond) +{ + int pshared = (cond->__data.__mutex == (void *) ~0l) + ? LLL_SHARED : LLL_PRIVATE; + /* Make sure we are alone. */ + lll_lock (cond->__data.__lock, pshared); + + /* Are there any waiters to be woken? */ + if (cond->__data.__total_seq > cond->__data.__wakeup_seq) + { + /* Yes. Mark them all as woken. */ + cond->__data.__wakeup_seq = cond->__data.__total_seq; + cond->__data.__woken_seq = cond->__data.__total_seq; + cond->__data.__futex = (unsigned int) cond->__data.__total_seq * 2; + int futex_val = cond->__data.__futex; + /* Signal that a broadcast happened. */ + ++cond->__data.__broadcast_seq; + + /* We are done. */ + lll_unlock (cond->__data.__lock, pshared); + + /* Do not use requeue for pshared condvars. */ + if (cond->__data.__mutex == (void *) ~0l) + goto wake_all; + + /* Wake everybody. */ + pthread_mutex_t *mut = (pthread_mutex_t *) cond->__data.__mutex; + + /* XXX: Kernel so far doesn't support requeue to PI futex. */ + /* XXX: Kernel so far can only requeue to the same type of futex, + in this case private (we don't requeue for pshared condvars). */ + if (__builtin_expect (mut->__data.__kind + & (PTHREAD_MUTEX_PRIO_INHERIT_NP + | PTHREAD_MUTEX_PSHARED_BIT), 0)) + goto wake_all; + + /* lll_futex_requeue returns 0 for success and non-zero + for errors. */ + if (__builtin_expect (lll_futex_requeue (&cond->__data.__futex, 1, + INT_MAX, &mut->__data.__lock, + futex_val, LLL_PRIVATE), 0)) + { + /* The requeue functionality is not available. */ + wake_all: + lll_futex_wake (&cond->__data.__futex, INT_MAX, pshared); + } + + /* That's all. */ + return 0; + } + + /* We are done. */ + lll_unlock (cond->__data.__lock, pshared); + + return 0; +} + +weak_alias(__pthread_cond_broadcast, pthread_cond_broadcast) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/pthread_cond_signal.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/pthread_cond_signal.c new file mode 100644 index 00000000..b207aa8e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/pthread_cond_signal.c @@ -0,0 +1,63 @@ +/* Copyright (C) 2003, 2004, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Martin Schwidefsky , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include + +#include + + +int +attribute_protected +__pthread_cond_signal ( + pthread_cond_t *cond) +{ + int pshared = (cond->__data.__mutex == (void *) ~0l) + ? LLL_SHARED : LLL_PRIVATE; + + /* Make sure we are alone. */ + lll_lock (cond->__data.__lock, pshared); + + /* Are there any waiters to be woken? */ + if (cond->__data.__total_seq > cond->__data.__wakeup_seq) + { + /* Yes. Mark one of them as woken. */ + ++cond->__data.__wakeup_seq; + ++cond->__data.__futex; + + /* Wake one. */ + if (! __builtin_expect (lll_futex_wake_unlock (&cond->__data.__futex, 1, + 1, &cond->__data.__lock, + pshared), 0)) + return 0; + + lll_futex_wake (&cond->__data.__futex, 1, pshared); + } + + /* We are done. */ + lll_unlock (cond->__data.__lock, pshared); + + return 0; +} + +weak_alias(__pthread_cond_signal, pthread_cond_signal) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/pthread_cond_timedwait.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/pthread_cond_timedwait.c new file mode 100644 index 00000000..7f367538 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/pthread_cond_timedwait.c @@ -0,0 +1,216 @@ +/* Copyright (C) 2003, 2004, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Martin Schwidefsky , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include +#include + + +/* Cleanup handler, defined in pthread_cond_wait.c. */ +extern void __condvar_cleanup (void *arg) + __attribute__ ((visibility ("hidden"))); + +struct _condvar_cleanup_buffer +{ + int oldtype; + pthread_cond_t *cond; + pthread_mutex_t *mutex; + unsigned int bc_seq; +}; + +int +attribute_protected +__pthread_cond_timedwait ( + pthread_cond_t *cond, + pthread_mutex_t *mutex, + const struct timespec *abstime) +{ + struct _pthread_cleanup_buffer buffer; + struct _condvar_cleanup_buffer cbuffer; + int result = 0; + + /* Catch invalid parameters. */ + if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) + return EINVAL; + + int pshared = (cond->__data.__mutex == (void *) ~0l) + ? LLL_SHARED : LLL_PRIVATE; + + /* Make sure we are along. */ + lll_lock (cond->__data.__lock, pshared); + + /* Now we can release the mutex. */ + int err = __pthread_mutex_unlock_usercnt (mutex, 0); + if (err) + { + lll_unlock (cond->__data.__lock, pshared); + return err; + } + + /* We have one new user of the condvar. */ + ++cond->__data.__total_seq; + ++cond->__data.__futex; + cond->__data.__nwaiters += 1 << COND_NWAITERS_SHIFT; + + /* Remember the mutex we are using here. If there is already a + different address store this is a bad user bug. Do not store + anything for pshared condvars. */ + if (cond->__data.__mutex != (void *) ~0l) + cond->__data.__mutex = mutex; + + /* Prepare structure passed to cancellation handler. */ + cbuffer.cond = cond; + cbuffer.mutex = mutex; + + /* Before we block we enable cancellation. Therefore we have to + install a cancellation handler. */ + __pthread_cleanup_push (&buffer, __condvar_cleanup, &cbuffer); + + /* The current values of the wakeup counter. The "woken" counter + must exceed this value. */ + unsigned long long int val; + unsigned long long int seq; + val = seq = cond->__data.__wakeup_seq; + /* Remember the broadcast counter. */ + cbuffer.bc_seq = cond->__data.__broadcast_seq; + + while (1) + { + struct timespec rt; + { +#ifdef __NR_clock_gettime + INTERNAL_SYSCALL_DECL (err); + int ret; + ret = INTERNAL_SYSCALL (clock_gettime, err, 2, + (cond->__data.__nwaiters + & ((1 << COND_NWAITERS_SHIFT) - 1)), + &rt); +# ifndef __ASSUME_POSIX_TIMERS + if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (ret, err), 0)) + { + struct timeval tv; + (void) gettimeofday (&tv, NULL); + + /* Convert the absolute timeout value to a relative timeout. */ + rt.tv_sec = abstime->tv_sec - tv.tv_sec; + rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000; + } + else +# endif + { + /* Convert the absolute timeout value to a relative timeout. */ + rt.tv_sec = abstime->tv_sec - rt.tv_sec; + rt.tv_nsec = abstime->tv_nsec - rt.tv_nsec; + } +#else + /* Get the current time. So far we support only one clock. */ + struct timeval tv; + (void) gettimeofday (&tv, NULL); + + /* Convert the absolute timeout value to a relative timeout. */ + rt.tv_sec = abstime->tv_sec - tv.tv_sec; + rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000; +#endif + } + if (rt.tv_nsec < 0) + { + rt.tv_nsec += 1000000000; + --rt.tv_sec; + } + /* Did we already time out? */ + if (__builtin_expect (rt.tv_sec < 0, 0)) + { + if (cbuffer.bc_seq != cond->__data.__broadcast_seq) + goto bc_out; + + goto timeout; + } + + unsigned int futex_val = cond->__data.__futex; + + /* Prepare to wait. Release the condvar futex. */ + lll_unlock (cond->__data.__lock, pshared); + + /* Enable asynchronous cancellation. Required by the standard. */ + cbuffer.oldtype = __pthread_enable_asynccancel (); + + /* Wait until woken by signal or broadcast. */ + err = lll_futex_timed_wait (&cond->__data.__futex, + futex_val, &rt, pshared); + + /* Disable asynchronous cancellation. */ + __pthread_disable_asynccancel (cbuffer.oldtype); + + /* We are going to look at shared data again, so get the lock. */ + lll_lock (cond->__data.__lock, pshared); + + /* If a broadcast happened, we are done. */ + if (cbuffer.bc_seq != cond->__data.__broadcast_seq) + goto bc_out; + + /* Check whether we are eligible for wakeup. */ + val = cond->__data.__wakeup_seq; + if (val != seq && cond->__data.__woken_seq != val) + break; + + /* Not woken yet. Maybe the time expired? */ + if (__builtin_expect (err == -ETIMEDOUT, 0)) + { + timeout: + /* Yep. Adjust the counters. */ + ++cond->__data.__wakeup_seq; + ++cond->__data.__futex; + + /* The error value. */ + result = ETIMEDOUT; + break; + } + } + + /* Another thread woken up. */ + ++cond->__data.__woken_seq; + + bc_out: + + cond->__data.__nwaiters -= 1 << COND_NWAITERS_SHIFT; + + /* If pthread_cond_destroy was called on this variable already, + notify the pthread_cond_destroy caller all waiters have left + and it can be successfully destroyed. */ + if (cond->__data.__total_seq == -1ULL + && cond->__data.__nwaiters < (1 << COND_NWAITERS_SHIFT)) + lll_futex_wake (&cond->__data.__nwaiters, 1, pshared); + + /* We are done with the condvar. */ + lll_unlock (cond->__data.__lock, pshared); + + /* The cancellation handling is back to normal, remove the handler. */ + __pthread_cleanup_pop (&buffer, 0); + + /* Get the mutex before returning. */ + err = __pthread_mutex_cond_lock (mutex); + + return err ?: result; +} + +weak_alias(__pthread_cond_timedwait, pthread_cond_timedwait) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/pthread_cond_wait.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/pthread_cond_wait.c new file mode 100644 index 00000000..05157ba1 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/pthread_cond_wait.c @@ -0,0 +1,193 @@ +/* Copyright (C) 2003, 2004, 2006, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Martin Schwidefsky , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include + + +struct _condvar_cleanup_buffer +{ + int oldtype; + pthread_cond_t *cond; + pthread_mutex_t *mutex; + unsigned int bc_seq; +}; + + +void +__attribute__ ((visibility ("hidden"))) +__condvar_cleanup (void *arg) +{ + struct _condvar_cleanup_buffer *cbuffer = + (struct _condvar_cleanup_buffer *) arg; + unsigned int destroying; + int pshared = (cbuffer->cond->__data.__mutex == (void *) ~0l) + ? LLL_SHARED : LLL_PRIVATE; + + /* We are going to modify shared data. */ + lll_lock (cbuffer->cond->__data.__lock, pshared); + + if (cbuffer->bc_seq == cbuffer->cond->__data.__broadcast_seq) + { + /* This thread is not waiting anymore. Adjust the sequence counters + appropriately. We do not increment WAKEUP_SEQ if this would + bump it over the value of TOTAL_SEQ. This can happen if a thread + was woken and then canceled. */ + if (cbuffer->cond->__data.__wakeup_seq + < cbuffer->cond->__data.__total_seq) + { + ++cbuffer->cond->__data.__wakeup_seq; + ++cbuffer->cond->__data.__futex; + } + ++cbuffer->cond->__data.__woken_seq; + } + + cbuffer->cond->__data.__nwaiters -= 1 << COND_NWAITERS_SHIFT; + + /* If pthread_cond_destroy was called on this variable already, + notify the pthread_cond_destroy caller all waiters have left + and it can be successfully destroyed. */ + destroying = 0; + if (cbuffer->cond->__data.__total_seq == -1ULL + && cbuffer->cond->__data.__nwaiters < (1 << COND_NWAITERS_SHIFT)) + { + lll_futex_wake (&cbuffer->cond->__data.__nwaiters, 1, pshared); + destroying = 1; + } + + /* We are done. */ + lll_unlock (cbuffer->cond->__data.__lock, pshared); + + /* Wake everybody to make sure no condvar signal gets lost. */ + if (! destroying) + lll_futex_wake (&cbuffer->cond->__data.__futex, INT_MAX, pshared); + + /* Get the mutex before returning unless asynchronous cancellation + is in effect. */ + __pthread_mutex_cond_lock (cbuffer->mutex); +} + + +int +attribute_protected +__pthread_cond_wait ( + pthread_cond_t *cond, + pthread_mutex_t *mutex) +{ + struct _pthread_cleanup_buffer buffer; + struct _condvar_cleanup_buffer cbuffer; + int err; + int pshared = (cond->__data.__mutex == (void *) ~0l) + ? LLL_SHARED : LLL_PRIVATE; + + /* Make sure we are along. */ + lll_lock (cond->__data.__lock, pshared); + + /* Now we can release the mutex. */ + err = __pthread_mutex_unlock_usercnt (mutex, 0); + if (__builtin_expect (err, 0)) + { + lll_unlock (cond->__data.__lock, pshared); + return err; + } + + /* We have one new user of the condvar. */ + ++cond->__data.__total_seq; + ++cond->__data.__futex; + cond->__data.__nwaiters += 1 << COND_NWAITERS_SHIFT; + + /* Remember the mutex we are using here. If there is already a + different address store this is a bad user bug. Do not store + anything for pshared condvars. */ + if (cond->__data.__mutex != (void *) ~0l) + cond->__data.__mutex = mutex; + + /* Prepare structure passed to cancellation handler. */ + cbuffer.cond = cond; + cbuffer.mutex = mutex; + + /* Before we block we enable cancellation. Therefore we have to + install a cancellation handler. */ + __pthread_cleanup_push (&buffer, __condvar_cleanup, &cbuffer); + + /* The current values of the wakeup counter. The "woken" counter + must exceed this value. */ + unsigned long long int val; + unsigned long long int seq; + val = seq = cond->__data.__wakeup_seq; + /* Remember the broadcast counter. */ + cbuffer.bc_seq = cond->__data.__broadcast_seq; + + do + { + unsigned int futex_val = cond->__data.__futex; + + /* Prepare to wait. Release the condvar futex. */ + lll_unlock (cond->__data.__lock, pshared); + + /* Enable asynchronous cancellation. Required by the standard. */ + cbuffer.oldtype = __pthread_enable_asynccancel (); + + /* Wait until woken by signal or broadcast. */ + lll_futex_wait (&cond->__data.__futex, futex_val, pshared); + + /* Disable asynchronous cancellation. */ + __pthread_disable_asynccancel (cbuffer.oldtype); + + /* We are going to look at shared data again, so get the lock. */ + lll_lock (cond->__data.__lock, pshared); + + /* If a broadcast happened, we are done. */ + if (cbuffer.bc_seq != cond->__data.__broadcast_seq) + goto bc_out; + + /* Check whether we are eligible for wakeup. */ + val = cond->__data.__wakeup_seq; + } + while (val == seq || cond->__data.__woken_seq == val); + + /* Another thread woken up. */ + ++cond->__data.__woken_seq; + + bc_out: + + cond->__data.__nwaiters -= 1 << COND_NWAITERS_SHIFT; + + /* If pthread_cond_destroy was called on this varaible already, + notify the pthread_cond_destroy caller all waiters have left + and it can be successfully destroyed. */ + if (cond->__data.__total_seq == -1ULL + && cond->__data.__nwaiters < (1 << COND_NWAITERS_SHIFT)) + lll_futex_wake (&cond->__data.__nwaiters, 1, pshared); + + /* We are done with the condvar. */ + lll_unlock (cond->__data.__lock, pshared); + + /* The cancellation handling is back to normal, remove the handler. */ + __pthread_cleanup_pop (&buffer, 0); + + /* Get the mutex before returning. */ + return __pthread_mutex_cond_lock (mutex); +} + +weak_alias(__pthread_cond_wait, pthread_cond_wait) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/pthread_once.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/pthread_once.c new file mode 100644 index 00000000..57bb6b97 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/pthread_once.c @@ -0,0 +1,54 @@ +/* Copyright (C) 2002, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "pthreadP.h" +#include + + + +static int once_lock = LLL_LOCK_INITIALIZER; + + +int +__pthread_once ( + pthread_once_t *once_control, + void (*init_routine) (void)) +{ + /* XXX Depending on whether the LOCK_IN_ONCE_T is defined use a + global lock variable or one which is part of the pthread_once_t + object. */ + if (*once_control == PTHREAD_ONCE_INIT) + { + lll_lock (once_lock, LLL_PRIVATE); + + /* XXX This implementation is not complete. It doesn't take + cancelation and fork into account. */ + if (*once_control == PTHREAD_ONCE_INIT) + { + init_routine (); + + *once_control = !PTHREAD_ONCE_INIT; + } + + lll_unlock (once_lock, LLL_PRIVATE); + } + + return 0; +} +strong_alias (__pthread_once, pthread_once) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/pthread_rwlock_rdlock.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/pthread_rwlock_rdlock.c new file mode 100644 index 00000000..98840f93 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/pthread_rwlock_rdlock.c @@ -0,0 +1,97 @@ +/* Copyright (C) 2003, 2004, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Martin Schwidefsky , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include + + +/* Acquire read lock for RWLOCK. */ +int +attribute_protected +__pthread_rwlock_rdlock ( + pthread_rwlock_t *rwlock) +{ + int result = 0; + + /* Make sure we are along. */ + lll_lock (rwlock->__data.__lock, rwlock->__data.__shared); + + while (1) + { + /* Get the rwlock if there is no writer... */ + if (rwlock->__data.__writer == 0 + /* ...and if either no writer is waiting or we prefer readers. */ + && (!rwlock->__data.__nr_writers_queued + || PTHREAD_RWLOCK_PREFER_READER_P (rwlock))) + { + /* Increment the reader counter. Avoid overflow. */ + if (__builtin_expect (++rwlock->__data.__nr_readers == 0, 0)) + { + /* Overflow on number of readers. */ + --rwlock->__data.__nr_readers; + result = EAGAIN; + } + + break; + } + + /* Make sure we are not holding the rwlock as a writer. This is + a deadlock situation we recognize and report. */ + if (__builtin_expect (rwlock->__data.__writer + == THREAD_GETMEM (THREAD_SELF, tid), 0)) + { + result = EDEADLK; + break; + } + + /* Remember that we are a reader. */ + if (__builtin_expect (++rwlock->__data.__nr_readers_queued == 0, 0)) + { + /* Overflow on number of queued readers. */ + --rwlock->__data.__nr_readers_queued; + result = EAGAIN; + break; + } + + int waitval = rwlock->__data.__readers_wakeup; + + /* Free the lock. */ + lll_unlock (rwlock->__data.__lock, rwlock->__data.__shared); + + /* Wait for the writer to finish. */ + lll_futex_wait (&rwlock->__data.__readers_wakeup, waitval, + rwlock->__data.__shared); + + /* Get the lock. */ + lll_lock (rwlock->__data.__lock, rwlock->__data.__shared); + + --rwlock->__data.__nr_readers_queued; + } + + /* We are done, free the lock. */ + lll_unlock (rwlock->__data.__lock, rwlock->__data.__shared); + + return result; +} + +weak_alias (__pthread_rwlock_rdlock, pthread_rwlock_rdlock) +strong_alias (__pthread_rwlock_rdlock, __pthread_rwlock_rdlock_internal) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/pthread_rwlock_timedrdlock.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/pthread_rwlock_timedrdlock.c new file mode 100644 index 00000000..3daefc71 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/pthread_rwlock_timedrdlock.c @@ -0,0 +1,137 @@ +/* Copyright (C) 2003, 2004, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Martin Schwidefsky , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include + + +/* Try to acquire read lock for RWLOCK or return after specfied time. */ +int +pthread_rwlock_timedrdlock ( + pthread_rwlock_t *rwlock, + const struct timespec *abstime) +{ + int result = 0; + + /* Make sure we are along. */ + lll_lock(rwlock->__data.__lock, rwlock->__data.__shared); + + while (1) + { + int err; + + /* Get the rwlock if there is no writer... */ + if (rwlock->__data.__writer == 0 + /* ...and if either no writer is waiting or we prefer readers. */ + && (!rwlock->__data.__nr_writers_queued + || PTHREAD_RWLOCK_PREFER_READER_P (rwlock))) + { + /* Increment the reader counter. Avoid overflow. */ + if (++rwlock->__data.__nr_readers == 0) + { + /* Overflow on number of readers. */ + --rwlock->__data.__nr_readers; + result = EAGAIN; + } + + break; + } + + /* Make sure we are not holding the rwlock as a writer. This is + a deadlock situation we recognize and report. */ + if (__builtin_expect (rwlock->__data.__writer + == THREAD_GETMEM (THREAD_SELF, tid), 0)) + { + result = EDEADLK; + break; + } + + /* Make sure the passed in timeout value is valid. Ideally this + test would be executed once. But since it must not be + performed if we would not block at all simply moving the test + to the front is no option. Replicating all the code is + costly while this test is not. */ + if (__builtin_expect (abstime->tv_nsec >= 1000000000 + || abstime->tv_nsec < 0, 0)) + { + result = EINVAL; + break; + } + + /* Get the current time. So far we support only one clock. */ + struct timeval tv; + (void) gettimeofday (&tv, NULL); + + /* Convert the absolute timeout value to a relative timeout. */ + struct timespec rt; + rt.tv_sec = abstime->tv_sec - tv.tv_sec; + rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000; + if (rt.tv_nsec < 0) + { + rt.tv_nsec += 1000000000; + --rt.tv_sec; + } + /* Did we already time out? */ + if (rt.tv_sec < 0) + { + /* Yep, return with an appropriate error. */ + result = ETIMEDOUT; + break; + } + + /* Remember that we are a reader. */ + if (++rwlock->__data.__nr_readers_queued == 0) + { + /* Overflow on number of queued readers. */ + --rwlock->__data.__nr_readers_queued; + result = EAGAIN; + break; + } + + int waitval = rwlock->__data.__readers_wakeup; + + /* Free the lock. */ + lll_unlock (rwlock->__data.__lock, rwlock->__data.__shared); + + /* Wait for the writer to finish. */ + err = lll_futex_timed_wait (&rwlock->__data.__readers_wakeup, + waitval, &rt, rwlock->__data.__shared); + + /* Get the lock. */ + lll_lock (rwlock->__data.__lock, rwlock->__data.__shared); + + --rwlock->__data.__nr_readers_queued; + + /* Did the futex call time out? */ + if (err == -ETIMEDOUT) + { + /* Yep, report it. */ + result = ETIMEDOUT; + break; + } + } + + /* We are done, free the lock. */ + lll_unlock (rwlock->__data.__lock, rwlock->__data.__shared); + + return result; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/pthread_rwlock_timedwrlock.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/pthread_rwlock_timedwrlock.c new file mode 100644 index 00000000..e6fcb164 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/pthread_rwlock_timedwrlock.c @@ -0,0 +1,127 @@ +/* Copyright (C) 2003, 2004, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Martin Schwidefsky , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include + + +/* Try to acquire write lock for RWLOCK or return after specfied time. */ +int +pthread_rwlock_timedwrlock ( + pthread_rwlock_t *rwlock, + const struct timespec *abstime) +{ + int result = 0; + + /* Make sure we are along. */ + lll_lock (rwlock->__data.__lock, rwlock->__data.__shared); + + while (1) + { + int err; + + /* Get the rwlock if there is no writer and no reader. */ + if (rwlock->__data.__writer == 0 && rwlock->__data.__nr_readers == 0) + { + /* Mark self as writer. */ + rwlock->__data.__writer = THREAD_GETMEM (THREAD_SELF, tid); + break; + } + + /* Make sure we are not holding the rwlock as a writer. This is + a deadlock situation we recognize and report. */ + if (__builtin_expect (rwlock->__data.__writer + == THREAD_GETMEM (THREAD_SELF, tid), 0)) + { + result = EDEADLK; + break; + } + + /* Make sure the passed in timeout value is valid. Ideally this + test would be executed once. But since it must not be + performed if we would not block at all simply moving the test + to the front is no option. Replicating all the code is + costly while this test is not. */ + if (__builtin_expect (abstime->tv_nsec >= 1000000000 + || abstime->tv_nsec < 0, 0)) + { + result = EINVAL; + break; + } + + /* Get the current time. So far we support only one clock. */ + struct timeval tv; + (void) gettimeofday (&tv, NULL); + + /* Convert the absolute timeout value to a relative timeout. */ + struct timespec rt; + rt.tv_sec = abstime->tv_sec - tv.tv_sec; + rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000; + if (rt.tv_nsec < 0) + { + rt.tv_nsec += 1000000000; + --rt.tv_sec; + } + /* Did we already time out? */ + if (rt.tv_sec < 0) + { + result = ETIMEDOUT; + break; + } + + /* Remember that we are a writer. */ + if (++rwlock->__data.__nr_writers_queued == 0) + { + /* Overflow on number of queued writers. */ + --rwlock->__data.__nr_writers_queued; + result = EAGAIN; + break; + } + + int waitval = rwlock->__data.__writer_wakeup; + + /* Free the lock. */ + lll_unlock (rwlock->__data.__lock, rwlock->__data.__shared); + + /* Wait for the writer or reader(s) to finish. */ + err = lll_futex_timed_wait (&rwlock->__data.__writer_wakeup, + waitval, &rt, rwlock->__data.__shared); + + /* Get the lock. */ + lll_lock (rwlock->__data.__lock, rwlock->__data.__shared); + + /* To start over again, remove the thread from the writer list. */ + --rwlock->__data.__nr_writers_queued; + + /* Did the futex call time out? */ + if (err == -ETIMEDOUT) + { + result = ETIMEDOUT; + break; + } + } + + /* We are done, free the lock. */ + lll_unlock (rwlock->__data.__lock, rwlock->__data.__shared); + + return result; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/pthread_rwlock_unlock.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/pthread_rwlock_unlock.c new file mode 100644 index 00000000..855fc198 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/pthread_rwlock_unlock.c @@ -0,0 +1,60 @@ +/* Copyright (C) 2003, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Martin Schwidefsky , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include + +/* Unlock RWLOCK. */ +int +attribute_protected +__pthread_rwlock_unlock (pthread_rwlock_t *rwlock) +{ + lll_lock (rwlock->__data.__lock, rwlock->__data.__shared); + if (rwlock->__data.__writer) + rwlock->__data.__writer = 0; + else + --rwlock->__data.__nr_readers; + if (rwlock->__data.__nr_readers == 0) + { + if (rwlock->__data.__nr_writers_queued) + { + ++rwlock->__data.__writer_wakeup; + lll_unlock (rwlock->__data.__lock, rwlock->__data.__shared); + lll_futex_wake (&rwlock->__data.__writer_wakeup, 1, + rwlock->__data.__shared); + return 0; + } + else if (rwlock->__data.__nr_readers_queued) + { + ++rwlock->__data.__readers_wakeup; + lll_unlock (rwlock->__data.__lock, rwlock->__data.__shared); + lll_futex_wake (&rwlock->__data.__readers_wakeup, INT_MAX, + rwlock->__data.__shared); + return 0; + } + } + lll_unlock (rwlock->__data.__lock, rwlock->__data.__shared); + return 0; +} + +weak_alias (__pthread_rwlock_unlock, pthread_rwlock_unlock) +strong_alias (__pthread_rwlock_unlock, __pthread_rwlock_unlock_internal) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/pthread_rwlock_wrlock.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/pthread_rwlock_wrlock.c new file mode 100644 index 00000000..9a441afe --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/pthread_rwlock_wrlock.c @@ -0,0 +1,89 @@ +/* Copyright (C) 2003, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Martin Schwidefsky , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include + + +/* Acquire write lock for RWLOCK. */ +int +attribute_protected +__pthread_rwlock_wrlock ( + pthread_rwlock_t *rwlock) +{ + int result = 0; + + /* Make sure we are along. */ + lll_lock (rwlock->__data.__lock, rwlock->__data.__shared); + + while (1) + { + /* Get the rwlock if there is no writer and no reader. */ + if (rwlock->__data.__writer == 0 && rwlock->__data.__nr_readers == 0) + { + /* Mark self as writer. */ + rwlock->__data.__writer = THREAD_GETMEM (THREAD_SELF, tid); + break; + } + + /* Make sure we are not holding the rwlock as a writer. This is + a deadlock situation we recognize and report. */ + if (__builtin_expect (rwlock->__data.__writer + == THREAD_GETMEM (THREAD_SELF, tid), 0)) + { + result = EDEADLK; + break; + } + + /* Remember that we are a writer. */ + if (++rwlock->__data.__nr_writers_queued == 0) + { + /* Overflow on number of queued writers. */ + --rwlock->__data.__nr_writers_queued; + result = EAGAIN; + break; + } + + int waitval = rwlock->__data.__writer_wakeup; + + /* Free the lock. */ + lll_unlock (rwlock->__data.__lock, rwlock->__data.__shared); + + /* Wait for the writer or reader(s) to finish. */ + lll_futex_wait (&rwlock->__data.__writer_wakeup, waitval, + rwlock->__data.__shared); + + /* Get the lock. */ + lll_lock (rwlock->__data.__lock, rwlock->__data.__shared); + + /* To start over again, remove the thread from the writer list. */ + --rwlock->__data.__nr_writers_queued; + } + + /* We are done, free the lock. */ + lll_unlock (rwlock->__data.__lock, rwlock->__data.__shared); + + return result; +} + +weak_alias (__pthread_rwlock_wrlock, pthread_rwlock_wrlock) +strong_alias (__pthread_rwlock_wrlock, __pthread_rwlock_wrlock_internal) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/pthread_sigmask.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/pthread_sigmask.c new file mode 100644 index 00000000..6f66bbbf --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/pthread_sigmask.c @@ -0,0 +1,58 @@ +/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + + +int +pthread_sigmask ( + int how, + const sigset_t *newmask, + sigset_t *oldmask) +{ + sigset_t local_newmask; + + /* The only thing we have to make sure here is that SIGCANCEL and + SIGSETXID is not blocked. */ + if (newmask != NULL + && (__builtin_expect (__sigismember (newmask, SIGCANCEL), 0) + || __builtin_expect (__sigismember (newmask, SIGSETXID), 0))) + { + local_newmask = *newmask; + __sigdelset (&local_newmask, SIGCANCEL); + __sigdelset (&local_newmask, SIGSETXID); + newmask = &local_newmask; + } + +#ifdef INTERNAL_SYSCALL + /* We know that realtime signals are available if NPTL is used. */ + INTERNAL_SYSCALL_DECL (err); + int result = INTERNAL_SYSCALL (rt_sigprocmask, err, 4, how, newmask, + oldmask, _NSIG / 8); + + return (INTERNAL_SYSCALL_ERROR_P (result, err) + ? INTERNAL_SYSCALL_ERRNO (result, err) + : 0); +#else + return sigprocmask (how, newmask, oldmask) == -1 ? errno : 0; +#endif +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/pthread_spin_destroy.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/pthread_spin_destroy.c new file mode 100644 index 00000000..7118f8a0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/pthread_spin_destroy.c @@ -0,0 +1,29 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "pthreadP.h" + + +int +pthread_spin_destroy ( + pthread_spinlock_t *lock) +{ + /* Nothing to do. */ + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/pthread_spin_init.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/pthread_spin_init.c new file mode 100644 index 00000000..c2275085 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/pthread_spin_init.c @@ -0,0 +1,28 @@ +/* pthread_spin_init -- initialize a spin lock. Generic version. + Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Paul Mackerras , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "pthreadP.h" + +int +pthread_spin_init (pthread_spinlock_t *lock, int pshared) +{ + *lock = 0; + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/pthread_spin_unlock.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/pthread_spin_unlock.c new file mode 100644 index 00000000..f97cadfb --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/pthread_spin_unlock.c @@ -0,0 +1,30 @@ +/* pthread_spin_unlock -- unlock a spin lock. Generic version. + Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Paul Mackerras , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "pthreadP.h" +#include + +int +pthread_spin_unlock (pthread_spinlock_t *lock) +{ + atomic_full_barrier (); + *lock = 0; + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/rt-unwind-resume.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/rt-unwind-resume.c new file mode 100644 index 00000000..743e675d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/rt-unwind-resume.c @@ -0,0 +1 @@ +#include diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/setxid.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/setxid.h new file mode 100644 index 00000000..aebdbd23 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/setxid.h @@ -0,0 +1,63 @@ +/* Copyright (C) 2004, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +#define __SETXID_1(cmd, arg1) \ + cmd.id[0] = arg1 +#define __SETXID_2(cmd, arg1, arg2) \ + __SETXID_1 (cmd, arg1); cmd.id[1] = arg2 +#define __SETXID_3(cmd, arg1, arg2, arg3) \ + __SETXID_2 (cmd, arg1, arg2); cmd.id[2] = arg3 + +#ifdef SINGLE_THREAD +# define INLINE_SETXID_SYSCALL(name, nr, args...) \ + INLINE_SYSCALL (name, nr, args) +#elif defined SHARED +# define INLINE_SETXID_SYSCALL(name, nr, args...) \ + ({ \ + int __result; \ + if (__builtin_expect (__libc_pthread_functions_init, 0)) \ + { \ + struct xid_command __cmd; \ + __cmd.syscall_no = __NR_##name; \ + __SETXID_##nr (__cmd, args); \ + __result = PTHFCT_CALL (ptr__nptl_setxid, (&__cmd)); \ + } \ + else \ + __result = INLINE_SYSCALL (name, nr, args); \ + __result; \ + }) +#else +# define INLINE_SETXID_SYSCALL(name, nr, args...) \ + ({ \ + extern __typeof (__nptl_setxid) __nptl_setxid __attribute__((weak));\ + int __result; \ + if (__builtin_expect (__nptl_setxid != NULL, 0)) \ + { \ + struct xid_command __cmd; \ + __cmd.syscall_no = __NR_##name; \ + __SETXID_##nr (__cmd, args); \ + __result =__nptl_setxid (&__cmd); \ + } \ + else \ + __result = INLINE_SYSCALL (name, nr, args); \ + __result; \ + }) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/sigaction.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/sigaction.c new file mode 100644 index 00000000..e004a390 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/sigaction.c @@ -0,0 +1,49 @@ +/* Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef LIBC_SIGACTION + +#include + +/* We use the libc implementation but we tell it to not allow + SIGCANCEL or SIGTIMER to be handled. */ +#define LIBC_SIGACTION 1 +#include + +extern __typeof(sigaction) __sigaction; +int +__sigaction (int sig, const struct sigaction *act, struct sigaction *oact) +{ + if (__builtin_expect (sig == SIGCANCEL || sig == SIGSETXID, 0)) + { + __set_errno (EINVAL); + return -1; + } + + return __libc_sigaction (sig, act, oact); +} +libc_hidden_proto(sigaction) +weak_alias (__sigaction, sigaction) +libc_hidden_weak(sigaction) + +#else + +# include_next + +#endif /* LIBC_SIGACTION */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/sigfillset.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/sigfillset.c new file mode 100644 index 00000000..eed75e23 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/sigfillset.c @@ -0,0 +1,21 @@ +/* Copyright (C) 2003, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#include <../../../../libc/signal/sigfillset.c> diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/sigprocmask.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/sigprocmask.c new file mode 100644 index 00000000..35aa843b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/sigprocmask.c @@ -0,0 +1,22 @@ +/* Copyright (C) 1997,1998,1999,2000,2001,2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#undef _LARGEFILE64_SOURCE + +#include <../../../../libc/sysdeps/linux/common/sigprocmask.c> diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/timer_create.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/timer_create.c new file mode 100644 index 00000000..ae82c5af --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/timer_create.c @@ -0,0 +1,170 @@ +/* Copyright (C) 2000, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Kaz Kylheku . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include +#include + +#include "posix-timer.h" + + +/* Create new per-process timer using CLOCK. */ +int +timer_create ( + clockid_t clock_id, + struct sigevent *evp, + timer_t *timerid) +{ + int retval = -1; + struct timer_node *newtimer = NULL; + struct thread_node *thread = NULL; + + if (0 +#if defined _POSIX_CPUTIME && _POSIX_CPUTIME >= 0 + || clock_id == CLOCK_PROCESS_CPUTIME_ID +#endif +#if defined _POSIX_THREAD_CPUTIME && _POSIX_THREAD_CPUTIME >= 0 + || clock_id == CLOCK_THREAD_CPUTIME_ID +#endif + ) + { + /* We don't allow timers for CPU clocks. At least not in the + moment. */ + __set_errno (ENOTSUP); + return -1; + } + + if (clock_id != CLOCK_REALTIME) + { + __set_errno (EINVAL); + return -1; + } + + pthread_once (&__timer_init_once_control, __timer_init_once); + + if (__timer_init_failed) + { + __set_errno (ENOMEM); + return -1; + } + + pthread_mutex_lock (&__timer_mutex); + + newtimer = __timer_alloc (); + if (__builtin_expect (newtimer == NULL, 0)) + { + __set_errno (EAGAIN); + goto unlock_bail; + } + + if (evp != NULL) + newtimer->event = *evp; + else + { + newtimer->event.sigev_notify = SIGEV_SIGNAL; + newtimer->event.sigev_signo = SIGALRM; + newtimer->event.sigev_value.sival_ptr = timer_ptr2id (newtimer); + newtimer->event.sigev_notify_function = 0; + } + + newtimer->event.sigev_notify_attributes = &newtimer->attr; + newtimer->creator_pid = getpid (); + + switch (__builtin_expect (newtimer->event.sigev_notify, SIGEV_SIGNAL)) + { + case SIGEV_NONE: + case SIGEV_SIGNAL: + /* We have a global thread for delivering timed signals. + If it is not running, try to start it up. */ + thread = &__timer_signal_thread_rclk; + if (! thread->exists) + { + if (__builtin_expect (__timer_thread_start (thread), + 1) < 0) + { + __set_errno (EAGAIN); + goto unlock_bail; + } + } + break; + + case SIGEV_THREAD: + /* Copy over thread attributes or set up default ones. */ + if (evp->sigev_notify_attributes) + newtimer->attr = *(pthread_attr_t *) evp->sigev_notify_attributes; + else + pthread_attr_init (&newtimer->attr); + + /* Ensure thread attributes call for deatched thread. */ + pthread_attr_setdetachstate (&newtimer->attr, PTHREAD_CREATE_DETACHED); + + /* Try to find existing thread having the right attributes. */ + thread = __timer_thread_find_matching (&newtimer->attr, clock_id); + + /* If no existing thread has these attributes, try to allocate one. */ + if (thread == NULL) + thread = __timer_thread_alloc (&newtimer->attr, clock_id); + + /* Out of luck; no threads are available. */ + if (__builtin_expect (thread == NULL, 0)) + { + __set_errno (EAGAIN); + goto unlock_bail; + } + + /* If the thread is not running already, try to start it. */ + if (! thread->exists + && __builtin_expect (! __timer_thread_start (thread), 0)) + { + __set_errno (EAGAIN); + goto unlock_bail; + } + break; + + default: + __set_errno (EINVAL); + goto unlock_bail; + } + + newtimer->clock = clock_id; + newtimer->abstime = 0; + newtimer->armed = 0; + newtimer->thread = thread; + + *timerid = timer_ptr2id (newtimer); + retval = 0; + + if (__builtin_expect (retval, 0) == -1) + { + unlock_bail: + if (thread != NULL) + __timer_thread_dealloc (thread); + if (newtimer != NULL) + { + timer_delref (newtimer); + __timer_dealloc (newtimer); + } + } + + pthread_mutex_unlock (&__timer_mutex); + + return retval; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/timer_delete.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/timer_delete.c new file mode 100644 index 00000000..4c53112d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/timer_delete.c @@ -0,0 +1,70 @@ +/* Copyright (C) 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Kaz Kylheku . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include + +#include "posix-timer.h" + + +/* Delete timer TIMERID. */ +int +timer_delete ( + timer_t timerid) +{ + struct timer_node *timer; + int retval = -1; + + pthread_mutex_lock (&__timer_mutex); + + timer = timer_id2ptr (timerid); + if (! timer_valid (timer)) + /* Invalid timer ID or the timer is not in use. */ + __set_errno (EINVAL); + else + { + if (timer->armed && timer->thread != NULL) + { + struct thread_node *thread = timer->thread; + assert (thread != NULL); + + /* If thread is cancelled while waiting for handler to terminate, + the mutex is unlocked and timer_delete is aborted. */ + pthread_cleanup_push (__timer_mutex_cancel_handler, &__timer_mutex); + + /* If timer is currently being serviced, wait for it to finish. */ + while (thread->current_timer == timer) + pthread_cond_wait (&thread->cond, &__timer_mutex); + + pthread_cleanup_pop (0); + } + + /* Remove timer from whatever queue it may be on and deallocate it. */ + timer->inuse = TIMER_DELETED; + list_unlink_ip (&timer->links); + timer_delref (timer); + retval = 0; + } + + pthread_mutex_unlock (&__timer_mutex); + + return retval; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/timer_getoverr.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/timer_getoverr.c new file mode 100644 index 00000000..f3e22215 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/timer_getoverr.c @@ -0,0 +1,45 @@ +/* Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Kaz Kylheku . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include + +#include "posix-timer.h" + + +/* Get expiration overrun for timer TIMERID. */ +int +timer_getoverrun (timerid) + timer_t timerid; +{ + struct timer_node *timer; + int retval = -1; + + pthread_mutex_lock (&__timer_mutex); + + if (! timer_valid (timer = timer_id2ptr (timerid))) + __set_errno (EINVAL); + else + retval = timer->overrun_count; + + pthread_mutex_unlock (&__timer_mutex); + + return retval; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/timer_gettime.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/timer_gettime.c new file mode 100644 index 00000000..723a6163 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/timer_gettime.c @@ -0,0 +1,77 @@ +/* Copyright (C) 2000, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Kaz Kylheku . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include + +#include "posix-timer.h" + + +/* Get current value of timer TIMERID and store it in VLAUE. */ +int +timer_gettime (timerid, value) + timer_t timerid; + struct itimerspec *value; +{ + struct timer_node *timer; + struct timespec now, expiry; + int retval = -1, armed = 0, valid; + clock_t clock = 0; + + pthread_mutex_lock (&__timer_mutex); + + timer = timer_id2ptr (timerid); + valid = timer_valid (timer); + + if (valid) { + armed = timer->armed; + expiry = timer->expirytime; + clock = timer->clock; + value->it_interval = timer->value.it_interval; + } + + pthread_mutex_unlock (&__timer_mutex); + + if (valid) + { + if (armed) + { + clock_gettime (clock, &now); + if (timespec_compare (&now, &expiry) < 0) + timespec_sub (&value->it_value, &expiry, &now); + else + { + value->it_value.tv_sec = 0; + value->it_value.tv_nsec = 0; + } + } + else + { + value->it_value.tv_sec = 0; + value->it_value.tv_nsec = 0; + } + + retval = 0; + } + else + __set_errno (EINVAL); + + return retval; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/timer_routines.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/timer_routines.c new file mode 100644 index 00000000..8d5b1d13 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/timer_routines.c @@ -0,0 +1,578 @@ +/* Helper code for POSIX timer implementation on NPTL. + Copyright (C) 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Kaz Kylheku . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "posix-timer.h" +#include + + +/* Number of threads used. */ +#define THREAD_MAXNODES 16 + +/* Array containing the descriptors for the used threads. */ +static struct thread_node thread_array[THREAD_MAXNODES]; + +/* Static array with the structures for all the timers. */ +struct timer_node __timer_array[TIMER_MAX]; + +/* Global lock to protect operation on the lists. */ +pthread_mutex_t __timer_mutex = PTHREAD_MUTEX_INITIALIZER; + +/* Variable to protext initialization. */ +pthread_once_t __timer_init_once_control = PTHREAD_ONCE_INIT; + +/* Nonzero if initialization of timer implementation failed. */ +int __timer_init_failed; + +/* Node for the thread used to deliver signals. */ +struct thread_node __timer_signal_thread_rclk; + +/* Lists to keep free and used timers and threads. */ +struct list_links timer_free_list; +struct list_links thread_free_list; +struct list_links thread_active_list; + + +#ifdef __NR_rt_sigqueueinfo +extern int __syscall_rt_sigqueueinfo (int, int, siginfo_t *); +#endif + + +/* List handling functions. */ +static inline void +list_init (struct list_links *list) +{ + list->next = list->prev = list; +} + +static inline void +list_append (struct list_links *list, struct list_links *newp) +{ + newp->prev = list->prev; + newp->next = list; + list->prev->next = newp; + list->prev = newp; +} + +static inline void +list_insbefore (struct list_links *list, struct list_links *newp) +{ + list_append (list, newp); +} + +/* + * Like list_unlink_ip, except that calling it on a node that + * is already unlinked is disastrous rather than a noop. + */ + +static inline void +list_unlink (struct list_links *list) +{ + struct list_links *lnext = list->next, *lprev = list->prev; + + lnext->prev = lprev; + lprev->next = lnext; +} + +static inline struct list_links * +list_first (struct list_links *list) +{ + return list->next; +} + +static inline struct list_links * +list_null (struct list_links *list) +{ + return list; +} + +static inline struct list_links * +list_next (struct list_links *list) +{ + return list->next; +} + +static inline int +list_isempty (struct list_links *list) +{ + return list->next == list; +} + + +/* Functions build on top of the list functions. */ +static inline struct thread_node * +thread_links2ptr (struct list_links *list) +{ + return (struct thread_node *) ((char *) list + - offsetof (struct thread_node, links)); +} + +static inline struct timer_node * +timer_links2ptr (struct list_links *list) +{ + return (struct timer_node *) ((char *) list + - offsetof (struct timer_node, links)); +} + + +/* Initialize a newly allocated thread structure. */ +static void +thread_init (struct thread_node *thread, const pthread_attr_t *attr, clockid_t clock_id) +{ + if (attr != NULL) + thread->attr = *attr; + else + { + pthread_attr_init (&thread->attr); + pthread_attr_setdetachstate (&thread->attr, PTHREAD_CREATE_DETACHED); + } + + thread->exists = 0; + list_init (&thread->timer_queue); + pthread_cond_init (&thread->cond, 0); + thread->current_timer = 0; + thread->captured = pthread_self (); + thread->clock_id = clock_id; +} + + +/* Initialize the global lists, and acquire global resources. Error + reporting is done by storing a non-zero value to the global variable + timer_init_failed. */ +static void +init_module (void) +{ + int i; + + list_init (&timer_free_list); + list_init (&thread_free_list); + list_init (&thread_active_list); + + for (i = 0; i < TIMER_MAX; ++i) + { + list_append (&timer_free_list, &__timer_array[i].links); + __timer_array[i].inuse = TIMER_FREE; + } + + for (i = 0; i < THREAD_MAXNODES; ++i) + list_append (&thread_free_list, &thread_array[i].links); + + thread_init (&__timer_signal_thread_rclk, 0, CLOCK_REALTIME); +} + + +/* This is a handler executed in a child process after a fork() + occurs. It reinitializes the module, resetting all of the data + structures to their initial state. The mutex is initialized in + case it was locked in the parent process. */ +static void +reinit_after_fork (void) +{ + init_module (); + pthread_mutex_init (&__timer_mutex, 0); +} + + +/* Called once form pthread_once in timer_init. This initializes the + module and ensures that reinit_after_fork will be executed in any + child process. */ +void +__timer_init_once (void) +{ + init_module (); + pthread_atfork (0, 0, reinit_after_fork); +} + + +/* Deinitialize a thread that is about to be deallocated. */ +static void +thread_deinit (struct thread_node *thread) +{ + assert (list_isempty (&thread->timer_queue)); + pthread_cond_destroy (&thread->cond); +} + + +/* Allocate a thread structure from the global free list. Global + mutex lock must be held by caller. The thread is moved to + the active list. */ +struct thread_node * +__timer_thread_alloc (const pthread_attr_t *desired_attr, clockid_t clock_id) +{ + struct list_links *node = list_first (&thread_free_list); + + if (node != list_null (&thread_free_list)) + { + struct thread_node *thread = thread_links2ptr (node); + list_unlink (node); + thread_init (thread, desired_attr, clock_id); + list_append (&thread_active_list, node); + return thread; + } + + return 0; +} + + +/* Return a thread structure to the global free list. Global lock + must be held by caller. */ +void +__timer_thread_dealloc (struct thread_node *thread) +{ + thread_deinit (thread); + list_unlink (&thread->links); + list_append (&thread_free_list, &thread->links); +} + + +/* Each of our threads which terminates executes this cleanup + handler. We never terminate threads ourselves; if a thread gets here + it means that the evil application has killed it. If the thread has + timers, these require servicing and so we must hire a replacement + thread right away. We must also unblock another thread that may + have been waiting for this thread to finish servicing a timer (see + timer_delete()). */ + +static void +thread_cleanup (void *val) +{ + if (val != NULL) + { + struct thread_node *thread = val; + + /* How did the signal thread get killed? */ + assert (thread != &__timer_signal_thread_rclk); + + pthread_mutex_lock (&__timer_mutex); + + thread->exists = 0; + + /* We are no longer processing a timer event. */ + thread->current_timer = 0; + + if (list_isempty (&thread->timer_queue)) + __timer_thread_dealloc (thread); + else + (void) __timer_thread_start (thread); + + pthread_mutex_unlock (&__timer_mutex); + + /* Unblock potentially blocked timer_delete(). */ + pthread_cond_broadcast (&thread->cond); + } +} + + +/* Handle a timer which is supposed to go off now. */ +static void +thread_expire_timer (struct thread_node *self, struct timer_node *timer) +{ + self->current_timer = timer; /* Lets timer_delete know timer is running. */ + + pthread_mutex_unlock (&__timer_mutex); + + switch (__builtin_expect (timer->event.sigev_notify, SIGEV_SIGNAL)) + { + case SIGEV_NONE: + break; + + case SIGEV_SIGNAL: +#ifdef __NR_rt_sigqueueinfo + { + siginfo_t info; + + /* First, clear the siginfo_t structure, so that we don't pass our + stack content to other tasks. */ + memset (&info, 0, sizeof (siginfo_t)); + /* We must pass the information about the data in a siginfo_t + value. */ + info.si_signo = timer->event.sigev_signo; + info.si_code = SI_TIMER; + info.si_pid = timer->creator_pid; + info.si_uid = getuid (); + info.si_value = timer->event.sigev_value; + + INLINE_SYSCALL (rt_sigqueueinfo, 3, info.si_pid, info.si_signo, &info); + } +#else + if (pthread_kill (self->captured, timer->event.sigev_signo) != 0) + { + if (pthread_kill (self->id, timer->event.sigev_signo) != 0) + abort (); + } +#endif + break; + + case SIGEV_THREAD: + timer->event.sigev_notify_function (timer->event.sigev_value); + break; + + default: + assert (! "unknown event"); + break; + } + + pthread_mutex_lock (&__timer_mutex); + + self->current_timer = 0; + + pthread_cond_broadcast (&self->cond); +} + + +/* Thread function; executed by each timer thread. The job of this + function is to wait on the thread's timer queue and expire the + timers in chronological order as close to their scheduled time as + possible. */ +static void +__attribute__ ((noreturn)) +thread_func (void *arg) +{ + struct thread_node *self = arg; + + /* Register cleanup handler, in case rogue application terminates + this thread. (This cannot happen to __timer_signal_thread, which + doesn't invoke application callbacks). */ + + pthread_cleanup_push (thread_cleanup, self); + + pthread_mutex_lock (&__timer_mutex); + + while (1) + { + struct list_links *first; + struct timer_node *timer = NULL; + + /* While the timer queue is not empty, inspect the first node. */ + first = list_first (&self->timer_queue); + if (first != list_null (&self->timer_queue)) + { + struct timespec now; + + timer = timer_links2ptr (first); + + /* This assumes that the elements of the list of one thread + are all for the same clock. */ + clock_gettime (timer->clock, &now); + + while (1) + { + /* If the timer is due or overdue, remove it from the queue. + If it's a periodic timer, re-compute its new time and + requeue it. Either way, perform the timer expiry. */ + if (timespec_compare (&now, &timer->expirytime) < 0) + break; + + list_unlink_ip (first); + + if (__builtin_expect (timer->value.it_interval.tv_sec, 0) != 0 + || timer->value.it_interval.tv_nsec != 0) + { + timer->overrun_count = 0; + timespec_add (&timer->expirytime, &timer->expirytime, + &timer->value.it_interval); + while (timespec_compare (&timer->expirytime, &now) < 0) + { + timespec_add (&timer->expirytime, &timer->expirytime, + &timer->value.it_interval); + if (timer->overrun_count < DELAYTIMER_MAX) + ++timer->overrun_count; + } + __timer_thread_queue_timer (self, timer); + } + + thread_expire_timer (self, timer); + + first = list_first (&self->timer_queue); + if (first == list_null (&self->timer_queue)) + break; + + timer = timer_links2ptr (first); + } + } + + /* If the queue is not empty, wait until the expiry time of the + first node. Otherwise wait indefinitely. Insertions at the + head of the queue must wake up the thread by broadcasting + this condition variable. */ + if (timer != NULL) + pthread_cond_timedwait (&self->cond, &__timer_mutex, + &timer->expirytime); + else + pthread_cond_wait (&self->cond, &__timer_mutex); + } + /* This macro will never be executed since the while loop loops + forever - but we have to add it for proper nesting. */ + pthread_cleanup_pop (1); +} + + +/* Enqueue a timer in wakeup order in the thread's timer queue. + Returns 1 if the timer was inserted at the head of the queue, + causing the queue's next wakeup time to change. */ + +int +__timer_thread_queue_timer (struct thread_node *thread, + struct timer_node *insert) +{ + struct list_links *iter; + int athead = 1; + + for (iter = list_first (&thread->timer_queue); + iter != list_null (&thread->timer_queue); + iter = list_next (iter)) + { + struct timer_node *timer = timer_links2ptr (iter); + + if (timespec_compare (&insert->expirytime, &timer->expirytime) < 0) + break; + athead = 0; + } + + list_insbefore (iter, &insert->links); + return athead; +} + + +/* Start a thread and associate it with the given thread node. Global + lock must be held by caller. */ +int +__timer_thread_start (struct thread_node *thread) +{ + int retval = 1; + + assert (!thread->exists); + thread->exists = 1; + + if (pthread_create (&thread->id, &thread->attr, + (void *(*) (void *)) thread_func, thread) != 0) + { + thread->exists = 0; + retval = -1; + } + + return retval; +} + + +void +__timer_thread_wakeup (struct thread_node *thread) +{ + pthread_cond_broadcast (&thread->cond); +} + + +/* Compare two pthread_attr_t thread attributes for exact equality. + Returns 1 if they are equal, otherwise zero if they are not equal + or contain illegal values. This version is NPTL-specific for + performance reason. One could use the access functions to get the + values of all the fields of the attribute structure. */ +static int +thread_attr_compare (const pthread_attr_t *left, const pthread_attr_t *right) +{ + struct pthread_attr *ileft = (struct pthread_attr *) left; + struct pthread_attr *iright = (struct pthread_attr *) right; + + return (ileft->flags == iright->flags + && ileft->schedpolicy == iright->schedpolicy + && (ileft->schedparam.sched_priority + == iright->schedparam.sched_priority) + && ileft->guardsize == iright->guardsize + && ileft->stackaddr == iright->stackaddr + && ileft->stacksize == iright->stacksize + && ((ileft->cpuset == NULL && iright->cpuset == NULL) + || (ileft->cpuset != NULL && iright->cpuset != NULL + && ileft->cpusetsize == iright->cpusetsize + && memcmp (ileft->cpuset, iright->cpuset, + ileft->cpusetsize) == 0))); +} + + +/* Search the list of active threads and find one which has matching + attributes. Global mutex lock must be held by caller. */ +struct thread_node * +__timer_thread_find_matching (const pthread_attr_t *desired_attr, + clockid_t desired_clock_id) +{ + struct list_links *iter = list_first (&thread_active_list); + + while (iter != list_null (&thread_active_list)) + { + struct thread_node *candidate = thread_links2ptr (iter); + + if (thread_attr_compare (desired_attr, &candidate->attr) + && desired_clock_id == candidate->clock_id) + return candidate; + + iter = list_next (iter); + } + + return NULL; +} + + +/* Grab a free timer structure from the global free list. The global + lock must be held by the caller. */ +struct timer_node * +__timer_alloc (void) +{ + struct list_links *node = list_first (&timer_free_list); + + if (node != list_null (&timer_free_list)) + { + struct timer_node *timer = timer_links2ptr (node); + list_unlink_ip (node); + timer->inuse = TIMER_INUSE; + timer->refcount = 1; + return timer; + } + + return NULL; +} + + +/* Return a timer structure to the global free list. The global lock + must be held by the caller. */ +void +__timer_dealloc (struct timer_node *timer) +{ + assert (timer->refcount == 0); + timer->thread = NULL; /* Break association between timer and thread. */ + timer->inuse = TIMER_FREE; + list_append (&timer_free_list, &timer->links); +} + + +/* Thread cancellation handler which unlocks a mutex. */ +void +__timer_mutex_cancel_handler (void *arg) +{ + pthread_mutex_unlock (arg); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/timer_settime.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/timer_settime.c new file mode 100644 index 00000000..592b5271 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/timer_settime.c @@ -0,0 +1,137 @@ +/* Copyright (C) 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Kaz Kylheku . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include + +#include "posix-timer.h" + + +/* Set timer TIMERID to VALUE, returning old value in OVLAUE. */ +int +timer_settime (timerid, flags, value, ovalue) + timer_t timerid; + int flags; + const struct itimerspec *value; + struct itimerspec *ovalue; +{ + struct timer_node *timer; + struct thread_node *thread = NULL; + struct timespec now; + int have_now = 0, need_wakeup = 0; + int retval = -1; + + timer = timer_id2ptr (timerid); + if (timer == NULL) + { + __set_errno (EINVAL); + goto bail; + } + + if (value->it_interval.tv_nsec < 0 + || value->it_interval.tv_nsec >= 1000000000 + || value->it_value.tv_nsec < 0 + || value->it_value.tv_nsec >= 1000000000) + { + __set_errno (EINVAL); + goto bail; + } + + /* Will need to know current time since this is a relative timer; + might as well make the system call outside of the lock now! */ + + if ((flags & TIMER_ABSTIME) == 0) + { + clock_gettime (timer->clock, &now); + have_now = 1; + } + + pthread_mutex_lock (&__timer_mutex); + timer_addref (timer); + + /* One final check of timer validity; this one is possible only + until we have the mutex, because it accesses the inuse flag. */ + + if (! timer_valid(timer)) + { + __set_errno (EINVAL); + goto unlock_bail; + } + + if (ovalue != NULL) + { + ovalue->it_interval = timer->value.it_interval; + + if (timer->armed) + { + if (! have_now) + { + pthread_mutex_unlock (&__timer_mutex); + clock_gettime (timer->clock, &now); + have_now = 1; + pthread_mutex_lock (&__timer_mutex); + timer_addref (timer); + } + + timespec_sub (&ovalue->it_value, &timer->expirytime, &now); + } + else + { + ovalue->it_value.tv_sec = 0; + ovalue->it_value.tv_nsec = 0; + } + } + + timer->value = *value; + + list_unlink_ip (&timer->links); + timer->armed = 0; + + thread = timer->thread; + + /* A value of { 0, 0 } causes the timer to be stopped. */ + if (value->it_value.tv_sec != 0 + || __builtin_expect (value->it_value.tv_nsec != 0, 1)) + { + if ((flags & TIMER_ABSTIME) != 0) + /* The user specified the expiration time. */ + timer->expirytime = value->it_value; + else + timespec_add (&timer->expirytime, &now, &value->it_value); + + /* Only need to wake up the thread if timer is inserted + at the head of the queue. */ + if (thread != NULL) + need_wakeup = __timer_thread_queue_timer (thread, timer); + timer->armed = 1; + } + + retval = 0; + +unlock_bail: + timer_delref (timer); + pthread_mutex_unlock (&__timer_mutex); + +bail: + if (thread != NULL && need_wakeup) + __timer_thread_wakeup (thread); + + return retval; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/tpp.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/tpp.c new file mode 100644 index 00000000..9adab791 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/tpp.c @@ -0,0 +1,172 @@ +/* Thread Priority Protect helpers. + Copyright (C) 2006, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2006. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include +#include "uClibc-glue.h" + +int __sched_fifo_min_prio = -1; +int __sched_fifo_max_prio = -1; + +void +__init_sched_fifo_prio (void) +{ + __sched_fifo_max_prio = sched_get_priority_max (SCHED_FIFO); + atomic_write_barrier (); + __sched_fifo_min_prio = sched_get_priority_min (SCHED_FIFO); +} + +int +__pthread_tpp_change_priority (int previous_prio, int new_prio) +{ + struct pthread *self = THREAD_SELF; + struct priority_protection_data *tpp = THREAD_GETMEM (self, tpp); + + if (tpp == NULL) + { + if (__sched_fifo_min_prio == -1) + __init_sched_fifo_prio (); + + size_t size = sizeof *tpp; + size += (__sched_fifo_max_prio - __sched_fifo_min_prio + 1) + * sizeof (tpp->priomap[0]); + tpp = calloc (size, 1); + if (tpp == NULL) + return ENOMEM; + tpp->priomax = __sched_fifo_min_prio - 1; + THREAD_SETMEM (self, tpp, tpp); + } + + assert (new_prio == -1 + || (new_prio >= __sched_fifo_min_prio + && new_prio <= __sched_fifo_max_prio)); + assert (previous_prio == -1 + || (previous_prio >= __sched_fifo_min_prio + && previous_prio <= __sched_fifo_max_prio)); + + int priomax = tpp->priomax; + int newpriomax = priomax; + if (new_prio != -1) + { + if (tpp->priomap[new_prio - __sched_fifo_min_prio] + 1 == 0) + return EAGAIN; + ++tpp->priomap[new_prio - __sched_fifo_min_prio]; + if (new_prio > priomax) + newpriomax = new_prio; + } + + if (previous_prio != -1) + { + if (--tpp->priomap[previous_prio - __sched_fifo_min_prio] == 0 + && priomax == previous_prio + && previous_prio > new_prio) + { + int i; + for (i = previous_prio - 1; i >= __sched_fifo_min_prio; --i) + if (tpp->priomap[i - __sched_fifo_min_prio]) + break; + newpriomax = i; + } + } + + if (priomax == newpriomax) + return 0; + + lll_lock (self->lock, LLL_PRIVATE); + + tpp->priomax = newpriomax; + + int result = 0; + + if ((self->flags & ATTR_FLAG_SCHED_SET) == 0) + { + if (__sched_getparam (self->tid, &self->schedparam) != 0) + result = errno; + else + self->flags |= ATTR_FLAG_SCHED_SET; + } + + if ((self->flags & ATTR_FLAG_POLICY_SET) == 0) + { + self->schedpolicy = __sched_getscheduler (self->tid); + if (self->schedpolicy == -1) + result = errno; + else + self->flags |= ATTR_FLAG_POLICY_SET; + } + + if (result == 0) + { + struct sched_param sp = self->schedparam; + if (sp.sched_priority < newpriomax || sp.sched_priority < priomax) + { + if (sp.sched_priority < newpriomax) + sp.sched_priority = newpriomax; + + if (__sched_setscheduler (self->tid, self->schedpolicy, &sp) < 0) + result = errno; + } + } + + lll_unlock (self->lock, LLL_PRIVATE); + + return result; +} + +int +__pthread_current_priority (void) +{ + struct pthread *self = THREAD_SELF; + if ((self->flags & (ATTR_FLAG_POLICY_SET | ATTR_FLAG_SCHED_SET)) + == (ATTR_FLAG_POLICY_SET | ATTR_FLAG_SCHED_SET)) + return self->schedparam.sched_priority; + + int result = 0; + + lll_lock (self->lock, LLL_PRIVATE); + + if ((self->flags & ATTR_FLAG_SCHED_SET) == 0) + { + if (__sched_getparam (self->tid, &self->schedparam) != 0) + result = -1; + else + self->flags |= ATTR_FLAG_SCHED_SET; + } + + if ((self->flags & ATTR_FLAG_POLICY_SET) == 0) + { + self->schedpolicy = __sched_getscheduler (self->tid); + if (self->schedpolicy == -1) + result = -1; + else + self->flags |= ATTR_FLAG_POLICY_SET; + } + + if (result != -1) + result = self->schedparam.sched_priority; + + lll_unlock (self->lock, LLL_PRIVATE); + + return result; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/uClibc-glue.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/uClibc-glue.h new file mode 100644 index 00000000..b957dedc --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/uClibc-glue.h @@ -0,0 +1,47 @@ +#ifndef _UCLIBC_GLUE_H +#define _UCLIBC_GLUE_H 1 + +#include +#include +#include + +#ifdef IS_IN_libpthread +#include + +#ifndef __GLIBC_HAVE_LONG_LONG +# define __GLIBC_HAVE_LONG_LONG +#endif + +#define __getpagesize getpagesize +#define __sched_get_priority_max sched_get_priority_max +#define __sched_get_priority_min sched_get_priority_min +#define __sched_getscheduler sched_getscheduler +#define __sched_setscheduler sched_setscheduler +#define __sched_getparam sched_getparam +#define __getpid getpid +#define __gettimeofday gettimeofday +#define __poll poll +#define __sysctl sysctl +#define __open open +#define __read read +#define __close close +#define __on_exit on_exit +#define __libc_current_sigrtmin_private __libc_current_sigrtmin +#define __clone clone + +extern void *__libc_stack_end; +extern int __cxa_atexit (void (*func) (void *), void *arg, void *d); + +#endif /* IS_IN_libpthread */ + +#ifdef __UCLIBC_HAS_XLOCALE__ +# define __uselocale(x) uselocale(x) +#else +# define __uselocale(x) ((void)0) +#endif + +/* Use a funky version in a probably vein attempt at preventing gdb + * from dlopen()'ing glibc's libthread_db library... */ +#define VERSION __stringify(__UCLIBC_MAJOR__) "." __stringify(__UCLIBC_MINOR__) "." __stringify(__UCLIBC_SUBLEVEL__) + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/unwind-forcedunwind.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/unwind-forcedunwind.c new file mode 100644 index 00000000..40b8d98c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/unwind-forcedunwind.c @@ -0,0 +1,151 @@ +/* Copyright (C) 2003, 2005, 2006, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include +#include +#include + +#define __libc_dlopen(x) dlopen(x, (RTLD_LOCAL | RTLD_LAZY)) +#define __libc_dlsym dlsym +#define __libc_dlclose dlclose + +static void *libgcc_s_handle; +static void (*libgcc_s_resume) (struct _Unwind_Exception *exc); +static _Unwind_Reason_Code (*libgcc_s_personality) + (int, _Unwind_Action, _Unwind_Exception_Class, struct _Unwind_Exception *, + struct _Unwind_Context *); +static _Unwind_Reason_Code (*libgcc_s_forcedunwind) + (struct _Unwind_Exception *, _Unwind_Stop_Fn, void *); +static _Unwind_Word (*libgcc_s_getcfa) (struct _Unwind_Context *); + +void +__attribute_noinline__ +pthread_cancel_init (void) +{ + void *resume; + void *personality; + void *forcedunwind; + void *getcfa; + void *handle; + + if (__builtin_expect (libgcc_s_handle != NULL, 1)) + { + /* Force gcc to reload all values. */ + __asm__ __volatile__ ("" ::: "memory"); + return; + } + + handle = __libc_dlopen (LIBGCC_S_SO); + + if (handle == NULL + || (resume = __libc_dlsym (handle, "_Unwind_Resume")) == NULL + || (personality = __libc_dlsym (handle, "__gcc_personality_v0")) == NULL + || (forcedunwind = __libc_dlsym (handle, "_Unwind_ForcedUnwind")) + == NULL + || (getcfa = __libc_dlsym (handle, "_Unwind_GetCFA")) == NULL +#ifdef ARCH_CANCEL_INIT + || ARCH_CANCEL_INIT (handle) +#endif + ) + { + printf (LIBGCC_S_SO " must be installed for pthread_cancel to work\n"); + abort(); + } + + PTR_MANGLE (resume); + libgcc_s_resume = resume; + PTR_MANGLE (personality); + libgcc_s_personality = personality; + PTR_MANGLE (forcedunwind); + libgcc_s_forcedunwind = forcedunwind; + PTR_MANGLE (getcfa); + libgcc_s_getcfa = getcfa; + /* Make sure libgcc_s_handle is written last. Otherwise, + pthread_cancel_init might return early even when the pointer the + caller is interested in is not initialized yet. */ + atomic_write_barrier (); + libgcc_s_handle = handle; +} + +void +__libc_freeres_fn_section +__unwind_freeres (void) +{ + void *handle = libgcc_s_handle; + if (handle != NULL) + { + libgcc_s_handle = NULL; + __libc_dlclose (handle); + } +} + +void +_Unwind_Resume (struct _Unwind_Exception *exc) +{ + if (__builtin_expect (libgcc_s_handle == NULL, 0)) + pthread_cancel_init (); + + void (*resume) (struct _Unwind_Exception *exc) = libgcc_s_resume; + PTR_DEMANGLE (resume); + resume (exc); +} + +_Unwind_Reason_Code +__gcc_personality_v0 (int version, _Unwind_Action actions, + _Unwind_Exception_Class exception_class, + struct _Unwind_Exception *ue_header, + struct _Unwind_Context *context) +{ + if (__builtin_expect (libgcc_s_handle == NULL, 0)) + pthread_cancel_init (); + + _Unwind_Reason_Code (*personality) + (int, _Unwind_Action, _Unwind_Exception_Class, struct _Unwind_Exception *, + struct _Unwind_Context *) = libgcc_s_personality; + PTR_DEMANGLE (personality); + return personality (version, actions, exception_class, ue_header, context); +} + +_Unwind_Reason_Code +_Unwind_ForcedUnwind (struct _Unwind_Exception *exc, _Unwind_Stop_Fn stop, + void *stop_argument) +{ + if (__builtin_expect (libgcc_s_handle == NULL, 0)) + pthread_cancel_init (); + + _Unwind_Reason_Code (*forcedunwind) + (struct _Unwind_Exception *, _Unwind_Stop_Fn, void *) + = libgcc_s_forcedunwind; + PTR_DEMANGLE (forcedunwind); + return forcedunwind (exc, stop, stop_argument); +} + +_Unwind_Word +_Unwind_GetCFA (struct _Unwind_Context *context) +{ + if (__builtin_expect (libgcc_s_handle == NULL, 0)) + pthread_cancel_init (); + + _Unwind_Word (*getcfa) (struct _Unwind_Context *) = libgcc_s_getcfa; + PTR_DEMANGLE (getcfa); + return getcfa (context); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/unwind-resume.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/unwind-resume.c new file mode 100644 index 00000000..94da075d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/pthread/unwind-resume.c @@ -0,0 +1,76 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include +#include + +#define __libc_dlopen(x) dlopen(x, (RTLD_LOCAL | RTLD_LAZY)) +#define __libc_dlsym dlsym +#define __libc_dlclose dlclose + +static void (*libgcc_s_resume) (struct _Unwind_Exception *exc); +static _Unwind_Reason_Code (*libgcc_s_personality) + (int, _Unwind_Action, _Unwind_Exception_Class, struct _Unwind_Exception *, + struct _Unwind_Context *); + +extern +void abort(void); + +static void +init (void) +{ + void *resume, *personality; + void *handle; + resume = personality = NULL; + handle = dlopen (LIBGCC_S_SO, (RTLD_LOCAL | RTLD_LAZY)); + + if (handle == NULL + || (resume = dlsym (handle, "_Unwind_Resume")) == NULL + || (personality = dlsym (handle, "__gcc_personality_v0")) == NULL) + { + printf (LIBGCC_S_SO " must be installed for pthread_cancel to work\n"); + abort(); + } + + libgcc_s_resume = resume; + libgcc_s_personality = personality; +} + +void +_Unwind_Resume (struct _Unwind_Exception *exc) +{ + if (__builtin_expect (libgcc_s_resume == NULL, 0)) + init (); + libgcc_s_resume (exc); +} + +_Unwind_Reason_Code +__gcc_personality_v0 (int version, _Unwind_Action actions, + _Unwind_Exception_Class exception_class, + struct _Unwind_Exception *ue_header, + struct _Unwind_Context *context) +{ + if (__builtin_expect (libgcc_s_personality == NULL, 0)) + init (); + return libgcc_s_personality (version, actions, exception_class, + ue_header, context); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sh/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sh/Makefile new file mode 100644 index 00000000..81bddf68 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sh/Makefile @@ -0,0 +1,3 @@ +ifeq ($(subdir),csu) +gen-as-const-headers += tcb-offsets.sym +endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sh/Makefile.arch b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sh/Makefile.arch new file mode 100644 index 00000000..411622ad --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sh/Makefile.arch @@ -0,0 +1,13 @@ +# Makefile for uClibc NPTL +# +# Copyright (C) 2005 Steven J. Hill +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +ASFLAGS-pthread_spin_unlock.S = -DNOT_IN_libc -DIS_IN_libpthread +ASFLAGS-pthread_spin_trylock.S = -DNOT_IN_libc -DIS_IN_libpthread + +CFLAGS-pthread_spin_lock.c += -D_GNU_SOURCE + +libc_arch_a_CSRC := libc-tls.c diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sh/dl-tls.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sh/dl-tls.h new file mode 100644 index 00000000..98e2f190 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sh/dl-tls.h @@ -0,0 +1,29 @@ +/* Thread-local storage handling in the ELF dynamic linker. SH version. + Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + + +/* Type used for the representation of TLS information in the GOT. */ +typedef struct +{ + unsigned long int ti_module; + unsigned long int ti_offset; +} tls_index; + + +extern void *__tls_get_addr (tls_index *ti); diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sh/jmpbuf-unwind.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sh/jmpbuf-unwind.h new file mode 100644 index 00000000..41c3c398 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sh/jmpbuf-unwind.h @@ -0,0 +1,33 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +#define _JMPBUF_CFA_UNWINDS_ADJ(_jmpbuf, _context, _adj) \ + _JMPBUF_UNWINDS_ADJ (_jmpbuf, (void *) _Unwind_GetCFA (_context), _adj) + +#define _JMPBUF_UNWINDS_ADJ(jmpbuf, address, adj) \ + ((uintptr_t) (address) - (adj) < (uintptr_t) (jmpbuf)[0].__regs[7] - (adj)) + +extern __typeof(longjmp) __libc_longjmp attribute_noreturn; + +/* We use the normal lobngjmp for unwinding. */ +#define __libc_unwind_longjmp(buf, val) __libc_longjmp (buf, val) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sh/libc-tls.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sh/libc-tls.c new file mode 100644 index 00000000..7b338950 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sh/libc-tls.c @@ -0,0 +1,31 @@ +/* + * Thread-local storage handling in statically linked binaries. SH version. + * Copyright (C) 2009 Free Software Foundation, Inc. + * + * Based on GNU C Library (file: libc/sysdeps/sh/libc-tls.c) + * + * Copyright (C) 2010 STMicroelectronics Ltd. + * Author: Filippo Arcidiacono + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + */ + +#include +#include + +#if defined (USE_TLS) && (USE_TLS) + +/* On SH, linker optimizations are not required, so __tls_get_addr + can be called even in statically linked binaries. In this case module + must be always 1 and PT_TLS segment exist in the binary, otherwise it + would not link. */ + +void * +__tls_get_addr (tls_index *ti) +{ + dtv_t *dtv = THREAD_DTV (); + return (char *) dtv[1].pointer.val + ti->ti_offset; +} + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sh/pthread_spin_init.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sh/pthread_spin_init.c new file mode 100644 index 00000000..0a47981a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sh/pthread_spin_init.c @@ -0,0 +1,20 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Not needed. pthread_spin_init is an alias for pthread_spin_unlock. */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sh/pthread_spin_lock.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sh/pthread_spin_lock.c new file mode 100644 index 00000000..74fad338 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sh/pthread_spin_lock.c @@ -0,0 +1,34 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "pthreadP.h" + +int +pthread_spin_lock (pthread_spinlock_t *lock) +{ + unsigned int val; + + do + __asm__ __volatile__ ("tas.b @%1; movt %0" + : "=&r" (val) + : "r" (lock) + : "memory"); + while (val == 0); + + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sh/pthread_spin_trylock.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sh/pthread_spin_trylock.S new file mode 100644 index 00000000..18112ba2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sh/pthread_spin_trylock.S @@ -0,0 +1,32 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + + .globl pthread_spin_trylock + .type pthread_spin_trylock,@function + .align 5 +pthread_spin_trylock: + tas.b @r4 + bf/s 1f + mov #EBUSY, r0 + mov #0, r0 +1: + rts + nop + .size pthread_spin_trylock,.-pthread_spin_trylock diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sh/pthread_spin_unlock.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sh/pthread_spin_unlock.S new file mode 100644 index 00000000..c77acaff --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sh/pthread_spin_unlock.S @@ -0,0 +1,30 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + + .globl pthread_spin_unlock + .type pthread_spin_unlock,@function + .align 5 +pthread_spin_unlock: + mov #0,r0 + rts + mov.l r0,@r4 + .size pthread_spin_unlock,.-pthread_spin_unlock + + /* The implementation of pthread_spin_init is identical. */ + .globl pthread_spin_init +pthread_spin_init = pthread_spin_unlock diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sh/pthreaddef.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sh/pthreaddef.h new file mode 100644 index 00000000..dc6a4f90 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sh/pthreaddef.h @@ -0,0 +1,49 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +/* Default stack size. */ +#define ARCH_STACK_DEFAULT_SIZE (2 * 1024 * 1024) + +/* Required stack pointer alignment at beginning. */ +#define STACK_ALIGN 8 + +/* Minimal stack size after allocating thread descriptor and guard size. */ +#define MINIMAL_REST_STACK 2048 + +/* Alignment requirement for TCB. */ +#define TCB_ALIGNMENT 8 + + +/* Location of current stack frame. */ +#define CURRENT_STACK_FRAME __builtin_frame_address (0) + + +/* XXX Until we have a better place keep the definitions here. */ + +/* While there is no such syscall. */ +#define __exit_thread_inline(val) \ + while (1) { \ + if (__builtin_constant_p (val) && (val) == 0) \ + __asm__ __volatile__ ("mov #0,r4; mov %0,r3; trapa #0x11\n\t" SYSCALL_INST_PAD \ + :: "i" (__NR_exit)); \ + else \ + __asm__ __volatile__ ("mov %1,r4; mov %0,r3; trapa #0x11\n\t" SYSCALL_INST_PAD \ + :: "i" (__NR_exit), "r" (val)); \ + } diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sh/tcb-offsets.sym b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sh/tcb-offsets.sym new file mode 100644 index 00000000..753b72b2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sh/tcb-offsets.sym @@ -0,0 +1,15 @@ +#include +#include + +RESULT offsetof (struct pthread, result) +TID offsetof (struct pthread, tid) +PID offsetof (struct pthread, pid) +CANCELHANDLING offsetof (struct pthread, cancelhandling) +CLEANUP_JMP_BUF offsetof (struct pthread, cleanup_jmp_buf) +MULTIPLE_THREADS_OFFSET offsetof (struct pthread, header.multiple_threads) +TLS_PRE_TCB_SIZE sizeof (struct pthread) +MUTEX_FUTEX offsetof (pthread_mutex_t, __data.__lock) +POINTER_GUARD offsetof (tcbhead_t, pointer_guard) +#ifndef __ASSUME_PRIVATE_FUTEX +PRIVATE_FUTEX offsetof (struct pthread, header.private_futex) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sh/tls.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sh/tls.h new file mode 100644 index 00000000..bbb11187 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sh/tls.h @@ -0,0 +1,182 @@ +/* Definition for thread-local data handling. NPTL/SH version. + Copyright (C) 2003, 2005, 2006, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _TLS_H +#define _TLS_H + +#ifndef __ASSEMBLER__ +# include +# include +# include +# include +# include +# include +# include + +/* Type for the dtv. */ +typedef union dtv +{ + size_t counter; + struct + { + void *val; + bool is_static; + } pointer; +} dtv_t; + +typedef struct +{ + dtv_t *dtv; + uintptr_t pointer_guard; +} tcbhead_t; + +# define TLS_MULTIPLE_THREADS_IN_TCB 1 + +#else /* __ASSEMBLER__ */ +# include +#endif /* __ASSEMBLER__ */ + + +/* We require TLS support in the tools. */ +#define HAVE_TLS_SUPPORT +#define HAVE___THREAD 1 +#define HAVE_TLS_MODEL_ATTRIBUTE 1 +/* Signal that TLS support is available. */ +# define USE_TLS 1 + +#ifndef __ASSEMBLER__ + +/* Get system call information. */ +# include + +/* This is the size of the initial TCB. */ +# define TLS_INIT_TCB_SIZE sizeof (tcbhead_t) + +/* Alignment requirements for the initial TCB. */ +# define TLS_INIT_TCB_ALIGN __alignof__ (tcbhead_t) + +/* This is the size of the TCB. */ +# define TLS_TCB_SIZE sizeof (tcbhead_t) + +/* This is the size we need before TCB. */ +# define TLS_PRE_TCB_SIZE sizeof (struct pthread) + +/* Alignment requirements for the TCB. */ +# define TLS_TCB_ALIGN __alignof__ (struct pthread) + +/* The TLS blocks start right after the TCB. */ +# define TLS_DTV_AT_TP 1 + +/* Get the thread descriptor definition. */ +# include + +/* Install the dtv pointer. The pointer passed is to the element with + index -1 which contain the length. */ +# define INSTALL_DTV(tcbp, dtvp) \ + ((tcbhead_t *) (tcbp))->dtv = (dtvp) + 1 + +/* Install new dtv for current thread. */ +# define INSTALL_NEW_DTV(dtv) \ + ({ tcbhead_t *__tcbp; \ + __asm__ __volatile__ ("stc gbr,%0" : "=r" (__tcbp)); \ + __tcbp->dtv = (dtv);}) + +/* Return dtv of given thread descriptor. */ +# define GET_DTV(tcbp) \ + (((tcbhead_t *) (tcbp))->dtv) + +/* Code to initially initialize the thread pointer. This might need + special attention since 'errno' is not yet available and if the + operation can cause a failure 'errno' must not be touched. */ +# define TLS_INIT_TP(tcbp, secondcall) \ + ({ __asm__ __volatile__ ("ldc %0,gbr" : : "r" (tcbp)); 0; }) + +/* Return the address of the dtv for the current thread. */ +# define THREAD_DTV() \ + ({ tcbhead_t *__tcbp; \ + __asm__ __volatile__ ("stc gbr,%0" : "=r" (__tcbp)); \ + __tcbp->dtv;}) + +/* Return the thread descriptor for the current thread. + The contained asm must *not* be marked volatile since otherwise + assignments like + struct pthread *self = thread_self(); + do not get optimized away. */ +# define THREAD_SELF \ + ({ struct pthread *__self; \ + __asm__ ("stc gbr,%0" : "=r" (__self)); \ + __self - 1;}) + +/* Magic for libthread_db to know how to do THREAD_SELF. */ +# define DB_THREAD_SELF \ + REGISTER (32, 32, REG_GBR * 4, -sizeof (struct pthread)) + +/* Read member of the thread descriptor directly. */ +# define THREAD_GETMEM(descr, member) (descr->member) + +/* Same as THREAD_GETMEM, but the member offset can be non-constant. */ +# define THREAD_GETMEM_NC(descr, member, idx) (descr->member[idx]) + +/* Set member of the thread descriptor directly. */ +# define THREAD_SETMEM(descr, member, value) \ + descr->member = (value) + +/* Same as THREAD_SETMEM, but the member offset can be non-constant. */ +# define THREAD_SETMEM_NC(descr, member, idx, value) \ + descr->member[idx] = (value) + +#define THREAD_GET_POINTER_GUARD() \ + ({ tcbhead_t *__tcbp; \ + __asm__ __volatile__ ("stc gbr,%0" : "=r" (__tcbp)); \ + __tcbp->pointer_guard;}) + #define THREAD_SET_POINTER_GUARD(value) \ + ({ tcbhead_t *__tcbp; \ + __asm__ __volatile__ ("stc gbr,%0" : "=r" (__tcbp)); \ + __tcbp->pointer_guard = (value);}) +#define THREAD_COPY_POINTER_GUARD(descr) \ + ({ tcbhead_t *__tcbp; \ + __asm__ __volatile__ ("stc gbr,%0" : "=r" (__tcbp)); \ + ((tcbhead_t *) (descr + 1))->pointer_guard = __tcbp->pointer_guard;}) + +/* Get and set the global scope generation counter in struct pthread. */ +#define THREAD_GSCOPE_FLAG_UNUSED 0 +#define THREAD_GSCOPE_FLAG_USED 1 +#define THREAD_GSCOPE_FLAG_WAIT 2 +#define THREAD_GSCOPE_RESET_FLAG() \ + do \ + { int __res \ + = atomic_exchange_rel (&THREAD_SELF->header.gscope_flag, \ + THREAD_GSCOPE_FLAG_UNUSED); \ + if (__res == THREAD_GSCOPE_FLAG_WAIT) \ + lll_futex_wake (&THREAD_SELF->header.gscope_flag, 1, LLL_PRIVATE); \ + } \ + while (0) +#define THREAD_GSCOPE_SET_FLAG() \ + do \ + { \ + THREAD_SELF->header.gscope_flag = THREAD_GSCOPE_FLAG_USED; \ + atomic_write_barrier (); \ + } \ + while (0) +#define THREAD_GSCOPE_WAIT() \ + GL(dl_wait_lookup_done) () + +#endif /* __ASSEMBLER__ */ + +#endif /* tls.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sparc/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sparc/Makefile new file mode 100644 index 00000000..81bddf68 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sparc/Makefile @@ -0,0 +1,3 @@ +ifeq ($(subdir),csu) +gen-as-const-headers += tcb-offsets.sym +endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sparc/Makefile.arch b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sparc/Makefile.arch new file mode 100644 index 00000000..52ac6dbe --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sparc/Makefile.arch @@ -0,0 +1,11 @@ +# Makefile for uClibc NPTL +# +# Copyright (C) 2005 Steven J. Hill +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# +subdirs += libpthread/nptl/sysdeps/$(TARGET_ARCH)/$(TARGET_SUBARCH)/sparv9 + +CFLAGS-pthread_spin_lock.c += -D_GNU_SOURCE + + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sparc/dl-tls.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sparc/dl-tls.h new file mode 100644 index 00000000..6edf8d52 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sparc/dl-tls.h @@ -0,0 +1,29 @@ +/* Thread-local storage handling in the ELF dynamic linker. SPARC version. + Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + + +/* Type used for the representation of TLS information in the GOT. */ +typedef struct +{ + unsigned long int ti_module; + unsigned long int ti_offset; +} tls_index; + + +extern void *__tls_get_addr (tls_index *ti); diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sparc/jmpbuf-unwind.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sparc/jmpbuf-unwind.h new file mode 100644 index 00000000..6cbb37ba --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sparc/jmpbuf-unwind.h @@ -0,0 +1,5 @@ +#if defined(__arch64__) +#include "sparc64/jmpbuf-unwind.h" +#else +#include "sparc32/jmpbuf-unwind.h" +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sparc/pthreaddef.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sparc/pthreaddef.h new file mode 100644 index 00000000..d4695c47 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sparc/pthreaddef.h @@ -0,0 +1,5 @@ +#if defined(__arch64__) +#include "sparc64/pthreaddef.h" +#else +#include "sparc32/pthreaddef.h" +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sparc/sparc32/jmpbuf-unwind.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sparc/sparc32/jmpbuf-unwind.h new file mode 100644 index 00000000..71a35820 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sparc/sparc32/jmpbuf-unwind.h @@ -0,0 +1,32 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +#define _JMPBUF_CFA_UNWINDS_ADJ(_jmpbuf, _context, _adj) \ + _JMPBUF_UNWINDS_ADJ (_jmpbuf, (void *) _Unwind_GetCFA (_context), _adj) + +#define _JMPBUF_UNWINDS_ADJ(_jmpbuf, _address, _adj) \ + ((uintptr_t) (_address) - (_adj) < (uintptr_t) (_jmpbuf)[JB_SP] - (_adj)) + +/* We use the normal longjmp for unwinding. */ +extern __typeof(longjmp) __libc_longjmp attribute_noreturn; +#define __libc_unwind_longjmp(buf, val) __libc_longjmp (buf, val) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sparc/sparc32/pthread_spin_lock.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sparc/sparc32/pthread_spin_lock.c new file mode 100644 index 00000000..c263bb7c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sparc/sparc32/pthread_spin_lock.c @@ -0,0 +1,40 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "pthreadP.h" + +int +pthread_spin_lock (pthread_spinlock_t *lock) +{ + __asm__ __volatile + ("1: ldstub [%0], %%g2\n" + " orcc %%g2, 0x0, %%g0\n" + " bne,a 2f\n" + " ldub [%0], %%g2\n" + ".subsection 2\n" + "2: orcc %%g2, 0x0, %%g0\n" + " bne,a 2b\n" + " ldub [%0], %%g2\n" + " b,a 1b\n" + ".previous" + : /* no outputs */ + : "r" (lock) + : "g2", "memory", "cc"); + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sparc/sparc32/pthread_spin_trylock.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sparc/sparc32/pthread_spin_trylock.c new file mode 100644 index 00000000..2994085a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sparc/sparc32/pthread_spin_trylock.c @@ -0,0 +1,29 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include "pthreadP.h" + +int +pthread_spin_trylock (pthread_spinlock_t *lock) +{ + int res; + __asm__ __volatile__ ("ldstub [%1], %0" : "=r" (res) : "r" (lock) : "memory"); + return res == 0 ? 0 : EBUSY; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sparc/sparc32/pthreaddef.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sparc/sparc32/pthreaddef.h new file mode 100644 index 00000000..9908df9e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sparc/sparc32/pthreaddef.h @@ -0,0 +1,40 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Default stack size. */ +#define ARCH_STACK_DEFAULT_SIZE (2 * 1024 * 1024) + +/* Required stack pointer alignment at beginning. */ +#define STACK_ALIGN 16 + +/* Minimal stack size after allocating thread descriptor and guard size. */ +#define MINIMAL_REST_STACK 2048 + +/* Alignment requirement for TCB. */ +#define TCB_ALIGNMENT 16 + + +/* Location of current stack frame. */ +#define CURRENT_STACK_FRAME (stack_pointer + (2 * 64)) +register char *stack_pointer __asm__("%sp"); + +/* XXX Until we have a better place keep the definitions here. */ + +/* While there is no such syscall. */ +#define __exit_thread_inline(val) \ + INLINE_SYSCALL (exit, 1, (val)) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sparc/sparc32/sparcv9/pthread_spin_lock.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sparc/sparc32/sparcv9/pthread_spin_lock.c new file mode 100644 index 00000000..0e18621e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sparc/sparc32/sparcv9/pthread_spin_lock.c @@ -0,0 +1,39 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "pthreadP.h" + +int +pthread_spin_lock (pthread_spinlock_t *lock) +{ + __asm__ __volatile + ("1: ldstub [%0], %%g2\n" + " brnz,pn %%g2, 2f\n" + " membar #StoreLoad | #StoreStore\n" + ".subsection 2\n" + "2: ldub [%0], %%g2\n" + " brnz,pt %%g2, 2b\n" + " membar #LoadLoad\n" + " b,a,pt %%xcc, 1b\n" + ".previous" + : /* no outputs */ + : "r" (lock) + : "g2", "memory"); + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sparc/sparc32/sparcv9/pthread_spin_trylock.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sparc/sparc32/sparcv9/pthread_spin_trylock.c new file mode 100644 index 00000000..3b20a218 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sparc/sparc32/sparcv9/pthread_spin_trylock.c @@ -0,0 +1 @@ +#include diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sparc/sparc32/sparcv9/pthread_spin_unlock.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sparc/sparc32/sparcv9/pthread_spin_unlock.c new file mode 100644 index 00000000..482cbe3d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sparc/sparc32/sparcv9/pthread_spin_unlock.c @@ -0,0 +1 @@ +#include diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sparc/sparc64/jmpbuf-unwind.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sparc/sparc64/jmpbuf-unwind.h new file mode 100644 index 00000000..5cef8b1c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sparc/sparc64/jmpbuf-unwind.h @@ -0,0 +1,31 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +#define _JMPBUF_CFA_UNWINDS_ADJ(_jmpbuf, _context, _adj) \ + _JMPBUF_UNWINDS_ADJ (_jmpbuf, (void *) _Unwind_GetCFA (_context), _adj) + +#define _JMPBUF_UNWINDS_ADJ(_jmpbuf, _address, _adj) \ + ((uintptr_t) (_address) - (_adj) < (uintptr_t) (_jmpbuf)[JB_SP] - (_adj)) + +/* We use the normal lobngjmp for unwinding. */ +#define __libc_unwind_longjmp(buf, val) __libc_longjmp (buf, val) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sparc/sparc64/pthread_spin_lock.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sparc/sparc64/pthread_spin_lock.c new file mode 100644 index 00000000..53a3eab0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sparc/sparc64/pthread_spin_lock.c @@ -0,0 +1,39 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "pthreadP.h" + +int +pthread_spin_lock (pthread_spinlock_t *lock) +{ + __asm__ __volatile + ("1: ldstub [%0], %%g5\n" + " brnz,pn %%g5, 2f\n" + " membar #StoreLoad | #StoreStore\n" + ".subsection 2\n" + "2: ldub [%0], %%g5\n" + " brnz,pt %%g5, 2b\n" + " membar #LoadLoad\n" + " b,a,pt %%xcc, 1b\n" + ".previous" + : /* no outputs */ + : "r" (lock) + : "g5", "memory"); + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sparc/sparc64/pthread_spin_trylock.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sparc/sparc64/pthread_spin_trylock.c new file mode 100644 index 00000000..a8ef1c21 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sparc/sparc64/pthread_spin_trylock.c @@ -0,0 +1,34 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include "pthreadP.h" + +int +pthread_spin_trylock (pthread_spinlock_t *lock) +{ + int res; + __asm__ __volatile + ("ldstub [%1], %0\n" + "membar #StoreLoad | #StoreStore" + : "=r" (res) + : "r" (lock) + : "memory"); + return res == 0 ? 0 : EBUSY; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sparc/sparc64/pthread_spin_unlock.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sparc/sparc64/pthread_spin_unlock.c new file mode 100644 index 00000000..25a8888d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sparc/sparc64/pthread_spin_unlock.c @@ -0,0 +1,30 @@ +/* pthread_spin_unlock -- unlock a spin lock. Generic version. + Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Paul Mackerras , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "pthreadP.h" +#include + +int +pthread_spin_unlock (pthread_spinlock_t *lock) +{ + __asm__ __volatile__ ("membar #StoreStore | #LoadStore"); + *lock = 0; + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sparc/sparc64/pthreaddef.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sparc/sparc64/pthreaddef.h new file mode 100644 index 00000000..ec765121 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sparc/sparc64/pthreaddef.h @@ -0,0 +1,40 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Default stack size. */ +#define ARCH_STACK_DEFAULT_SIZE (4 * 1024 * 1024) + +/* Required stack pointer alignment at beginning. */ +#define STACK_ALIGN 16 + +/* Minimal stack size after allocating thread descriptor and guard size. */ +#define MINIMAL_REST_STACK 4096 + +/* Alignment requirement for TCB. */ +#define TCB_ALIGNMENT 16 + + +/* Location of current stack frame. */ +#define CURRENT_STACK_FRAME (stack_pointer + (2 * 128)) +register char *stack_pointer __asm__("%sp"); + +/* XXX Until we have a better place keep the definitions here. */ + +/* While there is no such syscall. */ +#define __exit_thread_inline(val) \ + INLINE_SYSCALL (exit, 1, (val)) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sparc/tcb-offsets.sym b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sparc/tcb-offsets.sym new file mode 100644 index 00000000..923af8a5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sparc/tcb-offsets.sym @@ -0,0 +1,7 @@ +#include +#include + +MULTIPLE_THREADS_OFFSET offsetof (tcbhead_t, multiple_threads) +POINTER_GUARD offsetof (tcbhead_t, pointer_guard) +PID offsetof (struct pthread, pid) +TID offsetof (struct pthread, tid) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sparc/tls.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sparc/tls.h new file mode 100644 index 00000000..e93542c9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/sparc/tls.h @@ -0,0 +1,181 @@ +/* Definitions for thread-local data handling. NPTL/sparc version. + Copyright (C) 2003, 2005, 2006, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _TLS_H +#define _TLS_H + +#ifndef __ASSEMBLER__ +# include +# include +# include +# include +# include +# include + +/* Type for the dtv. */ +typedef union dtv +{ + size_t counter; + struct + { + void *val; + bool is_static; + } pointer; +} dtv_t; + +typedef struct +{ + void *tcb; /* Pointer to the TCB. Not necessary the + thread descriptor used by libpthread. */ + dtv_t *dtv; + void *self; + int multiple_threads; +#if __WORDSIZE == 64 + int gscope_flag; +#endif + uintptr_t sysinfo; + uintptr_t stack_guard; + uintptr_t pointer_guard; +#if __WORDSIZE != 64 + int gscope_flag; +#endif +#ifndef __ASSUME_PRIVATE_FUTEX + int private_futex; +#endif +} tcbhead_t; + +#else /* __ASSEMBLER__ */ +# include +#endif /* __ASSEMBLER__ */ + +/* We require TLS support in the tools. */ +#define HAVE_TLS_SUPPORT +#define HAVE___THREAD 1 +#define HAVE_TLS_MODEL_ATTRIBUTE 1 + +/* Signal that TLS support is available. */ +#define USE_TLS 1 + +#ifndef __ASSEMBLER__ +/* Get system call information. */ +# include + +/* Get the thread descriptor definition. */ +# include + +register struct pthread *__thread_self __asm__("%g7"); + +/* This is the size of the initial TCB. Can't be just sizeof (tcbhead_t), + because NPTL getpid, __libc_alloca_cutoff etc. need (almost) the whole + struct pthread even when not linked with -lpthread. */ +# define TLS_INIT_TCB_SIZE sizeof (struct pthread) + +/* Alignment requirements for the initial TCB. */ +# define TLS_INIT_TCB_ALIGN __alignof__ (struct pthread) + +/* This is the size of the TCB. */ +# define TLS_TCB_SIZE sizeof (struct pthread) + +/* Alignment requirements for the TCB. */ +# define TLS_TCB_ALIGN __alignof__ (struct pthread) + +/* The TCB can have any size and the memory following the address the + thread pointer points to is unspecified. Allocate the TCB there. */ +# define TLS_TCB_AT_TP 1 + +/* Install the dtv pointer. The pointer passed is to the element with + index -1 which contain the length. */ +# define INSTALL_DTV(descr, dtvp) \ + ((tcbhead_t *) (descr))->dtv = (dtvp) + 1 + +/* Install new dtv for current thread. */ +# define INSTALL_NEW_DTV(DTV) \ + (((tcbhead_t *) __thread_self)->dtv = (DTV)) + +/* Return dtv of given thread descriptor. */ +# define GET_DTV(descr) \ + (((tcbhead_t *) (descr))->dtv) + +/* Code to initially initialize the thread pointer. */ +# define TLS_INIT_TP(descr, secondcall) \ + (__thread_self = (__typeof (__thread_self)) (descr), NULL) + +/* Return the address of the dtv for the current thread. */ +# define THREAD_DTV() \ + (((tcbhead_t *) __thread_self)->dtv) + +/* Return the thread descriptor for the current thread. */ +#define THREAD_SELF __thread_self + +/* Magic for libthread_db to know how to do THREAD_SELF. */ +# define DB_THREAD_SELF_INCLUDE +# define DB_THREAD_SELF \ + REGISTER (32, 32, REG_G7 * 4, 0) REGISTER (64, 64, REG_G7 * 8, 0) + +/* Access to data in the thread descriptor is easy. */ +#define THREAD_GETMEM(descr, member) \ + descr->member +#define THREAD_GETMEM_NC(descr, member, idx) \ + descr->member[idx] +#define THREAD_SETMEM(descr, member, value) \ + descr->member = (value) +#define THREAD_SETMEM_NC(descr, member, idx, value) \ + descr->member[idx] = (value) + +/* Set the stack guard field in TCB head. */ +#define THREAD_SET_STACK_GUARD(value) \ + THREAD_SETMEM (THREAD_SELF, header.stack_guard, value) +# define THREAD_COPY_STACK_GUARD(descr) \ + ((descr)->header.stack_guard \ + = THREAD_GETMEM (THREAD_SELF, header.stack_guard)) + +/* Get/set the stack guard field in TCB head. */ +#define THREAD_GET_POINTER_GUARD() \ + THREAD_GETMEM (THREAD_SELF, header.pointer_guard) +#define THREAD_SET_POINTER_GUARD(value) \ + THREAD_SETMEM (THREAD_SELF, header.pointer_guard, value) +# define THREAD_COPY_POINTER_GUARD(descr) \ + ((descr)->header.pointer_guard = THREAD_GET_POINTER_GUARD ()) + +/* Get and set the global scope generation counter in struct pthread. */ +#define THREAD_GSCOPE_FLAG_UNUSED 0 +#define THREAD_GSCOPE_FLAG_USED 1 +#define THREAD_GSCOPE_FLAG_WAIT 2 +#define THREAD_GSCOPE_RESET_FLAG() \ + do \ + { int __res \ + = atomic_exchange_rel (&THREAD_SELF->header.gscope_flag, \ + THREAD_GSCOPE_FLAG_UNUSED); \ + if (__res == THREAD_GSCOPE_FLAG_WAIT) \ + lll_futex_wake (&THREAD_SELF->header.gscope_flag, 1, LLL_PRIVATE); \ + } \ + while (0) +#define THREAD_GSCOPE_SET_FLAG() \ + do \ + { \ + THREAD_SELF->header.gscope_flag = THREAD_GSCOPE_FLAG_USED; \ + atomic_write_barrier (); \ + } \ + while (0) +#define THREAD_GSCOPE_WAIT() \ + GL(dl_wait_lookup_done) () + +#endif /* !ASSEMBLER */ + +#endif /* tls.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/Makefile new file mode 100644 index 00000000..3ed177ae --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../../ +top_builddir=../../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/Makefile.in new file mode 100644 index 00000000..c2c9bcd3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/Makefile.in @@ -0,0 +1,8 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +subdirs += libpthread/nptl/sysdeps/unix diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/Makefile new file mode 100644 index 00000000..64f51c8d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../../../ +top_builddir=../../../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.in +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/Makefile.in new file mode 100644 index 00000000..83256164 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/Makefile.in @@ -0,0 +1,8 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +subdirs += libpthread/nptl/sysdeps/unix/sysv diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/Makefile new file mode 100644 index 00000000..930ff565 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc NPTL +# +# Copyright (C) 2005 Steven J. Hill +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../../../../ +top_builddir=../../../../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.commonarch +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/Makefile.commonarch b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/Makefile.commonarch new file mode 100644 index 00000000..f1b55357 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/Makefile.commonarch @@ -0,0 +1,211 @@ +# Makefile for uClibc NPTL +# +# Copyright (C) 2006 Steven J. Hill +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +subdirs += libpthread/nptl/sysdeps/unix/sysv/linux \ + libpthread/nptl/sysdeps/unix/sysv/linux/$(TARGET_ARCH) +ifneq ($(abspath libpthread/nptl/sysdeps/unix/sysv/linux/$(TARGET_ARCH)),$(abspath libpthread/nptl/sysdeps/unix/sysv/linux/$(TARGET_ARCH)/$(TARGET_SUBARCH))) +subdirs += libpthread/nptl/sysdeps/unix/sysv/linux/$(TARGET_ARCH)/$(TARGET_SUBARCH) +endif + +libpthread_linux_DIR := $(top_srcdir)libpthread/nptl/sysdeps/unix/sysv/linux +libpthread_linux_OUT := $(top_builddir)libpthread/nptl/sysdeps/unix/sysv/linux +libpthread_linux_arch_DIR := $(libpthread_linux_DIR)/$(TARGET_ARCH) +libpthread_linux_arch_OUT := $(libpthread_linux_OUT)/$(TARGET_ARCH) + +libc_linux_CSRC := +libpthread_linux_CSRC := +librt_linux_CSRC := + +-include $(libpthread_linux_arch_DIR)/Makefile.arch + +ifneq ($(TARGET_SUBARCH),) +libpthread_linux_subarch_DIR := $(libpthread_linux_arch_DIR)/$(TARGET_SUBARCH) +libpthread_linux_subarch_OUT := $(libpthread_linux_arch_OUT)/$(TARGET_SUBARCH) + +libpthread_linux_subarch_SSRC := $(notdir $(wildcard $(libpthread_linux_subarch_DIR)/*.S)) +libc_linux_subarch_SSRC := $(notdir $(wildcard $(libpthread_linux_subarch_DIR)/libc-*.S)) +librt_linux_subarch_SSRC := $(notdir $(wildcard $(libpthread_linux_subarch_DIR)/librt-*.S)) +ifneq ($(libc_linux_subarch_SSRC)$(librt_linux_subarch_SSRC),) +libpthread_linux_subarch_SSRC := $(filter-out $(libc_linux_subarch_SSRC) $(librt_linux_subarch_SSRC),$(libpthread_linux_subarch_SSRC)) +libc_linux_arch_CSRC := $(filter-out $(libc_linux_subarch_SSRC:.S=.c),$(libc_linux_arch_CSRC)) +libc_linux_arch_SSRC := $(filter-out $(libc_linux_subarch_SSRC),$(libc_linux_arch_SSRC)) +endif +ifneq ($(libpthread_linux_subarch_SSRC),) +libpthread_linux_arch_SSRC := $(filter-out $(libpthread_linux_subarch_SSRC),$(libpthread_linux_arch_SSRC)) +libpthread_linux_arch_CSRC := $(filter-out $(libpthread_linux_subarch_SSRC:.S=.c),$(libpthread_linux_arch_CSRC)) +endif +ifneq ($(librt_linux_subarch_SSRC),) +librt_linux_arch_SSRC := $(filter-out $(librt_linux_subarch_SSRC),$(librt_linux_arch_SSRC)) +librt_linux_arch_CSRC := $(filter-out $(librt_linux_subarch_SSRC:.S=.c),$(librt_linux_arch_CSRC)) +endif +libpthread_linux_subarch_SOBJ = $(patsubst %.S,$(libpthread_linux_subarch_OUT)/%.o,$(libpthread_linux_subarch_SSRC)) +libc_linux_subarch_SOBJ := $(patsubst %.S,$(libpthread_linux_subarch_OUT)/%.o,$(libc_linux_subarch_SSRC)) +librt_linux_subarch_SOBJ := $(patsubst %.S,$(libpthread_linux_subarch_OUT)/%.o,$(librt_linux_subarch_SSRC)) +endif + +libpthread_linux_arch_SOBJ = $(patsubst %.S,$(libpthread_linux_arch_OUT)/%.o,$(libpthread_linux_arch_SSRC)) +libpthread_linux_arch_COBJ = $(patsubst %.c,$(libpthread_linux_arch_OUT)/%.o,$(libpthread_linux_arch_CSRC)) +libpthread_linux_arch_OBJS := $(libpthread_linux_subarch_SOBJ) $(libpthread_linux_arch_SOBJ) $(libpthread_linux_arch_COBJ) +libc_linux_arch_SOBJ = $(patsubst %.S,$(libpthread_linux_arch_OUT)/%.o,$(libc_linux_arch_SSRC)) +libc_linux_arch_COBJ = $(patsubst %.c,$(libpthread_linux_arch_OUT)/%.o,$(libc_linux_arch_CSRC)) +libc_linux_arch_OBJS := $(libc_linux_subarch_SOBJ) $(libc_linux_arch_SOBJ) $(libc_linux_arch_COBJ) +librt_linux_arch_SOBJ = $(patsubst %.S,$(libpthread_linux_arch_OUT)/%.o,$(librt_linux_arch_SSRC)) +librt_linux_arch_COBJ = $(patsubst %.c,$(libpthread_linux_arch_OUT)/%.o,$(librt_linux_arch_CSRC)) +librt_linux_arch_OBJS := $(librt_linux_subarch_SOBJ) $(librt_linux_arch_SOBJ) $(librt_linux_arch_COBJ) + +libpthread_linux_CSRC += pthread_attr_getaffinity.c pthread_attr_setaffinity.c \ + pthread_getaffinity.c pthread_setaffinity.c \ + pthread_getcpuclockid.c pthread_kill.c \ + pthread_mutex_cond_lock.c pthread_yield.c \ + sem_post.c sem_timedwait.c sem_trywait.c sem_wait.c \ + pt-fork.c pt-sleep.c pthread_sigqueue.c \ + sigtimedwait.c sigwaitinfo.c sigwait.c \ + lowlevellock.c lowlevelrobustlock.c + +libpthread_linux_SSRC := #ptw-close.S ptw-open.S ptw-waitid.S ptw-waidpid.S ptw-write.S + +libc_linux_CSRC += libc_pthread_init.c libc_multiple_threads.c \ + register-atfork.c unregister-atfork.c getpid.c \ + raise.c sleep.c jmp-unwind.c libc-lowlevellock.c + +librt_linux_CSRC += mq_notify.c timer_create.c timer_delete.c \ + timer_getoverr.c timer_gettime.c timer_routines.c \ + timer_settime.c + +# These provide both a cancellable and a not cancellable implementation +libc_linux_SSRC = close.S open.S write.S read.S waitpid.S +libc_linux_SSRC := $(filter-out $(libc_linux_arch_SSRC-OMIT),$(libc_linux_SSRC)) + +libpthread_linux_CSRC := $(filter-out $(notdir $(libpthread_linux_arch_OBJS:.o=.c)),$(libpthread_linux_CSRC)) +libpthread_linux_SSRC := $(filter-out $(notdir $(libpthread_linux_arch_OBJS:.o=.S)),$(libpthread_linux_SSRC)) +libc_linux_SSRC := $(filter-out $(notdir $(libc_linux_arch_OBJS:.o=.S)),$(libc_linux_SSRC)) +libc_linux_CSRC := $(filter-out $(notdir $(libc_linux_arch_OBJS:.o=.c)),$(libc_linux_CSRC)) +librt_linux_SSRC := $(filter-out $(notdir $(librt_linux_arch_OBJS:.o=.S)),$(librt_linux_SSRC)) +librt_linux_CSRC := $(filter-out $(notdir $(librt_linux_arch_OBJS:.o=.c)),$(librt_linux_CSRC)) + +libpthread_linux_OBJS = $(libpthread_linux_arch_OBJS) +libpthread_linux_OBJS += $(patsubst %.c,$(libpthread_linux_OUT)/%.o,$(libpthread_linux_CSRC)) +libpthread_linux_OBJS += $(patsubst %.S,$(libpthread_linux_OUT)/%.o,$(libpthread_linux_SSRC)) +ifneq ($(libpthread_linux_OMIT_OBJS),) +libpthread_linux_OBJS := $(filter-out $(libpthread_linux_OMIT_OBJS),$(libpthread_linux_OBJS)) +endif + +libpthread-a-y += $(if $(DOPIC),$(libpthread_linux_OBJS:.o=.os),$(libpthread_linux_OBJS)) +libpthread-so-y += $(libpthread_linux_OBJS:.o=.oS) +libpthread-so-y += $(libpthread_linux_OUT)/pt-raise.oS +#libpthread-nomulti-y += $(libpthread_linux_OBJS) + +libc_linux_OBJS := $(libc_linux_arch_OBJS) +libc_linux_OBJS += $(patsubst %.c,$(libpthread_linux_OUT)/%.o,$(libc_linux_CSRC)) +libc_linux_OBJS += $(patsubst %.S,$(libpthread_linux_OUT)/%.o,$(libc_linux_SSRC)) +ifneq ($(libc_linux_OMIT_OBJS),) +libc_linux_OBJS := $(filter-out $(libc_linux_OMIT_OBJS),$(libc_linux_OBJS)) +endif + +libc-static-y += $(libc_linux_OBJS) +libc-shared-y += $(libc_linux_OBJS:.o=.oS) +#libc-nomulti-y += $(libc_linux_OBJS) + +librt_linux_OBJS := $(librt_linux_arch_OBJS) +librt_linux_OBJS += $(patsubst %.c,$(libpthread_linux_OUT)/%.o,$(librt_linux_CSRC)) +librt_linux_OBJS += $(patsubst %.S,$(libpthread_linux_OUT)/%.o,$(librt_linux_SSRC)) + +objclean-y += CLEAN_libpthread/nptl/sysdeps/unix/sysv/linux +headers_clean-y += HEADERCLEAN_libpthread/nptl/sysdeps/unix/sysv/linux + +CFLAGS-pthread_getcpuclockid.c = -I$(top_srcdir)librt +CFLAGS-pt-pread_pwrite.c = -I$(top_srcdir)libc/sysdeps/linux/$(TARGET_ARCH) \ + -I$(top_srcdir)libc/sysdeps/linux/common +CFLAGS-mq_notify.c = -I$(top_srcdir)librt -DIS_IN_librt +CFLAGS-timer_create.c = -I$(top_srcdir)librt -DIS_IN_librt +CFLAGS-timer_delete.c = -I$(top_srcdir)librt -DIS_IN_librt +CFLAGS-timer_getoverr.c = -I$(top_srcdir)librt -DIS_IN_librt +CFLAGS-timer_gettime.c = -I$(top_srcdir)librt -DIS_IN_librt +CFLAGS-timer_routines.c = -I$(top_srcdir)librt -DIS_IN_librt +CFLAGS-timer_settime.c = -I$(top_srcdir)librt -DIS_IN_librt + +CFLAGS-linux = -DNOT_IN_libc -DIS_IN_libpthread $(SSP_ALL_CFLAGS) + +CFLAGS-OMIT-libc_pthread_init.c = -DNOT_IN_libc -DIS_IN_libpthread +CFLAGS-OMIT-libc_multiple_threads.c = -DNOT_IN_libc -DIS_IN_libpthread +CFLAGS-OMIT-register-atfork.c = -DNOT_IN_libc -DIS_IN_libpthread +CFLAGS-OMIT-unregister-atfork.c = -DNOT_IN_libc -DIS_IN_libpthread +CFLAGS-OMIT-getpid.c = -DNOT_IN_libc -DIS_IN_libpthread +CFLAGS-OMIT-raise.c = -DNOT_IN_libc -DIS_IN_libpthread +CFLAGS-OMIT-sleep.c = -DNOT_IN_libc -DIS_IN_libpthread +CFLAGS-OMIT-libc-lowlevellock.c = -DNOT_IN_libc -DIS_IN_libpthread + +CFLAGS-OMIT-close.S = -DNOT_IN_libc -DIS_IN_libpthread +CFLAGS-OMIT-open.S = -DNOT_IN_libc -DIS_IN_libpthread +CFLAGS-OMIT-read.S = -DNOT_IN_libc -DIS_IN_libpthread +CFLAGS-OMIT-write.S = -DNOT_IN_libc -DIS_IN_libpthread +CFLAGS-OMIT-waitpid.S = -DNOT_IN_libc -DIS_IN_libpthread + +CFLAGS-OMIT-mq_notify.c = -DIS_IN_libpthread +CFLAGS-OMIT-timer_create.c = -DIS_IN_libpthread +CFLAGS-OMIT-timer_delete.c = -DIS_IN_libpthread +CFLAGS-OMIT-timer_getoverr.c = -DIS_IN_libpthread +CFLAGS-OMIT-timer_gettime.c = -DIS_IN_libpthread +CFLAGS-OMIT-timer_routines.c = -DIS_IN_libpthread +CFLAGS-OMIT-timer_settime.c = -DIS_IN_libpthread + +ASFLAGS-open.S = -D_LIBC_REENTRANT +ASFLAGS-close.S = -D_LIBC_REENTRANT +ASFLAGS-read.S = -D_LIBC_REENTRANT +ASFLAGS-write.S = -D_LIBC_REENTRANT +ASFLAGS-waitpid.S = -D_LIBC_REENTRANT + +# +# Create header files. +# +CFLAGS-gen_lowlevelbarrier.c = -S +CFLAGS-gen_lowlevelcond.c = -S +CFLAGS-gen_lowlevelrobustlock.c = -S +CFLAGS-gen_lowlevelrwlock.c = -S +CFLAGS-gen_pthread-pi-defines.c = -S +CFLAGS-gen_structsem.c = -S +CFLAGS-gen_unwindbuf.c = -S + +PTHREAD_GENERATE_MANGLE ?= -n "s/^.*@@@name@@@\([^@]*\)@@@value@@@[^0-9Xxa-fA-F-]*\([0-9Xxa-fA-F-][0-9Xxa-fA-F-]*\).*@@@end@@@.*\$$/\#define \1 \2/p" + +PTHREAD_LINUX_SYM := $(notdir $(wildcard $(libpthread_linux_DIR)/*.sym)) +PTHREAD_LINUX_SYM_C := $(addprefix $(libpthread_linux_OUT)/gen_,$(PTHREAD_LINUX_SYM:.sym=.c)) +PTHREAD_LINUX_SYM_S := $(PTHREAD_LINUX_SYM_C:.c=.s) +PTHREAD_LINUX_SYM_H := $(addprefix $(libpthread_linux_OUT)/,$(PTHREAD_LINUX_SYM:.sym=.h)) + +$(PTHREAD_LINUX_SYM_C): $(libpthread_linux_OUT)/gen_%.c: $(libpthread_linux_DIR)/%.sym | $(libpthread_linux_OUT) + $(do_awk) $(top_srcdir)extra/scripts/gen-as-const.awk $< > $@ +$(PTHREAD_LINUX_SYM_S): $(libpthread_linux_OUT)/gen_%.s: $(libpthread_linux_OUT)/gen_%.c | headers + $(compile.c) +libpthread-generated-y += $(PTHREAD_LINUX_SYM_S) +$(PTHREAD_LINUX_SYM_H): $(libpthread_linux_OUT)/%.h: $(libpthread_linux_OUT)/gen_%.s + $(do_sed) $(PTHREAD_GENERATE_MANGLE) $< > $@ + @if test ! -s $@ ; then rm -f $@ ; false ; fi + +pregen-headers-$(UCLIBC_HAS_THREADS_NATIVE) += $(PTHREAD_LINUX_SYM_H) + +HEADERS_BITS_PTHREAD := $(notdir $(wildcard $(libpthread_linux_DIR)/bits/*.h)) +ALL_HEADERS_BITS_PTHREAD := $(addprefix $(top_builddir)include/bits/,$(HEADERS_BITS_PTHREAD)) + +$(ALL_HEADERS_BITS_PTHREAD): $(top_builddir)include/bits/%: | $(top_builddir)include/bits + $(do_ln) $(call rel_srcdir)$(libpthread_linux_DIR)/bits/$(@F) $@ + +HEADERCLEAN_libpthread/nptl/sysdeps/unix/sysv/linux: + $(do_rm) $(PTHREAD_LINUX_SYM_C) $(PTHREAD_LINUX_SYM_S) \ + $(PTHREAD_LINUX_SYM_H) + +CLEAN_libpthread/nptl/sysdeps/unix/sysv/linux: + $(do_rm) $(addprefix $(libpthread_linux_OUT)/*., o os oS) + +objclean-y+=CLEAN_libpthread/nptl/sysdeps/unix/sysv/linux/$(TARGET_ARCH) +CLEAN_libpthread/nptl/sysdeps/unix/sysv/linux/$(TARGET_ARCH): + $(do_rm) $(addprefix $(libpthread_linux_arch_OUT)/*., o os oS) +ifneq ($(TARGET_SUBARCH),) +objclean-y+=CLEAN_libpthread/nptl/sysdeps/unix/sysv/linux/$(TARGET_ARCH)/$(TARGET_SUBARCH) +CLEAN_libpthread/nptl/sysdeps/unix/sysv/linux/$(TARGET_ARCH)/$(TARGET_SUBARCH): + $(do_rm) $(addprefix $(libpthread_linux_subarch_OUT)/*., o os oS) +endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/__syscall_error.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/__syscall_error.c new file mode 100644 index 00000000..5e109a83 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/__syscall_error.c @@ -0,0 +1,18 @@ +/* Wrapper for setting errno. + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +/* This routine is jumped to by all the syscall handlers, to stash + * an error number into errno. */ +int __syscall_error(int err_no) attribute_hidden; +int __syscall_error(int err_no) +{ + __set_errno(err_no); + return -1; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/accept.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/accept.S new file mode 100644 index 00000000..529763d8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/accept.S @@ -0,0 +1,12 @@ +#include +#ifndef __NR_accept +#error Missing definition of NR_accept needed for cancellation. +#endif +PSEUDO (__libc_accept, accept, 3) +ret +PSEUDO_END(__libc_accept) +libc_hidden_def (__libc_accept) +weak_alias (__libc_accept, __accept) +libc_hidden_weak (__accept) +weak_alias (__libc_accept, accept) +libc_hidden_weak (accept) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/Makefile new file mode 100644 index 00000000..8c808407 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/Makefile @@ -0,0 +1,2 @@ +# pull in __syscall_error routine, __sigprocmask, __syscall_rt_sigaction +libpthread-routines += ptw-sysdep ptw-sigprocmask ptw-rt_sigaction diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/bits/local_lim.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/bits/local_lim.h new file mode 100644 index 00000000..a7c9740a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/bits/local_lim.h @@ -0,0 +1,100 @@ +/* Minimum guaranteed maximum values for system limits. Linux/Alpha version. + Copyright (C) 1993-1998,2000,2002-2004,2008 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* The kernel header pollutes the namespace with the NR_OPEN symbol + and defines LINK_MAX although filesystems have different maxima. A + similar thing is true for OPEN_MAX: the limit can be changed at + runtime and therefore the macro must not be defined. Remove this + after including the header if necessary. */ +#ifndef NR_OPEN +# define __undef_NR_OPEN +#endif +#ifndef LINK_MAX +# define __undef_LINK_MAX +#endif +#ifndef OPEN_MAX +# define __undef_OPEN_MAX +#endif +#ifndef ARG_MAX +# define __undef_ARG_MAX +#endif + +/* The kernel sources contain a file with all the needed information. */ +#include + +/* Have to remove NR_OPEN? */ +#ifdef __undef_NR_OPEN +# undef NR_OPEN +# undef __undef_NR_OPEN +#endif +/* Have to remove LINK_MAX? */ +#ifdef __undef_LINK_MAX +# undef LINK_MAX +# undef __undef_LINK_MAX +#endif +/* Have to remove OPEN_MAX? */ +#ifdef __undef_OPEN_MAX +# undef OPEN_MAX +# undef __undef_OPEN_MAX +#endif +/* Have to remove ARG_MAX? */ +#ifdef __undef_ARG_MAX +# undef ARG_MAX +# undef __undef_ARG_MAX +#endif + +/* The number of data keys per process. */ +#define _POSIX_THREAD_KEYS_MAX 128 +/* This is the value this implementation supports. */ +#define PTHREAD_KEYS_MAX 1024 + +/* Controlling the iterations of destructors for thread-specific data. */ +#define _POSIX_THREAD_DESTRUCTOR_ITERATIONS 4 +/* Number of iterations this implementation does. */ +#define PTHREAD_DESTRUCTOR_ITERATIONS _POSIX_THREAD_DESTRUCTOR_ITERATIONS + +/* The number of threads per process. */ +#define _POSIX_THREAD_THREADS_MAX 64 +/* We have no predefined limit on the number of threads. */ +#undef PTHREAD_THREADS_MAX + +/* Maximum amount by which a process can descrease its asynchronous I/O + priority level. */ +#define AIO_PRIO_DELTA_MAX 20 + +/* Minimum size for a thread. We are free to choose a reasonable value. */ +#define PTHREAD_STACK_MIN 24576 + +/* Maximum number of timer expiration overruns. */ +#define DELAYTIMER_MAX 2147483647 + +/* Maximum tty name length. */ +#define TTY_NAME_MAX 32 + +/* Maximum login name length. This is arbitrary. */ +#define LOGIN_NAME_MAX 256 + +/* Maximum host name length. */ +#define HOST_NAME_MAX 64 + +/* Maximum message queue priority level. */ +#define MQ_PRIO_MAX 32768 + +/* Maximum value the semaphore can have. */ +#define SEM_VALUE_MAX (2147483647) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h new file mode 100644 index 00000000..41c0be19 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/bits/pthreadtypes.h @@ -0,0 +1,168 @@ +/* Machine-specific pthread type layouts. Alpha version. + Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _BITS_PTHREADTYPES_H +#define _BITS_PTHREADTYPES_H 1 + +#define __SIZEOF_PTHREAD_ATTR_T 56 +#define __SIZEOF_PTHREAD_MUTEX_T 40 +#define __SIZEOF_PTHREAD_MUTEXATTR_T 4 +#define __SIZEOF_PTHREAD_COND_T 48 +#define __SIZEOF_PTHREAD_CONDATTR_T 4 +#define __SIZEOF_PTHREAD_RWLOCK_T 56 +#define __SIZEOF_PTHREAD_RWLOCKATTR_T 8 +#define __SIZEOF_PTHREAD_BARRIER_T 32 +#define __SIZEOF_PTHREAD_BARRIERATTR_T 4 + + +/* Thread identifiers. The structure of the attribute type is + deliberately not exposed. */ +typedef unsigned long int pthread_t; + + +typedef union +{ + char __size[__SIZEOF_PTHREAD_ATTR_T]; + long int __align; +} pthread_attr_t; + + +typedef struct __pthread_internal_list +{ + struct __pthread_internal_list *__prev; + struct __pthread_internal_list *__next; +} __pthread_list_t; + + +/* Data structures for mutex handling. The structure of the attribute + type is deliberately not exposed. */ +typedef union +{ + struct __pthread_mutex_s + { + int __lock; + unsigned int __count; + int __owner; + unsigned int __nusers; + /* KIND must stay at this position in the structure to maintain + binary compatibility. */ + int __kind; + int __spins; + __pthread_list_t __list; +#define __PTHREAD_MUTEX_HAVE_PREV 1 + } __data; + char __size[__SIZEOF_PTHREAD_MUTEX_T]; + long int __align; +} pthread_mutex_t; + +typedef union +{ + char __size[__SIZEOF_PTHREAD_MUTEXATTR_T]; + int __align; +} pthread_mutexattr_t; + + +/* Data structure for conditional variable handling. The structure of + the attribute type is deliberately not exposed. */ +typedef union +{ + struct + { + int __lock; + unsigned int __futex; + __extension__ unsigned long long int __total_seq; + __extension__ unsigned long long int __wakeup_seq; + __extension__ unsigned long long int __woken_seq; + void *__mutex; + unsigned int __nwaiters; + unsigned int __broadcast_seq; + } __data; + char __size[__SIZEOF_PTHREAD_COND_T]; + __extension__ long long int __align; +} pthread_cond_t; + +typedef union +{ + char __size[__SIZEOF_PTHREAD_CONDATTR_T]; + int __align; +} pthread_condattr_t; + + +/* Keys for thread-specific data */ +typedef unsigned int pthread_key_t; + + +/* Once-only execution */ +typedef int pthread_once_t; + + +#if defined __USE_UNIX98 || defined __USE_XOPEN2K +/* Data structure for read-write lock variable handling. The + structure of the attribute type is deliberately not exposed. */ +typedef union +{ + struct + { + int __lock; + unsigned int __nr_readers; + unsigned int __readers_wakeup; + unsigned int __writer_wakeup; + unsigned int __nr_readers_queued; + unsigned int __nr_writers_queued; + int __writer; + int __shared; + unsigned long int __pad1; + unsigned long int __pad2; + /* FLAGS must stay at this position in the structure to maintain + binary compatibility. */ + unsigned int __flags; + } __data; + char __size[__SIZEOF_PTHREAD_RWLOCK_T]; + long int __align; +} pthread_rwlock_t; + +typedef union +{ + char __size[__SIZEOF_PTHREAD_RWLOCKATTR_T]; + long int __align; +} pthread_rwlockattr_t; +#endif + + +#ifdef __USE_XOPEN2K +/* POSIX spinlock data type. */ +typedef volatile int pthread_spinlock_t; + +/* POSIX barriers data type. The structure of the type is + deliberately not exposed. */ +typedef union +{ + char __size[__SIZEOF_PTHREAD_BARRIER_T]; + long int __align; +} pthread_barrier_t; + +typedef union +{ + char __size[__SIZEOF_PTHREAD_BARRIERATTR_T]; + int __align; +} pthread_barrierattr_t; +#endif + + +#endif /* bits/pthreadtypes.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/bits/semaphore.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/bits/semaphore.h new file mode 100644 index 00000000..be4469c6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/bits/semaphore.h @@ -0,0 +1,34 @@ +/* Machine-specific POSIX semaphore type layouts. Alpha version. + Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SEMAPHORE_H +# error "Never use directly; include instead." +#endif + +# define __SIZEOF_SEM_T 32 + +/* Value returned if `sem_open' failed. */ +#define SEM_FAILED ((sem_t *) 0) + + +typedef union +{ + char __size[__SIZEOF_SEM_T]; + long int __align; +} sem_t; diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/clone.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/clone.S new file mode 100644 index 00000000..eea1cbee --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/clone.S @@ -0,0 +1,2 @@ +#define RESET_PID +#include diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/createthread.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/createthread.c new file mode 100644 index 00000000..2b19fd5d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/createthread.c @@ -0,0 +1,23 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Value passed to 'clone' for initialization of the thread register. */ +#define TLS_VALUE (pd + 1) + +/* Get the real implementation. */ +#include diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/fork.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/fork.c new file mode 100644 index 00000000..ca85fc00 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/fork.c @@ -0,0 +1,30 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + + +#define ARCH_FORK() \ + INLINE_SYSCALL (clone, 5, \ + CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | SIGCHLD, \ + NULL, NULL, &THREAD_SELF->tid, NULL) + +#include "../fork.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/lowlevellock.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/lowlevellock.h new file mode 100644 index 00000000..b7f4de33 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/lowlevellock.h @@ -0,0 +1,284 @@ +/* Copyright (C) 2003, 2004, 2006, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Libr \ary; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _LOWLEVELLOCK_H +#define _LOWLEVELLOCK_H 1 + +#include +#include +#include +#include +#include +#include + + +#define FUTEX_WAIT 0 +#define FUTEX_WAKE 1 +#define FUTEX_REQUEUE 3 +#define FUTEX_CMP_REQUEUE 4 +#define FUTEX_WAKE_OP 5 +#define FUTEX_OP_CLEAR_WAKE_IF_GT_ONE ((4 << 24) | 1) +#define FUTEX_LOCK_PI 6 +#define FUTEX_UNLOCK_PI 7 +#define FUTEX_TRYLOCK_PI 8 +#define FUTEX_WAIT_BITSET 9 +#define FUTEX_WAKE_BITSET 10 +#define FUTEX_PRIVATE_FLAG 128 +#define FUTEX_CLOCK_REALTIME 256 + +#define FUTEX_BITSET_MATCH_ANY 0xffffffff + +/* Values for 'private' parameter of locking macros. Yes, the + definition seems to be backwards. But it is not. The bit will be + reversed before passing to the system call. */ +#define LLL_PRIVATE 0 +#define LLL_SHARED FUTEX_PRIVATE_FLAG + + +#if !defined NOT_IN_libc || defined IS_IN_rtld +/* In libc.so or ld.so all futexes are private. */ +# ifdef __ASSUME_PRIVATE_FUTEX +# define __lll_private_flag(fl, private) \ + ((fl) | FUTEX_PRIVATE_FLAG) +# else +# define __lll_private_flag(fl, private) \ + ((fl) | THREAD_GETMEM (THREAD_SELF, header.private_futex)) +# endif +#else +# ifdef __ASSUME_PRIVATE_FUTEX +# define __lll_private_flag(fl, private) \ + (((fl) | FUTEX_PRIVATE_FLAG) ^ (private)) +# else +# define __lll_private_flag(fl, private) \ + (__builtin_constant_p (private) \ + ? ((private) == 0 \ + ? ((fl) | THREAD_GETMEM (THREAD_SELF, header.private_futex)) \ + : (fl)) \ + : ((fl) | (((private) ^ FUTEX_PRIVATE_FLAG) \ + & THREAD_GETMEM (THREAD_SELF, header.private_futex)))) +# endif +#endif + + +#define lll_futex_wait(futexp, val, private) \ + lll_futex_timed_wait (futexp, val, NULL, private) + +#define lll_futex_timed_wait(futexp, val, timespec, private) \ + ({ \ + INTERNAL_SYSCALL_DECL (__err); \ + long int __ret; \ + __ret = INTERNAL_SYSCALL (futex, __err, 4, (futexp), \ + __lll_private_flag (FUTEX_WAIT, private), \ + (val), (timespec)); \ + INTERNAL_SYSCALL_ERROR_P (__ret, __err)? -__ret : __ret; \ + }) + +#define lll_futex_wake(futexp, nr, private) \ + ({ \ + INTERNAL_SYSCALL_DECL (__err); \ + long int __ret; \ + __ret = INTERNAL_SYSCALL (futex, __err, 4, (futexp), \ + __lll_private_flag (FUTEX_WAKE, private), \ + (nr), 0); \ + INTERNAL_SYSCALL_ERROR_P (__ret, __err)? -__ret : __ret; \ + }) + +#define lll_robust_dead(futexv, private) \ + do \ + { \ + int *__futexp = &(futexv); \ + atomic_or (__futexp, FUTEX_OWNER_DIED); \ + lll_futex_wake (__futexp, 1, private); \ + } \ + while (0) + +/* Returns non-zero if error happened, zero if success. */ +#define lll_futex_requeue(futexp, nr_wake, nr_move, mutex, val, private) \ + ({ \ + INTERNAL_SYSCALL_DECL (__err); \ + long int __ret; \ + __ret = INTERNAL_SYSCALL (futex, __err, 6, (futexp), \ + __lll_private_flag (FUTEX_CMP_REQUEUE, private),\ + (nr_wake), (nr_move), (mutex), (val)); \ + INTERNAL_SYSCALL_ERROR_P (__ret, __err); \ + }) + +/* Returns non-zero if error happened, zero if success. */ +#define lll_futex_wake_unlock(futexp, nr_wake, nr_wake2, futexp2, private) \ + ({ \ + INTERNAL_SYSCALL_DECL (__err); \ + long int __ret; \ + __ret = INTERNAL_SYSCALL (futex, __err, 6, (futexp), \ + __lll_private_flag (FUTEX_WAKE_OP, private), \ + (nr_wake), (nr_wake2), (futexp2), \ + FUTEX_OP_CLEAR_WAKE_IF_GT_ONE); \ + INTERNAL_SYSCALL_ERROR_P (__ret, __err); \ + }) + + + + +static inline int __attribute__((always_inline)) +__lll_trylock(int *futex) +{ + return atomic_compare_and_exchange_val_acq (futex, 1, 0) != 0; +} +#define lll_trylock(lock) __lll_trylock (&(lock)) + + +static inline int __attribute__((always_inline)) +__lll_cond_trylock(int *futex) +{ + return atomic_compare_and_exchange_val_acq (futex, 2, 0) != 0; +} +#define lll_cond_trylock(lock) __lll_cond_trylock (&(lock)) + + +static inline int __attribute__((always_inline)) +__lll_robust_trylock(int *futex, int id) +{ + return atomic_compare_and_exchange_val_acq (futex, id, 0) != 0; +} +#define lll_robust_trylock(lock, id) \ + __lll_robust_trylock (&(lock), id) + +extern void __lll_lock_wait_private (int *futex) attribute_hidden; +extern void __lll_lock_wait (int *futex, int private) attribute_hidden; +extern int __lll_robust_lock_wait (int *futex, int private) attribute_hidden; + +static inline void __attribute__((always_inline)) +__lll_lock(int *futex, int private) +{ + if (atomic_compare_and_exchange_bool_acq (futex, 1, 0) != 0) + { + if (__builtin_constant_p (private) && private == LLL_PRIVATE) + __lll_lock_wait_private (futex); + else + __lll_lock_wait (futex, private); + } +} +#define lll_lock(futex, private) __lll_lock (&(futex), private) + + +static inline int __attribute__ ((always_inline)) +__lll_robust_lock (int *futex, int id, int private) +{ + int result = 0; + if (atomic_compare_and_exchange_bool_acq (futex, id, 0) != 0) + result = __lll_robust_lock_wait (futex, private); + return result; +} +#define lll_robust_lock(futex, id, private) \ + __lll_robust_lock (&(futex), id, private) + + +static inline void __attribute__ ((always_inline)) +__lll_cond_lock (int *futex, int private) +{ + if (atomic_compare_and_exchange_bool_acq (futex, 2, 0) != 0) + __lll_lock_wait (futex, private); +} +#define lll_cond_lock(futex, private) __lll_cond_lock (&(futex), private) + + +#define lll_robust_cond_lock(futex, id, private) \ + __lll_robust_lock (&(futex), (id) | FUTEX_WAITERS, private) + + +extern int __lll_timedlock_wait (int *futex, const struct timespec *, + int private) attribute_hidden; +extern int __lll_robust_timedlock_wait (int *futex, const struct timespec *, + int private) attribute_hidden; + +static inline int __attribute__ ((always_inline)) +__lll_timedlock (int *futex, const struct timespec *abstime, int private) +{ + int result = 0; + if (atomic_compare_and_exchange_bool_acq (futex, 1, 0) != 0) + result = __lll_timedlock_wait (futex, abstime, private); + return result; +} +#define lll_timedlock(futex, abstime, private) \ + __lll_timedlock (&(futex), abstime, private) + + +static inline int __attribute__ ((always_inline)) +__lll_robust_timedlock (int *futex, const struct timespec *abstime, + int id, int private) +{ + int result = 0; + if (atomic_compare_and_exchange_bool_acq (futex, id, 0) != 0) + result = __lll_robust_timedlock_wait (futex, abstime, private); + return result; +} +#define lll_robust_timedlock(futex, abstime, id, private) \ + __lll_robust_timedlock (&(futex), abstime, id, private) + + +#define __lll_unlock(futex, private) \ + (void) \ + ({ int *__futex = (futex); \ + int __oldval = atomic_exchange_rel (__futex, 0); \ + if (__builtin_expect (__oldval > 1, 0)) \ + lll_futex_wake (__futex, 1, private); \ + }) +#define lll_unlock(futex, private) __lll_unlock(&(futex), private) + + +#define __lll_robust_unlock(futex, private) \ + (void) \ + ({ int *__futex = (futex); \ + int __oldval = atomic_exchange_rel (__futex, 0); \ + if (__builtin_expect (__oldval & FUTEX_WAITERS, 0)) \ + lll_futex_wake (__futex, 1, private); \ + }) +#define lll_robust_unlock(futex, private) \ + __lll_robust_unlock(&(futex), private) + + +#define lll_islocked(futex) \ + (futex != 0) + +/* Initializers for lock. */ +#define LLL_LOCK_INITIALIZER (0) +#define LLL_LOCK_INITIALIZER_LOCKED (1) + + +/* The kernel notifies a process which uses CLONE_CLEARTID via futex + wakeup when the clone terminates. The memory location contains the + thread ID while the clone is running and is reset to zero + afterwards. */ +#define lll_wait_tid(tid) \ + do { \ + __typeof (tid) __tid; \ + while ((__tid = (tid)) != 0) \ + lll_futex_wait (&(tid), __tid, LLL_SHARED); \ + } while (0) + +extern int __lll_timedwait_tid (int *, const struct timespec *) + attribute_hidden; + +#define lll_timedwait_tid(tid, abstime) \ + ({ \ + int __res = 0; \ + if ((tid) != 0) \ + __res = __lll_timedwait_tid (&(tid), (abstime)); \ + __res; \ + }) + +#endif /* lowlevellock.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/pt-vfork.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/pt-vfork.S new file mode 100644 index 00000000..ec5d175b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/pt-vfork.S @@ -0,0 +1,43 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +#undef PSEUDO_PREPARE_ARGS +#define PSEUDO_PREPARE_ARGS \ + /* Load the current cached pid value across the vfork. */ \ + rduniq; \ + ldl a2, PID_OFFSET(v0); \ + mov v0, a1; \ + /* Write back its negation, to indicate that the pid value is \ + uninitialized in the the child, and in the window between \ + here and the point at which we restore the value. */ \ + negl a2, t0; \ + stl t0, PID_OFFSET(v0); + +PSEUDO (__vfork, vfork, 0) + + /* If we're back in the parent, restore the saved pid. */ + beq v0, 1f + stl a2, PID_OFFSET(a1) +1: ret + +PSEUDO_END (__vfork) + +weak_alias (__vfork, vfork) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/pthread_once.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/pthread_once.c new file mode 100644 index 00000000..86b06280 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/pthread_once.c @@ -0,0 +1,97 @@ +/* Copyright (C) 2003, 2004, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "pthreadP.h" +#include + + +unsigned long int __fork_generation attribute_hidden; + +static void +clear_once_control (void *arg) +{ + pthread_once_t *once_control = (pthread_once_t *) arg; + + *once_control = 0; + lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE); +} + +int +attribute_protected +__pthread_once (pthread_once_t *once_control, void (*init_routine) (void)) +{ + for (;;) + { + int oldval; + int newval; + int tmp; + + /* Pseudo code: + newval = __fork_generation | 1; + oldval = *once_control; + if ((oldval & 2) == 0) + *once_control = newval; + Do this atomically. + */ + newval = __fork_generation | 1; + __asm__ __volatile__ ( + "1: ldl_l %0, %2\n" + " and %0, 2, %1\n" + " bne %1, 2f\n" + " mov %3, %1\n" + " stl_c %1, %2\n" + " beq %1, 1b\n" + "2: mb" + : "=&r" (oldval), "=&r" (tmp), "=m" (*once_control) + : "r" (newval), "m" (*once_control)); + + /* Check if the initializer has already been done. */ + if ((oldval & 2) != 0) + return 0; + + /* Check if another thread already runs the initializer. */ + if ((oldval & 1) == 0) + break; + + /* Check whether the initializer execution was interrupted by a fork. */ + if (oldval != newval) + break; + + /* Same generation, some other thread was faster. Wait. */ + lll_futex_wait (once_control, oldval, LLL_PRIVATE); + } + + /* This thread is the first here. Do the initialization. + Register a cleanup handler so that in case the thread gets + interrupted the initialization can be restarted. */ + pthread_cleanup_push (clear_once_control, once_control); + + init_routine (); + + pthread_cleanup_pop (0); + + /* Add one to *once_control to take the bottom 2 bits from 01 to 10. */ + atomic_increment (once_control); + + /* Wake up all other threads. */ + lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE); + + return 0; +} +weak_alias (__pthread_once, pthread_once) +strong_alias (__pthread_once, __pthread_once_internal) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/sem_post.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/sem_post.c new file mode 100644 index 00000000..27fd817e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/sem_post.c @@ -0,0 +1,5 @@ +/* ??? This is an ass-backwards way to do this. We should simply define + the acquire/release semantics of atomic_exchange_and_add. And even if + we don't do this, we should be using atomic_full_barrier or otherwise. */ +#define __lll_rel_instr "mb" +#include "../sem_post.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/sysdep-cancel.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/sysdep-cancel.h new file mode 100644 index 00000000..7049b360 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/sysdep-cancel.h @@ -0,0 +1,177 @@ +/* Copyright (C) 2003, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#ifndef __ASSEMBLER__ +# include +#endif + +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + +# ifdef PROF +# define PSEUDO_PROF \ + .set noat; \ + lda AT, _mcount; \ + jsr AT, (AT), _mcount; \ + .set at +# else +# define PSEUDO_PROF +# endif + +/* ??? Assumes that nothing comes between PSEUDO and PSEUDO_END + besides "ret". */ + +# undef PSEUDO +# define PSEUDO(name, syscall_name, args) \ + .globl name; \ + .align 4; \ + .type name, @function; \ + .usepv name, std; \ + cfi_startproc; \ +__LABEL(name) \ + ldgp gp, 0(pv); \ + PSEUDO_PROF; \ + PSEUDO_PREPARE_ARGS \ + SINGLE_THREAD_P(t0); \ + bne t0, $pseudo_cancel; \ + lda v0, SYS_ify(syscall_name); \ + call_pal PAL_callsys; \ + bne a3, SYSCALL_ERROR_LABEL; \ +__LABEL($pseudo_ret) \ + .subsection 2; \ + cfi_startproc; \ +__LABEL($pseudo_cancel) \ + subq sp, 64, sp; \ + cfi_def_cfa_offset(64); \ + stq ra, 0(sp); \ + cfi_offset(ra, -64); \ + SAVE_ARGS_##args; \ + CENABLE; \ + LOAD_ARGS_##args; \ + /* Save the CENABLE return value in RA. That register \ + is preserved across syscall and the real return \ + address is saved on the stack. */ \ + mov v0, ra; \ + lda v0, SYS_ify(syscall_name); \ + call_pal PAL_callsys; \ + stq v0, 8(sp); \ + mov ra, a0; \ + bne a3, $multi_error; \ + CDISABLE; \ + ldq ra, 0(sp); \ + ldq v0, 8(sp); \ + addq sp, 64, sp; \ + cfi_remember_state; \ + cfi_restore(ra); \ + cfi_def_cfa_offset(0); \ + ret; \ + cfi_restore_state; \ +__LABEL($multi_error) \ + CDISABLE; \ + ldq ra, 0(sp); \ + ldq v0, 8(sp); \ + addq sp, 64, sp; \ + cfi_restore(ra); \ + cfi_def_cfa_offset(0); \ +__LABEL($syscall_error) \ + SYSCALL_ERROR_HANDLER; \ + cfi_endproc; \ + .previous + +# undef PSEUDO_END +# define PSEUDO_END(sym) \ + cfi_endproc; \ + .subsection 2; \ + .size sym, .-sym + +# define SAVE_ARGS_0 /* Nothing. */ +# define SAVE_ARGS_1 SAVE_ARGS_0; stq a0, 8(sp) +# define SAVE_ARGS_2 SAVE_ARGS_1; stq a1, 16(sp) +# define SAVE_ARGS_3 SAVE_ARGS_2; stq a2, 24(sp) +# define SAVE_ARGS_4 SAVE_ARGS_3; stq a3, 32(sp) +# define SAVE_ARGS_5 SAVE_ARGS_4; stq a4, 40(sp) +# define SAVE_ARGS_6 SAVE_ARGS_5; stq a5, 48(sp) + +# define LOAD_ARGS_0 /* Nothing. */ +# define LOAD_ARGS_1 LOAD_ARGS_0; ldq a0, 8(sp) +# define LOAD_ARGS_2 LOAD_ARGS_1; ldq a1, 16(sp) +# define LOAD_ARGS_3 LOAD_ARGS_2; ldq a2, 24(sp) +# define LOAD_ARGS_4 LOAD_ARGS_3; ldq a3, 32(sp) +# define LOAD_ARGS_5 LOAD_ARGS_4; ldq a4, 40(sp) +# define LOAD_ARGS_6 LOAD_ARGS_5; ldq a5, 48(sp) + +# ifdef IS_IN_libpthread +# define __local_enable_asynccancel __pthread_enable_asynccancel +# define __local_disable_asynccancel __pthread_disable_asynccancel +# define __local_multiple_threads __pthread_multiple_threads +# elif !defined NOT_IN_libc +# define __local_enable_asynccancel __libc_enable_asynccancel +# define __local_disable_asynccancel __libc_disable_asynccancel +# define __local_multiple_threads __libc_multiple_threads +# elif defined IS_IN_librt +# define __local_enable_asynccancel __librt_enable_asynccancel +# define __local_disable_asynccancel __librt_disable_asynccancel +# else +# error Unsupported library +# endif + +# ifdef __PIC__ +# define CENABLE bsr ra, __local_enable_asynccancel !samegp +# define CDISABLE bsr ra, __local_disable_asynccancel !samegp +# else +# define CENABLE jsr ra, __local_enable_asynccancel; ldgp ra, 0(gp) +# define CDISABLE jsr ra, __local_disable_asynccancel; ldgp ra, 0(gp) +# endif + +# if defined IS_IN_libpthread || !defined NOT_IN_libc +# ifndef __ASSEMBLER__ +extern int __local_multiple_threads attribute_hidden; +# define SINGLE_THREAD_P \ + __builtin_expect (__local_multiple_threads == 0, 1) +# elif defined(__PIC__) +# define SINGLE_THREAD_P(reg) ldl reg, __local_multiple_threads(gp) !gprel +# else +# define SINGLE_THREAD_P(reg) \ + ldah reg, __local_multiple_threads(gp) !gprelhigh; \ + ldl reg, __local_multiple_threads(reg) !gprellow +# endif +# else +# ifndef __ASSEMBLER__ +# define SINGLE_THREAD_P \ + __builtin_expect (THREAD_GETMEM (THREAD_SELF, \ + header.multiple_threads) == 0, 1) +# else +# define SINGLE_THREAD_P(reg) \ + call_pal PAL_rduniq; \ + ldl reg, MULTIPLE_THREADS_OFFSET($0) +# endif +# endif + +#else + +# define SINGLE_THREAD_P (1) +# define NO_CANCELLATION 1 + +#endif + +#ifndef __ASSEMBLER__ +# define RTLD_SINGLE_THREAD_P \ + __builtin_expect (THREAD_GETMEM (THREAD_SELF, \ + header.multiple_threads) == 0, 1) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/timer_create.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/timer_create.c new file mode 100644 index 00000000..172223af --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/timer_create.c @@ -0,0 +1 @@ +#include "../x86_64/timer_create.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/timer_delete.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/timer_delete.c new file mode 100644 index 00000000..537516e0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/timer_delete.c @@ -0,0 +1 @@ +#include "../x86_64/timer_delete.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/timer_getoverr.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/timer_getoverr.c new file mode 100644 index 00000000..3f21a73c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/timer_getoverr.c @@ -0,0 +1 @@ +#include "../x86_64/timer_getoverr.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/timer_gettime.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/timer_gettime.c new file mode 100644 index 00000000..a50143ad --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/timer_gettime.c @@ -0,0 +1 @@ +#include "../x86_64/timer_gettime.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/timer_settime.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/timer_settime.c new file mode 100644 index 00000000..37baeffa --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/timer_settime.c @@ -0,0 +1 @@ +#include "../x86_64/timer_settime.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/vfork.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/vfork.S new file mode 100644 index 00000000..f4ed9311 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/alpha/vfork.S @@ -0,0 +1,46 @@ +/* Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +#undef PSEUDO_PREPARE_ARGS +#define PSEUDO_PREPARE_ARGS \ + /* Load the current cached pid value across the vfork. */ \ + rduniq; \ + ldl a2, PID_OFFSET(v0); \ + mov v0, a1; \ + /* If the cached value is initialized (nonzero), then write \ + back its negation, or INT_MIN, to indicate that the pid \ + value is uninitialized in the the child, and in the window \ + between here and the point at which we restore the value. */ \ + ldah t0, -0x8000; \ + negl a2, t1; \ + cmovne a2, t1, t0; \ + stl t0, PID_OFFSET(v0); + +PSEUDO (__vfork, vfork, 0) + + /* If we're back in the parent, restore the saved pid. */ + beq v0, 1f + stl a2, PID_OFFSET(a1) +1: ret + +PSEUDO_END (__vfork) +libc_hidden_def (__vfork) +weak_alias (__vfork, vfork) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/arm/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/arm/Makefile new file mode 100644 index 00000000..43a6fad8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/arm/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc NPTL +# +# Copyright (C) 2005 Steven J. Hill +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../../../../../ +top_builddir=../../../../../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.arch +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/arm/Makefile.arch b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/arm/Makefile.arch new file mode 100644 index 00000000..329d8a94 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/arm/Makefile.arch @@ -0,0 +1,32 @@ +# Makefile for uClibc NPTL +# +# Copyright (C) 2006 Steven J. Hill +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +libpthread_linux_arch_SSRC = pt-vfork.S +libpthread_linux_arch_CSRC = pthread_once.c \ + pt-__syscall_rt_sigaction.c pt-__syscall_error.c \ + lowlevellock.c + +libc_linux_arch_CSRC = fork.c libc-lowlevellock.c +libc_linux_arch_SSRC = clone.S vfork.S +libc_linux_arch_SSRC-OMIT = waitpid.S + + +CFLAGS-pthread_once.c = -DNOT_IN_libc -DIS_IN_libpthread +CFLAGS-pt-__syscall_rt_sigaction.c = -DNOT_IN_libc -DIS_IN_libpthread +CFLAGS-lowlevellock.c = -DNOT_IN_libc -DIS_IN_libpthread +CFLAGS-pt-__syscall_error.c = -DNOT_IN_libc -DIS_IN_libpthread +ASFLAGS-pt-vfork.S = -DNOT_IN_libc -DIS_IN_libpthread -marm + +ifeq ($(UCLIBC_HAS_STDIO_FUTEXES),y) +CFLAGS-fork.c = -D__USE_STDIO_FUTEXES__ +endif +CFLAGS-OMIT-fork.c = -DNOT_IN_libc -DIS_IN_libpthread +CFLAGS-OMIT-libc-lowlevellock.c = -DNOT_IN_libc -DIS_IN_libpthread +# We always compile it in arm mode because of SAVE_PID macro +# This macro should be alternatively implemented in THUMB +# assembly. +ASFLAGS-vfork.S = -marm diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/arm/bits/atomic.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/arm/bits/atomic.h new file mode 100644 index 00000000..8f63e251 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/arm/bits/atomic.h @@ -0,0 +1,122 @@ +/* Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + + +typedef int8_t atomic8_t; +typedef uint8_t uatomic8_t; +typedef int_fast8_t atomic_fast8_t; +typedef uint_fast8_t uatomic_fast8_t; + +typedef int32_t atomic32_t; +typedef uint32_t uatomic32_t; +typedef int_fast32_t atomic_fast32_t; +typedef uint_fast32_t uatomic_fast32_t; + +typedef intptr_t atomicptr_t; +typedef uintptr_t uatomicptr_t; +typedef intmax_t atomic_max_t; +typedef uintmax_t uatomic_max_t; + +void __arm_link_error (void); + +#ifdef __thumb2__ +#define atomic_full_barrier() \ + __asm__ __volatile__ \ + ("movw\tip, #0x0fa0\n\t" \ + "movt\tip, #0xffff\n\t" \ + "blx\tip" \ + : : : "ip", "lr", "cc", "memory"); +#else +#define atomic_full_barrier() \ + __asm__ __volatile__ \ + ("mov\tip, #0xffff0fff\n\t" \ + "mov\tlr, pc\n\t" \ + "add\tpc, ip, #(0xffff0fa0 - 0xffff0fff)" \ + : : : "ip", "lr", "cc", "memory"); +#endif + +/* Atomic compare and exchange. This sequence relies on the kernel to + provide a compare and exchange operation which is atomic on the + current architecture, either via cleverness on pre-ARMv6 or via + ldrex / strex on ARMv6. */ + +#define __arch_compare_and_exchange_val_8_acq(mem, newval, oldval) \ + ({ __arm_link_error (); oldval; }) + +#define __arch_compare_and_exchange_val_16_acq(mem, newval, oldval) \ + ({ __arm_link_error (); oldval; }) + +/* It doesn't matter what register is used for a_oldval2, but we must + specify one to work around GCC PR rtl-optimization/21223. Otherwise + it may cause a_oldval or a_tmp to be moved to a different register. */ + +#ifdef __thumb2__ +/* Thumb-2 has ldrex/strex. However it does not have barrier instructions, + so we still need to use the kernel helper. */ +#define __arch_compare_and_exchange_val_32_acq(mem, newval, oldval) \ + ({ register __typeof (oldval) a_oldval __asm__ ("r0"); \ + register __typeof (oldval) a_newval __asm__ ("r1") = (newval); \ + register __typeof (mem) a_ptr __asm__ ("r2") = (mem); \ + register __typeof (oldval) a_tmp __asm__ ("r3"); \ + register __typeof (oldval) a_oldval2 __asm__ ("r4") = (oldval); \ + __asm__ __volatile__ \ + ("0:\tldr\t%[tmp],[%[ptr]]\n\t" \ + "cmp\t%[tmp], %[old2]\n\t" \ + "bne\t1f\n\t" \ + "mov\t%[old], %[old2]\n\t" \ + "movw\t%[tmp], #0x0fc0\n\t" \ + "movt\t%[tmp], #0xffff\n\t" \ + "blx\t%[tmp]\n\t" \ + "bcc\t0b\n\t" \ + "mov\t%[tmp], %[old2]\n\t" \ + "1:" \ + : [old] "=&r" (a_oldval), [tmp] "=&r" (a_tmp) \ + : [new] "r" (a_newval), [ptr] "r" (a_ptr), \ + [old2] "r" (a_oldval2) \ + : "ip", "lr", "cc", "memory"); \ + a_tmp; }) +#else +#define __arch_compare_and_exchange_val_32_acq(mem, newval, oldval) \ + ({ register __typeof (oldval) a_oldval __asm__ ("r0"); \ + register __typeof (oldval) a_newval __asm__ ("r1") = (newval); \ + register __typeof (mem) a_ptr __asm__ ("r2") = (mem); \ + register __typeof (oldval) a_tmp __asm__ ("r3"); \ + register __typeof (oldval) a_oldval2 __asm__ ("r4") = (oldval); \ + __asm__ __volatile__ \ + ("0:\tldr\t%[tmp],[%[ptr]]\n\t" \ + "cmp\t%[tmp], %[old2]\n\t" \ + "bne\t1f\n\t" \ + "mov\t%[old], %[old2]\n\t" \ + "mov\t%[tmp], #0xffff0fff\n\t" \ + "mov\tlr, pc\n\t" \ + "add\tpc, %[tmp], #(0xffff0fc0 - 0xffff0fff)\n\t" \ + "bcc\t0b\n\t" \ + "mov\t%[tmp], %[old2]\n\t" \ + "1:" \ + : [old] "=&r" (a_oldval), [tmp] "=&r" (a_tmp) \ + : [new] "r" (a_newval), [ptr] "r" (a_ptr), \ + [old2] "r" (a_oldval2) \ + : "ip", "lr", "cc", "memory"); \ + a_tmp; }) +#endif + +#define __arch_compare_and_exchange_val_64_acq(mem, newval, oldval) \ + ({ __arm_link_error (); oldval; }) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/arm/bits/pthreadtypes.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/arm/bits/pthreadtypes.h new file mode 100644 index 00000000..e1b115c8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/arm/bits/pthreadtypes.h @@ -0,0 +1,181 @@ +/* Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _BITS_PTHREADTYPES_H +#define _BITS_PTHREADTYPES_H 1 + +#include + +#define __SIZEOF_PTHREAD_ATTR_T 36 +#define __SIZEOF_PTHREAD_MUTEX_T 24 +#define __SIZEOF_PTHREAD_MUTEXATTR_T 4 +#define __SIZEOF_PTHREAD_COND_T 48 +#define __SIZEOF_PTHREAD_COND_COMPAT_T 12 +#define __SIZEOF_PTHREAD_CONDATTR_T 4 +#define __SIZEOF_PTHREAD_RWLOCK_T 32 +#define __SIZEOF_PTHREAD_RWLOCKATTR_T 8 +#define __SIZEOF_PTHREAD_BARRIER_T 20 +#define __SIZEOF_PTHREAD_BARRIERATTR_T 4 + + +/* Thread identifiers. The structure of the attribute type is not + exposed on purpose. */ +typedef unsigned long int pthread_t; + + +typedef union +{ + char __size[__SIZEOF_PTHREAD_ATTR_T]; + long int __align; +} pthread_attr_t; + + +typedef struct __pthread_internal_slist +{ + struct __pthread_internal_slist *__next; +} __pthread_slist_t; + + +/* Data structures for mutex handling. The structure of the attribute + type is not exposed on purpose. */ +typedef union +{ + struct __pthread_mutex_s + { + int __lock; + unsigned int __count; + int __owner; + /* KIND must stay at this position in the structure to maintain + binary compatibility. */ + int __kind; + unsigned int __nusers; + __extension__ union + { + int __spins; + __pthread_slist_t __list; + }; + } __data; + char __size[__SIZEOF_PTHREAD_MUTEX_T]; + long int __align; +} pthread_mutex_t; + +typedef union +{ + char __size[__SIZEOF_PTHREAD_MUTEXATTR_T]; + long int __align; +} pthread_mutexattr_t; + + +/* Data structure for conditional variable handling. The structure of + the attribute type is not exposed on purpose. */ +typedef union +{ + struct + { + int __lock; + unsigned int __futex; + __extension__ unsigned long long int __total_seq; + __extension__ unsigned long long int __wakeup_seq; + __extension__ unsigned long long int __woken_seq; + void *__mutex; + unsigned int __nwaiters; + unsigned int __broadcast_seq; + } __data; + char __size[__SIZEOF_PTHREAD_COND_T]; + __extension__ long long int __align; +} pthread_cond_t; + +typedef union +{ + char __size[__SIZEOF_PTHREAD_CONDATTR_T]; + long int __align; +} pthread_condattr_t; + + +/* Keys for thread-specific data */ +typedef unsigned int pthread_key_t; + + +/* Once-only execution */ +typedef int pthread_once_t; + + +#if defined __USE_UNIX98 || defined __USE_XOPEN2K +/* Data structure for read-write lock variable handling. The + structure of the attribute type is not exposed on purpose. */ +typedef union +{ + struct + { + int __lock; + unsigned int __nr_readers; + unsigned int __readers_wakeup; + unsigned int __writer_wakeup; + unsigned int __nr_readers_queued; + unsigned int __nr_writers_queued; +#if __BYTE_ORDER == __BIG_ENDIAN + unsigned char __pad1; + unsigned char __pad2; + unsigned char __shared; + /* FLAGS must stay at this position in the structure to maintain + binary compatibility. */ + unsigned char __flags; +#else + /* FLAGS must stay at this position in the structure to maintain + binary compatibility. */ + unsigned char __flags; + unsigned char __shared; + unsigned char __pad1; + unsigned char __pad2; +#endif + int __writer; + } __data; + char __size[__SIZEOF_PTHREAD_RWLOCK_T]; + long int __align; +} pthread_rwlock_t; + +typedef union +{ + char __size[__SIZEOF_PTHREAD_RWLOCKATTR_T]; + long int __align; +} pthread_rwlockattr_t; +#endif + + +#ifdef __USE_XOPEN2K +/* POSIX spinlock data type. */ +typedef volatile int pthread_spinlock_t; + + +/* POSIX barriers data type. The structure of the type is + deliberately not exposed. */ +typedef union +{ + char __size[__SIZEOF_PTHREAD_BARRIER_T]; + long int __align; +} pthread_barrier_t; + +typedef union +{ + char __size[__SIZEOF_PTHREAD_BARRIERATTR_T]; + int __align; +} pthread_barrierattr_t; +#endif + + +#endif /* bits/pthreadtypes.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/arm/bits/semaphore.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/arm/bits/semaphore.h new file mode 100644 index 00000000..dadfac2a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/arm/bits/semaphore.h @@ -0,0 +1,35 @@ +/* Copyright (C) 2002, 2005, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SEMAPHORE_H +# error "Never use directly; include instead." +#endif + + +#define __SIZEOF_SEM_T 16 + + +/* Value returned if `sem_open' failed. */ +#define SEM_FAILED ((sem_t *) 0) + + +typedef union +{ + char __size[__SIZEOF_SEM_T]; + long int __align; +} sem_t; diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/arm/clone.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/arm/clone.S new file mode 100644 index 00000000..23227eb2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/arm/clone.S @@ -0,0 +1,3 @@ +#define RESET_PID +#include +#include "../../../../../../../libc/sysdeps/linux/arm/clone.S" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/arm/createthread.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/arm/createthread.c new file mode 100644 index 00000000..2d435598 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/arm/createthread.c @@ -0,0 +1,23 @@ +/* Copyright (C) 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Value passed to 'clone' for initialization of the thread register. */ +#define TLS_VALUE (pd + 1) + +/* Get the real implementation. */ +#include diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/arm/fork.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/arm/fork.c new file mode 100644 index 00000000..1c8f4c43 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/arm/fork.c @@ -0,0 +1,31 @@ +/* Copyright (C) 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Phil Blundell , 2005 + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + + +#define ARCH_FORK() \ + INLINE_SYSCALL (clone, 5, \ + CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | SIGCHLD, \ + NULL, NULL, NULL, &THREAD_SELF->tid) + +#include "../fork.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/arm/libc-lowlevellock.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/arm/libc-lowlevellock.c new file mode 100644 index 00000000..b1928228 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/arm/libc-lowlevellock.c @@ -0,0 +1,21 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Paul Mackerras , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* No difference to lowlevellock.c, except we lose a couple of functions. */ +#include "lowlevellock.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/arm/lowlevellock.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/arm/lowlevellock.c new file mode 100644 index 00000000..8c8955e0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/arm/lowlevellock.c @@ -0,0 +1,134 @@ +/* low level locking for pthread library. Generic futex-using version. + Copyright (C) 2003, 2005, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include + +void +__lll_lock_wait_private (int *futex) +{ + do + { + int oldval = atomic_compare_and_exchange_val_acq (futex, 2, 1); + if (oldval != 0) + lll_futex_wait (futex, 2, LLL_PRIVATE); + } + while (atomic_compare_and_exchange_bool_acq (futex, 2, 0) != 0); +} + + +/* These functions don't get included in libc.so */ +#ifdef IS_IN_libpthread +void +__lll_lock_wait (int *futex, int private) +{ + do + { + int oldval = atomic_compare_and_exchange_val_acq (futex, 2, 1); + if (oldval != 0) + lll_futex_wait (futex, 2, private); + } + while (atomic_compare_and_exchange_bool_acq (futex, 2, 0) != 0); +} + + +int +__lll_timedlock_wait (int *futex, const struct timespec *abstime, int private) +{ + struct timespec rt; + + /* Reject invalid timeouts. */ + if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) + return EINVAL; + + /* Upgrade the lock. */ + if (atomic_exchange_acq (futex, 2) == 0) + return 0; + + do + { + struct timeval tv; + + /* Get the current time. */ + (void) gettimeofday (&tv, NULL); + + /* Compute relative timeout. */ + rt.tv_sec = abstime->tv_sec - tv.tv_sec; + rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000; + if (rt.tv_nsec < 0) + { + rt.tv_nsec += 1000000000; + --rt.tv_sec; + } + + /* Already timed out? */ + if (rt.tv_sec < 0) + return ETIMEDOUT; + + // XYZ: Lost the lock to check whether it was private. + lll_futex_timed_wait (futex, 2, &rt, private); + } + while (atomic_compare_and_exchange_bool_acq (futex, 2, 0) != 0); + + return 0; +} + + +int +__lll_timedwait_tid (int *tidp, const struct timespec *abstime) +{ + int tid; + + if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) + return EINVAL; + + /* Repeat until thread terminated. */ + while ((tid = *tidp) != 0) + { + struct timeval tv; + struct timespec rt; + + /* Get the current time. */ + (void) gettimeofday (&tv, NULL); + + /* Compute relative timeout. */ + rt.tv_sec = abstime->tv_sec - tv.tv_sec; + rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000; + if (rt.tv_nsec < 0) + { + rt.tv_nsec += 1000000000; + --rt.tv_sec; + } + + /* Already timed out? */ + if (rt.tv_sec < 0) + return ETIMEDOUT; + + /* Wait until thread terminates. */ + // XYZ: Lost the lock to check whether it was private. + if (lll_futex_timed_wait (tidp, tid, &rt, LLL_SHARED) == -ETIMEDOUT) + return ETIMEDOUT; + } + + return 0; +} +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/arm/lowlevellock.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/arm/lowlevellock.h new file mode 100644 index 00000000..4c7d08c9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/arm/lowlevellock.h @@ -0,0 +1,282 @@ +/* Copyright (C) 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _LOWLEVELLOCK_H +#define _LOWLEVELLOCK_H 1 + +#include +#include +#include +#include +#include +#include + +#define FUTEX_WAIT 0 +#define FUTEX_WAKE 1 +#define FUTEX_REQUEUE 3 +#define FUTEX_CMP_REQUEUE 4 +#define FUTEX_WAKE_OP 5 +#define FUTEX_OP_CLEAR_WAKE_IF_GT_ONE ((4 << 24) | 1) +#define FUTEX_LOCK_PI 6 +#define FUTEX_UNLOCK_PI 7 +#define FUTEX_TRYLOCK_PI 8 +#define FUTEX_WAIT_BITSET 9 +#define FUTEX_WAKE_BITSET 10 +#define FUTEX_PRIVATE_FLAG 128 +#define FUTEX_CLOCK_REALTIME 256 + +#define FUTEX_BITSET_MATCH_ANY 0xffffffff + +/* Values for 'private' parameter of locking macros. Yes, the + definition seems to be backwards. But it is not. The bit will be + reversed before passing to the system call. */ +#define LLL_PRIVATE 0 +#define LLL_SHARED FUTEX_PRIVATE_FLAG + + +#if !defined NOT_IN_libc || defined IS_IN_rtld +/* In libc.so or ld.so all futexes are private. */ +# ifdef __ASSUME_PRIVATE_FUTEX +# define __lll_private_flag(fl, private) \ + ((fl) | FUTEX_PRIVATE_FLAG) +# else +# define __lll_private_flag(fl, private) \ + ((fl) | THREAD_GETMEM (THREAD_SELF, header.private_futex)) +# endif +#else +# ifdef __ASSUME_PRIVATE_FUTEX +# define __lll_private_flag(fl, private) \ + (((fl) | FUTEX_PRIVATE_FLAG) ^ (private)) +# else +# define __lll_private_flag(fl, private) \ + (__builtin_constant_p (private) \ + ? ((private) == 0 \ + ? ((fl) | THREAD_GETMEM (THREAD_SELF, header.private_futex)) \ + : (fl)) \ + : ((fl) | (((private) ^ FUTEX_PRIVATE_FLAG) \ + & THREAD_GETMEM (THREAD_SELF, header.private_futex)))) +# endif +#endif + + +#define lll_futex_wait(futexp, val, private) \ + lll_futex_timed_wait(futexp, val, NULL, private) + +#define lll_futex_timed_wait(futexp, val, timespec, private) \ + ({ \ + INTERNAL_SYSCALL_DECL (__err); \ + long int __ret; \ + __ret = INTERNAL_SYSCALL (futex, __err, 4, (futexp), \ + __lll_private_flag (FUTEX_WAIT, private), \ + (val), (timespec)); \ + __ret; \ + }) + +#define lll_futex_wake(futexp, nr, private) \ + ({ \ + INTERNAL_SYSCALL_DECL (__err); \ + long int __ret; \ + __ret = INTERNAL_SYSCALL (futex, __err, 4, (futexp), \ + __lll_private_flag (FUTEX_WAKE, private), \ + (nr), 0); \ + __ret; \ + }) + +#define lll_robust_dead(futexv, private) \ + do \ + { \ + int *__futexp = &(futexv); \ + atomic_or (__futexp, FUTEX_OWNER_DIED); \ + lll_futex_wake (__futexp, 1, private); \ + } \ + while (0) + +/* Returns non-zero if error happened, zero if success. */ +#define lll_futex_requeue(futexp, nr_wake, nr_move, mutex, val, private) \ + ({ \ + INTERNAL_SYSCALL_DECL (__err); \ + long int __ret; \ + __ret = INTERNAL_SYSCALL (futex, __err, 6, (futexp), \ + __lll_private_flag (FUTEX_CMP_REQUEUE, private),\ + (nr_wake), (nr_move), (mutex), (val)); \ + INTERNAL_SYSCALL_ERROR_P (__ret, __err); \ + }) + + +/* Returns non-zero if error happened, zero if success. */ +#define lll_futex_wake_unlock(futexp, nr_wake, nr_wake2, futexp2, private) \ + ({ \ + INTERNAL_SYSCALL_DECL (__err); \ + long int __ret; \ + __ret = INTERNAL_SYSCALL (futex, __err, 6, (futexp), \ + __lll_private_flag (FUTEX_WAKE_OP, private), \ + (nr_wake), (nr_wake2), (futexp2), \ + FUTEX_OP_CLEAR_WAKE_IF_GT_ONE); \ + INTERNAL_SYSCALL_ERROR_P (__ret, __err); \ + }) + + +#define lll_trylock(lock) \ + atomic_compare_and_exchange_val_acq(&(lock), 1, 0) + +#define lll_cond_trylock(lock) \ + atomic_compare_and_exchange_val_acq(&(lock), 2, 0) + +#define __lll_robust_trylock(futex, id) \ + (atomic_compare_and_exchange_val_acq (futex, id, 0) != 0) +#define lll_robust_trylock(lock, id) \ + __lll_robust_trylock (&(lock), id) + +extern void __lll_lock_wait_private (int *futex) attribute_hidden; +extern void __lll_lock_wait (int *futex, int private) attribute_hidden; +extern int __lll_robust_lock_wait (int *futex, int private) attribute_hidden; + +#define __lll_lock(futex, private) \ + ((void) ({ \ + int *__futex = (futex); \ + if (__builtin_expect (atomic_compare_and_exchange_val_acq (__futex, \ + 1, 0), 0)) \ + { \ + if (__builtin_constant_p (private) && (private) == LLL_PRIVATE) \ + __lll_lock_wait_private (__futex); \ + else \ + __lll_lock_wait (__futex, private); \ + } \ + })) +#define lll_lock(futex, private) __lll_lock (&(futex), private) + + +#define __lll_robust_lock(futex, id, private) \ + ({ \ + int *__futex = (futex); \ + int __val = 0; \ + \ + if (__builtin_expect (atomic_compare_and_exchange_bool_acq (__futex, id, \ + 0), 0)) \ + __val = __lll_robust_lock_wait (__futex, private); \ + __val; \ + }) +#define lll_robust_lock(futex, id, private) \ + __lll_robust_lock (&(futex), id, private) + + +#define __lll_cond_lock(futex, private) \ + ((void) ({ \ + int *__futex = (futex); \ + if (__builtin_expect (atomic_exchange_acq (__futex, 2), 0)) \ + __lll_lock_wait (__futex, private); \ + })) +#define lll_cond_lock(futex, private) __lll_cond_lock (&(futex), private) + + +#define lll_robust_cond_lock(futex, id, private) \ + __lll_robust_lock (&(futex), (id) | FUTEX_WAITERS, private) + + +extern int __lll_timedlock_wait (int *futex, const struct timespec *, + int private) attribute_hidden; +extern int __lll_robust_timedlock_wait (int *futex, const struct timespec *, + int private) attribute_hidden; + +#define __lll_timedlock(futex, abstime, private) \ + ({ \ + int *__futex = (futex); \ + int __val = 0; \ + \ + if (__builtin_expect (atomic_exchange_acq (__futex, 1), 0)) \ + __val = __lll_timedlock_wait (__futex, abstime, private); \ + __val; \ + }) +#define lll_timedlock(futex, abstime, private) \ + __lll_timedlock (&(futex), abstime, private) + + +#define __lll_robust_timedlock(futex, abstime, id, private) \ + ({ \ + int *__futex = (futex); \ + int __val = 0; \ + \ + if (__builtin_expect (atomic_compare_and_exchange_bool_acq (__futex, id, \ + 0), 0)) \ + __val = __lll_robust_timedlock_wait (__futex, abstime, private); \ + __val; \ + }) +#define lll_robust_timedlock(futex, abstime, id, private) \ + __lll_robust_timedlock (&(futex), abstime, id, private) + + +#define __lll_unlock(futex, private) \ + (void) \ + ({ int *__futex = (futex); \ + int __oldval = atomic_exchange_rel (__futex, 0); \ + if (__builtin_expect (__oldval > 1, 0)) \ + lll_futex_wake (__futex, 1, private); \ + }) +#define lll_unlock(futex, private) __lll_unlock(&(futex), private) + + +#define __lll_robust_unlock(futex, private) \ + (void) \ + ({ int *__futex = (futex); \ + int __oldval = atomic_exchange_rel (__futex, 0); \ + if (__builtin_expect (__oldval & FUTEX_WAITERS, 0)) \ + lll_futex_wake (__futex, 1, private); \ + }) +#define lll_robust_unlock(futex, private) \ + __lll_robust_unlock(&(futex), private) + + +#define lll_islocked(futex) \ + (futex != 0) + + +/* Our internal lock implementation is identical to the binary-compatible + mutex implementation. */ + +/* Initializers for lock. */ +#define LLL_LOCK_INITIALIZER (0) +#define LLL_LOCK_INITIALIZER_LOCKED (1) + +/* The states of a lock are: + 0 - untaken + 1 - taken by one user + >1 - taken by more users */ + +/* The kernel notifies a process which uses CLONE_CLEARTID via futex + wakeup when the clone terminates. The memory location contains the + thread ID while the clone is running and is reset to zero + afterwards. */ +#define lll_wait_tid(tid) \ + do { \ + __typeof (tid) __tid; \ + while ((__tid = (tid)) != 0) \ + lll_futex_wait (&(tid), __tid, LLL_SHARED);\ + } while (0) + +extern int __lll_timedwait_tid (int *, const struct timespec *) + attribute_hidden; + +#define lll_timedwait_tid(tid, abstime) \ + ({ \ + int __res = 0; \ + if ((tid) != 0) \ + __res = __lll_timedwait_tid (&(tid), (abstime)); \ + __res; \ + }) + +#endif /* lowlevellock.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/arm/nptl-aeabi_unwind_cpp_pr1.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/arm/nptl-aeabi_unwind_cpp_pr1.c new file mode 100644 index 00000000..7b835224 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/arm/nptl-aeabi_unwind_cpp_pr1.c @@ -0,0 +1 @@ +#include diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/arm/pt-__syscall_error.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/arm/pt-__syscall_error.c new file mode 100644 index 00000000..5a48a9b2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/arm/pt-__syscall_error.c @@ -0,0 +1 @@ +#include <../../../../../../../libc/sysdeps/linux/arm/__syscall_error.c> diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/arm/pt-__syscall_rt_sigaction.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/arm/pt-__syscall_rt_sigaction.c new file mode 100644 index 00000000..50137c84 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/arm/pt-__syscall_rt_sigaction.c @@ -0,0 +1 @@ +#include <../../../../../../../libc/sysdeps/linux/common/__syscall_rt_sigaction.c> diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/arm/pt-gettimeofday.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/arm/pt-gettimeofday.c new file mode 100644 index 00000000..08710f1c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/arm/pt-gettimeofday.c @@ -0,0 +1,5 @@ +#include +#include + +int gettimeofday (struct timeval *, struct timezone *) attribute_hidden; +_syscall2(int, gettimeofday, struct timeval *, tv, struct timezone *, tz); diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/arm/pt-vfork.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/arm/pt-vfork.S new file mode 100644 index 00000000..9764e9ee --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/arm/pt-vfork.S @@ -0,0 +1,38 @@ +/* Copyright (C) 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +/* Save the PID value. */ +#define SAVE_PID \ + str lr, [sp, #-4]!; /* Save LR. */ \ + mov r0, #0xffff0fff; /* Point to the high page. */ \ + mov lr, pc; /* Save our return address. */ \ + sub pc, r0, #31; /* Jump to the TLS entry. */ \ + ldr lr, [sp], #4; /* Restore LR. */ \ + mov r2, r0; /* Save the TLS addr in r2. */ \ + ldr r3, [r2, #PID_OFFSET]; /* Load the saved PID. */ \ + rsb r0, r3, #0; /* Negate it. */ \ + str r0, [r2, #PID_OFFSET] /* Store the temporary PID. */ + +/* Restore the old PID value in the parent. */ +#define RESTORE_PID \ + cmp r0, #0; /* If we are the parent... */ \ + strne r3, [r2, #PID_OFFSET] /* ... restore the saved PID. */ + +#INCLUDE <../../../../../../../LIBC/SYSDEPS/LINUX/ARM/VFORK.S> diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/arm/pthread_once.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/arm/pthread_once.c new file mode 100644 index 00000000..e977a7d0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/arm/pthread_once.c @@ -0,0 +1,100 @@ +/* Copyright (C) 2004, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "pthreadP.h" +#include + +unsigned long int __fork_generation attribute_hidden; + +static void +clear_once_control (void *arg) +{ + pthread_once_t *once_control = (pthread_once_t *) arg; + + *once_control = 0; + lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE); +} + +int +attribute_protected +__pthread_once (pthread_once_t *once_control, void (*init_routine) (void)) +{ + for (;;) + { + int oldval; + int newval; + + /* Pseudo code: + newval = __fork_generation | 1; + oldval = *once_control; + if ((oldval & 2) == 0) + *once_control = newval; + Do this atomically. + */ + do + { + newval = __fork_generation | 1; + oldval = *once_control; + if (oldval & 2) + break; + } while (atomic_compare_and_exchange_val_acq (once_control, newval, oldval) != oldval); + + /* Check if the initializer has already been done. */ + if ((oldval & 2) != 0) + return 0; + + /* Check if another thread already runs the initializer. */ + if ((oldval & 1) == 0) + break; + + /* Check whether the initializer execution was interrupted by a fork. */ + if (oldval != newval) + break; + + /* Same generation, some other thread was faster. Wait. */ + lll_futex_wait (once_control, oldval, LLL_PRIVATE); + } + + /* This thread is the first here. Do the initialization. + Register a cleanup handler so that in case the thread gets + interrupted the initialization can be restarted. */ + pthread_cleanup_push (clear_once_control, once_control); + + init_routine (); + + pthread_cleanup_pop (0); + + /* Say that the initialisation is done. */ + *once_control = __fork_generation | 2; + + /* Wake up all other threads. */ + lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE); + + return 0; +} +weak_alias (__pthread_once, pthread_once) +strong_alias (__pthread_once, __pthread_once_internal) + +#if defined(__USING_SJLJ_EXCEPTIONS__) && !defined(__PIC__) +/* When statically linked, if pthread_create is used, this file + will be brought in. The exception handling code in GCC assumes + that if pthread_create is available, so are these. */ +const void *include_pthread_getspecific attribute_hidden = pthread_getspecific; +const void *include_pthread_setspecific attribute_hidden = pthread_setspecific; +const void *include_pthread_key_create attribute_hidden = pthread_key_create; +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/arm/sysdep-cancel.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/arm/sysdep-cancel.h new file mode 100644 index 00000000..7ac9ca1e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/arm/sysdep-cancel.h @@ -0,0 +1,254 @@ +/* Copyright (C) 2003, 2004, 2005, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#ifndef __ASSEMBLER__ +# include +#endif + +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + +/* NOTE: We do mark syscalls with unwind annotations, for the benefit of + cancellation; but they're really only accurate at the point of the + syscall. The ARM unwind directives are not rich enough without adding + a custom personality function. */ + +# undef PSEUDO +# define PSEUDO(name, syscall_name, args) \ + .section ".text"; \ + PSEUDO_PROLOGUE; \ + .type __##syscall_name##_nocancel,%function; \ + .globl __##syscall_name##_nocancel; \ + __##syscall_name##_nocancel: \ + .cfi_sections .debug_frame; \ + cfi_startproc; \ + DO_CALL (syscall_name, args); \ + PSEUDO_RET; \ + cfi_endproc; \ + .size __##syscall_name##_nocancel,.-__##syscall_name##_nocancel; \ + ENTRY (name); \ + SINGLE_THREAD_P; \ + DOARGS_##args; \ + bne .Lpseudo_cancel; \ + cfi_remember_state; \ + DO_CALL (syscall_name, 0); \ + UNDOARGS_##args; \ + cmn r0, $4096; \ + PSEUDO_RET; \ + cfi_restore_state; \ + .Lpseudo_cancel: \ + .fnstart; \ + DOCARGS_##args; /* save syscall args etc. around CENABLE. */ \ + CENABLE; \ + mov ip, r0; /* put mask in safe place. */ \ + UNDOCARGS_##args; /* restore syscall args. */ \ + ldr r7, =SYS_ify (syscall_name); \ + swi 0x0; /* do the call. */ \ + .fnend; /* Past here we can't easily unwind. */ \ + mov r7, r0; /* save syscall return value. */ \ + mov r0, ip; /* get mask back. */ \ + CDISABLE; \ + mov r0, r7; /* retrieve return value. */ \ + RESTORE_LR_##args; \ + UNDOARGS_##args; \ + cmn r0, $4096 + +/* DOARGS pushes four bytes on the stack for five arguments, eight bytes for + six arguments, and nothing for fewer. In order to preserve doubleword + alignment, sometimes we must save an extra register. */ + +# define RESTART_UNWIND \ + .fnend; \ + .fnstart; \ + .save {r7, lr} + +# define DOCARGS_0 \ + stmfd sp!, {r7, lr}; \ + cfi_adjust_cfa_offset (8); \ + cfi_rel_offset (r7, 0); \ + cfi_rel_offset (lr, 4); \ + .save {r7, lr} +# define UNDOCARGS_0 +# define RESTORE_LR_0 \ + ldmfd sp!, {r7, lr}; \ + cfi_adjust_cfa_offset (-8); \ + cfi_restore (r7); \ + cfi_restore (lr) + +# define DOCARGS_1 \ + stmfd sp!, {r0, r1, r7, lr}; \ + cfi_adjust_cfa_offset (16); \ + cfi_rel_offset (r7, 8); \ + cfi_rel_offset (lr, 12); \ + .save {r7, lr}; \ + .pad #8 +# define UNDOCARGS_1 \ + ldr r0, [sp], #8; \ + cfi_adjust_cfa_offset (-8); \ + RESTART_UNWIND +# define RESTORE_LR_1 \ + RESTORE_LR_0 + +# define DOCARGS_2 \ + stmfd sp!, {r0, r1, r7, lr}; \ + cfi_adjust_cfa_offset (16); \ + cfi_rel_offset (r7, 8); \ + cfi_rel_offset (lr, 12); \ + .save {r7, lr}; \ + .pad #8 +# define UNDOCARGS_2 \ + ldmfd sp!, {r0, r1}; \ + cfi_adjust_cfa_offset (-8); \ + RESTART_UNWIND +# define RESTORE_LR_2 \ + RESTORE_LR_0 + +# define DOCARGS_3 \ + stmfd sp!, {r0, r1, r2, r3, r7, lr}; \ + cfi_adjust_cfa_offset (24); \ + cfi_rel_offset (r7, 16); \ + cfi_rel_offset (lr, 20); \ + .save {r7, lr}; \ + .pad #16 +# define UNDOCARGS_3 \ + ldmfd sp!, {r0, r1, r2, r3}; \ + cfi_adjust_cfa_offset (-16); \ + RESTART_UNWIND +# define RESTORE_LR_3 \ + RESTORE_LR_0 + +# define DOCARGS_4 \ + stmfd sp!, {r0, r1, r2, r3, r7, lr}; \ + cfi_adjust_cfa_offset (24); \ + cfi_rel_offset (r7, 16); \ + cfi_rel_offset (lr, 20); \ + .save {r7, lr}; \ + .pad #16 +# define UNDOCARGS_4 \ + ldmfd sp!, {r0, r1, r2, r3}; \ + cfi_adjust_cfa_offset (-16); \ + RESTART_UNWIND +# define RESTORE_LR_4 \ + RESTORE_LR_0 + +/* r4 is only stmfd'ed for correct stack alignment. */ +# define DOCARGS_5 \ + .save {r4}; \ + stmfd sp!, {r0, r1, r2, r3, r4, r7, lr}; \ + cfi_adjust_cfa_offset (28); \ + cfi_rel_offset (r7, 20); \ + cfi_rel_offset (lr, 24); \ + .save {r7, lr}; \ + .pad #20 +# define UNDOCARGS_5 \ + ldmfd sp!, {r0, r1, r2, r3}; \ + cfi_adjust_cfa_offset (-16); \ + .fnend; \ + .fnstart; \ + .save {r4}; \ + .save {r7, lr}; \ + .pad #4 +# define RESTORE_LR_5 \ + ldmfd sp!, {r4, r7, lr}; \ + cfi_adjust_cfa_offset (-12); \ + /* r4 will be marked as restored later. */ \ + cfi_restore (r7); \ + cfi_restore (lr) + +# define DOCARGS_6 \ + .save {r4, r5}; \ + stmfd sp!, {r0, r1, r2, r3, r7, lr}; \ + cfi_adjust_cfa_offset (24); \ + cfi_rel_offset (r7, 16); \ + cfi_rel_offset (lr, 20); \ + .save {r7, lr}; \ + .pad #16 +# define UNDOCARGS_6 \ + ldmfd sp!, {r0, r1, r2, r3}; \ + cfi_adjust_cfa_offset (-16); \ + .fnend; \ + .fnstart; \ + .save {r4, r5}; \ + .save {r7, lr} +# define RESTORE_LR_6 \ + RESTORE_LR_0 + +# ifdef IS_IN_libpthread +# define CENABLE bl PLTJMP(__pthread_enable_asynccancel) +# define CDISABLE bl PLTJMP(__pthread_disable_asynccancel) +# define __local_multiple_threads __pthread_multiple_threads +# elif !defined NOT_IN_libc +# define CENABLE bl PLTJMP(__libc_enable_asynccancel) +# define CDISABLE bl PLTJMP(__libc_disable_asynccancel) +# define __local_multiple_threads __libc_multiple_threads +# elif defined IS_IN_librt +# define CENABLE bl PLTJMP(__librt_enable_asynccancel) +# define CDISABLE bl PLTJMP(__librt_disable_asynccancel) +# else +# error Unsupported library +# endif + +# if defined IS_IN_libpthread || !defined NOT_IN_libc +# ifndef __ASSEMBLER__ +extern int __local_multiple_threads attribute_hidden; +# define SINGLE_THREAD_P __builtin_expect (__local_multiple_threads == 0, 1) +# else +# define SINGLE_THREAD_P \ + ldr ip, 1b; \ +2: \ + ldr ip, [pc, ip]; \ + teq ip, #0; +# define PSEUDO_PROLOGUE \ + 1: .word __local_multiple_threads - 2f - 8; +# endif +# else +/* There is no __local_multiple_threads for librt, so use the TCB. */ +# ifndef __ASSEMBLER__ +# define SINGLE_THREAD_P \ + __builtin_expect (THREAD_GETMEM (THREAD_SELF, \ + header.multiple_threads) == 0, 1) +# else +# define PSEUDO_PROLOGUE +# define SINGLE_THREAD_P \ + stmfd sp!, {r0, lr}; \ + cfi_adjust_cfa_offset (8); \ + cfi_rel_offset (lr, 4); \ + bl __aeabi_read_tp; \ + ldr ip, [r0, #MULTIPLE_THREADS_OFFSET]; \ + ldmfd sp!, {r0, lr}; \ + cfi_adjust_cfa_offset (-8); \ + cfi_restore (lr); \ + teq ip, #0 +# define SINGLE_THREAD_P_PIC(x) SINGLE_THREAD_P +# endif +# endif + +#elif !defined __ASSEMBLER__ + +/* For rtld, et cetera. */ +# define SINGLE_THREAD_P 1 +# define NO_CANCELLATION 1 + +#endif + +#ifndef __ASSEMBLER__ +# define RTLD_SINGLE_THREAD_P \ + __builtin_expect (THREAD_GETMEM (THREAD_SELF, \ + header.multiple_threads) == 0, 1) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/arm/unwind-forcedunwind.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/arm/unwind-forcedunwind.c new file mode 100644 index 00000000..88e12059 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/arm/unwind-forcedunwind.c @@ -0,0 +1,177 @@ +/* Copyright (C) 2003, 2005, 2007, 2009, 2010 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include + +#define __libc_dlopen(x) dlopen(x, (RTLD_LOCAL | RTLD_LAZY)) +#define __libc_dlsym dlsym +#define __libc_dlclose dlclose +#define __libc_fatal(x) {/*write(STDERR_FILENO, x, strlen(x));*/ abort();} + +static void *libgcc_s_handle; +static void (*libgcc_s_resume) (struct _Unwind_Exception *exc); +static _Unwind_Reason_Code (*libgcc_s_personality) + (_Unwind_State, struct _Unwind_Exception *, struct _Unwind_Context *); +static _Unwind_Reason_Code (*libgcc_s_forcedunwind) + (struct _Unwind_Exception *, _Unwind_Stop_Fn, void *); +static _Unwind_Word (*libgcc_s_getcfa) (struct _Unwind_Context *); + +void +__attribute_noinline__ +pthread_cancel_init (void) +{ + void *resume, *personality, *forcedunwind, *getcfa; + void *handle; + + if (__builtin_expect (libgcc_s_handle != NULL, 1)) + { + /* Force gcc to reload all values. */ + __asm__ __volatile__ ("" ::: "memory"); + return; + } + + handle = __libc_dlopen ("libgcc_s.so.1"); + + if (handle == NULL + || (resume = __libc_dlsym (handle, "_Unwind_Resume")) == NULL + || (personality = __libc_dlsym (handle, "__gcc_personality_v0")) == NULL + || (forcedunwind = __libc_dlsym (handle, "_Unwind_ForcedUnwind")) + == NULL + || (getcfa = __libc_dlsym (handle, "_Unwind_GetCFA")) == NULL +#ifdef ARCH_CANCEL_INIT + || ARCH_CANCEL_INIT (handle) +#endif + ) + __libc_fatal ("libgcc_s.so.1 must be installed for pthread_cancel to work\n"); + + libgcc_s_resume = resume; + libgcc_s_personality = personality; + libgcc_s_forcedunwind = forcedunwind; + libgcc_s_getcfa = getcfa; + /* Make sure libgcc_s_getcfa is written last. Otherwise, + pthread_cancel_init might return early even when the pointer the + caller is interested in is not initialized yet. */ + atomic_write_barrier (); + libgcc_s_handle = handle; +} + +void +__libc_freeres_fn_section +__unwind_freeres (void) +{ + void *handle = libgcc_s_handle; + if (handle != NULL) + { + libgcc_s_handle = NULL; + __libc_dlclose (handle); + } +} + +#ifdef __thumb__ +void +_Unwind_Resume (struct _Unwind_Exception *exc) +{ + if (__builtin_expect (libgcc_s_resume == NULL, 0)) + pthread_cancel_init (); + + libgcc_s_resume (exc); +} + +#else +/* It's vitally important that _Unwind_Resume not have a stack frame; the + ARM unwinder relies on register state at entrance. So we write this in + assembly. */ + +__asm__ ( +" .globl _Unwind_Resume\n" +" .type _Unwind_Resume, %function\n" +"_Unwind_Resume:\n" +" .cfi_sections .debug_frame\n" +" " CFI_STARTPROC "\n" +" stmfd sp!, {r4, r5, r6, lr}\n" +" " CFI_ADJUST_CFA_OFFSET (16)" \n" +" " CFI_REL_OFFSET (r4, 0) "\n" +" " CFI_REL_OFFSET (r5, 4) "\n" +" " CFI_REL_OFFSET (r6, 8) "\n" +" " CFI_REL_OFFSET (lr, 12) "\n" +" " CFI_REMEMBER_STATE "\n" +" ldr r4, 1f\n" +" ldr r5, 2f\n" +"3: add r4, pc, r4\n" +" ldr r3, [r4, r5]\n" +" mov r6, r0\n" +" cmp r3, #0\n" +" beq 4f\n" +"5: mov r0, r6\n" +" ldmfd sp!, {r4, r5, r6, lr}\n" +" " CFI_ADJUST_CFA_OFFSET (-16) "\n" +" " CFI_RESTORE (r4) "\n" +" " CFI_RESTORE (r5) "\n" +" " CFI_RESTORE (r6) "\n" +" " CFI_RESTORE (lr) "\n" +" bx r3\n" +" " CFI_RESTORE_STATE "\n" +"4: bl pthread_cancel_init\n" +" ldr r3, [r4, r5]\n" +" b 5b\n" +" " CFI_ENDPROC "\n" +" .align 2\n" +#ifdef __thumb2__ +"1: .word _GLOBAL_OFFSET_TABLE_ - 3b - 4\n" +#else +"1: .word _GLOBAL_OFFSET_TABLE_ - 3b - 8\n" +#endif +"2: .word libgcc_s_resume(GOTOFF)\n" +" .size _Unwind_Resume, .-_Unwind_Resume\n" +); + +#endif + +_Unwind_Reason_Code +__gcc_personality_v0 (_Unwind_State state, + struct _Unwind_Exception *ue_header, + struct _Unwind_Context *context) +{ + if (__builtin_expect (libgcc_s_personality == NULL, 0)) + pthread_cancel_init (); + + return libgcc_s_personality (state, ue_header, context); +} + +_Unwind_Reason_Code +_Unwind_ForcedUnwind (struct _Unwind_Exception *exc, _Unwind_Stop_Fn stop, + void *stop_argument) +{ + if (__builtin_expect (libgcc_s_forcedunwind == NULL, 0)) + pthread_cancel_init (); + + return libgcc_s_forcedunwind (exc, stop, stop_argument); +} + +_Unwind_Word +_Unwind_GetCFA (struct _Unwind_Context *context) +{ + if (__builtin_expect (libgcc_s_getcfa == NULL, 0)) + pthread_cancel_init (); + + return libgcc_s_getcfa (context); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/arm/unwind-resume.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/arm/unwind-resume.c new file mode 100644 index 00000000..e35374d3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/arm/unwind-resume.c @@ -0,0 +1,116 @@ +/* Copyright (C) 2003, 2005, 2010 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include + +#define __libc_dlopen(x) dlopen(x, (RTLD_LOCAL | RTLD_LAZY)) +#define __libc_dlsym dlsym +#define __libc_dlclose dlclose +#define __libc_fatal(x) {/*write(STDERR_FILENO, x, strlen(x));*/ abort();} + +static void (*libgcc_s_resume) (struct _Unwind_Exception *exc); +static _Unwind_Reason_Code (*libgcc_s_personality) + (_Unwind_State, struct _Unwind_Exception *, struct _Unwind_Context *); + +static void init (void) __attribute_used__; + +static void +init (void) +{ + void *resume, *personality; + void *handle; + + handle = __libc_dlopen ("libgcc_s.so.1"); + + if (handle == NULL + || (resume = __libc_dlsym (handle, "_Unwind_Resume")) == NULL + || (personality = __libc_dlsym (handle, "__gcc_personality_v0")) == NULL) + __libc_fatal ("libgcc_s.so.1 must be installed for pthread_cancel to work\n"); + + libgcc_s_resume = resume; + libgcc_s_personality = personality; +} +#ifdef __thumb__ +void +_Unwind_Resume (struct _Unwind_Exception *exc) +{ + if (__builtin_expect (libgcc_s_resume == NULL, 0)) + init (); + libgcc_s_resume (exc); +} +#else +/* It's vitally important that _Unwind_Resume not have a stack frame; the + ARM unwinder relies on register state at entrance. So we write this in + assembly. */ + +__asm__ ( +" .globl _Unwind_Resume\n" +" .type _Unwind_Resume, %function\n" +"_Unwind_Resume:\n" +" .cfi_sections .debug_frame\n" +" " CFI_STARTPROC "\n" +" stmfd sp!, {r4, r5, r6, lr}\n" +" " CFI_ADJUST_CFA_OFFSET (16)" \n" +" " CFI_REL_OFFSET (r4, 0) "\n" +" " CFI_REL_OFFSET (r5, 4) "\n" +" " CFI_REL_OFFSET (r6, 8) "\n" +" " CFI_REL_OFFSET (lr, 12) "\n" +" " CFI_REMEMBER_STATE "\n" +" ldr r4, 1f\n" +" ldr r5, 2f\n" +"3: add r4, pc, r4\n" +" ldr r3, [r4, r5]\n" +" mov r6, r0\n" +" cmp r3, #0\n" +" beq 4f\n" +"5: mov r0, r6\n" +" ldmfd sp!, {r4, r5, r6, lr}\n" +" " CFI_ADJUST_CFA_OFFSET (-16) "\n" +" " CFI_RESTORE (r4) "\n" +" " CFI_RESTORE (r5) "\n" +" " CFI_RESTORE (r6) "\n" +" " CFI_RESTORE (lr) "\n" +" bx r3\n" +" " CFI_RESTORE_STATE "\n" +"4: bl init\n" +" ldr r3, [r4, r5]\n" +" b 5b\n" +" " CFI_ENDPROC "\n" +" .align 2\n" +#ifdef __thumb2__ +"1: .word _GLOBAL_OFFSET_TABLE_ - 3b - 4\n" +#else +"1: .word _GLOBAL_OFFSET_TABLE_ - 3b - 8\n" +#endif +"2: .word libgcc_s_resume(GOTOFF)\n" +" .size _Unwind_Resume, .-_Unwind_Resume\n" +); +#endif + +_Unwind_Reason_Code +__gcc_personality_v0 (_Unwind_State state, + struct _Unwind_Exception *ue_header, + struct _Unwind_Context *context) +{ + if (__builtin_expect (libgcc_s_personality == NULL, 0)) + init (); + return libgcc_s_personality (state, ue_header, context); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/arm/unwind.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/arm/unwind.h new file mode 100644 index 00000000..eeb9cf8b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/arm/unwind.h @@ -0,0 +1,279 @@ +/* Header file for the ARM EABI unwinder + Copyright (C) 2003, 2004, 2005, 2009 Free Software Foundation, Inc. + Contributed by Paul Brook + + This file is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2, or (at your option) any + later version. + + In addition to the permissions in the GNU General Public License, the + Free Software Foundation gives you unlimited permission to link the + compiled version of this file into combinations with other programs, + and to distribute those combinations without any restriction coming + from the use of this file. (The General Public License restrictions + do apply in other respects; for example, they cover modification of + the file, and distribution when not linked into a combine + executable.) + + This file is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. */ + +/* Language-independent unwinder header public defines. This contains both + ABI defined objects, and GNU support routines. */ + +#ifndef UNWIND_ARM_H +#define UNWIND_ARM_H + +#define __ARM_EABI_UNWINDER__ 1 + +#ifdef __cplusplus +extern "C" { +#endif + typedef unsigned _Unwind_Word __attribute__((__mode__(__word__))); + typedef signed _Unwind_Sword __attribute__((__mode__(__word__))); + typedef unsigned _Unwind_Ptr __attribute__((__mode__(__pointer__))); + typedef unsigned _Unwind_Internal_Ptr __attribute__((__mode__(__pointer__))); + typedef _Unwind_Word _uw; + typedef unsigned _uw64 __attribute__((mode(__DI__))); + typedef unsigned _uw16 __attribute__((mode(__HI__))); + typedef unsigned _uw8 __attribute__((mode(__QI__))); + + typedef enum + { + _URC_OK = 0, /* operation completed successfully */ + _URC_FOREIGN_EXCEPTION_CAUGHT = 1, + _URC_END_OF_STACK = 5, + _URC_HANDLER_FOUND = 6, + _URC_INSTALL_CONTEXT = 7, + _URC_CONTINUE_UNWIND = 8, + _URC_FAILURE = 9 /* unspecified failure of some kind */ + } + _Unwind_Reason_Code; + + typedef enum + { + _US_VIRTUAL_UNWIND_FRAME = 0, + _US_UNWIND_FRAME_STARTING = 1, + _US_UNWIND_FRAME_RESUME = 2, + _US_ACTION_MASK = 3, + _US_FORCE_UNWIND = 8, + _US_END_OF_STACK = 16 + } + _Unwind_State; + + /* Provided only for for compatibility with existing code. */ + typedef int _Unwind_Action; +#define _UA_SEARCH_PHASE 1 +#define _UA_CLEANUP_PHASE 2 +#define _UA_HANDLER_FRAME 4 +#define _UA_FORCE_UNWIND 8 +#define _UA_END_OF_STACK 16 +#define _URC_NO_REASON _URC_OK + + typedef struct _Unwind_Control_Block _Unwind_Control_Block; + typedef struct _Unwind_Context _Unwind_Context; + typedef _uw _Unwind_EHT_Header; + + + /* UCB: */ + + struct _Unwind_Control_Block + { +#ifdef _LIBC + /* For the benefit of code which assumes this is a scalar. All + glibc ever does is clear it. */ + _uw64 exception_class; +#else + char exception_class[8]; +#endif + void (*exception_cleanup)(_Unwind_Reason_Code, _Unwind_Control_Block *); + /* Unwinder cache, private fields for the unwinder's use */ + struct + { + _uw reserved1; /* Forced unwind stop fn, 0 if not forced */ + _uw reserved2; /* Personality routine address */ + _uw reserved3; /* Saved callsite address */ + _uw reserved4; /* Forced unwind stop arg */ + _uw reserved5; + } + unwinder_cache; + /* Propagation barrier cache (valid after phase 1): */ + struct + { + _uw sp; + _uw bitpattern[5]; + } + barrier_cache; + /* Cleanup cache (preserved over cleanup): */ + struct + { + _uw bitpattern[4]; + } + cleanup_cache; + /* Pr cache (for pr's benefit): */ + struct + { + _uw fnstart; /* function start address */ + _Unwind_EHT_Header *ehtp; /* pointer to EHT entry header word */ + _uw additional; /* additional data */ + _uw reserved1; + } + pr_cache; + long long int :0; /* Force alignment to 8-byte boundary */ + }; + + /* Virtual Register Set*/ + + typedef enum + { + _UVRSC_CORE = 0, /* integer register */ + _UVRSC_VFP = 1, /* vfp */ + _UVRSC_FPA = 2, /* fpa */ + _UVRSC_WMMXD = 3, /* Intel WMMX data register */ + _UVRSC_WMMXC = 4 /* Intel WMMX control register */ + } + _Unwind_VRS_RegClass; + + typedef enum + { + _UVRSD_UINT32 = 0, + _UVRSD_VFPX = 1, + _UVRSD_FPAX = 2, + _UVRSD_UINT64 = 3, + _UVRSD_FLOAT = 4, + _UVRSD_DOUBLE = 5 + } + _Unwind_VRS_DataRepresentation; + + typedef enum + { + _UVRSR_OK = 0, + _UVRSR_NOT_IMPLEMENTED = 1, + _UVRSR_FAILED = 2 + } + _Unwind_VRS_Result; + + /* Frame unwinding state. */ + typedef struct + { + /* The current word (bytes packed msb first). */ + _uw data; + /* Pointer to the next word of data. */ + _uw *next; + /* The number of bytes left in this word. */ + _uw8 bytes_left; + /* The number of words pointed to by ptr. */ + _uw8 words_left; + } + __gnu_unwind_state; + + typedef _Unwind_Reason_Code (*personality_routine) (_Unwind_State, + _Unwind_Control_Block *, _Unwind_Context *); + + _Unwind_VRS_Result _Unwind_VRS_Set(_Unwind_Context *, _Unwind_VRS_RegClass, + _uw, _Unwind_VRS_DataRepresentation, + void *); + + _Unwind_VRS_Result _Unwind_VRS_Get(_Unwind_Context *, _Unwind_VRS_RegClass, + _uw, _Unwind_VRS_DataRepresentation, + void *); + + _Unwind_VRS_Result _Unwind_VRS_Pop(_Unwind_Context *, _Unwind_VRS_RegClass, + _uw, _Unwind_VRS_DataRepresentation); + + + /* Support functions for the PR. */ +#define _Unwind_Exception _Unwind_Control_Block + typedef char _Unwind_Exception_Class[8]; + + void * _Unwind_GetLanguageSpecificData (_Unwind_Context *); + _Unwind_Ptr _Unwind_GetRegionStart (_Unwind_Context *); + + /* These two should never be used. */ + _Unwind_Ptr _Unwind_GetDataRelBase (_Unwind_Context *); + _Unwind_Ptr _Unwind_GetTextRelBase (_Unwind_Context *); + + /* Interface functions: */ + _Unwind_Reason_Code _Unwind_RaiseException(_Unwind_Control_Block *ucbp); + void __attribute__((noreturn)) _Unwind_Resume(_Unwind_Control_Block *ucbp); + _Unwind_Reason_Code _Unwind_Resume_or_Rethrow (_Unwind_Control_Block *ucbp); + + typedef _Unwind_Reason_Code (*_Unwind_Stop_Fn) + (int, _Unwind_Action, _Unwind_Exception_Class, + _Unwind_Control_Block *, struct _Unwind_Context *, void *); + _Unwind_Reason_Code _Unwind_ForcedUnwind (_Unwind_Control_Block *, + _Unwind_Stop_Fn, void *); + _Unwind_Word _Unwind_GetCFA (struct _Unwind_Context *); + void _Unwind_Complete(_Unwind_Control_Block *ucbp); + void _Unwind_DeleteException (_Unwind_Exception *); + + _Unwind_Reason_Code __gnu_unwind_frame (_Unwind_Control_Block *, + _Unwind_Context *); + _Unwind_Reason_Code __gnu_unwind_execute (_Unwind_Context *, + __gnu_unwind_state *); + + /* Decode an R_ARM_TARGET2 relocation. */ + static inline _Unwind_Word + _Unwind_decode_target2 (_Unwind_Word ptr) + { + _Unwind_Word tmp; + + tmp = *(_Unwind_Word *) ptr; + /* Zero values are always NULL. */ + if (!tmp) + return 0; + +#if defined(linux) || defined(__NetBSD__) + /* Pc-relative indirect. */ + tmp += ptr; + tmp = *(_Unwind_Word *) tmp; +#elif defined(__symbian__) + /* Absolute pointer. Nothing more to do. */ +#else + /* Pc-relative pointer. */ + tmp += ptr; +#endif + return tmp; + } + + static inline _Unwind_Word + _Unwind_GetGR (_Unwind_Context *context, int regno) + { + _uw val; + _Unwind_VRS_Get (context, _UVRSC_CORE, regno, _UVRSD_UINT32, &val); + return val; + } + + /* Return the address of the instruction, not the actual IP value. */ +#define _Unwind_GetIP(context) \ + (_Unwind_GetGR (context, 15) & ~(_Unwind_Word)1) + + static inline void + _Unwind_SetGR (_Unwind_Context *context, int regno, _Unwind_Word val) + { + _Unwind_VRS_Set (context, _UVRSC_CORE, regno, _UVRSD_UINT32, &val); + } + + /* The dwarf unwinder doesn't understand arm/thumb state. We assume the + landing pad uses the same instruction set as the call site. */ +#define _Unwind_SetIP(context, val) \ + _Unwind_SetGR (context, 15, val | (_Unwind_GetGR (context, 15) & 1)) + +typedef _Unwind_Reason_Code (*_Unwind_Trace_Fn) + (struct _Unwind_Context *, void *); + +extern _Unwind_Reason_Code _Unwind_Backtrace (_Unwind_Trace_Fn, void *); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* defined UNWIND_ARM_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/arm/vfork.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/arm/vfork.S new file mode 100644 index 00000000..935a4e90 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/arm/vfork.S @@ -0,0 +1,39 @@ +/* Copyright (C) 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +/* Save the PID value. */ +#define SAVE_PID \ + str lr, [sp, #-4]!; /* Save LR. */ \ + mov r0, #0xffff0fff; /* Point to the high page. */ \ + mov lr, pc; /* Save our return address. */ \ + sub pc, r0, #31; /* Jump to the TLS entry. */ \ + ldr lr, [sp], #4; /* Restore LR. */ \ + mov r2, r0; /* Save the TLS addr in r2. */ \ + ldr r3, [r2, #PID_OFFSET]; /* Load the saved PID. */ \ + rsbs r0, r3, #0; /* Negate it. */ \ + moveq r0, #0x80000000; /* Use 0x80000000 if it was 0. */ \ + str r0, [r2, #PID_OFFSET] /* Store the temporary PID. */ + +/* Restore the old PID value in the parent. */ +#define RESTORE_PID \ + cmp r0, #0; /* If we are the parent... */ \ + strne r3, [r2, #PID_OFFSET] /* ... restore the saved PID. */ + +#include "../../../../../../../libc/sysdeps/linux/arm/vfork.S" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/bits/local_lim.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/bits/local_lim.h new file mode 100644 index 00000000..8f0df4f9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/bits/local_lim.h @@ -0,0 +1,100 @@ +/* Minimum guaranteed maximum values for system limits. Linux version. + Copyright (C) 1993-1998,2000,2002-2004,2008 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* The kernel header pollutes the namespace with the NR_OPEN symbol + and defines LINK_MAX although filesystems have different maxima. A + similar thing is true for OPEN_MAX: the limit can be changed at + runtime and therefore the macro must not be defined. Remove this + after including the header if necessary. */ +#ifndef NR_OPEN +# define __undef_NR_OPEN +#endif +#ifndef LINK_MAX +# define __undef_LINK_MAX +#endif +#ifndef OPEN_MAX +# define __undef_OPEN_MAX +#endif +#ifndef ARG_MAX +# define __undef_ARG_MAX +#endif + +/* The kernel sources contain a file with all the needed information. */ +#include + +/* Have to remove NR_OPEN? */ +#ifdef __undef_NR_OPEN +# undef NR_OPEN +# undef __undef_NR_OPEN +#endif +/* Have to remove LINK_MAX? */ +#ifdef __undef_LINK_MAX +# undef LINK_MAX +# undef __undef_LINK_MAX +#endif +/* Have to remove OPEN_MAX? */ +#ifdef __undef_OPEN_MAX +# undef OPEN_MAX +# undef __undef_OPEN_MAX +#endif +/* Have to remove ARG_MAX? */ +#ifdef __undef_ARG_MAX +# undef ARG_MAX +# undef __undef_ARG_MAX +#endif + +/* The number of data keys per process. */ +#define _POSIX_THREAD_KEYS_MAX 128 +/* This is the value this implementation supports. */ +#define PTHREAD_KEYS_MAX 1024 + +/* Controlling the iterations of destructors for thread-specific data. */ +#define _POSIX_THREAD_DESTRUCTOR_ITERATIONS 4 +/* Number of iterations this implementation does. */ +#define PTHREAD_DESTRUCTOR_ITERATIONS _POSIX_THREAD_DESTRUCTOR_ITERATIONS + +/* The number of threads per process. */ +#define _POSIX_THREAD_THREADS_MAX 64 +/* We have no predefined limit on the number of threads. */ +#undef PTHREAD_THREADS_MAX + +/* Maximum amount by which a process can descrease its asynchronous I/O + priority level. */ +#define AIO_PRIO_DELTA_MAX 20 + +/* Minimum size for a thread. We are free to choose a reasonable value. */ +#define PTHREAD_STACK_MIN 16384 + +/* Maximum number of timer expiration overruns. */ +#define DELAYTIMER_MAX 2147483647 + +/* Maximum tty name length. */ +#define TTY_NAME_MAX 32 + +/* Maximum login name length. This is arbitrary. */ +#define LOGIN_NAME_MAX 256 + +/* Maximum host name length. */ +#define HOST_NAME_MAX 64 + +/* Maximum message queue priority level. */ +#define MQ_PRIO_MAX 32768 + +/* Maximum value the semaphore can have. */ +#define SEM_VALUE_MAX (2147483647) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/bits/posix_opt.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/bits/posix_opt.h new file mode 100644 index 00000000..200dcf69 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/bits/posix_opt.h @@ -0,0 +1,204 @@ +/* Define POSIX options for Linux. + Copyright (C) 1996-2004, 2006, 2008, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _BITS_POSIX_OPT_H +#define _BITS_POSIX_OPT_H 1 + +/* Job control is supported. */ +#define _POSIX_JOB_CONTROL 1 + +/* Processes have a saved set-user-ID and a saved set-group-ID. */ +#define _POSIX_SAVED_IDS 1 + +/* Priority scheduling is supported. */ +#define _POSIX_PRIORITY_SCHEDULING 200809L + +/* Synchronizing file data is supported. */ +#define _POSIX_SYNCHRONIZED_IO 200809L + +/* The fsync function is present. */ +#define _POSIX_FSYNC 200809L + +/* Mapping of files to memory is supported. */ +#define _POSIX_MAPPED_FILES 200809L + +/* Locking of all memory is supported. */ +#define _POSIX_MEMLOCK 200809L + +/* Locking of ranges of memory is supported. */ +#define _POSIX_MEMLOCK_RANGE 200809L + +/* Setting of memory protections is supported. */ +#define _POSIX_MEMORY_PROTECTION 200809L + +/* Some filesystems allow all users to change file ownership. */ +#define _POSIX_CHOWN_RESTRICTED 0 + +/* `c_cc' member of 'struct termios' structure can be disabled by + using the value _POSIX_VDISABLE. */ +#define _POSIX_VDISABLE '\0' + +/* Filenames are not silently truncated. */ +#define _POSIX_NO_TRUNC 1 + +/* X/Open realtime support is available. */ +#define _XOPEN_REALTIME 1 + +/* X/Open thread realtime support is available. */ +#define _XOPEN_REALTIME_THREADS 1 + +/* XPG4.2 shared memory is supported. */ +#define _XOPEN_SHM 1 + +/* Tell we have POSIX threads. */ +#define _POSIX_THREADS 200809L + +/* We have the reentrant functions described in POSIX. */ +#define _POSIX_REENTRANT_FUNCTIONS 1 +#define _POSIX_THREAD_SAFE_FUNCTIONS 200809L + +/* We provide priority scheduling for threads. */ +#define _POSIX_THREAD_PRIORITY_SCHEDULING 200809L + +/* We support user-defined stack sizes. */ +#define _POSIX_THREAD_ATTR_STACKSIZE 200809L + +/* We support user-defined stacks. */ +#define _POSIX_THREAD_ATTR_STACKADDR 200809L + +/* We support priority inheritence. */ +#define _POSIX_THREAD_PRIO_INHERIT 200809L + +/* We support priority protection, though only for non-robust + mutexes. */ +#define _POSIX_THREAD_PRIO_PROTECT 200809L + +#ifdef __USE_XOPEN2K8 +/* We support priority inheritence for robust mutexes. */ +# define _POSIX_THREAD_ROBUST_PRIO_INHERIT 200809L + +/* We do not support priority protection for robust mutexes. */ +# define _POSIX_THREAD_ROBUST_PRIO_PROTECT -1 +#endif + +#ifdef __UCLIBC_HAS_REALTIME__ +/* We support POSIX.1b semaphores. */ +#define _POSIX_SEMAPHORES 200809L +#endif + +/* Real-time signals are supported. */ +#define _POSIX_REALTIME_SIGNALS 200809L + +/* We support asynchronous I/O. */ +#define _POSIX_ASYNCHRONOUS_IO 200809L +#define _POSIX_ASYNC_IO 1 +/* Alternative name for Unix98. */ +#define _LFS_ASYNCHRONOUS_IO 1 +/* Support for prioritization is also available. */ +#define _POSIX_PRIORITIZED_IO 200809L + +/* The LFS support in asynchronous I/O is also available. */ +#define _LFS64_ASYNCHRONOUS_IO 1 + +#ifdef __UCLIBC_HAS_LFS__ +/* The rest of the LFS is also available. */ +#define _LFS_LARGEFILE 1 +#define _LFS64_LARGEFILE 1 +#define _LFS64_STDIO 1 +#endif + +/* POSIX shared memory objects are implemented. */ +#define _POSIX_SHARED_MEMORY_OBJECTS 200809L + +/* CPU-time clocks support needs to be checked at runtime. */ +#define _POSIX_CPUTIME 0 + +/* Clock support in threads must be also checked at runtime. */ +#define _POSIX_THREAD_CPUTIME 0 + +#ifdef __UCLIBC_HAS_REGEX__ +/* GNU libc provides regular expression handling. */ +#define _POSIX_REGEXP 1 +#endif + +/* Reader/Writer locks are available. */ +#define _POSIX_READER_WRITER_LOCKS 200809L + +/* We have a POSIX shell. */ +#define _POSIX_SHELL 1 + +/* We support the Timeouts option. */ +#define _POSIX_TIMEOUTS 200809L + +/* We support spinlocks. */ +#define _POSIX_SPIN_LOCKS 200809L + +#if 0 /* no support in uClibc (yet) */ +/* The `spawn' function family is supported. */ +#define _POSIX_SPAWN 200809L +#endif + +/* We have POSIX timers. */ +#define _POSIX_TIMERS 200809L + +/* The barrier functions are available. */ +#define _POSIX_BARRIERS 200809L + +/* POSIX message queues are available. */ +#define _POSIX_MESSAGE_PASSING 200809L + +/* Thread process-shared synchronization is supported. */ +#define _POSIX_THREAD_PROCESS_SHARED 200809L + +/* The monotonic clock might be available. */ +#define _POSIX_MONOTONIC_CLOCK 0 + +/* The clock selection interfaces are available. */ +#define _POSIX_CLOCK_SELECTION 200809L + +/* Advisory information interfaces are available. */ +#define _POSIX_ADVISORY_INFO 200809L + +#ifdef __UCLIBC_HAS_IPV6__ +/* IPv6 support is available. */ +#define _POSIX_IPV6 200809L +#endif + +#ifdef __UCLIBC_HAS_SOCKET__ +/* Raw socket support is available. */ +#define _POSIX_RAW_SOCKETS 200809L +#endif + +/* We have at least one terminal. */ +#define _POSIX2_CHAR_TERM 200809L + +/* Neither process nor thread sporadic server interfaces is available. */ +#define _POSIX_SPORADIC_SERVER -1 +#define _POSIX_THREAD_SPORADIC_SERVER -1 + +/* trace.h is not available. */ +#define _POSIX_TRACE -1 +#define _POSIX_TRACE_EVENT_FILTER -1 +#define _POSIX_TRACE_INHERIT -1 +#define _POSIX_TRACE_LOG -1 + +/* Typed memory objects are not available. */ +#define _POSIX_TYPED_MEMORY_OBJECTS -1 + +#endif /* bits/posix_opt.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/close.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/close.S new file mode 100644 index 00000000..cf50a1ea --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/close.S @@ -0,0 +1,21 @@ +#include + +/* +extern int __close_nocancel (int) attribute_hidden; +*/ +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + + +PSEUDO (__libc_close, close, 1) +ret +PSEUDO_END(__libc_close) + +libc_hidden_def (__close_nocancel) +libc_hidden_def (__libc_close) +weak_alias (__libc_close, __close) +libc_hidden_weak (__close) +weak_alias (__libc_close, close) +libc_hidden_weak (close) + + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/connect.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/connect.S new file mode 100644 index 00000000..441843fa --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/connect.S @@ -0,0 +1,12 @@ +#include +#ifndef __NR_connect +#error Missing definition of NR_connect needed for cancellation. +#endif +PSEUDO (__libc_connect, connect, 3) +ret +PSEUDO_END(__libc_connect) +libc_hidden_def (__libc_connect) +weak_alias (__libc_connect, __connect) +libc_hidden_weak (__connect) +weak_alias (__libc_connect, connect) +libc_hidden_weak (connect) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/creat.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/creat.S new file mode 100644 index 00000000..cd0e1b87 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/creat.S @@ -0,0 +1,7 @@ +#include +PSEUDO (__libc_creat, creat, 2) +ret +PSEUDO_END(__libc_creat) +libc_hidden_def (__libc_creat) +weak_alias (__libc_creat, creat) +libc_hidden_weak (creat) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/createthread.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/createthread.c new file mode 100644 index 00000000..9149efe5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/createthread.c @@ -0,0 +1,24 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Martin Schwidefsky . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Value passed to 'clone' for initialization of the thread register. */ +#define TLS_VALUE pd + +/* Get the real implementation. */ +#include diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/exit-thread.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/exit-thread.S new file mode 100644 index 00000000..bb996fec --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/exit-thread.S @@ -0,0 +1,23 @@ +/* Copyright (C) 1991,92,97,99,2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +PSEUDO (__exit_thread, exit, 1) + /* Shouldn't get here. */ +PSEUDO_END(__exit_thread) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/fork.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/fork.c new file mode 100644 index 00000000..6ad9053b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/fork.c @@ -0,0 +1,229 @@ +/* Copyright (C) 2002, 2003, 2007, 2008 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include +#include +#include "fork.h" +#include +#include +#include +#include + +unsigned long int *__fork_generation_pointer; + + + +/* The single linked list of all currently registered for handlers. */ +struct fork_handler *__fork_handlers; + + +static void +fresetlockfiles (void) +{ + FILE *fp; +#ifdef __USE_STDIO_FUTEXES__ + for (fp = _stdio_openlist; fp != NULL; fp = fp->__nextopen) + STDIO_INIT_MUTEX(fp->__lock); +#else + pthread_mutexattr_t attr; + + pthread_mutexattr_init(&attr); + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE_NP); + + for (fp = _stdio_openlist; fp != NULL; fp = fp->__nextopen) + pthread_mutex_init(&fp->__lock, &attr); + + pthread_mutexattr_destroy(&attr); +#endif +} + +extern __typeof(fork) __libc_fork; +pid_t +__libc_fork (void) +{ + pid_t pid; + struct used_handler + { + struct fork_handler *handler; + struct used_handler *next; + } *allp = NULL; + + /* Run all the registered preparation handlers. In reverse order. + While doing this we build up a list of all the entries. */ + struct fork_handler *runp; + while ((runp = __fork_handlers) != NULL) + { + /* Make sure we read from the current RUNP pointer. */ + atomic_full_barrier (); + + unsigned int oldval = runp->refcntr; + + if (oldval == 0) + /* This means some other thread removed the list just after + the pointer has been loaded. Try again. Either the list + is empty or we can retry it. */ + continue; + + /* Bump the reference counter. */ + if (atomic_compare_and_exchange_bool_acq (&__fork_handlers->refcntr, + oldval + 1, oldval)) + /* The value changed, try again. */ + continue; + + /* We bumped the reference counter for the first entry in the + list. That means that none of the following entries will + just go away. The unloading code works in the order of the + list. + + While executing the registered handlers we are building a + list of all the entries so that we can go backward later on. */ + while (1) + { + /* Execute the handler if there is one. */ + if (runp->prepare_handler != NULL) + runp->prepare_handler (); + + /* Create a new element for the list. */ + struct used_handler *newp + = (struct used_handler *) alloca (sizeof (*newp)); + newp->handler = runp; + newp->next = allp; + allp = newp; + + /* Advance to the next handler. */ + runp = runp->next; + if (runp == NULL) + break; + + /* Bump the reference counter for the next entry. */ + atomic_increment (&runp->refcntr); + } + + /* We are done. */ + break; + } + + __UCLIBC_IO_MUTEX_LOCK_CANCEL_UNSAFE(_stdio_openlist_add_lock); + +#ifndef NDEBUG + pid_t ppid = THREAD_GETMEM (THREAD_SELF, tid); +#endif + + /* We need to prevent the getpid() code to update the PID field so + that, if a signal arrives in the child very early and the signal + handler uses getpid(), the value returned is correct. */ + pid_t parentpid = THREAD_GETMEM (THREAD_SELF, pid); + THREAD_SETMEM (THREAD_SELF, pid, -parentpid); + +#ifdef ARCH_FORK + pid = ARCH_FORK (); +#else +# error "ARCH_FORK must be defined so that the CLONE_SETTID flag is used" + pid = INLINE_SYSCALL (fork, 0); +#endif + + + if (pid == 0) + { + struct pthread *self = THREAD_SELF; + + assert (THREAD_GETMEM (self, tid) != ppid); + + if (__fork_generation_pointer != NULL) + *__fork_generation_pointer += 4; + + /* Adjust the PID field for the new process. */ + THREAD_SETMEM (self, pid, THREAD_GETMEM (self, tid)); + +#if HP_TIMING_AVAIL + /* The CPU clock of the thread and process have to be set to zero. */ + hp_timing_t now; + HP_TIMING_NOW (now); + THREAD_SETMEM (self, cpuclock_offset, now); + GL(dl_cpuclock_offset) = now; +#endif + + /* Reset the file list. These are recursive mutexes. */ + fresetlockfiles (); + + /* Reset locks in the I/O code. */ + STDIO_INIT_MUTEX(_stdio_openlist_add_lock); + + /* XXX reset any locks in dynamic loader */ + + /* Run the handlers registered for the child. */ + while (allp != NULL) + { + if (allp->handler->child_handler != NULL) + allp->handler->child_handler (); + + /* Note that we do not have to wake any possible waiter. + This is the only thread in the new process. The count + may have been bumped up by other threads doing a fork. + We reset it to 1, to avoid waiting for non-existing + thread(s) to release the count. */ + allp->handler->refcntr = 1; + + /* XXX We could at this point look through the object pool + and mark all objects not on the __fork_handlers list as + unused. This is necessary in case the fork() happened + while another thread called dlclose() and that call had + to create a new list. */ + + allp = allp->next; + } + + /* Initialize the fork lock. */ + __fork_lock = LLL_LOCK_INITIALIZER; + } + else + { + assert (THREAD_GETMEM (THREAD_SELF, tid) == ppid); + + /* Restore the PID value. */ + THREAD_SETMEM (THREAD_SELF, pid, parentpid); + + /* We execute this even if the 'fork' call failed. */ + __UCLIBC_IO_MUTEX_UNLOCK_CANCEL_UNSAFE(_stdio_openlist_add_lock); + + /* Run the handlers registered for the parent. */ + while (allp != NULL) + { + if (allp->handler->parent_handler != NULL) + allp->handler->parent_handler (); + + if (atomic_decrement_and_test (&allp->handler->refcntr) + && allp->handler->need_signal) + lll_futex_wake (allp->handler->refcntr, 1, LLL_PRIVATE); + + allp = allp->next; + } + } + + return pid; +} +weak_alias(__libc_fork,__fork) +libc_hidden_proto(fork) +weak_alias(__libc_fork,fork) +libc_hidden_weak(fork) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/fork.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/fork.h new file mode 100644 index 00000000..a00cfabe --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/fork.h @@ -0,0 +1,60 @@ +/* Copyright (C) 2002, 2003, 2006, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +/* The fork generation counter, defined in libpthread. */ +extern unsigned long int __fork_generation attribute_hidden; + +/* Pointer to the fork generation counter in the thread library. */ +extern unsigned long int *__fork_generation_pointer attribute_hidden; + +/* Lock to protect allocation and deallocation of fork handlers. */ +extern int __fork_lock attribute_hidden; + +/* Elements of the fork handler lists. */ +struct fork_handler +{ + struct fork_handler *next; + void (*prepare_handler) (void); + void (*parent_handler) (void); + void (*child_handler) (void); + void *dso_handle; + unsigned int refcntr; + int need_signal; +}; + +/* The single linked list of all currently registered for handlers. */ +extern struct fork_handler *__fork_handlers attribute_hidden; + + +/* Function to call to unregister fork handlers. */ +extern void __unregister_atfork (void *dso_handle) attribute_hidden; +#define UNREGISTER_ATFORK(dso_handle) __unregister_atfork (dso_handle) + + +/* C library side function to register new fork handlers. */ +extern int __register_atfork (void (*__prepare) (void), + void (*__parent) (void), + void (*__child) (void), + void *dso_handle); +libc_hidden_proto (__register_atfork) + +/* Add a new element to the fork list. */ +extern void __linkin_atfork (struct fork_handler *newp) attribute_hidden; diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/getpid.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/getpid.c new file mode 100644 index 00000000..d4de3cd9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/getpid.c @@ -0,0 +1,65 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + + +#ifndef NOT_IN_libc +static inline __attribute__((always_inline)) pid_t really_getpid (pid_t oldval); + +static inline __attribute__((always_inline)) pid_t +really_getpid (pid_t oldval) +{ + if (__builtin_expect (oldval == 0, 1)) + { + pid_t selftid = THREAD_GETMEM (THREAD_SELF, tid); + if (__builtin_expect (selftid != 0, 1)) + return selftid; + } + + INTERNAL_SYSCALL_DECL (err); + pid_t result = INTERNAL_SYSCALL (getpid, err, 0); + + /* We do not set the PID field in the TID here since we might be + called from a signal handler while the thread executes fork. */ + if (oldval == 0) + THREAD_SETMEM (THREAD_SELF, tid, result); + return result; +} +#endif + +extern __typeof(getpid) __getpid; +pid_t +__getpid (void) +{ +#ifdef NOT_IN_libc + INTERNAL_SYSCALL_DECL (err); + pid_t result = INTERNAL_SYSCALL (getpid, err, 0); +#else + pid_t result = THREAD_GETMEM (THREAD_SELF, pid); + if (__builtin_expect (result <= 0, 0)) + result = really_getpid (result); +#endif + return result; +} +libc_hidden_proto(getpid) +weak_alias(__getpid, getpid) +libc_hidden_weak(getpid) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/Makefile new file mode 100644 index 00000000..43a6fad8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc NPTL +# +# Copyright (C) 2005 Steven J. Hill +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../../../../../ +top_builddir=../../../../../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.arch +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/Makefile.arch b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/Makefile.arch new file mode 100644 index 00000000..9a34595f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/Makefile.arch @@ -0,0 +1,29 @@ +# Makefile for uClibc NPTL +# +# Copyright (C) 2006 Steven J. Hill +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +libpthread_linux_arch_SSRC = pt-vfork.S clone.S pthread_spin_unlock.S pthread_once.S +libpthread_linux_arch_CSRC = pthread_spin_init.c pt-__syscall_error.c + +libc_linux_arch_CSRC = fork.c +libc_linux_arch_SSRC = clone.S vfork.S + +ASFLAGS += -DUSE___THREAD + +CFLAGS-pt-__syscall_error.c = -DNOT_IN_libc -DIS_IN_libpthread +ASFLAGS-pt-vfork.S = -DNOT_IN_libc -DIS_IN_libpthread -D_LIBC_REENTRANT +ASFLAGS-lowlevellock.S = -DNOT_IN_libc -DIS_IN_libpthread -D_LIBC_REENTRANT +ASFLAGS-lowlevelrobustlock.S = -DNOT_IN_libc -DIS_IN_libpthread -D_LIBC_REENTRANT +ASFLAGS-pthread_once.S = -DNOT_IN_libc -DIS_IN_libpthread -D_LIBC_REENTRANT +ASFLAGS-pthread_spin_unlock.S = -DNOT_IN_libc -DIS_IN_libpthread -D_LIBC_REENTRANT + +ASFLAGS-clone.S = -D_LIBC_REENTRANT +ASFLAGS-vfork.S = -D_LIBC_REENTRANT +ASFLAGS-libc-lowlevellock.S = -D_LIBC_REENTRANT +ifeq ($(UCLIBC_HAS_STDIO_FUTEXES),y) +CFLAGS-fork.c = -D__USE_STDIO_FUTEXES__ +endif +CFLAGS-OMIT-fork.c = -DNOT_IN_libc -DIS_IN_libpthread diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h new file mode 100644 index 00000000..9e3e016f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/bits/pthreadtypes.h @@ -0,0 +1,173 @@ +/* Copyright (C) 2002,2003,2004,2005,2006,2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _BITS_PTHREADTYPES_H +#define _BITS_PTHREADTYPES_H 1 + +#define __SIZEOF_PTHREAD_ATTR_T 36 +#define __SIZEOF_PTHREAD_MUTEX_T 24 +#define __SIZEOF_PTHREAD_MUTEXATTR_T 4 +#define __SIZEOF_PTHREAD_COND_T 48 +#define __SIZEOF_PTHREAD_COND_COMPAT_T 12 +#define __SIZEOF_PTHREAD_CONDATTR_T 4 +#define __SIZEOF_PTHREAD_RWLOCK_T 32 +#define __SIZEOF_PTHREAD_RWLOCKATTR_T 8 +#define __SIZEOF_PTHREAD_BARRIER_T 20 +#define __SIZEOF_PTHREAD_BARRIERATTR_T 4 + + +/* Thread identifiers. The structure of the attribute type is not + exposed on purpose. */ +typedef unsigned long int pthread_t; + + +typedef union +{ + char __size[__SIZEOF_PTHREAD_ATTR_T]; + long int __align; +} pthread_attr_t; + + +typedef struct __pthread_internal_slist +{ + struct __pthread_internal_slist *__next; +} __pthread_slist_t; + + +/* Data structures for mutex handling. The structure of the attribute + type is not exposed on purpose. */ +typedef union +{ + struct __pthread_mutex_s + { + int __lock; + unsigned int __count; + int __owner; + /* KIND must stay at this position in the structure to maintain + binary compatibility. */ + int __kind; + unsigned int __nusers; + __extension__ union + { + int __spins; + __pthread_slist_t __list; + }; + } __data; + char __size[__SIZEOF_PTHREAD_MUTEX_T]; + long int __align; +} pthread_mutex_t; + +typedef union +{ + char __size[__SIZEOF_PTHREAD_MUTEXATTR_T]; + long int __align; +} pthread_mutexattr_t; + + +/* Data structure for conditional variable handling. The structure of + the attribute type is not exposed on purpose. */ +typedef union +{ + struct + { + int __lock; + unsigned int __futex; + __extension__ unsigned long long int __total_seq; + __extension__ unsigned long long int __wakeup_seq; + __extension__ unsigned long long int __woken_seq; + void *__mutex; + unsigned int __nwaiters; + unsigned int __broadcast_seq; + } __data; + char __size[__SIZEOF_PTHREAD_COND_T]; + __extension__ long long int __align; +} pthread_cond_t; + +typedef union +{ + char __size[__SIZEOF_PTHREAD_CONDATTR_T]; + long int __align; +} pthread_condattr_t; + + +/* Keys for thread-specific data */ +typedef unsigned int pthread_key_t; + + +/* Once-only execution */ +typedef int pthread_once_t; + + +#if defined __USE_UNIX98 || defined __USE_XOPEN2K +/* Data structure for read-write lock variable handling. The + structure of the attribute type is not exposed on purpose. */ +typedef union +{ + struct + { + int __lock; + unsigned int __nr_readers; + unsigned int __readers_wakeup; + unsigned int __writer_wakeup; + unsigned int __nr_readers_queued; + unsigned int __nr_writers_queued; + /* FLAGS must stay at this position in the structure to maintain + binary compatibility. */ + unsigned char __flags; + unsigned char __shared; + unsigned char __pad1; + unsigned char __pad2; + int __writer; + } __data; + char __size[__SIZEOF_PTHREAD_RWLOCK_T]; + long int __align; +} pthread_rwlock_t; + +typedef union +{ + char __size[__SIZEOF_PTHREAD_RWLOCKATTR_T]; + long int __align; +} pthread_rwlockattr_t; +#endif + + +#ifdef __USE_XOPEN2K +/* POSIX spinlock data type. */ +typedef volatile int pthread_spinlock_t; + + +/* POSIX barriers data type. The structure of the type is + deliberately not exposed. */ +typedef union +{ + char __size[__SIZEOF_PTHREAD_BARRIER_T]; + long int __align; +} pthread_barrier_t; + +typedef union +{ + char __size[__SIZEOF_PTHREAD_BARRIERATTR_T]; + int __align; +} pthread_barrierattr_t; +#endif + + +/* Extra attributes for the cleanup functions. */ +#define __cleanup_fct_attribute __attribute__ ((__regparm__ (1))) + +#endif /* bits/pthreadtypes.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/bits/semaphore.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/bits/semaphore.h new file mode 100644 index 00000000..934493c3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/bits/semaphore.h @@ -0,0 +1,36 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SEMAPHORE_H +# error "Never use directly; include instead." +#endif + + +#define __SIZEOF_SEM_T 16 + + +/* Value returned if `sem_open' failed. */ +#define SEM_FAILED ((sem_t *) 0) + + +typedef union +{ + char __size[__SIZEOF_SEM_T]; + long int __align; +} sem_t; diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/clone.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/clone.S new file mode 100644 index 00000000..9c7c4646 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/clone.S @@ -0,0 +1,2 @@ +#define RESET_PID +#include diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/createthread.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/createthread.c new file mode 100644 index 00000000..35719be9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/createthread.c @@ -0,0 +1,49 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* The "thread register" gets initialized from a segment descriptor. + Initialize such a descriptor first. */ +#define PREPARE_CREATE \ + union user_desc_init desc; \ + \ + /* Describe the thread-local storage segment. */ \ + \ + /* The 'entry_number' field. The first three bits of the segment \ + register value select the GDT, ignore them. We get the index \ + from the value of the %gs register in the current thread. */ \ + desc.vals[0] = TLS_GET_GS () >> 3; \ + /* The 'base_addr' field. Pointer to the TCB. */ \ + desc.vals[1] = (unsigned long int) pd; \ + /* The 'limit' field. We use 4GB which is 0xfffff pages. */ \ + desc.vals[2] = 0xfffff; \ + /* Collapsed value of the bitfield: \ + .seg_32bit = 1 \ + .contents = 0 \ + .read_exec_only = 0 \ + .limit_in_pages = 1 \ + .seg_not_present = 0 \ + .useable = 1 */ \ + desc.vals[3] = 0x51 + +/* Value passed to 'clone' for initialization of the thread register. */ +#define TLS_VALUE &desc.desc + + +/* Get the real implementation. */ +#include diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/fork.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/fork.c new file mode 100644 index 00000000..813e5299 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/fork.c @@ -0,0 +1,31 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + + +#define ARCH_FORK() \ + INLINE_SYSCALL (clone, 5, \ + CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | SIGCHLD, 0, \ + NULL, NULL, &THREAD_SELF->tid) + +#include "../fork.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/libc-lowlevellock.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/libc-lowlevellock.S new file mode 100644 index 00000000..ce8ad27a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/libc-lowlevellock.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2002, 2003, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "lowlevellock.S" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S new file mode 100644 index 00000000..00f8b56f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevellock.S @@ -0,0 +1,459 @@ +/* Copyright (C) 2002-2004, 2006, 2007, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include + + .text + +#ifdef __ASSUME_PRIVATE_FUTEX +# define LOAD_PRIVATE_FUTEX_WAIT(reg) \ + movl $(FUTEX_WAIT | FUTEX_PRIVATE_FLAG), reg +# define LOAD_PRIVATE_FUTEX_WAKE(reg) \ + movl $(FUTEX_WAKE | FUTEX_PRIVATE_FLAG), reg +# define LOAD_FUTEX_WAIT(reg) \ + xorl $(FUTEX_WAIT | FUTEX_PRIVATE_FLAG), reg +# define LOAD_FUTEX_WAIT_ABS(reg) \ + xorl $(FUTEX_WAIT_BITSET | FUTEX_PRIVATE_FLAG | FUTEX_CLOCK_REALTIME), reg +# define LOAD_FUTEX_WAKE(reg) \ + xorl $(FUTEX_WAKE | FUTEX_PRIVATE_FLAG), reg +#else +# if FUTEX_WAIT == 0 +# define LOAD_PRIVATE_FUTEX_WAIT(reg) \ + movl %gs:PRIVATE_FUTEX, reg +# else +# define LOAD_PRIVATE_FUTEX_WAIT(reg) \ + movl %gs:PRIVATE_FUTEX, reg ; \ + orl $FUTEX_WAIT, reg +# endif +# define LOAD_PRIVATE_FUTEX_WAKE(reg) \ + movl %gs:PRIVATE_FUTEX, reg ; \ + orl $FUTEX_WAKE, reg +# if FUTEX_WAIT == 0 +# define LOAD_FUTEX_WAIT(reg) \ + xorl $FUTEX_PRIVATE_FLAG, reg ; \ + andl %gs:PRIVATE_FUTEX, reg +# else +# define LOAD_FUTEX_WAIT(reg) \ + xorl $FUTEX_PRIVATE_FLAG, reg ; \ + andl %gs:PRIVATE_FUTEX, reg ; \ + orl $FUTEX_WAIT, reg +# endif +# define LOAD_FUTEX_WAIT_ABS(reg) \ + xorl $FUTEX_PRIVATE_FLAG, reg ; \ + andl %gs:PRIVATE_FUTEX, reg ; \ + orl $FUTEX_WAIT_BITSET | FUTEX_CLOCK_REALTIME, reg +# define LOAD_FUTEX_WAKE(reg) \ + xorl $FUTEX_PRIVATE_FLAG, reg ; \ + andl %gs:PRIVATE_FUTEX, reg ; \ + orl $FUTEX_WAKE, reg +#endif + + .globl __lll_lock_wait_private + .type __lll_lock_wait_private,@function + .hidden __lll_lock_wait_private + .align 16 +__lll_lock_wait_private: + cfi_startproc + pushl %edx + cfi_adjust_cfa_offset(4) + pushl %ebx + cfi_adjust_cfa_offset(4) + pushl %esi + cfi_adjust_cfa_offset(4) + cfi_offset(%edx, -8) + cfi_offset(%ebx, -12) + cfi_offset(%esi, -16) + + movl $2, %edx + movl %ecx, %ebx + xorl %esi, %esi /* No timeout. */ + LOAD_PRIVATE_FUTEX_WAIT (%ecx) + + cmpl %edx, %eax /* NB: %edx == 2 */ + jne 2f + +1: movl $SYS_futex, %eax + ENTER_KERNEL + +2: movl %edx, %eax + xchgl %eax, (%ebx) /* NB: lock is implied */ + + testl %eax, %eax + jnz 1b + + popl %esi + cfi_adjust_cfa_offset(-4) + cfi_restore(%esi) + popl %ebx + cfi_adjust_cfa_offset(-4) + cfi_restore(%ebx) + popl %edx + cfi_adjust_cfa_offset(-4) + cfi_restore(%edx) + ret + cfi_endproc + .size __lll_lock_wait_private,.-__lll_lock_wait_private + +#ifdef NOT_IN_libc + .globl __lll_lock_wait + .type __lll_lock_wait,@function + .hidden __lll_lock_wait + .align 16 +__lll_lock_wait: + cfi_startproc + pushl %edx + cfi_adjust_cfa_offset(4) + pushl %ebx + cfi_adjust_cfa_offset(4) + pushl %esi + cfi_adjust_cfa_offset(4) + cfi_offset(%edx, -8) + cfi_offset(%ebx, -12) + cfi_offset(%esi, -16) + + movl %edx, %ebx + movl $2, %edx + xorl %esi, %esi /* No timeout. */ + LOAD_FUTEX_WAIT (%ecx) + + cmpl %edx, %eax /* NB: %edx == 2 */ + jne 2f + +1: movl $SYS_futex, %eax + ENTER_KERNEL + +2: movl %edx, %eax + xchgl %eax, (%ebx) /* NB: lock is implied */ + + testl %eax, %eax + jnz 1b + + popl %esi + cfi_adjust_cfa_offset(-4) + cfi_restore(%esi) + popl %ebx + cfi_adjust_cfa_offset(-4) + cfi_restore(%ebx) + popl %edx + cfi_adjust_cfa_offset(-4) + cfi_restore(%edx) + ret + cfi_endproc + .size __lll_lock_wait,.-__lll_lock_wait + + /* %ecx: futex + %esi: flags + %edx: timeout + %eax: futex value + */ + .globl __lll_timedlock_wait + .type __lll_timedlock_wait,@function + .hidden __lll_timedlock_wait + .align 16 +__lll_timedlock_wait: + cfi_startproc + pushl %ebp + cfi_adjust_cfa_offset(4) + cfi_rel_offset(%ebp, 0) + pushl %ebx + cfi_adjust_cfa_offset(4) + cfi_rel_offset(%ebx, 0) + +# ifndef __ASSUME_FUTEX_CLOCK_REALTIME +# ifdef __PIC__ + LOAD_PIC_REG (bx) + cmpl $0, __have_futex_clock_realtime@GOTOFF(%ebx) +# else + cmpl $0, __have_futex_clock_realtime +# endif + je .Lreltmo +# endif + + movl %ecx, %ebx + movl %esi, %ecx + movl %edx, %esi + movl $0xffffffff, %ebp + LOAD_FUTEX_WAIT_ABS (%ecx) + + movl $2, %edx + cmpl %edx, %eax + jne 2f + +1: movl $SYS_futex, %eax + movl $2, %edx + ENTER_KERNEL + +2: xchgl %edx, (%ebx) /* NB: lock is implied */ + + testl %edx, %edx + jz 3f + + cmpl $-ETIMEDOUT, %eax + je 4f + cmpl $-EINVAL, %eax + jne 1b +4: movl %eax, %edx + negl %edx + +3: movl %edx, %eax +7: popl %ebx + cfi_adjust_cfa_offset(-4) + cfi_restore(%ebx) + popl %ebp + cfi_adjust_cfa_offset(-4) + cfi_restore(%ebp) + ret + +# ifndef __ASSUME_FUTEX_CLOCK_REALTIME +.Lreltmo: + /* Check for a valid timeout value. */ + cmpl $1000000000, 4(%edx) + jae 3f + + pushl %esi + cfi_adjust_cfa_offset(4) + cfi_rel_offset(%esi, 0) + pushl %edi + cfi_adjust_cfa_offset(4) + cfi_rel_offset(%edi, 0) + + /* Stack frame for the timespec and timeval structs. */ + subl $8, %esp + cfi_adjust_cfa_offset(8) + + movl %ecx, %ebp + movl %edx, %edi + + movl $2, %edx + xchgl %edx, (%ebp) + + test %edx, %edx + je 6f + +1: + /* Get current time. */ + movl %esp, %ebx + xorl %ecx, %ecx + movl $__NR_gettimeofday, %eax + ENTER_KERNEL + + /* Compute relative timeout. */ + movl 4(%esp), %eax + movl $1000, %edx + mul %edx /* Milli seconds to nano seconds. */ + movl (%edi), %ecx + movl 4(%edi), %edx + subl (%esp), %ecx + subl %eax, %edx + jns 4f + addl $1000000000, %edx + subl $1, %ecx +4: testl %ecx, %ecx + js 2f /* Time is already up. */ + + /* Store relative timeout. */ + movl %ecx, (%esp) + movl %edx, 4(%esp) + + /* Futex call. */ + movl %ebp, %ebx + movl $2, %edx + movl %esp, %esi + movl 16(%esp), %ecx + LOAD_FUTEX_WAIT (%ecx) + movl $SYS_futex, %eax + ENTER_KERNEL + + /* NB: %edx == 2 */ + xchgl %edx, (%ebp) + + testl %edx, %edx + je 6f + + cmpl $-ETIMEDOUT, %eax + jne 1b +2: movl $ETIMEDOUT, %edx + +6: addl $8, %esp + cfi_adjust_cfa_offset(-8) + popl %edi + cfi_adjust_cfa_offset(-4) + cfi_restore(%edi) + popl %esi + cfi_adjust_cfa_offset(-4) + cfi_restore(%esi) +7: popl %ebx + cfi_adjust_cfa_offset(-4) + cfi_restore(%ebx) + popl %ebp + cfi_adjust_cfa_offset(-4) + cfi_restore(%ebp) + movl %edx, %eax + ret + +3: movl $EINVAL, %edx + jmp 7b +# endif + cfi_endproc + .size __lll_timedlock_wait,.-__lll_timedlock_wait +#endif + + .globl __lll_unlock_wake_private + .type __lll_unlock_wake_private,@function + .hidden __lll_unlock_wake_private + .align 16 +__lll_unlock_wake_private: + cfi_startproc + pushl %ebx + cfi_adjust_cfa_offset(4) + pushl %ecx + cfi_adjust_cfa_offset(4) + pushl %edx + cfi_adjust_cfa_offset(4) + cfi_offset(%ebx, -8) + cfi_offset(%ecx, -12) + cfi_offset(%edx, -16) + + movl %eax, %ebx + movl $0, (%eax) + LOAD_PRIVATE_FUTEX_WAKE (%ecx) + movl $1, %edx /* Wake one thread. */ + movl $SYS_futex, %eax + ENTER_KERNEL + + popl %edx + cfi_adjust_cfa_offset(-4) + cfi_restore(%edx) + popl %ecx + cfi_adjust_cfa_offset(-4) + cfi_restore(%ecx) + popl %ebx + cfi_adjust_cfa_offset(-4) + cfi_restore(%ebx) + ret + cfi_endproc + .size __lll_unlock_wake_private,.-__lll_unlock_wake_private + +#ifdef NOT_IN_libc + .globl __lll_unlock_wake + .type __lll_unlock_wake,@function + .hidden __lll_unlock_wake + .align 16 +__lll_unlock_wake: + cfi_startproc + pushl %ebx + cfi_adjust_cfa_offset(4) + pushl %ecx + cfi_adjust_cfa_offset(4) + pushl %edx + cfi_adjust_cfa_offset(4) + cfi_offset(%ebx, -8) + cfi_offset(%ecx, -12) + cfi_offset(%edx, -16) + + movl %eax, %ebx + movl $0, (%eax) + LOAD_FUTEX_WAKE (%ecx) + movl $1, %edx /* Wake one thread. */ + movl $SYS_futex, %eax + ENTER_KERNEL + + popl %edx + cfi_adjust_cfa_offset(-4) + cfi_restore(%edx) + popl %ecx + cfi_adjust_cfa_offset(-4) + cfi_restore(%ecx) + popl %ebx + cfi_adjust_cfa_offset(-4) + cfi_restore(%ebx) + ret + cfi_endproc + .size __lll_unlock_wake,.-__lll_unlock_wake + + .globl __lll_timedwait_tid + .type __lll_timedwait_tid,@function + .hidden __lll_timedwait_tid + .align 16 +__lll_timedwait_tid: + pushl %edi + pushl %esi + pushl %ebx + pushl %ebp + + movl %eax, %ebp + movl %edx, %edi + subl $8, %esp + + /* Get current time. */ +2: movl %esp, %ebx + xorl %ecx, %ecx + movl $__NR_gettimeofday, %eax + ENTER_KERNEL + + /* Compute relative timeout. */ + movl 4(%esp), %eax + movl $1000, %edx + mul %edx /* Milli seconds to nano seconds. */ + movl (%edi), %ecx + movl 4(%edi), %edx + subl (%esp), %ecx + subl %eax, %edx + jns 5f + addl $1000000000, %edx + subl $1, %ecx +5: testl %ecx, %ecx + js 6f /* Time is already up. */ + + movl %ecx, (%esp) /* Store relative timeout. */ + movl %edx, 4(%esp) + + movl (%ebp), %edx + testl %edx, %edx + jz 4f + + movl %esp, %esi + /* XXX The kernel so far uses global futex for the wakeup at + all times. */ + xorl %ecx, %ecx /* movl $FUTEX_WAIT, %ecx */ + movl %ebp, %ebx + movl $SYS_futex, %eax + ENTER_KERNEL + + cmpl $0, (%ebx) + jne 1f +4: xorl %eax, %eax + +3: addl $8, %esp + popl %ebp + popl %ebx + popl %esi + popl %edi + ret + +1: cmpl $-ETIMEDOUT, %eax + jne 2b +6: movl $ETIMEDOUT, %eax + jmp 3b + .size __lll_timedwait_tid,.-__lll_timedwait_tid +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevelrobustlock.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevelrobustlock.S new file mode 100644 index 00000000..1d038001 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/lowlevelrobustlock.S @@ -0,0 +1,234 @@ +/* Copyright (C) 2002, 2003, 2004, 2006, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include + + .text + +#define FUTEX_WAITERS 0x80000000 +#define FUTEX_OWNER_DIED 0x40000000 + +#ifdef __ASSUME_PRIVATE_FUTEX +# define LOAD_FUTEX_WAIT(reg) \ + xorl $(FUTEX_WAIT | FUTEX_PRIVATE_FLAG), reg +#else +# if FUTEX_WAIT == 0 +# define LOAD_FUTEX_WAIT(reg) \ + xorl $FUTEX_PRIVATE_FLAG, reg ; \ + andl %gs:PRIVATE_FUTEX, reg +# else +# define LOAD_FUTEX_WAIT(reg) \ + xorl $FUTEX_PRIVATE_FLAG, reg ; \ + andl %gs:PRIVATE_FUTEX, reg ; \ + orl $FUTEX_WAIT, reg +# endif +#endif + + .globl __lll_robust_lock_wait + .type __lll_robust_lock_wait,@function + .hidden __lll_robust_lock_wait + .align 16 +__lll_robust_lock_wait: + cfi_startproc + pushl %edx + cfi_adjust_cfa_offset(4) + pushl %ebx + cfi_adjust_cfa_offset(4) + pushl %esi + cfi_adjust_cfa_offset(4) + cfi_offset(%edx, -8) + cfi_offset(%ebx, -12) + cfi_offset(%esi, -16) + + movl %edx, %ebx + xorl %esi, %esi /* No timeout. */ + LOAD_FUTEX_WAIT (%ecx) + +4: movl %eax, %edx + orl $FUTEX_WAITERS, %edx + + testl $FUTEX_OWNER_DIED, %eax + jnz 3f + + cmpl %edx, %eax /* NB: %edx == 2 */ + je 1f + + LOCK + cmpxchgl %edx, (%ebx) + jnz 2f + +1: movl $SYS_futex, %eax + ENTER_KERNEL + + movl (%ebx), %eax + +2: test %eax, %eax + jne 4b + + movl %gs:TID, %edx + orl $FUTEX_WAITERS, %edx + LOCK + cmpxchgl %edx, (%ebx) + jnz 4b + /* NB: %eax == 0 */ + +3: popl %esi + cfi_adjust_cfa_offset(-4) + cfi_restore(%esi) + popl %ebx + cfi_adjust_cfa_offset(-4) + cfi_restore(%ebx) + popl %edx + cfi_adjust_cfa_offset(-4) + cfi_restore(%edx) + ret + cfi_endproc + .size __lll_robust_lock_wait,.-__lll_robust_lock_wait + + + .globl __lll_robust_timedlock_wait + .type __lll_robust_timedlock_wait,@function + .hidden __lll_robust_timedlock_wait + .align 16 +__lll_robust_timedlock_wait: + cfi_startproc + /* Check for a valid timeout value. */ + cmpl $1000000000, 4(%edx) + jae 3f + + pushl %edi + cfi_adjust_cfa_offset(4) + pushl %esi + cfi_adjust_cfa_offset(4) + pushl %ebx + cfi_adjust_cfa_offset(4) + pushl %ebp + cfi_adjust_cfa_offset(4) + cfi_offset(%edi, -8) + cfi_offset(%esi, -12) + cfi_offset(%ebx, -16) + cfi_offset(%ebp, -20) + + /* Stack frame for the timespec and timeval structs. */ + subl $12, %esp + cfi_adjust_cfa_offset(12) + + movl %ecx, %ebp + movl %edx, %edi + +1: movl %eax, 8(%esp) + + /* Get current time. */ + movl %esp, %ebx + xorl %ecx, %ecx + movl $__NR_gettimeofday, %eax + ENTER_KERNEL + + /* Compute relative timeout. */ + movl 4(%esp), %eax + movl $1000, %edx + mul %edx /* Milli seconds to nano seconds. */ + movl (%edi), %ecx + movl 4(%edi), %edx + subl (%esp), %ecx + subl %eax, %edx + jns 4f + addl $1000000000, %edx + subl $1, %ecx +4: testl %ecx, %ecx + js 8f /* Time is already up. */ + + /* Store relative timeout. */ + movl %ecx, (%esp) + movl %edx, 4(%esp) + + movl %ebp, %ebx + + movl 8(%esp), %edx + movl %edx, %eax + orl $FUTEX_WAITERS, %edx + + testl $FUTEX_OWNER_DIED, %eax + jnz 6f + + cmpl %eax, %edx + je 2f + + LOCK + cmpxchgl %edx, (%ebx) + movl $0, %ecx /* Must use mov to avoid changing cc. */ + jnz 5f + +2: + /* Futex call. */ + movl %esp, %esi + movl 20(%esp), %ecx + LOAD_FUTEX_WAIT (%ecx) + movl $SYS_futex, %eax + ENTER_KERNEL + movl %eax, %ecx + + movl (%ebx), %eax + +5: testl %eax, %eax + jne 7f + + movl %gs:TID, %edx + orl $FUTEX_WAITERS, %edx + LOCK + cmpxchgl %edx, (%ebx) + jnz 7f + +6: addl $12, %esp + cfi_adjust_cfa_offset(-12) + popl %ebp + cfi_adjust_cfa_offset(-4) + cfi_restore(%ebp) + popl %ebx + cfi_adjust_cfa_offset(-4) + cfi_restore(%ebx) + popl %esi + cfi_adjust_cfa_offset(-4) + cfi_restore(%esi) + popl %edi + cfi_adjust_cfa_offset(-4) + cfi_restore(%edi) + ret + +3: movl $EINVAL, %eax + ret + + cfi_adjust_cfa_offset(28) + cfi_offset(%edi, -8) + cfi_offset(%esi, -12) + cfi_offset(%ebx, -16) + cfi_offset(%ebp, -20) + /* Check whether the time expired. */ +7: cmpl $-ETIMEDOUT, %ecx + jne 1b + +8: movl $ETIMEDOUT, %eax + jmp 6b + cfi_endproc + .size __lll_robust_timedlock_wait,.-__lll_robust_timedlock_wait diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_barrier_wait.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_barrier_wait.S new file mode 100644 index 00000000..040d7f8c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_barrier_wait.S @@ -0,0 +1,187 @@ +/* Copyright (C) 2002, 2003, 2004, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + + .text + + .globl pthread_barrier_wait + .type pthread_barrier_wait,@function + .align 16 +pthread_barrier_wait: + cfi_startproc + pushl %ebx + cfi_adjust_cfa_offset(4) + cfi_offset(%ebx, -8) + + movl 8(%esp), %ebx + + /* Get the mutex. */ + movl $1, %edx + xorl %eax, %eax + LOCK + cmpxchgl %edx, MUTEX(%ebx) + jnz 1f + + /* One less waiter. If this was the last one needed wake + everybody. */ +2: subl $1, LEFT(%ebx) + je 3f + + /* There are more threads to come. */ + pushl %esi + cfi_adjust_cfa_offset(4) + cfi_offset(%esi, -12) + +#if CURR_EVENT == 0 + movl (%ebx), %edx +#else + movl CURR_EVENT(%ebx), %edx +#endif + + /* Release the mutex. */ + LOCK + subl $1, MUTEX(%ebx) + jne 6f + + /* Wait for the remaining threads. The call will return immediately + if the CURR_EVENT memory has meanwhile been changed. */ +7: +#if FUTEX_WAIT == 0 + movl PRIVATE(%ebx), %ecx +#else + movl $FUTEX_WAIT, %ecx + orl PRIVATE(%ebx), %ecx +#endif + xorl %esi, %esi +8: movl $SYS_futex, %eax + ENTER_KERNEL + + /* Don't return on spurious wakeups. The syscall does not change + any register except %eax so there is no need to reload any of + them. */ +#if CURR_EVENT == 0 + cmpl %edx, (%ebx) +#else + cmpl %edx, CURR_EVENT(%ebx) +#endif + je 8b + + /* Increment LEFT. If this brings the count back to the + initial count unlock the object. */ + movl $1, %edx + movl INIT_COUNT(%ebx), %ecx + LOCK + xaddl %edx, LEFT(%ebx) + subl $1, %ecx + cmpl %ecx, %edx + jne 10f + + /* Release the mutex. We cannot release the lock before + waking the waiting threads since otherwise a new thread might + arrive and gets waken up, too. */ + LOCK + subl $1, MUTEX(%ebx) + jne 9f + + /* Note: %esi is still zero. */ +10: movl %esi, %eax /* != PTHREAD_BARRIER_SERIAL_THREAD */ + + popl %esi + cfi_adjust_cfa_offset(-4) + cfi_restore(%esi) + popl %ebx + cfi_adjust_cfa_offset(-4) + cfi_restore(%ebx) + ret + + cfi_adjust_cfa_offset(4) + cfi_offset(%ebx, -8) + + /* The necessary number of threads arrived. */ +3: +#if CURR_EVENT == 0 + addl $1, (%ebx) +#else + addl $1, CURR_EVENT(%ebx) +#endif + + /* Wake up all waiters. The count is a signed number in the kernel + so 0x7fffffff is the highest value. */ + movl $0x7fffffff, %edx + movl $FUTEX_WAKE, %ecx + orl PRIVATE(%ebx), %ecx + movl $SYS_futex, %eax + ENTER_KERNEL + + /* Increment LEFT. If this brings the count back to the + initial count unlock the object. */ + movl $1, %edx + movl INIT_COUNT(%ebx), %ecx + LOCK + xaddl %edx, LEFT(%ebx) + subl $1, %ecx + cmpl %ecx, %edx + jne 5f + + /* Release the mutex. We cannot release the lock before + waking the waiting threads since otherwise a new thread might + arrive and gets waken up, too. */ + LOCK + subl $1, MUTEX(%ebx) + jne 4f + +5: orl $-1, %eax /* == PTHREAD_BARRIER_SERIAL_THREAD */ + + popl %ebx + cfi_adjust_cfa_offset(-4) + cfi_restore(%ebx) + ret + + cfi_adjust_cfa_offset(4) + cfi_offset(%ebx, -8) +1: movl PRIVATE(%ebx), %ecx + leal MUTEX(%ebx), %edx + xorl $LLL_SHARED, %ecx + call __lll_lock_wait + jmp 2b + +4: movl PRIVATE(%ebx), %ecx + leal MUTEX(%ebx), %eax + xorl $LLL_SHARED, %ecx + call __lll_unlock_wake + jmp 5b + + cfi_adjust_cfa_offset(4) + cfi_offset(%esi, -12) +6: movl PRIVATE(%ebx), %ecx + leal MUTEX(%ebx), %eax + xorl $LLL_SHARED, %ecx + call __lll_unlock_wake + jmp 7b + +9: movl PRIVATE(%ebx), %ecx + leal MUTEX(%ebx), %eax + xorl $LLL_SHARED, %ecx + call __lll_unlock_wake + jmp 10b + cfi_endproc + .size pthread_barrier_wait,.-pthread_barrier_wait diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.S new file mode 100644 index 00000000..ca9ceca0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_broadcast.S @@ -0,0 +1,239 @@ +/* Copyright (C) 2002,2003,2004,2006,2007,2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include +#include + + .text + + /* int pthread_cond_broadcast (pthread_cond_t *cond) */ + .globl __pthread_cond_broadcast + .type __pthread_cond_broadcast, @function + .protected __pthread_cond_broadcast + .align 16 +__pthread_cond_broadcast: + cfi_startproc + pushl %ebx + cfi_adjust_cfa_offset(4) + cfi_rel_offset(%ebx, 0) + pushl %esi + cfi_adjust_cfa_offset(4) + cfi_rel_offset(%esi, 0) + pushl %edi + cfi_adjust_cfa_offset(4) + cfi_rel_offset(%edi, 0) + pushl %ebp + cfi_adjust_cfa_offset(4) + cfi_rel_offset(%ebp, 0) + cfi_remember_state + + movl 20(%esp), %ebx + + /* Get internal lock. */ + movl $1, %edx + xorl %eax, %eax + LOCK +#if cond_lock == 0 + cmpxchgl %edx, (%ebx) +#else + cmpxchgl %edx, cond_lock(%ebx) +#endif + jnz 1f + +2: addl $cond_futex, %ebx + movl total_seq+4-cond_futex(%ebx), %eax + movl total_seq-cond_futex(%ebx), %ebp + cmpl wakeup_seq+4-cond_futex(%ebx), %eax + ja 3f + jb 4f + cmpl wakeup_seq-cond_futex(%ebx), %ebp + jna 4f + + /* Cause all currently waiting threads to recognize they are + woken up. */ +3: movl %ebp, wakeup_seq-cond_futex(%ebx) + movl %eax, wakeup_seq-cond_futex+4(%ebx) + movl %ebp, woken_seq-cond_futex(%ebx) + movl %eax, woken_seq-cond_futex+4(%ebx) + addl %ebp, %ebp + addl $1, broadcast_seq-cond_futex(%ebx) + movl %ebp, (%ebx) + + /* Get the address of the mutex used. */ + movl dep_mutex-cond_futex(%ebx), %edi + + /* Unlock. */ + LOCK + subl $1, cond_lock-cond_futex(%ebx) + jne 7f + + /* Don't use requeue for pshared condvars. */ +8: cmpl $-1, %edi + je 9f + + /* Do not use requeue for pshared condvars. */ + testl $PS_BIT, MUTEX_KIND(%edi) + jne 9f + + /* Requeue to a non-robust PI mutex if the PI bit is set and + the robust bit is not set. */ + movl MUTEX_KIND(%edi), %eax + andl $(ROBUST_BIT|PI_BIT), %eax + cmpl $PI_BIT, %eax + je 81f + + /* Wake up all threads. */ +#ifdef __ASSUME_PRIVATE_FUTEX + movl $(FUTEX_CMP_REQUEUE|FUTEX_PRIVATE_FLAG), %ecx +#else + movl %gs:PRIVATE_FUTEX, %ecx + orl $FUTEX_CMP_REQUEUE, %ecx +#endif + movl $SYS_futex, %eax + movl $0x7fffffff, %esi + movl $1, %edx + /* Get the address of the futex involved. */ +# if MUTEX_FUTEX != 0 + addl $MUTEX_FUTEX, %edi +# endif +/* FIXME: Until Ingo fixes 4G/4G vDSO, 6 arg syscalls are broken for sysenter. + ENTER_KERNEL */ + int $0x80 + + /* For any kind of error, which mainly is EAGAIN, we try again + with WAKE. The general test also covers running on old + kernels. */ + cmpl $0xfffff001, %eax + jae 9f + +6: xorl %eax, %eax + popl %ebp + cfi_adjust_cfa_offset(-4) + cfi_restore(%ebp) + popl %edi + cfi_adjust_cfa_offset(-4) + cfi_restore(%edi) + popl %esi + cfi_adjust_cfa_offset(-4) + cfi_restore(%esi) + popl %ebx + cfi_adjust_cfa_offset(-4) + cfi_restore(%ebx) + ret + + cfi_restore_state + +81: movl $(FUTEX_CMP_REQUEUE_PI|FUTEX_PRIVATE_FLAG), %ecx + movl $SYS_futex, %eax + movl $0x7fffffff, %esi + movl $1, %edx + /* Get the address of the futex involved. */ +# if MUTEX_FUTEX != 0 + addl $MUTEX_FUTEX, %edi +# endif + int $0x80 + + /* For any kind of error, which mainly is EAGAIN, we try again + with WAKE. The general test also covers running on old + kernels. */ + cmpl $0xfffff001, %eax + jb 6b + jmp 9f + + /* Initial locking failed. */ +1: +#if cond_lock == 0 + movl %ebx, %edx +#else + leal cond_lock(%ebx), %edx +#endif +#if (LLL_SHARED-LLL_PRIVATE) > 255 + xorl %ecx, %ecx +#endif + cmpl $-1, dep_mutex(%ebx) + setne %cl + subl $1, %ecx + andl $(LLL_SHARED-LLL_PRIVATE), %ecx +#if LLL_PRIVATE != 0 + addl $LLL_PRIVATE, %ecx +#endif + call __lll_lock_wait + jmp 2b + + .align 16 + /* Unlock. */ +4: LOCK + subl $1, cond_lock-cond_futex(%ebx) + je 6b + + /* Unlock in loop requires wakeup. */ +5: leal cond_lock-cond_futex(%ebx), %eax +#if (LLL_SHARED-LLL_PRIVATE) > 255 + xorl %ecx, %ecx +#endif + cmpl $-1, dep_mutex-cond_futex(%ebx) + setne %cl + subl $1, %ecx + andl $(LLL_SHARED-LLL_PRIVATE), %ecx +#if LLL_PRIVATE != 0 + addl $LLL_PRIVATE, %ecx +#endif + call __lll_unlock_wake + jmp 6b + + /* Unlock in loop requires wakeup. */ +7: leal cond_lock-cond_futex(%ebx), %eax +#if (LLL_SHARED-LLL_PRIVATE) > 255 + xorl %ecx, %ecx +#endif + cmpl $-1, dep_mutex-cond_futex(%ebx) + setne %cl + subl $1, %ecx + andl $(LLL_SHARED-LLL_PRIVATE), %ecx +#if LLL_PRIVATE != 0 + addl $LLL_PRIVATE, %ecx +#endif + call __lll_unlock_wake + jmp 8b + +9: /* The futex requeue functionality is not available. */ + movl $0x7fffffff, %edx +#if FUTEX_PRIVATE_FLAG > 255 + xorl %ecx, %ecx +#endif + cmpl $-1, dep_mutex-cond_futex(%ebx) + sete %cl + subl $1, %ecx +#ifdef __ASSUME_PRIVATE_FUTEX + andl $FUTEX_PRIVATE_FLAG, %ecx +#else + andl %gs:PRIVATE_FUTEX, %ecx +#endif + addl $FUTEX_WAKE, %ecx + movl $SYS_futex, %eax + ENTER_KERNEL + jmp 6b + cfi_endproc + .size __pthread_cond_broadcast, .-__pthread_cond_broadcast +weak_alias(__pthread_cond_broadcast, pthread_cond_broadcast) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_signal.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_signal.S new file mode 100644 index 00000000..118bc073 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_signal.S @@ -0,0 +1,216 @@ +/* Copyright (C) 2002,2003,2004,2005,2007,2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include +#include + + + .text + + /* int pthread_cond_signal (pthread_cond_t *cond) */ + .globl __pthread_cond_signal + .type __pthread_cond_signal, @function + .protected __pthread_cond_signal + .align 16 +__pthread_cond_signal: + + cfi_startproc + pushl %ebx + cfi_adjust_cfa_offset(4) + cfi_rel_offset(%ebx, 0) + pushl %edi + cfi_adjust_cfa_offset(4) + cfi_rel_offset(%edi, 0) + cfi_remember_state + + movl 12(%esp), %edi + + /* Get internal lock. */ + movl $1, %edx + xorl %eax, %eax + LOCK +#if cond_lock == 0 + cmpxchgl %edx, (%edi) +#else + cmpxchgl %edx, cond_lock(%edi) +#endif + jnz 1f + +2: leal cond_futex(%edi), %ebx + movl total_seq+4(%edi), %eax + movl total_seq(%edi), %ecx + cmpl wakeup_seq+4(%edi), %eax +#if cond_lock != 0 + /* Must use leal to preserve the flags. */ + leal cond_lock(%edi), %edi +#endif + ja 3f + jb 4f + cmpl wakeup_seq-cond_futex(%ebx), %ecx + jbe 4f + + /* Bump the wakeup number. */ +3: addl $1, wakeup_seq-cond_futex(%ebx) + adcl $0, wakeup_seq-cond_futex+4(%ebx) + addl $1, (%ebx) + + /* Wake up one thread. */ + pushl %esi + cfi_adjust_cfa_offset(4) + cfi_rel_offset(%esi, 0) + pushl %ebp + cfi_adjust_cfa_offset(4) + cfi_rel_offset(%ebp, 0) + +#if FUTEX_PRIVATE_FLAG > 255 + xorl %ecx, %ecx +#endif + cmpl $-1, dep_mutex-cond_futex(%ebx) + sete %cl + je 8f + + movl dep_mutex-cond_futex(%ebx), %edx + /* Requeue to a non-robust PI mutex if the PI bit is set and + the robust bit is not set. */ + movl MUTEX_KIND(%edx), %eax + andl $(ROBUST_BIT|PI_BIT), %eax + cmpl $PI_BIT, %eax + je 9f + +8: subl $1, %ecx +#ifdef __ASSUME_PRIVATE_FUTEX + andl $FUTEX_PRIVATE_FLAG, %ecx +#else + andl %gs:PRIVATE_FUTEX, %ecx +#endif + addl $FUTEX_WAKE_OP, %ecx + movl $SYS_futex, %eax + movl $1, %edx + movl $1, %esi + movl $FUTEX_OP_CLEAR_WAKE_IF_GT_ONE, %ebp + /* FIXME: Until Ingo fixes 4G/4G vDSO, 6 arg syscalls are broken for + sysenter. + ENTER_KERNEL */ + int $0x80 + popl %ebp + cfi_adjust_cfa_offset(-4) + cfi_restore(%ebp) + popl %esi + cfi_adjust_cfa_offset(-4) + cfi_restore(%esi) + + /* For any kind of error, we try again with WAKE. + The general test also covers running on old kernels. */ + cmpl $-4095, %eax + jae 7f + +6: xorl %eax, %eax + popl %edi + cfi_adjust_cfa_offset(-4) + cfi_restore(%edi) + popl %ebx + cfi_adjust_cfa_offset(-4) + cfi_restore(%ebx) + ret + + cfi_restore_state + +9: movl $(FUTEX_CMP_REQUEUE_PI|FUTEX_PRIVATE_FLAG), %ecx + movl $SYS_futex, %eax + movl $1, %edx + xorl %esi, %esi + movl dep_mutex-cond_futex(%ebx), %edi + movl (%ebx), %ebp + /* FIXME: Until Ingo fixes 4G/4G vDSO, 6 arg syscalls are broken for + sysenter. + ENTER_KERNEL */ + int $0x80 + popl %ebp + popl %esi + + leal -cond_futex(%ebx), %edi + + /* For any kind of error, we try again with WAKE. + The general test also covers running on old kernels. */ + cmpl $-4095, %eax + jb 4f + +7: +#ifdef __ASSUME_PRIVATE_FUTEX + andl $FUTEX_PRIVATE_FLAG, %ecx +#else + andl %gs:PRIVATE_FUTEX, %ecx +#endif + orl $FUTEX_WAKE, %ecx + + xorl $(FUTEX_WAKE ^ FUTEX_WAKE_OP), %ecx + movl $SYS_futex, %eax + /* %edx should be 1 already from $FUTEX_WAKE_OP syscall. + movl $1, %edx */ + ENTER_KERNEL + + /* Unlock. Note that at this point %edi always points to + cond_lock. */ +4: LOCK + subl $1, (%edi) + je 6b + + /* Unlock in loop requires wakeup. */ +5: movl %edi, %eax +#if (LLL_SHARED-LLL_PRIVATE) > 255 + xorl %ecx, %ecx +#endif + cmpl $-1, dep_mutex-cond_futex(%ebx) + setne %cl + subl $1, %ecx + andl $(LLL_SHARED-LLL_PRIVATE), %ecx +#if LLL_PRIVATE != 0 + addl $LLL_PRIVATE, %ecx +#endif + call __lll_unlock_wake + jmp 6b + + /* Initial locking failed. */ +1: +#if cond_lock == 0 + movl %edi, %edx +#else + leal cond_lock(%edi), %edx +#endif +#if (LLL_SHARED-LLL_PRIVATE) > 255 + xorl %ecx, %ecx +#endif + cmpl $-1, dep_mutex(%edi) + setne %cl + subl $1, %ecx + andl $(LLL_SHARED-LLL_PRIVATE), %ecx +#if LLL_PRIVATE != 0 + addl $LLL_PRIVATE, %ecx +#endif + call __lll_lock_wait + jmp 2b + + cfi_endproc + .size __pthread_cond_signal, .-__pthread_cond_signal +weak_alias(__pthread_cond_signal, pthread_cond_signal) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S new file mode 100644 index 00000000..3b61367e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_timedwait.S @@ -0,0 +1,698 @@ +/* Copyright (C) 2002-2004,2006-2007,2009,2010 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include + + + .text + +/* int pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex, + const struct timespec *abstime) */ + .globl __pthread_cond_timedwait + .type __pthread_cond_timedwait, @function + .protected __pthread_cond_timedwait + .align 16 +__pthread_cond_timedwait: +.LSTARTCODE: + cfi_startproc +#ifdef SHARED + cfi_personality(DW_EH_PE_pcrel | DW_EH_PE_sdata4 | DW_EH_PE_indirect, + DW.ref.__gcc_personality_v0) + cfi_lsda(DW_EH_PE_pcrel | DW_EH_PE_sdata4, .LexceptSTART) +#else + cfi_personality(DW_EH_PE_udata4, __gcc_personality_v0) + cfi_lsda(DW_EH_PE_udata4, .LexceptSTART) +#endif + + pushl %ebp + cfi_adjust_cfa_offset(4) + cfi_rel_offset(%ebp, 0) + pushl %edi + cfi_adjust_cfa_offset(4) + cfi_rel_offset(%edi, 0) + pushl %esi + cfi_adjust_cfa_offset(4) + cfi_rel_offset(%esi, 0) + pushl %ebx + cfi_adjust_cfa_offset(4) + cfi_rel_offset(%ebx, 0) + + movl 20(%esp), %ebx + movl 28(%esp), %ebp + + cmpl $1000000000, 4(%ebp) + movl $EINVAL, %eax + jae 18f + + /* Get internal lock. */ + movl $1, %edx + xorl %eax, %eax + LOCK +#if cond_lock == 0 + cmpxchgl %edx, (%ebx) +#else + cmpxchgl %edx, cond_lock(%ebx) +#endif + jnz 1f + + /* Store the reference to the mutex. If there is already a + different value in there this is a bad user bug. */ +2: cmpl $-1, dep_mutex(%ebx) + movl 24(%esp), %eax + je 17f + movl %eax, dep_mutex(%ebx) + + /* Unlock the mutex. */ +17: xorl %edx, %edx + call __pthread_mutex_unlock_usercnt + + testl %eax, %eax + jne 16f + + addl $1, total_seq(%ebx) + adcl $0, total_seq+4(%ebx) + addl $1, cond_futex(%ebx) + addl $(1 << nwaiters_shift), cond_nwaiters(%ebx) + +#define FRAME_SIZE 32 + subl $FRAME_SIZE, %esp + cfi_adjust_cfa_offset(FRAME_SIZE) + cfi_remember_state + + /* Get and store current wakeup_seq value. */ + movl wakeup_seq(%ebx), %edi + movl wakeup_seq+4(%ebx), %edx + movl broadcast_seq(%ebx), %eax + movl %edi, 12(%esp) + movl %edx, 16(%esp) + movl %eax, 20(%esp) + + /* Reset the pi-requeued flag. */ +8: movl $0, 24(%esp) + /* Get the current time. */ + movl %ebx, %edx +#ifdef __NR_clock_gettime + /* Get the clock number. */ + movl cond_nwaiters(%ebx), %ebx + andl $((1 << nwaiters_shift) - 1), %ebx + /* Only clocks 0 and 1 are allowed so far. Both are handled in the + kernel. */ + leal 4(%esp), %ecx + movl $__NR_clock_gettime, %eax + ENTER_KERNEL +# ifndef __ASSUME_POSIX_TIMERS + cmpl $-ENOSYS, %eax + je 19f +# endif + movl %edx, %ebx + + /* Compute relative timeout. */ + movl (%ebp), %ecx + movl 4(%ebp), %edx + subl 4(%esp), %ecx + subl 8(%esp), %edx +#else + /* Get the current time. */ + leal 4(%esp), %ebx + xorl %ecx, %ecx + movl $__NR_gettimeofday, %eax + ENTER_KERNEL + movl %edx, %ebx + + /* Compute relative timeout. */ + movl 8(%esp), %eax + movl $1000, %edx + mul %edx /* Milli seconds to nano seconds. */ + movl (%ebp), %ecx + movl 4(%ebp), %edx + subl 4(%esp), %ecx + subl %eax, %edx +#endif + jns 12f + addl $1000000000, %edx + subl $1, %ecx +12: testl %ecx, %ecx + movl $-ETIMEDOUT, %esi + js 6f + + /* Store relative timeout. */ +21: movl %ecx, 4(%esp) + movl %edx, 8(%esp) + + movl cond_futex(%ebx), %edi + movl %edi, 28(%esp) + + /* Unlock. */ + LOCK +#if cond_lock == 0 + subl $1, (%ebx) +#else + subl $1, cond_lock(%ebx) +#endif + jne 3f + +.LcleanupSTART: +4: call __pthread_enable_asynccancel + movl %eax, (%esp) + +#if FUTEX_PRIVATE_FLAG > 255 + xorl %ecx, %ecx +#endif + cmpl $-1, dep_mutex(%ebx) + sete %cl + je 40f + + movl dep_mutex(%ebx), %edi + /* Requeue to a non-robust PI mutex if the PI bit is set and + the robust bit is not set. */ + movl MUTEX_KIND(%edi), %eax + andl $(ROBUST_BIT|PI_BIT), %eax + cmpl $PI_BIT, %eax + jne 40f + + movl $(FUTEX_WAIT_REQUEUE_PI|FUTEX_PRIVATE_FLAG), %ecx + /* The following only works like this because we only support + two clocks, represented using a single bit. */ + testl $1, cond_nwaiters(%ebx) + /* XXX Need to implement using sete instead of a jump. */ + jne 42f + orl $FUTEX_CLOCK_REALTIME, %ecx + + /* Requeue-PI uses absolute timeout */ +42: leal (%ebp), %esi + movl 28(%esp), %edx + addl $cond_futex, %ebx + movl $SYS_futex, %eax + ENTER_KERNEL + subl $cond_futex, %ebx + movl %eax, %esi + /* Set the pi-requeued flag only if the kernel has returned 0. The + kernel does not hold the mutex on ETIMEDOUT or any other error. */ + cmpl $0, %eax + sete 24(%esp) + je 41f + + /* Normal and PI futexes dont mix. Use normal futex functions only + if the kernel does not support the PI futex functions. */ + cmpl $-ENOSYS, %eax + jne 41f + xorl %ecx, %ecx + +40: subl $1, %ecx +#ifdef __ASSUME_PRIVATE_FUTEX + andl $FUTEX_PRIVATE_FLAG, %ecx +#else + andl %gs:PRIVATE_FUTEX, %ecx +#endif +#if FUTEX_WAIT != 0 + addl $FUTEX_WAIT, %ecx +#endif + leal 4(%esp), %esi + movl 28(%esp), %edx + addl $cond_futex, %ebx +.Ladd_cond_futex: + movl $SYS_futex, %eax + ENTER_KERNEL + subl $cond_futex, %ebx +.Lsub_cond_futex: + movl %eax, %esi + +41: movl (%esp), %eax + call __pthread_disable_asynccancel +.LcleanupEND: + + /* Lock. */ + movl $1, %edx + xorl %eax, %eax + LOCK +#if cond_lock == 0 + cmpxchgl %edx, (%ebx) +#else + cmpxchgl %edx, cond_lock(%ebx) +#endif + jnz 5f + +6: movl broadcast_seq(%ebx), %eax + cmpl 20(%esp), %eax + jne 23f + + movl woken_seq(%ebx), %eax + movl woken_seq+4(%ebx), %ecx + + movl wakeup_seq(%ebx), %edi + movl wakeup_seq+4(%ebx), %edx + + cmpl 16(%esp), %edx + jne 7f + cmpl 12(%esp), %edi + je 15f + +7: cmpl %ecx, %edx + jne 9f + cmp %eax, %edi + jne 9f + +15: cmpl $-ETIMEDOUT, %esi + jne 8b + + addl $1, wakeup_seq(%ebx) + adcl $0, wakeup_seq+4(%ebx) + addl $1, cond_futex(%ebx) + movl $ETIMEDOUT, %esi + jmp 14f + +23: xorl %esi, %esi + jmp 24f + +9: xorl %esi, %esi +14: addl $1, woken_seq(%ebx) + adcl $0, woken_seq+4(%ebx) + +24: subl $(1 << nwaiters_shift), cond_nwaiters(%ebx) + + /* Wake up a thread which wants to destroy the condvar object. */ + movl total_seq(%ebx), %eax + andl total_seq+4(%ebx), %eax + cmpl $0xffffffff, %eax + jne 25f + movl cond_nwaiters(%ebx), %eax + andl $~((1 << nwaiters_shift) - 1), %eax + jne 25f + + addl $cond_nwaiters, %ebx + movl $SYS_futex, %eax +#if FUTEX_PRIVATE_FLAG > 255 + xorl %ecx, %ecx +#endif + cmpl $-1, dep_mutex-cond_nwaiters(%ebx) + sete %cl + subl $1, %ecx +#ifdef __ASSUME_PRIVATE_FUTEX + andl $FUTEX_PRIVATE_FLAG, %ecx +#else + andl %gs:PRIVATE_FUTEX, %ecx +#endif + addl $FUTEX_WAKE, %ecx + movl $1, %edx + ENTER_KERNEL + subl $cond_nwaiters, %ebx + +25: LOCK +#if cond_lock == 0 + subl $1, (%ebx) +#else + subl $1, cond_lock(%ebx) +#endif + jne 10f + +11: movl 24+FRAME_SIZE(%esp), %eax + /* With requeue_pi, the mutex lock is held in the kernel. */ + movl 24(%esp), %ecx + testl %ecx, %ecx + jnz 27f + + call __pthread_mutex_cond_lock +26: addl $FRAME_SIZE, %esp + cfi_adjust_cfa_offset(-FRAME_SIZE); + + /* We return the result of the mutex_lock operation if it failed. */ + testl %eax, %eax +#ifdef HAVE_CMOV + cmovel %esi, %eax +#else + jne 22f + movl %esi, %eax +22: +#endif + +18: popl %ebx + cfi_adjust_cfa_offset(-4) + cfi_restore(%ebx) + popl %esi + cfi_adjust_cfa_offset(-4) + cfi_restore(%esi) + popl %edi + cfi_adjust_cfa_offset(-4) + cfi_restore(%edi) + popl %ebp + cfi_adjust_cfa_offset(-4) + cfi_restore(%ebp) + + ret + + cfi_restore_state + +27: call __pthread_mutex_cond_lock_adjust + xorl %eax, %eax + jmp 26b + + cfi_adjust_cfa_offset(-FRAME_SIZE); + /* Initial locking failed. */ +1: +#if cond_lock == 0 + movl %ebx, %edx +#else + leal cond_lock(%ebx), %edx +#endif +#if (LLL_SHARED-LLL_PRIVATE) > 255 + xorl %ecx, %ecx +#endif + cmpl $-1, dep_mutex(%ebx) + setne %cl + subl $1, %ecx + andl $(LLL_SHARED-LLL_PRIVATE), %ecx +#if LLL_PRIVATE != 0 + addl $LLL_PRIVATE, %ecx +#endif + call __lll_lock_wait + jmp 2b + + /* The initial unlocking of the mutex failed. */ +16: + LOCK +#if cond_lock == 0 + subl $1, (%ebx) +#else + subl $1, cond_lock(%ebx) +#endif + jne 18b + + movl %eax, %esi +#if cond_lock == 0 + movl %ebx, %eax +#else + leal cond_lock(%ebx), %eax +#endif +#if (LLL_SHARED-LLL_PRIVATE) > 255 + xorl %ecx, %ecx +#endif + cmpl $-1, dep_mutex(%ebx) + setne %cl + subl $1, %ecx + andl $(LLL_SHARED-LLL_PRIVATE), %ecx +#if LLL_PRIVATE != 0 + addl $LLL_PRIVATE, %ecx +#endif + call __lll_unlock_wake + + movl %esi, %eax + jmp 18b + + cfi_adjust_cfa_offset(FRAME_SIZE) + + /* Unlock in loop requires wakeup. */ +3: +#if cond_lock == 0 + movl %ebx, %eax +#else + leal cond_lock(%ebx), %eax +#endif +#if (LLL_SHARED-LLL_PRIVATE) > 255 + xorl %ecx, %ecx +#endif + cmpl $-1, dep_mutex(%ebx) + setne %cl + subl $1, %ecx + andl $(LLL_SHARED-LLL_PRIVATE), %ecx +#if LLL_PRIVATE != 0 + addl $LLL_PRIVATE, %ecx +#endif + call __lll_unlock_wake + jmp 4b + + /* Locking in loop failed. */ +5: +#if cond_lock == 0 + movl %ebx, %edx +#else + leal cond_lock(%ebx), %edx +#endif +#if (LLL_SHARED-LLL_PRIVATE) > 255 + xorl %ecx, %ecx +#endif + cmpl $-1, dep_mutex(%ebx) + setne %cl + subl $1, %ecx + andl $(LLL_SHARED-LLL_PRIVATE), %ecx +#if LLL_PRIVATE != 0 + addl $LLL_PRIVATE, %ecx +#endif + call __lll_lock_wait + jmp 6b + + /* Unlock after loop requires wakeup. */ +10: +#if cond_lock == 0 + movl %ebx, %eax +#else + leal cond_lock(%ebx), %eax +#endif +#if (LLL_SHARED-LLL_PRIVATE) > 255 + xorl %ecx, %ecx +#endif + cmpl $-1, dep_mutex(%ebx) + setne %cl + subl $1, %ecx + andl $(LLL_SHARED-LLL_PRIVATE), %ecx +#if LLL_PRIVATE != 0 + addl $LLL_PRIVATE, %ecx +#endif + call __lll_unlock_wake + jmp 11b + +#if defined __NR_clock_gettime && !defined __ASSUME_POSIX_TIMERS + /* clock_gettime not available. */ +19: leal 4(%esp), %ebx + xorl %ecx, %ecx + movl $__NR_gettimeofday, %eax + ENTER_KERNEL + movl %edx, %ebx + + /* Compute relative timeout. */ + movl 8(%esp), %eax + movl $1000, %edx + mul %edx /* Milli seconds to nano seconds. */ + movl (%ebp), %ecx + movl 4(%ebp), %edx + subl 4(%esp), %ecx + subl %eax, %edx + jns 20f + addl $1000000000, %edx + subl $1, %ecx +20: testl %ecx, %ecx + movl $-ETIMEDOUT, %esi + js 6b + jmp 21b +#endif + .size __pthread_cond_timedwait, .-__pthread_cond_timedwait +weak_alias(__pthread_cond_timedwait, pthread_cond_timedwait) + + + .type __condvar_tw_cleanup2, @function +__condvar_tw_cleanup2: + subl $cond_futex, %ebx + .size __condvar_tw_cleanup2, .-__condvar_tw_cleanup2 + .type __condvar_tw_cleanup, @function +__condvar_tw_cleanup: + movl %eax, %esi + + /* Get internal lock. */ + movl $1, %edx + xorl %eax, %eax + LOCK +#if cond_lock == 0 + cmpxchgl %edx, (%ebx) +#else + cmpxchgl %edx, cond_lock(%ebx) +#endif + jz 1f + +#if cond_lock == 0 + movl %ebx, %edx +#else + leal cond_lock(%ebx), %edx +#endif +#if (LLL_SHARED-LLL_PRIVATE) > 255 + xorl %ecx, %ecx +#endif + cmpl $-1, dep_mutex(%ebx) + setne %cl + subl $1, %ecx + andl $(LLL_SHARED-LLL_PRIVATE), %ecx +#if LLL_PRIVATE != 0 + addl $LLL_PRIVATE, %ecx +#endif + call __lll_lock_wait + +1: movl broadcast_seq(%ebx), %eax + cmpl 20(%esp), %eax + jne 3f + + /* We increment the wakeup_seq counter only if it is lower than + total_seq. If this is not the case the thread was woken and + then canceled. In this case we ignore the signal. */ + movl total_seq(%ebx), %eax + movl total_seq+4(%ebx), %edi + cmpl wakeup_seq+4(%ebx), %edi + jb 6f + ja 7f + cmpl wakeup_seq(%ebx), %eax + jbe 7f + +6: addl $1, wakeup_seq(%ebx) + adcl $0, wakeup_seq+4(%ebx) + addl $1, cond_futex(%ebx) + +7: addl $1, woken_seq(%ebx) + adcl $0, woken_seq+4(%ebx) + +3: subl $(1 << nwaiters_shift), cond_nwaiters(%ebx) + + /* Wake up a thread which wants to destroy the condvar object. */ + xorl %edi, %edi + movl total_seq(%ebx), %eax + andl total_seq+4(%ebx), %eax + cmpl $0xffffffff, %eax + jne 4f + movl cond_nwaiters(%ebx), %eax + andl $~((1 << nwaiters_shift) - 1), %eax + jne 4f + + addl $cond_nwaiters, %ebx + movl $SYS_futex, %eax +#if FUTEX_PRIVATE_FLAG > 255 + xorl %ecx, %ecx +#endif + cmpl $-1, dep_mutex-cond_nwaiters(%ebx) + sete %cl + subl $1, %ecx +#ifdef __ASSUME_PRIVATE_FUTEX + andl $FUTEX_PRIVATE_FLAG, %ecx +#else + andl %gs:PRIVATE_FUTEX, %ecx +#endif + addl $FUTEX_WAKE, %ecx + movl $1, %edx + ENTER_KERNEL + subl $cond_nwaiters, %ebx + movl $1, %edi + +4: LOCK +#if cond_lock == 0 + subl $1, (%ebx) +#else + subl $1, cond_lock(%ebx) +#endif + je 2f + +#if cond_lock == 0 + movl %ebx, %eax +#else + leal cond_lock(%ebx), %eax +#endif +#if (LLL_SHARED-LLL_PRIVATE) > 255 + xorl %ecx, %ecx +#endif + cmpl $-1, dep_mutex(%ebx) + setne %cl + subl $1, %ecx + andl $(LLL_SHARED-LLL_PRIVATE), %ecx +#if LLL_PRIVATE != 0 + addl $LLL_PRIVATE, %ecx +#endif + call __lll_unlock_wake + + /* Wake up all waiters to make sure no signal gets lost. */ +2: testl %edi, %edi + jnz 5f + addl $cond_futex, %ebx +#if FUTEX_PRIVATE_FLAG > 255 + xorl %ecx, %ecx +#endif + cmpl $-1, dep_mutex-cond_futex(%ebx) + sete %cl + subl $1, %ecx +#ifdef __ASSUME_PRIVATE_FUTEX + andl $FUTEX_PRIVATE_FLAG, %ecx +#else + andl %gs:PRIVATE_FUTEX, %ecx +#endif + addl $FUTEX_WAKE, %ecx + movl $SYS_futex, %eax + movl $0x7fffffff, %edx + ENTER_KERNEL + +5: movl 24+FRAME_SIZE(%esp), %eax + call __pthread_mutex_cond_lock + + movl %esi, (%esp) +.LcallUR: +#ifdef __PIC__ + call __i686.get_pc_thunk.bx + addl $_GLOBAL_OFFSET_TABLE_, %ebx +#endif + call _Unwind_Resume@PLT + hlt +.LENDCODE: + cfi_endproc + .size __condvar_tw_cleanup, .-__condvar_tw_cleanup + + + .section .gcc_except_table,"a",@progbits +.LexceptSTART: + .byte DW_EH_PE_omit # @LPStart format (omit) + .byte DW_EH_PE_omit # @TType format (omit) + .byte DW_EH_PE_sdata4 # call-site format + # DW_EH_PE_sdata4 + .uleb128 .Lcstend-.Lcstbegin +.Lcstbegin: + .long .LcleanupSTART-.LSTARTCODE + .long .Ladd_cond_futex-.LcleanupSTART + .long __condvar_tw_cleanup-.LSTARTCODE + .uleb128 0 + .long .Ladd_cond_futex-.LSTARTCODE + .long .Lsub_cond_futex-.Ladd_cond_futex + .long __condvar_tw_cleanup2-.LSTARTCODE + .uleb128 0 + .long .Lsub_cond_futex-.LSTARTCODE + .long .LcleanupEND-.Lsub_cond_futex + .long __condvar_tw_cleanup-.LSTARTCODE + .uleb128 0 + .long .LcallUR-.LSTARTCODE + .long .LENDCODE-.LcallUR + .long 0 + .uleb128 0 +.Lcstend: + + +#ifdef SHARED + .hidden DW.ref.__gcc_personality_v0 + .weak DW.ref.__gcc_personality_v0 + .section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits + .align 4 + .type DW.ref.__gcc_personality_v0, @object + .size DW.ref.__gcc_personality_v0, 4 +DW.ref.__gcc_personality_v0: + .long __gcc_personality_v0 +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S new file mode 100644 index 00000000..a1294c50 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_cond_wait.S @@ -0,0 +1,595 @@ +/* Copyright (C) 2002-2004,2006-2007,2009,2010 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include +#include + + + .text + +/* int pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex) */ + .globl __pthread_cond_wait + .type __pthread_cond_wait, @function + .protected __pthread_cond_wait + .align 16 +__pthread_cond_wait: +.LSTARTCODE: + cfi_startproc +#ifdef SHARED + cfi_personality(DW_EH_PE_pcrel | DW_EH_PE_sdata4 | DW_EH_PE_indirect, + DW.ref.__gcc_personality_v0) + cfi_lsda(DW_EH_PE_pcrel | DW_EH_PE_sdata4, .LexceptSTART) +#else + cfi_personality(DW_EH_PE_udata4, __gcc_personality_v0) + cfi_lsda(DW_EH_PE_udata4, .LexceptSTART) +#endif + + pushl %ebp + cfi_adjust_cfa_offset(4) + cfi_rel_offset(%ebp, 0) + pushl %edi + cfi_adjust_cfa_offset(4) + cfi_rel_offset(%edi, 0) + pushl %esi + cfi_adjust_cfa_offset(4) + cfi_rel_offset(%esi, 0) + pushl %ebx + cfi_adjust_cfa_offset(4) + cfi_rel_offset(%ebx, 0) + + xorl %esi, %esi + movl 20(%esp), %ebx + + /* Get internal lock. */ + movl $1, %edx + xorl %eax, %eax + LOCK +#if cond_lock == 0 + cmpxchgl %edx, (%ebx) +#else + cmpxchgl %edx, cond_lock(%ebx) +#endif + jnz 1f + + /* Store the reference to the mutex. If there is already a + different value in there this is a bad user bug. */ +2: cmpl $-1, dep_mutex(%ebx) + movl 24(%esp), %eax + je 15f + movl %eax, dep_mutex(%ebx) + + /* Unlock the mutex. */ +15: xorl %edx, %edx + call __pthread_mutex_unlock_usercnt + + testl %eax, %eax + jne 12f + + addl $1, total_seq(%ebx) + adcl $0, total_seq+4(%ebx) + addl $1, cond_futex(%ebx) + addl $(1 << nwaiters_shift), cond_nwaiters(%ebx) + +#define FRAME_SIZE 20 + subl $FRAME_SIZE, %esp + cfi_adjust_cfa_offset(FRAME_SIZE) + cfi_remember_state + + /* Get and store current wakeup_seq value. */ + movl wakeup_seq(%ebx), %edi + movl wakeup_seq+4(%ebx), %edx + movl broadcast_seq(%ebx), %eax + movl %edi, 4(%esp) + movl %edx, 8(%esp) + movl %eax, 12(%esp) + + /* Reset the pi-requeued flag. */ +8: movl $0, 16(%esp) + movl cond_futex(%ebx), %ebp + + /* Unlock. */ + LOCK +#if cond_lock == 0 + subl $1, (%ebx) +#else + subl $1, cond_lock(%ebx) +#endif + jne 3f + +.LcleanupSTART: +4: call __pthread_enable_asynccancel + movl %eax, (%esp) + + xorl %ecx, %ecx + cmpl $-1, dep_mutex(%ebx) + sete %cl + je 18f + + movl dep_mutex(%ebx), %edi + /* Requeue to a non-robust PI mutex if the PI bit is set and + the robust bit is not set. */ + movl MUTEX_KIND(%edi), %eax + andl $(ROBUST_BIT|PI_BIT), %eax + cmpl $PI_BIT, %eax + jne 18f + + movl $(FUTEX_WAIT_REQUEUE_PI|FUTEX_PRIVATE_FLAG), %ecx + movl %ebp, %edx + xorl %esi, %esi + addl $cond_futex, %ebx + movl $SYS_futex, %eax + ENTER_KERNEL + subl $cond_futex, %ebx + /* Set the pi-requeued flag only if the kernel has returned 0. The + kernel does not hold the mutex on error. */ + cmpl $0, %eax + sete 16(%esp) + je 19f + + /* Normal and PI futexes dont mix. Use normal futex functions only + if the kernel does not support the PI futex functions. */ + cmpl $-ENOSYS, %eax + jne 19f + xorl %ecx, %ecx + +18: subl $1, %ecx +#ifdef __ASSUME_PRIVATE_FUTEX + andl $FUTEX_PRIVATE_FLAG, %ecx +#else + andl %gs:PRIVATE_FUTEX, %ecx +#endif +#if FUTEX_WAIT != 0 + addl $FUTEX_WAIT, %ecx +#endif + movl %ebp, %edx + addl $cond_futex, %ebx +.Ladd_cond_futex: + movl $SYS_futex, %eax + ENTER_KERNEL + subl $cond_futex, %ebx +.Lsub_cond_futex: + +19: movl (%esp), %eax + call __pthread_disable_asynccancel +.LcleanupEND: + + /* Lock. */ + movl $1, %edx + xorl %eax, %eax + LOCK +#if cond_lock == 0 + cmpxchgl %edx, (%ebx) +#else + cmpxchgl %edx, cond_lock(%ebx) +#endif + jnz 5f + +6: movl broadcast_seq(%ebx), %eax + cmpl 12(%esp), %eax + jne 16f + + movl woken_seq(%ebx), %eax + movl woken_seq+4(%ebx), %ecx + + movl wakeup_seq(%ebx), %edi + movl wakeup_seq+4(%ebx), %edx + + cmpl 8(%esp), %edx + jne 7f + cmpl 4(%esp), %edi + je 8b + +7: cmpl %ecx, %edx + jne 9f + cmp %eax, %edi + je 8b + +9: addl $1, woken_seq(%ebx) + adcl $0, woken_seq+4(%ebx) + + /* Unlock */ +16: subl $(1 << nwaiters_shift), cond_nwaiters(%ebx) + + /* Wake up a thread which wants to destroy the condvar object. */ + movl total_seq(%ebx), %eax + andl total_seq+4(%ebx), %eax + cmpl $0xffffffff, %eax + jne 17f + movl cond_nwaiters(%ebx), %eax + andl $~((1 << nwaiters_shift) - 1), %eax + jne 17f + + addl $cond_nwaiters, %ebx + movl $SYS_futex, %eax +#if FUTEX_PRIVATE_FLAG > 255 + xorl %ecx, %ecx +#endif + cmpl $-1, dep_mutex-cond_nwaiters(%ebx) + sete %cl + subl $1, %ecx +#ifdef __ASSUME_PRIVATE_FUTEX + andl $FUTEX_PRIVATE_FLAG, %ecx +#else + andl %gs:PRIVATE_FUTEX, %ecx +#endif + addl $FUTEX_WAKE, %ecx + movl $1, %edx + ENTER_KERNEL + subl $cond_nwaiters, %ebx + +17: LOCK +#if cond_lock == 0 + subl $1, (%ebx) +#else + subl $1, cond_lock(%ebx) +#endif + jne 10f + + /* With requeue_pi, the mutex lock is held in the kernel. */ +11: movl 24+FRAME_SIZE(%esp), %eax + movl 16(%esp), %ecx + testl %ecx, %ecx + jnz 21f + + call __pthread_mutex_cond_lock +20: addl $FRAME_SIZE, %esp + cfi_adjust_cfa_offset(-FRAME_SIZE); + +14: popl %ebx + cfi_adjust_cfa_offset(-4) + cfi_restore(%ebx) + popl %esi + cfi_adjust_cfa_offset(-4) + cfi_restore(%esi) + popl %edi + cfi_adjust_cfa_offset(-4) + cfi_restore(%edi) + popl %ebp + cfi_adjust_cfa_offset(-4) + cfi_restore(%ebp) + + /* We return the result of the mutex_lock operation. */ + ret + + cfi_restore_state + +21: call __pthread_mutex_cond_lock_adjust + xorl %eax, %eax + jmp 20b + + cfi_adjust_cfa_offset(-FRAME_SIZE); + /* Initial locking failed. */ +1: +#if cond_lock == 0 + movl %ebx, %edx +#else + leal cond_lock(%ebx), %edx +#endif +#if (LLL_SHARED-LLL_PRIVATE) > 255 + xorl %ecx, %ecx +#endif + cmpl $-1, dep_mutex(%ebx) + setne %cl + subl $1, %ecx + andl $(LLL_SHARED-LLL_PRIVATE), %ecx +#if LLL_PRIVATE != 0 + addl $LLL_PRIVATE, %ecx +#endif + call __lll_lock_wait + jmp 2b + + /* The initial unlocking of the mutex failed. */ +12: + LOCK +#if cond_lock == 0 + subl $1, (%ebx) +#else + subl $1, cond_lock(%ebx) +#endif + jne 14b + + movl %eax, %esi +#if cond_lock == 0 + movl %ebx, %eax +#else + leal cond_lock(%ebx), %eax +#endif +#if (LLL_SHARED-LLL_PRIVATE) > 255 + xorl %ecx, %ecx +#endif + cmpl $-1, dep_mutex(%ebx) + setne %cl + subl $1, %ecx + andl $(LLL_SHARED-LLL_PRIVATE), %ecx +#if LLL_PRIVATE != 0 + addl $LLL_PRIVATE, %ecx +#endif + call __lll_unlock_wake + + movl %esi, %eax + jmp 14b + + cfi_adjust_cfa_offset(FRAME_SIZE) + + /* Unlock in loop requires wakeup. */ +3: +#if cond_lock == 0 + movl %ebx, %eax +#else + leal cond_lock(%ebx), %eax +#endif +#if (LLL_SHARED-LLL_PRIVATE) > 255 + xorl %ecx, %ecx +#endif + cmpl $-1, dep_mutex(%ebx) + setne %cl + subl $1, %ecx + andl $(LLL_SHARED-LLL_PRIVATE), %ecx +#if LLL_PRIVATE != 0 + addl $LLL_PRIVATE, %ecx +#endif + call __lll_unlock_wake + jmp 4b + + /* Locking in loop failed. */ +5: +#if cond_lock == 0 + movl %ebx, %edx +#else + leal cond_lock(%ebx), %edx +#endif +#if (LLL_SHARED-LLL_PRIVATE) > 255 + xorl %ecx, %ecx +#endif + cmpl $-1, dep_mutex(%ebx) + setne %cl + subl $1, %ecx + andl $(LLL_SHARED-LLL_PRIVATE), %ecx +#if LLL_PRIVATE != 0 + addl $LLL_PRIVATE, %ecx +#endif + call __lll_lock_wait + jmp 6b + + /* Unlock after loop requires wakeup. */ +10: +#if cond_lock == 0 + movl %ebx, %eax +#else + leal cond_lock(%ebx), %eax +#endif +#if (LLL_SHARED-LLL_PRIVATE) > 255 + xorl %ecx, %ecx +#endif + cmpl $-1, dep_mutex(%ebx) + setne %cl + subl $1, %ecx + andl $(LLL_SHARED-LLL_PRIVATE), %ecx +#if LLL_PRIVATE != 0 + addl $LLL_PRIVATE, %ecx +#endif + call __lll_unlock_wake + jmp 11b + .size __pthread_cond_wait, .-__pthread_cond_wait +weak_alias(__pthread_cond_wait, pthread_cond_wait) + + + .type __condvar_w_cleanup2, @function +__condvar_w_cleanup2: + subl $cond_futex, %ebx + .size __condvar_w_cleanup2, .-__condvar_w_cleanup2 +.LSbl4: + .type __condvar_w_cleanup, @function +__condvar_w_cleanup: + movl %eax, %esi + + /* Get internal lock. */ + movl $1, %edx + xorl %eax, %eax + LOCK +#if cond_lock == 0 + cmpxchgl %edx, (%ebx) +#else + cmpxchgl %edx, cond_lock(%ebx) +#endif + jz 1f + +#if cond_lock == 0 + movl %ebx, %edx +#else + leal cond_lock(%ebx), %edx +#endif +#if (LLL_SHARED-LLL_PRIVATE) > 255 + xorl %ecx, %ecx +#endif + cmpl $-1, dep_mutex(%ebx) + setne %cl + subl $1, %ecx + andl $(LLL_SHARED-LLL_PRIVATE), %ecx +#if LLL_PRIVATE != 0 + addl $LLL_PRIVATE, %ecx +#endif + call __lll_lock_wait + +1: movl broadcast_seq(%ebx), %eax + cmpl 12(%esp), %eax + jne 3f + + /* We increment the wakeup_seq counter only if it is lower than + total_seq. If this is not the case the thread was woken and + then canceled. In this case we ignore the signal. */ + movl total_seq(%ebx), %eax + movl total_seq+4(%ebx), %edi + cmpl wakeup_seq+4(%ebx), %edi + jb 6f + ja 7f + cmpl wakeup_seq(%ebx), %eax + jbe 7f + +6: addl $1, wakeup_seq(%ebx) + adcl $0, wakeup_seq+4(%ebx) + addl $1, cond_futex(%ebx) + +7: addl $1, woken_seq(%ebx) + adcl $0, woken_seq+4(%ebx) + +3: subl $(1 << nwaiters_shift), cond_nwaiters(%ebx) + + /* Wake up a thread which wants to destroy the condvar object. */ + xorl %edi, %edi + movl total_seq(%ebx), %eax + andl total_seq+4(%ebx), %eax + cmpl $0xffffffff, %eax + jne 4f + movl cond_nwaiters(%ebx), %eax + andl $~((1 << nwaiters_shift) - 1), %eax + jne 4f + + addl $cond_nwaiters, %ebx + movl $SYS_futex, %eax +#if FUTEX_PRIVATE_FLAG > 255 + xorl %ecx, %ecx +#endif + cmpl $-1, dep_mutex-cond_nwaiters(%ebx) + sete %cl + subl $1, %ecx +#ifdef __ASSUME_PRIVATE_FUTEX + andl $FUTEX_PRIVATE_FLAG, %ecx +#else + andl %gs:PRIVATE_FUTEX, %ecx +#endif + addl $FUTEX_WAKE, %ecx + movl $1, %edx + ENTER_KERNEL + subl $cond_nwaiters, %ebx + movl $1, %edi + +4: LOCK +#if cond_lock == 0 + subl $1, (%ebx) +#else + subl $1, cond_lock(%ebx) +#endif + je 2f + +#if cond_lock == 0 + movl %ebx, %eax +#else + leal cond_lock(%ebx), %eax +#endif +#if (LLL_SHARED-LLL_PRIVATE) > 255 + xorl %ecx, %ecx +#endif + cmpl $-1, dep_mutex(%ebx) + setne %cl + subl $1, %ecx + andl $(LLL_SHARED-LLL_PRIVATE), %ecx +#if LLL_PRIVATE != 0 + addl $LLL_PRIVATE, %ecx +#endif + call __lll_unlock_wake + + /* Wake up all waiters to make sure no signal gets lost. */ +2: testl %edi, %edi + jnz 5f + addl $cond_futex, %ebx +#if FUTEX_PRIVATE_FLAG > 255 + xorl %ecx, %ecx +#endif + cmpl $-1, dep_mutex-cond_futex(%ebx) + sete %cl + subl $1, %ecx +#ifdef __ASSUME_PRIVATE_FUTEX + andl $FUTEX_PRIVATE_FLAG, %ecx +#else + andl %gs:PRIVATE_FUTEX, %ecx +#endif + addl $FUTEX_WAKE, %ecx + movl $SYS_futex, %eax + movl $0x7fffffff, %edx + ENTER_KERNEL + +5: movl 24+FRAME_SIZE(%esp), %eax + call __pthread_mutex_cond_lock + + movl %esi, (%esp) +.LcallUR: +#ifdef __PIC__ + call __i686.get_pc_thunk.bx + addl $_GLOBAL_OFFSET_TABLE_, %ebx +#endif + call _Unwind_Resume@PLT + hlt +.LENDCODE: + cfi_endproc + .size __condvar_w_cleanup, .-__condvar_w_cleanup + + + .section .gcc_except_table,"a",@progbits +.LexceptSTART: + .byte DW_EH_PE_omit # @LPStart format (omit) + .byte DW_EH_PE_omit # @TType format (omit) + .byte DW_EH_PE_sdata4 # call-site format + # DW_EH_PE_sdata4 + .uleb128 .Lcstend-.Lcstbegin +.Lcstbegin: + .long .LcleanupSTART-.LSTARTCODE + .long .Ladd_cond_futex-.LcleanupSTART + .long __condvar_w_cleanup-.LSTARTCODE + .uleb128 0 + .long .Ladd_cond_futex-.LSTARTCODE + .long .Lsub_cond_futex-.Ladd_cond_futex + .long __condvar_w_cleanup2-.LSTARTCODE + .uleb128 0 + .long .Lsub_cond_futex-.LSTARTCODE + .long .LcleanupEND-.Lsub_cond_futex + .long __condvar_w_cleanup-.LSTARTCODE + .uleb128 0 + .long .LcallUR-.LSTARTCODE + .long .LENDCODE-.LcallUR + .long 0 + .uleb128 0 +.Lcstend: + +#ifdef __PIC__ + .section .gnu.linkonce.t.__i686.get_pc_thunk.bx,"ax",@progbits + .globl __i686.get_pc_thunk.bx + .hidden __i686.get_pc_thunk.bx + .type __i686.get_pc_thunk.bx,@function +__i686.get_pc_thunk.bx: + movl (%esp), %ebx; + ret + .size __i686.get_pc_thunk.bx,.-__i686.get_pc_thunk.bx +#endif + +#ifdef SHARED + .hidden DW.ref.__gcc_personality_v0 + .weak DW.ref.__gcc_personality_v0 + .section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits + .align 4 + .type DW.ref.__gcc_personality_v0, @object + .size DW.ref.__gcc_personality_v0, 4 +DW.ref.__gcc_personality_v0: + .long __gcc_personality_v0 +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_rdlock.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_rdlock.S new file mode 100644 index 00000000..79501bd5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_rdlock.S @@ -0,0 +1,195 @@ +/* Copyright (C) 2002, 2003, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include + + + .text + + .globl __pthread_rwlock_rdlock + .type __pthread_rwlock_rdlock,@function + .protected __pthread_rwlock_rdlock + .align 16 +__pthread_rwlock_rdlock: + cfi_startproc + pushl %esi + cfi_adjust_cfa_offset(4) + pushl %ebx + cfi_adjust_cfa_offset(4) + cfi_offset(%esi, -8) + cfi_offset(%ebx, -12) + + xorl %esi, %esi + movl 12(%esp), %ebx + + /* Get the lock. */ + movl $1, %edx + xorl %eax, %eax + LOCK +#if MUTEX == 0 + cmpxchgl %edx, (%ebx) +#else + cmpxchgl %edx, MUTEX(%ebx) +#endif + jnz 1f + +2: movl WRITER(%ebx), %eax + testl %eax, %eax + jne 14f + cmpl $0, WRITERS_QUEUED(%ebx) + je 5f + cmpb $0, FLAGS(%ebx) + je 5f + +3: addl $1, READERS_QUEUED(%ebx) + je 4f + + movl READERS_WAKEUP(%ebx), %edx + + LOCK +#if MUTEX == 0 + subl $1, (%ebx) +#else + subl $1, MUTEX(%ebx) +#endif + jne 10f + +11: +#ifdef __ASSUME_PRIVATE_FUTEX + movzbl PSHARED(%ebx), %ecx + xorl $FUTEX_PRIVATE_FLAG|FUTEX_WAIT, %ecx +#else + movzbl PSHARED(%ebx), %ecx +# if FUTEX_WAIT != 0 + orl $FUTEX_WAIT, %ecx +# endif + xorl %gs:PRIVATE_FUTEX, %ecx +#endif + addl $READERS_WAKEUP, %ebx + movl $SYS_futex, %eax + ENTER_KERNEL + + subl $READERS_WAKEUP, %ebx + + /* Reget the lock. */ + movl $1, %edx + xorl %eax, %eax + LOCK +#if MUTEX == 0 + cmpxchgl %edx, (%ebx) +#else + cmpxchgl %edx, MUTEX(%ebx) +#endif + jnz 12f + +13: subl $1, READERS_QUEUED(%ebx) + jmp 2b + +5: xorl %edx, %edx + addl $1, NR_READERS(%ebx) + je 8f +9: LOCK +#if MUTEX == 0 + subl $1, (%ebx) +#else + subl $1, MUTEX(%ebx) +#endif + jne 6f +7: + + movl %edx, %eax + popl %ebx + cfi_adjust_cfa_offset(-4) + cfi_restore(%ebx) + popl %esi + cfi_adjust_cfa_offset(-4) + cfi_restore(%esi) + ret + + cfi_adjust_cfa_offset(8) + cfi_offset(%esi, -8) + cfi_offset(%ebx, -12) +1: +#if MUTEX == 0 + movl %ebx, %edx +#else + leal MUTEX(%ebx), %edx +#endif + movzbl PSHARED(%ebx), %ecx + call __lll_lock_wait + jmp 2b + +14: cmpl %gs:TID, %eax + jne 3b + /* Deadlock detected. */ + movl $EDEADLK, %edx + jmp 9b + +6: +#if MUTEX == 0 + movl %ebx, %eax +#else + leal MUTEX(%ebx), %eax +#endif + movzbl PSHARED(%ebx), %ecx + call __lll_unlock_wake + jmp 7b + + /* Overflow. */ +8: subl $1, NR_READERS(%ebx) + movl $EAGAIN, %edx + jmp 9b + + /* Overflow. */ +4: subl $1, READERS_QUEUED(%ebx) + movl $EAGAIN, %edx + jmp 9b + +10: +#if MUTEX == 0 + movl %ebx, %eax +#else + leal MUTEX(%ebx), %eax +#endif + movzbl PSHARED(%ebx), %ecx + call __lll_unlock_wake + jmp 11b + +12: +#if MUTEX == 0 + movl %ebx, %edx +#else + leal MUTEX(%ebx), %edx +#endif + movzbl PSHARED(%ebx), %ecx + call __lll_lock_wait + jmp 13b + cfi_endproc + .size __pthread_rwlock_rdlock,.-__pthread_rwlock_rdlock + + .globl pthread_rwlock_rdlock +pthread_rwlock_rdlock = __pthread_rwlock_rdlock + + .globl __pthread_rwlock_rdlock_internal +__pthread_rwlock_rdlock_internal = __pthread_rwlock_rdlock diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedrdlock.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedrdlock.S new file mode 100644 index 00000000..be4530e1 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedrdlock.S @@ -0,0 +1,245 @@ +/* Copyright (C) 2002, 2003, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include + + + .text + + .globl pthread_rwlock_timedrdlock + .type pthread_rwlock_timedrdlock,@function + .align 16 +pthread_rwlock_timedrdlock: + cfi_startproc + pushl %esi + cfi_adjust_cfa_offset(4) + pushl %edi + cfi_adjust_cfa_offset(4) + pushl %ebx + cfi_adjust_cfa_offset(4) + pushl %ebp + cfi_adjust_cfa_offset(4) + cfi_offset(%esi, -8) + cfi_offset(%edi, -12) + cfi_offset(%ebx, -16) + cfi_offset(%ebp, -20) + subl $8, %esp + cfi_adjust_cfa_offset(8) + + movl 28(%esp), %ebp + movl 32(%esp), %edi + + /* Get the lock. */ + movl $1, %edx + xorl %eax, %eax + LOCK +#if MUTEX == 0 + cmpxchgl %edx, (%ebp) +#else + cmpxchgl %edx, MUTEX(%ebp) +#endif + jnz 1f + +2: movl WRITER(%ebp), %eax + testl %eax, %eax + jne 14f + cmpl $0, WRITERS_QUEUED(%ebp) + je 5f + cmpb $0, FLAGS(%ebp) + je 5f + + /* Check the value of the timeout parameter. */ +3: cmpl $1000000000, 4(%edi) + jae 19f + + addl $1, READERS_QUEUED(%ebp) + je 4f + + movl READERS_WAKEUP(%ebp), %esi + + LOCK +#if MUTEX == 0 + subl $1, (%ebp) +#else + subl $1, MUTEX(%ebp) +#endif + jne 10f + + /* Get current time. */ +11: movl %esp, %ebx + xorl %ecx, %ecx + movl $__NR_gettimeofday, %eax + ENTER_KERNEL + + /* Compute relative timeout. */ + movl 4(%esp), %eax + movl $1000, %edx + mul %edx /* Milli seconds to nano seconds. */ + movl (%edi), %ecx + movl 4(%edi), %edx + subl (%esp), %ecx + subl %eax, %edx + jns 15f + addl $1000000000, %edx + subl $1, %ecx +15: testl %ecx, %ecx + js 16f /* Time is already up. */ + + /* Futex call. */ + movl %ecx, (%esp) /* Store relative timeout. */ + movl %edx, 4(%esp) + + movl %esi, %edx +#ifdef __ASSUME_PRIVATE_FUTEX + movzbl PSHARED(%ebp), %ecx + xorl $FUTEX_PRIVATE_FLAG|FUTEX_WAIT, %ecx +#else + movzbl PSHARED(%ebp), %ecx +# if FUTEX_WAIT != 0 + orl $FUTEX_WAIT, %ecx +# endif + xorl %gs:PRIVATE_FUTEX, %ecx +#endif + movl %esp, %esi + leal READERS_WAKEUP(%ebp), %ebx + movl $SYS_futex, %eax + ENTER_KERNEL + movl %eax, %esi +17: + + /* Reget the lock. */ + movl $1, %edx + xorl %eax, %eax + LOCK +#if MUTEX == 0 + cmpxchgl %edx, (%ebp) +#else + cmpxchgl %edx, MUTEX(%ebp) +#endif + jnz 12f + +13: subl $1, READERS_QUEUED(%ebp) + cmpl $-ETIMEDOUT, %esi + jne 2b + +18: movl $ETIMEDOUT, %edx + jmp 9f + + +5: xorl %edx, %edx + addl $1, NR_READERS(%ebp) + je 8f +9: LOCK +#if MUTEX == 0 + subl $1, (%ebp) +#else + subl $1, MUTEX(%ebp) +#endif + jne 6f + +7: movl %edx, %eax + + addl $8, %esp + cfi_adjust_cfa_offset(-8) + popl %ebp + cfi_adjust_cfa_offset(-4) + cfi_restore(%ebp) + popl %ebx + cfi_adjust_cfa_offset(-4) + cfi_restore(%ebx) + popl %edi + cfi_adjust_cfa_offset(-4) + cfi_restore(%edi) + popl %esi + cfi_adjust_cfa_offset(-4) + cfi_restore(%esi) + ret + + cfi_adjust_cfa_offset(24) + cfi_offset(%esi, -8) + cfi_offset(%edi, -12) + cfi_offset(%ebx, -16) + cfi_offset(%ebp, -20) +1: +#if MUTEX == 0 + movl %ebp, %edx +#else + leal MUTEX(%ebp), %edx +#endif + movzbl PSHARED(%ebp), %ecx + call __lll_lock_wait + jmp 2b + +14: cmpl %gs:TID, %eax + jne 3b + movl $EDEADLK, %edx + jmp 9b + +6: +#if MUTEX == 0 + movl %ebp, %eax +#else + leal MUTEX(%ebp), %eax +#endif + movzbl PSHARED(%ebp), %ecx + call __lll_unlock_wake + jmp 7b + + /* Overflow. */ +8: subl $1, NR_READERS(%ebp) + movl $EAGAIN, %edx + jmp 9b + + /* Overflow. */ +4: subl $1, READERS_QUEUED(%ebp) + movl $EAGAIN, %edx + jmp 9b + +10: +#if MUTEX == 0 + movl %ebp, %eax +#else + leal MUTEX(%ebp), %eax +#endif + movzbl PSHARED(%ebp), %ecx + call __lll_unlock_wake + jmp 11b + +12: +#if MUTEX == 0 + movl %ebp, %edx +#else + leal MUTEX(%ebp), %edx +#endif + movzbl PSHARED(%ebp), %ecx + call __lll_lock_wait + jmp 13b + +16: movl $-ETIMEDOUT, %esi + jmp 17b + +19: movl $EINVAL, %edx + jmp 9b + cfi_endproc + .size pthread_rwlock_timedrdlock,.-pthread_rwlock_timedrdlock diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedwrlock.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedwrlock.S new file mode 100644 index 00000000..61431ab7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_timedwrlock.S @@ -0,0 +1,238 @@ +/* Copyright (C) 2002, 2003, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include + + + .text + + .globl pthread_rwlock_timedwrlock + .type pthread_rwlock_timedwrlock,@function + .align 16 +pthread_rwlock_timedwrlock: + cfi_startproc + pushl %esi + cfi_adjust_cfa_offset(4) + pushl %edi + cfi_adjust_cfa_offset(4) + pushl %ebx + cfi_adjust_cfa_offset(4) + pushl %ebp + cfi_adjust_cfa_offset(4) + cfi_offset(%esi, -8) + cfi_offset(%edi, -12) + cfi_offset(%ebx, -16) + cfi_offset(%ebp, -20) + subl $8, %esp + cfi_adjust_cfa_offset(8) + + movl 28(%esp), %ebp + movl 32(%esp), %edi + + /* Get the lock. */ + movl $1, %edx + xorl %eax, %eax + LOCK +#if MUTEX == 0 + cmpxchgl %edx, (%ebp) +#else + cmpxchgl %edx, MUTEX(%ebp) +#endif + jnz 1f + +2: movl WRITER(%ebp), %eax + testl %eax, %eax + jne 14f + cmpl $0, NR_READERS(%ebp) + je 5f + + /* Check the value of the timeout parameter. */ +3: cmpl $1000000000, 4(%edi) + jae 19f + + addl $1, WRITERS_QUEUED(%ebp) + je 4f + + movl WRITERS_WAKEUP(%ebp), %esi + + LOCK +#if MUTEX == 0 + subl $1, (%ebp) +#else + subl $1, MUTEX(%ebp) +#endif + jne 10f + + /* Get current time. */ +11: movl %esp, %ebx + xorl %ecx, %ecx + movl $__NR_gettimeofday, %eax + ENTER_KERNEL + + /* Compute relative timeout. */ + movl 4(%esp), %eax + movl $1000, %edx + mul %edx /* Milli seconds to nano seconds. */ + movl (%edi), %ecx + movl 4(%edi), %edx + subl (%esp), %ecx + subl %eax, %edx + jns 15f + addl $1000000000, %edx + subl $1, %ecx +15: testl %ecx, %ecx + js 16f /* Time is already up. */ + + /* Futex call. */ + movl %ecx, (%esp) /* Store relative timeout. */ + movl %edx, 4(%esp) + + movl %esi, %edx +#ifdef __ASSUME_PRIVATE_FUTEX + movzbl PSHARED(%ebp), %ecx + xorl $FUTEX_PRIVATE_FLAG|FUTEX_WAIT, %ecx +#else + movzbl PSHARED(%ebp), %ecx +# if FUTEX_WAIT != 0 + orl $FUTEX_WAIT, %ecx +# endif + xorl %gs:PRIVATE_FUTEX, %ecx +#endif + movl %esp, %esi + leal WRITERS_WAKEUP(%ebp), %ebx + movl $SYS_futex, %eax + ENTER_KERNEL + movl %eax, %esi +17: + + /* Reget the lock. */ + movl $1, %edx + xorl %eax, %eax + LOCK +#if MUTEX == 0 + cmpxchgl %edx, (%ebp) +#else + cmpxchgl %edx, MUTEX(%ebp) +#endif + jnz 12f + +13: subl $1, WRITERS_QUEUED(%ebp) + cmpl $-ETIMEDOUT, %esi + jne 2b + +18: movl $ETIMEDOUT, %edx + jmp 9f + + +5: xorl %edx, %edx + movl %gs:TID, %eax + movl %eax, WRITER(%ebp) +9: LOCK +#if MUTEX == 0 + subl $1, (%ebp) +#else + subl $1, MUTEX(%ebp) +#endif + jne 6f + +7: movl %edx, %eax + + addl $8, %esp + cfi_adjust_cfa_offset(-8) + popl %ebp + cfi_adjust_cfa_offset(-4) + cfi_restore(%ebp) + popl %ebx + cfi_adjust_cfa_offset(-4) + cfi_restore(%ebx) + popl %edi + cfi_adjust_cfa_offset(-4) + cfi_restore(%edi) + popl %esi + cfi_adjust_cfa_offset(-4) + cfi_restore(%esi) + ret + + cfi_adjust_cfa_offset(24) + cfi_offset(%esi, -8) + cfi_offset(%edi, -12) + cfi_offset(%ebx, -16) + cfi_offset(%ebp, -20) +1: +#if MUTEX == 0 + movl %ebp, %edx +#else + leal MUTEX(%ebp), %edx +#endif + movzbl PSHARED(%ebp), %ecx + call __lll_lock_wait + jmp 2b + +14: cmpl %gs:TID, %eax + jne 3b +20: movl $EDEADLK, %edx + jmp 9b + +6: +#if MUTEX == 0 + movl %ebp, %eax +#else + leal MUTEX(%ebp), %eax +#endif + movzbl PSHARED(%ebp), %ecx + call __lll_unlock_wake + jmp 7b + + /* Overflow. */ +4: subl $1, WRITERS_QUEUED(%ebp) + movl $EAGAIN, %edx + jmp 9b + +10: +#if MUTEX == 0 + movl %ebp, %eax +#else + leal MUTEX(%ebp), %eax +#endif + movzbl PSHARED(%ebp), %ecx + call __lll_unlock_wake + jmp 11b + +12: +#if MUTEX == 0 + movl %ebp, %edx +#else + leal MUTEX(%ebp), %edx +#endif + movzbl PSHARED(%ebp), %ecx + call __lll_lock_wait + jmp 13b + +16: movl $-ETIMEDOUT, %esi + jmp 17b + +19: movl $EINVAL, %edx + jmp 9b + cfi_endproc + .size pthread_rwlock_timedwrlock,.-pthread_rwlock_timedwrlock diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_unlock.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_unlock.S new file mode 100644 index 00000000..cfab60c6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_unlock.S @@ -0,0 +1,157 @@ +/* Copyright (C) 2002, 2003, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include + + + .text + + .globl __pthread_rwlock_unlock + .type __pthread_rwlock_unlock,@function + .protected __pthread_rwlock_unlock + .align 16 +__pthread_rwlock_unlock: + cfi_startproc + pushl %ebx + cfi_adjust_cfa_offset(4) + pushl %edi + cfi_adjust_cfa_offset(4) + cfi_offset(%ebx, -8) + cfi_offset(%edi, -12) + + movl 12(%esp), %edi + + /* Get the lock. */ + movl $1, %edx + xorl %eax, %eax + LOCK +#if MUTEX == 0 + cmpxchgl %edx, (%edi) +#else + cmpxchgl %edx, MUTEX(%edi) +#endif + jnz 1f + +2: cmpl $0, WRITER(%edi) + jne 5f + subl $1, NR_READERS(%edi) + jnz 6f + +5: movl $0, WRITER(%edi) + + movl $1, %edx + leal WRITERS_WAKEUP(%edi), %ebx + cmpl $0, WRITERS_QUEUED(%edi) + jne 0f + + /* If also no readers waiting nothing to do. */ + cmpl $0, READERS_QUEUED(%edi) + je 6f + + movl $0x7fffffff, %edx + leal READERS_WAKEUP(%edi), %ebx + +0: addl $1, (%ebx) + LOCK +#if MUTEX == 0 + subl $1, (%edi) +#else + subl $1, MUTEX(%edi) +#endif + jne 7f + +8: +#ifdef __ASSUME_PRIVATE_FUTEX + movzbl PSHARED(%edi), %ecx + xorl $FUTEX_PRIVATE_FLAG|FUTEX_WAKE, %ecx +#else + movzbl PSHARED(%edi), %ecx + orl $FUTEX_WAKE, %ecx + xorl %gs:PRIVATE_FUTEX, %ecx +#endif + movl $SYS_futex, %eax + ENTER_KERNEL + + xorl %eax, %eax + popl %edi + cfi_adjust_cfa_offset(-4) + cfi_restore(%edi) + popl %ebx + cfi_adjust_cfa_offset(-4) + cfi_restore(%ebx) + ret + + cfi_adjust_cfa_offset(8) + cfi_offset(%ebx, -8) + cfi_offset(%edi, -12) + .align 16 +6: LOCK +#if MUTEX == 0 + subl $1, (%edi) +#else + subl $1, MUTEX(%edi) +#endif + jne 3f + +4: xorl %eax, %eax + popl %edi + popl %ebx + ret + +1: +#if MUTEX == 0 + movl %edi, %edx +#else + leal MUTEX(%edi), %edx +#endif + movzbl PSHARED(%edi), %ecx + call __lll_lock_wait + jmp 2b + +3: +#if MUTEX == 0 + movl %edi, %eax +#else + leal MUTEX(%edi), %eax +#endif + movzbl PSHARED(%edi), %ecx + call __lll_unlock_wake + jmp 4b + +7: +#if MUTEX == 0 + movl %edi, %eax +#else + leal MUTEX(%edi), %eax +#endif + movzbl PSHARED(%edi), %ecx + call __lll_unlock_wake + jmp 8b + cfi_endproc + .size __pthread_rwlock_unlock,.-__pthread_rwlock_unlock + + .globl pthread_rwlock_unlock +pthread_rwlock_unlock = __pthread_rwlock_unlock + + .globl __pthread_rwlock_unlock_internal +__pthread_rwlock_unlock_internal = __pthread_rwlock_unlock diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_wrlock.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_wrlock.S new file mode 100644 index 00000000..5c96d900 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/pthread_rwlock_wrlock.S @@ -0,0 +1,186 @@ +/* Copyright (C) 2002, 2003, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include + + + .text + + .globl __pthread_rwlock_wrlock + .type __pthread_rwlock_wrlock,@function + .protected __pthread_rwlock_wrlock + .align 16 +__pthread_rwlock_wrlock: + cfi_startproc + pushl %esi + cfi_adjust_cfa_offset(4) + pushl %ebx + cfi_adjust_cfa_offset(4) + cfi_offset(%esi, -8) + cfi_offset(%ebx, -12) + + xorl %esi, %esi + movl 12(%esp), %ebx + + /* Get the lock. */ + movl $1, %edx + xorl %eax, %eax + LOCK +#if MUTEX == 0 + cmpxchgl %edx, (%ebx) +#else + cmpxchgl %edx, MUTEX(%ebx) +#endif + jnz 1f + +2: movl WRITER(%ebx), %eax + testl %eax, %eax + jne 14f + cmpl $0, NR_READERS(%ebx) + je 5f + +3: addl $1, WRITERS_QUEUED(%ebx) + je 4f + + movl WRITERS_WAKEUP(%ebx), %edx + + LOCK +#if MUTEX == 0 + subl $1, (%ebx) +#else + subl $1, MUTEX(%ebx) +#endif + jne 10f + +11: +#ifdef __ASSUME_PRIVATE_FUTEX + movzbl PSHARED(%ebx), %ecx + xorl $FUTEX_PRIVATE_FLAG|FUTEX_WAIT, %ecx +#else + movzbl PSHARED(%ebx), %ecx +# if FUTEX_WAIT != 0 + orl $FUTEX_WAIT, %ecx +# endif + xorl %gs:PRIVATE_FUTEX, %ecx +#endif + addl $WRITERS_WAKEUP, %ebx + movl $SYS_futex, %eax + ENTER_KERNEL + + subl $WRITERS_WAKEUP, %ebx + + /* Reget the lock. */ + movl $1, %edx + xorl %eax, %eax + LOCK +#if MUTEX == 0 + cmpxchgl %edx, (%ebx) +#else + cmpxchgl %edx, MUTEX(%ebx) +#endif + jnz 12f + +13: subl $1, WRITERS_QUEUED(%ebx) + jmp 2b + +5: xorl %edx, %edx + movl %gs:TID, %eax + movl %eax, WRITER(%ebx) +9: LOCK +#if MUTEX == 0 + subl $1, (%ebx) +#else + subl $1, MUTEX(%ebx) +#endif + jne 6f +7: + + movl %edx, %eax + popl %ebx + cfi_adjust_cfa_offset(-4) + cfi_restore(%ebx) + popl %esi + cfi_adjust_cfa_offset(-4) + cfi_restore(%esi) + ret + + cfi_adjust_cfa_offset(8) + cfi_offset(%esi, -8) + cfi_offset(%ebx, -12) +1: +#if MUTEX == 0 + movl %ebx, %edx +#else + leal MUTEX(%ebx), %edx +#endif + movzbl PSHARED(%ebx), %ecx + call __lll_lock_wait + jmp 2b + +14: cmpl %gs:TID , %eax + jne 3b + movl $EDEADLK, %edx + jmp 9b + +6: +#if MUTEX == 0 + movl %ebx, %eax +#else + leal MUTEX(%ebx), %eax +#endif + movzbl PSHARED(%ebx), %ecx + call __lll_unlock_wake + jmp 7b + +4: subl $1, WRITERS_QUEUED(%ebx) + movl $EAGAIN, %edx + jmp 9b + +10: +#if MUTEX == 0 + movl %ebx, %eax +#else + leal MUTEX(%ebx), %eax +#endif + movzbl PSHARED(%ebx), %ecx + call __lll_unlock_wake + jmp 11b + +12: +#if MUTEX == 0 + movl %ebx, %edx +#else + leal MUTEX(%ebx), %edx +#endif + movzbl PSHARED(%ebx), %ecx + call __lll_lock_wait + jmp 13b + cfi_endproc + .size __pthread_rwlock_wrlock,.-__pthread_rwlock_wrlock + + .globl pthread_rwlock_wrlock +pthread_rwlock_wrlock = __pthread_rwlock_wrlock + + .globl __pthread_rwlock_wrlock_internal +__pthread_rwlock_wrlock_internal = __pthread_rwlock_wrlock diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_post.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_post.S new file mode 100644 index 00000000..b077a20c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_post.S @@ -0,0 +1,142 @@ +/* Copyright (C) 2002, 2003, 2005, 2007, 2008 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + + + .text + + .globl __new_sem_post + .type __new_sem_post,@function + .align 16 +__new_sem_post: + cfi_startproc + pushl %ebx + cfi_adjust_cfa_offset(4) + cfi_offset(%ebx, -8) + + movl 8(%esp), %ebx + +#if VALUE == 0 + movl (%ebx), %eax +#else + movl VALUE(%ebx), %eax +#endif +0: cmpl $SEM_VALUE_MAX, %eax + je 3f + leal 1(%eax), %edx + LOCK +#if VALUE == 0 + cmpxchgl %edx, (%ebx) +#else + cmpxchgl %edx, VALUE(%ebx) +#endif + jnz 0b + + cmpl $0, NWAITERS(%ebx) + je 2f + + movl $FUTEX_WAKE, %ecx + orl PRIVATE(%ebx), %ecx + movl $1, %edx + movl $SYS_futex, %eax + ENTER_KERNEL + + testl %eax, %eax + js 1f + +2: xorl %eax, %eax + popl %ebx + cfi_adjust_cfa_offset(-4) + cfi_restore(%ebx) + ret + + cfi_adjust_cfa_offset(4) + cfi_offset(%ebx, -8) +1: +#ifdef __PIC__ + call __x86.get_pc_thunk.bx +#else + movl $4f, %ebx +4: +#endif + addl $_GLOBAL_OFFSET_TABLE_, %ebx +#if USE___THREAD +# ifdef NO_TLS_DIRECT_SEG_REFS + movl errno@gotntpoff(%ebx), %edx + addl %gs:0, %edx + movl $EINVAL, (%edx) +# else + movl errno@gotntpoff(%ebx), %edx + movl $EINVAL, %gs:(%edx) +# endif +#else + call __errno_location@plt + movl $EINVAL, (%eax) +#endif + + orl $-1, %eax + popl %ebx + ret + +3: +#ifdef __PIC__ + call __x86.get_pc_thunk.bx +#else + movl $5f, %ebx +5: +#endif + addl $_GLOBAL_OFFSET_TABLE_, %ebx +#if USE___THREAD +# ifdef NO_TLS_DIRECT_SEG_REFS + movl errno@gotntpoff(%ebx), %edx + addl %gs:0, %edx + movl $EOVERFLOW, (%edx) +# else + movl errno@gotntpoff(%ebx), %edx + movl $EOVERFLOW, %gs:(%edx) +# endif +#else + call __errno_location@plt + movl $EOVERFLOW, (%eax) +#endif + + orl $-1, %eax + popl %ebx + cfi_adjust_cfa_offset(-4) + cfi_restore(%ebx) + ret + cfi_endproc + .size __new_sem_post,.-__new_sem_post +weak_alias(__new_sem_post, sem_post) + + +#ifdef __PIC__ + .section .gnu.linkonce.t.__x86.get_pc_thunk.bx,"ax",@progbits + .globl __x86.get_pc_thunk.bx + .hidden __x86.get_pc_thunk.bx + .type __x86.get_pc_thunk.bx,@function +__x86.get_pc_thunk.bx: + movl (%esp), %ebx; + ret + .size __x86.get_pc_thunk.bx,.-__x86.get_pc_thunk.bx +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S new file mode 100644 index 00000000..a1e3225c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S @@ -0,0 +1,329 @@ +/* Copyright (C) 2002, 2003, 2004, 2005, 2007, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + + +#if VALUE != 0 +# error "code needs to be rewritten for VALUE != 0" +#endif + + + .text + + .globl sem_timedwait + .type sem_timedwait,@function + .align 16 +sem_timedwait: +.LSTARTCODE: + movl 4(%esp), %ecx + + movl (%ecx), %eax +2: testl %eax, %eax + je 1f + + leal -1(%eax), %edx + LOCK + cmpxchgl %edx, (%ecx) + jne 2b + + xorl %eax, %eax + ret + + /* Check whether the timeout value is valid. */ +1: pushl %esi +.Lpush_esi: + pushl %edi +.Lpush_edi: + pushl %ebx +.Lpush_ebx: + subl $12, %esp +.Lsub_esp: + + movl 32(%esp), %edi + + /* Check for invalid nanosecond field. */ + cmpl $1000000000, 4(%edi) + movl $EINVAL, %esi + jae 6f + + LOCK + incl NWAITERS(%ecx) + +7: xorl %ecx, %ecx + movl %esp, %ebx + movl %ecx, %edx + movl $__NR_gettimeofday, %eax + ENTER_KERNEL + + /* Compute relative timeout. */ + movl 4(%esp), %eax + movl $1000, %edx + mul %edx /* Milli seconds to nano seconds. */ + movl (%edi), %ecx + movl 4(%edi), %edx + subl (%esp), %ecx + subl %eax, %edx + jns 5f + addl $1000000000, %edx + subl $1, %ecx +5: testl %ecx, %ecx + movl $ETIMEDOUT, %esi + js 6f /* Time is already up. */ + + movl %ecx, (%esp) /* Store relative timeout. */ + movl %edx, 4(%esp) + +.LcleanupSTART: + call __pthread_enable_asynccancel + movl %eax, 8(%esp) + + movl 28(%esp), %ebx /* Load semaphore address. */ +#if FUTEX_WAIT == 0 + movl PRIVATE(%ebx), %ecx +#else + movl $FUTEX_WAIT, %ecx + orl PRIVATE(%ebx), %ecx +#endif + movl %esp, %esi + xorl %edx, %edx + movl $SYS_futex, %eax + ENTER_KERNEL + movl %eax, %esi + + movl 8(%esp), %eax + call __pthread_disable_asynccancel +.LcleanupEND: + + testl %esi, %esi + je 9f + cmpl $-EWOULDBLOCK, %esi + jne 3f + +9: movl (%ebx), %eax +8: testl %eax, %eax + je 7b + + leal -1(%eax), %ecx + LOCK + cmpxchgl %ecx, (%ebx) + jne 8b + + xorl %eax, %eax + + LOCK + decl NWAITERS(%ebx) + +10: addl $12, %esp +.Ladd_esp: + popl %ebx +.Lpop_ebx: + popl %edi +.Lpop_edi: + popl %esi +.Lpop_esi: + ret + +.Lafter_ret: +3: negl %esi +6: +#ifdef __PIC__ + call __x86.get_pc_thunk.bx +#else + movl $4f, %ebx +4: +#endif + addl $_GLOBAL_OFFSET_TABLE_, %ebx +#if USE___THREAD +# ifdef NO_TLS_DIRECT_SEG_REFS + movl errno@gotntpoff(%ebx), %edx + addl %gs:0, %edx + movl %esi, (%edx) +# else + movl errno@gotntpoff(%ebx), %edx + movl %esi, %gs:(%edx) +# endif +#else + call __errno_location@plt + movl %esi, (%eax) +#endif + + movl 28(%esp), %ebx /* Load semaphore address. */ + orl $-1, %eax + jmp 10b + .size sem_timedwait,.-sem_timedwait + + + .type sem_wait_cleanup,@function +sem_wait_cleanup: + LOCK + decl NWAITERS(%ebx) + movl %eax, (%esp) +.LcallUR: + call _Unwind_Resume@PLT + hlt +.LENDCODE: + .size sem_wait_cleanup,.-sem_wait_cleanup + + + .section .gcc_except_table,"a",@progbits +.LexceptSTART: + .byte 0xff # @LPStart format (omit) + .byte 0xff # @TType format (omit) + .byte 0x01 # call-site format + # DW_EH_PE_uleb128 + .uleb128 .Lcstend-.Lcstbegin +.Lcstbegin: + .uleb128 .LcleanupSTART-.LSTARTCODE + .uleb128 .LcleanupEND-.LcleanupSTART + .uleb128 sem_wait_cleanup-.LSTARTCODE + .uleb128 0 + .uleb128 .LcallUR-.LSTARTCODE + .uleb128 .LENDCODE-.LcallUR + .uleb128 0 + .uleb128 0 +.Lcstend: + + + .section .eh_frame,"a",@progbits +.LSTARTFRAME: + .long .LENDCIE-.LSTARTCIE # Length of the CIE. +.LSTARTCIE: + .long 0 # CIE ID. + .byte 1 # Version number. +#ifdef SHARED + .string "zPLR" # NUL-terminated augmentation + # string. +#else + .string "zPL" # NUL-terminated augmentation + # string. +#endif + .uleb128 1 # Code alignment factor. + .sleb128 -4 # Data alignment factor. + .byte 8 # Return address register + # column. +#ifdef SHARED + .uleb128 7 # Augmentation value length. + .byte 0x9b # Personality: DW_EH_PE_pcrel + # + DW_EH_PE_sdata4 + # + DW_EH_PE_indirect + .long DW.ref.__gcc_personality_v0-. + .byte 0x1b # LSDA Encoding: DW_EH_PE_pcrel + # + DW_EH_PE_sdata4. + .byte 0x1b # FDE Encoding: DW_EH_PE_pcrel + # + DW_EH_PE_sdata4. +#else + .uleb128 6 # Augmentation value length. + .byte 0x0 # Personality: absolute + .long __gcc_personality_v0 + .byte 0x0 # LSDA Encoding: absolute +#endif + .byte 0x0c # DW_CFA_def_cfa + .uleb128 4 + .uleb128 4 + .byte 0x88 # DW_CFA_offset, column 0x10 + .uleb128 1 + .align 4 +.LENDCIE: + + .long .LENDFDE-.LSTARTFDE # Length of the FDE. +.LSTARTFDE: + .long .LSTARTFDE-.LSTARTFRAME # CIE pointer. +#ifdef SHARED + .long .LSTARTCODE-. # PC-relative start address + # of the code. +#else + .long .LSTARTCODE # Start address of the code. +#endif + .long .LENDCODE-.LSTARTCODE # Length of the code. + .uleb128 4 # Augmentation size +#ifdef SHARED + .long .LexceptSTART-. +#else + .long .LexceptSTART +#endif + + .byte 4 # DW_CFA_advance_loc4 + .long .Lpush_esi-.LSTARTCODE + .byte 14 # DW_CFA_def_cfa_offset + .uleb128 8 + .byte 0x86 # DW_CFA_offset %esi + .uleb128 2 + .byte 4 # DW_CFA_advance_loc4 + .long .Lpush_edi-.Lpush_esi + .byte 14 # DW_CFA_def_cfa_offset + .uleb128 12 + .byte 0x87 # DW_CFA_offset %edi + .uleb128 3 + .byte 4 # DW_CFA_advance_loc4 + .long .Lpush_ebx-.Lpush_edi + .byte 14 # DW_CFA_def_cfa_offset + .uleb128 16 + .byte 0x83 # DW_CFA_offset %ebx + .uleb128 4 + .byte 4 # DW_CFA_advance_loc4 + .long .Lsub_esp-.Lpush_ebx + .byte 14 # DW_CFA_def_cfa_offset + .uleb128 28 + .byte 4 # DW_CFA_advance_loc4 + .long .Ladd_esp-.Lsub_esp + .byte 14 # DW_CFA_def_cfa_offset + .uleb128 16 + .byte 4 # DW_CFA_advance_loc4 + .long .Lpop_ebx-.Ladd_esp + .byte 14 # DW_CFA_def_cfa_offset + .uleb128 12 + .byte 0xc3 # DW_CFA_restore %ebx + .byte 4 # DW_CFA_advance_loc4 + .long .Lpop_edi-.Lpop_ebx + .byte 14 # DW_CFA_def_cfa_offset + .uleb128 8 + .byte 0xc7 # DW_CFA_restore %edi + .byte 4 # DW_CFA_advance_loc4 + .long .Lpop_esi-.Lpop_edi + .byte 14 # DW_CFA_def_cfa_offset + .uleb128 4 + .byte 0xc6 # DW_CFA_restore %esi + .byte 4 # DW_CFA_advance_loc4 + .long .Lafter_ret-.Lpop_esi + .byte 14 # DW_CFA_def_cfa_offset + .uleb128 28 + .byte 0x86 # DW_CFA_offset %esi + .uleb128 2 + .byte 0x87 # DW_CFA_offset %edi + .uleb128 3 + .byte 0x83 # DW_CFA_offset %ebx + .uleb128 4 + .align 4 +.LENDFDE: + + +#ifdef SHARED + .hidden DW.ref.__gcc_personality_v0 + .weak DW.ref.__gcc_personality_v0 + .section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits + .align 4 + .type DW.ref.__gcc_personality_v0, @object + .size DW.ref.__gcc_personality_v0, 4 +DW.ref.__gcc_personality_v0: + .long __gcc_personality_v0 +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_trywait.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_trywait.S new file mode 100644 index 00000000..dad96858 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_trywait.S @@ -0,0 +1,79 @@ +/* Copyright (C) 2002, 2003, 2005, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + + .text + + .globl __new_sem_trywait + .type __new_sem_trywait,@function + .align 16 +__new_sem_trywait: + movl 4(%esp), %ecx + + movl (%ecx), %eax +2: testl %eax, %eax + jz 1f + + leal -1(%eax), %edx + LOCK + cmpxchgl %edx, (%ecx) + jne 2b + xorl %eax, %eax + ret + +1: +#ifdef __PIC__ + call __x86.get_pc_thunk.cx +#else + movl $3f, %ecx +3: +#endif + addl $_GLOBAL_OFFSET_TABLE_, %ecx +#if USE___THREAD +# ifdef NO_TLS_DIRECT_SEG_REFS + movl errno@gotntpoff(%ecx), %edx + addl %gs:0, %edx + movl $EAGAIN, (%edx) +# else + movl errno@gotntpoff(%ecx), %edx + movl $EAGAIN, %gs:(%edx) +# endif +#else + call __errno_location@plt + movl $EAGAIN, (%eax) +#endif + orl $-1, %eax + ret + .size __new_sem_trywait,.-__new_sem_trywait +weak_alias(__new_sem_trywait, sem_trywait) + + +#ifdef __PIC__ + .section .gnu.linkonce.t.__x86.get_pc_thunk.cx,"ax",@progbits + .globl __x86.get_pc_thunk.cx + .hidden __x86.get_pc_thunk.cx + .type __x86.get_pc_thunk.cx,@function +__x86.get_pc_thunk.cx: + movl (%esp), %ecx; + ret + .size __x86.get_pc_thunk.cx,.-__x86.get_pc_thunk.cx +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_wait.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_wait.S new file mode 100644 index 00000000..b1c32ee4 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_wait.S @@ -0,0 +1,269 @@ +/* Copyright (C) 2002, 2003, 2005, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + + +#if VALUE != 0 +# error "code needs to be rewritten for VALUE != 0" +#endif + + .text + + .globl __new_sem_wait + .type __new_sem_wait,@function + .align 16 +__new_sem_wait: +.LSTARTCODE: + pushl %ebx +.Lpush_ebx: + pushl %esi +.Lpush_esi: + subl $4, %esp +.Lsub_esp: + + movl 16(%esp), %ebx + + movl (%ebx), %eax +2: testl %eax, %eax + je 1f + + leal -1(%eax), %edx + LOCK + cmpxchgl %edx, (%ebx) + jne 2b +7: xorl %eax, %eax + +9: movl 4(%esp), %esi + movl 8(%esp), %ebx + addl $12, %esp +.Ladd_esp: + ret + +.Lafter_ret: +1: LOCK + incl NWAITERS(%ebx) + +.LcleanupSTART: +6: call __pthread_enable_asynccancel + movl %eax, (%esp) + +#if FUTEX_WAIT == 0 + movl PRIVATE(%ebx), %ecx +#else + movl $FUTEX_WAIT, %ecx + orl PRIVATE(%ebx), %ecx +#endif + xorl %esi, %esi + xorl %edx, %edx + movl $SYS_futex, %eax + ENTER_KERNEL + movl %eax, %esi + + movl (%esp), %eax + call __pthread_disable_asynccancel +.LcleanupEND: + + testl %esi, %esi + je 3f + cmpl $-EWOULDBLOCK, %esi + jne 4f + +3: + movl (%ebx), %eax +5: testl %eax, %eax + je 6b + + leal -1(%eax), %edx + LOCK + cmpxchgl %edx, (%ebx) + jne 5b + + LOCK + decl NWAITERS(%ebx) + jmp 7b + +4: LOCK + decl NWAITERS(%ebx) + + negl %esi +#ifdef __PIC__ + call __x86.get_pc_thunk.bx +#else + movl $8f, %ebx +8: +#endif + addl $_GLOBAL_OFFSET_TABLE_, %ebx +#if USE___THREAD +# ifdef NO_TLS_DIRECT_SEG_REFS + movl errno@gotntpoff(%ebx), %edx + addl %gs:0, %edx + movl %esi, (%edx) +# else + movl errno@gotntpoff(%ebx), %edx + movl %esi, %gs:(%edx) +# endif +#else + call __errno_location@plt + movl %esi, (%eax) +#endif + orl $-1, %eax + + jmp 9b + .size __new_sem_wait,.-__new_sem_wait +weak_alias(__new_sem_wait, sem_wait) + + + .type sem_wait_cleanup,@function +sem_wait_cleanup: + LOCK + decl NWAITERS(%ebx) + movl %eax, (%esp) +.LcallUR: + call _Unwind_Resume@PLT + hlt +.LENDCODE: + .size sem_wait_cleanup,.-sem_wait_cleanup + + + .section .gcc_except_table,"a",@progbits +.LexceptSTART: + .byte 0xff # @LPStart format (omit) + .byte 0xff # @TType format (omit) + .byte 0x01 # call-site format + # DW_EH_PE_uleb128 + .uleb128 .Lcstend-.Lcstbegin +.Lcstbegin: + .uleb128 .LcleanupSTART-.LSTARTCODE + .uleb128 .LcleanupEND-.LcleanupSTART + .uleb128 sem_wait_cleanup-.LSTARTCODE + .uleb128 0 + .uleb128 .LcallUR-.LSTARTCODE + .uleb128 .LENDCODE-.LcallUR + .uleb128 0 + .uleb128 0 +.Lcstend: + + + .section .eh_frame,"a",@progbits +.LSTARTFRAME: + .long .LENDCIE-.LSTARTCIE # Length of the CIE. +.LSTARTCIE: + .long 0 # CIE ID. + .byte 1 # Version number. +#ifdef SHARED + .string "zPLR" # NUL-terminated augmentation + # string. +#else + .string "zPL" # NUL-terminated augmentation + # string. +#endif + .uleb128 1 # Code alignment factor. + .sleb128 -4 # Data alignment factor. + .byte 8 # Return address register + # column. +#ifdef SHARED + .uleb128 7 # Augmentation value length. + .byte 0x9b # Personality: DW_EH_PE_pcrel + # + DW_EH_PE_sdata4 + # + DW_EH_PE_indirect + .long DW.ref.__gcc_personality_v0-. + .byte 0x1b # LSDA Encoding: DW_EH_PE_pcrel + # + DW_EH_PE_sdata4. + .byte 0x1b # FDE Encoding: DW_EH_PE_pcrel + # + DW_EH_PE_sdata4. +#else + .uleb128 6 # Augmentation value length. + .byte 0x0 # Personality: absolute + .long __gcc_personality_v0 + .byte 0x0 # LSDA Encoding: absolute +#endif + .byte 0x0c # DW_CFA_def_cfa + .uleb128 4 + .uleb128 4 + .byte 0x88 # DW_CFA_offset, column 0x10 + .uleb128 1 + .align 4 +.LENDCIE: + + .long .LENDFDE-.LSTARTFDE # Length of the FDE. +.LSTARTFDE: + .long .LSTARTFDE-.LSTARTFRAME # CIE pointer. +#ifdef SHARED + .long .LSTARTCODE-. # PC-relative start address + # of the code. +#else + .long .LSTARTCODE # Start address of the code. +#endif + .long .LENDCODE-.LSTARTCODE # Length of the code. + .uleb128 4 # Augmentation size +#ifdef SHARED + .long .LexceptSTART-. +#else + .long .LexceptSTART +#endif + + .byte 4 # DW_CFA_advance_loc4 + .long .Lpush_ebx-.LSTARTCODE + .byte 14 # DW_CFA_def_cfa_offset + .uleb128 8 + .byte 0x83 # DW_CFA_offset %ebx + .uleb128 2 + .byte 4 # DW_CFA_advance_loc4 + .long .Lpush_esi-.Lpush_ebx + .byte 14 # DW_CFA_def_cfa_offset + .uleb128 12 + .byte 0x86 # DW_CFA_offset %esi + .uleb128 3 + .byte 4 # DW_CFA_advance_loc4 + .long .Lsub_esp-.Lpush_esi + .byte 14 # DW_CFA_def_cfa_offset + .uleb128 16 + .byte 4 # DW_CFA_advance_loc4 + .long .Ladd_esp-.Lsub_esp + .byte 14 # DW_CFA_def_cfa_offset + .uleb128 4 + .byte 0xc3 # DW_CFA_restore %ebx + .byte 0xc6 # DW_CFA_restore %esi + .byte 4 # DW_CFA_advance_loc4 + .long .Lafter_ret-.Ladd_esp + .byte 14 # DW_CFA_def_cfa_offset + .uleb128 16 + .byte 0x83 # DW_CFA_offset %ebx + .uleb128 2 + .byte 0x86 # DW_CFA_offset %esi + .uleb128 3 + .align 4 +.LENDFDE: + + +#ifdef SHARED + .hidden DW.ref.__gcc_personality_v0 + .weak DW.ref.__gcc_personality_v0 + .section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits + .align 4 + .type DW.ref.__gcc_personality_v0, @object + .size DW.ref.__gcc_personality_v0, 4 +DW.ref.__gcc_personality_v0: + .long __gcc_personality_v0 +#endif + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/libc-lowlevellock.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/libc-lowlevellock.S new file mode 100644 index 00000000..f567c1d6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/libc-lowlevellock.S @@ -0,0 +1 @@ +#include "../i486/libc-lowlevellock.S" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/lowlevellock.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/lowlevellock.S new file mode 100644 index 00000000..e60dea89 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/lowlevellock.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "../i486/lowlevellock.S" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/lowlevelrobustlock.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/lowlevelrobustlock.S new file mode 100644 index 00000000..f768e16a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/lowlevelrobustlock.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2002, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "../i486/lowlevelrobustlock.S" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_barrier_wait.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_barrier_wait.S new file mode 100644 index 00000000..6d20b9a9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_barrier_wait.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "../i486/pthread_barrier_wait.S" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_cond_broadcast.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_cond_broadcast.S new file mode 100644 index 00000000..5e1024ea --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_cond_broadcast.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "../i486/pthread_cond_broadcast.S" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_cond_signal.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_cond_signal.S new file mode 100644 index 00000000..da4e8cba --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_cond_signal.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "../i486/pthread_cond_signal.S" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_cond_timedwait.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_cond_timedwait.S new file mode 100644 index 00000000..c0131555 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_cond_timedwait.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "../i486/pthread_cond_timedwait.S" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_cond_wait.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_cond_wait.S new file mode 100644 index 00000000..9b57fbac --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_cond_wait.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "../i486/pthread_cond_wait.S" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_rwlock_rdlock.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_rwlock_rdlock.S new file mode 100644 index 00000000..da2bc470 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_rwlock_rdlock.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "../i486/pthread_rwlock_rdlock.S" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_rwlock_timedrdlock.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_rwlock_timedrdlock.S new file mode 100644 index 00000000..0f2ec168 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_rwlock_timedrdlock.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "../i486/pthread_rwlock_timedrdlock.S" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_rwlock_timedwrlock.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_rwlock_timedwrlock.S new file mode 100644 index 00000000..26501590 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_rwlock_timedwrlock.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "../i486/pthread_rwlock_timedwrlock.S" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_rwlock_unlock.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_rwlock_unlock.S new file mode 100644 index 00000000..5515e489 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_rwlock_unlock.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "../i486/pthread_rwlock_unlock.S" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_rwlock_wrlock.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_rwlock_wrlock.S new file mode 100644 index 00000000..04ac275f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/pthread_rwlock_wrlock.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "../i486/pthread_rwlock_wrlock.S" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/sem_post.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/sem_post.S new file mode 100644 index 00000000..7317e158 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/sem_post.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "../i486/sem_post.S" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/sem_timedwait.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/sem_timedwait.S new file mode 100644 index 00000000..f34539d5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/sem_timedwait.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "../i486/sem_timedwait.S" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/sem_trywait.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/sem_trywait.S new file mode 100644 index 00000000..64145c2e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/sem_trywait.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "../i486/sem_trywait.S" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/sem_wait.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/sem_wait.S new file mode 100644 index 00000000..b3d46212 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i586/sem_wait.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "../i486/sem_wait.S" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/libc-lowlevellock.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/libc-lowlevellock.S new file mode 100644 index 00000000..f567c1d6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/libc-lowlevellock.S @@ -0,0 +1 @@ +#include "../i486/libc-lowlevellock.S" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/lowlevellock.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/lowlevellock.S new file mode 100644 index 00000000..e60dea89 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/lowlevellock.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "../i486/lowlevellock.S" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/lowlevelrobustlock.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/lowlevelrobustlock.S new file mode 100644 index 00000000..f768e16a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/lowlevelrobustlock.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2002, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "../i486/lowlevelrobustlock.S" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_barrier_wait.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_barrier_wait.S new file mode 100644 index 00000000..6d20b9a9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_barrier_wait.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "../i486/pthread_barrier_wait.S" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_cond_broadcast.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_cond_broadcast.S new file mode 100644 index 00000000..5e1024ea --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_cond_broadcast.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "../i486/pthread_cond_broadcast.S" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_cond_signal.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_cond_signal.S new file mode 100644 index 00000000..da4e8cba --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_cond_signal.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "../i486/pthread_cond_signal.S" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_cond_timedwait.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_cond_timedwait.S new file mode 100644 index 00000000..07d481f3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_cond_timedwait.S @@ -0,0 +1,21 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define HAVE_CMOV 1 +#include "../i486/pthread_cond_timedwait.S" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_cond_wait.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_cond_wait.S new file mode 100644 index 00000000..9b57fbac --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_cond_wait.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "../i486/pthread_cond_wait.S" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_rwlock_rdlock.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_rwlock_rdlock.S new file mode 100644 index 00000000..da2bc470 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_rwlock_rdlock.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "../i486/pthread_rwlock_rdlock.S" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_rwlock_timedrdlock.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_rwlock_timedrdlock.S new file mode 100644 index 00000000..0f2ec168 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_rwlock_timedrdlock.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "../i486/pthread_rwlock_timedrdlock.S" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_rwlock_timedwrlock.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_rwlock_timedwrlock.S new file mode 100644 index 00000000..26501590 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_rwlock_timedwrlock.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "../i486/pthread_rwlock_timedwrlock.S" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_rwlock_unlock.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_rwlock_unlock.S new file mode 100644 index 00000000..0894f054 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_rwlock_unlock.S @@ -0,0 +1,21 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define HAVE_CMOV 1 +#include "../i486/pthread_rwlock_unlock.S" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_rwlock_wrlock.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_rwlock_wrlock.S new file mode 100644 index 00000000..04ac275f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/pthread_rwlock_wrlock.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "../i486/pthread_rwlock_wrlock.S" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/sem_post.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/sem_post.S new file mode 100644 index 00000000..7317e158 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/sem_post.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "../i486/sem_post.S" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/sem_timedwait.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/sem_timedwait.S new file mode 100644 index 00000000..f34539d5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/sem_timedwait.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "../i486/sem_timedwait.S" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/sem_trywait.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/sem_trywait.S new file mode 100644 index 00000000..64145c2e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/sem_trywait.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "../i486/sem_trywait.S" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/sem_wait.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/sem_wait.S new file mode 100644 index 00000000..b3d46212 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/i686/sem_wait.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "../i486/sem_wait.S" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h new file mode 100644 index 00000000..ab1a9395 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h @@ -0,0 +1,585 @@ +/* Copyright (C) 2002-2004, 2006-2008, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _LOWLEVELLOCK_H +#define _LOWLEVELLOCK_H 1 + +#ifndef __ASSEMBLER__ +# include +# include +# include +# include +# include +# include + +# ifndef LOCK_INSTR +# ifdef UP +# define LOCK_INSTR /* nothing */ +# else +# define LOCK_INSTR "lock;" +# endif +# endif +#else +# ifndef LOCK +# ifdef UP +# define LOCK +# else +# define LOCK lock +# endif +# endif +#endif + +#define FUTEX_WAIT 0 +#define FUTEX_WAKE 1 +#define FUTEX_CMP_REQUEUE 4 +#define FUTEX_WAKE_OP 5 +#define FUTEX_LOCK_PI 6 +#define FUTEX_UNLOCK_PI 7 +#define FUTEX_TRYLOCK_PI 8 +#define FUTEX_WAIT_BITSET 9 +#define FUTEX_WAKE_BITSET 10 +#define FUTEX_WAIT_REQUEUE_PI 11 +#define FUTEX_CMP_REQUEUE_PI 12 +#define FUTEX_PRIVATE_FLAG 128 +#define FUTEX_CLOCK_REALTIME 256 + +#define FUTEX_BITSET_MATCH_ANY 0xffffffff + +#define FUTEX_OP_CLEAR_WAKE_IF_GT_ONE ((4 << 24) | 1) + +/* Values for 'private' parameter of locking macros. Yes, the + definition seems to be backwards. But it is not. The bit will be + reversed before passing to the system call. */ +#define LLL_PRIVATE 0 +#define LLL_SHARED FUTEX_PRIVATE_FLAG + + +#if !defined NOT_IN_libc || defined IS_IN_rtld +/* In libc.so or ld.so all futexes are private. */ +# ifdef __ASSUME_PRIVATE_FUTEX +# define __lll_private_flag(fl, private) \ + ((fl) | FUTEX_PRIVATE_FLAG) +# else +# define __lll_private_flag(fl, private) \ + ((fl) | THREAD_GETMEM (THREAD_SELF, header.private_futex)) +# endif +#else +# ifdef __ASSUME_PRIVATE_FUTEX +# define __lll_private_flag(fl, private) \ + (((fl) | FUTEX_PRIVATE_FLAG) ^ (private)) +# else +# define __lll_private_flag(fl, private) \ + (__builtin_constant_p (private) \ + ? ((private) == 0 \ + ? ((fl) | THREAD_GETMEM (THREAD_SELF, header.private_futex)) \ + : (fl)) \ + : ({ unsigned int __fl = ((private) ^ FUTEX_PRIVATE_FLAG); \ + __asm__ ("andl %%gs:%P1, %0" : "+r" (__fl) \ + : "i" (offsetof (struct pthread, header.private_futex))); \ + __fl | (fl); })) +# endif +#endif + +#ifndef __ASSEMBLER__ + +/* Initializer for compatibility lock. */ +#define LLL_LOCK_INITIALIZER (0) +#define LLL_LOCK_INITIALIZER_LOCKED (1) +#define LLL_LOCK_INITIALIZER_WAITERS (2) + + +#ifdef __PIC__ +# define LLL_EBX_LOAD "xchgl %2, %%ebx\n" +# define LLL_EBX_REG "D" +#else +# define LLL_EBX_LOAD +# define LLL_EBX_REG "b" +#endif + +#ifdef I386_USE_SYSENTER +# ifdef SHARED +# define LLL_ENTER_KERNEL "call *%%gs:%P6\n\t" +# else +# define LLL_ENTER_KERNEL "call *_dl_sysinfo\n\t" +# endif +#else +# define LLL_ENTER_KERNEL "int $0x80\n\t" +#endif + +/* Delay in spinlock loop. */ +#define BUSY_WAIT_NOP __asm__ ("rep; nop") + + +#define LLL_STUB_UNWIND_INFO_START \ + ".section .eh_frame,\"a\",@progbits\n" \ +"5:\t" ".long 7f-6f # Length of Common Information Entry\n" \ +"6:\t" ".long 0x0 # CIE Identifier Tag\n\t" \ + ".byte 0x1 # CIE Version\n\t" \ + ".ascii \"zR\\0\" # CIE Augmentation\n\t" \ + ".uleb128 0x1 # CIE Code Alignment Factor\n\t" \ + ".sleb128 -4 # CIE Data Alignment Factor\n\t" \ + ".byte 0x8 # CIE RA Column\n\t" \ + ".uleb128 0x1 # Augmentation size\n\t" \ + ".byte 0x1b # FDE Encoding (pcrel sdata4)\n\t" \ + ".byte 0xc # DW_CFA_def_cfa\n\t" \ + ".uleb128 0x4\n\t" \ + ".uleb128 0x0\n\t" \ + ".align 4\n" \ +"7:\t" ".long 17f-8f # FDE Length\n" \ +"8:\t" ".long 8b-5b # FDE CIE offset\n\t" \ + ".long 1b-. # FDE initial location\n\t" \ + ".long 4b-1b # FDE address range\n\t" \ + ".uleb128 0x0 # Augmentation size\n\t" \ + ".byte 0x16 # DW_CFA_val_expression\n\t" \ + ".uleb128 0x8\n\t" \ + ".uleb128 10f-9f\n" \ +"9:\t" ".byte 0x78 # DW_OP_breg8\n\t" \ + ".sleb128 3b-1b\n" +#define LLL_STUB_UNWIND_INFO_END \ + ".byte 0x16 # DW_CFA_val_expression\n\t" \ + ".uleb128 0x8\n\t" \ + ".uleb128 12f-11f\n" \ +"11:\t" ".byte 0x78 # DW_OP_breg8\n\t" \ + ".sleb128 3b-2b\n" \ +"12:\t" ".byte 0x40 + (3b-2b-1) # DW_CFA_advance_loc\n\t" \ + ".byte 0x16 # DW_CFA_val_expression\n\t" \ + ".uleb128 0x8\n\t" \ + ".uleb128 16f-13f\n" \ +"13:\t" ".byte 0x78 # DW_OP_breg8\n\t" \ + ".sleb128 15f-14f\n\t" \ + ".byte 0x0d # DW_OP_const4s\n" \ +"14:\t" ".4byte 3b-.\n\t" \ + ".byte 0x1c # DW_OP_minus\n\t" \ + ".byte 0x0d # DW_OP_const4s\n" \ +"15:\t" ".4byte 18f-.\n\t" \ + ".byte 0x22 # DW_OP_plus\n" \ +"16:\t" ".align 4\n" \ +"17:\t" ".previous\n" + +/* Unwind info for + 1: lea ..., ... + 2: call ... + 3: jmp 18f + 4: + snippet. */ +#define LLL_STUB_UNWIND_INFO_3 \ +LLL_STUB_UNWIND_INFO_START \ +"10:\t" ".byte 0x40 + (2b-1b) # DW_CFA_advance_loc\n\t" \ +LLL_STUB_UNWIND_INFO_END + +/* Unwind info for + 1: lea ..., ... + 0: movl ..., ... + 2: call ... + 3: jmp 18f + 4: + snippet. */ +#define LLL_STUB_UNWIND_INFO_4 \ +LLL_STUB_UNWIND_INFO_START \ +"10:\t" ".byte 0x40 + (0b-1b) # DW_CFA_advance_loc\n\t" \ + ".byte 0x16 # DW_CFA_val_expression\n\t" \ + ".uleb128 0x8\n\t" \ + ".uleb128 20f-19f\n" \ +"19:\t" ".byte 0x78 # DW_OP_breg8\n\t" \ + ".sleb128 3b-0b\n" \ +"20:\t" ".byte 0x40 + (2b-0b) # DW_CFA_advance_loc\n\t" \ +LLL_STUB_UNWIND_INFO_END + + +#define lll_futex_wait(futex, val, private) \ + lll_futex_timed_wait (futex, val, NULL, private) + + +#define lll_futex_timed_wait(futex, val, timeout, private) \ + ({ \ + int __status; \ + register __typeof (val) _val __asm__ ("edx") = (val); \ + __asm__ __volatile__ (LLL_EBX_LOAD \ + LLL_ENTER_KERNEL \ + LLL_EBX_LOAD \ + : "=a" (__status) \ + : "0" (SYS_futex), LLL_EBX_REG (futex), "S" (timeout), \ + "c" (__lll_private_flag (FUTEX_WAIT, private)), \ + "d" (_val), "i" (offsetof (tcbhead_t, sysinfo)) \ + : "memory"); \ + __status; \ + }) + + +#define lll_futex_wake(futex, nr, private) \ + do { \ + int __ignore; \ + register __typeof (nr) _nr __asm__ ("edx") = (nr); \ + __asm__ __volatile__ (LLL_EBX_LOAD \ + LLL_ENTER_KERNEL \ + LLL_EBX_LOAD \ + : "=a" (__ignore) \ + : "0" (SYS_futex), LLL_EBX_REG (futex), \ + "c" (__lll_private_flag (FUTEX_WAKE, private)), \ + "d" (_nr), \ + "i" (0) /* phony, to align next arg's number */, \ + "i" (offsetof (tcbhead_t, sysinfo))); \ + } while (0) + + +/* NB: in the lll_trylock macro we simply return the value in %eax + after the cmpxchg instruction. In case the operation succeded this + value is zero. In case the operation failed, the cmpxchg instruction + has loaded the current value of the memory work which is guaranteed + to be nonzero. */ +#if defined NOT_IN_libc || defined UP +# define __lll_trylock_asm LOCK_INSTR "cmpxchgl %2, %1" +#else +# define __lll_trylock_asm "cmpl $0, %%gs:%P5\n\t" \ + "je 0f\n\t" \ + "lock\n" \ + "0:\tcmpxchgl %2, %1" +#endif + +#define lll_trylock(futex) \ + ({ int ret; \ + __asm__ __volatile__ (__lll_trylock_asm \ + : "=a" (ret), "=m" (futex) \ + : "r" (LLL_LOCK_INITIALIZER_LOCKED), "m" (futex), \ + "0" (LLL_LOCK_INITIALIZER), \ + "i" (MULTIPLE_THREADS_OFFSET) \ + : "memory"); \ + ret; }) + +#define lll_robust_trylock(futex, id) \ + ({ int ret; \ + __asm__ __volatile__ (LOCK_INSTR "cmpxchgl %2, %1" \ + : "=a" (ret), "=m" (futex) \ + : "r" (id), "m" (futex), \ + "0" (LLL_LOCK_INITIALIZER) \ + : "memory"); \ + ret; }) + + +#define lll_cond_trylock(futex) \ + ({ int ret; \ + __asm__ __volatile__ (LOCK_INSTR "cmpxchgl %2, %1" \ + : "=a" (ret), "=m" (futex) \ + : "r" (LLL_LOCK_INITIALIZER_WAITERS), \ + "m" (futex), "0" (LLL_LOCK_INITIALIZER) \ + : "memory"); \ + ret; }) + +#if defined NOT_IN_libc || defined UP +# define __lll_lock_asm_start LOCK_INSTR "cmpxchgl %1, %2\n\t" +#else +# define __lll_lock_asm_start "cmpl $0, %%gs:%P6\n\t" \ + "je 0f\n\t" \ + "lock\n" \ + "0:\tcmpxchgl %1, %2\n\t" +#endif + +#define lll_lock(futex, private) \ + (void) \ + ({ int ignore1, ignore2; \ + if (__builtin_constant_p (private) && (private) == LLL_PRIVATE) \ + __asm__ __volatile__ (__lll_lock_asm_start \ + "jnz _L_lock_%=\n\t" \ + ".subsection 1\n\t" \ + ".type _L_lock_%=,@function\n" \ + "_L_lock_%=:\n" \ + "1:\tleal %2, %%ecx\n" \ + "2:\tcall __lll_lock_wait_private\n" \ + "3:\tjmp 18f\n" \ + "4:\t.size _L_lock_%=, 4b-1b\n\t" \ + ".previous\n" \ + LLL_STUB_UNWIND_INFO_3 \ + "18:" \ + : "=a" (ignore1), "=c" (ignore2), "=m" (futex) \ + : "0" (0), "1" (1), "m" (futex), \ + "i" (MULTIPLE_THREADS_OFFSET) \ + : "memory"); \ + else \ + { \ + int ignore3; \ + __asm__ __volatile__ (__lll_lock_asm_start \ + "jnz _L_lock_%=\n\t" \ + ".subsection 1\n\t" \ + ".type _L_lock_%=,@function\n" \ + "_L_lock_%=:\n" \ + "1:\tleal %2, %%edx\n" \ + "0:\tmovl %8, %%ecx\n" \ + "2:\tcall __lll_lock_wait\n" \ + "3:\tjmp 18f\n" \ + "4:\t.size _L_lock_%=, 4b-1b\n\t" \ + ".previous\n" \ + LLL_STUB_UNWIND_INFO_4 \ + "18:" \ + : "=a" (ignore1), "=c" (ignore2), \ + "=m" (futex), "=&d" (ignore3) \ + : "1" (1), "m" (futex), \ + "i" (MULTIPLE_THREADS_OFFSET), "0" (0), \ + "g" ((int) (private)) \ + : "memory"); \ + } \ + }) + +#define lll_robust_lock(futex, id, private) \ + ({ int __result, ignore1, ignore2; \ + __asm__ __volatile__ (LOCK_INSTR "cmpxchgl %1, %2\n\t" \ + "jnz _L_robust_lock_%=\n\t" \ + ".subsection 1\n\t" \ + ".type _L_robust_lock_%=,@function\n" \ + "_L_robust_lock_%=:\n" \ + "1:\tleal %2, %%edx\n" \ + "0:\tmovl %7, %%ecx\n" \ + "2:\tcall __lll_robust_lock_wait\n" \ + "3:\tjmp 18f\n" \ + "4:\t.size _L_robust_lock_%=, 4b-1b\n\t" \ + ".previous\n" \ + LLL_STUB_UNWIND_INFO_4 \ + "18:" \ + : "=a" (__result), "=c" (ignore1), "=m" (futex), \ + "=&d" (ignore2) \ + : "0" (0), "1" (id), "m" (futex), "g" ((int) (private))\ + : "memory"); \ + __result; }) + + +/* Special version of lll_lock which causes the unlock function to + always wakeup waiters. */ +#define lll_cond_lock(futex, private) \ + (void) \ + ({ int ignore1, ignore2, ignore3; \ + __asm__ __volatile__ (LOCK_INSTR "cmpxchgl %1, %2\n\t" \ + "jnz _L_cond_lock_%=\n\t" \ + ".subsection 1\n\t" \ + ".type _L_cond_lock_%=,@function\n" \ + "_L_cond_lock_%=:\n" \ + "1:\tleal %2, %%edx\n" \ + "0:\tmovl %7, %%ecx\n" \ + "2:\tcall __lll_lock_wait\n" \ + "3:\tjmp 18f\n" \ + "4:\t.size _L_cond_lock_%=, 4b-1b\n\t" \ + ".previous\n" \ + LLL_STUB_UNWIND_INFO_4 \ + "18:" \ + : "=a" (ignore1), "=c" (ignore2), "=m" (futex), \ + "=&d" (ignore3) \ + : "0" (0), "1" (2), "m" (futex), "g" ((int) (private))\ + : "memory"); \ + }) + + +#define lll_robust_cond_lock(futex, id, private) \ + ({ int __result, ignore1, ignore2; \ + __asm__ __volatile__ (LOCK_INSTR "cmpxchgl %1, %2\n\t" \ + "jnz _L_robust_cond_lock_%=\n\t" \ + ".subsection 1\n\t" \ + ".type _L_robust_cond_lock_%=,@function\n" \ + "_L_robust_cond_lock_%=:\n" \ + "1:\tleal %2, %%edx\n" \ + "0:\tmovl %7, %%ecx\n" \ + "2:\tcall __lll_robust_lock_wait\n" \ + "3:\tjmp 18f\n" \ + "4:\t.size _L_robust_cond_lock_%=, 4b-1b\n\t" \ + ".previous\n" \ + LLL_STUB_UNWIND_INFO_4 \ + "18:" \ + : "=a" (__result), "=c" (ignore1), "=m" (futex), \ + "=&d" (ignore2) \ + : "0" (0), "1" (id | FUTEX_WAITERS), "m" (futex), \ + "g" ((int) (private)) \ + : "memory"); \ + __result; }) + + +#define lll_timedlock(futex, timeout, private) \ + ({ int __result, ignore1, ignore2, ignore3; \ + __asm__ __volatile__ (LOCK_INSTR "cmpxchgl %1, %3\n\t" \ + "jnz _L_timedlock_%=\n\t" \ + ".subsection 1\n\t" \ + ".type _L_timedlock_%=,@function\n" \ + "_L_timedlock_%=:\n" \ + "1:\tleal %3, %%ecx\n" \ + "0:\tmovl %8, %%edx\n" \ + "2:\tcall __lll_timedlock_wait\n" \ + "3:\tjmp 18f\n" \ + "4:\t.size _L_timedlock_%=, 4b-1b\n\t" \ + ".previous\n" \ + LLL_STUB_UNWIND_INFO_4 \ + "18:" \ + : "=a" (__result), "=c" (ignore1), "=&d" (ignore2), \ + "=m" (futex), "=S" (ignore3) \ + : "0" (0), "1" (1), "m" (futex), "m" (timeout), \ + "4" ((int) (private)) \ + : "memory"); \ + __result; }) + + +#define lll_robust_timedlock(futex, timeout, id, private) \ + ({ int __result, ignore1, ignore2, ignore3; \ + __asm__ __volatile__ (LOCK_INSTR "cmpxchgl %1, %3\n\t" \ + "jnz _L_robust_timedlock_%=\n\t" \ + ".subsection 1\n\t" \ + ".type _L_robust_timedlock_%=,@function\n" \ + "_L_robust_timedlock_%=:\n" \ + "1:\tleal %3, %%ecx\n" \ + "0:\tmovl %8, %%edx\n" \ + "2:\tcall __lll_robust_timedlock_wait\n" \ + "3:\tjmp 18f\n" \ + "4:\t.size _L_robust_timedlock_%=, 4b-1b\n\t" \ + ".previous\n" \ + LLL_STUB_UNWIND_INFO_4 \ + "18:" \ + : "=a" (__result), "=c" (ignore1), "=&d" (ignore2), \ + "=m" (futex), "=S" (ignore3) \ + : "0" (0), "1" (id), "m" (futex), "m" (timeout), \ + "4" ((int) (private)) \ + : "memory"); \ + __result; }) + +#if defined NOT_IN_libc || defined UP +# define __lll_unlock_asm LOCK_INSTR "subl $1, %0\n\t" +#else +# define __lll_unlock_asm "cmpl $0, %%gs:%P3\n\t" \ + "je 0f\n\t" \ + "lock\n" \ + "0:\tsubl $1,%0\n\t" +#endif + +#define lll_unlock(futex, private) \ + (void) \ + ({ int ignore; \ + if (__builtin_constant_p (private) && (private) == LLL_PRIVATE) \ + __asm__ __volatile__ (__lll_unlock_asm \ + "jne _L_unlock_%=\n\t" \ + ".subsection 1\n\t" \ + ".type _L_unlock_%=,@function\n" \ + "_L_unlock_%=:\n" \ + "1:\tleal %0, %%eax\n" \ + "2:\tcall __lll_unlock_wake_private\n" \ + "3:\tjmp 18f\n" \ + "4:\t.size _L_unlock_%=, 4b-1b\n\t" \ + ".previous\n" \ + LLL_STUB_UNWIND_INFO_3 \ + "18:" \ + : "=m" (futex), "=&a" (ignore) \ + : "m" (futex), "i" (MULTIPLE_THREADS_OFFSET) \ + : "memory"); \ + else \ + { \ + int ignore2; \ + __asm__ __volatile__ (__lll_unlock_asm \ + "jne _L_unlock_%=\n\t" \ + ".subsection 1\n\t" \ + ".type _L_unlock_%=,@function\n" \ + "_L_unlock_%=:\n" \ + "1:\tleal %0, %%eax\n" \ + "0:\tmovl %5, %%ecx\n" \ + "2:\tcall __lll_unlock_wake\n" \ + "3:\tjmp 18f\n" \ + "4:\t.size _L_unlock_%=, 4b-1b\n\t" \ + ".previous\n" \ + LLL_STUB_UNWIND_INFO_4 \ + "18:" \ + : "=m" (futex), "=&a" (ignore), "=&c" (ignore2) \ + : "i" (MULTIPLE_THREADS_OFFSET), "m" (futex), \ + "g" ((int) (private)) \ + : "memory"); \ + } \ + }) + +#define lll_robust_unlock(futex, private) \ + (void) \ + ({ int ignore, ignore2; \ + __asm__ __volatile__ (LOCK_INSTR "andl %3, %0\n\t" \ + "jne _L_robust_unlock_%=\n\t" \ + ".subsection 1\n\t" \ + ".type _L_robust_unlock_%=,@function\n" \ + "_L_robust_unlock_%=:\n\t" \ + "1:\tleal %0, %%eax\n" \ + "0:\tmovl %5, %%ecx\n" \ + "2:\tcall __lll_unlock_wake\n" \ + "3:\tjmp 18f\n" \ + "4:\t.size _L_robust_unlock_%=, 4b-1b\n\t" \ + ".previous\n" \ + LLL_STUB_UNWIND_INFO_4 \ + "18:" \ + : "=m" (futex), "=&a" (ignore), "=&c" (ignore2) \ + : "i" (FUTEX_WAITERS), "m" (futex), \ + "g" ((int) (private)) \ + : "memory"); \ + }) + + +#define lll_robust_dead(futex, private) \ + (void) \ + ({ int __ignore; \ + register int _nr __asm__ ("edx") = 1; \ + __asm__ __volatile__ (LOCK_INSTR "orl %5, (%2)\n\t" \ + LLL_EBX_LOAD \ + LLL_ENTER_KERNEL \ + LLL_EBX_LOAD \ + : "=a" (__ignore) \ + : "0" (SYS_futex), LLL_EBX_REG (&(futex)), \ + "c" (__lll_private_flag (FUTEX_WAKE, private)), \ + "d" (_nr), "i" (FUTEX_OWNER_DIED), \ + "i" (offsetof (tcbhead_t, sysinfo))); \ + }) + +#define lll_islocked(futex) \ + (futex != LLL_LOCK_INITIALIZER) + +/* The kernel notifies a process with uses CLONE_CLEARTID via futex + wakeup when the clone terminates. The memory location contains the + thread ID while the clone is running and is reset to zero + afterwards. + + The macro parameter must not have any side effect. */ +#define lll_wait_tid(tid) \ + do { \ + int __ignore; \ + register __typeof (tid) _tid __asm__ ("edx") = (tid); \ + if (_tid != 0) \ + __asm__ __volatile__ (LLL_EBX_LOAD \ + "1:\tmovl %1, %%eax\n\t" \ + LLL_ENTER_KERNEL \ + "cmpl $0, (%%ebx)\n\t" \ + "jne 1b\n\t" \ + LLL_EBX_LOAD \ + : "=&a" (__ignore) \ + : "i" (SYS_futex), LLL_EBX_REG (&tid), "S" (0), \ + "c" (FUTEX_WAIT), "d" (_tid), \ + "i" (offsetof (tcbhead_t, sysinfo)) \ + : "memory"); \ + } while (0) + +extern int __lll_timedwait_tid (int *tid, const struct timespec *abstime) + __attribute__ ((regparm (2))) attribute_hidden; +#define lll_timedwait_tid(tid, abstime) \ + ({ \ + int __result = 0; \ + if (tid != 0) \ + { \ + if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) \ + __result = EINVAL; \ + else \ + __result = __lll_timedwait_tid (&tid, abstime); \ + } \ + __result; }) + +#endif /* !__ASSEMBLER__ */ + +#endif /* lowlevellock.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/pt-__syscall_error.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/pt-__syscall_error.c new file mode 100644 index 00000000..620640ad --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/pt-__syscall_error.c @@ -0,0 +1 @@ +#include <../../../../../../../libc/sysdeps/linux/i386/__syscall_error.c> diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/pt-vfork.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/pt-vfork.S new file mode 100644 index 00000000..aff926a8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/pt-vfork.S @@ -0,0 +1,68 @@ +/* Copyright (C) 1999, 2002, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Andreas Schwab . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#define _ERRNO_H 1 +#include +#include +#include + +/* Save the PID value. */ +#define SAVE_PID \ + movl %gs:PID, %edx; \ + movl %edx, %eax; \ + negl %eax; \ + movl %eax, %gs:PID + +/* Restore the old PID value in the parent. */ +#define RESTORE_PID \ + testl %eax, %eax; \ + je 1f; \ + movl %edx, %gs:PID; \ +1: + +/* Clone the calling process, but without copying the whole address space. + The calling process is suspended until the new process exits or is + replaced by a call to `execve'. Return -1 for errors, 0 to the new process, + and the process ID of the new process to the old process. */ + +ENTRY (__vfork) + /* Pop the return PC value into ECX. */ + popl %ecx + + SAVE_PID + + /* Stuff the syscall number in EAX and enter into the kernel. */ + movl $SYS_ify (vfork), %eax + int $0x80 + + RESTORE_PID + + /* Jump to the return PC. Don't jump directly since this + disturbs the branch target cache. Instead push the return + address back on the stack. */ + pushl %ecx + + cmpl $-4095, %eax + jae SYSCALL_ERROR_LABEL /* Branch forward if it failed. */ +L(pseudo_end): + ret +PSEUDO_END (__vfork) + +weak_alias (__vfork, vfork) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/pthread_once.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/pthread_once.S new file mode 100644 index 00000000..7a2cbf46 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/pthread_once.S @@ -0,0 +1,197 @@ +/* Copyright (C) 2002, 2003, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include + + + .comm __fork_generation, 4, 4 + + .text + + + .globl __pthread_once + .type __pthread_once,@function + .protected __pthread_once + .align 16 + cfi_startproc +__pthread_once: + movl 4(%esp), %ecx + testl $2, (%ecx) + jz 1f + xorl %eax, %eax + ret + +1: pushl %ebx + cfi_adjust_cfa_offset (4) + cfi_rel_offset (3, 0) + pushl %esi + cfi_adjust_cfa_offset (4) + cfi_rel_offset (6, 0) + movl %ecx, %ebx + xorl %esi, %esi + + /* Not yet initialized or initialization in progress. + Get the fork generation counter now. */ +6: movl (%ebx), %eax +#ifdef __PIC__ + call __x86.get_pc_thunk.cx + addl $_GLOBAL_OFFSET_TABLE_, %ecx +#endif + +5: movl %eax, %edx + + testl $2, %eax + jnz 4f + + andl $3, %edx +#ifdef __PIC__ + orl __fork_generation@GOTOFF(%ecx), %edx +#else + orl __fork_generation, %edx +#endif + orl $1, %edx + + LOCK + cmpxchgl %edx, (%ebx) + jnz 5b + + /* Check whether another thread already runs the initializer. */ + testl $1, %eax + jz 3f /* No -> do it. */ + + /* Check whether the initializer execution was interrupted + by a fork. */ + xorl %edx, %eax + testl $0xfffffffc, %eax + jnz 3f /* Different for generation -> run initializer. */ + + /* Somebody else got here first. Wait. */ +#ifdef __ASSUME_PRIVATE_FUTEX + movl $FUTEX_WAIT|FUTEX_PRIVATE_FLAG, %ecx +#else +# if FUTEX_WAIT == 0 + movl %gs:PRIVATE_FUTEX, %ecx +# else + movl $FUTEX_WAIT, %ecx + orl %gs:PRIVATE_FUTEX, %ecx +# endif +#endif + movl $SYS_futex, %eax + ENTER_KERNEL + jmp 6b + +3: /* Call the initializer function after setting up the + cancellation handler. Note that it is not possible here + to use the unwind-based cleanup handling. This would require + that the user-provided function and all the code it calls + is compiled with exceptions. Unfortunately this cannot be + guaranteed. */ + subl $UNWINDBUFSIZE+8, %esp + cfi_adjust_cfa_offset (UNWINDBUFSIZE+8) + movl %ecx, %ebx /* PIC register value. */ + + leal 8+UWJMPBUF(%esp), %eax + movl $0, 4(%esp) + movl %eax, (%esp) + call __sigsetjmp@PLT + testl %eax, %eax + jne 7f + + leal 8(%esp), %eax + call HIDDEN_JUMPTARGET(__pthread_register_cancel) + + /* Call the user-provided initialization function. */ + call *24+UNWINDBUFSIZE(%esp) + + /* Pop the cleanup handler. */ + leal 8(%esp), %eax + call HIDDEN_JUMPTARGET(__pthread_unregister_cancel) + addl $UNWINDBUFSIZE+8, %esp + cfi_adjust_cfa_offset (-UNWINDBUFSIZE-8) + + /* Sucessful run of the initializer. Signal that we are done. */ + movl 12(%esp), %ebx + LOCK + addl $1, (%ebx) + + /* Wake up all other threads. */ + movl $0x7fffffff, %edx +#ifdef __ASSUME_PRIVATE_FUTEX + movl $FUTEX_WAKE|FUTEX_PRIVATE_FLAG, %ecx +#else + movl $FUTEX_WAKE, %ecx + orl %gs:PRIVATE_FUTEX, %ecx +#endif + movl $SYS_futex, %eax + ENTER_KERNEL + +4: popl %esi + cfi_adjust_cfa_offset (-4) + cfi_restore (6) + popl %ebx + cfi_adjust_cfa_offset (-4) + cfi_restore (3) + xorl %eax, %eax + ret + +7: /* __sigsetjmp returned for the second time. */ + movl 20+UNWINDBUFSIZE(%esp), %ebx + cfi_adjust_cfa_offset (UNWINDBUFSIZE+16) + cfi_offset (3, -8) + cfi_offset (6, -12) + movl $0, (%ebx) + + movl $0x7fffffff, %edx +#ifdef __ASSUME_PRIVATE_FUTEX + movl $FUTEX_WAKE|FUTEX_PRIVATE_FLAG, %ecx +#else + movl $FUTEX_WAKE, %ecx + orl %gs:PRIVATE_FUTEX, %ecx +#endif + movl $SYS_futex, %eax + ENTER_KERNEL + + leal 8(%esp), %eax + call HIDDEN_JUMPTARGET (__pthread_unwind_next) + /* NOTREACHED */ + hlt + cfi_endproc + .size __pthread_once,.-__pthread_once + + .globl __pthread_once_internal +__pthread_once_internal = __pthread_once + + .globl pthread_once +pthread_once = __pthread_once + + +#ifdef __PIC__ + .section .gnu.linkonce.t.__x86.get_pc_thunk.cx,"ax",@progbits + .globl __x86.get_pc_thunk.cx + .hidden __x86.get_pc_thunk.cx + .type __x86.get_pc_thunk.cx,@function +__x86.get_pc_thunk.cx: + movl (%esp), %ecx; + ret + .size __x86.get_pc_thunk.cx,.-__x86.get_pc_thunk.cx +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/pthread_spin_init.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/pthread_spin_init.c new file mode 100644 index 00000000..d36e5373 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/pthread_spin_init.c @@ -0,0 +1 @@ +#include diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/pthread_spin_unlock.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/pthread_spin_unlock.S new file mode 100644 index 00000000..8bae0fd3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/pthread_spin_unlock.S @@ -0,0 +1 @@ +#include diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/smp.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/smp.h new file mode 100644 index 00000000..f68a0c07 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/smp.h @@ -0,0 +1,56 @@ +/* Determine whether the host has multiple processors. Linux version. + Copyright (C) 1996, 2002, 2004, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include +#include + +/* Test whether the machine has more than one processor. This is not the + best test but good enough. More complicated tests would require `malloc' + which is not available at that time. */ +static inline int +is_smp_system (void) +{ + union + { + struct utsname uts; + char buf[512]; + } u; + char *cp; + + /* Try reading the number using `sysctl' first. */ + if (uname (&u.uts) == 0) + cp = u.uts.version; + else + { + /* This was not successful. Now try reading the /proc filesystem. */ + int fd = open_not_cancel_2 ("/proc/sys/kernel/version", O_RDONLY); + if (__builtin_expect (fd, 0) == -1 + || read_not_cancel (fd, u.buf, sizeof (u.buf)) <= 0) + /* This also didn't work. We give up and say it's a UP machine. */ + u.buf[0] = '\0'; + + close_not_cancel_no_status (fd); + cp = u.buf; + } + + return strstr (cp, "SMP") != NULL; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/sysdep-cancel.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/sysdep-cancel.h new file mode 100644 index 00000000..cb8d6891 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/sysdep-cancel.h @@ -0,0 +1,155 @@ +/* Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#ifndef __ASSEMBLER__ +# include +#endif + +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + +# undef PSEUDO +# define PSEUDO(name, syscall_name, args) \ + .text; \ + ENTRY (name) \ + cmpl $0, %gs:MULTIPLE_THREADS_OFFSET; \ + jne L(pseudo_cancel); \ + .type __##syscall_name##_nocancel,@function; \ + .globl __##syscall_name##_nocancel; \ + __##syscall_name##_nocancel: \ + DO_CALL (syscall_name, args); \ + cmpl $-4095, %eax; \ + jae SYSCALL_ERROR_LABEL; \ + ret; \ + .size __##syscall_name##_nocancel,.-__##syscall_name##_nocancel; \ + L(pseudo_cancel): \ + CENABLE \ + SAVE_OLDTYPE_##args \ + PUSHCARGS_##args \ + DOCARGS_##args \ + movl $SYS_ify (syscall_name), %eax; \ + ENTER_KERNEL; \ + POPCARGS_##args; \ + POPSTATE_##args \ + cmpl $-4095, %eax; \ + jae SYSCALL_ERROR_LABEL; \ + L(pseudo_end): + +# define SAVE_OLDTYPE_0 movl %eax, %ecx; +# define SAVE_OLDTYPE_1 SAVE_OLDTYPE_0 +# define SAVE_OLDTYPE_2 pushl %eax; cfi_adjust_cfa_offset (4); +# define SAVE_OLDTYPE_3 SAVE_OLDTYPE_2 +# define SAVE_OLDTYPE_4 SAVE_OLDTYPE_2 +# define SAVE_OLDTYPE_5 SAVE_OLDTYPE_2 +# define SAVE_OLDTYPE_6 SAVE_OLDTYPE_2 + +# define PUSHCARGS_0 /* No arguments to push. */ +# define DOCARGS_0 /* No arguments to frob. */ +# define POPCARGS_0 /* No arguments to pop. */ +# define _PUSHCARGS_0 /* No arguments to push. */ +# define _POPCARGS_0 /* No arguments to pop. */ + +# define PUSHCARGS_1 movl %ebx, %edx; cfi_register (ebx, edx); PUSHCARGS_0 +# define DOCARGS_1 _DOARGS_1 (4) +# define POPCARGS_1 POPCARGS_0; movl %edx, %ebx; cfi_restore (ebx); +# define _PUSHCARGS_1 pushl %ebx; cfi_adjust_cfa_offset (4); \ + cfi_rel_offset (ebx, 0); _PUSHCARGS_0 +# define _POPCARGS_1 _POPCARGS_0; popl %ebx; \ + cfi_adjust_cfa_offset (-4); cfi_restore (ebx); + +# define PUSHCARGS_2 PUSHCARGS_1 +# define DOCARGS_2 _DOARGS_2 (12) +# define POPCARGS_2 POPCARGS_1 +# define _PUSHCARGS_2 _PUSHCARGS_1 +# define _POPCARGS_2 _POPCARGS_1 + +# define PUSHCARGS_3 _PUSHCARGS_2 +# define DOCARGS_3 _DOARGS_3 (20) +# define POPCARGS_3 _POPCARGS_3 +# define _PUSHCARGS_3 _PUSHCARGS_2 +# define _POPCARGS_3 _POPCARGS_2 + +# define PUSHCARGS_4 _PUSHCARGS_4 +# define DOCARGS_4 _DOARGS_4 (28) +# define POPCARGS_4 _POPCARGS_4 +# define _PUSHCARGS_4 pushl %esi; cfi_adjust_cfa_offset (4); \ + cfi_rel_offset (esi, 0); _PUSHCARGS_3 +# define _POPCARGS_4 _POPCARGS_3; popl %esi; \ + cfi_adjust_cfa_offset (-4); cfi_restore (esi); + +# define PUSHCARGS_5 _PUSHCARGS_5 +# define DOCARGS_5 _DOARGS_5 (36) +# define POPCARGS_5 _POPCARGS_5 +# define _PUSHCARGS_5 pushl %edi; cfi_adjust_cfa_offset (4); \ + cfi_rel_offset (edi, 0); _PUSHCARGS_4 +# define _POPCARGS_5 _POPCARGS_4; popl %edi; \ + cfi_adjust_cfa_offset (-4); cfi_restore (edi); + +# define PUSHCARGS_6 _PUSHCARGS_6 +# define DOCARGS_6 _DOARGS_6 (44) +# define POPCARGS_6 _POPCARGS_6 +# define _PUSHCARGS_6 pushl %ebp; cfi_adjust_cfa_offset (4); \ + cfi_rel_offset (ebp, 0); _PUSHCARGS_5 +# define _POPCARGS_6 _POPCARGS_5; popl %ebp; \ + cfi_adjust_cfa_offset (-4); cfi_restore (ebp); + +# ifdef IS_IN_libpthread +# define CENABLE call __pthread_enable_asynccancel; +# define CDISABLE call __pthread_disable_asynccancel +# elif !defined NOT_IN_libc +# define CENABLE call __libc_enable_asynccancel; +# define CDISABLE call __libc_disable_asynccancel +# elif defined IS_IN_librt +# define CENABLE call __librt_enable_asynccancel; +# define CDISABLE call __librt_disable_asynccancel +# else +# error Unsupported library +# endif +# define POPSTATE_0 \ + pushl %eax; cfi_adjust_cfa_offset (4); movl %ecx, %eax; \ + CDISABLE; popl %eax; cfi_adjust_cfa_offset (-4); +# define POPSTATE_1 POPSTATE_0 +# define POPSTATE_2 xchgl (%esp), %eax; CDISABLE; popl %eax; \ + cfi_adjust_cfa_offset (-4); +# define POPSTATE_3 POPSTATE_2 +# define POPSTATE_4 POPSTATE_3 +# define POPSTATE_5 POPSTATE_4 +# define POPSTATE_6 POPSTATE_5 + +# ifndef __ASSEMBLER__ +# define SINGLE_THREAD_P \ + __builtin_expect (THREAD_GETMEM (THREAD_SELF, \ + header.multiple_threads) == 0, 1) +# else +# define SINGLE_THREAD_P cmpl $0, %gs:MULTIPLE_THREADS_OFFSET +# endif + +#elif !defined __ASSEMBLER__ + +# define SINGLE_THREAD_P (1) +# define NO_CANCELLATION 1 + +#endif + +#ifndef __ASSEMBLER__ +# define RTLD_SINGLE_THREAD_P \ + __builtin_expect (THREAD_GETMEM (THREAD_SELF, \ + header.multiple_threads) == 0, 1) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/vfork.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/vfork.S new file mode 100644 index 00000000..b39099af --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/i386/vfork.S @@ -0,0 +1,38 @@ +/* Copyright (C) 1999,2002,2004,2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +/* Save the PID value. */ +#define SAVE_PID \ + movl %gs:PID, %edx; \ + movl %edx, %eax; \ + negl %eax; \ + jne 1f; \ + movl $0x80000000, %eax; \ +1: movl %eax, %gs:PID + +/* Restore the old PID value in the parent. */ +#define RESTORE_PID \ + testl %eax, %eax; \ + je 1f; \ + movl %edx, %gs:PID; \ +1: + + +#include diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/internaltypes.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/internaltypes.h new file mode 100644 index 00000000..3466c7fe --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/internaltypes.h @@ -0,0 +1,162 @@ +/* Copyright (C) 2002, 2003, 2004, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _INTERNALTYPES_H +#define _INTERNALTYPES_H 1 + +#include +#include + +struct pthread_attr +{ + /* Scheduler parameters and priority. */ + struct sched_param schedparam; + int schedpolicy; + /* Various flags like detachstate, scope, etc. */ + int flags; + /* Size of guard area. */ + size_t guardsize; + /* Stack handling. */ + void *stackaddr; + size_t stacksize; + /* Affinity map. */ + cpu_set_t *cpuset; + size_t cpusetsize; +}; + +#define ATTR_FLAG_DETACHSTATE 0x0001 +#define ATTR_FLAG_NOTINHERITSCHED 0x0002 +#define ATTR_FLAG_SCOPEPROCESS 0x0004 +#define ATTR_FLAG_STACKADDR 0x0008 +#define ATTR_FLAG_OLDATTR 0x0010 +#define ATTR_FLAG_SCHED_SET 0x0020 +#define ATTR_FLAG_POLICY_SET 0x0040 + + +/* Mutex attribute data structure. */ +struct pthread_mutexattr +{ + /* Identifier for the kind of mutex. + + Bit 31 is set if the mutex is to be shared between processes. + + Bit 0 to 30 contain one of the PTHREAD_MUTEX_ values to identify + the type of the mutex. */ + int mutexkind; +}; + + +/* Conditional variable attribute data structure. */ +struct pthread_condattr +{ + /* Combination of values: + + Bit 0 : flag whether coditional variable will be shareable between + processes. + + Bit 1-7: clock ID. */ + int value; +}; + + +/* The __NWAITERS field is used as a counter and to house the number + of bits for other purposes. COND_CLOCK_BITS is the number + of bits needed to represent the ID of the clock. COND_NWAITERS_SHIFT + is the number of bits reserved for other purposes like the clock. */ +#define COND_CLOCK_BITS 1 +#define COND_NWAITERS_SHIFT 1 + + +/* Read-write lock variable attribute data structure. */ +struct pthread_rwlockattr +{ + int lockkind; + int pshared; +}; + + +/* Barrier data structure. */ +struct pthread_barrier +{ + unsigned int curr_event; + int lock; + unsigned int left; + unsigned int init_count; + int private; +}; + + +/* Barrier variable attribute data structure. */ +struct pthread_barrierattr +{ + int pshared; +}; + + +/* Thread-local data handling. */ +struct pthread_key_struct +{ + /* Sequence numbers. Even numbers indicated vacant entries. Note + that zero is even. We use uintptr_t to not require padding on + 32- and 64-bit machines. On 64-bit machines it helps to avoid + wrapping, too. */ + uintptr_t seq; + + /* Destructor for the data. */ + void (*destr) (void *); +}; + +/* Check whether an entry is unused. */ +#define KEY_UNUSED(p) (((p) & 1) == 0) +/* Check whether a key is usable. We cannot reuse an allocated key if + the sequence counter would overflow after the next destroy call. + This would mean that we potentially free memory for a key with the + same sequence. This is *very* unlikely to happen, A program would + have to create and destroy a key 2^31 times (on 32-bit platforms, + on 64-bit platforms that would be 2^63). If it should happen we + simply don't use this specific key anymore. */ +#define KEY_USABLE(p) (((uintptr_t) (p)) < ((uintptr_t) ((p) + 2))) + + +/* Handling of read-write lock data. */ +// XXX For now there is only one flag. Maybe more in future. +#define RWLOCK_RECURSIVE(rwlock) ((rwlock)->__data.__flags != 0) + + +/* Semaphore variable structure. */ +struct new_sem +{ + unsigned int value; + int private; + unsigned long int nwaiters; +}; + +struct old_sem +{ + unsigned int value; +}; + + +/* Compatibility type for old conditional variable interfaces. */ +typedef struct +{ + pthread_cond_t *cond; +} pthread_cond_2_0_t; + +#endif /* internaltypes.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/jmp-unwind.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/jmp-unwind.c new file mode 100644 index 00000000..f2795510 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/jmp-unwind.c @@ -0,0 +1,39 @@ +/* Clean up stack frames unwound by longjmp. Linux version. + Copyright (C) 1995, 1997, 2002, 2003, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +extern void __pthread_cleanup_upto (__jmp_buf env, char *targetframe); +#pragma weak __pthread_cleanup_upto + + +void +_longjmp_unwind (jmp_buf env, int val) +{ +#ifdef SHARED + if (__libc_pthread_functions_init) + PTHFCT_CALL (ptr___pthread_cleanup_upto, (env->__jmpbuf, + CURRENT_STACK_FRAME)); +#else + if (__pthread_cleanup_upto != NULL) + __pthread_cleanup_upto (env->__jmpbuf, CURRENT_STACK_FRAME); +#endif +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/kernel-posix-timers.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/kernel-posix-timers.h new file mode 100644 index 00000000..9be63026 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/kernel-posix-timers.h @@ -0,0 +1 @@ +#include <../../../../../../librt/kernel-posix-timers.h> diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/libc-lowlevellock.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/libc-lowlevellock.c new file mode 100644 index 00000000..b1928228 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/libc-lowlevellock.c @@ -0,0 +1,21 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Paul Mackerras , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* No difference to lowlevellock.c, except we lose a couple of functions. */ +#include "lowlevellock.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/libc_multiple_threads.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/libc_multiple_threads.c new file mode 100644 index 00000000..a96f1749 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/libc_multiple_threads.c @@ -0,0 +1,26 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#ifndef NOT_IN_libc +# ifndef TLS_MULTIPLE_THREADS_IN_TCB +int __libc_multiple_threads attribute_hidden; +# endif +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/libc_pthread_init.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/libc_pthread_init.c new file mode 100644 index 00000000..136b4459 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/libc_pthread_init.c @@ -0,0 +1,74 @@ +/* Copyright (C) 2002,2003,2005,2006,2007,2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#ifdef TLS_MULTIPLE_THREADS_IN_TCB +void +#else +extern int __libc_multiple_threads attribute_hidden; + +int * +#endif +__libc_pthread_init ( + unsigned long int *ptr, + void (*reclaim) (void), + const struct pthread_functions *functions) +{ + /* Remember the pointer to the generation counter in libpthread. */ + __fork_generation_pointer = ptr; + + /* Called by a child after fork. */ + __register_atfork (NULL, NULL, reclaim, NULL); + +#ifdef SHARED + /* We copy the content of the variable pointed to by the FUNCTIONS + parameter to one in libc.so since this means access to the array + can be done with one memory access instead of two. + */ + memcpy (&__libc_pthread_functions, functions, + sizeof (__libc_pthread_functions)); + __libc_pthread_functions_init = 1; +#endif + +#ifndef TLS_MULTIPLE_THREADS_IN_TCB + return &__libc_multiple_threads; +#endif +} + +#ifdef SHARED +#if 0 +void +libc_freeres_fn (freeres_libptread) +{ + if (__libc_pthread_functions_init) + PTHFCT_CALL (ptr_freeres, ()); +} +#endif +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevelbarrier.sym b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevelbarrier.sym new file mode 100644 index 00000000..cfe22b08 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevelbarrier.sym @@ -0,0 +1,12 @@ +#include +#include +#include +#include "internaltypes.h" + +-- + +CURR_EVENT offsetof (struct pthread_barrier, curr_event) +MUTEX offsetof (struct pthread_barrier, lock) +LEFT offsetof (struct pthread_barrier, left) +INIT_COUNT offsetof (struct pthread_barrier, init_count) +PRIVATE offsetof (struct pthread_barrier, private) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevelcond.sym b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevelcond.sym new file mode 100644 index 00000000..18e1adad --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevelcond.sym @@ -0,0 +1,16 @@ +#include +#include +#include +#include + +-- + +cond_lock offsetof (pthread_cond_t, __data.__lock) +cond_futex offsetof (pthread_cond_t, __data.__futex) +cond_nwaiters offsetof (pthread_cond_t, __data.__nwaiters) +total_seq offsetof (pthread_cond_t, __data.__total_seq) +wakeup_seq offsetof (pthread_cond_t, __data.__wakeup_seq) +woken_seq offsetof (pthread_cond_t, __data.__woken_seq) +dep_mutex offsetof (pthread_cond_t, __data.__mutex) +broadcast_seq offsetof (pthread_cond_t, __data.__broadcast_seq) +nwaiters_shift COND_NWAITERS_SHIFT diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevellock.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevellock.c new file mode 100644 index 00000000..e07d7881 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevellock.c @@ -0,0 +1,127 @@ +/* low level locking for pthread library. Generic futex-using version. + Copyright (C) 2003, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Paul Mackerras , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include + + +void +__lll_lock_wait_private (int *futex) +{ + if (*futex == 2) + lll_futex_wait (futex, 2, LLL_PRIVATE); + + while (atomic_exchange_acq (futex, 2) != 0) + lll_futex_wait (futex, 2, LLL_PRIVATE); +} + + +/* These functions don't get included in libc.so */ +#ifdef IS_IN_libpthread +void +__lll_lock_wait (int *futex, int private) +{ + if (*futex == 2) + lll_futex_wait (futex, 2, private); + + while (atomic_exchange_acq (futex, 2) != 0) + lll_futex_wait (futex, 2, private); +} + + +int +__lll_timedlock_wait (int *futex, const struct timespec *abstime, int private) +{ + /* Reject invalid timeouts. */ + if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) + return EINVAL; + + /* Try locking. */ + while (atomic_exchange_acq (futex, 2) != 0) + { + struct timeval tv; + + /* Get the current time. */ + (void) gettimeofday (&tv, NULL); + + /* Compute relative timeout. */ + struct timespec rt; + rt.tv_sec = abstime->tv_sec - tv.tv_sec; + rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000; + if (rt.tv_nsec < 0) + { + rt.tv_nsec += 1000000000; + --rt.tv_sec; + } + + if (rt.tv_sec < 0) + return ETIMEDOUT; + + /* Wait. */ + lll_futex_timed_wait (futex, 2, &rt, private); + } + + return 0; +} + + +int +__lll_timedwait_tid (int *tidp, const struct timespec *abstime) +{ + int tid; + + if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) + return EINVAL; + + /* Repeat until thread terminated. */ + while ((tid = *tidp) != 0) + { + struct timeval tv; + struct timespec rt; + + /* Get the current time. */ + (void) __gettimeofday (&tv, NULL); + + /* Compute relative timeout. */ + rt.tv_sec = abstime->tv_sec - tv.tv_sec; + rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000; + if (rt.tv_nsec < 0) + { + rt.tv_nsec += 1000000000; + --rt.tv_sec; + } + + /* Already timed out? */ + if (rt.tv_sec < 0) + return ETIMEDOUT; + + /* Wait until thread terminates. The kernel so far does not use + the private futex operations for this. */ + if (lll_futex_timed_wait (tidp, tid, &rt, LLL_SHARED) == -ETIMEDOUT) + return ETIMEDOUT; + } + + return 0; +} +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevelrobustlock.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevelrobustlock.c new file mode 100644 index 00000000..3830f94d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevelrobustlock.c @@ -0,0 +1,114 @@ +/* Copyright (C) 2006, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2006. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include + + +int +__lll_robust_lock_wait (int *futex, int private) +{ + int oldval = *futex; + int tid = THREAD_GETMEM (THREAD_SELF, tid); + + /* If the futex changed meanwhile try locking again. */ + if (oldval == 0) + goto try; + + do + { + if (__builtin_expect (oldval & FUTEX_OWNER_DIED, 0)) + return oldval; + + int newval = oldval | FUTEX_WAITERS; + if (oldval != newval + && atomic_compare_and_exchange_bool_acq (futex, newval, oldval)) + continue; + + lll_futex_wait (futex, newval, private); + + try: + ; + } + while ((oldval = atomic_compare_and_exchange_val_acq (futex, + tid | FUTEX_WAITERS, + 0)) != 0); + return 0; +} + + +int +__lll_robust_timedlock_wait (int *futex, const struct timespec *abstime, + int private) +{ + /* Reject invalid timeouts. */ + if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) + return EINVAL; + + int tid = THREAD_GETMEM (THREAD_SELF, tid); + int oldval = *futex; + + /* If the futex changed meanwhile try locking again. */ + if (oldval == 0) + goto try; + + do + { + struct timeval tv; + struct timespec rt; + + /* Get the current time. */ + (void) __gettimeofday (&tv, NULL); + + /* Compute relative timeout. */ + rt.tv_sec = abstime->tv_sec - tv.tv_sec; + rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000; + if (rt.tv_nsec < 0) + { + rt.tv_nsec += 1000000000; + --rt.tv_sec; + } + + /* Already timed out? */ + if (rt.tv_sec < 0) + return ETIMEDOUT; + + /* Wait. */ + if (__builtin_expect (oldval & FUTEX_OWNER_DIED, 0)) + return oldval; + + int newval = oldval | FUTEX_WAITERS; + if (oldval != newval + && atomic_compare_and_exchange_bool_acq (futex, newval, oldval)) + continue; + + lll_futex_timed_wait (futex, newval, &rt, private); + + try: + ; + } + while ((oldval = atomic_compare_and_exchange_val_acq (futex, + tid | FUTEX_WAITERS, + 0)) != 0); + + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevelrobustlock.sym b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevelrobustlock.sym new file mode 100644 index 00000000..2f1e9da5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevelrobustlock.sym @@ -0,0 +1,6 @@ +#include +#include + +-- + +TID offsetof (struct pthread, tid) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevelrwlock.sym b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevelrwlock.sym new file mode 100644 index 00000000..f50b25bf --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/lowlevelrwlock.sym @@ -0,0 +1,16 @@ +#include +#include +#include +#include + +-- + +MUTEX offsetof (pthread_rwlock_t, __data.__lock) +NR_READERS offsetof (pthread_rwlock_t, __data.__nr_readers) +READERS_WAKEUP offsetof (pthread_rwlock_t, __data.__readers_wakeup) +WRITERS_WAKEUP offsetof (pthread_rwlock_t, __data.__writer_wakeup) +READERS_QUEUED offsetof (pthread_rwlock_t, __data.__nr_readers_queued) +WRITERS_QUEUED offsetof (pthread_rwlock_t, __data.__nr_writers_queued) +FLAGS offsetof (pthread_rwlock_t, __data.__flags) +WRITER offsetof (pthread_rwlock_t, __data.__writer) +PSHARED offsetof (pthread_rwlock_t, __data.__shared) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/lseek.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/lseek.S new file mode 100644 index 00000000..70a920ba --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/lseek.S @@ -0,0 +1,7 @@ +#include +PSEUDO (__libc_lseek, lseek, 3) +ret +PSEUDO_END (__libc_lseek) +libc_hidden_def (__libc_lseek) +weak_alias (__libc_lseek, lseek) +libc_hidden_weak (lseek) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/mips/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/mips/Makefile new file mode 100644 index 00000000..43a6fad8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/mips/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc NPTL +# +# Copyright (C) 2005 Steven J. Hill +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../../../../../ +top_builddir=../../../../../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.arch +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/mips/Makefile.arch b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/mips/Makefile.arch new file mode 100644 index 00000000..84fe17e8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/mips/Makefile.arch @@ -0,0 +1,25 @@ +# Makefile for uClibc NPTL +# +# Copyright (C) 2006 Steven J. Hill +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +libpthread_linux_arch_SSRC = pt-vfork.S clone.S +libpthread_linux_arch_CSRC = pthread_once.c pt-__syscall_rt_sigaction.c + +libc_linux_arch_CSRC = fork.c +libc_linux_arch_SSRC = clone.S vfork.S + +ASFLAGS += -DUSE___THREAD + +CFLAGS-OMIT-fork.c = -DNOT_IN_libc -DIS_IN_libpthread +ifeq ($(UCLIBC_HAS_STDIO_FUTEXES),y) +CFLAGS-fork.c = -D__USE_STDIO_FUTEXES__ +endif +CFLAGS-pthread_once.c = -DNOT_IN_libc -DIS_IN_libpthread +CFLAGS-pt-__syscall_rt_sigaction.c = -DNOT_IN_libc -DIS_IN_libpthread +ASFLAGS-pt-vfork.S = -DNOT_IN_libc -DIS_IN_libpthread + +ASFLAGS-clone.S = -D_LIBC_REENTRANT +ASFLAGS-vfork.S = -D_LIBC_REENTRANT diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/mips/bits/pthreadtypes.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/mips/bits/pthreadtypes.h new file mode 100644 index 00000000..bd4b7a30 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/mips/bits/pthreadtypes.h @@ -0,0 +1,230 @@ +/* Machine-specific pthread type layouts. MIPS version. + Copyright (C) 2005, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _BITS_PTHREADTYPES_H +#define _BITS_PTHREADTYPES_H 1 + +#include +#include + +#if _MIPS_SIM == _ABI64 +# define __SIZEOF_PTHREAD_ATTR_T 56 +# define __SIZEOF_PTHREAD_MUTEX_T 40 +# define __SIZEOF_PTHREAD_MUTEXATTR_T 4 +# define __SIZEOF_PTHREAD_COND_T 48 +# define __SIZEOF_PTHREAD_CONDATTR_T 4 +# define __SIZEOF_PTHREAD_RWLOCK_T 56 +# define __SIZEOF_PTHREAD_RWLOCKATTR_T 8 +# define __SIZEOF_PTHREAD_BARRIER_T 32 +# define __SIZEOF_PTHREAD_BARRIERATTR_T 4 +#else +# define __SIZEOF_PTHREAD_ATTR_T 36 +# define __SIZEOF_PTHREAD_MUTEX_T 24 +# define __SIZEOF_PTHREAD_MUTEXATTR_T 4 +# define __SIZEOF_PTHREAD_COND_T 48 +# define __SIZEOF_PTHREAD_CONDATTR_T 4 +# define __SIZEOF_PTHREAD_RWLOCK_T 32 +# define __SIZEOF_PTHREAD_RWLOCKATTR_T 8 +# define __SIZEOF_PTHREAD_BARRIER_T 20 +# define __SIZEOF_PTHREAD_BARRIERATTR_T 4 +#endif + + +/* Thread identifiers. The structure of the attribute type is + deliberately not exposed. */ +typedef unsigned long int pthread_t; + + +typedef union +{ + char __size[__SIZEOF_PTHREAD_ATTR_T]; + long int __align; +} pthread_attr_t; + + +#if _MIPS_SIM == _ABI64 +typedef struct __pthread_internal_list +{ + struct __pthread_internal_list *__prev; + struct __pthread_internal_list *__next; +} __pthread_list_t; +#else +typedef struct __pthread_internal_slist +{ + struct __pthread_internal_slist *__next; +} __pthread_slist_t; +#endif + + +/* Data structures for mutex handling. The structure of the attribute + type is deliberately not exposed. */ +typedef union +{ + struct __pthread_mutex_s + { + int __lock; + unsigned int __count; + int __owner; +#if _MIPS_SIM == _ABI64 + unsigned int __nusers; +#endif + /* KIND must stay at this position in the structure to maintain + binary compatibility. */ + int __kind; +#if _MIPS_SIM == _ABI64 + int __spins; + __pthread_list_t __list; +# define __PTHREAD_MUTEX_HAVE_PREV 1 +#else + unsigned int __nusers; + __extension__ union + { + int __spins; + __pthread_slist_t __list; + }; +#endif + } __data; + char __size[__SIZEOF_PTHREAD_MUTEX_T]; + long int __align; +} pthread_mutex_t; + +typedef union +{ + char __size[__SIZEOF_PTHREAD_MUTEXATTR_T]; + int __align; +} pthread_mutexattr_t; + + +/* Data structure for conditional variable handling. The structure of + the attribute type is deliberately not exposed. */ +typedef union +{ + struct + { + int __lock; + unsigned int __futex; + __extension__ unsigned long long int __total_seq; + __extension__ unsigned long long int __wakeup_seq; + __extension__ unsigned long long int __woken_seq; + void *__mutex; + unsigned int __nwaiters; + unsigned int __broadcast_seq; + } __data; + char __size[__SIZEOF_PTHREAD_COND_T]; + __extension__ long long int __align; +} pthread_cond_t; + +typedef union +{ + char __size[__SIZEOF_PTHREAD_CONDATTR_T]; + int __align; +} pthread_condattr_t; + + +/* Keys for thread-specific data */ +typedef unsigned int pthread_key_t; + + +/* Once-only execution */ +typedef int pthread_once_t; + + +#if defined __USE_UNIX98 || defined __USE_XOPEN2K +/* Data structure for read-write lock variable handling. The + structure of the attribute type is deliberately not exposed. */ +typedef union +{ +# if _MIPS_SIM == _ABI64 + struct + { + int __lock; + unsigned int __nr_readers; + unsigned int __readers_wakeup; + unsigned int __writer_wakeup; + unsigned int __nr_readers_queued; + unsigned int __nr_writers_queued; + int __writer; + int __shared; + unsigned long int __pad1; + unsigned long int __pad2; + /* FLAGS must stay at this position in the structure to maintain + binary compatibility. */ + unsigned int __flags; + } __data; +# else + struct + { + int __lock; + unsigned int __nr_readers; + unsigned int __readers_wakeup; + unsigned int __writer_wakeup; + unsigned int __nr_readers_queued; + unsigned int __nr_writers_queued; +#if __BYTE_ORDER == __BIG_ENDIAN + unsigned char __pad1; + unsigned char __pad2; + unsigned char __shared; + /* FLAGS must stay at this position in the structure to maintain + binary compatibility. */ + unsigned char __flags; +#else + /* FLAGS must stay at this position in the structure to maintain + binary compatibility. */ + unsigned char __flags; + unsigned char __shared; + unsigned char __pad1; + unsigned char __pad2; +#endif + int __writer; + } __data; +# endif + char __size[__SIZEOF_PTHREAD_RWLOCK_T]; + long int __align; +} pthread_rwlock_t; + +typedef union +{ + char __size[__SIZEOF_PTHREAD_RWLOCKATTR_T]; + long int __align; +} pthread_rwlockattr_t; +#endif + + +#ifdef __USE_XOPEN2K +/* POSIX spinlock data type. */ +typedef volatile int pthread_spinlock_t; + + +/* POSIX barriers data type. The structure of the type is + deliberately not exposed. */ +typedef union +{ + char __size[__SIZEOF_PTHREAD_BARRIER_T]; + long int __align; +} pthread_barrier_t; + +typedef union +{ + char __size[__SIZEOF_PTHREAD_BARRIERATTR_T]; + int __align; +} pthread_barrierattr_t; +#endif + + +#endif /* bits/pthreadtypes.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/mips/bits/semaphore.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/mips/bits/semaphore.h new file mode 100644 index 00000000..af43a604 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/mips/bits/semaphore.h @@ -0,0 +1,37 @@ +/* Copyright (C) 2002, 2005, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SEMAPHORE_H +# error "Never use directly; include instead." +#endif + +#if _MIPS_SIM == _ABI64 +# define __SIZEOF_SEM_T 32 +#else +# define __SIZEOF_SEM_T 16 +#endif + +/* Value returned if `sem_open' failed. */ +#define SEM_FAILED ((sem_t *) 0) + + +typedef union +{ + char __size[__SIZEOF_SEM_T]; + long int __align; +} sem_t; diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/mips/clone.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/mips/clone.S new file mode 100644 index 00000000..858877f0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/mips/clone.S @@ -0,0 +1,2 @@ +#define RESET_PID +#include diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/mips/createthread.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/mips/createthread.c new file mode 100644 index 00000000..d8a7c553 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/mips/createthread.c @@ -0,0 +1,24 @@ +/* Copyright (C) 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Value passed to 'clone' for initialization of the thread register. */ +#define TLS_VALUE ((void *) (pd) \ + + TLS_TCB_OFFSET + TLS_PRE_TCB_SIZE) + +/* Get the real implementation. */ +#include diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/mips/fork.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/mips/fork.c new file mode 100644 index 00000000..06b7e1c6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/mips/fork.c @@ -0,0 +1 @@ +#include "../i386/fork.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/mips/lowlevellock.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/mips/lowlevellock.h new file mode 100644 index 00000000..01bcf412 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/mips/lowlevellock.h @@ -0,0 +1,295 @@ +/* Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, + 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _LOWLEVELLOCK_H +#define _LOWLEVELLOCK_H 1 + +#include +#include +#include +#include +#include +#include + +#define FUTEX_WAIT 0 +#define FUTEX_WAKE 1 +#define FUTEX_REQUEUE 3 +#define FUTEX_CMP_REQUEUE 4 +#define FUTEX_WAKE_OP 5 +#define FUTEX_OP_CLEAR_WAKE_IF_GT_ONE ((4 << 24) | 1) +#define FUTEX_LOCK_PI 6 +#define FUTEX_UNLOCK_PI 7 +#define FUTEX_TRYLOCK_PI 8 +#define FUTEX_WAIT_BITSET 9 +#define FUTEX_WAKE_BITSET 10 +#define FUTEX_PRIVATE_FLAG 128 +#define FUTEX_CLOCK_REALTIME 256 + +#define FUTEX_BITSET_MATCH_ANY 0xffffffff + +/* Values for 'private' parameter of locking macros. Yes, the + definition seems to be backwards. But it is not. The bit will be + reversed before passing to the system call. */ +#define LLL_PRIVATE 0 +#define LLL_SHARED FUTEX_PRIVATE_FLAG + + +#if !defined NOT_IN_libc || defined IS_IN_rtld +/* In libc.so or ld.so all futexes are private. */ +# ifdef __ASSUME_PRIVATE_FUTEX +# define __lll_private_flag(fl, private) \ + ((fl) | FUTEX_PRIVATE_FLAG) +# else +# define __lll_private_flag(fl, private) \ + ((fl) | THREAD_GETMEM (THREAD_SELF, header.private_futex)) +# endif +#else +# ifdef __ASSUME_PRIVATE_FUTEX +# define __lll_private_flag(fl, private) \ + (((fl) | FUTEX_PRIVATE_FLAG) ^ (private)) +# else +# define __lll_private_flag(fl, private) \ + (__builtin_constant_p (private) \ + ? ((private) == 0 \ + ? ((fl) | THREAD_GETMEM (THREAD_SELF, header.private_futex)) \ + : (fl)) \ + : ((fl) | (((private) ^ FUTEX_PRIVATE_FLAG) \ + & THREAD_GETMEM (THREAD_SELF, header.private_futex)))) +# endif +#endif + + +#define lll_futex_wait(futexp, val, private) \ + lll_futex_timed_wait(futexp, val, NULL, private) + +#define lll_futex_timed_wait(futexp, val, timespec, private) \ + ({ \ + INTERNAL_SYSCALL_DECL (__err); \ + long int __ret; \ + __ret = INTERNAL_SYSCALL (futex, __err, 4, (long) (futexp), \ + __lll_private_flag (FUTEX_WAIT, private), \ + (val), (timespec)); \ + INTERNAL_SYSCALL_ERROR_P (__ret, __err) ? -__ret : __ret; \ + }) + +#define lll_futex_wake(futexp, nr, private) \ + ({ \ + INTERNAL_SYSCALL_DECL (__err); \ + long int __ret; \ + __ret = INTERNAL_SYSCALL (futex, __err, 4, (long) (futexp), \ + __lll_private_flag (FUTEX_WAKE, private), \ + (nr), 0); \ + INTERNAL_SYSCALL_ERROR_P (__ret, __err) ? -__ret : __ret; \ + }) + +#define lll_robust_dead(futexv, private) \ + do \ + { \ + int *__futexp = &(futexv); \ + atomic_or (__futexp, FUTEX_OWNER_DIED); \ + lll_futex_wake (__futexp, 1, private); \ + } \ + while (0) + +/* Returns non-zero if error happened, zero if success. */ +#define lll_futex_requeue(futexp, nr_wake, nr_move, mutex, val, private) \ + ({ \ + INTERNAL_SYSCALL_DECL (__err); \ + long int __ret; \ + __ret = INTERNAL_SYSCALL (futex, __err, 6, (long) (futexp), \ + __lll_private_flag (FUTEX_CMP_REQUEUE, private),\ + (nr_wake), (nr_move), (mutex), (val)); \ + INTERNAL_SYSCALL_ERROR_P (__ret, __err); \ + }) + +/* Returns non-zero if error happened, zero if success. */ +#define lll_futex_wake_unlock(futexp, nr_wake, nr_wake2, futexp2, private) \ + ({ \ + INTERNAL_SYSCALL_DECL (__err); \ + long int __ret; \ + \ + __ret = INTERNAL_SYSCALL (futex, __err, 6, (futexp), \ + __lll_private_flag (FUTEX_WAKE_OP, private), \ + (nr_wake), (nr_wake2), (futexp2), \ + FUTEX_OP_CLEAR_WAKE_IF_GT_ONE); \ + INTERNAL_SYSCALL_ERROR_P (__ret, __err); \ + }) + +static inline int __attribute__((always_inline)) +__lll_trylock(int *futex) +{ + return atomic_compare_and_exchange_val_acq (futex, 1, 0) != 0; +} +#define lll_trylock(lock) __lll_trylock (&(lock)) + + +static inline int __attribute__((always_inline)) +__lll_cond_trylock(int *futex) +{ + return atomic_compare_and_exchange_val_acq (futex, 2, 0) != 0; +} +#define lll_cond_trylock(lock) __lll_cond_trylock (&(lock)) + + +static inline int __attribute__((always_inline)) +__lll_robust_trylock(int *futex, int id) +{ + return atomic_compare_and_exchange_val_acq (futex, id, 0) != 0; +} +#define lll_robust_trylock(lock, id) \ + __lll_robust_trylock (&(lock), id) + +extern void __lll_lock_wait_private (int *futex) attribute_hidden; +extern void __lll_lock_wait (int *futex, int private) attribute_hidden; +extern int __lll_robust_lock_wait (int *futex, int private) attribute_hidden; + +#define __lll_lock(futex, private) \ + ((void) ({ \ + int *__futex = (futex); \ + if (__builtin_expect (atomic_compare_and_exchange_bool_acq (__futex, \ + 1, 0), 0)) \ + { \ + if (__builtin_constant_p (private) && (private) == LLL_PRIVATE) \ + __lll_lock_wait_private (__futex); \ + else \ + __lll_lock_wait (__futex, private); \ + } \ + })) +#define lll_lock(futex, private) __lll_lock (&(futex), private) + + +#define __lll_robust_lock(futex, id, private) \ + ({ \ + int *__futex = (futex); \ + int __val = 0; \ + \ + if (__builtin_expect (atomic_compare_and_exchange_bool_acq (__futex, id, \ + 0), 0)) \ + __val = __lll_robust_lock_wait (__futex, private); \ + __val; \ + }) +#define lll_robust_lock(futex, id, private) \ + __lll_robust_lock (&(futex), id, private) + + +static inline void __attribute__ ((always_inline)) +__lll_cond_lock (int *futex, int private) +{ + if (atomic_compare_and_exchange_bool_acq (futex, 2, 0) != 0) + __lll_lock_wait (futex, private); +} +#define lll_cond_lock(futex, private) __lll_cond_lock (&(futex), private) + + +#define lll_robust_cond_lock(futex, id, private) \ + __lll_robust_lock (&(futex), (id) | FUTEX_WAITERS, private) + + +extern int __lll_timedlock_wait (int *futex, const struct timespec *, + int private) attribute_hidden; +extern int __lll_robust_timedlock_wait (int *futex, const struct timespec *, + int private) attribute_hidden; + +static inline int __attribute__ ((always_inline)) +__lll_timedlock (int *futex, const struct timespec *abstime, int private) +{ + int result = 0; + if (atomic_compare_and_exchange_bool_acq (futex, 1, 0) != 0) + result = __lll_timedlock_wait (futex, abstime, private); + return result; +} +#define lll_timedlock(futex, abstime, private) \ + __lll_timedlock (&(futex), abstime, private) + + +static inline int __attribute__ ((always_inline)) +__lll_robust_timedlock (int *futex, const struct timespec *abstime, + int id, int private) +{ + int result = 0; + if (atomic_compare_and_exchange_bool_acq (futex, id, 0) != 0) + result = __lll_robust_timedlock_wait (futex, abstime, private); + return result; +} +#define lll_robust_timedlock(futex, abstime, id, private) \ + __lll_robust_timedlock (&(futex), abstime, id, private) + + +#define __lll_unlock(futex, private) \ + ((void) ({ \ + int *__futex = (futex); \ + int __val = atomic_exchange_rel (__futex, 0); \ + \ + if (__builtin_expect (__val > 1, 0)) \ + lll_futex_wake (__futex, 1, private); \ + })) +#define lll_unlock(futex, private) __lll_unlock(&(futex), private) + + +#define __lll_robust_unlock(futex, private) \ + ((void) ({ \ + int *__futex = (futex); \ + int __val = atomic_exchange_rel (__futex, 0); \ + \ + if (__builtin_expect (__val & FUTEX_WAITERS, 0)) \ + lll_futex_wake (__futex, 1, private); \ + })) +#define lll_robust_unlock(futex, private) \ + __lll_robust_unlock(&(futex), private) + + +#define lll_islocked(futex) \ + (futex != 0) + + +/* Our internal lock implementation is identical to the binary-compatible + mutex implementation. */ + +/* Initializers for lock. */ +#define LLL_LOCK_INITIALIZER (0) +#define LLL_LOCK_INITIALIZER_LOCKED (1) + +/* The states of a lock are: + 0 - untaken + 1 - taken by one user + >1 - taken by more users */ + +/* The kernel notifies a process which uses CLONE_CLEARTID via futex + wakeup when the clone terminates. The memory location contains the + thread ID while the clone is running and is reset to zero + afterwards. */ +#define lll_wait_tid(tid) \ + do { \ + __typeof (tid) __tid; \ + while ((__tid = (tid)) != 0) \ + lll_futex_wait (&(tid), __tid, LLL_SHARED); \ + } while (0) + +extern int __lll_timedwait_tid (int *, const struct timespec *) + attribute_hidden; + +#define lll_timedwait_tid(tid, abstime) \ + ({ \ + int __res = 0; \ + if ((tid) != 0) \ + __res = __lll_timedwait_tid (&(tid), (abstime)); \ + __res; \ + }) + +#endif /* lowlevellock.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/mips/pt-__syscall_rt_sigaction.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/mips/pt-__syscall_rt_sigaction.c new file mode 100644 index 00000000..50137c84 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/mips/pt-__syscall_rt_sigaction.c @@ -0,0 +1 @@ +#include <../../../../../../../libc/sysdeps/linux/common/__syscall_rt_sigaction.c> diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/mips/pt-clone.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/mips/pt-clone.S new file mode 100644 index 00000000..add40552 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/mips/pt-clone.S @@ -0,0 +1,2 @@ +#define RESET_PID +#include <../../../../../../../libc/sysdeps/linux/mips/clone.S> diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/mips/pt-vfork.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/mips/pt-vfork.S new file mode 100644 index 00000000..c02ffca9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/mips/pt-vfork.S @@ -0,0 +1,38 @@ +/* Copyright (C) 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +/* Save the PID value. */ +#define SAVE_PID \ + READ_THREAD_POINTER(v1); /* Get the thread pointer. */ \ + lw a2, PID_OFFSET(v1); /* Load the saved PID. */ \ + subu a2, $0, a2; /* Negate it. */ \ + sw a2, PID_OFFSET(v1); /* Store the temporary PID. */ + +/* Restore the old PID value in the parent. */ +#define RESTORE_PID \ + beqz v0, 1f; /* If we are the parent... */ \ + READ_THREAD_POINTER(v1); /* Get the thread pointer. */ \ + lw a2, PID_OFFSET(v1); /* Load the saved PID. */ \ + subu a2, $0, a2; /* Re-negate it. */ \ + sw a2, PID_OFFSET(v1); /* Restore the PID. */ \ +1: + +#include <../../../../../../../libc/sysdeps/linux/mips/vfork.S> diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/mips/pthread_once.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/mips/pthread_once.c new file mode 100644 index 00000000..cc4658b3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/mips/pthread_once.c @@ -0,0 +1,95 @@ +/* Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "pthreadP.h" +#include + + +unsigned long int __fork_generation attribute_hidden; + + +static void +clear_once_control (void *arg) +{ + pthread_once_t *once_control = (pthread_once_t *) arg; + + *once_control = 0; + lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE); +} + + +int +attribute_protected +__pthread_once (once_control, init_routine) + pthread_once_t *once_control; + void (*init_routine) (void); +{ + while (1) + { + int oldval, val, newval; + + val = *once_control; + do + { + /* Check if the initialized has already been done. */ + if ((val & 2) != 0) + return 0; + + oldval = val; + newval = (oldval & 3) | __fork_generation | 1; + val = atomic_compare_and_exchange_val_acq (once_control, newval, + oldval); + } + while (__builtin_expect (val != oldval, 0)); + + /* Check if another thread already runs the initializer. */ + if ((oldval & 1) != 0) + { + /* Check whether the initializer execution was interrupted + by a fork. */ + if (((oldval ^ newval) & -4) == 0) + { + /* Same generation, some other thread was faster. Wait. */ + lll_futex_wait (once_control, newval, LLL_PRIVATE); + continue; + } + } + + /* This thread is the first here. Do the initialization. + Register a cleanup handler so that in case the thread gets + interrupted the initialization can be restarted. */ + pthread_cleanup_push (clear_once_control, once_control); + + init_routine (); + + pthread_cleanup_pop (0); + + + /* Add one to *once_control. */ + atomic_increment (once_control); + + /* Wake up all other threads. */ + lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE); + break; + } + + return 0; +} +weak_alias (__pthread_once, pthread_once) +strong_alias (__pthread_once, __pthread_once_internal) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/mips/sysdep-cancel.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/mips/sysdep-cancel.h new file mode 100644 index 00000000..c2cd14fe --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/mips/sysdep-cancel.h @@ -0,0 +1,188 @@ +/* Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#ifndef __ASSEMBLER__ +# include +#endif + +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + +# ifdef __PIC__ +# define PSEUDO_CPLOAD .cpload t9; +# define PSEUDO_ERRJMP move a0, v0; la t9, __syscall_error; jr t9; +# define PSEUDO_SAVEGP sw gp, 32(sp); cfi_rel_offset (gp, 32); +# define PSEUDO_LOADGP lw gp, 32(sp); +# else +# define PSEUDO_CPLOAD +# define PSEUDO_ERRJMP move a0, v0; j __syscall_error; +# define PSEUDO_SAVEGP +# define PSEUDO_LOADGP +# endif + +# undef PSEUDO +# define PSEUDO(name, syscall_name, args) \ + .align 2; \ + L(pseudo_start): \ + cfi_startproc; \ + 99: PSEUDO_ERRJMP \ + .type __##syscall_name##_nocancel, @function; \ + .globl __##syscall_name##_nocancel; \ + __##syscall_name##_nocancel: \ + .set noreorder; \ + PSEUDO_CPLOAD \ + li v0, SYS_ify(syscall_name); \ + syscall; \ + .set reorder; \ + bne a3, zero, 99b; \ + ret; \ + .size __##syscall_name##_nocancel,.-__##syscall_name##_nocancel; \ + ENTRY (name) \ + .set noreorder; \ + PSEUDO_CPLOAD \ + .set reorder; \ + SINGLE_THREAD_P(v1); \ + bne zero, v1, L(pseudo_cancel); \ + .set noreorder; \ + li v0, SYS_ify(syscall_name); \ + syscall; \ + .set reorder; \ + bne a3, zero, 99b; \ + ret; \ + L(pseudo_cancel): \ + SAVESTK_##args; \ + sw ra, 28(sp); \ + cfi_rel_offset (ra, 28); \ + PSEUDO_SAVEGP \ + PUSHARGS_##args; /* save syscall args */ \ + CENABLE; \ + PSEUDO_LOADGP \ + sw v0, 44(sp); /* save mask */ \ + POPARGS_##args; /* restore syscall args */ \ + .set noreorder; \ + li v0, SYS_ify (syscall_name); \ + syscall; \ + .set reorder; \ + sw v0, 36(sp); /* save syscall result */ \ + sw a3, 40(sp); /* save syscall error flag */ \ + lw a0, 44(sp); /* pass mask as arg1 */ \ + CDISABLE; \ + PSEUDO_LOADGP \ + lw v0, 36(sp); /* restore syscall result */ \ + lw a3, 40(sp); /* restore syscall error flag */ \ + lw ra, 28(sp); /* restore return address */ \ + .set noreorder; \ + bne a3, zero, 99b; \ + RESTORESTK; \ + L(pseudo_end): \ + .set reorder; + +# undef PSEUDO_END +# define PSEUDO_END(sym) cfi_endproc; .end sym; .size sym,.-sym + +# define PUSHARGS_0 /* nothing to do */ +# define PUSHARGS_1 PUSHARGS_0 sw a0, 0(sp); cfi_rel_offset (a0, 0); +# define PUSHARGS_2 PUSHARGS_1 sw a1, 4(sp); cfi_rel_offset (a1, 4); +# define PUSHARGS_3 PUSHARGS_2 sw a2, 8(sp); cfi_rel_offset (a2, 8); +# define PUSHARGS_4 PUSHARGS_3 sw a3, 12(sp); cfi_rel_offset (a3, 12); +# define PUSHARGS_5 PUSHARGS_4 /* handled by SAVESTK_## */ +# define PUSHARGS_6 PUSHARGS_5 +# define PUSHARGS_7 PUSHARGS_6 + +# define POPARGS_0 /* nothing to do */ +# define POPARGS_1 POPARGS_0 lw a0, 0(sp); +# define POPARGS_2 POPARGS_1 lw a1, 4(sp); +# define POPARGS_3 POPARGS_2 lw a2, 8(sp); +# define POPARGS_4 POPARGS_3 lw a3, 12(sp); +# define POPARGS_5 POPARGS_4 /* args already in new stackframe */ +# define POPARGS_6 POPARGS_5 +# define POPARGS_7 POPARGS_6 + + +# define STKSPACE 48 +# define SAVESTK_0 subu sp, STKSPACE; cfi_adjust_cfa_offset(STKSPACE) +# define SAVESTK_1 SAVESTK_0 +# define SAVESTK_2 SAVESTK_1 +# define SAVESTK_3 SAVESTK_2 +# define SAVESTK_4 SAVESTK_3 +# define SAVESTK_5 lw t0, 16(sp); \ + SAVESTK_0; \ + sw t0, 16(sp) + +# define SAVESTK_6 lw t0, 16(sp); \ + lw t1, 20(sp); \ + SAVESTK_0; \ + sw t0, 16(sp); \ + sw t1, 20(sp) + +# define SAVESTK_7 lw t0, 16(sp); \ + lw t1, 20(sp); \ + lw t2, 24(sp); \ + SAVESTK_0; \ + sw t0, 16(sp); \ + sw t1, 20(sp); \ + sw t2, 24(sp) + +# define RESTORESTK addu sp, STKSPACE; cfi_adjust_cfa_offset(-STKSPACE) + + +# ifdef __PIC__ +/* We use jalr rather than jal. This means that the assembler will not + automatically restore $gp (in case libc has multiple GOTs) so we must + do it manually - which we have to do anyway since we don't use .cprestore. + It also shuts up the assembler warning about not using .cprestore. */ +# define PSEUDO_JMP(sym) la t9, sym; jalr t9; +# else +# define PSEUDO_JMP(sym) jal sym; +# endif + +# ifdef IS_IN_libpthread +# define CENABLE PSEUDO_JMP (__pthread_enable_asynccancel) +# define CDISABLE PSEUDO_JMP (__pthread_disable_asynccancel) +# elif defined IS_IN_librt +# define CENABLE PSEUDO_JMP (__librt_enable_asynccancel) +# define CDISABLE PSEUDO_JMP (__librt_disable_asynccancel) +# else +# define CENABLE PSEUDO_JMP (__libc_enable_asynccancel) +# define CDISABLE PSEUDO_JMP (__libc_disable_asynccancel) +# endif + +# ifndef __ASSEMBLER__ +# define SINGLE_THREAD_P \ + __builtin_expect (THREAD_GETMEM (THREAD_SELF, \ + header.multiple_threads) \ + == 0, 1) +# else +# define SINGLE_THREAD_P(reg) \ + READ_THREAD_POINTER(reg); \ + lw reg, MULTIPLE_THREADS_OFFSET(reg) +#endif + +#elif !defined __ASSEMBLER__ + +# define SINGLE_THREAD_P 1 +# define NO_CANCELLATION 1 + +#endif + +#ifndef __ASSEMBLER__ +# define RTLD_SINGLE_THREAD_P \ + __builtin_expect (THREAD_GETMEM (THREAD_SELF, \ + header.multiple_threads) == 0, 1) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/mips/vfork.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/mips/vfork.S new file mode 100644 index 00000000..9d489e30 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/mips/vfork.S @@ -0,0 +1,43 @@ +/* Copyright (C) 2005, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +/* Save the PID value. */ +#define SAVE_PID \ + READ_THREAD_POINTER(v1); /* Get the thread pointer. */ \ + lw a2, PID_OFFSET(v1); /* Load the saved PID. */ \ + subu a2, $0, a2; /* Negate it. */ \ + bnez a2, 1f; /* If it was zero... */ \ + lui a2, 0x8000; /* use 0x80000000 instead. */ \ +1: sw a2, PID_OFFSET(v1); /* Store the temporary PID. */ + +/* Restore the old PID value in the parent. */ +#define RESTORE_PID \ + beqz v0, 1f; /* If we are the parent... */ \ + READ_THREAD_POINTER(v1); /* Get the thread pointer. */ \ + lw a2, PID_OFFSET(v1); /* Load the saved PID. */ \ + subu a2, $0, a2; /* Re-negate it. */ \ + lui a0, 0x8000; /* Load 0x80000000... */ \ + bne a2, a0, 2f; /* ... compare against it... */ \ + li a2, 0; /* ... use 0 instead. */ \ +2: sw a2, PID_OFFSET(v1); /* Restore the PID. */ \ +1: + +#include <../../../../../../../libc/sysdeps/linux/mips/vfork.S> diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/mq_notify.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/mq_notify.c new file mode 100644 index 00000000..188040ee --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/mq_notify.c @@ -0,0 +1,286 @@ +/* Copyright (C) 2004, 2005, 2008 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contribute by Ulrich Drepper , 2004. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#ifdef __NR_mq_notify + +/* Defined in the kernel headers: */ +#define NOTIFY_COOKIE_LEN 32 /* Length of the cookie used. */ +#define NOTIFY_WOKENUP 1 /* Code for notifcation. */ +#define NOTIFY_REMOVED 2 /* Code for closed message queue + of de-notifcation. */ + + +/* Data structure for the queued notification requests. */ +union notify_data +{ + struct + { + void (*fct) (union sigval); /* The function to run. */ + union sigval param; /* The parameter to pass. */ + pthread_attr_t *attr; /* Attributes to create the thread with. */ + /* NB: on 64-bit machines the struct as a size of 24 bytes. Which means + byte 31 can still be used for returning the status. */ + }; + char raw[NOTIFY_COOKIE_LEN]; +}; + + +/* Keep track of the initialization. */ +static pthread_once_t once = PTHREAD_ONCE_INIT; + + +/* The netlink socket. */ +static int netlink_socket = -1; + + +/* Barrier used to make sure data passed to the new thread is not + resused by the parent. */ +static pthread_barrier_t notify_barrier; + + +/* Modify the signal mask. We move this into a separate function so + that the stack space needed for sigset_t is not deducted from what + the thread can use. */ +static int +__attribute__ ((noinline)) +change_sigmask (int how, sigset_t *oss) +{ + sigset_t ss; + sigfillset (&ss); + return pthread_sigmask (how, &ss, oss); +} + + +/* The function used for the notification. */ +static void * +notification_function (void *arg) +{ + /* Copy the function and parameter so that the parent thread can go + on with its life. */ + volatile union notify_data *data = (volatile union notify_data *) arg; + void (*fct) (union sigval) = data->fct; + union sigval param = data->param; + + /* Let the parent go. */ + (void) pthread_barrier_wait (¬ify_barrier); + + /* Make the thread detached. */ + (void) pthread_detach (pthread_self ()); + + /* The parent thread has all signals blocked. This is probably a + bit surprising for this thread. So we unblock all of them. */ + (void) change_sigmask (SIG_UNBLOCK, NULL); + + /* Now run the user code. */ + fct (param); + + /* And we are done. */ + return NULL; +} + + +/* Helper thread. */ +static void * +helper_thread (void *arg) +{ + while (1) + { + union notify_data data; + + ssize_t n = recv (netlink_socket, &data, sizeof (data), + MSG_NOSIGNAL | MSG_WAITALL); + if (n < NOTIFY_COOKIE_LEN) + continue; + + if (data.raw[NOTIFY_COOKIE_LEN - 1] == NOTIFY_WOKENUP) + { + /* Just create the thread as instructed. There is no way to + report a problem with creating a thread. */ + pthread_t th; + if (__builtin_expect (pthread_create (&th, data.attr, + notification_function, &data) + == 0, 0)) + /* Since we passed a pointer to DATA to the new thread we have + to wait until it is done with it. */ + (void) pthread_barrier_wait (¬ify_barrier); + } + else if (data.raw[NOTIFY_COOKIE_LEN - 1] == NOTIFY_REMOVED) + /* The only state we keep is the copy of the thread attributes. */ + free (data.attr); + } + return NULL; +} + + +static void +reset_once (void) +{ + once = PTHREAD_ONCE_INIT; +} + + +static void +init_mq_netlink (void) +{ + /* This code might be called a second time after fork(). The file + descriptor is inherited from the parent. */ + if (netlink_socket == -1) + { + /* Just a normal netlink socket, not bound. */ + netlink_socket = socket (AF_NETLINK, SOCK_RAW, 0); + /* No need to do more if we have no socket. */ + if (netlink_socket == -1) + return; + + /* Make sure the descriptor is closed on exec. */ + if (fcntl (netlink_socket, F_SETFD, FD_CLOEXEC) != 0) + goto errout; + } + + int err = 1; + + /* Initialize the barrier. */ + if (__builtin_expect (pthread_barrier_init (¬ify_barrier, NULL, 2) == 0, + 0)) + { + /* Create the helper thread. */ + pthread_attr_t attr; + (void) pthread_attr_init (&attr); + (void) pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED); + /* We do not need much stack space, the bare minimum will be enough. */ + (void) pthread_attr_setstacksize (&attr, PTHREAD_STACK_MIN); + + /* Temporarily block all signals so that the newly created + thread inherits the mask. */ + sigset_t oss; + int have_no_oss = change_sigmask (SIG_BLOCK, &oss); + + pthread_t th; + err = pthread_create (&th, &attr, helper_thread, NULL); + + /* Reset the signal mask. */ + if (!have_no_oss) + pthread_sigmask (SIG_SETMASK, &oss, NULL); + + (void) pthread_attr_destroy (&attr); + + if (err == 0) + { + static int added_atfork; + + if (added_atfork == 0 + && pthread_atfork (NULL, NULL, reset_once) != 0) + { + /* The child thread will call recv() which is a + cancellation point. */ + (void) pthread_cancel (th); + err = 1; + } + else + added_atfork = 1; + } + } + + if (err != 0) + { + errout: + close_not_cancel_no_status (netlink_socket); + netlink_socket = -1; + } +} + + +/* Register notification upon message arrival to an empty message queue + MQDES. */ +int +mq_notify (mqd_t mqdes, const struct sigevent *notification) +{ + /* Make sure the type is correctly defined. */ + assert (sizeof (union notify_data) == NOTIFY_COOKIE_LEN); + + /* Special treatment needed for SIGEV_THREAD. */ + if (notification == NULL || notification->sigev_notify != SIGEV_THREAD) + return INLINE_SYSCALL (mq_notify, 2, mqdes, notification); + + /* The kernel cannot directly start threads. This will have to be + done at userlevel. Since we cannot start threads from signal + handlers we have to create a dedicated thread which waits for + notifications for arriving messages and creates threads in + response. */ + + /* Initialize only once. */ + pthread_once (&once, init_mq_netlink); + + /* If we cannot create the netlink socket we cannot provide + SIGEV_THREAD support. */ + if (__builtin_expect (netlink_socket == -1, 0)) + { + __set_errno (ENOSYS); + return -1; + } + + /* Create the cookie. It will hold almost all the state. */ + union notify_data data; + memset (&data, '\0', sizeof (data)); + data.fct = notification->sigev_notify_function; + data.param = notification->sigev_value; + + if (notification->sigev_notify_attributes != NULL) + { + /* The thread attribute has to be allocated separately. */ + data.attr = (pthread_attr_t *) malloc (sizeof (pthread_attr_t)); + if (data.attr == NULL) + return -1; + + memcpy (data.attr, notification->sigev_notify_attributes, + sizeof (pthread_attr_t)); + } + + /* Construct the new request. */ + struct sigevent se; + se.sigev_notify = SIGEV_THREAD; + se.sigev_signo = netlink_socket; + se.sigev_value.sival_ptr = &data; + + /* Tell the kernel. */ + int retval = INLINE_SYSCALL (mq_notify, 2, mqdes, &se); + + /* If it failed, free the allocated memory. */ + if (__builtin_expect (retval != 0, 0)) + free (data.attr); + + return retval; +} + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/msync.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/msync.S new file mode 100644 index 00000000..074a0d71 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/msync.S @@ -0,0 +1,7 @@ +#include +PSEUDO (__libc_msync, msync, 3) +ret +PSEUDO_END(__libc_msync) +libc_hidden_def (__libc_msync) +weak_alias (__libc_msync, msync) +libc_hidden_weak (msync) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/nanosleep.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/nanosleep.S new file mode 100644 index 00000000..71efe32f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/nanosleep.S @@ -0,0 +1,9 @@ +#include +PSEUDO (__libc_nanosleep, nanosleep, 3) +ret +PSEUDO_END (__libc_nanosleep) +libc_hidden_def (__libc_nanosleep) +weak_alias (__libc_nanosleep, __nanosleep) +libc_hidden_weak (__nanosleep) +weak_alias (__libc_nanosleep, nanosleep) +libc_hidden_weak (nanosleep) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/not-cancel.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/not-cancel.h new file mode 100644 index 00000000..80d33be2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/not-cancel.h @@ -0,0 +1,105 @@ +/* Uncancelable versions of cancelable interfaces. Linux version. + Copyright (C) 2003, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +/* Uncancelable open. */ +#define open_not_cancel(name, flags, mode) \ + INLINE_SYSCALL (open, 3, (const char *) (name), (flags), (mode)) +#define open_not_cancel_2(name, flags) \ + INLINE_SYSCALL (open, 2, (const char *) (name), (flags)) + +/* Uncancelable openat. */ +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt +extern int __openat_nocancel (int fd, const char *fname, int oflag, + mode_t mode) attribute_hidden; +extern int __openat64_nocancel (int fd, const char *fname, int oflag, + mode_t mode) attribute_hidden; +#else +# define __openat_nocancel(fd, fname, oflag, mode) \ + openat (fd, fname, oflag, mode) +# define __openat64_nocancel(fd, fname, oflag, mode) \ + openat64 (fd, fname, oflag, mode) +#endif + +#define openat_not_cancel(fd, fname, oflag, mode) \ + __openat_nocancel (fd, fname, oflag, mode) +#define openat_not_cancel_3(fd, fname, oflag) \ + __openat_nocancel (fd, fname, oflag, 0) +#define openat64_not_cancel(fd, fname, oflag, mode) \ + __openat64_nocancel (fd, fname, oflag, mode) +#define openat64_not_cancel_3(fd, fname, oflag) \ + __openat64_nocancel (fd, fname, oflag, 0) + +/* Uncancelable close. */ +#define close_not_cancel(fd) \ + INLINE_SYSCALL (close, 1, fd) +#define close_not_cancel_no_status(fd) \ + (void) ({ INTERNAL_SYSCALL_DECL (err); \ + INTERNAL_SYSCALL (close, err, 1, (fd)); }) + +/* Uncancelable read. */ +#define read_not_cancel(fd, buf, n) \ + INLINE_SYSCALL (read, 3, (fd), (buf), (n)) + +/* Uncancelable write. */ +#define write_not_cancel(fd, buf, n) \ + INLINE_SYSCALL (write, 3, (fd), (buf), (n)) + +/* Uncancelable writev. */ +#define writev_not_cancel_no_status(fd, iov, n) \ + (void) ({ INTERNAL_SYSCALL_DECL (err); \ + INTERNAL_SYSCALL (writev, err, 3, (fd), (iov), (n)); }) + +/* Uncancelable fcntl. */ +#define fcntl_not_cancel(fd, cmd, val) \ + __fcntl_nocancel (fd, cmd, val) + +/* Uncancelable waitpid. */ +#ifdef __NR_waitpid +# define waitpid_not_cancel(pid, stat_loc, options) \ + INLINE_SYSCALL (waitpid, 3, pid, stat_loc, options) +#else +# define waitpid_not_cancel(pid, stat_loc, options) \ + INLINE_SYSCALL (wait4, 4, pid, stat_loc, options, NULL) +#endif + +/* Uncancelable pause. */ +#ifdef __NR_pause +# define pause_not_cancel() \ + INLINE_SYSCALL (pause, 0) +#else +# define pause_not_cancel() \ + __pause_nocancel () +#endif + +/* Uncancelable nanosleep. */ +#ifdef __NR_nanosleep +# define nanosleep_not_cancel(requested_time, remaining) \ + INLINE_SYSCALL (nanosleep, 2, requested_time, remaining) +#else +# define nanosleep_not_cancel(requested_time, remaining) \ + __nanosleep_nocancel (requested_time, remaining) +#endif + +/* Uncancelable sigsuspend. */ +#define sigsuspend_not_cancel(set) \ + __sigsuspend_nocancel (set) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/open.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/open.S new file mode 100644 index 00000000..486686a2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/open.S @@ -0,0 +1,21 @@ +#include + +/* +extern int __open_nocancel (const char *, int, ...) attribute_hidden; +*/ +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + +PSEUDO (__libc_open, open, 3) +ret +PSEUDO_END(__libc_open) + +libc_hidden_def (__open_nocancel) +libc_hidden_def (__libc_open) +weak_alias (__libc_open, __open) +libc_hidden_weak (__open) +weak_alias (__libc_open, open) +libc_hidden_weak (open) + + + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pause.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pause.S new file mode 100644 index 00000000..3841018a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pause.S @@ -0,0 +1,7 @@ +#include +PSEUDO (__libc_pause, pause, 0) +ret +PSEUDO_END (__libc_pause) +libc_hidden_def (__libc_pause) +weak_alias (__libc_pause, pause) +libc_hidden_weak (pause) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/Makefile new file mode 100644 index 00000000..421a62b3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc NPTL +# +# Copyright (C) 2009 Bernhard Reutner-Fischer +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../../../../../ +top_builddir=../../../../../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.arch +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/Makefile.arch b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/Makefile.arch new file mode 100644 index 00000000..8581aea6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/Makefile.arch @@ -0,0 +1,30 @@ +# Makefile for uClibc NPTL +# +# Copyright (C) 2009 Bernhard Reutner-Fischer +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +libpthread_linux_arch_SSRC = pt-vfork.S +libpthread_linux_arch_CSRC = pthread_once.c pt-__syscall_error.c + +libc_linux_arch_CSRC = fork.c +libc_linux_arch_SSRC = clone.S vfork.S + +# powerpc32's PSEUDO_RET needs __syscall_error@local +librt_linux_arch_CSRC = pt-__syscall_error.c + +ASFLAGS += -DUSE___THREAD + +CFLAGS-pthread_once.c = -DNOT_IN_libc -DIS_IN_libpthread +CFLAGS-lowlevellock.c = -DNOT_IN_libc -DIS_IN_libpthread +CFLAGS-pt-__syscall_error.c = -DNOT_IN_libc -DIS_IN_libpthread +ASFLAGS-pt-vfork.S = -DNOT_IN_libc -DIS_IN_libpthread -D_LIBC_REENTRANT +#ASFLAGS-lowlevellock.S = -DNOT_IN_libc -DIS_IN_libpthread -D_LIBC_REENTRANT + +#ASFLAGS-libc-lowlevellock.S = -D_LIBC_REENTRANT +ASFLAGS-clone.S = -D_LIBC_REENTRANT +ASFLAGS-vfork.S = -D_LIBC_REENTRANT +ifeq ($(UCLIBC_HAS_STDIO_FUTEXES),y) +CFLAGS-fork.c = -D__USE_STDIO_FUTEXES__ +endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h new file mode 100644 index 00000000..c0b59c33 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/bits/pthreadtypes.h @@ -0,0 +1,221 @@ +/* Machine-specific pthread type layouts. PowerPC version. + Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Paul Mackerras , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _BITS_PTHREADTYPES_H +#define _BITS_PTHREADTYPES_H 1 + +#include + +#if __WORDSIZE == 64 +# define __SIZEOF_PTHREAD_ATTR_T 56 +# define __SIZEOF_PTHREAD_MUTEX_T 40 +# define __SIZEOF_PTHREAD_MUTEXATTR_T 4 +# define __SIZEOF_PTHREAD_COND_T 48 +# define __SIZEOF_PTHREAD_CONDATTR_T 4 +# define __SIZEOF_PTHREAD_RWLOCK_T 56 +# define __SIZEOF_PTHREAD_RWLOCKATTR_T 8 +# define __SIZEOF_PTHREAD_BARRIER_T 32 +# define __SIZEOF_PTHREAD_BARRIERATTR_T 4 +#else +# define __SIZEOF_PTHREAD_ATTR_T 36 +# define __SIZEOF_PTHREAD_MUTEX_T 24 +# define __SIZEOF_PTHREAD_MUTEXATTR_T 4 +# define __SIZEOF_PTHREAD_COND_T 48 +# define __SIZEOF_PTHREAD_CONDATTR_T 4 +# define __SIZEOF_PTHREAD_RWLOCK_T 32 +# define __SIZEOF_PTHREAD_RWLOCKATTR_T 8 +# define __SIZEOF_PTHREAD_BARRIER_T 20 +# define __SIZEOF_PTHREAD_BARRIERATTR_T 4 +#endif + + +/* Thread identifiers. The structure of the attribute type is + deliberately not exposed. */ +typedef unsigned long int pthread_t; + + +typedef union +{ + char __size[__SIZEOF_PTHREAD_ATTR_T]; + long int __align; +} pthread_attr_t; + + +#if __WORDSIZE == 64 +typedef struct __pthread_internal_list +{ + struct __pthread_internal_list *__prev; + struct __pthread_internal_list *__next; +} __pthread_list_t; +#else +typedef struct __pthread_internal_slist +{ + struct __pthread_internal_slist *__next; +} __pthread_slist_t; +#endif + + +/* Data structures for mutex handling. The structure of the attribute + type is deliberately not exposed. */ +typedef union +{ + struct __pthread_mutex_s + { + int __lock; + unsigned int __count; + int __owner; +#if __WORDSIZE == 64 + unsigned int __nusers; +#endif + /* KIND must stay at this position in the structure to maintain + binary compatibility. */ + int __kind; +#if __WORDSIZE == 64 + int __spins; + __pthread_list_t __list; +# define __PTHREAD_MUTEX_HAVE_PREV 1 +#else + unsigned int __nusers; + __extension__ union + { + int __spins; + __pthread_slist_t __list; + }; +#endif + } __data; + char __size[__SIZEOF_PTHREAD_MUTEX_T]; + long int __align; +} pthread_mutex_t; + +typedef union +{ + char __size[__SIZEOF_PTHREAD_MUTEXATTR_T]; + int __align; +} pthread_mutexattr_t; + + +/* Data structure for conditional variable handling. The structure of + the attribute type is deliberately not exposed. */ +typedef union +{ + struct + { + int __lock; + unsigned int __futex; + __extension__ unsigned long long int __total_seq; + __extension__ unsigned long long int __wakeup_seq; + __extension__ unsigned long long int __woken_seq; + void *__mutex; + unsigned int __nwaiters; + unsigned int __broadcast_seq; + } __data; + char __size[__SIZEOF_PTHREAD_COND_T]; + __extension__ long long int __align; +} pthread_cond_t; + +typedef union +{ + char __size[__SIZEOF_PTHREAD_CONDATTR_T]; + int __align; +} pthread_condattr_t; + + +/* Keys for thread-specific data */ +typedef unsigned int pthread_key_t; + + +/* Once-only execution */ +typedef int pthread_once_t; + + +#if defined __USE_UNIX98 || defined __USE_XOPEN2K +/* Data structure for read-write lock variable handling. The + structure of the attribute type is deliberately not exposed. */ +typedef union +{ +# if __WORDSIZE == 64 + struct + { + int __lock; + unsigned int __nr_readers; + unsigned int __readers_wakeup; + unsigned int __writer_wakeup; + unsigned int __nr_readers_queued; + unsigned int __nr_writers_queued; + int __writer; + int __shared; + unsigned long int __pad1; + unsigned long int __pad2; + /* FLAGS must stay at this position in the structure to maintain + binary compatibility. */ + unsigned int __flags; + } __data; +# else + struct + { + int __lock; + unsigned int __nr_readers; + unsigned int __readers_wakeup; + unsigned int __writer_wakeup; + unsigned int __nr_readers_queued; + unsigned int __nr_writers_queued; + unsigned char __pad1; + unsigned char __pad2; + unsigned char __shared; + /* FLAGS must stay at this position in the structure to maintain + binary compatibility. */ + unsigned char __flags; + int __writer; + } __data; +# endif + char __size[__SIZEOF_PTHREAD_RWLOCK_T]; + long int __align; +} pthread_rwlock_t; + +typedef union +{ + char __size[__SIZEOF_PTHREAD_RWLOCKATTR_T]; + long int __align; +} pthread_rwlockattr_t; +#endif + + +#ifdef __USE_XOPEN2K +/* POSIX spinlock data type. */ +typedef volatile int pthread_spinlock_t; + + +/* POSIX barriers data type. The structure of the type is + deliberately not exposed. */ +typedef union +{ + char __size[__SIZEOF_PTHREAD_BARRIER_T]; + long int __align; +} pthread_barrier_t; + +typedef union +{ + char __size[__SIZEOF_PTHREAD_BARRIERATTR_T]; + int __align; +} pthread_barrierattr_t; +#endif + + +#endif /* bits/pthreadtypes.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/bits/semaphore.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/bits/semaphore.h new file mode 100644 index 00000000..c7f121ba --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/bits/semaphore.h @@ -0,0 +1,41 @@ +/* Machine-specific POSIX semaphore type layouts. PowerPC version. + Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Paul Mackerras , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SEMAPHORE_H +# error "Never use directly; include instead." +#endif + +#include + +#if __WORDSIZE == 64 +# define __SIZEOF_SEM_T 32 +#else +# define __SIZEOF_SEM_T 16 +#endif + +/* Value returned if `sem_open' failed. */ +#define SEM_FAILED ((sem_t *) 0) + + +typedef union +{ + char __size[__SIZEOF_SEM_T]; + long int __align; +} sem_t; diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/clone.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/clone.S new file mode 100644 index 00000000..91c939e5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/clone.S @@ -0,0 +1,5 @@ +#if defined __powerpc64__ +# include "powerpc64/clone.S" +#else +# include "powerpc32/clone.S" +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/createthread.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/createthread.c new file mode 100644 index 00000000..26efabd0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/createthread.c @@ -0,0 +1,25 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Paul Mackerras . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Value passed to 'clone' for initialization of the thread register. */ +#define TLS_VALUE ((void *) (pd) \ + + TLS_TCB_OFFSET + TLS_PRE_TCB_SIZE) + +/* Get the real implementation. */ +#include diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/fork.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/fork.c new file mode 100644 index 00000000..06b7e1c6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/fork.c @@ -0,0 +1 @@ +#include "../i386/fork.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/lowlevellock.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/lowlevellock.h new file mode 100644 index 00000000..2c2557d5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/lowlevellock.h @@ -0,0 +1,315 @@ +/* Copyright (C) 2003, 2004, 2006-2008, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Paul Mackerras , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _LOWLEVELLOCK_H +#define _LOWLEVELLOCK_H 1 + +#include +#include +#include +#include +#include +#include + +#ifndef __NR_futex +# define __NR_futex 221 +#endif +#define FUTEX_WAIT 0 +#define FUTEX_WAKE 1 +#define FUTEX_REQUEUE 3 +#define FUTEX_CMP_REQUEUE 4 +#define FUTEX_WAKE_OP 5 +#define FUTEX_OP_CLEAR_WAKE_IF_GT_ONE ((4 << 24) | 1) +#define FUTEX_LOCK_PI 6 +#define FUTEX_UNLOCK_PI 7 +#define FUTEX_TRYLOCK_PI 8 +#define FUTEX_WAIT_BITSET 9 +#define FUTEX_WAKE_BITSET 10 +#define FUTEX_PRIVATE_FLAG 128 +#define FUTEX_CLOCK_REALTIME 256 + +#define FUTEX_BITSET_MATCH_ANY 0xffffffff + +/* Values for 'private' parameter of locking macros. Yes, the + definition seems to be backwards. But it is not. The bit will be + reversed before passing to the system call. */ +#define LLL_PRIVATE 0 +#define LLL_SHARED FUTEX_PRIVATE_FLAG + +#if !defined NOT_IN_libc || defined IS_IN_rtld +/* In libc.so or ld.so all futexes are private. */ +# ifdef __ASSUME_PRIVATE_FUTEX +# define __lll_private_flag(fl, private) \ + ((fl) | FUTEX_PRIVATE_FLAG) +# else +# define __lll_private_flag(fl, private) \ + ((fl) | THREAD_GETMEM (THREAD_SELF, header.private_futex)) +# endif +#else +# ifdef __ASSUME_PRIVATE_FUTEX +# define __lll_private_flag(fl, private) \ + (((fl) | FUTEX_PRIVATE_FLAG) ^ (private)) +# else +# define __lll_private_flag(fl, private) \ + (__builtin_constant_p (private) \ + ? ((private) == 0 \ + ? ((fl) | THREAD_GETMEM (THREAD_SELF, header.private_futex)) \ + : (fl)) \ + : ((fl) | (((private) ^ FUTEX_PRIVATE_FLAG) \ + & THREAD_GETMEM (THREAD_SELF, header.private_futex)))) +# endif +#endif + +#define lll_futex_wait(futexp, val, private) \ + lll_futex_timed_wait (futexp, val, NULL, private) + +#define lll_futex_timed_wait(futexp, val, timespec, private) \ + ({ \ + INTERNAL_SYSCALL_DECL (__err); \ + long int __ret; \ + \ + __ret = INTERNAL_SYSCALL (futex, __err, 4, (futexp), \ + __lll_private_flag (FUTEX_WAIT, private), \ + (val), (timespec)); \ + INTERNAL_SYSCALL_ERROR_P (__ret, __err) ? -__ret : __ret; \ + }) + +#define lll_futex_wake(futexp, nr, private) \ + ({ \ + INTERNAL_SYSCALL_DECL (__err); \ + long int __ret; \ + \ + __ret = INTERNAL_SYSCALL (futex, __err, 4, (futexp), \ + __lll_private_flag (FUTEX_WAKE, private), \ + (nr), 0); \ + INTERNAL_SYSCALL_ERROR_P (__ret, __err) ? -__ret : __ret; \ + }) + +#define lll_robust_dead(futexv, private) \ + do \ + { \ + INTERNAL_SYSCALL_DECL (__err); \ + int *__futexp = &(futexv); \ + \ + atomic_or (__futexp, FUTEX_OWNER_DIED); \ + INTERNAL_SYSCALL (futex, __err, 4, __futexp, \ + __lll_private_flag (FUTEX_WAKE, private), 1, 0); \ + } \ + while (0) + +/* Returns non-zero if error happened, zero if success. */ +#define lll_futex_requeue(futexp, nr_wake, nr_move, mutex, val, private) \ + ({ \ + INTERNAL_SYSCALL_DECL (__err); \ + long int __ret; \ + \ + __ret = INTERNAL_SYSCALL (futex, __err, 6, (futexp), \ + __lll_private_flag (FUTEX_CMP_REQUEUE, private),\ + (nr_wake), (nr_move), (mutex), (val)); \ + INTERNAL_SYSCALL_ERROR_P (__ret, __err); \ + }) + +/* Returns non-zero if error happened, zero if success. */ +#define lll_futex_wake_unlock(futexp, nr_wake, nr_wake2, futexp2, private) \ + ({ \ + INTERNAL_SYSCALL_DECL (__err); \ + long int __ret; \ + \ + __ret = INTERNAL_SYSCALL (futex, __err, 6, (futexp), \ + __lll_private_flag (FUTEX_WAKE_OP, private), \ + (nr_wake), (nr_wake2), (futexp2), \ + FUTEX_OP_CLEAR_WAKE_IF_GT_ONE); \ + INTERNAL_SYSCALL_ERROR_P (__ret, __err); \ + }) + + +#ifdef UP +# define __lll_acq_instr "" +# define __lll_rel_instr "" +#else +# define __lll_acq_instr "isync" +# ifdef _ARCH_PWR4 +/* + * Newer powerpc64 processors support the new "light weight" sync (lwsync) + * So if the build is using -mcpu=[power4,power5,power5+,970] we can + * safely use lwsync. + */ +# define __lll_rel_instr "lwsync" +# else +/* + * Older powerpc32 processors don't support the new "light weight" + * sync (lwsync). So the only safe option is to use normal sync + * for all powerpc32 applications. + */ +# define __lll_rel_instr "sync" +# endif +#endif + +/* Set *futex to ID if it is 0, atomically. Returns the old value */ +#define __lll_robust_trylock(futex, id) \ + ({ int __val; \ + __asm__ __volatile__ ("1: lwarx %0,0,%2" MUTEX_HINT_ACQ "\n" \ + " cmpwi 0,%0,0\n" \ + " bne 2f\n" \ + " stwcx. %3,0,%2\n" \ + " bne- 1b\n" \ + "2: " __lll_acq_instr \ + : "=&r" (__val), "=m" (*futex) \ + : "r" (futex), "r" (id), "m" (*futex) \ + : "cr0", "memory"); \ + __val; \ + }) + +#define lll_robust_trylock(lock, id) __lll_robust_trylock (&(lock), id) + +/* Set *futex to 1 if it is 0, atomically. Returns the old value */ +#define __lll_trylock(futex) __lll_robust_trylock (futex, 1) + +#define lll_trylock(lock) __lll_trylock (&(lock)) + +/* Set *futex to 2 if it is 0, atomically. Returns the old value */ +#define __lll_cond_trylock(futex) __lll_robust_trylock (futex, 2) + +#define lll_cond_trylock(lock) __lll_cond_trylock (&(lock)) + + +extern void __lll_lock_wait_private (int *futex) attribute_hidden; +extern void __lll_lock_wait (int *futex, int private) attribute_hidden; +extern int __lll_robust_lock_wait (int *futex, int private) attribute_hidden; + +#define lll_lock(lock, private) \ + (void) ({ \ + int *__futex = &(lock); \ + if (__builtin_expect (atomic_compare_and_exchange_val_acq (__futex, 1, 0),\ + 0) != 0) \ + { \ + if (__builtin_constant_p (private) && (private) == LLL_PRIVATE) \ + __lll_lock_wait_private (__futex); \ + else \ + __lll_lock_wait (__futex, private); \ + } \ + }) + +#define lll_robust_lock(lock, id, private) \ + ({ \ + int *__futex = &(lock); \ + int __val = 0; \ + if (__builtin_expect (atomic_compare_and_exchange_bool_acq (__futex, id, \ + 0), 0)) \ + __val = __lll_robust_lock_wait (__futex, private); \ + __val; \ + }) + +#define lll_cond_lock(lock, private) \ + (void) ({ \ + int *__futex = &(lock); \ + if (__builtin_expect (atomic_compare_and_exchange_val_acq (__futex, 2, 0),\ + 0) != 0) \ + __lll_lock_wait (__futex, private); \ + }) + +#define lll_robust_cond_lock(lock, id, private) \ + ({ \ + int *__futex = &(lock); \ + int __val = 0; \ + int __id = id | FUTEX_WAITERS; \ + if (__builtin_expect (atomic_compare_and_exchange_bool_acq (__futex, __id,\ + 0), 0)) \ + __val = __lll_robust_lock_wait (__futex, private); \ + __val; \ + }) + + +extern int __lll_timedlock_wait + (int *futex, const struct timespec *, int private) attribute_hidden; +extern int __lll_robust_timedlock_wait + (int *futex, const struct timespec *, int private) attribute_hidden; + +#define lll_timedlock(lock, abstime, private) \ + ({ \ + int *__futex = &(lock); \ + int __val = 0; \ + if (__builtin_expect (atomic_compare_and_exchange_val_acq (__futex, 1, 0),\ + 0) != 0) \ + __val = __lll_timedlock_wait (__futex, abstime, private); \ + __val; \ + }) + +#define lll_robust_timedlock(lock, abstime, id, private) \ + ({ \ + int *__futex = &(lock); \ + int __val = 0; \ + if (__builtin_expect (atomic_compare_and_exchange_bool_acq (__futex, id, \ + 0), 0)) \ + __val = __lll_robust_timedlock_wait (__futex, abstime, private); \ + __val; \ + }) + +#define lll_unlock(lock, private) \ + ((void) ({ \ + int *__futex = &(lock); \ + int __val = atomic_exchange_rel (__futex, 0); \ + if (__builtin_expect (__val > 1, 0)) \ + lll_futex_wake (__futex, 1, private); \ + })) + +#define lll_robust_unlock(lock, private) \ + ((void) ({ \ + int *__futex = &(lock); \ + int __val = atomic_exchange_rel (__futex, 0); \ + if (__builtin_expect (__val & FUTEX_WAITERS, 0)) \ + lll_futex_wake (__futex, 1, private); \ + })) + +#define lll_islocked(futex) \ + (futex != 0) + + +/* Initializers for lock. */ +#define LLL_LOCK_INITIALIZER (0) +#define LLL_LOCK_INITIALIZER_LOCKED (1) + +/* The states of a lock are: + 0 - untaken + 1 - taken by one user + >1 - taken by more users */ + +/* The kernel notifies a process which uses CLONE_CLEARTID via futex + wakeup when the clone terminates. The memory location contains the + thread ID while the clone is running and is reset to zero + afterwards. */ +#define lll_wait_tid(tid) \ + do { \ + __typeof (tid) __tid; \ + while ((__tid = (tid)) != 0) \ + lll_futex_wait (&(tid), __tid, LLL_SHARED); \ + } while (0) + +extern int __lll_timedwait_tid (int *, const struct timespec *) + attribute_hidden; + +#define lll_timedwait_tid(tid, abstime) \ + ({ \ + int __res = 0; \ + if ((tid) != 0) \ + __res = __lll_timedwait_tid (&(tid), (abstime)); \ + __res; \ + }) + +#endif /* lowlevellock.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc32/clone.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc32/clone.S new file mode 100644 index 00000000..675a997e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc32/clone.S @@ -0,0 +1,9 @@ +/* We want an #include_next, but we are the main source file. + So, #include ourselves and in that incarnation we can use #include_next. */ +#ifndef INCLUDED_SELF +# define INCLUDED_SELF +# include +#else +# define RESET_PID +# include_next +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc32/pt-vfork.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc32/pt-vfork.S new file mode 100644 index 00000000..61651fd9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc32/pt-vfork.S @@ -0,0 +1,49 @@ +/* Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2004. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#define _ERRNO_H 1 +#include +#include +#include + +/* Clone the calling process, but without copying the whole address space. + The calling process is suspended until the new process exits or is + replaced by a call to `execve'. Return -1 for errors, 0 to the new process, + and the process ID of the new process to the old process. */ + +ENTRY (__vfork) + lwz 0,PID(2) + neg 0,0 + stw 0,PID(2) + + DO_CALL (SYS_ify (vfork)) + + cmpwi 1,3,0 + beqlr- 1 + + lwz 0,PID(2) + neg 0,0 + stw 0,PID(2) + + PSEUDO_RET + +PSEUDO_END (__vfork) + +weak_alias (__vfork, vfork) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h new file mode 100644 index 00000000..4daa115e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep-cancel.h @@ -0,0 +1,119 @@ +/* Cancellable system call stubs. Linux/PowerPC version. + Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Franz Sirl , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA + 02110-1301 USA. */ + +#include +#include +#ifndef __ASSEMBLER__ +# include +#endif + +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + +# undef PSEUDO +# define PSEUDO(name, syscall_name, args) \ + .section ".text"; \ + ENTRY (name) \ + SINGLE_THREAD_P; \ + bne- .Lpseudo_cancel; \ + .type __##syscall_name##_nocancel,@function; \ + .globl __##syscall_name##_nocancel; \ + __##syscall_name##_nocancel: \ + DO_CALL (SYS_ify (syscall_name)); \ + PSEUDO_RET; \ + .size __##syscall_name##_nocancel,.-__##syscall_name##_nocancel; \ + .Lpseudo_cancel: \ + stwu 1,-48(1); \ + cfi_adjust_cfa_offset (48); \ + mflr 9; \ + stw 9,52(1); \ + cfi_offset (lr, 4); \ + DOCARGS_##args; /* save syscall args around CENABLE. */ \ + CENABLE; \ + stw 3,16(1); /* store CENABLE return value (MASK). */ \ + UNDOCARGS_##args; /* restore syscall args. */ \ + DO_CALL (SYS_ify (syscall_name)); \ + mfcr 0; /* save CR/R3 around CDISABLE. */ \ + stw 3,8(1); \ + stw 0,12(1); \ + lwz 3,16(1); /* pass MASK to CDISABLE. */ \ + CDISABLE; \ + lwz 4,52(1); \ + lwz 0,12(1); /* restore CR/R3. */ \ + lwz 3,8(1); \ + mtlr 4; \ + mtcr 0; \ + addi 1,1,48; + +# define DOCARGS_0 +# define UNDOCARGS_0 + +# define DOCARGS_1 stw 3,20(1); DOCARGS_0 +# define UNDOCARGS_1 lwz 3,20(1); UNDOCARGS_0 + +# define DOCARGS_2 stw 4,24(1); DOCARGS_1 +# define UNDOCARGS_2 lwz 4,24(1); UNDOCARGS_1 + +# define DOCARGS_3 stw 5,28(1); DOCARGS_2 +# define UNDOCARGS_3 lwz 5,28(1); UNDOCARGS_2 + +# define DOCARGS_4 stw 6,32(1); DOCARGS_3 +# define UNDOCARGS_4 lwz 6,32(1); UNDOCARGS_3 + +# define DOCARGS_5 stw 7,36(1); DOCARGS_4 +# define UNDOCARGS_5 lwz 7,36(1); UNDOCARGS_4 + +# define DOCARGS_6 stw 8,40(1); DOCARGS_5 +# define UNDOCARGS_6 lwz 8,40(1); UNDOCARGS_5 + +# ifdef IS_IN_libpthread +# define CENABLE bl __pthread_enable_asynccancel@local +# define CDISABLE bl __pthread_disable_asynccancel@local +# elif !defined NOT_IN_libc +# define CENABLE bl __libc_enable_asynccancel@local +# define CDISABLE bl __libc_disable_asynccancel@local +# elif defined IS_IN_librt +# define CENABLE bl __librt_enable_asynccancel@local +# define CDISABLE bl __librt_disable_asynccancel@local +# else +# error Unsupported library +# endif + +# ifndef __ASSEMBLER__ +# define SINGLE_THREAD_P \ + __builtin_expect (THREAD_GETMEM (THREAD_SELF, \ + header.multiple_threads) == 0, 1) +# else +# define SINGLE_THREAD_P \ + lwz 10,MULTIPLE_THREADS_OFFSET(2); \ + cmpwi 10,0 +# endif + +#elif !defined __ASSEMBLER__ + +# define SINGLE_THREAD_P (1) +# define NO_CANCELLATION 1 + +#endif + +#ifndef __ASSEMBLER__ +# define RTLD_SINGLE_THREAD_P \ + __builtin_expect (THREAD_GETMEM (THREAD_SELF, \ + header.multiple_threads) == 0, 1) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc32/vfork.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc32/vfork.S new file mode 100644 index 00000000..8d3773ca --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc32/vfork.S @@ -0,0 +1,58 @@ +/* Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2004. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#define _ERRNO_H 1 +#include +#include +#include + +/* Clone the calling process, but without copying the whole address space. + The calling process is suspended until the new process exits or is + replaced by a call to `execve'. Return -1 for errors, 0 to the new process, + and the process ID of the new process to the old process. */ + +ENTRY (__vfork) + lwz 0,PID(2) + cmpwi 0,0,0 + neg 0,0 + bne- 0,1f + lis 0,0x8000 +1: stw 0,PID(2) + + DO_CALL (SYS_ify (vfork)) + + cmpwi 1,3,0 + beqlr- 1 + + lwz 0,PID(2) + /* Cannot use clrlwi. here, because cr0 needs to be preserved + until PSEUDO_RET. */ + clrlwi 4,0,1 + cmpwi 1,4,0 + beq- 1,1f + neg 4,0 +1: stw 4,PID(2) + + PSEUDO_RET + +PSEUDO_END (__vfork) +libc_hidden_def (__vfork) +weak_alias (__vfork, vfork) +libc_hidden_weak(vfork) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/clone.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/clone.S new file mode 100644 index 00000000..675a997e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/clone.S @@ -0,0 +1,9 @@ +/* We want an #include_next, but we are the main source file. + So, #include ourselves and in that incarnation we can use #include_next. */ +#ifndef INCLUDED_SELF +# define INCLUDED_SELF +# include +#else +# define RESET_PID +# include_next +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/pt-vfork.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/pt-vfork.S new file mode 100644 index 00000000..e5b7b535 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/pt-vfork.S @@ -0,0 +1,49 @@ +/* Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2004. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#define _ERRNO_H 1 +#include +#include +#include + +/* Clone the calling process, but without copying the whole address space. + The calling process is suspended until the new process exits or is + replaced by a call to `execve'. Return -1 for errors, 0 to the new process, + and the process ID of the new process to the old process. */ + +ENTRY (__vfork) + lwz 0,PID(13) + neg 0,0 + stw 0,PID(13) + + DO_CALL (SYS_ify (vfork)) + + cmpwi 1,3,0 + beqlr- 1 + + lwz 0,PID(13) + neg 0,0 + stw 0,PID(13) + + PSEUDO_RET + +PSEUDO_END (__vfork) + +weak_alias (__vfork, vfork) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h new file mode 100644 index 00000000..8e5e477b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep-cancel.h @@ -0,0 +1,125 @@ +/* Cancellable system call stubs. Linux/PowerPC64 version. + Copyright (C) 2003, 2004, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Franz Sirl , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA + 02110-1301 USA. */ + +#include +#include +#ifndef __ASSEMBLER__ +# include +#endif + +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + +# ifdef HAVE_ASM_GLOBAL_DOT_NAME +# define DASHDASHPFX(str) .__##str +# else +# define DASHDASHPFX(str) __##str +# endif + +# undef PSEUDO +# define PSEUDO(name, syscall_name, args) \ + .section ".text"; \ + ENTRY (name) \ + SINGLE_THREAD_P; \ + bne- .Lpseudo_cancel; \ + .type DASHDASHPFX(syscall_name##_nocancel),@function; \ + .globl DASHDASHPFX(syscall_name##_nocancel); \ + DASHDASHPFX(syscall_name##_nocancel): \ + DO_CALL (SYS_ify (syscall_name)); \ + PSEUDO_RET; \ + .size DASHDASHPFX(syscall_name##_nocancel),.-DASHDASHPFX(syscall_name##_nocancel); \ + .Lpseudo_cancel: \ + stdu 1,-128(1); \ + cfi_adjust_cfa_offset (128); \ + mflr 9; \ + std 9,128+16(1); \ + cfi_offset (lr, 16); \ + DOCARGS_##args; /* save syscall args around CENABLE. */ \ + CENABLE; \ + std 3,72(1); /* store CENABLE return value (MASK). */ \ + UNDOCARGS_##args; /* restore syscall args. */ \ + DO_CALL (SYS_ify (syscall_name)); \ + mfcr 0; /* save CR/R3 around CDISABLE. */ \ + std 3,64(1); \ + std 0,8(1); \ + ld 3,72(1); /* pass MASK to CDISABLE. */ \ + CDISABLE; \ + ld 9,128+16(1); \ + ld 0,8(1); /* restore CR/R3. */ \ + ld 3,64(1); \ + mtlr 9; \ + mtcr 0; \ + addi 1,1,128; + +# define DOCARGS_0 +# define UNDOCARGS_0 + +# define DOCARGS_1 std 3,80(1); DOCARGS_0 +# define UNDOCARGS_1 ld 3,80(1); UNDOCARGS_0 + +# define DOCARGS_2 std 4,88(1); DOCARGS_1 +# define UNDOCARGS_2 ld 4,88(1); UNDOCARGS_1 + +# define DOCARGS_3 std 5,96(1); DOCARGS_2 +# define UNDOCARGS_3 ld 5,96(1); UNDOCARGS_2 + +# define DOCARGS_4 std 6,104(1); DOCARGS_3 +# define UNDOCARGS_4 ld 6,104(1); UNDOCARGS_3 + +# define DOCARGS_5 std 7,112(1); DOCARGS_4 +# define UNDOCARGS_5 ld 7,112(1); UNDOCARGS_4 + +# define DOCARGS_6 std 8,120(1); DOCARGS_5 +# define UNDOCARGS_6 ld 8,120(1); UNDOCARGS_5 + +# ifdef IS_IN_libpthread +# define CENABLE bl JUMPTARGET(__pthread_enable_asynccancel) +# define CDISABLE bl JUMPTARGET(__pthread_disable_asynccancel) +# elif !defined NOT_IN_libc +# define CENABLE bl JUMPTARGET(__libc_enable_asynccancel) +# define CDISABLE bl JUMPTARGET(__libc_disable_asynccancel) +# elif defined IS_IN_librt +# define CENABLE bl JUMPTARGET(__librt_enable_asynccancel) +# define CDISABLE bl JUMPTARGET(__librt_disable_asynccancel) +# else +# error Unsupported library +# endif + +# ifndef __ASSEMBLER__ +# define SINGLE_THREAD_P \ + __builtin_expect (THREAD_GETMEM (THREAD_SELF, \ + header.multiple_threads) == 0, 1) +# else +# define SINGLE_THREAD_P \ + lwz 10,MULTIPLE_THREADS_OFFSET(13); \ + cmpwi 10,0 +# endif + +#elif !defined __ASSEMBLER__ + +# define SINGLE_THREAD_P (1) +# define NO_CANCELLATION 1 + +#endif + +#ifndef __ASSEMBLER__ +# define RTLD_SINGLE_THREAD_P \ + __builtin_expect (THREAD_GETMEM (THREAD_SELF, \ + header.multiple_threads) == 0, 1) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/timer_create.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/timer_create.c new file mode 100644 index 00000000..172223af --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/timer_create.c @@ -0,0 +1 @@ +#include "../x86_64/timer_create.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/timer_delete.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/timer_delete.c new file mode 100644 index 00000000..537516e0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/timer_delete.c @@ -0,0 +1 @@ +#include "../x86_64/timer_delete.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/timer_getoverr.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/timer_getoverr.c new file mode 100644 index 00000000..3f21a73c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/timer_getoverr.c @@ -0,0 +1 @@ +#include "../x86_64/timer_getoverr.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/timer_gettime.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/timer_gettime.c new file mode 100644 index 00000000..a50143ad --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/timer_gettime.c @@ -0,0 +1 @@ +#include "../x86_64/timer_gettime.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/timer_settime.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/timer_settime.c new file mode 100644 index 00000000..37baeffa --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/timer_settime.c @@ -0,0 +1 @@ +#include "../x86_64/timer_settime.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/vfork.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/vfork.S new file mode 100644 index 00000000..64aa952c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/powerpc64/vfork.S @@ -0,0 +1,57 @@ +/* Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2004. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#define _ERRNO_H 1 +#include +#include +#include + +/* Clone the calling process, but without copying the whole address space. + The calling process is suspended until the new process exits or is + replaced by a call to `execve'. Return -1 for errors, 0 to the new process, + and the process ID of the new process to the old process. */ + +ENTRY (__vfork) + lwz 0,PID(13) + cmpwi 0,0,0 + neg 0,0 + bne- 0,1f + lis 0,0x8000 +1: stw 0,PID(13) + + DO_CALL (SYS_ify (vfork)) + + cmpwi 1,3,0 + beqlr- 1 + + lwz 0,PID(13) + clrlwi 4,0,1 + cmpwi 1,4,0 + beq- 1,1f + neg 4,0 +1: stw 4,PID(13) + + PSEUDO_RET + +PSEUDO_END (__vfork) +libc_hidden_def (__vfork) +weak_alias (__vfork, vfork) +libc_hidden_weak(vfork) + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/pt-__syscall_error.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/pt-__syscall_error.c new file mode 100644 index 00000000..2a402e5a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/pt-__syscall_error.c @@ -0,0 +1 @@ +#include <../../../../../../../libc/sysdeps/linux/powerpc/__syscall_error.c> diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/pt-longjmp.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/pt-longjmp.c new file mode 100644 index 00000000..b6d6b3d5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/pt-longjmp.c @@ -0,0 +1,37 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include "pthreadP.h" + +void +__vmx_longjmp (jmp_buf env, int val) +{ + __libc_longjmp (env, val); +} + +void +__vmx_siglongjmp (jmp_buf env, int val) +{ + __libc_siglongjmp (env, val); +} +weak_alias(__vmx_longjmp, longjmp) +weak_alias(__vmx_siglongjmp, siglongjmp) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/pt-vfork.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/pt-vfork.S new file mode 100644 index 00000000..0225219d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/pt-vfork.S @@ -0,0 +1,5 @@ +#if defined __powerpc64__ +# include "powerpc64/pt-vfork.S" +#else +# include "powerpc32/pt-vfork.S" +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/pthread_once.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/pthread_once.c new file mode 100644 index 00000000..a495b64f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/pthread_once.c @@ -0,0 +1,101 @@ +/* Copyright (C) 2003, 2004, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Paul Mackerras , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "pthreadP.h" +#include + + +unsigned long int __fork_generation attribute_hidden; + + +static void +clear_once_control (void *arg) +{ + pthread_once_t *once_control = (pthread_once_t *) arg; + + *once_control = 0; + lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE); +} + + +int +attribute_protected +__pthread_once (pthread_once_t *once_control, void (*init_routine) (void)) +{ + for (;;) + { + int oldval; + int newval; + int tmp; + + /* Pseudo code: + newval = __fork_generation | 1; + oldval = *once_control; + if ((oldval & 2) == 0) + *once_control = newval; + Do this atomically. + */ + newval = __fork_generation | 1; + __asm__ __volatile__ ("1: lwarx %0,0,%3\n" + " andi. %1,%0,2\n" + " bne 2f\n" + " stwcx. %4,0,%3\n" + " bne 1b\n" + "2: isync" + : "=&r" (oldval), "=&r" (tmp), "=m" (*once_control) + : "r" (once_control), "r" (newval), "m" (*once_control) + : "cr0"); + + /* Check if the initializer has already been done. */ + if ((oldval & 2) != 0) + return 0; + + /* Check if another thread already runs the initializer. */ + if ((oldval & 1) == 0) + break; + + /* Check whether the initializer execution was interrupted by a fork. */ + if (oldval != newval) + break; + + /* Same generation, some other thread was faster. Wait. */ + lll_futex_wait (once_control, oldval, LLL_PRIVATE); + } + + + /* This thread is the first here. Do the initialization. + Register a cleanup handler so that in case the thread gets + interrupted the initialization can be restarted. */ + pthread_cleanup_push (clear_once_control, once_control); + + init_routine (); + + pthread_cleanup_pop (0); + + + /* Add one to *once_control to take the bottom 2 bits from 01 to 10. */ + atomic_increment (once_control); + + /* Wake up all other threads. */ + lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE); + + return 0; +} +weak_alias (__pthread_once, pthread_once) +strong_alias (__pthread_once, __pthread_once_internal) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/pthread_spin_unlock.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/pthread_spin_unlock.c new file mode 100644 index 00000000..4be31ff6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/pthread_spin_unlock.c @@ -0,0 +1,29 @@ +/* pthread_spin_unlock -- unlock a spin lock. PowerPC version. + Copyright (C) 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "pthreadP.h" +#include + +int +pthread_spin_unlock (pthread_spinlock_t *lock) +{ + __asm__ __volatile__ (__lll_rel_instr ::: "memory"); + *lock = 0; + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/sem_post.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/sem_post.c new file mode 100644 index 00000000..cdc8be7e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/sem_post.c @@ -0,0 +1,47 @@ +/* sem_post -- post to a POSIX semaphore. Powerpc version. + Copyright (C) 2003, 2004, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Paul Mackerras , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include + +int +__new_sem_post (sem_t *sem) +{ + struct new_sem *isem = (struct new_sem *) sem; + + __asm__ __volatile__ (__lll_rel_instr ::: "memory"); + atomic_increment (&isem->value); + __asm__ __volatile__ (__lll_acq_instr ::: "memory"); + if (isem->nwaiters > 0) + { + int err = lll_futex_wake (&isem->value, 1, + isem->private ^ FUTEX_PRIVATE_FLAG); + if (__builtin_expect (err, 0) < 0) + { + __set_errno (-err); + return -1; + } + } + return 0; +} +weak_alias(__new_sem_post, sem_post) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/sysdep-cancel.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/sysdep-cancel.h new file mode 100644 index 00000000..dab7e0be --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/sysdep-cancel.h @@ -0,0 +1,5 @@ +#if defined(__powerpc64__) +#include "powerpc64/sysdep-cancel.h" +#else +#include "powerpc32/sysdep-cancel.h" +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/vfork.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/vfork.S new file mode 100644 index 00000000..27d29020 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/powerpc/vfork.S @@ -0,0 +1,5 @@ +#if defined __powerpc64__ +# include "powerpc64/vfork.S" +#else +# include "powerpc32/vfork.S" +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-accept.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-accept.S new file mode 100644 index 00000000..24062101 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-accept.S @@ -0,0 +1,12 @@ +#include +#ifndef __NR_accept +#error Missing definition of NR_accept needed for cancellation. +#endif +PSEUDO (__libc_accept, accept, 3) +ret +PSEUDO_END(__libc_accept) +libpthread_hidden_def (__libc_accept) +weak_alias (__libc_accept, __accept) +libpthread_hidden_weak (__accept) +weak_alias (__libc_accept, accept) +libpthread_hidden_weak (accept) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-close.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-close.S new file mode 100644 index 00000000..ab32ca59 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-close.S @@ -0,0 +1,9 @@ +#include +PSEUDO (__libc_close, close, 1) +ret +PSEUDO_END (__libc_close) +libpthread_hidden_def (__libc_close) +weak_alias (__libc_close, __close) +libpthread_hidden_weak (__close) +weak_alias (__libc_close, close) +libpthread_hidden_weak (close) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-connect.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-connect.S new file mode 100644 index 00000000..b5124f8e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-connect.S @@ -0,0 +1,12 @@ +#include +#ifndef __NR_connect +#error Missing definition of NR_connect needed for cancellation. +#endif +PSEUDO (__libc_connect, connect, 3) +ret +PSEUDO_END(__libc_connect) +libpthread_hidden_def (__libc_connect) +weak_alias (__libc_connect, __connect) +libpthread_hidden_weak (__connect) +weak_alias (__libc_connect, connect) +libpthread_hidden_weak (connect) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-fcntl.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-fcntl.c new file mode 100644 index 00000000..0a8fd3cc --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-fcntl.c @@ -0,0 +1 @@ +#include <../../../../../../libc/sysdeps/linux/common/__syscall_fcntl.c> diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-fork.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-fork.c new file mode 100644 index 00000000..3e1b70f8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-fork.c @@ -0,0 +1,29 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +extern int __libc_fork (void); + +pid_t +__fork (void) +{ + return __libc_fork (); +} +strong_alias (__fork, fork) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-fsync.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-fsync.c new file mode 100644 index 00000000..6ec4821c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-fsync.c @@ -0,0 +1,2 @@ +#include +#include <../../../../../../libc/sysdeps/linux/common/fsync.c> diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-llseek.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-llseek.c new file mode 100644 index 00000000..1d0d5787 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-llseek.c @@ -0,0 +1,3 @@ +#include +#define libc_hidden libpthread_hidden +#include <../../../../../../libc/sysdeps/linux/common/llseek.c> diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-lseek.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-lseek.S new file mode 100644 index 00000000..4db71722 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-lseek.S @@ -0,0 +1,7 @@ +#include +PSEUDO (__libc_lseek, lseek, 3) +ret +PSEUDO_END (__libc_lseek) +libpthread_hidden_def (__libc_lseek) +weak_alias (__libc_lseek, lseek) +libpthread_hidden_weak (lseek) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-msgrcv.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-msgrcv.c new file mode 100644 index 00000000..3bb9d53d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-msgrcv.c @@ -0,0 +1,2 @@ +#define L_msgrcv +#include <../../../../../../libc/misc/sysvipc/msgq.c> diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-msgsnd.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-msgsnd.c new file mode 100644 index 00000000..1566f65f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-msgsnd.c @@ -0,0 +1,2 @@ +#define L_msgsnd +#include <../../../../../../libc/misc/sysvipc/msgq.c> diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-msync.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-msync.S new file mode 100644 index 00000000..640270ad --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-msync.S @@ -0,0 +1,7 @@ +#include +PSEUDO (__libc_msync, msync, 3) +ret +PSEUDO_END(__libc_msync) +libpthread_hidden_def (__libc_msync) +weak_alias (__libc_msync, msync) +libpthread_hidden_weak (msync) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-nanosleep.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-nanosleep.S new file mode 100644 index 00000000..08d8f015 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-nanosleep.S @@ -0,0 +1,9 @@ +#include +PSEUDO (__libc_nanosleep, nanosleep, 3) +ret +PSEUDO_END (__libc_nanosleep) +libpthread_hidden_def (__libc_nanosleep) +weak_alias (__libc_nanosleep, __nanosleep) +libpthread_hidden_weak (__nanosleep) +weak_alias (__libc_nanosleep, nanosleep) +libpthread_hidden_weak (nanosleep) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-open.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-open.S new file mode 100644 index 00000000..39ed92cc --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-open.S @@ -0,0 +1,9 @@ +#include +PSEUDO (__libc_open, open, 3) +ret +PSEUDO_END (__libc_open) +libpthread_hidden_def (__libc_open) +weak_alias (__libc_open, __open) +libpthread_hidden_weak (__open) +weak_alias (__libc_open, open) +libpthread_hidden_weak (open) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-open64.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-open64.c new file mode 100644 index 00000000..2029539a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-open64.c @@ -0,0 +1 @@ +#include <../../../../../../libc/sysdeps/linux/common/open64.c> diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-pause.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-pause.S new file mode 100644 index 00000000..c6cb5718 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-pause.S @@ -0,0 +1,7 @@ +#include +PSEUDO (__libc_pause, pause, 0) +ret +PSEUDO_END (__libc_pause) +libpthread_hidden_def (__libc_pause) +weak_alias (__libc_pause, pause) +libpthread_hidden_weak (pause) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-pread_pwrite.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-pread_pwrite.c new file mode 100644 index 00000000..f32c0a67 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-pread_pwrite.c @@ -0,0 +1 @@ +#include "pread_write.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-raise.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-raise.c new file mode 100644 index 00000000..d256ebcb --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-raise.c @@ -0,0 +1,52 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include + + +int +raise ( + int sig) +{ +#if __ASSUME_TGKILL || defined __NR_tgkill + /* raise is an async-safe function. It could be called while the + fork function temporarily invalidated the PID field. Adjust for + that. */ + pid_t pid = THREAD_GETMEM (THREAD_SELF, pid); + if (__builtin_expect (pid < 0, 0)) + pid = -pid; +#endif + +#if __ASSUME_TGKILL + return INLINE_SYSCALL (tgkill, 3, pid, THREAD_GETMEM (THREAD_SELF, tid), + sig); +#else +# ifdef __NR_tgkill + int res = INLINE_SYSCALL (tgkill, 3, pid, THREAD_GETMEM (THREAD_SELF, tid), + sig); + if (res != -1 || errno != ENOSYS) + return res; +# endif + return INLINE_SYSCALL (tkill, 2, THREAD_GETMEM (THREAD_SELF, tid), sig); +#endif +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-read.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-read.S new file mode 100644 index 00000000..623ba27a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-read.S @@ -0,0 +1,9 @@ +#include +PSEUDO (__libc_read, read, 3) +ret +PSEUDO_END (__libc_read) +libpthread_hidden_def (__libc_read) +weak_alias (__libc_read, __read) +libpthread_hidden_weak (__read) +weak_alias (__libc_read, read) +libpthread_hidden_weak (read) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-recv.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-recv.S new file mode 100644 index 00000000..6d2e3c2d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-recv.S @@ -0,0 +1,12 @@ +#include +#ifndef __NR_recv +#error Missing definition of NR_recv needed for cancellation. +#endif +PSEUDO (__libc_recv, recv, 4) +ret +PSEUDO_END(__libc_recv) +libpthread_hidden_def (__libc_recv) +weak_alias (__libc_recv, __recv) +libpthread_hidden_weak (__recv) +weak_alias (__libc_recv, recv) +libpthread_hidden_weak (recv) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-recvfrom.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-recvfrom.S new file mode 100644 index 00000000..96aeeaa3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-recvfrom.S @@ -0,0 +1,12 @@ +#include +#ifndef __NR_recvfrom +#error Missing definition of NR_recvfrom needed for cancellation. +#endif +PSEUDO (__libc_recvfrom, recvfrom, 6) +ret +PSEUDO_END(__libc_recvfrom) +libpthread_hidden_def (__libc_recvfrom) +weak_alias (__libc_recvfrom, __recvfrom) +libpthread_hidden_weak (__recvfrom) +weak_alias (__libc_recvfrom, recvfrom) +libpthread_hidden_weak (recvfrom) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-recvmsg.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-recvmsg.S new file mode 100644 index 00000000..f7161e47 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-recvmsg.S @@ -0,0 +1,12 @@ +#include +#ifndef __NR_recvmsg +#error Missing definition of NR_recvmsg needed for cancellation. +#endif +PSEUDO (__libc_recvmsg, recvmsg, 3) +ret +PSEUDO_END(__libc_recvmsg) +libpthread_hidden_def (__libc_recvmsg) +weak_alias (__libc_recvmsg, __recvmsg) +libpthread_hidden_weak (__recvmsg) +weak_alias (__libc_recvmsg, recvmsg) +libpthread_hidden_weak (recvmsg) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-send.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-send.S new file mode 100644 index 00000000..76bed39e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-send.S @@ -0,0 +1,12 @@ +#include +#ifndef __NR_send +#error Missing definition of NR_send needed for cancellation. +#endif +PSEUDO (__libc_send, send, 4) +ret +PSEUDO_END (__libc_send) +libpthread_hidden_def (__libc_send) +weak_alias (__libc_send, __send) +libpthread_hidden_weak (__send) +weak_alias (__libc_send, send) +libpthread_hidden_weak (send) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-sendmsg.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-sendmsg.S new file mode 100644 index 00000000..d17096ea --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-sendmsg.S @@ -0,0 +1,12 @@ +#include +#ifndef __NR_sendmsg +#error Missing definition of NR_sendmsg needed for cancellation. +#endif +PSEUDO (__libc_sendmsg, sendmsg, 3) +ret +PSEUDO_END(__libc_sendmsg) +libpthread_hidden_def (__libc_sendmsg) +weak_alias (__libc_sendmsg, __sendmsg) +libpthread_hidden_weak (__sendmsg) +weak_alias (__libc_sendmsg, sendmsg) +libpthread_hidden_weak (sendmsg) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-sendto.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-sendto.S new file mode 100644 index 00000000..d07a71f8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-sendto.S @@ -0,0 +1,12 @@ +#include +#ifndef __NR_sendto +#error Missing definition of NR_sendto needed for cancellation. +#endif +PSEUDO (__libc_sendto, sendto, 6) +ret +PSEUDO_END(__libc_sendto) +libpthread_hidden_def (__libc_sendto) +weak_alias (__libc_sendto, __sendto) +libpthread_hidden_weak (__sendto) +weak_alias (__libc_sendto, sendto) +libpthread_hidden_weak (sendto) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-sigwait.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-sigwait.c new file mode 100644 index 00000000..bde0a929 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-sigwait.c @@ -0,0 +1,2 @@ +#include +#include "../../../../../../libc/signal/sigwait.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-sleep.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-sleep.c new file mode 100644 index 00000000..9e948adc --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-sleep.c @@ -0,0 +1,2 @@ +#include +#include <../../../../../../libc/unistd/sleep.c> diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-tcdrain.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-tcdrain.c new file mode 100644 index 00000000..07c1f823 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-tcdrain.c @@ -0,0 +1 @@ +#include <../../../../../../libc/termios/tcdrain.c> diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-wait.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-wait.c new file mode 100644 index 00000000..a05c3eb4 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-wait.c @@ -0,0 +1,2 @@ +#include +#include <../../../../../../libc/sysdeps/linux/common/wait.c> diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-waitpid.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-waitpid.c new file mode 100644 index 00000000..8461c3ff --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-waitpid.c @@ -0,0 +1 @@ +#include <../../../../../../libc/sysdeps/linux/common/waitpid.c> diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-write.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-write.S new file mode 100644 index 00000000..6bc66677 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pt-write.S @@ -0,0 +1,9 @@ +#include +PSEUDO (__libc_write, write, 3) +ret +PSEUDO_END (__libc_write) +libpthread_hidden_def (__libc_write) +weak_alias (__libc_write, __write) +libpthread_hidden_weak (__write) +weak_alias (__libc_write, write) +libpthread_hidden_weak (write) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pthread-pi-defines.sym b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pthread-pi-defines.sym new file mode 100644 index 00000000..46fbd0de --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pthread-pi-defines.sym @@ -0,0 +1,8 @@ +#include + +-- These PI macros are used by assembly code. + +MUTEX_KIND offsetof (pthread_mutex_t, __data.__kind) +ROBUST_BIT PTHREAD_MUTEX_ROBUST_NORMAL_NP +PI_BIT PTHREAD_MUTEX_PRIO_INHERIT_NP +PS_BIT PTHREAD_MUTEX_PSHARED_BIT diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_attr_getaffinity.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_attr_getaffinity.c new file mode 100644 index 00000000..01fd0312 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_attr_getaffinity.c @@ -0,0 +1,55 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include + + +int +pthread_attr_getaffinity_np(const pthread_attr_t *attr, size_t cpusetsize, + cpu_set_t *cpuset) +{ + const struct pthread_attr *iattr; + + assert (sizeof (*attr) >= sizeof (struct pthread_attr)); + iattr = (const struct pthread_attr *) attr; + + if (iattr->cpuset != NULL) + { + /* Check whether there are any bits set beyond the limits + the user requested. */ + size_t cnt; + for (cnt = cpusetsize; cnt < iattr->cpusetsize; ++cnt) + if (((char *) iattr->cpuset)[cnt] != 0) + return EINVAL; + + void *p = mempcpy (cpuset, iattr->cpuset, iattr->cpusetsize); + if (cpusetsize > iattr->cpusetsize) + memset (p, '\0', cpusetsize - iattr->cpusetsize); + } + else + /* We have no information. */ + memset (cpuset, -1, cpusetsize); + + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_attr_setaffinity.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_attr_setaffinity.c new file mode 100644 index 00000000..744d55af --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_attr_setaffinity.c @@ -0,0 +1,81 @@ +/* Copyright (C) 2003, 2004, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include + + +/* Defined in pthread_setaffinity.c. */ +extern size_t __kernel_cpumask_size attribute_hidden; +extern int __determine_cpumask_size (pid_t tid); +libpthread_hidden_proto(__determine_cpumask_size) + +int +pthread_attr_setaffinity_np (pthread_attr_t *attr, size_t cpusetsize, + const cpu_set_t *cpuset) +{ + struct pthread_attr *iattr; + + assert (sizeof (*attr) >= sizeof (struct pthread_attr)); + iattr = (struct pthread_attr *) attr; + + if (cpuset == NULL || cpusetsize == 0) + { + free (iattr->cpuset); + iattr->cpuset = NULL; + iattr->cpusetsize = 0; + } + else + { + if (__kernel_cpumask_size == 0) + { + int res = __determine_cpumask_size (THREAD_SELF->tid); + if (res != 0) + /* Some serious problem. */ + return res; + } + + /* Check whether the new bitmask has any bit set beyond the + last one the kernel accepts. */ + size_t cnt; + for (cnt = __kernel_cpumask_size; cnt < cpusetsize; ++cnt) + if (((char *) cpuset)[cnt] != '\0') + /* Found a nonzero byte. This means the user request cannot be + fulfilled. */ + return EINVAL; + + if (iattr->cpusetsize != cpusetsize) + { + void *newp = (cpu_set_t *) realloc (iattr->cpuset, cpusetsize); + if (newp == NULL) + return ENOMEM; + + iattr->cpuset = newp; + iattr->cpusetsize = cpusetsize; + } + + memcpy (iattr->cpuset, cpuset, cpusetsize); + } + + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_getaffinity.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_getaffinity.c new file mode 100644 index 00000000..affcc6a6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_getaffinity.c @@ -0,0 +1,46 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include +#include + + +int +__pthread_getaffinity_np (pthread_t th, size_t cpusetsize, cpu_set_t *cpuset) +{ + const struct pthread *pd = (const struct pthread *) th; + + INTERNAL_SYSCALL_DECL (err); + int res = INTERNAL_SYSCALL (sched_getaffinity, err, 3, pd->tid, + MIN (INT_MAX, cpusetsize), cpuset); + if (INTERNAL_SYSCALL_ERROR_P (res, err)) + return INTERNAL_SYSCALL_ERRNO (res, err); + + /* Clean the rest of the memory the kernel didn't do. */ + memset ((char *) cpuset + res, '\0', cpusetsize - res); + + return 0; +} +strong_alias(__pthread_getaffinity_np, pthread_getaffinity_np) + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_getcpuclockid.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_getcpuclockid.c new file mode 100644 index 00000000..9e28f69f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_getcpuclockid.c @@ -0,0 +1,57 @@ +/* Copyright (C) 2000, 2001, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include + + +int +pthread_getcpuclockid ( + pthread_t threadid, + clockid_t *clockid) +{ + struct pthread *pd = (struct pthread *) threadid; + + /* Make sure the descriptor is valid. */ + if (INVALID_TD_P (pd)) + /* Not a valid thread handle. */ + return ESRCH; + +#ifdef CLOCK_THREAD_CPUTIME_ID + /* We need to store the thread ID in the CLOCKID variable together + with a number identifying the clock. We reserve the low 3 bits + for the clock ID and the rest for the thread ID. This is + problematic if the thread ID is too large. But 29 bits should be + fine. + + If some day more clock IDs are needed the ID part can be + enlarged. The IDs are entirely internal. */ + if (pd->tid >= 1 << (8 * sizeof (*clockid) - CLOCK_IDFIELD_SIZE)) + return ERANGE; + + /* Store the number. */ + *clockid = CLOCK_THREAD_CPUTIME_ID | (pd->tid << CLOCK_IDFIELD_SIZE); + + return 0; +#else + /* We don't have a timer for that. */ + return ENOENT; +#endif +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_kill.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_kill.c new file mode 100644 index 00000000..3a70c376 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_kill.c @@ -0,0 +1,78 @@ +/* Copyright (C) 2002, 2003, 2004, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include + + +int +__pthread_kill ( + pthread_t threadid, + int signo) +{ + struct pthread *pd = (struct pthread *) threadid; + + /* Make sure the descriptor is valid. */ + if (DEBUGGING_P && INVALID_TD_P (pd)) + /* Not a valid thread handle. */ + return ESRCH; + + /* Force load of pd->tid into local variable or register. Otherwise + if a thread exits between ESRCH test and tgkill, we might return + EINVAL, because pd->tid would be cleared by the kernel. */ + pid_t tid = atomic_forced_read (pd->tid); + if (__builtin_expect (tid <= 0, 0)) + /* Not a valid thread handle. */ + return ESRCH; + + /* Disallow sending the signal we use for cancellation, timers, for + for the setxid implementation. */ + if (signo == SIGCANCEL || signo == SIGTIMER || signo == SIGSETXID) + return EINVAL; + + /* We have a special syscall to do the work. */ + INTERNAL_SYSCALL_DECL (err); + + /* One comment: The PID field in the TCB can temporarily be changed + (in fork). But this must not affect this code here. Since this + function would have to be called while the thread is executing + fork, it would have to happen in a signal handler. But this is + no allowed, pthread_kill is not guaranteed to be async-safe. */ + int val; +#if __ASSUME_TGKILL + val = INTERNAL_SYSCALL (tgkill, err, 3, THREAD_GETMEM (THREAD_SELF, pid), + tid, signo); +#else +# ifdef __NR_tgkill + val = INTERNAL_SYSCALL (tgkill, err, 3, THREAD_GETMEM (THREAD_SELF, pid), + tid, signo); + if (INTERNAL_SYSCALL_ERROR_P (val, err) + && INTERNAL_SYSCALL_ERRNO (val, err) == ENOSYS) +# endif + val = INTERNAL_SYSCALL (tkill, err, 2, tid, signo); +#endif + + return (INTERNAL_SYSCALL_ERROR_P (val, err) + ? INTERNAL_SYSCALL_ERRNO (val, err) : 0); +} +strong_alias (__pthread_kill, pthread_kill) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_mutex_cond_lock.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_mutex_cond_lock.c new file mode 100644 index 00000000..804bfab4 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_mutex_cond_lock.c @@ -0,0 +1,14 @@ +#include + +#define LLL_MUTEX_LOCK(mutex) \ + lll_cond_lock ((mutex)->__data.__lock, PTHREAD_MUTEX_PSHARED (mutex)) +#define LLL_MUTEX_TRYLOCK(mutex) \ + lll_cond_trylock ((mutex)->__data.__lock) +#define LLL_ROBUST_MUTEX_LOCK(mutex, id) \ + lll_robust_cond_lock ((mutex)->__data.__lock, id, \ + PTHREAD_ROBUST_MUTEX_PSHARED (mutex)) +#define __pthread_mutex_lock __pthread_mutex_cond_lock +#define __pthread_mutex_lock_full __pthread_mutex_cond_lock_full +#define NO_INCR + +#include diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_setaffinity.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_setaffinity.c new file mode 100644 index 00000000..73a21ed4 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_setaffinity.c @@ -0,0 +1,92 @@ +/* Copyright (C) 2003, 2004, 2006, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include + + +size_t __kernel_cpumask_size attribute_hidden; + + +/* Determine the current affinity. As a side affect we learn + about the size of the cpumask_t in the kernel. */ +extern int __determine_cpumask_size (pid_t tid); +libpthread_hidden_proto(__determine_cpumask_size) +int __determine_cpumask_size (pid_t tid) +{ + INTERNAL_SYSCALL_DECL (err); + int res; + + size_t psize = 128; + void *p = alloca (psize); + + while (res = INTERNAL_SYSCALL (sched_getaffinity, err, 3, tid, psize, p), + INTERNAL_SYSCALL_ERROR_P (res, err) + && INTERNAL_SYSCALL_ERRNO (res, err) == EINVAL) + p = extend_alloca (p, psize, 2 * psize); + + if (res == 0 || INTERNAL_SYSCALL_ERROR_P (res, err)) + return INTERNAL_SYSCALL_ERRNO (res, err); + + __kernel_cpumask_size = res; + + return 0; +} +libpthread_hidden_def(__determine_cpumask_size) + +int +pthread_setaffinity_np (pthread_t th, size_t cpusetsize, + const cpu_set_t *cpuset) +{ + const struct pthread *pd = (const struct pthread *) th; + + INTERNAL_SYSCALL_DECL (err); + int res; + + if (__builtin_expect (__kernel_cpumask_size == 0, 0)) + { + res = __determine_cpumask_size (pd->tid); + if (res != 0) + return res; + } + + /* We now know the size of the kernel cpumask_t. Make sure the user + does not request to set a bit beyond that. */ + size_t cnt; + for (cnt = __kernel_cpumask_size; cnt < cpusetsize; ++cnt) + if (((char *) cpuset)[cnt] != '\0') + /* Found a nonzero byte. This means the user request cannot be + fulfilled. */ + return EINVAL; + + res = INTERNAL_SYSCALL (sched_setaffinity, err, 3, pd->tid, cpusetsize, + cpuset); + +#ifdef RESET_VGETCPU_CACHE + if (!INTERNAL_SYSCALL_ERROR_P (res, err)) + RESET_VGETCPU_CACHE (); +#endif + + return (INTERNAL_SYSCALL_ERROR_P (res, err) + ? INTERNAL_SYSCALL_ERRNO (res, err) + : 0); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_sigqueue.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_sigqueue.c new file mode 100644 index 00000000..9e49085c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_sigqueue.c @@ -0,0 +1,83 @@ +/* Copyright (C) 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2009. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include +#include +#include + + +int +pthread_sigqueue ( + pthread_t threadid, + int signo, + const union sigval value) +{ +#ifdef __NR_rt_tgsigqueueinfo + struct pthread *pd = (struct pthread *) threadid; + + /* Make sure the descriptor is valid. */ + if (DEBUGGING_P && INVALID_TD_P (pd)) + /* Not a valid thread handle. */ + return ESRCH; + + /* Force load of pd->tid into local variable or register. Otherwise + if a thread exits between ESRCH test and tgkill, we might return + EINVAL, because pd->tid would be cleared by the kernel. */ + pid_t tid = atomic_forced_read (pd->tid); + if (__builtin_expect (tid <= 0, 0)) + /* Not a valid thread handle. */ + return ESRCH; + + /* Disallow sending the signal we use for cancellation, timers, for + for the setxid implementation. */ + if (signo == SIGCANCEL || signo == SIGTIMER || signo == SIGSETXID) + return EINVAL; + + /* Set up the siginfo_t structure. */ + siginfo_t info; + memset (&info, '\0', sizeof (siginfo_t)); + info.si_signo = signo; + info.si_code = SI_QUEUE; + info.si_pid = THREAD_GETMEM (THREAD_SELF, pid); + info.si_uid = getuid (); + info.si_value = value; + + /* We have a special syscall to do the work. */ + INTERNAL_SYSCALL_DECL (err); + + /* One comment: The PID field in the TCB can temporarily be changed + (in fork). But this must not affect this code here. Since this + function would have to be called while the thread is executing + fork, it would have to happen in a signal handler. But this is + no allowed, pthread_sigqueue is not guaranteed to be async-safe. */ + int val = INTERNAL_SYSCALL (rt_tgsigqueueinfo, err, 4, + THREAD_GETMEM (THREAD_SELF, pid), + tid, signo, &info); + + return (INTERNAL_SYSCALL_ERROR_P (val, err) + ? INTERNAL_SYSCALL_ERRNO (val, err) : 0); +#else + return ENOSYS; +#endif +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_yield.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_yield.c new file mode 100644 index 00000000..5aecffcf --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/pthread_yield.c @@ -0,0 +1,30 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + + +/* With the 1-on-1 model we implement this function is equivalent to + the 'sched_yield' function. */ +int +pthread_yield (void) +{ + return sched_yield (); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/raise.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/raise.c new file mode 100644 index 00000000..da35cfe9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/raise.c @@ -0,0 +1,74 @@ +/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include + + +int +raise ( + int sig) +{ + struct pthread *pd = THREAD_SELF; +#if __ASSUME_TGKILL || defined __NR_tgkill + pid_t pid = THREAD_GETMEM (pd, pid); +#endif + pid_t selftid = THREAD_GETMEM (pd, tid); + if (selftid == 0) + { + /* This system call is not supposed to fail. */ +#ifdef INTERNAL_SYSCALL + INTERNAL_SYSCALL_DECL (err); + selftid = INTERNAL_SYSCALL (gettid, err, 0); +#else + selftid = INLINE_SYSCALL (gettid, 0); +#endif + THREAD_SETMEM (pd, tid, selftid); + +#if __ASSUME_TGKILL || defined __NR_tgkill + /* We do not set the PID field in the TID here since we might be + called from a signal handler while the thread executes fork. */ + pid = selftid; +#endif + } +#if __ASSUME_TGKILL || defined __NR_tgkill + else + /* raise is an async-safe function. It could be called while the + fork/vfork function temporarily invalidated the PID field. Adjust for + that. */ + if (__builtin_expect (pid <= 0, 0)) + pid = (pid & INT_MAX) == 0 ? selftid : -pid; +#endif + +#if __ASSUME_TGKILL + return INLINE_SYSCALL (tgkill, 3, pid, selftid, sig); +#else +# ifdef __NR_tgkill + int res = INLINE_SYSCALL (tgkill, 3, pid, selftid, sig); + if (res != -1 || errno != ENOSYS) + return res; +# endif + return INLINE_SYSCALL (tkill, 2, selftid, sig); +#endif +} +libc_hidden_def (raise) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/read.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/read.S new file mode 100644 index 00000000..d3adfa84 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/read.S @@ -0,0 +1,19 @@ +#include + +/* +extern int __read_nocancel (int, void *, size_t) attribute_hidden; +*/ +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + +PSEUDO (__libc_read, read, 3) +ret +PSEUDO_END(__libc_read) + +libc_hidden_def (__read_nocancel) +libc_hidden_def (__libc_read) +weak_alias (__libc_read, __read) +libc_hidden_weak (__read) +weak_alias (__libc_read, read) +libc_hidden_weak (read) + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/recv.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/recv.S new file mode 100644 index 00000000..95fa6516 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/recv.S @@ -0,0 +1,12 @@ +#include +#ifndef __NR_recv +#error Missing definition of NR_recv needed for cancellation. +#endif +PSEUDO (__libc_recv, recv, 4) +ret +PSEUDO_END(__libc_recv) +libc_hidden_def (__libc_recv) +weak_alias (__libc_recv, __recv) +libc_hidden_weak (__recv) +weak_alias (__libc_recv, recv) +libc_hidden_weak (recv) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/recvfrom.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/recvfrom.S new file mode 100644 index 00000000..d9cc1e9b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/recvfrom.S @@ -0,0 +1,12 @@ +#include +#ifndef __NR_recvfrom +#error Missing definition of NR_recvfrom needed for cancellation. +#endif +PSEUDO (__libc_recvfrom, recvfrom, 6) +ret +PSEUDO_END(__libc_recvfrom) +libc_hidden_def (__libc_recvfrom) +weak_alias (__libc_recvfrom, __recvfrom) +libc_hidden_weak (__recvfrom) +weak_alias (__libc_recvfrom, recvfrom) +libc_hidden_weak (recvfrom) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/recvmsg.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/recvmsg.S new file mode 100644 index 00000000..c761b907 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/recvmsg.S @@ -0,0 +1,12 @@ +#include +#ifndef __NR_recvmsg +#error Missing definition of NR_recvmsg needed for cancellation. +#endif +PSEUDO (__libc_recvmsg, recvmsg, 3) +ret +PSEUDO_END(__libc_recvmsg) +libc_hidden_def (__libc_recvmsg) +weak_alias (__libc_recvmsg, __recvmsg) +libc_hidden_weak (__recvmsg) +weak_alias (__libc_recvmsg, recvmsg) +libc_hidden_weak (recvmsg) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/register-atfork.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/register-atfork.c new file mode 100644 index 00000000..f956ad56 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/register-atfork.c @@ -0,0 +1,149 @@ +/* Copyright (C) 2002, 2003, 2005, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include + + +/* Lock to protect allocation and deallocation of fork handlers. */ +int __fork_lock = LLL_LOCK_INITIALIZER; + + +/* Number of pre-allocated handler entries. */ +#define NHANDLER 48 + +/* Memory pool for fork handler structures. */ +static struct fork_handler_pool +{ + struct fork_handler_pool *next; + struct fork_handler mem[NHANDLER]; +} fork_handler_pool; + + +static struct fork_handler * +fork_handler_alloc (void) +{ + struct fork_handler_pool *runp = &fork_handler_pool; + struct fork_handler *result = NULL; + unsigned int i; + + do + { + /* Search for an empty entry. */ + for (i = 0; i < NHANDLER; ++i) + if (runp->mem[i].refcntr == 0) + goto found; + } + while ((runp = runp->next) != NULL); + + /* We have to allocate a new entry. */ + runp = (struct fork_handler_pool *) calloc (1, sizeof (*runp)); + if (runp != NULL) + { + /* Enqueue the new memory pool into the list. */ + runp->next = fork_handler_pool.next; + fork_handler_pool.next = runp; + + /* We use the last entry on the page. This means when we start + searching from the front the next time we will find the first + entry unused. */ + i = NHANDLER - 1; + + found: + result = &runp->mem[i]; + result->refcntr = 1; + result->need_signal = 0; + } + + return result; +} + + +int +__register_atfork ( + void (*prepare) (void), + void (*parent) (void), + void (*child) (void), + void *dso_handle) +{ + /* Get the lock to not conflict with other allocations. */ + lll_lock (__fork_lock, LLL_PRIVATE); + + struct fork_handler *newp = fork_handler_alloc (); + + if (newp != NULL) + { + /* Initialize the new record. */ + newp->prepare_handler = prepare; + newp->parent_handler = parent; + newp->child_handler = child; + newp->dso_handle = dso_handle; + + __linkin_atfork (newp); + } + + /* Release the lock. */ + lll_unlock (__fork_lock, LLL_PRIVATE); + + return newp == NULL ? ENOMEM : 0; +} +libc_hidden_def (__register_atfork) + + +void +attribute_hidden +__linkin_atfork (struct fork_handler *newp) +{ + do + newp->next = __fork_handlers; + while (catomic_compare_and_exchange_bool_acq (&__fork_handlers, + newp, newp->next) != 0); +} + +#if 0 +libc_freeres_fn (free_mem) +{ + /* Get the lock to not conflict with running forks. */ + lll_lock (__fork_lock, LLL_PRIVATE); + + /* No more fork handlers. */ + __fork_handlers = NULL; + + /* Free eventually alloated memory blocks for the object pool. */ + struct fork_handler_pool *runp = fork_handler_pool.next; + + memset (&fork_handler_pool, '\0', sizeof (fork_handler_pool)); + + /* Release the lock. */ + lll_unlock (__fork_lock, LLL_PRIVATE); + + /* We can free the memory after releasing the lock. */ + while (runp != NULL) + { + struct fork_handler_pool *oldp = runp; + runp = runp->next; + free (oldp); + } +} +#endif + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sem_post.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sem_post.c new file mode 100644 index 00000000..edb97c4b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sem_post.c @@ -0,0 +1,58 @@ +/* sem_post -- post to a POSIX semaphore. Generic futex-using version. + Copyright (C) 2003, 2004, 2007, 2008 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include + +int +__new_sem_post (sem_t *sem) +{ + struct new_sem *isem = (struct new_sem *) sem; + + __typeof (isem->value) cur; + do + { + cur = isem->value; + if (isem->value == SEM_VALUE_MAX) + { + __set_errno (EOVERFLOW); + return -1; + } + } + while (atomic_compare_and_exchange_bool_acq (&isem->value, cur + 1, cur)); + + atomic_full_barrier (); + if (isem->nwaiters > 0) + { + int err = lll_futex_wake (&isem->value, 1, + isem->private ^ FUTEX_PRIVATE_FLAG); + if (__builtin_expect (err, 0) < 0) + { + __set_errno (-err); + return -1; + } + } + return 0; +} +weak_alias(__new_sem_post, sem_post) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sem_timedwait.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sem_timedwait.c new file mode 100644 index 00000000..3e5e6dca --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sem_timedwait.c @@ -0,0 +1,111 @@ +/* sem_timedwait -- wait on a semaphore. Generic futex-using version. + Copyright (C) 2003, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Paul Mackerras , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include + +#include + + +extern void __sem_wait_cleanup (void *arg) attribute_hidden; + + +int +sem_timedwait (sem_t *sem, const struct timespec *abstime) +{ + struct new_sem *isem = (struct new_sem *) sem; + int err; + + if (atomic_decrement_if_positive (&isem->value) > 0) + return 0; + + if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) + { + __set_errno (EINVAL); + return -1; + } + + atomic_increment (&isem->nwaiters); + + pthread_cleanup_push (__sem_wait_cleanup, isem); + + while (1) + { + struct timeval tv; + struct timespec rt; + int sec, nsec; + + /* Get the current time. */ + __gettimeofday (&tv, NULL); + + /* Compute relative timeout. */ + sec = abstime->tv_sec - tv.tv_sec; + nsec = abstime->tv_nsec - tv.tv_usec * 1000; + if (nsec < 0) + { + nsec += 1000000000; + --sec; + } + + /* Already timed out? */ + err = -ETIMEDOUT; + if (sec < 0) + { + __set_errno (ETIMEDOUT); + err = -1; + break; + } + + /* Do wait. */ + rt.tv_sec = sec; + rt.tv_nsec = nsec; + + /* Enable asynchronous cancellation. Required by the standard. */ + int oldtype = __pthread_enable_asynccancel (); + + err = lll_futex_timed_wait (&isem->value, 0, &rt, + isem->private ^ FUTEX_PRIVATE_FLAG); + + /* Disable asynchronous cancellation. */ + __pthread_disable_asynccancel (oldtype); + + if (err != 0 && err != -EWOULDBLOCK) + { + __set_errno (-err); + err = -1; + break; + } + + if (atomic_decrement_if_positive (&isem->value) > 0) + { + err = 0; + break; + } + } + + pthread_cleanup_pop (0); + + atomic_decrement (&isem->nwaiters); + + return err; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sem_trywait.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sem_trywait.c new file mode 100644 index 00000000..3cf1d9a8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sem_trywait.c @@ -0,0 +1,44 @@ +/* sem_trywait -- wait on a semaphore. Generic futex-using version. + Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Paul Mackerras , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include + + +int +__new_sem_trywait (sem_t *sem) +{ + int *futex = (int *) sem; + int val; + + if (*futex > 0) + { + val = atomic_decrement_if_positive (futex); + if (val > 0) + return 0; + } + + __set_errno (EAGAIN); + return -1; +} +weak_alias(__new_sem_trywait, sem_trywait) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sem_wait.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sem_wait.c new file mode 100644 index 00000000..e661e09c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sem_wait.c @@ -0,0 +1,84 @@ +/* sem_wait -- wait on a semaphore. Generic futex-using version. + Copyright (C) 2003, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Paul Mackerras , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include + +#include + + +void +attribute_hidden +__sem_wait_cleanup (void *arg) +{ + struct new_sem *isem = (struct new_sem *) arg; + + atomic_decrement (&isem->nwaiters); +} + + +int +__new_sem_wait (sem_t *sem) +{ + struct new_sem *isem = (struct new_sem *) sem; + int err; + + if (atomic_decrement_if_positive (&isem->value) > 0) + return 0; + + atomic_increment (&isem->nwaiters); + + pthread_cleanup_push (__sem_wait_cleanup, isem); + + while (1) + { + /* Enable asynchronous cancellation. Required by the standard. */ + int oldtype = __pthread_enable_asynccancel (); + + err = lll_futex_wait (&isem->value, 0, + isem->private ^ FUTEX_PRIVATE_FLAG); + + /* Disable asynchronous cancellation. */ + __pthread_disable_asynccancel (oldtype); + + if (err != 0 && err != -EWOULDBLOCK) + { + __set_errno (-err); + err = -1; + break; + } + + if (atomic_decrement_if_positive (&isem->value) > 0) + { + err = 0; + break; + } + } + + pthread_cleanup_pop (0); + + atomic_decrement (&isem->nwaiters); + + return err; +} +weak_alias(__new_sem_wait, sem_wait) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/send.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/send.S new file mode 100644 index 00000000..eb744c71 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/send.S @@ -0,0 +1,12 @@ +#include +#ifndef __NR_send +#error Missing definition of NR_send needed for cancellation. +#endif +PSEUDO (__libc_send, send, 4) +ret +PSEUDO_END (__libc_send) +libc_hidden_def (__libc_send) +weak_alias (__libc_send, __send) +libc_hidden_weak (__send) +weak_alias (__libc_send, send) +libc_hidden_weak (send) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sendmsg.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sendmsg.S new file mode 100644 index 00000000..4c41e01c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sendmsg.S @@ -0,0 +1,12 @@ +#include +#ifndef __NR_sendmsg +#error Missing definition of NR_sendmsg needed for cancellation. +#endif +PSEUDO (__libc_sendmsg, sendmsg, 3) +ret +PSEUDO_END(__libc_sendmsg) +libc_hidden_def (__libc_sendmsg) +weak_alias (__libc_sendmsg, __sendmsg) +libc_hidden_weak (__sendmsg) +weak_alias (__libc_sendmsg, sendmsg) +libc_hidden_weak (sendmsg) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sendto.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sendto.S new file mode 100644 index 00000000..7cb5278e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sendto.S @@ -0,0 +1,12 @@ +#include +#ifndef __NR_sendto +#error Missing definition of NR_sendto needed for cancellation. +#endif +PSEUDO (__libc_sendto, sendto, 6) +ret +PSEUDO_END(__libc_sendto) +libc_hidden_def (__libc_sendto) +weak_alias (__libc_sendto, __sendto) +libc_hidden_weak (__sendto) +weak_alias (__libc_sendto, sendto) +libc_hidden_weak (sendto) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/Makefile new file mode 100644 index 00000000..43a6fad8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc NPTL +# +# Copyright (C) 2005 Steven J. Hill +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../../../../../ +top_builddir=../../../../../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.arch +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/Makefile.arch b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/Makefile.arch new file mode 100644 index 00000000..a8249e0f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/Makefile.arch @@ -0,0 +1,46 @@ +# Makefile for uClibc NPTL +# +# Copyright (C) 2006 Steven J. Hill +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +libpthread_linux_arch_SSRC = pt-vfork.S pthread_once.S pthread_rwlock_wrlock.S \ + pthread_rwlock_rdlock.S pthread_rwlock_unlock.S \ + lowlevellock.S lowlevelrobustlock.S pthread_barrier_wait.S \ + pthread_cond_broadcast.S pthread_cond_signal.S \ + pthread_rwlock_timedwrlock.S pthread_rwlock_timedrdlock.S \ + sem_post.S sem_timedwait.S sem_trywait.S sem_wait.S + +libc_linux_arch_CSRC = fork.c +libc_linux_arch_SSRC = libc-lowlevellock.S clone.S vfork.S + +ASFLAGS += -DUSE___THREAD + +ASFLAGS-pt-vfork.S = -DNOT_IN_libc -DIS_IN_libpthread -D_LIBC_REENTRANT +ASFLAGS-pthread_once.S = -D_LIBC_REENTRANT +ASFLAGS-pthread_rwlock_wrlock.S = -D_LIBC_REENTRANT +ASFLAGS-pthread_rwlock_rdlock.S = -D_LIBC_REENTRANT +ASFLAGS-pthread_rwlock_unlock.S = -D_LIBC_REENTRANT +ASFLAGS-pthread_barrier_wait.S = -D_LIBC_REENTRANT +ASFLAGS-pthread_cond_broadcast.S = -D_LIBC_REENTRANT +ASFLAGS-pthread_cond_signal.S = -D_LIBC_REENTRANT +ASFLAGS-pthread_cond_wait.S = -D_LIBC_REENTRANT +ASFLAGS-pthread_cond_timedwait.S = -D_LIBC_REENTRANT +ASFLAGS-pthread_rwlock_timedwrlock.S = -D_LIBC_REENTRANT +ASFLAGS-pthread_rwlock_timedrdlock.S = -D_LIBC_REENTRANT +ASFLAGS-sem_post.S = -D_LIBC_REENTRANT +ASFLAGS-sem_timedwait.S = -D_LIBC_REENTRANT +ASFLAGS-sem_trywait.S = -D_LIBC_REENTRANT +ASFLAGS-sem_wait.S = -D_LIBC_REENTRANT + +ASFLAGS-libc-lowlevellock.S = -D_LIBC_REENTRANT + +ASFLAGS-lowlevellock.S = -DNOT_IN_libc -DIS_IN_libpthread -D_LIBC_REENTRANT +ASFLAGS-lowlevelrobustlock.S = -DNOT_IN_libc -DIS_IN_libpthread -D_LIBC_REENTRANT + +ASFLAGS-clone.S = -D_LIBC_REENTRANT +ASFLAGS-vfork.S = -D_LIBC_REENTRANT +ifeq ($(UCLIBC_HAS_STDIO_FUTEXES),y) +CFLAGS-fork.c = -D__USE_STDIO_FUTEXES__ +endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h new file mode 100644 index 00000000..badcda57 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/bits/pthreadtypes.h @@ -0,0 +1,183 @@ +/* Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _BITS_PTHREADTYPES_H +#define _BITS_PTHREADTYPES_H 1 + +#include + +#define __SIZEOF_PTHREAD_ATTR_T 36 +#define __SIZEOF_PTHREAD_MUTEX_T 24 +#define __SIZEOF_PTHREAD_MUTEXATTR_T 4 +#define __SIZEOF_PTHREAD_COND_T 48 +#define __SIZEOF_PTHREAD_COND_COMPAT_T 12 +#define __SIZEOF_PTHREAD_CONDATTR_T 4 +#define __SIZEOF_PTHREAD_RWLOCK_T 32 +#define __SIZEOF_PTHREAD_RWLOCKATTR_T 8 +#define __SIZEOF_PTHREAD_BARRIER_T 20 +#define __SIZEOF_PTHREAD_BARRIERATTR_T 4 + + +/* Thread identifiers. The structure of the attribute type is not + exposed on purpose. */ +typedef unsigned long int pthread_t; + + +typedef union +{ + char __size[__SIZEOF_PTHREAD_ATTR_T]; + long int __align; +} pthread_attr_t; + + +typedef struct __pthread_internal_slist +{ + struct __pthread_internal_slist *__next; +} __pthread_slist_t; + + +/* Data structures for mutex handling. The structure of the attribute + type is not exposed on purpose. */ +typedef union +{ + struct __pthread_mutex_s + { + int __lock; + unsigned int __count; + int __owner; + /* KIND must stay at this position in the structure to maintain + binary compatibility. */ + int __kind; + unsigned int __nusers; + __extension__ union + { + int __spins; + __pthread_slist_t __list; + }; + } __data; + char __size[__SIZEOF_PTHREAD_MUTEX_T]; + long int __align; +} pthread_mutex_t; + +typedef union +{ + char __size[__SIZEOF_PTHREAD_MUTEXATTR_T]; + long int __align; +} pthread_mutexattr_t; + + +/* Data structure for conditional variable handling. The structure of + the attribute type is not exposed on purpose. */ +typedef union +{ + struct + { + int __lock; + unsigned int __futex; + __extension__ unsigned long long int __total_seq; + __extension__ unsigned long long int __wakeup_seq; + __extension__ unsigned long long int __woken_seq; + void *__mutex; + unsigned int __nwaiters; + unsigned int __broadcast_seq; + } __data; + char __size[__SIZEOF_PTHREAD_COND_T]; + __extension__ long long int __align; +} pthread_cond_t; + +typedef union +{ + char __size[__SIZEOF_PTHREAD_CONDATTR_T]; + long int __align; +} pthread_condattr_t; + + +/* Keys for thread-specific data */ +typedef unsigned int pthread_key_t; + + +/* Once-only execution */ +typedef int pthread_once_t; + + +#if defined __USE_UNIX98 || defined __USE_XOPEN2K +/* Data structure for read-write lock variable handling. The + structure of the attribute type is not exposed on purpose. */ +typedef union +{ + struct + { + int __lock; + unsigned int __nr_readers; + unsigned int __readers_wakeup; + unsigned int __writer_wakeup; + unsigned int __nr_readers_queued; + unsigned int __nr_writers_queued; +#if __BYTE_ORDER == __BIG_ENDIAN + unsigned char __pad1; + unsigned char __pad2; + unsigned char __shared; + /* FLAGS must stay at this position in the structure to maintain + binary compatibility. */ + unsigned char __flags; +#else + /* FLAGS must stay at this position in the structure to maintain + binary compatibility. */ + unsigned char __flags; + unsigned char __shared; + unsigned char __pad1; + unsigned char __pad2; +#endif + pthread_t __writer; + } __data; + char __size[__SIZEOF_PTHREAD_RWLOCK_T]; + long int __align; +} pthread_rwlock_t; + +typedef union +{ + char __size[__SIZEOF_PTHREAD_RWLOCKATTR_T]; + long int __align; +} pthread_rwlockattr_t; +#endif + + +#ifdef __USE_XOPEN2K +/* POSIX spinlock data type. */ +typedef volatile int pthread_spinlock_t; + + +/* POSIX barriers data type. The structure of the type is + deliberately not exposed. */ +typedef union +{ + char __size[__SIZEOF_PTHREAD_BARRIER_T]; + long int __align; +} pthread_barrier_t; + +typedef union +{ + char __size[__SIZEOF_PTHREAD_BARRIERATTR_T]; + int __align; +} pthread_barrierattr_t; +#endif + + +#endif /* bits/pthreadtypes.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/bits/semaphore.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/bits/semaphore.h new file mode 100644 index 00000000..934493c3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/bits/semaphore.h @@ -0,0 +1,36 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SEMAPHORE_H +# error "Never use directly; include instead." +#endif + + +#define __SIZEOF_SEM_T 16 + + +/* Value returned if `sem_open' failed. */ +#define SEM_FAILED ((sem_t *) 0) + + +typedef union +{ + char __size[__SIZEOF_SEM_T]; + long int __align; +} sem_t; diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/clone.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/clone.S new file mode 100644 index 00000000..918d5792 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/clone.S @@ -0,0 +1,2 @@ +#define RESET_PID +#include diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/createthread.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/createthread.c new file mode 100644 index 00000000..e17c0174 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/createthread.c @@ -0,0 +1,24 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Value passed to 'clone' for initialization of the thread register. */ +#define TLS_VALUE (pd + 1) + + +/* Get the real implementation. */ +#include diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/fork.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/fork.c new file mode 100644 index 00000000..6868b9bc --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/fork.c @@ -0,0 +1,30 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + +/* TLS pointer argument is passed as the 5-th argument. */ +#define ARCH_FORK() \ + INLINE_SYSCALL (clone, 5, \ + CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | SIGCHLD, 0, \ + NULL, &THREAD_SELF->tid, NULL) + +#include "../fork.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/libc-lowlevellock.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/libc-lowlevellock.S new file mode 100644 index 00000000..feb82110 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/libc-lowlevellock.S @@ -0,0 +1,19 @@ +/* Copyright (C) 2003, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "lowlevellock.S" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/lowlevel-atomic.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/lowlevel-atomic.h new file mode 100644 index 00000000..c7028360 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/lowlevel-atomic.h @@ -0,0 +1,81 @@ +/* Copyright (C) 2003, 2004, 2008 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifdef __ASSEMBLER__ + +#define _IMP1 #1 +#define _IMM1 #-1 +#define _IMM4 #-4 +#define _IMM6 #-6 +#define _IMM8 #-8 + +#define INC(mem, reg) \ + .align 2; \ + mova 99f, r0; \ + mov r15, r1; \ + mov _IMM6, r15; \ +98: mov.l mem, reg; \ + add _IMP1, reg; \ + mov.l reg, mem; \ +99: mov r1, r15 + +#define DEC(mem, reg) \ + .align 2; \ + mova 99f, r0; \ + mov r15, r1; \ + mov _IMM6, r15; \ +98: mov.l mem, reg; \ + add _IMM1, reg; \ + mov.l reg, mem; \ +99: mov r1, r15 + +#define XADD(reg, mem, old, tmp) \ + .align 2; \ + mova 99f, r0; \ + nop; \ + mov r15, r1; \ + mov _IMM8, r15; \ +98: mov.l mem, old; \ + mov reg, tmp; \ + add old, tmp; \ + mov.l tmp, mem; \ +99: mov r1, r15 + +#define XCHG(reg, mem, old) \ + .align 2; \ + mova 99f, r0; \ + nop; \ + mov r15, r1; \ + mov _IMM4, r15; \ +98: mov.l mem, old; \ + mov.l reg, mem; \ +99: mov r1, r15 + +#define CMPXCHG(reg, mem, new, old) \ + .align 2; \ + mova 99f, r0; \ + nop; \ + mov r15, r1; \ + mov _IMM8, r15; \ +98: mov.l mem, old; \ + cmp/eq old, reg; \ + bf 99f; \ + mov.l new, mem; \ +99: mov r1, r15 + +#endif /* __ASSEMBLER__ */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/lowlevellock.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/lowlevellock.S new file mode 100644 index 00000000..00edc75a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/lowlevellock.S @@ -0,0 +1,540 @@ +/* Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include "lowlevel-atomic.h" + + .text + +#ifdef __ASSUME_PRIVATE_FUTEX +# define LOAD_PRIVATE_FUTEX_WAIT(reg,tmp,tmp2) \ + mov #(FUTEX_WAIT | FUTEX_PRIVATE_FLAG), reg; \ + extu.b reg, reg +# define LOAD_PRIVATE_FUTEX_WAKE(reg,tmp,tmp2) \ + mov #(FUTEX_WAKE | FUTEX_PRIVATE_FLAG), reg; \ + extu.b reg, reg +# define LOAD_FUTEX_WAIT(reg,tmp,tmp2) \ + mov #(FUTEX_WAIT | FUTEX_PRIVATE_FLAG), tmp; \ + extu.b tmp, tmp; \ + xor tmp, reg +# define LOAD_FUTEX_WAIT_ABS(reg,tmp,tmp2) \ + mov #(FUTEX_WAIT_BITSET | FUTEX_PRIVATE_FLAG), tmp; \ + extu.b tmp, tmp; \ + mov #(FUTEX_CLOCK_REALTIME >> 8), tmp2; \ + swap.b tmp2, tmp2; \ + or tmp2, tmp; \ + xor tmp, reg +# define LOAD_FUTEX_WAKE(reg,tmp,tmp2) \ + mov #(FUTEX_WAKE | FUTEX_PRIVATE_FLAG), tmp; \ + extu.b tmp, tmp; \ + xor tmp, reg +#else +# if FUTEX_WAIT == 0 +# define LOAD_PRIVATE_FUTEX_WAIT(reg,tmp,tmp2) \ + stc gbr, tmp ; \ + mov.w 99f, reg ; \ + add reg, tmp ; \ + bra 98f ; \ + mov.l @tmp, reg ; \ +99: .word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE ; \ +98: +# else +# define LOAD_PRIVATE_FUTEX_WAIT(reg,tmp,tmp2) \ + stc gbr, tmp ; \ + mov.w 99f, reg ; \ + add reg, tmp ; \ + mov.l @tmp, reg ; \ + bra 98f ; \ + mov #FUTEX_WAIT, tmp ; \ +99: .word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE ; \ +98: or tmp, reg +# endif +# define LOAD_PRIVATE_FUTEX_WAKE(reg,tmp,tmp2) \ + stc gbr, tmp ; \ + mov.w 99f, reg ; \ + add reg, tmp ; \ + mov.l @tmp, reg ; \ + bra 98f ; \ + mov #FUTEX_WAKE, tmp ; \ +99: .word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE ; \ +98: or tmp, reg +# if FUTEX_WAIT == 0 +# define LOAD_FUTEX_WAIT(reg,tmp,tmp2) \ + stc gbr, tmp ; \ + mov.w 99f, tmp2 ; \ + add tmp2, tmp ; \ + mov.l @tmp, tmp2 ; \ + bra 98f ; \ + mov #FUTEX_PRIVATE_FLAG, tmp ; \ +99: .word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE ; \ +98: extu.b tmp, tmp ; \ + xor tmp, reg ; \ + and tmp2, reg +# else +# define LOAD_FUTEX_WAIT(reg,tmp,tmp2) \ + stc gbr, tmp ; \ + mov.w 99f, tmp2 ; \ + add tmp2, tmp ; \ + mov.l @tmp, tmp2 ; \ + bra 98f ; \ + mov #FUTEX_PRIVATE_FLAG, tmp ; \ +99: .word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE ; \ +98: extu.b tmp, tmp ; \ + xor tmp, reg ; \ + and tmp2, reg ; \ + mov #FUTEX_WAIT, tmp ; \ + or tmp, reg +# endif +# define LOAD_FUTEX_WAIT_ABS(reg,tmp,tmp2) \ + stc gbr, tmp ; \ + mov.w 99f, tmp2 ; \ + add tmp2, tmp ; \ + mov.l @tmp, tmp2 ; \ + bra 98f ; \ + mov #FUTEX_PRIVATE_FLAG, tmp ; \ +99: .word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE ; \ +98: extu.b tmp, tmp ; \ + xor tmp, reg ; \ + and tmp2, reg ; \ + mov #FUTEX_WAIT_BITSET, tmp ; \ + mov #(FUTEX_CLOCK_REALTIME >> 8), tmp2; \ + swap.b tmp2, tmp2; \ + or tmp2, tmp; \ + or tmp, reg +# define LOAD_FUTEX_WAKE(reg,tmp,tmp2) \ + stc gbr, tmp ; \ + mov.w 99f, tmp2 ; \ + add tmp2, tmp ; \ + mov.l @tmp, tmp2 ; \ + bra 98f ; \ + mov #FUTEX_PRIVATE_FLAG, tmp ; \ +99: .word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE ; \ +98: extu.b tmp, tmp ; \ + xor tmp, reg ; \ + and tmp2, reg ; \ + mov #FUTEX_WAKE, tmp ; \ + or tmp, reg +#endif + + .globl __lll_lock_wait_private + .type __lll_lock_wait_private,@function + .hidden __lll_lock_wait_private + .align 5 + cfi_startproc +__lll_lock_wait_private: + mov.l r8, @-r15 + cfi_adjust_cfa_offset(4) + cfi_rel_offset (r8, 0) + mov r4, r6 + mov r5, r8 + mov #0, r7 /* No timeout. */ + LOAD_PRIVATE_FUTEX_WAIT (r5, r0, r1) + + mov #2, r4 + cmp/eq r4, r6 + bf 2f + +1: + mov r8, r4 + mov #SYS_futex, r3 + extu.b r3, r3 + trapa #0x14 + SYSCALL_INST_PAD + +2: + mov #2, r6 + XCHG (r6, @r8, r2) + tst r2, r2 + bf 1b + + mov.l @r15+, r8 + rts + mov r2, r0 + cfi_endproc + .size __lll_lock_wait_private,.-__lll_lock_wait_private + +#ifdef NOT_IN_libc + .globl __lll_lock_wait + .type __lll_lock_wait,@function + .hidden __lll_lock_wait + .align 5 + cfi_startproc +__lll_lock_wait: + mov.l r9, @-r15 + cfi_adjust_cfa_offset(4) + cfi_rel_offset (r9, 0) + mov.l r8, @-r15 + cfi_adjust_cfa_offset(4) + cfi_rel_offset (r8, 0) + mov r6, r9 + mov r4, r6 + mov r5, r8 + mov #0, r7 /* No timeout. */ + mov r9, r5 + LOAD_FUTEX_WAIT (r5, r0, r1) + + mov #2, r4 + cmp/eq r4, r6 + bf 2f + +1: + mov r8, r4 + mov #SYS_futex, r3 + extu.b r3, r3 + trapa #0x14 + SYSCALL_INST_PAD + +2: + mov #2, r6 + XCHG (r6, @r8, r2) + tst r2, r2 + bf 1b + + mov.l @r15+, r8 + mov.l @r15+, r9 + ret + mov r2, r0 + cfi_endproc + .size __lll_lock_wait,.-__lll_lock_wait + + /* r5 (r8): futex + r7 (r11): flags + r6 (r9): timeout + r4 (r10): futex value + */ + .globl __lll_timedlock_wait + .type __lll_timedlock_wait,@function + .hidden __lll_timedlock_wait + .align 5 + cfi_startproc +__lll_timedlock_wait: + mov.l r12, @-r15 + cfi_adjust_cfa_offset(4) + cfi_rel_offset (r12, 0) + +# ifndef __ASSUME_FUTEX_CLOCK_REALTIME + mov.l .Lhave, r1 +# ifdef __PIC__ + mova .Lgot, r0 + mov.l .Lgot, r12 + add r0, r12 + add r12, r1 +# endif + mov.l @r1, r0 + tst r0, r0 + bt .Lreltmo +# endif + + mov r4, r2 + mov r5, r4 + mov r7, r5 + mov r6, r7 + LOAD_FUTEX_WAIT_ABS (r5, r0, r1) + + mov #2, r6 + cmp/eq r6, r2 + bf/s 2f + mov r6, r2 + +1: + mov #2, r6 + mov #-1, r1 + mov #SYS_futex, r3 + extu.b r3, r3 + trapa #0x16 + SYSCALL_INST_PAD + mov r0, r6 + +2: + XCHG (r2, @r4, r3) /* NB: lock is implied */ + + tst r3, r3 + bt/s 3f + mov r6, r0 + + cmp/eq #-ETIMEDOUT, r0 + bt 4f + cmp/eq #-EINVAL, r0 + bf 1b +4: + neg r0, r3 +3: + mov r3, r0 + rts + mov.l @r15+, r12 + + .align 2 +# ifndef __ASSUME_FUTEX_CLOCK_REALTIME +# ifdef __PIC__ +.Lgot: + .long _GLOBAL_OFFSET_TABLE_ +.Lhave: + .long __have_futex_clock_realtime@GOTOFF +# else +.Lhave: + .long __have_futex_clock_realtime +# endif + +.Lreltmo: + /* Check for a valid timeout value. */ + mov.l @(4,r6), r1 + mov.l .L1g, r0 + cmp/hs r0, r1 + bt 3f + + mov.l r11, @-r15 + cfi_adjust_cfa_offset(4) + cfi_rel_offset (r11, 0) + mov.l r10, @-r15 + cfi_adjust_cfa_offset(4) + cfi_rel_offset (r10, 0) + mov.l r9, @-r15 + cfi_adjust_cfa_offset(4) + cfi_rel_offset (r9, 0) + mov.l r8, @-r15 + cfi_adjust_cfa_offset(4) + cfi_rel_offset (r8, 0) + mov r7, r11 + mov r4, r10 + mov r6, r9 + mov r5, r8 + + /* Stack frame for the timespec and timeval structs. */ + add #-8, r15 + cfi_adjust_cfa_offset(8) + + mov #2, r2 + XCHG (r2, @r8, r3) + + tst r3, r3 + bt 6f + +1: + /* Get current time. */ + mov r15, r4 + mov #0, r5 + mov #__NR_gettimeofday, r3 + trapa #0x12 + SYSCALL_INST_PAD + + /* Compute relative timeout. */ + mov.l @(4,r15), r0 + mov.w .L1k, r1 + dmulu.l r0, r1 /* Micro seconds to nano seconds. */ + mov.l @r9, r2 + mov.l @(4,r9), r3 + mov.l @r15, r0 + sts macl, r1 + sub r0, r2 + clrt + subc r1, r3 + bf 4f + mov.l .L1g, r1 + add r1, r3 + add #-1, r2 +4: + cmp/pz r2 + bf 2f /* Time is already up. */ + + mov.l r2, @r15 /* Store relative timeout. */ + mov.l r3, @(4,r15) + + mov r8, r4 + mov r11, r5 + LOAD_FUTEX_WAIT (r5, r0, r1) + mov r10, r6 + mov r15, r7 + mov #SYS_futex, r3 + extu.b r3, r3 + trapa #0x14 + SYSCALL_INST_PAD + mov r0, r5 + + mov #2, r2 + XCHG (r2, @r8, r3) + + tst r3, r3 + bt/s 6f + mov #-ETIMEDOUT, r1 + cmp/eq r5, r1 + bf 1b + +2: mov #ETIMEDOUT, r3 + +6: + mov r3, r0 + add #8, r15 + mov.l @r15+, r8 + mov.l @r15+, r9 + mov.l @r15+, r10 + mov.l @r15+, r11 + rts + mov.l @r15+, r12 + +3: + mov.l @r15+, r12 + rts + mov #EINVAL, r0 +# endif + cfi_endproc + +.L1k: + .word 1000 + .align 2 +.L1g: + .long 1000000000 + + .size __lll_timedlock_wait,.-__lll_timedlock_wait +#endif + + .globl __lll_unlock_wake_private + .type __lll_unlock_wake_private,@function + .hidden __lll_unlock_wake_private + .align 5 + cfi_startproc +__lll_unlock_wake_private: + LOAD_PRIVATE_FUTEX_WAKE (r5, r0, r1) + mov #1, r6 /* Wake one thread. */ + mov #0, r7 + mov.l r7, @r4 /* Stores 0. */ + mov #SYS_futex, r3 + extu.b r3, r3 + trapa #0x14 + SYSCALL_INST_PAD + rts + nop + cfi_endproc + .size __lll_unlock_wake_private,.-__lll_unlock_wake_private + +#ifdef NOT_IN_libc + .globl __lll_unlock_wake + .type __lll_unlock_wake,@function + .hidden __lll_unlock_wake + .align 5 + cfi_startproc +__lll_unlock_wake: + LOAD_FUTEX_WAKE (r5, r0, r1) + mov #1, r6 /* Wake one thread. */ + mov #0, r7 + mov.l r7, @r4 /* Stores 0. */ + mov #SYS_futex, r3 + extu.b r3, r3 + trapa #0x14 + SYSCALL_INST_PAD + rts + nop + cfi_endproc + .size __lll_unlock_wake,.-__lll_unlock_wake + + .globl __lll_timedwait_tid + .type __lll_timedwait_tid,@function + .hidden __lll_timedwait_tid + .align 5 + cfi_startproc +__lll_timedwait_tid: + mov.l r9, @-r15 + cfi_adjust_cfa_offset(4) + cfi_rel_offset (r9, 0) + mov.l r8, @-r15 + cfi_adjust_cfa_offset(4) + cfi_rel_offset (r8, 0) + mov r4, r8 + mov r5, r9 + + /* Stack frame for the timespec and timeval structs. */ + add #-8, r15 + cfi_adjust_cfa_offset(8) + +2: + /* Get current time. */ + mov r15, r4 + mov #0, r5 + mov #__NR_gettimeofday, r3 + trapa #0x12 + SYSCALL_INST_PAD + + /* Compute relative timeout. */ + mov.l @(4,r15), r0 + mov.w .L1k2, r1 + dmulu.l r0, r1 /* Micro seconds to nano seconds. */ + mov.l @r9, r2 + mov.l @(4,r9), r3 + mov.l @r15, r0 + sts macl, r1 + sub r0, r2 + clrt + subc r1, r3 + bf 5f + mov.l .L1g2, r1 + add r1, r3 + add #-1, r2 +5: + cmp/pz r2 + bf 6f /* Time is already up. */ + + mov.l r2, @r15 /* Store relative timeout. */ + mov.l r3, @(4,r15) + + mov.l @r8, r2 + tst r2, r2 + bt 4f + + mov r8, r4 + /* XXX The kernel so far uses global futex for the wakeup at + all times. */ + mov #0, r5 + extu.b r5, r5 + mov r2, r6 + mov r15, r7 + mov #SYS_futex, r3 + extu.b r3, r3 + trapa #0x14 + SYSCALL_INST_PAD + + mov.l @r8, r2 + tst r2, r2 + bf 1f +4: + mov #0, r0 +3: + add #8, r15 + mov.l @r15+, r8 + rts + mov.l @r15+, r9 +1: + /* Check whether the time expired. */ + mov #-ETIMEDOUT, r1 + cmp/eq r0, r1 + bf 2b +6: + bra 3b + mov #ETIMEDOUT, r0 + cfi_endproc + +.L1k2: + .word 1000 + .align 2 +.L1g2: + .long 1000000000 + .size __lll_timedwait_tid,.-__lll_timedwait_tid +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/lowlevellock.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/lowlevellock.h new file mode 100644 index 00000000..0ea67e0e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/lowlevellock.h @@ -0,0 +1,420 @@ +/* Copyright (C) 2003, 2004, 2006, 2007, 2008, 2009 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _LOWLEVELLOCK_H +#define _LOWLEVELLOCK_H 1 + +#ifndef __ASSEMBLER__ +#include +#include +#include +#include +#endif + +#define FUTEX_WAIT 0 +#define FUTEX_WAKE 1 +#define FUTEX_CMP_REQUEUE 4 +#define FUTEX_WAKE_OP 5 +#define FUTEX_LOCK_PI 6 +#define FUTEX_UNLOCK_PI 7 +#define FUTEX_TRYLOCK_PI 8 +#define FUTEX_WAIT_BITSET 9 +#define FUTEX_WAKE_BITSET 10 +#define FUTEX_PRIVATE_FLAG 128 +#define FUTEX_CLOCK_REALTIME 256 + +#define FUTEX_BITSET_MATCH_ANY 0xffffffff + +#define FUTEX_OP_CLEAR_WAKE_IF_GT_ONE ((4 << 24) | 1) + +/* Values for 'private' parameter of locking macros. Yes, the + definition seems to be backwards. But it is not. The bit will be + reversed before passing to the system call. */ +#define LLL_PRIVATE 0 +#define LLL_SHARED FUTEX_PRIVATE_FLAG + + +#if !defined NOT_IN_libc || defined IS_IN_rtld +/* In libc.so or ld.so all futexes are private. */ +# ifdef __ASSUME_PRIVATE_FUTEX +# define __lll_private_flag(fl, private) \ + ((fl) | FUTEX_PRIVATE_FLAG) +# else +# define __lll_private_flag(fl, private) \ + ((fl) | THREAD_GETMEM (THREAD_SELF, header.private_futex)) +# endif +#else +# ifdef __ASSUME_PRIVATE_FUTEX +# define __lll_private_flag(fl, private) \ + (((fl) | FUTEX_PRIVATE_FLAG) ^ (private)) +# else +# define __lll_private_flag(fl, private) \ + (__builtin_constant_p (private) \ + ? ((private) == 0 \ + ? ((fl) | THREAD_GETMEM (THREAD_SELF, header.private_futex)) \ + : (fl)) \ + : ((fl) | (((private) ^ FUTEX_PRIVATE_FLAG) \ + & THREAD_GETMEM (THREAD_SELF, header.private_futex)))) +# endif +#endif + +#ifndef __ASSEMBLER__ + +/* Initializer for compatibility lock. */ +#define LLL_LOCK_INITIALIZER (0) +#define LLL_LOCK_INITIALIZER_LOCKED (1) +#define LLL_LOCK_INITIALIZER_WAITERS (2) + +extern int __lll_lock_wait_private (int val, int *__futex) + attribute_hidden; +extern int __lll_lock_wait (int val, int *__futex, int private) + attribute_hidden; +extern int __lll_timedlock_wait (int val, int *__futex, + const struct timespec *abstime, int private) + attribute_hidden; +extern int __lll_robust_lock_wait (int val, int *__futex, int private) + attribute_hidden; +extern int __lll_robust_timedlock_wait (int val, int *__futex, + const struct timespec *abstime, + int private) + attribute_hidden; +extern int __lll_unlock_wake_private (int *__futex) attribute_hidden; +extern int __lll_unlock_wake (int *__futex, int private) attribute_hidden; + +#define lll_trylock(futex) \ + ({ unsigned char __result; \ + __asm__ __volatile__ ("\ + .align 2\n\ + mova 1f,r0\n\ + nop\n\ + mov r15,r1\n\ + mov #-8,r15\n\ + 0: mov.l @%1,r2\n\ + cmp/eq r2,%3\n\ + bf 1f\n\ + mov.l %2,@%1\n\ + 1: mov r1,r15\n\ + mov #-1,%0\n\ + negc %0,%0"\ + : "=r" (__result) \ + : "r" (&(futex)), \ + "r" (LLL_LOCK_INITIALIZER_LOCKED), \ + "r" (LLL_LOCK_INITIALIZER) \ + : "r0", "r1", "r2", "t", "memory"); \ + __result; }) + +#define lll_robust_trylock(futex, id) \ + ({ unsigned char __result; \ + __asm__ __volatile__ ("\ + .align 2\n\ + mova 1f,r0\n\ + nop\n\ + mov r15,r1\n\ + mov #-8,r15\n\ + 0: mov.l @%1,r2\n\ + cmp/eq r2,%3\n\ + bf 1f\n\ + mov.l %2,@%1\n\ + 1: mov r1,r15\n\ + mov #-1,%0\n\ + negc %0,%0"\ + : "=r" (__result) \ + : "r" (&(futex)), \ + "r" (id), \ + "r" (LLL_LOCK_INITIALIZER) \ + : "r0", "r1", "r2", "t", "memory"); \ + __result; }) + +#define lll_cond_trylock(futex) \ + ({ unsigned char __result; \ + __asm__ __volatile__ ("\ + .align 2\n\ + mova 1f,r0\n\ + nop\n\ + mov r15,r1\n\ + mov #-8,r15\n\ + 0: mov.l @%1,r2\n\ + cmp/eq r2,%3\n\ + bf 1f\n\ + mov.l %2,@%1\n\ + 1: mov r1,r15\n\ + mov #-1,%0\n\ + negc %0,%0"\ + : "=r" (__result) \ + : "r" (&(futex)), \ + "r" (LLL_LOCK_INITIALIZER_WAITERS), \ + "r" (LLL_LOCK_INITIALIZER) \ + : "r0", "r1", "r2", "t", "memory"); \ + __result; }) + +#define lll_lock(futex, private) \ + (void) ({ int __result, *__futex = &(futex); \ + __asm__ __volatile__ ("\ + .align 2\n\ + mova 1f,r0\n\ + nop\n\ + mov r15,r1\n\ + mov #-8,r15\n\ + 0: mov.l @%2,%0\n\ + tst %0,%0\n\ + bf 1f\n\ + mov.l %1,@%2\n\ + 1: mov r1,r15"\ + : "=&r" (__result) : "r" (1), "r" (__futex) \ + : "r0", "r1", "t", "memory"); \ + if (__result) \ + { \ + if (__builtin_constant_p (private) \ + && (private) == LLL_PRIVATE) \ + __lll_lock_wait_private (__result, __futex); \ + else \ + __lll_lock_wait (__result, __futex, (private)); \ + } \ + }) + +#define lll_robust_lock(futex, id, private) \ + ({ int __result, *__futex = &(futex); \ + __asm__ __volatile__ ("\ + .align 2\n\ + mova 1f,r0\n\ + nop\n\ + mov r15,r1\n\ + mov #-8,r15\n\ + 0: mov.l @%2,%0\n\ + tst %0,%0\n\ + bf 1f\n\ + mov.l %1,@%2\n\ + 1: mov r1,r15"\ + : "=&r" (__result) : "r" (id), "r" (__futex) \ + : "r0", "r1", "t", "memory"); \ + if (__result) \ + __result = __lll_robust_lock_wait (__result, __futex, private); \ + __result; }) + +/* Special version of lll_mutex_lock which causes the unlock function to + always wakeup waiters. */ +#define lll_cond_lock(futex, private) \ + (void) ({ int __result, *__futex = &(futex); \ + __asm__ __volatile__ ("\ + .align 2\n\ + mova 1f,r0\n\ + nop\n\ + mov r15,r1\n\ + mov #-8,r15\n\ + 0: mov.l @%2,%0\n\ + tst %0,%0\n\ + bf 1f\n\ + mov.l %1,@%2\n\ + 1: mov r1,r15"\ + : "=&r" (__result) : "r" (2), "r" (__futex) \ + : "r0", "r1", "t", "memory"); \ + if (__result) \ + __lll_lock_wait (__result, __futex, private); }) + +#define lll_robust_cond_lock(futex, id, private) \ + ({ int __result, *__futex = &(futex); \ + __asm__ __volatile__ ("\ + .align 2\n\ + mova 1f,r0\n\ + nop\n\ + mov r15,r1\n\ + mov #-8,r15\n\ + 0: mov.l @%2,%0\n\ + tst %0,%0\n\ + bf 1f\n\ + mov.l %1,@%2\n\ + 1: mov r1,r15"\ + : "=&r" (__result) : "r" (id | FUTEX_WAITERS), "r" (__futex) \ + : "r0", "r1", "t", "memory"); \ + if (__result) \ + __result = __lll_robust_lock_wait (__result, __futex, private); \ + __result; }) + +#define lll_timedlock(futex, timeout, private) \ + ({ int __result, *__futex = &(futex); \ + __asm__ __volatile__ ("\ + .align 2\n\ + mova 1f,r0\n\ + nop\n\ + mov r15,r1\n\ + mov #-8,r15\n\ + 0: mov.l @%2,%0\n\ + tst %0,%0\n\ + bf 1f\n\ + mov.l %1,@%2\n\ + 1: mov r1,r15"\ + : "=&r" (__result) : "r" (1), "r" (__futex) \ + : "r0", "r1", "t", "memory"); \ + if (__result) \ + __result = __lll_timedlock_wait (__result, __futex, timeout, private); \ + __result; }) + +#define lll_robust_timedlock(futex, timeout, id, private) \ + ({ int __result, *__futex = &(futex); \ + __asm__ __volatile__ ("\ + .align 2\n\ + mova 1f,r0\n\ + nop\n\ + mov r15,r1\n\ + mov #-8,r15\n\ + 0: mov.l @%2,%0\n\ + tst %0,%0\n\ + bf 1f\n\ + mov.l %1,@%2\n\ + 1: mov r1,r15"\ + : "=&r" (__result) : "r" (id), "r" (__futex) \ + : "r0", "r1", "t", "memory"); \ + if (__result) \ + __result = __lll_robust_timedlock_wait (__result, __futex, \ + timeout, private); \ + __result; }) + +#define lll_unlock(futex, private) \ + (void) ({ int __result, *__futex = &(futex); \ + __asm__ __volatile__ ("\ + .align 2\n\ + mova 1f,r0\n\ + mov r15,r1\n\ + mov #-6,r15\n\ + 0: mov.l @%1,%0\n\ + add #-1,%0\n\ + mov.l %0,@%1\n\ + 1: mov r1,r15"\ + : "=&r" (__result) : "r" (__futex) \ + : "r0", "r1", "memory"); \ + if (__result) \ + { \ + if (__builtin_constant_p (private) \ + && (private) == LLL_PRIVATE) \ + __lll_unlock_wake_private (__futex); \ + else \ + __lll_unlock_wake (__futex, (private)); \ + } \ + }) + +#define lll_robust_unlock(futex, private) \ + (void) ({ int __result, *__futex = &(futex); \ + __asm__ __volatile__ ("\ + .align 2\n\ + mova 1f,r0\n\ + mov r15,r1\n\ + mov #-6,r15\n\ + 0: mov.l @%1,%0\n\ + and %2,%0\n\ + mov.l %0,@%1\n\ + 1: mov r1,r15"\ + : "=&r" (__result) : "r" (__futex), "r" (FUTEX_WAITERS) \ + : "r0", "r1", "memory"); \ + if (__result) \ + __lll_unlock_wake (__futex, private); }) + +#define lll_robust_dead(futex, private) \ + (void) ({ int __ignore, *__futex = &(futex); \ + __asm__ __volatile__ ("\ + .align 2\n\ + mova 1f,r0\n\ + mov r15,r1\n\ + mov #-6,r15\n\ + 0: mov.l @%1,%0\n\ + or %2,%0\n\ + mov.l %0,@%1\n\ + 1: mov r1,r15"\ + : "=&r" (__ignore) : "r" (__futex), "r" (FUTEX_OWNER_DIED) \ + : "r0", "r1", "memory"); \ + lll_futex_wake (__futex, 1, private); }) + +# ifdef NEED_SYSCALL_INST_PAD +# define SYSCALL_WITH_INST_PAD "\ + trapa #0x14; or r0,r0; or r0,r0; or r0,r0; or r0,r0; or r0,r0" +# else +# define SYSCALL_WITH_INST_PAD "\ + trapa #0x14" +# endif + +#define lll_futex_wait(futex, val, private) \ + lll_futex_timed_wait (futex, val, NULL, private) + + +#define lll_futex_timed_wait(futex, val, timeout, private) \ + ({ \ + int __status; \ + register unsigned long __r3 __asm__ ("r3") = SYS_futex; \ + register unsigned long __r4 __asm__ ("r4") = (unsigned long) (futex); \ + register unsigned long __r5 __asm__ ("r5") \ + = __lll_private_flag (FUTEX_WAIT, private); \ + register unsigned long __r6 __asm__ ("r6") = (unsigned long) (val); \ + register unsigned long __r7 __asm__ ("r7") = (timeout); \ + __asm__ __volatile__ (SYSCALL_WITH_INST_PAD \ + : "=z" (__status) \ + : "r" (__r3), "r" (__r4), "r" (__r5), \ + "r" (__r6), "r" (__r7) \ + : "memory", "t"); \ + __status; \ + }) + + +#define lll_futex_wake(futex, nr, private) \ + do { \ + int __ignore; \ + register unsigned long __r3 __asm__ ("r3") = SYS_futex; \ + register unsigned long __r4 __asm__ ("r4") = (unsigned long) (futex); \ + register unsigned long __r5 __asm__ ("r5") \ + = __lll_private_flag (FUTEX_WAKE, private); \ + register unsigned long __r6 __asm__ ("r6") = (unsigned long) (nr); \ + register unsigned long __r7 __asm__ ("r7") = 0; \ + __asm__ __volatile__ (SYSCALL_WITH_INST_PAD \ + : "=z" (__ignore) \ + : "r" (__r3), "r" (__r4), "r" (__r5), \ + "r" (__r6), "r" (__r7) \ + : "memory", "t"); \ + } while (0) + + +#define lll_islocked(futex) \ + (futex != LLL_LOCK_INITIALIZER) + +/* The kernel notifies a process with uses CLONE_CLEARTID via futex + wakeup when the clone terminates. The memory location contains the + thread ID while the clone is running and is reset to zero + afterwards. */ + +#define lll_wait_tid(tid) \ + do { \ + __typeof (tid) *__tid = &(tid); \ + while (*__tid != 0) \ + lll_futex_wait (__tid, *__tid, LLL_SHARED); \ + } while (0) + +extern int __lll_timedwait_tid (int *tid, const struct timespec *abstime) + attribute_hidden; +#define lll_timedwait_tid(tid, abstime) \ + ({ \ + int __result = 0; \ + if (tid != 0) \ + { \ + if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) \ + __result = EINVAL; \ + else \ + __result = __lll_timedwait_tid (&tid, abstime); \ + } \ + __result; }) + +#endif /* !__ASSEMBLER__ */ + +#endif /* lowlevellock.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/lowlevelrobustlock.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/lowlevelrobustlock.S new file mode 100644 index 00000000..1e05a56c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/lowlevelrobustlock.S @@ -0,0 +1,265 @@ +/* Copyright (C) 2003, 2004, 2005, 2006, 2007 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include +#include "lowlevel-atomic.h" + + .text + +#define FUTEX_WAITERS 0x80000000 +#define FUTEX_OWNER_DIED 0x40000000 + +#ifdef __ASSUME_PRIVATE_FUTEX +# define LOAD_FUTEX_WAIT(reg,tmp,tmp2) \ + mov #(FUTEX_WAIT | FUTEX_PRIVATE_FLAG), tmp; \ + extu.b tmp, tmp; \ + xor tmp, reg +#else +# if FUTEX_WAIT == 0 +# define LOAD_FUTEX_WAIT(reg,tmp,tmp2) \ + stc gbr, tmp ; \ + mov.w 99f, tmp2 ; \ + add tmp2, tmp ; \ + mov.l @tmp, tmp2 ; \ + bra 98f ; \ + mov #FUTEX_PRIVATE_FLAG, tmp ; \ +99: .word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE ; \ +98: extu.b tmp, tmp ; \ + xor tmp, reg ; \ + and tmp2, reg +# else +# define LOAD_FUTEX_WAIT(reg,tmp,tmp2) \ + stc gbr, tmp ; \ + mov.w 99f, tmp2 ; \ + add tmp2, tmp ; \ + mov.l @tmp, tmp2 ; \ + bra 98f ; \ + mov #FUTEX_PRIVATE_FLAG, tmp ; \ +99: .word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE ; \ +98: extu.b tmp, tmp ; \ + xor tmp, reg ; \ + and tmp2, reg ; \ + mov #FUTEX_WAIT, tmp ; \ + or tmp, reg +# endif +#endif + + .globl __lll_robust_lock_wait + .type __lll_robust_lock_wait,@function + .hidden __lll_robust_lock_wait + .align 5 + cfi_startproc +__lll_robust_lock_wait: + mov.l r8, @-r15 + cfi_adjust_cfa_offset(4) + cfi_rel_offset (r8, 0) + mov r5, r8 + mov #0, r7 /* No timeout. */ + mov r6, r5 + LOAD_FUTEX_WAIT (r5, r0, r1) + +4: + mov r4, r6 + mov.l .L_FUTEX_WAITERS, r0 + or r0, r6 + shlr r0 /* r0 = FUTEX_OWNER_DIED */ + tst r0, r4 + bf/s 3f + cmp/eq r4, r6 + bt 1f + + CMPXCHG (r4, @r8, r6, r2) + bf 2f + +1: + mov r8, r4 + mov #SYS_futex, r3 + extu.b r3, r3 + trapa #0x14 + SYSCALL_INST_PAD + + mov.l @r8, r2 + +2: + tst r2, r2 + bf/s 4b + mov r2, r4 + + stc gbr, r1 + mov.w .Ltidoff, r2 + add r2, r1 + mov.l @r1, r6 + mov #0, r3 + CMPXCHG (r3, @r8, r6, r4) + bf 4b + mov #0, r4 + +3: + mov.l @r15+, r8 + ret + mov r4, r0 + cfi_endproc + .align 2 +.L_FUTEX_WAITERS: + .long FUTEX_WAITERS +.Ltidoff: + .word TID - TLS_PRE_TCB_SIZE + .size __lll_robust_lock_wait,.-__lll_robust_lock_wait + + + .globl __lll_robust_timedlock_wait + .type __lll_robust_timedlock_wait,@function + .hidden __lll_robust_timedlock_wait + .align 5 + cfi_startproc +__lll_robust_timedlock_wait: + /* Check for a valid timeout value. */ + mov.l @(4,r6), r1 + mov.l .L1g, r0 + cmp/hs r0, r1 + bt 3f + + mov.l r11, @-r15 + cfi_adjust_cfa_offset(4) + cfi_rel_offset (r11, 0) + mov.l r10, @-r15 + cfi_adjust_cfa_offset(4) + cfi_rel_offset (r10, 0) + mov.l r9, @-r15 + cfi_adjust_cfa_offset(4) + cfi_rel_offset (r9, 0) + mov.l r8, @-r15 + cfi_adjust_cfa_offset(4) + cfi_rel_offset (r8, 0) + mov r7, r11 + mov r4, r10 + mov r6, r9 + mov r5, r8 + + /* Stack frame for the timespec and timeval structs. */ + add #-8, r15 + cfi_adjust_cfa_offset(8) + +1: + /* Get current time. */ + mov r15, r4 + mov #0, r5 + mov #__NR_gettimeofday, r3 + trapa #0x12 + SYSCALL_INST_PAD + + /* Compute relative timeout. */ + mov.l @(4,r15), r0 + mov.w .L1k, r1 + dmulu.l r0, r1 /* Micro seconds to nano seconds. */ + mov.l @r9, r2 + mov.l @(4,r9), r3 + mov.l @r15, r0 + sts macl, r1 + sub r0, r2 + clrt + subc r1, r3 + bf 4f + mov.l .L1g, r1 + add r1, r3 + add #-1, r2 +4: + cmp/pz r2 + bf 8f /* Time is already up. */ + + mov.l r2, @r15 /* Store relative timeout. */ + mov.l r3, @(4,r15) + + mov r10, r6 + mov.l .L_FUTEX_WAITERS2, r0 + or r0, r6 + shlr r0 /* r0 = FUTEX_OWNER_DIED */ + tst r0, r4 + bf/s 6f + cmp/eq r4, r6 + bt 2f + + CMPXCHG (r4, @r8, r6, r2) + bf/s 5f + mov #0, r5 + +2: + mov r8, r4 + mov r11, r5 + LOAD_FUTEX_WAIT (r5, r0, r1) + mov r10, r6 + mov r15, r7 + mov #SYS_futex, r3 + extu.b r3, r3 + trapa #0x14 + SYSCALL_INST_PAD + mov r0, r5 + + mov.l @r8, r2 + +5: + tst r2, r2 + bf/s 7f + mov r2, r10 + + stc gbr, r1 + mov.w .Ltidoff2, r2 + add r2, r1 + mov.l @r1, r4 + mov #0, r3 + CMPXCHG (r3, @r8, r4, r10) + bf 7f + mov #0, r0 + +6: + add #8, r15 + mov.l @r15+, r8 + mov.l @r15+, r9 + mov.l @r15+, r10 + rts + mov.l @r15+, r11 + +7: + /* Check whether the time expired. */ + mov #-ETIMEDOUT, r1 + cmp/eq r5, r1 + bf 1b + +8: + bra 6b + mov #ETIMEDOUT, r0 +3: + rts + mov #EINVAL, r0 + cfi_endproc + .align 2 +.L_FUTEX_WAITERS2: + .long FUTEX_WAITERS +.L1g: + .long 1000000000 +.Ltidoff2: + .word TID - TLS_PRE_TCB_SIZE +.L1k: + .word 1000 + .size __lll_robust_timedlock_wait,.-__lll_robust_timedlock_wait diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pt-initfini.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pt-initfini.c new file mode 100644 index 00000000..82c97c35 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pt-initfini.c @@ -0,0 +1,126 @@ +/* Special .init and .fini section support for SH. NPTL version. + Copyright (C) 2003, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it + and/or modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + In addition to the permissions in the GNU Library General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file with other + programs, and to distribute those programs without any restriction + coming from the use of this file. (The Library General Public + License restrictions do apply in other respects; for example, they + cover modification of the file, and distribution when not linked + into another program.) + + The GNU C Library is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* This file is compiled into assembly code which is then munged by a sed + script into two files: crti.s and crtn.s. + + * crti.s puts a function prologue at the beginning of the + .init and .fini sections and defines global symbols for + those addresses, so they can be called as functions. + + * crtn.s puts the corresponding function epilogues + in the .init and .fini sections. */ + +__asm__ ("\n\ +\n\ +#include \"defs.h\"\n\ +\n\ +/*@HEADER_ENDS*/\n\ +\n\ +/*@TESTS_BEGIN*/\n\ +\n\ +/*@TESTS_END*/\n\ +\n\ +/*@_init_PROLOG_BEGINS*/\n\ + .section .init\n\ + .align 5\n\ + .global _init\n\ + .type _init,@function\n\ +_init:\n\ + mov.l r12,@-r15\n\ + mov.l r14,@-r15\n\ + sts.l pr,@-r15\n\ + mova .L22,r0\n\ + mov.l .L22,r12\n\ + add r0,r12\n\ + mova .L24,r0\n\ + mov.l .L24,r1\n\ + add r0,r1\n\ + jsr @r1\n\ + mov r15,r14\n\ + bra 1f\n\ + nop\n\ + .align 2\n\ +.L22:\n\ + .long _GLOBAL_OFFSET_TABLE_\n\ +.L24:\n\ + .long __pthread_initialize_minimal_internal@PLT\n\ +1:\n\ + ALIGN\n\ + END_INIT\n\ +\n\ +/*@_init_PROLOG_ENDS*/\n\ +\n\ +/*@_init_EPILOG_BEGINS*/\n\ + .section .init\n\ + mov r14,r15\n\ + lds.l @r15+,pr\n\ + mov.l @r15+,r14\n\ + rts \n\ + mov.l @r15+,r12\n\ + END_INIT\n\ + \n\ +/*@_init_EPILOG_ENDS*/\n\ +\n\ +/*@_fini_PROLOG_BEGINS*/\n\ + .section .fini\n\ + .align 5\n\ + .global _fini\n\ + .type _fini,@function\n\ +_fini:\n\ + mov.l r12,@-r15\n\ + mov.l r14,@-r15\n\ + sts.l pr,@-r15\n\ + mova .L27,r0\n\ + mov.l .L27,r12\n\ + add r0,r12\n\ + mov r15,r14\n\ + ALIGN\n\ + END_FINI\n\ + bra 1f\n\ + nop\n\ + .align 2\n\ +.L27:\n\ + .long _GLOBAL_OFFSET_TABLE_\n\ +1:\n\ +/*@_fini_PROLOG_ENDS*/\n\ +\n\ +/*@_fini_EPILOG_BEGINS*/\n\ + .section .fini\n\ + mov r14,r15\n\ + lds.l @r15+,pr\n\ + mov.l @r15+,r14\n\ + rts \n\ + mov.l @r15+,r12\n\ +\n\ + END_FINI\n\ + \n\ +/*@_fini_EPILOG_ENDS*/\n\ +\n\ +/*@TRAILER_BEGINS*/\n\ +"); diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pt-vfork.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pt-vfork.S new file mode 100644 index 00000000..54f2281d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pt-vfork.S @@ -0,0 +1,65 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#define _ERRNO_H 1 +#include +#include + +/* Clone the calling process, but without copying the whole address space. + The calling process is suspended until the new process exits or is + replaced by a call to `execve'. Return -1 for errors, 0 to the new process, + and the process ID of the new process to the old process. */ + +ENTRY (__vfork) + /* Save the PID value. */ + stc gbr, r2 + mov.w .L2, r0 + mov.l @(r0,r2), r4 + neg r4, r1 + mov.l r1, @(r0,r2) + + mov.w .L1, r3 + trapa #0x10 + mov r0, r1 + + /* Restore the old PID value in the parent. */ + tst r0, r0 + bt/s 2f + stc gbr, r2 + mov.w .L2, r0 + mov.l r4, @(r0,r2) + mov r1, r0 +2: + mov #-12, r2 + shad r2, r1 + not r1, r1 // r1=0 means r0 = -1 to -4095 + tst r1, r1 // i.e. error in linux + bf .Lpseudo_end + SYSCALL_ERROR_HANDLER +.Lpseudo_end: + rts + nop +.L1: + .word __NR_vfork +.L2: + .word PID - TLS_PRE_TCB_SIZE + +PSEUDO_END (__vfork) + +weak_alias (__vfork, vfork) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_barrier_wait.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_barrier_wait.S new file mode 100644 index 00000000..4a6059ae --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_barrier_wait.S @@ -0,0 +1,216 @@ +/* Copyright (C) 2003, 2004, 2007, 2008 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include "lowlevel-atomic.h" + + .text + + .globl pthread_barrier_wait + .type pthread_barrier_wait,@function + .align 5 +pthread_barrier_wait: + mov.l r9, @-r15 + mov.l r8, @-r15 + sts.l pr, @-r15 + mov r4, r8 + + /* Get the mutex. */ + mov #0, r3 + mov #1, r4 + CMPXCHG (r3, @(MUTEX,r8), r4, r2) + bf 1f + + /* One less waiter. If this was the last one needed wake + everybody. */ +2: + mov.l @(LEFT,r8), r0 + add #-1, r0 + mov.l r0, @(LEFT,r8) + tst r0, r0 + bt 3f + + /* There are more threads to come. */ + mov.l @(CURR_EVENT,r8), r6 + + /* Release the mutex. */ + DEC (@(MUTEX,r8), r2) + tst r2, r2 + bf 6f +7: + /* Wait for the remaining threads. The call will return immediately + if the CURR_EVENT memory has meanwhile been changed. */ + mov r8, r4 +#if CURR_EVENT != 0 + add #CURR_EVENT, r4 +#endif +#if FUTEX_WAIT == 0 + mov.l @(PRIVATE,r8), r5 +#else + mov #FUTEX_WAIT, r5 + mov.l @(PRIVATE,r8), r0 + or r0, r5 +#endif + mov #0, r7 +8: + mov #SYS_futex, r3 + extu.b r3, r3 + trapa #0x14 + SYSCALL_INST_PAD + + /* Don't return on spurious wakeups. The syscall does not change + any register except r0 so there is no need to reload any of + them. */ + mov.l @(CURR_EVENT,r8), r0 + cmp/eq r0, r6 + bt 8b + + /* Increment LEFT. If this brings the count back to the + initial count unlock the object. */ + mov #1, r3 + mov.l @(INIT_COUNT,r8), r4 + XADD (r3, @(LEFT,r8), r2, r5) + add #-1, r4 + cmp/eq r2, r4 + bf 10f + + /* Release the mutex. We cannot release the lock before + waking the waiting threads since otherwise a new thread might + arrive and gets waken up, too. */ + DEC (@(MUTEX,r8), r2) + tst r2, r2 + bf 9f + +10: + mov #0, r0 /* != PTHREAD_BARRIER_SERIAL_THREAD */ + lds.l @r15+, pr + mov.l @r15+, r8 + rts + mov.l @r15+, r9 + +3: + /* The necessary number of threads arrived. */ + mov.l @(CURR_EVENT,r8), r1 + add #1, r1 + mov.l r1, @(CURR_EVENT,r8) + + /* Wake up all waiters. The count is a signed number in the kernel + so 0x7fffffff is the highest value. */ + mov.l .Lall, r6 + mov r8, r4 +#if CURR_EVENT != 0 + add #CURR_EVENT, r4 +#endif + mov #0, r7 + mov #FUTEX_WAKE, r5 + mov.l @(PRIVATE,r8), r0 + or r0, r5 + mov #SYS_futex, r3 + extu.b r3, r3 + trapa #0x14 + SYSCALL_INST_PAD + + /* Increment LEFT. If this brings the count back to the + initial count unlock the object. */ + mov #1, r3 + mov.l @(INIT_COUNT,r8), r4 + XADD (r3, @(LEFT,r8), r2, r5) + add #-1, r4 + cmp/eq r2, r4 + bf 5f + + /* Release the mutex. */ + DEC (@(MUTEX,r8), r2) + tst r2, r2 + bf 4f +5: + mov #-1, r0 /* == PTHREAD_BARRIER_SERIAL_THREAD */ + lds.l @r15+, pr + mov.l @r15+, r8 + rts + mov.l @r15+, r9 + +1: + mov.l @(PRIVATE,r8), r6 + mov #LLL_SHARED, r0 + extu.b r0, r0 + xor r0, r6 + mov r2, r4 + mov r8, r5 + mov.l .Lwait0, r1 + bsrf r1 + add #MUTEX, r5 +.Lwait0b: + bra 2b + nop + +4: + mov.l @(PRIVATE,r8), r5 + mov #LLL_SHARED, r0 + extu.b r0, r0 + xor r0, r5 + mov r8, r4 + mov.l .Lwake0, r1 + bsrf r1 + add #MUTEX, r4 +.Lwake0b: + bra 5b + nop + +6: + mov r6, r9 + mov.l @(PRIVATE,r8), r5 + mov #LLL_SHARED, r0 + extu.b r0, r0 + xor r0, r5 + mov r8, r4 + mov.l .Lwake1, r1 + bsrf r1 + add #MUTEX, r4 +.Lwake1b: + bra 7b + mov r9, r6 + +9: + mov r6, r9 + mov.l @(PRIVATE,r8), r5 + mov #LLL_SHARED, r0 + extu.b r0, r0 + xor r0, r5 + mov r8, r4 + mov.l .Lwake2, r1 + bsrf r1 + add #MUTEX, r4 +.Lwake2b: + bra 10b + mov r9, r6 + + .align 2 +.Lall: + .long 0x7fffffff +.Lwait0: + .long __lll_lock_wait-.Lwait0b +.Lwake0: + .long __lll_unlock_wake-.Lwake0b +.Lwake1: + .long __lll_unlock_wake-.Lwake1b +.Lwake2: + .long __lll_unlock_wake-.Lwake2b + .size pthread_barrier_wait,.-pthread_barrier_wait diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_broadcast.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_broadcast.S new file mode 100644 index 00000000..23318317 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_broadcast.S @@ -0,0 +1,263 @@ +/* Copyright (C) 2003, 2004, 2006, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include +#include +#include "lowlevel-atomic.h" + + .text + + /* int pthread_cond_broadcast (pthread_cond_t *cond) */ + .globl __pthread_cond_broadcast + .type __pthread_cond_broadcast, @function + .protected __pthread_cond_broadcast + .align 5 +__pthread_cond_broadcast: + mov.l r10, @-r15 + mov.l r9, @-r15 + mov.l r8, @-r15 + sts.l pr, @-r15 + mov r4, r8 + + /* Get internal lock. */ + mov #0, r3 + mov #1, r4 +#if cond_lock != 0 + CMPXCHG (r3, @(cond_lock,r8), r4, r2) +#else + CMPXCHG (r3, @r8, r4, r2) +#endif + bf 1f +2: + mov.l @(total_seq+4,r8),r0 + mov.l @(total_seq,r8),r1 + mov.l @(wakeup_seq+4,r8), r2 + cmp/hi r2, r0 + bt 3f + cmp/hi r0, r2 + bt 4f + mov.l @(wakeup_seq,r8), r2 + cmp/hi r2, r1 + bf 4f + +3: + /* Cause all currently waiting threads to recognize they are + woken up. */ + mov.l r1, @(wakeup_seq,r8) + mov.l r0, @(wakeup_seq+4,r8) + mov.l r1, @(woken_seq,r8) + mov.l r0, @(woken_seq+4,r8) + mov.l @(broadcast_seq,r8), r2 + add #1, r2 + mov.l r2, @(broadcast_seq,r8) + add r1, r1 + mov r1, r10 + mov.l r10, @(cond_futex,r8) + + /* Get the address of the mutex used. */ + mov.l @(dep_mutex,r8), r9 + + /* Unlock. */ +#if cond_lock != 0 + DEC (@(cond_lock,r8), r2) +#else + DEC (@r8, r2) +#endif + tst r2, r2 + bf 7f + +8: + /* Don't use requeue for pshared condvars. */ + mov #-1, r0 + cmp/eq r0, r9 + mov r8, r4 + bt/s 9f + add #cond_futex, r4 + + /* XXX: The kernel only supports FUTEX_CMP_REQUEUE to the same + type of futex (private resp. shared). */ + mov.l @(MUTEX_KIND,r9), r0 + tst #(PI_BIT|PS_BIT), r0 + bf 9f + + /* Wake up all threads. */ +#ifdef __ASSUME_PRIVATE_FUTEX + mov #(FUTEX_CMP_REQUEUE|FUTEX_PRIVATE_FLAG), r5 + extu.b r5, r5 +#else + stc gbr, r1 + mov.w .Lpfoff, r2 + add r2, r1 + mov.l @r1, r5 + mov #FUTEX_CMP_REQUEUE, r0 + or r0, r5 +#endif + mov #1, r6 + mov #-1, r7 + shlr r7 /* r7 = 0x7fffffff */ + mov r9, r0 +# if MUTEX_FUTEX != 0 + add #MUTEX_FUTEX, r0 +# endif + mov r10, r1 + mov #SYS_futex, r3 + extu.b r3, r3 + trapa #0x16 + SYSCALL_INST_PAD + + /* For any kind of error, which mainly is EAGAIN, we try again + with WAKE. The general test also covers running on old + kernels. */ + mov r0, r1 + mov #-12, r2 + shad r2, r1 + not r1, r1 + tst r1, r1 + mov r8, r4 + bt/s 9f + add #cond_futex, r4 + +10: + mov #0, r0 + lds.l @r15+, pr + mov.l @r15+, r8 + mov.l @r15+, r9 + rts + mov.l @r15+, r10 + +4: + /* Unlock. */ +#if cond_lock != 0 + DEC (@(cond_lock,r8), r2) +#else + DEC (@r8, r2) +#endif + tst r2, r2 + bf 5f +6: + mov #0, r0 + lds.l @r15+, pr + mov.l @r15+, r8 + mov.l @r15+, r9 + rts + mov.l @r15+, r10 + +1: + /* Initial locking failed. */ + mov r8, r5 +#if cond_lock != 0 + add #cond_lock, r5 +#endif + mov.l @(dep_mutex,r8), r0 + cmp/eq #-1, r0 + bf/s 99f + mov #LLL_PRIVATE, r6 + mov #LLL_SHARED, r6 +99: + extu.b r6, r6 + mov.l .Lwait5, r1 + bsrf r1 + mov r2, r4 +.Lwait5b: + bra 2b + nop + +5: + /* Unlock in loop requires wakeup. */ + mov r8, r4 +#if cond_lock != 0 + add #cond_lock, r4 +#endif + mov.l @(dep_mutex,r8), r0 + cmp/eq #-1, r0 + bf/s 99f + mov #LLL_PRIVATE, r5 + mov #LLL_SHARED, r5 +99: + mov.l .Lwake5, r1 + bsrf r1 + extu.b r5, r5 +.Lwake5b: + bra 6b + nop + +7: + /* Unlock in loop requires wakeup. */ + mov r8, r4 +#if cond_lock != 0 + add #cond_lock, r4 +#endif + mov #-1, r0 + cmp/eq r0, r9 + bf/s 99f + mov #LLL_PRIVATE, r5 + mov #LLL_SHARED, r5 +99: + mov.l .Lwake6, r1 + bsrf r1 + extu.b r5, r5 +.Lwake6b: + bra 8b + nop + +9: + mov #-1, r0 + cmp/eq r0, r9 + bt/s 99f + mov #FUTEX_WAKE, r5 +#ifdef __ASSUME_PRIVATE_FUTEX + mov #(FUTEX_WAKE|FUTEX_PRIVATE_FLAG), r5 + extu.b r5, r5 +#else + stc gbr, r1 + mov.w .Lpfoff, r2 + add r2, r1 + mov.l @r1, r5 + mov #FUTEX_WAKE, r0 + or r0, r5 +#endif +99: + mov #-1, r6 + shlr r6 /* r6 = 0x7fffffff */ + mov #0, r7 + mov #SYS_futex, r3 + extu.b r3, r3 + trapa #0x14 + SYSCALL_INST_PAD + bra 10b + nop + +#ifndef __ASSUME_PRIVATE_FUTEX +.Lpfoff: + .word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE +#endif + + .align 2 +.Lwait5: + .long __lll_lock_wait-.Lwait5b +.Lwake5: + .long __lll_unlock_wake-.Lwake5b +.Lwake6: + .long __lll_unlock_wake-.Lwake6b + .size __pthread_cond_broadcast, .-__pthread_cond_broadcast +weak_alias (__pthread_cond_broadcast, pthread_cond_broadcast) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_signal.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_signal.S new file mode 100644 index 00000000..ca87336d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_signal.S @@ -0,0 +1,190 @@ +/* Copyright (C) 2003, 2004, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include +#include "lowlevel-atomic.h" + + .text + + /* int pthread_cond_signal (pthread_cond_t *cond) */ + .globl __pthread_cond_signal + .type __pthread_cond_signal, @function + .protected __pthread_cond_signal + .align 5 +__pthread_cond_signal: + mov.l r8, @-r15 + sts.l pr, @-r15 + mov r4, r8 + + /* Get internal lock. */ + mov #0, r3 + mov #1, r4 +#if cond_lock != 0 + CMPXCHG (r3, @(cond_lock,r8), r4, r2) +#else + CMPXCHG (r3, @r8, r4, r2) +#endif + bf 1f +2: + mov.l @(total_seq+4,r8),r0 + mov.l @(total_seq,r8),r1 + mov.l @(wakeup_seq+4,r8), r2 + cmp/hi r2, r0 + bt 3f + cmp/hi r0, r2 + bt 4f + mov.l @(wakeup_seq,r8), r2 + cmp/hi r2, r1 + bf 4f + +3: + /* Bump the wakeup number. */ + mov #1, r2 + mov #0, r3 + clrt + mov.l @(wakeup_seq,r8),r0 + mov.l @(wakeup_seq+4,r8),r1 + addc r2, r0 + addc r3, r1 + mov.l r0,@(wakeup_seq,r8) + mov.l r1,@(wakeup_seq+4,r8) + mov.l @(cond_futex,r8),r0 + add r2, r0 + mov.l r0,@(cond_futex,r8) + + /* Wake up one thread. */ + mov r8, r4 + add #cond_futex, r4 + mov.l @(dep_mutex,r8), r0 + cmp/eq #-1, r0 + bt/s 99f + mov #FUTEX_WAKE_OP, r5 +#ifdef __ASSUME_PRIVATE_FUTEX + mov #(FUTEX_WAKE_OP|FUTEX_PRIVATE_FLAG), r5 + extu.b r5, r5 +#else + stc gbr, r1 + mov.w .Lpfoff, r2 + add r2, r1 + mov.l @r1, r5 + mov #FUTEX_WAKE_OP, r0 + or r0, r5 +#endif +99: + mov #1, r6 + mov #0, r7 + mov r8, r0 + add #cond_lock, r0 + mov.l .Lfutexop, r1 + mov #SYS_futex, r3 + extu.b r3, r3 + trapa #0x14 + SYSCALL_INST_PAD + + /* For any kind of error, we try again with WAKE. + The general test also covers running on old kernels. */ + mov r0, r1 + mov #-12, r2 + shad r2, r1 + not r1, r1 + tst r1, r1 + bt 7f + +6: + mov #0, r0 + lds.l @r15+, pr + rts + mov.l @r15+, r8 + +#ifndef __ASSUME_PRIVATE_FUTEX +.Lpfoff: + .word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE +#endif + .align 2 +.Lfutexop: + .long FUTEX_OP_CLEAR_WAKE_IF_GT_ONE + +7: + /* r5 should be either FUTEX_WAKE_OP or + FUTEX_WAKE_OP|FUTEX_PRIVATE_FLAG from the previous syscall. */ + mov #(FUTEX_WAKE ^ FUTEX_WAKE_OP), r0 + xor r0, r5 + trapa #0x14 + SYSCALL_INST_PAD + +4: + /* Unlock. */ +#if cond_lock != 0 + DEC (@(cond_lock,r8), r2) +#else + DEC (@r8, r2) +#endif + tst r2, r2 + bt 6b + +5: + /* Unlock in loop requires wakeup. */ + mov r8, r4 +#if cond_lock != 0 + add #cond_lock, r4 +#endif + mov.l @(dep_mutex,r8), r0 + cmp/eq #-1, r0 + bf/s 99f + mov #LLL_PRIVATE, r5 + mov #LLL_SHARED, r5 +99: + mov.l .Lwake4, r1 + bsrf r1 + extu.b r5, r5 +.Lwake4b: + bra 6b + nop + +1: + /* Initial locking failed. */ + mov r8, r5 +#if cond_lock != 0 + add #cond_lock, r5 +#endif + mov.l @(dep_mutex,r8), r0 + cmp/eq #-1, r0 + bf/s 99f + mov #LLL_PRIVATE, r6 + mov #LLL_SHARED, r6 +99: + extu.b r6, r6 + mov.l .Lwait4, r1 + bsrf r1 + mov r2, r4 +.Lwait4b: + bra 2b + nop + + .align 2 +.Lwait4: + .long __lll_lock_wait-.Lwait4b +.Lwake4: + .long __lll_unlock_wake-.Lwake4b + .size __pthread_cond_signal, .-__pthread_cond_signal +weak_alias (__pthread_cond_signal, pthread_cond_signal) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_timedwait.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_timedwait.S new file mode 100644 index 00000000..cacb037d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_timedwait.S @@ -0,0 +1,861 @@ +/* Copyright (C) 2003, 2004, 2006, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include +#include "lowlevel-atomic.h" + + .text + +/* int pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex, + const struct timespec *abstime) */ + .globl __pthread_cond_timedwait + .type __pthread_cond_timedwait, @function + .protected __pthread_cond_timedwait + .align 5 +__pthread_cond_timedwait: +.LSTARTCODE: + mov.l r8, @-r15 +.Lpush_r8: + mov.l r9, @-r15 +.Lpush_r9: + mov.l r10, @-r15 +.Lpush_r10: + mov.l r11, @-r15 +.Lpush_r11: + mov.l r12, @-r15 +.Lpush_r12: + mov.l r13, @-r15 +.Lpush_r13: + sts.l pr, @-r15 +.Lpush_pr: + add #-64, r15 +.Lalloc: + mov r4, r8 + mov r5, r9 + mov r6, r13 +#ifdef __PIC__ + mova .Lgot0, r0 + mov.l .Lgot0, r12 + add r0, r12 +#endif + + mov.l @(4,r13), r0 + mov.l .L1g, r1 + cmp/hs r1, r0 + bf 0f + bra 18f + mov #EINVAL, r0 +0: + /* Get internal lock. */ + mov #0, r3 + mov #1, r4 +#if cond_lock != 0 + CMPXCHG (r3, @(cond_lock,r8), r4, r2) +#else + CMPXCHG (r3, @r8, r4, r2) +#endif + bt 2f + bra 1f + nop +#ifdef __PIC__ + .align 2 +.Lgot0: + .long _GLOBAL_OFFSET_TABLE_ +#endif + +2: + /* Store the reference to the mutex. If there is already a + different value in there this is a bad user bug. */ + mov.l @(dep_mutex,r8),r0 + cmp/eq #-1, r0 + bt 17f + mov.l r9, @(dep_mutex,r8) + +17: + /* Unlock the mutex. */ + mov.l .Lmunlock1, r1 + mov #0, r5 + bsrf r1 + mov r9, r4 +.Lmunlock1b: + + tst r0, r0 + bt 0f + bra 16f + nop +0: + mov #1, r2 + mov #0, r3 + + clrt + mov.l @(total_seq,r8),r0 + mov.l @(total_seq+4,r8),r1 + addc r2, r0 + addc r3, r1 + mov.l r0,@(total_seq,r8) + mov.l r1,@(total_seq+4,r8) + mov.l @(cond_futex,r8), r0 + add r2, r0 + mov.l r0, @(cond_futex,r8) + mov #(1 << nwaiters_shift), r2 + mov.l @(cond_nwaiters,r8), r0 + add r2, r0 + mov.l r0, @(cond_nwaiters,r8) + + /* Get and store current wakeup_seq value. */ + mov.l @(wakeup_seq,r8), r10 + mov.l @(wakeup_seq+4,r8), r11 + mov.l @(broadcast_seq,r8), r0 + mov.l r0, @(4,r15) + +8: + /* Get current time. */ +#ifdef __NR_clock_gettime + /* Get the clock number. */ + mov.l @(cond_nwaiters,r8), r4 + mov #((1 << nwaiters_shift) - 1), r0 + and r0, r4 + /* Only clocks 0 and 1 are allowed. Both are handled in the + kernel. */ + mov r15, r5 + add #16, r5 + mov.w .L__NR_clock_gettime, r3 + trapa #0x12 + SYSCALL_INST_PAD +# ifndef __ASSUME_POSIX_TIMERS + cmp/eq #-ENOSYS, r0 + bt 19f +# endif + + /* Compute relative timeout. */ + mov.l @r13, r2 + mov.l @(4,r13), r3 + mov.l @(16,r15), r0 + bra 0f + mov.l @(20,r15), r1 +.L__NR_clock_gettime: + .word __NR_clock_gettime + +# ifndef __ASSUME_POSIX_TIMERS +19: + mov r15, r4 + add #16, r4 + mov #0, r5 + mov #__NR_gettimeofday, r3 + trapa #0x12 + SYSCALL_INST_PAD + + /* Compute relative timeout. */ + mov.l @(20,r15), r0 + mov.w .L1k, r1 + dmulu.l r0, r1 /* Micro seconds to nano seconds. */ + mov.l @r13, r2 + mov.l @(4,r13), r3 + mov.l @(16,r15), r0 + sts macl, r1 +#endif +0: +#else + mov r15, r4 + add #16, r4 + mov #0, r5 + mov #__NR_gettimeofday, r3 + trapa #0x12 + SYSCALL_INST_PAD + + /* Compute relative timeout. */ + mov.l @(20,r15), r0 + mov.w .L1k, r1 + dmulu.l r0, r1 /* Micro seconds to nano seconds. */ + mov.l @r13, r2 + mov.l @(4,r13), r3 + mov.l @(16,r15), r0 + sts macl, r1 +#endif + sub r0, r2 + clrt + subc r1, r3 + bf 12f + mov.l .L1g, r1 + add r1, r3 + add #-1, r2 +12: + mov #-ETIMEDOUT, r1 + mov.l r1, @(12,r15) + cmp/pz r2 + bf 6f /* Time is already up. */ + + /* Store relative timeout. */ + mov.l r2, @(16,r15) + mov.l r3, @(20,r15) + mov.l @(cond_futex,r8), r1 + mov.l r1, @(8,r15) + + /* Unlock. */ +#if cond_lock != 0 + DEC (@(cond_lock,r8), r2) +#else + DEC (@r8, r2) +#endif + tst r2, r2 + bt 4f + bra 3f + nop +4: +.LcleanupSTART: + mov.l .Lenable1, r1 + bsrf r1 + nop +.Lenable1b: + mov.l r0, @r15 + + mov r15, r7 + add #16, r7 + mov.l @(dep_mutex,r8), r0 + cmp/eq #-1, r0 + bt/s 99f + mov #FUTEX_WAIT, r5 +#ifdef __ASSUME_PRIVATE_FUTEX + mov #(FUTEX_WAIT|FUTEX_PRIVATE_FLAG), r5 + extu.b r5, r5 +#else + stc gbr, r1 + mov.w .Lpfoff, r2 + add r2, r1 + mov.l @r1, r5 + mov #FUTEX_WAIT, r0 + or r0, r5 +#endif +99: + mov.l @(8,r15), r6 + mov r8, r4 + add #cond_futex, r4 + mov #SYS_futex, r3 + extu.b r3, r3 + trapa #0x14 + SYSCALL_INST_PAD + mov.l r0, @(12,r15) + + mov.l .Ldisable1, r1 + bsrf r1 + mov.l @r15, r4 +.Ldisable1b: +.LcleanupEND: + + /* Lock. */ + mov #0, r3 + mov #1, r4 +#if cond_lock != 0 + CMPXCHG (r3, @(cond_lock,r8), r4, r2) +#else + CMPXCHG (r3, @r8, r4, r2) +#endif + bf 5f +6: + mov.l @(broadcast_seq,r8), r0 + mov.l @(4,r15), r1 + cmp/eq r0, r1 + bf 23f + + mov.l @(woken_seq,r8), r0 + mov.l @(woken_seq+4,r8), r1 + + mov.l @(wakeup_seq,r8), r2 + mov.l @(wakeup_seq+4,r8), r3 + + cmp/eq r3, r11 + bf 7f + cmp/eq r2, r10 + bt 15f +7: + cmp/eq r1, r3 + bf 9f + cmp/eq r0, r2 + bf 9f +15: + mov.l @(12,r15),r0 + cmp/eq #-ETIMEDOUT, r0 + bf 8b + + mov #1, r2 + mov #0, r3 + + clrt + mov.l @(wakeup_seq,r8),r0 + mov.l @(wakeup_seq+4,r8),r1 + addc r2, r0 + addc r3, r1 + mov.l r0,@(wakeup_seq,r8) + mov.l r1,@(wakeup_seq+4,r8) + mov.l @(cond_futex,r8),r0 + add r2, r0 + mov.l r0,@(cond_futex,r8) + mov #ETIMEDOUT, r0 + bra 14f + mov.l r0, @(24,r15) + +23: + mov #0, r0 + bra 24f + mov.l r0, @(24,r15) + +9: + mov #0, r0 + mov.l r0, @(24,r15) +14: + mov #1, r2 + mov #0, r3 + + clrt + mov.l @(woken_seq,r8),r0 + mov.l @(woken_seq+4,r8),r1 + addc r2, r0 + addc r3, r1 + mov.l r0,@(woken_seq,r8) + mov.l r1,@(woken_seq+4,r8) + +24: + mov #(1 << nwaiters_shift), r2 + mov.l @(cond_nwaiters,r8),r0 + sub r2, r0 + mov.l r0,@(cond_nwaiters,r8) + + /* Wake up a thread which wants to destroy the condvar object. */ + mov.l @(total_seq,r8),r0 + mov.l @(total_seq+4,r8),r1 + and r1, r0 + not r0, r0 + cmp/eq #0, r0 + bf/s 25f + mov #((1 << nwaiters_shift) - 1), r1 + not r1, r1 + mov.l @(cond_nwaiters,r8),r0 + tst r1, r0 + bf 25f + + mov r8, r4 + add #cond_nwaiters, r4 + mov.l @(dep_mutex,r8), r0 + cmp/eq #-1, r0 + bt/s 99f + mov #FUTEX_WAKE, r5 +#ifdef __ASSUME_PRIVATE_FUTEX + mov #(FUTEX_WAKE|FUTEX_PRIVATE_FLAG), r5 + extu.b r5, r5 +#else + stc gbr, r1 + mov.w .Lpfoff, r2 + add r2, r1 + mov.l @r1, r5 + mov #FUTEX_WAKE, r0 + or r0, r5 +#endif +99: + mov #1, r6 + mov #0, r7 + mov #SYS_futex, r3 + extu.b r3, r3 + trapa #0x14 + SYSCALL_INST_PAD + +25: +#if cond_lock != 0 + DEC (@(cond_lock,r8), r2) +#else + DEC (@r8, r2) +#endif + tst r2, r2 + bf 10f + +11: + mov r9, r4 + mov.l .Lmlocki1, r1 + bsrf r1 + nop +.Lmlocki1b: + + /* We return the result of the mutex_lock operation if it failed. */ + tst r0, r0 + bf 18f + mov.l @(24,r15), r0 + +18: + add #64, r15 + lds.l @r15+, pr + mov.l @r15+, r13 + mov.l @r15+, r12 + mov.l @r15+, r11 + mov.l @r15+, r10 + mov.l @r15+, r9 + rts + mov.l @r15+, r8 + +#ifndef __ASSUME_PRIVATE_FUTEX +.Lpfoff: + .word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE +#endif +.L1k: + .word 1000 + .align 2 +.Lmunlock1: + .long __pthread_mutex_unlock_usercnt-.Lmunlock1b +.Lenable1: + .long __pthread_enable_asynccancel-.Lenable1b +.Ldisable1: + .long __pthread_disable_asynccancel-.Ldisable1b +.Lmlocki1: + .long __pthread_mutex_cond_lock-.Lmlocki1b +.L1g: + .long 1000000000 + +1: + /* Initial locking failed. */ + mov r8, r5 +#if cond_lock != 0 + add #cond_lock, r5 +#endif + mov.l @(dep_mutex,r8), r0 + cmp/eq #-1, r0 + bf/s 99f + mov #LLL_PRIVATE, r6 + mov #LLL_SHARED, r6 +99: + extu.b r6, r6 + mov.l .Lwait2, r1 + bsrf r1 + mov r2, r4 +.Lwait2b: + bra 2b + nop + +3: + /* Unlock in loop requires wakeup. */ + mov r8, r4 +#if cond_lock != 0 + add #cond_lock, r4 +#endif + mov.l @(dep_mutex,r8), r0 + cmp/eq #-1, r0 + bf/s 99f + mov #LLL_PRIVATE, r5 + mov #LLL_SHARED, r5 +99: + mov.l .Lmwait2, r1 + bsrf r1 + extu.b r5, r5 +.Lmwait2b: + bra 4b + nop + +5: + /* Locking in loop failed. */ + mov r8, r5 +#if cond_lock != 0 + add #cond_lock, r5 +#endif + mov.l @(dep_mutex,r8), r0 + cmp/eq #-1, r0 + bf/s 99f + mov #LLL_PRIVATE, r6 + mov #LLL_SHARED, r6 +99: + extu.b r6, r6 + mov.l .Lwait3, r1 + bsrf r1 + mov r2, r4 +.Lwait3b: + bra 6b + nop + +10: + /* Unlock after loop requires wakeup. */ + mov r8, r4 +#if cond_lock != 0 + add #cond_lock, r4 +#endif + mov.l @(dep_mutex,r8), r0 + cmp/eq #-1, r0 + bf/s 99f + mov #LLL_PRIVATE, r5 + mov #LLL_SHARED, r5 +99: + mov.l .Lmwait3, r1 + bsrf r1 + extu.b r5, r5 +.Lmwait3b: + bra 11b + nop + +16: + /* The initial unlocking of the mutex failed. */ + mov.l r0, @(24,r15) +#if cond_lock != 0 + DEC (@(cond_lock,r8), r2) +#else + DEC (@r8, r2) +#endif + tst r2, r2 + bf 17f + + mov r8, r4 +#if cond_lock != 0 + add #cond_lock, r4 +#endif + mov.l @(dep_mutex,r8), r0 + cmp/eq #-1, r0 + bf/s 99f + mov #LLL_PRIVATE, r5 + mov #LLL_SHARED, r5 +99: + mov.l .Lmwait4, r1 + bsrf r1 + extu.b r5, r5 +.Lmwait4b: +17: + bra 18b + mov.l @(24,r15), r0 + + .align 2 +.Lwait2: + .long __lll_lock_wait-.Lwait2b +.Lmwait2: + .long __lll_unlock_wake-.Lmwait2b +.Lwait3: + .long __lll_lock_wait-.Lwait3b +.Lmwait3: + .long __lll_unlock_wake-.Lmwait3b +.Lmwait4: + .long __lll_unlock_wake-.Lmwait4b + .size __pthread_cond_timedwait, .-__pthread_cond_timedwait +weak_alias (__pthread_cond_timedwait, pthread_cond_timedwait) + + + .type __condvar_tw_cleanup, @function +__condvar_tw_cleanup: + mov r4, r11 + + /* Get internal lock. */ + mov #0, r3 + mov #1, r4 +#if cond_lock != 0 + CMPXCHG (r3, @(cond_lock,r8), r4, r2) +#else + CMPXCHG (r3, @r8, r4, r2) +#endif + bt 1f + nop + + mov r8, r5 +#if cond_lock != 0 + add #cond_lock, r5 +#endif + mov.l @(dep_mutex,r8), r0 + cmp/eq #-1, r0 + bf/s 99f + mov #LLL_PRIVATE, r6 + mov #LLL_SHARED, r6 +99: + extu.b r6, r6 + mov.l .Lwait5, r1 + bsrf r1 + mov r2, r4 +.Lwait5b: + +1: + mov.l @(broadcast_seq,r8), r0 + mov.l @(4,r15), r1 + cmp/eq r0, r1 + bf 3f + + mov #1, r2 + mov #0, r3 + + /* We increment the wakeup_seq counter only if it is lower than + total_seq. If this is not the case the thread was woken and + then canceled. In this case we ignore the signal. */ + mov.l @(total_seq+4,r8), r0 + mov.l @(wakeup_seq+4,r8), r1 + cmp/hi r1, r0 + bt/s 6f + cmp/hi r0, r1 + bt 7f + mov.l @(total_seq,r8), r0 + mov.l @(wakeup_seq,r8), r1 + cmp/hs r0, r1 + bt 7f + +6: + clrt + mov.l @(wakeup_seq,r8),r0 + mov.l @(wakeup_seq+4,r8),r1 + addc r2, r0 + addc r3, r1 + mov.l r0,@(wakeup_seq,r8) + mov.l r1,@(wakeup_seq+4,r8) + mov.l @(cond_futex,r8),r0 + add r2, r0 + mov.l r0,@(cond_futex,r8) + +7: + clrt + mov.l @(woken_seq,r8),r0 + mov.l @(woken_seq+4,r8),r1 + addc r2, r0 + addc r3, r1 + mov.l r0,@(woken_seq,r8) + mov.l r1,@(woken_seq+4,r8) + +3: + mov #(1 << nwaiters_shift), r2 + mov.l @(cond_nwaiters,r8),r0 + sub r2, r0 + mov.l r0,@(cond_nwaiters,r8) + + /* Wake up a thread which wants to destroy the condvar object. */ + mov #0, r10 + mov.l @(total_seq,r8),r0 + mov.l @(total_seq+4,r8),r1 + and r1, r0 + not r0, r0 + cmp/eq #0, r0 + bf/s 4f + mov #((1 << nwaiters_shift) - 1), r1 + not r1, r1 + mov.l @(cond_nwaiters,r8),r0 + tst r1, r0 + bf 4f + + mov r8, r4 + add #cond_nwaiters, r4 + mov #FUTEX_WAKE, r5 + mov #1, r6 + mov #0, r7 + mov #SYS_futex, r3 + extu.b r3, r3 + trapa #0x14 + SYSCALL_INST_PAD + mov #1, r10 + +4: +#if cond_lock != 0 + DEC (@(cond_lock,r8), r2) +#else + DEC (@r8, r2) +#endif + tst r2, r2 + bt 2f + + mov r8, r4 +#if cond_lock != 0 + add #cond_lock, r4 +#endif + mov.l @(dep_mutex,r8), r0 + cmp/eq #-1, r0 + bf/s 99f + mov #LLL_PRIVATE, r5 + mov #LLL_SHARED, r5 +99: + mov.l .Lmwait5, r1 + bsrf r1 + extu.b r5, r5 +.Lmwait5b: + +2: + /* Wake up all waiters to make sure no signal gets lost. */ + tst r10, r10 + bf/s 5f + mov r8, r4 + add #cond_futex, r4 + mov #FUTEX_WAKE, r5 + mov #-1, r6 + shlr r6 /* r6 = 0x7fffffff */ + mov #0, r7 + mov #SYS_futex, r3 + extu.b r3, r3 + trapa #0x14 + SYSCALL_INST_PAD + +5: + mov.l .Lmlocki5, r1 + bsrf r1 + mov r9, r4 +.Lmlocki5b: + +.LcallUR: + mov.l .Lresume, r1 +#ifdef __PIC__ + add r12, r1 +#endif + jsr @r1 + mov r11, r4 + sleep + + .align 2 +.Lwait5: + .long __lll_lock_wait-.Lwait5b +.Lmwait5: + .long __lll_unlock_wake-.Lmwait5b +.Lmlocki5: + .long __pthread_mutex_cond_lock-.Lmlocki5b +.Lresume: +#ifdef __PIC__ + .long _Unwind_Resume@GOTOFF +#else + .long _Unwind_Resume +#endif +.LENDCODE: + .size __condvar_tw_cleanup, .-__condvar_tw_cleanup + + + .section .gcc_except_table,"a",@progbits +.LexceptSTART: + .byte 0xff ! @LPStart format (omit) + .byte 0xff ! @TType format (omit) + .byte 0x0b ! call-site format + ! DW_EH_PE_sdata4 + .uleb128 .Lcstend-.Lcstbegin +.Lcstbegin: + .ualong .LcleanupSTART-.LSTARTCODE + .ualong .LcleanupEND-.LcleanupSTART + .ualong __condvar_tw_cleanup-.LSTARTCODE + .uleb128 0 + .ualong .LcallUR-.LSTARTCODE + .ualong .LENDCODE-.LcallUR + .ualong 0 + .uleb128 0 +.Lcstend: + + .section .eh_frame,"a",@progbits +.LSTARTFRAME: + .ualong .LENDCIE-.LSTARTCIE ! Length of the CIE. +.LSTARTCIE: + .ualong 0 ! CIE ID. + .byte 1 ! Version number. +#ifdef SHARED + .string "zPLR" ! NUL-terminated augmentation + ! string. +#else + .string "zPL" ! NUL-terminated augmentation + ! string. +#endif + .uleb128 1 ! Code alignment factor. + .sleb128 -4 ! Data alignment factor. + .byte 0x11 ! Return address register + ! column. +#ifdef SHARED + .uleb128 7 ! Augmentation value length. + .byte 0x9b ! Personality: DW_EH_PE_pcrel + ! + DW_EH_PE_sdata4 + ! + DW_EH_PE_indirect + .ualong DW.ref.__gcc_personality_v0-. + .byte 0x1b ! LSDA Encoding: DW_EH_PE_pcrel + ! + DW_EH_PE_sdata4. + .byte 0x1b ! FDE Encoding: DW_EH_PE_pcrel + ! + DW_EH_PE_sdata4. +#else + .uleb128 6 ! Augmentation value length. + .byte 0x0 ! Personality: absolute + .ualong __gcc_personality_v0 + .byte 0x0 ! LSDA Encoding: absolute +#endif + .byte 0x0c ! DW_CFA_def_cfa + .uleb128 0xf + .uleb128 0 + .align 2 +.LENDCIE: + + .ualong .LENDFDE-.LSTARTFDE ! Length of the FDE. +.LSTARTFDE: + .ualong .LSTARTFDE-.LSTARTFRAME ! CIE pointer. +#ifdef SHARED + .ualong .LSTARTCODE-. ! PC-relative start address + ! of the code. +#else + .ualong .LSTARTCODE ! Start address of the code. +#endif + .ualong .LENDCODE-.LSTARTCODE ! Length of the code. + .uleb128 4 ! Augmentation size +#ifdef SHARED + .ualong .LexceptSTART-. +#else + .ualong .LexceptSTART +#endif + .byte 0x4 + .ualong .Lpush_r8-.LSTARTCODE + .byte 0xe + .uleb128 4 + .byte 0x88 + .uleb128 1 + .byte 0x4 + .ualong .Lpush_r9-.Lpush_r8 + .byte 0xe + .uleb128 8 + .byte 0x89 + .uleb128 2 + .byte 0x4 + .ualong .Lpush_r10-.Lpush_r9 + .byte 0xe + .uleb128 12 + .byte 0x8a + .uleb128 3 + .byte 0x4 + .ualong .Lpush_r11-.Lpush_r10 + .byte 0xe + .uleb128 16 + .byte 0x8b + .uleb128 4 + .byte 0x4 + .ualong .Lpush_r12-.Lpush_r11 + .byte 0xe + .uleb128 20 + .byte 0x8c + .uleb128 5 + .byte 0x4 + .ualong .Lpush_r13-.Lpush_r12 + .byte 0xe + .uleb128 24 + .byte 0x8d + .uleb128 6 + .byte 0x4 + .ualong .Lpush_pr-.Lpush_r13 + .byte 0xe + .uleb128 28 + .byte 0x91 + .uleb128 7 + .byte 0x4 + .ualong .Lalloc-.Lpush_pr + .byte 0xe + .uleb128 92 + .align 2 +.LENDFDE: + +#ifdef SHARED + .hidden DW.ref.__gcc_personality_v0 + .weak DW.ref.__gcc_personality_v0 + .section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits + .align 4 + .type DW.ref.__gcc_personality_v0, @object + .size DW.ref.__gcc_personality_v0, 4 +DW.ref.__gcc_personality_v0: + .long __gcc_personality_v0 +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_wait.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_wait.S new file mode 100644 index 00000000..b0a4e988 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_cond_wait.S @@ -0,0 +1,754 @@ +/* Copyright (C) 2003, 2004, 2006, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include "lowlevel-atomic.h" + + .text + +/* int pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex) */ + .globl __pthread_cond_wait + .type __pthread_cond_wait, @function + .protected __pthread_cond_wait + .align 5 +__pthread_cond_wait: +.LSTARTCODE: + mov.l r8, @-r15 +.Lpush_r8: + mov.l r9, @-r15 +.Lpush_r9: + mov.l r10, @-r15 +.Lpush_r10: + mov.l r11, @-r15 +.Lpush_r11: + mov.l r12, @-r15 +.Lpush_r12: + sts.l pr, @-r15 +.Lpush_pr: + add #-48, r15 +.Lalloc: + mov r4, r8 + mov r5, r9 +#ifdef __PIC__ + mova .Lgot0, r0 + mov.l .Lgot0, r12 + add r0, r12 +#endif + + /* Get internal lock. */ + mov #0, r3 + mov #1, r4 +#if cond_lock != 0 + CMPXCHG (r3, @(cond_lock,r8), r4, r2) +#else + CMPXCHG (r3, @r8, r4, r2) +#endif + bt 2f + bra 1f + nop +#ifdef __PIC__ + .align 2 +.Lgot0: + .long _GLOBAL_OFFSET_TABLE_ +#endif + +2: + /* Store the reference to the mutex. If there is already a + different value in there this is a bad user bug. */ + mov.l @(dep_mutex,r8),r0 + cmp/eq #-1, r0 + bt 15f + mov.l r9, @(dep_mutex,r8) + +15: + /* Unlock the mutex. */ + mov.l .Lmunlock0, r1 + mov #0, r5 + bsrf r1 + mov r9, r4 +.Lmunlock0b: + + tst r0, r0 + bt 0f + bra 12f + nop +0: + mov #1, r2 + mov #0, r3 + + clrt + mov.l @(total_seq,r8),r0 + mov.l @(total_seq+4,r8),r1 + addc r2, r0 + addc r3, r1 + mov.l r0,@(total_seq,r8) + mov.l r1,@(total_seq+4,r8) + mov.l @(cond_futex,r8),r0 + add r2, r0 + mov.l r0,@(cond_futex,r8) + mov #(1 << nwaiters_shift), r2 + mov.l @(cond_nwaiters,r8), r0 + add r2, r0 + mov.l r0, @(cond_nwaiters,r8) + + /* Get and store current wakeup_seq value. */ + mov.l @(wakeup_seq,r8), r10 + mov.l @(wakeup_seq+4,r8), r11 + mov.l @(broadcast_seq,r8), r0 + mov.l r0, @(4,r15) + +8: + mov.l @(cond_futex,r8),r0 + mov.l r0, @(8,r15) + + /* Unlock. */ +#if cond_lock != 0 + DEC (@(cond_lock,r8), r2) +#else + DEC (@r8, r2) +#endif + tst r2, r2 + bf 3f +4: +.LcleanupSTART: + mov.l .Lenable0, r1 + bsrf r1 + nop +.Lenable0b: + mov.l r0, @r15 + + mov #0, r7 + mov.l @(dep_mutex,r8), r0 + cmp/eq #-1, r0 + bt/s 99f + mov #FUTEX_WAIT, r5 +#ifdef __ASSUME_PRIVATE_FUTEX + mov #(FUTEX_WAIT|FUTEX_PRIVATE_FLAG), r5 + extu.b r5, r5 +#else + stc gbr, r1 + mov.w .Lpfoff0, r2 + add r2, r1 + mov.l @r1, r5 + mov #FUTEX_WAIT, r0 + or r0, r5 +#endif +99: + mov.l @(8,r15), r6 + mov r8, r4 + add #cond_futex, r4 + mov #SYS_futex, r3 + extu.b r3, r3 + trapa #0x14 + SYSCALL_INST_PAD + + mov.l .Ldisable0, r1 + bsrf r1 + mov.l @r15, r4 +.Ldisable0b: +.LcleanupEND: + + /* Lock. */ + mov #0, r3 + mov #1, r4 +#if cond_lock != 0 + CMPXCHG (r3, @(cond_lock,r8), r4, r2) +#else + CMPXCHG (r3, @r8, r4, r2) +#endif + bf 5f +6: + mov.l @(broadcast_seq,r8), r0 + mov.l @(4,r15), r1 + cmp/eq r0, r1 + bf 16f + + mov.l @(woken_seq,r8), r0 + mov.l @(woken_seq+4,r8), r1 + + mov.l @(wakeup_seq,r8), r2 + mov.l @(wakeup_seq+4,r8), r3 + + cmp/eq r3, r11 + bf 7f + cmp/eq r2, r10 + bt 8b +7: + cmp/eq r1, r3 + bf 9f + cmp/eq r0, r2 + bt 8b +9: + mov #1, r2 + mov #0, r3 + + clrt + mov.l @(woken_seq,r8),r0 + mov.l @(woken_seq+4,r8),r1 + addc r2, r0 + addc r3, r1 + mov.l r0,@(woken_seq,r8) + mov.l r1,@(woken_seq+4,r8) + +16: + mov #(1 << nwaiters_shift), r2 + mov.l @(cond_nwaiters,r8),r0 + sub r2, r0 + mov.l r0,@(cond_nwaiters,r8) + + /* Wake up a thread which wants to destroy the condvar object. */ + mov.l @(total_seq,r8),r0 + mov.l @(total_seq+4,r8),r1 + and r1, r0 + not r0, r0 + cmp/eq #0, r0 + bf/s 17f + mov #((1 << nwaiters_shift) - 1), r1 + not r1, r1 + mov.l @(cond_nwaiters,r8),r0 + tst r1, r0 + bf 17f + + mov r8, r4 + add #cond_nwaiters, r4 + mov.l @(dep_mutex,r8), r0 + cmp/eq #-1, r0 + bt/s 99f + mov #FUTEX_WAKE, r5 +#ifdef __ASSUME_PRIVATE_FUTEX + mov #(FUTEX_WAKE|FUTEX_PRIVATE_FLAG), r5 + extu.b r5, r5 +#else + stc gbr, r1 + mov.w .Lpfoff0, r2 + add r2, r1 + mov.l @r1, r5 + mov #FUTEX_WAKE, r0 + or r0, r5 +#endif +99: + mov #1, r6 + mov #0, r7 + mov #SYS_futex, r3 + extu.b r3, r3 + trapa #0x14 + SYSCALL_INST_PAD + +17: +#if cond_lock != 0 + DEC (@(cond_lock,r8), r2) +#else + DEC (@r8, r2) +#endif + tst r2, r2 + bf 10f + +11: + mov.l .Lmlocki0, r1 + bsrf r1 + mov r9, r4 +.Lmlocki0b: + /* We return the result of the mutex_lock operation. */ + +14: + add #48, r15 + lds.l @r15+, pr + mov.l @r15+, r12 + mov.l @r15+, r11 + mov.l @r15+, r10 + mov.l @r15+, r9 + rts + mov.l @r15+, r8 + +#ifndef __ASSUME_PRIVATE_FUTEX +.Lpfoff0: + .word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE +#endif + .align 2 +.Lmunlock0: + .long __pthread_mutex_unlock_usercnt-.Lmunlock0b +.Lenable0: + .long __pthread_enable_asynccancel-.Lenable0b +.Ldisable0: + .long __pthread_disable_asynccancel-.Ldisable0b +.Lmlocki0: + .long __pthread_mutex_cond_lock-.Lmlocki0b + +1: + /* Initial locking failed. */ + mov r8, r5 +#if cond_lock != 0 + add #cond_lock, r5 +#endif + mov.l @(dep_mutex,r8), r0 + cmp/eq #-1, r0 + bf/s 99f + mov #LLL_PRIVATE, r6 + mov #LLL_SHARED, r6 +99: + extu.b r6, r6 + mov.l .Lwait0, r1 + bsrf r1 + mov r2, r4 +.Lwait0b: + bra 2b + nop +3: + /* Unlock in loop requires waekup. */ + mov r8, r4 +#if cond_lock != 0 + add #cond_lock, r4 +#endif + mov.l @(dep_mutex,r8), r0 + cmp/eq #-1, r0 + bf/s 99f + mov #LLL_PRIVATE, r5 + mov #LLL_SHARED, r5 +99: + mov.l .Lwake0, r1 + bsrf r1 + extu.b r5, r5 +.Lwake0b: + bra 4b + nop + +5: + /* Locking in loop failed. */ + mov r8, r5 +#if cond_lock != 0 + add #cond_lock, r5 +#endif + mov.l @(dep_mutex,r8), r0 + cmp/eq #-1, r0 + bf/s 99f + mov #LLL_PRIVATE, r6 + mov #LLL_SHARED, r6 +99: + extu.b r6, r6 + mov.l .Lwait1, r1 + bsrf r1 + mov r2, r4 +.Lwait1b: + bra 6b + nop + +10: + /* Unlock after loop requires wakeup. */ + mov r8, r4 +#if cond_lock != 0 + add #cond_lock, r4 +#endif + mov.l @(dep_mutex,r8), r0 + cmp/eq #-1, r0 + bf/s 99f + mov #LLL_PRIVATE, r5 + mov #LLL_SHARED, r5 +99: + mov.l .Lwake1, r1 + bsrf r1 + extu.b r5, r5 +.Lwake1b: + bra 11b + nop + +12: + /* The initial unlocking of the mutex failed. */ + mov.l r0, @(12,r15) +#if cond_lock != 0 + DEC (@(cond_lock,r8), r2) +#else + DEC (@r8, r2) +#endif + tst r2, r2 + bf 13f + + mov r8, r4 +#if cond_lock != 0 + add #cond_lock, r4 +#endif + mov.l @(dep_mutex,r8), r0 + cmp/eq #-1, r0 + bf/s 99f + mov #LLL_PRIVATE, r5 + mov #LLL_SHARED, r5 +99: + mov.l .Lwake2, r1 + bsrf r1 + extu.b r5, r5 +.Lwake2b: + +13: + bra 14b + mov.l @(12,r15), r0 + + .align 2 +.Lwait0: + .long __lll_lock_wait-.Lwait0b +.Lwake0: + .long __lll_unlock_wake-.Lwake0b +.Lwait1: + .long __lll_lock_wait-.Lwait1b +.Lwake1: + .long __lll_unlock_wake-.Lwake1b +.Lwake2: + .long __lll_unlock_wake-.Lwake2b + .size __pthread_cond_wait, .-__pthread_cond_wait +weak_alias (__pthread_cond_wait, pthread_cond_wait) + + + .type __condvar_w_cleanup, @function +__condvar_w_cleanup: + mov r4, r11 + + /* Get internal lock. */ + mov #0, r3 + mov #1, r4 +#if cond_lock != 0 + CMPXCHG (r3, @(cond_lock,r8), r4, r2) +#else + CMPXCHG (r3, @r8, r4, r2) +#endif + bt 1f + nop + + mov r8, r5 +#if cond_lock != 0 + add #cond_lock, r5 +#endif + mov.l @(dep_mutex,r8), r0 + cmp/eq #-1, r0 + bf/s 99f + mov #LLL_PRIVATE, r6 + mov #LLL_SHARED, r6 +99: + extu.b r6, r6 + mov.l .Lwait3, r1 + bsrf r1 + mov r2, r4 +.Lwait3b: + +1: + mov.l @(broadcast_seq,r8), r0 + mov.l @(4,r15), r1 + cmp/eq r0, r1 + bf 3f + + mov #1, r2 + mov #0, r3 + + /* We increment the wakeup_seq counter only if it is lower than + total_seq. If this is not the case the thread was woken and + then canceled. In this case we ignore the signal. */ + mov.l @(total_seq+4,r8), r0 + mov.l @(wakeup_seq+4,r8), r1 + cmp/hi r1, r0 + bt/s 6f + cmp/hi r0, r1 + bt 7f + mov.l @(total_seq,r8), r0 + mov.l @(wakeup_seq,r8), r1 + cmp/hs r0, r1 + bt 7f + +6: + clrt + mov.l @(wakeup_seq,r8),r0 + mov.l @(wakeup_seq+4,r8),r1 + addc r2, r0 + addc r3, r1 + mov.l r0,@(wakeup_seq,r8) + mov.l r1,@(wakeup_seq+4,r8) + mov.l @(cond_futex,r8),r0 + add r2, r0 + mov.l r0,@(cond_futex,r8) + +7: + clrt + mov.l @(woken_seq,r8),r0 + mov.l @(woken_seq+4,r8),r1 + addc r2, r0 + addc r3, r1 + mov.l r0,@(woken_seq,r8) + mov.l r1,@(woken_seq+4,r8) + +3: + mov #(1 << nwaiters_shift), r2 + mov.l @(cond_nwaiters,r8),r0 + sub r2, r0 + mov.l r0,@(cond_nwaiters,r8) + + /* Wake up a thread which wants to destroy the condvar object. */ + mov #0, r10 + mov.l @(total_seq,r8),r0 + mov.l @(total_seq+4,r8),r1 + and r1, r0 + not r0, r0 + cmp/eq #0, r0 + bf/s 4f + mov #((1 << nwaiters_shift) - 1), r1 + not r1, r1 + mov.l @(cond_nwaiters,r8),r0 + tst r1, r0 + bf 4f + + mov r8, r4 + add #cond_nwaiters, r4 + mov.l @(dep_mutex,r8), r0 + cmp/eq #-1, r0 + bt/s 99f + mov #FUTEX_WAKE, r5 +#ifdef __ASSUME_PRIVATE_FUTEX + mov #(FUTEX_WAKE|FUTEX_PRIVATE_FLAG), r5 + extu.b r5, r5 +#else + stc gbr, r1 + mov.w .Lpfoff1, r2 + add r2, r1 + mov.l @r1, r5 + mov #FUTEX_WAKE, r0 + or r0, r5 +#endif +99: + mov #1, r6 + mov #0, r7 + mov #SYS_futex, r3 + extu.b r3, r3 + trapa #0x14 + SYSCALL_INST_PAD + mov #1, r10 + +4: +#if cond_lock != 0 + DEC (@(cond_lock,r8), r2) +#else + DEC (@r8, r2) +#endif + tst r2, r2 + bt 2f + + mov r8, r4 +#if cond_lock != 0 + add #cond_lock, r4 +#endif + mov.l @(dep_mutex,r8), r0 + cmp/eq #-1, r0 + bf/s 99f + mov #LLL_PRIVATE, r5 + mov #LLL_SHARED, r5 +99: + mov.l .Lwake3, r1 + bsrf r1 + extu.b r5, r5 +.Lwake3b: + +2: + /* Wake up all waiters to make sure no signal gets lost. */ + tst r10, r10 + bf/s 5f + mov r8, r4 + add #cond_futex, r4 + mov.l @(dep_mutex,r8), r0 + cmp/eq #-1, r0 + bt/s 99f + mov #FUTEX_WAKE, r5 +#ifdef __ASSUME_PRIVATE_FUTEX + mov #(FUTEX_WAKE|FUTEX_PRIVATE_FLAG), r5 + extu.b r5, r5 +#else + stc gbr, r1 + mov.w .Lpfoff1, r2 + add r2, r1 + mov.l @r1, r5 + mov #FUTEX_WAKE, r0 + or r0, r5 +#endif +99: + mov #-1, r6 + shlr r6 /* r6 = 0x7fffffff */ + mov #0, r7 + mov #SYS_futex, r3 + extu.b r3, r3 + trapa #0x14 + SYSCALL_INST_PAD + +5: + mov.l .Lmlocki3, r1 + bsrf r1 + mov r9, r4 +.Lmlocki3b: + +.LcallUR: + mov.l .Lresume, r1 +#ifdef __PIC__ + add r12, r1 +#endif + jsr @r1 + mov r11, r4 + sleep + +#ifndef __ASSUME_PRIVATE_FUTEX +.Lpfoff1: + .word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE +#endif + .align 2 +.Lwait3: + .long __lll_lock_wait-.Lwait3b +.Lwake3: + .long __lll_unlock_wake-.Lwake3b +.Lmlocki3: + .long __pthread_mutex_cond_lock-.Lmlocki3b +.Lresume: +#ifdef __PIC__ + .long _Unwind_Resume@GOTOFF +#else + .long _Unwind_Resume +#endif +.LENDCODE: + .size __condvar_w_cleanup, .-__condvar_w_cleanup + + + .section .gcc_except_table,"a",@progbits +.LexceptSTART: + .byte 0xff ! @LPStart format (omit) + .byte 0xff ! @TType format (omit) + .byte 0x0b ! call-site format + ! DW_EH_PE_sdata4 + .uleb128 .Lcstend-.Lcstbegin +.Lcstbegin: + .ualong .LcleanupSTART-.LSTARTCODE + .ualong .LcleanupEND-.LcleanupSTART + .ualong __condvar_w_cleanup-.LSTARTCODE + .uleb128 0 + .ualong .LcallUR-.LSTARTCODE + .ualong .LENDCODE-.LcallUR + .ualong 0 + .uleb128 0 +.Lcstend: + + .section .eh_frame,"a",@progbits +.LSTARTFRAME: + .ualong .LENDCIE-.LSTARTCIE ! Length of the CIE. +.LSTARTCIE: + .ualong 0 ! CIE ID. + .byte 1 ! Version number. +#ifdef SHARED + .string "zPLR" ! NUL-terminated augmentation + ! string. +#else + .string "zPL" ! NUL-terminated augmentation + ! string. +#endif + .uleb128 1 ! Code alignment factor. + .sleb128 -4 ! Data alignment factor. + .byte 0x11 ! Return address register + ! column. +#ifdef SHARED + .uleb128 7 ! Augmentation value length. + .byte 0x9b ! Personality: DW_EH_PE_pcrel + ! + DW_EH_PE_sdata4 + ! + DW_EH_PE_indirect + .ualong DW.ref.__gcc_personality_v0-. + .byte 0x1b ! LSDA Encoding: DW_EH_PE_pcrel + ! + DW_EH_PE_sdata4. + .byte 0x1b ! FDE Encoding: DW_EH_PE_pcrel + ! + DW_EH_PE_sdata4. +#else + .uleb128 6 ! Augmentation value length. + .byte 0x0 ! Personality: absolute + .ualong __gcc_personality_v0 + .byte 0x0 ! LSDA Encoding: absolute +#endif + .byte 0x0c ! DW_CFA_def_cfa + .uleb128 0xf + .uleb128 0 + .align 2 +.LENDCIE: + + .ualong .LENDFDE-.LSTARTFDE ! Length of the FDE. +.LSTARTFDE: + .ualong .LSTARTFDE-.LSTARTFRAME ! CIE pointer. +#ifdef SHARED + .ualong .LSTARTCODE-. ! PC-relative start address + ! of the code. +#else + .ualong .LSTARTCODE ! Start address of the code. +#endif + .ualong .LENDCODE-.LSTARTCODE ! Length of the code. + .uleb128 4 ! Augmentation size +#ifdef SHARED + .ualong .LexceptSTART-. +#else + .ualong .LexceptSTART +#endif + .byte 0x4 + .ualong .Lpush_r8-.LSTARTCODE + .byte 0xe + .uleb128 4 + .byte 0x88 + .uleb128 1 + .byte 0x4 + .ualong .Lpush_r9-.Lpush_r8 + .byte 0xe + .uleb128 8 + .byte 0x89 + .uleb128 2 + .byte 0x4 + .ualong .Lpush_r10-.Lpush_r9 + .byte 0xe + .uleb128 12 + .byte 0x8a + .uleb128 3 + .byte 0x4 + .ualong .Lpush_r11-.Lpush_r10 + .byte 0xe + .uleb128 16 + .byte 0x8b + .uleb128 4 + .byte 0x4 + .ualong .Lpush_r12-.Lpush_r11 + .byte 0xe + .uleb128 20 + .byte 0x8c + .uleb128 5 + .byte 0x4 + .ualong .Lpush_pr-.Lpush_r12 + .byte 0xe + .uleb128 24 + .byte 0x91 + .uleb128 6 + .byte 0x4 + .ualong .Lalloc-.Lpush_pr + .byte 0xe + .uleb128 72 + .align 2 +.LENDFDE: + +#ifdef SHARED + .hidden DW.ref.__gcc_personality_v0 + .weak DW.ref.__gcc_personality_v0 + .section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits + .align 4 + .type DW.ref.__gcc_personality_v0, @object + .size DW.ref.__gcc_personality_v0, 4 +DW.ref.__gcc_personality_v0: + .long __gcc_personality_v0 +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_once.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_once.S new file mode 100644 index 00000000..46234459 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_once.S @@ -0,0 +1,263 @@ +/* Copyright (C) 2003, 2004, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include "lowlevel-atomic.h" + + + .comm __fork_generation, 4, 4 + + .text + .globl __pthread_once + .type __pthread_once,@function + .protected __pthread_once + .align 5 + cfi_startproc +__pthread_once: + mov.l @r4, r0 + tst #2, r0 + bt 1f + rts + mov #0, r0 + +1: + mov.l r12, @-r15 + cfi_adjust_cfa_offset (4) + cfi_rel_offset (r12, 0) + mov.l r9, @-r15 + cfi_adjust_cfa_offset (4) + cfi_rel_offset (r9, 0) + mov.l r8, @-r15 + cfi_adjust_cfa_offset (4) + cfi_rel_offset (r8, 0) + sts.l pr, @-r15 + cfi_adjust_cfa_offset (4) + cfi_rel_offset (pr, 0) + mov r5, r8 + mov r4, r9 + + /* Not yet initialized or initialization in progress. + Get the fork generation counter now. */ +6: + mov.l @r4, r1 + mova .Lgot, r0 + mov.l .Lgot, r12 + add r0, r12 + +5: + mov r1, r0 + + tst #2, r0 + bf 4f + + and #3, r0 + mov.l .Lfgen, r2 +#ifdef __PIC__ + add r12, r2 +#endif + mov.l @r2, r3 + or r3, r0 + or #1, r0 + mov r0, r3 + mov r1, r5 + + CMPXCHG (r5, @r4, r3, r2) + bf 5b + + /* Check whether another thread already runs the initializer. */ + mov r2, r0 + tst #1, r0 + bt 3f /* No -> do it. */ + + /* Check whether the initializer execution was interrupted + by a fork. */ + xor r3, r0 + mov #-4, r1 /* -4 = 0xfffffffc */ + tst r1, r0 + bf 3f /* Different for generation -> run initializer. */ + + /* Somebody else got here first. Wait. */ +#ifdef __ASSUME_PRIVATE_FUTEX + mov #(FUTEX_PRIVATE_FLAG|FUTEX_WAIT), r5 + extu.b r5, r5 +#else + stc gbr, r1 + mov.w .Lpfoff, r2 + add r2, r1 + mov.l @r1, r5 +# if FUTEX_WAIT != 0 + mov #FUTEX_WAIT, r0 + or r0, r5 +# endif +#endif + mov r3, r6 + mov #0, r7 + mov #SYS_futex, r3 + extu.b r3, r3 + trapa #0x14 + SYSCALL_INST_PAD + bra 6b + nop + + .align 2 +.Lgot: + .long _GLOBAL_OFFSET_TABLE_ +#ifdef __PIC__ +.Lfgen: + .long __fork_generation@GOTOFF +#else +.Lfgen: + .long __fork_generation +#endif + +3: + /* Call the initializer function after setting up the + cancellation handler. Note that it is not possible here + to use the unwind-based cleanup handling. This would require + that the user-provided function and all the code it calls + is compiled with exceptions. Unfortunately this cannot be + guaranteed. */ + add #-UNWINDBUFSIZE, r15 + cfi_adjust_cfa_offset (UNWINDBUFSIZE) + + mov.l .Lsigsetjmp, r1 + mov #UWJMPBUF, r4 + add r15, r4 + bsrf r1 + mov #0, r5 +.Lsigsetjmp0: + tst r0, r0 + bf 7f + + mov.l .Lcpush, r1 + bsrf r1 + mov r15, r4 +.Lcpush0: + + /* Call the user-provided initialization function. */ + jsr @r8 + nop + + /* Pop the cleanup handler. */ + mov.l .Lcpop, r1 + bsrf r1 + mov r15, r4 +.Lcpop0: + + add #UNWINDBUFSIZE, r15 + cfi_adjust_cfa_offset (-UNWINDBUFSIZE) + + /* Sucessful run of the initializer. Signal that we are done. */ + INC (@r9, r2) + /* Wake up all other threads. */ + mov r9, r4 +#ifdef __ASSUME_PRIVATE_FUTEX + mov #(FUTEX_PRIVATE_FLAG|FUTEX_WAKE), r5 + extu.b r5, r5 +#else + stc gbr, r1 + mov.w .Lpfoff, r2 + add r2, r1 + mov.l @r1, r5 + mov #FUTEX_WAKE, r0 + or r0, r5 +#endif + mov #-1, r6 + shlr r6 /* r6 = 0x7fffffff */ + mov #0, r7 + mov #SYS_futex, r3 + extu.b r3, r3 + trapa #0x14 + SYSCALL_INST_PAD + +4: + lds.l @r15+, pr + cfi_adjust_cfa_offset (-4) + cfi_restore (pr) + mov.l @r15+, r8 + cfi_adjust_cfa_offset (-4) + cfi_restore (r8) + mov.l @r15+, r9 + cfi_adjust_cfa_offset (-4) + cfi_restore (r9) + mov.l @r15+, r12 + cfi_adjust_cfa_offset (-4) + cfi_restore (r12) + rts + mov #0, r0 + +7: + /* __sigsetjmp returned for the second time. */ + cfi_adjust_cfa_offset (UNWINDBUFSIZE+16) + cfi_offset (r12, -4) + cfi_offset (r9, -8) + cfi_offset (r8, -12) + cfi_offset (pr, -16) + mov #0, r7 + mov.l r7, @r9 + mov r9, r4 +#ifdef __ASSUME_PRIVATE_FUTEX + mov #(FUTEX_PRIVATE_FLAG|FUTEX_WAKE), r5 +#else + stc gbr, r1 + mov.w .Lpfoff, r2 + add r2, r1 + mov.l @r1, r5 + mov #FUTEX_WAKE, r0 + or r0, r5 +#endif + extu.b r5, r5 + mov #-1, r6 + shlr r6 /* r6 = 0x7fffffff */ + mov #SYS_futex, r3 + extu.b r3, r3 + trapa #0x14 + SYSCALL_INST_PAD + + mov.l .Lunext, r1 + bsrf r1 + mov r15, r4 +.Lunext0: + /* NOTREACHED */ + sleep + cfi_endproc + +#ifndef __ASSUME_PRIVATE_FUTEX +.Lpfoff: + .word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE +#endif + .align 2 +.Lsigsetjmp: + .long __sigsetjmp@PLT-(.Lsigsetjmp0-.) +.Lcpush: + .long HIDDEN_JUMPTARGET(__pthread_register_cancel)-.Lcpush0 +.Lcpop: + .long HIDDEN_JUMPTARGET(__pthread_unregister_cancel)-.Lcpop0 +.Lunext: + .long HIDDEN_JUMPTARGET(__pthread_unwind_next)-.Lunext0 + .size __pthread_once,.-__pthread_once + + .globl __pthread_once_internal +__pthread_once_internal = __pthread_once + + .globl pthread_once +pthread_once = __pthread_once diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_rdlock.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_rdlock.S new file mode 100644 index 00000000..21e05e19 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_rdlock.S @@ -0,0 +1,255 @@ +/* Copyright (C) 2003, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include +#include "lowlevel-atomic.h" + + + .text + + .globl __pthread_rwlock_rdlock + .type __pthread_rwlock_rdlock,@function + .protected __pthread_rwlock_rdlock + .align 5 +__pthread_rwlock_rdlock: + mov.l r12, @-r15 + mov.l r9, @-r15 + mov.l r8, @-r15 + sts.l pr, @-r15 + mov r4, r8 + + /* Get the lock. */ + mov #0, r3 + mov #1, r4 +#if MUTEX == 0 + CMPXCHG (r3, @r8, r4, r2) +#else + CMPXCHG (r3, @(MUTEX,r8), r4, r2) +#endif + bf 1f +2: + mov.l @(WRITER,r8), r0 + tst r0, r0 + bf 14f + mov.l @(WRITERS_QUEUED,r8), r0 + tst r0, r0 + bt 5f + mov #FLAGS, r0 + mov.b @(r0,r8), r0 + tst r0, r0 + bt 5f +3: + mov.l @(READERS_QUEUED,r8), r0 + add #1, r0 + mov.l r0, @(READERS_QUEUED,r8) + tst r0, r0 + bt 4f + + mov.l @(READERS_WAKEUP,r8), r9 + +#if MUTEX == 0 + DEC (@r8, r2) +#else + DEC (@(MUTEX,r8), r2) +#endif + tst r2, r2 + bf 10f +11: +#ifdef __ASSUME_PRIVATE_FUTEX + mov #PSHARED, r0 + mov.b @(r0,r8), r5 + mov #(FUTEX_PRIVATE_FLAG|FUTEX_WAIT), r0 + xor r0, r5 + extu.b r5, r5 +#else + mov #PSHARED, r0 + mov.b @(r0,r8), r5 + extu.b r5, r5 +# if FUTEX_WAIT != 0 + mov #FUTEX_WAIT, r0 + or r0, r5 +# endif + stc gbr, r1 + mov.w .Lpfoff, r2 + add r2, r1 + mov.l @r1, r0 + xor r0, r5 +#endif + mov r8, r4 + add #READERS_WAKEUP, r4 + mov r9, r6 + mov #0, r7 + mov #SYS_futex, r3 + extu.b r3, r3 + trapa #0x14 + SYSCALL_INST_PAD + + /* Reget the lock. */ + mov #0, r3 + mov #1, r4 +#if MUTEX == 0 + CMPXCHG (r3, @r8, r4, r2) +#else + CMPXCHG (r3, @(MUTEX,r8), r4, r2) +#endif + bf 12f +13: + mov.l @(READERS_QUEUED,r8), r0 + add #-1, r0 + bra 2b + mov.l r0, @(READERS_QUEUED,r8) + +5: + mov #0, r3 + mov.l @(NR_READERS,r8), r0 + add #1, r0 + mov.l r0, @(NR_READERS,r8) + tst r0, r0 + bt 8f + +9: +#if MUTEX == 0 + DEC (@r8, r2) +#else + DEC (@(MUTEX,r8), r2) +#endif + tst r2, r2 + bf 6f +7: + lds.l @r15+, pr + mov.l @r15+, r8 + mov.l @r15+, r9 + mov.l @r15+, r12 + rts + mov r3, r0 + +#ifndef __ASSUME_PRIVATE_FUTEX +.Lpfoff: + .word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE +#endif + +1: + mov r8, r5 +#if MUTEX != 0 + add #MUTEX, r5 +#endif + mov #PSHARED, r0 + mov.b @(r0,r8), r6 + extu.b r6, r6 + mov.l .Lwait0, r1 + bsrf r1 + mov r2, r4 +.Lwait0b: + bra 2b + nop +14: + stc gbr, r1 + mov.w .Ltidoff, r2 + add r2, r1 + mov.l @r1, r1 + cmp/eq r1, r0 + bf 3b + /* Deadlock detected. */ + bra 9b + mov #EDEADLK, r3 + +.Ltidoff: + .word TID - TLS_PRE_TCB_SIZE + +6: + mov r8, r4 +#if MUTEX != 0 + add #MUTEX, r4 +#endif + mov #PSHARED, r0 + mov.b @(r0,r8), r5 + extu.b r5, r5 + mov.l .Lwake0, r1 + bsrf r1 + nop +.Lwake0b: + bra 7b + mov #0, r3 + +8: + /* Overflow. */ + mov.l @(NR_READERS,r8), r1 + add #-1, r1 + mov.l r1, @(NR_READERS,r8) + bra 9b + mov #EAGAIN, r3 + +4: + /* Overflow. */ + mov.l @(READERS_QUEUED,r8), r1 + add #-1, r1 + mov.l r1, @(READERS_QUEUED,r8) + bra 9b + mov #EAGAIN, r3 + +10: + mov r8, r4 +#if MUTEX != 0 + add #MUTEX, r4 +#endif + mov #PSHARED, r0 + mov.b @(r0,r8), r5 + extu.b r5, r5 + mov.l .Lwake1, r1 + bsrf r1 + nop +.Lwake1b: + bra 11b + nop + +12: + mov r8, r5 +#if MUTEX != 0 + add #MUTEX, r5 +#endif + mov #PSHARED, r0 + mov.b @(r0,r8), r6 + extu.b r6, r6 + mov.l .Lwait1, r1 + bsrf r1 + mov r2, r4 +.Lwait1b: + bra 13b + nop + + .align 2 +.Lwait0: + .long __lll_lock_wait-.Lwait0b +.Lwake0: + .long __lll_unlock_wake-.Lwake0b +.Lwait1: + .long __lll_lock_wait-.Lwait1b +.Lwake1: + .long __lll_unlock_wake-.Lwake1b + .size __pthread_rwlock_rdlock,.-__pthread_rwlock_rdlock + + .globl pthread_rwlock_rdlock +pthread_rwlock_rdlock = __pthread_rwlock_rdlock + + .globl __pthread_rwlock_rdlock_internal +__pthread_rwlock_rdlock_internal = __pthread_rwlock_rdlock diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedrdlock.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedrdlock.S new file mode 100644 index 00000000..6e7af21e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedrdlock.S @@ -0,0 +1,314 @@ +/* Copyright (C) 2003, 2007, 2008 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include +#include "lowlevel-atomic.h" + + + .text + + .globl pthread_rwlock_timedrdlock + .type pthread_rwlock_timedrdlock,@function + .align 5 +pthread_rwlock_timedrdlock: + mov.l r12, @-r15 + mov.l r10, @-r15 + mov.l r9, @-r15 + mov.l r8, @-r15 + sts.l pr, @-r15 + add #-8, r15 + mov r4, r8 + mov r5, r9 + + /* Get the lock. */ + mov #0, r3 + mov #1, r4 +#if MUTEX == 0 + CMPXCHG (r3, @r8, r4, r2) +#else + CMPXCHG (r3, @(MUTEX,r8), r4, r2) +#endif + bf 1f +2: + mov.l @(WRITER,r8), r0 + tst r0, r0 + bf 14f + mov.l @(WRITERS_QUEUED,r8), r0 + tst r0, r0 + bt 5f + mov #FLAGS, r0 + mov.b @(r0,r8), r0 + tst r0, r0 + bt 5f +3: + /* Check the value of the timeout parameter. */ + mov.l .L1g0, r1 + mov.l @(4,r9), r0 + cmp/hs r1, r0 + bt 19f + + mov.l @(READERS_QUEUED,r8), r0 + add #1, r0 + mov.l r0, @(READERS_QUEUED,r8) + tst r0, r0 + bt 4f + + mov.l @(READERS_WAKEUP,r8), r10 + +#if MUTEX == 0 + DEC (@r8, r2) +#else + DEC (@(MUTEX,r8), r2) +#endif + tst r2, r2 + bf 10f + +11: + /* Get current time. */ + mov r15, r4 + mov #0, r5 + mov #__NR_gettimeofday, r3 + trapa #0x12 + SYSCALL_INST_PAD + + mov.l @(4,r15), r0 + mov.w .L1k0, r1 + dmulu.l r0, r1 /* Milli seconds to nano seconds. */ + mov.l @r9, r2 + mov.l @(4,r9), r3 + mov.l @r15, r0 + sts macl, r1 + sub r0, r2 + clrt + subc r1, r3 + bf 15f + mov.l .L1g0, r1 + add r1, r3 + add #-1, r2 +15: + cmp/pz r2 + bf 16f /* Time is already up. */ + + /* Store relative timeout. */ + mov.l r2, @r15 + mov.l r3, @(4,r15) + + /* Futex call. */ + mov r15, r7 +#ifdef __ASSUME_PRIVATE_FUTEX + mov #PSHARED, r0 + mov.b @(r0,r8), r5 + mov #(FUTEX_PRIVATE_FLAG|FUTEX_WAIT), r0 + xor r0, r5 + extu.b r5, r5 +#else + mov #PSHARED, r0 + mov.b @(r0,r8), r5 + extu.b r5, r5 +# if FUTEX_WAIT != 0 + mov #FUTEX_WAIT, r0 + or r0, r5 +# endif + stc gbr, r1 + mov.w .Lpfoff, r2 + add r2, r1 + mov.l @r1, r0 + xor r0, r5 +#endif + mov r10, r6 + mov r8, r4 + add #READERS_WAKEUP, r4 + mov #SYS_futex, r3 + extu.b r3, r3 + trapa #0x14 + SYSCALL_INST_PAD + mov r0, r3 + +17: + /* Reget the lock. */ + mov #0, r5 + mov #1, r4 +#if MUTEX == 0 + CMPXCHG (r5, @r8, r4, r2) +#else + CMPXCHG (r5, @(MUTEX,r8), r4, r2) +#endif + bf 12f + +13: + mov.l @(READERS_QUEUED,r8), r0 + add #-1, r0 + mov.l r0, @(READERS_QUEUED,r8) + mov #-ETIMEDOUT, r0 + cmp/eq r0, r3 + bf 2b + +18: + bra 9f + mov #ETIMEDOUT, r3 + +5: + mov #0, r3 + mov.l @(NR_READERS,r8), r0 + add #1, r0 + mov.l r0, @(NR_READERS,r8) + tst r0, r0 + bt 8f + +9: +#if MUTEX == 0 + DEC (@r8, r2) +#else + DEC (@(MUTEX,r8), r2) +#endif + tst r2, r2 + bf 6f +7: + add #8,r15 + lds.l @r15+, pr + mov.l @r15+, r8 + mov.l @r15+, r9 + mov.l @r15+, r10 + mov.l @r15+, r12 + rts + mov r3, r0 + +#ifndef __ASSUME_PRIVATE_FUTEX +.Lpfoff: + .word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE +#endif + .align 2 +.L1k0: + .long 1000 +.L1g0: + .long 1000000000 + +1: + mov r8, r5 +#if MUTEX != 0 + add #MUTEX, r5 +#endif + mov #PSHARED, r0 + mov.b @(r0,r8), r6 + extu.b r6, r6 + mov.l .Lwait2, r1 + bsrf r1 + mov r2, r4 +.Lwait2b: + bra 2b + nop +14: + stc gbr, r1 + mov.w .Ltidoff, r2 + add r2, r1 + mov.l @r1, r1 + cmp/eq r1, r0 + bf 3b + /* Deadlock detected. */ + bra 9b + mov #EDEADLK, r3 + +.Ltidoff: + .word TID - TLS_PRE_TCB_SIZE + +6: + mov r3, r10 + mov r8, r4 +#if MUTEX != 0 + add #MUTEX, r4 +#endif + mov #PSHARED, r0 + mov.b @(r0,r8), r5 + extu.b r5, r5 + mov.l .Lwake2, r1 + bsrf r1 + nop +.Lwake2b: + bra 7b + mov r10, r3 + +8: + /* Overflow. */ + mov.l @(NR_READERS,r8), r1 + add #-1, r1 + mov.l r1, @(NR_READERS,r8) + bra 9b + mov #EAGAIN, r3 + +4: + /* Overflow. */ + mov.l @(READERS_QUEUED,r8), r1 + add #-1, r1 + mov.l r1, @(READERS_QUEUED,r8) + bra 9b + mov #EAGAIN, r3 + +10: + mov r8, r4 +#if MUTEX != 0 + add #MUTEX, r4 +#endif + mov #PSHARED, r0 + mov.b @(r0,r8), r5 + extu.b r5, r5 + mov.l .Lwake3, r1 + bsrf r1 + nop +.Lwake3b: + bra 11b + nop + +12: + mov r3, r10 + mov r8, r5 +#if MUTEX != 0 + add #MUTEX, r5 +#endif + mov #PSHARED, r0 + mov.b @(r0,r8), r6 + extu.b r6, r6 + mov.l .Lwait3, r1 + bsrf r1 + mov r2, r4 +.Lwait3b: + bra 13b + mov r10, r3 + +16: + bra 17b + mov #-ETIMEDOUT, r3 + +19: + bra 9b + mov #EINVAL, r3 + + .align 2 +.Lwait2: + .long __lll_lock_wait-.Lwait2b +.Lwake2: + .long __lll_unlock_wake-.Lwake2b +.Lwait3: + .long __lll_lock_wait-.Lwait3b +.Lwake3: + .long __lll_unlock_wake-.Lwake3b + .size pthread_rwlock_timedrdlock,.-pthread_rwlock_timedrdlock diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedwrlock.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedwrlock.S new file mode 100644 index 00000000..1cb7cbdd --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_timedwrlock.S @@ -0,0 +1,298 @@ +/* Copyright (C) 2003, 2007, 2008 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include +#include "lowlevel-atomic.h" + + + .text + + .globl pthread_rwlock_timedwrlock + .type pthread_rwlock_timedwrlock,@function + .align 5 +pthread_rwlock_timedwrlock: + mov.l r12, @-r15 + mov.l r10, @-r15 + mov.l r9, @-r15 + mov.l r8, @-r15 + sts.l pr, @-r15 + add #-8, r15 + mov r4, r8 + mov r5, r9 + + /* Get the lock. */ + mov #0, r3 + mov #1, r4 +#if MUTEX == 0 + CMPXCHG (r3, @r8, r4, r2) +#else + CMPXCHG (r3, @(MUTEX,r8), r4, r2) +#endif + bf 1f +2: + mov.l @(WRITER,r8), r0 + tst r0, r0 + bf 14f + mov.l @(NR_READERS,r8), r0 + tst r0, r0 + bt 5f +3: + /* Check the value of the timeout parameter. */ + mov.l .L1g1, r1 + mov.l @(4,r9), r0 + cmp/hs r1, r0 + bt 19f + + mov.l @(WRITERS_QUEUED,r8), r0 + add #1, r0 + mov.l r0, @(WRITERS_QUEUED,r8) + tst r0, r0 + bt 4f + + mov.l @(WRITERS_WAKEUP,r8), r10 + +#if MUTEX == 0 + DEC (@r8, r2) +#else + DEC (@(MUTEX,r8), r2) +#endif + tst r2, r2 + bf 10f + +11: + /* Get current time. */ + mov r15, r4 + mov #0, r5 + mov #__NR_gettimeofday, r3 + trapa #0x12 + SYSCALL_INST_PAD + + mov.l @(4,r15), r0 + mov.w .L1k1, r1 + dmulu.l r0, r1 /* Milli seconds to nano seconds. */ + mov.l @r9, r2 + mov.l @(4,r9), r3 + mov.l @r15, r0 + sts macl, r1 + sub r0, r2 + clrt + subc r1, r3 + bf 15f + mov.l .L1g1, r1 + add r1, r3 + add #-1, r2 +15: + cmp/pz r2 + bf 16f /* Time is already up. */ + + /* Store relative timeout. */ + mov.l r2, @r15 + mov.l r3, @(4,r15) + + /* Futex call. */ + mov r15, r7 +#ifdef __ASSUME_PRIVATE_FUTEX + mov #PSHARED, r0 + mov.b @(r0,r8), r5 + mov #(FUTEX_PRIVATE_FLAG|FUTEX_WAIT), r0 + xor r0, r5 + extu.b r5, r5 +#else + mov #PSHARED, r0 + mov.b @(r0,r8), r5 + extu.b r5, r5 +# if FUTEX_WAIT != 0 + mov #FUTEX_WAIT, r0 + or r0, r5 +# endif + stc gbr, r1 + mov.w .Lpfoff, r2 + add r2, r1 + mov.l @r1, r0 + xor r0, r5 +#endif + mov r10, r6 + mov r8, r4 + add #WRITERS_WAKEUP, r4 + mov #SYS_futex, r3 + extu.b r3, r3 + trapa #0x14 + SYSCALL_INST_PAD + mov r0, r3 + +17: + /* Reget the lock. */ + mov #0, r5 + mov #1, r4 +#if MUTEX == 0 + CMPXCHG (r5, @r8, r4, r2) +#else + CMPXCHG (r5, @(MUTEX,r8), r4, r2) +#endif + bf 12f + +13: + mov.l @(WRITERS_QUEUED,r8), r0 + add #-1, r0 + mov.l r0, @(WRITERS_QUEUED,r8) + mov #-ETIMEDOUT, r0 + cmp/eq r0, r3 + bf 2b + +18: + bra 9f + mov #ETIMEDOUT, r3 + +19: + bra 9f + mov #EINVAL, r3 + +5: + mov #0, r3 + stc gbr, r0 + mov.w .Ltidoff, r1 + mov.l @(r0,r1), r0 + mov.l r0, @(WRITER,r8) +9: +#if MUTEX == 0 + DEC (@r8, r2) +#else + DEC (@(MUTEX,r8), r2) +#endif + tst r2, r2 + bf 6f +7: + add #8,r15 + lds.l @r15+, pr + mov.l @r15+, r8 + mov.l @r15+, r9 + mov.l @r15+, r10 + mov.l @r15+, r12 + rts + mov r3, r0 + +#ifndef __ASSUME_PRIVATE_FUTEX +.Lpfoff: + .word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE +#endif +.L1k1: + .word 1000 + .align 2 +.L1g1: + .long 1000000000 + +1: + mov r8, r5 +#if MUTEX != 0 + add #MUTEX, r5 +#endif + mov #PSHARED, r0 + mov.b @(r0,r8), r6 + extu.b r6, r6 + mov.l .Lwait6, r1 + bsrf r1 + mov r2, r4 +.Lwait6b: + bra 2b + nop +14: + stc gbr, r1 + mov.w .Ltidoff, r2 + add r2, r1 + mov.l @r1, r1 + cmp/eq r1, r0 + bf 3b + bra 9b + mov #EDEADLK, r3 +6: + mov r3, r10 + mov r8, r4 +#if MUTEX != 0 + add #MUTEX, r4 +#endif + mov #PSHARED, r0 + mov.b @(r0,r8), r5 + extu.b r5, r5 + mov.l .Lwake6, r1 + bsrf r1 + nop +.Lwake6b: + bra 7b + mov r10, r3 + +.Ltidoff: + .word TID - TLS_PRE_TCB_SIZE + +4: + /* Overflow. */ + mov.l @(WRITERS_QUEUED,r8), r1 + add #-1, r1 + mov.l r1, @(WRITERS_QUEUED,r8) + bra 9b + mov #EAGAIN, r3 + +10: + mov r8, r4 +#if MUTEX != 0 + add #MUTEX, r4 +#endif + mov #PSHARED, r0 + mov.b @(r0,r8), r5 + extu.b r5, r5 + mov.l .Lwake7, r1 + bsrf r1 + nop +.Lwake7b: + bra 11b + nop + +12: + mov r3, r10 + mov r8, r5 +#if MUTEX != 0 + add #MUTEX, r5 +#endif + mov #PSHARED, r0 + mov.b @(r0,r8), r6 + extu.b r6, r6 + mov.l .Lwait7, r1 + bsrf r1 + mov r2, r4 +.Lwait7b: + bra 13b + mov r10, r3 + +16: + bra 17b + mov #-ETIMEDOUT, r3 + + .align 2 +.Lwait6: + .long __lll_lock_wait-.Lwait6b +.Lwake6: + .long __lll_unlock_wake-.Lwake6b +.Lwait7: + .long __lll_lock_wait-.Lwait7b +.Lwake7: + .long __lll_unlock_wake-.Lwake7b + .size pthread_rwlock_timedwrlock,.-pthread_rwlock_timedwrlock diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_unlock.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_unlock.S new file mode 100644 index 00000000..1f6c1d81 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_unlock.S @@ -0,0 +1,199 @@ +/* Copyright (C) 2003, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include "lowlevel-atomic.h" + + + .text + + .globl __pthread_rwlock_unlock + .type __pthread_rwlock_unlock,@function + .protected __pthread_rwlock_unlock + .align 5 +__pthread_rwlock_unlock: + mov.l r12, @-r15 + mov.l r8, @-r15 + sts.l pr, @-r15 + mov r4, r8 + + /* Get the lock. */ + mov #0, r3 + mov #1, r4 +#if MUTEX == 0 + CMPXCHG (r3, @r8, r4, r2) +#else + CMPXCHG (r3, @(MUTEX,r8), r4, r2) +#endif + bf 1f +2: + mov.l @(WRITER,r8), r0 + tst r0, r0 + bf 5f + mov.l @(NR_READERS,r8), r0 + add #-1, r0 + mov.l r0, @(NR_READERS,r8) + tst r0, r0 + bf 6f +5: + mov #0, r0 + mov.l r0, @(WRITER,r8) + mov #1, r6 + mov r8, r4 + add #WRITERS_WAKEUP, r4 + mov.l @(WRITERS_QUEUED,r8), r0 + tst r0, r0 + bf 0f + + /* If also no readers waiting nothing to do. */ + mov.l @(READERS_QUEUED,r8), r0 + tst r0, r0 + bt 6f + + mov #-1, r6 + shlr r6 /* r6 = 0x7fffffff */ + mov r8, r4 + add #READERS_WAKEUP, r4 + +0: + mov.l @r4, r0 + add #1, r0 + mov.l r0, @r4 +#if MUTEX == 0 + DEC (@r8, r2) +#else + DEC (@(MUTEX,r8), r2) +#endif + tst r2, r2 + bf 7f + +8: +#ifdef __ASSUME_PRIVATE_FUTEX + mov #PSHARED, r0 + mov.b @(r0,r8), r5 + mov #(FUTEX_PRIVATE_FLAG|FUTEX_WAKE), r0 + xor r0, r5 + extu.b r5, r5 +#else + mov #PSHARED, r0 + mov.b @(r0,r8), r5 + extu.b r5, r5 + mov #FUTEX_WAKE, r0 + or r0, r5 + stc gbr, r1 + mov.w .Lpfoff, r2 + add r2, r1 + mov.l @r1, r0 + xor r0, r5 +#endif + mov #SYS_futex, r3 + mov #0, r7 + extu.b r3, r3 + trapa #0x14 + SYSCALL_INST_PAD + + lds.l @r15+, pr + mov.l @r15+, r8 + mov.l @r15+, r12 + rts + mov #0, r0 +6: +#if MUTEX == 0 + DEC (@r8, r2) +#else + DEC (@(MUTEX,r8), r2) +#endif + tst r2, r2 + bf 3f +4: + lds.l @r15+, pr + mov.l @r15+, r8 + mov.l @r15+, r12 + rts + mov #0, r0 + +1: + mov r8, r5 +#if MUTEX != 0 + add #MUTEX, r5 +#endif + mov #PSHARED, r0 + mov.b @(r0,r8), r6 + extu.b r6, r6 + mov.l .Lwait8, r1 + bsrf r1 + mov r2, r4 +.Lwait8b: + bra 2b + nop +3: + mov r8, r4 +#if MUTEX != 0 + add #MUTEX, r4 +#endif + mov #PSHARED, r0 + mov.b @(r0,r8), r5 + extu.b r5, r5 + mov.l .Lwake8, r1 + bsrf r1 + nop +.Lwake8b: + bra 4b + nop + +7: + mov.l r4, @-r15 + mov.l r6, @-r15 + mov r8, r4 +#if MUTEX != 0 + add #MUTEX, r4 +#endif + mov #PSHARED, r0 + mov.b @(r0,r8), r5 + extu.b r5, r5 + mov.l .Lwake9, r1 + bsrf r1 + nop +.Lwake9b: + + mov.l @r15+, r6 + bra 8b + mov.l @r15+, r4 + +#ifndef __ASSUME_PRIVATE_FUTEX +.Lpfoff: + .word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE +#endif + .align 2 +.Lwait8: + .long __lll_lock_wait-.Lwait8b +.Lwake8: + .long __lll_unlock_wake-.Lwake8b +.Lwake9: + .long __lll_unlock_wake-.Lwake9b + .size __pthread_rwlock_unlock,.-__pthread_rwlock_unlock + + .globl pthread_rwlock_unlock +pthread_rwlock_unlock = __pthread_rwlock_unlock + + .globl __pthread_rwlock_unlock_internal +__pthread_rwlock_unlock_internal = __pthread_rwlock_unlock diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_wrlock.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_wrlock.S new file mode 100644 index 00000000..e7bfe0d0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/pthread_rwlock_wrlock.S @@ -0,0 +1,235 @@ +/* Copyright (C) 2003, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include +#include "lowlevel-atomic.h" + + + .text + + .globl __pthread_rwlock_wrlock + .type __pthread_rwlock_wrlock,@function + .protected __pthread_rwlock_wrlock + .align 5 +__pthread_rwlock_wrlock: + mov.l r12, @-r15 + mov.l r9, @-r15 + mov.l r8, @-r15 + sts.l pr, @-r15 + mov r4, r8 + + /* Get the lock. */ + mov #0, r3 + mov #1, r4 +#if MUTEX == 0 + CMPXCHG (r3, @r8, r4, r2) +#else + CMPXCHG (r3, @(MUTEX,r8), r4, r2) +#endif + bf 1f +2: + mov.l @(WRITER,r8), r0 + tst r0, r0 + bf 14f + mov.l @(NR_READERS,r8), r0 + tst r0, r0 + bt 5f +3: + mov.l @(WRITERS_QUEUED,r8), r0 + add #1, r0 + mov.l r0, @(WRITERS_QUEUED,r8) + tst r0, r0 + bt 4f + + mov.l @(WRITERS_WAKEUP,r8), r9 + +#if MUTEX == 0 + DEC (@r8, r2) +#else + DEC (@(MUTEX,r8), r2) +#endif + tst r2, r2 + bf 10f +11: + mov r8, r4 + add #WRITERS_WAKEUP, r4 +#ifdef __ASSUME_PRIVATE_FUTEX + mov #PSHARED, r0 + mov.b @(r0,r8), r5 + mov #(FUTEX_PRIVATE_FLAG|FUTEX_WAIT), r0 + xor r0, r5 + extu.b r5, r5 +#else + mov #PSHARED, r0 + mov.b @(r0,r8), r5 + extu.b r5, r5 +# if FUTEX_WAIT != 0 + mov #FUTEX_WAIT, r0 + or r0, r5 +# endif + stc gbr, r1 + mov.w .Lpfoff, r2 + add r2, r1 + mov.l @r1, r0 + xor r0, r5 +#endif + mov r9, r6 + mov #0, r7 + mov #SYS_futex, r3 + extu.b r3, r3 + trapa #0x14 + SYSCALL_INST_PAD + + /* Reget the lock. */ + mov #0, r3 + mov #1, r4 +#if MUTEX == 0 + CMPXCHG (r3, @r8, r4, r2) +#else + CMPXCHG (r3, @(MUTEX,r8), r4, r2) +#endif + bf 12f +13: + mov.l @(WRITERS_QUEUED,r8), r0 + add #-1, r0 + bra 2b + mov.l r0, @(WRITERS_QUEUED,r8) + +5: + mov #0, r3 + stc gbr, r0 + mov.w .Ltidoff, r1 + mov.l @(r0,r1), r0 + mov.l r0, @(WRITER,r8) +9: +#if MUTEX == 0 + DEC (@r8, r2) +#else + DEC (@(MUTEX,r8), r2) +#endif + tst r2, r2 + bf 6f +7: + lds.l @r15+, pr + mov.l @r15+, r8 + mov.l @r15+, r9 + mov.l @r15+, r12 + rts + mov r3, r0 + +1: + mov r8, r5 +#if MUTEX != 0 + add #MUTEX, r5 +#endif + mov #PSHARED, r0 + mov.b @(r0,r8), r6 + extu.b r6, r6 + mov.l .Lwait4, r1 + bsrf r1 + mov r2, r4 +.Lwait4b: + bra 2b + nop +14: + stc gbr, r1 + mov.w .Ltidoff, r2 + add r2, r1 + mov.l @r1, r1 + cmp/eq r1, r0 + bf 3b + bra 9b + mov #EDEADLK, r3 +6: + mov r8, r4 +#if MUTEX != 0 + add #MUTEX, r4 +#endif + mov #PSHARED, r0 + mov.b @(r0,r8), r5 + extu.b r5, r5 + mov.l .Lwake4, r1 + bsrf r1 + nop +.Lwake4b: + bra 7b + mov #0, r3 + +#ifndef __ASSUME_PRIVATE_FUTEX +.Lpfoff: + .word PRIVATE_FUTEX - TLS_PRE_TCB_SIZE +#endif +.Ltidoff: + .word TID - TLS_PRE_TCB_SIZE + +4: + mov.l @(WRITERS_QUEUED,r8), r1 + add #-1, r1 + mov.l r1, @(WRITERS_QUEUED,r8) + bra 9b + mov #EAGAIN, r3 + +10: + mov r8, r4 +#if MUTEX != 0 + add #MUTEX, r4 +#endif + mov #PSHARED, r0 + mov.b @(r0,r8), r5 + extu.b r5, r5 + mov.l .Lwake5, r1 + bsrf r1 + nop +.Lwake5b: + bra 11b + nop + +12: + mov r8, r5 +#if MUTEX != 0 + add #MUTEX, r5 +#endif + mov #PSHARED, r0 + mov.b @(r0,r8), r6 + extu.b r6, r6 + mov.l .Lwait5, r1 + bsrf r1 + mov r2, r4 +.Lwait5b: + bra 13b + nop + + .align 2 +.Lwait4: + .long __lll_lock_wait-.Lwait4b +.Lwake4: + .long __lll_unlock_wake-.Lwake4b +.Lwait5: + .long __lll_lock_wait-.Lwait5b +.Lwake5: + .long __lll_unlock_wake-.Lwake5b + .globl pthread_rwlock_wrlock +pthread_rwlock_wrlock = __pthread_rwlock_wrlock + + .globl __pthread_rwlock_wrlock_internal +__pthread_rwlock_wrlock_internal = __pthread_rwlock_wrlock diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sem_post.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sem_post.S new file mode 100644 index 00000000..f71cd930 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sem_post.S @@ -0,0 +1,110 @@ +/* Copyright (C) 2003, 2004, 2007, 2008 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include "lowlevel-atomic.h" + + + .text + + .globl __new_sem_post + .type __new_sem_post,@function + .align 5 +__new_sem_post: + mov.l @(VALUE,r4), r2 +0: + mov.l .Lmax, r1 + cmp/eq r1, r2 + bt/s 3f + mov r2, r3 + mov r3, r5 + add #1, r5 + CMPXCHG (r3, @(VALUE,r4), r5, r2) + bf 0b + mov.l @(NWAITERS,r4), r2 + tst r2, r2 + bt 2f + mov #FUTEX_WAKE, r5 + mov.l @(PRIVATE,r4), r1 + or r1, r5 + mov #1, r6 + mov #0, r7 + mov #SYS_futex, r3 + extu.b r3, r3 + trapa #0x14 + SYSCALL_INST_PAD + + cmp/pz r0 + bf 1f +2: + rts + mov #0, r0 + +1: + bra 4f + mov #EINVAL, r2 + +3: + mov #EOVERFLOW, r2 +4: + mov.l r12, @-r15 + mov.l r8, @-r15 + sts.l pr, @-r15 + mova .Lgot3, r0 + mov.l .Lgot3, r12 + add r0, r12 + +#if USE___THREAD + mov.l .Lerrno3, r0 + stc gbr, r1 + mov.l @(r0, r12), r0 + bra .Lexit + add r1, r0 + .align 2 +.Lerrno3: + .long errno@GOTTPOFF +.Lexit: + mov.l r2, @r0 +#else + mov r2, r8 + mov.l .Lerrloc3, r1 + bsrf r1 + nop +.Lerrloc3b: + mov r8, @r0 +#endif + lds.l @r15+, pr + mov.l @r15+, r8 + mov.l @r15+, r12 + rts + mov #-1, r0 + + .align 2 +.Lmax: + .long SEM_VALUE_MAX +.Lgot3: + .long _GLOBAL_OFFSET_TABLE_ +#if !USE___THREAD +.Lerrloc3: + .long __errno_location@PLT-(.Lerrloc3b-.) +#endif + .size __new_sem_post,.-__new_sem_post + weak_alias(__new_sem_post, sem_post) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sem_timedwait.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sem_timedwait.S new file mode 100644 index 00000000..7fb61b27 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sem_timedwait.S @@ -0,0 +1,358 @@ +/* Copyright (C) 2003, 2004, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include "lowlevel-atomic.h" + + +#if VALUE != 0 +# error "code needs to be rewritten for VALUE != 0" +#endif + + .text + + .globl sem_timedwait + .type sem_timedwait,@function + .align 5 +sem_timedwait: +.LSTARTCODE: + mov.l @r4, r0 +2: + tst r0, r0 + bt 1f + mov r0, r3 + mov r0, r6 + add #-1, r3 + CMPXCHG (r6, @r4, r3, r2) + bf/s 2b + mov r2, r0 + rts + mov #0, r0 + +1: + /* Check whether the timeout value is valid. */ + mov.l r8, @-r15 +.Lpush_r8: + mov.l r9, @-r15 +.Lpush_r9: + mov.l r10, @-r15 +.Lpush_r10: + mov.l r12, @-r15 +.Lpush_r12: + sts.l pr, @-r15 +.Lpush_pr: + add #-8, r15 +.Lalloc: + mov r4, r8 + mov r5, r9 + + /* Check for invalid nanosecond field. */ + mov.l @(4,r9), r0 + mov.l .L1g, r1 + cmp/hs r1, r0 + bt/s 6f + mov #EINVAL, r0 + INC (@(NWAITERS,r8),r2) + +7: + /* Compute relative timeout. */ + mov r15, r4 + mov #0, r5 + mov #__NR_gettimeofday, r3 + trapa #0x12 + SYSCALL_INST_PAD + + mov.l @(4,r15), r0 + mov.w .L1k, r1 + dmulu.l r0, r1 /* Milli seconds to nano seconds. */ + mov.l @r9, r2 + mov.l @(4,r9), r3 + mov.l @r15, r0 + sts macl, r1 + sub r0, r2 + clrt + subc r1, r3 + bf 5f + mov.l .L1g, r1 + add r1, r3 + add #-1, r2 +5: + cmp/pz r2 + bf/s 6f /* Time is already up. */ + mov #ETIMEDOUT, r0 + + /* Store relative timeout. */ + mov.l r2, @r15 + mov.l r3, @(4,r15) + +.LcleanupSTART: + mov.l .Lenable0, r1 + bsrf r1 + nop +.Lenable0b: + mov r0, r10 + + mov r8, r4 +#if FUTEX_WAIT == 0 + mov.l @(PRIVATE,r8), r5 +#else + mov.l @(PRIVATE,r8), r5 + mov #FUTEX_WAIT, r0 + or r0, r5 +#endif + mov #0, r6 + mov r15, r7 + mov #SYS_futex, r3 + extu.b r3, r3 + trapa #0x14 + SYSCALL_INST_PAD + + mov.l .Ldisable0, r1 + mov r10, r4 + bsrf r1 + mov r0, r10 +.Ldisable0b: + mov r10, r0 +.LcleanupEND: + + tst r0, r0 + bt 9f + cmp/eq #-EWOULDBLOCK, r0 + bf 3f +9: + mov.l @r8, r0 +8: + tst r0, r0 + bt 7b + + mov r0, r3 + mov r0, r4 + add #-1, r3 + CMPXCHG (r4, @r8, r3, r2) + bf/s 8b + mov r2, r0 + + DEC (@(NWAITERS,r8), r2) + mov #0, r0 + +10: + add #8, r15 + lds.l @r15+, pr + mov.l @r15+, r12 + mov.l @r15+, r10 + mov.l @r15+, r9 + mov.l @r15+, r8 + rts + nop + +3: + neg r0, r0 +6: + mov r0, r10 + mova .Lgot2, r0 + mov.l .Lgot2, r12 + add r0, r12 + +#if USE___THREAD + mov.l .Lerrno2, r0 + stc gbr, r1 + mov.l @(r0, r12), r0 + bra .Lexit + add r1, r0 + .align 2 +.Lerrno2: + .long errno@GOTTPOFF +.Lexit: +#else + mov.l .Lerrloc2, r1 + bsrf r1 + nop +.Lerrloc2b: +#endif + mov.l r10, @r0 + DEC (@(NWAITERS,r8), r2) + bra 10b + mov #-1, r0 + +.L1k: + .word 1000 + .align 2 +.L1g: + .long 1000000000 +.Lgot2: + .long _GLOBAL_OFFSET_TABLE_ +#if !USE___THREAD +.Lerrloc2: + .long __errno_location@PLT-(.Lerrloc2b-.) +#endif +.Lenable0: + .long __pthread_enable_asynccancel-.Lenable0b +.Ldisable0: + .long __pthread_disable_asynccancel-.Ldisable0b + .size sem_timedwait,.-sem_timedwait + + .type sem_wait_cleanup,@function +sem_wait_cleanup: + DEC (@(NWAITERS,r8), r2) +.LcallUR: + mov.l .Lresume, r1 +#ifdef __PIC__ + add r12, r1 +#endif + jsr @r1 + nop + sleep + + .align 2 +.Lresume: +#ifdef __PIC__ + .long _Unwind_Resume@GOTOFF +#else + .long _Unwind_Resume +#endif +.LENDCODE: + .size sem_wait_cleanup,.-sem_wait_cleanup + + + .section .gcc_except_table,"a",@progbits +.LexceptSTART: + .byte 0xff ! @LPStart format (omit) + .byte 0xff ! @TType format (omit) + .byte 0x01 ! call-site format + ! DW_EH_PE_uleb128 + .uleb128 .Lcstend-.Lcstbegin +.Lcstbegin: + .uleb128 .LcleanupSTART-.LSTARTCODE + .uleb128 .LcleanupEND-.LcleanupSTART + .uleb128 sem_wait_cleanup-.LSTARTCODE + .uleb128 0 + .uleb128 .LcallUR-.LSTARTCODE + .uleb128 .LENDCODE-.LcallUR + .uleb128 0 + .uleb128 0 +.Lcstend: + + + .section .eh_frame,"a",@progbits +.LSTARTFRAME: + .ualong .LENDCIE-.LSTARTCIE ! Length of the CIE. +.LSTARTCIE: + .ualong 0 ! CIE ID. + .byte 1 ! Version number. +#ifdef SHARED + .string "zPLR" ! NUL-terminated augmentation + ! string. +#else + .string "zPL" ! NUL-terminated augmentation + ! string. +#endif + .uleb128 1 ! Code alignment factor. + .sleb128 -4 ! Data alignment factor. + .byte 0x11 ! Return address register + ! column. +#ifdef SHARED + .uleb128 7 ! Augmentation value length. + .byte 0x9b ! Personality: DW_EH_PE_pcrel + ! + DW_EH_PE_sdata4 + ! + DW_EH_PE_indirect + .ualong DW.ref.__gcc_personality_v0-. + .byte 0x1b ! LSDA Encoding: DW_EH_PE_pcrel + ! + DW_EH_PE_sdata4. + .byte 0x1b ! FDE Encoding: DW_EH_PE_pcrel + ! + DW_EH_PE_sdata4. +#else + .uleb128 6 ! Augmentation value length. + .byte 0x0 ! Personality: absolute + .ualong __gcc_personality_v0 + .byte 0x0 ! LSDA Encoding: absolute +#endif + .byte 0x0c ! DW_CFA_def_cfa + .uleb128 0xf + .uleb128 0 + .align 4 +.LENDCIE: + + .ualong .LENDFDE-.LSTARTFDE ! Length of the FDE. +.LSTARTFDE: + .ualong .LSTARTFDE-.LSTARTFRAME ! CIE pointer. +#ifdef SHARED + .ualong .LSTARTCODE-. ! PC-relative start address + ! of the code. +#else + .ualong .LSTARTCODE ! Start address of the code. +#endif + .ualong .LENDCODE-.LSTARTCODE ! Length of the code. + .uleb128 4 ! Augmentation size +#ifdef SHARED + .ualong .LexceptSTART-. +#else + .ualong .LexceptSTART +#endif + + .byte 4 ! DW_CFA_advance_loc4 + .ualong .Lpush_r8-.LSTARTCODE + .byte 14 ! DW_CFA_def_cfa_offset + .uleb128 4 + .byte 0x88 ! DW_CFA_offset r8 + .uleb128 1 + .byte 4 ! DW_CFA_advance_loc4 + .ualong .Lpush_r9-.Lpush_r8 + .byte 14 ! DW_CFA_def_cfa_offset + .uleb128 8 + .byte 0x89 ! DW_CFA_offset r9 + .uleb128 2 + .byte 4 ! DW_CFA_advance_loc4 + .ualong .Lpush_r10-.Lpush_r9 + .byte 14 ! DW_CFA_def_cfa_offset + .uleb128 12 + .byte 0x8a ! DW_CFA_offset r10 + .uleb128 3 + .byte 4 ! DW_CFA_advance_loc4 + .ualong .Lpush_r12-.Lpush_r10 + .byte 14 ! DW_CFA_def_cfa_offset + .uleb128 16 + .byte 0x8c ! DW_CFA_offset r12 + .uleb128 4 + .byte 4 ! DW_CFA_advance_loc4 + .ualong .Lpush_pr-.Lpush_r12 + .byte 14 ! DW_CFA_def_cfa_offset + .uleb128 20 + .byte 0x91 ! DW_CFA_offset pr + .uleb128 5 + .byte 4 ! DW_CFA_advance_loc4 + .ualong .Lalloc-.Lpush_pr + .byte 14 ! DW_CFA_def_cfa_offset + .uleb128 28 + .align 4 +.LENDFDE: + + +#ifdef SHARED + .hidden DW.ref.__gcc_personality_v0 + .weak DW.ref.__gcc_personality_v0 + .section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits + .align 4 + .type DW.ref.__gcc_personality_v0, @object + .size DW.ref.__gcc_personality_v0, 4 +DW.ref.__gcc_personality_v0: + .long __gcc_personality_v0 +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sem_trywait.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sem_trywait.S new file mode 100644 index 00000000..b46eb1a5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sem_trywait.S @@ -0,0 +1,90 @@ +/* Copyright (C) 2003, 2004, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include "lowlevel-atomic.h" + + + .text + + .globl __new_sem_trywait + .type __new_sem_trywait,@function + .align 5 +__new_sem_trywait: + mov.l r12, @-r15 + mov.l r8, @-r15 + sts.l pr, @-r15 + mov r4, r8 + mov.l @r8, r0 +2: + tst r0, r0 + bt 1f + + mov r0, r3 + mov r0, r4 + add #-1, r3 + CMPXCHG (r4, @r8, r3, r2) + bf/s 2b + mov r2, r0 + + lds.l @r15+, pr + mov.l @r15+, r8 + mov.l @r15+, r12 + rts + mov #0, r0 + +1: + mov #EAGAIN, r8 + mova .Lgot1, r0 + mov.l .Lgot1, r12 + add r0, r12 + +#if USE___THREAD + mov.l .Lerrno1, r0 + stc gbr, r1 + mov.l @(r0, r12), r0 + bra .Lexit + add r1, r0 + .align 2 +.Lerrno1: + .long errno@GOTTPOFF +.Lexit: +#else + mov.l .Lerrloc1, r1 + bsrf r1 + nop +.Lerrloc1b: +#endif + mov.l r8, @r0 + lds.l @r15+, pr + mov.l @r15+, r8 + mov.l @r15+, r12 + rts + mov #-1, r0 + + .align 2 +.Lgot1: + .long _GLOBAL_OFFSET_TABLE_ +#if !USE___THREAD +.Lerrloc1: + .long __errno_location@PLT-(.Lerrloc1b-.) +#endif + .size __new_sem_trywait,.-__new_sem_trywait + weak_alias(__new_sem_trywait, sem_trywait) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sem_wait.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sem_wait.S new file mode 100644 index 00000000..00a125bc --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sem_wait.S @@ -0,0 +1,303 @@ +/* Copyright (C) 2003, 2004, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include "lowlevel-atomic.h" + + +#if VALUE != 0 +# error "code needs to be rewritten for VALUE != 0" +#endif + + .text + + .globl __new_sem_wait + .type __new_sem_wait,@function + .align 5 +__new_sem_wait: +.LSTARTCODE: + mov.l r8, @-r15 +.Lpush_r8: + mov.l r10, @-r15 +.Lpush_r10: + mov.l r12, @-r15 +.Lpush_r12: + sts.l pr, @-r15 +.Lpush_pr: + mov r4, r8 + + mov.l @r8, r0 +2: + tst r0, r0 + bt 1f + mov r0, r3 + mov r0, r4 + add #-1, r3 + CMPXCHG (r4, @r8, r3, r2) + bf/s 2b + mov r2, r0 +7: + mov #0, r0 +9: + lds.l @r15+, pr + mov.l @r15+, r12 + mov.l @r15+, r10 + rts + mov.l @r15+, r8 + +.Lafter_ret: +1: + INC (@(NWAITERS,r8),r2) + +.LcleanupSTART: +6: + mov.l .Lenable0, r1 + bsrf r1 + nop +.Lenable0b: + mov r0, r10 + + mov r8, r4 +#if FUTEX_WAIT == 0 + mov.l @(PRIVATE,r8), r5 +#else + mov.l @(PRIVATE,r8), r5 + mov #FUTEX_WAIT, r0 + or r0, r5 +#endif + mov #0, r6 + mov #0, r7 + mov #SYS_futex, r3 + extu.b r3, r3 + trapa #0x14 + SYSCALL_INST_PAD + + mov.l .Ldisable0, r1 + mov r10, r4 + bsrf r1 + mov r0, r10 +.Ldisable0b: + mov r10, r0 +.LcleanupEND: + + tst r0, r0 + bt 3f + cmp/eq #-EWOULDBLOCK, r0 + bf 4f + +3: + mov.l @r8, r0 +5: + tst r0, r0 + bt 6b + + mov r0, r3 + mov r0, r4 + add #-1, r3 + CMPXCHG (r4, @r8, r3, r2) + bf/s 5b + mov r2, r0 + + DEC (@(NWAITERS,r8), r2) + bra 7b + nop + +4: + neg r0, r0 + mov r0, r4 + DEC (@(NWAITERS,r8), r2) + mov r4, r8 + mova .Lgot0, r0 + mov.l .Lgot0, r12 + add r0, r12 + +#if USE___THREAD + mov.l .Lerrno0, r0 + stc gbr, r1 + mov.l @(r0, r12), r0 + bra .Lexit + add r1, r0 + .align 2 +.Lerrno0: + .long errno@GOTTPOFF +.Lexit: +#else + mov.l .Lerrloc0, r1 + bsrf r1 + nop +.Lerrloc0b: +#endif + mov.l r8, @r0 + bra 9b + mov #-1, r0 + + .align 2 +.Lgot0: + .long _GLOBAL_OFFSET_TABLE_ +#if !USE___THREAD +.Lerrloc0: + .long __errno_location@PLT-(.Lerrloc0b-.) +#endif +.Lenable0: + .long __pthread_enable_asynccancel-.Lenable0b +.Ldisable0: + .long __pthread_disable_asynccancel-.Ldisable0b + .size __new_sem_wait,.-__new_sem_wait + weak_alias(__new_sem_wait, sem_wait) + + + .type sem_wait_cleanup,@function +sem_wait_cleanup: + DEC (@(NWAITERS,r8), r2) +.LcallUR: + mov.l .Lresume, r1 +#ifdef __PIC__ + add r12, r1 +#endif + jsr @r1 + nop + sleep + + .align 2 +.Lresume: +#ifdef __PIC__ + .long _Unwind_Resume@GOTOFF +#else + .long _Unwind_Resume +#endif +.LENDCODE: + .size sem_wait_cleanup,.-sem_wait_cleanup + + + .section .gcc_except_table,"a",@progbits +.LexceptSTART: + .byte 0xff ! @LPStart format (omit) + .byte 0xff ! @TType format (omit) + .byte 0x01 ! call-site format + ! DW_EH_PE_uleb128 + .uleb128 .Lcstend-.Lcstbegin +.Lcstbegin: + .uleb128 .LcleanupSTART-.LSTARTCODE + .uleb128 .LcleanupEND-.LcleanupSTART + .uleb128 sem_wait_cleanup-.LSTARTCODE + .uleb128 0 + .uleb128 .LcallUR-.LSTARTCODE + .uleb128 .LENDCODE-.LcallUR + .uleb128 0 + .uleb128 0 +.Lcstend: + + + .section .eh_frame,"a",@progbits +.LSTARTFRAME: + .ualong .LENDCIE-.LSTARTCIE ! Length of the CIE. +.LSTARTCIE: + .ualong 0 ! CIE ID. + .byte 1 ! Version number. +#ifdef SHARED + .string "zPLR" ! NUL-terminated augmentation + ! string. +#else + .string "zPL" ! NUL-terminated augmentation + ! string. +#endif + .uleb128 1 ! Code alignment factor. + .sleb128 -4 ! Data alignment factor. + .byte 0x11 ! Return address register + ! column. +#ifdef SHARED + .uleb128 7 ! Augmentation value length. + .byte 0x9b ! Personality: DW_EH_PE_pcrel + ! + DW_EH_PE_sdata4 + ! + DW_EH_PE_indirect + .ualong DW.ref.__gcc_personality_v0-. + .byte 0x1b ! LSDA Encoding: DW_EH_PE_pcrel + ! + DW_EH_PE_sdata4. + .byte 0x1b ! FDE Encoding: DW_EH_PE_pcrel + ! + DW_EH_PE_sdata4. +#else + .uleb128 6 ! Augmentation value length. + .byte 0x0 ! Personality: absolute + .ualong __gcc_personality_v0 + .byte 0x0 ! LSDA Encoding: absolute +#endif + .byte 0x0c ! DW_CFA_def_cfa + .uleb128 0xf + .uleb128 0 + .align 4 +.LENDCIE: + + .ualong .LENDFDE-.LSTARTFDE ! Length of the FDE. +.LSTARTFDE: + .ualong .LSTARTFDE-.LSTARTFRAME ! CIE pointer. +#ifdef SHARED + .ualong .LSTARTCODE-. ! PC-relative start address + ! of the code. +#else + .ualong .LSTARTCODE ! Start address of the code. +#endif + .ualong .LENDCODE-.LSTARTCODE ! Length of the code. + .uleb128 4 ! Augmentation size +#ifdef SHARED + .ualong .LexceptSTART-. +#else + .ualong .LexceptSTART +#endif + + .byte 4 ! DW_CFA_advance_loc4 + .ualong .Lpush_r8-.LSTARTCODE + .byte 14 ! DW_CFA_def_cfa_offset + .uleb128 4 + .byte 0x88 ! DW_CFA_offset r8 + .uleb128 1 + .byte 4 ! DW_CFA_advance_loc4 + .ualong .Lpush_r10-.Lpush_r8 + .byte 14 ! DW_CFA_def_cfa_offset + .uleb128 8 + .byte 0x8a ! DW_CFA_offset r10 + .uleb128 2 + .byte 4 ! DW_CFA_advance_loc4 + .ualong .Lpush_r12-.Lpush_r10 + .byte 14 ! DW_CFA_def_cfa_offset + .uleb128 12 + .byte 0x8c ! DW_CFA_offset r12 + .uleb128 3 + .byte 4 ! DW_CFA_advance_loc4 + .ualong .Lpush_pr-.Lpush_r12 + .byte 14 ! DW_CFA_def_cfa_offset + .uleb128 16 + .byte 0x91 ! DW_CFA_offset pr + .uleb128 4 + .align 4 +.LENDFDE: + + +#ifdef SHARED + .hidden DW.ref.__gcc_personality_v0 + .weak DW.ref.__gcc_personality_v0 + .section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits + .align 4 + .type DW.ref.__gcc_personality_v0, @object + .size DW.ref.__gcc_personality_v0, 4 +DW.ref.__gcc_personality_v0: + .long __gcc_personality_v0 +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sh4/lowlevellock.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sh4/lowlevellock.h new file mode 100644 index 00000000..8cdcac55 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sh4/lowlevellock.h @@ -0,0 +1,4 @@ +/* 4 instruction cycles not accessing cache and TLB are needed after + trapa instruction to avoid an SH-4 silicon bug. */ +#define NEED_SYSCALL_INST_PAD +#include diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/smp.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/smp.h new file mode 100644 index 00000000..2c0cbe99 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/smp.h @@ -0,0 +1,24 @@ +/* Determine whether the host has multiple processors. SH version. + Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +static inline int +is_smp_system (void) +{ + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sysdep-cancel.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sysdep-cancel.h new file mode 100644 index 00000000..ad2ca40a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/sysdep-cancel.h @@ -0,0 +1,169 @@ +/* Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#ifndef __ASSEMBLER__ +# include +#endif + +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + +# define _IMM12 #-12 +# define _IMM16 #-16 +# define _IMP16 #16 +# undef PSEUDO +# define PSEUDO(name, syscall_name, args) \ + .text; \ + ENTRY (name); \ + .Lpseudo_start: \ + SINGLE_THREAD_P; \ + bf .Lpseudo_cancel; \ + .type __##syscall_name##_nocancel,@function; \ + .globl __##syscall_name##_nocancel; \ + __##syscall_name##_nocancel: \ + DO_CALL (syscall_name, args); \ + mov r0,r1; \ + mov _IMM12,r2; \ + shad r2,r1; \ + not r1,r1; \ + tst r1,r1; \ + bt .Lsyscall_error; \ + bra .Lpseudo_end; \ + nop; \ + .size __##syscall_name##_nocancel,.-__##syscall_name##_nocancel; \ + .Lpseudo_cancel: \ + sts.l pr,@-r15; \ + cfi_adjust_cfa_offset (4); \ + cfi_rel_offset (pr, 0); \ + add _IMM16,r15; \ + cfi_adjust_cfa_offset (16); \ + SAVE_ARGS_##args; \ + CENABLE; \ + LOAD_ARGS_##args; \ + add _IMP16,r15; \ + cfi_adjust_cfa_offset (-16); \ + lds.l @r15+,pr; \ + cfi_adjust_cfa_offset (-4); \ + cfi_restore (pr); \ + DO_CALL(syscall_name, args); \ + SYSCALL_INST_PAD; \ + sts.l pr,@-r15; \ + cfi_adjust_cfa_offset (4); \ + cfi_rel_offset (pr, 0); \ + mov.l r0,@-r15; \ + cfi_adjust_cfa_offset (4); \ + cfi_rel_offset (r0, 0); \ + CDISABLE; \ + mov.l @r15+,r0; \ + cfi_adjust_cfa_offset (-4); \ + lds.l @r15+,pr; \ + cfi_adjust_cfa_offset (-4); \ + cfi_restore (pr); \ + mov r0,r1; \ + mov _IMM12,r2; \ + shad r2,r1; \ + not r1,r1; \ + tst r1,r1; \ + bf .Lpseudo_end; \ + .Lsyscall_error: \ + SYSCALL_ERROR_HANDLER; \ + .Lpseudo_end: + +# undef PSEUDO_END +# define PSEUDO_END(sym) \ + END (sym) + +# define SAVE_ARGS_0 /* Nothing. */ +# define SAVE_ARGS_1 SAVE_ARGS_0; mov.l r4,@(0,r15); cfi_offset (r4,-4) +# define SAVE_ARGS_2 SAVE_ARGS_1; mov.l r5,@(4,r15); cfi_offset (r5,-8) +# define SAVE_ARGS_3 SAVE_ARGS_2; mov.l r6,@(8,r15); cfi_offset (r6,-12) +# define SAVE_ARGS_4 SAVE_ARGS_3; mov.l r7,@(12,r15); cfi_offset (r7,-16) +# define SAVE_ARGS_5 SAVE_ARGS_4 +# define SAVE_ARGS_6 SAVE_ARGS_5 + +# define LOAD_ARGS_0 /* Nothing. */ +# define LOAD_ARGS_1 LOAD_ARGS_0; mov.l @(0,r15),r4 +# define LOAD_ARGS_2 LOAD_ARGS_1; mov.l @(4,r15),r5 +# define LOAD_ARGS_3 LOAD_ARGS_2; mov.l @(8,r15),r6 +# define LOAD_ARGS_4 LOAD_ARGS_3; mov.l @(12,r15),r7 +# define LOAD_ARGS_5 LOAD_ARGS_4 +# define LOAD_ARGS_6 LOAD_ARGS_5 + +# ifdef IS_IN_libpthread +# define __local_enable_asynccancel __pthread_enable_asynccancel +# define __local_disable_asynccancel __pthread_disable_asynccancel +# elif !defined NOT_IN_libc +# define __local_enable_asynccancel __libc_enable_asynccancel +# define __local_disable_asynccancel __libc_disable_asynccancel +# elif defined IS_IN_librt +# define __local_enable_asynccancel __librt_enable_asynccancel +# define __local_disable_asynccancel __librt_disable_asynccancel +# else +# error Unsupported library +# endif + +# define CENABLE \ + mov.l 1f,r0; \ + bsrf r0; \ + nop; \ + 0: bra 2f; \ + mov r0,r2; \ + .align 2; \ + 1: .long __local_enable_asynccancel - 0b; \ + 2: + +# define CDISABLE \ + mov.l 1f,r0; \ + bsrf r0; \ + mov r2,r4; \ + 0: bra 2f; \ + nop; \ + .align 2; \ + 1: .long __local_disable_asynccancel - 0b; \ + 2: + +# ifndef __ASSEMBLER__ +# define SINGLE_THREAD_P \ + __builtin_expect (THREAD_GETMEM (THREAD_SELF, \ + header.multiple_threads) == 0, 1) +# else +# define SINGLE_THREAD_P \ + stc gbr,r0; \ + mov.w 0f,r1; \ + sub r1,r0; \ + mov.l @(MULTIPLE_THREADS_OFFSET,r0),r0; \ + bra 1f; \ + tst r0,r0; \ + 0: .word TLS_PRE_TCB_SIZE; \ + 1: + +# endif + +#elif !defined __ASSEMBLER__ + +# define SINGLE_THREAD_P (1) +# define NO_CANCELLATION 1 + +#endif + +#ifndef __ASSEMBLER__ +# define RTLD_SINGLE_THREAD_P \ + __builtin_expect (THREAD_GETMEM (THREAD_SELF, \ + header.multiple_threads) == 0, 1) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/vfork.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/vfork.S new file mode 100644 index 00000000..a45c09fd --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sh/vfork.S @@ -0,0 +1,71 @@ +/* Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#define _ERRNO_H 1 +#include +#include + +/* Clone the calling process, but without copying the whole address space. + The calling process is suspended until the new process exits or is + replaced by a call to `execve'. Return -1 for errors, 0 to the new process, + and the process ID of the new process to the old process. */ + +ENTRY (__vfork) + /* Save the PID value. */ + stc gbr, r2 + mov.w .L2, r0 + mov.l @(r0,r2), r4 + neg r4, r1 + tst r1, r1 + bf 1f + mov #1, r1 + rotr r1 +1: + mov.l r1, @(r0,r2) + + mov.w .L1, r3 + trapa #0x10 + mov r0, r1 + + /* Restore the old PID value in the parent. */ + tst r0, r0 + bt.s 2f + stc gbr, r2 + mov.w .L2, r0 + mov.l r4, @(r0,r2) + mov r1, r0 +2: + mov #-12, r2 + shad r2, r1 + not r1, r1 // r1=0 means r0 = -1 to -4095 + tst r1, r1 // i.e. error in linux + bf .Lpseudo_end + SYSCALL_ERROR_HANDLER +.Lpseudo_end: + rts + nop +.L1: + .word __NR_vfork +.L2: + .word PID - TLS_PRE_TCB_SIZE + .align 2 +PSEUDO_END (__vfork) +hidden_def (vfork) + +weak_alias (__vfork, vfork) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sigtimedwait.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sigtimedwait.c new file mode 100644 index 00000000..5159bf9b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sigtimedwait.c @@ -0,0 +1,88 @@ +/* Copyright (C) 1997,1998,2000,2002,2003,2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + +#include +#include + +#ifdef __NR_rt_sigtimedwait + +static int +do_sigtimedwait (const sigset_t *set, siginfo_t *info, + const struct timespec *timeout) +{ +#ifdef SIGCANCEL + sigset_t tmpset; + if (set != NULL + && (__builtin_expect (__sigismember (set, SIGCANCEL), 0) +# ifdef SIGSETXID + || __builtin_expect (__sigismember (set, SIGSETXID), 0) +# endif + )) + { + /* Create a temporary mask without the bit for SIGCANCEL set. */ + // We are not copying more than we have to. + memcpy (&tmpset, set, _NSIG / 8); + __sigdelset (&tmpset, SIGCANCEL); +# ifdef SIGSETXID + __sigdelset (&tmpset, SIGSETXID); +# endif + set = &tmpset; + } +#endif + + /* XXX The size argument hopefully will have to be changed to the + real size of the user-level sigset_t. */ + int result = INLINE_SYSCALL (rt_sigtimedwait, 4, set, + info, timeout, _NSIG / 8); + + /* The kernel generates a SI_TKILL code in si_code in case tkill is + used. tkill is transparently used in raise(). Since having + SI_TKILL as a code is useful in general we fold the results + here. */ + if (result != -1 && info != NULL && info->si_code == SI_TKILL) + info->si_code = SI_USER; + + return result; +} + + +/* Return any pending signal or wait for one for the given time. */ +int attribute_hidden +__sigtimedwait (const sigset_t *set, siginfo_t *info, + const struct timespec *timeout) +{ + if (SINGLE_THREAD_P) + return do_sigtimedwait (set, info, timeout); + + int oldtype = LIBC_CANCEL_ASYNC (); + + /* XXX The size argument hopefully will have to be changed to the + real size of the user-level sigset_t. */ + int result = do_sigtimedwait (set, info, timeout); + + LIBC_CANCEL_RESET (oldtype); + + return result; +} +weak_alias (__sigtimedwait, sigtimedwait) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sigwait.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sigwait.c new file mode 100644 index 00000000..bde0a929 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sigwait.c @@ -0,0 +1,2 @@ +#include +#include "../../../../../../libc/signal/sigwait.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sigwaitinfo.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sigwaitinfo.c new file mode 100644 index 00000000..6c47fdee --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sigwaitinfo.c @@ -0,0 +1,88 @@ +/* Copyright (C) 1997,1998,2000,2002,2003,2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#define __need_NULL +#include +#include + +#include +#include + +#ifdef __NR_rt_sigtimedwait + +static int +do_sigwaitinfo (const sigset_t *set, siginfo_t *info) +{ +#ifdef SIGCANCEL + sigset_t tmpset; + if (set != NULL + && (__builtin_expect (__sigismember (set, SIGCANCEL), 0) +# ifdef SIGSETXID + || __builtin_expect (__sigismember (set, SIGSETXID), 0) +# endif + )) + { + /* Create a temporary mask without the bit for SIGCANCEL set. */ + // We are not copying more than we have to. + memcpy (&tmpset, set, _NSIG / 8); + __sigdelset (&tmpset, SIGCANCEL); +# ifdef SIGSETXID + __sigdelset (&tmpset, SIGSETXID); +# endif + set = &tmpset; + } +#endif + + /* XXX The size argument hopefully will have to be changed to the + real size of the user-level sigset_t. */ + int result = INLINE_SYSCALL (rt_sigtimedwait, 4, set, + info, NULL, _NSIG / 8); + + /* The kernel generates a SI_TKILL code in si_code in case tkill is + used. tkill is transparently used in raise(). Since having + SI_TKILL as a code is useful in general we fold the results + here. */ + if (result != -1 && info != NULL && info->si_code == SI_TKILL) + info->si_code = SI_USER; + + return result; +} + + +/* Return any pending signal or wait for one for the given time. */ +int +__sigwaitinfo (const sigset_t *set, siginfo_t *info) +{ + if (SINGLE_THREAD_P) + return do_sigwaitinfo (set, info); + + int oldtype = LIBC_CANCEL_ASYNC (); + + /* XXX The size argument hopefully will have to be changed to the + real size of the user-level sigset_t. */ + int result = do_sigwaitinfo (set, info); + + LIBC_CANCEL_RESET (oldtype); + + return result; +} +weak_alias (__sigwaitinfo, sigwaitinfo) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sleep.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sleep.c new file mode 100644 index 00000000..9e948adc --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sleep.c @@ -0,0 +1,2 @@ +#include +#include <../../../../../../libc/unistd/sleep.c> diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/smp.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/smp.h new file mode 100644 index 00000000..fcc34f76 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/smp.h @@ -0,0 +1,28 @@ +/* Determine whether the host has multiple processors. Linux version. + Copyright (C) 1996, 2002, 2004, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* Test whether the machine has more than one processor. This is not the + best test but good enough. More complicated tests would require `malloc' + which is not available at that time. */ +static inline int +is_smp_system (void) +{ + /* Assume all machines are SMP and/or CMT and/or SMT. */ + return 1; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/Makefile new file mode 100644 index 00000000..43a6fad8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc NPTL +# +# Copyright (C) 2005 Steven J. Hill +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../../../../../ +top_builddir=../../../../../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.arch +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/Makefile.arch b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/Makefile.arch new file mode 100644 index 00000000..88ca01a5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/Makefile.arch @@ -0,0 +1,27 @@ +# Makefile for uClibc NPTL +# +# Copyright (C) 2006 Steven J. Hill +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +libpthread_linux_arch_SSRC = pt-vfork.S clone.S +libpthread_linux_arch_CSRC = pthread_once.c lowlevellock.c \ + pthread_barrier_init.c pthread_barrier_wait.c pthread_barrier_destroy.c + +libc_linux_arch_CSRC = fork.c libc-lowlevellock.c +libc_linux_arch_SSRC = clone.S vfork.S + +ASFLAGS += -DUSE___THREAD + +ASFLAGS-pt-vfork.S = -DNOT_IN_libc -DIS_IN_libpthread -D_LIBC_REENTRANT +CFLAGS-pthread_once.c = -DNOT_IN_libc -DIS_IN_libpthread +CFLAGS-lowlevellock.c = -DNOT_IN_libc -DIS_IN_libpthread + +ASFLAGS-clone.S = -D_LIBC_REENTRANT +ASFLAGS-vfork.S = -D_LIBC_REENTRANT +ifeq ($(UCLIBC_HAS_STDIO_FUTEXES),y) +CFLAGS-fork.c = -D__USE_STDIO_FUTEXES__ +endif +CFLAGS-OMIT-fork.c = -DNOT_IN_libc -DIS_IN_libpthread +CFLAGS-OMIT-libc-lowlevellock.c = -DNOT_IN_libc -DIS_IN_libpthread diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/bits/local_lim.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/bits/local_lim.h new file mode 100644 index 00000000..6e356031 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/bits/local_lim.h @@ -0,0 +1,100 @@ +/* Minimum guaranteed maximum values for system limits. Linux/SPARC version. + Copyright (C) 1993-1998,2000,2002-2004,2008 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* The kernel header pollutes the namespace with the NR_OPEN symbol + and defines LINK_MAX although filesystems have different maxima. A + similar thing is true for OPEN_MAX: the limit can be changed at + runtime and therefore the macro must not be defined. Remove this + after including the header if necessary. */ +#ifndef NR_OPEN +# define __undef_NR_OPEN +#endif +#ifndef LINK_MAX +# define __undef_LINK_MAX +#endif +#ifndef OPEN_MAX +# define __undef_OPEN_MAX +#endif +#ifndef ARG_MAX +# define __undef_ARG_MAX +#endif + +/* The kernel sources contain a file with all the needed information. */ +#include + +/* Have to remove NR_OPEN? */ +#ifdef __undef_NR_OPEN +# undef NR_OPEN +# undef __undef_NR_OPEN +#endif +/* Have to remove LINK_MAX? */ +#ifdef __undef_LINK_MAX +# undef LINK_MAX +# undef __undef_LINK_MAX +#endif +/* Have to remove OPEN_MAX? */ +#ifdef __undef_OPEN_MAX +# undef OPEN_MAX +# undef __undef_OPEN_MAX +#endif +/* Have to remove ARG_MAX? */ +#ifdef __undef_ARG_MAX +# undef ARG_MAX +# undef __undef_ARG_MAX +#endif + +/* The number of data keys per process. */ +#define _POSIX_THREAD_KEYS_MAX 128 +/* This is the value this implementation supports. */ +#define PTHREAD_KEYS_MAX 1024 + +/* Controlling the iterations of destructors for thread-specific data. */ +#define _POSIX_THREAD_DESTRUCTOR_ITERATIONS 4 +/* Number of iterations this implementation does. */ +#define PTHREAD_DESTRUCTOR_ITERATIONS _POSIX_THREAD_DESTRUCTOR_ITERATIONS + +/* The number of threads per process. */ +#define _POSIX_THREAD_THREADS_MAX 64 +/* We have no predefined limit on the number of threads. */ +#undef PTHREAD_THREADS_MAX + +/* Maximum amount by which a process can descrease its asynchronous I/O + priority level. */ +#define AIO_PRIO_DELTA_MAX 20 + +/* Minimum size for a thread. We are free to choose a reasonable value. */ +#define PTHREAD_STACK_MIN 24576 + +/* Maximum number of timer expiration overruns. */ +#define DELAYTIMER_MAX 2147483647 + +/* Maximum tty name length. */ +#define TTY_NAME_MAX 32 + +/* Maximum login name length. This is arbitrary. */ +#define LOGIN_NAME_MAX 256 + +/* Maximum host name length. */ +#define HOST_NAME_MAX 64 + +/* Maximum message queue priority level. */ +#define MQ_PRIO_MAX 32768 + +/* Maximum value the semaphore can have. */ +#define SEM_VALUE_MAX (2147483647) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/bits/pthreadtypes.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/bits/pthreadtypes.h new file mode 100644 index 00000000..faf05848 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/bits/pthreadtypes.h @@ -0,0 +1,221 @@ +/* Machine-specific pthread type layouts. SPARC version. + Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _BITS_PTHREADTYPES_H +#define _BITS_PTHREADTYPES_H 1 + +#include + +#if __WORDSIZE == 64 +# define __SIZEOF_PTHREAD_ATTR_T 56 +# define __SIZEOF_PTHREAD_MUTEX_T 40 +# define __SIZEOF_PTHREAD_MUTEXATTR_T 4 +# define __SIZEOF_PTHREAD_COND_T 48 +# define __SIZEOF_PTHREAD_CONDATTR_T 4 +# define __SIZEOF_PTHREAD_RWLOCK_T 56 +# define __SIZEOF_PTHREAD_RWLOCKATTR_T 8 +# define __SIZEOF_PTHREAD_BARRIER_T 32 +# define __SIZEOF_PTHREAD_BARRIERATTR_T 4 +#else +# define __SIZEOF_PTHREAD_ATTR_T 36 +# define __SIZEOF_PTHREAD_MUTEX_T 24 +# define __SIZEOF_PTHREAD_MUTEXATTR_T 4 +# define __SIZEOF_PTHREAD_COND_T 48 +# define __SIZEOF_PTHREAD_CONDATTR_T 4 +# define __SIZEOF_PTHREAD_RWLOCK_T 32 +# define __SIZEOF_PTHREAD_RWLOCKATTR_T 8 +# define __SIZEOF_PTHREAD_BARRIER_T 20 +# define __SIZEOF_PTHREAD_BARRIERATTR_T 4 +#endif + + +/* Thread identifiers. The structure of the attribute type is + deliberately not exposed. */ +typedef unsigned long int pthread_t; + + +typedef union +{ + char __size[__SIZEOF_PTHREAD_ATTR_T]; + long int __align; +} pthread_attr_t; + + +#if __WORDSIZE == 64 +typedef struct __pthread_internal_list +{ + struct __pthread_internal_list *__prev; + struct __pthread_internal_list *__next; +} __pthread_list_t; +#else +typedef struct __pthread_internal_slist +{ + struct __pthread_internal_slist *__next; +} __pthread_slist_t; +#endif + + +/* Data structures for mutex handling. The structure of the attribute + type is deliberately not exposed. */ +typedef union +{ + struct __pthread_mutex_s + { + int __lock; + unsigned int __count; + int __owner; +#if __WORDSIZE == 64 + unsigned int __nusers; +#endif + /* KIND must stay at this position in the structure to maintain + binary compatibility. */ + int __kind; +#if __WORDSIZE == 64 + int __spins; + __pthread_list_t __list; +# define __PTHREAD_MUTEX_HAVE_PREV 1 +#else + unsigned int __nusers; + __extension__ union + { + int __spins; + __pthread_slist_t __list; + }; +#endif + } __data; + char __size[__SIZEOF_PTHREAD_MUTEX_T]; + long int __align; +} pthread_mutex_t; + +typedef union +{ + char __size[__SIZEOF_PTHREAD_MUTEXATTR_T]; + int __align; +} pthread_mutexattr_t; + + +/* Data structure for conditional variable handling. The structure of + the attribute type is deliberately not exposed. */ +typedef union +{ + struct + { + int __lock; + unsigned int __futex; + __extension__ unsigned long long int __total_seq; + __extension__ unsigned long long int __wakeup_seq; + __extension__ unsigned long long int __woken_seq; + void *__mutex; + unsigned int __nwaiters; + unsigned int __broadcast_seq; + } __data; + char __size[__SIZEOF_PTHREAD_COND_T]; + __extension__ long long int __align; +} pthread_cond_t; + +typedef union +{ + char __size[__SIZEOF_PTHREAD_CONDATTR_T]; + int __align; +} pthread_condattr_t; + + +/* Keys for thread-specific data */ +typedef unsigned int pthread_key_t; + + +/* Once-only execution */ +typedef int pthread_once_t; + + +#if defined __USE_UNIX98 || defined __USE_XOPEN2K +/* Data structure for read-write lock variable handling. The + structure of the attribute type is deliberately not exposed. */ +typedef union +{ +# if __WORDSIZE == 64 + struct + { + int __lock; + unsigned int __nr_readers; + unsigned int __readers_wakeup; + unsigned int __writer_wakeup; + unsigned int __nr_readers_queued; + unsigned int __nr_writers_queued; + int __writer; + int __shared; + unsigned long int __pad1; + unsigned long int __pad2; + /* FLAGS must stay at this position in the structure to maintain + binary compatibility. */ + unsigned int __flags; + } __data; +# else + struct + { + int __lock; + unsigned int __nr_readers; + unsigned int __readers_wakeup; + unsigned int __writer_wakeup; + unsigned int __nr_readers_queued; + unsigned int __nr_writers_queued; + unsigned char __pad1; + unsigned char __pad2; + unsigned char __shared; + /* FLAGS must stay at this position in the structure to maintain + binary compatibility. */ + unsigned char __flags; + int __writer; + } __data; +# endif + char __size[__SIZEOF_PTHREAD_RWLOCK_T]; + long int __align; +} pthread_rwlock_t; + +typedef union +{ + char __size[__SIZEOF_PTHREAD_RWLOCKATTR_T]; + long int __align; +} pthread_rwlockattr_t; +#endif + + +#ifdef __USE_XOPEN2K +/* POSIX spinlock data type. */ +typedef volatile int pthread_spinlock_t; + + +/* POSIX barriers data type. The structure of the type is + deliberately not exposed. */ +typedef union +{ + char __size[__SIZEOF_PTHREAD_BARRIER_T]; + long int __align; +} pthread_barrier_t; + +typedef union +{ + char __size[__SIZEOF_PTHREAD_BARRIERATTR_T]; + int __align; +} pthread_barrierattr_t; +#endif + + +#endif /* bits/pthreadtypes.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/bits/semaphore.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/bits/semaphore.h new file mode 100644 index 00000000..8fd7d344 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/bits/semaphore.h @@ -0,0 +1,41 @@ +/* Machine-specific POSIX semaphore type layouts. SPARC version. + Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SEMAPHORE_H +# error "Never use directly; include instead." +#endif + +#include + +#if __WORDSIZE == 64 +# define __SIZEOF_SEM_T 32 +#else +# define __SIZEOF_SEM_T 16 +#endif + +/* Value returned if `sem_open' failed. */ +#define SEM_FAILED ((sem_t *) 0) + + +typedef union +{ + char __size[__SIZEOF_SEM_T]; + long int __align; +} sem_t; diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/clone.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/clone.S new file mode 100644 index 00000000..dfc5e826 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/clone.S @@ -0,0 +1,5 @@ +#if defined(__arch64__) +#include "./sparc64/clone.S" +#else +#include "./sparc32/clone.S" +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/fork.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/fork.c new file mode 100644 index 00000000..1cd79110 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/fork.c @@ -0,0 +1,29 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + +#define ARCH_FORK() \ + INLINE_CLONE_SYSCALL (CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | SIGCHLD, \ + 0, NULL, NULL, &THREAD_SELF->tid) + +#include "../fork.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/internaltypes.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/internaltypes.h new file mode 100644 index 00000000..4f400a3f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/internaltypes.h @@ -0,0 +1,34 @@ +#ifndef _INTERNALTYPES_H +#include "../internaltypes.h" + +union sparc_pthread_barrier +{ + struct pthread_barrier b; + struct sparc_pthread_barrier_s + { + unsigned int curr_event; + int lock; + unsigned int left; + unsigned int init_count; + unsigned char left_lock; + unsigned char pshared; + } s; +}; + +struct sparc_new_sem +{ + unsigned int value; + unsigned char lock; + unsigned char private; + unsigned char pad[2]; + unsigned long int nwaiters; +}; + +struct sparc_old_sem +{ + unsigned int value; + unsigned char lock; + unsigned char private; +}; + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/libc-lowlevellock.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/libc-lowlevellock.c new file mode 100644 index 00000000..b1928228 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/libc-lowlevellock.c @@ -0,0 +1,21 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Paul Mackerras , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* No difference to lowlevellock.c, except we lose a couple of functions. */ +#include "lowlevellock.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/lowlevellock.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/lowlevellock.c new file mode 100644 index 00000000..0471d1f7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/lowlevellock.c @@ -0,0 +1,133 @@ +/* low level locking for pthread library. SPARC version. + Copyright (C) 2003, 2006, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Paul Mackerras , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include + + +void +__lll_lock_wait_private (int *futex) +{ + do + { + int oldval = atomic_compare_and_exchange_val_24_acq (futex, 2, 1); + if (oldval != 0) + lll_futex_wait (futex, 2, LLL_PRIVATE); + } + while (atomic_compare_and_exchange_val_24_acq (futex, 2, 0) != 0); +} + + +/* These functions don't get included in libc.so */ +#ifdef IS_IN_libpthread +void +__lll_lock_wait (int *futex, int private) +{ + do + { + int oldval = atomic_compare_and_exchange_val_24_acq (futex, 2, 1); + if (oldval != 0) + lll_futex_wait (futex, 2, private); + } + while (atomic_compare_and_exchange_val_24_acq (futex, 2, 0) != 0); +} + + +int +__lll_timedlock_wait (int *futex, const struct timespec *abstime, int private) +{ + /* Reject invalid timeouts. */ + if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) + return EINVAL; + + do + { + struct timeval tv; + struct timespec rt; + + /* Get the current time. */ + (void) gettimeofday (&tv, NULL); + + /* Compute relative timeout. */ + rt.tv_sec = abstime->tv_sec - tv.tv_sec; + rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000; + if (rt.tv_nsec < 0) + { + rt.tv_nsec += 1000000000; + --rt.tv_sec; + } + + /* Already timed out? */ + if (rt.tv_sec < 0) + return ETIMEDOUT; + + /* Wait. */ + int oldval = atomic_compare_and_exchange_val_24_acq (futex, 2, 1); + if (oldval != 0) + lll_futex_timed_wait (futex, 2, &rt, private); + } + while (atomic_compare_and_exchange_val_24_acq (futex, 2, 0) != 0); + + return 0; +} + + +int +__lll_timedwait_tid (int *tidp, const struct timespec *abstime) +{ + int tid; + + if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) + return EINVAL; + + /* Repeat until thread terminated. */ + while ((tid = *tidp) != 0) + { + struct timeval tv; + struct timespec rt; + + /* Get the current time. */ + (void) gettimeofday (&tv, NULL); + + /* Compute relative timeout. */ + rt.tv_sec = abstime->tv_sec - tv.tv_sec; + rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000; + if (rt.tv_nsec < 0) + { + rt.tv_nsec += 1000000000; + --rt.tv_sec; + } + + /* Already timed out? */ + if (rt.tv_sec < 0) + return ETIMEDOUT; + + /* Wait until thread terminates. The kernel so far does not use + the private futex operations for this. */ + if (lll_futex_timed_wait (tidp, tid, &rt, LLL_SHARED) == -ETIMEDOUT) + return ETIMEDOUT; + } + + return 0; +} +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/lowlevellock.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/lowlevellock.h new file mode 100644 index 00000000..d8fe9be3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/lowlevellock.h @@ -0,0 +1,297 @@ +/* Copyright (C) 2003, 2004, 2006, 2007, 2008, 2009 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Libr \ary; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _LOWLEVELLOCK_H +#define _LOWLEVELLOCK_H 1 + +#include +#include +#include +#include +#include +#include + + +#define FUTEX_WAIT 0 +#define FUTEX_WAKE 1 +#define FUTEX_REQUEUE 3 +#define FUTEX_CMP_REQUEUE 4 +#define FUTEX_WAKE_OP 5 +#define FUTEX_OP_CLEAR_WAKE_IF_GT_ONE ((4 << 24) | 1) +#define FUTEX_LOCK_PI 6 +#define FUTEX_UNLOCK_PI 7 +#define FUTEX_TRYLOCK_PI 8 +#define FUTEX_WAIT_BITSET 9 +#define FUTEX_WAKE_BITSET 10 +#define FUTEX_PRIVATE_FLAG 128 +#define FUTEX_CLOCK_REALTIME 256 + +#define FUTEX_BITSET_MATCH_ANY 0xffffffff + + +/* Values for 'private' parameter of locking macros. Yes, the + definition seems to be backwards. But it is not. The bit will be + reversed before passing to the system call. */ +#define LLL_PRIVATE 0 +#define LLL_SHARED FUTEX_PRIVATE_FLAG + + +#if !defined NOT_IN_libc || defined IS_IN_rtld +/* In libc.so or ld.so all futexes are private. */ +# ifdef __ASSUME_PRIVATE_FUTEX +# define __lll_private_flag(fl, private) \ + ((fl) | FUTEX_PRIVATE_FLAG) +# else +# define __lll_private_flag(fl, private) \ + ((fl) | THREAD_GETMEM (THREAD_SELF, header.private_futex)) +# endif +#else +# ifdef __ASSUME_PRIVATE_FUTEX +# define __lll_private_flag(fl, private) \ + (((fl) | FUTEX_PRIVATE_FLAG) ^ (private)) +# else +# define __lll_private_flag(fl, private) \ + (__builtin_constant_p (private) \ + ? ((private) == 0 \ + ? ((fl) | THREAD_GETMEM (THREAD_SELF, header.private_futex)) \ + : (fl)) \ + : ((fl) | (((private) ^ FUTEX_PRIVATE_FLAG) \ + & THREAD_GETMEM (THREAD_SELF, header.private_futex)))) +# endif +#endif + + +#define lll_futex_wait(futexp, val, private) \ + lll_futex_timed_wait (futexp, val, NULL, private) + +#define lll_futex_timed_wait(futexp, val, timespec, private) \ + ({ \ + INTERNAL_SYSCALL_DECL (__err); \ + long int __ret; \ + \ + __ret = INTERNAL_SYSCALL (futex, __err, 4, (futexp), \ + __lll_private_flag (FUTEX_WAIT, private), \ + (val), (timespec)); \ + __ret; \ + }) + +#define lll_futex_wake(futexp, nr, private) \ + ({ \ + INTERNAL_SYSCALL_DECL (__err); \ + long int __ret; \ + \ + __ret = INTERNAL_SYSCALL (futex, __err, 4, (futexp), \ + __lll_private_flag (FUTEX_WAKE, private), \ + (nr), 0); \ + __ret; \ + }) + +/* Returns non-zero if error happened, zero if success. */ +#define lll_futex_requeue(futexp, nr_wake, nr_move, mutex, val, private) \ + ({ \ + INTERNAL_SYSCALL_DECL (__err); \ + long int __ret; \ + \ + __ret = INTERNAL_SYSCALL (futex, __err, 6, (futexp), \ + __lll_private_flag (FUTEX_CMP_REQUEUE, private),\ + (nr_wake), (nr_move), (mutex), (val)); \ + INTERNAL_SYSCALL_ERROR_P (__ret, __err); \ + }) + +#define lll_robust_dead(futexv, private) \ + do \ + { \ + int *__futexp = &(futexv); \ + atomic_or (__futexp, FUTEX_OWNER_DIED); \ + lll_futex_wake (__futexp, 1, private); \ + } \ + while (0) + +/* Returns non-zero if error happened, zero if success. */ +#ifdef __sparc32_atomic_do_lock +/* Avoid FUTEX_WAKE_OP if supporting pre-v9 CPUs. */ +# define lll_futex_wake_unlock(futexp, nr_wake, nr_wake2, futexp2, private) 1 +#else +# define lll_futex_wake_unlock(futexp, nr_wake, nr_wake2, futexp2, private) \ + ({ \ + INTERNAL_SYSCALL_DECL (__err); \ + long int __ret; \ + \ + __ret = INTERNAL_SYSCALL (futex, __err, 6, (futexp), \ + __lll_private_flag (FUTEX_WAKE_OP, private), \ + (nr_wake), (nr_wake2), (futexp2), \ + FUTEX_OP_CLEAR_WAKE_IF_GT_ONE); \ + INTERNAL_SYSCALL_ERROR_P (__ret, __err); \ + }) +#endif + +static inline int +__attribute__ ((always_inline)) +__lll_trylock (int *futex) +{ + return atomic_compare_and_exchange_val_24_acq (futex, 1, 0) != 0; +} +#define lll_trylock(futex) __lll_trylock (&(futex)) + +static inline int +__attribute__ ((always_inline)) +__lll_cond_trylock (int *futex) +{ + return atomic_compare_and_exchange_val_24_acq (futex, 2, 0) != 0; +} +#define lll_cond_trylock(futex) __lll_cond_trylock (&(futex)) + +static inline int +__attribute__ ((always_inline)) +__lll_robust_trylock (int *futex, int id) +{ + return atomic_compare_and_exchange_val_acq (futex, id, 0) != 0; +} +#define lll_robust_trylock(futex, id) \ + __lll_robust_trylock (&(futex), id) + + +extern void __lll_lock_wait_private (int *futex) attribute_hidden; +extern void __lll_lock_wait (int *futex, int private) attribute_hidden; +extern int __lll_robust_lock_wait (int *futex, int private) attribute_hidden; + +static inline void +__attribute__ ((always_inline)) +__lll_lock (int *futex, int private) +{ + int val = atomic_compare_and_exchange_val_24_acq (futex, 1, 0); + + if (__builtin_expect (val != 0, 0)) + { + if (__builtin_constant_p (private) && private == LLL_PRIVATE) + __lll_lock_wait_private (futex); + else + __lll_lock_wait (futex, private); + } +} +#define lll_lock(futex, private) __lll_lock (&(futex), private) + +static inline int +__attribute__ ((always_inline)) +__lll_robust_lock (int *futex, int id, int private) +{ + int result = 0; + if (atomic_compare_and_exchange_bool_acq (futex, id, 0) != 0) + result = __lll_robust_lock_wait (futex, private); + return result; +} +#define lll_robust_lock(futex, id, private) \ + __lll_robust_lock (&(futex), id, private) + +static inline void +__attribute__ ((always_inline)) +__lll_cond_lock (int *futex, int private) +{ + int val = atomic_compare_and_exchange_val_24_acq (futex, 2, 0); + + if (__builtin_expect (val != 0, 0)) + __lll_lock_wait (futex, private); +} +#define lll_cond_lock(futex, private) __lll_cond_lock (&(futex), private) + +#define lll_robust_cond_lock(futex, id, private) \ + __lll_robust_lock (&(futex), (id) | FUTEX_WAITERS, private) + + +extern int __lll_timedlock_wait (int *futex, const struct timespec *, + int private) attribute_hidden; +extern int __lll_robust_timedlock_wait (int *futex, const struct timespec *, + int private) attribute_hidden; + +static inline int +__attribute__ ((always_inline)) +__lll_timedlock (int *futex, const struct timespec *abstime, int private) +{ + int val = atomic_compare_and_exchange_val_24_acq (futex, 1, 0); + int result = 0; + + if (__builtin_expect (val != 0, 0)) + result = __lll_timedlock_wait (futex, abstime, private); + return result; +} +#define lll_timedlock(futex, abstime, private) \ + __lll_timedlock (&(futex), abstime, private) + +static inline int +__attribute__ ((always_inline)) +__lll_robust_timedlock (int *futex, const struct timespec *abstime, + int id, int private) +{ + int result = 0; + if (atomic_compare_and_exchange_bool_acq (futex, id, 0) != 0) + result = __lll_robust_timedlock_wait (futex, abstime, private); + return result; +} +#define lll_robust_timedlock(futex, abstime, id, private) \ + __lll_robust_timedlock (&(futex), abstime, id, private) + +#define lll_unlock(lock, private) \ + ((void) ({ \ + int *__futex = &(lock); \ + int __val = atomic_exchange_24_rel (__futex, 0); \ + if (__builtin_expect (__val > 1, 0)) \ + lll_futex_wake (__futex, 1, private); \ + })) + +#define lll_robust_unlock(lock, private) \ + ((void) ({ \ + int *__futex = &(lock); \ + int __val = atomic_exchange_rel (__futex, 0); \ + if (__builtin_expect (__val & FUTEX_WAITERS, 0)) \ + lll_futex_wake (__futex, 1, private); \ + })) + +#define lll_islocked(futex) \ + (futex != 0) + +/* Initializers for lock. */ +#define LLL_LOCK_INITIALIZER (0) +#define LLL_LOCK_INITIALIZER_LOCKED (1) + +/* The kernel notifies a process with uses CLONE_CLEARTID via futex + wakeup when the clone terminates. The memory location contains the + thread ID while the clone is running and is reset to zero + afterwards. */ +#define lll_wait_tid(tid) \ + do \ + { \ + __typeof (tid) __tid; \ + while ((__tid = (tid)) != 0) \ + lll_futex_wait (&(tid), __tid, LLL_SHARED); \ + } \ + while (0) + +extern int __lll_timedwait_tid (int *, const struct timespec *) + attribute_hidden; + +#define lll_timedwait_tid(tid, abstime) \ + ({ \ + int __res = 0; \ + if ((tid) != 0) \ + __res = __lll_timedwait_tid (&(tid), (abstime)); \ + __res; \ + }) + +#endif /* lowlevellock.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/pt-vfork.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/pt-vfork.S new file mode 100644 index 00000000..e8705c54 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/pt-vfork.S @@ -0,0 +1,5 @@ +#if defined(__arch64__) +#include "sparc64/pt-vfork.S" +#else +#include "sparc32/pt-vfork.S" +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/pthread_barrier_destroy.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/pthread_barrier_destroy.c new file mode 100644 index 00000000..ca96379c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/pthread_barrier_destroy.c @@ -0,0 +1,45 @@ +/* Copyright (C) 2002, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include "pthreadP.h" +#include + +int +pthread_barrier_destroy ( + pthread_barrier_t *barrier) +{ + union sparc_pthread_barrier *ibarrier; + int result = EBUSY; + + ibarrier = (union sparc_pthread_barrier *) barrier; + + int private = ibarrier->s.pshared ? LLL_SHARED : LLL_PRIVATE; + + lll_lock (ibarrier->b.lock, private); + + if (__builtin_expect (ibarrier->b.left == ibarrier->b.init_count, 1)) + /* The barrier is not used anymore. */ + result = 0; + else + /* Still used, return with an error. */ + lll_unlock (ibarrier->b.lock, private); + + return result; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/pthread_barrier_init.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/pthread_barrier_init.c new file mode 100644 index 00000000..8182f1ce --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/pthread_barrier_init.c @@ -0,0 +1,55 @@ +/* Copyright (C) 2002, 2006, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include "pthreadP.h" +#include + +int +pthread_barrier_init ( + pthread_barrier_t *barrier, + const pthread_barrierattr_t *attr, + unsigned int count) +{ + union sparc_pthread_barrier *ibarrier; + + if (__builtin_expect (count == 0, 0)) + return EINVAL; + + struct pthread_barrierattr *iattr = (struct pthread_barrierattr *) attr; + if (iattr != NULL) + { + if (iattr->pshared != PTHREAD_PROCESS_PRIVATE + && __builtin_expect (iattr->pshared != PTHREAD_PROCESS_SHARED, 0)) + /* Invalid attribute. */ + return EINVAL; + } + + ibarrier = (union sparc_pthread_barrier *) barrier; + + /* Initialize the individual fields. */ + ibarrier->b.lock = LLL_LOCK_INITIALIZER; + ibarrier->b.left = count; + ibarrier->b.init_count = count; + ibarrier->b.curr_event = 0; + ibarrier->s.left_lock = 0; + ibarrier->s.pshared = (iattr && iattr->pshared == PTHREAD_PROCESS_SHARED); + + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/pthread_barrier_wait.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/pthread_barrier_wait.c new file mode 100644 index 00000000..73eaa695 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/pthread_barrier_wait.c @@ -0,0 +1 @@ +#include "sparc32/pthread_barrier_wait.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/pthread_once.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/pthread_once.c new file mode 100644 index 00000000..24b74aca --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/pthread_once.c @@ -0,0 +1,95 @@ +/* Copyright (C) 2003, 2004, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "pthreadP.h" +#include + + +unsigned long int __fork_generation attribute_hidden; + + +static void +clear_once_control (void *arg) +{ + pthread_once_t *once_control = (pthread_once_t *) arg; + + *once_control = 0; + lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE); +} + + +int +attribute_protected +__pthread_once (once_control, init_routine) + pthread_once_t *once_control; + void (*init_routine) (void); +{ + while (1) + { + int oldval, val, newval; + + val = *once_control; + do + { + /* Check if the initialized has already been done. */ + if ((val & 2) != 0) + return 0; + + oldval = val; + newval = (oldval & 3) | __fork_generation | 1; + val = atomic_compare_and_exchange_val_acq (once_control, newval, + oldval); + } + while (__builtin_expect (val != oldval, 0)); + + /* Check if another thread already runs the initializer. */ + if ((oldval & 1) != 0) + { + /* Check whether the initializer execution was interrupted + by a fork. */ + if (((oldval ^ newval) & -4) == 0) + { + /* Same generation, some other thread was faster. Wait. */ + lll_futex_wait (once_control, newval, LLL_PRIVATE); + continue; + } + } + + /* This thread is the first here. Do the initialization. + Register a cleanup handler so that in case the thread gets + interrupted the initialization can be restarted. */ + pthread_cleanup_push (clear_once_control, once_control); + + init_routine (); + + pthread_cleanup_pop (0); + + + /* Add one to *once_control. */ + atomic_increment (once_control); + + /* Wake up all other threads. */ + lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE); + break; + } + + return 0; +} +weak_alias (__pthread_once, pthread_once) +strong_alias (__pthread_once, __pthread_once_internal) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sem_init.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sem_init.c new file mode 100644 index 00000000..f694b5e9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sem_init.c @@ -0,0 +1,57 @@ +/* Copyright (C) 2002, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include "semaphoreP.h" +#include + + +int +__new_sem_init (sem, pshared, value) + sem_t *sem; + int pshared; + unsigned int value; +{ + /* Parameter sanity check. */ + if (__builtin_expect (value > SEM_VALUE_MAX, 0)) + { + __set_errno (EINVAL); + return -1; + } + + /* Map to the internal type. */ + struct sparc_new_sem *isem = (struct sparc_new_sem *) sem; + + /* Use the values the user provided. */ + memset (isem, '\0', sizeof (*isem)); + isem->value = value; +#ifdef __ASSUME_PRIVATE_FUTEX + isem->private = pshared ? 0 : FUTEX_PRIVATE_FLAG; +#else + isem->private = pshared ? 0 : THREAD_GETMEM (THREAD_SELF, + header.private_futex); +#endif + + return 0; +} +weak_alias(__new_sem_init, sem_init) + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/clone.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/clone.S new file mode 100644 index 00000000..a6142aaf --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/clone.S @@ -0,0 +1,2 @@ +#define RESET_PID +#include diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/pt-vfork.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/pt-vfork.S new file mode 100644 index 00000000..fb01242b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/pt-vfork.S @@ -0,0 +1,45 @@ +/* Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2004. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + + .text + .globl __syscall_error +ENTRY(__vfork) + ld [%g7 + PID], %o5 + sub %g0, %o5, %o4 + st %o4, [%g7 + PID] + + LOADSYSCALL(vfork) + ta 0x10 + bcc 2f + mov %o7, %g1 + st %o5, [%g7 + PID] + call __syscall_error + mov %g1, %o7 +2: sub %o1, 1, %o1 + andcc %o0, %o1, %o0 + bne,a 1f + st %o5, [%g7 + PID] +1: retl + nop +END(__vfork) + +weak_alias (__vfork, vfork) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/pthread_barrier_wait.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/pthread_barrier_wait.c new file mode 100644 index 00000000..302d1b37 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/pthread_barrier_wait.c @@ -0,0 +1,94 @@ +/* Copyright (C) 2003, 2004, 2006, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Martin Schwidefsky , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + +/* Wait on barrier. */ +int +pthread_barrier_wait ( + pthread_barrier_t *barrier) +{ + union sparc_pthread_barrier *ibarrier + = (union sparc_pthread_barrier *) barrier; + int result = 0; + int private = ibarrier->s.pshared ? LLL_SHARED : LLL_PRIVATE; + + /* Make sure we are alone. */ + lll_lock (ibarrier->b.lock, private); + + /* One more arrival. */ + --ibarrier->b.left; + + /* Are these all? */ + if (ibarrier->b.left == 0) + { + /* Yes. Increment the event counter to avoid invalid wake-ups and + tell the current waiters that it is their turn. */ + ++ibarrier->b.curr_event; + + /* Wake up everybody. */ + lll_futex_wake (&ibarrier->b.curr_event, INT_MAX, private); + + /* This is the thread which finished the serialization. */ + result = PTHREAD_BARRIER_SERIAL_THREAD; + } + else + { + /* The number of the event we are waiting for. The barrier's event + number must be bumped before we continue. */ + unsigned int event = ibarrier->b.curr_event; + + /* Before suspending, make the barrier available to others. */ + lll_unlock (ibarrier->b.lock, private); + + /* Wait for the event counter of the barrier to change. */ + do + lll_futex_wait (&ibarrier->b.curr_event, event, private); + while (event == ibarrier->b.curr_event); + } + + /* Make sure the init_count is stored locally or in a register. */ + unsigned int init_count = ibarrier->b.init_count; + + /* If this was the last woken thread, unlock. */ + if (__atomic_is_v9 || ibarrier->s.pshared == 0) + { + if (atomic_increment_val (&ibarrier->b.left) == init_count) + /* We are done. */ + lll_unlock (ibarrier->b.lock, private); + } + else + { + unsigned int left; + /* Slightly more complicated. On pre-v9 CPUs, atomic_increment_val + is only atomic for threads within the same process, not for + multiple processes. */ + __sparc32_atomic_do_lock24 (&ibarrier->s.left_lock); + left = ++ibarrier->b.left; + __sparc32_atomic_do_unlock24 (&ibarrier->s.left_lock); + if (left == init_count) + /* We are done. */ + lll_unlock (ibarrier->b.lock, private); + } + + return result; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_post.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_post.c new file mode 100644 index 00000000..940728ee --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_post.c @@ -0,0 +1,55 @@ +/* sem_post -- post to a POSIX semaphore. SPARC version. + Copyright (C) 2003, 2004, 2006, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include + +int +__new_sem_post (sem_t *sem) +{ + struct sparc_new_sem *isem = (struct sparc_new_sem *) sem; + int nr; + + if (__atomic_is_v9) + nr = atomic_increment_val (&isem->value); + else + { + __sparc32_atomic_do_lock24 (&isem->lock); + nr = ++(isem->value); + __sparc32_atomic_do_unlock24 (&isem->lock); + } + atomic_full_barrier (); + if (isem->nwaiters > 0) + { + int err = lll_futex_wake (&isem->value, 1, + isem->private ^ FUTEX_PRIVATE_FLAG); + if (__builtin_expect (err, 0) < 0) + { + __set_errno (-err); + return -1; + } + } + return 0; +} +weak_alias(__new_sem_post, sem_post) + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_timedwait.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_timedwait.c new file mode 100644 index 00000000..aa5bd80e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_timedwait.c @@ -0,0 +1,148 @@ +/* sem_timedwait -- wait on a semaphore. SPARC version. + Copyright (C) 2003, 2006, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Paul Mackerras , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include + +#include + + +extern void __sem_wait_cleanup (void *arg) attribute_hidden; + + +int +sem_timedwait (sem_t *sem, const struct timespec *abstime) +{ + struct sparc_new_sem *isem = (struct sparc_new_sem *) sem; + int err; + int val; + + if (__atomic_is_v9) + val = atomic_decrement_if_positive (&isem->value); + else + { + __sparc32_atomic_do_lock24 (&isem->lock); + val = isem->value; + if (val > 0) + isem->value = val - 1; + __sparc32_atomic_do_unlock24 (&isem->lock); + } + + if (val > 0) + return 0; + + if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) + { + __set_errno (EINVAL); + return -1; + } + + if (__atomic_is_v9) + atomic_increment (&isem->nwaiters); + else + { + __sparc32_atomic_do_lock24 (&isem->lock); + isem->nwaiters++; + __sparc32_atomic_do_unlock24 (&isem->lock); + } + + pthread_cleanup_push (__sem_wait_cleanup, isem); + + while (1) + { + struct timeval tv; + struct timespec rt; + int sec, nsec; + + /* Get the current time. */ + __gettimeofday (&tv, NULL); + + /* Compute relative timeout. */ + sec = abstime->tv_sec - tv.tv_sec; + nsec = abstime->tv_nsec - tv.tv_usec * 1000; + if (nsec < 0) + { + nsec += 1000000000; + --sec; + } + + /* Already timed out? */ + err = -ETIMEDOUT; + if (sec < 0) + { + __set_errno (ETIMEDOUT); + err = -1; + break; + } + + /* Do wait. */ + rt.tv_sec = sec; + rt.tv_nsec = nsec; + + /* Enable asynchronous cancellation. Required by the standard. */ + int oldtype = __pthread_enable_asynccancel (); + + err = lll_futex_timed_wait (&isem->value, 0, &rt, + isem->private ^ FUTEX_PRIVATE_FLAG); + + /* Disable asynchronous cancellation. */ + __pthread_disable_asynccancel (oldtype); + + if (err != 0 && err != -EWOULDBLOCK) + { + __set_errno (-err); + err = -1; + break; + } + + if (__atomic_is_v9) + val = atomic_decrement_if_positive (&isem->value); + else + { + __sparc32_atomic_do_lock24 (&isem->lock); + val = isem->value; + if (val > 0) + isem->value = val - 1; + __sparc32_atomic_do_unlock24 (&isem->lock); + } + + if (val > 0) + { + err = 0; + break; + } + } + + pthread_cleanup_pop (0); + + if (__atomic_is_v9) + atomic_decrement (&isem->nwaiters); + else + { + __sparc32_atomic_do_lock24 (&isem->lock); + isem->nwaiters--; + __sparc32_atomic_do_unlock24 (&isem->lock); + } + + return err; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_trywait.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_trywait.c new file mode 100644 index 00000000..d4e89380 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_trywait.c @@ -0,0 +1,54 @@ +/* sem_trywait -- wait on a semaphore. SPARC version. + Copyright (C) 2003, 2006, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Paul Mackerras , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include + + +int +__new_sem_trywait (sem_t *sem) +{ + struct sparc_old_sem *isem = (struct sparc_old_sem *) sem; + int val; + + if (isem->value > 0) + { + if (__atomic_is_v9) + val = atomic_decrement_if_positive (&isem->value); + else + { + __sparc32_atomic_do_lock24 (&isem->lock); + val = isem->value; + if (val > 0) + isem->value = val - 1; + __sparc32_atomic_do_unlock24 (&isem->lock); + } + if (val > 0) + return 0; + } + + __set_errno (EAGAIN); + return -1; +} +weak_alias(__new_sem_trywait, sem_trywait) + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_wait.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_wait.c new file mode 100644 index 00000000..cfe04a80 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sem_wait.c @@ -0,0 +1,127 @@ +/* sem_wait -- wait on a semaphore. Generic futex-using version. + Copyright (C) 2003, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Paul Mackerras , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include + +#include + + +void +attribute_hidden +__sem_wait_cleanup (void *arg) +{ + struct sparc_new_sem *isem = (struct sparc_new_sem *) arg; + + if (__atomic_is_v9) + atomic_decrement (&isem->nwaiters); + else + { + __sparc32_atomic_do_lock24 (&isem->lock); + isem->nwaiters--; + __sparc32_atomic_do_unlock24 (&isem->lock); + } +} + + +int +__new_sem_wait (sem_t *sem) +{ + struct sparc_new_sem *isem = (struct sparc_new_sem *) sem; + int err; + int val; + + if (__atomic_is_v9) + val = atomic_decrement_if_positive (&isem->value); + else + { + __sparc32_atomic_do_lock24 (&isem->lock); + val = isem->value; + if (val > 0) + isem->value = val - 1; + else + isem->nwaiters++; + __sparc32_atomic_do_unlock24 (&isem->lock); + } + + if (val > 0) + return 0; + + if (__atomic_is_v9) + atomic_increment (&isem->nwaiters); + else + /* Already done above while still holding isem->lock. */; + + pthread_cleanup_push (__sem_wait_cleanup, isem); + + while (1) + { + /* Enable asynchronous cancellation. Required by the standard. */ + int oldtype = __pthread_enable_asynccancel (); + + err = lll_futex_wait (&isem->value, 0, + isem->private ^ FUTEX_PRIVATE_FLAG); + + /* Disable asynchronous cancellation. */ + __pthread_disable_asynccancel (oldtype); + + if (err != 0 && err != -EWOULDBLOCK) + { + __set_errno (-err); + err = -1; + break; + } + + if (__atomic_is_v9) + val = atomic_decrement_if_positive (&isem->value); + else + { + __sparc32_atomic_do_lock24 (&isem->lock); + val = isem->value; + if (val > 0) + isem->value = val - 1; + __sparc32_atomic_do_unlock24 (&isem->lock); + } + + if (val > 0) + { + err = 0; + break; + } + } + + pthread_cleanup_pop (0); + + if (__atomic_is_v9) + atomic_decrement (&isem->nwaiters); + else + { + __sparc32_atomic_do_lock24 (&isem->lock); + isem->nwaiters--; + __sparc32_atomic_do_unlock24 (&isem->lock); + } + + return err; +} +weak_alias(__new_sem_wait, sem_wait) + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sysdep-cancel.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sysdep-cancel.h new file mode 100644 index 00000000..1f55bd62 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sysdep-cancel.h @@ -0,0 +1,112 @@ +/* Copyright (C) 2002, 2003, 2004, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#ifndef __ASSEMBLER__ +# include +#endif + +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + +# undef PSEUDO +# define PSEUDO(name, syscall_name, args) \ + .text; \ + .globl __syscall_error; \ +ENTRY(name) \ + ld [%g7 + MULTIPLE_THREADS_OFFSET], %g1;\ + cmp %g1, 0; \ + bne 1f; \ +.type __##syscall_name##_nocancel,@function; \ +.globl __##syscall_name##_nocancel; \ +__##syscall_name##_nocancel: \ + mov SYS_ify(syscall_name), %g1; \ + ta 0x10; \ + bcc 8f; \ + mov %o7, %g1; \ + call __syscall_error; \ + mov %g1, %o7; \ +8: jmpl %o7 + 8, %g0; \ + nop; \ +.size __##syscall_name##_nocancel,.-__##syscall_name##_nocancel;\ +1: save %sp, -96, %sp; \ + cfi_def_cfa_register(%fp); \ + cfi_window_save; \ + cfi_register(%o7, %i7); \ + CENABLE; \ + nop; \ + mov %o0, %l0; \ + COPY_ARGS_##args \ + mov SYS_ify(syscall_name), %g1; \ + ta 0x10; \ + bcc 1f; \ + mov %o0, %l1; \ + CDISABLE; \ + mov %l0, %o0; \ + call __syscall_error; \ + mov %l1, %o0; \ + b 2f; \ + mov -1, %l1; \ +1: CDISABLE; \ + mov %l0, %o0; \ +2: jmpl %i7 + 8, %g0; \ + restore %g0, %l1, %o0; + + +# ifdef IS_IN_libpthread +# define CENABLE call __pthread_enable_asynccancel +# define CDISABLE call __pthread_disable_asynccancel +# elif !defined NOT_IN_libc +# define CENABLE call __libc_enable_asynccancel +# define CDISABLE call __libc_disable_asynccancel +# elif defined IS_IN_librt +# define CENABLE call __librt_enable_asynccancel +# define CDISABLE call __librt_disable_asynccancel +# else +# error Unsupported library +# endif + +#define COPY_ARGS_0 /* Nothing */ +#define COPY_ARGS_1 COPY_ARGS_0 mov %i0, %o0; +#define COPY_ARGS_2 COPY_ARGS_1 mov %i1, %o1; +#define COPY_ARGS_3 COPY_ARGS_2 mov %i2, %o2; +#define COPY_ARGS_4 COPY_ARGS_3 mov %i3, %o3; +#define COPY_ARGS_5 COPY_ARGS_4 mov %i4, %o4; +#define COPY_ARGS_6 COPY_ARGS_5 mov %i5, %o5; + +# ifndef __ASSEMBLER__ +# define SINGLE_THREAD_P \ + __builtin_expect (THREAD_GETMEM (THREAD_SELF, \ + header.multiple_threads) == 0, 1) +# else +# define SINGLE_THREAD_P ld [%g7 + MULTIPLE_THREADS_OFFSET], %g1 +# endif + +#elif !defined __ASSEMBLER__ + +# define SINGLE_THREAD_P (1) +# define NO_CANCELLATION 1 + +#endif + +#ifndef __ASSEMBLER__ +# define RTLD_SINGLE_THREAD_P \ + __builtin_expect (THREAD_GETMEM (THREAD_SELF, \ + header.multiple_threads) == 0, 1) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/vfork.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/vfork.S new file mode 100644 index 00000000..8ee98684 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/vfork.S @@ -0,0 +1,49 @@ +/* Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2004. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + + .text + .globl __syscall_error +ENTRY(__vfork) + ld [%g7 + PID], %o5 + cmp %o5, 0 + bne 1f + sub %g0, %o5, %o4 + sethi %hi(0x80000000), %o4 +1: st %o4, [%g7 + PID] + + LOADSYSCALL(vfork) + ta 0x10 + bcc 2f + mov %o7, %g1 + st %o5, [%g7 + PID] + call __syscall_error + mov %g1, %o7 +2: sub %o1, 1, %o1 + andcc %o0, %o1, %o0 + bne,a 1f + st %o5, [%g7 + PID] +1: retl + nop +END(__vfork) + +libc_hidden_def (vfork) +weak_alias (__vfork, vfork) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/clone.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/clone.S new file mode 100644 index 00000000..64e3bfc1 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/clone.S @@ -0,0 +1,2 @@ +#define RESET_PID +#include diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/pt-vfork.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/pt-vfork.S new file mode 100644 index 00000000..8941043c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/pt-vfork.S @@ -0,0 +1,45 @@ +/* Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2004. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + + .text + .globl __syscall_error +ENTRY(__vfork) + ld [%g7 + PID], %o5 + sub %g0, %o5, %o4 + st %o4, [%g7 + PID] + + LOADSYSCALL(vfork) + ta 0x6d + bcc,pt %xcc, 2f + mov %o7, %g1 + st %o5, [%g7 + PID] + call __syscall_error + mov %g1, %o7 +2: sub %o1, 1, %o1 + andcc %o0, %o1, %o0 + bne,a,pt %icc, 1f + st %o5, [%g7 + PID] +1: retl + nop +END(__vfork) + +weak_alias (__vfork, vfork) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/sysdep-cancel.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/sysdep-cancel.h new file mode 100644 index 00000000..aec2d4a8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/sysdep-cancel.h @@ -0,0 +1,110 @@ +/* Copyright (C) 2002, 2003, 2004, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#ifndef __ASSEMBLER__ +# include +#endif + +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + +# undef PSEUDO +# define PSEUDO(name, syscall_name, args) \ + .text; \ + .globl __syscall_error; \ +ENTRY(name) \ + ld [%g7 + MULTIPLE_THREADS_OFFSET], %g1;\ + brnz,pn %g1, 1f; \ +.type __##syscall_name##_nocancel,@function; \ +.globl __##syscall_name##_nocancel; \ +__##syscall_name##_nocancel: \ + mov SYS_ify(syscall_name), %g1; \ + ta 0x6d; \ + bcc,pt %xcc, 8f; \ + mov %o7, %g1; \ + call __syscall_error; \ + mov %g1, %o7; \ +8: jmpl %o7 + 8, %g0; \ + nop; \ +.size __##syscall_name##_nocancel,.-__##syscall_name##_nocancel;\ +1: save %sp, -192, %sp; \ + cfi_def_cfa_register(%fp); \ + cfi_window_save; \ + cfi_register(%o7, %i7); \ + CENABLE; \ + nop; \ + mov %o0, %l0; \ + COPY_ARGS_##args \ + mov SYS_ify(syscall_name), %g1; \ + ta 0x6d; \ + bcc,pt %xcc, 1f; \ + mov %o0, %l1; \ + CDISABLE; \ + mov %l0, %o0; \ + call __syscall_error; \ + mov %l1, %o0; \ + ba,pt %xcc, 2f; \ + mov -1, %l1; \ +1: CDISABLE; \ + mov %l0, %o0; \ +2: jmpl %i7 + 8, %g0; \ + restore %g0, %l1, %o0; + +# ifdef IS_IN_libpthread +# define CENABLE call __pthread_enable_asynccancel +# define CDISABLE call __pthread_disable_asynccancel +# elif !defined NOT_IN_libc +# define CENABLE call __libc_enable_asynccancel +# define CDISABLE call __libc_disable_asynccancel +# elif defined IS_IN_librt +# define CENABLE call __librt_enable_asynccancel +# define CDISABLE call __librt_disable_asynccancel +# else +# error Unsupported library +# endif + +#define COPY_ARGS_0 /* Nothing */ +#define COPY_ARGS_1 COPY_ARGS_0 mov %i0, %o0; +#define COPY_ARGS_2 COPY_ARGS_1 mov %i1, %o1; +#define COPY_ARGS_3 COPY_ARGS_2 mov %i2, %o2; +#define COPY_ARGS_4 COPY_ARGS_3 mov %i3, %o3; +#define COPY_ARGS_5 COPY_ARGS_4 mov %i4, %o4; +#define COPY_ARGS_6 COPY_ARGS_5 mov %i5, %o5; + +# ifndef __ASSEMBLER__ +# define SINGLE_THREAD_P \ + __builtin_expect (THREAD_GETMEM (THREAD_SELF, \ + header.multiple_threads) == 0, 1) +# else +# define SINGLE_THREAD_P ld [%g7 + MULTIPLE_THREADS_OFFSET], %g1 +# endif + +#elif !defined __ASSEMBLER__ + +# define SINGLE_THREAD_P (1) +# define NO_CANCELLATION 1 + +#endif + +#ifndef __ASSEMBLER__ +# define RTLD_SINGLE_THREAD_P \ + __builtin_expect (THREAD_GETMEM (THREAD_SELF, \ + header.multiple_threads) == 0, 1) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/timer_create.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/timer_create.c new file mode 100644 index 00000000..0a9c3372 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/timer_create.c @@ -0,0 +1 @@ +#include "../../x86_64/timer_create.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/timer_delete.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/timer_delete.c new file mode 100644 index 00000000..f0d4fd21 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/timer_delete.c @@ -0,0 +1 @@ +#include "../../x86_64/timer_delete.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/timer_getoverr.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/timer_getoverr.c new file mode 100644 index 00000000..82121a7a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/timer_getoverr.c @@ -0,0 +1 @@ +#include "../../x86_64/timer_getoverr.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/timer_gettime.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/timer_gettime.c new file mode 100644 index 00000000..313c05fe --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/timer_gettime.c @@ -0,0 +1 @@ +#include "../../x86_64/timer_gettime.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/timer_settime.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/timer_settime.c new file mode 100644 index 00000000..76f549cb --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/timer_settime.c @@ -0,0 +1 @@ +#include "../../x86_64/timer_settime.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/vfork.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/vfork.S new file mode 100644 index 00000000..b4e89ace --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sparc64/vfork.S @@ -0,0 +1,49 @@ +/* Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2004. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + + .text + .globl __syscall_error +ENTRY(__vfork) + ld [%g7 + PID], %o5 + sethi %hi(0x80000000), %o3 + cmp %o5, 0 + sub %g0, %o5, %o4 + move %icc, %o3, %o4 + st %o4, [%g7 + PID] + + LOADSYSCALL(vfork) + ta 0x6d + bcc,pt %xcc, 2f + mov %o7, %g1 + st %o5, [%g7 + PID] + call __syscall_error + mov %g1, %o7 +2: sub %o1, 1, %o1 + andcc %o0, %o1, %o0 + bne,a,pt %icc, 1f + st %o5, [%g7 + PID] +1: retl + nop +END(__vfork) + +hidden_def (vfork) +weak_alias (__vfork, vfork) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sysdep-cancel.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sysdep-cancel.h new file mode 100644 index 00000000..5be9beb9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/sysdep-cancel.h @@ -0,0 +1,5 @@ +#if defined(__arch64__) +#include "sparc64/sysdep-cancel.h" +#else +#include "sparc32/sysdep-cancel.h" +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/vfork.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/vfork.S new file mode 100644 index 00000000..160cd0b1 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/sparc/vfork.S @@ -0,0 +1,5 @@ +#if defined(__arch64__) +#include "sparc64/vfork.S" +#else +#include "sparc32/vfork.S" +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/structsem.sym b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/structsem.sym new file mode 100644 index 00000000..0e2a15f2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/structsem.sym @@ -0,0 +1,12 @@ +#include +#include +#include +#include +#include "internaltypes.h" + +-- + +VALUE offsetof (struct new_sem, value) +PRIVATE offsetof (struct new_sem, private) +NWAITERS offsetof (struct new_sem, nwaiters) +SEM_VALUE_MAX SEM_VALUE_MAX diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/timer_create.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/timer_create.c new file mode 100644 index 00000000..a7da2a09 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/timer_create.c @@ -0,0 +1,243 @@ +/* Copyright (C) 2003,2004, 2007, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "kernel-posix-timers.h" +#include "kernel-posix-cpu-timers.h" + + +#ifdef __NR_timer_create +# ifndef __ASSUME_POSIX_TIMERS +static int compat_timer_create (clockid_t clock_id, struct sigevent *evp, + timer_t *timerid); +# define timer_create static compat_timer_create +# include +# undef timer_create + +/* Nonzero if the system calls are not available. */ +int __no_posix_timers attribute_hidden; +# endif + +# ifdef timer_create_alias +# define timer_create timer_create_alias +# endif + + +int +timer_create ( + clockid_t clock_id, + struct sigevent *evp, + timer_t *timerid) +{ +# undef timer_create +# ifndef __ASSUME_POSIX_TIMERS + if (__no_posix_timers >= 0) +# endif + { + clockid_t syscall_clockid = (clock_id == CLOCK_PROCESS_CPUTIME_ID + ? MAKE_PROCESS_CPUCLOCK (0, CPUCLOCK_SCHED) + : clock_id == CLOCK_THREAD_CPUTIME_ID + ? MAKE_THREAD_CPUCLOCK (0, CPUCLOCK_SCHED) + : clock_id); + + /* If the user wants notification via a thread we need to handle + this special. */ + if (evp == NULL + || __builtin_expect (evp->sigev_notify != SIGEV_THREAD, 1)) + { + struct sigevent local_evp; + + /* We avoid allocating too much memory by basically + using struct timer as a derived class with the + first two elements being in the superclass. We only + need these two elements here. */ + struct timer *newp = (struct timer *) malloc (offsetof (struct timer, + thrfunc)); + if (newp == NULL) + /* No more memory. */ + return -1; + + if (evp == NULL) + { + /* The kernel has to pass up the timer ID which is a + userlevel object. Therefore we cannot leave it up to + the kernel to determine it. */ + local_evp.sigev_notify = SIGEV_SIGNAL; + local_evp.sigev_signo = SIGALRM; + local_evp.sigev_value.sival_ptr = newp; + + evp = &local_evp; + } + + kernel_timer_t ktimerid; + int retval = INLINE_SYSCALL (timer_create, 3, syscall_clockid, evp, + &ktimerid); + +# ifndef __ASSUME_POSIX_TIMERS + if (retval != -1 || errno != ENOSYS) +# endif + { +# ifndef __ASSUME_POSIX_TIMERS + __no_posix_timers = 1; +# endif + + if (retval != -1) + { + newp->sigev_notify = (evp != NULL + ? evp->sigev_notify : SIGEV_SIGNAL); + newp->ktimerid = ktimerid; + + *timerid = (timer_t) newp; + } + else + { + /* Cannot allocate the timer, fail. */ + free (newp); + retval = -1; + } + + return retval; + } + + free (newp); + +# ifndef __ASSUME_POSIX_TIMERS + /* When we come here the syscall does not exist. Make sure we + do not try to use it again. */ + __no_posix_timers = -1; +# endif + } + else + { +# ifndef __ASSUME_POSIX_TIMERS + /* Make sure we have the necessary kernel support. */ + if (__no_posix_timers == 0) + { + INTERNAL_SYSCALL_DECL (err); + struct timespec ts; + int res; + res = INTERNAL_SYSCALL (clock_getres, err, 2, + CLOCK_REALTIME, &ts); + __no_posix_timers = (INTERNAL_SYSCALL_ERROR_P (res, err) + ? -1 : 1); + } + + if (__no_posix_timers > 0) +# endif + { + /* Create the helper thread. */ + pthread_once (&__helper_once, __start_helper_thread); + if (__helper_tid == 0) + { + /* No resources to start the helper thread. */ + __set_errno (EAGAIN); + return -1; + } + + struct timer *newp; + newp = (struct timer *) malloc (sizeof (struct timer)); + if (newp == NULL) + return -1; + + /* Copy the thread parameters the user provided. */ + newp->sival = evp->sigev_value; + newp->thrfunc = evp->sigev_notify_function; + newp->sigev_notify = SIGEV_THREAD; + + /* We cannot simply copy the thread attributes since the + implementation might keep internal information for + each instance. */ + (void) pthread_attr_init (&newp->attr); + if (evp->sigev_notify_attributes != NULL) + { + struct pthread_attr *nattr; + struct pthread_attr *oattr; + + nattr = (struct pthread_attr *) &newp->attr; + oattr = (struct pthread_attr *) evp->sigev_notify_attributes; + + nattr->schedparam = oattr->schedparam; + nattr->schedpolicy = oattr->schedpolicy; + nattr->flags = oattr->flags; + nattr->guardsize = oattr->guardsize; + nattr->stackaddr = oattr->stackaddr; + nattr->stacksize = oattr->stacksize; + } + + /* In any case set the detach flag. */ + (void) pthread_attr_setdetachstate (&newp->attr, + PTHREAD_CREATE_DETACHED); + + /* Create the event structure for the kernel timer. */ + struct sigevent sev = + { .sigev_value.sival_ptr = newp, + .sigev_signo = SIGTIMER, + .sigev_notify = SIGEV_SIGNAL | SIGEV_THREAD_ID, + ._sigev_un = { ._pad = { [0] = __helper_tid } } }; + + /* Create the timer. */ + INTERNAL_SYSCALL_DECL (err); + int res; + res = INTERNAL_SYSCALL (timer_create, err, 3, + syscall_clockid, &sev, &newp->ktimerid); + if (! INTERNAL_SYSCALL_ERROR_P (res, err)) + { + /* Add to the queue of active timers with thread + delivery. */ + pthread_mutex_lock (&__active_timer_sigev_thread_lock); + newp->next = __active_timer_sigev_thread; + __active_timer_sigev_thread = newp; + pthread_mutex_unlock (&__active_timer_sigev_thread_lock); + + *timerid = (timer_t) newp; + return 0; + } + + /* Free the resources. */ + free (newp); + + __set_errno (INTERNAL_SYSCALL_ERRNO (res, err)); + + return -1; + } + } + } + +# ifndef __ASSUME_POSIX_TIMERS + /* Compatibility code. */ + return compat_timer_create (clock_id, evp, timerid); +# endif +} +#else +# ifdef timer_create_alias +# define timer_create timer_create_alias +# endif +/* The new system calls are not available. Use the userlevel + implementation. */ +# include +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/timer_delete.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/timer_delete.c new file mode 100644 index 00000000..5ad40b99 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/timer_delete.c @@ -0,0 +1,115 @@ +/* Copyright (C) 2003, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include +#include +#include "kernel-posix-timers.h" + + +#ifdef __NR_timer_delete +# ifndef __ASSUME_POSIX_TIMERS +static int compat_timer_delete (timer_t timerid); +# define timer_delete static compat_timer_delete +# include +# undef timer_delete +# endif + +# ifdef timer_delete_alias +# define timer_delete timer_delete_alias +# endif + + +int +timer_delete ( + timer_t timerid) +{ +# undef timer_delete +# ifndef __ASSUME_POSIX_TIMERS + if (__no_posix_timers >= 0) +# endif + { + struct timer *kt = (struct timer *) timerid; + + /* Delete the kernel timer object. */ + int res = INLINE_SYSCALL (timer_delete, 1, kt->ktimerid); + + if (res == 0) + { + if (kt->sigev_notify == SIGEV_THREAD) + { + /* Remove the timer from the list. */ + pthread_mutex_lock (&__active_timer_sigev_thread_lock); + if (__active_timer_sigev_thread == kt) + __active_timer_sigev_thread = kt->next; + else + { + struct timer *prevp = __active_timer_sigev_thread; + while (prevp->next != NULL) + if (prevp->next == kt) + { + prevp->next = kt->next; + break; + } + else + prevp = prevp->next; + } + pthread_mutex_unlock (&__active_timer_sigev_thread_lock); + } + +# ifndef __ASSUME_POSIX_TIMERS + /* We know the syscall support is available. */ + __no_posix_timers = 1; +# endif + + /* Free the memory. */ + (void) free (kt); + + return 0; + } + + /* The kernel timer is not known or something else bad happened. + Return the error. */ +# ifndef __ASSUME_POSIX_TIMERS + if (errno != ENOSYS) + { + __no_posix_timers = 1; +# endif + return -1; +# ifndef __ASSUME_POSIX_TIMERS + } + + __no_posix_timers = -1; +# endif + } + +# ifndef __ASSUME_POSIX_TIMERS + return compat_timer_delete (timerid); +# endif +} +#else +# ifdef timer_delete_alias +# define timer_delete timer_delete_alias +# endif +/* The new system calls are not available. Use the userlevel + implementation. */ +# include +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/timer_getoverr.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/timer_getoverr.c new file mode 100644 index 00000000..62a558ae --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/timer_getoverr.c @@ -0,0 +1,81 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include +#include "kernel-posix-timers.h" + + +#ifdef __NR_timer_getoverrun +# ifndef __ASSUME_POSIX_TIMERS +static int compat_timer_getoverrun (timer_t timerid); +# define timer_getoverrun static compat_timer_getoverrun +# include +# undef timer_getoverrun +# endif + +# ifdef timer_getoverrun_alias +# define timer_getoverrun timer_getoverrun_alias +# endif + + +int +timer_getoverrun ( + timer_t timerid) +{ +# undef timer_getoverrun +# ifndef __ASSUME_POSIX_TIMERS + if (__no_posix_timers >= 0) +# endif + { + struct timer *kt = (struct timer *) timerid; + + /* Get the information from the kernel. */ + int res = INLINE_SYSCALL (timer_getoverrun, 1, kt->ktimerid); + +# ifndef __ASSUME_POSIX_TIMERS + if (res != -1 || errno != ENOSYS) + { + /* We know the syscall support is available. */ + __no_posix_timers = 1; +# endif + return res; +# ifndef __ASSUME_POSIX_TIMERS + } +# endif + +# ifndef __ASSUME_POSIX_TIMERS + __no_posix_timers = -1; +# endif + } + +# ifndef __ASSUME_POSIX_TIMERS + return compat_timer_getoverrun (timerid); +# endif +} +#else +# ifdef timer_getoverrun_alias +# define timer_getoverrun timer_getoverrun_alias +# endif +/* The new system calls are not available. Use the userlevel + implementation. */ +# include +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/timer_gettime.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/timer_gettime.c new file mode 100644 index 00000000..31401b19 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/timer_gettime.c @@ -0,0 +1,83 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include +#include +#include "kernel-posix-timers.h" + + +#ifdef __NR_timer_gettime +# ifndef __ASSUME_POSIX_TIMERS +static int compat_timer_gettime (timer_t timerid, struct itimerspec *value); +# define timer_gettime static compat_timer_gettime +# include +# undef timer_gettime +# endif + +# ifdef timer_gettime_alias +# define timer_gettime timer_gettime_alias +# endif + + +int +timer_gettime ( + timer_t timerid, + struct itimerspec *value) +{ +# undef timer_gettime +# ifndef __ASSUME_POSIX_TIMERS + if (__no_posix_timers >= 0) +# endif + { + struct timer *kt = (struct timer *) timerid; + + /* Delete the kernel timer object. */ + int res = INLINE_SYSCALL (timer_gettime, 2, kt->ktimerid, value); + +# ifndef __ASSUME_POSIX_TIMERS + if (res != -1 || errno != ENOSYS) + { + /* We know the syscall support is available. */ + __no_posix_timers = 1; +# endif + return res; +# ifndef __ASSUME_POSIX_TIMERS + } +# endif + +# ifndef __ASSUME_POSIX_TIMERS + __no_posix_timers = -1; +# endif + } + +# ifndef __ASSUME_POSIX_TIMERS + return compat_timer_gettime (timerid, value); +# endif +} +#else +# ifdef timer_gettime_alias +# define timer_gettime timer_gettime_alias +# endif +/* The new system calls are not available. Use the userlevel + implementation. */ +# include +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/timer_routines.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/timer_routines.c new file mode 100644 index 00000000..4319d8db --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/timer_routines.c @@ -0,0 +1,204 @@ +/* Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include +#include +#include +#include +#include "kernel-posix-timers.h" + + +/* List of active SIGEV_THREAD timers. */ +struct timer *__active_timer_sigev_thread; +/* Lock for the __active_timer_sigev_thread. */ +pthread_mutex_t __active_timer_sigev_thread_lock = PTHREAD_MUTEX_INITIALIZER; + + +struct thread_start_data +{ + void (*thrfunc) (sigval_t); + sigval_t sival; +}; + + +#ifdef __NR_timer_create +/* Helper thread to call the user-provided function. */ +static void * +timer_sigev_thread (void *arg) +{ + /* The parent thread has all signals blocked. This is a bit + surprising for user code, although valid. We unblock all + signals. */ + sigset_t ss; + sigemptyset (&ss); + INTERNAL_SYSCALL_DECL (err); + INTERNAL_SYSCALL (rt_sigprocmask, err, 4, SIG_SETMASK, &ss, NULL, _NSIG / 8); + + struct thread_start_data *td = (struct thread_start_data *) arg; + + void (*thrfunc) (sigval_t) = td->thrfunc; + sigval_t sival = td->sival; + + /* The TD object was allocated in timer_helper_thread. */ + free (td); + + /* Call the user-provided function. */ + thrfunc (sival); + + return NULL; +} + + +/* Helper function to support starting threads for SIGEV_THREAD. */ +static void * +timer_helper_thread (void *arg) +{ + /* Wait for the SIGTIMER signal, allowing the setXid signal, and + none else. */ + sigset_t ss; + sigemptyset (&ss); + __sigaddset (&ss, SIGTIMER); + + /* Endless loop of waiting for signals. The loop is only ended when + the thread is canceled. */ + while (1) + { + siginfo_t si; + + /* sigwaitinfo cannot be used here, since it deletes + SIGCANCEL == SIGTIMER from the set. */ + + int oldtype = LIBC_CANCEL_ASYNC (); + + /* XXX The size argument hopefully will have to be changed to the + real size of the user-level sigset_t. */ + int result = INLINE_SYSCALL (rt_sigtimedwait, 4, &ss, &si, NULL, + _NSIG / 8); + + LIBC_CANCEL_RESET (oldtype); + + if (result > 0) + { + if (si.si_code == SI_TIMER) + { + struct timer *tk = (struct timer *) si.si_ptr; + + /* Check the timer is still used and will not go away + while we are reading the values here. */ + pthread_mutex_lock (&__active_timer_sigev_thread_lock); + + struct timer *runp = __active_timer_sigev_thread; + while (runp != NULL) + if (runp == tk) + break; + else + runp = runp->next; + + if (runp != NULL) + { + struct thread_start_data *td = malloc (sizeof (*td)); + + /* There is not much we can do if the allocation fails. */ + if (td != NULL) + { + /* This is the signal we are waiting for. */ + td->thrfunc = tk->thrfunc; + td->sival = tk->sival; + + pthread_t th; + (void) pthread_create (&th, &tk->attr, + timer_sigev_thread, td); + } + } + + pthread_mutex_unlock (&__active_timer_sigev_thread_lock); + } + else if (si.si_code == SI_TKILL) + /* The thread is canceled. */ + pthread_exit (NULL); + } + } +} + + +/* Control variable for helper thread creation. */ +pthread_once_t __helper_once attribute_hidden; + + +/* TID of the helper thread. */ +pid_t __helper_tid attribute_hidden; + + +/* Reset variables so that after a fork a new helper thread gets started. */ +static void +reset_helper_control (void) +{ + __helper_once = PTHREAD_ONCE_INIT; + __helper_tid = 0; +} + + +void +attribute_hidden +__start_helper_thread (void) +{ + /* The helper thread needs only very little resources + and should go away automatically when canceled. */ + pthread_attr_t attr; + (void) pthread_attr_init (&attr); + (void) pthread_attr_setstacksize (&attr, PTHREAD_STACK_MIN); + + /* Block all signals in the helper thread but SIGSETXID. To do this + thoroughly we temporarily have to block all signals here. The + helper can lose wakeups if SIGCANCEL is not blocked throughout, + but sigfillset omits it SIGSETXID. So, we add SIGCANCEL back + explicitly here. */ + sigset_t ss; + sigset_t oss; + sigfillset (&ss); + /*__sigaddset (&ss, SIGCANCEL); - already done by sigfillset */ + INTERNAL_SYSCALL_DECL (err); + INTERNAL_SYSCALL (rt_sigprocmask, err, 4, SIG_SETMASK, &ss, &oss, _NSIG / 8); + + /* Create the helper thread for this timer. */ + pthread_t th; + int res = pthread_create (&th, &attr, timer_helper_thread, NULL); + if (res == 0) + /* We managed to start the helper thread. */ + __helper_tid = ((struct pthread *) th)->tid; + + /* Restore the signal mask. */ + INTERNAL_SYSCALL (rt_sigprocmask, err, 4, SIG_SETMASK, &oss, NULL, + _NSIG / 8); + + /* No need for the attribute anymore. */ + (void) pthread_attr_destroy (&attr); + + /* We have to make sure that after fork()ing a new helper thread can + be created. */ + pthread_atfork (NULL, NULL, reset_helper_control); +} +#endif + +#ifndef __ASSUME_POSIX_TIMERS +# include +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/timer_settime.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/timer_settime.c new file mode 100644 index 00000000..8c6ad91f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/timer_settime.c @@ -0,0 +1,88 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include +#include +#include "kernel-posix-timers.h" + + +#ifdef __NR_timer_settime +# ifndef __ASSUME_POSIX_TIMERS +static int compat_timer_settime (timer_t timerid, int flags, + const struct itimerspec *value, + struct itimerspec *ovalue); +# define timer_settime static compat_timer_settime +# include +# undef timer_settime +# endif + +# ifdef timer_settime_alias +# define timer_settime timer_settime_alias +# endif + + +int +timer_settime ( + timer_t timerid, + int flags, + const struct itimerspec *value, + struct itimerspec *ovalue) +{ +# undef timer_settime +# ifndef __ASSUME_POSIX_TIMERS + if (__no_posix_timers >= 0) +# endif + { + struct timer *kt = (struct timer *) timerid; + + /* Delete the kernel timer object. */ + int res = INLINE_SYSCALL (timer_settime, 4, kt->ktimerid, flags, + value, ovalue); + +# ifndef __ASSUME_POSIX_TIMERS + if (res != -1 || errno != ENOSYS) + { + /* We know the syscall support is available. */ + __no_posix_timers = 1; +# endif + return res; +# ifndef __ASSUME_POSIX_TIMERS + } +# endif + +# ifndef __ASSUME_POSIX_TIMERS + __no_posix_timers = -1; +# endif + } + +# ifndef __ASSUME_POSIX_TIMERS + return compat_timer_settime (timerid, flags, value, ovalue); +# endif +} +#else +# ifdef timer_settime_alias +# define timer_settime timer_settime_alias +# endif +/* The new system calls are not available. Use the userlevel + implementation. */ +# include +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/unregister-atfork.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/unregister-atfork.c new file mode 100644 index 00000000..7eb095fd --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/unregister-atfork.c @@ -0,0 +1,123 @@ +/* Copyright (C) 2002, 2003, 2005, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include + + +void +__unregister_atfork ( + void *dso_handle) +{ + /* Check whether there is any entry in the list which we have to + remove. It is likely that this is not the case so don't bother + getting the lock. + + We do not worry about other threads adding entries for this DSO + right this moment. If this happens this is a race and we can do + whatever we please. The program will crash anyway seen. */ + struct fork_handler *runp = __fork_handlers; + struct fork_handler *lastp = NULL; + + while (runp != NULL) + if (runp->dso_handle == dso_handle) + break; + else + { + lastp = runp; + runp = runp->next; + } + + if (runp == NULL) + /* Nothing to do. */ + return; + + /* Get the lock to not conflict with additions or deletions. Note + that there couldn't have been another thread deleting something. + The __unregister_atfork function is only called from the + dlclose() code which itself serializes the operations. */ + lll_lock (__fork_lock, LLL_PRIVATE); + + /* We have to create a new list with all the entries we don't remove. */ + struct deleted_handler + { + struct fork_handler *handler; + struct deleted_handler *next; + } *deleted = NULL; + + /* Remove the entries for the DSO which is unloaded from the list. + It's a single linked list so readers are. */ + do + { + again: + if (runp->dso_handle == dso_handle) + { + if (lastp == NULL) + { + /* We have to use an atomic operation here because + __linkin_atfork also uses one. */ + if (catomic_compare_and_exchange_bool_acq (&__fork_handlers, + runp->next, runp) + != 0) + { + runp = __fork_handlers; + goto again; + } + } + else + lastp->next = runp->next; + + /* We cannot overwrite the ->next element now. Put the deleted + entries in a separate list. */ + struct deleted_handler *newp = alloca (sizeof (*newp)); + newp->handler = runp; + newp->next = deleted; + deleted = newp; + } + else + lastp = runp; + + runp = runp->next; + } + while (runp != NULL); + + /* Release the lock. */ + lll_unlock (__fork_lock, LLL_PRIVATE); + + /* Walk the list of all entries which have to be deleted. */ + while (deleted != NULL) + { + /* We need to be informed by possible current users. */ + deleted->handler->need_signal = 1; + /* Make sure this gets written out first. */ + atomic_write_barrier (); + + /* Decrement the reference counter. If it does not reach zero + wait for the last user. */ + atomic_decrement (&deleted->handler->refcntr); + unsigned int val; + while ((val = deleted->handler->refcntr) != 0) + lll_futex_wait (&deleted->handler->refcntr, val, LLL_PRIVATE); + + deleted = deleted->next; + } +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/unwindbuf.sym b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/unwindbuf.sym new file mode 100644 index 00000000..8044b407 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/unwindbuf.sym @@ -0,0 +1,7 @@ +#include +#include + +-- + +UNWINDBUFSIZE sizeof (__pthread_unwind_buf_t) +UWJMPBUF offsetof (__pthread_unwind_buf_t, __cancel_jmp_buf) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/waitpid.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/waitpid.S new file mode 100644 index 00000000..52abb27f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/waitpid.S @@ -0,0 +1,23 @@ +#include + +#ifndef __NR_waitpid +#error Makefile error: No NR_waitpid on this arch +#endif + +/* +extern pid_t __waitpid_nocancel (pid_t, int *, int) attribute_hidden; +*/ +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + + +PSEUDO (__waitpid, waitpid, 3) +ret +PSEUDO_END(__waitpid) + +libc_hidden_def (__waitpid) +weak_alias (__waitpid, waitpid) +libc_hidden_weak (waitpid) +weak_alias (__waitpid, __libc_waitpid) +libc_hidden_weak (__libc_waitpid) + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/write.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/write.S new file mode 100644 index 00000000..43de3320 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/write.S @@ -0,0 +1,19 @@ +#include + +/* +extern int __write_nocancel (int, const void *, size_t) attribute_hidden; +*/ +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + +PSEUDO (__libc_write, write, 3) +ret +PSEUDO_END(__libc_write) + +libc_hidden_def (__write_nocancel) +libc_hidden_def (__libc_write) +weak_alias (__libc_write, __write) +libc_hidden_weak (__write) +weak_alias (__libc_write, write) +libc_hidden_weak (write) + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/Makefile new file mode 100644 index 00000000..43a6fad8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc NPTL +# +# Copyright (C) 2005 Steven J. Hill +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../../../../../ +top_builddir=../../../../../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.arch +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/Makefile.arch b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/Makefile.arch new file mode 100644 index 00000000..71df9861 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/Makefile.arch @@ -0,0 +1,38 @@ +# Makefile for uClibc NPTL +# +# Copyright (C) 2006 Steven J. Hill +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +libpthread_linux_arch_SSRC = pt-vfork.S clone.S pthread_once.S \ + lowlevellock.S pthread_barrier_wait.S pthread_cond_signal.S pthread_cond_broadcast.S \ + sem_post.S sem_timedwait.S lowlevelrobustlock.S \ + sem_trywait.S sem_wait.S pthread_rwlock_rdlock.S pthread_rwlock_wrlock.S \ + pthread_rwlock_timedrdlock.S pthread_rwlock_timedwrlock.S pthread_rwlock_unlock.S \ + pthread_spin_unlock.S cancellation.S pthread_cond_timedwait.S pthread_cond_wait.S +libpthread_linux_arch_CSRC = pthread_spin_init.c pt-__syscall_error.c + +libc_linux_arch_CSRC = fork.c +libc_linux_arch_SSRC = clone.S vfork.S libc-cancellation.S libc-lowlevellock.S +libc_linux_arch_SSRC-OMIT = waitpid.S +librt_linux_arch_SSRC = librt-cancellation.S + +ASFLAGS += -DUSE___THREAD + +CFLAGS-pt-__syscall_error.c = -DNOT_IN_libc -DIS_IN_libpthread +ASFLAGS-pt-vfork.S = -DNOT_IN_libc -DIS_IN_libpthread -D_LIBC_REENTRANT +ASFLAGS-lowlevellock.S = -DNOT_IN_libc -DIS_IN_libpthread -D_LIBC_REENTRANT +ASFLAGS-pthread_once.S = -DNOT_IN_libc -DIS_IN_libpthread -D_LIBC_REENTRANT +ASFLAGS-cancellation.S = -DNOT_IN_libc -DIS_IN_libpthread -D_LIBC_REENTRANT +ASFLAGS-pthread_cond_timedwait.S = -D_LIBC_REENTRANT +ASFLAGS-pthread_cond_wait.S = -D_LIBC_REENTRANT + +ASFLAGS-clone.S = -D_LIBC_REENTRANT +ASFLAGS-vfork.S = -D_LIBC_REENTRANT +ASFLAGS-libc-lowlevellock.S = -D_LIBC_REENTRANT +ASFLAGS-libc-cancellation.S = -D_LIBC_REENTRANT +ifeq ($(UCLIBC_HAS_STDIO_FUTEXES),y) +CFLAGS-fork.c = -D__USE_STDIO_FUTEXES__ +endif +CFLAGS-OMIT-fork.c = -DNOT_IN_libc -DIS_IN_libpthread diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h new file mode 100644 index 00000000..7a09c811 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/bits/pthreadtypes.h @@ -0,0 +1,225 @@ +/* Copyright (C) 2002,2003,2004,2005,2006,2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _BITS_PTHREADTYPES_H +#define _BITS_PTHREADTYPES_H 1 + +#include + +#if __WORDSIZE == 64 +# define __SIZEOF_PTHREAD_ATTR_T 56 +# define __SIZEOF_PTHREAD_MUTEX_T 40 +# define __SIZEOF_PTHREAD_MUTEXATTR_T 4 +# define __SIZEOF_PTHREAD_COND_T 48 +# define __SIZEOF_PTHREAD_CONDATTR_T 4 +# define __SIZEOF_PTHREAD_RWLOCK_T 56 +# define __SIZEOF_PTHREAD_RWLOCKATTR_T 8 +# define __SIZEOF_PTHREAD_BARRIER_T 32 +# define __SIZEOF_PTHREAD_BARRIERATTR_T 4 +#else +# define __SIZEOF_PTHREAD_ATTR_T 36 +# define __SIZEOF_PTHREAD_MUTEX_T 24 +# define __SIZEOF_PTHREAD_MUTEXATTR_T 4 +# define __SIZEOF_PTHREAD_COND_T 48 +# define __SIZEOF_PTHREAD_CONDATTR_T 4 +# define __SIZEOF_PTHREAD_RWLOCK_T 32 +# define __SIZEOF_PTHREAD_RWLOCKATTR_T 8 +# define __SIZEOF_PTHREAD_BARRIER_T 20 +# define __SIZEOF_PTHREAD_BARRIERATTR_T 4 +#endif + + +/* Thread identifiers. The structure of the attribute type is not + exposed on purpose. */ +typedef unsigned long int pthread_t; + + +typedef union +{ + char __size[__SIZEOF_PTHREAD_ATTR_T]; + long int __align; +} pthread_attr_t; + + +#if __WORDSIZE == 64 +typedef struct __pthread_internal_list +{ + struct __pthread_internal_list *__prev; + struct __pthread_internal_list *__next; +} __pthread_list_t; +#else +typedef struct __pthread_internal_slist +{ + struct __pthread_internal_slist *__next; +} __pthread_slist_t; +#endif + + +/* Data structures for mutex handling. The structure of the attribute + type is not exposed on purpose. */ +typedef union +{ + struct __pthread_mutex_s + { + int __lock; + unsigned int __count; + int __owner; +#if __WORDSIZE == 64 + unsigned int __nusers; +#endif + /* KIND must stay at this position in the structure to maintain + binary compatibility. */ + int __kind; +#if __WORDSIZE == 64 + int __spins; + __pthread_list_t __list; +# define __PTHREAD_MUTEX_HAVE_PREV 1 +#else + unsigned int __nusers; + __extension__ union + { + int __spins; + __pthread_slist_t __list; + }; +#endif + } __data; + char __size[__SIZEOF_PTHREAD_MUTEX_T]; + long int __align; +} pthread_mutex_t; + +typedef union +{ + char __size[__SIZEOF_PTHREAD_MUTEXATTR_T]; + int __align; +} pthread_mutexattr_t; + + +/* Data structure for conditional variable handling. The structure of + the attribute type is not exposed on purpose. */ +typedef union +{ + struct + { + int __lock; + unsigned int __futex; + __extension__ unsigned long long int __total_seq; + __extension__ unsigned long long int __wakeup_seq; + __extension__ unsigned long long int __woken_seq; + void *__mutex; + unsigned int __nwaiters; + unsigned int __broadcast_seq; + } __data; + char __size[__SIZEOF_PTHREAD_COND_T]; + __extension__ long long int __align; +} pthread_cond_t; + +typedef union +{ + char __size[__SIZEOF_PTHREAD_CONDATTR_T]; + int __align; +} pthread_condattr_t; + + +/* Keys for thread-specific data */ +typedef unsigned int pthread_key_t; + + +/* Once-only execution */ +typedef int pthread_once_t; + + +#if defined __USE_UNIX98 || defined __USE_XOPEN2K +/* Data structure for read-write lock variable handling. The + structure of the attribute type is not exposed on purpose. */ +typedef union +{ +# if __WORDSIZE == 64 + struct + { + int __lock; + unsigned int __nr_readers; + unsigned int __readers_wakeup; + unsigned int __writer_wakeup; + unsigned int __nr_readers_queued; + unsigned int __nr_writers_queued; + int __writer; + int __shared; + unsigned long int __pad1; + unsigned long int __pad2; + /* FLAGS must stay at this position in the structure to maintain + binary compatibility. */ + unsigned int __flags; + } __data; +# else + struct + { + int __lock; + unsigned int __nr_readers; + unsigned int __readers_wakeup; + unsigned int __writer_wakeup; + unsigned int __nr_readers_queued; + unsigned int __nr_writers_queued; + /* FLAGS must stay at this position in the structure to maintain + binary compatibility. */ + unsigned char __flags; + unsigned char __shared; + unsigned char __pad1; + unsigned char __pad2; + int __writer; + } __data; +# endif + char __size[__SIZEOF_PTHREAD_RWLOCK_T]; + long int __align; +} pthread_rwlock_t; + +typedef union +{ + char __size[__SIZEOF_PTHREAD_RWLOCKATTR_T]; + long int __align; +} pthread_rwlockattr_t; +#endif + + +#ifdef __USE_XOPEN2K +/* POSIX spinlock data type. */ +typedef volatile int pthread_spinlock_t; + + +/* POSIX barriers data type. The structure of the type is + deliberately not exposed. */ +typedef union +{ + char __size[__SIZEOF_PTHREAD_BARRIER_T]; + long int __align; +} pthread_barrier_t; + +typedef union +{ + char __size[__SIZEOF_PTHREAD_BARRIERATTR_T]; + int __align; +} pthread_barrierattr_t; +#endif + + +#if __WORDSIZE == 32 +/* Extra attributes for the cleanup functions. */ +# define __cleanup_fct_attribute __attribute__ ((__regparm__ (1))) +#endif + +#endif /* bits/pthreadtypes.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/bits/semaphore.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/bits/semaphore.h new file mode 100644 index 00000000..e973bc5b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/bits/semaphore.h @@ -0,0 +1,41 @@ +/* Copyright (C) 2002, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SEMAPHORE_H +# error "Never use directly; include instead." +#endif + +#include + +#if __WORDSIZE == 64 +# define __SIZEOF_SEM_T 32 +#else +# define __SIZEOF_SEM_T 16 +#endif + + +/* Value returned if `sem_open' failed. */ +#define SEM_FAILED ((sem_t *) 0) + + +typedef union +{ + char __size[__SIZEOF_SEM_T]; + long int __align; +} sem_t; diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/cancellation.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/cancellation.S new file mode 100644 index 00000000..13adea77 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/cancellation.S @@ -0,0 +1,116 @@ +/* Copyright (C) 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2009. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include "lowlevellock.h" + +#ifdef IS_IN_libpthread +# ifdef SHARED +# define __pthread_unwind __GI___pthread_unwind +# endif +#else +# ifndef SHARED + .weak __pthread_unwind +# endif +#endif + + +#ifdef __ASSUME_PRIVATE_FUTEX +# define LOAD_PRIVATE_FUTEX_WAIT(reg) \ + movl $(FUTEX_WAIT | FUTEX_PRIVATE_FLAG), reg +#else +# if FUTEX_WAIT == 0 +# define LOAD_PRIVATE_FUTEX_WAIT(reg) \ + movl %fs:PRIVATE_FUTEX, reg +# else +# define LOAD_PRIVATE_FUTEX_WAIT(reg) \ + movl %fs:PRIVATE_FUTEX, reg ; \ + orl $FUTEX_WAIT, reg +# endif +#endif + +/* It is crucial that the functions in this file don't modify registers + other than %rax and %r11. The syscall wrapper code depends on this + because it doesn't explicitly save the other registers which hold + relevant values. */ + .text + + .hidden __pthread_enable_asynccancel +ENTRY(__pthread_enable_asynccancel) + movl %fs:CANCELHANDLING, %eax +2: movl %eax, %r11d + orl $TCB_CANCELTYPE_BITMASK, %r11d + cmpl %eax, %r11d + je 1f + + lock + cmpxchgl %r11d, %fs:CANCELHANDLING + jnz 2b + + andl $(TCB_CANCELSTATE_BITMASK|TCB_CANCELTYPE_BITMASK|TCB_CANCELED_BITMASK|TCB_EXITING_BITMASK|TCB_CANCEL_RESTMASK|TCB_TERMINATED_BITMASK), %r11d + cmpl $(TCB_CANCELTYPE_BITMASK|TCB_CANCELED_BITMASK), %r11d + je 3f + +1: ret + +3: movq $TCB_PTHREAD_CANCELED, %fs:RESULT + lock + orl $TCB_EXITING_BITMASK, %fs:CANCELHANDLING + movq %fs:CLEANUP_JMP_BUF, %rdi +#ifdef SHARED + call __pthread_unwind@PLT +#else + call __pthread_unwind +#endif + hlt +END(__pthread_enable_asynccancel) + + + .hidden __pthread_disable_asynccancel +ENTRY(__pthread_disable_asynccancel) + testl $TCB_CANCELTYPE_BITMASK, %edi + jnz 1f + + movl %fs:CANCELHANDLING, %eax +2: movl %eax, %r11d + andl $~TCB_CANCELTYPE_BITMASK, %r11d + lock + cmpxchgl %r11d, %fs:CANCELHANDLING + jnz 2b + + movl %r11d, %eax +3: andl $(TCB_CANCELING_BITMASK|TCB_CANCELED_BITMASK), %eax + cmpl $TCB_CANCELING_BITMASK, %eax + je 4f +1: ret + + /* Performance doesn't matter in this loop. We will + delay until the thread is canceled. And we will unlikely + enter the loop twice. */ +4: movq %fs:0, %rdi + movl $__NR_futex, %eax + xorq %r10, %r10 + addq $CANCELHANDLING, %rdi + LOAD_PRIVATE_FUTEX_WAIT (%esi) + syscall + movl %fs:CANCELHANDLING, %eax + jmp 3b +END(__pthread_disable_asynccancel) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/clone.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/clone.S new file mode 100644 index 00000000..efbaee3d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/clone.S @@ -0,0 +1,3 @@ +#include +#define RESET_PID +#include diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/compat-timer.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/compat-timer.h new file mode 100644 index 00000000..02485daa --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/compat-timer.h @@ -0,0 +1,46 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include + +#define OLD_TIMER_MAX 256 + +extern timer_t __compat_timer_list[OLD_TIMER_MAX] attribute_hidden; + + +extern int __timer_create_new (clockid_t clock_id, struct sigevent *evp, + timer_t *timerid); +extern int __timer_delete_new (timer_t timerid); +extern int __timer_getoverrun_new (timer_t timerid); +extern int __timer_gettime_new (timer_t timerid, struct itimerspec *value); +extern int __timer_settime_new (timer_t timerid, int flags, + const struct itimerspec *value, + struct itimerspec *ovalue); + + +extern int __timer_create_old (clockid_t clock_id, struct sigevent *evp, + int *timerid); +extern int __timer_delete_old (int timerid); +extern int __timer_getoverrun_old (int timerid); +extern int __timer_gettime_old (int timerid, struct itimerspec *value); +extern int __timer_settime_old (int timerid, int flags, + const struct itimerspec *value, + struct itimerspec *ovalue); diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/fork.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/fork.c new file mode 100644 index 00000000..c828e158 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/fork.c @@ -0,0 +1,31 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + + +#define ARCH_FORK() \ + INLINE_SYSCALL (clone, 4, \ + CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | SIGCHLD, 0, \ + NULL, &THREAD_SELF->tid) + +#include "../fork.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/libc-cancellation.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/libc-cancellation.S new file mode 100644 index 00000000..11005885 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/libc-cancellation.S @@ -0,0 +1,22 @@ +/* Copyright (C) 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2009. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define __pthread_enable_asynccancel __libc_enable_asynccancel +#define __pthread_disable_asynccancel __libc_disable_asynccancel +#include "cancellation.S" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/libc-lowlevellock.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/libc-lowlevellock.S new file mode 100644 index 00000000..ce8ad27a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/libc-lowlevellock.S @@ -0,0 +1,20 @@ +/* Copyright (C) 2002, 2003, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "lowlevellock.S" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/librt-cancellation.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/librt-cancellation.S new file mode 100644 index 00000000..ce4192b5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/librt-cancellation.S @@ -0,0 +1,22 @@ +/* Copyright (C) 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2009. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define __pthread_enable_asynccancel __librt_enable_asynccancel +#define __pthread_disable_asynccancel __librt_disable_asynccancel +#include "cancellation.S" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S new file mode 100644 index 00000000..f8753235 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S @@ -0,0 +1,457 @@ +/* Copyright (C) 2002-2006, 2007, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include + + .text + +#ifdef __ASSUME_PRIVATE_FUTEX +# define LOAD_PRIVATE_FUTEX_WAIT(reg) \ + movl $(FUTEX_WAIT | FUTEX_PRIVATE_FLAG), reg +# define LOAD_PRIVATE_FUTEX_WAKE(reg) \ + movl $(FUTEX_WAKE | FUTEX_PRIVATE_FLAG), reg +# define LOAD_FUTEX_WAIT(reg) \ + xorl $(FUTEX_WAIT | FUTEX_PRIVATE_FLAG), reg +# define LOAD_FUTEX_WAIT_ABS(reg) \ + xorl $(FUTEX_WAIT_BITSET | FUTEX_PRIVATE_FLAG | FUTEX_CLOCK_REALTIME), reg +# define LOAD_FUTEX_WAKE(reg) \ + xorl $(FUTEX_WAKE | FUTEX_PRIVATE_FLAG), reg +#else +# if FUTEX_WAIT == 0 +# define LOAD_PRIVATE_FUTEX_WAIT(reg) \ + movl %fs:PRIVATE_FUTEX, reg +# else +# define LOAD_PRIVATE_FUTEX_WAIT(reg) \ + movl %fs:PRIVATE_FUTEX, reg ; \ + orl $FUTEX_WAIT, reg +# endif +# define LOAD_PRIVATE_FUTEX_WAKE(reg) \ + movl %fs:PRIVATE_FUTEX, reg ; \ + orl $FUTEX_WAKE, reg +# if FUTEX_WAIT == 0 +# define LOAD_FUTEX_WAIT(reg) \ + xorl $FUTEX_PRIVATE_FLAG, reg ; \ + andl %fs:PRIVATE_FUTEX, reg +# else +# define LOAD_FUTEX_WAIT(reg) \ + xorl $FUTEX_PRIVATE_FLAG, reg ; \ + andl %fs:PRIVATE_FUTEX, reg ; \ + orl $FUTEX_WAIT, reg +# endif +# define LOAD_FUTEX_WAIT_ABS(reg) \ + xorl $FUTEX_PRIVATE_FLAG, reg ; \ + andl %fs:PRIVATE_FUTEX, reg ; \ + orl $FUTEX_WAIT_BITSET | FUTEX_CLOCK_REALTIME, reg +# define LOAD_FUTEX_WAKE(reg) \ + xorl $FUTEX_PRIVATE_FLAG, reg ; \ + andl %fs:PRIVATE_FUTEX, reg ; \ + orl $FUTEX_WAKE, reg +#endif + + +/* For the calculation see asm/vsyscall.h. */ +#define VSYSCALL_ADDR_vgettimeofday 0xffffffffff600000 + + + .globl __lll_lock_wait_private + .type __lll_lock_wait_private,@function + .hidden __lll_lock_wait_private + .align 16 +__lll_lock_wait_private: + cfi_startproc + pushq %r10 + cfi_adjust_cfa_offset(8) + pushq %rdx + cfi_adjust_cfa_offset(8) + cfi_offset(%r10, -16) + cfi_offset(%rdx, -24) + xorq %r10, %r10 /* No timeout. */ + movl $2, %edx + LOAD_PRIVATE_FUTEX_WAIT (%esi) + + cmpl %edx, %eax /* NB: %edx == 2 */ + jne 2f + +1: movl $SYS_futex, %eax + syscall + +2: movl %edx, %eax + xchgl %eax, (%rdi) /* NB: lock is implied */ + + testl %eax, %eax + jnz 1b + + popq %rdx + cfi_adjust_cfa_offset(-8) + cfi_restore(%rdx) + popq %r10 + cfi_adjust_cfa_offset(-8) + cfi_restore(%r10) + retq + cfi_endproc + .size __lll_lock_wait_private,.-__lll_lock_wait_private + +#ifdef NOT_IN_libc + .globl __lll_lock_wait + .type __lll_lock_wait,@function + .hidden __lll_lock_wait + .align 16 +__lll_lock_wait: + cfi_startproc + pushq %r10 + cfi_adjust_cfa_offset(8) + pushq %rdx + cfi_adjust_cfa_offset(8) + cfi_offset(%r10, -16) + cfi_offset(%rdx, -24) + xorq %r10, %r10 /* No timeout. */ + movl $2, %edx + LOAD_FUTEX_WAIT (%esi) + + cmpl %edx, %eax /* NB: %edx == 2 */ + jne 2f + +1: movl $SYS_futex, %eax + syscall + +2: movl %edx, %eax + xchgl %eax, (%rdi) /* NB: lock is implied */ + + testl %eax, %eax + jnz 1b + + popq %rdx + cfi_adjust_cfa_offset(-8) + cfi_restore(%rdx) + popq %r10 + cfi_adjust_cfa_offset(-8) + cfi_restore(%r10) + retq + cfi_endproc + .size __lll_lock_wait,.-__lll_lock_wait + + /* %rdi: futex + %rsi: flags + %rdx: timeout + %eax: futex value + */ + .globl __lll_timedlock_wait + .type __lll_timedlock_wait,@function + .hidden __lll_timedlock_wait + .align 16 +__lll_timedlock_wait: + cfi_startproc +# ifndef __ASSUME_FUTEX_CLOCK_REALTIME +# ifdef __PIC__ + cmpl $0, __have_futex_clock_realtime(%rip) +# else + cmpl $0, __have_futex_clock_realtime +# endif + je .Lreltmo +# endif + + pushq %r9 + cfi_adjust_cfa_offset(8) + cfi_rel_offset(%r9, 0) + movq %rdx, %r10 + movl $0xffffffff, %r9d + LOAD_FUTEX_WAIT_ABS (%esi) + + movl $2, %edx + cmpl %edx, %eax + jne 2f + +1: movl $SYS_futex, %eax + movl $2, %edx + syscall + +2: xchgl %edx, (%rdi) /* NB: lock is implied */ + + testl %edx, %edx + jz 3f + + cmpl $-ETIMEDOUT, %eax + je 4f + cmpl $-EINVAL, %eax + jne 1b +4: movl %eax, %edx + negl %edx + +3: movl %edx, %eax + popq %r9 + cfi_adjust_cfa_offset(-8) + cfi_restore(%r9) + retq + +# ifndef __ASSUME_FUTEX_CLOCK_REALTIME +.Lreltmo: + /* Check for a valid timeout value. */ + cmpq $1000000000, 8(%rdx) + jae 3f + + pushq %r8 + cfi_adjust_cfa_offset(8) + pushq %r9 + cfi_adjust_cfa_offset(8) + pushq %r12 + cfi_adjust_cfa_offset(8) + pushq %r13 + cfi_adjust_cfa_offset(8) + pushq %r14 + cfi_adjust_cfa_offset(8) + cfi_offset(%r8, -16) + cfi_offset(%r9, -24) + cfi_offset(%r12, -32) + cfi_offset(%r13, -40) + cfi_offset(%r14, -48) + pushq %rsi + cfi_adjust_cfa_offset(8) + + /* Stack frame for the timespec and timeval structs. */ + subq $24, %rsp + cfi_adjust_cfa_offset(24) + + movq %rdi, %r12 + movq %rdx, %r13 + + movl $2, %edx + xchgl %edx, (%r12) + + testl %edx, %edx + je 6f + +1: + /* Get current time. */ + movq %rsp, %rdi + xorl %esi, %esi + movq $VSYSCALL_ADDR_vgettimeofday, %rax + /* This is a regular function call, all caller-save registers + might be clobbered. */ + callq *%rax + + /* Compute relative timeout. */ + movq 8(%rsp), %rax + movl $1000, %edi + mul %rdi /* Milli seconds to nano seconds. */ + movq (%r13), %rdi + movq 8(%r13), %rsi + subq (%rsp), %rdi + subq %rax, %rsi + jns 4f + addq $1000000000, %rsi + decq %rdi +4: testq %rdi, %rdi + js 2f /* Time is already up. */ + + /* Store relative timeout. */ + movq %rdi, (%rsp) + movq %rsi, 8(%rsp) + + /* Futex call. */ + movl $2, %edx + movl $1, %eax + movq %rsp, %r10 + movl 24(%rsp), %esi + LOAD_FUTEX_WAIT (%esi) + movq %r12, %rdi + movl $SYS_futex, %eax + syscall + + /* NB: %edx == 2 */ + xchgl %edx, (%r12) + + testl %edx, %edx + je 6f + + cmpl $-ETIMEDOUT, %eax + jne 1b +2: movl $ETIMEDOUT, %edx + +6: addq $32, %rsp + cfi_adjust_cfa_offset(-32) + popq %r14 + cfi_adjust_cfa_offset(-8) + cfi_restore(%r14) + popq %r13 + cfi_adjust_cfa_offset(-8) + cfi_restore(%r13) + popq %r12 + cfi_adjust_cfa_offset(-8) + cfi_restore(%r12) + popq %r9 + cfi_adjust_cfa_offset(-8) + cfi_restore(%r9) + popq %r8 + cfi_adjust_cfa_offset(-8) + cfi_restore(%r8) + movl %edx, %eax + retq + +3: movl $EINVAL, %eax + retq +# endif + cfi_endproc + .size __lll_timedlock_wait,.-__lll_timedlock_wait +#endif + + + .globl __lll_unlock_wake_private + .type __lll_unlock_wake_private,@function + .hidden __lll_unlock_wake_private + .align 16 +__lll_unlock_wake_private: + cfi_startproc + pushq %rsi + cfi_adjust_cfa_offset(8) + pushq %rdx + cfi_adjust_cfa_offset(8) + cfi_offset(%rsi, -16) + cfi_offset(%rdx, -24) + + movl $0, (%rdi) + LOAD_PRIVATE_FUTEX_WAKE (%esi) + movl $1, %edx /* Wake one thread. */ + movl $SYS_futex, %eax + syscall + + popq %rdx + cfi_adjust_cfa_offset(-8) + cfi_restore(%rdx) + popq %rsi + cfi_adjust_cfa_offset(-8) + cfi_restore(%rsi) + retq + cfi_endproc + .size __lll_unlock_wake_private,.-__lll_unlock_wake_private + +#ifdef NOT_IN_libc + .globl __lll_unlock_wake + .type __lll_unlock_wake,@function + .hidden __lll_unlock_wake + .align 16 +__lll_unlock_wake: + cfi_startproc + pushq %rsi + cfi_adjust_cfa_offset(8) + pushq %rdx + cfi_adjust_cfa_offset(8) + cfi_offset(%rsi, -16) + cfi_offset(%rdx, -24) + + movl $0, (%rdi) + LOAD_FUTEX_WAKE (%esi) + movl $1, %edx /* Wake one thread. */ + movl $SYS_futex, %eax + syscall + + popq %rdx + cfi_adjust_cfa_offset(-8) + cfi_restore(%rdx) + popq %rsi + cfi_adjust_cfa_offset(-8) + cfi_restore(%rsi) + retq + cfi_endproc + .size __lll_unlock_wake,.-__lll_unlock_wake + + .globl __lll_timedwait_tid + .type __lll_timedwait_tid,@function + .hidden __lll_timedwait_tid + .align 16 +__lll_timedwait_tid: + cfi_startproc + pushq %r12 + cfi_adjust_cfa_offset(8) + pushq %r13 + cfi_adjust_cfa_offset(8) + cfi_offset(%r12, -16) + cfi_offset(%r13, -24) + + movq %rdi, %r12 + movq %rsi, %r13 + + subq $16, %rsp + cfi_adjust_cfa_offset(16) + + /* Get current time. */ +2: movq %rsp, %rdi + xorl %esi, %esi + movq $VSYSCALL_ADDR_vgettimeofday, %rax + callq *%rax + + /* Compute relative timeout. */ + movq 8(%rsp), %rax + movl $1000, %edi + mul %rdi /* Milli seconds to nano seconds. */ + movq (%r13), %rdi + movq 8(%r13), %rsi + subq (%rsp), %rdi + subq %rax, %rsi + jns 5f + addq $1000000000, %rsi + decq %rdi +5: testq %rdi, %rdi + js 6f /* Time is already up. */ + + movq %rdi, (%rsp) /* Store relative timeout. */ + movq %rsi, 8(%rsp) + + movl (%r12), %edx + testl %edx, %edx + jz 4f + + movq %rsp, %r10 + /* XXX The kernel so far uses global futex for the wakeup at + all times. */ +#if FUTEX_WAIT == 0 + xorl %esi, %esi +#else + movl $FUTEX_WAIT, %esi +#endif + movq %r12, %rdi + movl $SYS_futex, %eax + syscall + + cmpl $0, (%rdi) + jne 1f +4: xorl %eax, %eax + +8: addq $16, %rsp + cfi_adjust_cfa_offset(-16) + popq %r13 + cfi_adjust_cfa_offset(-8) + cfi_restore(%r13) + popq %r12 + cfi_adjust_cfa_offset(-8) + cfi_restore(%r12) + retq + + cfi_adjust_cfa_offset(32) +1: cmpq $-ETIMEDOUT, %rax + jne 2b + +6: movl $ETIMEDOUT, %eax + jmp 8b + cfi_endproc + .size __lll_timedwait_tid,.-__lll_timedwait_tid +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h new file mode 100644 index 00000000..ffab81eb --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h @@ -0,0 +1,598 @@ +/* Copyright (C) 2002-2004, 2006-2008, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _LOWLEVELLOCK_H +#define _LOWLEVELLOCK_H 1 + +#ifndef __ASSEMBLER__ +# include +# include +# include +# include +# include + +# ifndef LOCK_INSTR +# ifdef UP +# define LOCK_INSTR /* nothing */ +# else +# define LOCK_INSTR "lock;" +# endif +# endif +#else +# ifndef LOCK +# ifdef UP +# define LOCK +# else +# define LOCK lock +# endif +# endif +#endif + +#define FUTEX_WAIT 0 +#define FUTEX_WAKE 1 +#define FUTEX_CMP_REQUEUE 4 +#define FUTEX_WAKE_OP 5 +#define FUTEX_LOCK_PI 6 +#define FUTEX_UNLOCK_PI 7 +#define FUTEX_TRYLOCK_PI 8 +#define FUTEX_WAIT_BITSET 9 +#define FUTEX_WAKE_BITSET 10 +#define FUTEX_WAIT_REQUEUE_PI 11 +#define FUTEX_CMP_REQUEUE_PI 12 +#define FUTEX_PRIVATE_FLAG 128 +#define FUTEX_CLOCK_REALTIME 256 + +#define FUTEX_BITSET_MATCH_ANY 0xffffffff + +#define FUTEX_OP_CLEAR_WAKE_IF_GT_ONE ((4 << 24) | 1) + +/* Values for 'private' parameter of locking macros. Yes, the + definition seems to be backwards. But it is not. The bit will be + reversed before passing to the system call. */ +#define LLL_PRIVATE 0 +#define LLL_SHARED FUTEX_PRIVATE_FLAG + +#ifndef __ASSEMBLER__ + +#if !defined NOT_IN_libc || defined IS_IN_rtld +/* In libc.so or ld.so all futexes are private. */ +# ifdef __ASSUME_PRIVATE_FUTEX +# define __lll_private_flag(fl, private) \ + ((fl) | FUTEX_PRIVATE_FLAG) +# else +# define __lll_private_flag(fl, private) \ + ((fl) | THREAD_GETMEM (THREAD_SELF, header.private_futex)) +# endif +#else +# ifdef __ASSUME_PRIVATE_FUTEX +# define __lll_private_flag(fl, private) \ + (((fl) | FUTEX_PRIVATE_FLAG) ^ (private)) +# else +# define __lll_private_flag(fl, private) \ + (__builtin_constant_p (private) \ + ? ((private) == 0 \ + ? ((fl) | THREAD_GETMEM (THREAD_SELF, header.private_futex)) \ + : (fl)) \ + : ({ unsigned int __fl = ((private) ^ FUTEX_PRIVATE_FLAG); \ + __asm__ ("andl %%fs:%P1, %0" : "+r" (__fl) \ + : "i" (offsetof (struct pthread, header.private_futex))); \ + __fl | (fl); })) +# endif +#endif + +/* Initializer for lock. */ +#define LLL_LOCK_INITIALIZER (0) +#define LLL_LOCK_INITIALIZER_LOCKED (1) +#define LLL_LOCK_INITIALIZER_WAITERS (2) + +/* Delay in spinlock loop. */ +#define BUSY_WAIT_NOP __asm__ ("rep; nop") + + +#define LLL_STUB_UNWIND_INFO_START \ + ".section .eh_frame,\"a\",@progbits\n" \ +"7:\t" ".long 9f-8f # Length of Common Information Entry\n" \ +"8:\t" ".long 0x0 # CIE Identifier Tag\n\t" \ + ".byte 0x1 # CIE Version\n\t" \ + ".ascii \"zR\\0\" # CIE Augmentation\n\t" \ + ".uleb128 0x1 # CIE Code Alignment Factor\n\t" \ + ".sleb128 -8 # CIE Data Alignment Factor\n\t" \ + ".byte 0x10 # CIE RA Column\n\t" \ + ".uleb128 0x1 # Augmentation size\n\t" \ + ".byte 0x1b # FDE Encoding (pcrel sdata4)\n\t" \ + ".byte 0x12 # DW_CFA_def_cfa_sf\n\t" \ + ".uleb128 0x7\n\t" \ + ".sleb128 16\n\t" \ + ".align 8\n" \ +"9:\t" ".long 23f-10f # FDE Length\n" \ +"10:\t" ".long 10b-7b # FDE CIE offset\n\t" \ + ".long 1b-. # FDE initial location\n\t" \ + ".long 6b-1b # FDE address range\n\t" \ + ".uleb128 0x0 # Augmentation size\n\t" \ + ".byte 0x16 # DW_CFA_val_expression\n\t" \ + ".uleb128 0x10\n\t" \ + ".uleb128 12f-11f\n" \ +"11:\t" ".byte 0x80 # DW_OP_breg16\n\t" \ + ".sleb128 4b-1b\n" +#define LLL_STUB_UNWIND_INFO_END \ + ".byte 0x16 # DW_CFA_val_expression\n\t" \ + ".uleb128 0x10\n\t" \ + ".uleb128 14f-13f\n" \ +"13:\t" ".byte 0x80 # DW_OP_breg16\n\t" \ + ".sleb128 4b-2b\n" \ +"14:\t" ".byte 0x40 + (3b-2b) # DW_CFA_advance_loc\n\t" \ + ".byte 0x0e # DW_CFA_def_cfa_offset\n\t" \ + ".uleb128 0\n\t" \ + ".byte 0x16 # DW_CFA_val_expression\n\t" \ + ".uleb128 0x10\n\t" \ + ".uleb128 16f-15f\n" \ +"15:\t" ".byte 0x80 # DW_OP_breg16\n\t" \ + ".sleb128 4b-3b\n" \ +"16:\t" ".byte 0x40 + (4b-3b-1) # DW_CFA_advance_loc\n\t" \ + ".byte 0x0e # DW_CFA_def_cfa_offset\n\t" \ + ".uleb128 128\n\t" \ + ".byte 0x16 # DW_CFA_val_expression\n\t" \ + ".uleb128 0x10\n\t" \ + ".uleb128 20f-17f\n" \ +"17:\t" ".byte 0x80 # DW_OP_breg16\n\t" \ + ".sleb128 19f-18f\n\t" \ + ".byte 0x0d # DW_OP_const4s\n" \ +"18:\t" ".4byte 4b-.\n\t" \ + ".byte 0x1c # DW_OP_minus\n\t" \ + ".byte 0x0d # DW_OP_const4s\n" \ +"19:\t" ".4byte 24f-.\n\t" \ + ".byte 0x22 # DW_OP_plus\n" \ +"20:\t" ".byte 0x40 + (5b-4b+1) # DW_CFA_advance_loc\n\t" \ + ".byte 0x13 # DW_CFA_def_cfa_offset_sf\n\t" \ + ".sleb128 16\n\t" \ + ".byte 0x16 # DW_CFA_val_expression\n\t" \ + ".uleb128 0x10\n\t" \ + ".uleb128 22f-21f\n" \ +"21:\t" ".byte 0x80 # DW_OP_breg16\n\t" \ + ".sleb128 4b-5b\n" \ +"22:\t" ".align 8\n" \ +"23:\t" ".previous\n" + +/* Unwind info for + 1: leaq ..., %rdi + 2: subq $128, %rsp + 3: callq ... + 4: addq $128, %rsp + 5: jmp 24f + 6: + snippet. */ +#define LLL_STUB_UNWIND_INFO_5 \ +LLL_STUB_UNWIND_INFO_START \ +"12:\t" ".byte 0x40 + (2b-1b) # DW_CFA_advance_loc\n\t" \ +LLL_STUB_UNWIND_INFO_END + +/* Unwind info for + 1: leaq ..., %rdi + 0: movq ..., %rdx + 2: subq $128, %rsp + 3: callq ... + 4: addq $128, %rsp + 5: jmp 24f + 6: + snippet. */ +#define LLL_STUB_UNWIND_INFO_6 \ +LLL_STUB_UNWIND_INFO_START \ +"12:\t" ".byte 0x40 + (0b-1b) # DW_CFA_advance_loc\n\t" \ + ".byte 0x16 # DW_CFA_val_expression\n\t" \ + ".uleb128 0x10\n\t" \ + ".uleb128 26f-25f\n" \ +"25:\t" ".byte 0x80 # DW_OP_breg16\n\t" \ + ".sleb128 4b-0b\n" \ +"26:\t" ".byte 0x40 + (2b-0b) # DW_CFA_advance_loc\n\t" \ +LLL_STUB_UNWIND_INFO_END + + +#define lll_futex_wait(futex, val, private) \ + lll_futex_timed_wait(futex, val, NULL, private) + + +#define lll_futex_timed_wait(futex, val, timeout, private) \ + ({ \ + register const struct timespec *__to __asm__ ("r10") = timeout; \ + int __status; \ + register __typeof (val) _val __asm__ ("edx") = (val); \ + __asm__ __volatile__ ("syscall" \ + : "=a" (__status) \ + : "0" (SYS_futex), "D" (futex), \ + "S" (__lll_private_flag (FUTEX_WAIT, private)), \ + "d" (_val), "r" (__to) \ + : "memory", "cc", "r11", "cx"); \ + __status; \ + }) + + +#define lll_futex_wake(futex, nr, private) \ + do { \ + int __ignore; \ + register __typeof (nr) _nr __asm__ ("edx") = (nr); \ + __asm__ __volatile__ ("syscall" \ + : "=a" (__ignore) \ + : "0" (SYS_futex), "D" (futex), \ + "S" (__lll_private_flag (FUTEX_WAKE, private)), \ + "d" (_nr) \ + : "memory", "cc", "r10", "r11", "cx"); \ + } while (0) + + +/* NB: in the lll_trylock macro we simply return the value in %eax + after the cmpxchg instruction. In case the operation succeded this + value is zero. In case the operation failed, the cmpxchg instruction + has loaded the current value of the memory work which is guaranteed + to be nonzero. */ +#if defined NOT_IN_libc || defined UP +# define __lll_trylock_asm LOCK_INSTR "cmpxchgl %2, %1" +#else +# define __lll_trylock_asm "cmpl $0, __libc_multiple_threads(%%rip)\n\t" \ + "je 0f\n\t" \ + "lock; cmpxchgl %2, %1\n\t" \ + "jmp 1f\n\t" \ + "0:\tcmpxchgl %2, %1\n\t" \ + "1:" +#endif + +#define lll_trylock(futex) \ + ({ int ret; \ + __asm__ __volatile__ (__lll_trylock_asm \ + : "=a" (ret), "=m" (futex) \ + : "r" (LLL_LOCK_INITIALIZER_LOCKED), "m" (futex), \ + "0" (LLL_LOCK_INITIALIZER) \ + : "memory"); \ + ret; }) + +#define lll_robust_trylock(futex, id) \ + ({ int ret; \ + __asm__ __volatile__ (LOCK_INSTR "cmpxchgl %2, %1" \ + : "=a" (ret), "=m" (futex) \ + : "r" (id), "m" (futex), "0" (LLL_LOCK_INITIALIZER) \ + : "memory"); \ + ret; }) + +#define lll_cond_trylock(futex) \ + ({ int ret; \ + __asm__ __volatile__ (LOCK_INSTR "cmpxchgl %2, %1" \ + : "=a" (ret), "=m" (futex) \ + : "r" (LLL_LOCK_INITIALIZER_WAITERS), \ + "m" (futex), "0" (LLL_LOCK_INITIALIZER) \ + : "memory"); \ + ret; }) + +#if defined NOT_IN_libc || defined UP +# define __lll_lock_asm_start LOCK_INSTR "cmpxchgl %4, %2\n\t" \ + "jnz 1f\n\t" +#else +# define __lll_lock_asm_start "cmpl $0, __libc_multiple_threads(%%rip)\n\t" \ + "je 0f\n\t" \ + "lock; cmpxchgl %4, %2\n\t" \ + "jnz 1f\n\t" \ + "jmp 24f\n" \ + "0:\tcmpxchgl %4, %2\n\t" \ + "jnz 1f\n\t" +#endif + +#define lll_lock(futex, private) \ + (void) \ + ({ int ignore1, ignore2, ignore3; \ + if (__builtin_constant_p (private) && (private) == LLL_PRIVATE) \ + __asm__ __volatile__ (__lll_lock_asm_start \ + ".subsection 1\n\t" \ + ".type _L_lock_%=, @function\n" \ + "_L_lock_%=:\n" \ + "1:\tleaq %2, %%rdi\n" \ + "2:\tsubq $128, %%rsp\n" \ + "3:\tcallq __lll_lock_wait_private\n" \ + "4:\taddq $128, %%rsp\n" \ + "5:\tjmp 24f\n" \ + "6:\t.size _L_lock_%=, 6b-1b\n\t" \ + ".previous\n" \ + LLL_STUB_UNWIND_INFO_5 \ + "24:" \ + : "=S" (ignore1), "=&D" (ignore2), "=m" (futex), \ + "=a" (ignore3) \ + : "0" (1), "m" (futex), "3" (0) \ + : "cx", "r11", "cc", "memory"); \ + else \ + __asm__ __volatile__ (__lll_lock_asm_start \ + ".subsection 1\n\t" \ + ".type _L_lock_%=, @function\n" \ + "_L_lock_%=:\n" \ + "1:\tleaq %2, %%rdi\n" \ + "2:\tsubq $128, %%rsp\n" \ + "3:\tcallq __lll_lock_wait\n" \ + "4:\taddq $128, %%rsp\n" \ + "5:\tjmp 24f\n" \ + "6:\t.size _L_lock_%=, 6b-1b\n\t" \ + ".previous\n" \ + LLL_STUB_UNWIND_INFO_5 \ + "24:" \ + : "=S" (ignore1), "=D" (ignore2), "=m" (futex), \ + "=a" (ignore3) \ + : "1" (1), "m" (futex), "3" (0), "0" (private) \ + : "cx", "r11", "cc", "memory"); \ + }) \ + +#define lll_robust_lock(futex, id, private) \ + ({ int result, ignore1, ignore2; \ + __asm__ __volatile__ (LOCK_INSTR "cmpxchgl %4, %2\n\t" \ + "jnz 1f\n\t" \ + ".subsection 1\n\t" \ + ".type _L_robust_lock_%=, @function\n" \ + "_L_robust_lock_%=:\n" \ + "1:\tleaq %2, %%rdi\n" \ + "2:\tsubq $128, %%rsp\n" \ + "3:\tcallq __lll_robust_lock_wait\n" \ + "4:\taddq $128, %%rsp\n" \ + "5:\tjmp 24f\n" \ + "6:\t.size _L_robust_lock_%=, 6b-1b\n\t" \ + ".previous\n" \ + LLL_STUB_UNWIND_INFO_5 \ + "24:" \ + : "=S" (ignore1), "=D" (ignore2), "=m" (futex), \ + "=a" (result) \ + : "1" (id), "m" (futex), "3" (0), "0" (private) \ + : "cx", "r11", "cc", "memory"); \ + result; }) + +#define lll_cond_lock(futex, private) \ + (void) \ + ({ int ignore1, ignore2, ignore3; \ + __asm__ __volatile__ (LOCK_INSTR "cmpxchgl %4, %2\n\t" \ + "jnz 1f\n\t" \ + ".subsection 1\n\t" \ + ".type _L_cond_lock_%=, @function\n" \ + "_L_cond_lock_%=:\n" \ + "1:\tleaq %2, %%rdi\n" \ + "2:\tsubq $128, %%rsp\n" \ + "3:\tcallq __lll_lock_wait\n" \ + "4:\taddq $128, %%rsp\n" \ + "5:\tjmp 24f\n" \ + "6:\t.size _L_cond_lock_%=, 6b-1b\n\t" \ + ".previous\n" \ + LLL_STUB_UNWIND_INFO_5 \ + "24:" \ + : "=S" (ignore1), "=D" (ignore2), "=m" (futex), \ + "=a" (ignore3) \ + : "1" (2), "m" (futex), "3" (0), "0" (private) \ + : "cx", "r11", "cc", "memory"); \ + }) + +#define lll_robust_cond_lock(futex, id, private) \ + ({ int result, ignore1, ignore2; \ + __asm__ __volatile__ (LOCK_INSTR "cmpxchgl %4, %2\n\t" \ + "jnz 1f\n\t" \ + ".subsection 1\n\t" \ + ".type _L_robust_cond_lock_%=, @function\n" \ + "_L_robust_cond_lock_%=:\n" \ + "1:\tleaq %2, %%rdi\n" \ + "2:\tsubq $128, %%rsp\n" \ + "3:\tcallq __lll_robust_lock_wait\n" \ + "4:\taddq $128, %%rsp\n" \ + "5:\tjmp 24f\n" \ + "6:\t.size _L_robust_cond_lock_%=, 6b-1b\n\t" \ + ".previous\n" \ + LLL_STUB_UNWIND_INFO_5 \ + "24:" \ + : "=S" (ignore1), "=D" (ignore2), "=m" (futex), \ + "=a" (result) \ + : "1" (id | FUTEX_WAITERS), "m" (futex), "3" (0), \ + "0" (private) \ + : "cx", "r11", "cc", "memory"); \ + result; }) + +#define lll_timedlock(futex, timeout, private) \ + ({ int result, ignore1, ignore2, ignore3; \ + __asm__ __volatile__ (LOCK_INSTR "cmpxchgl %1, %4\n\t" \ + "jnz 1f\n\t" \ + ".subsection 1\n\t" \ + ".type _L_timedlock_%=, @function\n" \ + "_L_timedlock_%=:\n" \ + "1:\tleaq %4, %%rdi\n" \ + "0:\tmovq %8, %%rdx\n" \ + "2:\tsubq $128, %%rsp\n" \ + "3:\tcallq __lll_timedlock_wait\n" \ + "4:\taddq $128, %%rsp\n" \ + "5:\tjmp 24f\n" \ + "6:\t.size _L_timedlock_%=, 6b-1b\n\t" \ + ".previous\n" \ + LLL_STUB_UNWIND_INFO_6 \ + "24:" \ + : "=a" (result), "=D" (ignore1), "=S" (ignore2), \ + "=&d" (ignore3), "=m" (futex) \ + : "0" (0), "1" (1), "m" (futex), "m" (timeout), \ + "2" (private) \ + : "memory", "cx", "cc", "r10", "r11"); \ + result; }) + +#define lll_robust_timedlock(futex, timeout, id, private) \ + ({ int result, ignore1, ignore2, ignore3; \ + __asm__ __volatile__ (LOCK_INSTR "cmpxchgl %1, %4\n\t" \ + "jnz 1f\n\t" \ + ".subsection 1\n\t" \ + ".type _L_robust_timedlock_%=, @function\n" \ + "_L_robust_timedlock_%=:\n" \ + "1:\tleaq %4, %%rdi\n" \ + "0:\tmovq %8, %%rdx\n" \ + "2:\tsubq $128, %%rsp\n" \ + "3:\tcallq __lll_robust_timedlock_wait\n" \ + "4:\taddq $128, %%rsp\n" \ + "5:\tjmp 24f\n" \ + "6:\t.size _L_robust_timedlock_%=, 6b-1b\n\t" \ + ".previous\n" \ + LLL_STUB_UNWIND_INFO_6 \ + "24:" \ + : "=a" (result), "=D" (ignore1), "=S" (ignore2), \ + "=&d" (ignore3), "=m" (futex) \ + : "0" (0), "1" (id), "m" (futex), "m" (timeout), \ + "2" (private) \ + : "memory", "cx", "cc", "r10", "r11"); \ + result; }) + +#if defined NOT_IN_libc || defined UP +# define __lll_unlock_asm_start LOCK_INSTR "decl %0\n\t" \ + "jne 1f\n\t" +#else +# define __lll_unlock_asm_start "cmpl $0, __libc_multiple_threads(%%rip)\n\t" \ + "je 0f\n\t" \ + "lock; decl %0\n\t" \ + "jne 1f\n\t" \ + "jmp 24f\n\t" \ + "0:\tdecl %0\n\t" \ + "jne 1f\n\t" +#endif + +#define lll_unlock(futex, private) \ + (void) \ + ({ int ignore; \ + if (__builtin_constant_p (private) && (private) == LLL_PRIVATE) \ + __asm__ __volatile__ (__lll_unlock_asm_start \ + ".subsection 1\n\t" \ + ".type _L_unlock_%=, @function\n" \ + "_L_unlock_%=:\n" \ + "1:\tleaq %0, %%rdi\n" \ + "2:\tsubq $128, %%rsp\n" \ + "3:\tcallq __lll_unlock_wake_private\n" \ + "4:\taddq $128, %%rsp\n" \ + "5:\tjmp 24f\n" \ + "6:\t.size _L_unlock_%=, 6b-1b\n\t" \ + ".previous\n" \ + LLL_STUB_UNWIND_INFO_5 \ + "24:" \ + : "=m" (futex), "=&D" (ignore) \ + : "m" (futex) \ + : "ax", "cx", "r11", "cc", "memory"); \ + else \ + __asm__ __volatile__ (__lll_unlock_asm_start \ + ".subsection 1\n\t" \ + ".type _L_unlock_%=, @function\n" \ + "_L_unlock_%=:\n" \ + "1:\tleaq %0, %%rdi\n" \ + "2:\tsubq $128, %%rsp\n" \ + "3:\tcallq __lll_unlock_wake\n" \ + "4:\taddq $128, %%rsp\n" \ + "5:\tjmp 24f\n" \ + "6:\t.size _L_unlock_%=, 6b-1b\n\t" \ + ".previous\n" \ + LLL_STUB_UNWIND_INFO_5 \ + "24:" \ + : "=m" (futex), "=&D" (ignore) \ + : "m" (futex), "S" (private) \ + : "ax", "cx", "r11", "cc", "memory"); \ + }) + +#define lll_robust_unlock(futex, private) \ + do \ + { \ + int ignore; \ + __asm__ __volatile__ (LOCK_INSTR "andl %2, %0\n\t" \ + "jne 1f\n\t" \ + ".subsection 1\n\t" \ + ".type _L_robust_unlock_%=, @function\n" \ + "_L_robust_unlock_%=:\n" \ + "1:\tleaq %0, %%rdi\n" \ + "2:\tsubq $128, %%rsp\n" \ + "3:\tcallq __lll_unlock_wake\n" \ + "4:\taddq $128, %%rsp\n" \ + "5:\tjmp 24f\n" \ + "6:\t.size _L_robust_unlock_%=, 6b-1b\n\t" \ + ".previous\n" \ + LLL_STUB_UNWIND_INFO_5 \ + "24:" \ + : "=m" (futex), "=&D" (ignore) \ + : "i" (FUTEX_WAITERS), "m" (futex), \ + "S" (private) \ + : "ax", "cx", "r11", "cc", "memory"); \ + } \ + while (0) + +#define lll_robust_dead(futex, private) \ + do \ + { \ + int ignore; \ + __asm__ __volatile__ (LOCK_INSTR "orl %3, (%2)\n\t" \ + "syscall" \ + : "=m" (futex), "=a" (ignore) \ + : "D" (&(futex)), "i" (FUTEX_OWNER_DIED), \ + "S" (__lll_private_flag (FUTEX_WAKE, private)), \ + "1" (__NR_futex), "d" (1) \ + : "cx", "r11", "cc", "memory"); \ + } \ + while (0) + +/* Returns non-zero if error happened, zero if success. */ +#define lll_futex_requeue(ftx, nr_wake, nr_move, mutex, val, private) \ + ({ int __res; \ + register int __nr_move __asm__ ("r10") = nr_move; \ + register void *__mutex __asm__ ("r8") = mutex; \ + register int __val __asm__ ("r9") = val; \ + __asm__ __volatile__ ("syscall" \ + : "=a" (__res) \ + : "0" (__NR_futex), "D" ((void *) ftx), \ + "S" (__lll_private_flag (FUTEX_CMP_REQUEUE, \ + private)), "d" (nr_wake), \ + "r" (__nr_move), "r" (__mutex), "r" (__val) \ + : "cx", "r11", "cc", "memory"); \ + __res < 0; }) + +#define lll_islocked(futex) \ + (futex != LLL_LOCK_INITIALIZER) + + +/* The kernel notifies a process with uses CLONE_CLEARTID via futex + wakeup when the clone terminates. The memory location contains the + thread ID while the clone is running and is reset to zero + afterwards. + + The macro parameter must not have any side effect. */ +#define lll_wait_tid(tid) \ + do { \ + int __ignore; \ + register __typeof (tid) _tid __asm__ ("edx") = (tid); \ + if (_tid != 0) \ + __asm__ __volatile__ ("xorq %%r10, %%r10\n\t" \ + "1:\tmovq %2, %%rax\n\t" \ + "syscall\n\t" \ + "cmpl $0, (%%rdi)\n\t" \ + "jne 1b" \ + : "=&a" (__ignore) \ + : "S" (FUTEX_WAIT), "i" (SYS_futex), "D" (&tid), \ + "d" (_tid) \ + : "memory", "cc", "r10", "r11", "cx"); \ + } while (0) + +extern int __lll_timedwait_tid (int *tid, const struct timespec *abstime) + attribute_hidden; +#define lll_timedwait_tid(tid, abstime) \ + ({ \ + int __result = 0; \ + if (tid != 0) \ + { \ + if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) \ + __result = EINVAL; \ + else \ + __result = __lll_timedwait_tid (&tid, abstime); \ + } \ + __result; }) + +#endif /* !__ASSEMBLER__ */ + +#endif /* lowlevellock.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevelrobustlock.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevelrobustlock.S new file mode 100644 index 00000000..2eb8e29f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevelrobustlock.S @@ -0,0 +1,306 @@ +/* Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2009 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include + + .text + +#define FUTEX_WAITERS 0x80000000 +#define FUTEX_OWNER_DIED 0x40000000 + +#ifdef __ASSUME_PRIVATE_FUTEX +# define LOAD_FUTEX_WAIT(reg) \ + xorl $(FUTEX_WAIT | FUTEX_PRIVATE_FLAG), reg +# define LOAD_FUTEX_WAIT_ABS(reg) \ + xorl $(FUTEX_WAIT_BITSET | FUTEX_PRIVATE_FLAG | FUTEX_CLOCK_REALTIME), reg +#else +# if FUTEX_WAIT == 0 +# define LOAD_FUTEX_WAIT(reg) \ + xorl $FUTEX_PRIVATE_FLAG, reg ; \ + andl %fs:PRIVATE_FUTEX, reg +# else +# define LOAD_FUTEX_WAIT(reg) \ + xorl $FUTEX_PRIVATE_FLAG, reg ; \ + andl %fs:PRIVATE_FUTEX, reg ; \ + orl $FUTEX_WAIT, reg +# endif +# define LOAD_FUTEX_WAIT_ABS(reg) \ + xorl $FUTEX_PRIVATE_FLAG, reg ; \ + andl %fs:PRIVATE_FUTEX, reg ; \ + orl $FUTEX_WAIT_BITSET | FUTEX_CLOCK_REALTIME, reg +#endif + +/* For the calculation see asm/vsyscall.h. */ +#define VSYSCALL_ADDR_vgettimeofday 0xffffffffff600000 + + + .globl __lll_robust_lock_wait + .type __lll_robust_lock_wait,@function + .hidden __lll_robust_lock_wait + .align 16 +__lll_robust_lock_wait: + cfi_startproc + pushq %r10 + cfi_adjust_cfa_offset(8) + pushq %rdx + cfi_adjust_cfa_offset(8) + cfi_offset(%r10, -16) + cfi_offset(%rdx, -24) + + xorq %r10, %r10 /* No timeout. */ + LOAD_FUTEX_WAIT (%esi) + +4: movl %eax, %edx + orl $FUTEX_WAITERS, %edx + + testl $FUTEX_OWNER_DIED, %eax + jnz 3f + + cmpl %edx, %eax + je 1f + + LOCK + cmpxchgl %edx, (%rdi) + jnz 2f + +1: movl $SYS_futex, %eax + syscall + + movl (%rdi), %eax + +2: testl %eax, %eax + jne 4b + + movl %fs:TID, %edx + orl $FUTEX_WAITERS, %edx + LOCK + cmpxchgl %edx, (%rdi) + jnz 4b + /* NB: %rax == 0 */ + +3: popq %rdx + cfi_adjust_cfa_offset(-8) + cfi_restore(%rdx) + popq %r10 + cfi_adjust_cfa_offset(-8) + cfi_restore(%r10) + retq + cfi_endproc + .size __lll_robust_lock_wait,.-__lll_robust_lock_wait + + + .globl __lll_robust_timedlock_wait + .type __lll_robust_timedlock_wait,@function + .hidden __lll_robust_timedlock_wait + .align 16 +__lll_robust_timedlock_wait: + cfi_startproc +# ifndef __ASSUME_FUTEX_CLOCK_REALTIME +# ifdef __PIC__ + cmpl $0, __have_futex_clock_realtime(%rip) +# else + cmpl $0, __have_futex_clock_realtime +# endif + je .Lreltmo +# endif + + pushq %r9 + cfi_adjust_cfa_offset(8) + cfi_rel_offset(%r9, 0) + movq %rdx, %r10 + movl $0xffffffff, %r9d + LOAD_FUTEX_WAIT_ABS (%esi) + +1: testl $FUTEX_OWNER_DIED, %eax + jnz 3f + + movl %eax, %edx + orl $FUTEX_WAITERS, %edx + + cmpl %eax, %edx + je 5f + + LOCK + cmpxchgl %edx, (%rdi) + movq $0, %rcx /* Must use mov to avoid changing cc. */ + jnz 6f + +5: movl $SYS_futex, %eax + syscall + movl %eax, %ecx + + movl (%rdi), %eax + +6: testl %eax, %eax + jne 2f + + movl %fs:TID, %edx + orl $FUTEX_WAITERS, %edx + LOCK + cmpxchgl %edx, (%rdi) + jnz 2f + +3: popq %r9 + cfi_adjust_cfa_offset(-8) + cfi_restore(%r9) + retq + + cfi_adjust_cfa_offset(8) + cfi_rel_offset(%r9, 0) + /* Check whether the time expired. */ +2: cmpl $-ETIMEDOUT, %ecx + je 4f + cmpl $-EINVAL, %ecx + jne 1b + +4: movl %ecx, %eax + negl %eax + jmp 3b + cfi_adjust_cfa_offset(-8) + cfi_restore(%r9) + + +# ifndef __ASSUME_FUTEX_CLOCK_REALTIME +.Lreltmo: + /* Check for a valid timeout value. */ + cmpq $1000000000, 8(%rdx) + jae 3f + + pushq %r8 + cfi_adjust_cfa_offset(8) + pushq %r9 + cfi_adjust_cfa_offset(8) + pushq %r12 + cfi_adjust_cfa_offset(8) + pushq %r13 + cfi_adjust_cfa_offset(8) + cfi_offset(%r8, -16) + cfi_offset(%r9, -24) + cfi_offset(%r12, -32) + cfi_offset(%r13, -40) + pushq %rsi + cfi_adjust_cfa_offset(8) + + /* Stack frame for the timespec and timeval structs. */ + subq $32, %rsp + cfi_adjust_cfa_offset(32) + + movq %rdi, %r12 + movq %rdx, %r13 + +1: movq %rax, 16(%rsp) + + /* Get current time. */ + movq %rsp, %rdi + xorl %esi, %esi + movq $VSYSCALL_ADDR_vgettimeofday, %rax + /* This is a regular function call, all caller-save registers + might be clobbered. */ + callq *%rax + + /* Compute relative timeout. */ + movq 8(%rsp), %rax + movl $1000, %edi + mul %rdi /* Milli seconds to nano seconds. */ + movq (%r13), %rdi + movq 8(%r13), %rsi + subq (%rsp), %rdi + subq %rax, %rsi + jns 4f + addq $1000000000, %rsi + decq %rdi +4: testq %rdi, %rdi + js 8f /* Time is already up. */ + + /* Futex call. */ + movq %rdi, (%rsp) /* Store relative timeout. */ + movq %rsi, 8(%rsp) + + movq 16(%rsp), %rdx + movl %edx, %eax + orl $FUTEX_WAITERS, %edx + + testl $FUTEX_OWNER_DIED, %eax + jnz 6f + + cmpl %eax, %edx + je 2f + + LOCK + cmpxchgl %edx, (%r12) + movq $0, %rcx /* Must use mov to avoid changing cc. */ + jnz 5f + +2: movq %rsp, %r10 + movl 32(%rsp), %esi + LOAD_FUTEX_WAIT (%esi) + movq %r12, %rdi + movl $SYS_futex, %eax + syscall + movq %rax, %rcx + + movl (%r12), %eax + +5: testl %eax, %eax + jne 7f + + movl %fs:TID, %edx + orl $FUTEX_WAITERS, %edx + LOCK + cmpxchgl %edx, (%r12) + jnz 7f + +6: addq $40, %rsp + cfi_adjust_cfa_offset(-40) + popq %r13 + cfi_adjust_cfa_offset(-8) + cfi_restore(%r13) + popq %r12 + cfi_adjust_cfa_offset(-8) + cfi_restore(%r12) + popq %r9 + cfi_adjust_cfa_offset(-8) + cfi_restore(%r9) + popq %r8 + cfi_adjust_cfa_offset(-8) + cfi_restore(%r8) + retq + +3: movl $EINVAL, %eax + retq + + cfi_adjust_cfa_offset(72) + cfi_offset(%r8, -16) + cfi_offset(%r9, -24) + cfi_offset(%r12, -32) + cfi_offset(%r13, -40) + /* Check whether the time expired. */ +7: cmpl $-ETIMEDOUT, %ecx + jne 1b + +8: movl $ETIMEDOUT, %eax + jmp 6b +#endif + cfi_endproc + .size __lll_robust_timedlock_wait,.-__lll_robust_timedlock_wait diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pt-__syscall_error.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pt-__syscall_error.c new file mode 100644 index 00000000..2ab81490 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pt-__syscall_error.c @@ -0,0 +1 @@ +#include <../../../../../../../libc/sysdeps/linux/x86_64/__syscall_error.c> diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pt-vfork.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pt-vfork.S new file mode 100644 index 00000000..df494961 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pt-vfork.S @@ -0,0 +1,33 @@ +/* Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#define SAVE_PID \ + movl %fs:PID, %esi; \ + movl %esi, %edx; \ + negl %edx; \ + movl %edx, %fs:PID + +#define RESTORE_PID \ + testq %rax, %rax; \ + je 1f; \ + movl %esi, %fs:PID; \ +1: + +#include <../../../../../../../libc/sysdeps/linux/x86_64/vfork.S> diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_barrier_wait.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_barrier_wait.S new file mode 100644 index 00000000..15ad534f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_barrier_wait.S @@ -0,0 +1,161 @@ +/* Copyright (C) 2002, 2003, 2004, 2005, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + + + .text + + .globl pthread_barrier_wait + .type pthread_barrier_wait,@function + .align 16 +pthread_barrier_wait: + /* Get the mutex. */ + xorl %eax, %eax + movl $1, %esi + LOCK + cmpxchgl %esi, MUTEX(%rdi) + jnz 1f + + /* One less waiter. If this was the last one needed wake + everybody. */ +2: decl LEFT(%rdi) + je 3f + + /* There are more threads to come. */ +#if CURR_EVENT == 0 + movl (%rdi), %edx +#else + movl CURR_EVENT(%rdi), %edx +#endif + + /* Release the mutex. */ + LOCK + decl MUTEX(%rdi) + jne 6f + + /* Wait for the remaining threads. The call will return immediately + if the CURR_EVENT memory has meanwhile been changed. */ +7: +#if FUTEX_WAIT == 0 + movl PRIVATE(%rdi), %esi +#else + movl $FUTEX_WAIT, %esi + orl PRIVATE(%rdi), %esi +#endif + xorq %r10, %r10 +8: movl $SYS_futex, %eax + syscall + + /* Don't return on spurious wakeups. The syscall does not change + any register except %eax so there is no need to reload any of + them. */ +#if CURR_EVENT == 0 + cmpl %edx, (%rdi) +#else + cmpl %edx, CURR_EVENT(%rdi) +#endif + je 8b + + /* Increment LEFT. If this brings the count back to the + initial count unlock the object. */ + movl $1, %edx + movl INIT_COUNT(%rdi), %eax + LOCK + xaddl %edx, LEFT(%rdi) + subl $1, %eax + cmpl %eax, %edx + jne,pt 10f + + /* Release the mutex. We cannot release the lock before + waking the waiting threads since otherwise a new thread might + arrive and gets waken up, too. */ + LOCK + decl MUTEX(%rdi) + jne 9f + +10: xorl %eax, %eax /* != PTHREAD_BARRIER_SERIAL_THREAD */ + + retq + + /* The necessary number of threads arrived. */ +3: +#if CURR_EVENT == 0 + incl (%rdi) +#else + incl CURR_EVENT(%rdi) +#endif + + /* Wake up all waiters. The count is a signed number in the kernel + so 0x7fffffff is the highest value. */ + movl $0x7fffffff, %edx + movl $FUTEX_WAKE, %esi + orl PRIVATE(%rdi), %esi + movl $SYS_futex, %eax + syscall + + /* Increment LEFT. If this brings the count back to the + initial count unlock the object. */ + movl $1, %edx + movl INIT_COUNT(%rdi), %eax + LOCK + xaddl %edx, LEFT(%rdi) + subl $1, %eax + cmpl %eax, %edx + jne,pt 5f + + /* Release the mutex. We cannot release the lock before + waking the waiting threads since otherwise a new thread might + arrive and gets waken up, too. */ + LOCK + decl MUTEX(%rdi) + jne 4f + +5: orl $-1, %eax /* == PTHREAD_BARRIER_SERIAL_THREAD */ + + retq + +1: movl PRIVATE(%rdi), %esi + addq $MUTEX, %rdi + xorl $LLL_SHARED, %esi + callq __lll_lock_wait + subq $MUTEX, %rdi + jmp 2b + +4: movl PRIVATE(%rdi), %esi + addq $MUTEX, %rdi + xorl $LLL_SHARED, %esi + callq __lll_unlock_wake + jmp 5b + +6: movl PRIVATE(%rdi), %esi + addq $MUTEX, %rdi + xorl $LLL_SHARED, %esi + callq __lll_unlock_wake + subq $MUTEX, %rdi + jmp 7b + +9: movl PRIVATE(%rdi), %esi + addq $MUTEX, %rdi + xorl $LLL_SHARED, %esi + callq __lll_unlock_wake + jmp 10b + .size pthread_barrier_wait,.-pthread_barrier_wait diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S new file mode 100644 index 00000000..1a116cf8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_broadcast.S @@ -0,0 +1,178 @@ +/* Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2009 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include + + + .text + + /* int pthread_cond_broadcast (pthread_cond_t *cond) */ + .globl __pthread_cond_broadcast + .type __pthread_cond_broadcast, @function + .protected __pthread_cond_broadcast + .align 16 +__pthread_cond_broadcast: + + /* Get internal lock. */ + movl $1, %esi + xorl %eax, %eax + LOCK +#if cond_lock == 0 + cmpxchgl %esi, (%rdi) +#else + cmpxchgl %esi, cond_lock(%rdi) +#endif + jnz 1f + +2: addq $cond_futex, %rdi + movq total_seq-cond_futex(%rdi), %r9 + cmpq wakeup_seq-cond_futex(%rdi), %r9 + jna 4f + + /* Cause all currently waiting threads to recognize they are + woken up. */ + movq %r9, wakeup_seq-cond_futex(%rdi) + movq %r9, woken_seq-cond_futex(%rdi) + addq %r9, %r9 + movl %r9d, (%rdi) + incl broadcast_seq-cond_futex(%rdi) + + /* Get the address of the mutex used. */ + movq dep_mutex-cond_futex(%rdi), %r8 + + /* Unlock. */ + LOCK + decl cond_lock-cond_futex(%rdi) + jne 7f + +8: cmpq $-1, %r8 + je 9f + + /* Do not use requeue for pshared condvars. */ + testl $PS_BIT, MUTEX_KIND(%r8) + jne 9f + + /* Requeue to a PI mutex if the PI bit is set. */ + movl MUTEX_KIND(%r8), %eax + andl $(ROBUST_BIT|PI_BIT), %eax + cmpl $PI_BIT, %eax + je 81f + + /* Wake up all threads. */ +#ifdef __ASSUME_PRIVATE_FUTEX + movl $(FUTEX_CMP_REQUEUE|FUTEX_PRIVATE_FLAG), %esi +#else + movl %fs:PRIVATE_FUTEX, %esi + orl $FUTEX_CMP_REQUEUE, %esi +#endif + movl $SYS_futex, %eax + movl $1, %edx + movl $0x7fffffff, %r10d + syscall + + /* For any kind of error, which mainly is EAGAIN, we try again + with WAKE. The general test also covers running on old + kernels. */ + cmpq $-4095, %rax + jae 9f + +10: xorl %eax, %eax + retq + + /* Wake up all threads. */ +81: movl $(FUTEX_CMP_REQUEUE_PI|FUTEX_PRIVATE_FLAG), %esi + movl $SYS_futex, %eax + movl $1, %edx + movl $0x7fffffff, %r10d + syscall + + /* For any kind of error, which mainly is EAGAIN, we try again + with WAKE. The general test also covers running on old + kernels. */ + cmpq $-4095, %rax + jb 10b + jmp 9f + + .align 16 + /* Unlock. */ +4: LOCK + decl cond_lock-cond_futex(%rdi) + jne 5f + +6: xorl %eax, %eax + retq + + /* Initial locking failed. */ +1: +#if cond_lock != 0 + addq $cond_lock, %rdi +#endif + cmpq $-1, dep_mutex-cond_lock(%rdi) + movl $LLL_PRIVATE, %eax + movl $LLL_SHARED, %esi + cmovne %eax, %esi + callq __lll_lock_wait +#if cond_lock != 0 + subq $cond_lock, %rdi +#endif + jmp 2b + + /* Unlock in loop requires wakeup. */ +5: addq $cond_lock-cond_futex, %rdi + cmpq $-1, dep_mutex-cond_lock(%rdi) + movl $LLL_PRIVATE, %eax + movl $LLL_SHARED, %esi + cmovne %eax, %esi + callq __lll_unlock_wake + jmp 6b + + /* Unlock in loop requires wakeup. */ +7: addq $cond_lock-cond_futex, %rdi + cmpq $-1, %r8 + movl $LLL_PRIVATE, %eax + movl $LLL_SHARED, %esi + cmovne %eax, %esi + callq __lll_unlock_wake + subq $cond_lock-cond_futex, %rdi + jmp 8b + +9: /* The futex requeue functionality is not available. */ + cmpq $-1, %r8 + movl $0x7fffffff, %edx +#ifdef __ASSUME_PRIVATE_FUTEX + movl $FUTEX_WAKE, %eax + movl $(FUTEX_WAKE|FUTEX_PRIVATE_FLAG), %esi + cmove %eax, %esi +#else + movl $0, %eax + movl %fs:PRIVATE_FUTEX, %esi + cmove %eax, %esi + orl $FUTEX_WAKE, %esi +#endif + movl $SYS_futex, %eax + syscall + jmp 10b + .size __pthread_cond_broadcast, .-__pthread_cond_broadcast +weak_alias(__pthread_cond_broadcast, pthread_cond_broadcast) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.S new file mode 100644 index 00000000..9852e79f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_signal.S @@ -0,0 +1,161 @@ +/* Copyright (C) 2002-2005, 2007, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include + + + .text + + /* int pthread_cond_signal (pthread_cond_t *cond) */ + .globl __pthread_cond_signal + .type __pthread_cond_signal, @function + .protected __pthread_cond_signal + .align 16 +__pthread_cond_signal: + + /* Get internal lock. */ + movq %rdi, %r8 + movl $1, %esi + xorl %eax, %eax + LOCK +#if cond_lock == 0 + cmpxchgl %esi, (%rdi) +#else + cmpxchgl %esi, cond_lock(%rdi) +#endif + jnz 1f + +2: addq $cond_futex, %rdi + movq total_seq(%r8), %rcx + cmpq wakeup_seq(%r8), %rcx + jbe 4f + + /* Bump the wakeup number. */ + addq $1, wakeup_seq(%r8) + addl $1, (%rdi) + + /* Wake up one thread. */ + cmpq $-1, dep_mutex(%r8) + movl $FUTEX_WAKE_OP, %esi + movl $1, %edx + movl $SYS_futex, %eax + je 8f + + /* Get the address of the mutex used. */ + movq dep_mutex(%r8), %rcx + movl MUTEX_KIND(%rcx), %r11d + andl $(ROBUST_BIT|PI_BIT), %r11d + cmpl $PI_BIT, %r11d + je 9f + +#ifdef __ASSUME_PRIVATE_FUTEX + movl $(FUTEX_WAKE_OP|FUTEX_PRIVATE_FLAG), %esi +#else + orl %fs:PRIVATE_FUTEX, %esi +#endif + +8: movl $1, %r10d +#if cond_lock != 0 + addq $cond_lock, %r8 +#endif + movl $FUTEX_OP_CLEAR_WAKE_IF_GT_ONE, %r9d + syscall +#if cond_lock != 0 + subq $cond_lock, %r8 +#endif + /* For any kind of error, we try again with WAKE. + The general test also covers running on old kernels. */ + cmpq $-4095, %rax + jae 7f + + xorl %eax, %eax + retq + + /* Wake up one thread and requeue none in the PI Mutex case. */ +9: movl $(FUTEX_CMP_REQUEUE_PI|FUTEX_PRIVATE_FLAG), %esi + movq %rcx, %r8 + xorq %r10, %r10 + movl (%rdi), %r9d // XXX Can this be right? + syscall + + leaq -cond_futex(%rdi), %r8 + + /* For any kind of error, we try again with WAKE. + The general test also covers running on old kernels. */ + cmpq $-4095, %rax + jb 4f + +7: +#ifdef __ASSUME_PRIVATE_FUTEX + andl $FUTEX_PRIVATE_FLAG, %esi +#else + andl %fs:PRIVATE_FUTEX, %esi +#endif + orl $FUTEX_WAKE, %esi + movl $SYS_futex, %eax + /* %rdx should be 1 already from $FUTEX_WAKE_OP syscall. + movl $1, %edx */ + syscall + + /* Unlock. */ +4: LOCK +#if cond_lock == 0 + decl (%r8) +#else + decl cond_lock(%r8) +#endif + jne 5f + +6: xorl %eax, %eax + retq + + /* Initial locking failed. */ +1: +#if cond_lock != 0 + addq $cond_lock, %rdi +#endif + cmpq $-1, dep_mutex-cond_lock(%rdi) + movl $LLL_PRIVATE, %eax + movl $LLL_SHARED, %esi + cmovne %eax, %esi + callq __lll_lock_wait +#if cond_lock != 0 + subq $cond_lock, %rdi +#endif + jmp 2b + + /* Unlock in loop requires wakeup. */ +5: + movq %r8, %rdi +#if cond_lock != 0 + addq $cond_lock, %rdi +#endif + cmpq $-1, dep_mutex-cond_lock(%rdi) + movl $LLL_PRIVATE, %eax + movl $LLL_SHARED, %esi + cmovne %eax, %esi + callq __lll_unlock_wake + jmp 6b + .size __pthread_cond_signal, .-__pthread_cond_signal +weak_alias(__pthread_cond_signal, pthread_cond_signal) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S new file mode 100644 index 00000000..3a965ad0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_timedwait.S @@ -0,0 +1,804 @@ +/* Copyright (C) 2002-2005, 2007, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include +#include + +/* For the calculation see asm/vsyscall.h. */ +#define VSYSCALL_ADDR_vgettimeofday 0xffffffffff600000 + + + .text + + +/* int pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex, + const struct timespec *abstime) */ + .globl __pthread_cond_timedwait + .type __pthread_cond_timedwait, @function + .protected __pthread_cond_timedwait + .align 16 +__pthread_cond_timedwait: +.LSTARTCODE: + cfi_startproc + + pushq %r12 + cfi_adjust_cfa_offset(8) + cfi_rel_offset(%r12, 0) + pushq %r13 + cfi_adjust_cfa_offset(8) + cfi_rel_offset(%r13, 0) + pushq %r14 + cfi_adjust_cfa_offset(8) + cfi_rel_offset(%r14, 0) + pushq %r15 + cfi_adjust_cfa_offset(8) + cfi_rel_offset(%r15, 0) +#ifdef __ASSUME_FUTEX_CLOCK_REALTIME +# define FRAME_SIZE 32 +#else +# define FRAME_SIZE 48 +#endif + subq $FRAME_SIZE, %rsp + cfi_adjust_cfa_offset(FRAME_SIZE) + cfi_remember_state + + cmpq $1000000000, 8(%rdx) + movl $EINVAL, %eax + jae 48f + + /* Stack frame: + + rsp + 48 + +--------------------------+ + rsp + 32 | timeout value | + +--------------------------+ + rsp + 24 | old wake_seq value | + +--------------------------+ + rsp + 16 | mutex pointer | + +--------------------------+ + rsp + 8 | condvar pointer | + +--------------------------+ + rsp + 4 | old broadcast_seq value | + +--------------------------+ + rsp + 0 | old cancellation mode | + +--------------------------+ + */ + + cmpq $-1, dep_mutex(%rdi) + + /* Prepare structure passed to cancellation handler. */ + movq %rdi, 8(%rsp) + movq %rsi, 16(%rsp) + movq %rdx, %r13 + + je 22f + movq %rsi, dep_mutex(%rdi) + +22: +#ifndef __ASSUME_FUTEX_CLOCK_REALTIME +# ifdef __PIC__ + cmpl $0, __have_futex_clock_realtime(%rip) +# else + cmpl $0, __have_futex_clock_realtime +# endif + je .Lreltmo +#endif + + /* Get internal lock. */ + movl $1, %esi + xorl %eax, %eax + LOCK +#if cond_lock == 0 + cmpxchgl %esi, (%rdi) +#else + cmpxchgl %esi, cond_lock(%rdi) +#endif + jnz 31f + + /* Unlock the mutex. */ +32: movq 16(%rsp), %rdi + xorl %esi, %esi + callq __pthread_mutex_unlock_usercnt + + testl %eax, %eax + jne 46f + + movq 8(%rsp), %rdi + incq total_seq(%rdi) + incl cond_futex(%rdi) + addl $(1 << nwaiters_shift), cond_nwaiters(%rdi) + + /* Get and store current wakeup_seq value. */ + movq 8(%rsp), %rdi + movq wakeup_seq(%rdi), %r9 + movl broadcast_seq(%rdi), %edx + movq %r9, 24(%rsp) + movl %edx, 4(%rsp) + +38: movl cond_futex(%rdi), %r12d + + /* Unlock. */ + LOCK +#if cond_lock == 0 + decl (%rdi) +#else + decl cond_lock(%rdi) +#endif + jne 33f + +.LcleanupSTART1: +34: callq __pthread_enable_asynccancel + movl %eax, (%rsp) + + movq %r13, %r10 + movl $FUTEX_WAIT_BITSET, %esi + cmpq $-1, dep_mutex(%rdi) + je 60f + + movq dep_mutex(%rdi), %r8 + /* Requeue to a non-robust PI mutex if the PI bit is set and + the robust bit is not set. */ + movl MUTEX_KIND(%r8), %eax + andl $(ROBUST_BIT|PI_BIT), %eax + cmpl $PI_BIT, %eax + jne 61f + + movl $(FUTEX_WAIT_REQUEUE_PI|FUTEX_PRIVATE_FLAG), %esi + xorl %eax, %eax + /* The following only works like this because we only support + two clocks, represented using a single bit. */ + testl $1, cond_nwaiters(%rdi) + movl $FUTEX_CLOCK_REALTIME, %edx + cmove %edx, %eax + orl %eax, %esi + movq %r12, %rdx + addq $cond_futex, %rdi + movl $SYS_futex, %eax + syscall + + movl $1, %r15d +#ifdef __ASSUME_REQUEUE_PI + jmp 62f +#else + cmpq $-4095, %rax + jnae 62f + + subq $cond_futex, %rdi +#endif + +61: movl $(FUTEX_WAIT_BITSET|FUTEX_PRIVATE_FLAG), %esi +60: xorl %r15d, %r15d + xorl %eax, %eax + /* The following only works like this because we only support + two clocks, represented using a single bit. */ + testl $1, cond_nwaiters(%rdi) + movl $FUTEX_CLOCK_REALTIME, %edx + movl $0xffffffff, %r9d + cmove %edx, %eax + orl %eax, %esi + movq %r12, %rdx + addq $cond_futex, %rdi + movl $SYS_futex, %eax + syscall +62: movq %rax, %r14 + + movl (%rsp), %edi + callq __pthread_disable_asynccancel +.LcleanupEND1: + + /* Lock. */ + movq 8(%rsp), %rdi + movl $1, %esi + xorl %eax, %eax + LOCK +#if cond_lock == 0 + cmpxchgl %esi, (%rdi) +#else + cmpxchgl %esi, cond_lock(%rdi) +#endif + jne 35f + +36: movl broadcast_seq(%rdi), %edx + + movq woken_seq(%rdi), %rax + + movq wakeup_seq(%rdi), %r9 + + cmpl 4(%rsp), %edx + jne 53f + + cmpq 24(%rsp), %r9 + jbe 45f + + cmpq %rax, %r9 + ja 39f + +45: cmpq $-ETIMEDOUT, %r14 + jne 38b + +99: incq wakeup_seq(%rdi) + incl cond_futex(%rdi) + movl $ETIMEDOUT, %r14d + jmp 44f + +53: xorq %r14, %r14 + jmp 54f + +39: xorq %r14, %r14 +44: incq woken_seq(%rdi) + +54: subl $(1 << nwaiters_shift), cond_nwaiters(%rdi) + + /* Wake up a thread which wants to destroy the condvar object. */ + cmpq $0xffffffffffffffff, total_seq(%rdi) + jne 55f + movl cond_nwaiters(%rdi), %eax + andl $~((1 << nwaiters_shift) - 1), %eax + jne 55f + + addq $cond_nwaiters, %rdi + cmpq $-1, dep_mutex-cond_nwaiters(%rdi) + movl $1, %edx +#ifdef __ASSUME_PRIVATE_FUTEX + movl $FUTEX_WAKE, %eax + movl $(FUTEX_WAKE|FUTEX_PRIVATE_FLAG), %esi + cmove %eax, %esi +#else + movl $0, %eax + movl %fs:PRIVATE_FUTEX, %esi + cmove %eax, %esi + orl $FUTEX_WAKE, %esi +#endif + movl $SYS_futex, %eax + syscall + subq $cond_nwaiters, %rdi + +55: LOCK +#if cond_lock == 0 + decl (%rdi) +#else + decl cond_lock(%rdi) +#endif + jne 40f + + /* If requeue_pi is used the kernel performs the locking of the + mutex. */ +41: movq 16(%rsp), %rdi + testl %r15d, %r15d + jnz 64f + + callq __pthread_mutex_cond_lock + +63: testq %rax, %rax + cmoveq %r14, %rax + +48: addq $FRAME_SIZE, %rsp + cfi_adjust_cfa_offset(-FRAME_SIZE) + popq %r15 + cfi_adjust_cfa_offset(-8) + cfi_restore(%r15) + popq %r14 + cfi_adjust_cfa_offset(-8) + cfi_restore(%r14) + popq %r13 + cfi_adjust_cfa_offset(-8) + cfi_restore(%r13) + popq %r12 + cfi_adjust_cfa_offset(-8) + cfi_restore(%r12) + + retq + + cfi_restore_state + +64: callq __pthread_mutex_cond_lock_adjust + movq %r14, %rax + jmp 48b + + /* Initial locking failed. */ +31: +#if cond_lock != 0 + addq $cond_lock, %rdi +#endif + cmpq $-1, dep_mutex-cond_lock(%rdi) + movl $LLL_PRIVATE, %eax + movl $LLL_SHARED, %esi + cmovne %eax, %esi + callq __lll_lock_wait + jmp 32b + + /* Unlock in loop requires wakeup. */ +33: +#if cond_lock != 0 + addq $cond_lock, %rdi +#endif + cmpq $-1, dep_mutex-cond_lock(%rdi) + movl $LLL_PRIVATE, %eax + movl $LLL_SHARED, %esi + cmovne %eax, %esi + callq __lll_unlock_wake + jmp 34b + + /* Locking in loop failed. */ +35: +#if cond_lock != 0 + addq $cond_lock, %rdi +#endif + cmpq $-1, dep_mutex-cond_lock(%rdi) + movl $LLL_PRIVATE, %eax + movl $LLL_SHARED, %esi + cmovne %eax, %esi + callq __lll_lock_wait +#if cond_lock != 0 + subq $cond_lock, %rdi +#endif + jmp 36b + + /* Unlock after loop requires wakeup. */ +40: +#if cond_lock != 0 + addq $cond_lock, %rdi +#endif + cmpq $-1, dep_mutex-cond_lock(%rdi) + movl $LLL_PRIVATE, %eax + movl $LLL_SHARED, %esi + cmovne %eax, %esi + callq __lll_unlock_wake + jmp 41b + + /* The initial unlocking of the mutex failed. */ +46: movq 8(%rsp), %rdi + movq %rax, (%rsp) + LOCK +#if cond_lock == 0 + decl (%rdi) +#else + decl cond_lock(%rdi) +#endif + jne 47f + +#if cond_lock != 0 + addq $cond_lock, %rdi +#endif + cmpq $-1, dep_mutex-cond_lock(%rdi) + movl $LLL_PRIVATE, %eax + movl $LLL_SHARED, %esi + cmovne %eax, %esi + callq __lll_unlock_wake + +47: movq (%rsp), %rax + jmp 48b + + +#ifndef __ASSUME_FUTEX_CLOCK_REALTIME +.Lreltmo: + xorl %r15d, %r15d + + /* Get internal lock. */ + movl $1, %esi + xorl %eax, %eax + LOCK +# if cond_lock == 0 + cmpxchgl %esi, (%rdi) +# else + cmpxchgl %esi, cond_lock(%rdi) +# endif + jnz 1f + + /* Unlock the mutex. */ +2: movq 16(%rsp), %rdi + xorl %esi, %esi + callq __pthread_mutex_unlock_usercnt + + testl %eax, %eax + jne 46b + + movq 8(%rsp), %rdi + incq total_seq(%rdi) + incl cond_futex(%rdi) + addl $(1 << nwaiters_shift), cond_nwaiters(%rdi) + + /* Get and store current wakeup_seq value. */ + movq 8(%rsp), %rdi + movq wakeup_seq(%rdi), %r9 + movl broadcast_seq(%rdi), %edx + movq %r9, 24(%rsp) + movl %edx, 4(%rsp) + + /* Get the current time. */ +8: +# ifdef __NR_clock_gettime + /* Get the clock number. Note that the field in the condvar + structure stores the number minus 1. */ + movq 8(%rsp), %rdi + movl cond_nwaiters(%rdi), %edi + andl $((1 << nwaiters_shift) - 1), %edi + /* Only clocks 0 and 1 are allowed so far. Both are handled in the + kernel. */ + leaq 32(%rsp), %rsi +# ifdef SHARED + movq __vdso_clock_gettime@GOTPCREL(%rip), %rax + movq (%rax), %rax + PTR_DEMANGLE (%rax) + jz 26f + call *%rax + jmp 27f +# endif +26: movl $__NR_clock_gettime, %eax + syscall +27: +# ifndef __ASSUME_POSIX_TIMERS + cmpq $-ENOSYS, %rax + je 19f +# endif + + /* Compute relative timeout. */ + movq (%r13), %rcx + movq 8(%r13), %rdx + subq 32(%rsp), %rcx + subq 40(%rsp), %rdx +# else + leaq 24(%rsp), %rdi + xorl %esi, %esi + movq $VSYSCALL_ADDR_vgettimeofday, %rax + callq *%rax + + /* Compute relative timeout. */ + movq 40(%rsp), %rax + movl $1000, %edx + mul %rdx /* Milli seconds to nano seconds. */ + movq (%r13), %rcx + movq 8(%r13), %rdx + subq 32(%rsp), %rcx + subq %rax, %rdx +# endif + jns 12f + addq $1000000000, %rdx + decq %rcx +12: testq %rcx, %rcx + movq 8(%rsp), %rdi + movq $-ETIMEDOUT, %r14 + js 6f + + /* Store relative timeout. */ +21: movq %rcx, 32(%rsp) + movq %rdx, 40(%rsp) + + movl cond_futex(%rdi), %r12d + + /* Unlock. */ + LOCK +# if cond_lock == 0 + decl (%rdi) +# else + decl cond_lock(%rdi) +# endif + jne 3f + +.LcleanupSTART2: +4: callq __pthread_enable_asynccancel + movl %eax, (%rsp) + + leaq 32(%rsp), %r10 + cmpq $-1, dep_mutex(%rdi) + movq %r12, %rdx +# ifdef __ASSUME_PRIVATE_FUTEX + movl $FUTEX_WAIT, %eax + movl $(FUTEX_WAIT|FUTEX_PRIVATE_FLAG), %esi + cmove %eax, %esi +# else + movl $0, %eax + movl %fs:PRIVATE_FUTEX, %esi + cmove %eax, %esi +# if FUTEX_WAIT != 0 + orl $FUTEX_WAIT, %esi +# endif +# endif + addq $cond_futex, %rdi + movl $SYS_futex, %eax + syscall + movq %rax, %r14 + + movl (%rsp), %edi + callq __pthread_disable_asynccancel +.LcleanupEND2: + + /* Lock. */ + movq 8(%rsp), %rdi + movl $1, %esi + xorl %eax, %eax + LOCK +# if cond_lock == 0 + cmpxchgl %esi, (%rdi) +# else + cmpxchgl %esi, cond_lock(%rdi) +# endif + jne 5f + +6: movl broadcast_seq(%rdi), %edx + + movq woken_seq(%rdi), %rax + + movq wakeup_seq(%rdi), %r9 + + cmpl 4(%rsp), %edx + jne 53b + + cmpq 24(%rsp), %r9 + jbe 15f + + cmpq %rax, %r9 + ja 39b + +15: cmpq $-ETIMEDOUT, %r14 + jne 8b + + jmp 99b + + /* Initial locking failed. */ +1: +# if cond_lock != 0 + addq $cond_lock, %rdi +# endif + cmpq $-1, dep_mutex-cond_lock(%rdi) + movl $LLL_PRIVATE, %eax + movl $LLL_SHARED, %esi + cmovne %eax, %esi + callq __lll_lock_wait + jmp 2b + + /* Unlock in loop requires wakeup. */ +3: +# if cond_lock != 0 + addq $cond_lock, %rdi +# endif + cmpq $-1, dep_mutex-cond_lock(%rdi) + movl $LLL_PRIVATE, %eax + movl $LLL_SHARED, %esi + cmovne %eax, %esi + callq __lll_unlock_wake + jmp 4b + + /* Locking in loop failed. */ +5: +# if cond_lock != 0 + addq $cond_lock, %rdi +# endif + cmpq $-1, dep_mutex-cond_lock(%rdi) + movl $LLL_PRIVATE, %eax + movl $LLL_SHARED, %esi + cmovne %eax, %esi + callq __lll_lock_wait +# if cond_lock != 0 + subq $cond_lock, %rdi +# endif + jmp 6b + +# if defined __NR_clock_gettime && !defined __ASSUME_POSIX_TIMERS + /* clock_gettime not available. */ +19: leaq 32(%rsp), %rdi + xorl %esi, %esi + movq $VSYSCALL_ADDR_vgettimeofday, %rax + callq *%rax + + /* Compute relative timeout. */ + movq 40(%rsp), %rax + movl $1000, %edx + mul %rdx /* Milli seconds to nano seconds. */ + movq (%r13), %rcx + movq 8(%r13), %rdx + subq 32(%rsp), %rcx + subq %rax, %rdx + jns 20f + addq $1000000000, %rdx + decq %rcx +20: testq %rcx, %rcx + movq 8(%rsp), %rdi + movq $-ETIMEDOUT, %r14 + js 6b + jmp 21b +# endif +#endif + .size __pthread_cond_timedwait, .-__pthread_cond_timedwait +weak_alias(__pthread_cond_timedwait, pthread_cond_timedwait) + + + .align 16 + .type __condvar_cleanup2, @function +__condvar_cleanup2: + /* Stack frame: + + rsp + 72 + +--------------------------+ + rsp + 64 | %r12 | + +--------------------------+ + rsp + 56 | %r13 | + +--------------------------+ + rsp + 48 | %r14 | + +--------------------------+ + rsp + 24 | unused | + +--------------------------+ + rsp + 16 | mutex pointer | + +--------------------------+ + rsp + 8 | condvar pointer | + +--------------------------+ + rsp + 4 | old broadcast_seq value | + +--------------------------+ + rsp + 0 | old cancellation mode | + +--------------------------+ + */ + + movq %rax, 24(%rsp) + + /* Get internal lock. */ + movq 8(%rsp), %rdi + movl $1, %esi + xorl %eax, %eax + LOCK +#if cond_lock == 0 + cmpxchgl %esi, (%rdi) +#else + cmpxchgl %esi, cond_lock(%rdi) +#endif + jz 1f + +#if cond_lock != 0 + addq $cond_lock, %rdi +#endif + cmpq $-1, dep_mutex-cond_lock(%rdi) + movl $LLL_PRIVATE, %eax + movl $LLL_SHARED, %esi + cmovne %eax, %esi + callq __lll_lock_wait +#if cond_lock != 0 + subq $cond_lock, %rdi +#endif + +1: movl broadcast_seq(%rdi), %edx + cmpl 4(%rsp), %edx + jne 3f + + /* We increment the wakeup_seq counter only if it is lower than + total_seq. If this is not the case the thread was woken and + then canceled. In this case we ignore the signal. */ + movq total_seq(%rdi), %rax + cmpq wakeup_seq(%rdi), %rax + jbe 6f + incq wakeup_seq(%rdi) + incl cond_futex(%rdi) +6: incq woken_seq(%rdi) + +3: subl $(1 << nwaiters_shift), cond_nwaiters(%rdi) + + /* Wake up a thread which wants to destroy the condvar object. */ + xorq %r12, %r12 + cmpq $0xffffffffffffffff, total_seq(%rdi) + jne 4f + movl cond_nwaiters(%rdi), %eax + andl $~((1 << nwaiters_shift) - 1), %eax + jne 4f + + cmpq $-1, dep_mutex(%rdi) + leaq cond_nwaiters(%rdi), %rdi + movl $1, %edx +#ifdef __ASSUME_PRIVATE_FUTEX + movl $FUTEX_WAKE, %eax + movl $(FUTEX_WAKE|FUTEX_PRIVATE_FLAG), %esi + cmove %eax, %esi +#else + movl $0, %eax + movl %fs:PRIVATE_FUTEX, %esi + cmove %eax, %esi + orl $FUTEX_WAKE, %esi +#endif + movl $SYS_futex, %eax + syscall + subq $cond_nwaiters, %rdi + movl $1, %r12d + +4: LOCK +#if cond_lock == 0 + decl (%rdi) +#else + decl cond_lock(%rdi) +#endif + je 2f +#if cond_lock != 0 + addq $cond_lock, %rdi +#endif + cmpq $-1, dep_mutex-cond_lock(%rdi) + movl $LLL_PRIVATE, %eax + movl $LLL_SHARED, %esi + cmovne %eax, %esi + callq __lll_unlock_wake + + /* Wake up all waiters to make sure no signal gets lost. */ +2: testq %r12, %r12 + jnz 5f + addq $cond_futex, %rdi + cmpq $-1, dep_mutex-cond_futex(%rdi) + movl $0x7fffffff, %edx +#ifdef __ASSUME_PRIVATE_FUTEX + movl $FUTEX_WAKE, %eax + movl $(FUTEX_WAKE|FUTEX_PRIVATE_FLAG), %esi + cmove %eax, %esi +#else + movl $0, %eax + movl %fs:PRIVATE_FUTEX, %esi + cmove %eax, %esi + orl $FUTEX_WAKE, %esi +#endif + movl $SYS_futex, %eax + syscall + +5: movq 16(%rsp), %rdi + callq __pthread_mutex_cond_lock + + movq 24(%rsp), %rdi + movq FRAME_SIZE(%rsp), %r15 + movq FRAME_SIZE+8(%rsp), %r14 + movq FRAME_SIZE+16(%rsp), %r13 + movq FRAME_SIZE+24(%rsp), %r12 +.LcallUR: + call _Unwind_Resume@PLT + hlt +.LENDCODE: + cfi_endproc + .size __condvar_cleanup2, .-__condvar_cleanup2 + + + .section .gcc_except_table,"a",@progbits +.LexceptSTART: + .byte DW_EH_PE_omit # @LPStart format + .byte DW_EH_PE_omit # @TType format + .byte DW_EH_PE_uleb128 # call-site format + .uleb128 .Lcstend-.Lcstbegin +.Lcstbegin: + .uleb128 .LcleanupSTART1-.LSTARTCODE + .uleb128 .LcleanupEND1-.LcleanupSTART1 + .uleb128 __condvar_cleanup2-.LSTARTCODE + .uleb128 0 +#ifndef __ASSUME_FUTEX_CLOCK_REALTIME + .uleb128 .LcleanupSTART2-.LSTARTCODE + .uleb128 .LcleanupEND2-.LcleanupSTART2 + .uleb128 __condvar_cleanup2-.LSTARTCODE + .uleb128 0 +#endif + .uleb128 .LcallUR-.LSTARTCODE + .uleb128 .LENDCODE-.LcallUR + .uleb128 0 + .uleb128 0 +.Lcstend: + + +#ifdef SHARED + .hidden DW.ref.__gcc_personality_v0 + .weak DW.ref.__gcc_personality_v0 + .section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits + .align 8 + .type DW.ref.__gcc_personality_v0, @object + .size DW.ref.__gcc_personality_v0, 8 +DW.ref.__gcc_personality_v0: + .quad __gcc_personality_v0 +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S new file mode 100644 index 00000000..cc67ed9d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_cond_wait.S @@ -0,0 +1,487 @@ +/* Copyright (C) 2002-2007, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include + +#include + + + .text + +/* int pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex) */ + .globl __pthread_cond_wait + .type __pthread_cond_wait, @function + .protected __pthread_cond_wait + .align 16 +__pthread_cond_wait: +.LSTARTCODE: + cfi_startproc + +#define FRAME_SIZE 32 + leaq -FRAME_SIZE(%rsp), %rsp + cfi_adjust_cfa_offset(FRAME_SIZE) + + /* Stack frame: + + rsp + 32 + +--------------------------+ + rsp + 24 | old wake_seq value | + +--------------------------+ + rsp + 16 | mutex pointer | + +--------------------------+ + rsp + 8 | condvar pointer | + +--------------------------+ + rsp + 4 | old broadcast_seq value | + +--------------------------+ + rsp + 0 | old cancellation mode | + +--------------------------+ + */ + + cmpq $-1, dep_mutex(%rdi) + + /* Prepare structure passed to cancellation handler. */ + movq %rdi, 8(%rsp) + movq %rsi, 16(%rsp) + + je 15f + movq %rsi, dep_mutex(%rdi) + + /* Get internal lock. */ +15: movl $1, %esi + xorl %eax, %eax + LOCK +#if cond_lock == 0 + cmpxchgl %esi, (%rdi) +#else + cmpxchgl %esi, cond_lock(%rdi) +#endif + jne 1f + + /* Unlock the mutex. */ +2: movq 16(%rsp), %rdi + xorl %esi, %esi + callq __pthread_mutex_unlock_usercnt + + testl %eax, %eax + jne 12f + + movq 8(%rsp), %rdi + incq total_seq(%rdi) + incl cond_futex(%rdi) + addl $(1 << nwaiters_shift), cond_nwaiters(%rdi) + + /* Get and store current wakeup_seq value. */ + movq 8(%rsp), %rdi + movq wakeup_seq(%rdi), %r9 + movl broadcast_seq(%rdi), %edx + movq %r9, 24(%rsp) + movl %edx, 4(%rsp) + + /* Unlock. */ +8: movl cond_futex(%rdi), %edx + LOCK +#if cond_lock == 0 + decl (%rdi) +#else + decl cond_lock(%rdi) +#endif + jne 3f + +.LcleanupSTART: +4: callq __pthread_enable_asynccancel + movl %eax, (%rsp) + + xorq %r10, %r10 + cmpq $-1, dep_mutex(%rdi) + leaq cond_futex(%rdi), %rdi + movl $FUTEX_WAIT, %esi + je 60f + + movq dep_mutex-cond_futex(%rdi), %r8 + /* Requeue to a non-robust PI mutex if the PI bit is set and + the robust bit is not set. */ + movl MUTEX_KIND(%r8), %eax + andl $(ROBUST_BIT|PI_BIT), %eax + cmpl $PI_BIT, %eax + jne 61f + + movl $(FUTEX_WAIT_REQUEUE_PI|FUTEX_PRIVATE_FLAG), %esi + movl $SYS_futex, %eax + syscall + + movl $1, %r8d +#ifdef __ASSUME_REQUEUE_PI + jmp 62f +#else + cmpq $-4095, %rax + jnae 62f + +# ifndef __ASSUME_PRIVATE_FUTEX + movl $FUTEX_WAIT, %esi +# endif +#endif + +61: +#ifdef __ASSUME_PRIVATE_FUTEX + movl $(FUTEX_WAIT|FUTEX_PRIVATE_FLAG), %esi +#else + orl %fs:PRIVATE_FUTEX, %esi +#endif +60: xorl %r8d, %r8d + movl $SYS_futex, %eax + syscall + +62: movl (%rsp), %edi + callq __pthread_disable_asynccancel +.LcleanupEND: + + /* Lock. */ + movq 8(%rsp), %rdi + movl $1, %esi + xorl %eax, %eax + LOCK +#if cond_lock == 0 + cmpxchgl %esi, (%rdi) +#else + cmpxchgl %esi, cond_lock(%rdi) +#endif + jnz 5f + +6: movl broadcast_seq(%rdi), %edx + + movq woken_seq(%rdi), %rax + + movq wakeup_seq(%rdi), %r9 + + cmpl 4(%rsp), %edx + jne 16f + + cmpq 24(%rsp), %r9 + jbe 8b + + cmpq %rax, %r9 + jna 8b + + incq woken_seq(%rdi) + + /* Unlock */ +16: subl $(1 << nwaiters_shift), cond_nwaiters(%rdi) + + /* Wake up a thread which wants to destroy the condvar object. */ + cmpq $0xffffffffffffffff, total_seq(%rdi) + jne 17f + movl cond_nwaiters(%rdi), %eax + andl $~((1 << nwaiters_shift) - 1), %eax + jne 17f + + addq $cond_nwaiters, %rdi + cmpq $-1, dep_mutex-cond_nwaiters(%rdi) + movl $1, %edx +#ifdef __ASSUME_PRIVATE_FUTEX + movl $FUTEX_WAKE, %eax + movl $(FUTEX_WAKE|FUTEX_PRIVATE_FLAG), %esi + cmove %eax, %esi +#else + movl $0, %eax + movl %fs:PRIVATE_FUTEX, %esi + cmove %eax, %esi + orl $FUTEX_WAKE, %esi +#endif + movl $SYS_futex, %eax + syscall + subq $cond_nwaiters, %rdi + +17: LOCK +#if cond_lock == 0 + decl (%rdi) +#else + decl cond_lock(%rdi) +#endif + jne 10f + + /* If requeue_pi is used the kernel performs the locking of the + mutex. */ +11: movq 16(%rsp), %rdi + testl %r8d, %r8d + jnz 18f + + callq __pthread_mutex_cond_lock + +14: leaq FRAME_SIZE(%rsp), %rsp + cfi_adjust_cfa_offset(-FRAME_SIZE) + + /* We return the result of the mutex_lock operation. */ + retq + + cfi_adjust_cfa_offset(FRAME_SIZE) + +18: callq __pthread_mutex_cond_lock_adjust + xorl %eax, %eax + jmp 14b + + /* Initial locking failed. */ +1: +#if cond_lock != 0 + addq $cond_lock, %rdi +#endif + cmpq $-1, dep_mutex-cond_lock(%rdi) + movl $LLL_PRIVATE, %eax + movl $LLL_SHARED, %esi + cmovne %eax, %esi + callq __lll_lock_wait + jmp 2b + + /* Unlock in loop requires wakeup. */ +3: +#if cond_lock != 0 + addq $cond_lock, %rdi +#endif + cmpq $-1, dep_mutex-cond_lock(%rdi) + movl $LLL_PRIVATE, %eax + movl $LLL_SHARED, %esi + cmovne %eax, %esi + /* The call preserves %rdx. */ + callq __lll_unlock_wake +#if cond_lock != 0 + subq $cond_lock, %rdi +#endif + jmp 4b + + /* Locking in loop failed. */ +5: +#if cond_lock != 0 + addq $cond_lock, %rdi +#endif + cmpq $-1, dep_mutex-cond_lock(%rdi) + movl $LLL_PRIVATE, %eax + movl $LLL_SHARED, %esi + cmovne %eax, %esi + callq __lll_lock_wait +#if cond_lock != 0 + subq $cond_lock, %rdi +#endif + jmp 6b + + /* Unlock after loop requires wakeup. */ +10: +#if cond_lock != 0 + addq $cond_lock, %rdi +#endif + cmpq $-1, dep_mutex-cond_lock(%rdi) + movl $LLL_PRIVATE, %eax + movl $LLL_SHARED, %esi + cmovne %eax, %esi + callq __lll_unlock_wake + jmp 11b + + /* The initial unlocking of the mutex failed. */ +12: movq %rax, %r10 + movq 8(%rsp), %rdi + LOCK +#if cond_lock == 0 + decl (%rdi) +#else + decl cond_lock(%rdi) +#endif + je 13f + +#if cond_lock != 0 + addq $cond_lock, %rdi +#endif + cmpq $-1, dep_mutex-cond_lock(%rdi) + movl $LLL_PRIVATE, %eax + movl $LLL_SHARED, %esi + cmovne %eax, %esi + callq __lll_unlock_wake + +13: movq %r10, %rax + jmp 14b + .size __pthread_cond_wait, .-__pthread_cond_wait +weak_alias(__pthread_cond_wait, pthread_cond_wait) + + + .align 16 + .type __condvar_cleanup1, @function + .globl __condvar_cleanup1 + .hidden __condvar_cleanup1 +__condvar_cleanup1: + /* Stack frame: + + rsp + 32 + +--------------------------+ + rsp + 24 | unused | + +--------------------------+ + rsp + 16 | mutex pointer | + +--------------------------+ + rsp + 8 | condvar pointer | + +--------------------------+ + rsp + 4 | old broadcast_seq value | + +--------------------------+ + rsp + 0 | old cancellation mode | + +--------------------------+ + */ + + movq %rax, 24(%rsp) + + /* Get internal lock. */ + movq 8(%rsp), %rdi + movl $1, %esi + xorl %eax, %eax + LOCK +#if cond_lock == 0 + cmpxchgl %esi, (%rdi) +#else + cmpxchgl %esi, cond_lock(%rdi) +#endif + jz 1f + +#if cond_lock != 0 + addq $cond_lock, %rdi +#endif + cmpq $-1, dep_mutex-cond_lock(%rdi) + movl $LLL_PRIVATE, %eax + movl $LLL_SHARED, %esi + cmovne %eax, %esi + callq __lll_lock_wait +#if cond_lock != 0 + subq $cond_lock, %rdi +#endif + +1: movl broadcast_seq(%rdi), %edx + cmpl 4(%rsp), %edx + jne 3f + + /* We increment the wakeup_seq counter only if it is lower than + total_seq. If this is not the case the thread was woken and + then canceled. In this case we ignore the signal. */ + movq total_seq(%rdi), %rax + cmpq wakeup_seq(%rdi), %rax + jbe 6f + incq wakeup_seq(%rdi) + incl cond_futex(%rdi) +6: incq woken_seq(%rdi) + +3: subl $(1 << nwaiters_shift), cond_nwaiters(%rdi) + + /* Wake up a thread which wants to destroy the condvar object. */ + xorl %ecx, %ecx + cmpq $0xffffffffffffffff, total_seq(%rdi) + jne 4f + movl cond_nwaiters(%rdi), %eax + andl $~((1 << nwaiters_shift) - 1), %eax + jne 4f + + cmpq $-1, dep_mutex(%rdi) + leaq cond_nwaiters(%rdi), %rdi + movl $1, %edx +#ifdef __ASSUME_PRIVATE_FUTEX + movl $FUTEX_WAKE, %eax + movl $(FUTEX_WAKE|FUTEX_PRIVATE_FLAG), %esi + cmove %eax, %esi +#else + movl $0, %eax + movl %fs:PRIVATE_FUTEX, %esi + cmove %eax, %esi + orl $FUTEX_WAKE, %esi +#endif + movl $SYS_futex, %eax + syscall + subq $cond_nwaiters, %rdi + movl $1, %ecx + +4: LOCK +#if cond_lock == 0 + decl (%rdi) +#else + decl cond_lock(%rdi) +#endif + je 2f +#if cond_lock != 0 + addq $cond_lock, %rdi +#endif + cmpq $-1, dep_mutex-cond_lock(%rdi) + movl $LLL_PRIVATE, %eax + movl $LLL_SHARED, %esi + cmovne %eax, %esi + /* The call preserves %rcx. */ + callq __lll_unlock_wake + + /* Wake up all waiters to make sure no signal gets lost. */ +2: testl %ecx, %ecx + jnz 5f + addq $cond_futex, %rdi + cmpq $-1, dep_mutex-cond_futex(%rdi) + movl $0x7fffffff, %edx +#ifdef __ASSUME_PRIVATE_FUTEX + movl $FUTEX_WAKE, %eax + movl $(FUTEX_WAKE|FUTEX_PRIVATE_FLAG), %esi + cmove %eax, %esi +#else + movl $0, %eax + movl %fs:PRIVATE_FUTEX, %esi + cmove %eax, %esi + orl $FUTEX_WAKE, %esi +#endif + movl $SYS_futex, %eax + syscall + +5: movq 16(%rsp), %rdi + callq __pthread_mutex_cond_lock + + movq 24(%rsp), %rdi +.LcallUR: + call _Unwind_Resume@PLT + hlt +.LENDCODE: + cfi_endproc + .size __condvar_cleanup1, .-__condvar_cleanup1 + + + .section .gcc_except_table,"a",@progbits +.LexceptSTART: + .byte DW_EH_PE_omit # @LPStart format + .byte DW_EH_PE_omit # @TType format + .byte DW_EH_PE_uleb128 # call-site format + .uleb128 .Lcstend-.Lcstbegin +.Lcstbegin: + .uleb128 .LcleanupSTART-.LSTARTCODE + .uleb128 .LcleanupEND-.LcleanupSTART + .uleb128 __condvar_cleanup1-.LSTARTCODE + .uleb128 0 + .uleb128 .LcallUR-.LSTARTCODE + .uleb128 .LENDCODE-.LcallUR + .uleb128 0 + .uleb128 0 +.Lcstend: + + +#ifdef SHARED + .hidden DW.ref.__gcc_personality_v0 + .weak DW.ref.__gcc_personality_v0 + .section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits + .align 8 + .type DW.ref.__gcc_personality_v0, @object + .size DW.ref.__gcc_personality_v0, 8 +DW.ref.__gcc_personality_v0: + .quad __gcc_personality_v0 +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_once.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_once.S new file mode 100644 index 00000000..9013d8fa --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_once.S @@ -0,0 +1,190 @@ +/* Copyright (C) 2002, 2003, 2005, 2007, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + + + .comm __fork_generation, 4, 4 + + .text + + + .globl __pthread_once + .type __pthread_once,@function + .protected __pthread_once + .align 16 +__pthread_once: +.LSTARTCODE: + cfi_startproc + testl $2, (%rdi) + jz 1f + xorl %eax, %eax + retq + + /* Preserve the function pointer. */ +1: pushq %rsi + cfi_adjust_cfa_offset(8) + xorq %r10, %r10 + + /* Not yet initialized or initialization in progress. + Get the fork generation counter now. */ +6: movl (%rdi), %eax + +5: movl %eax, %edx + + testl $2, %eax + jnz 4f + + andl $3, %edx + orl __fork_generation(%rip), %edx + orl $1, %edx + + LOCK + cmpxchgl %edx, (%rdi) + jnz 5b + + /* Check whether another thread already runs the initializer. */ + testl $1, %eax + jz 3f /* No -> do it. */ + + /* Check whether the initializer execution was interrupted + by a fork. */ + xorl %edx, %eax + testl $0xfffffffc, %eax + jnz 3f /* Different for generation -> run initializer. */ + + /* Somebody else got here first. Wait. */ +#ifdef __ASSUME_PRIVATE_FUTEX + movl $FUTEX_WAIT|FUTEX_PRIVATE_FLAG, %esi +#else +# if FUTEX_WAIT == 0 + movl %fs:PRIVATE_FUTEX, %esi +# else + movl $FUTEX_WAIT, %esi + orl %fs:PRIVATE_FUTEX, %esi +# endif +#endif + movl $SYS_futex, %eax + syscall + jmp 6b + + /* Preserve the pointer to the control variable. */ +3: pushq %rdi + cfi_adjust_cfa_offset(8) + pushq %rdi + cfi_adjust_cfa_offset(8) + +.LcleanupSTART: + callq *16(%rsp) +.LcleanupEND: + + /* Get the control variable address back. */ + popq %rdi + cfi_adjust_cfa_offset(-8) + + /* Sucessful run of the initializer. Signal that we are done. */ + LOCK + incl (%rdi) + + addq $8, %rsp + cfi_adjust_cfa_offset(-8) + + /* Wake up all other threads. */ + movl $0x7fffffff, %edx +#ifdef __ASSUME_PRIVATE_FUTEX + movl $FUTEX_WAKE|FUTEX_PRIVATE_FLAG, %esi +#else + movl $FUTEX_WAKE, %esi + orl %fs:PRIVATE_FUTEX, %esi +#endif + movl $SYS_futex, %eax + syscall + +4: addq $8, %rsp + cfi_adjust_cfa_offset(-8) + xorl %eax, %eax + retq + .size __pthread_once,.-__pthread_once + + + .globl __pthread_once_internal +__pthread_once_internal = __pthread_once + + .globl pthread_once +pthread_once = __pthread_once + + + .type clear_once_control,@function + .align 16 +clear_once_control: + cfi_adjust_cfa_offset(3 * 8) + movq (%rsp), %rdi + movq %rax, %r8 + movl $0, (%rdi) + + movl $0x7fffffff, %edx +#ifdef __ASSUME_PRIVATE_FUTEX + movl $FUTEX_WAKE|FUTEX_PRIVATE_FLAG, %esi +#else + movl $FUTEX_WAKE, %esi + orl %fs:PRIVATE_FUTEX, %esi +#endif + movl $SYS_futex, %eax + syscall + + movq %r8, %rdi +.LcallUR: + call _Unwind_Resume@PLT + hlt +.LENDCODE: + cfi_endproc + .size clear_once_control,.-clear_once_control + + + .section .gcc_except_table,"a",@progbits +.LexceptSTART: + .byte DW_EH_PE_omit # @LPStart format + .byte DW_EH_PE_omit # @TType format + .byte DW_EH_PE_uleb128 # call-site format + .uleb128 .Lcstend-.Lcstbegin +.Lcstbegin: + .uleb128 .LcleanupSTART-.LSTARTCODE + .uleb128 .LcleanupEND-.LcleanupSTART + .uleb128 clear_once_control-.LSTARTCODE + .uleb128 0 + .uleb128 .LcallUR-.LSTARTCODE + .uleb128 .LENDCODE-.LcallUR + .uleb128 0 + .uleb128 0 +.Lcstend: + + +#ifdef SHARED + .hidden DW.ref.__gcc_personality_v0 + .weak DW.ref.__gcc_personality_v0 + .section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits + .align 8 + .type DW.ref.__gcc_personality_v0, @object + .size DW.ref.__gcc_personality_v0, 8 +DW.ref.__gcc_personality_v0: + .quad __gcc_personality_v0 +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_rdlock.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_rdlock.S new file mode 100644 index 00000000..82badb1e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_rdlock.S @@ -0,0 +1,180 @@ +/* Copyright (C) 2002, 2003, 2005, 2007, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include + + + .text + + .globl __pthread_rwlock_rdlock + .type __pthread_rwlock_rdlock,@function + .protected __pthread_rwlock_rdlock + .align 16 +__pthread_rwlock_rdlock: + cfi_startproc + xorq %r10, %r10 + + /* Get the lock. */ + movl $1, %esi + xorl %eax, %eax + LOCK +#if MUTEX == 0 + cmpxchgl %esi, (%rdi) +#else + cmpxchgl %esi, MUTEX(%rdi) +#endif + jnz 1f + +2: movl WRITER(%rdi), %eax + testl %eax, %eax + jne 14f + cmpl $0, WRITERS_QUEUED(%rdi) + je 5f + cmpl $0, FLAGS(%rdi) + je 5f + +3: incl READERS_QUEUED(%rdi) + je 4f + + movl READERS_WAKEUP(%rdi), %edx + + LOCK +#if MUTEX == 0 + decl (%rdi) +#else + decl MUTEX(%rdi) +#endif + jne 10f + +11: +#ifdef __ASSUME_PRIVATE_FUTEX + movl $FUTEX_PRIVATE_FLAG|FUTEX_WAIT, %esi + xorl PSHARED(%rdi), %esi +#else +# if FUTEX_WAIT == 0 + movl PSHARED(%rdi), %esi +# else + movl $FUTEX_WAIT, %esi + orl PSHARED(%rdi), %esi +# endif + xorl %fs:PRIVATE_FUTEX, %esi +#endif + addq $READERS_WAKEUP, %rdi + movl $SYS_futex, %eax + syscall + + subq $READERS_WAKEUP, %rdi + + /* Reget the lock. */ + movl $1, %esi + xorl %eax, %eax + LOCK +#if MUTEX == 0 + cmpxchgl %esi, (%rdi) +#else + cmpxchgl %esi, MUTEX(%rdi) +#endif + jnz 12f + +13: decl READERS_QUEUED(%rdi) + jmp 2b + +5: xorl %edx, %edx + incl NR_READERS(%rdi) + je 8f +9: LOCK +#if MUTEX == 0 + decl (%rdi) +#else + decl MUTEX(%rdi) +#endif + jne 6f +7: + + movq %rdx, %rax + retq + +1: movl PSHARED(%rdi), %esi +#if MUTEX != 0 + addq $MUTEX, %rdi +#endif + callq __lll_lock_wait +#if MUTEX != 0 + subq $MUTEX, %rdi +#endif + jmp 2b + +14: cmpl %fs:TID, %eax + jne 3b + /* Deadlock detected. */ + movl $EDEADLK, %edx + jmp 9b + +6: movl PSHARED(%rdi), %esi +#if MUTEX != 0 + addq $MUTEX, %rdi +#endif + callq __lll_unlock_wake +#if MUTEX != 0 + subq $MUTEX, %rdi +#endif + jmp 7b + + /* Overflow. */ +8: decl NR_READERS(%rdi) + movl $EAGAIN, %edx + jmp 9b + + /* Overflow. */ +4: decl READERS_QUEUED(%rdi) + movl $EAGAIN, %edx + jmp 9b + +10: movl PSHARED(%rdi), %esi +#if MUTEX != 0 + addq $MUTEX, %rdi +#endif + callq __lll_unlock_wake +#if MUTEX != 0 + subq $MUTEX, %rdi +#endif + jmp 11b + +12: movl PSHARED(%rdi), %esi +#if MUTEX == 0 + addq $MUTEX, %rdi +#endif + callq __lll_lock_wait +#if MUTEX != 0 + subq $MUTEX, %rdi +#endif + jmp 13b + cfi_endproc + .size __pthread_rwlock_rdlock,.-__pthread_rwlock_rdlock + + .globl pthread_rwlock_rdlock +pthread_rwlock_rdlock = __pthread_rwlock_rdlock + + .globl __pthread_rwlock_rdlock_internal +__pthread_rwlock_rdlock_internal = __pthread_rwlock_rdlock diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedrdlock.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedrdlock.S new file mode 100644 index 00000000..3629ffbe --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedrdlock.S @@ -0,0 +1,276 @@ +/* Copyright (C) 2002-2005, 2007, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include + + +/* For the calculation see asm/vsyscall.h. */ +#define VSYSCALL_ADDR_vgettimeofday 0xffffffffff600000 + + .text + + .globl pthread_rwlock_timedrdlock + .type pthread_rwlock_timedrdlock,@function + .align 16 +pthread_rwlock_timedrdlock: + cfi_startproc + pushq %r12 + cfi_adjust_cfa_offset(8) + cfi_rel_offset(%r12, 0) + pushq %r13 + cfi_adjust_cfa_offset(8) + cfi_rel_offset(%r13, 0) +#ifdef __ASSUME_FUTEX_CLOCK_REALTIME +# define VALREG %edx +#else + pushq %r14 + cfi_adjust_cfa_offset(8) + cfi_rel_offset(%r14, 0) + + subq $16, %rsp + cfi_adjust_cfa_offset(16) +# define VALREG %r14d +#endif + + movq %rdi, %r12 + movq %rsi, %r13 + + /* Get the lock. */ + movl $1, %esi + xorl %eax, %eax + LOCK +#if MUTEX == 0 + cmpxchgl %esi, (%rdi) +#else + cmpxchgl %esi, MUTEX(%rdi) +#endif + jnz 1f + +2: movl WRITER(%r12), %eax + testl %eax, %eax + jne 14f + cmpl $0, WRITERS_QUEUED(%r12) + je 5f + cmpl $0, FLAGS(%r12) + je 5f + + /* Check the value of the timeout parameter. */ +3: cmpq $1000000000, 8(%r13) + jae 19f + + incl READERS_QUEUED(%r12) + je 4f + + movl READERS_WAKEUP(%r12), VALREG + + /* Unlock. */ + LOCK +#if MUTEX == 0 + decl (%r12) +#else + decl MUTEX(%r12) +#endif + jne 10f + +11: +#ifndef __ASSUME_FUTEX_CLOCK_REALTIME +# ifdef __PIC__ + cmpl $0, __have_futex_clock_realtime(%rip) +# else + cmpl $0, __have_futex_clock_realtime +# endif + je .Lreltmo +#endif + + movl $FUTEX_PRIVATE_FLAG|FUTEX_WAIT_BITSET|FUTEX_CLOCK_REALTIME, %esi + xorl PSHARED(%r12), %esi + movq %r13, %r10 + movl $0xffffffff, %r9d +#ifndef __ASSUME_FUTEX_CLOCK_REALTIME + movl %r14d, %edx +#endif +21: leaq READERS_WAKEUP(%r12), %rdi + movl $SYS_futex, %eax + syscall + movq %rax, %rdx + +#ifndef __ASSUME_FUTEX_CLOCK_REALTIME + .subsection 2 +.Lreltmo: + /* Get current time. */ + movq %rsp, %rdi + xorl %esi, %esi + movq $VSYSCALL_ADDR_vgettimeofday, %rax + callq *%rax + + /* Compute relative timeout. */ + movq 8(%rsp), %rax + movl $1000, %edi + mul %rdi /* Milli seconds to nano seconds. */ + movq (%r13), %rcx + movq 8(%r13), %rdi + subq (%rsp), %rcx + subq %rax, %rdi + jns 15f + addq $1000000000, %rdi + decq %rcx +15: testq %rcx, %rcx + js 16f /* Time is already up. */ + + /* Futex call. */ + movq %rcx, (%rsp) /* Store relative timeout. */ + movq %rdi, 8(%rsp) + +# ifdef __ASSUME_PRIVATE_FUTEX + movl $FUTEX_PRIVATE_FLAG|FUTEX_WAIT, %esi + xorl PSHARED(%r12), %esi +# else +# if FUTEX_WAIT == 0 + movl PSHARED(%r12), %esi +# else + movl $FUTEX_WAIT, %esi + orl PSHARED(%r12), %esi +# endif + xorl %fs:PRIVATE_FUTEX, %esi +# endif + movq %rsp, %r10 + movl %r14d, %edx + + jmp 21b + .previous +#endif + +17: /* Reget the lock. */ + movl $1, %esi + xorl %eax, %eax + LOCK +#if MUTEX == 0 + cmpxchgl %esi, (%r12) +#else + cmpxchgl %esi, MUTEX(%r12) +#endif + jnz 12f + +13: decl READERS_QUEUED(%r12) + cmpq $-ETIMEDOUT, %rdx + jne 2b + +18: movl $ETIMEDOUT, %edx + jmp 9f + + +5: xorl %edx, %edx + incl NR_READERS(%r12) + je 8f +9: LOCK +#if MUTEX == 0 + decl (%r12) +#else + decl MUTEX(%r12) +#endif + jne 6f + +7: movq %rdx, %rax + +#ifndef __ASSUME_FUTEX_CLOCK_REALTIME + addq $16, %rsp + cfi_adjust_cfa_offset(-16) + popq %r14 + cfi_adjust_cfa_offset(-8) + cfi_restore(%r14) +#endif + popq %r13 + cfi_adjust_cfa_offset(-8) + cfi_restore(%r13) + popq %r12 + cfi_adjust_cfa_offset(-8) + cfi_restore(%r12) + retq + +#ifdef __ASSUME_PRIVATE_FUTEX + cfi_adjust_cfa_offset(16) + cfi_rel_offset(%r12, 8) + cfi_rel_offset(%r13, 0) +#else + cfi_adjust_cfa_offset(40) + cfi_offset(%r12, -16) + cfi_offset(%r13, -24) + cfi_offset(%r14, -32) +#endif +1: movl PSHARED(%rdi), %esi +#if MUTEX != 0 + addq $MUTEX, %rdi +#endif + callq __lll_lock_wait + jmp 2b + +14: cmpl %fs:TID, %eax + jne 3b + movl $EDEADLK, %edx + jmp 9b + +6: movl PSHARED(%r12), %esi +#if MUTEX == 0 + movq %r12, %rdi +#else + leal MUTEX(%r12), %rdi +#endif + callq __lll_unlock_wake + jmp 7b + + /* Overflow. */ +8: decl NR_READERS(%r12) + movl $EAGAIN, %edx + jmp 9b + + /* Overflow. */ +4: decl READERS_QUEUED(%r12) + movl $EAGAIN, %edx + jmp 9b + +10: movl PSHARED(%r12), %esi +#if MUTEX == 0 + movq %r12, %rdi +#else + leaq MUTEX(%r12), %rdi +#endif + callq __lll_unlock_wake + jmp 11b + +12: movl PSHARED(%r12), %esi +#if MUTEX == 0 + movq %r12, %rdi +#else + leaq MUTEX(%r12), %rdi +#endif + callq __lll_lock_wait + jmp 13b + +16: movq $-ETIMEDOUT, %rdx + jmp 17b + +19: movl $EINVAL, %edx + jmp 9b + cfi_endproc + .size pthread_rwlock_timedrdlock,.-pthread_rwlock_timedrdlock diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedwrlock.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedwrlock.S new file mode 100644 index 00000000..23e1ee15 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_timedwrlock.S @@ -0,0 +1,268 @@ +/* Copyright (C) 2002, 2003, 2005, 2007, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include + + +/* For the calculation see asm/vsyscall.h. */ +#define VSYSCALL_ADDR_vgettimeofday 0xffffffffff600000 + + .text + + .globl pthread_rwlock_timedwrlock + .type pthread_rwlock_timedwrlock,@function + .align 16 +pthread_rwlock_timedwrlock: + cfi_startproc + pushq %r12 + cfi_adjust_cfa_offset(8) + cfi_rel_offset(%r12, 0) + pushq %r13 + cfi_adjust_cfa_offset(8) + cfi_rel_offset(%r13, 0) +#ifdef __ASSUME_FUTEX_CLOCK_REALTIME +# define VALREG %edx +#else + pushq %r14 + cfi_adjust_cfa_offset(8) + cfi_rel_offset(%r14, 0) + + subq $16, %rsp + cfi_adjust_cfa_offset(16) +# define VALREG %r14d +#endif + + movq %rdi, %r12 + movq %rsi, %r13 + + /* Get the lock. */ + movl $1, %esi + xorl %eax, %eax + LOCK +#if MUTEX == 0 + cmpxchgl %esi, (%rdi) +#else + cmpxchgl %esi, MUTEX(%rdi) +#endif + jnz 1f + +2: movl WRITER(%r12), %eax + testl %eax, %eax + jne 14f + cmpl $0, NR_READERS(%r12) + je 5f + + /* Check the value of the timeout parameter. */ +3: cmpq $1000000000, 8(%r13) + jae 19f + + incl WRITERS_QUEUED(%r12) + je 4f + + movl WRITERS_WAKEUP(%r12), VALREG + + LOCK +#if MUTEX == 0 + decl (%r12) +#else + decl MUTEX(%r12) +#endif + jne 10f + +11: +#ifndef __ASSUME_FUTEX_CLOCK_REALTIME +# ifdef __PIC__ + cmpl $0, __have_futex_clock_realtime(%rip) +# else + cmpl $0, __have_futex_clock_realtime +# endif + je .Lreltmo +#endif + + movl $FUTEX_PRIVATE_FLAG|FUTEX_WAIT_BITSET|FUTEX_CLOCK_REALTIME, %esi + xorl PSHARED(%r12), %esi + movq %r13, %r10 + movl $0xffffffff, %r9d +#ifndef __ASSUME_FUTEX_CLOCK_REALTIME + movl %r14d, %edx +#endif +21: leaq WRITERS_WAKEUP(%r12), %rdi + movl $SYS_futex, %eax + syscall + movq %rax, %rdx + +#ifndef __ASSUME_FUTEX_CLOCK_REALTIME + .subsection 2 +.Lreltmo: + /* Get current time. */ + movq %rsp, %rdi + xorl %esi, %esi + movq $VSYSCALL_ADDR_vgettimeofday, %rax + callq *%rax + + /* Compute relative timeout. */ + movq 8(%rsp), %rax + movl $1000, %edi + mul %rdi /* Milli seconds to nano seconds. */ + movq (%r13), %rcx + movq 8(%r13), %rdi + subq (%rsp), %rcx + subq %rax, %rdi + jns 15f + addq $1000000000, %rdi + decq %rcx +15: testq %rcx, %rcx + js 16f /* Time is already up. */ + + /* Futex call. */ + movq %rcx, (%rsp) /* Store relative timeout. */ + movq %rdi, 8(%rsp) + +# ifdef __ASSUME_PRIVATE_FUTEX + movl $FUTEX_PRIVATE_FLAG|FUTEX_WAIT, %esi + xorl PSHARED(%r12), %esi +# else +# if FUTEX_WAIT == 0 + movl PSHARED(%r12), %esi +# else + movl $FUTEX_WAIT, %esi + orl PSHARED(%r12), %esi +# endif + xorl %fs:PRIVATE_FUTEX, %esi +# endif + movq %rsp, %r10 + movl %r14d, %edx + + jmp 21b + .previous +#endif + +17: /* Reget the lock. */ + movl $1, %esi + xorl %eax, %eax + LOCK +#if MUTEX == 0 + cmpxchgl %esi, (%r12) +#else + cmpxchgl %esi, MUTEX(%r12) +#endif + jnz 12f + +13: decl WRITERS_QUEUED(%r12) + cmpq $-ETIMEDOUT, %rdx + jne 2b + +18: movl $ETIMEDOUT, %edx + jmp 9f + + +5: xorl %edx, %edx + movl %fs:TID, %eax + movl %eax, WRITER(%r12) +9: LOCK +#if MUTEX == 0 + decl (%r12) +#else + decl MUTEX(%r12) +#endif + jne 6f + +7: movq %rdx, %rax + +#ifndef __ASSUME_PRIVATE_FUTEX + addq $16, %rsp + cfi_adjust_cfa_offset(-16) + popq %r14 + cfi_adjust_cfa_offset(-8) + cfi_restore(%r14) +#endif + popq %r13 + cfi_adjust_cfa_offset(-8) + cfi_restore(%r13) + popq %r12 + cfi_adjust_cfa_offset(-8) + cfi_restore(%r12) + retq + +#ifdef __ASSUME_PRIVATE_FUTEX + cfi_adjust_cfa_offset(16) + cfi_rel_offset(%r12, 8) + cfi_rel_offset(%r13, 0) +#else + cfi_adjust_cfa_offset(40) + cfi_offset(%r12, -16) + cfi_offset(%r13, -24) + cfi_offset(%r14, -32) +#endif +1: movl PSHARED(%rdi), %esi +#if MUTEX != 0 + addq $MUTEX, %rdi +#endif + callq __lll_lock_wait + jmp 2b + +14: cmpl %fs:TID, %eax + jne 3b +20: movl $EDEADLK, %edx + jmp 9b + +6: movl PSHARED(%r12), %esi +#if MUTEX == 0 + movq %r12, %rdi +#else + leal MUTEX(%r12), %rdi +#endif + callq __lll_unlock_wake + jmp 7b + + /* Overflow. */ +4: decl WRITERS_QUEUED(%r12) + movl $EAGAIN, %edx + jmp 9b + +10: movl PSHARED(%r12), %esi +#if MUTEX == 0 + movq %r12, %rdi +#else + leaq MUTEX(%r12), %rdi +#endif + callq __lll_unlock_wake + jmp 11b + +12: movl PSHARED(%r12), %esi +#if MUTEX == 0 + movq %r12, %rdi +#else + leaq MUTEX(%r12), %rdi +#endif + callq __lll_lock_wait + jmp 13b + +16: movq $-ETIMEDOUT, %rdx + jmp 17b + +19: movl $EINVAL, %edx + jmp 9b + cfi_endproc + .size pthread_rwlock_timedwrlock,.-pthread_rwlock_timedwrlock diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_unlock.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_unlock.S new file mode 100644 index 00000000..e34c42ea --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_unlock.S @@ -0,0 +1,131 @@ +/* Copyright (C) 2002, 2003, 2005, 2007, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + + + .text + + .globl __pthread_rwlock_unlock + .type __pthread_rwlock_unlock,@function + .protected __pthread_rwlock_unlock + .align 16 +__pthread_rwlock_unlock: + cfi_startproc + /* Get the lock. */ + movl $1, %esi + xorl %eax, %eax + LOCK +#if MUTEX == 0 + cmpxchgl %esi, (%rdi) +#else + cmpxchgl %esi, MUTEX(%rdi) +#endif + jnz 1f + +2: cmpl $0, WRITER(%rdi) + jne 5f + decl NR_READERS(%rdi) + jnz 6f + +5: movl $0, WRITER(%rdi) + + movl $1, %edx + leaq WRITERS_WAKEUP(%rdi), %r10 + cmpl $0, WRITERS_QUEUED(%rdi) + jne 0f + + /* If also no readers waiting nothing to do. */ + cmpl $0, READERS_QUEUED(%rdi) + je 6f + + movl $0x7fffffff, %edx + leaq READERS_WAKEUP(%rdi), %r10 + +0: incl (%r10) + LOCK +#if MUTEX == 0 + decl (%rdi) +#else + decl MUTEX(%rdi) +#endif + jne 7f + +8: +#ifdef __ASSUME_PRIVATE_FUTEX + movl $FUTEX_PRIVATE_FLAG|FUTEX_WAKE, %esi + xorl PSHARED(%rdi), %esi +#else + movl $FUTEX_WAKE, %esi + orl PSHARED(%rdi), %esi + xorl %fs:PRIVATE_FUTEX, %esi +#endif + movl $SYS_futex, %eax + movq %r10, %rdi + syscall + + xorl %eax, %eax + retq + + .align 16 +6: LOCK +#if MUTEX == 0 + decl (%rdi) +#else + decl MUTEX(%rdi) +#endif + jne 3f + +4: xorl %eax, %eax + retq + +1: movl PSHARED(%rdi), %esi +#if MUTEX != 0 + addq $MUTEX, %rdi +#endif + callq __lll_lock_wait +#if MUTEX != 0 + subq $MUTEX, %rdi +#endif + jmp 2b + +3: movl PSHARED(%rdi), %esi +#if MUTEX != 0 + addq $MUTEX, %rdi +#endif + callq __lll_unlock_wake + jmp 4b + +7: movl PSHARED(%rdi), %esi +#if MUTEX != 0 + addq $MUTEX, %rdi +#endif + callq __lll_unlock_wake + jmp 8b + cfi_endproc + .size __pthread_rwlock_unlock,.-__pthread_rwlock_unlock + + .globl pthread_rwlock_unlock +pthread_rwlock_unlock = __pthread_rwlock_unlock + + .globl __pthread_rwlock_unlock_internal +__pthread_rwlock_unlock_internal = __pthread_rwlock_unlock diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_wrlock.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_wrlock.S new file mode 100644 index 00000000..c626d9e1 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_rwlock_wrlock.S @@ -0,0 +1,168 @@ +/* Copyright (C) 2002, 2003, 2005, 2007, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include + + + .text + + .globl __pthread_rwlock_wrlock + .type __pthread_rwlock_wrlock,@function + .protected __pthread_rwlock_wrlock + .align 16 +__pthread_rwlock_wrlock: + cfi_startproc + xorq %r10, %r10 + + /* Get the lock. */ + movl $1, %esi + xorl %eax, %eax + LOCK +#if MUTEX == 0 + cmpxchgl %esi, (%rdi) +#else + cmpxchgl %esi, MUTEX(%rdi) +#endif + jnz 1f + +2: movl WRITER(%rdi), %eax + testl %eax, %eax + jne 14f + cmpl $0, NR_READERS(%rdi) + je 5f + +3: incl WRITERS_QUEUED(%rdi) + je 4f + + movl WRITERS_WAKEUP(%rdi), %edx + + LOCK +#if MUTEX == 0 + decl (%rdi) +#else + decl MUTEX(%rdi) +#endif + jne 10f + +11: +#ifdef __ASSUME_PRIVATE_FUTEX + movl $FUTEX_PRIVATE_FLAG|FUTEX_WAIT, %esi + xorl PSHARED(%rdi), %esi +#else +# if FUTEX_WAIT == 0 + movl PSHARED(%rdi), %esi +# else + movl $FUTEX_WAIT, %esi + orl PSHARED(%rdi), %esi +# endif + xorl %fs:PRIVATE_FUTEX, %esi +#endif + addq $WRITERS_WAKEUP, %rdi + movl $SYS_futex, %eax + syscall + + subq $WRITERS_WAKEUP, %rdi + + /* Reget the lock. */ + movl $1, %esi + xorl %eax, %eax + LOCK +#if MUTEX == 0 + cmpxchgl %esi, (%rdi) +#else + cmpxchgl %esi, MUTEX(%rdi) +#endif + jnz 12f + +13: decl WRITERS_QUEUED(%rdi) + jmp 2b + +5: xorl %edx, %edx + movl %fs:TID, %eax + movl %eax, WRITER(%rdi) +9: LOCK +#if MUTEX == 0 + decl (%rdi) +#else + decl MUTEX(%rdi) +#endif + jne 6f +7: + + movq %rdx, %rax + retq + +1: movl PSHARED(%rdi), %esi +#if MUTEX != 0 + addq $MUTEX, %rdi +#endif + callq __lll_lock_wait +#if MUTEX != 0 + subq $MUTEX, %rdi +#endif + jmp 2b + +14: cmpl %fs:TID, %eax + jne 3b + movl $EDEADLK, %edx + jmp 9b + +6: movl PSHARED(%rdi), %esi +#if MUTEX != 0 + addq $MUTEX, %rdi +#endif + callq __lll_unlock_wake + jmp 7b + +4: decl WRITERS_QUEUED(%rdi) + movl $EAGAIN, %edx + jmp 9b + +10: movl PSHARED(%rdi), %esi +#if MUTEX != 0 + addq $MUTEX, %rdi +#endif + callq __lll_unlock_wake +#if MUTEX != 0 + subq $MUTEX, %rdi +#endif + jmp 11b + +12: movl PSHARED(%rdi), %esi +#if MUTEX != 0 + addq $MUTEX, %rdi +#endif + callq __lll_lock_wait +#if MUTEX != 0 + subq $MUTEX, %rdi +#endif + jmp 13b + cfi_endproc + .size __pthread_rwlock_wrlock,.-__pthread_rwlock_wrlock + + .globl pthread_rwlock_wrlock +pthread_rwlock_wrlock = __pthread_rwlock_wrlock + + .globl __pthread_rwlock_wrlock_internal +__pthread_rwlock_wrlock_internal = __pthread_rwlock_wrlock diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_setaffinity.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_setaffinity.c new file mode 100644 index 00000000..e60113a7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_setaffinity.c @@ -0,0 +1,14 @@ +#include + +#define RESET_VGETCPU_CACHE() \ + do { \ + __asm__ __volatile__ ("movl %0, %%fs:%P1\n\t" \ + "movl %0, %%fs:%P2" \ + : \ + : "ir" (0), "i" (offsetof (struct pthread, \ + header.vgetcpu_cache[0])), \ + "i" (offsetof (struct pthread, \ + header.vgetcpu_cache[1]))); \ + } while (0) + +#include "../pthread_setaffinity.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_spin_init.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_spin_init.c new file mode 100644 index 00000000..483de8ca --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_spin_init.c @@ -0,0 +1 @@ +#include diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_spin_unlock.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_spin_unlock.S new file mode 100644 index 00000000..e8e2ba26 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/pthread_spin_unlock.S @@ -0,0 +1 @@ +#include diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/sem_post.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/sem_post.S new file mode 100644 index 00000000..7af6524f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/sem_post.S @@ -0,0 +1,89 @@ +/* Copyright (C) 2002, 2003, 2005, 2007, 2008 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + + + .text + + .globl sem_post + .type sem_post,@function + .align 16 +sem_post: +#if VALUE == 0 + movl (%rdi), %eax +#else + movl VALUE(%rdi), %eax +#endif +0: cmpl $SEM_VALUE_MAX, %eax + je 3f + leal 1(%rax), %esi + LOCK +#if VALUE == 0 + cmpxchgl %esi, (%rdi) +#else + cmpxchgl %esi, VALUE(%rdi) +#endif + jnz 0b + + cmpq $0, NWAITERS(%rdi) + je 2f + + movl $SYS_futex, %eax + movl $FUTEX_WAKE, %esi + orl PRIVATE(%rdi), %esi + movl $1, %edx + syscall + + testq %rax, %rax + js 1f + +2: xorl %eax, %eax + retq + +1: +#if USE___THREAD + movl $EINVAL, %eax +#else + callq __errno_location@plt + movl $EINVAL, %edx +#endif + jmp 4f + +3: +#if USE___THREAD + movl $EOVERFLOW, %eax +#else + callq __errno_location@plt + movl $EOVERFLOW, %edx +#endif + +4: +#if USE___THREAD + movq errno@gottpoff(%rip), %rdx + movl %eax, %fs:(%rdx) +#else + movl %edx, (%rax) +#endif + orl $-1, %eax + retq + .size sem_post,.-sem_post diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S new file mode 100644 index 00000000..704a2223 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S @@ -0,0 +1,379 @@ +/* Copyright (C) 2002, 2003, 2005, 2007, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include + + +/* For the calculation see asm/vsyscall.h. */ +#define VSYSCALL_ADDR_vgettimeofday 0xffffffffff600000 + + .text + + .globl sem_timedwait + .type sem_timedwait,@function + .align 16 +sem_timedwait: +.LSTARTCODE: + cfi_startproc +#if VALUE == 0 + movl (%rdi), %eax +#else + movl VALUE(%rdi), %eax +#endif +2: testl %eax, %eax + je 1f + + leaq -1(%rax), %rdx + LOCK +#if VALUE == 0 + cmpxchgl %edx, (%rdi) +#else + cmpxchgl %edx, VALUE(%rdi) +#endif + jne 2b + + xorl %eax, %eax + retq + + /* Check whether the timeout value is valid. */ +1: cmpq $1000000000, 8(%rsi) + jae 6f + +#ifndef __ASSUME_FUTEX_CLOCK_REALTIME +# ifdef __PIC__ + cmpl $0, __have_futex_clock_realtime(%rip) +# else + cmpl $0, __have_futex_clock_realtime +# endif + je .Lreltmo +#endif + + /* This push is only needed to store the sem_t pointer for the + exception handler. */ + pushq %rdi + cfi_adjust_cfa_offset(8) + + movq %rsi, %r10 + + LOCK + addq $1, NWAITERS(%rdi) + +.LcleanupSTART: +13: call __pthread_enable_asynccancel + movl %eax, %r8d + +#if VALUE != 0 + leaq VALUE(%rdi), %rdi +#endif + movl $0xffffffff, %r9d + movl $FUTEX_WAIT_BITSET|FUTEX_CLOCK_REALTIME, %esi + orl PRIVATE(%rdi), %esi + movl $SYS_futex, %eax + xorl %edx, %edx + syscall + movq %rax, %r9 +#if VALUE != 0 + leaq -VALUE(%rdi), %rdi +#endif + + xchgq %r8, %rdi + call __pthread_disable_asynccancel +.LcleanupEND: + movq %r8, %rdi + + testq %r9, %r9 + je 11f + cmpq $-EWOULDBLOCK, %r9 + jne 3f + +11: +#if VALUE == 0 + movl (%rdi), %eax +#else + movl VALUE(%rdi), %eax +#endif +14: testl %eax, %eax + je 13b + + leaq -1(%rax), %rcx + LOCK +#if VALUE == 0 + cmpxchgl %ecx, (%rdi) +#else + cmpxchgl %ecx, VALUE(%rdi) +#endif + jne 14b + + xorl %eax, %eax + +15: LOCK + subq $1, NWAITERS(%rdi) + + leaq 8(%rsp), %rsp + cfi_adjust_cfa_offset(-8) + retq + + cfi_adjust_cfa_offset(8) +3: negq %r9 +#if USE___THREAD + movq errno@gottpoff(%rip), %rdx + movl %r9d, %fs:(%rdx) +#else + callq __errno_location@plt + movl %r9d, (%rax) +#endif + + orl $-1, %eax + jmp 15b + + cfi_adjust_cfa_offset(-8) +6: +#if USE___THREAD + movq errno@gottpoff(%rip), %rdx + movl $EINVAL, %fs:(%rdx) +#else + callq __errno_location@plt + movl $EINVAL, (%rax) +#endif + + orl $-1, %eax + + retq + +#ifndef __ASSUME_FUTEX_CLOCK_REALTIME +.Lreltmo: + pushq %r12 + cfi_adjust_cfa_offset(8) + cfi_rel_offset(%r12, 0) + pushq %r13 + cfi_adjust_cfa_offset(8) + cfi_rel_offset(%r13, 0) + pushq %r14 + cfi_adjust_cfa_offset(8) + cfi_rel_offset(%r14, 0) + +#ifdef __ASSUME_FUTEX_CLOCK_REALTIME +# define STACKFRAME 8 +#else +# define STACKFRAME 24 +#endif + subq $STACKFRAME, %rsp + cfi_adjust_cfa_offset(STACKFRAME) + + movq %rdi, %r12 + movq %rsi, %r13 + + LOCK + addq $1, NWAITERS(%r12) + +7: xorl %esi, %esi + movq %rsp, %rdi + movq $VSYSCALL_ADDR_vgettimeofday, %rax + callq *%rax + + /* Compute relative timeout. */ + movq 8(%rsp), %rax + movl $1000, %edi + mul %rdi /* Milli seconds to nano seconds. */ + movq (%r13), %rdi + movq 8(%r13), %rsi + subq (%rsp), %rdi + subq %rax, %rsi + jns 5f + addq $1000000000, %rsi + decq %rdi +5: testq %rdi, %rdi + movl $ETIMEDOUT, %r14d + js 36f /* Time is already up. */ + + movq %rdi, (%rsp) /* Store relative timeout. */ + movq %rsi, 8(%rsp) + +.LcleanupSTART2: + call __pthread_enable_asynccancel + movl %eax, 16(%rsp) + + movq %rsp, %r10 +# if VALUE == 0 + movq %r12, %rdi +# else + leaq VALUE(%r12), %rdi +# endif +# if FUTEX_WAIT == 0 + movl PRIVATE(%rdi), %esi +# else + movl $FUTEX_WAIT, %esi + orl PRIVATE(%rdi), %esi +# endif + movl $SYS_futex, %eax + xorl %edx, %edx + syscall + movq %rax, %r14 + + movl 16(%rsp), %edi + call __pthread_disable_asynccancel +.LcleanupEND2: + + testq %r14, %r14 + je 9f + cmpq $-EWOULDBLOCK, %r14 + jne 33f + +9: +# if VALUE == 0 + movl (%r12), %eax +# else + movl VALUE(%r12), %eax +# endif +8: testl %eax, %eax + je 7b + + leaq -1(%rax), %rcx + LOCK +# if VALUE == 0 + cmpxchgl %ecx, (%r12) +# else + cmpxchgl %ecx, VALUE(%r12) +# endif + jne 8b + + xorl %eax, %eax + +45: LOCK + subq $1, NWAITERS(%r12) + + addq $STACKFRAME, %rsp + cfi_adjust_cfa_offset(-STACKFRAME) + popq %r14 + cfi_adjust_cfa_offset(-8) + cfi_restore(%r14) + popq %r13 + cfi_adjust_cfa_offset(-8) + cfi_restore(%r13) + popq %r12 + cfi_adjust_cfa_offset(-8) + cfi_restore(%r12) + retq + + cfi_adjust_cfa_offset(STACKFRAME + 3 * 8) + cfi_rel_offset(%r12, STACKFRAME + 2 * 8) + cfi_rel_offset(%r13, STACKFRAME + 1 * 8) + cfi_rel_offset(%r14, STACKFRAME) +33: negq %r14 +36: +#if USE___THREAD + movq errno@gottpoff(%rip), %rdx + movl %r14d, %fs:(%rdx) +#else + callq __errno_location@plt + movl %r14d, (%rax) +#endif + + orl $-1, %eax + jmp 45b +#endif + cfi_endproc + .size sem_timedwait,.-sem_timedwait + + + .type sem_timedwait_cleanup,@function +sem_timedwait_cleanup: + cfi_startproc + cfi_adjust_cfa_offset(8) + + movq (%rsp), %rdi + LOCK + subq $1, NWAITERS(%rdi) + movq %rax, %rdi +.LcallUR: + call _Unwind_Resume@PLT + hlt +.LENDCODE: + cfi_endproc + .size sem_timedwait_cleanup,.-sem_timedwait_cleanup + + +#ifndef __ASSUME_FUTEX_CLOCK_REALTIME + .type sem_timedwait_cleanup2,@function +sem_timedwait_cleanup2: + cfi_startproc + cfi_adjust_cfa_offset(STACKFRAME + 3 * 8) + cfi_rel_offset(%r12, STACKFRAME + 2 * 8) + cfi_rel_offset(%r13, STACKFRAME + 1 * 8) + cfi_rel_offset(%r14, STACKFRAME) + + LOCK + subq $1, NWAITERS(%r12) + movq %rax, %rdi + movq STACKFRAME(%rsp), %r14 + movq STACKFRAME+8(%rsp), %r13 + movq STACKFRAME+16(%rsp), %r12 +.LcallUR2: + call _Unwind_Resume@PLT + hlt +.LENDCODE2: + cfi_endproc + .size sem_timedwait_cleanup2,.-sem_timedwait_cleanup2 +#endif + + + .section .gcc_except_table,"a",@progbits +.LexceptSTART: + .byte DW_EH_PE_omit # @LPStart format + .byte DW_EH_PE_omit # @TType format + .byte DW_EH_PE_uleb128 # call-site format + .uleb128 .Lcstend-.Lcstbegin +.Lcstbegin: + .uleb128 .LcleanupSTART-.LSTARTCODE + .uleb128 .LcleanupEND-.LcleanupSTART + .uleb128 sem_timedwait_cleanup-.LSTARTCODE + .uleb128 0 +#ifndef __ASSUME_FUTEX_CLOCK_REALTIME + .uleb128 .LcleanupSTART2-.LSTARTCODE + .uleb128 .LcleanupEND2-.LcleanupSTART2 + .uleb128 sem_timedwait_cleanup2-.LSTARTCODE + .uleb128 0 +#endif + .uleb128 .LcallUR-.LSTARTCODE + .uleb128 .LENDCODE-.LcallUR + .uleb128 0 + .uleb128 0 +#ifndef __ASSUME_FUTEX_CLOCK_REALTIME + .uleb128 .LcallUR2-.LSTARTCODE + .uleb128 .LENDCODE2-.LcallUR2 + .uleb128 0 + .uleb128 0 +#endif +.Lcstend: + + +#ifdef SHARED + .hidden DW.ref.__gcc_personality_v0 + .weak DW.ref.__gcc_personality_v0 + .section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits + .align 8 + .type DW.ref.__gcc_personality_v0, @object + .size DW.ref.__gcc_personality_v0, 8 +DW.ref.__gcc_personality_v0: + .quad __gcc_personality_v0 +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/sem_trywait.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/sem_trywait.S new file mode 100644 index 00000000..7b7f63dd --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/sem_trywait.S @@ -0,0 +1,52 @@ +/* Copyright (C) 2002, 2003, 2005, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + + .text + + .globl sem_trywait + .type sem_trywait,@function + .align 16 +sem_trywait: + movl (%rdi), %eax +2: testl %eax, %eax + jz 1f + + leal -1(%rax), %edx + LOCK + cmpxchgl %edx, (%rdi) + jne 2b + + xorl %eax, %eax + retq + +1: +#if USE___THREAD + movq errno@gottpoff(%rip), %rdx + movl $EAGAIN, %fs:(%rdx) +#else + callq __errno_location@plt + movl $EAGAIN, (%rax) +#endif + orl $-1, %eax + retq + .size sem_trywait,.-sem_trywait diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/sem_wait.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/sem_wait.S new file mode 100644 index 00000000..f6b39bd7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/sem_wait.S @@ -0,0 +1,174 @@ +/* Copyright (C) 2002, 2003, 2005, 2007, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + + + .text + + .globl sem_wait + .type sem_wait,@function + .align 16 +sem_wait: +.LSTARTCODE: + cfi_startproc + +#if VALUE == 0 + movl (%rdi), %eax +#else + movl VALUE(%rdi), %eax +#endif +2: testl %eax, %eax + je 1f + + leal -1(%rax), %edx + LOCK +#if VALUE == 0 + cmpxchgl %edx, (%rdi) +#else + cmpxchgl %edx, VALUE(%rdi) +#endif + jne 2b + + xorl %eax, %eax + retq + + /* This push is only needed to store the sem_t pointer for the + exception handler. */ +1: pushq %rdi + cfi_adjust_cfa_offset(8) + + LOCK + addq $1, NWAITERS(%rdi) + +.LcleanupSTART: +6: call __pthread_enable_asynccancel + movl %eax, %r8d + + xorq %r10, %r10 + movl $SYS_futex, %eax +#if FUTEX_WAIT == 0 + movl PRIVATE(%rdi), %esi +#else + movl $FUTEX_WAIT, %esi + orl PRIVATE(%rdi), %esi +#endif + xorl %edx, %edx + syscall + movq %rax, %rcx + + xchgq %r8, %rdi + call __pthread_disable_asynccancel +.LcleanupEND: + movq %r8, %rdi + + testq %rcx, %rcx + je 3f + cmpq $-EWOULDBLOCK, %rcx + jne 4f + +3: +#if VALUE == 0 + movl (%rdi), %eax +#else + movl VALUE(%rdi), %eax +#endif +5: testl %eax, %eax + je 6b + + leal -1(%rax), %edx + LOCK +#if VALUE == 0 + cmpxchgl %edx, (%rdi) +#else + cmpxchgl %edx, VALUE(%rdi) +#endif + jne 5b + + xorl %eax, %eax + +9: LOCK + subq $1, NWAITERS(%rdi) + + leaq 8(%rsp), %rsp + cfi_adjust_cfa_offset(-8) + + retq + + cfi_adjust_cfa_offset(8) +4: negq %rcx +#if USE___THREAD + movq errno@gottpoff(%rip), %rdx + movl %ecx, %fs:(%rdx) +#else +# error "not supported. %rcx and %rdi must be preserved" + callq __errno_location@plt + movl %ecx, (%rax) +#endif + orl $-1, %eax + + jmp 9b + .size sem_wait,.-sem_wait + + + .type sem_wait_cleanup,@function +sem_wait_cleanup: + movq (%rsp), %rdi + LOCK + subq $1, NWAITERS(%rdi) + movq %rax, %rdi +.LcallUR: + call _Unwind_Resume@PLT + hlt +.LENDCODE: + cfi_endproc + .size sem_wait_cleanup,.-sem_wait_cleanup + + + .section .gcc_except_table,"a",@progbits +.LexceptSTART: + .byte DW_EH_PE_omit # @LPStart format + .byte DW_EH_PE_omit # @TType format + .byte DW_EH_PE_uleb128 # call-site format + .uleb128 .Lcstend-.Lcstbegin +.Lcstbegin: + .uleb128 .LcleanupSTART-.LSTARTCODE + .uleb128 .LcleanupEND-.LcleanupSTART + .uleb128 sem_wait_cleanup-.LSTARTCODE + .uleb128 0 + .uleb128 .LcallUR-.LSTARTCODE + .uleb128 .LENDCODE-.LcallUR + .uleb128 0 + .uleb128 0 +.Lcstend: + + +#ifdef SHARED + .hidden DW.ref.__gcc_personality_v0 + .weak DW.ref.__gcc_personality_v0 + .section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits + .align 8 + .type DW.ref.__gcc_personality_v0, @object + .size DW.ref.__gcc_personality_v0, 8 +DW.ref.__gcc_personality_v0: + .quad __gcc_personality_v0 +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h new file mode 100644 index 00000000..1c93952d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h @@ -0,0 +1,111 @@ +/* Copyright (C) 2002-2006, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#ifndef __ASSEMBLER__ +# include +#endif + +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + +/* The code to disable cancellation depends on the fact that the called + functions are special. They don't modify registers other than %rax + and %r11 if they return. Therefore we don't have to preserve other + registers around these calls. */ +# undef PSEUDO +# define PSEUDO(name, syscall_name, args) \ + .text; \ + ENTRY (name) \ + SINGLE_THREAD_P; \ + jne L(pseudo_cancel); \ + .type __##syscall_name##_nocancel,@function; \ + .globl __##syscall_name##_nocancel; \ + __##syscall_name##_nocancel: \ + DO_CALL (syscall_name, args); \ + cmpq $-4095, %rax; \ + jae SYSCALL_ERROR_LABEL; \ + ret; \ + .size __##syscall_name##_nocancel,.-__##syscall_name##_nocancel; \ + L(pseudo_cancel): \ + /* We always have to align the stack before calling a function. */ \ + subq $8, %rsp; cfi_adjust_cfa_offset (8); \ + CENABLE \ + /* The return value from CENABLE is argument for CDISABLE. */ \ + movq %rax, (%rsp); \ + DO_CALL (syscall_name, args); \ + movq (%rsp), %rdi; \ + /* Save %rax since it's the error code from the syscall. */ \ + movq %rax, %rdx; \ + CDISABLE \ + movq %rdx, %rax; \ + addq $8,%rsp; cfi_adjust_cfa_offset (-8); \ + cmpq $-4095, %rax; \ + jae SYSCALL_ERROR_LABEL; \ + L(pseudo_end): + + +# ifdef IS_IN_libpthread +# define CENABLE call __pthread_enable_asynccancel; +# define CDISABLE call __pthread_disable_asynccancel; +# define __local_multiple_threads __pthread_multiple_threads +# elif !defined NOT_IN_libc +# define CENABLE call __libc_enable_asynccancel; +# define CDISABLE call __libc_disable_asynccancel; +# define __local_multiple_threads __libc_multiple_threads +# elif defined IS_IN_librt +# define CENABLE call __librt_enable_asynccancel; +# define CDISABLE call __librt_disable_asynccancel; +# else +# error Unsupported library +# endif + +# if defined IS_IN_libpthread || !defined NOT_IN_libc +# ifndef __ASSEMBLER__ +extern int __local_multiple_threads attribute_hidden; +# define SINGLE_THREAD_P \ + __builtin_expect (__local_multiple_threads == 0, 1) +# else +# define SINGLE_THREAD_P cmpl $0, __local_multiple_threads(%rip) +# endif + +# else + +# ifndef __ASSEMBLER__ +# define SINGLE_THREAD_P \ + __builtin_expect (THREAD_GETMEM (THREAD_SELF, \ + header.multiple_threads) == 0, 1) +# else +# define SINGLE_THREAD_P cmpl $0, %fs:MULTIPLE_THREADS_OFFSET +# endif + +# endif + +#elif !defined __ASSEMBLER__ + +# define SINGLE_THREAD_P (1) +# define NO_CANCELLATION 1 + +#endif + +#ifndef __ASSEMBLER__ +# define RTLD_SINGLE_THREAD_P \ + __builtin_expect (THREAD_GETMEM (THREAD_SELF, \ + header.multiple_threads) == 0, 1) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/vfork.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/vfork.S new file mode 100644 index 00000000..9a9912ca --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/unix/sysv/linux/x86_64/vfork.S @@ -0,0 +1,43 @@ +/* Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* We want an #include_next, but we are the main source file. + So, #include ourselves and in that incarnation we can use #include_next. */ +#ifndef INCLUDED_SELF +# define INCLUDED_SELF +# include +#else + +# include + +# define SAVE_PID \ + movl %fs:PID, %esi; \ + movl $0x80000000, %ecx; \ + movl %esi, %edx; \ + negl %edx; \ + cmove %ecx, %edx; \ + movl %edx, %fs:PID + +# define RESTORE_PID \ + testq %rax, %rax; \ + je 1f; \ + movl %esi, %fs:PID; \ +1: + +# include_next +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/x86_64/Makefile.arch b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/x86_64/Makefile.arch new file mode 100644 index 00000000..cf6f1c22 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/x86_64/Makefile.arch @@ -0,0 +1,10 @@ +# Makefile for uClibc NPTL +# +# Copyright (C) 2005 Steven J. Hill +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +CFLAGS-pthread_spin_lock.c += -D_GNU_SOURCE + + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/x86_64/dl-tls.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/x86_64/dl-tls.h new file mode 100644 index 00000000..3e4768dc --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/x86_64/dl-tls.h @@ -0,0 +1,29 @@ +/* Thread-local storage handling in the ELF dynamic linker. x86-64 version. + Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + + +/* Type used for the representation of TLS information in the GOT. */ +typedef struct +{ + unsigned long int ti_module; + unsigned long int ti_offset; +} tls_index; + + +extern void *__tls_get_addr (tls_index *ti); diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/x86_64/jmpbuf-unwind.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/x86_64/jmpbuf-unwind.h new file mode 100644 index 00000000..345ed557 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/x86_64/jmpbuf-unwind.h @@ -0,0 +1,31 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +#define _JMPBUF_CFA_UNWINDS_ADJ(_jmpbuf, _context, _adj) \ + _JMPBUF_UNWINDS_ADJ (_jmpbuf, (void *) _Unwind_GetCFA (_context), _adj) + +#define _JMPBUF_UNWINDS_ADJ(_jmpbuf, _address, _adj) \ + ((uintptr_t) (_address) - (_adj) < (uintptr_t) (_jmpbuf)[JB_RSP] - (_adj)) + +/* We use the normal lobngjmp for unwinding. */ +#define __libc_unwind_longjmp(buf, val) __libc_longjmp (buf, val) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/x86_64/pthread_spin_init.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/x86_64/pthread_spin_init.c new file mode 100644 index 00000000..55696204 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/x86_64/pthread_spin_init.c @@ -0,0 +1 @@ +#include "../i386/pthread_spin_init.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/x86_64/pthread_spin_lock.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/x86_64/pthread_spin_lock.c new file mode 100644 index 00000000..7cf0e0ec --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/x86_64/pthread_spin_lock.c @@ -0,0 +1 @@ +#include "../i386/pthread_spin_lock.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/x86_64/pthread_spin_trylock.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/x86_64/pthread_spin_trylock.S new file mode 100644 index 00000000..9b513358 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/x86_64/pthread_spin_trylock.S @@ -0,0 +1,40 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + + +#ifdef UP +# define LOCK +#else +# define LOCK lock +#endif + + .globl pthread_spin_trylock + .type pthread_spin_trylock,@function + .align 16 +pthread_spin_trylock: + movl $1, %eax + xorl %ecx, %ecx + LOCK + cmpxchgl %ecx, (%rdi) + movl $EBUSY, %eax + cmovel %ecx, %eax + retq + .size pthread_spin_trylock,.-pthread_spin_trylock diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/x86_64/pthread_spin_unlock.S b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/x86_64/pthread_spin_unlock.S new file mode 100644 index 00000000..d3e13bde --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/x86_64/pthread_spin_unlock.S @@ -0,0 +1,31 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + + .globl pthread_spin_unlock + .type pthread_spin_unlock,@function + .align 16 +pthread_spin_unlock: + movl $1, (%rdi) + xorl %eax, %eax + retq + .size pthread_spin_unlock,.-pthread_spin_unlock + + /* The implementation of pthread_spin_init is identical. */ + .globl pthread_spin_init +pthread_spin_init = pthread_spin_unlock diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/x86_64/pthreaddef.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/x86_64/pthreaddef.h new file mode 100644 index 00000000..36e994d8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/x86_64/pthreaddef.h @@ -0,0 +1,43 @@ +/* Copyright (C) 2002, 2003, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Default stack size. */ +#define ARCH_STACK_DEFAULT_SIZE (2 * 1024 * 1024) + +/* Required stack pointer alignment at beginning. SSE requires 16 + bytes. */ +#define STACK_ALIGN 16 + +/* Minimal stack size after allocating thread descriptor and guard size. */ +#define MINIMAL_REST_STACK 2048 + +/* Alignment requirement for TCB. */ +#define TCB_ALIGNMENT 16 + + +/* Location of current stack frame. The frame pointer is not usable. */ +#define CURRENT_STACK_FRAME \ + ({ char *frame; __asm__ ("movq %%rsp, %0" : "=r" (frame)); frame; }) + + +/* XXX Until we have a better place keep the definitions here. */ + +/* While there is no such syscall. */ +#define __exit_thread_inline(val) \ + __asm__ __volatile__ ("syscall" :: "a" (__NR_exit), "D" (val)) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/x86_64/tcb-offsets.sym b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/x86_64/tcb-offsets.sym new file mode 100644 index 00000000..cf863752 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/x86_64/tcb-offsets.sym @@ -0,0 +1,28 @@ +#include +#include + +RESULT offsetof (struct pthread, result) +TID offsetof (struct pthread, tid) +PID offsetof (struct pthread, pid) +CANCELHANDLING offsetof (struct pthread, cancelhandling) +CLEANUP_JMP_BUF offsetof (struct pthread, cleanup_jmp_buf) +CLEANUP offsetof (struct pthread, cleanup) +CLEANUP_PREV offsetof (struct _pthread_cleanup_buffer, __prev) +MUTEX_FUTEX offsetof (pthread_mutex_t, __data.__lock) +MULTIPLE_THREADS_OFFSET offsetof (tcbhead_t, multiple_threads) +POINTER_GUARD offsetof (tcbhead_t, pointer_guard) +VGETCPU_CACHE_OFFSET offsetof (tcbhead_t, vgetcpu_cache) +#ifndef __ASSUME_PRIVATE_FUTEX +PRIVATE_FUTEX offsetof (tcbhead_t, private_futex) +#endif +RTLD_SAVESPACE_SSE offsetof (tcbhead_t, rtld_savespace_sse) + +-- Not strictly offsets, but these values are also used in the TCB. +TCB_CANCELSTATE_BITMASK CANCELSTATE_BITMASK +TCB_CANCELTYPE_BITMASK CANCELTYPE_BITMASK +TCB_CANCELING_BITMASK CANCELING_BITMASK +TCB_CANCELED_BITMASK CANCELED_BITMASK +TCB_EXITING_BITMASK EXITING_BITMASK +TCB_CANCEL_RESTMASK CANCEL_RESTMASK +TCB_TERMINATED_BITMASK TERMINATED_BITMASK +TCB_PTHREAD_CANCELED PTHREAD_CANCELED diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/x86_64/tls.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/x86_64/tls.h new file mode 100644 index 00000000..afaf1597 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/sysdeps/x86_64/tls.h @@ -0,0 +1,438 @@ +/* Definition for thread-local data handling. nptl/x86_64 version. + Copyright (C) 2002-2007, 2008, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _TLS_H +#define _TLS_H 1 + +#ifndef __ASSEMBLER__ +# include /* For ARCH_SET_FS. */ +# include +# include +# include +# include +# include +# include +# include +# include + + +/* Type for the dtv. */ +typedef union dtv +{ + size_t counter; + struct + { + void *val; + bool is_static; + } pointer; +} dtv_t; + + +typedef struct +{ + void *tcb; /* Pointer to the TCB. Not necessarily the + thread descriptor used by libpthread. */ + dtv_t *dtv; + void *self; /* Pointer to the thread descriptor. */ + int multiple_threads; + int gscope_flag; + uintptr_t sysinfo; + uintptr_t stack_guard; + uintptr_t pointer_guard; + unsigned long int vgetcpu_cache[2]; +# ifndef __ASSUME_PRIVATE_FUTEX + int private_futex; +# else + int __unused1; +# endif +# if __WORDSIZE == 64 + int rtld_must_xmm_save; +# endif + /* Reservation of some values for the TM ABI. */ + void *__private_tm[5]; +# if __WORDSIZE == 64 + long int __unused2; + /* Have space for the post-AVX register size. */ + __m128 rtld_savespace_sse[8][4]; + + void *__padding[8]; +# endif +} tcbhead_t; + +#else /* __ASSEMBLER__ */ +# include +#endif + + +/* We require TLS support in the tools. */ +#define HAVE_TLS_SUPPORT 1 +#define HAVE___THREAD 1 +#define HAVE_TLS_MODEL_ATTRIBUTE 1 + +/* Signal that TLS support is available. */ +#define USE_TLS 1 + +/* Alignment requirement for the stack. */ +#define STACK_ALIGN 16 + + +#ifndef __ASSEMBLER__ +/* Get system call information. */ +# include + + +/* Get the thread descriptor definition. */ +# include + +#ifndef LOCK_PREFIX +# ifdef UP +# define LOCK_PREFIX /* nothing */ +# else +# define LOCK_PREFIX "lock;" +# endif +#endif + +/* This is the size of the initial TCB. Can't be just sizeof (tcbhead_t), + because NPTL getpid, __libc_alloca_cutoff etc. need (almost) the whole + struct pthread even when not linked with -lpthread. */ +# define TLS_INIT_TCB_SIZE sizeof (struct pthread) + +/* Alignment requirements for the initial TCB. */ +# define TLS_INIT_TCB_ALIGN __alignof__ (struct pthread) + +/* This is the size of the TCB. */ +# define TLS_TCB_SIZE sizeof (struct pthread) + +/* Alignment requirements for the TCB. */ +//# define TLS_TCB_ALIGN __alignof__ (struct pthread) +// Normally the above would be correct But we have to store post-AVX +// vector registers in the TCB and we want the storage to be aligned. +// unfortunately there isn't yet a type for these values and hence no +// 32-byte alignment requirement. Make this explicit, for now. +# define TLS_TCB_ALIGN 32 + +/* The TCB can have any size and the memory following the address the + thread pointer points to is unspecified. Allocate the TCB there. */ +# define TLS_TCB_AT_TP 1 + + +/* Install the dtv pointer. The pointer passed is to the element with + index -1 which contain the length. */ +# define INSTALL_DTV(descr, dtvp) \ + ((tcbhead_t *) (descr))->dtv = (dtvp) + 1 + +/* Install new dtv for current thread. */ +# define INSTALL_NEW_DTV(dtvp) \ + ({ struct pthread *__pd; \ + THREAD_SETMEM (__pd, header.dtv, (dtvp)); }) + +/* Return dtv of given thread descriptor. */ +# define GET_DTV(descr) \ + (((tcbhead_t *) (descr))->dtv) + + +/* Macros to load from and store into segment registers. */ +# define TLS_GET_FS() \ + ({ int __seg; __asm__ ("movl %%fs, %0" : "=q" (__seg)); __seg; }) +# define TLS_SET_FS(val) \ + __asm__ ("movl %0, %%fs" :: "q" (val)) + + +/* Code to initially initialize the thread pointer. This might need + special attention since 'errno' is not yet available and if the + operation can cause a failure 'errno' must not be touched. + + We have to make the syscall for both uses of the macro since the + address might be (and probably is) different. */ +# define TLS_INIT_TP(thrdescr, secondcall) \ + ({ void *_thrdescr = (thrdescr); \ + tcbhead_t *_head = _thrdescr; \ + int _result; \ + \ + _head->tcb = _thrdescr; \ + /* For now the thread descriptor is at the same address. */ \ + _head->self = _thrdescr; \ + \ + /* It is a simple syscall to set the %fs value for the thread. */ \ + __asm__ __volatile__ ("syscall" \ + : "=a" (_result) \ + : "0" ((unsigned long int) __NR_arch_prctl), \ + "D" ((unsigned long int) ARCH_SET_FS), \ + "S" (_thrdescr) \ + : "memory", "cc", "r11", "cx"); \ + \ + _result ? "cannot set %fs base address for thread-local storage" : 0; \ + }) + + +/* Return the address of the dtv for the current thread. */ +# define THREAD_DTV() \ + ({ struct pthread *__pd; \ + THREAD_GETMEM (__pd, header.dtv); }) + + +/* Return the thread descriptor for the current thread. + + The contained asm must *not* be marked __volatile__ since otherwise + assignments like + pthread_descr self = thread_self(); + do not get optimized away. */ +# define THREAD_SELF \ + ({ struct pthread *__self; \ + __asm__ ("movq %%fs:%c1,%q0" : "=r" (__self) \ + : "i" (offsetof (struct pthread, header.self))); \ + __self;}) + +/* Magic for libthread_db to know how to do THREAD_SELF. */ +# define DB_THREAD_SELF_INCLUDE /* For the FS constant. */ +# define DB_THREAD_SELF CONST_THREAD_AREA (64, FS) + +/* Read member of the thread descriptor directly. */ +# define THREAD_GETMEM(descr, member) \ + ({ __typeof (descr->member) __value; \ + if (sizeof (__value) == 1) \ + __asm__ __volatile__ ("movb %%fs:%P2,%b0" \ + : "=q" (__value) \ + : "0" (0), "i" (offsetof (struct pthread, member))); \ + else if (sizeof (__value) == 4) \ + __asm__ __volatile__ ("movl %%fs:%P1,%0" \ + : "=r" (__value) \ + : "i" (offsetof (struct pthread, member))); \ + else \ + { \ + if (sizeof (__value) != 8) \ + /* There should not be any value with a size other than 1, \ + 4 or 8. */ \ + abort (); \ + \ + __asm__ __volatile__ ("movq %%fs:%P1,%q0" \ + : "=r" (__value) \ + : "i" (offsetof (struct pthread, member))); \ + } \ + __value; }) + + +/* Same as THREAD_GETMEM, but the member offset can be non-constant. */ +# define THREAD_GETMEM_NC(descr, member, idx) \ + ({ __typeof (descr->member[0]) __value; \ + if (sizeof (__value) == 1) \ + __asm__ __volatile__ ("movb %%fs:%P2(%q3),%b0" \ + : "=q" (__value) \ + : "0" (0), "i" (offsetof (struct pthread, member[0])), \ + "r" (idx)); \ + else if (sizeof (__value) == 4) \ + __asm__ __volatile__ ("movl %%fs:%P1(,%q2,4),%0" \ + : "=r" (__value) \ + : "i" (offsetof (struct pthread, member[0])), "r" (idx));\ + else \ + { \ + if (sizeof (__value) != 8) \ + /* There should not be any value with a size other than 1, \ + 4 or 8. */ \ + abort (); \ + \ + __asm__ __volatile__ ("movq %%fs:%P1(,%q2,8),%q0" \ + : "=r" (__value) \ + : "i" (offsetof (struct pthread, member[0])), \ + "r" (idx)); \ + } \ + __value; }) + + +/* Loading addresses of objects on x86-64 needs to be treated special + when generating PIC code. */ +#ifdef __pic__ +# define IMM_MODE "nr" +#else +# define IMM_MODE "ir" +#endif + + +/* Same as THREAD_SETMEM, but the member offset can be non-constant. */ +# define THREAD_SETMEM(descr, member, value) \ + ({ if (sizeof (descr->member) == 1) \ + __asm__ __volatile__ ("movb %b0,%%fs:%P1" : \ + : "iq" (value), \ + "i" (offsetof (struct pthread, member))); \ + else if (sizeof (descr->member) == 4) \ + __asm__ __volatile__ ("movl %0,%%fs:%P1" : \ + : IMM_MODE (value), \ + "i" (offsetof (struct pthread, member))); \ + else \ + { \ + if (sizeof (descr->member) != 8) \ + /* There should not be any value with a size other than 1, \ + 4 or 8. */ \ + abort (); \ + \ + __asm__ __volatile__ ("movq %q0,%%fs:%P1" : \ + : IMM_MODE ((unsigned long int) value), \ + "i" (offsetof (struct pthread, member))); \ + }}) + + +/* Set member of the thread descriptor directly. */ +# define THREAD_SETMEM_NC(descr, member, idx, value) \ + ({ if (sizeof (descr->member[0]) == 1) \ + __asm__ __volatile__ ("movb %b0,%%fs:%P1(%q2)" : \ + : "iq" (value), \ + "i" (offsetof (struct pthread, member[0])), \ + "r" (idx)); \ + else if (sizeof (descr->member[0]) == 4) \ + __asm__ __volatile__ ("movl %0,%%fs:%P1(,%q2,4)" : \ + : IMM_MODE (value), \ + "i" (offsetof (struct pthread, member[0])), \ + "r" (idx)); \ + else \ + { \ + if (sizeof (descr->member[0]) != 8) \ + /* There should not be any value with a size other than 1, \ + 4 or 8. */ \ + abort (); \ + \ + __asm__ __volatile__ ("movq %q0,%%fs:%P1(,%q2,8)" : \ + : IMM_MODE ((unsigned long int) value), \ + "i" (offsetof (struct pthread, member[0])), \ + "r" (idx)); \ + }}) + + +/* Atomic compare and exchange on TLS, returning old value. */ +# define THREAD_ATOMIC_CMPXCHG_VAL(descr, member, newval, oldval) \ + ({ __typeof (descr->member) __ret; \ + __typeof (oldval) __old = (oldval); \ + if (sizeof (descr->member) == 4) \ + __asm__ __volatile__ (LOCK_PREFIX "cmpxchgl %2, %%fs:%P3" \ + : "=a" (__ret) \ + : "0" (__old), "r" (newval), \ + "i" (offsetof (struct pthread, member))); \ + else \ + /* Not necessary for other sizes in the moment. */ \ + abort (); \ + __ret; }) + + +/* Atomic logical and. */ +# define THREAD_ATOMIC_AND(descr, member, val) \ + (void) ({ if (sizeof ((descr)->member) == 4) \ + __asm__ __volatile__ (LOCK_PREFIX "andl %1, %%fs:%P0" \ + :: "i" (offsetof (struct pthread, member)), \ + "ir" (val)); \ + else \ + /* Not necessary for other sizes in the moment. */ \ + abort (); }) + + +/* Atomic set bit. */ +# define THREAD_ATOMIC_BIT_SET(descr, member, bit) \ + (void) ({ if (sizeof ((descr)->member) == 4) \ + __asm__ __volatile__ (LOCK_PREFIX "orl %1, %%fs:%P0" \ + :: "i" (offsetof (struct pthread, member)), \ + "ir" (1 << (bit))); \ + else \ + /* Not necessary for other sizes in the moment. */ \ + abort (); }) + + +# define CALL_THREAD_FCT(descr) \ + ({ void *__res; \ + __asm__ __volatile__ ("movq %%fs:%P2, %%rdi\n\t" \ + "callq *%%fs:%P1" \ + : "=a" (__res) \ + : "i" (offsetof (struct pthread, start_routine)), \ + "i" (offsetof (struct pthread, arg)) \ + : "di", "si", "cx", "dx", "r8", "r9", "r10", "r11", \ + "memory", "cc"); \ + __res; }) + + +/* Set the stack guard field in TCB head. */ +# define THREAD_SET_STACK_GUARD(value) \ + THREAD_SETMEM (THREAD_SELF, header.stack_guard, value) +# define THREAD_COPY_STACK_GUARD(descr) \ + ((descr)->header.stack_guard \ + = THREAD_GETMEM (THREAD_SELF, header.stack_guard)) + + +/* Set the pointer guard field in the TCB head. */ +# define THREAD_SET_POINTER_GUARD(value) \ + THREAD_SETMEM (THREAD_SELF, header.pointer_guard, value) +# define THREAD_COPY_POINTER_GUARD(descr) \ + ((descr)->header.pointer_guard \ + = THREAD_GETMEM (THREAD_SELF, header.pointer_guard)) + + +/* Get and set the global scope generation counter in the TCB head. */ +# define THREAD_GSCOPE_FLAG_UNUSED 0 +# define THREAD_GSCOPE_FLAG_USED 1 +# define THREAD_GSCOPE_FLAG_WAIT 2 +# define THREAD_GSCOPE_RESET_FLAG() \ + do \ + { int __res; \ + __asm__ __volatile__ ("xchgl %0, %%fs:%P1" \ + : "=r" (__res) \ + : "i" (offsetof (struct pthread, header.gscope_flag)), \ + "0" (THREAD_GSCOPE_FLAG_UNUSED)); \ + if (__res == THREAD_GSCOPE_FLAG_WAIT) \ + lll_futex_wake (&THREAD_SELF->header.gscope_flag, 1, LLL_PRIVATE); \ + } \ + while (0) +# define THREAD_GSCOPE_SET_FLAG() \ + THREAD_SETMEM (THREAD_SELF, header.gscope_flag, THREAD_GSCOPE_FLAG_USED) +# define THREAD_GSCOPE_WAIT() \ + GL(dl_wait_lookup_done) () + + +# ifdef SHARED +/* Defined in dl-trampoline.S. */ +extern void _dl_x86_64_save_sse (void); +extern void _dl_x86_64_restore_sse (void); + +# define RTLD_CHECK_FOREIGN_CALL \ + (THREAD_GETMEM (THREAD_SELF, header.rtld_must_xmm_save) != 0) + +/* NB: Don't use the xchg operation because that would imply a lock + prefix which is expensive and unnecessary. The cache line is also + not contested at all. */ +# define RTLD_ENABLE_FOREIGN_CALL \ + int old_rtld_must_xmm_save = THREAD_GETMEM (THREAD_SELF, \ + header.rtld_must_xmm_save); \ + THREAD_SETMEM (THREAD_SELF, header.rtld_must_xmm_save, 1) + +# define RTLD_PREPARE_FOREIGN_CALL \ + do if (THREAD_GETMEM (THREAD_SELF, header.rtld_must_xmm_save)) \ + { \ + _dl_x86_64_save_sse (); \ + THREAD_SETMEM (THREAD_SELF, header.rtld_must_xmm_save, 0); \ + } \ + while (0) + +# define RTLD_FINALIZE_FOREIGN_CALL \ + do { \ + if (THREAD_GETMEM (THREAD_SELF, header.rtld_must_xmm_save) == 0) \ + _dl_x86_64_restore_sse (); \ + THREAD_SETMEM (THREAD_SELF, header.rtld_must_xmm_save, \ + old_rtld_must_xmm_save); \ + } while (0) +# endif + + +#endif /* __ASSEMBLER__ */ + +#endif /* tls.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/unwind.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/unwind.c new file mode 100644 index 00000000..c7e01e76 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/unwind.c @@ -0,0 +1,177 @@ +/* Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper + and Richard Henderson , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include "pthreadP.h" +#include + +#ifdef HAVE_FORCED_UNWIND + +#ifdef _STACK_GROWS_DOWN +# define FRAME_LEFT(frame, other, adj) \ + ((uintptr_t) frame - adj >= (uintptr_t) other - adj) +#elif _STACK_GROWS_UP +# define FRAME_LEFT(frame, other, adj) \ + ((uintptr_t) frame - adj <= (uintptr_t) other - adj) +#else +# error "Define either _STACK_GROWS_DOWN or _STACK_GROWS_UP" +#endif + +static _Unwind_Reason_Code +unwind_stop (int version, _Unwind_Action actions, + _Unwind_Exception_Class exc_class, + struct _Unwind_Exception *exc_obj, + struct _Unwind_Context *context, void *stop_parameter) +{ + struct pthread_unwind_buf *buf = stop_parameter; + struct pthread *self = THREAD_SELF; + struct _pthread_cleanup_buffer *curp = THREAD_GETMEM (self, cleanup); + int do_longjump = 0; + + /* Adjust all pointers used in comparisons, so that top of thread's + stack is at the top of address space. Without that, things break + if stack is allocated above the main stack. */ + uintptr_t adj = (uintptr_t) self->stackblock + self->stackblock_size; + + /* Do longjmp if we're at "end of stack", aka "end of unwind data". + We assume there are only C frame without unwind data in between + here and the jmp_buf target. Otherwise simply note that the CFA + of a function is NOT within it's stack frame; it's the SP of the + previous frame. */ + if ((actions & _UA_END_OF_STACK) + || ! _JMPBUF_CFA_UNWINDS_ADJ (buf->cancel_jmp_buf[0].jmp_buf, context, + adj)) + do_longjump = 1; + + if (__builtin_expect (curp != NULL, 0)) + { + /* Handle the compatibility stuff. Execute all handlers + registered with the old method which would be unwound by this + step. */ + struct _pthread_cleanup_buffer *oldp = buf->priv.data.cleanup; + void *cfa = (void *) _Unwind_GetCFA (context); + + if (curp != oldp && (do_longjump || FRAME_LEFT (cfa, curp, adj))) + { + do + { + /* Pointer to the next element. */ + struct _pthread_cleanup_buffer *nextp = curp->__prev; + + /* Call the handler. */ + curp->__routine (curp->__arg); + + /* To the next. */ + curp = nextp; + } + while (curp != oldp + && (do_longjump || FRAME_LEFT (cfa, curp, adj))); + + /* Mark the current element as handled. */ + THREAD_SETMEM (self, cleanup, curp); + } + } + + if (do_longjump) + __libc_unwind_longjmp ((struct __jmp_buf_tag *) buf->cancel_jmp_buf, 1); + + return _URC_NO_REASON; +} + + +static void +unwind_cleanup (_Unwind_Reason_Code reason, struct _Unwind_Exception *exc) +{ + /* When we get here a C++ catch block didn't rethrow the object. We + cannot handle this case and therefore abort. */ +# define STR_N_LEN(str) str, strlen (str) + INTERNAL_SYSCALL_DECL (err); + INTERNAL_SYSCALL (write, err, 3, STDERR_FILENO, + STR_N_LEN ("FATAL: exception not rethrown\n")); + abort (); +} + +#endif /* have forced unwind */ + + +void +attribute_protected +__cleanup_fct_attribute __attribute ((noreturn)) +__pthread_unwind (__pthread_unwind_buf_t *buf) +{ + struct pthread_unwind_buf *ibuf = (struct pthread_unwind_buf *) buf; + struct pthread *self = THREAD_SELF; + +#ifdef HAVE_FORCED_UNWIND + /* This is not a catchable exception, so don't provide any details about + the exception type. We do need to initialize the field though. */ + THREAD_SETMEM (self, exc.exception_class, 0); + THREAD_SETMEM (self, exc.exception_cleanup, unwind_cleanup); + + _Unwind_ForcedUnwind (&self->exc, unwind_stop, ibuf); +#else + /* Handle the compatibility stuff first. Execute all handlers + registered with the old method. We don't execute them in order, + instead, they will run first. */ + struct _pthread_cleanup_buffer *oldp = ibuf->priv.data.cleanup; + struct _pthread_cleanup_buffer *curp = THREAD_GETMEM (self, cleanup); + + if (curp != oldp) + { + do + { + /* Pointer to the next element. */ + struct _pthread_cleanup_buffer *nextp = curp->__prev; + + /* Call the handler. */ + curp->__routine (curp->__arg); + + /* To the next. */ + curp = nextp; + } + while (curp != oldp); + + /* Mark the current element as handled. */ + THREAD_SETMEM (self, cleanup, curp); + } + + /* We simply jump to the registered setjmp buffer. */ + __libc_unwind_longjmp ((struct __jmp_buf_tag *) ibuf->cancel_jmp_buf, 1); +#endif + /* NOTREACHED */ + + /* We better do not get here. */ + abort (); +} +hidden_def (__pthread_unwind) + + +void +__cleanup_fct_attribute __attribute ((noreturn)) +__pthread_unwind_next (__pthread_unwind_buf_t *buf) +{ + struct pthread_unwind_buf *ibuf = (struct pthread_unwind_buf *) buf; + + __pthread_unwind ((__pthread_unwind_buf_t *) ibuf->priv.data.prev); +} +hidden_def (__pthread_unwind_next) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/vars.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/vars.c new file mode 100644 index 00000000..1e1a3cf5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/vars.c @@ -0,0 +1,43 @@ +/* Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + +/* Default stack size. */ +size_t __default_stacksize attribute_hidden +#ifdef SHARED +; +#else + = PTHREAD_STACK_MIN; +#endif + +/* Flag whether the machine is SMP or not. */ +int __is_smp attribute_hidden; + +#ifndef TLS_MULTIPLE_THREADS_IN_TCB +/* Variable set to a nonzero value if more than one thread runs or ran. */ +int __pthread_multiple_threads attribute_hidden; +#endif + +/* Table of the key information. */ +struct pthread_key_struct __pthread_keys[PTHREAD_KEYS_MAX] + __attribute__ ((nocommon)); +hidden_data_def (__pthread_keys) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/version.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/version.c new file mode 100644 index 00000000..b69556e9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/version.c @@ -0,0 +1,45 @@ +/* Copyright (C) 2002, 2003, 2005, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + + +static const char banner[] = +#include "banner.h" +"Copyright (C) 2006 Free Software Foundation, Inc.\n\ +This is free software; see the source for copying conditions.\n\ +There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A\n\ +PARTICULAR PURPOSE.\n" +#ifdef HAVE_FORCED_UNWIND +"Forced unwind support included.\n" +#endif +; + + +extern void __nptl_main (void) __attribute__ ((noreturn)); +void +__nptl_main (void) +{ + INTERNAL_SYSCALL_DECL (err); + INTERNAL_SYSCALL (write, err, 3, STDOUT_FILENO, (const char *) banner, + sizeof banner - 1); + + _exit (0); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/version.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/version.h new file mode 100644 index 00000000..f294f5c9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl/version.h @@ -0,0 +1 @@ +#define VERSION __stringify(__UCLIBC_MAJOR__) "." __stringify(__UCLIBC_MINOR__) "." __stringify(__UCLIBC_SUBLEVEL__) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/ChangeLog b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/ChangeLog new file mode 100644 index 00000000..52c84913 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/ChangeLog @@ -0,0 +1,207 @@ +2004-09-09 Roland McGrath + + * td_ta_map_lwp2thr.c (td_ta_map_lwp2thr): Don't abort if inferior's + descriptor is bogus. + +2004-05-27 Roland McGrath + + * td_thr_validate.c: When we find no threads and the inferior appears + uninitialized, validate the main thread as a special case. + +2004-05-01 Jakub Jelinek + + * thread_dbP.h (LOG): Use write instead of __libc_write. + +2004-04-03 Ulrich Drepper + + * td_ta_set_event.c (td_ta_set_event): Initialize copy to avoid + warnings. + + * td_ta_thr_iter.c (td_ta_thr_iter): Initialize list to avoid warning. + * td_ta_clear_event.c (td_ta_clear_event): Initialize eventmask to + avoid warning. + * td_ta_set_event.c (td_ta_set_event): Likewise. + +2004-03-24 Roland McGrath + + * fetch-value.c (_td_locate_field): Cast DB_DESC_OFFSET to int32_t. + * thread_dbP.h (DB_DESC_OFFSET): Remove cast from definition. + +2004-03-13 Jakub Jelinek + + * db_info.c: Don't use TLS_TP_OFFSET in the #if, but + TLS_TCB_SIZE == 0 ?: in the DESC macro. + +2004-03-12 Roland McGrath + + * db_info.c [TLS_DTV_AT_TP && TLS_TP_OFFSET > 0] + (_thread_db_pthread_dtvp): Define differently for this case (PowerPC). + +2003-12-11 Ulrich Weigand + + * db_info.c (REGISTER): Add bit size of thread register as second + parameter to REGISTER macro. + +2003-12-02 Roland McGrath + + * thread_dbP.h (DB_FUNCTION): New macro. + * structs.def: Use it for __nptl_create_event and __nptl_death_event. + * db_info.c (DB_FUNCTION): New macro. + * td_symbol_list.c (DB_FUNCTION): New macro, prepend "." to symbol + name under [HAVE_ASM_GLOBAL_DOT_NAME]. + (td_lookup) [HAVE_ASM_GLOBAL_DOT_NAME]: If lookup fails with PS_NOSYM + and name starts with a dot, try it without the dot. + +2003-09-08 Roland McGrath + + * td_thr_get_info.c (td_thr_get_info): Cast th_unique to thread_t. + +2003-08-22 Roland McGrath + + * fetch-value.c (_td_check_sizeof, _td_locate_field): Return + TD_NOCAPAB for PS_NOSYM, instead of vanilla TD_ERR. + * td_thr_tls_get_addr.c (td_thr_tls_get_addr): Return TD_NOAPLIC when + DB_GET_FIELD returns TD_NOCAPAB. + + * thread_db.h (td_thr_tls_get_addr): Use psaddr_t in signature. + * structs.def [USE_TLS]: Add DB_STRUCT_FIELD (link_map, l_tls_modid). + * db_info.c (link_map): Typedef it. + * td_thr_tls_get_addr.c (td_thr_tls_get_addr): Rewritten. + +2003-08-14 Roland McGrath + + * thread_dbP.h: Mostly rewritten with many new macros and decls. + * td_ta_new.c (td_ta_new): Don't cache a lot of symbol values. + * structs.def: New file. + * db_info.c: New file. + * td_symbol_list.c (symbol_list_arr): Define with structs.def macros. + * td_ta_clear_event.c: Rewritten. + * td_ta_event_addr.c: Rewritten. + * td_ta_event_getmsg.c: Rewritten. + * td_ta_get_nthreads.c: Rewritten. + * td_ta_map_lwp2thr.c: New file. + * td_ta_set_event.c: Rewritten. + * td_ta_thr_iter.c: Rewritten. + * td_ta_tsd_iter.c: Rewritten. + * td_thr_clear_event.c: Rewritten. + * td_thr_event_enable.c: Rewritten. + * td_thr_event_getmsg.c: Rewritten. + * td_thr_get_info.c: Rewritten. + * td_thr_getfpregs.c: Rewritten. + * td_thr_getgregs.c: Rewritten. + * td_thr_set_event.c: Rewritten. + * td_thr_setfpregs.c: Rewritten. + * td_thr_setgregs.c: Rewritten. + * td_thr_tlsbase.c: Rewritten. + * td_thr_tsd.c: Rewritten. + * td_thr_validate.c: Rewritten. + * Makefile (distribute): Add them. + * fetch-value.c: New file. + * Makefile (libthread_db-routines): Add it. + + * thread_db.h (td_err_e): Comment fix. + +2003-08-05 Roland McGrath + + * thread_dbP.h (td_lookup): Add attribute_hidden to decl. + +2003-08-04 Roland McGrath + + * td_ta_clear_event.c (td_ta_clear_event): Fix sizes in ps_* calls. + +2003-06-23 Roland McGrath + + * proc_service.h: Cosmetic and comment fixes. + +2003-06-19 Roland McGrath + + * td_thr_event_enable.c (td_thr_event_enable): Use proper type `bool' + for value written into inferior's `report_events'. + +2003-03-18 Roland McGrath + + * td_thr_event_getmsg.c (td_thr_event_getmsg): Splice the thread out + of the ->nextevent linkage. + + * td_ta_event_getmsg.c (td_ta_event_getmsg): Runtime error instead of + assert for reading TD_EVENT_NONE. Clear the event buffer after + reading it. Add a sanity check for foo->nextevent = foo. + +2003-03-15 Roland McGrath + + * thread_db.h (td_err_e): Add TD_NOTLS and TD_TLSDEFER. + (td_thr_tlsbase): Declare it. + * td_thr_tlsbase.c: New file. + * Makefile (libthread_db-routines): Add it. + * Versions (libthread_db: GLIBC_2.3.3): New set, add td_thr_tlsbase. + * td_thr_tls_get_addr.c (td_thr_tls_get_addr): Use td_thr_tlsbase. + +2003-03-14 Roland McGrath + + * td_thr_tls_get_addr.c (td_thr_tls_get_addr): Use `header.' prefix. + +2003-03-10 Roland McGrath + + * td_ta_thr_iter.c (iterate_thread_list): Don't use `header.data.' + prefix for `struct pthread' members. + * td_thr_validate.c (check_thread_list): Likewise. + * td_thr_tls_get_addr.c (td_thr_tls_get_addr): Likewise. + +2003-03-03 Roland McGrath + + * td_thr_tls_get_addr.c (td_thr_tls_get_addr): Handle TLS_DTV_AT_TP. + +2003-02-15 Ulrich Drepper + + * td_symbol_list.c: New symbol name for SYM_PTHREAD_NTHREADS. + +2003-01-07 Jakub Jelinek + + * td_ta_event_getmsg.c: Include assert.h. + +-2003-01-05 Ulrich Drepper + + * Makefile (libthread_db.so-no-z-defs): Define. + +2003-01-03 Roland McGrath + + * td_thr_setgregs.c (td_thr_setgregs): *_BIT -> *_BITMASK + * td_thr_setfpregs.c (td_thr_setfpregs): Likewise. + * td_thr_get_info.c (td_thr_get_info): Likewise. + * td_thr_getgregs.c (td_thr_getgregs): Likewise. + * td_thr_getfpregs.c (td_thr_getfpregs): Likewise. + * td_ta_thr_iter.c (iterate_thread_list): Likewise. + +2002-12-12 Roland McGrath + + * td_ta_thr_iter.c (iterate_thread_list): Handle special case of + uninitialized __stack_user (zeros), hard-wire just the main thread. + + * td_thr_get_info.c (td_thr_get_info): Fix ti_lid initialization. + +2002-12-06 Roland McGrath + + * td_ta_event_getmsg.c (td_ta_event_getmsg): Write the NEXT pointer + into the inferior's __pthread_last_event variable, not a word from + an inferior address used in the parent. Pass the address of a + null word to ps_pdwrite, not a null pointer. + +2002-12-04 Roland McGrath + + * td_thr_get_info.c (td_thr_get_info): ti_tid is pthread_t, not a PID. + + * thread_db.h (td_thrinfo_t): Comment fix. + + * td_ta_map_lwp2thr.c: Moved to ../nptl/sysdeps/i386/. + +2002-12-04 Ulrich Drepper + + * td_ta_thr_iter.c (iterate_thread_list): At end of iteration read + pointer to the next element from inferior. + +2002-12-02 Roland McGrath + + * td_symbol_list.c (symbol_list_arr): pthread_keys -> __pthread_keys + + * td_ta_map_lwp2thr.c (td_ta_map_lwp2thr): Fetch inferior registers to + see its %gs value, not our own. diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/Makefile new file mode 100644 index 00000000..f9100219 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../ +top_builddir=../../ +include $(top_builddir)Rules.mak +all: libs +include Makefile.in +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/Makefile.in new file mode 100644 index 00000000..a3fc1cd7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/Makefile.in @@ -0,0 +1,69 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +subdirs += libpthread/nptl_db + +# Get the thread include dependencies and shared object name +CFLAGS-nptl_db := -DLIBPTHREAD_SO="\"libpthread.so.$(ABI_VERSION)\"" +CFLAGS-nptl_db += -I$(top_srcdir)libpthread/nptl -D_GNU_SOURCE +CFLAGS-nptl_db += -DIS_IN_libthread_db=1 -DNOT_IN_libc -std=gnu99 -I$(top_srcdir)ldso/include + +LDFLAGS-libthread_db.so := $(LDFLAGS_NOSTRIP) $(if $(call check_ld,--warn-unresolved-symbols),-Wl$(comma)--warn-unresolved-symbols) +LIBS-libthread_db.so := $(LIBS) + +libthread_db_FULL_NAME := libthread_db-$(VERSION).so + +libthread_db_DIR := $(top_srcdir)libpthread/nptl_db +libthread_db_OUT := $(top_builddir)libpthread/nptl_db + +libthread_db_SRC := $(wildcard $(libthread_db_DIR)/td_*.c) \ + $(libthread_db_DIR)/fetch-value.c + +libthread_db_OBJ := $(patsubst $(libthread_db_DIR)/%.c,$(libthread_db_OUT)/%.o,$(libthread_db_SRC)) + +libthread_db-so-y := $(libthread_db_OBJ:.o=.oS) +ifeq ($(DOPIC),y) +libthread_db-a-y := $(libthread_db-so-y) +else +libthread_db-a-y := $(libthread_db_OBJ) +endif + +libthread_db-multi-y := $(libthread_db_SRC) + +lib-a-$(PTHREADS_DEBUG_SUPPORT) += $(top_builddir)lib/libthread_db.a +lib-so-$(PTHREADS_DEBUG_SUPPORT) += $(top_builddir)lib/libthread_db.so +objclean-y += CLEAN_libpthread/nptl_db +headers-$(PTHREADS_DEBUG_SUPPORT) += $(nptl_db_headers) +headers_clean-y += HEADERCLEAN_libpthread/nptl_db + +ifeq ($(DOPIC),y) +$(top_builddir)lib/libthread_db.so: $(top_builddir)lib/libthread_db.a $(libc.depend) +else +$(top_builddir)lib/libthread_db.so: $(libthread_db_OUT)/libthread_db_so.a $(libc.depend) +endif + $(call link.so,$(libthread_db_FULL_NAME),1) + +$(libthread_db_OUT)/libthread_db_so.a: $(libthread_db-so-y) + $(Q)$(RM) $@ + $(do_strip) + $(do_ar) + +$(top_builddir)lib/libthread_db.a: $(libthread_db-a-y) | $(top_builddir)lib + $(Q)$(RM) $@ + $(do_strip) + $(do_ar) + +$(top_builddir)include/thread_db.h: + $(do_ln) $(call rel_srcdir)$(PTDIR)_db/$(@F) $@ + +nptl_db_headers:= $(top_builddir)include/thread_db.h + +HEADERCLEAN_libpthread/nptl_db: + $(do_rm) $(nptl_db_headers) + +CLEAN_libpthread/nptl_db: + $(do_rm) $(addprefix $(libthread_db_OUT)/*., o oS a) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/db_info.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/db_info.c new file mode 100644 index 00000000..5aec152d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/db_info.c @@ -0,0 +1,103 @@ +/* This file is included by pthread_create.c to define in libpthread + all the magic symbols required by libthread_db. + + Copyright (C) 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" +#include + +typedef struct pthread pthread; +typedef struct pthread_key_struct pthread_key_struct; +typedef struct pthread_key_data pthread_key_data; +typedef struct +{ + struct pthread_key_data data[PTHREAD_KEY_2NDLEVEL_SIZE]; +} +pthread_key_data_level2; + +typedef struct +{ + union dtv dtv[UINT32_MAX / 2 / sizeof (union dtv)]; /* No constant bound. */ +} dtv; + +typedef struct link_map link_map; + + +#define schedparam_sched_priority schedparam.sched_priority + +#define eventbuf_eventmask eventbuf.eventmask +#define eventbuf_eventmask_event_bits eventbuf.eventmask.event_bits + +#define DESC(name, offset, obj) \ + DB_DEFINE_DESC (name, 8 * sizeof (obj), 1, offset); +#define ARRAY_DESC(name, offset, obj) \ + DB_DEFINE_DESC (name, \ + 8 * sizeof (obj)[0], sizeof (obj) / sizeof (obj)[0], \ + offset); + +#if defined(TLS_TCB_AT_TP) +# define dtvp header.dtv +#elif defined(TLS_DTV_AT_TP) +/* Special case hack. If TLS_TCB_SIZE == 0 (on PowerPC), there is no TCB + containing the DTV at the TP, but actually the TCB lies behind the TP, + i.e. at the very end of the area covered by TLS_PRE_TCB_SIZE. */ +DESC (_thread_db_pthread_dtvp, + TLS_PRE_TCB_SIZE + offsetof (tcbhead_t, dtv) + - (TLS_TCB_SIZE == 0 ? sizeof (tcbhead_t) : 0), union dtv) +#endif + + +#define DB_STRUCT(type) \ + const uint32_t _thread_db_sizeof_##type = sizeof (type); +#define DB_STRUCT_FIELD(type, field) \ + DESC (_thread_db_##type##_##field, \ + offsetof (type, field), ((type *) 0)->field) +#define DB_STRUCT_ARRAY_FIELD(type, field) \ + ARRAY_DESC (_thread_db_##type##_##field, \ + offsetof (type, field), ((type *) 0)->field) +#define DB_VARIABLE(name) DESC (_thread_db_##name, 0, name) +#define DB_ARRAY_VARIABLE(name) ARRAY_DESC (_thread_db_##name, 0, name) +#define DB_SYMBOL(name) /* Nothing. */ +#define DB_FUNCTION(name) /* Nothing. */ +#include "structs.def" +#undef DB_STRUCT +#undef DB_STRUCT_FIELD +#undef DB_SYMBOL +#undef DB_FUNCTION +#undef DB_VARIABLE +#undef DESC + + + +#ifdef DB_THREAD_SELF +# ifdef DB_THREAD_SELF_INCLUDE +# include DB_THREAD_SELF_INCLUDE +# endif + +/* This macro is defined in the machine's tls.h using the three below. */ +# define CONST_THREAD_AREA(bits, value) \ + const uint32_t _thread_db_const_thread_area = (value); +# define REGISTER_THREAD_AREA(bits, regofs, scale) \ + DB_DEFINE_DESC (_thread_db_register##bits##_thread_area, \ + bits, (scale), (regofs)); +# define REGISTER(bits, size, regofs, bias) \ + DB_DEFINE_DESC (_thread_db_register##bits, size, (uint32_t)(bias), (regofs)); + +DB_THREAD_SELF +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/fetch-value.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/fetch-value.c new file mode 100644 index 00000000..0d9bb0eb --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/fetch-value.c @@ -0,0 +1,284 @@ +/* Helper routines for libthread_db. + Copyright (C) 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" +#include +#include + +td_err_e +_td_check_sizeof (td_thragent_t *ta, uint32_t *sizep, int sizep_name) +{ + if (*sizep == 0) + { + psaddr_t descptr; + ps_err_e err = td_lookup (ta->ph, sizep_name, &descptr); + if (err == PS_NOSYM) + return TD_NOCAPAB; + if (err == PS_OK) + err = ps_pdread (ta->ph, descptr, sizep, sizeof *sizep); + if (err != PS_OK) + return TD_ERR; + if (*sizep & 0xff000000U) + *sizep = bswap_32 (*sizep); + } + return TD_OK; +} + +td_err_e +_td_locate_field (td_thragent_t *ta, + db_desc_t desc, int descriptor_name, + psaddr_t idx, psaddr_t *address) +{ + uint32_t elemsize; + + if (DB_DESC_SIZE (desc) == 0) + { + /* Read the information about this field from the inferior. */ + psaddr_t descptr; + ps_err_e err = td_lookup (ta->ph, descriptor_name, &descptr); + if (err == PS_NOSYM) + return TD_NOCAPAB; + if (err == PS_OK) + err = ps_pdread (ta->ph, descptr, desc, DB_SIZEOF_DESC); + if (err != PS_OK) + return TD_ERR; + if (DB_DESC_SIZE (desc) == 0) + return TD_DBERR; + if (DB_DESC_SIZE (desc) & 0xff000000U) + { + /* Byte-swap these words, though we leave the size word + in native order as the handy way to distinguish. */ + DB_DESC_OFFSET (desc) = bswap_32 (DB_DESC_OFFSET (desc)); + DB_DESC_NELEM (desc) = bswap_32 (DB_DESC_NELEM (desc)); + } + } + + if (idx != 0 && idx - (psaddr_t) 0 > DB_DESC_NELEM (desc)) + /* This is an internal indicator to callers with nonzero IDX + that the IDX value is too big. */ + return TD_NOAPLIC; + + elemsize = DB_DESC_SIZE (desc); + if (elemsize & 0xff000000U) + elemsize = bswap_32 (elemsize); + + *address += (int32_t) DB_DESC_OFFSET (desc); + *address += (elemsize / 8 * (idx - (psaddr_t) 0)); + return TD_OK; +} + +td_err_e +_td_fetch_value (td_thragent_t *ta, + db_desc_t desc, int descriptor_name, + psaddr_t idx, psaddr_t address, + psaddr_t *result) +{ + ps_err_e err; + td_err_e terr = _td_locate_field (ta, desc, descriptor_name, idx, &address); + if (terr != TD_OK) + return terr; + + if (DB_DESC_SIZE (desc) == 8 || DB_DESC_SIZE (desc) == bswap_32 (8)) + { + uint8_t value; + err = ps_pdread (ta->ph, address, &value, sizeof value); + *result = (psaddr_t) 0 + value; + } + else if (DB_DESC_SIZE (desc) == 32) + { + uint32_t value; + err = ps_pdread (ta->ph, address, &value, sizeof value); + *result = (psaddr_t) 0 + value; + } + else if (DB_DESC_SIZE (desc) == 64) + { + uint64_t value; + if (sizeof (psaddr_t) < 8) + return TD_NOCAPAB; + err = ps_pdread (ta->ph, address, &value, sizeof value); + *result = (psaddr_t) 0 + value; + } + else if (DB_DESC_SIZE (desc) == bswap_32 (32)) + { + uint32_t value; + err = ps_pdread (ta->ph, address, &value, sizeof value); + value = bswap_32 (value); + *result = (psaddr_t) 0 + value; + } + else if (DB_DESC_SIZE (desc) == bswap_32 (64)) + { + uint64_t value; + if (sizeof (psaddr_t) < 8) + return TD_NOCAPAB; + err = ps_pdread (ta->ph, address, &value, sizeof value); + value = bswap_64 (value); + *result = (psaddr_t) 0 + value; + } + else + return TD_DBERR; + + return err == PS_OK ? TD_OK : TD_ERR; +} + + +td_err_e +_td_store_value (td_thragent_t *ta, + uint32_t desc[2], int descriptor_name, psaddr_t idx, + psaddr_t address, psaddr_t widened_value) +{ + ps_err_e err; + td_err_e terr = _td_locate_field (ta, desc, descriptor_name, idx, &address); + if (terr != TD_OK) + return terr; + + if (DB_DESC_SIZE (desc) == 8 || DB_DESC_SIZE (desc) == bswap_32 (8)) + { + uint8_t value = widened_value - (psaddr_t) 0; + err = ps_pdwrite (ta->ph, address, &value, sizeof value); + } + else if (DB_DESC_SIZE (desc) == 32) + { + uint32_t value = widened_value - (psaddr_t) 0; + err = ps_pdwrite (ta->ph, address, &value, sizeof value); + } + else if (DB_DESC_SIZE (desc) == 64) + { + uint64_t value = widened_value - (psaddr_t) 0; + if (sizeof (psaddr_t) < 8) + return TD_NOCAPAB; + err = ps_pdwrite (ta->ph, address, &value, sizeof value); + } + else if (DB_DESC_SIZE (desc) == bswap_32 (32)) + { + uint32_t value = widened_value - (psaddr_t) 0; + value = bswap_32 (value); + err = ps_pdwrite (ta->ph, address, &value, sizeof value); + } + else if (DB_DESC_SIZE (desc) == bswap_32 (64)) + { + uint64_t value = widened_value - (psaddr_t) 0; + if (sizeof (psaddr_t) < 8) + return TD_NOCAPAB; + value = bswap_64 (value); + err = ps_pdwrite (ta->ph, address, &value, sizeof value); + } + else + return TD_DBERR; + + return err == PS_OK ? TD_OK : TD_ERR; +} + +td_err_e +_td_fetch_value_local (td_thragent_t *ta, + db_desc_t desc, int descriptor_name, psaddr_t idx, + void *address, + psaddr_t *result) +{ + td_err_e terr = _td_locate_field (ta, desc, descriptor_name, idx, &address); + if (terr != TD_OK) + return terr; + + if (DB_DESC_SIZE (desc) == 8 || DB_DESC_SIZE (desc) == bswap_32 (8)) + { + uint8_t value; + memcpy (&value, address, sizeof value); + *result = (psaddr_t) 0 + value; + } + else if (DB_DESC_SIZE (desc) == 32) + { + uint32_t value; + memcpy (&value, address, sizeof value); + *result = (psaddr_t) 0 + value; + } + else if (DB_DESC_SIZE (desc) == 64) + { + uint64_t value; + if (sizeof (psaddr_t) < 8) + return TD_NOCAPAB; + memcpy (&value, address, sizeof value); + *result = (psaddr_t) 0 + value; + } + else if (DB_DESC_SIZE (desc) == bswap_32 (32)) + { + uint32_t value; + memcpy (&value, address, sizeof value); + value = bswap_32 (value); + *result = (psaddr_t) 0 + value; + } + else if (DB_DESC_SIZE (desc) == bswap_32 (64)) + { + uint64_t value; + if (sizeof (psaddr_t) < 8) + return TD_NOCAPAB; + memcpy (&value, address, sizeof value); + value = bswap_64 (value); + *result = (psaddr_t) 0 + value; + } + else + return TD_DBERR; + + return TD_OK; +} + + +td_err_e +_td_store_value_local (td_thragent_t *ta, + uint32_t desc[2], int descriptor_name, psaddr_t idx, + void *address, psaddr_t widened_value) +{ + td_err_e terr = _td_locate_field (ta, desc, descriptor_name, idx, &address); + if (terr != TD_OK) + return terr; + + if (DB_DESC_SIZE (desc) == 8 || DB_DESC_SIZE (desc) == bswap_32 (8)) + { + uint8_t value = widened_value - (psaddr_t) 0; + memcpy (address, &value, sizeof value); + } + else if (DB_DESC_SIZE (desc) == 32) + { + uint32_t value = widened_value - (psaddr_t) 0; + memcpy (address, &value, sizeof value); + } + else if (DB_DESC_SIZE (desc) == 64) + { + uint64_t value = widened_value - (psaddr_t) 0; + if (sizeof (psaddr_t) < 8) + return TD_NOCAPAB; + memcpy (address, &value, sizeof value); + } + else if (DB_DESC_SIZE (desc) == bswap_32 (32)) + { + uint32_t value = widened_value - (psaddr_t) 0; + value = bswap_32 (value); + memcpy (address, &value, sizeof value); + } + else if (DB_DESC_SIZE (desc) == bswap_32 (64)) + { + uint64_t value = widened_value - (psaddr_t) 0; + if (sizeof (psaddr_t) < 8) + return TD_NOCAPAB; + value = bswap_64 (value); + memcpy (address, &value, sizeof value); + } + else + return TD_DBERR; + + return TD_OK; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/proc_service.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/proc_service.h new file mode 100644 index 00000000..d49e87ab --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/proc_service.h @@ -0,0 +1,87 @@ +/* Callback interface for libthread_db, functions users must define. + Copyright (C) 1999,2002,2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* The definitions in this file must correspond to those in the debugger. */ +#include + +/* Functions in this interface return one of these status codes. */ +typedef enum +{ + PS_OK, /* Generic "call succeeded". */ + PS_ERR, /* Generic error. */ + PS_BADPID, /* Bad process handle. */ + PS_BADLID, /* Bad LWP identifier. */ + PS_BADADDR, /* Bad address. */ + PS_NOSYM, /* Could not find given symbol. */ + PS_NOFREGS /* FPU register set not available for given LWP. */ +} ps_err_e; + + +/* This type is opaque in this interface. + It's defined by the user of libthread_db. */ +struct ps_prochandle; + + +/* Read or write process memory at the given address. */ +extern ps_err_e ps_pdread (struct ps_prochandle *, + psaddr_t, void *, size_t); +extern ps_err_e ps_pdwrite (struct ps_prochandle *, + psaddr_t, const void *, size_t); +extern ps_err_e ps_ptread (struct ps_prochandle *, + psaddr_t, void *, size_t); +extern ps_err_e ps_ptwrite (struct ps_prochandle *, + psaddr_t, const void *, size_t); + + +/* Get and set the given LWP's general or FPU register set. */ +extern ps_err_e ps_lgetregs (struct ps_prochandle *, + lwpid_t, prgregset_t); +extern ps_err_e ps_lsetregs (struct ps_prochandle *, + lwpid_t, const prgregset_t); +extern ps_err_e ps_lgetfpregs (struct ps_prochandle *, + lwpid_t, prfpregset_t *); +extern ps_err_e ps_lsetfpregs (struct ps_prochandle *, + lwpid_t, const prfpregset_t *); + +/* Return the PID of the process. */ +extern pid_t ps_getpid (struct ps_prochandle *); + +/* Fetch the special per-thread address associated with the given LWP. + This call is only used on a few platforms (most use a normal register). + The meaning of the `int' parameter is machine-dependent. */ +extern ps_err_e ps_get_thread_area (const struct ps_prochandle *, + lwpid_t, int, psaddr_t *); + + +/* Look up the named symbol in the named DSO in the symbol tables + associated with the process being debugged, filling in *SYM_ADDR + with the corresponding run-time address. */ +extern ps_err_e ps_pglobal_lookup (struct ps_prochandle *, + const char *object_name, + const char *sym_name, + psaddr_t *sym_addr); + + +/* Stop or continue the entire process. */ +extern ps_err_e ps_pstop (const struct ps_prochandle *); +extern ps_err_e ps_pcontinue (const struct ps_prochandle *); + +/* Stop or continue the given LWP alone. */ +extern ps_err_e ps_lstop (const struct ps_prochandle *, lwpid_t); +extern ps_err_e ps_lcontinue (const struct ps_prochandle *, lwpid_t); diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/structs.def b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/structs.def new file mode 100644 index 00000000..1572ad69 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/structs.def @@ -0,0 +1,88 @@ +/* List of types and symbols in libpthread examined by libthread_db. + Copyright (C) 2003, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef DB_STRUCT_ARRAY_FIELD +# define DB_STRUCT_ARRAY_FIELD(type, field) DB_STRUCT_FIELD (type, field) +# define DB_ARRAY_VARIABLE(name) DB_VARIABLE (name) +# define STRUCTS_DEF_DEFAULTS 1 +#endif + +DB_STRUCT (pthread) +DB_STRUCT_FIELD (pthread, list) +DB_STRUCT_FIELD (pthread, report_events) +DB_STRUCT_FIELD (pthread, tid) +DB_STRUCT_FIELD (pthread, start_routine) +DB_STRUCT_FIELD (pthread, cancelhandling) +DB_STRUCT_FIELD (pthread, schedpolicy) +DB_STRUCT_FIELD (pthread, schedparam_sched_priority) +DB_STRUCT_FIELD (pthread, specific) +DB_STRUCT_FIELD (pthread, eventbuf) +DB_STRUCT_FIELD (pthread, eventbuf_eventmask) +DB_STRUCT_ARRAY_FIELD (pthread, eventbuf_eventmask_event_bits) +DB_STRUCT_FIELD (pthread, nextevent) + +DB_STRUCT (list_t) +DB_STRUCT_FIELD (list_t, next) +DB_STRUCT_FIELD (list_t, prev) + +DB_STRUCT (td_thr_events_t) +DB_STRUCT_ARRAY_FIELD (td_thr_events_t, event_bits) + +DB_STRUCT (td_eventbuf_t) +DB_STRUCT_FIELD (td_eventbuf_t, eventnum) +DB_STRUCT_FIELD (td_eventbuf_t, eventdata) + +DB_SYMBOL (stack_used) +DB_SYMBOL (__stack_user) +DB_SYMBOL (nptl_version) +DB_FUNCTION (__nptl_create_event) +DB_FUNCTION (__nptl_death_event) +DB_SYMBOL (__nptl_threads_events) +DB_VARIABLE (__nptl_nthreads) +DB_VARIABLE (__nptl_last_event) + +DB_ARRAY_VARIABLE (__pthread_keys) +DB_STRUCT (pthread_key_struct) +DB_STRUCT_FIELD (pthread_key_struct, seq) +DB_STRUCT_FIELD (pthread_key_struct, destr) + +DB_STRUCT (pthread_key_data) +DB_STRUCT_FIELD (pthread_key_data, seq) +DB_STRUCT_FIELD (pthread_key_data, data) +DB_STRUCT (pthread_key_data_level2) +DB_STRUCT_ARRAY_FIELD (pthread_key_data_level2, data) + +#if USE_TLS +DB_STRUCT_FIELD (link_map, l_tls_modid) +#endif + +#if !defined IS_IN_libpthread || USE_TLS +DB_STRUCT_ARRAY_FIELD (dtv, dtv) +# define pointer_val pointer.val /* Field of anonymous struct in dtv_t. */ +DB_STRUCT_FIELD (dtv_t, pointer_val) +#endif +#if !defined IS_IN_libpthread || (defined TLS_TCB_AT_TP && TLS_TCB_AT_TP) +DB_STRUCT_FIELD (pthread, dtvp) +#endif + +#ifdef STRUCTS_DEF_DEFAULTS +# undef DB_STRUCT_ARRAY_FIELD +# undef DB_ARRAY_VARIABLE +# undef STRUCTS_DEF_DEFAULTS +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_init.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_init.c new file mode 100644 index 00000000..946ff724 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_init.c @@ -0,0 +1,32 @@ +/* Initialization function of thread debugger support library. + Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + +int __td_debug; + + +td_err_e +td_init (void) +{ + /* XXX We have to figure out what has to be done. */ + LOG ("td_init"); + return TD_OK; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_log.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_log.c new file mode 100644 index 00000000..52212a0e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_log.c @@ -0,0 +1,32 @@ +/* Noop, left for historical reasons. + Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_log (void) +{ + /* This interface is deprecated in the Sun interface. We provide it + for compatibility but don't do anything ourself. We might in + future do some logging if this seems reasonable. */ + LOG ("td_log"); + return TD_OK; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_symbol_list.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_symbol_list.c new file mode 100644 index 00000000..04aed678 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_symbol_list.c @@ -0,0 +1,87 @@ +/* Return list of symbols the library can request. + Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2001. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#ifndef __UCLIBC__ +#include +#endif +#include "thread_dbP.h" + + +#ifdef HAVE_ASM_GLOBAL_DOT_NAME +# define DOT "." /* PPC64 requires . prefix on code symbols. */ +#else +# define DOT /* No prefix. */ +#endif + +static const char *symbol_list_arr[] = +{ +# define DB_STRUCT(type) \ + [SYM_SIZEOF_##type] = "_thread_db_sizeof_" #type, +# define DB_STRUCT_FIELD(type, field) \ + [SYM_##type##_FIELD_##field] = "_thread_db_" #type "_" #field, +# define DB_SYMBOL(name) \ + [SYM_##name] = #name, +# define DB_FUNCTION(name) \ + [SYM_##name] = DOT #name, +# define DB_VARIABLE(name) \ + [SYM_##name] = #name, \ + [SYM_DESC_##name] = "_thread_db_" #name, +# include "structs.def" +# undef DB_STRUCT +# undef DB_FUNCTION +# undef DB_SYMBOL +# undef DB_VARIABLE + + [SYM_TH_UNIQUE_CONST_THREAD_AREA] = "_thread_db_const_thread_area", + [SYM_TH_UNIQUE_REGISTER64] = "_thread_db_register64", + [SYM_TH_UNIQUE_REGISTER32] = "_thread_db_register32", + [SYM_TH_UNIQUE_REGISTER32_THREAD_AREA] = "_thread_db_register32_thread_area", + [SYM_TH_UNIQUE_REGISTER64_THREAD_AREA] = "_thread_db_register64_thread_area", + + [SYM_NUM_MESSAGES] = NULL +}; + + +const char ** +td_symbol_list (void) +{ + return symbol_list_arr; +} + + +ps_err_e +td_lookup (struct ps_prochandle *ps, int idx, psaddr_t *sym_addr) +{ + ps_err_e result; + assert (idx >= 0 && idx < SYM_NUM_MESSAGES); + result = ps_pglobal_lookup (ps, LIBPTHREAD_SO, symbol_list_arr[idx], + sym_addr); + +#ifdef HAVE_ASM_GLOBAL_DOT_NAME + /* For PowerPC, 64-bit uses dot symbols but 32-bit does not. + We could be a 64-bit libthread_db debugging a 32-bit libpthread. */ + if (result == PS_NOSYM && symbol_list_arr[idx][0] == '.') + result = ps_pglobal_lookup (ps, LIBPTHREAD_SO, &symbol_list_arr[idx][1], + sym_addr); +#endif + + return result; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_ta_clear_event.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_ta_clear_event.c new file mode 100644 index 00000000..b20a0abb --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_ta_clear_event.c @@ -0,0 +1,77 @@ +/* Globally disable events. + Copyright (C) 1999, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_ta_clear_event (const td_thragent_t *ta_arg, td_thr_events_t *event) +{ + td_thragent_t *const ta = (td_thragent_t *) ta_arg; + td_err_e err; + psaddr_t eventmask = 0; + void *copy = NULL; + + LOG ("td_ta_clear_event"); + + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + + /* Fetch the old event mask from the inferior and modify it in place. */ + err = DB_GET_SYMBOL (eventmask, ta, __nptl_threads_events); + if (err == TD_OK) + err = DB_GET_STRUCT (copy, ta, eventmask, td_thr_events_t); + if (err == TD_OK) + { + uint32_t idx; + for (idx = 0; idx < TD_EVENTSIZE; ++idx) + { + psaddr_t word; + uint32_t mask; + err = DB_GET_FIELD_LOCAL (word, ta, copy, + td_thr_events_t, event_bits, idx); + if (err != TD_OK) + break; + mask = (uintptr_t) word; + mask &= ~event->event_bits[idx]; + word = (psaddr_t) (uintptr_t) mask; + err = DB_PUT_FIELD_LOCAL (ta, copy, + td_thr_events_t, event_bits, idx, word); + if (err != TD_OK) + break; + } + if (err == TD_NOAPLIC) + { + err = TD_OK; + while (idx < TD_EVENTSIZE) + if (event->event_bits[idx++] != 0) + { + err = TD_NOEVENT; + break; + } + } + if (err == TD_OK) + /* Now write it back to the inferior. */ + err = DB_PUT_STRUCT (ta, eventmask, td_thr_events_t, copy); + } + + return err; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_ta_delete.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_ta_delete.c new file mode 100644 index 00000000..57b90e57 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_ta_delete.c @@ -0,0 +1,42 @@ +/* Detach to target process. + Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#include "thread_dbP.h" + + +td_err_e +td_ta_delete (td_thragent_t *ta) +{ + LOG ("td_ta_delete"); + + /* Safety check. Note that the test will also fail for TA == NULL. */ + if (!ta_ok (ta)) + return TD_BADTA; + + /* Remove the handle from the list. */ + list_del (&ta->list); + + /* The handle was allocated in `td_ta_new'. */ + free (ta); + + return TD_OK; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_ta_enable_stats.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_ta_enable_stats.c new file mode 100644 index 00000000..ec7014ad --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_ta_enable_stats.c @@ -0,0 +1,35 @@ +/* Enable collection of statistics for process. + Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_ta_enable_stats (const td_thragent_t *ta, int enable) +{ + /* XXX We have to figure out what has to be done. */ + LOG ("td_ta_enable_stats"); + + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + + return TD_OK; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_ta_event_addr.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_ta_event_addr.c new file mode 100644 index 00000000..45c6b113 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_ta_event_addr.c @@ -0,0 +1,61 @@ +/* Get event address. + Copyright (C) 1999,2001,2002,2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_ta_event_addr (const td_thragent_t *ta_arg, + td_event_e event, td_notify_t *addr) +{ + td_thragent_t *const ta = (td_thragent_t *) ta_arg; + td_err_e err; + psaddr_t taddr = NULL; + + LOG ("td_ta_event_addr"); + + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + + switch (event) + { + case TD_CREATE: + err = DB_GET_SYMBOL (taddr, ta, __nptl_create_event); + break; + + case TD_DEATH: + err = DB_GET_SYMBOL (taddr, ta, __nptl_death_event); + break; + + default: + /* Event cannot be handled. */ + return TD_NOEVENT; + } + + if (err == TD_OK) + { + /* Success, we got the address. */ + addr->type = NOTIFY_BPT; + addr->u.bptaddr = taddr; + } + + return err; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_ta_event_getmsg.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_ta_event_getmsg.c new file mode 100644 index 00000000..d3b46bd5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_ta_event_getmsg.c @@ -0,0 +1,105 @@ +/* Retrieve event. + Copyright (C) 1999, 2001, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +#include "thread_dbP.h" + + +td_err_e +td_ta_event_getmsg (const td_thragent_t *ta_arg, td_event_msg_t *msg) +{ + td_thragent_t *const ta = (td_thragent_t *) ta_arg; + td_err_e err; + psaddr_t eventbuf, eventnum, eventdata; + psaddr_t thp, next; + void *copy = NULL; + + /* XXX I cannot think of another way but using a static variable. */ + /* XXX Use at least __thread once it is possible. */ + static td_thrhandle_t th; + + LOG ("td_thr_event_getmsg"); + + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + + /* Get the pointer to the thread descriptor with the last event. */ + err = DB_GET_VALUE (thp, ta, __nptl_last_event, 0); + if (err != TD_OK) + return err; + + if (thp == 0) + /* Nothing waiting. */ + return TD_NOMSG; + + /* Copy the event message buffer in from the inferior. */ + err = DB_GET_FIELD_ADDRESS (eventbuf, ta, thp, pthread, eventbuf, 0); + if (err == TD_OK) + err = DB_GET_STRUCT (copy, ta, eventbuf, td_eventbuf_t); + if (err != TD_OK) + return err; + + /* Read the event details from the target thread. */ + err = DB_GET_FIELD_LOCAL (eventnum, ta, copy, td_eventbuf_t, eventnum, 0); + if (err != TD_OK) + return err; + /* If the structure is on the list there better be an event recorded. */ + if ((int) (uintptr_t) eventnum == TD_EVENT_NONE) + return TD_DBERR; + + /* Fill the user's data structure. */ + err = DB_GET_FIELD_LOCAL (eventdata, ta, copy, td_eventbuf_t, eventdata, 0); + if (err != TD_OK) + return err; + + /* Generate the thread descriptor. */ + th.th_ta_p = (td_thragent_t *) ta; + th.th_unique = thp; + + /* Fill the user's data structure. */ + msg->msg.data = (uintptr_t) eventdata; + msg->event = (uintptr_t) eventnum; + msg->th_p = &th; + + /* And clear the event message in the target. */ + memset (copy, 0, ta->ta_sizeof_td_eventbuf_t); + err = DB_PUT_STRUCT (ta, eventbuf, td_eventbuf_t, copy); + if (err != TD_OK) + return err; + + /* Get the pointer to the next descriptor with an event. */ + err = DB_GET_FIELD (next, ta, thp, pthread, nextevent, 0); + if (err != TD_OK) + return err; + + /* Store the pointer in the list head variable. */ + err = DB_PUT_VALUE (ta, __nptl_last_event, 0, next); + if (err != TD_OK) + return err; + + if (next != 0) + /* Clear the next pointer in the current descriptor. */ + err = DB_PUT_FIELD (ta, thp, pthread, nextevent, 0, 0); + + return err; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_ta_get_nthreads.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_ta_get_nthreads.c new file mode 100644 index 00000000..ffe78bd5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_ta_get_nthreads.c @@ -0,0 +1,42 @@ +/* Get the number of threads in the process. + Copyright (C) 1999,2001,2002,2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + +td_err_e +td_ta_get_nthreads (const td_thragent_t *ta_arg, int *np) +{ + td_thragent_t *const ta = (td_thragent_t *) ta_arg; + td_err_e err; + psaddr_t n; + + LOG ("td_ta_get_nthreads"); + + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + + /* Access the variable in the inferior that tells us. */ + err = DB_GET_VALUE (n, ta, __nptl_nthreads, 0); + if (err == TD_OK) + *np = (uintptr_t) n; + + return err; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_ta_get_ph.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_ta_get_ph.c new file mode 100644 index 00000000..04e01fb7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_ta_get_ph.c @@ -0,0 +1,36 @@ +/* Get external process handle. + Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_ta_get_ph (const td_thragent_t *ta, struct ps_prochandle **ph) +{ + LOG ("td_ta_get_ph"); + + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + + *ph = ta->ph; + + return TD_OK; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_ta_get_stats.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_ta_get_stats.c new file mode 100644 index 00000000..d5d879c3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_ta_get_stats.c @@ -0,0 +1,35 @@ +/* Retrieve statistics for process. + Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_ta_get_stats (const td_thragent_t *ta, td_ta_stats_t *statsp) +{ + /* XXX We have to figure out what has to be done. */ + LOG ("td_ta_get_stats"); + + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + + return TD_OK; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_ta_map_id2thr.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_ta_map_id2thr.c new file mode 100644 index 00000000..189a6717 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_ta_map_id2thr.c @@ -0,0 +1,38 @@ +/* Map thread ID to thread handle. + Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_ta_map_id2thr (const td_thragent_t *ta, pthread_t pt, td_thrhandle_t *th) +{ + LOG ("td_ta_map_id2thr"); + + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + + /* Create the `td_thrhandle_t' object. */ + th->th_ta_p = (td_thragent_t *) ta; + th->th_unique = (psaddr_t) pt; + + return TD_OK; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_ta_map_lwp2thr.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_ta_map_lwp2thr.c new file mode 100644 index 00000000..acfa0fd8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_ta_map_lwp2thr.c @@ -0,0 +1,178 @@ +/* Which thread is running on an LWP? + Copyright (C) 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" +#include +#include +#include + + +td_err_e +td_ta_map_lwp2thr (const td_thragent_t *ta_arg, + lwpid_t lwpid, td_thrhandle_t *th) +{ + td_thragent_t *const ta = (td_thragent_t *) ta_arg; + ps_err_e err; + td_err_e terr; + prgregset_t regs; + psaddr_t addr; + + LOG ("td_ta_map_lwp2thr"); + + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + + if (ta->ta_howto == ta_howto_unknown) + { + /* We need to read in from the inferior the instructions what to do. */ + psaddr_t howto; + + err = td_lookup (ta->ph, SYM_TH_UNIQUE_CONST_THREAD_AREA, &howto); + if (err == PS_OK) + { + err = ps_pdread (ta->ph, howto, + &ta->ta_howto_data.const_thread_area, + sizeof ta->ta_howto_data.const_thread_area); + if (err != PS_OK) + return TD_ERR; + ta->ta_howto = ta_howto_const_thread_area; + if (ta->ta_howto_data.const_thread_area & 0xff000000U) + ta->ta_howto_data.const_thread_area + = bswap_32 (ta->ta_howto_data.const_thread_area); + } + else + { + switch (sizeof (regs[0])) + { + case 8: + err = td_lookup (ta->ph, SYM_TH_UNIQUE_REGISTER64, &howto); + if (err == PS_OK) + ta->ta_howto = ta_howto_reg; + else if (err == PS_NOSYM) + { + err = td_lookup (ta->ph, + SYM_TH_UNIQUE_REGISTER64_THREAD_AREA, + &howto); + if (err == PS_OK) + ta->ta_howto = ta_howto_reg_thread_area; + } + break; + + case 4: + err = td_lookup (ta->ph, SYM_TH_UNIQUE_REGISTER32, &howto); + if (err == PS_OK) + ta->ta_howto = ta_howto_reg; + else if (err == PS_NOSYM) + { + err = td_lookup (ta->ph, + SYM_TH_UNIQUE_REGISTER32_THREAD_AREA, + &howto); + if (err == PS_OK) + ta->ta_howto = ta_howto_reg_thread_area; + } + break; + + default: + abort (); + return TD_DBERR; + } + + if (err != PS_OK) + return TD_DBERR; + + /* For either of these methods we read in the same descriptor. */ + err = ps_pdread (ta->ph, howto, + ta->ta_howto_data.reg, DB_SIZEOF_DESC); + if (err != PS_OK) + return TD_ERR; + if (DB_DESC_SIZE (ta->ta_howto_data.reg) == 0) + return TD_DBERR; + if (DB_DESC_SIZE (ta->ta_howto_data.reg) & 0xff000000U) + { + /* Byte-swap these words, though we leave the size word + in native order as the handy way to distinguish. */ + DB_DESC_OFFSET (ta->ta_howto_data.reg) + = bswap_32 (DB_DESC_OFFSET (ta->ta_howto_data.reg)); + DB_DESC_NELEM (ta->ta_howto_data.reg) + = bswap_32 (DB_DESC_NELEM (ta->ta_howto_data.reg)); + } + } + } + + switch (ta->ta_howto) + { + case ta_howto_unknown: + return TD_DBERR; + + default: + return TD_DBERR; + + case ta_howto_reg: + /* On most machines, we are just looking at a register. */ + if (ps_lgetregs (ta->ph, lwpid, regs) != PS_OK) + return TD_ERR; + terr = _td_fetch_value_local (ta, ta->ta_howto_data.reg, -1, + 0, regs, &addr); + if (terr != TD_OK) + return terr; + /* In this descriptor the nelem word is overloaded as the bias. */ + addr += (int32_t) DB_DESC_NELEM (ta->ta_howto_data.reg); + th->th_unique = addr; + break; + + case ta_howto_const_thread_area: + /* Some hosts don't have this call and this case won't be used. */ +# pragma weak ps_get_thread_area + if (&ps_get_thread_area == NULL) + return TD_NOCAPAB; + + /* A la x86-64, there is a constant magic index for get_thread_area. */ + if (ps_get_thread_area (ta->ph, lwpid, + ta->ta_howto_data.const_thread_area, + &th->th_unique) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + break; + + case ta_howto_reg_thread_area: + if (&ps_get_thread_area == NULL) + return TD_NOCAPAB; + + /* A la i386, there is a register with an index for get_thread_area. */ + if (ps_lgetregs (ta->ph, lwpid, regs) != PS_OK) + return TD_ERR; + terr = _td_fetch_value_local (ta, ta->ta_howto_data.reg_thread_area, -1, + 0, regs, &addr); + if (terr != TD_OK) + return terr; + /* In this descriptor the nelem word is overloaded as scale factor. */ + if (ps_get_thread_area + (ta->ph, lwpid, + ((addr - (psaddr_t) 0) + >> DB_DESC_NELEM (ta->ta_howto_data.reg_thread_area)), + &th->th_unique) != PS_OK) + return TD_ERR; /* XXX Other error value? */ + break; + } + + /* Found it. Now complete the `td_thrhandle_t' object. */ + th->th_ta_p = (td_thragent_t *) ta; + + return TD_OK; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_ta_new.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_ta_new.c new file mode 100644 index 00000000..f84049af --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_ta_new.c @@ -0,0 +1,65 @@ +/* Attach to target process. + Copyright (C) 1999,2001,2002,2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + +#include "thread_dbP.h" + + +/* Datatype for the list of known thread agents. Normally there will + be exactly one so we don't spend much though on making it fast. */ +LIST_HEAD (__td_agent_list); + + +td_err_e +td_ta_new (struct ps_prochandle *ps, td_thragent_t **ta) +{ + psaddr_t versaddr; + char versbuf[sizeof (VERSION)]; + + LOG ("td_ta_new"); + + /* Check whether the versions match. */ + if (td_lookup (ps, SYM_nptl_version, &versaddr) != PS_OK) + return TD_NOLIBTHREAD; + if (ps_pdread (ps, versaddr, versbuf, sizeof (versbuf)) != PS_OK) + return TD_ERR; + + if (memcmp (versbuf, VERSION, sizeof VERSION) != 0) + /* Not the right version. */ + return TD_VERSION; + + /* Fill in the appropriate information. */ + *ta = (td_thragent_t *) calloc (1, sizeof (td_thragent_t)); + if (*ta == NULL) + return TD_MALLOC; + + /* Store the proc handle which we will pass to the callback functions + back into the debugger. */ + (*ta)->ph = ps; + + /* Now add the new agent descriptor to the list. */ + list_add (&(*ta)->list, &__td_agent_list); + + return TD_OK; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_ta_reset_stats.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_ta_reset_stats.c new file mode 100644 index 00000000..ea59d2cd --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_ta_reset_stats.c @@ -0,0 +1,35 @@ +/* Reset statistics. + Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_ta_reset_stats (const td_thragent_t *ta) +{ + /* XXX We have to figure out what has to be done. */ + LOG ("td_ta_reset_stats"); + + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + + return TD_OK; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_ta_set_event.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_ta_set_event.c new file mode 100644 index 00000000..fcafba54 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_ta_set_event.c @@ -0,0 +1,77 @@ +/* Globally enable events. + Copyright (C) 1999,2001,2002,2003,2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_ta_set_event (const td_thragent_t *ta_arg, td_thr_events_t *event) +{ + td_thragent_t *const ta = (td_thragent_t *) ta_arg; + td_err_e err; + psaddr_t eventmask = 0; + void *copy = NULL; + + LOG ("td_ta_set_event"); + + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + + /* Fetch the old event mask from the inferior and modify it in place. */ + err = DB_GET_SYMBOL (eventmask, ta, __nptl_threads_events); + if (err == TD_OK) + err = DB_GET_STRUCT (copy, ta, eventmask, td_thr_events_t); + if (err == TD_OK) + { + uint32_t idx; + for (idx = 0; idx < TD_EVENTSIZE; ++idx) + { + psaddr_t word; + uint32_t mask; + err = DB_GET_FIELD_LOCAL (word, ta, copy, + td_thr_events_t, event_bits, idx); + if (err != TD_OK) + break; + mask = (uintptr_t) word; + mask |= event->event_bits[idx]; + word = (psaddr_t) (uintptr_t) mask; + err = DB_PUT_FIELD_LOCAL (ta, copy, + td_thr_events_t, event_bits, idx, word); + if (err != TD_OK) + break; + } + if (err == TD_NOAPLIC) + { + err = TD_OK; + while (idx < TD_EVENTSIZE) + if (event->event_bits[idx++] != 0) + { + err = TD_NOEVENT; + break; + } + } + if (err == TD_OK) + /* Now write it back to the inferior. */ + err = DB_PUT_STRUCT (ta, eventmask, td_thr_events_t, copy); + } + + return err; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_ta_setconcurrency.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_ta_setconcurrency.c new file mode 100644 index 00000000..8552ffbe --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_ta_setconcurrency.c @@ -0,0 +1,35 @@ +/* Set suggested concurrency level for process. + Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_ta_setconcurrency (const td_thragent_t *ta, int level) +{ + /* This is something LinuxThreads does not need to support. */ + LOG ("td_ta_setconcurrency"); + + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + + return TD_NOCAPAB; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_ta_thr_iter.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_ta_thr_iter.c new file mode 100644 index 00000000..66e43766 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_ta_thr_iter.c @@ -0,0 +1,148 @@ +/* Iterate over a process's threads. + Copyright (C) 1999,2000,2001,2002,2003,2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +static td_err_e +iterate_thread_list (td_thragent_t *ta, td_thr_iter_f *callback, + void *cbdata_p, td_thr_state_e state, int ti_pri, + psaddr_t head, int fake_empty) +{ + td_err_e err; + psaddr_t next, ofs; + void *copy; + + /* Test the state. + XXX This is incomplete. Normally this test should be in the loop. */ + if (state != TD_THR_ANY_STATE) + return TD_OK; + + err = DB_GET_FIELD (next, ta, head, list_t, next, 0); + if (err != TD_OK) + return err; + + if (next == 0 && fake_empty) + { + /* __pthread_initialize_minimal has not run. + There is just the main thread to return. */ + td_thrhandle_t th; + err = td_ta_map_lwp2thr (ta, ps_getpid (ta->ph), &th); + if (err == TD_OK) + err = callback (&th, cbdata_p) != 0 ? TD_DBERR : TD_OK; + return err; + } + + /* Cache the offset from struct pthread to its list_t member. */ + err = DB_GET_FIELD_ADDRESS (ofs, ta, 0, pthread, list, 0); + if (err != TD_OK) + return err; + + if (ta->ta_sizeof_pthread == 0) + { + err = _td_check_sizeof (ta, &ta->ta_sizeof_pthread, SYM_SIZEOF_pthread); + if (err != TD_OK) + return err; + } + copy = __alloca (ta->ta_sizeof_pthread); + + while (next != head) + { + psaddr_t addr, schedpolicy, schedprio; + + addr = next - (ofs - (psaddr_t) 0); + if (next == 0 || addr == 0) /* Sanity check. */ + return TD_DBERR; + + /* Copy the whole descriptor in once so we can access the several + fields locally. Excess copying in one go is much better than + multiple ps_pdread calls. */ + if (ps_pdread (ta->ph, addr, copy, ta->ta_sizeof_pthread) != PS_OK) + return TD_ERR; + + err = DB_GET_FIELD_LOCAL (schedpolicy, ta, copy, pthread, + schedpolicy, 0); + if (err != TD_OK) + break; + err = DB_GET_FIELD_LOCAL (schedprio, ta, copy, pthread, + schedparam_sched_priority, 0); + if (err != TD_OK) + break; + + /* Now test whether this thread matches the specified conditions. */ + + /* Only if the priority level is as high or higher. */ + int descr_pri = ((uintptr_t) schedpolicy == SCHED_OTHER + ? 0 : (uintptr_t) schedprio); + if (descr_pri >= ti_pri) + { + /* Yep, it matches. Call the callback function. */ + td_thrhandle_t th; + th.th_ta_p = (td_thragent_t *) ta; + th.th_unique = addr; + if (callback (&th, cbdata_p) != 0) + return TD_DBERR; + } + + /* Get the pointer to the next element. */ + err = DB_GET_FIELD_LOCAL (next, ta, copy + (ofs - (psaddr_t) 0), list_t, + next, 0); + if (err != TD_OK) + break; + } + + return err; +} + + +td_err_e +td_ta_thr_iter (const td_thragent_t *ta_arg, td_thr_iter_f *callback, + void *cbdata_p, td_thr_state_e state, int ti_pri, + sigset_t *ti_sigmask_p, unsigned int ti_user_flags) +{ + td_thragent_t *const ta = (td_thragent_t *) ta_arg; + td_err_e err; + psaddr_t list = 0; + + LOG ("td_ta_thr_iter"); + + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + + /* The thread library keeps two lists for the running threads. One + list contains the thread which are using user-provided stacks + (this includes the main thread) and the other includes the + threads for which the thread library allocated the stacks. We + have to iterate over both lists separately. We start with the + list of threads with user-defined stacks. */ + + err = DB_GET_SYMBOL (list, ta, __stack_user); + if (err == TD_OK) + err = iterate_thread_list (ta, callback, cbdata_p, state, ti_pri, list, 1); + + /* And the threads with stacks allocated by the implementation. */ + if (err == TD_OK) + err = DB_GET_SYMBOL (list, ta, stack_used); + if (err == TD_OK) + err = iterate_thread_list (ta, callback, cbdata_p, state, ti_pri, list, 0); + + return err; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_ta_tsd_iter.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_ta_tsd_iter.c new file mode 100644 index 00000000..9cfb1e8d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_ta_tsd_iter.c @@ -0,0 +1,81 @@ +/* Iterate over a process's thread-specific data. + Copyright (C) 1999,2000,2001,2002,2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" +#include + +td_err_e +td_ta_tsd_iter (const td_thragent_t *ta_arg, td_key_iter_f *callback, + void *cbdata_p) +{ + td_thragent_t *const ta = (td_thragent_t *) ta_arg; + td_err_e err; + void *keys; + size_t keys_nb, keys_elemsize; + psaddr_t addr; + uint32_t idx; + + LOG ("td_ta_tsd_iter"); + + /* Test whether the TA parameter is ok. */ + if (! ta_ok (ta)) + return TD_BADTA; + + /* This makes sure we have the size information on hand. */ + addr = 0; + err = _td_locate_field (ta, + ta->ta_var___pthread_keys, SYM_DESC___pthread_keys, + (psaddr_t) 0 + 1, &addr); + if (err != TD_OK) + return err; + + /* Now copy in the entire array of key descriptors. */ + keys_elemsize = (addr - (psaddr_t) 0) / 8; + keys_nb = keys_elemsize * DB_DESC_NELEM (ta->ta_var___pthread_keys); + keys = __alloca (keys_nb); + err = DB_GET_SYMBOL (addr, ta, __pthread_keys); + if (err != TD_OK) + return err; + if (ps_pdread (ta->ph, addr, keys, keys_nb) != PS_OK) + return TD_ERR; + + /* Now get all descriptors, one after the other. */ + for (idx = 0; idx < DB_DESC_NELEM (ta->ta_var___pthread_keys); ++idx) + { + psaddr_t seq, destr; + err = DB_GET_FIELD_LOCAL (seq, ta, keys, pthread_key_struct, seq, 0); + if (err != TD_OK) + return err; + if (((uintptr_t) seq) & 1) + { + err = DB_GET_FIELD_LOCAL (destr, ta, keys, pthread_key_struct, + destr, 0); + if (err != TD_OK) + return err; + /* Return with an error if the callback returns a nonzero value. */ + if (callback ((thread_key_t) idx, destr, cbdata_p) != 0) + return TD_DBERR; + } + /* Advance to the next element in the copied array. */ + keys += keys_elemsize; + } + + return TD_OK; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_thr_clear_event.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_thr_clear_event.c new file mode 100644 index 00000000..92e7f153 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_thr_clear_event.c @@ -0,0 +1,75 @@ +/* Disable specific event for thread. + Copyright (C) 1999,2001,2002,2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#include "thread_dbP.h" + + +td_err_e +td_thr_clear_event (const td_thrhandle_t *th, td_thr_events_t *event) +{ + td_err_e err; + psaddr_t eventmask; + void *copy = NULL; + + LOG ("td_thr_clear_event"); + + /* Fetch the old event mask from the inferior and modify it in place. */ + err = DB_GET_FIELD_ADDRESS (eventmask, th->th_ta_p, + th->th_unique, pthread, eventbuf_eventmask, 0); + if (err == TD_OK) + err = DB_GET_STRUCT (copy, th->th_ta_p, eventmask, td_thr_events_t); + if (err == TD_OK) + { + uint32_t idx; + for (idx = 0; idx < TD_EVENTSIZE; ++idx) + { + psaddr_t word; + uint32_t mask; + err = DB_GET_FIELD_LOCAL (word, th->th_ta_p, copy, + td_thr_events_t, event_bits, idx); + if (err != TD_OK) + break; + mask = (uintptr_t) word; + mask &= ~event->event_bits[idx]; + word = (psaddr_t) (uintptr_t) mask; + err = DB_PUT_FIELD_LOCAL (th->th_ta_p, copy, + td_thr_events_t, event_bits, idx, word); + if (err != TD_OK) + break; + } + if (err == TD_NOAPLIC) + { + err = TD_OK; + while (idx < TD_EVENTSIZE) + if (event->event_bits[idx++] != 0) + { + err = TD_NOEVENT; + break; + } + } + if (err == TD_OK) + /* Now write it back to the inferior. */ + err = DB_PUT_STRUCT (th->th_ta_p, eventmask, td_thr_events_t, copy); + } + + return err; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_thr_dbresume.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_thr_dbresume.c new file mode 100644 index 00000000..3fd79437 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_thr_dbresume.c @@ -0,0 +1,30 @@ +/* Resume execution of given thread. + Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_thr_dbresume (const td_thrhandle_t *th) +{ + /* XXX We have to figure out what has to be done. */ + LOG ("td_thr_dbresume"); + return TD_NOCAPAB; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_thr_dbsuspend.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_thr_dbsuspend.c new file mode 100644 index 00000000..6ef82ad3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_thr_dbsuspend.c @@ -0,0 +1,30 @@ +/* Suspend execution of given thread. + Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_thr_dbsuspend (const td_thrhandle_t *th) +{ + /* XXX We have to figure out what has to be done. */ + LOG ("td_thr_dbsuspend"); + return TD_NOCAPAB; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_thr_event_enable.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_thr_event_enable.c new file mode 100644 index 00000000..02140fd3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_thr_event_enable.c @@ -0,0 +1,32 @@ +/* Enable event process-wide. + Copyright (C) 1999, 2001, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_thr_event_enable (const td_thrhandle_t *th, int onoff) +{ + LOG ("td_thr_event_enable"); + + /* Write the new value into the thread data structure. */ + return DB_PUT_FIELD (th->th_ta_p, th->th_unique, pthread, report_events, 0, + (psaddr_t) 0 + (onoff != 0)); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_thr_event_getmsg.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_thr_event_getmsg.c new file mode 100644 index 00000000..b24fc25d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_thr_event_getmsg.c @@ -0,0 +1,119 @@ +/* Retrieve event. + Copyright (C) 1999, 2001, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" +#include + + +td_err_e +td_thr_event_getmsg (const td_thrhandle_t *th, td_event_msg_t *msg) +{ + td_err_e err; + psaddr_t eventbuf, eventnum, eventdata; + psaddr_t thp, prevp; + void *copy = NULL; + + LOG ("td_thr_event_getmsg"); + + /* Copy the event message buffer in from the inferior. */ + err = DB_GET_FIELD_ADDRESS (eventbuf, th->th_ta_p, th->th_unique, pthread, + eventbuf, 0); + if (err == TD_OK) + err = DB_GET_STRUCT (copy, th->th_ta_p, eventbuf, td_eventbuf_t); + if (err != TD_OK) + return err; + + /* Check whether an event occurred. */ + err = DB_GET_FIELD_LOCAL (eventnum, th->th_ta_p, copy, + td_eventbuf_t, eventnum, 0); + if (err != TD_OK) + return err; + if ((int) (uintptr_t) eventnum == TD_EVENT_NONE) + /* Nothing. */ + return TD_NOMSG; + + /* Fill the user's data structure. */ + err = DB_GET_FIELD_LOCAL (eventdata, th->th_ta_p, copy, + td_eventbuf_t, eventdata, 0); + if (err != TD_OK) + return err; + + msg->msg.data = (uintptr_t) eventdata; + msg->event = (uintptr_t) eventnum; + msg->th_p = th; + + /* And clear the event message in the target. */ + memset (copy, 0, th->th_ta_p->ta_sizeof_td_eventbuf_t); + err = DB_PUT_STRUCT (th->th_ta_p, eventbuf, td_eventbuf_t, copy); + if (err != TD_OK) + return err; + + /* Get the pointer to the thread descriptor with the last event. + If it doesn't match TH, then walk down the list until we find it. + We must splice it out of the list so that there is no dangling + pointer to it later when it dies. */ + err = DB_GET_SYMBOL (prevp, th->th_ta_p, __nptl_last_event); + if (err != TD_OK) + return err; + err = DB_GET_VALUE (thp, th->th_ta_p, __nptl_last_event, 0); + if (err != TD_OK) + return err; + + while (thp != 0) + { + psaddr_t next; + err = DB_GET_FIELD (next, th->th_ta_p, th->th_unique, pthread, + nextevent, 0); + if (err != TD_OK) + return err; + + if (next == thp) + return TD_DBERR; + + if (thp == th->th_unique) + { + /* PREVP points at this thread, splice it out. */ + psaddr_t next_nextp; + err = DB_GET_FIELD_ADDRESS (next_nextp, th->th_ta_p, next, pthread, + nextevent, 0); + assert (err == TD_OK); /* We used this field before. */ + if (prevp == next_nextp) + return TD_DBERR; + + err = _td_store_value (th->th_ta_p, + th->th_ta_p->ta_var___nptl_last_event, -1, + 0, prevp, next); + if (err != TD_OK) + return err; + + /* Now clear this thread's own next pointer so it's not dangling + when the thread resumes and then chains on for its next event. */ + return DB_PUT_FIELD (th->th_ta_p, thp, pthread, nextevent, 0, 0); + } + + err = DB_GET_FIELD_ADDRESS (prevp, th->th_ta_p, thp, pthread, + nextevent, 0); + assert (err == TD_OK); /* We used this field before. */ + thp = next; + } + + /* Ack! This should not happen. */ + return TD_DBERR; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_thr_get_info.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_thr_get_info.c new file mode 100644 index 00000000..bb138880 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_thr_get_info.c @@ -0,0 +1,110 @@ +/* Get thread information. + Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include "thread_dbP.h" + + +td_err_e +td_thr_get_info (const td_thrhandle_t *th, td_thrinfo_t *infop) +{ + td_err_e err; + void *copy; + psaddr_t tls, schedpolicy, schedprio, cancelhandling, tid, report_events; + + LOG ("td_thr_get_info"); + + /* Copy the whole descriptor in once so we can access the several + fields locally. Excess copying in one go is much better than + multiple ps_pdread calls. */ + err = DB_GET_STRUCT (copy, th->th_ta_p, th->th_unique, pthread); + if (err != TD_OK) + return err; + + err = DB_GET_FIELD_ADDRESS (tls, th->th_ta_p, th->th_unique, + pthread, specific, 0); + if (err != TD_OK) + return err; + + err = DB_GET_FIELD_LOCAL (schedpolicy, th->th_ta_p, copy, pthread, + schedpolicy, 0); + if (err != TD_OK) + return err; + err = DB_GET_FIELD_LOCAL (schedprio, th->th_ta_p, copy, pthread, + schedparam_sched_priority, 0); + if (err != TD_OK) + return err; + err = DB_GET_FIELD_LOCAL (tid, th->th_ta_p, copy, pthread, tid, 0); + if (err != TD_OK) + return err; + err = DB_GET_FIELD_LOCAL (cancelhandling, th->th_ta_p, copy, pthread, + cancelhandling, 0); + if (err != TD_OK) + return err; + err = DB_GET_FIELD_LOCAL (report_events, th->th_ta_p, copy, pthread, + report_events, 0); + if (err != TD_OK) + return err; + + /* Fill in information. Clear first to provide reproducable + results for the fields we do not fill in. */ + memset (infop, '\0', sizeof (td_thrinfo_t)); + + infop->ti_tid = (thread_t) th->th_unique; + infop->ti_tls = (char *) tls; + infop->ti_pri = ((uintptr_t) schedpolicy == SCHED_OTHER + ? 0 : (uintptr_t) schedprio); + infop->ti_type = TD_THR_USER; + + if ((((int) (uintptr_t) cancelhandling) & EXITING_BITMASK) == 0) + /* XXX For now there is no way to get more information. */ + infop->ti_state = TD_THR_ACTIVE; + else if ((((int) (uintptr_t) cancelhandling) & TERMINATED_BITMASK) == 0) + infop->ti_state = TD_THR_ZOMBIE; + else + infop->ti_state = TD_THR_UNKNOWN; + + /* Initialization which are the same in both cases. */ + infop->ti_ta_p = th->th_ta_p; + infop->ti_lid = tid == 0 ? ps_getpid (th->th_ta_p->ph) : (uintptr_t) tid; + infop->ti_traceme = report_events != 0; + + err = DB_GET_FIELD_LOCAL (infop->ti_startfunc, th->th_ta_p, copy, pthread, + start_routine, 0); + if (err == TD_OK) + { + uint32_t idx; + for (idx = 0; idx < TD_EVENTSIZE; ++idx) + { + psaddr_t word; + err = DB_GET_FIELD_LOCAL (word, th->th_ta_p, copy, pthread, + eventbuf_eventmask_event_bits, idx); + if (err != TD_OK) + break; + infop->ti_events.event_bits[idx] = (uintptr_t) word; + } + if (err == TD_NOAPLIC) + memset (&infop->ti_events.event_bits[idx], 0, + (TD_EVENTSIZE - idx) * sizeof infop->ti_events.event_bits[0]); + } + + return err; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_thr_getfpregs.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_thr_getfpregs.c new file mode 100644 index 00000000..7760512e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_thr_getfpregs.c @@ -0,0 +1,53 @@ +/* Get a thread's floating-point register set. + Copyright (C) 1999, 2001, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_thr_getfpregs (const td_thrhandle_t *th, prfpregset_t *regset) +{ + psaddr_t cancelhandling, tid; + td_err_e err; + + LOG ("td_thr_getfpregs"); + + /* We have to get the state and the PID for this thread. */ + err = DB_GET_FIELD (cancelhandling, th->th_ta_p, th->th_unique, pthread, + cancelhandling, 0); + if (err != TD_OK) + return err; + + /* If the thread already terminated we return all zeroes. */ + if (((int) (uintptr_t) cancelhandling) & TERMINATED_BITMASK) + memset (regset, '\0', sizeof (*regset)); + /* Otherwise get the register content through the callback. */ + else + { + err = DB_GET_FIELD (tid, th->th_ta_p, th->th_unique, pthread, tid, 0); + if (err != TD_OK) + return err; + + if (ps_lgetfpregs (th->th_ta_p->ph, (uintptr_t) tid, regset) != PS_OK) + return TD_ERR; + } + + return TD_OK; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_thr_getgregs.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_thr_getgregs.c new file mode 100644 index 00000000..4c2373ef --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_thr_getgregs.c @@ -0,0 +1,53 @@ +/* Get a thread's general register set. + Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_thr_getgregs (const td_thrhandle_t *th, prgregset_t regset) +{ + psaddr_t cancelhandling, tid; + td_err_e err; + + LOG ("td_thr_getgregs"); + + /* We have to get the state and the PID for this thread. */ + err = DB_GET_FIELD (cancelhandling, th->th_ta_p, th->th_unique, pthread, + cancelhandling, 0); + if (err != TD_OK) + return err; + + /* If the thread already terminated we return all zeroes. */ + if (((int) (uintptr_t) cancelhandling) & TERMINATED_BITMASK) + memset (regset, '\0', sizeof (*regset)); + /* Otherwise get the register content through the callback. */ + else + { + err = DB_GET_FIELD (tid, th->th_ta_p, th->th_unique, pthread, tid, 0); + if (err != TD_OK) + return err; + + if (ps_lgetregs (th->th_ta_p->ph, (uintptr_t) tid, regset) != PS_OK) + return TD_ERR; + } + + return TD_OK; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_thr_getxregs.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_thr_getxregs.c new file mode 100644 index 00000000..3c77ab6b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_thr_getxregs.c @@ -0,0 +1,30 @@ +/* Get a thread's extra state register set. + Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_thr_getxregs (const td_thrhandle_t *th, void *xregs) +{ + /* XXX This might be platform specific. */ + LOG ("td_thr_getxregs"); + return TD_NOXREGS; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_thr_getxregsize.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_thr_getxregsize.c new file mode 100644 index 00000000..1704e4b0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_thr_getxregsize.c @@ -0,0 +1,30 @@ +/* Get the size of the extra state register set for this architecture. + Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_thr_getxregsize (const td_thrhandle_t *th, int *sizep) +{ + /* XXX This might be platform specific. */ + LOG ("td_thr_getxregsize"); + return TD_NOXREGS; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_thr_set_event.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_thr_set_event.c new file mode 100644 index 00000000..d7f50ad1 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_thr_set_event.c @@ -0,0 +1,75 @@ +/* Enable specific event for thread. + Copyright (C) 1999,2001,2002,2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#include "thread_dbP.h" + + +td_err_e +td_thr_set_event (const td_thrhandle_t *th, td_thr_events_t *event) +{ + td_err_e err; + psaddr_t eventmask; + void *copy = NULL; + + LOG ("td_thr_set_event"); + + /* Fetch the old event mask from the inferior and modify it in place. */ + err = DB_GET_FIELD_ADDRESS (eventmask, th->th_ta_p, + th->th_unique, pthread, eventbuf_eventmask, 0); + if (err == TD_OK) + err = DB_GET_STRUCT (copy, th->th_ta_p, eventmask, td_thr_events_t); + if (err == TD_OK) + { + uint32_t idx; + for (idx = 0; idx < TD_EVENTSIZE; ++idx) + { + psaddr_t word; + uint32_t mask; + err = DB_GET_FIELD_LOCAL (word, th->th_ta_p, copy, + td_thr_events_t, event_bits, idx); + if (err != TD_OK) + break; + mask = (uintptr_t) word; + mask |= event->event_bits[idx]; + word = (psaddr_t) (uintptr_t) mask; + err = DB_PUT_FIELD_LOCAL (th->th_ta_p, copy, + td_thr_events_t, event_bits, idx, word); + if (err != TD_OK) + break; + } + if (err == TD_NOAPLIC) + { + err = TD_OK; + while (idx < TD_EVENTSIZE) + if (event->event_bits[idx++] != 0) + { + err = TD_NOEVENT; + break; + } + } + if (err == TD_OK) + /* Now write it back to the inferior. */ + err = DB_PUT_STRUCT (th->th_ta_p, eventmask, td_thr_events_t, copy); + } + + return err; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_thr_setfpregs.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_thr_setfpregs.c new file mode 100644 index 00000000..01bdb532 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_thr_setfpregs.c @@ -0,0 +1,50 @@ +/* Set a thread's floating-point register set. + Copyright (C) 1999, 2001, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_thr_setfpregs (const td_thrhandle_t *th, const prfpregset_t *fpregs) +{ + psaddr_t cancelhandling, tid; + td_err_e err; + + LOG ("td_thr_setfpregs"); + + /* We have to get the state and the PID for this thread. */ + err = DB_GET_FIELD (cancelhandling, th->th_ta_p, th->th_unique, pthread, + cancelhandling, 0); + if (err != TD_OK) + return err; + + /* Only set the registers if the thread hasn't yet terminated. */ + if ((((int) (uintptr_t) cancelhandling) & TERMINATED_BITMASK) == 0) + { + err = DB_GET_FIELD (tid, th->th_ta_p, th->th_unique, pthread, tid, 0); + if (err != TD_OK) + return err; + + if (ps_lsetfpregs (th->th_ta_p->ph, (uintptr_t) tid, fpregs) != PS_OK) + return TD_ERR; + } + + return TD_OK; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_thr_setgregs.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_thr_setgregs.c new file mode 100644 index 00000000..2a9ce7e0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_thr_setgregs.c @@ -0,0 +1,50 @@ +/* Set a thread's general register set. + Copyright (C) 1999, 2001, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_thr_setgregs (const td_thrhandle_t *th, prgregset_t gregs) +{ + psaddr_t cancelhandling, tid; + td_err_e err; + + LOG ("td_thr_setgregs"); + + /* We have to get the state and the PID for this thread. */ + err = DB_GET_FIELD (cancelhandling, th->th_ta_p, th->th_unique, pthread, + cancelhandling, 0); + if (err != TD_OK) + return err; + + /* Only set the registers if the thread hasn't yet terminated. */ + if ((((int) (uintptr_t) cancelhandling) & TERMINATED_BITMASK) == 0) + { + err = DB_GET_FIELD (tid, th->th_ta_p, th->th_unique, pthread, tid, 0); + if (err != TD_OK) + return err; + + if (ps_lsetregs (th->th_ta_p->ph, tid - (psaddr_t) 0, gregs) != PS_OK) + return TD_ERR; + } + + return TD_OK; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_thr_setprio.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_thr_setprio.c new file mode 100644 index 00000000..6032b0ed --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_thr_setprio.c @@ -0,0 +1,30 @@ +/* Set a thread's priority. + Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_thr_setprio (const td_thrhandle_t *th, int prio) +{ + /* XXX We have to figure out what has to be done. */ + LOG ("td_thr_setprio"); + return TD_OK; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_thr_setsigpending.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_thr_setsigpending.c new file mode 100644 index 00000000..e2c9d7ad --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_thr_setsigpending.c @@ -0,0 +1,31 @@ +/* Raise a signal for a thread. + Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_thr_setsigpending (const td_thrhandle_t *th, unsigned char n, + const sigset_t *ss) +{ + /* XXX We have to figure out what has to be done. */ + LOG ("td_thr_setsigpending"); + return TD_OK; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_thr_setxregs.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_thr_setxregs.c new file mode 100644 index 00000000..f48877c7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_thr_setxregs.c @@ -0,0 +1,30 @@ +/* Set a thread's extra state register set. + Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_thr_setxregs (const td_thrhandle_t *ta, const void *addr) +{ + /* XXX This might have to be platform specific. */ + LOG ("td_thr_setxregs"); + return TD_NOXREGS; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_thr_sigsetmask.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_thr_sigsetmask.c new file mode 100644 index 00000000..3a68aecd --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_thr_sigsetmask.c @@ -0,0 +1,30 @@ +/* Set a thread's signal mask. + Copyright (C) 1999, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_thr_sigsetmask (const td_thrhandle_t *th, const sigset_t *ss) +{ + /* XXX We have to figure out what has to be done. */ + LOG ("td_thr_sigsetmask"); + return TD_OK; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_thr_tls_get_addr.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_thr_tls_get_addr.c new file mode 100644 index 00000000..e7d23227 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_thr_tls_get_addr.c @@ -0,0 +1,43 @@ +/* Get address of thread local variable. + Copyright (C) 2002,2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include "thread_dbP.h" + +td_err_e +td_thr_tls_get_addr (const td_thrhandle_t *th, + psaddr_t map_address, size_t offset, psaddr_t *address) +{ + td_err_e err; + psaddr_t modid; + + /* Get the TLS module ID from the `struct link_map' in the inferior. */ + err = DB_GET_FIELD (modid, th->th_ta_p, map_address, link_map, + l_tls_modid, 0); + if (err == TD_NOCAPAB) + return TD_NOAPLIC; + if (err == TD_OK) + { + err = td_thr_tlsbase (th, (uintptr_t) modid, address); + if (err == TD_OK) + *address += offset; + } + return err; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_thr_tlsbase.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_thr_tlsbase.c new file mode 100644 index 00000000..aaeda6f3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_thr_tlsbase.c @@ -0,0 +1,55 @@ +/* Locate TLS data for a thread. + Copyright (C) 2003, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + +td_err_e +td_thr_tlsbase (const td_thrhandle_t *th, + unsigned long int modid, + psaddr_t *base) +{ + td_err_e err; + psaddr_t dtv, dtvslot, dtvptr; + + if (modid < 1) + return TD_NOTLS; + + /* Get the DTV pointer from the thread descriptor. */ + err = DB_GET_FIELD (dtv, th->th_ta_p, th->th_unique, pthread, dtvp, 0); + if (err != TD_OK) + return err; + + /* Find the corresponding entry in the DTV. */ + err = DB_GET_FIELD_ADDRESS (dtvslot, th->th_ta_p, dtv, dtv, dtv, modid); + if (err != TD_OK) + return err; + + /* Extract the TLS block address from that DTV slot. */ + err = DB_GET_FIELD (dtvptr, th->th_ta_p, dtvslot, dtv_t, pointer_val, 0); + if (err != TD_OK) + return err; + + /* It could be that the memory for this module is not allocated for + the given thread. */ + if ((uintptr_t) dtvptr & 1) + return TD_TLSDEFER; + + *base = dtvptr; + return TD_OK; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_thr_tsd.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_thr_tsd.c new file mode 100644 index 00000000..08f617b7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_thr_tsd.c @@ -0,0 +1,96 @@ +/* Get a thread-specific data pointer for a thread. + Copyright (C) 1999,2001,2002,2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" + + +td_err_e +td_thr_tsd (const td_thrhandle_t *th, const thread_key_t tk, void **data) +{ + td_err_e err; + psaddr_t tk_seq, level1, level2, seq, value; + void *copy; + uint32_t pthread_key_2ndlevel_size, idx1st, idx2nd; + + LOG ("td_thr_tsd"); + + /* Get the key entry. */ + err = DB_GET_VALUE (tk_seq, th->th_ta_p, __pthread_keys, tk); + if (err == TD_NOAPLIC) + return TD_BADKEY; + if (err != TD_OK) + return err; + + /* Fail if this key is not at all used. */ + if (((uintptr_t) tk_seq & 1) == 0) + return TD_BADKEY; + + /* This makes sure we have the size information on hand. */ + err = DB_GET_FIELD_ADDRESS (level2, th->th_ta_p, 0, pthread_key_data_level2, + data, 1); + if (err != TD_OK) + return err; + + /* Compute the indeces. */ + pthread_key_2ndlevel_size + = DB_DESC_NELEM (th->th_ta_p->ta_field_pthread_key_data_level2_data); + idx1st = tk / pthread_key_2ndlevel_size; + idx2nd = tk % pthread_key_2ndlevel_size; + + /* Now fetch the first level pointer. */ + err = DB_GET_FIELD (level1, th->th_ta_p, th->th_unique, pthread, + specific, idx1st); + if (err == TD_NOAPLIC) + return TD_DBERR; + if (err != TD_OK) + return err; + + /* Check the pointer to the second level array. */ + if (level1 == 0) + return TD_NOTSD; + + /* Locate the element within the second level array. */ + err = DB_GET_FIELD_ADDRESS (level2, th->th_ta_p, + level1, pthread_key_data_level2, data, idx2nd); + if (err == TD_NOAPLIC) + return TD_DBERR; + if (err != TD_OK) + return err; + + /* Now copy in that whole structure. */ + err = DB_GET_STRUCT (copy, th->th_ta_p, level2, pthread_key_data); + if (err != TD_OK) + return err; + + /* Check whether the data is valid. */ + err = DB_GET_FIELD_LOCAL (seq, th->th_ta_p, copy, pthread_key_data, seq, 0); + if (err != TD_OK) + return err; + if (seq != tk_seq) + return TD_NOTSD; + + /* Finally, fetch the value. */ + err = DB_GET_FIELD_LOCAL (value, th->th_ta_p, copy, pthread_key_data, + data, 0); + if (err == TD_OK) + *data = value; + + return err; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_thr_validate.c b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_thr_validate.c new file mode 100644 index 00000000..19ee940d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/td_thr_validate.c @@ -0,0 +1,91 @@ +/* Validate a thread handle. + Copyright (C) 1999, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1999. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "thread_dbP.h" +#include + +static td_err_e +check_thread_list (const td_thrhandle_t *th, psaddr_t head, bool *uninit) +{ + td_err_e err; + psaddr_t next, ofs; + + err = DB_GET_FIELD (next, th->th_ta_p, head, list_t, next, 0); + if (err == TD_OK) + { + if (next == 0) + { + *uninit = true; + return TD_NOTHR; + } + err = DB_GET_FIELD_ADDRESS (ofs, th->th_ta_p, 0, pthread, list, 0); + } + + while (err == TD_OK) + { + if (next == head) + return TD_NOTHR; + + if (next - (ofs - (psaddr_t) 0) == th->th_unique) + return TD_OK; + + err = DB_GET_FIELD (next, th->th_ta_p, next, list_t, next, 0); + } + + return err; +} + + +td_err_e +td_thr_validate (const td_thrhandle_t *th) +{ + td_err_e err; + psaddr_t list = NULL; + + LOG ("td_thr_validate"); + + /* First check the list with threads using user allocated stacks. */ + bool uninit = false; + err = DB_GET_SYMBOL (list, th->th_ta_p, __stack_user); + if (err == TD_OK) + err = check_thread_list (th, list, &uninit); + + /* If our thread is not on this list search the list with stack + using implementation allocated stacks. */ + if (err == TD_NOTHR) + { + err = DB_GET_SYMBOL (list, th->th_ta_p, stack_used); + if (err == TD_OK) + err = check_thread_list (th, list, &uninit); + + if (err == TD_NOTHR && uninit) + { + /* __pthread_initialize_minimal has not run yet. + But the main thread still has a valid ID. */ + td_thrhandle_t main_th; + err = td_ta_map_lwp2thr (th->th_ta_p, + ps_getpid (th->th_ta_p->ph), &main_th); + if (err == TD_OK && th->th_unique != main_th.th_unique) + err = TD_NOTHR; + } + } + + return err; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/thread_db.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/thread_db.h new file mode 100644 index 00000000..433b54fd --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/thread_db.h @@ -0,0 +1,459 @@ +/* thread_db.h -- interface to libthread_db.so library for debugging -lpthread + Copyright (C) 1999,2001,2002,2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _THREAD_DB_H +#define _THREAD_DB_H 1 + +/* This is the debugger interface for the NPTL library. It is + modelled closely after the interface with same names in Solaris + with the goal to share the same code in the debugger. */ +#include +#include +#include +#include + + +/* Error codes of the library. */ +typedef enum +{ + TD_OK, /* No error. */ + TD_ERR, /* No further specified error. */ + TD_NOTHR, /* No matching thread found. */ + TD_NOSV, /* No matching synchronization handle found. */ + TD_NOLWP, /* No matching light-weighted process found. */ + TD_BADPH, /* Invalid process handle. */ + TD_BADTH, /* Invalid thread handle. */ + TD_BADSH, /* Invalid synchronization handle. */ + TD_BADTA, /* Invalid thread agent. */ + TD_BADKEY, /* Invalid key. */ + TD_NOMSG, /* No event available. */ + TD_NOFPREGS, /* No floating-point register content available. */ + TD_NOLIBTHREAD, /* Application not linked with thread library. */ + TD_NOEVENT, /* Requested event is not supported. */ + TD_NOCAPAB, /* Capability not available. */ + TD_DBERR, /* Internal debug library error. */ + TD_NOAPLIC, /* Operation is not applicable. */ + TD_NOTSD, /* No thread-specific data available. */ + TD_MALLOC, /* Out of memory. */ + TD_PARTIALREG, /* Not entire register set was read or written. */ + TD_NOXREGS, /* X register set not available for given thread. */ + TD_TLSDEFER, /* Thread has not yet allocated TLS for given module. */ + TD_NOTALLOC = TD_TLSDEFER, + TD_VERSION, /* Version if libpthread and libthread_db do not match. */ + TD_NOTLS /* There is no TLS segment in the given module. */ +} td_err_e; + + +/* Possible thread states. TD_THR_ANY_STATE is a pseudo-state used to + select threads regardless of state in td_ta_thr_iter(). */ +typedef enum +{ + TD_THR_ANY_STATE, + TD_THR_UNKNOWN, + TD_THR_STOPPED, + TD_THR_RUN, + TD_THR_ACTIVE, + TD_THR_ZOMBIE, + TD_THR_SLEEP, + TD_THR_STOPPED_ASLEEP +} td_thr_state_e; + +/* Thread type: user or system. TD_THR_ANY_TYPE is a pseudo-type used + to select threads regardless of type in td_ta_thr_iter(). */ +typedef enum +{ + TD_THR_ANY_TYPE, + TD_THR_USER, + TD_THR_SYSTEM +} td_thr_type_e; + + +/* Types of the debugging library. */ + +/* Handle for a process. This type is opaque. */ +typedef struct td_thragent td_thragent_t; + +/* The actual thread handle type. This is also opaque. */ +typedef struct td_thrhandle +{ + td_thragent_t *th_ta_p; + psaddr_t th_unique; +} td_thrhandle_t; + + +/* Forward declaration of a type defined by and for the dynamic linker. */ +struct link_map; + + +/* Flags for `td_ta_thr_iter'. */ +#define TD_THR_ANY_USER_FLAGS 0xffffffff +#define TD_THR_LOWEST_PRIORITY -20 +#define TD_SIGNO_MASK NULL + + +#define TD_EVENTSIZE 2 +#define BT_UISHIFT 5 /* log base 2 of BT_NBIPUI, to extract word index */ +#define BT_NBIPUI (1 << BT_UISHIFT) /* n bits per uint */ +#define BT_UIMASK (BT_NBIPUI - 1) /* to extract bit index */ + +/* Bitmask of enabled events. */ +typedef struct td_thr_events +{ + uint32_t event_bits[TD_EVENTSIZE]; +} td_thr_events_t; + +/* Event set manipulation macros. */ +#define __td_eventmask(n) \ + (UINT32_C (1) << (((n) - 1) & BT_UIMASK)) +#define __td_eventword(n) \ + ((UINT32_C ((n) - 1)) >> BT_UISHIFT) + +#define td_event_emptyset(setp) \ + do { \ + int __i; \ + for (__i = TD_EVENTSIZE; __i > 0; --__i) \ + (setp)->event_bits[__i - 1] = 0; \ + } while (0) + +#define td_event_fillset(setp) \ + do { \ + int __i; \ + for (__i = TD_EVENTSIZE; __i > 0; --__i) \ + (setp)->event_bits[__i - 1] = UINT32_C (0xffffffff); \ + } while (0) + +#define td_event_addset(setp, n) \ + (((setp)->event_bits[__td_eventword (n)]) |= __td_eventmask (n)) +#define td_event_delset(setp, n) \ + (((setp)->event_bits[__td_eventword (n)]) &= ~__td_eventmask (n)) +#define td_eventismember(setp, n) \ + (__td_eventmask (n) & ((setp)->event_bits[__td_eventword (n)])) +#if TD_EVENTSIZE == 2 +# define td_eventisempty(setp) \ + (!((setp)->event_bits[0]) && !((setp)->event_bits[1])) +#else +# error "td_eventisempty must be changed to match TD_EVENTSIZE" +#endif + +/* Events reportable by the thread implementation. */ +typedef enum +{ + TD_ALL_EVENTS, /* Pseudo-event number. */ + TD_EVENT_NONE = TD_ALL_EVENTS, /* Depends on context. */ + TD_READY, /* Is executable now. */ + TD_SLEEP, /* Blocked in a synchronization obj. */ + TD_SWITCHTO, /* Now assigned to a process. */ + TD_SWITCHFROM, /* Not anymore assigned to a process. */ + TD_LOCK_TRY, /* Trying to get an unavailable lock. */ + TD_CATCHSIG, /* Signal posted to the thread. */ + TD_IDLE, /* Process getting idle. */ + TD_CREATE, /* New thread created. */ + TD_DEATH, /* Thread terminated. */ + TD_PREEMPT, /* Preempted. */ + TD_PRI_INHERIT, /* Inherited elevated priority. */ + TD_REAP, /* Reaped. */ + TD_CONCURRENCY, /* Number of processes changing. */ + TD_TIMEOUT, /* Conditional variable wait timed out. */ + TD_MIN_EVENT_NUM = TD_READY, + TD_MAX_EVENT_NUM = TD_TIMEOUT, + TD_EVENTS_ENABLE = 31 /* Event reporting enabled. */ +} td_event_e; + +/* Values representing the different ways events are reported. */ +typedef enum +{ + NOTIFY_BPT, /* User must insert breakpoint at u.bptaddr. */ + NOTIFY_AUTOBPT, /* Breakpoint at u.bptaddr is automatically + inserted. */ + NOTIFY_SYSCALL /* System call u.syscallno will be invoked. */ +} td_notify_e; + +/* Description how event type is reported. */ +typedef struct td_notify +{ + td_notify_e type; /* Way the event is reported. */ + union + { + psaddr_t bptaddr; /* Address of breakpoint. */ + int syscallno; /* Number of system call used. */ + } u; +} td_notify_t; + +/* Structure used to report event. */ +typedef struct td_event_msg +{ + td_event_e event; /* Event type being reported. */ + const td_thrhandle_t *th_p; /* Thread reporting the event. */ + union + { +# if 0 + td_synchandle_t *sh; /* Handle of synchronization object. */ +#endif + uintptr_t data; /* Event specific data. */ + } msg; +} td_event_msg_t; + +/* Structure containing event data available in each thread structure. */ +typedef struct +{ + td_thr_events_t eventmask; /* Mask of enabled events. */ + td_event_e eventnum; /* Number of last event. */ + void *eventdata; /* Data associated with event. */ +} td_eventbuf_t; + + +/* Gathered statistics about the process. */ +typedef struct td_ta_stats +{ + int nthreads; /* Total number of threads in use. */ + int r_concurrency; /* Concurrency level requested by user. */ + int nrunnable_num; /* Average runnable threads, numerator. */ + int nrunnable_den; /* Average runnable threads, denominator. */ + int a_concurrency_num; /* Achieved concurrency level, numerator. */ + int a_concurrency_den; /* Achieved concurrency level, denominator. */ + int nlwps_num; /* Average number of processes in use, + numerator. */ + int nlwps_den; /* Average number of processes in use, + denominator. */ + int nidle_num; /* Average number of idling processes, + numerator. */ + int nidle_den; /* Average number of idling processes, + denominator. */ +} td_ta_stats_t; + + +/* Since Sun's library is based on Solaris threads we have to define a few + types to map them to POSIX threads. */ +typedef pthread_t thread_t; +typedef pthread_key_t thread_key_t; + + +/* Callback for iteration over threads. */ +typedef int td_thr_iter_f (const td_thrhandle_t *, void *); + +/* Callback for iteration over thread local data. */ +typedef int td_key_iter_f (thread_key_t, void (*) (void *), void *); + + + +/* Forward declaration. This has to be defined by the user. */ +struct ps_prochandle; + + +/* Information about the thread. */ +typedef struct td_thrinfo +{ + td_thragent_t *ti_ta_p; /* Process handle. */ + unsigned int ti_user_flags; /* Unused. */ + thread_t ti_tid; /* Thread ID returned by + pthread_create(). */ + char *ti_tls; /* Pointer to thread-local data. */ + psaddr_t ti_startfunc; /* Start function passed to + pthread_create(). */ + psaddr_t ti_stkbase; /* Base of thread's stack. */ + long int ti_stksize; /* Size of thread's stack. */ + psaddr_t ti_ro_area; /* Unused. */ + int ti_ro_size; /* Unused. */ + td_thr_state_e ti_state; /* Thread state. */ + unsigned char ti_db_suspended; /* Nonzero if suspended by debugger. */ + td_thr_type_e ti_type; /* Type of the thread (system vs + user thread). */ + intptr_t ti_pc; /* Unused. */ + intptr_t ti_sp; /* Unused. */ + short int ti_flags; /* Unused. */ + int ti_pri; /* Thread priority. */ + lwpid_t ti_lid; /* Kernel PID for this thread. */ + sigset_t ti_sigmask; /* Signal mask. */ + unsigned char ti_traceme; /* Nonzero if event reporting + enabled. */ + unsigned char ti_preemptflag; /* Unused. */ + unsigned char ti_pirecflag; /* Unused. */ + sigset_t ti_pending; /* Set of pending signals. */ + td_thr_events_t ti_events; /* Set of enabled events. */ +} td_thrinfo_t; + + + +/* Prototypes for exported library functions. */ + +/* Initialize the thread debug support library. */ +extern td_err_e td_init (void); + +/* Historical relict. Should not be used anymore. */ +extern td_err_e td_log (void); + +/* Return list of symbols the library can request. */ +extern const char **td_symbol_list (void); + +/* Generate new thread debug library handle for process PS. */ +extern td_err_e td_ta_new (struct ps_prochandle *__ps, td_thragent_t **__ta); + +/* Free resources allocated for TA. */ +extern td_err_e td_ta_delete (td_thragent_t *__ta); + +/* Get number of currently running threads in process associated with TA. */ +extern td_err_e td_ta_get_nthreads (const td_thragent_t *__ta, int *__np); + +/* Return process handle passed in `td_ta_new' for process associated with + TA. */ +extern td_err_e td_ta_get_ph (const td_thragent_t *__ta, + struct ps_prochandle **__ph); + +/* Map thread library handle PT to thread debug library handle for process + associated with TA and store result in *TH. */ +extern td_err_e td_ta_map_id2thr (const td_thragent_t *__ta, pthread_t __pt, + td_thrhandle_t *__th); + +/* Map process ID LWPID to thread debug library handle for process + associated with TA and store result in *TH. */ +extern td_err_e td_ta_map_lwp2thr (const td_thragent_t *__ta, lwpid_t __lwpid, + td_thrhandle_t *__th); + + +/* Call for each thread in a process associated with TA the callback function + CALLBACK. */ +extern td_err_e td_ta_thr_iter (const td_thragent_t *__ta, + td_thr_iter_f *__callback, void *__cbdata_p, + td_thr_state_e __state, int __ti_pri, + sigset_t *__ti_sigmask_p, + unsigned int __ti_user_flags); + +/* Call for each defined thread local data entry the callback function KI. */ +extern td_err_e td_ta_tsd_iter (const td_thragent_t *__ta, td_key_iter_f *__ki, + void *__p); + + +/* Get event address for EVENT. */ +extern td_err_e td_ta_event_addr (const td_thragent_t *__ta, + td_event_e __event, td_notify_t *__ptr); + +/* Enable EVENT in global mask. */ +extern td_err_e td_ta_set_event (const td_thragent_t *__ta, + td_thr_events_t *__event); + +/* Disable EVENT in global mask. */ +extern td_err_e td_ta_clear_event (const td_thragent_t *__ta, + td_thr_events_t *__event); + +/* Return information about last event. */ +extern td_err_e td_ta_event_getmsg (const td_thragent_t *__ta, + td_event_msg_t *__msg); + + +/* Set suggested concurrency level for process associated with TA. */ +extern td_err_e td_ta_setconcurrency (const td_thragent_t *__ta, int __level); + + +/* Enable collecting statistics for process associated with TA. */ +extern td_err_e td_ta_enable_stats (const td_thragent_t *__ta, int __enable); + +/* Reset statistics. */ +extern td_err_e td_ta_reset_stats (const td_thragent_t *__ta); + +/* Retrieve statistics from process associated with TA. */ +extern td_err_e td_ta_get_stats (const td_thragent_t *__ta, + td_ta_stats_t *__statsp); + + +/* Validate that TH is a thread handle. */ +extern td_err_e td_thr_validate (const td_thrhandle_t *__th); + +/* Return information about thread TH. */ +extern td_err_e td_thr_get_info (const td_thrhandle_t *__th, + td_thrinfo_t *__infop); + +/* Retrieve floating-point register contents of process running thread TH. */ +extern td_err_e td_thr_getfpregs (const td_thrhandle_t *__th, + prfpregset_t *__regset); + +/* Retrieve general register contents of process running thread TH. */ +extern td_err_e td_thr_getgregs (const td_thrhandle_t *__th, + prgregset_t __gregs); + +/* Retrieve extended register contents of process running thread TH. */ +extern td_err_e td_thr_getxregs (const td_thrhandle_t *__th, void *__xregs); + +/* Get size of extended register set of process running thread TH. */ +extern td_err_e td_thr_getxregsize (const td_thrhandle_t *__th, int *__sizep); + +/* Set floating-point register contents of process running thread TH. */ +extern td_err_e td_thr_setfpregs (const td_thrhandle_t *__th, + const prfpregset_t *__fpregs); + +/* Set general register contents of process running thread TH. */ +extern td_err_e td_thr_setgregs (const td_thrhandle_t *__th, + prgregset_t __gregs); + +/* Set extended register contents of process running thread TH. */ +extern td_err_e td_thr_setxregs (const td_thrhandle_t *__th, + const void *__addr); + + +/* Get address of the given module's TLS storage area for the given thread. */ +extern td_err_e td_thr_tlsbase (const td_thrhandle_t *__th, + unsigned long int __modid, + psaddr_t *__base); + +/* Get address of thread local variable. */ +extern td_err_e td_thr_tls_get_addr (const td_thrhandle_t *__th, + psaddr_t __map_address, size_t __offset, + psaddr_t *__address); + + +/* Enable reporting for EVENT for thread TH. */ +extern td_err_e td_thr_event_enable (const td_thrhandle_t *__th, int __event); + +/* Enable EVENT for thread TH. */ +extern td_err_e td_thr_set_event (const td_thrhandle_t *__th, + td_thr_events_t *__event); + +/* Disable EVENT for thread TH. */ +extern td_err_e td_thr_clear_event (const td_thrhandle_t *__th, + td_thr_events_t *__event); + +/* Get event message for thread TH. */ +extern td_err_e td_thr_event_getmsg (const td_thrhandle_t *__th, + td_event_msg_t *__msg); + + +/* Set priority of thread TH. */ +extern td_err_e td_thr_setprio (const td_thrhandle_t *__th, int __prio); + + +/* Set pending signals for thread TH. */ +extern td_err_e td_thr_setsigpending (const td_thrhandle_t *__th, + unsigned char __n, const sigset_t *__ss); + +/* Set signal mask for thread TH. */ +extern td_err_e td_thr_sigsetmask (const td_thrhandle_t *__th, + const sigset_t *__ss); + + +/* Return thread local data associated with key TK in thread TH. */ +extern td_err_e td_thr_tsd (const td_thrhandle_t *__th, + const thread_key_t __tk, void **__data); + + +/* Suspend execution of thread TH. */ +extern td_err_e td_thr_dbsuspend (const td_thrhandle_t *__th); + +/* Resume execution of thread TH. */ +extern td_err_e td_thr_dbresume (const td_thrhandle_t *__th); + +#endif /* thread_db.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/thread_dbP.h b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/thread_dbP.h new file mode 100644 index 00000000..c3d263b0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libpthread/nptl_db/thread_dbP.h @@ -0,0 +1,258 @@ +/* Private header for thread debug library + Copyright (C) 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _THREAD_DBP_H +#define _THREAD_DBP_H 1 + +#include +#include +#include +#include +#include +#include +#include "proc_service.h" +#include "thread_db.h" +#include "../nptl/pthreadP.h" /* This is for *_BITMASK only. */ + +#ifdef __UCLIBC__ +#define __alloca alloca +#endif + +/* Indeces for the symbol names. */ +enum + { +# define DB_STRUCT(type) SYM_SIZEOF_##type, +# define DB_STRUCT_FIELD(type, field) SYM_##type##_FIELD_##field, +# define DB_SYMBOL(name) SYM_##name, +# define DB_FUNCTION(name) SYM_##name, +# define DB_VARIABLE(name) SYM_##name, SYM_DESC_##name, +# include "structs.def" +# undef DB_STRUCT +# undef DB_STRUCT_FIELD +# undef DB_SYMBOL +# undef DB_FUNCTION +# undef DB_VARIABLE + + SYM_TH_UNIQUE_CONST_THREAD_AREA, + SYM_TH_UNIQUE_REGISTER64, + SYM_TH_UNIQUE_REGISTER32, + SYM_TH_UNIQUE_REGISTER64_THREAD_AREA, + SYM_TH_UNIQUE_REGISTER32_THREAD_AREA, + + SYM_NUM_MESSAGES + }; + + +/* Comment out the following for less verbose output. */ +#ifndef NDEBUG +# define LOG(c) if (__td_debug) write (2, c "\n", strlen (c "\n")) +extern int __td_debug attribute_hidden; +#else +# define LOG(c) +#endif + + +#define DB_DESC_SIZE(desc) ((desc)[0]) +#define DB_DESC_NELEM(desc) ((desc)[1]) +#define DB_DESC_OFFSET(desc) ((desc)[2]) +#define DB_SIZEOF_DESC (3 * sizeof (uint32_t)) +#define DB_DEFINE_DESC(name, size, nelem, offset) \ + const uint32_t name[3] = { (size), (nelem), (offset) } +typedef uint32_t db_desc_t[3]; + + +/* Handle for a process. This type is opaque. */ +struct td_thragent +{ + /* Chain on the list of all agent structures. */ + list_t list; + + /* Delivered by the debugger and we have to pass it back in the + proc callbacks. */ + struct ps_prochandle *ph; + + /* Cached values read from the inferior. */ +# define DB_STRUCT(type) \ + uint32_t ta_sizeof_##type; +# define DB_STRUCT_FIELD(type, field) \ + db_desc_t ta_field_##type##_##field; +# define DB_SYMBOL(name) \ + psaddr_t ta_addr_##name; +# define DB_FUNCTION(name) \ + psaddr_t ta_addr_##name; +# define DB_VARIABLE(name) \ + psaddr_t ta_addr_##name; \ + db_desc_t ta_var_##name; +# include "structs.def" +# undef DB_STRUCT +# undef DB_STRUCT_FIELD +# undef DB_FUNCTION +# undef DB_SYMBOL +# undef DB_VARIABLE + + /* The method of locating a thread's th_unique value. */ + enum + { + ta_howto_unknown, + ta_howto_reg, + ta_howto_reg_thread_area, + ta_howto_const_thread_area + } ta_howto; + union + { + uint32_t const_thread_area; /* Constant argument to ps_get_thread_area. */ + /* These are as if the descriptor of the field in prregset_t, + but DB_DESC_NELEM is overloaded as follows: */ + db_desc_t reg; /* Signed bias applied to register value. */ + db_desc_t reg_thread_area; /* Bits to scale down register value. */ + } ta_howto_data; +}; + + +/* List of all known descriptors. */ +extern list_t __td_agent_list attribute_hidden; + + +/* Function used to test for correct thread agent pointer. */ +static inline bool +ta_ok (const td_thragent_t *ta) +{ + list_t *runp; + + list_for_each (runp, &__td_agent_list) + if (list_entry (runp, td_thragent_t, list) == ta) + return true; + + return false; +} + + +/* Internal wrapper around ps_pglobal_lookup. */ +extern ps_err_e td_lookup (struct ps_prochandle *ps, + int idx, psaddr_t *sym_addr) attribute_hidden; + + + + +/* Store in psaddr_t VAR the address of inferior's symbol NAME. */ +#define DB_GET_SYMBOL(var, ta, name) \ + (((ta)->ta_addr_##name == 0 \ + && td_lookup ((ta)->ph, SYM_##name, &(ta)->ta_addr_##name) != PS_OK) \ + ? TD_ERR : ((var) = (ta)->ta_addr_##name, TD_OK)) + +/* Store in psaddr_t VAR the value of ((TYPE) PTR)->FIELD[IDX] in the inferior. + A target field smaller than psaddr_t is zero-extended. */ +#define DB_GET_FIELD(var, ta, ptr, type, field, idx) \ + _td_fetch_value ((ta), (ta)->ta_field_##type##_##field, \ + SYM_##type##_FIELD_##field, \ + (psaddr_t) 0 + (idx), (ptr), &(var)) + +#define DB_GET_FIELD_ADDRESS(var, ta, ptr, type, field, idx) \ + ((var) = (ptr), _td_locate_field ((ta), (ta)->ta_field_##type##_##field, \ + SYM_##type##_FIELD_##field, \ + (psaddr_t) 0 + (idx), &(var))) + +extern td_err_e _td_locate_field (td_thragent_t *ta, + db_desc_t desc, int descriptor_name, + psaddr_t idx, + psaddr_t *address) attribute_hidden; + + +/* Like DB_GET_FIELD, but PTR is a local pointer to a structure that + has already been copied in from the inferior. */ +#define DB_GET_FIELD_LOCAL(var, ta, ptr, type, field, idx) \ + _td_fetch_value_local ((ta), (ta)->ta_field_##type##_##field, \ + SYM_##type##_FIELD_##field, \ + (psaddr_t) 0 + (idx), (ptr), &(var)) + +/* Store in psaddr_t VAR the value of variable NAME[IDX] in the inferior. + A target value smaller than psaddr_t is zero-extended. */ +#define DB_GET_VALUE(var, ta, name, idx) \ + (((ta)->ta_addr_##name == 0 \ + && td_lookup ((ta)->ph, SYM_##name, &(ta)->ta_addr_##name) != PS_OK) \ + ? TD_ERR \ + : _td_fetch_value ((ta), (ta)->ta_var_##name, SYM_DESC_##name, \ + (psaddr_t) 0 + (idx), (ta)->ta_addr_##name, &(var))) + +/* Helper functions for those. */ +extern td_err_e _td_fetch_value (td_thragent_t *ta, + db_desc_t field, int descriptor_name, + psaddr_t idx, psaddr_t address, + psaddr_t *result) attribute_hidden; +extern td_err_e _td_fetch_value_local (td_thragent_t *ta, + db_desc_t field, + int descriptor_name, + psaddr_t idx, void *address, + psaddr_t *result) attribute_hidden; + +/* Store psaddr_t VALUE in ((TYPE) PTR)->FIELD[IDX] in the inferior. + A target field smaller than psaddr_t is zero-extended. */ +#define DB_PUT_FIELD(ta, ptr, type, field, idx, value) \ + _td_store_value ((ta), (ta)->ta_field_##type##_##field, \ + SYM_##type##_FIELD_##field, \ + (psaddr_t) 0 + (idx), (ptr), (value)) + +#define DB_PUT_FIELD_LOCAL(ta, ptr, type, field, idx, value) \ + _td_store_value_local ((ta), (ta)->ta_field_##type##_##field, \ + SYM_##type##_FIELD_##field, \ + (psaddr_t) 0 + (idx), (ptr), (value)) + +/* Store psaddr_t VALUE in variable NAME[IDX] in the inferior. + A target field smaller than psaddr_t is zero-extended. */ +#define DB_PUT_VALUE(ta, name, idx, value) \ + (((ta)->ta_addr_##name == 0 \ + && td_lookup ((ta)->ph, SYM_##name, &(ta)->ta_addr_##name) != PS_OK) \ + ? TD_ERR \ + : _td_store_value ((ta), (ta)->ta_var_##name, SYM_DESC_##name, \ + (psaddr_t) 0 + (idx), (ta)->ta_addr_##name, (value))) + +/* Helper functions for those. */ +extern td_err_e _td_store_value (td_thragent_t *ta, + db_desc_t field, int descriptor_name, + psaddr_t idx, psaddr_t address, + psaddr_t value) attribute_hidden; +extern td_err_e _td_store_value_local (td_thragent_t *ta, + db_desc_t field, int descriptor_name, + psaddr_t idx, void *address, + psaddr_t value) attribute_hidden; + +#define DB_GET_STRUCT(var, ta, ptr, type) \ + ({ td_err_e _err = TD_OK; \ + if ((ta)->ta_sizeof_##type == 0) \ + _err = _td_check_sizeof ((ta), &(ta)->ta_sizeof_##type, \ + SYM_SIZEOF_##type); \ + if (_err == TD_OK) \ + _err = ps_pdread ((ta)->ph, (ptr), \ + (var) = __alloca ((ta)->ta_sizeof_##type), \ + (ta)->ta_sizeof_##type) \ + == PS_OK ? TD_OK : TD_ERR; \ + else \ + (var) = NULL; \ + _err; \ + }) +#define DB_PUT_STRUCT(ta, ptr, type, copy) \ + ({ assert ((ta)->ta_sizeof_##type != 0); \ + ps_pdwrite ((ta)->ph, (ptr), (copy), (ta)->ta_sizeof_##type) \ + == PS_OK ? TD_OK : TD_ERR; \ + }) + +extern td_err_e _td_check_sizeof (td_thragent_t *ta, uint32_t *sizep, + int sizep_name) attribute_hidden; + +#endif /* thread_dbP.h */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libresolv/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libresolv/Makefile new file mode 100644 index 00000000..c8dc9b46 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libresolv/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../ +top_builddir=../ +include $(top_builddir)Rules.mak +all: libs +include Makefile.in +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libresolv/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/libresolv/Makefile.in new file mode 100644 index 00000000..fb71b421 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libresolv/Makefile.in @@ -0,0 +1,52 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +subdirs += libresolv + +CFLAGS-libresolv := -DNOT_IN_libc -DIS_IN_libresolv $(SSP_ALL_CFLAGS) + +LDFLAGS-libresolv.so := $(LDFLAGS) $(call link.asneeded,-lc) + +LIBS-libresolv.so := $(LIBS) + +libresolv_FULL_NAME := libresolv-$(VERSION).so + +libresolv_DIR := $(top_srcdir)libresolv +libresolv_OUT := $(top_builddir)libresolv + +libresolv_SRC := $(libresolv_DIR)/resolv.c +libresolv_OBJ := $(patsubst $(libresolv_DIR)/%.c,$(libresolv_OUT)/%.o,$(libresolv_SRC)) + +ifeq ($(DOPIC),y) +libresolv-a-y := $(libresolv_OBJ:.o=.os) +else +libresolv-a-y := $(libresolv_OBJ) +endif +libresolv-so-y := $(libresolv_OBJ:.o=.os) + +lib-a-$(UCLIBC_HAS_LIBRESOLV_STUB) += $(top_builddir)lib/libresolv.a +lib-so-$(UCLIBC_HAS_LIBRESOLV_STUB) += $(top_builddir)lib/libresolv.so +objclean-y += CLEAN_libresolv + +ifeq ($(DOPIC),y) +$(top_builddir)lib/libresolv.so: $(top_builddir)lib/libresolv.a $(libc.depend) +else +$(top_builddir)lib/libresolv.so: $(libresolv_OUT)/libresolv_so.a $(libc.depend) +endif + $(call link.so,$(libresolv_FULL_NAME),$(ABI_VERSION)) + +$(libresolv_OUT)/libresolv_so.a: $(libresolv-so-y) + $(Q)$(RM) $@ + $(do_ar) + +$(top_builddir)lib/libresolv.a: $(libresolv-a-y) + $(Q)$(INSTALL) -d $(dir $@) + $(Q)$(RM) $@ + $(do_ar) + +CLEAN_libresolv: + $(do_rm) $(addprefix $(libresolv_OUT)/*., o os a) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libresolv/resolv.c b/l4/pkg/uclibc/lib/contrib/uclibc/libresolv/resolv.c new file mode 100644 index 00000000..38b10ff2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libresolv/resolv.c @@ -0,0 +1,18 @@ +/* vi: set sw=4 ts=4: */ +/* + * libresolv for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +void __stub1(void); +void __stub1(void) +{ + return; +} +link_warning (__stub1, "the `libresolv' library is a stub. Do you really need it?") + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/librt/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/librt/Makefile new file mode 100644 index 00000000..c8dc9b46 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/librt/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../ +top_builddir=../ +include $(top_builddir)Rules.mak +all: libs +include Makefile.in +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/librt/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/librt/Makefile.in new file mode 100644 index 00000000..6eb508cb --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/librt/Makefile.in @@ -0,0 +1,70 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +subdirs += librt + +CFLAGS-librt := -DNOT_IN_libc -DIS_IN_librt $(SSP_ALL_CFLAGS) + +LDFLAGS-librt.so := $(LDFLAGS) +LIBS-librt.so := $(LIBS) +ifeq ($(UCLIBC_HAS_THREADS_NATIVE),y) +LIBS-librt.so += $(top_builddir)lib/libdl.so $(top_builddir)lib/libpthread.so +endif + +librt_FULL_NAME := librt-$(VERSION).so + +librt_DIR := $(top_srcdir)librt +librt_OUT := $(top_builddir)librt + +ifeq ($(UCLIBC_HAS_REALTIME),y) +ifeq ($(UCLIBC_HAS_THREADS_NATIVE),y) +librt_CSRC := $(filter-out mq_notify.c timer_create.c timer_delete.c \ + timer_getoverr.c timer_gettime.c timer_settime.c, \ + $(notdir $(wildcard $(librt_DIR)/*.c))) +librt_SSRC := $(wildcard $(librt_DIR)/*.S) +librt_OBJ := $(patsubst %.c,$(librt_OUT)/%.o,$(librt_CSRC)) +librt_OBJ += $(patsubst $(librt_DIR)/%.S,$(librt_OUT)/%.o,$(librt_SSRC)) +else +librt_SRC := $(filter-out clock_nanosleep.c clock_getcpuclockid.c clock_gettime.c, \ + $(notdir $(wildcard $(librt_DIR)/*.c))) +librt_OBJ := $(patsubst %.c,$(librt_OUT)/%.o,$(librt_SRC)) +endif + +ASFLAGS-mq_timedreceive.S = -D_LIBC_REENTRANT +ASFLAGS-mq_timedsend.S = -D_LIBC_REENTRANT + +ifeq ($(DOPIC),y) +librt-a-y += $(librt_OBJ:.o=.os) +else +librt-a-y += $(librt_OBJ) +endif +librt-so-y += $(librt_OBJ:.o=.oS) + +lib-a-y += $(top_builddir)lib/librt.a +lib-so-y += $(top_builddir)lib/librt.so +endif + + +ifeq ($(DOPIC)$(UCLIBC_HAS_THREADS_NATIVE),yn) +$(top_builddir)lib/librt.so: $(top_builddir)lib/librt.a $(libc.depend) +else +$(top_builddir)lib/librt.so: $(librt_OUT)/librt_so.a $(libc.depend) $(libpthread.depend) $(libdl.depend) +endif + $(call link.so,$(librt_FULL_NAME),$(ABI_VERSION)) + +$(librt_OUT)/librt_so.a: $(librt-so-y) + $(Q)$(RM) $@ + $(do_ar) + +$(top_builddir)lib/librt.a: $(librt-a-y) | $(top_builddir)lib + $(Q)$(RM) $@ + $(do_ar) + +objclean-y += CLEAN_librt + +CLEAN_librt: + $(do_rm) $(addprefix $(librt_OUT)/*., o os oS a) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/librt/clock_getcpuclockid.c b/l4/pkg/uclibc/lib/contrib/uclibc/librt/clock_getcpuclockid.c new file mode 100644 index 00000000..704c5740 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/librt/clock_getcpuclockid.c @@ -0,0 +1,104 @@ +/* clock_getcpuclockid -- Get a clockid_t for process CPU time. Linux version. + Copyright (C) 2004, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include "kernel-posix-cpu-timers.h" + +#ifndef HAS_CPUCLOCK +# define HAS_CPUCLOCK 1 +#endif + +int +clock_getcpuclockid (pid_t pid, clockid_t *clock_id) +{ +#ifdef __NR_clock_getres + /* The clockid_t value is a simple computation from the PID. + But we do a clock_getres call to validate it. */ + + const clockid_t pidclock = MAKE_PROCESS_CPUCLOCK (pid, CPUCLOCK_SCHED); + +# if !(__ASSUME_POSIX_CPU_TIMERS > 0) + extern int __libc_missing_posix_cpu_timers attribute_hidden; +# if !(__ASSUME_POSIX_TIMERS > 0) + extern int __libc_missing_posix_timers attribute_hidden; + if (__libc_missing_posix_timers && !__libc_missing_posix_cpu_timers) + __libc_missing_posix_cpu_timers = 1; +# endif + if (!__libc_missing_posix_cpu_timers) +# endif + { + INTERNAL_SYSCALL_DECL (err); + int r = INTERNAL_SYSCALL (clock_getres, err, 2, pidclock, NULL); + if (!INTERNAL_SYSCALL_ERROR_P (r, err)) + { + *clock_id = pidclock; + return 0; + } + +# if !(__ASSUME_POSIX_TIMERS > 0) + if (INTERNAL_SYSCALL_ERRNO (r, err) == ENOSYS) + { + /* The kernel doesn't support these calls at all. */ + __libc_missing_posix_timers = 1; + __libc_missing_posix_cpu_timers = 1; + } + else +# endif + if (INTERNAL_SYSCALL_ERRNO (r, err) == EINVAL) + { +# if !(__ASSUME_POSIX_CPU_TIMERS > 0) + if (pidclock == MAKE_PROCESS_CPUCLOCK (0, CPUCLOCK_SCHED) + || INTERNAL_SYSCALL_ERROR_P (INTERNAL_SYSCALL + (clock_getres, err, 2, + MAKE_PROCESS_CPUCLOCK + (0, CPUCLOCK_SCHED), NULL), + err)) + /* The kernel doesn't support these clocks at all. */ + __libc_missing_posix_cpu_timers = 1; + else +# endif + /* The clock_getres system call checked the PID for us. */ + return ESRCH; + } + else + return INTERNAL_SYSCALL_ERRNO (r, err); + } +#endif + + /* We don't allow any process ID but our own. */ + if (pid != 0 && pid != getpid ()) + return EPERM; + +#ifdef CLOCK_PROCESS_CPUTIME_ID + if (HAS_CPUCLOCK) + { + /* Store the number. */ + *clock_id = CLOCK_PROCESS_CPUTIME_ID; + + return 0; + } +#endif + + /* We don't have a timer for that. */ + return ENOENT; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/librt/clock_gettime.c b/l4/pkg/uclibc/lib/contrib/uclibc/librt/clock_gettime.c new file mode 100644 index 00000000..8308329b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/librt/clock_gettime.c @@ -0,0 +1,301 @@ +/* clock_gettime -- Get current time from a POSIX clockid_t. Linux version. + Copyright (C) 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include "kernel-posix-cpu-timers.h" +#include + + +#define SYSCALL_GETTIME \ + retval = INLINE_SYSCALL (clock_gettime, 2, clock_id, tp); \ + break + +#ifdef __ASSUME_POSIX_TIMERS + +/* This means the REALTIME and MONOTONIC clock are definitely + supported in the kernel. */ +# define SYSDEP_GETTIME \ + SYSDEP_GETTIME_CPUTIME \ + case CLOCK_REALTIME: \ + case CLOCK_MONOTONIC: \ + SYSCALL_GETTIME + +# define __libc_missing_posix_timers 0 +#elif defined __NR_clock_gettime +/* Is the syscall known to exist? */ +int __libc_missing_posix_timers attribute_hidden; + +static inline int +maybe_syscall_gettime (clockid_t clock_id, struct timespec *tp) +{ + int e = EINVAL; + + if (!__libc_missing_posix_timers) + { + INTERNAL_SYSCALL_DECL (err); + int r = INTERNAL_SYSCALL (clock_gettime, err, 2, clock_id, tp); + if (!INTERNAL_SYSCALL_ERROR_P (r, err)) + return 0; + + e = INTERNAL_SYSCALL_ERRNO (r, err); + if (e == ENOSYS) + { + __libc_missing_posix_timers = 1; + e = EINVAL; + } + } + + return e; +} + +/* The REALTIME and MONOTONIC clock might be available. Try the + syscall first. */ +# define SYSDEP_GETTIME \ + SYSDEP_GETTIME_CPUTIME \ + case CLOCK_REALTIME: \ + case CLOCK_MONOTONIC: \ + retval = maybe_syscall_gettime (clock_id, tp); \ + if (retval == 0) \ + break; \ + /* Fallback code. */ \ + if (retval == EINVAL && clock_id == CLOCK_REALTIME) \ + retval = realtime_gettime (tp); \ + else \ + { \ + __set_errno (retval); \ + retval = -1; \ + } \ + break; +#endif + +#ifdef __NR_clock_gettime +/* We handled the REALTIME clock here. */ +# define HANDLED_REALTIME 1 +# define HANDLED_CPUTIME 1 + +# if __ASSUME_POSIX_CPU_TIMERS > 0 + +# define SYSDEP_GETTIME_CPU SYSCALL_GETTIME +# define SYSDEP_GETTIME_CPUTIME /* Default catches them too. */ + +# else + +int __libc_missing_posix_cpu_timers attribute_hidden; + +static int +maybe_syscall_gettime_cpu (clockid_t clock_id, struct timespec *tp) +{ + int e = EINVAL; + + if (!__libc_missing_posix_cpu_timers) + { + INTERNAL_SYSCALL_DECL (err); + int r = INTERNAL_SYSCALL (clock_gettime, err, 2, clock_id, tp); + if (!INTERNAL_SYSCALL_ERROR_P (r, err)) + return 0; + + e = INTERNAL_SYSCALL_ERRNO (r, err); +# ifndef __ASSUME_POSIX_TIMERS + if (e == ENOSYS) + { + __libc_missing_posix_timers = 1; + __libc_missing_posix_cpu_timers = 1; + e = EINVAL; + } + else +# endif + { + if (e == EINVAL) + { + /* Check whether the kernel supports CPU clocks at all. + If not, record it for the future. */ + r = INTERNAL_SYSCALL (clock_getres, err, 2, + MAKE_PROCESS_CPUCLOCK (0, CPUCLOCK_SCHED), + NULL); + if (INTERNAL_SYSCALL_ERROR_P (r, err)) + __libc_missing_posix_cpu_timers = 1; + } + } + } + + return e; +} + +# define SYSDEP_GETTIME_CPU \ + retval = maybe_syscall_gettime_cpu (clock_id, tp); \ + if (retval == 0) \ + break; \ + if (retval != EINVAL || !__libc_missing_posix_cpu_timers) \ + { \ + __set_errno (retval); \ + retval = -1; \ + break; \ + } \ + retval = -1 /* Otherwise continue on to the HP_TIMING version. */; + +static inline int +maybe_syscall_gettime_cputime (clockid_t clock_id, struct timespec *tp) +{ + return maybe_syscall_gettime_cpu + (clock_id == CLOCK_THREAD_CPUTIME_ID + ? MAKE_THREAD_CPUCLOCK (0, CPUCLOCK_SCHED) + : MAKE_PROCESS_CPUCLOCK (0, CPUCLOCK_SCHED), + tp); +} + +# define SYSDEP_GETTIME_CPUTIME \ + case CLOCK_PROCESS_CPUTIME_ID: \ + case CLOCK_THREAD_CPUTIME_ID: \ + retval = maybe_syscall_gettime_cputime (clock_id, tp); \ + if (retval == 0) \ + break; \ + if (retval != EINVAL || !__libc_missing_posix_cpu_timers) \ + { \ + __set_errno (retval); \ + retval = -1; \ + break; \ + } \ + retval = hp_timing_gettime (clock_id, tp); \ + break; +# if !HP_TIMING_AVAIL +# define hp_timing_gettime(clock_id, tp) (__set_errno (EINVAL), -1) +# endif + +# endif +#endif + +#include +#include +#include +#include +#include +#include + + +#if HP_TIMING_AVAIL +/* Clock frequency of the processor. We make it a 64-bit variable + because some jokers are already playing with processors with more + than 4GHz. */ +static hp_timing_t freq; + + +/* This function is defined in the thread library. */ +extern int __pthread_clock_gettime (clockid_t clock_id, hp_timing_t freq, + struct timespec *tp) + __attribute__ ((__weak__)); + +static int +hp_timing_gettime (clockid_t clock_id, struct timespec *tp) +{ + hp_timing_t tsc; + + if (__builtin_expect (freq == 0, 0)) + { + /* This can only happen if we haven't initialized the `freq' + variable yet. Do this now. We don't have to protect this + code against multiple execution since all of them should + lead to the same result. */ + freq = __get_clockfreq (); + if (__builtin_expect (freq == 0, 0)) + /* Something went wrong. */ + return -1; + } + + if (clock_id != CLOCK_PROCESS_CPUTIME_ID + && __pthread_clock_gettime != NULL) + return __pthread_clock_gettime (clock_id, freq, tp); + + /* Get the current counter. */ + HP_TIMING_NOW (tsc); + + /* Compute the offset since the start time of the process. */ + tsc -= GL(dl_cpuclock_offset); + + /* Compute the seconds. */ + tp->tv_sec = tsc / freq; + + /* And the nanoseconds. This computation should be stable until + we get machines with about 16GHz frequency. */ + tp->tv_nsec = ((tsc % freq) * UINT64_C (1000000000)) / freq; + + return 0; +} +#endif + + +static inline int +realtime_gettime (struct timespec *tp) +{ + struct timeval tv; + int retval = gettimeofday (&tv, NULL); + if (retval == 0) + /* Convert into `timespec'. */ + TIMEVAL_TO_TIMESPEC (&tv, tp); + return retval; +} + +librt_hidden_proto (clock_gettime) +/* Get current value of CLOCK and store it in TP. */ +int +clock_gettime (clockid_t clock_id, struct timespec *tp) +{ + int retval = -1; +#ifndef HANDLED_REALTIME + struct timeval tv; +#endif + + switch (clock_id) + { +#ifdef SYSDEP_GETTIME + SYSDEP_GETTIME; +#endif + +#ifndef HANDLED_REALTIME + case CLOCK_REALTIME: + retval = gettimeofday (&tv, NULL); + if (retval == 0) + TIMEVAL_TO_TIMESPEC (&tv, tp); + break; +#endif + + default: +#ifdef SYSDEP_GETTIME_CPU + SYSDEP_GETTIME_CPU; +#endif +#if HP_TIMING_AVAIL + if ((clock_id & ((1 << CLOCK_IDFIELD_SIZE) - 1)) + == CLOCK_THREAD_CPUTIME_ID) + retval = hp_timing_gettime (clock_id, tp); + else +#endif + __set_errno (EINVAL); + break; + +#if HP_TIMING_AVAIL && !defined HANDLED_CPUTIME + case CLOCK_PROCESS_CPUTIME_ID: + retval = hp_timing_gettime (clock_id, tp); + break; +#endif + } + + return retval; +} +librt_hidden_def (clock_gettime) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/librt/clock_nanosleep.c b/l4/pkg/uclibc/lib/contrib/uclibc/librt/clock_nanosleep.c new file mode 100644 index 00000000..69e60087 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/librt/clock_nanosleep.c @@ -0,0 +1,96 @@ +/* Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +#include +#include +#include "kernel-posix-cpu-timers.h" + + +#ifdef __ASSUME_POSIX_TIMERS +/* We can simply use the syscall. The CPU clocks are not supported + with this function. */ +int +clock_nanosleep (clockid_t clock_id, int flags, const struct timespec *req, + struct timespec *rem) +{ + INTERNAL_SYSCALL_DECL (err); + int r; + + if (clock_id == CLOCK_THREAD_CPUTIME_ID) + return EINVAL; + if (clock_id == CLOCK_PROCESS_CPUTIME_ID) + clock_id = MAKE_PROCESS_CPUCLOCK (0, CPUCLOCK_SCHED); + + if (SINGLE_THREAD_P) + r = INTERNAL_SYSCALL (clock_nanosleep, err, 4, clock_id, flags, req, rem); + else + { + int oldstate = LIBC_CANCEL_ASYNC (); + + r = INTERNAL_SYSCALL (clock_nanosleep, err, 4, clock_id, flags, req, + rem); + + LIBC_CANCEL_RESET (oldstate); + } + + return (INTERNAL_SYSCALL_ERROR_P (r, err) + ? INTERNAL_SYSCALL_ERRNO (r, err) : 0); +} + +#else +# ifdef __NR_clock_nanosleep +/* Is the syscall known to exist? */ +extern int __libc_missing_posix_timers attribute_hidden; + +/* The REALTIME and MONOTONIC clock might be available. Try the + syscall first. */ +# define SYSDEP_NANOSLEEP \ + if (!__libc_missing_posix_timers) \ + { \ + clockid_t syscall_clockid; \ + INTERNAL_SYSCALL_DECL (err); \ + \ + if (clock_id == CLOCK_THREAD_CPUTIME_ID) \ + return EINVAL; \ + if (clock_id == CLOCK_PROCESS_CPUTIME_ID) \ + syscall_clockid = MAKE_PROCESS_CPUCLOCK (0, CPUCLOCK_SCHED); \ + else \ + syscall_clockid = clock_id; \ + \ + int oldstate = LIBC_CANCEL_ASYNC (); \ + \ + int r = INTERNAL_SYSCALL (clock_nanosleep, err, 4, \ + syscall_clockid, flags, req, rem); \ + \ + LIBC_CANCEL_RESET (oldstate); \ + \ + if (!INTERNAL_SYSCALL_ERROR_P (r, err)) \ + return 0; \ + \ + if (INTERNAL_SYSCALL_ERRNO (r, err) != ENOSYS) \ + return INTERNAL_SYSCALL_ERRNO (r, err); \ + \ + __libc_missing_posix_timers = 1; \ + } +# endif + +# include +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/librt/kernel-posix-cpu-timers.h b/l4/pkg/uclibc/lib/contrib/uclibc/librt/kernel-posix-cpu-timers.h new file mode 100644 index 00000000..164a90dd --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/librt/kernel-posix-cpu-timers.h @@ -0,0 +1,18 @@ +/* Parameters for the Linux kernel ABI for CPU clocks. */ + +#define CPUCLOCK_PID(clock) ((pid_t) ~((clock) >> 3)) +#define CPUCLOCK_PERTHREAD(clock) \ + (((clock) & (clockid_t) CPUCLOCK_PERTHREAD_MASK) != 0) +#define CPUCLOCK_PID_MASK 7 +#define CPUCLOCK_PERTHREAD_MASK 4 +#define CPUCLOCK_WHICH(clock) ((clock) & (clockid_t) CPUCLOCK_CLOCK_MASK) +#define CPUCLOCK_CLOCK_MASK 3 +#define CPUCLOCK_PROF 0 +#define CPUCLOCK_VIRT 1 +#define CPUCLOCK_SCHED 2 +#define CPUCLOCK_MAX 3 + +#define MAKE_PROCESS_CPUCLOCK(pid, clock) \ + ((~(clockid_t) (pid) << 3) | (clockid_t) (clock)) +#define MAKE_THREAD_CPUCLOCK(tid, clock) \ + MAKE_PROCESS_CPUCLOCK((tid), (clock) | CPUCLOCK_PERTHREAD_MASK) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/librt/kernel-posix-timers.h b/l4/pkg/uclibc/lib/contrib/uclibc/librt/kernel-posix-timers.h new file mode 100644 index 00000000..f8bfdc2a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/librt/kernel-posix-timers.h @@ -0,0 +1,58 @@ +/* + * kernel-posix-timers.h - kernel-dependent definitions for POSIX timers. + */ + +#include +#include +#include +#include +#ifdef __UCLIBC_HAS_THREADS__ +#include +#endif + +#ifdef __UCLIBC_HAS_THREADS_NATIVE__ +/* Nonzero if the system calls are not available. */ +extern int __no_posix_timers attribute_hidden; + +/* Callback to start helper thread. */ +extern void __start_helper_thread (void) attribute_hidden; + +/* Control variable for helper thread creation. */ +extern pthread_once_t __helper_once attribute_hidden; + +/* TID of the helper thread. */ +extern pid_t __helper_tid attribute_hidden; + +/* List of active SIGEV_THREAD timers. */ +extern struct timer *__active_timer_sigev_thread attribute_hidden; +/* Lock for the __active_timer_sigev_thread. */ +extern pthread_mutex_t __active_timer_sigev_thread_lock attribute_hidden; +#endif + +/* Type of timers in the kernel */ +typedef int kernel_timer_t; + +/* Internal representation of timer */ +struct timer { + /* Notification mechanism */ + int sigev_notify; + + /* Timer ID returned by the kernel */ + kernel_timer_t ktimerid; + + /* + * All new elements must be added after ktimerid. And if the thrfunc + * element is not the third element anymore the memory allocation in + * timer_create needs to be changed. + */ + + /* Parameters for the thread to be started for SIGEV_THREAD */ + void (*thrfunc) (sigval_t); + sigval_t sival; +#ifdef __UCLIBC_HAS_THREADS__ + pthread_attr_t attr; +#endif + + /* Next element in list of active SIGEV_THREAD timers. */ + struct timer *next; +}; diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/librt/mq_close.c b/l4/pkg/uclibc/lib/contrib/uclibc/librt/mq_close.c new file mode 100644 index 00000000..cf04044c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/librt/mq_close.c @@ -0,0 +1,22 @@ +/* + * mq_close.c - close a message queue. + */ + +#include +#include +#include + +#include + +#ifdef __NR_mq_open + +/* + * Remove the association between message queue descriptor and its + * message queue. + */ +int mq_close(mqd_t mqdes) +{ + return close(mqdes); +} + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/librt/mq_getsetattr.c b/l4/pkg/uclibc/lib/contrib/uclibc/librt/mq_getsetattr.c new file mode 100644 index 00000000..b50d9a97 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/librt/mq_getsetattr.c @@ -0,0 +1,36 @@ +/* + * mq_getattr.c - get message queue attributes. + */ + +#include +#include +#include + +#include + +#ifdef __NR_mq_getsetattr + +librt_hidden_proto(mq_setattr) +#define __NR___syscall_mq_getsetattr __NR_mq_getsetattr +static __inline__ _syscall3(int, __syscall_mq_getsetattr, int, mqdes, + const void *, mqstat, void *, omqstat); + +/* + * Set attributes associated with message queue (and possibly also get + * its old attributes) + */ +int mq_setattr(mqd_t mqdes, const struct mq_attr *mqstat, + struct mq_attr *omqstat) +{ + return __syscall_mq_getsetattr(mqdes, mqstat, omqstat); +} + +librt_hidden_def(mq_setattr) + +/* Query status and attributes of message queue */ +int mq_getattr(mqd_t mqdes, struct mq_attr *mqstat) +{ + return mq_setattr(mqdes, NULL, mqstat); +} + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/librt/mq_notify.c b/l4/pkg/uclibc/lib/contrib/uclibc/librt/mq_notify.c new file mode 100644 index 00000000..2556669b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/librt/mq_notify.c @@ -0,0 +1,28 @@ +/* + * mq_notify.c - notify process that a message is available. + */ + +#include +#include +#include + +#include + +#ifdef __NR_mq_notify + +#define __NR___syscall_mq_notify __NR_mq_notify +static __inline__ _syscall2(int, __syscall_mq_notify, int, mqdes, + const void *, notification); + +/* Register notification upon message arrival to an empty message queue */ +int mq_notify(mqd_t mqdes, const struct sigevent *notification) +{ + /* We don't support SIGEV_THREAD notification yet */ + if (notification != NULL && notification->sigev_notify == SIGEV_THREAD) { + __set_errno(ENOSYS); + return -1; + } + return __syscall_mq_notify(mqdes, notification); +} + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/librt/mq_open.c b/l4/pkg/uclibc/lib/contrib/uclibc/librt/mq_open.c new file mode 100644 index 00000000..62c83103 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/librt/mq_open.c @@ -0,0 +1,52 @@ +/* + * mq_open.c - open a message queue. + */ + +#include +#include +#include +#include + +#include + +#ifdef __NR_mq_open + +#define __NR___syscall_mq_open __NR_mq_open +static __inline__ _syscall4(int, __syscall_mq_open, const char *, name, + int, oflag, __kernel_mode_t, mode, void *, attr); +/* + * Establish connection between a process and a message queue and + * return message queue descriptor or (mqd_t) -1 on error. + * oflag determines the type of access used. If O_CREAT is on oflag, the + * third argument is taken as a `mode_t', the mode of the created + * message queue, and the fourth argument is taken as `struct mq_attr *', + * pointer to message queue attributes. + * If the fourth argument is NULL, default attributes are used. + */ +mqd_t mq_open(const char *name, int oflag, ...) +{ + mode_t mode; + struct mq_attr *attr; + + if (name[0] != '/') { + __set_errno(EINVAL); + return -1; + } + + mode = 0; + attr = NULL; + + if (oflag & O_CREAT) { + va_list ap; + + va_start(ap, oflag); + mode = va_arg(ap, mode_t); + attr = va_arg(ap, struct mq_attr *); + + va_end(ap); + } + + return __syscall_mq_open(name + 1, oflag, mode, attr); +} + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/librt/mq_receive.c b/l4/pkg/uclibc/lib/contrib/uclibc/librt/mq_receive.c new file mode 100644 index 00000000..40447dfb --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/librt/mq_receive.c @@ -0,0 +1,46 @@ +/* + * mq_receive.c - functions for receiving from message queue. + */ + +#include +#include +#include +#include +#warning FIXME: hard dependency on ADVANCED REALTIME feature + +librt_hidden_proto(mq_timedreceive) + +#ifndef __UCLIBC_HAS_THREADS_NATIVE__ +#ifdef __NR_mq_timedreceive +#define __NR___syscall_mq_timedreceive __NR_mq_timedreceive +static __inline__ _syscall5(int, __syscall_mq_timedreceive, int, mqdes, + char *, msg_ptr, size_t, msg_len, unsigned int *, + msg_prio, const void *, abs_timeout); +#endif + +/* + * Receive the oldest from highest priority messages. + * Stop waiting if abs_timeout expires. + */ +ssize_t mq_timedreceive(mqd_t mqdes, char *msg_ptr, size_t msg_len, + unsigned int *msg_prio, + const struct timespec *abs_timeout) +{ +#ifdef __NR_mq_timedreceive + return __syscall_mq_timedreceive(mqdes, msg_ptr, msg_len, msg_prio, + abs_timeout); +#else + errno = ENOSYS; + return -1; +#endif +} + +librt_hidden_def(mq_timedreceive) +#endif + +/* Receive the oldest from highest priority messages */ +ssize_t mq_receive(mqd_t mqdes, char *msg_ptr, size_t msg_len, + unsigned int *msg_prio) +{ + return mq_timedreceive(mqdes, msg_ptr, msg_len, msg_prio, NULL); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/librt/mq_send.c b/l4/pkg/uclibc/lib/contrib/uclibc/librt/mq_send.c new file mode 100644 index 00000000..f0fcfa35 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/librt/mq_send.c @@ -0,0 +1,45 @@ +/* + * mq_send.c - functions for sending to message queue. + */ + +#include +#include +#include +#include +#warning FIXME: hard dependency on ADVANCED REALTIME feature + +librt_hidden_proto(mq_timedsend) + +#ifndef __UCLIBC_HAS_THREADS_NATIVE__ +#ifdef __NR_mq_timedsend +#define __NR___syscall_mq_timedsend __NR_mq_timedsend +static __inline__ _syscall5(int, __syscall_mq_timedsend, int, mqdes, + const char *, msg_ptr, size_t, msg_len, unsigned int, + msg_prio, const void *, abs_timeout); +#endif + +/* + * Add a message to queue. If O_NONBLOCK is set and queue is full, wait + * for sufficient room in the queue until abs_timeout expires. + */ +int mq_timedsend(mqd_t mqdes, const char *msg_ptr, size_t msg_len, + unsigned int msg_prio, const struct timespec *abs_timeout) +{ +#ifdef __NR_mq_timedsend + return __syscall_mq_timedsend(mqdes, msg_ptr, msg_len, msg_prio, + abs_timeout); +#else + errno = ENOSYS; + return -1; +#endif +} + +librt_hidden_def(mq_timedsend) +#endif + +/* Add a message to queue */ +int mq_send(mqd_t mqdes, const char *msg_ptr, size_t msg_len, + unsigned int msg_prio) +{ + return mq_timedsend(mqdes, msg_ptr, msg_len, msg_prio, NULL); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/librt/mq_timedreceive.S b/l4/pkg/uclibc/lib/contrib/uclibc/librt/mq_timedreceive.S new file mode 100644 index 00000000..015eb884 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/librt/mq_timedreceive.S @@ -0,0 +1,10 @@ +#include +#ifndef __NR_mq_timedreceive +#error Missing definition of NR_timedreceive needed for cancellation. +#endif +PSEUDO (__mq_timedreceive, mq_timedreceive, 5) +ret +PSEUDO_END(__mq_timedreceive) +librt_hidden_def (__mq_timedreceive) +weak_alias (__mq_timedreceive, mq_timedreceive) +librt_hidden_weak (mq_timedreceive) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/librt/mq_timedsend.S b/l4/pkg/uclibc/lib/contrib/uclibc/librt/mq_timedsend.S new file mode 100644 index 00000000..67758a3b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/librt/mq_timedsend.S @@ -0,0 +1,10 @@ +#include +#ifndef __NR_mq_timedsend +#error Missing definition of NR_timedsend needed for cancellation. +#endif +PSEUDO (__mq_timedsend, mq_timedsend, 5) +ret +PSEUDO_END(__mq_timedsend) +librt_hidden_def (__mq_timedsend) +weak_alias (__mq_timedsend, mq_timedsend) +librt_hidden_weak (mq_timedsend) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/librt/mq_unlink.c b/l4/pkg/uclibc/lib/contrib/uclibc/librt/mq_unlink.c new file mode 100644 index 00000000..3c490e0c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/librt/mq_unlink.c @@ -0,0 +1,39 @@ +/* + * mq_unlink.c - remove a message queue. + */ + +#include +#include + +#include + +#ifdef __NR_mq_unlink + +#define __NR___syscall_mq_unlink __NR_mq_unlink +static __inline__ _syscall1(int, __syscall_mq_unlink, const char *, name); + +/* Remove message queue */ +int mq_unlink(const char *name) +{ + int ret; + + if (name[0] != '/') { + __set_errno(EINVAL); + return -1; + } + + ret = __syscall_mq_unlink(name + 1); + + /* While unlink can return either EPERM or EACCES, mq_unlink should return just EACCES. */ + if (ret < 0) { + ret = errno; + if (ret == EPERM) + ret = EACCES; + __set_errno(ret); + ret = -1; + } + + return ret; +} + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/librt/shm.c b/l4/pkg/uclibc/lib/contrib/uclibc/librt/shm.c new file mode 100644 index 00000000..40e69fa2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/librt/shm.c @@ -0,0 +1,102 @@ +/* Copyright (C) 2009 Bernhard Reutner-Fischer + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef _PATH_SHM +#define _PATH_SHM "/dev/shm/" +#endif + +#ifndef NAME_MAX +#define NAME_MAX 255 +#endif + +/* Get name of dummy shm operation handle. + * Returns a malloc'ed buffer containing the OS specific path + * to the shm filename or NULL upon failure. + */ +static __attribute_noinline__ char* get_shm_name(const char *name) __nonnull((1)); +static char* get_shm_name(const char *name) +{ + char *path; + int i; + + /* Skip leading slashes */ + while (*name == '/') + ++name; +#ifdef __USE_GNU + i = asprintf(&path, _PATH_SHM "%s", name); + if (i < 0) + return NULL; +#else + path = malloc(NAME_MAX); + if (path == NULL) + return NULL; + i = snprintf(path, NAME_MAX, _PATH_SHM "%s", name); + if (i < 0) { + free(path); + return NULL; + } else if (i >= NAME_MAX) { + free(path); + __set_errno(ENAMETOOLONG); + return NULL; + } +#endif + return path; +} + +int shm_open(const char *name, int oflag, mode_t mode) +{ + int fd; + char *shm_name = get_shm_name(name); + + /* Stripped multiple '/' from start; may have set errno properly */ + if (shm_name == NULL) + return -1; + /* The FD_CLOEXEC file descriptor flag associated with the new + * file descriptor is set. */ +#ifdef O_CLOEXEC + /* Just open it with CLOEXEC set, for brevity */ + fd = open(shm_name, oflag | O_CLOEXEC, mode); +#else + fd = open(shm_name, oflag, mode); + if (fd >= 0) { + fcntl(fd, F_SETFD, FD_CLOEXEC); + /* thus far, {G,S}ETFD only has this single flag, + * and setting it never fails. + *int fdflags = fcntl(fd, F_GETFD); + *if (fdflags >= 0) + * fdflags = fcntl(fd, F_SETFD, fdflags | FD_CLOEXEC); + *if (fdflags < 0) { + * close(fd); + * fd = -1; + *} + */ + } +#endif + free(shm_name); /* doesn't affect errno */ + return fd; +} + +int shm_unlink(const char *name) +{ + char *shm_name = get_shm_name(name); + int ret; + + /* Stripped multiple '/' from start; may have set errno properly */ + if (shm_name == NULL) + return -1; + ret = unlink(shm_name); + free(shm_name); /* doesn't affect errno */ + return ret; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/librt/timer_create.c b/l4/pkg/uclibc/lib/contrib/uclibc/librt/timer_create.c new file mode 100644 index 00000000..9298a37c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/librt/timer_create.c @@ -0,0 +1,71 @@ +/* + * timer_create.c - create a per-process timer. + */ + +#include +#include +#include +#include +#include +#include + +#include "kernel-posix-timers.h" + +#ifdef __NR_timer_create + +#ifndef offsetof +# define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) +#endif + +#define __NR___syscall_timer_create __NR_timer_create +static __inline__ _syscall3(int, __syscall_timer_create, clockid_t, clock_id, + struct sigevent *, evp, kernel_timer_t *, ktimerid); + +/* Create a per-process timer */ +int timer_create(clockid_t clock_id, struct sigevent *evp, timer_t * timerid) +{ + int retval; + kernel_timer_t ktimerid; + struct sigevent default_evp; + struct timer *newp; + + if (evp == NULL) { + /* + * The kernel has to pass up the timer ID which is a userlevel object. + * Therefore we cannot leave it up to the kernel to determine it. + */ + default_evp.sigev_notify = SIGEV_SIGNAL; + default_evp.sigev_signo = SIGALRM; + evp = &default_evp; + } + + /* Notification via a thread is not supported yet */ + if (__builtin_expect(evp->sigev_notify == SIGEV_THREAD, 1)) + return -1; + + /* + * We avoid allocating too much memory by basically using + * struct timer as a derived class with the first two elements + * being in the superclass. We only need these two elements here. + */ + newp = malloc(offsetof(struct timer, thrfunc)); + if (newp == NULL) + return -1; /* No memory */ + default_evp.sigev_value.sival_ptr = newp; + + retval = __syscall_timer_create(clock_id, evp, &ktimerid); + if (retval != -1) { + newp->sigev_notify = evp->sigev_notify; + newp->ktimerid = ktimerid; + + *timerid = (timer_t) newp; + } else { + /* Cannot allocate the timer, fail */ + free(newp); + retval = -1; + } + + return retval; +} + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/librt/timer_delete.c b/l4/pkg/uclibc/lib/contrib/uclibc/librt/timer_delete.c new file mode 100644 index 00000000..af6b34f5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/librt/timer_delete.c @@ -0,0 +1,33 @@ +/* + * timer_delete.c - delete a per-process timer. + */ + +#include +#include +#include +#include + +#include "kernel-posix-timers.h" + +#ifdef __NR_timer_delete + +#define __NR___syscall_timer_delete __NR_timer_delete +static __inline__ _syscall1(int, __syscall_timer_delete, kernel_timer_t, ktimerid); + +/* Delete a per-process timer */ +int timer_delete(timer_t timerid) +{ + int res; + struct timer *kt = (struct timer *)timerid; + + /* Delete the kernel timer object */ + res = __syscall_timer_delete(kt->ktimerid); + if (res == 0) { + free(kt); /* Free the memory */ + return 0; + } + + return -1; +} + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/librt/timer_getoverr.c b/l4/pkg/uclibc/lib/contrib/uclibc/librt/timer_getoverr.c new file mode 100644 index 00000000..0e855168 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/librt/timer_getoverr.c @@ -0,0 +1,26 @@ +/* + * timer-getoverr.c - get the timer overrun count. + */ + +#include +#include +#include + +#include "kernel-posix-timers.h" + +#ifdef __NR_timer_getoverrun + +#define __NR___syscall_timer_getoverrun __NR_timer_getoverrun +static __inline__ _syscall1(int, __syscall_timer_getoverrun, kernel_timer_t, + ktimerid); + +/* Get the timer overrun count */ +int timer_getoverrun(timer_t timerid) +{ + struct timer *kt = (struct timer *)timerid; + + /* Get the information from the kernel */ + return __syscall_timer_getoverrun(kt->ktimerid); +} + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/librt/timer_gettime.c b/l4/pkg/uclibc/lib/contrib/uclibc/librt/timer_gettime.c new file mode 100644 index 00000000..e13f4464 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/librt/timer_gettime.c @@ -0,0 +1,27 @@ +/* + * timer_gettime.c - get the timer value. + */ + +#include +#include +#include +#include + +#include "kernel-posix-timers.h" + +#ifdef __NR_timer_gettime + +#define __NR___syscall_timer_gettime __NR_timer_gettime +static __inline__ _syscall2(int, __syscall_timer_gettime, kernel_timer_t, ktimerid, + void *, value); + +/* Get the amount of time left on a timer */ +int timer_gettime(timer_t timerid, struct itimerspec *value) +{ + struct timer *kt = (struct timer *)timerid; + + /* Get timeout from the kernel */ + return __syscall_timer_gettime(kt->ktimerid, value); +} + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/librt/timer_settime.c b/l4/pkg/uclibc/lib/contrib/uclibc/librt/timer_settime.c new file mode 100644 index 00000000..2703fa91 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/librt/timer_settime.c @@ -0,0 +1,28 @@ +/* + * timer_settime.c - set the timer. + */ + +#include +#include +#include +#include + +#include "kernel-posix-timers.h" + +#ifdef __NR_timer_settime + +#define __NR___syscall_timer_settime __NR_timer_settime +static __inline__ _syscall4(int, __syscall_timer_settime, kernel_timer_t, ktimerid, + int, flags, const void *, value, void *, ovalue); + +/* Set the expiration time for a timer */ +int timer_settime(timer_t timerid, int flags, const struct itimerspec *value, + struct itimerspec *ovalue) +{ + struct timer *kt = (struct timer *)timerid; + + /* Set timeout */ + return __syscall_timer_settime(kt->ktimerid, flags, value, ovalue); +} + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libubacktrace/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libubacktrace/Makefile new file mode 100644 index 00000000..0f746383 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libubacktrace/Makefile @@ -0,0 +1,14 @@ +# Makefile for uClibc (libubacktrace) +# +# Copyright (C) 2010 STMicroelectronics Ltd +# Author(s): Carmelo Amoroso +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../ +top_builddir=../ +include $(top_builddir)Rules.mak +all: libs +include Makefile.in +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libubacktrace/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/libubacktrace/Makefile.in new file mode 100644 index 00000000..c1dd5d7a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libubacktrace/Makefile.in @@ -0,0 +1,84 @@ +# Makefile for uClibc (libubacktrace) +# +# Copyright (C) 2010 STMicroelectronics Ltd +# Author: Carmelo Amoroso + +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +subdirs += libubacktrace + +CFLAGS-libubacktrace := -DNOT_IN_libc -DIS_IN_libubacktrace $(SSP_ALL_CFLAGS) + +LDFLAGS-libubacktrace.so := $(LDFLAGS) $(top_builddir)lib/libdl-$(VERSION).so + +LIBS-libubacktrace.so := $(LIBS) + +libubacktrace_FULL_NAME := libubacktrace-$(VERSION).so + +libubacktrace_DIR := $(top_srcdir)libubacktrace +libubacktrace_OUT := $(top_builddir)libubacktrace +libubacktrace_ARCH_DIR := $(libubacktrace_DIR)/sysdeps/$(TARGET_ARCH) +libubacktrace_ARCH_OUT := $(libubacktrace_OUT)/sysdeps/$(TARGET_ARCH) + +-include $(libubacktrace_ARCH_DIR)/Makefile.arch + +libubacktrace_SRC-y := +libubacktrace_SRC-$(UCLIBC_HAS_BACKTRACE) := backtrace.c backtracesyms.c backtracesymsfd.c + +CFLAGS-libubacktrace/sysdeps/$(TARGET_ARCH)/ := $(CFLAGS-libubacktrace) + +# remove generic sources, if arch specific version is present +ifneq ($(strip $(libubacktrace_ARCH_SRC-y)),) +libubacktrace_SRC-y := $(filter-out $(notdir $(libubacktrace_ARCH_SRC-y)),$(libubacktrace_SRC-y)) +libubacktrace_ARCH_SRC := $(addprefix $(libubacktrace_ARCH_DIR)/,$(libubacktrace_ARCH_SRC-y)) +libubacktrace_ARCH_OBJ := $(patsubst $(libubacktrace_ARCH_DIR)/%.c,$(libubacktrace_ARCH_OUT)/%.o,$(libubacktrace_ARCH_SRC)) +endif + + +libubacktrace_SRC := $(addprefix $(libubacktrace_DIR)/,$(libubacktrace_SRC-y)) +libubacktrace_OBJ := $(patsubst $(libubacktrace_DIR)/%.c,$(libubacktrace_OUT)/%.o,$(libubacktrace_SRC)) + +libubacktrace_SRCS := $(libubacktrace_SRC) $(libubacktrace_ARCH_SRC) +libubacktrace_OBJS := $(libubacktrace_OBJ) $(libubacktrace_ARCH_OBJ) + +ifeq ($(DOPIC),y) +libubacktrace-a-y := $(libubacktrace_OBJS:.o=.os) +else +libubacktrace-a-y := $(libubacktrace_OBJS) +endif +libubacktrace-so-y := $(libubacktrace_OBJS:.o=.os) + +lib-a-$(UCLIBC_HAS_BACKTRACE) += $(top_builddir)lib/libubacktrace.a +lib-so-$(UCLIBC_HAS_BACKTRACE) += $(top_builddir)lib/libubacktrace.so + +objclean-y += CLEAN_libubacktrace + +ifeq ($(DOMULTI),n) +ifeq ($(DOPIC),y) +$(top_builddir)lib/libubacktrace.so: $(top_builddir)lib/libubacktrace.a $(libdl.depend) +else +$(top_builddir)lib/libubacktrace.so: $(libubacktrace_OUT)/libubacktrace_so.a $(libdl.depend) +endif + $(call link.so,$(libubacktrace_FULL_NAME),$(ABI_VERSION)) +else +$(top_builddir)lib/libubacktrace.so: $(libubacktrace_OUT)/libubacktrace.oS | $(libdl.depend) + $(call linkm.so,$(libubacktrace_FULL_NAME),$(ABI_VERSION)) +endif + +$(libubacktrace_OUT)/libubacktrace_so.a: $(libubacktrace-so-y) + $(Q)$(RM) $@ + $(do_ar) + +$(libubacktrace_OUT)/libubacktrace.oS: $(libubacktrace_SRCS) + $(Q)$(RM) $@ + $(compile-m) + +$(top_builddir)lib/libubacktrace.a: $(libubacktrace-a-y) + $(Q)$(INSTALL) -d $(dir $@) + $(Q)$(RM) $@ + $(do_ar) + +CLEAN_libubacktrace: + $(do_rm) $(addprefix $(libubacktrace_OUT)/*., o os oS a) \ + $(addprefix $(libubacktrace_ARCH_OUT)/*., o os oS a) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libubacktrace/backtrace.c b/l4/pkg/uclibc/lib/contrib/uclibc/libubacktrace/backtrace.c new file mode 100644 index 00000000..87218002 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libubacktrace/backtrace.c @@ -0,0 +1,19 @@ +/* + * Perform stack unwinding by using the _Unwind_Backtrace. + * + * User application that wants to use backtrace needs to be + * compiled with -fexceptions option and -rdynamic to get full + * symbols printed. + + * Copyright (C) 2010 STMicroelectronics Ltd + * Author(s): Carmelo Amoroso + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + */ +#error "Arch specific implementation must be provided to properly work" +int backtrace (void **array, int size) +{ + return -1; +} + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libubacktrace/backtracesyms.c b/l4/pkg/uclibc/lib/contrib/uclibc/libubacktrace/backtracesyms.c new file mode 100644 index 00000000..4486fee9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libubacktrace/backtracesyms.c @@ -0,0 +1,105 @@ +/* Return list with names for address in backtrace. + Copyright (C) 1998,1999,2000,2001,2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. + + Based on glibc/sysdeps/generic/elf/backtracesyms.c + + Copyright (C) 2010 STMicroelectronics Ltd + Author(s): Carmelo Amoroso + * Modified to work with uClibc + - updated headers inclusion + - updated formatting and style + - updated to use dladdr from libdl */ + +#include +#include +#include +#include +#include + +#include +#include /* required for __ELF_NATIVE_CLASS */ + +#if __ELF_NATIVE_CLASS == 32 +# define WORD_WIDTH 8 +#else +/* We assyme 64bits. */ +# define WORD_WIDTH 16 +#endif + + +char ** backtrace_symbols (void *const *array, int size) +{ + Dl_info info[size]; + int status[size]; + int cnt; + size_t total = 0; + char **result; + + /* Fill in the information we can get from `dladdr'. */ + for (cnt = 0; cnt < size; ++cnt) { + status[cnt] = dladdr (array[cnt], &info[cnt]); + if (status[cnt] && info[cnt].dli_fname && + info[cnt].dli_fname[0] != '\0') + /* + * We have some info, compute the length of the string which will be + * "() [+offset]. + */ + total += (strlen (info[cnt].dli_fname ?: "") + + (info[cnt].dli_sname ? + strlen (info[cnt].dli_sname) + 3 + WORD_WIDTH + 3 : 1) + + WORD_WIDTH + 5); + else + total += 5 + WORD_WIDTH; + } + + /* Allocate memory for the result. */ + result = (char **) malloc (size * sizeof (char *) + total); + if (result != NULL) { + char *last = (char *) (result + size); + for (cnt = 0; cnt < size; ++cnt) { + result[cnt] = last; + + if (status[cnt] && info[cnt].dli_fname + && info[cnt].dli_fname[0] != '\0') { + + char buf[20]; + + if (array[cnt] >= (void *) info[cnt].dli_saddr) + sprintf (buf, "+%#lx", + (unsigned long)(array[cnt] - info[cnt].dli_saddr)); + else + sprintf (buf, "-%#lx", + (unsigned long)(info[cnt].dli_saddr - array[cnt])); + + last += 1 + sprintf (last, "%s%s%s%s%s[%p]", + info[cnt].dli_fname ?: "", + info[cnt].dli_sname ? "(" : "", + info[cnt].dli_sname ?: "", + info[cnt].dli_sname ? buf : "", + info[cnt].dli_sname ? ") " : " ", + array[cnt]); + } else + last += 1 + sprintf (last, "[%p]", array[cnt]); + } + assert (last <= (char *) result + size * sizeof (char *) + total); + } + + return result; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libubacktrace/backtracesymsfd.c b/l4/pkg/uclibc/lib/contrib/uclibc/libubacktrace/backtracesymsfd.c new file mode 100644 index 00000000..66d7687c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libubacktrace/backtracesymsfd.c @@ -0,0 +1,116 @@ +/* Write formatted list with names for addresses in backtrace to a file. + Copyright (C) 1998, 2000, 2003, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. + + Based on glibc/sysdeps/generic/elf/backtracesymsfd.c + + Copyright (C) 2010 STMicroelectronics Ltd + Author(s): Carmelo Amoroso + * Modified to work with uClibc + - updated headers inclusion + - updated formatting and style + - updated to use dladdr from libdl + - updated to use snprintf instead of _itoa_word */ + +#include +#include +#include +#include +#include +#include /* required for __ELF_NATIVE_CLASS */ + +#if __ELF_NATIVE_CLASS == 32 +# define WORD_WIDTH 8 +#else +/* We assyme 64bits. */ +# define WORD_WIDTH 16 +#endif + +#define BUF_SIZE (WORD_WIDTH + 1) + +void backtrace_symbols_fd (void *const *array, int size, int fd) +{ + struct iovec iov[9]; + int cnt; + + for (cnt = 0; cnt < size; ++cnt) { + char buf[BUF_SIZE]; + Dl_info info; + size_t last = 0; + size_t len = 0; + + memset(buf, 0, sizeof(buf)); + if (dladdr (array[cnt], &info) + && info.dli_fname && info.dli_fname[0] != '\0') { + /* Name of the file. */ + iov[0].iov_base = (void *) info.dli_fname; + iov[0].iov_len = strlen (info.dli_fname); + last = 1; + + /* Symbol name. */ + if (info.dli_sname != NULL) { + char buf2[BUF_SIZE]; + memset(buf2, 0, sizeof(buf2)); + size_t diff; + + iov[1].iov_base = (void *) "("; + iov[1].iov_len = 1; + iov[2].iov_base = (void *) info.dli_sname; + iov[2].iov_len = strlen (info.dli_sname); + + if (array[cnt] >= (void *) info.dli_saddr) { + iov[3].iov_base = (void *) "+0x"; + diff = array[cnt] - info.dli_saddr; + } else { + iov[3].iov_base = (void *) "-0x"; + diff = info.dli_saddr - array[cnt]; + } + + iov[3].iov_len = 3; + + /* convert diff to a string in hex format */ + len = snprintf(buf2, sizeof(buf2), "%lx", (unsigned long) diff); + iov[4].iov_base = buf2; + iov[4].iov_len = len; + + iov[5].iov_base = (void *) ")"; + iov[5].iov_len = 1; + + last = 6; + } + } + + iov[last].iov_base = (void *) "[0x"; + iov[last].iov_len = 3; + ++last; + + /* convert array[cnt] to a string in hex format */ + len = snprintf(buf, sizeof(buf), "%lx", (unsigned long) array[cnt]); + iov[last].iov_base = buf; + iov[last].iov_len = len; + + ++last; + + iov[last].iov_base = (void *) "]\n"; + iov[last].iov_len = 2; + ++last; + + writev (fd, iov, last); + } +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libubacktrace/sysdeps/sh/Makefile.arch b/l4/pkg/uclibc/lib/contrib/uclibc/libubacktrace/sysdeps/sh/Makefile.arch new file mode 100644 index 00000000..9b0de385 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libubacktrace/sysdeps/sh/Makefile.arch @@ -0,0 +1,12 @@ +# Makefile for uClibc (sh/libubacktrace) +# +# Copyright (C) 2010 STMicroelectronics Ltd +# Author: Carmelo Amoroso + +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +libubacktrace_ARCH_SRC-y := backtrace.c + +# -fexections is required for backtrace to work using dwarf2 +CFLAGS-backtrace.c := -fexceptions diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libubacktrace/sysdeps/sh/backtrace.c b/l4/pkg/uclibc/lib/contrib/uclibc/libubacktrace/sysdeps/sh/backtrace.c new file mode 100644 index 00000000..18b91b1b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libubacktrace/sysdeps/sh/backtrace.c @@ -0,0 +1,84 @@ +/* + * Perform stack unwinding by using the _Unwind_Backtrace. + * + * User application that wants to use backtrace needs to be + * compiled with -fexceptions option and -rdynamic to get full + * symbols printed. + * + * Copyright (C) 2009, 2010 STMicroelectronics Ltd. + * + * Author(s): Giuseppe Cavallaro + * - Initial implementation for glibc + * + * Author(s): Carmelo Amoroso + * - Reworked for uClibc + * - use dlsym/dlopen from libdl + * - rewrite initialisation to not use libc_once + * - make it available in static link too + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + * + */ + +#include +#include +#include +#include +#include +#include + +struct trace_arg +{ + void **array; + int cnt, size; +}; + +static _Unwind_Reason_Code (*unwind_backtrace) (_Unwind_Trace_Fn, void *); +static _Unwind_Ptr (*unwind_getip) (struct _Unwind_Context *); + +static void backtrace_init (void) +{ + void *handle = dlopen ("libgcc_s.so.1", RTLD_LAZY); + + if (handle == NULL + || ((unwind_backtrace = dlsym (handle, "_Unwind_Backtrace")) == NULL) + || ((unwind_getip = dlsym (handle, "_Unwind_GetIP")) == NULL)) { + printf("libgcc_s.so.1 must be installed for backtrace to work\n"); + abort(); + } +} + +static _Unwind_Reason_Code +backtrace_helper (struct _Unwind_Context *ctx, void *a) +{ + struct trace_arg *arg = a; + + assert (unwind_getip != NULL); + + /* We are first called with address in the __backtrace function. Skip it. */ + if (arg->cnt != -1) + arg->array[arg->cnt] = (void *) unwind_getip (ctx); + if (++arg->cnt == arg->size) + return _URC_END_OF_STACK; + return _URC_NO_REASON; +} + +/* + * Perform stack unwinding by using the _Unwind_Backtrace. + * + * User application that wants to use backtrace needs to be + * compiled with -fexceptions option and -rdynamic to get full + * symbols printed. + */ +int backtrace (void **array, int size) +{ + struct trace_arg arg = { .array = array, .size = size, .cnt = -1 }; + + if (unwind_backtrace == NULL) + backtrace_init(); + + if (size >= 1) + unwind_backtrace (backtrace_helper, &arg); + + return arg.cnt != -1 ? arg.cnt : 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libutil/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/libutil/Makefile new file mode 100644 index 00000000..c8dc9b46 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libutil/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../ +top_builddir=../ +include $(top_builddir)Rules.mak +all: libs +include Makefile.in +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libutil/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/libutil/Makefile.in new file mode 100644 index 00000000..057d02de --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libutil/Makefile.in @@ -0,0 +1,68 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2008 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +subdirs += libutil + +CFLAGS-libutil := -DNOT_IN_libc -DIS_IN_libutil $(SSP_ALL_CFLAGS) + +LDFLAGS-libutil.so := $(LDFLAGS) + +LIBS-libutil.so := $(LIBS) + +libutil_FULL_NAME := libutil-$(VERSION).so + +libutil_DIR := $(top_srcdir)libutil +libutil_OUT := $(top_builddir)libutil + +libutil_SRC := $(wildcard $(libutil_DIR)/*.c) +ifneq ($(ARCH_USE_MMU),y) +libutil_SRC := $(filter-out $(libutil_DIR)/forkpty.c,$(libutil_SRC)) +endif +ifneq ($(UCLIBC_HAS_PTY),y) +libutil_SRC := $(filter-out $(libutil_DIR)/openpty.c $(libutil_DIR)/forkpty.c \ + ,$(libutil_SRC)) +endif +libutil_OBJ := $(patsubst $(libutil_DIR)/%.c,$(libutil_OUT)/%.o,$(libutil_SRC)) + +ifeq ($(DOPIC),y) +libutil-a-y := $(libutil_OBJ:.o=.os) +else +libutil-a-y := $(libutil_OBJ) +endif +libutil-so-y := $(libutil_OBJ:.o=.os) + +lib-a-$(UCLIBC_HAS_LIBUTIL) += $(top_builddir)lib/libutil.a +lib-so-$(UCLIBC_HAS_LIBUTIL) += $(top_builddir)lib/libutil.so +objclean-y += CLEAN_libutil + +ifeq ($(DOMULTI),n) +ifeq ($(DOPIC),y) +$(top_builddir)lib/libutil.so: $(top_builddir)lib/libutil.a $(libc.depend) +else +$(top_builddir)lib/libutil.so: $(libutil_OUT)/libutil_so.a $(libc.depend) +endif + $(call link.so,$(libutil_FULL_NAME),$(ABI_VERSION)) +else +$(top_builddir)lib/libutil.so: $(libutil_OUT)/libutil.oS | $(libc.depend) + $(call linkm.so,$(libutil_FULL_NAME),$(ABI_VERSION)) +endif + +$(libutil_OUT)/libutil_so.a: $(libutil-so-y) + $(Q)$(RM) $@ + $(do_ar) + +$(libutil_OUT)/libutil.oS: $(libutil_SRC) + $(Q)$(RM) $@ + $(compile-m) + +$(top_builddir)lib/libutil.a: $(libutil-a-y) + $(Q)$(INSTALL) -d $(dir $@) + $(Q)$(RM) $@ + $(do_ar) + +CLEAN_libutil: + $(do_rm) $(addprefix $(libutil_OUT)/*., o os oS a) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libutil/forkpty.c b/l4/pkg/uclibc/lib/contrib/uclibc/libutil/forkpty.c new file mode 100644 index 00000000..61e85929 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libutil/forkpty.c @@ -0,0 +1,55 @@ +/* Copyright (C) 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Zack Weinberg , 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include + +libutil_hidden_proto(openpty) +libutil_hidden_proto(login_tty) + +int +forkpty (int *amaster, char *name, struct termios *termp, struct winsize *winp) +{ + int master, slave, pid; + + if (openpty (&master, &slave, name, termp, winp) == -1) + return -1; + + switch (pid = fork ()) + { + case -1: + return -1; + case 0: + /* Child. */ + close (master); + if (login_tty (slave)) + _exit (1); + + return 0; + default: + /* Parent. */ + *amaster = master; + close (slave); + + return pid; + } +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libutil/login.c b/l4/pkg/uclibc/lib/contrib/uclibc/libutil/login.c new file mode 100644 index 00000000..4007e4c7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libutil/login.c @@ -0,0 +1,60 @@ +#include +#include +#include +#include +#include +#include + +/* Write the given entry into utmp and wtmp. + * Note: the match in utmp is done against ut_id field, + * which is NOT set by this function - caller must set it. + */ +void login(const struct utmp *entry) +{ + struct utmp copy; + char tty_name[sizeof(copy.ut_line) + 6]; + int fd; + +// Manpage: +// login() takes the argument ut struct, fills the field ut->ut_type +// (if there is such a field) with the value USER_PROCESS, +// and fills the field ut->ut_pid (if there is such a field) +// with the process ID of the calling process. + copy = *entry; +#if _HAVE_UT_TYPE - 0 + copy.ut_type = USER_PROCESS; +#endif +#if _HAVE_UT_PID - 0 + copy.ut_pid = getpid(); +#endif + +// Then it tries to fill the field ut->ut_line. It takes the first of stdin, +// stdout, stderr that is a tty, and stores the corresponding pathname minus +// a possible leading /dev/ into this field, and then writes the struct +// to the utmp file. On the other hand, if no tty name was found, +// this field is filled with "???" and the struct is not written +// to the utmp file. + fd = 0; + while (fd != 3 && ttyname_r(fd, tty_name, sizeof(tty_name)) != 0) + fd++; + if (fd != 3) { + if (strncmp(tty_name, "/dev/", 5) == 0) + strncpy(copy.ut_line, tty_name + 5, sizeof(copy.ut_line)-1); + else + strncpy(copy.ut_line, tty_name, sizeof(copy.ut_line)-1); + copy.ut_line[sizeof(copy.ut_line)-1] = '\0'; + + /* utmpname(_PATH_UTMP); - why? + * this makes it impossible for caller to use other file! + * Does any standard or historical precedent says this must be done? */ + setutent(); + /* Replaces record with matching ut_id, or appends new one: */ + pututline(©); + endutent(); + } else { + strncpy(copy.ut_line, "???", sizeof(copy.ut_line)); + } + +// After this, the struct is written to the wtmp file. + updwtmp(_PATH_WTMP, ©); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libutil/login_tty.c b/l4/pkg/uclibc/lib/contrib/uclibc/libutil/login_tty.c new file mode 100644 index 00000000..3979adce --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libutil/login_tty.c @@ -0,0 +1,71 @@ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* Make FD be the controlling terminal, stdin, stdout, and stderr; + then close FD. Returns 0 on success, nonzero on error. */ + +#include +#include +#include +#include +#include + +libutil_hidden_proto(login_tty) +int login_tty(int fd) +{ + (void) setsid(); +#ifdef TIOCSCTTY + if (ioctl(fd, TIOCSCTTY, (char *)NULL) == -1) + return (-1); +#else + { + /* This might work. */ + char *fdname = ttyname (fd); + int newfd; + if (fdname) + { + if (fd != 0) + (void) close (0); + if (fd != 1) + (void) close (1); + if (fd != 2) + (void) close (2); + newfd = open (fdname, O_RDWR); + (void) close (newfd); + } + } +#endif + (void) dup2(fd, 0); + (void) dup2(fd, 1); + (void) dup2(fd, 2); + if (fd > 2) + (void) close(fd); + return (0); +} +libutil_hidden_def(login_tty) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libutil/logout.c b/l4/pkg/uclibc/lib/contrib/uclibc/libutil/logout.c new file mode 100644 index 00000000..5f58b8f4 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libutil/logout.c @@ -0,0 +1,79 @@ +/* Copyright (C) 1996, 1997, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1996. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + +int +logout (const char *line) +{ + struct utmp tmp; + struct utmp *ut; + int result = 0; + + /* if (utmpname (_PATH_UTMP) == -1) return 0; - why? + * this makes it impossible for caller to use other file! + * Does any standard or historical precedent says this must be done? */ + + /* Open UTMP file. */ + setutent (); + + /* Fill in search information. */ +#if _HAVE_UT_TYPE - 0 + tmp.ut_type = USER_PROCESS; +#endif + strncpy (tmp.ut_line, line, sizeof tmp.ut_line); + + /* Read the record. */ + if ((ut = getutline(&tmp)) != NULL) + { + /* Clear information about who & from where. */ + memset (ut->ut_name, 0, sizeof ut->ut_name); +#if _HAVE_UT_HOST - 0 + memset (ut->ut_host, 0, sizeof ut->ut_host); +#endif +#if _HAVE_UT_TV - 0 +# if !defined __WORDSIZE_COMPAT32 || __WORDSIZE_COMPAT32 == 0 + gettimeofday (&ut->ut_tv, NULL); +# else + { + struct timeval tv; + gettimeofday (&tv, NULL); + ut->ut_tv.tv_sec = tv.tv_sec; + ut->ut_tv.tv_usec = tv.tv_usec; + } +# endif +#else + time (&ut->ut_time); +#endif +#if _HAVE_UT_TYPE - 0 + ut->ut_type = DEAD_PROCESS; +#endif + + if (pututline (ut) != NULL) + result = 1; + } + + /* Close UTMP file. */ + endutent (); + + return result; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libutil/logwtmp.c b/l4/pkg/uclibc/lib/contrib/uclibc/libutil/logwtmp.c new file mode 100644 index 00000000..2a6f28a4 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libutil/logwtmp.c @@ -0,0 +1,55 @@ +/* vi: set sw=4 ts=4: */ +/* + * wtmp support rubbish (i.e. complete crap) + * Copyright (C) 2000-2006 by Erik Andersen + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include +#include +#include +#include + +void logwtmp(const char *line, const char *name, const char *host) +{ + struct utmp lutmp; + memset(&lutmp, 0, sizeof(lutmp)); + + lutmp.ut_type = (name && *name) ? USER_PROCESS : DEAD_PROCESS; + lutmp.ut_pid = getpid(); + strncpy(lutmp.ut_line, line, sizeof(lutmp.ut_line)-1); + strncpy(lutmp.ut_name, name, sizeof(lutmp.ut_name)-1); + strncpy(lutmp.ut_host, host, sizeof(lutmp.ut_host)-1); +#if !defined __WORDSIZE_COMPAT32 || __WORDSIZE_COMPAT32 == 0 + gettimeofday(&lutmp.ut_tv, NULL); +#else + { + struct timeval tv; + gettimeofday(&tv, NULL); + lutmp.ut_tv.tv_sec = tv.tv_sec; + lutmp.ut_tv.tv_usec = tv.tv_usec; + } +#endif + + updwtmp(_PATH_WTMP, &lutmp); +} + +#if 0 +/* This is enabled in uClibc/libc/misc/utmp/wtent.c */ +void updwtmp(const char *wtmp_file, const struct utmp *lutmp) +{ + int fd; + + fd = open(wtmp_file, O_APPEND | O_WRONLY); + if (fd >= 0) { + if (lockf(fd, F_LOCK, 0) == 0) { + write(fd, lutmp, sizeof(*lutmp)); + lockf(fd, F_ULOCK, 0); + close(fd); + } + } +} +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/libutil/openpty.c b/l4/pkg/uclibc/lib/contrib/uclibc/libutil/openpty.c new file mode 100644 index 00000000..5f58476e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/libutil/openpty.c @@ -0,0 +1,157 @@ +/* Copyright (C) 1998, 1999, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Zack Weinberg , 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* BCS: the following function is, IMO, overkill */ +#if 0 +/* Return the result of ptsname_r in the buffer pointed to by PTS, + which should be of length BUF_LEN. If it is too long to fit in + this buffer, a sufficiently long buffer is allocated using malloc, + and returned in PTS. 0 is returned upon success, -1 otherwise. */ +static int +pts_name (int fd, char **pts, size_t buf_len) +{ + int rv; + char *buf = *pts; + + for (;;) + { + char *new_buf; + + if (buf_len) + { + rv = ptsname_r (fd, buf, buf_len); + + if (rv != 0 || memchr (buf, '\0', buf_len)) + /* We either got an error, or we succeeded and the + returned name fit in the buffer. */ + break; + + /* Try again with a longer buffer. */ + buf_len += buf_len; /* Double it */ + } + else + /* No initial buffer; start out by mallocing one. */ + buf_len = 128; /* First time guess. */ + + if (buf != *pts) + /* We've already malloced another buffer at least once. */ + new_buf = realloc (buf, buf_len); + else + new_buf = malloc (buf_len); + if (! new_buf) + { + rv = -1; + __set_errno (ENOMEM); + break; + } + buf = new_buf; + } + + if (rv == 0) + *pts = buf; /* Return buffer to the user. */ + else if (buf != *pts) + free (buf); /* Free what we malloced when returning an error. */ + + return rv; +} +#endif + +/* Create pseudo tty master slave pair and set terminal attributes + according to TERMP and WINP. Return handles for both ends in + AMASTER and ASLAVE, and return the name of the slave end in NAME. */ +libutil_hidden_proto(openpty) +int +openpty (int *amaster, int *aslave, char *name, struct termios *termp, + struct winsize *winp) +{ +#if 0 +#ifdef PATH_MAX + char _buf[PATH_MAX]; +#else + char _buf[512]; +#endif + char *buf = _buf; +#else +#ifdef PATH_MAX + char buf[PATH_MAX]; +#else + char buf[512]; +#endif +#endif + int master, slave; + + master = posix_openpt (O_RDWR); + if (master == -1) + return -1; + + if (grantpt (master)) + goto fail; + + if (unlockpt (master)) + goto fail; + +#if 0 + if (pts_name (master, &buf, sizeof (_buf))) +#else + if (ptsname_r (master, buf, sizeof buf)) +#endif + goto fail; + + slave = open (buf, O_RDWR | O_NOCTTY); + if (slave == -1) + { +#if 0 + if (buf != _buf) + free (buf); +#endif + goto fail; + } + + /* XXX Should we ignore errors here? */ + if(termp) + tcsetattr (slave, TCSAFLUSH, termp); + if (winp) + ioctl (slave, TIOCSWINSZ, winp); + + *amaster = master; + *aslave = slave; + if (name != NULL) + strcpy (name, buf); + +#if 0 + if (buf != _buf) + free (buf); +#endif + return 0; + + fail: + close (master); + return -1; +} +libutil_hidden_def(openpty) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/.gitignore b/l4/pkg/uclibc/lib/contrib/uclibc/test/.gitignore new file mode 100644 index 00000000..991ce5f8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/.gitignore @@ -0,0 +1,304 @@ +# +# Never ignore these +# +!.gitignore +# +# Generated files +# +*.out +# +# Executable test +# +*_glibc +argp/argp-ex[1-4] +argp/argp-test +argp/bug-argp1 +argp/tst-argp[12] +args/arg_test +assert/assert +crypt/crypt +crypt/md5c-test +ctype/ctype +dlopen/dladdr +dlopen/dlafk +dlopen/dlstatic +dlopen/dltest +dlopen/dltest2 +dlopen/dlundef +dlopen/libafk.so +dlopen/libafk-temp.so +dlopen/libstatic.so +dlopen/libtest[123].so +dlopen/libtest.so +dlopen/libundef.so +dlopen/test[1-3] +inet/bug-if1 +inet/gethost_r-align +inet/if_nameindex +inet/tst-aton +inet/tst-ethers +inet/tst-ethers-line +inet/tst-network +inet/tst-ntoa +inet/gethostid +inet/getnetent +librt/shmtest +locale/bug-iconv-trans +locale/collate-test +locale/dump-ctype +locale/gen-unicode-ctype +locale-mbwc/tst_iswalnum +locale-mbwc/tst_iswalpha +locale-mbwc/tst_iswcntrl +locale-mbwc/tst_iswctype +locale-mbwc/tst_iswdigit +locale-mbwc/tst_iswgraph +locale-mbwc/tst_iswlower +locale-mbwc/tst_iswprint +locale-mbwc/tst_iswpunct +locale-mbwc/tst_iswspace +locale-mbwc/tst_iswupper +locale-mbwc/tst_iswxdigit +locale-mbwc/tst_mblen +locale-mbwc/tst_mbrlen +locale-mbwc/tst_mbrtowc +locale-mbwc/tst_mbsrtowcs +locale-mbwc/tst_mbstowcs +locale-mbwc/tst_mbtowc +locale-mbwc/tst_strcoll +locale-mbwc/tst_strxfrm +locale-mbwc/tst_swscanf +locale-mbwc/tst_towctrans +locale-mbwc/tst_towlower +locale-mbwc/tst_towupper +locale-mbwc/tst_wcrtomb +locale-mbwc/tst_wcscat +locale-mbwc/tst_wcschr +locale-mbwc/tst_wcscmp +locale-mbwc/tst_wcscoll +locale-mbwc/tst_wcscpy +locale-mbwc/tst_wcscspn +locale-mbwc/tst_wcslen +locale-mbwc/tst_wcsncat +locale-mbwc/tst_wcsncmp +locale-mbwc/tst_wcsncpy +locale-mbwc/tst_wcspbrk +locale-mbwc/tst_wcsrtombs +locale-mbwc/tst_wcsspn +locale-mbwc/tst_wcsstr +locale-mbwc/tst_wcstod +locale-mbwc/tst_wcstok +locale-mbwc/tst_wcstombs +locale-mbwc/tst_wcswidth +locale-mbwc/tst_wcsxfrm +locale-mbwc/tst_wctob +locale-mbwc/tst_wctomb +locale-mbwc/tst_wctrans +locale-mbwc/tst_wctype +locale-mbwc/tst_wcwidth +locale-mbwc/tst2_mbrtowc +locale/show-ucs-data +locale/tst-digits +locale/tst-langinfo +locale/tst-mbswcs[1-6] +locale/tst_nl_langinfo +locale/tst-numeric +locale/tst-setlocale +locale/tst-sscanf +locale/tst-trans +locale/tst-wctype +malloc/malloc +malloc/mallocbug +malloc/malloc-standard-alignment +malloc/realloc0 +malloc/realloc-can-shrink +malloc/testmalloc +malloc/tst-[cmv]alloc +malloc/tst-mallocfork +malloc/tst-mcheck +malloc/tst-obstack +math/basic-test +math/compile_test +math/c99_test +math/ilogb +math/libm-test-ulps.h +math/libm-test.c +math/rint +math/signgam +math/test-double +math/test-ildoubl +math/test-ldouble +math/test-float +math/test-fpucw +math/test-idouble +math/test-ifloat +math/tst-definitions +misc/bug-glob2 +misc/bug-readdir1 +misc/dirent +misc/dirent64 +misc/fdopen +misc/opendir-tst1 +misc/popen +misc/seek +misc/sem +misc/stdarg +misc/tst-scandir +misc/tst-seekdir +misc/tst-utmp +mmap/mmap +mmap/mmap2 +mmap/mmap64 +nptl/tst-align +nptl/tst-align2 +nptl/tst-align3 +nptl/tst-atfork1 +nptl/tst-attr[1-3] +nptl/tst-barrier[1-4] +nptl/tst-basic[1-7] +nptl/tst-cancel[1-9] +nptl/tst-cancelx[2-4] +nptl/tst-cancelx[6-9] +nptl/tst-cancelx1[0-8] +nptl/tst-cancelx2[0-1] +nptl/tst-cancel[1-3][0-9] +nptl/tst-cleanup[0-4] +nptl/tst-cleanupx[0-4] +nptl/tst-clock +nptl/tst-clock[12] +nptl/tst-clock_nanosleep +nptl/tst-cond[1-9] +nptl/tst-cond[1-2][0-9] +nptl/tst-cpuclock[12] +nptl/tst-cputimer[1-3] +nptl/tst-detach1 +nptl/tst-dlsym1 +nptl/tst-eintr[1-5] +nptl/tst-exec[2-4] +nptl/tst-exit[1-3] +nptl/tst-fini1 +nptl/tst-fini1mod.so +nptl/tst-flock[1-2] +nptl/tst-fork[1-4] +nptl/tst-getpid[1-3] +nptl/tst-initializers1 +nptl/tst-initializers1-c[89]9 +nptl/tst-initializers1-gnu[89]9 +nptl/tst-join[1-6] +nptl/tst-key[1-4] +nptl/tst-kill[1-6] +nptl/tst-mqueue[1-9] +nptl/tst-mutex[1-9] +nptl/tst-mutex[57]a +nptl/tst-once[1-4] +nptl/tst-oncex[3-4] +nptl/tst-popen1 +nptl/tst-oddstacklimit +nptl/tst-raise1 +nptl/tst-rwlock[1-9] +nptl/tst-rwlock1[0-4] +nptl/tst-rwlock2a +nptl/tst-sched1 +nptl/tst-sem[1-9] +nptl/tst-sem1[0-2] +nptl/tst-signal[1-7] +nptl/tst-spin[1-3] +nptl/tst-stack[12] +nptl/tst-stdio[12] +nptl/tst-sysconf +nptl/tst-timer[2-5] +nptl/tst-tls[1-5] +nptl/tst-tls4mod.so +nptl/tst-tls?mod[a-f].so +nptl/tst-tls4modb.so +nptl/tst-tls[35]mod.so +nptl/tst-tls6.sh +nptl/tst-tsd[1-6] +nptl/tst-typesizes +nptl/tst-umask1 +nptl/tst-unload +nptl/tst-vfork[12]x +pthread/cancellation-points +pthread/ex[1-7] +pthread/tst-too-many-cleanups +pwd_grp/getgroups +pwd_grp/grcat +pwd_grp/pwcat +pwd_grp/test_grp +pwd_grp/test_pwd +regex/testregex +regex/tst-regex2 +regex/tst-regexloc +rpc/getrpcent +rpc/getrpcent_r +setjmp/bug269-setjmp +setjmp/jmpbug +setjmp/sigjmpbug +setjmp/tst-setjmp +setjmp/tst-vfork-longjmp +signal/sigchld +signal/signal +signal/tst-raise +signal/tst-signal +signal/tst-sigset +signal/tst-sigsimple +silly/hello +silly/tiny +stat/memcmp-stat +stat/stat +stat/stat64 +stdio/64bit +stdio/fclose-loop +stdlib/ptytest +stdlib/qsort +stdlib/testatexit +stdlib/test-canon +stdlib/test-canon2 +stdlib/teston_exit +stdlib/teststrtol +stdlib/teststrtoq +string/bug-strcoll1 +string/bug-strncat1 +string/bug-strpbrk1 +string/bug-strspn1 +string/stratcliff +string/testcopy +string/tester +string/test-ffs +string/tst-bswap +string/tst-inlcall +string/tst-strlen +string/tst-strtok +string/tst-strxfrm +termios/termios +time/clocktest +time/test_time +time/tst-ctime +time/tst-ftime_l +time/tst-futimens1 +time/tst-mktime +time/tst-mktime3 +time/tst-strptime2 +time/tst_wcsftime +tls/tst-tls[1-9] +tls/tst-tls1[0-8] +tls/tst-tls-at-ctor +tls/tst-tlsmod[1-9].so +tls/tst-tlsmod1[0-9].so +tls/tst-tlsmod1[0-9][ab].so +tls/tst-tlsmod1[78]a[0-9].so +tls/tst-tlsmod1[78]a1[0-9].so +tls/tst-tlsmod-at-ctor.so +unistd/clone +unistd/errno +unistd/exec-null +unistd/fork +unistd/getconf +unistd/getconf.c +unistd/getcwd +unistd/getopt +unistd/getopt_long +unistd/tstgetopt +unistd/tst-preadwrite +unistd/tst-preadwrite64 +unistd/vfork diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/Makefile new file mode 100644 index 00000000..458d6c53 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/Makefile @@ -0,0 +1,7 @@ +# uClibc API tests +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + +top_builddir=../../ +include ../Rules.mak +-include Makefile.in +include ../Test.mak diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/Makefile.in new file mode 100644 index 00000000..9e7cfdf5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/Makefile.in @@ -0,0 +1,26 @@ +# uClibc API tests +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + +SHELL_TESTS := shell_tst-API +run: $(SHELL_TESTS) + +define get_codes + $(subst .,,$(sort $(suffix $(subst -,.,$(foreach x,$(1),$(if $(findstring -,$(x)),$(x),)))))) +endef +sym_files = $(patsubst %.syms,%,$(wildcard *.syms)) +stds = $(patsubst .%,%,$(sort $(suffix $(sym_files)))) +tests=$(foreach s,$(stds),$(patsubst %.$(s),%,$(sym_files))) +codes=$(call get_codes,$(tests)) + +shell_tst-API: uclibc_out=$(patsubst shell_%,%,$@).out +shell_tst-API: glibc_out=$(patsubst shell_%,%_glibc,$@).out +shell_tst-API: + @exec echo "DISABLED for now, needs improvement" +shell_tst-API_DISABLED: + $(showtest) + $(Q)top_builddir=$(top_builddir) AWK=$(AWK) \ + uclibc_out=$(uclibc_out) glibc_out=$(glibc_out) \ + $(SHELL) \ + $(patsubst shell_%,%.sh,$@) $(stds) "$(tests)" + $(do_showdiff) $(glibc_out) $(uclibc_out) ; \ + exec diff -u "$(glibc_out)" "$(uclibc_out)" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/aio.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/aio.SUSv4.syms new file mode 100644 index 00000000..c7d13e09 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/aio.SUSv4.syms @@ -0,0 +1,8 @@ +aio_cancel +aio_error +aio_fsync +aio_read +aio_return +aio_suspend +aio_write +lio_listio diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/arpa_inet.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/arpa_inet.SUSv4.syms new file mode 100644 index 00000000..e61cc9f7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/arpa_inet.SUSv4.syms @@ -0,0 +1,8 @@ +htonl +htons +ntohl +ntohs +inet_addr +inet_ntoa +inet_ntop +inet_pton diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/complex.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/complex.SUSv4.syms new file mode 100644 index 00000000..ce7be69c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/complex.SUSv4.syms @@ -0,0 +1,66 @@ +cabs +cabsf +cabsl +cacos +cacosf +cacosh +cacoshf +cacoshl +cacosl +carg +cargf +cargl +casin +casinf +casinh +casinhf +casinhl +casinl +catan +catanf +catanh +catanhf +catanhl +catanl +ccos +ccosf +ccosh +ccoshf +ccoshl +ccosl +cexp +cexpf +cexpl +cimag +cimagf +cimagl +clog +clogf +clogl +conj +conjf +conjl +cpow +cpowf +cpowl +cproj +cprojf +cprojl +creal +crealf +creall +csin +csinf +csinh +csinhf +csinhl +csinl +csqrt +csqrtf +csqrtl +ctan +ctanf +ctanh +ctanhf +ctanhl +ctanl diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/ctype-CX.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/ctype-CX.SUSv4.syms new file mode 100644 index 00000000..3963c49a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/ctype-CX.SUSv4.syms @@ -0,0 +1,14 @@ +isalnum_l +isalpha_l +isblank_l +iscntrl_l +isdigit_l +isgraph_l +islower_l +isprint_l +ispunct_l +isspace_l +isupper_l +isxdigit_l +tolower_l +toupper_l diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/ctype-OBXSI.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/ctype-OBXSI.SUSv4.syms new file mode 100644 index 00000000..7a5ad9b1 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/ctype-OBXSI.SUSv4.syms @@ -0,0 +1,2 @@ +isascii +toascii diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/ctype.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/ctype.SUSv4.syms new file mode 100644 index 00000000..fac123f3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/ctype.SUSv4.syms @@ -0,0 +1,14 @@ +isalnum +isalpha +isblank +iscntrl +isdigit +isgraph +islower +isprint +ispunct +isspace +isupper +isxdigit +tolower +toupper diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/dirent-XSI.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/dirent-XSI.SUSv4.syms new file mode 100644 index 00000000..97910709 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/dirent-XSI.SUSv4.syms @@ -0,0 +1,2 @@ +seekdir +telldir diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/dirent.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/dirent.SUSv4.syms new file mode 100644 index 00000000..e749efb6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/dirent.SUSv4.syms @@ -0,0 +1,9 @@ +alphasort +closedir +dirfd +fdopendir +opendir +readdir +readdir_r +rewinddir +scandir diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/dlfcn.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/dlfcn.SUSv4.syms new file mode 100644 index 00000000..1e7500ef --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/dlfcn.SUSv4.syms @@ -0,0 +1,4 @@ +dlclose +dlerror +dlopen +dlsym diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/fcntl-ADV.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/fcntl-ADV.SUSv4.syms new file mode 100644 index 00000000..899236e5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/fcntl-ADV.SUSv4.syms @@ -0,0 +1,2 @@ +posix_fadvise +posix_fallocate diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/fcntl.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/fcntl.SUSv4.syms new file mode 100644 index 00000000..588085b1 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/fcntl.SUSv4.syms @@ -0,0 +1,4 @@ +creat +fcntl +open +openat diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/fenv.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/fenv.SUSv4.syms new file mode 100644 index 00000000..a9aebcbd --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/fenv.SUSv4.syms @@ -0,0 +1,11 @@ +feclearexcept +fegetenv +fegetexceptflag +fegetround +feholdexcept +feraiseexcept +fesetenv +fesetexceptflag +fesetround +fetestexcept +feupdateenv diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/ftw-OB.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/ftw-OB.SUSv4.syms new file mode 100644 index 00000000..87a440fc --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/ftw-OB.SUSv4.syms @@ -0,0 +1 @@ +ftw diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/ftw.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/ftw.SUSv4.syms new file mode 100644 index 00000000..35000c9c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/ftw.SUSv4.syms @@ -0,0 +1 @@ +nftw diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/glob.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/glob.SUSv4.syms new file mode 100644 index 00000000..c2e4234a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/glob.SUSv4.syms @@ -0,0 +1,2 @@ +glob +globfree diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/grp-XSI.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/grp-XSI.SUSv4.syms new file mode 100644 index 00000000..e2b1c1dd --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/grp-XSI.SUSv4.syms @@ -0,0 +1 @@ +setgrent diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/grp.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/grp.SUSv4.syms new file mode 100644 index 00000000..77a8c6ea --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/grp.SUSv4.syms @@ -0,0 +1,6 @@ +endgrent +getgrent +getgrgid +getgrgid_r +getgrnam +getgrnam_r diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/html2input.sh b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/html2input.sh new file mode 100644 index 00000000..9ea68fec --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/html2input.sh @@ -0,0 +1,119 @@ +#!/bin/sh +# vi: ft=awk : +# +# Script to extract functions and external variables off SUS html docs +# +# Copyright (C) 2010 Bernhard Reutner-Fischer +# Public Domain + +# Usage: +# wget http://www.opengroup.org/onlinepubs/9699919799/download/susv4.tgz +# tar xzf susv4.tgz +# SUS=susv4 html2input.sh -vFULL_DECLARATIONS=1 +# or +# SUS=susv4 html2input.sh -vFULL_DECLARATIONS=0 -vSTDNAME=SUSv4 +# +# Bug in time.h.html of SUSv4: +# It inconsistently reads "as variables" instead of "external variables" that +# is used everywhere except in time.h.html + +test "x$SUS" = "x" && SUS="susv4" +test "x$AWK" = "x" && AWK="AWK" +test "x$GREP" = "x" && GREP="GREP" +for h in \ + $($GREP -l "shall be declared as functions" $SUS/basedefs/*.h.html) \ + $($GREP -l "shall declare the following as variables" $SUS/basedefs/*.h.html) \ + $($GREP -l "shall declare the following external variables" $SUS/basedefs/*.h.html) +do +$AWK $* ' +function get_filename () { + if (NR == 1) { + x=FILENAME + sub(".*/", "", x) + split(x, f , ".") + fname=f[1] + if (STDNAME) + fname=fname "." STDNAME + fname=fname ".in" + printf "" > fname + } +} +function unhtml (l) { + sub("", "", l) + sub("", "", l) + sub("", "", l) + sub("", "", l) + sub("]*>", "", l) + sub("", "", l) + if (l ~ /]*Option[[:space:]][[:space:]]*Start[^>]*>/) { + sub("]*>", "[Option Start]", l) + } else if (l ~ /]*Option[[:space:]][[:space:]]*End[^>]*>/) { + sub("]*>", "[Option End]", l) + } + sub("<.*>", "", l) + return l +} +function get_funcname (l) { + if (FULL_DECLARATIONS) + return l + if (l !~ /;$/) + return l + cnt = split(l, foo, " ") + if (cnt >= 2 && foo[2] ~ /^\(\*/) { + cnt = split(l, foo, "(") + # good enough for signal() and sigset() + if (cnt >= 2) + l=foo[2] + } else { + sub("\\(.*", "", l) + } + gsub("[[\\]\\*]", "", l) + i = split(l, a, " ") + if (i) + l = a[i] + return l +} +function get_varname (l) { + if (FULL_DECLARATIONS) + return l + if (l !~ /;$/) + return l + gsub(",[[:space:]][[:space:]]*", ",", l) + sub(";$", "", l) + i = split(l, a, " ") + if (i) + l = a[i] + gsub("[[\\]\\*]", "", l) + gsub(",", "\n", l) + return l +} +BEGIN{data=0;l=""} +get_filename() +/shall be declared as functions/{data=1;isvar=0;next;} +/shall declare the following as variables/{data=1;isvar=1;next;} +/shall declare the following external variables/{data=1;isvar=1;next;} +/

/{data++;next;}
+/<\/pre>/{data=0;next;}
+/.*/{
+	if (data == 2 && fname) {
+		tmp = $0
+		sub("^[[:space:]][[:space:]]*", " ", tmp)
+		l = l tmp
+		tmp = unhtml(l)
+		if (!tmp)
+			next
+		l = tmp
+		if (tmp !~ /;$/ && tmp !~ />$/ &&
+			tmp !~ /Option Start\]$/ && tmp !~ /Option End\]$/)
+			next
+		if (!isvar)
+			l = get_funcname(l)
+		else
+			l = get_varname(l)
+		if (l)
+			print l >> fname
+		l=""
+	}
+}
+' $h
+done
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/iconv.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/iconv.SUSv4.syms
new file mode 100644
index 00000000..05995206
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/iconv.SUSv4.syms
@@ -0,0 +1,3 @@
+iconv
+iconv_close
+iconv_open
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/inttypes.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/inttypes.SUSv4.syms
new file mode 100644
index 00000000..6cbc3a25
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/inttypes.SUSv4.syms
@@ -0,0 +1,6 @@
+imaxabs
+imaxdiv
+strtoimax
+strtoumax
+wcstoimax
+wcstoumax
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/libgen.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/libgen.SUSv4.syms
new file mode 100644
index 00000000..3d4945af
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/libgen.SUSv4.syms
@@ -0,0 +1,2 @@
+basename
+dirname
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/locale-CX.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/locale-CX.SUSv4.syms
new file mode 100644
index 00000000..22ffcfc2
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/locale-CX.SUSv4.syms
@@ -0,0 +1,4 @@
+duplocale
+freelocale
+newlocale
+uselocale
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/locale.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/locale.SUSv4.syms
new file mode 100644
index 00000000..33f8cad0
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/locale.SUSv4.syms
@@ -0,0 +1,2 @@
+localeconv
+setlocale
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/math-XSI.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/math-XSI.SUSv4.syms
new file mode 100644
index 00000000..4ce15d8f
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/math-XSI.SUSv4.syms
@@ -0,0 +1,6 @@
+j0
+j1
+jn
+y0
+y1
+yn
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/math.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/math.SUSv4.syms
new file mode 100644
index 00000000..5343ac06
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/math.SUSv4.syms
@@ -0,0 +1,171 @@
+acos
+acosf
+acosh
+acoshf
+acoshl
+acosl
+asin
+asinf
+asinh
+asinhf
+asinhl
+asinl
+atan
+atan2
+atan2f
+atan2l
+atanf
+atanh
+atanhf
+atanhl
+atanl
+cbrt
+cbrtf
+cbrtl
+ceil
+ceilf
+ceill
+copysign
+copysignf
+copysignl
+cos
+cosf
+cosh
+coshf
+coshl
+cosl
+erf
+erfc
+erfcf
+erfcl
+erff
+erfl
+exp
+exp2
+exp2f
+exp2l
+expf
+expl
+expm1
+expm1f
+expm1l
+fabs
+fabsf
+fabsl
+fdim
+fdimf
+fdiml
+floor
+floorf
+floorl
+fma
+fmaf
+fmal
+fmax
+fmaxf
+fmaxl
+fmin
+fminf
+fminl
+fmod
+fmodf
+fmodl
+frexp
+frexpf
+frexpl
+hypot
+hypotf
+hypotl
+ilogb
+ilogbf
+ilogbl
+ldexp
+ldexpf
+ldexpl
+lgamma
+lgammaf
+lgammal
+llrint
+llrintf
+llrintl
+llround
+llroundf
+llroundl
+log
+log10
+log10f
+log10l
+log1p
+log1pf
+log1pl
+log2
+log2f
+log2l
+logb
+logbf
+logbl
+logf
+logl
+lrint
+lrintf
+lrintl
+lround
+lroundf
+lroundl
+modf
+modff
+modfl
+nan
+nanf
+nanl
+nearbyint
+nearbyintf
+nearbyintl
+nextafter
+nextafterf
+nextafterl
+nexttoward
+nexttowardf
+nexttowardl
+pow
+powf
+powl
+remainder
+remainderf
+remainderl
+remquo
+remquof
+remquol
+rint
+rintf
+rintl
+round
+roundf
+roundl
+scalbln
+scalblnf
+scalblnl
+scalbn
+scalbnf
+scalbnl
+sin
+sinf
+sinh
+sinhf
+sinhl
+sinl
+sqrt
+sqrtf
+sqrtl
+tan
+tanf
+tanh
+tanhf
+tanhl
+tanl
+tgamma
+tgammaf
+tgammal
+trunc
+truncf
+truncl
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/monetary.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/monetary.SUSv4.syms
new file mode 100644
index 00000000..256b53a7
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/monetary.SUSv4.syms
@@ -0,0 +1,2 @@
+strfmon
+strfmon_l
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/mqueue.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/mqueue.SUSv4.syms
new file mode 100644
index 00000000..54c80a08
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/mqueue.SUSv4.syms
@@ -0,0 +1,10 @@
+mq_close
+mq_getattr
+mq_notify
+mq_open
+mq_receive
+mq_send
+mq_setattr
+mq_timedreceive
+mq_timedsend
+mq_unlink
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/ndbm.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/ndbm.SUSv4.syms
new file mode 100644
index 00000000..70116bf4
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/ndbm.SUSv4.syms
@@ -0,0 +1,9 @@
+dbm_clearerr
+dbm_close
+dbm_delete
+dbm_error
+dbm_fetch
+dbm_firstkey
+dbm_nextkey
+dbm_open
+dbm_store
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/net_if.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/net_if.SUSv4.syms
new file mode 100644
index 00000000..828a0cdb
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/net_if.SUSv4.syms
@@ -0,0 +1,4 @@
+if_freenameindex
+if_indextoname
+if_nameindex
+if_nametoindex
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/netdb.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/netdb.SUSv4.syms
new file mode 100644
index 00000000..daf932b0
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/netdb.SUSv4.syms
@@ -0,0 +1,22 @@
+endhostent
+endnetent
+endprotoent
+endservent
+freeaddrinfo
+gai_strerror
+getaddrinfo
+gethostent
+getnameinfo
+getnetbyaddr
+getnetbyname
+getnetent
+getprotobyname
+getprotobynumber
+getprotoent
+getservbyname
+getservbyport
+getservent
+sethostent
+setnetent
+setprotoent
+setservent
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/nl_types.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/nl_types.SUSv4.syms
new file mode 100644
index 00000000..ea005993
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/nl_types.SUSv4.syms
@@ -0,0 +1,3 @@
+catclose
+catgets
+catopen
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/pthread-MC1.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/pthread-MC1.SUSv4.syms
new file mode 100644
index 00000000..8a47a391
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/pthread-MC1.SUSv4.syms
@@ -0,0 +1,2 @@
+pthread_mutexattr_getprotocol
+pthread_mutexattr_setprotocol
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/pthread-OBXSI.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/pthread-OBXSI.SUSv4.syms
new file mode 100644
index 00000000..140b53d0
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/pthread-OBXSI.SUSv4.syms
@@ -0,0 +1,2 @@
+pthread_getconcurrency
+pthread_setconcurrency
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/pthread-RPP|TPP.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/pthread-RPP|TPP.SUSv4.syms
new file mode 100644
index 00000000..b116695f
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/pthread-RPP|TPP.SUSv4.syms
@@ -0,0 +1,4 @@
+pthread_mutex_getprioceiling
+pthread_mutex_setprioceiling
+pthread_mutexattr_getprioceiling
+pthread_mutexattr_setprioceiling
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/pthread-TCT.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/pthread-TCT.SUSv4.syms
new file mode 100644
index 00000000..7153787e
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/pthread-TCT.SUSv4.syms
@@ -0,0 +1 @@
+pthread_getcpuclockid
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/pthread-TPS.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/pthread-TPS.SUSv4.syms
new file mode 100644
index 00000000..76fcd956
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/pthread-TPS.SUSv4.syms
@@ -0,0 +1,9 @@
+pthread_attr_getinheritsched
+pthread_attr_getschedpolicy
+pthread_attr_getscope
+pthread_attr_setinheritsched
+pthread_attr_setschedpolicy
+pthread_attr_setscope
+pthread_getschedparam
+pthread_setschedparam
+pthread_setschedprio
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/pthread-TSATSS.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/pthread-TSATSS.SUSv4.syms
new file mode 100644
index 00000000..5e03091c
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/pthread-TSATSS.SUSv4.syms
@@ -0,0 +1,2 @@
+pthread_attr_getstack
+pthread_attr_setstack
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/pthread-TSH.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/pthread-TSH.SUSv4.syms
new file mode 100644
index 00000000..717b232a
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/pthread-TSH.SUSv4.syms
@@ -0,0 +1,8 @@
+pthread_barrierattr_getpshared
+pthread_barrierattr_setpshared
+pthread_condattr_getpshared
+pthread_condattr_setpshared
+pthread_mutexattr_getpshared
+pthread_mutexattr_setpshared
+pthread_rwlockattr_getpshared
+pthread_rwlockattr_setpshared
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/pthread-TSS.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/pthread-TSS.SUSv4.syms
new file mode 100644
index 00000000..1092f88d
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/pthread-TSS.SUSv4.syms
@@ -0,0 +1,2 @@
+pthread_attr_getstacksize
+pthread_attr_setstacksize
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/pthread.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/pthread.SUSv4.syms
new file mode 100644
index 00000000..524a6fec
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/pthread.SUSv4.syms
@@ -0,0 +1,70 @@
+pthread_atfork
+pthread_attr_destroy
+pthread_attr_getdetachstate
+pthread_attr_getguardsize
+pthread_attr_getschedparam
+pthread_attr_init
+pthread_attr_setdetachstate
+pthread_attr_setguardsize
+pthread_attr_setschedparam
+pthread_barrier_destroy
+pthread_barrier_init
+pthread_barrier_wait
+pthread_barrierattr_destroy
+pthread_barrierattr_init
+pthread_cancel
+pthread_cleanup_pop
+pthread_cleanup_push
+pthread_cond_broadcast
+pthread_cond_destroy
+pthread_cond_init
+pthread_cond_signal
+pthread_cond_timedwait
+pthread_cond_wait
+pthread_condattr_destroy
+pthread_condattr_getclock
+pthread_condattr_init
+pthread_condattr_setclock
+pthread_create
+pthread_detach
+pthread_equal
+pthread_exit
+pthread_getspecific
+pthread_join
+pthread_key_create
+pthread_key_delete
+pthread_mutex_consistent
+pthread_mutex_destroy
+pthread_mutex_init
+pthread_mutex_lock
+pthread_mutex_timedlock
+pthread_mutex_trylock
+pthread_mutex_unlock
+pthread_mutexattr_destroy
+pthread_mutexattr_getrobust
+pthread_mutexattr_gettype
+pthread_mutexattr_init
+pthread_mutexattr_setrobust
+pthread_mutexattr_settype
+pthread_once
+pthread_rwlock_destroy
+pthread_rwlock_init
+pthread_rwlock_rdlock
+pthread_rwlock_timedrdlock
+pthread_rwlock_timedwrlock
+pthread_rwlock_tryrdlock
+pthread_rwlock_trywrlock
+pthread_rwlock_unlock
+pthread_rwlock_wrlock
+pthread_rwlockattr_destroy
+pthread_rwlockattr_init
+pthread_self
+pthread_setcancelstate
+pthread_setcanceltype
+pthread_setspecific
+pthread_spin_destroy
+pthread_spin_init
+pthread_spin_lock
+pthread_spin_trylock
+pthread_spin_unlock
+pthread_testcancel
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/pwd-XSI.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/pwd-XSI.SUSv4.syms
new file mode 100644
index 00000000..8b0350aa
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/pwd-XSI.SUSv4.syms
@@ -0,0 +1,3 @@
+endpwent
+getpwent
+setpwent
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/pwd.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/pwd.SUSv4.syms
new file mode 100644
index 00000000..45328f66
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/pwd.SUSv4.syms
@@ -0,0 +1,4 @@
+getpwnam
+getpwnam_r
+getpwuid
+getpwuid_r
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/regex.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/regex.SUSv4.syms
new file mode 100644
index 00000000..94bf9fa6
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/regex.SUSv4.syms
@@ -0,0 +1,4 @@
+regcomp
+regerror
+regexec
+regfree
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/sched-PS.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/sched-PS.SUSv4.syms
new file mode 100644
index 00000000..51ce62af
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/sched-PS.SUSv4.syms
@@ -0,0 +1,4 @@
+sched_getparam
+sched_getscheduler
+sched_setparam
+sched_setscheduler
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/sched-PS|TPS.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/sched-PS|TPS.SUSv4.syms
new file mode 100644
index 00000000..67fdb603
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/sched-PS|TPS.SUSv4.syms
@@ -0,0 +1,3 @@
+sched_get_priority_max
+sched_get_priority_min
+sched_rr_get_interval
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/sched.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/sched.SUSv4.syms
new file mode 100644
index 00000000..0b6b81db
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/sched.SUSv4.syms
@@ -0,0 +1 @@
+sched_yield
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/search.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/search.SUSv4.syms
new file mode 100644
index 00000000..5bbf8451
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/search.SUSv4.syms
@@ -0,0 +1,11 @@
+hcreate
+hdestroy
+hsearch
+insque
+lfind
+lsearch
+remque
+tdelete
+tfind
+tsearch
+twalk
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/semaphore.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/semaphore.SUSv4.syms
new file mode 100644
index 00000000..1f291c54
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/semaphore.SUSv4.syms
@@ -0,0 +1,10 @@
+sem_close
+sem_destroy
+sem_getvalue
+sem_init
+sem_open
+sem_post
+sem_timedwait
+sem_trywait
+sem_unlink
+sem_wait
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/separate.awk b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/separate.awk
new file mode 100644
index 00000000..f7850c4f
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/separate.awk
@@ -0,0 +1,48 @@
+#!/usr/bin/awk -f
+# 
+# Usage: awk -f separate.awk foo.SUSv4.in
+# Input: http://www.opengroup.org/onlinepubs/9699919799/basedefs/unistd.h.html#tag_13_77_03_06
+# Output: foo-$CODE.SUSv4.syms, foo.SUSv4.syms
+#
+# Copyright (C) 2010 Bernhard Reutner-Fischer
+# Public domain
+
+function get_code(line)
+{
+	sub("\\]\\[.*", "", line)
+	sub("\\[", "", line)
+	sub(" ", "", line)
+	return line
+}
+BEGIN{
+	code="";# feature set; XSI, OB XSI, CX, etc
+
+}
+/\[Option Start\]/{
+	code = get_code($0)
+	next
+}
+/\[Option End\]/{ code = ""; next; }
+/.*/ {
+	if (!hdrname) {
+		split(FILENAME, fparts, ".")
+		hdrname = fparts[1]
+		stdname = fparts[2]
+		if (fparts[3] != "in") {
+			print "inputfilename may not be ok, exiting."
+			exit(1)
+		}
+	}
+	if (code) {
+		fname = hdrname "-" code "." stdname ".syms"
+	} else {
+		fname = hdrname "." stdname ".syms"
+	}
+	sub("^*", "", $0)
+	if (file[code]) {
+		print $0 >> fname
+	} else {
+		print $0 > fname
+		file[code] = 1
+	}
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/setjmp-CX.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/setjmp-CX.SUSv4.syms
new file mode 100644
index 00000000..fb0fbbe9
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/setjmp-CX.SUSv4.syms
@@ -0,0 +1 @@
+siglongjmp
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/setjmp-OBXSI.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/setjmp-OBXSI.SUSv4.syms
new file mode 100644
index 00000000..8f2d5b11
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/setjmp-OBXSI.SUSv4.syms
@@ -0,0 +1 @@
+_longjmp
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/setjmp.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/setjmp.SUSv4.syms
new file mode 100644
index 00000000..a51df77b
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/setjmp.SUSv4.syms
@@ -0,0 +1 @@
+longjmp
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/signal-CX.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/signal-CX.SUSv4.syms
new file mode 100644
index 00000000..3d77c5ac
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/signal-CX.SUSv4.syms
@@ -0,0 +1,18 @@
+kill
+psiginfo
+psignal
+pthread_kill
+pthread_sigmask
+sigaction
+sigaddset
+sigdelset
+sigemptyset
+sigfillset
+sigismember
+sigpending
+sigprocmask
+sigqueue
+sigsuspend
+sigtimedwait
+sigwait
+sigwaitinfo
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/signal-OBXSI.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/signal-OBXSI.SUSv4.syms
new file mode 100644
index 00000000..2a6341d6
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/signal-OBXSI.SUSv4.syms
@@ -0,0 +1,6 @@
+sighold
+sigignore
+siginterrupt
+sigpause
+sigrelse
+void
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/signal-XSI.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/signal-XSI.SUSv4.syms
new file mode 100644
index 00000000..f3df0c15
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/signal-XSI.SUSv4.syms
@@ -0,0 +1,2 @@
+killpg
+sigaltstack
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/signal.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/signal.SUSv4.syms
new file mode 100644
index 00000000..2119c27d
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/signal.SUSv4.syms
@@ -0,0 +1,2 @@
+raise
+void
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/spawn-PS.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/spawn-PS.SUSv4.syms
new file mode 100644
index 00000000..f92ebbb2
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/spawn-PS.SUSv4.syms
@@ -0,0 +1,4 @@
+posix_spawnattr_getschedparam
+posix_spawnattr_getschedpolicy
+posix_spawnattr_setschedparam
+posix_spawnattr_setschedpolicy
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/spawn.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/spawn.SUSv4.syms
new file mode 100644
index 00000000..7481640c
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/spawn.SUSv4.syms
@@ -0,0 +1,17 @@
+posix_spawn
+posix_spawn_file_actions_addclose
+posix_spawn_file_actions_adddup2
+posix_spawn_file_actions_addopen
+posix_spawn_file_actions_destroy
+posix_spawn_file_actions_init
+posix_spawnattr_destroy
+posix_spawnattr_getflags
+posix_spawnattr_getpgroup
+posix_spawnattr_getsigdefault
+posix_spawnattr_getsigmask
+posix_spawnattr_init
+posix_spawnattr_setflags
+posix_spawnattr_setpgroup
+posix_spawnattr_setsigdefault
+posix_spawnattr_setsigmask
+posix_spawnp
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/stdio-CX.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/stdio-CX.SUSv4.syms
new file mode 100644
index 00000000..98742c36
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/stdio-CX.SUSv4.syms
@@ -0,0 +1,20 @@
+ctermid
+fdopen
+fileno
+flockfile
+fmemopen
+fseeko
+ftello
+ftrylockfile
+funlockfile
+getc_unlocked
+getchar_unlocked
+getdelim
+getline
+open_memstream
+pclose
+popen
+putc_unlocked
+putchar_unlocked
+renameat
+vdprintf
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/stdio-OB.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/stdio-OB.SUSv4.syms
new file mode 100644
index 00000000..f874a6c1
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/stdio-OB.SUSv4.syms
@@ -0,0 +1,2 @@
+gets
+tmpnam
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/stdio-OBXSI.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/stdio-OBXSI.SUSv4.syms
new file mode 100644
index 00000000..644049ef
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/stdio-OBXSI.SUSv4.syms
@@ -0,0 +1 @@
+tempnam
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/stdio.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/stdio.SUSv4.syms
new file mode 100644
index 00000000..08404437
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/stdio.SUSv4.syms
@@ -0,0 +1,44 @@
+clearerr
+fclose
+feof
+ferror
+fflush
+fgetc
+fgetpos
+fgets
+fopen
+fprintf
+fputc
+fputs
+fread
+freopen
+fscanf
+fseek
+fsetpos
+ftell
+fwrite
+getc
+getchar
+perror
+printf
+putc
+putchar
+puts
+remove
+rename
+rewind
+scanf
+setbuf
+setvbuf
+snprintf
+sprintf
+sscanf
+tmpfile
+ungetc
+vfprintf
+vfscanf
+vprintf
+vscanf
+vsnprintf
+vsprintf
+vsscanf
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/stdlib-ADV.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/stdlib-ADV.SUSv4.syms
new file mode 100644
index 00000000..bfb66851
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/stdlib-ADV.SUSv4.syms
@@ -0,0 +1 @@
+posix_memalign
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/stdlib-CX.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/stdlib-CX.SUSv4.syms
new file mode 100644
index 00000000..10a7b1f6
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/stdlib-CX.SUSv4.syms
@@ -0,0 +1,4 @@
+mkdtemp
+mkstemp
+setenv
+unsetenv
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/stdlib-OBCX.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/stdlib-OBCX.SUSv4.syms
new file mode 100644
index 00000000..1947cc78
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/stdlib-OBCX.SUSv4.syms
@@ -0,0 +1 @@
+rand_r
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/stdlib-XSI.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/stdlib-XSI.SUSv4.syms
new file mode 100644
index 00000000..6cb0f1bb
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/stdlib-XSI.SUSv4.syms
@@ -0,0 +1,22 @@
+a64l
+drand48
+erand48
+grantpt
+initstate
+jrand48
+l64a
+lcong48
+lrand48
+mrand48
+nrand48
+posix_openpt
+ptsname
+putenv
+random
+realpath
+seed48
+setkey
+setstate
+srand48
+srandom
+unlockpt
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/stdlib.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/stdlib.SUSv4.syms
new file mode 100644
index 00000000..aefd9693
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/stdlib.SUSv4.syms
@@ -0,0 +1,37 @@
+_Exit
+abort
+abs
+atexit
+atof
+atoi
+atol
+atoll
+bsearch
+calloc
+div
+exit
+free
+getenv
+getsubopt
+labs
+ldiv
+llabs
+lldiv
+malloc
+mblen
+mbstowcs
+mbtowc
+qsort
+rand
+realloc
+srand
+strtod
+strtof
+strtol
+strtold
+strtoll
+strtoul
+strtoull
+system
+wcstombs
+wctomb
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/string-CX.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/string-CX.SUSv4.syms
new file mode 100644
index 00000000..4f493d4e
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/string-CX.SUSv4.syms
@@ -0,0 +1,11 @@
+stpcpy
+stpncpy
+strcoll_l
+strdup
+strerror_l
+strerror_r
+strndup
+strnlen
+strsignal
+strtok_r
+strxfrm_l
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/string-XSI.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/string-XSI.SUSv4.syms
new file mode 100644
index 00000000..e0ee4e32
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/string-XSI.SUSv4.syms
@@ -0,0 +1 @@
+memccpy
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/string.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/string.SUSv4.syms
new file mode 100644
index 00000000..3c5e2b87
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/string.SUSv4.syms
@@ -0,0 +1,22 @@
+memchr
+memcmp
+memcpy
+memmove
+memset
+strcat
+strchr
+strcmp
+strcoll
+strcpy
+strcspn
+strerror
+strlen
+strncat
+strncmp
+strncpy
+strpbrk
+strrchr
+strspn
+strstr
+strtok
+strxfrm
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/strings-XSI.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/strings-XSI.SUSv4.syms
new file mode 100644
index 00000000..c1173c1a
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/strings-XSI.SUSv4.syms
@@ -0,0 +1 @@
+ffs
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/strings.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/strings.SUSv4.syms
new file mode 100644
index 00000000..b4bc2337
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/strings.SUSv4.syms
@@ -0,0 +1,4 @@
+strcasecmp
+strcasecmp_l
+strncasecmp
+strncasecmp_l
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/stropts.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/stropts.SUSv4.syms
new file mode 100644
index 00000000..796d3885
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/stropts.SUSv4.syms
@@ -0,0 +1,8 @@
+fattach
+fdetach
+getmsg
+getpmsg
+ioctl
+isastream
+putmsg
+putpmsg
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/sys_mman-ADV.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/sys_mman-ADV.SUSv4.syms
new file mode 100644
index 00000000..4598c3b7
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/sys_mman-ADV.SUSv4.syms
@@ -0,0 +1 @@
+posix_madvise
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/sys_mman-ML.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/sys_mman-ML.SUSv4.syms
new file mode 100644
index 00000000..de0f37d4
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/sys_mman-ML.SUSv4.syms
@@ -0,0 +1,2 @@
+mlockall
+munlockall
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/sys_mman-MLR.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/sys_mman-MLR.SUSv4.syms
new file mode 100644
index 00000000..aa8ea9ca
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/sys_mman-MLR.SUSv4.syms
@@ -0,0 +1,2 @@
+mlock
+munlock
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/sys_mman-SHM.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/sys_mman-SHM.SUSv4.syms
new file mode 100644
index 00000000..885119a8
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/sys_mman-SHM.SUSv4.syms
@@ -0,0 +1,2 @@
+shm_open
+shm_unlink
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/sys_mman-TYM.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/sys_mman-TYM.SUSv4.syms
new file mode 100644
index 00000000..68bc50e3
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/sys_mman-TYM.SUSv4.syms
@@ -0,0 +1,3 @@
+posix_mem_offset
+posix_typed_mem_get_info
+posix_typed_mem_open
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/sys_mman-XSI|SIO.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/sys_mman-XSI|SIO.SUSv4.syms
new file mode 100644
index 00000000..3a2f8c30
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/sys_mman-XSI|SIO.SUSv4.syms
@@ -0,0 +1 @@
+msync
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/sys_mman.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/sys_mman.SUSv4.syms
new file mode 100644
index 00000000..46a46e7d
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/sys_mman.SUSv4.syms
@@ -0,0 +1,3 @@
+mmap
+mprotect
+munmap
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/sys_msg.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/sys_msg.SUSv4.syms
new file mode 100644
index 00000000..95c2ec18
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/sys_msg.SUSv4.syms
@@ -0,0 +1,4 @@
+msgctl
+msgget
+msgrcv
+msgsnd
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/sys_resource.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/sys_resource.SUSv4.syms
new file mode 100644
index 00000000..72d3e1e2
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/sys_resource.SUSv4.syms
@@ -0,0 +1,5 @@
+getpriority
+getrlimit
+getrusage
+setpriority
+setrlimit
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/sys_select.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/sys_select.SUSv4.syms
new file mode 100644
index 00000000..40cf6d86
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/sys_select.SUSv4.syms
@@ -0,0 +1,6 @@
+FD_CLR
+FD_ISSET
+FD_SET
+FD_ZERO
+pselect
+select
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/sys_sem.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/sys_sem.SUSv4.syms
new file mode 100644
index 00000000..173f1d99
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/sys_sem.SUSv4.syms
@@ -0,0 +1,3 @@
+semctl
+semget
+semop
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/sys_shm.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/sys_shm.SUSv4.syms
new file mode 100644
index 00000000..f284402e
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/sys_shm.SUSv4.syms
@@ -0,0 +1,4 @@
+shmat
+shmctl
+shmdt
+shmget
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/sys_socket.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/sys_socket.SUSv4.syms
new file mode 100644
index 00000000..cc51c9e5
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/sys_socket.SUSv4.syms
@@ -0,0 +1,18 @@
+accept
+bind
+connect
+getpeername
+getsockname
+getsockopt
+listen
+recv
+recvfrom
+recvmsg
+send
+sendmsg
+sendto
+setsockopt
+shutdown
+sockatmark
+socket
+socketpair
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/sys_stat-XSI.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/sys_stat-XSI.SUSv4.syms
new file mode 100644
index 00000000..4800d009
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/sys_stat-XSI.SUSv4.syms
@@ -0,0 +1,2 @@
+mknod
+mknodat
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/sys_stat.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/sys_stat.SUSv4.syms
new file mode 100644
index 00000000..3fe729fc
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/sys_stat.SUSv4.syms
@@ -0,0 +1,14 @@
+chmod
+fchmod
+fchmodat
+fstat
+fstatat
+futimens
+lstat
+mkdir
+mkdirat
+mkfifo
+mkfifoat
+stat
+umask
+utimensat
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/sys_statvfs.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/sys_statvfs.SUSv4.syms
new file mode 100644
index 00000000..c3fd5f4d
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/sys_statvfs.SUSv4.syms
@@ -0,0 +1,2 @@
+fstatvfs
+statvfs
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/sys_time-OB.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/sys_time-OB.SUSv4.syms
new file mode 100644
index 00000000..caf1f3f3
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/sys_time-OB.SUSv4.syms
@@ -0,0 +1,3 @@
+getitimer
+gettimeofday
+setitimer
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/sys_time.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/sys_time.SUSv4.syms
new file mode 100644
index 00000000..526a4049
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/sys_time.SUSv4.syms
@@ -0,0 +1,2 @@
+select
+utimes
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/sys_uio.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/sys_uio.SUSv4.syms
new file mode 100644
index 00000000..31caee5c
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/sys_uio.SUSv4.syms
@@ -0,0 +1,2 @@
+readv
+writev
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/sys_wait.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/sys_wait.SUSv4.syms
new file mode 100644
index 00000000..753c3806
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/sys_wait.SUSv4.syms
@@ -0,0 +1,3 @@
+wait
+waitid
+waitpid
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/syslog.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/syslog.SUSv4.syms
new file mode 100644
index 00000000..a44f514c
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/syslog.SUSv4.syms
@@ -0,0 +1,4 @@
+closelog
+openlog
+setlogmask
+syslog
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/termios.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/termios.SUSv4.syms
new file mode 100644
index 00000000..43ac8366
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/termios.SUSv4.syms
@@ -0,0 +1,11 @@
+cfgetispeed
+cfgetospeed
+cfsetispeed
+cfsetospeed
+tcdrain
+tcflow
+tcflush
+tcgetattr
+tcgetsid
+tcsendbreak
+tcsetattr
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/time-CPT.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/time-CPT.SUSv4.syms
new file mode 100644
index 00000000..278952e5
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/time-CPT.SUSv4.syms
@@ -0,0 +1 @@
+clock_getcpuclockid
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/time-CX.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/time-CX.SUSv4.syms
new file mode 100644
index 00000000..d2cbb775
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/time-CX.SUSv4.syms
@@ -0,0 +1,15 @@
+clock_getres
+clock_gettime
+clock_nanosleep
+clock_settime
+gmtime_r
+localtime_r
+nanosleep
+strftime_l
+timer_create
+timer_delete
+timer_getoverrun
+timer_gettime
+timer_settime
+tzset
+tzname
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/time-OB.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/time-OB.SUSv4.syms
new file mode 100644
index 00000000..ce1dad05
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/time-OB.SUSv4.syms
@@ -0,0 +1,2 @@
+asctime
+ctime
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/time-OBCX.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/time-OBCX.SUSv4.syms
new file mode 100644
index 00000000..b46018c5
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/time-OBCX.SUSv4.syms
@@ -0,0 +1,2 @@
+asctime_r
+ctime_r
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/time-XSI.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/time-XSI.SUSv4.syms
new file mode 100644
index 00000000..9bf1f622
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/time-XSI.SUSv4.syms
@@ -0,0 +1,4 @@
+getdate
+strptime
+daylight
+timezone
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/time.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/time.SUSv4.syms
new file mode 100644
index 00000000..788e19ee
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/time.SUSv4.syms
@@ -0,0 +1,7 @@
+clock
+difftime
+gmtime
+localtime
+mktime
+strftime
+time
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/trace-TEF.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/trace-TEF.SUSv4.syms
new file mode 100644
index 00000000..bc9f47bf
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/trace-TEF.SUSv4.syms
@@ -0,0 +1,8 @@
+posix_trace_eventset_add
+posix_trace_eventset_del
+posix_trace_eventset_empty
+posix_trace_eventset_fill
+posix_trace_eventset_ismember
+posix_trace_get_filter
+posix_trace_set_filter
+posix_trace_trid_eventid_open
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/trace-TRI.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/trace-TRI.SUSv4.syms
new file mode 100644
index 00000000..ea5723dc
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/trace-TRI.SUSv4.syms
@@ -0,0 +1,2 @@
+posix_trace_attr_getinherited
+posix_trace_attr_setinherited
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/trace-TRL.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/trace-TRL.SUSv4.syms
new file mode 100644
index 00000000..763c7f42
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/trace-TRL.SUSv4.syms
@@ -0,0 +1,9 @@
+posix_trace_attr_getlogfullpolicy
+posix_trace_attr_getlogsize
+posix_trace_attr_setlogfullpolicy
+posix_trace_attr_setlogsize
+posix_trace_close
+posix_trace_create_withlog
+posix_trace_flush
+posix_trace_open
+posix_trace_rewind
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/trace.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/trace.SUSv4.syms
new file mode 100644
index 00000000..c12b882e
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/trace.SUSv4.syms
@@ -0,0 +1,31 @@
+posix_trace_attr_destroy
+posix_trace_attr_getclockres
+posix_trace_attr_getcreatetime
+posix_trace_attr_getgenversion
+posix_trace_attr_getmaxdatasize
+posix_trace_attr_getmaxsystemeventsize
+posix_trace_attr_getmaxusereventsize
+posix_trace_attr_getname
+posix_trace_attr_getstreamfullpolicy
+posix_trace_attr_getstreamsize
+posix_trace_attr_init
+posix_trace_attr_setmaxdatasize
+posix_trace_attr_setname
+posix_trace_attr_setstreamfullpolicy
+posix_trace_attr_setstreamsize
+posix_trace_clear
+posix_trace_create
+posix_trace_event
+posix_trace_eventid_equal
+posix_trace_eventid_get_name
+posix_trace_eventid_open
+posix_trace_eventtypelist_getnext_id
+posix_trace_eventtypelist_rewind
+posix_trace_get_attr
+posix_trace_get_status
+posix_trace_getnext_event
+posix_trace_shutdown
+posix_trace_start
+posix_trace_stop
+posix_trace_timedgetnext_event
+posix_trace_trygetnext_event
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/tst-API.sh b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/tst-API.sh
new file mode 100644
index 00000000..38a33994
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/tst-API.sh
@@ -0,0 +1,16 @@
+#!/bin/sh
+
+std="$1"
+shift
+cod="$*"
+
+result=0
+
+for l in $top_builddir/lib/lib*-*.so; do \
+	readelf -D -W -s $l | \
+	egrep -v "(UND|LOCAL|^Symbol table for image:|^[[:space:]]*Num[[:space:]])" | \
+	$AWK '{print $NF}'; \
+	done | sort | uniq > $uclibc_out
+for code in $cod; do cat $code.$std.syms; done | sort | uniq > $glibc_out
+result=0
+exit $result
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/unistd-CX.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/unistd-CX.SUSv4.syms
new file mode 100644
index 00000000..4e183e44
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/unistd-CX.SUSv4.syms
@@ -0,0 +1 @@
+ctermid
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/unistd-FSC.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/unistd-FSC.SUSv4.syms
new file mode 100644
index 00000000..e5c2ab2b
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/unistd-FSC.SUSv4.syms
@@ -0,0 +1 @@
+fsync
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/unistd-OBXSI.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/unistd-OBXSI.SUSv4.syms
new file mode 100644
index 00000000..4e6787f6
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/unistd-OBXSI.SUSv4.syms
@@ -0,0 +1 @@
+setpgrp
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/unistd-SIO.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/unistd-SIO.SUSv4.syms
new file mode 100644
index 00000000..2ed33b39
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/unistd-SIO.SUSv4.syms
@@ -0,0 +1 @@
+fdatasync
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/unistd-XSI.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/unistd-XSI.SUSv4.syms
new file mode 100644
index 00000000..db541767
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/unistd-XSI.SUSv4.syms
@@ -0,0 +1,9 @@
+crypt
+encrypt
+gethostid
+lockf
+nice
+setregid
+setreuid
+swab
+sync
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/unistd.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/unistd.SUSv4.syms
new file mode 100644
index 00000000..fec630db
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/unistd.SUSv4.syms
@@ -0,0 +1,74 @@
+access
+alarm
+chdir
+chown
+close
+confstr
+dup
+dup2
+_exit
+execl
+execle
+execlp
+execv
+execve
+execvp
+faccessat
+fchdir
+fchown
+fchownat
+fexecve
+fork
+fpathconf
+ftruncate
+getcwd
+getegid
+geteuid
+getgid
+getgroups
+gethostname
+getlogin
+getlogin_r
+getopt
+getpgid
+getpgrp
+getpid
+getppid
+getsid
+getuid
+isatty
+lchown
+link
+linkat
+lseek
+pathconf
+pause
+pipe
+pread
+pwrite
+read
+readlink
+readlinkat
+rmdir
+setegid
+seteuid
+setgid
+setpgid
+setsid
+setuid
+sleep
+symlink
+symlinkat
+sysconf
+tcgetpgrp
+tcsetpgrp
+truncate
+ttyname
+ttyname_r
+unlink
+unlinkat
+write
+optarg
+opterr
+optind
+optopt
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/utmpx.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/utmpx.SUSv4.syms
new file mode 100644
index 00000000..1fd294aa
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/utmpx.SUSv4.syms
@@ -0,0 +1,6 @@
+endutxent
+getutxent
+getutxid
+getutxline
+pututxline
+setutxent
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/wchar-CX.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/wchar-CX.SUSv4.syms
new file mode 100644
index 00000000..08049384
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/wchar-CX.SUSv4.syms
@@ -0,0 +1,13 @@
+mbsnrtowcs
+open_wmemstream
+wcpcpy
+wcpncpy
+wcscasecmp
+wcscasecmp_l
+wcscoll_l
+wcsdup
+wcsncasecmp
+wcsncasecmp_l
+wcsnlen
+wcsnrtombs
+wcsxfrm_l
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/wchar-OBXSI.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/wchar-OBXSI.SUSv4.syms
new file mode 100644
index 00000000..bc76ee66
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/wchar-OBXSI.SUSv4.syms
@@ -0,0 +1,15 @@
+iswalnum
+iswalpha
+iswcntrl
+iswctype
+iswdigit
+iswgraph
+iswlower
+iswprint
+iswpunct
+iswspace
+iswupper
+iswxdigit
+towlower
+towupper
+wctype
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/wchar-XSI.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/wchar-XSI.SUSv4.syms
new file mode 100644
index 00000000..834731c9
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/wchar-XSI.SUSv4.syms
@@ -0,0 +1,2 @@
+wcswidth
+wcwidth
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/wchar.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/wchar.SUSv4.syms
new file mode 100644
index 00000000..d58f600b
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/wchar.SUSv4.syms
@@ -0,0 +1,59 @@
+btowc
+fgetwc
+fgetws
+fputwc
+fputws
+fwide
+fwprintf
+fwscanf
+getwc
+getwchar
+mbrlen
+mbrtowc
+mbsinit
+mbsrtowcs
+putwc
+putwchar
+swprintf
+swscanf
+ungetwc
+vfwprintf
+vfwscanf
+vswprintf
+vswscanf
+vwprintf
+vwscanf
+wcrtomb
+wcscat
+wcschr
+wcscmp
+wcscoll
+wcscpy
+wcscspn
+wcsftime
+wcslen
+wcsncat
+wcsncmp
+wcsncpy
+wcspbrk
+wcsrchr
+wcsrtombs
+wcsspn
+wcsstr
+wcstod
+wcstof
+wcstok
+wcstol
+wcstold
+wcstoll
+wcstoul
+wcstoull
+wcsxfrm
+wctob
+wmemchr
+wmemcmp
+wmemcpy
+wmemmove
+wmemset
+wprintf
+wscanf
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/wctype-CX.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/wctype-CX.SUSv4.syms
new file mode 100644
index 00000000..81c0331b
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/wctype-CX.SUSv4.syms
@@ -0,0 +1,18 @@
+iswalnum_l
+iswalpha_l
+iswblank_l
+iswcntrl_l
+iswctype_l
+iswdigit_l
+iswgraph_l
+iswlower_l
+iswprint_l
+iswpunct_l
+iswspace_l
+iswupper_l
+iswxdigit_l
+towctrans_l
+towlower_l
+towupper_l
+wctrans_l
+wctype_l
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/wctype.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/wctype.SUSv4.syms
new file mode 100644
index 00000000..fddc3955
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/wctype.SUSv4.syms
@@ -0,0 +1,18 @@
+iswalnum
+iswalpha
+iswblank
+iswcntrl
+iswctype
+iswdigit
+iswgraph
+iswlower
+iswprint
+iswpunct
+iswspace
+iswupper
+iswxdigit
+towctrans
+towlower
+towupper
+wctrans
+wctype
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/API/wordexp.SUSv4.syms b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/wordexp.SUSv4.syms
new file mode 100644
index 00000000..3681b3c4
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/API/wordexp.SUSv4.syms
@@ -0,0 +1,2 @@
+wordexp
+wordfree
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/test/Makefile
new file mode 100644
index 00000000..857ac8ad
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/Makefile
@@ -0,0 +1,76 @@
+# Makefile for uClibc
+#
+# Copyright (C) 2000-2005 Erik Andersen 
+#
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+#
+
+top_builddir=../
+include Rules.mak
+
+ALL_SUBDIRS := $(patsubst %/Makefile,%,$(wildcard */Makefile))
+
+DIRS := $(ALL_SUBDIRS)
+ifneq ($(HAVE_SHARED)$(UCLIBC_HAS_THREADS),yy)
+	DIRS := $(filter-out dlopen,$(DIRS))
+endif
+ifneq ($(findstring -static,$(LDFLAGS)),)
+	DIRS := $(filter-out dlopen,$(DIRS))
+endif
+ifneq ($(UCLIBC_HAS_THREADS),y)
+	DIRS := $(filter-out pthread,$(DIRS))
+endif
+ifneq ($(UCLIBC_HAS_FULL_RPC),y)
+	DIRS := $(filter-out rpc,$(DIRS))
+endif
+ifneq ($(UCLIBC_HAS_REGEX),y)
+	DIRS := $(filter-out regex,$(DIRS))
+endif
+ifneq ($(UCLIBC_HAS_THREADS_NATIVE),y)
+	DIRS := $(filter-out tls nptl,$(DIRS))
+endif
+ifneq ($(UCLIBC_HAS_WCHAR),y)
+	DIRS := $(filter-out locale-mbwc,$(DIRS))
+endif
+ifneq ($(UCLIBC_HAS_LOCALE),y)
+	DIRS := $(filter-out locale,$(DIRS))
+endif
+ifneq ($(UCLIBC_HAS_CRYPT),y)
+	DIRS := $(filter-out crypt,$(DIRS))
+endif
+ifeq ($(HAS_NO_THREADS),y)
+	DIRS := $(filter-out pthread,$(DIRS))
+endif
+
+test check all: run
+
+run: compile subdirs_run
+
+compile: $(top_builddir)/$(LOCAL_INSTALL_PATH) subdirs_compile
+
+$(top_builddir)/$(LOCAL_INSTALL_PATH):
+	$(Q)$(MAKE) -C $(top_builddir) $(LOCAL_INSTALL_PATH)
+
+tags:
+	ctags -R
+
+clean: subdirs_clean
+
+subdirs: $(patsubst %, _dir_%, $(DIRS))
+subdirs_compile: $(patsubst %, _dircompile_%, $(DIRS))
+subdirs_run: $(patsubst %, _dirrun_%, $(DIRS))
+subdirs_clean: $(patsubst %, _dirclean_%, $(ALL_SUBDIRS))
+
+$(patsubst %, _dir_%, $(DIRS)) : dummy
+	$(Q)$(MAKE) -C $(patsubst _dir_%, %, $@)
+
+$(patsubst %, _dirrun_%, $(DIRS)) : dummy
+	$(Q)$(MAKE) -C $(patsubst _dirrun_%, %, $@) run
+
+$(patsubst %, _dircompile_%, $(DIRS)) : dummy
+	$(Q)$(MAKE) -C $(patsubst _dircompile_%, %, $@) compile
+
+$(patsubst %, _dirclean_%, $(ALL_SUBDIRS)) : dummy
+	$(Q)$(MAKE) -C $(patsubst _dirclean_%, %, $@) clean
+
+.PHONY: all check clean dummy subdirs_compile subdirs_run subdirs subdirs_clean test run compile
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/README b/l4/pkg/uclibc/lib/contrib/uclibc/test/README
new file mode 100644
index 00000000..8fb12d9a
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/README
@@ -0,0 +1,85 @@
+-----------
+ For: User
+-----------
+Following make targets are avaialable
+
+make compile
+
+This will compile and link the tests
+
+make run
+
+This will check for binaries, if they are not there it
+will call 'compile' target, then it will execute all the tests.
+
+make check
+make all
+
+This will build and run tests.
+
+The following make variables may help you in testing:
+
+ - UCLIBC_ONLY  - only run tests against uClibc
+ - GLIBC_ONLY   - only run tests against glibc
+ - V / VERBOSE  - run tests with a lot of output
+ - TEST_INSTALLED_UCLIBC - Test installed libraries
+                           under /lib and /usr/lib.
+ - TIMEOUTFACTOR=nn - increase test timeout nn times.
+                  At least REGEX_OLD + regex/tst-regex2 needs it increased.
+
+So, to just run the uClibc tests, try this:
+make check UCLIBC_ONLY=1
+
+If you need to test just a subset of all test, delete subdirectories
+you do not need.
+
+As of 2009-07, build machinery does not track dependencies on uclibc.
+If you edit a header and re-run "make compile", it does not re-install it
+into ../install_dir. If you delete ../install_dir, "make compile"
+rebuilds uclibc as needed and re-installs ../install_dir,
+but still does not rebuild testcases.
+(You can work around it by "touch */*.c" for now).
+
+----------------
+ For: Developer
+----------------
+
+The structure of this test system is:
+ test/                    toplevel dir containing common test code
+ test/Rules.mak           Common build code
+ test/Test.mak            Runtime test make code
+ test/subdir/             code specific to a subsystem is stored in a subdir
+ test/subdir/Makefile.in  describe the tests to run
+ test/subdir/Makefile     test entry point, includes needed upper-level
+                          makefiles plus Makefile.in
+ test/subdir/*.c          the tests
+
+Each subdir has a Makefile (same for any subdir) that must include in strict order:
+  - the upper-level Rules.mak file
+  - the Makefile.in
+  - the upper-level Test.mak file
+Makefile.in may be used to define the TESTS and TESTS_DISABLED variables.
+If you do not, TESTS is built automatically based upon all the .c files in the subdir.
+TESTS := foo
+TESTS_DISABLED := bar
+Each test must use a similar .c name; so the "foo" test needs a "foo.c".
+
+Additionally, the following options further control specific test behavior:
+CFLAGS_foo    := extra cflags to use to compile test
+DODIFF_foo    := compare the output of the glibc and uClibc tests (see below)
+LDFLAGS_foo   := extra ldflags to use to link test
+OPTS_foo      := extra options to pass to test
+RET_foo       := expected exit code of test; default is 0
+WRAPPER_foo   := execute stuff just before test
+
+Or to control all tests in a subdir:
+EXTRA_CLEAN   := extra files to remove in the clean target
+EXTRA_DIRS    := extra directories to remove in the clean target
+EXTRA_CFLAGS  := -DFOO
+EXTRA_LDFLAGS := -lpthread
+OPTS          :=
+WRAPPER       :=
+
+If you want to compare the output of a test with known good output, then just
+create a local file named "foo.out.good" and the output generated by the test
+"foo" will be automatically stored in "foo.out" and compared to "foo.out.good".
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/Rules.mak b/l4/pkg/uclibc/lib/contrib/uclibc/test/Rules.mak
new file mode 100644
index 00000000..2131a7b1
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/Rules.mak
@@ -0,0 +1,140 @@
+# Rules.mak for uClibc test subdirs
+#
+# Copyright (C) 2000-2006 Erik Andersen 
+#
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+#
+
+.SUFFIXES:
+
+top_builddir ?= ../
+
+TESTDIR=$(top_builddir)test/
+
+include $(top_builddir)/Rules.mak
+ifndef TEST_INSTALLED_UCLIBC
+ifdef UCLIBC_LDSO
+ifeq (,$(findstring /,$(UCLIBC_LDSO)))
+UCLIBC_LDSO := $(top_builddir)lib/$(UCLIBC_LDSO)
+endif
+else
+UCLIBC_LDSO := $(firstword $(wildcard $(top_builddir)lib/ld*))
+endif
+endif
+#--------------------------------------------------------
+# Ensure consistent sort order, 'gcc -print-search-dirs' behavior, etc.
+LC_ALL:= C
+export LC_ALL
+
+ifeq ($(strip $(TARGET_ARCH)),)
+TARGET_ARCH:=$(shell $(CC) -dumpmachine | sed -e s'/-.*//' \
+	-e 's/i.86/i386/' \
+	-e 's/sun.*/sparc/' -e 's/sparc.*/sparc/' \
+	-e 's/sa110/arm/' -e 's/arm.*/arm/g' \
+	-e 's/m68k.*/m68k/' \
+	-e 's/parisc.*/hppa/' \
+	-e 's/ppc/powerpc/g' \
+	-e 's/v850.*/v850/g' \
+	-e 's/sh[234]/sh/' \
+	-e 's/mips.*/mips/' \
+	-e 's/cris.*/cris/' \
+	-e 's/xtensa.*/xtensa/' \
+	)
+endif
+export TARGET_ARCH
+
+RM_R = $(Q)$(RM) -r
+LN_S = $(Q)$(LN) -fs
+
+ifneq ($(KERNEL_HEADERS),)
+ifeq ($(patsubst /%,/,$(KERNEL_HEADERS)),/)
+# Absolute path in KERNEL_HEADERS
+KERNEL_INCLUDES += -I$(KERNEL_HEADERS)
+else
+# Relative path in KERNEL_HEADERS
+KERNEL_INCLUDES += -I$(top_builddir)$(KERNEL_HEADERS)
+endif
+endif
+
+XCOMMON_CFLAGS := -I$(top_builddir)test -D_GNU_SOURCE
+XWARNINGS      += $(call check_gcc,-Wstrict-prototypes,)
+CFLAGS         := -nostdinc -I$(top_builddir)$(LOCAL_INSTALL_PATH)/usr/include
+CFLAGS         += $(XCOMMON_CFLAGS) $(KERNEL_INCLUDES) $(CC_INC)
+CFLAGS         += $(OPTIMIZATION) $(CPU_CFLAGS) $(XWARNINGS)
+
+# Can't add $(OPTIMIZATION) here, it may be target-specific.
+# Just adding -Os for now.
+HOST_CFLAGS    += $(XCOMMON_CFLAGS) -Os $(XWARNINGS) -std=gnu99
+
+LDFLAGS        := $(CPU_LDFLAGS-y) -Wl,-z,now
+ifeq ($(DODEBUG),y)
+	CFLAGS        += -g
+	HOST_CFLAGS   += -g
+	LDFLAGS       += -Wl,-g
+	HOST_LDFLAGS  += -Wl,-g
+else
+	LDFLAGS       += -Wl,-s
+	HOST_LDFLAGS  += -Wl,-s
+endif
+
+ifneq ($(HAVE_SHARED),y)
+	LDFLAGS       += -Wl,-static -static-libgcc
+endif
+
+LDFLAGS += -B$(top_builddir)lib -Wl,-rpath,$(top_builddir)lib -Wl,-rpath-link,$(top_builddir)lib
+UCLIBC_LDSO_ABSPATH=$(shell pwd)
+ifdef TEST_INSTALLED_UCLIBC
+LDFLAGS += -Wl,-rpath,./
+UCLIBC_LDSO_ABSPATH=$(RUNTIME_PREFIX)$(MULTILIB_DIR)
+endif
+
+ifeq ($(findstring -static,$(LDFLAGS)),)
+LDFLAGS += -Wl,--dynamic-linker,$(UCLIBC_LDSO_ABSPATH)/$(UCLIBC_LDSO)
+endif
+
+ifeq ($(LDSO_GNU_HASH_SUPPORT),y)
+# Check for binutils support is done on root Rules.mak
+LDFLAGS += -Wl,${LDFLAGS_GNUHASH}
+endif
+
+
+ifneq ($(findstring -s,$(MAKEFLAGS)),)
+DISP := sil
+Q    := @
+SCAT := -@true
+else
+ifneq ($(V)$(VERBOSE),)
+DISP := ver
+Q    :=
+SCAT := cat
+else
+DISP := pur
+Q    := @
+SCAT := -@true
+endif
+endif
+ifneq ($(Q),)
+MAKEFLAGS += --no-print-directory
+endif
+
+banner := ---------------------------------
+pur_showclean = echo "  "CLEAN $(notdir $(CURDIR))
+pur_showdiff  = echo "  "TEST_DIFF $(notdir $(CURDIR))/
+pur_showlink  = echo "  "TEST_LINK $(notdir $(CURDIR))/ $@
+pur_showtest  = echo "  "TEST_EXEC $(notdir $(CURDIR))/ $(@:.exe=)
+sil_showclean =
+sil_showdiff  = true
+sil_showlink  = true
+sil_showtest  = true
+ver_showclean =
+ver_showdiff  = true echo
+ver_showlink  = true echo
+ver_showtest  = printf "\n$(banner)\nTEST $(notdir $(CURDIR))/ $(@:.exe=)\n$(banner)\n"
+do_showclean  = $($(DISP)_showclean)
+do_showdiff   = $($(DISP)_showdiff)
+do_showlink   = $($(DISP)_showlink)
+do_showtest   = $($(DISP)_showtest)
+showclean = @$(do_showclean)
+showdiff  = @$(do_showdiff)
+showlink  = @$(do_showlink)
+showtest  = @$(do_showtest)
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/Test.mak b/l4/pkg/uclibc/lib/contrib/uclibc/test/Test.mak
new file mode 100644
index 00000000..dd3fcc38
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/Test.mak
@@ -0,0 +1,129 @@
+# Common makefile rules for tests
+#
+# Copyright (C) 2000-2006 Erik Andersen 
+#
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+
+ifeq ($(TESTS),)
+TESTS := $(patsubst %.c,%,$(wildcard *.c))
+endif
+ifneq ($(TESTS_DISABLED),)
+TESTS := $(filter-out $(TESTS_DISABLED),$(TESTS))
+endif
+ifeq ($(SHELL_TESTS),)
+SHELL_TESTS := $(patsubst %.sh,shell_%,$(wildcard *.sh))
+endif
+
+ifneq ($(filter-out test,$(strip $(TESTS))),$(strip $(TESTS)))
+$(error Sanity check: cannot have a test named "test.c")
+endif
+
+U_TARGETS := $(TESTS)
+G_TARGETS := $(addsuffix _glibc,$(U_TARGETS))
+
+ifneq ($(GLIBC_TESTS_DISABLED),)
+G_TARGETS := $(filter-out $(GLIBC_TESTS_DISABLED),$(G_TARGETS))
+endif
+
+ifeq ($(GLIBC_ONLY),)
+TARGETS   += $(U_TARGETS)
+endif
+ifeq ($(UCLIBC_ONLY),)
+TARGETS   += $(G_TARGETS)
+endif
+
+CLEAN_TARGETS := $(U_TARGETS) $(G_TARGETS)
+CLEAN_TARGETS += $(TESTS_DISABLED) $(addsuffix _glibc,$(TESTS_DISABLED)) $(GLIBC_TESTS_DISABLED)
+COMPILE_TARGETS :=  $(TARGETS)
+RUN_TARGETS := $(addsuffix .exe,$(TARGETS))
+# provide build rules even for disabled tests:
+U_TARGETS += $(TESTS_DISABLED)
+G_TARGETS += $(addsuffix _glibc,$(TESTS_DISABLED)) $(GLIBC_TESTS_DISABLED)
+TARGETS += $(SHELL_TESTS)
+CFLAGS += $(CFLAGS_$(notdir $(CURDIR)))
+
+define binary_name
+$(patsubst %.exe,%,$@)
+endef
+define tst_src_name
+$(patsubst %_glibc,%,$(binary_name))
+endef
+
+define diff_test
+	$(Q)\
+	for x in "$(binary_name).out" "$(tst_src_name).out" ; do \
+		test -e "$$x.good" && $(do_showdiff) "$(binary_name).out" "$$x.good" && exec diff -u "$(binary_name).out" "$$x.good" ; \
+	done ; \
+	true
+endef
+define uclibc_glibc_diff_test
+	$(Q)\
+	test -z "$(DODIFF_$(tst_src_name))" && exec true ; \
+	uclibc_out="$(binary_name).out" ; \
+	glibc_out="$(tst_src_name).out" ; \
+	$(do_showdiff) $$uclibc_out $$glibc_out ; \
+	exec diff -u "$$uclibc_out" "$$glibc_out"
+endef
+define exec_test
+	$(showtest)
+	$(Q)\
+	$(WRAPPER) $(WRAPPER_$(tst_src_name)) \
+	./$(binary_name) $(OPTS) $(OPTS_$(tst_src_name)) > "$(binary_name).out" 2>&1 ; \
+		ret=$$? ; \
+		expected_ret="$(RET_$(tst_src_name))" ; \
+		test -z "$$expected_ret" && export expected_ret=0 ; \
+	if ! test $$ret -eq $$expected_ret ; then \
+		echo "ret == $$ret ; expected_ret == $$expected_ret" ; \
+		echo "The output of failed test is:"; \
+		cat "$(binary_name).out"; \
+		exit 1 ; \
+	fi
+	$(SCAT) "$(binary_name).out"
+endef
+
+test check all: run
+run: $(RUN_TARGETS)
+$(RUN_TARGETS):
+	$(exec_test)
+	$(diff_test)
+ifeq ($(UCLIBC_ONLY),)
+	$(uclibc_glibc_diff_test)
+endif
+
+compile: $(COMPILE_TARGETS)
+
+G_TARGET_SRCS := $(addsuffix .c,$(G_TARGETS))
+U_TARGET_SRCS := $(addsuffix .c,$(U_TARGETS))
+
+$(MAKE_SRCS): Makefile $(TESTDIR)Makefile $(TESTDIR)Rules.mak $(TESTDIR)Test.mak
+
+$(U_TARGETS): $(U_TARGET_SRCS) $(MAKE_SRCS)
+	$(showlink)
+	$(Q)$(CC) $(CFLAGS) $(EXTRA_CFLAGS) $(CFLAGS_$(notdir $(CURDIR))) $(CFLAGS_$@) -c $@.c -o $@.o
+	$(Q)$(CC) $(LDFLAGS) $@.o -o $@ $(EXTRA_LDFLAGS) $(LDFLAGS_$@)
+
+$(G_TARGETS): $(U_TARGET_SRCS) $(MAKE_SRCS)
+	$(showlink)
+	$(Q)$(HOSTCC) $(HOST_CFLAGS) $(CFLAGS_$(notdir $(CURDIR))) $(CFLAGS_$(patsubst %_glibc,%,$@)) -c $(patsubst %_glibc,%,$@).c -o $@.o
+	$(Q)$(HOSTCC) $(HOST_LDFLAGS) $@.o -o $@ $(EXTRA_LDFLAGS) $(LDFLAGS_$(patsubst %_glibc,%,$@))
+
+
+shell_%:
+	$(showtest)
+	$(Q)$(if $(PRE_RUN_$(@)),$(PRE_RUN_$(@)))
+	$(Q)$(SHELL) $(patsubst shell_%,%.sh,$(binary_name))
+	$(Q)$(if $(POST_RUN_$(@)),$(POST_RUN_$(@)))
+
+%.so: %.c
+	$(showlink)
+	$(Q)$(CC) \
+		$(CFLAGS) $(EXTRA_CFLAGS) $(CFLAGS_$(patsubst %_glibc,%,$@)) \
+		-fPIC -shared $< -o $@ -Wl,-soname,$@ \
+		$(LDFLAGS) $(EXTRA_LIBS) $(LDFLAGS_$(patsubst %_glibc,%,$@))
+
+clean:
+	$(showclean)
+	$(Q)$(RM) *.a *.o *.so *~ core *.out *.gdb $(CLEAN_TARGETS) $(EXTRA_CLEAN)
+	$(Q)$(RM_R) $(EXTRA_DIRS)
+
+.PHONY: all check clean test run compile
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/args/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/test/args/Makefile
new file mode 100644
index 00000000..67ee452a
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/args/Makefile
@@ -0,0 +1,7 @@
+# uClibc args tests
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+
+top_builddir=../../
+include ../Rules.mak
+-include Makefile.in
+include ../Test.mak
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/args/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/test/args/Makefile.in
new file mode 100644
index 00000000..f4edab45
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/args/Makefile.in
@@ -0,0 +1,9 @@
+# uClibc args tests
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+
+OPTS_arg_test = a b c d e f g h
+WRAPPER_arg_test = \
+	env -i \
+	ENVVAR=123 \
+	SOMETHING=sldajfasdf \
+	BLAHBLAH=" hi hi "
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/args/arg_test.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/args/arg_test.c
new file mode 100644
index 00000000..86f31575
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/args/arg_test.c
@@ -0,0 +1,40 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Test application for argc and argv handling
+ * Copyright (C) 2000-2006 by Erik Andersen 
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#include 
+#include 
+#include 
+
+int main(int argc, char **argv)
+{
+	int i=0;
+	char** index=__environ;
+
+#ifdef __powerpc__
+	{
+		unsigned long sp;
+		sp = (unsigned long) __builtin_frame_address(0);
+		if(sp&0xf){
+			printf("stack pointer is unaligned! (%08lx)\n", sp);
+		}
+	}
+#endif
+
+	printf("argc=%d\n", argc);
+
+	for(i=0;i
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#undef NDEBUG
+
+#include 
+#include 
+#include 
+#include 
+#include "../testsuite.h"
+
+int got_abort;
+
+static void aborthandler(int junk)
+{
+	got_abort = 1;
+}
+
+int main(int argc, char *argv[])
+{
+	signal(SIGABRT, aborthandler);
+
+	init_testsuite("Testing functions defined in assert.h:\n\t");
+
+	got_abort=0;
+	assert(0 == 0);
+	TEST_NUMERIC(got_abort, 0);
+
+#define NDEBUG
+	got_abort = 0;
+	printf("Don't worry -- This next test is supposed to print an assert message:\n");
+	fprintf(stderr, "\t");
+	assert(0 == 1);
+	TEST_NUMERIC(got_abort, 0);
+
+#undef NDEBUG
+	got_abort = 0;
+	assert(0 == 1);
+	TEST_NUMERIC(got_abort, 1);
+
+	exit(0);
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/build/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/test/build/Makefile
new file mode 100644
index 00000000..99a64d51
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/build/Makefile
@@ -0,0 +1,7 @@
+# uClibc build tests
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+
+top_builddir=../../
+include ../Rules.mak
+-include Makefile.in
+include ../Test.mak
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/build/check_config_options.sh b/l4/pkg/uclibc/lib/contrib/uclibc/test/build/check_config_options.sh
new file mode 100644
index 00000000..086131f3
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/build/check_config_options.sh
@@ -0,0 +1,21 @@
+#!/bin/sh
+
+ret=0
+
+# Make sure nothing uses the ARCH_HAS_MMU option anymore
+result=$(
+find ../.. \
+	| grep -v \
+		-e include/bits/uClibc_config.h \
+		-e /test/ \
+		-e /.svn/ \
+	| xargs grep -sHI \
+		__ARCH_HAS_MMU__
+)
+if [ -n "$result" ] ; then
+	echo "The build system is incorrectly using ARCH_HAS_MMU:"
+	echo "$result"
+	ret=1
+fi
+
+exit $ret
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/crypt/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/test/crypt/Makefile
new file mode 100644
index 00000000..44bbde03
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/crypt/Makefile
@@ -0,0 +1,7 @@
+# uClibc crypt tests
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+
+top_builddir=../../
+include ../Rules.mak
+-include Makefile.in
+include ../Test.mak
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/crypt/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/test/crypt/Makefile.in
new file mode 100644
index 00000000..22c27e9e
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/crypt/Makefile.in
@@ -0,0 +1,6 @@
+# uClibc crypt tests
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+
+EXTRA_LDFLAGS := -lcrypt
+
+OPTS_crypt = < crypt.input
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/crypt/crypt.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/crypt/crypt.c
new file mode 100644
index 00000000..34d7e415
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/crypt/crypt.c
@@ -0,0 +1,113 @@
+
+/*
+ * This crypt(3) validation program shipped with UFC-crypt
+ * is derived from one distributed with Phil Karns PD DES package.
+ *
+ * @(#)cert.c	1.8 11 Aug 1996
+ */
+
+#include 
+#include 
+#include "crypt.h"
+
+int totfails = 0;
+
+#if __STDC__ - 0
+int main (int argc, char *argv[]);
+void get8 (char *cp);
+void put8 (char *cp);
+void good_bye (void) __attribute__ ((noreturn));
+#else
+void get8(), put8();
+#endif
+
+void good_bye ()
+{
+  if(totfails == 0) {
+    printf("Passed DES validation suite\n");
+    exit(0);
+  } else {
+    printf("%d failures during DES validation suite!!!\n", totfails);
+    exit(1);
+  }
+}
+
+int
+main(argc, argv)
+     int argc;
+     char *argv[];
+{
+	char key[64],plain[64],cipher[64],answer[64];
+	int i;
+	int test;
+	int fail;
+
+	for(test=0;!feof(stdin);test++){
+
+		get8(key);
+		printf(" K: "); put8(key);
+		setkey(key);
+
+		get8(plain);
+		printf(" P: "); put8(plain);
+
+		get8(answer);
+		printf(" C: "); put8(answer);
+
+		for(i=0;i<64;i++)
+			cipher[i] = plain[i];
+		encrypt(cipher, 0);
+
+		for(i=0;i<64;i++)
+			if(cipher[i] != answer[i])
+				break;
+		fail = 0;
+		if(i != 64){
+			printf(" Encrypt FAIL");
+			fail++; totfails++;
+		}
+
+		encrypt(cipher, 1);
+
+		for(i=0;i<64;i++)
+			if(cipher[i] != plain[i])
+				break;
+		if(i != 64){
+			printf(" Decrypt FAIL");
+			fail++; totfails++;
+		}
+
+		if(fail == 0)
+			printf(" OK");
+		printf("\n");
+	}
+	good_bye();
+}
+void
+get8(cp)
+char *cp;
+{
+	int i,j,t;
+
+	for(i=0;i<8;i++){
+		scanf("%2x",&t);
+		if(feof(stdin))
+		  good_bye();
+		for(j=0; j<8 ; j++) {
+		  *cp++ = (t & (0x01 << (7-j))) != 0;
+		}
+	}
+}
+void
+put8(cp)
+char *cp;
+{
+	int i,j,t;
+
+	for(i=0;i<8;i++){
+	  t = 0;
+	  for(j = 0; j<8; j++)
+	    t = (t<<1) | *cp++;
+	  printf("%02x", t);
+	}
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/crypt/crypt.input b/l4/pkg/uclibc/lib/contrib/uclibc/test/crypt/crypt.input
new file mode 100644
index 00000000..d843fa8a
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/crypt/crypt.input
@@ -0,0 +1,171 @@
+0101010101010101 95f8a5e5dd31d900 8000000000000000
+0101010101010101 dd7f121ca5015619 4000000000000000
+0101010101010101 2e8653104f3834ea 2000000000000000
+0101010101010101 4bd388ff6cd81d4f 1000000000000000
+0101010101010101 20b9e767b2fb1456 0800000000000000
+0101010101010101 55579380d77138ef 0400000000000000
+0101010101010101 6cc5defaaf04512f 0200000000000000
+0101010101010101 0d9f279ba5d87260 0100000000000000
+0101010101010101 d9031b0271bd5a0a 0080000000000000
+0101010101010101 424250b37c3dd951 0040000000000000
+0101010101010101 b8061b7ecd9a21e5 0020000000000000
+0101010101010101 f15d0f286b65bd28 0010000000000000
+0101010101010101 add0cc8d6e5deba1 0008000000000000
+0101010101010101 e6d5f82752ad63d1 0004000000000000
+0101010101010101 ecbfe3bd3f591a5e 0002000000000000
+0101010101010101 f356834379d165cd 0001000000000000
+0101010101010101 2b9f982f20037fa9 0000800000000000
+0101010101010101 889de068a16f0be6 0000400000000000
+0101010101010101 e19e275d846a1298 0000200000000000
+0101010101010101 329a8ed523d71aec 0000100000000000
+0101010101010101 e7fce22557d23c97 0000080000000000
+0101010101010101 12a9f5817ff2d65d 0000040000000000
+0101010101010101 a484c3ad38dc9c19 0000020000000000
+0101010101010101 fbe00a8a1ef8ad72 0000010000000000
+0101010101010101 750d079407521363 0000008000000000
+0101010101010101 64feed9c724c2faf 0000004000000000
+0101010101010101 f02b263b328e2b60 0000002000000000
+0101010101010101 9d64555a9a10b852 0000001000000000
+0101010101010101 d106ff0bed5255d7 0000000800000000
+0101010101010101 e1652c6b138c64a5 0000000400000000
+0101010101010101 e428581186ec8f46 0000000200000000
+0101010101010101 aeb5f5ede22d1a36 0000000100000000
+0101010101010101 e943d7568aec0c5c 0000000080000000
+0101010101010101 df98c8276f54b04b 0000000040000000
+0101010101010101 b160e4680f6c696f 0000000020000000
+0101010101010101 fa0752b07d9c4ab8 0000000010000000
+0101010101010101 ca3a2b036dbc8502 0000000008000000
+0101010101010101 5e0905517bb59bcf 0000000004000000
+0101010101010101 814eeb3b91d90726 0000000002000000
+0101010101010101 4d49db1532919c9f 0000000001000000
+0101010101010101 25eb5fc3f8cf0621 0000000000800000
+0101010101010101 ab6a20c0620d1c6f 0000000000400000
+0101010101010101 79e90dbc98f92cca 0000000000200000
+0101010101010101 866ecedd8072bb0e 0000000000100000
+0101010101010101 8b54536f2f3e64a8 0000000000080000
+0101010101010101 ea51d3975595b86b 0000000000040000
+0101010101010101 caffc6ac4542de31 0000000000020000
+0101010101010101 8dd45a2ddf90796c 0000000000010000
+0101010101010101 1029d55e880ec2d0 0000000000008000
+0101010101010101 5d86cb23639dbea9 0000000000004000
+0101010101010101 1d1ca853ae7c0c5f 0000000000002000
+0101010101010101 ce332329248f3228 0000000000001000
+0101010101010101 8405d1abe24fb942 0000000000000800
+0101010101010101 e643d78090ca4207 0000000000000400
+0101010101010101 48221b9937748a23 0000000000000200
+0101010101010101 dd7c0bbd61fafd54 0000000000000100
+0101010101010101 2fbc291a570db5c4 0000000000000080
+0101010101010101 e07c30d7e4e26e12 0000000000000040
+0101010101010101 0953e2258e8e90a1 0000000000000020
+0101010101010101 5b711bc4ceebf2ee 0000000000000010
+0101010101010101 cc083f1e6d9e85f6 0000000000000008
+0101010101010101 d2fd8867d50d2dfe 0000000000000004
+0101010101010101 06e7ea22ce92708f 0000000000000002
+0101010101010101 166b40b44aba4bd6 0000000000000001
+8001010101010101 0000000000000000 95a8d72813daa94d
+4001010101010101 0000000000000000 0eec1487dd8c26d5
+2001010101010101 0000000000000000 7ad16ffb79c45926
+1001010101010101 0000000000000000 d3746294ca6a6cf3
+0801010101010101 0000000000000000 809f5f873c1fd761
+0401010101010101 0000000000000000 c02faffec989d1fc
+0201010101010101 0000000000000000 4615aa1d33e72f10
+0180010101010101 0000000000000000 2055123350c00858
+0140010101010101 0000000000000000 df3b99d6577397c8
+0120010101010101 0000000000000000 31fe17369b5288c9
+0110010101010101 0000000000000000 dfdd3cc64dae1642
+0108010101010101 0000000000000000 178c83ce2b399d94
+0104010101010101 0000000000000000 50f636324a9b7f80
+0102010101010101 0000000000000000 a8468ee3bc18f06d
+0101800101010101 0000000000000000 a2dc9e92fd3cde92
+0101400101010101 0000000000000000 cac09f797d031287
+0101200101010101 0000000000000000 90ba680b22aeb525
+0101100101010101 0000000000000000 ce7a24f350e280b6
+0101080101010101 0000000000000000 882bff0aa01a0b87
+0101040101010101 0000000000000000 25610288924511c2
+0101020101010101 0000000000000000 c71516c29c75d170
+0101018001010101 0000000000000000 5199c29a52c9f059
+0101014001010101 0000000000000000 c22f0a294a71f29f
+0101012001010101 0000000000000000 ee371483714c02ea
+0101011001010101 0000000000000000 a81fbd448f9e522f
+0101010801010101 0000000000000000 4f644c92e192dfed
+0101010401010101 0000000000000000 1afa9a66a6df92ae
+0101010201010101 0000000000000000 b3c1cc715cb879d8
+0101010180010101 0000000000000000 19d032e64ab0bd8b
+0101010140010101 0000000000000000 3cfaa7a7dc8720dc
+0101010120010101 0000000000000000 b7265f7f447ac6f3
+0101010110010101 0000000000000000 9db73b3c0d163f54
+0101010108010101 0000000000000000 8181b65babf4a975
+0101010104010101 0000000000000000 93c9b64042eaa240
+0101010102010101 0000000000000000 5570530829705592
+0101010101800101 0000000000000000 8638809e878787a0
+0101010101400101 0000000000000000 41b9a79af79ac208
+0101010101200101 0000000000000000 7a9be42f2009a892
+0101010101100101 0000000000000000 29038d56ba6d2745
+0101010101080101 0000000000000000 5495c6abf1e5df51
+0101010101040101 0000000000000000 ae13dbd561488933
+0101010101020101 0000000000000000 024d1ffa8904e389
+0101010101018001 0000000000000000 d1399712f99bf02e
+0101010101014001 0000000000000000 14c1d7c1cffec79e
+0101010101012001 0000000000000000 1de5279dae3bed6f
+0101010101011001 0000000000000000 e941a33f85501303
+0101010101010801 0000000000000000 da99dbbc9a03f379
+0101010101010401 0000000000000000 b7fc92f91d8e92e9
+0101010101010201 0000000000000000 ae8e5caa3ca04e85
+0101010101010180 0000000000000000 9cc62df43b6eed74
+0101010101010140 0000000000000000 d863dbb5c59a91a0
+0101010101010120 0000000000000000 a1ab2190545b91d7
+0101010101010110 0000000000000000 0875041e64c570f7
+0101010101010108 0000000000000000 5a594528bebef1cc
+0101010101010104 0000000000000000 fcdb3291de21f0c0
+0101010101010102 0000000000000000 869efd7f9f265a09
+1046913489980131 0000000000000000 88d55e54f54c97b4
+1007103489988020 0000000000000000 0c0cc00c83ea48fd
+10071034c8980120 0000000000000000 83bc8ef3a6570183
+1046103489988020 0000000000000000 df725dcad94ea2e9
+1086911519190101 0000000000000000 e652b53b550be8b0
+1086911519580101 0000000000000000 af527120c485cbb0
+5107b01519580101 0000000000000000 0f04ce393db926d5
+1007b01519190101 0000000000000000 c9f00ffc74079067
+3107915498080101 0000000000000000 7cfd82a593252b4e
+3107919498080101 0000000000000000 cb49a2f9e91363e3
+10079115b9080140 0000000000000000 00b588be70d23f56
+3107911598080140 0000000000000000 406a9a6ab43399ae
+1007d01589980101 0000000000000000 6cb773611dca9ada
+9107911589980101 0000000000000000 67fd21c17dbb5d70
+9107d01589190101 0000000000000000 9592cb4110430787
+1007d01598980120 0000000000000000 a6b7ff68a318ddd3
+1007940498190101 0000000000000000 4d102196c914ca16
+0107910491190401 0000000000000000 2dfa9f4573594965
+0107910491190101 0000000000000000 b46604816c0e0774
+0107940491190401 0000000000000000 6e7e6221a4f34e87
+19079210981a0101 0000000000000000 aa85e74643233199
+1007911998190801 0000000000000000 2e5a19db4d1962d6
+10079119981a0801 0000000000000000 23a866a809d30894
+1007921098190101 0000000000000000 d812d961f017d320
+100791159819010b 0000000000000000 055605816e58608f
+1004801598190101 0000000000000000 abd88e8b1b7716f1
+1004801598190102 0000000000000000 537ac95be69da1e1
+1004801598190108 0000000000000000 aed0f6ae3c25cdd8
+1002911598100104 0000000000000000 b3e35a5ee53e7b8d
+1002911598190104 0000000000000000 61c79c71921a2ef8
+1002911598100201 0000000000000000 e2f5728f0995013c
+1002911698100101 0000000000000000 1aeac39a61f0a464
+7ca110454a1a6e57 01a1d6d039776742 690f5b0d9a26939b
+0131d9619dc1376e 5cd54ca83def57da 7a389d10354bd271
+07a1133e4a0b2686 0248d43806f67172 868ebb51cab4599a
+3849674c2602319e 51454b582ddf440a 7178876e01f19b2a
+04b915ba43feb5b6 42fd443059577fa2 af37fb421f8c4095
+0113b970fd34f2ce 059b5e0851cf143a 86a560f10ec6d85b
+0170f175468fb5e6 0756d8e0774761d2 0cd3da020021dc09
+43297fad38e373fe 762514b829bf486a ea676b2cb7db2b7a
+07a7137045da2a16 3bdd119049372802 dfd64a815caf1a0f
+04689104c2fd3b2f 26955f6835af609a 5c513c9c4886c088
+37d06bb516cb7546 164d5e404f275232 0a2aeeae3ff4ab77
+1f08260d1ac2465e 6b056e18759f5cca ef1bf03e5dfa575a
+584023641aba6176 004bd6ef09176062 88bf0db6d70dee56
+025816164629b007 480d39006ee762f2 a1f9915541020b56
+49793ebc79b3258f 437540c8698f3cfa 6fbf1cafcffd0556
+4fb05e1515ab73a7 072d43a077075292 2f22e49bab7ca1ac
+49e95d6d4ca229bf 02fe55778117f12a 5a6b612cc26cce4a
+018310dc409b26d6 1d9d5c5018f728c2 5f4c038ed12b2e41
+1c587f1c13924fef 305532286d6f295a 63fac0d034d9f793
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/crypt/crypt.out.good b/l4/pkg/uclibc/lib/contrib/uclibc/test/crypt/crypt.out.good
new file mode 100644
index 00000000..073ab2be
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/crypt/crypt.out.good
@@ -0,0 +1,172 @@
+ K: 0101010101010101 P: 95f8a5e5dd31d900 C: 8000000000000000 OK
+ K: 0101010101010101 P: dd7f121ca5015619 C: 4000000000000000 OK
+ K: 0101010101010101 P: 2e8653104f3834ea C: 2000000000000000 OK
+ K: 0101010101010101 P: 4bd388ff6cd81d4f C: 1000000000000000 OK
+ K: 0101010101010101 P: 20b9e767b2fb1456 C: 0800000000000000 OK
+ K: 0101010101010101 P: 55579380d77138ef C: 0400000000000000 OK
+ K: 0101010101010101 P: 6cc5defaaf04512f C: 0200000000000000 OK
+ K: 0101010101010101 P: 0d9f279ba5d87260 C: 0100000000000000 OK
+ K: 0101010101010101 P: d9031b0271bd5a0a C: 0080000000000000 OK
+ K: 0101010101010101 P: 424250b37c3dd951 C: 0040000000000000 OK
+ K: 0101010101010101 P: b8061b7ecd9a21e5 C: 0020000000000000 OK
+ K: 0101010101010101 P: f15d0f286b65bd28 C: 0010000000000000 OK
+ K: 0101010101010101 P: add0cc8d6e5deba1 C: 0008000000000000 OK
+ K: 0101010101010101 P: e6d5f82752ad63d1 C: 0004000000000000 OK
+ K: 0101010101010101 P: ecbfe3bd3f591a5e C: 0002000000000000 OK
+ K: 0101010101010101 P: f356834379d165cd C: 0001000000000000 OK
+ K: 0101010101010101 P: 2b9f982f20037fa9 C: 0000800000000000 OK
+ K: 0101010101010101 P: 889de068a16f0be6 C: 0000400000000000 OK
+ K: 0101010101010101 P: e19e275d846a1298 C: 0000200000000000 OK
+ K: 0101010101010101 P: 329a8ed523d71aec C: 0000100000000000 OK
+ K: 0101010101010101 P: e7fce22557d23c97 C: 0000080000000000 OK
+ K: 0101010101010101 P: 12a9f5817ff2d65d C: 0000040000000000 OK
+ K: 0101010101010101 P: a484c3ad38dc9c19 C: 0000020000000000 OK
+ K: 0101010101010101 P: fbe00a8a1ef8ad72 C: 0000010000000000 OK
+ K: 0101010101010101 P: 750d079407521363 C: 0000008000000000 OK
+ K: 0101010101010101 P: 64feed9c724c2faf C: 0000004000000000 OK
+ K: 0101010101010101 P: f02b263b328e2b60 C: 0000002000000000 OK
+ K: 0101010101010101 P: 9d64555a9a10b852 C: 0000001000000000 OK
+ K: 0101010101010101 P: d106ff0bed5255d7 C: 0000000800000000 OK
+ K: 0101010101010101 P: e1652c6b138c64a5 C: 0000000400000000 OK
+ K: 0101010101010101 P: e428581186ec8f46 C: 0000000200000000 OK
+ K: 0101010101010101 P: aeb5f5ede22d1a36 C: 0000000100000000 OK
+ K: 0101010101010101 P: e943d7568aec0c5c C: 0000000080000000 OK
+ K: 0101010101010101 P: df98c8276f54b04b C: 0000000040000000 OK
+ K: 0101010101010101 P: b160e4680f6c696f C: 0000000020000000 OK
+ K: 0101010101010101 P: fa0752b07d9c4ab8 C: 0000000010000000 OK
+ K: 0101010101010101 P: ca3a2b036dbc8502 C: 0000000008000000 OK
+ K: 0101010101010101 P: 5e0905517bb59bcf C: 0000000004000000 OK
+ K: 0101010101010101 P: 814eeb3b91d90726 C: 0000000002000000 OK
+ K: 0101010101010101 P: 4d49db1532919c9f C: 0000000001000000 OK
+ K: 0101010101010101 P: 25eb5fc3f8cf0621 C: 0000000000800000 OK
+ K: 0101010101010101 P: ab6a20c0620d1c6f C: 0000000000400000 OK
+ K: 0101010101010101 P: 79e90dbc98f92cca C: 0000000000200000 OK
+ K: 0101010101010101 P: 866ecedd8072bb0e C: 0000000000100000 OK
+ K: 0101010101010101 P: 8b54536f2f3e64a8 C: 0000000000080000 OK
+ K: 0101010101010101 P: ea51d3975595b86b C: 0000000000040000 OK
+ K: 0101010101010101 P: caffc6ac4542de31 C: 0000000000020000 OK
+ K: 0101010101010101 P: 8dd45a2ddf90796c C: 0000000000010000 OK
+ K: 0101010101010101 P: 1029d55e880ec2d0 C: 0000000000008000 OK
+ K: 0101010101010101 P: 5d86cb23639dbea9 C: 0000000000004000 OK
+ K: 0101010101010101 P: 1d1ca853ae7c0c5f C: 0000000000002000 OK
+ K: 0101010101010101 P: ce332329248f3228 C: 0000000000001000 OK
+ K: 0101010101010101 P: 8405d1abe24fb942 C: 0000000000000800 OK
+ K: 0101010101010101 P: e643d78090ca4207 C: 0000000000000400 OK
+ K: 0101010101010101 P: 48221b9937748a23 C: 0000000000000200 OK
+ K: 0101010101010101 P: dd7c0bbd61fafd54 C: 0000000000000100 OK
+ K: 0101010101010101 P: 2fbc291a570db5c4 C: 0000000000000080 OK
+ K: 0101010101010101 P: e07c30d7e4e26e12 C: 0000000000000040 OK
+ K: 0101010101010101 P: 0953e2258e8e90a1 C: 0000000000000020 OK
+ K: 0101010101010101 P: 5b711bc4ceebf2ee C: 0000000000000010 OK
+ K: 0101010101010101 P: cc083f1e6d9e85f6 C: 0000000000000008 OK
+ K: 0101010101010101 P: d2fd8867d50d2dfe C: 0000000000000004 OK
+ K: 0101010101010101 P: 06e7ea22ce92708f C: 0000000000000002 OK
+ K: 0101010101010101 P: 166b40b44aba4bd6 C: 0000000000000001 OK
+ K: 8001010101010101 P: 0000000000000000 C: 95a8d72813daa94d OK
+ K: 4001010101010101 P: 0000000000000000 C: 0eec1487dd8c26d5 OK
+ K: 2001010101010101 P: 0000000000000000 C: 7ad16ffb79c45926 OK
+ K: 1001010101010101 P: 0000000000000000 C: d3746294ca6a6cf3 OK
+ K: 0801010101010101 P: 0000000000000000 C: 809f5f873c1fd761 OK
+ K: 0401010101010101 P: 0000000000000000 C: c02faffec989d1fc OK
+ K: 0201010101010101 P: 0000000000000000 C: 4615aa1d33e72f10 OK
+ K: 0180010101010101 P: 0000000000000000 C: 2055123350c00858 OK
+ K: 0140010101010101 P: 0000000000000000 C: df3b99d6577397c8 OK
+ K: 0120010101010101 P: 0000000000000000 C: 31fe17369b5288c9 OK
+ K: 0110010101010101 P: 0000000000000000 C: dfdd3cc64dae1642 OK
+ K: 0108010101010101 P: 0000000000000000 C: 178c83ce2b399d94 OK
+ K: 0104010101010101 P: 0000000000000000 C: 50f636324a9b7f80 OK
+ K: 0102010101010101 P: 0000000000000000 C: a8468ee3bc18f06d OK
+ K: 0101800101010101 P: 0000000000000000 C: a2dc9e92fd3cde92 OK
+ K: 0101400101010101 P: 0000000000000000 C: cac09f797d031287 OK
+ K: 0101200101010101 P: 0000000000000000 C: 90ba680b22aeb525 OK
+ K: 0101100101010101 P: 0000000000000000 C: ce7a24f350e280b6 OK
+ K: 0101080101010101 P: 0000000000000000 C: 882bff0aa01a0b87 OK
+ K: 0101040101010101 P: 0000000000000000 C: 25610288924511c2 OK
+ K: 0101020101010101 P: 0000000000000000 C: c71516c29c75d170 OK
+ K: 0101018001010101 P: 0000000000000000 C: 5199c29a52c9f059 OK
+ K: 0101014001010101 P: 0000000000000000 C: c22f0a294a71f29f OK
+ K: 0101012001010101 P: 0000000000000000 C: ee371483714c02ea OK
+ K: 0101011001010101 P: 0000000000000000 C: a81fbd448f9e522f OK
+ K: 0101010801010101 P: 0000000000000000 C: 4f644c92e192dfed OK
+ K: 0101010401010101 P: 0000000000000000 C: 1afa9a66a6df92ae OK
+ K: 0101010201010101 P: 0000000000000000 C: b3c1cc715cb879d8 OK
+ K: 0101010180010101 P: 0000000000000000 C: 19d032e64ab0bd8b OK
+ K: 0101010140010101 P: 0000000000000000 C: 3cfaa7a7dc8720dc OK
+ K: 0101010120010101 P: 0000000000000000 C: b7265f7f447ac6f3 OK
+ K: 0101010110010101 P: 0000000000000000 C: 9db73b3c0d163f54 OK
+ K: 0101010108010101 P: 0000000000000000 C: 8181b65babf4a975 OK
+ K: 0101010104010101 P: 0000000000000000 C: 93c9b64042eaa240 OK
+ K: 0101010102010101 P: 0000000000000000 C: 5570530829705592 OK
+ K: 0101010101800101 P: 0000000000000000 C: 8638809e878787a0 OK
+ K: 0101010101400101 P: 0000000000000000 C: 41b9a79af79ac208 OK
+ K: 0101010101200101 P: 0000000000000000 C: 7a9be42f2009a892 OK
+ K: 0101010101100101 P: 0000000000000000 C: 29038d56ba6d2745 OK
+ K: 0101010101080101 P: 0000000000000000 C: 5495c6abf1e5df51 OK
+ K: 0101010101040101 P: 0000000000000000 C: ae13dbd561488933 OK
+ K: 0101010101020101 P: 0000000000000000 C: 024d1ffa8904e389 OK
+ K: 0101010101018001 P: 0000000000000000 C: d1399712f99bf02e OK
+ K: 0101010101014001 P: 0000000000000000 C: 14c1d7c1cffec79e OK
+ K: 0101010101012001 P: 0000000000000000 C: 1de5279dae3bed6f OK
+ K: 0101010101011001 P: 0000000000000000 C: e941a33f85501303 OK
+ K: 0101010101010801 P: 0000000000000000 C: da99dbbc9a03f379 OK
+ K: 0101010101010401 P: 0000000000000000 C: b7fc92f91d8e92e9 OK
+ K: 0101010101010201 P: 0000000000000000 C: ae8e5caa3ca04e85 OK
+ K: 0101010101010180 P: 0000000000000000 C: 9cc62df43b6eed74 OK
+ K: 0101010101010140 P: 0000000000000000 C: d863dbb5c59a91a0 OK
+ K: 0101010101010120 P: 0000000000000000 C: a1ab2190545b91d7 OK
+ K: 0101010101010110 P: 0000000000000000 C: 0875041e64c570f7 OK
+ K: 0101010101010108 P: 0000000000000000 C: 5a594528bebef1cc OK
+ K: 0101010101010104 P: 0000000000000000 C: fcdb3291de21f0c0 OK
+ K: 0101010101010102 P: 0000000000000000 C: 869efd7f9f265a09 OK
+ K: 1046913489980131 P: 0000000000000000 C: 88d55e54f54c97b4 OK
+ K: 1007103489988020 P: 0000000000000000 C: 0c0cc00c83ea48fd OK
+ K: 10071034c8980120 P: 0000000000000000 C: 83bc8ef3a6570183 OK
+ K: 1046103489988020 P: 0000000000000000 C: df725dcad94ea2e9 OK
+ K: 1086911519190101 P: 0000000000000000 C: e652b53b550be8b0 OK
+ K: 1086911519580101 P: 0000000000000000 C: af527120c485cbb0 OK
+ K: 5107b01519580101 P: 0000000000000000 C: 0f04ce393db926d5 OK
+ K: 1007b01519190101 P: 0000000000000000 C: c9f00ffc74079067 OK
+ K: 3107915498080101 P: 0000000000000000 C: 7cfd82a593252b4e OK
+ K: 3107919498080101 P: 0000000000000000 C: cb49a2f9e91363e3 OK
+ K: 10079115b9080140 P: 0000000000000000 C: 00b588be70d23f56 OK
+ K: 3107911598080140 P: 0000000000000000 C: 406a9a6ab43399ae OK
+ K: 1007d01589980101 P: 0000000000000000 C: 6cb773611dca9ada OK
+ K: 9107911589980101 P: 0000000000000000 C: 67fd21c17dbb5d70 OK
+ K: 9107d01589190101 P: 0000000000000000 C: 9592cb4110430787 OK
+ K: 1007d01598980120 P: 0000000000000000 C: a6b7ff68a318ddd3 OK
+ K: 1007940498190101 P: 0000000000000000 C: 4d102196c914ca16 OK
+ K: 0107910491190401 P: 0000000000000000 C: 2dfa9f4573594965 OK
+ K: 0107910491190101 P: 0000000000000000 C: b46604816c0e0774 OK
+ K: 0107940491190401 P: 0000000000000000 C: 6e7e6221a4f34e87 OK
+ K: 19079210981a0101 P: 0000000000000000 C: aa85e74643233199 OK
+ K: 1007911998190801 P: 0000000000000000 C: 2e5a19db4d1962d6 OK
+ K: 10079119981a0801 P: 0000000000000000 C: 23a866a809d30894 OK
+ K: 1007921098190101 P: 0000000000000000 C: d812d961f017d320 OK
+ K: 100791159819010b P: 0000000000000000 C: 055605816e58608f OK
+ K: 1004801598190101 P: 0000000000000000 C: abd88e8b1b7716f1 OK
+ K: 1004801598190102 P: 0000000000000000 C: 537ac95be69da1e1 OK
+ K: 1004801598190108 P: 0000000000000000 C: aed0f6ae3c25cdd8 OK
+ K: 1002911598100104 P: 0000000000000000 C: b3e35a5ee53e7b8d OK
+ K: 1002911598190104 P: 0000000000000000 C: 61c79c71921a2ef8 OK
+ K: 1002911598100201 P: 0000000000000000 C: e2f5728f0995013c OK
+ K: 1002911698100101 P: 0000000000000000 C: 1aeac39a61f0a464 OK
+ K: 7ca110454a1a6e57 P: 01a1d6d039776742 C: 690f5b0d9a26939b OK
+ K: 0131d9619dc1376e P: 5cd54ca83def57da C: 7a389d10354bd271 OK
+ K: 07a1133e4a0b2686 P: 0248d43806f67172 C: 868ebb51cab4599a OK
+ K: 3849674c2602319e P: 51454b582ddf440a C: 7178876e01f19b2a OK
+ K: 04b915ba43feb5b6 P: 42fd443059577fa2 C: af37fb421f8c4095 OK
+ K: 0113b970fd34f2ce P: 059b5e0851cf143a C: 86a560f10ec6d85b OK
+ K: 0170f175468fb5e6 P: 0756d8e0774761d2 C: 0cd3da020021dc09 OK
+ K: 43297fad38e373fe P: 762514b829bf486a C: ea676b2cb7db2b7a OK
+ K: 07a7137045da2a16 P: 3bdd119049372802 C: dfd64a815caf1a0f OK
+ K: 04689104c2fd3b2f P: 26955f6835af609a C: 5c513c9c4886c088 OK
+ K: 37d06bb516cb7546 P: 164d5e404f275232 C: 0a2aeeae3ff4ab77 OK
+ K: 1f08260d1ac2465e P: 6b056e18759f5cca C: ef1bf03e5dfa575a OK
+ K: 584023641aba6176 P: 004bd6ef09176062 C: 88bf0db6d70dee56 OK
+ K: 025816164629b007 P: 480d39006ee762f2 C: a1f9915541020b56 OK
+ K: 49793ebc79b3258f P: 437540c8698f3cfa C: 6fbf1cafcffd0556 OK
+ K: 4fb05e1515ab73a7 P: 072d43a077075292 C: 2f22e49bab7ca1ac OK
+ K: 49e95d6d4ca229bf P: 02fe55778117f12a C: 5a6b612cc26cce4a OK
+ K: 018310dc409b26d6 P: 1d9d5c5018f728c2 C: 5f4c038ed12b2e41 OK
+ K: 1c587f1c13924fef P: 305532286d6f295a C: 63fac0d034d9f793 OK
+Passed DES validation suite
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/crypt/md5c-test.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/crypt/md5c-test.c
new file mode 100644
index 00000000..3c615402
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/crypt/md5c-test.c
@@ -0,0 +1,19 @@
+#include 
+#include 
+#include 
+#include 
+
+int
+main (int argc, char *argv[])
+{
+  const char salt[] = "$1$saltstring";
+  char *cp;
+
+  cp = crypt ("Hello world!", salt);
+  if (strcmp ("$1$saltstri$YMyguxXMBpd2TEZ.vS/3q1", cp)) {
+      fprintf(stderr, "Failed md5 crypt test!\n");
+      return EXIT_FAILURE;
+  }
+  fprintf(stderr, "Passed md5 crypt test!\n");
+  return EXIT_SUCCESS;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/ctype/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/test/ctype/Makefile
new file mode 100644
index 00000000..fd72584c
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/ctype/Makefile
@@ -0,0 +1,7 @@
+# uClibc ctype tests
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+
+top_builddir=../../
+include ../Rules.mak
+-include Makefile.in
+include ../Test.mak
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/ctype/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/test/ctype/Makefile.in
new file mode 100644
index 00000000..ee10d592
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/ctype/Makefile.in
@@ -0,0 +1,4 @@
+# uClibc ctype tests
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+
+TESTS := ctype
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/ctype/ctype.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/ctype/ctype.c
new file mode 100644
index 00000000..f38f722b
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/ctype/ctype.c
@@ -0,0 +1,250 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Test application for functions defined in ctype.h
+ * Copyright (C) 2000-2006 by Erik Andersen 
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include "../testsuite.h"
+
+
+int main( int argc, char **argv)
+{
+	int i, c;
+
+
+    init_testsuite("Testing functions defined in ctype.h\n");
+
+	/* isalnum() */
+	{
+		int buffer[]={ '1', '4', 'a', 'z', 'A', 'Z', '5', -1};
+		for(i=0; buffer[i]!=-1; i++) {
+			c = buffer[i];
+			TEST( isalnum(c)!=0);
+		}
+	}
+	{
+		int buffer[]={  2, 128, 254, '\n', -1};
+		for(i=0; buffer[i]!=-1; i++) {
+			c = buffer[i];
+			TEST( isalnum(c)==0);
+		}
+	}
+
+
+
+	/* isalpha() */
+	{
+		int buffer[]={ 'a', 'z', 'A', 'Z', -1};
+		for(i=0; buffer[i]!=-1; i++) {
+			c = buffer[i];
+			TEST( isalpha(c)!=0);
+		}
+	}
+	{
+		int buffer[]={  2, 63, 128, 254, '\n', -1};
+		for(i=0; buffer[i]!=-1; i++) {
+			c = buffer[i];
+			TEST( isalpha(c)==0);
+		}
+	}
+
+
+
+#ifdef __UCLIBC_SUSV4_LEGACY__
+	/* isascii() */
+	{
+		int buffer[]={ 'a', 'z', 'A', 'Z', '\n', -1};
+		for(i=0; buffer[i]!=-1; i++) {
+			c = buffer[i];
+			TEST( isascii(c)!=0);
+		}
+	}
+	{
+		int buffer[]={  128, 254, -1};
+		for(i=0; buffer[i]!=-1; i++) {
+			c = buffer[i];
+			TEST( isascii(c)==0);
+		}
+	}
+#endif
+
+
+	/* iscntrl() */
+	{
+		int buffer[]={ 0x7F, 6, '\t', '\n', 0x7F, -1};
+		for(i=0; buffer[i]!=-1; i++) {
+			c = buffer[i];
+			TEST( iscntrl(c)!=0);
+		}
+	}
+	{
+		int buffer[]={  63, 128, 254, -1};
+		for(i=0; buffer[i]!=-1; i++) {
+			c = buffer[i];
+			TEST( iscntrl(c)==0);
+		}
+	}
+
+
+	/* isdigit() */
+	{
+		int buffer[]={ '1', '5', '7', '9', -1};
+		for(i=0; buffer[i]!=-1; i++) {
+			c = buffer[i];
+			TEST( isdigit(c)!=0);
+		}
+	}
+	{
+		int buffer[]={  2, 'a', 'z', 'A', 'Z', 63, 128, 254, '\n', -1};
+		for(i=0; buffer[i]!=-1; i++) {
+			c = buffer[i];
+			TEST( isdigit(c)==0);
+		}
+	}
+
+
+
+	/* isgraph() */
+	{
+		int buffer[]={ ')', '~', '9', -1};
+		for(i=0; buffer[i]!=-1; i++) {
+			c = buffer[i];
+			TEST( isgraph(c)!=0);
+		}
+	}
+	{
+		int buffer[]={ 9, ' ', '\t', '\n', 200, 0x7F, -1};
+		for(i=0; buffer[i]!=-1; i++) {
+			c = buffer[i];
+			TEST( isgraph(c)==0);
+		}
+	}
+
+
+	/* islower() */
+	{
+		int buffer[]={ 'a', 'g', 'z', -1};
+		for(i=0; buffer[i]!=-1; i++) {
+			c = buffer[i];
+			TEST( islower(c)!=0);
+		}
+	}
+	{
+		int buffer[]={ 9, 'A', 'Z', 128, 254, ' ', '\t', '\n', 0x7F, -1};
+		for(i=0; buffer[i]!=-1; i++) {
+			c = buffer[i];
+			TEST( islower(c)==0);
+		}
+	}
+
+
+	/* isprint() */
+	{
+		int buffer[]={ ' ', ')', '~', '9', -1};
+		for(i=0; buffer[i]!=-1; i++) {
+			c = buffer[i];
+			TEST( isprint(c)!=0);
+		}
+	}
+	{
+		int buffer[]={ '\b', '\t', '\n', 9, 128, 254, 200, 0x7F, -1};
+		for(i=0; buffer[i]!=-1; i++) {
+			c = buffer[i];
+			TEST( isprint(c)==0);
+		}
+	}
+
+
+	/* ispunct() */
+	{
+		int buffer[]={ '.', '#', '@', ';', -1};
+		for(i=0; buffer[i]!=-1; i++) {
+			c = buffer[i];
+			TEST( ispunct(c)!=0);
+		}
+	}
+	{
+		int buffer[]={  2, 'a', 'Z', '1', 128, 254, '\n', -1};
+		for(i=0; buffer[i]!=-1; i++) {
+			c = buffer[i];
+			TEST( ispunct(c)==0);
+		}
+	}
+
+
+	/* isspace() */
+	{
+		int buffer[]={ ' ', '\t', '\r', '\v', '\n', -1};
+		for(i=0; buffer[i]!=-1; i++) {
+			c = buffer[i];
+			TEST( isspace(c)!=0);
+		}
+	}
+	{
+		int buffer[]={  2, 'a', 'Z', '1', 128, 254, -1};
+		for(i=0; buffer[i]!=-1; i++) {
+			c = buffer[i];
+			TEST( isspace(c)==0);
+		}
+	}
+
+
+	/* isupper() */
+	{
+		int buffer[]={ 'A', 'G', 'Z', -1};
+		for(i=0; buffer[i]!=-1; i++) {
+			c = buffer[i];
+			TEST( isupper(c)!=0);
+		}
+	}
+	{
+		int buffer[]={  2, 'a', 'z', '1', 128, 254, -1};
+		for(i=0; buffer[i]!=-1; i++) {
+			c = buffer[i];
+			TEST( isupper(c)==0);
+		}
+	}
+
+
+
+	/* isxdigit() */
+	{
+		int buffer[]={ 'f', 'A', '1', '8', -1};
+		for(i=0; buffer[i]!=-1; i++) {
+			c = buffer[i];
+			TEST( isxdigit(c)!=0);
+		}
+	}
+	{
+		int buffer[]={  2, 'g', 'G', 'x', '\n', -1};
+		for(i=0; buffer[i]!=-1; i++) {
+			c = buffer[i];
+			TEST( isxdigit(c)==0);
+		}
+	}
+
+
+	/* tolower() */
+	c='A';
+	TEST_NUMERIC( tolower(c), 'a');
+	c='a';
+	TEST_NUMERIC( tolower(c), 'a');
+	c='#';
+	TEST_NUMERIC( tolower(c), c);
+
+	/* toupper() */
+	c='a';
+	TEST_NUMERIC( toupper(c), 'A');
+	c='A';
+	TEST_NUMERIC( toupper(c), 'A');
+	c='#';
+	TEST_NUMERIC( toupper(c), c);
+
+	exit(0);
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/dlopen/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/test/dlopen/Makefile
new file mode 100644
index 00000000..92d14b90
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/dlopen/Makefile
@@ -0,0 +1,12 @@
+# uClibc dlopen tests
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+
+top_builddir=../../
+include ../Rules.mak
+-include Makefile.in
+ifneq ($(HAVE_SHARED),y)
+TESTS_DISABLED := test3
+LDFLAGS_libtest.so := -lpthread
+endif
+
+include ../Test.mak
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/dlopen/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/test/dlopen/Makefile.in
new file mode 100644
index 00000000..22190d9f
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/dlopen/Makefile.in
@@ -0,0 +1,39 @@
+# uClibc dlopen tests
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+
+# rules need a little love to work with glibc ...
+export UCLIBC_ONLY := 1
+
+TESTS := dltest dltest2 dlstatic test1 test2 test3 dlundef dlafk dladdr
+
+CFLAGS_dltest    := -DLIBNAME="\"./libtest.so\""
+CFLAGS_dltest2   := -DLIBNAME="\"./libtest3.so\""
+
+LDFLAGS_dlstatic := -ldl
+LDFLAGS_dltest   := -ldl
+LDFLAGS_dltest2  := -ldl
+LDFLAGS_dlundef  := -ldl
+LDFLAGS_dlafk    := -ldl ./libafk.so -Wl,-rpath,.
+LDFLAGS_test1    := -ldl
+LDFLAGS_test2    := -ldl
+LDFLAGS_test3    := -ldl ./libtest1.so ./libtest2.so -Wl,-rpath,.
+LDFLAGS_dladdr   := -ldl
+
+DEBUG_LIBS := X
+WRAPPER := env $(DEBUG_LIBS)=all LD_LIBRARY_PATH="$$PWD:.:$(LD_LIBRARY_PATH)"
+
+dltest: libtest.so
+dltest2: libtest3.so
+dlstatic: libstatic.so
+dlundef: libundef.so
+dlafk: libafk.so
+libafk.so: libafk-temp.so
+LDFLAGS_libafk.so := ./libafk-temp.so -Wl,-rpath,.
+test1: libtest1.so
+test2: libtest1.so libtest2.so
+test3: libtest1.so libtest2.so
+libtest1.so: libtest2.so
+LDFLAGS_libtest.so := -lpthread
+LDFLAGS_libtest1.so := ./libtest2.so -Wl,-rpath,.
+LDFLAGS_libtest2.so := -Wl,-rpath,.
+LDFLAGS_libtest3.so := -lpthread -Wl,-rpath,.
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/dlopen/dladdr.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/dlopen/dladdr.c
new file mode 100644
index 00000000..b64c000b
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/dlopen/dladdr.c
@@ -0,0 +1,25 @@
+#include 
+#include 
+#include 
+#include 
+
+int main(int argc, char **argv)
+{
+	Dl_info info;
+	int res = 0;
+
+	memset(&info, '\0', sizeof(Dl_info));
+	res = dladdr((void *)1, &info);
+	if (res != 0) {
+		fprintf(stderr, "dladdr() should fail\n");
+		fprintf(stderr, "dli_fname = %s\n", info.dli_fname);
+		fprintf(stderr, "dli_fbase = 0x%08x\n", (unsigned int)info.dli_fbase);
+		fprintf(stderr, "dli_sname = %s\n", info.dli_sname);
+		fprintf(stderr, "dli_saddr = 0x%08x\n", (unsigned int)info.dli_saddr);
+		exit(1);
+        }
+
+	fprintf(stderr, "dladdr() failed as expected\n");
+	return EXIT_SUCCESS;
+}
+
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/dlopen/dlafk.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/dlopen/dlafk.c
new file mode 100644
index 00000000..2eac4afb
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/dlopen/dlafk.c
@@ -0,0 +1,36 @@
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define LIBNAME "libafk.so"
+
+#define LIBAFK "libafk-temp.so"
+#define LIBAFK_BAK ".libafk-temp.so.temp"
+
+int main(int argc, char **argv)
+{
+	void *handle;
+
+	if (rename(LIBAFK, LIBAFK_BAK)) {
+		fprintf(stderr, "Unable to rename %s: %s\n", LIBAFK, strerror(errno));
+		return EXIT_FAILURE;
+	}
+
+	handle = dlopen(LIBNAME, RTLD_NOW);
+	if (!handle) {
+		fprintf(stderr, "Could not open ./%s: %s\n", LIBNAME, dlerror());
+		return EXIT_FAILURE;
+	}
+
+	if (rename(LIBAFK_BAK, LIBAFK)) {
+		fprintf(stderr, "Unable to rename %s: %s\n", LIBAFK_BAK, strerror(errno));
+		return EXIT_FAILURE;
+	}
+
+	return EXIT_SUCCESS;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/dlopen/dlstatic.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/dlopen/dlstatic.c
new file mode 100644
index 00000000..57c8c5dd
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/dlopen/dlstatic.c
@@ -0,0 +1,43 @@
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define LIBNAME "libstatic.so"
+
+int load_and_test(void)
+{
+	void *handle;
+	int (*mystatic)(void);
+
+	handle = dlopen(LIBNAME, RTLD_LAZY);
+	if (!handle) {
+		fprintf(stderr, "Could not open ./%s: %s\n", LIBNAME, dlerror());
+		return 1;
+	}
+
+	mystatic = dlsym(handle, "static_test");
+	if (mystatic == NULL) {
+		fprintf(stderr, "Could not locate symbol 'static_test': %s\n", dlerror());
+		return 1;
+	}
+
+	if (!mystatic()) {
+		fprintf(stderr, "mystatic() failed: static vars were not setup properly\n");
+		return 1;
+	}
+
+	dlclose(handle);
+
+	return 0;
+}
+
+int main(int argc, char **argv)
+{
+	int count = 5;
+	while (count-- > 0)
+		if (load_and_test())
+			return EXIT_FAILURE;
+	return EXIT_SUCCESS;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/dlopen/dltest.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/dlopen/dltest.c
new file mode 100644
index 00000000..b5fa1cdd
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/dlopen/dltest.c
@@ -0,0 +1,41 @@
+#include 
+#include 
+#include 
+#include 
+#include 
+
+int main(int argc, char **argv)
+{
+	int ret = EXIT_SUCCESS;
+	void *handle;
+	void (*mydltest)(void *value1, void *value2);
+	char *error;
+	uint32_t *value1, *value2;
+
+	handle = dlopen (LIBNAME, RTLD_LAZY);
+	if (!handle) {
+		fprintf(stderr, "Could not open ./%s: %s\n", LIBNAME, dlerror());
+		exit(1);
+	}
+
+	mydltest = dlsym(handle, "dltest");
+	if ((error = dlerror()) != NULL)  {
+		fprintf(stderr, "Could not locate symbol 'dltest': %s\n", error);
+		exit(1);
+	}
+
+	mydltest(&value1, &value2);
+	printf("dltest: pthread_once=%p\n", value1);
+	printf("dltest: pthread_self=%p\n", value2);
+	if (value1 == value2) {
+	    ret = EXIT_FAILURE;
+	    printf("dltest: values should NOT be equal  Weak values resolved incorrectly!\n");
+	} else {
+	    printf("dltest: weak symbols resoved correctly.\n");
+	}
+
+	dlclose(handle);
+
+	return ret;
+}
+
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/dlopen/dltest2.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/dlopen/dltest2.c
new file mode 100644
index 00000000..127b3b52
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/dlopen/dltest2.c
@@ -0,0 +1 @@
+#include "dltest.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/dlopen/dlundef.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/dlopen/dlundef.c
new file mode 100644
index 00000000..cefd9331
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/dlopen/dlundef.c
@@ -0,0 +1,29 @@
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define LIBNAME "libundef.so"
+
+int main(int argc, char **argv)
+{
+	void *handle;
+	int (*myundefined)(void);
+
+	handle = dlopen(LIBNAME, RTLD_LAZY);
+	if (!handle) {
+		fprintf(stderr, "Could not open ./%s: %s\n", LIBNAME, dlerror());
+		return EXIT_FAILURE;
+	}
+
+	myundefined = dlsym(handle, "__booga_booga_you_cant_touch_this__");
+	if (myundefined != NULL) {
+		fprintf(stderr, "dlsym() found a symbol that does not exist!\n");
+		return EXIT_FAILURE;
+	}
+
+	dlclose(handle);
+
+	return EXIT_SUCCESS;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/dlopen/libafk-temp.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/dlopen/libafk-temp.c
new file mode 100644
index 00000000..39b58df2
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/dlopen/libafk-temp.c
@@ -0,0 +1 @@
+/* the actual contents doesnt matter */
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/dlopen/libafk.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/dlopen/libafk.c
new file mode 100644
index 00000000..39b58df2
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/dlopen/libafk.c
@@ -0,0 +1 @@
+/* the actual contents doesnt matter */
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/dlopen/libstatic.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/dlopen/libstatic.c
new file mode 100644
index 00000000..bf44c3c6
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/dlopen/libstatic.c
@@ -0,0 +1,15 @@
+#include 
+
+static int global_static = -1;
+
+int static_test(void)
+{
+	static int local_static = -2;
+
+	if (global_static != -1)
+		printf("FAIL: global_static is not -1\n");
+	if (local_static != -2)
+		printf("FAIL: local_static is not -2\n");
+
+	return (global_static == -1 && local_static == -2);
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/dlopen/libtest.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/dlopen/libtest.c
new file mode 100644
index 00000000..3fd137f0
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/dlopen/libtest.c
@@ -0,0 +1,11 @@
+#include 
+#include 
+#include 
+
+void dltest(uint32_t **value1, uint32_t **value2);
+void dltest(uint32_t **value1, uint32_t **value2)
+{
+	*value1 = (uint32_t *) pthread_once;
+	*value2 = (uint32_t *) pthread_self;
+}
+
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/dlopen/libtest1.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/dlopen/libtest1.c
new file mode 100644
index 00000000..a2f7dcdc
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/dlopen/libtest1.c
@@ -0,0 +1,40 @@
+#include 
+
+extern int libtest2_func(const char *s);
+
+void __attribute__((constructor)) libtest1_ctor(void);
+void libtest1_ctor(void)
+{
+    printf("libtest1: constructor!\n");
+}
+
+void __attribute__((destructor)) libtest1_dtor(void);
+void libtest1_dtor(void)
+{
+    printf("libtest1: destructor!\n");
+}
+
+void __attribute__((weak)) function1(void);
+void function1(void)
+{
+    printf("libtest1: I am weak function1!\n");
+}
+
+void function2(void);
+void function2(void)
+{
+    printf("libtest1: I am function2!\n");
+}
+
+int dltest(const char *s);
+int dltest(const char *s)
+{
+    printf( "libtest1: function1 = %p\n"
+	    "libtest1: function2 = %p\n",
+	    function1, function2);
+    function1();
+    function2();
+    return(libtest2_func(s));
+}
+
+
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/dlopen/libtest2.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/dlopen/libtest2.c
new file mode 100644
index 00000000..52615066
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/dlopen/libtest2.c
@@ -0,0 +1,38 @@
+#include 
+#include 
+
+void __attribute__((constructor)) libtest2_ctor(void);
+void libtest2_ctor(void)
+{
+    printf("libtest2: constructor!\n");
+}
+
+void __attribute__((destructor)) libtest2_dtor(void);
+void libtest2_dtor(void)
+{
+    printf("libtest2: destructor!\n");
+}
+
+void function1(void);
+void function1(void)
+{
+    printf("libtest2: I am function1!\n");
+}
+
+void __attribute__((weak)) function2(void);
+void function2(void)
+{
+    printf("libtest2: I am weak function2!\n");
+}
+
+
+int libtest2_func(const char *s);
+int libtest2_func(const char *s)
+{
+    printf( "libtest2: function1 = %p\n"
+	    "libtest2: function2 = %p\n",
+	    function1, function2);
+    function1();
+    function2();
+    return 0;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/dlopen/libtest3.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/dlopen/libtest3.c
new file mode 100644
index 00000000..1d4bd7e6
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/dlopen/libtest3.c
@@ -0,0 +1 @@
+#include "libtest.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/dlopen/libundef.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/dlopen/libundef.c
new file mode 100644
index 00000000..39b58df2
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/dlopen/libundef.c
@@ -0,0 +1 @@
+/* the actual contents doesnt matter */
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/dlopen/test1.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/dlopen/test1.c
new file mode 100644
index 00000000..c13eb300
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/dlopen/test1.c
@@ -0,0 +1,33 @@
+#include 
+#include 
+#include 
+#include 
+
+#ifdef __UCLIBC__
+extern void _dlinfo(void);
+#endif
+
+int main(int argc, char **argv) {
+	void *handle;
+	int (*mydltest)(const char *s);
+	char *error;
+
+	handle = dlopen ("./libtest1.so", RTLD_LAZY);
+	if (!handle) {
+		fprintf(stderr, "Could not open ./libtest1.so: %s\n", dlerror());
+		exit(1);
+	}
+
+	mydltest = dlsym(handle, "dltest");
+	if ((error = dlerror()) != NULL)  {
+		fprintf(stderr, "Could not locate symbol 'dltest': %s\n", error);
+		exit(1);
+	}
+
+	mydltest("hello world!");
+
+	dlclose(handle);
+
+	return EXIT_SUCCESS;
+}
+
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/dlopen/test2.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/dlopen/test2.c
new file mode 100644
index 00000000..d8428f7f
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/dlopen/test2.c
@@ -0,0 +1,39 @@
+#include 
+#include 
+#include 
+#include 
+
+#ifdef __UCLIBC__
+extern void _dlinfo(void);
+#endif
+
+int main(int argc, char **argv) {
+	void *handle;
+	int (*mydltest)(const char *s);
+	char *error;
+
+	handle = dlopen ("./libtest2.so", RTLD_LAZY);
+	if (!handle) {
+		fprintf(stderr, "Could not open ./libtest2.so: %s\n", dlerror());
+		exit(1);
+	}
+
+	handle = dlopen ("./libtest1.so", RTLD_LAZY);
+	if (!handle) {
+		fprintf(stderr, "Could not open ./libtest1.so: %s\n", dlerror());
+		exit(1);
+	}
+
+	mydltest = dlsym(handle, "dltest");
+	if ((error = dlerror()) != NULL)  {
+		fprintf(stderr, "Could not locate symbol 'dltest': %s\n", error);
+		exit(1);
+	}
+
+	mydltest("hello world!");
+
+	dlclose(handle);
+
+	return EXIT_SUCCESS;
+}
+
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/dlopen/test3.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/dlopen/test3.c
new file mode 100644
index 00000000..2f2dfc65
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/dlopen/test3.c
@@ -0,0 +1,13 @@
+#include 
+#include 
+#include 
+#include 
+
+extern int dltest(const char *s);
+
+int main(int argc, char **argv)
+{
+	dltest("hello world!");
+	return EXIT_SUCCESS;
+}
+
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/inet/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/test/inet/Makefile
new file mode 100644
index 00000000..9605dca6
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/inet/Makefile
@@ -0,0 +1,7 @@
+# uClibc inet tests
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+
+top_builddir=../../
+include ../Rules.mak
+-include Makefile.in
+include ../Test.mak
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/inet/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/test/inet/Makefile.in
new file mode 100644
index 00000000..0c0b9dc3
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/inet/Makefile.in
@@ -0,0 +1,7 @@
+# uClibc inet tests
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+#
+ifeq ($(UCLIBC_HAS_IPV4)$(UCLIBC_HAS_IPV6),)
+TESTS_DISABLED := bug-if1 gethost_r-align gethostid if_nameindex tst-aton \
+	tst-network tst-ntoa 
+endif
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/inet/bug-if1.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/inet/bug-if1.c
new file mode 100644
index 00000000..6bcd175e
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/inet/bug-if1.c
@@ -0,0 +1,54 @@
+/* Copyright (C) 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2004.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+static int
+do_test (void)
+{
+  char buf[IF_NAMESIZE];
+  /* Index 0 is always invalid (see RFC 3493).  */
+  char *cp = if_indextoname (0, buf);
+  if (cp != NULL)
+    {
+      printf ("invalid index returned result \"%s\"\n", cp);
+      return 1;
+    }
+  else if (errno != ENXIO)
+    {
+      int err = errno;
+      char errbuf1[256];
+      char errbuf2[256];
+
+      printf ("errno = %d (%s), expected %d (%s)\n",
+	      err, strerror_r (err, errbuf1, sizeof (errbuf1)),
+	      ENXIO, strerror_r (ENXIO, errbuf2, sizeof (errbuf2)));
+      return 1;
+    }
+
+  return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/inet/gethost_r-align.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/inet/gethost_r-align.c
new file mode 100644
index 00000000..53ce93ac
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/inet/gethost_r-align.c
@@ -0,0 +1,50 @@
+/* Since the reentrant gethost functions take a char * buffer,
+ * we have to make sure they internally do not assume alignment.
+ * The actual return values are not relevant.  If the test fails,
+ * it'll be due to an alignment exception which means the test
+ * app is killed by the kernel.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+int main(int argc, char *argv[])
+{
+	size_t i;
+	char buf[1024];
+	in_addr_t addr;
+
+	addr = inet_addr("127.0.0.1");
+
+	for (i = 0; i < sizeof(size_t) * 2; ++i) {
+		struct hostent hent, *hentres;
+		int ret, herr;
+
+		printf("Testing misalignment of %2zi bytes: ", i);
+
+		memset(&hent, 0x00, sizeof(hent));
+		ret = gethostent_r(&hent, buf + i, sizeof(buf) - i, &hentres, &herr);
+		printf("%sgethostent_r() ", (ret ? "!!!" : ""));
+
+		memset(&hent, 0x00, sizeof(hent));
+		ret = gethostbyname_r("localhost", &hent, buf + i, sizeof(buf) - i, &hentres, &herr);
+		printf("%sgethostbyname_r() ", (ret ? "!!!" : ""));
+
+		memset(&hent, 0x00, sizeof(hent));
+		ret = gethostbyname2_r("localhost", AF_INET, &hent, buf + i, sizeof(buf) - i, &hentres, &herr);
+		printf("%sgethostbyname2_r() ", (ret ? "!!!" : ""));
+
+		memset(&hent, 0x00, sizeof(hent));
+		ret = gethostbyaddr_r(&addr, sizeof(addr), AF_INET, &hent, buf + i, sizeof(buf) - i, &hentres, &herr);
+		printf("%sgethostbyaddr_r() ", (ret ? "!!!" : ""));
+
+		puts("OK!");
+	}
+
+	return 0;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/inet/gethostid.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/inet/gethostid.c
new file mode 100644
index 00000000..29516653
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/inet/gethostid.c
@@ -0,0 +1,6 @@
+#include 
+#include 
+int main(void) {
+	printf("hostid=%d\n", gethostid());
+	return 0;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/inet/getnetent.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/inet/getnetent.c
new file mode 100644
index 00000000..6607cea9
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/inet/getnetent.c
@@ -0,0 +1,17 @@
+#include 
+#include 
+int main(void)
+{
+	struct netent *net;
+	setnetent(0);
+	while ((net = getnetent())) {
+		while (net->n_net && !((net->n_net >> 24) & 0xff)) {
+			net->n_net <<= 8;
+		}
+		printf("%lu.%lu.%lu.%lu\n",
+			   (net->n_net >> 24) & 0xff, (net->n_net >> 16) & 0xff,
+			   (net->n_net >> 8) & 0xff, net->n_net & 0xff);
+	}
+	endnetent();
+	return 0;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/inet/if_nameindex.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/inet/if_nameindex.c
new file mode 100644
index 00000000..126c5bab
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/inet/if_nameindex.c
@@ -0,0 +1,61 @@
+/* if_nameindex.c: test the if_nameindex() function
+ *
+ * Copyright (C) 2006 Erik Andersen 
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#include 
+#include 
+#include 
+
+static char ifname[IF_NAMESIZE];
+
+static void test_if_nameindex(void)
+{
+	size_t i;
+	struct if_nameindex *ret;
+
+	ret = if_nameindex();
+
+	if (ret == NULL) {
+		perror("if_nameindex()");
+		exit(1);
+	}
+
+	printf("--- if_nameindex()\n");
+	for (i=0; ret[i].if_name; ++i)
+		printf("%i: %s\n", ret[i].if_index, ret[i].if_name);
+
+	if_freenameindex(ret);
+}
+
+static void test_if_indextoname(void)
+{
+	if (if_indextoname(1, ifname) == NULL) {
+		perror("if_nameindex()");
+		exit(1);
+	}
+
+	printf("if_indextoname(1) = %s\n", ifname);
+}
+
+static void test_if_nametoindex(void)
+{
+	int ifindex = if_nametoindex(ifname);
+
+	if (ifindex == 0) {
+		perror("if_nametoindex()");
+		exit(1);
+	}
+
+	printf("if_nametoindex(%s) = %i\n", ifname, ifindex);
+}
+
+int main(void)
+{
+	test_if_nameindex();
+	test_if_indextoname();
+	test_if_nametoindex();
+	return 0;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/inet/tst-aton.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/inet/tst-aton.c
new file mode 100644
index 00000000..3e945f13
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/inet/tst-aton.c
@@ -0,0 +1,80 @@
+#include 
+#include 
+#include 
+#include 
+
+/* Note: uClibc only supports the standard notation 'a.b.c.d' */
+
+static struct tests
+{
+  const char *input;
+  int valid;
+  uint32_t result;
+} tests[] =
+{
+  { "", 0, 0 },
+  { "-1", 0, 0 },
+/*
+  { "256", 1, 0x00000100 },
+*/
+  { "256.", 0, 0 },
+  { "256a", 0, 0 },
+/*
+  { "0x100", 1, 0x00000100 },
+  { "0200.0x123456", 1, 0x80123456 },
+  { "0300.0x89123456.", 0 ,0 },
+  { "0100.-0xffff0000", 0, 0 },
+  { "0.0xffffff", 1, 0x00ffffff },
+  { "0.0x1000000", 0, 0 },
+  { "0377.16777215", 1, 0xffffffff },
+  { "0377.16777216", 0, 0 },
+  { "0x87.077777777", 1, 0x87ffffff },
+  { "0x87.0100000000", 0, 0 },
+  { "0.1.3", 1, 0x00010003 },
+*/
+  { "0.256.3", 0, 0 },
+  { "256.1.3", 0, 0 },
+/*
+  { "0.1.0x10000", 0, 0 },
+  { "0.1.0xffff", 1, 0x0001ffff },
+*/
+  { "0.1a.3", 0, 0 },
+  { "0.1.a3", 0, 0 },
+  { "1.2.3.4", 1, 0x01020304 },
+  { "0400.2.3.4", 0, 0 },
+  { "1.0x100.3.4", 0, 0 },
+  { "1.2.256.4", 0, 0 },
+  { "1.2.3.0x100", 0, 0 },
+  { "323543357756889", 0, 0 },
+  { "10.1.2.3.4", 0, 0},
+};
+
+
+int
+main (int argc, char *argv[])
+{
+  int result = 0;
+  size_t cnt;
+
+  for (cnt = 0; cnt < sizeof (tests) / sizeof (tests[0]); ++cnt)
+    {
+      struct in_addr addr;
+
+      if ((int) inet_aton (tests[cnt].input, &addr) != tests[cnt].valid)
+	{
+	  if (tests[cnt].valid)
+	    printf ("\"%s\" not seen as valid IP address\n", tests[cnt].input);
+	  else
+	    printf ("\"%s\" seen as valid IP address\n", tests[cnt].input);
+	  result = 1;
+	}
+      else if (tests[cnt].valid && addr.s_addr != ntohl (tests[cnt].result))
+	{
+	  printf ("\"%s\" not converted correctly: is %08x, should be %08x\n",
+		  tests[cnt].input, addr.s_addr, tests[cnt].result);
+	  result = 1;
+	}
+    }
+
+  return result;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/inet/tst-ethers-line.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/inet/tst-ethers-line.c
new file mode 100644
index 00000000..19cf2fbf
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/inet/tst-ethers-line.c
@@ -0,0 +1,54 @@
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/* glibc 2.4 has no ETHER_FILE_NAME, host compile fails without this */
+#ifndef ETHER_FILE_NAME
+#define ETHER_FILE_NAME "/etc/ethers"
+#endif
+
+#define ETHER_LINE_LEN 256
+
+/* This test requires /etc/ethers to exist
+ * and to have nonzero length
+ */
+
+int main(void)
+{
+	struct ether_addr addr;
+	char hostname[ETHER_LINE_LEN];
+	int fd, i;
+	const char *ethers;
+	struct stat statb;
+
+	if ((fd = open(ETHER_FILE_NAME, O_RDONLY)) == -1) {
+		perror ("Cannot open file");
+		exit(1);
+	}
+
+	if (fstat(fd, &statb)) {
+		perror("Stat failed");
+		exit(1);
+	}
+	ethers = mmap(NULL, statb.st_size, PROT_READ, MAP_SHARED, fd, 0);
+
+	if (ethers == MAP_FAILED) {
+		perror("File mapping failed");
+		exit(1);
+	}
+
+	ether_line(ethers, &addr, hostname);
+
+	for (i = 0; i < 6; i++) {
+		printf("%02x", addr.ether_addr_octet[i]);
+		if (i < 5)
+			printf(":");
+	}
+	printf(" %s\n", hostname);
+
+	return 0;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/inet/tst-ethers.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/inet/tst-ethers.c
new file mode 100644
index 00000000..6b6e10cd
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/inet/tst-ethers.c
@@ -0,0 +1,33 @@
+#include 
+#include 
+
+#define ETHER_LINE_LEN 256
+
+/* This test requires /etc/ethers to exist
+ * and to have host "teeth". For example:
+ * 00:11:22:33:44:55 teeth
+ */
+
+int main(void)
+{
+	struct ether_addr addr;
+	char host[ETHER_LINE_LEN];
+	int i;
+	int res = ether_hostton("teeth", &addr);
+
+	if (res)
+		return 1;
+
+	for (i = 0; i < 6; i++) {
+		printf("%02x", addr.ether_addr_octet[i]);
+		if (i < 5)
+			printf(":");
+	}
+
+	res = ether_ntohost(host, &addr);
+	if (res)
+		return 1;
+	printf(" %s\n", host);
+
+	return 0;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/inet/tst-network.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/inet/tst-network.c
new file mode 100644
index 00000000..25986373
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/inet/tst-network.c
@@ -0,0 +1,105 @@
+/* Test for inet_network.
+   Copyright (C) 2000, 2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Andreas Jaeger , 2000.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+
+struct
+{
+  const char *network;
+  uint32_t number;
+} tests [] =
+{
+  {"1.0.0.0", 0x1000000},
+  {"1.0.0", 0x10000},
+  {"1.0", 0x100},
+  {"1", 0x1},
+  {"192.168.0.0", 0xC0A80000},
+  /* Now some invalid addresses.  */
+  {"141.30.225.2800", INADDR_NONE},
+  {"141.76.1.1.1", INADDR_NONE},
+  {"141.76.1.11.", INADDR_NONE},
+  {"1410", INADDR_NONE},
+  {"1.1410", INADDR_NONE},
+  {"1.1410.", INADDR_NONE},
+  {"1.1410", INADDR_NONE},
+  {"141.76.1111", INADDR_NONE},
+  {"141.76.1111.", INADDR_NONE},
+  {"1.1.1.257", INADDR_NONE},
+  /* Now some from BSD */
+  {"0x12", 0x00000012},
+  {"127.1", 0x00007f01},
+  {"127.1.2.3", 0x7f010203},
+  {"0x123456", INADDR_NONE},
+  {"0x12.0x34", 0x00001234},
+  {"0x12.0x345", INADDR_NONE},
+  {"1.2.3.4.5", INADDR_NONE},
+  {"1..3.4", INADDR_NONE},
+  {".", INADDR_NONE},
+  {"1.", INADDR_NONE},
+  {".1", INADDR_NONE},
+  {"x", INADDR_NONE},
+  {"0x", INADDR_NONE},
+  {"0", 0x00000000},
+  {"0x0", 0x00000000},
+  {"01.02.07.077", 0x0102073f},
+  {"0x1.23.045.0", 0x01172500},
+  {"", INADDR_NONE},
+  {" ", INADDR_NONE},
+  {"bar", INADDR_NONE},
+  {"1.2bar", INADDR_NONE},
+  {"1.", INADDR_NONE},
+  {"ÊÃÕËÅÎ", INADDR_NONE},
+  {"255.255.255.255", INADDR_NONE},
+  {"x", INADDR_NONE},
+  {"0X12", 0x00000012},
+  {"078", INADDR_NONE},
+  {"1 bar", INADDR_NONE},
+  {"127.0xfff", INADDR_NONE},
+};
+
+
+int
+main (void)
+{
+  int errors = 0;
+  size_t i;
+  uint32_t res;
+
+  for (i = 0; i < sizeof (tests) / sizeof (tests[0]); ++i)
+    {
+      printf ("Testing: %s\n", tests[i].network);
+      res = inet_network (tests[i].network);
+
+      if (res != tests[i].number)
+	{
+	  ++errors;
+	  printf ("Test failed for inet_network (\"%s\"):\n",
+		  tests[i].network);
+	  printf ("Expected return value %u (0x%x) but got %u (0x%x).\n",
+		  tests[i].number, tests[i].number, res, res);
+	}
+
+    }
+
+  return errors != 0;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/inet/tst-ntoa.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/inet/tst-ntoa.c
new file mode 100644
index 00000000..9be91eb5
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/inet/tst-ntoa.c
@@ -0,0 +1,36 @@
+#include 
+#include 
+#include 
+#include 
+
+
+static int
+test (unsigned int inaddr, const char *expected)
+{
+  struct in_addr addr;
+  char *res;
+  int fail;
+
+  addr.s_addr = htonl (inaddr);
+  res = inet_ntoa (addr);
+  fail = strcmp (res, expected);
+
+  printf ("%#010x -> \"%s\" -> %s%s\n", inaddr, res,
+	  fail ? "fail, expected" : "ok", fail ? expected : "");
+
+  return fail;
+}
+
+
+int
+main (void)
+{
+  int result = 0;
+
+  result |= test (INADDR_LOOPBACK, "127.0.0.1");
+  result |= test (INADDR_BROADCAST, "255.255.255.255");
+  result |= test (INADDR_ANY, "0.0.0.0");
+  result |= test (0xc0060746, "192.6.7.70");
+
+  return result;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/librt/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/test/librt/Makefile
new file mode 100644
index 00000000..354c6811
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/librt/Makefile
@@ -0,0 +1,7 @@
+# uClibc shm tests
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+
+top_builddir=../../
+include ../Rules.mak
+-include Makefile.in
+include ../Test.mak
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/librt/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/test/librt/Makefile.in
new file mode 100644
index 00000000..15ecbae5
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/librt/Makefile.in
@@ -0,0 +1,4 @@
+# uClibc shm tests
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+
+LDFLAGS_shmtest := -lrt
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/librt/shmtest.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/librt/shmtest.c
new file mode 100644
index 00000000..a14302d0
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/librt/shmtest.c
@@ -0,0 +1,104 @@
+/* Copyright (C) 2009 Mikael Lund Jepsen 
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
+
+char shared_name[] = "/sharetest";
+int test_data[11] = {0,1,2,3,4,5,6,7,8,9,10};
+
+int main(void) {
+	int pfds[2];
+	pid_t pid;
+	int fd;
+	int test_data_fails = 0;
+	char *ptest_data;
+	unsigned int i;
+	char buf[30];
+	int rv;
+
+	pipe(pfds);
+
+	switch(pid = fork()) {
+	case -1:
+		perror("fork");
+		exit(1);	/* parent exits */
+
+	case 0:
+		/* Child */
+
+		/* wait for parent */
+		read(pfds[0], buf, 5);
+
+		fd =  shm_open(shared_name, O_RDWR, DEFFILEMODE);
+		if (fd == -1) {
+			perror("CHILD - shm_open(existing):");
+			exit(1);
+		} else {
+			ptest_data = mmap(0, sizeof(test_data), PROT_READ + PROT_WRITE, MAP_SHARED, fd, 0);
+			if (ptest_data != MAP_FAILED) {
+				for (i=0; i < ARRAY_SIZE(test_data); i++) {
+					if (ptest_data[i] != test_data[i]) {
+						printf("%-40s: Offset %d, local %d, shm %d\n", "Compare memory error", i, test_data[i], ptest_data[i]);
+						test_data_fails++;
+					}
+				}
+				if (test_data_fails == 0)
+					printf("%-40s: %s\n", "Compare memory", "Success");
+
+				munmap(ptest_data, sizeof(test_data));
+			}
+		}
+		exit(0);
+
+	default:
+		/* Parent */
+		fd = shm_open(shared_name, O_RDWR+O_CREAT+O_EXCL, DEFFILEMODE );
+		if (fd == -1) {
+			perror("PARENT - shm_open(create):");
+		} else {
+			if ((ftruncate(fd, sizeof(test_data))) == -1)
+			{
+				printf("%-40s: %s", "ftruncate", strerror(errno));
+				shm_unlink(shared_name);
+				return 0;
+			}
+
+			ptest_data = mmap(0, sizeof(test_data), PROT_READ + PROT_WRITE, MAP_SHARED, fd, 0);
+			if (ptest_data == MAP_FAILED)
+			{
+				perror("PARENT - mmap:");
+				if (shm_unlink(shared_name) == -1) {
+					perror("PARENT - shm_unlink:");
+				}
+				return 0;
+			}
+			for (i=0; i < ARRAY_SIZE(test_data); i++)
+				ptest_data[i] = test_data[i];
+
+			/* signal child */
+			write(pfds[1], "rdy", 5);
+			/* wait for child */
+			wait(&rv);
+
+			/* Cleanup */
+			munmap(ptest_data, sizeof(test_data));
+			if (shm_unlink(shared_name) == -1) {
+				perror("PARENT - shm_unlink:");
+			}
+		}
+	}
+	return 0;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/Makefile
new file mode 100644
index 00000000..771c3d11
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/Makefile
@@ -0,0 +1,7 @@
+# uClibc locale tests
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+
+top_builddir=../../
+include ../Rules.mak
+-include Makefile.in
+include ../Test.mak
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/Makefile.in
new file mode 100644
index 00000000..7c0e9d52
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/Makefile.in
@@ -0,0 +1,27 @@
+# uClibc locale tests
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+#	 tst_mbtowc tst_strcoll tst_strfmon tst_strxfrm    \
+
+TESTS := tst_iswalnum tst_iswalpha tst_iswcntrl          \
+	 tst_iswctype tst_iswdigit tst_iswgraph          \
+	 tst_iswlower tst_iswprint tst_iswpunct          \
+	 tst_iswspace tst_iswupper tst_iswxdigit         \
+	 tst_mblen tst_mbrlen tst_mbrtowc tst_mbsrtowcs  \
+	 tst_mbstowcs tst_mbtowc tst_strcoll tst_strxfrm \
+	 tst_swscanf tst_towctrans tst_towlower          \
+	 tst_towupper tst_wcrtomb tst_wcscat tst_wcschr  \
+	 tst_wcscmp tst_wcscoll tst_wcscpy tst_wcscspn   \
+	 tst_wcslen tst_wcsncat tst_wcsncmp tst_wcsncpy  \
+	 tst_wcspbrk tst_wcsrtombs tst_wcsspn tst_wcsstr \
+	 tst_wcstod tst_wcstok tst_wcstombs tst_wcswidth \
+	 tst_wcsxfrm tst_wctob tst_wctomb tst_wctrans    \
+	 tst_wctype tst_wcwidth tst_strfmon \
+	 tst2_mbrtowc
+
+# NOTE: For now disabled tst_strfmon to avoid build failure.
+TESTS_DISABLED := tst_strfmon
+
+DODIFF_rint     := 1
+
+EXTRA_CFLAGS    := -D__USE_GNU -fno-builtin
+
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_isw-funcs.h b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_isw-funcs.h
new file mode 100644
index 00000000..70aecb08
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_isw-funcs.h
@@ -0,0 +1,37 @@
+/*
+ *  TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY
+ *
+ *	 FILE:	dat_isw-funcs.h
+ *
+ *	 ISW*:	int isw* (wint_t wc);
+ */
+
+#include 
+#include 
+#include 
+#include "tst_types.h"
+#include "tgn_locdef.h"
+
+#define TST_ISW_LOC(FUNC, func) \
+	TST_ISW## FUNC	  tst_isw## func ##_loc []
+
+#define TST_ISW_REC(locale, func) \
+	{  Tisw## func,	   TST_LOC_## locale  },
+
+/*
+ *  NOTE:
+ *    Set ret_flg = 1, when a return value is expected to be 0 (FALSE).
+ *    Set ret_flg = 0, when a return value is expected to be non-zero (TRUE).
+ *
+ *    Since the functions return *non*-zero value for TRUE, can't
+ *    compare an actual return value with an expected return value.
+ *    Set the ret_flg=0 for TRUE cases and the tst_isw*() will check
+ *    the non-zero value.
+ *
+ *    { { WEOF }, { 0,1,0 } },
+ *		      | |
+ *		      | ret_val: an expected return value
+ *		      ret_flg: if 1, compare an actual return value with the
+ *			       ret_val; if 0, the test program
+ *			       checks the actual return value.
+ */
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_iswalnum.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_iswalnum.c
new file mode 100644
index 00000000..50937035
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_iswalnum.c
@@ -0,0 +1,196 @@
+/*
+ *  TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY
+ *
+ *	 FILE:	dat_iswalnum.c
+ *
+ *	 ISW*:	int iswalnum (wint_t wc);
+ */
+
+
+#include "dat_isw-funcs.h"
+
+
+TST_ISW_LOC (ALNUM, alnum) = {
+
+    {	TST_ISW_REC (de, alnum)
+	{
+	  {  { 0x0080 }, { 0,1,0 }  },  /* CTRL     */
+	  {  { 0x009F }, { 0,1,0 }  },  /* CTRL     */
+	  {  { 0x00A0 }, { 0,1,0 }  },  /* NB SPACE */
+	  {  { 0x00A1 }, { 0,1,0 }  },  /* UD !     */
+	  {  { 0x00B0 }, { 0,1,0 }  },  /* Degree   */
+	  {  { 0x00B1 }, { 0,1,0 }  },  /* +- sign  */
+	  {  { 0x00B2 }, { 0,1,0 }  },  /* SUP 2    */
+	  {  { 0x00B3 }, { 0,1,0 }  },  /* SUP 3    */
+	  {  { 0x00B4 }, { 0,1,0 }  },  /* ACUTE    */
+	  {  { 0x00B8 }, { 0,1,0 }  },  /* CEDILLA  */
+	  {  { 0x00B9 }, { 0,1,0 }  },  /* SUP 1    */
+	  {  { 0x00BB }, { 0,1,0 }  },  /* >>	      */
+	  {  { 0x00BC }, { 0,1,0 }  },  /* 1/4      */
+	  {  { 0x00BD }, { 0,1,0 }  },  /* 1/2      */
+	  {  { 0x00BE }, { 0,1,0 }  },  /* 3/4      */
+	  {  { 0x00BF }, { 0,1,0 }  },  /* UD ?     */
+	  {  { 0x00C0 }, { 0,0,0 }  },  /* A Grave  */
+	  {  { 0x00D6 }, { 0,0,0 }  },  /* O dia    */
+	  {  { 0x00D7 }, { 0,1,0 }  },  /* multipl. */
+	  {  { 0x00D8 }, { 0,0,0 }  },  /* O stroke */
+	  {  { 0x00DF }, { 0,0,0 }  },  /* small Sh */
+	  {  { 0x00E0 }, { 0,0,0 }  },  /* a grave  */
+	  {  { 0x00F6 }, { 0,0,0 }  },  /* o dia    */
+	  {  { 0x00F7 }, { 0,1,0 }  },  /* division */
+	  {  { 0x00F8 }, { 0,0,0 }  },  /* o stroke */
+	  {  { 0x00FF }, { 0,0,0 }  },  /* y dia    */
+	  {  .is_last = 1 }		  /* last element    */
+	}
+    },
+    {	TST_ISW_REC (de_UTF8, alnum)
+	{
+	  {  { 0x0080 }, { 0,1,0 }  },  /* CTRL     */
+	  {  { 0x009F }, { 0,1,0 }  },  /* CTRL     */
+	  {  { 0x00A0 }, { 0,1,0 }  },  /* NB SPACE */
+	  {  { 0x00A1 }, { 0,1,0 }  },  /* UD !     */
+	  {  { 0x00B0 }, { 0,1,0 }  },  /* Degree   */
+	  {  { 0x00B1 }, { 0,1,0 }  },  /* +- sign  */
+	  {  { 0x00B2 }, { 0,1,0 }  },  /* SUP 2    */
+	  {  { 0x00B3 }, { 0,1,0 }  },  /* SUP 3    */
+	  {  { 0x00B4 }, { 0,1,0 }  },  /* ACUTE    */
+	  {  { 0x00B8 }, { 0,1,0 }  },  /* CEDILLA  */
+	  {  { 0x00B9 }, { 0,1,0 }  },  /* SUP 1    */
+	  {  { 0x00BB }, { 0,1,0 }  },  /* >>	      */
+	  {  { 0x00BC }, { 0,1,0 }  },  /* 1/4      */
+	  {  { 0x00BD }, { 0,1,0 }  },  /* 1/2      */
+	  {  { 0x00BE }, { 0,1,0 }  },  /* 3/4      */
+	  {  { 0x00BF }, { 0,1,0 }  },  /* UD ?     */
+	  {  { 0x00C0 }, { 0,0,0 }  },  /* A Grave  */
+	  {  { 0x00D6 }, { 0,0,0 }  },  /* O dia    */
+	  {  { 0x00D7 }, { 0,1,0 }  },  /* multipl. */
+	  {  { 0x00D8 }, { 0,0,0 }  },  /* O stroke */
+	  {  { 0x00DF }, { 0,0,0 }  },  /* small Sh */
+	  {  { 0x00E0 }, { 0,0,0 }  },  /* a grave  */
+	  {  { 0x00F6 }, { 0,0,0 }  },  /* o dia    */
+	  {  { 0x00F7 }, { 0,1,0 }  },  /* division */
+	  {  { 0x00F8 }, { 0,0,0 }  },  /* o stroke */
+	  {  { 0x00FF }, { 0,0,0 }  },  /* y dia    */
+	  {  .is_last = 1 }		  /* last element    */
+	}
+    },
+    {	TST_ISW_REC (enUS, alnum)
+	{
+	  {  { WEOF   }, { 0,1,0 }  },
+	  {  { 0x0000 }, { 0,1,0 }  },
+	  {  { 0x001F }, { 0,1,0 }  },
+	  {  { 0x0020 }, { 0,1,0 }  },
+	  {  { 0x0021 }, { 0,1,0 }  },
+	  {  { 0x002F }, { 0,1,0 }  },
+	  {  { 0x0030 }, { 0,0,0 }  },
+	  {  { 0x0039 }, { 0,0,0 }  },
+	  {  { 0x003A }, { 0,1,0 }  },
+	  {  { 0x0040 }, { 0,1,0 }  },
+	  {  { 0x0041 }, { 0,0,0 }  },
+	  {  { 0x005A }, { 0,0,0 }  },
+	  {  { 0x005B }, { 0,1,0 }  },
+	  {  { 0x0060 }, { 0,1,0 }  },
+	  {  { 0x0061 }, { 0,0,0 }  },
+	  {  { 0x007A }, { 0,0,0 }  },
+	  {  { 0x007B }, { 0,1,0 }  },
+	  {  { 0x007E }, { 0,1,0 }  },
+	  {  { 0x007F }, { 0,1,0 }  },
+	  {  { 0x0080 }, { 0,1,0 }  },
+	  {  .is_last = 1 }		  /* last element    */
+	}
+    },
+#if 0
+    {	TST_ISW_REC (eucJP, alnum)
+#else
+    {	TST_ISW_REC (ja_UTF8, alnum)
+#endif
+	{
+	  {  { 0x3000 }, { 0,1,0 }  },  /* IDEO. SPACE	*/
+	  {  { 0x3020 }, { 0,1,0 }  },  /* POSTAL MARK FACE	*/
+#ifdef SHOJI_IS_RIGHT
+	  {  { 0x3029 }, { 0,1,0 }  },  /* Hangzhou NUM9	*/
+#else
+	  {  { 0x3029 }, { 0,0,0 }  },  /* Hangzhou NUM9	*/
+#endif
+	  {  { 0x302F }, { 0,1,0 }  },  /* Diacritics(Hangul) */
+	  {  { 0x3037 }, { 0,1,0 }  },  /* Separator Symbol	*/
+	  {  { 0x303F }, { 0,1,0 }  },  /* IDEO. HALF SPACE	*/
+#ifdef SHOJI_IS_RIGHT
+	  {  { 0x3041 }, { 0,1,0 }  },  /* HIRAGANA a		*/
+	  {  { 0x3094 }, { 0,1,0 }  },  /* HIRAGANA u"		*/
+#else
+	  {  { 0x3041 }, { 0,0,0 }  },  /* HIRAGANA a		*/
+	  {  { 0x3094 }, { 0,0,0 }  },  /* HIRAGANA u"		*/
+#endif
+	  {  { 0x3099 }, { 0,1,0 }  },  /* SOUND MARK		*/
+#ifdef SHOJI_IS_RIGHT
+	  {  { 0x309E }, { 0,1,0 }  },  /* ITERATION MARK	*/
+	  {  { 0x30A1 }, { 0,1,0 }  },  /* KATAKANA a		*/
+	  {  { 0x30FA }, { 0,1,0 }  },  /* KATAKANA wo"	*/
+#else
+	  {  { 0x309E }, { 0,0,0 }  },  /* ITERATION MARK	*/
+	  {  { 0x30A1 }, { 0,0,0 }  },  /* KATAKANA a		*/
+	  {  { 0x30FA }, { 0,0,0 }  },  /* KATAKANA wo"	*/
+#endif
+	  {  { 0x30FB }, { 0,1,0 }  },  /* KATAKANA MID.DOT	*/
+#ifdef SHOJI_IS_RIGHT
+	  {  { 0x30FE }, { 0,1,0 }  },  /* KATAKANA ITERATION	*/
+#else
+	  {  { 0x30FE }, { 0,0,0 }  },  /* KATAKANA ITERATION	*/
+#endif
+	  {  { 0x3191 }, { 0,1,0 }  },  /* KANBUN REV.MARK	*/
+	  {  { 0x3243 }, { 0,1,0 }  },  /* IDEO. MARK (reach) */
+	  {  { 0x32CB }, { 0,1,0 }  },  /* IDEO.TEL.SYM.DEC12 */
+	  {  { 0x32FE }, { 0,1,0 }  },  /* MARU KATAKANA wo	*/
+	  {  { 0x33FE }, { 0,1,0 }  },  /* CJK IDEO.TEL.31th	*/
+#ifdef SHOJI_IS_RIGHT
+	  {  { 0x4E00 }, { 0,1,0 }  },  /* CJK UNI.IDEO.	*/
+	  {  { 0x4E05 }, { 0,1,0 }  },  /* CJK UNI.IDEO.	*/
+	  {  { 0x4E06 }, { 0,1,0 }  },  /* CJK UNI.IDEO.NON-J	*/
+	  {  { 0x4E07 }, { 0,1,0 }  },  /* CJK UNI.IDEO.	*/
+	  {  { 0x4FFF }, { 0,1,0 }  },  /* CJK UNI.IDEO.	*/
+	  {  { 0x9000 }, { 0,1,0 }  },  /* CJK UNI.IDEO.	*/
+	  {  { 0x9006 }, { 0,1,0 }  },  /* CJK UNI.IDEO.	*/
+	  {  { 0x9007 }, { 0,1,0 }  },  /* CJK UNI.IDEO.NON-J	*/
+	  {  { 0x9FA4 }, { 0,1,0 }  },  /* CJK UNI.IDEO.NON-J	*/
+	  {  { 0x9FA5 }, { 0,1,0 }  },  /* CJK UNI.IDEO.	*/
+#else
+	  {  { 0x4E00 }, { 0,0,0 }  },  /* CJK UNI.IDEO.	*/
+	  {  { 0x4E05 }, { 0,0,0 }  },  /* CJK UNI.IDEO.	*/
+	  {  { 0x4E06 }, { 0,0,0 }  },  /* CJK UNI.IDEO.NON-J	*/
+	  {  { 0x4E07 }, { 0,0,0 }  },  /* CJK UNI.IDEO.	*/
+	  {  { 0x4FFF }, { 0,0,0 }  },  /* CJK UNI.IDEO.	*/
+	  {  { 0x9000 }, { 0,0,0 }  },  /* CJK UNI.IDEO.	*/
+	  {  { 0x9006 }, { 0,0,0 }  },  /* CJK UNI.IDEO.	*/
+	  {  { 0x9007 }, { 0,0,0 }  },  /* CJK UNI.IDEO.NON-J	*/
+	  {  { 0x9FA4 }, { 0,0,0 }  },  /* CJK UNI.IDEO.NON-J	*/
+	  {  { 0x9FA5 }, { 0,0,0 }  },  /* CJK UNI.IDEO.	*/
+#endif
+	  {  { 0xFE4F }, { 0,1,0 }  },  /* CJK UNI.IDEO.	*/
+	  {  { 0xFF0F }, { 0,1,0 }  },  /* FULL SLASH		*/
+	  {  { 0xFF19 }, { 0,0,0 }  },  /* FULL 9		*/
+	  {  { 0xFF20 }, { 0,1,0 }  },  /* FULL @		*/
+	  {  { 0xFF3A }, { 0,0,0 }  },  /* FULL Z		*/
+	  {  { 0xFF40 }, { 0,1,0 }  },  /* FULL GRAVE ACC.	*/
+	  {  { 0xFF5A }, { 0,0,0 }  },  /* FULL z		*/
+	  {  { 0xFF5E }, { 0,1,0 }  },  /* FULL ~ (tilde)	*/
+	  {  { 0xFF61 }, { 0,1,0 }  },  /* HALF IDEO.STOP. .	*/
+	  {  { 0xFF65 }, { 0,1,0 }  },  /* HALF KATA MID.DOT	*/
+#ifdef SHOJI_IS_RIGHT
+	  {  { 0xFF66 }, { 0,1,0 }  },  /* HALF KATA WO		*/
+	  {  { 0xFF6F }, { 0,1,0 }  },  /* HALF KATA tu		*/
+	  {  { 0xFF70 }, { 0,1,0 }  },  /* HALF KATA PL -	*/
+	  {  { 0xFF71 }, { 0,1,0 }  },  /* HALF KATA A		*/
+	  {  { 0xFF9E }, { 0,1,0 }  },  /* HALF KATA MI		*/
+#else
+	  {  { 0xFF66 }, { 0,0,0 }  },  /* HALF KATA WO		*/
+	  {  { 0xFF6F }, { 0,0,0 }  },  /* HALF KATA tu		*/
+	  {  { 0xFF70 }, { 0,0,0 }  },  /* HALF KATA PL -	*/
+	  {  { 0xFF71 }, { 0,0,0 }  },  /* HALF KATA A		*/
+	  {  { 0xFF9E }, { 0,0,0 }  },  /* HALF KATA MI		*/
+#endif
+	  {  .is_last = 1 }		  /* last element    */
+	}
+    },
+    {	TST_ISW_REC (end, alnum) }
+};
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_iswalpha.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_iswalpha.c
new file mode 100644
index 00000000..c2b59fbf
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_iswalpha.c
@@ -0,0 +1,169 @@
+/*
+ *  TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY
+ *
+ *	 FILE:	dat_iswalpha.c
+ *
+ *	 ISW*:	int iswalpha (wint_t wc);
+ */
+
+
+#include "dat_isw-funcs.h"
+
+
+TST_ISW_LOC (ALPHA, alpha)  = {
+
+    {	TST_ISW_REC (de, alpha)
+	{
+	  {  { 0x0080 }, { 0,1,0 }  },  /* CTRL     */
+	  {  { 0x009F }, { 0,1,0 }  },  /* CTRL     */
+	  {  { 0x00A0 }, { 0,1,0 }  },  /* NB SPACE */
+	  {  { 0x00A1 }, { 0,1,0 }  },  /* UD !     */
+	  {  { 0x00B0 }, { 0,1,0 }  },  /* Degree   */
+	  {  { 0x00B1 }, { 0,1,0 }  },  /* +- sign  */
+	  {  { 0x00B2 }, { 0,1,0 }  },  /* SUP 2    */
+	  {  { 0x00B3 }, { 0,1,0 }  },  /* SUP 3    */
+	  {  { 0x00B4 }, { 0,1,0 }  },  /* ACUTE    */
+	  {  { 0x00B8 }, { 0,1,0 }  },  /* CEDILLA  */
+	  {  { 0x00B9 }, { 0,1,0 }  },  /* SUP 1    */
+	  {  { 0x00BB }, { 0,1,0 }  },  /* >>	      */
+	  {  { 0x00BC }, { 0,1,0 }  },  /* 1/4      */
+	  {  { 0x00BD }, { 0,1,0 }  },  /* 1/2      */
+	  {  { 0x00BE }, { 0,1,0 }  },  /* 3/4      */
+	  {  { 0x00BF }, { 0,1,0 }  },  /* UD ?     */
+	  {  { 0x00C0 }, { 0,0,0 }  },  /* A Grave  */
+	  {  { 0x00D6 }, { 0,0,0 }  },  /* O dia    */
+	  {  { 0x00D7 }, { 0,1,0 }  },  /* multipl. */
+	  {  { 0x00D8 }, { 0,0,0 }  },  /* O stroke */
+	  {  { 0x00DF }, { 0,0,0 }  },  /* small Sh */
+	  {  { 0x00E0 }, { 0,0,0 }  },  /* a grave  */
+	  {  { 0x00F6 }, { 0,0,0 }  },  /* o dia    */
+	  {  { 0x00F7 }, { 0,1,0 }  },  /* division */
+	  {  { 0x00F8 }, { 0,0,0 }  },  /* o stroke */
+	  {  { 0x00FF }, { 0,0,0 }  },  /* y dia    */
+	  {  .is_last = 1 }		  /* last element    */
+	}
+    },
+    {	TST_ISW_REC (enUS, alpha)
+	{
+	  {  { WEOF   }, { 0,1,0 }  },
+	  {  { 0x0000 }, { 0,1,0 }  },
+	  {  { 0x001F }, { 0,1,0 }  },
+	  {  { 0x0020 }, { 0,1,0 }  },
+	  {  { 0x0021 }, { 0,1,0 }  },
+	  {  { 0x002F }, { 0,1,0 }  },
+	  {  { 0x0030 }, { 0,1,0 }  },
+	  {  { 0x0039 }, { 0,1,0 }  },
+	  {  { 0x003A }, { 0,1,0 }  },
+	  {  { 0x0040 }, { 0,1,0 }  },
+	  {  { 0x0041 }, { 0,0,0 }  },
+	  {  { 0x005A }, { 0,0,0 }  },
+	  {  { 0x005B }, { 0,1,0 }  },
+	  {  { 0x0060 }, { 0,1,0 }  },
+	  {  { 0x0061 }, { 0,0,0 }  },
+	  {  { 0x007A }, { 0,0,0 }  },
+	  {  { 0x007B }, { 0,1,0 }  },
+	  {  { 0x007E }, { 0,1,0 }  },
+	  {  { 0x007F }, { 0,1,0 }  },
+	  {  { 0x0080 }, { 0,1,0 }  },  /* 20 */
+	  {  .is_last = 1 }		  /* last element    */
+	}
+    },
+#if 0
+    {	TST_ISW_REC (eucJP, alpha)
+#else
+    {	TST_ISW_REC (ja_UTF8, alpha)
+#endif
+	{
+	  {  { 0x3000 }, { 0,1,0 }  },  /* IDEO. SPACE	*/
+	  {  { 0x3020 }, { 0,1,0 }  },  /* POSTAL MARK FACE	*/
+#ifdef SHOJI_IS_RIGHT
+	  {  { 0x3029 }, { 0,1,0 }  },  /* Hangzhou NUM9	*/
+#else
+	  {  { 0x3029 }, { 0,0,0 }  },  /* Hangzhou NUM9	*/
+#endif
+	  {  { 0x302F }, { 0,1,0 }  },  /* Diacritics(Hangul) */
+	  {  { 0x3037 }, { 0,1,0 }  },  /* Separator Symbol	*/
+	  {  { 0x303F }, { 0,1,0 }  },  /* IDEO. HALF SPACE	*/
+#ifdef SHOJI_IS_RIGHT
+	  {  { 0x3041 }, { 0,1,0 }  },  /* HIRAGANA a		*/
+	  {  { 0x3094 }, { 0,1,0 }  },  /* HIRAGANA u"		*/
+#else
+	  {  { 0x3041 }, { 0,0,0 }  },  /* HIRAGANA a		*/
+	  {  { 0x3094 }, { 0,0,0 }  },  /* HIRAGANA u"		*/
+#endif
+	  {  { 0x3099 }, { 0,1,0 }  },  /* SOUND MARK		*/
+#ifdef SHOJI_IS_RIGHT
+	  {  { 0x309E }, { 0,1,0 }  },  /* ITERATION MARK	*/
+	  {  { 0x30A1 }, { 0,1,0 }  },  /* KATAKANA a		*/
+	  {  { 0x30FA }, { 0,1,0 }  },  /* KATAKANA wo"		*/
+#else
+	  {  { 0x309E }, { 0,0,0 }  },  /* ITERATION MARK	*/
+	  {  { 0x30A1 }, { 0,0,0 }  },  /* KATAKANA a		*/
+	  {  { 0x30FA }, { 0,0,0 }  },  /* KATAKANA wo"		*/
+#endif
+	  {  { 0x30FB }, { 0,1,0 }  },  /* KATAKANA MID.DOT	*/
+#ifdef SHOJI_IS_RIGHT
+	  {  { 0x30FE }, { 0,1,0 }  },  /* KATAKANA ITERATION	*/
+#else
+	  {  { 0x30FE }, { 0,0,0 }  },  /* KATAKANA ITERATION	*/
+#endif
+	  {  { 0x3191 }, { 0,1,0 }  },  /* KANBUN REV.MARK	*/
+	  {  { 0x3243 }, { 0,1,0 }  },  /* IDEO. MARK (reach) */
+	  {  { 0x32CB }, { 0,1,0 }  },  /* IDEO.TEL.SYM.DEC12 */
+	  {  { 0x32FE }, { 0,1,0 }  },  /* MARU KATAKANA wo	*/
+	  {  { 0x33FE }, { 0,1,0 }  },  /* CJK IDEO.TEL.31th	*/
+#ifdef SHOJI_IS_RIGHT
+	  {  { 0x4E00 }, { 0,1,0 }  },  /* CJK UNI.IDEO.	*/
+	  {  { 0x4E05 }, { 0,1,0 }  },  /* CJK UNI.IDEO.	*/
+	  {  { 0x4E06 }, { 0,1,0 }  },  /* CJK UNI.IDEO.NON-J	*/
+	  {  { 0x4E07 }, { 0,1,0 }  },  /* CJK UNI.IDEO.	*/
+	  {  { 0x4FFF }, { 0,1,0 }  },  /* CJK UNI.IDEO.	*/
+	  {  { 0x9000 }, { 0,1,0 }  },  /* CJK UNI.IDEO.	*/
+	  {  { 0x9006 }, { 0,1,0 }  },  /* CJK UNI.IDEO.	*/
+	  {  { 0x9007 }, { 0,1,0 }  },  /* CJK UNI.IDEO.NON-J	*/
+	  {  { 0x9FA4 }, { 0,1,0 }  },  /* CJK UNI.IDEO.NON-J	*/
+	  {  { 0x9FA5 }, { 0,1,0 }  },  /* CJK UNI.IDEO.	*/
+#else
+	  {  { 0x4E00 }, { 0,0,0 }  },  /* CJK UNI.IDEO.	*/
+	  {  { 0x4E05 }, { 0,0,0 }  },  /* CJK UNI.IDEO.	*/
+	  {  { 0x4E06 }, { 0,0,0 }  },  /* CJK UNI.IDEO.NON-J	*/
+	  {  { 0x4E07 }, { 0,0,0 }  },  /* CJK UNI.IDEO.	*/
+	  {  { 0x4FFF }, { 0,0,0 }  },  /* CJK UNI.IDEO.	*/
+	  {  { 0x9000 }, { 0,0,0 }  },  /* CJK UNI.IDEO.	*/
+	  {  { 0x9006 }, { 0,0,0 }  },  /* CJK UNI.IDEO.	*/
+	  {  { 0x9007 }, { 0,0,0 }  },  /* CJK UNI.IDEO.NON-J	*/
+	  {  { 0x9FA4 }, { 0,0,0 }  },  /* CJK UNI.IDEO.NON-J	*/
+	  {  { 0x9FA5 }, { 0,0,0 }  },  /* CJK UNI.IDEO.	*/
+#endif
+	  {  { 0xFE4F }, { 0,1,0 }  },  /* CJK UNI.IDEO.	*/
+	  {  { 0xFF0F }, { 0,1,0 }  },  /* FULL SLASH		*/
+#ifdef SHOJI_IS_RIGHT
+	  {  { 0xFF19 }, { 0,1,0 }  },  /* FULL 9		*/
+#else
+	  {  { 0xFF19 }, { 0,0,0 }  },  /* FULL 9		*/
+#endif
+	  {  { 0xFF20 }, { 0,1,0 }  },  /* FULL @		*/
+	  {  { 0xFF3A }, { 0,0,0 }  },  /* FULL Z		*/
+	  {  { 0xFF40 }, { 0,1,0 }  },  /* FULL GRAVE ACC.	*/
+	  {  { 0xFF5A }, { 0,0,0 }  },  /* FULL z		*/
+	  {  { 0xFF5E }, { 0,1,0 }  },  /* FULL ~ (tilde)	*/
+	  {  { 0xFF61 }, { 0,1,0 }  },  /* HALF IDEO.STOP. .	*/
+	  {  { 0xFF65 }, { 0,1,0 }  },  /* HALF KATA MID.DOT	*/
+#ifdef SHOJI_IS_RIGHT
+	  {  { 0xFF66 }, { 0,1,0 }  },  /* HALF KATA WO		*/
+	  {  { 0xFF6F }, { 0,1,0 }  },  /* HALF KATA tu		*/
+	  {  { 0xFF70 }, { 0,1,0 }  },  /* HALF KATA PL -	*/
+	  {  { 0xFF71 }, { 0,1,0 }  },  /* HALF KATA A		*/
+	  {  { 0xFF9E }, { 0,1,0 }  },  /* HALF KATA MI		*/
+#else
+	  {  { 0xFF66 }, { 0,0,0 }  },  /* HALF KATA WO		*/
+	  {  { 0xFF6F }, { 0,0,0 }  },  /* HALF KATA tu		*/
+	  {  { 0xFF70 }, { 0,0,0 }  },  /* HALF KATA PL -	*/
+	  {  { 0xFF71 }, { 0,0,0 }  },  /* HALF KATA A		*/
+	  {  { 0xFF9E }, { 0,0,0 }  },  /* HALF KATA MI		*/
+#endif
+	  {  .is_last = 1 }		  /* last element    */
+	}
+    },
+    {	TST_ISW_REC (end, alpha) }
+};
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_iswcntrl.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_iswcntrl.c
new file mode 100644
index 00000000..e6ec685e
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_iswcntrl.c
@@ -0,0 +1,125 @@
+/*
+ *  TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY
+ *
+ *	 FILE:	dat_iswcntrl.c
+ *
+ *	 ISW*:	int iswcntrl (wint_t wc);
+ */
+
+
+#include "dat_isw-funcs.h"
+
+
+TST_ISW_LOC (CNTRL, cntrl) = {
+
+    {	TST_ISW_REC (de, cntrl)
+	{
+	  {  { 0x0080 }, { 0,0,0 }  },  /* CTRL     */
+	  {  { 0x009F }, { 0,0,0 }  },  /* CTRL     */
+	  {  { 0x00A0 }, { 0,1,0 }  },  /* NB SPACE */
+	  {  { 0x00A1 }, { 0,1,0 }  },  /* UD !     */
+	  {  { 0x00B0 }, { 0,1,0 }  },  /* Degree   */
+	  {  { 0x00B1 }, { 0,1,0 }  },  /* +- sign  */
+	  {  { 0x00B2 }, { 0,1,0 }  },  /* SUP 2    */
+	  {  { 0x00B3 }, { 0,1,0 }  },  /* SUP 3    */
+	  {  { 0x00B4 }, { 0,1,0 }  },  /* ACUTE    */
+	  {  { 0x00B8 }, { 0,1,0 }  },  /* CEDILLA  */
+	  {  { 0x00B9 }, { 0,1,0 }  },  /* SUP 1    */
+	  {  { 0x00BB }, { 0,1,0 }  },  /* >>	      */
+	  {  { 0x00BC }, { 0,1,0 }  },  /* 1/4      */
+	  {  { 0x00BD }, { 0,1,0 }  },  /* 1/2      */
+	  {  { 0x00BE }, { 0,1,0 }  },  /* 3/4      */
+	  {  { 0x00BF }, { 0,1,0 }  },  /* UD ?     */
+	  {  { 0x00C0 }, { 0,1,0 }  },  /* A Grave  */
+	  {  { 0x00D6 }, { 0,1,0 }  },  /* O dia    */
+	  {  { 0x00D7 }, { 0,1,0 }  },  /* multipl. */
+	  {  { 0x00D8 }, { 0,1,0 }  },  /* O stroke */
+	  {  { 0x00DF }, { 0,1,0 }  },  /* small Sh */
+	  {  { 0x00E0 }, { 0,1,0 }  },  /* a grave  */
+	  {  { 0x00F6 }, { 0,1,0 }  },  /* o dia    */
+	  {  { 0x00F7 }, { 0,1,0 }  },  /* division */
+	  {  { 0x00F8 }, { 0,1,0 }  },  /* o stroke */
+	  {  { 0x00FF }, { 0,1,0 }  },  /* y dia    */
+	  { .is_last = 1 }		  /* Last element.  */
+	}
+    },
+    {	TST_ISW_REC (enUS, cntrl)
+	{
+	  {  { WEOF   }, { 0,1,0 }  },
+	  {  { 0x0000 }, { 0,0,0 }  },
+	  {  { 0x001F }, { 0,0,0 }  },
+	  {  { 0x0020 }, { 0,1,0 }  },
+	  {  { 0x0021 }, { 0,1,0 }  },
+	  {  { 0x002F }, { 0,1,0 }  },
+	  {  { 0x0030 }, { 0,1,0 }  },
+	  {  { 0x0039 }, { 0,1,0 }  },
+	  {  { 0x003A }, { 0,1,0 }  },
+	  {  { 0x0040 }, { 0,1,0 }  },
+	  {  { 0x0041 }, { 0,1,0 }  },
+	  {  { 0x005A }, { 0,1,0 }  },
+	  {  { 0x005B }, { 0,1,0 }  },
+	  {  { 0x0060 }, { 0,1,0 }  },
+	  {  { 0x0061 }, { 0,1,0 }  },
+	  {  { 0x007A }, { 0,1,0 }  },
+	  {  { 0x007B }, { 0,1,0 }  },
+	  {  { 0x007E }, { 0,1,0 }  },
+	  {  { 0x007F }, { 0,0,0 }  },
+	  {  { 0x0080 }, { 0,1,0 }  },
+	  { .is_last = 1 }		  /* Last element.  */
+	}
+    },
+#if 0
+    {	TST_ISW_REC (eucJP, cntrl)
+#else
+    {	TST_ISW_REC (ja_UTF8, cntrl)
+#endif
+	{
+	  {  { 0x3000 }, { 0,1,0 }  },  /* IDEO. SPACE	*/
+	  {  { 0x3020 }, { 0,1,0 }  },  /* POSTAL MARK FACE	*/
+	  {  { 0x3029 }, { 0,1,0 }  },  /* Hangzhou NUM9	*/
+	  {  { 0x302F }, { 0,1,0 }  },  /* Diacritics(Hangul) */
+	  {  { 0x3037 }, { 0,1,0 }  },  /* Separator Symbol	*/
+	  {  { 0x303F }, { 0,1,0 }  },  /* IDEO. HALF SPACE	*/
+	  {  { 0x3041 }, { 0,1,0 }  },  /* HIRAGANA a		*/
+	  {  { 0x3094 }, { 0,1,0 }  },  /* HIRAGANA u"	*/
+	  {  { 0x3099 }, { 0,1,0 }  },  /* SOUND MARK		*/
+	  {  { 0x309E }, { 0,1,0 }  },  /* ITERATION MARK	*/
+	  {  { 0x30A1 }, { 0,1,0 }  },  /* KATAKANA a		*/
+	  {  { 0x30FA }, { 0,1,0 }  },  /* KATAKANA wo"	*/
+	  {  { 0x30FB }, { 0,1,0 }  },  /* KATAKANA MID.DOT	*/
+	  {  { 0x30FE }, { 0,1,0 }  },  /* KATAKANA ITERATION */
+	  {  { 0x3191 }, { 0,1,0 }  },  /* KANBUN REV.MARK	*/
+	  {  { 0x3243 }, { 0,1,0 }  },  /* IDEO. MARK (reach) */
+	  {  { 0x32CB }, { 0,1,0 }  },  /* IDEO.TEL.SYM.DEC12 */
+	  {  { 0x32FE }, { 0,1,0 }  },  /* MARU KATAKANA wo	*/
+	  {  { 0x33FE }, { 0,1,0 }  },  /* CJK IDEO.TEL.31th	*/
+	  {  { 0x4E00 }, { 0,1,0 }  },  /* CJK UNI.IDEO.	*/
+	  {  { 0x4E05 }, { 0,1,0 }  },  /* CJK UNI.IDEO.	*/
+	  {  { 0x4E06 }, { 0,1,0 }  },  /* CJK UNI.IDEO.NON-J */
+	  {  { 0x4E07 }, { 0,1,0 }  },  /* CJK UNI.IDEO.	*/
+	  {  { 0x4FFF }, { 0,1,0 }  },  /* CJK UNI.IDEO.	*/
+	  {  { 0x9000 }, { 0,1,0 }  },  /* CJK UNI.IDEO.	*/
+	  {  { 0x9006 }, { 0,1,0 }  },  /* CJK UNI.IDEO.	*/
+	  {  { 0x9007 }, { 0,1,0 }  },  /* CJK UNI.IDEO.NON-J */
+	  {  { 0x9FA4 }, { 0,1,0 }  },  /* CJK UNI.IDEO.NON-J */
+	  {  { 0x9FA5 }, { 0,1,0 }  },  /* CJK UNI.IDEO.	*/
+	  {  { 0xFE4F }, { 0,1,0 }  },  /* CJK UNI.IDEO.	*/
+	  {  { 0xFF0F }, { 0,1,0 }  },  /* FULL SLASH		*/
+	  {  { 0xFF19 }, { 0,1,0 }  },  /* FULL 9		*/
+	  {  { 0xFF20 }, { 0,1,0 }  },  /* FULL @		*/
+	  {  { 0xFF3A }, { 0,1,0 }  },  /* FULL Z		*/
+	  {  { 0xFF40 }, { 0,1,0 }  },  /* FULL GRAVE ACC.	*/
+	  {  { 0xFF5A }, { 0,1,0 }  },  /* FULL z		*/
+	  {  { 0xFF5E }, { 0,1,0 }  },  /* FULL ~ (tilde)	*/
+	  {  { 0xFF61 }, { 0,1,0 }  },  /* HALF IDEO.STOP. .	*/
+	  {  { 0xFF65 }, { 0,1,0 }  },  /* HALF KATA MID.DOT	*/
+	  {  { 0xFF66 }, { 0,1,0 }  },  /* HALF KATA WO	*/
+	  {  { 0xFF6F }, { 0,1,0 }  },  /* HALF KATA tu	*/
+	  {  { 0xFF70 }, { 0,1,0 }  },  /* HALF KATA PL -	*/
+	  {  { 0xFF71 }, { 0,1,0 }  },  /* HALF KATA A	*/
+	  {  { 0xFF9E }, { 0,1,0 }  },  /* HALF KATA MI	*/
+	  { .is_last = 1 }		  /* Last element.  */
+	}
+    },
+    {	TST_ISW_REC(end, cntrl) }
+};
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_iswctype.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_iswctype.c
new file mode 100644
index 00000000..0dcf1824
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_iswctype.c
@@ -0,0 +1,667 @@
+/*
+ *  TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY
+ *
+ *	 FILE:	dat_iswctype.c
+ *
+ *	 ISWCTYPE:  int iswctype( wint_t wc, wctype_t charclass );
+ */
+
+#include 
+#include 
+#include 
+#include "tst_types.h"
+#include "tgn_locdef.h"
+
+/*
+ *  NOTE:
+ *   Set ret_flg = 1, when a return value is expected to be 0 (FALSE).
+ *   Set ret_flg = 0, when a return value is expected to be non-zero (TRUE).
+ *
+ *   Since the functions return *non*-zero value for TRUE, can't
+ *   compare an actual return value with an expected return value.
+ *   Set the ret_flg=0 for TRUE cases and the tst_isw*() will check
+ *   the non-zero value.
+ *
+ * { { WEOF }, { 0,1,0 } },
+ *		   | |
+ *		   | ret_val: an expected return value
+ *		   ret_flg: if 1, compare an actual return value with the
+ *			    ret_val; if 0, the test program checks
+ *			    the actual return value.
+ */
+
+TST_ISWCTYPE tst_iswctype_loc [] = {
+  {
+    { Tiswctype, TST_LOC_de },
+    {
+      {	 { 0x009F, "alnum"  }, { 0,1,0 }  },	   /* CTRL     */
+      {	 { 0x00A0, "alnum"  }, { 0,1,0 }  },	   /* NB SPACE */
+      {	 { 0x00A1, "alnum"  }, { 0,1,0 }  },	   /* UD !     */
+      {	 { 0x00B1, "alnum"  }, { 0,1,0 }  },	   /* +- sign  */
+      {	 { 0x00B3, "alnum"  }, { 0,1,0 }  },	   /* SUP 3    */
+      {	 { 0x00B4, "alnum"  }, { 0,1,0 }  },	   /* ACUTE    */
+      {	 { 0x00BB, "alnum"  }, { 0,1,0 }  },	   /* >>       */
+      {	 { 0x00BE, "alnum"  }, { 0,1,0 }  },	   /* 3/4      */
+      {	 { 0x00BF, "alnum"  }, { 0,1,0 }  },	   /* UD ?     */
+      {	 { 0x00C0, "alnum"  }, { 0,0,0 }  },	   /* A Grave  */
+      {	 { 0x00D6, "alnum"  }, { 0,0,0 }  },	   /* O dia    */
+      {	 { 0x00D7, "alnum"  }, { 0,1,0 }  },	   /* multipl. */
+      {	 { 0x00D8, "alnum"  }, { 0,0,0 }  },	   /* O stroke */
+      {	 { 0x00DF, "alnum"  }, { 0,0,0 }  },	   /* small Sh */
+      {	 { 0x00E0, "alnum"  }, { 0,0,0 }  },	   /* a grave  */
+      {	 { 0x00F6, "alnum"  }, { 0,0,0 }  },	   /* o dia    */
+      {	 { 0x00F7, "alnum"  }, { 0,1,0 }  },	   /* division */
+      {	 { 0x00F8, "alnum"  }, { 0,0,0 }  },	   /* o stroke */
+      {	 { 0x00FF, "alnum"  }, { 0,0,0 }  },	   /* y dia    */
+      {	 { 0x0080, "alpha"  }, { 0,1,0 }  },	   /* CTRL     */
+      {	 { 0x00A0, "alpha"  }, { 0,1,0 }  },	   /* NB SPACE */
+      {	 { 0x00A1, "alpha"  }, { 0,1,0 }  },	   /* UD !     */
+      {	 { 0x00B1, "alpha"  }, { 0,1,0 }  },	   /* +- sign  */
+      {	 { 0x00B4, "alpha"  }, { 0,1,0 }  },	   /* ACUTE    */
+      {	 { 0x00B8, "alpha"  }, { 0,1,0 }  },	   /* CEDILLA  */
+      {	 { 0x00B9, "alpha"  }, { 0,1,0 }  },	   /* SUP 1    */
+      {	 { 0x00BB, "alpha"  }, { 0,1,0 }  },	   /* >>       */
+      {	 { 0x00BE, "alpha"  }, { 0,1,0 }  },	   /* 3/4      */
+      {	 { 0x00BF, "alpha"  }, { 0,1,0 }  },	   /* UD ?     */
+      {	 { 0x00C0, "alpha"  }, { 0,0,0 }  },	   /* A Grave  */
+      {	 { 0x00D6, "alpha"  }, { 0,0,0 }  },	   /* O dia    */
+      {	 { 0x00D7, "alpha"  }, { 0,1,0 }  },	   /* multipl. */
+      {	 { 0x00D8, "alpha"  }, { 0,0,0 }  },	   /* O stroke */
+      {	 { 0x00DF, "alpha"  }, { 0,0,0 }  },	   /* small Sh */
+      {	 { 0x00E0, "alpha"  }, { 0,0,0 }  },	   /* a grave  */
+      {	 { 0x00F6, "alpha"  }, { 0,0,0 }  },	   /* o dia    */
+      {	 { 0x00F7, "alpha"  }, { 0,1,0 }  },	   /* division */
+      {	 { 0x00F8, "alpha"  }, { 0,0,0 }  },	   /* o stroke */
+      {	 { 0x00FF, "alpha"  }, { 0,0,0 }  },	   /* y dia    */
+      {	 { 0x0080, "cntrl"  }, { 0,0,0 }  },	   /* CTRL     */
+      {	 { 0x009F, "cntrl"  }, { 0,0,0 }  },	   /* CTRL     */
+      {	 { 0x00A0, "cntrl"  }, { 0,1,0 }  },	   /* NB SPACE */
+      {	 { 0x00F6, "cntrl"  }, { 0,1,0 }  },	   /* o dia    */
+      {	 { 0x00FF, "cntrl"  }, { 0,1,0 }  },	   /* y dia    */
+      {	 { 0x00B9, "digit"  }, { 0,1,0 }  },	   /* SUP 1    */
+      {	 { 0x00BE, "digit"  }, { 0,1,0 }  },	   /* 3/4      */
+      {	 { 0x009F, "graph"  }, { 0,1,0 }  },	   /* CTRL     */
+#ifdef SHOJI_IS_RIGHT
+      {	 { 0x00A0, "graph"  }, { 0,1,0 }  },	   /* NB SPACE */
+#else
+      {	 { 0x00A0, "graph"  }, { 0,0,0 }  },	   /* NB SPACE */
+#endif
+      {	 { 0x00A1, "graph"  }, { 0,0,0 }  },	   /* UD !     */
+      {	 { 0x00B1, "graph"  }, { 0,0,0 }  },	   /* +- sign  */
+      {	 { 0x00B3, "graph"  }, { 0,0,0 }  },	   /* SUP 3    */
+      {	 { 0x00B4, "graph"  }, { 0,0,0 }  },	   /* ACUTE    */
+      {	 { 0x00BB, "graph"  }, { 0,0,0 }  },	   /* >>       */
+      {	 { 0x00BE, "graph"  }, { 0,0,0 }  },	   /* 3/4      */
+      {	 { 0x00C0, "graph"  }, { 0,0,0 }  },	   /* A Grave  */
+      {	 { 0x00D6, "graph"  }, { 0,0,0 }  },	   /* O dia    */
+      {	 { 0x00D7, "graph"  }, { 0,0,0 }  },	   /* multipl. */
+      {	 { 0x00D8, "graph"  }, { 0,0,0 }  },	   /* O stroke */
+      {	 { 0x00DF, "graph"  }, { 0,0,0 }  },	   /* small Sh */
+      {	 { 0x00F7, "graph"  }, { 0,0,0 }  },	   /* division */
+      {	 { 0x00F8, "graph"  }, { 0,0,0 }  },	   /* o stroke */
+      {	 { 0x00FF, "graph"  }, { 0,0,0 }  },	   /* y dia    */
+      {	 { 0x009F, "print"  }, { 0,1,0 }  },	   /* CTRL     */
+#ifdef SHOJI_IS_RIGHT
+      {	 { 0x00A0, "print"  }, { 0,1,0 }  },	   /* NB SPACE */
+#else
+      {	 { 0x00A0, "print"  }, { 0,0,0 }  },	   /* NB SPACE */
+#endif
+      {	 { 0x00A1, "print"  }, { 0,0,0 }  },	   /* UD !     */
+      {	 { 0x00B1, "print"  }, { 0,0,0 }  },	   /* +- sign  */
+      {	 { 0x00B4, "print"  }, { 0,0,0 }  },	   /* ACUTE    */
+      {	 { 0x00B8, "print"  }, { 0,0,0 }  },	   /* CEDILLA  */
+      {	 { 0x00B9, "print"  }, { 0,0,0 }  },	   /* SUP 1    */
+      {	 { 0x00BB, "print"  }, { 0,0,0 }  },	   /* >>       */
+      {	 { 0x00BE, "print"  }, { 0,0,0 }  },	   /* 3/4      */
+      {	 { 0x00C0, "print"  }, { 0,0,0 }  },	   /* A Grave  */
+      {	 { 0x00DF, "print"  }, { 0,0,0 }  },	   /* small Sh */
+      {	 { 0x00F6, "print"  }, { 0,0,0 }  },	   /* o dia    */
+      {	 { 0x00F7, "print"  }, { 0,0,0 }  },	   /* division */
+      {	 { 0x00F8, "print"  }, { 0,0,0 }  },	   /* o stroke */
+      {	 { 0x00FF, "print"  }, { 0,0,0 }  },	   /* y dia    */
+      {	 { 0x009F, "punct"  }, { 0,1,0 }  },	   /* CTRL     */
+#ifdef SHOJI_IS_RIGHT
+      {	 { 0x00A0, "punct"  }, { 0,1,0 }  },	   /* NB SPACE */
+#else
+      {	 { 0x00A0, "punct"  }, { 0,0,0 }  },	   /* NB SPACE */
+#endif
+      {	 { 0x00A1, "punct"  }, { 0,0,0 }  },	   /* UD !     */
+      {	 { 0x00B0, "punct"  }, { 0,0,0 }  },	   /* Degree   */
+      {	 { 0x00B1, "punct"  }, { 0,0,0 }  },	   /* +- sign  */
+      {	 { 0x00B2, "punct"  }, { 0,0,0 }  },	   /* SUP 2    */
+      {	 { 0x00B3, "punct"  }, { 0,0,0 }  },	   /* SUP 3    */
+      {	 { 0x00B4, "punct"  }, { 0,0,0 }  },	   /* ACUTE    */
+      {	 { 0x00B8, "punct"  }, { 0,0,0 }  },	   /* CEDILLA  */
+      {	 { 0x00B9, "punct"  }, { 0,0,0 }  },	   /* SUP 1    */
+      {	 { 0x00BB, "punct"  }, { 0,0,0 }  },	   /* >>       */
+      {	 { 0x00BC, "punct"  }, { 0,0,0 }  },	   /* 1/4      */
+      {	 { 0x00BD, "punct"  }, { 0,0,0 }  },	   /* 1/2      */
+      {	 { 0x00BE, "punct"  }, { 0,0,0 }  },	   /* 3/4      */
+      {	 { 0x00BF, "punct"  }, { 0,0,0 }  },	   /* UD ?     */
+      {	 { 0x00C0, "punct"  }, { 0,1,0 }  },	   /* A Grave  */
+      {	 { 0x00D7, "punct"  }, { 0,0,0 }  },	   /* multipl. */
+      {	 { 0x00DF, "punct"  }, { 0,1,0 }  },	   /* small Sh */
+      {	 { 0x00F6, "punct"  }, { 0,1,0 }  },	   /* o dia    */
+      {	 { 0x00F7, "punct"  }, { 0,0,0 }  },	   /* division */
+      {	 { 0x00FF, "punct"  }, { 0,1,0 }  },	   /* y dia    */
+      {	 { 0x009F, "space"  }, { 0,1,0 }  },	   /* CTRL     */
+      {	 { 0x00A0, "space"  }, { 0,1,0 }  },	   /* NB SPACE */
+      {	 { 0x00A1, "space"  }, { 0,1,0 }  },	   /* UD !     */
+      {	 { 0x00B1, "space"  }, { 0,1,0 }  },	   /* +- sign  */
+      {	 { 0x00F8, "space"  }, { 0,1,0 }  },	   /* o stroke */
+      {	 { 0x00B3, "lower"  }, { 0,1,0 }  },	   /* SUP 3    */
+      {	 { 0x00B8, "lower"  }, { 0,1,0 }  },	   /* CEDILLA  */
+      {	 { 0x00BE, "lower"  }, { 0,1,0 }  },	   /* 3/4      */
+      {	 { 0x00C0, "lower"  }, { 0,1,0 }  },	   /* A Grave  */
+      {	 { 0x00D6, "lower"  }, { 0,1,0 }  },	   /* O dia    */
+      {	 { 0x00D8, "lower"  }, { 0,1,0 }  },	   /* O stroke */
+      {	 { 0x00DF, "lower"  }, { 0,0,0 }  },	   /* small Sh */
+      {	 { 0x00E0, "lower"  }, { 0,0,0 }  },	   /* a grave  */
+      {	 { 0x00F6, "lower"  }, { 0,0,0 }  },	   /* o dia    */
+      {	 { 0x00F7, "lower"  }, { 0,1,0 }  },	   /* division */
+      {	 { 0x00F8, "lower"  }, { 0,0,0 }  },	   /* o stroke */
+      {	 { 0x00FF, "lower"  }, { 0,0,0 }  },	   /* y dia    */
+      {	 { 0x00B4, "upper"  }, { 0,1,0 }  },	   /* ACUTE    */
+      {	 { 0x00B8, "upper"  }, { 0,1,0 }  },	   /* CEDILLA  */
+      {	 { 0x00B9, "upper"  }, { 0,1,0 }  },	   /* SUP 1    */
+      {	 { 0x00BE, "upper"  }, { 0,1,0 }  },	   /* 3/4      */
+      {	 { 0x00BF, "upper"  }, { 0,1,0 }  },	   /* UD ?     */
+      {	 { 0x00C0, "upper"  }, { 0,0,0 }  },	   /* A Grave  */
+      {	 { 0x00D6, "upper"  }, { 0,0,0 }  },	   /* O dia    */
+      {	 { 0x00D7, "upper"  }, { 0,1,0 }  },	   /* multipl. */
+      {	 { 0x00D8, "upper"  }, { 0,0,0 }  },	   /* O stroke */
+      {	 { 0x00DF, "upper"  }, { 0,1,0 }  },	   /* small Sh */
+      {	 { 0x00FF, "upper"  }, { 0,1,0 }  },	   /* y dia    */
+      {	 { 0x00B9, "xdigit" }, { 0,1,0 }  },	   /* SUP 1    */
+      {	 { 0x00BC, "xdigit" }, { 0,1,0 }  },	   /* 1/4      */
+      { .is_last = 1 }
+    }
+  },
+  {
+    { Tiswctype, TST_LOC_enUS },
+    {
+      {	 { WEOF,   "alnum"  }, { 0,1,0 }  },
+      {	 { 0x0000, "alnum"  }, { 0,1,0 }  },
+      {	 { 0x001F, "alnum"  }, { 0,1,0 }  },
+      {	 { 0x0020, "alnum"  }, { 0,1,0 }  },
+      {	 { 0x0021, "alnum"  }, { 0,1,0 }  },
+      {	 { 0x002F, "alnum"  }, { 0,1,0 }  },
+      {	 { 0x0030, "alnum"  }, { 0,0,0 }  },
+      {	 { 0x0039, "alnum"  }, { 0,0,0 }  },
+      {	 { 0x003A, "alnum"  }, { 0,1,0 }  },
+      {	 { 0x0040, "alnum"  }, { 0,1,0 }  },
+      {	 { 0x0041, "alnum"  }, { 0,0,0 }  },
+      {	 { 0x005A, "alnum"  }, { 0,0,0 }  },
+      {	 { 0x005B, "alnum"  }, { 0,1,0 }  },
+      {	 { 0x0060, "alnum"  }, { 0,1,0 }  },
+      {	 { 0x0061, "alnum"  }, { 0,0,0 }  },
+      {	 { 0x007A, "alnum"  }, { 0,0,0 }  },
+      {	 { 0x007B, "alnum"  }, { 0,1,0 }  },
+      {	 { 0x007E, "alnum"  }, { 0,1,0 }  },
+      {	 { 0x007F, "alnum"  }, { 0,1,0 }  },
+      {	 { 0x0080, "alnum"  }, { 0,1,0 }  },
+      {	 { 0x0000, "alpha"  }, { 0,1,0 }  },
+      {	 { 0x001F, "alpha"  }, { 0,1,0 }  },
+      {	 { 0x0020, "alpha"  }, { 0,1,0 }  },
+      {	 { 0x0021, "alpha"  }, { 0,1,0 }  },
+      {	 { 0x002F, "alpha"  }, { 0,1,0 }  },
+      {	 { 0x0030, "alpha"  }, { 0,1,0 }  },
+      {	 { 0x0039, "alpha"  }, { 0,1,0 }  },
+      {	 { 0x003A, "alpha"  }, { 0,1,0 }  },
+      {	 { 0x0040, "alpha"  }, { 0,1,0 }  },
+      {	 { 0x0041, "alpha"  }, { 0,0,0 }  },
+      {	 { 0x005A, "alpha"  }, { 0,0,0 }  },
+      {	 { 0x005B, "alpha"  }, { 0,1,0 }  },
+      {	 { 0x0060, "alpha"  }, { 0,1,0 }  },
+      {	 { 0x0061, "alpha"  }, { 0,0,0 }  },
+      {	 { 0x007A, "alpha"  }, { 0,0,0 }  },
+      {	 { 0x007B, "alpha"  }, { 0,1,0 }  },
+      {	 { 0x007E, "alpha"  }, { 0,1,0 }  },
+      {	 { 0x007F, "alpha"  }, { 0,1,0 }  },
+      {	 { 0x0080, "alpha"  }, { 0,1,0 }  },
+      {	 { 0x0009, "blank"  }, { 0,0,0 }  },
+      {	 { 0x000B, "blank"  }, { 0,1,0 }  },
+      {	 { 0x0020, "blank"  }, { 0,0,0 }  },
+      {	 { 0x0000, "cntrl"  }, { 0,0,0 }  },
+      {	 { 0x001F, "cntrl"  }, { 0,0,0 }  },
+      {	 { 0x0020, "cntrl"  }, { 0,1,0 }  },
+      {	 { 0x0021, "cntrl"  }, { 0,1,0 }  },
+      {	 { 0x002F, "cntrl"  }, { 0,1,0 }  },
+      {	 { 0x0030, "cntrl"  }, { 0,1,0 }  },
+      {	 { 0x0039, "cntrl"  }, { 0,1,0 }  },
+      {	 { 0x003A, "cntrl"  }, { 0,1,0 }  },
+      {	 { 0x0040, "cntrl"  }, { 0,1,0 }  },
+      {	 { 0x0041, "cntrl"  }, { 0,1,0 }  },
+      {	 { 0x005A, "cntrl"  }, { 0,1,0 }  },
+      {	 { 0x005B, "cntrl"  }, { 0,1,0 }  },
+      {	 { 0x0060, "cntrl"  }, { 0,1,0 }  },
+      {	 { 0x0061, "cntrl"  }, { 0,1,0 }  },
+      {	 { 0x007A, "cntrl"  }, { 0,1,0 }  },
+      {	 { 0x007B, "cntrl"  }, { 0,1,0 }  },
+      {	 { 0x007E, "cntrl"  }, { 0,1,0 }  },
+      {	 { 0x007F, "cntrl"  }, { 0,0,0 }  },
+      {	 { 0x0080, "cntrl"  }, { 0,1,0 }  },
+      {	 { 0x0000, "digit"  }, { 0,1,0 }  },
+      {	 { 0x001F, "digit"  }, { 0,1,0 }  },
+      {	 { 0x0020, "digit"  }, { 0,1,0 }  },
+      {	 { 0x0021, "digit"  }, { 0,1,0 }  },
+      {	 { 0x002F, "digit"  }, { 0,1,0 }  },
+      {	 { 0x0030, "digit"  }, { 0,0,0 }  },
+      {	 { 0x0039, "digit"  }, { 0,0,0 }  },
+      {	 { 0x003A, "digit"  }, { 0,1,0 }  },
+      {	 { 0x0040, "digit"  }, { 0,1,0 }  },
+      {	 { 0x0041, "digit"  }, { 0,1,0 }  },
+      {	 { 0x005A, "digit"  }, { 0,1,0 }  },
+      {	 { 0x005B, "digit"  }, { 0,1,0 }  },
+      {	 { 0x0060, "digit"  }, { 0,1,0 }  },
+      {	 { 0x0061, "digit"  }, { 0,1,0 }  },
+      {	 { 0x007A, "digit"  }, { 0,1,0 }  },
+      {	 { 0x007B, "digit"  }, { 0,1,0 }  },
+      {	 { 0x007E, "digit"  }, { 0,1,0 }  },
+      {	 { 0x007F, "digit"  }, { 0,1,0 }  },
+      {	 { 0x0080, "digit"  }, { 0,1,0 }  },
+      {	 { 0x0000, "graph"  }, { 0,1,0 }  },
+      {	 { 0x001F, "graph"  }, { 0,1,0 }  },
+      {	 { 0x0020, "graph"  }, { 0,1,0 }  },
+      {	 { 0x0021, "graph"  }, { 0,0,0 }  },
+      {	 { 0x002F, "graph"  }, { 0,0,0 }  },
+      {	 { 0x0030, "graph"  }, { 0,0,0 }  },
+      {	 { 0x0039, "graph"  }, { 0,0,0 }  },
+      {	 { 0x003A, "graph"  }, { 0,0,0 }  },
+      {	 { 0x0040, "graph"  }, { 0,0,0 }  },
+      {	 { 0x0041, "graph"  }, { 0,0,0 }  },
+      {	 { 0x005A, "graph"  }, { 0,0,0 }  },
+      {	 { 0x005B, "graph"  }, { 0,0,0 }  },
+      {	 { 0x0060, "graph"  }, { 0,0,0 }  },
+      {	 { 0x0061, "graph"  }, { 0,0,0 }  },
+      {	 { 0x007A, "graph"  }, { 0,0,0 }  },
+      {	 { 0x007B, "graph"  }, { 0,0,0 }  },
+      {	 { 0x007E, "graph"  }, { 0,0,0 }  },
+      {	 { 0x007F, "graph"  }, { 0,1,0 }  },
+      {	 { 0x0080, "graph"  }, { 0,1,0 }  },
+      {	 { 0x0000, "print"  }, { 0,1,0 }  },
+      {	 { 0x001F, "print"  }, { 0,1,0 }  },
+      {	 { 0x0020, "print"  }, { 0,0,0 }  },
+      {	 { 0x0021, "print"  }, { 0,0,0 }  },
+      {	 { 0x002F, "print"  }, { 0,0,0 }  },
+      {	 { 0x0030, "print"  }, { 0,0,0 }  },
+      {	 { 0x0039, "print"  }, { 0,0,0 }  },
+      {	 { 0x003A, "print"  }, { 0,0,0 }  },
+      {	 { 0x0040, "print"  }, { 0,0,0 }  },
+      {	 { 0x0041, "print"  }, { 0,0,0 }  },
+      {	 { 0x005A, "print"  }, { 0,0,0 }  },
+      {	 { 0x005B, "print"  }, { 0,0,0 }  },
+      {	 { 0x0060, "print"  }, { 0,0,0 }  },
+      {	 { 0x0061, "print"  }, { 0,0,0 }  },
+      {	 { 0x007A, "print"  }, { 0,0,0 }  },
+      {	 { 0x007B, "print"  }, { 0,0,0 }  },
+      {	 { 0x007E, "print"  }, { 0,0,0 }  },
+      {	 { 0x007F, "print"  }, { 0,1,0 }  },
+      {	 { 0x0080, "print"  }, { 0,1,0 }  },
+      {	 { 0x0000, "punct"  }, { 0,1,0 }  },
+      {	 { 0x001F, "punct"  }, { 0,1,0 }  },
+      {	 { 0x0020, "punct"  }, { 0,1,0 }  },
+      {	 { 0x0021, "punct"  }, { 0,0,0 }  },
+      {	 { 0x002F, "punct"  }, { 0,0,0 }  },
+      {	 { 0x0030, "punct"  }, { 0,1,0 }  },
+      {	 { 0x0039, "punct"  }, { 0,1,0 }  },
+      {	 { 0x003A, "punct"  }, { 0,0,0 }  },
+      {	 { 0x0040, "punct"  }, { 0,0,0 }  },
+      {	 { 0x0041, "punct"  }, { 0,1,0 }  },
+      {	 { 0x005A, "punct"  }, { 0,1,0 }  },
+      {	 { 0x005B, "punct"  }, { 0,0,0 }  },
+      {	 { 0x0060, "punct"  }, { 0,0,0 }  },
+      {	 { 0x0061, "punct"  }, { 0,1,0 }  },
+      {	 { 0x007A, "punct"  }, { 0,1,0 }  },
+      {	 { 0x007B, "punct"  }, { 0,0,0 }  },
+      {	 { 0x007E, "punct"  }, { 0,0,0 }  },
+      {	 { 0x007F, "punct"  }, { 0,1,0 }  },
+      {	 { 0x0080, "punct"  }, { 0,1,0 }  },
+      {	 { 0x0000, "space"  }, { 0,1,0 }  },
+      {	 { 0x001F, "space"  }, { 0,1,0 }  },
+      {	 { 0x0020, "space"  }, { 0,0,0 }  },
+      {	 { 0x0021, "space"  }, { 0,1,0 }  },
+      {	 { 0x002F, "space"  }, { 0,1,0 }  },
+      {	 { 0x007E, "space"  }, { 0,1,0 }  },
+      {	 { 0x007F, "space"  }, { 0,1,0 }  },
+      {	 { 0x0080, "space"  }, { 0,1,0 }  },
+      {	 { 0x0000, "lower"  }, { 0,1,0 }  },
+      {	 { 0x001F, "lower"  }, { 0,1,0 }  },
+      {	 { 0x0020, "lower"  }, { 0,1,0 }  },
+      {	 { 0x0021, "lower"  }, { 0,1,0 }  },
+      {	 { 0x002F, "lower"  }, { 0,1,0 }  },
+      {	 { 0x0030, "lower"  }, { 0,1,0 }  },
+      {	 { 0x0039, "lower"  }, { 0,1,0 }  },
+      {	 { 0x003A, "lower"  }, { 0,1,0 }  },
+      {	 { 0x0040, "lower"  }, { 0,1,0 }  },
+      {	 { 0x0041, "lower"  }, { 0,1,0 }  },
+      {	 { 0x005A, "lower"  }, { 0,1,0 }  },
+      {	 { 0x005B, "lower"  }, { 0,1,0 }  },
+      {	 { 0x0060, "lower"  }, { 0,1,0 }  },
+      {	 { 0x0061, "lower"  }, { 0,0,0 }  },
+      {	 { 0x007A, "lower"  }, { 0,0,0 }  },
+      {	 { 0x007B, "lower"  }, { 0,1,0 }  },
+      {	 { 0x007E, "lower"  }, { 0,1,0 }  },
+      {	 { 0x007F, "lower"  }, { 0,1,0 }  },
+      {	 { 0x0080, "lower"  }, { 0,1,0 }  },
+      {	 { 0x0000, "upper"  }, { 0,1,0 }  },
+      {	 { 0x001F, "upper"  }, { 0,1,0 }  },
+      {	 { 0x0020, "upper"  }, { 0,1,0 }  },
+      {	 { 0x0021, "upper"  }, { 0,1,0 }  },
+      {	 { 0x002F, "upper"  }, { 0,1,0 }  },
+      {	 { 0x0030, "upper"  }, { 0,1,0 }  },
+      {	 { 0x0039, "upper"  }, { 0,1,0 }  },
+      {	 { 0x003A, "upper"  }, { 0,1,0 }  },
+      {	 { 0x0040, "upper"  }, { 0,1,0 }  },
+      {	 { 0x0041, "upper"  }, { 0,0,0 }  },
+      {	 { 0x005A, "upper"  }, { 0,0,0 }  },
+      {	 { 0x005B, "upper"  }, { 0,1,0 }  },
+      {	 { 0x0060, "upper"  }, { 0,1,0 }  },
+      {	 { 0x0061, "upper"  }, { 0,1,0 }  },
+      {	 { 0x007A, "upper"  }, { 0,1,0 }  },
+      {	 { 0x007B, "upper"  }, { 0,1,0 }  },
+      {	 { 0x007E, "upper"  }, { 0,1,0 }  },
+      {	 { 0x007F, "upper"  }, { 0,1,0 }  },
+      {	 { 0x0080, "upper"  }, { 0,1,0 }  },
+      {	 { 0x0000, "xdigit" }, { 0,1,0 }  },
+      {	 { 0x001F, "xdigit" }, { 0,1,0 }  },
+      {	 { 0x0020, "xdigit" }, { 0,1,0 }  },
+      {	 { 0x0021, "xdigit" }, { 0,1,0 }  },
+      {	 { 0x002F, "xdigit" }, { 0,1,0 }  },
+      {	 { 0x0030, "xdigit" }, { 0,0,0 }  },
+      {	 { 0x0039, "xdigit" }, { 0,0,0 }  },
+      {	 { 0x003A, "xdigit" }, { 0,1,0 }  },
+      {	 { 0x0040, "xdigit" }, { 0,1,0 }  },
+      {	 { 0x0041, "xdigit" }, { 0,0,0 }  },
+      {	 { 0x005A, "xdigit" }, { 0,1,0 }  },
+      {	 { 0x005B, "xdigit" }, { 0,1,0 }  },
+      {	 { 0x0060, "xdigit" }, { 0,1,0 }  },
+      {	 { 0x0061, "xdigit" }, { 0,0,0 }  },
+      {	 { 0x007A, "xdigit" }, { 0,1,0 }  },
+      {	 { 0x007B, "xdigit" }, { 0,1,0 }  },
+      {	 { 0x007E, "xdigit" }, { 0,1,0 }  },
+      {	 { 0x007F, "xdigit" }, { 0,1,0 }  },
+      {	 { 0x0080, "xdigit" }, { 0,1,0 }  },
+      {	 { 0x0061, "xxxxxx" }, { 0,1,0 }  },
+      { .is_last = 1 }
+    }
+  },
+  {
+#if 0
+    { Tiswctype, TST_LOC_eucJP },
+#else
+    { Tiswctype, TST_LOC_ja_UTF8 },
+#endif
+    {
+#ifdef SHOJI_IS_RIGHT
+      {	 { 0x3029, "alnum"  }, { 0,1,0 }  },	   /* Hangzhou NUM9	 */
+#else
+      {	 { 0x3029, "alnum"  }, { 0,0,0 }  },	   /* Hangzhou NUM9	 */
+#endif
+      {	 { 0xFE4F, "alnum"  }, { 0,1,0 }  },	   /* CJK UNI.IDEO.	 */
+      {	 { 0xFF19, "alnum"  }, { 0,0,0 }  },	   /* FULL 9		 */
+      {	 { 0xFF20, "alnum"  }, { 0,1,0 }  },	   /* FULL @		 */
+      {	 { 0xFF3A, "alnum"  }, { 0,0,0 }  },	   /* FULL Z		 */
+      {	 { 0xFF40, "alnum"  }, { 0,1,0 }  },	   /* FULL GRAVE ACC.	 */
+      {	 { 0xFF5A, "alnum"  }, { 0,0,0 }  },	   /* FULL z		 */
+#ifdef SHOJI_IS_RIGHT
+      {	 { 0xFF71, "alnum"  }, { 0,1,0 }  },	   /* HALF KATA A	 */
+#else
+      {	 { 0xFF71, "alnum"  }, { 0,0,0 }  },	   /* HALF KATA A	 */
+#endif
+#ifdef SHOJI_IS_RIGHT
+      {	 { 0x3029, "alpha"  }, { 0,1,0 }  },	   /* Hangzhou NUM9	 */
+#else
+      {	 { 0x3029, "alpha"  }, { 0,0,0 }  },	   /* Hangzhou NUM9	 */
+#endif
+      {	 { 0xFE4F, "alpha"  }, { 0,1,0 }  },	   /* CJK UNI.IDEO.	 */
+#ifdef SHOJI_IS_RIGHT
+      {	 { 0xFF19, "alpha"  }, { 0,1,0 }  },	   /* FULL 9		 */
+#else
+      {	 { 0xFF19, "alpha"  }, { 0,0,0 }  },	   /* FULL 9		 */
+#endif
+      {	 { 0xFF20, "alpha"  }, { 0,1,0 }  },	   /* FULL @		 */
+      {	 { 0xFF3A, "alpha"  }, { 0,0,0 }  },	   /* FULL Z		 */
+      {	 { 0xFF40, "alpha"  }, { 0,1,0 }  },	   /* FULL GRAVE ACC.	 */
+      {	 { 0xFF5A, "alpha"  }, { 0,0,0 }  },	   /* FULL z		 */
+#ifdef SHOJI_IS_RIGHT
+      {	 { 0xFF71, "alpha"  }, { 0,1,0 }  },	   /* HALF KATA A	 */
+#else
+      {	 { 0xFF71, "alpha"  }, { 0,0,0 }  },	   /* HALF KATA A	 */
+#endif
+      {	 { 0x0080, "cntrl"  }, { 0,0,0 }  },	   /* CNTRL		 */
+      {	 { 0x3000, "cntrl"  }, { 0,1,0 }  },	   /* IDEO. SPACE	 */
+      {	 { 0x3029, "digit"  }, { 0,1,0 }  },	   /* Hangzhou NUM9	 */
+      {	 { 0x32CB, "digit"  }, { 0,1,0 }  },	   /* IDEO.TEL.SYM.DEC12 */
+      /* 21: */
+      {	 { 0x33FE, "digit"  }, { 0,1,0 }  },	   /* CJK IDEO.TEL.31th	 */
+      {	 { 0xFF19, "digit"  }, { 0,1,0 }  },	   /* FULL 9		 */
+      {	 { 0x3000, "graph"  }, { 0,1,0 }  },	   /* IDEO. SPACE	 */
+#ifdef SHOJI_IS_RIGHT
+      {	 { 0x3020, "graph"  }, { 0,1,0 }  },	   /* POSTAL MARK FACE	 */
+      {	 { 0x3029, "graph"  }, { 0,1,0 }  },	   /* Hangzhou NUM9	 */
+      {	 { 0x302F, "graph"  }, { 0,1,0 }  },	   /* Diacritics(Hangul) */
+      {	 { 0x3037, "graph"  }, { 0,1,0 }  },	   /* Separator Symbol	 */
+      {	 { 0x303F, "graph"  }, { 0,1,0 }  },	   /* IDEO. HALF SPACE	 */
+#else
+      {	 { 0x3020, "graph"  }, { 0,0,0 }  },	   /* POSTAL MARK FACE	 */
+      {	 { 0x3029, "graph"  }, { 0,0,0 }  },	   /* Hangzhou NUM9	 */
+      {	 { 0x302F, "graph"  }, { 0,0,0 }  },	   /* Diacritics(Hangul) */
+      {	 { 0x3037, "graph"  }, { 0,0,0 }  },	   /* Separator Symbol	 */
+      {	 { 0x303F, "graph"  }, { 0,0,0 }  },	   /* IDEO. HALF SPACE	 */
+#endif
+      /* 29: */
+      {	 { 0x3041, "graph"  }, { 0,0,0 }  },	   /* HIRAGANA a	 */
+      /* Non jis: */
+#ifdef SHOJI_IS_RIGHT
+      {	 { 0x3094, "graph"  }, { 0,1,0 }  },	   /* HIRAGANA u"	 */
+#else
+      {	 { 0x3094, "graph"  }, { 0,0,0 }  },	   /* HIRAGANA u"	 */
+#endif
+      /* Non jis: */
+#ifdef SHOJI_IS_RIGHT
+      {	 { 0x3099, "graph"  }, { 0,1,0 }  },	   /* SOUND MARK	 */
+#else
+      {	 { 0x3099, "graph"  }, { 0,0,0 }  },	   /* SOUND MARK	 */
+#endif
+      {	 { 0x309E, "graph"  }, { 0,0,0 }  },	   /* ITERATION MARK	 */
+      /* 33: */
+      {	 { 0x30A1, "graph"  }, { 0,0,0 }  },	   /* KATAKANA a	 */
+      /* Non jis: */
+#ifdef SHOJI_IS_RIGHT
+      {	 { 0x30FA, "graph"  }, { 0,1,0 }  },	   /* KATAKANA wo"	 */
+#else
+      {	 { 0x30FA, "graph"  }, { 0,0,0 }  },	   /* KATAKANA wo"	 */
+#endif
+      {	 { 0x30FB, "graph"  }, { 0,0,0 }  },	   /* KATAKANA MID.DOT	 */
+      {	 { 0x30FE, "graph"  }, { 0,0,0 }  },	   /* KATAKANA ITERATION */
+#ifdef SHOJI_IS_RIGHT
+      {	 { 0x3191, "graph"  }, { 0,1,0 }  },	   /* KANBUN REV.MARK	 */
+      {	 { 0x3243, "graph"  }, { 0,1,0 }  },	   /* IDEO. MARK (reach) */
+      {	 { 0x32CB, "graph"  }, { 0,1,0 }  },	   /* IDEO.TEL.SYM.DEC12 */
+      {	 { 0x32FE, "graph"  }, { 0,1,0 }  },	   /* MARU KATAKANA wo	 */
+      {	 { 0x33FE, "graph"  }, { 0,1,0 }  },	   /* CJK IDEO.TEL.31th	 */
+#else
+      {	 { 0x3191, "graph"  }, { 0,0,0 }  },	   /* KANBUN REV.MARK	 */
+      {	 { 0x3243, "graph"  }, { 0,0,0 }  },	   /* IDEO. MARK (reach) */
+      {	 { 0x32CB, "graph"  }, { 0,0,0 }  },	   /* IDEO.TEL.SYM.DEC12 */
+      {	 { 0x32FE, "graph"  }, { 0,0,0 }  },	   /* MARU KATAKANA wo	 */
+      {	 { 0x33FE, "graph"  }, { 0,0,0 }  },	   /* CJK IDEO.TEL.31th	 */
+#endif
+      {	 { 0x4E00, "graph"  }, { 0,0,0 }  },	   /* CJK UNI.IDEO.	 */
+      {	 { 0x4E05, "graph"  }, { 0,0,0 }  },	   /* CJK UNI.IDEO.	 */
+#ifdef SHOJI_IS_RIGHT
+      {	 { 0x4E06, "graph"  }, { 0,1,0 }  },	   /* CJK UNI.IDEO.NON-J */
+#else
+      {	 { 0x4E06, "graph"  }, { 0,0,0 }  },	   /* CJK UNI.IDEO.NON-J */
+#endif
+      {	 { 0x4E07, "graph"  }, { 0,0,0 }  },	   /* CJK UNI.IDEO.	 */
+      {	 { 0x4FFF, "graph"  }, { 0,0,0 }  },	   /* CJK UNI.IDEO.	 */
+      {	 { 0x9000, "graph"  }, { 0,0,0 }  },	   /* CJK UNI.IDEO.	 */
+      {	 { 0x9006, "graph"  }, { 0,0,0 }  },	   /* CJK UNI.IDEO.	 */
+#ifdef SHOJI_IS_RIGHT
+      {	 { 0x9007, "graph"  }, { 0,1,0 }  },	   /* CJK UNI.IDEO.NON-J */
+      {	 { 0x9FA4, "graph"  }, { 0,1,0 }  },	   /* CJK UNI.IDEO.NON-J */
+#else
+      {	 { 0x9007, "graph"  }, { 0,0,0 }  },	   /* CJK UNI.IDEO.NON-J */
+      {	 { 0x9FA4, "graph"  }, { 0,0,0 }  },	   /* CJK UNI.IDEO.NON-J */
+#endif
+      /* 51 */
+      {	 { 0x9FA5, "graph"  }, { 0,0,0 }  },	   /* CJK UNI.IDEO.	 */
+      /* Non jis: */
+#ifdef SHOJI_IS_RIGHT
+      {	 { 0xFE4F, "graph"  }, { 0,1,0 }  },	   /* CJK UNI.IDEO.	 */
+#else
+      {	 { 0xFE4F, "graph"  }, { 0,0,0 }  },	   /* CJK UNI.IDEO.	 */
+#endif
+      {	 { 0xFF0F, "graph"  }, { 0,0,0 }  },	   /* FULL SLASH	 */
+      {	 { 0xFF19, "graph"  }, { 0,0,0 }  },	   /* FULL 9		 */
+      {	 { 0xFF20, "graph"  }, { 0,0,0 }  },	   /* FULL @		 */
+      {	 { 0xFF3A, "graph"  }, { 0,0,0 }  },	   /* FULL Z		 */
+      {	 { 0xFF40, "graph"  }, { 0,0,0 }  },	   /* FULL GRAVE ACC.	 */
+      {	 { 0xFF5A, "graph"  }, { 0,0,0 }  },	   /* FULL z		 */
+      {	 { 0xFF5E, "graph"  }, { 0,0,0 }  },	   /* FULL ~ (tilde)	 */
+      {	 { 0xFF61, "graph"  }, { 0,0,0 }  },	   /* HALF IDEO.STOP. .	 */
+      {	 { 0xFF65, "graph"  }, { 0,0,0 }  },	   /* HALF KATA MID.DOT	 */
+      {	 { 0xFF66, "graph"  }, { 0,0,0 }  },	   /* HALF KATA WO	 */
+      {	 { 0xFF6F, "graph"  }, { 0,0,0 }  },	   /* HALF KATA tu	 */
+      {	 { 0xFF70, "graph"  }, { 0,0,0 }  },	   /* HALF KATA PL -	 */
+      {	 { 0xFF71, "graph"  }, { 0,0,0 }  },	   /* HALF KATA A	 */
+      {	 { 0xFF9E, "graph"  }, { 0,0,0 }  },	   /* HALF KATA MI	 */
+      {	 { 0x3000, "print"  }, { 0,0,0 }  },	   /* IDEO. SPACE	 */
+#ifdef SHOJI_IS_RIGHT
+      {	 { 0x3020, "print"  }, { 0,1,0 }  },	   /* POSTAL MARK FACE	 */
+      {	 { 0x3029, "print"  }, { 0,1,0 }  },	   /* Hangzhou NUM9	 */
+      {	 { 0x302F, "print"  }, { 0,1,0 }  },	   /* Diacritics(Hangul) */
+      {	 { 0x3037, "print"  }, { 0,1,0 }  },	   /* Separator Symbol	 */
+#else
+      {	 { 0x3020, "print"  }, { 0,0,0 }  },	   /* POSTAL MARK FACE	 */
+      {	 { 0x3029, "print"  }, { 0,0,0 }  },	   /* Hangzhou NUM9	 */
+      {	 { 0x302F, "print"  }, { 0,0,0 }  },	   /* Diacritics(Hangul) */
+      {	 { 0x3037, "print"  }, { 0,0,0 }  },	   /* Separator Symbol	 */
+#endif
+      {	 { 0x4E00, "print"  }, { 0,0,0 }  },	   /* CJK UNI.IDEO.	 */
+      {	 { 0x4E05, "print"  }, { 0,0,0 }  },	   /* CJK UNI.IDEO.	 */
+#ifdef SHOJI_IS_RIGHT
+      {	 { 0x4E06, "print"  }, { 0,1,0 }  },	   /* CJK UNI.IDEO.NON-J */
+#else
+      {	 { 0x4E06, "print"  }, { 0,0,0 }  },	   /* CJK UNI.IDEO.NON-J */
+#endif
+      {	 { 0x4E07, "print"  }, { 0,0,0 }  },	   /* CJK UNI.IDEO.	 */
+      {	 { 0x4FFF, "print"  }, { 0,0,0 }  },	   /* CJK UNI.IDEO.	 */
+      {	 { 0x9000, "print"  }, { 0,0,0 }  },	   /* CJK UNI.IDEO.	 */
+      {	 { 0x9006, "print"  }, { 0,0,0 }  },	   /* CJK UNI.IDEO.	 */
+#ifdef SHOJI_IS_RIGHT
+      {	 { 0x9007, "print"  }, { 0,1,0 }  },	   /* CJK UNI.IDEO.NON-J */
+      {	 { 0x9FA4, "print"  }, { 0,1,0 }  },	   /* CJK UNI.IDEO.NON-J */
+#else
+      {	 { 0x9007, "print"  }, { 0,0,0 }  },	   /* CJK UNI.IDEO.NON-J */
+      {	 { 0x9FA4, "print"  }, { 0,0,0 }  },	   /* CJK UNI.IDEO.NON-J */
+#endif
+      /* 81: */
+      {	 { 0x9FA5, "print"  }, { 0,0,0 }  },	   /* CJK UNI.IDEO.	 */
+      /* Non jis: */
+#ifdef SHOJI_IS_RIGHT
+      {	 { 0xFE4F, "print"  }, { 0,1,0 }  },	   /* CJK UNI.IDEO.	 */
+#else
+      {	 { 0xFE4F, "print"  }, { 0,0,0 }  },	   /* CJK UNI.IDEO.	 */
+#endif
+      {	 { 0x3000, "punct"  }, { 0,1,0 }  },	   /* IDEO. SPACE	 */
+#ifdef SHOJI_IS_RIGHT
+      {	 { 0x3020, "punct"  }, { 0,1,0 }  },	   /* POSTAL MARK FACE	 */
+      {	 { 0x302F, "punct"  }, { 0,1,0 }  },	   /* Diacritics(Hangul) */
+      {	 { 0x3037, "punct"  }, { 0,1,0 }  },	   /* FEED Separator	 */
+      {	 { 0x303F, "punct"  }, { 0,1,0 }  },	   /* IDEO. HALF SPACE	 */
+#else
+      {	 { 0x3020, "punct"  }, { 0,0,0 }  },	   /* POSTAL MARK FACE	 */
+      {	 { 0x302F, "punct"  }, { 0,0,0 }  },	   /* Diacritics(Hangul) */
+      {	 { 0x3037, "punct"  }, { 0,0,0 }  },	   /* FEED Separator	 */
+      {	 { 0x303F, "punct"  }, { 0,0,0 }  },	   /* IDEO. HALF SPACE	 */
+#endif
+      {	 { 0x3041, "punct"  }, { 0,1,0 }  },	   /* HIRAGANA a	 */
+      {	 { 0x3094, "punct"  }, { 0,1,0 }  },	   /* HIRAGANA u"	 */
+      /* 90: */
+#ifdef SHOJI_IS_RIGHT
+      {	 { 0x3099, "punct"  }, { 0,1,0 }  },	   /* SOUND MARK	 */
+#else
+      {	 { 0x3099, "punct"  }, { 0,0,0 }  },	   /* SOUND MARK	 */
+#endif
+      {	 { 0x309E, "punct"  }, { 0,1,0 }  },	   /* ITERATION MARK	 */
+      {	 { 0x30A1, "punct"  }, { 0,1,0 }  },	   /* KATAKANA a	 */
+      {	 { 0x30FA, "punct"  }, { 0,1,0 }  },	   /* KATAKANA wo"	 */
+      {	 { 0x30FB, "punct"  }, { 0,0,0 }  },	   /* KATAKANA MID.DOT	 */
+      /* 95: */
+      {	 { 0x30FE, "punct"  }, { 0,1,0 }  },	   /* KATAKANA ITERATION */
+#ifdef SHOJI_IS_RIGHT
+      {	 { 0x3191, "punct"  }, { 0,1,0 }  },	   /* KANBUN REV.MARK	 */
+      {	 { 0x3243, "punct"  }, { 0,1,0 }  },	   /* IDEO. MARK (reach) */
+      {	 { 0x32CB, "punct"  }, { 0,1,0 }  },	   /* IDEO.TEL.SYM.DEC12 */
+      {	 { 0x32FE, "punct"  }, { 0,1,0 }  },	   /* MARU KATAKANA wo	 */
+      {	 { 0x33FE, "punct"  }, { 0,1,0 }  },	   /* CJK IDEO.TEL.31th	 */
+#else
+      {	 { 0x3191, "punct"  }, { 0,0,0 }  },	   /* KANBUN REV.MARK	 */
+      {	 { 0x3243, "punct"  }, { 0,0,0 }  },	   /* IDEO. MARK (reach) */
+      {	 { 0x32CB, "punct"  }, { 0,0,0 }  },	   /* IDEO.TEL.SYM.DEC12 */
+      {	 { 0x32FE, "punct"  }, { 0,0,0 }  },	   /* MARU KATAKANA wo	 */
+      {	 { 0x33FE, "punct"  }, { 0,0,0 }  },	   /* CJK IDEO.TEL.31th	 */
+#endif
+      {	 { 0x9007, "punct"  }, { 0,1,0 }  },	   /* CJK UNI.IDEO.NON-J */
+      {	 { 0x9FA4, "punct"  }, { 0,1,0 }  },	   /* CJK UNI.IDEO.NON-J */
+      {	 { 0x9FA5, "punct"  }, { 0,1,0 }  },	   /* CJK UNI.IDEO.	 */
+      {	 { 0xFF0F, "punct"  }, { 0,0,0 }  },	   /* FULL SLASH	 */
+      /* 105: */
+      {	 { 0xFF19, "punct"  }, { 0,1,0 }  },	   /* FULL 9		 */
+      {	 { 0xFF20, "punct"  }, { 0,0,0 }  },	   /* FULL @		 */
+      {	 { 0xFF3A, "punct"  }, { 0,1,0 }  },	   /* FULL Z		 */
+      {	 { 0xFF40, "punct"  }, { 0,0,0 }  },	   /* FULL GRAVE ACC.	 */
+      {	 { 0xFF5A, "punct"  }, { 0,1,0 }  },	   /* FULL z		 */
+      {	 { 0xFF5E, "punct"  }, { 0,0,0 }  },	   /* FULL ~ (tilde)	 */
+      {	 { 0xFF61, "punct"  }, { 0,0,0 }  },	   /* HALF IDEO.STOP. .	 */
+      {	 { 0xFF65, "punct"  }, { 0,0,0 }  },	   /* HALF KATA MID.DOT	 */
+      {	 { 0xFF70, "punct"  }, { 0,1,0 }  },	   /* HALF KATA PL -	 */
+      {	 { 0xFF9E, "punct"  }, { 0,1,0 }  },	   /* HALF KATA MI	 */
+      /* 115: */
+      {	 { 0x3000, "space"  }, { 0,0,0 }  },	   /* IDEO. SPACE	 */
+      {	 { 0x303F, "space"  }, { 0,1,0 }  },	   /* IDEO. HALF SPACE	 */
+      {	 { 0x3041, "lower"  }, { 0,1,0 }  },	   /* HIRAGANA a	 */
+      {	 { 0x3094, "lower"  }, { 0,1,0 }  },	   /* HIRAGANA u"	 */
+      {	 { 0x30A1, "lower"  }, { 0,1,0 }  },	   /* KATAKANA a	 */
+      {	 { 0x30FA, "lower"  }, { 0,1,0 }  },	   /* KATAKANA wo"	 */
+      {	 { 0xFF66, "lower"  }, { 0,1,0 }  },	   /* HALF KATA WO	 */
+      {	 { 0xFF6F, "lower"  }, { 0,1,0 }  },	   /* HALF KATA tu	 */
+      {	 { 0xFF70, "lower"  }, { 0,1,0 }  },	   /* HALF KATA PL -	 */
+      /* 124: */
+      {	 { 0xFF71, "lower"  }, { 0,1,0 }  },	   /* HALF KATA A	 */
+      {	 { 0xFF9E, "lower"  }, { 0,1,0 }  },	   /* HALF KATA MI	 */
+      {	 { 0xFF71, "upper"  }, { 0,1,0 }  },	   /* HALF KATA A	 */
+      {	 { 0xFF19, "xdigit" }, { 0,1,0 }  },	   /* FULL 9		 */
+      {	 { 0x3000, "jspace" }, { 0,0,0 }  },	   /* IDEO. SPACE	 */
+      /* Non jis? */
+      {	 { 0x303F, "jspace" }, { 0,1,0 }  },	   /* IDEO.HALF SPACE	 */
+      {	 { 0xFF19, "jdigit" }, { 0,0,0 }  },	   /* FULL 9		 */
+      {	 { 0x3041, "jhira"  }, { 0,0,0 }  },	   /* HIRAGANA a	 */
+      {	 { 0x3094, "jhira"  }, { 0,1,0 }  },	   /* HIRAGANA u"	 */
+      {	 { 0x30A1, "jkata"  }, { 0,0,0 }  },	   /* KATAKANA a	 */
+      /* Non jis: */
+      {	 { 0x30FA, "jkata"  }, { 0,1,0 }  },	   /* KATAKANA wo"	 */
+      {	 { 0xFF66, "jkata"  }, { 0,0,0 }  },	   /* HALF KATA WO	 */
+      {	 { 0xFF6F, "jkata"  }, { 0,0,0 }  },	   /* HALF KATA tu	 */
+      {	 { 0x4E05, "jkanji" }, { 0,0,0 }  },	   /* CJK UNI.IDEO.	 */
+#ifdef SHOJI_IS_RIGHT
+      /* : */
+      {	 { 0x4E06, "jkanji" }, { 0,1,1 }  },	   /* CJK UNI.IDEO.NON-J */
+#else
+      /* XXX This character does not exist in EUC-JP.  */
+      {	 { 0x4E06, "jkanji" }, { 0,1,0 }  },	   /* CJK UNI.IDEO.NON-J */
+#endif
+      {	 { 0x4E07, "jkanji" }, { 0,0,0 }  },	   /* CJK UNI.IDEO.	 */
+      { .is_last = 1 }
+    }
+  },
+  {
+    { Tiswctype, TST_LOC_end }
+  }
+};
+
+
+/* dat_isw-funcs.c */
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_iswdigit.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_iswdigit.c
new file mode 100644
index 00000000..70ca5447
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_iswdigit.c
@@ -0,0 +1,125 @@
+/*
+ *  TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY
+ *
+ *	 FILE:	dat_iswdigit.c
+ *
+ *	 ISW*:	int iswdigit (wint_t wc);
+ */
+
+
+#include "dat_isw-funcs.h"
+
+
+TST_ISW_LOC (DIGIT, digit) = {
+
+  {   TST_ISW_REC (de, digit)
+      {
+	{  { 0x0080 }, { 0,1,0 }  },	/* CTRL	    */
+	{  { 0x009F }, { 0,1,0 }  },	/* CTRL	    */
+	{  { 0x00A0 }, { 0,1,0 }  },	/* NB SPACE */
+	{  { 0x00A1 }, { 0,1,0 }  },	/* UD !	    */
+	{  { 0x00B0 }, { 0,1,0 }  },	/* Degree   */
+	{  { 0x00B1 }, { 0,1,0 }  },	/* +- sign  */
+	{  { 0x00B2 }, { 0,1,0 }  },	/* SUP 2    */
+	{  { 0x00B3 }, { 0,1,0 }  },	/* SUP 3    */
+	{  { 0x00B4 }, { 0,1,0 }  },	/* ACUTE    */
+	{  { 0x00B8 }, { 0,1,0 }  },	/* CEDILLA  */
+	{  { 0x00B9 }, { 0,1,0 }  },	/* SUP 1    */
+	{  { 0x00BB }, { 0,1,0 }  },	/* >>	    */
+	{  { 0x00BC }, { 0,1,0 }  },	/* 1/4	    */
+	{  { 0x00BD }, { 0,1,0 }  },	/* 1/2	    */
+	{  { 0x00BE }, { 0,1,0 }  },	/* 3/4	    */
+	{  { 0x00BF }, { 0,1,0 }  },	/* UD ?	    */
+	{  { 0x00C0 }, { 0,1,0 }  },	/* A Grave  */
+	{  { 0x00D6 }, { 0,1,0 }  },	/* O dia    */
+	{  { 0x00D7 }, { 0,1,0 }  },	/* multipl. */
+	{  { 0x00D8 }, { 0,1,0 }  },	/* O stroke */
+	{  { 0x00DF }, { 0,1,0 }  },	/* small Sh */
+	{  { 0x00E0 }, { 0,1,0 }  },	/* a grave  */
+	{  { 0x00F6 }, { 0,1,0 }  },	/* o dia    */
+	{  { 0x00F7 }, { 0,1,0 }  },	/* division */
+	{  { 0x00F8 }, { 0,1,0 }  },	/* o stroke */
+	{  { 0x00FF }, { 0,1,0 }  },	/* y dia    */
+	{ .is_last = 1 }		/* Last element.  */
+      }
+  },
+  {   TST_ISW_REC (enUS, digit)
+      {
+	{  { WEOF   }, { 0,1,0 }  },
+	{  { 0x0000 }, { 0,1,0 }  },
+	{  { 0x001F }, { 0,1,0 }  },
+	{  { 0x0020 }, { 0,1,0 }  },
+	{  { 0x0021 }, { 0,1,0 }  },
+	{  { 0x002F }, { 0,1,0 }  },
+	{  { 0x0030 }, { 0,0,0 }  },
+	{  { 0x0039 }, { 0,0,0 }  },
+	{  { 0x003A }, { 0,1,0 }  },
+	{  { 0x0040 }, { 0,1,0 }  },
+	{  { 0x0041 }, { 0,1,0 }  },
+	{  { 0x005A }, { 0,1,0 }  },
+	{  { 0x005B }, { 0,1,0 }  },
+	{  { 0x0060 }, { 0,1,0 }  },
+	{  { 0x0061 }, { 0,1,0 }  },
+	{  { 0x007A }, { 0,1,0 }  },
+	{  { 0x007B }, { 0,1,0 }  },
+	{  { 0x007E }, { 0,1,0 }  },
+	{  { 0x007F }, { 0,1,0 }  },
+	{  { 0x0080 }, { 0,1,0 }  },
+	{ .is_last = 1 }		/* Last element.  */
+      }
+  },
+#if 0
+  {   TST_ISW_REC (eucJP, digit)
+#else
+  {   TST_ISW_REC (ja_UTF8, digit)
+#endif
+      {
+	{  { 0x3000 }, { 0,1,0 }  },	/* IDEO. SPACE	      */
+	{  { 0x3020 }, { 0,1,0 }  },	/* POSTAL MARK FACE   */
+	{  { 0x3029 }, { 0,1,0 }  },	/* Hangzhou NUM9      */
+	{  { 0x302F }, { 0,1,0 }  },	/* Diacritics(Hangul) */
+	{  { 0x3037 }, { 0,1,0 }  },	/* Separator Symbol   */
+	{  { 0x303F }, { 0,1,0 }  },	/* IDEO. HALF SPACE   */
+	{  { 0x3041 }, { 0,1,0 }  },	/* HIRAGANA a	      */
+	{  { 0x3094 }, { 0,1,0 }  },	/* HIRAGANA u"	      */
+	{  { 0x3099 }, { 0,1,0 }  },	/* SOUND MARK	      */
+	{  { 0x309E }, { 0,1,0 }  },	/* ITERATION MARK     */
+	{  { 0x30A1 }, { 0,1,0 }  },	/* KATAKANA a	      */
+	{  { 0x30FA }, { 0,1,0 }  },	/* KATAKANA wo"	      */
+	{  { 0x30FB }, { 0,1,0 }  },	/* KATAKANA MID.DOT   */
+	{  { 0x30FE }, { 0,1,0 }  },	/* KATAKANA ITERATION */
+	{  { 0x3191 }, { 0,1,0 }  },	/* KANBUN REV.MARK    */
+	{  { 0x3243 }, { 0,1,0 }  },	/* IDEO. MARK (reach) */
+	{  { 0x32CB }, { 0,1,0 }  },	/* IDEO.TEL.SYM.DEC12 */
+	{  { 0x32FE }, { 0,1,0 }  },	/* MARU KATAKANA wo   */
+	{  { 0x33FE }, { 0,1,0 }  },	/* CJK IDEO.TEL.31th  */
+	{  { 0x4E00 }, { 0,1,0 }  },	/* CJK UNI.IDEO.      */
+	{  { 0x4E05 }, { 0,1,0 }  },	/* CJK UNI.IDEO.      */
+	{  { 0x4E06 }, { 0,1,0 }  },	/* CJK UNI.IDEO.NON-J */
+	{  { 0x4E07 }, { 0,1,0 }  },	/* CJK UNI.IDEO.      */
+	{  { 0x4FFF }, { 0,1,0 }  },	/* CJK UNI.IDEO.      */
+	{  { 0x9000 }, { 0,1,0 }  },	/* CJK UNI.IDEO.      */
+	{  { 0x9006 }, { 0,1,0 }  },	/* CJK UNI.IDEO.      */
+	{  { 0x9007 }, { 0,1,0 }  },	/* CJK UNI.IDEO.NON-J */
+	{  { 0x9FA4 }, { 0,1,0 }  },	/* CJK UNI.IDEO.NON-J */
+	{  { 0x9FA5 }, { 0,1,0 }  },	/* CJK UNI.IDEO.      */
+	{  { 0xFE4F }, { 0,1,0 }  },	/* CJK UNI.IDEO.      */
+	{  { 0xFF0F }, { 0,1,0 }  },	/* FULL SLASH	      */
+	{  { 0xFF19 }, { 0,1,0 }  },	/* FULL 9	      */
+	{  { 0xFF20 }, { 0,1,0 }  },	/* FULL @	      */
+	{  { 0xFF3A }, { 0,1,0 }  },	/* FULL Z	      */
+	{  { 0xFF40 }, { 0,1,0 }  },	/* FULL GRAVE ACC.    */
+	{  { 0xFF5A }, { 0,1,0 }  },	/* FULL z	      */
+	{  { 0xFF5E }, { 0,1,0 }  },	/* FULL ~ (tilde)     */
+	{  { 0xFF61 }, { 0,1,0 }  },	/* HALF IDEO.STOP. .  */
+	{  { 0xFF65 }, { 0,1,0 }  },	/* HALF KATA MID.DOT  */
+	{  { 0xFF66 }, { 0,1,0 }  },	/* HALF KATA WO	      */
+	{  { 0xFF6F }, { 0,1,0 }  },	/* HALF KATA tu	      */
+	{  { 0xFF70 }, { 0,1,0 }  },	/* HALF KATA PL -     */
+	{  { 0xFF71 }, { 0,1,0 }  },	/* HALF KATA A	      */
+	{  { 0xFF9E }, { 0,1,0 }  },	/* HALF KATA MI	      */
+	{ .is_last = 1 }		/* Last element.  */
+      }
+  },
+  {   TST_ISW_REC (end, digit) }
+};
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_iswgraph.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_iswgraph.c
new file mode 100644
index 00000000..80cacb2a
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_iswgraph.c
@@ -0,0 +1,167 @@
+/*
+ *  TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY
+ *
+ *	 FILE:	dat_iswgraph.c
+ *
+ *	 ISW*:	int iswgraph (wint_t wc);
+ */
+
+
+#include "dat_isw-funcs.h"
+
+
+TST_ISW_LOC (GRAPH, graph) = {
+
+  {   TST_ISW_REC (de, graph)
+      {
+	{  { 0x0080 }, { 0,1,0 }  },	/* CTRL	    */
+	{  { 0x009F }, { 0,1,0 }  },	/* CTRL	    */
+#ifdef SHOJI_IS_RIGHT
+	{  { 0x00A0 }, { 0,1,0 }  },	/* NB SPACE */
+#else
+	{  { 0x00A0 }, { 0,0,0 }  },	/* NB SPACE */
+#endif
+	{  { 0x00A1 }, { 0,0,0 }  },	/* UD !	    */
+	{  { 0x00B0 }, { 0,0,0 }  },	/* Degree   */
+	{  { 0x00B1 }, { 0,0,0 }  },	/* +- sign  */
+	{  { 0x00B2 }, { 0,0,0 }  },	/* SUP 2    */
+	{  { 0x00B3 }, { 0,0,0 }  },	/* SUP 3    */
+	{  { 0x00B4 }, { 0,0,0 }  },	/* ACUTE    */
+	{  { 0x00B8 }, { 0,0,0 }  },	/* CEDILLA  */
+	{  { 0x00B9 }, { 0,0,0 }  },	/* SUP 1    */
+	{  { 0x00BB }, { 0,0,0 }  },	/* >>	    */
+	{  { 0x00BC }, { 0,0,0 }  },	/* 1/4	    */
+	{  { 0x00BD }, { 0,0,0 }  },	/* 1/2	    */
+	{  { 0x00BE }, { 0,0,0 }  },	/* 3/4	    */
+	{  { 0x00BF }, { 0,0,0 }  },	/* UD ?	    */
+	{  { 0x00C0 }, { 0,0,0 }  },	/* A Grave  */
+	{  { 0x00D6 }, { 0,0,0 }  },	/* O dia    */
+	{  { 0x00D7 }, { 0,0,0 }  },	/* multipl. */
+	{  { 0x00D8 }, { 0,0,0 }  },	/* O stroke */
+	{  { 0x00DF }, { 0,0,0 }  },	/* small Sh */
+	{  { 0x00E0 }, { 0,0,0 }  },	/* a grave  */
+	{  { 0x00F6 }, { 0,0,0 }  },	/* o dia    */
+	{  { 0x00F7 }, { 0,0,0 }  },	/* division */
+	{  { 0x00F8 }, { 0,0,0 }  },	/* o stroke */
+	{  { 0x00FF }, { 0,0,0 }  },	/* y dia    */
+	{ .is_last = 1 }		/* Last element.  */
+      }
+  },
+  {   TST_ISW_REC (enUS, graph)
+      {
+	{  { WEOF   }, { 0,1,0 }  },
+	{  { 0x0000 }, { 0,1,0 }  },
+	{  { 0x001F }, { 0,1,0 }  },
+	{  { 0x0020 }, { 0,1,0 }  },
+	{  { 0x0021 }, { 0,0,0 }  },
+	{  { 0x002F }, { 0,0,0 }  },
+	{  { 0x0030 }, { 0,0,0 }  },
+	{  { 0x0039 }, { 0,0,0 }  },
+	{  { 0x003A }, { 0,0,0 }  },
+	{  { 0x0040 }, { 0,0,0 }  },
+	{  { 0x0041 }, { 0,0,0 }  },
+	{  { 0x005A }, { 0,0,0 }  },
+	{  { 0x005B }, { 0,0,0 }  },
+	{  { 0x0060 }, { 0,0,0 }  },
+	{  { 0x0061 }, { 0,0,0 }  },
+	{  { 0x007A }, { 0,0,0 }  },
+	{  { 0x007B }, { 0,0,0 }  },
+	{  { 0x007E }, { 0,0,0 }  },
+	{  { 0x007F }, { 0,1,0 }  },
+	{  { 0x0080 }, { 0,1,0 }  }, /* 20 */
+	{ .is_last = 1 }		/* Last element.  */
+      }
+  },
+#if 0
+  {   TST_ISW_REC( eucJP, graph )
+#else
+  {   TST_ISW_REC( ja_UTF8, graph )
+#endif
+      {
+	{  { 0x3000 }, { 0,1,0 }  },	/* IDEO. SPACE	      */
+#ifdef SHOJI_IS_RIGHT
+	{  { 0x3020 }, { 0,1,0 }  },	/* POSTAL MARK FACE   */
+	{  { 0x3029 }, { 0,1,0 }  },	/* Hangzhou NUM9      */
+	{  { 0x302F }, { 0,1,0 }  },	/* Diacritics(Hangul) */
+	{  { 0x3037 }, { 0,1,0 }  },	/* Separator Symbol   */
+	{  { 0x303F }, { 0,1,0 }  },	/* IDEO. HALF SPACE   */
+#else
+	{  { 0x3020 }, { 0,0,0 }  },	/* POSTAL MARK FACE   */
+	{  { 0x3029 }, { 0,0,0 }  },	/* Hangzhou NUM9      */
+	{  { 0x302F }, { 0,0,0 }  },	/* Diacritics(Hangul) */
+	{  { 0x3037 }, { 0,0,0 }  },	/* Separator Symbol   */
+	{  { 0x303F }, { 0,0,0 }  },	/* IDEO. HALF SPACE   */
+#endif
+	{  { 0x3041 }, { 0,0,0 }  },	/* HIRAGANA a	      */
+#ifdef SHOJI_IS_RIGHT
+	{  { 0x3094 }, { 0,1,0 }  },	/* HIRAGANA u"	      */  /* non jis */
+	{  { 0x3099 }, { 0,1,0 }  },	/* SOUND MARK	      */
+#else
+	{  { 0x3094 }, { 0,0,0 }  },	/* HIRAGANA u"	      */  /* non jis */
+	{  { 0x3099 }, { 0,0,0 }  },	/* SOUND MARK	      */
+#endif
+	{  { 0x309E }, { 0,0,0 }  },	/* ITERATION MARK     */  /* 10 */
+	{  { 0x30A1 }, { 0,0,0 }  },	/* KATAKANA a	      */
+#ifdef SHOJI_IS_RIGHT
+	{  { 0x30FA }, { 0,1,0 }  },	/* KATAKANA wo"	      */  /* non jis */
+#else
+	{  { 0x30FA }, { 0,0,0 }  },	/* KATAKANA wo"	      */  /* non jis */
+#endif
+	{  { 0x30FB }, { 0,0,0 }  },	/* KATAKANA MID.DOT   */
+	{  { 0x30FE }, { 0,0,0 }  },	/* KATAKANA ITERATION */
+#ifdef SHOJI_IS_RIGHT
+	{  { 0x3191 }, { 0,1,0 }  },	/* KANBUN REV.MARK    */
+	{  { 0x3243 }, { 0,1,0 }  },	/* IDEO. MARK (reach) */
+	{  { 0x32CB }, { 0,1,0 }  },	/* IDEO.TEL.SYM.DEC12 */
+	{  { 0x32FE }, { 0,1,0 }  },	/* MARU KATAKANA wo   */
+	{  { 0x33FE }, { 0,1,0 }  },	/* CJK IDEO.TEL.31th  */
+#else
+	{  { 0x3191 }, { 0,0,0 }  },	/* KANBUN REV.MARK    */
+	{  { 0x3243 }, { 0,0,0 }  },	/* IDEO. MARK (reach) */
+	{  { 0x32CB }, { 0,0,0 }  },	/* IDEO.TEL.SYM.DEC12 */
+	{  { 0x32FE }, { 0,0,0 }  },	/* MARU KATAKANA wo   */
+	{  { 0x33FE }, { 0,0,0 }  },	/* CJK IDEO.TEL.31th  */
+#endif
+	{  { 0x4E00 }, { 0,0,0 }  },	/* CJK UNI.IDEO.      */  /* 20 */
+	{  { 0x4E05 }, { 0,0,0 }  },	/* CJK UNI.IDEO.      */
+#ifdef SHOJI_IS_RIGHT
+	{  { 0x4E06 }, { 0,1,0 }  },	/* CJK UNI.IDEO.NON-J */
+#else
+	{  { 0x4E06 }, { 0,0,0 }  },	/* CJK UNI.IDEO.NON-J */
+#endif
+	{  { 0x4E07 }, { 0,0,0 }  },	/* CJK UNI.IDEO.      */
+	{  { 0x4FFF }, { 0,0,0 }  },	/* CJK UNI.IDEO.      */
+	{  { 0x9000 }, { 0,0,0 }  },	/* CJK UNI.IDEO.      */
+	{  { 0x9006 }, { 0,0,0 }  },	/* CJK UNI.IDEO.      */
+#ifdef SHOJI_IS_RIGHT
+	{  { 0x9007 }, { 0,1,0 }  },	/* CJK UNI.IDEO.NON-J */
+	{  { 0x9FA4 }, { 0,1,0 }  },	/* CJK UNI.IDEO.NON-J */
+#else
+	{  { 0x9007 }, { 0,0,0 }  },	/* CJK UNI.IDEO.NON-J */
+	{  { 0x9FA4 }, { 0,0,0 }  },	/* CJK UNI.IDEO.NON-J */
+#endif
+	{  { 0x9FA5 }, { 0,0,0 }  },	/* CJK UNI.IDEO.      */
+#ifdef SHOJI_IS_RIGHT
+	{  { 0xFE4F }, { 0,1,0 }  },	/* CJK Wave Low Line  */  /* 30 */
+#else
+	{  { 0xFE4F }, { 0,0,0 }  },	/* CJK Wave Low Line  */  /* 30 */
+#endif
+	{  { 0xFF0F }, { 0,0,0 }  },	/* FULL SLASH	      */
+	{  { 0xFF19 }, { 0,0,0 }  },	/* FULL 9	      */
+	{  { 0xFF20 }, { 0,0,0 }  },	/* FULL @	      */
+	{  { 0xFF3A }, { 0,0,0 }  },	/* FULL Z	      */
+	{  { 0xFF40 }, { 0,0,0 }  },	/* FULL GRAVE ACC.    */
+	{  { 0xFF5A }, { 0,0,0 }  },	/* FULL z	      */
+	{  { 0xFF5E }, { 0,0,0 }  },	/* FULL ~ (tilde)     */
+	{  { 0xFF61 }, { 0,0,0 }  },	/* HALF IDEO.STOP. .  */
+	{  { 0xFF65 }, { 0,0,0 }  },	/* HALF KATA MID.DOT  */
+	{  { 0xFF66 }, { 0,0,0 }  },	/* HALF KATA WO	      */
+	{  { 0xFF6F }, { 0,0,0 }  },	/* HALF KATA tu	      */
+	{  { 0xFF70 }, { 0,0,0 }  },	/* HALF KATA PL -     */
+	{  { 0xFF71 }, { 0,0,0 }  },	/* HALF KATA A	      */
+	{  { 0xFF9E }, { 0,0,0 }  },	/* HALF KATA MI	      */
+	{ .is_last = 1 }		/* Last element.  */
+      }
+  },
+  {   TST_ISW_REC (end, graph) }
+};
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_iswlower.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_iswlower.c
new file mode 100644
index 00000000..58ec08ed
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_iswlower.c
@@ -0,0 +1,96 @@
+/*
+ *  TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY
+ *
+ *	 FILE:	dat_iswlower.c
+ *
+ *	 ISW*:	int iswlower (wint_t wc);
+ */
+
+
+#include "dat_isw-funcs.h"
+
+
+TST_ISW_LOC (LOWER, lower) = {
+
+  {   TST_ISW_REC (de, lower)
+      {
+	{  { 0x0080 }, { 0,1,0 }  },	/* CTRL	    */
+	{  { 0x009F }, { 0,1,0 }  },	/* CTRL	    */
+	{  { 0x00A0 }, { 0,1,0 }  },	/* NB SPACE */
+	{  { 0x00A1 }, { 0,1,0 }  },	/* UD !	    */
+	{  { 0x00B0 }, { 0,1,0 }  },	/* Degree   */
+	{  { 0x00B1 }, { 0,1,0 }  },	/* +- sign  */
+	{  { 0x00B2 }, { 0,1,0 }  },	/* SUP 2    */
+	{  { 0x00B3 }, { 0,1,0 }  },	/* SUP 3    */
+	{  { 0x00B4 }, { 0,1,0 }  },	/* ACUTE    */
+	{  { 0x00B8 }, { 0,1,0 }  },	/* CEDILLA  */
+	{  { 0x00B9 }, { 0,1,0 }  },	/* SUP 1    */
+	{  { 0x00BB }, { 0,1,0 }  },	/* >>	    */
+	{  { 0x00BC }, { 0,1,0 }  },	/* 1/4	    */
+	{  { 0x00BD }, { 0,1,0 }  },	/* 1/2	    */
+	{  { 0x00BE }, { 0,1,0 }  },	/* 3/4	    */
+	{  { 0x00BF }, { 0,1,0 }  },	/* UD ?	    */
+	{  { 0x00C0 }, { 0,1,0 }  },	/* A Grave  */
+	{  { 0x00D6 }, { 0,1,0 }  },	/* O dia    */
+	{  { 0x00D7 }, { 0,1,0 }  },	/* multipl. */
+	{  { 0x00D8 }, { 0,1,0 }  },	/* O stroke */
+	{  { 0x00DF }, { 0,0,0 }  },	/* small Sh */
+	{  { 0x00E0 }, { 0,0,0 }  },	/* a grave  */
+	{  { 0x00F6 }, { 0,0,0 }  },	/* o dia    */
+	{  { 0x00F7 }, { 0,1,0 }  },	/* division */
+	{  { 0x00F8 }, { 0,0,0 }  },	/* o stroke */
+	{  { 0x00FF }, { 0,0,0 }  },	/* y dia    */
+	{ .is_last = 1 }		/* Last element.  */
+      }
+  },
+  {   TST_ISW_REC (enUS, lower)
+      {
+	{  { WEOF   }, { 0,1,0 }  },
+	{  { 0x0000 }, { 0,1,0 }  },
+	{  { 0x001F }, { 0,1,0 }  },
+	{  { 0x0020 }, { 0,1,0 }  },
+	{  { 0x0021 }, { 0,1,0 }  },
+	{  { 0x002F }, { 0,1,0 }  },
+	{  { 0x0030 }, { 0,1,0 }  },
+	{  { 0x0039 }, { 0,1,0 }  },
+	{  { 0x003A }, { 0,1,0 }  },
+	{  { 0x0040 }, { 0,1,0 }  },
+	{  { 0x0041 }, { 0,1,0 }  },
+	{  { 0x005A }, { 0,1,0 }  },
+	{  { 0x005B }, { 0,1,0 }  },
+	{  { 0x0060 }, { 0,1,0 }  },
+	{  { 0x0061 }, { 0,0,0 }  },
+	{  { 0x007A }, { 0,0,0 }  },
+	{  { 0x007B }, { 0,1,0 }  },
+	{  { 0x007E }, { 0,1,0 }  },
+	{  { 0x007F }, { 0,1,0 }  },
+	{  { 0x0080 }, { 0,1,0 }  },
+	{ .is_last = 1 }		/* Last element.  */
+      }
+  },
+#if 0
+  {   TST_ISW_REC (eucJP, lower)
+#else
+  {   TST_ISW_REC (ja_UTF8, lower)
+#endif
+      {
+	{  { 0x3000 }, { 0,1,0 }  },	/* IDEO. SPACE	      */
+	{  { 0x303F }, { 0,1,0 }  },	/* IDEO. HALF SPACE   */
+	{  { 0x3041 }, { 0,1,0 }  },	/* HIRAGANA a	      */
+	{  { 0x3094 }, { 0,1,0 }  },	/* HIRAGANA u"	      */
+	{  { 0x3099 }, { 0,1,0 }  },	/* SOUND MARK	      */
+	{  { 0x309E }, { 0,1,0 }  },	/* ITERATION MARK     */
+	{  { 0x30A1 }, { 0,1,0 }  },	/* KATAKANA a	      */
+	{  { 0x30FA }, { 0,1,0 }  },	/* KATAKANA wo"	      */
+	{  { 0xFF3A }, { 0,1,0 }  },	/* FULL Z	      */
+	{  { 0xFF40 }, { 0,1,0 }  },	/* FULL GRAVE ACC.    */
+	{  { 0xFF5A }, { 0,0,0 }  },	/* FULL z	      */
+	{  { 0xFF6F }, { 0,1,0 }  },	/* HALF KATA tu	      */
+	{  { 0xFF71 }, { 0,1,0 }  },	/* HALF KATA A	      */
+	{  { 0xFF9E }, { 0,1,0 }  },	/* HALF KATA MI	      */
+	{ .is_last = 1 }		/* Last element.  */
+      }
+  },
+  {   TST_ISW_REC (end, lower) }
+
+};
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_iswprint.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_iswprint.c
new file mode 100644
index 00000000..bcd96d05
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_iswprint.c
@@ -0,0 +1,170 @@
+/*
+ *  TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY
+ *
+ *       FILE:  dat_iswprint.c
+ *
+ *       ISW*:  int iswprint (wint_t wc);
+ */
+
+
+#include "dat_isw-funcs.h"
+
+
+TST_ISW_LOC (PRINT, print) = {
+
+  {   TST_ISW_REC (de, print)
+      {
+	{  { 0x0080 }, { 0,1,0 }  },  /* CTRL     */
+	{  { 0x009F }, { 0,1,0 }  },  /* CTRL     */
+#ifdef SHOJI_IS_RIGHT
+	{  { 0x00A0 }, { 0,1,0 }  },  /* NB SPACE */
+#else
+	{  { 0x00A0 }, { 0,0,0 }  },  /* NB SPACE */
+#endif
+	{  { 0x00A1 }, { 0,0,0 }  },  /* UD !     */
+	{  { 0x00B0 }, { 0,0,0 }  },  /* Degree   */
+	{  { 0x00B1 }, { 0,0,0 }  },  /* +- sign  */
+	{  { 0x00B2 }, { 0,0,0 }  },  /* SUP 2    */
+	{  { 0x00B3 }, { 0,0,0 }  },  /* SUP 3    */
+	{  { 0x00B4 }, { 0,0,0 }  },  /* ACUTE    */
+	{  { 0x00B8 }, { 0,0,0 }  },  /* CEDILLA  */
+	{  { 0x00B9 }, { 0,0,0 }  },  /* SUP 1    */
+	{  { 0x00BB }, { 0,0,0 }  },  /* >>       */
+	{  { 0x00BC }, { 0,0,0 }  },  /* 1/4      */
+	{  { 0x00BD }, { 0,0,0 }  },  /* 1/2      */
+	{  { 0x00BE }, { 0,0,0 }  },  /* 3/4      */
+	{  { 0x00BF }, { 0,0,0 }  },  /* UD ?     */
+	{  { 0x00C0 }, { 0,0,0 }  },  /* A Grave  */
+	{  { 0x00D6 }, { 0,0,0 }  },  /* O dia    */
+	{  { 0x00D7 }, { 0,0,0 }  },  /* multipl. */
+	{  { 0x00D8 }, { 0,0,0 }  },  /* O stroke */
+	{  { 0x00DF }, { 0,0,0 }  },  /* small Sh */
+	{  { 0x00E0 }, { 0,0,0 }  },  /* a grave  */
+	{  { 0x00F6 }, { 0,0,0 }  },  /* o dia    */
+	{  { 0x00F7 }, { 0,0,0 }  },  /* division */
+	{  { 0x00F8 }, { 0,0,0 }  },  /* o stroke */
+	{  { 0x00FF }, { 0,0,0 }  },  /* y dia    */
+	{ .is_last = 1 }		/* Last element.  */
+      }
+  },
+  {   TST_ISW_REC (enUS, print)
+      {
+	{  { WEOF   }, { 0,1,0 }  }, /* 01 */
+	{  { 0x0000 }, { 0,1,0 }  },
+	{  { 0x001F }, { 0,1,0 }  },
+	{  { 0x0020 }, { 0,0,0 }  },
+	{  { 0x0021 }, { 0,0,0 }  },
+	{  { 0x002F }, { 0,0,0 }  },
+	{  { 0x0030 }, { 0,0,0 }  },
+	{  { 0x0039 }, { 0,0,0 }  },
+	{  { 0x003A }, { 0,0,0 }  },
+	{  { 0x0040 }, { 0,0,0 }  },
+	{  { 0x0041 }, { 0,0,0 }  },
+	{  { 0x005A }, { 0,0,0 }  },
+	{  { 0x005B }, { 0,0,0 }  },
+	{  { 0x0060 }, { 0,0,0 }  },
+	{  { 0x0061 }, { 0,0,0 }  },
+	{  { 0x007A }, { 0,0,0 }  },
+	{  { 0x007B }, { 0,0,0 }  },
+	{  { 0x007E }, { 0,0,0 }  },
+	{  { 0x007F }, { 0,1,0 }  },
+	{  { 0x0080 }, { 0,1,0 }  }, /* 20 */
+#ifdef NO_WAIVER
+	{  { 0x3042 }, { 0,1,0 }  }, /*  */
+#endif
+	{ .is_last = 1 }		/* Last element.  */
+      }
+  },
+#if 0
+  {   TST_ISW_REC (eucJP, print)
+#else
+  {   TST_ISW_REC (ja_UTF8, print)
+#endif
+      {
+	{  { 0x3000 }, { 0,0,0 }  },  /* IDEO. SPACE        */
+#ifdef SHOJI_IS_RIGHT
+	{  { 0x3020 }, { 0,1,0 }  },  /* POSTAL MARK FACE   */
+	{  { 0x3029 }, { 0,1,0 }  },  /* Hangzhou NUM9      */
+	{  { 0x302F }, { 0,1,0 }  },  /* Diacritics(Hangul) */
+	{  { 0x3037 }, { 0,1,0 }  },  /* Separator Symbol   */
+	{  { 0x303F }, { 0,1,0 }  },  /* IDEO. HALF SPACE   */
+#else
+	{  { 0x3020 }, { 0,0,0 }  },  /* POSTAL MARK FACE   */
+	{  { 0x3029 }, { 0,0,0 }  },  /* Hangzhou NUM9      */
+	{  { 0x302F }, { 0,0,0 }  },  /* Diacritics(Hangul) */
+	{  { 0x3037 }, { 0,0,0 }  },  /* Separator Symbol   */
+	{  { 0x303F }, { 0,0,0 }  },  /* IDEO. HALF SPACE   */
+#endif
+	{  { 0x3041 }, { 0,0,0 }  },  /* HIRAGANA a         */
+#ifdef SHOJI_IS_RIGHT
+	{  { 0x3094 }, { 0,1,0 }  },  /* HIRAGANA u"        */  /* non jis */
+	{  { 0x3099 }, { 0,1,0 }  },  /* SOUND MARK         */
+#else
+	{  { 0x3094 }, { 0,0,0 }  },  /* HIRAGANA u"        */  /* non jis */
+	{  { 0x3099 }, { 0,0,0 }  },  /* SOUND MARK         */
+#endif
+	{  { 0x309E }, { 0,0,0 }  },  /* ITERATION MARK     */  /* 10 */
+	{  { 0x30A1 }, { 0,0,0 }  },  /* KATAKANA a         */
+#ifdef SHOJI_IS_RIGHT
+	{  { 0x30FA }, { 0,1,0 }  },  /* KATAKANA wo"       */  /* non jis */
+#else
+	{  { 0x30FA }, { 0,0,0 }  },  /* KATAKANA wo"       */  /* non jis */
+#endif
+	{  { 0x30FB }, { 0,0,0 }  },  /* KATAKANA MID.DOT   */
+	{  { 0x30FE }, { 0,0,0 }  },  /* KATAKANA ITERATION */
+#ifdef SHOJI_IS_RIGHT
+	{  { 0x3191 }, { 0,1,0 }  },  /* KANBUN REV.MARK    */
+	{  { 0x3243 }, { 0,1,0 }  },  /* IDEO. MARK (reach) */
+	{  { 0x32CB }, { 0,1,0 }  },  /* IDEO.TEL.SYM.DEC12 */
+	{  { 0x32FE }, { 0,1,0 }  },  /* MARU KATAKANA wo   */
+	{  { 0x33FE }, { 0,1,0 }  },  /* CJK IDEO.TEL.31th  */
+#else
+	{  { 0x3191 }, { 0,0,0 }  },  /* KANBUN REV.MARK    */
+	{  { 0x3243 }, { 0,0,0 }  },  /* IDEO. MARK (reach) */
+	{  { 0x32CB }, { 0,0,0 }  },  /* IDEO.TEL.SYM.DEC12 */
+	{  { 0x32FE }, { 0,0,0 }  },  /* MARU KATAKANA wo   */
+	{  { 0x33FE }, { 0,0,0 }  },  /* CJK IDEO.TEL.31th  */
+#endif
+	{  { 0x4E00 }, { 0,0,0 }  },  /* CJK UNI.IDEO.      */  /* 20 */
+	{  { 0x4E05 }, { 0,0,0 }  },  /* CJK UNI.IDEO.      */
+#ifdef SHOJI_IS_RIGHT
+	{  { 0x4E06 }, { 0,1,0 }  },  /* CJK UNI.IDEO.NON-J */
+#else
+	{  { 0x4E06 }, { 0,0,0 }  },  /* CJK UNI.IDEO.NON-J */
+#endif
+	{  { 0x4E07 }, { 0,0,0 }  },  /* CJK UNI.IDEO.      */
+	{  { 0x4FFF }, { 0,0,0 }  },  /* CJK UNI.IDEO.      */
+	{  { 0x9000 }, { 0,0,0 }  },  /* CJK UNI.IDEO.      */
+	{  { 0x9006 }, { 0,0,0 }  },  /* CJK UNI.IDEO.      */
+#ifdef SHOJI_IS_RIGHT
+	{  { 0x9007 }, { 0,1,0 }  },  /* CJK UNI.IDEO.NON-J */
+	{  { 0x9FA4 }, { 0,1,0 }  },  /* CJK UNI.IDEO.NON-J */
+#else
+	{  { 0x9007 }, { 0,0,0 }  },  /* CJK UNI.IDEO.NON-J */
+	{  { 0x9FA4 }, { 0,0,0 }  },  /* CJK UNI.IDEO.NON-J */
+#endif
+	{  { 0x9FA5 }, { 0,0,0 }  },  /* CJK UNI.IDEO.      */
+#ifdef SHOJI_IS_RIGHT
+	{  { 0xFE4F }, { 0,1,0 }  },  /* WAVE LOW LINE      */  /* 30 */
+#else
+	{  { 0xFE4F }, { 0,0,0 }  },  /* WAVE LOW LINE      */  /* 30 */
+#endif
+	{  { 0xFF0F }, { 0,0,0 }  },  /* FULL SLASH         */
+	{  { 0xFF19 }, { 0,0,0 }  },  /* FULL 9             */
+	{  { 0xFF20 }, { 0,0,0 }  },  /* FULL @             */
+	{  { 0xFF3A }, { 0,0,0 }  },  /* FULL Z             */
+	{  { 0xFF40 }, { 0,0,0 }  },  /* FULL GRAVE ACC.    */
+	{  { 0xFF5A }, { 0,0,0 }  },  /* FULL z             */
+	{  { 0xFF5E }, { 0,0,0 }  },  /* FULL ~ (tilde)     */
+	{  { 0xFF61 }, { 0,0,0 }  },  /* HALF IDEO.STOP. .  */
+	{  { 0xFF65 }, { 0,0,0 }  },  /* HALF KATA MID.DOT  */
+	{  { 0xFF66 }, { 0,0,0 }  },  /* HALF KATA WO       */  /* 40 */
+	{  { 0xFF6F }, { 0,0,0 }  },  /* HALF KATA tu       */
+	{  { 0xFF70 }, { 0,0,0 }  },  /* HALF KATA PL -     */
+	{  { 0xFF71 }, { 0,0,0 }  },  /* HALF KATA A        */
+	{  { 0xFF9E }, { 0,0,0 }  },  /* HALF KATA MI       */
+	{ .is_last = 1 }		/* Last element.  */
+      }
+  },
+  {   TST_ISW_REC (end, print) }
+};
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_iswpunct.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_iswpunct.c
new file mode 100644
index 00000000..2b3612ff
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_iswpunct.c
@@ -0,0 +1,155 @@
+/*
+ *  TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY
+ *
+ *	 FILE:	dat_iswpunct.c
+ *
+ *	 ISW*:	int iswpunct (wint_t wc);
+ */
+
+
+#include "dat_isw-funcs.h"
+
+
+TST_ISW_LOC (PUNCT, punct) = {
+
+  {   TST_ISW_REC (de, punct)
+      {
+	{  { 0x0080 }, { 0,1,0 }  },	/* CTRL	    */
+	{  { 0x009F }, { 0,1,0 }  },	/* CTRL	    */
+#ifdef SHOJI_IS_RIGHT
+	{  { 0x00A0 }, { 0,1,0 }  },	/* NB SPACE */
+#else
+	{  { 0x00A0 }, { 0,0,0 }  },	/* NB SPACE */
+#endif
+	{  { 0x00A1 }, { 0,0,0 }  },	/* UD !	    */
+	{  { 0x00B0 }, { 0,0,0 }  },	/* Degree   */
+	{  { 0x00B1 }, { 0,0,0 }  },	/* +- sign  */
+	{  { 0x00B2 }, { 0,0,0 }  },	/* SUP 2    */
+	{  { 0x00B3 }, { 0,0,0 }  },	/* SUP 3    */
+	{  { 0x00B4 }, { 0,0,0 }  },	/* ACUTE    */
+	{  { 0x00B8 }, { 0,0,0 }  },	/* CEDILLA  */
+	{  { 0x00B9 }, { 0,0,0 }  },	/* SUP 1    */
+	{  { 0x00BB }, { 0,0,0 }  },	/* >>	    */
+	{  { 0x00BC }, { 0,0,0 }  },	/* 1/4	    */
+	{  { 0x00BD }, { 0,0,0 }  },	/* 1/2	    */
+	{  { 0x00BE }, { 0,0,0 }  },	/* 3/4	    */
+	{  { 0x00BF }, { 0,0,0 }  },	/* UD ?	    */
+	{  { 0x00C0 }, { 0,1,0 }  },	/* A Grave  */
+	{  { 0x00D6 }, { 0,1,0 }  },	/* O dia    */
+	{  { 0x00D7 }, { 0,0,0 }  },	/* multipl. */
+	{  { 0x00D8 }, { 0,1,0 }  },	/* O stroke */
+	{  { 0x00DF }, { 0,1,0 }  },	/* small Sh */
+	{  { 0x00E0 }, { 0,1,0 }  },	/* a grave  */
+	{  { 0x00F6 }, { 0,1,0 }  },	/* o dia    */
+	{  { 0x00F7 }, { 0,0,0 }  },	/* division */
+	{  { 0x00F8 }, { 0,1,0 }  },	/* o stroke */
+	{  { 0x00FF }, { 0,1,0 }  },	/* y dia    */
+	{ .is_last = 1 }		/* Last element.  */
+      }
+  },
+  {   TST_ISW_REC (enUS, punct)
+      {
+	{  { WEOF   }, { 0,1,0 }  }, /* 01 */
+	{  { 0x0000 }, { 0,1,0 }  },
+	{  { 0x001F }, { 0,1,0 }  },
+	{  { 0x0020 }, { 0,1,0 }  },
+	{  { 0x0021 }, { 0,0,0 }  },
+	{  { 0x002F }, { 0,0,0 }  },
+	{  { 0x0030 }, { 0,1,0 }  },
+	{  { 0x0039 }, { 0,1,0 }  },
+	{  { 0x003A }, { 0,0,0 }  },
+	{  { 0x0040 }, { 0,0,0 }  },
+	{  { 0x0041 }, { 0,1,0 }  },
+	{  { 0x005A }, { 0,1,0 }  },
+	{  { 0x005B }, { 0,0,0 }  },
+	{  { 0x0060 }, { 0,0,0 }  },
+	{  { 0x0061 }, { 0,1,0 }  },
+	{  { 0x007A }, { 0,1,0 }  },
+	{  { 0x007B }, { 0,0,0 }  },
+	{  { 0x007E }, { 0,0,0 }  },
+	{  { 0x007F }, { 0,1,0 }  },
+	{  { 0x0080 }, { 0,1,0 }  }, /* 20 */
+	{ .is_last = 1 }		/* Last element.  */
+      }
+  },
+#if 0
+  {   TST_ISW_REC (eucJP, punct)
+#else
+  {   TST_ISW_REC (ja_UTF8, punct)
+#endif
+      {
+	{  { 0x3000 }, { 0,1,0 }  },	/* IDEO. SPACE	      */
+#ifdef SHOJI_IS_RIGHT
+	{  { 0x3020 }, { 0,1,0 }  },	/* POSTAL MARK FACE   */
+#else
+	{  { 0x3020 }, { 0,0,0 }  },	/* POSTAL MARK FACE   */
+#endif
+	{  { 0x3029 }, { 0,1,0 }  },	/* Hangzhou NUM9      */
+#ifdef SHOJI_IS_RIGHT
+	{  { 0x302F }, { 0,1,0 }  },	/* Diacritics(Hangul) */
+	{  { 0x3037 }, { 0,1,0 }  },	/* Separator Symbol   */
+	{  { 0x303F }, { 0,1,0 }  },	/* IDEO. HALF SPACE   */
+#else
+	{  { 0x302F }, { 0,0,0 }  },	/* Diacritics(Hangul) */
+	{  { 0x3037 }, { 0,0,0 }  },	/* Separator Symbol   */
+	{  { 0x303F }, { 0,0,0 }  },	/* IDEO. HALF SPACE   */
+#endif
+	{  { 0x3041 }, { 0,1,0 }  },	/* HIRAGANA a	      */
+	{  { 0x3094 }, { 0,1,0 }  },	/* HIRAGANA u"	      */
+#ifdef SHOJI_IS_RIGHT
+	{  { 0x3099 }, { 0,1,0 }  },	/* SOUND MARK	      */
+#else
+	{  { 0x3099 }, { 0,0,0 }  },	/* SOUND MARK	      */
+#endif
+	{  { 0x309E }, { 0,1,0 }  },	/* ITERATION MARK     */  /* 10 */
+	{  { 0x30A1 }, { 0,1,0 }  },	/* KATAKANA a	      */
+	{  { 0x30FA }, { 0,1,0 }  },	/* KATAKANA wo"	      */
+	{  { 0x30FB }, { 0,0,0 }  },	/* KATAKANA MID.DOT   */
+	{  { 0x30FE }, { 0,1,0 }  },	/* KATAKANA ITERATION */
+#ifdef SHOJI_IS_RIGHT
+	{  { 0x3191 }, { 0,1,0 }  },	/* KANBUN REV.MARK    */
+	{  { 0x3243 }, { 0,1,0 }  },	/* IDEO. MARK (reach) */
+	{  { 0x32CB }, { 0,1,0 }  },	/* IDEO.TEL.SYM.DEC12 */
+	{  { 0x32FE }, { 0,1,0 }  },	/* MARU KATAKANA wo   */
+	{  { 0x33FE }, { 0,1,0 }  },	/* CJK IDEO.TEL.31th  */
+#else
+	{  { 0x3191 }, { 0,0,0 }  },	/* KANBUN REV.MARK    */
+	{  { 0x3243 }, { 0,0,0 }  },	/* IDEO. MARK (reach) */
+	{  { 0x32CB }, { 0,0,0 }  },	/* IDEO.TEL.SYM.DEC12 */
+	{  { 0x32FE }, { 0,0,0 }  },	/* MARU KATAKANA wo   */
+	{  { 0x33FE }, { 0,0,0 }  },	/* CJK IDEO.TEL.31th  */
+#endif
+	{  { 0x4E00 }, { 0,1,0 }  },	/* CJK UNI.IDEO.      */  /* 20 */
+	{  { 0x4E05 }, { 0,1,0 }  },	/* CJK UNI.IDEO.      */
+	{  { 0x4E06 }, { 0,1,0 }  },	/* CJK UNI.IDEO.NON-J */
+	{  { 0x4E07 }, { 0,1,0 }  },	/* CJK UNI.IDEO.      */
+	{  { 0x4FFF }, { 0,1,0 }  },	/* CJK UNI.IDEO.      */
+	{  { 0x9000 }, { 0,1,0 }  },	/* CJK UNI.IDEO.      */
+	{  { 0x9006 }, { 0,1,0 }  },	/* CJK UNI.IDEO.      */
+	{  { 0x9007 }, { 0,1,0 }  },	/* CJK UNI.IDEO.NON-J */
+	{  { 0x9FA4 }, { 0,1,0 }  },	/* CJK UNI.IDEO.NON-J */
+	{  { 0x9FA5 }, { 0,1,0 }  },	/* CJK UNI.IDEO.      */
+#ifdef SHOJI_IS_RIGHT
+	{  { 0xFE4F }, { 0,1,0 }  },	/* CJK UNI.IDEO.      */  /* 30 */
+#else
+	{  { 0xFE4F }, { 0,0,0 }  },	/* CJK UNI.IDEO.      */  /* 30 */
+#endif
+	{  { 0xFF0F }, { 0,0,0 }  },	/* FULL SLASH	      */
+	{  { 0xFF19 }, { 0,1,0 }  },	/* FULL 9	      */
+	{  { 0xFF20 }, { 0,0,0 }  },	/* FULL @	      */
+	{  { 0xFF3A }, { 0,1,0 }  },	/* FULL Z	      */
+	{  { 0xFF40 }, { 0,0,0 }  },	/* FULL GRAVE ACC.    */
+	{  { 0xFF5A }, { 0,1,0 }  },	/* FULL z	      */
+	{  { 0xFF5E }, { 0,0,0 }  },	/* FULL ~ (tilde)     */
+	{  { 0xFF61 }, { 0,0,0 }  },	/* HALF IDEO.STOP. .  */
+	{  { 0xFF65 }, { 0,0,0 }  },	/* HALF KATA MID.DOT  */
+	{  { 0xFF66 }, { 0,1,0 }  },	/* HALF KATA WO	      */  /* 40 */
+	{  { 0xFF6F }, { 0,1,0 }  },	/* HALF KATA tu	      */
+	{  { 0xFF70 }, { 0,1,0 }  },	/* HALF KATA PL -     */
+	{  { 0xFF71 }, { 0,1,0 }  },	/* HALF KATA A	      */
+	{  { 0xFF9E }, { 0,1,0 }  },	/* HALF KATA MI	      */
+	{ .is_last = 1 }		/* Last element.  */
+      }
+  },
+  {   TST_ISW_REC (end, punct) }
+};
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_iswspace.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_iswspace.c
new file mode 100644
index 00000000..2131b87a
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_iswspace.c
@@ -0,0 +1,129 @@
+/*
+ *  TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY
+ *
+ *	 FILE:	dat_iswspace.c
+ *
+ *	 ISW*:	int iswspace (wint_t wc);
+ */
+
+
+#include "dat_isw-funcs.h"
+
+
+TST_ISW_LOC (SPACE, space) = {
+
+  {   TST_ISW_REC (de, space)
+      {
+	{  { 0x0080 }, { 0,1,0 }  },	/* CTRL	    */
+	{  { 0x009F }, { 0,1,0 }  },	/* CTRL	    */
+	{  { 0x00A0 }, { 0,1,0 }  },	/* NB SPACE */
+	{  { 0x00A1 }, { 0,1,0 }  },	/* UD !	    */
+	{  { 0x00B0 }, { 0,1,0 }  },	/* Degree   */
+	{  { 0x00B1 }, { 0,1,0 }  },	/* +- sign  */
+	{  { 0x00B2 }, { 0,1,0 }  },	/* SUP 2    */
+	{  { 0x00B3 }, { 0,1,0 }  },	/* SUP 3    */
+	{  { 0x00B4 }, { 0,1,0 }  },	/* ACUTE    */
+	{  { 0x00B8 }, { 0,1,0 }  },	/* CEDILLA  */
+	{  { 0x00B9 }, { 0,1,0 }  },	/* SUP 1    */
+	{  { 0x00BB }, { 0,1,0 }  },	/* >>	    */
+	{  { 0x00BC }, { 0,1,0 }  },	/* 1/4	    */
+	{  { 0x00BD }, { 0,1,0 }  },	/* 1/2	    */
+	{  { 0x00BE }, { 0,1,0 }  },	/* 3/4	    */
+	{  { 0x00BF }, { 0,1,0 }  },	/* UD ?	    */
+	{  { 0x00C0 }, { 0,1,0 }  },	/* A Grave  */
+	{  { 0x00D6 }, { 0,1,0 }  },	/* O dia    */
+	{  { 0x00D7 }, { 0,1,0 }  },	/* multipl. */
+	{  { 0x00D8 }, { 0,1,0 }  },	/* O stroke */
+	{  { 0x00DF }, { 0,1,0 }  },	/* small Sh */
+	{  { 0x00E0 }, { 0,1,0 }  },	/* a grave  */
+	{  { 0x00F6 }, { 0,1,0 }  },	/* o dia    */
+	{  { 0x00F7 }, { 0,1,0 }  },	/* division */
+	{  { 0x00F8 }, { 0,1,0 }  },	/* o stroke */
+	{  { 0x00FF }, { 0,1,0 }  },	/* y dia    */
+	{ .is_last = 1 }		/* Last element.  */
+      }
+  },
+  {   TST_ISW_REC (enUS, space)
+      {
+	{  { WEOF   }, { 0,1,0 }  },
+	{  { 0x0000 }, { 0,1,0 }  },
+	{  { 0x0008 }, { 0,1,0 }  },
+	{  { 0x0009 }, { 0,0,0 }  },
+	{  { 0x000D }, { 0,0,0 }  },
+	{  { 0x000E }, { 0,1,0 }  },
+	{  { 0x001F }, { 0,1,0 }  },
+	{  { 0x0020 }, { 0,0,0 }  },
+	{  { 0x0021 }, { 0,1,0 }  },
+	{  { 0x002F }, { 0,1,0 }  },
+	{  { 0x0030 }, { 0,1,0 }  },
+	{  { 0x0039 }, { 0,1,0 }  },
+	{  { 0x003A }, { 0,1,0 }  },
+	{  { 0x0040 }, { 0,1,0 }  },
+	{  { 0x0041 }, { 0,1,0 }  },
+	{  { 0x005A }, { 0,1,0 }  },
+	{  { 0x005B }, { 0,1,0 }  },
+	{  { 0x0060 }, { 0,1,0 }  },
+	{  { 0x0061 }, { 0,1,0 }  },
+	{  { 0x007A }, { 0,1,0 }  }, /* 20 */
+	{  { 0x007B }, { 0,1,0 }  },
+	{  { 0x007E }, { 0,1,0 }  },
+	{  { 0x007F }, { 0,1,0 }  },
+	{  { 0x0080 }, { 0,1,0 }  },
+	{ .is_last = 1 }		/* Last element.  */
+      }
+  },
+#if 0
+  {   TST_ISW_REC (eucJP, space)
+#else
+  {   TST_ISW_REC (ja_UTF8, space)
+#endif
+      {
+	{  { 0x3000 }, { 0,0,0 }  },	/* IDEO. SPACE	      */
+	{  { 0x3020 }, { 0,1,0 }  },	/* POSTAL MARK FACE   */
+	{  { 0x3029 }, { 0,1,0 }  },	/* Hangzhou NUM9      */
+	{  { 0x302F }, { 0,1,0 }  },	/* Diacritics(Hangul) */
+	{  { 0x3037 }, { 0,1,0 }  },	/* Separator Symbol   */
+	{  { 0x303F }, { 0,1,0 }  },	/* IDEO. HALF SPACE   */  /* No JIS */
+	{  { 0x3041 }, { 0,1,0 }  },	/* HIRAGANA a	      */
+	{  { 0x3094 }, { 0,1,0 }  },	/* HIRAGANA u"	      */
+	{  { 0x3099 }, { 0,1,0 }  },	/* SOUND MARK	      */
+	{  { 0x309E }, { 0,1,0 }  },	/* ITERATION MARK     */
+	{  { 0x30A1 }, { 0,1,0 }  },	/* KATAKANA a	      */
+	{  { 0x30FA }, { 0,1,0 }  },	/* KATAKANA wo"	      */
+	{  { 0x30FB }, { 0,1,0 }  },	/* KATAKANA MID.DOT   */
+	{  { 0x30FE }, { 0,1,0 }  },	/* KATAKANA ITERATION */
+	{  { 0x3191 }, { 0,1,0 }  },	/* KANBUN REV.MARK    */
+	{  { 0x3243 }, { 0,1,0 }  },	/* IDEO. MARK (reach) */
+	{  { 0x32CB }, { 0,1,0 }  },	/* IDEO.TEL.SYM.DEC12 */
+	{  { 0x32FE }, { 0,1,0 }  },	/* MARU KATAKANA wo   */
+	{  { 0x33FE }, { 0,1,0 }  },	/* CJK IDEO.TEL.31th  */
+	{  { 0x4E00 }, { 0,1,0 }  },	/* CJK UNI.IDEO.      */
+	{  { 0x4E05 }, { 0,1,0 }  },	/* CJK UNI.IDEO.      */
+	{  { 0x4E06 }, { 0,1,0 }  },	/* CJK UNI.IDEO.NON-J */
+	{  { 0x4E07 }, { 0,1,0 }  },	/* CJK UNI.IDEO.      */
+	{  { 0x4FFF }, { 0,1,0 }  },	/* CJK UNI.IDEO.      */
+	{  { 0x9000 }, { 0,1,0 }  },	/* CJK UNI.IDEO.      */
+	{  { 0x9006 }, { 0,1,0 }  },	/* CJK UNI.IDEO.      */
+	{  { 0x9007 }, { 0,1,0 }  },	/* CJK UNI.IDEO.NON-J */
+	{  { 0x9FA4 }, { 0,1,0 }  },	/* CJK UNI.IDEO.NON-J */
+	{  { 0x9FA5 }, { 0,1,0 }  },	/* CJK UNI.IDEO.      */
+	{  { 0xFE4F }, { 0,1,0 }  },	/* CJK UNI.IDEO.      */
+	{  { 0xFF0F }, { 0,1,0 }  },	/* FULL SLASH	      */
+	{  { 0xFF19 }, { 0,1,0 }  },	/* FULL 9	      */
+	{  { 0xFF20 }, { 0,1,0 }  },	/* FULL @	      */
+	{  { 0xFF3A }, { 0,1,0 }  },	/* FULL Z	      */
+	{  { 0xFF40 }, { 0,1,0 }  },	/* FULL GRAVE ACC.    */
+	{  { 0xFF5A }, { 0,1,0 }  },	/* FULL z	      */
+	{  { 0xFF5E }, { 0,1,0 }  },	/* FULL ~ (tilde)     */
+	{  { 0xFF61 }, { 0,1,0 }  },	/* HALF IDEO.STOP. .  */
+	{  { 0xFF65 }, { 0,1,0 }  },	/* HALF KATA MID.DOT  */
+	{  { 0xFF66 }, { 0,1,0 }  },	/* HALF KATA WO	      */
+	{  { 0xFF6F }, { 0,1,0 }  },	/* HALF KATA tu	      */
+	{  { 0xFF70 }, { 0,1,0 }  },	/* HALF KATA PL -     */
+	{  { 0xFF71 }, { 0,1,0 }  },	/* HALF KATA A	      */
+	{  { 0xFF9E }, { 0,1,0 }  },	/* HALF KATA MI	      */
+	{ .is_last = 1 }		/* Last element.  */
+      }
+  },
+  {   TST_ISW_REC (end, space) }
+};
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_iswupper.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_iswupper.c
new file mode 100644
index 00000000..865f42fe
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_iswupper.c
@@ -0,0 +1,94 @@
+/*
+ *  TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY
+ *
+ *	 FILE:	dat_iswupper.c
+ *
+ *	 ISW*:	int iswupper (wint_t wc);
+ */
+
+
+#include "dat_isw-funcs.h"
+
+
+TST_ISW_LOC (UPPER, upper) = {
+
+  {   TST_ISW_REC (de, upper)
+      {
+	{  { 0x0080 }, { 0,1,0 }  },	/* CTRL	    */
+	{  { 0x009F }, { 0,1,0 }  },	/* CTRL	    */
+	{  { 0x00A0 }, { 0,1,0 }  },	/* NB SPACE */
+	{  { 0x00A1 }, { 0,1,0 }  },	/* UD !	    */
+	{  { 0x00B0 }, { 0,1,0 }  },	/* Degree   */
+	{  { 0x00B1 }, { 0,1,0 }  },	/* +- sign  */
+	{  { 0x00B2 }, { 0,1,0 }  },	/* SUP 2    */
+	{  { 0x00B3 }, { 0,1,0 }  },	/* SUP 3    */
+	{  { 0x00B4 }, { 0,1,0 }  },	/* ACUTE    */
+	{  { 0x00B8 }, { 0,1,0 }  },	/* CEDILLA  */
+	{  { 0x00B9 }, { 0,1,0 }  },	/* SUP 1    */
+	{  { 0x00BB }, { 0,1,0 }  },	/* >>	    */
+	{  { 0x00BC }, { 0,1,0 }  },	/* 1/4	    */
+	{  { 0x00BD }, { 0,1,0 }  },	/* 1/2	    */
+	{  { 0x00BE }, { 0,1,0 }  },	/* 3/4	    */
+	{  { 0x00BF }, { 0,1,0 }  },	/* UD ?	    */
+	{  { 0x00C0 }, { 0,0,0 }  },	/* A Grave  */
+	{  { 0x00D6 }, { 0,0,0 }  },	/* O dia    */
+	{  { 0x00D7 }, { 0,1,0 }  },	/* multipl. */
+	{  { 0x00D8 }, { 0,0,0 }  },	/* O stroke */
+	{  { 0x00DF }, { 0,1,0 }  },	/* small Sh */
+	{  { 0x00E0 }, { 0,1,0 }  },	/* a grave  */
+	{  { 0x00F6 }, { 0,1,0 }  },	/* o dia    */
+	{  { 0x00F7 }, { 0,1,0 }  },	/* division */
+	{  { 0x00F8 }, { 0,1,0 }  },	/* o stroke */
+	{  { 0x00FF }, { 0,1,0 }  },	/* y dia    */
+	{ .is_last = 1 }		/* Last entry.	*/
+      }
+  },
+  {   TST_ISW_REC (enUS, upper)
+      {
+	{  { WEOF   }, { 0,1,0 }  },
+	{  { 0x0000 }, { 0,1,0 }  },
+	{  { 0x001F }, { 0,1,0 }  },
+	{  { 0x0020 }, { 0,1,0 }  },
+	{  { 0x0021 }, { 0,1,0 }  },
+	{  { 0x002F }, { 0,1,0 }  },
+	{  { 0x0030 }, { 0,1,0 }  },
+	{  { 0x0039 }, { 0,1,0 }  },
+	{  { 0x003A }, { 0,1,0 }  },
+	{  { 0x0040 }, { 0,1,0 }  },
+	{  { 0x0041 }, { 0,0,0 }  },
+	{  { 0x005A }, { 0,0,0 }  },
+	{  { 0x005B }, { 0,1,0 }  },
+	{  { 0x0060 }, { 0,1,0 }  },
+	{  { 0x0061 }, { 0,1,0 }  },
+	{  { 0x007A }, { 0,1,0 }  },
+	{  { 0x007B }, { 0,1,0 }  },
+	{  { 0x007E }, { 0,1,0 }  },
+	{  { 0x007F }, { 0,1,0 }  },
+	{  { 0x0080 }, { 0,1,0 }  },
+	{ .is_last = 1 }		/* Last entry.  */
+      }
+  },
+#if 0
+  {   TST_ISW_REC (eucJP, upper)
+#else
+  {   TST_ISW_REC (ja_UTF8, upper)
+#endif
+      {
+	{  { 0x3041 }, { 0,1,0 }  },	/* HIRAGANA a	      */
+	{  { 0x3094 }, { 0,1,0 }  },	/* HIRAGANA u"	      */
+	{  { 0x30A1 }, { 0,1,0 }  },	/* KATAKANA a	      */
+	{  { 0x30FA }, { 0,1,0 }  },	/* KATAKANA wo"	      */
+	{  { 0xFF19 }, { 0,1,0 }  },	/* FULL 9	      */
+	{  { 0xFF20 }, { 0,1,0 }  },	/* FULL @	      */
+	{  { 0xFF3A }, { 0,0,0 }  },	/* FULL Z	      */
+	{  { 0xFF40 }, { 0,1,0 }  },	/* FULL GRAVE ACC.    */
+	{  { 0xFF5A }, { 0,1,0 }  },	/* FULL z	      */
+	{  { 0xFF66 }, { 0,1,0 }  },	/* HALF KATA WO	      */
+	{  { 0xFF6F }, { 0,1,0 }  },	/* HALF KATA tu	      */
+	{  { 0xFF71 }, { 0,1,0 }  },	/* HALF KATA A	      */
+	{  { 0xFF9E }, { 0,1,0 }  },	/* HALF KATA MI	      */
+	{ .is_last = 1 }		/* Last entry.	*/
+      }
+  },
+  {   TST_ISW_REC (end, upper) }
+};
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_iswxdigit.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_iswxdigit.c
new file mode 100644
index 00000000..5d6c652f
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_iswxdigit.c
@@ -0,0 +1,125 @@
+/*
+ *  TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY
+ *
+ *	 FILE:	dat_iswxdigit.c
+ *
+ *	 ISW*:	int iswxdigit (wint_t wc);
+ */
+
+
+#include "dat_isw-funcs.h"
+
+
+TST_ISW_LOC (XDIGIT, xdigit) = {
+
+  {   TST_ISW_REC (de, xdigit)
+      {
+	{  { 0x0080 }, { 0,1,0 }  },	/* CTRL	    */
+	{  { 0x009F }, { 0,1,0 }  },	/* CTRL	    */
+	{  { 0x00A0 }, { 0,1,0 }  },	/* NB SPACE */
+	{  { 0x00A1 }, { 0,1,0 }  },	/* UD !	    */
+	{  { 0x00B0 }, { 0,1,0 }  },	/* Degree   */
+	{  { 0x00B1 }, { 0,1,0 }  },	/* +- sign  */
+	{  { 0x00B2 }, { 0,1,0 }  },	/* SUP 2    */
+	{  { 0x00B3 }, { 0,1,0 }  },	/* SUP 3    */
+	{  { 0x00B4 }, { 0,1,0 }  },	/* ACUTE    */
+	{  { 0x00B8 }, { 0,1,0 }  },	/* CEDILLA  */
+	{  { 0x00B9 }, { 0,1,0 }  },	/* SUP 1    */
+	{  { 0x00BB }, { 0,1,0 }  },	/* >>	    */
+	{  { 0x00BC }, { 0,1,0 }  },	/* 1/4	    */
+	{  { 0x00BD }, { 0,1,0 }  },	/* 1/2	    */
+	{  { 0x00BE }, { 0,1,0 }  },	/* 3/4	    */
+	{  { 0x00BF }, { 0,1,0 }  },	/* UD ?	    */
+	{  { 0x00C0 }, { 0,1,0 }  },	/* A Grave  */
+	{  { 0x00D6 }, { 0,1,0 }  },	/* O dia    */
+	{  { 0x00D7 }, { 0,1,0 }  },	/* multipl. */
+	{  { 0x00D8 }, { 0,1,0 }  },	/* O stroke */
+	{  { 0x00DF }, { 0,1,0 }  },	/* small Sh */
+	{  { 0x00E0 }, { 0,1,0 }  },	/* a grave  */
+	{  { 0x00F6 }, { 0,1,0 }  },	/* o dia    */
+	{  { 0x00F7 }, { 0,1,0 }  },	/* division */
+	{  { 0x00F8 }, { 0,1,0 }  },	/* o stroke */
+	{  { 0x00FF }, { 0,1,0 }  },	/* y dia    */
+	{ .is_last = 1 }		/* Last element.  */
+      }
+  },
+  {   TST_ISW_REC( enUS, xdigit )
+      {
+	{  { WEOF   }, { 0,1,0 }  },
+	{  { 0x0000 }, { 0,1,0 }  },
+	{  { 0x001F }, { 0,1,0 }  },
+	{  { 0x0020 }, { 0,1,0 }  },
+	{  { 0x0021 }, { 0,1,0 }  },
+	{  { 0x002F }, { 0,1,0 }  },
+	{  { 0x0030 }, { 0,0,0 }  },
+	{  { 0x0039 }, { 0,0,0 }  },
+	{  { 0x003A }, { 0,1,0 }  },
+	{  { 0x0040 }, { 0,1,0 }  },
+	{  { 0x0041 }, { 0,0,0 }  },
+	{  { 0x005A }, { 0,1,0 }  },
+	{  { 0x005B }, { 0,1,0 }  },
+	{  { 0x0060 }, { 0,1,0 }  },
+	{  { 0x0061 }, { 0,0,0 }  },
+	{  { 0x007A }, { 0,1,0 }  },
+	{  { 0x007B }, { 0,1,0 }  },
+	{  { 0x007E }, { 0,1,0 }  },
+	{  { 0x007F }, { 0,1,0 }  },
+	{  { 0x0080 }, { 0,1,0 }  },
+	{ .is_last = 1 }		/* Last element.  */
+      }
+  },
+#if 0
+  {   TST_ISW_REC( eucJP, xdigit )
+#else
+  {   TST_ISW_REC( ja_UTF8, xdigit )
+#endif
+      {
+	{  { 0x3000 }, { 0,1,0 }  },	/* IDEO. SPACE	      */
+	{  { 0x3020 }, { 0,1,0 }  },	/* POSTAL MARK FACE   */
+	{  { 0x3029 }, { 0,1,0 }  },	/* Hangzhou NUM9      */
+	{  { 0x302F }, { 0,1,0 }  },	/* Diacritics(Hangul) */
+	{  { 0x3037 }, { 0,1,0 }  },	/* Separator Symbol   */
+	{  { 0x303F }, { 0,1,0 }  },	/* IDEO. HALF SPACE   */
+	{  { 0x3041 }, { 0,1,0 }  },	/* HIRAGANA a	      */
+	{  { 0x3094 }, { 0,1,0 }  },	/* HIRAGANA u"	      */
+	{  { 0x3099 }, { 0,1,0 }  },	/* SOUND MARK	      */
+	{  { 0x309E }, { 0,1,0 }  },	/* ITERATION MARK     */
+	{  { 0x30A1 }, { 0,1,0 }  },	/* KATAKANA a	      */
+	{  { 0x30FA }, { 0,1,0 }  },	/* KATAKANA wo"	      */
+	{  { 0x30FB }, { 0,1,0 }  },	/* KATAKANA MID.DOT   */
+	{  { 0x30FE }, { 0,1,0 }  },	/* KATAKANA ITERATION */
+	{  { 0x3191 }, { 0,1,0 }  },	/* KANBUN REV.MARK    */
+	{  { 0x3243 }, { 0,1,0 }  },	/* IDEO. MARK (reach) */
+	{  { 0x32CB }, { 0,1,0 }  },	/* IDEO.TEL.SYM.DEC12 */
+	{  { 0x32FE }, { 0,1,0 }  },	/* MARU KATAKANA wo   */
+	{  { 0x33FE }, { 0,1,0 }  },	/* CJK IDEO.TEL.31th  */
+	{  { 0x4E00 }, { 0,1,0 }  },	/* CJK UNI.IDEO.      */
+	{  { 0x4E05 }, { 0,1,0 }  },	/* CJK UNI.IDEO.      */
+	{  { 0x4E06 }, { 0,1,0 }  },	/* CJK UNI.IDEO.NON-J */
+	{  { 0x4E07 }, { 0,1,0 }  },	/* CJK UNI.IDEO.      */
+	{  { 0x4FFF }, { 0,1,0 }  },	/* CJK UNI.IDEO.      */
+	{  { 0x9000 }, { 0,1,0 }  },	/* CJK UNI.IDEO.      */
+	{  { 0x9006 }, { 0,1,0 }  },	/* CJK UNI.IDEO.      */
+	{  { 0x9007 }, { 0,1,0 }  },	/* CJK UNI.IDEO.NON-J */
+	{  { 0x9FA4 }, { 0,1,0 }  },	/* CJK UNI.IDEO.NON-J */
+	{  { 0x9FA5 }, { 0,1,0 }  },	/* CJK UNI.IDEO.      */
+	{  { 0xFE4F }, { 0,1,0 }  },	/* CJK UNI.IDEO.      */
+	{  { 0xFF0F }, { 0,1,0 }  },	/* FULL SLASH	      */
+	{  { 0xFF19 }, { 0,1,0 }  },	/* FULL 9	      */
+	{  { 0xFF20 }, { 0,1,0 }  },	/* FULL @	      */
+	{  { 0xFF3A }, { 0,1,0 }  },	/* FULL Z	      */
+	{  { 0xFF40 }, { 0,1,0 }  },	/* FULL GRAVE ACC.    */
+	{  { 0xFF5A }, { 0,1,0 }  },	/* FULL z	      */
+	{  { 0xFF5E }, { 0,1,0 }  },	/* FULL ~ (tilde)     */
+	{  { 0xFF61 }, { 0,1,0 }  },	/* HALF IDEO.STOP. .  */
+	{  { 0xFF65 }, { 0,1,0 }  },	/* HALF KATA MID.DOT  */
+	{  { 0xFF66 }, { 0,1,0 }  },	/* HALF KATA WO	      */
+	{  { 0xFF6F }, { 0,1,0 }  },	/* HALF KATA tu	      */
+	{  { 0xFF70 }, { 0,1,0 }  },	/* HALF KATA PL -     */
+	{  { 0xFF71 }, { 0,1,0 }  },	/* HALF KATA A	      */
+	{  { 0xFF9E }, { 0,1,0 }  },	/* HALF KATA MI	      */
+	{ .is_last = 1 }		/* Last element.  */
+      }
+  },
+  {   TST_ISW_REC (end, xdigit) }
+};
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_mblen.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_mblen.c
new file mode 100644
index 00000000..8da038c7
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_mblen.c
@@ -0,0 +1,137 @@
+/*
+ *  TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY
+ *
+ *	 FILE:	dat_mblen.c
+ *
+ *	 MBLEN:	 int mblen (char *s, size_t n);
+ */
+
+
+/*
+ *  NOTE:
+ *	  int  mblen (char *s, size_t n);
+ *
+ *	  where	     n: a maximum number of bytes
+ *
+ *	  return - the number of bytes
+ *
+ *  CAUTION:
+ *
+ *	 o When you feed a null pointer for a string (s) to the function,
+ *	   set s_flg=0 instead of putting just a 'NULL' there.
+ *	   Even if you set a 'NULL', it doens't mean a NULL pointer.
+ *
+ *	 o When s is a null pointer, the function checks state dependency.
+ *
+ *	       state-dependent encoding	     - return  NON-zero
+ *	       state-independent encoding    - return  0
+ *
+ *	   If state-dependent encoding is expected, set
+ *
+ *	       s_flg = 0,  ret_flg = 0,	 ret_val = +1
+ *
+ *	   If state-independent encoding is expected, set
+ *
+ *	       s_flg = 0,  ret_flg = 0,	 ret_val = 0
+ *
+ *
+ *	   When you set ret_flg=1, the test program simply compares an
+ *	   actual return value with an expected value. You can check
+ *	   state-independent case (return value is 0) in that way, but
+ *	   you can not check state-dependent case. So when you check
+ *	   state- dependency in this test function: tst_mblen(), set
+ *	   ret_flg=0 always. It's a special case, and the test
+ *	   function takes care of it.
+ *
+ *	       s_flg=0		 ret_flg=0
+ *	       |		 |
+ *	     { 0, 0 },	 { 0, 0, 0,  x }
+ *		  |		     |
+ *		  not used	     ret_val: 0/+1
+ *				     (expected val) */
+
+
+TST_MBLEN tst_mblen_loc [] = {
+  {
+    { Tmblen, TST_LOC_de },
+    {
+      /* 01: a character.  */
+      {	 { 1, "\300",	   USE_MBCURMAX }, { 0,	1,  1 }	 },
+      /* 02: a character.  */
+      {	 { 1, "\309",	   USE_MBCURMAX }, { 0,	1,  1 }	 },
+      /* 03: a character + an invalid byte.  */
+      {	 { 1, "Z\204",	   USE_MBCURMAX }, { 0,	1, +1 }	 },
+      /* 04: control/invalid characters.  */
+      {	 { 1, "\177\000",  USE_MBCURMAX }, { 0,	1, +1 }	 },
+      /* 05: a null string.  */
+      {	 { 1, "",	   USE_MBCURMAX }, { 0,	1,  0 }	 },
+      /* 06: a null pointer.  */
+      {	 { 0, "",	   USE_MBCURMAX }, { 0,	0,  0 }	 },
+      /* Last element.	*/
+      {	 .is_last = 1 }
+    }
+  },
+  {
+    { Tmblen, TST_LOC_enUS },
+    {
+      /* 01: a character.  */
+      {	 { 1, "A",	   USE_MBCURMAX }, { 0,	1,  1 }	 },
+      /* 02: a character.  */
+      {	 { 1, "a",	   USE_MBCURMAX }, { 0,	1,  1 }	 },
+      /* 03: a character + an invalid byte.  */
+      {	 { 1, "Z\204",	   USE_MBCURMAX }, { 0,	1, +1 }	 },
+      /* 04: control/invalid characters.  */
+      {	 { 1, "\177\000",  USE_MBCURMAX }, { 0,	1, +1 }	 },
+      /* 05: a null string.  */
+      {	 { 1, "",	   USE_MBCURMAX }, { 0,	1,  0 }	 },
+      /* 06: a null pointer.  */
+      {	 { 0, "",	   USE_MBCURMAX }, { 0,	0,  0 }	 },
+      /* Last element.	*/
+      {	 .is_last = 1 }
+    }
+  },
+#if 0
+  {
+    { Tmblen, TST_LOC_eucJP },
+    {
+      /* 01: a character.  */
+      {	 { 1, "\264\301",	   USE_MBCURMAX }, { 0, 1,  2 }	 },
+      /* 02: a character.  */
+      {	 { 1, "\216\261",	   USE_MBCURMAX }, { 0, 1,  2 }  },
+      /* 03: a character + an invalid byte.  */
+      {	 { 1, "\260\241\200",	   USE_MBCURMAX }, { 0, 1,  2 }	 },
+      /* 04: control/invalid characters.  */
+      {	 { 1, "\377\202",  USE_MBCURMAX }, { EILSEQ, 1, -1 }	 },
+      /* 05: a null string.  */
+      {	 { 1, "",	   USE_MBCURMAX }, { 0,	1,  0 }	 },
+      /* 06: a null pointer.  */
+      {	 { 0, "",	   USE_MBCURMAX }, { 0,	0,  0 }	 },
+      /* Last element.	*/
+      {	 .is_last = 1 }
+    }
+  },
+#else
+  {
+    { Tmblen, TST_LOC_ja_UTF8 },
+    {
+      /* 01: a character.  */
+      {	 { 1, "\346\274\242",	   USE_MBCURMAX }, { 0, 1,  3 }	 },
+      /* 02: a character.  */
+      {	 { 1, "\357\275\261",	   USE_MBCURMAX }, { 0, 1,  3 }  },
+      /* 03: a character + an invalid byte.  */
+      {	 { 1, "\345\272\234\200",	   USE_MBCURMAX }, { 0, 1,  3 }	 },
+      /* 04: control/invalid characters.  */
+      {	 { 1, "\377\202",  USE_MBCURMAX }, { EILSEQ, 1, -1 }	 },
+      /* 05: a null string.  */
+      {	 { 1, "",	   USE_MBCURMAX }, { 0,	1,  0 }	 },
+      /* 06: a null pointer.  */
+      {	 { 0, "",	   USE_MBCURMAX }, { 0,	0,  0 }	 },
+      /* Last element.	*/
+      {	 .is_last = 1 }
+    }
+  },
+#endif
+  {
+    { Tmblen, TST_LOC_end}
+  }
+};
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_mbrlen.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_mbrlen.c
new file mode 100644
index 00000000..63ae19fb
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_mbrlen.c
@@ -0,0 +1,222 @@
+/*
+ *  TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY
+ *
+ *	 FILE:	dat_mbrlen.c
+ *
+ *	 MBRLEN:  size_t mbrlen (const char *s, size_t n, mbstate_t *ps);
+ */
+
+/*
+ *  NOTE:
+ *	  (1) A mbstate object is initialized for
+ *	      every new data record by the test program.
+ *
+ *	  (2) USE_MBCURMAX is defined as a value of 99.
+ *
+ */
+
+
+TST_MBRLEN tst_mbrlen_loc [] = {
+  {
+    { Tmbrlen, TST_LOC_de },
+    {
+      { /*----------------- #01 -----------------*/
+	{
+	  {
+	    { 1, "",	   0,		   0, 0 },
+	    { 1, "",	   1,		   0, 0 },
+	    { 1, "\300",	   USE_MBCURMAX,   0, 0 },
+	  }
+	},
+	{
+	  {
+	    { 0,		1,  0,		     },
+	    { 0,		1,  0,		     },
+	    { 0,		1,  1,		     },
+	  }
+	}
+      },
+      { /*----------------- #02 -----------------*/
+	{
+	  {
+	    { 1, "\300\001",   0,		   0, 0 },
+	    { 1, "\300\001",   1,		   0, 0 },
+	    { 1, "\317\001",   USE_MBCURMAX,   0, 0 },
+	  }
+	},
+	{
+	  {
+	    { 0,		1,  0,		     },
+	    { 0,		1,  1,		     },
+	    { 0,		1,  1,		     },
+	  }
+	}
+      },
+      { .is_last = 1 }
+    }
+  },
+  {
+    { Tmbrlen, TST_LOC_enUS },
+    {
+      { /*----------------- #01 -----------------*/
+	{
+	  {
+	    { 1, "A",	   0,		   0, 0 },
+	    { 1, "A",	   1,		   0, 0 },
+	    { 1, "A",	   USE_MBCURMAX,   0, 0 },
+	  }
+	},
+	{
+	  {
+	    { 0,		1,  0,		     },
+	    { 0,		1,  1,		     },
+	    { 0,		1,  1,		     },
+	  }
+	}
+      },
+      { /*----------------- #02 -----------------*/
+	{
+	  {
+	    { 1, "\317\001",   0,		   1, 0 },
+	    { 1, "\317\001",   1,		   1, 0 },
+	    { 1, "\317\001",   USE_MBCURMAX,   1, 0 },
+	  }
+	},
+	{
+	  {
+	    { 0,		1,  0,		     },
+	    { EILSEQ,	1, -1,		     },
+	    { EILSEQ,	1, -1,		     },
+	  }
+	}
+      },
+      { .is_last = 1 }
+    }
+  },
+#if 0
+  {
+    { Tmbrlen, TST_LOC_eucJP },
+    {
+      { /*----------------- #01 -----------------*/
+	{
+	  {
+	    { 1, "\317\302",   1,		   1, 1 },
+	    { 0, "",	       0,		   1, 0 },
+	    { 1, "\317\302",   USE_MBCURMAX,	   1, 1 },
+	  }
+	},
+	{
+	  {
+	    { 0,		1, -2,		     },
+	    { 0,		1, -1,		     },
+	    { 0,		1,  2,		     },
+	  }
+	}
+      },
+      { /*----------------- #02 -----------------*/
+	{
+	  {
+	    { 1, "\317",	   1,		   1, 0 },
+	    { 1, "\302",	   1,		   1, 0 },
+	    { 1, "\317\302",   USE_MBCURMAX,   0, 0 },
+	  }
+	},
+	{
+	  {
+	    { 0,		1, -2,		     },
+#ifdef SHOJI_IS_RIGHT
+	    { 0,		1, +2,		     },
+#else
+	    /* XXX ISO C explicitly says that the return value does not
+	       XXX reflect the bytes contained in the state.  */
+	    { 0,		1, +1,		     },
+#endif
+	    { 0,		1,  2,		     },
+	  }
+	}
+      },
+      { /*----------------- #03 -----------------*/
+	{
+	  {
+	    { 1, "\216\217",   0,		   0, 0 },
+	    { 1, "\216\217",   1,		   0, 0 },
+	    { 1, "\216\217",   USE_MBCURMAX,   0, 0 },
+	  }
+	},
+	{
+	  {
+	    { 0,		1,  0,		     },
+	    { 0,		1, -2,		     },
+	    { EILSEQ,	1, -1,		     },
+	  }
+	}
+      },
+      { .is_last = 1 }
+    }
+  },
+#else
+  {
+    { Tmbrlen, TST_LOC_ja_UTF8 },
+    {
+      { /*----------------- #01 -----------------*/
+	{
+	  {
+	    { 1, "\345\222\214",   1,		   1, 1 },
+	    { 0, "",	       0,		   1, 0 },
+	    { 1, "\345\222\214",   USE_MBCURMAX,	   1, 1 },
+	  }
+	},
+	{
+	  {
+	    { 0,		1, -2,		     },
+	    { 0,		1, -1,		     },
+	    { 0,		1,  3,		     },
+	  }
+	}
+      },
+      { /*----------------- #02 -----------------*/
+	{
+	  {
+	    { 1, "\317",	   1,		   1, 0 },
+	    { 1, "\266",	   1,		   1, 0 },
+	    { 1, "\345\222\214",   USE_MBCURMAX,   0, 0 },
+	  }
+	},
+	{
+	  {
+	    { 0,		1, -2,		     },
+#ifdef SHOJI_IS_RIGHT
+	    { 0,		1, +2,		     },
+#else
+	    /* XXX ISO C explicitly says that the return value does not
+	       XXX reflect the bytes contained in the state.  */
+	    { 0,		1, +1,		     },
+#endif
+	    { 0,		1,  3,		     },
+	  }
+	}
+      },
+      { /*----------------- #03 -----------------*/
+	{
+	  {
+	    { 1, "\302\303",   0,		   0, 0 },
+	    { 1, "\302\303",   1,		   0, 0 },
+	    { 1, "\302\303",   USE_MBCURMAX,   0, 0 },
+	  }
+	},
+	{
+	  {
+	    { 0,		1,  0,		     },
+	    { 0,		1, -2,		     },
+	    { EILSEQ,	1, -1,		     },
+	  }
+	}
+      },
+      { .is_last = 1 }
+    }
+  },
+#endif
+  {
+    { Tmbrlen, TST_LOC_end }
+  }
+};
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_mbrtowc.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_mbrtowc.c
new file mode 100644
index 00000000..b8eb3dd2
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_mbrtowc.c
@@ -0,0 +1,140 @@
+/*
+ *  TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY
+ *
+ *	 FILE:	dat_mbrtowc.c
+ *
+ *	 MBTOWC:  size_t mbrtowc (wchar_t *pwc, char *s, size_t n,
+ *				  mbstate_t *ps);
+ */
+
+#include 
+
+/* Note:
+	assumes	 en_US = en_US.ascii
+*/
+
+
+
+
+TST_MBRTOWC tst_mbrtowc_loc [] = {
+  {
+    { Tmbrtowc, TST_LOC_de },
+    {
+      { /*----------------- #01 -----------------*/
+	{
+	  {
+	    { 1, 1, "ÄÖÜ",	   1,		 0, 0 },
+	    { 1, 1, "ÄÖÜ",	   2,		 0, 0 },
+	    { 1, 1, "ÄÖÜ",	   USE_MBCURMAX, 0, 0 },
+	  }
+	},
+	{
+	  {
+	    { 0,  1,  1,   0x00C4 },
+	    { 0,  1,  1,   0x00C4 },
+	    { 0,  1,  1,   0x00C4 },
+	  }
+	}
+      },
+      { /*----------------- #02 -----------------*/
+	{
+	  {
+	    { 1, 1, "ÄÖÜ",	    1,		  0, 0 },
+	    { 1, 1, "ÄÖÜ",	    2,		  0, 0 },
+	    { 1, 1, "ÄÖÜ",	    USE_MBCURMAX, 0, 0 },
+	  }
+	},
+	{
+	  {
+	    { 0,  1,  1,   0x00C4 },
+	    { 0,  1,  1,   0x00C4 },
+	    { 0,  1,  1,   0x00C4 },
+	  }
+	}
+      },
+      { .is_last = 1 }
+    }
+  },
+#if 0
+  /* XXX: These tests don't make sense to me.  */
+  {
+    { Tmbrtowc, TST_LOC_enUS },
+    {
+      { /*----------------- #01 -----------------*/
+	{
+	  {
+	    { 1, 1, "ÄÖÜ",	    1,		  0, 0 },
+	    { 1, 1, "ÄÖÜ",	    2,		  0, 0 },
+	    { 1, 1, "ÄÖÜ",	    USE_MBCURMAX, 0, 0 },
+	  }
+	},
+	{
+	  {
+	    { 0,  1,  1,   0x00C4 },
+	    { 0,  1,  1,   0x00C4 },
+	    { 0,  1,  1,   0x00C4 },
+	  }
+	}
+      },
+      { /*----------------- #02 -----------------*/
+	{
+	  {
+	    { 1, 1, "ÄÖÜ",	    1,		  0, 0 },
+	    { 1, 1, "ÄÖÜ",	    2,		  0, 0 },
+	    { 1, 1, "ÄÖÜ",	    USE_MBCURMAX, 0, 0 },
+	  }
+	},
+	{
+	  {
+	    { 0,  1,  1,   0x00C4 },
+	    { 0,  1,  1,   0x00C4 },
+	    { 0,  1,  1,   0x00C4 },
+	  }
+	}
+      },
+      { .is_last = 1 }
+    }
+  },
+  {
+    { Tmbrtowc, TST_LOC_eucJP },
+    {
+      { /*----------------- #01 -----------------*/
+	{
+	  {
+	    { 1, 1, "ÄÖÜ",	    1,		  0, 0 },
+	    { 1, 1, "ÄÖÜ",	    2,		  0, 0 },
+	    { 1, 1, "ÄÖÜ",	    USE_MBCURMAX, 0, 0 },
+	  }
+	},
+	{
+	  {
+	    { 0,  1,  1,   0x00C4 },
+	    { 0,  1,  1,   0x00C4 },
+	    { 0,  1,  1,   0x00C4 },
+	  }
+	}
+      },
+      { /*----------------- #02 -----------------*/
+	{
+	  {
+	    { 1, 1, "ÄÖÜ",	    1,		  0, 0 },
+	    { 1, 1, "ÄÖÜ",	    2,		  0, 0 },
+	    { 1, 1, "ÄÖÜ",	    USE_MBCURMAX, 0, 0 },
+	  }
+	},
+	{
+	  {
+	    { 0,  1,  1,   0x00C4 },
+	    { 0,  1,  1,   0x00C4 },
+	    { 0,  1,  1,   0x00C4 },
+	  }
+	}
+      },
+      { .is_last = 1 }
+    }
+  },
+#endif
+  {
+    { Tmbrtowc, TST_LOC_end }
+  }
+};
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_mbsrtowcs.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_mbsrtowcs.c
new file mode 100644
index 00000000..30a0a6c0
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_mbsrtowcs.c
@@ -0,0 +1,180 @@
+/*
+ *  TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY
+ *
+ *	 FILE:	dat_mbsrtowcs.c
+ *
+ *	 MBSRTOWCS:  size_t mbsrtowcs (wchar_t *ws, char **s, size_t n,
+ *				       mbstate_t *ps);
+ */
+
+
+TST_MBSRTOWCS tst_mbsrtowcs_loc [] = {
+  {
+    { Tmbsrtowcs, TST_LOC_de },
+    {
+      { /*----------------- #01 -----------------*/
+	{
+	  {
+	    { 1,  "üäö",	    4,			 0,0 },
+	    { 1,  "üäö",	    3,			 0,0 },
+	    { 1,  "üäö",	    2,			 0,0 },
+	  }
+	},
+	{
+	  {
+	    { 0,1,3, { 0x00FC,0x00E4,0x00F6,0x0000 }	     },
+	    { 0,1,3, { 0x00FC,0x00E4,0x00F6,0x0000 }	     },
+	    { 0,1,2, { 0x00FC,0x00E4,0x00F6,0x0000 }	     },
+	  }
+	}
+      },
+      { /*----------------- #02 -----------------*/
+	{
+	  {
+	    { 1,  "üäö",	    4,			 0,0 },
+	    { 1,  "",		    1,			 0,0 },
+	    { 0,  "üäö",	    4,			 0,0 },
+	  }
+	},
+	{
+	  {
+	    { 0,1,3, { 0x00FC,0x00E4,0x00F6,0x0000 }	     },
+	    { 0,1,0, { 0x0000 }			     },
+	    { 0,1,3, { 0x0000 }			     },
+	  }
+	}
+      },
+      { /*----------------- END -----------------*/
+	.is_last = 1
+      }
+    }
+  },
+
+  {
+    { Tmbsrtowcs, TST_LOC_enUS },
+    {
+      { /*----------------- #01 -----------------*/
+	{
+	  {
+	    { 1,  "ABC",	    4,			 0,0 },
+	    { 1,  "ABC",	    3,			 0,0 },
+	    { 1,  "ABC",	    2,			 0,0 },
+	  }
+	},
+	{
+	  {
+	    { 0,1,3, { 0x0041,0x0042,0x0043,0x0000 }	     },
+	    { 0,1,3, { 0x0041,0x0042,0x0043,0x0000 }	     },
+	    { 0,1,2, { 0x0041,0x0042,0x0043,0x0000 }	     },
+	  }
+	}
+      },
+      { /*----------------- #02 -----------------*/
+	{
+	  {
+	    { 1,  "ABC",	    4,			 0,0 },
+	    { 1,  "",		    1,			 0,0 },
+	    { 0,  "ABC",	    4,			 0,0 },
+	  }
+	},
+	{
+	  {
+	    { 0,1,3, { 0x0041,0x0042,0x0043,0x0000 }	     },
+	    { 0,1,0, { 0x0000 }			     },
+	    { 0,1,3, { 0x0000 }			     },
+	  }
+	}
+      },
+      { /*----------------- END -----------------*/
+	.is_last = 1
+      }
+    }
+  },
+
+#if 0
+  {
+    { Tmbsrtowcs, TST_LOC_eucJP },
+    {
+      { /*----------------- #01 -----------------*/
+	{
+	  {
+	    { 1,  "\244\242\244\244\244\246ABC",      7, 0,0 },
+	    { 1,  "\244\242\244\244\244\246ABC",      6, 0,0 },
+	    { 1,  "\244\242\244\244\244\246ABC",      4, 0,0 },
+	  }
+	},
+	{
+	  {
+	    { 0,1,6, { 0x3042,0x3044,0x3046,0x0041,0x0042,0x0043,0x0000 }},
+	    { 0,1,6, { 0x3042,0x3044,0x3046,0x0041,0x0042,0x0043,0x0000 }},
+	    { 0,1,4, { 0x3042,0x3044,0x3046,0x0041,0x0000 }		   },
+	  }
+	}
+      },
+      { /*----------------- #02 -----------------*/
+	{
+	  {
+	    { 1,  "\244\242\244\244\244\246ABC",      7, 0,0 },
+	    { 1,  "",		      1, 0,0 },
+	    { 0,  "\244\242\244\244\244\246ABC",      7, 0,0 },
+	  }
+	},
+	{
+	  {
+	    { 0,1,6, { 0x3042,0x3044,0x3046,0x0041,0x0042,0x0043,0x0000 }},
+	    { 0,1,0, { 0x0000 }					   },
+	    { 0,1,6, { 0x0000 }					   },
+	  }
+	}
+      },
+      { /*----------------- END -----------------*/
+	.is_last = 1
+      }
+    }
+  },
+#else
+  {
+    { Tmbsrtowcs, TST_LOC_ja_UTF8 },
+    {
+      { /*----------------- #01 -----------------*/
+	{
+	  {
+	    { 1,  "\343\201\202\343\201\204\343\201\206ABC",      7, 0,0 },
+	    { 1,  "\343\201\202\343\201\204\343\201\206ABC",      6, 0,0 },
+	    { 1,  "\343\201\202\343\201\204\343\201\206ABC",      4, 0,0 },
+	  }
+	},
+	{
+	  {
+	    { 0,1,6, { 0x3042,0x3044,0x3046,0x0041,0x0042,0x0043,0x0000 }},
+	    { 0,1,6, { 0x3042,0x3044,0x3046,0x0041,0x0042,0x0043,0x0000 }},
+	    { 0,1,4, { 0x3042,0x3044,0x3046,0x0041,0x0000 }		   },
+	  }
+	}
+      },
+      { /*----------------- #02 -----------------*/
+	{
+	  {
+	    { 1,  "\343\201\202\343\201\204\343\201\206ABC",      7, 0,0 },
+	    { 1,  "",		      1, 0,0 },
+	    { 0,  "\343\201\202\343\201\204\343\201\206ABC",      7, 0,0 },
+	  }
+	},
+	{
+	  {
+	    { 0,1,6, { 0x3042,0x3044,0x3046,0x0041,0x0042,0x0043,0x0000 }},
+	    { 0,1,0, { 0x0000 }					   },
+	    { 0,1,6, { 0x0000 }					   },
+	  }
+	}
+      },
+      { /*----------------- END -----------------*/
+	.is_last = 1
+      }
+    }
+  },
+#endif
+  {
+    { Tmbsrtowcs, TST_LOC_end }
+  }
+};
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_mbstowcs.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_mbstowcs.c
new file mode 100644
index 00000000..3b8ce65d
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_mbstowcs.c
@@ -0,0 +1,190 @@
+/*
+ *  TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY
+ *
+ *	 FILE:	dat_mbstowcs.c
+ *
+ *	 MBSTOWCS:  size_t  mbstowcs (wchar_t *ws, char *s, size_t n);
+ */
+
+#include 
+
+TST_MBSTOWCS tst_mbstowcs_loc [] = {
+  {
+    { Tmbstowcs, TST_LOC_de },
+    {
+      { /*----------------- #01 -----------------*/
+	{
+	  {
+	    { 1,  1, "ABC",		   4			 },
+	    { 1,  1, "ABC",		   3			 },
+	    { 1,  1, "ABC",		   2			 },
+	  }
+	},
+	{
+	  {
+	    { 0,1,3, { 0x0041,0x0042,0x0043,0x0000 }	 },
+	    { 0,1,3, { 0x0041,0x0042,0x0043,0x0000 }	 },
+	    { 0,1,2, { 0x0041,0x0042,0x0043,0x0000 }	 },
+	  }
+	}
+      },
+      { /*----------------- #02 -----------------*/
+	{
+	  {
+	    { 1,  1, "ABC",		   4			 },
+	    { 1,  1, "",		   1			 },
+	    { 0,  1, "ABC",		   4			 },
+	  }
+	},
+	{
+	  {
+	    { 0,1,3, { 0x0041,0x0042,0x0043,0x0000 }	 },
+	    { 0,1,0, { 0x0000 }				 },
+	    { 0,1,3, { 0x0000 }				 },
+	  }
+	}
+      },
+      { .is_last = 1 }
+    }
+  },
+  {
+    { Tmbstowcs, TST_LOC_enUS },
+    {
+      { /*----------------- #01 -----------------*/
+	{
+	  {
+	    { 1,  1, "ABC",		   4			 },
+	    { 1,  1, "ABC",		   3			 },
+	    { 1,  1, "ABC",		   2			 },
+	  }
+	},
+	{
+	  {
+	    { 0,1,3, { 0x0041,0x0042,0x0043,0x0000 }	 },
+	    { 0,1,3, { 0x0041,0x0042,0x0043,0x0000 }	 },
+	    { 0,1,2, { 0x0041,0x0042,0x0043,0x0000 }	 },
+	  }
+	}
+      },
+      { /*----------------- #02 -----------------*/
+	{
+	  {
+	    { 1,  1, "ABC",		   4			 },
+	    { 1,  1, "",		   1			 },
+	    { 0,  1, "ABC",		   4			 },
+	  }
+	},
+	{
+	  {
+	    { 0,1,3, { 0x0041,0x0042,0x0043,0x0000 }	 },
+	    { 0,1,0, { 0x0000 }				 },
+	    { 0,1,3, { 0x0000 }				 },
+	  }
+	}
+      },
+      { .is_last = 1 }
+    }
+  },
+#if 0
+  {
+    { Tmbstowcs, TST_LOC_eucJP },
+    {
+      { /*----------------- #01 -----------------*/
+	{
+	  {
+	    { 1,  1, "\244\242\244\244\244\246ABC",      7 },
+	    { 1,  1, "\244\242\244\244\244\246ABC",      6 },
+	    { 1,  1, "\244\242\244\244\244\246ABC",      4 },
+	  }
+	},
+	{
+	  {
+	    { 0,1,6, { 0x3042,0x3044,0x3046,0x0041,0x0042,0x0043,0x0000 }},
+	    { 0,1,6, { 0x3042,0x3044,0x3046,0x0041,0x0042,0x0043,0x0000 }},
+	    { 0,1,4, { 0x3042,0x3044,0x3046,0x0041,0x0000 }		 },
+	  }
+	}
+      },
+      { /*----------------- #02 -----------------*/
+	{
+	  {
+#ifdef SHOJI_IS_RIGHT
+	    /* XXX I really don't understand the first and third line.
+	       the result of the first line is the same as the first
+	       in the last test (i.e., returns 6).  Also, the third
+	       test will simply convert everything.  */
+	    { 1,  1, "\244\242\244\244\244\246ABC",      7 },
+	    { 1,  1, "",                                 1 },
+	    { 0,  1, "\244\242\244\244\244\246ABC",      7 },
+#else
+	    { 1,  1, "\244\242\244\244\244\246ABC",      4 },
+	    { 1,  1, "",                                 1 },
+	    { 0,  1, "\244\242\244\244\244\246ABC",      0 },
+#endif
+	  }
+	},
+	{
+	  {
+	    { 0,1,4, { 0x3042,0x3044,0x3046,0x0041,0x0000 }		 },
+	    { 0,1,0, { 0x0000 }					 },
+	    { 0,1,6, { 0x0000 }					 },
+	  }
+	}
+      },
+      { .is_last = 1 }
+    }
+  },
+#else
+  {
+    { Tmbstowcs, TST_LOC_ja_UTF8 },
+    {
+      { /*----------------- #01 -----------------*/
+	{
+	  {
+	    { 1,  1, "\343\201\202\343\201\204\343\201\206ABC",      7 },
+	    { 1,  1, "\343\201\202\343\201\204\343\201\206ABC",      6 },
+	    { 1,  1, "\343\201\202\343\201\204\343\201\206ABC",      4 },
+	  }
+	},
+	{
+	  {
+	    { 0,1,6, { 0x3042,0x3044,0x3046,0x0041,0x0042,0x0043,0x0000 }},
+	    { 0,1,6, { 0x3042,0x3044,0x3046,0x0041,0x0042,0x0043,0x0000 }},
+	    { 0,1,4, { 0x3042,0x3044,0x3046,0x0041,0x0000 }		 },
+	  }
+	}
+      },
+      { /*----------------- #02 -----------------*/
+	{
+	  {
+#ifdef SHOJI_IS_RIGHT
+	    /* XXX I really don't understand the first and third line.
+	       the result of the first line is the same as the first
+	       in the last test (i.e., returns 6).  Also, the third
+	       test will simply convert everything.  */
+	    { 1,  1, "\244\242\244\244\244\246ABC",      7 },
+	    { 1,  1, "",                                 1 },
+	    { 0,  1, "\244\242\244\244\244\246ABC",      7 },
+#else
+	    { 1,  1, "\343\201\202\343\201\204\343\201\206ABC",      4 },
+	    { 1,  1, "",                                 1 },
+	    { 0,  1, "\343\201\202\343\201\204\343\201\206ABC",      7 },
+#endif
+	  }
+	},
+	{
+	  {
+	    { 0,1,4, { 0x3042,0x3044,0x3046,0x0041,0x0000 }		 },
+	    { 0,1,0, { 0x0000 }					 },
+	    { 0,1,6, { 0x0000 }					 },
+	  }
+	}
+      },
+      { .is_last = 1 }
+    }
+  },
+#endif
+  {
+    { Tmbstowcs, TST_LOC_end }
+  }
+};
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_mbtowc.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_mbtowc.c
new file mode 100644
index 00000000..6527dfc2
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_mbtowc.c
@@ -0,0 +1,444 @@
+/*
+ *  TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY
+ *
+ *	 FILE:	dat_mbtowc.c
+ *
+ *	 MBTOWC:  int  mbtowc (wchar_t *wp, char *s, size_t n);
+ */
+
+/*  NOTE:
+ *
+ *	 int  mbtowc (wchar_t *wp, char *s, size_t n);
+ *
+ *	 where	     n: a maximum number of bytes
+ *		return: the number of bytes
+ *
+ *
+ *	  o When you feed a null pointer for a string (s) to the function,
+ *	    set s_flg=0 instead of putting just a 'NULL' there.
+ *	    Even if you put a 'NULL', it means a null string as well as "".
+ *
+ *	  o When s is a null pointer, the function checks state dependency.
+ *
+ *		state-dependent encoding      - return	NON-zero
+ *		state-independent encoding    - return	0
+ *
+ *	    If state-dependent encoding is expected, set
+ *
+ *		s_flg = 0,  ret_flg = 0,  ret_val = +1
+ *
+ *	    If state-independent encoding is expected, set
+ *
+ *		s_flg = 0,  ret_flg = 0,  ret_val = 0
+ *
+ *
+ *	    When you set ret_flg=1, the test program simply compares
+ *	    an actual return value with an expected value. You can
+ *	    check state-independent case (return value is 0) in that
+ *	    way, but you can not check state-dependent case. So when
+ *	    you check state- dependency in this test function:
+ *	    tst_mbtowc(), set ret_flg=0 always. It's a special case
+ *	    and the test function takes care of it.
+ *
+ *			  w_flg
+ *			  |	s: (a null string; can't be (char *)NULL)
+ *			  |	|
+ *	       input.	{ 1, 0, (char)NULL, MB_LEN_MAX	},
+ *			     |
+ *			     s_flg=0: makes _s_ a null pointer.
+ *
+ *	       expect	{ 0,0,0,x,     0x0000	  },
+ *			      | |
+ *			      | ret_val: 0/+1
+ *			      ret_flg=0
+ *
+ *
+ *    Test data for State dependent encodings:
+ *
+ *	  mbtowc( NULL, NULL, 0 );	 ... first  data
+ *	  mbtowc( &wc,	s1,  n1 );	 ... second data
+ *	  mbtowc( &wc,	s2,  n2 );	 ... third  data
+ * */
+
+#include 
+
+TST_MBTOWC tst_mbtowc_loc [] = {
+  {
+    { Tmbtowc, TST_LOC_de },
+    {
+      { /*----------------- #01 -----------------*/
+	{
+	  {
+	    { 1, 1, "\xfc\xe4\xf6",	    1	       },
+	    { 1, 1, "\xfc\xe4\xf6",	    2	       },
+	    { 1, 1, "\xfc\xe4\xf6",	    MB_LEN_MAX },
+	  }
+	},
+	{
+	  {
+	    { 0,  1,  1,   0x00FC },
+	    { 0,  1,  1,   0x00FC },
+	    { 0,  1,  1,   0x00FC },
+	  }
+	}
+      },
+      { /*----------------- #02 -----------------*/
+	{
+	  {
+	    { 1, 1, "\177",	    MB_LEN_MAX },
+	    { 1, 1, "\200",	    MB_LEN_MAX },
+	    { 1, 1, "\201",	    MB_LEN_MAX },
+	  }
+	},
+	{
+	  {
+	    { 0,  1,  1,   0x007F },
+	    { 0,  1,  1,   0x0080 },
+	    { 0,  1,  1,   0x0081 },
+	  }
+	}
+      },
+      { /*----------------- #03 -----------------*/
+	{
+	  {
+	    { 1, 1, "",			    MB_LEN_MAX },
+	    { 0, 1, "\xfc\xe4\xf6",	    1	       },
+	    { 0, 1, "\xfc\xe4\xf6",	    2	       },
+	  }
+	},
+	{
+	  {
+	    { 0,  1,  0,   0x0000 },
+	    { 0,  1,  1,   0x0000 },
+	    { 0,  1,  1,   0x0000 },
+	  }
+	}
+      },
+      { /*----------------- #04 -----------------*/
+	{
+	  {
+	    { 0, 1, "\xfc\xe4\xf6",	    MB_LEN_MAX },
+	    { 0, 1, "\177",		    MB_LEN_MAX },
+	    { 0, 1, "",	 		   MB_LEN_MAX },
+	  }
+	},
+	{
+	  {
+	    { 0,  1,  1,   0x0000 },
+	    { 0,  1,  1,   0x0000 },
+	    { 0,  1,  0,   0x0000 },
+	  }
+	}
+      },
+      { /*----------------- #05 -----------------*/
+	{
+	  {
+	    { 0, 1, "\xfc\xe4\xf6",	MB_LEN_MAX },
+	    { 0, 1, "\177",	   	MB_LEN_MAX },
+	    { 0, 0, (char)NULL, 	MB_LEN_MAX },
+	  }
+	},
+	{
+	  {
+	    { 0,  1,  1,   0x0000 },
+	    { 0,  1,  1,   0x0000 },
+	    { 0,  0,  0,   0x0000 },
+	  }
+	}
+      },
+      { .is_last = 1 }
+    }
+  },
+  {
+    { Tmbtowc, TST_LOC_enUS },
+    {
+      { /*----------------- #01 -----------------*/
+	{
+	  {
+	    { 1, 1, "ABC",	    1	       },
+	    { 1, 1, "ABC",	    2	       },
+	    { 1, 1, "ABC",	    MB_LEN_MAX },
+	  }
+	},
+	{
+	  {
+	    { 0,  1,  1,   0x0041 },
+	    { 0,  1,  1,   0x0041 },
+	    { 0,  1,  1,   0x0041 },
+	  }
+	}
+      },
+      { /*----------------- #02 -----------------*/
+	{
+	  {
+	    { 1, 1, "\177",	    MB_LEN_MAX },
+	    { 1, 1, "\200",	    MB_LEN_MAX },
+	    { 1, 1, "\201",	    MB_LEN_MAX },
+	  }
+	},
+	{
+	  {
+	    { 0,  1,  1,   0x007F },
+	    { EILSEQ,  1, -1,   0x0000 },
+	    { EILSEQ,  1, -1,   0x0000 },
+	  }
+	}
+      },
+      { /*----------------- #03 -----------------*/
+	{
+	  {
+	    { 1, 1, "",	    MB_LEN_MAX },
+	    { 0, 1, "ABC",	    1	       },
+	    { 0, 1, "ABC",	    2	       },
+	  }
+	},
+	{
+	  {
+	    { 0,  1,  0,   0x0000 },
+	    { 0,  1,  1,   0x0000 },
+	    { 0,  1,  1,   0x0000 },
+	  }
+	}
+      },
+      { /*----------------- #04 -----------------*/
+	{
+	  {
+	    { 0, 1, "ABC",	    MB_LEN_MAX },
+	    { 0, 1, "\177",	    MB_LEN_MAX },
+	    { 0, 1, "",	    MB_LEN_MAX },
+	  }
+	},
+	{
+	  {
+	    { 0,  1,  1,   0x0000 },
+	    { 0,  1,  1,   0x0000 },
+	    { 0,  1,  0,   0x0000 },
+	  }
+	}
+      },
+      { /*----------------- #05 -----------------*/
+	{
+	  {
+	    { 0, 1, "ABC",	    MB_LEN_MAX },
+	    { 0, 1, "\177",	    MB_LEN_MAX },
+	    { 0, 0, (char)NULL, MB_LEN_MAX },
+	  }
+	},
+	{
+	  {
+	    { 0,  1,  1,   0x0000 },
+	    { 0,  1,  1,   0x0000 },
+	    { 0,  0,  0,   0x0000 },
+	  }
+	}
+      },
+      { .is_last = 1 }
+    }
+  },
+#if 0
+  {
+    { Tmbtowc, TST_LOC_eucJP },
+    {
+      { /*----------------- #01 -----------------*/
+	{
+	  {
+	    { 1, 1, "\244\242A",      1          },
+	    { 1, 1, "\244\242A",      2          },
+	    { 1, 1, "\244\242A",      MB_LEN_MAX },
+	  }
+	},
+	{
+	  {
+#ifdef SHOJI_IS_RIGHT
+	    { EILSEQ,  1, -1,   0x0000 },
+#else
+	    /* XXX EILSEQ was introduced in ISO C99.  */
+	    { 0,	  1, -1,   0x0000 },
+#endif
+	    { 0,       1,  2,   0x3042 },
+	    { 0,       1,  2,   0x3042 },
+	  }
+	}
+      },
+      { /*----------------- #02 -----------------*/
+	{
+	  {
+	    { 1, 1, "\177\244\242",   MB_LEN_MAX },
+	    { 1, 1, "\377\244\242",   MB_LEN_MAX },
+	    { 1, 1, "\201\244\242",   MB_LEN_MAX },
+	  }
+	},
+	{
+	  {
+	    { 0,  1, +1,   0x007F },
+#ifdef SHOJI_IS_RIGHT
+	    { EILSEQ,  1, -1,   0x0000 },
+#else
+	    { 0,  1, -1,   0x0000 },
+#endif
+	    { 0,  1, +1,   0x0081 },
+	  }
+	}
+      },
+      { /*----------------- #03 -----------------*/
+	{
+	  {
+	    { 1, 1, "",         MB_LEN_MAX },
+	    { 0, 1, "\244\242A",      1          },
+	    { 0, 1, "\244\242A",      2          },
+	  }
+	},
+	{
+	  {
+	    { 0,  1,  0,   0x0000 },
+#ifdef SHOJI_IS_RIGHT
+	    { EILSEQ,  1, -1,   0x0000 },
+#else
+	    /* XXX EILSEQ was introduced in ISO C99.  */
+	    { 0,       1, -1,   0x0000 },
+#endif
+	    { 0,  1,  2,   0x0000 },
+	  }
+	}
+      },
+      { /*----------------- #04 -----------------*/
+	{
+	  {
+	    { 0, 1, "\244\242A",      MB_LEN_MAX },
+	    { 0, 1, "\177\244\242",   MB_LEN_MAX },
+	    { 0, 1, "",         MB_LEN_MAX },
+	  }
+	},
+	{
+	  {
+	    { 0,  1,  2,   0x0000 },
+	    { 0,  1, +1,   0x0000 },
+	    { 0,  1,  0,   0x0000 },
+	  }
+	}
+      },
+      { /*----------------- #05 -----------------*/
+	{
+	  {
+	    { 0, 1, "\244\242A",      MB_LEN_MAX },
+	    { 0, 1, "\177\244\242",   MB_LEN_MAX },
+	    { 0, 0, (char)NULL, MB_LEN_MAX },
+	  }
+	},
+	{
+	  {
+	    { 0,  1,  2,   0x0000 },
+	    { 0,  1, +1,   0x0000 },
+	    { 0,  0,  0,   0x0000 },
+	  }
+	}
+      },
+      { .is_last = 1 }
+    }
+  },
+#else
+  {
+    { Tmbtowc, TST_LOC_ja_UTF8 },
+    {
+      { /*----------------- #01 -----------------*/
+	{
+	  {
+	    { 1, 1, "\343\201\202A",      1          },
+	    { 1, 1, "\343\201\202A",      3          },
+	    { 1, 1, "\343\201\202A",      MB_LEN_MAX },
+	  }
+	},
+	{
+	  {
+#ifdef SHOJI_IS_RIGHT
+	    { EILSEQ,  1, -1,   0x0000 },
+#else
+	    /* XXX EILSEQ was introduced in ISO C99.  */
+	    { 0,	  1, -1,   0x0000 },
+#endif
+	    { 0,       1,  3,   0x3042 },
+	    { 0,       1,  3,   0x3042 },
+	  }
+	}
+      },
+      { /*----------------- #02 -----------------*/
+	{
+	  {
+	    { 1, 1, "\177\343\201\202",   MB_LEN_MAX },
+	    { 1, 1, "\377\343\201\202",   MB_LEN_MAX },
+	    { 1, 1, "\302\201\343\201\202",   MB_LEN_MAX },
+	  }
+	},
+	{
+	  {
+	    { 0,  1, +1,   0x007F },
+#ifdef SHOJI_IS_RIGHT
+	    { EILSEQ,  1, -1,   0x0000 },
+#else
+	    { 0,  1, -1,   0x0000 },
+#endif
+	    { 0,  1, +2,   0x0081 },
+	  }
+	}
+      },
+      { /*----------------- #03 -----------------*/
+	{
+	  {
+	    { 1, 1, "",         MB_LEN_MAX },
+	    { 0, 1, "\343\201\202A",      1          },
+	    { 0, 1, "\343\201\202A",      3          },
+	  }
+	},
+	{
+	  {
+	    { 0,  1,  0,   0x0000 },
+#ifdef SHOJI_IS_RIGHT
+	    { EILSEQ,  1, -1,   0x0000 },
+#else
+	    /* XXX EILSEQ was introduced in ISO C99.  */
+	    { 0,       1, -1,   0x0000 },
+#endif
+	    { 0,  1,  3,   0x0000 },
+	  }
+	}
+      },
+      { /*----------------- #04 -----------------*/
+	{
+	  {
+	    { 0, 1, "\343\201\202A",      MB_LEN_MAX },
+	    { 0, 1, "\177\343\201\202",   MB_LEN_MAX },
+	    { 0, 1, "",         MB_LEN_MAX },
+	  }
+	},
+	{
+	  {
+	    { 0,  1,  3,   0x0000 },
+	    { 0,  1, +1,   0x0000 },
+	    { 0,  1,  0,   0x0000 },
+	  }
+	}
+      },
+      { /*----------------- #05 -----------------*/
+	{
+	  {
+	    { 0, 1, "\343\201\202A",      MB_LEN_MAX },
+	    { 0, 1, "\177\343\201\202",   MB_LEN_MAX },
+	    { 0, 0, (char)NULL, MB_LEN_MAX },
+	  }
+	},
+	{
+	  {
+	    { 0,  1,  3,   0x0000 },
+	    { 0,  1, +1,   0x0000 },
+	    { 0,  0,  0,   0x0000 },
+	  }
+	}
+      },
+      { .is_last = 1 }
+    }
+  },
+#endif
+  {
+    { Tmbtowc, TST_LOC_end }
+  }
+};
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_strcoll.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_strcoll.c
new file mode 100644
index 00000000..e12037ca
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_strcoll.c
@@ -0,0 +1,209 @@
+/*
+ *  TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY
+ *
+ *	 FILE: dat_strcoll.c
+ *
+ *	 STRCOLL:  int strcoll (const char *s1, const char *s2);
+ */
+
+/*
+   NOTE:
+
+   If a return value is expected to be 0, set ret_flg=1 and the
+   expected value = 0.	If a return value is expected to be a
+   positive/negative value, set ret_flg=0, and set the expected value
+   = +1/-1.
+   There is inconsistensy between tst_strcoll() and tst_wcscoll()(it
+   has cmp_flg) for input data. I'll fix it.
+
+   Assuming en_US to be en_US.ascii. (maybe, should be iso8859-1).
+
+
+
+   ASCII CODE  : A,B,C, ...  , a, b, c, ...	 B,a:-1	  a,B:+1
+   DICTIONARY : A,a,B,b,C,c,....  a,B:-1 B,a:+1 */
+
+TST_STRCOLL tst_strcoll_loc [] = {
+  {
+    { Tstrcoll, TST_LOC_de },
+    {
+      { /*input.*/ { "ÄBCDEFG", "ÄBCDEFG"	      },  /* #1 */
+	/*expect*/ { 0,1,0,			      },
+      },
+      { /*input.*/ { "XX Ä XX", "XX B XX"	      },  /* #2 */
+	/*expect*/ { 0,0,-1,			      },
+      },
+      { /*input.*/ { "XX B XX", "XX Ä XX"	      },  /* #3 */
+	/*expect*/ { 0,0,+1,			      },
+      },
+      { /*input.*/ { "B",	"a"		      },  /* #4 */
+	/*expect*/ { 0,0,+1,			      },
+      },
+      { /*input.*/ { "a",	"B"		      },  /* #5 */
+	/*expect*/ { 0,0,-1,			      },
+      },
+      { /*input.*/ { "b",	"A"		      },  /* #6 */
+	/*expect*/ { 0,0,+1,			      },
+      },
+      { /*input.*/ { "A",	"b"		      },  /* #7 */
+	/*expect*/ { 0,0,-1,			      },
+      },
+      { /*input.*/ { "ä",	"B"		      },  /* #8 */
+	/*expect*/ { 0,0,-1,			      },
+      },
+      { /*input.*/ { "B",	"ä"		      },  /* #9 */
+	/*expect*/ { 0,0,+1,			      },
+      },
+      { .is_last = 1 } /* Last element.  */
+    }
+  },
+  {
+    { Tstrcoll, TST_LOC_en },
+    {
+      { /*input.*/ { "ABCDEFG", "ABCDEFG"	      },  /* #1 */
+	/*expect*/ { 0,1,0,			      },
+      },
+      { /*input.*/ { "XX a XX", "XX B XX"	      },  /* #2 */
+	/*expect*/ { 0,0,-1,			      },
+      },
+      { /*input.*/ { "XX B XX", "XX a XX"	      },  /* #3 */
+	/*expect*/ { 0,0,+1,			      },
+      },
+      {
+	/*  */
+	/*input.*/ { "B",	"a"		      },  /* #4 */
+#ifdef SHOJI_IS_RIGHT
+	/*expect*/ { 0,0,-1,			      },
+#else
+		   /* XXX We are not testing the C locale.  */
+	/*expect*/ { 0,0,+1,			      },
+#endif
+      },
+      {
+	/*  */
+	/*input.*/ { "a",	"B"		      },  /* #5 */
+#ifdef SHOJI_IS_RIGHT
+	/*expect*/ { 0,0,+1,			      },
+#else
+		   /* XXX We are not testing the C locale.  */
+	/*expect*/ { 0,0,-1,			      },
+#endif
+      },
+      { /*input.*/ { "b",	"A"		      },  /* #6 */
+	/*expect*/ { 0,0,+1,			      },
+      },
+      { /*input.*/ { "A",	"b"		      },  /* #7 */
+	/*expect*/ { 0,0,-1,			      },
+      },
+#ifdef NO_WAIVER
+      /* XXX I do not yet know whether strcoll really should reject
+	 characters outside the multibyte character range.  */
+      {
+	/* #8 */  /*  */
+	/*input.*/ { "\244\242\244\244\244\246\244\250\244\252", "ABCDEFG" },
+	/*expect*/ { EINVAL,0,0,		      },
+      },
+      {
+	/* #9 */  /*  */
+	/*input.*/ { "ABCZEFG", "\244\242\244\244\244\246\244\250\244\252" },
+	/*expect*/ { EINVAL,0,0,		      },
+      },
+#endif
+      { .is_last = 1 } /* Last element.  */
+    }
+  },
+#if 0
+  {
+    { Tstrcoll, TST_LOC_eucJP },
+    {
+      { /*input.*/ { "\244\242\244\244\244\246\244\250\244\252",
+		     "\244\242\244\244\244\246\244\250\244\252" },  /* #1 */
+	/*expect*/ { 0,1,0,			      },
+      },
+      { /*input.*/ { "\244\242\244\244\244\246\244\250\244\252",
+		     "\244\242\244\244\244\363\244\250\244\252" },  /* #2 */
+	/*expect*/ { 0,0,-1,			      },
+      },
+      { /*input.*/ { "\244\242\244\244\244\363\244\250\244\252",
+		     "\244\242\244\244\244\246\244\250\244\252" },  /* #3 */
+	/*expect*/ { 0,0,+1,			      },
+      },
+      { /*input.*/ { "B",	"a"		      },  /* #4 */
+	/*expect*/ { 0,0,-1,			      },
+      },
+      { /*input.*/ { "a",	"B"		      },  /* #5 */
+	/*expect*/ { 0,0,+1,			      },
+      },
+      { /*input.*/ { "b",	"A"		      },  /* #6 */
+	/*expect*/ { 0,0,+1,			      },
+      },
+      { /*input.*/ { "A",	"b"		      },  /* #7 */
+	/*expect*/ { 0,0,-1,			      },
+      },
+#ifdef NO_WAIVER
+      /* XXX I do not yet know whether strcoll really should reject
+	 characters outside the multibyte character range.  */
+      {
+	/*  */
+	/*input.*/ { "\200\216\217", "ABCDEFG"	      },  /* #8 */
+	/*expect*/ { EINVAL,0,0,		      },
+      },
+      {
+	/*  */
+	/*input.*/ { "ABCZEFG", "\200\216\217"	      },  /* #9 */
+	/*expect*/ { EINVAL,0,0,		      },
+      },
+#endif
+      { .is_last = 1 } /* Last element.  */
+    }
+  },
+#else
+  {
+    { Tstrcoll, TST_LOC_ja_UTF8 },
+    {
+      { /*input.*/ { "\343\201\202\343\201\204\343\201\206\343\201\210\343\201\212",
+		     "\343\201\202\343\201\204\343\201\206\343\201\210\343\201\212" },  /* #1 */
+	/*expect*/ { 0,1,0,			      },
+      },
+      { /*input.*/ { "\343\201\202\343\201\204\343\201\206\343\201\210\343\201\212",
+		     "\343\201\202\343\201\204\343\202\223\343\201\210\343\201\212" },  /* #2 */
+	/*expect*/ { 0,0,-1,			      },
+      },
+      { /*input.*/ { "\343\201\202\343\201\204\343\202\223\343\201\210\343\201\212",
+		     "\343\201\202\343\201\204\343\201\206\343\201\210\343\201\212" },  /* #3 */
+	/*expect*/ { 0,0,+1,			      },
+      },
+      { /*input.*/ { "B",	"a"		      },  /* #4 */
+	/*expect*/ { 0,0,-1,			      },
+      },
+      { /*input.*/ { "a",	"B"		      },  /* #5 */
+	/*expect*/ { 0,0,+1,			      },
+      },
+      { /*input.*/ { "b",	"A"		      },  /* #6 */
+	/*expect*/ { 0,0,+1,			      },
+      },
+      { /*input.*/ { "A",	"b"		      },  /* #7 */
+	/*expect*/ { 0,0,-1,			      },
+      },
+#ifdef NO_WAIVER
+      /* XXX I do not yet know whether strcoll really should reject
+	 characters outside the multibyte character range.  */
+      {
+	/*  */
+	/*input.*/ { "\200\216\217", "ABCDEFG"	      },  /* #8 */
+	/*expect*/ { EINVAL,0,0,		      },
+      },
+      {
+	/*  */
+	/*input.*/ { "ABCZEFG", "\200\216\217"	      },  /* #9 */
+	/*expect*/ { EINVAL,0,0,		      },
+      },
+#endif
+      { .is_last = 1 } /* Last element.  */
+    }
+  },
+#endif
+  {
+    { Tstrcoll, TST_LOC_end }
+  }
+};
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_strfmon.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_strfmon.c
new file mode 100644
index 00000000..8c28bba5
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_strfmon.c
@@ -0,0 +1,268 @@
+/*
+ *  TEST SUITE FOR MB/WC FUNCTIONS IN CLIBRARY
+ *
+ *	 FILE:	dat_strfmon.c
+ *
+ *	 STRFMON:  size_t strfmon (char *buf, size_t nbyte, char *fmt, ... );
+ */
+
+/*
+ *  NOTE:
+ *
+ *  The buffer size should be enough to contain a string including a
+ *  null char.
+ *  Returns the number of bytes of the string (NOT including a null char).
+ */
+
+TST_STRFMON tst_strfmon_loc [] = {
+  {
+    { Tstrfmon, TST_LOC_de },
+    {
+      {
+	/* #01 */
+	/*inp*/ { 24, "%n %% %i",	     123.00			},
+	/*exp*/ { 0,1,23,		     "123,00 EUR % 123,00 EUR"	},
+      },
+      {
+	/* #02 */
+	/*inp*/ { 24, "%n %% %i",	     123.00			},
+	/*exp*/ { 0,1,23,		     "123,00 EUR % 123,00 EUR"	},
+      },
+      {
+	/* #03 */
+	/*inp*/ { 23, "%n %% %i",	     123.00			},
+	/*exp*/ { E2BIG,1,-1,	     ""					},
+      },
+      {
+	/* #04 */
+	/*inp*/ { 31, "%n|%i",	     1234.561				},
+	/*exp*/ { 0,1,25,		     "1.234,56 EUR|1.234,56 EUR"},
+      },
+      {
+	/* #05 */
+	/*inp*/ { 33, "%n|%i",	    -1234.561				},
+	/*exp*/ { 0,1,27,		     "-1.234,56 EUR|-1.234,56 EUR"},
+      },
+      {
+	/* #06 */
+	/*inp*/ { 33, "%13n|%12i",	     1234.561			},
+	/*exp*/ { 0,1,26,		     " 1.234,56 EUR|1.234,56 EUR"},
+      },
+      {
+	/* #07 */
+	/*inp*/ { 33, "%12n|%12i",	    -1234.561			},
+	/*exp*/ { 0,1,27,		     "-1.234,56 EUR|-1.234,56 EUR"},
+      },
+      {
+	/* #08 */
+	/*inp*/ { 33, "%#5n|%#5i",	     1234.561			},
+	/*exp*/ { 0,1,29,		     "  1.234,56 EUR|  1.234,56 EUR"},
+      },
+      {
+	/* #09 */
+	/*inp*/ { 33, "%#5n|%#5i",	    -1234.561			},
+	/*exp*/ { 0,1,29,		     "- 1.234,56 EUR|- 1.234,56 EUR"},
+      },
+      {
+	/* #10 */
+	/*inp*/ { 33, "%=*#5n|%=*#5i",	 1234.561			},
+	/*exp*/ { 0,1,29,		     " *1.234,56 EUR| *1.234,56 EUR"},
+      },
+      {
+	/* #11 */
+	/*inp*/ { 33, "%=0#5n|%=0#5i",	-1234.561			},
+	/*exp*/ { 0,1,29,		     "-01.234,56 EUR|-01.234,56 EUR"},
+      },
+      {
+	/* #12 */
+	/*inp*/ { 33, "%^#5n|%^#5i",	-1234.561			},
+	/*exp*/ { 0,1,27,		     "- 1234,56 EUR|- 1234,56 EUR"},
+      },
+      {
+	/* #13 */
+	/*inp*/ { 33, "%#5.0n|%#5.0i",	 1234.444			},
+	/*exp*/ { 0,1,23,		     "  1.234 EUR|  1.234 EUR"	},
+      },
+      {
+	/* #14 */
+	/*inp*/ { 33, "%#5.0n|%#5.4i",	-1234.555			},
+	/*exp*/ { 0,1,28,		     "- 1.235 EUR|- 1.234,5550 EUR"},
+      },
+      {
+	/* #15 */
+	/*inp*/ { 33, "%(#5n|%!(#5i",	-1234.561			},
+	/*exp*/ { 0,1,27,		     "( 1.234,56 EUR)|( 1.234,56)"},
+      },
+      { .is_last = 1 }
+    }
+  },
+  {
+    { Tstrfmon, TST_LOC_enUS },
+    {
+      {
+	/* #01 */
+	/*inp*/ { 22, "%n %% %i",	     123.00			},
+	/*exp*/ { 0,1,20,		     "$123.00 % USD 123.00"	},
+      },
+      {
+	/* #02 */
+	/*inp*/ { 21, "%n %% %i",	     123.00			},
+	/*exp*/ { 0,1,20,		     "$123.00 % USD 123.00"	},
+      },
+      {
+	/* #03 */
+	/*inp*/ { 20, "%n %% %i",	     123.00			},
+	/*exp*/ { E2BIG,1,-1,	     ""					},
+      },
+      {
+	/* #04 */
+	/*inp*/ { 30, "%n|%i",	     1234.561				},
+	/*exp*/ { 0,1,22,		     "$1,234.56|USD 1,234.56"	},
+      },
+      {
+	/* #05 */
+	/*inp*/ { 32, "%n|%i",	    -1234.561				},
+	/*exp*/ { 0,1,24,		     "-$1,234.56|-USD 1,234.56"	},
+      },
+      {
+	/* #06 */
+	/*inp*/ { 30, "%12n|%12i",	     1234.561			},
+	/*exp*/ { 0,1,25,		     "   $1,234.56|USD 1,234.56"},
+      },
+      {
+	/* #07 */
+	/*inp*/ { 32, "%12n|%12i",	    -1234.561			},
+	/*exp*/ { 0,1,26,		     "  -$1,234.56|-USD 1,234.56"},
+      },
+      {
+	/* #08 */
+	/*inp*/ { 32, "%#5n|%#5i",	     1234.561			},
+	/*exp*/ { 0,1,26,		     " $ 1,234.56| USD  1,234.56"},
+      },
+      {
+	/* #09 */
+	/*inp*/ { 32, "%#5n|%#5i",	    -1234.561			},
+	/*exp*/ { 0,1,26,		     "-$ 1,234.56|-USD  1,234.56"},
+      },
+      {
+	/* #10 */
+	/*inp*/ { 32, "%=*#5n|%=*#5i",	 1234.561			},
+	/*exp*/ { 0,1,26,		     " $*1,234.56| USD *1,234.56"},
+      },
+      {
+	/* #11 */
+	/*inp*/ { 32, "%=0#5n|%=0#5i",	-1234.561			},
+	/*exp*/ { 0,1,26,		     "-$01,234.56|-USD 01,234.56"},
+      },
+      {
+	/* #12 */
+	/*inp*/ { 32, "%^#5n|%^#5i",	-1234.561			},
+	/*exp*/ { 0,1,24,		     "-$ 1234.56|-USD  1234.56"	},
+      },
+      {
+	/* #13 */
+	/*inp*/ { 32, "%#5.0n|%#5.0i",	 1234.444			},
+	/*exp*/ { 0,1,20,		     " $ 1,234| USD  1,234"	},
+      },
+      {
+	/* #14 */
+	/*inp*/ { 32, "%#5.0n|%#5.4i",	-1234.555			},
+	/*exp*/ { 0,1,25,		     "-$ 1,235|-USD  1,234.5550"},
+      },
+      {
+	/* #15 */
+	/*inp*/ { 32, "%(#5n|%!(#5i",	-1234.561			},
+	/*exp*/ { 0,1,24,		     "($ 1,234.56)|( 1,234.56)"	},
+      },
+      { .is_last = 1 }
+    }
+  },
+  {
+#if 0
+    { Tstrfmon, TST_LOC_eucJP },
+#else
+    { Tstrfmon, TST_LOC_ja_UTF8 },
+#endif
+    {
+      {
+	/* #01 */
+	/*inp*/ { 17, "%n %% %i",	 123.00				   },
+	/*exp*/ { 0,1,15,		 "\241\357123 % JPY 123"	   },
+      },
+      {
+	/* #02 */
+	/*inp*/ { 16, "%n %% %i",	 123.00				   },
+	/*exp*/ { 0,1,15,		 "\241\357123 % JPY 123"	   },
+      },
+      {
+	/* #03 */
+	/*inp*/ { 15, "%n %% %i",	 123.00				   },
+	/*exp*/ { E2BIG,1,-1,		 ""				   },
+      },
+      {
+	/* #04 */
+	/*inp*/ { 30, "%n|%i",		 1234.561			   },
+	/*exp*/ { 0,1,17,		 "\241\3571,235|JPY 1,235"	   },
+      },
+      {
+	/* #05 */
+	/*inp*/ { 32, "%n|%i",		-1234.561			   },
+	/*exp*/ { 0,1,19,		 "\241\357-1,235|JPY -1,235"	   },
+      },
+      {
+	/* #06 */
+	/*inp*/ { 32, "%12n|%12i",	 1234.561			   },
+	/*exp*/ { 0,1,25,		 "     \241\3571,235|   JPY 1,235" },
+      },
+      {
+	/* #07 */
+	/*inp*/ { 32, "%12n|%12i",	-1234.561			   },
+	/*exp*/ { 0,1,25,		 "    \241\357-1,235|  JPY -1,235" },
+      },
+      {
+	/* #08 */
+	/*inp*/ { 32, "%#5n|%#5i",	 1234.561			   },
+	/*exp*/ { 0,1,21,		 " \241\357 1,235| JPY  1,235"	   },
+      },
+      {
+	/* #09 */
+	/*inp*/ { 32, "%#5n|%#5i",	-1234.561			   },
+	/*exp*/ { 0,1,21,		 "\241\357- 1,235|JPY - 1,235"	   },
+      },
+      {
+	/* #10 */
+	/*inp*/ { 32, "%=*#5n|%=*#5i",	 1234.561			   },
+	/*exp*/ { 0,1,21,		 " \241\357*1,235| JPY *1,235"	   },
+      },
+      {
+	/* #11 */
+	/*inp*/ { 32, "%=0#5n|%=0#5i",	-1234.561			   },
+	/*exp*/ { 0,1,21,		 "\241\357-01,235|JPY -01,235"	   },
+      },
+      {
+	/* #12 */
+	/*inp*/ { 32, "%^#5n|%^#5i",	-1234.561			   },
+	/*exp*/ { 0,1,19,		 "\241\357- 1235|JPY - 1235"	   },
+      },
+      {
+	/* #13 */
+	/*inp*/ { 32, "%#5.0n|%#5.0i",	 1234.444			   },
+	/*exp*/ { 0,1,21,		 " \241\357 1,234| JPY  1,234"	   },
+      },
+      {
+	/* #14 */
+	/*inp*/ { 32, "%#5.0n|%#5.4i",	-1234.555			   },
+	/*exp*/ { 0,1,26,		 "\241\357- 1,235|JPY - 1,234.5550"},
+      },
+      {
+	/* #15 */
+	/*inp*/ { 32, "%(#5n|%!(#5i",	-1234.561			   },
+	/*exp*/ { 0,1,19,		 "(\241\357 1,235)|( 1,235)"	   },
+      },
+      { .is_last = 1 }
+    }
+  },
+  {
+    { Tstrfmon, TST_LOC_end }
+  }
+};
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_strxfrm.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_strxfrm.c
new file mode 100644
index 00000000..0c672d3d
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_strxfrm.c
@@ -0,0 +1,147 @@
+/*
+ *  TEST SUITE FOR MB/WC FUNCTIONS IN CLIBRARY
+ *
+ *	 FILE:	dat_strxfrm.c
+ *
+ *	 STRXFRM:  size_t strxfrm (char *s1, const char s2, size_t n);
+ */
+
+
+/*
+ *  NOTE:
+ *
+ *  Return value and errno value are checked only for 2nd string:
+ *  org2[]; n1 and n2 don't mean bytes to be translated.
+ *  It means a buffer size including a null character.
+ *  Results of this test depens on results of strcoll().
+ *  If you got errors, check both test results.
+ *
+ *  The buffer size should be enough to contain a string including a
+ *  null char.	Returns the number of bytes of the string (NOT
+ *  including a null char).
+ */
+
+
+
+TST_STRXFRM tst_strxfrm_loc [] = {
+  {
+    { Tstrxfrm, TST_LOC_de },
+    {
+      { /*inp*/ { "\xf6\xc4\xe4\xfc", "\xf6\xc4\xe4\xfc", 17, 17 },  /* #01 */
+	/*exp*/ { 0,0,0,			   },
+      },
+      { /*inp*/ { "aA", "Aa",	    10, 10 },  /* #02 */
+	/*exp*/ { 0,0,0 ,			   },
+      },
+      { /*inp*/ { "Aa", "aA",	    10, 10 },  /* #03 */
+	/*exp*/ { 0,0,0,			   },
+      },
+      { /*inp*/ { "abc", "",	    13, 13 },  /* #04 */
+	/*exp*/ { 0,0,0,			   },
+      },
+      { /*inp*/ { "a", "B",		     7,	 7 },  /* #05 */
+	/*exp*/ { 0,0,0,			   },
+      },
+      { /*inp*/ { "B", "a",		     7,	 7 },  /* #06 */
+	/*exp*/ { 0,0,0,			   },
+      },
+      {
+	/* hiragana == latin1 */
+	/*inp*/ { "abc", "\244\241\244\242",  13,  9 },	 /* #07 */
+	/*exp*/ { 0,0,0,		       },
+      },
+      { .is_last = 1 }
+    }
+  },
+  {
+    { Tstrxfrm, TST_LOC_enUS },
+    {
+      { /*inp*/ { "abcd", "abcd",	    17, 17 },  /* #01 */
+	/*exp*/ { 0,0,0,			   },
+      },
+      { /*inp*/ { "aA", "Aa",	    10, 10 },  /* #02 */
+	/*exp*/ { 0,0,0 ,			   },
+      },
+      { /*inp*/ { "Aa", "aA",	    10, 10 },  /* #03 */
+	/*exp*/ { 0,0,0,			   },
+      },
+      { /*inp*/ { "abc", "",	    13, 13 },  /* #04 */
+	/*exp*/ { 0,0,0,			   },
+      },
+      { /*inp*/ { "a", "B",		     7,	 7 },  /* #05 */
+	/*exp*/ { 0,0,0,			   },
+      },
+      { /*inp*/ { "B", "a",		     7,	 7 },  /* #06 */
+	/*exp*/ { 0,0,0,			   },
+      },
+#ifdef NO_WAIVER
+      {
+	/*  */
+	/*inp*/ { "abc", "\244\241\244\242",  13,  9 },	 /* #07 */
+	/*exp*/ { EINVAL,0,0,		       },
+      },
+#endif
+      { .is_last = 1 }
+    }
+  },
+#if 0
+  {
+    { Tstrxfrm, TST_LOC_eucJP },	 /* ??? */
+    {
+      {
+	/* #01 */
+	/*inp*/ { "\244\242\244\241",  "\244\241\244\242",   5,	 5 },
+	/*exp*/ { 0,0,0,		       },
+      },
+      {
+	/* #02 */
+	/*inp*/ { "\244\241\244\242",  "\244\242\244\241",   5,	 5 },
+	/*exp*/ { 0,0,0,		       },
+      },
+      {
+	/* #03 */
+	/*inp*/ { "\244\242\216\261",  "\216\261\244\242",   5,	 5 },
+	/*exp*/ { 0,0,0,		       },
+      },
+#ifdef NO_WAIVER
+      {
+	/*inp*/ { "AAA", "\216\217",	 5,  5 },  /* #04 */ /*  */
+	/*exp*/ { EINVAL,0,0,		       },
+      },
+#endif
+      { .is_last = 1 }
+    }
+  },
+#else
+  {
+    { Tstrxfrm, TST_LOC_ja_UTF8 },	 /* ??? */
+    {
+      {
+	/* #01 */
+	/*inp*/ { "\343\201\202\343\201\201",  "\343\201\201\343\201\202",   7,	 7 },
+	/*exp*/ { 0,0,0,		       },
+      },
+      {
+	/* #02 */
+	/*inp*/ { "\343\201\201\343\201\202",  "\343\201\202\343\201\201",   7,	 7 },
+	/*exp*/ { 0,0,0,		       },
+      },
+      {
+	/* #03 */
+	/*inp*/ { "\343\201\202\357\275\261",  "\357\275\261343\201\202",   7,	 7 },
+	/*exp*/ { 0,0,0,		       },
+      },
+#ifdef NO_WAIVER
+      {
+	/*inp*/ { "AAA", "\340\277\220",	 5,  5 },  /* #04 */ /*  */
+	/*exp*/ { EINVAL,0,0,		       },
+      },
+#endif
+      { .is_last = 1 }
+    }
+  },
+#endif
+  {
+    { Tstrxfrm, TST_LOC_end }
+  }
+};
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_swscanf.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_swscanf.c
new file mode 100644
index 00000000..088f165f
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_swscanf.c
@@ -0,0 +1,185 @@
+/*
+ *  TEST SUITE FOR MB/WC FUNCTIONS IN CLIBRARY
+ *
+ *	 FILE:	dat_swscanf.c
+ *
+ *	 SWSCANF:  int	swscanf (const wchar_t *s, const wchar_t *fmt, ...);
+ */
+
+
+#include 
+#include 
+#include "tst_types.h"
+#include "tgn_locdef.h"
+
+
+TST_SWSCANF tst_swscanf_loc [] =
+{
+  {
+    { Tswscanf, TST_LOC_de },
+    {
+      /*------------------------ 01 -----------------------*/
+      { { {
+	0x002D, 0x0031,		0x003A,	   /* %d: -1   */
+	0x0032,			0x003A,	   /* %u:  2   */
+	0x0033, 0x002C, 0x0033, 0x003A,	   /* %f:  3.3 */
+	0x00E4,			0x003A,	   /* %c: 'ä'  */
+	0x00C4, 0x00DC, 0x0000, 0x0000,	   /* %s: "ÄÜ" */
+      },
+	  L"%d:%u:%f:%c:%s", 0
+      },
+	{ /* The fields are: err_val, ret_flag, ret_val,
+	     val_int, val_uns, val_flt, val_c, val_s, val_S.  */
+	  0,1,5,
+	  -1, 2, 3.3, 'ä', "ÄÜ", { 0x0000, },
+	},
+      },
+      /*------------------------ 02 -----------------------*/
+      { { {
+	0x00E4, 0x00C4, 0x0000		       /* "äÄ" */
+      },
+	  L"%lc", 'C'
+      },
+	{ 0,1,1,
+	  0,0,0,0,"", { 0x00E4, 0x0000 },
+	},
+      },
+      /*------------------------ 03 -----------------------*/
+      { { {
+	0x00E4, 0x00C4, 0x0000		       /* "äÄ" */
+      },
+	  L"%ls", 'S'
+      },
+	{ 0,1,1,
+	  0,0,0,0,"", { 0x00E4, 0x00C4, 0x0000 },
+	},
+      },
+      /*------------------------ 04 -----------------------*/
+      /*  x 2 */
+      { { {
+	0x00E4, 0x00C4, 0x0000		       /* "äÄ" */
+      },
+	  L"1%d:2%d:3%d:4%d:5%d:6%d:7%d:8%d:9%d", 0
+      },
+#ifdef SHOJI_IS_RIGHT
+	{ 1,EINVAL,1,WEOF,
+	  0,0,0,0,"", { 0x0000 },
+#else
+	{ 0,1,0,
+	  0,0,0,0,"", { 0x0000 },
+#endif
+	},
+      },
+      /*---------------------------------------------------*/
+      { .is_last = 1}	/* Last element.  */
+    }
+  },
+  {
+    { Tswscanf, TST_LOC_enUS },
+    {
+      /*------------------------ 01 -----------------------*/
+      { { { 0x002D, 0x0031,					    0x003A,
+	    0x0032,						    0x003A,
+	    0x0035, 0x0034, 0x002E, 0x0033, 0x0045, 0x002D, 0x0031, 0x003A,
+	    0x0041,						    0x003A,
+	    0x0061, 0x0062, 0x0000,				    0x0000,
+      },
+	  L"%d:%u:%f:%c:%s", 0
+      },
+	{ 0,1,5,
+	  -1, 2, 5.43, 'A', "ab", { 0x0000 },
+	},
+      },
+      /*------------------------ 02 -----------------------*/
+      /*  x 2 */
+      { { {
+	0x0063, 0x0064, 0x0000
+      },
+	  L"%C", 'C'
+      },
+	{ 0,1,1,
+	  0,0,0,0,"", { 0x0063, 0x0000 },
+	},
+      },
+      /*------------------------ 03 -----------------------*/
+      { { {
+	0x0063, 0x0064, 0x0000
+      },
+	  L"%S", 'S'
+      },
+	{ 0,1,1,
+	  0,0,0,0,"", { 0x0063, 0x0064, 0x0000 },
+	},
+      },
+      /*---------------------------------------------------*/
+      { .is_last = 1}	/* Last element.  */
+    }
+  },
+  {
+#if 0
+    { Tswscanf, TST_LOC_eucJP },
+#else
+    { Tswscanf, TST_LOC_ja_UTF8 },
+#endif
+    {
+      /*------------------------ 01 -----------------------*/
+      { { { 0x002D, 0x0031,	    0x003A,
+	    0x0032,		    0x003A,
+	    0x0033, 0x002E, 0x0033, 0x003A,
+	    0x0062,		    0x003A,
+	    0x0061, 0x0062, 0x0000, 0x0000,
+      },
+	  L"%d:%u:%f:%c:%s", 0
+      },
+	{ 0,1,5,
+	  -1, 2, 3.3, 'b', "ab", { 0x0000 }
+	},
+      },
+      /*------------------------ 02 -----------------------*/
+      { { {
+	0x30A2, 0x30A4, 0x0000
+      },
+	  L"%ls", 'S'
+      },
+	{ 0,1,1,
+	  0,0,0,0,"", { 0x30A2, 0x30A4, 0x0000 }
+	},
+      },
+      /*------------------------ 03 -----------------------*/
+      { { {
+	0x0031,			0x003A,
+	0x0030,			0x003A,
+	0x0033, 0x002E, 0x0039, 0x003A,
+	0x0061,			0x003A,
+	0x0063, 0x0064, 0x0000, 0x0000,
+      },
+	  L"%2$d:%1$u:%3$f:%4$c:%5$s", 0
+      },
+	{ 0,1,5,
+	  0, 1, 3.9, 'a', "cd", { 0x0000 }
+	},
+      },
+#ifdef SHOJI_IS_RIGHT
+      /* XXX This test does not make sense.  The format string is
+	 L"\x1\x2\x25\x53" and it is supposed to match the words
+	 0x30A2, 0x30A4, 0x0001.  */
+      /*------------------------ 04 -----------------------*/
+      /*  x 2 */
+      { { {
+	0x30A2, 0x30A4, 0x0001, 0x0000
+      },
+	  { 0x0001,0x0002,0x0025,0x0053,0x0000 }, 'S'
+      },
+	{ EILSEQ,1,EOF,
+	  0,0,0,0,"", { 0x0000 }
+	},
+      },
+#endif
+      /*---------------------------------------------------*/
+      { .is_last = 1}	/* Last element.  */
+    }
+  },
+  {
+    { Tswscanf, TST_LOC_end }
+  }
+};
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_tow-funcs.h b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_tow-funcs.h
new file mode 100644
index 00000000..44564374
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_tow-funcs.h
@@ -0,0 +1,24 @@
+/*
+ *  TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY
+ *
+ *       FILE:  dat_tow-funcs.h
+ *
+ *       ISW*:  int tow*( wint_t wc );
+ */
+
+#include 
+#include 
+#include 
+#include "tst_types.h"
+#include "tgn_locdef.h"
+
+#define TST_TOW_LOC(FUNC, func) \
+        TST_TOW## FUNC    tst_tow## func ##_loc[]
+
+#define TST_TOW_REC(locale, func) \
+        {  Ttow## func,    TST_LOC_## locale },
+
+/*
+ *  NOTE:
+ *        need more test data!
+ */
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_towctrans.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_towctrans.c
new file mode 100644
index 00000000..cf3712a2
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_towctrans.c
@@ -0,0 +1,97 @@
+/*
+ *  TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY
+ *
+ *	 FILE:	dat_towctrans.c
+ *
+ *	 TOWCTRANS:  wint_t towctrans (wint_t wc, wctrans_t charclass);
+ */
+
+#include 
+#include 
+#include 
+#include "tst_types.h"
+#include "tgn_locdef.h"
+
+/*
+ *  NOTE:
+ *    Set ret_flg = 1, when a return value is expected to be 0 (FALSE).
+ *    Set ret_flg = 0, when a return value is expected to be non-zero (TRUE).
+ *
+ *    Since the functions return *non*-zero value for TRUE, can't
+ *    compare an actual return value with an expected return value.
+ *    Set the ret_flg=0 for TRUE cases and the tst_isw*() will check
+ *    the non-zero value.
+ *
+ *  { { WEOF }, { 0,0,1,0 } },
+ *		      | |
+ *		      | ret_val: an expected return value
+ *		      ret_flg: if 1, compare an actual return value with the
+ *			       ret_val; if 0, the test program checks
+ *			       the actual return value.
+ *
+ *    CAUTION: if a charclass is invalid, the test function gives
+ *    towctrans() an invalid wctrans object instead of a return value
+ *    from wctrans() which is supposed to be 0.
+ */
+
+TST_TOWCTRANS tst_towctrans_loc [] = {
+  {
+    { Ttowctrans, TST_LOC_C },
+    {
+#ifdef SHOJI_IS_RIGHT
+      {	 { 0x0010, "xxxxxxx" }, { EINVAL,1,0x0010 }  },
+#else
+      {	 { 0x0010, "xxxxxxx" }, { 0,     1,0x0010 }  },
+#endif
+      {	 { 0x007F, "tolower" }, { 0,	   1,0x007F }  },
+      {	 { 0x0061, "toupper" }, { 0,	   1,0x0041 }  },
+      {	 { 0x0041, "tolower" }, { 0,	   1,0x0061 }  },
+      { .is_last = 1 }
+    }
+  },
+  {
+    { Ttowctrans, TST_LOC_de },
+    {
+#ifdef SHOJI_IS_RIGHT
+      {	 { 0x0010, "tojkata" }, { EINVAL,1,0x0010 }  },
+#else
+      {	 { 0x0010, "tojkata" }, { 0,     1,0x0010 }  },
+#endif
+      {	 { 0x0080, "tolower" }, { 0,	   1,0x0080 }  },
+      {	 { 0x00EC, "toupper" }, { 0,	   1,0x00CC }  },
+      {	 { 0x00CC, "tolower" }, { 0,	   1,0x00EC }  },
+      { .is_last = 1 }
+    }
+  },
+  {
+    { Ttowctrans, TST_LOC_enUS },
+    {
+#ifdef SHOJI_IS_RIGHT
+      {	 { 0x0010, "xxxxxxx" }, { EINVAL,1,0x0010 }  },
+#else
+      {	 { 0x0010, "xxxxxxx" }, { 0,     1,0x0010 }  },
+#endif
+      {	 { 0x007F, "tolower" }, { 0,	   1,0x007F }  },
+      {	 { 0x0061, "toupper" }, { 0,	   1,0x0041 }  },
+      {	 { 0x0041, "tolower" }, { 0,	   1,0x0061 }  },
+      { .is_last = 1 }
+    }
+  },
+  {
+#if 0
+    { Ttowctrans, TST_LOC_eucJP },
+#else
+    { Ttowctrans, TST_LOC_ja_UTF8 },
+#endif
+    {
+      {	 { 0xFF21, "tolower" }, { 0,	   1,0xFF41 }  },
+      {	 { 0xFF41, "toupper" }, { 0,	   1,0xFF21 }  },
+      {	 { 0x30A1, "tojhira" }, { 0,	   1,0x3041 }  },
+      {	 { 0x3041, "tojkata" }, { 0,	   1,0x30A1 }  },
+      { .is_last = 1 }
+    }
+  },
+  {
+    { Ttowctrans, TST_LOC_end }
+  }
+};
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_towlower.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_towlower.c
new file mode 100644
index 00000000..b6dd275f
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_towlower.c
@@ -0,0 +1,47 @@
+/*
+ *  TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY
+ *
+ *	 FILE:	dat_towlower.c
+ *
+ *	 ISW*:	int towlower (wint_t wc);
+ */
+
+
+#include "dat_tow-funcs.h"
+
+
+TST_TOW_LOC (LOWER, lower) = {
+
+  {   TST_TOW_REC (de, lower)
+      {
+	{  { WEOF   }, { 0,  1, (wint_t)-1 }	},
+	{  { 0x0080 }, { 0,  1, 0x0080     }	},
+	{  { 0x00CC }, { 0,  1, 0x00EC     }	},
+	{  { 0x00EC }, { 0,  1, 0x00EC     }	},
+	{ .is_last = 1 } /* Last element.	 */
+      }
+  },
+  {   TST_TOW_REC (enUS, lower)
+      {
+	{  { WEOF   }, { 0,  1, (wint_t)-1 }	},
+	{  { 0x007F }, { 0,  1, 0x007F     }	},
+	{  { 0x0041 }, { 0,  1, 0x0061     }	},
+	{  { 0x0061 }, { 0,  1, 0x0061     }	},
+	{ .is_last = 1 } /* Last element.	 */
+      }
+  },
+#if 0
+  {   TST_TOW_REC (eucJP, lower)
+#else
+  {   TST_TOW_REC (ja_UTF8, lower)
+#endif
+      {
+	{  { 0x007F }, { 0,  1, 0x007F     }	},
+	{  { 0x0080 }, { 0,  1, 0x0080     }	},
+	{  { 0xFF21 }, { 0,  1, 0xFF41     }	},
+	{  { 0xFF41 }, { 0,  1, 0xFF41     }	},
+	{ .is_last = 1 } /* Last element.	 */
+      }
+  },
+  {   TST_TOW_REC (end, lower) }
+};
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_towupper.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_towupper.c
new file mode 100644
index 00000000..704ad44a
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_towupper.c
@@ -0,0 +1,47 @@
+/*
+ *  TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY
+ *
+ *	 FILE:	dat_towupper.c
+ *
+ *	 ISW*:	int towupper (wint_t wc);
+ */
+
+
+#include "dat_tow-funcs.h"
+
+
+TST_TOW_LOC (UPPER, upper) = {
+
+  {   TST_TOW_REC (de, upper)
+      {
+	{  { WEOF   }, { 0,  1, (wint_t)-1 }	},
+	{  { 0x0080 }, { 0,  1, 0x0080     }	},
+	{  { 0x00EC }, { 0,  1, 0x00CC     }	},
+	{  { 0x00CC }, { 0,  1, 0x00CC     }	},
+	{ .is_last = 1 } /* Last element.	 */
+      }
+  },
+  {   TST_TOW_REC (enUS, upper)
+      {
+	{  { WEOF   }, { 0,  1, (wint_t)-1 }	},
+	{  { 0x0080 }, { 0,  1, 0x0080     }	},
+	{  { 0x0041 }, { 0,  1, 0x0041     }	},
+	{  { 0x0061 }, { 0,  1, 0x0041     }	},
+	{ .is_last = 1 } /* Last element.	 */
+      }
+  },
+#if 0
+  {   TST_TOW_REC (eucJP, upper)
+#else
+  {   TST_TOW_REC (ja_UTF8, upper)
+#endif
+      {
+	{  { WEOF   }, { 0,  1, (wint_t)-1 }	},
+	{  { 0x007F }, { 0,  1, 0x007F     }	},
+	{  { 0xFF41 }, { 0,  1, 0xFF21     }	},
+	{  { 0xFF21 }, { 0,  1, 0xFF21     }	},
+	{ .is_last = 1 } /* Last element.	 */
+      }
+  },
+  {   TST_TOW_REC (end, upper) }
+};
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wcrtomb.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wcrtomb.c
new file mode 100644
index 00000000..055f7b08
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wcrtomb.c
@@ -0,0 +1,122 @@
+/*
+ *  TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY
+ *
+ *	 FILE:	dat_wcrtomb.c
+ *
+ *	 WCRTOMB:  intwcrtomb (char *s, wchar_t wc, mbstate_t *ps);
+ *
+ */
+
+TST_WCRTOMB tst_wcrtomb_loc [] = {
+  {
+    { Twcrtomb, TST_LOC_de },
+    {
+      /* #01 : normal case			       */
+      { /*input.*/ { 1,		 0x00FC,   0,0 },
+	/*expect*/ { 0,	   1,1,	 "ü"	       },
+      },
+      /* #02 : normal case			       */
+      { /*input.*/ { 1,		 0x00D6,   0,0 },
+	/*expect*/ { 0,	   1,1,	 "Ö"	       },
+      },
+      /* #03 : error case			       */
+      { /*input.*/ { 1,		 0xFFA1,   0,0 },
+	/*expect*/ {  EILSEQ,1,-1, ""	       },
+      },
+      /* #04 :				       */
+      { /*input.*/ { 0,		 0x0041,   0,0 },
+	/*expect*/ { 0,	   1,1,	 ""	       },
+      },
+      /* #05 :				       */
+      { /*input.*/ { 0,		 0x0092,   0,0 },
+	/*expect*/ { 0,	   1,1,	 ""	       },
+      },
+      { .is_last = 1 }
+    }
+  },
+  {
+    { Twcrtomb, TST_LOC_enUS },
+    {
+      /* #01 : normal case			       */
+      { /*input.*/ { 1,		 0x0041,   0,0 },
+	/*expect*/ { 0,	   1,1,	 "A"	       },
+      },
+      /* #02 : normal case			       */
+      { /*input.*/ { 1,		 0x0042,   0,0 },
+	/*expect*/ { 0,	   1,1,	 "B"	       },
+      },
+      /* #03 : error case			       */
+      /*  x 2 */
+      { /*input.*/ { 1,		 0x0092,   0,0 },  /* assume ascii */
+	/*expect*/ {  EILSEQ,1,-1, ""	       },
+      },
+      /* #04 :				       */
+      { /*input.*/ { 0,		 0x0041,   0,0 },
+	/*expect*/ { 0,	   1,1,	 ""	       },
+      },
+      /* #05 :				       */
+      { /*input.*/ { 0,		 0x0092,   0,0 },
+	/*expect*/ { 0,	   1,1,	 ""	       },
+      },
+      { .is_last = 1 }
+    }
+  },
+#if 0
+  {
+    { Twcrtomb, TST_LOC_eucJP },
+    {
+      /* #01 : normal case			       */
+      { /*input.*/ { 1,		 0x3042,   0,0 },
+	/*expect*/ { 0,      1,2,  "\244\242"	   },
+      },
+      /* #02 : normal case			       */
+      { /*input.*/ { 1,		 0x3044,   0,0 },
+	/*expect*/ { 0,      1,2,  "\244\244"	   },
+      },
+      /* #03 : normal case			       */
+      { /*input.*/ { 1,		 0x008E,   0,0 },
+	/*expect*/ { EILSEQ, 1,-1, ""	       },
+      },
+      /* #04 :				       */
+      { /*input.*/ { 0,		 0x3042,   0,0 },
+	/*expect*/ { 0,	   0,0,	 ""	       },
+      },
+      /* #05 :				       */
+      { /*input.*/ { 0,		 0x008E,   0,0 },
+	/*expect*/ { 0,	   0,0,	 ""	       },
+      },
+      { .is_last = 1 }
+    }
+  },
+#else
+  {
+    { Twcrtomb, TST_LOC_ja_UTF8 },
+    {
+      /* #01 : normal case			       */
+      { /*input.*/ { 1,		 0x3042,   0,0 },
+	/*expect*/ { 0,      1,3,  "\343\201\202"	   },
+      },
+      /* #02 : normal case			       */
+      { /*input.*/ { 1,		 0x3044,   0,0 },
+	/*expect*/ { 0,      1,3,  "\343\201\204"	   },
+      },
+      /* #03 : normal case			       */
+      { /*input.*/ { 1,		 0x008E,   0,0 },
+	/*expect*/ { EILSEQ, 1,-1, ""	       },
+      },
+      /* #04 :				       */
+      { /*input.*/ { 0,		 0x3042,   0,0 },
+	/*expect*/ { 0,	   0,0,	 ""	       },
+      },
+      /* #05 :				       */
+      { /*input.*/ { 0,		 0x008E,   0,0 },
+	/*expect*/ { 0,	   0,0,	 ""	       },
+      },
+      { .is_last = 1 }
+    }
+  },
+#endif
+  {
+    { Twcrtomb, TST_LOC_end }
+  }
+};
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wcscat.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wcscat.c
new file mode 100644
index 00000000..f54e72de
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wcscat.c
@@ -0,0 +1,116 @@
+/*
+ *  TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY
+ *
+ *	 FILE:	dat_wcscat.c
+ *
+ *	 WCSCAT:  wchar_t *wcscat (wchar_t *ws1, wchar_t *ws2)
+ */
+
+/* NOTE:
+   Since this is not a locale sensitive function,
+   it doesn't make sense to test the function on some
+   locales. Better make different test cases for each locale ...
+   (Also some wc* functions are not locale sensitive.)
+*/
+
+
+TST_WCSCAT tst_wcscat_loc [] = {
+
+  {
+    {Twcscat, TST_LOC_de},
+    {
+      /* 1 */
+      {{{ 0x00C1,0x00C2,0x0000	},
+	{			0x00C3,0x00C4,0x0000 }, },
+       {   0,	0,    0,
+	   { 0x00C1,0x00C2,0x00C3,0x00C4,0x0000 }	},
+      },
+      /* 2 */
+      {{{ 0x0001,0x0002,0x0000	},
+	{			0x0003,0x0004,0x0000 }, },
+       {   0,	0,    0,
+	   { 0x0001,0x0002,0x0003,0x0004,0x0000 }	},
+      },
+      /* 3 */
+      {{{ 0x0000		  },
+	{			0x00C3,0x00C4,0x0000 }, },
+       {   0,	0,    0,
+	   {		0x00C3,0x00C4,0x0000 }	},
+      },
+      /* 4 */
+      {{{ 0x0001,0xFFFF,0x0000	},
+	{			0x0080,0x0090,0x0000 }, },
+       {   0,	0,    0,
+	   { 0x0001,0xFFFF,0x0080,0x0090,0x0000 }	},
+      },
+      {.is_last = 1}
+    }
+  },
+  {
+    {Twcscat, TST_LOC_enUS},
+    {
+      /* 1 */
+      {{{ 0x0041,0x0042,0x0000	},
+	{		  0x0043,0x0044,0x0000 }, },
+       {   0,	  0,	0,
+	   { 0x0041,0x0042,0x0043,0x0044,0x0000 }  },
+      },
+      /* 2 */
+      {{{ 0x0001,0x0002,0x0000	},
+	{		  0x0003,0x0004,0x0000 }, },
+       {   0,	  0,	0,
+	   { 0x0001,0x0002,0x0003,0x0004,0x0000 }  },
+      },
+      /* 3 */
+      {{{ 0x0000		    },
+	{		  0x0043,0x0044,0x0000 }, },
+       {   0,	  0,	0,
+	   {		  0x0043,0x0044,0x0000 }  },
+      },
+      /* 4 */
+      {{{ 0x0001,0xFFFF,0x0000	},
+	{		  0x0080,0x0090,0x0000 }, },
+       {   0,	  0,	0,
+	   { 0x0001,0xFFFF,0x0080,0x0090,0x0000 }  },
+      },
+      {.is_last = 1}
+    }
+  },
+  {
+#if 0
+    {Twcscat, TST_LOC_eucJP},
+#else
+    {Twcscat, TST_LOC_ja_UTF8},
+#endif
+    {
+      /* 1 */
+      {{{ 0x30A2,0x74E0,0x0000	},
+	{			0xFF71,0x0041,0x0000 }, },
+       {   0,	0,    0,
+	   { 0x30A2,0x74E0,0xFF71,0x0041,0x0000 }	},
+      },
+      /* 2 */
+      {{{ 0x0001,0x0002,0x0000	},
+	{			0x0003,0x0004,0x0000 }, },
+       {   0,	0,    0,
+	   { 0x0001,0x0002,0x0003,0x0004,0x0000 }	},
+      },
+      /* 3 */
+      {{{ 0x30A2,0xFF71,0x0000	},
+	{			0x0000		     }, },
+       {   0,	0,    0,
+	   { 0x30A2,0xFF71,0x0000		     }	},
+      },
+      /* 4 */
+      {{{ 0x0001,0xFFFF,0x0000	},
+	{			0x0080,0x0090,0x0000 }, },
+       {   0,	0,    0,
+	   { 0x0001,0xFFFF,0x0080,0x0090,0x0000 }	},
+      },
+      {.is_last = 1}
+    }
+  },
+  {
+    {Twcscat, TST_LOC_end}
+  }
+};
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wcschr.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wcschr.c
new file mode 100644
index 00000000..aa355e98
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wcschr.c
@@ -0,0 +1,94 @@
+/*
+ *  TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY
+ *
+ *	 FILE:	dat_wcschr.c
+ *
+ *	 WCSCHR:  wchar_t  *wcschr (const wchar_t *ws, wchar_t wc);
+ */
+
+TST_WCSCHR tst_wcschr_loc [] = {
+
+    {	{ Twcschr, TST_LOC_de },
+	{
+	  { /*input.*/ { { 0x00C1,0x00C2,0x00C3,0x0000 }, 0x00C0 },  /* #1 */
+	    /*expect*/ { 0,1,(wchar_t *)NULL },
+	  },
+	  { /*input.*/ { { 0x00C1,0x00C2,0x00C3,0x0000 }, 0x00C1 },  /* #2 */
+	    /*expect*/ { 0,0,0 },
+	  },
+	  { /*input.*/ { { 0x00C1,0x00C2,0x00C3,0x0000 }, 0x00C2 },  /* #3 */
+	    /*expect*/ { 0,0,0 },
+	  },
+	  { /*input.*/ { { 0x00C1,0x00C2,0x00C3,0x0000 }, 0x00C3 },  /* #4 */
+	    /*expect*/ { 0,0,0 },
+	  },
+	  { /*input.*/ { { 0x00C1,0x00C2,0x00C3,0x0000 }, 0x0000 },  /* #5 */
+	    /*expect*/ { 0,0,0 },
+	  },
+	  { /*input.*/ { { 0x0000,0x00C2,0x00C3,0x0000 }, 0x00C1 },  /* #6 */
+	    /*expect*/ { 0,1,(wchar_t *)NULL },
+	  },
+	  { /*input.*/ { { 0x0000,0x00C2,0x00C3,0x0000 }, 0x0000 },  /* #7 */
+	    /*expect*/ { 0,0,0 },
+	  },
+	  { .is_last = 1 }
+	}
+    },
+    {	{ Twcschr, TST_LOC_enUS },
+	{
+	  { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 }, 0x0040 },  /* #1 */
+	    /*expect*/ { 0,1,(wchar_t *)NULL },
+	  },
+	  { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 }, 0x0041 },  /* #2 */
+	    /*expect*/ { 0,0,0 },
+	  },
+	  { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 }, 0x0042 },  /* #3 */
+	    /*expect*/ { 0,0,0 },
+	  },
+	  { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 }, 0x0043 },  /* #4 */
+	    /*expect*/ { 0,0,0 },
+	  },
+	  { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 }, 0x0000 },  /* #5 */
+	    /*expect*/ { 0,0,0 },
+	  },
+	  { /*input.*/ { { 0x0000,0x0042,0x0043,0x0000 }, 0x0041 },  /* #6 */
+	    /*expect*/ { 0,1,(wchar_t *)NULL },
+	  },
+	  { /*input.*/ { { 0x0000,0x0042,0x0043,0x0000 }, 0x0000 },  /* #7 */
+	    /*expect*/ { 0,0,0 },
+	  },
+	  { .is_last = 1 }
+	}
+    },
+#if 0
+    {	{ Twcschr, TST_LOC_eucJP },
+#else
+    {	{ Twcschr, TST_LOC_ja_UTF8 },
+#endif
+	{
+	  { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 }, 0x3040 },  /* #1 */
+	    /*expect*/ { 0,1,(wchar_t *)NULL },
+	  },
+	  { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 }, 0x3041 },  /* #2 */
+	    /*expect*/ { 0,0,0 },
+	  },
+	  { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 }, 0x3042 },  /* #3 */
+	    /*expect*/ { 0,0,0 },
+	  },
+	  { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 }, 0x3043 },  /* #4 */
+	    /*expect*/ { 0,0,0 },
+	  },
+	  { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 }, 0x0000 },  /* #5 */
+	    /*expect*/ { 0,0,0 },
+	  },
+	  { /*input.*/ { { 0x0000,0x3042,0x3043,0x0000 }, 0x3041 },  /* #6 */
+	    /*expect*/ { 0,1,(wchar_t *)NULL },
+	  },
+	  { /*input.*/ { { 0x0000,0x3042,0x3043,0x0000 }, 0x0000 },  /* #7 */
+	    /*expect*/ { 0,0,0 },
+	  },
+	  { .is_last = 1 }
+	}
+    },
+    {	{ Twcschr, TST_LOC_end } }
+};
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wcscmp.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wcscmp.c
new file mode 100644
index 00000000..a2da5519
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wcscmp.c
@@ -0,0 +1,137 @@
+/*
+ *  TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY
+ *
+ *	 FILE: dat_wcscmp.c
+ *
+ *	 WCSCMP:  int  wcscmp (const wchar_t *ws1, const wchar_t *ws2);
+ */
+
+/* NOTE:
+	This is not a locale sensitive function and
+	it may not make sence testing it for each locale ...
+*/
+
+
+TST_WCSCMP tst_wcscmp_loc [] = {
+  {
+    { Twcscmp, TST_LOC_de },
+    {
+      { /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 },
+		     { 0x00D1,0x00D2,0x00D3,0x0000 }, },  /* #1 */
+	/*expect*/ { 0,1,0,			  },
+      },
+      { /*input.*/ { { 0x0000,0x00D1,0x00D3,0x0000 },
+		     { 0x0000,0x00D2,0x00D3,0x0000 }, },  /* #2 */
+	/*expect*/ { 0,1,0,			  },
+      },
+      { /*input.*/ { { 0x00D1,0x00D1,0x00D3,0x0000 },
+		     { 0x0000,0x00D2,0x00D3,0x0000 }, },  /* #3 */
+	/*expect*/ { 0,1,1,			  },
+      },
+      { /*input.*/ { { 0x0000,0x00D2,0x00D3,0x0000 },
+		     { 0x00D1,0x00D1,0x00D3,0x0000 }, },  /* #4 */
+	/*expect*/ { 0,1,-1,			  },
+      },
+      { /*input.*/ { { 0x00D1,0x00D5,0x00D3,0x0000 },
+		     { 0x00D1,0x00D2,0x00D3,0x0000 }, },  /* #5 */
+	/*expect*/ { 0,1,1,			  },
+      },
+      { /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 },
+		     { 0x00D1,0x00D2,0x00D9,0x0000 }, },  /* #6 */
+	/*expect*/ { 0,1,-1,			  },
+      },
+      { /*input.*/ { { 0x00D1,0x00D2,0x0000	       },
+		     { 0x00D1,0x00D2,0x00D9,0x0000 }, },  /* #7 */
+	/*expect*/ { 0,1,-1,			  },
+      },
+      { /*input.*/ { { 0x00D1,0x00D2,0x00D9,0x0000 },
+		     { 0x00D1,0x00D2,0x0000	       }, },  /* #8 */
+	/*expect*/ { 0,1,1,			  },
+      },
+      { .is_last = 1 }
+    }
+  },
+  {
+    { Twcscmp, TST_LOC_enUS },
+    {
+      { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 },
+		     { 0x0041,0x0042,0x0043,0x0000 }, },  /* #1 */
+	/*expect*/ { 0,1,0,			  },
+      },
+      { /*input.*/ { { 0x0000,0x0041,0x0043,0x0000 },
+		     { 0x0000,0x0042,0x0043,0x0000 }, },  /* #2 */
+	/*expect*/ { 0,1,0,			  },
+      },
+      { /*input.*/ { { 0x0041,0x0041,0x0043,0x0000 },
+		     { 0x0000,0x0042,0x0043,0x0000 }, },  /* #3 */
+	/*expect*/ { 0,1,1,			  },
+      },
+      { /*input.*/ { { 0x0000,0x0042,0x0043,0x0000 },
+		     { 0x0041,0x0041,0x0043,0x0000 }, },  /* #4 */
+	/*expect*/ { 0,1,-1,			  },
+      },
+      { /*input.*/ { { 0x0041,0x0045,0x0043,0x0000 },
+		     { 0x0041,0x0042,0x0043,0x0000 }, },  /* #5 */
+	/*expect*/ { 0,1,1,			  },
+      },
+      { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 },
+		     { 0x0041,0x0042,0x0049,0x0000 }, },  /* #6 */
+	/*expect*/ { 0,1,-1,			  },
+      },
+      { /*input.*/ { { 0x0041,0x0042,0x0000	       },
+		     { 0x0041,0x0042,0x0049,0x0000 }, },  /* #7 */
+	/*expect*/ { 0,1,-1,			  },
+      },
+      { /*input.*/ { { 0x0041,0x0042,0x0049,0x0000 },
+		     { 0x0041,0x0042,0x0000	       }, },  /* #8 */
+	/*expect*/ { 0,1,1,			  },
+      },
+      { .is_last = 1 }
+    }
+  },
+  {
+#if 0
+    { Twcscmp, TST_LOC_eucJP},
+#else
+    { Twcscmp, TST_LOC_ja_UTF8},
+#endif
+    {
+      { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 },
+		     { 0x3041,0x3042,0x3043,0x0000 }, },  /* #1 */
+	/*expect*/ { 0,1,0,			  },
+      },
+      { /*input.*/ { { 0x0000,0x3041,0x3043,0x0000 },
+		     { 0x0000,0x3042,0x3043,0x0000 }, },  /* #2 */
+	/*expect*/ { 0,1,0,			  },
+      },
+      { /*input.*/ { { 0x3041,0x3041,0x3043,0x0000 },
+		     { 0x0000,0x3042,0x3043,0x0000 }, },  /* #3 */
+	/*expect*/ { 0,1,1,			  },
+      },
+      { /*input.*/ { { 0x0000,0x3042,0x3043,0x0000 },
+		     { 0x3041,0x3041,0x3043,0x0000 }, },  /* #4 */
+	/*expect*/ { 0,1,-1,			  },
+      },
+      { /*input.*/ { { 0x3041,0x3045,0x3043,0x0000 },
+		     { 0x3041,0x3042,0x3043,0x0000 }, },  /* #5 */
+	/*expect*/ { 0,1,1,			  },
+      },
+      { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 },
+		     { 0x3041,0x3042,0x3049,0x0000 }, },  /* #6 */
+	/*expect*/ { 0,1,-1,			  },
+      },
+      { /*input.*/ { { 0x3041,0x3042,0x0000	       },
+		     { 0x3041,0x3042,0x3049,0x0000 }, },  /* #7 */
+	/*expect*/ { 0,1,-1,			  },
+      },
+      { /*input.*/ { { 0x3041,0x3042,0x3049,0x0000 },
+		     { 0x3041,0x3042,0x0000	       }, },  /* #8 */
+	/*expect*/ { 0,1,1,			  },
+      },
+      { .is_last = 1 }
+    }
+  },
+  {
+    { Twcschr, TST_LOC_end}
+  }
+};
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wcscoll.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wcscoll.c
new file mode 100644
index 00000000..a9733ad8
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wcscoll.c
@@ -0,0 +1,210 @@
+/*
+ *  TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY
+ *
+ *	 FILE: dat_wcscoll.c
+ *
+ *	 WCSCOLL:  int	wcscoll (const wchar_t *ws1, const wchar_t *ws2);
+ */
+
+/*
+ *  CAUTION:
+ *	     When LC_COLLATE (or LC_ALL) is set for ja_JP.EUC,
+ *	     wcscoll() core-dumps for big values such as 0x3041
+ *	     (0x0041 is okay) in glibc 2.1.2.
+ *
+ *  NOTE:
+ *    a) When 0 is expected as a return value, set ret_flg=1.
+ *	 - the return value is compared with an expected value: ret_val.
+ *    b) When a positive value is expected as a return value,
+ *	 set ret_flg=0 and set cmp_flg=+1.
+ *	 - the return value is not compared with the expected value
+ *	   (can not be compared); instead, the test program checks
+ *	   if the return value is positive when cmp_flg=+1.
+ *    c) When a negative value is expected as a return value,
+ *	 ......
+ *    d) When data contains invalid values, set err_val to the expected errno.
+ *	 Set ret_flg=0 and cmp_flg=0 so that it doesn't compare
+ *	 the return value with an expected value or doesn't check
+ *	 the sign of the return value.
+ *
+ *
+ *	     -------------------------------------------
+ *	     CASE  err_val   ret_flg  ret_val	 cmp_flg
+ *	     -------------------------------------------
+ *	      a)      0	 1	  0	    0
+ *	      b)      0	 0	  0	   +1
+ *	      c)      0	 0	  0	   -1
+ *	      d)    EINVAL	 0	  0	    0
+ *	     -------------------------------------------
+ */
+
+
+TST_WCSCOLL tst_wcscoll_loc [] = {
+
+    {	{ Twcscoll, TST_LOC_de },
+	{
+	  { /*input.*/ { { 0x00E1,0x00E2,0x00E3,0x0000 },
+			 { 0x00E1,0x00E2,0x00E3,0x0000 }, },  /* #1 */
+	    /*expect*/ { 0,1,0, 0,			  },
+	  },
+	  { /*input.*/ { { 0x0000,0x00E1,0x00E3,0x0000 },
+			 { 0x0000,0x00E2,0x00E3,0x0000 }, },  /* #2 */
+	    /*expect*/ { 0,1,0, 0,			  },
+	  },
+	  { /*input.*/ { { 0x00E1,0x00E1,0x00E3,0x0000 },
+			 { 0x0000,0x00E2,0x00E3,0x0000 }, },  /* #3 */
+	    /*expect*/ { 0,0,0, +1,			  },
+	  },
+	  { /*input.*/ { { 0x0000,0x00E2,0x00E3,0x0000 },
+			 { 0x00E1,0x00E1,0x00E3,0x0000 }, },  /* #4 */
+	    /*expect*/ { 0,0,0, -1,			  },
+	  },
+	  { /*input.*/ { { 0x00E1,0x0042,0x00E3,0x0000 },
+			 { 0x00E1,0x0061,0x00E3,0x0000 }, },  /* #5 */
+	    /*expect*/ { 0,0,0, +1,			  },
+	  },
+	  { /*input.*/ { { 0x00E1,0x0061,0x00E3,0x0000 },
+			 { 0x00E1,0x0042,0x00E3,0x0000 }, },  /* #6 */
+	    /*expect*/ { 0,0,0, -1,			  },
+	  },
+	  { /*input.*/ { { 0x00E1,0x00E2,0x0000	       },
+			 { 0x00E1,0x00E2,0x00E9,0x0000 }, },  /* #7 */
+	    /*expect*/ { 0,0,0, -1,			  },
+	  },
+	  { /*input.*/ { { 0x00E1,0x00E2,0x00E9,0x0000 },
+			 { 0x00E1,0x00E2,0x0000	       }, },  /* #8 */
+	    /*expect*/ { 0,0,0, +1,			  },
+	  },
+	  { /*input.*/ { { 0x00E1,0x0092,0x00E9,0x0000 },
+			 { 0x00E1,0x008E,0x00E9,0x0000 }, },  /* #9 */
+	    /*expect*/ { 0,0,0, +1,		       },
+	  },
+	  { /*input.*/ { { 0x00E1,0x008E,0x00E9,0x0000 },
+			 { 0x00E1,0x0092,0x00E9,0x0000 }, },  /* #10 */
+	    /*expect*/ { 0,0,0, -1,		       },
+	  },
+	  { .is_last = 1 }
+	}
+    },
+    {	{ Twcscoll, TST_LOC_en },
+	{
+	  { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 },
+			 { 0x0041,0x0042,0x0043,0x0000 }, },  /* #1 */
+	    /*expect*/ { 0,1,0, 0,			  },
+	  },
+	  { /*input.*/ { { 0x0000,0x0041,0x0043,0x0000 },
+			 { 0x0000,0x0042,0x0043,0x0000 }, },  /* #2 */
+	    /*expect*/ { 0,1,0, 0,			  },
+	  },
+	  { /*input.*/ { { 0x0041,0x0041,0x0043,0x0000 },
+			 { 0x0000,0x0042,0x0043,0x0000 }, },  /* #3 */
+	    /*expect*/ { 0,0,0, +1,			  },
+	  },
+	  { /*input.*/ { { 0x0000,0x0042,0x0043,0x0000 },
+			 { 0x0041,0x0041,0x0043,0x0000 }, },  /* #4 */
+	    /*expect*/ { 0,0,0, -1,			  },
+	  },
+#ifdef SHOJI_IS_RIGHT
+	  /*  */ /* assume ascii */
+	  { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 },
+			 { 0x0041,0x0061,0x0043,0x0000 }, },  /* #5 */
+	    /*expect*/ { 0,0,0, -1,			  },
+	  },
+	  /*  */ /* assume ascii */
+	  { /*input.*/ { { 0x0041,0x0061,0x0043,0x0000 },
+			 { 0x0041,0x0042,0x0043,0x0000 }, },  /* #6 */
+	    /*expect*/ { 0,0,0, +1,			  },
+	  },
+#else
+	  /* XXX Correct order is lowercase before uppercase.  */
+	  { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 },
+			 { 0x0041,0x0061,0x0043,0x0000 }, },  /* #5 */
+	    /*expect*/ { 0,0,0, +1,			  },
+	  },
+	  { /*input.*/ { { 0x0041,0x0061,0x0043,0x0000 },
+			 { 0x0041,0x0042,0x0043,0x0000 }, },  /* #6 */
+	    /*expect*/ { 0,0,0, -1,			  },
+	  },
+#endif
+	  { /*input.*/ { { 0x0041,0x0042,0x0000	       },
+			 { 0x0041,0x0042,0x0049,0x0000 }, },  /* #7 */
+	    /*expect*/ { 0,0,0, -1,			  },
+	  },
+	  { /*input.*/ { { 0x0041,0x0042,0x0049,0x0000 },
+			 { 0x0041,0x0042,0x0000	       }, },  /* #8 */
+	    /*expect*/ { 0,0,0, +1,			  },
+	  },
+#ifdef SHOJI_IS_RIGHT
+	  { /*input.*/ { { 0x0041,0x0092,0x0049,0x0000 },
+			 { 0x0041,0x008E,0x0049,0x0000 }, },  /* #9 */
+	    /*expect*/ { 0,0,0, +1,		       },
+	  },
+	  { /*input.*/ { { 0x0041,0x008E,0x0049,0x0000 },
+			 { 0x0041,0x0092,0x0049,0x0000 }, },  /* #10 */
+	    /*expect*/ { 0,0,0, -1,		       },
+	  },
+#else
+	  /* Do not assume position of character out of range.  */
+	  { /*input.*/ { { 0x0041,0x0092,0x0049,0x0000 },
+			 { 0x0041,0x008E,0x0049,0x0000 }, },  /* #9 */
+	    /*expect*/ { 0,0,0, 0,		       },
+	  },
+	  { /*input.*/ { { 0x0041,0x008E,0x0049,0x0000 },
+			 { 0x0041,0x0092,0x0049,0x0000 }, },  /* #10 */
+	    /*expect*/ { 0,0,0, 0,		       },
+	  },
+#endif
+	  { .is_last = 1 }
+	}
+    },
+#if 0
+    {	{ Twcscoll, TST_LOC_eucJP },
+#else
+    {	{ Twcscoll, TST_LOC_ja_UTF8 },
+#endif
+	{
+	  { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 },
+			 { 0x3041,0x3042,0x3043,0x0000 }, },  /* #1 */
+	    /*expect*/ { 0,1,0, 0,			  },
+	  },
+	  { /*input.*/ { { 0x0000,0x3041,0x3043,0x0000 },
+			 { 0x0000,0x3042,0x3043,0x0000 }, },  /* #2 */
+	    /*expect*/ { 0,1,0, 0,			  },
+	  },
+	  { /*input.*/ { { 0x3041,0x3041,0x3043,0x0000 },
+			 { 0x0000,0x3042,0x3043,0x0000 }, },  /* #3 */
+	    /*expect*/ { 0,0,0, +1,			  },
+	  },
+	  { /*input.*/ { { 0x0000,0x3042,0x3043,0x0000 },
+			 { 0x3041,0x3041,0x3043,0x0000 }, },  /* #4 */
+	    /*expect*/ { 0,0,0, -1,			  },
+	  },
+	  { /*input.*/ { { 0x3041,0x0042,0x3043,0x0000 },
+			 { 0x3041,0x0061,0x3043,0x0000 }, },  /* #5 */
+	    /*expect*/ { 0,0,0, -1,			  },
+	  },
+	  { /*input.*/ { { 0x3041,0x0061,0x3043,0x0000 },
+			 { 0x3041,0x0042,0x3043,0x0000 }, },  /* #6 */
+	    /*expect*/ { 0,0,0, +1,			  },
+	  },
+	  { /*input.*/ { { 0x3041,0x3042,0xFF71,0x0000 },
+			 { 0x3041,0x3042,0x30A2,0x0000 }, },  /* #7 */
+	    /*expect*/ { 0,0,0, -1,			  },
+	  },
+	  { /*input.*/ { { 0x3041,0x3042,0x30A2,0x0000 },
+			 { 0x3041,0x3042,0xFF71,0x0000 }, },  /* #8 */
+	    /*expect*/ { 0,0,0, +1,			  },
+	  },
+	  { /*input.*/ { { 0x30FF,0x3092,0x3049,0x0000 },
+			 { 0x3041,0x308E,0x3049,0x0000 }, },  /* #9 */
+	    /*expect*/ { 0,0,0, -1,		       },
+	  },
+	  { /*input.*/ { { 0x3041,0x308E,0x3049,0x0000 },
+			 { 0x30FF,0x3092,0x3049,0x0000 }, },  /* #10 */
+	    /*expect*/ { 0,0,0, +1,		       },
+	  },
+	  { .is_last = 1 }
+	}
+    },
+    {	{ Twcscoll, TST_LOC_end } }
+};
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wcscpy.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wcscpy.c
new file mode 100644
index 00000000..b376bfc5
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wcscpy.c
@@ -0,0 +1,44 @@
+/*
+ *  TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY
+ *
+ *	 FILE:	dat_wcscpy.c
+ *
+ *	 WCSCPY:  wchar_t *wcscpy (wchar_t *ws1, const wchar_t *ws2);
+ */
+
+TST_WCSCPY tst_wcscpy_loc [] = {
+
+    {	{ Twcscpy, TST_LOC_de },
+	{
+	    { {		  { 0x00F1,0x00F2,0x00F3,0x0000	 }, },	   /* 1 */
+	      {	 0,0,0,   { 0x00F1,0x00F2,0x00F3,0x0000, }  }, },
+	    { {		  { 0x0000,0x00F2,0x00F3,0x0000	 }, },	   /* 2 */
+	      {	 0,0,0,   { 0x0000,			 }  }, },
+	    { .is_last = 1 }
+	}
+    },
+    {	{ Twcscpy, TST_LOC_enUS },
+	{
+	    { {		  { 0x0041,0x0082,0x0043,0x0000	 }, },	   /* 1 */
+	      {	 0,0,0,   { 0x0041,0x0082,0x0043,0x0000, }  }, },
+	    { {		  { 0x0000,0x0082,0x0043,0x0000	 }, },	   /* 2 */
+	      {	 0,0,0,   { 0x0000,			 }  }, },
+	    { .is_last = 1 }
+	}
+    },
+#if 0
+    {	{ Twcscpy, TST_LOC_eucJP },
+#else
+    {	{ Twcscpy, TST_LOC_ja_UTF8 },
+#endif
+	{
+	    { {		  { 0x3041,0x0092,0x3043,0x0000	 }, },	   /* 1 */
+	      {	 0,0,0,   { 0x3041,0x0092,0x3043,0x0000, }  }, },
+	    { {		  { 0x0000,0x0092,0x3043,0x0000	 }, },	   /* 2 */
+	      {	 0,0,0,   { 0x0000,			 }  }, },
+	    { .is_last = 1 }
+	}
+    },
+    {	{ Twcscpy, TST_LOC_end }}
+
+};
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wcscspn.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wcscspn.c
new file mode 100644
index 00000000..f6eb0c3b
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wcscspn.c
@@ -0,0 +1,164 @@
+/*
+ *  TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY
+ *
+ *	 FILE:	dat_wcscspn.c
+ *
+ *	 WCSCSPN:  size_t wcscspn (const wchar_t *ws1, const wchar_t *ws2);
+ */
+
+
+TST_WCSCSPN tst_wcscspn_loc [] = {
+
+    {	{ Twcscspn, TST_LOC_de },
+	{
+	  { /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 },
+			 { 0x00D1,0x0000	       }, },  /* #1 */
+	    /*expect*/ { 0,1,0,			  },
+	  },
+	  { /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 },
+			 {	  0x00D2,0x0000	       }, },  /* #2 */
+	    /*expect*/ { 0,1,1,			  },
+	  },
+	  { /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 },
+			 {		 0x00D3,0x0000 }, },  /* #3 */
+	    /*expect*/ { 0,1,2,			  },
+	  },
+	  { /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 },
+			 {	  0x00D2,0x00D3,0x0000 }, },  /* #4 */
+	    /*expect*/ { 0,1,1,			  },
+	  },
+	  { /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 },
+			 { 0x00D2,0x00D3,0x00D4,0x0000 }, },  /* #5 */
+	    /*expect*/ { 0,1,1,			  },
+	  },
+	  { /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 },
+			 { 0x00D3,0x00D4,0x00D5,0x0000 }, },  /* #6 */
+	    /*expect*/ { 0,1,2,			  },
+	  },
+	  { /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 },
+			 { 0x00D1,0x00D2,0x00D3,0x0000 }, },  /* #7 */
+	    /*expect*/ { 0,1,0,			  },
+	  },
+	  { /*input.*/ { { 0x0000,0x00D2,0x00D3,0x0000 },
+			 { 0x00D2,0x000		       }, },  /* #8 */
+	    /*expect*/ { 0,1,0,			  },
+	  },
+	  { /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 },
+			 { 0x0000,0x00D2,0x00D3,0x0000 }, },  /* #9 */
+	    /*expect*/ { 0,1,3,			  },
+	  },
+	  { /*input.*/ { { 0x00D1,0x00D2,0x0000	       },
+			 { 0x00D1,0x00D2,0x00D3,0x0000 }, },  /* #10 */
+	    /*expect*/ { 0,1,0,			  },
+	  },
+	  { /*input.*/ { { 0x00D1,0x00D2,0x0000	       },
+			 { 0x00D1,0x00D3,0x00D4,0x0000 }, },  /* #11 */
+	    /*expect*/ { 0,1,0,			  },
+	  },
+	  { .is_last = 1 }
+	}
+    },
+    {	{ Twcscspn, TST_LOC_enUS },
+	{
+	  { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 },
+			 { 0x0041,0x0000	       }, },  /* #1 */
+	    /*expect*/ { 0,1,0,			  },
+	  },
+	  { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 },
+			 {	  0x0042,0x0000	       }, },  /* #2 */
+	    /*expect*/ { 0,1,1,			  },
+	  },
+	  { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 },
+			 {		 0x0043,0x0000 }, },  /* #3 */
+	    /*expect*/ { 0,1,2,			  },
+	  },
+	  { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 },
+			 {	  0x0042,0x0043,0x0000 }, },  /* #4 */
+	    /*expect*/ { 0,1,1,			  },
+	  },
+	  { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 },
+			 { 0x0042,0x0043,0x0044,0x0000 }, },  /* #5 */
+	    /*expect*/ { 0,1,1,			  },
+	  },
+	  { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 },
+			 { 0x0043,0x0044,0x0045,0x0000 }, },  /* #6 */
+	    /*expect*/ { 0,1,2,			  },
+	  },
+	  { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 },
+			 { 0x0041,0x0042,0x0043,0x0000 }, },  /* #7 */
+	    /*expect*/ { 0,1,0,			  },
+	  },
+	  { /*input.*/ { { 0x0000,0x0042,0x0043,0x0000 },
+			 { 0x0042,0x000		       }, },  /* #8 */
+	    /*expect*/ { 0,1,0,			  },
+	  },
+	  { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 },
+			 { 0x0000,0x0042,0x0043,0x0000 }, },  /* #9 */
+	    /*expect*/ { 0,1,3,			  },
+	  },
+	  { /*input.*/ { { 0x0041,0x0042,0x0000	       },
+			 { 0x0041,0x0042,0x0043,0x0000 }, },  /* #10 */
+	    /*expect*/ { 0,1,0,			  },
+	  },
+	  { /*input.*/ { { 0x0041,0x0042,0x0000	       },
+			 { 0x0041,0x0043,0x0044,0x0000 }, },  /* #11 */
+	    /*expect*/ { 0,1,0,			  },
+	  },
+	  { .is_last = 1 }
+	}
+    },
+#if 0
+    {	{ Twcscspn, TST_LOC_eucJP },
+#else
+    {	{ Twcscspn, TST_LOC_ja_UTF8 },
+#endif
+	{
+	  { /*input.*/ { { 0x3041,0x3042,0x0043,0x0000 },
+			 { 0x3041,0x0000	       }, },  /* #1 */
+	    /*expect*/ { 0,1,0,			  },
+	  },
+	  { /*input.*/ { { 0x3041,0x3042,0x0043,0x0000 },
+			 {	  0x3042,0x0000	       }, },  /* #2 */
+	    /*expect*/ { 0,1,1,			  },
+	  },
+	  { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 },
+			 {		 0x3043,0x0000 }, },  /* #3 */
+	    /*expect*/ { 0,1,2,			  },
+	  },
+	  { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 },
+			 {	  0x3042,0x3043,0x0000 }, },  /* #4 */
+	    /*expect*/ { 0,1,1,			  },
+	  },
+	  { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 },
+			 { 0x3042,0x3043,0x3044,0x0000 }, },  /* #5 */
+	    /*expect*/ { 0,1,1,			  },
+	  },
+	  { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 },
+			 { 0x3043,0x3044,0x3045,0x0000 }, },  /* #6 */
+	    /*expect*/ { 0,1,2,			  },
+	  },
+	  { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 },
+			 { 0x3041,0x3042,0x3043,0x0000 }, },  /* #7 */
+	    /*expect*/ { 0,1,0,			  },
+	  },
+	  { /*input.*/ { { 0x0000,0x3042,0x3043,0x0000 },
+			 { 0x3042,0x0000	       }, },  /* #8 */
+	    /*expect*/ { 0,1,0,			  },
+	  },
+	  { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 },
+			 { 0x0000,0x3042,0x3043,0x0000 }, },  /* #9 */
+	    /*expect*/ { 0,1,3,			  },
+	  },
+	  { /*input.*/ { { 0x3041,0x3042,0x0000	       },
+			 { 0x3041,0x3042,0x3043,0x0000 }, },  /* #10 */
+	    /*expect*/ { 0,1,0,			  },
+	  },
+	  { /*input.*/ { { 0x3041,0x3042,0x0000	       },
+			 { 0x3041,0x3043,0x3044,0x0000 }, },  /* #11 */
+	    /*expect*/ { 0,1,0,			  },
+	  },
+	  { .is_last = 1 }
+	}
+    },
+    {	{ Twcscspn, TST_LOC_end }}
+};
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wcslen.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wcslen.c
new file mode 100644
index 00000000..7bb2c892
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wcslen.c
@@ -0,0 +1,62 @@
+/*
+ *  TEST SUITE FOR MB/WC FUNCTIONS IN CLIBRARY
+ *
+ *       FILE:  dat_wcslen.c
+ *
+ *       WCSLEN:  size_t wcslen (const wchar_t *ws);
+ */
+
+
+/*
+ *  NOTE:
+ *
+ *      a header in each expected data:
+ *
+ *         int  err_val;  ... expected value for errno
+ *         ret_flg; ... set ret_flg=1 to compare an expected
+ *                           value with an actual value
+ *         ret_val; ... expected value for return
+ */
+
+
+TST_WCSLEN tst_wcslen_loc [] = {
+
+  {   { Twcslen, TST_LOC_de },
+      {
+	{ /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 } },  /* #01 */
+	  /*expect*/ { 0,1,3,                        },
+	},
+	{ /*input.*/ { { 0x0000 }                      },  /* #02 */
+	  /*expect*/ { 0,1,0,                        },
+	},
+	{ .is_last = 1 }
+      }
+  },
+  {   { Twcslen, TST_LOC_enUS },
+      {
+	{ /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 } },  /* #01 */
+	  /*expect*/ { 0,1,3,                        },
+	},
+	{ /*input.*/ { { 0x0000 }                      },  /* #02 */
+	  /*expect*/ { 0,1,0,                        },
+	},
+	{ .is_last = 1 }
+      }
+  },
+#if 0
+  {   { Twcslen, TST_LOC_eucJP },
+#else
+  {   { Twcslen, TST_LOC_ja_UTF8 },
+#endif
+      {
+	{ /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 } },  /* #01 */
+	  /*expect*/ { 0,1,3,                        },
+	},
+	{ /*input.*/ { { 0x0000 }                      },  /* #02 */
+	  /*expect*/ { 0,1,0,                        },
+	},
+	{ .is_last = 1 }
+      }
+  },
+  {   { Twcslen, TST_LOC_end }}
+};
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wcsncat.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wcsncat.c
new file mode 100644
index 00000000..9d1e46b9
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wcsncat.c
@@ -0,0 +1,158 @@
+/*
+ *  TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY
+ *
+ *	 FILE:	dat_wcsncat.c
+ *
+ *	 WCSNCAT:  wchar_t *wcsncat (wchar_t *ws1, wchar_t *ws2, size_t n);
+ */
+
+
+/*
+ *  Note:
+ *	  A terminating null wide chararacter is always appended to
+ *	  the result: ws1.
+ *
+ */
+
+
+TST_WCSNCAT tst_wcsncat_loc [] = {
+  {
+    {Twcsncat, TST_LOC_de},
+    {
+      /* 1 */
+      {
+	/* Input: */
+	{{ 0x00D1,0x00D2,0x0000	 },
+	 {		    0x00D3,0x00D4,0x0000 }, 3 },
+	/* Expect: */
+	{   0,	0,    0,
+	    { 0x00D1,0x00D2,0x00D3,0x00D4,0x0000 }    },
+      },
+      /* 2 */
+      {{{ 0x00D1,0x00D2,0x0000	},
+	{		   0x00D3,0x00D4,0x0000 }, 2 },
+       {   0,    0,    0,
+	   { 0x00D1,0x00D2,0x00D3,0x00D4,0x0000 }    },
+      },
+      /* 3 */
+      {{{ 0x00E1,0x00E2,0x0000	},
+	{		   0x00E3,0x00E4,0x0000 }, 1 },
+       {   0,    0,    0,
+	   { 0x00E1,0x00E2,0x00E3,0x0000	}    },
+      },
+      /* 4 */
+      {{{ 0x00E1,0x00E2,0x0000	},
+	{		   0x00E3,0x00E4,0x0000 }, 0 },
+       {   0,    0,    0,
+	   { 0x00E1,0x00E2,0x0000		}    },
+      },
+      /* 5 */
+      {{{ 0x0000		},
+	{		   0x00D3,0x00D4,0x0000 }, 3 },
+       {   0,    0,    0,
+	   {		   0x00D3,0x00D4,0x0000 }    },
+      },
+      /* 6 */
+      {{{ 0x00E1,0x00E2,0x0000	},
+	{		   0x0000		}, 3 },
+       {   0,    0,    0,
+	   { 0x00E1,0x00E2,0x0000		}    },
+      },
+      {.is_last = 1}
+    }
+  },
+  {
+    {Twcsncat, TST_LOC_enUS},
+    {
+      /* 1 */
+      {
+	/* Input:  */
+	{{ 0x0041,0x0042,0x0000	 },
+	 {		    0x0043,0x0044,0x0000 }, 3 },
+	/* Expect:  */
+	{   0,	0,    0,
+	    { 0x0041,0x0042,0x0043,0x0044,0x0000 }    },
+      },
+      /* 2 */
+      {{{ 0x0041,0x0042,0x0000	},
+	{		   0x0043,0x0044,0x0000 }, 2 },
+       {   0,    0,    0,
+	   { 0x0041,0x0042,0x0043,0x0044,0x0000 }    },
+      },
+      /* 3 */
+      {{{ 0x0051,0x0052,0x0000	},
+	{		   0x0053,0x0054,0x0000 }, 1 },
+       {   0,    0,    0,
+	   { 0x0051,0x0052,0x0053,0x0000	}    },
+      },
+      /* 4 */
+      {{{ 0x0051,0x0052,0x0000	},
+	{		   0x0053,0x0054,0x0000 }, 0 },
+       {   0,    0,    0,
+	   { 0x0051,0x0052,0x0000		}    },
+      },
+      /* 5 */
+      {{{ 0x0000		},
+	{		   0x0043,0x0044,0x0000 }, 3 },
+       {   0,    0,    0,
+	   {		   0x0043,0x0044,0x0000 }    },
+      },
+      /* 6 */
+      {{{ 0x0051,0x0052,0x0000	},
+	{		   0x0000		}, 3 },
+       {   0,    0,    0,
+	   { 0x0051,0x0052,0x0000		}    },
+      },
+      {.is_last = 1}
+    }
+  },
+  {
+#if 0
+    {Twcsncat, TST_LOC_eucJP},
+#else
+    {Twcsncat, TST_LOC_ja_UTF8},
+#endif
+    {
+      /* 1 */
+      {{{ 0x3041,0x3042,0x0000	},
+	{		   0x3043,0x3044,0x0000 }, 3 },
+       {   0,    0,    0,
+	   { 0x3041,0x3042,0x3043,0x3044,0x0000 }    },
+      },
+      /* 2 */
+      {{{ 0x30A2,0x30A3,0x0000	},
+	{		   0xFF71,0xFF72,0x0000 }, 2 },
+       {   0,    0,    0,
+	   { 0x30A2,0x30A3,0xFF71,0xFF72,0x0000 }    },
+      },
+      /* 3 */
+      {{{ 0x3051,0x3052,0x0000	},
+	{		   0x3053,0x3054,0x0000 }, 1 },
+       {   0,    0,    0,
+	   { 0x3051,0x3052,0x3053,0x0000	}    },
+      },
+      /* 4 */
+      {{{ 0x3051,0x3052,0x0000	},
+	{		   0x3053,0x3054,0x0000 }, 0 },
+       {   0,    0,    0,
+	   { 0x3051,0x3052,0x0000		}    },
+      },
+      /* 5 */
+      {{{ 0x0000		},
+	{		   0x3043,0x3044,0x0000 }, 3 },
+       {   0,    0,    0,
+	   {		   0x3043,0x3044,0x0000 }    },
+      },
+      /* 6 */
+      {{{ 0x3051,0x3052,0x0000	},
+	{		   0x0000		}, 3 },
+       {   0,    0,    0,
+	   { 0x3051,0x3052,0x0000		}    },
+      },
+      {.is_last = 1}
+    }
+  },
+  {
+    {Twcsncat, TST_LOC_end}
+  }
+};
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wcsncmp.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wcsncmp.c
new file mode 100644
index 00000000..5c596316
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wcsncmp.c
@@ -0,0 +1,144 @@
+/*
+ *  TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY
+ *
+ *	 FILE:	dat_wcsncmp.c
+ *
+ *	 WCSNCMP:  int wcsncmp (const wchar_t *ws1, const wchar_t *ws2,
+ *				size_t n);
+ */
+
+TST_WCSNCMP tst_wcsncmp_loc [] = {
+  {
+    { Twcsncmp, TST_LOC_de },
+    {
+      { /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 },
+		     { 0x00D1,0x00D2,0x00D3,0x0000 }, 4 },  /* #01 */
+	/*expect*/ { 0,1,0,				},
+      },
+      { /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 },
+		     { 0x00D1,0x00D2,0x00D3,0x0000 }, 3 },  /* #02 */
+	/*expect*/ { 0,1,0,				},
+      },
+      { /*input.*/ { { 0x00D1,0x00D2,0x00D1,0x0000 },
+		     { 0x00D1,0x00D2,0x00D3,0x0000 }, 2 },  /* #03 */
+	/*expect*/ { 0,1,0,				},
+      },
+      { /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 },
+		     { 0x00D0,0x00D2,0x00D3,0x0000 }, 0 },  /* #04 */
+	/*expect*/ { 0,1,0,				},
+      },
+      { /*input.*/ { { 0x0000,0x00D2,0x00D3,0x0000 },
+		     { 0x0000,0x00D2,0x00D1,0x0000 }, 3 },  /* #05 */
+	/*expect*/ { 0,1,0,				},
+      },
+      { /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 },
+		     { 0x0000,0x00D2,0x00D3,0x0000 }, 3 },  /* #06 */
+	/*expect*/ { 0,1,0x00D1,			},
+      },
+      { /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 },
+		     { 0x00D1,0x00D2,0x00D9,0x0000 }, 2 },  /* #07 */
+	/*expect*/ { 0,1,0,				},
+      },
+      { /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 },
+		     { 0x00D1,0x00D2,0x00D9,0x0000 }, 3 },  /* #08 */
+	/*expect*/ { 0,1,-0x0006,			},
+      },
+      { /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 },
+		     { 0x00D1,0x00D2,0x0000	   }, 4 },  /* #09 */
+	/*expect*/ { 0,1,0x00D3,			},
+      },
+      { .is_last = 1 }
+    }
+  },
+  {
+    { Twcsncmp, TST_LOC_enUS },
+    {
+      { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 },
+		     { 0x0041,0x0042,0x0043,0x0000 }, 4 },  /* #01 */
+	/*expect*/ { 0,1,0,				},
+      },
+      { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 },
+		     { 0x0041,0x0042,0x0043,0x0000 }, 3 },  /* #02 */
+	/*expect*/ { 0,1,0,				},
+      },
+      { /*input.*/ { { 0x0041,0x0042,0x0041,0x0000 },
+		     { 0x0041,0x0042,0x0043,0x0000 }, 2 },  /* #03 */
+	/*expect*/ { 0,1,0,				},
+      },
+      { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 },
+		     { 0x0040,0x0042,0x0043,0x0000 }, 0 },  /* #04 */
+	/*expect*/ { 0,1,0,				},
+      },
+      { /*input.*/ { { 0x0000,0x0042,0x0043,0x0000 },
+		     { 0x0000,0x0042,0x0041,0x0000 }, 3 },  /* #05 */
+	/*expect*/ { 0,1,0,				},
+      },
+      { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 },
+		     { 0x0000,0x0042,0x0043,0x0000 }, 3 },  /* #06 */
+	/*expect*/ { 0,1,0x0041,			},
+      },
+      { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 },
+		     { 0x0041,0x0042,0x0049,0x0000 }, 2 },  /* #07 */
+	/*expect*/ { 0,1,0,				},
+      },
+      { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 },
+		     { 0x0041,0x0042,0x0049,0x0000 }, 3 },  /* #08 */
+	/*expect*/ { 0,1,-0x0006,			},
+      },
+      { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 },
+		     { 0x0041,0x0042,0x0000	   }, 4 },  /* #09 */
+	/*expect*/ { 0,1,0x0043,			},
+      },
+      { .is_last = 1 }
+    }
+  },
+  {
+#if 0
+    { Twcsncmp, TST_LOC_eucJP },
+#else
+    { Twcsncmp, TST_LOC_ja_UTF8 },
+#endif
+    {
+      { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 },
+		     { 0x3041,0x3042,0x3043,0x0000 }, 4 },  /* #01 */
+	/*expect*/ { 0,1,0,				},
+      },
+      { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 },
+		     { 0x3041,0x3042,0x3043,0x0000 }, 3 },  /* #02 */
+	/*expect*/ { 0,1,0,				},
+      },
+      { /*input.*/ { { 0x3041,0x3042,0x3041,0x0000 },
+		     { 0x3041,0x3042,0x3043,0x0000 }, 2 },  /* #03 */
+	/*expect*/ { 0,1,0,				},
+      },
+      { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 },
+		     { 0x3040,0x3042,0x3043,0x0000 }, 0 },  /* #04 */
+	/*expect*/ { 0,1,0,				},
+      },
+      { /*input.*/ { { 0x0000,0x3042,0x3043,0x0000 },
+		     { 0x0000,0x3042,0x3041,0x0000 }, 3 },  /* #05 */
+	/*expect*/ { 0,1,0,				},
+      },
+      { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 },
+		     { 0x0000,0x3042,0x3043,0x0000 }, 3 },  /* #06 */
+	/*expect*/ { 0,1,0x3041,			},
+      },
+      { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 },
+		     { 0x3041,0x3042,0x3049,0x0000 }, 2 },  /* #07 */
+	/*expect*/ { 0,1,0,				},
+      },
+      { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 },
+		     { 0x3041,0x3042,0x3049,0x0000 }, 3 },  /* #08 */
+	/*expect*/ { 0,1,-0x0006,			},
+      },
+      { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 },
+		     { 0x3041,0x3042,0x0000	   }, 4 },  /* #09 */
+	/*expect*/ { 0,1,0x3043,			},
+      },
+      { .is_last = 1 }
+    }
+  },
+  {
+    { Twcsncmp, TST_LOC_end }
+  }
+};
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wcsncpy.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wcsncpy.c
new file mode 100644
index 00000000..7a657838
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wcsncpy.c
@@ -0,0 +1,119 @@
+/*
+ *  TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY
+ *
+ *       FILE:  dat_wcsncpy.c
+ *
+ *       WCSNCPY:  wchar_t *wcsncpy (wchar_t *ws1, const wchar_t *ws2,
+ *                                   size_t n);
+ */
+
+
+/* Note:
+ *
+ *       An initial value of ws1 in the test program is defined as:
+ *
+ *       #define WCSNUM_NCPY 7
+ *       wchar_t ws1 [WCSSIZE] = { 0x9999, 0x9999, 0x9999, 0x9999,
+ *                                 0x9999, 0x9999, 0x0000 };
+ * */
+
+
+TST_WCSNCPY tst_wcsncpy_loc [] = {
+  {
+    {Twcsncpy, TST_LOC_de},
+    {
+      /* 1 */
+      {{           { 0x00D1,0x00D2,0x00D3,0x0000                      }, 6 },
+       {    0,0,0, { 0x00D1,0x00D2,0x00D3,0x0000,0x0000,0x0000,0x0000 }    },
+      },
+      /* 2 */
+      {{           { 0x00D1,0x00D2,0x00D3,0x0000                      }, 5 },
+       {    0,0,0, { 0x00D1,0x00D2,0x00D3,0x0000,0x0000,0x9999,0x0000 }    },
+      },
+      /* 3 */
+      {{           { 0x00D1,0x00D2,0x00D3,0x0000                      }, 3 },
+       {    0,0,0, { 0x00D1,0x00D2,0x00D3,0x9999,0x9999,0x9999,0x0000 }    },
+      },
+      /* 4 */
+      {{           { 0x00D1,0x00D2,0x00D3,0x0000                      }, 2 },
+       {    0,0,0, { 0x00D1,0x00D2,0x9999,0x9999,0x9999,0x9999,0x0000 }    },
+      },
+      /* 5 */
+      {{           { 0x00D1,0x00D2,0x00D3,0x0000                      }, 0 },
+       {    0,0,0, { 0x9999,0x9999,0x9999,0x9999,0x9999,0x9999,0x0000 }    },
+      },
+      /* 6 */
+      {{           { 0x0000,0x00D2,0x00D3,0x0000                      }, 3 },
+       {    0,0,0, { 0x0000,0x0000,0x0000,0x9999,0x9999,0x9999,0x0000 }    },
+      },
+      {.is_last = 1}
+    }
+  },
+  {
+    {Twcsncpy, TST_LOC_enUS},
+    {
+      /* 1 */
+      {{           { 0x0041,0x0042,0x0043,0x0000                      }, 6 },
+       {    0,0,0, { 0x0041,0x0042,0x0043,0x0000,0x0000,0x0000,0x0000 }    },
+      },
+      /* 2 */
+      {{           { 0x0041,0x0042,0x0043,0x0000                      }, 5 },
+       {    0,0,0, { 0x0041,0x0042,0x0043,0x0000,0x0000,0x9999,0x0000 }    },
+      },
+      /* 3 */
+      {{           { 0x0041,0x0042,0x0043,0x0000                      }, 3 },
+       {    0,0,0, { 0x0041,0x0042,0x0043,0x9999,0x9999,0x9999,0x0000 }    },
+      },
+      /* 4 */
+      {{           { 0x0041,0x0042,0x0043,0x0000                      }, 2 },
+       {    0,0,0, { 0x0041,0x0042,0x9999,0x9999,0x9999,0x9999,0x0000 }    },
+      },
+      /* 5 */
+      {{           { 0x0041,0x0042,0x0043,0x0000                      }, 0 },
+       {    0,0,0, { 0x9999,0x9999,0x9999,0x9999,0x9999,0x9999,0x0000 }    },
+      },
+      /* 6 */
+      {{           { 0x0000,0x0042,0x0043,0x0000                      }, 3 },
+       {    0,0,0, { 0x0000,0x0000,0x0000,0x9999,0x9999,0x9999,0x0000 }    },
+      },
+      {.is_last = 1}
+    }
+  },
+  {
+#if 0
+    {Twcsncpy, TST_LOC_eucJP},
+#else
+    {Twcsncpy, TST_LOC_ja_UTF8},
+#endif
+    {
+      /* 1 */
+      {{           { 0x3041,0x3042,0x3043,0x0000                      }, 6 },
+       {    0,0,0, { 0x3041,0x3042,0x3043,0x0000,0x0000,0x0000,0x0000 }    },
+      },
+      /* 2 */
+      {{           { 0x3041,0x3042,0x3043,0x0000                      }, 5 },
+       {    0,0,0, { 0x3041,0x3042,0x3043,0x0000,0x0000,0x9999,0x0000 }    },
+      },
+      /* 3 */
+      {{           { 0x3041,0x3042,0x3043,0x0000                      }, 3 },
+       {    0,0,0, { 0x3041,0x3042,0x3043,0x9999,0x9999,0x9999,0x0000 }    },
+      },
+      /* 4 */
+      {{           { 0x3041,0x3042,0x3043,0x0000                      }, 2 },
+       {    0,0,0, { 0x3041,0x3042,0x9999,0x9999,0x9999,0x9999,0x0000 }    },
+      },
+      /* 5 */
+      {{           { 0x3041,0x3042,0x3043,0x0000                      }, 0 },
+       {    0,0,0, { 0x9999,0x9999,0x9999,0x9999,0x9999,0x9999,0x0000 }    },
+      },
+      /* 6 */
+      {{           { 0x0000,0x3042,0x3043,0x0000                      }, 3 },
+       {    0,0,0, { 0x0000,0x0000,0x0000,0x9999,0x9999,0x9999,0x0000 }    },
+      },
+      {.is_last = 1}
+    }
+  },
+  {
+    {Twcsncpy, TST_LOC_end}
+  }
+};
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wcspbrk.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wcspbrk.c
new file mode 100644
index 00000000..471515eb
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wcspbrk.c
@@ -0,0 +1,176 @@
+/*
+ *  TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY
+ *
+ *	 FILE:	dat_wcspbrk.c
+ *
+ *	 WCSSTR:  wchar_t *wcspbrk (const wchar_t *ws1, const wchar_t *ws2);
+ */
+
+
+/*
+ * NOTE:
+ *	 This is not a locale sensitive function.
+ *	 So those data in each locale doesn't make sense
+ *	 ... (redundant test cases)
+ */
+
+
+TST_WCSPBRK tst_wcspbrk_loc [] = {
+  {
+    { Twcspbrk, TST_LOC_de },
+    {
+      { /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 },
+		     { 0x00D1,0x0000		   }, },  /* #01 */
+	/*expect*/ { 0,0,0,		    0x00D1    },
+      },
+      { /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 },
+		     {	      0x00D2,0x0000	   }, },  /* #02 */
+	/*expect*/ { 0,0,0,		    0x00D2    },
+      },
+      { /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 },
+		     {		     0x00D3,0x0000 }, },  /* #03 */
+	/*expect*/ { 0,0,0,		    0x00D3    },
+      },
+      { /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 },
+		     { 0x00D1,0x00D2,0x0000	   }, },  /* #04 */
+	/*expect*/ { 0,0,0,		    0x00D1    },
+      },
+      { /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 },
+		     {	      0x00D2,0x00D3,0x0000 }, },  /* #05 */
+	/*expect*/ { 0,0,0,		    0x00D2    },
+      },
+      { /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 },
+		     { 0x00D1,0x00D2,0x00D3,0x0000 }, },  /* #06 */
+	/*expect*/ { 0,0,0,		    0x00D1    },
+      },
+      { /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 },
+		     { 0x00D0,0x00D4,0x00D5,0x0000 }, },  /* #07 */
+	/*expect*/ { 0,1,(wchar_t *)NULL, 0x0000    },
+      },
+      { /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 },
+		     { 0x00D5,0x00D0,0x00D4,0x0000 }, },  /* #08 */
+	/*expect*/ { 0,1,(wchar_t *)NULL, 0x0000    },
+      },
+      { /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 },
+		     { 0x0000			   }, },  /* #09 */
+	/*expect*/ { 0,1,(wchar_t *)NULL, 0x0000    },
+      },
+      { /*input.*/ { { 0x0000,0x00D2,0x00D3,0x0000 },
+		     { 0x00D1,0x0000		   }, },  /* #10 */
+	/*expect*/ { 0,1,(wchar_t *)NULL, 0x0000    },
+      },
+      { /*input.*/ { { 0x0000,0x00D2,0x00D3,0x0000 },
+		     { 0x0000			   }, },  /* #11 */
+	/*expect*/ { 0,1,(wchar_t *)NULL, 0x0000    },
+      },
+      { .is_last = 1 }
+    }
+  },
+  {
+    { Twcspbrk, TST_LOC_enUS },
+    {
+      { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 },
+		     { 0x0041,0x0000		   }, },  /* #01 */
+	/*expect*/ { 0,0,0,		    0x0041    },
+      },
+      { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 },
+		     {	      0x0042,0x0000	   }, },  /* #02 */
+	/*expect*/ { 0,0,0,		    0x0042    },
+      },
+      { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 },
+		     {		     0x0043,0x0000 }, },  /* #03 */
+	/*expect*/ { 0,0,0,		    0x0043    },
+      },
+      { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 },
+		     { 0x0041,0x0042,0x0000	   }, },  /* #04 */
+	/*expect*/ { 0,0,0,		    0x0041    },
+      },
+      { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 },
+		     {	      0x0042,0x0043,0x0000 }, },  /* #05 */
+	/*expect*/ { 0,0,0,		    0x0042    },
+      },
+      { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 },
+		     { 0x0041,0x0042,0x0043,0x0000 }, },  /* #06 */
+	/*expect*/ { 0,0,0,		    0x0041    },
+      },
+      { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 },
+		     { 0x0040,0x0044,0x0045,0x0000 }, },  /* #07 */
+	/*expect*/ { 0,1,(wchar_t *)NULL, 0x0000    },
+      },
+      { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 },
+		     { 0x0045,0x0040,0x0044,0x0000 }, },  /* #08 */
+	/*expect*/ { 0,1,(wchar_t *)NULL, 0x0000    },
+      },
+      { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 },
+		     { 0x0000			   }, },  /* #09 */
+	/*expect*/ { 0,1,(wchar_t *)NULL, 0x0000    },
+      },
+      { /*input.*/ { { 0x0000,0x0042,0x0043,0x0000 },
+		     { 0x0041,0x0000		   }, },  /* #10 */
+	/*expect*/ { 0,1,(wchar_t *)NULL, 0x0000    },
+      },
+      { /*input.*/ { { 0x0000,0x0042,0x0043,0x0000 },
+		     { 0x0000			   }, },  /* #11 */
+	/*expect*/ { 0,1,(wchar_t *)NULL, 0x0000    },
+      },
+      { .is_last = 1 }
+    }
+  },
+  {
+#if 0
+    { Twcspbrk, TST_LOC_eucJP },
+#else
+    { Twcspbrk, TST_LOC_ja_UTF8 },
+#endif
+    {
+      { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 },
+		     { 0x3041,0x0000		   }, },  /* #01 */
+	/*expect*/ { 0,0,0,		    0x3041    },
+      },
+      { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 },
+		     {	      0x3042,0x0000	   }, },  /* #02 */
+	/*expect*/ { 0,0,0,		    0x3042    },
+      },
+      { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 },
+		     {		     0x3043,0x0000 }, },  /* #03 */
+	/*expect*/ { 0,0,0,		    0x3043    },
+      },
+      { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 },
+		     { 0x3041,0x3042,0x0000	   }, },  /* #04 */
+	/*expect*/ { 0,0,0,		    0x3041    },
+      },
+      { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 },
+		     {	      0x3042,0x3043,0x0000 }, },  /* #05 */
+	/*expect*/ { 0,0,0,		    0x3042    },
+      },
+      { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 },
+		     { 0x3041,0x3042,0x3043,0x0000 }, },  /* #06 */
+	/*expect*/ { 0,0,0,		    0x3041    },
+      },
+      { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 },
+		     { 0x3042,0x3043,0x3044,0x0000 }, },  /* #07 */
+	/*expect*/ { 0,0,0, 0x3042		      },
+      },
+      { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 },
+		     { 0x3040,0x3041,0x3042,0x0000 }, },  /* #08 */
+	/*expect*/ { 0,0,0, 0x3041		      },
+      },
+      { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 },
+		     { 0x0000			   }, },  /* #09 */
+	/*expect*/ { 0,1,(wchar_t *)NULL, 0x0000    },
+      },
+      { /*input.*/ { { 0x0000,0x3042,0x3043,0x0000 },
+		     { 0x3041,0x0000		   }, },  /* #10 */
+	/*expect*/ { 0,1,(wchar_t *)NULL, 0x0000    },
+      },
+      { /*input.*/ { { 0x0000,0x3042,0x3043,0x0000 },
+		     { 0x0000			   }, },  /* #11 */
+	/*expect*/ { 0,1,(wchar_t *)NULL, 0x0000    },
+      },
+      { .is_last = 1 }
+    }
+  },
+  {
+    { Twcspbrk, TST_LOC_end }
+  }
+};
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wcsrtombs.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wcsrtombs.c
new file mode 100644
index 00000000..f8adc6cf
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wcsrtombs.c
@@ -0,0 +1,272 @@
+/*
+ *  TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY
+ *
+ *	 FILE:	dat_wcsrtombs.c
+ *
+ *	 WCSTOMBS:  size_t wcsrtombs (char *s, const wchar_t **ws,
+ *				      size_t n, mbstate *ps)
+ */
+
+
+/*
+ *  CAUTION:
+ *	     Do not use a value 0x01 for string data. The test program
+ *	     uses it.
+ *
+ */
+
+
+TST_WCSRTOMBS tst_wcsrtombs_loc [] = {
+  {
+    { Twcsrtombs, TST_LOC_de },
+    {
+      /* #01 : Any chars including a null char should not be stored in s.  */
+      { /*input.*/ { 1,1,	{ 0x00C4,0x00D6,0x00DC,0x0000 }, 0, 0, 0},
+	/*expect*/ { 0,1,0,	 ""					},
+      },
+      /* #02 : Only one chars should be stored in s. No null termination.  */
+      { /*input.*/ { 1,1,	{ 0x00C4,0x00D6,0x00DC,0x0000 }, 1, 0, 0 },
+	/*expect*/ { 0,1,1,	 "Ä"					 },
+      },
+      /* #03 : Only two chars should be stored in s. No null termination.  */
+      { /*input.*/ { 1,1,	{ 0x00C4,0x00D6,0x00DC,0x0000 }, 2, 0, 0 },
+	/*expect*/ { 0,1,2,	 "ÄÖ"					 },
+      },
+      /* #04 : Only three chars should be stored in s. No null
+	       termination.  */
+      { /*input.*/ { 1,1,	{ 0x00C4,0x00D6,0x00DC,0x0000 }, 3, 0, 0 },
+	/*expect*/ { 0,1,3,	 "ÄÖÜ"					 },
+      },
+      /* #05 : Only three chars should be stored in s with a null
+	       termination. */
+      { /*input.*/ { 1,1,	{ 0x00C4,0x00D6,0x00DC,0x0000 }, 4, 0, 0 },
+	/*expect*/ { 0,1,3,	 "ÄÖÜ"					 },
+      },
+      /* #06 : Only three chars should be stored in s with a null
+	       termination. */
+      { /*input.*/ { 1,1,	{ 0x00C4,0x00D6,0x00DC,0x0000 }, 5, 0, 0 },
+	/*expect*/ { 0,1,3,	 "ÄÖÜ"					 },
+      },
+      /* #07 : Invalid mb sequence. No chars should be stored in s.  */
+      { /*input.*/ { 1,1,	{ 0x0201,0x0221,0x0000,0x0000 }, 2, 0, 0 },
+	/*expect*/ { EILSEQ,1,(size_t)-1,	 ""			 },
+      },
+      /* #08 : s is a null pointer, no chars should be stored in s.  */
+      { /*input.*/ { 0,1,	{ 0x00C4,0x00D6,0x00DC,0x0000 }, 0, 0, 0 },
+	/*expect*/ { 0,1,3,	 ""					 },
+      },
+      /* #09 : s is a null pointer, no chars should be stored in s.  */
+      { /*input.*/ { 0,1,	{ 0x00C4,0x00D6,0x00DC,0x0000 }, 1, 0, 0 },
+	/*expect*/ { 0,1,3,	 ""					 },
+      },
+      /* #10 : s is a null pointer, no chars should be stored in s.  */
+      { /*input.*/ { 0,1,	{ 0x00C4,0x00D6,0x00DC,0x0000 }, 5, 0, 0 },
+	/*expect*/ { 0,1,3,	 ""					 },
+      },
+      /* #11 : s is a null pointer. No chars should be stored in s.  */
+      { /*input.*/ { 0,1,	{ 0x0201,0x0221,0x0000,0x0000 }, 5, 0, 0 },
+	/*expect*/ { EILSEQ,1,(size_t)-1,	 ""			 },
+      },
+      /* #12 : ws is a null wc string, no chars should be stored in s.  */
+      { /*input.*/ { 1,1,	{ 0x0000 },			 5, 0, 0 },
+	/*expect*/ { 0,1,0,	 ""					 },
+      },
+      /* #13 : s is a null pointer, no chars should be stored in s.  */
+      { /*input.*/ { 0,1,	{ 0x0000 },			 5, 0, 0 },
+	/*expect*/ { 0,1,0,	 ""					 },
+      },
+      { .is_last = 1 }
+    }
+  },
+  {
+    { Twcsrtombs, TST_LOC_enUS },
+    {
+      /* #01 : Any chars including a null char should not be stored in s.  */
+      { /*input.*/ { 1,1,	{ 0x0041,0x0042,0x0043,0x0000 }, 0, 0, 0 },
+	/*expect*/ { 0,1,0,	 ""					 },
+      },
+      /* #02 : Only one chars should be stored in s. No null termination.  */
+      { /*input.*/ { 1,1,	{ 0x0041,0x0042,0x0043,0x0000 }, 1, 0, 0 },
+	/*expect*/ { 0,1,1,	 "A"					 },
+      },
+      /* #03 : Only two chars should be stored in s. No null termination. */
+      { /*input.*/ { 1,1,	{ 0x0041,0x0042,0x0043,0x0000 }, 2, 0, 0 },
+	/*expect*/ { 0,1,2,	 "AB"					 },
+      },
+      /* #04 : Only three chars should be stored in s. No null
+	       termination.  */
+      { /*input.*/ { 1,1,	{ 0x0041,0x0042,0x0043,0x0000 }, 3, 0, 0 },
+	/*expect*/ { 0,1,3,	 "ABC"					 },
+      },
+      /* #05 : Only three chars should be stored in s with a null
+	       termination. */
+      { /*input.*/ { 1,1,	{ 0x0041,0x0042,0x0043,0x0000 }, 4, 0, 0 },
+	/*expect*/ { 0,1,3,	 "ABC"					 },
+      },
+      /* #06 : Only three chars should be stored in s with a null
+	       termination. */
+      { /*input.*/ { 1,1,	{ 0x0041,0x0042,0x0043,0x0000 }, 5, 0, 0 },
+	/*expect*/ { 0,1,3,	 "ABC"					 },
+      },
+      /* #07 : Invalid mb sequence. No chars should be stored in s.  */
+      { /*input.*/ { 1,1,	{ 0x0201,0x0221,0x0000,0x0000 }, 2, 0, 0 },
+	/*expect*/ { EILSEQ,1,(size_t)-1,	 ""					},
+      },
+      /* #08 : s is a null pointer, no chars should be stored in s.  */
+      { /*input.*/ { 0,1,	{ 0x0041,0x0042,0x0043,0x0000 }, 0, 0, 0 },
+	/*expect*/ { 0,1,3,	 ""					 },
+      },
+      /* #09 : s is a null pointer, no chars should be stored in s.  */
+      { /*input.*/ { 0,1,	{ 0x0041,0x0042,0x0043,0x0000 }, 1, 0, 0 },
+	/*expect*/ { 0,1,3,	 ""					 },
+      },
+      /* #10 : s is a null pointer, no chars should be stored in s.  */
+      { /*input.*/ { 0,1,	{ 0x0041,0x0042,0x0043,0x0000 }, 5, 0, 0 },
+	/*expect*/ { 0,1,3,	 ""					 },
+      },
+      /* #11 : s is a null pointer. No chars should be stored in s.  */
+      { /*input.*/ { 0,1,	{ 0x0201,0x0221,0x0000,0x0000 }, 5, 0, 0 },
+	/*expect*/ { EILSEQ,1,(size_t)-1,	 ""			 },
+      },
+      /* #12 : ws is a null wc string, no chars should be stored in s.  */
+      { /*input.*/ { 1,1,	{ 0x0000 },			 5, 0, 0 },
+	/*expect*/ { 0,1,0,	 ""					 },
+      },
+      /* #13 : s is a null pointer, no chars should be stored in s.  */
+      { /*input.*/ { 0,1,	{ 0x0000 },			 5, 0, 0 },
+	/*expect*/ { 0,1,0,	 ""					 },
+      },
+      { .is_last = 1 }
+    }
+  },
+#if 0
+  {
+    { Twcsrtombs, TST_LOC_eucJP },
+    {
+
+      /* #01 : Any chars including a null char should not be stored in s.  */
+      { /*input.*/ { 1,1,	{ 0x3042,0x3044,0xFF73,0x0000 }, 0, 0, 0 },
+	/*expect*/ { 0,1,0,	 ""					 },
+      },
+      /* #02 : Only one chars should be stored in s. No null termination.  */
+      { /*input.*/ { 1,1,	{ 0x3042,0x3044,0xFF73,0x0000 }, 2, 0, 0 },
+	/*expect*/ { 0,1,2,	    "\244\242"				 },
+      },
+      /* #03 : Only two chars should be stored in s. No null termination.  */
+      { /*input.*/ { 1,1,	{ 0x3042,0x3044,0xFF73,0x0000 }, 4, 0, 0 },
+	/*expect*/ { 0,1,4,	    "\244\242\244\244"			 },
+      },
+      /* #04 : Only three chars should be stored in s. No null
+	       termination.  */
+      { /*input.*/ { 1,1,	{ 0x3042,0x3044,0xFF73,0x0000 }, 6, 0, 0 },
+	/*expect*/ { 0,1,6,	    "\244\242\244\244\216\263"		 },
+      },
+      /* #05 : Only three chars should be stored in s with a null
+	       termination. */
+      { /*input.*/ { 1,1,	{ 0x3042,0x3044,0xFF73,0x0000 }, 7, 0, 0 },
+	/*expect*/ { 0,1,6,	    "\244\242\244\244\216\263"		 },
+      },
+      /* #06 : Only three chars should be stored in s with a null
+	       termination. */
+      { /*input.*/ { 1,1,	{ 0x3042,0x3044,0xFF73,0x0000 }, 8, 0, 0 },
+	/*expect*/ { 0,1,6,	    "\244\242\244\244\216\263"		 },
+      },
+      /* #07 : Invalid mb sequence. No chars should be stored in s.  */
+      { /*input.*/ { 1,1,	{ 0x0201,0x0221,0x0000,0x0000 }, 2, 0, 0 },
+	/*expect*/ { EILSEQ,1,-1, ""					 },
+      },
+      /* #08 : s is a null pointer, no chars should be stored in s.  */
+      { /*input.*/ { 0,1,	{ 0x3042,0x3044,0xFF73,0x0000 }, 0, 0, 0 },
+	/*expect*/ { 0,1,6,	 ""					 },
+      },
+      /* #09 : s is a null pointer, no chars should be stored in s.  */
+      { /*input.*/ { 0,1,	{ 0x3042,0x3044,0xFF73,0x0000 }, 1, 0, 0 },
+	/*expect*/ { 0,1,6,	 ""					 },
+      },
+      /* #10 : s is a null pointer, no chars should be stored in s.  */
+      { /*input.*/ { 0,1,	{ 0x3042,0x3044,0xFF73,0x0000 }, 8, 0, 0 },
+	/*expect*/ { 0,1,6,	 ""					 },
+      },
+      /* #11 : s is a null pointer. No chars should be stored in s.  */
+      { /*input.*/ { 0,1,	{ 0x0201,0x0221,0x0000,0x0000 }, 5, 0, 0 },
+	/*expect*/ { EILSEQ,1,(size_t)-1,	 ""			 },
+      },
+      /* #12 : ws is a null wc string, no chars should be stored in s.  */
+      { /*input.*/ { 1,1,	{ 0x0000 },			 5, 0, 0 },
+	/*expect*/ { 0,1,0,	 ""					 },
+      },
+      /* #13 : s is a null pointer, no chars should be stored in s.  */
+      { /*input.*/ { 0,1,	{ 0x0000 },			 5, 0, 0 },
+	/*expect*/ { 0,1,0,	 ""					 },
+      },
+      { .is_last = 1 }
+    }
+  },
+#else
+  {
+    { Twcsrtombs, TST_LOC_ja_UTF8 },
+    {
+
+      /* #01 : Any chars including a null char should not be stored in s.  */
+      { /*input.*/ { 1,1,	{ 0x3042,0x3044,0xFF73,0x0000 }, 0, 0, 0 },
+	/*expect*/ { 0,1,0,	 ""					 },
+      },
+      /* #02 : Only one chars should be stored in s. No null termination.  */
+      { /*input.*/ { 1,1,	{ 0x3042,0x3044,0xFF73,0x0000 }, 3, 0, 0 },
+	/*expect*/ { 0,1,3,	    "\343\201\202"			 },
+      },
+      /* #03 : Only two chars should be stored in s. No null termination.  */
+      { /*input.*/ { 1,1,	{ 0x3042,0x3044,0xFF73,0x0000 }, 6, 0, 0 },
+	/*expect*/ { 0,1,6,	    "\343\201\202\343\201\204"		 },
+      },
+      /* #04 : Only three chars should be stored in s. No null
+	       termination.  */
+      { /*input.*/ { 1,1,	{ 0x3042,0x3044,0xFF73,0x0000 }, 9, 0, 0 },
+	/*expect*/ { 0,1,9,    "\343\201\202\343\201\204\357\275\263"	 },
+      },
+      /* #05 : Only three chars should be stored in s with a null
+	       termination. */
+      { /*input.*/ { 1,1,	{ 0x3042,0x3044,0xFF73,0x0000 }, 10, 0, 0 },
+	/*expect*/ { 0,1,9,	"\343\201\202\343\201\204\357\275\263"	 },
+      },
+      /* #06 : Only three chars should be stored in s with a null
+	       termination. */
+      { /*input.*/ { 1,1,	{ 0x3042,0x3044,0xFF73,0x0000 }, 11, 0, 0 },
+	/*expect*/ { 0,1,9,	"\343\201\202\343\201\204\357\275\263"	  },
+      },
+      /* #07 : Invalid mb sequence. No chars should be stored in s.  */
+      { /*input.*/ { 1,1,	{ 0x0201,0x0221,0x0000,0x0000 }, 2, 0, 0 },
+	/*expect*/ { EILSEQ,1,-1, ""					 },
+      },
+      /* #08 : s is a null pointer, no chars should be stored in s.  */
+      { /*input.*/ { 0,1,	{ 0x3042,0x3044,0xFF73,0x0000 }, 0, 0, 0 },
+	/*expect*/ { 0,1,9,	 ""					 },
+      },
+      /* #09 : s is a null pointer, no chars should be stored in s.  */
+      { /*input.*/ { 0,1,	{ 0x3042,0x3044,0xFF73,0x0000 }, 1, 0, 0 },
+	/*expect*/ { 0,1,9,	 ""					 },
+      },
+      /* #10 : s is a null pointer, no chars should be stored in s.  */
+      { /*input.*/ { 0,1,	{ 0x3042,0x3044,0xFF73,0x0000 }, 8, 0, 0 },
+	/*expect*/ { 0,1,9,	 ""					 },
+      },
+      /* #11 : s is a null pointer. No chars should be stored in s.  */
+      { /*input.*/ { 0,1,	{ 0x0201,0x0221,0x0000,0x0000 }, 5, 0, 0 },
+	/*expect*/ { EILSEQ,1,(size_t)-1,	 ""			 },
+      },
+      /* #12 : ws is a null wc string, no chars should be stored in s.  */
+      { /*input.*/ { 1,1,	{ 0x0000 },			 5, 0, 0 },
+	/*expect*/ { 0,1,0,	 ""					 },
+      },
+      /* #13 : s is a null pointer, no chars should be stored in s.  */
+      { /*input.*/ { 0,1,	{ 0x0000 },			 5, 0, 0 },
+	/*expect*/ { 0,1,0,	 ""					 },
+      },
+      { .is_last = 1 }
+    }
+  },
+#endif
+  {
+    { Twcsrtombs, TST_LOC_end }
+  }
+};
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wcsspn.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wcsspn.c
new file mode 100644
index 00000000..06af2d6a
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wcsspn.c
@@ -0,0 +1,179 @@
+/*
+ *  TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY
+ *
+ *	 FILE:	dat_wcsspn.c
+ *
+ *	 WCSSPN:  size_t wcsspn (const wchar_t *ws1, const wchar_t *ws2);
+ */
+
+TST_WCSSPN tst_wcsspn_loc [] = {
+    {
+      { Twcsspn, TST_LOC_de },
+      {
+	{ /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 },
+		       { 0x00D1,0x0000		     }, },  /* #01 */
+	  /*expect*/ { 0,1,1,				},
+	},
+	{ /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 },
+		       {	0x00D2,0x0000	     }, },  /* #02 */
+	  /*expect*/ { 0,1,0,				},
+	},
+	{ /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 },
+		       {	       0x00D3,0x0000 }, },  /* #03 */
+	  /*expect*/ { 0,1,0,				},
+	},
+	{ /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 },
+		       {	       0x00D4,0x0000 }, },  /* #04 */
+	  /*expect*/ { 0,1,0,				},
+	},
+	{ /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 },
+		       {	0x00D2,0x00D3,0x0000 }, },  /* #05 */
+	  /*expect*/ { 0,1,0,				},
+	},
+	{ /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 },
+		       {	0x00D3,0x00D4,0x0000 }, },  /* #06 */
+	  /*expect*/ { 0,1,0,				},
+	},
+	{ /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 },
+		       { 0x00D1,0x00D2,0x00D3,0x0000 }, },  /* #07 */
+	  /*expect*/ { 0,1,3,				},
+	},
+	{ /*input.*/ { { 0x00D1,0x00D2,0x0000	     },
+		       { 0x00D1,0x00D2,0x00D3,0x0000 }, },  /* #08 */
+	  /*expect*/ { 0,1,2,				},
+	},
+	{ /*input.*/ { { 0x0000,0x00D2,0x00D3,0x0000 },
+		       { 0x00D2,0x0000		     }, },  /* #09 */
+	  /*expect*/ { 0,1,0,				},
+	},
+	{ /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 },
+		       { 0x0000,0x00D2,0x0000	     }, },  /* #10 */
+	  /*expect*/ { 0,1,0,				},
+	},
+	{ /*input.*/ { { 0x0000,0x00D2,0x00D3,0x0000 },
+		       { 0x0000,0x00D2,0x0000	     }, },  /* #11 */
+	  /*expect*/ { 0,1,0,				},
+	},
+	{ /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 },
+		       { 0x00D2,0x00D1,0x0000	     }, },  /* #12 */
+	  /*expect*/ { 0,1,2,				},
+	},
+	{ .is_last = 1 }
+      }
+    },
+    {
+      { Twcsspn, TST_LOC_enUS },
+      {
+	{ /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 },
+		       { 0x0041,0x0000		     }, },  /* #01 */
+	  /*expect*/ { 0,1,1,				},
+	},
+	{ /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 },
+		       {	0x0042,0x0000	     }, },  /* #02 */
+	  /*expect*/ { 0,1,0,				},
+	},
+	{ /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 },
+		       {	       0x0043,0x0000 }, },  /* #03 */
+	  /*expect*/ { 0,1,0,				},
+	},
+	{ /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 },
+		       {	       0x0044,0x0000 }, },  /* #04 */
+	  /*expect*/ { 0,1,0,				},
+	},
+	{ /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 },
+		       {	0x0042,0x0043,0x0000 }, },  /* #05 */
+	  /*expect*/ { 0,1,0,				},
+	},
+	{ /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 },
+		       {	0x0043,0x0044,0x0000 }, },  /* #06 */
+	  /*expect*/ { 0,1,0,				},
+	},
+	{ /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 },
+		       { 0x0041,0x0042,0x0043,0x0000 }, },  /* #07 */
+	  /*expect*/ { 0,1,3,				},
+	},
+	{ /*input.*/ { { 0x0041,0x0042,0x0000	     },
+		       { 0x0041,0x0042,0x0043,0x0000 }, },  /* #08 */
+	  /*expect*/ { 0,1,2,				},
+	},
+	{ /*input.*/ { { 0x0000,0x0042,0x0043,0x0000 },
+		       { 0x0042,0x0000		     }, },  /* #09 */
+	  /*expect*/ { 0,1,0,				},
+	},
+	{ /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 },
+		       { 0x0000,0x0042,0x0000	     }, },  /* #10 */
+	  /*expect*/ { 0,1,0,				},
+	},
+	{ /*input.*/ { { 0x0000,0x0042,0x0043,0x0000 },
+		       { 0x0000,0x0042,0x0000	     }, },  /* #11 */
+	  /*expect*/ { 0,1,0,				},
+	},
+	{ /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 },
+		       { 0x0042,0x0041,0x0000	     }, },  /* #12 */
+	  /*expect*/ { 0,1,2,				},
+	},
+	{ .is_last = 1 }
+      }
+    },
+    {
+#if 0
+      { Twcsspn, TST_LOC_eucJP },
+#else
+      { Twcsspn, TST_LOC_ja_UTF8 },
+#endif
+      {
+	{ /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 },
+		       { 0x3041,0x0000		     }, },  /* #1 */
+	  /*expect*/ { 0,1,1,				},
+	},
+	{ /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 },
+		       {	0x3042,0x0000	     }, },  /* #2 */
+	  /*expect*/ { 0,1,0,				},
+	},
+	{ /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 },
+		       {	       0x3043,0x0000 }, },  /* #3 */
+	  /*expect*/ { 0,1,0,				},
+	},
+	{ /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 },
+		       {	       0x3044,0x0000 }, },  /* #4 */
+	  /*expect*/ { 0,1,0,				},
+	},
+	{ /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 },
+		       {	0x3042,0x3043,0x0000 }, },  /* #5 */
+	  /*expect*/ { 0,1,0,				},
+	},
+	{ /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 },
+		       {	0x3043,0x3044,0x0000 }, },  /* #6 */
+	  /*expect*/ { 0,1,0,				},
+	},
+	{ /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 },
+		       { 0x3041,0x3042,0x3043,0x0000 }, },  /* #7 */
+	  /*expect*/ { 0,1,3,				},
+	},
+	{ /*input.*/ { { 0x3041,0x3042,0x0000	     },
+		       { 0x3041,0x3042,0x3043,0x0000 }, },  /* #8 */
+	  /*expect*/ { 0,1,2,				},
+	},
+	{ /*input.*/ { { 0x0000,0x3042,0x3043,0x0000 },
+		       { 0x3042,0x0000		     }, },  /* #9 */
+	  /*expect*/ { 0,1,0,				},
+	},
+	{ /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 },
+		       { 0x0000,0x3042,0x0000	     }, },  /* #10 */
+	  /*expect*/ { 0,1,0,				},
+	},
+	{ /*input.*/ { { 0x0000,0x3042,0x3043,0x0000 },
+		       { 0x0000,0x3042,0x0000	     }, },  /* #11 */
+	  /*expect*/ { 0,1,0,				},
+	},
+	{ /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 },
+		       { 0x3042,0x3041,0x0000	     }, },  /* #12 */
+	  /*expect*/ { 0,1,2,				},
+	},
+	{ .is_last = 1 }
+      }
+    },
+    {
+      { Twcsspn, TST_LOC_end }
+    }
+};
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wcsstr.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wcsstr.c
new file mode 100644
index 00000000..f999dc5c
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wcsstr.c
@@ -0,0 +1,175 @@
+/*
+ *  TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY
+ *
+ *	 FILE:	dat_wcsstr.c
+ *
+ *	 WCSSTR:  wchar_t *wcsstr (const wchar_t *ws1, const wchar_t *ws2);
+ */
+
+/*
+ * NOTE:
+ *	 This is not a locale sensitive function.
+ *	 So those data in each locale doesn't make sense ...
+ *	 (redundant test cases)
+ */
+
+
+TST_WCSSTR tst_wcsstr_loc [] = {
+  {
+    { Twcsstr, TST_LOC_de },
+    {
+      { /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 },
+		     { 0x00D1,0x0000		   }, },  /* #01 */
+	/*expect*/ { 0,0,0,			      },
+      },
+      { /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 },
+		     {	      0x00D2,0x0000	   }, },  /* #02 */
+	/*expect*/ { 0,0,0,			      },
+      },
+      { /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 },
+		     {		     0x00D3,0x0000 }, },  /* #03 */
+	/*expect*/ { 0,0,0,			      },
+      },
+      { /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 },
+		     { 0x00D1,0x00D2,0x0000	   }, },  /* #04 */
+	/*expect*/ { 0,0,0,			      },
+      },
+      { /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 },
+		     {	      0x00D2,0x00D3,0x0000 }, },  /* #05 */
+	/*expect*/ { 0,0,0,			      },
+      },
+      { /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 },
+		     { 0x00D1,0x00D2,0x00D3,0x0000 }, },  /* #06 */
+	/*expect*/ { 0,0,0,			      },
+      },
+      { /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 },
+		     { 0x00D2,0x00D3,0x00D4,0x0000 }, },  /* #07 */
+	/*expect*/ { 0,1,(wchar_t *)NULL,	      },
+      },
+      { /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 },
+		     { 0x00D0,0x00D1,0x00D2,0x0000 }, },  /* #08 */
+	/*expect*/ { 0,1,(wchar_t *)NULL,	      },
+      },
+      { /*input.*/ { { 0x00D1,0x00D2,0x00D3,0x0000 },
+		     { 0x0000			   }, },  /* #09 */
+	/*expect*/ { 0,0,0,			      },
+      },
+      { /*input.*/ { { 0x0000,0x00D2,0x00D3,0x0000 },
+		     { 0x00D1,0x0000		   }, },  /* #10 */
+	/*expect*/ { 0,1,(wchar_t *)NULL,	      },
+      },
+      { /*input.*/ { { 0x0000,0x00D2,0x00D3,0x0000 },
+		     { 0x0000			   }, },  /* #11 */
+	/*expect*/ { 0,0,0,			      },
+      },
+      { .is_last = 1 }
+    }
+  },
+  {
+    { Twcsstr, TST_LOC_enUS },
+    {
+      { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 },
+		     { 0x0041,0x0000		   }, },  /* #01 */
+	/*expect*/ { 0,0,0,			      },
+      },
+      { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 },
+		     {	      0x0042,0x0000	   }, },  /* #02 */
+	/*expect*/ { 0,0,0,			      },
+      },
+      { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 },
+		     {		     0x0043,0x0000 }, },  /* #03 */
+	/*expect*/ { 0,0,0,			      },
+      },
+      { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 },
+		     { 0x0041,0x0042,0x0000	   }, },  /* #04 */
+	/*expect*/ { 0,0,0,			      },
+      },
+      { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 },
+		     {	      0x0042,0x0043,0x0000 }, },  /* #05 */
+	/*expect*/ { 0,0,0,			      },
+      },
+      { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 },
+		     { 0x0041,0x0042,0x0043,0x0000 }, },  /* #06 */
+	/*expect*/ { 0,0,0,			      },
+      },
+      { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 },
+		     { 0x0042,0x0043,0x0044,0x0000 }, },  /* #07 */
+	/*expect*/ { 0,1,(wchar_t *)NULL,	      },
+      },
+      { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 },
+		     { 0x0040,0x0041,0x0042,0x0000 }, },  /* #08 */
+	/*expect*/ { 0,1,(wchar_t *)NULL,	      },
+      },
+      { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 },
+		     { 0x0000			   }, },  /* #09 */
+	/*expect*/ { 0,0,0,			      },
+      },
+      { /*input.*/ { { 0x0000,0x0042,0x0043,0x0000 },
+		     { 0x0041,0x0000		   }, },  /* #10 */
+	/*expect*/ { 0,1,(wchar_t *)NULL,	      },
+      },
+      { /*input.*/ { { 0x0000,0x0042,0x0043,0x0000 },
+		     { 0x0000			   }, },  /* #11 */
+	/*expect*/ { 0,0,0,			      },
+      },
+      { .is_last = 1 }
+    }
+  },
+  {
+#if 0
+    { Twcsstr, TST_LOC_eucJP },
+#else
+    { Twcsstr, TST_LOC_ja_UTF8 },
+#endif
+    {
+      { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 },
+		     { 0x3041,0x0000		   }, },  /* #01 */
+	/*expect*/ { 0,0,0,			      },
+      },
+      { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 },
+		     {	      0x3042,0x0000	   }, },  /* #02 */
+	/*expect*/ { 0,0,0,			      },
+      },
+      { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 },
+		     {		     0x3043,0x0000 }, },  /* #03 */
+	/*expect*/ { 0,0,0,			      },
+      },
+      { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 },
+		     { 0x3041,0x3042,0x0000	   }, },  /* #04 */
+	/*expect*/ { 0,0,0,			      },
+      },
+      { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 },
+		     {	      0x3042,0x3043,0x0000 }, },  /* #05 */
+	/*expect*/ { 0,0,0,			      },
+      },
+      { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 },
+		     { 0x3041,0x3042,0x3043,0x0000 }, },  /* #06 */
+	/*expect*/ { 0,0,0,			      },
+      },
+      { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 },
+		     { 0x3042,0x3043,0x3044,0x0000 }, },  /* #07 */
+	/*expect*/ { 0,1,(wchar_t *)NULL,	      },
+      },
+      { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 },
+		     { 0x3040,0x3041,0x3042,0x0000 }, },  /* #08 */
+	/*expect*/ { 0,1,(wchar_t *)NULL,	      },
+      },
+      { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 },
+		     { 0x0000			   }, },  /* #09 */
+	/*expect*/ { 0,0,0,			      },
+      },
+      { /*input.*/ { { 0x0000,0x3042,0x3043,0x0000 },
+		     { 0x3041,0x0000		   }, },  /* #10 */
+	/*expect*/ { 0,1,(wchar_t *)NULL,	      },
+      },
+      { /*input.*/ { { 0x0000,0x3042,0x3043,0x0000 },
+		     { 0x0000			   }, },  /* #11 */
+	/*expect*/ { 0,0,0,			      },
+      },
+      { .is_last = 1 }
+    }
+  },
+  {
+    { Twcsstr, TST_LOC_end }
+  }
+};
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wcstod.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wcstod.c
new file mode 100644
index 00000000..c7b40184
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wcstod.c
@@ -0,0 +1,78 @@
+/*
+ *  TEST SUITE FOR MB/WC FUNCTIONS IN CLIBRARY
+ *
+ *	 FILE:	dat_wcstod.c
+ *
+ *	 WCSTOD:  double wcstod (const wchar_t *np, wchar_t **endp);
+ */
+
+
+/*
+ *  NOTE:
+ *	  need more test data!
+ *
+ */
+
+
+TST_WCSTOD tst_wcstod_loc [] = {
+  {
+    { Twcstod, TST_LOC_de },
+    {
+      {
+	/*01*/
+	/*I*/
+	{{ 0x0030,0x0030,0x0030,0x002C,0x0030,0x0030,0x0030,0x0030,0x0000 }},
+	/*E*/
+	{ 0,1,0.0,	       0.0,				  0x0000   }
+      },
+      {
+	/*02*/
+	/*I*/
+	{{ 0x0031,0x0032,0x0033,0x002C,0x0034,0x0035,0x0036,0x0040,0x0000 }},
+	/*E*/
+	{ 0,1,123.456,	       123.456,			   0x0040  }
+      },
+      { .is_last = 1 }
+    }
+  },
+  {
+    { Twcstod, TST_LOC_enUS },
+    {
+      {
+	/*01*/
+	/*I*/
+	{{ 0x0030,0x0030,0x0030,0x002E,0x0030,0x0030,0x0030,0x0030,0x0000 }},
+	/*E*/
+	{ 0,1,0.0,	       0.0,				  0x0000   }
+      },
+      {
+	/*02*/
+	/*I*/
+	{{ 0x0031,0x0032,0x0033,0x002E,0x0034,0x0035,0x0036,0x0040,0x0000 }},
+	/*E*/
+	{ 0,1,123.456,	       123.456,			   0x0040  }
+      },
+      { .is_last = 1 }
+    }
+  },
+  {
+#if 0
+    { Twcstod, TST_LOC_eucJP },
+#else
+    { Twcstod, TST_LOC_ja_UTF8 },
+#endif
+    {
+      {
+	/*01*/
+	/*I*/
+	{{ 0x0031,0x0032,0x0033,0x002E,0x0034,0x0035,0x0036,0x0040,0x0000 }},
+	/*E*/
+	{ 0,1,123.456,	       123.456,			   0x0040  }
+      },
+      { .is_last = 1 }
+    }
+  },
+  {
+    { Twcstod, TST_LOC_end }
+  }
+};
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wcstok.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wcstok.c
new file mode 100644
index 00000000..559b4018
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wcstok.c
@@ -0,0 +1,138 @@
+/*
+ *  TEST SUITE FOR MB/WC FUNCTIONS IN CLIBRARY
+ *
+ *	 FILE:	dat_wcstok.c
+ *
+ *	 WCSTOK: wchar_t *wcstok (wchar_t *ws, const wchar_t *dlm,
+ *				  wchar_t **pt);
+ */
+
+/*
+ *  NOTE:
+ *	  need more test data!
+ *	  locale insensitive function...
+ */
+
+
+
+
+TST_WCSTOK tst_wcstok_loc [] = {
+  {
+    { Twcstok, TST_LOC_de },
+    {
+      {
+	{
+	  {
+	    { 1, { 0x00D1,0x00D2,0x00D3,0x00D4,0x00D5,0x00D6,0x00D7,0x00D8,
+		   0x00D9,0x0000 },
+	      {	       0x00D3,0x00D2,	    0x00D5 }
+	    },
+	    { 0, { 0x00D1,0x00D2,0x00D3,0x00D4,0x00D5,0x00D6,0x00D7,0x00D8,
+		   0x00D9,0x0000 },
+	      {	       0x00D3,0x00D2,	    0x00D5 }
+	    },
+	    { 0, { 0x00D1,0x00D2,0x00D3,0x00D4,0x00D5,0x00D6,0x00D7,0x00D8,
+		   0x00D9,0x0000 },
+	      {	       0x00D3,0x00D2,	    0x00D5 }
+	    },
+	  }
+	},
+	{
+	  {
+	    { 0, 0,0,
+	      { 0x00D1,0x0000 }
+	    },
+	    { 0, 0,0,
+	      {			     0x00D4,0x0000 }
+	    },
+	    { 0, 0,0,
+	      { 0x00D6,0x00D7,0x00D8,0x00D9,0x0000 }
+	    },
+	  }
+	}
+      },
+      { .is_last = 1 }
+    }
+  },
+  {
+    { Twcstok, TST_LOC_enUS },
+    {
+      {
+	{
+	  {
+	    { 1, { 0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,0x0048,
+		   0x0049,0x0000 },
+	      {	       0x0043,0x0042,	    0x0045 }
+	    },
+	    { 0, { 0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,0x0048,
+		   0x0049,0x0000 },
+	      {	       0x0043,0x0042,	    0x0045 }
+	    },
+	    { 0, { 0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,0x0048,
+		   0x0049,0x0000 },
+	      {	       0x0043,0x0042,	    0x0045 }
+	    },
+	  }
+	},
+	{
+	  {
+	    { 0, 0,0,
+	      { 0x0041,0x0000 }
+	    },
+	    { 0, 0,0,
+	      {			     0x0044,0x0000 }
+	    },
+	    { 0, 0,0,
+	      { 0x0046,0x0047,0x0048,0x0049,0x0000 }
+	    },
+	  }
+	}
+      },
+      { .is_last = 1 }
+    }
+  },
+  {
+#if 0
+    { Twcstok, TST_LOC_eucJP },
+#else
+    { Twcstok, TST_LOC_ja_UTF8 },
+#endif
+    {
+      {
+	{
+	  {
+	    { 1, { 0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,0x0048,
+		   0x0049,0x0000 },
+	      {	       0x0043,0x0042,	    0x0045 }
+	    },
+	    { 0, { 0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,0x0048,
+		   0x0049,0x0000 },
+	      {	       0x0043,0x0042,	    0x0045 }
+	    },
+	    { 0, { 0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,0x0048,
+		   0x0049,0x0000 },
+	      {	       0x0043,0x0042,	    0x0045 }
+	    },
+	  }
+	},
+	{
+	  {
+	    { 0, 0,0,
+	      { 0x0041,0x0000 }
+	    },
+	    { 0, 0,0,
+	      {			     0x0044,0x0000 }
+	    },
+	    { 0, 0,0,
+	      { 0x0046,0x0047,0x0048,0x0049,0x0000 }
+	    },
+	  }
+	}
+      },
+      { .is_last = 1 }
+    }
+  },
+  {
+    { Twcstok, TST_LOC_end }
+  }
+};
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wcstombs.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wcstombs.c
new file mode 100644
index 00000000..ffeb0ef8
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wcstombs.c
@@ -0,0 +1,271 @@
+/*
+ *  TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY
+ *
+ *	 FILE:	dat_wcstombs.c
+ *
+ *	 WCSTOMBS:  size_t wcstombs (char *s, const wchar_t *ws, size_t n)
+ */
+
+
+/*
+ *  CAUTION:
+ *	     Do not use a value 0x01 for string data. The test program
+ *	     uses it.
+ *
+ */
+
+
+TST_WCSTOMBS tst_wcstombs_loc [] = {
+  {
+    { Twcstombs, TST_LOC_de },
+    {
+      /* #01 : Any chars including a null char should not be stored in s.  */
+      { /*input.*/ { 1,1,	       { 0x00C4,0x00D6,0x00DC,0x0000 }, 0 },
+	/*expect*/ { 0,1,0,	 ""					  },
+      },
+      /* #02 : Only one chars should be stored in s. No null termination.  */
+      { /*input.*/ { 1,1,	       { 0x00C4,0x00D6,0x00DC,0x0000 },	1 },
+	/*expect*/ { 0,1,1,	 "Ä"					  },
+      },
+      /* #03 : Only two chars should be stored in s. No null termination.  */
+      { /*input.*/ { 1,1,	       { 0x00C4,0x00D6,0x00DC,0x0000 },	2 },
+	/*expect*/ { 0,1,2,	 "ÄÖ"					  },
+      },
+      /* #04 : Only three chars should be stored in s. No null
+	       termination.  */
+      { /*input.*/ { 1,1,	       { 0x00C4,0x00D6,0x00DC,0x0000 },	3 },
+	/*expect*/ { 0,1,3,	 "ÄÖÜ"					  },
+      },
+      /* #05 : Only three chars should be stored in s with a null
+	       termination.  */
+      { /*input.*/ { 1,1,	       { 0x00C4,0x00D6,0x00DC,0x0000 },	4 },
+	/*expect*/ { 0,1,3,	 "ÄÖÜ"					  },
+      },
+      /* #06 : Only three chars should be stored in s with a null
+	       termination.  */
+      { /*input.*/ { 1,1,	       { 0x00C4,0x00D6,0x00DC,0x0000 },	5 },
+	/*expect*/ { 0,1,3,	 "ÄÖÜ"					  },
+      },
+      /* #07 : Invalid mb sequence. No chars should be stored in s. */
+      { /*input.*/ { 1,1,	       { 0x0201,0x0221,0x0000,0x0000 },	2 },
+	/*expect*/ { EILSEQ,1,(size_t)-1,	 ""			  },
+      },
+      /* #08 : s is a null pointer, no chars should be stored in s.  */
+      { /*input.*/ { 0,1,	       { 0x00C4,0x00D6,0x00DC,0x0000 }, 0 },
+	/*expect*/ { 0,1,3,	 ""					  },
+      },
+      /* #09 : s is a null pointer, no chars should be stored in s.  */
+      { /*input.*/ { 0,1,	       { 0x00C4,0x00D6,0x00DC,0x0000 }, 1 },
+	/*expect*/ { 0,1,3,	 ""					  },
+      },
+      /* #10 : s is a null pointer, no chars should be stored in s.  */
+      { /*input.*/ { 0,1,	       { 0x00C4,0x00D6,0x00DC,0x0000 }, 5 },
+	/*expect*/ { 0,1,3,	 ""					  },
+      },
+      /* #11 : s is a null pointer. No chars should be stored in s.  */
+      { /*input.*/ { 0,1,	       { 0x0201,0x0221,0x0000,0x0000 }, 5 },
+	/*expect*/ { EILSEQ,1,(size_t)-1,	 ""			  },
+      },
+      /* #12 : ws is a null wc string, no chars should be stored in s.  */
+      { /*input.*/ { 1,1,	       { 0x0000 },			5 },
+	/*expect*/ { 0,1,0,	 ""					  },
+      },
+      /* #13 : s is a null pointer, no chars should be stored in s.  */
+      { /*input.*/ { 0,1,	       { 0x0000 },			5 },
+	/*expect*/ { 0,1,0,	 ""					  },
+      },
+      { .is_last = 1 }
+    }
+  },
+  {
+    { Twcstombs, TST_LOC_enUS },
+    {
+      /* #01 : Any chars including a null char should not be stored in s.  */
+      { /*input.*/ { 1,1,	       { 0x00C4,0x0042,0x0043,0x0000 },	0  },
+	/*expect*/ { 0,1,0,	 ""					   },
+      },
+      /* #02 : Only one chars should be stored in s. No null termination.  */
+      { /*input.*/ { 1,1,	       { 0x0041,0x0042,0x0043,0x0000 }, 1  },
+	/*expect*/ { 0,1,1,	 "A"					   },
+      },
+      /* #03 : Only two chars should be stored in s. No null termination.  */
+      { /*input.*/ { 1,1,	       { 0x0041,0x0042,0x0043,0x0000 }, 2  },
+	/*expect*/ { 0,1,2,	 "AB"					   },
+      },
+      /* #04 : Only three chars should be stored in s. No null
+	       termination.  */
+      { /*input.*/ { 1,1,	       { 0x0041,0x0042,0x0043,0x0000 }, 3  },
+	/*expect*/ { 0,1,3,	 "ABC"					   },
+      },
+      /* #05 : Only three chars should be stored in s with a null
+	       termination.  */
+      { /*input.*/ { 1,1,	       { 0x0041,0x0042,0x0043,0x0000 }, 4  },
+	/*expect*/ { 0,1,3,	 "ABC"					   },
+      },
+      /* #06 : Only three chars should be stored in s with a null
+	       termination.  */
+      { /*input.*/ { 1,1,	       { 0x0041,0x0042,0x0043,0x0000 }, 5  },
+	/*expect*/ { 0,1,3,	 "ABC"					   },
+      },
+      /* #07 : Invalid mb sequence. No chars should be stored in s.  */
+      { /*input.*/ { 1,1,	       { 0x0201,0x0221,0x0000,0x0000 }, 2  },
+	/*expect*/ { EILSEQ,1,(size_t)-1,	 ""			   },
+      },
+      /* #08 : s is a null pointer, no chars should be stored in s.  */
+      { /*input.*/ { 0,1,	       { 0x0041,0x0042,0x0043,0x0000 }, 0  },
+	/*expect*/ { 0,1,3,	 ""					   },
+      },
+      /* #09 : s is a null pointer, no chars should be stored in s.  */
+      { /*input.*/ { 0,1,	       { 0x0041,0x0042,0x0043,0x0000 }, 1  },
+	/*expect*/ { 0,1,3,	 ""					   },
+      },
+      /* #10 : s is a null pointer, no chars should be stored in s.  */
+      { /*input.*/ { 0,1,	       { 0x0041,0x0042,0x0043,0x0000 }, 5  },
+	/*expect*/ { 0,1,3,	 ""					   },
+      },
+      /* #11 : s is a null pointer. No chars should be stored in s.  */
+      { /*input.*/ { 0,1,	       { 0x0201,0x0221,0x0000,0x0000 }, 5  },
+	/*expect*/ { EILSEQ,1,(size_t)-1,	 ""			   },
+      },
+      /* #12 : ws is a null wc string, no chars should be stored in s.  */
+      { /*input.*/ { 1,1,	       { 0x0000 },			5, },
+	/*expect*/ { 0,1,0,	 ""			                   },
+      },
+      /* #13 : s is a null pointer, no chars should be stored in s.  */
+      { /*input.*/ { 0,1,	       { 0x0000 },			5  },
+	/*expect*/ { 0,1,0,	 ""					   },
+      },
+      { .is_last = 1 }
+    }
+  },
+#if 0
+  {
+    { Twcstombs, TST_LOC_eucJP },
+    {
+
+      /* #01 : Any chars including a null char should not be stored in s.  */
+      { /*input.*/ { 1,1,	       { 0x3042,0x3044,0xFF73,0x0000 }, 0  },
+	/*expect*/ { 0,1,0,	 ""					   },
+      },
+      /* #02 : Only one chars should be stored in s. No null termination.  */
+      { /*input.*/ { 1,1,	       { 0x3042,0x3044,0xFF73,0x0000 }, 2  },
+	/*expect*/ { 0,1,2,	     "\244\242"				   },
+      },
+      /* #03 : Only two chars should be stored in s. No null termination.  */
+      { /*input.*/ { 1,1,	       { 0x3042,0x3044,0xFF73,0x0000 }, 4  },
+	/*expect*/ { 0,1,4,	     "\244\242\244\244"			   },
+      },
+      /* #04 : Only three chars should be stored in s. No null
+	       termination.  */
+      { /*input.*/ { 1,1,	       { 0x3042,0x3044,0xFF73,0x0000 }, 6  },
+	/*expect*/ { 0,1,6,	     "\244\242\244\244\216\263"		   },
+      },
+      /* #05 : Only three chars should be stored in s with a null
+	       termination.  */
+      { /*input.*/ { 1,1,	       { 0x3042,0x3044,0xFF73,0x0000 }, 7  },
+	/*expect*/ { 0,1,6,	     "\244\242\244\244\216\263"		   },
+      },
+      /* #06 : Only three chars should be stored in s with a null
+	       termination.  */
+      { /*input.*/ { 1,1,	       { 0x3042,0x3044,0xFF73,0x0000 }, 8  },
+	/*expect*/ { 0,1,6,	     "\244\242\244\244\216\263"		   },
+      },
+      /* #07 : Invalid mb sequence. No chars should be stored in s.  */
+      { /*input.*/ { 1,1,	       { 0x0201,0x0221,0x0000,0x0000 }, 2  },
+	/*expect*/ { EILSEQ,1,-1,	 ""				   },
+      },
+      /* #08 : s is a null pointer, no chars should be stored in s.  */
+      { /*input.*/ { 0,1,	       { 0x3042,0x3044,0xFF73,0x0000 }, 0  },
+	/*expect*/ { 0,1,6,	 ""					   },
+      },
+      /* #09 : s is a null pointer, no chars should be stored in s.  */
+      { /*input.*/ { 0,1,	       { 0x3042,0x3044,0xFF73,0x0000 }, 1  },
+	/*expect*/ { 0,1,6,	 ""					   },
+      },
+      /* #10 : s is a null pointer, no chars should be stored in s.  */
+      { /*input.*/ { 0,1,	       { 0x3042,0x3044,0xFF73,0x0000 }, 8  },
+	/*expect*/ { 0,1,6,	 ""					   },
+      },
+      /* #11 : s is a null pointer. No chars should be stored in s.  */
+      { /*input.*/ { 0,1,	       { 0x0201,0x0221,0x0000,0x0000 }, 5  },
+	/*expect*/ { EILSEQ,1,(size_t)-1,	 ""			   },
+      },
+      /* #12 : ws is a null wc string, no chars should be stored in s.  */
+      { /*input.*/ { 1,1,	       { 0x0000 },			5  },
+	/*expect*/ { 0,1,0,	 ""					   },
+      },
+      /* #13 : s is a null pointer, no chars should be stored in s.  */
+      { /*input.*/ { 0,1,	       { 0x0000 },			5  },
+	/*expect*/ { 0,1,0,	 ""					   },
+      },
+      { .is_last = 1 }
+    }
+  },
+#else
+  {
+    { Twcstombs, TST_LOC_ja_UTF8 },
+    {
+
+      /* #01 : Any chars including a null char should not be stored in s.  */
+      { /*input.*/ { 1,1,	       { 0x3042,0x3044,0xFF73,0x0000 }, 0  },
+	/*expect*/ { 0,1,0,	 ""					   },
+      },
+      /* #02 : Only one chars should be stored in s. No null termination.  */
+      { /*input.*/ { 1,1,	       { 0x3042,0x3044,0xFF73,0x0000 }, 3  },
+	/*expect*/ { 0,1,3,	     "\343\201\202"			   },
+      },
+      /* #03 : Only two chars should be stored in s. No null termination.  */
+      { /*input.*/ { 1,1,	       { 0x3042,0x3044,0xFF73,0x0000 }, 6  },
+	/*expect*/ { 0,1,6,	     "\343\201\202\343\201\204"		   },
+      },
+      /* #04 : Only three chars should be stored in s. No null
+	       termination.  */
+      { /*input.*/ { 1,1,	       { 0x3042,0x3044,0xFF73,0x0000 }, 9  },
+	/*expect*/ { 0,1,9,	"\343\201\202\343\201\204\357\275\263"	   },
+      },
+      /* #05 : Only three chars should be stored in s with a null
+	       termination.  */
+      { /*input.*/ { 1,1,	       { 0x3042,0x3044,0xFF73,0x0000 }, 10 },
+	/*expect*/ { 0,1,9,	"\343\201\202\343\201\204\357\275\263"	   },
+      },
+      /* #06 : Only three chars should be stored in s with a null
+	       termination.  */
+      { /*input.*/ { 1,1,	       { 0x3042,0x3044,0xFF73,0x0000 }, 11 },
+	/*expect*/ { 0,1,9,	"\343\201\202\343\201\204\357\275\263"	   },
+      },
+      /* #07 : Invalid mb sequence. No chars should be stored in s.  */
+      { /*input.*/ { 1,1,	       { 0x0201,0x0221,0x0000,0x0000 }, 2  },
+	/*expect*/ { EILSEQ,1,-1,	 ""				   },
+      },
+      /* #08 : s is a null pointer, no chars should be stored in s.  */
+      { /*input.*/ { 0,1,	       { 0x3042,0x3044,0xFF73,0x0000 }, 0  },
+	/*expect*/ { 0,1,9,	 ""					   },
+      },
+      /* #09 : s is a null pointer, no chars should be stored in s.  */
+      { /*input.*/ { 0,1,	       { 0x3042,0x3044,0xFF73,0x0000 }, 1  },
+	/*expect*/ { 0,1,9,	 ""					   },
+      },
+      /* #10 : s is a null pointer, no chars should be stored in s.  */
+      { /*input.*/ { 0,1,	       { 0x3042,0x3044,0xFF73,0x0000 }, 8  },
+	/*expect*/ { 0,1,9,	 ""					   },
+      },
+      /* #11 : s is a null pointer. No chars should be stored in s.  */
+      { /*input.*/ { 0,1,	       { 0x0201,0x0221,0x0000,0x0000 }, 5  },
+	/*expect*/ { EILSEQ,1,(size_t)-1,	 ""			   },
+      },
+      /* #12 : ws is a null wc string, no chars should be stored in s.  */
+      { /*input.*/ { 1,1,	       { 0x0000 },			5  },
+	/*expect*/ { 0,1,0,	 ""					   },
+      },
+      /* #13 : s is a null pointer, no chars should be stored in s.  */
+      { /*input.*/ { 0,1,	       { 0x0000 },			5  },
+	/*expect*/ { 0,1,0,	 ""					   },
+      },
+      { .is_last = 1 }
+    }
+  },
+#endif
+  {
+    { Twcstombs, TST_LOC_end }
+  }
+};
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wcswidth.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wcswidth.c
new file mode 100644
index 00000000..6d2f98e1
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wcswidth.c
@@ -0,0 +1,263 @@
+/*
+ *  TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY
+ *
+ *	 FILE:	dat_wcswidth.c
+ *
+ *	 WCSWIDTH:  int	 wcswidth (const wchar_t *ws, size_t n);
+ */
+
+TST_WCSWIDTH tst_wcswidth_loc [] = {
+  {
+    { Twcswidth, TST_LOC_de },
+    {
+      { /*input.*/ { { 0x00C1,0x00C2,0x00C3,0x0000 },	 0 },  /* 01 */
+	/*expect*/ { 0,1,0				   },
+      },
+      { /*input.*/ { { 0x00C1,0x00C2,0x00C3,0x0000 },	 1 },  /* 02 */
+	/*expect*/ { 0,1,1				   },
+      },
+      { /*input.*/ { { 0x00C1,0x00C2,0x00C3,0x0000 },	 2 },  /* 03 */
+	/*expect*/ { 0,1,2				   },
+      },
+      { /*input.*/ { { 0x00C1,0x00C2,0x00C3,0x0000 },	 3 },  /* 04 */
+	/*expect*/ { 0,1,3				   },
+      },
+      { /*input.*/ { { 0x00C1,0x00C2,0x00C3,0x0000 },	 4 },  /* 05 */
+	/*expect*/ { 0,1,3				   },
+      },
+      { /*input.*/ { { 0x0000 },			 1 },  /* 06 */
+	/*expect*/ { 0,1,0				   },
+      },
+      { /*input.*/ { { 0x00C1,0x0001,0x0000 },		 2 },  /* 07 */
+	/*expect*/ { 0,1,-1				   },
+      },
+      { /*input.*/ { { 0x00C1,0x0001,0x0000 },		 1 },  /* 08 */
+	/*expect*/ { 0,1,1				   },
+      },
+      { /*input.*/ { { 0x00C1,0x0001,0x0000 },		 2 },  /* 09 */
+	/*expect*/ { 0,1,-1				   },
+      },
+      { /*input.*/ { { 0x00C1,0x0092,0x0000 },		 2 },  /* 10 */
+	/*expect*/ { 0,1,-1				   },
+      },
+      { /*input.*/ { { 0x00C1,0x0020,0x0000 },		 2 },  /* 11 */
+	/*expect*/ { 0,1,2				   },
+      },
+      { /*input.*/ { { 0x00C1,0x0021,0x0000 },		 2 },  /* 12 */
+	/*expect*/ { 0,1,2				   },
+      },
+      { /*input.*/ { { 0x00C1,0x007E,0x0000 },		 2 },  /* 13 */
+	/*expect*/ { 0,1,2				   },
+      },
+      { /*input.*/ { { 0x00C1,0x007F,0x0000 },		 2 },  /* 14 */
+	/*expect*/ { 0,1,-1				   },
+      },
+      { /*input.*/ { { 0x00C1,0x0080,0x0000 },		 2 },  /* 15 */
+	/*expect*/ { 0,1,-1				   },
+      },
+      { /*input.*/ { { 0x00C1,0x00A0,0x0000 },		 2 },  /* 16 */
+#ifdef SHOJI_IS_RIGHT
+	/*expect*/ { 0,1,-1				   },
+#else
+	/*expect*/ { 0,1,2				   },
+#endif
+      },
+      { /*input.*/ { { 0x00C1,0x00A1,0x0000 },		 2 },  /* 17 */
+	/*expect*/ { 0,1,2				   },
+      },
+      { /*input.*/ { { 0x00C1,0x00FF,0x0000 },		 2 },  /* 18 */
+	/*expect*/ { 0,1,2				   },
+      },
+      { /*input.*/ { { 0x00C1,0x3042,0x0000 },		 2 },  /* 19 */
+	/*expect*/ { 0,1,-1				   },
+      },
+      { /*input.*/ { { 0x00C1,0x3044,0x0000 },		 2 },  /* 20 */
+	/*expect*/ { 0,1,-1				   },
+      },
+      { .is_last = 1 }
+    }
+  },
+  {
+    { Twcswidth, TST_LOC_enUS },
+    {
+      { /*input.*/ { { 0x0041,0x0042,0x00C3,0x0000 },	 0 },  /* 01 */
+	/*expect*/ { 0,1,0				   },
+      },
+      { /*input.*/ { { 0x0041,0x0042,0x00C3,0x0000 },	 1 },  /* 02 */
+	/*expect*/ { 0,1,1				   },
+      },
+      { /*input.*/ { { 0x0041,0x0042,0x00C3,0x0000 },	 2 },  /* 03 */
+	/*expect*/ { 0,1,2				   },
+      },
+#ifdef SHOJI_IS_RIGHT
+      { /*input.*/ { { 0x0041,0x0042,0x00C3,0x0000 },	 3 },  /* 04 */
+	/*expect*/ { 0,1,3				   },
+      },
+      { /*input.*/ { { 0x0041,0x0042,0x00C3,0x0000 },	 4 },  /* 05 */
+	/*expect*/ { 0,1,3				   },
+      },
+#else
+      { /*input.*/ { { 0x0041,0x0042,0x00C3,0x0000 },	 3 },  /* 04 */
+	/*expect*/ { 0,1,-1				   },
+      },
+      { /*input.*/ { { 0x0041,0x0042,0x0043,0x0000 },	 4 },  /* 05 */
+	/*expect*/ { 0,1,3				   },
+      },
+#endif
+      { /*input.*/ { { 0x0000 },			 1 },  /* 06 */
+	/*expect*/ { 0,1,0				   },
+      },
+      { /*input.*/ { { 0x0041,0x0001,0x0000 },		 2 },  /* 07 */
+	/*expect*/ { 0,1,-1				   },
+      },
+      { /*input.*/ { { 0x0041,0x0001,0x0000 },		 1 },  /* 08 */
+	/*expect*/ { 0,1,1				   },
+      },
+      { /*input.*/ { { 0x0041,0x0001,0x0000 },		 2 },  /* 09 */
+	/*expect*/ { 0,1,-1				   },
+      },
+      { /*input.*/ { { 0x0041,0x0092,0x0000 },		 2 },  /* 10 */
+	/*expect*/ { 0,1,-1				   },
+      },
+      { /*input.*/ { { 0x0041,0x0020,0x0000 },		 2 },  /* 11 */
+	/*expect*/ { 0,1,2				   },
+      },
+      { /*input.*/ { { 0x0041,0x0021,0x0000 },		 2 },  /* 12 */
+	/*expect*/ { 0,1,2				   },
+      },
+      { /*input.*/ { { 0x0041,0x007E,0x0000 },		 2 },  /* 13 */
+	/*expect*/ { 0,1,2				   },
+      },
+      { /*input.*/ { { 0x0041,0x007F,0x0000 },		 2 },  /* 14 */
+	/*expect*/ { 0,1,-1				   },
+      },
+      { /*input.*/ { { 0x0041,0x0080,0x0000 },		 2 },  /* 15 */
+	/*expect*/ { 0,1,-1				   },
+      },
+      { /*input.*/ { { 0x0041,0x00A0,0x0000 },		 2 },  /* 16 */
+	/*expect*/ { 0,1,-1				   },
+      },
+#ifdef SHOJI_IS_RIGHT
+      { /*input.*/ { { 0x0041,0x00A1,0x0000 },		 2 },  /* 17 */
+	/*expect*/ { 0,1,2				   },
+      },
+      { /*input.*/ { { 0x0041,0x00FF,0x0000 },		 2 },  /* 18 */
+	/*expect*/ { 0,1,2				   },
+      },
+#else
+      { /*input.*/ { { 0x0041,0x007E,0x0000 },		 2 },  /* 17 */
+	/*expect*/ { 0,1,2				   },
+      },
+      { /*input.*/ { { 0x0041,0x0020,0x0000 },		 2 },  /* 18 */
+	/*expect*/ { 0,1,2				   },
+      },
+#endif
+      { /*input.*/ { { 0x0041,0x3042,0x0000 },		 2 },  /* 19 */
+	/*expect*/ { 0,1,-1				   },
+      },
+      { /*input.*/ { { 0x0041,0x3044,0x0000 },		 2 },  /* 20 */
+	/*expect*/ { 0,1,-1				   },
+      },
+      { .is_last = 1 }
+    }
+  },
+  {
+#if 0
+    { Twcswidth, TST_LOC_eucJP },
+#else
+    { Twcswidth, TST_LOC_ja_UTF8 },
+#endif
+    {
+      { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 },	 0 },  /* 01 */
+	/*expect*/ { 0,1,0				   },
+      },
+      { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 },	 1 },  /* 02 */
+	/*expect*/ { 0,1,2				   },
+      },
+      { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 },	 2 },  /* 03 */
+	/*expect*/ { 0,1,4				   },
+      },
+      { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 },	 3 },  /* 04 */
+	/*expect*/ { 0,1,6				   },
+      },
+      { /*input.*/ { { 0x3041,0x3042,0x3043,0x0000 },	 4 },  /* 05 */
+	/*expect*/ { 0,1,6				   },
+      },
+      { /*input.*/ { { 0x0000 },			 1 },  /* 06 */
+	/*expect*/ { 0,1,0				   },
+      },
+      { /*input.*/ { { 0x008E,0x0001,0x0000 },		 2 },  /* 07 */
+	/*expect*/ { 0,1,-1				   },
+      },
+      { /*input.*/ { { 0x3041,0x008E,0x0000 },		 1 },  /* 08 */
+	/*expect*/ { 0,1,2				   },
+      },
+      { /*input.*/ { { 0x3041,0x008E,0x0000 },		 2 },  /* 09 */
+	/*expect*/ { 0,1,-1				   },
+      },
+      { /*input.*/ { { 0x3041,0x0001,0x0000 },		 2 },  /* 10 */
+	/*expect*/ { 0,1,-1				   },
+      },
+      { /*input.*/ { { 0x3041,0x3000,0x0000 },		 2 },  /* 11 */
+	/*expect*/ { 0,1,4				   },
+      },
+      { /*input.*/ { { 0x0041,0x0021,0x0000 },		 2 },  /* 12 */
+	/*expect*/ { 0,1,2				   },
+      },
+      { /*input.*/ { { 0x0041,0x007E,0x0000 },		 2 },  /* 13 */
+	/*expect*/ { 0,1,2				   },
+      },
+      { /*input.*/ { { 0x0041,0x007F,0x0000 },		 2 },  /* 14 */
+	/*expect*/ { 0,1,-1				   },
+      },
+      { /*input.*/ { { 0x0041,0x0080,0x0000 },		 2 },  /* 15 */
+	/*expect*/ { 0,1,-1				   },
+      },
+#if 0
+      { /*input.*/ { { 0x0041,0x00A0,0x0000 },		 2 },  /* 16 */
+	/*expect*/ { 0,1,-1				   },
+      },
+#ifdef NO_WAIVER
+      /*  */	 /* returns 3 */
+      { /*input.*/ { { 0x0041,0x00A1,0x0000 },		 2 },  /* 17 */
+	/*expect*/ { 0,1,-1				   },
+      },
+#else
+      /* XXX U00A1 is valid -> /x8f/xa2/xc4 in JIS X 0212 */
+      { /*input.*/ { { 0x0041,0x00A1,0x0000 },		 2 },  /* 17 */
+	/*expect*/ { 0,1,3				   },
+      },
+#endif
+#else
+      /* XXX U00A0 i UTF8 is valid -> /xc2/xa0 */
+      { /*input.*/ { { 0x0041,0x00A0,0x0000 },		 2 },  /* 16 */
+	/*expect*/ { 0,1,2				   },
+      },
+#ifdef NO_WAIVER
+      /*  */	 /* returns 3 */
+      { /*input.*/ { { 0x0041,0x00A1,0x0000 },		 2 },  /* 17 */
+	/*expect*/ { 0,1,-1				   },
+      },
+#else
+      /* XXX U00A1 in UTF-8 is valid -> /xc2/xa1 */
+      { /*input.*/ { { 0x0041,0x00A1,0x0000 },		 2 },  /* 17 */
+	/*expect*/ { 0,1,2				   },
+      },
+#endif
+#endif
+      { /*input.*/ { { 0x0041,0xFF71,0x0000 },		 2 },  /* 18 */
+	/*expect*/ { 0,1,2				   },
+      },
+      { /*input.*/ { { 0x0041,0x3042,0x0000 },		 2 },  /* 19 */
+	/*expect*/ { 0,1,3				   },
+      },
+      { /*input.*/ { { 0x0041,0x3044,0x0000 },		 2 },  /* 20 */
+	/*expect*/ { 0,1,3				   },
+      },
+      { .is_last = 1 }
+    }
+  },
+  {
+    { Twcswidth, TST_LOC_end }
+  }
+};
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wcsxfrm.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wcsxfrm.c
new file mode 100644
index 00000000..acb6727a
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wcsxfrm.c
@@ -0,0 +1,102 @@
+/*
+ *  TEST SUITE FOR MB/WC FUNCTIONS IN CLIBRARY
+ *
+ *	 FILE:	dat_wcsxfrm.c
+ *
+ *	 WCSXFRM:  size_t  wcsxfrm (char *s1, const char s2, size_t n);
+ */
+
+/*
+ *  NOTE:
+ *
+ *  Return value and errno value are checked only for 2nd string:
+ *  org2[]; n1 and n2 don't mean bytes to be translated.
+ *  It means a buffer size including a null character.
+ *  Results of this test depens on results of wcscoll().
+ *  If you got errors, check both test results.
+ */
+
+
+TST_WCSXFRM tst_wcsxfrm_loc [] = {
+
+  {
+    { Twcsxfrm, TST_LOC_de },
+    {
+      { /*inp*/ { { 0x00C1,0x0000 }, { 0x00C1,0x0000 }, 7, 7 },	 /* #01 */
+	/*exp*/ {   0,	       0,0,		     },
+      },
+      { /*inp*/ { { 0x0042,0x0000 }, { 0x0061,0x0000 }, 7, 7 },	 /* #02 */
+	/*exp*/ {   0,	       0,0,		     },
+      },
+      { /*inp*/ { { 0x0061,0x0000 }, { 0x0042,0x0000 }, 7, 7 },	 /* #03 */
+	/*exp*/ {   0,	       0,0,		     },
+      },
+      { /*inp*/ { { 0x00E4,0x0000 }, { 0x00DC,0x0000 }, 7, 7 },	 /* #04 */
+	/*exp*/ {   0,	       0,0,		     },
+      },
+      { /*inp*/ { { 0x00DC,0x0000 }, { 0x00E4,0x0000 }, 7, 7 },	 /* #05 */
+	/*exp*/ {   0,	       0,0,		     },
+      },
+      { .is_last = 1 }
+    }
+  },
+  {
+    { Twcsxfrm, TST_LOC_enUS },
+    {
+      { /*inp*/ { { 0x0041,0x0000 }, { 0x0041,0x0000 }, 7, 7 },	 /* #01 */
+	/*exp*/ {   0,	       0,0,		     },
+      },
+      { /*inp*/ { { 0x0042,0x0000 }, { 0x0061,0x0000 }, 7, 7 },	 /* #02 */
+	/*exp*/ {   0,	       0,0,		     },
+      },
+      { /*inp*/ { { 0x0061,0x0000 }, { 0x0042,0x0000 }, 7, 7 },	 /* #03 */
+	/*exp*/ {   0,	       0,0,		     },
+      },
+      { /*inp*/ { { 0x0000,0x0000 }, { 0x0000,0x0000 }, 7, 7 },	 /* #04 */
+	/*exp*/ {   0,	       0,0,		     },
+      },
+#ifdef NO_WAIVER
+      { /*  x 2 */
+	/*inp*/ { { 0x3061,0x0000 }, { 0xFF42,0x0000 }, 7, 7 },	 /* #05 */
+	/* 	*/
+	/*exp*/ {   EINVAL,	       1,(size_t)-1,	     },
+      },
+#endif
+      { .is_last = 1 }
+    }
+  },
+  {
+#if 0
+    { Twcsxfrm, TST_LOC_eucJP },	     /* need more test data ! */
+#else
+    { Twcsxfrm, TST_LOC_ja_UTF8 },	     /* need more test data ! */
+#endif
+    {
+      { /*inp*/ { { 0x3041,0x0000 }, { 0x3041,0x0000 }, 7, 7 },	 /* #01 */
+	/*exp*/ {   0,	       0,0,		     },
+      },
+      { /*inp*/ { { 0x0042,0x0000 }, { 0x0061,0x0000 }, 7, 7 },	 /* #02 */
+	/*exp*/ {   0,	       0,0,		     },
+      },
+      { /*inp*/ { { 0x0061,0x0000 }, { 0x0042,0x0000 }, 7, 7 },	 /* #03 */
+	/*exp*/ {   0,	       0,0,		     },
+      },
+      { /*inp*/ { { 0x30A2,0x0000 }, { 0xFF71,0x0000 }, 7, 7 },	 /* #04 */
+	/*exp*/ {   0,	       0,0,		     },
+      },
+      { /*inp*/ { { 0xFF71,0x0000 }, { 0x30A2,0x0000 }, 7, 7 },	 /* #05 */
+	/*exp*/ {   0,	       0,0,		     },
+      },
+#ifdef NO_WAIVER
+      /*  x 2 */
+      { /*inp*/ { { 0x008E,0x0000 }, { 0x008F,0x0000 }, 7, 7 },	 /* #06 */
+	/*exp*/ {   EINVAL,	       1,(size_t)-1,	     },
+      },
+#endif
+      { .is_last = 1 }
+    }
+  },
+  {
+    { Twcsxfrm, TST_LOC_end }
+  }
+};
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wctob.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wctob.c
new file mode 100644
index 00000000..dfd344eb
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wctob.c
@@ -0,0 +1,61 @@
+/*
+ *  TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY
+ *
+ *	 FILE:	dat_wctob.c
+ *
+ *	 ISW*:	int wctob( wint_t wc );
+ */
+
+
+TST_WCTOB tst_wctob_loc [] = {
+
+    {	{ Twctob, TST_LOC_de },
+	{
+	  {  { WEOF   }, { 0,	 1, EOF	       }  },
+	  {  { 0x0020 }, { 0,	 1, 0x20       }  },
+	  {  { 0x0061 }, { 0,	 1, 0x61       }  },
+	  {  { 0x0080 }, { 0,	 1, 0x80       }  },
+	  {  { 0x00C4 }, { 0,	 1, 0xC4       }  },
+	  {  { 0x30C4 }, { 0,	 1, EOF	       }  },
+	  {  .is_last = 1 } /* Last element.  */
+	}
+    },
+    {	{ Twctob, TST_LOC_enUS },
+	{
+	  {  { WEOF   }, { 0,	 1, EOF	       }  },
+	  {  { 0x0020 }, { 0,	 1, 0x20       }  },
+	  {  { 0x0061 }, { 0,	 1, 0x61       }  },
+#ifdef SHOJI_IS_RIGHT
+	  {  { 0x0080 }, { 0,	 1, 0x80       }  },
+	  {  { 0x00C4 }, { 0,	 1, 0xC4       }  },
+#else
+	  /* XXX These are no valid characters.  */
+	  {  { 0x0080 }, { 0,	 1, EOF        }  },
+	  {  { 0x00C4 }, { 0,	 1, EOF        }  },
+#endif
+	  {  { 0x30C4 }, { 0,	 1, EOF	       }  },
+	  {  .is_last = 1 } /* Last element.  */
+	}
+    },
+#if 0
+    {	{ Twctob, TST_LOC_eucJP },
+#else
+    {	{ Twctob, TST_LOC_ja_UTF8 },
+#endif
+	{
+	  {  { WEOF   }, { 0,	 1, EOF	       }  },
+	  {  { 0x0020 }, { 0,	 1, 0x20       }  },
+	  {  { 0x0061 }, { 0,	 1, 0x61       }  },
+#if 0
+	  {  { 0x0080 }, { 0,	 1, 0x80       }  },
+#else
+	  {  { 0x0080 }, { 0,	 1, EOF       }  },
+#endif
+	  {  { 0x00FF }, { 0,	 1, EOF        }  },
+	  {  { 0x00C4 }, { 0,	 1, EOF	       }  },
+	  {  { 0x30C4 }, { 0,	 1, EOF	       }  },
+	  {  .is_last = 1 } /* Last element.  */
+	}
+    },
+    {	{ Twctob, TST_LOC_end } }
+};
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wctomb.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wctomb.c
new file mode 100644
index 00000000..0ec3a9c0
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wctomb.c
@@ -0,0 +1,168 @@
+/*
+ *  TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY
+ *
+ *	 FILE:	dat_wctomb.c
+ *
+ *	 WCTOMB:  int wctomb (char *s, wchar_t wc)
+ */
+
+
+/*
+ *  FUNCTION:
+ *
+ *	  int  wctomb (char *s, wchar_t wc);
+ *
+ *	       return: the number of bytes
+ *
+ *  NOTE:
+ *
+ *	 o When you feed a null pointer for a string (s) to the function,
+ *	   set s_flg=0 instead of putting just a 'NULL' there.
+ *	   Even if you put a 'NULL', it means a null string as well as "".
+ *
+ *	 o When s is a null pointer, the function checks state dependency.
+ *
+ *	       state-dependent encoding	     - return  NON-zero
+ *	       state-independent encoding    - return  0
+ *
+ *	   If state-dependent encoding is expected, set
+ *
+ *	       s_flg = 0,  ret_flg = 0,	 ret_val = +1
+ *
+ *	   If state-independent encoding is expected, set
+ *
+ *	       s_flg = 0,  ret_flg = 0,	 ret_val = 0
+ *
+ *
+ *	   When you set ret_flg=1, the test program simply compares an
+ *	   actual return value with an expected value. You can check
+ *	   state-independent case (return value is 0) in that way, but
+ *	   you can not check state-dependent case. So when you check
+ *	   state- dependency in this test function: tst_wctomb(), set
+ *	   ret_flg=0 always. It's a special case, and the test
+ *	   function takes care of it.
+ *
+ *	      Input	  Expect
+ *
+ *		s_flg=0		  ret_flg=0
+ *		|		  |
+ *	      { 0, 0 },	  { 0, 0, 0,  x,  "" }
+ *		   |		      |
+ *		   not used	      ret_val: 0/+1
+ * (expected val)
+ */
+
+
+TST_WCTOMB tst_wctomb_loc [] = {
+  {
+    { Twctomb, TST_LOC_de },
+    {
+      /* #01 : normal case		   */
+      { /*input.*/ { 1,	   0x00C4  },
+	/*expect*/ { 0,1,1,  "Ä"	   },
+      },
+      /* #02 : normal case		   */
+      { /*input.*/ { 1,	   0x00DC  },
+	/*expect*/ { 0,1,1,  "Ü"	   },
+      },
+      /* #03 : normal case		   */
+      { /*input.*/ { 1,	   0x0092  },
+	/*expect*/ { 0,1,1,  "\222"  },
+      },
+      /* #04 : error case		   */
+      { /*input.*/ { 1,	   0x3041  },
+	/*expect*/ { 0,1,-1, ""	   },
+      },
+      /* #05 : state dependency	   */
+      { /*input.*/ { 0,	   0x0000  },
+	/*expect*/ { 0,0,0,  ""	   },
+      },
+      { .is_last = 1 }
+    }
+  },
+  {
+    { Twctomb, TST_LOC_enUS },
+    {
+      /* #01 : normal case		   */
+      { /*input.*/ { 1,	   0x0041  },
+	/*expect*/ { 0,1,1,  "A"	   },
+      },
+      /* #02 : normal case		   */
+      { /*input.*/ { 1,	   0x0042  },
+	/*expect*/ { 0,1,1,  "B"	   },
+      },
+      /* #03 : error case		   */
+      /*  */
+      { /*input.*/ { 1,	   0x00C4  },
+	/*expect*/ { 0,1,-1, ""	   },
+      },
+      /* #04 : error case		   */
+      { /*input.*/ { 1,	   0x30A4  },
+	/*expect*/ { 0,1,-1, ""	   },
+      },
+      /* #05 : state dependency	   */
+      { /*input.*/ { 0,	   0x0000  },
+	/*expect*/ { 0,0,0,  ""	   },
+      },
+      { .is_last = 1 }
+    }
+  },
+#if 0
+  {
+    { Twctomb, TST_LOC_eucJP },
+    {
+      /* #01 : normal case		   */
+      { /*input.*/ { 1,	   0x3042  },
+	/*expect*/ { 0,1,2,  "\244\242"   },
+      },
+      /* #02 : normal case		   */
+      { /*input.*/ { 1,	   0x3044  },
+	/*expect*/ { 0,1,2,  "\244\244"   },
+      },
+      /* #03 : normal case		   */
+      { /*input.*/ { 1,	   0x008E  },
+	/*expect*/ { 0,1,-1, ""	   },
+      },
+      /* #04 : jisX0212		   */
+      { /*input.*/ { 1,	   0x00C4	  },
+	/*expect*/ { 0,1,3,  "\217\252\243" }, /* jisx0210  returns 3 */
+      },
+      /* #05 : state dependency	   */
+      { /*input.*/ { 0,	   0x008E  },
+	/*expect*/ { 0,0,0,  ""	   },
+      },
+      { .is_last = 1 }
+    }
+  },
+#else
+  {
+    { Twctomb, TST_LOC_ja_UTF8 },
+    {
+      /* #01 : normal case		   */
+      { /*input.*/ { 1,	   0x3042  },
+	/*expect*/ { 0,1,3,  "\343\201\202"   },
+      },
+      /* #02 : normal case		   */
+      { /*input.*/ { 1,	   0x3044  },
+	/*expect*/ { 0,1,3,  "\343\201\204"   },
+      },
+      /* #03 : normal case		   */
+      { /*input.*/ { 1,	   0x008E  },
+	/*expect*/ { 0,1,2, "\302\216"	   },
+      },
+      /* #04 : jisX0212		   */
+      { /*input.*/ { 1,	   0x00C4	  },
+	/*expect*/ { 0,1,2,  "\303\204" }, /* jisx0210  returns 3 */
+      },
+      /* #05 : state dependency	   */
+      { /*input.*/ { 0,	   0x008E  },
+	/*expect*/ { 0,0,0,  ""	   },
+      },
+      { .is_last = 1 }
+    }
+  },
+#endif
+  {
+    { Twctomb, TST_LOC_end }
+  }
+};
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wctrans.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wctrans.c
new file mode 100644
index 00000000..df4d3ad6
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wctrans.c
@@ -0,0 +1,99 @@
+/*
+ *  TEST SUITE FOR MB/WC FUNCTIONS IN CLIBRARY
+ *
+ *       FILE:  dat_wctrans.c
+ *
+ *       WCTRANS:  wctrans_t  wctrans( const char *charclass );
+ */
+
+/*
+ *  NOTE:
+ *        When a return value is expected to be 0 (false),
+ *        set ret_flg=1 and set ret_val=0.
+ *        Otherwise just set ret_flg=0.
+ */
+
+
+TST_WCTRANS tst_wctrans_loc [] = {
+
+    {   { Twctrans, TST_LOC_de },
+        {
+          { /*inp*/ { ""               },  /* #1 */
+            /*exp*/ { 0,1,0,         },
+          },
+          { /*inp*/ { "upper"          },  /* #2 */
+            /*exp*/ { 0,1,0,         },
+          },
+          { /*inp*/ { "lower"          },  /* #3 */
+            /*exp*/ { 0,1,0,         },
+          },
+          { /*inp*/ { "toupper"        },  /* #4 */
+            /*exp*/ { 0,0,0,         },
+          },
+          { /*inp*/ { "tolower"        },  /* #5 */
+            /*exp*/ { 0,0,0,         },
+          },
+          { /*inp*/ { "xxxxx"          },  /* #6 */
+            /*exp*/ { 0,1,0,         },
+          },
+	  { .is_last = 1 }
+        }
+    },
+    {   { Twctrans, TST_LOC_enUS },
+        {
+          { /*inp*/ { ""               },  /* #1 */
+            /*exp*/ { 0,1,0,         },
+          },
+          { /*inp*/ { "upper"          },  /* #2 */
+            /*exp*/ { 0,1,0,         },
+          },
+          { /*inp*/ { "lower"          },  /* #3 */
+            /*exp*/ { 0,1,0,         },
+          },
+          { /*inp*/ { "toupper"        },  /* #4 */
+            /*exp*/ { 0,0,0,         },
+          },
+          { /*inp*/ { "tolower"        },  /* #5 */
+            /*exp*/ { 0,0,0,         },
+          },
+          { /*inp*/ { "xxxxx"          },  /* #6 */
+            /*exp*/ { 0,1,0,         },
+          },
+	  { .is_last = 1 }
+        }
+    },
+#if 0
+    {   { Twctrans, TST_LOC_eucJP },
+#else
+    {   { Twctrans, TST_LOC_ja_UTF8 },
+#endif
+        {
+          { /*inp*/ { ""               },  /* #1 */
+            /*exp*/ { 0,1,0,         },
+          },
+          { /*inp*/ { "upper"          },  /* #2 */
+            /*exp*/ { 0,1,0,         },
+          },
+          { /*inp*/ { "lower"          },  /* #3 */
+            /*exp*/ { 0,1,0,         },
+          },
+          { /*inp*/ { "toupper"        },  /* #4 */
+            /*exp*/ { 0,0,0,         },
+          },
+          { /*inp*/ { "tolower"        },  /* #5 */
+            /*exp*/ { 0,0,0,         },
+          },
+          { /*inp*/ { "xxxxx"          },  /* #6 */
+            /*exp*/ { 0,1,0,         },
+          },
+          { /*inp*/ { "tojhira"        },  /* #7 */
+            /*exp*/ { 0,0,0,         },
+          },
+          { /*inp*/ { "tojkata"        },  /* #8 */
+            /*exp*/ { 0,0,0,         },
+          },
+	  { .is_last = 1 }
+        }
+    },
+    {   { Twctrans, TST_LOC_end }}
+};
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wctype.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wctype.c
new file mode 100644
index 00000000..db3bf33e
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wctype.c
@@ -0,0 +1,189 @@
+/*
+ *  TEST SUITE FOR MB/WC FUNCTIONS IN CLIBRARY
+ *
+ *	 FILE:	dat_wctype.c
+ *
+ *	 WCTYPE:  wctype_t  wctype( const char *class );
+ */
+
+/*
+ *  NOTE:
+ *	  When a return value is expected to be 0 (false),
+ *	  set ret_flg=1 and set ret_val=0.
+ *	  Otherwise just set ret_flg=0.
+ */
+
+
+TST_WCTYPE tst_wctype_loc [] = {
+
+    {	{ Twctype, TST_LOC_de },
+	{
+	  { /*inp*/ { "alnum"	       },  /* #01 */
+	    /*exp*/ { 0,0,0,	       },
+	  },
+	  { /*inp*/ { "alpha"	       },  /* #02 */
+	    /*exp*/ { 0,0,0,	       },
+	  },
+	  { /*inp*/ { "cntrl"	       },  /* #03 */
+	    /*exp*/ { 0,0,0,	       },
+	  },
+	  { /*inp*/ { "digit"	       },  /* #04 */
+	    /*exp*/ { 0,0,0,	       },
+	  },
+	  { /*inp*/ { "graph"	       },  /* #05 */
+	    /*exp*/ { 0,0,0,	       },
+	  },
+	  { /*inp*/ { "lower"	       },  /* #06 */
+	    /*exp*/ { 0,0,0,	       },
+	  },
+	  { /*inp*/ { "print"	       },  /* #07 */
+	    /*exp*/ { 0,0,0,	       },
+	  },
+	  { /*inp*/ { "punct"	       },  /* #08 */
+	    /*exp*/ { 0,0,0,	       },
+	  },
+	  { /*inp*/ { "space"	       },  /* #09 */
+	    /*exp*/ { 0,0,0,	       },
+	  },
+	  { /*inp*/ { "upper"	       },  /* #10 */
+	    /*exp*/ { 0,0,0,	       },
+	  },
+	  { /*inp*/ { "xdigit"	       },  /* #11 */
+	    /*exp*/ { 0,0,0,	       },
+	  },
+	  { /*inp*/ { ""	       },  /* #12 */
+	    /*exp*/ { 0,1,0,	       },
+	  },
+	  { /*inp*/ { "ideograph"      },  /* #13 */
+	    /*exp*/ { 0,1,0,	       },
+	  },
+	  { /*inp*/ { "english"	       },  /* #14 */
+	    /*exp*/ { 0,1,0,	       },
+	  },
+	  { /*inp*/ { "ascii"	       },  /* #15 */
+	    /*exp*/ { 0,1,0,	       },
+	  },
+	  { /*inp*/ { "special"	       },  /* #16 */
+	    /*exp*/ { 0,1,0,	       },
+	  },
+	  { .is_last = 1 }
+	}
+    },
+    {	{ Twctype, TST_LOC_enUS },
+	{
+	  { /*inp*/ { "alnum"	       },  /* #01 */
+	    /*exp*/ { 0,0,0,	       },
+	  },
+	  { /*inp*/ { "alpha"	       },  /* #02 */
+	    /*exp*/ { 0,0,0,	       },
+	  },
+	  { /*inp*/ { "cntrl"	       },  /* #03 */
+	    /*exp*/ { 0,0,0,	       },
+	  },
+	  { /*inp*/ { "digit"	       },  /* #04 */
+	    /*exp*/ { 0,0,0,	       },
+	  },
+	  { /*inp*/ { "graph"	       },  /* #05 */
+	    /*exp*/ { 0,0,0,	       },
+	  },
+	  { /*inp*/ { "lower"	       },  /* #06 */
+	    /*exp*/ { 0,0,0,	       },
+	  },
+	  { /*inp*/ { "print"	       },  /* #07 */
+	    /*exp*/ { 0,0,0,	       },
+	  },
+	  { /*inp*/ { "punct"	       },  /* #08 */
+	    /*exp*/ { 0,0,0,	       },
+	  },
+	  { /*inp*/ { "space"	       },  /* #09 */
+	    /*exp*/ { 0,0,0,	       },
+	  },
+	  { /*inp*/ { "upper"	       },  /* #10 */
+	    /*exp*/ { 0,0,0,	       },
+	  },
+	  { /*inp*/ { "xdigit"	       },  /* #11 */
+	    /*exp*/ { 0,0,0,	       },
+	  },
+	  { /*inp*/ { ""	       },  /* #12 */
+	    /*exp*/ { 0,1,0,	       },
+	  },
+	  { /*inp*/ { "ideograph"      },  /* #13 */
+	    /*exp*/ { 0,1,0,	       },
+	  },
+	  { /*inp*/ { "english"	       },  /* #14 */
+	    /*exp*/ { 0,1,0,	       },
+	  },
+	  { /*inp*/ { "ascii"	       },  /* #15 */
+	    /*exp*/ { 0,1,0,	       },
+	  },
+	  { /*inp*/ { "special"	       },  /* #16 */
+	    /*exp*/ { 0,1,0,	       },
+	  },
+	  { .is_last = 1 }
+	}
+    },
+#if 0
+    {	{ Twctype, TST_LOC_eucJP },
+#else
+    {	{ Twctype, TST_LOC_ja_UTF8 },
+#endif
+	{
+	  { /*inp*/ { "alnum"	       },  /* #01 */
+	    /*exp*/ { 0,0,0,	       },
+	  },
+	  { /*inp*/ { "alpha"	       },  /* #02 */
+	    /*exp*/ { 0,0,0,	       },
+	  },
+	  { /*inp*/ { "cntrl"	       },  /* #03 */
+	    /*exp*/ { 0,0,0,	       },
+	  },
+	  { /*inp*/ { "digit"	       },  /* #04 */
+	    /*exp*/ { 0,0,0,	       },
+	  },
+	  { /*inp*/ { "graph"	       },  /* #05 */
+	    /*exp*/ { 0,0,0,	       },
+	  },
+	  { /*inp*/ { "lower"	       },  /* #06 */
+	    /*exp*/ { 0,0,0,	       },
+	  },
+	  { /*inp*/ { "print"	       },  /* #07 */
+	    /*exp*/ { 0,0,0,	       },
+	  },
+	  { /*inp*/ { "punct"	       },  /* #08 */
+	    /*exp*/ { 0,0,0,	       },
+	  },
+	  { /*inp*/ { "space"	       },  /* #09 */
+	    /*exp*/ { 0,0,0,	       },
+	  },
+	  { /*inp*/ { "upper"	       },  /* #10 */
+	    /*exp*/ { 0,0,0,	       },
+	  },
+	  { /*inp*/ { "xdigit"	       },  /* #11 */
+	    /*exp*/ { 0,0,0,	       },
+	  },
+	  { /*inp*/ { "ideogram"       },  /* #12 */
+	    /*exp*/ { 0,1,0,	       },
+	  },
+	  { /*inp*/ { "phonogram"      },  /* #13 */
+	    /*exp*/ { 0,1,0,	       },
+	  },
+	  { /*inp*/ { "jspace"	       },  /* #14 */
+	    /*exp*/ { 0,0,0,	       },
+	  },
+	  { /*inp*/ { "jhira"	       },  /* #15 */
+	    /*exp*/ { 0,0,0,	       },
+	  },
+	  { /*inp*/ { "jkata"	       },  /* #16 */
+	    /*exp*/ { 0,0,0,	       },
+	  },
+	  { /*inp*/ { "jkanji"	       },  /* #17 */
+	    /*exp*/ { 0,0,0,	       },
+	  },
+	  { /*inp*/ { "jdigit"	       },  /* #18 */
+	    /*exp*/ { 0,0,0,	       },
+	  },
+	  { .is_last = 1 }
+	}
+    },
+    {	{ Twctype, TST_LOC_end }}
+};
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wcwidth.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wcwidth.c
new file mode 100644
index 00000000..b6b7c297
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/dat_wcwidth.c
@@ -0,0 +1,149 @@
+/*
+ *  TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY
+ *
+ *	 FILE:	dat_wcwidth.c
+ *
+ *	 WCWIDTH:  int wcwidth (wchar_t wc);
+ */
+
+TST_WCWIDTH tst_wcwidth_loc [] = {
+    {
+      { Twcwidth, TST_LOC_de },
+      {
+	{ /*inp*/ { 0x0000		     },	 /* #01 */
+	  /*exp*/ { 0,	1,0,	     },
+	},
+	{ /*inp*/ { 0x0020		     },	 /* #02 */
+	  /*exp*/ { 0,	1,1,	     },
+	},
+	{ /*inp*/ { 0x007F		     },	 /* #03 */
+	  /*exp*/ { 0,	1,-1,	     },
+	},
+	{ /*inp*/ { 0x0080		     },	 /* #04 */
+	  /*exp*/ { 0,	1,-1,	     },
+	},
+	{ /*inp*/ { 0x00A1		     },	 /* #05 */
+	  /*exp*/ { 0,	1,1,	     },
+	},
+	{ /*inp*/ { 0x00C1		     },	 /* #06 */
+	  /*exp*/ { 0,	1,1,	     },
+	},
+#ifdef SHOJI_IS_RIGHT
+	/*  */	/* CHECK : wint_t */
+	{ /*inp*/ { 0x3041		     },	 /* #07 */
+	  /*exp*/ { 0,	1,0,	     },
+	},
+#else
+	{ /*inp*/ { 0x3041		     },	 /* #07 */
+	  /*exp*/ { 0,	1,EOF,	     },
+	},
+#endif
+	{ .is_last = 1 }
+      }
+    },
+    {
+      { Twcwidth, TST_LOC_enUS },
+      {
+	{ /*inp*/ { 0x0000		     },	 /* #01 */
+	  /*exp*/ { 0,	1,0,	     },
+	},
+	{ /*inp*/ { 0x0020		     },	 /* #02 */
+	  /*exp*/ { 0,	1,1,	     },
+	},
+	{ /*inp*/ { 0x007F		     },	 /* #03 */
+	  /*exp*/ { 0,	1,-1,	     },
+	},
+	{ /*inp*/ { 0x0080		     },	 /* #04 */
+	  /*exp*/ { 0,	1,-1,	     },
+	},
+	{ /*inp*/ { 0x00A1		     },	 /* #05 */
+	  /*exp*/ { 0,	1,-1,	     },
+	},
+	{ /*inp*/ { 0x00C1		     },	 /* #06 */
+	  /*exp*/ { 0,	1,-1,	     },
+	},
+	{ /*inp*/ { 0x3041		     },	 /* #07 */
+	  /*exp*/ { 0,	1,-1,	     },
+	},
+	{ .is_last = 1 }
+      }
+    },
+#if 0
+    {
+      { Twcwidth, TST_LOC_eucJP },
+      {
+	{ /*inp*/ { 0x0000		     },	 /* #01 */
+	  /*exp*/ { 0,	1,0,	     },
+	},
+	{ /*inp*/ { 0x0020		     },	 /* #02 */
+	  /*exp*/ { 0,	1,1,	     },
+	},
+	{ /*inp*/ { 0x007F		     },	 /* #03 */
+	  /*exp*/ { 0,	1,-1,	     },
+	},
+	{ /*inp*/ { 0x0080		     },	 /* #04 */
+	  /*exp*/ { 0,	1,-1,	     },
+	},
+#ifdef SHOJI_IS_RIGHT
+	/*  */
+	{ /*inp*/ { 0x00A1		     },	 /* #05 */
+	  /*exp*/ { 0,	1,0,	     },
+	},
+#else
+	/* XXX U00A1 is a valid character in EUC-JP.  */
+	{ /*inp*/ { 0x00A1		     },	 /* #05 */
+	  /*exp*/ { 0,	1,2,	     },
+	},
+#endif
+	/* jisx0212 */
+	{ /*inp*/ { 0x00C1		     },	 /* #06 */
+	  /*exp*/ { 0,	1,2,	     },
+	},
+	{ /*inp*/ { 0x3041		     },	 /* #07 */
+	  /*exp*/ { 0,	1,2,	     },
+	},
+	{ .is_last = 1 }
+      }
+    },
+#else
+    {
+      { Twcwidth, TST_LOC_ja_UTF8 },
+      {
+	{ /*inp*/ { 0x0000		     },	 /* #01 */
+	  /*exp*/ { 0,	1,0,	     },
+	},
+	{ /*inp*/ { 0x0020		     },	 /* #02 */
+	  /*exp*/ { 0,	1,1,	     },
+	},
+	{ /*inp*/ { 0x007F		     },	 /* #03 */
+	  /*exp*/ { 0,	1,-1,	     },
+	},
+	{ /*inp*/ { 0x0080		     },	 /* #04 */
+	  /*exp*/ { 0,	1,-1,	     },
+	},
+#ifdef SHOJI_IS_RIGHT
+	/*  */
+	{ /*inp*/ { 0x00A1		     },	 /* #05 */
+	  /*exp*/ { 0,	1,0,	     },
+	},
+#else
+	/* XXX U00A1 is a valid character in EUC-JP.UTF-8.  */
+	{ /*inp*/ { 0x00A1		     },	 /* #05 */
+	  /*exp*/ { 0,	1,1,	     },
+	},
+#endif
+	/* jisx0212 */
+	{ /*inp*/ { 0x00C1		     },	 /* #06 */
+	  /*exp*/ { 0,	1,1,	     },
+	},
+	{ /*inp*/ { 0x3041		     },	 /* #07 */
+	  /*exp*/ { 0,	1,2,	     },
+	},
+	{ .is_last = 1 }
+      }
+    },
+#endif
+    {
+      { Twcwidth, TST_LOC_end }
+    }
+};
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tgn_funcdef.h b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tgn_funcdef.h
new file mode 100644
index 00000000..ec247926
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tgn_funcdef.h
@@ -0,0 +1,160 @@
+#ifndef TGN_FUNCDEF_H
+#define TGN_FUNCDEF_H
+
+/* Unique number for each test.  */
+#define	 Tiswalnum		1
+#define	 Tiswalpha		2
+#define	 Tiswcntrl		3
+#define	 Tiswctype		4
+#define	 Tiswdigit		5
+#define	 Tiswgraph		6
+#define	 Tiswlower		7
+#define	 Tiswprint		8
+#define	 Tiswpunct		9
+#define	 Tiswspace		10
+#define	 Tiswupper		11
+#define	 Tiswxdigit		12
+#define	 Tmblen			13
+#define	 Tmbrlen		14
+#define	 Tmbrtowc		15
+#define	 Tmbsrtowcs		16
+#define	 Tmbstowcs		17
+#define	 Tmbtowc		18
+#define	 Tstrcoll		19
+#define	 Tstrfmon		20
+#define	 Tstrxfrm		21
+#define	 Tswscanf		22
+#define	 Ttowctrans		23
+#define	 Ttowlower		24
+#define	 Ttowupper		25
+#define	 Twcrtomb		26
+#define	 Twcscat		27
+#define	 Twcschr		28
+#define	 Twcscmp		29
+#define	 Twcscoll		30
+#define	 Twcscpy		31
+#define	 Twcscspn		32
+#define	 Twcslen		33
+#define	 Twcsncat		34
+#define	 Twcsncmp		35
+#define	 Twcsncpy		36
+#define	 Twcspbrk		37
+#define	 Twcsrtombs		38
+#define	 Twcsspn		39
+#define	 Twcsstr		40
+#define	 Twcstod		41
+#define	 Twcstok		42
+#define	 Twcstombs		43
+#define	 Twcswidth		44
+#define	 Twcsxfrm		45
+#define	 Twctob			46
+#define	 Twctomb		47
+#define	 Twctrans		48
+#define	 Twctype		49
+#define	 Twcwidth		50
+
+/* Name of each test.  */
+#define	 S_ISWALNUM	"iswalnum"
+#define	 S_ISWALPHA	"iswalpha"
+#define	 S_ISWCNTRL	"iswcntrl"
+#define	 S_ISWCTYPE	"iswctype"
+#define	 S_ISWDIGIT	"iswdigit"
+#define	 S_ISWGRAPH	"iswgraph"
+#define	 S_ISWLOWER	"iswlower"
+#define	 S_ISWPRINT	"iswprint"
+#define	 S_ISWPUNCT	"iswpunct"
+#define	 S_ISWSPACE	"iswspace"
+#define	 S_ISWUPPER	"iswupper"
+#define	 S_ISWXDIGIT	"iswxdigit"
+#define	 S_MBLEN	"mblen"
+#define	 S_MBRLEN	"mbrlen"
+#define	 S_MBRTOWC	"mbrtowc"
+#define	 S_MBSRTOWCS	"mbsrtowcs"
+#define	 S_MBSTOWCS	"mbstowcs"
+#define	 S_MBTOWC	"mbtowc"
+#define	 S_STRCOLL	"strcoll"
+#define	 S_STRFMON	"strfmon"
+#define	 S_STRXFRM	"strxfrm"
+#define	 S_SWSCANF	"swscanf"
+#define	 S_TOWCTRANS	"towctrans"
+#define	 S_TOWLOWER	"towlower"
+#define	 S_TOWUPPER	"towupper"
+#define	 S_WCRTOMB	"wcrtomb"
+#define	 S_WCSCAT	"wcscat"
+#define	 S_WCSCHR	"wcschr"
+#define	 S_WCSCMP	"wcscmp"
+#define	 S_WCSCOLL	"wcscoll"
+#define	 S_WCSCPY	"wcscpy"
+#define	 S_WCSCSPN	"wcscspn"
+#define	 S_WCSLEN	"wcslen"
+#define	 S_WCSNCAT	"wcsncat"
+#define	 S_WCSNCMP	"wcsncmp"
+#define	 S_WCSNCPY	"wcsncpy"
+#define	 S_WCSPBRK	"wcspbrk"
+#define	 S_WCSRTOMBS	"wcsrtombs"
+#define	 S_WCSSPN	"wcsspn"
+#define	 S_WCSSTR	"wcsstr"
+#define	 S_WCSTOD	"wcstod"
+#define	 S_WCSTOK	"wcstok"
+#define	 S_WCSTOMBS	"wcstombs"
+#define	 S_WCSWIDTH	"wcswidth"
+#define	 S_WCSXFRM	"wcsxfrm"
+#define	 S_WCTOB	"wctob"
+#define	 S_WCTOMB	"wctomb"
+#define	 S_WCTRANS	"wctrans"
+#define	 S_WCTYPE	"wctype"
+#define	 S_WCWIDTH	"wcwidth"
+
+/* Prototypes for test functions.  */
+extern int tst_iswalnum (FILE *, int);
+extern int tst_iswalpha (FILE *, int);
+extern int tst_iswcntrl (FILE *, int);
+extern int tst_iswctype (FILE *, int);
+extern int tst_iswdigit (FILE *, int);
+extern int tst_iswgraph (FILE *, int);
+extern int tst_iswlower (FILE *, int);
+extern int tst_iswprint (FILE *, int);
+extern int tst_iswpunct (FILE *, int);
+extern int tst_iswspace (FILE *, int);
+extern int tst_iswupper (FILE *, int);
+extern int tst_iswxdigit (FILE *, int);
+extern int tst_mblen (FILE *, int);
+extern int tst_mbrlen (FILE *, int);
+extern int tst_mbrtowc (FILE *, int);
+extern int tst_mbsrtowcs (FILE *, int);
+extern int tst_mbstowcs (FILE *, int);
+extern int tst_mbtowc (FILE *, int);
+extern int tst_strcoll (FILE *, int);
+extern int tst_strfmon (FILE *, int);
+extern int tst_strxfrm (FILE *, int);
+extern int tst_swscanf (FILE *, int);
+extern int tst_towctrans (FILE *, int);
+extern int tst_towlower (FILE *, int);
+extern int tst_towupper (FILE *, int);
+extern int tst_wcrtomb (FILE *, int);
+extern int tst_wcscat (FILE *, int);
+extern int tst_wcschr (FILE *, int);
+extern int tst_wcscmp (FILE *, int);
+extern int tst_wcscoll (FILE *, int);
+extern int tst_wcscpy (FILE *, int);
+extern int tst_wcscspn (FILE *, int);
+extern int tst_wcslen (FILE *, int);
+extern int tst_wcsncat (FILE *, int);
+extern int tst_wcsncmp (FILE *, int);
+extern int tst_wcsncpy (FILE *, int);
+extern int tst_wcspbrk (FILE *, int);
+extern int tst_wcsrtombs (FILE *, int);
+extern int tst_wcsspn (FILE *, int);
+extern int tst_wcsstr (FILE *, int);
+extern int tst_wcstod (FILE *, int);
+extern int tst_wcstok (FILE *, int);
+extern int tst_wcstombs (FILE *, int);
+extern int tst_wcswidth (FILE *, int);
+extern int tst_wcsxfrm (FILE *, int);
+extern int tst_wctob (FILE *, int);
+extern int tst_wctomb (FILE *, int);
+extern int tst_wctrans (FILE *, int);
+extern int tst_wctype (FILE *, int);
+extern int tst_wcwidth (FILE *, int);
+
+#endif /* TGN_FUNCDEF_H */
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tgn_locdef.h b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tgn_locdef.h
new file mode 100644
index 00000000..89146a71
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tgn_locdef.h
@@ -0,0 +1,32 @@
+#ifndef TGN_LOCDEF_H
+#define TGN_LOCDEF_H
+
+/* Defines for all locales used in the suite.  */
+
+/* POSIX C locale.  */
+#define TST_LOC_C	"C"
+
+/* German locale with ISO-8859-1.  */
+#define TST_LOC_de	"de_DE.ISO-8859-1"
+
+/* For US we use ANSI_X3.4-1968 (ASCII). Changed in en_US.ISO-8859-1  */
+#define TST_LOC_en	"en_US.ISO-8859-1"
+#define TST_LOC_enUS	TST_LOC_C
+
+/* NOTE: ja_JP.EUC-JP locale isn't supported into the uClibc!
+         UTF-8 is the only multibyte codeset supported. */
+/* Japanese locale with EUC-JP. */
+#if 0
+#define TST_LOC_eucJP	"ja_JP.EUC-JP"
+#endif
+
+/* Japanese locale with UTF-8. */
+#define TST_LOC_ja_UTF8	"ja_JP.UTF-8"
+
+/* German locale with UTF-8.  */
+#define TST_LOC_de_UTF8	"de_DE.UTF-8"
+
+/* End marker - must appear in each table as last entry.  */
+#define	TST_LOC_end	"lastEntry"
+
+#endif /* TGN_LOCDEF_H */
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tsp_common.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tsp_common.c
new file mode 100644
index 00000000..cd88274c
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tsp_common.c
@@ -0,0 +1,64 @@
+/*
+ *  TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY
+ *  Main driver
+ */
+
+
+#define TST_FUNCTION_CALL(func) _TST_FUNCTION_CALL(func)
+#define _TST_FUNCTION_CALL(func) tst ##_## func
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "tst_types.h"
+#include "tgn_locdef.h"
+
+
+int
+main (int argc, char *argv[])
+{
+  int ret;
+  int debug;
+
+  debug = argc > 1 ? atoi (argv[1]) : 0;
+
+  if (debug)
+    {
+      fprintf (stdout, "\nTST_MBWC ===> %s ...\n", argv[0]);
+    }
+  ret = TST_FUNCTION_CALL (TST_FUNCTION) (stdout, debug);
+
+  return (ret != 0);
+}
+
+#define	 MAX_RESULT_REC	 132
+char result_rec[MAX_RESULT_REC];
+
+
+int
+result (FILE * fp, char res, const char *func, const char *loc, int rec_no,
+	int seq_no, int case_no, const char *msg)
+{
+  if (fp == NULL
+      || strlen (func) + strlen (loc) + strlen (msg) + 32 > MAX_RESULT_REC)
+    {
+      fprintf (stderr,
+	       "Warning: result(): can't write the result: %s:%s:%d:%d:%s\n",
+	       func, loc, rec_no, case_no, msg);
+      return 0;
+    }
+
+  sprintf (result_rec, "%s:%s:%d:%d:%d:%c:%s\n", func, loc, rec_no, seq_no,
+	   case_no, res, msg);
+
+  if (fputs (result_rec, fp) == EOF)
+    {
+      return 0;
+    }
+
+  return 1;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst2_mbrtowc.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst2_mbrtowc.c
new file mode 100644
index 00000000..92e12838
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst2_mbrtowc.c
@@ -0,0 +1,21 @@
+#include 
+#include 
+#include 
+
+/* bugs.uclibc.org/1471 : make sure output is 0  */
+static int
+do_test(void)
+{
+  wchar_t output;
+  int result;
+
+  output = L'A';		/* anything other than 0 will do... */
+  result = mbrtowc (&output, "", 1, 0);
+
+  assert (result == 0);
+  assert (output == 0);
+
+  return EXIT_SUCCESS;
+}
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_funcs.h b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_funcs.h
new file mode 100644
index 00000000..4bd0fb1a
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_funcs.h
@@ -0,0 +1,296 @@
+/*
+ *  TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY
+ *
+ *	 FILE:	tst_funcs.h
+ *
+ *	 Definitions of macros
+ */
+
+
+#ifndef TST_FUNCS_H
+#define TST_FUNCS_H
+
+#define C_SUCCESS	   'S'	/* test case test passed		 */
+#define C_FAILURE	   'F'	/* test case failed			 */
+#define C_IGNORED	   'I'	/* test case/result ignored (not tested) */
+#define C_INVALID	   'D'	/* test data may be wrong		 */
+#define C_LOCALES	   'L'	/* can't set locale (skip)		 */
+
+
+extern int result (FILE * fp, char res, const char *func, const char *loc,
+		   int rec_no, int seq_num, int case_no, const char *msg);
+
+#define Result(C, S, E, M) \
+  result (fp, (C), (S), locale, rec+1, seq_num+1, (E), (M))
+
+#define CASE_0	  0
+#define CASE_1	  1
+#define CASE_2	  2
+#define CASE_3	  3
+#define CASE_4	  4
+#define CASE_5	  5
+#define CASE_6	  6
+#define CASE_7	  7
+#define CASE_8	  8
+#define CASE_9	  9
+
+#define MS_PASSED "PASSED"
+#define MS_SPACE  "	 "
+#define MS_FAILED "	 "
+#define MS_NOTEST "NOTEST"
+#define MS_ABORTU "ABEND0"
+#define MS_ABORT  "ABEND1"
+
+#define MK_PASSED 0x00
+#define MK_SPACE  0x01
+#define MK_NOTEST 0x02
+#define MK_ABORTU 0x04
+#define MK_ABORT  0x08
+
+
+
+/* ------------------ COMMON MACROS ------------------ */
+
+#define TST_ABS(x)  (((x) > 0) ? (x) : -(x))
+
+#define TMD_ERRET(_type_)   int	  err_val; \
+			    int	  ret_flg; \
+			    _type_ ret_val
+
+#define TMD_RECHEAD(_FUNC_)				      \
+									 \
+			      typedef struct {				 \
+				  TIN_##_FUNC_##_REC  input;		 \
+				  TEX_##_FUNC_##_REC  expect;		 \
+				  int is_last;				 \
+			      }	  TST_##_FUNC_##_REC;			 \
+			      typedef struct {				 \
+				  TST_HEAD	      hd;		 \
+				  TST_##_FUNC_##_REC  rec[ MAX_LOC_TEST ]; \
+			      }	  TST_##_FUNC_
+
+#define TST_FTYP(func)		tst_##func##_loc
+#define TST_HEAD(func)		tst_##func##_loc[ loc ].hd
+#define TST_INPUT(func)		tst_##func##_loc[ loc ].rec[ rec ].input
+#define TST_EXPECT(func)	tst_##func##_loc[ loc ].rec[ rec ].expect
+#define TST_INPUT_SEQ(func) \
+	tst_##func##_loc[ loc ].rec[ rec ].input.seq[ seq_num ]
+#define TST_EXPECT_SEQ(func) \
+	tst_##func##_loc[ loc ].rec[ rec ].expect.seq[ seq_num ]
+#define TST_IS_LAST(func) \
+	tst_##func##_loc[ loc ].rec[ rec ].is_last
+
+
+#define TST_DECL_VARS(_type_)				\
+	int   loc, rec, err_count = 0;			\
+	int   warn_count __attribute__ ((unused));	\
+	int   func_id, seq_num = 0;			\
+	const char *locale;				\
+	int   err_exp, ret_flg;				\
+	int errno_save = 0;				\
+	_type_ ret_exp;					\
+	_type_ ret
+
+#define TST_DO_TEST(o_func) \
+	for (loc = 0; strcmp (TST_HEAD (o_func).locale, TST_LOC_end); ++loc)
+
+
+#ifdef __UCLIBC_HAS_LOCALE__
+#define TST_HEAD_LOCALE(ofunc, s_func) \
+  func_id = TST_HEAD (ofunc).func_id;					      \
+  locale  = TST_HEAD (ofunc).locale;					      \
+  if (setlocale (LC_ALL, locale) == NULL)				      \
+    {									      \
+      fprintf (stderr, "Warning : can't set locale: %s\nskipping ...\n",      \
+	       locale);							      \
+      result (fp, C_LOCALES, s_func, locale, 0, 0, 0, "can't set locale");    \
+      ++err_count;							      \
+      continue;								      \
+    }
+#else
+#define TST_HEAD_LOCALE(ofunc, s_func)					\
+  func_id = TST_HEAD (ofunc).func_id;					\
+  locale  = TST_HEAD (ofunc).locale;					\
+  if (strcmp(locale, "C") == 0)					\
+	{								\
+	if (setlocale (LC_ALL, locale) == NULL)						\
+		{									\
+		fprintf (stderr, "Warning : can't set locale: %s\nskipping ...\n",	\
+			locale);							\
+		result (fp, C_LOCALES, s_func, locale, 0, 0, 0, "can't set locale");	\
+		++err_count;						\
+		continue;						\
+		}							\
+	}								\
+  else									\
+  	{								\
+		fprintf (stderr, "Warning : locale %s unsupported\n\n",		\
+			locale);						\
+		result (fp, C_LOCALES, s_func, locale, 0, 0, 0, "unsupported");	\
+		continue;						      	\
+	}
+#endif
+
+#define TST_DO_REC(ofunc) \
+	for (rec=0; !TST_IS_LAST (ofunc); ++rec)
+
+#define TST_DO_SEQ(_count_) \
+	for (seq_num=0; seq_num < _count_; seq_num++)
+
+#define TST_GET_ERRET(_ofunc_)			\
+	err_exp = TST_EXPECT (_ofunc_).err_val; \
+	ret_flg = TST_EXPECT (_ofunc_).ret_flg; \
+	ret_exp = TST_EXPECT (_ofunc_).ret_val
+
+#define TST_GET_ERRET_SEQ(_ofunc_)		    \
+	err_exp = TST_EXPECT_SEQ (_ofunc_).err_val; \
+	ret_flg = TST_EXPECT_SEQ (_ofunc_).ret_flg; \
+	ret_exp = TST_EXPECT_SEQ (_ofunc_).ret_val
+
+#define TST_CLEAR_ERRNO \
+	errno = 0
+
+#define TST_SAVE_ERRNO \
+	errno_save = errno
+
+/* Test value of ret and of errno if it should have a value.  */
+#define TST_IF_RETURN(_s_func_) \
+  if (err_exp != 0)							      \
+    {									      \
+      if (errno_save == err_exp)					      \
+	{								      \
+	  result (fp, C_SUCCESS, _s_func_, locale, rec+1, seq_num+1, 1,	      \
+		  MS_PASSED);						      \
+	}								      \
+      else								      \
+	{								      \
+	  err_count++;							      \
+	  result (fp, C_FAILURE, _s_func_, locale, rec+1, seq_num+1, 1,	      \
+		  "the value of errno is different from an expected value");  \
+	}								      \
+    }									      \
+									      \
+  if (ret_flg == 1)							      \
+    {									      \
+      if (ret == ret_exp)						      \
+	{								      \
+	  result (fp, C_SUCCESS, _s_func_, locale, rec+1, seq_num+1, 2,	      \
+		  MS_PASSED);						      \
+	}								      \
+      else								      \
+	{								      \
+	  err_count++;							      \
+	  result (fp, C_FAILURE, _s_func_, locale, rec+1, seq_num+1, 2,	      \
+		  "the return value is different from an expected value");    \
+	}								      \
+    }									      \
+  else
+
+#define TEX_ERRET_REC(_type_)			\
+	struct {				\
+	    TMD_ERRET (_type_);			\
+	}
+
+#define TEX_ERRET_REC_SEQ(_type_, _count_)	\
+	struct {				\
+	    struct {				\
+		TMD_ERRET (_type_);		\
+	    } seq[ _count_ ];			\
+	}
+
+
+
+/* ------------------ FUNCTION: ISW*() ------------------- */
+
+#define TST_ISW_STRUCT(_FUNC_, _func_)			\
+	typedef						\
+	struct {					\
+	    wint_t   wc;				\
+	} TIN_ISW##_FUNC_##_REC;			\
+	typedef						\
+	TEX_ERRET_REC (int)   TEX_ISW##_FUNC_##_REC;	\
+	TMD_RECHEAD (ISW##_FUNC_)
+
+#define TST_FUNC_ISW(_FUNC_, _func_) \
+int									      \
+tst_isw##_func_ (FILE *fp, int debug_flg)				      \
+{									      \
+  TST_DECL_VARS(int);							      \
+  wint_t wc;								      \
+  TST_DO_TEST (isw##_func_)						      \
+    {									      \
+      TST_HEAD_LOCALE (isw##_func_, S_ISW##_FUNC_);			      \
+      TST_DO_REC(isw##_func_)						      \
+	{								      \
+	  TST_GET_ERRET (isw##_func_);					      \
+	  wc = TST_INPUT (isw##_func_).wc;				      \
+	  ret = isw##_func_ (wc);					      \
+	  if (debug_flg)						      \
+	    {								      \
+	      fprintf (stdout, "isw*() [ %s : %d ] ret = %d\n", locale,	      \
+		       rec+1, ret);					      \
+	    }								      \
+									      \
+	  TST_IF_RETURN (S_ISW##_FUNC_)					      \
+	    {								      \
+	      if (ret != 0)						      \
+		{							      \
+		  result (fp, C_SUCCESS, S_ISW##_FUNC_, locale, rec+1,	      \
+			  seq_num+1, 3, MS_PASSED);			      \
+		}							      \
+	      else							      \
+		{							      \
+		  err_count++;						      \
+		  result (fp, C_FAILURE, S_ISW##_FUNC_, locale, rec+1,	      \
+			  seq_num+1, 3,					      \
+			  "the function returned 0, but should be non-zero"); \
+		}							      \
+	    }								      \
+	}								      \
+    }									      \
+									      \
+  return err_count;							      \
+}
+
+
+
+/* ------------------ FUNCTION: TOW*() ------------------ */
+
+#define TST_TOW_STRUCT(_FUNC_, _func_)			\
+	typedef						\
+	struct {					\
+	    wint_t   wc;				\
+	} TIN_TOW##_FUNC_##_REC;			\
+	typedef						\
+	TEX_ERRET_REC (wint_t)	TEX_TOW##_FUNC_##_REC;	\
+	TMD_RECHEAD (TOW##_FUNC_)
+
+#define TST_FUNC_TOW(_FUNC_, _func_)					\
+int									\
+tst_tow##_func_ (FILE *fp, int debug_flg)				\
+{									\
+  TST_DECL_VARS (wint_t);						\
+  wint_t wc;								\
+  TST_DO_TEST (tow##_func_)						\
+    {									\
+      TST_HEAD_LOCALE (tow##_func_, S_TOW##_FUNC_);			\
+      TST_DO_REC (tow##_func_)						\
+	{								\
+	  TST_GET_ERRET (tow##_func_);					\
+	  wc = TST_INPUT (tow##_func_).wc;				\
+	  ret = tow##_func_ (wc);					\
+	  if (debug_flg)						\
+	    {								\
+	      fprintf (stdout, "tow*() [ %s : %d ] ret = 0x%x\n",	\
+		       locale, rec+1, ret);				\
+	    }								\
+									\
+	  TST_IF_RETURN (S_TOW##_FUNC_) { };				\
+	}								\
+    }									\
+									\
+  return err_count;							\
+}
+
+
+#endif /* TST_FUNCS_H */
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_iswalnum.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_iswalnum.c
new file mode 100644
index 00000000..95ba863f
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_iswalnum.c
@@ -0,0 +1,10 @@
+/*
+  ISWALNUM: int iswalnum (wint_t wc)
+*/
+
+#define TST_FUNCTION iswalnum
+
+#include "tsp_common.c"
+#include "dat_iswalnum.c"
+
+TST_FUNC_ISW (ALNUM, alnum);
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_iswalpha.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_iswalpha.c
new file mode 100644
index 00000000..8eff2cc1
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_iswalpha.c
@@ -0,0 +1,10 @@
+/*
+  ISWALPHA: int iswalpha (wint_t wc);
+*/
+
+#define TST_FUNCTION iswalpha
+
+#include "tsp_common.c"
+#include "dat_iswalpha.c"
+
+TST_FUNC_ISW (ALPHA, alpha);
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_iswcntrl.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_iswcntrl.c
new file mode 100644
index 00000000..4e1baa8d
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_iswcntrl.c
@@ -0,0 +1,10 @@
+/*
+  ISWCNTRL: int iswcntrl (wint_t wc);
+*/
+
+#define TST_FUNCTION iswcntrl
+
+#include "tsp_common.c"
+#include "dat_iswcntrl.c"
+
+TST_FUNC_ISW (CNTRL, cntrl);
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_iswctype.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_iswctype.c
new file mode 100644
index 00000000..3e79e092
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_iswctype.c
@@ -0,0 +1,53 @@
+/*
+  ISWCTYPE: int iswctype (wint_t wc, wctype_t desc);
+*/
+
+#define TST_FUNCTION iswctype
+
+#include "tsp_common.c"
+#include "dat_iswctype.c"
+
+
+int
+tst_iswctype (FILE *fp, int debug_flg)
+{
+  TST_DECL_VARS (int);
+  wint_t wc;
+  const char *ts;
+
+  TST_DO_TEST (iswctype)
+    {
+      TST_HEAD_LOCALE (iswctype, S_ISWCTYPE);
+      TST_DO_REC (iswctype)
+	{
+	  TST_GET_ERRET (iswctype);
+	  wc = TST_INPUT (iswctype).wc;
+	  ts = TST_INPUT (iswctype).ts;
+	  ret = iswctype (wc, wctype (ts));
+	  TST_SAVE_ERRNO;
+	  if (debug_flg)
+	    {
+	      fprintf (stdout, "iswctype() [ %s : %d ] ret = %d\n",
+		       locale, rec+1, ret);
+	    }
+
+	  TST_IF_RETURN (S_ISWCTYPE)
+	    {
+	      if (ret != 0)
+		{
+		  result (fp, C_SUCCESS, S_ISWCTYPE, locale, rec+1,
+			  seq_num+1, 3, MS_PASSED);
+		}
+	      else
+		{
+		  err_count++;
+		  result (fp, C_FAILURE, S_ISWCTYPE, locale, rec+1,
+			  seq_num+1, 3,
+			  "the function returned 0, but should be non-zero");
+		}
+	    }
+	}
+    }
+
+  return err_count;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_iswdigit.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_iswdigit.c
new file mode 100644
index 00000000..5429ed07
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_iswdigit.c
@@ -0,0 +1,11 @@
+/*
+  ISWDIGIT: int iswdigit (wint_t wc);
+*/
+
+
+#define TST_FUNCTION iswdigit
+
+#include "tsp_common.c"
+#include "dat_iswdigit.c"
+
+TST_FUNC_ISW (DIGIT, digit);
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_iswgraph.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_iswgraph.c
new file mode 100644
index 00000000..91a70e2d
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_iswgraph.c
@@ -0,0 +1,10 @@
+/*
+  ISWGRAPH: int iswgraph (wint_t wc);
+*/
+
+#define TST_FUNCTION iswgraph
+
+#include "tsp_common.c"
+#include "dat_iswgraph.c"
+
+TST_FUNC_ISW (GRAPH, graph);
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_iswlower.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_iswlower.c
new file mode 100644
index 00000000..e0911001
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_iswlower.c
@@ -0,0 +1,10 @@
+/*
+  ISWLOWER: int iswlower (wint_t wc);
+*/
+
+#define TST_FUNCTION iswlower
+
+#include "tsp_common.c"
+#include "dat_iswlower.c"
+
+TST_FUNC_ISW (LOWER, lower);
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_iswprint.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_iswprint.c
new file mode 100644
index 00000000..8d5bde51
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_iswprint.c
@@ -0,0 +1,10 @@
+/*
+  ISWPRINT: int iswprint (wint_t wc);
+*/
+
+#define TST_FUNCTION iswprint
+
+#include "tsp_common.c"
+#include "dat_iswprint.c"
+
+TST_FUNC_ISW (PRINT, print);
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_iswpunct.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_iswpunct.c
new file mode 100644
index 00000000..4749d61e
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_iswpunct.c
@@ -0,0 +1,10 @@
+/*
+  ISWPUNCT: int iswpunct (wint_t wc);
+*/
+
+#define TST_FUNCTION iswpunct
+
+#include "tsp_common.c"
+#include "dat_iswpunct.c"
+
+TST_FUNC_ISW (PUNCT, punct);
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_iswspace.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_iswspace.c
new file mode 100644
index 00000000..6c26d5ff
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_iswspace.c
@@ -0,0 +1,10 @@
+/*
+  ISWSPACE: int iswspace (wint_t wc);
+*/
+
+#define TST_FUNCTION iswspace
+
+#include "tsp_common.c"
+#include "dat_iswspace.c"
+
+TST_FUNC_ISW (SPACE, space);
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_iswupper.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_iswupper.c
new file mode 100644
index 00000000..dfe5a5b3
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_iswupper.c
@@ -0,0 +1,10 @@
+/*
+  ISWUPPER: int iswupper (wint_t wc);
+*/
+
+#define TST_FUNCTION iswupper
+
+#include "tsp_common.c"
+#include "dat_iswupper.c"
+
+TST_FUNC_ISW (UPPER, upper);
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_iswxdigit.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_iswxdigit.c
new file mode 100644
index 00000000..5f9c0c5d
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_iswxdigit.c
@@ -0,0 +1,10 @@
+/*
+  ISWXDIGIT: int iswxdigit (wint_t wc);
+*/
+
+#define TST_FUNCTION iswxdigit
+
+#include "tsp_common.c"
+#include "dat_iswxdigit.c"
+
+TST_FUNC_ISW (XDIGIT, xdigit);
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_mblen.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_mblen.c
new file mode 100644
index 00000000..35ccf6c1
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_mblen.c
@@ -0,0 +1,85 @@
+/*
+  MBLEN: int mblen (char *s, size_t n)
+*/
+
+#define TST_FUNCTION mblen
+
+#include "tsp_common.c"
+#include "dat_mblen.c"
+
+int
+tst_mblen (FILE * fp, int debug_flg)
+{
+  TST_DECL_VARS (int);
+  char s_flg;
+  const char *s_in;
+  size_t n;
+
+  TST_DO_TEST (mblen)
+  {
+    TST_HEAD_LOCALE (mblen, S_MBLEN);
+    TST_DO_REC (mblen)
+    {
+      TST_GET_ERRET (mblen);
+      s_flg = TST_INPUT (mblen).s_flg;
+      s_in = TST_INPUT (mblen).s;
+      n = TST_INPUT (mblen).n;
+
+      if (s_flg == 0)
+	{
+	  s_in = NULL;
+	}
+
+      if (n == USE_MBCURMAX)
+	{
+	  n = MB_CUR_MAX;
+	}
+
+      TST_CLEAR_ERRNO;
+      ret = mblen (s_in, n);
+      TST_SAVE_ERRNO;
+
+      TST_IF_RETURN (S_MBLEN)
+      {
+	if (s_in == NULL)
+	  {			/* state dependency */
+	    if (ret_exp == +1)
+	      {			/* state-dependent  */
+		if (ret != 0)
+		  {
+		    /* non-zero: state-dependent encoding */
+		    Result (C_SUCCESS, S_MBLEN, CASE_3, MS_PASSED);
+		  }
+		else
+		  {
+		    err_count++;
+		    Result (C_FAILURE, S_MBLEN, CASE_3,
+			    "should be state-dependent encoding, "
+			    "but the return value shows it is"
+			    " state-independent");
+		  }
+	      }
+
+	    if (ret_exp == 0)
+	      {			/* state-independent */
+		if (ret == 0)
+		  {
+		    /* non-zero: state-dependent encoding */
+		    Result (C_SUCCESS, S_MBLEN, CASE_3, MS_PASSED);
+		  }
+		else
+		  {
+		    err_count++;
+		    Result (C_FAILURE, S_MBLEN, CASE_3,
+			    "should be state-independent encoding, "
+			    "but the return value shows it is"
+			    " state-dependent");
+		  }
+	      }
+	  }
+      }
+    }
+  }
+
+  return err_count;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_mbrlen.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_mbrlen.c
new file mode 100644
index 00000000..b8681b72
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_mbrlen.c
@@ -0,0 +1,82 @@
+/*
+  MBRLEN: size_t mbrlen (char *s, size_t n, mbstate_t *ps)
+*/
+
+#define TST_FUNCTION mbrlen
+
+#include "tsp_common.c"
+#include "dat_mbrlen.c"
+
+
+int
+tst_mbrlen (FILE * fp, int debug_flg)
+{
+  TST_DECL_VARS (size_t);
+  char s_flg;
+  const char *s_in;
+  size_t n;
+  char t_flg;
+  char t_ini;
+  static mbstate_t s = { 0 };
+  mbstate_t *ps;
+
+  TST_DO_TEST (mbrlen)
+  {
+    TST_HEAD_LOCALE (mbrlen, S_MBRLEN);
+    TST_DO_REC (mbrlen)
+    {
+      if (mbrlen (NULL, 0, &s) != 0)
+	{
+	  err_count++;
+	  Result (C_FAILURE, S_MBRLEN, CASE_3,
+		  "Initialization (external mbstate object) failed "
+		  "- skipped this test case.");
+	  continue;
+	}
+
+      TST_DO_SEQ (MBRLEN_SEQNUM)
+      {
+	TST_GET_ERRET_SEQ (mbrlen);
+	s_flg = TST_INPUT_SEQ (mbrlen).s_flg;
+	s_in = TST_INPUT_SEQ (mbrlen).s;
+	n = TST_INPUT_SEQ (mbrlen).n;
+	t_flg = TST_INPUT_SEQ (mbrlen).t_flg;
+	t_ini = TST_INPUT_SEQ (mbrlen).t_init;
+	if (s_flg == 0)
+	  {
+	    s_in = NULL;
+	  }
+
+	if (n == USE_MBCURMAX)	/* rewrite tst_mblen() like this */
+	  {
+	    n = MB_CUR_MAX;
+	  }
+
+	ps = (t_flg == 0) ? NULL : &s;
+
+	if (t_ini != 0)
+	  {
+	    memset (&s, 0, sizeof (s));
+	    mbrlen (NULL, 0, NULL);
+	  }
+
+	TST_CLEAR_ERRNO;
+	ret = mbrlen (s_in, n, ps);
+	TST_SAVE_ERRNO;
+
+	if (debug_flg)
+	  {
+	    fprintf (stdout, "mbrlen() [ %s : %d : %d ] ret = %zd\n",
+		     locale, rec + 1, seq_num + 1, ret);
+	    fprintf (stdout, "			   errno = %d\n", errno_save);
+	  }
+
+	TST_IF_RETURN (S_MBRLEN)
+	{
+	};
+      }
+    }
+  }
+
+  return err_count;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_mbrtowc.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_mbrtowc.c
new file mode 100644
index 00000000..3a6070a8
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_mbrtowc.c
@@ -0,0 +1,103 @@
+/*
+  MBRTOWC: size_t mbrtowc (wchar_t *pwc, const char *s, size_t n,
+			   mbstate_t *ps)
+*/
+
+#define TST_FUNCTION mbrtowc
+
+#include "tsp_common.c"
+#include "dat_mbrtowc.c"
+
+
+int
+tst_mbrtowc (FILE * fp, int debug_flg)
+{
+  TST_DECL_VARS (size_t);
+  char w_flg, s_flg;
+  char *s;
+  size_t n;
+  char t_flg, t_ini;
+  static mbstate_t t = { 0 };
+  mbstate_t *pt;
+  wchar_t wc, *pwc, wc_ex;
+
+  TST_DO_TEST (mbrtowc)
+  {
+    TST_HEAD_LOCALE (mbrtowc, S_MBRTOWC);
+    TST_DO_REC (mbrtowc)
+    {
+      if (mbrtowc (NULL, "", 0, &t) != 0)
+	{
+	  err_count++;
+	  Result (C_FAILURE, S_MBRTOWC, CASE_3,
+		  "Initialization failed - skipping this test case.");
+	  continue;
+	}
+
+      TST_DO_SEQ (MBRTOWC_SEQNUM)
+      {
+	TST_GET_ERRET_SEQ (mbrtowc);
+	w_flg = TST_INPUT_SEQ (mbrtowc).w_flg;
+	s_flg = TST_INPUT_SEQ (mbrtowc).s_flg;
+	s = TST_INPUT_SEQ (mbrtowc).s;
+	n = TST_INPUT_SEQ (mbrtowc).n;
+	t_flg = TST_INPUT_SEQ (mbrtowc).t_flg;
+	t_ini = TST_INPUT_SEQ (mbrtowc).t_init;
+	pwc = (w_flg == 0) ? NULL : &wc;
+
+	if (s_flg == 0)
+	  {
+	    s = NULL;
+	  }
+
+	if (n == USE_MBCURMAX)
+	  {
+	    n = MB_CUR_MAX;
+	  }
+
+	pt = (t_flg == 0) ? NULL : &t;
+#if 0
+	if (t_ini != 0)
+	  {
+	    memset (&t, 0, sizeof (t));
+	  }
+#endif
+	TST_CLEAR_ERRNO;
+	ret = mbrtowc (pwc, s, n, pt);
+	TST_SAVE_ERRNO;
+
+	if (debug_flg)
+	  {
+	    fprintf (stdout, "mbrtowc() [ %s : %d : %d ] ret = %zd\n",
+		     locale, rec + 1, seq_num + 1, ret);
+	    fprintf (stdout, "			    errno = %hd\n",
+		     errno_save);
+	  }
+
+	TST_IF_RETURN (S_MBRTOWC)
+	{
+	};
+
+	if (pwc == NULL || s == NULL || ret == (size_t) - 1
+	    || ret == (size_t) - 2)
+	  {
+	    continue;
+	  }
+
+	wc_ex = TST_EXPECT_SEQ (mbrtowc).wc;
+	if (wc_ex == wc)
+	  {
+	    Result (C_SUCCESS, S_MBRTOWC, CASE_4, MS_PASSED);
+	  }
+	else
+	  {
+	    err_count++;
+	    Result (C_FAILURE, S_MBRTOWC, CASE_4,
+		    "converted wc is different from an expected wc");
+	  }
+      }
+    }
+  }
+
+  return err_count;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_mbsrtowcs.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_mbsrtowcs.c
new file mode 100644
index 00000000..3f3ea716
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_mbsrtowcs.c
@@ -0,0 +1,109 @@
+/*
+  MBSRTOWCS: size_t mbsrtowcs (wchar_t *ws, const char **s, size_t n,
+			       mbstate_t *ps)
+*/
+
+#define TST_FUNCTION mbsrtowcs
+
+#include "tsp_common.c"
+#include "dat_mbsrtowcs.c"
+
+int
+tst_mbsrtowcs (FILE * fp, int debug_flg)
+{
+  TST_DECL_VARS (size_t);
+  char w_flg;
+  const char *s, *p;
+  size_t n;
+  char t_flg, t_ini;
+  static mbstate_t t = { 0 };
+  mbstate_t *pt;
+  wchar_t ws[WCSSIZE], *ws_ex, *wp;
+  int err, i;
+
+  TST_DO_TEST (mbsrtowcs)
+  {
+    TST_HEAD_LOCALE (mbsrtowcs, S_MBSRTOWCS);
+    TST_DO_REC (mbsrtowcs)
+    {
+      s = "";
+      if (mbsrtowcs (NULL, &s, 0, &t) != 0)
+	{
+	  err_count++;
+	  Result (C_FAILURE, S_MBSRTOWCS, CASE_3,
+		  "Initialization failed - skipping this test case.");
+	  continue;
+	}
+
+      TST_DO_SEQ (MBSRTOWCS_SEQNUM)
+      {
+	TST_GET_ERRET_SEQ (mbsrtowcs);
+	w_flg = TST_INPUT_SEQ (mbsrtowcs).w_flg;
+	p = s = TST_INPUT_SEQ (mbsrtowcs).s;
+	n = TST_INPUT_SEQ (mbsrtowcs).n;
+	t_flg = TST_INPUT_SEQ (mbsrtowcs).t_flg;
+	t_ini = TST_INPUT_SEQ (mbsrtowcs).t_init;
+	wp = (w_flg == 0) ? NULL : ws;
+
+	if (n == USE_MBCURMAX)
+	  {
+	    n = MB_CUR_MAX;
+	  }
+
+	pt = (t_flg == 0) ? NULL : &t;
+
+	if (t_ini != 0)
+	  {
+	    memset (&t, 0, sizeof (t));
+	  }
+
+	TST_CLEAR_ERRNO;
+	ret = mbsrtowcs (wp, &p, n, pt);
+	TST_SAVE_ERRNO;
+
+	if (debug_flg)
+	  {
+	    fprintf (stderr, "mbsrtowcs: [ %d ] : ret = %zd\n", rec + 1, ret);
+	  }
+
+	TST_IF_RETURN (S_MBSRTOWCS)
+	{
+	};
+
+	if (wp == NULL || ret == (size_t) - 1 || ret == (size_t) - 2)
+	  {
+	    continue;
+	  }
+
+	ws_ex = TST_EXPECT_SEQ (mbsrtowcs).ws;
+	for (err = 0, i = 0; i < ret; i++)
+	  {
+	    if (debug_flg)
+	      {
+		fprintf (stderr,
+			 "mbsrtowcs: ws[%d] => 0x%lx : 0x%lx <= ws_ex[%d]\n",
+			 i, (unsigned long int) ws[i],
+			 (unsigned long int) ws_ex[i], i);
+	      }
+
+	    if (ws[i] != ws_ex[i])
+	      {
+		err++;
+		err_count++;
+		Result (C_FAILURE, S_MBSRTOWCS, CASE_4,
+			"the converted wc string has "
+			"different value from an expected string");
+		break;
+	      }
+	  }
+
+	if (!err)
+	  {
+	    Result (C_SUCCESS, S_MBSRTOWCS, CASE_4, MS_PASSED);
+	  }
+      }
+    }
+  }
+
+  return err_count;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_mbstowcs.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_mbstowcs.c
new file mode 100644
index 00000000..878df6a9
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_mbstowcs.c
@@ -0,0 +1,98 @@
+/*
+  MBSTOWCS: size_t mbstowcs (wchar_t *ws, char *s, size_t n)
+*/
+
+#define TST_FUNCTION mbstowcs
+
+#include "tsp_common.c"
+#include "dat_mbstowcs.c"
+
+int
+tst_mbstowcs (FILE * fp, int debug_flg)
+{
+  TST_DECL_VARS (size_t);
+  char w_flg, s_flg;
+  const char *s;
+  size_t n;
+  wchar_t ws[WCSSIZE], *ws_ex, *wp;
+  int err, i;
+
+  TST_DO_TEST (mbstowcs)
+  {
+    TST_HEAD_LOCALE (mbstowcs, S_MBSTOWCS);
+    TST_DO_REC (mbstowcs)
+    {
+      if (mbstowcs (NULL, "", 0) != 0)
+	{
+	  err_count++;
+	  Result (C_FAILURE, S_MBSTOWCS, CASE_3,
+		  "Initialization failed - skipping this test case.");
+	  continue;
+	}
+
+      TST_DO_SEQ (MBSTOWCS_SEQNUM)
+      {
+	TST_GET_ERRET_SEQ (mbstowcs);
+	w_flg = TST_INPUT_SEQ (mbstowcs).w_flg;
+	s_flg = TST_INPUT_SEQ (mbstowcs).s_flg;
+	n = TST_INPUT_SEQ (mbstowcs).n;
+
+	if (s_flg == 0)
+	  s = NULL;
+	else
+	  s = TST_INPUT_SEQ (mbstowcs).s;
+
+
+	wp = (wchar_t *) ((w_flg == 0) ? NULL : ws);
+
+	TST_CLEAR_ERRNO;
+	ret = mbstowcs (wp, s, n);
+	TST_SAVE_ERRNO;
+
+	if (debug_flg)
+	  {
+	    fprintf (stderr, "mbstowcs: ret = %zd\n", ret);
+	  }
+
+	TST_IF_RETURN (S_MBSTOWCS)
+	{
+	};
+
+	if (s == NULL || wp == NULL || ret == (size_t) - 1)
+	  {
+	    continue;
+	  }
+
+	ws_ex = TST_EXPECT_SEQ (mbstowcs).ws;
+
+	for (err = 0, i = 0; i < ret; i++)
+	  {
+	    if (debug_flg)
+	      {
+		fprintf (stderr,
+			 "mbstowcs: ws[%d] => 0x%lx : 0x%lx <= ws_ex[%d]\n",
+			 i, (unsigned long int) ws[i],
+			 (unsigned long int) ws_ex[i], i);
+	      }
+
+	    if (ws[i] != ws_ex[i])
+	      {
+		err++;
+		err_count++;
+		Result (C_FAILURE, S_MBSTOWCS, CASE_4,
+			"the converted wc string has "
+			"different value from an expected string");
+		break;
+	      }
+	  }
+
+	if (!err)
+	  {
+	    Result (C_SUCCESS, S_MBSTOWCS, CASE_4, MS_PASSED);
+	  }
+      }
+    }
+  }
+
+  return err_count;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_mbtowc.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_mbtowc.c
new file mode 100644
index 00000000..7c274f66
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_mbtowc.c
@@ -0,0 +1,130 @@
+/*
+  MBTOWC: int mbtowc (wchar_t *wc, char *s, size_t n)
+*/
+
+#define TST_FUNCTION mbtowc
+
+#include "tsp_common.c"
+#include "dat_mbtowc.c"
+
+
+int
+tst_mbtowc (FILE * fp, int debug_flg)
+{
+  TST_DECL_VARS (int);
+  char w_flg, s_flg;
+  const char *s_in;
+  size_t n;
+  wchar_t wc, wc_ex, *wp;
+
+  TST_DO_TEST (mbtowc)
+  {
+    TST_HEAD_LOCALE (mbtowc, S_MBTOWC);
+    TST_DO_REC (mbtowc)
+    {
+      if (mbstowcs (NULL, "", 0) != 0)
+	{
+	  err_count++;
+	  Result (C_FAILURE, S_MBSTOWCS, CASE_3,
+		  "Initialization failed - skipping this test case.");
+	  continue;
+	}
+
+      TST_DO_SEQ (MBTOWC_SEQNUM)
+      {
+	TST_GET_ERRET_SEQ (mbtowc);
+	w_flg = TST_INPUT_SEQ (mbtowc).w_flg;
+	s_flg = TST_INPUT_SEQ (mbtowc).s_flg;
+	n = TST_INPUT_SEQ (mbtowc).n;
+
+	if (n == USE_MBCURMAX)
+	  {
+	    n = MB_CUR_MAX;
+	  }
+
+	if (s_flg == 0)
+	  s_in = NULL;
+	else
+	  s_in = TST_INPUT_SEQ (mbtowc).s;
+
+	wp = (wchar_t *) ((w_flg == 0) ? NULL : &wc);
+
+	/* XXX Clear the internal state.  We should probably have
+	   a flag for this.  */
+	mbtowc (NULL, NULL, 0);
+
+	TST_CLEAR_ERRNO;
+	ret = mbtowc (wp, s_in, n);
+	TST_SAVE_ERRNO;
+
+	if (debug_flg)
+	  {
+	    fprintf (stdout, "mbtowc() [ %s : %d ] ret = %d\n", locale,
+		     rec + 1, ret);
+	    fprintf (stdout, "			   errno      = %d\n",
+		     errno_save);
+	  }
+
+	TST_IF_RETURN (S_MBTOWC)
+	{
+	  if (s_in == NULL)
+	    {			/* state dependency */
+	      if (ret_exp == +1)
+		{		/* state-dependent  */
+		  if (ret != 0)
+		    {
+		      /* Non-zero: state-dependent encoding.  */
+		      Result (C_SUCCESS, S_MBTOWC, CASE_3, MS_PASSED);
+		    }
+		  else
+		    {
+		      err_count++;
+		      Result (C_FAILURE, S_MBTOWC, CASE_3,
+			      "should be state-dependent encoding, "
+			      "but a return value shows it is "
+			      "state-independent");
+		    }
+		}
+
+	      if (ret_exp == 0)
+		{		/* state-independent */
+		  if (ret == 0)
+		    {
+		      /* Non-zero: state-dependent encoding.  */
+		      Result (C_SUCCESS, S_MBTOWC, CASE_3, MS_PASSED);
+		    }
+		  else
+		    {
+		      err_count++;
+		      Result (C_FAILURE, S_MBTOWC, CASE_3,
+			      "should be state-independent encoding, "
+			      "but a return value shows it is "
+			      "state-dependent");
+		    }
+		}
+	    }
+	}
+
+	if ((wp == NULL || s_in == NULL || s_in[0] == 0) || ret <= 0)
+	  {
+	    continue;
+	  }
+
+	wc_ex = TST_EXPECT_SEQ (mbtowc).wc;
+
+	if (wc_ex == wc)
+	  {
+	    Result (C_SUCCESS, S_MBTOWC, CASE_4, MS_PASSED);
+	  }
+	else
+	  {
+	    err_count++;
+	    Result (C_FAILURE, S_MBTOWC, CASE_4,
+		    "converted wc is different from an expected wc");
+	  }
+      }
+    }
+  }
+
+  return err_count;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_strcoll.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_strcoll.c
new file mode 100644
index 00000000..4c5a84f6
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_strcoll.c
@@ -0,0 +1,87 @@
+/*
+  STRCOLL: int strcoll (const char *s1, const char *s2)
+*/
+
+#define TST_FUNCTION strcoll
+
+#include "tsp_common.c"
+#include "dat_strcoll.c"
+
+int
+tst_strcoll (FILE * fp, int debug_flg)
+{
+  TST_DECL_VARS (int);
+  const char *s1, *s2;
+
+  TST_DO_TEST (strcoll)
+  {
+    TST_HEAD_LOCALE (strcoll, S_STRCOLL);
+    TST_DO_REC (strcoll)
+    {
+      TST_GET_ERRET (strcoll);
+      s1 = TST_INPUT (strcoll).s1;
+      s2 = TST_INPUT (strcoll).s2;
+
+      TST_CLEAR_ERRNO;
+      ret = strcoll (s1, s2);
+      TST_SAVE_ERRNO;
+
+      if (debug_flg)
+	{
+	  fprintf (stdout, "strcoll() [ %s : %d ] ret = %d\n", locale,
+		   rec + 1, ret);
+	  fprintf (stdout, "			    errno = %d\n",
+		   errno_save);
+	  fprintf (stdout, "			    LC_COLLATE = %s\n",
+		   (setlocale (LC_COLLATE, NULL)) ? setlocale (LC_COLLATE,
+							       NULL) : "");
+	}
+
+      TST_IF_RETURN (S_STRCOLL)
+      {
+	if (ret_exp == +1)
+	  {
+	    if (ret > 0)
+	      {
+		Result (C_SUCCESS, S_STRCOLL, CASE_3, MS_PASSED);
+	      }
+	    else
+	      {
+		err_count++;
+		Result (C_FAILURE, S_STRCOLL, CASE_3,
+			"the return value should be greater than 0,"
+			" but is not ...");
+	      }
+	  }
+	else if (ret_exp == -1)
+	  {
+	    if (ret < 0)
+	      {
+		Result (C_SUCCESS, S_STRCOLL, CASE_3, MS_PASSED);
+	      }
+	    else
+	      {
+		err_count++;
+		Result (C_FAILURE, S_STRCOLL, CASE_3,
+			"the return value should less than 0, but not ...");
+	      }
+	  }
+	else if (ret_exp != 0)
+	  {
+	    if (debug_flg)
+	      {
+		fprintf (stderr, "*** Warning *** : tst_strcoll : "
+			 "(check the test data); should set ret_flg=1"
+			 " to check a return value");
+	      }
+
+	    warn_count++;
+	    Result (C_INVALID, S_WCSCHR, CASE_3, "(check the test data); "
+		    "should set ret_flg=1 to check a return value");
+	  }
+      }
+    }
+  }
+
+  return err_count;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_strfmon.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_strfmon.c
new file mode 100644
index 00000000..88e93167
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_strfmon.c
@@ -0,0 +1,74 @@
+/*
+  STRFMON: size_t strfmon (char *buf, size_t nbyte, const char *fmt, ...)
+*/
+
+#define TST_FUNCTION strfmon
+
+#include "tsp_common.c"
+#include "dat_strfmon.c"
+#include 
+
+int
+tst_strfmon (FILE * fp, int debug_flg)
+{
+  TST_DECL_VARS (size_t);
+  char buf[MONSIZE], *mon;
+  size_t nbt;
+  char *fmt;
+  double val;
+
+  TST_DO_TEST (strfmon)
+  {
+    TST_HEAD_LOCALE (strfmon, S_STRFMON);
+    TST_DO_REC (strfmon)
+    {
+      TST_GET_ERRET (strfmon);
+      nbt = TST_INPUT (strfmon).nbytes;
+      fmt = TST_INPUT (strfmon).fmt;
+      val = TST_INPUT (strfmon).val;
+      memset (buf, 0, MONSIZE);
+      if (nbt > MONSIZE)
+	{
+	  err_count++;
+	  Result (C_FAILURE, S_STRFMON, CASE_3, "buffer too small in test");
+	  continue;
+	}
+
+      TST_CLEAR_ERRNO;
+      ret = strfmon (buf, nbt, fmt, val, val, val);
+      TST_SAVE_ERRNO;
+
+      if (debug_flg)		/* seems fprintf doesn't update the errno */
+	{
+	  fprintf (stdout, "strfmon() [ %s : %d ]\n", locale, rec + 1);
+	  fprintf (stdout, "	  : err = %d | %s\n", errno_save,
+		   strerror (errno));
+	  fprintf (stdout, "	  : ret = %zd; \t fmt = |%s|\n", ret, fmt);
+	  fprintf (stdout, "	  : buf = |%s|\n\n", buf);
+	}
+
+      TST_IF_RETURN (S_STRFMON)
+      {
+      };
+      if (errno != 0 || ret == -1)
+	{
+	  continue;
+	}
+
+      mon = TST_EXPECT (strfmon).mon;
+
+      if (!strcmp (buf, mon))
+	{
+	  Result (C_SUCCESS, S_STRFMON, CASE_3, MS_PASSED);
+	}
+      else
+	{
+	  err_count++;
+	  Result (C_FAILURE, S_STRFMON, CASE_3, "the formatted string is "
+		  "different from an expected result");
+	}
+    }
+  }
+
+  return err_count;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_strxfrm.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_strxfrm.c
new file mode 100644
index 00000000..fdfeffc8
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_strxfrm.c
@@ -0,0 +1,136 @@
+/*
+  STRXFRM: size_t strxfrm (char *s1, const char *s2, size_t n)
+*/
+
+#define TST_FUNCTION strxfrm
+
+#include "tsp_common.c"
+#include "dat_strxfrm.c"
+
+
+int
+tst_strxfrm (FILE * fp, int debug_flg)
+{
+  TST_DECL_VARS (size_t);
+  const char *org1, *org2;
+  char frm1[MBSSIZE], frm2[MBSSIZE];
+  size_t n1, n2;
+  int ret_coll, ret_cmp;
+
+  TST_DO_TEST (strxfrm)
+  {
+    TST_HEAD_LOCALE (strxfrm, S_STRXFRM);
+    TST_DO_REC (strxfrm)
+    {
+      TST_GET_ERRET (strxfrm);
+      org1 = TST_INPUT (strxfrm).org1;
+      org2 = TST_INPUT (strxfrm).org2;
+      n1 = TST_INPUT (strxfrm).n1;
+      n2 = TST_INPUT (strxfrm).n2;
+
+      if (n1 < 0 || sizeof (frm1) < n1 || sizeof (frm2) < n2)
+	{
+	  warn_count++;
+	  Result (C_IGNORED, S_STRXFRM, CASE_9,
+		  "input data n1 or n2 is invalid");
+	  continue;
+	}
+
+      /* An errno and a return value are checked
+	 only for 2nd strxfrm() call.
+	 A result of 1st call is used for comparing
+	 those 2 values by using strcmp().
+      */
+
+      /*-- First call --*/
+
+      TST_CLEAR_ERRNO;
+      ret = strxfrm (frm1, org1, n1);
+      TST_SAVE_ERRNO;
+
+      if (debug_flg)
+	{
+	  fprintf (stdout, "strxfrm() [ %s : %d ] ( 1st call )\n", locale,
+		   rec + 1);
+	  fprintf (stdout, "	  : err = %d | %s\n", errno_save,
+		   strerror (errno));
+	  fprintf (stdout, "	  : ret = %zu\n", ret);
+	  fprintf (stdout, "	  : org = %s\n", org1);
+	}
+
+      if (ret >= n1 || errno != 0)
+	{
+	  warn_count++;
+	  Result (C_INVALID, S_STRXFRM, CASE_8,
+		  "got an error in fist strxfrm() call");
+	  continue;
+	}
+
+      /*-- Second call --*/
+
+      TST_CLEAR_ERRNO;
+      ret = strxfrm (((n2 == 0) ? NULL : frm2), org2, n2);
+      TST_SAVE_ERRNO;
+
+      if (debug_flg)
+	{
+	  fprintf (stderr, "	  ..............( 2nd call )\n");
+	  fprintf (stdout, "	  : err = %d | %s\n", errno,
+		   strerror (errno));
+	  fprintf (stdout, "	  : ret = %zu\n", ret);
+	  fprintf (stdout, "	  : org = %s\n", org2);
+	}
+
+      TST_IF_RETURN (S_STRXFRM)
+      {
+      };
+
+      if (n2 == 0 || ret >= n2 || errno != 0)
+	{
+#if 0
+	  warn_count++;
+	  Result (C_IGNORED, S_STRXFRM, CASE_7, "did not get a result");
+#endif
+	  continue;
+	}
+
+      /*-- strcoll & strcmp --*/
+
+      TST_CLEAR_ERRNO;
+      /* Depends on strcoll() ... not good though ... */
+      ret_coll = strcoll (org1, org2);
+
+      if (errno != 0)
+	{
+	  /* bug * bug may get correct results ...	  */
+	  warn_count++;
+	  Result (C_INVALID, S_STRXFRM, CASE_6,
+		  "got an error in strcoll() call");
+	  continue;
+	}
+
+      ret_cmp = strcmp (frm1, frm2);
+
+      if ((ret_coll == 0 && ret_cmp == 0)
+	  || (ret_coll < 0 && ret_cmp < 0) || (ret_coll > 0 && ret_cmp > 0))
+	{
+	  Result (C_SUCCESS, S_STRXFRM, CASE_3,
+		  MS_PASSED "(depends on strcoll & strcmp)");
+	}
+      else
+	{
+	  err_count++;
+	  Result (C_FAILURE, S_STRXFRM, CASE_3,
+		  "results from strcoll & strcmp() do not match");
+	}
+
+      if (debug_flg)
+	{
+	  fprintf (stdout, ".......... strcoll = %d <-> %d = strcmp\n",
+		   ret_coll, ret_cmp);
+	}
+    }
+  }
+
+  return err_count;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_swscanf.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_swscanf.c
new file mode 100644
index 00000000..76445d75
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_swscanf.c
@@ -0,0 +1,137 @@
+/*
+  SWSCANF: int swscanf (const wchar_t *ws, const wchar_t *fmt, ...);
+*/
+
+#define TST_FUNCTION swscanf
+
+#include "tsp_common.c"
+#include "dat_swscanf.c"
+
+int
+tst_swscanf (FILE * fp, int debug_flg)
+{
+  TST_DECL_VARS (int);
+  wchar_t *ws;
+  wchar_t *fmt;
+  int val_int1;
+  unsigned val_int2;
+  float val_flt;
+  char val_c;
+  char val_s[MBSSIZE * 3];
+  wchar_t val_S[WCSSIZE * 3], *exp_S;
+  int i;
+
+  TST_DO_TEST (swscanf)
+  {
+    TST_HEAD_LOCALE (swscanf, S_SWSCANF);
+    TST_DO_REC (swscanf)
+    {
+      TST_GET_ERRET (swscanf);
+      ws = TST_INPUT (swscanf).ws;
+      fmt = TST_INPUT (swscanf).fmt;
+      val_int1 = val_int2 = val_flt = val_c = 0;
+      memset (val_s, 0, sizeof (val_s));
+      memset (val_S, 0, sizeof (val_S));
+
+      TST_CLEAR_ERRNO;
+
+      if (TST_INPUT (swscanf).wch)
+	{
+	  ret = swscanf (ws, fmt, val_S);
+	}
+      else
+	{
+	  ret =
+	    swscanf (ws, fmt, &val_int1, &val_int2, &val_flt, &val_c, val_s);
+	}
+
+      TST_SAVE_ERRNO;
+
+      if (debug_flg)
+	{			/* seems fprintf doesn't update errno */
+	  fprintf (stdout, "swscanf() [ %s : %d ] ret = %d\n", locale,
+		   rec + 1, ret);
+	  fprintf (stdout, "			    errno   = %d\n",
+		   errno_save);
+	  fprintf (stdout, "			    collate = %s\n",
+		   (setlocale (LC_COLLATE, NULL)) ? setlocale (LC_COLLATE,
+							       NULL) : "");
+
+	  if (TST_INPUT (swscanf).wch)
+	    {
+	      fprintf (stdout, "			val_S[ 0 ] = 0x%lx\n",
+		       (unsigned long int) val_S[0]);
+	    }
+	  else
+	    {
+	      fprintf (stdout, "			val_int1   = %d\n",
+		       val_int1);
+	      fprintf (stdout, "			val_int2   = %d\n",
+		       val_int2);
+	      fprintf (stdout, "			val_flt	   = %f\n",
+		       val_flt);
+	      fprintf (stdout, "			val_c	   = %c\n",
+		       val_c);
+	      fprintf (stdout, "			val_s	   = %s\n",
+		       val_s);
+	    }
+	}
+
+      TST_IF_RETURN (S_SWSCANF)
+      {
+      };
+
+      if (errno == 0 && TST_INPUT (swscanf).wch)
+	{
+	  for (exp_S = TST_EXPECT (swscanf).val_S, i = 0; i < WCSSIZE * 3;
+	       i++)
+	    {
+	      if (val_S[i] == L'\0' || exp_S[i] == L'\0')
+		{
+		  if (val_S[i] != exp_S[i] && TST_INPUT (swscanf).wch == 'C')
+		    {
+		      err_count++;
+		      Result (C_FAILURE, S_SWSCANF, CASE_4,
+			      "the converted wide-char string is different"
+			      " from an expected value.");
+		    }
+		  break;
+		}
+
+	      if (val_S[i] != exp_S[i])
+		{
+		  err_count++;
+		  Result (C_FAILURE, S_SWSCANF, CASE_4,
+			  "the converted wide-char string is different from"
+			  " an expected value.");
+		  break;
+		}
+	      else
+		{
+		  Result (C_SUCCESS, S_SWSCANF, CASE_4, MS_PASSED);
+		}
+	    }
+	}
+
+      if (errno == 0 && !TST_INPUT (swscanf).wch)
+	{
+	  if (val_int1 != TST_EXPECT (swscanf).val_int ||
+	      val_int2 != TST_EXPECT (swscanf).val_uns ||
+	      val_flt != TST_EXPECT (swscanf).val_flt ||
+	      val_c != TST_EXPECT (swscanf).val_c ||
+	      strcmp (val_s, TST_EXPECT (swscanf).val_s))
+	    {
+	      err_count++;
+	      Result (C_FAILURE, S_SWSCANF, CASE_3,
+		      "the converted values are different from expected values.");
+	    }
+	  else
+	    {
+	      Result (C_SUCCESS, S_SWSCANF, CASE_3, MS_PASSED);
+	    }
+	}
+    }
+  }
+
+  return err_count;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_towctrans.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_towctrans.c
new file mode 100644
index 00000000..1d874dc0
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_towctrans.c
@@ -0,0 +1,82 @@
+/*
+  TOWCTRANS: wint_t towctrans (wint_t wc, wctrans_t desc);
+*/
+
+#define TST_FUNCTION towctrans
+
+#include "tsp_common.c"
+#include "dat_towctrans.c"
+
+
+int
+tst_towctrans (FILE *fp, int debug_flg)
+{
+  TST_DECL_VARS (wint_t);
+  wint_t wc;
+  const char *ts;
+#if SHOJI_IS_RIGHT
+  int dummy=0;
+#endif
+  wctrans_t wto;
+
+  TST_DO_TEST (towctrans)
+    {
+      TST_HEAD_LOCALE (towctrans, S_TOWCTRANS);
+      TST_DO_REC (towctrans)
+	{
+	  TST_GET_ERRET (towctrans);
+	  wc = TST_INPUT (towctrans).wc;
+	  ts = TST_INPUT (towctrans).ts;
+
+#if SHOJI_IS_RIGHT
+	  if ((wto = wctrans (ts)) == (wctrans_t) 0)
+	    {
+#if 0
+	      result (fp, C_IGNORED, S_TOWCTRANS, locale, rec+1, seq_num+1, 3,
+		      "Skip this data because the wctrans object is not invalid.");
+	      warn_count++;
+	      continue;
+#else
+	      wto = &dummy;	/* not good ... */
+#endif
+	      if (debug_flg)
+		{
+		  fprintf (stdout, "towctrans() ------ wctrans() returnd 0.\n");
+		}
+	    }
+#else
+	  wto = wctrans (ts);
+#endif
+
+	  TST_CLEAR_ERRNO;
+	  ret = towctrans (wc, wto);
+	  TST_SAVE_ERRNO;
+
+	  if (debug_flg)
+	    {
+	      fprintf (stdout, "towctrans() [ %s : %d ] ret = 0x%x\n",
+		       locale, rec+1, ret);
+	      fprintf (stdout, "		      errno = %d\n",
+		       errno_save);
+	    }
+
+	  TST_IF_RETURN (S_TOWCTRANS)
+	    {
+	      if (ret != 0)
+		{
+		  result (fp, C_SUCCESS, S_TOWCTRANS, locale, rec+1,
+			  seq_num+1, 3, MS_PASSED);
+		}
+	      else
+		{
+		  err_count++;
+		  result (fp, C_FAILURE, S_TOWCTRANS, locale, rec+1,
+			  seq_num+1, 3,
+			  "the function returned 0, but should be non-zero");
+		}
+	    }
+	}
+    }
+
+  return err_count;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_towlower.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_towlower.c
new file mode 100644
index 00000000..7719b0da
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_towlower.c
@@ -0,0 +1,11 @@
+/*
+  TOWLOWER: int towlower (wint_t wc);
+*/
+
+#define TST_FUNCTION towlower
+
+#include "tsp_common.c"
+#include "dat_towlower.c"
+
+
+TST_FUNC_TOW (LOWER, lower);
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_towupper.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_towupper.c
new file mode 100644
index 00000000..a077d27d
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_towupper.c
@@ -0,0 +1,10 @@
+/*
+  TOWUPPER: int towupper (wint_t wc);
+*/
+
+#define TST_FUNCTION towupper
+
+#include "tsp_common.c"
+#include "dat_towupper.c"
+
+TST_FUNC_TOW (UPPER, upper);
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_types.h b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_types.h
new file mode 100644
index 00000000..3d182794
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_types.h
@@ -0,0 +1,729 @@
+/*
+ *  TEST SUITE FOR MB/WC FUNCTIONS IN C LIBRARY
+ *
+ *	 FILE:	tst_types.h
+ *
+ *	 Definitions of data types for each test function
+ */
+
+
+#ifndef TST_TYPES_H
+#define TST_TYPES_H
+
+#include 
+#include 
+#include 
+#include "tst_funcs.h"
+#include "tgn_funcdef.h"
+
+#define MBSSIZE		   24
+#define WCSSIZE		   12
+#define MONFMTSIZE	   16
+#define MONSIZE		   64
+#define USE_MBCURMAX	   99	/* well, but ... */
+#define TST_DBL_EPS	   2.22153e-16
+#define WCSTOK_SEQNUM	   3
+#define MBLEN_SEQNUM	   3
+#define MBTOWC_SEQNUM	   3
+#define MBSTOWCS_SEQNUM	   3
+#define WCTOMB_SEQNUM	   3
+#define WCSTOMBS_SEQNUM	   3
+#define MBRLEN_SEQNUM	   3
+#define MBRTOWC_SEQNUM	   3
+#define MBSRTOWCS_SEQNUM   3
+#define WCRTOMB_SEQNUM	   3
+#define WCSRTOMBS_SEQNUM   3
+
+/* Maximum numbers of test in one of the _loc arrays.  */
+#define MAX_LOC_TEST		300
+
+
+/*----------------------------------------------------------------------*/
+/*  FUNCTION								*/
+/*----------------------------------------------------------------------*/
+
+typedef struct
+{
+  char *func_str;
+  int func_id;
+}
+TST_FID;
+
+typedef struct
+{
+  int func_id;
+  const char *locale;
+}
+TST_HEAD;
+
+typedef struct
+{
+  TST_HEAD *head;
+}
+TST_FUNCS;
+
+
+/*----------------------------------------------------------------------*/
+/*  ISW*: int isw* (wchar_t wc)						*/
+/*----------------------------------------------------------------------*/
+
+TST_ISW_STRUCT (ALNUM, alnum);
+TST_ISW_STRUCT (ALPHA, alpha);
+TST_ISW_STRUCT (CNTRL, cntrl);
+TST_ISW_STRUCT (DIGIT, digit);
+TST_ISW_STRUCT (GRAPH, graph);
+TST_ISW_STRUCT (LOWER, lower);
+TST_ISW_STRUCT (PRINT, print);
+TST_ISW_STRUCT (PUNCT, punct);
+TST_ISW_STRUCT (SPACE, space);
+TST_ISW_STRUCT (UPPER, upper);
+TST_ISW_STRUCT (XDIGIT, xdigit);
+
+typedef struct
+{
+  wint_t wc;
+  const char *ts;
+}
+TIN_ISWCTYPE_REC;
+
+typedef
+TEX_ERRET_REC (int)
+  TEX_ISWCTYPE_REC;
+TMD_RECHEAD (ISWCTYPE);
+
+
+/*----------------------------------------------------------------------*/
+/*  MBLEN: int mblen (const char *s, size_t n)				*/
+/*----------------------------------------------------------------------*/
+
+typedef struct
+{
+  char s_flg;
+  char s[MBSSIZE];
+  size_t n;
+}
+TIN_MBLEN_REC;
+
+typedef TEX_ERRET_REC (int) TEX_MBLEN_REC;
+TMD_RECHEAD (MBLEN);
+
+
+/*----------------------------------------------------------------------*/
+/*  MBRLEN: size_t mbrlen (const char *s, size_t n, mbstate_t *ps)	*/
+/*----------------------------------------------------------------------*/
+
+typedef struct
+{
+  struct
+  {
+    int s_flg;
+    char s[MBSSIZE];
+    size_t n;
+    int t_flg;
+    int t_init;
+  }
+  seq[WCSTOK_SEQNUM];
+}
+TIN_MBRLEN_REC;
+
+typedef TEX_ERRET_REC_SEQ (size_t, MBRLEN_SEQNUM) TEX_MBRLEN_REC;
+TMD_RECHEAD (MBRLEN);
+
+
+/*----------------------------------------------------------------------*/
+/*  MBRTOWC: size_t mbrtowc (wchar_t *pwc, const char *s, size_t n,	*/
+/*			     mbstate_t *ps)				*/
+/*----------------------------------------------------------------------*/
+
+typedef struct
+{
+  struct
+  {
+    int w_flg;
+    int s_flg;
+    char s[MBSSIZE];
+    size_t n;
+    int t_flg;
+    int t_init;
+  }
+  seq[MBRTOWC_SEQNUM];
+}
+TIN_MBRTOWC_REC;
+
+typedef struct
+{
+  struct
+  {
+    TMD_ERRET (size_t);
+    wchar_t wc;
+  }
+  seq[MBRTOWC_SEQNUM];
+}
+TEX_MBRTOWC_REC;
+
+TMD_RECHEAD (MBRTOWC);
+
+
+/*----------------------------------------------------------------------*/
+/*  MBSRTOWCS: size_t mbsrtowcs (wchar_t *ws, const char **s, size_t n, */
+/*				 mbstate_t *ps )			*/
+/*----------------------------------------------------------------------*/
+
+typedef struct
+{
+  struct
+  {
+    int w_flg;
+    char s[MBSSIZE];
+    size_t n;
+    int t_flg;
+    int t_init;
+  }
+  seq[MBSRTOWCS_SEQNUM];
+}
+TIN_MBSRTOWCS_REC;
+
+typedef struct
+{
+  struct
+  {
+    TMD_ERRET (size_t);
+    wchar_t ws[WCSSIZE];
+  }
+  seq[MBSRTOWCS_SEQNUM];
+}
+TEX_MBSRTOWCS_REC;
+
+TMD_RECHEAD (MBSRTOWCS);
+
+
+/*----------------------------------------------------------------------*/
+/*  MBSTOWCS: size_t mbstowcs (wchar_t *ws, const char *s, size_t n)	*/
+/*----------------------------------------------------------------------*/
+
+typedef struct
+{
+  struct
+  {
+    int w_flg;
+    int s_flg;
+    const char *s;
+    size_t n;
+  }
+  seq[MBSTOWCS_SEQNUM];
+}
+TIN_MBSTOWCS_REC;
+
+typedef TEX_MBSRTOWCS_REC TEX_MBSTOWCS_REC;
+/* MBSRTOWCS_SEQNUM == MBSTOWCS_SEQNUM */
+TMD_RECHEAD (MBSTOWCS);
+
+
+/*----------------------------------------------------------------------*/
+/*  MBTOWC: int mbtowc (wchar_t *wc, const char *s, size_t n)		*/
+/*----------------------------------------------------------------------*/
+
+typedef TIN_MBSTOWCS_REC TIN_MBTOWC_REC;
+/* MBTOWC_SEQNUM == MBSTOWCS_SEQNUM */
+
+typedef struct
+{
+  struct
+  {
+    TMD_ERRET (int);
+    wchar_t wc;
+  }
+  seq[MBTOWC_SEQNUM];
+}
+TEX_MBTOWC_REC;
+
+TMD_RECHEAD (MBTOWC);
+
+
+/*----------------------------------------------------------------------*/
+/*  STRCOLL: int strcoll (const char *s1, const char *s2)		*/
+/*----------------------------------------------------------------------*/
+
+typedef struct
+{
+  char s1[MBSSIZE];
+  char s2[MBSSIZE];
+}
+TIN_STRCOLL_REC;
+
+typedef TEX_ERRET_REC (int) TEX_STRCOLL_REC;
+TMD_RECHEAD (STRCOLL);
+
+
+/*----------------------------------------------------------------------*/
+/*  STRFMON: size_t strfmon (char *buf, size_t nbytes,			*/
+/*			     const char *fmt, ... )			*/
+/*----------------------------------------------------------------------*/
+
+typedef struct
+{
+  int nbytes;
+  char fmt[MONFMTSIZE];
+  double val;
+}
+TIN_STRFMON_REC;
+
+typedef struct
+{
+  TMD_ERRET (size_t);
+  char mon[MONSIZE];
+}
+TEX_STRFMON_REC;
+
+TMD_RECHEAD (STRFMON);
+
+
+/*----------------------------------------------------------------------*/
+/*  STRXFRM: size_t strxfrm (char *s1, const char *s2, size_t n)	*/
+/*----------------------------------------------------------------------*/
+
+typedef struct
+{
+  char org1[MBSSIZE];
+  char org2[MBSSIZE];
+  size_t n1, n2;
+}
+TIN_STRXFRM_REC;
+
+typedef TEX_ERRET_REC (size_t) TEX_STRXFRM_REC;	/* only for org2[] */
+TMD_RECHEAD (STRXFRM);
+
+
+/*----------------------------------------------------------------------*/
+/*  SWSCANF: int swscanf (const wchar_t *ws, const wchar_t *fmt, ...)	*/
+/*----------------------------------------------------------------------*/
+
+typedef struct
+{
+  wchar_t ws[WCSSIZE * 3];
+  wchar_t fmt[WCSSIZE * 3];
+  int wch;
+}
+TIN_SWSCANF_REC;
+
+typedef struct
+{
+  TMD_ERRET (int);
+  int val_int;		/* %d */
+  unsigned val_uns;	/* %u */
+  float val_flt;		/* %f */
+  int val_c;		/* %c */
+  char val_s[MBSSIZE * 2];	/* %s */
+  wchar_t val_S[WCSSIZE * 2];	/* %lc, %ls, %C, %S */
+}
+TEX_SWSCANF_REC;
+
+TMD_RECHEAD (SWSCANF);
+
+
+/*----------------------------------------------------------------------*/
+/*  TOWCTRANS: wint_t towctrans (wint_t wc, wctrans_t desc)		*/
+/*----------------------------------------------------------------------*/
+
+typedef TIN_ISWCTYPE_REC TIN_TOWCTRANS_REC;
+typedef TEX_ERRET_REC (wint_t) TEX_TOWCTRANS_REC;
+TMD_RECHEAD (TOWCTRANS);
+
+
+/*----------------------------------------------------------------------*/
+/*  TOW*ER: wint_t tow*er (wint_t wc)					*/
+/*----------------------------------------------------------------------*/
+
+TST_TOW_STRUCT (LOWER, lower);
+TST_TOW_STRUCT (UPPER, upper);
+
+
+/*----------------------------------------------------------------------*/
+/*  WCRTOMB: wchar_t wcrtomb (char *s, wchar_t wc, mbstate_t *ps)	*/
+/*----------------------------------------------------------------------*/
+
+typedef struct
+{
+  int s_flg;
+  wchar_t wc;
+  int t_flg;
+  int t_init;
+}
+TIN_WCRTOMB_REC;
+
+typedef struct
+{
+  TMD_ERRET (wchar_t);
+  char s[MBSSIZE];
+}
+TEX_WCRTOMB_REC;
+
+TMD_RECHEAD (WCRTOMB);
+
+
+/*----------------------------------------------------------------------*/
+/*  WCSCAT: wchar_t *wcscat (wchar_t *ws1, wchar_t *ws2)		*/
+/*----------------------------------------------------------------------*/
+
+typedef struct
+{
+  wchar_t ws1[WCSSIZE];
+  wchar_t ws2[WCSSIZE];
+}
+TIN_WCSCAT_REC;
+
+typedef struct
+{
+  TMD_ERRET (wchar_t *);
+  wchar_t ws[WCSSIZE];
+}
+TEX_WCSCAT_REC;
+
+TMD_RECHEAD (WCSCAT);
+
+
+/*----------------------------------------------------------------------*/
+/*  WCSCHR: wchar_t *wcschr (wchar_t *ws, wchar_t wc);			*/
+/*----------------------------------------------------------------------*/
+
+typedef struct
+{
+  wchar_t ws[WCSSIZE];
+  wchar_t wc;
+}
+TIN_WCSCHR_REC;
+
+typedef TEX_ERRET_REC (wchar_t *) TEX_WCSCHR_REC;
+TMD_RECHEAD (WCSCHR);
+
+
+/*----------------------------------------------------------------------*/
+/*  WCSCMP: int wcscmp (const wchar_t *ws1, const wchar_t *ws2)		*/
+/*----------------------------------------------------------------------*/
+
+typedef TIN_WCSCAT_REC TIN_WCSCMP_REC;
+typedef TEX_ERRET_REC (int) TEX_WCSCMP_REC;
+TMD_RECHEAD (WCSCMP);
+
+
+/*----------------------------------------------------------------------*/
+/*  WCSCOLL: int wcscoll (const wchar_t *ws1, const wchar_t *ws2)	*/
+/*----------------------------------------------------------------------*/
+
+typedef TIN_WCSCMP_REC TIN_WCSCOLL_REC;
+typedef struct
+{
+  TMD_ERRET (int);
+  int cmp_flg;
+}
+TEX_WCSCOLL_REC;
+TMD_RECHEAD (WCSCOLL);
+
+
+/*----------------------------------------------------------------------*/
+/*  WCSCPY: wchar_t *wcscpy (wchar_t *ws1, const wchar_t *ws2)		*/
+/*----------------------------------------------------------------------*/
+
+typedef struct
+{
+  wchar_t ws[WCSSIZE];	/* ws2: original string */
+}
+TIN_WCSCPY_REC;
+
+typedef TEX_WCSCAT_REC TEX_WCSCPY_REC;
+TMD_RECHEAD (WCSCPY);
+
+
+/*----------------------------------------------------------------------*/
+/*  WCSCSPN: size_t wcscspn (const wchar_t *ws1, const wchar_t *ws2)	*/
+/*----------------------------------------------------------------------*/
+
+typedef TIN_WCSCAT_REC TIN_WCSCSPN_REC;
+typedef TEX_ERRET_REC (size_t) TEX_WCSCSPN_REC;
+TMD_RECHEAD (WCSCSPN);
+
+
+/*----------------------------------------------------------------------*/
+/*  WCSLEN: size_t wcslen (const wchar_t *ws)				*/
+/*----------------------------------------------------------------------*/
+
+typedef TIN_WCSCPY_REC TIN_WCSLEN_REC;
+typedef TEX_ERRET_REC (size_t) TEX_WCSLEN_REC;
+TMD_RECHEAD (WCSLEN);
+
+
+/*----------------------------------------------------------------------*/
+/*  WCSNCAT: wchar_t *wcsncat (wchar_t *ws1, const wchar_t *ws2,	*/
+/*			       size_t n)				*/
+/*----------------------------------------------------------------------*/
+
+typedef struct
+{
+  wchar_t ws1[WCSSIZE];
+  wchar_t ws2[WCSSIZE];
+  size_t n;
+}
+TIN_WCSNCAT_REC;
+
+typedef TEX_WCSCAT_REC TEX_WCSNCAT_REC;
+TMD_RECHEAD (WCSNCAT);
+
+
+/*----------------------------------------------------------------------*/
+/*  WCSNCMP: int *wcsncmp (const wchar_t *ws1, const wchar_t *ws2,	*/
+/*			   size_t n)					*/
+/*----------------------------------------------------------------------*/
+
+typedef TIN_WCSNCAT_REC TIN_WCSNCMP_REC;
+typedef TEX_ERRET_REC (int) TEX_WCSNCMP_REC;
+TMD_RECHEAD (WCSNCMP);
+
+
+/*----------------------------------------------------------------------*/
+/*  WCSNCPY: wchar_t *wcsncpy (wchar_t *ws1, const wchar_t *ws2,	*/
+/*			       size_t n)				*/
+/*----------------------------------------------------------------------*/
+
+typedef struct
+{
+  wchar_t ws[WCSSIZE];	/* ws2: original string */
+  size_t n;
+}
+TIN_WCSNCPY_REC;
+
+typedef TEX_WCSCPY_REC TEX_WCSNCPY_REC;
+TMD_RECHEAD (WCSNCPY);
+
+
+/*----------------------------------------------------------------------*/
+/*  WCSPBRK: wchar_t *wcspbrk (const wchar_t *ws1, const wchar_t *ws2)	*/
+/*----------------------------------------------------------------------*/
+
+typedef TIN_WCSCSPN_REC TIN_WCSPBRK_REC;
+
+typedef struct
+{
+  TMD_ERRET (wchar_t *);
+  wchar_t wc;
+}
+TEX_WCSPBRK_REC;
+
+TMD_RECHEAD (WCSPBRK);
+
+
+/*----------------------------------------------------------------------*/
+/*  WCSRTOMBS: size_t wcsrtombs (char *s, const wchar_t **ws, size_t n, */
+/*				 mbstate_t *ps)				*/
+/*----------------------------------------------------------------------*/
+
+typedef struct
+{
+  int s_flg;
+  int w_flg;		/* don't need this */
+  wchar_t ws[WCSSIZE];
+  size_t n;
+  int t_flg;
+  int t_init;
+}
+TIN_WCSRTOMBS_REC;
+
+typedef struct
+{
+  TMD_ERRET (size_t);
+  char s[MBSSIZE];
+}
+TEX_WCSRTOMBS_REC;
+
+TMD_RECHEAD (WCSRTOMBS);
+
+
+/*----------------------------------------------------------------------*/
+/*  WCSSPN: size_t wcsspn (const wchar_t *ws1, const wchar_t *ws2)	*/
+/*----------------------------------------------------------------------*/
+
+typedef TIN_WCSCSPN_REC TIN_WCSSPN_REC;
+typedef TEX_WCSCSPN_REC TEX_WCSSPN_REC;
+TMD_RECHEAD (WCSSPN);
+
+
+/*----------------------------------------------------------------------*/
+/*  WCSSTR: wchar_t *wcsstr (const wchar_t *ws1, const wchar_t *ws2)	*/
+/*----------------------------------------------------------------------*/
+
+typedef TIN_WCSCSPN_REC TIN_WCSSTR_REC;
+typedef TEX_ERRET_REC (wchar_t *) TEX_WCSSTR_REC;
+TMD_RECHEAD (WCSSTR);
+
+
+/*----------------------------------------------------------------------*/
+/*  WCSTOD: double wcstod (const wchar_t *np, wchar_t **endp)		*/
+/*----------------------------------------------------------------------*/
+
+typedef struct
+{
+  wchar_t np[WCSSIZE];
+}
+TIN_WCSTOD_REC;
+
+typedef struct
+{
+  TMD_ERRET (double);
+  double val;
+  wchar_t fwc;
+}
+TEX_WCSTOD_REC;
+
+TMD_RECHEAD (WCSTOD);
+
+
+/*----------------------------------------------------------------------*/
+/*  WCSTOK: wchar_t *wcstok (wchar_t *ws, const wchar_t *dlm,		*/
+/*			     wchar_t **pt)				*/
+/*----------------------------------------------------------------------*/
+
+typedef struct
+{
+  struct
+  {
+    int w_flg;
+    wchar_t ws[WCSSIZE];
+    wchar_t dt[WCSSIZE];	/* delimiter */
+  }
+  seq[WCSTOK_SEQNUM];
+}
+TIN_WCSTOK_REC;
+
+typedef struct
+{
+  struct
+  {
+    TMD_ERRET (wchar_t *);
+    wchar_t ws[WCSSIZE];
+  }
+  seq[WCSTOK_SEQNUM];
+}
+TEX_WCSTOK_REC;
+
+TMD_RECHEAD (WCSTOK);
+
+
+/*----------------------------------------------------------------------*/
+/*  WCSTOMBS: size_t wcstombs (char s, const wchar_t *ws, size_t n)	*/
+/*----------------------------------------------------------------------*/
+
+typedef struct
+{
+  int s_flg;
+  int w_flg;		/* currently we don't need it. */
+  wchar_t ws[WCSSIZE];
+  size_t n;
+}
+TIN_WCSTOMBS_REC;
+
+typedef struct
+{
+  TMD_ERRET (size_t);
+  char s[MBSSIZE];
+}
+TEX_WCSTOMBS_REC;
+
+TMD_RECHEAD (WCSTOMBS);
+
+
+/*----------------------------------------------------------------------*/
+/*  WCSWIDTH: int wcswidth (const wchar_t *ws, size_t n)		*/
+/*----------------------------------------------------------------------*/
+
+typedef TIN_WCSNCPY_REC TIN_WCSWIDTH_REC;
+typedef TEX_ERRET_REC (int) TEX_WCSWIDTH_REC;
+TMD_RECHEAD (WCSWIDTH);
+
+
+/*----------------------------------------------------------------------*/
+/*  WCSXFRM: size_t wcsxfrm (wchar_t *ws1, const wchar_t *ws2, size_t n)*/
+/*----------------------------------------------------------------------*/
+
+typedef struct
+{
+  wchar_t org1[WCSSIZE];
+  wchar_t org2[WCSSIZE];
+  int n1, n2;
+}
+TIN_WCSXFRM_REC;
+
+typedef TEX_ERRET_REC (size_t) TEX_WCSXFRM_REC;	/* only for org2[] */
+TMD_RECHEAD (WCSXFRM);
+
+
+/*----------------------------------------------------------------------*/
+/*  WCTOB: int wctob (wint_t wc)					*/
+/*----------------------------------------------------------------------*/
+
+typedef struct
+{
+  wint_t wc;
+}
+TIN_WCTOB_REC;
+
+typedef TEX_ERRET_REC (int) TEX_WCTOB_REC;
+TMD_RECHEAD (WCTOB);
+
+
+/*----------------------------------------------------------------------*/
+/*  WCTOMB: int wctomb (char *s, wchar_t wc)				*/
+/*----------------------------------------------------------------------*/
+
+typedef struct
+{
+  int s_flg;
+  wchar_t wc;
+}
+TIN_WCTOMB_REC;
+
+typedef struct
+{
+  TMD_ERRET (int);
+  char s[MBSSIZE];
+}
+TEX_WCTOMB_REC;
+
+TMD_RECHEAD (WCTOMB);
+
+
+/*----------------------------------------------------------------------*/
+/*  WCTRANS: wctrans_t wctrans (const char *charclass)			*/
+/*----------------------------------------------------------------------*/
+
+typedef struct
+{
+  char class[MBSSIZE];
+}
+TIN_WCTRANS_REC;
+
+typedef TEX_ERRET_REC (wctrans_t) TEX_WCTRANS_REC;
+TMD_RECHEAD (WCTRANS);
+
+
+/*----------------------------------------------------------------------*/
+/*  WCTYPE: wctype_t wctype (const char *class)				*/
+/*----------------------------------------------------------------------*/
+
+typedef TIN_WCTRANS_REC TIN_WCTYPE_REC;
+typedef TEX_ERRET_REC (wctype_t) TEX_WCTYPE_REC;
+TMD_RECHEAD (WCTYPE);
+
+
+/*----------------------------------------------------------------------*/
+/*  WCWIDTH: int wcwidth (wchar_t wc)					*/
+/*----------------------------------------------------------------------*/
+
+typedef struct
+{
+  wchar_t wc;
+}
+TIN_WCWIDTH_REC;
+
+typedef TEX_ERRET_REC (int) TEX_WCWIDTH_REC;
+TMD_RECHEAD (WCWIDTH);
+
+#endif /* TST_TYPES_H */
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wcrtomb.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wcrtomb.c
new file mode 100644
index 00000000..0029a494
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wcrtomb.c
@@ -0,0 +1,79 @@
+/*
+  WCRTOMB: wchar_t wcrtomb (char *s, wchar_t wc, mbstate_t *ps)
+*/
+
+#define TST_FUNCTION wcrtomb
+
+#include "tsp_common.c"
+#include "dat_wcrtomb.c"
+
+
+int
+tst_wcrtomb (FILE * fp, int debug_flg)
+{
+  TST_DECL_VARS (wchar_t);
+  wchar_t wc;
+  char s[MBSSIZE], *s_in, *s_ex;
+  char t_flg, t_ini;
+  static mbstate_t t = { 0 };
+  mbstate_t *pt;
+  int err, i;
+
+  TST_DO_TEST (wcrtomb)
+  {
+    TST_HEAD_LOCALE (wcrtomb, S_WCRTOMB);
+    TST_DO_REC (wcrtomb)
+    {
+      TST_GET_ERRET (wcrtomb);
+      s_in = ((TST_INPUT (wcrtomb).s_flg) == 0) ? (char *) NULL : s;
+      wc = TST_INPUT (wcrtomb).wc;
+      t_flg = TST_INPUT (wcrtomb).t_flg;
+      t_ini = TST_INPUT (wcrtomb).t_init;
+      pt = (t_flg == 0) ? NULL : &t;
+
+      if (t_ini != 0)
+	{
+	  memset (&t, 0, sizeof (t));
+	}
+
+      TST_CLEAR_ERRNO;
+      ret = wcrtomb (s_in, wc, pt);
+      TST_SAVE_ERRNO;
+
+      if (debug_flg)
+	{
+	  fprintf (stdout, "wcrtomb() [ %s : %d ] ret = %lu\n", locale,
+		   rec + 1, (unsigned long int) ret);
+	  fprintf (stdout, "			errno = %d\n", errno_save);
+	}
+
+      TST_IF_RETURN (S_WCRTOMB)
+      {
+      };
+
+      s_ex = TST_EXPECT (wcrtomb).s;
+
+      if (s_in)
+	{
+	  for (i = 0, err = 0; *(s_ex + i) != 0 && i < MBSSIZE; i++)
+	    {
+	      if (s_in[i] != s_ex[i])
+		{
+		  err++;
+		  err_count++;
+		  Result (C_FAILURE, S_WCRTOMB, CASE_4,
+			  "copied string is different from an "
+			  "expected string");
+		  break;
+		}
+	    }
+	  if (!err)
+	    {
+	      Result (C_SUCCESS, S_WCRTOMB, CASE_4, MS_PASSED);
+	    }
+	}
+    }
+  }
+
+  return err_count;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wcscat.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wcscat.c
new file mode 100644
index 00000000..3dc98091
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wcscat.c
@@ -0,0 +1,78 @@
+/*
+  WCSCAT: wchar_t *wcscat (wchar_t *ws1, const wchar_t *ws2);
+*/
+
+#define TST_FUNCTION wcscat
+
+#include "tsp_common.c"
+#include "dat_wcscat.c"
+
+int
+tst_wcscat (FILE * fp, int debug_flg)
+{
+  TST_DECL_VARS (wchar_t *);
+  wchar_t *ws1, *ws2, *ws_ex;
+  int i, err;
+
+  TST_DO_TEST (wcscat)
+  {
+    TST_HEAD_LOCALE (wcscat, S_WCSCAT);
+    TST_DO_REC (wcscat)
+    {
+      TST_GET_ERRET (wcscat);
+      ws1 = TST_INPUT (wcscat).ws1;	/* external value: size WCSSIZE */
+      ws2 = TST_INPUT (wcscat).ws2;
+
+      TST_CLEAR_ERRNO;
+      ret = wcscat (ws1, ws2);
+      TST_SAVE_ERRNO;
+
+      TST_IF_RETURN (S_WCSCAT)
+      {
+	if (ret == ws1)
+	  {
+	    Result (C_SUCCESS, S_WCSCAT, CASE_3, MS_PASSED);
+	  }
+	else
+	  {
+	    err_count++;
+	    Result (C_FAILURE, S_WCSCAT, CASE_3,
+		    "the return address may not be correct");
+	  }
+      }
+
+      /* function specific test cases here */
+
+      if (ret == ws1)
+	{
+	  ws_ex = TST_EXPECT (wcscat).ws;
+	  for (err = 0, i = 0;
+	       (ws1[i] != 0L || ws_ex[i] != 0L) && i < WCSSIZE; i++)
+	    {
+	      if (debug_flg)
+		{
+		  fprintf (stdout, "tst_wcscat() : ws1[%d] = 0x%lx\n", i,
+			   (unsigned long int) ws1[i]);
+		}
+
+	      if (ws1[i] != ws_ex[i])
+		{
+		  err++;
+		  err_count++;
+		  Result (C_FAILURE, S_WCSCAT, CASE_4,
+			  "concatinated string is different from an "
+			  "expected string");
+		  break;
+		}
+	    }
+
+	  if (!err)
+	    {
+	      Result (C_SUCCESS, S_WCSCAT, CASE_4, MS_PASSED);
+	    }
+	}
+    }
+  }
+
+  return err_count;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wcschr.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wcschr.c
new file mode 100644
index 00000000..b57a05a8
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wcschr.c
@@ -0,0 +1,70 @@
+/*
+  WCSCHR: wchar_t *wcschr (wchar_t *ws, wchar_t wc);
+*/
+
+#define TST_FUNCTION wcschr
+
+#include "tsp_common.c"
+#include "dat_wcschr.c"
+
+int
+tst_wcschr (FILE * fp, int debug_flg)
+{
+  TST_DECL_VARS (wchar_t *);
+  wchar_t *ws, wc;
+
+  TST_DO_TEST (wcschr)
+  {
+    TST_HEAD_LOCALE (wcschr, S_WCSCHR);
+    TST_DO_REC (wcschr)
+    {
+      TST_GET_ERRET (wcschr);
+      ws = TST_INPUT (wcschr).ws;	/* external value: size WCSSIZE */
+      wc = TST_INPUT (wcschr).wc;
+      ret = wcschr (ws, wc);
+
+      if (debug_flg)
+	{
+	  if (ret)
+	    {
+	      fprintf (stderr, "wcschr: ret = 0x%lx\n",
+		       (unsigned long int) *ret);
+	    }
+	  else
+	    {
+	      fprintf (stderr, "wcschr: ret = NULL pointer\n");
+	    }
+	}
+
+      TST_IF_RETURN (S_WCSCHR)
+      {
+	if (ret == NULL)
+	  {
+	    if (debug_flg)
+	      {
+		fprintf (stderr, "*** Warning *** tst_wcschr: "
+			 "set ret_flg=1 to check NULL return value\n");
+	      }
+
+	    warn_count++;
+	    Result (C_INVALID, S_WCSCHR, CASE_3, "(check the test data) "
+		    "set ret_flg=1 to check NULL return value");
+	    continue;
+	  }
+
+	if (*ret == wc)
+	  {
+	    Result (C_SUCCESS, S_WCSCHR, CASE_3, MS_PASSED);
+	  }
+	else
+	  {
+	    err_count++;
+	    Result (C_FAILURE, S_WCSCHR, CASE_3,
+		    "the returned address of the string seems to be wrong");
+	  }
+      }
+    }
+  }
+
+  return err_count;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wcscmp.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wcscmp.c
new file mode 100644
index 00000000..594682ce
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wcscmp.c
@@ -0,0 +1,40 @@
+/*
+  WCSCMP: int wcscmp (const wchar_t *ws1, const wchar_t *ws2);
+*/
+
+#define TST_FUNCTION wcscmp
+
+#include "tsp_common.c"
+#include "dat_wcscmp.c"
+
+
+int
+tst_wcscmp (FILE * fp, int debug_flg)
+{
+  TST_DECL_VARS (int);
+  wchar_t *ws1, *ws2;
+
+  TST_DO_TEST (wcscmp)
+  {
+    TST_HEAD_LOCALE (wcscmp, S_WCSCMP);
+    TST_DO_REC (wcscmp)
+    {
+      TST_GET_ERRET (wcscmp);
+      ws1 = TST_INPUT (wcscmp).ws1;
+      ws2 = TST_INPUT (wcscmp).ws2;
+      ret = wcscmp (ws1, ws2);
+      ret = (ret > 0 ? 1 : ret < 0 ? -1 : 0);
+
+      if (debug_flg)
+	{
+	  fprintf (stderr, "tst_wcscmp: ret = %d\n", ret);
+	}
+
+      TST_IF_RETURN (S_WCSCMP)
+      {
+      };
+    }
+  }
+
+  return err_count;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wcscoll.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wcscoll.c
new file mode 100644
index 00000000..929f80d8
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wcscoll.c
@@ -0,0 +1,76 @@
+/*
+  WCSCOLL: int wcscoll (const wchar_t *ws1, const wchar_t *ws2);
+*/
+
+#define TST_FUNCTION wcscoll
+
+#include "tsp_common.c"
+#include "dat_wcscoll.c"
+
+int
+tst_wcscoll (FILE * fp, int debug_flg)
+{
+  TST_DECL_VARS (int);
+  wchar_t *ws1, *ws2;
+  int cmp;
+
+  TST_DO_TEST (wcscoll)
+  {
+    TST_HEAD_LOCALE (wcscoll, S_WCSCOLL);
+    TST_DO_REC (wcscoll)
+    {
+      TST_GET_ERRET (wcscoll);
+      ws1 = TST_INPUT (wcscoll).ws1;	/* external value: size WCSSIZE */
+      ws2 = TST_INPUT (wcscoll).ws2;
+
+      TST_CLEAR_ERRNO;
+      ret = wcscoll (ws1, ws2);
+      TST_SAVE_ERRNO;
+
+      if (debug_flg)
+	{
+	  fprintf (stderr, "tst_wcscoll: ret = %d\n", ret);
+	}
+
+      cmp = TST_EXPECT (wcscoll).cmp_flg;
+      TST_IF_RETURN (S_WCSCOLL)
+      {
+	if (cmp != 0)
+	  {
+	    if ((cmp == 1 && ret > 0) || (cmp == -1 && ret < 0))
+	      {
+		Result (C_SUCCESS, S_WCSCOLL, CASE_3, MS_PASSED);
+	      }
+	    else
+	      {
+		err_count++;
+		if (cmp == 1)
+		  {
+		    if (ret == 0)
+		      Result (C_FAILURE, S_WCSCOLL, CASE_3,
+			      "the return value should be positive"
+			      " but it's zero.");
+		    else
+		      Result (C_FAILURE, S_WCSCOLL, CASE_3,
+			      "the return value should be positive"
+			      " but it's negative.");
+		  }
+		else
+		  {
+		    if (ret == 0)
+		      Result (C_FAILURE, S_WCSCOLL, CASE_3,
+			      "the return value should be negative"
+			      " but it's zero.");
+		    else
+		      Result (C_FAILURE, S_WCSCOLL, CASE_3,
+			      "the return value should be negative"
+			      " but it's positive.");
+		  }
+	      }
+	  }
+      }
+    }
+  }
+
+  return err_count;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wcscpy.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wcscpy.c
new file mode 100644
index 00000000..d5705a55
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wcscpy.c
@@ -0,0 +1,85 @@
+/*-------------------------------------------------------------------------------------*/
+/* WCSCPY: wchar_t *wcscpy( wchar_t *ws1, const wchar_t *ws2 )			       */
+/*-------------------------------------------------------------------------------------*/
+#define TST_FUNCTION wcscpy
+
+#include "tsp_common.c"
+#include "dat_wcscpy.c"
+
+int
+tst_wcscpy (FILE * fp, int debug_flg)
+{
+  TST_DECL_VARS (wchar_t *);
+  wchar_t ws1[WCSSIZE], *ws2, *ws_ex;
+  int err, i;
+
+  TST_DO_TEST (wcscpy)
+  {
+    TST_HEAD_LOCALE (wcscpy, S_WCSCPY);
+    TST_DO_REC (wcscpy)
+    {
+      TST_GET_ERRET (wcscpy);
+      ws2 = TST_INPUT (wcscpy).ws;	/* external value: size WCSSIZE */
+      ret = wcscpy (ws1, ws2);
+
+      TST_IF_RETURN (S_WCSCPY)
+      {
+	if (ret == ws1)
+	  {
+	    Result (C_SUCCESS, S_WCSCPY, CASE_3, MS_PASSED);
+	  }
+	else
+	  {
+	    err_count++;
+	    Result (C_FAILURE, S_WCSCPY, CASE_3,
+		    "the return address may not be correct");
+	  }
+      }
+
+      if (ret == ws1)
+	{
+	  ws_ex = TST_EXPECT (wcscpy).ws;
+
+	  for (err = 0, i = 0;
+	       (ws1[i] != 0L || ws_ex[i] != 0L) && i < WCSSIZE; i++)
+	    {
+	      if (debug_flg)
+		{
+		  fprintf (stderr,
+			   "ws1[ %d ] = 0x%lx <-> wx_ex[ %d ] = 0x%lx\n", i,
+			   (unsigned long int) ws1[i], i,
+			   (unsigned long int) ws_ex[i]);
+		}
+
+	      if (ws1[i] != ws_ex[i])
+		{
+		  err++;
+		  err_count++;
+		  Result (C_FAILURE, S_WCSCPY, CASE_4,
+			  "copied string is different from an"
+			  " expected string");
+		  break;
+		}
+	    }
+
+	  if (!err)
+	    {
+	      Result (C_SUCCESS, S_WCSCPY, CASE_4, MS_PASSED);
+	    }
+
+	  if (ws1[i] == 0L)
+	    {
+	      Result (C_SUCCESS, S_WCSCPY, CASE_5, MS_PASSED);
+	    }
+	  else
+	    {
+	      err_count++;
+	      Result (C_FAILURE, S_WCSCPY, CASE_5,
+		      "copied string is not null-terminated");
+	    }
+	}
+    }
+  }
+
+  return err_count;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wcscspn.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wcscspn.c
new file mode 100644
index 00000000..e1c8892f
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wcscspn.c
@@ -0,0 +1,38 @@
+/*
+  WCSCSPN: size_t wcscspn (const wchar_t *ws1, const wchar_t *ws2);
+*/
+
+#define TST_FUNCTION wcscspn
+
+#include "tsp_common.c"
+#include "dat_wcscspn.c"
+
+int
+tst_wcscspn (FILE * fp, int debug_flg)
+{
+  TST_DECL_VARS (size_t);
+  wchar_t *ws1, *ws2;
+
+  TST_DO_TEST (wcscspn)
+  {
+    TST_HEAD_LOCALE (wcscspn, S_WCSCSPN);
+    TST_DO_REC (wcscspn)
+    {
+      TST_GET_ERRET (wcscspn);
+      ws1 = TST_INPUT (wcscspn).ws1;
+      ws2 = TST_INPUT (wcscspn).ws2;	/* external value: size WCSSIZE */
+      ret = wcscspn (ws1, ws2);
+
+      if (debug_flg)
+	{
+	  fprintf (stderr, "wcscspn: ret = %zu\n", ret);
+	}
+
+      TST_IF_RETURN (S_WCSCSPN)
+      {
+      };
+    }
+  }
+
+  return err_count;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wcslen.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wcslen.c
new file mode 100644
index 00000000..d0ffa5a4
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wcslen.c
@@ -0,0 +1,31 @@
+/*
+  WCSLEN: size_t wcslen (const wchar_t *ws);
+*/
+
+#define TST_FUNCTION wcslen
+
+#include "tsp_common.c"
+#include "dat_wcslen.c"
+
+int
+tst_wcslen (FILE * fp, int debug_flg)
+{
+  TST_DECL_VARS (size_t);
+  wchar_t *ws;
+
+  TST_DO_TEST (wcslen)
+  {
+    TST_HEAD_LOCALE (wcslen, S_WCSLEN);
+    TST_DO_REC (wcslen)
+    {
+      TST_GET_ERRET (wcslen);
+      ws = TST_INPUT (wcslen).ws;
+      ret = wcslen (ws);
+      TST_IF_RETURN (S_WCSLEN)
+      {
+      };
+    }
+  }
+
+  return err_count;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wcsncat.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wcsncat.c
new file mode 100644
index 00000000..a2f6ba02
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wcsncat.c
@@ -0,0 +1,75 @@
+/*
+  WCSNCAT: wchar_t *wcsncat (wchar_t *ws1, const wchar_t *ws2, size_t n);
+*/
+
+#define TST_FUNCTION wcsncat
+
+#include "tsp_common.c"
+#include "dat_wcsncat.c"
+
+int
+tst_wcsncat (FILE * fp, int debug_flg)
+{
+  TST_DECL_VARS (wchar_t *);
+  wchar_t *ws1, *ws2, *ws_ex;
+  int n, i, err;
+
+  TST_DO_TEST (wcsncat)
+  {
+    TST_HEAD_LOCALE (wcsncat, S_WCSNCAT);
+    TST_DO_REC (wcsncat)
+    {
+      TST_GET_ERRET (wcsncat);
+      ws1 = TST_INPUT (wcsncat).ws1;	/* external value: size WCSSIZE */
+      ws2 = TST_INPUT (wcsncat).ws2;
+      n = TST_INPUT (wcsncat).n;
+      ret = wcsncat (ws1, ws2, n);
+
+      TST_IF_RETURN (S_WCSNCAT)
+      {
+	if (ret == ws1)
+	  {
+	    Result (C_SUCCESS, S_WCSNCAT, CASE_3, MS_PASSED);
+	  }
+	else
+	  {
+	    err_count++;
+	    Result (C_FAILURE, S_WCSNCAT, CASE_3,
+		    "the return address may not be correct");
+	  }
+      }
+
+      if (ret == ws1)
+	{
+	  ws_ex = TST_EXPECT (wcsncat).ws;
+
+	  for (err = 0, i = 0;
+	       (ws1[i] != 0L || ws_ex[i] != 0L) && i < WCSSIZE; i++)
+	    {
+	      if (debug_flg)
+		{
+		  fprintf (stderr, "ws1[%d] = 0x%lx\n", i,
+			   (unsigned long int) ws1[i]);
+		}
+
+	      if (ws1[i] != ws_ex[i])
+		{
+		  err++;
+		  err_count++;
+		  Result (C_FAILURE, S_WCSNCAT, CASE_4,
+			  "the concatinated string has "
+			  "different value from an expected string");
+		  break;
+		}
+	    }
+
+	  if (!err)
+	    {
+	      Result (C_SUCCESS, S_WCSNCAT, CASE_4, MS_PASSED);
+	    }
+	}
+    }
+  }
+
+  return err_count;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wcsncmp.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wcsncmp.c
new file mode 100644
index 00000000..d046ecd1
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wcsncmp.c
@@ -0,0 +1,40 @@
+/*-------------------------------------------------------------------------------------*/
+/* WCSNCMP: int wcsncmp( const wchar_t *ws1, const wchar_t *ws2, size_t n )	       */
+/*-------------------------------------------------------------------------------------*/
+
+#define TST_FUNCTION wcsncmp
+
+#include "tsp_common.c"
+#include "dat_wcsncmp.c"
+
+int
+tst_wcsncmp (FILE * fp, int debug_flg)
+{
+  TST_DECL_VARS (int);
+  wchar_t *ws1, *ws2;
+  size_t n;
+
+  TST_DO_TEST (wcsncmp)
+  {
+    TST_HEAD_LOCALE (wcsncmp, S_WCSNCMP);
+    TST_DO_REC (wcsncmp)
+    {
+      TST_GET_ERRET (wcsncmp);
+      ws1 = TST_INPUT (wcsncmp).ws1;	/* external value: size WCSSIZE */
+      ws2 = TST_INPUT (wcsncmp).ws2;
+      n = TST_INPUT (wcsncmp).n;
+      ret = wcsncmp (ws1, ws2, n);
+
+      if (debug_flg)
+	{
+	  fprintf (stderr, "tst_wcsncmp: ret = %d, 0x%x\n", ret, ret);
+	}
+
+      TST_IF_RETURN (S_WCSNCMP)
+      {
+      };
+    }
+  }
+
+  return err_count;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wcsncpy.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wcsncpy.c
new file mode 100644
index 00000000..814bbc0a
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wcsncpy.c
@@ -0,0 +1,93 @@
+/*
+  WCSNCPY: wchar_t *wcsncpy (wchar_t *ws1, const wchar_t *ws2, size_t n);
+*/
+
+#define TST_FUNCTION wcsncpy
+
+#include "tsp_common.c"
+#include "dat_wcsncpy.c"
+
+#define WCSNUM_NCPY 7
+
+int
+tst_wcsncpy (FILE *fp, int debug_flg)
+{
+  TST_DECL_VARS (wchar_t *);
+  wchar_t ws1[WCSSIZE] =
+    { 0x9999, 0x9999, 0x9999, 0x9999, 0x9999, 0x9999, 0x0000 };
+  wchar_t *ws2, *ws_ex;
+  int err, i;
+  size_t n;
+
+  TST_DO_TEST (wcsncpy)
+  {
+    TST_HEAD_LOCALE (wcsncpy, S_WCSNCPY);
+    TST_DO_REC (wcsncpy)
+    {
+      TST_GET_ERRET (wcsncpy);
+
+      for (n = 0; n < WCSNUM_NCPY - 1; ++n)
+	{
+	  ws1[n] = 0x9999;
+	}
+
+      ws1[n] = 0;
+      ws2 = TST_INPUT (wcsncpy).ws;	/* external value: size WCSSIZE */
+      n = TST_INPUT (wcsncpy).n;
+      ret = wcsncpy (ws1, ws2, n);
+
+      TST_IF_RETURN (S_WCSNCPY)
+      {
+	if (ret == ws1)
+	  {
+	    Result (C_SUCCESS, S_WCSNCPY, CASE_3, MS_PASSED);
+	  }
+	else
+	  {
+	    err_count++;
+	    Result (C_FAILURE, S_WCSNCPY, CASE_3,
+		    "the return address may not be correct");
+	  }
+      }
+
+      if (ret == ws1)
+	{
+	  if (debug_flg)
+	    {
+	      fprintf (stderr, "\nwcsncpy: n = %zu\n\n", n);
+	    }
+
+	  ws_ex = TST_EXPECT (wcsncpy).ws;
+
+	  for (err = 0, i = 0; i < WCSNUM_NCPY && i < WCSSIZE; i++)
+	    {
+	      if (debug_flg)
+		fprintf (stderr,
+			 "wcsncpy: ws1[ %d ] = 0x%lx <-> wx_ex[ %d ] = 0x%lx\n",
+			 i, (unsigned long int) ws1[i], i,
+			 (unsigned long int) ws_ex[i]);
+
+	      if (ws1[i] != ws_ex[i])
+		{
+		  err++;
+		  err_count++;
+		  Result (C_FAILURE, S_WCSNCPY, CASE_4,
+			  "copied string is different from an "
+			  "expected string");
+		  break;
+		}
+	    }
+
+	  if (!err)
+	    {
+	      Result (C_SUCCESS, S_WCSNCPY, CASE_4, MS_PASSED);
+	    }
+
+	  /* A null terminate character is not supposed to be copied
+	     unless (num chars of ws2) 0x%lx = wc_ex\n",
+		   (unsigned long int) *ret, (unsigned long int) wc_ex);
+
+	if (*ret != wc_ex)
+	  {
+	    err++;
+	    err_count++;
+	    Result (C_FAILURE, S_WCSPBRK, CASE_4, "the pointed wc is "
+		    "different from an expected wc");
+	  }
+	else
+	  {
+	    Result (C_SUCCESS, S_WCSPBRK, CASE_4, MS_PASSED);
+	  }
+      }
+    }
+  }
+
+  return err_count;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wcsrtombs.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wcsrtombs.c
new file mode 100644
index 00000000..3a8edcca
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wcsrtombs.c
@@ -0,0 +1,127 @@
+/*
+  WCSRTOMBS: size_t wcsrtombs (char *s, const wchar_t **ws, size_t n,
+			       mbstate_t *ps)
+*/
+
+#define TST_FUNCTION wcsrtombs
+
+#include "tsp_common.c"
+#include "dat_wcsrtombs.c"
+
+#define MARK_VAL 0x01
+
+int
+tst_wcsrtombs (FILE * fp, int debug_flg)
+{
+  TST_DECL_VARS (size_t);
+  char s_flg, n;
+  const wchar_t *ws, *wp;
+  char s[MBSSIZE], *s_in;
+  char t_flg, t_ini;
+  static mbstate_t t = { 0 };
+  mbstate_t *pt;
+  int err, i;
+  char *s_ex;
+
+  TST_DO_TEST (wcsrtombs)
+  {
+    TST_HEAD_LOCALE (wcsrtombs, S_WCSRTOMBS);
+    TST_DO_REC (wcsrtombs)
+    {
+      TST_GET_ERRET (wcsrtombs);
+      memset (s, MARK_VAL, MBSSIZE);
+
+      s_flg = TST_INPUT (wcsrtombs).s_flg;
+      s_in = (s_flg == 1) ? s : (char *) NULL;
+      wp = ws = TST_INPUT (wcsrtombs).ws;
+      n = TST_INPUT (wcsrtombs).n;
+      t_flg = TST_INPUT (wcsrtombs).t_flg;
+      t_ini = TST_INPUT (wcsrtombs).t_init;
+      pt = (t_flg == 0) ? NULL : &t;
+
+      if (t_ini != 0)
+	{
+	  memset (&t, 0, sizeof (t));
+	}
+
+      TST_CLEAR_ERRNO;
+      ret = wcsrtombs (s_in, &wp, n, pt);
+      TST_SAVE_ERRNO;
+
+      if (debug_flg)
+	{
+	  fprintf (stderr, "wcsrtombs: ret	= %zu\n", ret);
+	}
+
+      TST_IF_RETURN (S_WCSRTOMBS)
+      {
+      };
+
+      if (s_in != NULL && ret != (size_t) - 1)
+	{
+	  /* No definition for s, when error occurs.  */
+	  s_ex = TST_EXPECT (wcsrtombs).s;
+
+	  for (err = 0, i = 0; i <= ret && i < MBSSIZE; i++)
+	    {
+	      if (debug_flg)
+		{
+		  fprintf (stderr,
+			   "	: s[%d] = 0x%hx <-> 0x%hx = s_ex[%d]\n", i,
+			   s[i], s_ex[i], i);
+		}
+
+	      if (i == ret && ret == n)	/* no null termination */
+		{
+		  if (s[i] == MARK_VAL)
+		    {
+		      Result (C_SUCCESS, S_WCSRTOMBS, CASE_4, MS_PASSED);
+		    }
+		  else
+		    {
+		      err_count++;
+		      Result (C_FAILURE, S_WCSRTOMBS, CASE_4,
+			      "should not be null terminated "
+			      "(it may be a null char), but it is");
+		    }
+
+		  break;
+		}
+
+	      if (i == ret && ret < n)	/* null termination */
+		{
+		  if (s[i] == 0)
+		    {
+		      Result (C_SUCCESS, S_WCSRTOMBS, CASE_5, MS_PASSED);
+		    }
+		  else
+		    {
+		      err_count++;
+		      Result (C_FAILURE, S_WCSRTOMBS, CASE_5,
+			      "should be null terminated, but it is not");
+		    }
+
+		  break;
+		}
+
+	      if (s[i] != s_ex[i])
+		{
+		  err++;
+		  err_count++;
+		  Result (C_FAILURE, S_WCSRTOMBS, CASE_6,
+			  "converted string is different from an"
+			  " expected string");
+		  break;
+		}
+	    }
+
+	  if (!err)
+	    {
+	      Result (C_SUCCESS, S_WCSRTOMBS, CASE_6, MS_PASSED);
+	    }
+	}
+    }
+  }
+
+  return err_count;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wcsspn.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wcsspn.c
new file mode 100644
index 00000000..02157eec
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wcsspn.c
@@ -0,0 +1,38 @@
+/*
+  WCSSPN: size_t wcsspn (const wchar_t *ws1, const wchar_t *ws2);
+*/
+
+#define TST_FUNCTION wcsspn
+
+#include "tsp_common.c"
+#include "dat_wcsspn.c"
+
+int
+tst_wcsspn (FILE *fp, int debug_flg)
+{
+  TST_DECL_VARS (size_t);
+  wchar_t *ws1, *ws2;
+
+  TST_DO_TEST (wcsspn)
+  {
+    TST_HEAD_LOCALE (wcsspn, S_WCSSPN);
+    TST_DO_REC (wcsspn)
+    {
+      TST_GET_ERRET (wcsspn);
+      ws1 = TST_INPUT (wcsspn).ws1;
+      ws2 = TST_INPUT (wcsspn).ws2;	/* external value: size WCSSIZE */
+      ret = wcsspn (ws1, ws2);
+
+      if (debug_flg)
+	{
+	  fprintf (stderr, "wcsspn: ret = %zu\n", ret);
+	}
+
+      TST_IF_RETURN (S_WCSSPN)
+      {
+      };
+    }
+  }
+
+  return err_count;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wcsstr.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wcsstr.c
new file mode 100644
index 00000000..f8b00c4b
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wcsstr.c
@@ -0,0 +1,86 @@
+/*
+  WCSSTR: wchar_t *wcsstr (const wchar_t *ws1, const wchar_t *ws2);
+*/
+
+#define TST_FUNCTION wcsstr
+
+#include "tsp_common.c"
+#include "dat_wcsstr.c"
+
+int
+tst_wcsstr (FILE * fp, int debug_flg)
+{
+  TST_DECL_VARS (wchar_t *);
+  wchar_t *ws1, *ws2;
+  int err, i;
+
+  TST_DO_TEST (wcsstr)
+  {
+    TST_HEAD_LOCALE (wcsstr, S_WCSSTR);
+    TST_DO_REC (wcsstr)
+    {
+      TST_GET_ERRET (wcsstr);
+      ws1 = TST_INPUT (wcsstr).ws1;
+      ws2 = TST_INPUT (wcsstr).ws2;	/* external value: size WCSSIZE */
+      ret = wcsstr (ws1, ws2);
+
+      if (debug_flg)
+	{
+	  fprintf (stderr, "wcsstr: %d : ret = %s\n", rec + 1,
+		   (ret == NULL) ? "null" : "not null");
+	  if (ret)
+	    {
+	      fprintf (stderr,
+		       "	ret[ 0 ] = 0x%lx <-> 0x%lx = ws2[ 0 ]\n",
+		       (unsigned long int) ret[0], (unsigned long int) ws2[0]);
+	    }
+	}
+
+      TST_IF_RETURN (S_WCSSTR)
+      {
+	if (ws2[0] == 0)
+	  {
+	    if (ret == ws1)
+	      {
+		Result (C_SUCCESS, S_WCSSTR, CASE_3, MS_PASSED);
+	      }
+	    else
+	      {
+		err_count++;
+		Result (C_FAILURE, S_WCSSTR, CASE_3,
+			"return address is not same address as ws1");
+	      }
+
+	    continue;
+	  }
+
+	for (i = 0, err = 0; *(ws2 + i) != 0 && i < WCSSIZE; i++)
+	  {
+	    if (debug_flg)
+	      {
+		fprintf (stderr,
+			 "	: ret[ %d ] = 0x%lx <-> 0x%lx = ws2[ %d ]\n",
+			 i, (unsigned long int) ret[i],
+			 (unsigned long int) ws2[i], i);
+	      }
+
+	    if (ret[i] != ws2[i])
+	      {
+		err++;
+		err_count++;
+		Result (C_FAILURE, S_WCSSTR, CASE_4, "pointed sub-string is "
+			"different from an expected sub-string");
+		break;
+	      }
+	  }
+
+	if (!err)
+	  {
+	    Result (C_SUCCESS, S_WCSSTR, CASE_4, MS_PASSED);
+	  }
+      }
+    }
+  }
+
+  return err_count;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wcstod.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wcstod.c
new file mode 100644
index 00000000..1648d353
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wcstod.c
@@ -0,0 +1,69 @@
+/*
+  WCSTOD: double wcstod (wchar_t *np, const wchar_t **endp);
+*/
+
+#define TST_FUNCTION wcstod
+
+#include "tsp_common.c"
+#include "dat_wcstod.c"
+
+int
+tst_wcstod (FILE * fp, int debug_flg)
+{
+  TST_DECL_VARS (double);
+  wchar_t *np, *endp, fwc;
+  double val;
+
+  TST_DO_TEST (wcstod)
+  {
+    TST_HEAD_LOCALE (wcstod, S_WCSTOD);
+    TST_DO_REC (wcstod)
+    {
+      TST_GET_ERRET (wcstod);
+      np = TST_INPUT (wcstod).np;
+
+      TST_CLEAR_ERRNO;
+      ret = wcstod (np, &endp);
+      TST_SAVE_ERRNO;
+
+      if (debug_flg)
+	{
+	  fprintf (stdout, "wcstod() [ %s : %d ] ret  = %f\n", locale,
+		   rec + 1, ret);
+	  fprintf (stdout, "			  *endp = 0x%lx\n",
+		   (unsigned long int) *endp);
+	}
+
+      TST_IF_RETURN (S_WCSTOD)
+      {
+	if (ret != 0)
+	  {
+	    val = ret - TST_EXPECT (wcstod).val;
+	    if (TST_ABS (val) < TST_DBL_EPS)
+	      {
+		Result (C_SUCCESS, S_WCSTOD, CASE_3, MS_PASSED);
+	      }
+	    else
+	      {
+		err_count++;
+		Result (C_FAILURE, S_WCSTOD, CASE_3, "return value is wrong");
+	      }
+	  }
+      }
+
+      fwc = TST_EXPECT (wcstod).fwc;
+
+      if (fwc == *endp)
+	{
+	  Result (C_SUCCESS, S_WCSTOD, CASE_4, MS_PASSED);
+	}
+      else
+	{
+	  err_count++;
+	  Result (C_FAILURE, S_WCSTOD, CASE_4, "a final wc is wrong.");
+	}
+    }
+  }
+
+  return err_count;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wcstok.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wcstok.c
new file mode 100644
index 00000000..1222b978
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wcstok.c
@@ -0,0 +1,96 @@
+/*
+  WCSTOK: wchar_t *wcstok (wchar_t *ws, const wchar_t *dlm, wchar_t **pt);
+*/
+
+
+#define TST_FUNCTION wcstok
+
+#include "tsp_common.c"
+#include "dat_wcstok.c"
+
+int
+tst_wcstok (FILE * fp, int debug_flg)
+{
+  TST_DECL_VARS (wchar_t *);
+  char w_flg;
+  wchar_t *ws;
+  wchar_t *dt, *pt;
+  wchar_t *ws_ex;
+  int err, i;
+
+  TST_DO_TEST (wcstok)
+  {
+    TST_HEAD_LOCALE (wcstok, S_WCSTOK);
+    TST_DO_REC (wcstok)
+    {
+      TST_DO_SEQ (WCSTOK_SEQNUM)
+      {
+	TST_GET_ERRET_SEQ (wcstok);
+	w_flg = TST_INPUT_SEQ (wcstok).w_flg;
+	ws = (w_flg) ? TST_INPUT_SEQ (wcstok).ws : NULL;
+	dt = TST_INPUT_SEQ (wcstok).dt;
+
+	ret = wcstok (ws, dt, &pt);
+
+	if (debug_flg)
+	  {
+	    fprintf (stdout, "wcstok() [ %s : %d : %d ] *ret  = 0x%lx\n",
+		     locale, rec + 1, seq_num + 1, (unsigned long int) *ret);
+	    if (pt && *pt)
+	      {
+		fprintf (stdout, "			 *pt   = 0x%lx\n",
+			 (unsigned long int) *pt);
+	      }
+	  }
+
+	TST_IF_RETURN (S_WCSTOK)
+	{
+	};
+
+	if (ret != NULL)
+	  {
+	    ws_ex = TST_EXPECT_SEQ (wcstok).ws;
+
+	    /* XXX: REVISIT : insufficient conditions */
+	    for (err = 0, i = 0; i < WCSSIZE; i++)
+	      {
+		if (ret[i] == L'\0' && ws_ex[i] == L'\0')
+		  {
+		    break;
+		  }
+
+		if (debug_flg)
+		  {
+		    fprintf (stderr,
+			     "			      ret[%d] = 0x%lx <-> "
+			     "0x%lx = ws_ex[%d]\n",
+			     i, (unsigned long int) ret[i],
+			     (unsigned long int) ws_ex[i], i);
+		  }
+
+		if (ret[i] != ws_ex[i])
+		  {
+		    err++;
+		    err_count++;
+		    Result (C_FAILURE, S_WCSTOK, CASE_3,
+			    "the token is different from an expected string");
+		    break;
+		  }
+
+		if (ret[i] == L'\0' || ws_ex[i] == L'\0')
+		  {
+		    break;
+		  }
+	      }
+
+	    if (!err)
+	      {
+		Result (C_SUCCESS, S_WCSTOK, CASE_3, MS_PASSED);
+	      }
+	  }
+      }
+    }
+  }
+
+  return err_count;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wcstombs.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wcstombs.c
new file mode 100644
index 00000000..c0851a43
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wcstombs.c
@@ -0,0 +1,115 @@
+/*
+  WCSTOMBS: size_t wcstombs (char *s, const wchar_t *ws, size_t n)
+*/
+
+#define TST_FUNCTION wcstombs
+
+#include "tsp_common.c"
+#include "dat_wcstombs.c"
+
+#define MARK_VAL 0x01
+
+int
+tst_wcstombs (FILE * fp, int debug_flg)
+{
+  TST_DECL_VARS (size_t);
+  char s_flg, n;
+  wchar_t *ws;
+  char s[MBSSIZE], *s_in;
+  int err, i;
+  char *s_ex;
+
+  TST_DO_TEST (wcstombs)
+  {
+    TST_HEAD_LOCALE (wcstombs, S_WCSTOMBS);
+    TST_DO_REC (wcstombs)
+    {
+      TST_GET_ERRET (wcstombs);
+      memset (s, MARK_VAL, MBSSIZE);
+
+      s_flg = TST_INPUT (wcstombs).s_flg;
+      s_in = (s_flg == 1) ? s : (char *) NULL;
+      ws = TST_INPUT (wcstombs).ws;
+      n = TST_INPUT (wcstombs).n;
+
+      TST_CLEAR_ERRNO;
+      ret = wcstombs (s_in, ws, n);
+      TST_SAVE_ERRNO;
+
+      if (debug_flg)
+	{
+	  fprintf (stdout, "wcstombs: ret  = %zu\n", ret);
+	}
+
+      TST_IF_RETURN (S_WCSTOMBS)
+      {
+      };
+
+      if (s_in != NULL && ret != (size_t) - 1)
+	{
+	  /* No definition for s, when error occurs.  */
+	  s_ex = TST_EXPECT (wcstombs).s;
+
+	  for (err = 0, i = 0; i <= ret && i < MBSSIZE; i++)
+	    {
+	      if (debug_flg)
+		{
+		  fprintf (stdout,
+			   "	: s[%d] = 0x%hx <-> 0x%hx = s_ex[%d]\n", i,
+			   s[i], s_ex[i], i);
+		}
+
+	      if (i == ret && ret == n)	/* no null termination */
+		{
+		  if (s[i] == MARK_VAL)
+		    {
+		      Result (C_SUCCESS, S_WCSTOMBS, CASE_4, MS_PASSED);
+		    }
+		  else
+		    {
+		      err_count++;
+		      Result (C_FAILURE, S_WCSTOMBS, CASE_4,
+			      "should not be null terminated "
+			      "(it may be a null char), but it is");
+		    }
+
+		  break;
+		}
+
+	      if (i == ret && ret < n)	/* null termination */
+		{
+		  if (s[i] == 0)
+		    {
+		      Result (C_SUCCESS, S_WCSTOMBS, CASE_5, MS_PASSED);
+		    }
+		  else
+		    {
+		      err_count++;
+		      Result (C_FAILURE, S_WCSTOMBS, CASE_5,
+			      "should be null terminated, but it is not");
+		    }
+
+		  break;
+		}
+
+	      if (s[i] != s_ex[i])
+		{
+		  err++;
+		  err_count++;
+		  Result (C_FAILURE, S_WCSTOMBS, CASE_6,
+			  "converted string is different from an "
+			  "expected string");
+		  break;
+		}
+	    }
+
+	  if (!err)
+	    {
+	      Result (C_SUCCESS, S_WCSTOMBS, CASE_6, MS_PASSED);
+	    }
+	}
+    }
+  }
+
+  return err_count;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wcswidth.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wcswidth.c
new file mode 100644
index 00000000..c8369753
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wcswidth.c
@@ -0,0 +1,39 @@
+/*
+  WCSWIDTH: int wcswidth (const wchar_t *ws, size_t n);
+*/
+
+#define TST_FUNCTION wcswidth
+
+#include "tsp_common.c"
+#include "dat_wcswidth.c"
+
+int
+tst_wcswidth (FILE *fp, int debug_flg)
+{
+  TST_DECL_VARS (int);
+  wchar_t *ws;
+  int n;
+
+  TST_DO_TEST (wcswidth)
+  {
+    TST_HEAD_LOCALE (wcswidth, S_WCSWIDTH);
+    TST_DO_REC (wcswidth)
+    {
+      TST_GET_ERRET (wcswidth);
+      ws = TST_INPUT (wcswidth).ws;
+      n = TST_INPUT (wcswidth).n;
+      ret = wcswidth (ws, n);
+
+      if (debug_flg)
+	{
+	  fprintf (stderr, "wcswidth: [ %d ] : ret = %d\n", rec + 1, ret);
+	}
+
+      TST_IF_RETURN (S_WCSWIDTH)
+      {
+      };
+    }
+  }
+
+  return err_count;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wcsxfrm.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wcsxfrm.c
new file mode 100644
index 00000000..6fb8a1c2
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wcsxfrm.c
@@ -0,0 +1,122 @@
+/*
+  WCSXFRM: size_t wcsxfrm (wchar_t *ws1, const wchar_t *ws2, size_t n);
+*/
+
+#define TST_FUNCTION wcsxfrm
+
+#include "tsp_common.c"
+#include "dat_wcsxfrm.c"
+
+int
+tst_wcsxfrm (FILE * fp, int debug_flg)
+{
+  TST_DECL_VARS (size_t);
+  wchar_t *org1, *org2;
+  wchar_t frm1[MBSSIZE], frm2[MBSSIZE];
+  size_t n1, n2;
+  int ret_coll, ret_cmp;
+
+  TST_DO_TEST (wcsxfrm)
+  {
+    TST_HEAD_LOCALE (wcsxfrm, S_WCSXFRM);
+    TST_DO_REC (wcsxfrm)
+    {
+      TST_GET_ERRET (wcsxfrm);
+      org1 = TST_INPUT (wcsxfrm).org1;
+      org2 = TST_INPUT (wcsxfrm).org2;
+      n1 = TST_INPUT (wcsxfrm).n1;
+      n2 = TST_INPUT (wcsxfrm).n2;
+      if (n1 < 0 || sizeof (frm1) < n1 || sizeof (frm2) < n2)
+	{
+	  warn_count++;
+	  Result (C_IGNORED, S_WCSXFRM, CASE_9,
+		  "input data n1 or n2 is invalid");
+	  continue;
+	}
+
+      /* an errno and a return value are checked
+	 only for 2nd wcsxfrm() call.
+	 A result of 1st call is used to compare
+	 those 2 values by using wcscmp().
+       */
+
+      TST_CLEAR_ERRNO;
+      ret = wcsxfrm (frm1, org1, n1);	/* First call */
+      TST_SAVE_ERRNO;
+
+      if (debug_flg)
+	{
+	  fprintf (stdout, "tst_wcsxfrm() : REC = %d\n", rec + 1);
+	  fprintf (stdout, "tst_wcsxfrm() : 1st ret = %zu\n", ret);
+	}
+
+      if (ret == -1 || ret >= n1 || errno_save != 0)
+	{
+	  warn_count++;
+	  Result (C_INVALID, S_WCSXFRM, CASE_8,
+		  "got an error in fist wcsxfrm() call");
+	  continue;
+	}
+
+      TST_CLEAR_ERRNO;
+      /* Second call */
+      ret = wcsxfrm (((n2 == 0) ? NULL : frm2), org2, n2);
+      TST_SAVE_ERRNO;
+
+      TST_IF_RETURN (S_WCSXFRM)
+      {
+      };
+
+      if (n2 == 0 || ret >= n2 || errno != 0)
+	{
+#if 0
+	  warn_count++;
+	  Result (C_IGNORED, S_WCSXFRM, CASE_7, "did not get a result");
+#endif
+	  continue;
+	}
+
+      if (debug_flg)
+	{
+	  fprintf (stdout, "tst_wcsxfrm() : 2nd ret = %zu\n", ret);
+	}
+
+      /* wcscoll() */
+      TST_CLEAR_ERRNO;
+      /* depends on wcscoll() ... not good though ... */
+      ret_coll = wcscoll (org1, org2);
+      TST_SAVE_ERRNO;
+
+      if (errno != 0)		/* bugs * bugs may got correct results ... */
+	{
+	  warn_count++;
+	  Result (C_INVALID, S_WCSXFRM, CASE_6,
+		  "got an error in wcscoll() call");
+	  continue;
+	}
+      /* wcscmp() */
+      ret_cmp = wcscmp (frm1, frm2);
+
+      if ((ret_coll == ret_cmp) || (ret_coll > 0 && ret_cmp > 0)
+	  || (ret_coll < 0 && ret_cmp < 0))
+	{
+	  Result (C_SUCCESS, S_WCSXFRM, CASE_3,
+		  MS_PASSED " (depends on wcscoll & wcscmp)");
+	}
+      else
+	{
+	  err_count++;
+	  Result (C_FAILURE, S_WCSXFRM, CASE_3,
+		  "results from wcscoll & wcscmp() do not match");
+	}
+
+      if (debug_flg)
+	{
+	  fprintf (stdout, "tst_wcsxfrm() : coll = %d <-> %d = cmp\n",
+		   ret_coll, ret_cmp);
+	}
+    }
+  }
+
+  return err_count;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wctob.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wctob.c
new file mode 100644
index 00000000..2377daf5
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wctob.c
@@ -0,0 +1,37 @@
+/*-------------------------------------------------------------------------------------*/
+/* WCTOB: int wctob( wint_t wc )						       */
+/*-------------------------------------------------------------------------------------*/
+
+#define TST_FUNCTION wctob
+
+#include "tsp_common.c"
+#include "dat_wctob.c"
+
+int
+tst_wctob (FILE * fp, int debug_flg)
+{
+  TST_DECL_VARS (int);
+  wchar_t wc;
+
+  TST_DO_TEST (wctob)
+  {
+    TST_HEAD_LOCALE (wctob, S_WCTOB);
+    TST_DO_REC (wctob)
+    {
+      TST_GET_ERRET (wctob);
+      wc = TST_INPUT (wctob).wc;
+      ret = wctob (wc);
+
+      if (debug_flg)
+	{
+	  fprintf (stderr, "tst_wctob : [ %d ] ret = %d\n", rec + 1, ret);
+	}
+
+      TST_IF_RETURN (S_WCTOB)
+      {
+      };
+    }
+  }
+
+  return err_count;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wctomb.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wctomb.c
new file mode 100644
index 00000000..aea89fed
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wctomb.c
@@ -0,0 +1,99 @@
+/*
+  WCTOMB: int wctomb (char *s, wchar_t wc)
+*/
+
+#define TST_FUNCTION wctomb
+
+#include "tsp_common.c"
+#include "dat_wctomb.c"
+
+int
+tst_wctomb (FILE * fp, int debug_flg)
+{
+  TST_DECL_VARS (int);
+  wchar_t wc;
+  char s[MBSSIZE], *s_in, *s_ex;
+  int err, i;
+
+  TST_DO_TEST (wctomb)
+  {
+    TST_HEAD_LOCALE (wctomb, S_WCTOMB);
+    TST_DO_REC (wctomb)
+    {
+      TST_GET_ERRET (wctomb);
+      wc = TST_INPUT (wctomb).wc;
+      s_in = ((TST_INPUT (wctomb).s_flg) == 0) ? (char *) NULL : s;
+      ret = wctomb (s_in, wc);
+
+      if (debug_flg)
+	{
+	  fprintf (stdout, "wctomb() [ %s : %d ] ret  = %d\n", locale,
+		   rec + 1, ret);
+	}
+
+      TST_IF_RETURN (S_WCTOMB)
+      {
+	if (s_in == NULL)	/* state dependency */
+	  {
+	    if (ret_exp == +1)	/* state-dependent  */
+	      {
+		if (ret != 0)
+		  {
+		    /* Non-zero means state-dependent encoding.	 */
+		    Result (C_SUCCESS, S_WCTOMB, CASE_3, MS_PASSED);
+		  }
+		else
+		  {
+		    err_count++;
+		    Result (C_FAILURE, S_WCTOMB, CASE_3,
+			    "should be state-dependent encoding, "
+			    "but a return value shows it is "
+			    "state-independent");
+		  }
+	      }
+
+	    if (ret_exp == 0)	/* state-independent */
+	      {
+		if (ret == 0)
+		  {
+		    /* Non-zero means state-dependent encoding.	 */
+		    Result (C_SUCCESS, S_WCTOMB, CASE_3, MS_PASSED);
+		  }
+		else
+		  {
+		    err_count++;
+		    Result (C_FAILURE, S_WCTOMB, CASE_3,
+			    "should be state-independent encoding, "
+			    "but a return value shows it is state-dependent");
+		  }
+	      }
+	  }
+      }
+
+      s_ex = TST_EXPECT (wctomb).s;
+
+      if (s_in)
+	{
+	  for (i = 0, err = 0; *(s_ex + i) != 0 && i < MBSSIZE; i++)
+	    {
+	      if (s_in[i] != s_ex[i])
+		{
+		  err++;
+		  err_count++;
+		  Result (C_FAILURE, S_WCTOMB, CASE_4,
+			  "copied string is different from an"
+			  " expected string");
+		  break;
+		}
+	    }
+
+	  if (!err)
+	    {
+	      Result (C_SUCCESS, S_WCTOMB, CASE_4, MS_PASSED);
+	    }
+	}
+    }
+  }
+
+  return err_count;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wctrans.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wctrans.c
new file mode 100644
index 00000000..b422d6ff
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wctrans.c
@@ -0,0 +1,52 @@
+/*
+  WCTRANS: wctrans_t wctrans (const char *charclass);
+*/
+
+#define TST_FUNCTION wctrans
+
+#include "tsp_common.c"
+#include "dat_wctrans.c"
+
+int
+tst_wctrans (FILE * fp, int debug_flg)
+{
+  TST_DECL_VARS (wctrans_t);
+  char *class;
+
+  TST_DO_TEST (wctrans)
+  {
+    TST_HEAD_LOCALE (wctrans, S_WCTRANS);
+    TST_DO_REC (wctrans)
+    {
+      TST_GET_ERRET (wctrans);
+      class = TST_INPUT (wctrans).class;
+
+      TST_CLEAR_ERRNO;
+      ret = wctrans (class);
+      TST_SAVE_ERRNO;
+
+      if (debug_flg)
+	{
+	  fprintf (stderr, "tst_wctrans : [ %d ] ret = %ld\n", rec + 1,
+		   (long int) ret);
+	  fprintf (stderr, "		       errno = %d\n", errno_save);
+	}
+
+      TST_IF_RETURN (S_WCTRANS)
+      {
+	if (ret != 0)
+	  {
+	    Result (C_SUCCESS, S_WCTYPE, CASE_3, MS_PASSED);
+	  }
+	else
+	  {
+	    err_count++;
+	    Result (C_FAILURE, S_WCTYPE, CASE_3,
+		    "should return non-0, but returned 0");
+	  }
+      }
+    }
+  }
+
+  return err_count;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wctype.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wctype.c
new file mode 100644
index 00000000..a203e490
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wctype.c
@@ -0,0 +1,48 @@
+/*
+  WCTYPE: wctype_t wctype (const char *class);
+*/
+
+
+#define TST_FUNCTION wctype
+
+#include "tsp_common.c"
+#include "dat_wctype.c"
+
+int
+tst_wctype (FILE * fp, int debug_flg)
+{
+  TST_DECL_VARS (wctype_t);
+  char *class;
+
+  TST_DO_TEST (wctype)
+  {
+    TST_HEAD_LOCALE (wctype, S_WCTYPE);
+    TST_DO_REC (wctype)
+    {
+      TST_GET_ERRET (wctype);
+      class = TST_INPUT (wctype).class;
+      ret = wctype (class);
+
+      if (debug_flg)
+	{
+	  fprintf (stderr, "tst_wctype : [ %d ] ret = %ld\n", rec + 1, ret);
+	}
+
+      TST_IF_RETURN (S_WCTYPE)
+      {
+	if (ret != 0)
+	  {
+	    Result (C_SUCCESS, S_WCTYPE, CASE_3, MS_PASSED);
+	  }
+	else
+	  {
+	    err_count++;
+	    Result (C_FAILURE, S_WCTYPE, CASE_3,
+		    "should return non-0, but returned 0");
+	  }
+      }
+    }
+  }
+
+  return err_count;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wcwidth.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wcwidth.c
new file mode 100644
index 00000000..6a5af6fa
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale-mbwc/tst_wcwidth.c
@@ -0,0 +1,38 @@
+/*
+  WCWIDTH: int wcwidth (wchar_t wc);
+*/
+
+#define TST_FUNCTION wcwidth
+
+#include "tsp_common.c"
+#include "dat_wcwidth.c"
+
+int
+tst_wcwidth (FILE * fp, int debug_flg)
+{
+  TST_DECL_VARS (int);
+  wchar_t wc;
+
+  TST_DO_TEST (wcwidth)
+  {
+    TST_HEAD_LOCALE (wcwidth, S_WCWIDTH);
+    TST_DO_REC (wcwidth)
+    {
+      TST_GET_ERRET (wcwidth);
+      wc = TST_INPUT (wcwidth).wc;
+      ret = wcwidth (wc);
+
+      if (debug_flg)
+	{
+	  fprintf (stdout, "wcwidth() [ %s : %d ] ret  = %d\n", locale,
+		   rec + 1, ret);
+	}
+
+      TST_IF_RETURN (S_WCWIDTH)
+      {
+      }
+    }
+  }
+
+  return err_count;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/Makefile
new file mode 100644
index 00000000..771c3d11
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/Makefile
@@ -0,0 +1,7 @@
+# uClibc locale tests
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+
+top_builddir=../../
+include ../Rules.mak
+-include Makefile.in
+include ../Test.mak
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/Makefile.in
new file mode 100644
index 00000000..5a57ca54
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/Makefile.in
@@ -0,0 +1,29 @@
+# uClibc locale tests
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+#	 tst_mbtowc tst_strcoll tst_strfmon tst_strxfrm    \
+
+TESTS := bug-iconv-trans bug-usesetlocale collate-test dump-ctype \
+	 gen-unicode-ctype show-ucs-data tst-ctype \
+	 tst-digits tst-fmon tst-langinfo tst-leaks tst-mbswcs1 \
+	 tst-mbswcs2 tst-mbswcs3 tst-mbswcs4 tst-mbswcs5 tst-mbswcs6 \
+	 tst_nl_langinfo tst-numeric tst-rpmatch tst-setlocale \
+	 tst-sscanf tst-strfmon1 tst-trans tst-wctype tst-xlocale1 \
+	 tst-xlocale2 xfrm-test
+
+
+# NOTE: For now disabled some tests that are known not build
+TESTS_DISABLED := tst-ctype tst-fmon tst-leaks tst-rpmatch tst-strfmon1
+
+ifneq ($(UCLIBC_HAS_XLOCALE),y)
+TESTS_DISABLED += bug-usesetlocale tst-xlocale1 tst-xlocale2 xfrm-test tst-C-locale
+endif
+
+DODIFF_rint     := 1
+
+EXTRA_CFLAGS    := -D__USE_GNU -fno-builtin
+
+OPTS_dump-ctype = C
+OPTS_tst-ctype = < tst-ctype-de_DE.ISO-8859-1.in
+OPTS_tst-langinfo = < tst-langinfo.input
+
+EXTRA_DIRS := C
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/bug-iconv-trans.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/bug-iconv-trans.c
new file mode 100644
index 00000000..3886247c
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/bug-iconv-trans.c
@@ -0,0 +1,68 @@
+#include 
+#include 
+#include 
+#include 
+
+int
+main (void)
+{
+  iconv_t cd;
+  const char str[] = "ÄäÖöÜüß";
+  const char expected[] = "AEaeOEoeUEuess";
+  char *inptr = (char *) str;
+  size_t inlen = strlen (str) + 1;
+  char outbuf[500];
+  char *outptr = outbuf;
+  size_t outlen = sizeof (outbuf);
+  int result = 0;
+  size_t n;
+
+  if (setlocale (LC_ALL, "de_DE.UTF-8") == NULL)
+    {
+      puts ("setlocale failed");
+      return 1;
+    }
+
+  cd = iconv_open ("ANSI_X3.4-1968//TRANSLIT", "ISO-8859-1");
+  if (cd == (iconv_t) -1)
+    {
+      puts ("iconv_open failed");
+      return 1;
+    }
+
+  n = iconv (cd, &inptr, &inlen, &outptr, &outlen);
+  if (n != 7)
+    {
+      if (n == (size_t) -1)
+	printf ("iconv() returned error: %m\n");
+      else
+	printf ("iconv() returned %Zd, expected 7\n", n);
+      result = 1;
+    }
+  if (inlen != 0)
+    {
+      puts ("not all input consumed");
+      result = 1;
+    }
+  else if (inptr - str != strlen (str) + 1)
+    {
+      printf ("inptr wrong, advanced by %td\n", inptr - str);
+      result = 1;
+    }
+  if (memcmp (outbuf, expected, sizeof (expected)) != 0)
+    {
+      printf ("result wrong: \"%.*s\", expected: \"%s\"\n",
+	      (int) (sizeof (outbuf) - outlen), outbuf, expected);
+      result = 1;
+    }
+  else if (outlen != sizeof (outbuf) - sizeof (expected))
+    {
+      printf ("outlen wrong: %Zd, expected %Zd\n", outlen,
+	      sizeof (outbuf) - 15);
+      result = 1;
+    }
+  else
+    printf ("output is \"%s\" which is OK\n", outbuf);
+
+  return result;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/bug-usesetlocale.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/bug-usesetlocale.c
new file mode 100644
index 00000000..0637067d
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/bug-usesetlocale.c
@@ -0,0 +1,38 @@
+/* Test case for setlocale vs uselocale (LC_GLOBAL_LOCALE) bug.  */
+
+#define _GNU_SOURCE 1
+#include 
+#include 
+#include 
+
+static int
+do_test (void)
+{
+  __locale_t loc_new, loc_old;
+
+  int first = !!isalpha(0xE4);
+
+  setlocale (LC_ALL, "de_DE");
+
+  int global_de = !!isalpha(0xE4);
+
+  loc_new = newlocale (1 << LC_ALL, "C", 0);
+  loc_old = uselocale (loc_new);
+
+  int used_c = !!isalpha(0xE4);
+
+  uselocale (loc_old);
+
+  int used_global = !!isalpha(0xE4);
+
+  printf ("started %d, after setlocale %d\n", first, global_de);
+  printf ("after uselocale %d, after LC_GLOBAL_LOCALE %d\n",
+	  used_c, used_global);
+
+  freelocale (loc_new);
+  return !(used_c == first && used_global == global_de);
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/collate-test.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/collate-test.c
new file mode 100644
index 00000000..e8f43218
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/collate-test.c
@@ -0,0 +1,133 @@
+/* Test collation function using real data.
+   Copyright (C) 1997, 1999, 2000, 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 1997.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+struct lines
+{
+  char *key;
+  char *line;
+};
+
+static int xstrcoll (const void *, const void *);
+
+int
+main (int argc, char *argv[])
+{
+  int result = 0;
+  size_t nstrings, nstrings_max;
+  struct lines *strings;
+  char *line = NULL;
+  size_t len = 0;
+  size_t n;
+
+  if (argc < 2)
+    error (1, 0, "usage: %s ", argv[0]);
+
+  setlocale (LC_ALL, "");
+
+  nstrings_max = 100;
+  nstrings = 0;
+  strings = (struct lines *) malloc (nstrings_max * sizeof (struct lines));
+  if (strings == NULL)
+    {
+      perror (argv[0]);
+      exit (1);
+    }
+
+  while (1)
+    {
+      int l;
+      if (getline (&line, &len, stdin) < 0)
+	break;
+
+      if (nstrings == nstrings_max)
+	{
+	  strings = (struct lines *) realloc (strings,
+					      (nstrings_max *= 2)
+					       * sizeof (*strings));
+	  if (strings == NULL)
+	    {
+	      perror (argv[0]);
+	      exit (1);
+	    }
+	}
+      strings[nstrings].line = strdup (line);
+      l = strcspn (line, ":(;");
+      while (l > 0 && isspace (line[l - 1]))
+	--l;
+      strings[nstrings].key = strndup (line, l);
+      ++nstrings;
+    }
+  free (line);
+
+  /* First shuffle.  */
+  srandom (atoi (argv[1]));
+  for (n = 0; n < 10 * nstrings; ++n)
+    {
+      int r1, r2, r;
+      size_t idx1 = random () % nstrings;
+      size_t idx2 = random () % nstrings;
+      struct lines tmp = strings[idx1];
+      strings[idx1] = strings[idx2];
+      strings[idx2] = tmp;
+
+      /* While we are at it a first little test.  */
+      r1 = strcoll (strings[idx1].key, strings[idx2].key);
+      r2 = strcoll (strings[idx2].key, strings[idx1].key);
+      r = r1 * r2;
+
+      if (r > 0 || (r == 0 && r1 != 0) || (r == 0 && r2 != 0))
+	printf ("`%s' and `%s' collate wrong: %d vs. %d\n",
+		strings[idx1].key, strings[idx2].key, r1, r2);
+    }
+
+  /* Now sort.  */
+  qsort (strings, nstrings, sizeof (struct lines), xstrcoll);
+
+  /* Print the result.  */
+  for (n = 0; n < nstrings; ++n)
+    {
+      fputs (strings[n].line, stdout);
+      free (strings[n].line);
+      free (strings[n].key);
+    }
+  free (strings);
+
+  return result;
+}
+
+
+static int
+xstrcoll (ptr1, ptr2)
+     const void *ptr1;
+     const void *ptr2;
+{
+  const struct lines *l1 = (const struct lines *) ptr1;
+  const struct lines *l2 = (const struct lines *) ptr2;
+
+  return strcoll (l1->key, l2->key);
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/dump-ctype.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/dump-ctype.c
new file mode 100644
index 00000000..a1f24c65
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/dump-ctype.c
@@ -0,0 +1,164 @@
+/* Dump the character classes and character maps of a locale to a bunch
+   of individual files which can be processed with diff, sed etc.
+   Copyright (C) 2000 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Bruno Haible , 2000.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+/* Usage example:
+     $ dump-ctype de_DE.UTF-8
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+static const char *program_name = "dump-ctype";
+static const char *locale;
+
+static const char *class_names[] =
+  {
+    "alnum", "alpha", "blank", "cntrl", "digit", "graph", "lower",
+    "print", "punct", "space", "upper", "xdigit"
+  };
+
+static const char *map_names[] =
+  {
+    "tolower", "toupper", "totitle"
+  };
+
+static void dump_class (const char *class_name)
+{
+  wctype_t class;
+  FILE *f;
+  unsigned int ch;
+
+  class = wctype (class_name);
+  if (class == (wctype_t) 0)
+    {
+      fprintf (stderr, "%s %s: noexistent class %s\n", program_name,
+	       locale, class_name);
+      return;
+    }
+
+  f = fopen (class_name, "w");
+  if (f == NULL)
+    {
+      fprintf (stderr, "%s %s: cannot open file %s/%s\n", program_name,
+	       locale, locale, class_name);
+      exit (1);
+    }
+
+  for (ch = 0; ch < 0x10000; ch++)
+    if (iswctype (ch, class))
+      fprintf (f, "0x%04X\n", ch);
+
+  if (ferror (f) || fclose (f))
+    {
+      fprintf (stderr, "%s %s: I/O error on file %s/%s\n", program_name,
+	       locale, locale, class_name);
+      exit (1);
+    }
+}
+
+static void dump_map (const char *map_name)
+{
+  wctrans_t map;
+  FILE *f;
+  unsigned int ch;
+
+  map = wctrans (map_name);
+  if (map == (wctrans_t) 0)
+    {
+      fprintf (stderr, "%s %s: noexistent map %s\n", program_name,
+	       locale, map_name);
+      return;
+    }
+
+  f = fopen (map_name, "w");
+  if (f == NULL)
+    {
+      fprintf (stderr, "%s %s: cannot open file %s/%s\n", program_name,
+	       locale, locale, map_name);
+      exit (1);
+    }
+
+  for (ch = 0; ch < 0x10000; ch++)
+    if (towctrans (ch, map) != ch)
+      fprintf (f, "0x%04X\t0x%04X\n", ch, towctrans (ch, map));
+
+  if (ferror (f) || fclose (f))
+    {
+      fprintf (stderr, "%s %s: I/O error on file %s/%s\n", program_name,
+	       locale, locale, map_name);
+      exit (1);
+    }
+}
+
+int
+main (int argc, char *argv[])
+{
+  size_t i;
+
+  if (argc != 2)
+    {
+      fprintf (stderr, "Usage: dump-ctype locale\n");
+      exit (1);
+    }
+  locale = argv[1];
+
+  if (setlocale (LC_ALL, locale) == NULL)
+    {
+      fprintf (stderr, "%s: setlocale cannot switch to locale %s\n",
+	       program_name, locale);
+      exit (1);
+    }
+
+  if (mkdir (locale, 0777) < 0)
+    {
+      char buf[100];
+      int save_errno = errno;
+
+      sprintf (buf, "%s: cannot create directory %s", program_name, locale);
+      errno = save_errno;
+      perror (buf);
+      exit (1);
+    }
+
+  if (chdir (locale) < 0)
+    {
+      char buf[100];
+      int save_errno = errno;
+
+      sprintf (buf, "%s: cannot chdir to %s", program_name, locale);
+      errno = save_errno;
+      perror (buf);
+      exit (1);
+    }
+
+  for (i = 0; i < sizeof (class_names) / sizeof (class_names[0]); i++)
+    dump_class (class_names[i]);
+
+  for (i = 0; i < sizeof (map_names) / sizeof (map_names[0]); i++)
+    dump_map (map_names[i]);
+
+  return 0;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/gen-unicode-ctype.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/gen-unicode-ctype.c
new file mode 100644
index 00000000..849f272e
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/gen-unicode-ctype.c
@@ -0,0 +1,785 @@
+/* Generate a Unicode conforming LC_CTYPE category from a UnicodeData file.
+   Copyright (C) 2000-2001 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Bruno Haible , 2000.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+/* Usage example:
+     $ gen-unicode /usr/local/share/Unidata/UnicodeData.txt 3.1
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/* This structure represents one line in the UnicodeData.txt file.  */
+struct unicode_attribute
+{
+  const char *name;           /* Character name */
+  const char *category;       /* General category */
+  const char *combining;      /* Canonical combining classes */
+  const char *bidi;           /* Bidirectional category */
+  const char *decomposition;  /* Character decomposition mapping */
+  const char *decdigit;       /* Decimal digit value */
+  const char *digit;          /* Digit value */
+  const char *numeric;        /* Numeric value */
+  int mirrored;               /* mirrored */
+  const char *oldname;        /* Old Unicode 1.0 name */
+  const char *comment;        /* Comment */
+  unsigned int upper;         /* Uppercase mapping */
+  unsigned int lower;         /* Lowercase mapping */
+  unsigned int title;         /* Titlecase mapping */
+};
+
+/* Missing fields are represented with "" for strings, and NONE for
+   characters.  */
+#define NONE (~(unsigned int)0)
+
+/* The entire contents of the UnicodeData.txt file.  */
+struct unicode_attribute unicode_attributes [0x110000];
+
+/* Stores in unicode_attributes[i] the values from the given fields.  */
+static void
+fill_attribute (unsigned int i,
+		const char *field1, const char *field2,
+		const char *field3, const char *field4,
+		const char *field5, const char *field6,
+		const char *field7, const char *field8,
+		const char *field9, const char *field10,
+		const char *field11, const char *field12,
+		const char *field13, const char *field14)
+{
+  struct unicode_attribute * uni;
+
+  if (i >= 0x110000)
+    {
+      fprintf (stderr, "index too large\n");
+      exit (1);
+    }
+  if (strcmp (field2, "Cs") == 0)
+    /* Surrogates are UTF-16 artefacts, not real characters. Ignore them.  */
+    return;
+  uni = &unicode_attributes[i];
+  /* Copy the strings.  */
+  uni->name          = strdup (field1);
+  uni->category      = (field2[0] == '\0' ? "" : strdup (field2));
+  uni->combining     = (field3[0] == '\0' ? "" : strdup (field3));
+  uni->bidi          = (field4[0] == '\0' ? "" : strdup (field4));
+  uni->decomposition = (field5[0] == '\0' ? "" : strdup (field5));
+  uni->decdigit      = (field6[0] == '\0' ? "" : strdup (field6));
+  uni->digit         = (field7[0] == '\0' ? "" : strdup (field7));
+  uni->numeric       = (field8[0] == '\0' ? "" : strdup (field8));
+  uni->mirrored      = (field9[0] == 'Y');
+  uni->oldname       = (field10[0] == '\0' ? "" : strdup (field10));
+  uni->comment       = (field11[0] == '\0' ? "" : strdup (field11));
+  uni->upper = (field12[0] =='\0' ? NONE : strtoul (field12, NULL, 16));
+  uni->lower = (field13[0] =='\0' ? NONE : strtoul (field13, NULL, 16));
+  uni->title = (field14[0] =='\0' ? NONE : strtoul (field14, NULL, 16));
+}
+
+/* Maximum length of a field in the UnicodeData.txt file.  */
+#define FIELDLEN 120
+
+/* Reads the next field from STREAM.  The buffer BUFFER has size FIELDLEN.
+   Reads up to (but excluding) DELIM.
+   Returns 1 when a field was successfully read, otherwise 0.  */
+static int
+getfield (FILE *stream, char *buffer, int delim)
+{
+  int count = 0;
+  int c;
+
+  for (; (c = getc (stream)), (c != EOF && c != delim); )
+    {
+      /* The original unicode.org UnicodeData.txt file happens to have
+	 CR/LF line terminators.  Silently convert to LF.  */
+      if (c == '\r')
+	continue;
+
+      /* Put c into the buffer.  */
+      if (++count >= FIELDLEN - 1)
+	{
+	  fprintf (stderr, "field too long\n");
+	  exit (1);
+	}
+      *buffer++ = c;
+    }
+
+  if (c == EOF)
+    return 0;
+
+  *buffer = '\0';
+  return 1;
+}
+
+/* Stores in unicode_attributes[] the entire contents of the UnicodeData.txt
+   file.  */
+static void
+fill_attributes (const char *unicodedata_filename)
+{
+  unsigned int i, j;
+  FILE *stream;
+  char field0[FIELDLEN];
+  char field1[FIELDLEN];
+  char field2[FIELDLEN];
+  char field3[FIELDLEN];
+  char field4[FIELDLEN];
+  char field5[FIELDLEN];
+  char field6[FIELDLEN];
+  char field7[FIELDLEN];
+  char field8[FIELDLEN];
+  char field9[FIELDLEN];
+  char field10[FIELDLEN];
+  char field11[FIELDLEN];
+  char field12[FIELDLEN];
+  char field13[FIELDLEN];
+  char field14[FIELDLEN];
+  int lineno = 0;
+
+  for (i = 0; i < 0x110000; i++)
+    unicode_attributes[i].name = NULL;
+
+  stream = fopen (unicodedata_filename, "r");
+  if (stream == NULL)
+    {
+      fprintf (stderr, "error during fopen of '%s'\n", unicodedata_filename);
+      exit (1);
+    }
+
+  for (;;)
+    {
+      int n;
+
+      lineno++;
+      n = getfield (stream, field0, ';');
+      n += getfield (stream, field1, ';');
+      n += getfield (stream, field2, ';');
+      n += getfield (stream, field3, ';');
+      n += getfield (stream, field4, ';');
+      n += getfield (stream, field5, ';');
+      n += getfield (stream, field6, ';');
+      n += getfield (stream, field7, ';');
+      n += getfield (stream, field8, ';');
+      n += getfield (stream, field9, ';');
+      n += getfield (stream, field10, ';');
+      n += getfield (stream, field11, ';');
+      n += getfield (stream, field12, ';');
+      n += getfield (stream, field13, ';');
+      n += getfield (stream, field14, '\n');
+      if (n == 0)
+	break;
+      if (n != 15)
+	{
+	  fprintf (stderr, "short line in'%s':%d\n",
+		   unicodedata_filename, lineno);
+	  exit (1);
+	}
+      i = strtoul (field0, NULL, 16);
+      if (field1[0] == '<'
+	  && strlen (field1) >= 9
+	  && !strcmp (field1 + strlen(field1) - 8, ", First>"))
+	{
+	  /* Deal with a range. */
+	  lineno++;
+	  n = getfield (stream, field0, ';');
+	  n += getfield (stream, field1, ';');
+	  n += getfield (stream, field2, ';');
+	  n += getfield (stream, field3, ';');
+	  n += getfield (stream, field4, ';');
+	  n += getfield (stream, field5, ';');
+	  n += getfield (stream, field6, ';');
+	  n += getfield (stream, field7, ';');
+	  n += getfield (stream, field8, ';');
+	  n += getfield (stream, field9, ';');
+	  n += getfield (stream, field10, ';');
+	  n += getfield (stream, field11, ';');
+	  n += getfield (stream, field12, ';');
+	  n += getfield (stream, field13, ';');
+	  n += getfield (stream, field14, '\n');
+	  if (n != 15)
+	    {
+	      fprintf (stderr, "missing end range in '%s':%d\n",
+		       unicodedata_filename, lineno);
+	      exit (1);
+	    }
+	  if (!(field1[0] == '<'
+		&& strlen (field1) >= 8
+		&& !strcmp (field1 + strlen (field1) - 7, ", Last>")))
+	    {
+	      fprintf (stderr, "missing end range in '%s':%d\n",
+		       unicodedata_filename, lineno);
+	      exit (1);
+	    }
+	  field1[strlen (field1) - 7] = '\0';
+	  j = strtoul (field0, NULL, 16);
+	  for (; i <= j; i++)
+	    fill_attribute (i, field1+1, field2, field3, field4, field5,
+			       field6, field7, field8, field9, field10,
+			       field11, field12, field13, field14);
+	}
+      else
+	{
+	  /* Single character line */
+	  fill_attribute (i, field1, field2, field3, field4, field5,
+			     field6, field7, field8, field9, field10,
+			     field11, field12, field13, field14);
+	}
+    }
+  if (ferror (stream) || fclose (stream))
+    {
+      fprintf (stderr, "error reading from '%s'\n", unicodedata_filename);
+      exit (1);
+    }
+}
+
+/* Character mappings.  */
+
+static unsigned int
+to_upper (unsigned int ch)
+{
+  if (unicode_attributes[ch].name != NULL
+      && unicode_attributes[ch].upper != NONE)
+    return unicode_attributes[ch].upper;
+  else
+    return ch;
+}
+
+static unsigned int
+to_lower (unsigned int ch)
+{
+  if (unicode_attributes[ch].name != NULL
+      && unicode_attributes[ch].lower != NONE)
+    return unicode_attributes[ch].lower;
+  else
+    return ch;
+}
+
+static unsigned int
+to_title (unsigned int ch)
+{
+  if (unicode_attributes[ch].name != NULL
+      && unicode_attributes[ch].title != NONE)
+    return unicode_attributes[ch].title;
+  else
+    return ch;
+}
+
+/* Character class properties.  */
+
+static bool
+is_upper (unsigned int ch)
+{
+  return (to_lower (ch) != ch);
+}
+
+static bool
+is_lower (unsigned int ch)
+{
+  return (to_upper (ch) != ch)
+	 /*  is lowercase, but without simple to_upper mapping.  */
+	 || (ch == 0x00DF);
+}
+
+static bool
+is_alpha (unsigned int ch)
+{
+  return (unicode_attributes[ch].name != NULL
+	  && ((unicode_attributes[ch].category[0] == 'L'
+	       /* Theppitak Karoonboonyanan  says
+		  ,  should belong to is_punct.  */
+	       && (ch != 0x0E2F) && (ch != 0x0E46))
+	      /* Theppitak Karoonboonyanan  says
+		 , .., .. are is_alpha.  */
+	      || (ch == 0x0E31)
+	      || (ch >= 0x0E34 && ch <= 0x0E3A)
+	      || (ch >= 0x0E47 && ch <= 0x0E4E)
+	      /* Avoid warning for .  */
+	      || (ch == 0x0345)
+	      /* Avoid warnings for ...  */
+	      || (unicode_attributes[ch].category[0] == 'N'
+		  && unicode_attributes[ch].category[1] == 'l')
+	      /* Avoid warnings for ...  */
+	      || (unicode_attributes[ch].category[0] == 'S'
+		  && unicode_attributes[ch].category[1] == 'o'
+		  && strstr (unicode_attributes[ch].name, " LETTER ")
+		     != NULL)
+	      /* Consider all the non-ASCII digits as alphabetic.
+		 ISO C 99 forbids us to have them in category "digit",
+		 but we want iswalnum to return true on them.  */
+	      || (unicode_attributes[ch].category[0] == 'N'
+		  && unicode_attributes[ch].category[1] == 'd'
+		  && !(ch >= 0x0030 && ch <= 0x0039))));
+}
+
+static bool
+is_digit (unsigned int ch)
+{
+#if 0
+  return (unicode_attributes[ch].name != NULL
+	  && unicode_attributes[ch].category[0] == 'N'
+	  && unicode_attributes[ch].category[1] == 'd');
+  /* Note: U+0BE7..U+0BEF and U+1369..U+1371 are digit systems without
+     a zero.  Must add <0> in front of them by hand.  */
+#else
+  /* SUSV2 gives us some freedom for the "digit" category, but ISO C 99
+     takes it away:
+     7.25.2.1.5:
+        The iswdigit function tests for any wide character that corresponds
+        to a decimal-digit character (as defined in 5.2.1).
+     5.2.1:
+        the 10 decimal digits 0 1 2 3 4 5 6 7 8 9
+   */
+  return (ch >= 0x0030 && ch <= 0x0039);
+#endif
+}
+
+static bool
+is_outdigit (unsigned int ch)
+{
+  return (ch >= 0x0030 && ch <= 0x0039);
+}
+
+static bool
+is_blank (unsigned int ch)
+{
+  return (ch == 0x0009 /* '\t' */
+	  /* Category Zs without mention of "" */
+	  || (unicode_attributes[ch].name != NULL
+	      && unicode_attributes[ch].category[0] == 'Z'
+	      && unicode_attributes[ch].category[1] == 's'
+	      && !strstr (unicode_attributes[ch].decomposition, "")));
+}
+
+static bool
+is_space (unsigned int ch)
+{
+  /* Don't make U+00A0 a space. Non-breaking space means that all programs
+     should treat it like a punctuation character, not like a space. */
+  return (ch == 0x0020 /* ' ' */
+	  || ch == 0x000C /* '\f' */
+	  || ch == 0x000A /* '\n' */
+	  || ch == 0x000D /* '\r' */
+	  || ch == 0x0009 /* '\t' */
+	  || ch == 0x000B /* '\v' */
+	  /* Categories Zl, Zp, and Zs without mention of "" */
+	  || (unicode_attributes[ch].name != NULL
+	      && unicode_attributes[ch].category[0] == 'Z'
+	      && (unicode_attributes[ch].category[1] == 'l'
+		  || unicode_attributes[ch].category[1] == 'p'
+		  || (unicode_attributes[ch].category[1] == 's'
+		      && !strstr (unicode_attributes[ch].decomposition,
+				  "")))));
+}
+
+static bool
+is_cntrl (unsigned int ch)
+{
+  return (unicode_attributes[ch].name != NULL
+	  && (!strcmp (unicode_attributes[ch].name, "")
+	      /* Categories Zl and Zp */
+	      || (unicode_attributes[ch].category[0] == 'Z'
+		  && (unicode_attributes[ch].category[1] == 'l'
+		      || unicode_attributes[ch].category[1] == 'p'))));
+}
+
+static bool
+is_xdigit (unsigned int ch)
+{
+#if 0
+  return is_digit (ch)
+	 || (ch >= 0x0041 && ch <= 0x0046)
+	 || (ch >= 0x0061 && ch <= 0x0066);
+#else
+  /* SUSV2 gives us some freedom for the "xdigit" category, but ISO C 99
+     takes it away:
+     7.25.2.1.12:
+        The iswxdigit function tests for any wide character that corresponds
+        to a hexadecimal-digit character (as defined in 6.4.4.1).
+     6.4.4.1:
+        hexadecimal-digit: one of 0 1 2 3 4 5 6 7 8 9 a b c d e f A B C D E F
+   */
+  return (ch >= 0x0030 && ch <= 0x0039)
+	 || (ch >= 0x0041 && ch <= 0x0046)
+	 || (ch >= 0x0061 && ch <= 0x0066);
+#endif
+}
+
+static bool
+is_graph (unsigned int ch)
+{
+  return (unicode_attributes[ch].name != NULL
+	  && strcmp (unicode_attributes[ch].name, "")
+	  && !is_space (ch));
+}
+
+static bool
+is_print (unsigned int ch)
+{
+  return (unicode_attributes[ch].name != NULL
+	  && strcmp (unicode_attributes[ch].name, "")
+	  /* Categories Zl and Zp */
+	  && !(unicode_attributes[ch].name != NULL
+	       && unicode_attributes[ch].category[0] == 'Z'
+	       && (unicode_attributes[ch].category[1] == 'l'
+		   || unicode_attributes[ch].category[1] == 'p')));
+}
+
+static bool
+is_punct (unsigned int ch)
+{
+#if 0
+  return (unicode_attributes[ch].name != NULL
+	  && unicode_attributes[ch].category[0] == 'P');
+#else
+  /* The traditional POSIX definition of punctuation is every graphic,
+     non-alphanumeric character.  */
+  return (is_graph (ch) && !is_alpha (ch) && !is_digit (ch));
+#endif
+}
+
+static bool
+is_combining (unsigned int ch)
+{
+  /* Up to Unicode 3.0.1 we took the Combining property from the PropList.txt
+     file. In 3.0.1 it was identical to the union of the general categories
+     "Mn", "Mc", "Me". In Unicode 3.1 this property has been dropped from the
+     PropList.txt file, so we take the latter definition.  */
+  return (unicode_attributes[ch].name != NULL
+	  && unicode_attributes[ch].category[0] == 'M'
+	  && (unicode_attributes[ch].category[1] == 'n'
+	      || unicode_attributes[ch].category[1] == 'c'
+	      || unicode_attributes[ch].category[1] == 'e'));
+}
+
+static bool
+is_combining_level3 (unsigned int ch)
+{
+  return is_combining (ch)
+	 && !(unicode_attributes[ch].combining[0] != '\0'
+	      && unicode_attributes[ch].combining[0] != '0'
+	      && strtoul (unicode_attributes[ch].combining, NULL, 10) >= 200);
+}
+
+/* Return the UCS symbol string for a Unicode character.  */
+static const char *
+ucs_symbol (unsigned int i)
+{
+  static char buf[11+1];
+
+  sprintf (buf, (i < 0x10000 ? "" : ""), i);
+  return buf;
+}
+
+/* Return the UCS symbol range string for a Unicode characters interval.  */
+static const char *
+ucs_symbol_range (unsigned int low, unsigned int high)
+{
+  static char buf[24+1];
+
+  strcpy (buf, ucs_symbol (low));
+  strcat (buf, "..");
+  strcat (buf, ucs_symbol (high));
+  return buf;
+}
+
+/* Output a character class (= property) table.  */
+
+static void
+output_charclass (FILE *stream, const char *classname,
+		  bool (*func) (unsigned int))
+{
+  char table[0x110000];
+  unsigned int i;
+  bool need_semicolon;
+  const int max_column = 75;
+  int column;
+
+  for (i = 0; i < 0x110000; i++)
+    table[i] = (int) func (i);
+
+  fprintf (stream, "%s ", classname);
+  need_semicolon = false;
+  column = 1000;
+  for (i = 0; i < 0x110000; )
+    {
+      if (!table[i])
+	i++;
+      else
+	{
+	  unsigned int low, high;
+	  char buf[25];
+
+	  low = i;
+	  do
+	    i++;
+	  while (i < 0x110000 && table[i]);
+	  high = i - 1;
+
+	  if (low == high)
+	    strcpy (buf, ucs_symbol (low));
+	  else
+	    strcpy (buf, ucs_symbol_range (low, high));
+
+	  if (need_semicolon)
+	    {
+	      fprintf (stream, ";");
+	      column++;
+	    }
+
+	  if (column + strlen (buf) > max_column)
+	    {
+	      fprintf (stream, "/\n   ");
+	      column = 3;
+	    }
+
+	  fprintf (stream, "%s", buf);
+	  column += strlen (buf);
+	  need_semicolon = true;
+	}
+    }
+  fprintf (stream, "\n");
+}
+
+/* Output a character mapping table.  */
+
+static void
+output_charmap (FILE *stream, const char *mapname,
+		unsigned int (*func) (unsigned int))
+{
+  char table[0x110000];
+  unsigned int i;
+  bool need_semicolon;
+  const int max_column = 75;
+  int column;
+
+  for (i = 0; i < 0x110000; i++)
+    table[i] = (func (i) != i);
+
+  fprintf (stream, "%s ", mapname);
+  need_semicolon = false;
+  column = 1000;
+  for (i = 0; i < 0x110000; i++)
+    if (table[i])
+      {
+	char buf[25+1];
+
+	strcpy (buf, "(");
+	strcat (buf, ucs_symbol (i));
+	strcat (buf, ",");
+	strcat (buf, ucs_symbol (func (i)));
+	strcat (buf, ")");
+
+	if (need_semicolon)
+	  {
+	    fprintf (stream, ";");
+	    column++;
+	  }
+
+	if (column + strlen (buf) > max_column)
+	  {
+	    fprintf (stream, "/\n   ");
+	    column = 3;
+	  }
+
+	fprintf (stream, "%s", buf);
+	column += strlen (buf);
+	need_semicolon = true;
+      }
+  fprintf (stream, "\n");
+}
+
+/* Output the width table.  */
+
+static void
+output_widthmap (FILE *stream)
+{
+}
+
+/* Output the tables to the given file.  */
+
+static void
+output_tables (const char *filename, const char *version)
+{
+  FILE *stream;
+  unsigned int ch;
+
+  stream = fopen (filename, "w");
+  if (stream == NULL)
+    {
+      fprintf (stderr, "cannot open '%s' for writing\n", filename);
+      exit (1);
+    }
+
+  fprintf (stream, "escape_char /\n");
+  fprintf (stream, "comment_char %%\n");
+  fprintf (stream, "\n");
+  fprintf (stream, "%% Generated automatically by gen-unicode-ctype for Unicode %s.\n",
+	   version);
+  fprintf (stream, "\n");
+
+  fprintf (stream, "LC_IDENTIFICATION\n");
+  fprintf (stream, "title     \"Unicode %s FDCC-set\"\n", version);
+  fprintf (stream, "source    \"UnicodeData.txt, PropList.txt\"\n");
+  fprintf (stream, "address   \"\"\n");
+  fprintf (stream, "contact   \"\"\n");
+  fprintf (stream, "email     \"bug-glibc-locales@gnu.org\"\n");
+  fprintf (stream, "tel       \"\"\n");
+  fprintf (stream, "fax       \"\"\n");
+  fprintf (stream, "language  \"\"\n");
+  fprintf (stream, "territory \"Earth\"\n");
+  fprintf (stream, "revision  \"%s\"\n", version);
+  {
+    time_t now;
+    char date[11];
+    now = time (NULL);
+    strftime (date, sizeof (date), "%Y-%m-%d", gmtime (&now));
+    fprintf (stream, "date      \"%s\"\n", date);
+  }
+  fprintf (stream, "category  \"unicode:2001\";LC_CTYPE\n");
+  fprintf (stream, "END LC_IDENTIFICATION\n");
+  fprintf (stream, "\n");
+
+  /* Verifications. */
+  for (ch = 0; ch < 0x110000; ch++)
+    {
+      /* toupper restriction: "Only characters specified for the keywords
+	 lower and upper shall be specified.  */
+      if (to_upper (ch) != ch && !(is_lower (ch) || is_upper (ch)))
+	fprintf (stderr,
+		 "%s is not upper|lower but toupper(0x%04X) = 0x%04X\n",
+		 ucs_symbol (ch), ch, to_upper (ch));
+
+      /* tolower restriction: "Only characters specified for the keywords
+	 lower and upper shall be specified.  */
+      if (to_lower (ch) != ch && !(is_lower (ch) || is_upper (ch)))
+	fprintf (stderr,
+		 "%s is not upper|lower but tolower(0x%04X) = 0x%04X\n",
+		 ucs_symbol (ch), ch, to_lower (ch));
+
+      /* alpha restriction: "Characters classified as either upper or lower
+	 shall automatically belong to this class.  */
+      if ((is_lower (ch) || is_upper (ch)) && !is_alpha (ch))
+	fprintf (stderr, "%s is upper|lower but not alpha\n", ucs_symbol (ch));
+
+      /* alpha restriction: "No character specified for the keywords cntrl,
+	 digit, punct or space shall be specified."  */
+      if (is_alpha (ch) && is_cntrl (ch))
+	fprintf (stderr, "%s is alpha and cntrl\n", ucs_symbol (ch));
+      if (is_alpha (ch) && is_digit (ch))
+	fprintf (stderr, "%s is alpha and digit\n", ucs_symbol (ch));
+      if (is_alpha (ch) && is_punct (ch))
+	fprintf (stderr, "%s is alpha and punct\n", ucs_symbol (ch));
+      if (is_alpha (ch) && is_space (ch))
+	fprintf (stderr, "%s is alpha and space\n", ucs_symbol (ch));
+
+      /* space restriction: "No character specified for the keywords upper,
+	 lower, alpha, digit, graph or xdigit shall be specified."
+	 upper, lower, alpha already checked above.  */
+      if (is_space (ch) && is_digit (ch))
+	fprintf (stderr, "%s is space and digit\n", ucs_symbol (ch));
+      if (is_space (ch) && is_graph (ch))
+	fprintf (stderr, "%s is space and graph\n", ucs_symbol (ch));
+      if (is_space (ch) && is_xdigit (ch))
+	fprintf (stderr, "%s is space and xdigit\n", ucs_symbol (ch));
+
+      /* cntrl restriction: "No character specified for the keywords upper,
+	 lower, alpha, digit, punct, graph, print or xdigit shall be
+	 specified."  upper, lower, alpha already checked above.  */
+      if (is_cntrl (ch) && is_digit (ch))
+	fprintf (stderr, "%s is cntrl and digit\n", ucs_symbol (ch));
+      if (is_cntrl (ch) && is_punct (ch))
+	fprintf (stderr, "%s is cntrl and punct\n", ucs_symbol (ch));
+      if (is_cntrl (ch) && is_graph (ch))
+	fprintf (stderr, "%s is cntrl and graph\n", ucs_symbol (ch));
+      if (is_cntrl (ch) && is_print (ch))
+	fprintf (stderr, "%s is cntrl and print\n", ucs_symbol (ch));
+      if (is_cntrl (ch) && is_xdigit (ch))
+	fprintf (stderr, "%s is cntrl and xdigit\n", ucs_symbol (ch));
+
+      /* punct restriction: "No character specified for the keywords upper,
+	 lower, alpha, digit, cntrl, xdigit or as the  character shall
+	 be specified."  upper, lower, alpha, cntrl already checked above.  */
+      if (is_punct (ch) && is_digit (ch))
+	fprintf (stderr, "%s is punct and digit\n", ucs_symbol (ch));
+      if (is_punct (ch) && is_xdigit (ch))
+	fprintf (stderr, "%s is punct and xdigit\n", ucs_symbol (ch));
+      if (is_punct (ch) && (ch == 0x0020))
+	fprintf (stderr, "%s is punct\n", ucs_symbol (ch));
+
+      /* graph restriction: "No character specified for the keyword cntrl
+	 shall be specified."  Already checked above.  */
+
+      /* print restriction: "No character specified for the keyword cntrl
+	 shall be specified."  Already checked above.  */
+
+      /* graph - print relation: differ only in the  character.
+	 How is this possible if there are more than one space character?!
+	 I think susv2/xbd/locale.html should speak of "space characters",
+	 not "space character".  */
+      if (is_print (ch) && !(is_graph (ch) || /* ch == 0x0020 */ is_space (ch)))
+	fprintf (stderr,
+		 "%s is print but not graph|\n", ucs_symbol (ch));
+      if (!is_print (ch) && (is_graph (ch) || ch == 0x0020))
+	fprintf (stderr,
+		 "%s is graph| but not print\n", ucs_symbol (ch));
+    }
+
+  fprintf (stream, "LC_CTYPE\n");
+  output_charclass (stream, "upper", is_upper);
+  output_charclass (stream, "lower", is_lower);
+  output_charclass (stream, "alpha", is_alpha);
+  output_charclass (stream, "digit", is_digit);
+  output_charclass (stream, "outdigit", is_outdigit);
+  output_charclass (stream, "blank", is_blank);
+  output_charclass (stream, "space", is_space);
+  output_charclass (stream, "cntrl", is_cntrl);
+  output_charclass (stream, "punct", is_punct);
+  output_charclass (stream, "xdigit", is_xdigit);
+  output_charclass (stream, "graph", is_graph);
+  output_charclass (stream, "print", is_print);
+  output_charclass (stream, "class \"combining\";", is_combining);
+  output_charclass (stream, "class \"combining_level3\";", is_combining_level3);
+  output_charmap (stream, "toupper", to_upper);
+  output_charmap (stream, "tolower", to_lower);
+  output_charmap (stream, "map \"totitle\";", to_title);
+  output_widthmap (stream);
+  fprintf (stream, "END LC_CTYPE\n");
+
+  if (ferror (stream) || fclose (stream))
+    {
+      fprintf (stderr, "error writing to '%s'\n", filename);
+      exit (1);
+    }
+}
+
+int
+main (int argc, char * argv[])
+{
+  if (argc != 3)
+    {
+      fprintf (stderr, "Usage: %s UnicodeData.txt version\n", argv[0]);
+      exit (1);
+    }
+
+  fill_attributes (argv[1]);
+
+  output_tables ("unicode", argv[2]);
+
+  return 0;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/show-ucs-data.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/show-ucs-data.c
new file mode 100644
index 00000000..9992ece4
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/show-ucs-data.c
@@ -0,0 +1,62 @@
+#include 
+#include 
+#include 
+#include 
+
+int
+main (int argc, char *argv[])
+{
+  int n;
+  char *line = NULL;
+  size_t len = 0;
+
+  for (n = 1; n < argc; ++n)
+    {
+      FILE *fp = fopen (argv[n], "r");
+      if (fp == NULL)
+	continue;
+
+      while (! feof (fp))
+	{
+	  ssize_t cnt = getline (&line, &len, fp);
+	  char *runp;
+	  if (cnt <= 0)
+	    break;
+
+	  runp = line;
+	  do
+	    {
+	      if (runp[0] == '<' && runp[1] == 'U' && isxdigit (runp[2])
+		  && isxdigit (runp[3]) && isxdigit (runp[4])
+		  && isxdigit (runp[5]) && runp[6] == '>')
+		{
+		  unsigned int val = strtoul (runp + 2, NULL, 16);
+
+		  //putchar ('<');
+		  if (val < 128)
+		    putchar (val);
+		  else if (val < 0x800)
+		    {
+		      putchar (0xc0 | (val >> 6));
+		      putchar (0x80 | (val & 0x3f));
+		    }
+		  else
+		    {
+		      putchar (0xe0 | (val >> 12));
+		      putchar (0x80 | ((val >> 6) & 0x3f));
+		      putchar (0x80 | (val & 0x3f));
+		    }
+		  //putchar ('>');
+		  runp += 7;
+		}
+	      else
+		putchar (*runp++);
+	    }
+	  while (runp < &line[cnt]);
+	}
+
+      fclose (fp);
+    }
+
+  return 0;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-C-locale.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-C-locale.c
new file mode 100644
index 00000000..c568cf40
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-C-locale.c
@@ -0,0 +1,498 @@
+/* Tests of C and POSIX locale contents.
+   Copyright (C) 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2000.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+static int
+run_test (const char *locname)
+{
+  struct lconv *lc;
+  const char *str;
+  const wchar_t *wstr;
+  int result = 0;
+  locale_t loc;
+
+  /* ISO C stuff.  */
+  lc = localeconv ();
+  if (lc == NULL)
+    {
+      printf ("localeconv failed for locale %s\n", locname);
+      result = 1;
+    }
+  else
+    {
+#define STRTEST(name, exp) \
+      do								      \
+	if (strcmp (lc->name, exp) != 0)				      \
+	  {								      \
+	    printf (#name " in locale %s wrong (is \"%s\", should be \"%s\")\n",\
+		    locname, lc->name, exp);				      \
+	    result = 1;							      \
+	  }								      \
+      while (0)
+      STRTEST (decimal_point, ".");
+      STRTEST (thousands_sep, "");
+      STRTEST (grouping, "");
+      STRTEST (mon_decimal_point, "");
+      STRTEST (mon_thousands_sep, "");
+      STRTEST (mon_grouping, "");
+      STRTEST (positive_sign, "");
+      STRTEST (negative_sign, "");
+      STRTEST (currency_symbol, "");
+      STRTEST (int_curr_symbol, "");
+
+#define CHARTEST(name, exp) \
+      do								      \
+	if (lc->name != exp)						      \
+	  {								      \
+	    printf (#name " in locale %s wrong (is %d, should be %d)\n",      \
+		    locname, lc->name, CHAR_MAX);			      \
+	    result = 1;							      \
+	  }								      \
+      while (0)
+      CHARTEST (frac_digits, CHAR_MAX);
+      CHARTEST (p_cs_precedes, CHAR_MAX);
+      CHARTEST (n_cs_precedes, CHAR_MAX);
+      CHARTEST (p_sep_by_space, CHAR_MAX);
+      CHARTEST (n_sep_by_space, CHAR_MAX);
+      CHARTEST (p_sign_posn, CHAR_MAX);
+      CHARTEST (n_sign_posn, CHAR_MAX);
+      CHARTEST (int_frac_digits, CHAR_MAX);
+      CHARTEST (int_p_cs_precedes, CHAR_MAX);
+      CHARTEST (int_n_cs_precedes, CHAR_MAX);
+      CHARTEST (int_p_sep_by_space, CHAR_MAX);
+      CHARTEST (int_n_sep_by_space, CHAR_MAX);
+      CHARTEST (int_p_sign_posn, CHAR_MAX);
+      CHARTEST (int_n_sign_posn, CHAR_MAX);
+    }
+
+#undef STRTEST
+#define STRTEST(name, exp) \
+  str = nl_langinfo (name);						      \
+  if (strcmp (str, exp) != 0)						      \
+    {									      \
+      printf ("nl_langinfo(" #name ") in locale %s wrong "		      \
+	      "(is \"%s\", should be \"%s\")\n", locname, str, exp);	      \
+      result = 1;							      \
+    }
+#define WSTRTEST(name, exp) \
+  wstr = (wchar_t *) nl_langinfo (name);				      \
+  if (wcscmp (wstr, exp) != 0)						      \
+    {									      \
+      printf ("nl_langinfo(" #name ") in locale %s wrong "		      \
+	      "(is \"%S\", should be \"%S\")\n", locname, wstr, exp);	      \
+      result = 1;							      \
+    }
+
+  /* Unix stuff.  */
+  STRTEST (ABDAY_1, "Sun");
+  STRTEST (ABDAY_2, "Mon");
+  STRTEST (ABDAY_3, "Tue");
+  STRTEST (ABDAY_4, "Wed");
+  STRTEST (ABDAY_5, "Thu");
+  STRTEST (ABDAY_6, "Fri");
+  STRTEST (ABDAY_7, "Sat");
+  STRTEST (DAY_1, "Sunday");
+  STRTEST (DAY_2, "Monday");
+  STRTEST (DAY_3, "Tuesday");
+  STRTEST (DAY_4, "Wednesday");
+  STRTEST (DAY_5, "Thursday");
+  STRTEST (DAY_6, "Friday");
+  STRTEST (DAY_7, "Saturday");
+  STRTEST (ABMON_1, "Jan");
+  STRTEST (ABMON_2, "Feb");
+  STRTEST (ABMON_3, "Mar");
+  STRTEST (ABMON_4, "Apr");
+  STRTEST (ABMON_5, "May");
+  STRTEST (ABMON_6, "Jun");
+  STRTEST (ABMON_7, "Jul");
+  STRTEST (ABMON_8, "Aug");
+  STRTEST (ABMON_9, "Sep");
+  STRTEST (ABMON_10, "Oct");
+  STRTEST (ABMON_11, "Nov");
+  STRTEST (ABMON_12, "Dec");
+  STRTEST (MON_1, "January");
+  STRTEST (MON_2, "February");
+  STRTEST (MON_3, "March");
+  STRTEST (MON_4, "April");
+  STRTEST (MON_5, "May");
+  STRTEST (MON_6, "June");
+  STRTEST (MON_7, "July");
+  STRTEST (MON_8, "August");
+  STRTEST (MON_9, "September");
+  STRTEST (MON_10, "October");
+  STRTEST (MON_11, "November");
+  STRTEST (MON_12, "December");
+  STRTEST (AM_STR, "AM");
+  STRTEST (PM_STR, "PM");
+  STRTEST (D_T_FMT, "%a %b %e %H:%M:%S %Y");
+  STRTEST (D_FMT, "%m/%d/%y");
+  STRTEST (T_FMT, "%H:%M:%S");
+  STRTEST (T_FMT_AMPM, "%I:%M:%S %p");
+  STRTEST (ERA, "");
+  STRTEST (ERA_D_FMT, "");
+  STRTEST (ERA_T_FMT, "");
+  STRTEST (ERA_D_T_FMT, "");
+  STRTEST (ALT_DIGITS, "");
+
+  STRTEST (RADIXCHAR, ".");
+  STRTEST (THOUSEP, "");
+
+  STRTEST (YESEXPR, "^[yY]");
+  STRTEST (NOEXPR, "^[nN]");
+
+  /* Extensions.  */
+  WSTRTEST (_NL_WABDAY_1, L"Sun");
+  WSTRTEST (_NL_WABDAY_2, L"Mon");
+  WSTRTEST (_NL_WABDAY_3, L"Tue");
+  WSTRTEST (_NL_WABDAY_4, L"Wed");
+  WSTRTEST (_NL_WABDAY_5, L"Thu");
+  WSTRTEST (_NL_WABDAY_6, L"Fri");
+  WSTRTEST (_NL_WABDAY_7, L"Sat");
+  WSTRTEST (_NL_WDAY_1, L"Sunday");
+  WSTRTEST (_NL_WDAY_2, L"Monday");
+  WSTRTEST (_NL_WDAY_3, L"Tuesday");
+  WSTRTEST (_NL_WDAY_4, L"Wednesday");
+  WSTRTEST (_NL_WDAY_5, L"Thursday");
+  WSTRTEST (_NL_WDAY_6, L"Friday");
+  WSTRTEST (_NL_WDAY_7, L"Saturday");
+  WSTRTEST (_NL_WABMON_1, L"Jan");
+  WSTRTEST (_NL_WABMON_2, L"Feb");
+  WSTRTEST (_NL_WABMON_3, L"Mar");
+  WSTRTEST (_NL_WABMON_4, L"Apr");
+  WSTRTEST (_NL_WABMON_5, L"May");
+  WSTRTEST (_NL_WABMON_6, L"Jun");
+  WSTRTEST (_NL_WABMON_7, L"Jul");
+  WSTRTEST (_NL_WABMON_8, L"Aug");
+  WSTRTEST (_NL_WABMON_9, L"Sep");
+  WSTRTEST (_NL_WABMON_10, L"Oct");
+  WSTRTEST (_NL_WABMON_11, L"Nov");
+  WSTRTEST (_NL_WABMON_12, L"Dec");
+  WSTRTEST (_NL_WMON_1, L"January");
+  WSTRTEST (_NL_WMON_2, L"February");
+  WSTRTEST (_NL_WMON_3, L"March");
+  WSTRTEST (_NL_WMON_4, L"April");
+  WSTRTEST (_NL_WMON_5, L"May");
+  WSTRTEST (_NL_WMON_6, L"June");
+  WSTRTEST (_NL_WMON_7, L"July");
+  WSTRTEST (_NL_WMON_8, L"August");
+  WSTRTEST (_NL_WMON_9, L"September");
+  WSTRTEST (_NL_WMON_10, L"October");
+  WSTRTEST (_NL_WMON_11, L"November");
+  WSTRTEST (_NL_WMON_12, L"December");
+  WSTRTEST (_NL_WAM_STR, L"AM");
+  WSTRTEST (_NL_WPM_STR, L"PM");
+  WSTRTEST (_NL_WD_T_FMT, L"%a %b %e %H:%M:%S %Y");
+  WSTRTEST (_NL_WD_FMT, L"%m/%d/%y");
+  WSTRTEST (_NL_WT_FMT, L"%H:%M:%S");
+  WSTRTEST (_NL_WT_FMT_AMPM, L"%I:%M:%S %p");
+  WSTRTEST (_NL_WERA_D_FMT, L"");
+  WSTRTEST (_NL_WERA_T_FMT, L"");
+  WSTRTEST (_NL_WERA_D_T_FMT, L"");
+  WSTRTEST (_NL_WALT_DIGITS, L"");
+
+  STRTEST (_DATE_FMT, "%a %b %e %H:%M:%S %Z %Y");
+  WSTRTEST (_NL_W_DATE_FMT, L"%a %b %e %H:%M:%S %Z %Y");
+
+  STRTEST (INT_CURR_SYMBOL, "");
+  STRTEST (CURRENCY_SYMBOL, "");
+  STRTEST (MON_DECIMAL_POINT, "");
+  STRTEST (MON_THOUSANDS_SEP, "");
+  STRTEST (MON_GROUPING, "");
+  STRTEST (POSITIVE_SIGN, "");
+  STRTEST (NEGATIVE_SIGN, "");
+  STRTEST (GROUPING, "");
+
+  STRTEST (YESSTR, "");
+  STRTEST (NOSTR, "");
+
+  /* Test the new locale mechanisms.  */
+  loc = newlocale (LC_ALL_MASK, locname, NULL);
+  if (loc == NULL)
+    {
+      printf ("cannot create locale object for locale %s\n", locname);
+      result = 1;
+    }
+  else
+    {
+      int c;
+
+#undef STRTEST
+#define STRTEST(name, exp) \
+      str = nl_langinfo_l (name, loc);				      \
+      if (strcmp (str, exp) != 0)					      \
+	{								      \
+	  printf ("nl_langinfo_l(" #name ") in locale %s wrong "	      \
+		  "(is \"%s\", should be \"%s\")\n", locname, str, exp);      \
+	  result = 1;							      \
+	}
+#undef WSTRTEST
+#define WSTRTEST(name, exp) \
+      wstr = (wchar_t *) nl_langinfo_l (name, loc);			      \
+      if (wcscmp (wstr, exp) != 0)					      \
+	{								      \
+	  printf ("nl_langinfo_l(" #name ") in locale %s wrong "	      \
+		  "(is \"%S\", should be \"%S\")\n", locname, wstr, exp);     \
+	  result = 1;							      \
+	}
+
+      /* Unix stuff.  */
+      STRTEST (ABDAY_1, "Sun");
+      STRTEST (ABDAY_2, "Mon");
+      STRTEST (ABDAY_3, "Tue");
+      STRTEST (ABDAY_4, "Wed");
+      STRTEST (ABDAY_5, "Thu");
+      STRTEST (ABDAY_6, "Fri");
+      STRTEST (ABDAY_7, "Sat");
+      STRTEST (DAY_1, "Sunday");
+      STRTEST (DAY_2, "Monday");
+      STRTEST (DAY_3, "Tuesday");
+      STRTEST (DAY_4, "Wednesday");
+      STRTEST (DAY_5, "Thursday");
+      STRTEST (DAY_6, "Friday");
+      STRTEST (DAY_7, "Saturday");
+      STRTEST (ABMON_1, "Jan");
+      STRTEST (ABMON_2, "Feb");
+      STRTEST (ABMON_3, "Mar");
+      STRTEST (ABMON_4, "Apr");
+      STRTEST (ABMON_5, "May");
+      STRTEST (ABMON_6, "Jun");
+      STRTEST (ABMON_7, "Jul");
+      STRTEST (ABMON_8, "Aug");
+      STRTEST (ABMON_9, "Sep");
+      STRTEST (ABMON_10, "Oct");
+      STRTEST (ABMON_11, "Nov");
+      STRTEST (ABMON_12, "Dec");
+      STRTEST (MON_1, "January");
+      STRTEST (MON_2, "February");
+      STRTEST (MON_3, "March");
+      STRTEST (MON_4, "April");
+      STRTEST (MON_5, "May");
+      STRTEST (MON_6, "June");
+      STRTEST (MON_7, "July");
+      STRTEST (MON_8, "August");
+      STRTEST (MON_9, "September");
+      STRTEST (MON_10, "October");
+      STRTEST (MON_11, "November");
+      STRTEST (MON_12, "December");
+      STRTEST (AM_STR, "AM");
+      STRTEST (PM_STR, "PM");
+      STRTEST (D_T_FMT, "%a %b %e %H:%M:%S %Y");
+      STRTEST (D_FMT, "%m/%d/%y");
+      STRTEST (T_FMT, "%H:%M:%S");
+      STRTEST (T_FMT_AMPM, "%I:%M:%S %p");
+      STRTEST (ERA, "");
+      STRTEST (ERA_D_FMT, "");
+      STRTEST (ERA_T_FMT, "");
+      STRTEST (ERA_D_T_FMT, "");
+      STRTEST (ALT_DIGITS, "");
+
+      STRTEST (RADIXCHAR, ".");
+      STRTEST (THOUSEP, "");
+
+      STRTEST (YESEXPR, "^[yY]");
+      STRTEST (NOEXPR, "^[nN]");
+
+      /* Extensions.  */
+      WSTRTEST (_NL_WABDAY_1, L"Sun");
+      WSTRTEST (_NL_WABDAY_2, L"Mon");
+      WSTRTEST (_NL_WABDAY_3, L"Tue");
+      WSTRTEST (_NL_WABDAY_4, L"Wed");
+      WSTRTEST (_NL_WABDAY_5, L"Thu");
+      WSTRTEST (_NL_WABDAY_6, L"Fri");
+      WSTRTEST (_NL_WABDAY_7, L"Sat");
+      WSTRTEST (_NL_WDAY_1, L"Sunday");
+      WSTRTEST (_NL_WDAY_2, L"Monday");
+      WSTRTEST (_NL_WDAY_3, L"Tuesday");
+      WSTRTEST (_NL_WDAY_4, L"Wednesday");
+      WSTRTEST (_NL_WDAY_5, L"Thursday");
+      WSTRTEST (_NL_WDAY_6, L"Friday");
+      WSTRTEST (_NL_WDAY_7, L"Saturday");
+      WSTRTEST (_NL_WABMON_1, L"Jan");
+      WSTRTEST (_NL_WABMON_2, L"Feb");
+      WSTRTEST (_NL_WABMON_3, L"Mar");
+      WSTRTEST (_NL_WABMON_4, L"Apr");
+      WSTRTEST (_NL_WABMON_5, L"May");
+      WSTRTEST (_NL_WABMON_6, L"Jun");
+      WSTRTEST (_NL_WABMON_7, L"Jul");
+      WSTRTEST (_NL_WABMON_8, L"Aug");
+      WSTRTEST (_NL_WABMON_9, L"Sep");
+      WSTRTEST (_NL_WABMON_10, L"Oct");
+      WSTRTEST (_NL_WABMON_11, L"Nov");
+      WSTRTEST (_NL_WABMON_12, L"Dec");
+      WSTRTEST (_NL_WMON_1, L"January");
+      WSTRTEST (_NL_WMON_2, L"February");
+      WSTRTEST (_NL_WMON_3, L"March");
+      WSTRTEST (_NL_WMON_4, L"April");
+      WSTRTEST (_NL_WMON_5, L"May");
+      WSTRTEST (_NL_WMON_6, L"June");
+      WSTRTEST (_NL_WMON_7, L"July");
+      WSTRTEST (_NL_WMON_8, L"August");
+      WSTRTEST (_NL_WMON_9, L"September");
+      WSTRTEST (_NL_WMON_10, L"October");
+      WSTRTEST (_NL_WMON_11, L"November");
+      WSTRTEST (_NL_WMON_12, L"December");
+      WSTRTEST (_NL_WAM_STR, L"AM");
+      WSTRTEST (_NL_WPM_STR, L"PM");
+      WSTRTEST (_NL_WD_T_FMT, L"%a %b %e %H:%M:%S %Y");
+      WSTRTEST (_NL_WD_FMT, L"%m/%d/%y");
+      WSTRTEST (_NL_WT_FMT, L"%H:%M:%S");
+      WSTRTEST (_NL_WT_FMT_AMPM, L"%I:%M:%S %p");
+      WSTRTEST (_NL_WERA_D_FMT, L"");
+      WSTRTEST (_NL_WERA_T_FMT, L"");
+      WSTRTEST (_NL_WERA_D_T_FMT, L"");
+      WSTRTEST (_NL_WALT_DIGITS, L"");
+
+      STRTEST (_DATE_FMT, "%a %b %e %H:%M:%S %Z %Y");
+      WSTRTEST (_NL_W_DATE_FMT, L"%a %b %e %H:%M:%S %Z %Y");
+
+      STRTEST (INT_CURR_SYMBOL, "");
+      STRTEST (CURRENCY_SYMBOL, "");
+      STRTEST (MON_DECIMAL_POINT, "");
+      STRTEST (MON_THOUSANDS_SEP, "");
+      STRTEST (MON_GROUPING, "");
+      STRTEST (POSITIVE_SIGN, "");
+      STRTEST (NEGATIVE_SIGN, "");
+      STRTEST (GROUPING, "");
+
+      STRTEST (YESSTR, "");
+      STRTEST (NOSTR, "");
+
+      /* Character class tests.  */
+      for (c = 0; c < 128; ++c)
+	{
+#define CLASSTEST(name) \
+	  if (is##name (c) != is##name##_l (c, loc))			      \
+	    {								      \
+	      printf ("is%s('\\%o') != is%s_l('\\%o')\n",		      \
+		      #name, c, #name, c);				      \
+	      result = 1;						      \
+	    }
+	  CLASSTEST (alnum);
+	  CLASSTEST (alpha);
+	  CLASSTEST (blank);
+	  CLASSTEST (cntrl);
+	  CLASSTEST (digit);
+	  CLASSTEST (lower);
+	  CLASSTEST (graph);
+	  CLASSTEST (print);
+	  CLASSTEST (punct);
+	  CLASSTEST (space);
+	  CLASSTEST (upper);
+	  CLASSTEST (xdigit);
+
+	  /* Character mapping tests.  */
+#define MAPTEST(name) \
+	  if (to##name (c) != to##name##_l (c, loc))			      \
+	    {								      \
+	      printf ("to%s('\\%o') != to%s_l('\\%o'): '\\%o' vs '\\%o'\n", \
+		      #name, c, #name, c,				      \
+		      to##name (c), to##name##_l (c, loc));		      \
+	      result = 1;						      \
+	    }
+	  MAPTEST (lower);
+	  MAPTEST (upper);
+	}
+
+      /* Character class tests, this time for wide characters.  Note that
+	 this only works because we know that the internal encoding is
+	 UCS4.  */
+      for (c = 0; c < 128; ++c)
+	{
+#undef CLASSTEST
+#define CLASSTEST(name) \
+	  if (isw##name (c) != isw##name##_l (c, loc))		      \
+	    {								      \
+	      printf ("isw%s('\\%o') != isw%s_l('\\%o')\n",		      \
+		      #name, c, #name, c);				      \
+	      result = 1;						      \
+	    }
+	  CLASSTEST (alnum);
+	  CLASSTEST (alpha);
+	  CLASSTEST (blank);
+	  CLASSTEST (cntrl);
+	  CLASSTEST (digit);
+	  CLASSTEST (lower);
+	  CLASSTEST (graph);
+	  CLASSTEST (print);
+	  CLASSTEST (punct);
+	  CLASSTEST (space);
+	  CLASSTEST (upper);
+	  CLASSTEST (xdigit);
+
+	  /* Character mapping tests.  Note that
+	     this only works because we know that the internal encoding is
+	     UCS4.  */
+#undef MAPTEST
+#define MAPTEST(name) \
+	  if (tow##name (c) != tow##name##_l (c, loc))		      \
+	    {								      \
+	      printf ("tow%s('\\%o') != tow%s_l('\\%o'): '\\%o' vs '\\%o'\n",\
+		      #name, c, #name, c,				      \
+		      tow##name (c), tow##name##_l (c, loc));		      \
+	      result = 1;						      \
+	    }
+	  MAPTEST (lower);
+	  MAPTEST (upper);
+	}
+
+      freelocale (loc);
+    }
+
+  return result;
+}
+
+
+static int
+do_test (void)
+{
+  int result;
+
+  /* First use the name "C".  */
+  if (setlocale (LC_ALL, "C") == NULL)
+    {
+      puts ("cannot set C locale");
+      result = 1;
+    }
+  else
+    result = run_test ("C");
+
+  /* Then the name "POSIX".  */
+  if (setlocale (LC_ALL, "POSIX") == NULL)
+    {
+      puts ("cannot set POSIX locale");
+      result = 1;
+    }
+  else
+    result |= run_test ("POSIX");
+
+  return result;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-ctype-de_DE.ISO-8859-1.in b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-ctype-de_DE.ISO-8859-1.in
new file mode 100644
index 00000000..f71d76cc
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-ctype-de_DE.ISO-8859-1.in
@@ -0,0 +1,56 @@
+lower    ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏ
+        000000000000000000000100000000000000000000000000
+lower   ÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ
+        000000000000000111111111111111111111111011111111
+upper    ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏ
+        000000000000000000000000000000001111111111111111
+upper   ÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ
+        111111101111111000000000000000000000000000000000
+alpha    ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏ
+        000000000010000000000100001000001111111111111111
+alpha   ÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ
+        111111101111111111111111111111111111111011111111
+digit    ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏ
+        000000000000000000000000000000000000000000000000
+digit   ÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ
+        000000000000000000000000000000000000000000000000
+xdigit   ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏ
+        000000000000000000000000000000000000000000000000
+xdigit  ÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ
+        000000000000000000000000000000000000000000000000
+space    ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏ
+        000000000000000000000000000000000000000000000000
+space   ÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ
+        000000000000000000000000000000000000000000000000
+print    ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏ
+        111111111111111111111111111111111111111111111111
+print   ÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ
+        111111111111111111111111111111111111111111111111
+graph    ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏ
+        111111111111111111111111111111111111111111111111
+graph   ÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ
+        111111111111111111111111111111111111111111111111
+blank    ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏ
+        000000000000000000000000000000000000000000000000
+blank   ÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ
+        000000000000000000000000000000000000000000000000
+cntrl    ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏ
+        000000000000000000000000000000000000000000000000
+cntrl   ÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ
+        000000000000000000000000000000000000000000000000
+punct    ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏ
+        111111111101111111111011110111110000000000000000
+punct   ÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ
+        000000010000000000000000000000000000000100000000
+alnum    ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏ
+        000000000010000000000100001000001111111111111111
+alnum   ÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ
+        111111101111111111111111111111111111111011111111
+tolower  ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏ
+         ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿àáâãäåæçèéêëìíîï
+tolower ÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ
+        ðñòóôõö×øùúûüýþßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ
+toupper  ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏ
+         ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏ
+toupper ÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ
+        ÐÑÒÓÔÕÖרÙÚÛÜÝÞßÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ÷ØÙÚÛÜÝÞÿ
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-ctype.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-ctype.c
new file mode 100644
index 00000000..c03c2dab
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-ctype.c
@@ -0,0 +1,447 @@
+/* Copyright (C) 2000,02, 05 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2000.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+static const char lower[] = "abcdefghijklmnopqrstuvwxyz";
+static const char upper[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+static const char digits[] = "0123456789";
+static const char cntrl[] = "\
+\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\
+\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f ";
+
+
+static struct classes
+{
+  const char *name;
+  int mask;
+} classes[] =
+{
+#define ENTRY(name) { #name, _IS##name }
+  ENTRY (upper),
+  ENTRY (lower),
+  ENTRY (alpha),
+  ENTRY (digit),
+  ENTRY (xdigit),
+  ENTRY (space),
+  ENTRY (print),
+  ENTRY (graph),
+  ENTRY (blank),
+  ENTRY (cntrl),
+  ENTRY (punct),
+  ENTRY (alnum)
+};
+#define nclasses (sizeof (classes) / sizeof (classes[0]))
+
+
+#define FAIL(str, args...) \
+  {									      \
+    printf ("      " str "\n", ##args);					      \
+    ++errors;								      \
+  }
+
+
+int
+main (void)
+{
+  const char *cp;
+  const char *cp2;
+  int errors = 0;
+  char *inpline = NULL;
+  size_t inplinelen = 0;
+  char *resline = NULL;
+  size_t reslinelen = 0;
+  size_t n;
+
+  setlocale (LC_ALL, "");
+
+  printf ("Testing the ctype data of the `%s' locale\n",
+	  setlocale (LC_CTYPE, NULL));
+
+#if 0
+  /* Just for debugging.  */
+
+  /* Contents of the class array.  */
+  printf ("\
+upper = %04x  lower = %04x  alpha = %04x  digit = %04x  xdigit = %04x\n\
+space = %04x  print = %04x  graph = %04x  blank = %04x  cntrl  = %04x\n\
+punct = %04x  alnum = %04x\n",
+	  _ISupper, _ISlower, _ISalpha, _ISdigit, _ISxdigit,
+	  _ISspace, _ISprint, _ISgraph, _ISblank, _IScntrl,
+	  _ISpunct, _ISalnum);
+
+  while (n < 256)
+    {
+      if (n % 8 == 0)
+	printf ("%02x: ", n);
+      printf ("%04x%s", __ctype_b[n], (n + 1) % 8 == 0 ? "\n" : " ");
+      ++n;
+    }
+#endif
+
+  puts ("  Test of ASCII character range\n    special NUL byte handling");
+  if (isupper ('\0'))
+    FAIL ("isupper ('\\0') is true");
+  if (islower ('\0'))
+    FAIL ("islower ('\\0') is true");
+  if (isalpha ('\0'))
+    FAIL ("isalpha ('\\0') is true");
+  if (isdigit ('\0'))
+    FAIL ("isdigit ('\\0') is true");
+  if (isxdigit ('\0'))
+    FAIL ("isxdigit ('\\0') is true");
+  if (isspace ('\0'))
+    FAIL ("isspace ('\\0') is true");
+  if (isprint ('\0'))
+    FAIL ("isprint ('\\0') is true");
+  if (isgraph ('\0'))
+    FAIL ("isgraph ('\\0') is true");
+  if (isblank ('\0'))
+    FAIL ("isblank ('\\0') is true");
+  if (! iscntrl ('\0'))
+    FAIL ("iscntrl ('\\0') not true");
+  if (ispunct ('\0'))
+    FAIL ("ispunct ('\\0') is true");
+  if (isalnum ('\0'))
+    FAIL ("isalnum ('\\0') is true");
+
+  puts ("    islower()");
+  for (cp = lower; *cp != '\0'; ++cp)
+    if (! islower (*cp))
+      FAIL ("islower ('%c') not true", *cp);
+  for (cp = upper; *cp != '\0'; ++cp)
+    if (islower (*cp))
+      FAIL ("islower ('%c') is true", *cp);
+  for (cp = digits; *cp != '\0'; ++cp)
+    if (islower (*cp))
+      FAIL ("islower ('%c') is true", *cp);
+  for (cp = cntrl; *cp != '\0'; ++cp)
+    if (islower (*cp))
+      FAIL ("islower ('\\x%02x') is true", *cp);
+
+  puts ("    isupper()");
+  for (cp = lower; *cp != '\0'; ++cp)
+    if (isupper (*cp))
+      FAIL ("isupper ('%c') is true", *cp);
+  for (cp = upper; *cp != '\0'; ++cp)
+    if (! isupper (*cp))
+      FAIL ("isupper ('%c') not true", *cp);
+  for (cp = digits; *cp != '\0'; ++cp)
+    if (isupper (*cp))
+      FAIL ("isupper ('%c') is true", *cp);
+  for (cp = cntrl; *cp != '\0'; ++cp)
+    if (isupper (*cp))
+      FAIL ("isupper ('\\x%02x') is true", *cp);
+
+  puts ("    isalpha()");
+  for (cp = lower; *cp != '\0'; ++cp)
+    if (! isalpha (*cp))
+      FAIL ("isalpha ('%c') not true", *cp);
+  for (cp = upper; *cp != '\0'; ++cp)
+    if (! isalpha (*cp))
+      FAIL ("isalpha ('%c') not true", *cp);
+  for (cp = digits; *cp != '\0'; ++cp)
+    if (isalpha (*cp))
+      FAIL ("isalpha ('%c') is true", *cp);
+  for (cp = cntrl; *cp != '\0'; ++cp)
+    if (isalpha (*cp))
+      FAIL ("isalpha ('\\x%02x') is true", *cp);
+
+  puts ("    isdigit()");
+  for (cp = lower; *cp != '\0'; ++cp)
+    if (isdigit (*cp))
+      FAIL ("isdigit ('%c') is true", *cp);
+  for (cp = upper; *cp != '\0'; ++cp)
+    if (isdigit (*cp))
+      FAIL ("isdigit ('%c') is true", *cp);
+  for (cp = digits; *cp != '\0'; ++cp)
+    if (! isdigit (*cp))
+      FAIL ("isdigit ('%c') not true", *cp);
+  for (cp = cntrl; *cp != '\0'; ++cp)
+    if (isdigit (*cp))
+      FAIL ("isdigit ('\\x%02x') is true", *cp);
+
+  puts ("    isxdigit()");
+  for (cp = lower; *cp != '\0'; ++cp)
+    if ((! isxdigit (*cp) && cp - lower < 6)
+	|| (isxdigit (*cp) && cp - lower >= 6))
+      FAIL ("isxdigit ('%c') %s true", *cp, cp - upper < 6 ? "not" : "is");
+  for (cp = upper; *cp != '\0'; ++cp)
+    if ((! isxdigit (*cp) && cp - upper < 6)
+	|| (isxdigit (*cp) && cp - upper >= 6))
+      FAIL ("isxdigit ('%c') %s true", *cp, cp - upper < 6 ? "not" : "is");
+  for (cp = digits; *cp != '\0'; ++cp)
+    if (! isxdigit (*cp))
+      FAIL ("isxdigit ('%c') not true", *cp);
+  for (cp = cntrl; *cp != '\0'; ++cp)
+    if (isxdigit (*cp))
+      FAIL ("isxdigit ('\\x%02x') is true", *cp);
+
+  puts ("    isspace()");
+  for (cp = lower; *cp != '\0'; ++cp)
+    if (isspace (*cp))
+      FAIL ("isspace ('%c') is true", *cp);
+  for (cp = upper; *cp != '\0'; ++cp)
+    if (isspace (*cp))
+      FAIL ("isspace ('%c') is true", *cp);
+  for (cp = digits; *cp != '\0'; ++cp)
+    if (isspace (*cp))
+      FAIL ("isspace ('%c') is true", *cp);
+  for (cp = cntrl; *cp != '\0'; ++cp)
+    if ((isspace (*cp) && ((*cp < '\x09' || *cp > '\x0d') && *cp != ' '))
+	|| (! isspace (*cp)
+	    && ((*cp >= '\x09' && *cp <= '\x0d') || *cp == ' ')))
+      FAIL ("isspace ('\\x%02x') %s true", *cp,
+	    (*cp < '\x09' || *cp > '\x0d') ? "is" : "not");
+
+  puts ("    isprint()");
+  for (cp = lower; *cp != '\0'; ++cp)
+    if (! isprint (*cp))
+      FAIL ("isprint ('%c') not true", *cp);
+  for (cp = upper; *cp != '\0'; ++cp)
+    if (! isprint (*cp))
+      FAIL ("isprint ('%c') not true", *cp);
+  for (cp = digits; *cp != '\0'; ++cp)
+    if (! isprint (*cp))
+      FAIL ("isprint ('%c') not true", *cp);
+  for (cp = cntrl; *cp != '\0'; ++cp)
+    if ((isprint (*cp) && *cp != ' ')
+	|| (! isprint (*cp) && *cp == ' '))
+      FAIL ("isprint ('\\x%02x') is true", *cp);
+
+  puts ("    isgraph()");
+  for (cp = lower; *cp != '\0'; ++cp)
+    if (! isgraph (*cp))
+      FAIL ("isgraph ('%c') not true", *cp);
+  for (cp = upper; *cp != '\0'; ++cp)
+    if (! isgraph (*cp))
+      FAIL ("isgraph ('%c') not true", *cp);
+  for (cp = digits; *cp != '\0'; ++cp)
+    if (! isgraph (*cp))
+      FAIL ("isgraph ('%c') not true", *cp);
+  for (cp = cntrl; *cp != '\0'; ++cp)
+    if (isgraph (*cp))
+      FAIL ("isgraph ('\\x%02x') is true", *cp);
+
+  puts ("    isblank()");
+  for (cp = lower; *cp != '\0'; ++cp)
+    if (isblank (*cp))
+      FAIL ("isblank ('%c') is true", *cp);
+  for (cp = upper; *cp != '\0'; ++cp)
+    if (isblank (*cp))
+      FAIL ("isblank ('%c') is true", *cp);
+  for (cp = digits; *cp != '\0'; ++cp)
+    if (isblank (*cp))
+      FAIL ("isblank ('%c') is true", *cp);
+  for (cp = cntrl; *cp != '\0'; ++cp)
+    if ((isblank (*cp) && *cp != '\x09' && *cp != ' ')
+	|| (! isblank (*cp) && (*cp == '\x09' || *cp == ' ')))
+      FAIL ("isblank ('\\x%02x') %s true", *cp, *cp != '\x09' ? "is" : "not");
+
+  puts ("    iscntrl()");
+  for (cp = lower; *cp != '\0'; ++cp)
+    if (iscntrl (*cp))
+      FAIL ("iscntrl ('%c') is true", *cp);
+  for (cp = upper; *cp != '\0'; ++cp)
+    if (iscntrl (*cp))
+      FAIL ("iscntrl ('%c') is true", *cp);
+  for (cp = digits; *cp != '\0'; ++cp)
+    if (iscntrl (*cp))
+      FAIL ("iscntrl ('%c') is true", *cp);
+  for (cp = cntrl; *cp != '\0'; ++cp)
+    if ((iscntrl (*cp) && *cp == ' ')
+	|| (! iscntrl (*cp) && *cp != ' '))
+      FAIL ("iscntrl ('\\x%02x') not true", *cp);
+
+  puts ("    ispunct()");
+  for (cp = lower; *cp != '\0'; ++cp)
+    if (ispunct (*cp))
+      FAIL ("ispunct ('%c') is true", *cp);
+  for (cp = upper; *cp != '\0'; ++cp)
+    if (ispunct (*cp))
+      FAIL ("ispunct ('%c') is true", *cp);
+  for (cp = digits; *cp != '\0'; ++cp)
+    if (ispunct (*cp))
+      FAIL ("ispunct ('%c') is true", *cp);
+  for (cp = cntrl; *cp != '\0'; ++cp)
+    if (ispunct (*cp))
+      FAIL ("ispunct ('\\x%02x') is true", *cp);
+
+  puts ("    isalnum()");
+  for (cp = lower; *cp != '\0'; ++cp)
+    if (! isalnum (*cp))
+      FAIL ("isalnum ('%c') not true", *cp);
+  for (cp = upper; *cp != '\0'; ++cp)
+    if (! isalnum (*cp))
+      FAIL ("isalnum ('%c') not true", *cp);
+  for (cp = digits; *cp != '\0'; ++cp)
+    if (! isalnum (*cp))
+      FAIL ("isalnum ('%c') not true", *cp);
+  for (cp = cntrl; *cp != '\0'; ++cp)
+    if (isalnum (*cp))
+      FAIL ("isalnum ('\\x%02x') is true", *cp);
+
+
+  puts ("    tolower()");
+  for (cp = lower; *cp != '\0'; ++cp)
+    if (tolower (*cp) != *cp)
+      FAIL ("tolower ('%c') != '%c'", *cp, *cp);
+  for (cp = upper, cp2 = lower; *cp != '\0'; ++cp, ++cp2)
+    if (tolower (*cp) != *cp2)
+      FAIL ("tolower ('%c') != '%c'", *cp, *cp2);
+  for (cp = digits; *cp != '\0'; ++cp)
+    if (tolower (*cp) != *cp)
+      FAIL ("tolower ('%c') != '%c'", *cp, *cp);
+  for (cp = cntrl; *cp != '\0'; ++cp)
+    if (tolower (*cp) != *cp)
+      FAIL ("tolower ('\\x%02x') != '\\x%02x'", *cp, *cp);
+
+  puts ("    toupper()");
+  for (cp = lower, cp2 = upper; *cp != '\0'; ++cp, ++cp2)
+    if (toupper (*cp) != *cp2)
+      FAIL ("toupper ('%c') != '%c'", *cp, *cp2);
+  for (cp = upper; *cp != '\0'; ++cp)
+    if (toupper (*cp) != *cp)
+      FAIL ("toupper ('%c') != '%c'", *cp, *cp);
+  for (cp = digits; *cp != '\0'; ++cp)
+    if (toupper (*cp) != *cp)
+      FAIL ("toupper ('%c') != '%c'", *cp, *cp);
+  for (cp = cntrl; *cp != '\0'; ++cp)
+    if (toupper (*cp) != *cp)
+      FAIL ("toupper ('\\x%02x') != '\\x%02x'", *cp, *cp);
+
+
+  /* Now some locale specific tests.  */
+  while (! feof (stdin))
+    {
+      unsigned char *inp;
+      unsigned char *resp;
+
+      if (getline (&inpline, &inplinelen, stdin) <= 0
+	  || getline (&resline, &reslinelen, stdin) <= 0)
+	break;
+
+      inp = (unsigned char *) strchr (inpline, '\n');
+      if (inp != NULL)
+	*inp = '\0';
+      resp = (unsigned char *) strchr (resline, '\n');
+      if (resp != NULL)
+	*resp = '\0';
+
+      inp = (unsigned char *) inpline;
+      while (*inp != ' ' && *inp != '\t' && *inp && *inp != '\n'
+	     && *inp != '\0')
+	++inp;
+
+      if (*inp == '\0')
+	{
+	  printf ("line \"%s\" is without content\n", inpline);
+	  continue;
+	}
+      *inp++ = '\0';
+      while (*inp == ' ' || *inp == '\t')
+	++inp;
+
+      /* Try all classes.  */
+      for (n = 0; n < nclasses; ++n)
+	if (strcmp (inpline, classes[n].name) == 0)
+	  break;
+
+      resp = (unsigned char *) resline;
+      while (*resp == ' ' || *resp == '\t')
+	++resp;
+
+      if (strlen ((char *) inp) != strlen ((char *) resp))
+	{
+	  printf ("lines \"%.20s\"... and \"%.20s\" have not the same length\n",
+		  inp, resp);
+	  continue;
+	}
+
+      if (n < nclasses)
+	{
+	  if (strspn ((char *) resp, "01") != strlen ((char *) resp))
+	    {
+	      printf ("result string \"%s\" malformed\n", resp);
+	      continue;
+	    }
+
+	  printf ("  Locale-specific tests for `%s'\n", inpline);
+
+	  while (*inp != '\0' && *inp != '\n')
+	    {
+	      if (((__ctype_b[(unsigned int) *inp] & classes[n].mask) != 0)
+		  != (*resp != '0'))
+		{
+		  printf ("    is%s('%c' = '\\x%02x') %s true\n", inpline,
+			  *inp, *inp, *resp == '1' ? "not" : "is");
+		  ++errors;
+		}
+	      ++inp;
+	      ++resp;
+	    }
+	}
+      else if (strcmp (inpline, "tolower") == 0)
+	{
+	  while (*inp != '\0')
+	    {
+	      if (tolower (*inp) != *resp)
+		{
+		  printf ("    tolower('%c' = '\\x%02x') != '%c'\n",
+			  *inp, *inp, *resp);
+		  ++errors;
+		}
+	      ++inp;
+	      ++resp;
+	    }
+	}
+      else if (strcmp (inpline, "toupper") == 0)
+	{
+	  while (*inp != '\0')
+	    {
+	      if (toupper (*inp) != *resp)
+		{
+		  printf ("    toupper('%c' = '\\x%02x') != '%c'\n",
+			  *inp, *inp, *resp);
+		  ++errors;
+		}
+	      ++inp;
+	      ++resp;
+	    }
+	}
+      else
+	printf ("\"%s\": unknown class or map\n", inpline);
+    }
+
+
+  if (errors != 0)
+    {
+      printf ("  %d error%s for `%s' locale\n\n\n", errors,
+	      errors == 1 ? "" : "s", setlocale (LC_ALL, NULL));
+      return 1;
+    }
+
+  printf ("  No errors for `%s' locale\n\n\n", setlocale (LC_ALL, NULL));
+  return 0;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-digits.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-digits.c
new file mode 100644
index 00000000..8414a4b5
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-digits.c
@@ -0,0 +1,249 @@
+/* Copyright (C) 2000 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2000.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+#define ZERO  "\xe2\x82\x80"
+#define ONE   "\xe2\x82\x81"
+#define TWO   "\xe2\x82\x82"
+#define THREE "\xe2\x82\x83"
+#define FOUR  "\xe2\x82\x84"
+#define FIVE  "\xe2\x82\x85"
+#define SIX   "\xe2\x82\x86"
+#define SEVEN "\xe2\x82\x87"
+#define EIGHT "\xe2\x82\x88"
+#define NINE  "\xe2\x82\x89"
+
+static struct printf_int_test
+{
+  int n;
+  const char *format;
+  const char *expected;
+} printf_int_tests[] =
+{
+  {       0, "%I'10d", "       " ZERO },
+  {       1, "%I'10d", "       " ONE },
+  {       2, "%I'10d", "       " TWO },
+  {       3, "%I'10d", "       " THREE },
+  {       4, "%I'10d", "       " FOUR },
+  {       5, "%I'10d", "       " FIVE },
+  {       6, "%I'10d", "       " SIX },
+  {       7, "%I'10d", "       " SEVEN },
+  {       8, "%I'10d", "       " EIGHT },
+  {       9, "%I'10d", "       " NINE },
+  {      11, "%I'10d", "    " ONE ONE },
+  {      12, "%I'10d", "    " ONE TWO },
+  {     123, "%I10d",  " " ONE TWO THREE },
+  {     123, "%I'10d", " " ONE TWO THREE },
+  {    1234, "%I10d",  ONE TWO THREE FOUR },
+  {    1234, "%I'10d", ONE "," TWO THREE FOUR },
+  {   12345, "%I'10d", ONE TWO "," THREE FOUR FIVE },
+  {  123456, "%I'10d", ONE TWO THREE "," FOUR FIVE SIX },
+  { 1234567, "%I'10d", ONE "," TWO THREE FOUR "," FIVE SIX SEVEN }
+};
+#define nprintf_int_tests \
+  (sizeof (printf_int_tests) / sizeof (printf_int_tests[0]))
+
+#define WZERO  L"\x2080"
+#define WONE   L"\x2081"
+#define WTWO   L"\x2082"
+#define WTHREE L"\x2083"
+#define WFOUR  L"\x2084"
+#define WFIVE  L"\x2085"
+#define WSIX   L"\x2086"
+#define WSEVEN L"\x2087"
+#define WEIGHT L"\x2088"
+#define WNINE  L"\x2089"
+
+static struct wprintf_int_test
+{
+  int n;
+  const wchar_t *format;
+  const wchar_t *expected;
+} wprintf_int_tests[] =
+{
+  {       0, L"%I'10d", L"         " WZERO },
+  {       1, L"%I'10d", L"         " WONE },
+  {       2, L"%I'10d", L"         " WTWO },
+  {       3, L"%I'10d", L"         " WTHREE },
+  {       4, L"%I'10d", L"         " WFOUR },
+  {       5, L"%I'10d", L"         " WFIVE },
+  {       6, L"%I'10d", L"         " WSIX },
+  {       7, L"%I'10d", L"         " WSEVEN },
+  {       8, L"%I'10d", L"         " WEIGHT },
+  {       9, L"%I'10d", L"         " WNINE },
+  {      11, L"%I'10d", L"        " WONE WONE },
+  {      12, L"%I'10d", L"        " WONE WTWO },
+  {     123, L"%I10d",  L"       " WONE WTWO WTHREE },
+  {     123, L"%I'10d", L"       " WONE WTWO WTHREE },
+  {    1234, L"%I10d",  L"      " WONE WTWO WTHREE WFOUR },
+  {    1234, L"%I'10d", L"     " WONE L"," WTWO WTHREE WFOUR },
+  {   12345, L"%I'10d", L"    " WONE WTWO L"," WTHREE WFOUR WFIVE },
+  {  123456, L"%I'10d", L"   " WONE WTWO WTHREE L"," WFOUR WFIVE WSIX },
+  { 1234567, L"%I'10d", L" " WONE L"," WTWO WTHREE WFOUR L"," WFIVE WSIX WSEVEN }
+};
+#define nwprintf_int_tests \
+  (sizeof (wprintf_int_tests) / sizeof (wprintf_int_tests[0]))
+
+
+int
+main (void)
+{
+  int cnt;
+  int failures;
+  int status;
+
+  if (setlocale (LC_ALL, "test7") == NULL)
+    {
+      puts ("cannot set locale `test7'");
+      exit (1);
+    }
+  printf ("CODESET = \"%s\"\n", nl_langinfo (CODESET));
+
+  /* First: printf tests.  */
+  failures = 0;
+  for (cnt = 0; cnt < (int) nprintf_int_tests; ++cnt)
+    {
+      char buf[100];
+      ssize_t n;
+
+      n = snprintf (buf, sizeof buf, printf_int_tests[cnt].format,
+		    printf_int_tests[cnt].n);
+
+      printf ("%3d: got \"%s\", expected \"%s\"",
+	      cnt, buf, printf_int_tests[cnt].expected);
+
+      if (n != (ssize_t) strlen (printf_int_tests[cnt].expected)
+	  || strcmp (buf, printf_int_tests[cnt].expected) != 0)
+	{
+	  puts ("  -> FAILED");
+	  ++failures;
+	}
+      else
+	puts ("  -> OK");
+    }
+
+  printf ("%d failures in printf tests\n", failures);
+  status = failures != 0;
+
+  /* wprintf tests.  */
+  failures = 0;
+  for (cnt = 0; cnt < (int) nwprintf_int_tests; ++cnt)
+    {
+      wchar_t buf[100];
+      ssize_t n;
+
+      n = swprintf (buf, sizeof buf / sizeof (buf[0]),
+		    wprintf_int_tests[cnt].format,
+		    wprintf_int_tests[cnt].n);
+
+      printf ("%3d: got \"%ls\", expected \"%ls\"",
+	      cnt, buf, wprintf_int_tests[cnt].expected);
+
+      if (n != (ssize_t) wcslen (wprintf_int_tests[cnt].expected)
+	  || wcscmp (buf, wprintf_int_tests[cnt].expected) != 0)
+	{
+	  puts ("  -> FAILED");
+	  ++failures;
+	}
+      else
+	puts ("  -> OK");
+    }
+
+  printf ("%d failures in wprintf tests\n", failures);
+  status = failures != 0;
+
+  /* ctype tests.  This makes sure that the multibyte chracter digit
+     representations are not handle in this table.  */
+  failures = 0;
+  for (cnt = 0; cnt < 256; ++cnt)
+    if (cnt >= '0' && cnt <= '9')
+      {
+	if (! isdigit (cnt))
+	  {
+	    printf ("isdigit ('%c') == 0\n", cnt);
+	    ++failures;
+	  }
+      }
+    else
+      {
+	if (isdigit (cnt))
+	  {
+	    printf ("isdigit (%d) != 0\n", cnt);
+	    ++failures;
+	  }
+      }
+
+  printf ("%d failures in ctype tests\n", failures);
+  status = failures != 0;
+
+  /* wctype tests.  This makes sure the second set of digits is also
+     recorded.  */
+  failures = 0;
+  for (cnt = 0; cnt < 256; ++cnt)
+    if (cnt >= '0' && cnt <= '9')
+      {
+	if (! iswdigit (cnt))
+	  {
+	    printf ("iswdigit (L'%c') == 0\n", cnt);
+	    ++failures;
+	  }
+      }
+    else
+      {
+	if (iswdigit (cnt))
+	  {
+	    printf ("iswdigit (%d) != 0\n", cnt);
+	    ++failures;
+	  }
+      }
+
+  for (cnt = 0x2070; cnt < 0x2090; ++cnt)
+    if (cnt >= 0x2080 && cnt <= 0x2089)
+      {
+	if (! iswdigit (cnt))
+	  {
+	    printf ("iswdigit (U%04X) == 0\n", cnt);
+	    ++failures;
+	  }
+      }
+    else
+      {
+	if (iswdigit (cnt))
+	  {
+	    printf ("iswdigit (U%04X) != 0\n", cnt);
+	    ++failures;
+	  }
+      }
+
+  printf ("%d failures in wctype tests\n", failures);
+  status = failures != 0;
+
+  return status;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-fmon.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-fmon.c
new file mode 100644
index 00000000..11093ce6
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-fmon.c
@@ -0,0 +1,68 @@
+/* Testing the implementation of strfmon(3).
+   Copyright (C) 1996, 1997, 2000, 2003, 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jochen Hein , 1997.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/*
+  test-strfmon gets called with three parameters:
+   - the locale
+   - the format-string to be used
+   - the actual number to be formatted
+   - the expected string
+   If the test passes, test-strfmon terminates with returncode 0,
+   otherwise with 1
+*/
+#define EXIT_SUCCESS 0
+#define EXIT_FAILURE 1
+#define EXIT_SETLOCALE 2
+#define EXIT_STRFMON 3
+
+int
+main (int argc, char *argv[])
+{
+  char *s = malloc (201);
+
+  if (setlocale (LC_MONETARY, argv[1]) == NULL)
+    {
+      fprintf (stderr, "setlocale(LC_MONETARY, \"%s\"): %m\n", argv[1]);
+      exit (EXIT_SETLOCALE);
+    }
+
+  if (strfmon (s, 200, argv[2], (double) atof (argv[3])) == -1)
+    {
+      perror ("strfmon");
+      exit (EXIT_STRFMON);
+    }
+
+  if (strcmp (s, argv[4]) != 0)
+    {
+      printf ("\
+Locale: \"%s\" Format: \"%s\" Value: \"%s\" Received: \"%s\" Expected: \"%s\" => %s\n",
+	      argv[1], argv[2], argv[3], s, argv[4],
+	      strcmp (s, argv[4]) != 0 ? "false" : "correct");
+      exit (EXIT_FAILURE);
+    }
+
+  return EXIT_SUCCESS;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-langinfo.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-langinfo.c
new file mode 100644
index 00000000..e95f0da5
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-langinfo.c
@@ -0,0 +1,284 @@
+/* Test program for nl_langinfo() function.
+   Copyright (C) 2000 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper .
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+
+
+struct map
+{
+  const char *str;
+  int val;
+} map[] =
+{
+#define VAL(name) { #name, name }
+  VAL (ABDAY_1),
+  VAL (ABDAY_2),
+  VAL (ABDAY_3),
+  VAL (ABDAY_4),
+  VAL (ABDAY_5),
+  VAL (ABDAY_6),
+  VAL (ABDAY_7),
+  VAL (ABMON_1),
+  VAL (ABMON_10),
+  VAL (ABMON_11),
+  VAL (ABMON_12),
+  VAL (ABMON_2),
+  VAL (ABMON_3),
+  VAL (ABMON_4),
+  VAL (ABMON_5),
+  VAL (ABMON_6),
+  VAL (ABMON_7),
+  VAL (ABMON_8),
+  VAL (ABMON_9),
+  VAL (ALT_DIGITS),
+  VAL (AM_STR),
+  VAL (CRNCYSTR),
+  VAL (CURRENCY_SYMBOL),
+  VAL (DAY_1),
+  VAL (DAY_2),
+  VAL (DAY_3),
+  VAL (DAY_4),
+  VAL (DAY_5),
+  VAL (DAY_6),
+  VAL (DAY_7),
+  VAL (DECIMAL_POINT),
+  VAL (D_FMT),
+  VAL (D_T_FMT),
+  VAL (ERA),
+  VAL (ERA_D_FMT),
+  VAL (ERA_D_T_FMT),
+  VAL (ERA_T_FMT),
+  VAL (ERA_YEAR),
+  VAL (FRAC_DIGITS),
+  VAL (GROUPING),
+  VAL (INT_CURR_SYMBOL),
+  VAL (INT_FRAC_DIGITS),
+  VAL (MON_1),
+  VAL (MON_10),
+  VAL (MON_11),
+  VAL (MON_12),
+  VAL (MON_2),
+  VAL (MON_3),
+  VAL (MON_4),
+  VAL (MON_5),
+  VAL (MON_6),
+  VAL (MON_7),
+  VAL (MON_8),
+  VAL (MON_9),
+  VAL (MON_DECIMAL_POINT),
+  VAL (MON_GROUPING),
+  VAL (MON_THOUSANDS_SEP),
+  VAL (NEGATIVE_SIGN),
+  VAL (NOEXPR),
+  VAL (NOSTR),
+  VAL (N_CS_PRECEDES),
+  VAL (N_SEP_BY_SPACE),
+  VAL (N_SIGN_POSN),
+  VAL (PM_STR),
+  VAL (POSITIVE_SIGN),
+  VAL (P_CS_PRECEDES),
+  VAL (P_SEP_BY_SPACE),
+  VAL (P_SIGN_POSN),
+  VAL (RADIXCHAR),
+  VAL (THOUSANDS_SEP),
+  VAL (THOUSEP),
+  VAL (T_FMT),
+  VAL (T_FMT_AMPM),
+  VAL (YESEXPR),
+  VAL (YESSTR)
+};
+
+
+static int
+map_paramstr (const char *str)
+{
+  int low = 0;
+  int high = sizeof (map) / sizeof (map[0]);
+
+  while (low < high)
+    {
+      int med = (low + high) / 2;
+      int cmpres;
+
+      cmpres = strcmp (str, map[med].str);
+      if (cmpres == 0)
+	return map[med].val;
+      else if (cmpres > 0)
+	low = med + 1;
+      else
+	high = med;
+    }
+
+  return -1;
+}
+
+
+#ifdef DEBUG
+# define REASON(str) printf ("\"%s\" ignored: %s\n", buf, str)
+#else
+# define REASON(str)
+#endif
+
+int
+main (void)
+{
+  int result = 0;
+
+  while (! feof (stdin))
+    {
+      char buf[1000];
+      char *rp;
+      char *locale;
+      char *paramstr;
+      char *expected;
+      char *actual;
+      int param;
+
+      if (fgets (buf, sizeof (buf), stdin) == NULL)
+	break;
+
+      /* Split the fields.   There are three is them:
+	 1. locale
+	 2. langinfo() parameter
+	 3. expected result; this can be a string with white space etc.
+      */
+      rp = buf;
+      while (*rp == ' ' || *rp == '\t')
+	++rp;
+
+      if  (*rp == '#')
+	{
+	  /* It's a comment line.  Ignore it.  */
+	  REASON ("comment");
+	  continue;
+	}
+      locale = rp;
+
+      while (*rp != '\0' && *rp != ' ' && *rp != '\t' && *rp != '\n')
+	++rp;
+      if (*rp == '\0' || *rp == '\n')
+	{
+	  /* Incomplete line.  */
+	  REASON ("incomplete line");
+	  continue;
+	}
+      *rp++ = '\0';
+
+      while (*rp == ' ' || *rp == '\t')
+	++rp;
+      paramstr = rp;
+
+      while (*rp != '\0' && *rp != ' ' && *rp != '\t' && *rp != '\n')
+	++rp;
+      if (*rp == '\0' || *rp == '\n')
+	{
+	  /* Incomplete line.  */
+	  REASON ("incomplete line");
+	  continue;
+	}
+      *rp++ = '\0';
+
+      while (*rp == ' ' || *rp == '\t')
+	++rp;
+
+      if (*rp == '"')
+	{
+	  char *wp;
+
+	  expected = wp = ++rp;
+	  while (*rp != '"' && *rp != '\n' && *rp != '\0')
+	    {
+	      if (*rp == '\\')
+		{
+		  ++rp;
+		  if (*rp == '\0')
+		    break;
+		  if (*rp >= '0' && *rp <= '9')
+		    {
+		      int val = *rp - '0';
+		      if (rp[1] >= '0' && rp[1] <= '9')
+			{
+			  ++rp;
+			  val *= 10;
+			  val += *rp - '0';
+			  if (rp[1] >= '0' && rp[1] <= '9')
+			    {
+			      ++rp;
+			      val *= 10;
+			      val += *rp - '0';
+			    }
+			}
+		      *rp = val;
+		    }
+		}
+	      *wp++ = *rp++;
+	    }
+
+	  if (*rp != '"')
+	    {
+	      REASON ("missing '\"'");
+	      continue;
+	    }
+
+	  *wp = '\0';
+	}
+      else
+	{
+	  expected = rp;
+	  while (*rp != '\0' && *rp != '\n')
+	    ++rp;
+	  *rp = '\0';
+	}
+
+      param = map_paramstr (paramstr);
+      if (param == -1)
+	{
+	  /* Invalid parameter.  */
+	  REASON ("invalid parameter");
+	  continue;
+	}
+
+      /* Set the locale and check whether it worked.  */
+      printf ("LC_ALL=%s nl_langinfo(%s)", locale, paramstr);
+      setlocale (LC_ALL, locale);
+      if (strcmp (locale, setlocale (LC_ALL, NULL)) != 0)
+	{
+	  puts (": failed to set locale");
+	  result = 1;
+	  continue;
+	}
+
+      actual = nl_langinfo (param);
+      printf (" = \"%s\", ", actual);
+
+      if (strcmp (actual, expected) == 0)
+	puts ("OK");
+      else
+	{
+	  printf ("FAILED (expected: %s)\n", expected);
+	  result = 1;
+	}
+    }
+
+  return result;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-langinfo.input b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-langinfo.input
new file mode 100644
index 00000000..0a05ab86
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-langinfo.input
@@ -0,0 +1,303 @@
+#! /bin/sh
+# Input file for tst-langinfo.
+# Copyright (C) 2000, 2001, 2003 Free Software Foundation, Inc.
+# This file is part of the GNU C Library.
+#
+
+# The GNU C Library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+
+# The GNU C Library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+
+# You should have received a copy of the GNU Lesser General Public
+# License along with the GNU C Library; if not, write to the Free
+# Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+# 02111-1307 USA.
+
+
+# Run the test program.
+# Only decimal numerical escape sequences allowed in strings.
+C                    ABDAY_1     Sun
+C                    ABDAY_2     Mon
+C                    ABDAY_3     Tue
+C                    ABDAY_4     Wed
+C                    ABDAY_5     Thu
+C                    ABDAY_6     Fri
+C                    ABDAY_7     Sat
+C                    DAY_1       Sunday
+C                    DAY_2       Monday
+C                    DAY_3       Tuesday
+C                    DAY_4       Wednesday
+C                    DAY_5       Thursday
+C                    DAY_6       Friday
+C                    DAY_7       Saturday
+C                    ABMON_1     Jan
+C                    ABMON_2     Feb
+C                    ABMON_3     Mar
+C                    ABMON_4     Apr
+C                    ABMON_5     May
+C                    ABMON_6     Jun
+C                    ABMON_7     Jul
+C                    ABMON_8     Aug
+C                    ABMON_9     Sep
+C                    ABMON_10    Oct
+C                    ABMON_11    Nov
+C                    ABMON_12    Dec
+C                    MON_1       January
+C                    MON_2       February
+C                    MON_3       March
+C                    MON_4       April
+C                    MON_5       May
+C                    MON_6       June
+C                    MON_7       July
+C                    MON_8       August
+C                    MON_9       September
+C                    MON_10      October
+C                    MON_11      November
+C                    MON_12      December
+C                    AM_STR      AM
+C                    PM_STR      PM
+C                    D_T_FMT     "%a %b %e %H:%M:%S %Y"
+C                    D_FMT       "%m/%d/%y"
+C                    T_FMT       "%H:%M:%S"
+C                    T_FMT_AMPM  "%I:%M:%S %p"
+C                    ABDAY_1     Sun
+C                    ABDAY_2     Mon
+C                    ABDAY_3     Tue
+C                    ABDAY_4     Wed
+C                    ABDAY_5     Thu
+C                    ABDAY_6     Fri
+C                    ABDAY_7     Sat
+C                    DAY_1       Sunday
+C                    DAY_2       Monday
+C                    DAY_3       Tuesday
+C                    DAY_4       Wednesday
+C                    DAY_5       Thursday
+C                    DAY_6       Friday
+C                    DAY_7       Saturday
+C                    RADIXCHAR   .
+C                    THOUSEP     ""
+C                    YESEXPR     ^[yY]
+C                    NOEXPR      ^[nN]
+en_US.ISO-8859-1     ABMON_1     Jan
+en_US.ISO-8859-1     ABMON_2     Feb
+en_US.ISO-8859-1     ABMON_3     Mar
+en_US.ISO-8859-1     ABMON_4     Apr
+en_US.ISO-8859-1     ABMON_5     May
+en_US.ISO-8859-1     ABMON_6     Jun
+en_US.ISO-8859-1     ABMON_7     Jul
+en_US.ISO-8859-1     ABMON_8     Aug
+en_US.ISO-8859-1     ABMON_9     Sep
+en_US.ISO-8859-1     ABMON_10    Oct
+en_US.ISO-8859-1     ABMON_11    Nov
+en_US.ISO-8859-1     ABMON_12    Dec
+en_US.ISO-8859-1     MON_1       January
+en_US.ISO-8859-1     MON_2       February
+en_US.ISO-8859-1     MON_3       March
+en_US.ISO-8859-1     MON_4       April
+en_US.ISO-8859-1     MON_5       May
+en_US.ISO-8859-1     MON_6       June
+en_US.ISO-8859-1     MON_7       July
+en_US.ISO-8859-1     MON_8       August
+en_US.ISO-8859-1     MON_9       September
+en_US.ISO-8859-1     MON_10      October
+en_US.ISO-8859-1     MON_11      November
+en_US.ISO-8859-1     MON_12      December
+en_US.ISO-8859-1     AM_STR      AM
+en_US.ISO-8859-1     PM_STR      PM
+en_US.ISO-8859-1     D_T_FMT     "%a %d %b %Y %r %Z"
+en_US.ISO-8859-1     D_FMT       "%m/%d/%Y"
+en_US.ISO-8859-1     T_FMT       "%r"
+en_US.ISO-8859-1     T_FMT_AMPM  "%I:%M:%S %p"
+en_US.ISO-8859-1     RADIXCHAR   .
+en_US.ISO-8859-1     THOUSEP     ,
+en_US.ISO-8859-1     YESEXPR     ^[yY].*
+en_US.ISO-8859-1     NOEXPR      ^[nN].*
+de_DE.ISO-8859-1     ABDAY_1     So
+de_DE.ISO-8859-1     ABDAY_2     Mo
+de_DE.ISO-8859-1     ABDAY_3     Di
+de_DE.ISO-8859-1     ABDAY_4     Mi
+de_DE.ISO-8859-1     ABDAY_5     Do
+de_DE.ISO-8859-1     ABDAY_6     Fr
+de_DE.ISO-8859-1     ABDAY_7     Sa
+de_DE.ISO-8859-1     DAY_1       Sonntag
+de_DE.ISO-8859-1     DAY_2       Montag
+de_DE.ISO-8859-1     DAY_3       Dienstag
+de_DE.ISO-8859-1     DAY_4       Mittwoch
+de_DE.ISO-8859-1     DAY_5       Donnerstag
+de_DE.ISO-8859-1     DAY_6       Freitag
+de_DE.ISO-8859-1     DAY_7       Samstag
+de_DE.ISO-8859-1     ABMON_1     Jan
+de_DE.ISO-8859-1     ABMON_2     Feb
+de_DE.ISO-8859-1     ABMON_3     Mär
+de_DE.ISO-8859-1     ABMON_4     Apr
+de_DE.ISO-8859-1     ABMON_5     Mai
+de_DE.ISO-8859-1     ABMON_6     Jun
+de_DE.ISO-8859-1     ABMON_7     Jul
+de_DE.ISO-8859-1     ABMON_8     Aug
+de_DE.ISO-8859-1     ABMON_9     Sep
+de_DE.ISO-8859-1     ABMON_10    Okt
+de_DE.ISO-8859-1     ABMON_11    Nov
+de_DE.ISO-8859-1     ABMON_12    Dez
+de_DE.ISO-8859-1     MON_1       Januar
+de_DE.ISO-8859-1     MON_2       Februar
+de_DE.ISO-8859-1     MON_3       März
+de_DE.ISO-8859-1     MON_4       April
+de_DE.ISO-8859-1     MON_5       Mai
+de_DE.ISO-8859-1     MON_6       Juni
+de_DE.ISO-8859-1     MON_7       Juli
+de_DE.ISO-8859-1     MON_8       August
+de_DE.ISO-8859-1     MON_9       September
+de_DE.ISO-8859-1     MON_10      Oktober
+de_DE.ISO-8859-1     MON_11      November
+de_DE.ISO-8859-1     MON_12      Dezember
+de_DE.ISO-8859-1     D_T_FMT     "%a %d %b %Y %T %Z"
+de_DE.ISO-8859-1     D_FMT       "%d.%m.%Y"
+de_DE.ISO-8859-1     T_FMT       "%T"
+de_DE.ISO-8859-1     RADIXCHAR   ,
+de_DE.ISO-8859-1     THOUSEP     .
+de_DE.ISO-8859-1     YESEXPR     ^[jJyY].*
+de_DE.ISO-8859-1     NOEXPR      ^[nN].*
+de_DE.UTF-8          ABDAY_1     So
+de_DE.UTF-8          ABDAY_2     Mo
+de_DE.UTF-8          ABDAY_3     Di
+de_DE.UTF-8          ABDAY_4     Mi
+de_DE.UTF-8          ABDAY_5     Do
+de_DE.UTF-8          ABDAY_6     Fr
+de_DE.UTF-8          ABDAY_7     Sa
+de_DE.UTF-8          DAY_1       Sonntag
+de_DE.UTF-8          DAY_2       Montag
+de_DE.UTF-8          DAY_3       Dienstag
+de_DE.UTF-8          DAY_4       Mittwoch
+de_DE.UTF-8          DAY_5       Donnerstag
+de_DE.UTF-8          DAY_6       Freitag
+de_DE.UTF-8          DAY_7       Samstag
+de_DE.UTF-8          ABMON_1     Jan
+de_DE.UTF-8          ABMON_2     Feb
+de_DE.UTF-8          ABMON_3     Mär
+de_DE.UTF-8          ABMON_4     Apr
+de_DE.UTF-8          ABMON_5     Mai
+de_DE.UTF-8          ABMON_6     Jun
+de_DE.UTF-8          ABMON_7     Jul
+de_DE.UTF-8          ABMON_8     Aug
+de_DE.UTF-8          ABMON_9     Sep
+de_DE.UTF-8          ABMON_10    Okt
+de_DE.UTF-8          ABMON_11    Nov
+de_DE.UTF-8          ABMON_12    Dez
+de_DE.UTF-8          MON_1       Januar
+de_DE.UTF-8          MON_2       Februar
+de_DE.UTF-8          MON_3       März
+de_DE.UTF-8          MON_4       April
+de_DE.UTF-8          MON_5       Mai
+de_DE.UTF-8          MON_6       Juni
+de_DE.UTF-8          MON_7       Juli
+de_DE.UTF-8          MON_8       August
+de_DE.UTF-8          MON_9       September
+de_DE.UTF-8          MON_10      Oktober
+de_DE.UTF-8          MON_11      November
+de_DE.UTF-8          MON_12      Dezember
+de_DE.UTF-8          D_T_FMT     "%a %d %b %Y %T %Z"
+de_DE.UTF-8          D_FMT       "%d.%m.%Y"
+de_DE.UTF-8          T_FMT       "%T"
+de_DE.UTF-8          RADIXCHAR   ,
+de_DE.UTF-8          THOUSEP     .
+de_DE.UTF-8          YESEXPR     ^[jJyY].*
+de_DE.UTF-8          NOEXPR      ^[nN].*
+fr_FR.ISO-8859-1     ABDAY_1     dim
+fr_FR.ISO-8859-1     ABDAY_2     lun
+fr_FR.ISO-8859-1     ABDAY_3     mar
+fr_FR.ISO-8859-1     ABDAY_4     mer
+fr_FR.ISO-8859-1     ABDAY_5     jeu
+fr_FR.ISO-8859-1     ABDAY_6     ven
+fr_FR.ISO-8859-1     ABDAY_7     sam
+fr_FR.ISO-8859-1     DAY_1       dimanche
+fr_FR.ISO-8859-1     DAY_2       lundi
+fr_FR.ISO-8859-1     DAY_3       mardi
+fr_FR.ISO-8859-1     DAY_4       mercredi
+fr_FR.ISO-8859-1     DAY_5       jeudi
+fr_FR.ISO-8859-1     DAY_6       vendredi
+fr_FR.ISO-8859-1     DAY_7       samedi
+fr_FR.ISO-8859-1     ABMON_1     jan
+fr_FR.ISO-8859-1     ABMON_2     fév
+fr_FR.ISO-8859-1     ABMON_3     mar
+fr_FR.ISO-8859-1     ABMON_4     avr
+fr_FR.ISO-8859-1     ABMON_5     mai
+fr_FR.ISO-8859-1     ABMON_6     jun
+fr_FR.ISO-8859-1     ABMON_7     jui
+fr_FR.ISO-8859-1     ABMON_8     aoû
+fr_FR.ISO-8859-1     ABMON_9     sep
+fr_FR.ISO-8859-1     ABMON_10    oct
+fr_FR.ISO-8859-1     ABMON_11    nov
+fr_FR.ISO-8859-1     ABMON_12    déc
+fr_FR.ISO-8859-1     MON_1       janvier
+fr_FR.ISO-8859-1     MON_2       février
+fr_FR.ISO-8859-1     MON_3       mars
+fr_FR.ISO-8859-1     MON_4       avril
+fr_FR.ISO-8859-1     MON_5       mai
+fr_FR.ISO-8859-1     MON_6       juin
+fr_FR.ISO-8859-1     MON_7       juillet
+fr_FR.ISO-8859-1     MON_8       août
+fr_FR.ISO-8859-1     MON_9       septembre
+fr_FR.ISO-8859-1     MON_10      octobre
+fr_FR.ISO-8859-1     MON_11      novembre
+fr_FR.ISO-8859-1     MON_12      décembre
+fr_FR.ISO-8859-1     D_T_FMT     "%a %d %b %Y %T %Z"
+fr_FR.ISO-8859-1     D_FMT       "%d.%m.%Y"
+fr_FR.ISO-8859-1     T_FMT       "%T"
+fr_FR.ISO-8859-1     RADIXCHAR   ,
+fr_FR.ISO-8859-1     THOUSEP     ""
+fr_FR.ISO-8859-1     YESEXPR     ^[oOyY].*
+fr_FR.ISO-8859-1     NOEXPR      ^[nN].*
+ja_JP.EUC-JP         ABDAY_1     Æü
+ja_JP.EUC-JP         ABDAY_2     ·î
+ja_JP.EUC-JP         ABDAY_3     ²Ð
+ja_JP.EUC-JP         ABDAY_4     ¿å
+ja_JP.EUC-JP         ABDAY_5     ÌÚ
+ja_JP.EUC-JP         ABDAY_6     ¶â
+ja_JP.EUC-JP         ABDAY_7     ÅÚ
+ja_JP.EUC-JP         DAY_1       ÆüÍËÆü
+ja_JP.EUC-JP         DAY_2       ·îÍËÆü
+ja_JP.EUC-JP         DAY_3       ²ÐÍËÆü
+ja_JP.EUC-JP         DAY_4       ¿åÍËÆü
+ja_JP.EUC-JP         DAY_5       ÌÚÍËÆü
+ja_JP.EUC-JP         DAY_6       ¶âÍËÆü
+ja_JP.EUC-JP         DAY_7       ÅÚÍËÆü
+ja_JP.EUC-JP         ABMON_1     " 1·î"
+ja_JP.EUC-JP         ABMON_2     " 2·î"
+ja_JP.EUC-JP         ABMON_3     " 3·î"
+ja_JP.EUC-JP         ABMON_4     " 4·î"
+ja_JP.EUC-JP         ABMON_5     " 5·î"
+ja_JP.EUC-JP         ABMON_6     " 6·î"
+ja_JP.EUC-JP         ABMON_7     " 7·î"
+ja_JP.EUC-JP         ABMON_8     " 8·î"
+ja_JP.EUC-JP         ABMON_9     " 9·î"
+ja_JP.EUC-JP         ABMON_10    "10·î"
+ja_JP.EUC-JP         ABMON_11    "11·î"
+ja_JP.EUC-JP         ABMON_12    "12·î"
+ja_JP.EUC-JP         MON_1       "1·î"
+ja_JP.EUC-JP         MON_2       "2·î"
+ja_JP.EUC-JP         MON_3       "3·î"
+ja_JP.EUC-JP         MON_4       "4·î"
+ja_JP.EUC-JP         MON_5       "5·î"
+ja_JP.EUC-JP         MON_6       "6·î"
+ja_JP.EUC-JP         MON_7       "7·î"
+ja_JP.EUC-JP         MON_8       "8·î"
+ja_JP.EUC-JP         MON_9       "9·î"
+ja_JP.EUC-JP         MON_10      "10·î"
+ja_JP.EUC-JP         MON_11      "11·î"
+ja_JP.EUC-JP         MON_12      "12·î"
+ja_JP.EUC-JP         T_FMT_AMPM  "%p%I»þ%Mʬ%SÉÃ"
+ja_JP.EUC-JP         ERA_D_FMT   "%EY%m·î%dÆü"
+ja_JP.EUC-JP         ERA_D_T_FMT "%EY%m·î%dÆü %H»þ%Mʬ%SÉÃ"
+ja_JP.EUC-JP         RADIXCHAR   .
+ja_JP.EUC-JP         THOUSEP     ,
+ja_JP.EUC-JP         YESEXPR     ^([yY£ù£Ù]|¤Ï¤¤|¥Ï¥¤)
+ja_JP.EUC-JP         NOEXPR      ^([nN£î£Î]|¤¤¤¤¤¨|¥¤¥¤¥¨)
+# Is CRNCYSTR supposed to be the national or international sign?
+# ja_JP.EUC-JP         CRNCYSTR    JPY
+ja_JP.EUC-JP         CODESET     EUC-JP
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-leaks.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-leaks.c
new file mode 100644
index 00000000..7a4b557f
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-leaks.c
@@ -0,0 +1,18 @@
+#include 
+#include 
+
+int
+main (void)
+{
+  int cnt;
+
+  mtrace ();
+
+  for (cnt = 0; cnt < 100; ++cnt)
+    {
+      setlocale (LC_ALL, "de_DE.ISO-8859-1");
+      setlocale (LC_ALL, "de_DE.UTF-8");
+    }
+
+  return 0;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-mbswcs1.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-mbswcs1.c
new file mode 100644
index 00000000..fb2ea84c
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-mbswcs1.c
@@ -0,0 +1,63 @@
+/* Test restarting behaviour of mbrtowc.
+   Copyright (C) 2000, 2005 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Bruno Haible .
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+
+#define show(expr, nexp, wcexp) \
+  n = expr;								  \
+  printf (#expr " -> %Zd", n);						  \
+  printf (", wc = %lu", (unsigned long int) wc);			  \
+  if (n != (size_t) nexp || wc != wcexp)				  \
+    {									  \
+      printf (", expected %Zd and %lu", nexp, (unsigned long int) wcexp); \
+      result = 1;							  \
+    }									  \
+  putc ('\n', stdout)
+
+int
+main (void)
+{
+  const unsigned char buf[6] = { 0x25,  0xe2, 0x82, 0xac,  0xce, 0xbb };
+  mbstate_t state;
+  wchar_t wc = 42;
+  size_t n;
+  int result = 0;
+  const char *used_locale;
+
+  setlocale (LC_CTYPE, "de_DE.UTF-8");
+  /* Double check.  */
+  used_locale = setlocale (LC_CTYPE, NULL);
+  printf ("used locale: \"%s\"\n", used_locale);
+  result = strcmp (used_locale, "de_DE.UTF-8");
+
+  memset (&state, '\0', sizeof (state));
+
+  show (mbrtowc (&wc, (const char *) buf + 0, 1, &state), 1, 37);
+  show (mbrtowc (&wc, (const char *) buf + 1, 1, &state), -2, 37);
+  show (mbrtowc (&wc, (const char *) buf + 2, 3, &state), 2, 8364);
+  show (mbrtowc (&wc, (const char *) buf + 4, 1, &state), -2, 8364);
+  show (mbrtowc (&wc, (const char *) buf + 5, 1, &state), 1, 955);
+  show (mbrtowc (&wc, (const char *) buf + 5, 1, &state), -1, 955);
+
+  return result;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-mbswcs2.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-mbswcs2.c
new file mode 100644
index 00000000..49f13cc8
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-mbswcs2.c
@@ -0,0 +1,65 @@
+/* Test restarting behaviour of mbsnrtowcs.
+   Copyright (C) 2000 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Bruno Haible .
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+
+#define show(expr, nexp, wcexp, end) \
+  n = expr;								\
+  printf (#expr " -> %Zd", n);						\
+  printf (", wc = %lu, src = buf+%d", (unsigned long int) wc,		\
+	  src - (const char *) buf);					\
+  if (n != (size_t) nexp || wc != wcexp || src != (const char *) (end))	\
+    {									\
+      printf (", expected %Zd and %lu and buf+%d", nexp,		\
+	      (unsigned long int) wcexp, (end) - buf);			\
+      result = 1;							\
+    }									\
+  putc ('\n', stdout)
+
+int
+main (void)
+{
+  unsigned char buf[6] = { 0x25,  0xe2, 0x82, 0xac,  0xce, 0xbb };
+  mbstate_t state;
+  const char *src;
+  wchar_t wc = 42;
+  size_t n;
+  int result = 0;
+  const char *used_locale;
+
+  setlocale (LC_CTYPE,"de_DE.UTF-8");
+  /* Double check.  */
+  used_locale = setlocale (LC_CTYPE, NULL);
+  printf ("used locale: \"%s\"\n", used_locale);
+  result = strcmp (used_locale, "de_DE.UTF-8");
+
+  memset (&state, '\0', sizeof (state));
+
+  src = (const char *) buf;
+  show (mbsnrtowcs (&wc, &src, 1, 1, &state), 1, 37, buf + 1);
+  show (mbsnrtowcs (&wc, &src, 3, 1, &state), 1, 8364, buf + 4);
+  show (mbsnrtowcs (&wc, &src, 1, 1, &state), 0, 8364, buf + 5);
+  show (mbsnrtowcs (&wc, &src, 1, 1, &state), 1, 955, buf + 6);
+
+  return result;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-mbswcs3.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-mbswcs3.c
new file mode 100644
index 00000000..0c4af4c1
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-mbswcs3.c
@@ -0,0 +1,76 @@
+/* Test restarting behaviour of wcsrtombs.
+   Copyright (C) 2000 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Bruno Haible .
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+
+#define show(expr, nexp, srcexp, bufexp) \
+  {									\
+    size_t res = expr;							\
+    printf (#expr " -> %Zd", res);					\
+    dst += res;								\
+    printf (", src = srcbuf+%td, dst = buf+%td",			\
+	    src - srcbuf, dst - (char *) buf);				\
+    if (res != nexp || src != (srcexp) || dst != (char *) (bufexp))	\
+      {									\
+	printf (", expected %Zd and srcbuf+%td and buf+%td", nexp,	\
+		(srcexp) - srcbuf, (bufexp) - (unsigned char *) buf);	\
+	result = 1;							\
+      }									\
+    putc ('\n', stdout);						\
+  }
+
+int
+main (void)
+{
+  unsigned char buf[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+  const unsigned char bufcheck[6] = { 0x25, 0xe2, 0x82, 0xac, 0xce, 0xbb };
+  const wchar_t srcbuf[4] = { 0x25, 0x20ac, 0x03bb, 0 };
+  mbstate_t state;
+  const wchar_t *src;
+  char *dst;
+  int result = 0;
+  const char *used_locale;
+
+  setlocale (LC_CTYPE, "de_DE.UTF-8");
+  /* Double check.  */
+  used_locale = setlocale (LC_CTYPE, NULL);
+  printf ("used locale: \"%s\"\n", used_locale);
+  result = strcmp (used_locale, "de_DE.UTF-8");
+
+  memset (&state, '\0', sizeof (state));
+
+  src = srcbuf;
+  dst = (char *) buf;
+  show (wcsrtombs (dst, &src, 1, &state), 1, srcbuf + 1, buf + 1);
+  show (wcsrtombs (dst, &src, 1, &state), 0, srcbuf + 1, buf + 1);
+  show (wcsrtombs (dst, &src, 4, &state), 3, srcbuf + 2, buf + 4);
+  show (wcsrtombs (dst, &src, 2, &state), 2, srcbuf + 3, buf + 6);
+
+  if (memcmp (buf, bufcheck, 6))
+    {
+      puts ("wrong results");
+      result = 1;
+    }
+
+  return result;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-mbswcs4.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-mbswcs4.c
new file mode 100644
index 00000000..e02b6756
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-mbswcs4.c
@@ -0,0 +1,63 @@
+/* Test restarting behaviour of mbsrtowcs.
+   Copyright (C) 2000 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+
+#define show(expr, nexp, wcexp, end) \
+  n = expr;								\
+  printf (#expr " -> %Zd", n);						\
+  printf (", wc = %lu, src = buf+%d", (unsigned long int) wc,		\
+	  src - (const char *) buf);					\
+  if (n != (size_t) nexp || wc != wcexp || src != (const char *) (end))	\
+    {									\
+      printf (", expected %Zd and %lu and buf+%d", nexp,		\
+	      (unsigned long int) wcexp, (end) - buf);			\
+      result = 1;							\
+    }									\
+  putc ('\n', stdout)
+
+int
+main (void)
+{
+  unsigned char buf[6] = { 0x25,  0xe2, 0x82, 0xac,  0xce, 0xbb };
+  mbstate_t state;
+  const char *src;
+  wchar_t wc = 42;
+  size_t n;
+  int result = 0;
+  const char *used_locale;
+
+  setlocale (LC_CTYPE,"de_DE.UTF-8");
+  /* Double check.  */
+  used_locale = setlocale (LC_CTYPE, NULL);
+  printf ("used locale: \"%s\"\n", used_locale);
+  result = strcmp (used_locale, "de_DE.UTF-8");
+
+  memset (&state, '\0', sizeof (state));
+
+  src = (const char *) buf;
+  show (mbsrtowcs (&wc, &src, 1, &state), 1, 37, buf + 1);
+  show (mbsrtowcs (&wc, &src, 1, &state), 1, 8364, buf + 4);
+  show (mbsrtowcs (&wc, &src, 1, &state), 1, 955, buf + 6);
+
+  return result;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-mbswcs5.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-mbswcs5.c
new file mode 100644
index 00000000..7cab97e7
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-mbswcs5.c
@@ -0,0 +1,75 @@
+/* Test restarting behaviour of wcrtomb.
+   Copyright (C) 2000 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Bruno Haible .
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+
+#define show(expr, nexp, bufexp) \
+  {									\
+    size_t res = expr;							\
+    printf (#expr " -> %Zd", res);					\
+    dst += res;								\
+    printf (", dst = buf+%td", dst - (char *) buf);			\
+    if (res != nexp || dst != (char *) (bufexp))			\
+      {									\
+	printf (", expected %Zd and buf+%td", nexp,			\
+		(bufexp) - (unsigned char *) buf);			\
+	result = 1;							\
+      }									\
+    putc ('\n', stdout);						\
+  }
+
+int
+main (void)
+{
+  unsigned char buf[7] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+  const unsigned char bufcheck[7] = { 0x25, 0xe2, 0x82, 0xac, 0xce, 0xbb, 0 };
+  const wchar_t srcbuf[4] = { 0x25, 0x20ac, 0x03bb, 0 };
+  mbstate_t state;
+  const wchar_t *src;
+  char *dst;
+  int result = 0;
+  const char *used_locale;
+
+  setlocale (LC_CTYPE, "de_DE.UTF-8");
+  /* Double check.  */
+  used_locale = setlocale (LC_CTYPE, NULL);
+  printf ("used locale: \"%s\"\n", used_locale);
+  result = strcmp (used_locale, "de_DE.UTF-8");
+
+  memset (&state, '\0', sizeof (state));
+
+  src = srcbuf;
+  dst = (char *) buf;
+  show (wcrtomb (dst, *src++, &state), 1, buf + 1);
+  show (wcrtomb (dst, *src++, &state), 3, buf + 4);
+  show (wcrtomb (dst, *src++, &state), 2, buf + 6);
+  show (wcrtomb (dst, *src, &state), 1, buf + 7);
+
+  if (memcmp (buf, bufcheck, 7))
+    {
+      puts ("wrong results");
+      result = 1;
+    }
+
+  return result;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-mbswcs6.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-mbswcs6.c
new file mode 100644
index 00000000..eb383ac8
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-mbswcs6.c
@@ -0,0 +1,74 @@
+/* Test for invalid input to wcrtomb.
+   Copyright (C) 2001 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2001.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+static int
+do_test (const char *loc)
+{
+  char buf[100];
+  size_t n;
+  mbstate_t state;
+  const char *nloc;
+  int res;
+
+  nloc = setlocale (LC_ALL, loc);
+  if (nloc == NULL)
+    {
+      printf ("could not set locale \"%s\"\n", loc);
+      return 1;
+    }
+  printf ("new locale: %s\n", nloc);
+
+  memset (&state, '\0', sizeof (state));
+  errno = 0;
+  n = wcrtomb (buf, (wchar_t) -15l, &state);
+
+  printf ("n = %zd, errno = %d (%s)\n", n, errno, strerror (errno));
+
+  res = n != (size_t) -1 || errno != EILSEQ;
+  if (res)
+    puts ("*** FAIL");
+  putchar ('\n');
+
+  return res;
+}
+
+
+int
+main (void)
+{
+  int res;
+
+  res = do_test ("C");
+  res |= do_test ("de_DE.ISO-8859-1");
+  res |= do_test ("de_DE.UTF-8");
+  res |= do_test ("en_US.ISO-8859-1");
+  res |= do_test ("ja_JP.UTF-8");
+  res |= do_test ("hr_HR.ISO-8859-2");
+  //res |= do_test ("ru_RU.KOI8-R");
+
+  return res;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-numeric.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-numeric.c
new file mode 100644
index 00000000..9d3c91d1
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-numeric.c
@@ -0,0 +1,74 @@
+/* Testing the implementation of LC_NUMERIC and snprintf().
+   Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Petter Reinholdtsen , 2003
+
+   Based on tst-fmon.c by Jochen Hein , 1997.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+
+/*
+  test-numeric gets called with three parameters:
+   - the locale
+   - the format-string to be used
+   - the actual number to be formatted
+   - the expected string
+   If the test passes, test-numeric terminates with returncode 0,
+   otherwise with 1
+*/
+#define EXIT_SUCCESS 0
+#define EXIT_FAILURE 1
+#define EXIT_SETLOCALE 2
+#define EXIT_SNPRINTF 3
+
+int
+main (int argc, char *argv[])
+{
+  char *s = malloc (201);
+  double val;
+
+  /* Make sure to read the value before setting of the locale, as
+     strtod() is locale-dependent. */
+  val = strtod (argv[3], NULL);
+
+  if (setlocale (LC_ALL, argv[1]) == NULL)
+    {
+      fprintf (stderr, "setlocale(LC_ALL, \"%s\"): %m\n", argv[1]);
+      exit (EXIT_SETLOCALE);
+    }
+
+  if (snprintf (s, 200, argv[2], val) == -1)
+    {
+      perror ("snprintf");
+      exit (EXIT_SNPRINTF);
+    }
+
+  if (strcmp (s, argv[4]) != 0)
+    {
+      printf ("\
+locale: \"%s\", format: \"%s\", expected: \"%s\", got: \"%s\" => %s\n",
+	      argv[1], argv[2], argv[4], s,
+	      strcmp (s, argv[4]) != 0 ? "false" : "correct");
+      exit (EXIT_FAILURE);
+    }
+
+  return EXIT_SUCCESS;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-rpmatch.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-rpmatch.c
new file mode 100644
index 00000000..d751a43b
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-rpmatch.c
@@ -0,0 +1,37 @@
+/* Test program for rpmatch function.
+   Copyright (C) 1998, 2000 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jochen Hein .
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+
+int
+main (int argc, char* argv[])
+{
+  setlocale (LC_ALL, argv[1]);
+
+  if (rpmatch (argv[2]) != atol (argv[3]))
+    {
+      fprintf (stderr,"Failed: Locale %s, String %s, Exp: %s, got %d\n",
+	       argv[1], argv[2], argv[3], rpmatch (argv[2]));
+      exit (EXIT_FAILURE);
+    }
+  return EXIT_SUCCESS;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-setlocale.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-setlocale.c
new file mode 100644
index 00000000..1f8e68d8
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-setlocale.c
@@ -0,0 +1,25 @@
+/* Test case by Jakub Jelinek .  */
+#include 
+#include 
+#include 
+
+int
+main (void)
+{
+  char q[30];
+  char *s;
+
+  setlocale (LC_ALL, "");
+  printf ("after setlocale (LC_ALL, \"\"): %s\n", setlocale(LC_NUMERIC, NULL));
+
+  strcpy (q, "de_DE.UTF-8");
+  setlocale (LC_NUMERIC, q);
+  printf ("after setlocale (LC_NUMERIC, \"%s\"): %s\n",
+	  q, setlocale(LC_NUMERIC, NULL));
+
+  strcpy (q, "de_DE.ISO-8859-1");
+  s = setlocale (LC_NUMERIC, NULL);
+  printf ("after overwriting string: %s\n", s);
+
+  return strcmp (s, "de_DE.UTF-8") != 0;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-sscanf.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-sscanf.c
new file mode 100644
index 00000000..32c13285
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-sscanf.c
@@ -0,0 +1,56 @@
+#include 
+#include 
+#include 
+
+#define P0 "\xDB\xB0"
+#define P1 "\xDB\xB1"
+#define P2 "\xDB\xB2"
+#define P3 "\xDB\xB3"
+#define P4 "\xDB\xB4"
+#define P5 "\xDB\xB5"
+#define P6 "\xDB\xB6"
+#define P7 "\xDB\xB7"
+#define P8 "\xDB\xB8"
+#define P9 "\xDB\xB9"
+#define PD "\xd9\xab"
+#define PT "\xd9\xac"
+
+static int
+check_sscanf (const char *s, const char *format, const float n)
+{
+  float f;
+
+  if (sscanf (s, format, &f) != 1)
+    {
+      printf ("nothing found for \"%s\"\n", s);
+      return 1;
+    }
+  if (f != n)
+    {
+      printf ("got %f expected %f from \"%s\"\n", f, n, s);
+      return 1;
+    }
+  return 0;
+}
+
+static int
+do_test (void)
+{
+  if (setlocale (LC_ALL, "fa_IR.UTF-8") == NULL)
+    {
+      puts ("cannot set fa_IR locale");
+      return 1;
+    }
+
+  int r = check_sscanf (P3 PD P1 P4, "%I8f", 3.14);
+  r |= check_sscanf (P3 PT P1 P4 P5, "%I'f", 3145);
+  r |= check_sscanf (P3 PD P1 P4 P1 P5 P9, "%If", 3.14159);
+  r |= check_sscanf ("-" P3 PD P1 P4 P1 P5, "%If", -3.1415);
+  r |= check_sscanf ("+" PD P1 P4 P1 P5, "%If", +.1415);
+  r |= check_sscanf (P3 PD P1 P4 P1 P5 "e+" P2, "%Ie", 3.1415e+2);
+
+  return r;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-strfmon1.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-strfmon1.c
new file mode 100644
index 00000000..e30aa1b2
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-strfmon1.c
@@ -0,0 +1,42 @@
+#include 
+#include 
+#include 
+#include 
+
+static const struct
+{
+  const char *locale;
+  const char *expected;
+} tests[] =
+  {
+    { "de_DE.ISO-8859-1", "|-12,34 EUR|-12,34|" },
+    { "da_DK.ISO-8859-1", "|kr -12,34|-12,34|" },
+    { "zh_TW.EUC-TW", "|-NT$12.34|-12.34|" },
+    { "sv_SE.ISO-8859-1", "|-12,34 kr|-12,34|" }
+  };
+#define ntests (sizeof (tests) / sizeof (tests[0]))
+
+
+static int
+do_test (void)
+{
+  int res = 0;
+  for (int i = 0; i < ntests; ++i)
+    {
+      char buf[500];
+      if (setlocale (LC_ALL, tests[i].locale) == NULL)
+	{
+	  printf ("failed to set locale %s\n", tests[i].locale);
+	  res = 1;
+	  continue;
+	}
+      strfmon (buf, sizeof (buf), "|%n|%!n|", -12.34, -12.34);
+      int fail = strcmp (buf, tests[i].expected) != 0;
+      printf ("%s%s\n", buf, fail ? " *** FAIL ***" : "");
+      res |= fail;
+    }
+  return res;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-trans.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-trans.c
new file mode 100644
index 00000000..034a3621
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-trans.c
@@ -0,0 +1,71 @@
+/* Test program for user-defined character maps.
+   Copyright (C) 1999, 2000 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper .
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+int
+main (void)
+{
+  char buf[30];
+  wchar_t wbuf[30];
+  wctrans_t t;
+  wint_t wch;
+  int errors = 0;
+  int len;
+
+  setlocale (LC_ALL, "");
+
+  t = wctrans ("test");
+  if (t == (wctrans_t) 0)
+    {
+      puts ("locale data files probably not loaded");
+      exit (1);
+    }
+
+  wch = towctrans (L'A', t);
+  printf ("towctrans (L'A', t) = %c\n", wch);
+  if (wch != L'B')
+    errors = 1;
+
+  wch = towctrans (L'B', t);
+  printf ("towctrans (L'B', t) = %c\n", wch);
+  if (wch != L'C')
+    errors = 1;
+
+  /* Test the output digit handling.  */
+  swprintf (wbuf, sizeof (wbuf) / sizeof (wbuf[0]), L"%Id", 0x499602D2);
+  errors |= wcscmp (wbuf, L"bcdefghija") != 0;
+  len = wcslen (wbuf);
+  errors |= len != 10;
+  printf ("len = %d, wbuf = L\"%ls\"\n", len, wbuf);
+
+  snprintf (buf, sizeof buf, "%Id", 0x499602D2);
+  errors |= strcmp (buf, "bcdefghija") != 0;
+  len = strlen (buf);
+  errors |= len != 10;
+  printf ("len = %d, buf = \"%s\"\n", len, buf);
+
+  return errors;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-wctype.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-wctype.c
new file mode 100644
index 00000000..8fd8ce51
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-wctype.c
@@ -0,0 +1,144 @@
+/* Test program for iswctype() function in ja_JP locale.
+   Copyright (C) 2000 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper .
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+int
+main (void)
+{
+  wctype_t wct;
+  wchar_t buf[1000];
+  int result = 1;
+
+  setlocale (LC_ALL, "");
+  wprintf (L"locale = %s\n", setlocale (LC_CTYPE, NULL));
+
+  wct = wctype ("jhira");
+  if (wct == 0)
+    error (EXIT_FAILURE, 0, "jhira: no such character class");
+
+  if (fgetws (buf, sizeof (buf) / sizeof (buf[0]), stdin) != NULL)
+    {
+      int n;
+
+      wprintf (L"buf[] = \"%ls\"\n", buf);
+
+      result = 0;
+
+      for (n = 0; buf[n] != L'\0'; ++n)
+	{
+	  wprintf (L"jhira(U%04lx = %lc) = %d\n", (long) buf[n], buf[n],
+		   iswctype (buf[n], wct));
+	  result |= ((buf[n] < 0xff && iswctype (buf[n], wct))
+		     || (buf[n] > 0xff && !iswctype (buf[n], wct)));
+	}
+    }
+
+  wct = wctype ("jkata");
+  if (wct == 0)
+    error (EXIT_FAILURE, 0, "jkata: no such character class");
+
+  if (fgetws (buf, sizeof (buf) / sizeof (buf[0]), stdin) != NULL)
+    {
+      int n;
+
+      wprintf (L"buf[] = \"%ls\"\n", buf);
+
+      result = 0;
+
+      for (n = 0; buf[n] != L'\0'; ++n)
+	{
+	  wprintf (L"jkata(U%04lx = %lc) = %d\n", (long) buf[n], buf[n],
+		   iswctype (buf[n], wct));
+	  result |= ((buf[n] < 0xff && iswctype (buf[n], wct))
+		     || (buf[n] > 0xff && !iswctype (buf[n], wct)));
+	}
+    }
+
+  wct = wctype ("jdigit");
+  if (wct == 0)
+    error (EXIT_FAILURE, 0, "jdigit: no such character class");
+
+  if (fgetws (buf, sizeof (buf) / sizeof (buf[0]), stdin) != NULL)
+    {
+      int n;
+
+      wprintf (L"buf[] = \"%ls\"\n", buf);
+
+      result = 0;
+
+      for (n = 0; buf[n] != L'\0'; ++n)
+	{
+	  wprintf (L"jdigit(U%04lx = %lc) = %d\n", (long) buf[n], buf[n],
+		   iswctype (buf[n], wct));
+	  result |= ((buf[n] < 0xff && iswctype (buf[n], wct))
+		     || (buf[n] > 0xff && !iswctype (buf[n], wct)));
+	}
+    }
+
+  wct = wctype ("jspace");
+  if (wct == 0)
+    error (EXIT_FAILURE, 0, "jspace: no such character class");
+
+  if (fgetws (buf, sizeof (buf) / sizeof (buf[0]), stdin) != NULL)
+    {
+      int n;
+
+      wprintf (L"buf[] = \"%ls\"\n", buf);
+
+      result = 0;
+
+      for (n = 0; buf[n] != L'\0'; ++n)
+	{
+	  wprintf (L"jspace(U%04lx = %lc) = %d\n", (long) buf[n], buf[n],
+		   iswctype (buf[n], wct));
+	  result |= ((buf[n] < 0xff && iswctype (buf[n], wct))
+		     || (buf[n] > 0xff && !iswctype (buf[n], wct)));
+	}
+    }
+
+  wct = wctype ("jkanji");
+  if (wct == 0)
+    error (EXIT_FAILURE, 0, "jkanji: no such character class");
+
+  if (fgetws (buf, sizeof (buf) / sizeof (buf[0]), stdin) != NULL)
+    {
+      int n;
+
+      wprintf (L"buf[] = \"%ls\"\n", buf);
+
+      result = 0;
+
+      for (n = 0; buf[n] != L'\0'; ++n)
+	{
+	  wprintf (L"jkanji(U%04lx = %lc) = %d\n", (long) buf[n], buf[n],
+		   iswctype (buf[n], wct));
+	  result |= ((buf[n] < 0xff && iswctype (buf[n], wct))
+		     || (buf[n] > 0xff && !iswctype (buf[n], wct)));
+	}
+    }
+
+  return result;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-xlocale1.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-xlocale1.c
new file mode 100644
index 00000000..297c9ad7
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-xlocale1.c
@@ -0,0 +1,75 @@
+#include 
+#include 
+#include 
+
+
+static struct
+{
+  const char *locale;
+  const char *str1;
+  const char *str2;
+  int result;
+} tests[] =
+  {
+    { "C", "TRANSLIT", "translit", 0 },
+    { "de_DE.ISO-8859-1", "TRANSLIT", "translit", 0 },
+    { "de_DE.ISO-8859-1", "TRANSLIT", "trÄnslit", -1 },
+    { "de_DE.UTF-8", "TRANSLIT", "translit", 0 },
+    { "de_DE.ISO-8859-1", "ä", "Ä", 1 }
+  };
+#define ntests (sizeof (tests) / sizeof (tests[0]))
+
+
+int
+main (void)
+{
+  size_t cnt;
+  int result = 0;
+  locale_t loc = newlocale (1 << LC_ALL, "C", NULL);
+
+  for (cnt = 0; cnt < ntests; ++cnt)
+    {
+      int r;
+
+      if (setlocale (LC_ALL, tests[cnt].locale) == NULL)
+	{
+	  printf ("cannot set locale \"%s\": %m\n", tests[cnt].locale);
+	  result = 1;
+	  continue;
+	}
+
+      printf ("\nstrcasecmp_l (\"%s\", \"%s\", loc)\n",
+	      tests[cnt].str1, tests[cnt].str2);
+
+      r = strcasecmp_l (tests[cnt].str1, tests[cnt].str2, loc);
+      if (tests[cnt].result == 0)
+	{
+	  if (r != 0)
+	    {
+	      printf ("\"%s\" and \"%s\" expected to be the same, result %d\n",
+		      tests[cnt].str1, tests[cnt].str2, r);
+	      result = 1;
+	    }
+	}
+      else if (tests[cnt].result < 0)
+	{
+	  if (r >= 0)
+	    {
+	      printf ("\"%s\" expected to be smaller than \"%s\", result %d\n",
+		      tests[cnt].str1, tests[cnt].str2, r);
+	      result = 1;
+	    }
+	}
+      else
+	{
+	  if (r <= 0)
+	    {
+	      printf ("\"%s\" expected to be larger than \"%s\", result %d\n",
+		      tests[cnt].str1, tests[cnt].str2, r);
+	      result = 1;
+	    }
+	}
+    }
+
+  return result;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-xlocale2.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-xlocale2.c
new file mode 100644
index 00000000..30d87de7
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst-xlocale2.c
@@ -0,0 +1,64 @@
+#include 
+#include 
+#include 
+#include 
+
+
+static int do_test (__locale_t l);
+
+int
+main (void)
+{
+  locale_t l;
+  locale_t l2;
+  int result;
+
+  l = newlocale (1 << LC_ALL, "de_DE.ISO-8859-1", NULL);
+  if (l == NULL)
+    {
+      printf ("newlocale failed: %m\n");
+      exit (EXIT_FAILURE);
+    }
+  puts ("Running tests of created locale");
+  result = do_test (l);
+
+  l2 = duplocale (l);
+  if (l2 == NULL)
+    {
+      printf ("duplocale failed: %m\n");
+      exit (EXIT_FAILURE);
+    }
+  freelocale (l);
+  puts ("Running tests of duplicated locale");
+  result |= do_test (l2);
+
+  return result;
+}
+
+
+static const char str[] = "0123456789abcdef ABCDEF ghijklmnopqrstuvwxyzäÄöÖüÜ";
+static const char exd[] = "11111111110000000000000000000000000000000000000000";
+static const char exa[] = "00000000001111110111111011111111111111111111111111";
+static const char exx[] = "11111111111111110111111000000000000000000000000000";
+
+
+static int
+do_test (locale_t l)
+{
+  int result = 0;
+size_t n;
+
+#define DO_TEST(TEST, RES) \
+  for (n = 0; n < sizeof (str) - 1; ++n)				      \
+    if ('0' + (TEST (str[n], l) != 0) != RES[n])			      \
+      {									      \
+	printf ("%s(%c) failed\n", #TEST, str[n]);			      \
+	result = 1;							      \
+      }
+
+  DO_TEST (isdigit_l, exd);
+  DO_TEST (isalpha_l, exa);
+  DO_TEST (isxdigit_l, exx);
+
+  return result;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst_nl_langinfo.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst_nl_langinfo.c
new file mode 100644
index 00000000..fcf2fe2e
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/tst_nl_langinfo.c
@@ -0,0 +1,296 @@
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#if !defined(__UCLIBC__) && 0
+#define DO_EXTRA
+#endif
+
+int main(int argc, char **argv)
+{
+	char *l;
+	const unsigned char *x;
+/*  	const unsigned char *y; */
+	const unsigned char *p;
+
+	if (argc > 2) {
+		printf("invalid args\n");
+		return EXIT_FAILURE;
+	}
+	if (argc == 1) {
+		l = "";
+	} else {
+		l = *++argv;
+	}
+
+	if (!(x = setlocale(LC_ALL,l))) {
+		printf("couldn't set locale %s\n", l);
+		return EXIT_FAILURE;
+	}
+
+/*  	printf("\nsetlocale returned:\n  "); */
+/*  	do { */
+/*  		printf("\\x%02x", *x); */
+/*  	} while (*x++); */
+/*  	printf("\n"); */
+
+#ifndef __BCC__
+#define STR(X) #X
+#else
+#define STR(X) __STR(X)
+#endif
+#define __PASTE2(A,B) A.B
+
+#define DO_NL_I(X) \
+	printf( STR(X) " = %d\n", (int) nl_langinfo(X) );
+#define DO_NL_S(X) \
+	printf( STR(X) " = \"%s\"\n", nl_langinfo(X) );
+#define DO_NL_C(X) \
+	printf( STR(X) " = \"\\x%02x\"\n", *((unsigned char *) nl_langinfo(X)) );
+
+	printf("ctype\n");
+
+		DO_NL_S(CODESET);
+#ifdef DO_EXTRA
+		DO_NL_I(_NL_CTYPE_INDIGITS_MB_LEN);
+		DO_NL_S(_NL_CTYPE_INDIGITS0_MB);
+		DO_NL_S(_NL_CTYPE_INDIGITS1_MB);
+		DO_NL_S(_NL_CTYPE_INDIGITS2_MB);
+		DO_NL_S(_NL_CTYPE_INDIGITS3_MB);
+		DO_NL_S(_NL_CTYPE_INDIGITS4_MB);
+		DO_NL_S(_NL_CTYPE_INDIGITS5_MB);
+		DO_NL_S(_NL_CTYPE_INDIGITS6_MB);
+		DO_NL_S(_NL_CTYPE_INDIGITS7_MB);
+		DO_NL_S(_NL_CTYPE_INDIGITS8_MB);
+		DO_NL_S(_NL_CTYPE_INDIGITS9_MB);
+#endif
+		DO_NL_S(_NL_CTYPE_OUTDIGIT0_MB);
+		DO_NL_S(_NL_CTYPE_OUTDIGIT1_MB);
+		DO_NL_S(_NL_CTYPE_OUTDIGIT2_MB);
+		DO_NL_S(_NL_CTYPE_OUTDIGIT3_MB);
+		DO_NL_S(_NL_CTYPE_OUTDIGIT4_MB);
+		DO_NL_S(_NL_CTYPE_OUTDIGIT5_MB);
+		DO_NL_S(_NL_CTYPE_OUTDIGIT6_MB);
+		DO_NL_S(_NL_CTYPE_OUTDIGIT7_MB);
+		DO_NL_S(_NL_CTYPE_OUTDIGIT8_MB);
+		DO_NL_S(_NL_CTYPE_OUTDIGIT9_MB);
+
+
+	printf("numeric\n");
+
+		DO_NL_S(RADIXCHAR);		/* DECIMAL_POINT */
+		DO_NL_S(THOUSEP);		/* THOUSANDS_SEP */
+/*  		DO_NL_S(GROUPING); */
+
+	printf("GROUPING = \"");
+	for (p = (unsigned char *) nl_langinfo(GROUPING) ; *p ; p++) {
+		printf("\\x%02x", *p);
+	}
+	printf("\"\n\n");
+
+	printf("monetary\n");
+
+		DO_NL_S(INT_CURR_SYMBOL);
+		DO_NL_S(CURRENCY_SYMBOL);
+		DO_NL_S(MON_DECIMAL_POINT);
+		DO_NL_S(MON_THOUSANDS_SEP);
+/*  		DO_NL_S(MON_GROUPING); */
+
+	printf("MON_GROUPING = \"");
+	for (p = (unsigned char *) nl_langinfo(MON_GROUPING) ; *p ; p++) {
+		printf("\\x%02x", *p);
+	}
+	printf("\"\n\n");
+
+		DO_NL_S(POSITIVE_SIGN);
+		DO_NL_S(NEGATIVE_SIGN);
+		DO_NL_C(INT_FRAC_DIGITS);
+		DO_NL_C(FRAC_DIGITS);
+		DO_NL_C(P_CS_PRECEDES);
+		DO_NL_C(P_SEP_BY_SPACE);
+		DO_NL_C(N_CS_PRECEDES);
+		DO_NL_C(N_SEP_BY_SPACE);
+		DO_NL_C(P_SIGN_POSN);
+		DO_NL_C(N_SIGN_POSN);
+		DO_NL_C(INT_P_CS_PRECEDES);
+		DO_NL_C(INT_P_SEP_BY_SPACE);
+		DO_NL_C(INT_N_CS_PRECEDES);
+		DO_NL_C(INT_N_SEP_BY_SPACE);
+		DO_NL_C(INT_P_SIGN_POSN);
+		DO_NL_C(INT_N_SIGN_POSN);
+
+		DO_NL_S(CRNCYSTR);		/* CURRENCY_SYMBOL */
+
+
+	printf("time\n");
+
+		DO_NL_S(ABDAY_1);
+		DO_NL_S(ABDAY_2);
+		DO_NL_S(ABDAY_3);
+		DO_NL_S(ABDAY_4);
+		DO_NL_S(ABDAY_5);
+		DO_NL_S(ABDAY_6);
+		DO_NL_S(ABDAY_7);
+
+		DO_NL_S(DAY_1);
+		DO_NL_S(DAY_2);
+		DO_NL_S(DAY_3);
+		DO_NL_S(DAY_4);
+		DO_NL_S(DAY_5);
+		DO_NL_S(DAY_6);
+		DO_NL_S(DAY_7);
+
+		DO_NL_S(ABMON_1);
+		DO_NL_S(ABMON_2);
+		DO_NL_S(ABMON_3);
+		DO_NL_S(ABMON_4);
+		DO_NL_S(ABMON_5);
+		DO_NL_S(ABMON_6);
+		DO_NL_S(ABMON_7);
+		DO_NL_S(ABMON_8);
+		DO_NL_S(ABMON_9);
+		DO_NL_S(ABMON_10);
+		DO_NL_S(ABMON_11);
+		DO_NL_S(ABMON_12);
+
+		DO_NL_S(MON_1);
+		DO_NL_S(MON_2);
+		DO_NL_S(MON_3);
+		DO_NL_S(MON_4);
+		DO_NL_S(MON_5);
+		DO_NL_S(MON_6);
+		DO_NL_S(MON_7);
+		DO_NL_S(MON_8);
+		DO_NL_S(MON_9);
+		DO_NL_S(MON_10);
+		DO_NL_S(MON_11);
+		DO_NL_S(MON_12);
+
+		DO_NL_S(AM_STR);
+		DO_NL_S(PM_STR);
+
+		DO_NL_S(D_T_FMT);
+		DO_NL_S(D_FMT);
+		DO_NL_S(T_FMT);
+		DO_NL_S(T_FMT_AMPM);
+/* 		DO_NL_S(ERA); */
+		{
+		    const char *p = nl_langinfo(ERA);
+		    if (!p || !*p) {
+			printf("ERA = (none)\n");
+		    } else {
+			int i;
+			printf("ERA:\n");
+			for (i=0 ; i < 100 ; i++) {
+			    printf("  %3d: \"%s\"\n", i, p);
+			    while (*p) ++p;
+			    ++p;
+			    if (!*p) break;
+			}
+		    }
+		}
+
+		DO_NL_S(ERA_YEAR);		/* non SuSv3 */
+		DO_NL_S(ERA_D_FMT);
+/* 		DO_NL_S(ALT_DIGITS); */
+		{
+		    const char *p = nl_langinfo(ALT_DIGITS);
+		    if (!p || !*p) {
+			printf("ALT_DIGITS = (none)\n");
+		    } else {
+			int i;
+			printf("ALT_DIGITS:\n");
+			for (i=0 ; i < 100 ; i++) {
+			    printf("  %3d: \"%s\"\n", i, p);
+			    while (*p) ++p;
+			    ++p;
+			}
+		    }
+		}
+		DO_NL_S(ERA_D_T_FMT);
+		DO_NL_S(ERA_T_FMT);
+
+#ifdef DO_EXTRA
+		DO_NL_C(_NL_TIME_WEEK_NDAYS);
+		DO_NL_I(_NL_TIME_WEEK_1STDAY); /* grr... this won't work with 16bit ptrs */
+		DO_NL_C(_NL_TIME_WEEK_1STWEEK);
+		DO_NL_C(_NL_TIME_FIRST_WEEKDAY);
+		DO_NL_C(_NL_TIME_FIRST_WORKDAY);
+		DO_NL_C(_NL_TIME_CAL_DIRECTION);
+		DO_NL_S(_NL_TIME_TIMEZONE);
+		DO_NL_S(_DATE_FMT);
+#endif
+
+	printf("messages\n");
+
+		DO_NL_S(YESEXPR);
+		DO_NL_S(NOEXPR);
+		DO_NL_S(YESSTR);
+		DO_NL_S(NOSTR);
+
+#ifdef DO_EXTRA
+
+	printf("paper\n");
+
+		DO_NL_I(_NL_PAPER_HEIGHT);
+		DO_NL_I(_NL_PAPER_WIDTH);
+
+	printf("name\n");
+
+		DO_NL_S(_NL_NAME_NAME_FMT);
+		DO_NL_S(_NL_NAME_NAME_GEN);
+		DO_NL_S(_NL_NAME_NAME_MR);
+		DO_NL_S(_NL_NAME_NAME_MRS);
+		DO_NL_S(_NL_NAME_NAME_MISS);
+		DO_NL_S(_NL_NAME_NAME_MS);
+
+	printf("address\n");
+
+		DO_NL_S(_NL_ADDRESS_POSTAL_FMT);
+		DO_NL_S(_NL_ADDRESS_COUNTRY_NAME);
+		DO_NL_S(_NL_ADDRESS_COUNTRY_POST);
+		DO_NL_S(_NL_ADDRESS_COUNTRY_AB2);
+		DO_NL_S(_NL_ADDRESS_COUNTRY_AB3);
+		DO_NL_S(_NL_ADDRESS_COUNTRY_CAR);
+		DO_NL_I(_NL_ADDRESS_COUNTRY_NUM);
+		DO_NL_S(_NL_ADDRESS_COUNTRY_ISBN);
+		DO_NL_S(_NL_ADDRESS_LANG_NAME);
+		DO_NL_S(_NL_ADDRESS_LANG_AB);
+		DO_NL_S(_NL_ADDRESS_LANG_TERM);
+		DO_NL_S(_NL_ADDRESS_LANG_LIB);
+
+	printf("telephone\n");
+
+		DO_NL_S(_NL_TELEPHONE_TEL_INT_FMT);
+		DO_NL_S(_NL_TELEPHONE_TEL_DOM_FMT);
+		DO_NL_S(_NL_TELEPHONE_INT_SELECT);
+		DO_NL_S(_NL_TELEPHONE_INT_PREFIX);
+
+	printf("measurement\n");
+
+		DO_NL_C(_NL_MEASUREMENT_MEASUREMENT); /* 1 is metric, 2 is US */
+
+	printf("identification\n");
+
+		DO_NL_S(_NL_IDENTIFICATION_TITLE);
+		DO_NL_S(_NL_IDENTIFICATION_SOURCE);
+		DO_NL_S(_NL_IDENTIFICATION_ADDRESS);
+		DO_NL_S(_NL_IDENTIFICATION_CONTACT);
+		DO_NL_S(_NL_IDENTIFICATION_EMAIL);
+		DO_NL_S(_NL_IDENTIFICATION_TEL);
+		DO_NL_S(_NL_IDENTIFICATION_FAX);
+		DO_NL_S(_NL_IDENTIFICATION_LANGUAGE);
+		DO_NL_S(_NL_IDENTIFICATION_TERRITORY);
+		DO_NL_S(_NL_IDENTIFICATION_AUDIENCE);
+		DO_NL_S(_NL_IDENTIFICATION_APPLICATION);
+		DO_NL_S(_NL_IDENTIFICATION_ABBREVIATION);
+		DO_NL_S(_NL_IDENTIFICATION_REVISION);
+		DO_NL_S(_NL_IDENTIFICATION_DATE);
+		DO_NL_S(_NL_IDENTIFICATION_CATEGORY);
+
+#endif
+
+	return EXIT_SUCCESS;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/xfrm-test.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/xfrm-test.c
new file mode 100644
index 00000000..199bb6b5
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/locale/xfrm-test.c
@@ -0,0 +1,144 @@
+/* Test collation function via transformation using real data.
+   Copyright (C) 1997, 1998, 2000, 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 1997.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+struct lines
+{
+  char *xfrm;
+  char *line;
+};
+
+static int xstrcmp (const void *, const void *);
+
+int
+main (int argc, char *argv[])
+{
+  int result = 0;
+  size_t nstrings, nstrings_max;
+  struct lines *strings;
+  char *line = NULL;
+  size_t len = 0;
+  size_t n;
+
+  if (argc < 2)
+    error (1, 0, "usage: %s ", argv[0]);
+
+  setlocale (LC_ALL, "");
+
+  nstrings_max = 100;
+  nstrings = 0;
+  strings = (struct lines *) malloc (nstrings_max * sizeof (struct lines));
+  if (strings == NULL)
+    {
+      perror (argv[0]);
+      exit (1);
+    }
+
+  while (1)
+    {
+      char saved, *newp;
+      int needed;
+      int l;
+      if (getline (&line, &len, stdin) < 0)
+	break;
+
+      if (nstrings == nstrings_max)
+	{
+	  strings = (struct lines *) realloc (strings,
+					      (nstrings_max *= 2)
+					       * sizeof (*strings));
+	  if (strings == NULL)
+	    {
+	      perror (argv[0]);
+	      exit (1);
+	    }
+	}
+      strings[nstrings].line = strdup (line);
+      l = strcspn (line, ":(;");
+      while (l > 0 && isspace (line[l - 1]))
+	--l;
+
+      saved = line[l];
+      line[l] = '\0';
+      needed = strxfrm (NULL, line, 0);
+      newp = malloc (needed + 1);
+      strxfrm (newp, line, needed + 1);
+      strings[nstrings].xfrm = newp;
+      line[l] = saved;
+      ++nstrings;
+    }
+  free (line);
+
+  /* First shuffle.  */
+  srandom (atoi (argv[1]));
+  for (n = 0; n < 10 * nstrings; ++n)
+    {
+      int r1, r2, r;
+      size_t idx1 = random () % nstrings;
+      size_t idx2 = random () % nstrings;
+      struct lines tmp = strings[idx1];
+      strings[idx1] = strings[idx2];
+      strings[idx2] = tmp;
+
+      /* While we are at it a first little test.  */
+      r1 = strcmp (strings[idx1].xfrm, strings[idx2].xfrm);
+      r2 = strcmp (strings[idx2].xfrm, strings[idx1].xfrm);
+      r = -(r1 ^ r2);
+      if (r)
+	r /= abs (r1 ^ r2);
+
+      if (r < 0 || (r == 0 && (r1 != 0 || r2 != 0))
+	  || (r > 0 && (r1 ^ r2) >= 0))
+	printf ("collate wrong: %d vs. %d\n", r1, r2);
+    }
+
+  /* Now sort.  */
+  qsort (strings, nstrings, sizeof (struct lines), xstrcmp);
+
+  /* Print the result.  */
+  for (n = 0; n < nstrings; ++n)
+    {
+      fputs (strings[n].line, stdout);
+      free (strings[n].line);
+      free (strings[n].xfrm);
+    }
+  free (strings);
+
+  return result;
+}
+
+
+static int
+xstrcmp (ptr1, ptr2)
+     const void *ptr1;
+     const void *ptr2;
+{
+  const struct lines *l1 = (const struct lines *) ptr1;
+  const struct lines *l2 = (const struct lines *) ptr2;
+
+  return strcmp (l1->xfrm, l2->xfrm);
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/malloc/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/test/malloc/Makefile
new file mode 100644
index 00000000..d76f07b1
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/malloc/Makefile
@@ -0,0 +1,7 @@
+# uClibc malloc tests
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+
+top_builddir=../../
+include ../Rules.mak
+-include Makefile.in
+include ../Test.mak
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/malloc/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/test/malloc/Makefile.in
new file mode 100644
index 00000000..7b8c0fab
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/malloc/Makefile.in
@@ -0,0 +1,4 @@
+# uClibc malloc tests
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+
+TESTS_DISABLED := time_malloc
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/malloc/malloc-standard-alignment.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/malloc/malloc-standard-alignment.c
new file mode 100644
index 00000000..71e5023a
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/malloc/malloc-standard-alignment.c
@@ -0,0 +1,42 @@
+/* exercise a bug found in malloc-standard when alignment
+ * values are out of whack and cause a small overflow into
+ * actual user data.
+ */
+
+#include 
+#include 
+#include 
+
+#define ok(p) ((void*)p > (void*)0x1000)
+#define x \
+	do { \
+		printf("%i: phead = %p, phead->link @ %p = %p %s\n", \
+			__LINE__, phead, \
+			ok(phead) ? &phead->link : 0, \
+			ok(phead) ? phead->link : 0, \
+			ok(phead) ? phead->link == 0 ? "" : "!!!!!!!!!!!" : ""); \
+		if (phead->link != NULL) exit(1); \
+	} while (0);
+
+struct llist_s {
+	void *data;
+	struct llist_s *link;
+} *phead;
+
+int main(int argc, char *argv[])
+{
+	char *line, *reg;
+
+	setbuf(stdout, NULL);
+	setbuf(stderr, NULL);
+
+	phead = malloc(sizeof(*phead));
+	phead->link = NULL;
+
+x	line = malloc(80);
+x	line = realloc(line, 2);
+x	reg = malloc(32);
+x	free(line);
+
+x	return 0;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/malloc/malloc.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/malloc/malloc.c
new file mode 100644
index 00000000..ca7c5f92
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/malloc/malloc.c
@@ -0,0 +1,81 @@
+
+#include 
+#include 
+#include 
+#include 
+
+#define N_PTRS 1000
+#define N_ALLOCS 10000
+#define MAX_SIZE 0x10000
+
+#define random_size()	(random()%MAX_SIZE)
+#define random_ptr()	(random()%N_PTRS)
+
+int test1(void);
+int test2(void);
+
+int main(int argc, char *argv[])
+{
+	return test1() + test2();
+}
+
+int test1(void)
+{
+	void **ptrs;
+	int i,j;
+	int size;
+	int ret = 0;
+
+	srandom(0x19730929);
+
+	ptrs = malloc(N_PTRS*sizeof(void *));
+
+	for(i=0; i
+#include 
+#include 
+
+#define size_t unsigned int
+
+int
+main (int argc, char *argv[])
+{
+  char *dummy0;
+  char *dummy1;
+  char *fill_info_table1;
+  char *over_top;
+  size_t over_top_size = 0x3000;
+  char *over_top_dup;
+  size_t over_top_dup_size = 0x7000;
+  char *x;
+  size_t i;
+
+  /* Here's what memory is supposed to look like (hex):
+        size  contents
+        3000  original_info_table, later fill_info_table1
+      3fa000  dummy0
+      3fa000  dummy1
+        6000  info_table_2
+	3000  over_top
+
+	*/
+  /* mem: original_info_table */
+  dummy0 = malloc (0x3fa000);
+  /* mem: original_info_table, dummy0 */
+  dummy1 = malloc (0x3fa000);
+  /* mem: free, dummy0, dummy1, info_table_2 */
+  fill_info_table1 = malloc (0x3000);
+  /* mem: fill_info_table1, dummy0, dummy1, info_table_2 */
+
+  x = malloc (0x1000);
+  free (x);
+  /* mem: fill_info_table1, dummy0, dummy1, info_table_2, freexx */
+
+  /* This is what loses; info_table_2 and freexx get combined unbeknownst
+     to mmalloc, and mmalloc puts over_top in a section of memory which
+     is on the free list as part of another block (where info_table_2 had
+     been).  */
+  over_top = malloc (over_top_size);
+  over_top_dup = malloc (over_top_dup_size);
+  memset (over_top, 0, over_top_size);
+  memset (over_top_dup, 1, over_top_dup_size);
+
+  for (i = 0; i < over_top_size; ++i)
+    if (over_top[i] != 0)
+      {
+	printf ("FAIL: malloc expands info table\n");
+	return 0;
+      }
+
+  for (i = 0; i < over_top_dup_size; ++i)
+    if (over_top_dup[i] != 1)
+      {
+	printf ("FAIL: malloc expands info table\n");
+	return 0;
+      }
+
+  printf ("PASS: malloc expands info table\n");
+  return 0;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/malloc/realloc-can-shrink.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/malloc/realloc-can-shrink.c
new file mode 100644
index 00000000..33249db4
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/malloc/realloc-can-shrink.c
@@ -0,0 +1,17 @@
+/* make sure that realloc() can properly shrink buffers */
+
+#include 
+
+#define LARGE_BUFFER (1 << 20) /* idea is to span a lot of pages */
+
+int main(int argc, char *argv[])
+{
+	int count = 20;
+	char *ptr = NULL;
+	while (count--) {
+		ptr = realloc(ptr, LARGE_BUFFER);
+		ptr = realloc(ptr, 1);
+	}
+	free(ptr);
+	return 0;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/malloc/realloc0.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/malloc/realloc0.c
new file mode 100644
index 00000000..62ae39d2
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/malloc/realloc0.c
@@ -0,0 +1,13 @@
+#include 
+#include 
+
+int main(int argc, char **argv)
+{
+	void *ptr = NULL;
+	ptr = realloc(ptr, 0);
+	printf("realloc(NULL, 0)  --  pointer = %p\n", ptr);
+
+	ptr = malloc(0);
+	printf("malloc(0)  --  pointer = %p\n", ptr);
+	return 0;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/malloc/testmalloc.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/malloc/testmalloc.c
new file mode 100644
index 00000000..42707d23
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/malloc/testmalloc.c
@@ -0,0 +1,101 @@
+#include 
+#include 
+#include 
+
+
+struct list {
+	struct list *next;
+};
+
+int main(void)
+{
+	int z=999;
+	int *y=&z;
+	int *x=NULL;
+	struct list *save;
+	struct list *lp;
+	int i;
+
+
+	printf("pointer to x is %p\n", x);
+	printf("pointer to y is %p\n", y);
+	x=malloc(sizeof(int)*2000);
+	printf("pointer to x is %p\n", x);
+	y=malloc(sizeof(int)*100);
+	printf("pointer to y is %p\n", y);
+	free(x);
+	free(y);
+	printf("about to free(0)\n");
+	free(0);
+
+	x=malloc(13);
+	printf("x = %p\n", x);
+	memcpy(x, "Small string", 13);
+	printf("0x%p test string1: %s\n", x, (char *)x);
+	y = realloc(x, 36);
+	printf("0x%p test string1: %s\n", y, (char *)y);
+	memcpy(y, "********** Larger string **********", 36);
+	printf("0x%p test string2: %s\n", y, (char *)y);
+	free(y);
+
+
+	printf("Allocate 100 nodes 500 bytes each\n");
+	save = 0;
+	for (i=0; i<100; i++) {
+		lp = malloc(500);
+		if (lp == 0) {
+			printf("loop 1: malloc returned 0\n");
+			goto Failed;
+		}
+		lp->next = save;
+		save = lp;
+	}
+
+	printf("freeing 100 nodes\n");
+	while (save) {
+		lp = save;
+		save = save->next;
+		free(lp);
+	}
+
+	printf("try realloc 100 times \n");
+	lp = 0;
+	for (i=1; i<=100; i++) {
+		lp = realloc(lp, i*200);
+		if (lp == 0) {
+			printf("loop 3: realloc returned 0\n");
+			goto Failed;
+		}
+	}
+	{
+	void *unused_ret = realloc(lp, 0);
+	(void) unused_ret;
+	}
+
+	printf("Allocate another 100 nodes 600 bytes each\n");
+	save = 0;
+	for (i=0; i<100; i++) {
+		lp = malloc(600);
+		if (lp == 0) {
+			printf("loop 2: malloc returned 0\n");
+			goto Failed;
+		}
+		lp->next = save;
+		save = lp;
+	}
+
+	printf("freeing 100 nodes\n");
+	while (save) {
+		lp = save;
+		save = save->next;
+		free(lp);
+	}
+
+
+	printf("alloc test PASSED\n");
+	exit(0);
+
+Failed:
+	printf("!!!!!!!!!!!! alloc test FAILED. !!!!!!!!!!!!!!!\n");
+	exit(1);
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/malloc/time_malloc.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/malloc/time_malloc.c
new file mode 100644
index 00000000..0b626654
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/malloc/time_malloc.c
@@ -0,0 +1,62 @@
+#include 
+#define REPS (100000)
+int sizes[] = {
+    100000, 1024, 42000, 350, 100, 80, 3 ,3,3,3,3,3,3,3,3,3,3,3,3,50,
+    100000, 1024, 42000, 350, 100, 80, 3 ,3,3,3,3,3,3,3,3,3,3,3,3,50,
+    100000, 1024, 42000, 350, 100, 80, 3 ,3,3,3,3,3,3,3,3,3,3,3,3,50,
+    100000, 1024, 42000, 350, 100, 80, 3 ,3,3,3,3,3,3,3,3,3,3,3,3,50,
+    100000, 1024, 42000, 350, 100, 80, 3 ,3,3,3,3,3,3,3,3,3,3,3,3,50,
+    100000, 1024, 42000, 350, 100, 80, 3 ,3,3,3,3,3,3,3,3,3,3,3,3,50,
+    100000, 1024, 42000, 350, 100, 80, 3 ,3,3,3,3,3,3,3,3,3,3,3,3,50,
+    100000, 1024, 42000, 350, 100, 80, 3 ,3,3,3,3,3,3,3,3,3,3,3,3,50,
+    100000, 1024, 42000, 350, 100, 80, 3 ,3,3,3,3,3,3,3,3,3,3,3,3,50,
+    100000, 1024, 42000, 350, 100, 80, 3 ,3,3,3,3,3,3,3,3,3,3,3,3,50,
+    100000, 1024, 42000, 350, 100, 80, 3 ,3,3,3,3,3,3,3,3,3,3,3,3,50,
+    100000, 1024, 42000, 350, 100, 80, 3 ,3,3,3,3,3,3,3,3,3,3,3,3,50,
+    100000, 1024, 42000, 350, 100, 80, 3 ,3,3,3,3,3,3,3,3,3,3,3,3,50,
+    100000, 1024, 42000, 350, 100, 80, 3 ,3,3,3,3,3,3,3,3,3,3,3,3,50,
+    100000, 1024, 42000, 350, 100, 80, 3 ,3,3,3,3,3,3,3,3,3,3,3,3,50,
+    100000, 1024, 42000, 350, 100, 80, 3 ,3,3,3,3,3,3,3,3,3,3,3,3,50,
+    100000, 1024, 42000, 350, 100, 80, 3 ,3,3,3,3,3,3,3,3,3,3,3,3,50,
+    100000, 1024, 42000, 350, 100, 80, 3 ,3,3,3,3,3,3,3,3,3,3,3,3,50,
+    100000, 1024, 42000, 350, 100, 80, 3 ,3,3,3,3,3,3,3,3,3,3,3,3,50,
+    100000, 1024, 42000, 350, 100, 80, 3 ,3,3,3,3,3,3,3,3,3,3,3,3,50,
+    100000, 1024, 42000, 350, 100, 80, 3 ,3,3,3,3,3,3,3,3,3,3,3,3,50,
+    100000, 1024, 42000, 350, 100, 80, 3 ,3,3,3,3,3,3,3,3,3,3,3,3,50,
+    100000, 1024, 42000, 350, 100, 80, 3 ,3,3,3,3,3,3,3,3,3,3,3,3,50,
+    100000, 1024, 42000, 350, 100, 80, 3 ,3,3,3,3,3,3,3,3,3,3,3,3,50,
+    100000, 1024, 42000, 350, 100, 80, 3 ,3,3,3,3,3,3,3,3,3,3,3,3,50,
+    100000, 1024, 42000, 350, 100, 80, 3 ,3,3,3,3,3,3,3,3,3,3,3,3,50,
+    100000, 1024, 42000, 350, 100, 80, 3 ,3,3,3,3,3,3,3,3,3,3,3,3,50,
+    100000, 1024, 42000, 350, 100, 80, 3 ,3,3,3,3,3,3,3,3,3,3,3,3,50,
+    100000, 1024, 42000, 350, 100, 80, 3 ,3,3,3,3,3,3,3,3,3,3,3,3,50,
+    100000, 1024, 42000, 350, 100, 80, 3 ,3,3,3,3,3,3,3,3,3,3,3,3,50,
+    100000, 1024, 42000, 350, 100, 80, 3 ,3,3,3,3,3,3,3,3,3,3,3,3,50,
+    100000, 1024, 42000, 350, 100, 80, 3 ,3,3,3,3,3,3,3,3,3,3,3,3,50,
+    100000, 1024, 42000, 350, 100, 80, 3 ,3,3,3,3,3,3,3,3,3,3,3,3,50,
+    100000, 1024, 42000, 350, 100, 80, 3 ,3,3,3,3,3,3,3,3,3,3,3,3,50,
+    100000, 1024, 42000, 350, 100, 80, 3 ,3,3,3,3,3,3,3,3,3,3,3,3,50,
+    100000, 1024, 42000, 350, 100, 80, 3 ,3,3,3,3,3,3,3,3,3,3,3,3,50,
+    100000, 1024, 42000, 350, 100, 80, 3 ,3,3,3,3,3,3,3,3,3,3,3,3,50,
+    100000, 1024, 42000, 350, 100, 80, 3 ,3,3,3,3,3,3,3,3,3,3,3,3,50,
+    100000, 1024, 42000, 350, 100, 80, 3 ,3,3,3,3,3,3,3,3,3,3,3,3,50,
+    100000, 1024, 42000, 350, 100, 80, 3 ,3,3,3,3,3,3,3,3,3,3,3,3,50,
+    100000, 1024, 42000, 350, 100, 80, 3 ,3,3,3,3,3,3,3,3,3,3,3,3,50,
+    100000, 1024, 42000, 350, 100, 80, 3 ,3,3,3,3,3,3,3,3,3,3,3,3,50
+};
+#define NUM (sizeof sizes / sizeof sizes[0])
+int main ()
+{
+    int i, j;
+    void *allocs[NUM];
+    for (i = 0; i < REPS; i++) {
+	for (j = 0; j < NUM; j++) {
+	    allocs[j] = malloc(sizes[j]);
+	}
+	for (j = 0; j < NUM; j++) {
+	    free(allocs[j]);
+	}
+    }
+    return 0;
+}
+
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/malloc/tst-calloc.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/malloc/tst-calloc.c
new file mode 100644
index 00000000..eb0059f6
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/malloc/tst-calloc.c
@@ -0,0 +1,128 @@
+/* Copyright (C) 2000, 2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper .
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+static int errors = 0;
+
+/* Number of samples per size.  */
+#define N 50000
+
+
+static void
+fixed_test (int size)
+{
+  char *ptrs[N];
+  int i;
+
+  for (i = 0; i < N; ++i)
+    {
+      int j;
+
+      ptrs[i] = (char *) calloc (1, size);
+
+      if (ptrs[i] == NULL)
+	break;
+
+      for (j = 0; j < size; ++j)
+	{
+	  if (ptrs[i][j] != '\0') {
+	    ++errors;
+	    printf("byte not cleared (size %d, element %d, byte %d)",
+		   size, i, j);
+	  }
+	  ptrs[i][j] = '\xff';
+	}
+    }
+
+  while (i-- > 0)
+    free (ptrs[i]);
+}
+
+
+static void
+random_test (void)
+{
+  char *ptrs[N];
+  int i;
+
+  for (i = 0; i < N; ++i)
+    {
+      int j;
+      int n = 1 + random () % 10;
+      int elem = 1 + random () % 100;
+      int size = n * elem;
+
+      ptrs[i] = (char *) calloc (n, elem);
+
+      if (ptrs[i] == NULL)
+	break;
+
+      for (j = 0; j < size; ++j)
+	{
+	  if (ptrs[i][j] != '\0') {
+	    ++errors;
+	    printf("byte not cleared (size %d, element %d, byte %d)",
+		   size, i, j);
+	  }
+	  ptrs[i][j] = '\xff';
+	}
+    }
+
+  while (i-- > 0)
+    free (ptrs[i]);
+}
+
+
+static void
+null_test (void)
+{
+  /* If the size is 0 the result is implementation defined.  Just make
+     sure the program doesn't crash.  */
+  calloc (0, 0);
+  calloc (0, UINT_MAX);
+  calloc (UINT_MAX, 0);
+  calloc (0, ~((size_t) 0));
+  calloc (~((size_t) 0), 0);
+}
+
+
+int
+main (void)
+{
+  /* We are allocating blocks with `calloc' and check whether every
+     block is completely cleared.  We first try this for some fixed
+     times and then with random size.  */
+  fixed_test (15);
+  fixed_test (5);
+  fixed_test (17);
+  fixed_test (6);
+  fixed_test (31);
+  fixed_test (96);
+
+  random_test ();
+
+  null_test ();
+
+  return errors != 0;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/malloc/tst-malloc.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/malloc/tst-malloc.c
new file mode 100644
index 00000000..468e1d4b
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/malloc/tst-malloc.c
@@ -0,0 +1,73 @@
+/* Copyright (C) 1999 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Andreas Jaeger , 1999.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+
+static int errors = 0;
+
+static void
+merror (const char *msg)
+{
+  ++errors;
+  printf ("Error: %s\n", msg);
+}
+
+int
+main (void)
+{
+  void *p;
+  int save;
+
+  errno = 0;
+
+  p = malloc (-1);
+  save = errno;
+
+  if (p != NULL)
+    merror ("malloc (-1) succeeded.");
+
+  if (p == NULL && save != ENOMEM)
+    merror ("errno is not set correctly");
+
+  p = malloc (10);
+  if (p == NULL)
+    merror ("malloc (10) failed.");
+
+  /* realloc (p, 0) == free (p).  */
+  p = realloc (p, 0);
+  if (p != NULL)
+    merror ("realloc (p, 0) failed.");
+
+  p = malloc (0);
+#if !defined(__UCLIBC__) || defined(__MALLOC_GLIBC_COMPAT__)
+  if (p == NULL)
+#else
+  if (p != NULL)
+#endif
+    merror ("malloc (0) failed.");
+
+  p = realloc (p, 0);
+  if (p != NULL)
+    merror ("realloc (p, 0) failed.");
+
+  return errors != 0;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/malloc/tst-mallocfork.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/malloc/tst-mallocfork.c
new file mode 100644
index 00000000..5bb1d762
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/malloc/tst-mallocfork.c
@@ -0,0 +1,51 @@
+/* Derived from the test case in
+   http://sourceware.org/bugzilla/show_bug.cgi?id=838.  */
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+static void
+sig_handler (int signum)
+{
+  pid_t child = vfork ();
+  if (child == 0)
+    exit (0);
+  TEMP_FAILURE_RETRY (waitpid (child, NULL, 0));
+}
+
+static int
+do_test (void)
+{
+  pid_t parent = getpid ();
+
+  struct sigaction action = { .sa_handler = sig_handler };
+  sigemptyset (&action.sa_mask);
+
+  malloc (sizeof (int));
+
+  if (sigaction (SIGALRM, &action, NULL) != 0)
+    {
+      puts ("sigaction failed");
+      return 1;
+    }
+
+  /* Create a child that sends the signal to be caught.  */
+  pid_t child = vfork ();
+  if (child == 0)
+    {
+      if (kill (parent, SIGALRM) == -1)
+	perror ("kill");
+      exit (0);
+    }
+
+  TEMP_FAILURE_RETRY (waitpid (child, NULL, 0));
+
+  return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/malloc/tst-mcheck.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/malloc/tst-mcheck.c
new file mode 100644
index 00000000..af72c042
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/malloc/tst-mcheck.c
@@ -0,0 +1,96 @@
+/* Copyright (C) 2005 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek , 2005.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+
+static int errors = 0;
+
+static void
+merror (const char *msg)
+{
+  ++errors;
+  printf ("Error: %s\n", msg);
+}
+
+int
+main (void)
+{
+  void *p, *q;
+
+  errno = 0;
+
+  p = malloc (-1);
+
+  if (p != NULL)
+    merror ("malloc (-1) succeeded.");
+  else if (errno != ENOMEM)
+    merror ("errno is not set correctly.");
+
+  p = malloc (10);
+  if (p == NULL)
+    merror ("malloc (10) failed.");
+
+  p = realloc (p, 0);
+  if (p != NULL)
+    merror ("realloc (p, 0) failed.");
+
+  p = malloc (0);
+#if !defined(__UCLIBC__) || defined(__MALLOC_GLIBC_COMPAT__)
+  if (p == NULL)
+#else
+  if (p != NULL)
+#endif
+    merror ("malloc (0) failed.");
+
+  p = realloc (p, 0);
+  if (p != NULL)
+    merror ("realloc (p, 0) failed.");
+
+  q = malloc (256);
+  if (q == NULL)
+    merror ("malloc (256) failed.");
+
+  p = malloc (512);
+  if (p == NULL)
+    merror ("malloc (512) failed.");
+
+  if (realloc (p, -256) != NULL)
+    merror ("realloc (p, -256) succeeded.");
+  else if (errno != ENOMEM)
+    merror ("errno is not set correctly.");
+
+  free (p);
+
+  p = malloc (512);
+  if (p == NULL)
+    merror ("malloc (512) failed.");
+
+  if (realloc (p, -1) != NULL)
+    merror ("realloc (p, -1) succeeded.");
+  else if (errno != ENOMEM)
+    merror ("errno is not set correctly.");
+
+  free (p);
+  free (q);
+
+  return errors != 0;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/malloc/tst-obstack.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/malloc/tst-obstack.c
new file mode 100644
index 00000000..769697f1
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/malloc/tst-obstack.c
@@ -0,0 +1,64 @@
+/* Test case by Alexandre Duret-Lutz .  */
+#include 
+#include 
+#include 
+#include 
+
+#define obstack_chunk_alloc verbose_malloc
+#define obstack_chunk_free verbose_free
+#define ALIGN_BOUNDARY 64
+#define ALIGN_MASK (ALIGN_BOUNDARY - 1)
+#define OBJECT_SIZE 1000
+
+static void *
+verbose_malloc (size_t size)
+{
+  void *buf = malloc (size);
+  printf ("malloc (%zu) => %p\n", size, buf);
+  return buf;
+}
+
+static void
+verbose_free (void *buf)
+{
+  free (buf);
+  printf ("free (%p)\n", buf);
+}
+
+int
+main (void)
+{
+  int result = 0;
+  int align = 2;
+
+  while (align <= 64)
+    {
+      struct obstack obs;
+      int i;
+      int align_mask = align - 1;
+
+      printf ("\n Alignment mask: %d\n", align_mask);
+
+      obstack_init (&obs);
+      obstack_alignment_mask (&obs) = align_mask;
+      /* finish an empty object to take alignment into account */
+      obstack_finish (&obs);
+
+      /* let's allocate some objects and print their addresses */
+      for (i = 15; i > 0; --i)
+	{
+	  void *obj = obstack_alloc (&obs, OBJECT_SIZE);
+
+	  printf ("obstack_alloc (%u) => %p \t%s\n", OBJECT_SIZE, obj,
+		  ((uintptr_t) obj & align_mask) ? "(not aligned)" : "");
+	  result |= ((uintptr_t) obj & align_mask) != 0;
+	}
+
+      /* clean up */
+      obstack_free (&obs, 0);
+
+      align <<= 1;
+    }
+
+  return result;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/malloc/tst-valloc.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/malloc/tst-valloc.c
new file mode 100644
index 00000000..643a0dda
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/malloc/tst-valloc.c
@@ -0,0 +1,23 @@
+/* Test case by Stephen Tweedie .  */
+#include 
+#include 
+#include 
+
+int
+main (void)
+{
+  char *p;
+  int pagesize = getpagesize ();
+  int i;
+
+  p = valloc (pagesize);
+  i = (long int) p;
+
+  if ((i & (pagesize-1)) != 0)
+    {
+      fprintf (stderr, "Alignment problem: valloc returns %p\n", p);
+      exit (1);
+    }
+
+  return 0;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/math/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/test/math/Makefile
new file mode 100644
index 00000000..135aedb2
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/math/Makefile
@@ -0,0 +1,7 @@
+# uClibc math tests
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+
+top_builddir=../../
+include ../Rules.mak
+-include Makefile.in
+include ../Test.mak
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/math/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/test/math/Makefile.in
new file mode 100644
index 00000000..e76cbdba
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/math/Makefile.in
@@ -0,0 +1,31 @@
+# uClibc math tests
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+
+TESTS := basic-test tst-definitions test-fpucw test-float test-ifloat test-double test-idouble \
+    rint signgam ilogb
+# gamma (removed from TESTS, need to add "small errors are ok" machinery there)
+ifeq ($(UCLIBC_HAS_LONG_DOUBLE_MATH),y)
+TESTS += test-ldouble test-ildoubl compile_test c99_test
+else
+CFLAGS_basic-test := -DNO_LONG_DOUBLE
+endif
+
+DODIFF_rint     := 1
+DODIFF_signgam  := 1
+
+# NOTE: For basic-test we must disable the floating point optimization.
+#       Only for sh architecture because in the other architecture are disabled.
+ifeq ($(TARGET_ARCH),sh)
+CFLAGS_basic-test += -mieee
+endif
+EXTRA_CFLAGS    := -fno-builtin
+EXTRA_LDFLAGS   := -lm
+
+PERL := /usr/bin/perl
+
+$(TESTS): libm-test.c
+
+libm-test.c: libm-test-ulps-$(TARGET_ARCH) libm-test.inc gen-libm-test.pl
+	$(Q)$(PERL) ./gen-libm-test.pl -u libm-test-ulps-$(TARGET_ARCH) ./libm-test.inc -o "." 2>&1 > /dev/null
+
+EXTRA_CLEAN := libm-test.c libm-test-ulps.h
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/math/basic-test.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/math/basic-test.c
new file mode 100644
index 00000000..04ec6ea3
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/math/basic-test.c
@@ -0,0 +1,125 @@
+/* Copyright (C) 1999 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Andreas Jaeger , 1999.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#define _ISOC99_SOURCE
+
+#include 
+#include 
+#include 
+
+static int errors = 0;
+
+
+static void
+check (const char *testname, int result)
+{
+  if (!result) {
+    printf ("Failure: %s\n", testname);
+    errors++;
+  }
+}
+
+#define TEST_FUNC(NAME, FLOAT, NANFUNC, EPSILON, HUGEVAL) \
+static void								      \
+NAME (void)								      \
+{									      \
+  /* Variables are declared volatile to forbid some compiler		      \
+     optimizations.  */							      \
+  volatile FLOAT Inf_var, NaN_var, zero_var, one_var;			      \
+  FLOAT x1, x2;								      \
+									      \
+  zero_var = 0.0;							      \
+  one_var = 1.0;							      \
+  NaN_var = zero_var/zero_var;						      \
+  Inf_var = one_var / zero_var;						      \
+									      \
+  (void) &zero_var;							      \
+  (void) &one_var;							      \
+  (void) &NaN_var;							      \
+  (void) &Inf_var;							      \
+									      \
+									      \
+  check (#FLOAT " isinf (inf) == 1", isinf (Inf_var) == 1);		      \
+  check (#FLOAT " isinf (-inf) == -1", isinf (-Inf_var) == -1);		      \
+  check (#FLOAT " !isinf (1)", !(isinf (one_var)));			      \
+  check (#FLOAT " !isinf (NaN)", !(isinf (NaN_var)));			      \
+									      \
+  check (#FLOAT " isnan (NaN)", isnan (NaN_var));			      \
+  check (#FLOAT " isnan (-NaN)", isnan (-NaN_var));			      \
+  check (#FLOAT " !isnan (1)", !(isnan (one_var)));			      \
+  check (#FLOAT " !isnan (inf)", !(isnan (Inf_var)));			      \
+									      \
+  check (#FLOAT " inf == inf", Inf_var == Inf_var);			      \
+  check (#FLOAT " -inf == -inf", -Inf_var == -Inf_var);			      \
+  check (#FLOAT " inf != -inf", Inf_var != -Inf_var);			      \
+  check (#FLOAT " NaN != NaN", NaN_var != NaN_var);			      \
+									      \
+  /*									      \
+     the same tests but this time with NAN from 		      \
+     NAN is a double const						      \
+   */									      \
+  check (#FLOAT " isnan (NAN)", isnan (NAN));				      \
+  check (#FLOAT " isnan (-NAN)", isnan (-NAN));				      \
+  check (#FLOAT " !isinf (NAN)", !(isinf (NAN)));			      \
+  check (#FLOAT " !isinf (-NAN)", !(isinf (-NAN)));			      \
+  check (#FLOAT " NAN != NAN", NAN != NAN);				      \
+									      \
+  /*									      \
+     And again with the value returned by the `nan' function.		      \
+   */									      \
+  check (#FLOAT " isnan (NAN)", isnan (NANFUNC ("")));			      \
+  check (#FLOAT " isnan (-NAN)", isnan (-NANFUNC ("")));		      \
+  check (#FLOAT " !isinf (NAN)", !(isinf (NANFUNC (""))));		      \
+  check (#FLOAT " !isinf (-NAN)", !(isinf (-NANFUNC (""))));		      \
+  check (#FLOAT " NAN != NAN", NANFUNC ("") != NANFUNC (""));		      \
+									      \
+  /* test if EPSILON is ok */						      \
+  x1 = 1.0;								      \
+  x2 = x1 + EPSILON;							      \
+  check (#FLOAT " 1 != 1+EPSILON", x1 != x2);				      \
+									      \
+  x1 = 1.0;								      \
+  x2 = x1 - EPSILON;							      \
+  check (#FLOAT " 1 != 1-EPSILON", x1 != x2);				      \
+									      \
+  /* test if HUGE_VALx is ok */						      \
+  x1 = HUGEVAL;								      \
+  check (#FLOAT " isinf (HUGE_VALx) == +1", isinf (x1) == +1);		      \
+  x1 = - HUGEVAL;							      \
+  check (#FLOAT " isinf (-HUGE_VALx) == -1", isinf (x1) == -1);		      \
+}
+
+TEST_FUNC (float_test, float, nanf, FLT_EPSILON, HUGE_VALF)
+TEST_FUNC (double_test, double, nan, DBL_EPSILON, HUGE_VAL)
+#ifndef NO_LONG_DOUBLE
+TEST_FUNC (ldouble_test, long double, nanl, LDBL_EPSILON, HUGE_VALL)
+#endif
+
+int
+main (void)
+{
+  float_test ();
+  double_test ();
+
+#ifndef NO_LONG_DOUBLE
+  ldouble_test ();
+#endif
+
+  return errors != 0;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/math/c99_test.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/math/c99_test.c
new file mode 100644
index 00000000..73382e41
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/math/c99_test.c
@@ -0,0 +1,116 @@
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define check_d1(func, param, expected) \
+do { \
+	int err; hex_union ur; hex_union up; \
+	double result = func(param); up.f = param; ur.f = result; \
+	errors += (err = (result != (expected))); \
+	err \
+	? printf("FAIL: %s(%g/"HEXFMT")=%g/"HEXFMT" (expected %g)\n", \
+		#func, (double)(param), (long long)up.hex, result, (long long)ur.hex, (double)(expected)) \
+	: printf("PASS: %s(%g)=%g\n", #func, (double)(param), result); \
+} while (0)
+
+#define check_i1(func, param, expected) \
+do { \
+	int err; hex_union up; \
+	long long result = func(param); up.f = param; \
+	errors += (err = (result != (expected))); \
+	err \
+	? printf("FAIL: %s(%g/"HEXFMT")=%lld/%llu (expected %llu)\n", \
+		#func, (double)(param), (long long)up.hex, result, result, (long long)(expected)) \
+	: printf("PASS: %s(%g)=%lld/%llu\n", #func, (double)(param), result, result); \
+} while (0)
+
+#define HEXFMT "%08llx"
+typedef union {
+	double f;
+	uint64_t hex;
+} hex_union;
+
+double zero = 0.0;
+double minus_zero = 0.0;
+double nan_value = 0.0;
+int errors = 0;
+
+int main(void)
+{
+	nan_value /= nan_value;
+	minus_zero = copysign(zero, -1.0);
+
+	check_i1(isfinite, 1.0, 1);
+	check_i1(isfinite, 2.0, 1);
+	check_i1(isfinite, 3.0, 1);
+	check_i1(isfinite, DBL_MAX, 1);
+	check_i1(isfinite, FLT_MAX, 1);
+	check_i1(isfinite, HUGE_VAL, 0);
+	check_i1(isfinite, HUGE_VALF, 0);
+	check_i1(isfinite, HUGE_VALL, 0);
+	check_i1(isfinite, nan_value, 0);
+	check_i1(isfinite, nan_value, 0);
+	check_i1(isfinite, nan_value, 0);
+
+	check_i1(isnan, 1.0, 0);
+	check_i1(isnan, 2.0, 0);
+	check_i1(isnan, 3.0, 0);
+	check_i1(isnan, DBL_MAX, 0);
+	check_i1(isnan, FLT_MAX, 0);
+	check_i1(isnan, HUGE_VAL, 0);
+	check_i1(isnan, HUGE_VALF, 0);
+	check_i1(isnan, HUGE_VALL, 0);
+	check_i1(isnan, (float)HUGE_VALL, 0);
+	check_i1(isnan, nan_value, 1);
+	check_i1(isnan, nan_value, 1);
+	check_i1(isnan, nan_value, 1);
+
+	check_i1(isinf, 1.0, 0);
+	check_i1(isinf, 2.0, 0);
+	check_i1(isinf, 3.0, 0);
+	check_i1(isinf, DBL_MAX, 0);
+	check_i1(isinf, FLT_MAX, 0);
+	check_i1(isinf, (float)DBL_MAX, 1);
+	check_i1(isinf, HUGE_VAL, 1);
+	check_i1(isinf, HUGE_VALF, 1);
+	check_i1(isinf, HUGE_VALL, 1);
+	check_i1(isinf, (float)HUGE_VALL, 1);
+	check_i1(isinf, nan_value, 0);
+	check_i1(isinf, nan_value, 0);
+	check_i1(isinf, nan_value, 0);
+
+	check_i1(fpclassify, minus_zero, FP_ZERO);
+	check_i1(fpclassify, 0.0, FP_ZERO);
+	check_i1(fpclassify, 1.0, FP_NORMAL);
+	check_i1(fpclassify, 2.0, FP_NORMAL);
+	check_i1(fpclassify, 3.0, FP_NORMAL);
+	check_i1(fpclassify, DBL_MIN/1.01, FP_SUBNORMAL);
+	check_i1(fpclassify, DBL_MIN, FP_NORMAL);
+	check_i1(fpclassify, DBL_MAX, FP_NORMAL);
+	check_i1(fpclassify, FLT_MAX, FP_NORMAL);
+	check_i1(fpclassify, DBL_MAX, FP_NORMAL);
+	check_i1(fpclassify, DBL_MAX*1.01, FP_INFINITE);
+	check_i1(fpclassify, HUGE_VAL, FP_INFINITE);
+	check_i1(fpclassify, HUGE_VALF, FP_INFINITE);
+	check_i1(fpclassify, HUGE_VALL, FP_INFINITE);
+	check_i1(fpclassify, (float)HUGE_VALL, FP_INFINITE);
+	check_i1(fpclassify, nan_value, FP_NAN);
+	check_i1(fpclassify, nan_value, FP_NAN);
+	check_i1(fpclassify, nan_value, FP_NAN);
+
+	check_i1(!!signbit, -1.0, 1);
+	check_i1(!!signbit, minus_zero, 1);
+	check_i1(!!signbit, 0.0, 0);
+	check_i1(!!signbit, HUGE_VAL, 0);
+	check_i1(!!signbit, HUGE_VALF, 0);
+	check_i1(!!signbit, HUGE_VALL, 0);
+	check_i1(!!signbit, -HUGE_VAL, 1);
+	check_i1(!!signbit, -HUGE_VALF, 1);
+	check_i1(!!signbit, -HUGE_VALL, 1);
+
+	printf("Errors: %d\n", errors);
+	return errors;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/math/compile_test.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/math/compile_test.c
new file mode 100644
index 00000000..ab8c40c4
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/math/compile_test.c
@@ -0,0 +1,141 @@
+#include 
+
+static int testf(float float_x, long double long_double_x, /*float complex float_complex_x,*/ int int_x, long long_x)
+{
+int r = 0;
+r += acosf(float_x);
+r += acoshf(float_x);
+r += asinf(float_x);
+r += asinhf(float_x);
+r += atan2f(float_x, float_x);
+r += atanf(float_x);
+r += atanhf(float_x);
+/*r += cargf(float_complex_x); - will fight with complex numbers later */
+r += cbrtf(float_x);
+r += ceilf(float_x);
+r += copysignf(float_x, float_x);
+r += cosf(float_x);
+r += coshf(float_x);
+r += erfcf(float_x);
+r += erff(float_x);
+r += exp2f(float_x);
+r += expf(float_x);
+r += expm1f(float_x);
+r += fabsf(float_x);
+/*r += fdimf(float_x, float_x); - uclibc does not have it (yet?) */
+r += floorf(float_x);
+/*r += fmaf(float_x, float_x, float_x); - uclibc does not have it (yet?) */
+/*r += fmaxf(float_x, float_x); - uclibc does not have it (yet?) */
+/*r += fminf(float_x, float_x); - uclibc does not have it (yet?) */
+r += fmodf(float_x, float_x);
+r += frexpf(float_x, &int_x);
+r += gammaf(float_x);
+r += hypotf(float_x, float_x);
+r += ilogbf(float_x);
+r += ldexpf(float_x, int_x);
+r += lgammaf(float_x);
+r += llrintf(float_x);
+r += llroundf(float_x);
+r += log10f(float_x);
+r += log1pf(float_x);
+r += log2f(float_x);
+r += logbf(float_x);
+r += logf(float_x);
+r += lrintf(float_x);
+r += lroundf(float_x);
+r += modff(float_x, &float_x);
+/*r += nearbyintf(float_x); - uclibc does not have it (yet?) */
+/*r += nexttowardf(float_x, long_double_x); - uclibc does not have it (yet?) */
+r += powf(float_x, float_x);
+r += remainderf(float_x, float_x);
+/*r += remquof(float_x, float_x, &int_x); - uclibc does not have it (yet?) */
+r += rintf(float_x);
+r += roundf(float_x);
+#ifdef __UCLIBC_SUSV3_LEGACY__
+r += scalbf(float_x, float_x);
+#endif
+/*r += scalblnf(float_x, long_x); - uclibc does not have it (yet?) */
+r += scalbnf(float_x, int_x);
+r += significandf(float_x);
+r += sinf(float_x);
+r += sinhf(float_x);
+r += sqrtf(float_x);
+r += tanf(float_x);
+r += tanhf(float_x);
+/*r += tgammaf(float_x); - uclibc does not have it (yet?) */
+r += truncf(float_x);
+return r;
+}
+
+static int testl(long double long_double_x, int int_x, long long_x)
+{
+int r = 0;
+r += __finitel(long_double_x);
+r += __fpclassifyl(long_double_x);
+r += __isinfl(long_double_x);
+r += __isnanl(long_double_x);
+r += __signbitl(long_double_x);
+r += acoshl(long_double_x);
+r += acosl(long_double_x);
+r += asinhl(long_double_x);
+r += asinl(long_double_x);
+r += atan2l(long_double_x, long_double_x);
+r += atanhl(long_double_x);
+r += atanl(long_double_x);
+r += cbrtl(long_double_x);
+r += ceill(long_double_x);
+r += copysignl(long_double_x, long_double_x);
+r += coshl(long_double_x);
+r += cosl(long_double_x);
+r += erfcl(long_double_x);
+r += erfl(long_double_x);
+r += exp2l(long_double_x);
+r += expl(long_double_x);
+r += expm1l(long_double_x);
+r += fabsl(long_double_x);
+r += fdiml(long_double_x, long_double_x);
+r += floorl(long_double_x);
+r += fmal(long_double_x, long_double_x, long_double_x);
+r += fmaxl(long_double_x, long_double_x);
+r += fminl(long_double_x, long_double_x);
+r += fmodl(long_double_x, long_double_x);
+r += frexpl(long_double_x, &int_x);
+r += hypotl(long_double_x, long_double_x);
+r += ilogbl(long_double_x);
+r += ldexpl(long_double_x, int_x);
+r += lgammal(long_double_x);
+r += llrintl(long_double_x);
+r += llroundl(long_double_x);
+r += log10l(long_double_x);
+r += log1pl(long_double_x);
+r += log2l(long_double_x);
+r += logbl(long_double_x);
+r += logl(long_double_x);
+r += lrintl(long_double_x);
+r += lroundl(long_double_x);
+r += modfl(long_double_x, &long_double_x);
+r += nearbyintl(long_double_x);
+r += nextafterl(long_double_x, long_double_x);
+/* r += nexttowardl(long_double_x, long_double_x); - uclibc doesn't provide this [yet?] */
+r += powl(long_double_x, long_double_x);
+r += remainderl(long_double_x, long_double_x);
+r += remquol(long_double_x, long_double_x, &int_x);
+r += rintl(long_double_x);
+r += roundl(long_double_x);
+r += scalblnl(long_double_x, long_x);
+r += scalbnl(long_double_x, int_x);
+r += sinhl(long_double_x);
+r += sinl(long_double_x);
+r += sqrtl(long_double_x);
+r += tanhl(long_double_x);
+r += tanl(long_double_x);
+r += tgammal(long_double_x);
+r += truncl(long_double_x);
+return r;
+}
+
+int main(int argc, char **argv)
+{
+        /* Always 0 but gcc hopefully won't be able to notice */
+        return 5 & ((long)&testf) & ((long)&testl) & 2;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/math/fenv.h b/l4/pkg/uclibc/lib/contrib/uclibc/test/math/fenv.h
new file mode 100644
index 00000000..0025a62c
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/math/fenv.h
@@ -0,0 +1,3 @@
+/* until we support fenv ... */
+#define feclearexcept(X)
+#define fetestexcept(X) (0)
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/math/gamma.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/math/gamma.c
new file mode 100644
index 00000000..69c10afa
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/math/gamma.c
@@ -0,0 +1,73 @@
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define check_d1(func, param, expected) \
+do { \
+	int err; hex_union ur; hex_union up; \
+	double result = func(param); up.f = param; ur.f = result; \
+	errors += (err = (result != (expected))); \
+	err \
+	? printf("FAIL: %s(%g/"HEXFMT")=%g/"HEXFMT" (expected %g)\n", \
+		#func, (double)(param), (long long)up.hex, result, (long long)ur.hex, (double)(expected)) \
+	: printf("PASS: %s(%g)=%g\n", #func, (double)(param), result); \
+} while (0)
+
+#define HEXFMT "%08llx"
+typedef union {
+	double f;
+	uint64_t hex;
+} hex_union;
+double result;
+
+#define M_2_SQRT_PIl   3.5449077018110320545963349666822903L   /* 2 sqrt (M_PIl)  */
+#define M_SQRT_PIl     1.7724538509055160272981674833411451L   /* sqrt (M_PIl)  */
+
+double zero = 0.0;
+double minus_zero = 0.0;
+double nan_value = 0.0;
+int errors = 0;
+
+int main(void)
+{
+        nan_value /= nan_value;
+        minus_zero = copysign(zero, -1.0);
+
+	//check_d1(tgamma, HUGE_VAL, NAN);
+	//check_d1(tgamma, negative_integer, NAN);
+	check_d1(tgamma, 0.0, HUGE_VAL); /* pole */
+	check_d1(tgamma, minus_zero, -HUGE_VAL); /* pole */
+	check_d1(tgamma, DBL_MAX/2, HUGE_VAL); /* overflow to inf */
+	check_d1(tgamma, DBL_MAX, HUGE_VAL); /* overflow to inf */
+	check_d1(tgamma, HUGE_VAL, HUGE_VAL); /* overflow to inf */
+	check_d1(tgamma, 7, 2*3*4*5*6); /* normal value */
+	check_d1(tgamma, -0.5, -M_2_SQRT_PIl); /* normal value (testing negative points) */
+
+	check_d1(lgamma, -HUGE_VAL, HUGE_VAL);
+	//check_d1(lgamma, HUGE_VAL, NAN);
+	check_d1(lgamma, 0.0, HUGE_VAL); /* pole */
+	check_d1(lgamma, minus_zero, HUGE_VAL); /* pole */
+	check_d1(lgamma, 1.0, 0.0);
+	check_d1(lgamma, 2.0, 0.0);
+	check_d1(lgamma, DBL_MAX/2, HUGE_VAL); /* overflow to inf */
+	check_d1(lgamma, DBL_MAX, HUGE_VAL); /* overflow to inf */
+	check_d1(lgamma, HUGE_VAL, HUGE_VAL); /* overflow to inf */
+	check_d1(lgamma, 7, log(2*3*4*5*6)); /* normal value */
+
+	/* In glibc, gamma == lgamma. (In BSD, it's == tgamma */
+	check_d1(gamma, -HUGE_VAL, HUGE_VAL);
+	//check_d1(gamma, HUGE_VAL, NAN);
+	check_d1(gamma, 0.0, HUGE_VAL); /* pole */
+	check_d1(gamma, minus_zero, HUGE_VAL); /* pole */
+	check_d1(gamma, 1.0, 0.0);
+	check_d1(gamma, 2.0, 0.0);
+	check_d1(gamma, DBL_MAX/2, HUGE_VAL); /* overflow to inf */
+	check_d1(gamma, DBL_MAX, HUGE_VAL); /* overflow to inf */
+	check_d1(gamma, HUGE_VAL, HUGE_VAL); /* overflow to inf */
+	check_d1(gamma, 7, log(2*3*4*5*6)); /* normal value */
+
+	printf("Errors: %d\n", errors);
+	return errors;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/math/gen-libm-test.pl b/l4/pkg/uclibc/lib/contrib/uclibc/test/math/gen-libm-test.pl
new file mode 100755
index 00000000..26f819a8
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/math/gen-libm-test.pl
@@ -0,0 +1,738 @@
+#!/usr/bin/perl -w
+# Copyright (C) 1999 Free Software Foundation, Inc.
+# This file is part of the GNU C Library.
+# Contributed by Andreas Jaeger , 1999.
+
+# The GNU C Library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+
+# The GNU C Library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+
+# You should have received a copy of the GNU Lesser General Public
+# License along with the GNU C Library; if not, write to the Free
+# Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+# 02111-1307 USA.
+
+# This file needs to be tidied up
+# Note that functions and tests share the same namespace.
+
+# Information about tests are stored in: %results
+# $results{$test}{"kind"} is either "fct" or "test" and flags whether this
+# is a maximal error of a function or a single test.
+# $results{$test}{"type"} is the result type, e.g. normal or complex.
+# $results{$test}{"has_ulps"} is set if deltas exist.
+# $results{$test}{"has_fails"} is set if exptected failures exist.
+# In the following description $type and $float are:
+# - $type is either "normal", "real" (for the real part of a complex number)
+#   or "imag" (for the imaginary part # of a complex number).
+# - $float is either of float, ifloat, double, idouble, ldouble, ildouble;
+#   It represents the underlying floating point type (float, double or long
+#   double) and if inline functions (the leading i stands for inline)
+#   are used.
+# $results{$test}{$type}{"fail"}{$float} is defined and has a 1 if
+# the test is expected to fail
+# $results{$test}{$type}{"ulp"}{$float} is defined and has a delta as value
+
+
+use Getopt::Std;
+
+use strict;
+
+use vars qw ($input $output);
+use vars qw (%results);
+use vars qw (@tests @functions);
+use vars qw ($count);
+use vars qw (%beautify @all_floats);
+use vars qw ($output_dir $ulps_file);
+
+# all_floats is sorted and contains all recognised float types
+@all_floats = ('double', 'float', 'idouble',
+	       'ifloat', 'ildouble', 'ldouble');
+
+%beautify =
+  ( "minus_zero" => "-0",
+    "plus_zero" => "+0",
+    "minus_infty" => "-inf",
+    "plus_infty" => "inf",
+    "nan_value" => "NaN",
+    "M_El" => "e",
+    "M_E2l" => "e^2",
+    "M_E3l" => "e^3",
+    "M_LOG10El", "log10(e)",
+    "M_PIl" => "pi",
+    "M_PI_34l" => "3/4 pi",
+    "M_PI_2l" => "pi/2",
+    "M_PI_4l" => "pi/4",
+    "M_PI_6l" => "pi/6",
+    "M_PI_34_LOG10El" => "3/4 pi*log10(e)",
+    "M_PI_LOG10El" => "pi*log10(e)",
+    "M_PI2_LOG10El" => "pi/2*log10(e)",
+    "M_PI4_LOG10El" => "pi/4*log10(e)",
+    "M_LOG_SQRT_PIl" => "log(sqrt(pi))",
+    "M_LOG_2_SQRT_PIl" => "log(2*sqrt(pi))",
+    "M_2_SQRT_PIl" => "2 sqrt (pi)",
+    "M_SQRT_PIl" => "sqrt (pi)",
+    "INVALID_EXCEPTION" => "invalid exception",
+    "DIVIDE_BY_ZERO_EXCEPTION" => "division by zero exception",
+    "INVALID_EXCEPTION_OK" => "invalid exception allowed",
+    "DIVIDE_BY_ZERO_EXCEPTION_OK" => "division by zero exception allowed",
+    "EXCEPTIONS_OK" => "exceptions allowed",
+    "IGNORE_ZERO_INF_SIGN" => "sign of zero/inf not specified",
+"INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN" => "invalid exception and sign of zero/inf not specified"
+  );
+
+
+# get Options
+# Options:
+# u: ulps-file
+# h: help
+# o: output-directory
+# n: generate new ulps file
+use vars qw($opt_u $opt_h $opt_o $opt_n);
+getopts('u:o:nh');
+
+$ulps_file = 'libm-test-ulps';
+$output_dir = '';
+
+if ($opt_h) {
+  print "Usage: gen-libm-test.pl [OPTIONS]\n";
+  print " -h         print this help, then exit\n";
+  print " -o DIR     directory where generated files will be placed\n";
+  print " -n         only generate sorted file NewUlps from libm-test-ulps\n";
+  print " -u FILE    input file with ulps\n";
+  exit 0;
+}
+
+$ulps_file = $opt_u if ($opt_u);
+$output_dir = $opt_o if ($opt_o);
+
+$input = "libm-test.inc";
+$output = "${output_dir}libm-test.c";
+
+$count = 0;
+
+&parse_ulps ($ulps_file);
+&generate_testfile ($input, $output) unless ($opt_n);
+&output_ulps ("${output_dir}libm-test-ulps.h", $ulps_file) unless ($opt_n);
+&print_ulps_file ("${output_dir}NewUlps") if ($opt_n);
+
+# Return a nicer representation
+sub beautify {
+  my ($arg) = @_;
+  my ($tmp);
+
+  if (exists $beautify{$arg}) {
+    return $beautify{$arg};
+  }
+  if ($arg =~ /^-/) {
+    $tmp = $arg;
+    $tmp =~ s/^-//;
+    if (exists $beautify{$tmp}) {
+      return '-' . $beautify{$tmp};
+    }
+  }
+  if ($arg =~ /[0-9]L$/) {
+    $arg =~ s/L$//;
+  }
+  return $arg;
+}
+
+# Return a nicer representation of a complex number
+sub build_complex_beautify {
+  my ($r, $i) = @_;
+  my ($str1, $str2);
+
+  $str1 = &beautify ($r);
+  $str2 = &beautify ($i);
+  if ($str2 =~ /^-/) {
+    $str2 =~ s/^-//;
+    $str1 .= ' - ' . $str2;
+  } else {
+    $str1 .= ' + ' . $str2;
+  }
+  $str1 .= ' i';
+  return $str1;
+}
+
+# Return name of a variable
+sub get_variable {
+  my ($number) = @_;
+
+  return "x" if ($number == 1);
+  return "y" if ($number == 2);
+  return "z" if ($number == 3);
+  # return x1,x2,...
+  $number =-3;
+  return "x$number";
+}
+
+# Add a new test to internal data structures and fill in the
+# ulps, failures and exception information for the C line.
+sub new_test {
+  my ($test, $exception) = @_;
+  my $rest;
+
+  # Add ulp, xfail
+  if (exists $results{$test}{'has_ulps'}) {
+    $rest = ", DELTA$count";
+  } else {
+    $rest = ', 0';
+  }
+  if (exists $results{$test}{'has_fails'}) {
+    $rest .= ", FAIL$count";
+  } else {
+    $rest .= ', 0';
+  }
+  if (defined $exception) {
+    $rest .= ", $exception";
+  } else {
+    $rest .= ', 0';
+  }
+  $rest .= ");\n";
+  # We must increment here to keep @tests and count in sync
+  push @tests, $test;
+  ++$count;
+  return $rest;
+}
+
+# Treat some functions especially.
+# Currently only sincos needs extra treatment.
+sub special_functions {
+  my ($file, $args) = @_;
+  my (@args, $str, $test, $cline);
+
+  @args = split /,\s*/, $args;
+
+  unless ($args[0] =~ /sincos/) {
+    die ("Don't know how to handle $args[0] extra.");
+  }
+  print $file "  FUNC (sincos) ($args[1], &sin_res, &cos_res);\n";
+
+  $str = 'sincos (' . &beautify ($args[1]) . ', &sin_res, &cos_res)';
+  # handle sin
+  $test = $str . ' puts ' . &beautify ($args[2]) . ' in sin_res';
+  if ($#args == 4) {
+    $test .= " plus " . &beautify ($args[4]);
+  }
+
+  $cline = "  check_float (\"$test\", sin_res, $args[2]";
+  $cline .= &new_test ($test, $args[4]);
+  print $file $cline;
+
+  # handle cos
+  $test = $str . ' puts ' . &beautify ($args[3]) . ' in cos_res';
+  $cline = "  check_float (\"$test\", cos_res, $args[3]";
+  # only tests once for exception
+  $cline .= &new_test ($test, undef);
+  print $file $cline;
+}
+
+# Parse the arguments to TEST_x_y
+sub parse_args {
+  my ($file, $descr, $args) = @_;
+  my (@args, $str, $descr_args, $descr_res, @descr);
+  my ($current_arg, $cline, $i);
+  my ($pre, $post, @special);
+  my ($extra_var, $call, $c_call);
+
+  if ($descr eq 'extra') {
+    &special_functions ($file, $args);
+    return;
+  }
+  ($descr_args, $descr_res) = split /_/,$descr, 2;
+
+  @args = split /,\s*/, $args;
+
+  $call = "$args[0] (";
+
+  # Generate first the string that's shown to the user
+  $current_arg = 1;
+  $extra_var = 0;
+  @descr = split //,$descr_args;
+  for ($i = 0; $i <= $#descr; $i++) {
+    if ($i >= 1) {
+      $call .= ', ';
+    }
+    # FLOAT, int, long int, long long int
+    if ($descr[$i] =~ /f|i|l|L/) {
+      $call .= &beautify ($args[$current_arg]);
+      ++$current_arg;
+      next;
+    }
+    # &FLOAT, &int - argument is added here
+    if ($descr[$i] =~ /F|I/) {
+      ++$extra_var;
+      $call .= '&' . &get_variable ($extra_var);
+      next;
+    }
+    # complex
+    if ($descr[$i] eq 'c') {
+      $call .= &build_complex_beautify ($args[$current_arg], $args[$current_arg+1]);
+      $current_arg += 2;
+      next;
+    }
+
+    die ("$descr[$i] is unknown");
+  }
+  $call .= ')';
+  $str = "$call == ";
+
+  # Result
+  @descr = split //,$descr_res;
+  foreach (@descr) {
+    if ($_ =~ /f|i|l|L/) {
+      $str .= &beautify ($args[$current_arg]);
+      ++$current_arg;
+    } elsif ($_ eq 'c') {
+      $str .= &build_complex_beautify ($args[$current_arg], $args[$current_arg+1]);
+      $current_arg += 2;
+    } elsif ($_ eq 'b') {
+      # boolean
+      $str .= ($args[$current_arg] == 0) ? "false" : "true";
+      ++$current_arg;
+    } elsif ($_ eq '1') {
+      ++$current_arg;
+    } else {
+      die ("$_ is unknown");
+    }
+  }
+  # consistency check
+  if ($current_arg == $#args) {
+    die ("wrong number of arguments")
+      unless ($args[$current_arg] =~ /EXCEPTION|IGNORE_ZERO_INF_SIGN/);
+  } elsif ($current_arg < $#args) {
+    die ("wrong number of arguments");
+  } elsif ($current_arg > ($#args+1)) {
+    die ("wrong number of arguments");
+  }
+
+
+  # check for exceptions
+  if ($current_arg <= $#args) {
+    $str .= " plus " . &beautify ($args[$current_arg]);
+  }
+
+  # Put the C program line together
+  # Reset some variables to start again
+  $current_arg = 1;
+  $extra_var = 0;
+  if (substr($descr_res,0,1) eq 'f') {
+    $cline = 'check_float'
+  } elsif (substr($descr_res,0,1) eq 'b') {
+    $cline = 'check_bool';
+  } elsif (substr($descr_res,0,1) eq 'c') {
+    $cline = 'check_complex';
+  } elsif (substr($descr_res,0,1) eq 'i') {
+    $cline = 'check_int';
+  } elsif (substr($descr_res,0,1) eq 'l') {
+    $cline = 'check_long';
+  } elsif (substr($descr_res,0,1) eq 'L') {
+    $cline = 'check_longlong';
+  }
+  # Special handling for some macros:
+  $cline .= " (\"$str\", ";
+  if ($args[0] =~ /fpclassify|isnormal|isfinite|signbit/) {
+    $c_call = "$args[0] (";
+  } else {
+    $c_call = " FUNC($args[0]) (";
+  }
+  @descr = split //,$descr_args;
+  for ($i=0; $i <= $#descr; $i++) {
+    if ($i >= 1) {
+      $c_call .= ', ';
+    }
+    # FLOAT, int, long int, long long int
+    if ($descr[$i] =~ /f|i|l|L/) {
+      $c_call .= $args[$current_arg];
+      $current_arg++;
+      next;
+    }
+    # &FLOAT, &int
+    if ($descr[$i] =~ /F|I/) {
+      ++$extra_var;
+      $c_call .= '&' . &get_variable ($extra_var);
+      next;
+    }
+    # complex
+    if ($descr[$i] eq 'c') {
+      $c_call .= "BUILD_COMPLEX ($args[$current_arg], $args[$current_arg+1])";
+      $current_arg += 2;
+      next;
+    }
+  }
+  $c_call .= ')';
+  $cline .= "$c_call, ";
+
+  @descr = split //,$descr_res;
+  foreach (@descr) {
+    if ($_ =~ /b|f|i|l|L/ ) {
+      $cline .= $args[$current_arg];
+      $current_arg++;
+    } elsif ($_ eq 'c') {
+      $cline .= "BUILD_COMPLEX ($args[$current_arg], $args[$current_arg+1])";
+      $current_arg += 2;
+    } elsif ($_ eq '1') {
+      push @special, $args[$current_arg];
+      ++$current_arg;
+    }
+  }
+  # Add ulp, xfail
+  $cline .= &new_test ($str, ($current_arg <= $#args) ? $args[$current_arg] : undef);
+
+  # special treatment for some functions
+  if ($args[0] eq 'frexp') {
+    if (defined $special[0] && $special[0] ne "IGNORE") {
+      my ($str) = "$call sets x to $special[0]";
+      $post = "  check_int (\"$str\", x, $special[0]";
+      $post .= &new_test ($str, undef);
+    }
+  } elsif ($args[0] eq 'gamma' || $args[0] eq 'lgamma') {
+    $pre = "  signgam = 0;\n";
+    if (defined $special[0] && $special[0] ne "IGNORE") {
+      my ($str) = "$call sets signgam to $special[0]";
+      $post = "  check_int (\"$str\", signgam, $special[0]";
+      $post .= &new_test ($str, undef);
+    }
+  } elsif ($args[0] eq 'modf') {
+    if (defined $special[0] && $special[0] ne "IGNORE") {
+      my ($str) = "$call sets x to $special[0]";
+      $post = "  check_float (\"$str\", x, $special[0]";
+      $post .= &new_test ($str, undef);
+    }
+  } elsif ($args[0] eq 'remquo') {
+    if (defined $special[0] && $special[0] ne "IGNORE") {
+      my ($str) = "$call sets x to $special[0]";
+      $post = "  check_int (\"$str\", x, $special[0]";
+      $post .= &new_test ($str, undef);
+    }
+  }
+
+  print $file $pre if (defined $pre);
+
+  print $file "  $cline";
+
+  print $file $post if (defined $post);
+}
+
+# Generate libm-test.c
+sub generate_testfile {
+  my ($input, $output) = @_;
+  my ($lasttext);
+  my (@args, $i, $str);
+
+  open INPUT, $input or die ("Can't open $input: $!");
+  open OUTPUT, ">$output" or die ("Can't open $output: $!");
+
+  # Replace the special macros
+  while () {
+
+    # TEST_...
+    if (/^\s*TEST_/) {
+      my ($descr, $args);
+      chop;
+      ($descr, $args) = ($_ =~ /TEST_(\w+)\s*\((.*)\)/);
+      &parse_args (\*OUTPUT, $descr, $args);
+      next;
+    }
+    # START (function)
+    if (/START/) {
+      print OUTPUT "  init_max_error ();\n";
+      next;
+    }
+    # END (function)
+    if (/END/) {
+      my ($fct, $line, $type);
+      if (/complex/) {
+	s/,\s*complex\s*//;
+	$type = 'complex';
+      } else {
+	$type = 'normal';
+      }
+      ($fct) = ($_ =~ /END\s*\((.*)\)/);
+      if ($type eq 'complex') {
+	$line = "  print_complex_max_error (\"$fct\", ";
+      } else {
+	$line = "  print_max_error (\"$fct\", ";
+      }
+      if (exists $results{$fct}{'has_ulps'}) {
+	$line .= "DELTA$fct";
+      } else {
+	$line .= '0';
+      }
+      if (exists $results{$fct}{'has_fails'}) {
+	$line .= ", FAIL$fct";
+      } else {
+	$line .= ', 0';
+      }
+      $line .= ");\n";
+      print OUTPUT $line;
+      push @functions, $fct;
+      next;
+    }
+    print OUTPUT;
+  }
+  close INPUT;
+  close OUTPUT;
+}
+
+
+
+# Parse ulps file
+sub parse_ulps {
+  my ($file) = @_;
+  my ($test, $type, $float, $eps, $kind);
+
+  # $type has the following values:
+  # "normal": No complex variable
+  # "real": Real part of complex result
+  # "imag": Imaginary part of complex result
+  open ULP, $file  or die ("Can't open $file: $!");
+  while () {
+    chop;
+    # ignore comments and empty lines
+    next if /^#/;
+    next if /^\s*$/;
+    if (/^Test/) {
+      if (/Real part of:/) {
+	s/Real part of: //;
+	$type = 'real';
+      } elsif (/Imaginary part of:/) {
+	s/Imaginary part of: //;
+	$type = 'imag';
+      } else {
+	$type = 'normal';
+      }
+      s/^.+\"(.*)\".*$/$1/;
+      $test = $_;
+      $kind = 'test';
+      next;
+    }
+    if (/^Function: /) {
+      if (/Real part of/) {
+	s/Real part of //;
+	$type = 'real';
+      } elsif (/Imaginary part of/) {
+	s/Imaginary part of //;
+	$type = 'imag';
+      } else {
+	$type = 'normal';
+      }
+      ($test) = ($_ =~ /^Function:\s*\"([a-zA-Z0-9_]+)\"/);
+      $kind = 'fct';
+      next;
+    }
+    if (/^i?(float|double|ldouble):/) {
+      ($float, $eps) = split /\s*:\s*/,$_,2;
+
+      if ($eps eq 'fail') {
+	$results{$test}{$type}{'fail'}{$float} = 1;
+	$results{$test}{'has_fails'} = 1;
+      } elsif ($eps eq "0") {
+	# ignore
+	next;
+      } else {
+	$results{$test}{$type}{'ulp'}{$float} = $eps;
+	$results{$test}{'has_ulps'} = 1;
+      }
+      if ($type =~ /^real|imag$/) {
+	$results{$test}{'type'} = 'complex';
+      } elsif ($type eq 'normal') {
+	$results{$test}{'type'} = 'normal';
+      }
+      $results{$test}{'kind'} = $kind;
+      next;
+    }
+    print "Skipping unknown entry: `$_'\n";
+  }
+  close ULP;
+}
+
+
+# Clean up a floating point number
+sub clean_up_number {
+  my ($number) = @_;
+
+  # Remove trailing zeros
+  $number =~ s/0+$//;
+  $number =~ s/\.$//;
+  return $number;
+}
+
+# Output a file which can be read in as ulps file.
+sub print_ulps_file {
+  my ($file) = @_;
+  my ($test, $type, $float, $eps, $fct, $last_fct);
+
+  $last_fct = '';
+  open NEWULP, ">$file" or die ("Can't open $file: $!");
+  print NEWULP "# Begin of automatic generation\n";
+  # first the function calls
+  foreach $test (sort keys %results) {
+    next if ($results{$test}{'kind'} ne 'test');
+    foreach $type ('real', 'imag', 'normal') {
+      if (exists $results{$test}{$type}) {
+	if (defined $results{$test}) {
+	  ($fct) = ($test =~ /^(\w+)\s/);
+	  if ($fct ne $last_fct) {
+	    $last_fct = $fct;
+	    print NEWULP "\n# $fct\n";
+	  }
+	}
+	if ($type eq 'normal') {
+	  print NEWULP "Test \"$test\":\n";
+	} elsif ($type eq 'real') {
+	  print NEWULP "Test \"Real part of: $test\":\n";
+	} elsif ($type eq 'imag') {
+	  print NEWULP "Test \"Imaginary part of: $test\":\n";
+	}
+	foreach $float (@all_floats) {
+	  if (exists $results{$test}{$type}{'ulp'}{$float}) {
+	    print NEWULP "$float: ",
+	    &clean_up_number ($results{$test}{$type}{'ulp'}{$float}),
+	    "\n";
+	  }
+	  if (exists $results{$test}{$type}{'fail'}{$float}) {
+	    print NEWULP "$float: fail\n";
+	  }
+	}
+      }
+    }
+  }
+  print NEWULP "\n# Maximal error of functions:\n";
+
+  foreach $fct (sort keys %results) {
+    next if ($results{$fct}{'kind'} ne 'fct');
+    foreach $type ('real', 'imag', 'normal') {
+      if (exists $results{$fct}{$type}) {
+	if ($type eq 'normal') {
+	  print NEWULP "Function: \"$fct\":\n";
+	} elsif ($type eq 'real') {
+	  print NEWULP "Function: Real part of \"$fct\":\n";
+	} elsif ($type eq 'imag') {
+	  print NEWULP "Function: Imaginary part of \"$fct\":\n";
+	}
+	foreach $float (@all_floats) {
+	  if (exists $results{$fct}{$type}{'ulp'}{$float}) {
+	    print NEWULP "$float: ",
+	    &clean_up_number ($results{$fct}{$type}{'ulp'}{$float}),
+	    "\n";
+	  }
+	  if (exists $results{$fct}{$type}{'fail'}{$float}) {
+	    print NEWULP "$float: fail\n";
+	  }
+	}
+	print NEWULP "\n";
+      }
+    }
+  }
+  print NEWULP "# end of automatic generation\n";
+  close NEWULP;
+}
+
+sub get_ulps {
+  my ($test, $type, $float) = @_;
+
+  if ($type eq 'complex') {
+    my ($res);
+    # Return 0 instead of BUILD_COMPLEX (0,0)
+    if (!exists $results{$test}{'real'}{'ulp'}{$float} &&
+	!exists $results{$test}{'imag'}{'ulp'}{$float}) {
+      return "0";
+    }
+    $res = 'BUILD_COMPLEX (';
+    $res .= (exists $results{$test}{'real'}{'ulp'}{$float}
+	     ? $results{$test}{'real'}{'ulp'}{$float} : "0");
+    $res .= ', ';
+    $res .= (exists $results{$test}{'imag'}{'ulp'}{$float}
+	     ? $results{$test}{'imag'}{'ulp'}{$float} : "0");
+    $res .= ')';
+    return $res;
+  }
+  return (exists $results{$test}{'normal'}{'ulp'}{$float}
+	  ? $results{$test}{'normal'}{'ulp'}{$float} : "0");
+}
+
+sub get_failure {
+  my ($test, $type, $float) = @_;
+  if ($type eq 'complex') {
+    # return x,y
+    my ($res);
+    # Return 0 instead of BUILD_COMPLEX_INT (0,0)
+    if (!exists $results{$test}{'real'}{'ulp'}{$float} &&
+	!exists $results{$test}{'imag'}{'ulp'}{$float}) {
+      return "0";
+    }
+    $res = 'BUILD_COMPLEX_INT (';
+    $res .= (exists $results{$test}{'real'}{'fail'}{$float}
+	     ? $results{$test}{'real'}{'fail'}{$float} : "0");
+    $res .= ', ';
+    $res .= (exists $results{$test}{'imag'}{'fail'}{$float}
+	     ? $results{$test}{'imag'}{'fail'}{$float} : "0");
+    $res .= ')';
+    return $res;
+  }
+  return (exists $results{$test}{'normal'}{'fail'}{$float}
+	  ? $results{$test}{'normal'}{'fail'}{$float} : "0");
+
+}
+
+# Output the defines for a single test
+sub output_test {
+  my ($file, $test, $name) = @_;
+  my ($ldouble, $double, $float, $ildouble, $idouble, $ifloat);
+  my ($type);
+
+  # Do we have ulps/failures?
+  if (!exists $results{$test}{'type'}) {
+    return;
+  }
+  $type = $results{$test}{'type'};
+  if (exists $results{$test}{'has_ulps'}) {
+    # XXX use all_floats (change order!)
+    $ldouble = &get_ulps ($test, $type, "ldouble");
+    $double = &get_ulps ($test, $type, "double");
+    $float = &get_ulps ($test, $type, "float");
+    $ildouble = &get_ulps ($test, $type, "ildouble");
+    $idouble = &get_ulps ($test, $type, "idouble");
+    $ifloat = &get_ulps ($test, $type, "ifloat");
+    print $file "#define DELTA$name CHOOSE($ldouble, $double, $float, $ildouble, $idouble, $ifloat)\t/* $test  */\n";
+  }
+
+  if (exists $results{$test}{'has_fails'}) {
+    $ldouble = &get_failure ($test, "ldouble");
+    $double = &get_failure ($test, "double");
+    $float = &get_failure ($test, "float");
+    $ildouble = &get_failure ($test, "ildouble");
+    $idouble = &get_failure ($test, "idouble");
+    $ifloat = &get_failure ($test, "ifloat");
+    print $file "#define FAIL$name CHOOSE($ldouble, $double, $float $ildouble, $idouble, $ifloat)\t/* $test  */\n";
+  }
+}
+
+# Print include file
+sub output_ulps {
+  my ($file, $ulps_filename) = @_;
+  my ($i, $fct);
+
+  open ULP, ">$file" or die ("Can't open $file: $!");
+
+  print ULP "/* This file is automatically generated\n";
+  print ULP "   from $ulps_filename with gen-libm-test.pl.\n";
+  print ULP "   Don't change it - change instead the master files.  */\n\n";
+
+  print ULP "\n/* Maximal error of functions.  */\n";
+  foreach $fct (@functions) {
+    output_test (\*ULP, $fct, $fct);
+  }
+
+  print ULP "\n/* Error of single function calls.  */\n";
+  for ($i = 0; $i < $count; $i++) {
+    output_test (\*ULP, $tests[$i], $i);
+  }
+  close ULP;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/math/ilogb.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/math/ilogb.c
new file mode 100644
index 00000000..041e66b0
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/math/ilogb.c
@@ -0,0 +1,52 @@
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define check_d1(func, param, expected) \
+do { \
+	int err; hex_union ur; hex_union up; \
+	double result = func(param); up.f = param; ur.f = result; \
+	errors += (err = (result != (expected))); \
+	err \
+	? printf("FAIL: %s(%g/"HEXFMT")=%g/"HEXFMT" (expected %g)\n", \
+		#func, (double)(param), (long long)up.hex, result, (long long)ur.hex, (double)(expected)) \
+	: printf("PASS: %s(%g)=%g\n", #func, (double)(param), result); \
+} while (0)
+
+#define check_i1(func, param, expected) \
+do { \
+	int err; hex_union up; \
+	long long result = func(param); up.f = param; \
+	errors += (err = (result != (expected))); \
+	err \
+	? printf("FAIL: %s(%g/"HEXFMT")=%lld/%llu (expected %llu)\n", \
+		#func, (double)(param), (long long)up.hex, result, result, (long long)(expected)) \
+	: printf("PASS: %s(%g)=%lld/%llu\n", #func, (double)(param), result, result); \
+} while (0)
+
+#define HEXFMT "%08llx"
+typedef union {
+	double f;
+	uint64_t hex;
+} hex_union;
+
+double nan_value = 0.0;
+int errors = 0;
+
+int main(void)
+{
+	nan_value /= nan_value;
+
+	check_i1(ilogb, 0.0, FP_ILOGB0);
+	check_i1(ilogb, HUGE_VAL, INT_MAX);
+	check_i1(ilogb, nan_value, FP_ILOGBNAN);
+	check_i1(ilogbf, 0.0, FP_ILOGB0);
+	check_i1(ilogbf, HUGE_VALF, INT_MAX);
+	check_i1(ilogbf, nan_value, FP_ILOGBNAN);
+
+	printf("Errors: %d\n", errors);
+	return errors;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/math/libm-test-ulps-generic b/l4/pkg/uclibc/lib/contrib/uclibc/test/math/libm-test-ulps-generic
new file mode 100644
index 00000000..7cfa1f82
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/math/libm-test-ulps-generic
@@ -0,0 +1,5 @@
+# File with deltas for math/libm-test
+# This file is the fallback and contains
+# no data
+# You can create a new file with e.g. `test-double -u'
+# followed by `gen-libm-test.pl -u ULPs -n'.
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/math/libm-test-ulps-i386 b/l4/pkg/uclibc/lib/contrib/uclibc/test/math/libm-test-ulps-i386
new file mode 100644
index 00000000..a6fd6ac2
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/math/libm-test-ulps-i386
@@ -0,0 +1,1261 @@
+# Begin of automatic generation
+
+# acos
+Test "acos (0.75) == 0.722734247813415611178377352641333362":
+ildouble: 1
+ldouble: 1
+
+# asin
+Test "asin (-0.5) == -pi/6":
+ildouble: 1
+ldouble: 1
+Test "asin (-1.0) == -pi/2":
+ildouble: 1
+ldouble: 1
+Test "asin (0.5) == pi/6":
+ildouble: 1
+ldouble: 1
+Test "asin (0.75) == 0.848062078981481008052944338998418080":
+ildouble: 1
+ldouble: 1
+Test "asin (1.0) == pi/2":
+ildouble: 1
+ldouble: 1
+
+# atanh
+Test "atanh (0.75) == 0.972955074527656652552676371721589865":
+ildouble: 2
+ldouble: 1
+
+# cacos
+Test "Imaginary part of: cacos (0.75 + 1.25 i) == 1.11752014915610270578240049553777969 - 1.13239363160530819522266333696834467 i":
+float: 1
+ifloat: 1
+ildouble: 2
+ldouble: 2
+
+# cacosh
+Test "Real part of: cacosh (-2 - 3 i) == 1.9833870299165354323470769028940395 - 2.1414491111159960199416055713254211 i":
+double: 1
+float: 9
+idouble: 1
+ifloat: 9
+ildouble: 6
+ldouble: 6
+Test "Imaginary part of: cacosh (-2 - 3 i) == 1.9833870299165354323470769028940395 - 2.1414491111159960199416055713254211 i":
+double: 1
+float: 4
+idouble: 1
+ifloat: 4
+ildouble: 1
+ldouble: 1
+Test "Real part of: cacosh (0.75 + 1.25 i) == 1.13239363160530819522266333696834467 + 1.11752014915610270578240049553777969 i":
+ildouble: 1
+ldouble: 1
+
+# casin
+Test "Real part of: casin (0.75 + 1.25 i) == 0.453276177638793913448921196101971749 + 1.13239363160530819522266333696834467 i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 2
+ldouble: 2
+Test "Imaginary part of: casin (0.75 + 1.25 i) == 0.453276177638793913448921196101971749 + 1.13239363160530819522266333696834467 i":
+float: 1
+ifloat: 1
+ildouble: 2
+ldouble: 2
+
+# casinh
+Test "Real part of: casinh (-2 - 3 i) == -1.9686379257930962917886650952454982 - 0.96465850440760279204541105949953237 i":
+double: 5
+float: 1
+idouble: 5
+ifloat: 1
+ildouble: 5
+ldouble: 5
+Test "Imaginary part of: casinh (-2 - 3 i) == -1.9686379257930962917886650952454982 - 0.96465850440760279204541105949953237 i":
+double: 3
+float: 6
+idouble: 3
+ifloat: 6
+ildouble: 5
+ldouble: 5
+Test "Real part of: casinh (0.75 + 1.25 i) == 1.03171853444778027336364058631006594 + 0.911738290968487636358489564316731207 i":
+float: 1
+ifloat: 1
+Test "Imaginary part of: casinh (0.75 + 1.25 i) == 1.03171853444778027336364058631006594 + 0.911738290968487636358489564316731207 i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+# catan
+Test "Imaginary part of: catan (-2 - 3 i) == -1.4099210495965755225306193844604208 - 0.22907268296853876629588180294200276 i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+# catanh
+Test "Real part of: catanh (-2 - 3 i) == -0.14694666622552975204743278515471595 - 1.3389725222944935611241935759091443 i":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "Real part of: catanh (0.75 + 1.25 i) == 0.261492138795671927078652057366532140 + 0.996825126463918666098902241310446708 i":
+double: 1
+idouble: 1
+
+# cbrt
+Test "cbrt (-27.0) == -3.0":
+ildouble: 1
+ldouble: 1
+Test "cbrt (0.75) == 0.908560296416069829445605878163630251":
+ildouble: 1
+ldouble: 1
+
+# ccos
+Test "Imaginary part of: ccos (-2 - 3 i) == -4.18962569096880723013255501961597373 - 9.10922789375533659797919726277886212 i":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "Real part of: ccos (0.75 + 1.25 i) == 1.38173873063425888530729933139078645 - 1.09193013555397466170919531722024128 i":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+Test "Imaginary part of: ccos (0.75 + 1.25 i) == 1.38173873063425888530729933139078645 - 1.09193013555397466170919531722024128 i":
+ildouble: 1
+ldouble: 1
+
+# ccosh
+Test "Imaginary part of: ccosh (-2 - 3 i) == -3.72454550491532256547397070325597253 + 0.511822569987384608834463849801875634 i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "Real part of: ccosh (0.75 + 1.25 i) == 0.408242591877968807788852146397499084 + 0.780365930845853240391326216300863152 i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: ccosh (0.75 + 1.25 i) == 0.408242591877968807788852146397499084 + 0.780365930845853240391326216300863152 i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+# cexp
+Test "Real part of: cexp (-2.0 - 3.0 i) == -0.13398091492954261346140525546115575 - 0.019098516261135196432576240858800925 i":
+ildouble: 1
+ldouble: 1
+Test "Imaginary part of: cexp (-2.0 - 3.0 i) == -0.13398091492954261346140525546115575 - 0.019098516261135196432576240858800925 i":
+ildouble: 1
+ldouble: 1
+Test "Real part of: cexp (0.75 + 1.25 i) == 0.667537446429131586942201977015932112 + 2.00900045494094876258347228145863909 i":
+ildouble: 1
+ldouble: 1
+
+# clog
+Test "Real part of: clog (0.75 + 1.25 i) == 0.376885901188190075998919126749298416 + 1.03037682652431246378774332703115153 i":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+# clog10
+Test "Imaginary part of: clog10 (-0 + inf i) == inf + pi/2*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (-0 - inf i) == inf - pi/2*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (-2 - 3 i) == 0.556971676153418384603252578971164214 - 0.937554462986374708541507952140189646 i":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+Test "Imaginary part of: clog10 (-3 + inf i) == inf + pi/2*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (-3 - inf i) == inf - pi/2*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (-inf + 0 i) == inf + pi*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (-inf + 1 i) == inf + pi*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (-inf + inf i) == inf + 3/4 pi*log10(e) i":
+double: 1
+idouble: 1
+Test "Imaginary part of: clog10 (-inf - 0 i) == inf - pi*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (-inf - 1 i) == inf - pi*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (0 + inf i) == inf + pi/2*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (0 - inf i) == inf - pi/2*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Real part of: clog10 (0.75 + 1.25 i) == 0.163679467193165171449476605077428975 + 0.447486970040493067069984724340855636 i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "Imaginary part of: clog10 (3 + inf i) == inf + pi/2*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (3 - inf i) == inf - pi/2*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (inf + inf i) == inf + pi/4*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (inf - inf i) == inf - pi/4*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+# cos
+Test "cos (M_PI_6l * 2.0) == 0.5":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "cos (M_PI_6l * 4.0) == -0.5":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "cos (pi/2) == 0":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+# cosh
+Test "cosh (0.75) == 1.29468328467684468784170818539018176":
+ildouble: 1
+
+# cpow
+Test "Real part of: cpow (0.75 + 1.25 i, 0.0 + 1.0 i) == 0.331825439177608832276067945276730566 + 0.131338600281188544930936345230903032 i":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "Imaginary part of: cpow (0.75 + 1.25 i, 0.0 + 1.0 i) == 0.331825439177608832276067945276730566 + 0.131338600281188544930936345230903032 i":
+ildouble: 1
+ldouble: 1
+Test "Real part of: cpow (0.75 + 1.25 i, 0.75 + 1.25 i) == 0.117506293914473555420279832210420483 + 0.346552747708338676483025352060418001 i":
+float: 3
+ifloat: 3
+ildouble: 6
+ldouble: 6
+Test "Imaginary part of: cpow (0.75 + 1.25 i, 0.75 + 1.25 i) == 0.117506293914473555420279832210420483 + 0.346552747708338676483025352060418001 i":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "Real part of: cpow (0.75 + 1.25 i, 1.0 + 0.0 i) == 0.75 + 1.25 i":
+ildouble: 1
+ldouble: 1
+Test "Imaginary part of: cpow (0.75 + 1.25 i, 1.0 + 0.0 i) == 0.75 + 1.25 i":
+float: 1
+ifloat: 1
+Test "Real part of: cpow (0.75 + 1.25 i, 1.0 + 1.0 i) == 0.0846958290317209430433805274189191353 + 0.513285749182902449043287190519090481 i":
+double: 1
+float: 3
+idouble: 1
+ifloat: 3
+ildouble: 3
+ldouble: 3
+Test "Real part of: cpow (2 + 3 i, 4 + 0 i) == -119.0 - 120.0 i":
+double: 1
+float: 4
+idouble: 1
+ifloat: 4
+Test "Imaginary part of: cpow (2 + 3 i, 4 + 0 i) == -119.0 - 120.0 i":
+float: 1
+ifloat: 1
+ildouble: 2
+ldouble: 2
+Test "Imaginary part of: cpow (e + 0 i, 0 + 2 * M_PIl i) == 1.0 + 0.0 i":
+double: 2
+float: 3
+idouble: 2
+ifloat: 3
+ildouble: 1
+ldouble: 1
+
+# csin
+Test "Real part of: csin (0.75 + 1.25 i) == 1.28722291002649188575873510790565441 + 1.17210635989270256101081285116138863 i":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "Imaginary part of: csin (0.75 + 1.25 i) == 1.28722291002649188575873510790565441 + 1.17210635989270256101081285116138863 i":
+float: 1
+ifloat: 1
+
+# csinh
+Test "Real part of: csinh (-2 - 3 i) == 3.59056458998577995201256544779481679 - 0.530921086248519805267040090660676560 i":
+double: 1
+idouble: 1
+Test "Imaginary part of: csinh (-2 - 3 i) == 3.59056458998577995201256544779481679 - 0.530921086248519805267040090660676560 i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 2
+ldouble: 2
+Test "Real part of: csinh (0.75 + 1.25 i) == 0.259294854551162779153349830618433028 + 1.22863452409509552219214606515777594 i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "Imaginary part of: csinh (0.75 + 1.25 i) == 0.259294854551162779153349830618433028 + 1.22863452409509552219214606515777594 i":
+float: 1
+ifloat: 1
+
+# ctan
+Test "Real part of: ctan (-2 - 3 i) == 0.376402564150424829275122113032269084e-2 - 1.00323862735360980144635859782192726 i":
+double: 1
+idouble: 1
+ildouble: 439
+ldouble: 439
+Test "Imaginary part of: ctan (-2 - 3 i) == 0.376402564150424829275122113032269084e-2 - 1.00323862735360980144635859782192726 i":
+float: 1
+ifloat: 1
+ildouble: 2
+ldouble: 2
+Test "Real part of: ctan (0.75 + 1.25 i) == 0.160807785916206426725166058173438663 + 0.975363285031235646193581759755216379 i":
+ildouble: 1
+ldouble: 1
+Test "Imaginary part of: ctan (0.75 + 1.25 i) == 0.160807785916206426725166058173438663 + 0.975363285031235646193581759755216379 i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 3
+ldouble: 3
+
+# ctanh
+Test "Real part of: ctanh (-2 - 3 i) == -0.965385879022133124278480269394560686 + 0.988437503832249372031403430350121098e-2 i":
+ildouble: 5
+ldouble: 5
+Test "Imaginary part of: ctanh (-2 - 3 i) == -0.965385879022133124278480269394560686 + 0.988437503832249372031403430350121098e-2 i":
+float: 1
+ifloat: 1
+ildouble: 25
+ldouble: 25
+Test "Imaginary part of: ctanh (0 + pi/4 i) == 0.0 + 1.0 i":
+float: 1
+ifloat: 1
+Test "Real part of: ctanh (0.75 + 1.25 i) == 1.37260757053378320258048606571226857 + 0.385795952609750664177596760720790220 i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: ctanh (0.75 + 1.25 i) == 1.37260757053378320258048606571226857 + 0.385795952609750664177596760720790220 i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+# erf
+Test "erf (1.25) == 0.922900128256458230136523481197281140":
+double: 1
+idouble: 1
+
+# erfc
+Test "erfc (0.75) == 0.288844366346484868401062165408589223":
+float: 1
+ifloat: 1
+Test "erfc (1.25) == 0.0770998717435417698634765188027188596":
+ildouble: 1
+ldouble: 1
+Test "erfc (2.0) == 0.00467773498104726583793074363274707139":
+double: 1
+idouble: 1
+Test "erfc (4.125) == 0.542340079956506600531223408575531062e-8":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+
+# exp
+Test "exp (0.75) == 2.11700001661267466854536981983709561":
+ildouble: 1
+Test "exp (1000.0) == 0.197007111401704699388887935224332313e435":
+ildouble: 754
+Test "exp (50.0) == 5184705528587072464087.45332293348538":
+ildouble: 16
+
+# exp10
+Test "exp10 (-1) == 0.1":
+ildouble: 1
+ldouble: 1
+Test "exp10 (0.75) == 5.62341325190349080394951039776481231":
+ildouble: 2
+ldouble: 2
+Test "exp10 (3) == 1000":
+ildouble: 8
+ldouble: 8
+
+# expm1
+Test "expm1 (1) == M_El - 1.0":
+ildouble: 1
+
+# gamma
+Test "gamma (-0.5) == log(2*sqrt(pi))":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+
+# hypot
+Test "hypot (-0.7, -12.4) == 12.419742348374220601176836866763271":
+float: 1
+ifloat: 1
+Test "hypot (-0.7, 12.4) == 12.419742348374220601176836866763271":
+float: 1
+ifloat: 1
+Test "hypot (-12.4, -0.7) == 12.419742348374220601176836866763271":
+float: 1
+ifloat: 1
+Test "hypot (-12.4, 0.7) == 12.419742348374220601176836866763271":
+float: 1
+ifloat: 1
+Test "hypot (0.7, -12.4) == 12.419742348374220601176836866763271":
+float: 1
+ifloat: 1
+Test "hypot (0.7, 12.4) == 12.419742348374220601176836866763271":
+float: 1
+ifloat: 1
+Test "hypot (12.4, -0.7) == 12.419742348374220601176836866763271":
+float: 1
+ifloat: 1
+Test "hypot (12.4, 0.7) == 12.419742348374220601176836866763271":
+float: 1
+ifloat: 1
+
+# j0
+Test "j0 (-4.0) == -3.9714980986384737228659076845169804197562E-1":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 1
+ldouble: 1
+Test "j0 (10.0) == -0.245935764451348335197760862485328754":
+double: 3
+float: 1
+idouble: 3
+ifloat: 1
+Test "j0 (2.0) == 0.223890779141235668051827454649948626":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "j0 (4.0) == -3.9714980986384737228659076845169804197562E-1":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 1
+ldouble: 1
+Test "j0 (8.0) == 0.171650807137553906090869407851972001":
+float: 1
+ifloat: 1
+
+# j1
+Test "j1 (0.75) == 0.349243602174862192523281016426251335":
+double: 1
+idouble: 1
+Test "j1 (10.0) == 0.0434727461688614366697487680258592883":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "j1 (2.0) == 0.576724807756873387202448242269137087":
+double: 1
+idouble: 1
+Test "j1 (8.0) == 0.234636346853914624381276651590454612":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+# jn
+Test "jn (0, -4.0) == -3.9714980986384737228659076845169804197562E-1":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 1
+ldouble: 1
+Test "jn (0, 10.0) == -0.245935764451348335197760862485328754":
+double: 3
+float: 1
+idouble: 3
+ifloat: 1
+Test "jn (0, 2.0) == 0.223890779141235668051827454649948626":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "jn (0, 4.0) == -3.9714980986384737228659076845169804197562E-1":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 1
+ldouble: 1
+Test "jn (0, 8.0) == 0.171650807137553906090869407851972001":
+float: 1
+ifloat: 1
+Test "jn (1, 0.75) == 0.349243602174862192523281016426251335":
+double: 1
+idouble: 1
+Test "jn (1, 10.0) == 0.0434727461688614366697487680258592883":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "jn (1, 2.0) == 0.576724807756873387202448242269137087":
+double: 1
+idouble: 1
+Test "jn (1, 8.0) == 0.234636346853914624381276651590454612":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "jn (10, -1.0) == 0.263061512368745320699785368779050294e-9":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "jn (10, 0.125) == 0.250543369809369890173993791865771547e-18":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "jn (10, 0.75) == 0.149621713117596814698712483621682835e-10":
+float: 1
+ifloat: 1
+ildouble: 2
+ldouble: 2
+Test "jn (10, 1.0) == 0.263061512368745320699785368779050294e-9":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "jn (10, 10.0) == 0.207486106633358857697278723518753428":
+double: 5
+float: 2
+idouble: 5
+ifloat: 2
+ildouble: 2
+ldouble: 2
+Test "jn (10, 2.0) == 0.251538628271673670963516093751820639e-6":
+double: 2
+idouble: 2
+ildouble: 1
+ldouble: 1
+Test "jn (3, -1.0) == -0.0195633539826684059189053216217515083":
+ildouble: 1
+ldouble: 1
+Test "jn (3, 0.75) == 0.848438342327410884392755236884386804e-2":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "jn (3, 1.0) == 0.0195633539826684059189053216217515083":
+ildouble: 1
+ldouble: 1
+Test "jn (3, 10.0) == 0.0583793793051868123429354784103409563":
+double: 5
+float: 2
+idouble: 5
+ifloat: 2
+ildouble: 1
+ldouble: 1
+Test "jn (3, 2.0) == 0.128943249474402051098793332969239835":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+
+# lgamma
+Test "lgamma (-0.5) == log(2*sqrt(pi))":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+Test "lgamma (0.7) == 0.260867246531666514385732417016759578":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "lgamma (1.2) == -0.853740900033158497197028392998854470e-1":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 1
+ldouble: 1
+
+# log
+Test "log (e) == 1":
+float: 1
+ifloat: 1
+
+# log10
+Test "log10 (0.75) == -0.124938736608299953132449886193870744":
+ildouble: 1
+ldouble: 1
+Test "log10 (e) == log10(e)":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+# sincos
+Test "sincos (M_PI_6l*2.0, &sin_res, &cos_res) puts 0.5 in cos_res":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "sincos (M_PI_6l*2.0, &sin_res, &cos_res) puts 0.86602540378443864676372317075293616 in sin_res":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "sincos (pi/2, &sin_res, &cos_res) puts 0 in cos_res":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+# sin
+Test "sin (0.80190127184058835) == 0.71867942238767868":
+double: 1
+idouble: 1
+
+# sinh
+Test "sinh (0.75) == 0.822316731935829980703661634446913849":
+double: 1
+ildouble: 1
+
+# tan
+Test "tan (pi/4) == 1":
+double: 1
+idouble: 1
+
+# tgamma
+Test "tgamma (-0.5) == -2 sqrt (pi)":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "tgamma (0.5) == sqrt (pi)":
+float: 1
+ifloat: 1
+Test "tgamma (0.7) == 1.29805533264755778568117117915281162":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "tgamma (4) == 6":
+ildouble: 1
+ldouble: 1
+
+# y0
+Test "y0 (0.125) == -1.38968062514384052915582277745018693":
+ildouble: 1
+ldouble: 1
+Test "y0 (0.75) == -0.137172769385772397522814379396581855":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "y0 (1.0) == 0.0882569642156769579829267660235151628":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "y0 (1.5) == 0.382448923797758843955068554978089862":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "y0 (10.0) == 0.0556711672835993914244598774101900481":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "y0 (8.0) == 0.223521489387566220527323400498620359":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+# y1
+Test "y1 (0.125) == -5.19993611253477499595928744876579921":
+ildouble: 1
+ldouble: 1
+Test "y1 (1.0) == -0.781212821300288716547150000047964821":
+double: 1
+idouble: 1
+Test "y1 (10.0) == 0.249015424206953883923283474663222803":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+Test "y1 (2.0) == -0.107032431540937546888370772277476637":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 1
+ldouble: 1
+Test "y1 (8.0) == -0.158060461731247494255555266187483550":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 1
+ldouble: 1
+
+# yn
+Test "yn (0, 0.125) == -1.38968062514384052915582277745018693":
+ildouble: 1
+ldouble: 1
+Test "yn (0, 0.75) == -0.137172769385772397522814379396581855":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "yn (0, 1.0) == 0.0882569642156769579829267660235151628":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "yn (0, 1.5) == 0.382448923797758843955068554978089862":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "yn (0, 10.0) == 0.0556711672835993914244598774101900481":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "yn (0, 8.0) == 0.223521489387566220527323400498620359":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "yn (1, 0.125) == -5.19993611253477499595928744876579921":
+ildouble: 1
+ldouble: 1
+Test "yn (1, 1.0) == -0.781212821300288716547150000047964821":
+double: 1
+idouble: 1
+Test "yn (1, 10.0) == 0.249015424206953883923283474663222803":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+Test "yn (1, 2.0) == -0.107032431540937546888370772277476637":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 1
+ldouble: 1
+Test "yn (1, 8.0) == -0.158060461731247494255555266187483550":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 1
+ldouble: 1
+Test "yn (10, 0.125) == -127057845771019398.252538486899753195":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 2
+ldouble: 2
+Test "yn (10, 0.75) == -2133501638.90573424452445412893839236":
+float: 1
+ifloat: 1
+ildouble: 4
+ldouble: 4
+Test "yn (10, 1.0) == -121618014.278689189288130426667971145":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+Test "yn (10, 10.0) == -0.359814152183402722051986577343560609":
+double: 1
+float: 3
+idouble: 1
+ifloat: 3
+Test "yn (10, 2.0) == -129184.542208039282635913145923304214":
+double: 2
+float: 3
+idouble: 2
+ifloat: 3
+Test "yn (3, 0.125) == -2612.69757350066712600220955744091741":
+ildouble: 1
+ldouble: 1
+Test "yn (3, 0.75) == -12.9877176234475433186319774484809207":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 2
+ldouble: 2
+Test "yn (3, 10.0) == -0.251362657183837329779204747654240998":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "yn (3, 2.0) == -1.12778377684042778608158395773179238":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+# Maximal error of functions:
+Function: "acos":
+ildouble: 622
+ldouble: 622
+
+Function: "asin":
+ildouble: 1
+ldouble: 1
+
+Function: "atanh":
+ildouble: 2
+ldouble: 1
+
+Function: Imaginary part of "cacos":
+float: 1
+ifloat: 1
+ildouble: 2
+ldouble: 2
+
+Function: Real part of "cacosh":
+double: 1
+float: 9
+idouble: 1
+ifloat: 9
+ildouble: 6
+ldouble: 6
+
+Function: Imaginary part of "cacosh":
+double: 1
+float: 4
+idouble: 1
+ifloat: 4
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "casin":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 2
+ldouble: 2
+
+Function: Imaginary part of "casin":
+float: 1
+ifloat: 1
+ildouble: 2
+ldouble: 2
+
+Function: Real part of "casinh":
+double: 5
+float: 1
+idouble: 5
+ifloat: 1
+ildouble: 5
+ldouble: 5
+
+Function: Imaginary part of "casinh":
+double: 3
+float: 6
+idouble: 3
+ifloat: 6
+ildouble: 5
+ldouble: 5
+
+Function: Imaginary part of "catan":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: Real part of "catanh":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "cbrt":
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "ccos":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+
+Function: Imaginary part of "ccos":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "ccosh":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: Imaginary part of "ccosh":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "cexp":
+ildouble: 1
+ldouble: 1
+
+Function: Imaginary part of "cexp":
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "clog":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "clog10":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: Imaginary part of "clog10":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "cos":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "cosh":
+ildouble: 1
+
+Function: Real part of "cpow":
+double: 1
+float: 4
+idouble: 1
+ifloat: 4
+ildouble: 763
+ldouble: 763
+
+Function: Imaginary part of "cpow":
+double: 2
+float: 3
+idouble: 2
+ifloat: 3
+ildouble: 2
+ldouble: 2
+
+Function: Real part of "csin":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: Imaginary part of "csin":
+float: 1
+ifloat: 1
+
+Function: Real part of "csinh":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: Imaginary part of "csinh":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 2
+ldouble: 2
+
+Function: Real part of "ctan":
+double: 1
+idouble: 1
+ildouble: 439
+ldouble: 439
+
+Function: Imaginary part of "ctan":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 3
+ldouble: 3
+
+Function: Real part of "ctanh":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 5
+ldouble: 5
+
+Function: Imaginary part of "ctanh":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 25
+ldouble: 25
+
+Function: "erf":
+double: 1
+idouble: 1
+
+Function: "erfc":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "exp":
+ildouble: 754
+
+Function: "exp10":
+ildouble: 8
+ldouble: 8
+
+Function: "expm1":
+ildouble: 1
+
+Function: "gamma":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+
+Function: "hypot":
+float: 1
+ifloat: 1
+
+Function: "j0":
+double: 3
+float: 2
+idouble: 3
+ifloat: 2
+ildouble: 1
+ldouble: 1
+
+Function: "j1":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "jn":
+double: 5
+float: 2
+idouble: 5
+ifloat: 2
+ildouble: 2
+ldouble: 2
+
+Function: "lgamma":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 1
+ldouble: 1
+
+Function: "log":
+float: 1
+ifloat: 1
+
+Function: "log10":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "sincos":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "sin":
+double: 1
+idouble: 1
+
+Function: "sinh":
+double: 1
+ildouble: 1
+
+Function: "tan":
+double: 1
+idouble: 1
+
+Function: "tgamma":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "y0":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "y1":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+ildouble: 1
+ldouble: 1
+
+Function: "yn":
+double: 2
+float: 3
+idouble: 2
+ifloat: 3
+ildouble: 4
+ldouble: 4
+
+# end of automatic generation
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/math/libm-test-ulps-ia64 b/l4/pkg/uclibc/lib/contrib/uclibc/test/math/libm-test-ulps-ia64
new file mode 100644
index 00000000..c5a2a085
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/math/libm-test-ulps-ia64
@@ -0,0 +1,1146 @@
+# Begin of automatic generation
+
+# cacos
+Test "Imaginary part of: cacos (0.75 + 1.25 i) == 1.11752014915610270578240049553777969 - 1.13239363160530819522266333696834467 i":
+float: 1
+ifloat: 1
+ildouble: 2
+ldouble: 2
+
+# cacosh
+Test "Real part of: cacosh (-2 - 3 i) == 1.9833870299165354323470769028940395 - 2.1414491111159960199416055713254211 i":
+double: 1
+float: 7
+idouble: 1
+ifloat: 7
+ildouble: 7
+ldouble: 7
+Test "Imaginary part of: cacosh (-2 - 3 i) == 1.9833870299165354323470769028940395 - 2.1414491111159960199416055713254211 i":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+
+# casin
+Test "Real part of: casin (0.75 + 1.25 i) == 0.453276177638793913448921196101971749 + 1.13239363160530819522266333696834467 i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 2
+ldouble: 2
+Test "Imaginary part of: casin (0.75 + 1.25 i) == 0.453276177638793913448921196101971749 + 1.13239363160530819522266333696834467 i":
+float: 1
+ifloat: 1
+ildouble: 2
+ldouble: 2
+
+# casinh
+Test "Real part of: casinh (-2 - 3 i) == -1.9686379257930962917886650952454982 - 0.96465850440760279204541105949953237 i":
+double: 5
+float: 1
+idouble: 5
+ifloat: 1
+ildouble: 5
+ldouble: 5
+Test "Imaginary part of: casinh (-2 - 3 i) == -1.9686379257930962917886650952454982 - 0.96465850440760279204541105949953237 i":
+double: 3
+float: 6
+idouble: 3
+ifloat: 6
+ildouble: 5
+ldouble: 5
+Test "Real part of: casinh (0.75 + 1.25 i) == 1.03171853444778027336364058631006594 + 0.911738290968487636358489564316731207 i":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "Imaginary part of: casinh (0.75 + 1.25 i) == 1.03171853444778027336364058631006594 + 0.911738290968487636358489564316731207 i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+# catan
+Test "Imaginary part of: catan (-2 - 3 i) == -1.4099210495965755225306193844604208 - 0.22907268296853876629588180294200276 i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+# catanh
+Test "Real part of: catanh (-2 - 3 i) == -0.14694666622552975204743278515471595 - 1.3389725222944935611241935759091443 i":
+double: 4
+idouble: 4
+ildouble: 1
+ldouble: 1
+Test "Real part of: catanh (0.75 + 1.25 i) == 0.261492138795671927078652057366532140 + 0.996825126463918666098902241310446708 i":
+double: 1
+idouble: 1
+
+# ccos
+Test "Imaginary part of: ccos (-2 - 3 i) == -4.18962569096880723013255501961597373 - 9.10922789375533659797919726277886212 i":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "Real part of: ccos (0.75 + 1.25 i) == 1.38173873063425888530729933139078645 - 1.09193013555397466170919531722024128 i":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+Test "Imaginary part of: ccos (0.75 + 1.25 i) == 1.38173873063425888530729933139078645 - 1.09193013555397466170919531722024128 i":
+ildouble: 1
+ldouble: 1
+
+# ccosh
+Test "Imaginary part of: ccosh (-2 - 3 i) == -3.72454550491532256547397070325597253 + 0.511822569987384608834463849801875634 i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "Real part of: ccosh (0.75 + 1.25 i) == 0.408242591877968807788852146397499084 + 0.780365930845853240391326216300863152 i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: ccosh (0.75 + 1.25 i) == 0.408242591877968807788852146397499084 + 0.780365930845853240391326216300863152 i":
+float: 1
+ifloat: 1
+
+# cexp
+Test "Imaginary part of: cexp (-2.0 - 3.0 i) == -0.13398091492954261346140525546115575 - 0.019098516261135196432576240858800925 i":
+float: 1
+ifloat: 1
+Test "Real part of: cexp (0.75 + 1.25 i) == 0.667537446429131586942201977015932112 + 2.00900045494094876258347228145863909 i":
+float: 1
+ifloat: 1
+Test "Imaginary part of: cexp (0.75 + 1.25 i) == 0.667537446429131586942201977015932112 + 2.00900045494094876258347228145863909 i":
+ildouble: 1
+ldouble: 1
+
+# clog
+Test "Real part of: clog (0.75 + 1.25 i) == 0.376885901188190075998919126749298416 + 1.03037682652431246378774332703115153 i":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+# clog10
+Test "Imaginary part of: clog10 (-0 + inf i) == inf + pi/2*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (-0 - inf i) == inf - pi/2*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (-2 - 3 i) == 0.556971676153418384603252578971164214 - 0.937554462986374708541507952140189646 i":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+Test "Imaginary part of: clog10 (-3 + inf i) == inf + pi/2*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (-3 - inf i) == inf - pi/2*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (-inf + 0 i) == inf + pi*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (-inf + 1 i) == inf + pi*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (-inf + inf i) == inf + 3/4 pi*log10(e) i":
+double: 1
+idouble: 1
+Test "Imaginary part of: clog10 (-inf - 0 i) == inf - pi*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (-inf - 1 i) == inf - pi*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (0 + inf i) == inf + pi/2*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (0 - inf i) == inf - pi/2*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Real part of: clog10 (0.75 + 1.25 i) == 0.163679467193165171449476605077428975 + 0.447486970040493067069984724340855636 i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "Imaginary part of: clog10 (3 + inf i) == inf + pi/2*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (3 - inf i) == inf - pi/2*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (inf + inf i) == inf + pi/4*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (inf - inf i) == inf - pi/4*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+# cos
+Test "cos (0.80190127184058835) == 0.69534156199418473":
+double: 1
+idouble: 1
+Test "cos (M_PI_6l * 2.0) == 0.5":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "cos (M_PI_6l * 4.0) == -0.5":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "cos (pi/2) == 0":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+# cpow
+Test "Real part of: cpow (0.75 + 1.25 i, 0.0 + 1.0 i) == 0.331825439177608832276067945276730566 + 0.131338600281188544930936345230903032 i":
+float: 1
+ifloat: 1
+Test "Imaginary part of: cpow (0.75 + 1.25 i, 0.0 + 1.0 i) == 0.331825439177608832276067945276730566 + 0.131338600281188544930936345230903032 i":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "Real part of: cpow (0.75 + 1.25 i, 0.75 + 1.25 i) == 0.117506293914473555420279832210420483 + 0.346552747708338676483025352060418001 i":
+double: 1
+float: 4
+idouble: 1
+ifloat: 4
+ildouble: 6
+ldouble: 6
+Test "Imaginary part of: cpow (0.75 + 1.25 i, 0.75 + 1.25 i) == 0.117506293914473555420279832210420483 + 0.346552747708338676483025352060418001 i":
+ildouble: 1
+ldouble: 1
+Test "Real part of: cpow (0.75 + 1.25 i, 1.0 + 0.0 i) == 0.75 + 1.25 i":
+ildouble: 1
+ldouble: 1
+Test "Real part of: cpow (0.75 + 1.25 i, 1.0 + 1.0 i) == 0.0846958290317209430433805274189191353 + 0.513285749182902449043287190519090481 i":
+double: 2
+float: 3
+idouble: 2
+ifloat: 3
+ildouble: 3
+ldouble: 3
+Test "Real part of: cpow (2 + 0 i, 10 + 0 i) == 1024.0 + 0.0 i":
+ildouble: 1
+ldouble: 1
+Test "Real part of: cpow (2 + 3 i, 4 + 0 i) == -119.0 - 120.0 i":
+double: 1
+float: 5
+idouble: 1
+ifloat: 5
+ildouble: 1
+ldouble: 1
+Test "Imaginary part of: cpow (2 + 3 i, 4 + 0 i) == -119.0 - 120.0 i":
+float: 2
+ifloat: 2
+ildouble: 4
+ldouble: 4
+Test "Imaginary part of: cpow (e + 0 i, 0 + 2 * M_PIl i) == 1.0 + 0.0 i":
+double: 2
+float: 3
+idouble: 2
+ifloat: 3
+ildouble: 1
+ldouble: 1
+
+# csin
+Test "Real part of: csin (0.75 + 1.25 i) == 1.28722291002649188575873510790565441 + 1.17210635989270256101081285116138863 i":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "Imaginary part of: csin (0.75 + 1.25 i) == 1.28722291002649188575873510790565441 + 1.17210635989270256101081285116138863 i":
+float: 1
+ifloat: 1
+
+# csinh
+Test "Real part of: csinh (-2 - 3 i) == 3.59056458998577995201256544779481679 - 0.530921086248519805267040090660676560 i":
+double: 1
+idouble: 1
+Test "Imaginary part of: csinh (-2 - 3 i) == 3.59056458998577995201256544779481679 - 0.530921086248519805267040090660676560 i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 2
+ldouble: 2
+Test "Real part of: csinh (0.75 + 1.25 i) == 0.259294854551162779153349830618433028 + 1.22863452409509552219214606515777594 i":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "Imaginary part of: csinh (0.75 + 1.25 i) == 0.259294854551162779153349830618433028 + 1.22863452409509552219214606515777594 i":
+float: 1
+ifloat: 1
+
+# csqrt
+Test "Real part of: csqrt (-2 + 3 i) == 0.89597747612983812471573375529004348 + 1.6741492280355400404480393008490519 i":
+float: 1
+ifloat: 1
+Test "Real part of: csqrt (-2 - 3 i) == 0.89597747612983812471573375529004348 - 1.6741492280355400404480393008490519 i":
+float: 1
+ifloat: 1
+
+# ctan
+Test "Real part of: ctan (-2 - 3 i) == 0.376402564150424829275122113032269084e-2 - 1.00323862735360980144635859782192726 i":
+double: 1
+idouble: 1
+ildouble: 2
+ldouble: 2
+Test "Imaginary part of: ctan (-2 - 3 i) == 0.376402564150424829275122113032269084e-2 - 1.00323862735360980144635859782192726 i":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "Real part of: ctan (0.75 + 1.25 i) == 0.160807785916206426725166058173438663 + 0.975363285031235646193581759755216379 i":
+ildouble: 1
+ldouble: 1
+Test "Imaginary part of: ctan (0.75 + 1.25 i) == 0.160807785916206426725166058173438663 + 0.975363285031235646193581759755216379 i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+# ctanh
+Test "Real part of: ctanh (-2 - 3 i) == -0.965385879022133124278480269394560686 + 0.988437503832249372031403430350121098e-2 i":
+ildouble: 1
+ldouble: 1
+Test "Imaginary part of: ctanh (-2 - 3 i) == -0.965385879022133124278480269394560686 + 0.988437503832249372031403430350121098e-2 i":
+float: 1
+ifloat: 1
+ildouble: 24
+ldouble: 24
+Test "Imaginary part of: ctanh (0 + pi/4 i) == 0.0 + 1.0 i":
+float: 1
+ifloat: 1
+Test "Real part of: ctanh (0.75 + 1.25 i) == 1.37260757053378320258048606571226857 + 0.385795952609750664177596760720790220 i":
+double: 1
+idouble: 1
+Test "Imaginary part of: ctanh (0.75 + 1.25 i) == 1.37260757053378320258048606571226857 + 0.385795952609750664177596760720790220 i":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+
+# erf
+Test "erf (1.25) == 0.922900128256458230136523481197281140":
+double: 1
+idouble: 1
+
+# erfc
+Test "erfc (0.75) == 0.288844366346484868401062165408589223":
+float: 1
+ifloat: 1
+Test "erfc (1.25) == 0.0770998717435417698634765188027188596":
+ildouble: 1
+ldouble: 1
+Test "erfc (2.0) == 0.00467773498104726583793074363274707139":
+double: 1
+idouble: 1
+Test "erfc (4.125) == 0.542340079956506600531223408575531062e-8":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+
+# exp10
+Test "exp10 (-1) == 0.1":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+Test "exp10 (0.75) == 5.62341325190349080394951039776481231":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "exp10 (3) == 1000":
+double: 6
+float: 2
+idouble: 6
+ifloat: 2
+ildouble: 3
+ldouble: 3
+
+# expm1
+Test "expm1 (1) == M_El - 1.0":
+ildouble: 1
+ldouble: 1
+
+# gamma
+Test "gamma (-0.5) == log(2*sqrt(pi))":
+ildouble: 1
+ldouble: 1
+
+# hypot
+Test "hypot (-0.7, -12.4) == 12.419742348374220601176836866763271":
+float: 1
+ifloat: 1
+Test "hypot (-0.7, 12.4) == 12.419742348374220601176836866763271":
+float: 1
+ifloat: 1
+Test "hypot (-12.4, -0.7) == 12.419742348374220601176836866763271":
+float: 1
+ifloat: 1
+Test "hypot (-12.4, 0.7) == 12.419742348374220601176836866763271":
+float: 1
+ifloat: 1
+Test "hypot (0.7, -12.4) == 12.419742348374220601176836866763271":
+float: 1
+ifloat: 1
+Test "hypot (0.7, 12.4) == 12.419742348374220601176836866763271":
+float: 1
+ifloat: 1
+Test "hypot (12.4, -0.7) == 12.419742348374220601176836866763271":
+float: 1
+ifloat: 1
+Test "hypot (12.4, 0.7) == 12.419742348374220601176836866763271":
+float: 1
+ifloat: 1
+
+# j0
+Test "j0 (-4.0) == -3.9714980986384737228659076845169804197562E-1":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 2
+ldouble: 2
+Test "j0 (10.0) == -0.245935764451348335197760862485328754":
+double: 3
+float: 1
+idouble: 3
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "j0 (2.0) == 0.223890779141235668051827454649948626":
+float: 2
+ifloat: 2
+Test "j0 (4.0) == -3.9714980986384737228659076845169804197562E-1":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 2
+ldouble: 2
+Test "j0 (8.0) == 0.171650807137553906090869407851972001":
+float: 1
+ifloat: 1
+
+# j1
+Test "j1 (10.0) == 0.0434727461688614366697487680258592883":
+float: 2
+ifloat: 2
+ildouble: 1
+ldouble: 1
+Test "j1 (2.0) == 0.576724807756873387202448242269137087":
+double: 1
+idouble: 1
+Test "j1 (8.0) == 0.234636346853914624381276651590454612":
+double: 1
+idouble: 1
+
+# jn
+Test "jn (0, -4.0) == -3.9714980986384737228659076845169804197562E-1":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 2
+ldouble: 2
+Test "jn (0, 10.0) == -0.245935764451348335197760862485328754":
+double: 3
+float: 1
+idouble: 3
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "jn (0, 2.0) == 0.223890779141235668051827454649948626":
+float: 2
+ifloat: 2
+Test "jn (0, 4.0) == -3.9714980986384737228659076845169804197562E-1":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 2
+ldouble: 2
+Test "jn (0, 8.0) == 0.171650807137553906090869407851972001":
+float: 1
+ifloat: 1
+Test "jn (1, 10.0) == 0.0434727461688614366697487680258592883":
+float: 2
+ifloat: 2
+ildouble: 1
+ldouble: 1
+Test "jn (1, 2.0) == 0.576724807756873387202448242269137087":
+double: 1
+idouble: 1
+Test "jn (1, 8.0) == 0.234636346853914624381276651590454612":
+double: 1
+idouble: 1
+Test "jn (10, -1.0) == 0.263061512368745320699785368779050294e-9":
+ildouble: 1
+ldouble: 1
+Test "jn (10, 0.125) == 0.250543369809369890173993791865771547e-18":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "jn (10, 0.75) == 0.149621713117596814698712483621682835e-10":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 2
+ldouble: 2
+Test "jn (10, 1.0) == 0.263061512368745320699785368779050294e-9":
+ildouble: 1
+ldouble: 1
+Test "jn (10, 10.0) == 0.207486106633358857697278723518753428":
+float: 1
+ifloat: 1
+ildouble: 2
+ldouble: 2
+Test "jn (10, 2.0) == 0.251538628271673670963516093751820639e-6":
+float: 4
+ifloat: 4
+ildouble: 1
+ldouble: 1
+Test "jn (3, -1.0) == -0.0195633539826684059189053216217515083":
+ildouble: 1
+ldouble: 1
+Test "jn (3, 0.125) == 0.406503832554912875023029337653442868e-4":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "jn (3, 0.75) == 0.848438342327410884392755236884386804e-2":
+double: 1
+idouble: 1
+Test "jn (3, 1.0) == 0.0195633539826684059189053216217515083":
+ildouble: 1
+ldouble: 1
+Test "jn (3, 10.0) == 0.0583793793051868123429354784103409563":
+double: 3
+float: 2
+idouble: 3
+ifloat: 2
+ildouble: 1
+ldouble: 1
+Test "jn (3, 2.0) == 0.128943249474402051098793332969239835":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 1
+ldouble: 1
+
+# lgamma
+Test "lgamma (-0.5) == log(2*sqrt(pi))":
+ildouble: 1
+ldouble: 1
+Test "lgamma (0.7) == 0.260867246531666514385732417016759578":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "lgamma (1.2) == -0.853740900033158497197028392998854470e-1":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 1
+ldouble: 1
+
+# log
+Test "log (e) == 1":
+float: 1
+ifloat: 1
+
+# log10
+Test "log10 (e) == log10(e)":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+# sincos
+Test "sincos (0.80190127184058835, &sin_res, &cos_res) puts 0.69534156199418473 in cos_res":
+double: 1
+idouble: 1
+Test "sincos (M_PI_6l*2.0, &sin_res, &cos_res) puts 0.5 in cos_res":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "sincos (M_PI_6l*2.0, &sin_res, &cos_res) puts 0.86602540378443864676372317075293616 in sin_res":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "sincos (pi/2, &sin_res, &cos_res) puts 0 in cos_res":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+# tan
+Test "tan (pi/4) == 1":
+double: 1
+idouble: 1
+
+# tgamma
+Test "tgamma (-0.5) == -2 sqrt (pi)":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "tgamma (0.5) == sqrt (pi)":
+float: 1
+ifloat: 1
+Test "tgamma (0.7) == 1.29805533264755778568117117915281162":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+# y0
+Test "y0 (0.125) == -1.38968062514384052915582277745018693":
+ildouble: 1
+ldouble: 1
+Test "y0 (1.0) == 0.0882569642156769579829267660235151628":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "y0 (1.5) == 0.382448923797758843955068554978089862":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+Test "y0 (10.0) == 0.0556711672835993914244598774101900481":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "y0 (2.0) == 0.510375672649745119596606592727157873":
+double: 1
+idouble: 1
+Test "y0 (8.0) == 0.223521489387566220527323400498620359":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+# y1
+Test "y1 (0.125) == -5.19993611253477499595928744876579921":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+Test "y1 (10.0) == 0.249015424206953883923283474663222803":
+double: 3
+float: 1
+idouble: 3
+ifloat: 1
+Test "y1 (1.5) == -0.412308626973911295952829820633445323";
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "y1 (2.0) == -0.107032431540937546888370772277476637":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "y1 (8.0) == -0.158060461731247494255555266187483550":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+
+# yn
+Test "yn (0, 0.125) == -1.38968062514384052915582277745018693":
+ildouble: 1
+ldouble: 1
+Test "yn (0, 1.0) == 0.0882569642156769579829267660235151628":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "yn (0, 1.5) == 0.382448923797758843955068554978089862":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+Test "yn (0, 10.0) == 0.0556711672835993914244598774101900481":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "yn (0, 2.0) == 0.510375672649745119596606592727157873":
+double: 1
+idouble: 1
+Test "yn (0, 8.0) == 0.223521489387566220527323400498620359":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "yn (1, 0.125) == -5.19993611253477499595928744876579921":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+Test "yn (1, 10.0) == 0.249015424206953883923283474663222803":
+double: 3
+float: 1
+idouble: 3
+ifloat: 1
+Test "yn (1, 1.5) == -0.412308626973911295952829820633445323";
+float: 1
+ifloat: 1
+ldouble: 1
+ildouble: 1
+Test "yn (1, 2.0) == -0.107032431540937546888370772277476637":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "yn (1, 8.0) == -0.158060461731247494255555266187483550":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+Test "yn (10, 0.125) == -127057845771019398.252538486899753195":
+double: 1
+idouble: 1
+ildouble: 2
+ldouble: 2
+Test "yn (10, 0.75) == -2133501638.90573424452445412893839236":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+Test "yn (10, 1.0) == -121618014.278689189288130426667971145":
+float: 2
+ifloat: 2
+Test "yn (10, 10.0) == -0.359814152183402722051986577343560609":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+Test "yn (10, 2.0) == -129184.542208039282635913145923304214":
+double: 3
+float: 1
+idouble: 3
+ifloat: 1
+Test "yn (3, 0.125) == -2612.69757350066712600220955744091741":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+Test "yn (3, 0.75) == -12.9877176234475433186319774484809207":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "yn (3, 10.0) == -0.251362657183837329779204747654240998":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "yn (3, 2.0) == -1.12778377684042778608158395773179238":
+double: 1
+idouble: 1
+
+# Maximal error of functions:
+Function: Imaginary part of "cacos":
+float: 1
+ifloat: 1
+ildouble: 2
+ldouble: 2
+
+Function: Real part of "cacosh":
+double: 1
+float: 7
+idouble: 1
+ifloat: 7
+ildouble: 7
+ldouble: 7
+
+Function: Imaginary part of "cacosh":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "casin":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 2
+ldouble: 2
+
+Function: Imaginary part of "casin":
+float: 1
+ifloat: 1
+ildouble: 2
+ldouble: 2
+
+Function: Real part of "casinh":
+double: 5
+float: 1
+idouble: 5
+ifloat: 1
+ildouble: 5
+ldouble: 5
+
+Function: Imaginary part of "casinh":
+double: 3
+float: 6
+idouble: 3
+ifloat: 6
+ildouble: 5
+ldouble: 5
+
+Function: Imaginary part of "catan":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: Real part of "catanh":
+double: 4
+idouble: 4
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "ccos":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+
+Function: Imaginary part of "ccos":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "ccosh":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: Imaginary part of "ccosh":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "cexp":
+float: 1
+ifloat: 1
+
+Function: Imaginary part of "cexp":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "clog":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "clog10":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: Imaginary part of "clog10":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "cos":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "cpow":
+double: 2
+float: 5
+idouble: 2
+ifloat: 5
+ildouble: 6
+ldouble: 6
+
+Function: Imaginary part of "cpow":
+double: 2
+float: 3
+idouble: 2
+ifloat: 3
+ildouble: 4
+ldouble: 4
+
+Function: Real part of "csin":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: Imaginary part of "csin":
+float: 1
+ifloat: 1
+
+Function: Real part of "csinh":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: Imaginary part of "csinh":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 2
+ldouble: 2
+
+Function: Real part of "csqrt":
+float: 1
+ifloat: 1
+
+Function: Real part of "ctan":
+double: 1
+idouble: 1
+ildouble: 2
+ldouble: 2
+
+Function: Imaginary part of "ctan":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "ctanh":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+
+Function: Imaginary part of "ctanh":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 24
+ldouble: 24
+
+Function: "erf":
+double: 1
+idouble: 1
+
+Function: "erfc":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "exp10":
+double: 6
+float: 2
+idouble: 6
+ifloat: 2
+ildouble: 3
+ldouble: 3
+
+Function: "expm1":
+ildouble: 1
+ldouble: 1
+
+Function: "gamma":
+ildouble: 1
+ldouble: 1
+
+Function: "hypot":
+float: 1
+ifloat: 1
+
+Function: "j0":
+double: 3
+float: 2
+idouble: 3
+ifloat: 2
+ildouble: 2
+ldouble: 2
+
+Function: "j1":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 1
+ldouble: 1
+
+Function: "jn":
+double: 3
+float: 4
+idouble: 3
+ifloat: 4
+ildouble: 2
+ldouble: 2
+
+Function: "lgamma":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 1
+ldouble: 1
+
+Function: "log":
+float: 1
+ifloat: 1
+
+Function: "log10":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "sincos":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "tan":
+double: 1
+idouble: 1
+
+Function: "tgamma":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "y0":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "y1":
+double: 3
+float: 2
+idouble: 3
+ifloat: 2
+ildouble: 1
+ldouble: 1
+
+Function: "yn":
+double: 3
+float: 2
+idouble: 3
+ifloat: 2
+ildouble: 2
+ldouble: 2
+
+# end of automatic generation
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/math/libm-test-ulps-powerpc b/l4/pkg/uclibc/lib/contrib/uclibc/test/math/libm-test-ulps-powerpc
new file mode 100644
index 00000000..8516e915
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/math/libm-test-ulps-powerpc
@@ -0,0 +1,1336 @@
+# Begin of automatic generation
+
+# acos
+Test "acos (2e-17) == 1.57079632679489659923132169163975144":
+ildouble: 1
+ldouble: 1
+
+# asin
+Test "asin (0.75) == 0.848062078981481008052944338998418080":
+ildouble: 2
+ldouble: 2
+
+# atan2
+Test "atan2 (-0.00756827042671106339, -.001792735857538728036) == -1.80338464113663849327153994379639112":
+ildouble: 1
+ldouble: 1
+Test "atan2 (-0.75, -1.0) == -2.49809154479650885165983415456218025":
+float: 1
+ifloat: 1
+Test "atan2 (0.75, -1.0) == 2.49809154479650885165983415456218025":
+float: 1
+ifloat: 1
+Test "atan2 (1.390625, 0.9296875) == 0.981498387184244311516296577615519772":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+# atanh
+Test "atanh (0.75) == 0.972955074527656652552676371721589865":
+float: 1
+ifloat: 1
+
+# cabs
+Test "cabs (0.75 + 1.25 i) == 1.45773797371132511771853821938639577":
+ildouble: 1
+ldouble: 1
+
+# cacosh
+Test "Real part of: cacosh (-2 - 3 i) == 1.9833870299165354323470769028940395 - 2.1414491111159960199416055713254211 i":
+double: 1
+float: 7
+idouble: 1
+ifloat: 7
+Test "Imaginary part of: cacosh (-2 - 3 i) == 1.9833870299165354323470769028940395 - 2.1414491111159960199416055713254211 i":
+double: 1
+float: 3
+idouble: 1
+ifloat: 3
+
+# casin
+Test "Real part of: casin (-2 - 3 i) == -0.57065278432109940071028387968566963 - 1.9833870299165354323470769028940395 i":
+ildouble: 1
+ldouble: 1
+Test "Real part of: casin (0.75 + 1.25 i) == 0.453276177638793913448921196101971749 + 1.13239363160530819522266333696834467 i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+# casinh
+Test "Real part of: casinh (-2 - 3 i) == -1.9686379257930962917886650952454982 - 0.96465850440760279204541105949953237 i":
+double: 5
+float: 1
+idouble: 5
+ifloat: 1
+ildouble: 4
+ldouble: 4
+Test "Imaginary part of: casinh (-2 - 3 i) == -1.9686379257930962917886650952454982 - 0.96465850440760279204541105949953237 i":
+double: 3
+float: 6
+idouble: 3
+ifloat: 6
+ildouble: 1
+ldouble: 1
+Test "Real part of: casinh (0.75 + 1.25 i) == 1.03171853444778027336364058631006594 + 0.911738290968487636358489564316731207 i":
+float: 1
+ifloat: 1
+Test "Imaginary part of: casinh (0.75 + 1.25 i) == 1.03171853444778027336364058631006594 + 0.911738290968487636358489564316731207 i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+# catan
+Test "Real part of: catan (-2 - 3 i) == -1.4099210495965755225306193844604208 - 0.22907268296853876629588180294200276 i":
+float: 3
+ifloat: 3
+ildouble: 1
+ldouble: 1
+Test "Imaginary part of: catan (-2 - 3 i) == -1.4099210495965755225306193844604208 - 0.22907268296853876629588180294200276 i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Real part of: catan (0.75 + 1.25 i) == 1.10714871779409050301706546017853704 + 0.549306144334054845697622618461262852 i":
+float: 4
+ifloat: 4
+
+# catanh
+Test "Real part of: catanh (-2 - 3 i) == -0.14694666622552975204743278515471595 - 1.3389725222944935611241935759091443 i":
+double: 4
+idouble: 4
+Test "Imaginary part of: catanh (-2 - 3 i) == -0.14694666622552975204743278515471595 - 1.3389725222944935611241935759091443 i":
+float: 4
+ifloat: 4
+Test "Real part of: catanh (0.75 + 1.25 i) == 0.261492138795671927078652057366532140 + 0.996825126463918666098902241310446708 i":
+double: 1
+idouble: 1
+Test "Imaginary part of: catanh (0.75 + 1.25 i) == 0.261492138795671927078652057366532140 + 0.996825126463918666098902241310446708 i":
+float: 6
+ifloat: 6
+
+# cbrt
+Test "cbrt (-27.0) == -3.0":
+double: 1
+idouble: 1
+Test "cbrt (0.9921875) == 0.997389022060725270579075195353955217":
+double: 1
+idouble: 1
+
+# ccos
+Test "Imaginary part of: ccos (-2 - 3 i) == -4.18962569096880723013255501961597373 - 9.10922789375533659797919726277886212 i":
+float: 1
+ifloat: 1
+Test "Real part of: ccos (0.75 + 1.25 i) == 1.38173873063425888530729933139078645 - 1.09193013555397466170919531722024128 i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: ccos (0.75 + 1.25 i) == 1.38173873063425888530729933139078645 - 1.09193013555397466170919531722024128 i":
+float: 1
+ifloat: 1
+
+# ccosh
+Test "Real part of: ccosh (-2 - 3 i) == -3.72454550491532256547397070325597253 + 0.511822569987384608834463849801875634 i":
+float: 1
+ifloat: 1
+Test "Imaginary part of: ccosh (-2 - 3 i) == -3.72454550491532256547397070325597253 + 0.511822569987384608834463849801875634 i":
+float: 1
+ifloat: 1
+Test "Real part of: ccosh (0.75 + 1.25 i) == 0.408242591877968807788852146397499084 + 0.780365930845853240391326216300863152 i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "Imaginary part of: ccosh (0.75 + 1.25 i) == 0.408242591877968807788852146397499084 + 0.780365930845853240391326216300863152 i":
+float: 1
+ifloat: 1
+ildouble: 2
+ldouble: 2
+
+# cexp
+Test "Imaginary part of: cexp (-2.0 - 3.0 i) == -0.13398091492954261346140525546115575 - 0.019098516261135196432576240858800925 i":
+float: 1
+ifloat: 1
+Test "Real part of: cexp (0.75 + 1.25 i) == 0.667537446429131586942201977015932112 + 2.00900045494094876258347228145863909 i":
+float: 1
+ifloat: 1
+ildouble: 2
+ldouble: 2
+Test "Imaginary part of: cexp (0.75 + 1.25 i) == 0.667537446429131586942201977015932112 + 2.00900045494094876258347228145863909 i":
+ildouble: 1
+ldouble: 1
+
+# clog
+Test "Imaginary part of: clog (-2 - 3 i) == 1.2824746787307683680267437207826593 - 2.1587989303424641704769327722648368 i":
+float: 3
+ifloat: 3
+ildouble: 1
+ldouble: 1
+Test "Real part of: clog (0.75 + 1.25 i) == 0.376885901188190075998919126749298416 + 1.03037682652431246378774332703115153 i":
+float: 1
+ifloat: 1
+ildouble: 2
+ldouble: 2
+Test "Imaginary part of: clog (0.75 + 1.25 i) == 0.376885901188190075998919126749298416 + 1.03037682652431246378774332703115153 i":
+ildouble: 1
+ldouble: 1
+
+# clog10
+Test "Imaginary part of: clog10 (-0 + inf i) == inf + pi/2*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "Imaginary part of: clog10 (-0 - inf i) == inf - pi/2*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "Imaginary part of: clog10 (-2 - 3 i) == 0.556971676153418384603252578971164214 - 0.937554462986374708541507952140189646 i":
+double: 1
+float: 5
+idouble: 1
+ifloat: 5
+ildouble: 1
+ldouble: 1
+Test "Imaginary part of: clog10 (-3 + inf i) == inf + pi/2*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "Imaginary part of: clog10 (-3 - inf i) == inf - pi/2*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "Imaginary part of: clog10 (-inf + 0 i) == inf + pi*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "Imaginary part of: clog10 (-inf + 1 i) == inf + pi*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "Imaginary part of: clog10 (-inf + inf i) == inf + 3/4 pi*log10(e) i":
+double: 1
+idouble: 1
+Test "Imaginary part of: clog10 (-inf - 0 i) == inf - pi*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "Imaginary part of: clog10 (-inf - 1 i) == inf - pi*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "Imaginary part of: clog10 (0 + inf i) == inf + pi/2*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "Imaginary part of: clog10 (0 - inf i) == inf - pi/2*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "Real part of: clog10 (0.75 + 1.25 i) == 0.163679467193165171449476605077428975 + 0.447486970040493067069984724340855636 i":
+float: 1
+ifloat: 1
+ildouble: 3
+ldouble: 3
+Test "Imaginary part of: clog10 (3 + inf i) == inf + pi/2*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "Imaginary part of: clog10 (3 - inf i) == inf - pi/2*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "Imaginary part of: clog10 (inf + inf i) == inf + pi/4*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "Imaginary part of: clog10 (inf - inf i) == inf - pi/4*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+# cos
+Test "cos (M_PI_6l * 2.0) == 0.5":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "cos (M_PI_6l * 4.0) == -0.5":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+Test "cos (pi/2) == 0":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "cos (16.0) == -0.9576594803233846418996372326511034717803"
+ildouble: 2
+ldouble: 2
+
+# cpow
+Test "Real part of: cpow (0.75 + 1.25 i, 0.0 + 1.0 i) == 0.331825439177608832276067945276730566 + 0.131338600281188544930936345230903032 i":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "Imaginary part of: cpow (0.75 + 1.25 i, 0.0 + 1.0 i) == 0.331825439177608832276067945276730566 + 0.131338600281188544930936345230903032 i":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "Real part of: cpow (0.75 + 1.25 i, 0.75 + 1.25 i) == 0.117506293914473555420279832210420483 + 0.346552747708338676483025352060418001 i":
+double: 1
+float: 4
+idouble: 1
+ifloat: 4
+Test "Real part of: cpow (0.75 + 1.25 i, 1.0 + 0.0 i) == 0.75 + 1.25 i":
+ildouble: 2
+ldouble: 2
+Test "Real part of: cpow (0.75 + 1.25 i, 1.0 + 1.0 i) == 0.0846958290317209430433805274189191353 + 0.513285749182902449043287190519090481 i":
+double: 2
+float: 3
+idouble: 2
+ifloat: 3
+Test "Real part of: cpow (2 + 0 i, 10 + 0 i) == 1024.0 + 0.0 i":
+ildouble: 1
+ldouble: 1
+Test "Real part of: cpow (2 + 3 i, 4 + 0 i) == -119.0 - 120.0 i":
+double: 1
+float: 5
+idouble: 1
+ifloat: 5
+Test "Imaginary part of: cpow (2 + 3 i, 4 + 0 i) == -119.0 - 120.0 i":
+float: 2
+ifloat: 2
+ildouble: 2
+ldouble: 2
+Test "Imaginary part of: cpow (e + 0 i, 0 + 2 * M_PIl i) == 1.0 + 0.0 i":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+ildouble: 2
+ldouble: 2
+
+# csinh
+Test "Imaginary part of: csinh (-2 - 3 i) == 3.59056458998577995201256544779481679 - 0.530921086248519805267040090660676560 i":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+Test "Real part of: csinh (0.75 + 1.25 i) == 0.259294854551162779153349830618433028 + 1.22863452409509552219214606515777594 i":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "Imaginary part of: csinh (0.75 + 1.25 i) == 0.259294854551162779153349830618433028 + 1.22863452409509552219214606515777594 i":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+# csqrt
+Test "Real part of: csqrt (-2 + 3 i) == 0.89597747612983812471573375529004348 + 1.6741492280355400404480393008490519 i":
+float: 1
+ifloat: 1
+Test "Real part of: csqrt (-2 - 3 i) == 0.89597747612983812471573375529004348 - 1.6741492280355400404480393008490519 i":
+float: 1
+ifloat: 1
+
+# ctan
+Test "Real part of: ctan (-2 - 3 i) == 0.376402564150424829275122113032269084e-2 - 1.00323862735360980144635859782192726 i":
+double: 1
+idouble: 1
+Test "Imaginary part of: ctan (-2 - 3 i) == 0.376402564150424829275122113032269084e-2 - 1.00323862735360980144635859782192726 i":
+ildouble: 1
+ldouble: 1
+Test "Imaginary part of: ctan (0.75 + 1.25 i) == 0.160807785916206426725166058173438663 + 0.975363285031235646193581759755216379 i":
+double: 1
+idouble: 1
+
+# ctanh
+Test "Real part of: ctanh (-2 - 3 i) == -0.965385879022133124278480269394560686 + 0.988437503832249372031403430350121098e-2 i":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+Test "Imaginary part of: ctanh (0 + pi/4 i) == 0.0 + 1.0 i":
+float: 1
+ifloat: 1
+Test "Real part of: ctanh (0.75 + 1.25 i) == 1.37260757053378320258048606571226857 + 0.385795952609750664177596760720790220 i":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+
+# erf
+Test "erf (1.25) == 0.922900128256458230136523481197281140":
+double: 1
+idouble: 1
+
+# erfc
+Test "erfc (0.75) == 0.288844366346484868401062165408589223":
+float: 1
+ifloat: 1
+Test "erfc (2.0) == 0.00467773498104726583793074363274707139":
+double: 1
+idouble: 1
+Test "erfc (4.125) == 0.542340079956506600531223408575531062e-8":
+double: 1
+idouble: 1
+
+# exp
+Test "exp (0.75) == 2.11700001661267466854536981983709561":
+ildouble: 1
+ldouble: 1
+Test "exp (50.0) == 5184705528587072464087.45332293348538":
+ildouble: 1
+ldouble: 1
+
+# exp10
+Test "exp10 (-1) == 0.1":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "exp10 (0.75) == 5.62341325190349080394951039776481231":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "exp10 (3) == 1000":
+double: 6
+float: 2
+idouble: 6
+ifloat: 2
+ildouble: 8
+ldouble: 8
+
+# exp2
+Test "exp2 (10) == 1024":
+ildouble: 2
+ldouble: 2
+
+# expm1
+Test "expm1 (0.75) == 1.11700001661267466854536981983709561":
+double: 1
+idouble: 1
+Test "expm1 (1) == M_El - 1.0":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+# hypot
+Test "hypot (-0.7, -12.4) == 12.419742348374220601176836866763271":
+float: 1
+ifloat: 1
+Test "hypot (-0.7, 12.4) == 12.419742348374220601176836866763271":
+float: 1
+ifloat: 1
+Test "hypot (-12.4, -0.7) == 12.419742348374220601176836866763271":
+float: 1
+ifloat: 1
+Test "hypot (-12.4, 0.7) == 12.419742348374220601176836866763271":
+float: 1
+ifloat: 1
+Test "hypot (0.7, -12.4) == 12.419742348374220601176836866763271":
+float: 1
+ifloat: 1
+Test "hypot (0.7, 12.4) == 12.419742348374220601176836866763271":
+float: 1
+ifloat: 1
+Test "hypot (0.75, 1.25) == 1.45773797371132511771853821938639577":
+ildouble: 1
+ldouble: 1
+Test "hypot (12.4, -0.7) == 12.419742348374220601176836866763271":
+float: 1
+ifloat: 1
+Test "hypot (12.4, 0.7) == 12.419742348374220601176836866763271":
+float: 1
+ifloat: 1
+
+# j0
+Test "j0 (-4.0) == -3.9714980986384737228659076845169804197562E-1":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 1
+ldouble: 1
+Test "j0 (10.0) == -0.245935764451348335197760862485328754":
+double: 3
+float: 1
+idouble: 3
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "j0 (2.0) == 0.223890779141235668051827454649948626":
+float: 2
+ifloat: 2
+Test "j0 (4.0) == -3.9714980986384737228659076845169804197562E-1":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 1
+ldouble: 1
+Test "j0 (8.0) == 0.171650807137553906090869407851972001":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+# j1
+Test "j1 (10.0) == 0.0434727461688614366697487680258592883":
+float: 2
+ifloat: 2
+ildouble: 1
+ldouble: 1
+Test "j1 (2.0) == 0.576724807756873387202448242269137087":
+double: 1
+idouble: 1
+Test "j1 (8.0) == 0.234636346853914624381276651590454612":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+
+# jn
+Test "jn (0, -4.0) == -3.9714980986384737228659076845169804197562E-1":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 1
+ldouble: 1
+Test "jn (0, 10.0) == -0.245935764451348335197760862485328754":
+double: 3
+float: 1
+idouble: 3
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "jn (0, 2.0) == 0.223890779141235668051827454649948626":
+float: 2
+ifloat: 2
+Test "jn (0, 4.0) == -3.9714980986384737228659076845169804197562E-1":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 1
+ldouble: 1
+Test "jn (0, 8.0) == 0.171650807137553906090869407851972001":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "jn (1, 10.0) == 0.0434727461688614366697487680258592883":
+float: 2
+ifloat: 2
+ildouble: 1
+ldouble: 1
+Test "jn (1, 2.0) == 0.576724807756873387202448242269137087":
+double: 1
+idouble: 1
+Test "jn (1, 8.0) == 0.234636346853914624381276651590454612":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+Test "jn (10, -1.0) == 0.263061512368745320699785368779050294e-9":
+ildouble: 1
+ldouble: 1
+Test "jn (10, 0.125) == 0.250543369809369890173993791865771547e-18":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "jn (10, 0.75) == 0.149621713117596814698712483621682835e-10":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "jn (10, 1.0) == 0.263061512368745320699785368779050294e-9":
+ildouble: 1
+ldouble: 1
+Test "jn (10, 10.0) == 0.207486106633358857697278723518753428":
+float: 1
+ifloat: 1
+ildouble: 4
+ldouble: 4
+Test "jn (10, 2.0) == 0.251538628271673670963516093751820639e-6":
+float: 4
+ifloat: 4
+Test "jn (3, -1.0) == -0.0195633539826684059189053216217515083":
+ildouble: 1
+ldouble: 1
+Test "jn (3, 0.125) == 0.406503832554912875023029337653442868e-4":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "jn (3, 0.75) == 0.848438342327410884392755236884386804e-2":
+double: 1
+idouble: 1
+Test "jn (3, 1.0) == 0.0195633539826684059189053216217515083":
+ildouble: 1
+ldouble: 1
+Test "jn (3, 10.0) == 0.0583793793051868123429354784103409563":
+double: 3
+float: 2
+idouble: 3
+ifloat: 2
+ildouble: 2
+ldouble: 2
+Test "jn (3, 2.0) == 0.128943249474402051098793332969239835":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 2
+ldouble: 2
+
+# lgamma
+Test "lgamma (0.7) == 0.260867246531666514385732417016759578":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "lgamma (1.2) == -0.853740900033158497197028392998854470e-1":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 3
+ldouble: 3
+
+# log10
+Test "log10 (0.75) == -0.124938736608299953132449886193870744":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+Test "log10 (e) == log10(e)":
+float: 1
+ifloat: 1
+
+# log1p
+Test "log1p (-0.25) == -0.287682072451780927439219005993827432":
+float: 1
+ifloat: 1
+
+# log2
+Test "log2 (e) == M_LOG2El":
+ildouble: 1
+ldouble: 1
+
+# sin
+Test "sin (16.0) == -0.2879033166650652947844562482186175296207"
+ildouble: 2
+ldouble: 2
+
+# sincos
+Test "sincos (M_PI_6l*2.0, &sin_res, &cos_res) puts 0.5 in cos_res":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "sincos (M_PI_6l*2.0, &sin_res, &cos_res) puts 0.86602540378443864676372317075293616 in sin_res":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "sincos (pi/2, &sin_res, &cos_res) puts 0 in cos_res":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "sincos (pi/6, &sin_res, &cos_res) puts 0.86602540378443864676372317075293616 in cos_res":
+float: 1
+ifloat: 1
+
+# sinh
+Test "sinh (0.75) == 0.822316731935829980703661634446913849":
+ildouble: 1
+ldouble: 1
+
+# tan
+Test "tan (pi/4) == 1":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+
+# tanh
+Test "tanh (-0.75) == -0.635148952387287319214434357312496495":
+ildouble: 1
+ldouble: 1
+Test "tanh (0.75) == 0.635148952387287319214434357312496495":
+ildouble: 1
+ldouble: 1
+
+# tgamma
+Test "tgamma (-0.5) == -2 sqrt (pi)":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "tgamma (0.5) == sqrt (pi)":
+float: 1
+ifloat: 1
+Test "tgamma (0.7) == 1.29805533264755778568117117915281162":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+# y0
+Test "y0 (0.125) == -1.38968062514384052915582277745018693":
+ildouble: 1
+ldouble: 1
+Test "y0 (0.75) == -0.137172769385772397522814379396581855":
+ildouble: 1
+ldouble: 1
+Test "y0 (1.0) == 0.0882569642156769579829267660235151628":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "y0 (1.5) == 0.382448923797758843955068554978089862":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+Test "y0 (10.0) == 0.0556711672835993914244598774101900481":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "y0 (2.0) == 0.510375672649745119596606592727157873":
+double: 1
+idouble: 1
+Test "y0 (8.0) == 0.223521489387566220527323400498620359":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+# y1
+Test "y1 (0.125) == -5.19993611253477499595928744876579921":
+double: 1
+idouble: 1
+Test "y1 (1.5) == -0.412308626973911295952829820633445323":
+float: 1
+ifloat: 1
+Test "y1 (10.0) == 0.249015424206953883923283474663222803":
+double: 3
+float: 1
+idouble: 3
+ifloat: 1
+ildouble: 2
+ldouble: 2
+Test "y1 (2.0) == -0.107032431540937546888370772277476637":
+double: 1
+float: 1
+idouble: 2
+ifloat: 2
+Test "y1 (8.0) == -0.158060461731247494255555266187483550":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 2
+ldouble: 2
+
+# yn
+Test "yn (0, 0.125) == -1.38968062514384052915582277745018693":
+ildouble: 1
+ldouble: 1
+Test "yn (0, 0.75) == -0.137172769385772397522814379396581855":
+ildouble: 1
+ldouble: 1
+Test "yn (0, 1.0) == 0.0882569642156769579829267660235151628":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+ildouble: 2
+ldouble: 2
+Test "yn (0, 1.5) == 0.382448923797758843955068554978089862":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+Test "yn (0, 10.0) == 0.0556711672835993914244598774101900481":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 2
+ldouble: 2
+Test "yn (0, 2.0) == 0.510375672649745119596606592727157873":
+double: 1
+idouble: 1
+Test "yn (0, 8.0) == 0.223521489387566220527323400498620359":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 2
+ldouble: 2
+Test "yn (1, 0.125) == -5.19993611253477499595928744876579921":
+double: 1
+idouble: 1
+Test "yn (1, 1.5) == -0.412308626973911295952829820633445323":
+float: 2
+ifloat: 2
+Test "yn (1, 10.0) == 0.249015424206953883923283474663222803":
+double: 3
+float: 1
+idouble: 3
+ifloat: 1
+ildouble: 2
+ldouble: 2
+Test "yn (1, 2.0) == -0.107032431540937546888370772277476637":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "yn (1, 8.0) == -0.158060461731247494255555266187483550":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 2
+ldouble: 2
+Test "yn (3, 0.125) == -2612.69757350066712600220955744091741":
+double: 1
+idouble: 1
+Test "yn (10, 0.125) == -127057845771019398.252538486899753195":
+double: 1
+idouble: 1
+Test "yn (10, 0.75) == -2133501638.90573424452445412893839236":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+Test "yn (10, 1.0) == -121618014.278689189288130426667971145":
+float: 2
+ifloat: 2
+Test "yn (10, 10.0) == -0.359814152183402722051986577343560609":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+ildouble: 2
+ldouble: 2
+Test "yn (10, 2.0) == -129184.542208039282635913145923304214":
+double: 3
+float: 1
+idouble: 3
+ifloat: 1
+ildouble: 2
+ldouble: 2
+Test "yn (3, 0.125) == -2612.69757350066712600220955744091741":
+double: 1
+idouble: 1
+Test "yn (3, 0.75) == -12.9877176234475433186319774484809207":
+float: 1
+ifloat: 1
+Test "yn (3, 10.0) == -0.251362657183837329779204747654240998":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 2
+ldouble: 2
+Test "yn (3, 2.0) == -1.12778377684042778608158395773179238":
+double: 1
+idouble: 1
+
+# Maximal error of functions:
+Function: "acos":
+ildouble: 1
+ldouble: 1
+
+Function: "acosh":
+ildouble: 1
+ldouble: 1
+
+Function: "asin":
+ildouble: 2
+ldouble: 2
+
+Function: "asinh":
+ildouble: 1
+ldouble: 1
+
+Function: "atan2":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "atanh":
+float: 1
+ifloat: 1
+
+Function: "cabs":
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "cacos":
+ildouble: 1
+ldouble: 1
+
+Function: Imaginary part of "cacos":
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "cacosh":
+double: 1
+float: 7
+idouble: 1
+ifloat: 7
+ildouble: 1
+ldouble: 1
+
+Function: Imaginary part of "cacosh":
+double: 1
+float: 3
+idouble: 1
+ifloat: 3
+
+Function: Real part of "casin":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: Imaginary part of "casin":
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "casinh":
+double: 5
+float: 1
+idouble: 5
+ifloat: 1
+ildouble: 4
+ldouble: 4
+
+Function: Imaginary part of "casinh":
+double: 3
+float: 6
+idouble: 3
+ifloat: 6
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "catan":
+float: 4
+ifloat: 4
+ildouble: 1
+ldouble: 1
+
+Function: Imaginary part of "catan":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "catanh":
+double: 4
+idouble: 4
+
+Function: Imaginary part of "catanh":
+float: 6
+ifloat: 6
+
+Function: "cbrt":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "ccos":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: Imaginary part of "ccos":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "ccosh":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: Imaginary part of "ccosh":
+float: 1
+ifloat: 1
+ildouble: 2
+ldouble: 2
+
+Function: Real part of "cexp":
+float: 1
+ifloat: 1
+ildouble: 2
+ldouble: 2
+
+Function: Imaginary part of "cexp":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "clog":
+float: 1
+ifloat: 1
+ildouble: 2
+ldouble: 2
+
+Function: Imaginary part of "clog":
+float: 3
+ifloat: 3
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "clog10":
+float: 1
+ifloat: 1
+ildouble: 3
+ldouble: 3
+
+Function: Imaginary part of "clog10":
+double: 1
+float: 5
+idouble: 1
+ifloat: 5
+ildouble: 1
+ldouble: 1
+
+Function: "cos":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "cosh":
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "cpow":
+double: 2
+float: 5
+idouble: 2
+ifloat: 5
+ildouble: 2
+ldouble: 2
+
+Function: Imaginary part of "cpow":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+ildouble: 2
+ldouble: 2
+
+Function: Imaginary part of "cproj":
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "csin":
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "csinh":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: Imaginary part of "csinh":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "csqrt":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: Imaginary part of "csqrt":
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "ctan":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+
+Function: Imaginary part of "ctan":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "ctanh":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 1
+ldouble: 1
+
+Function: Imaginary part of "ctanh":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "erf":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+
+Function: "erfc":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "exp":
+ildouble: 1
+ldouble: 1
+
+Function: "exp10":
+double: 6
+float: 2
+idouble: 6
+ifloat: 2
+ildouble: 8
+ldouble: 8
+
+Function: "exp2":
+ildouble: 2
+ldouble: 2
+
+Function: "expm1":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: "gamma":
+ildouble: 1
+ldouble: 1
+
+Function: "hypot":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "j0":
+double: 3
+float: 2
+idouble: 3
+ifloat: 2
+ildouble: 1
+ldouble: 1
+
+Function: "j1":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 1
+ldouble: 1
+
+Function: "jn":
+double: 3
+float: 4
+idouble: 3
+ifloat: 4
+ildouble: 4
+ldouble: 4
+
+Function: "lgamma":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 3
+ldouble: 3
+
+Function: "log":
+ildouble: 1
+ldouble: 1
+
+Function: "log10":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 1
+ldouble: 1
+
+Function: "log1p":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "log2":
+ildouble: 1
+ldouble: 1
+
+Function: "pow":
+ildouble: 1
+ldouble: 1
+
+Function: "sin":
+ildouble: 1
+ldouble: 1
+
+Function: "sincos":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "sinh":
+ildouble: 1
+ldouble: 1
+
+Function: "tan":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+
+Function: "tanh":
+ildouble: 1
+ldouble: 1
+
+Function: "tgamma":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "y0":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "y1":
+double: 3
+float: 2
+idouble: 3
+ifloat: 2
+ildouble: 2
+ldouble: 2
+
+Function: "yn":
+double: 3
+float: 2
+idouble: 3
+ifloat: 2
+ildouble: 2
+ldouble: 2
+
+# end of automatic generation
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/math/libm-test-ulps-s390 b/l4/pkg/uclibc/lib/contrib/uclibc/test/math/libm-test-ulps-s390
new file mode 100644
index 00000000..989722e6
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/math/libm-test-ulps-s390
@@ -0,0 +1,1332 @@
+# Begin of automatic generation
+
+# atan2
+Test "atan2 (-0.00756827042671106339, -.001792735857538728036) == -1.80338464113663849327153994379639112":
+ildouble: 1
+ldouble: 1
+Test "atan2 (-0.75, -1.0) == -2.49809154479650885165983415456218025":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "atan2 (0.75, -1.0) == 2.49809154479650885165983415456218025":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "atan2 (1.390625, 0.9296875) == 0.981498387184244311516296577615519772":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+# atanh
+Test "atanh (0.75) == 0.972955074527656652552676371721589865":
+float: 1
+ifloat: 1
+
+# cacos
+Test "Imaginary part of: cacos (0.75 + 1.25 i) == 1.11752014915610270578240049553777969 - 1.13239363160530819522266333696834467 i":
+ildouble: 1
+ldouble: 1
+
+# cacosh
+Test "Real part of: cacosh (-2 - 3 i) == 1.9833870299165354323470769028940395 - 2.1414491111159960199416055713254211 i":
+double: 1
+float: 7
+idouble: 1
+ifloat: 7
+Test "Imaginary part of: cacosh (-2 - 3 i) == 1.9833870299165354323470769028940395 - 2.1414491111159960199416055713254211 i":
+double: 1
+float: 3
+idouble: 1
+ifloat: 3
+ildouble: 1
+ldouble: 1
+
+# casin
+Test "Real part of: casin (0.75 + 1.25 i) == 0.453276177638793913448921196101971749 + 1.13239363160530819522266333696834467 i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: casin (0.75 + 1.25 i) == 0.453276177638793913448921196101971749 + 1.13239363160530819522266333696834467 i":
+ildouble: 1
+ldouble: 1
+
+# casinh
+Test "Real part of: casinh (-2 - 3 i) == -1.9686379257930962917886650952454982 - 0.96465850440760279204541105949953237 i":
+double: 5
+float: 1
+idouble: 5
+ifloat: 1
+ildouble: 4
+ldouble: 4
+Test "Imaginary part of: casinh (-2 - 3 i) == -1.9686379257930962917886650952454982 - 0.96465850440760279204541105949953237 i":
+double: 3
+float: 6
+idouble: 3
+ifloat: 6
+ildouble: 2
+ldouble: 2
+Test "Real part of: casinh (0.75 + 1.25 i) == 1.03171853444778027336364058631006594 + 0.911738290968487636358489564316731207 i":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "Imaginary part of: casinh (0.75 + 1.25 i) == 1.03171853444778027336364058631006594 + 0.911738290968487636358489564316731207 i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+# catan
+Test "Real part of: catan (-2 - 3 i) == -1.4099210495965755225306193844604208 - 0.22907268296853876629588180294200276 i":
+float: 3
+ifloat: 3
+Test "Imaginary part of: catan (-2 - 3 i) == -1.4099210495965755225306193844604208 - 0.22907268296853876629588180294200276 i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Real part of: catan (0.75 + 1.25 i) == 1.10714871779409050301706546017853704 + 0.549306144334054845697622618461262852 i":
+float: 4
+ifloat: 4
+Test "Imaginary part of: catan (0.75 + 1.25 i) == 1.10714871779409050301706546017853704 + 0.549306144334054845697622618461262852 i":
+ildouble: 1
+ldouble: 1
+
+# catanh
+Test "Real part of: catanh (-2 - 3 i) == -0.14694666622552975204743278515471595 - 1.3389725222944935611241935759091443 i":
+double: 4
+idouble: 4
+Test "Imaginary part of: catanh (-2 - 3 i) == -0.14694666622552975204743278515471595 - 1.3389725222944935611241935759091443 i":
+float: 4
+ifloat: 4
+Test "Real part of: catanh (0.75 + 1.25 i) == 0.261492138795671927078652057366532140 + 0.996825126463918666098902241310446708 i":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+Test "Imaginary part of: catanh (0.75 + 1.25 i) == 0.261492138795671927078652057366532140 + 0.996825126463918666098902241310446708 i":
+float: 6
+ifloat: 6
+ildouble: 1
+ldouble: 1
+
+# cbrt
+Test "cbrt (-0.001) == -0.1":
+ildouble: 1
+ldouble: 1
+Test "cbrt (-27.0) == -3.0":
+double: 1
+idouble: 1
+Test "cbrt (0.75) == 0.908560296416069829445605878163630251":
+double: 1
+idouble: 1
+Test "cbrt (0.9921875) == 0.997389022060725270579075195353955217":
+double: 1
+idouble: 1
+
+# ccos
+Test "Real part of: ccos (-2 - 3 i) == -4.18962569096880723013255501961597373 - 9.10922789375533659797919726277886212 i":
+ildouble: 1
+ldouble: 1
+Test "Imaginary part of: ccos (-2 - 3 i) == -4.18962569096880723013255501961597373 - 9.10922789375533659797919726277886212 i":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "Real part of: ccos (0.75 + 1.25 i) == 1.38173873063425888530729933139078645 - 1.09193013555397466170919531722024128 i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: ccos (0.75 + 1.25 i) == 1.38173873063425888530729933139078645 - 1.09193013555397466170919531722024128 i":
+float: 1
+ifloat: 1
+
+# ccosh
+Test "Real part of: ccosh (-2 - 3 i) == -3.72454550491532256547397070325597253 + 0.511822569987384608834463849801875634 i":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "Imaginary part of: ccosh (-2 - 3 i) == -3.72454550491532256547397070325597253 + 0.511822569987384608834463849801875634 i":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "Real part of: ccosh (0.75 + 1.25 i) == 0.408242591877968807788852146397499084 + 0.780365930845853240391326216300863152 i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: ccosh (0.75 + 1.25 i) == 0.408242591877968807788852146397499084 + 0.780365930845853240391326216300863152 i":
+float: 1
+ifloat: 1
+
+# cexp
+Test "Real part of: cexp (-2.0 - 3.0 i) == -0.13398091492954261346140525546115575 - 0.019098516261135196432576240858800925 i":
+ildouble: 1
+ldouble: 1
+Test "Imaginary part of: cexp (-2.0 - 3.0 i) == -0.13398091492954261346140525546115575 - 0.019098516261135196432576240858800925 i":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "Real part of: cexp (0.75 + 1.25 i) == 0.667537446429131586942201977015932112 + 2.00900045494094876258347228145863909 i":
+float: 1
+ifloat: 1
+Test "Imaginary part of: cexp (0.75 + 1.25 i) == 0.667537446429131586942201977015932112 + 2.00900045494094876258347228145863909 i":
+ildouble: 1
+ldouble: 1
+
+# clog
+Test "Imaginary part of: clog (-2 - 3 i) == 1.2824746787307683680267437207826593 - 2.1587989303424641704769327722648368 i":
+float: 3
+ifloat: 3
+Test "Real part of: clog (0.75 + 1.25 i) == 0.376885901188190075998919126749298416 + 1.03037682652431246378774332703115153 i":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+# clog10
+Test "Imaginary part of: clog10 (-0 + inf i) == inf + pi/2*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (-0 - inf i) == inf - pi/2*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Real part of: clog10 (-2 - 3 i) == 0.556971676153418384603252578971164214 - 0.937554462986374708541507952140189646 i":
+ildouble: 1
+ldouble: 1
+Test "Imaginary part of: clog10 (-2 - 3 i) == 0.556971676153418384603252578971164214 - 0.937554462986374708541507952140189646 i":
+double: 1
+float: 5
+idouble: 1
+ifloat: 5
+ildouble: 1
+ldouble: 1
+Test "Imaginary part of: clog10 (-3 + inf i) == inf + pi/2*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (-3 - inf i) == inf - pi/2*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (-inf + 0 i) == inf + pi*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (-inf + 1 i) == inf + pi*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (-inf + inf i) == inf + 3/4 pi*log10(e) i":
+double: 1
+idouble: 1
+Test "Imaginary part of: clog10 (-inf - 0 i) == inf - pi*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (-inf - 1 i) == inf - pi*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (0 + inf i) == inf + pi/2*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (0 - inf i) == inf - pi/2*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Real part of: clog10 (0.75 + 1.25 i) == 0.163679467193165171449476605077428975 + 0.447486970040493067069984724340855636 i":
+float: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (0.75 + 1.25 i) == 0.163679467193165171449476605077428975 + 0.447486970040493067069984724340855636 i":
+ildouble: 1
+ldouble: 1
+Test "Imaginary part of: clog10 (3 + inf i) == inf + pi/2*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (3 - inf i) == inf - pi/2*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (inf + inf i) == inf + pi/4*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (inf - inf i) == inf - pi/4*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+# cos
+Test "cos (M_PI_6l * 2.0) == 0.5":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "cos (M_PI_6l * 4.0) == -0.5":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "cos (pi/2) == 0":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+# cpow
+Test "Real part of: cpow (0.75 + 1.25 i, 0.0 + 1.0 i) == 0.331825439177608832276067945276730566 + 0.131338600281188544930936345230903032 i":
+float: 1
+ifloat: 1
+Test "Imaginary part of: cpow (0.75 + 1.25 i, 0.0 + 1.0 i) == 0.331825439177608832276067945276730566 + 0.131338600281188544930936345230903032 i":
+float: 1
+ifloat: 1
+Test "Real part of: cpow (0.75 + 1.25 i, 0.75 + 1.25 i) == 0.117506293914473555420279832210420483 + 0.346552747708338676483025352060418001 i":
+double: 1
+float: 4
+idouble: 1
+ifloat: 4
+ildouble: 4
+ldouble: 4
+Test "Real part of: cpow (0.75 + 1.25 i, 1.0 + 0.0 i) == 0.75 + 1.25 i":
+ildouble: 2
+ldouble: 2
+Test "Imaginary part of: cpow (0.75 + 1.25 i, 1.0 + 0.0 i) == 0.75 + 1.25 i":
+ildouble: 1
+ldouble: 1
+Test "Real part of: cpow (0.75 + 1.25 i, 1.0 + 1.0 i) == 0.0846958290317209430433805274189191353 + 0.513285749182902449043287190519090481 i":
+double: 2
+float: 3
+idouble: 2
+ifloat: 3
+ildouble: 10
+ldouble: 10
+Test "Real part of: cpow (2 + 0 i, 10 + 0 i) == 1024.0 + 0.0 i":
+ildouble: 2
+ldouble: 2
+Test "Real part of: cpow (2 + 3 i, 4 + 0 i) == -119.0 - 120.0 i":
+double: 1
+float: 4
+idouble: 1
+ifloat: 4
+ildouble: 3
+ldouble: 3
+Test "Imaginary part of: cpow (2 + 3 i, 4 + 0 i) == -119.0 - 120.0 i":
+float: 2
+ifloat: 2
+Test "Imaginary part of: cpow (e + 0 i, 0 + 2 * M_PIl i) == 1.0 + 0.0 i":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+ildouble: 1
+ldouble: 1
+
+# csin
+Test "Imaginary part of: csin (-2 - 3 i) == -9.15449914691142957346729954460983256 + 4.16890695996656435075481305885375484 i":
+ildouble: 1
+ldouble: 1
+Test "Real part of: csin (0.75 + 1.25 i) == 1.28722291002649188575873510790565441 + 1.17210635989270256101081285116138863 i":
+ildouble: 1
+ldouble: 1
+
+# csinh
+Test "Real part of: csinh (-2 - 3 i) == 3.59056458998577995201256544779481679 - 0.530921086248519805267040090660676560 i":
+ildouble: 1
+ldouble: 1
+Test "Imaginary part of: csinh (-2 - 3 i) == 3.59056458998577995201256544779481679 - 0.530921086248519805267040090660676560 i":
+double: 1
+idouble: 1
+Test "Real part of: csinh (0.75 + 1.25 i) == 0.259294854551162779153349830618433028 + 1.22863452409509552219214606515777594 i":
+float: 1
+ifloat: 1
+Test "Imaginary part of: csinh (0.75 + 1.25 i) == 0.259294854551162779153349830618433028 + 1.22863452409509552219214606515777594 i":
+float: 1
+ifloat: 1
+
+# csqrt
+Test "Real part of: csqrt (-2 + 3 i) == 0.89597747612983812471573375529004348 + 1.6741492280355400404480393008490519 i":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "Real part of: csqrt (-2 - 3 i) == 0.89597747612983812471573375529004348 - 1.6741492280355400404480393008490519 i":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "Imaginary part of: csqrt (0.75 + 1.25 i) == 1.05065169626078392338656675760808326 + 0.594868882070379067881984030639932657 i":
+ildouble: 1
+ldouble: 1
+
+# ctan
+Test "Real part of: ctan (-2 - 3 i) == 0.376402564150424829275122113032269084e-2 - 1.00323862735360980144635859782192726 i":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+Test "Imaginary part of: ctan (-2 - 3 i) == 0.376402564150424829275122113032269084e-2 - 1.00323862735360980144635859782192726 i":
+ildouble: 1
+ldouble: 1
+Test "Imaginary part of: ctan (0.75 + 1.25 i) == 0.160807785916206426725166058173438663 + 0.975363285031235646193581759755216379 i":
+double: 1
+idouble: 1
+ildouble: 2
+ldouble: 2
+
+# ctanh
+Test "Real part of: ctanh (-2 - 3 i) == -0.965385879022133124278480269394560686 + 0.988437503832249372031403430350121098e-2 i":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 1
+ldouble: 1
+Test "Imaginary part of: ctanh (-2 - 3 i) == -0.965385879022133124278480269394560686 + 0.988437503832249372031403430350121098e-2 i":
+ildouble: 1
+ldouble: 1
+Test "Imaginary part of: ctanh (0 + pi/4 i) == 0.0 + 1.0 i":
+float: 1
+ifloat: 1
+Test "Real part of: ctanh (0.75 + 1.25 i) == 1.37260757053378320258048606571226857 + 0.385795952609750664177596760720790220 i":
+double: 1
+idouble: 1
+
+# erf
+Test "erf (1.25) == 0.922900128256458230136523481197281140":
+double: 1
+idouble: 1
+
+# erfc
+Test "erfc (0.75) == 0.288844366346484868401062165408589223":
+float: 1
+ifloat: 1
+Test "erfc (2.0) == 0.00467773498104726583793074363274707139":
+double: 1
+idouble: 1
+Test "erfc (27.0) == 0.523704892378925568501606768284954709e-318":
+ildouble: 1
+ldouble: 1
+Test "erfc (4.125) == 0.542340079956506600531223408575531062e-8":
+double: 1
+idouble: 1
+
+# exp10
+Test "exp10 (-1) == 0.1":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+Test "exp10 (0.75) == 5.62341325190349080394951039776481231":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "exp10 (3) == 1000":
+double: 6
+float: 2
+idouble: 6
+ifloat: 2
+ildouble: 1
+ldouble: 1
+
+# exp2
+Test "exp2 (10) == 1024":
+ildouble: 2
+ldouble: 2
+
+# expm1
+Test "expm1 (0.75) == 1.11700001661267466854536981983709561":
+double: 1
+idouble: 1
+Test "expm1 (1) == M_El - 1.0":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+# gamma
+Test "gamma (-0.5) == log(2*sqrt(pi))":
+ildouble: 1
+ldouble: 1
+
+# hypot
+Test "hypot (-0.7, -12.4) == 12.419742348374220601176836866763271":
+float: 1
+ifloat: 1
+Test "hypot (-0.7, 12.4) == 12.419742348374220601176836866763271":
+float: 1
+ifloat: 1
+Test "hypot (-12.4, -0.7) == 12.419742348374220601176836866763271":
+float: 1
+ifloat: 1
+Test "hypot (-12.4, 0.7) == 12.419742348374220601176836866763271":
+float: 1
+ifloat: 1
+Test "hypot (0.7, -12.4) == 12.419742348374220601176836866763271":
+float: 1
+ifloat: 1
+Test "hypot (0.7, 12.4) == 12.419742348374220601176836866763271":
+float: 1
+ifloat: 1
+Test "hypot (12.4, -0.7) == 12.419742348374220601176836866763271":
+float: 1
+ifloat: 1
+Test "hypot (12.4, 0.7) == 12.419742348374220601176836866763271":
+float: 1
+ifloat: 1
+
+# j0
+Test "j0 (-4.0) == -3.9714980986384737228659076845169804197562E-1":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+Test "j0 (0.75) == 0.864242275166648623555731103820923211":
+float: 1
+ifloat: 1
+Test "j0 (10.0) == -0.245935764451348335197760862485328754":
+double: 3
+float: 1
+idouble: 3
+ifloat: 1
+ildouble: 2
+ldouble: 2
+Test "j0 (2.0) == 0.223890779141235668051827454649948626":
+float: 2
+ifloat: 2
+ildouble: 2
+ldouble: 2
+Test "j0 (4.0) == -3.9714980986384737228659076845169804197562E-1":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+Test "j0 (8.0) == 0.171650807137553906090869407851972001":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+# j1
+Test "j1 (-1.0) == -0.440050585744933515959682203718914913":
+ildouble: 1
+ldouble: 1
+Test "j1 (0.75) == 0.349243602174862192523281016426251335":
+ildouble: 1
+ldouble: 1
+Test "j1 (1.0) == 0.440050585744933515959682203718914913":
+ildouble: 1
+ldouble: 1
+Test "j1 (10.0) == 0.0434727461688614366697487680258592883":
+float: 2
+ifloat: 2
+ildouble: 2
+ldouble: 2
+Test "j1 (2.0) == 0.576724807756873387202448242269137087":
+double: 1
+idouble: 1
+Test "j1 (8.0) == 0.234636346853914624381276651590454612":
+double: 1
+idouble: 1
+ildouble: 4
+ldouble: 4
+
+# jn
+Test "jn (0, -4.0) == -3.9714980986384737228659076845169804197562E-1":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+Test "jn (0, 0.75) == 0.864242275166648623555731103820923211":
+float: 1
+ifloat: 1
+Test "jn (0, 10.0) == -0.245935764451348335197760862485328754":
+double: 3
+float: 1
+idouble: 3
+ifloat: 1
+ildouble: 2
+ldouble: 2
+Test "jn (0, 2.0) == 0.223890779141235668051827454649948626":
+float: 2
+ifloat: 2
+ildouble: 2
+ldouble: 2
+Test "jn (0, 4.0) == -3.9714980986384737228659076845169804197562E-1":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+Test "jn (0, 8.0) == 0.171650807137553906090869407851972001":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "jn (1, -1.0) == -0.440050585744933515959682203718914913":
+ildouble: 1
+ldouble: 1
+Test "jn (1, 0.75) == 0.349243602174862192523281016426251335":
+ildouble: 1
+ldouble: 1
+Test "jn (1, 1.0) == 0.440050585744933515959682203718914913":
+ildouble: 1
+ldouble: 1
+Test "jn (1, 10.0) == 0.0434727461688614366697487680258592883":
+float: 2
+ifloat: 2
+ildouble: 2
+ldouble: 2
+Test "jn (1, 2.0) == 0.576724807756873387202448242269137087":
+double: 1
+idouble: 1
+Test "jn (1, 8.0) == 0.234636346853914624381276651590454612":
+double: 1
+idouble: 1
+ildouble: 4
+ldouble: 4
+Test "jn (10, -1.0) == 0.263061512368745320699785368779050294e-9":
+ildouble: 1
+ldouble: 1
+Test "jn (10, 0.125) == 0.250543369809369890173993791865771547e-18":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "jn (10, 0.75) == 0.149621713117596814698712483621682835e-10":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "jn (10, 1.0) == 0.263061512368745320699785368779050294e-9":
+ildouble: 1
+ldouble: 1
+Test "jn (10, 10.0) == 0.207486106633358857697278723518753428":
+double: 4
+float: 3
+idouble: 4
+ifloat: 3
+ildouble: 2
+ldouble: 2
+Test "jn (10, 2.0) == 0.251538628271673670963516093751820639e-6":
+float: 4
+ifloat: 4
+Test "jn (3, 0.125) == 0.406503832554912875023029337653442868e-4":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "jn (3, 0.75) == 0.848438342327410884392755236884386804e-2":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "jn (3, 10.0) == 0.0583793793051868123429354784103409563":
+double: 3
+float: 2
+idouble: 3
+ifloat: 2
+ildouble: 2
+ldouble: 2
+Test "jn (3, 2.0) == 0.128943249474402051098793332969239835":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+
+# lgamma
+Test "lgamma (-0.5) == log(2*sqrt(pi))":
+ildouble: 1
+ldouble: 1
+Test "lgamma (0.7) == 0.260867246531666514385732417016759578":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "lgamma (1.2) == -0.853740900033158497197028392998854470e-1":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 1
+ldouble: 1
+
+# log10
+Test "log10 (0.75) == -0.124938736608299953132449886193870744":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+Test "log10 (e) == log10(e)":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+# log1p
+Test "log1p (-0.25) == -0.287682072451780927439219005993827432":
+float: 1
+ifloat: 1
+
+# log2
+Test "log2 (0.75) == -.415037499278843818546261056052183492":
+ildouble: 1
+ldouble: 1
+
+# sincos
+Test "sincos (M_PI_6l*2.0, &sin_res, &cos_res) puts 0.5 in cos_res":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "sincos (M_PI_6l*2.0, &sin_res, &cos_res) puts 0.86602540378443864676372317075293616 in sin_res":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "sincos (pi/2, &sin_res, &cos_res) puts 0 in cos_res":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "sincos (pi/6, &sin_res, &cos_res) puts 0.86602540378443864676372317075293616 in cos_res":
+float: 1
+ifloat: 1
+
+# sqrt
+Test "sqrt (2) == M_SQRT2l":
+ildouble: 1
+ldouble: 1
+
+# tan
+Test "tan (pi/4) == 1":
+double: 1
+idouble: 1
+
+# tanh
+Test "tanh (-0.75) == -0.635148952387287319214434357312496495":
+ildouble: 1
+ldouble: 1
+Test "tanh (-1.0) == -0.7615941559557648881194582826047935904":
+ildouble: 1
+ldouble: 1
+Test "tanh (0.75) == 0.635148952387287319214434357312496495":
+ildouble: 1
+ldouble: 1
+Test "tanh (1.0) == 0.7615941559557648881194582826047935904":
+ildouble: 1
+ldouble: 1
+
+# tgamma
+Test "tgamma (-0.5) == -2 sqrt (pi)":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "tgamma (0.5) == sqrt (pi)":
+float: 1
+ifloat: 1
+Test "tgamma (0.7) == 1.29805533264755778568117117915281162":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "tgamma (4) == 6":
+ildouble: 1
+ldouble: 1
+
+# y0
+Test "y0 (1.0) == 0.0882569642156769579829267660235151628":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+Test "y0 (1.5) == 0.382448923797758843955068554978089862":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+Test "y0 (10.0) == 0.0556711672835993914244598774101900481":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 3
+ldouble: 3
+Test "y0 (2.0) == 0.510375672649745119596606592727157873":
+double: 1
+idouble: 1
+Test "y0 (8.0) == 0.223521489387566220527323400498620359":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 3
+ldouble: 3
+
+# y1
+Test "y1 (0.125) == -5.19993611253477499595928744876579921":
+double: 1
+idouble: 1
+Test "y1 (0.75) == -1.03759455076928541973767132140642198":
+ildouble: 1
+ldouble: 1
+Test "y1 (1.5) == -0.412308626973911295952829820633445323":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "y1 (10.0) == 0.249015424206953883923283474663222803":
+double: 3
+float: 1
+idouble: 3
+ifloat: 1
+Test "y1 (2.0) == -0.107032431540937546888370772277476637":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "y1 (8.0) == -0.158060461731247494255555266187483550":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 1
+ldouble: 1
+
+# yn
+Test "yn (0, 1.0) == 0.0882569642156769579829267660235151628":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+Test "yn (0, 1.5) == 0.382448923797758843955068554978089862":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+Test "yn (0, 10.0) == 0.0556711672835993914244598774101900481":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 3
+ldouble: 3
+Test "yn (0, 2.0) == 0.510375672649745119596606592727157873":
+double: 1
+idouble: 1
+Test "yn (0, 8.0) == 0.223521489387566220527323400498620359":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 3
+ldouble: 3
+Test "yn (1, 0.125) == -5.19993611253477499595928744876579921":
+double: 1
+idouble: 1
+Test "yn (1, 0.75) == -1.03759455076928541973767132140642198":
+ildouble: 1
+ldouble: 1
+Test "yn (1, 1.5) == -0.412308626973911295952829820633445323":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "yn (1, 10.0) == 0.249015424206953883923283474663222803":
+double: 3
+float: 1
+idouble: 3
+ifloat: 1
+Test "yn (1, 2.0) == -0.107032431540937546888370772277476637":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "yn (1, 8.0) == -0.158060461731247494255555266187483550":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 1
+ldouble: 1
+Test "yn (10, 0.125) == -127057845771019398.252538486899753195":
+double: 1
+idouble: 1
+ildouble: 2
+ldouble: 2
+Test "yn (10, 0.75) == -2133501638.90573424452445412893839236":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 5
+ldouble: 5
+Test "yn (10, 1.0) == -121618014.278689189288130426667971145":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 1
+ldouble: 1
+Test "yn (10, 10.0) == -0.359814152183402722051986577343560609":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+ildouble: 2
+ldouble: 2
+Test "yn (10, 2.0) == -129184.542208039282635913145923304214":
+double: 3
+float: 1
+idouble: 3
+ifloat: 1
+ildouble: 2
+ldouble: 2
+Test "yn (3, 0.125) == -2612.69757350066712600220955744091741":
+double: 1
+idouble: 1
+Test "yn (3, 0.75) == -12.9877176234475433186319774484809207":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 2
+ldouble: 2
+Test "yn (3, 10.0) == -0.251362657183837329779204747654240998":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "yn (3, 2.0) == -1.12778377684042778608158395773179238":
+double: 1
+idouble: 1
+
+# Maximal error of functions:
+Function: "atan2":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "atanh":
+float: 1
+ifloat: 1
+
+Function: Imaginary part of "cacos":
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "cacosh":
+double: 1
+float: 7
+idouble: 1
+ifloat: 7
+
+Function: Imaginary part of "cacosh":
+double: 1
+float: 3
+idouble: 1
+ifloat: 3
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "casin":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: Imaginary part of "casin":
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "casinh":
+double: 5
+float: 1
+idouble: 5
+ifloat: 1
+ildouble: 4
+ldouble: 4
+
+Function: Imaginary part of "casinh":
+double: 3
+float: 6
+idouble: 3
+ifloat: 6
+ildouble: 2
+ldouble: 2
+
+Function: Real part of "catan":
+float: 4
+ifloat: 4
+
+Function: Imaginary part of "catan":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "catanh":
+double: 4
+idouble: 4
+ildouble: 1
+ldouble: 1
+
+Function: Imaginary part of "catanh":
+float: 6
+ifloat: 6
+ildouble: 1
+ldouble: 1
+
+Function: "cbrt":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "ccos":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: Imaginary part of "ccos":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "ccosh":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: Imaginary part of "ccosh":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "cexp":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: Imaginary part of "cexp":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "clog":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: Imaginary part of "clog":
+float: 3
+ifloat: 3
+
+Function: Real part of "clog10":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: Imaginary part of "clog10":
+double: 1
+float: 5
+idouble: 1
+ifloat: 5
+ildouble: 1
+ldouble: 1
+
+Function: "cos":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "cpow":
+double: 2
+float: 4
+idouble: 2
+ifloat: 4
+ildouble: 10
+ldouble: 10
+
+Function: Imaginary part of "cpow":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "csin":
+ildouble: 1
+ldouble: 1
+
+Function: Imaginary part of "csin":
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "csinh":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: Imaginary part of "csinh":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: Real part of "csqrt":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: Imaginary part of "csqrt":
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "ctan":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+
+Function: Imaginary part of "ctan":
+double: 1
+idouble: 1
+ildouble: 2
+ldouble: 2
+
+Function: Real part of "ctanh":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 1
+ldouble: 1
+
+Function: Imaginary part of "ctanh":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "erf":
+double: 1
+idouble: 1
+
+Function: "erfc":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "exp10":
+double: 6
+float: 2
+idouble: 6
+ifloat: 2
+ildouble: 1
+ldouble: 1
+
+Function: "exp2":
+ildouble: 2
+ldouble: 2
+
+Function: "expm1":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "gamma":
+ildouble: 1
+ldouble: 1
+
+Function: "hypot":
+float: 1
+ifloat: 1
+
+Function: "j0":
+double: 3
+float: 2
+idouble: 3
+ifloat: 2
+ildouble: 2
+ldouble: 2
+
+Function: "j1":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 4
+ldouble: 4
+
+Function: "jn":
+double: 4
+float: 4
+idouble: 4
+ifloat: 4
+ildouble: 4
+ldouble: 4
+
+Function: "lgamma":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 1
+ldouble: 1
+
+Function: "log10":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 1
+ldouble: 1
+
+Function: "log1p":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "log2":
+ildouble: 1
+ldouble: 1
+
+Function: "sincos":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "sqrt":
+ildouble: 1
+ldouble: 1
+
+Function: "tan":
+double: 1
+idouble: 1
+
+Function: "tanh":
+ildouble: 1
+ldouble: 1
+
+Function: "tgamma":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "y0":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+ildouble: 3
+ldouble: 3
+
+Function: "y1":
+double: 3
+float: 2
+idouble: 3
+ifloat: 2
+ildouble: 1
+ldouble: 1
+
+Function: "yn":
+double: 3
+float: 2
+idouble: 3
+ifloat: 2
+ildouble: 5
+ldouble: 5
+
+# end of automatic generation
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/math/libm-test-ulps-sh4 b/l4/pkg/uclibc/lib/contrib/uclibc/test/math/libm-test-ulps-sh4
new file mode 100644
index 00000000..4831f484
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/math/libm-test-ulps-sh4
@@ -0,0 +1,1094 @@
+# Begin of automatic generation
+
+# asin
+Test "asin (-0.5) == -pi/6":
+float: 2
+ifloat: 2
+Test "asin (0.5) == pi/6":
+float: 2
+ifloat: 2
+Test "asin (0.7) == 0.7753974966107530637":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+
+# atan2
+Test "atan2 (0.7, -1.0) == 2.530866689200584621918884506789267":
+float: 3
+ifloat: 3
+Test "atan2 (-0.7, -1.0) == -2.530866689200584621918884506789267":
+float: 3
+ifloat: 3
+Test "atan2 (1.4, -0.93) == 2.1571487668237843754887415992772736":
+float: 4
+ifloat: 4
+
+# atanh
+Test "atanh (0.7) == 0.8673005276940531944":
+double: 1
+idouble: 1
+
+# cabs
+Test "cabs (-0.7 + 12.4 i) == 12.419742348374220601176836866763271":
+float: 1
+ifloat: 1
+Test "cabs (-0.7 - 12.4 i) == 12.419742348374220601176836866763271":
+float: 1
+ifloat: 1
+Test "cabs (-12.4 + 0.7 i) == 12.419742348374220601176836866763271":
+float: 1
+ifloat: 1
+Test "cabs (-12.4 - 0.7 i) == 12.419742348374220601176836866763271":
+float: 1
+ifloat: 1
+Test "cabs (0.7 + 1.2 i) == 1.3892443989449804508432547041028554":
+double: 1
+idouble: 1
+Test "cabs (0.7 + 12.4 i) == 12.419742348374220601176836866763271":
+float: 1
+ifloat: 1
+
+# cacos
+Test "Real part of: cacos (0.7 + 1.2 i) == 1.1351827477151551088992008271819053 - 1.0927647857577371459105272080819308 i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: cacos (0.7 + 1.2 i) == 1.1351827477151551088992008271819053 - 1.0927647857577371459105272080819308 i":
+float: 1
+ifloat: 1
+
+# cacosh
+Test "Real part of: cacosh (-2 - 3 i) == 1.9833870299165354323470769028940395 - 2.1414491111159960199416055713254211 i":
+double: 1
+float: 7
+idouble: 1
+ifloat: 7
+Test "Imaginary part of: cacosh (-2 - 3 i) == 1.9833870299165354323470769028940395 - 2.1414491111159960199416055713254211 i":
+double: 1
+float: 3
+idouble: 1
+ifloat: 3
+Test "Real part of: cacosh (0.7 + 1.2 i) == 1.0927647857577371459105272080819308 + 1.1351827477151551088992008271819053 i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+# casin
+Test "Real part of: casin (0.7 + 1.2 i) == 0.4356135790797415103321208644578462 + 1.0927647857577371459105272080819308 i":
+double: 3
+float: 2
+idouble: 3
+ifloat: 2
+Test "Imaginary part of: casin (0.7 + 1.2 i) == 0.4356135790797415103321208644578462 + 1.0927647857577371459105272080819308 i":
+float: 1
+ifloat: 1
+
+# casinh
+Test "Real part of: casinh (-2 - 3 i) == -1.9686379257930962917886650952454982 - 0.96465850440760279204541105949953237 i":
+double: 5
+float: 1
+idouble: 5
+ifloat: 1
+Test "Imaginary part of: casinh (-2 - 3 i) == -1.9686379257930962917886650952454982 - 0.96465850440760279204541105949953237 i":
+double: 3
+float: 6
+idouble: 3
+ifloat: 6
+Test "Real part of: casinh (0.7 + 1.2 i) == 0.97865459559367387689317593222160964 + 0.91135418953156011567903546856170941 i":
+double: 1
+idouble: 1
+Test "Imaginary part of: casinh (0.7 + 1.2 i) == 0.97865459559367387689317593222160964 + 0.91135418953156011567903546856170941 i":
+float: 1
+ifloat: 1
+
+# catan
+Test "Real part of: catan (-2 - 3 i) == -1.4099210495965755225306193844604208 - 0.22907268296853876629588180294200276 i":
+float: 3
+ifloat: 3
+Test "Imaginary part of: catan (-2 - 3 i) == -1.4099210495965755225306193844604208 - 0.22907268296853876629588180294200276 i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Real part of: catan (0.7 + 1.2 i) == 1.0785743834118921877443707996386368 + 0.57705737765343067644394541889341712 i":
+float: 4
+ifloat: 4
+Test "Imaginary part of: catan (0.7 + 1.2 i) == 1.0785743834118921877443707996386368 + 0.57705737765343067644394541889341712 i":
+double: 1
+idouble: 1
+
+# catanh
+Test "Real part of: catanh (-2 - 3 i) == -0.14694666622552975204743278515471595 - 1.3389725222944935611241935759091443 i":
+double: 4
+idouble: 4
+Test "Imaginary part of: catanh (-2 - 3 i) == -0.14694666622552975204743278515471595 - 1.3389725222944935611241935759091443 i":
+float: 4
+ifloat: 4
+Test "Real part of: catanh (0.7 + 1.2 i) == 0.2600749516525135959200648705635915 + 0.97024030779509898497385130162655963 i":
+float: 1
+ifloat: 1
+Test "Imaginary part of: catanh (0.7 + 1.2 i) == 0.2600749516525135959200648705635915 + 0.97024030779509898497385130162655963 i":
+double: 1
+float: 6
+idouble: 1
+ifloat: 6
+
+# cbrt
+Test "cbrt (-27.0) == -3.0":
+double: 1
+idouble: 1
+Test "cbrt (0.970299) == 0.99":
+double: 1
+idouble: 1
+
+# ccos
+Test "Imaginary part of: ccos (-2 - 3 i) == -4.18962569096880723013255501961597373 - 9.10922789375533659797919726277886212 i":
+float: 1
+ifloat: 1
+Test "Real part of: ccos (0.7 + 1.2 i) == 1.3848657645312111080 - 0.97242170335830028619 i":
+double: 1
+idouble: 1
+Test "Imaginary part of: ccos (0.7 + 1.2 i) == 1.3848657645312111080 - 0.97242170335830028619 i":
+double: 1
+idouble: 1
+
+# ccosh
+Test "Real part of: ccosh (-2 - 3 i) == -3.72454550491532256547397070325597253 + 0.511822569987384608834463849801875634 i":
+float: 1
+ifloat: 1
+Test "Imaginary part of: ccosh (-2 - 3 i) == -3.72454550491532256547397070325597253 + 0.511822569987384608834463849801875634 i":
+float: 1
+ifloat: 1
+Test "Real part of: ccosh (0.7 + 1.2 i) == 0.4548202223691477654 + 0.7070296600921537682 i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: ccosh (0.7 + 1.2 i) == 0.4548202223691477654 + 0.7070296600921537682 i":
+double: 1
+idouble: 1
+
+# cexp
+Test "Imaginary part of: cexp (-2.0 - 3.0 i) == -0.13398091492954261346140525546115575 - 0.019098516261135196432576240858800925 i":
+float: 1
+ifloat: 1
+Test "Real part of: cexp (0.7 + 1.2 i) == 0.7296989091503236012 + 1.8768962328348102821 i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: cexp (0.7 + 1.2 i) == 0.7296989091503236012 + 1.8768962328348102821 i":
+float: 1
+ifloat: 1
+
+# clog
+Test "Imaginary part of: clog (-2 - 3 i) == 1.2824746787307683680267437207826593 - 2.1587989303424641704769327722648368 i":
+double: 1
+float: 3
+idouble: 1
+ifloat: 3
+
+# clog10
+Test "Imaginary part of: clog10 (-0 + inf i) == inf + pi/2*log10(e) i":
+float: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (-0 - inf i) == inf - pi/2*log10(e) i":
+float: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (-2 - 3 i) == 0.556971676153418384603252578971164214 - 0.937554462986374708541507952140189646 i":
+double: 1
+float: 5
+idouble: 1
+ifloat: 5
+Test "Imaginary part of: clog10 (-3 + inf i) == inf + pi/2*log10(e) i":
+float: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (-3 - inf i) == inf - pi/2*log10(e) i":
+float: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (-inf + 0 i) == inf + pi*log10(e) i":
+float: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (-inf + 1 i) == inf + pi*log10(e) i":
+float: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (-inf - 0 i) == inf - pi*log10(e) i":
+float: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (-inf - 1 i) == inf - pi*log10(e) i":
+float: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (0 + inf i) == inf + pi/2*log10(e) i":
+float: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (0 - inf i) == inf - pi/2*log10(e) i":
+float: 1
+ifloat: 1
+Test "Real part of: clog10 (0.7 + 1.2 i) == 0.1427786545038868803 + 0.4528483579352493248 i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (0.7 + 1.2 i) == 0.1427786545038868803 + 0.4528483579352493248 i":
+double: 1
+idouble: 1
+Test "Imaginary part of: clog10 (3 + inf i) == inf + pi/2*log10(e) i":
+float: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (3 - inf i) == inf - pi/2*log10(e) i":
+float: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (inf + inf i) == inf + pi/4*log10(e) i":
+float: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (inf - inf i) == inf - pi/4*log10(e) i":
+float: 1
+ifloat: 1
+
+# cos
+Test "cos (0.7) == 0.7648421872844884262":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "cos (M_PI_6l * 2.0) == 0.5":
+double: 1
+float: 0.5
+idouble: 1
+ifloat: 0.5
+Test "cos (M_PI_6l * 4.0) == -0.5":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+Test "cos (pi/2) == 0":
+double: 0.2758
+float: 0.3667
+idouble: 0.2758
+ifloat: 0.3667
+
+# cpow
+Test "Real part of: cpow (2 + 3 i, 4 + 0 i) == -119.0 - 120.0 i":
+double: 1
+float: 4
+idouble: 1
+ifloat: 4
+Test "Imaginary part of: cpow (2 + 3 i, 4 + 0 i) == -119.0 - 120.0 i":
+float: 2
+ifloat: 2
+Test "Imaginary part of: cpow (e + 0 i, 0 + 2 * M_PIl i) == 1.0 + 0.0 i":
+double: 1.1031
+float: 1.5
+idouble: 1.1031
+ifloat: 1.5
+
+# csin
+Test "Imaginary part of: csin (0.7 + 1.2 i) == 1.1664563419657581376 + 1.1544997246948547371 i":
+float: 1
+ifloat: 1
+
+# csinh
+Test "Imaginary part of: csinh (-2 - 3 i) == 3.59056458998577995201256544779481679 - 0.530921086248519805267040090660676560 i":
+double: 1
+idouble: 1
+Test "Real part of: csinh (0.7 + 1.2 i) == 0.27487868678117583582 + 1.1698665727426565139 i":
+float: 1
+ifloat: 1
+Test "Imaginary part of: csinh (0.7 + 1.2 i) == 0.27487868678117583582 + 1.1698665727426565139 i":
+float: 1
+ifloat: 1
+
+# csqrt
+Test "Real part of: csqrt (-2 + 3 i) == 0.89597747612983812471573375529004348 + 1.6741492280355400404480393008490519 i":
+float: 1
+ifloat: 1
+Test "Real part of: csqrt (-2 - 3 i) == 0.89597747612983812471573375529004348 - 1.6741492280355400404480393008490519 i":
+float: 1
+ifloat: 1
+Test "Real part of: csqrt (0.7 + 1.2 i) == 1.022067610030026450706487883081139 + 0.58704531296356521154977678719838035 i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: csqrt (0.7 + 1.2 i) == 1.022067610030026450706487883081139 + 0.58704531296356521154977678719838035 i":
+float: 1
+ifloat: 1
+
+# ctan
+Test "Real part of: ctan (-2 - 3 i) == 0.376402564150424829275122113032269084e-2 - 1.00323862735360980144635859782192726 i":
+double: 1
+idouble: 1
+Test "Real part of: ctan (0.7 + 1.2 i) == 0.1720734197630349001 + 0.9544807059989405538 i":
+float: 1
+ifloat: 1
+Test "Imaginary part of: ctan (0.7 + 1.2 i) == 0.1720734197630349001 + 0.9544807059989405538 i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+# ctanh
+Test "Real part of: ctanh (-2 - 3 i) == -0.965385879022133124278480269394560686 + 0.988437503832249372031403430350121098e-2 i":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+Test "Imaginary part of: ctanh (0 + pi/4 i) == 0.0 + 1.0 i":
+float: 1
+ifloat: 1
+Test "Real part of: ctanh (0.7 + 1.2 i) == 1.3472197399061191630 + 0.4778641038326365540 i":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+Test "Imaginary part of: ctanh (0.7 + 1.2 i) == 1.3472197399061191630 + 0.4778641038326365540 i":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+
+# erfc
+Test "erfc (0.7) == 0.32219880616258152702":
+double: 1
+idouble: 1
+Test "erfc (1.2) == 0.089686021770364619762":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+Test "erfc (2.0) == 0.0046777349810472658379":
+double: 1
+idouble: 1
+Test "erfc (4.1) == 0.67000276540848983727e-8":
+double: 24
+float: 12
+idouble: 24
+ifloat: 12
+
+# exp10
+Test "exp10 (-1) == 0.1":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+Test "exp10 (0.7) == 5.0118723362727228500":
+float: 1
+ifloat: 1
+Test "exp10 (3) == 1000":
+double: 6
+float: 2
+idouble: 6
+ifloat: 2
+
+# expm1
+Test "expm1 (1) == M_El - 1.0":
+float: 1
+ifloat: 1
+
+# fmod
+Test "fmod (-6.5, -2.3) == -1.9":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+Test "fmod (-6.5, 2.3) == -1.9":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+Test "fmod (6.5, -2.3) == 1.9":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+Test "fmod (6.5, 2.3) == 1.9":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+
+# hypot
+Test "hypot (-0.7, -12.4) == 12.419742348374220601176836866763271":
+float: 1
+ifloat: 1
+Test "hypot (-0.7, 12.4) == 12.419742348374220601176836866763271":
+float: 1
+ifloat: 1
+Test "hypot (-12.4, -0.7) == 12.419742348374220601176836866763271":
+float: 1
+ifloat: 1
+Test "hypot (-12.4, 0.7) == 12.419742348374220601176836866763271":
+float: 1
+ifloat: 1
+Test "hypot (0.7, -12.4) == 12.419742348374220601176836866763271":
+float: 1
+ifloat: 1
+Test "hypot (0.7, 1.2) == 1.3892443989449804508432547041028554":
+double: 1
+idouble: 1
+Test "hypot (0.7, 12.4) == 12.419742348374220601176836866763271":
+float: 1
+ifloat: 1
+Test "hypot (12.4, -0.7) == 12.419742348374220601176836866763271":
+float: 1
+ifloat: 1
+Test "hypot (12.4, 0.7) == 12.419742348374220601176836866763271":
+float: 1
+ifloat: 1
+
+# j0
+Test "j0 (10.0) == -0.24593576445134833520":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+Test "j0 (2.0) == 0.22389077914123566805":
+float: 2
+ifloat: 2
+Test "j0 (8.0) == 0.17165080713755390609":
+float: 1
+ifloat: 1
+
+# j1
+Test "j1 (10.0) == 0.043472746168861436670":
+float: 2
+ifloat: 2
+Test "j1 (2.0) == 0.57672480775687338720":
+double: 1
+idouble: 1
+Test "j1 (8.0) == 0.23463634685391462438":
+double: 1
+idouble: 1
+
+# jn
+Test "jn (0, 10.0) == -0.24593576445134833520":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+Test "jn (0, 2.0) == 0.22389077914123566805":
+float: 2
+ifloat: 2
+Test "jn (0, 8.0) == 0.17165080713755390609":
+float: 1
+ifloat: 1
+Test "jn (1, 10.0) == 0.043472746168861436670":
+float: 2
+ifloat: 2
+Test "jn (1, 2.0) == 0.57672480775687338720":
+double: 1
+idouble: 1
+Test "jn (1, 8.0) == 0.23463634685391462438":
+double: 1
+idouble: 1
+Test "jn (10, 0.1) == 0.26905328954342155795e-19":
+double: 6
+float: 4
+idouble: 6
+ifloat: 4
+Test "jn (10, 0.7) == 0.75175911502153953928e-11":
+double: 3
+float: 1
+idouble: 3
+ifloat: 1
+Test "jn (10, 10.0) == 0.20748610663335885770":
+double: 4
+float: 3
+idouble: 4
+ifloat: 3
+Test "jn (10, 2.0) == 0.25153862827167367096e-6":
+float: 4
+ifloat: 4
+Test "jn (3, 0.1) == 0.000020820315754756261429":
+double: 1
+idouble: 1
+Test "jn (3, 0.7) == 0.0069296548267508408077":
+float: 1
+ifloat: 1
+Test "jn (3, 10.0) == 0.058379379305186812343":
+double: 3
+float: 1
+idouble: 3
+ifloat: 1
+Test "jn (3, 2.0) == 0.12894324947440205110":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+
+# lgamma
+Test "lgamma (0.7) == 0.260867246531666514385732417016759578":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "lgamma (1.2) == -0.853740900033158497197028392998854470e-1":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+
+# log
+Test "log (0.7) == -0.35667494393873237891263871124118447":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+# log10
+Test "log10 (0.7) == -0.15490195998574316929":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "log10 (e) == log10(e)":
+float: 1
+ifloat: 1
+
+# log1p
+Test "log1p (-0.3) == -0.35667494393873237891263871124118447":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+# log2
+Test "log2 (0.7) == -0.51457317282975824043":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+# sincos
+Test "sincos (0.7, &sin_res, &cos_res) puts 0.76484218728448842626 in cos_res":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "sincos (M_PI_6l*2.0, &sin_res, &cos_res) puts 0.5 in cos_res":
+double: 1
+float: 0.5
+idouble: 1
+ifloat: 0.5
+Test "sincos (M_PI_6l*2.0, &sin_res, &cos_res) puts 0.866025403784438646764 in sin_res":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "sincos (pi/2, &sin_res, &cos_res) puts 0 in cos_res":
+double: 0.2758
+float: 0.3667
+idouble: 0.2758
+ifloat: 0.3667
+Test "sincos (pi/6, &sin_res, &cos_res) puts 0.866025403784438646764 in cos_res":
+float: 1
+ifloat: 1
+
+# sinh
+Test "sinh (0.7) == 0.75858370183953350346":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+# tan
+Test "tan (pi/4) == 1":
+double: 0.5
+idouble: 0.5
+
+# tanh
+Test "tanh (0.7) == 0.60436777711716349631":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+# tgamma
+Test "tgamma (-0.5) == -2 sqrt (pi)":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "tgamma (0.5) == sqrt (pi)":
+float: 1
+ifloat: 1
+Test "tgamma (0.7) == 1.29805533264755778568117117915281162":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+# y0
+Test "y0 (0.7) == -0.19066492933739506743":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+Test "y0 (1.0) == 0.088256964215676957983":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+Test "y0 (1.5) == 0.38244892379775884396":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+Test "y0 (10.0) == 0.055671167283599391424":
+float: 1
+ifloat: 1
+Test "y0 (8.0) == 0.22352148938756622053":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+# y1
+Test "y1 (0.1) == -6.4589510947020269877":
+double: 1
+idouble: 1
+Test "y1 (0.7) == -1.1032498719076333697":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "y1 (1.5) == -0.41230862697391129595":
+float: 1
+ifloat: 1
+Test "y1 (10.0) == 0.24901542420695388392":
+double: 3
+float: 1
+idouble: 3
+ifloat: 1
+Test "y1 (2.0) == -0.10703243154093754689":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "y1 (8.0) == -0.15806046173124749426":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+
+# yn
+Test "yn (0, 0.7) == -0.19066492933739506743":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+Test "yn (0, 1.0) == 0.088256964215676957983":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+Test "yn (0, 1.5) == 0.38244892379775884396":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+Test "yn (0, 10.0) == 0.055671167283599391424":
+float: 1
+ifloat: 1
+Test "yn (0, 8.0) == 0.22352148938756622053":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "yn (1, 0.1) == -6.4589510947020269877":
+double: 1
+idouble: 1
+Test "yn (1, 0.7) == -1.1032498719076333697":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "yn (1, 1.5) == -0.41230862697391129595":
+float: 1
+ifloat: 1
+Test "yn (1, 10.0) == 0.24901542420695388392":
+double: 3
+float: 1
+idouble: 3
+ifloat: 1
+Test "yn (1, 2.0) == -0.10703243154093754689":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "yn (1, 8.0) == -0.15806046173124749426":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+Test "yn (10, 0.1) == -0.11831335132045197885e19":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+Test "yn (10, 0.7) == -0.42447194260703866924e10":
+double: 3
+idouble: 3
+Test "yn (10, 1.0) == -0.12161801427868918929e9":
+double: 1
+idouble: 1
+Test "yn (10, 10.0) == -0.35981415218340272205":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "yn (10, 2.0) == -129184.54220803928264":
+double: 2
+idouble: 2
+Test "yn (3, 0.1) == -5099.3323786129048894":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "yn (3, 0.7) == -15.819479052819633505":
+double: 3
+float: 1
+idouble: 3
+ifloat: 1
+Test "yn (3, 10.0) == -0.25136265718383732978":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "yn (3, 2.0) == -1.1277837768404277861":
+double: 1
+idouble: 1
+
+# Maximal error of functions:
+Function: "asin":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+
+Function: "atan2":
+float: 4
+ifloat: 4
+
+Function: "atanh":
+double: 1
+idouble: 1
+
+Function: "cabs":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: Real part of "cacos":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: Imaginary part of "cacos":
+float: 1
+ifloat: 1
+
+Function: Real part of "cacosh":
+double: 1
+float: 7
+idouble: 1
+ifloat: 7
+
+Function: Imaginary part of "cacosh":
+double: 1
+float: 3
+idouble: 1
+ifloat: 3
+
+Function: Real part of "casin":
+double: 3
+float: 2
+idouble: 3
+ifloat: 2
+
+Function: Imaginary part of "casin":
+float: 1
+ifloat: 1
+
+Function: Real part of "casinh":
+double: 5
+float: 1
+idouble: 5
+ifloat: 1
+
+Function: Imaginary part of "casinh":
+double: 3
+float: 6
+idouble: 3
+ifloat: 6
+
+Function: Real part of "catan":
+float: 4
+ifloat: 4
+
+Function: Imaginary part of "catan":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: Real part of "catanh":
+double: 4
+float: 1
+idouble: 4
+ifloat: 1
+
+Function: Imaginary part of "catanh":
+double: 1
+float: 6
+idouble: 1
+ifloat: 6
+
+Function: "cbrt":
+double: 1
+idouble: 1
+
+Function: Real part of "ccos":
+double: 1
+idouble: 1
+
+Function: Imaginary part of "ccos":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: Real part of "ccosh":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: Imaginary part of "ccosh":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: Real part of "cexp":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: Imaginary part of "cexp":
+float: 1
+ifloat: 1
+
+Function: Imaginary part of "clog":
+double: 1
+float: 3
+idouble: 1
+ifloat: 3
+
+Function: Real part of "clog10":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: Imaginary part of "clog10":
+double: 1
+float: 5
+idouble: 1
+ifloat: 5
+
+Function: "cos":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+
+Function: Real part of "cpow":
+double: 1
+float: 4
+idouble: 1
+ifloat: 4
+
+Function: Imaginary part of "cpow":
+double: 1.1031
+float: 2
+idouble: 1.1031
+ifloat: 2
+
+Function: Imaginary part of "csin":
+float: 1
+ifloat: 1
+
+Function: Real part of "csinh":
+float: 1
+ifloat: 1
+
+Function: Imaginary part of "csinh":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: Real part of "csqrt":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: Imaginary part of "csqrt":
+float: 1
+ifloat: 1
+
+Function: Real part of "ctan":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: Imaginary part of "ctan":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: Real part of "ctanh":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+
+Function: Imaginary part of "ctanh":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+
+Function: "erfc":
+double: 24
+float: 12
+idouble: 24
+ifloat: 12
+
+Function: "exp10":
+double: 6
+float: 2
+idouble: 6
+ifloat: 2
+
+Function: "expm1":
+float: 1
+ifloat: 1
+
+Function: "fmod":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+
+Function: "hypot":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: "j0":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+
+Function: "j1":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+
+Function: "jn":
+double: 6
+float: 4
+idouble: 6
+ifloat: 4
+
+Function: "lgamma":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+
+Function: "log":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: "log10":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: "log1p":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: "log2":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: "sincos":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: "sinh":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: "tan":
+double: 0.5
+idouble: 0.5
+
+Function: "tanh":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: "tgamma":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: "y0":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+
+Function: "y1":
+double: 3
+float: 2
+idouble: 3
+ifloat: 2
+
+Function: "yn":
+double: 3
+float: 2
+idouble: 3
+ifloat: 2
+
+# end of automatic generation
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/math/libm-test-ulps-sparc32 b/l4/pkg/uclibc/lib/contrib/uclibc/test/math/libm-test-ulps-sparc32
new file mode 100644
index 00000000..ccf53788
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/math/libm-test-ulps-sparc32
@@ -0,0 +1,1322 @@
+# Begin of automatic generation
+
+# atan2
+Test "atan2 (-0.75, -1.0) == -2.49809154479650885165983415456218025":
+float: 3
+ifloat: 3
+ildouble: 1
+ldouble: 1
+Test "atan2 (0.75, -1.0) == 2.49809154479650885165983415456218025":
+float: 3
+ifloat: 3
+ildouble: 1
+ldouble: 1
+Test "atan2 (1.390625, 0.9296875) == 0.981498387184244311516296577615519772":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "atan2 (-0.00756827042671106339, -.001792735857538728036) == -1.80338464113663849327153994379639112":
+float: 6
+ifloat: 6
+ildouble: 1
+ldouble: 1
+
+# atanh
+Test "atanh (0.75) == 0.972955074527656652552676371721589865":
+float: 1
+ifloat: 1
+
+# cacos
+Test "Imaginary part of: cacos (0.75 + 1.25 i) == 1.11752014915610270578240049553777969 - 1.13239363160530819522266333696834467 i":
+ildouble: 1
+ldouble: 1
+
+# cacosh
+Test "Real part of: cacosh (-2 - 3 i) == 1.9833870299165354323470769028940395 - 2.1414491111159960199416055713254211 i":
+double: 1
+float: 7
+idouble: 1
+ifloat: 7
+ildouble: 5
+ldouble: 5
+Test "Imaginary part of: cacosh (-2 - 3 i) == 1.9833870299165354323470769028940395 - 2.1414491111159960199416055713254211 i":
+double: 1
+float: 3
+idouble: 1
+ifloat: 3
+ildouble: 1
+ldouble: 1
+
+# casin
+Test "Real part of: casin (0.75 + 1.25 i) == 0.453276177638793913448921196101971749 + 1.13239363160530819522266333696834467 i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: casin (0.75 + 1.25 i) == 0.453276177638793913448921196101971749 + 1.13239363160530819522266333696834467 i":
+ildouble: 1
+ldouble: 1
+
+# casinh
+Test "Real part of: casinh (-2 - 3 i) == -1.9686379257930962917886650952454982 - 0.96465850440760279204541105949953237 i":
+double: 5
+float: 1
+idouble: 5
+ifloat: 1
+ildouble: 4
+ldouble: 4
+Test "Imaginary part of: casinh (-2 - 3 i) == -1.9686379257930962917886650952454982 - 0.96465850440760279204541105949953237 i":
+double: 3
+float: 6
+idouble: 3
+ifloat: 6
+ildouble: 2
+ldouble: 2
+Test "Real part of: casinh (0.75 + 1.25 i) == 1.03171853444778027336364058631006594 + 0.911738290968487636358489564316731207 i":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "Imaginary part of: casinh (0.75 + 1.25 i) == 1.03171853444778027336364058631006594 + 0.911738290968487636358489564316731207 i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+# catan
+Test "Real part of: catan (-2 - 3 i) == -1.4099210495965755225306193844604208 - 0.22907268296853876629588180294200276 i":
+float: 3
+ifloat: 3
+Test "Imaginary part of: catan (-2 - 3 i) == -1.4099210495965755225306193844604208 - 0.22907268296853876629588180294200276 i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Real part of: catan (0.75 + 1.25 i) == 1.10714871779409050301706546017853704 + 0.549306144334054845697622618461262852 i":
+float: 4
+ifloat: 4
+Test "Imaginary part of: catan (0.75 + 1.25 i) == 1.10714871779409050301706546017853704 + 0.549306144334054845697622618461262852 i":
+ildouble: 1
+ldouble: 1
+
+# catanh
+Test "Real part of: catanh (-2 - 3 i) == -0.14694666622552975204743278515471595 - 1.3389725222944935611241935759091443 i":
+double: 4
+idouble: 4
+Test "Imaginary part of: catanh (-2 - 3 i) == -0.14694666622552975204743278515471595 - 1.3389725222944935611241935759091443 i":
+float: 4
+ifloat: 4
+Test "Real part of: catanh (0.75 + 1.25 i) == 0.261492138795671927078652057366532140 + 0.996825126463918666098902241310446708 i":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+Test "Imaginary part of: catanh (0.75 + 1.25 i) == 0.261492138795671927078652057366532140 + 0.996825126463918666098902241310446708 i":
+float: 6
+ifloat: 6
+ildouble: 1
+ldouble: 1
+
+# cbrt
+Test "cbrt (-0.001) == -0.1":
+ildouble: 1
+ldouble: 1
+Test "cbrt (-27.0) == -3.0":
+double: 1
+idouble: 1
+Test "cbrt (0.75) == 0.908560296416069829445605878163630251":
+double: 1
+idouble: 1
+Test "cbrt (0.9921875) == 0.997389022060725270579075195353955217":
+double: 1
+idouble: 1
+
+# ccos
+Test "Real part of: ccos (-2 - 3 i) == -4.18962569096880723013255501961597373 - 9.10922789375533659797919726277886212 i":
+ildouble: 1
+ldouble: 1
+Test "Imaginary part of: ccos (-2 - 3 i) == -4.18962569096880723013255501961597373 - 9.10922789375533659797919726277886212 i":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "Real part of: ccos (0.75 + 1.25 i) == 1.38173873063425888530729933139078645 - 1.09193013555397466170919531722024128 i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: ccos (0.75 + 1.25 i) == 1.38173873063425888530729933139078645 - 1.09193013555397466170919531722024128 i":
+float: 1
+ifloat: 1
+
+# ccosh
+Test "Real part of: ccosh (-2 - 3 i) == -3.72454550491532256547397070325597253 + 0.511822569987384608834463849801875634 i":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "Imaginary part of: ccosh (-2 - 3 i) == -3.72454550491532256547397070325597253 + 0.511822569987384608834463849801875634 i":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "Real part of: ccosh (0.75 + 1.25 i) == 0.408242591877968807788852146397499084 + 0.780365930845853240391326216300863152 i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: ccosh (0.75 + 1.25 i) == 0.408242591877968807788852146397499084 + 0.780365930845853240391326216300863152 i":
+float: 1
+ifloat: 1
+
+# cexp
+Test "Real part of: cexp (-2.0 - 3.0 i) == -0.13398091492954261346140525546115575 - 0.019098516261135196432576240858800925 i":
+ildouble: 1
+ldouble: 1
+Test "Imaginary part of: cexp (-2.0 - 3.0 i) == -0.13398091492954261346140525546115575 - 0.019098516261135196432576240858800925 i":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "Real part of: cexp (0.75 + 1.25 i) == 0.667537446429131586942201977015932112 + 2.00900045494094876258347228145863909 i":
+float: 1
+ifloat: 1
+Test "Imaginary part of: cexp (0.75 + 1.25 i) == 0.667537446429131586942201977015932112 + 2.00900045494094876258347228145863909 i":
+ildouble: 1
+ldouble: 1
+
+# clog
+Test "Imaginary part of: clog (-2 - 3 i) == 1.2824746787307683680267437207826593 - 2.1587989303424641704769327722648368 i":
+float: 3
+ifloat: 3
+Test "Real part of: clog (0.75 + 1.25 i) == 0.376885901188190075998919126749298416 + 1.03037682652431246378774332703115153 i":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+# clog10
+Test "Imaginary part of: clog10 (-0 + inf i) == inf + pi/2*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (-0 - inf i) == inf - pi/2*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Real part of: clog10 (-2 - 3 i) == 0.556971676153418384603252578971164214 - 0.937554462986374708541507952140189646 i":
+ildouble: 1
+ldouble: 1
+Test "Imaginary part of: clog10 (-2 - 3 i) == 0.556971676153418384603252578971164214 - 0.937554462986374708541507952140189646 i":
+double: 1
+float: 5
+idouble: 1
+ifloat: 5
+ildouble: 1
+ldouble: 1
+Test "Imaginary part of: clog10 (-3 + inf i) == inf + pi/2*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (-3 - inf i) == inf - pi/2*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (-inf + 0 i) == inf + pi*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (-inf + 1 i) == inf + pi*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (-inf + inf i) == inf + 3/4 pi*log10(e) i":
+double: 1
+idouble: 1
+Test "Imaginary part of: clog10 (-inf - 0 i) == inf - pi*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (-inf - 1 i) == inf - pi*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (0 + inf i) == inf + pi/2*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (0 - inf i) == inf - pi/2*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Real part of: clog10 (0.75 + 1.25 i) == 0.163679467193165171449476605077428975 + 0.447486970040493067069984724340855636 i":
+float: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (0.75 + 1.25 i) == 0.163679467193165171449476605077428975 + 0.447486970040493067069984724340855636 i":
+ildouble: 1
+ldouble: 1
+Test "Imaginary part of: clog10 (3 + inf i) == inf + pi/2*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (3 - inf i) == inf - pi/2*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (inf + inf i) == inf + pi/4*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (inf - inf i) == inf - pi/4*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+# cos
+Test "cos (M_PI_6l * 2.0) == 0.5":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "cos (M_PI_6l * 4.0) == -0.5":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "cos (pi/2) == 0":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+# cpow
+Test "Real part of: cpow (0.75 + 1.25 i, 0.0 + 1.0 i) == 0.331825439177608832276067945276730566 + 0.131338600281188544930936345230903032 i":
+float: 1
+ifloat: 1
+Test "Imaginary part of: cpow (0.75 + 1.25 i, 0.0 + 1.0 i) == 0.331825439177608832276067945276730566 + 0.131338600281188544930936345230903032 i":
+float: 1
+ifloat: 1
+Test "Real part of: cpow (0.75 + 1.25 i, 0.75 + 1.25 i) == 0.117506293914473555420279832210420483 + 0.346552747708338676483025352060418001 i":
+double: 1
+float: 4
+idouble: 1
+ifloat: 4
+ildouble: 4
+ldouble: 4
+Test "Real part of: cpow (0.75 + 1.25 i, 1.0 + 0.0 i) == 0.75 + 1.25 i":
+ildouble: 2
+ldouble: 2
+Test "Imaginary part of: cpow (0.75 + 1.25 i, 1.0 + 0.0 i) == 0.75 + 1.25 i":
+ildouble: 1
+ldouble: 1
+Test "Real part of: cpow (0.75 + 1.25 i, 1.0 + 1.0 i) == 0.0846958290317209430433805274189191353 + 0.513285749182902449043287190519090481 i":
+double: 2
+float: 3
+idouble: 2
+ifloat: 3
+ildouble: 10
+ldouble: 10
+Test "Real part of: cpow (2 + 0 i, 10 + 0 i) == 1024.0 + 0.0 i":
+ildouble: 2
+ldouble: 2
+Test "Real part of: cpow (2 + 3 i, 4 + 0 i) == -119.0 - 120.0 i":
+double: 1
+float: 4
+idouble: 1
+ifloat: 4
+ildouble: 3
+ldouble: 3
+Test "Imaginary part of: cpow (2 + 3 i, 4 + 0 i) == -119.0 - 120.0 i":
+float: 2
+ifloat: 2
+Test "Imaginary part of: cpow (e + 0 i, 0 + 2 * M_PIl i) == 1.0 + 0.0 i":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+ildouble: 1
+ldouble: 1
+
+# csin
+Test "Imaginary part of: csin (-2 - 3 i) == -9.15449914691142957346729954460983256 + 4.16890695996656435075481305885375484 i":
+ildouble: 1
+ldouble: 1
+Test "Real part of: csin (0.75 + 1.25 i) == 1.28722291002649188575873510790565441 + 1.17210635989270256101081285116138863 i":
+ildouble: 1
+ldouble: 1
+
+# csinh
+Test "Real part of: csinh (-2 - 3 i) == 3.59056458998577995201256544779481679 - 0.530921086248519805267040090660676560 i":
+ildouble: 1
+ldouble: 1
+Test "Imaginary part of: csinh (-2 - 3 i) == 3.59056458998577995201256544779481679 - 0.530921086248519805267040090660676560 i":
+double: 1
+idouble: 1
+Test "Real part of: csinh (0.75 + 1.25 i) == 0.259294854551162779153349830618433028 + 1.22863452409509552219214606515777594 i":
+float: 1
+ifloat: 1
+Test "Imaginary part of: csinh (0.75 + 1.25 i) == 0.259294854551162779153349830618433028 + 1.22863452409509552219214606515777594 i":
+float: 1
+ifloat: 1
+
+# csqrt
+Test "Real part of: csqrt (-2 + 3 i) == 0.89597747612983812471573375529004348 + 1.6741492280355400404480393008490519 i":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "Real part of: csqrt (-2 - 3 i) == 0.89597747612983812471573375529004348 - 1.6741492280355400404480393008490519 i":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "Imaginary part of: csqrt (0.75 + 1.25 i) == 1.05065169626078392338656675760808326 + 0.594868882070379067881984030639932657 i":
+ildouble: 1
+ldouble: 1
+
+# ctan
+Test "Real part of: ctan (-2 - 3 i) == 0.376402564150424829275122113032269084e-2 - 1.00323862735360980144635859782192726 i":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+Test "Imaginary part of: ctan (-2 - 3 i) == 0.376402564150424829275122113032269084e-2 - 1.00323862735360980144635859782192726 i":
+ildouble: 1
+ldouble: 1
+Test "Imaginary part of: ctan (0.75 + 1.25 i) == 0.160807785916206426725166058173438663 + 0.975363285031235646193581759755216379 i":
+double: 1
+idouble: 1
+ildouble: 2
+ldouble: 2
+
+# ctanh
+Test "Real part of: ctanh (-2 - 3 i) == -0.965385879022133124278480269394560686 + 0.988437503832249372031403430350121098e-2 i":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 1
+ldouble: 1
+Test "Imaginary part of: ctanh (-2 - 3 i) == -0.965385879022133124278480269394560686 + 0.988437503832249372031403430350121098e-2 i":
+ildouble: 1
+ldouble: 1
+Test "Imaginary part of: ctanh (0 + pi/4 i) == 0.0 + 1.0 i":
+float: 1
+ifloat: 1
+Test "Real part of: ctanh (0.75 + 1.25 i) == 1.37260757053378320258048606571226857 + 0.385795952609750664177596760720790220 i":
+double: 1
+idouble: 1
+
+# erf
+Test "erf (1.25) == 0.922900128256458230136523481197281140":
+double: 1
+idouble: 1
+
+# erfc
+Test "erfc (2.0) == 0.00467773498104726583793074363274707139":
+double: 1
+idouble: 1
+Test "erfc (27.0) == 0.523704892378925568501606768284954709e-318":
+ildouble: 1
+ldouble: 1
+Test "erfc (4.125) == 0.542340079956506600531223408575531062e-8":
+double: 1
+idouble: 1
+
+# exp10
+Test "exp10 (-1) == 0.1":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+Test "exp10 (0.75) == 5.62341325190349080394951039776481231":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "exp10 (3) == 1000":
+double: 6
+float: 2
+idouble: 6
+ifloat: 2
+ildouble: 1
+ldouble: 1
+
+# exp2
+Test "exp2 (10) == 1024":
+ildouble: 2
+ldouble: 2
+
+# expm1
+Test "expm1 (0.75) == 1.11700001661267466854536981983709561":
+double: 1
+idouble: 1
+Test "expm1 (1) == M_El - 1.0":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+# gamma
+Test "gamma (-0.5) == log(2*sqrt(pi))":
+ildouble: 1
+ldouble: 1
+
+# hypot
+Test "hypot (-0.7, -12.4) == 12.419742348374220601176836866763271":
+float: 1
+ifloat: 1
+Test "hypot (-0.7, 12.4) == 12.419742348374220601176836866763271":
+float: 1
+ifloat: 1
+Test "hypot (-12.4, -0.7) == 12.419742348374220601176836866763271":
+float: 1
+ifloat: 1
+Test "hypot (-12.4, 0.7) == 12.419742348374220601176836866763271":
+float: 1
+ifloat: 1
+Test "hypot (0.7, -12.4) == 12.419742348374220601176836866763271":
+float: 1
+ifloat: 1
+Test "hypot (0.7, 12.4) == 12.419742348374220601176836866763271":
+float: 1
+ifloat: 1
+Test "hypot (12.4, -0.7) == 12.419742348374220601176836866763271":
+float: 1
+ifloat: 1
+Test "hypot (12.4, 0.7) == 12.419742348374220601176836866763271":
+float: 1
+ifloat: 1
+
+# j0
+Test "j0 (-4.0) == -3.9714980986384737228659076845169804197562E-1":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "j0 (0.75) == 0.864242275166648623555731103820923211":
+float: 1
+ifloat: 1
+Test "j0 (10.0) == -0.245935764451348335197760862485328754":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+ildouble: 2
+ldouble: 2
+Test "j0 (2.0) == 0.223890779141235668051827454649948626":
+float: 2
+ifloat: 2
+ildouble: 2
+ldouble: 2
+Test "j0 (4.0) == -3.9714980986384737228659076845169804197562E-1":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "j0 (8.0) == 0.171650807137553906090869407851972001":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+# j1
+Test "j1 (-1.0) == -0.440050585744933515959682203718914913":
+ildouble: 1
+ldouble: 1
+Test "j1 (0.75) == 0.349243602174862192523281016426251335":
+ildouble: 1
+ldouble: 1
+Test "j1 (1.0) == 0.440050585744933515959682203718914913":
+ildouble: 1
+ldouble: 1
+Test "j1 (10.0) == 0.0434727461688614366697487680258592883":
+float: 2
+ifloat: 2
+ildouble: 2
+ldouble: 2
+Test "j1 (2.0) == 0.576724807756873387202448242269137087":
+double: 1
+idouble: 1
+Test "j1 (8.0) == 0.234636346853914624381276651590454612":
+double: 1
+idouble: 1
+ildouble: 4
+ldouble: 4
+
+# jn
+Test "jn (0, -4.0) == -3.9714980986384737228659076845169804197562E-1":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "jn (0, 0.75) == 0.864242275166648623555731103820923211":
+float: 1
+ifloat: 1
+Test "jn (0, 10.0) == -0.245935764451348335197760862485328754":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+ildouble: 2
+ldouble: 2
+Test "jn (0, 2.0) == 0.223890779141235668051827454649948626":
+float: 2
+ifloat: 2
+ildouble: 2
+ldouble: 2
+Test "jn (0, 4.0) == -3.9714980986384737228659076845169804197562E-1":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "jn (0, 8.0) == 0.171650807137553906090869407851972001":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "jn (1, -1.0) == -0.440050585744933515959682203718914913":
+ildouble: 1
+ldouble: 1
+Test "jn (1, 0.75) == 0.349243602174862192523281016426251335":
+ildouble: 1
+ldouble: 1
+Test "jn (1, 1.0) == 0.440050585744933515959682203718914913":
+ildouble: 1
+ldouble: 1
+Test "jn (1, 10.0) == 0.0434727461688614366697487680258592883":
+float: 2
+ifloat: 2
+ildouble: 2
+ldouble: 2
+Test "jn (1, 2.0) == 0.576724807756873387202448242269137087":
+double: 1
+idouble: 1
+Test "jn (1, 8.0) == 0.234636346853914624381276651590454612":
+double: 1
+idouble: 1
+ildouble: 4
+ldouble: 4
+Test "jn (10, -1.0) == 0.263061512368745320699785368779050294e-9":
+ildouble: 1
+ldouble: 1
+Test "jn (10, 0.125) == 0.250543369809369890173993791865771547e-18":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "jn (10, 0.75) == 0.149621713117596814698712483621682835e-10":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "jn (10, 1.0) == 0.263061512368745320699785368779050294e-9":
+ildouble: 1
+ldouble: 1
+Test "jn (10, 10.0) == 0.207486106633358857697278723518753428":
+double: 4
+float: 3
+idouble: 4
+ifloat: 3
+ildouble: 2
+ldouble: 2
+Test "jn (10, 2.0) == 0.251538628271673670963516093751820639e-6":
+float: 4
+ifloat: 4
+Test "jn (3, 0.125) == 0.406503832554912875023029337653442868e-4":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "jn (3, 0.75) == 0.848438342327410884392755236884386804e-2":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "jn (3, 10.0) == 0.0583793793051868123429354784103409563":
+double: 3
+float: 1
+idouble: 3
+ifloat: 1
+ildouble: 2
+ldouble: 2
+Test "jn (3, 2.0) == 0.128943249474402051098793332969239835":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+
+# lgamma
+Test "lgamma (-0.5) == log(2*sqrt(pi))":
+ildouble: 1
+ldouble: 1
+Test "lgamma (0.7) == 0.260867246531666514385732417016759578":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "lgamma (1.2) == -0.853740900033158497197028392998854470e-1":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 1
+ldouble: 1
+
+# log10
+Test "log10 (0.75) == -0.124938736608299953132449886193870744":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+Test "log10 (e) == log10(e)":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+# log1p
+Test "log1p (-0.25) == -0.287682072451780927439219005993827432":
+float: 1
+ifloat: 1
+Test "log1p (M_El - 1.0) == 1":
+ildouble: 1
+ldouble: 1
+
+# log2
+Test "log2 (0.75) == -.415037499278843818546261056052183492":
+ildouble: 1
+ldouble: 1
+
+# sincos
+Test "sincos (M_PI_6l*2.0, &sin_res, &cos_res) puts 0.5 in cos_res":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "sincos (M_PI_6l*2.0, &sin_res, &cos_res) puts 0.86602540378443864676372317075293616 in sin_res":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "sincos (pi/2, &sin_res, &cos_res) puts 0 in cos_res":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "sincos (pi/6, &sin_res, &cos_res) puts 0.86602540378443864676372317075293616 in cos_res":
+float: 1
+ifloat: 1
+
+# sqrt
+Test "sqrt (2) == M_SQRT2l":
+ildouble: 1
+ldouble: 1
+
+# tan
+Test "tan (pi/4) == 1":
+double: 1
+idouble: 1
+
+# tanh
+Test "tanh (-0.75) == -0.635148952387287319214434357312496495":
+ildouble: 1
+ldouble: 1
+Test "tanh (-1.0) == -0.7615941559557648881194582826047935904":
+ildouble: 1
+ldouble: 1
+Test "tanh (0.75) == 0.635148952387287319214434357312496495":
+ildouble: 1
+ldouble: 1
+Test "tanh (1.0) == 0.7615941559557648881194582826047935904":
+ildouble: 1
+ldouble: 1
+
+# tgamma
+Test "tgamma (-0.5) == -2 sqrt (pi)":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "tgamma (0.5) == sqrt (pi)":
+float: 1
+ifloat: 1
+Test "tgamma (0.7) == 1.29805533264755778568117117915281162":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "tgamma (4) == 6":
+ildouble: 1
+ldouble: 1
+
+# y0
+Test "y0 (1.0) == 0.0882569642156769579829267660235151628":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+Test "y0 (1.5) == 0.382448923797758843955068554978089862":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+Test "y0 (10.0) == 0.0556711672835993914244598774101900481":
+float: 1
+ifloat: 1
+ildouble: 3
+ldouble: 3
+Test "y0 (8.0) == 0.223521489387566220527323400498620359":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 3
+ldouble: 3
+
+# y1
+Test "y1 (0.125) == -5.19993611253477499595928744876579921":
+double: 1
+idouble: 1
+Test "y1 (0.75) == -1.03759455076928541973767132140642198":
+ildouble: 1
+ldouble: 1
+Test "y1 (1.5) == -0.412308626973911295952829820633445323":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "y1 (10.0) == 0.249015424206953883923283474663222803":
+double: 3
+float: 1
+idouble: 3
+ifloat: 1
+Test "y1 (2.0) == -0.107032431540937546888370772277476637":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "y1 (8.0) == -0.158060461731247494255555266187483550":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 1
+ldouble: 1
+
+# yn
+Test "yn (0, 1.0) == 0.0882569642156769579829267660235151628":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+Test "yn (0, 1.5) == 0.382448923797758843955068554978089862":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+Test "yn (0, 10.0) == 0.0556711672835993914244598774101900481":
+float: 1
+ifloat: 1
+ildouble: 3
+ldouble: 3
+Test "yn (0, 8.0) == 0.223521489387566220527323400498620359":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 3
+ldouble: 3
+Test "yn (1, 0.125) == -5.19993611253477499595928744876579921":
+double: 1
+idouble: 1
+Test "yn (1, 0.75) == -1.03759455076928541973767132140642198":
+ildouble: 1
+ldouble: 1
+Test "yn (1, 1.5) == -0.412308626973911295952829820633445323":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "yn (1, 10.0) == 0.249015424206953883923283474663222803":
+double: 3
+float: 1
+idouble: 3
+ifloat: 1
+Test "yn (1, 2.0) == -0.107032431540937546888370772277476637":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "yn (1, 8.0) == -0.158060461731247494255555266187483550":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 1
+ldouble: 1
+Test "yn (10, 0.125) == -127057845771019398.252538486899753195":
+double: 1
+idouble: 1
+ildouble: 2
+ldouble: 2
+Test "yn (10, 0.75) == -2133501638.90573424452445412893839236":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 5
+ldouble: 5
+Test "yn (10, 1.0) == -121618014.278689189288130426667971145":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+Test "yn (10, 10.0) == -0.359814152183402722051986577343560609":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 2
+ldouble: 2
+Test "yn (10, 2.0) == -129184.542208039282635913145923304214":
+double: 2
+idouble: 2
+ildouble: 2
+ldouble: 2
+Test "yn (3, 0.125) == -2612.69757350066712600220955744091741":
+double: 1
+idouble: 1
+Test "yn (3, 0.75) == -12.9877176234475433186319774484809207":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 2
+ldouble: 2
+Test "yn (3, 10.0) == -0.251362657183837329779204747654240998":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "yn (3, 2.0) == -1.12778377684042778608158395773179238":
+double: 1
+idouble: 1
+
+# Maximal error of functions:
+Function: "atan2":
+float: 6
+ifloat: 6
+ildouble: 1
+ldouble: 1
+
+Function: "atanh":
+float: 1
+ifloat: 1
+
+Function: Imaginary part of "cacos":
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "cacosh":
+double: 1
+float: 7
+idouble: 1
+ifloat: 7
+ildouble: 5
+ldouble: 5
+
+Function: Imaginary part of "cacosh":
+double: 1
+float: 3
+idouble: 1
+ifloat: 3
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "casin":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: Imaginary part of "casin":
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "casinh":
+double: 5
+float: 1
+idouble: 5
+ifloat: 1
+ildouble: 4
+ldouble: 4
+
+Function: Imaginary part of "casinh":
+double: 3
+float: 6
+idouble: 3
+ifloat: 6
+ildouble: 2
+ldouble: 2
+
+Function: Real part of "catan":
+float: 4
+ifloat: 4
+
+Function: Imaginary part of "catan":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "catanh":
+double: 4
+idouble: 4
+ildouble: 1
+ldouble: 1
+
+Function: Imaginary part of "catanh":
+float: 6
+ifloat: 6
+ildouble: 1
+ldouble: 1
+
+Function: "cbrt":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "ccos":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: Imaginary part of "ccos":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "ccosh":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: Imaginary part of "ccosh":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "cexp":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: Imaginary part of "cexp":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "clog":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: Imaginary part of "clog":
+float: 3
+ifloat: 3
+
+Function: Real part of "clog10":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: Imaginary part of "clog10":
+double: 1
+float: 5
+idouble: 1
+ifloat: 5
+ildouble: 1
+ldouble: 1
+
+Function: "cos":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "cpow":
+double: 2
+float: 4
+idouble: 2
+ifloat: 4
+ildouble: 10
+ldouble: 10
+
+Function: Imaginary part of "cpow":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "csin":
+ildouble: 1
+ldouble: 1
+
+Function: Imaginary part of "csin":
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "csinh":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: Imaginary part of "csinh":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: Real part of "csqrt":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: Imaginary part of "csqrt":
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "ctan":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+
+Function: Imaginary part of "ctan":
+double: 1
+idouble: 1
+ildouble: 2
+ldouble: 2
+
+Function: Real part of "ctanh":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 1
+ldouble: 1
+
+Function: Imaginary part of "ctanh":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "erf":
+double: 1
+idouble: 1
+
+Function: "erfc":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+
+Function: "exp10":
+double: 6
+float: 2
+idouble: 6
+ifloat: 2
+ildouble: 1
+ldouble: 1
+
+Function: "exp2":
+ildouble: 2
+ldouble: 2
+
+Function: "expm1":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "gamma":
+ildouble: 1
+ldouble: 1
+
+Function: "hypot":
+float: 1
+ifloat: 1
+
+Function: "j0":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+ildouble: 2
+ldouble: 2
+
+Function: "j1":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 4
+ldouble: 4
+
+Function: "jn":
+double: 4
+float: 4
+idouble: 4
+ifloat: 4
+ildouble: 4
+ldouble: 4
+
+Function: "lgamma":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 1
+ldouble: 1
+
+Function: "log10":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 1
+ldouble: 1
+
+Function: "log1p":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "log2":
+ildouble: 1
+ldouble: 1
+
+Function: "sincos":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "sqrt":
+ildouble: 1
+ldouble: 1
+
+Function: "tan":
+double: 1
+idouble: 1
+
+Function: "tanh":
+ildouble: 1
+ldouble: 1
+
+Function: "tgamma":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "y0":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+ildouble: 3
+ldouble: 3
+
+Function: "y1":
+double: 3
+float: 2
+idouble: 3
+ifloat: 2
+ildouble: 1
+ldouble: 1
+
+Function: "yn":
+double: 3
+float: 2
+idouble: 3
+ifloat: 2
+ildouble: 5
+ldouble: 5
+
+# end of automatic generation
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/math/libm-test-ulps-sparc64 b/l4/pkg/uclibc/lib/contrib/uclibc/test/math/libm-test-ulps-sparc64
new file mode 100644
index 00000000..db5543e9
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/math/libm-test-ulps-sparc64
@@ -0,0 +1,1322 @@
+# Begin of automatic generation
+
+# atan2
+Test "atan2 (-0.00756827042671106339, -.001792735857538728036) == -1.80338464113663849327153994379639112":
+float: 6
+ifloat: 6
+ildouble: 1
+ldouble: 1
+Test "atan2 (-0.75, -1.0) == -2.49809154479650885165983415456218025":
+float: 3
+ifloat: 3
+ildouble: 1
+ldouble: 1
+Test "atan2 (0.75, -1.0) == 2.49809154479650885165983415456218025":
+float: 3
+ifloat: 3
+ildouble: 1
+ldouble: 1
+Test "atan2 (1.390625, 0.9296875) == 0.981498387184244311516296577615519772":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+# atanh
+Test "atanh (0.75) == 0.972955074527656652552676371721589865":
+float: 1
+ifloat: 1
+
+# cacos
+Test "Imaginary part of: cacos (0.75 + 1.25 i) == 1.11752014915610270578240049553777969 - 1.13239363160530819522266333696834467 i":
+ildouble: 1
+ldouble: 1
+
+# cacosh
+Test "Real part of: cacosh (-2 - 3 i) == 1.9833870299165354323470769028940395 - 2.1414491111159960199416055713254211 i":
+double: 1
+float: 7
+idouble: 1
+ifloat: 7
+ildouble: 5
+ldouble: 5
+Test "Imaginary part of: cacosh (-2 - 3 i) == 1.9833870299165354323470769028940395 - 2.1414491111159960199416055713254211 i":
+double: 1
+float: 3
+idouble: 1
+ifloat: 3
+ildouble: 1
+ldouble: 1
+
+# casin
+Test "Real part of: casin (0.75 + 1.25 i) == 0.453276177638793913448921196101971749 + 1.13239363160530819522266333696834467 i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: casin (0.75 + 1.25 i) == 0.453276177638793913448921196101971749 + 1.13239363160530819522266333696834467 i":
+ildouble: 1
+ldouble: 1
+
+# casinh
+Test "Real part of: casinh (-2 - 3 i) == -1.9686379257930962917886650952454982 - 0.96465850440760279204541105949953237 i":
+double: 5
+float: 1
+idouble: 5
+ifloat: 1
+ildouble: 4
+ldouble: 4
+Test "Imaginary part of: casinh (-2 - 3 i) == -1.9686379257930962917886650952454982 - 0.96465850440760279204541105949953237 i":
+double: 3
+float: 6
+idouble: 3
+ifloat: 6
+ildouble: 2
+ldouble: 2
+Test "Real part of: casinh (0.75 + 1.25 i) == 1.03171853444778027336364058631006594 + 0.911738290968487636358489564316731207 i":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "Imaginary part of: casinh (0.75 + 1.25 i) == 1.03171853444778027336364058631006594 + 0.911738290968487636358489564316731207 i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+# catan
+Test "Real part of: catan (-2 - 3 i) == -1.4099210495965755225306193844604208 - 0.22907268296853876629588180294200276 i":
+float: 3
+ifloat: 3
+Test "Imaginary part of: catan (-2 - 3 i) == -1.4099210495965755225306193844604208 - 0.22907268296853876629588180294200276 i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Real part of: catan (0.75 + 1.25 i) == 1.10714871779409050301706546017853704 + 0.549306144334054845697622618461262852 i":
+float: 4
+ifloat: 4
+Test "Imaginary part of: catan (0.75 + 1.25 i) == 1.10714871779409050301706546017853704 + 0.549306144334054845697622618461262852 i":
+ildouble: 1
+ldouble: 1
+
+# catanh
+Test "Real part of: catanh (-2 - 3 i) == -0.14694666622552975204743278515471595 - 1.3389725222944935611241935759091443 i":
+double: 4
+idouble: 4
+Test "Imaginary part of: catanh (-2 - 3 i) == -0.14694666622552975204743278515471595 - 1.3389725222944935611241935759091443 i":
+float: 4
+ifloat: 4
+Test "Real part of: catanh (0.75 + 1.25 i) == 0.261492138795671927078652057366532140 + 0.996825126463918666098902241310446708 i":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+Test "Imaginary part of: catanh (0.75 + 1.25 i) == 0.261492138795671927078652057366532140 + 0.996825126463918666098902241310446708 i":
+float: 6
+ifloat: 6
+ildouble: 1
+ldouble: 1
+
+# cbrt
+Test "cbrt (-0.001) == -0.1":
+ildouble: 1
+ldouble: 1
+Test "cbrt (-27.0) == -3.0":
+double: 1
+idouble: 1
+Test "cbrt (0.75) == 0.908560296416069829445605878163630251":
+double: 1
+idouble: 1
+Test "cbrt (0.9921875) == 0.997389022060725270579075195353955217":
+double: 1
+idouble: 1
+
+# ccos
+Test "Real part of: ccos (-2 - 3 i) == -4.18962569096880723013255501961597373 - 9.10922789375533659797919726277886212 i":
+ildouble: 1
+ldouble: 1
+Test "Imaginary part of: ccos (-2 - 3 i) == -4.18962569096880723013255501961597373 - 9.10922789375533659797919726277886212 i":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "Real part of: ccos (0.75 + 1.25 i) == 1.38173873063425888530729933139078645 - 1.09193013555397466170919531722024128 i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: ccos (0.75 + 1.25 i) == 1.38173873063425888530729933139078645 - 1.09193013555397466170919531722024128 i":
+float: 1
+ifloat: 1
+
+# ccosh
+Test "Real part of: ccosh (-2 - 3 i) == -3.72454550491532256547397070325597253 + 0.511822569987384608834463849801875634 i":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "Imaginary part of: ccosh (-2 - 3 i) == -3.72454550491532256547397070325597253 + 0.511822569987384608834463849801875634 i":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "Real part of: ccosh (0.75 + 1.25 i) == 0.408242591877968807788852146397499084 + 0.780365930845853240391326216300863152 i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: ccosh (0.75 + 1.25 i) == 0.408242591877968807788852146397499084 + 0.780365930845853240391326216300863152 i":
+float: 1
+ifloat: 1
+
+# cexp
+Test "Real part of: cexp (-2.0 - 3.0 i) == -0.13398091492954261346140525546115575 - 0.019098516261135196432576240858800925 i":
+ildouble: 1
+ldouble: 1
+Test "Imaginary part of: cexp (-2.0 - 3.0 i) == -0.13398091492954261346140525546115575 - 0.019098516261135196432576240858800925 i":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "Real part of: cexp (0.75 + 1.25 i) == 0.667537446429131586942201977015932112 + 2.00900045494094876258347228145863909 i":
+float: 1
+ifloat: 1
+Test "Imaginary part of: cexp (0.75 + 1.25 i) == 0.667537446429131586942201977015932112 + 2.00900045494094876258347228145863909 i":
+ildouble: 1
+ldouble: 1
+
+# clog
+Test "Imaginary part of: clog (-2 - 3 i) == 1.2824746787307683680267437207826593 - 2.1587989303424641704769327722648368 i":
+float: 3
+ifloat: 3
+Test "Real part of: clog (0.75 + 1.25 i) == 0.376885901188190075998919126749298416 + 1.03037682652431246378774332703115153 i":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+# clog10
+Test "Imaginary part of: clog10 (-0 + inf i) == inf + pi/2*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (-0 - inf i) == inf - pi/2*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Real part of: clog10 (-2 - 3 i) == 0.556971676153418384603252578971164214 - 0.937554462986374708541507952140189646 i":
+ildouble: 1
+ldouble: 1
+Test "Imaginary part of: clog10 (-2 - 3 i) == 0.556971676153418384603252578971164214 - 0.937554462986374708541507952140189646 i":
+double: 1
+float: 5
+idouble: 1
+ifloat: 5
+ildouble: 1
+ldouble: 1
+Test "Imaginary part of: clog10 (-3 + inf i) == inf + pi/2*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (-3 - inf i) == inf - pi/2*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (-inf + 0 i) == inf + pi*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (-inf + 1 i) == inf + pi*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (-inf + inf i) == inf + 3/4 pi*log10(e) i":
+double: 1
+idouble: 1
+Test "Imaginary part of: clog10 (-inf - 0 i) == inf - pi*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (-inf - 1 i) == inf - pi*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (0 + inf i) == inf + pi/2*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (0 - inf i) == inf - pi/2*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Real part of: clog10 (0.75 + 1.25 i) == 0.163679467193165171449476605077428975 + 0.447486970040493067069984724340855636 i":
+float: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (0.75 + 1.25 i) == 0.163679467193165171449476605077428975 + 0.447486970040493067069984724340855636 i":
+ildouble: 1
+ldouble: 1
+Test "Imaginary part of: clog10 (3 + inf i) == inf + pi/2*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (3 - inf i) == inf - pi/2*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (inf + inf i) == inf + pi/4*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (inf - inf i) == inf - pi/4*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+# cos
+Test "cos (M_PI_6l * 2.0) == 0.5":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "cos (M_PI_6l * 4.0) == -0.5":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "cos (pi/2) == 0":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+# cpow
+Test "Real part of: cpow (0.75 + 1.25 i, 0.0 + 1.0 i) == 0.331825439177608832276067945276730566 + 0.131338600281188544930936345230903032 i":
+float: 1
+ifloat: 1
+Test "Imaginary part of: cpow (0.75 + 1.25 i, 0.0 + 1.0 i) == 0.331825439177608832276067945276730566 + 0.131338600281188544930936345230903032 i":
+float: 1
+ifloat: 1
+Test "Real part of: cpow (0.75 + 1.25 i, 0.75 + 1.25 i) == 0.117506293914473555420279832210420483 + 0.346552747708338676483025352060418001 i":
+double: 1
+float: 4
+idouble: 1
+ifloat: 4
+ildouble: 4
+ldouble: 4
+Test "Real part of: cpow (0.75 + 1.25 i, 1.0 + 0.0 i) == 0.75 + 1.25 i":
+ildouble: 2
+ldouble: 2
+Test "Imaginary part of: cpow (0.75 + 1.25 i, 1.0 + 0.0 i) == 0.75 + 1.25 i":
+ildouble: 1
+ldouble: 1
+Test "Real part of: cpow (0.75 + 1.25 i, 1.0 + 1.0 i) == 0.0846958290317209430433805274189191353 + 0.513285749182902449043287190519090481 i":
+double: 2
+float: 3
+idouble: 2
+ifloat: 3
+ildouble: 10
+ldouble: 10
+Test "Real part of: cpow (2 + 0 i, 10 + 0 i) == 1024.0 + 0.0 i":
+ildouble: 2
+ldouble: 2
+Test "Real part of: cpow (2 + 3 i, 4 + 0 i) == -119.0 - 120.0 i":
+double: 1
+float: 4
+idouble: 1
+ifloat: 4
+ildouble: 3
+ldouble: 3
+Test "Imaginary part of: cpow (2 + 3 i, 4 + 0 i) == -119.0 - 120.0 i":
+float: 2
+ifloat: 2
+Test "Imaginary part of: cpow (e + 0 i, 0 + 2 * M_PIl i) == 1.0 + 0.0 i":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+ildouble: 1
+ldouble: 1
+
+# csin
+Test "Imaginary part of: csin (-2 - 3 i) == -9.15449914691142957346729954460983256 + 4.16890695996656435075481305885375484 i":
+ildouble: 1
+ldouble: 1
+Test "Real part of: csin (0.75 + 1.25 i) == 1.28722291002649188575873510790565441 + 1.17210635989270256101081285116138863 i":
+ildouble: 1
+ldouble: 1
+
+# csinh
+Test "Real part of: csinh (-2 - 3 i) == 3.59056458998577995201256544779481679 - 0.530921086248519805267040090660676560 i":
+ildouble: 1
+ldouble: 1
+Test "Imaginary part of: csinh (-2 - 3 i) == 3.59056458998577995201256544779481679 - 0.530921086248519805267040090660676560 i":
+double: 1
+idouble: 1
+Test "Real part of: csinh (0.75 + 1.25 i) == 0.259294854551162779153349830618433028 + 1.22863452409509552219214606515777594 i":
+float: 1
+ifloat: 1
+Test "Imaginary part of: csinh (0.75 + 1.25 i) == 0.259294854551162779153349830618433028 + 1.22863452409509552219214606515777594 i":
+float: 1
+ifloat: 1
+
+# csqrt
+Test "Real part of: csqrt (-2 + 3 i) == 0.89597747612983812471573375529004348 + 1.6741492280355400404480393008490519 i":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "Real part of: csqrt (-2 - 3 i) == 0.89597747612983812471573375529004348 - 1.6741492280355400404480393008490519 i":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "Imaginary part of: csqrt (0.75 + 1.25 i) == 1.05065169626078392338656675760808326 + 0.594868882070379067881984030639932657 i":
+ildouble: 1
+ldouble: 1
+
+# ctan
+Test "Real part of: ctan (-2 - 3 i) == 0.376402564150424829275122113032269084e-2 - 1.00323862735360980144635859782192726 i":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+Test "Imaginary part of: ctan (-2 - 3 i) == 0.376402564150424829275122113032269084e-2 - 1.00323862735360980144635859782192726 i":
+ildouble: 1
+ldouble: 1
+Test "Imaginary part of: ctan (0.75 + 1.25 i) == 0.160807785916206426725166058173438663 + 0.975363285031235646193581759755216379 i":
+double: 1
+idouble: 1
+ildouble: 2
+ldouble: 2
+
+# ctanh
+Test "Real part of: ctanh (-2 - 3 i) == -0.965385879022133124278480269394560686 + 0.988437503832249372031403430350121098e-2 i":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 1
+ldouble: 1
+Test "Imaginary part of: ctanh (-2 - 3 i) == -0.965385879022133124278480269394560686 + 0.988437503832249372031403430350121098e-2 i":
+ildouble: 1
+ldouble: 1
+Test "Imaginary part of: ctanh (0 + pi/4 i) == 0.0 + 1.0 i":
+float: 1
+ifloat: 1
+Test "Real part of: ctanh (0.75 + 1.25 i) == 1.37260757053378320258048606571226857 + 0.385795952609750664177596760720790220 i":
+double: 1
+idouble: 1
+
+# erf
+Test "erf (1.25) == 0.922900128256458230136523481197281140":
+double: 1
+idouble: 1
+
+# erfc
+Test "erfc (2.0) == 0.00467773498104726583793074363274707139":
+double: 1
+idouble: 1
+Test "erfc (27.0) == 0.523704892378925568501606768284954709e-318":
+ildouble: 1
+ldouble: 1
+Test "erfc (4.125) == 0.542340079956506600531223408575531062e-8":
+double: 1
+idouble: 1
+
+# exp10
+Test "exp10 (-1) == 0.1":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+Test "exp10 (0.75) == 5.62341325190349080394951039776481231":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "exp10 (3) == 1000":
+double: 6
+float: 2
+idouble: 6
+ifloat: 2
+ildouble: 1
+ldouble: 1
+
+# exp2
+Test "exp2 (10) == 1024":
+ildouble: 2
+ldouble: 2
+
+# expm1
+Test "expm1 (0.75) == 1.11700001661267466854536981983709561":
+double: 1
+idouble: 1
+Test "expm1 (1) == M_El - 1.0":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+# gamma
+Test "gamma (-0.5) == log(2*sqrt(pi))":
+ildouble: 1
+ldouble: 1
+
+# hypot
+Test "hypot (-0.7, -12.4) == 12.419742348374220601176836866763271":
+float: 1
+ifloat: 1
+Test "hypot (-0.7, 12.4) == 12.419742348374220601176836866763271":
+float: 1
+ifloat: 1
+Test "hypot (-12.4, -0.7) == 12.419742348374220601176836866763271":
+float: 1
+ifloat: 1
+Test "hypot (-12.4, 0.7) == 12.419742348374220601176836866763271":
+float: 1
+ifloat: 1
+Test "hypot (0.7, -12.4) == 12.419742348374220601176836866763271":
+float: 1
+ifloat: 1
+Test "hypot (0.7, 12.4) == 12.419742348374220601176836866763271":
+float: 1
+ifloat: 1
+Test "hypot (12.4, -0.7) == 12.419742348374220601176836866763271":
+float: 1
+ifloat: 1
+Test "hypot (12.4, 0.7) == 12.419742348374220601176836866763271":
+float: 1
+ifloat: 1
+
+# j0
+Test "j0 (-4.0) == -3.9714980986384737228659076845169804197562E-1":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "j0 (0.75) == 0.864242275166648623555731103820923211":
+float: 1
+ifloat: 1
+Test "j0 (10.0) == -0.245935764451348335197760862485328754":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+ildouble: 2
+ldouble: 2
+Test "j0 (2.0) == 0.223890779141235668051827454649948626":
+float: 2
+ifloat: 2
+ildouble: 2
+ldouble: 2
+Test "j0 (4.0) == -3.9714980986384737228659076845169804197562E-1":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "j0 (8.0) == 0.171650807137553906090869407851972001":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+# j1
+Test "j1 (-1.0) == -0.440050585744933515959682203718914913":
+ildouble: 1
+ldouble: 1
+Test "j1 (0.75) == 0.349243602174862192523281016426251335":
+ildouble: 1
+ldouble: 1
+Test "j1 (1.0) == 0.440050585744933515959682203718914913":
+ildouble: 1
+ldouble: 1
+Test "j1 (10.0) == 0.0434727461688614366697487680258592883":
+float: 2
+ifloat: 2
+ildouble: 2
+ldouble: 2
+Test "j1 (2.0) == 0.576724807756873387202448242269137087":
+double: 1
+idouble: 1
+Test "j1 (8.0) == 0.234636346853914624381276651590454612":
+double: 1
+idouble: 1
+ildouble: 4
+ldouble: 4
+
+# jn
+Test "jn (0, -4.0) == -3.9714980986384737228659076845169804197562E-1":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "jn (0, 0.75) == 0.864242275166648623555731103820923211":
+float: 1
+ifloat: 1
+Test "jn (0, 10.0) == -0.245935764451348335197760862485328754":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+ildouble: 2
+ldouble: 2
+Test "jn (0, 2.0) == 0.223890779141235668051827454649948626":
+float: 2
+ifloat: 2
+ildouble: 2
+ldouble: 2
+Test "jn (0, 4.0) == -3.9714980986384737228659076845169804197562E-1":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "jn (0, 8.0) == 0.171650807137553906090869407851972001":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "jn (1, -1.0) == -0.440050585744933515959682203718914913":
+ildouble: 1
+ldouble: 1
+Test "jn (1, 0.75) == 0.349243602174862192523281016426251335":
+ildouble: 1
+ldouble: 1
+Test "jn (1, 1.0) == 0.440050585744933515959682203718914913":
+ildouble: 1
+ldouble: 1
+Test "jn (1, 10.0) == 0.0434727461688614366697487680258592883":
+float: 2
+ifloat: 2
+ildouble: 2
+ldouble: 2
+Test "jn (1, 2.0) == 0.576724807756873387202448242269137087":
+double: 1
+idouble: 1
+Test "jn (1, 8.0) == 0.234636346853914624381276651590454612":
+double: 1
+idouble: 1
+ildouble: 4
+ldouble: 4
+Test "jn (10, -1.0) == 0.263061512368745320699785368779050294e-9":
+ildouble: 1
+ldouble: 1
+Test "jn (10, 0.125) == 0.250543369809369890173993791865771547e-18":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "jn (10, 0.75) == 0.149621713117596814698712483621682835e-10":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "jn (10, 1.0) == 0.263061512368745320699785368779050294e-9":
+ildouble: 1
+ldouble: 1
+Test "jn (10, 10.0) == 0.207486106633358857697278723518753428":
+double: 4
+float: 3
+idouble: 4
+ifloat: 3
+ildouble: 2
+ldouble: 2
+Test "jn (10, 2.0) == 0.251538628271673670963516093751820639e-6":
+float: 4
+ifloat: 4
+Test "jn (3, 0.125) == 0.406503832554912875023029337653442868e-4":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "jn (3, 0.75) == 0.848438342327410884392755236884386804e-2":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "jn (3, 10.0) == 0.0583793793051868123429354784103409563":
+double: 3
+float: 1
+idouble: 3
+ifloat: 1
+ildouble: 2
+ldouble: 2
+Test "jn (3, 2.0) == 0.128943249474402051098793332969239835":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+
+# lgamma
+Test "lgamma (-0.5) == log(2*sqrt(pi))":
+ildouble: 1
+ldouble: 1
+Test "lgamma (0.7) == 0.260867246531666514385732417016759578":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "lgamma (1.2) == -0.853740900033158497197028392998854470e-1":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 1
+ldouble: 1
+
+# log10
+Test "log10 (0.75) == -0.124938736608299953132449886193870744":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+Test "log10 (e) == log10(e)":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+# log1p
+Test "log1p (-0.25) == -0.287682072451780927439219005993827432":
+float: 1
+ifloat: 1
+Test "log1p (M_El - 1.0) == 1":
+ildouble: 1
+ldouble: 1
+
+# log2
+Test "log2 (0.75) == -.415037499278843818546261056052183492":
+ildouble: 1
+ldouble: 1
+
+# sincos
+Test "sincos (M_PI_6l*2.0, &sin_res, &cos_res) puts 0.5 in cos_res":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "sincos (M_PI_6l*2.0, &sin_res, &cos_res) puts 0.86602540378443864676372317075293616 in sin_res":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "sincos (pi/2, &sin_res, &cos_res) puts 0 in cos_res":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "sincos (pi/6, &sin_res, &cos_res) puts 0.86602540378443864676372317075293616 in cos_res":
+float: 1
+ifloat: 1
+
+# sqrt
+Test "sqrt (2) == M_SQRT2l":
+ildouble: 1
+ldouble: 1
+
+# tan
+Test "tan (pi/4) == 1":
+double: 1
+idouble: 1
+
+# tanh
+Test "tanh (-0.75) == -0.635148952387287319214434357312496495":
+ildouble: 1
+ldouble: 1
+Test "tanh (-1.0) == -0.7615941559557648881194582826047935904":
+ildouble: 1
+ldouble: 1
+Test "tanh (0.75) == 0.635148952387287319214434357312496495":
+ildouble: 1
+ldouble: 1
+Test "tanh (1.0) == 0.7615941559557648881194582826047935904":
+ildouble: 1
+ldouble: 1
+
+# tgamma
+Test "tgamma (-0.5) == -2 sqrt (pi)":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "tgamma (0.5) == sqrt (pi)":
+float: 1
+ifloat: 1
+Test "tgamma (0.7) == 1.29805533264755778568117117915281162":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "tgamma (4) == 6":
+ildouble: 1
+ldouble: 1
+
+# y0
+Test "y0 (1.0) == 0.0882569642156769579829267660235151628":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+Test "y0 (1.5) == 0.382448923797758843955068554978089862":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+Test "y0 (10.0) == 0.0556711672835993914244598774101900481":
+float: 1
+ifloat: 1
+ildouble: 3
+ldouble: 3
+Test "y0 (8.0) == 0.223521489387566220527323400498620359":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 3
+ldouble: 3
+
+# y1
+Test "y1 (0.125) == -5.19993611253477499595928744876579921":
+double: 1
+idouble: 1
+Test "y1 (0.75) == -1.03759455076928541973767132140642198":
+ildouble: 1
+ldouble: 1
+Test "y1 (1.5) == -0.412308626973911295952829820633445323":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "y1 (10.0) == 0.249015424206953883923283474663222803":
+double: 3
+float: 1
+idouble: 3
+ifloat: 1
+Test "y1 (2.0) == -0.107032431540937546888370772277476637":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "y1 (8.0) == -0.158060461731247494255555266187483550":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 1
+ldouble: 1
+
+# yn
+Test "yn (0, 1.0) == 0.0882569642156769579829267660235151628":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+Test "yn (0, 1.5) == 0.382448923797758843955068554978089862":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+Test "yn (0, 10.0) == 0.0556711672835993914244598774101900481":
+float: 1
+ifloat: 1
+ildouble: 3
+ldouble: 3
+Test "yn (0, 8.0) == 0.223521489387566220527323400498620359":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 3
+ldouble: 3
+Test "yn (1, 0.125) == -5.19993611253477499595928744876579921":
+double: 1
+idouble: 1
+Test "yn (1, 0.75) == -1.03759455076928541973767132140642198":
+ildouble: 1
+ldouble: 1
+Test "yn (1, 1.5) == -0.412308626973911295952829820633445323":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "yn (1, 10.0) == 0.249015424206953883923283474663222803":
+double: 3
+float: 1
+idouble: 3
+ifloat: 1
+Test "yn (1, 2.0) == -0.107032431540937546888370772277476637":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "yn (1, 8.0) == -0.158060461731247494255555266187483550":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 1
+ldouble: 1
+Test "yn (10, 0.125) == -127057845771019398.252538486899753195":
+double: 1
+idouble: 1
+ildouble: 2
+ldouble: 2
+Test "yn (10, 0.75) == -2133501638.90573424452445412893839236":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 5
+ldouble: 5
+Test "yn (10, 1.0) == -121618014.278689189288130426667971145":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+Test "yn (10, 10.0) == -0.359814152183402722051986577343560609":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 2
+ldouble: 2
+Test "yn (10, 2.0) == -129184.542208039282635913145923304214":
+double: 2
+idouble: 2
+ildouble: 2
+ldouble: 2
+Test "yn (3, 0.125) == -2612.69757350066712600220955744091741":
+double: 1
+idouble: 1
+Test "yn (3, 0.75) == -12.9877176234475433186319774484809207":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 2
+ldouble: 2
+Test "yn (3, 10.0) == -0.251362657183837329779204747654240998":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "yn (3, 2.0) == -1.12778377684042778608158395773179238":
+double: 1
+idouble: 1
+
+# Maximal error of functions:
+Function: "atan2":
+float: 6
+ifloat: 6
+ildouble: 1
+ldouble: 1
+
+Function: "atanh":
+float: 1
+ifloat: 1
+
+Function: Imaginary part of "cacos":
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "cacosh":
+double: 1
+float: 7
+idouble: 1
+ifloat: 7
+ildouble: 5
+ldouble: 5
+
+Function: Imaginary part of "cacosh":
+double: 1
+float: 3
+idouble: 1
+ifloat: 3
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "casin":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: Imaginary part of "casin":
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "casinh":
+double: 5
+float: 1
+idouble: 5
+ifloat: 1
+ildouble: 4
+ldouble: 4
+
+Function: Imaginary part of "casinh":
+double: 3
+float: 6
+idouble: 3
+ifloat: 6
+ildouble: 2
+ldouble: 2
+
+Function: Real part of "catan":
+float: 4
+ifloat: 4
+
+Function: Imaginary part of "catan":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "catanh":
+double: 4
+idouble: 4
+ildouble: 1
+ldouble: 1
+
+Function: Imaginary part of "catanh":
+float: 6
+ifloat: 6
+ildouble: 1
+ldouble: 1
+
+Function: "cbrt":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "ccos":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: Imaginary part of "ccos":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "ccosh":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: Imaginary part of "ccosh":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "cexp":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: Imaginary part of "cexp":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "clog":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: Imaginary part of "clog":
+float: 3
+ifloat: 3
+
+Function: Real part of "clog10":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: Imaginary part of "clog10":
+double: 1
+float: 5
+idouble: 1
+ifloat: 5
+ildouble: 1
+ldouble: 1
+
+Function: "cos":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "cpow":
+double: 2
+float: 4
+idouble: 2
+ifloat: 4
+ildouble: 10
+ldouble: 10
+
+Function: Imaginary part of "cpow":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "csin":
+ildouble: 1
+ldouble: 1
+
+Function: Imaginary part of "csin":
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "csinh":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: Imaginary part of "csinh":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: Real part of "csqrt":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: Imaginary part of "csqrt":
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "ctan":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+
+Function: Imaginary part of "ctan":
+double: 1
+idouble: 1
+ildouble: 2
+ldouble: 2
+
+Function: Real part of "ctanh":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 1
+ldouble: 1
+
+Function: Imaginary part of "ctanh":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "erf":
+double: 1
+idouble: 1
+
+Function: "erfc":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+
+Function: "exp10":
+double: 6
+float: 2
+idouble: 6
+ifloat: 2
+ildouble: 1
+ldouble: 1
+
+Function: "exp2":
+ildouble: 2
+ldouble: 2
+
+Function: "expm1":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "gamma":
+ildouble: 1
+ldouble: 1
+
+Function: "hypot":
+float: 1
+ifloat: 1
+
+Function: "j0":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+ildouble: 2
+ldouble: 2
+
+Function: "j1":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 4
+ldouble: 4
+
+Function: "jn":
+double: 4
+float: 4
+idouble: 4
+ifloat: 4
+ildouble: 4
+ldouble: 4
+
+Function: "lgamma":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 1
+ldouble: 1
+
+Function: "log10":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 1
+ldouble: 1
+
+Function: "log1p":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "log2":
+ildouble: 1
+ldouble: 1
+
+Function: "sincos":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "sqrt":
+ildouble: 1
+ldouble: 1
+
+Function: "tan":
+double: 1
+idouble: 1
+
+Function: "tanh":
+ildouble: 1
+ldouble: 1
+
+Function: "tgamma":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "y0":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+ildouble: 3
+ldouble: 3
+
+Function: "y1":
+double: 3
+float: 2
+idouble: 3
+ifloat: 2
+ildouble: 1
+ldouble: 1
+
+Function: "yn":
+double: 3
+float: 2
+idouble: 3
+ifloat: 2
+ildouble: 5
+ldouble: 5
+
+# end of automatic generation
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/math/libm-test-ulps-x86_64 b/l4/pkg/uclibc/lib/contrib/uclibc/test/math/libm-test-ulps-x86_64
new file mode 100644
index 00000000..0ced4be7
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/math/libm-test-ulps-x86_64
@@ -0,0 +1,1308 @@
+# Begin of automatic generation
+
+# acos
+Test "acos (0.75) == 0.722734247813415611178377352641333362":
+ildouble: 1
+ldouble: 1
+
+# asin
+Test "asin (-0.5) == -pi/6":
+ildouble: 1
+ldouble: 1
+Test "asin (-1.0) == -pi/2":
+ildouble: 1
+ldouble: 1
+Test "asin (0.5) == pi/6":
+ildouble: 1
+ldouble: 1
+Test "asin (0.75) == 0.848062078981481008052944338998418080":
+ildouble: 1
+ldouble: 1
+Test "asin (1.0) == pi/2":
+ildouble: 1
+ldouble: 1
+
+# atan2
+Test "atan2 (-0.75, -1.0) == -2.49809154479650885165983415456218025":
+float: 1
+ifloat: 1
+Test "atan2 (0.75, -1.0) == 2.49809154479650885165983415456218025":
+float: 1
+ifloat: 1
+Test "atan2 (1.390625, 0.9296875) == 0.981498387184244311516296577615519772":
+float: 1
+ifloat: 1
+
+# atanh
+Test "atanh (0.75) == 0.972955074527656652552676371721589865":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+# cacos
+Test "Imaginary part of: cacos (0.75 + 1.25 i) == 1.11752014915610270578240049553777969 - 1.13239363160530819522266333696834467 i":
+float: 1
+ifloat: 1
+ildouble: 2
+ldouble: 2
+
+# cacosh
+Test "Real part of: cacosh (-2 - 3 i) == 1.9833870299165354323470769028940395 - 2.1414491111159960199416055713254211 i":
+double: 1
+float: 7
+idouble: 1
+ifloat: 7
+ildouble: 6
+ldouble: 6
+Test "Imaginary part of: cacosh (-2 - 3 i) == 1.9833870299165354323470769028940395 - 2.1414491111159960199416055713254211 i":
+double: 1
+float: 3
+idouble: 1
+ifloat: 3
+ildouble: 1
+ldouble: 1
+Test "Real part of: cacosh (0.75 + 1.25 i) == 1.13239363160530819522266333696834467 + 1.11752014915610270578240049553777969 i":
+ildouble: 1
+ldouble: 1
+
+# casin
+Test "Real part of: casin (0.75 + 1.25 i) == 0.453276177638793913448921196101971749 + 1.13239363160530819522266333696834467 i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 2
+ldouble: 2
+Test "Imaginary part of: casin (0.75 + 1.25 i) == 0.453276177638793913448921196101971749 + 1.13239363160530819522266333696834467 i":
+float: 1
+ifloat: 1
+ildouble: 2
+ldouble: 2
+
+# casinh
+Test "Real part of: casinh (-2 - 3 i) == -1.9686379257930962917886650952454982 - 0.96465850440760279204541105949953237 i":
+double: 5
+float: 1
+idouble: 5
+ifloat: 1
+ildouble: 5
+ldouble: 5
+Test "Imaginary part of: casinh (-2 - 3 i) == -1.9686379257930962917886650952454982 - 0.96465850440760279204541105949953237 i":
+double: 3
+float: 6
+idouble: 3
+ifloat: 6
+ildouble: 5
+ldouble: 5
+Test "Real part of: casinh (0.75 + 1.25 i) == 1.03171853444778027336364058631006594 + 0.911738290968487636358489564316731207 i":
+float: 1
+ifloat: 1
+Test "Imaginary part of: casinh (0.75 + 1.25 i) == 1.03171853444778027336364058631006594 + 0.911738290968487636358489564316731207 i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ldouble: 1
+ildouble: 1
+
+# catan
+Test "Real part of: catan (-2 - 3 i) == -1.4099210495965755225306193844604208 - 0.22907268296853876629588180294200276 i":
+float: 3
+ifloat: 3
+Test "Imaginary part of: catan (-2 - 3 i) == -1.4099210495965755225306193844604208 - 0.22907268296853876629588180294200276 i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Real part of: catan (0.75 + 1.25 i) == 1.10714871779409050301706546017853704 + 0.549306144334054845697622618461262852 i":
+float: 4
+ifloat: 4
+
+# catanh
+Test "Real part of: catanh (-2 - 3 i) == -0.14694666622552975204743278515471595 - 1.3389725222944935611241935759091443 i":
+double: 4
+idouble: 4
+ildouble: 1
+ldouble: 1
+Test "Imaginary part of: catanh (-2 - 3 i) == -0.14694666622552975204743278515471595 - 1.3389725222944935611241935759091443 i":
+float: 4
+ifloat: 4
+Test "Real part of: catanh (0.75 + 1.25 i) == 0.261492138795671927078652057366532140 + 0.996825126463918666098902241310446708 i":
+double: 1
+idouble: 1
+Test "Imaginary part of: catanh (0.75 + 1.25 i) == 0.261492138795671927078652057366532140 + 0.996825126463918666098902241310446708 i":
+float: 6
+ifloat: 6
+
+# cbrt
+Test "cbrt (-0.001) == -0.1":
+ildouble: 1
+ldouble: 1
+Test "cbrt (-27.0) == -3.0":
+double: 1
+idouble: 1
+Test "cbrt (0.75) == 0.908560296416069829445605878163630251":
+double: 1
+idouble: 1
+Test "cbrt (0.9921875) == 0.997389022060725270579075195353955217":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+
+# ccos
+Test "Real part of: ccos (-2 - 3 i) == -4.18962569096880723013255501961597373 - 9.10922789375533659797919726277886212 i":
+double: 1
+idouble: 1
+Test "Imaginary part of: ccos (-2 - 3 i) == -4.18962569096880723013255501961597373 - 9.10922789375533659797919726277886212 i":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "Real part of: ccos (0.75 + 1.25 i) == 1.38173873063425888530729933139078645 - 1.09193013555397466170919531722024128 i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "Imaginary part of: ccos (0.75 + 1.25 i) == 1.38173873063425888530729933139078645 - 1.09193013555397466170919531722024128 i":
+ildouble: 1
+ldouble: 1
+float: 1
+ifloat: 1
+
+# ccosh
+Test "Real part of: ccosh (-2 - 3 i) == -3.72454550491532256547397070325597253 + 0.511822569987384608834463849801875634 i":
+float: 1
+ifloat: 1
+Test "Imaginary part of: ccosh (-2 - 3 i) == -3.72454550491532256547397070325597253 + 0.511822569987384608834463849801875634 i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "Real part of: ccosh (0.75 + 1.25 i) == 0.408242591877968807788852146397499084 + 0.780365930845853240391326216300863152 i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: ccosh (0.75 + 1.25 i) == 0.408242591877968807788852146397499084 + 0.780365930845853240391326216300863152 i":
+float: 1
+ifloat: 1
+
+# cexp
+Test "Imaginary part of: cexp (-2.0 - 3.0 i) == -0.13398091492954261346140525546115575 - 0.019098516261135196432576240858800925 i":
+float: 1
+ifloat: 1
+Test "Real part of: cexp (0.75 + 1.25 i) == 0.667537446429131586942201977015932112 + 2.00900045494094876258347228145863909 i":
+float: 1
+ifloat: 1
+Test "Imaginary part of: cexp (0.75 + 1.25 i) == 0.667537446429131586942201977015932112 + 2.00900045494094876258347228145863909 i":
+ildouble: 1
+ldouble: 1
+
+# clog
+Test "Imaginary part of: clog (-2 - 3 i) == 1.2824746787307683680267437207826593 - 2.1587989303424641704769327722648368 i":
+float: 3
+ifloat: 3
+Test "Real part of: clog (0.75 + 1.25 i) == 0.376885901188190075998919126749298416 + 1.03037682652431246378774332703115153 i":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+# clog10
+Test "Imaginary part of: clog10 (-0 + inf i) == inf + pi/2*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (-0 - inf i) == inf - pi/2*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (-2 - 3 i) == 0.556971676153418384603252578971164214 - 0.937554462986374708541507952140189646 i":
+double: 1
+float: 5
+idouble: 1
+ifloat: 5
+ildouble: 1
+ldouble: 1
+Test "Imaginary part of: clog10 (-3 + inf i) == inf + pi/2*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (-3 - inf i) == inf - pi/2*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (-inf + 0 i) == inf + pi*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (-inf + 1 i) == inf + pi*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (-inf + inf i) == inf + 3/4 pi*log10(e) i":
+double: 1
+idouble: 1
+Test "Imaginary part of: clog10 (-inf - 0 i) == inf - pi*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (-inf - 1 i) == inf - pi*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (0 + inf i) == inf + pi/2*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (0 - inf i) == inf - pi/2*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Real part of: clog10 (0.75 + 1.25 i) == 0.163679467193165171449476605077428975 + 0.447486970040493067069984724340855636 i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "Imaginary part of: clog10 (3 + inf i) == inf + pi/2*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (3 - inf i) == inf - pi/2*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (inf + inf i) == inf + pi/4*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "Imaginary part of: clog10 (inf - inf i) == inf - pi/4*log10(e) i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+# cos
+Test "cos (M_PI_6l * 2.0) == 0.5":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "cos (M_PI_6l * 4.0) == -0.5":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "cos (pi/2) == 0":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "cos (0.80190127184058835) == 0.69534156199418473":
+double: 1
+idouble: 1
+
+# cpow
+Test "Real part of: cpow (0.75 + 1.25 i, 0.0 + 1.0 i) == 0.331825439177608832276067945276730566 + 0.131338600281188544930936345230903032 i":
+float: 1
+ifloat: 1
+ldouble: 1
+ildouble: 1
+Test "Imaginary part of: cpow (0.75 + 1.25 i, 0.0 + 1.0 i) == 0.331825439177608832276067945276730566 + 0.131338600281188544930936345230903032 i":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "Real part of: cpow (0.75 + 1.25 i, 0.75 + 1.25 i) == 0.117506293914473555420279832210420483 + 0.346552747708338676483025352060418001 i":
+double: 1
+float: 4
+idouble: 1
+ifloat: 4
+ildouble: 5
+ldouble: 5
+Test "Imaginary part of: cpow (0.75 + 1.25 i, 0.75 + 1.25 i) == 0.117506293914473555420279832210420483 + 0.346552747708338676483025352060418001 i":
+ildouble: 2
+ldouble: 2
+Test "Real part of: cpow (0.75 + 1.25 i, 1.0 + 0.0 i) == 0.75 + 1.25 i":
+ildouble: 1
+ldouble: 1
+Test "Real part of: cpow (0.75 + 1.25 i, 1.0 + 1.0 i) == 0.0846958290317209430433805274189191353 + 0.513285749182902449043287190519090481 i":
+double: 2
+float: 3
+idouble: 2
+ifloat: 3
+ildouble: 3
+ldouble: 3
+Test "Real part of: cpow (2 + 0 i, 10 + 0 i) == 1024.0 + 0.0 i":
+ildouble: 1
+ldouble: 1
+Test "Real part of: cpow (2 + 3 i, 4 + 0 i) == -119.0 - 120.0 i":
+double: 1
+float: 5
+idouble: 1
+ifloat: 5
+Test "Imaginary part of: cpow (2 + 3 i, 4 + 0 i) == -119.0 - 120.0 i":
+float: 2
+ifloat: 2
+ildouble: 2
+ldouble: 2
+Test "Imaginary part of: cpow (e + 0 i, 0 + 2 * M_PIl i) == 1.0 + 0.0 i":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+ildouble: 1
+ldouble: 1
+
+# csin
+Test "Real part of: csin (0.75 + 1.25 i) == 1.28722291002649188575873510790565441 + 1.17210635989270256101081285116138863 i":
+ildouble: 1
+ldouble: 1
+Test "Imaginary part of: csin (0.75 + 1.25 i) == 1.28722291002649188575873510790565441 + 1.17210635989270256101081285116138863 i":
+float: 1
+ifloat: 1
+Test "Imaginary part of: csin (-2 - 3 i) == -9.15449914691142957346729954460983256 + 4.16890695996656435075481305885375484 i":
+double: 1
+idouble: 1
+
+# csinh
+Test "Real part of: csinh (-2 - 3 i) == 3.59056458998577995201256544779481679 - 0.530921086248519805267040090660676560 i":
+double: 1
+idouble: 1
+Test "Imaginary part of: csinh (-2 - 3 i) == 3.59056458998577995201256544779481679 - 0.530921086248519805267040090660676560 i":
+double: 1
+idouble: 1
+ildouble: 2
+ldouble: 2
+Test "Real part of: csinh (0.75 + 1.25 i) == 0.259294854551162779153349830618433028 + 1.22863452409509552219214606515777594 i":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "Imaginary part of: csinh (0.75 + 1.25 i) == 0.259294854551162779153349830618433028 + 1.22863452409509552219214606515777594 i":
+float: 1
+ifloat: 1
+
+# csqrt
+Test "Real part of: csqrt (-2 + 3 i) == 0.89597747612983812471573375529004348 + 1.6741492280355400404480393008490519 i":
+float: 1
+ifloat: 1
+Test "Real part of: csqrt (-2 - 3 i) == 0.89597747612983812471573375529004348 - 1.6741492280355400404480393008490519 i":
+float: 1
+ifloat: 1
+
+# ctan
+Test "Real part of: ctan (-2 - 3 i) == 0.376402564150424829275122113032269084e-2 - 1.00323862735360980144635859782192726 i":
+double: 1
+idouble: 1
+ildouble: 439
+ldouble: 439
+Test "Imaginary part of: ctan (-2 - 3 i) == 0.376402564150424829275122113032269084e-2 - 1.00323862735360980144635859782192726 i":
+float: 1
+ifloat: 1
+ildouble: 2
+ldouble: 2
+Test "Real part of: ctan (0.75 + 1.25 i) == 0.160807785916206426725166058173438663 + 0.975363285031235646193581759755216379 i":
+ildouble: 1
+ldouble: 1
+Test "Imaginary part of: ctan (0.75 + 1.25 i) == 0.160807785916206426725166058173438663 + 0.975363285031235646193581759755216379 i":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 3
+ldouble: 3
+
+# ctanh
+Test "Real part of: ctanh (-2 - 3 i) == -0.965385879022133124278480269394560686 + 0.988437503832249372031403430350121098e-2 i":
+float: 2
+ifloat: 2
+ildouble: 5
+ldouble: 5
+double: 1
+idouble: 1
+Test "Imaginary part of: ctanh (-2 - 3 i) == -0.965385879022133124278480269394560686 + 0.988437503832249372031403430350121098e-2 i":
+ildouble: 25
+ldouble: 25
+Test "Imaginary part of: ctanh (0 + pi/4 i) == 0.0 + 1.0 i":
+float: 1
+ifloat: 1
+Test "Real part of: ctanh (0.75 + 1.25 i) == 1.37260757053378320258048606571226857 + 0.385795952609750664177596760720790220 i":
+double: 1
+idouble: 1
+Test "Imaginary part of: ctanh (0.75 + 1.25 i) == 1.37260757053378320258048606571226857 + 0.385795952609750664177596760720790220 i":
+ildouble: 1
+ldouble: 1
+double: 1
+idouble: 1
+
+# erf
+Test "erf (1.25) == 0.922900128256458230136523481197281140":
+double: 1
+idouble: 1
+
+# erfc
+Test "erfc (1.25) == 0.0770998717435417698634765188027188596":
+ildouble: 1
+ldouble: 1
+Test "erfc (2.0) == 0.00467773498104726583793074363274707139":
+double: 1
+idouble: 1
+Test "erfc (4.125) == 0.542340079956506600531223408575531062e-8":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+
+# exp10
+Test "exp10 (-1) == 0.1":
+ildouble: 1
+ldouble: 1
+float: 1
+ifloat: 1
+double: 2
+idouble: 2
+Test "exp10 (0.75) == 5.62341325190349080394951039776481231":
+ildouble: 2
+ldouble: 2
+float: 1
+ifloat: 1
+double: 1
+idouble: 1
+Test "exp10 (3) == 1000":
+ildouble: 8
+ldouble: 8
+float: 2
+ifloat: 2
+double: 6
+idouble: 6
+
+# expm1
+Test "expm1 (0.75) == 1.11700001661267466854536981983709561":
+double: 1
+idouble: 1
+Test "expm1 (1) == M_El - 1.0":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+# gamma
+Test "gamma (-0.5) == log(2*sqrt(pi))":
+ildouble: 1
+ldouble: 1
+
+# hypot
+Test "hypot (-0.7, -12.4) == 12.419742348374220601176836866763271":
+float: 1
+ifloat: 1
+Test "hypot (-0.7, 12.4) == 12.419742348374220601176836866763271":
+float: 1
+ifloat: 1
+Test "hypot (-12.4, -0.7) == 12.419742348374220601176836866763271":
+float: 1
+ifloat: 1
+Test "hypot (-12.4, 0.7) == 12.419742348374220601176836866763271":
+float: 1
+ifloat: 1
+Test "hypot (0.7, -12.4) == 12.419742348374220601176836866763271":
+float: 1
+ifloat: 1
+Test "hypot (0.7, 12.4) == 12.419742348374220601176836866763271":
+float: 1
+ifloat: 1
+Test "hypot (12.4, -0.7) == 12.419742348374220601176836866763271":
+float: 1
+ifloat: 1
+Test "hypot (12.4, 0.7) == 12.419742348374220601176836866763271":
+float: 1
+ifloat: 1
+
+# j0
+Test "j0 (-4.0) == -3.9714980986384737228659076845169804197562E-1":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "j0 (0.75) == 0.864242275166648623555731103820923211":
+float: 1
+ifloat: 1
+Test "j0 (10.0) == -0.245935764451348335197760862485328754":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+Test "j0 (2.0) == 0.223890779141235668051827454649948626":
+float: 2
+ifloat: 2
+Test "j0 (4.0) == -3.9714980986384737228659076845169804197562E-1":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "j0 (8.0) == 0.171650807137553906090869407851972001":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+
+# j1
+Test "j1 (10.0) == 0.0434727461688614366697487680258592883":
+float: 2
+ifloat: 2
+ildouble: 1
+ldouble: 1
+Test "j1 (2.0) == 0.576724807756873387202448242269137087":
+double: 1
+idouble: 1
+Test "j1 (8.0) == 0.234636346853914624381276651590454612":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+
+# jn
+Test "jn (0, -4.0) == -3.9714980986384737228659076845169804197562E-1":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "jn (0, 0.75) == 0.864242275166648623555731103820923211":
+float: 1
+ifloat: 1
+Test "jn (0, 10.0) == -0.245935764451348335197760862485328754":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+Test "jn (0, 2.0) == 0.223890779141235668051827454649948626":
+float: 2
+ifloat: 2
+Test "jn (0, 4.0) == -3.9714980986384737228659076845169804197562E-1":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "jn (0, 8.0) == 0.171650807137553906090869407851972001":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+Test "jn (1, 10.0) == 0.0434727461688614366697487680258592883":
+float: 2
+ifloat: 2
+ildouble: 1
+ldouble: 1
+Test "jn (1, 2.0) == 0.576724807756873387202448242269137087":
+double: 1
+idouble: 1
+Test "jn (1, 8.0) == 0.234636346853914624381276651590454612":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+Test "jn (10, -1.0) == 0.263061512368745320699785368779050294e-9":
+ildouble: 1
+ldouble: 1
+Test "jn (10, 0.125) == 0.250543369809369890173993791865771547e-18":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "jn (10, 0.75) == 0.149621713117596814698712483621682835e-10":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 2
+ldouble: 2
+Test "jn (10, 1.0) == 0.263061512368745320699785368779050294e-9":
+ildouble: 1
+ldouble: 1
+Test "jn (10, 10.0) == 0.207486106633358857697278723518753428":
+double: 4
+float: 3
+idouble: 4
+ifloat: 3
+ildouble: 2
+ldouble: 2
+Test "jn (10, 2.0) == 0.251538628271673670963516093751820639e-6":
+float: 4
+ifloat: 4
+ildouble: 1
+ldouble: 1
+Test "jn (3, -1.0) == -0.0195633539826684059189053216217515083":
+ildouble: 1
+ldouble: 1
+Test "jn (3, 0.125) == 0.406503832554912875023029337653442868e-4":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "jn (3, 0.75) == 0.848438342327410884392755236884386804e-2":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "jn (3, 1.0) == 0.0195633539826684059189053216217515083":
+ildouble: 1
+ldouble: 1
+Test "jn (3, 10.0) == 0.0583793793051868123429354784103409563":
+double: 3
+float: 1
+idouble: 3
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "jn (3, 2.0) == 0.128943249474402051098793332969239835":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 1
+ldouble: 1
+
+# lgamma
+Test "lgamma (-0.5) == log(2*sqrt(pi))":
+ildouble: 1
+ldouble: 1
+Test "lgamma (0.7) == 0.260867246531666514385732417016759578":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "lgamma (1.2) == -0.853740900033158497197028392998854470e-1":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 1
+ldouble: 1
+
+# log10
+Test "log10 (0.75) == -0.124938736608299953132449886193870744":
+ildouble: 1
+ldouble: 1
+float: 2
+ifloat: 2
+double: 1
+idouble: 1
+Test "log10 (e) == log10(e)":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+# log1p
+Test "log1p (-0.25) == -0.287682072451780927439219005993827432":
+float: 1
+ifloat: 1
+
+# sincos
+Test "sincos (M_PI_6l*2.0, &sin_res, &cos_res) puts 0.5 in cos_res":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "sincos (M_PI_6l*2.0, &sin_res, &cos_res) puts 0.86602540378443864676372317075293616 in sin_res":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "sincos (pi/2, &sin_res, &cos_res) puts 0 in cos_res":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "sincos (pi/6, &sin_res, &cos_res) puts 0.86602540378443864676372317075293616 in cos_res":
+float: 1
+ifloat: 1
+Test "sincos (0.80190127184058835, &sin_res, &cos_res) puts 0.69534156199418473 in cos_res":
+double: 1
+idouble: 1
+
+# tan
+Test "tan (pi/4) == 1":
+double: 1
+idouble: 1
+
+# tgamma
+Test "tgamma (-0.5) == -2 sqrt (pi)":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "tgamma (0.5) == sqrt (pi)":
+float: 1
+ifloat: 1
+Test "tgamma (0.7) == 1.29805533264755778568117117915281162":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "tgamma (4) == 6":
+ildouble: 1
+ldouble: 1
+
+# y0
+Test "y0 (0.125) == -1.38968062514384052915582277745018693":
+ildouble: 1
+ldouble: 1
+Test "y0 (1.0) == 0.0882569642156769579829267660235151628":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "y0 (1.5) == 0.382448923797758843955068554978089862":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+Test "y0 (10.0) == 0.0556711672835993914244598774101900481":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "y0 (8.0) == 0.223521489387566220527323400498620359":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+# y1
+Test "y1 (0.125) == -5.19993611253477499595928744876579921":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+Test "y1 (1.5) == -0.412308626973911295952829820633445323":
+float: 1
+ifloat: 1
+Test "y1 (10.0) == 0.249015424206953883923283474663222803":
+double: 3
+float: 1
+idouble: 3
+ifloat: 1
+Test "y1 (2.0) == -0.107032431540937546888370772277476637":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "y1 (8.0) == -0.158060461731247494255555266187483550":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 1
+ldouble: 1
+
+# yn
+Test "yn (0, 0.125) == -1.38968062514384052915582277745018693":
+ildouble: 1
+ldouble: 1
+Test "yn (0, 1.0) == 0.0882569642156769579829267660235151628":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "yn (0, 1.5) == 0.382448923797758843955068554978089862":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+Test "yn (0, 10.0) == 0.0556711672835993914244598774101900481":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "yn (0, 8.0) == 0.223521489387566220527323400498620359":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "yn (1, 0.125) == -5.19993611253477499595928744876579921":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+Test "yn (1, 1.5) == -0.412308626973911295952829820633445323":
+float: 1
+ifloat: 1
+Test "yn (1, 10.0) == 0.249015424206953883923283474663222803":
+double: 3
+float: 1
+idouble: 3
+ifloat: 1
+Test "yn (1, 2.0) == -0.107032431540937546888370772277476637":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "yn (1, 8.0) == -0.158060461731247494255555266187483550":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 1
+ldouble: 1
+Test "yn (10, 0.125) == -127057845771019398.252538486899753195":
+double: 1
+idouble: 1
+ildouble: 2
+ldouble: 2
+Test "yn (10, 0.75) == -2133501638.90573424452445412893839236":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 4
+ldouble: 4
+Test "yn (10, 1.0) == -121618014.278689189288130426667971145":
+double: 1
+idouble: 1
+Test "yn (10, 10.0) == -0.359814152183402722051986577343560609":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "yn (10, 2.0) == -129184.542208039282635913145923304214":
+double: 2
+idouble: 2
+Test "yn (3, 0.125) == -2612.69757350066712600220955744091741":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+Test "yn (3, 0.75) == -12.9877176234475433186319774484809207":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 2
+ldouble: 2
+Test "yn (3, 10.0) == -0.251362657183837329779204747654240998":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "yn (3, 2.0) == -1.12778377684042778608158395773179238":
+double: 1
+idouble: 1
+
+# Maximal error of functions:
+Function: "acos":
+ildouble: 1
+ldouble: 1
+
+Function: "asin":
+ildouble: 1
+ldouble: 1
+
+Function: "atan2":
+float: 1
+ifloat: 1
+
+Function: "atanh":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: Imaginary part of "cacos":
+float: 1
+ifloat: 1
+ildouble: 2
+ldouble: 2
+
+Function: Real part of "cacosh":
+double: 1
+float: 7
+idouble: 1
+ifloat: 7
+ildouble: 6
+ldouble: 6
+
+Function: Imaginary part of "cacosh":
+double: 1
+float: 3
+idouble: 1
+ifloat: 3
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "casin":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 2
+ldouble: 2
+
+Function: Imaginary part of "casin":
+float: 1
+ifloat: 1
+ildouble: 2
+ldouble: 2
+
+Function: Real part of "casinh":
+double: 5
+float: 1
+idouble: 5
+ifloat: 1
+ildouble: 5
+ldouble: 5
+
+Function: Imaginary part of "casinh":
+double: 3
+float: 6
+idouble: 3
+ifloat: 6
+ildouble: 5
+ldouble: 5
+
+Function: Real part of "catan":
+float: 4
+ifloat: 4
+
+Function: Imaginary part of "catan":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: Real part of "catanh":
+double: 4
+idouble: 4
+ildouble: 1
+ldouble: 1
+
+Function: Imaginary part of "catanh":
+float: 6
+ifloat: 6
+
+Function: "cbrt":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "ccos":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: Imaginary part of "ccos":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "ccosh":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: Imaginary part of "ccosh":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "cexp":
+float: 1
+ifloat: 1
+
+Function: Imaginary part of "cexp":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "clog":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: Imaginary part of "clog":
+float: 3
+ifloat: 3
+
+Function: Real part of "clog10":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: Imaginary part of "clog10":
+double: 1
+float: 5
+idouble: 1
+ifloat: 5
+ildouble: 1
+ldouble: 1
+
+Function: "cos":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: Real part of "cpow":
+double: 2
+float: 5
+idouble: 2
+ifloat: 5
+ildouble: 5
+ldouble: 5
+
+Function: Imaginary part of "cpow":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+ildouble: 2
+ldouble: 2
+
+Function: Real part of "csin":
+ildouble: 1
+ldouble: 1
+
+Function: Imaginary part of "csin":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: Real part of "csinh":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: Imaginary part of "csinh":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 2
+ldouble: 2
+
+Function: Real part of "csqrt":
+float: 1
+ifloat: 1
+
+Function: Real part of "ctan":
+double: 1
+idouble: 1
+ildouble: 439
+ldouble: 439
+
+Function: Imaginary part of "ctan":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 3
+ldouble: 3
+
+Function: Real part of "ctanh":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 5
+ldouble: 5
+
+Function: Imaginary part of "ctanh":
+float: 1
+ifloat: 1
+ildouble: 25
+ldouble: 25
+double: 1
+idouble: 1
+
+Function: "erf":
+double: 1
+idouble: 1
+
+Function: "erfc":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+
+Function: "exp10":
+ildouble: 8
+ldouble: 8
+float: 2
+ifloat: 2
+double: 6
+idouble: 6
+
+Function: "expm1":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+Function: "gamma":
+ildouble: 1
+ldouble: 1
+
+Function: "hypot":
+float: 1
+ifloat: 1
+
+Function: "j0":
+double: 2
+float: 2
+idouble: 2
+ifloat: 2
+ildouble: 1
+ldouble: 1
+
+Function: "j1":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 1
+ldouble: 1
+
+Function: "jn":
+double: 4
+float: 4
+idouble: 4
+ifloat: 4
+ildouble: 2
+ldouble: 2
+
+Function: "lgamma":
+double: 1
+float: 2
+idouble: 1
+ifloat: 2
+ildouble: 1
+ldouble: 1
+
+Function: "log10":
+float: 2
+ifloat: 2
+ildouble: 1
+ldouble: 1
+double: 1
+idouble: 1
+
+Function: "log1p":
+float: 1
+ifloat: 1
+
+Function: "sincos":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "tan":
+double: 1
+idouble: 1
+
+Function: "tgamma":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "y0":
+double: 2
+float: 1
+idouble: 2
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "y1":
+double: 3
+float: 2
+idouble: 3
+ifloat: 2
+ildouble: 1
+ldouble: 1
+
+Function: "yn":
+double: 3
+float: 2
+idouble: 3
+ifloat: 2
+ildouble: 4
+ldouble: 4
+
+# end of automatic generation
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/math/libm-test.inc b/l4/pkg/uclibc/lib/contrib/uclibc/test/math/libm-test.inc
new file mode 100644
index 00000000..59555669
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/math/libm-test.inc
@@ -0,0 +1,5109 @@
+/* Copyright (C) 1997-2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Andreas Jaeger , 1997.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+/* Part of testsuite for libm.
+
+   This file is processed by a perl script.  The resulting file has to
+   be included by a master file that defines:
+
+   Macros:
+   FUNC(function): converts general function name (like cos) to
+   name with correct suffix (e.g. cosl or cosf)
+   MATHCONST(x):   like FUNC but for constants (e.g convert 0.0 to 0.0L)
+   FLOAT:          floating point type to test
+   - TEST_MSG:     informal message to be displayed
+   CHOOSE(Clongdouble,Cdouble,Cfloat,Cinlinelongdouble,Cinlinedouble,Cinlinefloat):
+   chooses one of the parameters as delta for testing
+   equality
+   PRINTF_EXPR     Floating point conversion specification to print a variable
+   of type FLOAT with printf.  PRINTF_EXPR just contains
+   the specifier, not the percent and width arguments,
+   e.g. "f".
+   PRINTF_XEXPR	   Like PRINTF_EXPR, but print in hexadecimal format.
+   PRINTF_NEXPR    Like PRINTF_EXPR, but print nice.  */
+
+/* This testsuite has currently tests for:
+   acos, acosh, asin, asinh, atan, atan2, atanh,
+   cbrt, ceil, copysign, cos, cosh, erf, erfc, exp, exp10, exp2, expm1,
+   fabs, fdim, floor, fma, fmax, fmin, fmod, fpclassify,
+   frexp, gamma, hypot,
+   ilogb, isfinite, isinf, isnan, isnormal,
+   isless, islessequal, isgreater, isgreaterequal, islessgreater, isunordered,
+   j0, j1, jn,
+   ldexp, lgamma, log, log10, log1p, log2, logb,
+   modf, nearbyint, nextafter,
+   pow, remainder, remquo, rint, lrint, llrint,
+   round, lround, llround,
+   scalb, scalbn, scalbln, signbit, sin, sincos, sinh, sqrt, tan, tanh, tgamma, trunc,
+   y0, y1, yn, significand
+
+   and for the following complex math functions:
+   cabs, cacos, cacosh, carg, casin, casinh, catan, catanh,
+   ccos, ccosh, cexp, clog, cpow, cproj, csin, csinh, csqrt, ctan, ctanh.
+
+   At the moment the following functions aren't tested:
+   drem, nan
+
+   Parameter handling is primitive in the moment:
+   --verbose=[0..3] for different levels of output:
+   0: only error count
+   1: basic report on failed tests (default)
+   2: full report on all tests
+   -v for full output (equals --verbose=3)
+   -u for generation of an ULPs file
+ */
+
+/* "Philosophy":
+
+   This suite tests some aspects of the correct implementation of
+   mathematical functions in libm.  Some simple, specific parameters
+   are tested for correctness but there's no exhaustive
+   testing.  Handling of specific inputs (e.g. infinity, not-a-number)
+   is also tested.  Correct handling of exceptions is checked
+   against.  These implemented tests should check all cases that are
+   specified in ISO C99.
+
+   Exception testing: At the moment only divide-by-zero and invalid
+   exceptions are tested.  Overflow/underflow and inexact exceptions
+   aren't checked at the moment.
+
+   NaN values: There exist signalling and quiet NaNs.  This implementation
+   only uses quiet NaN as parameter but does not differenciate
+   between the two kinds of NaNs as result.
+
+   Inline functions: Inlining functions should give an improvement in
+   speed - but not in precission.  The inlined functions return
+   reasonable values for a reasonable range of input values.  The
+   result is not necessarily correct for all values and exceptions are
+   not correctly raised in all cases.  Problematic input and return
+   values are infinity, not-a-number and minus zero.  This suite
+   therefore does not check these specific inputs and the exception
+   handling for inlined mathematical functions - just the "reasonable"
+   values are checked.
+
+   Beware: The tests might fail for any of the following reasons:
+   - Tests are wrong
+   - Functions are wrong
+   - Floating Point Unit not working properly
+   - Compiler has errors
+
+   With e.g. gcc 2.7.2.2 the test for cexp fails because of a compiler error.
+
+
+   To Do: All parameter should be numbers that can be represented as
+   exact floating point values.  Currently some values cannot be
+   represented exactly and therefore the result is not the expected
+   result.  For this we will use 36 digits so that numbers can be
+   represented exactly.  */
+
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE
+#endif
+
+#include "libm-test-ulps.h"
+#include 
+#include 
+#include 
+#include "fenv.h"
+#include 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/* Possible exceptions */
+#define NO_EXCEPTION			0x0
+#define INVALID_EXCEPTION		0x1
+#define DIVIDE_BY_ZERO_EXCEPTION	0x2
+/* The next flags signals that those exceptions are allowed but not required.   */
+#define INVALID_EXCEPTION_OK		0x4
+#define DIVIDE_BY_ZERO_EXCEPTION_OK	0x8
+#define EXCEPTIONS_OK INVALID_EXCEPTION_OK+DIVIDE_BY_ZERO_EXCEPTION_OK
+/* Some special test flags, passed togther with exceptions.  */
+#define IGNORE_ZERO_INF_SIGN		0x10
+
+/* Various constants (we must supply them precalculated for accuracy).  */
+#define M_PI_6l			.52359877559829887307710723054658383L
+#define M_E2l			7.389056098930650227230427460575008L
+#define M_E3l			20.085536923187667740928529654581719L
+#define M_2_SQRT_PIl		3.5449077018110320545963349666822903L	/* 2 sqrt (M_PIl)  */
+#define M_SQRT_PIl		1.7724538509055160272981674833411451L	/* sqrt (M_PIl)  */
+#define M_LOG_SQRT_PIl		0.57236494292470008707171367567652933L	/* log(sqrt(M_PIl))  */
+#define M_LOG_2_SQRT_PIl	1.265512123484645396488945797134706L	/* log(2*sqrt(M_PIl))  */
+#define M_PI_34l		(M_PIl - M_PI_4l)		/* 3*pi/4 */
+#define M_PI_34_LOG10El		(M_PIl - M_PI_4l) * M_LOG10El
+#define M_PI2_LOG10El		M_PI_2l * M_LOG10El
+#define M_PI4_LOG10El		M_PI_4l * M_LOG10El
+#define M_PI_LOG10El		M_PIl * M_LOG10El
+#define M_SQRT_2_2		0.70710678118654752440084436210484903L /* sqrt (2) / 2 */
+
+static FILE *ulps_file;	/* File to document difference.  */
+static int output_ulps;	/* Should ulps printed?  */
+
+static int noErrors;	/* number of errors */
+static int noTests;	/* number of tests (without testing exceptions) */
+static int noExcTests;	/* number of tests for exception flags */
+static int noXFails;	/* number of expected failures.  */
+static int noXPasses;	/* number of unexpected passes.  */
+
+static int verbose;
+static int output_max_error;	/* Should the maximal errors printed?  */
+static int output_points;	/* Should the single function results printed?  */
+static int ignore_max_ulp;	/* Should we ignore max_ulp?  */
+
+static FLOAT minus_zero, plus_zero;
+static FLOAT plus_infty, minus_infty, nan_value, max_value, min_value;
+
+static FLOAT max_error, real_max_error, imag_max_error;
+
+
+#define BUILD_COMPLEX(real, imag) \
+  ({ __complex__ FLOAT __retval;					      \
+     __real__ __retval = (real);					      \
+     __imag__ __retval = (imag);					      \
+     __retval; })
+
+#define BUILD_COMPLEX_INT(real, imag) \
+  ({ __complex__ int __retval;						      \
+     __real__ __retval = (real);					      \
+     __imag__ __retval = (imag);					      \
+     __retval; })
+
+
+#define MANT_DIG CHOOSE ((LDBL_MANT_DIG-1), (DBL_MANT_DIG-1), (FLT_MANT_DIG-1),  \
+                         (LDBL_MANT_DIG-1), (DBL_MANT_DIG-1), (FLT_MANT_DIG-1))
+
+static void
+init_max_error (void)
+{
+  max_error = 0;
+  real_max_error = 0;
+  imag_max_error = 0;
+  feclearexcept (FE_ALL_EXCEPT);
+}
+
+static void
+set_max_error (FLOAT current, FLOAT *curr_max_error)
+{
+  if (current > *curr_max_error)
+    *curr_max_error = current;
+}
+
+
+/* Should the message print to screen?  This depends on the verbose flag,
+   and the test status.  */
+static int
+print_screen (int ok, int xfail)
+{
+  if (output_points
+      && (verbose > 1
+	  || (verbose == 1 && ok == xfail)))
+    return 1;
+  return 0;
+}
+
+
+/* Should the message print to screen?  This depends on the verbose flag,
+   and the test status.  */
+static int
+print_screen_max_error (int ok, int xfail)
+{
+  if (output_max_error
+      && (verbose > 1
+	  || ((verbose == 1) && (ok == xfail))))
+    return 1;
+  return 0;
+}
+
+/* Update statistic counters.  */
+static void
+update_stats (int ok, int xfail)
+{
+  ++noTests;
+  if (ok && xfail)
+    ++noXPasses;
+  else if (!ok && xfail)
+    ++noXFails;
+  else if (!ok && !xfail)
+    ++noErrors;
+}
+
+static void
+print_ulps (const char *test_name, FLOAT ulp)
+{
+  if (output_ulps)
+    {
+      fprintf (ulps_file, "Test \"%s\":\n", test_name);
+      fprintf (ulps_file, "%s: %.0" PRINTF_NEXPR "\n",
+	       CHOOSE("ldouble", "double", "float",
+		      "ildouble", "idouble", "ifloat"),
+	       FUNC(ceil) (ulp));
+    }
+}
+
+static void
+print_function_ulps (const char *function_name, FLOAT ulp)
+{
+  if (output_ulps)
+    {
+      fprintf (ulps_file, "Function: \"%s\":\n", function_name);
+      fprintf (ulps_file, "%s: %.0" PRINTF_NEXPR "\n",
+	       CHOOSE("ldouble", "double", "float",
+		      "ildouble", "idouble", "ifloat"),
+	       FUNC(ceil) (ulp));
+    }
+}
+
+
+static void
+print_complex_function_ulps (const char *function_name, FLOAT real_ulp,
+			     FLOAT imag_ulp)
+{
+  if (output_ulps)
+    {
+      if (real_ulp != 0.0)
+	{
+	  fprintf (ulps_file, "Function: Real part of \"%s\":\n", function_name);
+	  fprintf (ulps_file, "%s: %.0" PRINTF_NEXPR "\n",
+		   CHOOSE("ldouble", "double", "float",
+			  "ildouble", "idouble", "ifloat"),
+		   FUNC(ceil) (real_ulp));
+	}
+      if (imag_ulp != 0.0)
+	{
+	  fprintf (ulps_file, "Function: Imaginary part of \"%s\":\n", function_name);
+	  fprintf (ulps_file, "%s: %.0" PRINTF_NEXPR "\n",
+		   CHOOSE("ldouble", "double", "float",
+			  "ildouble", "idouble", "ifloat"),
+		   FUNC(ceil) (imag_ulp));
+	}
+
+
+    }
+}
+
+
+
+/* Test if Floating-Point stack hasn't changed */
+static void
+fpstack_test (const char *test_name)
+{
+#ifdef i386
+  static int old_stack;
+  int sw;
+
+  __asm__ ("fnstsw" : "=a" (sw));
+  sw >>= 11;
+  sw &= 7;
+
+  if (sw != old_stack)
+    {
+      printf ("FP-Stack wrong after test %s (%d, should be %d)\n",
+	      test_name, sw, old_stack);
+      ++noErrors;
+      old_stack = sw;
+    }
+#endif
+}
+
+
+static void
+print_max_error (const char *func_name, FLOAT allowed, int xfail)
+{
+  int ok = 0;
+
+  if (max_error == 0.0 || (max_error <= allowed && !ignore_max_ulp))
+    {
+      ok = 1;
+    }
+
+  if (!ok)
+    print_function_ulps (func_name, max_error);
+
+
+  if (print_screen_max_error (ok, xfail))
+    {
+      printf ("Maximal error of `%s'\n", func_name);
+      printf (" is      : %.0" PRINTF_NEXPR " ulp\n", FUNC(ceil) (max_error));
+      printf (" accepted: %.0" PRINTF_NEXPR " ulp\n", FUNC(ceil) (allowed));
+    }
+
+  update_stats (ok, xfail);
+}
+
+
+static void
+print_complex_max_error (const char *func_name, __complex__ FLOAT allowed,
+			 __complex__ int xfail)
+{
+  int ok = 0;
+
+  if ((real_max_error == 0 && imag_max_error == 0)
+      || (real_max_error <= __real__ allowed
+	  && imag_max_error <= __imag__ allowed
+	  && !ignore_max_ulp))
+    {
+      ok = 1;
+    }
+
+  if (!ok)
+    print_complex_function_ulps (func_name, real_max_error, imag_max_error);
+
+
+  if (print_screen_max_error (ok, xfail))
+    {
+      printf ("Maximal error of real part of: %s\n", func_name);
+      printf (" is      : %.0" PRINTF_NEXPR " ulp\n",
+	      FUNC(ceil) (real_max_error));
+      printf (" accepted: %.0" PRINTF_NEXPR " ulp\n",
+	      FUNC(ceil) (__real__ allowed));
+      printf ("Maximal error of imaginary part of: %s\n", func_name);
+      printf (" is      : %.0" PRINTF_NEXPR " ulp\n",
+	      FUNC(ceil) (imag_max_error));
+      printf (" accepted: %.0" PRINTF_NEXPR " ulp\n",
+	      FUNC(ceil) (__imag__ allowed));
+    }
+
+  update_stats (ok, xfail);
+}
+
+
+/* Test whether a given exception was raised.  */
+static void
+test_single_exception (const char *test_name,
+		       int exception,
+		       int exc_flag,
+		       int fe_flag,
+		       const char *flag_name)
+{
+#ifndef TEST_INLINE
+  int ok = 1;
+  if (exception & exc_flag)
+    {
+      if (fetestexcept (fe_flag))
+	{
+	  if (print_screen (1, 0))
+	    printf ("Pass: %s: Exception \"%s\" set\n", test_name, flag_name);
+	}
+      else
+	{
+	  ok = 0;
+	  if (print_screen (0, 0))
+	    printf ("Failure: %s: Exception \"%s\" not set\n",
+		    test_name, flag_name);
+	}
+    }
+  else
+    {
+      if (fetestexcept (fe_flag))
+	{
+	  ok = 0;
+	  if (print_screen (0, 0))
+	    printf ("Failure: %s: Exception \"%s\" set\n",
+		    test_name, flag_name);
+	}
+      else
+	{
+	  if (print_screen (1, 0))
+	    printf ("%s: Exception \"%s\" not set\n", test_name,
+		    flag_name);
+	}
+    }
+  if (!ok)
+    ++noErrors;
+
+#endif
+}
+
+
+/* Test whether exceptions given by EXCEPTION are raised.  Ignore thereby
+   allowed but not required exceptions.
+*/
+static void
+test_exceptions (const char *test_name, int exception)
+{
+  ++noExcTests;
+#ifdef FE_DIVBYZERO
+  if ((exception & DIVIDE_BY_ZERO_EXCEPTION_OK) == 0)
+    test_single_exception (test_name, exception,
+			   DIVIDE_BY_ZERO_EXCEPTION, FE_DIVBYZERO,
+			   "Divide by zero");
+#endif
+#ifdef FE_INVALID
+  if ((exception & INVALID_EXCEPTION_OK) == 0)
+    test_single_exception (test_name, exception, INVALID_EXCEPTION, FE_INVALID,
+			 "Invalid operation");
+#endif
+  feclearexcept (FE_ALL_EXCEPT);
+}
+
+
+static void
+check_float_internal (const char *test_name, FLOAT computed, FLOAT expected,
+		      FLOAT max_ulp, int xfail, int exceptions,
+		      FLOAT *curr_max_error)
+{
+  int ok = 0;
+  int print_diff = 0;
+  FLOAT diff = 0;
+  FLOAT ulp = 0;
+
+  test_exceptions (test_name, exceptions);
+  if (isnan (computed) && isnan (expected))
+    ok = 1;
+  else if (isinf (computed) && isinf (expected))
+    {
+      /* Test for sign of infinities.  */
+      if ((exceptions & IGNORE_ZERO_INF_SIGN) == 0
+	  && signbit (computed) != signbit (expected))
+	{
+	  ok = 0;
+	  printf ("infinity has wrong sign.\n");
+	}
+      else
+	ok = 1;
+    }
+  /* Don't calc ulp for NaNs or infinities.  */
+  else if (isinf (computed) || isnan (computed) || isinf (expected) || isnan (expected))
+    ok = 0;
+  else
+    {
+      diff = FUNC(fabs) (computed - expected);
+      /* ilogb (0) isn't allowed.  */
+      if (expected == 0.0)
+	ulp = diff / FUNC(ldexp) (1.0, - MANT_DIG);
+      else
+	ulp = diff / FUNC(ldexp) (1.0, FUNC(ilogb) (expected) - MANT_DIG);
+      set_max_error (ulp, curr_max_error);
+      print_diff = 1;
+      if ((exceptions & IGNORE_ZERO_INF_SIGN) == 0
+	  && computed == 0.0 && expected == 0.0
+	  && signbit(computed) != signbit (expected))
+	ok = 0;
+      else if (ulp <= 0.5 || (ulp <= max_ulp && !ignore_max_ulp))
+	ok = 1;
+      else
+	{
+	  ok = 0;
+	  print_ulps (test_name, ulp);
+	}
+
+    }
+  if (print_screen (ok, xfail))
+    {
+      if (!ok)
+	printf ("Failure: ");
+      printf ("Test: %s\n", test_name);
+      printf ("Result:\n");
+      printf (" is:         % .20" PRINTF_EXPR "  % .20" PRINTF_XEXPR "\n",
+	      computed, computed);
+      printf (" should be:  % .20" PRINTF_EXPR "  % .20" PRINTF_XEXPR "\n",
+	      expected, expected);
+      if (print_diff)
+	{
+	  printf (" difference: % .20" PRINTF_EXPR "  % .20" PRINTF_XEXPR
+		  "\n", diff, diff);
+	  printf (" ulp       : % .4" PRINTF_NEXPR "\n", ulp);
+	  printf (" max.ulp   : % .4" PRINTF_NEXPR "\n", max_ulp);
+	}
+    }
+  update_stats (ok, xfail);
+
+  fpstack_test (test_name);
+}
+
+
+static void
+check_float (const char *test_name, FLOAT computed, FLOAT expected,
+	     FLOAT max_ulp, int xfail, int exceptions)
+{
+  check_float_internal (test_name, computed, expected, max_ulp, xfail,
+			exceptions, &max_error);
+}
+
+
+static void
+check_complex (const char *test_name, __complex__ FLOAT computed,
+	       __complex__ FLOAT expected,
+	       __complex__ FLOAT max_ulp, __complex__ int xfail,
+	       int exception)
+{
+  FLOAT part_comp, part_exp, part_max_ulp;
+  int part_xfail;
+  char str[200];
+
+  sprintf (str, "Real part of: %s", test_name);
+  part_comp = __real__ computed;
+  part_exp = __real__ expected;
+  part_max_ulp = __real__ max_ulp;
+  part_xfail = __real__ xfail;
+
+  check_float_internal (str, part_comp, part_exp, part_max_ulp, part_xfail,
+			exception, &real_max_error);
+
+  sprintf (str, "Imaginary part of: %s", test_name);
+  part_comp = __imag__ computed;
+  part_exp = __imag__ expected;
+  part_max_ulp = __imag__ max_ulp;
+  part_xfail = __imag__ xfail;
+
+  /* Don't check again for exceptions, just pass through the
+     zero/inf sign test.  */
+  check_float_internal (str, part_comp, part_exp, part_max_ulp, part_xfail,
+			exception & IGNORE_ZERO_INF_SIGN,
+			&imag_max_error);
+}
+
+
+/* Check that computed and expected values are equal (int values).  */
+static void
+check_int (const char *test_name, int computed, int expected, int max_ulp,
+	   int xfail, int exceptions)
+{
+  int diff = computed - expected;
+  int ok = 0;
+
+  test_exceptions (test_name, exceptions);
+  noTests++;
+  if (abs (diff) <= max_ulp)
+    ok = 1;
+
+  if (!ok)
+    print_ulps (test_name, diff);
+
+  if (print_screen (ok, xfail))
+    {
+      if (!ok)
+	printf ("Failure: ");
+      printf ("Test: %s\n", test_name);
+      printf ("Result:\n");
+      printf (" is:         %d\n", computed);
+      printf (" should be:  %d\n", expected);
+    }
+
+  update_stats (ok, xfail);
+  fpstack_test (test_name);
+}
+
+
+/* Check that computed and expected values are equal (long int values).  */
+static void
+check_long (const char *test_name, long int computed, long int expected,
+	    long int max_ulp, int xfail, int exceptions)
+{
+  long int diff = computed - expected;
+  int ok = 0;
+
+  test_exceptions (test_name, exceptions);
+  noTests++;
+  if (labs (diff) <= max_ulp)
+    ok = 1;
+
+  if (!ok)
+    print_ulps (test_name, diff);
+
+  if (print_screen (ok, xfail))
+    {
+      if (!ok)
+	printf ("Failure: ");
+      printf ("Test: %s\n", test_name);
+      printf ("Result:\n");
+      printf (" is:         %ld\n", computed);
+      printf (" should be:  %ld\n", expected);
+    }
+
+  update_stats (ok, xfail);
+  fpstack_test (test_name);
+}
+
+
+/* Check that computed value is true/false.  */
+static void
+check_bool (const char *test_name, int computed, int expected,
+	    long int max_ulp, int xfail, int exceptions)
+{
+  int ok = 0;
+
+  test_exceptions (test_name, exceptions);
+  noTests++;
+  if ((computed == 0) == (expected == 0))
+    ok = 1;
+
+  if (print_screen (ok, xfail))
+    {
+      if (!ok)
+	printf ("Failure: ");
+      printf ("Test: %s\n", test_name);
+      printf ("Result:\n");
+      printf (" is:         %d\n", computed);
+      printf (" should be:  %d\n", expected);
+    }
+
+  update_stats (ok, xfail);
+  fpstack_test (test_name);
+}
+
+
+/* check that computed and expected values are equal (long int values) */
+static void
+check_longlong (const char *test_name, long long int computed,
+		long long int expected,
+		long long int max_ulp, int xfail,
+		int exceptions)
+{
+  long long int diff = computed - expected;
+  int ok = 0;
+
+  test_exceptions (test_name, exceptions);
+  noTests++;
+  if (llabs (diff) <= max_ulp)
+    ok = 1;
+
+  if (!ok)
+    print_ulps (test_name, diff);
+
+  if (print_screen (ok, xfail))
+    {
+      if (!ok)
+	printf ("Failure:");
+      printf ("Test: %s\n", test_name);
+      printf ("Result:\n");
+      printf (" is:         %lld\n", computed);
+      printf (" should be:  %lld\n", expected);
+    }
+
+  update_stats (ok, xfail);
+  fpstack_test (test_name);
+}
+
+
+
+/* This is to prevent messages from the SVID libm emulation.  */
+int
+matherr (struct exception *x __attribute__ ((unused)))
+{
+  return 1;
+}
+
+
+/****************************************************************************
+  Tests for single functions of libm.
+  Please keep them alphabetically sorted!
+****************************************************************************/
+
+static void
+acos_test (void)
+{
+  errno = 0;
+  FUNC(acos) (0);
+  if (errno == ENOSYS)
+    /* Function not implemented.  */
+    return;
+
+  START (acos);
+
+  TEST_f_f (acos, plus_infty, nan_value, INVALID_EXCEPTION);
+  TEST_f_f (acos, minus_infty, nan_value, INVALID_EXCEPTION);
+  TEST_f_f (acos, nan_value, nan_value);
+
+  /* |x| > 1: */
+  TEST_f_f (acos, 1.125L, nan_value, INVALID_EXCEPTION);
+  TEST_f_f (acos, -1.125L, nan_value, INVALID_EXCEPTION);
+
+  TEST_f_f (acos, 0, M_PI_2l);
+  TEST_f_f (acos, minus_zero, M_PI_2l);
+  TEST_f_f (acos, 1, 0);
+  TEST_f_f (acos, -1, M_PIl);
+  TEST_f_f (acos, 0.5, M_PI_6l*2.0);
+  TEST_f_f (acos, -0.5, M_PI_6l*4.0);
+  TEST_f_f (acos, 0.75L, 0.722734247813415611178377352641333362L);
+  TEST_f_f (acos, 2e-17L, 1.57079632679489659923132169163975144L);
+  TEST_f_f (acos, 0.0625L, 1.50825556499840522843072005474337068L);
+  END (acos);
+}
+
+static void
+acosh_test (void)
+{
+  errno = 0;
+  FUNC(acosh) (7);
+  if (errno == ENOSYS)
+    /* Function not implemented.  */
+    return;
+
+  START (acosh);
+
+  TEST_f_f (acosh, plus_infty, plus_infty);
+  TEST_f_f (acosh, minus_infty, nan_value, INVALID_EXCEPTION);
+
+  /* x < 1:  */
+  TEST_f_f (acosh, -1.125L, nan_value, INVALID_EXCEPTION);
+
+  TEST_f_f (acosh, 1, 0);
+  TEST_f_f (acosh, 7, 2.63391579384963341725009269461593689L);
+
+  END (acosh);
+}
+
+static void
+asin_test (void)
+{
+  errno = 0;
+  FUNC(asin) (0);
+  if (errno == ENOSYS)
+    /* Function not implemented.  */
+    return;
+
+  START (asin);
+
+  TEST_f_f (asin, plus_infty, nan_value, INVALID_EXCEPTION);
+  TEST_f_f (asin, minus_infty, nan_value, INVALID_EXCEPTION);
+  TEST_f_f (asin, nan_value, nan_value);
+
+  /* asin x == NaN plus invalid exception for |x| > 1.  */
+  TEST_f_f (asin, 1.125L, nan_value, INVALID_EXCEPTION);
+  TEST_f_f (asin, -1.125L, nan_value, INVALID_EXCEPTION);
+
+  TEST_f_f (asin, 0, 0);
+  TEST_f_f (asin, minus_zero, minus_zero);
+  TEST_f_f (asin, 0.5, M_PI_6l);
+  TEST_f_f (asin, -0.5, -M_PI_6l);
+  TEST_f_f (asin, 1.0, M_PI_2l);
+  TEST_f_f (asin, -1.0, -M_PI_2l);
+  TEST_f_f (asin, 0.75L, 0.848062078981481008052944338998418080L);
+
+  END (asin);
+}
+
+static void
+asinh_test (void)
+{
+  errno = 0;
+  FUNC(asinh) (0.7L);
+  if (errno == ENOSYS)
+    /* Function not implemented.  */
+    return;
+
+  START (asinh);
+
+  TEST_f_f (asinh, 0, 0);
+  TEST_f_f (asinh, minus_zero, minus_zero);
+#ifndef TEST_INLINE
+  TEST_f_f (asinh, plus_infty, plus_infty);
+  TEST_f_f (asinh, minus_infty, minus_infty);
+#endif
+  TEST_f_f (asinh, nan_value, nan_value);
+  TEST_f_f (asinh, 0.75L, 0.693147180559945309417232121458176568L);
+
+  END (asinh);
+}
+
+static void
+atan_test (void)
+{
+  errno = 0;
+  FUNC(atan) (0);
+  if (errno == ENOSYS)
+    /* Function not implemented.  */
+    return;
+
+  START (atan);
+
+  TEST_f_f (atan, 0, 0);
+  TEST_f_f (atan, minus_zero, minus_zero);
+
+  TEST_f_f (atan, plus_infty, M_PI_2l);
+  TEST_f_f (atan, minus_infty, -M_PI_2l);
+  TEST_f_f (atan, nan_value, nan_value);
+
+  TEST_f_f (atan, 1, M_PI_4l);
+  TEST_f_f (atan, -1, -M_PI_4l);
+
+  TEST_f_f (atan, 0.75L, 0.643501108793284386802809228717322638L);
+
+  END (atan);
+}
+
+
+
+static void
+atanh_test (void)
+{
+  errno = 0;
+  FUNC(atanh) (0.7L);
+  if (errno == ENOSYS)
+    /* Function not implemented.  */
+    return;
+
+  START (atanh);
+
+
+  TEST_f_f (atanh, 0, 0);
+  TEST_f_f (atanh, minus_zero, minus_zero);
+
+  TEST_f_f (atanh, 1, plus_infty, DIVIDE_BY_ZERO_EXCEPTION);
+  TEST_f_f (atanh, -1, minus_infty, DIVIDE_BY_ZERO_EXCEPTION);
+  TEST_f_f (atanh, nan_value, nan_value);
+
+  /* atanh (x) == NaN plus invalid exception if |x| > 1.  */
+  TEST_f_f (atanh, 1.125L, nan_value, INVALID_EXCEPTION);
+  TEST_f_f (atanh, -1.125L, nan_value, INVALID_EXCEPTION);
+
+  TEST_f_f (atanh, 0.75L, 0.972955074527656652552676371721589865L);
+
+  END (atanh);
+}
+
+static void
+atan2_test (void)
+{
+  errno = 0;
+  FUNC(atan2) (-0, 1);
+  if (errno == ENOSYS)
+    /* Function not implemented.  */
+    return;
+
+  START (atan2);
+
+  /* atan2 (0,x) == 0 for x > 0.  */
+  TEST_ff_f (atan2, 0, 1, 0);
+
+  /* atan2 (-0,x) == -0 for x > 0.  */
+  TEST_ff_f (atan2, minus_zero, 1, minus_zero);
+
+  TEST_ff_f (atan2, 0, 0, 0);
+  TEST_ff_f (atan2, minus_zero, 0, minus_zero);
+
+  /* atan2 (+0,x) == +pi for x < 0.  */
+  TEST_ff_f (atan2, 0, -1, M_PIl);
+
+  /* atan2 (-0,x) == -pi for x < 0.  */
+  TEST_ff_f (atan2, minus_zero, -1, -M_PIl);
+
+  TEST_ff_f (atan2, 0, minus_zero, M_PIl);
+  TEST_ff_f (atan2, minus_zero, minus_zero, -M_PIl);
+
+  /* atan2 (y,+0) == pi/2 for y > 0.  */
+  TEST_ff_f (atan2, 1, 0, M_PI_2l);
+
+  /* atan2 (y,-0) == pi/2 for y > 0.  */
+  TEST_ff_f (atan2, 1, minus_zero, M_PI_2l);
+
+  /* atan2 (y,+0) == -pi/2 for y < 0.  */
+  TEST_ff_f (atan2, -1, 0, -M_PI_2l);
+
+  /* atan2 (y,-0) == -pi/2 for y < 0.  */
+  TEST_ff_f (atan2, -1, minus_zero, -M_PI_2l);
+
+  /* atan2 (y,inf) == +0 for finite y > 0.  */
+  TEST_ff_f (atan2, 1, plus_infty, 0);
+
+  /* atan2 (y,inf) == -0 for finite y < 0.  */
+  TEST_ff_f (atan2, -1, plus_infty, minus_zero);
+
+  /* atan2(+inf, x) == pi/2 for finite x.  */
+  TEST_ff_f (atan2, plus_infty, -1, M_PI_2l);
+
+  /* atan2(-inf, x) == -pi/2 for finite x.  */
+  TEST_ff_f (atan2, minus_infty, 1, -M_PI_2l);
+
+  /* atan2 (y,-inf) == +pi for finite y > 0.  */
+  TEST_ff_f (atan2, 1, minus_infty, M_PIl);
+
+  /* atan2 (y,-inf) == -pi for finite y < 0.  */
+  TEST_ff_f (atan2, -1, minus_infty, -M_PIl);
+
+  TEST_ff_f (atan2, plus_infty, plus_infty, M_PI_4l);
+  TEST_ff_f (atan2, minus_infty, plus_infty, -M_PI_4l);
+  TEST_ff_f (atan2, plus_infty, minus_infty, M_PI_34l);
+  TEST_ff_f (atan2, minus_infty, minus_infty, -M_PI_34l);
+  TEST_ff_f (atan2, nan_value, nan_value, nan_value);
+
+  TEST_ff_f (atan2, 0.75L, 1, 0.643501108793284386802809228717322638L);
+  TEST_ff_f (atan2, -0.75L, 1.0L, -0.643501108793284386802809228717322638L);
+  TEST_ff_f (atan2, 0.75L, -1.0L, 2.49809154479650885165983415456218025L);
+  TEST_ff_f (atan2, -0.75L, -1.0L, -2.49809154479650885165983415456218025L);
+  TEST_ff_f (atan2, 0.390625L, .00029L, 1.57005392693128974780151246612928941L);
+  TEST_ff_f (atan2, 1.390625L, 0.9296875L, 0.981498387184244311516296577615519772L);
+
+  TEST_ff_f (atan2, -0.00756827042671106339L, -.001792735857538728036L, -1.80338464113663849327153994379639112L);
+
+  END (atan2);
+}
+
+static void
+cabs_test (void)
+{
+  errno = 0;
+  FUNC(cabs) (BUILD_COMPLEX (0.7L, 12.4L));
+  if (errno == ENOSYS)
+    /* Function not implemented.  */
+    return;
+
+  START (cabs);
+
+  /* cabs (x + iy) is specified as hypot (x,y) */
+
+  /* cabs (+inf + i x) == +inf.  */
+  TEST_c_f (cabs, plus_infty, 1.0, plus_infty);
+  /* cabs (-inf + i x) == +inf.  */
+  TEST_c_f (cabs, minus_infty, 1.0, plus_infty);
+
+  TEST_c_f (cabs, minus_infty, nan_value, plus_infty);
+  TEST_c_f (cabs, minus_infty, nan_value, plus_infty);
+
+  TEST_c_f (cabs, nan_value, nan_value, nan_value);
+
+  /* cabs (x,y) == cabs (y,x).  */
+  TEST_c_f (cabs, 0.75L, 12.390625L, 12.4133028598606664302388810868156657L);
+  /* cabs (x,y) == cabs (-x,y).  */
+  TEST_c_f (cabs, -12.390625L, 0.75L, 12.4133028598606664302388810868156657L);
+  /* cabs (x,y) == cabs (-y,x).  */
+  TEST_c_f (cabs, -0.75L, 12.390625L, 12.4133028598606664302388810868156657L);
+  /* cabs (x,y) == cabs (-x,-y).  */
+  TEST_c_f (cabs, -12.390625L, -0.75L, 12.4133028598606664302388810868156657L);
+  /* cabs (x,y) == cabs (-y,-x).  */
+  TEST_c_f (cabs, -0.75L, -12.390625L, 12.4133028598606664302388810868156657L);
+  /* cabs (x,0) == fabs (x).  */
+  TEST_c_f (cabs, -0.75L, 0, 0.75L);
+  TEST_c_f (cabs, 0.75L, 0, 0.75L);
+  TEST_c_f (cabs, -1.0L, 0, 1.0L);
+  TEST_c_f (cabs, 1.0L, 0, 1.0L);
+  TEST_c_f (cabs, -5.7e7L, 0, 5.7e7L);
+  TEST_c_f (cabs, 5.7e7L, 0, 5.7e7L);
+
+  TEST_c_f (cabs, 0.75L, 1.25L, 1.45773797371132511771853821938639577L);
+
+  END (cabs);
+}
+
+
+#if 0
+static void
+cacos_test (void)
+{
+  errno = 0;
+  FUNC(cacos) (BUILD_COMPLEX (0.7L, 1.2L));
+  if (errno == ENOSYS)
+    /* Function not implemented.  */
+    return;
+
+  START (cacos);
+
+
+  TEST_c_c (cacos, 0, 0, M_PI_2l, minus_zero);
+  TEST_c_c (cacos, minus_zero, 0, M_PI_2l, minus_zero);
+  TEST_c_c (cacos, minus_zero, minus_zero, M_PI_2l, 0.0);
+  TEST_c_c (cacos, 0, minus_zero, M_PI_2l, 0.0);
+
+  TEST_c_c (cacos, minus_infty, plus_infty, M_PI_34l, minus_infty);
+  TEST_c_c (cacos, minus_infty, minus_infty, M_PI_34l, plus_infty);
+
+  TEST_c_c (cacos, plus_infty, plus_infty, M_PI_4l, minus_infty);
+  TEST_c_c (cacos, plus_infty, minus_infty, M_PI_4l, plus_infty);
+
+  TEST_c_c (cacos, -10.0, plus_infty, M_PI_2l, minus_infty);
+  TEST_c_c (cacos, -10.0, minus_infty, M_PI_2l, plus_infty);
+  TEST_c_c (cacos, 0, plus_infty, M_PI_2l, minus_infty);
+  TEST_c_c (cacos, 0, minus_infty, M_PI_2l, plus_infty);
+  TEST_c_c (cacos, 0.1L, plus_infty, M_PI_2l, minus_infty);
+  TEST_c_c (cacos, 0.1L, minus_infty, M_PI_2l, plus_infty);
+
+  TEST_c_c (cacos, minus_infty, 0, M_PIl, minus_infty);
+  TEST_c_c (cacos, minus_infty, minus_zero, M_PIl, plus_infty);
+  TEST_c_c (cacos, minus_infty, 100, M_PIl, minus_infty);
+  TEST_c_c (cacos, minus_infty, -100, M_PIl, plus_infty);
+
+  TEST_c_c (cacos, plus_infty, 0, 0.0, minus_infty);
+  TEST_c_c (cacos, plus_infty, minus_zero, 0.0, plus_infty);
+  TEST_c_c (cacos, plus_infty, 0.5, 0.0, minus_infty);
+  TEST_c_c (cacos, plus_infty, -0.5, 0.0, plus_infty);
+
+  TEST_c_c (cacos, plus_infty, nan_value, nan_value, plus_infty, IGNORE_ZERO_INF_SIGN);
+  TEST_c_c (cacos, minus_infty, nan_value, nan_value, plus_infty, IGNORE_ZERO_INF_SIGN);
+
+  TEST_c_c (cacos, 0, nan_value, M_PI_2l, nan_value);
+  TEST_c_c (cacos, minus_zero, nan_value, M_PI_2l, nan_value);
+
+  TEST_c_c (cacos, nan_value, plus_infty, nan_value, minus_infty);
+  TEST_c_c (cacos, nan_value, minus_infty, nan_value, plus_infty);
+
+  TEST_c_c (cacos, 10.5, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK);
+  TEST_c_c (cacos, -10.5, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK);
+
+  TEST_c_c (cacos, nan_value, 0.75, nan_value, nan_value, INVALID_EXCEPTION_OK);
+  TEST_c_c (cacos, nan_value, -0.75, nan_value, nan_value, INVALID_EXCEPTION_OK);
+
+  TEST_c_c (cacos, nan_value, nan_value, nan_value, nan_value);
+
+  TEST_c_c (cacos, 0.75L, 1.25L, 1.11752014915610270578240049553777969L, -1.13239363160530819522266333696834467L);
+  TEST_c_c (cacos, -2, -3, 2.1414491111159960199416055713254211L, 1.9833870299165354323470769028940395L);
+
+  END (cacos, complex);
+}
+
+static void
+cacosh_test (void)
+{
+  errno = 0;
+  FUNC(cacosh) (BUILD_COMPLEX (0.7L, 1.2L));
+  if (errno == ENOSYS)
+    /* Function not implemented.  */
+    return;
+
+  START (cacosh);
+
+
+  TEST_c_c (cacosh, 0, 0, 0.0, M_PI_2l);
+  TEST_c_c (cacosh, minus_zero, 0, 0.0, M_PI_2l);
+  TEST_c_c (cacosh, 0, minus_zero, 0.0, -M_PI_2l);
+  TEST_c_c (cacosh, minus_zero, minus_zero, 0.0, -M_PI_2l);
+  TEST_c_c (cacosh, minus_infty, plus_infty, plus_infty, M_PI_34l);
+  TEST_c_c (cacosh, minus_infty, minus_infty, plus_infty, -M_PI_34l);
+
+  TEST_c_c (cacosh, plus_infty, plus_infty, plus_infty, M_PI_4l);
+  TEST_c_c (cacosh, plus_infty, minus_infty, plus_infty, -M_PI_4l);
+
+  TEST_c_c (cacosh, -10.0, plus_infty, plus_infty, M_PI_2l);
+  TEST_c_c (cacosh, -10.0, minus_infty, plus_infty, -M_PI_2l);
+  TEST_c_c (cacosh, 0, plus_infty, plus_infty, M_PI_2l);
+  TEST_c_c (cacosh, 0, minus_infty, plus_infty, -M_PI_2l);
+  TEST_c_c (cacosh, 0.1L, plus_infty, plus_infty, M_PI_2l);
+  TEST_c_c (cacosh, 0.1L, minus_infty, plus_infty, -M_PI_2l);
+
+  TEST_c_c (cacosh, minus_infty, 0, plus_infty, M_PIl);
+  TEST_c_c (cacosh, minus_infty, minus_zero, plus_infty, -M_PIl);
+  TEST_c_c (cacosh, minus_infty, 100, plus_infty, M_PIl);
+  TEST_c_c (cacosh, minus_infty, -100, plus_infty, -M_PIl);
+
+  TEST_c_c (cacosh, plus_infty, 0, plus_infty, 0.0);
+  TEST_c_c (cacosh, plus_infty, minus_zero, plus_infty, minus_zero);
+  TEST_c_c (cacosh, plus_infty, 0.5, plus_infty, 0.0);
+  TEST_c_c (cacosh, plus_infty, -0.5, plus_infty, minus_zero);
+
+  TEST_c_c (cacosh, plus_infty, nan_value, plus_infty, nan_value);
+  TEST_c_c (cacosh, minus_infty, nan_value, plus_infty, nan_value);
+
+  TEST_c_c (cacosh, 0, nan_value, nan_value, nan_value);
+  TEST_c_c (cacosh, minus_zero, nan_value, nan_value, nan_value);
+
+  TEST_c_c (cacosh, nan_value, plus_infty, plus_infty, nan_value);
+  TEST_c_c (cacosh, nan_value, minus_infty, plus_infty, nan_value);
+
+  TEST_c_c (cacosh, 10.5, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK);
+  TEST_c_c (cacosh, -10.5, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK);
+
+  TEST_c_c (cacosh, nan_value, 0.75, nan_value, nan_value, INVALID_EXCEPTION_OK);
+  TEST_c_c (cacosh, nan_value, -0.75, nan_value, nan_value, INVALID_EXCEPTION_OK);
+
+  TEST_c_c (cacosh, nan_value, nan_value, nan_value, nan_value);
+
+  TEST_c_c (cacosh, 0.75L, 1.25L, 1.13239363160530819522266333696834467L, 1.11752014915610270578240049553777969L);
+  TEST_c_c (cacosh, -2, -3, 1.9833870299165354323470769028940395L, -2.1414491111159960199416055713254211L);
+
+  END (cacosh, complex);
+}
+
+
+static void
+carg_test (void)
+{
+  START (carg);
+
+  /* carg (x + iy) is specified as atan2 (y, x) */
+
+  /* carg (x + i 0) == 0 for x > 0.  */
+  TEST_c_f (carg, 2.0, 0, 0);
+  /* carg (x - i 0) == -0 for x > 0.  */
+  TEST_c_f (carg, 2.0, minus_zero, minus_zero);
+
+  TEST_c_f (carg, 0, 0, 0);
+  TEST_c_f (carg, 0, minus_zero, minus_zero);
+
+  /* carg (x + i 0) == +pi for x < 0.  */
+  TEST_c_f (carg, -2.0, 0, M_PIl);
+
+  /* carg (x - i 0) == -pi for x < 0.  */
+  TEST_c_f (carg, -2.0, minus_zero, -M_PIl);
+
+  TEST_c_f (carg, minus_zero, 0, M_PIl);
+  TEST_c_f (carg, minus_zero, minus_zero, -M_PIl);
+
+  /* carg (+0 + i y) == pi/2 for y > 0.  */
+  TEST_c_f (carg, 0, 2.0, M_PI_2l);
+
+  /* carg (-0 + i y) == pi/2 for y > 0.  */
+  TEST_c_f (carg, minus_zero, 2.0, M_PI_2l);
+
+  /* carg (+0 + i y) == -pi/2 for y < 0.  */
+  TEST_c_f (carg, 0, -2.0, -M_PI_2l);
+
+  /* carg (-0 + i y) == -pi/2 for y < 0.  */
+  TEST_c_f (carg, minus_zero, -2.0, -M_PI_2l);
+
+  /* carg (inf + i y) == +0 for finite y > 0.  */
+  TEST_c_f (carg, plus_infty, 2.0, 0);
+
+  /* carg (inf + i y) == -0 for finite y < 0.  */
+  TEST_c_f (carg, plus_infty, -2.0, minus_zero);
+
+  /* carg(x + i inf) == pi/2 for finite x.  */
+  TEST_c_f (carg, 10.0, plus_infty, M_PI_2l);
+
+  /* carg(x - i inf) == -pi/2 for finite x.  */
+  TEST_c_f (carg, 10.0, minus_infty, -M_PI_2l);
+
+  /* carg (-inf + i y) == +pi for finite y > 0.  */
+  TEST_c_f (carg, minus_infty, 10.0, M_PIl);
+
+  /* carg (-inf + i y) == -pi for finite y < 0.  */
+  TEST_c_f (carg, minus_infty, -10.0, -M_PIl);
+
+  TEST_c_f (carg, plus_infty, plus_infty, M_PI_4l);
+
+  TEST_c_f (carg, plus_infty, minus_infty, -M_PI_4l);
+
+  TEST_c_f (carg, minus_infty, plus_infty, 3 * M_PI_4l);
+
+  TEST_c_f (carg, minus_infty, minus_infty, -3 * M_PI_4l);
+
+  TEST_c_f (carg, nan_value, nan_value, nan_value);
+
+  END (carg);
+}
+
+static void
+casin_test (void)
+{
+  errno = 0;
+  FUNC(casin) (BUILD_COMPLEX (0.7L, 1.2L));
+  if (errno == ENOSYS)
+    /* Function not implemented.  */
+    return;
+
+  START (casin);
+
+  TEST_c_c (casin, 0, 0, 0.0, 0.0);
+  TEST_c_c (casin, minus_zero, 0, minus_zero, 0.0);
+  TEST_c_c (casin, 0, minus_zero, 0.0, minus_zero);
+  TEST_c_c (casin, minus_zero, minus_zero, minus_zero, minus_zero);
+
+  TEST_c_c (casin, plus_infty, plus_infty, M_PI_4l, plus_infty);
+  TEST_c_c (casin, plus_infty, minus_infty, M_PI_4l, minus_infty);
+  TEST_c_c (casin, minus_infty, plus_infty, -M_PI_4l, plus_infty);
+  TEST_c_c (casin, minus_infty, minus_infty, -M_PI_4l, minus_infty);
+
+  TEST_c_c (casin, -10.0, plus_infty, minus_zero, plus_infty);
+  TEST_c_c (casin, -10.0, minus_infty, minus_zero, minus_infty);
+  TEST_c_c (casin, 0, plus_infty, 0.0, plus_infty);
+  TEST_c_c (casin, 0, minus_infty, 0.0, minus_infty);
+  TEST_c_c (casin, minus_zero, plus_infty, minus_zero, plus_infty);
+  TEST_c_c (casin, minus_zero, minus_infty, minus_zero, minus_infty);
+  TEST_c_c (casin, 0.1L, plus_infty, 0.0, plus_infty);
+  TEST_c_c (casin, 0.1L, minus_infty, 0.0, minus_infty);
+
+  TEST_c_c (casin, minus_infty, 0, -M_PI_2l, plus_infty);
+  TEST_c_c (casin, minus_infty, minus_zero, -M_PI_2l, minus_infty);
+  TEST_c_c (casin, minus_infty, 100, -M_PI_2l, plus_infty);
+  TEST_c_c (casin, minus_infty, -100, -M_PI_2l, minus_infty);
+
+  TEST_c_c (casin, plus_infty, 0, M_PI_2l, plus_infty);
+  TEST_c_c (casin, plus_infty, minus_zero, M_PI_2l, minus_infty);
+  TEST_c_c (casin, plus_infty, 0.5, M_PI_2l, plus_infty);
+  TEST_c_c (casin, plus_infty, -0.5, M_PI_2l, minus_infty);
+
+  TEST_c_c (casin, nan_value, plus_infty, nan_value, plus_infty);
+  TEST_c_c (casin, nan_value, minus_infty, nan_value, minus_infty);
+
+  TEST_c_c (casin, 0.0, nan_value, 0.0, nan_value);
+  TEST_c_c (casin, minus_zero, nan_value, minus_zero, nan_value);
+
+  TEST_c_c (casin, plus_infty, nan_value, nan_value, plus_infty, IGNORE_ZERO_INF_SIGN);
+  TEST_c_c (casin, minus_infty, nan_value, nan_value, plus_infty, IGNORE_ZERO_INF_SIGN);
+
+  TEST_c_c (casin, nan_value, 10.5, nan_value, nan_value, INVALID_EXCEPTION_OK);
+  TEST_c_c (casin, nan_value, -10.5, nan_value, nan_value, INVALID_EXCEPTION_OK);
+
+  TEST_c_c (casin, 0.75, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK);
+  TEST_c_c (casin, -0.75, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK);
+
+  TEST_c_c (casin, nan_value, nan_value, nan_value, nan_value);
+
+  TEST_c_c (casin, 0.75L, 1.25L, 0.453276177638793913448921196101971749L, 1.13239363160530819522266333696834467L);
+  TEST_c_c (casin, -2, -3, -0.57065278432109940071028387968566963L, -1.9833870299165354323470769028940395L);
+
+  END (casin, complex);
+}
+
+
+static void
+casinh_test (void)
+{
+  errno = 0;
+  FUNC(casinh) (BUILD_COMPLEX (0.7L, 1.2L));
+  if (errno == ENOSYS)
+    /* Function not implemented.  */
+    return;
+
+  START (casinh);
+
+  TEST_c_c (casinh, 0, 0, 0.0, 0.0);
+  TEST_c_c (casinh, minus_zero, 0, minus_zero, 0);
+  TEST_c_c (casinh, 0, minus_zero, 0.0, minus_zero);
+  TEST_c_c (casinh, minus_zero, minus_zero, minus_zero, minus_zero);
+
+  TEST_c_c (casinh, plus_infty, plus_infty, plus_infty, M_PI_4l);
+  TEST_c_c (casinh, plus_infty, minus_infty, plus_infty, -M_PI_4l);
+  TEST_c_c (casinh, minus_infty, plus_infty, minus_infty, M_PI_4l);
+  TEST_c_c (casinh, minus_infty, minus_infty, minus_infty, -M_PI_4l);
+
+  TEST_c_c (casinh, -10.0, plus_infty, minus_infty, M_PI_2l);
+  TEST_c_c (casinh, -10.0, minus_infty, minus_infty, -M_PI_2l);
+  TEST_c_c (casinh, 0, plus_infty, plus_infty, M_PI_2l);
+  TEST_c_c (casinh, 0, minus_infty, plus_infty, -M_PI_2l);
+  TEST_c_c (casinh, minus_zero, plus_infty, minus_infty, M_PI_2l);
+  TEST_c_c (casinh, minus_zero, minus_infty, minus_infty, -M_PI_2l);
+  TEST_c_c (casinh, 0.1L, plus_infty, plus_infty, M_PI_2l);
+  TEST_c_c (casinh, 0.1L, minus_infty, plus_infty, -M_PI_2l);
+
+  TEST_c_c (casinh, minus_infty, 0, minus_infty, 0.0);
+  TEST_c_c (casinh, minus_infty, minus_zero, minus_infty, minus_zero);
+  TEST_c_c (casinh, minus_infty, 100, minus_infty, 0.0);
+  TEST_c_c (casinh, minus_infty, -100, minus_infty, minus_zero);
+
+  TEST_c_c (casinh, plus_infty, 0, plus_infty, 0.0);
+  TEST_c_c (casinh, plus_infty, minus_zero, plus_infty, minus_zero);
+  TEST_c_c (casinh, plus_infty, 0.5, plus_infty, 0.0);
+  TEST_c_c (casinh, plus_infty, -0.5, plus_infty, minus_zero);
+
+  TEST_c_c (casinh, plus_infty, nan_value, plus_infty, nan_value);
+  TEST_c_c (casinh, minus_infty, nan_value, minus_infty, nan_value);
+
+  TEST_c_c (casinh, nan_value, 0, nan_value, 0.0);
+  TEST_c_c (casinh, nan_value, minus_zero, nan_value, minus_zero);
+
+  TEST_c_c (casinh, nan_value, plus_infty, plus_infty, nan_value, IGNORE_ZERO_INF_SIGN);
+  TEST_c_c (casinh, nan_value, minus_infty, plus_infty, nan_value, IGNORE_ZERO_INF_SIGN);
+
+  TEST_c_c (casinh, 10.5, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK);
+  TEST_c_c (casinh, -10.5, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK);
+
+  TEST_c_c (casinh, nan_value, 0.75, nan_value, nan_value, INVALID_EXCEPTION_OK);
+  TEST_c_c (casinh, -0.75, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK);
+
+  TEST_c_c (casinh, nan_value, nan_value, nan_value, nan_value);
+
+  TEST_c_c (casinh, 0.75L, 1.25L, 1.03171853444778027336364058631006594L, 0.911738290968487636358489564316731207L);
+  TEST_c_c (casinh, -2, -3, -1.9686379257930962917886650952454982L, -0.96465850440760279204541105949953237L);
+
+  END (casinh, complex);
+}
+
+
+static void
+catan_test (void)
+{
+  errno = 0;
+  FUNC(catan) (BUILD_COMPLEX (0.7L, 1.2L));
+  if (errno == ENOSYS)
+    /* Function not implemented.  */
+    return;
+
+  START (catan);
+
+  TEST_c_c (catan, 0, 0, 0, 0);
+  TEST_c_c (catan, minus_zero, 0, minus_zero, 0);
+  TEST_c_c (catan, 0, minus_zero, 0, minus_zero);
+  TEST_c_c (catan, minus_zero, minus_zero, minus_zero, minus_zero);
+
+  TEST_c_c (catan, plus_infty, plus_infty, M_PI_2l, 0);
+  TEST_c_c (catan, plus_infty, minus_infty, M_PI_2l, minus_zero);
+  TEST_c_c (catan, minus_infty, plus_infty, -M_PI_2l, 0);
+  TEST_c_c (catan, minus_infty, minus_infty, -M_PI_2l, minus_zero);
+
+
+  TEST_c_c (catan, plus_infty, -10.0, M_PI_2l, minus_zero);
+  TEST_c_c (catan, minus_infty, -10.0, -M_PI_2l, minus_zero);
+  TEST_c_c (catan, plus_infty, minus_zero, M_PI_2l, minus_zero);
+  TEST_c_c (catan, minus_infty, minus_zero, -M_PI_2l, minus_zero);
+  TEST_c_c (catan, plus_infty, 0.0, M_PI_2l, 0);
+  TEST_c_c (catan, minus_infty, 0.0, -M_PI_2l, 0);
+  TEST_c_c (catan, plus_infty, 0.1L, M_PI_2l, 0);
+  TEST_c_c (catan, minus_infty, 0.1L, -M_PI_2l, 0);
+
+  TEST_c_c (catan, 0.0, minus_infty, M_PI_2l, minus_zero);
+  TEST_c_c (catan, minus_zero, minus_infty, -M_PI_2l, minus_zero);
+  TEST_c_c (catan, 100.0, minus_infty, M_PI_2l, minus_zero);
+  TEST_c_c (catan, -100.0, minus_infty, -M_PI_2l, minus_zero);
+
+  TEST_c_c (catan, 0.0, plus_infty, M_PI_2l, 0);
+  TEST_c_c (catan, minus_zero, plus_infty, -M_PI_2l, 0);
+  TEST_c_c (catan, 0.5, plus_infty, M_PI_2l, 0);
+  TEST_c_c (catan, -0.5, plus_infty, -M_PI_2l, 0);
+
+  TEST_c_c (catan, nan_value, 0.0, nan_value, 0);
+  TEST_c_c (catan, nan_value, minus_zero, nan_value, minus_zero);
+
+  TEST_c_c (catan, nan_value, plus_infty, nan_value, 0);
+  TEST_c_c (catan, nan_value, minus_infty, nan_value, minus_zero);
+
+  TEST_c_c (catan, 0.0, nan_value, nan_value, nan_value);
+  TEST_c_c (catan, minus_zero, nan_value, nan_value, nan_value);
+
+  TEST_c_c (catan, plus_infty, nan_value, M_PI_2l, 0, IGNORE_ZERO_INF_SIGN);
+  TEST_c_c (catan, minus_infty, nan_value, -M_PI_2l, 0, IGNORE_ZERO_INF_SIGN);
+
+  TEST_c_c (catan, nan_value, 10.5, nan_value, nan_value, INVALID_EXCEPTION_OK);
+  TEST_c_c (catan, nan_value, -10.5, nan_value, nan_value, INVALID_EXCEPTION_OK);
+
+  TEST_c_c (catan, 0.75, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK);
+  TEST_c_c (catan, -0.75, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK);
+
+  TEST_c_c (catan, nan_value, nan_value, nan_value, nan_value);
+
+  TEST_c_c (catan, 0.75L, 1.25L, 1.10714871779409050301706546017853704L, 0.549306144334054845697622618461262852L);
+  TEST_c_c (catan, -2, -3, -1.4099210495965755225306193844604208L, -0.22907268296853876629588180294200276L);
+
+  END (catan, complex);
+}
+
+static void
+catanh_test (void)
+{
+  errno = 0;
+  FUNC(catanh) (BUILD_COMPLEX (0.7L, 1.2L));
+  if (errno == ENOSYS)
+    /* Function not implemented.  */
+    return;
+
+  START (catanh);
+
+  TEST_c_c (catanh, 0, 0, 0.0, 0.0);
+  TEST_c_c (catanh, minus_zero, 0, minus_zero, 0.0);
+  TEST_c_c (catanh, 0, minus_zero, 0.0, minus_zero);
+  TEST_c_c (catanh, minus_zero, minus_zero, minus_zero, minus_zero);
+
+  TEST_c_c (catanh, plus_infty, plus_infty, 0.0, M_PI_2l);
+  TEST_c_c (catanh, plus_infty, minus_infty, 0.0, -M_PI_2l);
+  TEST_c_c (catanh, minus_infty, plus_infty, minus_zero, M_PI_2l);
+  TEST_c_c (catanh, minus_infty, minus_infty, minus_zero, -M_PI_2l);
+
+  TEST_c_c (catanh, -10.0, plus_infty, minus_zero, M_PI_2l);
+  TEST_c_c (catanh, -10.0, minus_infty, minus_zero, -M_PI_2l);
+  TEST_c_c (catanh, minus_zero, plus_infty, minus_zero, M_PI_2l);
+  TEST_c_c (catanh, minus_zero, minus_infty, minus_zero, -M_PI_2l);
+  TEST_c_c (catanh, 0, plus_infty, 0.0, M_PI_2l);
+  TEST_c_c (catanh, 0, minus_infty, 0.0, -M_PI_2l);
+  TEST_c_c (catanh, 0.1L, plus_infty, 0.0, M_PI_2l);
+  TEST_c_c (catanh, 0.1L, minus_infty, 0.0, -M_PI_2l);
+
+  TEST_c_c (catanh, minus_infty, 0, minus_zero, M_PI_2l);
+  TEST_c_c (catanh, minus_infty, minus_zero, minus_zero, -M_PI_2l);
+  TEST_c_c (catanh, minus_infty, 100, minus_zero, M_PI_2l);
+  TEST_c_c (catanh, minus_infty, -100, minus_zero, -M_PI_2l);
+
+  TEST_c_c (catanh, plus_infty, 0, 0.0, M_PI_2l);
+  TEST_c_c (catanh, plus_infty, minus_zero, 0.0, -M_PI_2l);
+  TEST_c_c (catanh, plus_infty, 0.5, 0.0, M_PI_2l);
+  TEST_c_c (catanh, plus_infty, -0.5, 0.0, -M_PI_2l);
+
+  TEST_c_c (catanh, 0, nan_value, 0.0, nan_value);
+  TEST_c_c (catanh, minus_zero, nan_value, minus_zero, nan_value);
+
+  TEST_c_c (catanh, plus_infty, nan_value, 0.0, nan_value);
+  TEST_c_c (catanh, minus_infty, nan_value, minus_zero, nan_value);
+
+  TEST_c_c (catanh, nan_value, 0, nan_value, nan_value);
+  TEST_c_c (catanh, nan_value, minus_zero, nan_value, nan_value);
+
+  TEST_c_c (catanh, nan_value, plus_infty, 0.0, M_PI_2l, IGNORE_ZERO_INF_SIGN);
+  TEST_c_c (catanh, nan_value, minus_infty, 0.0, -M_PI_2l, IGNORE_ZERO_INF_SIGN);
+
+  TEST_c_c (catanh, 10.5, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK);
+  TEST_c_c (catanh, -10.5, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK);
+
+  TEST_c_c (catanh, nan_value, 0.75, nan_value, nan_value, INVALID_EXCEPTION_OK);
+  TEST_c_c (catanh, nan_value, -0.75, nan_value, nan_value, INVALID_EXCEPTION_OK);
+
+  TEST_c_c (catanh, nan_value, nan_value, nan_value, nan_value);
+
+  TEST_c_c (catanh, 0.75L, 1.25L, 0.261492138795671927078652057366532140L, 0.996825126463918666098902241310446708L);
+  TEST_c_c (catanh, -2, -3, -0.14694666622552975204743278515471595L, -1.3389725222944935611241935759091443L);
+
+  END (catanh, complex);
+}
+#endif
+
+static void
+cbrt_test (void)
+{
+  errno = 0;
+  FUNC(cbrt) (8);
+  if (errno == ENOSYS)
+    /* Function not implemented.  */
+    return;
+
+  START (cbrt);
+
+  TEST_f_f (cbrt, 0.0, 0.0);
+  TEST_f_f (cbrt, minus_zero, minus_zero);
+
+  TEST_f_f (cbrt, plus_infty, plus_infty);
+  TEST_f_f (cbrt, minus_infty, minus_infty);
+  TEST_f_f (cbrt, nan_value, nan_value);
+
+  TEST_f_f (cbrt, -0.001L, -0.1L);
+  TEST_f_f (cbrt, 8, 2);
+  TEST_f_f (cbrt, -27.0, -3.0);
+  TEST_f_f (cbrt, 0.9921875L, 0.997389022060725270579075195353955217L);
+  TEST_f_f (cbrt, 0.75L, 0.908560296416069829445605878163630251L);
+
+  END (cbrt);
+}
+
+
+#if 0
+static void
+ccos_test (void)
+{
+  errno = 0;
+  FUNC(ccos) (BUILD_COMPLEX (0, 0));
+  if (errno == ENOSYS)
+    /* Function not implemented.  */
+    return;
+
+  START (ccos);
+
+  TEST_c_c (ccos, 0.0, 0.0, 1.0, minus_zero);
+  TEST_c_c (ccos, minus_zero, 0.0, 1.0, 0.0);
+  TEST_c_c (ccos, 0.0, minus_zero, 1.0, 0.0);
+  TEST_c_c (ccos, minus_zero, minus_zero, 1.0, minus_zero);
+
+  TEST_c_c (ccos, plus_infty, 0.0, nan_value, 0.0, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN);
+  TEST_c_c (ccos, plus_infty, minus_zero, nan_value, 0.0, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN);
+  TEST_c_c (ccos, minus_infty, 0.0, nan_value, 0.0, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN);
+  TEST_c_c (ccos, minus_infty, minus_zero, nan_value, 0.0, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN);
+
+  TEST_c_c (ccos, 0.0, plus_infty, plus_infty, minus_zero);
+  TEST_c_c (ccos, 0.0, minus_infty, plus_infty, 0.0);
+  TEST_c_c (ccos, minus_zero, plus_infty, plus_infty, 0.0);
+  TEST_c_c (ccos, minus_zero, minus_infty, plus_infty, minus_zero);
+
+  TEST_c_c (ccos, plus_infty, plus_infty, plus_infty, nan_value, INVALID_EXCEPTION);
+  TEST_c_c (ccos, minus_infty, plus_infty, plus_infty, nan_value, INVALID_EXCEPTION);
+  TEST_c_c (ccos, plus_infty, minus_infty, plus_infty, nan_value, INVALID_EXCEPTION);
+  TEST_c_c (ccos, minus_infty, minus_infty, plus_infty, nan_value, INVALID_EXCEPTION);
+
+  TEST_c_c (ccos, 4.625, plus_infty, minus_infty, plus_infty);
+  TEST_c_c (ccos, 4.625, minus_infty, minus_infty, minus_infty);
+  TEST_c_c (ccos, -4.625, plus_infty, minus_infty, minus_infty);
+  TEST_c_c (ccos, -4.625, minus_infty, minus_infty, plus_infty);
+
+  TEST_c_c (ccos, plus_infty, 6.75, nan_value, nan_value, INVALID_EXCEPTION);
+  TEST_c_c (ccos, plus_infty, -6.75, nan_value, nan_value, INVALID_EXCEPTION);
+  TEST_c_c (ccos, minus_infty, 6.75, nan_value, nan_value, INVALID_EXCEPTION);
+  TEST_c_c (ccos, minus_infty, -6.75, nan_value, nan_value, INVALID_EXCEPTION);
+
+  TEST_c_c (ccos, nan_value, 0.0, nan_value, 0.0, IGNORE_ZERO_INF_SIGN);
+  TEST_c_c (ccos, nan_value, minus_zero, nan_value, 0.0, IGNORE_ZERO_INF_SIGN);
+
+  TEST_c_c (ccos, nan_value, plus_infty, plus_infty, nan_value);
+  TEST_c_c (ccos, nan_value, minus_infty, plus_infty, nan_value);
+
+  TEST_c_c (ccos, nan_value, 9.0, nan_value, nan_value, INVALID_EXCEPTION_OK);
+  TEST_c_c (ccos, nan_value, -9.0, nan_value, nan_value, INVALID_EXCEPTION_OK);
+
+  TEST_c_c (ccos, 0.0, nan_value, nan_value, 0.0, IGNORE_ZERO_INF_SIGN);
+  TEST_c_c (ccos, minus_zero, nan_value, nan_value, 0.0, IGNORE_ZERO_INF_SIGN);
+
+  TEST_c_c (ccos, 10.0, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK);
+  TEST_c_c (ccos, -10.0, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK);
+
+  TEST_c_c (ccos, plus_infty, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK);
+  TEST_c_c (ccos, minus_infty, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK);
+
+  TEST_c_c (ccos, nan_value, nan_value, nan_value, nan_value);
+
+  TEST_c_c (ccos, 0.75L, 1.25L, 1.38173873063425888530729933139078645L, -1.09193013555397466170919531722024128L);
+  TEST_c_c (ccos, -2, -3, -4.18962569096880723013255501961597373L, -9.10922789375533659797919726277886212L);
+
+  END (ccos, complex);
+}
+
+
+static void
+ccosh_test (void)
+{
+  errno = 0;
+  FUNC(ccosh) (BUILD_COMPLEX (0.7L, 1.2L));
+  if (errno == ENOSYS)
+    /* Function not implemented.  */
+    return;
+
+  START (ccosh);
+
+  TEST_c_c (ccosh, 0.0, 0.0, 1.0, 0.0);
+  TEST_c_c (ccosh, minus_zero, 0.0, 1.0, minus_zero);
+  TEST_c_c (ccosh, 0.0, minus_zero, 1.0, minus_zero);
+  TEST_c_c (ccosh, minus_zero, minus_zero, 1.0, 0.0);
+
+  TEST_c_c (ccosh, 0.0, plus_infty, nan_value, 0.0, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN);
+  TEST_c_c (ccosh, minus_zero, plus_infty, nan_value, 0.0, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN);
+  TEST_c_c (ccosh, 0.0, minus_infty, nan_value, 0.0, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN);
+  TEST_c_c (ccosh, minus_zero, minus_infty, nan_value, 0.0, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN);
+
+  TEST_c_c (ccosh, plus_infty, 0.0, plus_infty, 0.0);
+  TEST_c_c (ccosh, minus_infty, 0.0, plus_infty, minus_zero);
+  TEST_c_c (ccosh, plus_infty, minus_zero, plus_infty, minus_zero);
+  TEST_c_c (ccosh, minus_infty, minus_zero, plus_infty, 0.0);
+
+  TEST_c_c (ccosh, plus_infty, plus_infty, plus_infty, nan_value, INVALID_EXCEPTION);
+  TEST_c_c (ccosh, minus_infty, plus_infty, plus_infty, nan_value, INVALID_EXCEPTION);
+  TEST_c_c (ccosh, plus_infty, minus_infty, plus_infty, nan_value, INVALID_EXCEPTION);
+  TEST_c_c (ccosh, minus_infty, minus_infty, plus_infty, nan_value, INVALID_EXCEPTION);
+
+  TEST_c_c (ccosh, plus_infty, 4.625, minus_infty, minus_infty);
+  TEST_c_c (ccosh, minus_infty, 4.625, minus_infty, plus_infty);
+  TEST_c_c (ccosh, plus_infty, -4.625, minus_infty, plus_infty);
+  TEST_c_c (ccosh, minus_infty, -4.625, minus_infty, minus_infty);
+
+  TEST_c_c (ccosh, 6.75, plus_infty, nan_value, nan_value, INVALID_EXCEPTION);
+  TEST_c_c (ccosh, -6.75, plus_infty, nan_value, nan_value, INVALID_EXCEPTION);
+  TEST_c_c (ccosh, 6.75, minus_infty, nan_value, nan_value, INVALID_EXCEPTION);
+  TEST_c_c (ccosh, -6.75, minus_infty, nan_value, nan_value, INVALID_EXCEPTION);
+
+  TEST_c_c (ccosh, 0.0, nan_value, nan_value, 0.0, IGNORE_ZERO_INF_SIGN);
+  TEST_c_c (ccosh, minus_zero, nan_value, nan_value, 0.0, IGNORE_ZERO_INF_SIGN);
+
+  TEST_c_c (ccosh, plus_infty, nan_value, plus_infty, nan_value);
+  TEST_c_c (ccosh, minus_infty, nan_value, plus_infty, nan_value);
+
+  TEST_c_c (ccosh, 9.0, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK);
+  TEST_c_c (ccosh, -9.0, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK);
+
+  TEST_c_c (ccosh, nan_value, 0.0, nan_value, 0.0, IGNORE_ZERO_INF_SIGN);
+  TEST_c_c (ccosh, nan_value, minus_zero, nan_value, 0.0, IGNORE_ZERO_INF_SIGN);
+
+  TEST_c_c (ccosh, nan_value, 10.0, nan_value, nan_value, INVALID_EXCEPTION_OK);
+  TEST_c_c (ccosh, nan_value, -10.0, nan_value, nan_value, INVALID_EXCEPTION_OK);
+
+  TEST_c_c (ccosh, nan_value, plus_infty, nan_value, nan_value, INVALID_EXCEPTION_OK);
+  TEST_c_c (ccosh, nan_value, minus_infty, nan_value, nan_value, INVALID_EXCEPTION_OK);
+
+  TEST_c_c (ccosh, nan_value, nan_value, nan_value, nan_value);
+
+  TEST_c_c (ccosh, 0.75L, 1.25L, 0.408242591877968807788852146397499084L, 0.780365930845853240391326216300863152L);
+
+  TEST_c_c (ccosh, -2, -3, -3.72454550491532256547397070325597253L, 0.511822569987384608834463849801875634L);
+
+  END (ccosh, complex);
+}
+#endif
+
+
+static void
+ceil_test (void)
+{
+  START (ceil);
+
+  TEST_f_f (ceil, 0.0, 0.0);
+  TEST_f_f (ceil, minus_zero, minus_zero);
+  TEST_f_f (ceil, plus_infty, plus_infty);
+  TEST_f_f (ceil, minus_infty, minus_infty);
+  TEST_f_f (ceil, nan_value, nan_value);
+
+  TEST_f_f (ceil, M_PIl, 4.0);
+  TEST_f_f (ceil, -M_PIl, -3.0);
+  TEST_f_f (ceil, 0.25, 1.0);
+  TEST_f_f (ceil, -0.25, minus_zero);
+
+#ifdef TEST_LDOUBLE
+  /* The result can only be represented in long double.  */
+  TEST_f_f (ceil, 4503599627370495.5L, 4503599627370496.0L);
+  TEST_f_f (ceil, 4503599627370496.25L, 4503599627370497.0L);
+  TEST_f_f (ceil, 4503599627370496.5L, 4503599627370497.0L);
+  TEST_f_f (ceil, 4503599627370496.75L, 4503599627370497.0L);
+  TEST_f_f (ceil, 4503599627370497.5L, 4503599627370498.0L);
+
+  TEST_f_f (ceil, -4503599627370495.5L, -4503599627370495.0L);
+  TEST_f_f (ceil, -4503599627370496.25L, -4503599627370496.0L);
+  TEST_f_f (ceil, -4503599627370496.5L, -4503599627370496.0L);
+  TEST_f_f (ceil, -4503599627370496.75L, -4503599627370496.0L);
+  TEST_f_f (ceil, -4503599627370497.5L, -4503599627370497.0L);
+
+  TEST_f_f (ceil, 9007199254740991.5L, 9007199254740992.0L);
+  TEST_f_f (ceil, 9007199254740992.25L, 9007199254740993.0L);
+  TEST_f_f (ceil, 9007199254740992.5L, 9007199254740993.0L);
+  TEST_f_f (ceil, 9007199254740992.75L, 9007199254740993.0L);
+  TEST_f_f (ceil, 9007199254740993.5L, 9007199254740994.0L);
+
+  TEST_f_f (ceil, -9007199254740991.5L, -9007199254740991.0L);
+  TEST_f_f (ceil, -9007199254740992.25L, -9007199254740992.0L);
+  TEST_f_f (ceil, -9007199254740992.5L, -9007199254740992.0L);
+  TEST_f_f (ceil, -9007199254740992.75L, -9007199254740992.0L);
+  TEST_f_f (ceil, -9007199254740993.5L, -9007199254740993.0L);
+
+  TEST_f_f (ceil, 72057594037927935.5L, 72057594037927936.0L);
+  TEST_f_f (ceil, 72057594037927936.25L, 72057594037927937.0L);
+  TEST_f_f (ceil, 72057594037927936.5L, 72057594037927937.0L);
+  TEST_f_f (ceil, 72057594037927936.75L, 72057594037927937.0L);
+  TEST_f_f (ceil, 72057594037927937.5L, 72057594037927938.0L);
+
+  TEST_f_f (ceil, -72057594037927935.5L, -72057594037927935.0L);
+  TEST_f_f (ceil, -72057594037927936.25L, -72057594037927936.0L);
+  TEST_f_f (ceil, -72057594037927936.5L, -72057594037927936.0L);
+  TEST_f_f (ceil, -72057594037927936.75L, -72057594037927936.0L);
+  TEST_f_f (ceil, -72057594037927937.5L, -72057594037927937.0L);
+
+  TEST_f_f (ceil, 10141204801825835211973625643007.5L, 10141204801825835211973625643008.0L);
+  TEST_f_f (ceil, 10141204801825835211973625643008.25L, 10141204801825835211973625643009.0L);
+  TEST_f_f (ceil, 10141204801825835211973625643008.5L, 10141204801825835211973625643009.0L);
+  TEST_f_f (ceil, 10141204801825835211973625643008.75L, 10141204801825835211973625643009.0L);
+  TEST_f_f (ceil, 10141204801825835211973625643009.5L, 10141204801825835211973625643010.0L);
+#endif
+
+  END (ceil);
+}
+
+
+#if 0
+static void
+cexp_test (void)
+{
+  errno = 0;
+  FUNC(cexp) (BUILD_COMPLEX (0, 0));
+  if (errno == ENOSYS)
+    /* Function not implemented.  */
+    return;
+
+  START (cexp);
+
+  TEST_c_c (cexp, plus_zero, plus_zero, 1, 0.0);
+  TEST_c_c (cexp, minus_zero, plus_zero, 1, 0.0);
+  TEST_c_c (cexp, plus_zero, minus_zero, 1, minus_zero);
+  TEST_c_c (cexp, minus_zero, minus_zero, 1, minus_zero);
+
+  TEST_c_c (cexp, plus_infty, plus_zero, plus_infty, 0.0);
+  TEST_c_c (cexp, plus_infty, minus_zero, plus_infty, minus_zero);
+
+  TEST_c_c (cexp, minus_infty, plus_zero, 0.0, 0.0);
+  TEST_c_c (cexp, minus_infty, minus_zero, 0.0, minus_zero);
+
+  TEST_c_c (cexp, 0.0, plus_infty, nan_value, nan_value, INVALID_EXCEPTION);
+  TEST_c_c (cexp, minus_zero, plus_infty, nan_value, nan_value, INVALID_EXCEPTION);
+
+  TEST_c_c (cexp, 0.0, minus_infty, nan_value, nan_value, INVALID_EXCEPTION);
+  TEST_c_c (cexp, minus_zero, minus_infty, nan_value, nan_value, INVALID_EXCEPTION);
+
+  TEST_c_c (cexp, 100.0, plus_infty, nan_value, nan_value, INVALID_EXCEPTION);
+  TEST_c_c (cexp, -100.0, plus_infty, nan_value, nan_value, INVALID_EXCEPTION);
+
+  TEST_c_c (cexp, 100.0, minus_infty, nan_value, nan_value, INVALID_EXCEPTION);
+  TEST_c_c (cexp, -100.0, minus_infty, nan_value, nan_value, INVALID_EXCEPTION);
+
+  TEST_c_c (cexp, minus_infty, 2.0, minus_zero, 0.0);
+  TEST_c_c (cexp, minus_infty, 4.0, minus_zero, minus_zero);
+  TEST_c_c (cexp, plus_infty, 2.0, minus_infty, plus_infty);
+  TEST_c_c (cexp, plus_infty, 4.0, minus_infty, minus_infty);
+
+  TEST_c_c (cexp, plus_infty, plus_infty, plus_infty, nan_value, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN);
+  TEST_c_c (cexp, plus_infty, minus_infty, plus_infty, nan_value, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN);
+
+  TEST_c_c (cexp, minus_infty, plus_infty, 0.0, 0.0, IGNORE_ZERO_INF_SIGN);
+  TEST_c_c (cexp, minus_infty, minus_infty, 0.0, minus_zero, IGNORE_ZERO_INF_SIGN);
+
+  TEST_c_c (cexp, minus_infty, nan_value, 0, 0, IGNORE_ZERO_INF_SIGN);
+
+  TEST_c_c (cexp, plus_infty, nan_value, plus_infty, nan_value);
+
+  TEST_c_c (cexp, nan_value, 0.0, nan_value, nan_value, INVALID_EXCEPTION_OK);
+  TEST_c_c (cexp, nan_value, 1.0, nan_value, nan_value, INVALID_EXCEPTION_OK);
+
+  TEST_c_c (cexp, nan_value, plus_infty, nan_value, nan_value, INVALID_EXCEPTION_OK);
+  TEST_c_c (cexp, 0, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK);
+  TEST_c_c (cexp, 1, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK);
+  TEST_c_c (cexp, nan_value, nan_value, nan_value, nan_value);
+
+  TEST_c_c (cexp, 0.75L, 1.25L, 0.667537446429131586942201977015932112L, 2.00900045494094876258347228145863909L);
+  TEST_c_c (cexp, -2.0, -3.0, -0.13398091492954261346140525546115575L, -0.019098516261135196432576240858800925L);
+
+  END (cexp, complex);
+}
+
+
+static void
+cimag_test (void)
+{
+  START (cimag);
+  TEST_c_f (cimag, 1.0, 0.0, 0.0);
+  TEST_c_f (cimag, 1.0, minus_zero, minus_zero);
+  TEST_c_f (cimag, 1.0, nan_value, nan_value);
+  TEST_c_f (cimag, nan_value, nan_value, nan_value);
+  TEST_c_f (cimag, 1.0, plus_infty, plus_infty);
+  TEST_c_f (cimag, 1.0, minus_infty, minus_infty);
+  TEST_c_f (cimag, 2.0, 3.0, 3.0);
+
+  END (cimag);
+}
+
+static void
+clog_test (void)
+{
+  errno = 0;
+  FUNC(clog) (BUILD_COMPLEX (-2, -3));
+  if (errno == ENOSYS)
+    /* Function not implemented.  */
+    return;
+
+  START (clog);
+
+  TEST_c_c (clog, minus_zero, 0, minus_infty, M_PIl, DIVIDE_BY_ZERO_EXCEPTION);
+  TEST_c_c (clog, minus_zero, minus_zero, minus_infty, -M_PIl, DIVIDE_BY_ZERO_EXCEPTION);
+
+  TEST_c_c (clog, 0, 0, minus_infty, 0.0, DIVIDE_BY_ZERO_EXCEPTION);
+  TEST_c_c (clog, 0, minus_zero, minus_infty, minus_zero, DIVIDE_BY_ZERO_EXCEPTION);
+
+  TEST_c_c (clog, minus_infty, plus_infty, plus_infty, M_PI_34l);
+  TEST_c_c (clog, minus_infty, minus_infty, plus_infty, -M_PI_34l);
+
+  TEST_c_c (clog, plus_infty, plus_infty, plus_infty, M_PI_4l);
+  TEST_c_c (clog, plus_infty, minus_infty, plus_infty, -M_PI_4l);
+
+  TEST_c_c (clog, 0, plus_infty, plus_infty, M_PI_2l);
+  TEST_c_c (clog, 3, plus_infty, plus_infty, M_PI_2l);
+  TEST_c_c (clog, minus_zero, plus_infty, plus_infty, M_PI_2l);
+  TEST_c_c (clog, -3, plus_infty, plus_infty, M_PI_2l);
+  TEST_c_c (clog, 0, minus_infty, plus_infty, -M_PI_2l);
+  TEST_c_c (clog, 3, minus_infty, plus_infty, -M_PI_2l);
+  TEST_c_c (clog, minus_zero, minus_infty, plus_infty, -M_PI_2l);
+  TEST_c_c (clog, -3, minus_infty, plus_infty, -M_PI_2l);
+
+  TEST_c_c (clog, minus_infty, 0, plus_infty, M_PIl);
+  TEST_c_c (clog, minus_infty, 1, plus_infty, M_PIl);
+  TEST_c_c (clog, minus_infty, minus_zero, plus_infty, -M_PIl);
+  TEST_c_c (clog, minus_infty, -1, plus_infty, -M_PIl);
+
+  TEST_c_c (clog, plus_infty, 0, plus_infty, 0.0);
+  TEST_c_c (clog, plus_infty, 1, plus_infty, 0.0);
+  TEST_c_c (clog, plus_infty, minus_zero, plus_infty, minus_zero);
+  TEST_c_c (clog, plus_infty, -1, plus_infty, minus_zero);
+
+  TEST_c_c (clog, plus_infty, nan_value, plus_infty, nan_value);
+  TEST_c_c (clog, minus_infty, nan_value, plus_infty, nan_value);
+
+  TEST_c_c (clog, nan_value, plus_infty, plus_infty, nan_value);
+  TEST_c_c (clog, nan_value, minus_infty, plus_infty, nan_value);
+
+  TEST_c_c (clog, 0, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK);
+  TEST_c_c (clog, 3, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK);
+  TEST_c_c (clog, minus_zero, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK);
+  TEST_c_c (clog, -3, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK);
+
+  TEST_c_c (clog, nan_value, 0, nan_value, nan_value, INVALID_EXCEPTION_OK);
+  TEST_c_c (clog, nan_value, 5, nan_value, nan_value, INVALID_EXCEPTION_OK);
+  TEST_c_c (clog, nan_value, minus_zero, nan_value, nan_value, INVALID_EXCEPTION_OK);
+  TEST_c_c (clog, nan_value, -5, nan_value, nan_value, INVALID_EXCEPTION_OK);
+
+  TEST_c_c (clog, nan_value, nan_value, nan_value, nan_value);
+
+  TEST_c_c (clog, 0.75L, 1.25L, 0.376885901188190075998919126749298416L, 1.03037682652431246378774332703115153L);
+  TEST_c_c (clog, -2, -3, 1.2824746787307683680267437207826593L, -2.1587989303424641704769327722648368L);
+
+  END (clog, complex);
+}
+
+
+static void
+clog10_test (void)
+{
+  errno = 0;
+  FUNC(clog10) (BUILD_COMPLEX (0.7L, 1.2L));
+  if (errno == ENOSYS)
+    /* Function not implemented.  */
+    return;
+
+  START (clog10);
+
+  TEST_c_c (clog10, minus_zero, 0, minus_infty, M_PIl, DIVIDE_BY_ZERO_EXCEPTION);
+  TEST_c_c (clog10, minus_zero, minus_zero, minus_infty, -M_PIl, DIVIDE_BY_ZERO_EXCEPTION);
+
+  TEST_c_c (clog10, 0, 0, minus_infty, 0.0, DIVIDE_BY_ZERO_EXCEPTION);
+  TEST_c_c (clog10, 0, minus_zero, minus_infty, minus_zero, DIVIDE_BY_ZERO_EXCEPTION);
+
+  TEST_c_c (clog10, minus_infty, plus_infty, plus_infty, M_PI_34_LOG10El);
+
+  TEST_c_c (clog10, plus_infty, plus_infty, plus_infty, M_PI4_LOG10El);
+  TEST_c_c (clog10, plus_infty, minus_infty, plus_infty, -M_PI4_LOG10El);
+
+  TEST_c_c (clog10, 0, plus_infty, plus_infty, M_PI2_LOG10El);
+  TEST_c_c (clog10, 3, plus_infty, plus_infty, M_PI2_LOG10El);
+  TEST_c_c (clog10, minus_zero, plus_infty, plus_infty, M_PI2_LOG10El);
+  TEST_c_c (clog10, -3, plus_infty, plus_infty, M_PI2_LOG10El);
+  TEST_c_c (clog10, 0, minus_infty, plus_infty, -M_PI2_LOG10El);
+  TEST_c_c (clog10, 3, minus_infty, plus_infty, -M_PI2_LOG10El);
+  TEST_c_c (clog10, minus_zero, minus_infty, plus_infty, -M_PI2_LOG10El);
+  TEST_c_c (clog10, -3, minus_infty, plus_infty, -M_PI2_LOG10El);
+
+  TEST_c_c (clog10, minus_infty, 0, plus_infty, M_PI_LOG10El);
+  TEST_c_c (clog10, minus_infty, 1, plus_infty, M_PI_LOG10El);
+  TEST_c_c (clog10, minus_infty, minus_zero, plus_infty, -M_PI_LOG10El);
+  TEST_c_c (clog10, minus_infty, -1, plus_infty, -M_PI_LOG10El);
+
+  TEST_c_c (clog10, plus_infty, 0, plus_infty, 0.0);
+  TEST_c_c (clog10, plus_infty, 1, plus_infty, 0.0);
+  TEST_c_c (clog10, plus_infty, minus_zero, plus_infty, minus_zero);
+  TEST_c_c (clog10, plus_infty, -1, plus_infty, minus_zero);
+
+  TEST_c_c (clog10, plus_infty, nan_value, plus_infty, nan_value);
+  TEST_c_c (clog10, minus_infty, nan_value, plus_infty, nan_value);
+
+  TEST_c_c (clog10, nan_value, plus_infty, plus_infty, nan_value);
+  TEST_c_c (clog10, nan_value, minus_infty, plus_infty, nan_value);
+
+  TEST_c_c (clog10, 0, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK);
+  TEST_c_c (clog10, 3, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK);
+  TEST_c_c (clog10, minus_zero, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK);
+  TEST_c_c (clog10, -3, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK);
+
+  TEST_c_c (clog10, nan_value, 0, nan_value, nan_value, INVALID_EXCEPTION_OK);
+  TEST_c_c (clog10, nan_value, 5, nan_value, nan_value, INVALID_EXCEPTION_OK);
+  TEST_c_c (clog10, nan_value, minus_zero, nan_value, nan_value, INVALID_EXCEPTION_OK);
+  TEST_c_c (clog10, nan_value, -5, nan_value, nan_value, INVALID_EXCEPTION_OK);
+
+  TEST_c_c (clog10, nan_value, nan_value, nan_value, nan_value);
+
+  TEST_c_c (clog10, 0.75L, 1.25L, 0.163679467193165171449476605077428975L, 0.447486970040493067069984724340855636L);
+  TEST_c_c (clog10, -2, -3, 0.556971676153418384603252578971164214L, -0.937554462986374708541507952140189646L);
+
+  END (clog10, complex);
+}
+#endif
+
+
+#if 0
+static void
+conj_test (void)
+{
+  START (conj);
+  TEST_c_c (conj, 0.0, 0.0, 0.0, minus_zero);
+  TEST_c_c (conj, 0.0, minus_zero, 0.0, 0.0);
+  TEST_c_c (conj, nan_value, nan_value, nan_value, nan_value);
+  TEST_c_c (conj, plus_infty, minus_infty, plus_infty, plus_infty);
+  TEST_c_c (conj, plus_infty, plus_infty, plus_infty, minus_infty);
+  TEST_c_c (conj, 1.0, 2.0, 1.0, -2.0);
+  TEST_c_c (conj, 3.0, -4.0, 3.0, 4.0);
+
+  END (conj, complex);
+}
+#endif
+
+
+static void
+copysign_test (void)
+{
+  START (copysign);
+
+  TEST_ff_f (copysign, 0, 4, 0);
+  TEST_ff_f (copysign, 0, -4, minus_zero);
+  TEST_ff_f (copysign, minus_zero, 4, 0);
+  TEST_ff_f (copysign, minus_zero, -4, minus_zero);
+
+  TEST_ff_f (copysign, plus_infty, 0, plus_infty);
+  TEST_ff_f (copysign, plus_infty, minus_zero, minus_infty);
+  TEST_ff_f (copysign, minus_infty, 0, plus_infty);
+  TEST_ff_f (copysign, minus_infty, minus_zero, minus_infty);
+
+  TEST_ff_f (copysign, 0, plus_infty, 0);
+  TEST_ff_f (copysign, 0, minus_zero, minus_zero);
+  TEST_ff_f (copysign, minus_zero, plus_infty, 0);
+  TEST_ff_f (copysign, minus_zero, minus_zero, minus_zero);
+
+  /* XXX More correctly we would have to check the sign of the NaN.  */
+  TEST_ff_f (copysign, nan_value, 0, nan_value);
+  TEST_ff_f (copysign, nan_value, minus_zero, nan_value);
+  TEST_ff_f (copysign, -nan_value, 0, nan_value);
+  TEST_ff_f (copysign, -nan_value, minus_zero, nan_value);
+
+  END (copysign);
+}
+
+
+static void
+cos_test (void)
+{
+  errno = 0;
+  FUNC(cos) (0);
+  if (errno == ENOSYS)
+    /* Function not implemented.  */
+    return;
+
+  START (cos);
+
+  TEST_f_f (cos, 0, 1);
+  TEST_f_f (cos, minus_zero, 1);
+  TEST_f_f (cos, plus_infty, nan_value, INVALID_EXCEPTION);
+  TEST_f_f (cos, minus_infty, nan_value, INVALID_EXCEPTION);
+  TEST_f_f (cos, nan_value, nan_value);
+
+  TEST_f_f (cos, M_PI_6l * 2.0, 0.5);
+  TEST_f_f (cos, M_PI_6l * 4.0, -0.5);
+  TEST_f_f (cos, M_PI_2l, 0);
+
+  TEST_f_f (cos, 0.75L, 0.731688868873820886311838753000084544L);
+
+#ifdef TEST_DOUBLE
+  TEST_f_f (cos, 0.80190127184058835, 0.69534156199418473);
+#endif
+
+  END (cos);
+}
+
+
+static void
+cosh_test (void)
+{
+  errno = 0;
+  FUNC(cosh) (0.7L);
+  if (errno == ENOSYS)
+    /* Function not implemented.  */
+    return;
+
+  START (cosh);
+  TEST_f_f (cosh, 0, 1);
+  TEST_f_f (cosh, minus_zero, 1);
+
+#ifndef TEST_INLINE
+  TEST_f_f (cosh, plus_infty, plus_infty);
+  TEST_f_f (cosh, minus_infty, plus_infty);
+#endif
+  TEST_f_f (cosh, nan_value, nan_value);
+
+  TEST_f_f (cosh, 0.75L, 1.29468328467684468784170818539018176L);
+
+  END (cosh);
+}
+
+
+#if 0
+static void
+cpow_test (void)
+{
+  errno = 0;
+  FUNC(cpow) (BUILD_COMPLEX (1, 0), BUILD_COMPLEX (0, 0));
+  if (errno == ENOSYS)
+    /* Function not implemented.  */
+    return;
+
+  START (cpow);
+
+  TEST_cc_c (cpow, 1, 0, 0, 0, 1.0, 0.0);
+  TEST_cc_c (cpow, 2, 0, 10, 0, 1024.0, 0.0);
+
+  TEST_cc_c (cpow, M_El, 0, 0, 2 * M_PIl, 1.0, 0.0);
+  TEST_cc_c (cpow, 2, 3, 4, 0, -119.0, -120.0);
+
+  TEST_cc_c (cpow, nan_value, nan_value, nan_value, nan_value, nan_value, nan_value);
+
+  TEST_cc_c (cpow, 0.75L, 1.25L, 0.75L, 1.25L, 0.117506293914473555420279832210420483L, 0.346552747708338676483025352060418001L);
+  TEST_cc_c (cpow, 0.75L, 1.25L, 1.0L, 1.0L, 0.0846958290317209430433805274189191353L, 0.513285749182902449043287190519090481L);
+  TEST_cc_c (cpow, 0.75L, 1.25L, 1.0L, 0.0L, 0.75L, 1.25L);
+  TEST_cc_c (cpow, 0.75L, 1.25L, 0.0L, 1.0L, 0.331825439177608832276067945276730566L, 0.131338600281188544930936345230903032L);
+
+  END (cpow, complex);
+}
+
+
+static void
+cproj_test (void)
+{
+  START (cproj);
+  TEST_c_c (cproj, 0.0, 0.0, 0.0, 0.0);
+  TEST_c_c (cproj, minus_zero, minus_zero, minus_zero, minus_zero);
+  TEST_c_c (cproj, 0.0, minus_zero, 0.0, minus_zero);
+  TEST_c_c (cproj, minus_zero, 0.0, minus_zero, 0.0);
+
+  TEST_c_c (cproj, nan_value, nan_value, nan_value, nan_value);
+
+  TEST_c_c (cproj, plus_infty, plus_infty, plus_infty, 0.0);
+  TEST_c_c (cproj, plus_infty, minus_infty, plus_infty, minus_zero);
+  TEST_c_c (cproj, minus_infty, plus_infty, plus_infty, 0.0);
+  TEST_c_c (cproj, minus_infty, minus_infty, plus_infty, minus_zero);
+
+  TEST_c_c (cproj, 1.0, 0.0, 1.0, 0.0);
+  TEST_c_c (cproj, 2.0, 3.0, 0.2857142857142857142857142857142857L, 0.42857142857142857142857142857142855L);
+
+  END (cproj, complex);
+}
+
+
+static void
+creal_test (void)
+{
+  START (creal);
+  TEST_c_f (creal, 0.0, 1.0, 0.0);
+  TEST_c_f (creal, minus_zero, 1.0, minus_zero);
+  TEST_c_f (creal, nan_value, 1.0, nan_value);
+  TEST_c_f (creal, nan_value, nan_value, nan_value);
+  TEST_c_f (creal, plus_infty, 1.0, plus_infty);
+  TEST_c_f (creal, minus_infty, 1.0, minus_infty);
+  TEST_c_f (creal, 2.0, 3.0, 2.0);
+
+  END (creal);
+}
+
+static void
+csin_test (void)
+{
+  errno = 0;
+  FUNC(csin) (BUILD_COMPLEX (0.7L, 1.2L));
+  if (errno == ENOSYS)
+    /* Function not implemented.  */
+    return;
+
+  START (csin);
+
+  TEST_c_c (csin, 0.0, 0.0, 0.0, 0.0);
+  TEST_c_c (csin, minus_zero, 0.0, minus_zero, 0.0);
+  TEST_c_c (csin, 0.0, minus_zero, 0, minus_zero);
+  TEST_c_c (csin, minus_zero, minus_zero, minus_zero, minus_zero);
+
+  TEST_c_c (csin, 0.0, plus_infty, 0.0, plus_infty);
+  TEST_c_c (csin, minus_zero, plus_infty, minus_zero, plus_infty);
+  TEST_c_c (csin, 0.0, minus_infty, 0.0, minus_infty);
+  TEST_c_c (csin, minus_zero, minus_infty, minus_zero, minus_infty);
+
+  TEST_c_c (csin, plus_infty, 0.0, nan_value, 0.0, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN);
+  TEST_c_c (csin, minus_infty, 0.0, nan_value, 0.0, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN);
+  TEST_c_c (csin, plus_infty, minus_zero, nan_value, 0.0, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN);
+  TEST_c_c (csin, minus_infty, minus_zero, nan_value, 0.0, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN);
+
+  TEST_c_c (csin, plus_infty, plus_infty, nan_value, plus_infty, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN);
+  TEST_c_c (csin, minus_infty, plus_infty, nan_value, plus_infty, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN);
+  TEST_c_c (csin, plus_infty, minus_infty, nan_value, plus_infty, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN);
+  TEST_c_c (csin, minus_infty, minus_infty, nan_value, plus_infty, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN);
+
+  TEST_c_c (csin, plus_infty, 6.75, nan_value, nan_value, INVALID_EXCEPTION);
+  TEST_c_c (csin, plus_infty, -6.75, nan_value, nan_value, INVALID_EXCEPTION);
+  TEST_c_c (csin, minus_infty, 6.75, nan_value, nan_value, INVALID_EXCEPTION);
+  TEST_c_c (csin, minus_infty, -6.75,  nan_value, nan_value, INVALID_EXCEPTION);
+
+  TEST_c_c (csin, 4.625, plus_infty, minus_infty, minus_infty);
+  TEST_c_c (csin, 4.625, minus_infty, minus_infty, plus_infty);
+  TEST_c_c (csin, -4.625, plus_infty, plus_infty, minus_infty);
+  TEST_c_c (csin, -4.625, minus_infty, plus_infty, plus_infty);
+
+  TEST_c_c (csin, nan_value, 0.0, nan_value, 0.0, IGNORE_ZERO_INF_SIGN);
+  TEST_c_c (csin, nan_value, minus_zero, nan_value, 0.0, IGNORE_ZERO_INF_SIGN);
+
+  TEST_c_c (csin, nan_value, plus_infty, nan_value, plus_infty, IGNORE_ZERO_INF_SIGN);
+  TEST_c_c (csin, nan_value, minus_infty, nan_value, plus_infty, IGNORE_ZERO_INF_SIGN);
+
+  TEST_c_c (csin, nan_value, 9.0, nan_value, nan_value, INVALID_EXCEPTION_OK);
+  TEST_c_c (csin, nan_value, -9.0, nan_value, nan_value, INVALID_EXCEPTION_OK);
+
+  TEST_c_c (csin, 0.0, nan_value, 0.0, nan_value);
+  TEST_c_c (csin, minus_zero, nan_value, minus_zero, nan_value);
+
+  TEST_c_c (csin, 10.0, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK);
+  TEST_c_c (csin, nan_value, -10.0, nan_value, nan_value, INVALID_EXCEPTION_OK);
+
+  TEST_c_c (csin, plus_infty, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK);
+  TEST_c_c (csin, minus_infty, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK);
+
+  TEST_c_c (csin, nan_value, nan_value, nan_value, nan_value);
+
+  TEST_c_c (csin, 0.75L, 1.25L, 1.28722291002649188575873510790565441L, 1.17210635989270256101081285116138863L);
+  TEST_c_c (csin, -2, -3, -9.15449914691142957346729954460983256L, 4.16890695996656435075481305885375484L);
+
+  END (csin, complex);
+}
+
+
+static void
+csinh_test (void)
+{
+  errno = 0;
+  FUNC(csinh) (BUILD_COMPLEX (0.7L, 1.2L));
+  if (errno == ENOSYS)
+    /* Function not implemented.  */
+    return;
+
+  START (csinh);
+
+  TEST_c_c (csinh, 0.0, 0.0, 0.0, 0.0);
+  TEST_c_c (csinh, minus_zero, 0.0, minus_zero, 0.0);
+  TEST_c_c (csinh, 0.0, minus_zero, 0.0, minus_zero);
+  TEST_c_c (csinh, minus_zero, minus_zero, minus_zero, minus_zero);
+
+  TEST_c_c (csinh, 0.0, plus_infty, 0.0, nan_value, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN);
+  TEST_c_c (csinh, minus_zero, plus_infty, 0.0, nan_value, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN);
+  TEST_c_c (csinh, 0.0, minus_infty, 0.0, nan_value, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN);
+  TEST_c_c (csinh, minus_zero, minus_infty, 0.0, nan_value, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN);
+
+  TEST_c_c (csinh, plus_infty, 0.0, plus_infty, 0.0);
+  TEST_c_c (csinh, minus_infty, 0.0, minus_infty, 0.0);
+  TEST_c_c (csinh, plus_infty, minus_zero, plus_infty, minus_zero);
+  TEST_c_c (csinh, minus_infty, minus_zero, minus_infty, minus_zero);
+
+  TEST_c_c (csinh, plus_infty, plus_infty, plus_infty, nan_value, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN);
+  TEST_c_c (csinh, minus_infty, plus_infty, plus_infty, nan_value, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN);
+  TEST_c_c (csinh, plus_infty, minus_infty, plus_infty, nan_value, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN);
+  TEST_c_c (csinh, minus_infty, minus_infty, plus_infty, nan_value, INVALID_EXCEPTION|IGNORE_ZERO_INF_SIGN);
+
+  TEST_c_c (csinh, plus_infty, 4.625, minus_infty, minus_infty);
+  TEST_c_c (csinh, minus_infty, 4.625, plus_infty, minus_infty);
+  TEST_c_c (csinh, plus_infty, -4.625, minus_infty, plus_infty);
+  TEST_c_c (csinh, minus_infty, -4.625, plus_infty, plus_infty);
+
+  TEST_c_c (csinh, 6.75, plus_infty, nan_value, nan_value, INVALID_EXCEPTION);
+  TEST_c_c (csinh, -6.75, plus_infty, nan_value, nan_value, INVALID_EXCEPTION);
+  TEST_c_c (csinh, 6.75, minus_infty, nan_value, nan_value, INVALID_EXCEPTION);
+  TEST_c_c (csinh, -6.75, minus_infty, nan_value, nan_value, INVALID_EXCEPTION);
+
+  TEST_c_c (csinh, 0.0, nan_value, 0.0, nan_value, IGNORE_ZERO_INF_SIGN);
+  TEST_c_c (csinh, minus_zero, nan_value, 0.0, nan_value, IGNORE_ZERO_INF_SIGN);
+
+  TEST_c_c (csinh, plus_infty, nan_value, plus_infty, nan_value, IGNORE_ZERO_INF_SIGN);
+  TEST_c_c (csinh, minus_infty, nan_value, plus_infty, nan_value, IGNORE_ZERO_INF_SIGN);
+
+  TEST_c_c (csinh, 9.0, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK);
+  TEST_c_c (csinh, -9.0, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK);
+
+  TEST_c_c (csinh, nan_value, 0.0, nan_value, 0.0);
+  TEST_c_c (csinh, nan_value, minus_zero, nan_value, minus_zero);
+
+  TEST_c_c (csinh, nan_value, 10.0, nan_value, nan_value, INVALID_EXCEPTION_OK);
+  TEST_c_c (csinh, nan_value, -10.0, nan_value, nan_value, INVALID_EXCEPTION_OK);
+
+  TEST_c_c (csinh, nan_value, plus_infty, nan_value, nan_value, INVALID_EXCEPTION_OK);
+  TEST_c_c (csinh, nan_value, minus_infty, nan_value, nan_value, INVALID_EXCEPTION_OK);
+
+  TEST_c_c (csinh, nan_value, nan_value, nan_value, nan_value);
+
+  TEST_c_c (csinh, 0.75L, 1.25L, 0.259294854551162779153349830618433028L, 1.22863452409509552219214606515777594L);
+  TEST_c_c (csinh, -2, -3, 3.59056458998577995201256544779481679L, -0.530921086248519805267040090660676560L);
+
+  END (csinh, complex);
+}
+
+
+static void
+csqrt_test (void)
+{
+  errno = 0;
+  FUNC(csqrt) (BUILD_COMPLEX (-1, 0));
+  if (errno == ENOSYS)
+    /* Function not implemented.  */
+    return;
+
+  START (csqrt);
+
+  TEST_c_c (csqrt, 0, 0, 0.0, 0.0);
+  TEST_c_c (csqrt, 0, minus_zero, 0, minus_zero);
+  TEST_c_c (csqrt, minus_zero, 0, 0.0, 0.0);
+  TEST_c_c (csqrt, minus_zero, minus_zero, 0.0, minus_zero);
+
+  TEST_c_c (csqrt, minus_infty, 0, 0.0, plus_infty);
+  TEST_c_c (csqrt, minus_infty, 6, 0.0, plus_infty);
+  TEST_c_c (csqrt, minus_infty, minus_zero, 0.0, minus_infty);
+  TEST_c_c (csqrt, minus_infty, -6, 0.0, minus_infty);
+
+  TEST_c_c (csqrt, plus_infty, 0, plus_infty, 0.0);
+  TEST_c_c (csqrt, plus_infty, 6, plus_infty, 0.0);
+  TEST_c_c (csqrt, plus_infty, minus_zero, plus_infty, minus_zero);
+  TEST_c_c (csqrt, plus_infty, -6, plus_infty, minus_zero);
+
+  TEST_c_c (csqrt, 0, plus_infty, plus_infty, plus_infty);
+  TEST_c_c (csqrt, 4, plus_infty, plus_infty, plus_infty);
+  TEST_c_c (csqrt, plus_infty, plus_infty, plus_infty, plus_infty);
+  TEST_c_c (csqrt, minus_zero, plus_infty, plus_infty, plus_infty);
+  TEST_c_c (csqrt, -4, plus_infty, plus_infty, plus_infty);
+  TEST_c_c (csqrt, minus_infty, plus_infty, plus_infty, plus_infty);
+  TEST_c_c (csqrt, 0, minus_infty, plus_infty, minus_infty);
+  TEST_c_c (csqrt, 4, minus_infty, plus_infty, minus_infty);
+  TEST_c_c (csqrt, plus_infty, minus_infty, plus_infty, minus_infty);
+  TEST_c_c (csqrt, minus_zero, minus_infty, plus_infty, minus_infty);
+  TEST_c_c (csqrt, -4, minus_infty, plus_infty, minus_infty);
+  TEST_c_c (csqrt, minus_infty, minus_infty, plus_infty, minus_infty);
+
+  TEST_c_c (csqrt, minus_infty, nan_value, nan_value, plus_infty, IGNORE_ZERO_INF_SIGN);
+
+  TEST_c_c (csqrt, plus_infty, nan_value, plus_infty, nan_value);
+
+  TEST_c_c (csqrt, 0, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK);
+  TEST_c_c (csqrt, 1, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK);
+  TEST_c_c (csqrt, minus_zero, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK);
+  TEST_c_c (csqrt, -1, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK);
+
+  TEST_c_c (csqrt, nan_value, 0, nan_value, nan_value, INVALID_EXCEPTION_OK);
+  TEST_c_c (csqrt, nan_value, 8, nan_value, nan_value, INVALID_EXCEPTION_OK);
+  TEST_c_c (csqrt, nan_value, minus_zero, nan_value, nan_value, INVALID_EXCEPTION_OK);
+  TEST_c_c (csqrt, nan_value, -8, nan_value, nan_value, INVALID_EXCEPTION_OK);
+
+  TEST_c_c (csqrt, nan_value, nan_value, nan_value, nan_value);
+
+  TEST_c_c (csqrt, 16.0, -30.0, 5.0, -3.0);
+  TEST_c_c (csqrt, -1, 0, 0.0, 1.0);
+  TEST_c_c (csqrt, 0, 2, 1.0, 1.0);
+  TEST_c_c (csqrt, 119, 120, 12.0, 5.0);
+  TEST_c_c (csqrt, 0.75L, 1.25L, 1.05065169626078392338656675760808326L, 0.594868882070379067881984030639932657L);
+  TEST_c_c (csqrt, -2, -3, 0.89597747612983812471573375529004348L, -1.6741492280355400404480393008490519L);
+  TEST_c_c (csqrt, -2, 3, 0.89597747612983812471573375529004348L, 1.6741492280355400404480393008490519L);
+  /* Principal square root should be returned (i.e., non-negative real
+     part).  */
+  TEST_c_c (csqrt, 0, -1, M_SQRT_2_2, -M_SQRT_2_2);
+
+  END (csqrt, complex);
+}
+
+static void
+ctan_test (void)
+{
+  errno = 0;
+  FUNC(ctan) (BUILD_COMPLEX (0.7L, 1.2L));
+  if (errno == ENOSYS)
+    /* Function not implemented.  */
+    return;
+
+  START (ctan);
+
+  TEST_c_c (ctan, 0, 0, 0.0, 0.0);
+  TEST_c_c (ctan, 0, minus_zero, 0.0, minus_zero);
+  TEST_c_c (ctan, minus_zero, 0, minus_zero, 0.0);
+  TEST_c_c (ctan, minus_zero, minus_zero, minus_zero, minus_zero);
+
+  TEST_c_c (ctan, 0, plus_infty, 0.0, 1.0);
+  TEST_c_c (ctan, 1, plus_infty, 0.0, 1.0);
+  TEST_c_c (ctan, minus_zero, plus_infty, minus_zero, 1.0);
+  TEST_c_c (ctan, -1, plus_infty, minus_zero, 1.0);
+
+  TEST_c_c (ctan, 0, minus_infty, 0.0, -1.0);
+  TEST_c_c (ctan, 1, minus_infty, 0.0, -1.0);
+  TEST_c_c (ctan, minus_zero, minus_infty, minus_zero, -1.0);
+  TEST_c_c (ctan, -1, minus_infty, minus_zero, -1.0);
+
+  TEST_c_c (ctan, plus_infty, 0, nan_value, nan_value, INVALID_EXCEPTION);
+  TEST_c_c (ctan, plus_infty, 2, nan_value, nan_value, INVALID_EXCEPTION);
+  TEST_c_c (ctan, minus_infty, 0, nan_value, nan_value, INVALID_EXCEPTION);
+  TEST_c_c (ctan, minus_infty, 2, nan_value, nan_value, INVALID_EXCEPTION);
+  TEST_c_c (ctan, plus_infty, minus_zero, nan_value, nan_value, INVALID_EXCEPTION);
+  TEST_c_c (ctan, plus_infty, -2, nan_value, nan_value, INVALID_EXCEPTION);
+  TEST_c_c (ctan, minus_infty, minus_zero, nan_value, nan_value, INVALID_EXCEPTION);
+  TEST_c_c (ctan, minus_infty, -2, nan_value, nan_value, INVALID_EXCEPTION);
+
+  TEST_c_c (ctan, nan_value, plus_infty, 0.0, 1.0, IGNORE_ZERO_INF_SIGN);
+  TEST_c_c (ctan, nan_value, minus_infty, 0.0, -1.0, IGNORE_ZERO_INF_SIGN);
+
+  TEST_c_c (ctan, 0, nan_value, 0.0, nan_value);
+  TEST_c_c (ctan, minus_zero, nan_value, minus_zero, nan_value);
+
+  TEST_c_c (ctan, 0.5, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK);
+  TEST_c_c (ctan, -4.5, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK);
+
+  TEST_c_c (ctan, nan_value, 0, nan_value, nan_value, INVALID_EXCEPTION_OK);
+  TEST_c_c (ctan, nan_value, 5, nan_value, nan_value, INVALID_EXCEPTION_OK);
+  TEST_c_c (ctan, nan_value, minus_zero, nan_value, nan_value, INVALID_EXCEPTION_OK);
+  TEST_c_c (ctan, nan_value, -0.25, nan_value, nan_value, INVALID_EXCEPTION_OK);
+
+  TEST_c_c (ctan, nan_value, nan_value, nan_value, nan_value);
+
+  TEST_c_c (ctan, 0.75L, 1.25L, 0.160807785916206426725166058173438663L, 0.975363285031235646193581759755216379L);
+  TEST_c_c (ctan, -2, -3, 0.376402564150424829275122113032269084e-2L, -1.00323862735360980144635859782192726L);
+
+  END (ctan, complex);
+}
+
+
+static void
+ctanh_test (void)
+{
+  errno = 0;
+  FUNC(ctanh) (BUILD_COMPLEX (0, 0));
+  if (errno == ENOSYS)
+    /* Function not implemented.  */
+    return;
+
+  START (ctanh);
+
+  TEST_c_c (ctanh, 0, 0, 0.0, 0.0);
+  TEST_c_c (ctanh, 0, minus_zero, 0.0, minus_zero);
+  TEST_c_c (ctanh, minus_zero, 0, minus_zero, 0.0);
+  TEST_c_c (ctanh, minus_zero, minus_zero, minus_zero, minus_zero);
+
+  TEST_c_c (ctanh, plus_infty, 0, 1.0, 0.0);
+  TEST_c_c (ctanh, plus_infty, 1, 1.0, 0.0);
+  TEST_c_c (ctanh, plus_infty, minus_zero, 1.0, minus_zero);
+  TEST_c_c (ctanh, plus_infty, -1, 1.0, minus_zero);
+  TEST_c_c (ctanh, minus_infty, 0, -1.0, 0.0);
+  TEST_c_c (ctanh, minus_infty, 1, -1.0, 0.0);
+  TEST_c_c (ctanh, minus_infty, minus_zero, -1.0, minus_zero);
+  TEST_c_c (ctanh, minus_infty, -1, -1.0, minus_zero);
+
+  TEST_c_c (ctanh, 0, plus_infty, nan_value, nan_value, INVALID_EXCEPTION);
+  TEST_c_c (ctanh, 2, plus_infty, nan_value, nan_value, INVALID_EXCEPTION);
+  TEST_c_c (ctanh, 0, minus_infty, nan_value, nan_value, INVALID_EXCEPTION);
+  TEST_c_c (ctanh, 2, minus_infty, nan_value, nan_value, INVALID_EXCEPTION);
+  TEST_c_c (ctanh, minus_zero, plus_infty, nan_value, nan_value, INVALID_EXCEPTION);
+  TEST_c_c (ctanh, -2, plus_infty, nan_value, nan_value, INVALID_EXCEPTION);
+  TEST_c_c (ctanh, minus_zero, minus_infty, nan_value, nan_value, INVALID_EXCEPTION);
+  TEST_c_c (ctanh, -2, minus_infty, nan_value, nan_value, INVALID_EXCEPTION);
+
+  TEST_c_c (ctanh, plus_infty, nan_value, 1.0, 0.0, IGNORE_ZERO_INF_SIGN);
+  TEST_c_c (ctanh, minus_infty, nan_value, -1.0, 0.0, IGNORE_ZERO_INF_SIGN);
+
+  TEST_c_c (ctanh, nan_value, 0, nan_value, 0.0);
+  TEST_c_c (ctanh, nan_value, minus_zero, nan_value, minus_zero);
+
+  TEST_c_c (ctanh, nan_value, 0.5, nan_value, nan_value, INVALID_EXCEPTION_OK);
+  TEST_c_c (ctanh, nan_value, -4.5, nan_value, nan_value, INVALID_EXCEPTION_OK);
+
+  TEST_c_c (ctanh, 0, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK);
+  TEST_c_c (ctanh, 5, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK);
+  TEST_c_c (ctanh, minus_zero, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK);
+  TEST_c_c (ctanh, -0.25, nan_value, nan_value, nan_value, INVALID_EXCEPTION_OK);
+
+  TEST_c_c (ctanh, nan_value, nan_value, nan_value, nan_value);
+
+  TEST_c_c (ctanh, 0, M_PI_4l, 0.0, 1.0);
+
+  TEST_c_c (ctanh, 0.75L, 1.25L, 1.37260757053378320258048606571226857L, 0.385795952609750664177596760720790220L);
+  TEST_c_c (ctanh, -2, -3, -0.965385879022133124278480269394560686L, 0.988437503832249372031403430350121098e-2L);
+
+  END (ctanh, complex);
+}
+#endif
+
+
+static void
+erf_test (void)
+{
+  errno = 0;
+  FUNC(erf) (0);
+  if (errno == ENOSYS)
+    /* Function not implemented.  */
+    return;
+
+  START (erf);
+
+  TEST_f_f (erf, 0, 0);
+  TEST_f_f (erf, minus_zero, minus_zero);
+  TEST_f_f (erf, plus_infty, 1);
+  TEST_f_f (erf, minus_infty, -1);
+  TEST_f_f (erf, nan_value, nan_value);
+
+  TEST_f_f (erf, 0.125L, 0.140316204801333817393029446521623398L);
+  TEST_f_f (erf, 0.75L, 0.711155633653515131598937834591410777L);
+  TEST_f_f (erf, 1.25L, 0.922900128256458230136523481197281140L);
+  TEST_f_f (erf, 2.0L, 0.995322265018952734162069256367252929L);
+  TEST_f_f (erf, 4.125L, 0.999999994576599200434933994687765914L);
+  TEST_f_f (erf, 27.0L, 1.0L);
+
+  END (erf);
+}
+
+
+static void
+erfc_test (void)
+{
+  errno = 0;
+  FUNC(erfc) (0);
+  if (errno == ENOSYS)
+    /* Function not implemented.  */
+    return;
+
+  START (erfc);
+
+  TEST_f_f (erfc, plus_infty, 0.0);
+  TEST_f_f (erfc, minus_infty, 2.0);
+  TEST_f_f (erfc, 0.0, 1.0);
+  TEST_f_f (erfc, minus_zero, 1.0);
+  TEST_f_f (erfc, nan_value, nan_value);
+
+  TEST_f_f (erfc, 0.125L, 0.859683795198666182606970553478376602L);
+  TEST_f_f (erfc, 0.75L, 0.288844366346484868401062165408589223L);
+  TEST_f_f (erfc, 1.25L, 0.0770998717435417698634765188027188596L);
+  TEST_f_f (erfc, 2.0L, 0.00467773498104726583793074363274707139L);
+  TEST_f_f (erfc, 4.125L, 0.542340079956506600531223408575531062e-8L);
+#ifdef TEST_LDOUBLE
+  /* The result can only be represented in long double.  */
+# if LDBL_MIN_10_EXP < -319
+  TEST_f_f (erfc, 27.0L, 0.523704892378925568501606768284954709e-318L);
+# endif
+#endif
+
+  END (erfc);
+}
+
+
+static void
+exp_test (void)
+{
+  errno = 0;
+  FUNC(exp) (0);
+  if (errno == ENOSYS)
+    /* Function not implemented.  */
+    return;
+
+  START (exp);
+
+  TEST_f_f (exp, 0, 1);
+  TEST_f_f (exp, minus_zero, 1);
+
+#ifndef TEST_INLINE
+  TEST_f_f (exp, plus_infty, plus_infty);
+  TEST_f_f (exp, minus_infty, 0);
+#endif
+  TEST_f_f (exp, nan_value, nan_value);
+  TEST_f_f (exp, 1, M_El);
+
+  TEST_f_f (exp, 2, M_E2l);
+  TEST_f_f (exp, 3, M_E3l);
+  TEST_f_f (exp, 0.75L, 2.11700001661267466854536981983709561L);
+  TEST_f_f (exp, 50.0L, 5184705528587072464087.45332293348538L);
+#ifdef TEST_LDOUBLE
+  /* The result can only be represented in long double.  */
+  TEST_f_f (exp, 1000.0L, 0.197007111401704699388887935224332313e435L);
+#endif
+
+  END (exp);
+}
+
+
+#if 0
+static void
+exp10_test (void)
+{
+  errno = 0;
+  FUNC(exp10) (0);
+  if (errno == ENOSYS)
+    /* Function not implemented.  */
+    return;
+
+  START (exp10);
+
+  TEST_f_f (exp10, 0, 1);
+  TEST_f_f (exp10, minus_zero, 1);
+
+  TEST_f_f (exp10, plus_infty, plus_infty);
+  TEST_f_f (exp10, minus_infty, 0);
+  TEST_f_f (exp10, nan_value, nan_value);
+  TEST_f_f (exp10, 3, 1000);
+  TEST_f_f (exp10, -1, 0.1L);
+  TEST_f_f (exp10, 1e6, plus_infty);
+  TEST_f_f (exp10, -1e6, 0);
+  TEST_f_f (exp10, 0.75L, 5.62341325190349080394951039776481231L);
+
+  END (exp10);
+}
+
+
+static void
+exp2_test (void)
+{
+  errno = 0;
+  FUNC(exp2) (0);
+  if (errno == ENOSYS)
+    /* Function not implemented.  */
+    return;
+
+  START (exp2);
+
+  TEST_f_f (exp2, 0, 1);
+  TEST_f_f (exp2, minus_zero, 1);
+  TEST_f_f (exp2, plus_infty, plus_infty);
+  TEST_f_f (exp2, minus_infty, 0);
+  TEST_f_f (exp2, nan_value, nan_value);
+
+  TEST_f_f (exp2, 10, 1024);
+  TEST_f_f (exp2, -1, 0.5);
+  TEST_f_f (exp2, 1e6, plus_infty);
+  TEST_f_f (exp2, -1e6, 0);
+  TEST_f_f (exp2, 0.75L, 1.68179283050742908606225095246642979L);
+
+  END (exp2);
+}
+#endif
+
+
+static void
+expm1_test (void)
+{
+  errno = 0;
+  FUNC(expm1) (0);
+  if (errno == ENOSYS)
+    /* Function not implemented.  */
+    return;
+
+  START (expm1);
+
+  TEST_f_f (expm1, 0, 0);
+  TEST_f_f (expm1, minus_zero, minus_zero);
+
+#ifndef TEST_INLINE
+  TEST_f_f (expm1, plus_infty, plus_infty);
+  TEST_f_f (expm1, minus_infty, -1);
+#endif
+  TEST_f_f (expm1, nan_value, nan_value);
+
+  TEST_f_f (expm1, 1, M_El - 1.0);
+  TEST_f_f (expm1, 0.75L, 1.11700001661267466854536981983709561L);
+
+  END (expm1);
+}
+
+
+static void
+fabs_test (void)
+{
+  START (fabs);
+
+  TEST_f_f (fabs, 0, 0);
+  TEST_f_f (fabs, minus_zero, 0);
+
+  TEST_f_f (fabs, plus_infty, plus_infty);
+  TEST_f_f (fabs, minus_infty, plus_infty);
+  TEST_f_f (fabs, nan_value, nan_value);
+
+  TEST_f_f (fabs, 38.0, 38.0);
+  TEST_f_f (fabs, -M_El, M_El);
+
+  END (fabs);
+}
+
+
+#if 0
+static void
+fdim_test (void)
+{
+  START (fdim);
+
+  TEST_ff_f (fdim, 0, 0, 0);
+  TEST_ff_f (fdim, 9, 0, 9);
+  TEST_ff_f (fdim, 0, 9, 0);
+  TEST_ff_f (fdim, -9, 0, 0);
+  TEST_ff_f (fdim, 0, -9, 9);
+
+  TEST_ff_f (fdim, plus_infty, 9, plus_infty);
+  TEST_ff_f (fdim, plus_infty, -9, plus_infty);
+  TEST_ff_f (fdim, minus_infty, 9, 0);
+  TEST_ff_f (fdim, minus_infty, -9, 0);
+  TEST_ff_f (fdim, 9, minus_infty, plus_infty);
+  TEST_ff_f (fdim, -9, minus_infty, plus_infty);
+  TEST_ff_f (fdim, 9, plus_infty, 0);
+  TEST_ff_f (fdim, -9, plus_infty, 0);
+
+  TEST_ff_f (fdim, 0, nan_value, nan_value);
+  TEST_ff_f (fdim, 9, nan_value, nan_value);
+  TEST_ff_f (fdim, -9, nan_value, nan_value);
+  TEST_ff_f (fdim, nan_value, 9, nan_value);
+  TEST_ff_f (fdim, nan_value, -9, nan_value);
+  TEST_ff_f (fdim, plus_infty, nan_value, nan_value);
+  TEST_ff_f (fdim, minus_infty, nan_value, nan_value);
+  TEST_ff_f (fdim, nan_value, plus_infty, nan_value);
+  TEST_ff_f (fdim, nan_value, minus_infty, nan_value);
+  TEST_ff_f (fdim, nan_value, nan_value, nan_value);
+
+  TEST_ff_f (fdim, plus_infty, plus_infty, 0);
+
+  END (fdim);
+}
+#endif
+
+
+static void
+floor_test (void)
+{
+  START (floor);
+
+  TEST_f_f (floor, 0.0, 0.0);
+  TEST_f_f (floor, minus_zero, minus_zero);
+  TEST_f_f (floor, plus_infty, plus_infty);
+  TEST_f_f (floor, minus_infty, minus_infty);
+  TEST_f_f (floor, nan_value, nan_value);
+
+  TEST_f_f (floor, M_PIl, 3.0);
+  TEST_f_f (floor, -M_PIl, -4.0);
+
+  TEST_f_f (floor, 0.25, 0.0);
+  TEST_f_f (floor, -0.25, -1.0);
+
+
+#ifdef TEST_LDOUBLE
+  /* The result can only be represented in long double.  */
+  TEST_f_f (floor, 4503599627370495.5L, 4503599627370495.0L);
+  TEST_f_f (floor, 4503599627370496.25L, 4503599627370496.0L);
+  TEST_f_f (floor, 4503599627370496.5L, 4503599627370496.0L);
+  TEST_f_f (floor, 4503599627370496.75L, 4503599627370496.0L);
+  TEST_f_f (floor, 4503599627370497.5L, 4503599627370497.0L);
+
+  TEST_f_f (floor, -4503599627370495.5L, -4503599627370496.0L);
+  TEST_f_f (floor, -4503599627370496.25L, -4503599627370497.0L);
+  TEST_f_f (floor, -4503599627370496.5L, -4503599627370497.0L);
+  TEST_f_f (floor, -4503599627370496.75L, -4503599627370497.0L);
+  TEST_f_f (floor, -4503599627370497.5L, -4503599627370498.0L);
+
+  TEST_f_f (floor, 9007199254740991.5L, 9007199254740991.0L);
+  TEST_f_f (floor, 9007199254740992.25L, 9007199254740992.0L);
+  TEST_f_f (floor, 9007199254740992.5L, 9007199254740992.0L);
+  TEST_f_f (floor, 9007199254740992.75L, 9007199254740992.0L);
+  TEST_f_f (floor, 9007199254740993.5L, 9007199254740993.0L);
+
+  TEST_f_f (floor, -9007199254740991.5L, -9007199254740992.0L);
+  TEST_f_f (floor, -9007199254740992.25L, -9007199254740993.0L);
+  TEST_f_f (floor, -9007199254740992.5L, -9007199254740993.0L);
+  TEST_f_f (floor, -9007199254740992.75L, -9007199254740993.0L);
+  TEST_f_f (floor, -9007199254740993.5L, -9007199254740994.0L);
+
+  TEST_f_f (floor, 72057594037927935.5L, 72057594037927935.0L);
+  TEST_f_f (floor, 72057594037927936.25L, 72057594037927936.0L);
+  TEST_f_f (floor, 72057594037927936.5L, 72057594037927936.0L);
+  TEST_f_f (floor, 72057594037927936.75L, 72057594037927936.0L);
+  TEST_f_f (floor, 72057594037927937.5L, 72057594037927937.0L);
+
+  TEST_f_f (floor, -72057594037927935.5L, -72057594037927936.0L);
+  TEST_f_f (floor, -72057594037927936.25L, -72057594037927937.0L);
+  TEST_f_f (floor, -72057594037927936.5L, -72057594037927937.0L);
+  TEST_f_f (floor, -72057594037927936.75L, -72057594037927937.0L);
+  TEST_f_f (floor, -72057594037927937.5L, -72057594037927938.0L);
+
+  TEST_f_f (floor, 10141204801825835211973625643007.5L, 10141204801825835211973625643007.0L);
+  TEST_f_f (floor, 10141204801825835211973625643008.25L, 10141204801825835211973625643008.0L);
+  TEST_f_f (floor, 10141204801825835211973625643008.5L, 10141204801825835211973625643008.0L);
+  TEST_f_f (floor, 10141204801825835211973625643008.75L, 10141204801825835211973625643008.0L);
+  TEST_f_f (floor, 10141204801825835211973625643009.5L, 10141204801825835211973625643009.0L);
+#endif
+
+  END (floor);
+}
+
+
+#if 0
+static void
+fma_test (void)
+{
+  START (fma);
+
+  TEST_fff_f (fma, 1.0, 2.0, 3.0, 5.0);
+  TEST_fff_f (fma, nan_value, 2.0, 3.0, nan_value);
+  TEST_fff_f (fma, 1.0, nan_value, 3.0, nan_value);
+  TEST_fff_f (fma, 1.0, 2.0, nan_value, nan_value, INVALID_EXCEPTION_OK);
+  TEST_fff_f (fma, plus_infty, 0.0, nan_value, nan_value, INVALID_EXCEPTION_OK);
+  TEST_fff_f (fma, minus_infty, 0.0, nan_value, nan_value, INVALID_EXCEPTION_OK);
+  TEST_fff_f (fma, 0.0, plus_infty, nan_value, nan_value, INVALID_EXCEPTION_OK);
+  TEST_fff_f (fma, 0.0, minus_infty, nan_value, nan_value, INVALID_EXCEPTION_OK);
+  TEST_fff_f (fma, plus_infty, 0.0, 1.0, nan_value, INVALID_EXCEPTION);
+  TEST_fff_f (fma, minus_infty, 0.0, 1.0, nan_value, INVALID_EXCEPTION);
+  TEST_fff_f (fma, 0.0, plus_infty, 1.0, nan_value, INVALID_EXCEPTION);
+  TEST_fff_f (fma, 0.0, minus_infty, 1.0, nan_value, INVALID_EXCEPTION);
+
+  TEST_fff_f (fma, plus_infty, plus_infty, minus_infty, nan_value, INVALID_EXCEPTION);
+  TEST_fff_f (fma, minus_infty, plus_infty, plus_infty, nan_value, INVALID_EXCEPTION);
+  TEST_fff_f (fma, plus_infty, minus_infty, plus_infty, nan_value, INVALID_EXCEPTION);
+  TEST_fff_f (fma, minus_infty, minus_infty, minus_infty, nan_value, INVALID_EXCEPTION);
+
+  TEST_fff_f (fma, 1.25L, 0.75L, 0.0625L, 1.0L);
+
+  END (fma);
+}
+
+
+static void
+fmax_test (void)
+{
+  START (fmax);
+
+  TEST_ff_f (fmax, 0, 0, 0);
+  TEST_ff_f (fmax, minus_zero, minus_zero, minus_zero);
+  TEST_ff_f (fmax, 9, 0, 9);
+  TEST_ff_f (fmax, 0, 9, 9);
+  TEST_ff_f (fmax, -9, 0, 0);
+  TEST_ff_f (fmax, 0, -9, 0);
+
+  TEST_ff_f (fmax, plus_infty, 9, plus_infty);
+  TEST_ff_f (fmax, 0, plus_infty, plus_infty);
+  TEST_ff_f (fmax, -9, plus_infty, plus_infty);
+  TEST_ff_f (fmax, plus_infty, -9, plus_infty);
+
+  TEST_ff_f (fmax, minus_infty, 9, 9);
+  TEST_ff_f (fmax, minus_infty, -9, -9);
+  TEST_ff_f (fmax, 9, minus_infty, 9);
+  TEST_ff_f (fmax, -9, minus_infty, -9);
+
+  TEST_ff_f (fmax, 0, nan_value, 0);
+  TEST_ff_f (fmax, 9, nan_value, 9);
+  TEST_ff_f (fmax, -9, nan_value, -9);
+  TEST_ff_f (fmax, nan_value, 0, 0);
+  TEST_ff_f (fmax, nan_value, 9, 9);
+  TEST_ff_f (fmax, nan_value, -9, -9);
+  TEST_ff_f (fmax, plus_infty, nan_value, plus_infty);
+  TEST_ff_f (fmax, minus_infty, nan_value, minus_infty);
+  TEST_ff_f (fmax, nan_value, plus_infty, plus_infty);
+  TEST_ff_f (fmax, nan_value, minus_infty, minus_infty);
+  TEST_ff_f (fmax, nan_value, nan_value, nan_value);
+
+  END (fmax);
+}
+
+
+static void
+fmin_test (void)
+{
+  START (fmin);
+
+  TEST_ff_f (fmin, 0, 0, 0);
+  TEST_ff_f (fmin, minus_zero, minus_zero, minus_zero);
+  TEST_ff_f (fmin, 9, 0, 0);
+  TEST_ff_f (fmin, 0, 9, 0);
+  TEST_ff_f (fmin, -9, 0, -9);
+  TEST_ff_f (fmin, 0, -9, -9);
+
+  TEST_ff_f (fmin, plus_infty, 9, 9);
+  TEST_ff_f (fmin, 9, plus_infty, 9);
+  TEST_ff_f (fmin, plus_infty, -9, -9);
+  TEST_ff_f (fmin, -9, plus_infty, -9);
+  TEST_ff_f (fmin, minus_infty, 9, minus_infty);
+  TEST_ff_f (fmin, minus_infty, -9, minus_infty);
+  TEST_ff_f (fmin, 9, minus_infty, minus_infty);
+  TEST_ff_f (fmin, -9, minus_infty, minus_infty);
+
+  TEST_ff_f (fmin, 0, nan_value, 0);
+  TEST_ff_f (fmin, 9, nan_value, 9);
+  TEST_ff_f (fmin, -9, nan_value, -9);
+  TEST_ff_f (fmin, nan_value, 0, 0);
+  TEST_ff_f (fmin, nan_value, 9, 9);
+  TEST_ff_f (fmin, nan_value, -9, -9);
+  TEST_ff_f (fmin, plus_infty, nan_value, plus_infty);
+  TEST_ff_f (fmin, minus_infty, nan_value, minus_infty);
+  TEST_ff_f (fmin, nan_value, plus_infty, plus_infty);
+  TEST_ff_f (fmin, nan_value, minus_infty, minus_infty);
+  TEST_ff_f (fmin, nan_value, nan_value, nan_value);
+
+  END (fmin);
+}
+#endif
+
+
+static void
+fmod_test (void)
+{
+  errno = 0;
+  FUNC(fmod) (6.5, 2.3L);
+  if (errno == ENOSYS)
+    /* Function not implemented.  */
+    return;
+
+  START (fmod);
+
+  /* fmod (+0, y) == +0 for y != 0.  */
+  TEST_ff_f (fmod, 0, 3, 0);
+
+  /* fmod (-0, y) == -0 for y != 0.  */
+  TEST_ff_f (fmod, minus_zero, 3, minus_zero);
+
+  /* fmod (+inf, y) == NaN plus invalid exception.  */
+  TEST_ff_f (fmod, plus_infty, 3, nan_value, INVALID_EXCEPTION);
+  /* fmod (-inf, y) == NaN plus invalid exception.  */
+  TEST_ff_f (fmod, minus_infty, 3, nan_value, INVALID_EXCEPTION);
+  /* fmod (x, +0) == NaN plus invalid exception.  */
+  TEST_ff_f (fmod, 3, 0, nan_value, INVALID_EXCEPTION);
+  /* fmod (x, -0) == NaN plus invalid exception.  */
+  TEST_ff_f (fmod, 3, minus_zero, nan_value, INVALID_EXCEPTION);
+
+  /* fmod (x, +inf) == x for x not infinite.  */
+  TEST_ff_f (fmod, 3.0, plus_infty, 3.0);
+  /* fmod (x, -inf) == x for x not infinite.  */
+  TEST_ff_f (fmod, 3.0, minus_infty, 3.0);
+
+  TEST_ff_f (fmod, nan_value, nan_value, nan_value);
+
+  TEST_ff_f (fmod, 6.5, 2.25L, 2.0L);
+  TEST_ff_f (fmod, -6.5, 2.25L, -2.0L);
+  TEST_ff_f (fmod, 6.5, -2.25L, 2.0L);
+  TEST_ff_f (fmod, -6.5, -2.25L, -2.0L);
+
+  END (fmod);
+}
+
+
+static void
+fpclassify_test (void)
+{
+  START (fpclassify);
+
+  TEST_f_i (fpclassify, nan_value, FP_NAN);
+  TEST_f_i (fpclassify, plus_infty, FP_INFINITE);
+  TEST_f_i (fpclassify, minus_infty, FP_INFINITE);
+  TEST_f_i (fpclassify, plus_zero, FP_ZERO);
+  TEST_f_i (fpclassify, minus_zero, FP_ZERO);
+  TEST_f_i (fpclassify, 1000, FP_NORMAL);
+
+  END (fpclassify);
+}
+
+
+static void
+frexp_test (void)
+{
+  int x;
+
+  START (frexp);
+
+  TEST_fI_f1 (frexp, plus_infty, plus_infty, IGNORE);
+  TEST_fI_f1 (frexp, minus_infty, minus_infty, IGNORE);
+  TEST_fI_f1 (frexp, nan_value, nan_value, IGNORE);
+
+  TEST_fI_f1 (frexp, 0.0, 0.0, 0.0);
+  TEST_fI_f1 (frexp, minus_zero, minus_zero, 0.0);
+
+  TEST_fI_f1 (frexp, 12.8L, 0.8L, 4);
+  TEST_fI_f1 (frexp, -27.34L, -0.854375L, 5);
+
+  END (frexp);
+}
+
+
+static void
+gamma_test (void)
+{
+  errno = 0;
+  FUNC(gamma) (1);
+
+  if (errno == ENOSYS)
+    /* Function not implemented.  */
+    return;
+  feclearexcept (FE_ALL_EXCEPT);
+
+  START (gamma);
+
+  TEST_f_f (gamma, plus_infty, plus_infty);
+  TEST_f_f (gamma, 0, plus_infty, DIVIDE_BY_ZERO_EXCEPTION);
+  TEST_f_f (gamma, -3, plus_infty, DIVIDE_BY_ZERO_EXCEPTION);
+  TEST_f_f (gamma, minus_infty, plus_infty);
+  TEST_f_f (gamma, nan_value, nan_value);
+
+  TEST_f_f1 (gamma, 1, 0, 1);
+  TEST_f_f1 (gamma, 3, M_LN2l, 1);
+
+  TEST_f_f1 (gamma, 0.5, M_LOG_SQRT_PIl, 1);
+  TEST_f_f1 (gamma, -0.5, M_LOG_2_SQRT_PIl, -1);
+
+  END (gamma);
+}
+
+static void
+hypot_test (void)
+{
+  errno = 0;
+  FUNC(hypot) (0.7L, 12.4L);
+  if (errno == ENOSYS)
+    /* Function not implemented.  */
+    return;
+
+  START (hypot);
+
+  TEST_ff_f (hypot, plus_infty, 1, plus_infty, IGNORE_ZERO_INF_SIGN);
+  TEST_ff_f (hypot, minus_infty, 1, plus_infty, IGNORE_ZERO_INF_SIGN);
+
+#ifndef TEST_INLINE
+  TEST_ff_f (hypot, plus_infty, nan_value, plus_infty);
+  TEST_ff_f (hypot, minus_infty, nan_value, plus_infty);
+  TEST_ff_f (hypot, nan_value, plus_infty, plus_infty);
+  TEST_ff_f (hypot, nan_value, minus_infty, plus_infty);
+#endif
+
+  TEST_ff_f (hypot, nan_value, nan_value, nan_value);
+
+  /* hypot (x,y) == hypot (+-x, +-y)  */
+  TEST_ff_f (hypot, 0.7L, 12.4L, 12.419742348374220601176836866763271L);
+  TEST_ff_f (hypot, -0.7L, 12.4L, 12.419742348374220601176836866763271L);
+  TEST_ff_f (hypot, 0.7L, -12.4L, 12.419742348374220601176836866763271L);
+  TEST_ff_f (hypot, -0.7L, -12.4L, 12.419742348374220601176836866763271L);
+  TEST_ff_f (hypot, 12.4L, 0.7L, 12.419742348374220601176836866763271L);
+  TEST_ff_f (hypot, -12.4L, 0.7L, 12.419742348374220601176836866763271L);
+  TEST_ff_f (hypot, 12.4L, -0.7L, 12.419742348374220601176836866763271L);
+  TEST_ff_f (hypot, -12.4L, -0.7L, 12.419742348374220601176836866763271L);
+
+  /*  hypot (x,0) == fabs (x)  */
+  TEST_ff_f (hypot, 0.75L, 0, 0.75L);
+  TEST_ff_f (hypot, -0.75L, 0, 0.75L);
+  TEST_ff_f (hypot, -5.7e7, 0, 5.7e7L);
+
+  TEST_ff_f (hypot, 0.75L, 1.25L, 1.45773797371132511771853821938639577L);
+
+  END (hypot);
+}
+
+
+static void
+ilogb_test (void)
+{
+  START (ilogb);
+
+  TEST_f_i (ilogb, 1, 0);
+  TEST_f_i (ilogb, M_El, 1);
+  TEST_f_i (ilogb, 1024, 10);
+  TEST_f_i (ilogb, -2000, 10);
+
+  /* XXX We have a problem here: the standard does not tell us whether
+     exceptions are allowed/required.  ignore them for now.  */
+
+  TEST_f_i (ilogb, 0.0, FP_ILOGB0, EXCEPTIONS_OK);
+  TEST_f_i (ilogb, nan_value, FP_ILOGBNAN, EXCEPTIONS_OK);
+  TEST_f_i (ilogb, plus_infty, INT_MAX, EXCEPTIONS_OK);
+  TEST_f_i (ilogb, minus_infty, INT_MAX, EXCEPTIONS_OK);
+
+  END (ilogb);
+}
+
+static void
+isfinite_test (void)
+{
+  START (isfinite);
+
+  TEST_f_b (isfinite, 0, 1);
+  TEST_f_b (isfinite, minus_zero, 1);
+  TEST_f_b (isfinite, 10, 1);
+  TEST_f_b (isfinite, plus_infty, 0);
+  TEST_f_b (isfinite, minus_infty, 0);
+  TEST_f_b (isfinite, nan_value, 0);
+
+  END (isfinite);
+}
+
+static void
+isnormal_test (void)
+{
+  START (isnormal);
+
+  TEST_f_b (isnormal, 0, 0);
+  TEST_f_b (isnormal, minus_zero, 0);
+  TEST_f_b (isnormal, 10, 1);
+  TEST_f_b (isnormal, plus_infty, 0);
+  TEST_f_b (isnormal, minus_infty, 0);
+  TEST_f_b (isnormal, nan_value, 0);
+
+  END (isnormal);
+}
+
+#if defined __DO_XSI_MATH__
+static void
+j0_test (void)
+{
+  errno = 0;
+#if 0
+  FLOAT s, c;
+  FUNC (sincos) (0, &s, &c);
+  if (errno == ENOSYS)
+    /* Required function not implemented.  */
+    return;
+#endif
+  FUNC(j0) (0);
+  if (errno == ENOSYS)
+    /* Function not implemented.  */
+    return;
+
+  START (j0);
+
+  /* j0 is the Bessel function of the first kind of order 0 */
+  TEST_f_f (j0, nan_value, nan_value);
+  TEST_f_f (j0, plus_infty, 0);
+  TEST_f_f (j0, -1.0, 0.765197686557966551449717526102663221L);
+  TEST_f_f (j0, 0.0, 1.0);
+  TEST_f_f (j0, 0.125L, 0.996097563041985204620768999453174712L);
+  TEST_f_f (j0, 0.75L, 0.864242275166648623555731103820923211L);
+  TEST_f_f (j0, 1.0, 0.765197686557966551449717526102663221L);
+  TEST_f_f (j0, 1.5, 0.511827671735918128749051744283411720L);
+  TEST_f_f (j0, 2.0, 0.223890779141235668051827454649948626L);
+  TEST_f_f (j0, 8.0, 0.171650807137553906090869407851972001L);
+  TEST_f_f (j0, 10.0, -0.245935764451348335197760862485328754L);
+  TEST_f_f (j0, 4.0, -3.9714980986384737228659076845169804197562E-1L);
+  TEST_f_f (j0, -4.0, -3.9714980986384737228659076845169804197562E-1L);
+
+  END (j0);
+}
+
+
+static void
+j1_test (void)
+{
+  errno = 0;
+#if 0
+  FLOAT s, c;
+  FUNC (sincos) (0, &s, &c);
+  if (errno == ENOSYS)
+    /* Required function not implemented.  */
+    return;
+#endif
+  FUNC(j1) (0);
+  if (errno == ENOSYS)
+    /* Function not implemented.  */
+    return;
+
+  /* j1 is the Bessel function of the first kind of order 1 */
+
+  START (j1);
+
+  TEST_f_f (j1, nan_value, nan_value);
+  TEST_f_f (j1, plus_infty, 0);
+
+  TEST_f_f (j1, -1.0, -0.440050585744933515959682203718914913L);
+  TEST_f_f (j1, 0.0, 0.0);
+  TEST_f_f (j1, 0.125L, 0.0623780091344946810942311355879361177L);
+  TEST_f_f (j1, 0.75L, 0.349243602174862192523281016426251335L);
+  TEST_f_f (j1, 1.0, 0.440050585744933515959682203718914913L);
+  TEST_f_f (j1, 1.5, 0.557936507910099641990121213156089400L);
+  TEST_f_f (j1, 2.0, 0.576724807756873387202448242269137087L);
+  TEST_f_f (j1, 8.0, 0.234636346853914624381276651590454612L);
+  TEST_f_f (j1, 10.0, 0.0434727461688614366697487680258592883L);
+
+  END (j1);
+}
+
+static void
+jn_test (void)
+{
+  errno = 0;
+#if 0
+  FLOAT s, c;
+  FUNC (sincos) (0, &s, &c);
+  if (errno == ENOSYS)
+    /* Required function not implemented.  */
+    return;
+#endif
+  FUNC(jn) (1, 1);
+  if (errno == ENOSYS)
+    /* Function not implemented.  */
+    return;
+
+  /* jn is the Bessel function of the first kind of order n.  */
+  START (jn);
+
+  /* jn (0, x) == j0 (x)  */
+  TEST_ff_f (jn, 0, nan_value, nan_value);
+  TEST_ff_f (jn, 0, plus_infty, 0);
+  TEST_ff_f (jn, 0, -1.0, 0.765197686557966551449717526102663221L);
+  TEST_ff_f (jn, 0, 0.0, 1.0);
+  TEST_ff_f (jn, 0, 0.125L, 0.996097563041985204620768999453174712L);
+  TEST_ff_f (jn, 0, 0.75L, 0.864242275166648623555731103820923211L);
+  TEST_ff_f (jn, 0, 1.0, 0.765197686557966551449717526102663221L);
+  TEST_ff_f (jn, 0, 1.5, 0.511827671735918128749051744283411720L);
+  TEST_ff_f (jn, 0, 2.0, 0.223890779141235668051827454649948626L);
+  TEST_ff_f (jn, 0, 8.0, 0.171650807137553906090869407851972001L);
+  TEST_ff_f (jn, 0, 10.0, -0.245935764451348335197760862485328754L);
+  TEST_ff_f (jn, 0, 4.0, -3.9714980986384737228659076845169804197562E-1L);
+  TEST_ff_f (jn, 0, -4.0, -3.9714980986384737228659076845169804197562E-1L);
+
+  /* jn (1, x) == j1 (x)  */
+  TEST_ff_f (jn, 1, nan_value, nan_value);
+  TEST_ff_f (jn, 1, plus_infty, 0);
+  TEST_ff_f (jn, 1, -1.0, -0.440050585744933515959682203718914913L);
+  TEST_ff_f (jn, 1, 0.0, 0.0);
+  TEST_ff_f (jn, 1, 0.125L, 0.0623780091344946810942311355879361177L);
+  TEST_ff_f (jn, 1, 0.75L, 0.349243602174862192523281016426251335L);
+  TEST_ff_f (jn, 1, 1.0, 0.440050585744933515959682203718914913L);
+  TEST_ff_f (jn, 1, 1.5, 0.557936507910099641990121213156089400L);
+  TEST_ff_f (jn, 1, 2.0, 0.576724807756873387202448242269137087L);
+  TEST_ff_f (jn, 1, 8.0, 0.234636346853914624381276651590454612L);
+  TEST_ff_f (jn, 1, 10.0, 0.0434727461688614366697487680258592883L);
+
+  /* jn (3, x)  */
+  TEST_ff_f (jn, 3, nan_value, nan_value);
+  TEST_ff_f (jn, 3, plus_infty, 0);
+
+  TEST_ff_f (jn, 3, -1.0, -0.0195633539826684059189053216217515083L);
+  TEST_ff_f (jn, 3, 0.0, 0.0);
+  TEST_ff_f (jn, 3, 0.125L, 0.406503832554912875023029337653442868e-4L);
+  TEST_ff_f (jn, 3, 0.75L, 0.848438342327410884392755236884386804e-2L);
+  TEST_ff_f (jn, 3, 1.0, 0.0195633539826684059189053216217515083L);
+  TEST_ff_f (jn, 3, 2.0, 0.128943249474402051098793332969239835L);
+  TEST_ff_f (jn, 3, 10.0, 0.0583793793051868123429354784103409563L);
+
+  /*  jn (10, x)  */
+  TEST_ff_f (jn, 10, nan_value, nan_value);
+  TEST_ff_f (jn, 10, plus_infty, 0);
+
+  TEST_ff_f (jn, 10, -1.0, 0.263061512368745320699785368779050294e-9L);
+  TEST_ff_f (jn, 10, 0.0, 0.0);
+  TEST_ff_f (jn, 10, 0.125L, 0.250543369809369890173993791865771547e-18L);
+  TEST_ff_f (jn, 10, 0.75L, 0.149621713117596814698712483621682835e-10L);
+  TEST_ff_f (jn, 10, 1.0, 0.263061512368745320699785368779050294e-9L);
+  TEST_ff_f (jn, 10, 2.0, 0.251538628271673670963516093751820639e-6L);
+  TEST_ff_f (jn, 10, 10.0, 0.207486106633358857697278723518753428L);
+
+  END (jn);
+}
+#endif /* __DO_XSI_MATH__ */
+
+
+static void
+ldexp_test (void)
+{
+  TEST_ff_f (ldexp, 0, 0, 0);
+  TEST_ff_f (ldexp, minus_zero, 0, minus_zero);
+
+  TEST_ff_f (ldexp, plus_infty, 1, plus_infty);
+  TEST_ff_f (ldexp, minus_infty, 1, minus_infty);
+  TEST_ff_f (ldexp, nan_value, 1, nan_value);
+
+  TEST_ff_f (ldexp, 0.8L, 4, 12.8L);
+  TEST_ff_f (ldexp, -0.854375L, 5, -27.34L);
+
+  /* ldexp (x, 0) == x.  */
+  TEST_ff_f (ldexp, 1.0L, 0L, 1.0L);
+}
+
+
+static void
+lgamma_test (void)
+{
+  errno = 0;
+  FUNC(lgamma) (0);
+  if (errno == ENOSYS)
+    /* Function not implemented.  */
+    return;
+  feclearexcept (FE_ALL_EXCEPT);
+
+  START (lgamma);
+
+  TEST_f_f (lgamma, plus_infty, plus_infty);
+  TEST_f_f (lgamma, 0, plus_infty, DIVIDE_BY_ZERO_EXCEPTION);
+  TEST_f_f (lgamma, nan_value, nan_value);
+
+  /* lgamma (x) == +inf plus divide by zero exception for integer x <= 0.  */
+  TEST_f_f (lgamma, -3, plus_infty, DIVIDE_BY_ZERO_EXCEPTION);
+  TEST_f_f (lgamma, minus_infty, plus_infty);
+
+  TEST_f_f1 (lgamma, 1, 0, 1);
+
+  TEST_f_f1 (lgamma, 3, M_LN2l, 1);
+
+  TEST_f_f1 (lgamma, 0.5, M_LOG_SQRT_PIl, 1);
+  TEST_f_f1 (lgamma, -0.5, M_LOG_2_SQRT_PIl, -1);
+  TEST_f_f1 (lgamma, 0.7L, 0.260867246531666514385732417016759578L, 1);
+  TEST_f_f1 (lgamma, 1.2L, -0.853740900033158497197028392998854470e-1L, 1);
+
+  END (lgamma);
+}
+
+
+#if 0
+static void
+lrint_test (void)
+{
+  /* XXX this test is incomplete.  We need to have a way to specifiy
+     the rounding method and test the critical cases.  So far, only
+     unproblematic numbers are tested.  */
+
+  START (lrint);
+
+  TEST_f_l (lrint, 0.0, 0);
+  TEST_f_l (lrint, minus_zero, 0);
+  TEST_f_l (lrint, 0.2L, 0);
+  TEST_f_l (lrint, -0.2L, 0);
+
+  TEST_f_l (lrint, 1.4L, 1);
+  TEST_f_l (lrint, -1.4L, -1);
+
+  TEST_f_l (lrint, 8388600.3L, 8388600);
+  TEST_f_l (lrint, -8388600.3L, -8388600);
+
+  TEST_f_l (lrint, 1071930.0008, 1071930);
+#ifndef TEST_FLOAT
+  TEST_f_l (lrint, 1073741824.01, 1073741824);
+# if LONG_MAX > 281474976710656
+  TEST_f_l (lrint, 281474976710656.025, 281474976710656);
+# endif
+#endif
+
+  END (lrint);
+}
+
+
+static void
+llrint_test (void)
+{
+  /* XXX this test is incomplete.  We need to have a way to specifiy
+     the rounding method and test the critical cases.  So far, only
+     unproblematic numbers are tested.  */
+
+  START (llrint);
+
+  TEST_f_L (llrint, 0.0, 0);
+  TEST_f_L (llrint, minus_zero, 0);
+  TEST_f_L (llrint, 0.2L, 0);
+  TEST_f_L (llrint, -0.2L, 0);
+
+  TEST_f_L (llrint, 1.4L, 1);
+  TEST_f_L (llrint, -1.4L, -1);
+
+  TEST_f_L (llrint, 8388600.3L, 8388600);
+  TEST_f_L (llrint, -8388600.3L, -8388600);
+
+  TEST_f_l (llrint, 1071930.0008, 1071930);
+
+  /* Test boundary conditions.  */
+  /* 0x1FFFFF */
+  TEST_f_L (llrint, 2097151.0,2097151LL);
+  /* 0x800000 */
+  TEST_f_L (llrint, 8388608.0, 8388608LL);
+  /* 0x1000000 */
+  TEST_f_L (llrint, 16777216.0, 16777216LL);
+  /* 0x20000000000 */
+  TEST_f_L (llrint, 2199023255552.0, 2199023255552LL);
+  /* 0x40000000000 */
+  TEST_f_L (llrint, 4398046511104.0, 4398046511104LL);
+  /* 0x1000000000000 */
+  TEST_f_L (llrint, 281474976710656.0, 281474976710656LL);
+  /* 0x10000000000000 */
+  TEST_f_L (llrint, 4503599627370496.0, 4503599627370496LL);
+  /* 0x10000080000000 */
+  TEST_f_L (llrint, 4503601774854144.0, 4503601774854144LL);
+  /* 0x20000000000000 */
+  TEST_f_L (llrint, 9007199254740992.0, 9007199254740992LL);
+  /* 0x80000000000000 */
+  TEST_f_L (llrint, 36028797018963968.0, 36028797018963968LL);
+  /* 0x100000000000000 */
+  TEST_f_L (llrint, 72057594037927936.0, 72057594037927936LL);
+#ifdef TEST_LDOUBLE
+  /* The input can only be represented in long double.  */
+  TEST_f_L (llrint, 4503599627370495.5L, 4503599627370496LL);
+  TEST_f_L (llrint, 4503599627370496.25L, 4503599627370496LL);
+  TEST_f_L (llrint, 4503599627370496.5L, 4503599627370496LL);
+  TEST_f_L (llrint, 4503599627370496.75L, 4503599627370497LL);
+  TEST_f_L (llrint, 4503599627370497.5L, 4503599627370498LL);
+
+  TEST_f_L (llrint, -4503599627370495.5L, -4503599627370496LL);
+  TEST_f_L (llrint, -4503599627370496.25L, -4503599627370496LL);
+  TEST_f_L (llrint, -4503599627370496.5L, -4503599627370496LL);
+  TEST_f_L (llrint, -4503599627370496.75L, -4503599627370497LL);
+  TEST_f_L (llrint, -4503599627370497.5L, -4503599627370498LL);
+
+  TEST_f_L (llrint, 9007199254740991.5L, 9007199254740992LL);
+  TEST_f_L (llrint, 9007199254740992.25L, 9007199254740992LL);
+  TEST_f_L (llrint, 9007199254740992.5L, 9007199254740992LL);
+  TEST_f_L (llrint, 9007199254740992.75L, 9007199254740993LL);
+  TEST_f_L (llrint, 9007199254740993.5L, 9007199254740994LL);
+
+  TEST_f_L (llrint, -9007199254740991.5L, -9007199254740992LL);
+  TEST_f_L (llrint, -9007199254740992.25L, -9007199254740992LL);
+  TEST_f_L (llrint, -9007199254740992.5L, -9007199254740992LL);
+  TEST_f_L (llrint, -9007199254740992.75L, -9007199254740993LL);
+  TEST_f_L (llrint, -9007199254740993.5L, -9007199254740994LL);
+
+  TEST_f_L (llrint, 72057594037927935.5L, 72057594037927936LL);
+  TEST_f_L (llrint, 72057594037927936.25L, 72057594037927936LL);
+  TEST_f_L (llrint, 72057594037927936.5L, 72057594037927936LL);
+  TEST_f_L (llrint, 72057594037927936.75L, 72057594037927937LL);
+  TEST_f_L (llrint, 72057594037927937.5L, 72057594037927938LL);
+
+  TEST_f_L (llrint, -72057594037927935.5L, -72057594037927936LL);
+  TEST_f_L (llrint, -72057594037927936.25L, -72057594037927936LL);
+  TEST_f_L (llrint, -72057594037927936.5L, -72057594037927936LL);
+  TEST_f_L (llrint, -72057594037927936.75L, -72057594037927937LL);
+  TEST_f_L (llrint, -72057594037927937.5L, -72057594037927938LL);
+#endif
+
+  END (llrint);
+}
+#endif
+
+
+static void
+log_test (void)
+{
+  errno = 0;
+  FUNC(log) (1);
+  if (errno == ENOSYS)
+    /* Function not implemented.  */
+    return;
+  START (log);
+
+  TEST_f_f (log, 0, minus_infty, DIVIDE_BY_ZERO_EXCEPTION);
+  TEST_f_f (log, minus_zero, minus_infty, DIVIDE_BY_ZERO_EXCEPTION);
+
+  TEST_f_f (log, 1, 0);
+
+  TEST_f_f (log, -1, nan_value, INVALID_EXCEPTION);
+  TEST_f_f (log, plus_infty, plus_infty);
+
+  TEST_f_f (log, M_El, 1);
+  TEST_f_f (log, 1.0 / M_El, -1);
+  TEST_f_f (log, 2, M_LN2l);
+  TEST_f_f (log, 10, M_LN10l);
+  TEST_f_f (log, 0.75L, -0.287682072451780927439219005993827432L);
+
+  END (log);
+}
+
+
+static void
+log10_test (void)
+{
+  errno = 0;
+  FUNC(log10) (1);
+  if (errno == ENOSYS)
+    /* Function not implemented.  */
+    return;
+
+  START (log10);
+
+  TEST_f_f (log10, 0, minus_infty, DIVIDE_BY_ZERO_EXCEPTION);
+  TEST_f_f (log10, minus_zero, minus_infty, DIVIDE_BY_ZERO_EXCEPTION);
+
+  TEST_f_f (log10, 1, 0);
+
+  /* log10 (x) == NaN plus invalid exception if x < 0.  */
+  TEST_f_f (log10, -1, nan_value, INVALID_EXCEPTION);
+
+  TEST_f_f (log10, plus_infty, plus_infty);
+  TEST_f_f (log10, nan_value, nan_value);
+
+  TEST_f_f (log10, 0.1L, -1);
+  TEST_f_f (log10, 10.0, 1);
+  TEST_f_f (log10, 100.0, 2);
+  TEST_f_f (log10, 10000.0, 4);
+  TEST_f_f (log10, M_El, M_LOG10El);
+  TEST_f_f (log10, 0.75L, -0.124938736608299953132449886193870744L);
+
+  END (log10);
+}
+
+
+static void
+log1p_test (void)
+{
+  errno = 0;
+  FUNC(log1p) (0);
+  if (errno == ENOSYS)
+    /* Function not implemented.  */
+    return;
+
+  START (log1p);
+
+  TEST_f_f (log1p, 0, 0);
+  TEST_f_f (log1p, minus_zero, minus_zero);
+
+  TEST_f_f (log1p, -1, minus_infty, DIVIDE_BY_ZERO_EXCEPTION);
+  TEST_f_f (log1p, -2, nan_value, INVALID_EXCEPTION);
+
+  TEST_f_f (log1p, plus_infty, plus_infty);
+  TEST_f_f (log1p, nan_value, nan_value);
+
+  TEST_f_f (log1p, M_El - 1.0, 1);
+
+  TEST_f_f (log1p, -0.25L, -0.287682072451780927439219005993827432L);
+  TEST_f_f (log1p, -0.875, -2.07944154167983592825169636437452970L);
+
+  END (log1p);
+}
+
+
+#if 0
+static void
+log2_test (void)
+{
+  errno = 0;
+  FUNC(log2) (1);
+  if (errno == ENOSYS)
+    /* Function not implemented.  */
+    return;
+
+  START (log2);
+
+  TEST_f_f (log2, 0, minus_infty, DIVIDE_BY_ZERO_EXCEPTION);
+  TEST_f_f (log2, minus_zero, minus_infty, DIVIDE_BY_ZERO_EXCEPTION);
+
+  TEST_f_f (log2, 1, 0);
+
+  TEST_f_f (log2, -1, nan_value, INVALID_EXCEPTION);
+
+  TEST_f_f (log2, plus_infty, plus_infty);
+  TEST_f_f (log2, nan_value, nan_value);
+
+  TEST_f_f (log2, M_El, M_LOG2El);
+  TEST_f_f (log2, 2.0, 1);
+  TEST_f_f (log2, 16.0, 4);
+  TEST_f_f (log2, 256.0, 8);
+  TEST_f_f (log2, 0.75L, -.415037499278843818546261056052183492L);
+
+  END (log2);
+}
+#endif
+
+
+static void
+logb_test (void)
+{
+  START (logb);
+
+  TEST_f_f (logb, plus_infty, plus_infty);
+  TEST_f_f (logb, minus_infty, plus_infty);
+
+  TEST_f_f (logb, 0, minus_infty, DIVIDE_BY_ZERO_EXCEPTION);
+
+  TEST_f_f (logb, minus_zero, minus_infty, DIVIDE_BY_ZERO_EXCEPTION);
+  TEST_f_f (logb, nan_value, nan_value);
+
+  TEST_f_f (logb, 1, 0);
+  TEST_f_f (logb, M_El, 1);
+  TEST_f_f (logb, 1024, 10);
+  TEST_f_f (logb, -2000, 10);
+
+  END (logb);
+}
+
+
+#if 0
+static void
+lround_test (void)
+{
+  START (lround);
+
+  TEST_f_l (lround, 0, 0);
+  TEST_f_l (lround, minus_zero, 0);
+  TEST_f_l (lround, 0.2L, 0.0);
+  TEST_f_l (lround, -0.2L, 0);
+  TEST_f_l (lround, 0.5, 1);
+  TEST_f_l (lround, -0.5, -1);
+  TEST_f_l (lround, 0.8L, 1);
+  TEST_f_l (lround, -0.8L, -1);
+  TEST_f_l (lround, 1.5, 2);
+  TEST_f_l (lround, -1.5, -2);
+  TEST_f_l (lround, 22514.5, 22515);
+  TEST_f_l (lround, -22514.5, -22515);
+  TEST_f_l (lround, 1071930.0008, 1071930);
+#ifndef TEST_FLOAT
+  TEST_f_l (lround, 1073741824.01, 1073741824);
+# if LONG_MAX > 281474976710656
+  TEST_f_l (lround, 281474976710656.025, 281474976710656);
+# endif
+  TEST_f_l (lround, 2097152.5, 2097153);
+  TEST_f_l (lround, -2097152.5, -2097153);
+#endif
+  END (lround);
+}
+
+
+static void
+llround_test (void)
+{
+  START (llround);
+
+  TEST_f_L (llround, 0, 0);
+  TEST_f_L (llround, minus_zero, 0);
+  TEST_f_L (llround, 0.2L, 0.0);
+  TEST_f_L (llround, -0.2L, 0);
+  TEST_f_L (llround, 0.5, 1);
+  TEST_f_L (llround, -0.5, -1);
+  TEST_f_L (llround, 0.8L, 1);
+  TEST_f_L (llround, -0.8L, -1);
+  TEST_f_L (llround, 1.5, 2);
+  TEST_f_L (llround, -1.5, -2);
+  TEST_f_L (llround, 22514.5, 22515);
+  TEST_f_L (llround, -22514.5, -22515);
+  TEST_f_l (llround, 1071930.0008, 1071930);
+#ifndef TEST_FLOAT
+  TEST_f_L (llround, 2097152.5, 2097153);
+  TEST_f_L (llround, -2097152.5, -2097153);
+  TEST_f_L (llround, 34359738368.5, 34359738369ll);
+  TEST_f_L (llround, -34359738368.5, -34359738369ll);
+#endif
+
+  /* Test boundary conditions.  */
+  /* 0x1FFFFF */
+  TEST_f_L (llround, 2097151.0, 2097151LL);
+  /* 0x800000 */
+  TEST_f_L (llround, 8388608.0, 8388608LL);
+  /* 0x1000000 */
+  TEST_f_L (llround, 16777216.0, 16777216LL);
+  /* 0x20000000000 */
+  TEST_f_L (llround, 2199023255552.0, 2199023255552LL);
+  /* 0x40000000000 */
+  TEST_f_L (llround, 4398046511104.0, 4398046511104LL);
+  /* 0x1000000000000 */
+  TEST_f_L (llround, 281474976710656.0, 281474976710656LL);
+  /* 0x10000000000000 */
+  TEST_f_L (llround, 4503599627370496.0, 4503599627370496LL);
+  /* 0x10000080000000 */
+  TEST_f_L (llround, 4503601774854144.0, 4503601774854144LL);
+  /* 0x20000000000000 */
+  TEST_f_L (llround, 9007199254740992.0, 9007199254740992LL);
+  /* 0x80000000000000 */
+  TEST_f_L (llround, 36028797018963968.0, 36028797018963968LL);
+  /* 0x100000000000000 */
+  TEST_f_L (llround, 72057594037927936.0, 72057594037927936LL);
+
+#ifndef TEST_FLOAT
+  /* 0x100000000 */
+  TEST_f_L (llround, 4294967295.5, 4294967296LL);
+  /* 0x200000000 */
+  TEST_f_L (llround, 8589934591.5, 8589934592LL);
+#endif
+
+#ifdef TEST_LDOUBLE
+  /* The input can only be represented in long double.  */
+  TEST_f_L (llround, 4503599627370495.5L, 4503599627370496LL);
+  TEST_f_L (llround, 4503599627370496.25L, 4503599627370496LL);
+  TEST_f_L (llround, 4503599627370496.5L, 4503599627370497LL);
+  TEST_f_L (llround, 4503599627370496.75L, 4503599627370497LL);
+  TEST_f_L (llround, 4503599627370497.5L, 4503599627370498LL);
+
+  TEST_f_L (llround, -4503599627370495.5L, -4503599627370496LL);
+  TEST_f_L (llround, -4503599627370496.25L, -4503599627370496LL);
+  TEST_f_L (llround, -4503599627370496.5L, -4503599627370497LL);
+  TEST_f_L (llround, -4503599627370496.75L, -4503599627370497LL);
+  TEST_f_L (llround, -4503599627370497.5L, -4503599627370498LL);
+
+  TEST_f_L (llround, 9007199254740991.5L, 9007199254740992LL);
+  TEST_f_L (llround, 9007199254740992.25L, 9007199254740992LL);
+  TEST_f_L (llround, 9007199254740992.5L, 9007199254740993LL);
+  TEST_f_L (llround, 9007199254740992.75L, 9007199254740993LL);
+  TEST_f_L (llround, 9007199254740993.5L, 9007199254740994LL);
+
+  TEST_f_L (llround, -9007199254740991.5L, -9007199254740992LL);
+  TEST_f_L (llround, -9007199254740992.25L, -9007199254740992LL);
+  TEST_f_L (llround, -9007199254740992.5L, -9007199254740993LL);
+  TEST_f_L (llround, -9007199254740992.75L, -9007199254740993LL);
+  TEST_f_L (llround, -9007199254740993.5L, -9007199254740994LL);
+
+  TEST_f_L (llround, 72057594037927935.5L, 72057594037927936LL);
+  TEST_f_L (llround, 72057594037927936.25L, 72057594037927936LL);
+  TEST_f_L (llround, 72057594037927936.5L, 72057594037927937LL);
+  TEST_f_L (llround, 72057594037927936.75L, 72057594037927937LL);
+  TEST_f_L (llround, 72057594037927937.5L, 72057594037927938LL);
+
+  TEST_f_L (llround, -72057594037927935.5L, -72057594037927936LL);
+  TEST_f_L (llround, -72057594037927936.25L, -72057594037927936LL);
+  TEST_f_L (llround, -72057594037927936.5L, -72057594037927937LL);
+  TEST_f_L (llround, -72057594037927936.75L, -72057594037927937LL);
+  TEST_f_L (llround, -72057594037927937.5L, -72057594037927938LL);
+
+  TEST_f_L (llround, 9223372036854775806.25L, 9223372036854775806LL);
+  TEST_f_L (llround, -9223372036854775806.25L, -9223372036854775806LL);
+  TEST_f_L (llround, 9223372036854775806.5L, 9223372036854775807LL);
+  TEST_f_L (llround, -9223372036854775806.5L, -9223372036854775807LL);
+  TEST_f_L (llround, 9223372036854775807.0L, 9223372036854775807LL);
+  TEST_f_L (llround, -9223372036854775807.0L, -9223372036854775807LL);
+#endif
+
+  END (llround);
+}
+#endif
+
+static void
+modf_test (void)
+{
+  FLOAT x;
+
+  START (modf);
+
+  TEST_fF_f1 (modf, plus_infty, 0, plus_infty);
+  TEST_fF_f1 (modf, minus_infty, minus_zero, minus_infty);
+  TEST_fF_f1 (modf, nan_value, nan_value, nan_value);
+  TEST_fF_f1 (modf, 0, 0, 0);
+  TEST_fF_f1 (modf, 1.5, 0.5, 1);
+  TEST_fF_f1 (modf, 2.5, 0.5, 2);
+  TEST_fF_f1 (modf, -2.5, -0.5, -2);
+  TEST_fF_f1 (modf, 20, 0, 20);
+  TEST_fF_f1 (modf, 21, 0, 21);
+  TEST_fF_f1 (modf, 89.5, 0.5, 89);
+
+  END (modf);
+}
+
+
+#if 0
+static void
+nearbyint_test (void)
+{
+  START (nearbyint);
+
+  TEST_f_f (nearbyint, 0.0, 0.0);
+  TEST_f_f (nearbyint, minus_zero, minus_zero);
+  TEST_f_f (nearbyint, plus_infty, plus_infty);
+  TEST_f_f (nearbyint, minus_infty, minus_infty);
+  TEST_f_f (nearbyint, nan_value, nan_value);
+
+  /* Default rounding mode is round to nearest.  */
+  TEST_f_f (nearbyint, 0.5, 0.0);
+  TEST_f_f (nearbyint, 1.5, 2.0);
+  TEST_f_f (nearbyint, -0.5, minus_zero);
+  TEST_f_f (nearbyint, -1.5, -2.0);
+
+  END (nearbyint);
+}
+
+static void
+nextafter_test (void)
+{
+
+  START (nextafter);
+
+  TEST_ff_f (nextafter, 0, 0, 0);
+  TEST_ff_f (nextafter, minus_zero, 0, 0);
+  TEST_ff_f (nextafter, 0, minus_zero, minus_zero);
+  TEST_ff_f (nextafter, minus_zero, minus_zero, minus_zero);
+
+  TEST_ff_f (nextafter, 9, 9, 9);
+  TEST_ff_f (nextafter, -9, -9, -9);
+  TEST_ff_f (nextafter, plus_infty, plus_infty, plus_infty);
+  TEST_ff_f (nextafter, minus_infty, minus_infty, minus_infty);
+
+  TEST_ff_f (nextafter, nan_value, 1.1L, nan_value);
+  TEST_ff_f (nextafter, 1.1L, nan_value, nan_value);
+  TEST_ff_f (nextafter, nan_value, nan_value, nan_value);
+
+  FLOAT fltmax = CHOOSE (LDBL_MAX, DBL_MAX, FLT_MAX,
+			 LDBL_MAX, DBL_MAX, FLT_MAX);
+  TEST_ff_f (nextafter, fltmax, plus_infty, plus_infty);
+  TEST_ff_f (nextafter, -fltmax, minus_infty, minus_infty);
+
+#ifdef TEST_LDOUBLE
+  // XXX Enable once gcc is fixed.
+  //TEST_ff_f (nextafter, 0x0.00000040000000000000p-16385L, -0.1L, 0x0.0000003ffffffff00000p-16385L);
+#endif
+
+  /* XXX We need the hexadecimal FP number representation here for further
+     tests.  */
+
+  END (nextafter);
+}
+
+
+static void
+nexttoward_test (void)
+{
+  START (nexttoward);
+  TEST_ff_f (nexttoward, 0, 0, 0);
+  TEST_ff_f (nexttoward, minus_zero, 0, 0);
+  TEST_ff_f (nexttoward, 0, minus_zero, minus_zero);
+  TEST_ff_f (nexttoward, minus_zero, minus_zero, minus_zero);
+
+  TEST_ff_f (nexttoward, 9, 9, 9);
+  TEST_ff_f (nexttoward, -9, -9, -9);
+  TEST_ff_f (nexttoward, plus_infty, plus_infty, plus_infty);
+  TEST_ff_f (nexttoward, minus_infty, minus_infty, minus_infty);
+
+  TEST_ff_f (nexttoward, nan_value, 1.1L, nan_value);
+  TEST_ff_f (nexttoward, 1.1L, nan_value, nan_value);
+  TEST_ff_f (nexttoward, nan_value, nan_value, nan_value);
+
+  /* XXX We need the hexadecimal FP number representation here for further
+     tests.  */
+
+  END (nexttoward);
+}
+#endif
+
+
+static void
+pow_test (void)
+{
+
+  errno = 0;
+  FUNC(pow) (0, 0);
+  if (errno == ENOSYS)
+    /* Function not implemented.  */
+    return;
+
+  START (pow);
+
+  TEST_ff_f (pow, 0, 0, 1);
+  TEST_ff_f (pow, 0, minus_zero, 1);
+  TEST_ff_f (pow, minus_zero, 0, 1);
+  TEST_ff_f (pow, minus_zero, minus_zero, 1);
+
+  TEST_ff_f (pow, 10, 0, 1);
+  TEST_ff_f (pow, 10, minus_zero, 1);
+  TEST_ff_f (pow, -10, 0, 1);
+  TEST_ff_f (pow, -10, minus_zero, 1);
+
+  TEST_ff_f (pow, nan_value, 0, 1);
+  TEST_ff_f (pow, nan_value, minus_zero, 1);
+
+
+#ifndef TEST_INLINE
+  TEST_ff_f (pow, 1.1L, plus_infty, plus_infty);
+  TEST_ff_f (pow, plus_infty, plus_infty, plus_infty);
+  TEST_ff_f (pow, -1.1L, plus_infty, plus_infty);
+  TEST_ff_f (pow, minus_infty, plus_infty, plus_infty);
+
+  TEST_ff_f (pow, 0.9L, plus_infty, 0);
+  TEST_ff_f (pow, 1e-7L, plus_infty, 0);
+  TEST_ff_f (pow, -0.9L, plus_infty, 0);
+  TEST_ff_f (pow, -1e-7L, plus_infty, 0);
+
+  TEST_ff_f (pow, 1.1L, minus_infty, 0);
+  TEST_ff_f (pow, plus_infty, minus_infty, 0);
+  TEST_ff_f (pow, -1.1L, minus_infty, 0);
+  TEST_ff_f (pow, minus_infty, minus_infty, 0);
+
+  TEST_ff_f (pow, 0.9L, minus_infty, plus_infty);
+  TEST_ff_f (pow, 1e-7L, minus_infty, plus_infty);
+  TEST_ff_f (pow, -0.9L, minus_infty, plus_infty);
+  TEST_ff_f (pow, -1e-7L, minus_infty, plus_infty);
+
+  TEST_ff_f (pow, plus_infty, 1e-7L, plus_infty);
+  TEST_ff_f (pow, plus_infty, 1, plus_infty);
+  TEST_ff_f (pow, plus_infty, 1e7L, plus_infty);
+
+  TEST_ff_f (pow, plus_infty, -1e-7L, 0);
+  TEST_ff_f (pow, plus_infty, -1, 0);
+  TEST_ff_f (pow, plus_infty, -1e7L, 0);
+
+  TEST_ff_f (pow, minus_infty, 1, minus_infty);
+  TEST_ff_f (pow, minus_infty, 11, minus_infty);
+  TEST_ff_f (pow, minus_infty, 1001, minus_infty);
+
+  TEST_ff_f (pow, minus_infty, 2, plus_infty);
+  TEST_ff_f (pow, minus_infty, 12, plus_infty);
+  TEST_ff_f (pow, minus_infty, 1002, plus_infty);
+  TEST_ff_f (pow, minus_infty, 0.1L, plus_infty);
+  TEST_ff_f (pow, minus_infty, 1.1L, plus_infty);
+  TEST_ff_f (pow, minus_infty, 11.1L, plus_infty);
+  TEST_ff_f (pow, minus_infty, 1001.1L, plus_infty);
+
+  TEST_ff_f (pow, minus_infty, -1, minus_zero);
+  TEST_ff_f (pow, minus_infty, -11, minus_zero);
+  TEST_ff_f (pow, minus_infty, -1001, minus_zero);
+
+  TEST_ff_f (pow, minus_infty, -2, 0);
+  TEST_ff_f (pow, minus_infty, -12, 0);
+  TEST_ff_f (pow, minus_infty, -1002, 0);
+  TEST_ff_f (pow, minus_infty, -0.1L, 0);
+  TEST_ff_f (pow, minus_infty, -1.1L, 0);
+  TEST_ff_f (pow, minus_infty, -11.1L, 0);
+  TEST_ff_f (pow, minus_infty, -1001.1L, 0);
+#endif
+
+  TEST_ff_f (pow, nan_value, nan_value, nan_value);
+  TEST_ff_f (pow, 0, nan_value, nan_value);
+  TEST_ff_f (pow, 1, nan_value, 1);
+  TEST_ff_f (pow, -1, nan_value, nan_value);
+  TEST_ff_f (pow, nan_value, 1, nan_value);
+  TEST_ff_f (pow, nan_value, -1, nan_value);
+
+  /* pow (x, NaN) == NaN.  */
+  TEST_ff_f (pow, 3.0, nan_value, nan_value);
+
+  TEST_ff_f (pow, 1, plus_infty, 1);
+  TEST_ff_f (pow, -1, plus_infty, 1);
+  TEST_ff_f (pow, 1, minus_infty, 1);
+  TEST_ff_f (pow, -1, minus_infty, 1);
+  TEST_ff_f (pow, 1, 1, 1);
+  TEST_ff_f (pow, 1, -1, 1);
+  TEST_ff_f (pow, 1, 1.25, 1);
+  TEST_ff_f (pow, 1, -1.25, 1);
+  TEST_ff_f (pow, 1, 0x1p62L, 1);
+  TEST_ff_f (pow, 1, 0x1p63L, 1);
+  TEST_ff_f (pow, 1, 0x1p64L, 1);
+  TEST_ff_f (pow, 1, 0x1p72L, 1);
+
+  /* pow (x, +-0) == 1.  */
+  TEST_ff_f (pow, plus_infty, 0, 1);
+  TEST_ff_f (pow, plus_infty, minus_zero, 1);
+  TEST_ff_f (pow, minus_infty, 0, 1);
+  TEST_ff_f (pow, minus_infty, minus_zero, 1);
+  TEST_ff_f (pow, 32.75L, 0, 1);
+  TEST_ff_f (pow, 32.75L, minus_zero, 1);
+  TEST_ff_f (pow, -32.75L, 0, 1);
+  TEST_ff_f (pow, -32.75L, minus_zero, 1);
+  TEST_ff_f (pow, 0x1p72L, 0, 1);
+  TEST_ff_f (pow, 0x1p72L, minus_zero, 1);
+  TEST_ff_f (pow, 0x1p-72L, 0, 1);
+  TEST_ff_f (pow, 0x1p-72L, minus_zero, 1);
+
+  TEST_ff_f (pow, -0.1L, 1.1L, nan_value, INVALID_EXCEPTION);
+  TEST_ff_f (pow, -0.1L, -1.1L, nan_value, INVALID_EXCEPTION);
+  TEST_ff_f (pow, -10.1L, 1.1L, nan_value, INVALID_EXCEPTION);
+  TEST_ff_f (pow, -10.1L, -1.1L, nan_value, INVALID_EXCEPTION);
+
+  TEST_ff_f (pow, 0, -1, plus_infty, DIVIDE_BY_ZERO_EXCEPTION);
+  TEST_ff_f (pow, 0, -11, plus_infty, DIVIDE_BY_ZERO_EXCEPTION);
+  TEST_ff_f (pow, minus_zero, -1, minus_infty, DIVIDE_BY_ZERO_EXCEPTION);
+  TEST_ff_f (pow, minus_zero, -11, minus_infty, DIVIDE_BY_ZERO_EXCEPTION);
+
+  TEST_ff_f (pow, 0, -2, plus_infty, DIVIDE_BY_ZERO_EXCEPTION);
+  TEST_ff_f (pow, 0, -11.1L, plus_infty, DIVIDE_BY_ZERO_EXCEPTION);
+  TEST_ff_f (pow, minus_zero, -2, plus_infty, DIVIDE_BY_ZERO_EXCEPTION);
+  TEST_ff_f (pow, minus_zero, -11.1L, plus_infty, DIVIDE_BY_ZERO_EXCEPTION);
+
+  TEST_ff_f (pow, 0x1p72L, 0x1p72L, plus_infty);
+  TEST_ff_f (pow, 10, -0x1p72L, 0);
+  TEST_ff_f (pow, max_value, max_value, plus_infty);
+  TEST_ff_f (pow, 10, -max_value, 0);
+
+  TEST_ff_f (pow, 0, 1, 0);
+  TEST_ff_f (pow, 0, 11, 0);
+
+  TEST_ff_f (pow, minus_zero, 1, minus_zero);
+  TEST_ff_f (pow, minus_zero, 11, minus_zero);
+
+
+  TEST_ff_f (pow, 0, 2, 0);
+  TEST_ff_f (pow, 0, 11.1L, 0);
+
+
+  TEST_ff_f (pow, minus_zero, 2, 0);
+  TEST_ff_f (pow, minus_zero, 11.1L, 0);
+  TEST_ff_f (pow, 0, plus_infty, 0);
+  TEST_ff_f (pow, minus_zero, plus_infty, 0);
+
+#ifndef TEST_INLINE
+  /* pow (x, +inf) == +inf for |x| > 1.  */
+  TEST_ff_f (pow, 1.5, plus_infty, plus_infty);
+
+  /* pow (x, +inf) == +0 for |x| < 1.  */
+  TEST_ff_f (pow, 0.5, plus_infty, 0.0);
+
+  /* pow (x, -inf) == +0 for |x| > 1.  */
+  TEST_ff_f (pow, 1.5, minus_infty, 0.0);
+
+  /* pow (x, -inf) == +inf for |x| < 1.  */
+  TEST_ff_f (pow, 0.5, minus_infty, plus_infty);
+#endif
+
+  /* pow (+inf, y) == +inf for y > 0.  */
+  TEST_ff_f (pow, plus_infty, 2, plus_infty);
+
+  /* pow (+inf, y) == +0 for y < 0.  */
+  TEST_ff_f (pow, plus_infty, -1, 0.0);
+
+  /* pow (-inf, y) == -inf for y an odd integer > 0.  */
+  TEST_ff_f (pow, minus_infty, 27, minus_infty);
+
+  /* pow (-inf, y) == +inf for y > 0 and not an odd integer.  */
+  TEST_ff_f (pow, minus_infty, 28, plus_infty);
+
+  /* pow (-inf, y) == -0 for y an odd integer < 0. */
+  TEST_ff_f (pow, minus_infty, -3, minus_zero);
+  /* pow (-inf, y) == +0 for y < 0 and not an odd integer.  */
+  TEST_ff_f (pow, minus_infty, -2.0, 0.0);
+
+  /* pow (+0, y) == +0 for y an odd integer > 0.  */
+  TEST_ff_f (pow, 0.0, 27, 0.0);
+
+  /* pow (-0, y) == -0 for y an odd integer > 0.  */
+  TEST_ff_f (pow, minus_zero, 27, minus_zero);
+
+  /* pow (+0, y) == +0 for y > 0 and not an odd integer.  */
+  TEST_ff_f (pow, 0.0, 4, 0.0);
+
+  /* pow (-0, y) == +0 for y > 0 and not an odd integer.  */
+  TEST_ff_f (pow, minus_zero, 4, 0.0);
+
+  TEST_ff_f (pow, 16, 0.25L, 2);
+  TEST_ff_f (pow, 0x1p64L, 0.125L, 256);
+  TEST_ff_f (pow, 2, 4, 16);
+  TEST_ff_f (pow, 256, 8, 0x1p64L);
+
+  TEST_ff_f (pow, 0.75L, 1.25L, 0.697953644326574699205914060237425566L);
+
+#if defined TEST_DOUBLE || defined TEST_LDOUBLE
+  TEST_ff_f (pow, -7.49321e+133, -9.80818e+16, 0);
+#endif
+
+  END (pow);
+}
+
+static void
+remainder_test (void)
+{
+  errno = 0;
+  FUNC(remainder) (1.625, 1.0);
+  if (errno == ENOSYS)
+    /* Function not implemented.  */
+    return;
+
+  START (remainder);
+
+  TEST_ff_f (remainder, 1, 0, nan_value, INVALID_EXCEPTION);
+  TEST_ff_f (remainder, 1, minus_zero, nan_value, INVALID_EXCEPTION);
+  TEST_ff_f (remainder, plus_infty, 1, nan_value, INVALID_EXCEPTION);
+  TEST_ff_f (remainder, minus_infty, 1, nan_value, INVALID_EXCEPTION);
+  TEST_ff_f (remainder, nan_value, nan_value, nan_value);
+
+  TEST_ff_f (remainder, 1.625, 1.0, -0.375);
+  TEST_ff_f (remainder, -1.625, 1.0, 0.375);
+  TEST_ff_f (remainder, 1.625, -1.0, -0.375);
+  TEST_ff_f (remainder, -1.625, -1.0, 0.375);
+  TEST_ff_f (remainder, 5.0, 2.0, 1.0);
+  TEST_ff_f (remainder, 3.0, 2.0, -1.0);
+
+  END (remainder);
+}
+
+#if 0
+static void
+remquo_test (void)
+{
+  /* x is needed.  */
+  int x;
+
+  errno = 0;
+  FUNC(remquo) (1.625, 1.0, &x);
+  if (errno == ENOSYS)
+    /* Function not implemented.  */
+    return;
+
+  START (remquo);
+
+  TEST_ffI_f1 (remquo, 1, 0, nan_value, IGNORE, INVALID_EXCEPTION);
+  TEST_ffI_f1 (remquo, 1, minus_zero, nan_value, IGNORE, INVALID_EXCEPTION);
+  TEST_ffI_f1 (remquo, plus_infty, 1, nan_value, IGNORE, INVALID_EXCEPTION);
+  TEST_ffI_f1 (remquo, minus_infty, 1, nan_value, IGNORE, INVALID_EXCEPTION);
+  TEST_ffI_f1 (remquo, nan_value, nan_value, nan_value, IGNORE);
+
+  TEST_ffI_f1 (remquo, 1.625, 1.0, -0.375, 2);
+  TEST_ffI_f1 (remquo, -1.625, 1.0, 0.375, -2);
+  TEST_ffI_f1 (remquo, 1.625, -1.0, -0.375, -2);
+  TEST_ffI_f1 (remquo, -1.625, -1.0, 0.375, 2);
+
+  TEST_ffI_f1 (remquo, 5, 2, 1, 2);
+  TEST_ffI_f1 (remquo, 3, 2, -1, 2);
+
+  END (remquo);
+}
+#endif
+
+static void
+rint_test (void)
+{
+  START (rint);
+
+  TEST_f_f (rint, 0.0, 0.0);
+  TEST_f_f (rint, minus_zero, minus_zero);
+  TEST_f_f (rint, plus_infty, plus_infty);
+  TEST_f_f (rint, minus_infty, minus_infty);
+
+  /* Default rounding mode is round to even.  */
+  TEST_f_f (rint, 0.5, 0.0);
+  TEST_f_f (rint, 1.5, 2.0);
+  TEST_f_f (rint, 2.5, 2.0);
+  TEST_f_f (rint, 3.5, 4.0);
+  TEST_f_f (rint, 4.5, 4.0);
+  TEST_f_f (rint, -0.5, -0.0);
+  TEST_f_f (rint, -1.5, -2.0);
+  TEST_f_f (rint, -2.5, -2.0);
+  TEST_f_f (rint, -3.5, -4.0);
+  TEST_f_f (rint, -4.5, -4.0);
+#ifdef TEST_LDOUBLE
+  /* The result can only be represented in long double.  */
+  TEST_f_f (rint, 4503599627370495.5L, 4503599627370496.0L);
+  TEST_f_f (rint, 4503599627370496.25L, 4503599627370496.0L);
+  TEST_f_f (rint, 4503599627370496.5L, 4503599627370496.0L);
+  TEST_f_f (rint, 4503599627370496.75L, 4503599627370497.0L);
+  TEST_f_f (rint, 4503599627370497.5L, 4503599627370498.0L);
+
+  TEST_f_f (rint, -4503599627370495.5L, -4503599627370496.0L);
+  TEST_f_f (rint, -4503599627370496.25L, -4503599627370496.0L);
+  TEST_f_f (rint, -4503599627370496.5L, -4503599627370496.0L);
+  TEST_f_f (rint, -4503599627370496.75L, -4503599627370497.0L);
+  TEST_f_f (rint, -4503599627370497.5L, -4503599627370498.0L);
+
+  TEST_f_f (rint, 9007199254740991.5L, 9007199254740992.0L);
+  TEST_f_f (rint, 9007199254740992.25L, 9007199254740992.0L);
+  TEST_f_f (rint, 9007199254740992.5L, 9007199254740992.0L);
+  TEST_f_f (rint, 9007199254740992.75L, 9007199254740993.0L);
+  TEST_f_f (rint, 9007199254740993.5L, 9007199254740994.0L);
+
+  TEST_f_f (rint, -9007199254740991.5L, -9007199254740992.0L);
+  TEST_f_f (rint, -9007199254740992.25L, -9007199254740992.0L);
+  TEST_f_f (rint, -9007199254740992.5L, -9007199254740992.0L);
+  TEST_f_f (rint, -9007199254740992.75L, -9007199254740993.0L);
+  TEST_f_f (rint, -9007199254740993.5L, -9007199254740994.0L);
+
+  TEST_f_f (rint, 72057594037927935.5L, 72057594037927936.0L);
+  TEST_f_f (rint, 72057594037927936.25L, 72057594037927936.0L);
+  TEST_f_f (rint, 72057594037927936.5L, 72057594037927936.0L);
+  TEST_f_f (rint, 72057594037927936.75L, 72057594037927937.0L);
+  TEST_f_f (rint, 72057594037927937.5L, 72057594037927938.0L);
+
+  TEST_f_f (rint, -72057594037927935.5L, -72057594037927936.0L);
+  TEST_f_f (rint, -72057594037927936.25L, -72057594037927936.0L);
+  TEST_f_f (rint, -72057594037927936.5L, -72057594037927936.0L);
+  TEST_f_f (rint, -72057594037927936.75L, -72057594037927937.0L);
+  TEST_f_f (rint, -72057594037927937.5L, -72057594037927938.0L);
+
+  TEST_f_f (rint, 10141204801825835211973625643007.5L, 10141204801825835211973625643008.0L);
+  TEST_f_f (rint, 10141204801825835211973625643008.25L, 10141204801825835211973625643008.0L);
+  TEST_f_f (rint, 10141204801825835211973625643008.5L, 10141204801825835211973625643008.0L);
+  TEST_f_f (rint, 10141204801825835211973625643008.75L, 10141204801825835211973625643009.0L);
+  TEST_f_f (rint, 10141204801825835211973625643009.5L, 10141204801825835211973625643010.0L);
+#endif
+
+  END (rint);
+}
+
+#if 0
+static void
+rint_test_tonearest (void)
+{
+  int save_round_mode;
+  START (rint_tonearest);
+
+  save_round_mode = fegetround();
+
+  if (!fesetround (FE_TONEAREST))
+  {
+    TEST_f_f (rint, 2.0, 2.0);
+    TEST_f_f (rint, 1.5, 2.0);
+    TEST_f_f (rint, 1.0, 1.0);
+    TEST_f_f (rint, 0.5, 0.0);
+    TEST_f_f (rint, 0.0, 0.0);
+    TEST_f_f (rint, minus_zero, minus_zero);
+    TEST_f_f (rint, -0.5, -0.0);
+    TEST_f_f (rint, -1.0, -1.0);
+    TEST_f_f (rint, -1.5, -2.0);
+    TEST_f_f (rint, -2.0, -2.0);
+  }
+
+  fesetround(save_round_mode);
+
+  END (rint_tonearest);
+}
+
+static void
+rint_test_towardzero (void)
+{
+  int save_round_mode;
+  START (rint_towardzero);
+
+  save_round_mode = fegetround();
+
+  if (!fesetround (FE_TOWARDZERO))
+  {
+    TEST_f_f (rint, 2.0, 2.0);
+    TEST_f_f (rint, 1.5, 1.0);
+    TEST_f_f (rint, 1.0, 1.0);
+    TEST_f_f (rint, 0.5, 0.0);
+    TEST_f_f (rint, 0.0, 0.0);
+    TEST_f_f (rint, minus_zero, minus_zero);
+    TEST_f_f (rint, -0.5, -0.0);
+    TEST_f_f (rint, -1.0, -1.0);
+    TEST_f_f (rint, -1.5, -1.0);
+    TEST_f_f (rint, -2.0, -2.0);
+  }
+
+  fesetround(save_round_mode);
+
+  END (rint_towardzero);
+}
+
+static void
+rint_test_downward (void)
+{
+  int save_round_mode;
+  START (rint_downward);
+
+  save_round_mode = fegetround();
+
+  if (!fesetround (FE_DOWNWARD))
+  {
+    TEST_f_f (rint, 2.0, 2.0);
+    TEST_f_f (rint, 1.5, 1.0);
+    TEST_f_f (rint, 1.0, 1.0);
+    TEST_f_f (rint, 0.5, 0.0);
+    TEST_f_f (rint, 0.0, 0.0);
+    TEST_f_f (rint, minus_zero, minus_zero);
+    TEST_f_f (rint, -0.5, -1.0);
+    TEST_f_f (rint, -1.0, -1.0);
+    TEST_f_f (rint, -1.5, -2.0);
+    TEST_f_f (rint, -2.0, -2.0);
+  }
+
+  fesetround(save_round_mode);
+
+  END (rint_downward);
+}
+
+static void
+rint_test_upward (void)
+{
+  int save_round_mode;
+  START (rint_upward);
+
+  save_round_mode = fegetround();
+
+  if (!fesetround (FE_UPWARD))
+  {
+    TEST_f_f (rint, 2.0, 2.0);
+    TEST_f_f (rint, 1.5, 2.0);
+    TEST_f_f (rint, 1.0, 1.0);
+    TEST_f_f (rint, 0.5, 1.0);
+    TEST_f_f (rint, 0.0, 0.0);
+    TEST_f_f (rint, minus_zero, minus_zero);
+    TEST_f_f (rint, -0.5, -0.0);
+    TEST_f_f (rint, -1.0, -1.0);
+    TEST_f_f (rint, -1.5, -1.0);
+    TEST_f_f (rint, -2.0, -2.0);
+  }
+
+  fesetround(save_round_mode);
+
+  END (rint_upward);
+}
+
+static void
+round_test (void)
+{
+  START (round);
+
+  TEST_f_f (round, 0, 0);
+  TEST_f_f (round, minus_zero, minus_zero);
+  TEST_f_f (round, 0.2L, 0.0);
+  TEST_f_f (round, -0.2L, minus_zero);
+  TEST_f_f (round, 0.5, 1.0);
+  TEST_f_f (round, -0.5, -1.0);
+  TEST_f_f (round, 0.8L, 1.0);
+  TEST_f_f (round, -0.8L, -1.0);
+  TEST_f_f (round, 1.5, 2.0);
+  TEST_f_f (round, -1.5, -2.0);
+  TEST_f_f (round, 2097152.5, 2097153);
+  TEST_f_f (round, -2097152.5, -2097153);
+
+#ifdef TEST_LDOUBLE
+  /* The result can only be represented in long double.  */
+  TEST_f_f (round, 4503599627370495.5L, 4503599627370496.0L);
+  TEST_f_f (round, 4503599627370496.25L, 4503599627370496.0L);
+  TEST_f_f (round, 4503599627370496.5L, 4503599627370497.0L);
+  TEST_f_f (round, 4503599627370496.75L, 4503599627370497.0L);
+  TEST_f_f (round, 4503599627370497.5L, 4503599627370498.0L);
+
+  TEST_f_f (round, -4503599627370495.5L, -4503599627370496.0L);
+  TEST_f_f (round, -4503599627370496.25L, -4503599627370496.0L);
+  TEST_f_f (round, -4503599627370496.5L, -4503599627370497.0L);
+  TEST_f_f (round, -4503599627370496.75L, -4503599627370497.0L);
+  TEST_f_f (round, -4503599627370497.5L, -4503599627370498.0L);
+
+  TEST_f_f (round, 9007199254740991.5L, 9007199254740992.0L);
+  TEST_f_f (round, 9007199254740992.25L, 9007199254740992.0L);
+  TEST_f_f (round, 9007199254740992.5L, 9007199254740993.0L);
+  TEST_f_f (round, 9007199254740992.75L, 9007199254740993.0L);
+  TEST_f_f (round, 9007199254740993.5L, 9007199254740994.0L);
+
+  TEST_f_f (round, -9007199254740991.5L, -9007199254740992.0L);
+  TEST_f_f (round, -9007199254740992.25L, -9007199254740992.0L);
+  TEST_f_f (round, -9007199254740992.5L, -9007199254740993.0L);
+  TEST_f_f (round, -9007199254740992.75L, -9007199254740993.0L);
+  TEST_f_f (round, -9007199254740993.5L, -9007199254740994.0L);
+
+  TEST_f_f (round, 72057594037927935.5L, 72057594037927936.0L);
+  TEST_f_f (round, 72057594037927936.25L, 72057594037927936.0L);
+  TEST_f_f (round, 72057594037927936.5L, 72057594037927937.0L);
+  TEST_f_f (round, 72057594037927936.75L, 72057594037927937.0L);
+  TEST_f_f (round, 72057594037927937.5L, 72057594037927938.0L);
+
+  TEST_f_f (round, -72057594037927935.5L, -72057594037927936.0L);
+  TEST_f_f (round, -72057594037927936.25L, -72057594037927936.0L);
+  TEST_f_f (round, -72057594037927936.5L, -72057594037927937.0L);
+  TEST_f_f (round, -72057594037927936.75L, -72057594037927937.0L);
+  TEST_f_f (round, -72057594037927937.5L, -72057594037927938.0L);
+
+  TEST_f_f (round, 10141204801825835211973625643007.5L, 10141204801825835211973625643008.0L);
+  TEST_f_f (round, 10141204801825835211973625643008.25L, 10141204801825835211973625643008.0L);
+  TEST_f_f (round, 10141204801825835211973625643008.5L, 10141204801825835211973625643009.0L);
+  TEST_f_f (round, 10141204801825835211973625643008.75L, 10141204801825835211973625643009.0L);
+  TEST_f_f (round, 10141204801825835211973625643009.5L, 10141204801825835211973625643010.0L);
+#endif
+
+  END (round);
+}
+#endif
+
+
+static void
+scalb_test (void)
+{
+  START (scalb);
+#ifndef TEST_LDOUBLE /* uclibc doesn't have scalbl */
+#ifdef __UCLIBC_SUSV3_LEGACY__ /* scalbf is susv3 legacy */
+
+  TEST_ff_f (scalb, 2.0, 0.5, nan_value, INVALID_EXCEPTION);
+  TEST_ff_f (scalb, 3.0, -2.5, nan_value, INVALID_EXCEPTION);
+
+  TEST_ff_f (scalb, 0, nan_value, nan_value);
+  TEST_ff_f (scalb, 1, nan_value, nan_value);
+
+  TEST_ff_f (scalb, 1, 0, 1);
+  TEST_ff_f (scalb, -1, 0, -1);
+
+  TEST_ff_f (scalb, 0, plus_infty, nan_value, INVALID_EXCEPTION);
+  TEST_ff_f (scalb, minus_zero, plus_infty, nan_value, INVALID_EXCEPTION);
+
+  TEST_ff_f (scalb, 0, 2, 0);
+  TEST_ff_f (scalb, minus_zero, -4, minus_zero);
+  TEST_ff_f (scalb, 0, 0, 0);
+  TEST_ff_f (scalb, minus_zero, 0, minus_zero);
+  TEST_ff_f (scalb, 0, -1, 0);
+  TEST_ff_f (scalb, minus_zero, -10, minus_zero);
+  TEST_ff_f (scalb, 0, minus_infty, 0);
+  TEST_ff_f (scalb, minus_zero, minus_infty, minus_zero);
+
+  TEST_ff_f (scalb, plus_infty, -1, plus_infty);
+  TEST_ff_f (scalb, minus_infty, -10, minus_infty);
+  TEST_ff_f (scalb, plus_infty, 0, plus_infty);
+  TEST_ff_f (scalb, minus_infty, 0, minus_infty);
+  TEST_ff_f (scalb, plus_infty, 2, plus_infty);
+  TEST_ff_f (scalb, minus_infty, 100, minus_infty);
+
+  TEST_ff_f (scalb, 0.1L, minus_infty, 0.0);
+  TEST_ff_f (scalb, -0.1L, minus_infty, minus_zero);
+
+  TEST_ff_f (scalb, 1, plus_infty, plus_infty);
+  TEST_ff_f (scalb, -1, plus_infty, minus_infty);
+  TEST_ff_f (scalb, plus_infty, plus_infty, plus_infty);
+  TEST_ff_f (scalb, minus_infty, plus_infty, minus_infty);
+
+  TEST_ff_f (scalb, plus_infty, minus_infty, nan_value, INVALID_EXCEPTION);
+  TEST_ff_f (scalb, minus_infty, minus_infty, nan_value, INVALID_EXCEPTION);
+
+  TEST_ff_f (scalb, nan_value, 1, nan_value);
+  TEST_ff_f (scalb, 1, nan_value, nan_value);
+  TEST_ff_f (scalb, nan_value, 0, nan_value);
+  TEST_ff_f (scalb, 0, nan_value, nan_value);
+  TEST_ff_f (scalb, nan_value, plus_infty, nan_value);
+  TEST_ff_f (scalb, plus_infty, nan_value, nan_value);
+  TEST_ff_f (scalb, nan_value, nan_value, nan_value);
+
+  TEST_ff_f (scalb, 0.8L, 4, 12.8L);
+  TEST_ff_f (scalb, -0.854375L, 5, -27.34L);
+#endif /* __UCLIBC_SUSV3_LEGACY__ */
+#endif /* TEST_LDOUBLE */
+  END (scalb);
+}
+
+
+static void
+scalbn_test (void)
+{
+
+  START (scalbn);
+
+  TEST_fi_f (scalbn, 0, 0, 0);
+  TEST_fi_f (scalbn, minus_zero, 0, minus_zero);
+
+  TEST_fi_f (scalbn, plus_infty, 1, plus_infty);
+  TEST_fi_f (scalbn, minus_infty, 1, minus_infty);
+  TEST_fi_f (scalbn, nan_value, 1, nan_value);
+
+  TEST_fi_f (scalbn, 0.8L, 4, 12.8L);
+  TEST_fi_f (scalbn, -0.854375L, 5, -27.34L);
+
+  TEST_fi_f (scalbn, 1, 0L, 1);
+
+  END (scalbn);
+}
+
+
+#if 0
+static void
+scalbln_test (void)
+{
+
+  START (scalbln);
+
+  TEST_fl_f (scalbln, 0, 0, 0);
+  TEST_fl_f (scalbln, minus_zero, 0, minus_zero);
+
+  TEST_fl_f (scalbln, plus_infty, 1, plus_infty);
+  TEST_fl_f (scalbln, minus_infty, 1, minus_infty);
+  TEST_fl_f (scalbln, nan_value, 1, nan_value);
+
+  TEST_fl_f (scalbln, 0.8L, 4, 12.8L);
+  TEST_fl_f (scalbln, -0.854375L, 5, -27.34L);
+
+  TEST_fl_f (scalbln, 1, 0L, 1);
+
+  END (scalbn);
+}
+#endif
+
+
+static void
+signbit_test (void)
+{
+
+  START (signbit);
+
+  TEST_f_b (signbit, 0, 0);
+  TEST_f_b (signbit, minus_zero, 1);
+  TEST_f_b (signbit, plus_infty, 0);
+  TEST_f_b (signbit, minus_infty, 1);
+
+  /* signbit (x) != 0 for x < 0.  */
+  TEST_f_b (signbit, -1, 1);
+  /* signbit (x) == 0 for x >= 0.  */
+  TEST_f_b (signbit, 1, 0);
+
+  END (signbit);
+}
+
+
+static void
+sin_test (void)
+{
+  errno = 0;
+  FUNC(sin) (0);
+  if (errno == ENOSYS)
+    /* Function not implemented.  */
+    return;
+
+  START (sin);
+
+  TEST_f_f (sin, 0, 0);
+  TEST_f_f (sin, minus_zero, minus_zero);
+  TEST_f_f (sin, plus_infty, nan_value, INVALID_EXCEPTION);
+  TEST_f_f (sin, minus_infty, nan_value, INVALID_EXCEPTION);
+  TEST_f_f (sin, nan_value, nan_value);
+
+  TEST_f_f (sin, M_PI_6l, 0.5);
+  TEST_f_f (sin, -M_PI_6l, -0.5);
+  TEST_f_f (sin, M_PI_2l, 1);
+  TEST_f_f (sin, -M_PI_2l, -1);
+  TEST_f_f (sin, 0.75L, 0.681638760023334166733241952779893935L);
+
+#ifdef TEST_DOUBLE
+  TEST_f_f (sin, 0.80190127184058835, 0.71867942238767868);
+#endif
+
+  END (sin);
+
+}
+
+
+#if 0
+static void
+sincos_test (void)
+{
+  FLOAT sin_res, cos_res;
+
+  errno = 0;
+  FUNC(sincos) (0, &sin_res, &cos_res);
+  if (errno == ENOSYS)
+    /* Function not implemented.  */
+    return;
+
+  START (sincos);
+
+  /* sincos is treated differently because it returns void.  */
+  TEST_extra (sincos, 0, 0, 1);
+
+  TEST_extra (sincos, minus_zero, minus_zero, 1);
+  TEST_extra (sincos, plus_infty, nan_value, nan_value, INVALID_EXCEPTION);
+  TEST_extra (sincos, minus_infty, nan_value, nan_value, INVALID_EXCEPTION);
+  TEST_extra (sincos, nan_value, nan_value, nan_value);
+
+  TEST_extra (sincos, M_PI_2l, 1, 0);
+  TEST_extra (sincos, M_PI_6l, 0.5, 0.86602540378443864676372317075293616L);
+  TEST_extra (sincos, M_PI_6l*2.0, 0.86602540378443864676372317075293616L, 0.5);
+  TEST_extra (sincos, 0.75L, 0.681638760023334166733241952779893935L, 0.731688868873820886311838753000084544L);
+
+#ifdef TEST_DOUBLE
+  TEST_extra (sincos, 0.80190127184058835, 0.71867942238767868, 0.69534156199418473);
+#endif
+
+  END (sincos);
+}
+#endif
+
+static void
+sinh_test (void)
+{
+  errno = 0;
+  FUNC(sinh) (0.7L);
+  if (errno == ENOSYS)
+    /* Function not implemented.  */
+    return;
+
+  START (sinh);
+  TEST_f_f (sinh, 0, 0);
+  TEST_f_f (sinh, minus_zero, minus_zero);
+
+#ifndef TEST_INLINE
+  TEST_f_f (sinh, plus_infty, plus_infty);
+  TEST_f_f (sinh, minus_infty, minus_infty);
+#endif
+  TEST_f_f (sinh, nan_value, nan_value);
+
+  TEST_f_f (sinh, 0.75L, 0.822316731935829980703661634446913849L);
+  TEST_f_f (sinh, 0x8p-32L, 1.86264514923095703232705808926175479e-9L);
+
+  END (sinh);
+}
+
+static void
+sqrt_test (void)
+{
+  errno = 0;
+  FUNC(sqrt) (1);
+  if (errno == ENOSYS)
+    /* Function not implemented.  */
+    return;
+
+  START (sqrt);
+
+  TEST_f_f (sqrt, 0, 0);
+  TEST_f_f (sqrt, nan_value, nan_value);
+  TEST_f_f (sqrt, plus_infty, plus_infty);
+
+  TEST_f_f (sqrt, minus_zero, minus_zero);
+
+  /* sqrt (x) == NaN plus invalid exception for x < 0.  */
+  TEST_f_f (sqrt, -1, nan_value, INVALID_EXCEPTION);
+  TEST_f_f (sqrt, minus_infty, nan_value, INVALID_EXCEPTION);
+  TEST_f_f (sqrt, nan_value, nan_value);
+
+  TEST_f_f (sqrt, 2209, 47);
+  TEST_f_f (sqrt, 4, 2);
+  TEST_f_f (sqrt, 2, M_SQRT2l);
+  TEST_f_f (sqrt, 0.25, 0.5);
+  TEST_f_f (sqrt, 6642.25, 81.5);
+  TEST_f_f (sqrt, 15190.5625L, 123.25L);
+  TEST_f_f (sqrt, 0.75L, 0.866025403784438646763723170752936183L);
+
+  END (sqrt);
+}
+
+
+static void
+tan_test (void)
+{
+  errno = 0;
+  FUNC(tan) (0);
+  if (errno == ENOSYS)
+    /* Function not implemented.  */
+    return;
+
+  START (tan);
+
+  TEST_f_f (tan, 0, 0);
+  TEST_f_f (tan, minus_zero, minus_zero);
+  TEST_f_f (tan, plus_infty, nan_value, INVALID_EXCEPTION);
+  TEST_f_f (tan, minus_infty, nan_value, INVALID_EXCEPTION);
+  TEST_f_f (tan, nan_value, nan_value);
+
+  TEST_f_f (tan, M_PI_4l, 1);
+  TEST_f_f (tan, 0.75L, 0.931596459944072461165202756573936428L);
+
+  END (tan);
+}
+
+static void
+tanh_test (void)
+{
+  errno = 0;
+  FUNC(tanh) (0.7L);
+  if (errno == ENOSYS)
+    /* Function not implemented.  */
+    return;
+
+  START (tanh);
+
+  TEST_f_f (tanh, 0, 0);
+  /* vda: uclibc: added IGNORE_ZERO_INF_SIGN to treat -0 as ok */
+  TEST_f_f (tanh, minus_zero, minus_zero, IGNORE_ZERO_INF_SIGN);
+
+#ifndef TEST_INLINE
+  TEST_f_f (tanh, plus_infty, 1);
+  TEST_f_f (tanh, minus_infty, -1);
+#endif
+  TEST_f_f (tanh, nan_value, nan_value);
+
+  TEST_f_f (tanh, 0.75L, 0.635148952387287319214434357312496495L);
+  TEST_f_f (tanh, -0.75L, -0.635148952387287319214434357312496495L);
+
+  TEST_f_f (tanh, 1.0L, 0.7615941559557648881194582826047935904L);
+  TEST_f_f (tanh, -1.0L, -0.7615941559557648881194582826047935904L);
+
+  /* 2^-57  */
+  TEST_f_f (tanh, 0x1p-57L, 6.938893903907228377647697925567626953125e-18L);
+
+  END (tanh);
+}
+
+#if 0
+static void
+tgamma_test (void)
+{
+  errno = 0;
+  FUNC(tgamma) (1);
+  if (errno == ENOSYS)
+    /* Function not implemented.  */
+    return;
+  feclearexcept (FE_ALL_EXCEPT);
+
+  START (tgamma);
+
+  TEST_f_f (tgamma, plus_infty, plus_infty);
+  TEST_f_f (tgamma, 0, plus_infty, DIVIDE_BY_ZERO_EXCEPTION);
+  TEST_f_f (tgamma, minus_zero, minus_infty, DIVIDE_BY_ZERO_EXCEPTION);
+  /* tgamma (x) == NaN plus invalid exception for integer x <= 0.  */
+  TEST_f_f (tgamma, -2, nan_value, INVALID_EXCEPTION);
+  TEST_f_f (tgamma, minus_infty, nan_value, INVALID_EXCEPTION);
+  TEST_f_f (tgamma, nan_value, nan_value);
+
+  TEST_f_f (tgamma, 0.5, M_SQRT_PIl);
+  TEST_f_f (tgamma, -0.5, -M_2_SQRT_PIl);
+
+  TEST_f_f (tgamma, 1, 1);
+  TEST_f_f (tgamma, 4, 6);
+
+  TEST_f_f (tgamma, 0.7L, 1.29805533264755778568117117915281162L);
+  TEST_f_f (tgamma, 1.2L, 0.918168742399760610640951655185830401L);
+
+  END (tgamma);
+}
+#endif
+
+
+#if 0
+static void
+trunc_test (void)
+{
+  START (trunc);
+
+  TEST_f_f (trunc, plus_infty, plus_infty);
+  TEST_f_f (trunc, minus_infty, minus_infty);
+  TEST_f_f (trunc, nan_value, nan_value);
+
+  TEST_f_f (trunc, 0, 0);
+  TEST_f_f (trunc, minus_zero, minus_zero);
+  TEST_f_f (trunc, 0.625, 0);
+  TEST_f_f (trunc, -0.625, minus_zero);
+  TEST_f_f (trunc, 1, 1);
+  TEST_f_f (trunc, -1, -1);
+  TEST_f_f (trunc, 1.625, 1);
+  TEST_f_f (trunc, -1.625, -1);
+
+  TEST_f_f (trunc, 1048580.625L, 1048580L);
+  TEST_f_f (trunc, -1048580.625L, -1048580L);
+
+  TEST_f_f (trunc, 8388610.125L, 8388610.0L);
+  TEST_f_f (trunc, -8388610.125L, -8388610.0L);
+
+  TEST_f_f (trunc, 4294967296.625L, 4294967296.0L);
+  TEST_f_f (trunc, -4294967296.625L, -4294967296.0L);
+
+#ifdef TEST_LDOUBLE
+  /* The result can only be represented in long double.  */
+  TEST_f_f (trunc, 4503599627370495.5L, 4503599627370495.0L);
+  TEST_f_f (trunc, 4503599627370496.25L, 4503599627370496.0L);
+  TEST_f_f (trunc, 4503599627370496.5L, 4503599627370496.0L);
+  TEST_f_f (trunc, 4503599627370496.75L, 4503599627370496.0L);
+  TEST_f_f (trunc, 4503599627370497.5L, 4503599627370497.0L);
+
+  TEST_f_f (trunc, -4503599627370495.5L, -4503599627370495.0L);
+  TEST_f_f (trunc, -4503599627370496.25L, -4503599627370496.0L);
+  TEST_f_f (trunc, -4503599627370496.5L, -4503599627370496.0L);
+  TEST_f_f (trunc, -4503599627370496.75L, -4503599627370496.0L);
+  TEST_f_f (trunc, -4503599627370497.5L, -4503599627370497.0L);
+
+  TEST_f_f (trunc, 9007199254740991.5L, 9007199254740991.0L);
+  TEST_f_f (trunc, 9007199254740992.25L, 9007199254740992.0L);
+  TEST_f_f (trunc, 9007199254740992.5L, 9007199254740992.0L);
+  TEST_f_f (trunc, 9007199254740992.75L, 9007199254740992.0L);
+  TEST_f_f (trunc, 9007199254740993.5L, 9007199254740993.0L);
+
+  TEST_f_f (trunc, -9007199254740991.5L, -9007199254740991.0L);
+  TEST_f_f (trunc, -9007199254740992.25L, -9007199254740992.0L);
+  TEST_f_f (trunc, -9007199254740992.5L, -9007199254740992.0L);
+  TEST_f_f (trunc, -9007199254740992.75L, -9007199254740992.0L);
+  TEST_f_f (trunc, -9007199254740993.5L, -9007199254740993.0L);
+
+  TEST_f_f (trunc, 72057594037927935.5L, 72057594037927935.0L);
+  TEST_f_f (trunc, 72057594037927936.25L, 72057594037927936.0L);
+  TEST_f_f (trunc, 72057594037927936.5L, 72057594037927936.0L);
+  TEST_f_f (trunc, 72057594037927936.75L, 72057594037927936.0L);
+  TEST_f_f (trunc, 72057594037927937.5L, 72057594037927937.0L);
+
+  TEST_f_f (trunc, -72057594037927935.5L, -72057594037927935.0L);
+  TEST_f_f (trunc, -72057594037927936.25L, -72057594037927936.0L);
+  TEST_f_f (trunc, -72057594037927936.5L, -72057594037927936.0L);
+  TEST_f_f (trunc, -72057594037927936.75L, -72057594037927936.0L);
+  TEST_f_f (trunc, -72057594037927937.5L, -72057594037927937.0L);
+
+  TEST_f_f (trunc, 10141204801825835211973625643007.5L, 10141204801825835211973625643007.0L);
+  TEST_f_f (trunc, 10141204801825835211973625643008.25L, 10141204801825835211973625643008.0L);
+  TEST_f_f (trunc, 10141204801825835211973625643008.5L, 10141204801825835211973625643008.0L);
+  TEST_f_f (trunc, 10141204801825835211973625643008.75L, 10141204801825835211973625643008.0L);
+  TEST_f_f (trunc, 10141204801825835211973625643009.5L, 10141204801825835211973625643009.0L);
+#endif
+
+  END (trunc);
+}
+#endif
+
+#if defined __DO_XSI_MATH__
+static void
+y0_test (void)
+{
+  errno = 0;
+#if 0
+  FLOAT s, c;
+  FUNC (sincos) (0, &s, &c);
+  if (errno == ENOSYS)
+    /* Required function not implemented.  */
+    return;
+#endif
+  FUNC(y0) (1);
+  if (errno == ENOSYS)
+    /* Function not implemented.  */
+    return;
+
+  /* y0 is the Bessel function of the second kind of order 0 */
+  START (y0);
+
+  TEST_f_f (y0, -1.0, minus_infty, INVALID_EXCEPTION);
+  TEST_f_f (y0, 0.0, minus_infty);
+  TEST_f_f (y0, nan_value, nan_value);
+  TEST_f_f (y0, plus_infty, 0);
+
+  TEST_f_f (y0, 0.125L, -1.38968062514384052915582277745018693L);
+  TEST_f_f (y0, 0.75L, -0.137172769385772397522814379396581855L);
+  TEST_f_f (y0, 1.0, 0.0882569642156769579829267660235151628L);
+  TEST_f_f (y0, 1.5, 0.382448923797758843955068554978089862L);
+  TEST_f_f (y0, 2.0, 0.510375672649745119596606592727157873L);
+  TEST_f_f (y0, 8.0, 0.223521489387566220527323400498620359L);
+  TEST_f_f (y0, 10.0, 0.0556711672835993914244598774101900481L);
+
+  END (y0);
+}
+
+
+static void
+y1_test (void)
+{
+  errno = 0;
+#if 0
+  FLOAT s, c;
+  FUNC (sincos) (0, &s, &c);
+  if (errno == ENOSYS)
+    /* Required function not implemented.  */
+    return;
+#endif
+  FUNC(y1) (1);
+  if (errno == ENOSYS)
+    /* Function not implemented.  */
+    return;
+
+  /* y1 is the Bessel function of the second kind of order 1 */
+  START (y1);
+
+  TEST_f_f (y1, -1.0, minus_infty, INVALID_EXCEPTION);
+  TEST_f_f (y1, 0.0, minus_infty);
+  TEST_f_f (y1, plus_infty, 0);
+  TEST_f_f (y1, nan_value, nan_value);
+
+  TEST_f_f (y1, 0.125L, -5.19993611253477499595928744876579921L);
+  TEST_f_f (y1, 0.75L, -1.03759455076928541973767132140642198L);
+  TEST_f_f (y1, 1.0, -0.781212821300288716547150000047964821L);
+  TEST_f_f (y1, 1.5, -0.412308626973911295952829820633445323L);
+  TEST_f_f (y1, 2.0, -0.107032431540937546888370772277476637L);
+  TEST_f_f (y1, 8.0, -0.158060461731247494255555266187483550L);
+  TEST_f_f (y1, 10.0, 0.249015424206953883923283474663222803L);
+
+  END (y1);
+}
+
+
+static void
+yn_test (void)
+{
+  errno = 0;
+#if 0
+  FLOAT s, c;
+  FUNC (sincos) (0, &s, &c);
+  if (errno == ENOSYS)
+    /* Required function not implemented.  */
+    return;
+#endif
+  FUNC(yn) (1, 1);
+  if (errno == ENOSYS)
+    /* Function not implemented.  */
+    return;
+
+  /* yn is the Bessel function of the second kind of order n */
+  START (yn);
+
+  /* yn (0, x) == y0 (x)  */
+  TEST_ff_f (yn, 0, -1.0, minus_infty, INVALID_EXCEPTION);
+  TEST_ff_f (yn, 0, 0.0, minus_infty);
+  TEST_ff_f (yn, 0, nan_value, nan_value);
+  TEST_ff_f (yn, 0, plus_infty, 0);
+
+  TEST_ff_f (yn, 0, 0.125L, -1.38968062514384052915582277745018693L);
+  TEST_ff_f (yn, 0, 0.75L, -0.137172769385772397522814379396581855L);
+  TEST_ff_f (yn, 0, 1.0, 0.0882569642156769579829267660235151628L);
+  TEST_ff_f (yn, 0, 1.5, 0.382448923797758843955068554978089862L);
+  TEST_ff_f (yn, 0, 2.0, 0.510375672649745119596606592727157873L);
+  TEST_ff_f (yn, 0, 8.0, 0.223521489387566220527323400498620359L);
+  TEST_ff_f (yn, 0, 10.0, 0.0556711672835993914244598774101900481L);
+
+  /* yn (1, x) == y1 (x)  */
+  TEST_ff_f (yn, 1, -1.0, minus_infty, INVALID_EXCEPTION);
+  TEST_ff_f (yn, 1, 0.0, minus_infty);
+  TEST_ff_f (yn, 1, plus_infty, 0);
+  TEST_ff_f (yn, 1, nan_value, nan_value);
+
+  TEST_ff_f (yn, 1, 0.125L, -5.19993611253477499595928744876579921L);
+  TEST_ff_f (yn, 1, 0.75L, -1.03759455076928541973767132140642198L);
+  TEST_ff_f (yn, 1, 1.0, -0.781212821300288716547150000047964821L);
+  TEST_ff_f (yn, 1, 1.5, -0.412308626973911295952829820633445323L);
+  TEST_ff_f (yn, 1, 2.0, -0.107032431540937546888370772277476637L);
+  TEST_ff_f (yn, 1, 8.0, -0.158060461731247494255555266187483550L);
+  TEST_ff_f (yn, 1, 10.0, 0.249015424206953883923283474663222803L);
+
+  /* yn (3, x)  */
+  TEST_ff_f (yn, 3, plus_infty, 0);
+  TEST_ff_f (yn, 3, nan_value, nan_value);
+
+  TEST_ff_f (yn, 3, 0.125L, -2612.69757350066712600220955744091741L);
+  TEST_ff_f (yn, 3, 0.75L, -12.9877176234475433186319774484809207L);
+  TEST_ff_f (yn, 3, 1.0, -5.82151760596472884776175706442981440L);
+  TEST_ff_f (yn, 3, 2.0, -1.12778377684042778608158395773179238L);
+  TEST_ff_f (yn, 3, 10.0, -0.251362657183837329779204747654240998L);
+
+  /* yn (10, x)  */
+  TEST_ff_f (yn, 10, plus_infty, 0);
+  TEST_ff_f (yn, 10, nan_value, nan_value);
+
+  TEST_ff_f (yn, 10, 0.125L, -127057845771019398.252538486899753195L);
+  TEST_ff_f (yn, 10, 0.75L, -2133501638.90573424452445412893839236L);
+  TEST_ff_f (yn, 10, 1.0, -121618014.278689189288130426667971145L);
+  TEST_ff_f (yn, 10, 2.0, -129184.542208039282635913145923304214L);
+  TEST_ff_f (yn, 10, 10.0, -0.359814152183402722051986577343560609L);
+
+  END (yn);
+
+}
+#endif /* __DO_XSI_MATH__ */
+
+
+static void
+significand_test (void)
+{
+  /* significand returns the mantissa of the exponential representation.  */
+  START (significand);
+
+  TEST_f_f (significand, 4.0, 1.0);
+  TEST_f_f (significand, 6.0, 1.5);
+  TEST_f_f (significand, 8.0, 1.0);
+
+  END (significand);
+}
+
+
+static void
+initialize (void)
+{
+  fpstack_test ("start *init*");
+  plus_zero = 0.0;
+  nan_value = plus_zero / plus_zero;	/* Suppress GCC warning */
+
+  minus_zero = FUNC(copysign) (0.0, -1.0);
+  plus_infty = CHOOSE (HUGE_VALL, HUGE_VAL, HUGE_VALF,
+		       HUGE_VALL, HUGE_VAL, HUGE_VALF);
+  minus_infty = CHOOSE (-HUGE_VALL, -HUGE_VAL, -HUGE_VALF,
+			-HUGE_VALL, -HUGE_VAL, -HUGE_VALF);
+  max_value = CHOOSE (LDBL_MAX, DBL_MAX, FLT_MAX,
+		      LDBL_MAX, DBL_MAX, FLT_MAX);
+  min_value = CHOOSE (LDBL_MIN, DBL_MIN, FLT_MIN,
+		      LDBL_MIN, DBL_MIN, FLT_MIN);
+
+  (void) &plus_zero;
+  (void) &nan_value;
+  (void) &minus_zero;
+  (void) &plus_infty;
+  (void) &minus_infty;
+  (void) &max_value;
+  (void) &min_value;
+
+  /* Clear all exceptions.  From now on we must not get random exceptions.  */
+  feclearexcept (FE_ALL_EXCEPT);
+
+  /* Test to make sure we start correctly.  */
+  fpstack_test ("end *init*");
+}
+
+#if 0
+/* function to check our ulp calculation.  */
+void
+check_ulp (void)
+{
+  int i;
+
+  FLOAT u, diff, ulp;
+  /* This gives one ulp.  */
+  u = FUNC(nextafter) (10, 20);
+  check_equal (10.0, u, 1, &diff, &ulp);
+  printf ("One ulp: % .4" PRINTF_NEXPR "\n", ulp);
+
+  /* This gives one more ulp.  */
+  u = FUNC(nextafter) (u, 20);
+  check_equal (10.0, u, 2, &diff, &ulp);
+  printf ("two ulp: % .4" PRINTF_NEXPR "\n", ulp);
+
+  /* And now calculate 100 ulp.  */
+  for (i = 2; i < 100; i++)
+    u = FUNC(nextafter) (u, 20);
+  check_equal (10.0, u, 100, &diff, &ulp);
+  printf ("100 ulp: % .4" PRINTF_NEXPR "\n", ulp);
+}
+#endif
+
+int
+main (int argc, char **argv)
+{
+
+  int key;
+
+  verbose = 1;
+  output_ulps = 0;
+  output_max_error = 1;
+  output_points = 1;
+  /* XXX set to 0 for releases.  */
+  ignore_max_ulp = 0;
+
+  /* Parse and process arguments.  */
+  while ((key = getopt(argc, argv, "fi:puv")) > 0) {
+      switch (key)
+      {
+	  case 'f':
+	      output_max_error = 0;
+	      break;
+	  case 'i':
+	      if (strcmp (optarg, "yes") == 0)
+		  ignore_max_ulp = 1;
+	      else if (strcmp (optarg, "no") == 0)
+		  ignore_max_ulp = 0;
+	      break;
+	  case 'p':
+	      output_points = 0;
+	      break;
+	  case 'u':
+	      output_ulps = 1;
+	      break;
+	  case 'v':
+	      verbose = 3;
+	      break;
+	  default:
+	      fprintf (stderr, "Unknown argument: %c", key);
+	      exit (EXIT_FAILURE);
+      }
+  }
+
+  if (optind != argc)
+    {
+      fprintf (stderr, "wrong number of arguments");
+      exit (EXIT_FAILURE);
+    }
+
+  if (output_ulps)
+    {
+      ulps_file = fopen ("ULPs", "a");
+      if (ulps_file == NULL)
+	{
+	  perror ("can't open file `ULPs' for writing: ");
+	  exit (1);
+	}
+    }
+
+
+  initialize ();
+  printf (TEST_MSG);
+
+#if 0
+  check_ulp ();
+#endif
+
+  /* Keep the tests a wee bit ordered (according to ISO C99).  */
+  /* Classification macros:  */
+  fpclassify_test ();
+  isfinite_test ();
+  isnormal_test ();
+  signbit_test ();
+
+  /* Trigonometric functions:  */
+  acos_test ();
+  asin_test ();
+  atan_test ();
+  atan2_test ();
+  cos_test ();
+  sin_test ();
+#if 0
+  sincos_test ();
+#endif
+  tan_test ();
+
+  /* Hyperbolic functions:  */
+  acosh_test ();
+  asinh_test ();
+  atanh_test ();
+  cosh_test ();
+  sinh_test ();
+  tanh_test ();
+
+  /* Exponential and logarithmic functions:  */
+  exp_test ();
+#if 0
+  exp10_test ();
+  exp2_test ();
+#endif
+  expm1_test ();
+  frexp_test ();
+  ldexp_test ();
+  log_test ();
+  log10_test ();
+  log1p_test ();
+#if 0
+  log2_test ();
+#endif
+  logb_test ();
+  modf_test ();
+  ilogb_test ();
+  scalb_test ();
+  scalbn_test ();
+#if 0
+  scalbln_test ();
+#endif
+  significand_test ();
+
+  /* Power and absolute value functions:  */
+  cbrt_test ();
+  fabs_test ();
+  hypot_test ();
+  pow_test ();
+  sqrt_test ();
+
+  /* Error and gamma functions:  */
+  erf_test ();
+  erfc_test ();
+  gamma_test ();
+  lgamma_test ();
+#if 0
+  tgamma_test ();
+#endif
+
+  /* Nearest integer functions:  */
+  ceil_test ();
+  floor_test ();
+#if 0
+  nearbyint_test ();
+#endif
+  rint_test ();
+#if 0
+  rint_test_tonearest ();
+  rint_test_towardzero ();
+  rint_test_downward ();
+  rint_test_upward ();
+  lrint_test ();
+  llrint_test ();
+  round_test ();
+  lround_test ();
+  llround_test ();
+  trunc_test ();
+#endif
+
+  /* Remainder functions:  */
+  fmod_test ();
+  remainder_test ();
+#if 0
+  remquo_test ();
+#endif
+
+  /* Manipulation functions:  */
+  copysign_test ();
+#if 0
+  nextafter_test ();
+  nexttoward_test ();
+
+  /* maximum, minimum and positive difference functions */
+  fdim_test ();
+  fmax_test ();
+  fmin_test ();
+
+  /* Multiply and add:  */
+  fma_test ();
+
+  /* Complex functions:  */
+  cabs_test ();
+  cacos_test ();
+  cacosh_test ();
+  carg_test ();
+  casin_test ();
+  casinh_test ();
+  catan_test ();
+  catanh_test ();
+  ccos_test ();
+  ccosh_test ();
+  cexp_test ();
+  cimag_test ();
+  clog10_test ();
+  clog_test ();
+#if 0
+  conj_test ();
+#endif
+  cpow_test ();
+  cproj_test ();
+  creal_test ();
+  csin_test ();
+  csinh_test ();
+  csqrt_test ();
+  ctan_test ();
+  ctanh_test ();
+#endif
+
+  /* Bessel functions:  */
+#if defined __DO_XSI_MATH__
+  j0_test ();
+  j1_test ();
+  jn_test ();
+  y0_test ();
+  y1_test ();
+  yn_test ();
+#endif /* __DO_XSI_MATH__ */
+
+  if (output_ulps)
+    fclose (ulps_file);
+
+  printf ("\nTest suite completed:\n");
+  printf ("  %d test cases plus %d tests for exception flags executed.\n",
+	  noTests, noExcTests);
+  if (noXFails)
+    printf ("  %d expected failures occurred.\n", noXFails);
+  if (noXPasses)
+    printf ("  %d unexpected passes occurred.\n", noXPasses);
+  if (noErrors)
+    {
+      printf ("  %d errors occurred.\n", noErrors);
+      return 1;
+    }
+  printf ("  All tests passed successfully.\n");
+
+  return 0;
+}
+
+/*
+ * Local Variables:
+ * mode:c
+ * End:
+ */
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/math/rint.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/math/rint.c
new file mode 100644
index 00000000..b595459a
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/math/rint.c
@@ -0,0 +1,33 @@
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define check_d1(func, param, expected) \
+do { \
+	int err; hex_union ur; hex_union up; \
+	double result = func(param); up.f = param; ur.f = result; \
+	errors += (err = (result != (expected))); \
+	err \
+	? printf("FAIL: %s(%g/"HEXFMT")=%g/"HEXFMT" (expected %g)\n", \
+		#func, (double)(param), (long long)up.hex, result, (long long)ur.hex, (double)(expected)) \
+	: printf("PASS: %s(%g)=%g\n", #func, (double)(param), result); \
+} while (0)
+
+#define HEXFMT "%08llx"
+typedef union {
+	double f;
+	uint64_t hex;
+} hex_union;
+double result;
+
+int errors = 0;
+
+int main(void)
+{
+	check_d1(rint, 0.6, 1.0);
+
+	printf("Errors: %d\n", errors);
+	return errors;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/math/signgam.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/math/signgam.c
new file mode 100644
index 00000000..2f1adbaa
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/math/signgam.c
@@ -0,0 +1,28 @@
+#define _XOPEN_SOURCE 600
+#include 
+#include 
+#include 
+
+double zero = 0.0;
+double mzero;
+
+int main(void)
+{
+	double d;
+	int errors = 0;
+
+	mzero = copysign(zero, -1.0);
+
+	d = lgamma(zero);
+	printf("%g %d\n", d, signgam);
+	errors += !(d == HUGE_VAL);
+	errors += !(signgam == 1);
+
+	d = lgamma(mzero);
+	printf("%g %d\n", d, signgam);
+	errors += !(d == HUGE_VAL);
+	errors += !(signgam == -1);
+
+	printf("Errors: %d\n", errors);
+	return errors;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/math/test-double.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/math/test-double.c
new file mode 100644
index 00000000..4d239a71
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/math/test-double.c
@@ -0,0 +1,34 @@
+/* Copyright (C) 1997, 1999 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Andreas Jaeger , 1997.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#define FUNC(function) function
+#define FLOAT double
+#define TEST_MSG "testing double (without inline functions)\n"
+#define MATHCONST(x) x
+#define CHOOSE(Clongdouble,Cdouble,Cfloat,Cinlinelongdouble,Cinlinedouble,Cinlinefloat) Cdouble
+#define PRINTF_EXPR "e"
+#define PRINTF_XEXPR "a"
+#define PRINTF_NEXPR "f"
+#define TEST_DOUBLE 1
+
+#ifndef __NO_MATH_INLINES
+# define __NO_MATH_INLINES
+#endif
+
+#include "libm-test.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/math/test-float.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/math/test-float.c
new file mode 100644
index 00000000..26a4213b
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/math/test-float.c
@@ -0,0 +1,34 @@
+/* Copyright (C) 1997, 1999 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Andreas Jaeger , 1997.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#define FUNC(function) function ## f
+#define FLOAT float
+#define TEST_MSG "testing float (without inline functions)\n"
+#define MATHCONST(x) x
+#define CHOOSE(Clongdouble,Cdouble,Cfloat,Cinlinelongdouble,Cinlinedouble,Cinlinefloat) Cfloat
+#define PRINTF_EXPR "e"
+#define PRINTF_XEXPR "a"
+#define PRINTF_NEXPR "f"
+#define TEST_FLOAT 1
+
+#ifndef __NO_MATH_INLINES
+# define __NO_MATH_INLINES
+#endif
+
+#include "libm-test.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/math/test-fpucw.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/math/test-fpucw.c
new file mode 100644
index 00000000..6d638c66
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/math/test-fpucw.c
@@ -0,0 +1,43 @@
+/* Copyright (C) 2000 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Andreas Jaeger , 2000.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+
+int
+main (void)
+{
+#ifdef _FPU_GETCW
+/* Some architectures don't have _FPU_GETCW (e.g. Linux/Alpha).  */
+  fpu_control_t cw;
+
+  _FPU_GETCW (cw);
+
+  cw &= ~_FPU_RESERVED;
+
+  if (cw != (_FPU_DEFAULT & ~_FPU_RESERVED))
+    printf ("control word is 0x%lx but should be 0x%lx.\n",
+	    (long int) cw, (long int) (_FPU_DEFAULT & ~_FPU_RESERVED));
+
+  return cw != (_FPU_DEFAULT & ~_FPU_RESERVED);
+
+#else
+  return 0;
+#endif
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/math/test-idouble.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/math/test-idouble.c
new file mode 100644
index 00000000..7606a89f
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/math/test-idouble.c
@@ -0,0 +1,35 @@
+/* Copyright (C) 1997, 1999 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Andreas Jaeger , 1997.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#define FUNC(function) function
+#define FLOAT double
+#define TEST_MSG "testing double (inline functions)\n"
+#define MATHCONST(x) x
+#define CHOOSE(Clongdouble,Cdouble,Cfloat,Cinlinelongdouble,Cinlinedouble,Cinlinefloat) Cinlinedouble
+#define PRINTF_EXPR "e"
+#define PRINTF_XEXPR "a"
+#define PRINTF_NEXPR "f"
+#define TEST_DOUBLE 1
+#define TEST_INLINE
+
+#ifdef __NO_MATH_INLINES
+# undef __NO_MATH_INLINES
+#endif
+
+#include "libm-test.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/math/test-ifloat.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/math/test-ifloat.c
new file mode 100644
index 00000000..9eb9ce50
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/math/test-ifloat.c
@@ -0,0 +1,35 @@
+/* Copyright (C) 1997, 1999 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Andreas Jaeger , 1997.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#define FUNC(function) function ## f
+#define FLOAT float
+#define TEST_MSG "testing float (inline functions)\n"
+#define MATHCONST(x) x
+#define CHOOSE(Clongdouble,Cdouble,Cfloat,Cinlinelongdouble,Cinlinedouble,Cinlinefloat) Cinlinefloat
+#define PRINTF_EXPR "e"
+#define PRINTF_XEXPR "a"
+#define PRINTF_NEXPR "f"
+#define TEST_FLOAT 1
+#define TEST_INLINE 1
+
+#ifdef __NO_MATH_INLINES
+# undef __NO_MATH_INLINES
+#endif
+
+#include "libm-test.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/math/test-ildoubl.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/math/test-ildoubl.c
new file mode 100644
index 00000000..597edbca
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/math/test-ildoubl.c
@@ -0,0 +1,35 @@
+/* Copyright (C) 1997, 1999, 2001 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Andreas Jaeger , 1997.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#define FUNC(function) function##l
+#define FLOAT long double
+#define TEST_MSG "testing long double (inline functions)\n"
+#define MATHCONST(x) x##L
+#define CHOOSE(Clongdouble,Cdouble,Cfloat,Cinlinelongdouble,Cinlinedouble,Cinlinefloat) Cinlinelongdouble
+#define PRINTF_EXPR "Le"
+#define PRINTF_XEXPR "La"
+#define PRINTF_NEXPR "Lf"
+#define TEST_INLINE
+#define TEST_LDOUBLE 1
+
+#ifdef __NO_MATH_INLINES
+# undef __NO_MATH_INLINES
+#endif
+
+#include "libm-test.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/math/test-ldouble.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/math/test-ldouble.c
new file mode 100644
index 00000000..27212276
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/math/test-ldouble.c
@@ -0,0 +1,34 @@
+/* Copyright (C) 1997, 1999, 2001 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Andreas Jaeger , 1997.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#define FUNC(function) function##l
+#define FLOAT long double
+#define TEST_MSG "testing long double (without inline functions)\n"
+#define MATHCONST(x) x##L
+#define CHOOSE(Clongdouble,Cdouble,Cfloat,Cinlinelongdouble,Cinlinedouble,Cinlinefloat) Clongdouble
+#define PRINTF_EXPR "Le"
+#define PRINTF_XEXPR "La"
+#define PRINTF_NEXPR "Lf"
+#define TEST_LDOUBLE 1
+
+#ifndef __NO_MATH_INLINES
+# define __NO_MATH_INLINES
+#endif
+
+#include "libm-test.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/math/tst-definitions.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/math/tst-definitions.c
new file mode 100644
index 00000000..7d352af4
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/math/tst-definitions.c
@@ -0,0 +1,47 @@
+/* Copyright (C) 2000 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2000.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+
+
+int
+main (void)
+{
+  int result = 0;
+
+  if (FP_ILOGB0 != INT_MIN && FP_ILOGB0 != -INT_MAX)
+    {
+      puts ("FP_ILOGB0 has no valid value");
+      result = 1;
+    }
+  else
+    puts ("FP_ILOGB0 value is OK");
+
+  if (FP_ILOGBNAN != INT_MIN && FP_ILOGBNAN != INT_MAX)
+    {
+      puts ("FP_ILOBNAN has no valid value");
+      result = 1;
+    }
+  else
+    puts ("FP_ILOGBNAN value is OK");
+
+  return result;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/misc/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/test/misc/Makefile
new file mode 100644
index 00000000..52f6c679
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/misc/Makefile
@@ -0,0 +1,7 @@
+# uClibc misc tests
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+
+top_builddir=../../
+include ../Rules.mak
+-include Makefile.in
+include ../Test.mak
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/misc/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/test/misc/Makefile.in
new file mode 100644
index 00000000..22632113
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/misc/Makefile.in
@@ -0,0 +1,14 @@
+# uClibc misc tests
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+
+TESTS_DISABLED := outb tst-fnmatch bug-glob1 tst-gnuglob
+ifeq  ($(UCLIBC_HAS_LFS),)
+TESTS_DISABLED += dirent64
+endif
+CFLAGS_dirent64 := -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64
+
+DODIFF_dirent    := 1
+DODIFF_dirent64  := 1
+
+OPTS_bug-glob1   := $(PWD)
+OPTS_tst-fnmatch := < tst-fnmatch.input
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/misc/bug-glob1.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/misc/bug-glob1.c
new file mode 100644
index 00000000..aec84ad4
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/misc/bug-glob1.c
@@ -0,0 +1,94 @@
+/* Test case for globbing dangling symlink.  By Ulrich Drepper.  */
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+static void prepare (int argc, char *argv[]);
+#define PREPARE prepare
+static int do_test (void);
+#define TEST_FUNCTION do_test ()
+
+#include "../test-skeleton.c"
+
+
+static char *fname;
+
+static void
+prepare (int argc, char *argv[])
+{
+  if (argc < 2)
+    error (EXIT_FAILURE, 0, "missing argument");
+
+  size_t len = strlen (argv[1]);
+  static const char ext[] = "globXXXXXX";
+  fname = malloc (len + sizeof (ext));
+  if (fname == NULL)
+    error (EXIT_FAILURE, errno, "cannot create temp file");
+ again:
+  strcpy (stpcpy (fname, argv[1]), ext);
+
+/*
+  fname = mktemp (fname);
+*/
+  close(mkstemp(fname));
+  unlink(fname);
+
+  if (fname == NULL || *fname == '\0')
+    error (EXIT_FAILURE, errno, "cannot create temp file name");
+  if (symlink ("bug-glob1-does-not-exist", fname) != 0)
+    {
+      if (errno == EEXIST)
+	goto again;
+
+      error (EXIT_FAILURE, errno, "cannot create symlink");
+    }
+  add_temp_file (fname);
+}
+
+
+static int
+do_test (void)
+{
+  glob_t gl;
+  int retval = 0;
+  int e;
+
+  e = glob (fname, 0, NULL, &gl);
+  if (e == 0)
+    {
+      printf ("glob(\"%s\") succeeded when it should not have\n", fname);
+      retval = 1;
+    }
+  globfree (&gl);
+
+  size_t fnamelen = strlen (fname);
+  char buf[fnamelen + 2];
+
+  strcpy (buf, fname);
+  buf[fnamelen - 1] = '?';
+  e = glob (buf, 0, NULL, &gl);
+  if (e == 0)
+    {
+      printf ("glob(\"%s\") succeeded when it should not have\n", buf);
+      retval = 1;
+    }
+  globfree (&gl);
+
+  strcpy (buf, fname);
+  buf[fnamelen] = '*';
+  buf[fnamelen + 1] = '\0';
+  e = glob (buf, 0, NULL, &gl);
+  if (e == 0)
+    {
+      printf ("glob(\"%s\") succeeded when it should not have\n", buf);
+      retval = 1;
+    }
+  globfree (&gl);
+
+  return retval;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/misc/bug-glob2.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/misc/bug-glob2.c
new file mode 100644
index 00000000..f8b030e2
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/misc/bug-glob2.c
@@ -0,0 +1,302 @@
+/* Test glob memory management.
+   for the filesystem access functions.
+   Copyright (C) 2001, 2002, 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+// #define DEBUG
+#ifdef DEBUG
+# define PRINTF(fmt, args...) \
+  do					\
+    {					\
+      int save_errno = errno;		\
+      printf (fmt, ##args);		\
+      errno = save_errno;		\
+    } while (0)
+#else
+# define PRINTF(fmt, args...)
+#endif
+
+
+#ifdef GLOB_ALTDIRFUNC
+static struct
+{
+  const char *name;
+  int level;
+  int type;
+  mode_t mode;
+} filesystem[] =
+{
+  { ".", 1, DT_DIR, 0755 },
+  { "..", 1, DT_DIR, 0755 },
+  { "dir", 1, DT_DIR, 0755 },
+    { ".", 2, DT_DIR, 0755 },
+    { "..", 2, DT_DIR, 0755 },
+    { "readable", 2, DT_DIR, 0755 },
+      { ".", 3, DT_DIR, 0755 },
+      { "..", 3, DT_DIR, 0755 },
+      { "a", 3, DT_REG, 0644 },
+    { "unreadable", 2, DT_DIR, 0111 },
+      { ".", 3, DT_DIR, 0111 },
+      { "..", 3, DT_DIR, 0755 },
+      { "a", 3, DT_REG, 0644 },
+    { "zz-readable", 2, DT_DIR, 0755 },
+      { ".", 3, DT_DIR, 0755 },
+      { "..", 3, DT_DIR, 0755 },
+      { "a", 3, DT_REG, 0644 }
+};
+#define nfiles (sizeof (filesystem) / sizeof (filesystem[0]))
+
+
+typedef struct
+{
+  int level;
+  int idx;
+  struct dirent d;
+  char room_for_dirent[NAME_MAX];
+} my_DIR;
+
+
+static long int
+find_file (const char *s)
+{
+  int level = 1;
+  long int idx = 0;
+
+  if (strcmp (s, ".") == 0)
+    return 0;
+
+  if (s[0] == '.' && s[1] == '/')
+    s += 2;
+
+  while (*s != '\0')
+    {
+      char *endp = strchrnul (s, '/');
+
+      PRINTF ("looking for %.*s, level %d\n", (int) (endp - s), s, level);
+
+      while (idx < nfiles && filesystem[idx].level >= level)
+	{
+	  if (filesystem[idx].level == level
+	      && memcmp (s, filesystem[idx].name, endp - s) == 0
+	      && filesystem[idx].name[endp - s] == '\0')
+	    break;
+	  ++idx;
+	}
+
+      if (idx == nfiles || filesystem[idx].level < level)
+	{
+	  errno = ENOENT;
+	  return -1;
+	}
+
+      if (*endp == '\0')
+	return idx + 1;
+
+      if (filesystem[idx].type != DT_DIR
+	  && (idx + 1 >= nfiles
+	      || filesystem[idx].level >= filesystem[idx + 1].level))
+	{
+	  errno = ENOTDIR;
+	  return -1;
+	}
+
+      ++idx;
+
+      s = endp + 1;
+      ++level;
+    }
+
+  errno = ENOENT;
+  return -1;
+}
+
+
+static void *
+my_opendir (const char *s)
+{
+  long int idx = find_file (s);
+  my_DIR *dir;
+
+  if (idx == -1)
+    {
+      PRINTF ("my_opendir(\"%s\") == NULL (%m)\n", s);
+      return NULL;
+    }
+
+  if ((filesystem[idx].mode & 0400) == 0)
+    {
+      errno = EACCES;
+      PRINTF ("my_opendir(\"%s\") == NULL (%m)\n", s);
+      return NULL;
+    }
+
+  dir = (my_DIR *) malloc (sizeof (my_DIR));
+  if (dir == NULL)
+    {
+      printf ("cannot allocate directory handle: %m\n");
+      exit (EXIT_FAILURE);
+    }
+
+  dir->level = filesystem[idx].level;
+  dir->idx = idx;
+
+  PRINTF ("my_opendir(\"%s\") == { level: %d, idx: %ld }\n",
+	  s, filesystem[idx].level, idx);
+
+  return dir;
+}
+
+
+static struct dirent *
+my_readdir (void *gdir)
+{
+  my_DIR *dir = gdir;
+
+  if (dir->idx == -1)
+    {
+      PRINTF ("my_readdir ({ level: %d, idx: %ld }) = NULL\n",
+	      dir->level, (long int) dir->idx);
+      return NULL;
+    }
+
+  while (dir->idx < nfiles && filesystem[dir->idx].level > dir->level)
+    ++dir->idx;
+
+  if (dir->idx == nfiles || filesystem[dir->idx].level < dir->level)
+    {
+      dir->idx = -1;
+      PRINTF ("my_readdir ({ level: %d, idx: %ld }) = NULL\n",
+	      dir->level, (long int) dir->idx);
+      return NULL;
+    }
+
+  dir->d.d_ino = dir->idx;
+
+#ifdef _DIRENT_HAVE_D_TYPE
+  dir->d.d_type = filesystem[dir->idx].type;
+#endif
+
+  strcpy (dir->d.d_name, filesystem[dir->idx].name);
+
+#ifdef _DIRENT_HAVE_D_TYPE
+  PRINTF ("my_readdir ({ level: %d, idx: %ld }) = { d_ino: %ld, d_type: %d, d_name: \"%s\" }\n",
+	  dir->level, (long int) dir->idx, dir->d.d_ino, dir->d.d_type,
+	  dir->d.d_name);
+#else
+  PRINTF ("my_readdir ({ level: %d, idx: %ld }) = { d_ino: %ld, d_name: \"%s\" }\n",
+	  dir->level, (long int) dir->idx, dir->d.d_ino,
+	  dir->d.d_name);
+#endif
+
+  ++dir->idx;
+
+  return &dir->d;
+}
+
+
+static void
+my_closedir (void *dir)
+{
+  PRINTF ("my_closedir ()\n");
+  free (dir);
+}
+
+
+/* We use this function for lstat as well since we don't have any.  */
+static int
+my_stat (const char *name, struct stat *st)
+{
+  long int idx = find_file (name);
+
+  if (idx == -1)
+    {
+      PRINTF ("my_stat (\"%s\", ...) = -1 (%m)\n", name);
+      return -1;
+    }
+
+  memset (st, '\0', sizeof (*st));
+
+  if (filesystem[idx].type == DT_UNKNOWN)
+    st->st_mode = DTTOIF (idx + 1 < nfiles
+			  && filesystem[idx].level < filesystem[idx + 1].level
+			  ? DT_DIR : DT_REG) | filesystem[idx].mode;
+  else
+    st->st_mode = DTTOIF (filesystem[idx].type) | filesystem[idx].mode;
+
+  PRINTF ("my_stat (\"%s\", { st_mode: %o }) = 0\n", name, st->st_mode);
+
+  return 0;
+}
+
+
+static void
+init_glob_altdirfuncs (glob_t *pglob)
+{
+  pglob->gl_closedir = my_closedir;
+  pglob->gl_readdir = my_readdir;
+  pglob->gl_opendir = my_opendir;
+  pglob->gl_lstat = my_stat;
+  pglob->gl_stat = my_stat;
+}
+
+
+static int
+do_test (void)
+{
+  glob_t gl;
+  memset (&gl, 0, sizeof (gl));
+  init_glob_altdirfuncs (&gl);
+
+  if (glob ("dir/*able/*", GLOB_ERR | GLOB_ALTDIRFUNC, NULL, &gl)
+      != GLOB_ABORTED)
+    {
+      puts ("glob did not fail with GLOB_ABORTED");
+      exit (EXIT_FAILURE);
+    }
+
+  globfree (&gl);
+
+  memset (&gl, 0, sizeof (gl));
+  init_glob_altdirfuncs (&gl);
+
+  gl.gl_offs = 3;
+  if (glob ("dir2/*", GLOB_DOOFFS, NULL, &gl) != GLOB_NOMATCH)
+    {
+      puts ("glob did not fail with GLOB_NOMATCH");
+      exit (EXIT_FAILURE);
+    }
+
+  globfree (&gl);
+
+  return 0;
+}
+#else
+static int do_test (void) { return 0; }
+#endif
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/misc/bug-readdir1.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/misc/bug-readdir1.c
new file mode 100644
index 00000000..a8594a82
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/misc/bug-readdir1.c
@@ -0,0 +1,37 @@
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+int
+main (void)
+{
+  DIR *dirp;
+  struct dirent* ent;
+
+  /* open a dir stream */
+  dirp = opendir ("/tmp");
+  if (dirp == NULL)
+    {
+      if (errno == ENOENT)
+	exit (0);
+
+      perror ("opendir");
+      exit (1);
+    }
+
+  /* close the directory file descriptor, making it invalid */
+  if (close (dirfd (dirp)) != 0)
+    {
+      puts ("could not close directory file descriptor");
+      /* This is not an error.  It is not guaranteed this is possible.  */
+      return 0;
+    }
+
+  ent = readdir (dirp);
+
+  return ent != NULL || errno != EBADF;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/misc/dirent.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/misc/dirent.c
new file mode 100644
index 00000000..491e3cf7
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/misc/dirent.c
@@ -0,0 +1,39 @@
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define _DTIFY(DT) [DT] #DT
+const char * const types[] = {
+	_DTIFY(DT_UNKNOWN),
+	_DTIFY(DT_FIFO),
+	_DTIFY(DT_CHR),
+	_DTIFY(DT_DIR),
+	_DTIFY(DT_BLK),
+	_DTIFY(DT_REG),
+	_DTIFY(DT_LNK),
+	_DTIFY(DT_SOCK),
+	_DTIFY(DT_WHT)
+};
+
+int main(int argc, char *argv[])
+{
+	DIR *dirh;
+	struct dirent *de;
+	const char *mydir = (argc == 1 ? "/" : argv[1]);
+
+	if ((dirh = opendir(mydir)) == NULL) {
+		perror("opendir");
+		return 1;
+	}
+
+	printf("readdir() says:\n");
+	while ((de = readdir(dirh)) != NULL)
+		printf("\tdir entry %s: %s\n", types[de->d_type], de->d_name);
+
+	closedir(dirh);
+
+	return 0;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/misc/dirent64.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/misc/dirent64.c
new file mode 100644
index 00000000..26455ab6
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/misc/dirent64.c
@@ -0,0 +1 @@
+#include "dirent.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/misc/fdopen.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/misc/fdopen.c
new file mode 100644
index 00000000..f64cfb6b
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/misc/fdopen.c
@@ -0,0 +1,52 @@
+/* Test for fdopen bugs.  */
+
+#include 
+#include 
+#include 
+#include 
+
+#define assert(x) \
+  if (!(x)) \
+    { \
+      fputs ("test failed: " #x "\n", stderr); \
+      retval = 1; \
+      goto the_end; \
+    }
+
+int
+main (int argc, char *argv[])
+{
+  char name[256];
+  FILE *fp = NULL;
+  int retval = 0;
+  int fd;
+
+  /* hack to get a tempfile name w/out using tmpname()
+   * as that func causes a link time warning */
+  sprintf(name, "%s-uClibc-test.XXXXXX", __FILE__);
+  fd = mkstemp(name);
+  close(fd);
+
+  fp = fopen (name, "w");
+  assert (fp != NULL)
+  assert (fputs ("foobar and baz", fp) > 0);
+  assert (fclose (fp) == 0);
+  fp = NULL;
+
+  fd = open (name, O_RDWR|O_CREAT);
+  assert (fd != -1);
+  assert (lseek (fd, 5, SEEK_SET) == 5);
+
+  fp = fdopen (fd, "a");
+  assert (fp != NULL);
+  /* SuSv3 says that doing a fdopen() does not reset the file position,
+   * thus the '5' here is correct, not '14'. */
+  assert (ftell (fp) == 5);
+
+the_end:
+  if (fp != NULL)
+    assert (fclose (fp) == 0);
+  unlink (name);
+
+  return retval;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/misc/opendir-tst1.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/misc/opendir-tst1.c
new file mode 100644
index 00000000..302158d0
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/misc/opendir-tst1.c
@@ -0,0 +1,95 @@
+/* Copyright (C) 1998, 2000 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 1998.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/* Name of the FIFO.  */
+char tmpname[] = "fifoXXXXXX";
+
+
+/* Do the real work.  */
+static int
+real_test (void)
+{
+  DIR *dirp;
+
+  /* This should not block for an FIFO.  */
+  dirp = opendir (tmpname);
+
+  /* Successful.  */
+  if (dirp != NULL)
+    {
+      /* Oh, oh, how can this work?  */
+      fputs ("`opendir' succeeded on a FIFO???\n", stdout);
+      closedir (dirp);
+      return 1;
+    }
+
+  if (errno != ENOTDIR)
+    {
+      fprintf (stdout, "`opendir' return error `%s' instead of `%s'\n",
+	       strerror (errno), strerror (ENOTDIR));
+      return 1;
+    }
+
+  return 0;
+}
+
+
+static int
+do_test (int argc, char *argv[])
+{
+  int retval;
+
+  retval = mkstemp(tmpname);
+  close(retval);
+  unlink(tmpname);
+
+  /* Try to generate a FIFO.  */
+  if (mknod (tmpname, 0600 | S_IFIFO, 0) < 0)
+    {
+      perror ("mknod");
+      /* We cannot make this an error.  */
+      return 0;
+    }
+
+  retval = real_test ();
+
+  remove (tmpname);
+
+  return retval;
+}
+
+
+static void
+do_cleanup (void)
+{
+  remove (tmpname);
+}
+#define CLEANUP_HANDLER do_cleanup ()
+
+
+/* Include the test skeleton.  */
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/misc/outb.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/misc/outb.c
new file mode 100644
index 00000000..bbe18eae
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/misc/outb.c
@@ -0,0 +1,9 @@
+#include 
+
+int main(void)
+{
+    ioperm(0x340,0x342,1);
+    outb(0x340,0x0);
+    exit(0);
+}
+
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/misc/popen.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/misc/popen.c
new file mode 100644
index 00000000..868b70ee
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/misc/popen.c
@@ -0,0 +1,47 @@
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define TEST(r, f, x, m) ( \
+((r) = (f)) == (x) || \
+(printf(__FILE__ ":%d: %s failed (" m ")\n", __LINE__, #f, r, x), err++, 0) )
+
+#define TEST_E(f) ( (errno = 0), (f) || \
+(printf(__FILE__ ":%d: %s failed (errno = %d)\n", __LINE__, #f, errno), err++, 0) )
+
+#define TEST_S(s, x, m) ( \
+!strcmp((s),(x)) || \
+(printf(__FILE__ ":%d: [%s] != [%s] (%s)\n", __LINE__, s, x, m), err++, 0) )
+
+static sig_atomic_t got_sig;
+
+static void handler(int sig)
+{
+	got_sig = 1;
+}
+
+int main(void)
+{
+	int i;
+	char foo[6];
+	char cmd[64];
+	int err = 0;
+	FILE *f;
+
+	TEST_E(f = popen("echo hello", "r"));
+	TEST_E(fgets(foo, sizeof foo, f));
+	TEST_S(foo, "hello", "child process did not say hello");
+	TEST(i, pclose(f), 0, "exit status %04x != %04x");
+
+	signal(SIGUSR1, handler);
+	snprintf(cmd, sizeof cmd, "read a ; test \"x$a\" = xhello && kill -USR1 %d", getpid());
+	TEST_E(f = popen(cmd, "w"));
+	TEST_E(fputs("hello", f) >= 0);
+	TEST(i, pclose(f), 0, "exit status %04x != %04x");
+	signal(SIGUSR1, SIG_DFL);
+	TEST(i, got_sig, 1, "child process did not send signal (%i!=%i)");
+
+	return err;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/misc/seek.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/misc/seek.c
new file mode 100644
index 00000000..c5edb94c
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/misc/seek.c
@@ -0,0 +1,82 @@
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define ARRAY_SIZE(arr) (sizeof(arr)/sizeof(*arr))
+
+int main(void)
+{
+	struct {
+		off_t offset;
+		int   whence;
+	} tests[] = {
+		{ 0x00, SEEK_SET },
+		{ 0x01, SEEK_SET },
+		{ 0xFF, SEEK_SET }
+	};
+	char buf[2000];
+	off_t ret;
+	int i, fd;
+	FILE *fp;
+	int tmp;
+
+	fd = open("lseek.out", O_RDWR|O_CREAT, 0600);
+	if (fd == -1) {
+		perror("open(lseek.out) failed");
+		return 1;
+	}
+	unlink("lseek.out");
+	fp = fdopen(fd, "rw");
+	if (fp == NULL) {
+		perror("fopen(lseek.out) failed");
+		return 1;
+	}
+
+	memset(buf, 0xAB, sizeof(buf));
+	ret = write(fd, buf, sizeof(buf));
+	if (ret != sizeof(buf)) {
+		fprintf(stderr, "write() failed to write %zi bytes (wrote %li): ", sizeof(buf), (long)ret);
+		perror("");
+		return 1;
+	}
+
+	tmp = fseeko(fp, 1024, SEEK_SET);
+	assert(tmp == 0);
+	tmp = fseeko(fp, (off_t)-16, SEEK_CUR);
+	assert(tmp == 0);
+	ret = ftell(fp);
+	if (ret != (1024-16)) {
+		fprintf(stderr, "ftell() failed, we wanted pos %i but got %li: ", (1024-16), (long)ret);
+		perror("");
+		return 1;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(tests); ++i) {
+		ret = lseek(fd, tests[i].offset, tests[i].whence);
+		if (ret != tests[i].offset) {
+			fprintf(stderr, "lseek(%li,%i) failed (wanted %li, got %li): ", (long)tests[i].offset,
+			        tests[i].whence, (long)tests[i].offset, (long)ret);
+			perror("");
+			return 1;
+		}
+		ret = fseek(fp, tests[i].offset, tests[i].whence);
+		if (ret != 0) {
+			fprintf(stderr, "fseek(%li,%i) failed (wanted 0, got %li): ", (long)tests[i].offset,
+			        tests[i].whence, (long)ret);
+			perror("");
+			return 1;
+		}
+	}
+
+	fclose(fp);
+	close(fd);
+
+	printf("Success!\n");
+
+	return 0;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/misc/sem.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/misc/sem.c
new file mode 100644
index 00000000..62a59b1e
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/misc/sem.c
@@ -0,0 +1,45 @@
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+int main(void)
+{
+	int k, r;
+	union semun {
+		int val;
+		struct semid_ds *buf;
+		unsigned short int *array;
+		struct seminfo *__buf;
+	} sd;
+	struct semid_ds sd_buf;
+
+	k = semget(IPC_PRIVATE, 10, IPC_CREAT | 0666 );
+	printf("semget(IPC_CREAT) = %d\n", k);
+
+	if (k < 0) {
+		fprintf(stderr, "semget failed: %s\n", strerror(errno));
+		return 1;
+	}
+
+	sd.buf = &sd_buf;
+	r = semctl(k, 0, IPC_STAT, sd);
+	printf("semctl(k) = %d\n", r);
+
+	if (r < 0) {
+		perror("semctl IPC_STAT failed");
+		return 1;
+	}
+
+	printf("sem_nsems = %lu\n", sd_buf.sem_nsems);
+	if (sd_buf.sem_nsems != 10) {
+		fprintf(stderr, "failed: incorrect sem_nsems!\n");
+		return 1;
+	}
+
+	printf("succeeded\n");
+
+	return 0;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/misc/stdarg.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/misc/stdarg.c
new file mode 100644
index 00000000..1566e0ce
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/misc/stdarg.c
@@ -0,0 +1,23 @@
+/* copied from rsync */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+static int foo(const char *format, ...)
+{
+	va_list ap;
+	size_t len;
+	char buf[5];
+
+	va_start(ap, format);
+	len = vsnprintf(0, 0, format, ap);
+	va_end(ap);
+	if (len != 5) return(1);
+
+	if (snprintf(buf, 3, "hello") != 5 || strcmp(buf, "he") != 0) return(1);
+
+	return(0);
+}
+int main(void) { return foo("hello"); }
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/misc/tst-fnmatch.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/misc/tst-fnmatch.c
new file mode 100644
index 00000000..bb102c5b
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/misc/tst-fnmatch.c
@@ -0,0 +1,444 @@
+/* Tests for fnmatch function.
+   Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+static char *next_input (char **line, int first, int last);
+static int convert_flags (const char *str);
+static char *flag_output (int flags);
+static char *escape (const char *str, size_t *reslenp, char **resbuf);
+
+
+int str_isalpha(const char *str)
+{
+	size_t i = strlen(str);
+	while (i--)
+		if (isascii(str[i]) == 0)
+			return 0;
+	return 1;
+}
+int str_has_funk(const char *str, const char x)
+{
+	size_t i, max = strlen(str);
+	for (i=0; i+1 reslen)
+    {
+      resbuf = (char *) realloc (resbuf, 2 * len + 1);
+      if (resbuf == NULL)
+	error (EXIT_FAILURE, errno, "while allocating buffer for printing");
+      *reslenp = 2 * len + 1;
+      *resbufp = resbuf;
+    }
+
+  wp = resbuf;
+  while (*str != '\0')
+    if (*str == '\t')
+      {
+	*wp++ = '\\';
+	*wp++ = 't';
+	++str;
+      }
+    else if (*str == '\n')
+      {
+	*wp++ = '\\';
+	*wp++ = 'n';
+	++str;
+      }
+    else if (*str == '"')
+      {
+	*wp++ = '\\';
+	*wp++ = '"';
+	++str;
+      }
+    else if (*str == '\\')
+      {
+	*wp++ = '\\';
+	*wp++ = '\\';
+	++str;
+      }
+    else
+      *wp++ = *str++;
+
+  *wp = '\0';
+
+  return resbuf;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/misc/tst-fnmatch.input b/l4/pkg/uclibc/lib/contrib/uclibc/test/misc/tst-fnmatch.input
new file mode 100644
index 00000000..9061d199
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/misc/tst-fnmatch.input
@@ -0,0 +1,755 @@
+# Tests for fnmatch.
+# Copyright (C) 2000, 2001, 2004 Free Software Foundation, Inc.
+# This file is part of the GNU C Library.
+# Contributes by Ulrich Drepper .
+#
+
+# The GNU C Library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+
+# The GNU C Library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+
+# You should have received a copy of the GNU Lesser General Public
+# License along with the GNU C Library; if not, write to the Free
+# Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+# 02111-1307 USA.
+
+
+# Derived from the IEEE 2003.2 text.  The standard only contains some
+# wording describing the situations to be tested.  It does not specify
+# any specific tests.  I.e., the tests below are in no case sufficient.
+# They are hopefully necessary, though.
+
+# B.6 004(C)
+C		 "!#%+,-./01234567889"	"!#%+,-./01234567889"  0
+C		 ":;=@ABCDEFGHIJKLMNO"	":;=@ABCDEFGHIJKLMNO"  0
+C		 "PQRSTUVWXYZ]abcdefg"	"PQRSTUVWXYZ]abcdefg"  0
+C		 "hijklmnopqrstuvwxyz"	"hijklmnopqrstuvwxyz"  0
+C		 "^_{}~"		"^_{}~"		       0
+
+# B.6 005(C)
+C		 "\"$&'()"		"\\\"\\$\\&\\'\\(\\)"  0
+C		 "*?[\\`|"		"\\*\\?\\[\\\\\\`\\|"  0
+C		 "<>"			"\\<\\>"	       0
+
+# B.6 006(C)
+C		 "?*["			"[?*[][?*[][?*[]"      0
+C		 "a/b"			"?/b"		       0
+
+# B.6 007(C)
+C		 "a/b"			"a?b"		       0
+C		 "a/b"			"a/?"		       0
+C		 "aa/b"			"?/b"		       NOMATCH
+C		 "aa/b"			"a?b"		       NOMATCH
+C		 "a/bb"			"a/?"		       NOMATCH
+
+# B.6 009(C)
+C		 "abc"			"[abc]"		       NOMATCH
+C		 "x"			"[abc]"		       NOMATCH
+C		 "a"			"[abc]"		       0
+C		 "["			"[[abc]"	       0
+C		 "a"			"[][abc]"	       0
+C		 "a]"			"[]a]]"		       0
+
+# B.6 010(C)
+C		 "xyz"			"[!abc]"	       NOMATCH
+C		 "x"			"[!abc]"	       0
+C		 "a"			"[!abc]"	       NOMATCH
+
+# B.6 011(C)
+C		 "]"			"[][abc]"	       0
+C		 "abc]"			"[][abc]"	       NOMATCH
+C		 "[]abc"		"[][]abc"	       NOMATCH
+C		 "]"		        "[!]]"		       NOMATCH
+C		 "aa]"			"[!]a]"		       NOMATCH
+C		 "]"		        "[!a]"		       0
+C		 "]]"		        "[!a]]"		       0
+
+# B.6 012(C)
+C		 "a"			"[[.a.]]"	       0
+C		 "-"			"[[.-.]]"	       0
+C		 "-"			"[[.-.][.].]]"	       0
+C		 "-"			"[[.].][.-.]]"	       0
+C		 "-"			"[[.-.][=u=]]"	       0
+C		 "-"			"[[.-.][:alpha:]]"     0
+C		 "a"			"[![.a.]]"	       NOMATCH
+
+# B.6 013(C)
+C		 "a"			"[[.b.]]"	       NOMATCH
+C		 "a"			"[[.b.][.c.]]"	       NOMATCH
+C		 "a"			"[[.b.][=b=]]"	       NOMATCH
+
+
+# B.6 015(C)
+C		 "a"			"[[=a=]]"	       0
+C		 "b"			"[[=a=]b]"	       0
+C		 "b"			"[[=a=][=b=]]"	       0
+C		 "a"			"[[=a=][=b=]]"	       0
+C		 "a"			"[[=a=][.b.]]"	       0
+C		 "a"			"[[=a=][:digit:]]"     0
+
+# B.6 016(C)
+C		 "="			"[[=a=]b]"	       NOMATCH
+C		 "]"			"[[=a=]b]"	       NOMATCH
+C		 "a"			"[[=b=][=c=]]"	       NOMATCH
+C		 "a"			"[[=b=][.].]]"	       NOMATCH
+C		 "a"			"[[=b=][:digit:]]"     NOMATCH
+
+# B.6 017(C)
+C		 "a"			"[[:alnum:]]"	       0
+C		 "a"			"[![:alnum:]]"	       NOMATCH
+C		 "-"			"[[:alnum:]]"	       NOMATCH
+C		 "a]a"			"[[:alnum:]]a"	       NOMATCH
+C		 "-"			"[[:alnum:]-]"	       0
+C		 "aa"			"[[:alnum:]]a"	       0
+C		 "-"			"[![:alnum:]]"	       0
+C		 "]"			"[!][:alnum:]]"	       NOMATCH
+C		 "["			"[![:alnum:][]"	       NOMATCH
+C		 "a"			"[[:alnum:]]"	       0
+C		 "b"			"[[:alnum:]]"	       0
+C		 "c"			"[[:alnum:]]"	       0
+C		 "d"			"[[:alnum:]]"	       0
+C		 "e"			"[[:alnum:]]"	       0
+C		 "f"			"[[:alnum:]]"	       0
+C		 "g"			"[[:alnum:]]"	       0
+C		 "h"			"[[:alnum:]]"	       0
+C		 "i"			"[[:alnum:]]"	       0
+C		 "j"			"[[:alnum:]]"	       0
+C		 "k"			"[[:alnum:]]"	       0
+C		 "l"			"[[:alnum:]]"	       0
+C		 "m"			"[[:alnum:]]"	       0
+C		 "n"			"[[:alnum:]]"	       0
+C		 "o"			"[[:alnum:]]"	       0
+C		 "p"			"[[:alnum:]]"	       0
+C		 "q"			"[[:alnum:]]"	       0
+C		 "r"			"[[:alnum:]]"	       0
+C		 "s"			"[[:alnum:]]"	       0
+C		 "t"			"[[:alnum:]]"	       0
+C		 "u"			"[[:alnum:]]"	       0
+C		 "v"			"[[:alnum:]]"	       0
+C		 "w"			"[[:alnum:]]"	       0
+C		 "x"			"[[:alnum:]]"	       0
+C		 "y"			"[[:alnum:]]"	       0
+C		 "z"			"[[:alnum:]]"	       0
+C		 "A"			"[[:alnum:]]"	       0
+C		 "B"			"[[:alnum:]]"	       0
+C		 "C"			"[[:alnum:]]"	       0
+C		 "D"			"[[:alnum:]]"	       0
+C		 "E"			"[[:alnum:]]"	       0
+C		 "F"			"[[:alnum:]]"	       0
+C		 "G"			"[[:alnum:]]"	       0
+C		 "H"			"[[:alnum:]]"	       0
+C		 "I"			"[[:alnum:]]"	       0
+C		 "J"			"[[:alnum:]]"	       0
+C		 "K"			"[[:alnum:]]"	       0
+C		 "L"			"[[:alnum:]]"	       0
+C		 "M"			"[[:alnum:]]"	       0
+C		 "N"			"[[:alnum:]]"	       0
+C		 "O"			"[[:alnum:]]"	       0
+C		 "P"			"[[:alnum:]]"	       0
+C		 "Q"			"[[:alnum:]]"	       0
+C		 "R"			"[[:alnum:]]"	       0
+C		 "S"			"[[:alnum:]]"	       0
+C		 "T"			"[[:alnum:]]"	       0
+C		 "U"			"[[:alnum:]]"	       0
+C		 "V"			"[[:alnum:]]"	       0
+C		 "W"			"[[:alnum:]]"	       0
+C		 "X"			"[[:alnum:]]"	       0
+C		 "Y"			"[[:alnum:]]"	       0
+C		 "Z"			"[[:alnum:]]"	       0
+C		 "0"			"[[:alnum:]]"	       0
+C		 "1"			"[[:alnum:]]"	       0
+C		 "2"			"[[:alnum:]]"	       0
+C		 "3"			"[[:alnum:]]"	       0
+C		 "4"			"[[:alnum:]]"	       0
+C		 "5"			"[[:alnum:]]"	       0
+C		 "6"			"[[:alnum:]]"	       0
+C		 "7"			"[[:alnum:]]"	       0
+C		 "8"			"[[:alnum:]]"	       0
+C		 "9"			"[[:alnum:]]"	       0
+C		 "!"			"[[:alnum:]]"	       NOMATCH
+C		 "#"			"[[:alnum:]]"	       NOMATCH
+C		 "%"			"[[:alnum:]]"	       NOMATCH
+C		 "+"			"[[:alnum:]]"	       NOMATCH
+C		 ","			"[[:alnum:]]"	       NOMATCH
+C		 "-"			"[[:alnum:]]"	       NOMATCH
+C		 "."			"[[:alnum:]]"	       NOMATCH
+C		 "/"			"[[:alnum:]]"	       NOMATCH
+C		 ":"			"[[:alnum:]]"	       NOMATCH
+C		 ";"			"[[:alnum:]]"	       NOMATCH
+C		 "="			"[[:alnum:]]"	       NOMATCH
+C		 "@"			"[[:alnum:]]"	       NOMATCH
+C		 "["			"[[:alnum:]]"	       NOMATCH
+C		 "\\"			"[[:alnum:]]"	       NOMATCH
+C		 "]"			"[[:alnum:]]"	       NOMATCH
+C		 "^"			"[[:alnum:]]"	       NOMATCH
+C		 "_"			"[[:alnum:]]"	       NOMATCH
+C		 "{"			"[[:alnum:]]"	       NOMATCH
+C		 "}"			"[[:alnum:]]"	       NOMATCH
+C		 "~"			"[[:alnum:]]"	       NOMATCH
+C		 "\""			"[[:alnum:]]"	       NOMATCH
+C		 "$"			"[[:alnum:]]"	       NOMATCH
+C		 "&"			"[[:alnum:]]"	       NOMATCH
+C		 "'"			"[[:alnum:]]"	       NOMATCH
+C		 "("			"[[:alnum:]]"	       NOMATCH
+C		 ")"			"[[:alnum:]]"	       NOMATCH
+C		 "*"			"[[:alnum:]]"	       NOMATCH
+C		 "?"			"[[:alnum:]]"	       NOMATCH
+C		 "`"			"[[:alnum:]]"	       NOMATCH
+C		 "|"			"[[:alnum:]]"	       NOMATCH
+C		 "<"			"[[:alnum:]]"	       NOMATCH
+C		 ">"			"[[:alnum:]]"	       NOMATCH
+C		 "\t"			"[[:cntrl:]]"	       0
+C		 "t"			"[[:cntrl:]]"	       NOMATCH
+C		 "t"			"[[:lower:]]"	       0
+C		 "\t"			"[[:lower:]]"	       NOMATCH
+C		 "T"			"[[:lower:]]"	       NOMATCH
+C		 "\t"			"[[:space:]]"	       0
+C		 "t"			"[[:space:]]"	       NOMATCH
+C		 "t"			"[[:alpha:]]"	       0
+C		 "\t"			"[[:alpha:]]"	       NOMATCH
+C		 "0"			"[[:digit:]]"	       0
+C		 "\t"			"[[:digit:]]"	       NOMATCH
+C		 "t"			"[[:digit:]]"	       NOMATCH
+C		 "\t"			"[[:print:]]"	       NOMATCH
+C		 "t"			"[[:print:]]"	       0
+C		 "T"			"[[:upper:]]"	       0
+C		 "\t"			"[[:upper:]]"	       NOMATCH
+C		 "t"			"[[:upper:]]"	       NOMATCH
+C		 "\t"			"[[:blank:]]"	       0
+C		 "t"			"[[:blank:]]"	       NOMATCH
+C		 "\t"			"[[:graph:]]"	       NOMATCH
+C		 "t"			"[[:graph:]]"	       0
+C		 "."			"[[:punct:]]"	       0
+C		 "t"			"[[:punct:]]"	       NOMATCH
+C		 "\t"			"[[:punct:]]"	       NOMATCH
+C		 "0"			"[[:xdigit:]]"	       0
+C		 "\t"			"[[:xdigit:]]"	       NOMATCH
+C		 "a"			"[[:xdigit:]]"	       0
+C		 "A"			"[[:xdigit:]]"	       0
+C		 "t"			"[[:xdigit:]]"	       NOMATCH
+C		 "a"			"[[alpha]]"	       NOMATCH
+C		 "a"			"[[alpha:]]"	       NOMATCH
+C		 "a]"			"[[alpha]]"	       0
+C		 "a]"			"[[alpha:]]"	       0
+C		 "a"			"[[:alpha:][.b.]]"     0
+C		 "a"			"[[:alpha:][=b=]]"     0
+C		 "a"			"[[:alpha:][:digit:]]" 0
+C		 "a"			"[[:digit:][:alpha:]]" 0
+
+# B.6 018(C)
+C		 "a"			"[a-c]"		       0
+C		 "b"			"[a-c]"		       0
+C		 "c"			"[a-c]"		       0
+C		 "a"			"[b-c]"		       NOMATCH
+C		 "d"			"[b-c]"		       NOMATCH
+C		 "B"			"[a-c]"		       NOMATCH
+C		 "b"			"[A-C]"		       NOMATCH
+C		 ""			"[a-c]"		       NOMATCH
+C		 "as"			"[a-ca-z]"	       NOMATCH
+C		 "a"			"[[.a.]-c]"	       0
+C		 "a"			"[a-[.c.]]"	       0
+C		 "a"			"[[.a.]-[.c.]]"	       0
+C		 "b"			"[[.a.]-c]"	       0
+C		 "b"			"[a-[.c.]]"	       0
+C		 "b"			"[[.a.]-[.c.]]"	       0
+C		 "c"			"[[.a.]-c]"	       0
+C		 "c"			"[a-[.c.]]"	       0
+C		 "c"			"[[.a.]-[.c.]]"	       0
+C		 "d"			"[[.a.]-c]"	       NOMATCH
+C		 "d"			"[a-[.c.]]"	       NOMATCH
+C		 "d"			"[[.a.]-[.c.]]"	       NOMATCH
+
+# B.6 019(C)
+C		 "a"			"[c-a]"		       NOMATCH
+C		 "a"			"[[.c.]-a]"	       NOMATCH
+C		 "a"			"[c-[.a.]]"	       NOMATCH
+C		 "a"			"[[.c.]-[.a.]]"	       NOMATCH
+C		 "c"			"[c-a]"		       NOMATCH
+C		 "c"			"[[.c.]-a]"	       NOMATCH
+C		 "c"			"[c-[.a.]]"	       NOMATCH
+C		 "c"			"[[.c.]-[.a.]]"	       NOMATCH
+
+# B.6 020(C)
+C		 "a"			"[a-c0-9]"	       0
+C		 "d"			"[a-c0-9]"	       NOMATCH
+C		 "B"			"[a-c0-9]"	       NOMATCH
+
+# B.6 021(C)
+C		 "-"			"[-a]"		       0
+C		 "a"			"[-b]"		       NOMATCH
+C		 "-"			"[!-a]"		       NOMATCH
+C		 "a"			"[!-b]"		       0
+C		 "-"			"[a-c-0-9]"	       0
+C		 "b"			"[a-c-0-9]"	       0
+C		 "a:"			"a[0-9-a]"	       NOMATCH
+C		 "a:"			"a[09-a]"	       0
+
+# B.6 024(C)
+C		 ""			"*"		       0
+C		 "asd/sdf"		"*"		       0
+
+# B.6 025(C)
+C		 "as"			"[a-c][a-z]"	       0
+C		 "as"			"??"		       0
+
+# B.6 026(C)
+C		 "asd/sdf"		"as*df"		       0
+C		 "asd/sdf"		"as*"		       0
+C		 "asd/sdf"		"*df"		       0
+C		 "asd/sdf"		"as*dg"		       NOMATCH
+C		 "asdf"			"as*df"		       0
+C		 "asdf"			"as*df?"	       NOMATCH
+C		 "asdf"			"as*??"		       0
+C		 "asdf"			"a*???"		       0
+C		 "asdf"			"*????"		       0
+C		 "asdf"			"????*"		       0
+C		 "asdf"			"??*?"		       0
+
+# B.6 027(C)
+C		 "/"			"/"		       0
+C		 "/"			"/*"		       0
+C		 "/"			"*/"		       0
+C		 "/"			"/?"		       NOMATCH
+C		 "/"			"?/"		       NOMATCH
+C		 "/"			"?"		       0
+C		 "."			"?"		       0
+C		 "/."			"??"		       0
+C		 "/"			"[!a-c]"	       0
+C		 "."			"[!a-c]"	       0
+
+# B.6 029(C)
+C		 "/"			"/"		       0       PATHNAME
+C		 "//"			"//"		       0       PATHNAME
+C		 "/.a"			"/*"		       0       PATHNAME
+C		 "/.a"			"/?a"		       0       PATHNAME
+C		 "/.a"			"/[!a-z]a"	       0       PATHNAME
+C		 "/.a/.b"		"/*/?b"		       0       PATHNAME
+
+# B.6 030(C)
+C		 "/"			"?"		       NOMATCH PATHNAME
+C		 "/"			"*"		       NOMATCH PATHNAME
+C		 "a/b"			"a?b"		       NOMATCH PATHNAME
+C		 "/.a/.b"		"/*b"		       NOMATCH PATHNAME
+
+# B.6 031(C)
+C		 "/$"			"\\/\\$"	       0
+C		 "/["			"\\/\\["	       0
+C		 "/["			"\\/["		       NOMATCH
+
+# B.6 032(C)
+C		 "/$"			"\\/\\$"	       NOMATCH NOESCAPE
+C		 "/\\$"			"\\/\\$"	       NOMATCH NOESCAPE
+C		 "\\/\\$"		"\\/\\$"	       0       NOESCAPE
+
+# B.6 033(C)
+C		 ".asd"			".*"		       0       PERIOD
+C		 "/.asd"		"*"		       0       PERIOD
+C		 "/as/.df"		"*/?*f"		       0       PERIOD
+C		 "..asd"		".[!a-z]*"	       0       PERIOD
+
+# B.6 034(C)
+C		 ".asd"			"*"		       NOMATCH PERIOD
+C		 ".asd"			"?asd"		       NOMATCH PERIOD
+C		 ".asd"			"[!a-z]*"	       NOMATCH PERIOD
+
+# B.6 035(C)
+C		 "/."			"/."		       0       PATHNAME|PERIOD
+C		 "/.a./.b."		"/.*/.*"	       0       PATHNAME|PERIOD
+C		 "/.a./.b."		"/.??/.??"	       0       PATHNAME|PERIOD
+
+# B.6 036(C)
+C		 "/."			"*"		       NOMATCH PATHNAME|PERIOD
+C		 "/."			"/*"		       NOMATCH PATHNAME|PERIOD
+C		 "/."			"/?"		       NOMATCH PATHNAME|PERIOD
+C		 "/."			"/[!a-z]"	       NOMATCH PATHNAME|PERIOD
+C		 "/a./.b."		"/*/*"		       NOMATCH PATHNAME|PERIOD
+C		 "/a./.b."		"/??/???"	       NOMATCH PATHNAME|PERIOD
+
+# Some home-grown tests.
+C		"foobar"		"foo*[abc]z"	       NOMATCH
+C		"foobaz"		"foo*[abc][xyz]"       0
+C		"foobaz"		"foo?*[abc][xyz]"      0
+C		"foobaz"		"foo?*[abc][x/yz]"     0
+C		"foobaz"		"foo?*[abc]/[xyz]"     NOMATCH PATHNAME
+C		"a"			"a/"                   NOMATCH PATHNAME
+C		"a/"			"a"		       NOMATCH PATHNAME
+C		"//a"			"/a"		       NOMATCH PATHNAME
+C		"/a"			"//a"		       NOMATCH PATHNAME
+C		"az"			"[a-]z"		       0
+C		"bz"			"[ab-]z"	       0
+C		"cz"			"[ab-]z"	       NOMATCH
+C		"-z"			"[ab-]z"	       0
+C		"az"			"[-a]z"		       0
+C		"bz"			"[-ab]z"	       0
+C		"cz"			"[-ab]z"	       NOMATCH
+C		"-z"			"[-ab]z"	       0
+C		"\\"			"[\\\\-a]"	       0
+C		"_"			"[\\\\-a]"	       0
+C		"a"			"[\\\\-a]"	       0
+C		"-"			"[\\\\-a]"	       NOMATCH
+C		"\\"			"[\\]-a]"	       NOMATCH
+C		"_"			"[\\]-a]"	       0
+C		"a"			"[\\]-a]"	       0
+C		"]"			"[\\]-a]"	       0
+C		"-"			"[\\]-a]"	       NOMATCH
+C		"\\"			"[!\\\\-a]"	       NOMATCH
+C		"_"			"[!\\\\-a]"	       NOMATCH
+C		"a"			"[!\\\\-a]"	       NOMATCH
+C		"-"			"[!\\\\-a]"	       0
+C		"!"			"[\\!-]"	       0
+C		"-"			"[\\!-]"	       0
+C		"\\"			"[\\!-]"	       NOMATCH
+C		"Z"			"[Z-\\\\]"	       0
+C		"["			"[Z-\\\\]"	       0
+C		"\\"			"[Z-\\\\]"	       0
+C		"-"			"[Z-\\\\]"	       NOMATCH
+C		"Z"			"[Z-\\]]"	       0
+C		"["			"[Z-\\]]"	       0
+C		"\\"			"[Z-\\]]"	       0
+C		"]"			"[Z-\\]]"	       0
+C		"-"			"[Z-\\]]"	       NOMATCH
+
+# Following are tests outside the scope of IEEE 2003.2 since they are using
+# locales other than the C locale.  The main focus of the tests is on the
+# handling of ranges and the recognition of character (vs bytes).
+de_DE.ISO-8859-1 "a"			"[a-z]"		       0
+de_DE.ISO-8859-1 "z"			"[a-z]"		       0
+de_DE.ISO-8859-1 "ä"			"[a-z]"		       0
+de_DE.ISO-8859-1 "ö"			"[a-z]"		       0
+de_DE.ISO-8859-1 "ü"			"[a-z]"		       0
+de_DE.ISO-8859-1 "A"			"[a-z]"		       NOMATCH
+de_DE.ISO-8859-1 "Z"			"[a-z]"		       NOMATCH
+de_DE.ISO-8859-1 "Ä"			"[a-z]"		       NOMATCH
+de_DE.ISO-8859-1 "Ö"			"[a-z]"		       NOMATCH
+de_DE.ISO-8859-1 "Ü"			"[a-z]"		       NOMATCH
+de_DE.ISO-8859-1 "a"			"[A-Z]"		       NOMATCH
+de_DE.ISO-8859-1 "z"			"[A-Z]"		       NOMATCH
+de_DE.ISO-8859-1 "ä"			"[A-Z]"		       NOMATCH
+de_DE.ISO-8859-1 "ö"			"[A-Z]"		       NOMATCH
+de_DE.ISO-8859-1 "ü"			"[A-Z]"		       NOMATCH
+de_DE.ISO-8859-1 "A"			"[A-Z]"		       0
+de_DE.ISO-8859-1 "Z"			"[A-Z]"		       0
+de_DE.ISO-8859-1 "Ä"			"[A-Z]"		       0
+de_DE.ISO-8859-1 "Ö"			"[A-Z]"		       0
+de_DE.ISO-8859-1 "Ü"			"[A-Z]"		       0
+de_DE.ISO-8859-1 "a"			"[[:lower:]]"	       0
+de_DE.ISO-8859-1 "z"			"[[:lower:]]"	       0
+de_DE.ISO-8859-1 "ä"			"[[:lower:]]"	       0
+de_DE.ISO-8859-1 "ö"			"[[:lower:]]"	       0
+de_DE.ISO-8859-1 "ü"			"[[:lower:]]"	       0
+de_DE.ISO-8859-1 "A"			"[[:lower:]]"	       NOMATCH
+de_DE.ISO-8859-1 "Z"			"[[:lower:]]"	       NOMATCH
+de_DE.ISO-8859-1 "Ä"			"[[:lower:]]"	       NOMATCH
+de_DE.ISO-8859-1 "Ö"			"[[:lower:]]"	       NOMATCH
+de_DE.ISO-8859-1 "Ü"			"[[:lower:]]"	       NOMATCH
+de_DE.ISO-8859-1 "a"			"[[:upper:]]"	       NOMATCH
+de_DE.ISO-8859-1 "z"			"[[:upper:]]"	       NOMATCH
+de_DE.ISO-8859-1 "ä"			"[[:upper:]]"	       NOMATCH
+de_DE.ISO-8859-1 "ö"			"[[:upper:]]"	       NOMATCH
+de_DE.ISO-8859-1 "ü"			"[[:upper:]]"	       NOMATCH
+de_DE.ISO-8859-1 "A"			"[[:upper:]]"	       0
+de_DE.ISO-8859-1 "Z"			"[[:upper:]]"	       0
+de_DE.ISO-8859-1 "Ä"			"[[:upper:]]"	       0
+de_DE.ISO-8859-1 "Ö"			"[[:upper:]]"	       0
+de_DE.ISO-8859-1 "Ü"			"[[:upper:]]"	       0
+de_DE.ISO-8859-1 "a"			"[[:alpha:]]"	       0
+de_DE.ISO-8859-1 "z"			"[[:alpha:]]"	       0
+de_DE.ISO-8859-1 "ä"			"[[:alpha:]]"	       0
+de_DE.ISO-8859-1 "ö"			"[[:alpha:]]"	       0
+de_DE.ISO-8859-1 "ü"			"[[:alpha:]]"	       0
+de_DE.ISO-8859-1 "A"			"[[:alpha:]]"	       0
+de_DE.ISO-8859-1 "Z"			"[[:alpha:]]"	       0
+de_DE.ISO-8859-1 "Ä"			"[[:alpha:]]"	       0
+de_DE.ISO-8859-1 "Ö"			"[[:alpha:]]"	       0
+de_DE.ISO-8859-1 "Ü"			"[[:alpha:]]"	       0
+
+de_DE.ISO-8859-1 "a"			"[[=a=]b]"	       0
+de_DE.ISO-8859-1 "â"			"[[=a=]b]"	       0
+de_DE.ISO-8859-1 "à"			"[[=a=]b]"	       0
+de_DE.ISO-8859-1 "á"			"[[=a=]b]"	       0
+de_DE.ISO-8859-1 "ä"			"[[=a=]b]"	       0
+de_DE.ISO-8859-1 "b"			"[[=a=]b]"	       0
+de_DE.ISO-8859-1 "c"			"[[=a=]b]"	       NOMATCH
+de_DE.ISO-8859-1 "a"			"[[=â=]b]"	       0
+de_DE.ISO-8859-1 "â"			"[[=â=]b]"	       0
+de_DE.ISO-8859-1 "à"			"[[=â=]b]"	       0
+de_DE.ISO-8859-1 "á"			"[[=â=]b]"	       0
+de_DE.ISO-8859-1 "ä"			"[[=â=]b]"	       0
+de_DE.ISO-8859-1 "b"			"[[=â=]b]"	       0
+de_DE.ISO-8859-1 "c"			"[[=â=]b]"	       NOMATCH
+de_DE.ISO-8859-1 "a"			"[[=à=]b]"	       0
+de_DE.ISO-8859-1 "â"			"[[=à=]b]"	       0
+de_DE.ISO-8859-1 "à"			"[[=à=]b]"	       0
+de_DE.ISO-8859-1 "á"			"[[=à=]b]"	       0
+de_DE.ISO-8859-1 "ä"			"[[=à=]b]"	       0
+de_DE.ISO-8859-1 "b"			"[[=à=]b]"	       0
+de_DE.ISO-8859-1 "c"			"[[=à=]b]"	       NOMATCH
+de_DE.ISO-8859-1 "a"			"[[=á=]b]"	       0
+de_DE.ISO-8859-1 "â"			"[[=á=]b]"	       0
+de_DE.ISO-8859-1 "à"			"[[=á=]b]"	       0
+de_DE.ISO-8859-1 "á"			"[[=á=]b]"	       0
+de_DE.ISO-8859-1 "ä"			"[[=á=]b]"	       0
+de_DE.ISO-8859-1 "b"			"[[=á=]b]"	       0
+de_DE.ISO-8859-1 "c"			"[[=á=]b]"	       NOMATCH
+de_DE.ISO-8859-1 "a"			"[[=ä=]b]"	       0
+de_DE.ISO-8859-1 "â"			"[[=ä=]b]"	       0
+de_DE.ISO-8859-1 "à"			"[[=ä=]b]"	       0
+de_DE.ISO-8859-1 "á"			"[[=ä=]b]"	       0
+de_DE.ISO-8859-1 "ä"			"[[=ä=]b]"	       0
+de_DE.ISO-8859-1 "b"			"[[=ä=]b]"	       0
+de_DE.ISO-8859-1 "c"			"[[=ä=]b]"	       NOMATCH
+
+de_DE.ISO-8859-1 "aa"			"[[.a.]]a"	       0
+de_DE.ISO-8859-1 "ba"			"[[.a.]]a"	       NOMATCH
+
+
+# And with a multibyte character set.
+de_DE.UTF-8	 "a"			"[a-z]"		       0
+de_DE.UTF-8	 "z"			"[a-z]"		       0
+de_DE.UTF-8	 "ä"			"[a-z]"		       0
+de_DE.UTF-8	 "ö"			"[a-z]"		       0
+de_DE.UTF-8	 "ü"			"[a-z]"		       0
+de_DE.UTF-8	 "A"			"[a-z]"		       NOMATCH
+de_DE.UTF-8	 "Z"			"[a-z]"		       NOMATCH
+de_DE.UTF-8	 "Ä"			"[a-z]"		       NOMATCH
+de_DE.UTF-8	 "Ö"			"[a-z]"		       NOMATCH
+de_DE.UTF-8	 "Ü"			"[a-z]"		       NOMATCH
+de_DE.UTF-8	 "a"			"[A-Z]"		       NOMATCH
+de_DE.UTF-8	 "z"			"[A-Z]"		       NOMATCH
+de_DE.UTF-8	 "ä"			"[A-Z]"		       NOMATCH
+de_DE.UTF-8	 "ö"			"[A-Z]"		       NOMATCH
+de_DE.UTF-8	 "ü"			"[A-Z]"		       NOMATCH
+de_DE.UTF-8	 "A"			"[A-Z]"		       0
+de_DE.UTF-8	 "Z"			"[A-Z]"		       0
+de_DE.UTF-8	 "Ä"			"[A-Z]"		       0
+de_DE.UTF-8	 "Ö"			"[A-Z]"		       0
+de_DE.UTF-8	 "Ü"			"[A-Z]"		       0
+de_DE.UTF-8	 "a"			"[[:lower:]]"	       0
+de_DE.UTF-8	 "z"			"[[:lower:]]"	       0
+de_DE.UTF-8	 "ä"			"[[:lower:]]"	       0
+de_DE.UTF-8	 "ö"			"[[:lower:]]"	       0
+de_DE.UTF-8	 "ü"			"[[:lower:]]"	       0
+de_DE.UTF-8	 "A"			"[[:lower:]]"	       NOMATCH
+de_DE.UTF-8	 "Z"			"[[:lower:]]"	       NOMATCH
+de_DE.UTF-8	 "Ä"			"[[:lower:]]"	       NOMATCH
+de_DE.UTF-8	 "Ö"			"[[:lower:]]"	       NOMATCH
+de_DE.UTF-8	 "Ü"			"[[:lower:]]"	       NOMATCH
+de_DE.UTF-8	 "a"			"[[:upper:]]"	       NOMATCH
+de_DE.UTF-8	 "z"			"[[:upper:]]"	       NOMATCH
+de_DE.UTF-8	 "ä"			"[[:upper:]]"	       NOMATCH
+de_DE.UTF-8	 "ö"			"[[:upper:]]"	       NOMATCH
+de_DE.UTF-8	 "ü"			"[[:upper:]]"	       NOMATCH
+de_DE.UTF-8	 "A"			"[[:upper:]]"	       0
+de_DE.UTF-8	 "Z"			"[[:upper:]]"	       0
+de_DE.UTF-8	 "Ä"			"[[:upper:]]"	       0
+de_DE.UTF-8	 "Ö"			"[[:upper:]]"	       0
+de_DE.UTF-8	 "Ü"			"[[:upper:]]"	       0
+de_DE.UTF-8	 "a"			"[[:alpha:]]"	       0
+de_DE.UTF-8	 "z"			"[[:alpha:]]"	       0
+de_DE.UTF-8	 "ä"			"[[:alpha:]]"	       0
+de_DE.UTF-8	 "ö"			"[[:alpha:]]"	       0
+de_DE.UTF-8	 "ü"			"[[:alpha:]]"	       0
+de_DE.UTF-8	 "A"			"[[:alpha:]]"	       0
+de_DE.UTF-8	 "Z"			"[[:alpha:]]"	       0
+de_DE.UTF-8	 "Ä"			"[[:alpha:]]"	       0
+de_DE.UTF-8	 "Ö"			"[[:alpha:]]"	       0
+de_DE.UTF-8	 "Ü"			"[[:alpha:]]"	       0
+
+de_DE.UTF-8	 "a"			"[[=a=]b]"	       0
+de_DE.UTF-8	 "â"			"[[=a=]b]"	       0
+de_DE.UTF-8	 "à"			"[[=a=]b]"	       0
+de_DE.UTF-8	 "á"			"[[=a=]b]"	       0
+de_DE.UTF-8	 "ä"			"[[=a=]b]"	       0
+de_DE.UTF-8	 "b"			"[[=a=]b]"	       0
+de_DE.UTF-8	 "c"			"[[=a=]b]"	       NOMATCH
+de_DE.UTF-8	 "a"			"[[=â=]b]"	       0
+de_DE.UTF-8	 "â"			"[[=â=]b]"	       0
+de_DE.UTF-8	 "à"			"[[=â=]b]"	       0
+de_DE.UTF-8	 "á"			"[[=â=]b]"	       0
+de_DE.UTF-8	 "ä"			"[[=â=]b]"	       0
+de_DE.UTF-8	 "b"			"[[=â=]b]"	       0
+de_DE.UTF-8	 "c"			"[[=â=]b]"	       NOMATCH
+de_DE.UTF-8	 "a"			"[[=à=]b]"	       0
+de_DE.UTF-8	 "â"			"[[=à=]b]"	       0
+de_DE.UTF-8	 "à"			"[[=à=]b]"	       0
+de_DE.UTF-8	 "á"			"[[=à=]b]"	       0
+de_DE.UTF-8	 "ä"			"[[=à=]b]"	       0
+de_DE.UTF-8	 "b"			"[[=à=]b]"	       0
+de_DE.UTF-8	 "c"			"[[=à=]b]"	       NOMATCH
+de_DE.UTF-8	 "a"			"[[=á=]b]"	       0
+de_DE.UTF-8	 "â"			"[[=á=]b]"	       0
+de_DE.UTF-8	 "à"			"[[=á=]b]"	       0
+de_DE.UTF-8	 "á"			"[[=á=]b]"	       0
+de_DE.UTF-8	 "ä"			"[[=á=]b]"	       0
+de_DE.UTF-8	 "b"			"[[=á=]b]"	       0
+de_DE.UTF-8	 "c"			"[[=á=]b]"	       NOMATCH
+de_DE.UTF-8	 "a"			"[[=ä=]b]"	       0
+de_DE.UTF-8	 "â"			"[[=ä=]b]"	       0
+de_DE.UTF-8	 "à"			"[[=ä=]b]"	       0
+de_DE.UTF-8	 "á"			"[[=ä=]b]"	       0
+de_DE.UTF-8	 "ä"			"[[=ä=]b]"	       0
+de_DE.UTF-8	 "b"			"[[=ä=]b]"	       0
+de_DE.UTF-8	 "c"			"[[=ä=]b]"	       NOMATCH
+
+de_DE.UTF-8	 "aa"			"[[.a.]]a"	       0
+de_DE.UTF-8	 "ba"			"[[.a.]]a"	       NOMATCH
+
+
+# Test of GNU extensions.
+C		 "x"			"x"		       0       PATHNAME|LEADING_DIR
+C		 "x/y"			"x"		       0       PATHNAME|LEADING_DIR
+C		 "x/y/z"		"x"		       0       PATHNAME|LEADING_DIR
+C		 "x"			"*"		       0       PATHNAME|LEADING_DIR
+C		 "x/y"			"*"		       0       PATHNAME|LEADING_DIR
+C		 "x/y/z"		"*"		       0       PATHNAME|LEADING_DIR
+C		 "x"			"*x"		       0       PATHNAME|LEADING_DIR
+C		 "x/y"			"*x"		       0       PATHNAME|LEADING_DIR
+C		 "x/y/z"		"*x"		       0       PATHNAME|LEADING_DIR
+C		 "x"			"x*"		       0       PATHNAME|LEADING_DIR
+C		 "x/y"			"x*"		       0       PATHNAME|LEADING_DIR
+C		 "x/y/z"		"x*"		       0       PATHNAME|LEADING_DIR
+C		 "x"			"a"		       NOMATCH PATHNAME|LEADING_DIR
+C		 "x/y"			"a"		       NOMATCH PATHNAME|LEADING_DIR
+C		 "x/y/z"		"a"		       NOMATCH PATHNAME|LEADING_DIR
+C		 "x"			"x/y"		       NOMATCH PATHNAME|LEADING_DIR
+C		 "x/y"			"x/y"		       0       PATHNAME|LEADING_DIR
+C		 "x/y/z"		"x/y"		       0       PATHNAME|LEADING_DIR
+C		 "x"			"x?y"		       NOMATCH PATHNAME|LEADING_DIR
+C		 "x/y"			"x?y"		       NOMATCH PATHNAME|LEADING_DIR
+C		 "x/y/z"		"x?y"		       NOMATCH PATHNAME|LEADING_DIR
+
+# ksh style matching.
+C		"abcd"			"?@(a|b)*@(c)d"	       0       EXTMATCH
+C		"/dev/udp/129.22.8.102/45" "/dev/@(tcp|udp)/*/*" 0     PATHNAME|EXTMATCH
+C		"12"			"[1-9]*([0-9])"        0       EXTMATCH
+C		"12abc"			"[1-9]*([0-9])"        NOMATCH EXTMATCH
+C		"1"			"[1-9]*([0-9])"	       0       EXTMATCH
+C		"07"			"+([0-7])"	       0       EXTMATCH
+C		"0377"			"+([0-7])"	       0       EXTMATCH
+C		"09"			"+([0-7])"	       NOMATCH EXTMATCH
+C		"paragraph"		"para@(chute|graph)"   0       EXTMATCH
+C		"paramour"		"para@(chute|graph)"   NOMATCH EXTMATCH
+C		"para991"		"para?([345]|99)1"     0       EXTMATCH
+C		"para381"		"para?([345]|99)1"     NOMATCH EXTMATCH
+C		"paragraph"		"para*([0-9])"	       NOMATCH EXTMATCH
+C		"para"			"para*([0-9])"	       0       EXTMATCH
+C		"para13829383746592"	"para*([0-9])"	       0       EXTMATCH
+C		"paragraph"		"para+([0-9])"	       NOMATCH EXTMATCH
+C		"para"			"para+([0-9])"	       NOMATCH EXTMATCH
+C		"para987346523"		"para+([0-9])"	       0       EXTMATCH
+C		"paragraph"		"para!(*.[0-9])"       0       EXTMATCH
+C		"para.38"		"para!(*.[0-9])"       0       EXTMATCH
+C		"para.graph"		"para!(*.[0-9])"       0       EXTMATCH
+C		"para39"		"para!(*.[0-9])"       0       EXTMATCH
+C		""			"*(0|1|3|5|7|9)"       0       EXTMATCH
+C		"137577991"		"*(0|1|3|5|7|9)"       0       EXTMATCH
+C		"2468"			"*(0|1|3|5|7|9)"       NOMATCH EXTMATCH
+C		"1358"			"*(0|1|3|5|7|9)"       NOMATCH EXTMATCH
+C		"file.c"		"*.c?(c)"	       0       EXTMATCH
+C		"file.C"		"*.c?(c)"	       NOMATCH EXTMATCH
+C		"file.cc"		"*.c?(c)"	       0       EXTMATCH
+C		"file.ccc"		"*.c?(c)"	       NOMATCH EXTMATCH
+C		"parse.y"		"!(*.c|*.h|Makefile.in|config*|README)" 0 EXTMATCH
+C		"shell.c"		"!(*.c|*.h|Makefile.in|config*|README)" NOMATCH EXTMATCH
+C		"Makefile"		"!(*.c|*.h|Makefile.in|config*|README)" 0 EXTMATCH
+C		"VMS.FILE;1"		"*\;[1-9]*([0-9])"     0       EXTMATCH
+C		"VMS.FILE;0"		"*\;[1-9]*([0-9])"     NOMATCH EXTMATCH
+C		"VMS.FILE;"		"*\;[1-9]*([0-9])"     NOMATCH EXTMATCH
+C		"VMS.FILE;139"		"*\;[1-9]*([0-9])"     0       EXTMATCH
+C		"VMS.FILE;1N"		"*\;[1-9]*([0-9])"     NOMATCH EXTMATCH
+C		"abcfefg"		"ab**(e|f)"	       0       EXTMATCH
+C		"abcfefg"		"ab**(e|f)g"	       0       EXTMATCH
+C		"ab"			"ab*+(e|f)"	       NOMATCH EXTMATCH
+C		"abef"			"ab***ef"	       0       EXTMATCH
+C		"abef"			"ab**"		       0       EXTMATCH
+C		"fofo"			"*(f*(o))"	       0       EXTMATCH
+C		"ffo"			"*(f*(o))"	       0       EXTMATCH
+C		"foooofo"		"*(f*(o))"	       0       EXTMATCH
+C		"foooofof"		"*(f*(o))"	       0       EXTMATCH
+C		"fooofoofofooo"		"*(f*(o))"	       0       EXTMATCH
+C		"foooofof"		"*(f+(o))"	       NOMATCH EXTMATCH
+C		"xfoooofof"		"*(f*(o))"	       NOMATCH EXTMATCH
+C		"foooofofx"		"*(f*(o))"	       NOMATCH EXTMATCH
+C		"ofxoofxo"		"*(*(of*(o)x)o)"       0       EXTMATCH
+C		"ofooofoofofooo"	"*(f*(o))"	       NOMATCH EXTMATCH
+C		"foooxfooxfoxfooox"	"*(f*(o)x)"	       0       EXTMATCH
+C		"foooxfooxofoxfooox"	"*(f*(o)x)"	       NOMATCH EXTMATCH
+C		"foooxfooxfxfooox"	"*(f*(o)x)"	       0       EXTMATCH
+C		"ofxoofxo"		"*(*(of*(o)x)o)"       0       EXTMATCH
+C		"ofoooxoofxo"		"*(*(of*(o)x)o)"       0       EXTMATCH
+C		"ofoooxoofxoofoooxoofxo" "*(*(of*(o)x)o)"      0       EXTMATCH
+C		"ofoooxoofxoofoooxoofxoo" "*(*(of*(o)x)o)"     0       EXTMATCH
+C		"ofoooxoofxoofoooxoofxofo" "*(*(of*(o)x)o)"    NOMATCH EXTMATCH
+C		"ofoooxoofxoofoooxoofxooofxofxo" "*(*(of*(o)x)o)" 0    EXTMATCH
+C		"aac"			"*(@(a))a@(c)"	       0       EXTMATCH
+C		"ac"			"*(@(a))a@(c)"	       0       EXTMATCH
+C		"c"			"*(@(a))a@(c)"	       NOMATCH EXTMATCH
+C		"aaac"			"*(@(a))a@(c)"	       0       EXTMATCH
+C		"baaac"			"*(@(a))a@(c)"	       NOMATCH EXTMATCH
+C		"abcd"			"?@(a|b)*@(c)d"	       0       EXTMATCH
+C		"abcd"			"@(ab|a*@(b))*(c)d"    0       EXTMATCH
+C		"acd"			"@(ab|a*(b))*(c)d"     0       EXTMATCH
+C		"abbcd"			"@(ab|a*(b))*(c)d"     0       EXTMATCH
+C		"effgz"			"@(b+(c)d|e*(f)g?|?(h)i@(j|k))" 0 EXTMATCH
+C		"efgz"			"@(b+(c)d|e*(f)g?|?(h)i@(j|k))" 0 EXTMATCH
+C		"egz"			"@(b+(c)d|e*(f)g?|?(h)i@(j|k))" 0 EXTMATCH
+C		"egzefffgzbcdij"	"*(b+(c)d|e*(f)g?|?(h)i@(j|k))" 0 EXTMATCH
+C		"egz"			"@(b+(c)d|e+(f)g?|?(h)i@(j|k))" NOMATCH EXTMATCH
+C		"ofoofo"		"*(of+(o))"	       0       EXTMATCH
+C		"oxfoxoxfox"		"*(oxf+(ox))"	       0       EXTMATCH
+C		"oxfoxfox"		"*(oxf+(ox))"	       NOMATCH EXTMATCH
+C		"ofoofo"		"*(of+(o)|f)"	       0       EXTMATCH
+C		"foofoofo"		"@(foo|f|fo)*(f|of+(o))" 0     EXTMATCH
+C		"oofooofo"		"*(of|oof+(o))"	       0       EXTMATCH
+C		"fffooofoooooffoofffooofff" "*(*(f)*(o))"      0       EXTMATCH
+C		"fofoofoofofoo"		"*(fo|foo)"	       0       EXTMATCH
+C		"foo"			"!(x)"		       0       EXTMATCH
+C		"foo"			"!(x)*"		       0       EXTMATCH
+C		"foo"			"!(foo)"	       NOMATCH EXTMATCH
+C		"foo"			"!(foo)*"	       0       EXTMATCH
+C		"foobar"		"!(foo)"	       0       EXTMATCH
+C		"foobar"		"!(foo)*"	       0       EXTMATCH
+C		"moo.cow"		"!(*.*).!(*.*)"	       0       EXTMATCH
+C		"mad.moo.cow"		"!(*.*).!(*.*)"	       NOMATCH EXTMATCH
+C		"mucca.pazza"		"mu!(*(c))?.pa!(*(z))?" NOMATCH EXTMATCH
+C		"fff"			"!(f)"		       0       EXTMATCH
+C		"fff"			"*(!(f))"	       0       EXTMATCH
+C		"fff"			"+(!(f))"	       0       EXTMATCH
+C		"ooo"			"!(f)"		       0       EXTMATCH
+C		"ooo"			"*(!(f))"	       0       EXTMATCH
+C		"ooo"			"+(!(f))"	       0       EXTMATCH
+C		"foo"			"!(f)"		       0       EXTMATCH
+C		"foo"			"*(!(f))"	       0       EXTMATCH
+C		"foo"			"+(!(f))"	       0       EXTMATCH
+C		"f"			"!(f)"		       NOMATCH EXTMATCH
+C		"f"			"*(!(f))"	       NOMATCH EXTMATCH
+C		"f"			"+(!(f))"	       NOMATCH EXTMATCH
+C		"foot"			"@(!(z*)|*x)"	       0       EXTMATCH
+C		"zoot"			"@(!(z*)|*x)"	       NOMATCH EXTMATCH
+C		"foox"			"@(!(z*)|*x)"	       0       EXTMATCH
+C		"zoox"			"@(!(z*)|*x)"	       0       EXTMATCH
+C		"foo"			"*(!(foo))	       0       EXTMATCH
+C		"foob"			"!(foo)b*"	       NOMATCH EXTMATCH
+C		"foobb"			"!(foo)b*"	       0       EXTMATCH
+C		"["			"*([a[])"	       0       EXTMATCH
+C		"]"			"*([]a[])"	       0       EXTMATCH
+C		"a"			"*([]a[])"	       0       EXTMATCH
+C		"b"			"*([!]a[])"	       0       EXTMATCH
+C		"["			"*([!]a[]|[[])"	       0       EXTMATCH
+C		"]"			"*([!]a[]|[]])"	       0       EXTMATCH
+C		"["			"!([!]a[])"	       0       EXTMATCH
+C		"]"			"!([!]a[])"	       0       EXTMATCH
+C		")"			"*([)])"	       0       EXTMATCH
+C		"*"			"*([*(])"	       0       EXTMATCH
+C		"abcd"			"*!(|a)cd"	       0       EXTMATCH
+C		"ab/.a"			"+([abc])/*"	       NOMATCH EXTMATCH|PATHNAME|PERIOD
+C		""			""		       0
+C		""			""		       0       EXTMATCH
+C		""			"*([abc])"	       0       EXTMATCH
+C		""			"?([abc])"	       0       EXTMATCH
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/misc/tst-gnuglob.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/misc/tst-gnuglob.c
new file mode 100644
index 00000000..04c6743e
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/misc/tst-gnuglob.c
@@ -0,0 +1,447 @@
+/* Test the GNU extensions in glob which allow the user to provide callbacks
+   for the filesystem access functions.
+   Copyright (C) 2001-2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2001.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+// #define DEBUG
+#ifdef DEBUG
+# define PRINTF(fmt, args...) printf (fmt, ##args)
+#else
+# define PRINTF(fmt, args...)
+#endif
+
+
+#ifdef GLOB_ALTDIRFUNC
+static struct
+{
+  const char *name;
+  int level;
+  int type;
+} filesystem[] =
+{
+  { ".", 1, DT_DIR },
+  { "..", 1, DT_DIR },
+  { "file1lev1", 1, DT_REG },
+  { "file2lev1", 1, DT_UNKNOWN },
+  { "dir1lev1", 1, DT_UNKNOWN },
+    { ".", 2, DT_DIR },
+    { "..", 2, DT_DIR },
+    { "file1lev2", 2, DT_REG },
+    { "dir1lev2", 2, DT_DIR },
+      { ".", 3, DT_DIR },
+      { "..", 3, DT_DIR },
+    { "dir2lev2", 2, DT_DIR },
+      { ".", 3, DT_DIR },
+      { "..", 3, DT_DIR },
+      { ".foo", 3, DT_REG },
+      { "dir1lev3", 3, DT_DIR },
+        { ".", 4, DT_DIR },
+        { "..", 4, DT_DIR },
+        { "file1lev4", 4, DT_REG },
+      { "file1lev3", 3, DT_REG },
+      { "file2lev3", 3, DT_REG },
+    { "file2lev2", 2, DT_REG },
+    { "file3lev2", 2, DT_REG },
+    { "dir3lev2", 2, DT_DIR },
+      { ".", 3, DT_DIR },
+      { "..", 3, DT_DIR },
+      { "file3lev3", 3, DT_REG },
+      { "file4lev3", 3, DT_REG },
+  { "dir2lev1", 1, DT_DIR },
+    { ".", 2, DT_DIR },
+    { "..", 2, DT_DIR },
+    { "dir1lev2", 2, DT_UNKNOWN },
+      { ".", 3, DT_DIR },
+      { "..", 3, DT_DIR },
+      { ".foo", 3, DT_REG },
+      { ".dir", 3, DT_DIR },
+        { ".", 4, DT_DIR },
+        { "..", 4, DT_DIR },
+        { "hidden", 4, DT_REG }
+};
+#define nfiles (sizeof (filesystem) / sizeof (filesystem[0]))
+
+
+typedef struct
+{
+  int level;
+  int idx;
+  struct dirent d;
+  char room_for_dirent[NAME_MAX];
+} my_DIR;
+
+
+static long int
+find_file (const char *s)
+{
+  int level = 1;
+  long int idx = 0;
+
+  if (strcmp (s, ".") == 0)
+    return 0;
+
+  if (s[0] == '.' && s[1] == '/')
+    s += 2;
+
+  while (*s != '\0')
+    {
+      char *endp = strchrnul (s, '/');
+
+      PRINTF ("looking for %.*s, level %d\n", (int) (endp - s), s, level);
+
+      while (idx < nfiles && filesystem[idx].level >= level)
+	{
+	  if (filesystem[idx].level == level
+	      && memcmp (s, filesystem[idx].name, endp - s) == 0
+	      && filesystem[idx].name[endp - s] == '\0')
+	    break;
+	  ++idx;
+	}
+
+      if (idx == nfiles || filesystem[idx].level < level)
+	{
+	  errno = ENOENT;
+	  return -1;
+	}
+
+      if (*endp == '\0')
+	return idx + 1;
+
+      if (filesystem[idx].type != DT_DIR
+	  && (idx + 1 >= nfiles
+	      || filesystem[idx].level >= filesystem[idx + 1].level))
+	{
+	  errno = ENOTDIR;
+	  return -1;
+	}
+
+      ++idx;
+
+      s = endp + 1;
+      ++level;
+    }
+
+  errno = ENOENT;
+  return -1;
+}
+
+
+static void *
+my_opendir (const char *s)
+{
+  long int idx = find_file (s);
+  my_DIR *dir;
+
+
+  if (idx == -1)
+    {
+      PRINTF ("my_opendir(\"%s\") == NULL\n", s);
+      return NULL;
+    }
+
+  dir = (my_DIR *) malloc (sizeof (my_DIR));
+  if (dir == NULL)
+    error (EXIT_FAILURE, errno, "cannot allocate directory handle");
+
+  dir->level = filesystem[idx].level;
+  dir->idx = idx;
+
+  PRINTF ("my_opendir(\"%s\") == { level: %d, idx: %ld }\n",
+	  s, filesystem[idx].level, idx);
+
+  return dir;
+}
+
+
+static struct dirent *
+my_readdir (void *gdir)
+{
+  my_DIR *dir = gdir;
+
+  if (dir->idx == -1)
+    {
+      PRINTF ("my_readdir ({ level: %d, idx: %ld }) = NULL\n",
+	      dir->level, (long int) dir->idx);
+      return NULL;
+    }
+
+  while (dir->idx < nfiles && filesystem[dir->idx].level > dir->level)
+    ++dir->idx;
+
+  if (dir->idx == nfiles || filesystem[dir->idx].level < dir->level)
+    {
+      dir->idx = -1;
+      PRINTF ("my_readdir ({ level: %d, idx: %ld }) = NULL\n",
+	      dir->level, (long int) dir->idx);
+      return NULL;
+    }
+
+  dir->d.d_ino = dir->idx;
+
+#ifdef _DIRENT_HAVE_D_TYPE
+  dir->d.d_type = filesystem[dir->idx].type;
+#endif
+
+  strcpy (dir->d.d_name, filesystem[dir->idx].name);
+
+#ifdef _DIRENT_HAVE_D_TYPE
+  PRINTF ("my_readdir ({ level: %d, idx: %ld }) = { d_ino: %ld, d_type: %d, d_name: \"%s\" }\n",
+	  dir->level, (long int) dir->idx, dir->d.d_ino, dir->d.d_type,
+	  dir->d.d_name);
+#else
+  PRINTF ("my_readdir ({ level: %d, idx: %ld }) = { d_ino: %ld, d_name: \"%s\" }\n",
+	  dir->level, (long int) dir->idx, dir->d.d_ino,
+	  dir->d.d_name);
+#endif
+
+  ++dir->idx;
+
+  return &dir->d;
+}
+
+
+static void
+my_closedir (void *dir)
+{
+  PRINTF ("my_closedir ()\n");
+  free (dir);
+}
+
+
+/* We use this function for lstat as well since we don't have any.  */
+static int
+my_stat (const char *name, struct stat *st)
+{
+  long int idx = find_file (name);
+
+  if (idx == -1)
+    {
+      PRINTF ("my_stat (\"%s\", ...) = -1 (%s)\n", name, strerror (errno));
+      return -1;
+    }
+
+  memset (st, '\0', sizeof (*st));
+
+  if (filesystem[idx].type == DT_UNKNOWN)
+    st->st_mode = DTTOIF (idx + 1 < nfiles
+			  && filesystem[idx].level < filesystem[idx + 1].level
+			  ? DT_DIR : DT_REG) | 0777;
+  else
+    st->st_mode = DTTOIF (filesystem[idx].type) | 0777;
+
+  PRINTF ("my_stat (\"%s\", { st_mode: %o }) = 0\n", name, st->st_mode);
+
+  return 0;
+}
+
+
+static const char *glob_errstring[] =
+{
+  [GLOB_NOSPACE] = "out of memory",
+  [GLOB_ABORTED] = "read error",
+  [GLOB_NOMATCH] = "no matches found"
+};
+#define nglob_errstring (sizeof (glob_errstring) / sizeof (glob_errstring[0]))
+
+
+static const char *
+flagstr (int flags)
+{
+  const char *strs[] =
+  {
+    "GLOB_ERR", "GLOB_MARK", "GLOB_NOSORT", "GLOB_DOOFSS", "GLOB_NOCHECK",
+    "GLOB_APPEND", "GLOB_NOESCAPE", "GLOB_PERIOD", "GLOB_MAGCHAR",
+    "GLOB_ALTDIRFUNC", "GLOB_BRACE", "GLOB_NOMAGIC", "GLOB_TILDE",
+    "GLOB_ONLYDIR", "GLOB_TILDECHECK"
+  };
+#define nstrs (sizeof (strs) / sizeof (strs[0]))
+  static char buf[100];
+  char *cp = buf;
+  int cnt;
+
+  for (cnt = 0; cnt < nstrs; ++cnt)
+    if (flags & (1 << cnt))
+      {
+	flags &= ~(1 << cnt);
+	if (cp != buf)
+	  *cp++ = '|';
+	cp = stpcpy (cp, strs[cnt]);
+      }
+
+  if (flags != 0)
+    {
+      if (cp != buf)
+	*cp++ = '|';
+      sprintf (cp, "%#x", flags);
+    }
+
+  return buf;
+}
+
+
+static int
+test_result (const char *fmt, int flags, glob_t *gl, const char *str[])
+{
+  size_t cnt;
+  int result = 0;
+
+  printf ("results for glob (\"%s\", %s)\n", fmt, flagstr (flags));
+  for (cnt = 0; cnt < gl->gl_pathc && str[cnt] != NULL; ++cnt)
+    {
+      int ok = strcmp (gl->gl_pathv[cnt], str[cnt]) == 0;
+      const char *errstr = "";
+
+      if (! ok)
+	{
+	  size_t inner;
+
+	  for (inner = 0; str[inner] != NULL; ++inner)
+	    if (strcmp (gl->gl_pathv[cnt], str[inner]) == 0)
+	      break;
+
+	  if (str[inner] == NULL)
+	    errstr =  ok ? "" : " *** WRONG";
+	  else
+	    errstr = ok ? "" : " * wrong position";
+
+	  result = 1;
+	}
+
+      printf ("  %s%s\n", gl->gl_pathv[cnt], errstr);
+    }
+  puts ("");
+
+  if (str[cnt] != NULL || cnt < gl->gl_pathc)
+    {
+      puts ("  *** incorrect number of entries");
+      result = 1;
+    }
+
+  return result;
+}
+
+
+int
+main (void)
+{
+  glob_t gl;
+  int errval;
+  int result = 0;
+  const char *fmt;
+  int flags;
+
+  memset (&gl, '\0', sizeof (gl));
+
+  gl.gl_closedir = my_closedir;
+  gl.gl_readdir = my_readdir;
+  gl.gl_opendir = my_opendir;
+  gl.gl_lstat = my_stat;
+  gl.gl_stat = my_stat;
+
+#define test(a, b, c...) \
+  fmt = a;								      \
+  flags = b;								      \
+  errval = glob (fmt, flags, NULL, &gl);				      \
+  if (errval != 0)							      \
+    {									      \
+      printf ("glob (\"%s\", %s) failed: %s\n", fmt, flagstr (flags),	      \
+	      errval >= 0 && errval < nglob_errstring			      \
+	      ? glob_errstring[errval] : "???");			      \
+      result = 1;							      \
+    }									      \
+  else									      \
+    result |= test_result (fmt, flags, &gl, (const char *[]) { c, NULL })
+
+  test ("*/*/*", GLOB_ALTDIRFUNC,
+	"dir1lev1/dir2lev2/dir1lev3",
+	"dir1lev1/dir2lev2/file1lev3",
+	"dir1lev1/dir2lev2/file2lev3",
+	"dir1lev1/dir3lev2/file3lev3",
+	"dir1lev1/dir3lev2/file4lev3");
+
+  test ("*/*/*", GLOB_ALTDIRFUNC | GLOB_PERIOD,
+	"dir1lev1/dir1lev2/.",
+	"dir1lev1/dir1lev2/..",
+	"dir1lev1/dir2lev2/.",
+	"dir1lev1/dir2lev2/..",
+	"dir1lev1/dir2lev2/.foo",
+	"dir1lev1/dir2lev2/dir1lev3",
+	"dir1lev1/dir2lev2/file1lev3",
+	"dir1lev1/dir2lev2/file2lev3",
+	"dir1lev1/dir3lev2/.",
+	"dir1lev1/dir3lev2/..",
+	"dir1lev1/dir3lev2/file3lev3",
+	"dir1lev1/dir3lev2/file4lev3",
+	"dir2lev1/dir1lev2/.",
+	"dir2lev1/dir1lev2/..",
+	"dir2lev1/dir1lev2/.dir",
+	"dir2lev1/dir1lev2/.foo");
+
+  test ("*/*/.*", GLOB_ALTDIRFUNC,
+	"dir1lev1/dir1lev2/.",
+	"dir1lev1/dir1lev2/..",
+	"dir1lev1/dir2lev2/.",
+	"dir1lev1/dir2lev2/..",
+	"dir1lev1/dir2lev2/.foo",
+	"dir1lev1/dir3lev2/.",
+	"dir1lev1/dir3lev2/..",
+	"dir2lev1/dir1lev2/.",
+	"dir2lev1/dir1lev2/..",
+	"dir2lev1/dir1lev2/.dir",
+	"dir2lev1/dir1lev2/.foo");
+
+  test ("*1*/*2*/.*", GLOB_ALTDIRFUNC,
+	"dir1lev1/dir1lev2/.",
+	"dir1lev1/dir1lev2/..",
+	"dir1lev1/dir2lev2/.",
+	"dir1lev1/dir2lev2/..",
+	"dir1lev1/dir2lev2/.foo",
+	"dir1lev1/dir3lev2/.",
+	"dir1lev1/dir3lev2/..",
+	"dir2lev1/dir1lev2/.",
+	"dir2lev1/dir1lev2/..",
+	"dir2lev1/dir1lev2/.dir",
+	"dir2lev1/dir1lev2/.foo");
+
+  test ("*1*/*1*/.*", GLOB_ALTDIRFUNC,
+	"dir1lev1/dir1lev2/.",
+	"dir1lev1/dir1lev2/..",
+	"dir2lev1/dir1lev2/.",
+	"dir2lev1/dir1lev2/..",
+	"dir2lev1/dir1lev2/.dir",
+	"dir2lev1/dir1lev2/.foo");
+
+  globfree (&gl);
+
+  return result;
+}
+
+#else
+int main(void) { return 0; }
+#endif
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/misc/tst-scandir.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/misc/tst-scandir.c
new file mode 100644
index 00000000..df62a40d
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/misc/tst-scandir.c
@@ -0,0 +1,23 @@
+#include 
+#include 
+#include  /* perror() */
+#include 
+
+int skip_all(const struct dirent *dirbuf)
+{
+	errno = EBADF;
+	return 0;
+}
+
+int main(void)
+{
+	struct dirent **namelist;
+	int n;
+
+	n = scandir(".", &namelist, skip_all, 0);
+	if (n < 0) {
+		perror("scandir");
+		return EXIT_FAILURE;
+	}
+	return EXIT_SUCCESS;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/misc/tst-seekdir.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/misc/tst-seekdir.c
new file mode 100644
index 00000000..7dd5d2e8
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/misc/tst-seekdir.c
@@ -0,0 +1,79 @@
+#include 
+#include 
+#include 
+#include 
+#include 
+
+int
+main (int argc, char *argv[])
+{
+  DIR * dirp;
+  long int save3 = 0;
+  long int cur;
+  int i = 0;
+  int result = 0;
+  struct dirent *dp;
+  off_t save0, rewind_ret;
+
+  dirp = opendir (".");
+  if (dirp == NULL)
+    {
+      printf ("opendir failed: %s\n", strerror(errno));
+      return 1;
+    }
+
+  save0 = telldir (dirp);
+  if (save0 == -1)
+    {
+      printf ("telldir failed: %s\n", strerror(errno));
+      result = 1;
+    }
+
+  for (dp = readdir (dirp); dp != NULL; dp = readdir (dirp))
+    {
+      /* save position 3 (after fourth entry) */
+      if (i++ == 3)
+	save3 = telldir (dirp);
+
+      printf ("%s\n", dp->d_name);
+
+      /* stop at 400 (just to make sure dirp->__offset and dirp->__size are
+	 scrambled */
+      if (i == 400)
+	break;
+    }
+
+  printf ("going back past 4-th entry...\n");
+
+  /* go back to saved entry */
+  seekdir (dirp, save3);
+
+  /* Check whether telldir equals to save3 now.  */
+  cur = telldir (dirp);
+  if (cur != save3)
+    {
+      printf ("seekdir (d, %ld); telldir (d) == %ld\n", save3, cur);
+      result = 1;
+    }
+
+  /* print remaining files (3-last) */
+  for (dp = readdir (dirp); dp != NULL; dp = readdir (dirp))
+    printf ("%s\n", dp->d_name);
+
+  /* Check rewinddir */
+  rewinddir (dirp);
+  rewind_ret = telldir (dirp);
+  if (rewind_ret == -1)
+    {
+      printf ("telldir failed: %s\n", strerror(errno));
+      result = 1;
+    }
+  else if (save0 != rewind_ret)
+    {
+      printf ("rewinddir didn't reset directory stream\n");
+      result = 1;
+    }
+
+  closedir (dirp);
+  return result;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/misc/tst-utmp.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/misc/tst-utmp.c
new file mode 100644
index 00000000..06ba1409
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/misc/tst-utmp.c
@@ -0,0 +1,404 @@
+/* Tests for UTMP functions.
+   Copyright (C) 1998, 2001-2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Mark Kettenis , 1998.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#ifdef UTMPX
+# include 
+# define utmp utmpx
+# define utmpname utmpxname
+# define setutent setutxent
+# define getutent getutxent
+# define endutent endutxent
+# define getutline getutxline
+# define getutid getutxid
+# define pututline pututxline
+#else
+# include 
+#endif
+
+
+#if _HAVE_UT_TYPE || defined UTMPX
+
+/* Prototype for our test function.  */
+static int do_test (int argc, char *argv[]);
+
+/* We have a preparation function.  */
+static void do_prepare (int argc, char *argv[]);
+#define PREPARE do_prepare
+
+/* This defines the `main' function and some more.  */
+#include "../test-skeleton.c"
+
+
+/* These are for the temporary file we generate.  */
+char *name;
+int fd;
+
+static void
+do_prepare (int argc, char *argv[])
+{
+  size_t name_len;
+
+  name_len = strlen (test_dir);
+  name = malloc (name_len + sizeof ("/utmpXXXXXX"));
+  mempcpy (mempcpy (name, test_dir, name_len),
+	   "/utmpXXXXXX", sizeof ("/utmpXXXXXX"));
+  add_temp_file (name);
+
+  /* Open our test file.  */
+  fd = mkstemp (name);
+  if (fd == -1)
+    error (EXIT_FAILURE, errno, "cannot open test file `%s'", name);
+}
+
+struct utmp entry[] =
+{
+#if _HAVE_UT_TV || defined UTMPX
+#define UT(a)  .ut_tv = { .tv_sec = (a)}
+#else
+#define UT(a)  .ut_time = (a)
+#endif
+
+  { .ut_type = BOOT_TIME, .ut_pid = 1, UT(1000) },
+  { .ut_type = RUN_LVL, .ut_pid = 1, UT(2000) },
+  { .ut_type = INIT_PROCESS, .ut_pid = 5, .ut_id = "si", UT(3000) },
+  { .ut_type = LOGIN_PROCESS, .ut_pid = 23, .ut_line = "tty1", .ut_id = "1",
+    .ut_user = "LOGIN", UT(4000) },
+  { .ut_type = USER_PROCESS, .ut_pid = 24, .ut_line = "tty2", .ut_id = "2",
+    .ut_user = "albert", UT(8000) },
+  { .ut_type = USER_PROCESS, .ut_pid = 196, .ut_line = "ttyp0", .ut_id = "p0",
+    .ut_user = "niels", UT(10000) },
+  { .ut_type = DEAD_PROCESS, .ut_line = "ttyp1", .ut_id = "p1", UT(16000) },
+  { .ut_type = EMPTY },
+  { .ut_type = EMPTY }
+};
+int num_entries = sizeof entry / sizeof (struct utmp);
+
+time_t entry_time = 20000;
+pid_t entry_pid = 234;
+
+static int
+do_init (void)
+{
+  int n;
+
+  setutent ();
+
+  for (n = 0; n < num_entries; n++)
+    {
+      if (pututline (&entry[n]) == NULL)
+	{
+	  error (0, errno, "cannot write UTMP entry");
+	  return 1;
+	}
+    }
+
+  endutent ();
+
+  return 0;
+}
+
+
+static int
+do_check (void)
+{
+  struct utmp *ut;
+  int n;
+
+  setutent ();
+
+  n = 0;
+  while ((ut = getutent ()))
+    {
+      if (n < num_entries &&
+	  memcmp (ut, &entry[n], sizeof (struct utmp)))
+	{
+	  error (0, 0, "UTMP entry does not match");
+	  return 1;
+	}
+
+      n++;
+    }
+
+  if (n != num_entries)
+    {
+      error (0, 0, "number of UTMP entries is incorrect");
+      return 1;
+    }
+
+  endutent ();
+
+  return 0;
+}
+
+static int
+simulate_login (const char *line, const char *user)
+{
+  int n;
+
+  for (n = 0; n < num_entries; n++)
+    {
+      if (strcmp (line, entry[n].ut_line) == 0 ||
+	  entry[n].ut_type == DEAD_PROCESS)
+	{
+	  if (entry[n].ut_pid == DEAD_PROCESS)
+	    entry[n].ut_pid = (entry_pid += 27);
+	  entry[n].ut_type = USER_PROCESS;
+	  strncpy (entry[n].ut_user, user, sizeof (entry[n].ut_user));
+#if _HAVE_UT_TV - 0 || defined UTMPX
+	  entry[n].ut_tv.tv_sec = (entry_time += 1000);
+#else
+          entry[n].ut_time = (entry_time += 1000);
+#endif
+	  setutent ();
+
+	  if (pututline (&entry[n]) == NULL)
+	    {
+	      error (0, errno, "cannot write UTMP entry");
+	      return 1;
+	    }
+
+	  endutent ();
+
+	  return 0;
+	}
+    }
+
+  error (0, 0, "no entries available");
+  return 1;
+}
+
+static int
+simulate_logout (const char *line)
+{
+  int n;
+
+  for (n = 0; n < num_entries; n++)
+    {
+      if (strcmp (line, entry[n].ut_line) == 0)
+	{
+	  entry[n].ut_type = DEAD_PROCESS;
+	  strncpy (entry[n].ut_user, "", sizeof (entry[n].ut_user));
+#if _HAVE_UT_TV - 0 || defined UTMPX
+          entry[n].ut_tv.tv_sec = (entry_time += 1000);
+#else
+          entry[n].ut_time = (entry_time += 1000);
+#endif
+	  setutent ();
+
+	  if (pututline (&entry[n]) == NULL)
+	    {
+	      error (0, errno, "cannot write UTMP entry");
+	      return 1;
+	    }
+
+	  endutent ();
+
+	  return 0;
+	}
+    }
+
+  error (0, 0, "no entry found for `%s'", line);
+  return 1;
+}
+
+static int
+check_login (const char *line)
+{
+  struct utmp *up;
+  struct utmp ut;
+  int n;
+
+  setutent ();
+
+  strcpy (ut.ut_line, line);
+  up = getutline (&ut);
+  if (up == NULL)
+    {
+      error (0, errno, "cannot get entry for line `%s'", line);
+      return 1;
+    }
+
+  endutent ();
+
+  for (n = 0; n < num_entries; n++)
+    {
+      if (strcmp (line, entry[n].ut_line) == 0)
+	{
+	  if (memcmp (up, &entry[n], sizeof (struct utmp)))
+	    {
+	      error (0, 0, "UTMP entry does not match");
+	      return 1;
+	    }
+
+	  return 0;
+	}
+    }
+
+  error (0, 0, "bogus entry for line `%s'", line);
+  return 1;
+}
+
+static int
+check_logout (const char *line)
+{
+  struct utmp ut;
+
+  setutent ();
+
+  strcpy (ut.ut_line, line);
+  if (getutline (&ut) != NULL)
+    {
+      error (0, 0, "bogus login entry for `%s'", line);
+      return 1;
+    }
+
+  endutent ();
+
+  return 0;
+}
+
+static int
+check_id (const char *id)
+{
+  struct utmp *up;
+  struct utmp ut;
+  int n;
+
+  setutent ();
+
+  ut.ut_type = USER_PROCESS;
+  strcpy (ut.ut_id, id);
+  up = getutid (&ut);
+  if (up == NULL)
+    {
+      error (0, errno, "cannot get entry for ID `%s'", id);
+      return 1;
+    }
+
+  endutent ();
+
+  for (n = 0; n < num_entries; n++)
+    {
+      if (strcmp (id, entry[n].ut_id) == 0)
+	{
+	  if (memcmp (up, &entry[n], sizeof (struct utmp)))
+	    {
+	      error (0, 0, "UTMP entry does not match");
+	      return 1;
+	    }
+
+	  return 0;
+	}
+    }
+
+  error (0, 0, "bogus entry for ID `%s'", id);
+  return 1;
+}
+
+static int
+check_type (int type)
+{
+  struct utmp *up;
+  struct utmp ut;
+  int n;
+
+  setutent ();
+
+  ut.ut_type = type;
+  up = getutid (&ut);
+  if (up == NULL)
+    {
+      error (0, errno, "cannot get entry for type `%d'", type);
+      return 1;
+    }
+
+  endutent ();
+
+  for (n = 0; n < num_entries; n++)
+    {
+      if (type == entry[n].ut_type)
+	{
+	  if (memcmp (up, &entry[n], sizeof (struct utmp)))
+	    {
+	      error (0, 0, "UTMP entry does not match");
+	      return 1;
+	    }
+
+	  return 0;
+	}
+    }
+
+  error (0, 0, "bogus entry for type `%d'", type);
+  return 1;
+}
+
+static int
+do_test (int argc, char *argv[])
+{
+  int result = 0;
+
+  utmpname (name);
+
+  result |= do_init ();
+  result |= do_check ();
+
+  result |= simulate_login ("tty1", "erwin");
+  result |= do_check ();
+
+  result |= simulate_login ("ttyp1", "paul");
+  result |= do_check ();
+
+  result |= simulate_logout ("tty2");
+  result |= do_check ();
+
+  result |= simulate_logout ("ttyp0");
+  result |= do_check ();
+
+  result |= simulate_login ("ttyp2", "richard");
+  result |= do_check ();
+
+  result |= check_login ("tty1");
+  result |= check_logout ("ttyp0");
+  result |= check_id ("p1");
+  result |= check_id ("2");
+  result |= check_id ("si");
+  result |= check_type (BOOT_TIME);
+  result |= check_type (RUN_LVL);
+
+  return result;
+}
+
+#else
+
+/* No field 'ut_type' in struct utmp.  */
+int
+main ()
+{
+  return 0;
+}
+
+#endif
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/mmap/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/test/mmap/Makefile
new file mode 100644
index 00000000..64b652de
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/mmap/Makefile
@@ -0,0 +1,7 @@
+# uClibc mmap tests
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+
+top_builddir=../../
+include ../Rules.mak
+-include Makefile.in
+include ../Test.mak
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/mmap/mmap.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/mmap/mmap.c
new file mode 100644
index 00000000..8b29737a
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/mmap/mmap.c
@@ -0,0 +1,73 @@
+
+/* The mmap test is useful, since syscalls with 6 arguments
+ * (as mmap) are done differently on various architectures.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define SIZEOF_ARRAY(type) (sizeof(type)/sizeof(*type))
+
+struct mmap_test {
+	void *ret;
+	int err;
+	struct {
+		void *start;
+		size_t length;
+		int prot;
+		int flags;
+		int fd;
+		off_t offset;
+	} args;
+};
+
+struct mmap_test tests[] = {
+	[0] {
+		.err = 0,
+		.args.start = NULL,
+		.args.length = 4096,
+		.args.prot = PROT_READ|PROT_WRITE,
+		.args.flags = MAP_PRIVATE|MAP_ANONYMOUS,
+		.args.fd = 0,
+		.args.offset = 0
+	},
+};
+
+#define err(fmt, args...) \
+	do { \
+		fprintf(stderr, fmt "\n" , ## args); \
+		exit(1); \
+	} while (0)
+#define errp(fmt, args...) err(fmt ": %s" , ## args , strerror(errno))
+
+int main(int argc, char **argv)
+{
+	int i;
+	struct mmap_test *t;
+
+	for (i=0; iret = mmap(t->args.start, t->args.length, t->args.prot,
+		              t->args.flags, t->args.fd, t->args.offset);
+
+		if (t->err) {
+			if (t->ret != MAP_FAILED)
+				err("mmap test %i should have failed, but gave us %p", i, t->ret);
+			else if (t->err != errno)
+				errp("mmap test %i failed, but gave us wrong errno (got %i instead of %i)", i, errno, t->err);
+		} else {
+			if (t->ret == MAP_FAILED)
+				errp("mmap test %i failed", i);
+			else if (munmap(t->ret, t->args.length) != 0)
+				errp("munmap test %i failed", i);
+		}
+	}
+
+	exit(0);
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/mmap/mmap2.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/mmap/mmap2.c
new file mode 100644
index 00000000..b9a8f9ac
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/mmap/mmap2.c
@@ -0,0 +1,41 @@
+/* When trying to map /dev/mem with offset 0xFFFFF000 on the ARM platform, mmap
+ * returns -EOVERFLOW.
+ *
+ * Since off_t is defined as a long int and the sign bit is set in the address,
+ * the shift operation shifts in ones instead of zeroes
+ * from the left. This results the offset sent to the kernel function becomes
+ * 0xFFFFFFFF instead of 0x000FFFFF with MMAP2_PAGE_SHIFT set to 12.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define FATAL do { fprintf(stderr, "Error at line %d, file %s (%d) [%s]\n", \
+  __LINE__, __FILE__, errno, strerror(errno)); exit(1); } while(0)
+
+#define MAP_SIZE 4096UL
+#define MAP_MASK (MAP_SIZE - 1)
+
+int main(int argc, char **argv) {
+    void* map_base = 0;
+    int fd;
+    off_t target = 0xfffff000;
+    if((fd = open("/dev/mem", O_RDWR | O_SYNC)) == -1) FATAL;
+    printf("/dev/mem opened.\n");
+    fflush(stdout);
+
+   /* Map one page */
+    map_base = mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED,
+                        fd, target & ~MAP_MASK);
+    if(map_base == (void *) -1) FATAL;
+    printf("Memory mapped at address %p.\n", map_base);
+    fflush(stdout);
+    if(munmap(map_base, MAP_SIZE) == -1) FATAL;
+    close(fd);
+    return 0;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/mmap/mmap64.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/mmap/mmap64.c
new file mode 100644
index 00000000..87165fe2
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/mmap/mmap64.c
@@ -0,0 +1,29 @@
+
+/* The mmap test is useful, since syscalls with 6 arguments
+ * (as mmap) are done differently on various architectures.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+int main(int argc, char **argv)
+{
+#ifdef __UCLIBC_HAS_LFS__
+	void *ptr;
+
+	ptr = mmap64(NULL, 4096, PROT_READ|PROT_WRITE,
+		MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
+
+	if (ptr == MAP_FAILED) {
+		perror("mmap");
+		exit(1);
+	}
+	printf("mmap returned %p\n", ptr);
+	exit(0);
+#else
+	exit(0);
+#endif
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/Makefile
new file mode 100644
index 00000000..c22b635b
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/Makefile
@@ -0,0 +1,8 @@
+# uClibc NPTL tests
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+
+top_builddir=../../
+top_srcdir=../../
+include ../Rules.mak
+-include Makefile.in
+include ../Test.mak
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/Makefile.in
new file mode 100644
index 00000000..b6a279eb
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/Makefile.in
@@ -0,0 +1,229 @@
+# uClibc NPTL tests
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+
+TESTS := tst-align tst-align2 tst-atfork1 tst-attr1 tst-attr2 tst-attr3	\
+	tst-barrier1 tst-barrier2 tst-barrier3 tst-barrier4 tst-basic1	\
+	tst-basic2 tst-basic3 tst-basic4 tst-basic5 tst-basic6		\
+	tst-cancel1 tst-cancel2 tst-cancel3 tst-cancel6 tst-cancel7	\
+	tst-cancel8 tst-cancel9 tst-cancel10 tst-cancel11 tst-cancel12	\
+	tst-cancel13 tst-cancel14 tst-cancel15 tst-cancel16		\
+	tst-cancel19 tst-cancel20 tst-cancel21 tst-cancel22		\
+	tst-cleanup0 tst-cleanup1 tst-cleanup2 tst-cleanup3		\
+	tst-cleanup4 tst-clock1 tst-clock2 tst-cond1 tst-cond2		\
+	tst-cond3 tst-cond4 tst-cond5 tst-cond6 tst-cond7 tst-cond8	\
+	tst-cond9 tst-cond10 tst-cond11 tst-cond12 tst-cond13		\
+	tst-cond14 tst-cond15 tst-cond16 tst-cond17 tst-cond18		\
+	tst-cond19 tst-cond20 tst-cond21 tst-detach1 tst-eintr1		\
+	tst-eintr2 tst-eintr3 tst-eintr4 tst-eintr5 tst-exec2 tst-exec3	\
+	tst-exec4 tst-exit1 tst-exit2 tst-exit3 tst-flock1 tst-flock2	\
+	tst-fork1 tst-fork2 tst-fork3 tst-fork4 tst-initializers1	\
+	tst-join1 tst-join2 tst-join3 tst-join4 tst-join5 tst-key1	\
+	tst-key2 tst-key3 tst-key4 tst-kill1 tst-kill2 tst-kill3	\
+	tst-kill4 tst-kill5 tst-kill6 tst-mutex1 tst-mutex2 tst-mutex3	\
+	tst-mutex4 tst-mutex5 tst-mutex6 tst-mutex7 tst-mutex8		\
+	tst-mutex9 tst-mutex5a tst-mutex7a tst-once1 tst-once2		\
+	tst-once3 tst-once4 tst-popen1 tst-raise1 tst-rwlock1		\
+	tst-rwlock2 tst-rwlock3 tst-rwlock4 tst-rwlock5 tst-rwlock6	\
+	tst-rwlock7 tst-rwlock8 tst-rwlock9 tst-rwlock10 tst-rwlock11	\
+	tst-rwlock12 tst-rwlock13 tst-rwlock14 tst-sched1 tst-sem1	\
+	tst-sem2 tst-sem3 tst-sem4 tst-sem5 tst-sem6 tst-sem7 tst-sem8	\
+	tst-sem9 tst-signal1 tst-signal2 tst-signal3 tst-signal4	\
+	tst-signal5 tst-signal6 tst-spin1 tst-spin2 tst-spin3		\
+	tst-stack1 tst-stack2 tst-stdio1 tst-stdio2 tst-sysconf		\
+	tst-tls1 tst-tls2 tst-tls3 tst-tls4 tst-tls5 tst-tsd1 tst-tsd2	\
+	tst-tsd3 tst-tsd4 tst-tsd5 tst-umask1 \
+	tst-align3 tst-cancel4 tst-cancel5 tst-cancel18 tst-cancel23 \
+	tst-cancel25 tst-cancelx2 tst-cancelx3 tst-cancelx4 tst-cancelx6 \
+	tst-cancelx7 tst-cancelx8 tst-cancelx9 tst-cancelx10 tst-cancelx11 \
+	tst-cancelx12 tst-cancelx13 tst-cancelx14 tst-cancelx15 tst-cancelx16 \
+	tst-cancelx18 tst-cancelx20 tst-cancelx21 tst-cleanupx0 tst-cleanupx1 \
+	tst-cleanupx2 tst-cleanupx3 tst-cleanupx4 tst-cond22 tst-cond23 \
+	tst-dlsym1 tst-getpid1 tst-getpid2 tst-getpid3 tst-join6 tst-tsd6 \
+	tst-oddstacklimit tst-oncex3 tst-oncex4 tst-rwlock2a  \
+	tst-basic7 tst-fini1 tst-signal7 \
+	tst-unload tst-vfork1x tst-vfork2x tst-sem10 tst-sem11 tst-sem12 \
+	tst-typesizes tst-initializers1-c89 tst-initializers1-c99 \
+	tst-initializers1-gnu89 tst-initializers1-gnu99
+
+#
+# These are for the RT library and POSIX timers.
+#
+TESTS += tst-clock tst-clock_nanosleep tst-cpuclock1 tst-cpuclock2	\
+	tst-cputimer1 tst-cputimer2 tst-cputimer3 tst-mqueue1		\
+	tst-mqueue2 tst-mqueue3 tst-mqueue4 tst-mqueue5 tst-mqueue6	\
+	tst-mqueue7 tst-mqueue8 tst-mqueue9 tst-timer2 tst-timer3	\
+	tst-timer4 tst-timer5
+
+ifeq ($(UCLIBC_HAS_OBSOLETE_BSD_SIGNAL),)
+TESTS_DISABLED += tst-exec2 tst-exec3 tst-exec4
+endif
+
+ifeq ($(UCLIBC_SUSV4_LEGACY),)
+TESTS_DISABLED += tst-basic5
+endif
+
+GLIBC_TESTS_DISABLED := tst-eintr1_glibc tst-eintr2_glibc \
+	tst-eintr3_glibc tst-eintr4_glibc tst-eintr5_glibc \
+	tst-tls1_glibc tst-tls2_glibc
+
+
+ifeq ($(HAVE_SHARED),)
+TESTS_DISABLED += tst-tls3 tst-tls4 tst-tls5
+else
+GLIBC_TESTS_DISABLED += tst-tls3_glibc tst-tls4_glibc tst-tls5_glibc
+endif
+
+PTDIR := $(top_builddir)libpthread/nptl
+SYSDEPS_DIR := $(top_srcdir)libc/sysdeps
+
+EXTRA_CFLAGS := -DNOT_IN_libc=1 -D_LIBC -D__USE_GNU -std=gnu99 \
+	-I$(SYSDEPS_DIR)/linux \
+	-I$(SYSDEPS_DIR)/linux/$(TARGET_ARCH) \
+	-I$(PTDIR) -I$(PTDIR)/sysdeps/unix/sysv/linux/$(TARGET_ARCH)	\
+	-I$(PTDIR)/sysdeps/$(TARGET_ARCH)				\
+	-I$(PTDIR)/sysdeps/unix/sysv/linux				\
+	-I$(PTDIR)/sysdeps/pthread					\
+	-I$(PTDIR)/sysdeps/pthread/bits					\
+	-I$(PTDIR)/sysdeps/generic					\
+	-I$(top_builddir)ldso/include					\
+	-I$(top_builddir)ldso/ldso/$(TARGET_ARCH)			\
+	-I$(top_builddir)include					\
+	-include $(top_builddir)include/libc-symbols.h
+
+ifeq ($(TARGET_ARCH),i386)
+CFLAGS_tst-align := -malign-double -mpreferred-stack-boundary=4
+endif
+ifeq ($(TARGET_ARCH),i686)
+CFLAGS_tst-align := -malign-double -mpreferred-stack-boundary=4 -msse
+endif
+CFLAGS_tst-cleanup4aux.o := -W
+CFLAGS_tst-initializers1 := -W -Werror
+CFLAGS_tst-tls3mod.so := -fPIC -DPIC -DSHARED -shared -DNOT_IN_libc
+CFLAGS_tst-tls4moda.so := -fPIC -DPIC -DSHARED -shared -DNOT_IN_libc
+CFLAGS_tst-tls4modb.so := -fPIC -DPIC -DSHARED -shared -DNOT_IN_libc
+CFLAGS_tst-tls5mod.so := -fPIC -DPIC -DSHARED -shared -DNOT_IN_libc
+CFLAGS_tst-tls5moda.so := -fPIC -DPIC -DSHARED -shared -DNOT_IN_libc
+CFLAGS_tst-tls5modb.so := -fPIC -DPIC -DSHARED -shared -DNOT_IN_libc
+CFLAGS_tst-tls5modc.so := -fPIC -DPIC -DSHARED -shared -DNOT_IN_libc
+CFLAGS_tst-tls5modd.so := -fPIC -DPIC -DSHARED -shared -DNOT_IN_libc
+CFLAGS_tst-tls5mode.so := -fPIC -DPIC -DSHARED -shared -DNOT_IN_libc
+CFLAGS_tst-tls5modf.so := -fPIC -DPIC -DSHARED -shared -DNOT_IN_libc
+
+CFLAGS_tst-fini1mod.so := -fPIC -DPIC -DSHARED -shared -DNOT_IN_libc
+LDFLAGS_tst-cond11 = -lrt
+LDFLAGS_tst-cond19 = -lrt
+LDFLAGS_tst-cancel18 = -lrt
+LDFLAGS_tst-cancelx18 = -lrt
+LDFLAGS_tst-clock2 = -lrt
+LDFLAGS_tst-rwlock14 = -lrt
+LDFLAGS_tst-fini1 = -Wl,-rpath=./ tst-fini1mod.so
+LDFLAGS_tst-fini1mod.so = -Wl,-soname=tst-fini1mod.so
+LDFLAGS_tst-unload = -ldl
+LDFLAGS_tst-cancel5 := -lpthread -lpthread_nonshared
+LDFLAGS_tst-cancel23 := -lc -lpthread
+LDFLAGS_tst-vfork1x := -lc -lpthread
+LDFLAGS_tst-vfork2x := -lc -lpthread
+
+CFLAGS_tst-cancelx2 += -fexceptions
+CFLAGS_tst-cancelx3 += -fexceptions
+CFLAGS_tst-cancelx4 += -fexceptions
+CFLAGS_tst-cancelx6 += -fexceptions
+CFLAGS_tst-cancelx7 += -fexceptions
+CFLAGS_tst-cancelx8 += -fexceptions
+CFLAGS_tst-cancelx9 += -fexceptions
+CFLAGS_tst-cancelx10 += -fexceptions
+CFLAGS_tst-cancelx11 += -fexceptions
+CFLAGS_tst-cancelx12 += -fexceptions
+CFLAGS_tst-cancelx13 += -fexceptions
+CFLAGS_tst-cancelx14 += -fexceptions
+CFLAGS_tst-cancelx15 += -fexceptions
+CFLAGS_tst-cancelx16 += -fexceptions
+CFLAGS_tst-cancelx18 += -fexceptions
+CFLAGS_tst-cancelx20 += -fexceptions -fasynchronous-unwind-tables
+CFLAGS_tst-cancelx21 += -fexceptions -fasynchronous-unwind-tables
+CFLAGS_tst-cleanupx0 += -fexceptions -fasynchronous-unwind-tables
+CFLAGS_tst-cleanupx1 += -fexceptions -fasynchronous-unwind-tables
+CFLAGS_tst-cleanupx2 += -fexceptions
+CFLAGS_tst-cleanupx3 += -fexceptions
+
+CFLAGS_tst-oncex3 += -fexceptions
+CFLAGS_tst-oncex4 += -fexceptions
+CFLAGS_tst-align += $(stack-align-test-flags)
+CFLAGS_tst-align3 += $(stack-align-test-flags)
+CFLAGS_tst-initializers1 = -W -Wall -Werror
+CFLAGS_tst-sem11 += -fexceptions -fasynchronous-unwind-tables
+CFLAGS_tst-sem12 += -fexceptions -fasynchronous-unwind-tables
+CFLAGS_tst-initializers1 = -W -Wall -Werror
+CFLAGS_tst-initializers1-c89 = $(CFLAGS-tst-initializers1) -std=c89
+CFLAGS_tst-initializers1-c99 = $(CFLAGS-tst-initializers1) -std=c99
+CFLAGS_tst-initializers1-gnu89 = $(CFLAGS-tst-initializers1) -std=gnu89
+CFLAGS_tst-initializers1-gnu99 = $(CFLAGS-tst-initializers1) -std=gnu99
+
+EXTRA_LDFLAGS = $(if $(findstring -lpthread,$(LDFLAGS_$@)),,-lpthread)
+
+LDFLAGS_tst-cleanup4 := tst-cleanup4aux.o
+LDFLAGS_tst-cleanupx4 := tst-cleanup4aux.o
+LDFLAGS_tst-clock2 := -lrt
+LDFLAGS_tst-cond11 := -lrt
+LDFLAGS_tst-cond19 := -lrt
+LDFLAGS_tst-rwlock14 := -lrt
+LDFLAGS_tst-tls3 := -ldl -rdynamic
+LDFLAGS_tst-tls4 := -ldl
+LDFLAGS_tst-tls5 :=  tst-tls5mod.so
+LDFLAGS_tst-clock := -lrt
+LDFLAGS_tst-clock_nanosleep := -lrt
+LDFLAGS_tst-cpuclock1 := -lrt
+LDFLAGS_tst-cpuclock2 := -lrt -lpthread
+LDFLAGS_tst-cputimer1 := -lrt -lpthread
+LDFLAGS_tst-cputimer2 := -lrt -lpthread
+LDFLAGS_tst-cputimer3 := -lrt -lpthread
+LDFLAGS_tst-mqueue1 := -lrt
+LDFLAGS_tst-mqueue2 := -lrt
+LDFLAGS_tst-mqueue3 := -lrt -lpthread
+LDFLAGS_tst-mqueue4 := -lrt
+LDFLAGS_tst-mqueue5 := -lrt -lpthread
+LDFLAGS_tst-mqueue6 := -lrt -lpthread
+LDFLAGS_tst-mqueue7 := -lrt
+LDFLAGS_tst-mqueue8 := -lrt
+LDFLAGS_tst-mqueue9 := -lrt
+LDFLAGS_tst-timer2 := -lrt -lpthread
+LDFLAGS_tst-timer3 := -lrt -lpthread
+LDFLAGS_tst-timer4 := -lrt -lpthread
+LDFLAGS_tst-timer5 := -lrt -lpthread
+LDFLAGS_tst-dlsym1 := -ldl -rdynamic
+LDFLAGS_tst-tls3mod.so := -shared -static-libgcc -lpthread
+LDFLAGS_tst-tls4moda.so := -shared -static-libgcc
+LDFLAGS_tst-tls4modb.so := -shared -static-libgcc
+LDFLAGS_tst-tls5mod.so := -shared -static-libgcc -Wl,-soname,tst-tls5mod.so
+LDFLAGS_tst-tls5moda.so := -shared -static-libgcc
+LDFLAGS_tst-tls5modb.so := -shared -static-libgcc
+LDFLAGS_tst-tls5modc.so := -shared -static-libgcc
+LDFLAGS_tst-tls5modd.so := -shared -static-libgcc
+LDFLAGS_tst-tls5mode.so := -shared -static-libgcc
+LDFLAGS_tst-tls5modf.so := -shared -static-libgcc
+LDFLAGS_tst-cleanupx4 := tst-cleanup4aux.o
+
+#
+# Special case
+#
+tst-cleanup4aux.o:
+	$(Q)$(CC) $(CFLAGS) $(CFLAGS_$@) $(EXTRA_CFLAGS) -c tst-cleanup4aux.c -o $@
+
+tst-cleanup4: tst-cleanup4aux.o
+tst-tls3: tst-tls3mod.so
+tst-tls4: tst-tls4moda.so tst-tls4modb.so
+tst-tls5: tst-tls5mod.so
+
+tst-cleanupx4 : tst-cleanup4aux.o
+tst-fini1: tst-fini1mod.so
+
+OPTS_tst-cancel7 = --command ./tst-cancel7
+OPTS_tst-mqueue7 = -- ./tst-mqueue7
+OPTS_tst-exec4 = ./tst-exec4
+
+RET_tst-clock2 := 1
+RET_tst-cputimer1 := 1
+RET_tst-cputimer2 := 1
+RET_tst-cputimer3 := 1
+
+WRAPPER := env LD_LIBRARY_PATH="$$PWD:.:$(LD_LIBRARY_PATH)" TIMEOUTFACTOR=100
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/eintr.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/eintr.c
new file mode 100644
index 00000000..933c5d81
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/eintr.c
@@ -0,0 +1,89 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+
+
+static int the_sig;
+
+
+static void
+eintr_handler (int sig)
+{
+  if (sig != the_sig)
+    {
+      write (STDOUT_FILENO, "eintr_handler: signal number wrong\n", 35);
+      _exit (1);
+    }
+  write (STDOUT_FILENO, ".", 1);
+}
+
+
+static void *
+eintr_source (void *arg)
+{
+  struct timespec ts = { .tv_sec = 0, .tv_nsec = 500000 };
+
+  if (arg == NULL)
+    {
+      sigset_t ss;
+      sigemptyset (&ss);
+      sigaddset (&ss, the_sig);
+      pthread_sigmask (SIG_BLOCK, &ss, NULL);
+    }
+
+  while (1)
+    {
+      if (arg != NULL)
+	pthread_kill (*(pthread_t *) arg, the_sig);
+      else
+	kill (getpid (), the_sig);
+
+      nanosleep (&ts, NULL);
+    }
+
+  /* NOTREACHED */
+  return NULL;
+}
+
+
+static void
+setup_eintr (int sig, pthread_t *thp)
+{
+  struct sigaction sa;
+  sigemptyset (&sa.sa_mask);
+  sa.sa_flags = 0;
+  sa.sa_handler = eintr_handler;
+  if (sigaction (sig, &sa, NULL) != 0)
+    {
+      puts ("setup_eintr: sigaction failed");
+      exit (1);
+    }
+  the_sig = sig;
+
+  /* Create the thread which will fire off the signals.  */
+  pthread_t th;
+  if (pthread_create (&th, NULL, eintr_source, thp) != 0)
+    {
+      puts ("setup_eintr: pthread_create failed");
+      exit (1);
+    }
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-align.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-align.c
new file mode 100644
index 00000000..381db8f4
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-align.c
@@ -0,0 +1,71 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include "tst-stack-align.h"
+
+static void *
+tf (void *arg)
+{
+  bool ok = true;
+
+  puts ("in thread");
+
+  if (TEST_STACK_ALIGN ())
+    ok = false;
+
+  return ok ? NULL : (void *) -1l;
+}
+
+static int
+do_test (void)
+{
+  bool ok = true;
+
+  puts ("in main");
+
+  if (TEST_STACK_ALIGN ())
+    ok = false;
+
+  pthread_t th;
+  if (pthread_create (&th, NULL, tf, NULL) != 0)
+    {
+      puts ("create failed");
+      return 1;
+    }
+
+  void *res;
+  if (pthread_join (th, &res) != 0)
+    {
+      puts ("join failed");
+      return 1;
+    }
+
+  if (res != NULL)
+    ok = false;
+
+  return ok ? 0 : 1;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-align2.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-align2.c
new file mode 100644
index 00000000..7d8be53d
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-align2.c
@@ -0,0 +1,87 @@
+/* Copyright (C) 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "tst-stack-align.h"
+
+static int
+f (void *arg)
+{
+  bool ok = true;
+
+  if (TEST_STACK_ALIGN ())
+    ok = false;
+
+  return ok ? 0 : 1;
+}
+
+static int
+do_test (void)
+{
+  bool ok = true;
+
+  puts ("in main");
+
+  if (TEST_STACK_ALIGN ())
+    ok = false;
+
+#ifdef __ia64__
+  extern int __clone2 (int (*__fn) (void *__arg), void *__child_stack_base,
+		       size_t __child_stack_size, int __flags,
+		       void *__arg, ...);
+  char st[256 * 1024];
+  pid_t p = __clone2 (f, st, sizeof (st), 0, 0);
+#else
+  char st[128 * 1024];
+  pid_t p = clone (f, st + sizeof (st), 0, 0);
+#endif
+  if (p == -1)
+    {
+      printf("clone failed: %m\n");
+      return 1;
+    }
+
+  int e;
+  if (waitpid (p, &e, __WCLONE) != p)
+    {
+      puts ("waitpid failed");
+      kill (p, SIGKILL);
+      return 1;
+    }
+  if (!WIFEXITED (e))
+    {
+      if (WIFSIGNALED (e))
+	printf ("died from signal %s\n", strsignal (WTERMSIG (e)));
+      else
+	puts ("did not terminate correctly");
+      return 1;
+    }
+  if (WEXITSTATUS (e) != 0)
+    ok = false;
+
+  return ok ? 0 : 1;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-align3.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-align3.c
new file mode 100644
index 00000000..f4507f2e
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-align3.c
@@ -0,0 +1,57 @@
+/* Copyright (C) 2005 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek , 2005.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include "tst-stack-align.h"
+
+static bool ok = true;
+static pthread_once_t once = PTHREAD_ONCE_INIT;
+
+static void
+once_test (void)
+{
+  puts ("in once_test");
+
+  if (TEST_STACK_ALIGN ())
+    ok = false;
+}
+
+static int
+do_test (void)
+{
+  puts ("in main");
+
+  if (TEST_STACK_ALIGN ())
+    ok = false;
+
+  if (pthread_once (&once, once_test))
+    {
+      puts ("pthread once failed");
+      return 1;
+    }
+
+  return ok ? 0 : 1;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-atfork1.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-atfork1.c
new file mode 100644
index 00000000..b42ab424
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-atfork1.c
@@ -0,0 +1,121 @@
+/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2002.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+static int val;
+
+
+static void
+prepare1 (void)
+{
+  val *= 2;
+}
+
+static void
+prepare2 (void)
+{
+  ++val;
+}
+
+static void
+parent1 (void)
+{
+  val += 4;
+}
+
+static void
+parent2 (void)
+{
+  val *= 4;
+}
+
+static void
+child1 (void)
+{
+  val += 8;
+}
+
+static void
+child2 (void)
+{
+  val *= 8;
+}
+
+
+static int
+do_test (void)
+{
+  pid_t pid;
+  int status = 0;
+
+  if (pthread_atfork (prepare1, parent1, child1) != 0)
+    {
+      puts ("1st atfork failed");
+      exit (1);
+    }
+  if (pthread_atfork (prepare2, parent2, child2) != 0)
+    {
+      puts ("2nd atfork failed");
+      exit (1);
+    }
+
+  pid = fork ();
+  if (pid == -1)
+    {
+      puts ("fork failed");
+      exit (1);
+    }
+
+  if (pid != 0)
+    {
+      /* Parent.  */
+      if (val != 24)
+	{
+	  printf ("expected val=%d, got %d\n", 24, val);
+	  exit (1);
+	}
+
+      if (TEMP_FAILURE_RETRY (waitpid (pid, &status, 0)) != pid)
+	{
+	  puts ("waitpid failed");
+	  exit (1);
+	}
+    }
+  else
+    {
+      /* Child.  */
+      if (val != 80)
+	{
+	  printf ("expected val=%d, got %d\n", 80, val);
+	  exit (2);
+	}
+    }
+
+  return status;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-attr1.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-attr1.c
new file mode 100644
index 00000000..13b62a69
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-attr1.c
@@ -0,0 +1,306 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+int
+do_test (void)
+{
+  int i;
+  pthread_attr_t a;
+
+  if (pthread_attr_init (&a) != 0)
+    {
+      puts ("attr_init failed");
+      exit (1);
+    }
+
+  pthread_mutexattr_t ma;
+
+  if (pthread_mutexattr_init (&ma) != 0)
+    {
+      puts ("mutexattr_init failed");
+      exit (1);
+    }
+
+  pthread_rwlockattr_t rwa;
+
+  if (pthread_rwlockattr_init (&rwa) != 0)
+    {
+      puts ("rwlockattr_init failed");
+      exit (1);
+    }
+
+  /* XXX Remove if default value is clear.  */
+  pthread_attr_setinheritsched (&a, PTHREAD_INHERIT_SCHED);
+  pthread_attr_setschedpolicy (&a, SCHED_OTHER);
+  pthread_attr_setscope (&a, PTHREAD_SCOPE_SYSTEM);
+
+  for (i = 0; i < 10000; ++i)
+    {
+      long int r = random ();
+
+      if (r != PTHREAD_CREATE_DETACHED && r != PTHREAD_CREATE_JOINABLE)
+	{
+	  int e = pthread_attr_setdetachstate (&a, r);
+
+	  if (e == 0)
+	    {
+	      printf ("attr_setdetachstate with value %ld succeeded\n", r);
+	      exit (1);
+	    }
+	  if (e != EINVAL)
+	    {
+	      puts ("attr_setdetachstate didn't return EINVAL");
+	      exit (1);
+	    }
+
+	  int s;
+	  if (pthread_attr_getdetachstate (&a, &s) != 0)
+	    {
+	      puts ("attr_getdetachstate failed");
+	      exit (1);
+	    }
+
+	  if (s != PTHREAD_CREATE_JOINABLE)
+	    {
+	      printf ("\
+detach state changed to %d by invalid setdetachstate call\n", s);
+	      exit (1);
+	    }
+	}
+
+      if (r != PTHREAD_INHERIT_SCHED && r != PTHREAD_EXPLICIT_SCHED)
+	{
+	  int e = pthread_attr_setinheritsched (&a, r);
+
+	  if (e == 0)
+	    {
+	      printf ("attr_setinheritsched with value %ld succeeded\n", r);
+	      exit (1);
+	    }
+	  if (e != EINVAL)
+	    {
+	      puts ("attr_setinheritsched didn't return EINVAL");
+	      exit (1);
+	    }
+
+	  int s;
+	  if (pthread_attr_getinheritsched (&a, &s) != 0)
+	    {
+	      puts ("attr_getinheritsched failed");
+	      exit (1);
+	    }
+
+	  if (s != PTHREAD_INHERIT_SCHED)
+	    {
+	      printf ("\
+inheritsched changed to %d by invalid setinheritsched call\n", s);
+	      exit (1);
+	    }
+	}
+
+      if (r != SCHED_OTHER && r != SCHED_RR && r != SCHED_FIFO)
+	{
+	  int e = pthread_attr_setschedpolicy (&a, r);
+
+	  if (e == 0)
+	    {
+	      printf ("attr_setschedpolicy with value %ld succeeded\n", r);
+	      exit (1);
+	    }
+	  if (e != EINVAL)
+	    {
+	      puts ("attr_setschedpolicy didn't return EINVAL");
+	      exit (1);
+	    }
+
+	  int s;
+	  if (pthread_attr_getschedpolicy (&a, &s) != 0)
+	    {
+	      puts ("attr_getschedpolicy failed");
+	      exit (1);
+	    }
+
+	  if (s != SCHED_OTHER)
+	    {
+	      printf ("\
+schedpolicy changed to %d by invalid setschedpolicy call\n", s);
+	      exit (1);
+	    }
+	}
+
+      if (r != PTHREAD_SCOPE_SYSTEM && r != PTHREAD_SCOPE_PROCESS)
+	{
+	  int e = pthread_attr_setscope (&a, r);
+
+	  if (e == 0)
+	    {
+	      printf ("attr_setscope with value %ld succeeded\n", r);
+	      exit (1);
+	    }
+	  if (e != EINVAL)
+	    {
+	      puts ("attr_setscope didn't return EINVAL");
+	      exit (1);
+	    }
+
+	  int s;
+	  if (pthread_attr_getscope (&a, &s) != 0)
+	    {
+	      puts ("attr_getscope failed");
+	      exit (1);
+	    }
+
+	  if (s != PTHREAD_SCOPE_SYSTEM)
+	    {
+	      printf ("\
+contentionscope changed to %d by invalid setscope call\n", s);
+	      exit (1);
+	    }
+	}
+
+      if (r != PTHREAD_PROCESS_PRIVATE && r != PTHREAD_PROCESS_SHARED)
+	{
+	  int e = pthread_mutexattr_setpshared (&ma, r);
+
+	  if (e == 0)
+	    {
+	      printf ("mutexattr_setpshared with value %ld succeeded\n", r);
+	      exit (1);
+	    }
+	  if (e != EINVAL)
+	    {
+	      puts ("mutexattr_setpshared didn't return EINVAL");
+	      exit (1);
+	    }
+
+	  int s;
+	  if (pthread_mutexattr_getpshared (&ma, &s) != 0)
+	    {
+	      puts ("mutexattr_getpshared failed");
+	      exit (1);
+	    }
+
+	  if (s != PTHREAD_PROCESS_PRIVATE)
+	    {
+	      printf ("\
+pshared changed to %d by invalid mutexattr_setpshared call\n", s);
+	      exit (1);
+	    }
+
+	  e = pthread_rwlockattr_setpshared (&rwa, r);
+
+	  if (e == 0)
+	    {
+	      printf ("rwlockattr_setpshared with value %ld succeeded\n", r);
+	      exit (1);
+	    }
+	  if (e != EINVAL)
+	    {
+	      puts ("rwlockattr_setpshared didn't return EINVAL");
+	      exit (1);
+	    }
+
+	  if (pthread_rwlockattr_getpshared (&rwa, &s) != 0)
+	    {
+	      puts ("rwlockattr_getpshared failed");
+	      exit (1);
+	    }
+
+	  if (s != PTHREAD_PROCESS_PRIVATE)
+	    {
+	      printf ("\
+pshared changed to %d by invalid rwlockattr_setpshared call\n", s);
+	      exit (1);
+	    }
+	}
+
+      if (r != PTHREAD_CANCEL_ENABLE && r != PTHREAD_CANCEL_DISABLE)
+	{
+	  int e = pthread_setcancelstate (r, NULL);
+
+	  if (e == 0)
+	    {
+	      printf ("setcancelstate with value %ld succeeded\n", r);
+	      exit (1);
+	    }
+
+	  if (e != EINVAL)
+	    {
+	      puts ("setcancelstate didn't return EINVAL");
+	      exit (1);
+	    }
+
+	  int s;
+	  if (pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, &s) != 0)
+	    {
+	      puts ("setcancelstate failed for PTHREAD_CANCEL_ENABLE");
+	      exit (1);
+	    }
+
+	  if (s != PTHREAD_CANCEL_ENABLE)
+	    {
+	      puts ("invalid setcancelstate changed state");
+	      exit (1);
+	    }
+	}
+
+      if (r != PTHREAD_CANCEL_DEFERRED && r != PTHREAD_CANCEL_ASYNCHRONOUS)
+	{
+	  int e = pthread_setcanceltype (r, NULL);
+
+	  if (e == 0)
+	    {
+	      printf ("setcanceltype with value %ld succeeded\n", r);
+	      exit (1);
+	    }
+
+	  if (e != EINVAL)
+	    {
+	      puts ("setcanceltype didn't return EINVAL");
+	      exit (1);
+	    }
+
+	  int s;
+	  if (pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, &s) != 0)
+	    {
+	      puts ("setcanceltype failed for PTHREAD_CANCEL_DEFERRED");
+	      exit (1);
+	    }
+
+	  if (s != PTHREAD_CANCEL_DEFERRED)
+	    {
+	      puts ("invalid setcanceltype changed state");
+	      exit (1);
+	    }
+	}
+    }
+
+  return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-attr2.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-attr2.c
new file mode 100644
index 00000000..a60598dd
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-attr2.c
@@ -0,0 +1,317 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+int
+do_test (void)
+{
+  pthread_attr_t a;
+
+  if (pthread_attr_init (&a) != 0)
+    {
+      puts ("attr_init failed");
+      exit (1);
+    }
+
+  /* Check default value of detach state.  */
+  int s;
+  if (pthread_attr_getdetachstate (&a, &s) != 0)
+    {
+      puts ("1st attr_getdestachstate failed");
+      exit (1);
+    }
+  if (s != PTHREAD_CREATE_JOINABLE)
+    {
+      printf ("\
+default detach state wrong: %d, expected %d (PTHREAD_CREATE_JOINABLE)\n",
+	      s, PTHREAD_CREATE_JOINABLE);
+      exit (1);
+    }
+
+  int e = pthread_attr_setdetachstate (&a, PTHREAD_CREATE_DETACHED);
+  if (e != 0)
+    {
+      puts ("1st attr_setdetachstate failed");
+      exit (1);
+    }
+  if (pthread_attr_getdetachstate (&a, &s) != 0)
+    {
+      puts ("2nd attr_getdestachstate failed");
+      exit (1);
+    }
+  if (s != PTHREAD_CREATE_DETACHED)
+    {
+      puts ("PTHREAD_CREATE_DETACHED set, but not given back");
+      exit (1);
+    }
+
+  e = pthread_attr_setdetachstate (&a, PTHREAD_CREATE_JOINABLE);
+  if (e != 0)
+    {
+      puts ("2nd attr_setdetachstate failed");
+      exit (1);
+    }
+  if (pthread_attr_getdetachstate (&a, &s) != 0)
+    {
+      puts ("3rd attr_getdestachstate failed");
+      exit (1);
+    }
+  if (s != PTHREAD_CREATE_JOINABLE)
+    {
+      puts ("PTHREAD_CREATE_JOINABLE set, but not given back");
+      exit (1);
+    }
+
+
+  size_t g;
+  if (pthread_attr_getguardsize (&a, &g) != 0)
+    {
+      puts ("1st attr_getguardsize failed");
+      exit (1);
+    }
+  if (g != (size_t) sysconf (_SC_PAGESIZE))
+    {
+      printf ("default guardsize %zu, expected %ld (PAGESIZE)\n",
+	      g, sysconf (_SC_PAGESIZE));
+      exit (1);
+    }
+
+  e = pthread_attr_setguardsize (&a, 0);
+  if (e != 0)
+    {
+      puts ("1st attr_setguardsize failed");
+      exit (1);
+    }
+  if (pthread_attr_getguardsize (&a, &g) != 0)
+    {
+      puts ("2nd attr_getguardsize failed");
+      exit (1);
+    }
+  if (g != 0)
+    {
+      printf ("guardsize set to zero but %zu returned\n", g);
+      exit (1);
+    }
+
+  e = pthread_attr_setguardsize (&a, 1);
+  if (e != 0)
+    {
+      puts ("2nd attr_setguardsize failed");
+      exit (1);
+    }
+  if (pthread_attr_getguardsize (&a, &g) != 0)
+    {
+      puts ("3rd attr_getguardsize failed");
+      exit (1);
+    }
+  if (g != 1)
+    {
+      printf ("guardsize set to 1 but %zu returned\n", g);
+      exit (1);
+    }
+
+
+  if (pthread_attr_getinheritsched (&a, &s) != 0)
+    {
+      puts ("1st attr_getinheritsched failed");
+      exit (1);
+    }
+  /* XXX What is the correct default value.  */
+  if (s != PTHREAD_INHERIT_SCHED && s != PTHREAD_EXPLICIT_SCHED)
+    {
+      puts ("incorrect default value for inheritsched");
+      exit (1);
+    }
+
+  e = pthread_attr_setinheritsched (&a, PTHREAD_EXPLICIT_SCHED);
+  if (e != 0)
+    {
+      puts ("1st attr_setinheritsched failed");
+      exit (1);
+    }
+  if (pthread_attr_getinheritsched (&a, &s) != 0)
+    {
+      puts ("2nd attr_getinheritsched failed");
+      exit (1);
+    }
+  if (s != PTHREAD_EXPLICIT_SCHED)
+    {
+      printf ("inheritsched set to PTHREAD_EXPLICIT_SCHED, but got %d\n", s);
+      exit (1);
+    }
+
+  e = pthread_attr_setinheritsched (&a, PTHREAD_INHERIT_SCHED);
+  if (e != 0)
+    {
+      puts ("2nd attr_setinheritsched failed");
+      exit (1);
+    }
+  if (pthread_attr_getinheritsched (&a, &s) != 0)
+    {
+      puts ("3rd attr_getinheritsched failed");
+      exit (1);
+    }
+  if (s != PTHREAD_INHERIT_SCHED)
+    {
+      printf ("inheritsched set to PTHREAD_INHERIT_SCHED, but got %d\n", s);
+      exit (1);
+    }
+
+
+  if (pthread_attr_getschedpolicy (&a, &s) != 0)
+    {
+      puts ("1st attr_getschedpolicy failed");
+      exit (1);
+    }
+  /* XXX What is the correct default value.  */
+  if (s != SCHED_OTHER && s != SCHED_FIFO && s != SCHED_RR)
+    {
+      puts ("incorrect default value for schedpolicy");
+      exit (1);
+    }
+
+  e = pthread_attr_setschedpolicy (&a, SCHED_RR);
+  if (e != 0)
+    {
+      puts ("1st attr_setschedpolicy failed");
+      exit (1);
+    }
+  if (pthread_attr_getschedpolicy (&a, &s) != 0)
+    {
+      puts ("2nd attr_getschedpolicy failed");
+      exit (1);
+    }
+  if (s != SCHED_RR)
+    {
+      printf ("schedpolicy set to SCHED_RR, but got %d\n", s);
+      exit (1);
+    }
+
+  e = pthread_attr_setschedpolicy (&a, SCHED_FIFO);
+  if (e != 0)
+    {
+      puts ("2nd attr_setschedpolicy failed");
+      exit (1);
+    }
+  if (pthread_attr_getschedpolicy (&a, &s) != 0)
+    {
+      puts ("3rd attr_getschedpolicy failed");
+      exit (1);
+    }
+  if (s != SCHED_FIFO)
+    {
+      printf ("schedpolicy set to SCHED_FIFO, but got %d\n", s);
+      exit (1);
+    }
+
+  e = pthread_attr_setschedpolicy (&a, SCHED_OTHER);
+  if (e != 0)
+    {
+      puts ("3rd attr_setschedpolicy failed");
+      exit (1);
+    }
+  if (pthread_attr_getschedpolicy (&a, &s) != 0)
+    {
+      puts ("4th attr_getschedpolicy failed");
+      exit (1);
+    }
+  if (s != SCHED_OTHER)
+    {
+      printf ("schedpolicy set to SCHED_OTHER, but got %d\n", s);
+      exit (1);
+    }
+
+
+  if (pthread_attr_getscope (&a, &s) != 0)
+    {
+      puts ("1st attr_getscope failed");
+      exit (1);
+    }
+  /* XXX What is the correct default value.  */
+  if (s != PTHREAD_SCOPE_SYSTEM && s != PTHREAD_SCOPE_PROCESS)
+    {
+      puts ("incorrect default value for contentionscope");
+      exit (1);
+    }
+
+  e = pthread_attr_setscope (&a, PTHREAD_SCOPE_PROCESS);
+  if (e != ENOTSUP)
+    {
+      if (e != 0)
+	{
+	  puts ("1st attr_setscope failed");
+	  exit (1);
+	}
+      if (pthread_attr_getscope (&a, &s) != 0)
+	{
+	  puts ("2nd attr_getscope failed");
+	  exit (1);
+	}
+      if (s != PTHREAD_SCOPE_PROCESS)
+	{
+	  printf ("\
+contentionscope set to PTHREAD_SCOPE_PROCESS, but got %d\n", s);
+	  exit (1);
+	}
+    }
+
+  e = pthread_attr_setscope (&a, PTHREAD_SCOPE_SYSTEM);
+  if (e != 0)
+    {
+      puts ("2nd attr_setscope failed");
+      exit (1);
+    }
+  if (pthread_attr_getscope (&a, &s) != 0)
+    {
+      puts ("3rd attr_getscope failed");
+      exit (1);
+    }
+  if (s != PTHREAD_SCOPE_SYSTEM)
+    {
+      printf ("contentionscope set to PTHREAD_SCOPE_SYSTEM, but got %d\n", s);
+      exit (1);
+    }
+
+  char buf[1];
+  e = pthread_attr_setstack (&a, buf, 1);
+  if (e != EINVAL)
+    {
+      puts ("setstack with size 1 did not produce EINVAL");
+      exit (1);
+    }
+
+  e = pthread_attr_setstacksize (&a, 1);
+  if (e != EINVAL)
+    {
+      puts ("setstacksize with size 1 did not produce EINVAL");
+      exit (1);
+    }
+
+  return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-attr3.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-attr3.c
new file mode 100644
index 00000000..29b4bbe3
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-attr3.c
@@ -0,0 +1,420 @@
+/* pthread_getattr_np test.
+   Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek , 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+static void *
+tf (void *arg)
+{
+  pthread_attr_t a, *ap, a2;
+  int err;
+  void *result = NULL;
+
+  if (arg == NULL)
+    {
+      ap = &a2;
+      err = pthread_attr_init (ap);
+      if (err)
+        {
+          error (0, err, "pthread_attr_init failed");
+          return tf;
+        }
+    }
+  else
+    ap = (pthread_attr_t *) arg;
+
+  err = pthread_getattr_np (pthread_self (), &a);
+  if (err)
+    {
+      error (0, err, "pthread_getattr_np failed");
+      result = tf;
+    }
+
+  int detachstate1, detachstate2;
+  err = pthread_attr_getdetachstate (&a, &detachstate1);
+  if (err)
+    {
+      error (0, err, "pthread_attr_getdetachstate failed");
+      result = tf;
+    }
+  else
+    {
+      err = pthread_attr_getdetachstate (ap, &detachstate2);
+      if (err)
+	{
+	  error (0, err, "pthread_attr_getdetachstate failed");
+	  result = tf;
+	}
+      else if (detachstate1 != detachstate2)
+	{
+	  error (0, 0, "detachstate differs %d != %d",
+		 detachstate1, detachstate2);
+	  result = tf;
+	}
+    }
+
+  void *stackaddr;
+  size_t stacksize;
+  err = pthread_attr_getstack (&a, &stackaddr, &stacksize);
+  if (err)
+    {
+      error (0, err, "pthread_attr_getstack failed");
+      result = tf;
+    }
+  else if ((void *) &a < stackaddr
+	   || (void *) &a >= stackaddr + stacksize)
+    {
+      error (0, 0, "pthread_attr_getstack returned range does not cover thread's stack");
+      result = tf;
+    }
+  else
+    printf ("thread stack %p-%p (0x%zx)\n", stackaddr, stackaddr + stacksize,
+	    stacksize);
+
+  size_t guardsize1, guardsize2;
+  err = pthread_attr_getguardsize (&a, &guardsize1);
+  if (err)
+    {
+      error (0, err, "pthread_attr_getguardsize failed");
+      result = tf;
+    }
+  else
+    {
+      err = pthread_attr_getguardsize (ap, &guardsize2);
+      if (err)
+	{
+	  error (0, err, "pthread_attr_getguardsize failed");
+	  result = tf;
+	}
+      else if (guardsize1 != guardsize2)
+	{
+	  error (0, 0, "guardsize differs %zd != %zd",
+		 guardsize1, guardsize2);
+	  result = tf;
+	}
+      else
+	printf ("thread guardsize %zd\n", guardsize1);
+    }
+
+  int scope1, scope2;
+  err = pthread_attr_getscope (&a, &scope1);
+  if (err)
+    {
+      error (0, err, "pthread_attr_getscope failed");
+      result = tf;
+    }
+  else
+    {
+      err = pthread_attr_getscope (ap, &scope2);
+      if (err)
+	{
+	  error (0, err, "pthread_attr_getscope failed");
+	  result = tf;
+	}
+      else if (scope1 != scope2)
+	{
+	  error (0, 0, "scope differs %d != %d",
+		 scope1, scope2);
+	  result = tf;
+	}
+    }
+
+  int inheritsched1, inheritsched2;
+  err = pthread_attr_getinheritsched (&a, &inheritsched1);
+  if (err)
+    {
+      error (0, err, "pthread_attr_getinheritsched failed");
+      result = tf;
+    }
+  else
+    {
+      err = pthread_attr_getinheritsched (ap, &inheritsched2);
+      if (err)
+	{
+	  error (0, err, "pthread_attr_getinheritsched failed");
+	  result = tf;
+	}
+      else if (inheritsched1 != inheritsched2)
+	{
+	  error (0, 0, "inheritsched differs %d != %d",
+		 inheritsched1, inheritsched2);
+	  result = tf;
+	}
+    }
+
+  cpu_set_t c1, c2;
+  err = pthread_getaffinity_np (pthread_self (), sizeof (c1), &c1);
+  if (err == 0)
+    {
+      err = pthread_attr_getaffinity_np (&a, sizeof (c2), &c2);
+      if (err)
+	{
+	  error (0, err, "pthread_attr_getaffinity_np failed");
+	  result = tf;
+	}
+      else if (memcmp (&c1, &c2, sizeof (c1)))
+	{
+	  error (0, 0, "pthread_attr_getaffinity_np returned different CPU mask than pthread_getattr_np");
+	  result = tf;
+	}
+    }
+
+  err = pthread_attr_destroy (&a);
+  if (err)
+    {
+      error (0, err, "pthread_attr_destroy failed");
+      result = tf;
+    }
+
+  if (ap == &a2)
+    {
+      err = pthread_attr_destroy (ap);
+      if (err)
+	{
+	  error (0, err, "pthread_attr_destroy failed");
+	  result = tf;
+	}
+    }
+
+  return result;
+}
+
+
+static int
+do_test (void)
+{
+  int result = 0;
+  pthread_attr_t a;
+  cpu_set_t c1, c2;
+
+  int err = pthread_attr_init (&a);
+  if (err)
+    {
+      error (0, err, "pthread_attr_init failed");
+      result = 1;
+    }
+
+  err = pthread_attr_getaffinity_np (&a, sizeof (c1), &c1);
+  if (err && err != ENOSYS)
+    {
+      error (0, err, "pthread_attr_getaffinity_np failed");
+      result = 1;
+    }
+
+  err = pthread_attr_destroy (&a);
+  if (err)
+    {
+      error (0, err, "pthread_attr_destroy failed");
+      result = 1;
+    }
+
+  err = pthread_getattr_np (pthread_self (), &a);
+  if (err)
+    {
+      error (0, err, "pthread_getattr_np failed");
+      result = 1;
+    }
+
+  int detachstate;
+  err = pthread_attr_getdetachstate (&a, &detachstate);
+  if (err)
+    {
+      error (0, err, "pthread_attr_getdetachstate failed");
+      result = 1;
+    }
+  else if (detachstate != PTHREAD_CREATE_JOINABLE)
+    {
+      error (0, 0, "initial thread not joinable");
+      result = 1;
+    }
+
+  void *stackaddr;
+  size_t stacksize;
+  err = pthread_attr_getstack (&a, &stackaddr, &stacksize);
+  if (err)
+    {
+      error (0, err, "pthread_attr_getstack failed");
+      result = 1;
+    }
+  else if ((void *) &a < stackaddr
+	   || (void *) &a >= stackaddr + stacksize)
+    {
+      error (0, 0, "pthread_attr_getstack returned range does not cover main's stack");
+      result = 1;
+    }
+  else
+    printf ("initial thread stack %p-%p (0x%zx)\n", stackaddr,
+	    stackaddr + stacksize, stacksize);
+
+  size_t guardsize;
+  err = pthread_attr_getguardsize (&a, &guardsize);
+  if (err)
+    {
+      error (0, err, "pthread_attr_getguardsize failed");
+      result = 1;
+    }
+  else if (guardsize != 0)
+    {
+      error (0, 0, "pthread_attr_getguardsize returned %zd != 0",
+	     guardsize);
+      result = 1;
+    }
+
+  int scope;
+  err = pthread_attr_getscope (&a, &scope);
+  if (err)
+    {
+      error (0, err, "pthread_attr_getscope failed");
+      result = 1;
+    }
+  else if (scope != PTHREAD_SCOPE_SYSTEM)
+    {
+      error (0, 0, "pthread_attr_getscope returned %d != PTHREAD_SCOPE_SYSTEM",
+	     scope);
+      result = 1;
+    }
+
+  int inheritsched;
+  err = pthread_attr_getinheritsched (&a, &inheritsched);
+  if (err)
+    {
+      error (0, err, "pthread_attr_getinheritsched failed");
+      result = 1;
+    }
+  else if (inheritsched != PTHREAD_INHERIT_SCHED)
+    {
+      error (0, 0, "pthread_attr_getinheritsched returned %d != PTHREAD_INHERIT_SCHED",
+	     inheritsched);
+      result = 1;
+    }
+
+  err = pthread_getaffinity_np (pthread_self (), sizeof (c1), &c1);
+  if (err == 0)
+    {
+      err = pthread_attr_getaffinity_np (&a, sizeof (c2), &c2);
+      if (err)
+	{
+	  error (0, err, "pthread_attr_getaffinity_np failed");
+	  result = 1;
+	}
+      else if (memcmp (&c1, &c2, sizeof (c1)))
+	{
+	  error (0, 0, "pthread_attr_getaffinity_np returned different CPU mask than pthread_getattr_np");
+	  result = 1;
+	}
+    }
+
+  err = pthread_attr_destroy (&a);
+  if (err)
+    {
+      error (0, err, "pthread_attr_destroy failed");
+      result = 1;
+    }
+
+  pthread_t th;
+  err = pthread_create (&th, NULL, tf, NULL);
+  if (err)
+    {
+      error (0, err, "pthread_create #1 failed");
+      result = 1;
+    }
+  else
+    {
+      void *ret;
+      err = pthread_join (th, &ret);
+      if (err)
+	{
+	  error (0, err, "pthread_join #1 failed");
+	  result = 1;
+	}
+      else if (ret != NULL)
+        result = 1;
+    }
+
+  err = pthread_attr_init (&a);
+  if (err)
+    {
+      error (0, err, "pthread_attr_init failed");
+      result = 1;
+    }
+
+  err = pthread_create (&th, &a, tf, &a);
+  if (err)
+    {
+      error (0, err, "pthread_create #2 failed");
+      result = 1;
+    }
+  else
+    {
+      void *ret;
+      err = pthread_join (th, &ret);
+      if (err)
+	{
+	  error (0, err, "pthread_join #2 failed");
+	  result = 1;
+	}
+      else if (ret != NULL)
+        result = 1;
+    }
+
+  err = pthread_attr_setguardsize (&a, 16 * sysconf (_SC_PAGESIZE));
+  if (err)
+    {
+      error (0, err, "pthread_attr_setguardsize failed");
+      result = 1;
+    }
+
+  err = pthread_create (&th, &a, tf, &a);
+  if (err)
+    {
+      error (0, err, "pthread_create #3 failed");
+      result = 1;
+    }
+  else
+    {
+      void *ret;
+      err = pthread_join (th, &ret);
+      if (err)
+	{
+	  error (0, err, "pthread_join #3 failed");
+	  result = 1;
+	}
+      else if (ret != NULL)
+        result = 1;
+    }
+
+  err = pthread_attr_destroy (&a);
+  if (err)
+    {
+      error (0, err, "pthread_attr_destroy failed");
+      result = 1;
+    }
+
+  return result;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-barrier1.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-barrier1.c
new file mode 100644
index 00000000..2859fb4c
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-barrier1.c
@@ -0,0 +1,71 @@
+/* Copyright (C) 2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2002.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+
+
+static int
+do_test (void)
+{
+  pthread_barrier_t b;
+  int e;
+  int cnt;
+
+  e = pthread_barrier_init (&b, NULL, 0);
+  if (e == 0)
+    {
+      puts ("barrier_init with count 0 succeeded");
+      return 1;
+    }
+  if (e != EINVAL)
+    {
+      puts ("barrier_init with count 0 didn't return EINVAL");
+      return 1;
+    }
+
+  if (pthread_barrier_init (&b, NULL, 1) != 0)
+    {
+      puts ("real barrier_init failed");
+      return 1;
+    }
+
+  for (cnt = 0; cnt < 10; ++cnt)
+    {
+      e = pthread_barrier_wait (&b);
+
+      if (e != PTHREAD_BARRIER_SERIAL_THREAD)
+	{
+	  puts ("barrier_wait didn't return PTHREAD_BARRIER_SERIAL_THREAD");
+	  return 1;
+	}
+    }
+
+  if (pthread_barrier_destroy (&b) != 0)
+    {
+      puts ("barrier_destroy failed");
+      return 1;
+    }
+
+  return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-barrier2.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-barrier2.c
new file mode 100644
index 00000000..7f588694
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-barrier2.c
@@ -0,0 +1,185 @@
+/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2002.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+static int
+do_test (void)
+{
+  size_t ps = sysconf (_SC_PAGESIZE);
+  char tmpfname[] = "/tmp/tst-barrier2.XXXXXX";
+  char data[ps];
+  void *mem;
+  int fd;
+  pthread_barrier_t *b;
+  pthread_barrierattr_t a;
+  pid_t pid;
+  int serials = 0;
+  int cnt;
+  int status;
+  int p;
+
+  fd = mkstemp (tmpfname);
+  if (fd == -1)
+    {
+      printf ("cannot open temporary file: %m\n");
+      return 1;
+    }
+
+  /* Make sure it is always removed.  */
+  unlink (tmpfname);
+
+  /* Create one page of data.  */
+  memset (data, '\0', ps);
+
+  /* Write the data to the file.  */
+  if (write (fd, data, ps) != (ssize_t) ps)
+    {
+      puts ("short write");
+      return 1;
+    }
+
+  mem = mmap (NULL, ps, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+  if (mem == MAP_FAILED)
+    {
+      printf ("mmap failed: %m\n");
+      return 1;
+    }
+
+  b = (pthread_barrier_t *) (((uintptr_t) mem + __alignof (pthread_barrier_t))
+			     & ~(__alignof (pthread_barrier_t) - 1));
+
+  if (pthread_barrierattr_init (&a) != 0)
+    {
+      puts ("barrierattr_init failed");
+      return 1;
+    }
+
+  if (pthread_barrierattr_getpshared (&a, &p) != 0)
+    {
+      puts ("1st barrierattr_getpshared failed");
+      return 1;
+    }
+
+  if (p != PTHREAD_PROCESS_PRIVATE)
+    {
+      puts ("default pshared value wrong");
+      return 1;
+    }
+
+  if (pthread_barrierattr_setpshared (&a, PTHREAD_PROCESS_SHARED) != 0)
+    {
+      puts ("barrierattr_setpshared failed");
+      return 1;
+    }
+
+  if (pthread_barrierattr_getpshared (&a, &p) != 0)
+    {
+      puts ("2nd barrierattr_getpshared failed");
+      return 1;
+    }
+
+  if (p != PTHREAD_PROCESS_SHARED)
+    {
+      puts ("pshared value after setpshared call wrong");
+      return 1;
+    }
+
+  if (pthread_barrier_init (b, &a, 2) != 0)
+    {
+      puts ("barrier_init failed");
+      return 1;
+    }
+
+  if (pthread_barrierattr_destroy (&a) != 0)
+    {
+      puts ("barrierattr_destroy failed");
+      return 1;
+    }
+
+  puts ("going to fork now");
+  pid = fork ();
+  if (pid == -1)
+    {
+      puts ("fork failed");
+      return 1;
+    }
+
+  /* Just to be sure we don't hang forever.  */
+  alarm (4);
+
+#define N 30
+  for (cnt = 0; cnt < N; ++cnt)
+    {
+      int e;
+
+      e = pthread_barrier_wait (b);
+      if (e == PTHREAD_BARRIER_SERIAL_THREAD)
+	++serials;
+      else if (e != 0)
+	{
+	  printf ("%s: barrier_wait returned value %d != 0 and PTHREAD_BARRIER_SERIAL_THREAD\n",
+		  pid == 0 ? "child" : "parent", e);
+	  return 1;
+	}
+    }
+
+  alarm (0);
+
+  printf ("%s: was %d times the serial thread\n",
+	  pid == 0 ? "child" : "parent", serials);
+
+  if (pid == 0)
+    /* The child.  Pass the number of times we had the serializing
+       thread back to the parent.  */
+    exit (serials);
+
+  if (waitpid (pid, &status, 0) != pid)
+    {
+      puts ("waitpid failed");
+      return 1;
+    }
+
+  if (!WIFEXITED (status))
+    {
+      puts ("child exited abnormally");
+      return 1;
+    }
+
+  if (WEXITSTATUS (status) + serials != N)
+    {
+      printf ("total number of serials is %d, expected %d\n",
+	      WEXITSTATUS (status) + serials, N);
+      return 1;
+    }
+
+  return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-barrier3.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-barrier3.c
new file mode 100644
index 00000000..b5478f82
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-barrier3.c
@@ -0,0 +1,154 @@
+/* Copyright (C) 2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2002.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+/* Test of POSIX barriers.  */
+
+#include 
+#include 
+#include 
+#include 
+
+#define NTHREADS 20
+
+#define ROUNDS 20
+
+static pthread_barrier_t barriers[NTHREADS];
+
+static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
+static int counters[NTHREADS];
+static int serial[NTHREADS];
+
+static void *
+worker (void *arg)
+{
+  void *result = NULL;
+  int nr = (long int) arg;
+  int i;
+
+  for (i = 0; i < ROUNDS; ++i)
+    {
+      int j;
+      int retval;
+
+      if (nr == 0)
+	{
+	  memset (counters, '\0', sizeof (counters));
+	  memset (serial, '\0', sizeof (serial));
+	}
+
+      retval = pthread_barrier_wait (&barriers[NTHREADS - 1]);
+      if (retval != 0 && retval != PTHREAD_BARRIER_SERIAL_THREAD)
+	{
+	  printf ("thread %d failed to wait for all the others\n", nr);
+	  result = (void *) 1;
+	}
+
+      for (j = nr; j < NTHREADS; ++j)
+	{
+	  /* Increment the counter for this round.  */
+	  pthread_mutex_lock (&lock);
+	  ++counters[j];
+	  pthread_mutex_unlock (&lock);
+
+	  /* Wait for the rest.  */
+	  retval = pthread_barrier_wait (&barriers[j]);
+
+	  /* Test the result.  */
+	  if (nr == 0 && counters[j] != j + 1)
+	    {
+	      printf ("barrier in round %d released but count is %d\n",
+		      j, counters[j]);
+	      result = (void *) 1;
+	    }
+
+	  if (retval != 0)
+	    {
+	      if (retval != PTHREAD_BARRIER_SERIAL_THREAD)
+		{
+		  printf ("thread %d in round %d has nonzero return value != PTHREAD_BARRIER_SERIAL_THREAD\n",
+			  nr, j);
+		  result = (void *) 1;
+		}
+	      else
+		{
+		  pthread_mutex_lock (&lock);
+		  ++serial[j];
+		  pthread_mutex_unlock (&lock);
+		}
+	    }
+
+	  /* Wait for the rest again.  */
+	  retval = pthread_barrier_wait (&barriers[j]);
+
+	  /* Now we can check whether exactly one thread was serializing.  */
+	  if (nr == 0 && serial[j] != 1)
+	    {
+	      printf ("not exactly one serial thread in round %d\n", j);
+	      result = (void *) 1;
+	    }
+	}
+    }
+
+  return result;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#define TIMEOUT 60
+static int
+do_test (void)
+{
+  pthread_t threads[NTHREADS];
+  int i;
+  void *res;
+  int result = 0;
+
+  /* Initialized the barrier variables.  */
+  for (i = 0; i < NTHREADS; ++i)
+    if (pthread_barrier_init (&barriers[i], NULL, i + 1) != 0)
+      {
+	printf ("Failed to initialize barrier %d\n", i);
+	exit (1);
+      }
+
+  /* Start the threads.  */
+  for (i = 0; i < NTHREADS; ++i)
+    if (pthread_create (&threads[i], NULL, worker, (void *) (long int) i) != 0)
+      {
+	printf ("Failed to start thread %d\n", i);
+	exit (1);
+      }
+
+  /* And wait for them.  */
+  for (i = 0; i < NTHREADS; ++i)
+    if (pthread_join (threads[i], &res) != 0 || res != NULL)
+      {
+	printf ("thread %d returned a failure\n", i);
+	result = 1;
+      }
+    else
+      printf ("joined threads %d\n", i);
+
+  if (result == 0)
+    puts ("all OK");
+
+  return result;
+}
+
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-barrier4.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-barrier4.c
new file mode 100644
index 00000000..efc27551
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-barrier4.c
@@ -0,0 +1,122 @@
+/* Copyright (C) 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2004.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+/* This is a test for behavior not guaranteed by POSIX.  */
+#include 
+#include 
+#include 
+#include 
+
+
+static pthread_barrier_t b1;
+static pthread_barrier_t b2;
+
+
+#define N 20
+
+static void *
+tf (void *arg)
+{
+  int round = 0;
+
+  while (round++ < 30)
+    {
+      if (pthread_barrier_wait (&b1) == PTHREAD_BARRIER_SERIAL_THREAD)
+	{
+	  pthread_barrier_destroy (&b1);
+	  if (pthread_barrier_init (&b1, NULL, N) != 0)
+	    {
+	      puts ("tf: 1st barrier_init failed");
+	      exit (1);
+	    }
+	}
+
+      if (pthread_barrier_wait (&b2) == PTHREAD_BARRIER_SERIAL_THREAD)
+	{
+	  pthread_barrier_destroy (&b2);
+	  if (pthread_barrier_init (&b2, NULL, N) != 0)
+	    {
+	      puts ("tf: 2nd barrier_init failed");
+	      exit (1);
+	    }
+	}
+    }
+
+  return NULL;
+}
+
+
+static int
+do_test (void)
+{
+  pthread_attr_t at;
+  int cnt;
+
+  if (pthread_attr_init (&at) != 0)
+    {
+      puts ("attr_init failed");
+      return 1;
+    }
+
+  if (pthread_attr_setstacksize (&at, 1 * 1024 * 1024) != 0)
+    {
+      puts ("attr_setstacksize failed");
+      return 1;
+    }
+
+  if (pthread_barrier_init (&b1, NULL, N) != 0)
+    {
+      puts ("1st barrier_init failed");
+      return 1;
+    }
+
+  if (pthread_barrier_init (&b2, NULL, N) != 0)
+    {
+      puts ("2nd barrier_init failed");
+      return 1;
+    }
+
+  pthread_t th[N - 1];
+  for (cnt = 0; cnt < N - 1; ++cnt)
+    if (pthread_create (&th[cnt], &at, tf, NULL) != 0)
+      {
+	puts ("pthread_create failed");
+	return 1;
+      }
+
+  if (pthread_attr_destroy (&at) != 0)
+    {
+      puts ("attr_destroy failed");
+      return 1;
+    }
+
+  tf (NULL);
+
+  for (cnt = 0; cnt < N - 1; ++cnt)
+    if (pthread_join (th[cnt], NULL) != 0)
+      {
+	puts ("pthread_join failed");
+	return 1;
+      }
+
+  return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-basic1.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-basic1.c
new file mode 100644
index 00000000..7637c8e4
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-basic1.c
@@ -0,0 +1,82 @@
+/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2002.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+
+
+static pid_t pid;
+
+static void *
+tf (void *a)
+{
+  if (getpid () != pid)
+    {
+      write (2, "pid mismatch\n", 13);
+      _exit (1);
+    }
+
+  return a;
+}
+
+
+int
+do_test (void)
+{
+  pid = getpid ();
+
+#define N 2
+  pthread_t t[N];
+  int i;
+
+  for (i = 0; i < N; ++i)
+    if (pthread_create (&t[i], NULL, tf, (void *) (long int) (i + 1)) != 0)
+      {
+	write (2, "create failed\n", 14);
+	_exit (1);
+      }
+    else
+      printf ("created thread %d\n", i);
+
+  for (i = 0; i < N; ++i)
+    {
+      void *r;
+      int e;
+      if ((e = pthread_join (t[i], &r)) != 0)
+	{
+	  printf ("join failed: %d\n", e);
+	  _exit (1);
+	}
+      else if (r != (void *) (long int) (i + 1))
+	{
+	  write (2, "result wrong\n", 13);
+	  _exit (1);
+	}
+      else
+	printf ("joined thread %d\n", i);
+    }
+
+  return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-basic2.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-basic2.c
new file mode 100644
index 00000000..1c4632ce
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-basic2.c
@@ -0,0 +1,121 @@
+/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2002.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+#define N 20
+
+static pthread_t th[N];
+static pthread_mutex_t lock[N];
+
+
+static void *tf (void *a)
+{
+  uintptr_t idx = (uintptr_t) a;
+
+  pthread_mutex_lock (&lock[idx]);
+
+  return pthread_equal (pthread_self (), th[idx]) ? NULL : (void *) 1l;
+}
+
+
+int
+do_test (void)
+{
+  if (pthread_equal (pthread_self (), pthread_self ()) == 0)
+    {
+      puts ("pthread_equal (pthread_self (), pthread_self ()) failed");
+      exit (1);
+    }
+
+  pthread_attr_t at;
+
+  if (pthread_attr_init (&at) != 0)
+    {
+      puts ("attr_init failed");
+      return 1;
+    }
+
+  if (pthread_attr_setstacksize (&at, 1 * 1024 * 1024) != 0)
+    {
+      puts ("attr_setstacksize failed");
+      return 1;
+    }
+
+  int i;
+  for (i = 0; i < N; ++i)
+    {
+      if (pthread_mutex_init (&lock[i], NULL) != 0)
+	{
+	  puts ("mutex_init failed");
+	  exit (1);
+	}
+
+      if (pthread_mutex_lock (&lock[i]) != 0)
+	{
+	  puts ("mutex_lock failed");
+	  exit (1);
+	}
+
+      if (pthread_create (&th[i], &at, tf, (void *) (long int) i) != 0)
+	{
+	  puts ("create failed");
+	  exit (1);
+	}
+
+      if (pthread_mutex_unlock (&lock[i]) != 0)
+	{
+	  puts ("mutex_unlock failed");
+	  exit (1);
+	}
+
+      printf ("created thread %d\n", i);
+    }
+
+  if (pthread_attr_destroy (&at) != 0)
+    {
+      puts ("attr_destroy failed");
+      return 1;
+    }
+
+  int result = 0;
+  for (i = 0; i < N; ++i)
+    {
+      void *r;
+      int e;
+      if ((e = pthread_join (th[i], &r)) != 0)
+	{
+	  printf ("join failed: %d\n", e);
+	  _exit (1);
+	}
+      else if (r != NULL)
+	result = 1;
+    }
+
+  return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-basic3.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-basic3.c
new file mode 100644
index 00000000..cb4816d2
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-basic3.c
@@ -0,0 +1,87 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+static int nrunning = 1;
+
+
+static void
+final_test (void)
+{
+  puts ("final_test has been called");
+
+#define THE_SIGNAL SIGUSR1
+  kill (getpid (), SIGUSR1);
+}
+
+
+static void *
+tf (void *a)
+{
+  if (pthread_join ((pthread_t) a, NULL) != 0)
+    {
+      printf ("join failed while %d are running\n", nrunning);
+      _exit (1);
+    }
+
+  printf ("%2d left\n", --nrunning);
+
+  return NULL;
+}
+
+
+int
+do_test (void)
+{
+#define N 20
+  pthread_t t[N];
+  pthread_t last = pthread_self ();
+  int i;
+
+  atexit (final_test);
+
+  printf ("starting %d + 1 threads\n", N);
+  for (i = 0; i < N; ++i)
+    {
+      if (pthread_create (&t[i], NULL, tf, (void *) last) != 0)
+	{
+	  puts ("create failed");
+	  _exit (1);
+	}
+
+      ++nrunning;
+
+      last = t[i];
+    }
+
+  printf ("%2d left\n", --nrunning);
+
+  pthread_exit (NULL);
+}
+
+
+#define EXPECTED_SIGNAL THE_SIGNAL
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-basic4.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-basic4.c
new file mode 100644
index 00000000..6eb6ea9f
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-basic4.c
@@ -0,0 +1,101 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+static void
+final_test (void)
+{
+  puts ("final_test has been called");
+
+#define THE_SIGNAL SIGUSR1
+  kill (getpid (), SIGUSR1);
+}
+
+
+static void *
+tf (void *a)
+{
+  pid_t pid = fork ();
+  if (pid == -1)
+    {
+      puts ("fork failed");
+      exit (1);
+    }
+
+  if (pid == 0)
+    {
+      atexit (final_test);
+
+      pthread_exit (NULL);
+    }
+
+  int r;
+  int e = TEMP_FAILURE_RETRY (waitpid (pid, &r, 0));
+  if (e != pid)
+    {
+      puts ("waitpid failed");
+      exit (1);
+    }
+
+  if (! WIFSIGNALED (r))
+    {
+      puts ("child not signled");
+      exit (1);
+    }
+
+  if (WTERMSIG (r) != THE_SIGNAL)
+    {
+      puts ("child's termination signal wrong");
+      exit (1);
+    }
+
+  return NULL;
+}
+
+
+int
+do_test (void)
+{
+  pthread_t th;
+
+  if (pthread_create (&th, NULL, tf, NULL) != 0)
+    {
+      puts ("create failed");
+      _exit (1);
+    }
+
+  if (pthread_join (th, NULL) != 0)
+    {
+      puts ("join failed");
+      exit (1);
+    }
+
+  return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-basic5.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-basic5.c
new file mode 100644
index 00000000..83a8810f
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-basic5.c
@@ -0,0 +1,74 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+
+
+
+int
+do_test (void)
+{
+  int c = pthread_getconcurrency ();
+  if (c != 0)
+    {
+      puts ("initial concurrencylevel wrong");
+      exit (1);
+    }
+
+  if (pthread_setconcurrency (1) != 0)
+    {
+      puts ("setconcurrency failed");
+      exit (1);
+    }
+
+  c = pthread_getconcurrency ();
+  if (c != 1)
+    {
+      puts ("getconcurrency didn't return the value previous set");
+      exit (1);
+    }
+
+  int e = pthread_setconcurrency (-1);
+  if (e == 0)
+    {
+      puts ("setconcurrency of negative value didn't failed");
+      exit (1);
+    }
+  if (e != EINVAL)
+    {
+      puts ("setconcurrency didn't return EINVAL for negative value");
+      exit (1);
+    }
+
+  c = pthread_getconcurrency ();
+  if (c != 1)
+    {
+      puts ("invalid getconcurrency changed level");
+      exit (1);
+    }
+
+  return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-basic6.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-basic6.c
new file mode 100644
index 00000000..413ae034
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-basic6.c
@@ -0,0 +1,132 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+static char *p;
+
+static pthread_barrier_t b;
+#define BT \
+  e = pthread_barrier_wait (&b);					      \
+  if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)			      \
+    {									      \
+      puts ("barrier_wait failed");					      \
+      exit (1);								      \
+    }
+
+
+static void *
+tf (void *a)
+{
+  int e;
+
+  BT;
+
+  char *p2 = getcwd (NULL, 0);
+  if (p2 == NULL)
+    {
+      puts ("2nd getcwd failed");
+      exit (1);
+    }
+
+  if (strcmp (p, p2) != 0)
+    {
+      printf ("initial cwd mismatch: \"%s\" vs \"%s\"\n", p, p2);
+      exit (1);
+    }
+
+  free (p);
+  free (p2);
+
+  if (chdir ("..") != 0)
+    {
+      puts ("chdir failed");
+      exit (1);
+    }
+
+  p = getcwd (NULL, 0);
+  if (p == NULL)
+    {
+      puts ("getcwd failed");
+      exit (1);
+    }
+
+  return a;
+}
+
+
+int
+do_test (void)
+{
+  if (pthread_barrier_init (&b, NULL, 2) != 0)
+    {
+      puts ("barrier_init failed");
+      exit (1);
+    }
+
+  pthread_t th;
+  if (pthread_create (&th, NULL, tf, NULL) != 0)
+    {
+      puts ("create failed");
+      exit (1);
+    }
+
+  p = getcwd (NULL, 0);
+  if (p == NULL)
+    {
+      puts ("getcwd failed");
+      exit (1);
+    }
+
+  int e;
+  BT;
+
+  if (pthread_join (th, NULL) != 0)
+    {
+      puts ("join failed");
+      exit (1);
+    }
+
+  char *p2 = getcwd (NULL, 0);
+  if (p2 == NULL)
+    {
+      puts ("2nd getcwd failed");
+      exit (1);
+    }
+
+  if (strcmp (p, p2) != 0)
+    {
+      printf ("cwd after chdir mismatch: \"%s\" vs \"%s\"\n", p, p2);
+      exit (1);
+    }
+
+  free (p);
+  free (p2);
+
+  return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-basic7.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-basic7.c
new file mode 100644
index 00000000..15b61878
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-basic7.c
@@ -0,0 +1,75 @@
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+static void use_stack (size_t needed);
+
+void (*use_stack_ptr) (size_t) = use_stack;
+
+static void
+use_stack (size_t needed)
+{
+  size_t sz = sysconf (_SC_PAGESIZE);
+  char *buf = alloca (sz);
+  memset (buf, '\0', sz);
+
+  if (needed > sz)
+    use_stack_ptr (needed  - sz);
+}
+
+static void
+use_up_memory (void)
+{
+  struct rlimit rl;
+  getrlimit (RLIMIT_AS, &rl);
+  rl.rlim_cur = 10 * 1024 * 1024;
+  setrlimit (RLIMIT_AS, &rl);
+
+  char *c;
+  int PAGESIZE = getpagesize ();
+  while (1)
+    {
+      c = mmap (NULL, PAGESIZE, PROT_NONE, MAP_ANON | MAP_PRIVATE, -1, 0);
+      if (c == MAP_FAILED)
+	break;
+    }
+}
+
+static void *
+child (void *arg)
+{
+  sleep (1);
+  return arg;
+}
+
+static int
+do_test (void)
+{
+  int err;
+  pthread_t tid;
+
+  /* Allocate the memory needed for the stack.  */
+  use_stack_ptr (PTHREAD_STACK_MIN);
+
+  use_up_memory ();
+
+  err = pthread_create (&tid, NULL, child, NULL);
+  if (err != 0)
+    {
+      printf ("pthread_create returns %d: %s\n", err,
+	      err == EAGAIN ? "OK" : "FAIL");
+      return err != EAGAIN;
+    }
+
+  /* We did not fail to allocate memory despite the preparation.  Oh well.  */
+  return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel1.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel1.c
new file mode 100644
index 00000000..690319d8
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel1.c
@@ -0,0 +1,163 @@
+/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2002.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+static pthread_mutex_t m1 = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t m2 = PTHREAD_MUTEX_INITIALIZER;
+
+static int cntr;
+
+
+static void
+cleanup (void *arg)
+{
+  if (arg != (void *) 42l)
+    cntr = 42;
+  else
+    cntr = 1;
+}
+
+
+static void *
+tf (void *arg)
+{
+  /* Ignore all signals.  This must not have any effect on delivering
+     the cancellation signal.  */
+  sigset_t ss;
+
+  sigfillset (&ss);
+
+  if (pthread_sigmask (SIG_BLOCK, &ss, NULL) != 0)
+    {
+      puts ("pthread_sigmask failed");
+      exit (1);
+    }
+
+  pthread_cleanup_push (cleanup, (void *) 42l);
+
+  int err = pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
+  if (err != 0)
+    {
+      printf ("setcanceltype failed: %s\n", strerror (err));
+      exit (1);
+    }
+  /* The following code is not standard compliant: the mutex functions
+     must not be called with asynchronous cancellation enabled.  */
+
+  err = pthread_mutex_unlock (&m2);
+  if (err != 0)
+    {
+      printf ("child: mutex_unlock failed: %s\n", strerror (err));
+      exit (1);
+    }
+
+  err = pthread_mutex_lock (&m1);
+  if (err != 0)
+    {
+      printf ("child: 1st mutex_lock failed: %s\n", strerror (err));
+      exit (1);
+    }
+
+  /* We should never come here.  */
+
+  pthread_cleanup_pop (0);
+
+  return NULL;
+}
+
+
+static int
+do_test (void)
+{
+  int err;
+  pthread_t th;
+  int result = 0;
+  void *retval;
+
+  /* Get the mutexes.  */
+  err = pthread_mutex_lock (&m1);
+  if (err != 0)
+    {
+      printf ("parent: 1st mutex_lock failed: %s\n", strerror (err));
+      return 1;
+    }
+  err = pthread_mutex_lock (&m2);
+  if (err != 0)
+    {
+      printf ("parent: 2nd mutex_lock failed: %s\n", strerror (err));
+      return 1;
+    }
+
+  err = pthread_create (&th, NULL, tf, NULL);
+  if (err != 0)
+    {
+      printf ("create failed: %s\n", strerror (err));
+      return 1;
+    }
+
+  err = pthread_mutex_lock (&m2);
+  if (err != 0)
+    {
+      printf ("parent: 3rd mutex_lock failed: %s\n", strerror (err));
+      return 1;
+    }
+
+  err = pthread_cancel (th);
+  if (err != 0)
+    {
+      printf ("cancel failed: %s\n", strerror (err));
+      return 1;
+    }
+
+  err = pthread_join (th, &retval);
+  if (err != 0)
+    {
+      printf ("join failed: %s\n", strerror (err));
+      return 1;
+    }
+
+  if (retval != PTHREAD_CANCELED)
+    {
+      printf ("wrong return value: %p\n", retval);
+      result = 1;
+    }
+
+  if (cntr == 42)
+    {
+      puts ("cleanup handler called with wrong argument");
+      result = 1;
+    }
+  else if (cntr != 1)
+    {
+      puts ("cleanup handling not called");
+      result = 1;
+    }
+
+  return result;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel10.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel10.c
new file mode 100644
index 00000000..7af0f2f8
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel10.c
@@ -0,0 +1,126 @@
+/* Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+
+
+static void
+cleanup (void *arg)
+{
+  /* Just for fun.  */
+  if (pthread_cancel (pthread_self ()) != 0)
+    {
+      puts ("cleanup: cancel failed");
+      exit (1);
+    }
+
+  printf ("cleanup for %ld\n", (long int) arg);
+}
+
+
+static void *
+tf (void *arg)
+{
+  long int n = (long int) arg;
+
+  pthread_cleanup_push (cleanup, arg);
+
+  if (pthread_setcanceltype ((n & 1) == 0
+			     ? PTHREAD_CANCEL_DEFERRED
+			     : PTHREAD_CANCEL_ASYNCHRONOUS, NULL) != 0)
+    {
+      puts ("setcanceltype failed");
+      exit (1);
+    }
+
+  if (pthread_cancel (pthread_self ()) != 0)
+    {
+      puts ("cancel failed");
+      exit (1);
+    }
+
+  pthread_testcancel ();
+
+  /* We should never come here.  */
+
+  pthread_cleanup_pop (0);
+
+  return NULL;
+}
+
+
+static int
+do_test (void)
+{
+  pthread_attr_t at;
+
+  if (pthread_attr_init (&at) != 0)
+    {
+      puts ("attr_init failed");
+      return 1;
+    }
+
+  if (pthread_attr_setstacksize (&at, 1 * 1024 * 1024) != 0)
+    {
+      puts ("attr_setstacksize failed");
+      return 1;
+    }
+
+#define N 20
+  int i;
+  pthread_t th[N];
+
+  for (i = 0; i < N; ++i)
+    if (pthread_create (&th[i], &at, tf, (void *) (long int) i) != 0)
+      {
+	puts ("create failed");
+	exit (1);
+      }
+
+  if (pthread_attr_destroy (&at) != 0)
+    {
+      puts ("attr_destroy failed");
+      return 1;
+    }
+
+  for (i = 0; i < N; ++i)
+    {
+      void *r;
+      if (pthread_join (th[i], &r) != 0)
+	{
+	  puts ("join failed");
+	  exit (1);
+	}
+
+      if (r != PTHREAD_CANCELED)
+	{
+	  puts ("thread not canceled");
+	  exit (1);
+	}
+    }
+
+  return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel11.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel11.c
new file mode 100644
index 00000000..235aef5c
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel11.c
@@ -0,0 +1,123 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+static pthread_barrier_t bar;
+static int fd[2];
+
+
+static void
+cleanup (void *arg)
+{
+  static int ncall;
+
+  if (++ncall != 1)
+    {
+      puts ("second call to cleanup");
+      exit (1);
+    }
+
+  printf ("cleanup call #%d\n", ncall);
+}
+
+
+static void *
+tf (void *arg)
+{
+  pthread_cleanup_push (cleanup, NULL);
+
+  int e = pthread_barrier_wait (&bar);
+  if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("tf: 1st barrier_wait failed");
+      exit (1);
+    }
+
+  /* This call should block and be cancelable.  */
+  char buf[20];
+  read (fd[0], buf, sizeof (buf));
+
+  pthread_cleanup_pop (0);
+
+  return NULL;
+}
+
+
+static int
+do_test (void)
+{
+  pthread_t th;
+
+  if (pthread_barrier_init (&bar, NULL, 2) != 0)
+    {
+      puts ("barrier_init failed");
+      exit (1);
+    }
+
+  if (pipe (fd) != 0)
+    {
+      puts ("pipe failed");
+      exit (1);
+    }
+
+  if (pthread_create (&th, NULL, tf, NULL) != 0)
+    {
+      puts ("create failed");
+      exit (1);
+    }
+
+  int e = pthread_barrier_wait (&bar);
+  if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("1st barrier_wait failed");
+      exit (1);
+    }
+
+  if (pthread_cancel (th) != 0)
+    {
+      puts ("1st cancel failed");
+      exit (1);
+    }
+
+  void *r;
+  if (pthread_join (th, &r) != 0)
+    {
+      puts ("join failed");
+      exit (1);
+    }
+
+  if (r != PTHREAD_CANCELED)
+    {
+      puts ("thread not canceled");
+      exit (1);
+    }
+
+  return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel12.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel12.c
new file mode 100644
index 00000000..6fdf5cf5
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel12.c
@@ -0,0 +1,127 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+static pthread_barrier_t bar;
+static sem_t sem;
+
+
+static void
+cleanup (void *arg)
+{
+  static int ncall;
+
+  if (++ncall != 1)
+    {
+      puts ("second call to cleanup");
+      exit (1);
+    }
+
+  printf ("cleanup call #%d\n", ncall);
+}
+
+
+static void *
+tf (void *arg)
+{
+  pthread_cleanup_push (cleanup, NULL);
+
+  int e = pthread_barrier_wait (&bar);
+  if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("tf: 1st barrier_wait failed");
+      exit (1);
+    }
+
+  /* This call should block and be cancelable.  */
+  sem_wait (&sem);
+
+  pthread_cleanup_pop (0);
+
+  puts ("sem_wait returned");
+
+  return NULL;
+}
+
+
+static int
+do_test (void)
+{
+  pthread_t th;
+
+  if (pthread_barrier_init (&bar, NULL, 2) != 0)
+    {
+      puts ("barrier_init failed");
+      exit (1);
+    }
+
+  if (sem_init (&sem, 0, 1) != 0)
+    {
+      puts ("sem_init failed");
+      exit (1);
+    }
+
+  if (pthread_create (&th, NULL, tf, NULL) != 0)
+    {
+      puts ("create failed");
+      exit (1);
+    }
+
+  /* Check whether cancellation is honored even before sem_wait does
+     anything.  */
+  if (pthread_cancel (th) != 0)
+    {
+      puts ("1st cancel failed");
+      exit (1);
+    }
+
+  int e = pthread_barrier_wait (&bar);
+  if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("1st barrier_wait failed");
+      exit (1);
+    }
+
+  void *r;
+  if (pthread_join (th, &r) != 0)
+    {
+      puts ("join failed");
+      exit (1);
+    }
+
+  if (r != PTHREAD_CANCELED)
+    {
+      puts ("thread not canceled");
+      exit (1);
+    }
+
+  return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel13.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel13.c
new file mode 100644
index 00000000..66ab4550
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel13.c
@@ -0,0 +1,129 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+static pthread_barrier_t bar;
+static sem_t sem;
+
+
+static void
+cleanup (void *arg)
+{
+  static int ncall;
+
+  if (++ncall != 1)
+    {
+      puts ("second call to cleanup");
+      exit (1);
+    }
+
+  printf ("cleanup call #%d\n", ncall);
+}
+
+
+static void *
+tf (void *arg)
+{
+  pthread_cleanup_push (cleanup, NULL);
+
+  int e = pthread_barrier_wait (&bar);
+  if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("tf: 1st barrier_wait failed");
+      exit (1);
+    }
+
+  /* This call should block and be cancelable.  */
+  sem_wait (&sem);
+
+  pthread_cleanup_pop (0);
+
+  puts ("sem_wait returned");
+
+  return NULL;
+}
+
+
+static int
+do_test (void)
+{
+  pthread_t th;
+
+  if (pthread_barrier_init (&bar, NULL, 2) != 0)
+    {
+      puts ("barrier_init failed");
+      exit (1);
+    }
+
+  if (sem_init (&sem, 0, 0) != 0)
+    {
+      puts ("sem_init failed");
+      exit (1);
+    }
+
+  if (pthread_create (&th, NULL, tf, NULL) != 0)
+    {
+      puts ("create failed");
+      exit (1);
+    }
+
+  int e = pthread_barrier_wait (&bar);
+  if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("1st barrier_wait failed");
+      exit (1);
+    }
+
+  /* Give the child a chance to go to sleep in sem_wait.  */
+  sleep (1);
+
+  /* Check whether cancellation is honored when waiting in sem_wait.  */
+  if (pthread_cancel (th) != 0)
+    {
+      puts ("1st cancel failed");
+      exit (1);
+    }
+
+  void *r;
+  if (pthread_join (th, &r) != 0)
+    {
+      puts ("join failed");
+      exit (1);
+    }
+
+  if (r != PTHREAD_CANCELED)
+    {
+      puts ("thread not canceled");
+      exit (1);
+    }
+
+  return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel14.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel14.c
new file mode 100644
index 00000000..592c0864
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel14.c
@@ -0,0 +1,137 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+static pthread_barrier_t bar;
+static sem_t sem;
+
+
+static void
+cleanup (void *arg)
+{
+  static int ncall;
+
+  if (++ncall != 1)
+    {
+      puts ("second call to cleanup");
+      exit (1);
+    }
+
+  printf ("cleanup call #%d\n", ncall);
+}
+
+
+static void *
+tf (void *arg)
+{
+  pthread_cleanup_push (cleanup, NULL);
+
+  int e = pthread_barrier_wait (&bar);
+  if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("tf: 1st barrier_wait failed");
+      exit (1);
+    }
+
+  struct timeval tv;
+  (void) gettimeofday (&tv, NULL);
+
+  struct timespec ts;
+  TIMEVAL_TO_TIMESPEC (&tv, &ts);
+
+  /* Timeout in 5 seconds.  */
+  ts.tv_sec += 5;
+
+  /* This call should block and be cancelable.  */
+  sem_timedwait (&sem, &ts);
+
+  pthread_cleanup_pop (0);
+
+  puts ("sem_timedwait returned");
+
+  return NULL;
+}
+
+
+static int
+do_test (void)
+{
+  pthread_t th;
+
+  if (pthread_barrier_init (&bar, NULL, 2) != 0)
+    {
+      puts ("barrier_init failed");
+      exit (1);
+    }
+
+  if (sem_init (&sem, 0, 1) != 0)
+    {
+      puts ("sem_init failed");
+      exit (1);
+    }
+
+  if (pthread_create (&th, NULL, tf, NULL) != 0)
+    {
+      puts ("create failed");
+      exit (1);
+    }
+
+  /* Check whether cancellation is honored even before sem_timedwait does
+     anything.  */
+  if (pthread_cancel (th) != 0)
+    {
+      puts ("1st cancel failed");
+      exit (1);
+    }
+
+  int e = pthread_barrier_wait (&bar);
+  if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("1st barrier_wait failed");
+      exit (1);
+    }
+
+  void *r;
+  if (pthread_join (th, &r) != 0)
+    {
+      puts ("join failed");
+      exit (1);
+    }
+
+  if (r != PTHREAD_CANCELED)
+    {
+      puts ("thread not canceled");
+      exit (1);
+    }
+
+  return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel15.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel15.c
new file mode 100644
index 00000000..5fd95022
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel15.c
@@ -0,0 +1,142 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+static pthread_barrier_t bar;
+static sem_t sem;
+
+
+static void
+cleanup (void *arg)
+{
+  static int ncall;
+
+  if (++ncall != 1)
+    {
+      puts ("second call to cleanup");
+      exit (1);
+    }
+
+  printf ("cleanup call #%d\n", ncall);
+}
+
+
+static void *
+tf (void *arg)
+{
+  int e;
+
+  pthread_cleanup_push (cleanup, NULL);
+
+  e = pthread_barrier_wait (&bar);
+  if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("tf: 1st barrier_wait failed");
+      exit (1);
+    }
+
+  struct timeval tv;
+  (void) gettimeofday (&tv, NULL);
+
+  struct timespec ts;
+  TIMEVAL_TO_TIMESPEC (&tv, &ts);
+
+  /* Timeout in 5 seconds.  */
+  ts.tv_sec += 5;
+
+  /* This call should block and be cancelable.  */
+  errno = 0;
+  e = sem_timedwait (&sem, &ts);
+
+  pthread_cleanup_pop (0);
+
+  printf ("sem_timedwait returned, e = %d, errno = %d\n", e, errno);
+
+  return NULL;
+}
+
+
+static int
+do_test (void)
+{
+  pthread_t th;
+
+  if (pthread_barrier_init (&bar, NULL, 2) != 0)
+    {
+      puts ("barrier_init failed");
+      exit (1);
+    }
+
+  if (sem_init (&sem, 0, 0) != 0)
+    {
+      puts ("sem_init failed");
+      exit (1);
+    }
+
+  if (pthread_create (&th, NULL, tf, NULL) != 0)
+    {
+      puts ("create failed");
+      exit (1);
+    }
+
+  int e = pthread_barrier_wait (&bar);
+  if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("1st barrier_wait failed");
+      exit (1);
+    }
+
+  /* Give the child a chance to go to sleep in sem_wait.  */
+  sleep (1);
+
+  /* Check whether cancellation is honored when waiting in sem_timedwait.  */
+  if (pthread_cancel (th) != 0)
+    {
+      puts ("1st cancel failed");
+      exit (1);
+    }
+
+  void *r;
+  if (pthread_join (th, &r) != 0)
+    {
+      puts ("join failed");
+      exit (1);
+    }
+
+  if (r != PTHREAD_CANCELED)
+    {
+      puts ("thread not canceled");
+      exit (1);
+    }
+
+  return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel16.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel16.c
new file mode 100644
index 00000000..709902e9
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel16.c
@@ -0,0 +1,231 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+static pthread_barrier_t b2;
+static int fd;
+static int called;
+
+
+static void
+cl (void *arg)
+{
+  called = 1;
+}
+
+
+static void *
+tf (void *arg)
+{
+  int r = pthread_barrier_wait (&b2);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("child thread: barrier_wait failed");
+      exit (1);
+    }
+
+  pthread_cleanup_push (cl, NULL);
+
+  /* This call should never return.  */
+  (void) lockf (fd, F_LOCK, 0);
+
+  pthread_cleanup_pop (0);
+
+  return NULL;
+}
+
+
+static int
+do_test (void)
+{
+  char fname[] = "/tmp/cancel16XXXXXX";
+  fd = mkstemp (fname);
+  if (fd == -1)
+    {
+      puts ("mkstemp failed");
+      return 1;
+    }
+  unlink (fname);
+
+  char mem[sizeof (pthread_barrier_t)];
+  memset (mem, '\0', sizeof (mem));
+  if (TEMP_FAILURE_RETRY (pwrite (fd, mem, sizeof (mem), 0)) != sizeof (mem))
+    {
+      puts ("pwrite failed");
+      return 1;
+    }
+
+  void *p = mmap (NULL, sizeof (mem), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
+  if (p == MAP_FAILED)
+    {
+      puts ("mmap failed");
+      return 1;
+    }
+  pthread_barrier_t *b = (pthread_barrier_t *) p;
+
+  pthread_barrierattr_t ba;
+  if (pthread_barrierattr_init (&ba) != 0)
+    {
+      puts ("barrierattr_init failed");
+      return 1;
+    }
+  if (pthread_barrierattr_setpshared (&ba, 1) != 0)
+    {
+      puts ("barrierattr_setshared failed");
+      return 1;
+    }
+
+  if (pthread_barrier_init (b, &ba, 2) != 0)
+    {
+      puts ("1st barrier_init failed");
+      return 1;
+    }
+  if (pthread_barrierattr_destroy (&ba) != 0)
+    {
+      puts ("barrier_destroy failed");
+      return 1;
+    }
+
+  pid_t pid = fork ();
+  if (pid == 0)
+    {
+      /* Child.  Lock the file and wait.  */
+      if (lockf (fd, F_LOCK, 0) != 0)
+	{
+	  puts ("child process: lockf failed");
+	  _exit (1);
+	}
+
+      int r = pthread_barrier_wait (b);
+      if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+	{
+	  puts ("child process: 1st barrier_wait failed");
+	  _exit (1);
+	}
+
+      /* Make sure the process dies.  */
+      alarm (5);
+
+      r = pthread_barrier_wait (b);
+      if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+	{
+	  puts ("child process: 2nd barrier_wait failed");
+	  _exit (1);
+	}
+
+      _exit (0);
+    }
+  if (pid == -1)
+    {
+      puts ("fork failed");
+      return 1;
+    }
+
+  int r = pthread_barrier_wait (b);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("main: 1st barrier_wait failed");
+      _exit (1);
+    }
+
+  if (pthread_barrier_init (&b2, NULL, 2) != 0)
+    {
+      puts ("2nd barrier_init failed");
+      return 1;
+    }
+
+  pthread_t th;
+  if (pthread_create (&th, NULL, tf, NULL) != 0)
+    {
+      puts ("create failed");
+      return 1;
+    }
+
+  r = pthread_barrier_wait (&b2);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("main: 2nd barrier_wait failed");
+      return 1;
+    }
+
+  /* Delay.  */
+  sleep (1);
+
+  if (pthread_cancel (th) != 0)
+    {
+      puts ("cancel failed");
+      return 1;
+    }
+
+  void *result;
+  if (pthread_join (th, &result) != 0)
+    {
+      puts ("join failed");
+      return 1;
+    }
+  if (result != PTHREAD_CANCELED)
+    {
+      puts ("thread not canceled");
+      return 1;
+    }
+  if (called == 0)
+    {
+      puts ("cleanup handler not called");
+      return 1;
+    }
+
+  r = pthread_barrier_wait (b);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("main: 3rd barrier_wait failed");
+      return 1;
+    }
+
+  int status;
+  if (TEMP_FAILURE_RETRY (waitpid (pid, &status, 0)) != pid)
+    {
+      puts ("waitpid failed");
+      return 1;
+    }
+  if (WEXITSTATUS (status) != 0)
+    {
+      printf ("child process exits with %d\n", WEXITSTATUS (status));
+      return 1;
+    }
+
+  if (lockf (fd, F_LOCK, 0) != 0)
+    {
+      puts ("main: lockf failed");
+      return 1;
+    }
+
+  return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel18.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel18.c
new file mode 100644
index 00000000..15e9ddfb
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel18.c
@@ -0,0 +1,174 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+static pthread_barrier_t b;
+
+
+/* Cleanup handling test.  */
+static int cl_called;
+
+static void
+cl (void *arg)
+{
+  ++cl_called;
+}
+
+
+static void *
+tf (void *arg)
+{
+  int r = pthread_barrier_wait (&b);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("barrier_wait failed");
+      exit (1);
+    }
+
+  pthread_cleanup_push (cl, NULL);
+
+  struct timespec ts = { .tv_sec = arg == NULL ? 10000000 : 0, .tv_nsec = 0 };
+  TEMP_FAILURE_RETRY (clock_nanosleep (CLOCK_REALTIME, 0, &ts, &ts));
+
+  pthread_cleanup_pop (0);
+
+  puts ("clock_nanosleep returned");
+
+  exit (1);
+}
+
+
+static int
+do_test (void)
+{
+  if (pthread_barrier_init (&b, NULL, 2) != 0)
+    {
+      puts ("barrier_init failed");
+      return 1;
+    }
+
+  pthread_t th;
+  if (pthread_create (&th, NULL, tf, NULL) != 0)
+    {
+      puts ("1st create failed");
+      return 1;
+    }
+
+  int r = pthread_barrier_wait (&b);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("barrier_wait failed");
+      exit (1);
+    }
+
+  struct timespec  ts = { .tv_sec = 0, .tv_nsec = 100000000 };
+  while (nanosleep (&ts, &ts) != 0)
+    continue;
+
+  puts ("going to cancel in-time");
+  if (pthread_cancel (th) != 0)
+    {
+      puts ("1st cancel failed");
+      return 1;
+    }
+
+  void *status;
+  if (pthread_join (th, &status) != 0)
+    {
+      puts ("1st join failed");
+      return 1;
+    }
+  if (status != PTHREAD_CANCELED)
+    {
+      puts ("1st thread not canceled");
+      return 1;
+    }
+
+  if (cl_called == 0)
+    {
+      puts ("cleanup handler not called");
+      return 1;
+    }
+  if (cl_called > 1)
+    {
+      puts ("cleanup handler called more than once");
+      return 1;
+    }
+
+  puts ("in-time cancellation succeeded");
+
+
+  cl_called = 0;
+
+  if (pthread_create (&th, NULL, tf, NULL) != 0)
+    {
+      puts ("2nd create failed");
+      return 1;
+    }
+
+  puts ("going to cancel early");
+  if (pthread_cancel (th) != 0)
+    {
+      puts ("2nd cancel failed");
+      return 1;
+    }
+
+  r = pthread_barrier_wait (&b);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("barrier_wait failed");
+      exit (1);
+    }
+
+  if (pthread_join (th, &status) != 0)
+    {
+      puts ("2nd join failed");
+      return 1;
+    }
+  if (status != PTHREAD_CANCELED)
+    {
+      puts ("2nd thread not canceled");
+      return 1;
+    }
+
+  if (cl_called == 0)
+    {
+      printf ("cleanup handler not called\n");
+      return 1;
+    }
+  if (cl_called > 1)
+    {
+      printf ("cleanup handler called more than once\n");
+      return 1;
+    }
+
+  puts ("early cancellation succeeded");
+
+  return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel19.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel19.c
new file mode 100644
index 00000000..b346f602
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel19.c
@@ -0,0 +1,287 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek , 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+static void *
+tf (void *arg)
+{
+  return NULL;
+}
+
+static void
+handler (int sig)
+{
+}
+
+static void __attribute__ ((noinline))
+clobber_lots_of_regs (void)
+{
+#define X1(n) long r##n = 10##n; __asm__ __volatile__ ("" : "+r" (r##n));
+#define X2(n) X1(n##0) X1(n##1) X1(n##2) X1(n##3) X1(n##4)
+#define X3(n) X2(n##0) X2(n##1) X2(n##2) X2(n##3) X2(n##4)
+  X3(0) X3(1) X3(2) X3(3) X3(4)
+#undef X1
+#define X1(n) __asm__ __volatile__ ("" : : "r" (r##n));
+  X3(0) X3(1) X3(2) X3(3) X3(4)
+#undef X1
+#undef X2
+#undef X3
+}
+
+static int
+do_test (void)
+{
+  pthread_t th;
+  int old, rc;
+  int ret = 0;
+  int fd[2];
+
+  rc = pipe (fd);
+  if (rc < 0)
+    error (EXIT_FAILURE, errno, "couldn't create pipe");
+
+  rc = pthread_create (&th, NULL, tf, NULL);
+  if (rc)
+    error (EXIT_FAILURE, rc, "couldn't create thread");
+
+  rc = pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, &old);
+  if (rc)
+    {
+      error (0, rc, "1st pthread_setcanceltype failed");
+      ret = 1;
+    }
+  if (old != PTHREAD_CANCEL_DEFERRED && old != PTHREAD_CANCEL_ASYNCHRONOUS)
+    {
+      error (0, 0, "1st pthread_setcanceltype returned invalid value %d",
+	     old);
+      ret = 1;
+    }
+
+  clobber_lots_of_regs ();
+  close (fd[0]);
+
+  rc = pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &old);
+  if (rc)
+    {
+      error (0, rc, "pthread_setcanceltype after close failed");
+      ret = 1;
+    }
+  if (old != PTHREAD_CANCEL_DEFERRED)
+    {
+      error (0, 0, "pthread_setcanceltype after close returned invalid value %d",
+	     old);
+      ret = 1;
+    }
+
+  clobber_lots_of_regs ();
+  close (fd[1]);
+
+  rc = pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, &old);
+  if (rc)
+    {
+      error (0, rc, "pthread_setcanceltype after 2nd close failed");
+      ret = 1;
+    }
+  if (old != PTHREAD_CANCEL_ASYNCHRONOUS)
+    {
+      error (0, 0, "pthread_setcanceltype after 2nd close returned invalid value %d",
+	     old);
+      ret = 1;
+    }
+
+  struct sigaction sa = { .sa_handler = handler, .sa_flags = 0 };
+  sigemptyset (&sa.sa_mask);
+  sigaction (SIGALRM, &sa, NULL);
+
+  struct itimerval it;
+  it.it_value.tv_sec = 1;
+  it.it_value.tv_usec = 0;
+  it.it_interval = it.it_value;
+  setitimer (ITIMER_REAL, &it, NULL);
+
+  clobber_lots_of_regs ();
+  pause ();
+
+  memset (&it, 0, sizeof (it));
+  setitimer (ITIMER_REAL, &it, NULL);
+
+  rc = pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &old);
+  if (rc)
+    {
+      error (0, rc, "pthread_setcanceltype after pause failed");
+      ret = 1;
+    }
+  if (old != PTHREAD_CANCEL_DEFERRED)
+    {
+      error (0, 0, "pthread_setcanceltype after pause returned invalid value %d",
+	     old);
+      ret = 1;
+    }
+
+  it.it_value.tv_sec = 1;
+  it.it_value.tv_usec = 0;
+  it.it_interval = it.it_value;
+  setitimer (ITIMER_REAL, &it, NULL);
+
+  clobber_lots_of_regs ();
+  pause ();
+
+  memset (&it, 0, sizeof (it));
+  setitimer (ITIMER_REAL, &it, NULL);
+
+  rc = pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, &old);
+  if (rc)
+    {
+      error (0, rc, "pthread_setcanceltype after 2nd pause failed");
+      ret = 1;
+    }
+  if (old != PTHREAD_CANCEL_ASYNCHRONOUS)
+    {
+      error (0, 0, "pthread_setcanceltype after 2nd pause returned invalid value %d",
+	     old);
+      ret = 1;
+    }
+
+  char fname[] = "/tmp/tst-cancel19-dir-XXXXXX\0foo/bar";
+  char *enddir = strchr (fname, '\0');
+  if (mkdtemp (fname) == NULL)
+    {
+      error (0, errno, "mkdtemp failed");
+      ret = 1;
+    }
+  *enddir = '/';
+
+  clobber_lots_of_regs ();
+  creat (fname, 0400);
+
+  rc = pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &old);
+  if (rc)
+    {
+      error (0, rc, "pthread_setcanceltype after creat failed");
+      ret = 1;
+    }
+  if (old != PTHREAD_CANCEL_DEFERRED)
+    {
+      error (0, 0, "pthread_setcanceltype after creat returned invalid value %d",
+	     old);
+      ret = 1;
+    }
+
+  clobber_lots_of_regs ();
+  creat (fname, 0400);
+
+  rc = pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, &old);
+  if (rc)
+    {
+      error (0, rc, "pthread_setcanceltype after 2nd creat failed");
+      ret = 1;
+    }
+  if (old != PTHREAD_CANCEL_ASYNCHRONOUS)
+    {
+      error (0, 0, "pthread_setcanceltype after 2nd creat returned invalid value %d",
+	     old);
+      ret = 1;
+    }
+
+  clobber_lots_of_regs ();
+  open (fname, O_CREAT, 0400);
+
+  rc = pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &old);
+  if (rc)
+    {
+      error (0, rc, "pthread_setcanceltype after open failed");
+      ret = 1;
+    }
+  if (old != PTHREAD_CANCEL_DEFERRED)
+    {
+      error (0, 0, "pthread_setcanceltype after open returned invalid value %d",
+	     old);
+      ret = 1;
+    }
+
+  clobber_lots_of_regs ();
+  open (fname, O_CREAT, 0400);
+
+  rc = pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, &old);
+  if (rc)
+    {
+      error (0, rc, "pthread_setcanceltype after 2nd open failed");
+      ret = 1;
+    }
+  if (old != PTHREAD_CANCEL_ASYNCHRONOUS)
+    {
+      error (0, 0, "pthread_setcanceltype after 2nd open returned invalid value %d",
+	     old);
+      ret = 1;
+    }
+
+  *enddir = '\0';
+  rmdir (fname);
+
+  clobber_lots_of_regs ();
+  select (-1, NULL, NULL, NULL, NULL);
+
+  rc = pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &old);
+  if (rc)
+    {
+      error (0, rc, "pthread_setcanceltype after select failed");
+      ret = 1;
+    }
+  if (old != PTHREAD_CANCEL_DEFERRED)
+    {
+      error (0, 0, "pthread_setcanceltype after select returned invalid value %d",
+	     old);
+      ret = 1;
+    }
+
+  clobber_lots_of_regs ();
+  select (-1, NULL, NULL, NULL, NULL);
+
+  rc = pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, &old);
+  if (rc)
+    {
+      error (0, rc, "pthread_setcanceltype after 2nd select failed");
+      ret = 1;
+    }
+  if (old != PTHREAD_CANCEL_ASYNCHRONOUS)
+    {
+      error (0, 0, "pthread_setcanceltype after 2nd select returned invalid value %d",
+	     old);
+      ret = 1;
+    }
+
+  pthread_join (th, NULL);
+
+  return ret;
+}
+
+#define TIMEOUT 20
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel2.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel2.c
new file mode 100644
index 00000000..6d80f8ae
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel2.c
@@ -0,0 +1,100 @@
+/* Copyright (C) 2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2002.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+
+
+static int fd[2];
+
+
+static void *
+tf (void *arg)
+{
+  /* The buffer size must be larger than the pipe size so that the
+     write blocks.  */
+  char buf[100000];
+
+  if (write (fd[1], buf, sizeof (buf)) == sizeof (buf))
+    {
+      puts ("write succeeded");
+      return (void *) 1l;
+    }
+
+  return (void *) 42l;
+}
+
+
+static int
+do_test (void)
+{
+  pthread_t th;
+  void *r;
+  struct sigaction sa;
+
+  sa.sa_handler = SIG_IGN;
+  sigemptyset (&sa.sa_mask);
+  sa.sa_flags = 0;
+
+  if (sigaction (SIGPIPE, &sa, NULL) != 0)
+    {
+      puts ("sigaction failed");
+      return 1;
+    }
+
+  if (pipe (fd) != 0)
+    {
+      puts ("pipe failed");
+      return 1;
+    }
+
+  if (pthread_create (&th, NULL, tf, NULL) != 0)
+    {
+      puts ("create failed");
+      return 1;
+    }
+
+  if (pthread_cancel (th) != 0)
+    {
+      puts ("cancel failed");
+      return 1;
+    }
+
+  /* This will cause the write in the child to return.  */
+  close (fd[0]);
+
+  if (pthread_join (th, &r) != 0)
+    {
+      puts ("join failed");
+      return 1;
+    }
+
+  if (r != PTHREAD_CANCELED)
+    {
+      printf ("result is wrong: expected %p, got %p\n", PTHREAD_CANCELED, r);
+      return 1;
+    }
+
+  return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel20.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel20.c
new file mode 100644
index 00000000..d88cb9ca
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel20.c
@@ -0,0 +1,264 @@
+/* Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek , 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+static int fd[4];
+static pthread_barrier_t b;
+volatile int in_sh_body;
+unsigned long cleanups;
+
+static void
+cl (void *arg)
+{
+  cleanups = (cleanups << 4) | (long) arg;
+}
+
+
+static void __attribute__((noinline))
+sh_body (void)
+{
+  char c;
+
+  pthread_cleanup_push (cl, (void *) 1L);
+
+  in_sh_body = 1;
+  if (read (fd[2], &c, 1) == 1)
+    {
+      puts ("read succeeded");
+      exit (1);
+    }
+
+  pthread_cleanup_pop (0);
+}
+
+
+static void
+sh (int sig)
+{
+  pthread_cleanup_push (cl, (void *) 2L);
+  sh_body ();
+  in_sh_body = 0;
+
+  pthread_cleanup_pop (0);
+}
+
+
+static void __attribute__((noinline))
+tf_body (void)
+{
+  char c;
+
+  pthread_cleanup_push (cl, (void *) 3L);
+
+  int r = pthread_barrier_wait (&b);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("child thread: barrier_wait failed");
+      exit (1);
+    }
+
+  if (read (fd[0], &c, 1) == 1)
+    {
+      puts ("read succeeded");
+      exit (1);
+    }
+
+  read (fd[0], &c, 1);
+
+  pthread_cleanup_pop (0);
+}
+
+
+static void *
+tf (void *arg)
+{
+  pthread_cleanup_push (cl, (void *) 4L);
+  tf_body ();
+  pthread_cleanup_pop (0);
+  return NULL;
+}
+
+
+static int
+do_one_test (void)
+{
+  in_sh_body = 0;
+  cleanups = 0;
+  if (pipe (fd) != 0 || pipe (fd + 2) != 0)
+    {
+      puts ("pipe failed");
+      return 1;
+    }
+
+  pthread_t th;
+  if (pthread_create (&th, NULL, tf, NULL) != 0)
+    {
+      puts ("create failed");
+      return 1;
+    }
+
+  int r = pthread_barrier_wait (&b);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("parent thread: barrier_wait failed");
+      return 1;
+    }
+
+  sleep (1);
+
+  r = pthread_kill (th, SIGHUP);
+  if (r)
+    {
+      errno = r;
+      printf ("pthread_kill failed %m\n");
+      return 1;
+    }
+
+  while (in_sh_body == 0)
+    sleep (1);
+
+  if (pthread_cancel (th) != 0)
+    {
+      puts ("cancel failed");
+      return 1;
+    }
+
+  /* This will cause the read in the child to return.  */
+  close (fd[0]);
+  close (fd[1]);
+  close (fd[2]);
+  close (fd[3]);
+
+  void *ret;
+  if (pthread_join (th, &ret) != 0)
+    {
+      puts ("join failed");
+      return 1;
+    }
+
+  if (ret != PTHREAD_CANCELED)
+    {
+      puts ("result is wrong");
+      return 1;
+    }
+
+  if (cleanups != 0x1234L)
+    {
+      printf ("called cleanups %lx\n", cleanups);
+      return 1;
+    }
+
+  return 0;
+}
+
+
+static int
+do_test (void)
+{
+  stack_t ss;
+  ss.ss_sp = malloc (2 * SIGSTKSZ);
+  if (ss.ss_sp == NULL)
+    {
+      puts ("failed to allocate alternate stack");
+      return 1;
+    }
+  ss.ss_flags = 0;
+  ss.ss_size = 2 * SIGSTKSZ;
+  if (sigaltstack (&ss, NULL) < 0)
+    {
+      printf ("sigaltstack failed %m\n");
+      return 1;
+    }
+
+  if (pthread_barrier_init (&b, NULL, 2) != 0)
+    {
+      puts ("barrier_init failed");
+      return 1;
+    }
+
+  struct sigaction sa;
+  sa.sa_handler = sh;
+  sigemptyset (&sa.sa_mask);
+  sa.sa_flags = 0;
+
+  if (sigaction (SIGHUP, &sa, NULL) != 0)
+    {
+      puts ("sigaction failed");
+      return 1;
+    }
+
+  puts ("sa_flags = 0 test");
+  if (do_one_test ())
+    return 1;
+
+  sa.sa_handler = sh;
+  sigemptyset (&sa.sa_mask);
+  sa.sa_flags = SA_ONSTACK;
+
+  if (sigaction (SIGHUP, &sa, NULL) != 0)
+    {
+      puts ("sigaction failed");
+      return 1;
+    }
+
+  puts ("sa_flags = SA_ONSTACK test");
+  if (do_one_test ())
+    return 1;
+
+  sa.sa_sigaction = (void (*)(int, siginfo_t *, void *)) sh;
+  sigemptyset (&sa.sa_mask);
+  sa.sa_flags = SA_SIGINFO;
+
+  if (sigaction (SIGHUP, &sa, NULL) != 0)
+    {
+      puts ("sigaction failed");
+      return 1;
+    }
+
+  puts ("sa_flags = SA_SIGINFO test");
+  if (do_one_test ())
+    return 1;
+
+  sa.sa_sigaction = (void (*)(int, siginfo_t *, void *)) sh;
+  sigemptyset (&sa.sa_mask);
+  sa.sa_flags = SA_SIGINFO | SA_ONSTACK;
+
+  if (sigaction (SIGHUP, &sa, NULL) != 0)
+    {
+      puts ("sigaction failed");
+      return 1;
+    }
+
+  puts ("sa_flags = SA_SIGINFO|SA_ONSTACK test");
+  if (do_one_test ())
+    return 1;
+
+  return 0;
+}
+
+#define TIMEOUT 40
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel21.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel21.c
new file mode 100644
index 00000000..cc00cc16
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel21.c
@@ -0,0 +1,294 @@
+/* Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek , 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+static int fd[4];
+static pthread_barrier_t b;
+volatile int in_sh_body;
+unsigned long cleanups;
+
+static void
+cl (void *arg)
+{
+  cleanups = (cleanups << 4) | (long) arg;
+}
+
+
+static void __attribute__((noinline))
+sh_body (void)
+{
+  char c;
+
+  pthread_cleanup_push (cl, (void *) 1L);
+
+  in_sh_body = 1;
+  if (read (fd[2], &c, 1) == 1)
+    {
+      puts ("read succeeded");
+      exit (1);
+    }
+
+  pthread_cleanup_pop (0);
+}
+
+
+static void
+sh (int sig)
+{
+  pthread_cleanup_push (cl, (void *) 2L);
+  sh_body ();
+  in_sh_body = 0;
+
+  pthread_cleanup_pop (0);
+}
+
+
+static void __attribute__((noinline))
+tf_body (void)
+{
+  char c;
+
+  pthread_cleanup_push (cl, (void *) 3L);
+
+  int r = pthread_barrier_wait (&b);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("child thread: barrier_wait failed");
+      exit (1);
+    }
+
+  if (read (fd[0], &c, 1) == 1)
+    {
+      puts ("read succeeded");
+      exit (1);
+    }
+
+  read (fd[0], &c, 1);
+
+  pthread_cleanup_pop (0);
+}
+
+
+static void *
+tf (void *arg)
+{
+  pthread_t th = (pthread_t) arg;
+
+  int r = pthread_barrier_wait (&b);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("parent thread: barrier_wait failed");
+      exit (1);
+    }
+
+  sleep (1);
+
+  r = pthread_kill (th, SIGHUP);
+  if (r)
+    {
+      errno = r;
+      printf ("pthread_kill failed %m\n");
+      exit (1);
+    }
+
+  while (in_sh_body == 0)
+    sleep (1);
+
+  if (pthread_cancel (th) != 0)
+    {
+      puts ("cancel failed");
+      exit (1);
+    }
+
+  /* This will cause the read in the initial thread to return.  */
+  close (fd[0]);
+  close (fd[1]);
+  close (fd[2]);
+  close (fd[3]);
+
+  void *ret;
+  if (pthread_join (th, &ret) != 0)
+    {
+      puts ("join failed");
+      exit (1);
+    }
+
+  if (ret != PTHREAD_CANCELED)
+    {
+      puts ("result is wrong");
+      exit (1);
+    }
+
+  if (cleanups != 0x1234L)
+    {
+      printf ("called cleanups %lx\n", cleanups);
+      exit (1);
+    }
+
+  if (pthread_barrier_destroy (&b))
+    {
+      puts ("barrier destroy failed");
+      exit (1);
+    }
+
+  exit (0);
+}
+
+
+static int
+do_one_test (void)
+{
+  in_sh_body = 0;
+
+  pid_t pid = fork ();
+
+  if (pid == -1)
+    {
+      printf ("fork failed: %m\n");
+      return 1;
+    }
+
+  if (pid)
+    {
+      int status;
+      if (waitpid (pid, &status, 0) < 0)
+	{
+	  printf ("waitpid failed %m\n");
+	  return 1;
+	}
+
+      return !WIFEXITED (status) || WEXITSTATUS (status);
+    }
+
+  if (pthread_barrier_init (&b, NULL, 2) != 0)
+    {
+      puts ("barrier_init failed");
+      exit (1);
+    }
+
+  cleanups = 0;
+  if (pipe (fd) != 0 || pipe (fd + 2) != 0)
+    {
+      puts ("pipe failed");
+      exit (1);
+    }
+
+  pthread_t th;
+  if (pthread_create (&th, NULL, tf, (void *) pthread_self ()) != 0)
+    {
+      puts ("create failed");
+      exit (1);
+    }
+
+  pthread_cleanup_push (cl, (void *) 4L);
+  tf_body ();
+  pthread_cleanup_pop (0);
+  exit (1);
+}
+
+
+static int
+do_test (void)
+{
+  stack_t ss;
+  ss.ss_sp = malloc (2 * SIGSTKSZ);
+  if (ss.ss_sp == NULL)
+    {
+      puts ("failed to allocate alternate stack");
+      return 1;
+    }
+  ss.ss_flags = 0;
+  ss.ss_size = 2 * SIGSTKSZ;
+  if (sigaltstack (&ss, NULL) < 0)
+    {
+      printf ("sigaltstack failed %m\n");
+      return 1;
+    }
+
+  struct sigaction sa;
+  sa.sa_handler = sh;
+  sigemptyset (&sa.sa_mask);
+  sa.sa_flags = 0;
+
+  if (sigaction (SIGHUP, &sa, NULL) != 0)
+    {
+      puts ("sigaction failed");
+      return 1;
+    }
+
+  puts ("sa_flags = 0 test");
+  if (do_one_test ())
+    return 1;
+
+  sa.sa_handler = sh;
+  sigemptyset (&sa.sa_mask);
+  sa.sa_flags = SA_ONSTACK;
+
+  if (sigaction (SIGHUP, &sa, NULL) != 0)
+    {
+      puts ("sigaction failed");
+      return 1;
+    }
+
+  puts ("sa_flags = SA_ONSTACK test");
+  if (do_one_test ())
+    return 1;
+
+  sa.sa_sigaction = (void (*)(int, siginfo_t *, void *)) sh;
+  sigemptyset (&sa.sa_mask);
+  sa.sa_flags = SA_SIGINFO;
+
+  if (sigaction (SIGHUP, &sa, NULL) != 0)
+    {
+      puts ("sigaction failed");
+      return 1;
+    }
+
+  puts ("sa_flags = SA_SIGINFO test");
+  if (do_one_test ())
+    return 1;
+
+  sa.sa_sigaction = (void (*)(int, siginfo_t *, void *)) sh;
+  sigemptyset (&sa.sa_mask);
+  sa.sa_flags = SA_SIGINFO | SA_ONSTACK;
+
+  if (sigaction (SIGHUP, &sa, NULL) != 0)
+    {
+      puts ("sigaction failed");
+      return 1;
+    }
+
+  puts ("sa_flags = SA_SIGINFO|SA_ONSTACK test");
+  if (do_one_test ())
+    return 1;
+
+  return 0;
+}
+
+#define TIMEOUT 40
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel22.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel22.c
new file mode 100644
index 00000000..c47167b9
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel22.c
@@ -0,0 +1,122 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek , 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+pthread_barrier_t b;
+int seen;
+
+static void *
+tf (void *arg)
+{
+  int i;
+  int old;
+  int r = pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &old);
+  if (r != 0)
+    {
+      puts ("setcancelstate failed");
+      exit (1);
+    }
+
+  r = pthread_barrier_wait (&b);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("barrier_wait failed");
+      exit (1);
+    }
+
+  for (i = 0; i < 10; ++i)
+    {
+      struct timespec ts = { .tv_sec = 0, .tv_nsec = 100000000 };
+      TEMP_FAILURE_RETRY (nanosleep (&ts, &ts));
+    }
+
+  seen = 1;
+  pthread_setcancelstate (old, NULL);
+
+  struct timespec ts = { .tv_sec = 0, .tv_nsec = 100000000 };
+  TEMP_FAILURE_RETRY (nanosleep (&ts, &ts));
+
+  exit (1);
+}
+
+
+static int
+do_test (void)
+{
+  if (pthread_barrier_init (&b, NULL, 2) != 0)
+   {
+     puts ("barrier init failed");
+     return 1;
+   }
+
+  pthread_t th;
+  if (pthread_create (&th, NULL, tf, NULL) != 0)
+    {
+      puts ("thread creation failed");
+      return 1;
+    }
+
+  int r = pthread_barrier_wait (&b);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("barrier_wait failed");
+      return 1;
+    }
+
+  if (pthread_cancel (th) != 0)
+    {
+      puts ("cancel failed");
+      return 1;
+    }
+
+  void *status;
+  if (pthread_join (th, &status) != 0)
+    {
+      puts ("join failed");
+      return 1;
+    }
+  if (status != PTHREAD_CANCELED)
+    {
+      puts ("thread not canceled");
+      return 1;
+    }
+
+  if (pthread_barrier_destroy (&b) != 0)
+    {
+      puts ("barrier_destroy failed");
+      return 1;
+    }
+
+  if (seen != 1)
+    {
+      puts ("thread cancelled when PTHREAD_CANCEL_DISABLED");
+      return 1;
+    }
+
+  return 0;
+}
+
+#define TIMEOUT 5
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel23.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel23.c
new file mode 100644
index 00000000..21116874
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel23.c
@@ -0,0 +1 @@
+#include "tst-cancel22.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel25.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel25.c
new file mode 100644
index 00000000..00b99ad5
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel25.c
@@ -0,0 +1,171 @@
+#include 
+#include 
+#include 
+#include 
+
+
+static pthread_barrier_t b;
+static pthread_t th2;
+
+
+static void *
+tf2 (void *arg)
+{
+  sigset_t mask;
+  if (pthread_sigmask (SIG_SETMASK, NULL, &mask) != 0)
+    {
+      puts ("pthread_sigmask failed");
+      exit (1);
+    }
+  if (sigismember (&mask, SIGCANCEL))
+    {
+      puts ("SIGCANCEL blocked in new thread");
+      exit (1);
+    }
+
+  /* Sync with the main thread so that we do not test anything else.  */
+  int e = pthread_barrier_wait (&b);
+  if (e != 0  && e != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("barrier_wait failed");
+      exit (1);
+    }
+
+  while (1)
+    {
+      /* Just a cancelable call.  */
+      struct timespec ts = { 10000, 0 };
+      nanosleep (&ts, 0);
+    }
+
+  return NULL;
+}
+
+
+static void
+unwhand (void *arg)
+{
+  if (pthread_create (&th2, NULL, tf2, NULL) != 0)
+    {
+      puts ("unwhand: create failed");
+      exit (1);
+    }
+}
+
+
+static void *
+tf (void *arg)
+{
+  pthread_cleanup_push (unwhand, NULL);
+
+  /* Sync with the main thread so that we do not test anything else.  */
+  int e = pthread_barrier_wait (&b);
+  if (e != 0  && e != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("barrier_wait failed");
+      exit (1);
+    }
+
+  while (1)
+    {
+      /* Just a cancelable call.  */
+      struct timespec ts = { 10000, 0 };
+      nanosleep (&ts, 0);
+    }
+
+  pthread_cleanup_pop (0);
+
+  return NULL;
+}
+
+
+static int
+do_test (void)
+{
+  if (pthread_barrier_init (&b, NULL, 2) != 0)
+    {
+      puts ("barrier_init failed");
+      return 1;
+    }
+
+  pthread_t th1;
+  if (pthread_create (&th1, NULL, tf, NULL) != 0)
+    {
+      puts ("create failed");
+      return 1;
+    }
+
+  int e = pthread_barrier_wait (&b);
+  if (e != 0  && e != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("barrier_wait failed");
+      return 1;
+    }
+
+  /* Make sure tf1 enters nanosleep.  */
+  struct timespec ts = { 0, 500000000 };
+  while (nanosleep (&ts, &ts) != 0)
+    ;
+
+  if (pthread_cancel (th1) != 0)
+    {
+      puts ("1st cancel failed");
+      return 1;
+    }
+
+  void *res;
+  if (pthread_join (th1, &res) != 0)
+    {
+      puts ("1st join failed");
+      return 1;
+    }
+  if (res != PTHREAD_CANCELED)
+    {
+      puts ("1st thread not canceled");
+      return 1;
+    }
+
+  e = pthread_barrier_wait (&b);
+  if (e != 0  && e != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("barrier_wait failed");
+      return 1;
+    }
+
+  /* Make sure tf2 enters nanosleep.  */
+  ts.tv_sec = 0;
+  ts.tv_nsec = 500000000;
+  while (nanosleep (&ts, &ts) != 0)
+    ;
+
+  puts ("calling pthread_cancel the second time");
+  if (pthread_cancel (th2) != 0)
+    {
+      puts ("2nd cancel failed");
+      return 1;
+    }
+
+  puts ("calling pthread_join the second time");
+  if (pthread_join (th2, &res) != 0)
+    {
+      puts ("2nd join failed");
+      return 1;
+    }
+  if (res != PTHREAD_CANCELED)
+    {
+      puts ("2nd thread not canceled");
+      return 1;
+    }
+
+  if (pthread_barrier_destroy (&b) != 0)
+    {
+      puts ("barrier_destroy failed");
+      return 0;
+    }
+
+  return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#define TIMEOUT 4
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel3.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel3.c
new file mode 100644
index 00000000..86c482bc
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel3.c
@@ -0,0 +1,98 @@
+/* Copyright (C) 2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2002.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+
+
+static int fd[2];
+
+
+static void *
+tf (void *arg)
+{
+  char buf[100];
+
+  if (read (fd[0], buf, sizeof (buf)) == sizeof (buf))
+    {
+      puts ("read succeeded");
+      return (void *) 1l;
+    }
+
+  return NULL;
+}
+
+
+static int
+do_test (void)
+{
+  pthread_t th;
+  void *r;
+  struct sigaction sa;
+
+  sa.sa_handler = SIG_IGN;
+  sigemptyset (&sa.sa_mask);
+  sa.sa_flags = 0;
+
+  if (sigaction (SIGPIPE, &sa, NULL) != 0)
+    {
+      puts ("sigaction failed");
+      return 1;
+    }
+
+  if (pipe (fd) != 0)
+    {
+      puts ("pipe failed");
+      return 1;
+    }
+
+  if (pthread_create (&th, NULL, tf, NULL) != 0)
+    {
+      puts ("create failed");
+      return 1;
+    }
+
+  if (pthread_cancel (th) != 0)
+    {
+      puts ("cancel failed");
+      return 1;
+    }
+
+  /* This will cause the read in the child to return.  */
+  close (fd[0]);
+
+  if (pthread_join (th, &r) != 0)
+    {
+      puts ("join failed");
+      return 1;
+    }
+
+  if (r != PTHREAD_CANCELED)
+    {
+      puts ("result is wrong");
+      return 1;
+    }
+
+  return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel4.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel4.c
new file mode 100644
index 00000000..12d40d5b
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel4.c
@@ -0,0 +1,2374 @@
+/* Copyright (C) 2002, 2003, 2004, 2006, 2007 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2002.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+/* NOTE: this tests functionality beyond POSIX.  POSIX does not allow
+   exit to be called more than once.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "pthreadP.h"
+
+
+/* Since STREAMS are not supported in the standard Linux kernel and
+   there we don't advertise STREAMS as supported is no need to test
+   the STREAMS related functions.  This affects
+     getmsg()              getpmsg()          putmsg()
+     putpmsg()
+
+   lockf() and fcntl() are tested in tst-cancel16.
+
+   pthread_join() is tested in tst-join5.
+
+   pthread_testcancel()'s only purpose is to allow cancellation.  This
+   is tested in several places.
+
+   sem_wait() and sem_timedwait() are checked in tst-cancel1[2345] tests.
+
+   mq_send(), mq_timedsend(), mq_receive() and mq_timedreceive() are checked
+   in tst-mqueue8{,x} tests.
+
+   aio_suspend() is tested in tst-cancel17.
+
+   clock_nanosleep() is tested in tst-cancel18.
+*/
+
+/* Pipe descriptors.  */
+static int fds[2];
+
+/* Temporary file descriptor, to be closed after each round.  */
+static int tempfd = -1;
+static int tempfd2 = -1;
+/* Name of temporary file to be removed after each round.  */
+static char *tempfname;
+/* Temporary message queue.  */
+static int tempmsg = -1;
+
+/* Often used barrier for two threads.  */
+static pthread_barrier_t b2;
+
+
+#ifndef IPC_ADDVAL
+# define IPC_ADDVAL 0
+#endif
+
+#define WRITE_BUFFER_SIZE 4096
+
+/* Cleanup handling test.  */
+static int cl_called;
+
+static void
+cl (void *arg)
+{
+  ++cl_called;
+}
+
+
+
+static void *
+tf_read  (void *arg)
+{
+  int fd;
+  int r;
+
+  if (arg == NULL)
+    fd = fds[0];
+  else
+    {
+      char fname[] = "/tmp/tst-cancel4-fd-XXXXXX";
+      tempfd = fd = mkstemp (fname);
+      if (fd == -1)
+	printf ("%s: mkstemp failed\n", __FUNCTION__);
+      unlink (fname);
+
+      r = pthread_barrier_wait (&b2);
+      if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+	{
+	  printf ("%s: barrier_wait failed\n", __FUNCTION__);
+	  exit (1);
+	}
+    }
+
+  r = pthread_barrier_wait (&b2);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: barrier_wait failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  ssize_t s;
+  pthread_cleanup_push (cl, NULL);
+
+  char buf[100];
+  s = read (fd, buf, sizeof (buf));
+
+  pthread_cleanup_pop (0);
+
+  printf ("%s: read returns with %zd\n", __FUNCTION__, s);
+
+  exit (1);
+}
+
+
+static void *
+tf_readv  (void *arg)
+{
+  int fd;
+  int r;
+
+  if (arg == NULL)
+    fd = fds[0];
+  else
+    {
+      char fname[] = "/tmp/tst-cancel4-fd-XXXXXX";
+      tempfd = fd = mkstemp (fname);
+      if (fd == -1)
+	printf ("%s: mkstemp failed\n", __FUNCTION__);
+      unlink (fname);
+
+      r = pthread_barrier_wait (&b2);
+      if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+	{
+	  printf ("%s: barrier_wait failed\n", __FUNCTION__);
+	  exit (1);
+	}
+    }
+
+  r = pthread_barrier_wait (&b2);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: barrier_wait failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  ssize_t s;
+  pthread_cleanup_push (cl, NULL);
+
+  char buf[100];
+  struct iovec iov[1] = { [0] = { .iov_base = buf, .iov_len = sizeof (buf) } };
+  s = readv (fd, iov, 1);
+
+  pthread_cleanup_pop (0);
+
+  printf ("%s: readv returns with %zd\n", __FUNCTION__, s);
+
+  exit (1);
+}
+
+
+static void *
+tf_write  (void *arg)
+{
+  int fd;
+  int r;
+
+  if (arg == NULL)
+    fd = fds[1];
+  else
+    {
+      char fname[] = "/tmp/tst-cancel4-fd-XXXXXX";
+      tempfd = fd = mkstemp (fname);
+      if (fd == -1)
+	printf ("%s: mkstemp failed\n", __FUNCTION__);
+      unlink (fname);
+
+      r = pthread_barrier_wait (&b2);
+      if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+	{
+	  printf ("%s: barrier_wait failed\n", __FUNCTION__);
+	  exit (1);
+	}
+    }
+
+  r = pthread_barrier_wait (&b2);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: barrier_wait failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  ssize_t s;
+  pthread_cleanup_push (cl, NULL);
+
+  char buf[WRITE_BUFFER_SIZE];
+  memset (buf, '\0', sizeof (buf));
+  s = write (fd, buf, sizeof (buf));
+
+  pthread_cleanup_pop (0);
+
+  printf ("%s: write returns with %zd\n", __FUNCTION__, s);
+
+  exit (1);
+}
+
+
+static void *
+tf_writev  (void *arg)
+{
+  int fd;
+  int r;
+
+  if (arg == NULL)
+    fd = fds[1];
+  else
+    {
+      char fname[] = "/tmp/tst-cancel4-fd-XXXXXX";
+      tempfd = fd = mkstemp (fname);
+      if (fd == -1)
+	printf ("%s: mkstemp failed\n", __FUNCTION__);
+      unlink (fname);
+
+      r = pthread_barrier_wait (&b2);
+      if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+	{
+	  printf ("%s: barrier_wait failed\n", __FUNCTION__);
+	  exit (1);
+	}
+    }
+
+  r = pthread_barrier_wait (&b2);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: barrier_wait failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  ssize_t s;
+  pthread_cleanup_push (cl, NULL);
+
+  char buf[WRITE_BUFFER_SIZE];
+  memset (buf, '\0', sizeof (buf));
+  struct iovec iov[1] = { [0] = { .iov_base = buf, .iov_len = sizeof (buf) } };
+  s = writev (fd, iov, 1);
+
+  pthread_cleanup_pop (0);
+
+  printf ("%s: writev returns with %zd\n", __FUNCTION__, s);
+
+  exit (1);
+}
+
+
+static void *
+tf_sleep (void *arg)
+{
+  int r = pthread_barrier_wait (&b2);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: barrier_wait failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  if (arg != NULL)
+    {
+      r = pthread_barrier_wait (&b2);
+      if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+	{
+	  printf ("%s: barrier_wait failed\n", __FUNCTION__);
+	  exit (1);
+	}
+    }
+
+  pthread_cleanup_push (cl, NULL);
+
+  sleep (arg == NULL ? 1000000 : 0);
+
+  pthread_cleanup_pop (0);
+
+  printf ("%s: sleep returns\n", __FUNCTION__);
+
+  exit (1);
+}
+
+
+static void *
+tf_usleep (void *arg)
+{
+  int r = pthread_barrier_wait (&b2);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: barrier_wait failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  if (arg != NULL)
+    {
+      r = pthread_barrier_wait (&b2);
+      if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+	{
+	  printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
+	  exit (1);
+	}
+    }
+
+  pthread_cleanup_push (cl, NULL);
+
+  usleep (arg == NULL ? (useconds_t) ULONG_MAX : 0);
+
+  pthread_cleanup_pop (0);
+
+  printf ("%s: usleep returns\n", __FUNCTION__);
+
+  exit (1);
+}
+
+
+static void *
+tf_nanosleep (void *arg)
+{
+  int r = pthread_barrier_wait (&b2);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: barrier_wait failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  if (arg != NULL)
+    {
+      r = pthread_barrier_wait (&b2);
+      if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+	{
+	  printf ("%s: barrier_wait failed\n", __FUNCTION__);
+	  exit (1);
+	}
+    }
+
+  pthread_cleanup_push (cl, NULL);
+
+  struct timespec ts = { .tv_sec = arg == NULL ? 10000000 : 0, .tv_nsec = 0 };
+  TEMP_FAILURE_RETRY (nanosleep (&ts, &ts));
+
+  pthread_cleanup_pop (0);
+
+  printf ("%s: nanosleep returns\n", __FUNCTION__);
+
+  exit (1);
+}
+
+
+static void *
+tf_select (void *arg)
+{
+  int fd;
+  int r;
+
+  if (arg == NULL)
+    fd = fds[0];
+  else
+    {
+      char fname[] = "/tmp/tst-cancel4-fd-XXXXXX";
+      tempfd = fd = mkstemp (fname);
+      if (fd == -1)
+	printf ("%s: mkstemp failed\n", __FUNCTION__);
+      unlink (fname);
+
+      r = pthread_barrier_wait (&b2);
+      if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+	{
+	  printf ("%s: barrier_wait failed\n", __FUNCTION__);
+	  exit (1);
+	}
+    }
+
+  r = pthread_barrier_wait (&b2);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: barrier_wait failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  fd_set rfs;
+  FD_ZERO (&rfs);
+  FD_SET (fd, &rfs);
+
+  int s;
+  pthread_cleanup_push (cl, NULL);
+
+  s = select (fd + 1, &rfs, NULL, NULL, NULL);
+
+  pthread_cleanup_pop (0);
+
+  printf ("%s: select returns with %d (%s)\n", __FUNCTION__, s,
+	  strerror (errno));
+
+  exit (1);
+}
+
+
+static void *
+tf_pselect (void *arg)
+{
+  int fd;
+  int r;
+
+  if (arg == NULL)
+    fd = fds[0];
+  else
+    {
+      char fname[] = "/tmp/tst-cancel4-fd-XXXXXX";
+      tempfd = fd = mkstemp (fname);
+      if (fd == -1)
+	printf ("%s: mkstemp failed\n", __FUNCTION__);
+      unlink (fname);
+
+      r = pthread_barrier_wait (&b2);
+      if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+	{
+	  printf ("%s: barrier_wait failed\n", __FUNCTION__);
+	  exit (1);
+	}
+    }
+
+  r = pthread_barrier_wait (&b2);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: barrier_wait failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  fd_set rfs;
+  FD_ZERO (&rfs);
+  FD_SET (fd, &rfs);
+
+  int s;
+  pthread_cleanup_push (cl, NULL);
+
+  s = pselect (fd + 1, &rfs, NULL, NULL, NULL, NULL);
+
+  pthread_cleanup_pop (0);
+
+  printf ("%s: pselect returns with %d (%s)\n", __FUNCTION__, s,
+	  strerror (errno));
+
+  exit (1);
+}
+
+
+static void *
+tf_poll (void *arg)
+{
+  int fd;
+  int r;
+
+  if (arg == NULL)
+    fd = fds[0];
+  else
+    {
+      char fname[] = "/tmp/tst-cancel4-fd-XXXXXX";
+      tempfd = fd = mkstemp (fname);
+      if (fd == -1)
+	printf ("%s: mkstemp failed\n", __FUNCTION__);
+      unlink (fname);
+
+      r = pthread_barrier_wait (&b2);
+      if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+	{
+	  printf ("%s: barrier_wait failed\n", __FUNCTION__);
+	  exit (1);
+	}
+    }
+
+  r = pthread_barrier_wait (&b2);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: barrier_wait failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  struct pollfd rfs[1] = { [0] = { .fd = fd, .events = POLLIN } };
+
+  int s;
+  pthread_cleanup_push (cl, NULL);
+
+  s = poll (rfs, 1, -1);
+
+  pthread_cleanup_pop (0);
+
+  printf ("%s: poll returns with %d (%s)\n", __FUNCTION__, s,
+	  strerror (errno));
+
+  exit (1);
+}
+
+
+static void *
+tf_ppoll (void *arg)
+{
+  int fd;
+  int r;
+
+  if (arg == NULL)
+    fd = fds[0];
+  else
+    {
+      char fname[] = "/tmp/tst-cancel4-fd-XXXXXX";
+      tempfd = fd = mkstemp (fname);
+      if (fd == -1)
+	printf ("%s: mkstemp failed\n", __FUNCTION__);
+      unlink (fname);
+
+      r = pthread_barrier_wait (&b2);
+      if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+	{
+	  printf ("%s: barrier_wait failed\n", __FUNCTION__);
+	  exit (1);
+	}
+    }
+
+  r = pthread_barrier_wait (&b2);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: barrier_wait failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  struct pollfd rfs[1] = { [0] = { .fd = fd, .events = POLLIN } };
+
+  int s;
+  pthread_cleanup_push (cl, NULL);
+
+  s = ppoll (rfs, 1, NULL, NULL);
+
+  pthread_cleanup_pop (0);
+
+  printf ("%s: ppoll returns with %d (%s)\n", __FUNCTION__, s,
+	  strerror (errno));
+
+  exit (1);
+}
+
+
+static void *
+tf_wait (void *arg)
+{
+  pid_t pid = fork ();
+  if (pid == -1)
+    {
+      puts ("fork failed");
+      exit (1);
+    }
+
+  if (pid == 0)
+    {
+      /* Make the program disappear after a while.  */
+      if (arg == NULL)
+	sleep (10);
+      exit (0);
+    }
+
+  int r;
+  if (arg != NULL)
+    {
+      struct timespec  ts = { .tv_sec = 0, .tv_nsec = 100000000 };
+      while (nanosleep (&ts, &ts) != 0)
+	continue;
+
+      r = pthread_barrier_wait (&b2);
+      if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+	{
+	  printf ("%s: barrier_wait failed\n", __FUNCTION__);
+	  exit (1);
+	}
+    }
+
+  r = pthread_barrier_wait (&b2);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: barrier_wait failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  int s;
+  pthread_cleanup_push (cl, NULL);
+
+  s = wait (NULL);
+
+  pthread_cleanup_pop (0);
+
+  printf ("%s: wait returns with %d (%s)\n", __FUNCTION__, s,
+	  strerror (errno));
+
+  exit (1);
+}
+
+
+static void *
+tf_waitpid (void *arg)
+{
+
+  pid_t pid = fork ();
+  if (pid == -1)
+    {
+      puts ("fork failed");
+      exit (1);
+    }
+
+  if (pid == 0)
+    {
+      /* Make the program disappear after a while.  */
+      if (arg == NULL)
+	sleep (10);
+      exit (0);
+    }
+
+  int r;
+  if (arg != NULL)
+    {
+      struct timespec  ts = { .tv_sec = 0, .tv_nsec = 100000000 };
+      while (nanosleep (&ts, &ts) != 0)
+	continue;
+
+      r = pthread_barrier_wait (&b2);
+      if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+	{
+	  printf ("%s: barrier_wait failed\n", __FUNCTION__);
+	  exit (1);
+	}
+    }
+
+  r = pthread_barrier_wait (&b2);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: barrier_wait failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  int s;
+ pthread_cleanup_push (cl, NULL);
+
+  s = waitpid (-1, NULL, 0);
+
+  pthread_cleanup_pop (0);
+
+  printf ("%s: waitpid returns with %d (%s)\n", __FUNCTION__, s,
+	  strerror (errno));
+
+  exit (1);
+}
+
+
+static void *
+tf_waitid (void *arg)
+{
+  pid_t pid = fork ();
+  if (pid == -1)
+    {
+      puts ("fork failed");
+      exit (1);
+    }
+
+  if (pid == 0)
+    {
+      /* Make the program disappear after a while.  */
+      if (arg == NULL)
+	sleep (10);
+      exit (0);
+    }
+
+  int r;
+  if (arg != NULL)
+    {
+      struct timespec  ts = { .tv_sec = 0, .tv_nsec = 100000000 };
+      while (nanosleep (&ts, &ts) != 0)
+	continue;
+
+      r = pthread_barrier_wait (&b2);
+      if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+	{
+	  printf ("%s: barrier_wait failed\n", __FUNCTION__);
+	  exit (1);
+	}
+    }
+
+  r = pthread_barrier_wait (&b2);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: barrier_wait failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  int s;
+  pthread_cleanup_push (cl, NULL);
+
+#ifndef WEXITED
+# define WEXITED 0
+#endif
+  siginfo_t si;
+  s = waitid (P_PID, pid, &si, WEXITED);
+
+  pthread_cleanup_pop (0);
+
+  printf ("%s: waitid returns with %d (%s)\n", __FUNCTION__, s,
+	  strerror (errno));
+
+  exit (1);
+}
+
+
+static void *
+tf_sigpause (void *arg)
+{
+  int r = pthread_barrier_wait (&b2);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: barrier_wait failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  if (arg != NULL)
+    {
+      r = pthread_barrier_wait (&b2);
+      if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+	{
+	  printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
+	  exit (1);
+	}
+    }
+
+  pthread_cleanup_push (cl, NULL);
+
+  /* Just for fun block the cancellation signal.  We need to use
+     __xpg_sigpause since otherwise we will get the BSD version.  */
+  //__xpg_sigpause (SIGCANCEL);
+
+  __sigpause (SIGCANCEL, 1);
+
+  pthread_cleanup_pop (0);
+
+  printf ("%s: sigpause returned\n", __FUNCTION__);
+
+  exit (1);
+}
+
+
+static void *
+tf_sigsuspend (void *arg)
+{
+  int r = pthread_barrier_wait (&b2);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: barrier_wait failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  if (arg != NULL)
+    {
+      r = pthread_barrier_wait (&b2);
+      if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+	{
+	  printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
+	  exit (1);
+	}
+    }
+
+  pthread_cleanup_push (cl, NULL);
+
+  /* Just for fun block all signals.  */
+  sigset_t mask;
+  sigfillset (&mask);
+  sigsuspend (&mask);
+
+  pthread_cleanup_pop (0);
+
+  printf ("%s: sigsuspend returned\n", __FUNCTION__);
+
+  exit (1);
+}
+
+
+static void *
+tf_sigwait (void *arg)
+{
+  int r = pthread_barrier_wait (&b2);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: barrier_wait failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  if (arg != NULL)
+    {
+      r = pthread_barrier_wait (&b2);
+      if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+	{
+	  printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
+	  exit (1);
+	}
+    }
+
+  /* Block SIGUSR1.  */
+  sigset_t mask;
+  sigemptyset (&mask);
+  sigaddset (&mask, SIGUSR1);
+  if (pthread_sigmask (SIG_BLOCK, &mask, NULL) != 0)
+    {
+      printf ("%s: pthread_sigmask failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  int sig;
+  pthread_cleanup_push (cl, NULL);
+
+  /* Wait for SIGUSR1.  */
+  sigwait (&mask, &sig);
+
+  pthread_cleanup_pop (0);
+
+  printf ("%s: sigwait returned with signal %d\n", __FUNCTION__, sig);
+
+  exit (1);
+}
+
+
+static void *
+tf_sigwaitinfo (void *arg)
+{
+  int r = pthread_barrier_wait (&b2);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: barrier_wait failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  if (arg != NULL)
+    {
+      r = pthread_barrier_wait (&b2);
+      if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+	{
+	  printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
+	  exit (1);
+	}
+    }
+
+  /* Block SIGUSR1.  */
+  sigset_t mask;
+  sigemptyset (&mask);
+  sigaddset (&mask, SIGUSR1);
+  if (pthread_sigmask (SIG_BLOCK, &mask, NULL) != 0)
+    {
+      printf ("%s: pthread_sigmask failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  siginfo_t info;
+  pthread_cleanup_push (cl, NULL);
+
+  /* Wait for SIGUSR1.  */
+  sigwaitinfo (&mask, &info);
+
+  pthread_cleanup_pop (0);
+
+  printf ("%s: sigwaitinfo returned with signal %d\n", __FUNCTION__,
+	  info.si_signo);
+
+  exit (1);
+}
+
+
+static void *
+tf_sigtimedwait (void *arg)
+{
+  int r = pthread_barrier_wait (&b2);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: barrier_wait failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  if (arg != NULL)
+    {
+      r = pthread_barrier_wait (&b2);
+      if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+	{
+	  printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
+	  exit (1);
+	}
+    }
+
+  /* Block SIGUSR1.  */
+  sigset_t mask;
+  sigemptyset (&mask);
+  sigaddset (&mask, SIGUSR1);
+  if (pthread_sigmask (SIG_BLOCK, &mask, NULL) != 0)
+    {
+      printf ("%s: pthread_sigmask failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  /* Wait for SIGUSR1.  */
+  siginfo_t info;
+  struct timespec ts = { .tv_sec = 60, .tv_nsec = 0 };
+  pthread_cleanup_push (cl, NULL);
+
+  sigtimedwait (&mask, &info, &ts);
+
+  pthread_cleanup_pop (0);
+
+  printf ("%s: sigtimedwait returned with signal %d\n", __FUNCTION__,
+	  info.si_signo);
+
+  exit (1);
+}
+
+
+static void *
+tf_pause (void *arg)
+{
+  int r = pthread_barrier_wait (&b2);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: barrier_wait failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  if (arg != NULL)
+    {
+      r = pthread_barrier_wait (&b2);
+      if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+	{
+	  printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
+	  exit (1);
+	}
+    }
+
+  pthread_cleanup_push (cl, NULL);
+
+  pause ();
+
+  pthread_cleanup_pop (0);
+
+  printf ("%s: pause returned\n", __FUNCTION__);
+
+  exit (1);
+}
+
+
+static void *
+tf_accept (void *arg)
+{
+  struct sockaddr_un sun;
+  /* To test a non-blocking accept call we make the call file by using
+     a datagrame socket.  */
+  int pf = arg == NULL ? SOCK_STREAM : SOCK_DGRAM;
+
+  tempfd = socket (AF_UNIX, pf, 0);
+  if (tempfd == -1)
+    {
+      printf ("%s: socket call failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  int tries = 0;
+  do
+    {
+      if (++tries > 10)
+	{
+	  printf ("%s: too many unsuccessful bind calls\n", __FUNCTION__);
+	}
+
+      strcpy (sun.sun_path, "/tmp/tst-cancel4-socket-1-XXXXXX");
+      if (mktemp (sun.sun_path) == NULL)
+	{
+	  printf ("%s: cannot generate temp file name\n", __FUNCTION__);
+	  exit (1);
+	}
+
+      sun.sun_family = AF_UNIX;
+    }
+  while (bind (tempfd, (struct sockaddr *) &sun,
+	       offsetof (struct sockaddr_un, sun_path)
+	       + strlen (sun.sun_path) + 1) != 0);
+
+  unlink (sun.sun_path);
+
+  listen (tempfd, 5);
+
+  socklen_t len = sizeof (sun);
+
+  int r = pthread_barrier_wait (&b2);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: barrier_wait failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  if (arg != NULL)
+    {
+      r = pthread_barrier_wait (&b2);
+      if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+	{
+	  printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
+	  exit (1);
+	}
+    }
+
+  pthread_cleanup_push (cl, NULL);
+
+  accept (tempfd, (struct sockaddr *) &sun, &len);
+
+  pthread_cleanup_pop (0);
+
+  printf ("%s: accept returned\n", __FUNCTION__);
+
+  exit (1);
+}
+
+
+static void *
+tf_send (void *arg)
+{
+  struct sockaddr_un sun;
+
+  tempfd = socket (AF_UNIX, SOCK_STREAM, 0);
+  if (tempfd == -1)
+    {
+      printf ("%s: first socket call failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  int tries = 0;
+  do
+    {
+      if (++tries > 10)
+	{
+	  printf ("%s: too many unsuccessful bind calls\n", __FUNCTION__);
+	}
+
+      strcpy (sun.sun_path, "/tmp/tst-cancel4-socket-2-XXXXXX");
+      if (mktemp (sun.sun_path) == NULL)
+	{
+	  printf ("%s: cannot generate temp file name\n", __FUNCTION__);
+	  exit (1);
+	}
+
+      sun.sun_family = AF_UNIX;
+    }
+  while (bind (tempfd, (struct sockaddr *) &sun,
+	       offsetof (struct sockaddr_un, sun_path)
+	       + strlen (sun.sun_path) + 1) != 0);
+
+  listen (tempfd, 5);
+
+  tempfd2 = socket (AF_UNIX, SOCK_STREAM, 0);
+  if (tempfd2 == -1)
+    {
+      printf ("%s: second socket call failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  if (connect (tempfd2, (struct sockaddr *) &sun, sizeof (sun)) != 0)
+    {
+      printf ("%s: connect failed\n", __FUNCTION__);
+      exit(1);
+    }
+
+  unlink (sun.sun_path);
+
+  int r = pthread_barrier_wait (&b2);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: barrier_wait failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  if (arg != NULL)
+    {
+      r = pthread_barrier_wait (&b2);
+      if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+	{
+	  printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
+	  exit (1);
+	}
+    }
+
+  pthread_cleanup_push (cl, NULL);
+
+  /* Very large block, so that the send call blocks.  */
+  char mem[700000];
+
+  send (tempfd2, mem, arg == NULL ? sizeof (mem) : 1, 0);
+
+  pthread_cleanup_pop (0);
+
+  printf ("%s: send returned\n", __FUNCTION__);
+
+  exit (1);
+}
+
+
+static void *
+tf_recv (void *arg)
+{
+  struct sockaddr_un sun;
+
+  tempfd = socket (AF_UNIX, SOCK_STREAM, 0);
+  if (tempfd == -1)
+    {
+      printf ("%s: first socket call failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  int tries = 0;
+  do
+    {
+      if (++tries > 10)
+	{
+	  printf ("%s: too many unsuccessful bind calls\n", __FUNCTION__);
+	}
+
+      strcpy (sun.sun_path, "/tmp/tst-cancel4-socket-3-XXXXXX");
+      if (mktemp (sun.sun_path) == NULL)
+	{
+	  printf ("%s: cannot generate temp file name\n", __FUNCTION__);
+	  exit (1);
+	}
+
+      sun.sun_family = AF_UNIX;
+    }
+  while (bind (tempfd, (struct sockaddr *) &sun,
+	       offsetof (struct sockaddr_un, sun_path)
+	       + strlen (sun.sun_path) + 1) != 0);
+
+  listen (tempfd, 5);
+
+  tempfd2 = socket (AF_UNIX, SOCK_STREAM, 0);
+  if (tempfd2 == -1)
+    {
+      printf ("%s: second socket call failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  if (connect (tempfd2, (struct sockaddr *) &sun, sizeof (sun)) != 0)
+    {
+      printf ("%s: connect failed\n", __FUNCTION__);
+      exit(1);
+    }
+
+  unlink (sun.sun_path);
+
+  int r = pthread_barrier_wait (&b2);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: barrier_wait failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  if (arg != NULL)
+    {
+      r = pthread_barrier_wait (&b2);
+      if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+	{
+	  printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
+	  exit (1);
+	}
+    }
+
+  pthread_cleanup_push (cl, NULL);
+
+  char mem[70];
+
+  recv (tempfd2, mem, arg == NULL ? sizeof (mem) : 0, 0);
+
+  pthread_cleanup_pop (0);
+
+  printf ("%s: recv returned\n", __FUNCTION__);
+
+  exit (1);
+}
+
+
+static void *
+tf_recvfrom (void *arg)
+{
+  struct sockaddr_un sun;
+
+  tempfd = socket (AF_UNIX, SOCK_DGRAM, 0);
+  if (tempfd == -1)
+    {
+      printf ("%s: first socket call failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  int tries = 0;
+  do
+    {
+      if (++tries > 10)
+	{
+	  printf ("%s: too many unsuccessful bind calls\n", __FUNCTION__);
+	}
+
+      strcpy (sun.sun_path, "/tmp/tst-cancel4-socket-4-XXXXXX");
+      if (mktemp (sun.sun_path) == NULL)
+	{
+	  printf ("%s: cannot generate temp file name\n", __FUNCTION__);
+	  exit (1);
+	}
+
+      sun.sun_family = AF_UNIX;
+    }
+  while (bind (tempfd, (struct sockaddr *) &sun,
+	       offsetof (struct sockaddr_un, sun_path)
+	       + strlen (sun.sun_path) + 1) != 0);
+
+  tempfname = strdup (sun.sun_path);
+
+  tempfd2 = socket (AF_UNIX, SOCK_DGRAM, 0);
+  if (tempfd2 == -1)
+    {
+      printf ("%s: second socket call failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  int r = pthread_barrier_wait (&b2);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: barrier_wait failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  if (arg != NULL)
+    {
+      r = pthread_barrier_wait (&b2);
+      if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+	{
+	  printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
+	  exit (1);
+	}
+    }
+
+  pthread_cleanup_push (cl, NULL);
+
+  char mem[70];
+  socklen_t len = sizeof (sun);
+
+  recvfrom (tempfd2, mem, arg == NULL ? sizeof (mem) : 0, 0,
+	    (struct sockaddr *) &sun, &len);
+
+  pthread_cleanup_pop (0);
+
+  printf ("%s: recvfrom returned\n", __FUNCTION__);
+
+  exit (1);
+}
+
+
+static void *
+tf_recvmsg (void *arg)
+{
+  struct sockaddr_un sun;
+
+  tempfd = socket (AF_UNIX, SOCK_DGRAM, 0);
+  if (tempfd == -1)
+    {
+      printf ("%s: first socket call failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  int tries = 0;
+  do
+    {
+      if (++tries > 10)
+	{
+	  printf ("%s: too many unsuccessful bind calls\n", __FUNCTION__);
+	}
+
+      strcpy (sun.sun_path, "/tmp/tst-cancel4-socket-5-XXXXXX");
+      if (mktemp (sun.sun_path) == NULL)
+	{
+	  printf ("%s: cannot generate temp file name\n", __FUNCTION__);
+	  exit (1);
+	}
+
+      sun.sun_family = AF_UNIX;
+    }
+  while (bind (tempfd, (struct sockaddr *) &sun,
+	       offsetof (struct sockaddr_un, sun_path)
+	       + strlen (sun.sun_path) + 1) != 0);
+
+  tempfname = strdup (sun.sun_path);
+
+  tempfd2 = socket (AF_UNIX, SOCK_DGRAM, 0);
+  if (tempfd2 == -1)
+    {
+      printf ("%s: second socket call failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  int r = pthread_barrier_wait (&b2);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: barrier_wait failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  if (arg != NULL)
+    {
+      r = pthread_barrier_wait (&b2);
+      if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+	{
+	  printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
+	  exit (1);
+	}
+    }
+
+  pthread_cleanup_push (cl, NULL);
+
+  char mem[70];
+  struct iovec iov[1];
+  iov[0].iov_base = mem;
+  iov[0].iov_len = arg == NULL ? sizeof (mem) : 0;
+
+  struct msghdr m;
+  m.msg_name = &sun;
+  m.msg_namelen = sizeof (sun);
+  m.msg_iov = iov;
+  m.msg_iovlen = 1;
+  m.msg_control = NULL;
+  m.msg_controllen = 0;
+
+  recvmsg (tempfd2, &m, 0);
+
+  pthread_cleanup_pop (0);
+
+  printf ("%s: recvmsg returned\n", __FUNCTION__);
+
+  exit (1);
+}
+
+
+static void *
+tf_open (void *arg)
+{
+  if (arg == NULL)
+    // XXX If somebody can provide a portable test case in which open()
+    // blocks we can enable this test to run in both rounds.
+    abort ();
+
+  int r = pthread_barrier_wait (&b2);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: barrier_wait failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  r = pthread_barrier_wait (&b2);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  pthread_cleanup_push (cl, NULL);
+
+  open ("Makefile", O_RDONLY);
+
+  pthread_cleanup_pop (0);
+
+  printf ("%s: open returned\n", __FUNCTION__);
+
+  exit (1);
+}
+
+
+static void *
+tf_close (void *arg)
+{
+  if (arg == NULL)
+    // XXX If somebody can provide a portable test case in which close()
+    // blocks we can enable this test to run in both rounds.
+    abort ();
+
+  char fname[] = "/tmp/tst-cancel-fd-XXXXXX";
+  tempfd = mkstemp (fname);
+  if (tempfd == -1)
+    {
+      printf ("%s: mkstemp failed\n", __FUNCTION__);
+      exit (1);
+    }
+  unlink (fname);
+
+  int r = pthread_barrier_wait (&b2);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: barrier_wait failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  r = pthread_barrier_wait (&b2);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  pthread_cleanup_push (cl, NULL);
+
+  close (tempfd);
+
+  pthread_cleanup_pop (0);
+
+  printf ("%s: close returned\n", __FUNCTION__);
+
+  exit (1);
+}
+
+
+static void *
+tf_pread (void *arg)
+{
+  if (arg == NULL)
+    // XXX If somebody can provide a portable test case in which pread()
+    // blocks we can enable this test to run in both rounds.
+    abort ();
+
+  tempfd = open ("Makefile", O_RDONLY);
+  if (tempfd == -1)
+    {
+      printf ("%s: cannot open Makefile\n", __FUNCTION__);
+      exit (1);
+    }
+
+  int r = pthread_barrier_wait (&b2);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: barrier_wait failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  r = pthread_barrier_wait (&b2);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  pthread_cleanup_push (cl, NULL);
+
+  char mem[10];
+  pread (tempfd, mem, sizeof (mem), 0);
+
+  pthread_cleanup_pop (0);
+
+  printf ("%s: pread returned\n", __FUNCTION__);
+
+  exit (1);
+}
+
+
+static void *
+tf_pwrite (void *arg)
+{
+  if (arg == NULL)
+    // XXX If somebody can provide a portable test case in which pwrite()
+    // blocks we can enable this test to run in both rounds.
+    abort ();
+
+  char fname[] = "/tmp/tst-cancel4-fd-XXXXXX";
+  tempfd = mkstemp (fname);
+  if (tempfd == -1)
+    {
+      printf ("%s: mkstemp failed\n", __FUNCTION__);
+      exit (1);
+    }
+  unlink (fname);
+
+  int r = pthread_barrier_wait (&b2);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: barrier_wait failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  r = pthread_barrier_wait (&b2);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  pthread_cleanup_push (cl, NULL);
+
+  char mem[10];
+  pwrite (tempfd, mem, sizeof (mem), 0);
+
+  pthread_cleanup_pop (0);
+
+  printf ("%s: pwrite returned\n", __FUNCTION__);
+
+  exit (1);
+}
+
+
+static void *
+tf_fsync (void *arg)
+{
+  if (arg == NULL)
+    // XXX If somebody can provide a portable test case in which fsync()
+    // blocks we can enable this test to run in both rounds.
+    abort ();
+
+  tempfd = open ("Makefile", O_RDONLY);
+  if (tempfd == -1)
+    {
+      printf ("%s: cannot open Makefile\n", __FUNCTION__);
+      exit (1);
+    }
+
+  int r = pthread_barrier_wait (&b2);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: barrier_wait failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  r = pthread_barrier_wait (&b2);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  pthread_cleanup_push (cl, NULL);
+
+  fsync (tempfd);
+
+  pthread_cleanup_pop (0);
+
+  printf ("%s: fsync returned\n", __FUNCTION__);
+
+  exit (1);
+}
+
+
+static void *
+tf_fdatasync (void *arg)
+{
+  if (arg == NULL)
+    // XXX If somebody can provide a portable test case in which fdatasync()
+    // blocks we can enable this test to run in both rounds.
+    abort ();
+
+  tempfd = open ("Makefile", O_RDONLY);
+  if (tempfd == -1)
+    {
+      printf ("%s: cannot open Makefile\n", __FUNCTION__);
+      exit (1);
+    }
+
+  int r = pthread_barrier_wait (&b2);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: barrier_wait failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  r = pthread_barrier_wait (&b2);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  pthread_cleanup_push (cl, NULL);
+
+  fdatasync (tempfd);
+
+  pthread_cleanup_pop (0);
+
+  printf ("%s: fdatasync returned\n", __FUNCTION__);
+
+  exit (1);
+}
+
+
+static void *
+tf_msync (void *arg)
+{
+  if (arg == NULL)
+    // XXX If somebody can provide a portable test case in which msync()
+    // blocks we can enable this test to run in both rounds.
+    abort ();
+
+  tempfd = open ("Makefile", O_RDONLY);
+  if (tempfd == -1)
+    {
+      printf ("%s: cannot open Makefile\n", __FUNCTION__);
+      exit (1);
+    }
+  void *p = mmap (NULL, 10, PROT_READ, MAP_SHARED, tempfd, 0);
+  if (p == MAP_FAILED)
+    {
+      printf ("%s: mmap failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  int r = pthread_barrier_wait (&b2);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: barrier_wait failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  r = pthread_barrier_wait (&b2);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  pthread_cleanup_push (cl, NULL);
+
+  msync (p, 10, 0);
+
+  pthread_cleanup_pop (0);
+
+  printf ("%s: msync returned\n", __FUNCTION__);
+
+  exit (1);
+}
+
+
+static void *
+tf_sendto (void *arg)
+{
+  if (arg == NULL)
+    // XXX If somebody can provide a portable test case in which sendto()
+    // blocks we can enable this test to run in both rounds.
+    abort ();
+
+  struct sockaddr_un sun;
+
+  tempfd = socket (AF_UNIX, SOCK_DGRAM, 0);
+  if (tempfd == -1)
+    {
+      printf ("%s: first socket call failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  int tries = 0;
+  do
+    {
+      if (++tries > 10)
+	{
+	  printf ("%s: too many unsuccessful bind calls\n", __FUNCTION__);
+	}
+
+      strcpy (sun.sun_path, "/tmp/tst-cancel4-socket-6-XXXXXX");
+      if (mktemp (sun.sun_path) == NULL)
+	{
+	  printf ("%s: cannot generate temp file name\n", __FUNCTION__);
+	  exit (1);
+	}
+
+      sun.sun_family = AF_UNIX;
+    }
+  while (bind (tempfd, (struct sockaddr *) &sun,
+	       offsetof (struct sockaddr_un, sun_path)
+	       + strlen (sun.sun_path) + 1) != 0);
+  tempfname = strdup (sun.sun_path);
+
+  tempfd2 = socket (AF_UNIX, SOCK_DGRAM, 0);
+  if (tempfd2 == -1)
+    {
+      printf ("%s: second socket call failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  int r = pthread_barrier_wait (&b2);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: barrier_wait failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  r = pthread_barrier_wait (&b2);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  pthread_cleanup_push (cl, NULL);
+
+  char mem[1];
+
+  sendto (tempfd2, mem, arg == NULL ? sizeof (mem) : 1, 0,
+	  (struct sockaddr *) &sun,
+	  offsetof (struct sockaddr_un, sun_path) + strlen (sun.sun_path) + 1);
+
+  pthread_cleanup_pop (0);
+
+  printf ("%s: sendto returned\n", __FUNCTION__);
+
+  exit (1);
+}
+
+
+static void *
+tf_sendmsg (void *arg)
+{
+  if (arg == NULL)
+    // XXX If somebody can provide a portable test case in which sendmsg()
+    // blocks we can enable this test to run in both rounds.
+    abort ();
+
+  struct sockaddr_un sun;
+
+  tempfd = socket (AF_UNIX, SOCK_DGRAM, 0);
+  if (tempfd == -1)
+    {
+      printf ("%s: first socket call failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  int tries = 0;
+  do
+    {
+      if (++tries > 10)
+	{
+	  printf ("%s: too many unsuccessful bind calls\n", __FUNCTION__);
+	}
+
+      strcpy (sun.sun_path, "/tmp/tst-cancel4-socket-7-XXXXXX");
+      if (mktemp (sun.sun_path) == NULL)
+	{
+	  printf ("%s: cannot generate temp file name\n", __FUNCTION__);
+	  exit (1);
+	}
+
+      sun.sun_family = AF_UNIX;
+    }
+  while (bind (tempfd, (struct sockaddr *) &sun,
+	       offsetof (struct sockaddr_un, sun_path)
+	       + strlen (sun.sun_path) + 1) != 0);
+  tempfname = strdup (sun.sun_path);
+
+  tempfd2 = socket (AF_UNIX, SOCK_DGRAM, 0);
+  if (tempfd2 == -1)
+    {
+      printf ("%s: second socket call failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  int r = pthread_barrier_wait (&b2);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: barrier_wait failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  r = pthread_barrier_wait (&b2);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  pthread_cleanup_push (cl, NULL);
+
+  char mem[1];
+  struct iovec iov[1];
+  iov[0].iov_base = mem;
+  iov[0].iov_len = 1;
+
+  struct msghdr m;
+  m.msg_name = &sun;
+  m.msg_namelen = (offsetof (struct sockaddr_un, sun_path)
+		   + strlen (sun.sun_path) + 1);
+  m.msg_iov = iov;
+  m.msg_iovlen = 1;
+  m.msg_control = NULL;
+  m.msg_controllen = 0;
+
+  sendmsg (tempfd2, &m, 0);
+
+  pthread_cleanup_pop (0);
+
+  printf ("%s: sendmsg returned\n", __FUNCTION__);
+
+  exit (1);
+}
+
+
+static void *
+tf_creat (void *arg)
+{
+  if (arg == NULL)
+    // XXX If somebody can provide a portable test case in which sendmsg()
+    // blocks we can enable this test to run in both rounds.
+    abort ();
+
+  int r = pthread_barrier_wait (&b2);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: barrier_wait failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  r = pthread_barrier_wait (&b2);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  pthread_cleanup_push (cl, NULL);
+
+  creat ("tmp/tst-cancel-4-should-not-exist", 0666);
+
+  pthread_cleanup_pop (0);
+
+  printf ("%s: creat returned\n", __FUNCTION__);
+
+  exit (1);
+}
+
+
+static void *
+tf_connect (void *arg)
+{
+  if (arg == NULL)
+    // XXX If somebody can provide a portable test case in which connect()
+    // blocks we can enable this test to run in both rounds.
+    abort ();
+
+  struct sockaddr_un sun;
+
+  tempfd = socket (AF_UNIX, SOCK_STREAM, 0);
+  if (tempfd == -1)
+    {
+      printf ("%s: first socket call failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  int tries = 0;
+  do
+    {
+      if (++tries > 10)
+	{
+	  printf ("%s: too many unsuccessful bind calls\n", __FUNCTION__);
+	}
+
+      strcpy (sun.sun_path, "/tmp/tst-cancel4-socket-2-XXXXXX");
+      if (mktemp (sun.sun_path) == NULL)
+	{
+	  printf ("%s: cannot generate temp file name\n", __FUNCTION__);
+	  exit (1);
+	}
+
+      sun.sun_family = AF_UNIX;
+    }
+  while (bind (tempfd, (struct sockaddr *) &sun,
+	       offsetof (struct sockaddr_un, sun_path)
+	       + strlen (sun.sun_path) + 1) != 0);
+  tempfname = strdup (sun.sun_path);
+
+  listen (tempfd, 5);
+
+  tempfd2 = socket (AF_UNIX, SOCK_STREAM, 0);
+  if (tempfd2 == -1)
+    {
+      printf ("%s: second socket call failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  int r = pthread_barrier_wait (&b2);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: barrier_wait failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  if (arg != NULL)
+    {
+      r = pthread_barrier_wait (&b2);
+      if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+	{
+	  printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
+	  exit (1);
+	}
+    }
+
+  pthread_cleanup_push (cl, NULL);
+
+  connect (tempfd2, (struct sockaddr *) &sun, sizeof (sun));
+
+  pthread_cleanup_pop (0);
+
+  printf ("%s: connect returned\n", __FUNCTION__);
+
+  exit (1);
+}
+
+
+static void *
+tf_tcdrain (void *arg)
+{
+  if (arg == NULL)
+    // XXX If somebody can provide a portable test case in which tcdrain()
+    // blocks we can enable this test to run in both rounds.
+    abort ();
+
+  int r = pthread_barrier_wait (&b2);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: barrier_wait failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  if (arg != NULL)
+    {
+      r = pthread_barrier_wait (&b2);
+      if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+	{
+	  printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
+	  exit (1);
+	}
+    }
+
+  pthread_cleanup_push (cl, NULL);
+
+  /* Regardless of stderr being a terminal, the tcdrain call should be
+     canceled.  */
+  tcdrain (STDERR_FILENO);
+
+  pthread_cleanup_pop (0);
+
+  printf ("%s: tcdrain returned\n", __FUNCTION__);
+
+  exit (1);
+}
+
+
+static void *
+tf_msgrcv (void *arg)
+{
+  tempmsg = msgget (IPC_PRIVATE, 0666 | IPC_CREAT);
+  if (tempmsg == -1)
+    {
+      printf ("%s: msgget failed: %s\n", __FUNCTION__, strerror (errno));
+      exit (1);
+    }
+
+  int r = pthread_barrier_wait (&b2);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: barrier_wait failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  if (arg != NULL)
+    {
+      r = pthread_barrier_wait (&b2);
+      if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+	{
+	  printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
+	  exit (1);
+	}
+    }
+
+  ssize_t s;
+
+  pthread_cleanup_push (cl, NULL);
+
+  struct
+  {
+    long int type;
+    char mem[10];
+  } m;
+  int randnr;
+  /* We need a positive random number.  */
+  do
+    randnr = random () % 64000;
+  while (randnr <= 0);
+  do
+    {
+      errno = 0;
+      s = msgrcv (tempmsg, (struct msgbuf *) &m, 10, randnr, 0);
+    }
+  while (errno == EIDRM || errno == EINTR);
+
+  pthread_cleanup_pop (0);
+
+  printf ("%s: msgrcv returned %zd with errno = %m\n", __FUNCTION__, s);
+
+  msgctl (tempmsg, IPC_RMID, NULL);
+
+  exit (1);
+}
+
+
+static void *
+tf_msgsnd (void *arg)
+{
+  if (arg == NULL)
+    // XXX If somebody can provide a portable test case in which msgsnd()
+    // blocks we can enable this test to run in both rounds.
+    abort ();
+
+  tempmsg = msgget (IPC_PRIVATE, 0666 | IPC_CREAT);
+  if (tempmsg == -1)
+    {
+      printf ("%s: msgget failed: %s\n", __FUNCTION__, strerror (errno));
+      exit (1);
+    }
+
+  int r = pthread_barrier_wait (&b2);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: barrier_wait failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  r = pthread_barrier_wait (&b2);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  pthread_cleanup_push (cl, NULL);
+
+  struct
+  {
+    long int type;
+    char mem[1];
+  } m;
+  /* We need a positive random number.  */
+  do
+    m.type = random () % 64000;
+  while (m.type <= 0);
+  msgsnd (tempmsg, (struct msgbuf *) &m, sizeof (m.mem), 0);
+
+  pthread_cleanup_pop (0);
+
+  printf ("%s: msgsnd returned\n", __FUNCTION__);
+
+  msgctl (tempmsg, IPC_RMID, NULL);
+
+  exit (1);
+}
+
+
+static struct
+{
+  const char *name;
+  void *(*tf) (void *);
+  int nb;
+  int only_early;
+} tests[] =
+{
+#define ADD_TEST(name, nbar, early) { #name, tf_##name, nbar, early }
+  ADD_TEST (read, 2, 0),
+  ADD_TEST (readv, 2, 0),
+  ADD_TEST (select, 2, 0),
+  ADD_TEST (pselect, 2, 0),
+  ADD_TEST (poll, 2, 0),
+  ADD_TEST (ppoll, 2, 0),
+  ADD_TEST (write, 2, 0),
+  ADD_TEST (writev, 2, 0),
+  ADD_TEST (sleep, 2, 0),
+  ADD_TEST (usleep, 2, 0),
+  ADD_TEST (nanosleep, 2, 0),
+  ADD_TEST (wait, 2, 0),
+  ADD_TEST (waitid, 2, 0),
+  ADD_TEST (waitpid, 2, 0),
+  ADD_TEST (sigpause, 2, 0),
+  ADD_TEST (sigsuspend, 2, 0),
+  ADD_TEST (sigwait, 2, 0),
+  ADD_TEST (sigwaitinfo, 2, 0),
+  ADD_TEST (sigtimedwait, 2, 0),
+  ADD_TEST (pause, 2, 0),
+  ADD_TEST (accept, 2, 0),
+  ADD_TEST (send, 2, 0),
+  ADD_TEST (recv, 2, 0),
+  ADD_TEST (recvfrom, 2, 0),
+  ADD_TEST (recvmsg, 2, 0),
+  ADD_TEST (open, 2, 1),
+  ADD_TEST (close, 2, 1),
+  ADD_TEST (pread, 2, 1),
+  ADD_TEST (pwrite, 2, 1),
+  ADD_TEST (fsync, 2, 1),
+  ADD_TEST (fdatasync, 2, 1),
+  ADD_TEST (msync, 2, 1),
+  ADD_TEST (sendto, 2, 1),
+  ADD_TEST (sendmsg, 2, 1),
+  ADD_TEST (creat, 2, 1),
+  ADD_TEST (connect, 2, 1),
+  ADD_TEST (tcdrain, 2, 1),
+  ADD_TEST (msgrcv, 2, 0),
+  ADD_TEST (msgsnd, 2, 1),
+};
+#define ntest_tf (sizeof (tests) / sizeof (tests[0]))
+
+
+static int
+do_test (void)
+{
+  int val;
+  socklen_t len;
+
+  if (socketpair (AF_UNIX, SOCK_STREAM, PF_UNIX, fds) != 0)
+    {
+      perror ("socketpair");
+      exit (1);
+    }
+
+  val = 1;
+  len = sizeof(val);
+  setsockopt (fds[1], SOL_SOCKET, SO_SNDBUF, &val, sizeof(val));
+  if (getsockopt (fds[1], SOL_SOCKET, SO_SNDBUF, &val, &len) < 0)
+    {
+      perror ("getsockopt");
+      exit (1);
+    }
+  if (val >= WRITE_BUFFER_SIZE)
+    {
+      puts ("minimum write buffer size too large");
+      exit (1);
+    }
+  setsockopt (fds[1], SOL_SOCKET, SO_SNDBUF, &val, sizeof(val));
+
+  int result = 0;
+  size_t cnt;
+  for (cnt = 0; cnt < ntest_tf; ++cnt)
+    {
+      if (tests[cnt].only_early)
+	continue;
+
+      if (pthread_barrier_init (&b2, NULL, tests[cnt].nb) != 0)
+	{
+	  puts ("b2 init failed");
+	  exit (1);
+	}
+
+      /* Reset the counter for the cleanup handler.  */
+      cl_called = 0;
+
+      pthread_t th;
+      if (pthread_create (&th, NULL, tests[cnt].tf, NULL) != 0)
+	{
+	  printf ("create for '%s' test failed\n", tests[cnt].name);
+	  result = 1;
+	  continue;
+	}
+
+      int r = pthread_barrier_wait (&b2);
+      if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+	{
+	  printf ("%s: barrier_wait failed\n", __FUNCTION__);
+	  result = 1;
+	  continue;
+	}
+
+      struct timespec  ts = { .tv_sec = 0, .tv_nsec = 100000000 };
+      while (nanosleep (&ts, &ts) != 0)
+	continue;
+
+      if (pthread_cancel (th) != 0)
+	{
+	  printf ("cancel for '%s' failed\n", tests[cnt].name);
+	  result = 1;
+	  continue;
+	}
+
+      void *status;
+      if (pthread_join (th, &status) != 0)
+	{
+	  printf ("join for '%s' failed\n", tests[cnt].name);
+	  result = 1;
+	  continue;
+	}
+      if (status != PTHREAD_CANCELED)
+	{
+	  printf ("thread for '%s' not canceled\n", tests[cnt].name);
+	  result = 1;
+	  continue;
+	}
+
+      if (pthread_barrier_destroy (&b2) != 0)
+	{
+	  puts ("barrier_destroy failed");
+	  result = 1;
+	  continue;
+	}
+
+      if (cl_called == 0)
+	{
+	  printf ("cleanup handler not called for '%s'\n", tests[cnt].name);
+	  result = 1;
+	  continue;
+	}
+      if (cl_called > 1)
+	{
+	  printf ("cleanup handler called more than once for '%s'\n",
+		  tests[cnt].name);
+	  result = 1;
+	  continue;
+	}
+
+      printf ("in-time cancel test of '%s' successful\n", tests[cnt].name);
+
+      if (tempfd != -1)
+	{
+	  close (tempfd);
+	  tempfd = -1;
+	}
+      if (tempfd2 != -1)
+	{
+	  close (tempfd2);
+	  tempfd2 = -1;
+	}
+      if (tempfname != NULL)
+	{
+	  unlink (tempfname);
+	  free (tempfname);
+	  tempfname = NULL;
+	}
+      if (tempmsg != -1)
+	{
+	  msgctl (tempmsg, IPC_RMID, NULL);
+	  tempmsg = -1;
+	}
+    }
+
+  for (cnt = 0; cnt < ntest_tf; ++cnt)
+    {
+      if (pthread_barrier_init (&b2, NULL, tests[cnt].nb) != 0)
+	{
+	  puts ("b2 init failed");
+	  exit (1);
+	}
+
+      /* Reset the counter for the cleanup handler.  */
+      cl_called = 0;
+
+      pthread_t th;
+      if (pthread_create (&th, NULL, tests[cnt].tf, (void *) 1l) != 0)
+	{
+	  printf ("create for '%s' test failed\n", tests[cnt].name);
+	  result = 1;
+	  continue;
+	}
+
+      int r = pthread_barrier_wait (&b2);
+      if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+	{
+	  printf ("%s: barrier_wait failed\n", __FUNCTION__);
+	  result = 1;
+	  continue;
+	}
+
+      if (pthread_cancel (th) != 0)
+	{
+	  printf ("cancel for '%s' failed\n", tests[cnt].name);
+	  result = 1;
+	  continue;
+	}
+
+      r = pthread_barrier_wait (&b2);
+      if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+	{
+	  printf ("%s: barrier_wait failed\n", __FUNCTION__);
+	  result = 1;
+	  continue;
+	}
+
+      void *status;
+      if (pthread_join (th, &status) != 0)
+	{
+	  printf ("join for '%s' failed\n", tests[cnt].name);
+	  result = 1;
+	  continue;
+	}
+      if (status != PTHREAD_CANCELED)
+	{
+	  printf ("thread for '%s' not canceled\n", tests[cnt].name);
+	  result = 1;
+	  continue;
+	}
+
+      if (pthread_barrier_destroy (&b2) != 0)
+	{
+	  puts ("barrier_destroy failed");
+	  result = 1;
+	  continue;
+	}
+
+      if (cl_called == 0)
+	{
+	  printf ("cleanup handler not called for '%s'\n", tests[cnt].name);
+	  result = 1;
+	  continue;
+	}
+      if (cl_called > 1)
+	{
+	  printf ("cleanup handler called more than once for '%s'\n",
+		  tests[cnt].name);
+	  result = 1;
+	  continue;
+	}
+
+      printf ("early cancel test of '%s' successful\n", tests[cnt].name);
+
+      if (tempfd != -1)
+	{
+	  close (tempfd);
+	  tempfd = -1;
+	}
+      if (tempfd2 != -1)
+	{
+	  close (tempfd2);
+	  tempfd2 = -1;
+	}
+      if (tempfname != NULL)
+	{
+	  unlink (tempfname);
+	  free (tempfname);
+	  tempfname = NULL;
+	}
+      if (tempmsg != -1)
+	{
+	  msgctl (tempmsg, IPC_RMID, NULL);
+	  tempmsg = -1;
+	}
+    }
+
+  return result;
+}
+
+#define TIMEOUT 60
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel5.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel5.c
new file mode 100644
index 00000000..1c879eba
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel5.c
@@ -0,0 +1 @@
+#include "tst-cancel4.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel6.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel6.c
new file mode 100644
index 00000000..94de8583
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel6.c
@@ -0,0 +1,79 @@
+/* Copyright (C) 2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2002.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+
+
+static void *
+tf (void *arg)
+{
+  char buf[100];
+  fgets (buf, sizeof (buf), arg);
+  /* This call should never return.  */
+  return NULL;
+}
+
+
+static int
+do_test (void)
+{
+  int fd[2];
+  if (pipe (fd) != 0)
+    {
+      puts ("pipe failed");
+      return 1;
+    }
+
+  FILE *fp = fdopen (fd[0], "r");
+  if (fp == NULL)
+    {
+      puts ("fdopen failed");
+      return 1;
+    }
+
+  pthread_t th;
+  if (pthread_create (&th, NULL, tf, fp) != 0)
+    {
+      puts ("pthread_create failed");
+      return 1;
+    }
+
+  sleep (1);
+
+  if (pthread_cancel (th) != 0)
+    {
+      puts ("pthread_cancel failed");
+      return 1;
+    }
+
+  void *r;
+  if (pthread_join (th, &r) != 0)
+    {
+      puts ("pthread_join failed");
+      return 1;
+    }
+
+  return r != PTHREAD_CANCELED;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel7.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel7.c
new file mode 100644
index 00000000..16cc47cf
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel7.c
@@ -0,0 +1,213 @@
+/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek , 2002.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+const char *command;
+const char *pidfile;
+char pidfilename[] = "/tmp/tst-cancel7-XXXXXX";
+
+static void *
+tf (void *arg)
+{
+  const char *args = " --direct --pidfile ";
+  char *cmd = alloca (strlen (command) + strlen (args)
+		      + strlen (pidfilename) + 1);
+
+  strcpy (stpcpy (stpcpy (cmd, command), args), pidfilename);
+  system (cmd);
+  /* This call should never return.  */
+  return NULL;
+}
+
+
+static void
+sl (void)
+{
+  FILE *f = fopen (pidfile, "w");
+  if (f == NULL)
+    exit (1);
+
+  fprintf (f, "%lld\n", (long long) getpid ());
+  fflush (f);
+
+  struct flock fl =
+    {
+      .l_type = F_WRLCK,
+      .l_start = 0,
+      .l_whence = SEEK_SET,
+      .l_len = 1
+    };
+  if (fcntl (fileno (f), F_SETLK, &fl) != 0)
+    exit (1);
+
+  sigset_t ss;
+  sigfillset (&ss);
+  sigsuspend (&ss);
+  exit (0);
+}
+
+
+static void
+do_prepare (int argc, char *argv[])
+{
+  if (command == NULL)
+    command = argv[0];
+
+  if (pidfile)
+    sl ();
+
+  int fd = mkstemp (pidfilename);
+  if (fd == -1)
+    {
+      puts ("mkstemp failed");
+      exit (1);
+    }
+
+  write (fd, " ", 1);
+  close (fd);
+}
+
+
+static int
+do_test (void)
+{
+  pthread_t th;
+  if (pthread_create (&th, NULL, tf, NULL) != 0)
+    {
+      puts ("pthread_create failed");
+      return 1;
+    }
+
+  do
+    sleep (1);
+  while (access (pidfilename, R_OK) != 0);
+
+  if (pthread_cancel (th) != 0)
+    {
+      puts ("pthread_cancel failed");
+      return 1;
+    }
+
+  void *r;
+  if (pthread_join (th, &r) != 0)
+    {
+      puts ("pthread_join failed");
+      return 1;
+    }
+
+  sleep (1);
+
+  FILE *f = fopen (pidfilename, "r+");
+  if (f == NULL)
+    {
+      puts ("no pidfile");
+      return 1;
+    }
+
+  long long ll;
+  if (fscanf (f, "%lld\n", &ll) != 1)
+    {
+      puts ("could not read pid");
+      unlink (pidfilename);
+      return 1;
+    }
+
+  struct flock fl =
+    {
+      .l_type = F_WRLCK,
+      .l_start = 0,
+      .l_whence = SEEK_SET,
+      .l_len = 1
+    };
+  if (fcntl (fileno (f), F_GETLK, &fl) != 0)
+    {
+      puts ("F_GETLK failed");
+      unlink (pidfilename);
+      return 1;
+    }
+
+  if (fl.l_type != F_UNLCK)
+    {
+      printf ("child %lld still running\n", (long long) fl.l_pid);
+      if (fl.l_pid == ll)
+	kill (fl.l_pid, SIGKILL);
+
+      unlink (pidfilename);
+      return 1;
+    }
+
+  fclose (f);
+
+  unlink (pidfilename);
+
+  return r != PTHREAD_CANCELED;
+}
+
+#if 0 /* unused */
+static void
+do_cleanup (void)
+{
+  FILE *f = fopen (pidfilename, "r+");
+  long long ll;
+
+  if (f != NULL && fscanf (f, "%lld\n", &ll) == 1)
+    {
+      struct flock fl =
+	{
+	  .l_type = F_WRLCK,
+	  .l_start = 0,
+	  .l_whence = SEEK_SET,
+	  .l_len = 1
+	};
+      if (fcntl (fileno (f), F_GETLK, &fl) == 0 && fl.l_type != F_UNLCK
+	  && fl.l_pid == ll)
+	kill (fl.l_pid, SIGKILL);
+
+      fclose (f);
+    }
+
+  unlink (pidfilename);
+}
+#endif
+
+#define OPT_COMMAND	10000
+#define OPT_PIDFILE	10001
+#define CMDLINE_OPTIONS \
+  { "command", required_argument, NULL, OPT_COMMAND },	\
+  { "pidfile", required_argument, NULL, OPT_PIDFILE },
+#define CMDLINE_PROCESS \
+  case OPT_COMMAND:	\
+    command = optarg;	\
+    break;		\
+  case OPT_PIDFILE:	\
+    pidfile = optarg;	\
+    break;
+// #define CLEANUP_HANDLER do_cleanup ()
+#define PREPARE(argc, argv) do_prepare (argc, argv)
+#define TEST_FUNCTION do_test ()
+#define TIMEOUT 5
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel8.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel8.c
new file mode 100644
index 00000000..fc836627
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel8.c
@@ -0,0 +1,143 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+
+
+static pthread_barrier_t bar;
+
+static int global;
+
+
+static void
+cleanup (void *arg)
+{
+  global = 1;
+}
+
+
+static void *
+tf (void *arg)
+{
+  /* Enable cancellation, but defer it.  */
+  if (pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, NULL) != 0)
+    {
+      puts ("setcancelstate failed");
+      exit (1);
+    }
+  if (pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, NULL) != 0)
+    {
+      puts ("setcanceltype failed");
+      exit (1);
+    }
+
+  /* Add cleanup handler.  */
+  pthread_cleanup_push (cleanup, NULL);
+
+  /* Synchronize with the main thread.  */
+  int r = pthread_barrier_wait (&bar);
+  if (r != 0 && r!= PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("tf: first barrier_wait failed");
+      exit (1);
+    }
+
+  /* And again.  Once this is done the main thread should have canceled
+     this thread.  */
+  r = pthread_barrier_wait (&bar);
+  if (r != 0 && r!= PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("tf: second barrier_wait failed");
+      exit (1);
+    }
+
+  /* Remove the cleanup handler without executing it.  */
+  pthread_cleanup_pop (0);
+
+  /* Now react on the cancellation.  */
+  pthread_testcancel ();
+
+  /* This call should never return.  */
+  return NULL;
+}
+
+
+static int
+do_test (void)
+{
+  if (pthread_barrier_init (&bar, NULL, 2) != 0)
+    {
+      puts ("barrier_init failed");
+      exit (1);
+    }
+
+  pthread_t th;
+  if (pthread_create (&th, NULL, tf, NULL) != 0)
+    {
+      puts ("pthread_create failed");
+      return 1;
+    }
+
+  int r = pthread_barrier_wait (&bar);
+  if (r != 0 && r!= PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("first barrier_wait failed");
+      exit (1);
+    }
+
+  if (pthread_cancel (th) != 0)
+    {
+      puts ("pthread_cancel failed");
+      return 1;
+    }
+
+  r = pthread_barrier_wait (&bar);
+  if (r != 0 && r!= PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("second barrier_wait failed");
+      exit (1);
+    }
+
+  void *result;
+  if (pthread_join (th, &result) != 0)
+    {
+      puts ("pthread_join failed");
+      return 1;
+    }
+
+  if (result != PTHREAD_CANCELED)
+    {
+      puts ("thread was not canceled");
+      exit (1);
+    }
+
+  if (global != 0)
+    {
+      puts ("cancellation handler has been called");
+      exit (1);
+    }
+
+  return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel9.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel9.c
new file mode 100644
index 00000000..037ef30f
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancel9.c
@@ -0,0 +1,126 @@
+/* Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+static pthread_barrier_t b;
+
+
+static void
+cleanup (void *arg)
+{
+  fputs ("in cleanup\n", stdout);
+}
+
+
+static void *
+tf (void *arg)
+{
+  int fd = open ("/dev/null", O_RDWR);
+  if (fd == -1)
+    {
+      puts ("cannot open /dev/null");
+      exit (1);
+    }
+  FILE *fp = fdopen (fd, "w");
+  if (fp == NULL)
+    {
+      puts ("fdopen failed");
+      exit (1);
+    }
+
+  pthread_cleanup_push (cleanup, NULL);
+
+  int e = pthread_barrier_wait (&b);
+  if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("barrier_wait failed");
+      exit (1);
+    }
+
+  while (1)
+    /* fprintf() uses write() which is a cancallation point.  */
+    fprintf (fp, "foo");
+
+  pthread_cleanup_pop (0);
+
+  return NULL;
+}
+
+
+static int
+do_test (void)
+{
+  if (pthread_barrier_init (&b, NULL, 2) != 0)
+    {
+      puts ("barrier_init failed");
+      exit (1);
+    }
+
+  pthread_t th;
+  if (pthread_create (&th, NULL, tf, NULL) != 0)
+    {
+      puts ("create failed");
+      return 1;
+    }
+
+  int e = pthread_barrier_wait (&b);
+  if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("barrier_wait failed");
+      exit (1);
+    }
+
+  sleep (1);
+
+  puts ("cancel now");
+
+  if (pthread_cancel (th) != 0)
+    {
+      puts ("cancel failed");
+      exit (1);
+    }
+
+  puts ("waiting for the child");
+
+  void *r;
+  if (pthread_join (th, &r) != 0)
+    {
+      puts ("join failed");
+      exit (1);
+    }
+
+  if (r != PTHREAD_CANCELED)
+    {
+      puts ("thread wasn't canceled");
+      exit (1);
+    }
+
+  return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancelx10.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancelx10.c
new file mode 100644
index 00000000..e5bbb34e
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancelx10.c
@@ -0,0 +1 @@
+#include "tst-cancel10.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancelx11.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancelx11.c
new file mode 100644
index 00000000..ffcc2eef
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancelx11.c
@@ -0,0 +1 @@
+#include "tst-cancel11.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancelx12.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancelx12.c
new file mode 100644
index 00000000..f90ae61b
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancelx12.c
@@ -0,0 +1 @@
+#include "tst-cancel12.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancelx13.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancelx13.c
new file mode 100644
index 00000000..37c4c39c
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancelx13.c
@@ -0,0 +1 @@
+#include "tst-cancel13.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancelx14.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancelx14.c
new file mode 100644
index 00000000..ba4e7758
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancelx14.c
@@ -0,0 +1 @@
+#include "tst-cancel14.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancelx15.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancelx15.c
new file mode 100644
index 00000000..005c1f6e
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancelx15.c
@@ -0,0 +1 @@
+#include "tst-cancel15.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancelx16.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancelx16.c
new file mode 100644
index 00000000..99af3b19
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancelx16.c
@@ -0,0 +1 @@
+#include "tst-cancel16.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancelx18.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancelx18.c
new file mode 100644
index 00000000..56da18f3
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancelx18.c
@@ -0,0 +1 @@
+#include "tst-cancel18.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancelx2.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancelx2.c
new file mode 100644
index 00000000..95dc8a85
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancelx2.c
@@ -0,0 +1 @@
+#include "tst-cancel2.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancelx20.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancelx20.c
new file mode 100644
index 00000000..6bd86376
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancelx20.c
@@ -0,0 +1 @@
+#include "tst-cancel20.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancelx21.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancelx21.c
new file mode 100644
index 00000000..2a01061e
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancelx21.c
@@ -0,0 +1 @@
+#include "tst-cancel21.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancelx3.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancelx3.c
new file mode 100644
index 00000000..3937f10b
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancelx3.c
@@ -0,0 +1 @@
+#include "tst-cancel3.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancelx4.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancelx4.c
new file mode 100644
index 00000000..1c879eba
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancelx4.c
@@ -0,0 +1 @@
+#include "tst-cancel4.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancelx6.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancelx6.c
new file mode 100644
index 00000000..6926e21c
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancelx6.c
@@ -0,0 +1 @@
+#include "tst-cancel6.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancelx7.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancelx7.c
new file mode 100644
index 00000000..4df1a588
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancelx7.c
@@ -0,0 +1 @@
+#include "tst-cancel7.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancelx8.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancelx8.c
new file mode 100644
index 00000000..0555c7ce
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancelx8.c
@@ -0,0 +1 @@
+#include "tst-cancel8.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancelx9.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancelx9.c
new file mode 100644
index 00000000..9d84663d
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cancelx9.c
@@ -0,0 +1 @@
+#include "tst-cancel9.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cleanup0.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cleanup0.c
new file mode 100644
index 00000000..6fc2209c
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cleanup0.c
@@ -0,0 +1,76 @@
+/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2002.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+
+
+static int global;
+
+
+static void
+ch (void *arg)
+{
+  int val = (long int) arg;
+
+  printf ("ch (%d)\n", val);
+
+  global *= val;
+  global += val;
+}
+
+
+static void
+endfct (void)
+{
+  /* We force exit right here.  */
+  _exit (global);
+}
+
+
+static int
+do_test (void)
+{
+  atexit (endfct);
+
+  pthread_cancel (pthread_self ());
+
+  pthread_cleanup_push (ch, (void *) 1l);
+
+  pthread_cleanup_push (ch, (void *) 2l);
+
+  pthread_cleanup_push (ch, (void *) 3l);
+
+//  pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
+
+  pthread_cleanup_pop (1);
+
+  pthread_cleanup_pop (1);
+
+  pthread_cleanup_pop (1);
+
+  return 100;
+}
+
+
+#define EXPECTED_STATUS 9
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cleanup1.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cleanup1.c
new file mode 100644
index 00000000..2230e0fb
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cleanup1.c
@@ -0,0 +1,100 @@
+/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2002.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+
+
+static int global;
+
+
+static void
+ch (void *arg)
+{
+  int val = (long int) arg;
+
+  printf ("ch (%d)\n", val);
+
+  global *= val;
+  global += val;
+}
+
+
+static void *
+tf (void *a)
+{
+  pthread_cancel (pthread_self ());
+
+  pthread_cleanup_push (ch, (void *) 1l);
+
+  pthread_cleanup_push (ch, (void *) 2l);
+
+  pthread_cleanup_push (ch, (void *) 3l);
+
+  pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
+
+  pthread_cleanup_pop (1);
+
+  pthread_cleanup_pop (1);
+
+  pthread_cleanup_pop (1);
+
+  return NULL;
+}
+
+
+int
+do_test (void)
+{
+  pthread_t th;
+
+  if (pthread_create (&th, NULL, tf, NULL) != 0)
+    {
+      write (2, "create failed\n", 14);
+      _exit (1);
+    }
+
+  void *r;
+  int e;
+  if ((e = pthread_join (th, &r)) != 0)
+    {
+      printf ("join failed: %d\n", e);
+      _exit (1);
+    }
+
+  if (r != PTHREAD_CANCELED)
+    {
+      puts ("thread not canceled");
+      exit (1);
+    }
+
+  if (global != 9)
+    {
+      printf ("global = %d, expected 9\n", global);
+      exit (1);
+    }
+
+  return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cleanup2.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cleanup2.c
new file mode 100644
index 00000000..30e10b12
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cleanup2.c
@@ -0,0 +1,63 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Bao Duong , 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+static sigjmp_buf jmpbuf;
+
+static void
+sig_handler (int signo)
+{
+  siglongjmp (jmpbuf, 1);
+}
+
+static int
+do_test (void)
+{
+  char *p = NULL;
+  struct sigaction sa;
+
+  sa.sa_handler = sig_handler;
+  sigemptyset (&sa.sa_mask);
+  sa.sa_flags = SA_SIGINFO;
+
+  if (sigaction (SIGSEGV, &sa, 0))
+    {
+      perror ("installing SIGSEGV handler\n");
+      exit (1);
+    }
+
+  puts ("Attempting to sprintf to null ptr");
+  if (setjmp (jmpbuf))
+    {
+      puts ("Exiting main...");
+      return 0;
+    }
+
+  sprintf (p, "This should segv\n");
+
+  return 1;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cleanup3.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cleanup3.c
new file mode 100644
index 00000000..c4427737
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cleanup3.c
@@ -0,0 +1,98 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+
+
+static int global;
+
+
+static void
+ch (void *arg)
+{
+  int val = (long int) arg;
+
+  printf ("ch (%d)\n", val);
+
+  global *= val;
+  global += val;
+}
+
+
+static void *
+tf (void *a)
+{
+  pthread_cleanup_push (ch, (void *) 1l);
+
+  pthread_cleanup_push (ch, (void *) 2l);
+
+  pthread_cleanup_push (ch, (void *) 3l);
+
+  pthread_exit ((void *) 1l);
+
+  pthread_cleanup_pop (1);
+
+  pthread_cleanup_pop (1);
+
+  pthread_cleanup_pop (1);
+
+  return NULL;
+}
+
+
+int
+do_test (void)
+{
+  pthread_t th;
+
+  if (pthread_create (&th, NULL, tf, NULL) != 0)
+    {
+      write (2, "create failed\n", 14);
+      _exit (1);
+    }
+
+  void *r;
+  int e;
+  if ((e = pthread_join (th, &r)) != 0)
+    {
+      printf ("join failed: %d\n", e);
+      _exit (1);
+    }
+
+  if (r != (void *) 1l)
+    {
+      puts ("thread not canceled");
+      exit (1);
+    }
+
+  if (global != 9)
+    {
+      printf ("global = %d, expected 9\n", global);
+      exit (1);
+    }
+
+  return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cleanup4.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cleanup4.c
new file mode 100644
index 00000000..1489fd31
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cleanup4.c
@@ -0,0 +1,198 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek , 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+
+/* LinuxThreads pthread_cleanup_{push,pop} helpers.  */
+extern void _pthread_cleanup_push (struct _pthread_cleanup_buffer *__buffer,
+                                   void (*__routine) (void *),
+                                   void *__arg);
+extern void _pthread_cleanup_pop (struct _pthread_cleanup_buffer *__buffer,
+                                  int __execute);
+
+static int fds[2];
+static pthread_barrier_t b2;
+static int global;
+
+/* Defined in tst-cleanup4aux.c, never compiled with -fexceptions.  */
+extern void fn5 (void);
+extern void fn7 (void);
+extern void fn9 (void);
+
+void
+clh (void *arg)
+{
+  int val = (long int) arg;
+
+  printf ("clh (%d)\n", val);
+
+  global *= val;
+  global += val;
+}
+
+
+static __attribute__((noinline)) void
+fn_read (void)
+{
+  int r = pthread_barrier_wait (&b2);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: barrier_wait failed\n", __FUNCTION__);
+      exit (1);
+    }
+
+  char c;
+  read (fds[0], &c, 1);
+}
+
+
+__attribute__((noinline)) void
+fn0 (void)
+{
+  pthread_cleanup_push (clh, (void *) 1l);
+
+  fn_read ();
+
+  pthread_cleanup_pop (1);
+}
+
+
+__attribute__((noinline)) void
+fn1 (void)
+{
+  /* This is the old LinuxThreads pthread_cleanup_{push,pop}.  */
+  struct _pthread_cleanup_buffer b;
+  _pthread_cleanup_push (&b, clh, (void *) 2l);
+
+  fn0 ();
+
+  _pthread_cleanup_pop (&b, 1);
+}
+
+
+static __attribute__((noinline)) void
+fn2 (void)
+{
+  pthread_cleanup_push (clh, (void *) 3l);
+
+  fn1 ();
+
+  pthread_cleanup_pop (1);
+}
+
+
+static void *
+tf (void *a)
+{
+  switch ((long) a)
+    {
+    case 0:
+      fn2 ();
+      break;
+    case 1:
+      fn5 ();
+      break;
+    case 2:
+      fn7 ();
+      break;
+    case 3:
+      fn9 ();
+      break;
+    }
+
+  return NULL;
+}
+
+
+int
+do_test (void)
+{
+  int result = 0;
+
+  if (pipe (fds) != 0)
+    {
+      puts ("pipe failed");
+      exit (1);
+    }
+
+  if (pthread_barrier_init (&b2, NULL, 2) != 0)
+    {
+      puts ("b2 init failed");
+      exit (1);
+    }
+
+  const int expect[] =
+    {
+      15,	/* 1 2 3 */
+      276,	/* 1 4 5 6 */
+      120,	/* 1 7 8 */
+      460	/* 1 2 9 10 */
+    };
+
+  long i;
+  for (i = 0; i < 4; ++i)
+    {
+      global = 0;
+
+      printf ("test %ld\n", i);
+
+      pthread_t th;
+      if (pthread_create (&th, NULL, tf, (void *) i) != 0)
+	{
+	  puts ("create failed");
+	  exit (1);
+	}
+
+      int e = pthread_barrier_wait (&b2);
+      if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+	{
+	  printf ("%s: barrier_wait failed\n", __FUNCTION__);
+	  exit (1);
+	}
+
+      pthread_cancel (th);
+
+      void *r;
+      if ((e = pthread_join (th, &r)) != 0)
+	{
+	  printf ("join failed: %d\n", e);
+	  _exit (1);
+	}
+
+      if (r != PTHREAD_CANCELED)
+	{
+	  puts ("thread not canceled");
+	  exit (1);
+	}
+
+      if (global != expect[i])
+	{
+	  printf ("global = %d, expected %d\n", global, expect[i]);
+	  result = 1;
+	}
+    }
+
+  return result;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cleanup4aux.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cleanup4aux.c
new file mode 100644
index 00000000..cd1a89ac
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cleanup4aux.c
@@ -0,0 +1,121 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek , 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+
+extern void _pthread_cleanup_push (struct _pthread_cleanup_buffer *__buffer,
+                                   void (*__routine) (void *),
+                                   void *__arg);
+extern void _pthread_cleanup_pop (struct _pthread_cleanup_buffer *__buffer,
+                                  int __execute);
+
+extern void clh (void *arg);
+extern void fn0 (void);
+extern void fn1 (void);
+extern void fn5 (void);
+extern void fn7 (void);
+extern void fn9 (void);
+
+
+static __attribute__((noinline)) void
+fn3 (void)
+{
+  /* This is the old LinuxThreads pthread_cleanup_{push,pop}.  */
+     struct _pthread_cleanup_buffer b;
+  _pthread_cleanup_push (&b, clh, (void *) 4l);
+
+  fn0 ();
+
+  _pthread_cleanup_pop (&b, 1);
+}
+
+
+static __attribute__((noinline)) void
+fn4 (void)
+{
+  pthread_cleanup_push (clh, (void *) 5l);
+
+  fn3 ();
+
+  pthread_cleanup_pop (1);
+}
+
+
+void
+fn5 (void)
+{
+  /* This is the old LinuxThreads pthread_cleanup_{push,pop}.  */
+     struct _pthread_cleanup_buffer b;
+  _pthread_cleanup_push (&b, clh, (void *) 6l);
+
+  fn4 ();
+
+  _pthread_cleanup_pop (&b, 1);
+}
+
+
+static __attribute__((noinline)) void
+fn6 (void)
+{
+  pthread_cleanup_push (clh, (void *) 7l);
+
+  fn0 ();
+
+  pthread_cleanup_pop (1);
+}
+
+
+void
+fn7 (void)
+{
+  /* This is the old LinuxThreads pthread_cleanup_{push,pop}.  */
+     struct _pthread_cleanup_buffer b;
+  _pthread_cleanup_push (&b, clh, (void *) 8l);
+
+  fn6 ();
+
+  _pthread_cleanup_pop (&b, 1);
+}
+
+
+static __attribute__((noinline)) void
+fn8 (void)
+{
+  pthread_cleanup_push (clh, (void *) 9l);
+
+  fn1 ();
+
+  pthread_cleanup_pop (1);
+}
+
+
+void
+fn9 (void)
+{
+  /* This is the old LinuxThreads pthread_cleanup_{push,pop}.  */
+     struct _pthread_cleanup_buffer b;
+  _pthread_cleanup_push (&b, clh, (void *) 10l);
+
+  fn8 ();
+
+  _pthread_cleanup_pop (&b, 1);
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cleanupx0.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cleanupx0.c
new file mode 100644
index 00000000..0012ab1b
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cleanupx0.c
@@ -0,0 +1 @@
+#include "tst-cleanup0.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cleanupx1.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cleanupx1.c
new file mode 100644
index 00000000..21e9e58b
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cleanupx1.c
@@ -0,0 +1 @@
+#include "tst-cleanup1.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cleanupx2.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cleanupx2.c
new file mode 100644
index 00000000..8b9e3509
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cleanupx2.c
@@ -0,0 +1 @@
+#include "tst-cleanup2.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cleanupx3.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cleanupx3.c
new file mode 100644
index 00000000..90baf904
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cleanupx3.c
@@ -0,0 +1 @@
+#include "tst-cleanup3.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cleanupx4.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cleanupx4.c
new file mode 100644
index 00000000..8dea954b
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cleanupx4.c
@@ -0,0 +1 @@
+#include "tst-cleanup4.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-clock.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-clock.c
new file mode 100644
index 00000000..f2f18874
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-clock.c
@@ -0,0 +1,124 @@
+/* Test program for POSIX clock_* functions.
+   Copyright (C) 2000 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2000.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+
+
+/* We want to see output immediately.  */
+#define STDOUT_UNBUFFERED
+
+/* We expect to run at least 10 seconds.  */
+#define TIMEOUT 15
+
+static int
+clock_test (clockid_t cl)
+{
+  struct timespec old_ts;
+  struct timespec ts;
+  struct timespec waitit;
+  int result = 0;
+  int i;
+
+  memset (&ts, '\0', sizeof ts);
+
+  waitit.tv_sec = 0;
+  waitit.tv_nsec = 500000000;
+
+  /* Get and print resolution of the clock.  */
+  if (clock_getres (cl, &ts) == 0)
+    {
+      if (ts.tv_nsec < 0 || ts.tv_nsec >= 1000000000)
+	{
+	  printf ("clock %d: nanosecond value of resolution wrong\n", cl);
+	  result = 1;
+	}
+      else
+	printf ("clock %d: resolution = %ld.%09ld secs\n",
+		cl, ts.tv_sec, ts.tv_nsec);
+    }
+  else
+    {
+      printf ("clock %d: cannot get resolution\n", cl);
+      result = 1;
+    }
+
+  memset (&ts, '\0', sizeof ts);
+  memset (&old_ts, '\0', sizeof old_ts);
+
+  /* Next get the current time value a few times.  */
+  for (i = 0; i < 10; ++i)
+    {
+      if (clock_gettime (cl, &ts) == 0)
+	{
+	  if (ts.tv_nsec < 0 || ts.tv_nsec >= 1000000000)
+	    {
+	      printf ("clock %d: nanosecond value of time wrong (try %d)\n",
+		      cl, i);
+	      result = 1;
+	    }
+	  else
+	    {
+	      printf ("clock %d: time = %ld.%09ld secs\n",
+		      cl, ts.tv_sec, ts.tv_nsec);
+
+	      if (memcmp (&ts, &old_ts, sizeof ts) == 0)
+		{
+		  printf ("clock %d: time hasn't changed (try %d)\n", cl, i);
+		  result = 1;
+
+		  old_ts = ts;
+		}
+	    }
+	}
+      else
+	{
+	  printf ("clock %d: cannot get time (try %d)\n", cl, i);
+	  result = 1;
+	}
+
+      /* Wait a bit before the next iteration.  */
+      nanosleep (&waitit, NULL);
+    }
+
+  return result;
+}
+
+static int
+do_test (void)
+{
+  clockid_t cl;
+  int result;
+
+  result = clock_test (CLOCK_REALTIME);
+
+  if (clock_getcpuclockid (0, &cl) == 0)
+    /* XXX It's not yet a bug when this fails.  */
+    clock_test (cl);
+  else
+	  printf("CPU clock unavailble, skipping test\n");
+
+  return result;
+}
+#define TEST_FUNCTION do_test ()
+
+
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-clock1.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-clock1.c
new file mode 100644
index 00000000..0848d770
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-clock1.c
@@ -0,0 +1,51 @@
+/* Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+int
+do_test (void)
+{
+#if defined _POSIX_THREAD_CPUTIME && _POSIX_THREAD_CPUTIME >= 0
+  clockid_t cl;
+  /* This is really only a linking-test here.  */
+  int e = pthread_getcpuclockid (pthread_self (), &cl);
+  if (e != 0)
+    {
+# if _POSIX_THREAD_CPUTIME == 0
+      if (sysconf (_SC_THREAD_CPUTIME) >= 0)
+# endif
+	{
+	  puts ("cpuclock advertized, but cannot get ID");
+	  exit (1);
+	}
+    }
+#endif
+
+  return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-clock2.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-clock2.c
new file mode 100644
index 00000000..49a769bf
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-clock2.c
@@ -0,0 +1,202 @@
+/* Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+#if defined _POSIX_THREAD_CPUTIME && _POSIX_THREAD_CPUTIME >= 0
+static pthread_barrier_t b2;
+static pthread_barrier_t bN;
+
+
+static void *
+tf (void *arg)
+{
+  int e = pthread_barrier_wait (&b2);
+  if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("barrier_wait failed");
+      exit (1);
+    }
+
+  e = pthread_barrier_wait (&bN);
+  if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("barrier_wait failed");
+      exit (1);
+    }
+
+  return NULL;
+}
+#endif
+
+
+int
+do_test (void)
+{
+#if defined _POSIX_THREAD_CPUTIME && _POSIX_THREAD_CPUTIME >= 0
+# define N 10
+
+# if _POSIX_THREAD_CPUTIME == 0
+  if (sysconf (_SC_THREAD_CPUTIME) < 0)
+    {
+      puts ("_POSIX_THREAD_CPUTIME option not available");
+      return 1;
+    }
+# endif
+
+  if (pthread_barrier_init (&b2, NULL, 2) != 0
+      || pthread_barrier_init (&bN, NULL, N + 1) != 0)
+    {
+      puts ("barrier_init failed");
+      return 1;
+    }
+
+  struct timespec ts = { .tv_sec = 0, .tv_nsec = 100000000 };
+  TEMP_FAILURE_RETRY (nanosleep (&ts, &ts));
+
+  pthread_t th[N + 1];
+  clockid_t cl[N + 1];
+# ifndef CLOCK_THREAD_CPUTIME_ID
+  if (pthread_getcpuclockid (pthread_self (), &cl[0]) != 0)
+    {
+      puts ("own pthread_getcpuclockid failed");
+      return 1;
+    }
+# else
+  cl[0] = CLOCK_THREAD_CPUTIME_ID;
+# endif
+
+  pthread_attr_t at;
+
+  if (pthread_attr_init (&at) != 0)
+    {
+      puts ("attr_init failed");
+      return 1;
+    }
+
+  if (pthread_attr_setstacksize (&at, 1 * 1024 * 1024) != 0)
+    {
+      puts ("attr_setstacksize failed");
+      return 1;
+    }
+
+  int i;
+  int e;
+  for (i = 0; i < N; ++i)
+    {
+      if (pthread_create (&th[i], &at, tf, NULL) != 0)
+	{
+	  puts ("create failed");
+	  return 1;
+	}
+
+      e = pthread_barrier_wait (&b2);
+      if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+	{
+	  puts ("barrier_wait failed");
+	  return 1;
+	}
+
+      ts.tv_sec = 0;
+      ts.tv_nsec = 100000000;
+      TEMP_FAILURE_RETRY (nanosleep (&ts, &ts));
+
+      if (pthread_getcpuclockid (th[i], &cl[i + 1]) != 0)
+	{
+	  puts ("pthread_getcpuclockid failed");
+	  return 1;
+	}
+    }
+
+  if (pthread_attr_destroy (&at) != 0)
+    {
+      puts ("attr_destroy failed");
+      return 1;
+    }
+
+  struct timespec t[N + 1];
+  for (i = 0; i < N + 1; ++i)
+    if (clock_gettime (cl[i], &t[i]) != 0)
+      {
+	printf ("clock_gettime round %d failed\n", i);
+	return 1;
+      }
+
+  for (i = 0; i < N; ++i)
+    {
+      struct timespec diff;
+
+      diff.tv_sec = t[i].tv_sec - t[i + 1].tv_sec;
+      diff.tv_nsec = t[i].tv_nsec - t[i + 1].tv_nsec;
+      if (diff.tv_nsec < 0)
+	{
+	  diff.tv_nsec += 1000000000;
+	  --diff.tv_sec;
+	}
+
+      if (diff.tv_sec < 0 || (diff.tv_sec == 0 && diff.tv_nsec < 100000000))
+	{
+	  printf ("\
+difference between thread %d and %d too small (%ld.%09ld)\n",
+		  i, i + 1, (long int) diff.tv_sec, (long int) diff.tv_nsec);
+	  return 1;
+	}
+
+      printf ("diff %d->%d: %ld.%09ld\n",
+	      i, i + 1, (long int) diff.tv_sec, (long int) diff.tv_nsec);
+    }
+
+  ts.tv_sec = 0;
+  ts.tv_nsec = 0;
+  for (i = 0; i < N + 1; ++i)
+    if (clock_settime (cl[i], &ts) != 0)
+      {
+	printf ("clock_settime(%d) round %d failed\n", cl[i], i);
+	return 1;
+      }
+
+  for (i = 0; i < N + 1; ++i)
+    {
+      if (clock_gettime (cl[i], &ts) != 0)
+	{
+	  puts ("clock_gettime failed");
+	  return 1;
+	}
+
+      if (ts.tv_sec > t[i].tv_sec
+	  || (ts.tv_sec == t[i].tv_sec && ts.tv_nsec > t[i].tv_nsec))
+	{
+	  puts ("clock_settime didn't reset clock");
+	  return 1;
+	}
+    }
+#endif
+
+  return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-clock_nanosleep.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-clock_nanosleep.c
new file mode 100644
index 00000000..98a8b5f5
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-clock_nanosleep.c
@@ -0,0 +1,58 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+/* Test that clock_nanosleep() does sleep.  */
+static int
+do_test (void)
+{
+  /* Current time.  */
+  struct timeval tv1;
+  (void) gettimeofday (&tv1, NULL);
+
+  struct timespec ts;
+  ts.tv_sec = 1;
+  ts.tv_nsec = 0;
+  TEMP_FAILURE_RETRY (clock_nanosleep (CLOCK_REALTIME, 0, &ts, &ts));
+
+  /* At least one second must have passed.  */
+  struct timeval tv2;
+  (void) gettimeofday (&tv2, NULL);
+
+  tv2.tv_sec -= tv1.tv_sec;
+  tv2.tv_usec -= tv1.tv_usec;
+  if (tv2.tv_usec < 0)
+    --tv2.tv_sec;
+
+  if (tv2.tv_sec < 1)
+    {
+      puts ("clock_nanosleep didn't sleep long enough");
+      return 1;
+    }
+
+  return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond1.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond1.c
new file mode 100644
index 00000000..46085c2b
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond1.c
@@ -0,0 +1,94 @@
+/* Copyright (C) 2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2002.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+
+
+static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
+static pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
+
+
+static void *
+tf (void *p)
+{
+  int err;
+
+  err = pthread_mutex_lock (&mut);
+  if (err != 0)
+    error (EXIT_FAILURE, err, "child: cannot get mutex");
+
+  puts ("child: got mutex; signalling");
+
+  pthread_cond_signal (&cond);
+
+  puts ("child: unlock");
+
+  err = pthread_mutex_unlock (&mut);
+  if (err != 0)
+    error (EXIT_FAILURE, err, "child: cannot unlock");
+
+  puts ("child: done");
+
+  return NULL;
+}
+
+
+static int
+do_test (void)
+{
+  pthread_t th;
+  int err;
+
+  printf ("&cond = %p\n&mut = %p\n", &cond, &mut);
+
+  puts ("parent: get mutex");
+
+  err = pthread_mutex_lock (&mut);
+  if (err != 0)
+    error (EXIT_FAILURE, err, "parent: cannot get mutex");
+
+  puts ("parent: create child");
+
+  err = pthread_create (&th, NULL, tf, NULL);
+  if (err != 0)
+    error (EXIT_FAILURE, err, "parent: cannot create thread");
+
+  puts ("parent: wait for condition");
+
+  err = pthread_cond_wait (&cond, &mut);
+  if (err != 0)
+    error (EXIT_FAILURE, err, "parent: cannot wait fir signal");
+
+  puts ("parent: got signal");
+
+  err = pthread_join (th, NULL);
+  if (err != 0)
+    error (EXIT_FAILURE, err, "parent: failed to join");
+
+  puts ("done");
+
+  return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond10.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond10.c
new file mode 100644
index 00000000..34956d46
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond10.c
@@ -0,0 +1,173 @@
+/* Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+#define N 10
+#define ROUNDS 100
+
+static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
+static pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
+static pthread_barrier_t bN1;
+static pthread_barrier_t b2;
+
+
+static void *
+tf (void *p)
+{
+  if (pthread_mutex_lock (&mut) != 0)
+    {
+      puts ("child: 1st mutex_lock failed");
+      exit (1);
+    }
+
+  int e = pthread_barrier_wait (&b2);
+  if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("child: 1st barrier_wait failed");
+      exit (1);
+    }
+
+  if (pthread_cond_wait (&cond, &mut) != 0)
+    {
+      puts ("child: cond_wait failed");
+      exit (1);
+    }
+
+  if (pthread_mutex_unlock (&mut) != 0)
+    {
+      puts ("child: mutex_unlock failed");
+      exit (1);
+    }
+
+  e = pthread_barrier_wait (&bN1);
+  if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("child: 2nd barrier_wait failed");
+      exit (1);
+    }
+
+  return NULL;
+}
+
+
+static int
+do_test (void)
+{
+  if (pthread_barrier_init (&bN1, NULL, N + 1) != 0)
+    {
+      puts ("barrier_init failed");
+      exit (1);
+    }
+
+  if (pthread_barrier_init (&b2, NULL, 2) != 0)
+    {
+      puts ("barrier_init failed");
+      exit (1);
+    }
+
+  pthread_attr_t at;
+
+  if (pthread_attr_init (&at) != 0)
+    {
+      puts ("attr_init failed");
+      return 1;
+    }
+
+  if (pthread_attr_setstacksize (&at, 1 * 1024 * 1024) != 0)
+    {
+      puts ("attr_setstacksize failed");
+      return 1;
+    }
+
+  int r;
+  for (r = 0; r < ROUNDS; ++r)
+    {
+      printf ("round %d\n", r + 1);
+
+      int i;
+      pthread_t th[N];
+      for (i = 0; i < N; ++i)
+	{
+	  if (pthread_create (&th[i], &at, tf, NULL) != 0)
+	    {
+	      puts ("create failed");
+	      exit (1);
+	    }
+
+	  int e = pthread_barrier_wait (&b2);
+	  if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+	    {
+	      puts ("parent: 1st barrier_wait failed");
+	      exit (1);
+	    }
+	}
+
+      if (pthread_mutex_lock (&mut) != 0)
+	{
+	  puts ("parent: mutex_lock failed");
+	  exit (1);
+	}
+      if (pthread_mutex_unlock (&mut) != 0)
+	{
+	  puts ("parent: mutex_unlock failed");
+	  exit (1);
+	}
+
+      /* N single signal calls.  Without locking.  This tests that no
+	 signal gets lost.  */
+      for (i = 0; i < N; ++i)
+	if (pthread_cond_signal (&cond) != 0)
+	  {
+	    puts ("cond_signal failed");
+	    exit (1);
+	  }
+
+      int e = pthread_barrier_wait (&bN1);
+      if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+	{
+	  puts ("parent: 2nd barrier_wait failed");
+	  exit (1);
+	}
+
+      for (i = 0; i < N; ++i)
+	if (pthread_join (th[i], NULL) != 0)
+	  {
+	    puts ("join failed");
+	    exit (1);
+	  }
+    }
+
+  if (pthread_attr_destroy (&at) != 0)
+    {
+      puts ("attr_destroy failed");
+      return 1;
+    }
+
+  return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond11.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond11.c
new file mode 100644
index 00000000..0de4d561
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond11.c
@@ -0,0 +1,191 @@
+/* Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+#if defined _POSIX_CLOCK_SELECTION && _POSIX_CLOCK_SELECTION >= 0
+static int
+run_test (clockid_t cl)
+{
+  pthread_condattr_t condattr;
+  pthread_cond_t cond;
+  pthread_mutexattr_t mutattr;
+  pthread_mutex_t mut;
+
+  printf ("clock = %d\n", (int) cl);
+
+  if (pthread_condattr_init (&condattr) != 0)
+    {
+      puts ("condattr_init failed");
+      return 1;
+    }
+
+  if (pthread_condattr_setclock (&condattr, cl) != 0)
+    {
+      puts ("condattr_setclock failed");
+      return 1;
+    }
+
+  clockid_t cl2;
+  if (pthread_condattr_getclock (&condattr, &cl2) != 0)
+    {
+      puts ("condattr_getclock failed");
+      return 1;
+    }
+  if (cl != cl2)
+    {
+      printf ("condattr_getclock returned wrong value: %d, expected %d\n",
+	      (int) cl2, (int) cl);
+      return 1;
+    }
+
+  if (pthread_cond_init (&cond, &condattr) != 0)
+    {
+      puts ("cond_init failed");
+      return 1;
+    }
+
+  if (pthread_condattr_destroy (&condattr) != 0)
+    {
+      puts ("condattr_destroy failed");
+      return 1;
+    }
+
+  if (pthread_mutexattr_init (&mutattr) != 0)
+    {
+      puts ("mutexattr_init failed");
+      return 1;
+    }
+
+  if (pthread_mutexattr_settype (&mutattr, PTHREAD_MUTEX_ERRORCHECK) != 0)
+    {
+      puts ("mutexattr_settype failed");
+      return 1;
+    }
+
+  if (pthread_mutex_init (&mut, &mutattr) != 0)
+    {
+      puts ("mutex_init failed");
+      return 1;
+    }
+
+  if (pthread_mutexattr_destroy (&mutattr) != 0)
+    {
+      puts ("mutexattr_destroy failed");
+      return 1;
+    }
+
+  if (pthread_mutex_lock (&mut) != 0)
+    {
+      puts ("mutex_lock failed");
+      return 1;
+    }
+
+  if (pthread_mutex_lock (&mut) != EDEADLK)
+    {
+      puts ("2nd mutex_lock did not return EDEADLK");
+      return 1;
+    }
+
+  struct timespec ts;
+  if (clock_gettime (cl, &ts) != 0)
+    {
+      puts ("clock_gettime failed");
+      return 1;
+    }
+
+  /* Wait one second.  */
+  ++ts.tv_sec;
+
+  int e = pthread_cond_timedwait (&cond, &mut, &ts);
+  if (e == 0)
+    {
+      puts ("cond_timedwait succeeded");
+      return 1;
+    }
+  else if (e != ETIMEDOUT)
+    {
+      puts ("cond_timedwait did not return ETIMEDOUT");
+      return 1;
+    }
+
+  if (pthread_mutex_unlock (&mut) != 0)
+    {
+      puts ("mutex_unlock failed");
+      return 1;
+    }
+
+  if (pthread_mutex_destroy (&mut) != 0)
+    {
+      puts ("mutex_destroy failed");
+      return 1;
+    }
+
+  if (pthread_cond_destroy (&cond) != 0)
+    {
+      puts ("cond_destroy failed");
+      return 1;
+    }
+
+  return 0;
+}
+#endif
+
+
+static int
+do_test (void)
+{
+#if !defined _POSIX_CLOCK_SELECTION || _POSIX_CLOCK_SELECTION == -1
+
+  puts ("_POSIX_CLOCK_SELECTION not supported, test skipped");
+  return 0;
+
+#else
+
+  int res = run_test (CLOCK_REALTIME);
+
+# if defined _POSIX_MONOTONIC_CLOCK && _POSIX_MONOTONIC_CLOCK >= 0
+#  if _POSIX_MONOTONIC_CLOCK == 0
+  int e = sysconf (_SC_MONOTONIC_CLOCK);
+  if (e < 0)
+    puts ("CLOCK_MONOTONIC not supported");
+  else if (e == 0)
+    {
+      puts ("sysconf (_SC_MONOTONIC_CLOCK) must not return 0");
+      res = 1;
+    }
+  else
+#  endif
+    res |= run_test (CLOCK_MONOTONIC);
+# else
+  puts ("_POSIX_MONOTONIC_CLOCK not defined");
+# endif
+
+  return res;
+#endif
+}
+
+#define TIMEOUT 3
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond12.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond12.c
new file mode 100644
index 00000000..03e4881c
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond12.c
@@ -0,0 +1,196 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+static char fname[] = "/tmp/tst-cond12-XXXXXX";
+static int fd;
+
+
+static void prepare (void);
+#define PREPARE(argc, argv) prepare ()
+
+static int do_test (void);
+#define TEST_FUNCTION do_test ()
+
+#include "../test-skeleton.c"
+
+
+static void
+prepare (void)
+{
+  fd = mkstemp (fname);
+  if (fd == -1)
+    {
+      printf ("mkstemp failed: %m\n");
+      exit (1);
+    }
+  add_temp_file (fname);
+  if (ftruncate (fd, 1000) < 0)
+    {
+      printf ("ftruncate failed: %m\n");
+      exit (1);
+    }
+}
+
+
+static int
+do_test (void)
+{
+  struct
+  {
+    pthread_mutex_t m;
+    pthread_cond_t c;
+    int var;
+  } *p = mmap (NULL, sizeof (*p), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
+  if (p == MAP_FAILED)
+    {
+      printf ("initial mmap failed: %m\n");
+      return 1;
+    }
+
+  pthread_mutexattr_t ma;
+  if (pthread_mutexattr_init (&ma) != 0)
+    {
+      puts ("mutexattr_init failed");
+      return 1;
+    }
+  if (pthread_mutexattr_setpshared (&ma, 1) != 0)
+    {
+      puts ("mutexattr_setpshared failed");
+      return 1;
+    }
+  if (pthread_mutex_init (&p->m, &ma) != 0)
+    {
+      puts ("mutex_init failed");
+      return 1;
+    }
+  if (pthread_mutexattr_destroy (&ma) != 0)
+    {
+      puts ("mutexattr_destroy failed");
+      return 1;
+    }
+
+  pthread_condattr_t ca;
+  if (pthread_condattr_init (&ca) != 0)
+    {
+      puts ("condattr_init failed");
+      return 1;
+    }
+  if (pthread_condattr_setpshared (&ca, 1) != 0)
+    {
+      puts ("condattr_setpshared failed");
+      return 1;
+    }
+  if (pthread_cond_init (&p->c, &ca) != 0)
+    {
+      puts ("mutex_init failed");
+      return 1;
+    }
+  if (pthread_condattr_destroy (&ca) != 0)
+    {
+      puts ("condattr_destroy failed");
+      return 1;
+    }
+
+  if (pthread_mutex_lock (&p->m) != 0)
+    {
+      puts ("initial mutex_lock failed");
+      return 1;
+    }
+
+  p->var = 42;
+
+  pid_t pid = fork ();
+  if (pid == -1)
+    {
+      printf ("fork failed: %m\n");
+      return 1;
+    }
+
+  if (pid == 0)
+    {
+      void *oldp = p;
+      p = mmap (NULL, sizeof (*p), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
+
+      if (p == oldp)
+	{
+	  puts ("child: mapped to same address");
+	  kill (getppid (), SIGKILL);
+	  exit (1);
+	}
+
+      munmap (oldp, sizeof (*p));
+
+      if (pthread_mutex_lock (&p->m) != 0)
+	{
+	  puts ("child: mutex_lock failed");
+	  kill (getppid (), SIGKILL);
+	  exit (1);
+	}
+
+      p->var = 0;
+
+#ifndef USE_COND_SIGNAL
+      if (pthread_cond_broadcast (&p->c) != 0)
+	{
+	  puts ("child: cond_broadcast failed");
+	  kill (getppid (), SIGKILL);
+	  exit (1);
+	}
+#else
+      if (pthread_cond_signal (&p->c) != 0)
+	{
+	  puts ("child: cond_signal failed");
+	  kill (getppid (), SIGKILL);
+	  exit (1);
+	}
+#endif
+
+      if (pthread_mutex_unlock (&p->m) != 0)
+	{
+	  puts ("child: mutex_unlock failed");
+	  kill (getppid (), SIGKILL);
+	  exit (1);
+	}
+
+      exit (0);
+    }
+
+  do
+    pthread_cond_wait (&p->c, &p->m);
+  while (p->var != 0);
+
+  if (TEMP_FAILURE_RETRY (waitpid (pid, NULL, 0)) != pid)
+    {
+      printf ("waitpid failed: %m\n");
+      kill (pid, SIGKILL);
+      return 1;
+    }
+
+  return 0;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond13.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond13.c
new file mode 100644
index 00000000..29d79b53
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond13.c
@@ -0,0 +1,2 @@
+#define USE_COND_SIGNAL 1
+#include "tst-cond12.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond14.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond14.c
new file mode 100644
index 00000000..106fa8c2
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond14.c
@@ -0,0 +1,118 @@
+/* Copyright (C) 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2004.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
+static pthread_mutex_t mut = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
+static pthread_mutex_t mut2 = PTHREAD_MUTEX_INITIALIZER;
+
+static void *
+tf (void *p)
+{
+  if (pthread_mutex_lock (&mut) != 0)
+    {
+      printf ("%s: 1st mutex_lock failed\n", __func__);
+      exit (1);
+    }
+  if (pthread_mutex_lock (&mut) != 0)
+    {
+      printf ("%s: 2nd mutex_lock failed\n", __func__);
+      exit (1);
+    }
+  if (pthread_mutex_lock (&mut) != 0)
+    {
+      printf ("%s: 3rd mutex_lock failed\n", __func__);
+      exit (1);
+    }
+
+  if (pthread_mutex_unlock (&mut2) != 0)
+    {
+      printf ("%s: mutex_unlock failed\n", __func__);
+      exit (1);
+    }
+
+  if (pthread_cond_wait (&cond, &mut) != 0)
+    {
+      printf ("%s: cond_wait failed\n", __func__);
+      exit (1);
+    }
+
+  puts ("child: done");
+
+  return NULL;
+}
+
+
+static int
+do_test (void)
+{
+  if (pthread_mutex_lock (&mut2) != 0)
+    {
+      puts ("1st mutex_lock failed");
+      return 1;
+    }
+
+  puts ("parent: create child");
+
+  pthread_t th;
+  int err = pthread_create (&th, NULL, tf, NULL);
+  if (err != 0)
+    {
+      printf ("parent: cannot create thread: %s\n", strerror (err));
+      return 1;
+    }
+
+  /* We have to synchronize with the child.  */
+  if (pthread_mutex_lock (&mut2) != 0)
+    {
+      puts ("2nd mutex_lock failed");
+      return 1;
+    }
+
+  /* Give the child to reach to pthread_cond_wait.  */
+  sleep (1);
+
+  if (pthread_cond_signal (&cond) != 0)
+    {
+      puts ("cond_signal failed");
+      return 1;
+    }
+
+  err = pthread_join (th, NULL);
+  if (err != 0)
+    {
+      printf ("parent: failed to join: %s\n", strerror (err));
+      return 1;
+    }
+
+  puts ("done");
+
+  return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#define TIMEOUT 3
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond15.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond15.c
new file mode 100644
index 00000000..e815e253
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond15.c
@@ -0,0 +1,160 @@
+/* Copyright (C) 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2004.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
+static pthread_mutex_t mut = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
+static pthread_mutex_t mut2 = PTHREAD_MUTEX_INITIALIZER;
+
+static void *
+tf (void *p)
+{
+  if (pthread_mutex_lock (&mut) != 0)
+    {
+      printf ("%s: 1st mutex_lock failed\n", __func__);
+      exit (1);
+    }
+  if (pthread_mutex_lock (&mut) != 0)
+    {
+      printf ("%s: 2nd mutex_lock failed\n", __func__);
+      exit (1);
+    }
+  if (pthread_mutex_lock (&mut) != 0)
+    {
+      printf ("%s: 3rd mutex_lock failed\n", __func__);
+      exit (1);
+    }
+
+  if (pthread_mutex_unlock (&mut2) != 0)
+    {
+      printf ("%s: mutex_unlock failed\n", __func__);
+      exit (1);
+    }
+
+  struct timeval tv;
+  gettimeofday (&tv, NULL);
+  struct timespec ts;
+  TIMEVAL_TO_TIMESPEC (&tv, &ts);
+  ts.tv_sec += p == NULL ? 100 : 1;
+
+  int err = pthread_cond_timedwait (&cond, &mut, &ts);
+  if ((err != 0 && p == NULL) || (err != ETIMEDOUT && p != NULL))
+    {
+      printf ("%s: cond_wait failed\n", __func__);
+      exit (1);
+    }
+
+  if (pthread_mutex_unlock (&mut) != 0)
+    {
+      printf ("%s: 1st mutex_unlock failed\n", __func__);
+      exit (1);
+    }
+  if (pthread_mutex_unlock (&mut) != 0)
+    {
+      printf ("%s: 2nd mutex_unlock failed\n", __func__);
+      exit (1);
+    }
+  if (pthread_mutex_unlock (&mut) != 0)
+    {
+      printf ("%s: 3rd mutex_unlock failed\n", __func__);
+      exit (1);
+    }
+
+  puts ("child: done");
+
+  return NULL;
+}
+
+
+static int
+do_test (void)
+{
+  if (pthread_mutex_lock (&mut2) != 0)
+    {
+      puts ("1st mutex_lock failed");
+      return 1;
+    }
+
+  puts ("parent: create 1st child");
+
+  pthread_t th;
+  int err = pthread_create (&th, NULL, tf, NULL);
+  if (err != 0)
+    {
+      printf ("parent: cannot 1st create thread: %s\n", strerror (err));
+      return 1;
+    }
+
+  /* We have to synchronize with the child.  */
+  if (pthread_mutex_lock (&mut2) != 0)
+    {
+      puts ("2nd mutex_lock failed");
+      return 1;
+    }
+
+  /* Give the child to reach to pthread_cond_wait.  */
+  sleep (1);
+
+  if (pthread_cond_signal (&cond) != 0)
+    {
+      puts ("cond_signal failed");
+      return 1;
+    }
+
+  err = pthread_join (th, NULL);
+  if (err != 0)
+    {
+      printf ("parent: failed to join: %s\n", strerror (err));
+      return 1;
+    }
+
+
+  puts ("parent: create 2nd child");
+
+  err = pthread_create (&th, NULL, tf, (void *) 1l);
+  if (err != 0)
+    {
+      printf ("parent: cannot 2nd create thread: %s\n", strerror (err));
+      return 1;
+    }
+
+  err = pthread_join (th, NULL);
+  if (err != 0)
+    {
+      printf ("parent: failed to join: %s\n", strerror (err));
+      return 1;
+    }
+
+  puts ("done");
+
+  return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#define TIMEOUT 6
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond16.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond16.c
new file mode 100644
index 00000000..00c27ece
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond16.c
@@ -0,0 +1,105 @@
+/* Copyright (C) 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek , 2004.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+pthread_cond_t cv = PTHREAD_COND_INITIALIZER;
+pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
+bool n, exiting;
+FILE *f;
+int count;
+
+void *
+tf (void *dummy)
+{
+  bool loop = true;
+
+  while (loop)
+    {
+      pthread_mutex_lock (&lock);
+      while (n && !exiting)
+	pthread_cond_wait (&cv, &lock);
+      n = true;
+      pthread_mutex_unlock (&lock);
+
+      fputs (".", f);
+
+      pthread_mutex_lock (&lock);
+      n = false;
+      if (exiting)
+	loop = false;
+#ifdef UNLOCK_AFTER_BROADCAST
+      pthread_cond_broadcast (&cv);
+      pthread_mutex_unlock (&lock);
+#else
+      pthread_mutex_unlock (&lock);
+      pthread_cond_broadcast (&cv);
+#endif
+    }
+
+  return NULL;
+}
+
+int
+do_test (void)
+{
+  f = fopen ("/dev/null", "w");
+  if (f == NULL)
+    {
+      printf ("couldn't open /dev/null, %m\n");
+      return 1;
+    }
+
+  count = sysconf (_SC_NPROCESSORS_ONLN);
+  if (count <= 0)
+    count = 1;
+  count *= 4;
+
+  pthread_t th[count];
+  int i, ret;
+  for (i = 0; i < count; ++i)
+    if ((ret = pthread_create (&th[i], NULL, tf, NULL)) != 0)
+      {
+	errno = ret;
+	printf ("pthread_create %d failed: %m\n", i);
+	return 1;
+      }
+
+  struct timespec ts = { .tv_sec = 20, .tv_nsec = 0 };
+  while (nanosleep (&ts, &ts) != 0);
+
+  pthread_mutex_lock (&lock);
+  exiting = true;
+  pthread_mutex_unlock (&lock);
+
+  for (i = 0; i < count; ++i)
+    pthread_join (th[i], NULL);
+
+  fclose (f);
+  return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#define TIMEOUT 40
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond17.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond17.c
new file mode 100644
index 00000000..0586fa59
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond17.c
@@ -0,0 +1,2 @@
+#define UNLOCK_AFTER_BROADCAST 1
+#include "tst-cond16.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond18.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond18.c
new file mode 100644
index 00000000..9fd81d29
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond18.c
@@ -0,0 +1,117 @@
+/* Copyright (C) 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek , 2004.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+pthread_cond_t cv = PTHREAD_COND_INITIALIZER;
+pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
+bool exiting;
+int fd, count, spins, nn;
+
+void *
+tf (void *id)
+{
+  pthread_mutex_lock (&lock);
+
+  if ((long) id == 0)
+    {
+      while (!exiting)
+	{
+	  if ((spins++ % 1000) == 0)
+	    write (fd, ".", 1);
+	  pthread_mutex_unlock (&lock);
+
+	  pthread_mutex_lock (&lock);
+	  int njobs = rand () % (count + 1);
+	  nn = njobs;
+	  if ((rand () % 30) == 0)
+	    pthread_cond_broadcast (&cv);
+	  else
+	    while (njobs--)
+	      pthread_cond_signal (&cv);
+	}
+
+      pthread_cond_broadcast (&cv);
+    }
+  else
+    {
+      while (!exiting)
+	{
+	  while (!nn && !exiting)
+	    pthread_cond_wait (&cv, &lock);
+	  --nn;
+	  pthread_mutex_unlock (&lock);
+
+	  pthread_mutex_lock (&lock);
+	}
+    }
+
+  pthread_mutex_unlock (&lock);
+  return NULL;
+}
+
+int
+do_test (void)
+{
+  fd = open ("/dev/null", O_WRONLY);
+  if (fd < 0)
+    {
+      printf ("couldn't open /dev/null, %m\n");
+      return 1;
+    }
+
+  count = sysconf (_SC_NPROCESSORS_ONLN);
+  if (count <= 0)
+    count = 1;
+  count *= 8;
+
+  pthread_t th[count + 1];
+  int i, ret;
+
+  for (i = 0; i <= count; ++i)
+    if ((ret = pthread_create (&th[i], NULL, tf, (void *) (long) i)) != 0)
+      {
+	errno = ret;
+	printf ("pthread_create %d failed: %m\n", i);
+	return 1;
+      }
+
+  struct timespec ts = { .tv_sec = 20, .tv_nsec = 0 };
+  while (nanosleep (&ts, &ts) != 0);
+
+  pthread_mutex_lock (&lock);
+  exiting = true;
+  pthread_mutex_unlock (&lock);
+
+  for (i = 0; i < count; ++i)
+    pthread_join (th[i], NULL);
+
+  close (fd);
+  return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#define TIMEOUT 40
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond19.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond19.c
new file mode 100644
index 00000000..1c9bb7dd
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond19.c
@@ -0,0 +1,76 @@
+/* Copyright (C) 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2004.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
+static pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
+
+
+static int
+do_test (void)
+{
+  int result = 0;
+  struct timespec ts;
+
+  if (clock_gettime (CLOCK_REALTIME, &ts) != 0)
+    {
+      puts ("clock_gettime failed");
+      return 1;
+    }
+
+  ts.tv_nsec = -1;
+
+  int e = pthread_cond_timedwait (&cond, &mut, &ts);
+  if (e == 0)
+    {
+      puts ("first cond_timedwait did not fail");
+      result = 1;
+    }
+  else if (e != EINVAL)
+    {
+      puts ("first cond_timedwait did not return EINVAL");
+      result = 1;
+    }
+
+  ts.tv_nsec = 2000000000;
+
+  e = pthread_cond_timedwait (&cond, &mut, &ts);
+  if (e == 0)
+    {
+      puts ("second cond_timedwait did not fail");
+      result = 1;
+    }
+  else if (e != EINVAL)
+    {
+      puts ("second cond_timedwait did not return EINVAL");
+      result = 1;
+    }
+
+  return result;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond2.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond2.c
new file mode 100644
index 00000000..36f0f294
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond2.c
@@ -0,0 +1,163 @@
+/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2002.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+
+
+static pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
+
+static pthread_barrier_t bar;
+
+
+static void *
+tf (void *a)
+{
+  int i = (long int) a;
+  int err;
+
+  printf ("child %d: lock\n", i);
+
+  err = pthread_mutex_lock (&mut);
+  if (err != 0)
+    error (EXIT_FAILURE, err, "locking in child failed");
+
+  printf ("child %d: sync\n", i);
+
+  int e = pthread_barrier_wait (&bar);
+  if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("child: barrier_wait failed");
+      exit (1);
+    }
+
+  printf ("child %d: wait\n", i);
+
+  err = pthread_cond_wait (&cond, &mut);
+  if (err != 0)
+    error (EXIT_FAILURE, err, "child %d: failed to wait", i);
+
+  printf ("child %d: woken up\n", i);
+
+  err = pthread_mutex_unlock (&mut);
+  if (err != 0)
+    error (EXIT_FAILURE, err, "child %d: unlock[2] failed", i);
+
+  printf ("child %d: done\n", i);
+
+  return NULL;
+}
+
+
+#define N 10
+
+
+static int
+do_test (void)
+{
+  pthread_t th[N];
+  int i;
+  int err;
+
+  printf ("&cond = %p\n&mut = %p\n", &cond, &mut);
+
+  if (pthread_barrier_init (&bar, NULL, 2) != 0)
+    {
+      puts ("barrier_init failed");
+      exit (1);
+    }
+
+  pthread_attr_t at;
+
+  if (pthread_attr_init (&at) != 0)
+    {
+      puts ("attr_init failed");
+      return 1;
+    }
+
+  if (pthread_attr_setstacksize (&at, 1 * 1024 * 1024) != 0)
+    {
+      puts ("attr_setstacksize failed");
+      return 1;
+    }
+
+  for (i = 0; i < N; ++i)
+    {
+      printf ("create thread %d\n", i);
+
+      err = pthread_create (&th[i], &at, tf, (void *) (long int) i);
+      if (err != 0)
+	error (EXIT_FAILURE, err, "cannot create thread %d", i);
+
+      printf ("wait for child %d\n", i);
+
+      /* Wait for the child to start up and get the mutex for the
+	 conditional variable.  */
+      int e = pthread_barrier_wait (&bar);
+      if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+	{
+	  puts ("barrier_wait failed");
+	  exit (1);
+	}
+    }
+
+  if (pthread_attr_destroy (&at) != 0)
+    {
+      puts ("attr_destroy failed");
+      return 1;
+    }
+
+  puts ("get lock outselves");
+
+  err = pthread_mutex_lock (&mut);
+  if (err != 0)
+    error (EXIT_FAILURE, err, "mut locking failed");
+
+  puts ("broadcast");
+
+  /* Wake up all threads.  */
+  err = pthread_cond_broadcast (&cond);
+  if (err != 0)
+    error (EXIT_FAILURE, err, "parent: broadcast failed");
+
+  err = pthread_mutex_unlock (&mut);
+  if (err != 0)
+    error (EXIT_FAILURE, err, "mut unlocking failed");
+
+  /* Join all threads.  */
+  for (i = 0; i < N; ++i)
+    {
+      printf ("join thread %d\n", i);
+
+      err = pthread_join (th[i], NULL);
+      if (err != 0)
+	error (EXIT_FAILURE, err, "join of child %d failed", i);
+    }
+
+  puts ("done");
+
+  return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond20.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond20.c
new file mode 100644
index 00000000..18918f32
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond20.c
@@ -0,0 +1,170 @@
+/* Copyright (C) 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek , 2004.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define N 10
+#define ROUNDS 1000
+static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
+static pthread_cond_t cond2 = PTHREAD_COND_INITIALIZER;
+static pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
+static pthread_barrier_t b;
+static int count;
+
+static void *
+tf (void *p)
+{
+  int i;
+  for (i = 0; i < ROUNDS; ++i)
+    {
+      pthread_mutex_lock (&mut);
+
+      if (++count == N)
+	pthread_cond_signal (&cond2);
+
+#ifdef TIMED
+      struct timeval tv;
+      gettimeofday (&tv, NULL);
+      struct timespec ts;
+      /* Wait three seconds.  */
+      ts.tv_sec = tv.tv_sec + 3;
+      ts.tv_nsec = tv.tv_usec * 1000;
+      pthread_cond_timedwait (&cond, &mut, &ts);
+#else
+      pthread_cond_wait (&cond, &mut);
+#endif
+
+      pthread_mutex_unlock (&mut);
+
+      int err = pthread_barrier_wait (&b);
+      if (err != 0 && err != PTHREAD_BARRIER_SERIAL_THREAD)
+	{
+	  puts ("child: barrier_wait failed");
+	  exit (1);
+	}
+
+      err = pthread_barrier_wait (&b);
+      if (err != 0 && err != PTHREAD_BARRIER_SERIAL_THREAD)
+	{
+	  puts ("child: barrier_wait failed");
+	  exit (1);
+	}
+    }
+
+  return NULL;
+}
+
+
+static int
+do_test (void)
+{
+  if (pthread_barrier_init (&b, NULL, N + 1) != 0)
+    {
+      puts ("barrier_init failed");
+      return 1;
+    }
+
+  pthread_mutex_lock (&mut);
+
+  int i, j, err;
+  pthread_t th[N];
+  for (i = 0; i < N; ++i)
+    if ((err = pthread_create (&th[i], NULL, tf, NULL)) != 0)
+      {
+	printf ("cannot create thread %d: %s\n", i, strerror (err));
+	return 1;
+      }
+
+  for (i = 0; i < ROUNDS; ++i)
+    {
+      pthread_cond_wait (&cond2, &mut);
+
+      if (i & 1)
+        pthread_mutex_unlock (&mut);
+
+      if (i & 2)
+	pthread_cond_broadcast (&cond);
+      else if (i & 4)
+	for (j = 0; j < N; ++j)
+	  pthread_cond_signal (&cond);
+      else
+	{
+	  for (j = 0; j < (i / 8) % N; ++j)
+	    pthread_cond_signal (&cond);
+	  pthread_cond_broadcast (&cond);
+	}
+
+      if ((i & 1) == 0)
+        pthread_mutex_unlock (&mut);
+
+      err = pthread_cond_destroy (&cond);
+      if (err)
+	{
+	  printf ("pthread_cond_destroy failed: %s\n", strerror (err));
+	  return 1;
+	}
+
+      /* Now clobber the cond variable which has been successfully
+         destroyed above.  */
+      memset (&cond, (char) i, sizeof (cond));
+
+      err = pthread_barrier_wait (&b);
+      if (err != 0 && err != PTHREAD_BARRIER_SERIAL_THREAD)
+	{
+	  puts ("parent: barrier_wait failed");
+	  return 1;
+	}
+
+      pthread_mutex_lock (&mut);
+
+      err = pthread_barrier_wait (&b);
+      if (err != 0 && err != PTHREAD_BARRIER_SERIAL_THREAD)
+	{
+	  puts ("parent: barrier_wait failed");
+	  return 1;
+	}
+
+      count = 0;
+      err = pthread_cond_init (&cond, NULL);
+      if (err)
+	{
+	  printf ("pthread_cond_init failed: %s\n", strerror (err));
+	  return 1;
+	}
+    }
+
+  for (i = 0; i < N; ++i)
+    if ((err = pthread_join (th[i], NULL)) != 0)
+      {
+	printf ("failed to join thread %d: %s\n", i, strerror (err));
+	return 1;
+      }
+
+  puts ("done");
+
+  return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond21.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond21.c
new file mode 100644
index 00000000..89cb771b
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond21.c
@@ -0,0 +1,3 @@
+#include 
+#define TIMED 1
+#include "tst-cond20.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond22.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond22.c
new file mode 100644
index 00000000..bd978e50
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond22.c
@@ -0,0 +1,160 @@
+#include 
+#include 
+#include 
+
+
+static pthread_barrier_t b;
+static pthread_cond_t c = PTHREAD_COND_INITIALIZER;
+static pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
+
+
+static void
+cl (void *arg)
+{
+  pthread_mutex_unlock (&m);
+}
+
+
+static void *
+tf (void *arg)
+{
+  if (pthread_mutex_lock (&m) != 0)
+    {
+      printf ("%s: mutex_lock failed\n", __func__);
+      exit (1);
+    }
+  int e = pthread_barrier_wait (&b);
+  if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("%s: barrier_wait failed\n", __func__);
+      exit (1);
+    }
+  pthread_cleanup_push (cl, NULL);
+  /* We have to loop here because the cancellation might come after
+     the cond_wait call left the cancelable area and is then waiting
+     on the mutex.  In this case the beginning of the second cond_wait
+     call will cause the cancellation to happen.  */
+  do
+    if (pthread_cond_wait (&c, &m) != 0)
+      {
+	printf ("%s: cond_wait failed\n", __func__);
+	exit (1);
+      }
+  while (arg == NULL);
+  pthread_cleanup_pop (0);
+  if (pthread_mutex_unlock (&m) != 0)
+    {
+      printf ("%s: mutex_unlock failed\n", __func__);
+      exit (1);
+    }
+  return NULL;
+}
+
+
+static int
+do_test (void)
+{
+  int status = 0;
+
+  if (pthread_barrier_init (&b, NULL, 2) != 0)
+    {
+      puts ("barrier_init failed");
+      return 1;
+    }
+
+  pthread_t th;
+  if (pthread_create (&th, NULL, tf, NULL) != 0)
+    {
+      puts ("1st create failed");
+      return 1;
+    }
+  int e = pthread_barrier_wait (&b);
+  if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("1st barrier_wait failed");
+      return 1;
+    }
+  if (pthread_mutex_lock (&m) != 0)
+    {
+      puts ("1st mutex_lock failed");
+      return 1;
+    }
+  if (pthread_cond_signal (&c) != 0)
+    {
+      puts ("1st cond_signal failed");
+      return 1;
+    }
+  if (pthread_cancel (th) != 0)
+    {
+      puts ("cancel failed");
+      return 1;
+    }
+  if (pthread_mutex_unlock (&m) != 0)
+    {
+      puts ("1st mutex_unlock failed");
+      return 1;
+    }
+  void *res;
+  if (pthread_join (th, &res) != 0)
+    {
+      puts ("1st join failed");
+      return 1;
+    }
+  if (res != PTHREAD_CANCELED)
+    {
+      puts ("first thread not canceled");
+      status = 1;
+    }
+
+  printf ("cond = { %d, %x, %lld, %lld, %lld, %p, %u, %u }\n",
+	  c.__data.__lock, c.__data.__futex, c.__data.__total_seq,
+	  c.__data.__wakeup_seq, c.__data.__woken_seq, c.__data.__mutex,
+	  c.__data.__nwaiters, c.__data.__broadcast_seq);
+
+  if (pthread_create (&th, NULL, tf, (void *) 1l) != 0)
+    {
+      puts ("2nd create failed");
+      return 1;
+    }
+  e = pthread_barrier_wait (&b);
+  if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("2nd barrier_wait failed");
+      return 1;
+    }
+  if (pthread_mutex_lock (&m) != 0)
+    {
+      puts ("2nd mutex_lock failed");
+      return 1;
+    }
+  if (pthread_cond_signal (&c) != 0)
+    {
+      puts ("2nd cond_signal failed");
+      return 1;
+    }
+  if (pthread_mutex_unlock (&m) != 0)
+    {
+      puts ("2nd mutex_unlock failed");
+      return 1;
+    }
+  if (pthread_join (th, &res) != 0)
+    {
+      puts ("2nd join failed");
+      return 1;
+    }
+  if (res != NULL)
+    {
+      puts ("2nd thread canceled");
+      status = 1;
+    }
+
+  printf ("cond = { %d, %x, %lld, %lld, %lld, %p, %u, %u }\n",
+	  c.__data.__lock, c.__data.__futex, c.__data.__total_seq,
+	  c.__data.__wakeup_seq, c.__data.__woken_seq, c.__data.__mutex,
+	  c.__data.__nwaiters, c.__data.__broadcast_seq);
+
+  return status;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond23.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond23.c
new file mode 100644
index 00000000..254d821c
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond23.c
@@ -0,0 +1,184 @@
+/* Copyright (C) 2008 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek , 2008.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+#if defined _POSIX_CLOCK_SELECTION && _POSIX_CLOCK_SELECTION >= 0
+static int
+check (pthread_condattr_t *condattr, int pshared, clockid_t cl)
+{
+  clockid_t cl2;
+  if (pthread_condattr_getclock (condattr, &cl2) != 0)
+    {
+      puts ("condattr_getclock failed");
+      return 1;
+    }
+  if (cl != cl2)
+    {
+      printf ("condattr_getclock returned wrong value: %d, expected %d\n",
+	      (int) cl2, (int) cl);
+      return 1;
+    }
+
+  int p;
+  if (pthread_condattr_getpshared (condattr, &p) != 0)
+    {
+      puts ("condattr_getpshared failed");
+      return 1;
+    }
+  else if (p != pshared)
+    {
+      printf ("condattr_getpshared returned wrong value: %d, expected %d\n",
+	      p, pshared);
+      return 1;
+    }
+
+  return 0;
+}
+
+static int
+run_test (clockid_t cl)
+{
+  pthread_condattr_t condattr;
+
+  printf ("clock = %d\n", (int) cl);
+
+  if (pthread_condattr_init (&condattr) != 0)
+    {
+      puts ("condattr_init failed");
+      return 1;
+    }
+
+  if (check (&condattr, PTHREAD_PROCESS_PRIVATE, CLOCK_REALTIME))
+    return 1;
+
+  if (pthread_condattr_setpshared (&condattr, PTHREAD_PROCESS_SHARED) != 0)
+    {
+      puts ("1st condattr_setpshared failed");
+      return 1;
+    }
+
+  if (check (&condattr, PTHREAD_PROCESS_SHARED, CLOCK_REALTIME))
+    return 1;
+
+  if (pthread_condattr_setclock (&condattr, cl) != 0)
+    {
+      puts ("1st condattr_setclock failed");
+      return 1;
+    }
+
+  if (check (&condattr, PTHREAD_PROCESS_SHARED, cl))
+    return 1;
+
+  if (pthread_condattr_setpshared (&condattr, PTHREAD_PROCESS_PRIVATE) != 0)
+    {
+      puts ("2nd condattr_setpshared failed");
+      return 1;
+    }
+
+  if (check (&condattr, PTHREAD_PROCESS_PRIVATE, cl))
+    return 1;
+
+  if (pthread_condattr_setclock (&condattr, CLOCK_REALTIME) != 0)
+    {
+      puts ("2nd condattr_setclock failed");
+      return 1;
+    }
+
+  if (check (&condattr, PTHREAD_PROCESS_PRIVATE, CLOCK_REALTIME))
+    return 1;
+
+  if (pthread_condattr_setclock (&condattr, cl) != 0)
+    {
+      puts ("3rd condattr_setclock failed");
+      return 1;
+    }
+
+  if (check (&condattr, PTHREAD_PROCESS_PRIVATE, cl))
+    return 1;
+
+  if (pthread_condattr_setpshared (&condattr, PTHREAD_PROCESS_SHARED) != 0)
+    {
+      puts ("3rd condattr_setpshared failed");
+      return 1;
+    }
+
+  if (check (&condattr, PTHREAD_PROCESS_SHARED, cl))
+    return 1;
+
+  if (pthread_condattr_setclock (&condattr, CLOCK_REALTIME) != 0)
+    {
+      puts ("4th condattr_setclock failed");
+      return 1;
+    }
+
+  if (check (&condattr, PTHREAD_PROCESS_SHARED, CLOCK_REALTIME))
+    return 1;
+
+  if (pthread_condattr_destroy (&condattr) != 0)
+    {
+      puts ("condattr_destroy failed");
+      return 1;
+    }
+
+  return 0;
+}
+#endif
+
+
+static int
+do_test (void)
+{
+#if !defined _POSIX_CLOCK_SELECTION || _POSIX_CLOCK_SELECTION == -1
+
+  puts ("_POSIX_CLOCK_SELECTION not supported, test skipped");
+  return 0;
+
+#else
+
+  int res = run_test (CLOCK_REALTIME);
+
+# if defined _POSIX_MONOTONIC_CLOCK && _POSIX_MONOTONIC_CLOCK >= 0
+#  if _POSIX_MONOTONIC_CLOCK == 0
+  int e = sysconf (_SC_MONOTONIC_CLOCK);
+  if (e < 0)
+    puts ("CLOCK_MONOTONIC not supported");
+  else if (e == 0)
+    {
+      puts ("sysconf (_SC_MONOTONIC_CLOCK) must not return 0");
+      res = 1;
+    }
+  else
+#  endif
+    res |= run_test (CLOCK_MONOTONIC);
+# else
+  puts ("_POSIX_MONOTONIC_CLOCK not defined");
+# endif
+
+  return res;
+#endif
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond3.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond3.c
new file mode 100644
index 00000000..cb9eb855
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond3.c
@@ -0,0 +1,113 @@
+/* Copyright (C) 2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2002.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+/* Note that this test requires more than the standard.  It is
+   required that there are no spurious wakeups if only more readers
+   are added.  This is a reasonable demand.  */
+
+
+static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
+static pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
+
+
+#define N 10
+
+
+static void *
+tf (void *arg)
+{
+  int i = (long int) arg;
+  int err;
+
+  /* Get the mutex.  */
+  err = pthread_mutex_lock (&mut);
+  if (err != 0)
+    {
+      printf ("child %d mutex_lock failed: %s\n", i, strerror (err));
+      exit (1);
+    }
+
+  /* This call should never return.  */
+  pthread_cond_wait (&cond, &mut);
+
+  /* We should never get here.  */
+  exit (1);
+
+  return NULL;
+}
+
+
+static int
+do_test (void)
+{
+  int err;
+  int i;
+
+  for (i = 0; i < N; ++i)
+    {
+      pthread_t th;
+
+      if (i != 0)
+	{
+	  /* Release the mutex.  */
+	  err = pthread_mutex_unlock (&mut);
+	  if (err != 0)
+	    {
+	      printf ("mutex_unlock %d failed: %s\n", i, strerror (err));
+	      return 1;
+	    }
+	}
+
+      err = pthread_create (&th, NULL, tf, (void *) (long int) i);
+      if (err != 0)
+	{
+	  printf ("create %d failed: %s\n", i, strerror (err));
+	  return 1;
+	}
+
+      /* Get the mutex.  */
+      err = pthread_mutex_lock (&mut);
+      if (err != 0)
+	{
+	  printf ("mutex_lock %d failed: %s\n", i, strerror (err));
+	  return 1;
+	}
+    }
+
+  /* Set an alarm for 1 second.  The wrapper will expect this.  */
+  alarm (1);
+
+  /* This call should never return.  */
+  pthread_cond_wait (&cond, &mut);
+
+  puts ("cond_wait returned");
+  return 1;
+}
+
+
+#define EXPECTED_SIGNAL SIGALRM
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond4.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond4.c
new file mode 100644
index 00000000..4d885961
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond4.c
@@ -0,0 +1,264 @@
+/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2002.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+int *condition;
+
+static int
+do_test (void)
+{
+  size_t ps = sysconf (_SC_PAGESIZE);
+  char tmpfname[] = "/tmp/tst-cond4.XXXXXX";
+  char data[ps];
+  void *mem;
+  int fd;
+  pthread_mutexattr_t ma;
+  pthread_mutex_t *mut1;
+  pthread_mutex_t *mut2;
+  pthread_condattr_t ca;
+  pthread_cond_t *cond;
+  pid_t pid;
+  int result = 0;
+  int p;
+
+  fd = mkstemp (tmpfname);
+  if (fd == -1)
+    {
+      printf ("cannot open temporary file: %m\n");
+      return 1;
+    }
+
+  /* Make sure it is always removed.  */
+  unlink (tmpfname);
+
+  /* Create one page of data.  */
+  memset (data, '\0', ps);
+
+  /* Write the data to the file.  */
+  if (write (fd, data, ps) != (ssize_t) ps)
+    {
+      puts ("short write");
+      return 1;
+    }
+
+  mem = mmap (NULL, ps, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+  if (mem == MAP_FAILED)
+    {
+      printf ("mmap failed: %m\n");
+      return 1;
+    }
+
+  mut1 = (pthread_mutex_t *) (((uintptr_t) mem
+			       + __alignof (pthread_mutex_t))
+			      & ~(__alignof (pthread_mutex_t) - 1));
+  mut2 = mut1 + 1;
+
+  cond = (pthread_cond_t *) (((uintptr_t) (mut2 + 1)
+			      + __alignof (pthread_cond_t))
+			     & ~(__alignof (pthread_cond_t) - 1));
+
+  condition = (int *) (((uintptr_t) (cond + 1) + __alignof (int))
+		       & ~(__alignof (int) - 1));
+
+  if (pthread_mutexattr_init (&ma) != 0)
+    {
+      puts ("mutexattr_init failed");
+      return 1;
+    }
+
+  if (pthread_mutexattr_getpshared (&ma, &p) != 0)
+    {
+      puts ("1st mutexattr_getpshared failed");
+      return 1;
+    }
+
+  if (p != PTHREAD_PROCESS_PRIVATE)
+    {
+      puts ("default pshared value wrong");
+      return 1;
+    }
+
+  if (pthread_mutexattr_setpshared (&ma, PTHREAD_PROCESS_SHARED) != 0)
+    {
+      puts ("mutexattr_setpshared failed");
+      return 1;
+    }
+
+  if (pthread_mutexattr_getpshared (&ma, &p) != 0)
+    {
+      puts ("2nd mutexattr_getpshared failed");
+      return 1;
+    }
+
+  if (p != PTHREAD_PROCESS_SHARED)
+    {
+      puts ("pshared value after setpshared call wrong");
+      return 1;
+    }
+
+  if (pthread_mutex_init (mut1, &ma) != 0)
+    {
+      puts ("1st mutex_init failed");
+      return 1;
+    }
+
+  if (pthread_mutex_init (mut2, &ma) != 0)
+    {
+      puts ("2nd mutex_init failed");
+      return 1;
+    }
+
+  if (pthread_condattr_init (&ca) != 0)
+    {
+      puts ("condattr_init failed");
+      return 1;
+    }
+
+  if (pthread_condattr_getpshared (&ca, &p) != 0)
+    {
+      puts ("1st condattr_getpshared failed");
+      return 1;
+    }
+
+  if (p != PTHREAD_PROCESS_PRIVATE)
+    {
+      puts ("default value for pshared in condattr wrong");
+      return 1;
+    }
+
+  if (pthread_condattr_setpshared (&ca, PTHREAD_PROCESS_SHARED) != 0)
+    {
+      puts ("condattr_setpshared failed");
+      return 1;
+    }
+
+  if (pthread_condattr_getpshared (&ca, &p) != 0)
+    {
+      puts ("2nd condattr_getpshared failed");
+      return 1;
+    }
+
+  if (p != PTHREAD_PROCESS_SHARED)
+    {
+      puts ("pshared condattr still not set");
+      return 1;
+    }
+
+  if (pthread_cond_init (cond, &ca) != 0)
+    {
+      puts ("cond_init failed");
+      return 1;
+    }
+
+  if (pthread_mutex_lock (mut1) != 0)
+    {
+      puts ("parent: 1st mutex_lock failed");
+      return 1;
+    }
+
+  puts ("going to fork now");
+  pid = fork ();
+  if (pid == -1)
+    {
+      puts ("fork failed");
+      return 1;
+    }
+  else if (pid == 0)
+    {
+      if (pthread_mutex_lock (mut2) != 0)
+	{
+	  puts ("child: mutex_lock failed");
+	  return 1;
+	}
+
+      if (pthread_mutex_unlock (mut1) != 0)
+	{
+	  puts ("child: 1st mutex_unlock failed");
+	  return 1;
+	}
+
+      do
+	if (pthread_cond_wait (cond, mut2) != 0)
+	  {
+	    puts ("child: cond_wait failed");
+	    return 1;
+	  }
+      while (*condition == 0);
+
+      if (pthread_mutex_unlock (mut2) != 0)
+	{
+	  puts ("child: 2nd mutex_unlock failed");
+	  return 1;
+	}
+
+      puts ("child done");
+    }
+  else
+    {
+      int status;
+
+      if (pthread_mutex_lock (mut1) != 0)
+	{
+	  puts ("parent: 2nd mutex_lock failed");
+	  return 1;
+	}
+
+      if (pthread_mutex_lock (mut2) != 0)
+	{
+	  puts ("parent: 3rd mutex_lock failed");
+	  return 1;
+	}
+
+      if (pthread_cond_signal (cond) != 0)
+	{
+	  puts ("parent: cond_signal failed");
+	  return 1;
+	}
+
+      *condition = 1;
+
+      if (pthread_mutex_unlock (mut2) != 0)
+	{
+	  puts ("parent: mutex_unlock failed");
+	  return 1;
+	}
+
+      puts ("waiting for child");
+
+      waitpid (pid, &status, 0);
+      result |= status;
+
+      puts ("parent done");
+    }
+
+ return result;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond5.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond5.c
new file mode 100644
index 00000000..efa207b5
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond5.c
@@ -0,0 +1,106 @@
+/* Copyright (C) 2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2002.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+static pthread_mutex_t mut;
+static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
+
+
+static int
+do_test (void)
+{
+  pthread_mutexattr_t ma;
+  int err;
+  struct timespec ts;
+  struct timeval tv;
+
+  if (pthread_mutexattr_init (&ma) != 0)
+    {
+      puts ("mutexattr_init failed");
+      exit (1);
+    }
+
+  if (pthread_mutexattr_settype (&ma, PTHREAD_MUTEX_ERRORCHECK) != 0)
+    {
+      puts ("mutexattr_settype failed");
+      exit (1);
+    }
+
+  if (pthread_mutex_init (&mut, &ma) != 0)
+    {
+      puts ("mutex_init failed");
+      exit (1);
+    }
+
+  /* Get the mutex.  */
+  if (pthread_mutex_lock (&mut) != 0)
+    {
+      puts ("mutex_lock failed");
+      exit (1);
+    }
+
+  /* Waiting for the condition will fail.  But we want the timeout here.  */
+  if (gettimeofday (&tv, NULL) != 0)
+    {
+      puts ("gettimeofday failed");
+      exit (1);
+    }
+
+  TIMEVAL_TO_TIMESPEC (&tv, &ts);
+  ts.tv_nsec += 500000000;
+  if (ts.tv_nsec >= 1000000000)
+    {
+      ts.tv_nsec -= 1000000000;
+      ++ts.tv_sec;
+    }
+  err = pthread_cond_timedwait (&cond, &mut, &ts);
+  if (err == 0)
+    {
+      /* This could in theory happen but here without any signal and
+	 additional waiter it should not.  */
+      puts ("cond_timedwait succeeded");
+      exit (1);
+    }
+  else if (err != ETIMEDOUT)
+    {
+      printf ("cond_timedwait returned with %s\n", strerror (err));
+      exit (1);
+    }
+
+  err = pthread_mutex_unlock (&mut);
+  if (err != 0)
+    {
+      printf ("mutex_unlock failed: %s\n", strerror (err));
+      exit (1);
+    }
+
+  return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond6.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond6.c
new file mode 100644
index 00000000..8c5fe209
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond6.c
@@ -0,0 +1,234 @@
+/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2002.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+int *condition;
+
+static int
+do_test (void)
+{
+  size_t ps = sysconf (_SC_PAGESIZE);
+  char tmpfname[] = "/tmp/tst-cond6.XXXXXX";
+  char data[ps];
+  void *mem;
+  int fd;
+  pthread_mutexattr_t ma;
+  pthread_mutex_t *mut1;
+  pthread_mutex_t *mut2;
+  pthread_condattr_t ca;
+  pthread_cond_t *cond;
+  pid_t pid;
+  int result = 0;
+
+  fd = mkstemp (tmpfname);
+  if (fd == -1)
+    {
+      printf ("cannot open temporary file: %m\n");
+      exit (1);
+    }
+
+  /* Make sure it is always removed.  */
+  unlink (tmpfname);
+
+  /* Create one page of data.  */
+  memset (data, '\0', ps);
+
+  /* Write the data to the file.  */
+  if (write (fd, data, ps) != (ssize_t) ps)
+    {
+      puts ("short write");
+      exit (1);
+    }
+
+  mem = mmap (NULL, ps, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+  if (mem == MAP_FAILED)
+    {
+      printf ("mmap failed: %m\n");
+      exit (1);
+    }
+
+  mut1 = (pthread_mutex_t *) (((uintptr_t) mem
+			       + __alignof (pthread_mutex_t))
+			      & ~(__alignof (pthread_mutex_t) - 1));
+  mut2 = mut1 + 1;
+
+  cond = (pthread_cond_t *) (((uintptr_t) (mut2 + 1)
+			      + __alignof (pthread_cond_t))
+			     & ~(__alignof (pthread_cond_t) - 1));
+
+  condition = (int *) (((uintptr_t) (cond + 1) + __alignof (int))
+		       & ~(__alignof (int) - 1));
+
+  if (pthread_mutexattr_init (&ma) != 0)
+    {
+      puts ("mutexattr_init failed");
+      exit (1);
+    }
+
+  if (pthread_mutexattr_setpshared (&ma, PTHREAD_PROCESS_SHARED) != 0)
+    {
+      puts ("mutexattr_setpshared failed");
+      exit (1);
+    }
+
+  if (pthread_mutex_init (mut1, &ma) != 0)
+    {
+      puts ("1st mutex_init failed");
+      exit (1);
+    }
+
+  if (pthread_mutex_init (mut2, &ma) != 0)
+    {
+      puts ("2nd mutex_init failed");
+      exit (1);
+    }
+
+  if (pthread_condattr_init (&ca) != 0)
+    {
+      puts ("condattr_init failed");
+      exit (1);
+    }
+
+  if (pthread_condattr_setpshared (&ca, PTHREAD_PROCESS_SHARED) != 0)
+    {
+      puts ("condattr_setpshared failed");
+      exit (1);
+    }
+
+  if (pthread_cond_init (cond, &ca) != 0)
+    {
+      puts ("cond_init failed");
+      exit (1);
+    }
+
+  if (pthread_mutex_lock (mut1) != 0)
+    {
+      puts ("parent: 1st mutex_lock failed");
+      exit (1);
+    }
+
+  puts ("going to fork now");
+  pid = fork ();
+  if (pid == -1)
+    {
+      puts ("fork failed");
+      exit (1);
+    }
+  else if (pid == 0)
+    {
+      struct timespec ts;
+      struct timeval tv;
+
+      if (pthread_mutex_lock (mut2) != 0)
+	{
+	  puts ("child: mutex_lock failed");
+	  exit (1);
+	}
+
+      if (pthread_mutex_unlock (mut1) != 0)
+	{
+	  puts ("child: 1st mutex_unlock failed");
+	  exit (1);
+	}
+
+      if (gettimeofday (&tv, NULL) != 0)
+	{
+	  puts ("gettimeofday failed");
+	  exit (1);
+	}
+
+      TIMEVAL_TO_TIMESPEC (&tv, &ts);
+      ts.tv_nsec += 500000000;
+      if (ts.tv_nsec >= 1000000000)
+	{
+	  ts.tv_nsec -= 1000000000;
+	  ++ts.tv_sec;
+	}
+
+      do
+	if (pthread_cond_timedwait (cond, mut2, &ts) != 0)
+	  {
+	    puts ("child: cond_wait failed");
+	    exit (1);
+	  }
+      while (*condition == 0);
+
+      if (pthread_mutex_unlock (mut2) != 0)
+	{
+	  puts ("child: 2nd mutex_unlock failed");
+	  exit (1);
+	}
+
+      puts ("child done");
+    }
+  else
+    {
+      int status;
+
+      if (pthread_mutex_lock (mut1) != 0)
+	{
+	  puts ("parent: 2nd mutex_lock failed");
+	  exit (1);
+	}
+
+      if (pthread_mutex_lock (mut2) != 0)
+	{
+	  puts ("parent: 3rd mutex_lock failed");
+	  exit (1);
+	}
+
+      if (pthread_cond_signal (cond) != 0)
+	{
+	  puts ("parent: cond_signal failed");
+	  exit (1);
+	}
+
+      *condition = 1;
+
+      if (pthread_mutex_unlock (mut2) != 0)
+	{
+	  puts ("parent: mutex_unlock failed");
+	  exit (1);
+	}
+
+      puts ("waiting for child");
+
+      waitpid (pid, &status, 0);
+      result |= status;
+
+      puts ("parent done");
+    }
+
+ return result;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond7.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond7.c
new file mode 100644
index 00000000..5ab7b8f8
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond7.c
@@ -0,0 +1,168 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek , 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+typedef struct
+  {
+    pthread_cond_t cond;
+    pthread_mutex_t lock;
+    pthread_t h;
+  } T;
+
+
+static volatile bool done;
+
+
+static void *
+tf (void *arg)
+{
+  puts ("child created");
+
+  if (pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, NULL) != 0
+      || pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, NULL) != 0)
+    {
+      puts ("cannot set cancellation options");
+      exit (1);
+    }
+
+  T *t = (T *) arg;
+
+  if (pthread_mutex_lock (&t->lock) != 0)
+    {
+      puts ("child: lock failed");
+      exit (1);
+    }
+
+  done = true;
+
+  if (pthread_cond_signal (&t->cond) != 0)
+    {
+      puts ("child: cond_signal failed");
+      exit (1);
+    }
+
+  if (pthread_cond_wait (&t->cond, &t->lock) != 0)
+    {
+      puts ("child: cond_wait failed");
+      exit (1);
+    }
+
+  if (pthread_mutex_unlock (&t->lock) != 0)
+    {
+      puts ("child: unlock failed");
+      exit (1);
+    }
+
+  return NULL;
+}
+
+
+static int
+do_test (void)
+{
+  int i;
+#define N 100
+  T *t[N];
+  for (i = 0; i < N; ++i)
+    {
+      printf ("round %d\n", i);
+
+      t[i] = (T *) malloc (sizeof (T));
+      if (t[i] == NULL)
+	{
+	  puts ("out of memory");
+	  exit (1);
+	}
+
+      if (pthread_mutex_init (&t[i]->lock, NULL) != 0
+	  || pthread_cond_init (&t[i]->cond, NULL) != 0)
+	{
+	  puts ("an _init function failed");
+	  exit (1);
+	}
+
+      if (pthread_mutex_lock (&t[i]->lock) != 0)
+	{
+	  puts ("initial mutex_lock failed");
+	  exit (1);
+	}
+
+      done = false;
+
+      if (pthread_create (&t[i]->h, NULL, tf, t[i]) != 0)
+	{
+	  puts ("pthread_create failed");
+	  exit (1);
+	}
+
+      do
+	if (pthread_cond_wait (&t[i]->cond, &t[i]->lock) != 0)
+	  {
+	    puts ("cond_wait failed");
+	    exit (1);
+	  }
+      while (! done);
+
+      /* Release the lock since the cancel handler will get it.  */
+      if (pthread_mutex_unlock (&t[i]->lock) != 0)
+	{
+	  puts ("mutex_unlock failed");
+	  exit (1);
+	}
+
+      if (pthread_cancel (t[i]->h) != 0)
+	{
+	  puts ("cancel failed");
+	  exit (1);
+	}
+
+      puts ("parent: joining now");
+
+      void *result;
+      if (pthread_join (t[i]->h, &result) != 0)
+	{
+	  puts ("join failed");
+	  exit (1);
+	}
+
+      if (result != PTHREAD_CANCELED)
+	{
+	  puts ("result != PTHREAD_CANCELED");
+	  exit (1);
+	}
+    }
+
+  for (i = 0; i < N; ++i)
+    free (t[i]);
+
+  return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond8.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond8.c
new file mode 100644
index 00000000..9c97a96f
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond8.c
@@ -0,0 +1,277 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
+static pthread_mutex_t mut = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;
+
+static pthread_barrier_t bar;
+
+
+static void
+ch (void *arg)
+{
+  int e = pthread_mutex_lock (&mut);
+  if (e == 0)
+    {
+      puts ("mutex not locked at all by cond_wait");
+      exit (1);
+    }
+
+  if (e != EDEADLK)
+    {
+      puts ("no deadlock error signaled");
+      exit (1);
+    }
+
+  if (pthread_mutex_unlock (&mut) != 0)
+    {
+      puts ("ch: cannot unlock mutex");
+      exit (1);
+    }
+
+  puts ("ch done");
+}
+
+
+static void *
+tf1 (void *p)
+{
+  int err;
+
+  if (pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, NULL) != 0
+      || pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, NULL) != 0)
+    {
+      puts ("cannot set cancellation options");
+      exit (1);
+    }
+
+  err = pthread_mutex_lock (&mut);
+  if (err != 0)
+    {
+      puts ("child: cannot get mutex");
+      exit (1);
+    }
+
+  err = pthread_barrier_wait (&bar);
+  if (err != 0 && err != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("barrier_wait returned %d\n", err);
+      exit (1);
+    }
+
+  puts ("child: got mutex; waiting");
+
+  pthread_cleanup_push (ch, NULL);
+
+  pthread_cond_wait (&cond, &mut);
+
+  pthread_cleanup_pop (0);
+
+  puts ("child: cond_wait should not have returned");
+
+  return NULL;
+}
+
+
+static void *
+tf2 (void *p)
+{
+  int err;
+
+  if (pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, NULL) != 0
+      || pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, NULL) != 0)
+    {
+      puts ("cannot set cancellation options");
+      exit (1);
+    }
+
+  err = pthread_mutex_lock (&mut);
+  if (err != 0)
+    {
+      puts ("child: cannot get mutex");
+      exit (1);
+    }
+
+  err = pthread_barrier_wait (&bar);
+  if (err != 0 && err != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      printf ("barrier_wait returned %d\n", err);
+      exit (1);
+    }
+
+  puts ("child: got mutex; waiting");
+
+  pthread_cleanup_push (ch, NULL);
+
+  /* Current time.  */
+  struct timeval tv;
+  (void) gettimeofday (&tv, NULL);
+  /* +1000 seconds in correct format.  */
+  struct timespec ts;
+  TIMEVAL_TO_TIMESPEC (&tv, &ts);
+  ts.tv_sec += 1000;
+
+  pthread_cond_timedwait (&cond, &mut, &ts);
+
+  pthread_cleanup_pop (0);
+
+  puts ("child: cond_wait should not have returned");
+
+  return NULL;
+}
+
+
+static int
+do_test (void)
+{
+  pthread_t th;
+  int err;
+
+  printf ("&cond = %p\n&mut = %p\n", &cond, &mut);
+
+  puts ("parent: get mutex");
+
+  err = pthread_barrier_init (&bar, NULL, 2);
+  if (err != 0)
+    {
+      puts ("parent: cannot init barrier");
+      exit (1);
+    }
+
+  puts ("parent: create child");
+
+  err = pthread_create (&th, NULL, tf1, NULL);
+  if (err != 0)
+    {
+      puts ("parent: cannot create thread");
+      exit (1);
+    }
+
+  puts ("parent: wait for child to lock mutex");
+
+  err = pthread_barrier_wait (&bar);
+  if (err != 0 && err != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("parent: cannot wait for barrier");
+      exit (1);
+    }
+
+  err = pthread_mutex_lock (&mut);
+  if (err != 0)
+    {
+      puts ("parent: mutex_lock failed");
+      exit (1);
+    }
+
+  err = pthread_mutex_unlock (&mut);
+  if (err != 0)
+    {
+      puts ("parent: mutex_unlock failed");
+      exit (1);
+    }
+
+  if (pthread_cancel (th) != 0)
+    {
+      puts ("cannot cancel thread");
+      exit (1);
+    }
+
+  void *r;
+  err = pthread_join (th, &r);
+  if (err != 0)
+    {
+      puts ("parent: failed to join");
+      exit (1);
+    }
+
+  if (r != PTHREAD_CANCELED)
+    {
+      puts ("child hasn't been canceled");
+      exit (1);
+    }
+
+
+
+  puts ("parent: create 2nd child");
+
+  err = pthread_create (&th, NULL, tf2, NULL);
+  if (err != 0)
+    {
+      puts ("parent: cannot create thread");
+      exit (1);
+    }
+
+  puts ("parent: wait for child to lock mutex");
+
+  err = pthread_barrier_wait (&bar);
+  if (err != 0 && err != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("parent: cannot wait for barrier");
+      exit (1);
+    }
+
+  err = pthread_mutex_lock (&mut);
+  if (err != 0)
+    {
+      puts ("parent: mutex_lock failed");
+      exit (1);
+    }
+
+  err = pthread_mutex_unlock (&mut);
+  if (err != 0)
+    {
+      puts ("parent: mutex_unlock failed");
+      exit (1);
+    }
+
+  if (pthread_cancel (th) != 0)
+    {
+      puts ("cannot cancel thread");
+      exit (1);
+    }
+
+  err = pthread_join (th, &r);
+  if (err != 0)
+    {
+      puts ("parent: failed to join");
+      exit (1);
+    }
+
+  if (r != PTHREAD_CANCELED)
+    {
+      puts ("child hasn't been canceled");
+      exit (1);
+    }
+
+  puts ("done");
+
+  return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond9.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond9.c
new file mode 100644
index 00000000..2a8477dd
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cond9.c
@@ -0,0 +1,150 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
+static pthread_mutex_t mut = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;
+
+
+static void *
+tf (void *arg)
+{
+  int err = pthread_cond_wait (&cond, &mut);
+  if (err == 0)
+    {
+      puts ("cond_wait did not fail");
+      exit (1);
+    }
+
+  if (err != EPERM)
+    {
+      printf ("cond_wait didn't return EPERM but %d\n", err);
+      exit (1);
+    }
+
+
+  /* Current time.  */
+  struct timeval tv;
+  (void) gettimeofday (&tv, NULL);
+  /* +1000 seconds in correct format.  */
+  struct timespec ts;
+  TIMEVAL_TO_TIMESPEC (&tv, &ts);
+  ts.tv_sec += 1000;
+
+  err = pthread_cond_timedwait (&cond, &mut, &ts);
+  if (err == 0)
+    {
+      puts ("cond_timedwait did not fail");
+      exit (1);
+    }
+
+  if (err != EPERM)
+    {
+      printf ("cond_timedwait didn't return EPERM but %d\n", err);
+      exit (1);
+    }
+
+  return (void *) 1l;
+}
+
+
+static int
+do_test (void)
+{
+  pthread_t th;
+  int err;
+
+  printf ("&cond = %p\n&mut = %p\n", &cond, &mut);
+
+  err = pthread_cond_wait (&cond, &mut);
+  if (err == 0)
+    {
+      puts ("cond_wait did not fail");
+      exit (1);
+    }
+
+  if (err != EPERM)
+    {
+      printf ("cond_wait didn't return EPERM but %d\n", err);
+      exit (1);
+    }
+
+
+  /* Current time.  */
+  struct timeval tv;
+  (void) gettimeofday (&tv, NULL);
+  /* +1000 seconds in correct format.  */
+  struct timespec ts;
+  TIMEVAL_TO_TIMESPEC (&tv, &ts);
+  ts.tv_sec += 1000;
+
+  err = pthread_cond_timedwait (&cond, &mut, &ts);
+  if (err == 0)
+    {
+      puts ("cond_timedwait did not fail");
+      exit (1);
+    }
+
+  if (err != EPERM)
+    {
+      printf ("cond_timedwait didn't return EPERM but %d\n", err);
+      exit (1);
+    }
+
+  if (pthread_mutex_lock (&mut) != 0)
+    {
+      puts ("parent: mutex_lock failed");
+      exit (1);
+    }
+
+  puts ("creating thread");
+
+  if (pthread_create (&th, NULL, tf, NULL) != 0)
+    {
+      puts ("create failed");
+      exit (1);
+    }
+
+  void *r;
+  if (pthread_join (th, &r) != 0)
+    {
+      puts ("join failed");
+      exit (1);
+    }
+  if (r != (void *) 1l)
+    {
+      puts ("thread has wrong return value");
+      exit (1);
+    }
+
+  puts ("done");
+
+  return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cpuclock1.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cpuclock1.c
new file mode 100644
index 00000000..024df631
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cpuclock1.c
@@ -0,0 +1,307 @@
+/* Test program for process CPU clocks.
+   Copyright (C) 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/* This function is intended to rack up both user and system time.  */
+static void
+chew_cpu (void)
+{
+  while (1)
+    {
+      static volatile char buf[4096];
+      for (int i = 0; i < 100; ++i)
+	for (size_t j = 0; j < sizeof buf; ++j)
+	  buf[j] = 0xaa;
+      int nullfd = open ("/dev/null", O_WRONLY);
+      for (int i = 0; i < 100; ++i)
+	for (size_t j = 0; j < sizeof buf; ++j)
+	  buf[j] = 0xbb;
+      write (nullfd, (char *) buf, sizeof buf);
+      close (nullfd);
+      if (getppid () == 1)
+	_exit (2);
+    }
+}
+
+static int
+do_test (void)
+{
+  int result = 0;
+  clockid_t cl;
+  int e;
+  pid_t dead_child, child;
+
+  /* Fork a child and let it die, to give us a PID known not be valid
+     (assuming PIDs don't wrap around during the test).  */
+  {
+    dead_child = fork ();
+    if (dead_child == 0)
+      _exit (0);
+    if (dead_child < 0)
+      {
+	perror ("fork");
+	return 1;
+      }
+    int x;
+    if (wait (&x) != dead_child)
+      {
+	perror ("wait");
+	return 2;
+      }
+  }
+
+  /* POSIX says we should get ESRCH for this.  */
+  e = clock_getcpuclockid (dead_child, &cl);
+  if (e != ENOSYS && e != ESRCH && e != EPERM)
+    {
+      printf ("clock_getcpuclockid on dead PID %d => %s\n",
+	      dead_child, strerror (e));
+      result = 1;
+    }
+
+  /* Now give us a live child eating up CPU time.  */
+  child = fork ();
+  if (child == 0)
+    {
+      chew_cpu ();
+      _exit (1);
+    }
+  if (child < 0)
+    {
+      perror ("fork");
+      return 1;
+    }
+
+  e = clock_getcpuclockid (child, &cl);
+  if (e == EPERM)
+    {
+      puts ("clock_getcpuclockid does not support other processes");
+      goto done;
+    }
+  if (e != 0)
+    {
+      printf ("clock_getcpuclockid on live PID %d => %s\n",
+	      child, strerror (e));
+      result = 1;
+      goto done;
+    }
+
+  const clockid_t child_clock = cl;
+  struct timespec res;
+  if (clock_getres (child_clock, &res) < 0)
+    {
+      printf ("clock_getres on live PID %d clock %lx => %s\n",
+	      child, (unsigned long int) child_clock, strerror (errno));
+      result = 1;
+      goto done;
+    }
+  printf ("live PID %d clock %lx resolution %lu.%.9lu\n",
+	  child, (unsigned long int) child_clock, res.tv_sec, res.tv_nsec);
+
+  struct timespec before, after;
+  if (clock_gettime (child_clock, &before) < 0)
+    {
+      printf ("clock_gettime on live PID %d clock %lx => %s\n",
+	      child, (unsigned long int) child_clock, strerror (errno));
+      result = 1;
+      goto done;
+    }
+  printf ("live PID %d before sleep => %lu.%.9lu\n",
+	  child, before.tv_sec, before.tv_nsec);
+
+  struct timespec sleeptime = { .tv_nsec = 500000000 };
+  nanosleep (&sleeptime, NULL);
+
+  if (clock_gettime (child_clock, &after) < 0)
+    {
+      printf ("clock_gettime on live PID %d clock %lx => %s\n",
+	      child, (unsigned long int) child_clock, strerror (errno));
+      result = 1;
+      goto done;
+    }
+  printf ("live PID %d after sleep => %lu.%.9lu\n",
+	  child, after.tv_sec, after.tv_nsec);
+
+  struct timespec diff = { .tv_sec = after.tv_sec - before.tv_sec,
+			   .tv_nsec = after.tv_nsec - before.tv_nsec };
+  if (diff.tv_nsec < 0)
+    {
+      --diff.tv_sec;
+      diff.tv_nsec += 1000000000;
+    }
+  if (diff.tv_sec != 0
+      || diff.tv_nsec > 600000000
+      || diff.tv_nsec < 100000000)
+    {
+      printf ("before - after %lu.%.9lu outside reasonable range\n",
+	      diff.tv_sec, diff.tv_nsec);
+      result = 1;
+    }
+
+  sleeptime.tv_nsec = 100000000;
+  e = clock_nanosleep (child_clock, 0, &sleeptime, NULL);
+  if (e == EINVAL || e == ENOTSUP || e == ENOSYS)
+    {
+      printf ("clock_nanosleep not supported for other process clock: %s\n",
+	      strerror (e));
+    }
+  else if (e != 0)
+    {
+      printf ("clock_nanosleep on other process clock: %s\n", strerror (e));
+      result = 1;
+    }
+  else
+    {
+      struct timespec afterns;
+      if (clock_gettime (child_clock, &afterns) < 0)
+	{
+	  printf ("clock_gettime on live PID %d clock %lx => %s\n",
+		  child, (unsigned long int) child_clock, strerror (errno));
+	  result = 1;
+	}
+      else
+	{
+	  struct timespec d = { .tv_sec = afterns.tv_sec - after.tv_sec,
+				.tv_nsec = afterns.tv_nsec - after.tv_nsec };
+	  if (d.tv_nsec < 0)
+	    {
+	      --d.tv_sec;
+	      d.tv_nsec += 1000000000;
+	    }
+	  if (d.tv_sec > 0
+	      || d.tv_nsec < sleeptime.tv_nsec
+	      || d.tv_nsec > sleeptime.tv_nsec * 2)
+	    {
+	      printf ("nanosleep time %lu.%.9lu outside reasonable range\n",
+		      d.tv_sec, d.tv_nsec);
+	      result = 1;
+	    }
+	}
+    }
+
+  if (kill (child, SIGKILL) != 0)
+    {
+      perror ("kill");
+      result = 2;
+      goto done;
+    }
+
+  /* Wait long enough to let the child finish dying.  */
+
+  sleeptime.tv_nsec = 200000000;
+  nanosleep (&sleeptime, NULL);
+
+  struct timespec dead;
+  if (clock_gettime (child_clock, &dead) < 0)
+    {
+      printf ("clock_gettime on dead PID %d clock %lx => %s\n",
+	      child, (unsigned long int) child_clock, strerror (errno));
+      result = 1;
+      goto done;
+    }
+  printf ("dead PID %d => %lu.%.9lu\n",
+	  child, dead.tv_sec, dead.tv_nsec);
+
+  diff.tv_sec = dead.tv_sec - after.tv_sec;
+  diff.tv_nsec = dead.tv_nsec - after.tv_nsec;
+  if (diff.tv_nsec < 0)
+    {
+      --diff.tv_sec;
+      diff.tv_nsec += 1000000000;
+    }
+  if (diff.tv_sec != 0 || diff.tv_nsec > 200000000)
+    {
+      printf ("dead - after %lu.%.9lu outside reasonable range\n",
+	      diff.tv_sec, diff.tv_nsec);
+      result = 1;
+    }
+
+  /* Now reap the child and verify that its clock is no longer valid.  */
+  {
+    int x;
+    if (waitpid (child, &x, 0) != child)
+      {
+	perror ("waitpid");
+	result = 1;
+      }
+  }
+
+  if (clock_gettime (child_clock, &dead) == 0)
+    {
+      printf ("clock_gettime on reaped PID %d clock %lx => %lu%.9lu\n",
+	      child, (unsigned long int) child_clock,
+	      dead.tv_sec, dead.tv_nsec);
+      result = 1;
+    }
+  else
+    {
+      if (errno != EINVAL)
+	result = 1;
+      printf ("clock_gettime on reaped PID %d clock %lx => %s\n",
+	      child, (unsigned long int) child_clock, strerror (errno));
+    }
+
+  if (clock_getres (child_clock, &dead) == 0)
+    {
+      printf ("clock_getres on reaped PID %d clock %lx => %lu%.9lu\n",
+	      child, (unsigned long int) child_clock,
+	      dead.tv_sec, dead.tv_nsec);
+      result = 1;
+    }
+  else
+    {
+      if (errno != EINVAL)
+	result = 1;
+      printf ("clock_getres on reaped PID %d clock %lx => %s\n",
+	      child, (unsigned long int) child_clock, strerror (errno));
+    }
+
+  return result;
+
+ done:
+  {
+    if (kill (child, SIGKILL) != 0 && errno != ESRCH)
+      {
+	perror ("kill");
+	return 2;
+      }
+    int x;
+    if (waitpid (child, &x, 0) != child && errno != ECHILD)
+      {
+	perror ("waitpid");
+	return 2;
+      }
+  }
+
+  return result;
+}
+
+
+#define TIMEOUT 5
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cpuclock2.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cpuclock2.c
new file mode 100644
index 00000000..d1621f3d
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cpuclock2.c
@@ -0,0 +1,332 @@
+/* Test program for process and thread CPU clocks.
+   Copyright (C) 2005 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+
+#if (_POSIX_THREADS - 0) <= 0
+
+# define TEST_FUNCTION 0
+
+#else
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+static pthread_barrier_t barrier;
+
+/* This function is intended to rack up both user and system time.  */
+static void *
+chew_cpu (void *arg)
+{
+  pthread_barrier_wait (&barrier);
+
+  while (1)
+    {
+      static volatile char buf[4096];
+      for (int i = 0; i < 100; ++i)
+	for (size_t j = 0; j < sizeof buf; ++j)
+	  buf[j] = 0xaa;
+      int nullfd = open ("/dev/null", O_WRONLY);
+      for (int i = 0; i < 100; ++i)
+	for (size_t j = 0; j < sizeof buf; ++j)
+	  buf[j] = 0xbb;
+      write (nullfd, (char *) buf, sizeof buf);
+      close (nullfd);
+    }
+
+  return NULL;
+}
+
+static unsigned long long int
+tsdiff (const struct timespec *before, const struct timespec *after)
+{
+  struct timespec diff = { .tv_sec = after->tv_sec - before->tv_sec,
+			   .tv_nsec = after->tv_nsec - before->tv_nsec };
+  while (diff.tv_nsec < 0)
+    {
+      --diff.tv_sec;
+      diff.tv_nsec += 1000000000;
+    }
+  return diff.tv_sec * 1000000000ULL + diff.tv_nsec;
+}
+
+static unsigned long long int
+test_nanosleep (clockid_t clock, const char *which,
+		const struct timespec *before, int *bad)
+{
+  const struct timespec sleeptime = { .tv_nsec = 100000000 };
+  int e = clock_nanosleep (clock, 0, &sleeptime, NULL);
+  if (e == EINVAL || e == ENOTSUP || e == ENOSYS)
+    {
+      printf ("clock_nanosleep not supported for %s CPU clock: %s\n",
+	      which, strerror (e));
+      return 0;
+    }
+  if (e != 0)
+    {
+      printf ("clock_nanosleep on %s CPU clock: %s\n", which, strerror (e));
+      *bad = 1;
+      return 0;
+    }
+
+  struct timespec after;
+  if (clock_gettime (clock, &after) < 0)
+    {
+      printf ("clock_gettime on %s CPU clock %lx => %s\n",
+	      which, (unsigned long int) clock, strerror (errno));
+      *bad = 1;
+      return 0;
+    }
+
+  unsigned long long int diff = tsdiff (before, &after);
+  if (diff < sleeptime.tv_nsec || diff > sleeptime.tv_nsec * 2)
+    {
+      printf ("clock_nanosleep on %s slept %llu (outside reasonable range)\n",
+	      which, diff);
+      *bad = 1;
+      return diff;
+    }
+
+  struct timespec sleeptimeabs = sleeptime;
+  sleeptimeabs.tv_sec += after.tv_sec;
+  sleeptimeabs.tv_nsec += after.tv_nsec;
+  while (sleeptimeabs.tv_nsec > 1000000000)
+    {
+      ++sleeptimeabs.tv_sec;
+      sleeptimeabs.tv_nsec -= 1000000000;
+    }
+  e = clock_nanosleep (clock, TIMER_ABSTIME, &sleeptimeabs, NULL);
+  if (e != 0)
+    {
+      printf ("absolute clock_nanosleep on %s CPU clock: %s\n",
+	      which, strerror (e));
+      *bad = 1;
+      return diff;
+    }
+
+  struct timespec afterabs;
+  if (clock_gettime (clock, &afterabs) < 0)
+    {
+      printf ("clock_gettime on %s CPU clock %lx => %s\n",
+	      which, (unsigned long int) clock, strerror (errno));
+      *bad = 1;
+      return diff;
+    }
+
+  unsigned long long int sleepdiff = tsdiff (&sleeptimeabs, &afterabs);
+  if (sleepdiff > sleeptime.tv_nsec)
+    {
+      printf ("\
+absolute clock_nanosleep on %s %llu past target (outside reasonable range)\n",
+	      which, sleepdiff);
+      *bad = 1;
+    }
+
+  unsigned long long int diffabs = tsdiff (&after, &afterabs);
+  if (diffabs < sleeptime.tv_nsec || diffabs > sleeptime.tv_nsec * 2)
+    {
+      printf ("\
+absolute clock_nanosleep on %s slept %llu (outside reasonable range)\n",
+	      which, diffabs);
+      *bad = 1;
+    }
+
+  return diff + diffabs;
+}
+
+
+
+static int
+do_test (void)
+{
+  int result = 0;
+  clockid_t process_clock, th_clock, my_thread_clock;
+  int e;
+  pthread_t th;
+
+  e = clock_getcpuclockid (0, &process_clock);
+  if (e != 0)
+    {
+      printf ("clock_getcpuclockid on self => %s\n", strerror (e));
+      return 1;
+    }
+
+  e = pthread_getcpuclockid (pthread_self (), &my_thread_clock);
+  if (e != 0)
+    {
+      printf ("pthread_getcpuclockid on self => %s\n", strerror (e));
+      return 1;
+    }
+
+  /* This is a kludge.  This test fails if the semantics of thread and
+     process clocks are wrong.  The old code using hp-timing without kernel
+     support has bogus semantics if there are context switches.  We don't
+     fail to report failure when the proper functionality is not available
+     in the kernel.  It so happens that Linux kernels without correct CPU
+     clock support also lack CPU timer support, so we use use that to guess
+     that we are using the bogus code and not test it.  */
+  timer_t t;
+  if (timer_create (my_thread_clock, NULL, &t) != 0)
+    {
+      printf ("timer_create: %m\n");
+      puts ("No support for CPU clocks with good semantics, skipping test");
+      return 0;
+    }
+  timer_delete (t);
+
+
+  pthread_barrier_init (&barrier, NULL, 2);
+
+  e = pthread_create (&th, NULL, chew_cpu, NULL);
+  if (e != 0)
+    {
+      printf ("pthread_create: %s\n", strerror (e));
+      return 1;
+    }
+
+  e = pthread_getcpuclockid (th, &th_clock);
+  if (e == ENOENT || e == ENOSYS || e == ENOTSUP)
+    {
+      puts ("pthread_getcpuclockid does not support other threads");
+      return 1;
+    }
+
+  pthread_barrier_wait (&barrier);
+
+  struct timespec res;
+  if (clock_getres (th_clock, &res) < 0)
+    {
+      printf ("clock_getres on thread clock %lx => %s\n",
+	      (unsigned long int) th_clock, strerror (errno));
+      result = 1;
+      return 1;
+    }
+  printf ("live thread clock %lx resolution %lu.%.9lu\n",
+	  (unsigned long int) th_clock, res.tv_sec, res.tv_nsec);
+
+  struct timespec process_before, process_after;
+  if (clock_gettime (process_clock, &process_before) < 0)
+    {
+      printf ("clock_gettime on process clock %lx => %s\n",
+	      (unsigned long int) th_clock, strerror (errno));
+      return 1;
+    }
+
+  struct timespec before, after;
+  if (clock_gettime (th_clock, &before) < 0)
+    {
+      printf ("clock_gettime on live thread clock %lx => %s\n",
+	      (unsigned long int) th_clock, strerror (errno));
+      return 1;
+    }
+  printf ("live thread before sleep => %lu.%.9lu\n",
+	  before.tv_sec, before.tv_nsec);
+
+  struct timespec me_before, me_after;
+  if (clock_gettime (my_thread_clock, &me_before) < 0)
+    {
+      printf ("clock_gettime on live thread clock %lx => %s\n",
+	      (unsigned long int) th_clock, strerror (errno));
+      return 1;
+    }
+  printf ("self thread before sleep => %lu.%.9lu\n",
+	  me_before.tv_sec, me_before.tv_nsec);
+
+  struct timespec sleeptime = { .tv_nsec = 500000000 };
+  nanosleep (&sleeptime, NULL);
+
+  if (clock_gettime (th_clock, &after) < 0)
+    {
+      printf ("clock_gettime on live thread clock %lx => %s\n",
+	      (unsigned long int) th_clock, strerror (errno));
+      return 1;
+    }
+  printf ("live thread after sleep => %lu.%.9lu\n",
+	  after.tv_sec, after.tv_nsec);
+
+  if (clock_gettime (process_clock, &process_after) < 0)
+    {
+      printf ("clock_gettime on process clock %lx => %s\n",
+	      (unsigned long int) th_clock, strerror (errno));
+      return 1;
+    }
+
+  if (clock_gettime (my_thread_clock, &me_after) < 0)
+    {
+      printf ("clock_gettime on live thread clock %lx => %s\n",
+	      (unsigned long int) th_clock, strerror (errno));
+      return 1;
+    }
+  printf ("self thread after sleep => %lu.%.9lu\n",
+	  me_after.tv_sec, me_after.tv_nsec);
+
+  unsigned long long int th_diff = tsdiff (&before, &after);
+  unsigned long long int pdiff = tsdiff (&process_before, &process_after);
+  unsigned long long int my_diff = tsdiff (&me_before, &me_after);
+
+  if (th_diff < 100000000 || th_diff > 600000000)
+    {
+      printf ("thread before - after %llu outside reasonable range\n",
+	      th_diff);
+      result = 1;
+    }
+
+  if (my_diff > 100000000)
+    {
+      printf ("self thread before - after %llu outside reasonable range\n",
+	      my_diff);
+      result = 1;
+    }
+
+  if (pdiff < th_diff)
+    {
+      printf ("process before - after %llu outside reasonable range (%llu)\n",
+	      pdiff, th_diff);
+      result = 1;
+    }
+
+  process_after.tv_nsec += test_nanosleep (th_clock, "thread",
+					   &after, &result);
+  process_after.tv_nsec += test_nanosleep (process_clock, "process",
+					   &process_after, &result);
+  test_nanosleep (CLOCK_PROCESS_CPUTIME_ID,
+		  "PROCESS_CPUTIME_ID", &process_after, &result);
+
+  pthread_cancel (th);
+
+  e = clock_nanosleep (CLOCK_THREAD_CPUTIME_ID, 0, &sleeptime, NULL);
+  if (e != EINVAL)
+    {
+      printf ("clock_nanosleep CLOCK_THREAD_CPUTIME_ID: %s\n",
+	      strerror (e));
+      result = 1;
+    }
+
+  return result;
+}
+# define TIMEOUT 8
+# define TEST_FUNCTION do_test ()
+#endif
+
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cputimer1.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cputimer1.c
new file mode 100644
index 00000000..8f5dd76c
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cputimer1.c
@@ -0,0 +1,68 @@
+/* Tests for POSIX timer implementation using process CPU clock.  */
+
+#include 
+
+#if _POSIX_THREADS && defined _POSIX_CPUTIME
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define TEST_CLOCK CLOCK_PROCESS_CPUTIME_ID
+#define TEST_CLOCK_MISSING(clock) \
+  (setup_test () ? "process CPU clock timer support" : NULL)
+
+/* This function is intended to rack up both user and system time.  */
+static void *
+chew_cpu (void *arg)
+{
+  while (1)
+    {
+      static volatile char buf[4096];
+      for (int i = 0; i < 100; ++i)
+	for (size_t j = 0; j < sizeof buf; ++j)
+	  buf[j] = 0xaa;
+      int nullfd = open ("/dev/null", O_WRONLY);
+      for (int i = 0; i < 100; ++i)
+	for (size_t j = 0; j < sizeof buf; ++j)
+	  buf[j] = 0xbb;
+      write (nullfd, (char *) buf, sizeof buf);
+      close (nullfd);
+    }
+
+  return NULL;
+}
+
+static int
+setup_test (void)
+{
+  /* Test timers on our own process CPU clock by having a worker thread
+     eating CPU.  First make sure we can make such timers at all.  */
+
+  timer_t t;
+  if (timer_create (TEST_CLOCK, NULL, &t) != 0)
+    {
+      printf ("timer_create: %m\n");
+      return 1;
+    }
+  timer_delete (t);
+
+  pthread_t th;
+  int e = pthread_create (&th, NULL, chew_cpu, NULL);
+  if (e != 0)
+    {
+      printf ("pthread_create: %s\n", strerror (e));
+      exit (1);
+    }
+
+  return 0;
+}
+
+#else
+# define TEST_CLOCK_MISSING(clock) "process clocks"
+#endif
+
+#include "tst-timer4.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cputimer2.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cputimer2.c
new file mode 100644
index 00000000..397d7998
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cputimer2.c
@@ -0,0 +1,83 @@
+/* Tests for POSIX timer implementation using thread CPU clock.  */
+
+#include 
+
+#if _POSIX_THREADS && defined _POSIX_CPUTIME
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+static clockid_t worker_thread_clock;
+
+#define TEST_CLOCK worker_thread_clock
+#define TEST_CLOCK_MISSING(clock) \
+  (setup_test () ? "thread CPU clock timer support" : NULL)
+
+/* This function is intended to rack up both user and system time.  */
+static void *
+chew_cpu (void *arg)
+{
+  while (1)
+    {
+      static volatile char buf[4096];
+      for (int i = 0; i < 100; ++i)
+	for (size_t j = 0; j < sizeof buf; ++j)
+	  buf[j] = 0xaa;
+      int nullfd = open ("/dev/null", O_WRONLY);
+      for (int i = 0; i < 100; ++i)
+	for (size_t j = 0; j < sizeof buf; ++j)
+	  buf[j] = 0xbb;
+      write (nullfd, (char *) buf, sizeof buf);
+      close (nullfd);
+    }
+
+  return NULL;
+}
+
+static int
+setup_test (void)
+{
+  /* Test timers on a thread CPU clock by having a worker thread eating
+     CPU.  First make sure we can make such timers at all.  */
+
+  pthread_t th;
+  int e = pthread_create (&th, NULL, chew_cpu, NULL);
+  if (e != 0)
+    {
+      printf ("pthread_create: %s\n", strerror (e));
+      exit (1);
+    }
+
+  e = pthread_getcpuclockid (th, &worker_thread_clock);
+  if (e == EPERM || e == ENOENT || e == ENOTSUP)
+    {
+      puts ("pthread_getcpuclockid does not support other threads");
+      return 1;
+    }
+  if (e != 0)
+    {
+      printf ("pthread_getcpuclockid: %s\n", strerror (e));
+      exit (1);
+    }
+
+  timer_t t;
+  if (timer_create (TEST_CLOCK, NULL, &t) != 0)
+    {
+      printf ("timer_create: %m\n");
+      return 1;
+    }
+  timer_delete (t);
+
+  return 0;
+}
+
+#else
+# define TEST_CLOCK_MISSING(clock) "process clocks"
+#endif
+
+#include "tst-timer4.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cputimer3.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cputimer3.c
new file mode 100644
index 00000000..056766a3
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-cputimer3.c
@@ -0,0 +1,130 @@
+/* Tests for POSIX timer implementation using another process's CPU clock.  */
+
+#include 
+
+#if _POSIX_THREADS && defined _POSIX_CPUTIME
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+static clockid_t child_clock;
+
+#define TEST_CLOCK child_clock
+#define TEST_CLOCK_MISSING(clock) \
+  (setup_test () ? "other-process CPU clock timer support" : NULL)
+
+/* This function is intended to rack up both user and system time.  */
+static void
+chew_cpu (void)
+{
+  while (1)
+    {
+      static volatile char buf[4096];
+      for (int i = 0; i < 100; ++i)
+	for (size_t j = 0; j < sizeof buf; ++j)
+	  buf[j] = 0xaa;
+      int nullfd = open ("/dev/null", O_WRONLY);
+      for (int i = 0; i < 100; ++i)
+	for (size_t j = 0; j < sizeof buf; ++j)
+	  buf[j] = 0xbb;
+      write (nullfd, (char *) buf, sizeof buf);
+      close (nullfd);
+      if (getppid () == 1)
+	_exit (2);
+    }
+}
+
+static pid_t child;
+static void
+cleanup_child (void)
+{
+  if (child <= 0)
+    return;
+  if (kill (child, SIGKILL) < 0 && errno != ESRCH)
+    printf ("cannot kill child %d: %m\n", child);
+  else
+    {
+      int status;
+      errno = 0;
+      if (waitpid (child, &status, 0) != child)
+	printf ("waitpid %d: %m\n", child);
+    }
+}
+#define CLEANUP_HANDLER cleanup_child ()
+
+static int
+setup_test (void)
+{
+  /* Test timers on a process CPU clock by having a child process eating
+     CPU.  First make sure we can make such timers at all.  */
+
+  int pipefd[2];
+  if (pipe (pipefd) < 0)
+    {
+      printf ("pipe: %m\n");
+      exit (1);
+    }
+
+  child = fork ();
+
+  if (child == 0)
+    {
+      char c;
+      close (pipefd[1]);
+      if (read (pipefd[0], &c, 1) == 1)
+	chew_cpu ();
+      _exit (1);
+    }
+
+  if (child < 0)
+    {
+      printf ("fork: %m\n");
+      exit (1);
+    }
+
+  atexit (&cleanup_child);
+
+  close (pipefd[0]);
+
+  int e = clock_getcpuclockid (child, &child_clock);
+  if (e == EPERM)
+    {
+      puts ("clock_getcpuclockid does not support other processes");
+      return 1;
+    }
+  if (e != 0)
+    {
+      printf ("clock_getcpuclockid: %s\n", strerror (e));
+      exit (1);
+    }
+
+  timer_t t;
+  if (timer_create (TEST_CLOCK, NULL, &t) != 0)
+    {
+      printf ("timer_create: %m\n");
+      return 1;
+    }
+  timer_delete (t);
+
+  /* Get the child started chewing.  */
+  if (write (pipefd[1], "x", 1) != 1)
+    {
+      printf ("write to pipe: %m\n");
+      return 1;
+    }
+  close (pipefd[1]);
+
+  return 0;
+}
+
+#else
+# define TEST_CLOCK_MISSING(clock) "process clocks"
+#endif
+
+#include "tst-timer4.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-detach1.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-detach1.c
new file mode 100644
index 00000000..7b27f6ea
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-detach1.c
@@ -0,0 +1,56 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+
+
+static void *
+tf (void *arg)
+{
+  return NULL;
+}
+
+
+static int
+do_test (void)
+{
+  pthread_t th;
+  if (pthread_create (&th, NULL, tf, (void *) pthread_self ()) != 0)
+    {
+      puts ("create failed");
+      exit (1);
+    }
+
+  /* Give the child a chance to finish.  */
+  sleep (1);
+
+  if (pthread_detach (th) != 0)
+    {
+      puts ("detach failed");
+      exit (1);
+    }
+
+  return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-dlsym1.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-dlsym1.c
new file mode 100644
index 00000000..3744570c
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-dlsym1.c
@@ -0,0 +1,66 @@
+/* Test case by Hui Huang .  */
+#include 
+#include 
+#include 
+#include 
+
+
+static void *
+start_routine (void *args)
+{
+  int i;
+  void **addrs = (void **) args;
+  for (i = 0; i < 10000; ++i)
+    addrs[i % 1024] = dlsym (NULL, "does_not_exist");
+
+  return addrs;
+}
+
+
+static int
+do_test (void)
+{
+  pthread_t tid1, tid2, tid3;
+
+  void *addrs1[1024];
+  void *addrs2[1024];
+  void *addrs3[1024];
+
+  if (pthread_create (&tid1, NULL, start_routine, addrs1) != 0)
+    {
+      puts ("1st create failed");
+      exit (1);
+    }
+  if (pthread_create (&tid2, NULL, start_routine, addrs2) != 0)
+    {
+      puts ("2nd create failed");
+      exit (1);
+    }
+  if (pthread_create (&tid3, NULL, start_routine, addrs3) != 0)
+    {
+      puts ("3rd create failed");
+      exit (1);
+    }
+
+  if (pthread_join (tid1, NULL) != 0)
+    {
+      puts ("1st join failed");
+      exit (1);
+    }
+  if (pthread_join (tid2, NULL) != 0)
+    {
+      puts ("2nd join failed");
+      exit (1);
+    }
+  if (pthread_join (tid3, NULL) != 0)
+    {
+      puts ("2rd join failed");
+      exit (1);
+    }
+
+  return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-eintr1.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-eintr1.c
new file mode 100644
index 00000000..43a5df5b
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-eintr1.c
@@ -0,0 +1,105 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "eintr.c"
+
+
+static void *
+tf2 (void *arg)
+{
+  return arg;
+}
+
+
+static void *
+tf1 (void *arg)
+{
+  while (1)
+    {
+      pthread_t th;
+
+      int e = pthread_create (&th, NULL, tf2, NULL);
+      if (e != 0)
+	{
+	  if (e == EINTR)
+	    {
+	      puts ("pthread_create returned EINTR");
+	      exit (1);
+	    }
+
+	  char buf[100];
+	  printf ("tf1: pthread_create failed: %s\n",
+		  strerror_r (e, buf, sizeof (buf)));
+	  exit (1);
+	}
+
+      e = pthread_join (th, NULL);
+      if (e != 0)
+	{
+	  if (e == EINTR)
+	    {
+	      puts ("pthread_join returned EINTR");
+	      exit (1);
+	    }
+
+	  char buf[100];
+	  printf ("tf1: pthread_join failed: %s\n",
+		  strerror_r (e, buf, sizeof (buf)));
+	  exit (1);
+	}
+    }
+}
+
+
+static int
+do_test (void)
+{
+  setup_eintr (SIGUSR1, NULL);
+
+  int i;
+  for (i = 0; i < 10; ++i)
+    {
+      pthread_t th;
+      int e = pthread_create (&th, NULL, tf1, NULL);
+      if (e != 0)
+	{
+	  char buf[100];
+	  printf ("main: pthread_create failed: %s\n",
+		  strerror_r (e, buf, sizeof (buf)));
+	  exit (1);
+	}
+    }
+
+  (void) tf1 (NULL);
+  /* NOTREACHED */
+
+  return 0;
+}
+
+#define EXPECTED_SIGNAL SIGALRM
+#define TIMEOUT 3
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-eintr2.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-eintr2.c
new file mode 100644
index 00000000..8cbbc5a0
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-eintr2.c
@@ -0,0 +1,118 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "eintr.c"
+
+
+static pthread_mutex_t m1 = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t m2 = PTHREAD_MUTEX_INITIALIZER;
+
+
+static void *
+tf1 (void *arg)
+{
+  struct timespec ts;
+  struct timeval tv;
+
+  gettimeofday (&tv, NULL);
+  TIMEVAL_TO_TIMESPEC (&tv, &ts);
+  ts.tv_sec += 10000;
+
+  /* This call must never return.  */
+  int e = pthread_mutex_timedlock (&m1, &ts);
+  char buf[100];
+  printf ("tf1: mutex_timedlock returned: %s\n",
+	  strerror_r (e, buf, sizeof (buf)));
+
+  exit (1);
+}
+
+
+static void *
+tf2 (void *arg)
+{
+  while (1)
+    {
+      int e = pthread_mutex_lock (&m2);
+      if (e != 0)
+	{
+	  puts ("tf2: mutex_lock failed");
+	  exit (1);
+	}
+      e = pthread_mutex_unlock (&m2);
+      if (e != 0)
+	{
+	  puts ("tf2: mutex_unlock failed");
+	  exit (1);
+	}
+      struct timespec ts = { .tv_sec = 0, .tv_nsec = 10000000 };
+      nanosleep (&ts, NULL);
+    }
+}
+
+
+static int
+do_test (void)
+{
+  if (pthread_mutex_lock (&m1) != 0)
+    {
+      puts ("mutex_lock failed");
+      exit (1);
+    }
+
+  setup_eintr (SIGUSR1, NULL);
+
+  pthread_t th;
+  char buf[100];
+  int e = pthread_create (&th, NULL, tf1, NULL);
+  if (e != 0)
+    {
+      printf ("main: 1st pthread_create failed: %s\n",
+	      strerror_r (e, buf, sizeof (buf)));
+      exit (1);
+    }
+
+  e = pthread_create (&th, NULL, tf2, NULL);
+  if (e != 0)
+    {
+      printf ("main: 2nd pthread_create failed: %s\n",
+	      strerror_r (e, buf, sizeof (buf)));
+      exit (1);
+    }
+
+  /* This call must never return.  */
+  e = pthread_mutex_lock (&m1);
+  printf ("main: mutex_lock returned: %s\n",
+	  strerror_r (e, buf, sizeof (buf)));
+
+  return 0;
+}
+
+#define EXPECTED_SIGNAL SIGALRM
+#define TIMEOUT 3
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-eintr3.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-eintr3.c
new file mode 100644
index 00000000..eecab48b
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-eintr3.c
@@ -0,0 +1,72 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "eintr.c"
+
+
+static void *
+tf (void *arg)
+{
+  pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
+  pthread_mutex_lock (&m);
+  /* This call must not return.  */
+  pthread_mutex_lock (&m);
+
+  puts ("tf: mutex_lock returned");
+  exit (1);
+}
+
+
+static int
+do_test (void)
+{
+  pthread_t self = pthread_self ();
+
+  setup_eintr (SIGUSR1, &self);
+
+  pthread_t th;
+  char buf[100];
+  int e = pthread_create (&th, NULL, tf, NULL);
+  if (e != 0)
+    {
+      printf ("main: pthread_create failed: %s\n",
+	      strerror_r (e, buf, sizeof (buf)));
+      exit (1);
+    }
+
+  /* This call must never return.  */
+  e = pthread_join (th, NULL);
+
+  if (e == EINTR)
+    puts ("pthread_join returned with EINTR");
+
+  return 0;
+}
+
+#define EXPECTED_SIGNAL SIGALRM
+#define TIMEOUT 1
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-eintr4.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-eintr4.c
new file mode 100644
index 00000000..dffbdd60
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-eintr4.c
@@ -0,0 +1,56 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "eintr.c"
+
+
+static int
+do_test (void)
+{
+  pthread_t self = pthread_self ();
+
+  setup_eintr (SIGUSR1, &self);
+
+  pthread_barrier_t b;
+  if (pthread_barrier_init (&b, NULL, 2) != 0)
+    {
+      puts ("barrier_init failed");
+      exit (1);
+    }
+
+  /* This call must never return.  */
+  int e = pthread_barrier_wait (&b);
+
+  if (e == EINTR)
+    puts ("pthread_join returned with EINTR");
+
+  return 0;
+}
+
+#define EXPECTED_SIGNAL SIGALRM
+#define TIMEOUT 1
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-eintr5.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-eintr5.c
new file mode 100644
index 00000000..91473ec4
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-eintr5.c
@@ -0,0 +1,81 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "eintr.c"
+
+
+static pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t c = PTHREAD_COND_INITIALIZER;
+
+
+static void *
+tf (void *arg)
+{
+  struct timespec ts;
+  struct timeval tv;
+
+  gettimeofday (&tv, NULL);
+  TIMEVAL_TO_TIMESPEC (&tv, &ts);
+  ts.tv_sec += 10000;
+
+  /* This call must never return.  */
+  int e = pthread_cond_timedwait (&c, &m, &ts);
+  char buf[100];
+  printf ("tf: cond_timedwait returned: %s\n",
+	  strerror_r (e, buf, sizeof (buf)));
+
+  exit (1);
+}
+
+
+static int
+do_test (void)
+{
+  setup_eintr (SIGUSR1, NULL);
+
+  pthread_t th;
+  char buf[100];
+  int e = pthread_create (&th, NULL, tf, NULL);
+  if (e != 0)
+    {
+      printf ("main: pthread_create failed: %s\n",
+	      strerror_r (e, buf, sizeof (buf)));
+      exit (1);
+    }
+
+  /* This call must never return.  */
+  e = pthread_cond_wait (&c, &m);
+  printf ("main: cond_wait returned: %s\n",
+	  strerror_r (e, buf, sizeof (buf)));
+
+  return 0;
+}
+
+#define EXPECTED_SIGNAL SIGALRM
+#define TIMEOUT 3
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-exec2.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-exec2.c
new file mode 100644
index 00000000..432da32e
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-exec2.c
@@ -0,0 +1,154 @@
+/* Thread with running thread calls exec.
+   Copyright (C) 2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2002.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+static void *
+tf (void *arg)
+{
+  pthread_t th = (pthread_t) arg;
+
+  if (pthread_join (th, NULL) == 0)
+    {
+      puts ("thread in parent joined!?");
+      exit (1);
+    }
+
+  puts ("join in thread in parent returned!?");
+  exit (1);
+}
+
+
+static int
+do_test (void)
+{
+  int fd[2];
+  if (pipe (fd) != 0)
+    {
+      puts ("pipe failed");
+      exit (1);
+    }
+
+  /* Not interested in knowing when the pipe is closed.  */
+  if (sigignore (SIGPIPE) != 0)
+    {
+      puts ("sigignore failed");
+      exit (1);
+    }
+
+  pid_t pid = fork ();
+  if (pid == -1)
+    {
+      puts ("fork failed");
+      exit (1);
+    }
+
+  if (pid == 0)
+    {
+      /* Use the fd for stdout.  This is kind of ugly because it
+	 substitutes the fd of stdout but we know what we are doing
+	 here...  */
+      if (dup2 (fd[1], STDOUT_FILENO) != STDOUT_FILENO)
+	{
+	  puts ("dup2 failed");
+	  exit (1);
+	}
+
+      close (fd[0]);
+
+      pthread_t th;
+      if (pthread_create (&th, NULL, tf, (void *) pthread_self ()) != 0)
+	{
+	  puts ("create failed");
+	  exit (1);
+	}
+
+      execl (_PATH_BSHELL, _PATH_BSHELL, "-c", "echo $$", NULL);
+
+      puts ("execl failed");
+      exit (1);
+    }
+
+  close (fd[1]);
+
+  char buf[200];
+  ssize_t n;
+  bool seen_pid = false;
+  while (TEMP_FAILURE_RETRY ((n = read (fd[0], buf, sizeof (buf)))) > 0)
+    {
+      /* We only expect to read the PID.  */
+      char *endp;
+      long int rpid = strtol (buf, &endp, 10);
+
+      if (*endp != '\n')
+	{
+	  printf ("didn't parse whole line: \"%s\"\n", buf);
+	  exit (1);
+	}
+      if (endp == buf)
+	{
+	  puts ("read empty line");
+	  exit (1);
+	}
+
+      if (rpid != pid)
+	{
+	  printf ("found \"%s\", expected PID %ld\n", buf, (long int) pid);
+	  exit (1);
+	}
+
+      if (seen_pid)
+	{
+	  puts ("found more than one PID line");
+	  exit (1);
+	}
+      seen_pid = true;
+    }
+
+  close (fd[0]);
+
+  int status;
+  int err = waitpid (pid, &status, 0);
+  if (err != pid)
+    {
+      puts ("waitpid failed");
+      exit (1);
+    }
+
+  if (!seen_pid)
+    {
+      puts ("didn't get PID");
+      exit (1);
+    }
+
+  return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-exec3.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-exec3.c
new file mode 100644
index 00000000..be49b048
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-exec3.c
@@ -0,0 +1,152 @@
+/* Thread calls exec.
+   Copyright (C) 2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2002.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+static void *
+tf (void *arg)
+{
+  execl (_PATH_BSHELL, _PATH_BSHELL, "-c", "echo $$", NULL);
+
+  puts ("execl failed");
+  exit (1);
+}
+
+
+static int
+do_test (void)
+{
+  int fd[2];
+  if (pipe (fd) != 0)
+    {
+      puts ("pipe failed");
+      exit (1);
+    }
+
+  /* Not interested in knowing when the pipe is closed.  */
+  if (sigignore (SIGPIPE) != 0)
+    {
+      puts ("sigignore failed");
+      exit (1);
+    }
+
+  pid_t pid = fork ();
+  if (pid == -1)
+    {
+      puts ("fork failed");
+      exit (1);
+    }
+
+  if (pid == 0)
+    {
+      /* Use the fd for stdout.  This is kind of ugly because it
+	 substitutes the fd of stdout but we know what we are doing
+	 here...  */
+      if (dup2 (fd[1], STDOUT_FILENO) != STDOUT_FILENO)
+	{
+	  puts ("dup2 failed");
+	  exit (1);
+	}
+
+      close (fd[0]);
+
+      pthread_t th;
+      if (pthread_create (&th, NULL, tf, NULL) != 0)
+	{
+	  puts ("create failed");
+	  exit (1);
+	}
+
+      if (pthread_join (th, NULL) == 0)
+	{
+	  puts ("join succeeded!?");
+	  exit (1);
+	}
+
+      puts ("join returned!?");
+      exit (1);
+    }
+
+  close (fd[1]);
+
+  char buf[200];
+  ssize_t n;
+  bool seen_pid = false;
+  while (TEMP_FAILURE_RETRY ((n = read (fd[0], buf, sizeof (buf)))) > 0)
+    {
+      /* We only expect to read the PID.  */
+      char *endp;
+      long int rpid = strtol (buf, &endp, 10);
+
+      if (*endp != '\n')
+	{
+	  printf ("didn't parse whole line: \"%s\"\n", buf);
+	  exit (1);
+	}
+      if (endp == buf)
+	{
+	  puts ("read empty line");
+	  exit (1);
+	}
+
+      if (rpid != pid)
+	{
+	  printf ("found \"%s\", expected PID %ld\n", buf, (long int) pid);
+	  exit (1);
+	}
+
+      if (seen_pid)
+	{
+	  puts ("found more than one PID line");
+	  exit (1);
+	}
+      seen_pid = true;
+    }
+
+  close (fd[0]);
+
+  int status;
+  int err = waitpid (pid, &status, 0);
+  if (err != pid)
+    {
+      puts ("waitpid failed");
+      exit (1);
+    }
+
+  if (!seen_pid)
+    {
+      puts ("didn't get PID");
+      exit (1);
+    }
+
+  return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-exec4.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-exec4.c
new file mode 100644
index 00000000..b3920a03
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-exec4.c
@@ -0,0 +1,116 @@
+/* Signal handler and mask set in thread which calls exec.
+   Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+static void *
+tf (void *arg)
+{
+  /* Ignore SIGUSR1 and block SIGUSR2.  */
+  if (sigignore (SIGUSR1) != 0)
+    {
+      puts ("sigignore failed");
+      exit (1);
+    }
+
+  sigset_t ss;
+  sigemptyset (&ss);
+  sigaddset (&ss, SIGUSR2);
+  if (pthread_sigmask (SIG_BLOCK, &ss, NULL) != 0)
+    {
+      puts ("1st run: sigmask failed");
+      exit (1);
+    }
+
+  char **oldargv = (char **) arg;
+  size_t n = 1;
+  while (oldargv[n] != NULL)
+    ++n;
+
+  char **argv = (char **) alloca ((n + 1) * sizeof (char *));
+  for (n = 0; oldargv[n + 1] != NULL; ++n)
+    argv[n] = oldargv[n + 1];
+  argv[n++] = (char *) "--direct";
+  argv[n] = NULL;
+
+  execv (argv[0], argv);
+
+  puts ("execv failed");
+
+  exit (1);
+}
+
+
+static int
+do_test (int argc, char *argv[])
+{
+  if (argc == 1)
+    {
+      /* This is the second call.  Perform the test.  */
+      struct sigaction sa;
+
+      if (sigaction (SIGUSR1, NULL, &sa) != 0)
+	{
+	  puts ("2nd run: sigaction failed");
+	  return 1;
+	}
+      if (sa.sa_handler != SIG_IGN)
+	{
+	  puts ("SIGUSR1 not ignored");
+	  return 1;
+	}
+
+      sigset_t ss;
+      if (pthread_sigmask (SIG_SETMASK, NULL, &ss) != 0)
+	{
+	  puts ("2nd run: sigmask failed");
+	  return 1;
+	}
+      if (! sigismember (&ss, SIGUSR2))
+	{
+	  puts ("SIGUSR2 not blocked");
+	  return 1;
+	}
+
+      return 0;
+    }
+
+  pthread_t th;
+  if (pthread_create (&th, NULL, tf, argv) != 0)
+    {
+      puts ("create failed");
+      exit (1);
+    }
+
+  /* This call should never return.  */
+  pthread_join (th, NULL);
+
+  puts ("join returned");
+
+  return 1;
+}
+
+#define TEST_FUNCTION do_test (argc, argv)
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-exit1.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-exit1.c
new file mode 100644
index 00000000..44175f76
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-exit1.c
@@ -0,0 +1,79 @@
+/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2002.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+/* NOTE: this tests functionality beyond POSIX.  POSIX does not allow
+   exit to be called more than once.  */
+
+#include 
+#include 
+#include 
+
+static pthread_barrier_t b;
+
+
+static void *
+tf (void *arg)
+{
+  int r = pthread_barrier_wait (&b);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("barrier_wait failed");
+      exit (1);
+    }
+
+  exit (0);
+}
+
+
+static int
+do_test (void)
+{
+  if (pthread_barrier_init (&b, NULL, 2) != 0)
+    {
+      puts ("barrier_init failed");
+      exit (1);
+    }
+
+  pthread_t th;
+  if (pthread_create (&th, NULL, tf, NULL) != 0)
+    {
+      puts ("create failed");
+      exit (1);
+    }
+
+  int r = pthread_barrier_wait (&b);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("barrier_wait failed");
+      exit (1);
+    }
+
+  /* Do nothing.  */
+  if (pthread_join (th, NULL) == 0)
+    {
+      puts ("join succeeded!?");
+      exit (1);
+    }
+
+  puts ("join returned!?");
+  exit (1);
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-exit2.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-exit2.c
new file mode 100644
index 00000000..3f5ff27b
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-exit2.c
@@ -0,0 +1,40 @@
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+static void *
+tf (void *arg)
+{
+  while (1)
+    sleep (100);
+
+  /* NOTREACHED */
+  return NULL;
+}
+
+
+static int
+do_test (void)
+{
+  pthread_t th;
+
+  int e = pthread_create (&th, NULL, tf, NULL);
+  if (e != 0)
+    {
+      printf ("create failed: %s\n", strerror (e));
+      return 1;
+    }
+
+  /* Terminate only this thread.  */
+  pthread_exit (NULL);
+
+  /* NOTREACHED */
+  return 1;
+}
+
+#define EXPECTED_SIGNAL SIGALRM
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-exit3.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-exit3.c
new file mode 100644
index 00000000..da92c82c
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-exit3.c
@@ -0,0 +1,81 @@
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+static pthread_barrier_t b;
+
+
+static void *
+tf2 (void *arg)
+{
+  while (1)
+    sleep (100);
+
+  /* NOTREACHED */
+  return NULL;
+}
+
+
+static void *
+tf (void *arg)
+{
+  pthread_t th;
+
+  int e = pthread_barrier_wait (&b);
+  if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("barrier_wait failed");
+      exit (1);
+    }
+
+  e = pthread_create (&th, NULL, tf2, NULL);
+  if (e != 0)
+    {
+      printf ("create failed: %s\n", strerror (e));
+      exit (1);
+    }
+
+  /* Terminate only this thread.  */
+  return NULL;
+}
+
+
+static int
+do_test (void)
+{
+  pthread_t th;
+
+  if (pthread_barrier_init (&b, NULL, 2) != 0)
+    {
+      puts ("barrier_init failed");
+      exit (1);
+    }
+
+  int e = pthread_create (&th, NULL, tf, NULL);
+  if (e != 0)
+    {
+      printf ("create failed: %s\n", strerror (e));
+      exit (1);
+    }
+
+  e = pthread_barrier_wait (&b);
+  if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("barrier_wait failed");
+      exit (1);
+    }
+
+  /* Terminate only this thread.  */
+  pthread_exit (NULL);
+
+  /* NOTREACHED */
+  return 1;
+}
+
+#define EXPECTED_SIGNAL SIGALRM
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-fini1.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-fini1.c
new file mode 100644
index 00000000..bec4be1d
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-fini1.c
@@ -0,0 +1,35 @@
+/* Copyright (C) 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2004.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+
+extern void m (void);
+
+int
+main (void)
+{
+  alarm (5);
+
+  m ();
+
+  /* The destructor is supposed to run now.  Make sure that if it is
+     not we will notice it by using 42 as the exit code.  In case the
+     destructor is run it will terminate with status zero.  */
+  return 42;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-fini1mod.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-fini1mod.c
new file mode 100644
index 00000000..492d9ffb
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-fini1mod.c
@@ -0,0 +1,72 @@
+/* Copyright (C) 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2004.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+
+
+static void *
+tf (void *arg)
+{
+  int fds[2];
+  if (pipe (fds) != 0)
+    {
+      puts ("pipe failed");
+      exit (1);
+    }
+
+  char buf[10];
+  read (fds[0], buf, sizeof (buf));
+
+  puts ("read returned");
+  exit (1);
+}
+
+static pthread_t th;
+
+static void
+__attribute ((destructor))
+dest (void)
+{
+  if (pthread_cancel (th) != 0)
+    {
+      puts ("cancel failed");
+      _exit (1);
+    }
+  void *r;
+  if (pthread_join (th, &r) != 0)
+    {
+      puts ("join failed");
+      _exit (1);
+    }
+  /* Exit successfully.  */
+  _exit (0);
+}
+
+void
+m (void)
+{
+  if (pthread_create (&th, NULL, tf, NULL) != 0)
+    {
+      puts ("create failed");
+      _exit (1);
+    }
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-flock1.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-flock1.c
new file mode 100644
index 00000000..ed2472d3
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-flock1.c
@@ -0,0 +1,93 @@
+/* Copyright (C) 2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2002.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
+
+static int fd;
+
+
+static void *
+tf (void *arg)
+{
+  if (flock (fd, LOCK_SH | LOCK_NB) != 0)
+    {
+      puts ("second flock failed");
+      exit (1);
+    }
+
+  pthread_mutex_unlock (&lock);
+
+  return NULL;
+}
+
+
+static int
+do_test (void)
+{
+  char tmp[] = "/tmp/tst-flock1-XXXXXX";
+
+  fd = mkstemp (tmp);
+  if (fd == -1)
+    {
+      puts ("mkstemp failed");
+      exit (1);
+    }
+
+  unlink (tmp);
+
+  write (fd, "foobar xyzzy", 12);
+
+  if (flock (fd, LOCK_EX | LOCK_NB) != 0)
+    {
+      puts ("first flock failed");
+      exit (1);
+    }
+
+  pthread_mutex_lock (&lock);
+
+  pthread_t th;
+  if (pthread_create (&th, NULL, tf, NULL) != 0)
+    {
+      puts ("pthread_create failed");
+      exit (1);
+    }
+
+  pthread_mutex_lock (&lock);
+
+  void *result;
+  if (pthread_join (th, &result) != 0)
+    {
+      puts ("pthread_join failed");
+      exit (1);
+    }
+
+  close (fd);
+
+  return result != NULL;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-flock2.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-flock2.c
new file mode 100644
index 00000000..8ef3206c
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-flock2.c
@@ -0,0 +1,260 @@
+/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2002.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t lock2 = PTHREAD_MUTEX_INITIALIZER;
+static int fd;
+
+
+static void *
+tf (void *arg)
+{
+  struct flock fl =
+    {
+      .l_type = F_WRLCK,
+      .l_start = 0,
+      .l_whence = SEEK_SET,
+      .l_len = 10
+    };
+  if (TEMP_FAILURE_RETRY (fcntl (fd, F_SETLKW, &fl)) != 0)
+    {
+      puts ("fourth fcntl failed");
+      exit (1);
+    }
+
+  pthread_mutex_unlock (&lock);
+
+  pthread_mutex_lock (&lock2);
+
+  return NULL;
+}
+
+
+static int
+do_test (void)
+{
+  char tmp[] = "/tmp/tst-flock2-XXXXXX";
+
+  fd = mkstemp (tmp);
+  if (fd == -1)
+    {
+      puts ("mkstemp failed");
+      return 1;
+    }
+
+  unlink (tmp);
+
+  int i;
+  for (i = 0; i < 20; ++i)
+    write (fd, "foobar xyzzy", 12);
+
+  pthread_barrier_t *b;
+  b = mmap (NULL, sizeof (pthread_barrier_t), PROT_READ | PROT_WRITE,
+	    MAP_SHARED, fd, 0);
+  if (b == MAP_FAILED)
+    {
+      puts ("mmap failed");
+      return 1;
+    }
+
+  pthread_barrierattr_t ba;
+  if (pthread_barrierattr_init (&ba) != 0)
+    {
+      puts ("barrierattr_init failed");
+      return 1;
+    }
+
+  if (pthread_barrierattr_setpshared (&ba, PTHREAD_PROCESS_SHARED) != 0)
+    {
+      puts ("barrierattr_setpshared failed");
+      return 1;
+    }
+
+  if (pthread_barrier_init (b, &ba, 2) != 0)
+    {
+      puts ("barrier_init failed");
+      return 1;
+    }
+
+  if (pthread_barrierattr_destroy (&ba) != 0)
+    {
+      puts ("barrierattr_destroy failed");
+      return 1;
+    }
+
+  struct flock fl =
+    {
+      .l_type = F_WRLCK,
+      .l_start = 0,
+      .l_whence = SEEK_SET,
+      .l_len = 10
+    };
+  if (TEMP_FAILURE_RETRY (fcntl (fd, F_SETLKW, &fl)) != 0)
+    {
+      puts ("first fcntl failed");
+      return 1;
+    }
+
+  pid_t pid = fork ();
+  if (pid == -1)
+    {
+      puts ("fork failed");
+      return 1;
+    }
+
+  if (pid == 0)
+    {
+      /* Make sure the child does not stay around indefinitely.  */
+      alarm (10);
+
+      /* Try to get the lock.  */
+      if (TEMP_FAILURE_RETRY (fcntl (fd, F_SETLK, &fl)) == 0)
+	{
+	  puts ("child:  second flock succeeded");
+	  return 1;
+	}
+    }
+
+  pthread_barrier_wait (b);
+
+  if (pid != 0)
+    {
+      fl.l_type = F_UNLCK;
+      if (TEMP_FAILURE_RETRY (fcntl (fd, F_SETLKW, &fl)) != 0)
+	{
+	  puts ("third fcntl failed");
+	  return 1;
+	}
+    }
+
+  pthread_barrier_wait (b);
+
+  pthread_t th;
+  if (pid == 0)
+    {
+      if (pthread_mutex_lock (&lock) != 0)
+	{
+	  puts ("1st locking of lock failed");
+	  return 1;
+	}
+
+      if (pthread_mutex_lock (&lock2) != 0)
+	{
+	  puts ("1st locking of lock2 failed");
+	  return 1;
+	}
+
+      if (pthread_create (&th, NULL, tf, NULL) != 0)
+	{
+	  puts ("pthread_create failed");
+	  return 1;
+	}
+
+      if (pthread_mutex_lock (&lock) != 0)
+	{
+	  puts ("2nd locking of lock failed");
+	  return 1;
+	}
+
+      puts ("child locked file");
+    }
+
+  pthread_barrier_wait (b);
+
+  if (pid != 0)
+    {
+      fl.l_type = F_WRLCK;
+      if (TEMP_FAILURE_RETRY (fcntl (fd, F_SETLK, &fl)) == 0)
+	{
+	  puts ("fifth fcntl succeeded");
+	  return 1;
+	}
+
+      puts ("file locked by child");
+    }
+
+  pthread_barrier_wait (b);
+
+  if (pid == 0)
+    {
+      if (pthread_mutex_unlock (&lock2) != 0)
+	{
+	  puts ("unlock of lock2 failed");
+	  return 1;
+	}
+
+      if (pthread_join (th, NULL) != 0)
+	{
+	  puts ("join failed");
+	  return 1;
+	}
+
+      puts ("child's thread terminated");
+    }
+
+  pthread_barrier_wait (b);
+
+  if (pid != 0)
+    {
+      fl.l_type = F_WRLCK;
+      if (TEMP_FAILURE_RETRY (fcntl (fd, F_SETLK, &fl)) == 0)
+	{
+	  puts ("fifth fcntl succeeded");
+	  return 1;
+	}
+
+      puts ("file still locked");
+    }
+
+  pthread_barrier_wait (b);
+
+  if (pid == 0)
+    {
+      _exit (0);
+    }
+
+  int status;
+  if (TEMP_FAILURE_RETRY (waitpid (pid, &status, 0)) != pid)
+    {
+      puts ("waitpid failed");
+      return 1;
+    }
+  puts ("child terminated");
+
+  if (TEMP_FAILURE_RETRY (fcntl (fd, F_SETLKW, &fl)) != 0)
+    {
+      puts ("sixth fcntl failed");
+      return 1;
+    }
+
+  return status;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-fork1.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-fork1.c
new file mode 100644
index 00000000..33c4ed84
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-fork1.c
@@ -0,0 +1,120 @@
+/* Copyright (C) 2002, 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Roland McGrath , 2002.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+static void *
+thread_function (void * arg)
+{
+  int i = (intptr_t) arg;
+  int status;
+  pid_t pid;
+  pid_t pid2;
+
+  pid = fork ();
+  switch (pid)
+    {
+    case 0:
+      printf ("%ld for %d\n", (long int) getpid (), i);
+      struct timespec ts = { .tv_sec = 0, .tv_nsec = 100000000 * i };
+      nanosleep (&ts, NULL);
+      _exit (i);
+      break;
+    case -1:
+      printf ("fork: %m\n");
+      return (void *) 1l;
+      break;
+    }
+
+  pid2 = TEMP_FAILURE_RETRY (waitpid (pid, &status, 0));
+  if (pid2 != pid)
+    {
+      printf ("waitpid returned %ld, expected %ld\n",
+	      (long int) pid2, (long int) pid);
+      return (void *) 1l;
+    }
+
+  printf ("%ld with %d, expected %d\n",
+	  (long int) pid, WEXITSTATUS (status), i);
+
+  return WEXITSTATUS (status) == i ? NULL : (void *) 1l;
+}
+
+#define N 5
+static const int t[N] = { 7, 6, 5, 4, 3 };
+
+int
+main (void)
+{
+  pthread_t th[N];
+  int i;
+  int result = 0;
+  pthread_attr_t at;
+
+  if (pthread_attr_init (&at) != 0)
+    {
+      puts ("attr_init failed");
+      return 1;
+    }
+
+  if (pthread_attr_setstacksize (&at, 1 * 1024 * 1024) != 0)
+    {
+      puts ("attr_setstacksize failed");
+      return 1;
+    }
+
+  for (i = 0; i < N; ++i)
+    if (pthread_create (&th[i], NULL, thread_function,
+			(void *) (intptr_t) t[i]) != 0)
+      {
+	printf ("creation of thread %d failed\n", i);
+	exit (1);
+      }
+
+  if (pthread_attr_destroy (&at) != 0)
+    {
+      puts ("attr_destroy failed");
+      return 1;
+    }
+
+  for (i = 0; i < N; ++i)
+    {
+      void *v;
+      if (pthread_join (th[i], &v) != 0)
+	{
+	  printf ("join of thread %d failed\n", i);
+	  result = 1;
+	}
+      else if (v != NULL)
+	{
+	  printf ("join %d successful, but child failed\n", i);
+	  result = 1;
+	}
+      else
+	printf ("join %d successful\n", i);
+    }
+
+  return result;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-fork2.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-fork2.c
new file mode 100644
index 00000000..07d6c226
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-fork2.c
@@ -0,0 +1,90 @@
+/* Copyright (C) 2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Roland McGrath , 2002.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+static pid_t initial_pid;
+
+
+static void *
+tf (void *arg)
+{
+  if (getppid () != initial_pid)
+    {
+      printf ("getppid in thread returned %ld, expected %ld\n",
+	      (long int) getppid (), (long int) initial_pid);
+      return (void *) -1;
+    }
+
+  return NULL;
+}
+
+
+int
+main (void)
+{
+  initial_pid = getpid ();
+
+  pid_t child = fork ();
+  if (child == 0)
+    {
+      if (getppid () != initial_pid)
+	{
+	  printf ("first getppid returned %ld, expected %ld\n",
+		  (long int) getppid (), (long int) initial_pid);
+	  exit (1);
+	}
+
+      pthread_t th;
+      if (pthread_create (&th, NULL, tf, NULL) != 0)
+	{
+	  puts ("pthread_create failed");
+	  exit (1);
+	}
+
+      void *result;
+      if (pthread_join (th, &result) != 0)
+	{
+	  puts ("pthread_join failed");
+	  exit  (1);
+	}
+
+      exit (result == NULL ? 0 : 1);
+    }
+  else if (child == -1)
+    {
+      puts ("initial fork failed");
+      return 1;
+    }
+
+  int status;
+  if (TEMP_FAILURE_RETRY (waitpid (child, &status, 0)) != child)
+    {
+      printf ("waitpid failed: %m\n");
+      return 1;
+    }
+
+  return status;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-fork3.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-fork3.c
new file mode 100644
index 00000000..bc73853a
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-fork3.c
@@ -0,0 +1,107 @@
+/* Copyright (C) 2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Roland McGrath , 2002.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+static pid_t initial_pid;
+
+
+static void *
+tf2 (void *arg)
+{
+  if (getppid () != initial_pid)
+    {
+      printf ("getppid in thread returned %ld, expected %ld\n",
+	      (long int) getppid (), (long int) initial_pid);
+      return (void *) -1;
+    }
+
+  return NULL;
+}
+
+
+static void *
+tf1 (void *arg)
+{
+  pid_t child = fork ();
+  if (child == 0)
+    {
+      if (getppid () != initial_pid)
+	{
+	  printf ("first getppid returned %ld, expected %ld\n",
+		  (long int) getppid (), (long int) initial_pid);
+	  exit (1);
+	}
+
+      pthread_t th2;
+      if (pthread_create (&th2, NULL, tf2, NULL) != 0)
+	{
+	  puts ("child: pthread_create failed");
+	  exit (1);
+	}
+
+      void *result;
+      if (pthread_join (th2, &result) != 0)
+	{
+	  puts ("pthread_join failed");
+	  exit  (1);
+	}
+
+      exit (result == NULL ? 0 : 1);
+    }
+  else if (child == -1)
+    {
+      puts ("initial fork failed");
+      exit (1);
+    }
+
+  int status;
+  if (TEMP_FAILURE_RETRY (waitpid (child, &status, 0)) != child)
+    {
+      printf ("waitpid failed: %m\n");
+      exit (1);
+    }
+
+  exit (status);
+}
+
+
+int
+main (void)
+{
+  initial_pid = getpid ();
+
+  pthread_t th1;
+  if (pthread_create (&th1, NULL, tf1, NULL) != 0)
+    {
+      puts ("parent: pthread_create failed");
+      exit (1);
+    }
+
+  /* This call should never return.  */
+  pthread_join (th1, NULL);
+
+  return 1;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-fork4.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-fork4.c
new file mode 100644
index 00000000..cca19f40
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-fork4.c
@@ -0,0 +1,65 @@
+/* Test of fork updating child universe's pthread structures.
+   Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+static int
+do_test (void)
+{
+  pthread_t me = pthread_self ();
+
+  pid_t pid = fork ();
+
+  if (pid < 0)
+    {
+      printf ("fork: %m\n");
+      return 1;
+    }
+
+  if (pid == 0)
+    {
+      int err = pthread_kill (me, SIGTERM);
+      printf ("pthread_kill returned: %s\n", strerror (err));
+      return 3;
+    }
+
+  int status;
+  errno = 0;
+  if (wait (&status) != pid)
+    printf ("wait failed: %m\n");
+  else if (WIFSIGNALED (status) && WTERMSIG (status) == SIGTERM)
+    {
+      printf ("child correctly died with SIGTERM\n");
+      return 0;
+    }
+  else
+    printf ("child died with bad status %#x\n", status);
+
+  return 1;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-getpid1.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-getpid1.c
new file mode 100644
index 00000000..4d25b0de
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-getpid1.c
@@ -0,0 +1,122 @@
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#ifndef TEST_CLONE_FLAGS
+#define TEST_CLONE_FLAGS 0
+#endif
+
+static int sig;
+
+static int
+f (void *a)
+{
+  puts ("in f");
+  union sigval sival;
+  sival.sival_int = getpid ();
+  printf ("pid = %d\n", sival.sival_int);
+  if (sigqueue (getppid (), sig, sival) != 0)
+    return 1;
+  return 0;
+}
+
+
+static int
+do_test (void)
+{
+  int mypid = getpid ();
+
+  sig = SIGRTMIN;
+  sigset_t ss;
+  sigemptyset (&ss);
+  sigaddset (&ss, sig);
+  if (sigprocmask (SIG_BLOCK, &ss, NULL) != 0)
+    {
+      printf ("sigprocmask failed: %m\n");
+      return 1;
+    }
+
+#ifdef __ia64__
+  extern int __clone2 (int (*__fn) (void *__arg), void *__child_stack_base,
+		       size_t __child_stack_size, int __flags,
+		       void *__arg, ...);
+  char st[256 * 1024] __attribute__ ((aligned));
+  pid_t p = __clone2 (f, st, sizeof (st), TEST_CLONE_FLAGS, 0);
+#else
+  char st[128 * 1024] __attribute__ ((aligned));
+# if _STACK_GROWS_DOWN
+  pid_t p = clone (f, st + sizeof (st), TEST_CLONE_FLAGS, 0);
+# elif _STACK_GROWS_UP
+  pid_t p = clone (f, st, TEST_CLONE_FLAGS, 0);
+# else
+#  error "Define either _STACK_GROWS_DOWN or _STACK_GROWS_UP"
+# endif
+#endif
+  if (p == -1)
+    {
+      printf("clone failed: %m\n");
+      return 1;
+    }
+  printf ("new thread: %d\n", (int) p);
+
+  siginfo_t si;
+  do
+    if (sigwaitinfo (&ss, &si) < 0)
+      {
+	printf("sigwaitinfo failed: %m\n");
+	kill (p, SIGKILL);
+	return 1;
+      }
+  while  (si.si_signo != sig || si.si_code != SI_QUEUE);
+
+  int e;
+  if (waitpid (p, &e, __WCLONE) != p)
+    {
+      puts ("waitpid failed");
+      kill (p, SIGKILL);
+      return 1;
+    }
+  if (!WIFEXITED (e))
+    {
+      if (WIFSIGNALED (e))
+	printf ("died from signal %s\n", strsignal (WTERMSIG (e)));
+      else
+	puts ("did not terminate correctly");
+      return 1;
+    }
+  if (WEXITSTATUS (e) != 0)
+    {
+      printf ("exit code %d\n", WEXITSTATUS (e));
+      return 1;
+    }
+
+  if (si.si_int != (int) p)
+    {
+      printf ("expected PID %d, got si_int %d\n", (int) p, si.si_int);
+      kill (p, SIGKILL);
+      return 1;
+    }
+
+  if (si.si_pid != p)
+    {
+      printf ("expected PID %d, got si_pid %d\n", (int) p, (int) si.si_pid);
+      kill (p, SIGKILL);
+      return 1;
+    }
+
+  if (getpid () != mypid)
+    {
+      puts ("my PID changed");
+      return 1;
+    }
+
+  return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-getpid2.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-getpid2.c
new file mode 100644
index 00000000..fc98cb60
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-getpid2.c
@@ -0,0 +1,2 @@
+#define TEST_CLONE_FLAGS CLONE_VM
+#include "tst-getpid1.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-getpid3.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-getpid3.c
new file mode 100644
index 00000000..f1e77f6b
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-getpid3.c
@@ -0,0 +1,114 @@
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+static pid_t pid;
+
+static void *
+pid_thread (void *arg)
+{
+  if (pid != getpid ())
+    {
+      printf ("pid wrong in thread: should be %d, is %d\n",
+	      (int) pid, (int) getpid ());
+      return (void *) 1L;
+    }
+
+  return NULL;
+}
+
+static int
+do_test (void)
+{
+  pid = getpid ();
+
+  pthread_t thr;
+  int ret = pthread_create (&thr, NULL, pid_thread, NULL);
+  if (ret)
+    {
+      printf ("pthread_create failed: %d\n", ret);
+      return 1;
+    }
+
+  void *thr_ret;
+  ret = pthread_join (thr, &thr_ret);
+  if (ret)
+    {
+      printf ("pthread_create failed: %d\n", ret);
+      return 1;
+    }
+  else if (thr_ret)
+    {
+      printf ("thread getpid failed\n");
+      return 1;
+    }
+
+  pid_t child = fork ();
+  if (child == -1)
+    {
+      printf ("fork failed: %m\n");
+      return 1;
+    }
+  else if (child == 0)
+    {
+      if (pid == getpid ())
+	{
+	  puts ("pid did not change after fork");
+	  exit (1);
+	}
+
+      pid = getpid ();
+      ret = pthread_create (&thr, NULL, pid_thread, NULL);
+      if (ret)
+	{
+	  printf ("pthread_create failed: %d\n", ret);
+	  return 1;
+	}
+
+      ret = pthread_join (thr, &thr_ret);
+      if (ret)
+	{
+	  printf ("pthread_create failed: %d\n", ret);
+	  return 1;
+	}
+      else if (thr_ret)
+	{
+	  printf ("thread getpid failed\n");
+	  return 1;
+	}
+
+      return 0;
+    }
+
+  int status;
+  if (TEMP_FAILURE_RETRY (waitpid (child, &status, 0)) != child)
+    {
+      puts ("waitpid failed");
+      kill (child, SIGKILL);
+      return 1;
+    }
+
+  if (!WIFEXITED (status))
+    {
+      if (WIFSIGNALED (status))
+	printf ("died from signal %s\n", strsignal (WTERMSIG (status)));
+      else
+	puts ("did not terminate correctly");
+      return 1;
+    }
+  if (WEXITSTATUS (status) != 0)
+    {
+      printf ("exit code %d\n", WEXITSTATUS (status));
+      return 1;
+    }
+
+  return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-initializers1-c89.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-initializers1-c89.c
new file mode 100644
index 00000000..7c27c1d5
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-initializers1-c89.c
@@ -0,0 +1 @@
+#include "tst-initializers1.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-initializers1-c99.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-initializers1-c99.c
new file mode 100644
index 00000000..7c27c1d5
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-initializers1-c99.c
@@ -0,0 +1 @@
+#include "tst-initializers1.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-initializers1-gnu89.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-initializers1-gnu89.c
new file mode 100644
index 00000000..7c27c1d5
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-initializers1-gnu89.c
@@ -0,0 +1 @@
+#include "tst-initializers1.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-initializers1-gnu99.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-initializers1-gnu99.c
new file mode 100644
index 00000000..7c27c1d5
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-initializers1-gnu99.c
@@ -0,0 +1 @@
+#include "tst-initializers1.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-initializers1.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-initializers1.c
new file mode 100644
index 00000000..ccd27286
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-initializers1.c
@@ -0,0 +1,48 @@
+/* Copyright (C) 2005 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek , 2005.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+
+pthread_mutex_t mtx_normal = PTHREAD_MUTEX_INITIALIZER;
+pthread_mutex_t mtx_recursive = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
+pthread_mutex_t mtx_errorchk = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;
+pthread_mutex_t mtx_adaptive = PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP;
+pthread_rwlock_t rwl_normal = PTHREAD_RWLOCK_INITIALIZER;
+pthread_rwlock_t rwl_writer
+  = PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP;
+pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
+
+int
+main (void)
+{
+  if (mtx_normal.__data.__kind != PTHREAD_MUTEX_TIMED_NP)
+    return 1;
+  if (mtx_recursive.__data.__kind != PTHREAD_MUTEX_RECURSIVE_NP)
+    return 1;
+  if (mtx_errorchk.__data.__kind != PTHREAD_MUTEX_ERRORCHECK_NP)
+    return 1;
+  if (mtx_adaptive.__data.__kind != PTHREAD_MUTEX_ADAPTIVE_NP)
+    return 1;
+  if (rwl_normal.__data.__flags != PTHREAD_RWLOCK_PREFER_READER_NP)
+    return 1;
+  if (rwl_writer.__data.__flags
+      != PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP)
+    return 1;
+  return 0;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-join1.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-join1.c
new file mode 100644
index 00000000..95a78ba0
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-join1.c
@@ -0,0 +1,83 @@
+/* Copyright (C) 2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2002.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+
+
+static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
+
+
+static void *
+tf (void *arg)
+{
+  pthread_t mh = (pthread_t) arg;
+  void *result;
+
+  if (pthread_mutex_unlock (&lock) != 0)
+    {
+      puts ("unlock failed");
+      exit (1);
+    }
+
+  if (pthread_join (mh, &result) != 0)
+    {
+      puts ("join failed");
+      exit (1);
+    }
+
+  if (result != (void *) 42l)
+    {
+      printf ("result wrong: expected %p, got %p\n", (void *) 42, result);
+      exit (1);
+    }
+
+  exit (0);
+}
+
+
+static int
+do_test (void)
+{
+  pthread_t th;
+
+  if (pthread_mutex_lock (&lock) != 0)
+    {
+      puts ("1st lock failed");
+      exit (1);
+    }
+
+  if (pthread_create (&th, NULL, tf, (void *) pthread_self ()) != 0)
+    {
+      puts ("create failed");
+      exit (1);
+    }
+
+  if (pthread_mutex_lock (&lock) != 0)
+    {
+      puts ("2nd lock failed");
+      exit (1);
+    }
+
+  pthread_exit ((void *) 42);
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-join2.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-join2.c
new file mode 100644
index 00000000..2cfab8b0
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-join2.c
@@ -0,0 +1,104 @@
+/* Copyright (C) 2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2002.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
+
+
+static void *
+tf (void *arg)
+{
+  if (pthread_mutex_lock (&lock) != 0)
+    {
+      puts ("child: mutex_lock failed");
+      return NULL;
+    }
+
+  return (void *) 42l;
+}
+
+
+static int
+do_test (void)
+{
+  pthread_t th;
+
+  if (pthread_mutex_lock (&lock) != 0)
+    {
+      puts ("mutex_lock failed");
+      exit (1);
+    }
+
+  if (pthread_create (&th, NULL, tf, NULL) != 0)
+    {
+      puts ("mutex_create failed");
+      exit (1);
+    }
+
+  void *status;
+  int val = pthread_tryjoin_np (th, &status);
+  if (val == 0)
+    {
+      puts ("1st tryjoin succeeded");
+      exit (1);
+    }
+  else if (val != EBUSY)
+    {
+      puts ("1st tryjoin didn't return EBUSY");
+      exit (1);
+    }
+
+  if (pthread_mutex_unlock (&lock) != 0)
+    {
+      puts ("mutex_unlock failed");
+      exit (1);
+    }
+
+  while ((val = pthread_tryjoin_np (th, &status)) != 0)
+    {
+      if (val != EBUSY)
+	{
+	  printf ("tryjoin returned %s (%d), expected only 0 or EBUSY\n",
+		  strerror (val), val);
+	  exit (1);
+	}
+
+      /* Delay minimally.  */
+      struct timespec ts = { .tv_sec = 0, .tv_nsec = 10000000 };
+      nanosleep (&ts, NULL);
+    }
+
+  if (status != (void *) 42l)
+    {
+      printf ("return value %p, expected %p\n", status, (void *) 42l);
+      exit (1);
+    }
+
+  return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-join3.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-join3.c
new file mode 100644
index 00000000..df1135fb
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-join3.c
@@ -0,0 +1,123 @@
+/* Copyright (C) 2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2002.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
+
+
+static void *
+tf (void *arg)
+{
+  if (pthread_mutex_lock (&lock) != 0)
+    {
+      puts ("child: mutex_lock failed");
+      return NULL;
+    }
+
+  return (void *) 42l;
+}
+
+
+static int
+do_test (void)
+{
+  pthread_t th;
+
+  if (pthread_mutex_lock (&lock) != 0)
+    {
+      puts ("mutex_lock failed");
+      exit (1);
+    }
+
+  if (pthread_create (&th, NULL, tf, NULL) != 0)
+    {
+      puts ("mutex_create failed");
+      exit (1);
+    }
+
+  void *status;
+  struct timespec ts;
+  struct timeval tv;
+  (void) gettimeofday (&tv, NULL);
+  TIMEVAL_TO_TIMESPEC (&tv, &ts);
+  ts.tv_nsec += 200000000;
+  if (ts.tv_nsec >= 1000000000)
+    {
+      ts.tv_nsec -= 1000000000;
+      ++ts.tv_sec;
+    }
+  int val = pthread_timedjoin_np (th, &status, &ts);
+  if (val == 0)
+    {
+      puts ("1st timedjoin succeeded");
+      exit (1);
+    }
+  else if (val != ETIMEDOUT)
+    {
+      puts ("1st timedjoin didn't return ETIMEDOUT");
+      exit (1);
+    }
+
+  if (pthread_mutex_unlock (&lock) != 0)
+    {
+      puts ("mutex_unlock failed");
+      exit (1);
+    }
+
+  while (1)
+    {
+      (void) gettimeofday (&tv, NULL);
+      TIMEVAL_TO_TIMESPEC (&tv, &ts);
+      ts.tv_nsec += 200000000;
+      if (ts.tv_nsec >= 1000000000)
+	{
+	  ts.tv_nsec -= 1000000000;
+	  ++ts.tv_sec;
+	}
+
+      val = pthread_timedjoin_np (th, &status, &ts);
+      if (val == 0)
+	break;
+
+      if (val != ETIMEDOUT)
+	{
+	  printf ("timedjoin returned %s (%d), expected only 0 or ETIMEDOUT\n",
+		  strerror (val), val);
+	  exit (1);
+	}
+    }
+
+  if (status != (void *) 42l)
+    {
+      printf ("return value %p, expected %p\n", status, (void *) 42l);
+      exit (1);
+    }
+
+  return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-join4.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-join4.c
new file mode 100644
index 00000000..b13a5101
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-join4.c
@@ -0,0 +1,125 @@
+/* Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+
+
+static pthread_barrier_t bar;
+
+
+static void *
+tf (void *arg)
+{
+  if (pthread_barrier_wait (&bar) != 0)
+    {
+      puts ("tf: barrier_wait failed");
+      exit (1);
+    }
+
+  return (void *) 1l;
+}
+
+
+static int
+do_test (void)
+{
+  if (pthread_barrier_init (&bar, NULL, 3) != 0)
+    {
+      puts ("barrier_init failed");
+      exit (1);
+    }
+
+  pthread_attr_t a;
+
+  if (pthread_attr_init (&a) != 0)
+    {
+      puts ("attr_init failed");
+      exit (1);
+    }
+
+  if (pthread_attr_setstacksize (&a, 1 * 1024 * 1024) != 0)
+    {
+      puts ("attr_setstacksize failed");
+      return 1;
+    }
+
+  pthread_t th[2];
+
+  if (pthread_create (&th[0], &a, tf, NULL) != 0)
+    {
+      puts ("1st create failed");
+      exit (1);
+    }
+
+  if (pthread_attr_setdetachstate (&a, PTHREAD_CREATE_DETACHED) != 0)
+    {
+      puts ("attr_setdetachstate failed");
+      exit (1);
+    }
+
+  if (pthread_create (&th[1], &a, tf, NULL) != 0)
+    {
+      puts ("1st create failed");
+      exit (1);
+    }
+
+  if (pthread_attr_destroy (&a) != 0)
+    {
+      puts ("attr_destroy failed");
+      exit (1);
+    }
+
+  if (pthread_detach (th[0]) != 0)
+    {
+      puts ("could not detach 1st thread");
+      exit (1);
+    }
+
+  int err = pthread_detach (th[0]);
+  if (err == 0)
+    {
+      puts ("second detach of 1st thread succeeded");
+      exit (1);
+    }
+  if (err != EINVAL)
+    {
+      printf ("second detach of 1st thread returned %d, not EINVAL\n", err);
+      exit (1);
+    }
+
+  err = pthread_detach (th[1]);
+  if (err == 0)
+    {
+      puts ("detach of 2nd thread succeeded");
+      exit (1);
+    }
+  if (err != EINVAL)
+    {
+      printf ("detach of 2nd thread returned %d, not EINVAL\n", err);
+      exit (1);
+    }
+
+  exit (0);
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-join5.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-join5.c
new file mode 100644
index 00000000..b08af6e4
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-join5.c
@@ -0,0 +1,143 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+
+
+static void *
+tf1 (void *arg)
+{
+  pthread_join ((pthread_t) arg, NULL);
+
+  puts ("1st join returned");
+
+  return (void *) 1l;
+}
+
+
+static void *
+tf2 (void *arg)
+{
+  int a;
+  a = pthread_join ((pthread_t) arg, NULL);
+
+  puts ("2nd join returned");
+  printf("a = %i\n", a);
+
+  return (void *) 1l;
+}
+
+
+static int
+do_test (void)
+{
+  pthread_t th;
+
+  int err = pthread_join (pthread_self (), NULL);
+  if (err == 0)
+    {
+      puts ("1st circular join succeeded");
+      exit (1);
+    }
+  if (err != EDEADLK)
+    {
+      printf ("1st circular join %d, not EDEADLK\n", err);
+      exit (1);
+    }
+
+  if (pthread_create (&th, NULL, tf1, (void *) pthread_self ()) != 0)
+    {
+      puts ("1st create failed");
+      exit (1);
+    }
+
+  if (pthread_cancel (th) != 0)
+    {
+      puts ("cannot cancel 1st thread");
+      exit (1);
+    }
+
+  void *r;
+  err = pthread_join (th, &r);
+  if (err != 0)
+    {
+      printf ("cannot join 1st thread: %d\n", err);
+      exit (1);
+    }
+  if (r != PTHREAD_CANCELED)
+    {
+      puts ("1st thread not canceled");
+      exit (1);
+    }
+
+  err = pthread_join (pthread_self (), NULL);
+  if (err == 0)
+    {
+      puts ("2nd circular join succeeded");
+      exit (1);
+    }
+  if (err != EDEADLK)
+    {
+      printf ("2nd circular join %d, not EDEADLK\n", err);
+      exit (1);
+    }
+
+  if (pthread_create (&th, NULL, tf2, (void *) pthread_self ()) != 0)
+    {
+      puts ("2nd create failed");
+      exit (1);
+    }
+
+  if (pthread_cancel (th) != 0)
+    {
+      puts ("cannot cancel 2nd thread");
+      exit (1);
+    }
+
+  if (pthread_join (th, &r) != 0)
+    {
+      puts ("cannot join 2nd thread");
+      exit (1);
+    }
+  if (r != PTHREAD_CANCELED)
+    {
+      puts ("2nd thread not canceled");
+      exit (1);
+    }
+
+  err = pthread_join (pthread_self (), NULL);
+  if (err == 0)
+    {
+      puts ("2nd circular join succeeded");
+      exit (1);
+    }
+  if (err != EDEADLK)
+    {
+      printf ("2nd circular join %d, not EDEADLK\n", err);
+      exit (1);
+    }
+
+  exit (0);
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-join6.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-join6.c
new file mode 100644
index 00000000..0c9e7c05
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-join6.c
@@ -0,0 +1,2 @@
+#define WAIT_IN_CHILD 1
+#include "tst-join5.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-key1.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-key1.c
new file mode 100644
index 00000000..dfbe5841
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-key1.c
@@ -0,0 +1,89 @@
+/* Copyright (C) 2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2002.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+int
+do_test (void)
+{
+  int max;
+#ifdef PTHREAD_KEYS_MAX
+  max = PTHREAD_KEYS_MAX;
+#else
+  max = _POSIX_THREAD_KEYS_MAX;
+#endif
+  pthread_key_t *keys = alloca (max * sizeof (pthread_key_t));
+
+  int i;
+  for (i = 0; i < max; ++i)
+    if (pthread_key_create (&keys[i], NULL) != 0)
+      {
+	write (2, "key_create failed\n", 18);
+	_exit (1);
+      }
+    else
+      {
+	printf ("created key %d\n", i);
+
+	if (pthread_setspecific (keys[i], (const void *) (i + 100l)) != 0)
+	  {
+	    write (2, "setspecific failed\n", 19);
+	    _exit (1);
+	  }
+      }
+
+  for (i = 0; i < max; ++i)
+    {
+      if (pthread_getspecific (keys[i]) != (void *) (i + 100l))
+	{
+	  write (2, "getspecific failed\n", 19);
+	  _exit (1);
+	}
+
+      if (pthread_key_delete (keys[i]) != 0)
+	{
+	  write (2, "key_delete failed\n", 18);
+	  _exit (1);
+	}
+    }
+
+  /* Now it must be once again possible to allocate keys.  */
+  if (pthread_key_create (&keys[0], NULL) != 0)
+    {
+      write (2, "2nd key_create failed\n", 22);
+      _exit (1);
+    }
+
+  if (pthread_key_delete (keys[0]) != 0)
+    {
+      write (2, "2nd key_delete failed\n", 22);
+      _exit (1);
+    }
+
+  return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-key2.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-key2.c
new file mode 100644
index 00000000..c5493322
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-key2.c
@@ -0,0 +1,115 @@
+/* Copyright (C) 2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2002.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+
+#define N 2
+
+
+static int cnt0;
+static void
+f0 (void *p)
+{
+  ++cnt0;
+}
+
+
+static int cnt1;
+static void
+f1 (void *p)
+{
+  ++cnt1;
+}
+
+
+static void (*fcts[N]) (void *) =
+{
+  f0,
+  f1
+};
+
+
+static void *
+tf (void *arg)
+{
+  pthread_key_t *key = (pthread_key_t *) arg;
+
+  if (pthread_setspecific (*key, (void *) -1l) != 0)
+    {
+      write (2, "setspecific failed\n", 19);
+      _exit (1);
+    }
+
+  return NULL;
+}
+
+
+int
+do_test (void)
+{
+  pthread_key_t keys[N];
+
+  int i;
+  for (i = 0; i < N; ++i)
+    if (pthread_key_create (&keys[i], fcts[i]) != 0)
+      {
+	write (2, "key_create failed\n", 18);
+	_exit (1);
+      }
+
+  pthread_t th;
+  if (pthread_create (&th, NULL, tf, &keys[1]) != 0)
+    {
+      write (2, "create failed\n", 14);
+      _exit (1);
+    }
+
+  if (pthread_join (th, NULL) != 0)
+    {
+      write (2, "join failed\n", 12);
+      _exit (1);
+    }
+
+  if (cnt0 != 0)
+    {
+      write (2, "cnt0 != 0\n", 10);
+      _exit (1);
+    }
+
+  if (cnt1 != 1)
+    {
+      write (2, "cnt1 != 1\n", 10);
+      _exit (1);
+    }
+
+  for (i = 0; i < N; ++i)
+    if (pthread_key_delete (keys[i]) != 0)
+      {
+	write (2, "key_delete failed\n", 18);
+	_exit (1);
+      }
+
+  return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-key3.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-key3.c
new file mode 100644
index 00000000..73cb7417
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-key3.c
@@ -0,0 +1,156 @@
+/* Copyright (C) 2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2002.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+
+#define N 2
+
+
+static int cnt0;
+static void
+f0 (void *p)
+{
+  ++cnt0;
+}
+
+
+static int cnt1;
+static void
+f1 (void *p)
+{
+  ++cnt1;
+}
+
+
+static void (*fcts[N]) (void *) =
+{
+  f0,
+  f1
+};
+
+
+static pthread_barrier_t b;
+
+
+static void *
+tf (void *arg)
+{
+  pthread_key_t *key = (pthread_key_t *) arg;
+
+  if (pthread_setspecific (*key, (void *) -1l) != 0)
+    {
+      write (2, "setspecific failed\n", 19);
+      _exit (1);
+    }
+
+  pthread_barrier_wait (&b);
+
+  const struct timespec t = { .tv_sec = 1000, .tv_nsec = 0 };
+  while (1)
+    nanosleep (&t, NULL);
+
+  /* NOTREACHED */
+  return NULL;
+}
+
+
+int
+do_test (void)
+{
+  pthread_key_t keys[N];
+
+  int i;
+  for (i = 0; i < N; ++i)
+    if (pthread_key_create (&keys[i], fcts[i]) != 0)
+      {
+	write (2, "key_create failed\n", 18);
+	_exit (1);
+      }
+
+  if (pthread_barrier_init (&b, NULL, 2) != 0)
+    {
+      write (2, "barrier_init failed\n", 20);
+      _exit (1);
+    }
+
+  pthread_t th;
+  if (pthread_create (&th, NULL, tf, &keys[1]) != 0)
+    {
+      write (2, "create failed\n", 14);
+      _exit (1);
+    }
+
+  pthread_barrier_wait (&b);
+
+  if (pthread_cancel (th) != 0)
+    {
+      write (2, "cancel failed\n", 14);
+      _exit (1);
+    }
+
+  void *status;
+  if (pthread_join (th, &status) != 0)
+    {
+      write (2, "join failed\n", 12);
+      _exit (1);
+    }
+
+  if (status != PTHREAD_CANCELED)
+    {
+      write (2, "thread not canceled\n", 20);
+      _exit (1);
+    }
+
+  /* Note that the TSD destructors not necessarily have to have
+     finished by the time pthread_join returns.  At least according to
+     POSIX.  We implement the stronger requirement that they indeed
+     have run and therefore these tests succeed.  */
+  if (cnt0 != 0)
+    {
+      write (2, "cnt0 != 0\n", 10);
+      _exit (1);
+    }
+
+  if (cnt1 != 1)
+    {
+      write (2, "cnt1 != 1\n", 10);
+      _exit (1);
+    }
+
+  for (i = 0; i < N; ++i)
+    if (pthread_key_delete (keys[i]) != 0)
+      {
+	write (2, "key_delete failed\n", 18);
+	_exit (1);
+      }
+
+  if (pthread_barrier_destroy (&b) != 0)
+    {
+      write (2, "barrier_destroy failed\n", 23);
+      _exit (1);
+    }
+
+  return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-key4.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-key4.c
new file mode 100644
index 00000000..0a5b448e
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-key4.c
@@ -0,0 +1,137 @@
+/* Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+#ifdef PTHREAD_KEYS_MAX
+const int max = PTHREAD_KEYS_MAX;
+#else
+const int max = _POSIX_THREAD_KEYS_MAX;
+#endif
+static pthread_key_t *keys;
+
+
+static void *
+tf1 (void *arg)
+{
+  int i;
+  for (i = 0; i < max; ++i)
+    if (pthread_setspecific (keys[i], (void *) (long int) (i + 1)) != 0)
+      {
+	puts ("setspecific failed");
+	exit (1);
+      }
+
+  return NULL;
+}
+
+
+static void *
+tf2 (void *arg)
+{
+  int i;
+  for (i = 0; i < max; ++i)
+    if (pthread_getspecific (keys[i]) != NULL)
+      {
+	printf ("getspecific for key %d not NULL\n", i);
+	exit (1);
+      }
+
+  return NULL;
+}
+
+
+static int
+do_test (void)
+{
+  keys = alloca (max * sizeof (pthread_key_t));
+
+  int i;
+  for (i = 0; i < max; ++i)
+    if (pthread_key_create (&keys[i], NULL) != 0)
+      {
+	puts ("key_create failed");
+	exit (1);
+      }
+
+  pthread_attr_t a;
+
+  if (pthread_attr_init (&a) != 0)
+    {
+      puts ("attr_init failed");
+      exit (1);
+    }
+
+  if (pthread_attr_setstacksize (&a, 1 * 1024 * 1024) != 0)
+    {
+      puts ("attr_setstacksize failed");
+      return 1;
+    }
+
+  for (i = 0; i < 10; ++i)
+    {
+      int j;
+#define N 2
+      pthread_t th[N];
+      for (j = 0; j < N; ++j)
+	if (pthread_create (&th[j], NULL, tf1, NULL) != 0)
+	  {
+	    puts ("1st create failed");
+	    exit (1);
+	  }
+
+      for (j = 0; j < N; ++j)
+	if (pthread_join (th[j], NULL) != 0)
+	  {
+	    puts ("1st join failed");
+	    exit (1);
+	  }
+
+      for (j = 0; j < N; ++j)
+	if (pthread_create (&th[j], NULL, tf2, NULL) != 0)
+	  {
+	    puts ("2nd create failed");
+	    exit (1);
+	  }
+
+      for (j = 0; j < N; ++j)
+	if (pthread_join (th[j], NULL) != 0)
+	  {
+	    puts ("2nd join failed");
+	    exit (1);
+	  }
+    }
+
+  if (pthread_attr_destroy (&a) != 0)
+    {
+      puts ("attr_destroy failed");
+      exit (1);
+    }
+
+  return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-kill1.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-kill1.c
new file mode 100644
index 00000000..9eaf29be
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-kill1.c
@@ -0,0 +1,100 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+
+
+static pthread_cond_t c = PTHREAD_COND_INITIALIZER;
+static pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
+static pthread_barrier_t b;
+
+static void *
+tf (void *a)
+{
+  if (pthread_mutex_lock (&m) != 0)
+    {
+      puts ("child: mutex_lock failed");
+      exit (1);
+    }
+
+  int e = pthread_barrier_wait (&b);
+  if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("child: barrier_wait failed");
+      exit (1);
+    }
+
+  /* This call should never return.  */
+  pthread_cond_wait (&c, &m);
+
+  return NULL;
+}
+
+
+int
+do_test (void)
+{
+  pthread_t th;
+
+  if (pthread_barrier_init (&b, NULL, 2) != 0)
+    {
+      puts ("barrier_init failed");
+      exit (1);
+    }
+
+  if (pthread_create (&th, NULL, tf, NULL) != 0)
+    {
+      puts ("create failed");
+      exit (1);
+    }
+
+  int e = pthread_barrier_wait (&b);
+  if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("barrier_wait failed");
+      exit (1);
+    }
+
+  if (pthread_mutex_lock (&m) != 0)
+    {
+      puts ("mutex_lock failed");
+      exit (1);
+    }
+
+  /* Send the thread a signal which it doesn't catch and which will
+     cause the process to terminate.  */
+  if (pthread_kill (th, SIGUSR1) != 0)
+    {
+      puts ("kill failed");
+      exit (1);
+    }
+
+  /* This call should never return.  */
+  pthread_join (th, NULL);
+
+  return 0;
+}
+
+
+#define EXPECTED_SIGNAL SIGUSR1
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-kill2.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-kill2.c
new file mode 100644
index 00000000..1e3dc410
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-kill2.c
@@ -0,0 +1,139 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+static pthread_cond_t c = PTHREAD_COND_INITIALIZER;
+static pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
+static pthread_barrier_t b;
+
+static void *
+tf (void *a)
+{
+  /* Block SIGUSR1.  */
+  sigset_t ss;
+
+  sigemptyset (&ss);
+  sigaddset (&ss, SIGUSR1);
+  if (pthread_sigmask (SIG_BLOCK, &ss, NULL) != 0)
+    {
+      puts ("child: sigmask failed");
+      exit (1);
+    }
+
+  if (pthread_mutex_lock (&m) != 0)
+    {
+      puts ("child: mutex_lock failed");
+      exit (1);
+    }
+
+  int e = pthread_barrier_wait (&b);
+  if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("child: barrier_wait failed");
+      exit (1);
+    }
+
+  /* Compute timeout.  */
+  struct timeval tv;
+  (void) gettimeofday (&tv, NULL);
+  struct timespec ts;
+  TIMEVAL_TO_TIMESPEC (&tv, &ts);
+  /* Timeout: 1sec.  */
+  ts.tv_sec += 1;
+
+  /* This call should never return.  */
+  if (pthread_cond_timedwait (&c, &m, &ts) != ETIMEDOUT)
+    {
+      puts ("cond_timedwait didn't time out");
+      exit (1);
+    }
+
+  return NULL;
+}
+
+
+int
+do_test (void)
+{
+  pthread_t th;
+
+  if (pthread_barrier_init (&b, NULL, 2) != 0)
+    {
+      puts ("barrier_init failed");
+      exit (1);
+    }
+
+  if (pthread_create (&th, NULL, tf, NULL) != 0)
+    {
+      puts ("create failed");
+      exit (1);
+    }
+
+  int e = pthread_barrier_wait (&b);
+  if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("barrier_wait failed");
+      exit (1);
+    }
+
+  if (pthread_mutex_lock (&m) != 0)
+    {
+      puts ("mutex_lock failed");
+      exit (1);
+    }
+
+  /* Send the thread a signal which it has blocked.  */
+  if (pthread_kill (th, SIGUSR1) != 0)
+    {
+      puts ("kill failed");
+      exit (1);
+    }
+
+  if (pthread_mutex_unlock (&m) != 0)
+    {
+      puts ("mutex_unlock failed");
+      exit (1);
+    }
+
+  void *r;
+  if (pthread_join (th, &r) != 0)
+    {
+      puts ("join failed");
+      exit (1);
+    }
+  if (r != NULL)
+    {
+      puts ("return value wrong");
+      exit (1);
+    }
+
+  return 0;
+}
+
+
+#define TIMEOUT 5
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-kill3.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-kill3.c
new file mode 100644
index 00000000..9ea8d553
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-kill3.c
@@ -0,0 +1,159 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+static pthread_cond_t c = PTHREAD_COND_INITIALIZER;
+static pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
+static pthread_barrier_t b;
+
+
+static void
+handler (int sig)
+{
+  write (1, "handler called\n", 15);
+  _exit (1);
+}
+
+
+static void *
+tf (void *a)
+{
+  /* Block SIGUSR1.  */
+  sigset_t ss;
+
+  sigemptyset (&ss);
+  sigaddset (&ss, SIGUSR1);
+  if (pthread_sigmask (SIG_BLOCK, &ss, NULL) != 0)
+    {
+      puts ("child: sigmask failed");
+      exit (1);
+    }
+
+  if (pthread_mutex_lock (&m) != 0)
+    {
+      puts ("child: mutex_lock failed");
+      exit (1);
+    }
+
+  int e = pthread_barrier_wait (&b);
+  if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("child: barrier_wait failed");
+      exit (1);
+    }
+
+  /* Compute timeout.  */
+  struct timeval tv;
+  (void) gettimeofday (&tv, NULL);
+  struct timespec ts;
+  TIMEVAL_TO_TIMESPEC (&tv, &ts);
+  /* Timeout: 1sec.  */
+  ts.tv_sec += 1;
+
+  /* This call should never return.  */
+  if (pthread_cond_timedwait (&c, &m, &ts) != ETIMEDOUT)
+    {
+      puts ("cond_timedwait didn't time out");
+      exit (1);
+    }
+
+  return NULL;
+}
+
+
+int
+do_test (void)
+{
+  pthread_t th;
+
+  struct sigaction sa;
+  sigemptyset (&sa.sa_mask);
+  sa.sa_flags = 0;
+  sa.sa_handler = handler;
+  if (sigaction (SIGUSR1, &sa, NULL) != 0)
+    {
+      puts ("sigaction failed");
+      exit (1);
+    }
+
+  if (pthread_barrier_init (&b, NULL, 2) != 0)
+    {
+      puts ("barrier_init failed");
+      exit (1);
+    }
+
+  if (pthread_create (&th, NULL, tf, NULL) != 0)
+    {
+      puts ("create failed");
+      exit (1);
+    }
+
+  int e = pthread_barrier_wait (&b);
+  if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("barrier_wait failed");
+      exit (1);
+    }
+
+  if (pthread_mutex_lock (&m) != 0)
+    {
+      puts ("mutex_lock failed");
+      exit (1);
+    }
+
+  /* Send the thread a signal which it has blocked.  */
+  if (pthread_kill (th, SIGUSR1) != 0)
+    {
+      puts ("kill failed");
+      exit (1);
+    }
+
+  if (pthread_mutex_unlock (&m) != 0)
+    {
+      puts ("mutex_unlock failed");
+      exit (1);
+    }
+
+  void *r;
+  if (pthread_join (th, &r) != 0)
+    {
+      puts ("join failed");
+      exit (1);
+    }
+  if (r != NULL)
+    {
+      puts ("return value wrong");
+      exit (1);
+    }
+
+  return 0;
+}
+
+
+#define TIMEOUT 5
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-kill4.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-kill4.c
new file mode 100644
index 00000000..4e7ff5ea
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-kill4.c
@@ -0,0 +1,74 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+static void *
+tf (void *a)
+{
+  return NULL;
+}
+
+
+int
+do_test (void)
+{
+  pthread_t th;
+  if (pthread_create (&th, NULL, tf, NULL) != 0)
+    {
+      puts ("create failed");
+      exit (1);
+    }
+
+  if (pthread_join (th, NULL) != 0)
+    {
+      puts ("join failed");
+      exit (1);
+    }
+
+  /* The following only works because we assume here something about
+     the implementation.  Namely, that the memory allocated for the
+     thread descriptor is not going away, that the the TID field is
+     cleared and therefore the signal is sent to process 0, and that
+     we can savely assume there is no other process with this ID at
+     that time.  */
+  int e = pthread_kill (th, 0);
+  if (e == 0)
+    {
+      puts ("pthread_kill succeeded");
+      exit (1);
+    }
+  if (e != ESRCH)
+    {
+      puts ("pthread_kill didn't return ESRCH");
+      exit (1);
+    }
+
+  return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-kill5.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-kill5.c
new file mode 100644
index 00000000..12560943
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-kill5.c
@@ -0,0 +1,49 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+int
+do_test (void)
+{
+  /* XXX This test might require architecture and system specific changes.
+     There is no guarantee that this signal number is invalid.  */
+  int e = pthread_kill (pthread_self (), SIGRTMAX + 10);
+  if (e == 0)
+    {
+      puts ("kill didn't failed");
+      exit (1);
+    }
+  if (e != EINVAL)
+    {
+      puts ("error not EINVAL");
+      exit (1);
+    }
+
+  return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-kill6.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-kill6.c
new file mode 100644
index 00000000..26e82d98
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-kill6.c
@@ -0,0 +1,162 @@
+/* Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+static pthread_t receiver;
+static sem_t sem;
+static pthread_barrier_t b;
+
+static void
+handler (int sig)
+{
+  if (sig != SIGUSR1)
+    {
+      write (STDOUT_FILENO, "wrong signal\n", 13);
+      _exit (1);
+    }
+
+  if (pthread_self () != receiver)
+    {
+      write (STDOUT_FILENO, "not the intended receiver\n", 26);
+      _exit (1);
+    }
+
+  if (sem_post (&sem) != 0)
+    {
+      write (STDOUT_FILENO, "sem_post failed\n", 16);
+      _exit (1);
+    }
+}
+
+
+static void *
+tf (void *a)
+{
+  int e = pthread_barrier_wait (&b);
+  if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("child: barrier_wait failed");
+      exit (1);
+    }
+
+  return NULL;
+}
+
+
+int
+do_test (void)
+{
+  struct sigaction sa;
+  sigemptyset (&sa.sa_mask);
+  sa.sa_flags = 0;
+  sa.sa_handler = handler;
+  if (sigaction (SIGUSR1, &sa, NULL) != 0)
+    {
+      puts ("sigaction failed");
+      exit (1);
+    }
+
+#define N 20
+
+  if (pthread_barrier_init (&b, NULL, N + 1) != 0)
+    {
+      puts ("barrier_init failed");
+      exit (1);
+    }
+
+  pthread_attr_t a;
+
+  if (pthread_attr_init (&a) != 0)
+    {
+      puts ("attr_init failed");
+      exit (1);
+    }
+
+  if (pthread_attr_setstacksize (&a, 1 * 1024 * 1024) != 0)
+    {
+      puts ("attr_setstacksize failed");
+      return 1;
+    }
+
+  pthread_t th[N];
+  int i;
+  for (i = 0; i < N; ++i)
+    if (pthread_create (&th[i], &a, tf, NULL) != 0)
+      {
+	puts ("create failed");
+	exit (1);
+      }
+
+  if (pthread_attr_destroy (&a) != 0)
+    {
+      puts ("attr_destroy failed");
+      exit (1);
+    }
+
+  if (sem_init (&sem, 0, 0) != 0)
+    {
+      puts ("sem_init failed");
+      exit (1);
+    }
+
+  for (i = 0; i < N * 10; ++i)
+    {
+      receiver = th[i % N];
+
+      if (pthread_kill (receiver, SIGUSR1) != 0)
+	{
+	  puts ("kill failed");
+	  exit (1);
+	}
+
+      if (TEMP_FAILURE_RETRY (sem_wait (&sem)) != 0)
+	{
+	  puts ("sem_wait failed");
+	  exit (1);
+	}
+    }
+
+  int e = pthread_barrier_wait (&b);
+  if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("barrier_wait failed");
+      exit (1);
+    }
+
+  for (i = 0; i < N; ++i)
+    if (pthread_join (th[i], NULL) != 0)
+      {
+	puts ("join failed");
+	exit (1);
+      }
+
+  return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-mqueue.h b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-mqueue.h
new file mode 100644
index 00000000..8e73be51
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-mqueue.h
@@ -0,0 +1,84 @@
+/* Common code for message queue passing tests.
+   Copyright (C) 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek , 2004.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+static int temp_mq_fd;
+
+/* Add temporary files in list.  */
+static void
+__attribute__ ((unused))
+add_temp_mq (const char *name)
+{
+  struct iovec iov[2];
+  iov[0].iov_base = (char *) name;
+  iov[0].iov_len = strlen (name);
+  iov[1].iov_base = (char *) "\n";
+  iov[1].iov_len = 1;
+  if (writev (temp_mq_fd, iov, 2) != iov[0].iov_len + 1)
+    printf ("Could not record temp mq filename %s\n", name);
+}
+
+/* Delete all temporary message queues.  */
+static void
+do_cleanup (void)
+{
+  if (lseek (temp_mq_fd, 0, SEEK_SET) != 0)
+    return;
+
+  FILE *f = fdopen (temp_mq_fd, "r");
+  if (f == NULL)
+    return;
+
+  char *line = NULL;
+  size_t n = 0;
+  ssize_t rets;
+  while ((rets = getline (&line, &n, f)) > 0)
+    {
+      if (line[rets - 1] != '\n')
+        continue;
+
+      line[rets - 1] = '\0';
+      mq_unlink (line);
+    }
+  fclose (f);
+}
+
+static void
+do_prepare (void)
+{
+  char name [] = "/tmp/tst-mqueueN.XXXXXX";
+  temp_mq_fd = mkstemp (name);
+  if (temp_mq_fd == -1)
+    {
+      printf ("Could not create temporary file %s: %m\n", name);
+      exit (1);
+    }
+  unlink (name);
+}
+
+#define PREPARE(argc, argv) do_prepare ()
+#define CLEANUP_HANDLER	do_cleanup ()
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-mqueue1.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-mqueue1.c
new file mode 100644
index 00000000..70e42377
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-mqueue1.c
@@ -0,0 +1,417 @@
+/* Test message queue passing.
+   Copyright (C) 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek , 2004.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "tst-mqueue.h"
+
+static int
+intcmp (const void *a, const void *b)
+{
+  if (*(unsigned char *)a < *(unsigned char *)b)
+    return 1;
+  if (*(unsigned char *)a > *(unsigned char *)b)
+    return -1;
+  return 0;
+}
+
+static int
+check_attrs (struct mq_attr *attr, int nonblock, long cnt)
+{
+  int result = 0;
+
+  if (attr->mq_maxmsg != 10 || attr->mq_msgsize != 1)
+    {
+      printf ("attributes don't match those passed to mq_open\n"
+	      "mq_maxmsg %ld, mq_msgsize %ld\n",
+	      attr->mq_maxmsg, attr->mq_msgsize);
+      result = 1;
+    }
+
+  if ((attr->mq_flags & O_NONBLOCK) != nonblock)
+    {
+      printf ("mq_flags %lx != %x\n", (attr->mq_flags & O_NONBLOCK), nonblock);
+      result = 1;
+    }
+
+  if (attr->mq_curmsgs != cnt)
+    {
+      printf ("mq_curmsgs %ld != %ld\n", attr->mq_curmsgs, cnt);
+      result = 1;
+    }
+
+  return result;
+}
+
+static int
+do_one_test (mqd_t q, const char *name, int nonblock)
+{
+  int result = 0;
+
+  char v []
+    = { 0x32, 0x62, 0x22, 0x31, 0x11, 0x73, 0x61, 0x21, 0x72, 0x71, 0x81 };
+
+  struct mq_attr attr;
+  memset (&attr, 0xaa, sizeof (attr));
+  if (mq_getattr (q, &attr) != 0)
+    {
+      printf ("mq_getattr failed: %m\n");
+      result = 1;
+    }
+  else
+    result |= check_attrs (&attr, nonblock, 0);
+
+  if (mq_receive (q, &v[0], 1, NULL) != -1)
+    {
+      puts ("mq_receive on O_WRONLY mqd_t unexpectedly succeeded");
+      result = 1;
+    }
+  else if (errno != EBADF)
+    {
+      printf ("mq_receive on O_WRONLY mqd_t did not fail with EBADF: %m\n");
+      result = 1;
+    }
+
+  struct timespec ts;
+  if (clock_gettime (CLOCK_REALTIME, &ts) == 0)
+    --ts.tv_sec;
+  else
+    {
+      ts.tv_sec = time (NULL) - 1;
+      ts.tv_nsec = 0;
+    }
+
+  int ret;
+  for (int i = 0; i < 10; ++i)
+    {
+      if (i & 1)
+	ret = mq_send (q, &v[i], 1, v[i] >> 4);
+      else
+	ret = mq_timedsend (q, &v[i], 1, v[i] >> 4, &ts);
+
+      if (ret)
+	{
+	  printf ("mq_%ssend failed: %m\n", (i & 1) ? "" : "timed");
+	  result = 1;
+	}
+    }
+
+  ret = mq_timedsend (q, &v[10], 1, 8, &ts);
+  if (ret != -1)
+    {
+      puts ("mq_timedsend on full queue did not fail");
+      result = 1;
+    }
+  else if (errno != (nonblock ? EAGAIN : ETIMEDOUT))
+    {
+      printf ("mq_timedsend on full queue did not fail with %s: %m\n",
+	      nonblock ? "EAGAIN" : "ETIMEDOUT");
+      result = 1;
+    }
+
+  if (nonblock)
+    {
+      ret = mq_send (q, &v[10], 1, 8);
+      if (ret != -1)
+	{
+	  puts ("mq_send on full non-blocking queue did not fail");
+	  result = 1;
+	}
+      else if (errno != EAGAIN)
+	{
+	  printf ("mq_send on full non-blocking queue did not fail"
+		  "with EAGAIN: %m\n");
+	  result = 1;
+	}
+    }
+
+  memset (&attr, 0xaa, sizeof (attr));
+  if (mq_getattr (q, &attr) != 0)
+    {
+      printf ("mq_getattr failed: %m\n");
+      result = 1;
+    }
+  else
+    result |= check_attrs (&attr, nonblock, 10);
+
+  pid_t pid = fork ();
+  if (pid == -1)
+    {
+      printf ("fork failed: %m\n");
+      result = 1;
+    }
+  else if (pid == 0)
+    {
+      result = 0;
+
+      if (mq_close (q) != 0)
+	{
+	  printf ("mq_close in child failed: %m\n");
+	  result = 1;
+	}
+
+      q = mq_open (name, O_RDONLY | nonblock);
+      if (q == (mqd_t) -1)
+        {
+	  printf ("mq_open in child failed: %m\n");
+	  exit (1);
+        }
+
+      memset (&attr, 0xaa, sizeof (attr));
+      if (mq_getattr (q, &attr) != 0)
+	{
+	  printf ("mq_getattr failed: %m\n");
+	  result = 1;
+	}
+      else
+	result |= check_attrs (&attr, nonblock, 10);
+
+      char vr[11] = { };
+      unsigned int prio;
+      ssize_t rets;
+
+      if (mq_send (q, &v[0], 1, 1) != -1)
+	{
+	  puts ("mq_send on O_RDONLY mqd_t unexpectedly succeeded");
+	  result = 1;
+	}
+      else if (errno != EBADF)
+	{
+	  printf ("mq_send on O_WRONLY mqd_t did not fail with EBADF: %m\n");
+	  result = 1;
+	}
+
+      for (int i = 0; i < 10; ++i)
+	{
+	  if (i & 1)
+	    rets = mq_receive (q, &vr[i], 1, &prio);
+	  else
+	    rets = mq_timedreceive (q, &vr[i], 1, &prio, &ts);
+
+	  if (rets != 1)
+	    {
+	      if (rets == -1)
+		printf ("mq_%sreceive failed: %m\n", (i & 1) ? "" : "timed");
+	      else
+		printf ("mq_%sreceive returned %zd != 1\n",
+			(i & 1) ? "" : "timed", rets);
+	      result = 1;
+	    }
+	  else if (prio != (unsigned int) vr[i] >> 4)
+	    {
+	      printf ("unexpected priority %x for value %02x\n", prio,
+		      vr[i]);
+	      result = 1;
+	    }
+	}
+
+      qsort (v, 10, 1, intcmp);
+      if (memcmp (v, vr, 10) != 0)
+	{
+	  puts ("messages not received in expected order");
+	  result = 1;
+	}
+
+      rets = mq_timedreceive (q, &vr[10], 1, &prio, &ts);
+      if (rets != -1)
+	{
+	  puts ("mq_timedreceive on empty queue did not fail");
+	  result = 1;
+	}
+      else if (errno != (nonblock ? EAGAIN : ETIMEDOUT))
+	{
+	  printf ("mq_timedreceive on empty queue did not fail with %s: %m\n",
+		  nonblock ? "EAGAIN" : "ETIMEDOUT");
+	  result = 1;
+	}
+
+      if (nonblock)
+	{
+	  ret = mq_receive (q, &vr[10], 1, &prio);
+	  if (ret != -1)
+	    {
+	      puts ("mq_receive on empty non-blocking queue did not fail");
+	      result = 1;
+	    }
+	  else if (errno != EAGAIN)
+	    {
+	      printf ("mq_receive on empty non-blocking queue did not fail"
+		      "with EAGAIN: %m\n");
+	      result = 1;
+	    }
+	}
+
+      memset (&attr, 0xaa, sizeof (attr));
+      if (mq_getattr (q, &attr) != 0)
+	{
+	  printf ("mq_getattr failed: %m\n");
+	  result = 1;
+	}
+      else
+	result |= check_attrs (&attr, nonblock, 0);
+
+      if (mq_close (q) != 0)
+	{
+	  printf ("mq_close in child failed: %m\n");
+	  result = 1;
+	}
+
+      exit (result);
+    }
+
+  int status;
+  if (TEMP_FAILURE_RETRY (waitpid (pid, &status, 0)) != pid)
+    {
+      printf ("waitpid failed: %m\n");
+      kill (pid, SIGKILL);
+      result = 1;
+    }
+  else if (!WIFEXITED (status) || WEXITSTATUS (status))
+    {
+      printf ("child failed: %d\n", status);
+      result = 1;
+    }
+
+  memset (&attr, 0xaa, sizeof (attr));
+  if (mq_getattr (q, &attr) != 0)
+    {
+      printf ("mq_getattr failed: %m\n");
+      result = 1;
+    }
+  else
+    result |= check_attrs (&attr, nonblock, 0);
+
+  return result;
+}
+
+#define TEST_FUNCTION do_test ()
+static int
+do_test (void)
+{
+  int result = 0;
+
+  char name[sizeof "/tst-mqueue1-" + sizeof (pid_t) * 3];
+  snprintf (name, sizeof (name), "/tst-mqueue1-%u", getpid ());
+
+  struct mq_attr attr = { .mq_maxmsg = 10, .mq_msgsize = 1 };
+  mqd_t q = mq_open (name, O_CREAT | O_EXCL | O_WRONLY, 0600, &attr);
+
+  if (q == (mqd_t) -1)
+    {
+      printf ("mq_open failed with: %m\n");
+      return result;
+    }
+  else
+    add_temp_mq (name);
+
+  result |= do_one_test (q, name, 0);
+
+  mqd_t q2 = mq_open (name, O_WRONLY | O_NONBLOCK);
+  if (q2 == (mqd_t) -1)
+    {
+      printf ("mq_open failed with: %m\n");
+      q2 = q;
+      result = 1;
+    }
+  else
+    {
+      if (mq_close (q) != 0)
+	{
+	  printf ("mq_close in parent failed: %m\n");
+	  result = 1;
+	}
+
+      q = q2;
+      result |= do_one_test (q, name, O_NONBLOCK);
+
+      if (mq_getattr (q, &attr) != 0)
+	{
+	  printf ("mq_getattr failed: %m\n");
+	  result = 1;
+	}
+      else
+	{
+	  attr.mq_flags ^= O_NONBLOCK;
+
+	  struct mq_attr attr2;
+	  memset (&attr2, 0x55, sizeof (attr2));
+	  if (mq_setattr (q, &attr, &attr2) != 0)
+	    {
+	      printf ("mq_setattr failed: %m\n");
+	      result = 1;
+	    }
+	  else if (attr.mq_flags != (attr2.mq_flags ^ O_NONBLOCK)
+		   || attr.mq_maxmsg != attr2.mq_maxmsg
+		   || attr.mq_msgsize != attr2.mq_msgsize
+		   || attr.mq_curmsgs != 0
+		   || attr2.mq_curmsgs != 0)
+	    {
+	      puts ("mq_setattr returned unexpected values in *omqstat");
+	      result = 1;
+	    }
+	  else
+	    {
+	      result |= do_one_test (q, name, 0);
+
+	      if (mq_setattr (q, &attr2, NULL) != 0)
+		{
+		  printf ("mq_setattr failed: %m\n");
+		  result = 1;
+		}
+	      else
+		result |= do_one_test (q, name, O_NONBLOCK);
+	    }
+	}
+    }
+
+  if (mq_unlink (name) != 0)
+    {
+      printf ("mq_unlink failed: %m\n");
+      result = 1;
+    }
+
+  if (mq_close (q) != 0)
+    {
+      printf ("mq_close in parent failed: %m\n");
+      result = 1;
+    }
+
+  if (mq_close (q) != -1)
+    {
+      puts ("second mq_close did not fail");
+      result = 1;
+    }
+  else if (errno != EBADF)
+    {
+      printf ("second mq_close did not fail with EBADF: %m\n");
+      result = 1;
+    }
+
+  return result;
+}
+
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-mqueue2.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-mqueue2.c
new file mode 100644
index 00000000..1948965c
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-mqueue2.c
@@ -0,0 +1,477 @@
+/* Test message queue passing.
+   Copyright (C) 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek , 2004.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "tst-mqueue.h"
+
+static void
+alrm_handler (int sig)
+{
+}
+
+#define TIMEOUT 10
+#define TEST_FUNCTION do_test ()
+static int
+do_test (void)
+{
+  int result = 0;
+
+  char name[sizeof "/tst-mqueue2-" + sizeof (pid_t) * 3];
+  snprintf (name, sizeof (name), "/tst-mqueue2-%u", getpid ());
+
+  struct mq_attr attr = { .mq_maxmsg = 2, .mq_msgsize = 2 };
+  mqd_t q = mq_open (name, O_CREAT | O_EXCL | O_RDWR, 0600, &attr);
+
+  if (q == (mqd_t) -1)
+    {
+      printf ("mq_open failed with: %m\n");
+      return result;
+    }
+  else
+    add_temp_mq (name);
+
+  mqd_t q2 = mq_open (name, O_CREAT | O_EXCL | O_RDWR, 0600, &attr);
+  if (q2 != (mqd_t) -1)
+    {
+      puts ("mq_open with O_EXCL unexpectedly succeeded");
+      result = 1;
+    }
+  else if (errno != EEXIST)
+    {
+      printf ("mq_open did not fail with EEXIST: %m\n");
+      result = 1;
+    }
+
+  char name2[sizeof "/tst-mqueue2-2-" + sizeof (pid_t) * 3];
+  snprintf (name2, sizeof (name2), "/tst-mqueue2-2-%u", getpid ());
+
+  attr.mq_maxmsg = -2;
+  q2 = mq_open (name2, O_CREAT | O_EXCL | O_RDWR, 0600, &attr);
+  if (q2 != (mqd_t) -1)
+    {
+      puts ("mq_open with invalid mq_maxmsg unexpectedly succeeded");
+      add_temp_mq (name2);
+      result = 1;
+    }
+  else if (errno != EINVAL)
+    {
+      printf ("mq_open with invalid mq_maxmsg did not fail with "
+	      "EINVAL: %m\n");
+      result = 1;
+    }
+
+  attr.mq_maxmsg = 2;
+  attr.mq_msgsize = -56;
+  q2 = mq_open (name2, O_CREAT | O_EXCL | O_RDWR, 0600, &attr);
+  if (q2 != (mqd_t) -1)
+    {
+      puts ("mq_open with invalid mq_msgsize unexpectedly succeeded");
+      add_temp_mq (name2);
+      result = 1;
+    }
+  else if (errno != EINVAL)
+    {
+      printf ("mq_open with invalid mq_msgsize did not fail with "
+	      "EINVAL: %m\n");
+      result = 1;
+    }
+
+  char buf[3];
+  struct timespec ts;
+  if (clock_gettime (CLOCK_REALTIME, &ts) == 0)
+    ts.tv_sec += 10;
+  else
+    {
+      ts.tv_sec = time (NULL) + 10;
+      ts.tv_nsec = 0;
+    }
+
+  if (mq_timedreceive (q, buf, 1, NULL, &ts) == 0)
+    {
+      puts ("mq_timedreceive with too small msg_len did not fail");
+      result = 1;
+    }
+  else if (errno != EMSGSIZE)
+    {
+      printf ("mq_timedreceive with too small msg_len did not fail with "
+	      "EMSGSIZE: %m\n");
+      result = 1;
+    }
+
+  ts.tv_nsec = -1;
+  if (mq_timedreceive (q, buf, 2, NULL, &ts) == 0)
+    {
+      puts ("mq_timedreceive with negative tv_nsec did not fail");
+      result = 1;
+    }
+  else if (errno != EINVAL)
+    {
+      printf ("mq_timedreceive with negative tv_nsec did not fail with "
+	      "EINVAL: %m\n");
+      result = 1;
+    }
+
+  ts.tv_nsec = 1000000000;
+  if (mq_timedreceive (q, buf, 2, NULL, &ts) == 0)
+    {
+      puts ("mq_timedreceive with tv_nsec >= 1000000000 did not fail");
+      result = 1;
+    }
+  else if (errno != EINVAL)
+    {
+      printf ("mq_timedreceive with tv_nsec >= 1000000000 did not fail with "
+	      "EINVAL: %m\n");
+      result = 1;
+    }
+
+  struct sigaction sa = { .sa_handler = alrm_handler, .sa_flags = 0 };
+  sigemptyset (&sa.sa_mask);
+  sigaction (SIGALRM, &sa, NULL);
+
+  struct itimerval it = { .it_value = { .tv_sec = 1 } };
+  setitimer (ITIMER_REAL, &it, NULL);
+
+  if (mq_receive (q, buf, 2, NULL) == 0)
+    {
+      puts ("mq_receive on empty queue did not block");
+      result = 1;
+    }
+  else if (errno != EINTR)
+    {
+      printf ("mq_receive on empty queue did not fail with EINTR: %m\n");
+      result = 1;
+    }
+
+  setitimer (ITIMER_REAL, &it, NULL);
+
+  ts.tv_nsec = 0;
+  if (mq_timedreceive (q, buf, 2, NULL, &ts) == 0)
+    {
+      puts ("mq_timedreceive on empty queue did not block");
+      result = 1;
+    }
+  else if (errno != EINTR)
+    {
+      printf ("mq_timedreceive on empty queue did not fail with EINTR: %m\n");
+      result = 1;
+    }
+
+  buf[0] = '6';
+  buf[1] = '7';
+  if (mq_send (q, buf, 2, 3) != 0
+      || (buf[0] = '8', mq_send (q, buf, 1, 4) != 0))
+    {
+      printf ("mq_send failed: %m\n");
+      result = 1;
+    }
+
+  memset (buf, ' ', sizeof (buf));
+
+  unsigned int prio;
+  ssize_t rets = mq_receive (q, buf, 3, &prio);
+  if (rets != 1)
+    {
+      if (rets == -1)
+	printf ("mq_receive failed: %m\n");
+      else
+	printf ("mq_receive returned %zd != 1\n", rets);
+      result = 1;
+    }
+  else if (prio != 4 || memcmp (buf, "8  ", 3) != 0)
+    {
+      printf ("mq_receive prio %u (4) buf \"%c%c%c\" (\"8  \")\n",
+	      prio, buf[0], buf[1], buf[2]);
+      result = 1;
+    }
+
+  rets = mq_receive (q, buf, 2, NULL);
+  if (rets != 2)
+    {
+      if (rets == -1)
+	printf ("mq_receive failed: %m\n");
+      else
+	printf ("mq_receive returned %zd != 2\n", rets);
+      result = 1;
+    }
+  else if (memcmp (buf, "67 ", 3) != 0)
+    {
+      printf ("mq_receive buf \"%c%c%c\" != \"67 \"\n",
+	      buf[0], buf[1], buf[2]);
+      result = 1;
+    }
+
+  buf[0] = '2';
+  buf[1] = '1';
+  if (clock_gettime (CLOCK_REALTIME, &ts) != 0)
+    ts.tv_sec = time (NULL);
+  ts.tv_nsec = -1000000001;
+  if ((mq_timedsend (q, buf, 2, 5, &ts) != 0
+       && (errno != EINVAL || mq_send (q, buf, 2, 5) != 0))
+      || (buf[0] = '3', ts.tv_nsec = -ts.tv_nsec,
+	  (mq_timedsend (q, buf, 1, 4, &ts) != 0
+	   && (errno != EINVAL || mq_send (q, buf, 1, 4) != 0))))
+    {
+      printf ("mq_timedsend failed: %m\n");
+      result = 1;
+    }
+
+  buf[0] = '-';
+  ts.tv_nsec = 1000000001;
+  if (mq_timedsend (q, buf, 1, 6, &ts) == 0)
+    {
+      puts ("mq_timedsend with tv_nsec >= 1000000000 did not fail");
+      result = 1;
+    }
+  else if (errno != EINVAL)
+    {
+      printf ("mq_timedsend with tv_nsec >= 1000000000 did not fail with "
+	      "EINVAL: %m\n");
+      result = 1;
+    }
+
+  ts.tv_nsec = -2;
+  if (mq_timedsend (q, buf, 1, 6, &ts) == 0)
+    {
+      puts ("mq_timedsend with negative tv_nsec did not fail");
+      result = 1;
+    }
+  else if (errno != EINVAL)
+    {
+      printf ("mq_timedsend with megatove tv_nsec did not fail with "
+	      "EINVAL: %m\n");
+      result = 1;
+    }
+
+  setitimer (ITIMER_REAL, &it, NULL);
+
+  if (mq_send (q, buf, 2, 8) == 0)
+    {
+      puts ("mq_send on full queue did not block");
+      result = 1;
+    }
+  else if (errno != EINTR)
+    {
+      printf ("mq_send on full queue did not fail with EINTR: %m\n");
+      result = 1;
+    }
+
+  setitimer (ITIMER_REAL, &it, NULL);
+
+  ts.tv_sec += 10;
+  ts.tv_nsec = 0;
+  if (mq_timedsend (q, buf, 2, 7, &ts) == 0)
+    {
+      puts ("mq_timedsend on full queue did not block");
+      result = 1;
+    }
+  else if (errno != EINTR)
+    {
+      printf ("mq_timedsend on full queue did not fail with EINTR: %m\n");
+      result = 1;
+    }
+
+  memset (buf, ' ', sizeof (buf));
+
+  if (clock_gettime (CLOCK_REALTIME, &ts) != 0)
+    ts.tv_sec = time (NULL);
+  ts.tv_nsec = -1000000001;
+  rets = mq_timedreceive (q, buf, 2, &prio, &ts);
+  if (rets == -1 && errno == EINVAL)
+    rets = mq_receive (q, buf, 2, &prio);
+  if (rets != 2)
+    {
+      if (rets == -1)
+	printf ("mq_timedreceive failed: %m\n");
+      else
+	printf ("mq_timedreceive returned %zd != 2\n", rets);
+      result = 1;
+    }
+  else if (prio != 5 || memcmp (buf, "21 ", 3) != 0)
+    {
+      printf ("mq_timedreceive prio %u (5) buf \"%c%c%c\" (\"21 \")\n",
+	      prio, buf[0], buf[1], buf[2]);
+      result = 1;
+    }
+
+  if (mq_receive (q, buf, 1, NULL) == 0)
+    {
+      puts ("mq_receive with too small msg_len did not fail");
+      result = 1;
+    }
+  else if (errno != EMSGSIZE)
+    {
+      printf ("mq_receive with too small msg_len did not fail with "
+	      "EMSGSIZE: %m\n");
+      result = 1;
+    }
+
+  ts.tv_nsec = -ts.tv_nsec;
+  rets = mq_timedreceive (q, buf, 2, NULL, &ts);
+  if (rets == -1 && errno == EINVAL)
+    rets = mq_receive (q, buf, 2, NULL);
+  if (rets != 1)
+    {
+      if (rets == -1)
+	printf ("mq_timedreceive failed: %m\n");
+      else
+	printf ("mq_timedreceive returned %zd != 1\n", rets);
+      result = 1;
+    }
+  else if (memcmp (buf, "31 ", 3) != 0)
+    {
+      printf ("mq_timedreceive buf \"%c%c%c\" != \"31 \"\n",
+	      buf[0], buf[1], buf[2]);
+      result = 1;
+    }
+
+  if (mq_send (q, "", 0, 2) != 0)
+    {
+      printf ("mq_send with msg_len 0 failed: %m\n");
+      result = 1;
+    }
+
+  rets = mq_receive (q, buf, 2, &prio);
+  if (rets)
+    {
+      if (rets == -1)
+	printf ("mq_receive failed: %m\n");
+      else
+	printf ("mq_receive returned %zd != 0\n", rets);
+      result = 1;
+    }
+
+  long mq_prio_max = sysconf (_SC_MQ_PRIO_MAX);
+  if (mq_prio_max > 0 && (unsigned int) mq_prio_max == mq_prio_max)
+    {
+      if (mq_send (q, buf, 1, mq_prio_max) == 0)
+	{
+	  puts ("mq_send with MQ_PRIO_MAX priority unpexpectedly succeeded");
+	  result = 1;
+	}
+      else if (errno != EINVAL)
+	{
+	  printf ("mq_send with MQ_PRIO_MAX priority did not fail with "
+		  "EINVAL: %m\n");
+	  result = 1;
+	}
+
+      if (mq_send (q, buf, 1, mq_prio_max - 1) != 0)
+	{
+	  printf ("mq_send with MQ_PRIO_MAX-1 priority failed: %m\n");
+	  result = 1;
+	}
+    }
+
+  if (mq_unlink (name) != 0)
+    {
+      printf ("mq_unlink failed: %m\n");
+      result = 1;
+    }
+
+  q2 = mq_open (name, O_RDWR);
+  if (q2 != (mqd_t) -1)
+    {
+      printf ("mq_open of unlinked %s without O_CREAT unexpectedly"
+	      "succeeded\n", name);
+      result = 1;
+    }
+  else if (errno != ENOENT)
+    {
+      printf ("mq_open of unlinked %s without O_CREAT did not fail with "
+	      "ENOENT: %m\n", name);
+      result = 1;
+    }
+
+  if (mq_close (q) != 0)
+    {
+      printf ("mq_close in parent failed: %m\n");
+      result = 1;
+    }
+
+  if (mq_receive (q, buf, 2, NULL) == 0)
+    {
+      puts ("mq_receive on invalid mqd_t did not fail");
+      result = 1;
+    }
+  else if (errno != EBADF)
+    {
+      printf ("mq_receive on invalid mqd_t did not fail with EBADF: %m\n");
+      result = 1;
+    }
+
+  if (mq_send (q, buf, 1, 2) == 0)
+    {
+      puts ("mq_send on invalid mqd_t did not fail");
+      result = 1;
+    }
+  else if (errno != EBADF)
+    {
+      printf ("mq_send on invalid mqd_t did not fail with EBADF: %m\n");
+      result = 1;
+    }
+
+  if (mq_getattr (q, &attr) == 0)
+    {
+      puts ("mq_getattr on invalid mqd_t did not fail");
+      result = 1;
+    }
+  else if (errno != EBADF)
+    {
+      printf ("mq_getattr on invalid mqd_t did not fail with EBADF: %m\n");
+      result = 1;
+    }
+
+  memset (&attr, 0, sizeof (attr));
+  if (mq_setattr (q, &attr, NULL) == 0)
+    {
+      puts ("mq_setattr on invalid mqd_t did not fail");
+      result = 1;
+    }
+  else if (errno != EBADF)
+    {
+      printf ("mq_setattr on invalid mqd_t did not fail with EBADF: %m\n");
+      result = 1;
+    }
+
+  if (mq_unlink ("/tst-mqueue2-which-should-never-exist") != -1)
+    {
+      puts ("mq_unlink of non-existant message queue unexpectedly succeeded");
+      result = 1;
+    }
+  else if (errno != ENOENT)
+    {
+      printf ("mq_unlink of non-existant message queue did not fail with "
+	      "ENOENT: %m\n");
+      result = 1;
+    }
+  return result;
+}
+
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-mqueue3.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-mqueue3.c
new file mode 100644
index 00000000..990e0572
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-mqueue3.c
@@ -0,0 +1,244 @@
+/* Test SIGEV_THREAD handling for POSIX message queues.
+   Copyright (C) 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2004.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#if _POSIX_THREADS
+# include 
+
+static pid_t pid;
+static mqd_t m;
+static const char message[] = "hello";
+
+# define MAXMSG 10
+# define MSGSIZE 10
+# define UNIQUE 42
+
+
+static void
+fct (union sigval s)
+{
+  /* Put the mq in non-blocking mode.  */
+  struct mq_attr attr;
+  if (mq_getattr (m, &attr) != 0)
+    {
+      printf ("%s: mq_getattr failed: %m\n", __FUNCTION__);
+      exit (1);
+    }
+  attr.mq_flags |= O_NONBLOCK;
+  if (mq_setattr (m, &attr, NULL) != 0)
+    {
+      printf ("%s: mq_setattr failed: %m\n", __FUNCTION__);
+      exit (1);
+    }
+
+  /* Check the values.  */
+  if (attr.mq_maxmsg != MAXMSG)
+    {
+      printf ("%s: mq_maxmsg wrong: is %ld, expecte %d\n",
+	      __FUNCTION__, attr.mq_maxmsg, MAXMSG);
+      exit (1);
+    }
+  if (attr.mq_msgsize != MAXMSG)
+    {
+      printf ("%s: mq_msgsize wrong: is %ld, expecte %d\n",
+	      __FUNCTION__, attr.mq_msgsize, MSGSIZE);
+      exit (1);
+    }
+
+  /* Read the message.  */
+  char buf[attr.mq_msgsize];
+  ssize_t n = TEMP_FAILURE_RETRY (mq_receive (m, buf, attr.mq_msgsize, NULL));
+  if (n != sizeof (message))
+    {
+      printf ("%s: length of message wrong: is %zd, expected %zu\n",
+	      __FUNCTION__, n, sizeof (message));
+      exit (1);
+    }
+  if (memcmp (buf, message, sizeof (message)) != 0)
+    {
+      printf ("%s: message wrong: is \"%s\", expected \"%s\"\n",
+	      __FUNCTION__, buf, message);
+      exit (1);
+    }
+
+  exit (UNIQUE);
+}
+
+
+int
+do_test (void)
+{
+  char tmpfname[] = "/tmp/tst-mqueue3-barrier.XXXXXX";
+  int fd = mkstemp (tmpfname);
+  if (fd == -1)
+    {
+      printf ("cannot open temporary file: %m\n");
+      return 1;
+    }
+
+  /* Make sure it is always removed.  */
+  unlink (tmpfname);
+
+  /* Create one page of data.  */
+  size_t ps = sysconf (_SC_PAGESIZE);
+  char data[ps];
+  memset (data, '\0', ps);
+
+  /* Write the data to the file.  */
+  if (write (fd, data, ps) != (ssize_t) ps)
+    {
+      puts ("short write");
+      return 1;
+    }
+
+  void *mem = mmap (NULL, ps, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+  if (mem == MAP_FAILED)
+    {
+      printf ("mmap failed: %m\n");
+      return 1;
+    }
+
+  pthread_barrier_t *b;
+  b = (pthread_barrier_t *) (((uintptr_t) mem + __alignof (pthread_barrier_t))
+                             & ~(__alignof (pthread_barrier_t) - 1));
+
+  pthread_barrierattr_t a;
+  if (pthread_barrierattr_init (&a) != 0)
+    {
+      puts ("barrierattr_init failed");
+      return 1;
+    }
+
+  if (pthread_barrierattr_setpshared (&a, PTHREAD_PROCESS_SHARED) != 0)
+    {
+      puts ("barrierattr_setpshared failed, could not test");
+      return 0;
+    }
+
+  if (pthread_barrier_init (b, &a, 2) != 0)
+    {
+      puts ("barrier_init failed");
+      return 1;
+    }
+
+  if (pthread_barrierattr_destroy (&a) != 0)
+    {
+      puts ("barrierattr_destroy failed");
+      return 1;
+    }
+
+  /* Name for the message queue.  */
+  char mqname[sizeof ("/tst-mqueue3-") + 3 * sizeof (pid_t)];
+  snprintf (mqname, sizeof (mqname) - 1, "/tst-mqueue3-%ld",
+	    (long int) getpid ());
+
+  /* Create the message queue.  */
+  struct mq_attr attr = { .mq_maxmsg = MAXMSG, .mq_msgsize = MSGSIZE };
+  m = mq_open (mqname, O_CREAT | O_EXCL | O_RDWR, 0600, &attr);
+  if (m == -1)
+    {
+      if (errno == ENOSYS)
+	{
+	  puts ("not implemented");
+	  return 0;
+	}
+
+      puts ("mq_open failed");
+      return 1;
+    }
+
+  /* Unlink the message queue right away.  */
+  if (mq_unlink (mqname) != 0)
+    {
+      puts ("mq_unlink failed");
+      return 1;
+    }
+
+  pid = fork ();
+  if (pid == -1)
+    {
+      puts ("fork failed");
+      return 1;
+    }
+  if (pid == 0)
+    {
+      /* Request notification via thread.  */
+      struct sigevent ev;
+      ev.sigev_notify = SIGEV_THREAD;
+      ev.sigev_notify_function = fct;
+      ev.sigev_value.sival_ptr = NULL;
+      ev.sigev_notify_attributes = NULL;
+
+      /* Tell the kernel.  */
+      if (mq_notify (m,&ev) != 0)
+	{
+	  puts ("mq_notify failed");
+	  exit (1);
+	}
+
+      /* Tell the parent we are ready.  */
+      (void) pthread_barrier_wait (b);
+
+      /* Make sure the process goes away eventually.  */
+      alarm (10);
+
+      /* Do nothing forever.  */
+      while (1)
+	pause ();
+    }
+
+  /* Wait for the child process to register to notification method.  */
+  (void) pthread_barrier_wait (b);
+
+  /* Send the message.  */
+  if (mq_send (m, message, sizeof (message), 1) != 0)
+    {
+      kill (pid, SIGKILL);
+      puts ("mq_send failed");
+      return 1;
+    }
+
+  int r;
+  if (TEMP_FAILURE_RETRY (waitpid (pid, &r, 0)) != pid)
+    {
+      kill (pid, SIGKILL);
+      puts ("waitpid failed");
+      return 1;
+    }
+
+  return WIFEXITED (r) && WEXITSTATUS (r) == UNIQUE ? 0 : 1;
+}
+# define TEST_FUNCTION do_test ()
+#else
+# define TEST_FUNCTION 0
+#endif
+
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-mqueue4.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-mqueue4.c
new file mode 100644
index 00000000..aa31706f
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-mqueue4.c
@@ -0,0 +1,288 @@
+/* Test message queue passing.
+   Copyright (C) 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek , 2004.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "tst-mqueue.h"
+
+#define TIMEOUT 4
+#define TEST_FUNCTION do_test ()
+static int
+do_test (void)
+{
+  int result = 0;
+
+  char name[sizeof "/tst-mqueue4-" + sizeof (pid_t) * 3 + NAME_MAX];
+  char *p;
+  p = name + snprintf (name, sizeof (name), "/tst-mqueue4-%u", getpid ());
+  struct mq_attr attr = { .mq_maxmsg = 2, .mq_msgsize = 2 };
+  mqd_t q = mq_open (name, O_CREAT | O_EXCL | O_RDWR, 0600, &attr);
+
+  if (q == (mqd_t) -1)
+    {
+      printf ("mq_open failed with: %m\n");
+      return result;
+    }
+  else
+    add_temp_mq (name);
+
+  *p = '.';
+  memset (p + 1, 'x', NAME_MAX + 1 - (p - name));
+  name[NAME_MAX + 1] = '\0';
+
+  mqd_t q2 = mq_open (name, O_CREAT | O_EXCL | O_RDWR, 0600, &attr);
+  if (q2 == (mqd_t) -1)
+    {
+      printf ("mq_open with NAME_MAX long name compoment failed with: %m\n");
+      result = 1;
+    }
+
+  if (mq_unlink (name) != 0)
+    {
+      printf ("mq_unlink failed: %m\n");
+      result = 1;
+    }
+
+  if (mq_close (q2) != 0)
+    {
+      printf ("mq_close failed: %m\n");
+      result = 1;
+    }
+
+  name[NAME_MAX + 1] = 'x';
+  name[NAME_MAX + 2] = '\0';
+  q2 = mq_open (name, O_CREAT | O_EXCL | O_RDWR, 0600, &attr);
+  if (q2 != (mqd_t) -1)
+    {
+      puts ("mq_open with too long name component unexpectedly succeeded");
+      mq_unlink (name);
+      mq_close (q2);
+      result = 1;
+    }
+  else if (errno != ENAMETOOLONG)
+    {
+      printf ("mq_open with too long name component did not fail with "
+	      "ENAMETOOLONG: %m\n");
+      result = 1;
+    }
+
+  if (mq_unlink (name) == 0)
+    {
+      puts ("mq_unlink with too long name component unexpectedly succeeded");
+      result = 1;
+    }
+  else if (errno != ENAMETOOLONG)
+    {
+      printf ("mq_unlink with too long name component did not fail with "
+	      "ENAMETOOLONG: %m\n");
+      result = 1;
+    }
+
+  *p = '\0';
+  attr.mq_maxmsg = 1;
+  attr.mq_msgsize = 3;
+  q2 = mq_open (name, O_CREAT | O_RDWR, 0600, &attr);
+  if (q2 == (mqd_t) -1)
+    {
+      printf ("mq_open without O_EXCL failed with %m\n");
+      result = 1;
+    }
+
+  char buf[3];
+  strcpy (buf, "jk");
+  if (mq_send (q, buf, 2, 4) != 0)
+    {
+      printf ("mq_send failed: %m\n");
+      result = 1;
+    }
+
+  if (mq_send (q, buf + 1, 1, 5) != 0)
+    {
+      printf ("mq_send failed: %m\n");
+      result = 1;
+    }
+
+  if (mq_getattr (q2, &attr) != 0)
+    {
+      printf ("mq_getattr failed: %m\n");
+      result = 1;
+    }
+
+  if ((attr.mq_flags & O_NONBLOCK)
+      || attr.mq_maxmsg != 2
+      || attr.mq_msgsize != 2
+      || attr.mq_curmsgs != 2)
+    {
+      printf ("mq_getattr returned unexpected { .mq_flags = %ld,\n"
+	      ".mq_maxmsg = %ld, .mq_msgsize = %ld, .mq_curmsgs = %ld }\n",
+	      attr.mq_flags, attr.mq_maxmsg, attr.mq_msgsize, attr.mq_curmsgs);
+      result = 1;
+    }
+
+  struct timespec ts;
+  if (clock_gettime (CLOCK_REALTIME, &ts) == 0)
+    ++ts.tv_sec;
+  else
+    {
+      ts.tv_sec = time (NULL) + 1;
+      ts.tv_nsec = 0;
+    }
+
+  if (mq_timedsend (q2, buf, 1, 1, &ts) == 0)
+    {
+      puts ("mq_timedsend unexpectedly succeeded");
+      result = 1;
+    }
+  else if (errno != ETIMEDOUT)
+    {
+      printf ("mq_timedsend did not fail with ETIMEDOUT: %m\n");
+      result = 1;
+    }
+
+  if (mq_close (q2) != 0)
+    {
+      printf ("mq_close failed: %m\n");
+      result = 1;
+    }
+
+  q2 = mq_open (name, O_RDONLY, 0600);
+  if (q2 == (mqd_t) -1)
+    {
+      printf ("mq_open without O_CREAT failed with %m\n");
+      result = 1;
+    }
+
+  mqd_t q3 = mq_open (name, O_RDONLY, 0600);
+  if (q3 == (mqd_t) -1)
+    {
+      printf ("mq_open without O_CREAT failed with %m\n");
+      result = 1;
+    }
+
+  memset (buf, ' ', sizeof (buf));
+
+  unsigned int prio;
+  ssize_t rets = mq_receive (q2, buf, 2, &prio);
+  if (rets != 1)
+    {
+      if (rets == -1)
+	printf ("mq_receive failed with: %m\n");
+      else
+	printf ("mq_receive returned %zd != 1\n", rets);
+      result = 1;
+    }
+  else if (prio != 5 || memcmp (buf, "k  ", 3) != 0)
+    {
+      printf ("mq_receive returned prio %u (2) buf \"%c%c%c\" (\"k  \")\n",
+	      prio, buf[0], buf[1], buf[2]);
+      result = 1;
+    }
+
+  if (mq_getattr (q3, &attr) != 0)
+    {
+      printf ("mq_getattr failed: %m\n");
+      result = 1;
+    }
+
+  if ((attr.mq_flags & O_NONBLOCK)
+      || attr.mq_maxmsg != 2
+      || attr.mq_msgsize != 2
+      || attr.mq_curmsgs != 1)
+    {
+      printf ("mq_getattr returned unexpected { .mq_flags = %ld,\n"
+	      ".mq_maxmsg = %ld, .mq_msgsize = %ld, .mq_curmsgs = %ld }\n",
+	      attr.mq_flags, attr.mq_maxmsg, attr.mq_msgsize, attr.mq_curmsgs);
+      result = 1;
+    }
+
+  rets = mq_receive (q3, buf, 2, NULL);
+  if (rets != 2)
+    {
+      if (rets == -1)
+	printf ("mq_receive failed with: %m\n");
+      else
+	printf ("mq_receive returned %zd != 2\n", rets);
+      result = 1;
+    }
+  else if (memcmp (buf, "jk ", 3) != 0)
+    {
+      printf ("mq_receive returned buf \"%c%c%c\" != \"jk \"\n",
+	      buf[0], buf[1], buf[2]);
+      result = 1;
+    }
+
+  if (clock_gettime (CLOCK_REALTIME, &ts) == 0)
+    ++ts.tv_sec;
+  else
+    {
+      ts.tv_sec = time (NULL) + 1;
+      ts.tv_nsec = 0;
+    }
+
+  if (mq_timedreceive (q2, buf, 2, NULL, &ts) != -1)
+    {
+      puts ("mq_timedreceive on empty queue unexpectedly succeeded");
+      result = 1;
+    }
+  else if (errno != ETIMEDOUT)
+    {
+      printf ("mq_timedreceive on empty queue did not fail with "
+	      "ETIMEDOUT: %m\n");
+      result = 1;
+    }
+
+  if (mq_unlink (name) != 0)
+    {
+      printf ("mq_unlink failed: %m\n");
+      result = 1;
+    }
+
+  if (mq_close (q) != 0)
+    {
+      printf ("mq_close failed: %m\n");
+      result = 1;
+    }
+
+  if (mq_close (q2) != 0)
+    {
+      printf ("mq_close failed: %m\n");
+      result = 1;
+    }
+
+  if (mq_close (q3) != 0)
+    {
+      printf ("mq_close failed: %m\n");
+      result = 1;
+    }
+
+  return result;
+}
+
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-mqueue5.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-mqueue5.c
new file mode 100644
index 00000000..97571da8
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-mqueue5.c
@@ -0,0 +1,1014 @@
+/* Test mq_notify.
+   Copyright (C) 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek , 2004.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "tst-mqueue.h"
+
+#define TIMEOUT 3
+
+#if _POSIX_THREADS
+# include 
+
+volatile int rtmin_cnt;
+volatile pid_t rtmin_pid;
+volatile uid_t rtmin_uid;
+volatile int rtmin_code;
+volatile union sigval rtmin_sigval;
+
+static void
+rtmin_handler (int sig, siginfo_t *info, void *ctx)
+{
+  if (sig != SIGRTMIN)
+    abort ();
+  ++rtmin_cnt;
+  rtmin_pid = info->si_pid;
+  rtmin_uid = info->si_uid;
+  rtmin_code = info->si_code;
+  rtmin_sigval = info->si_value;
+}
+
+#define mqsend(q) (mqsend) (q, __LINE__)
+static int
+(mqsend) (mqd_t q, int line)
+{
+  char c;
+  if (mq_send (q, &c, 1, 1) != 0)
+    {
+      printf ("mq_send on line %d failed with: %m\n", line);
+      return 1;
+    }
+  return 0;
+}
+
+#define mqrecv(q) (mqrecv) (q, __LINE__)
+static int
+(mqrecv) (mqd_t q, int line)
+{
+  char c;
+  ssize_t rets = TEMP_FAILURE_RETRY (mq_receive (q, &c, 1, NULL));
+  if (rets != 1)
+    {
+      if (rets == -1)
+	printf ("mq_receive on line %d failed with: %m\n", line);
+      else
+	printf ("mq_receive on line %d returned %zd != 1\n",
+		line, rets);
+      return 1;
+    }
+  return 0;
+}
+
+struct thr_data
+{
+  const char *name;
+  pthread_barrier_t *b3;
+  mqd_t q;
+};
+
+static void *
+thr (void *arg)
+{
+  pthread_barrier_t *b3 = ((struct thr_data *)arg)->b3;
+  mqd_t q = ((struct thr_data *)arg)->q;
+  const char *name = ((struct thr_data *)arg)->name;
+  int result = 0;
+
+  result |= mqrecv (q);
+
+  (void) pthread_barrier_wait (b3);
+
+  /* Child verifies SIGRTMIN has not been sent.  */
+
+  (void) pthread_barrier_wait (b3);
+
+  /* Parent calls mqsend (q), which should trigger notification.  */
+
+  (void) pthread_barrier_wait (b3);
+
+  if (rtmin_cnt != 2)
+    {
+      puts ("SIGRTMIN signal in child did not arrive");
+      result = 1;
+    }
+  else if (rtmin_pid != getppid ()
+	   || rtmin_uid != getuid ()
+	   || rtmin_code != SI_MESGQ
+	   || rtmin_sigval.sival_int != 0xdeadbeef)
+    {
+      printf ("unexpected siginfo_t fields: pid %u (%u), uid %u (%u), code %d (%d), si_int %d (%d)\n",
+	      rtmin_pid, getppid (), rtmin_uid, getuid (),
+	      rtmin_code, SI_MESGQ, rtmin_sigval.sival_int, 0xdeadbeef);
+      result = 1;
+    }
+
+  struct sigevent ev;
+  memset (&ev, 0x82, sizeof (ev));
+  ev.sigev_notify = SIGEV_NONE;
+  if (mq_notify (q, &ev) != 0)
+    {
+      printf ("mq_notify in thread (q, { SIGEV_NONE }) failed with: %m\n");
+      result = 1;
+    }
+
+  if (mq_notify (q, NULL) != 0)
+    {
+      printf ("mq_notify in thread (q, NULL) failed with: %m\n");
+      result = 1;
+    }
+
+  result |= mqrecv (q);
+
+  (void) pthread_barrier_wait (b3);
+
+  /* Child calls mq_notify (q, { SIGEV_SIGNAL }).  */
+
+  (void) pthread_barrier_wait (b3);
+
+  if (mq_notify (q, NULL) != 0)
+    {
+      printf ("second mq_notify in thread (q, NULL) failed with: %m\n");
+      result = 1;
+    }
+
+  (void) pthread_barrier_wait (b3);
+
+  /* Parent calls mqsend (q), which should not trigger notification.  */
+
+  (void) pthread_barrier_wait (b3);
+
+  /* Child verifies SIGRTMIN has not been received.  */
+  /* Child calls mq_notify (q, { SIGEV_SIGNAL }).  */
+
+  (void) pthread_barrier_wait (b3);
+
+  mqd_t q4 = mq_open (name, O_RDONLY);
+  if (q4 == (mqd_t) -1)
+    {
+      printf ("mq_open in thread failed with: %m\n");
+      result = 1;
+    }
+
+  if (mq_notify (q4, NULL) != 0)
+    {
+      printf ("mq_notify in thread (q4, NULL) failed with: %m\n");
+      result = 1;
+    }
+
+  if (mq_close (q4) != 0)
+    {
+      printf ("mq_close in thread failed with: %m\n");
+      result = 1;
+    }
+
+  (void) pthread_barrier_wait (b3);
+
+  /* Parent calls mqsend (q), which should not trigger notification.  */
+
+  (void) pthread_barrier_wait (b3);
+
+  /* Child verifies SIGRTMIN has not been received.  */
+  /* Child calls mq_notify (q, { SIGEV_SIGNAL }).  */
+
+  (void) pthread_barrier_wait (b3);
+
+  mqd_t q5 = mq_open (name, O_WRONLY);
+  if (q5 == (mqd_t) -1)
+    {
+      printf ("mq_open O_WRONLY in thread failed with: %m\n");
+      result = 1;
+    }
+
+  if (mq_notify (q5, NULL) != 0)
+    {
+      printf ("mq_notify in thread (q5, NULL) failed with: %m\n");
+      result = 1;
+    }
+
+  if (mq_close (q5) != 0)
+    {
+      printf ("mq_close in thread failed with: %m\n");
+      result = 1;
+    }
+
+  (void) pthread_barrier_wait (b3);
+
+  /* Parent calls mqsend (q), which should not trigger notification.  */
+
+  (void) pthread_barrier_wait (b3);
+
+  /* Child verifies SIGRTMIN has not been received.  */
+
+  return (void *) (long) result;
+}
+
+static void
+do_child (const char *name, pthread_barrier_t *b2, pthread_barrier_t *b3,
+	  mqd_t q)
+{
+  int result = 0;
+
+  struct sigevent ev;
+  memset (&ev, 0x55, sizeof (ev));
+  ev.sigev_notify = SIGEV_SIGNAL;
+  ev.sigev_signo = SIGRTMIN;
+  ev.sigev_value.sival_ptr = &ev;
+  if (mq_notify (q, &ev) == 0)
+    {
+      puts ("first mq_notify in child (q, { SIGEV_SIGNAL }) unexpectedly succeeded");
+      result = 1;
+    }
+  else if (errno != EBUSY)
+    {
+      printf ("first mq_notify in child (q, { SIGEV_SIGNAL }) failed with: %m\n");
+      result = 1;
+    }
+
+  (void) pthread_barrier_wait (b2);
+
+  /* Parent calls mqsend (q), which makes notification available.  */
+
+  (void) pthread_barrier_wait (b2);
+
+  rtmin_cnt = 0;
+
+  if (mq_notify (q, &ev) != 0)
+    {
+      printf ("second mq_notify in child (q, { SIGEV_SIGNAL }) failed with: %m\n");
+      result = 1;
+    }
+
+  if (rtmin_cnt != 0)
+    {
+      puts ("SIGRTMIN signal in child caught too early");
+      result = 1;
+    }
+
+  (void) pthread_barrier_wait (b2);
+
+  /* Parent unsuccessfully attempts to mq_notify.  */
+  /* Parent calls mqsend (q), which makes notification available
+     and triggers a signal in the child.  */
+  /* Parent successfully calls mq_notify SIGEV_SIGNAL.  */
+
+  (void) pthread_barrier_wait (b2);
+
+  if (rtmin_cnt != 1)
+    {
+      puts ("SIGRTMIN signal in child did not arrive");
+      result = 1;
+    }
+  else if (rtmin_pid != getppid ()
+	   || rtmin_uid != getuid ()
+	   || rtmin_code != SI_MESGQ
+	   || rtmin_sigval.sival_ptr != &ev)
+    {
+      printf ("unexpected siginfo_t fields: pid %u (%u), uid %u (%u), code %d (%d), si_ptr %p (%p)\n",
+	      rtmin_pid, getppid (), rtmin_uid, getuid (),
+	      rtmin_code, SI_MESGQ, rtmin_sigval.sival_ptr, &ev);
+      result = 1;
+    }
+
+  result |= mqsend (q);
+
+  (void) pthread_barrier_wait (b2);
+
+  /* Parent verifies caught SIGRTMIN.  */
+
+  mqd_t q2 = mq_open (name, O_RDWR);
+  if (q2 == (mqd_t) -1)
+    {
+      printf ("mq_open in child failed with: %m\n");
+      result = 1;
+    }
+
+  (void) pthread_barrier_wait (b2);
+
+  /* Parent mq_open's another mqd_t for the same queue (q3).  */
+
+  memset (&ev, 0x11, sizeof (ev));
+  ev.sigev_notify = SIGEV_SIGNAL;
+  ev.sigev_signo = SIGRTMIN;
+  ev.sigev_value.sival_ptr = &ev;
+  if (mq_notify (q2, &ev) != 0)
+    {
+      printf ("mq_notify in child (q2, { SIGEV_SIGNAL }) failed with: %m\n");
+      result = 1;
+    }
+
+  (void) pthread_barrier_wait (b2);
+
+  /* Parent unsuccessfully attempts to mq_notify { SIGEV_NONE } on q.  */
+
+  (void) pthread_barrier_wait (b2);
+
+  if (mq_close (q2) != 0)
+    {
+      printf ("mq_close failed: %m\n");
+      result = 1;
+    }
+
+  (void) pthread_barrier_wait (b2);
+
+  /* Parent successfully calls mq_notify { SIGEV_NONE } on q3.  */
+
+  (void) pthread_barrier_wait (b2);
+
+  memset (&ev, 0xbb, sizeof (ev));
+  ev.sigev_notify = SIGEV_SIGNAL;
+  ev.sigev_signo = SIGRTMIN;
+  ev.sigev_value.sival_ptr = &b2;
+  if (mq_notify (q, &ev) == 0)
+    {
+      puts ("third mq_notify in child (q, { SIGEV_SIGNAL }) unexpectedly succeeded");
+      result = 1;
+    }
+  else if (errno != EBUSY)
+    {
+      printf ("third mq_notify in child (q, { SIGEV_SIGNAL }) failed with: %m\n");
+      result = 1;
+    }
+
+  (void) pthread_barrier_wait (b2);
+
+  /* Parent calls mq_close on q3, which makes the queue available again for
+     notification.  */
+
+  (void) pthread_barrier_wait (b2);
+
+  memset (&ev, 0x13, sizeof (ev));
+  ev.sigev_notify = SIGEV_NONE;
+  if (mq_notify (q, &ev) != 0)
+    {
+      printf ("mq_notify in child (q, { SIGEV_NONE }) failed with: %m\n");
+      result = 1;
+    }
+
+  if (mq_notify (q, NULL) != 0)
+    {
+      printf ("mq_notify in child (q, NULL) failed with: %m\n");
+      result = 1;
+    }
+
+  (void) pthread_barrier_wait (b2);
+
+  struct thr_data thr_data = { .name = name, .b3 = b3, .q = q };
+  pthread_t th;
+  int ret = pthread_create (&th, NULL, thr, &thr_data);
+  if (ret)
+    {
+      errno = ret;
+      printf ("pthread_created failed with: %m\n");
+      result = 1;
+    }
+
+  /* Wait till thr calls mq_receive on the empty queue q and blocks on it.  */
+  sleep (1);
+
+  memset (&ev, 0x5f, sizeof (ev));
+  ev.sigev_notify = SIGEV_SIGNAL;
+  ev.sigev_signo = SIGRTMIN;
+  ev.sigev_value.sival_int = 0xdeadbeef;
+  if (mq_notify (q, &ev) != 0)
+    {
+      printf ("fourth mq_notify in child (q, { SIGEV_SIGNAL }) failed with: %m\n");
+      result = 1;
+    }
+
+  (void) pthread_barrier_wait (b2);
+
+  /* Parent calls mqsend (q), which should wake up mqrecv (q)
+     in the thread but no notification should be sent.  */
+
+  (void) pthread_barrier_wait (b3);
+
+  if (rtmin_cnt != 1)
+    {
+      puts ("SIGRTMIN signal caught while thr was blocked on mq_receive");
+      result = 1;
+    }
+
+  (void) pthread_barrier_wait (b3);
+
+  /* Parent calls mqsend (q), which should trigger notification.  */
+
+  (void) pthread_barrier_wait (b3);
+
+  /* Thread verifies SIGRTMIN has been received.  */
+  /* Thread calls mq_notify (q, { SIGEV_NONE }) to verify notification is now
+     available for registration.  */
+  /* Thread calls mq_notify (q, NULL).  */
+
+  (void) pthread_barrier_wait (b3);
+
+  memset (&ev, 0x6a, sizeof (ev));
+  ev.sigev_notify = SIGEV_SIGNAL;
+  ev.sigev_signo = SIGRTMIN;
+  ev.sigev_value.sival_ptr = do_child;
+  if (mq_notify (q, &ev) != 0)
+    {
+      printf ("fifth mq_notify in child (q, { SIGEV_SIGNAL }) failed with: %m\n");
+      result = 1;
+    }
+
+  (void) pthread_barrier_wait (b3);
+
+  /* Thread calls mq_notify (q, NULL), which should unregister the above
+     notification.  */
+
+  (void) pthread_barrier_wait (b3);
+
+  /* Parent calls mqsend (q), which should not trigger notification.  */
+
+  (void) pthread_barrier_wait (b3);
+
+  if (rtmin_cnt != 2)
+    {
+      puts ("SIGRTMIN signal caught while notification has been disabled");
+      result = 1;
+    }
+
+  memset (&ev, 0x7b, sizeof (ev));
+  ev.sigev_notify = SIGEV_SIGNAL;
+  ev.sigev_signo = SIGRTMIN;
+  ev.sigev_value.sival_ptr = thr;
+  if (mq_notify (q, &ev) != 0)
+    {
+      printf ("sixth mq_notify in child (q, { SIGEV_SIGNAL }) failed with: %m\n");
+      result = 1;
+    }
+
+  (void) pthread_barrier_wait (b3);
+
+  /* Thread opens a new O_RDONLY mqd_t (q4).  */
+  /* Thread calls mq_notify (q4, NULL), which should unregister the above
+     notification.  */
+  /* Thread calls mq_close (q4).  */
+
+  (void) pthread_barrier_wait (b3);
+
+  /* Parent calls mqsend (q), which should not trigger notification.  */
+
+  (void) pthread_barrier_wait (b3);
+
+  if (rtmin_cnt != 2)
+    {
+      puts ("SIGRTMIN signal caught while notification has been disabled");
+      result = 1;
+    }
+
+  memset (&ev, 0xe1, sizeof (ev));
+  ev.sigev_notify = SIGEV_SIGNAL;
+  ev.sigev_signo = SIGRTMIN;
+  ev.sigev_value.sival_int = 127;
+  if (mq_notify (q, &ev) != 0)
+    {
+      printf ("seventh mq_notify in child (q, { SIGEV_SIGNAL }) failed with: %m\n");
+      result = 1;
+    }
+
+  (void) pthread_barrier_wait (b3);
+
+  /* Thread opens a new O_WRONLY mqd_t (q5).  */
+  /* Thread calls mq_notify (q5, NULL), which should unregister the above
+     notification.  */
+  /* Thread calls mq_close (q5).  */
+
+  (void) pthread_barrier_wait (b3);
+
+  /* Parent calls mqsend (q), which should not trigger notification.  */
+
+  (void) pthread_barrier_wait (b3);
+
+  if (rtmin_cnt != 2)
+    {
+      puts ("SIGRTMIN signal caught while notification has been disabled");
+      result = 1;
+    }
+
+ void *thr_ret;
+  ret = pthread_join (th, &thr_ret);
+  if (ret)
+    {
+      errno = ret;
+      printf ("pthread_join failed: %m\n");
+      result = 1;
+    }
+  else if (thr_ret)
+    result = 1;
+
+  if (mq_close (q) != 0)
+    {
+      printf ("mq_close failed: %m\n");
+      result = 1;
+    }
+
+  exit (result);
+}
+
+#define TEST_FUNCTION do_test ()
+static int
+do_test (void)
+{
+  int result = 0;
+
+  char tmpfname[] = "/tmp/tst-mqueue5-barrier.XXXXXX";
+  int fd = mkstemp (tmpfname);
+  if (fd == -1)
+    {
+      printf ("cannot open temporary file: %m\n");
+      return 1;
+    }
+
+  /* Make sure it is always removed.  */
+  unlink (tmpfname);
+
+  /* Create one page of data.  */
+  size_t ps = sysconf (_SC_PAGESIZE);
+  char data[ps];
+  memset (data, '\0', ps);
+
+  /* Write the data to the file.  */
+  if (write (fd, data, ps) != (ssize_t) ps)
+    {
+      puts ("short write");
+      return 1;
+    }
+
+  void *mem = mmap (NULL, ps, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+  if (mem == MAP_FAILED)
+    {
+      printf ("mmap failed: %m\n");
+      return 1;
+    }
+
+  pthread_barrier_t *b2;
+  b2 = (pthread_barrier_t *) (((uintptr_t) mem + __alignof (pthread_barrier_t))
+			      & ~(__alignof (pthread_barrier_t) - 1));
+
+  pthread_barrier_t *b3;
+  b3 = b2 + 1;
+
+  pthread_barrierattr_t a;
+  if (pthread_barrierattr_init (&a) != 0)
+    {
+      puts ("barrierattr_init failed");
+      return 1;
+    }
+
+  if (pthread_barrierattr_setpshared (&a, PTHREAD_PROCESS_SHARED) != 0)
+    {
+      puts ("barrierattr_setpshared failed, could not test");
+      return 0;
+    }
+
+  if (pthread_barrier_init (b2, &a, 2) != 0)
+    {
+      puts ("barrier_init failed");
+      return 1;
+    }
+
+  if (pthread_barrier_init (b3, &a, 3) != 0)
+    {
+      puts ("barrier_init failed");
+      return 1;
+    }
+
+  if (pthread_barrierattr_destroy (&a) != 0)
+    {
+      puts ("barrierattr_destroy failed");
+      return 1;
+    }
+
+  char name[sizeof "/tst-mqueue5-" + sizeof (pid_t) * 3];
+  snprintf (name, sizeof (name), "/tst-mqueue5-%u", getpid ());
+
+  struct mq_attr attr = { .mq_maxmsg = 1, .mq_msgsize = 1 };
+  mqd_t q = mq_open (name, O_CREAT | O_EXCL | O_RDWR, 0600, &attr);
+
+  if (q == (mqd_t) -1)
+    {
+      printf ("mq_open failed with: %m\n");
+      return result;
+    }
+  else
+    add_temp_mq (name);
+
+  struct sigevent ev;
+  memset (&ev, 0xaa, sizeof (ev));
+  ev.sigev_notify = SIGEV_NONE;
+  if (mq_notify (q, &ev) != 0)
+    {
+      printf ("mq_notify (q, { SIGEV_NONE }) failed with: %m\n");
+      result = 1;
+    }
+
+  if (mq_notify (q, &ev) == 0)
+    {
+      puts ("second mq_notify (q, { SIGEV_NONE }) unexpectedly succeeded");
+      result = 1;
+    }
+  else if (errno != EBUSY)
+    {
+      printf ("second mq_notify (q, { SIGEV_NONE }) failed with: %m\n");
+      result = 1;
+    }
+
+  result |= mqsend (q);
+
+  if (mq_notify (q, &ev) != 0)
+    {
+      printf ("third mq_notify (q, { SIGEV_NONE }) failed with: %m\n");
+      result = 1;
+    }
+
+  result |= mqrecv (q);
+
+  if (mq_notify (q, NULL) != 0)
+    {
+      printf ("mq_notify (q, NULL) failed with: %m\n");
+      result = 1;
+    }
+
+  if (mq_notify (q, NULL) != 0)
+    {
+      /* Implementation-defined behaviour, so don't fail,
+	 just inform.  */
+      printf ("second mq_notify (q, NULL) failed with: %m\n");
+    }
+
+  struct sigaction sa = { .sa_sigaction = rtmin_handler,
+			  .sa_flags = SA_SIGINFO };
+  sigemptyset (&sa.sa_mask);
+  sigaction (SIGRTMIN, &sa, NULL);
+
+  memset (&ev, 0x55, sizeof (ev));
+  ev.sigev_notify = SIGEV_SIGNAL;
+  ev.sigev_signo = SIGRTMIN;
+  ev.sigev_value.sival_int = 26;
+  if (mq_notify (q, &ev) != 0)
+    {
+      printf ("mq_notify (q, { SIGEV_SIGNAL }) failed with: %m\n");
+      result = 1;
+    }
+
+  ev.sigev_value.sival_ptr = &ev;
+  if (mq_notify (q, &ev) == 0)
+    {
+      puts ("second mq_notify (q, { SIGEV_SIGNAL }) unexpectedly succeeded");
+      result = 1;
+    }
+  else if (errno != EBUSY)
+    {
+      printf ("second mq_notify (q, { SIGEV_SIGNAL }) failed with: %m\n");
+      result = 1;
+    }
+
+  if (rtmin_cnt != 0)
+    {
+      puts ("SIGRTMIN signal caught too early");
+      result = 1;
+    }
+
+  result |= mqsend (q);
+
+  if (rtmin_cnt != 1)
+    {
+      puts ("SIGRTMIN signal did not arrive");
+      result = 1;
+    }
+  else if (rtmin_pid != getpid ()
+	   || rtmin_uid != getuid ()
+	   || rtmin_code != SI_MESGQ
+	   || rtmin_sigval.sival_int != 26)
+    {
+      printf ("unexpected siginfo_t fields: pid %u (%u), uid %u (%u), code %d (%d), si_int %d (26)\n",
+	      rtmin_pid, getpid (), rtmin_uid, getuid (),
+	      rtmin_code, SI_MESGQ, rtmin_sigval.sival_int);
+      result = 1;
+    }
+
+  ev.sigev_value.sival_int = 75;
+  if (mq_notify (q, &ev) != 0)
+    {
+      printf ("third mq_notify (q, { SIGEV_SIGNAL }) failed with: %m\n");
+      result = 1;
+    }
+
+  result |= mqrecv (q);
+
+  if (mq_notify (q, NULL) != 0)
+    {
+      printf ("mq_notify (q, NULL) failed with: %m\n");
+      result = 1;
+    }
+
+  memset (&ev, 0x33, sizeof (ev));
+  ev.sigev_notify = SIGEV_NONE;
+  if (mq_notify (q, &ev) != 0)
+    {
+      printf ("fourth mq_notify (q, { SIGEV_NONE }) failed with: %m\n");
+      result = 1;
+    }
+
+  pid_t pid = fork ();
+  if (pid == -1)
+    {
+      printf ("fork () failed: %m\n");
+      mq_unlink (name);
+      return 1;
+    }
+
+  if (pid == 0)
+    do_child (name, b2, b3, q);
+
+  /* Child unsuccessfully attempts to mq_notify.  */
+
+  (void) pthread_barrier_wait (b2);
+
+  result |= mqsend (q);
+
+  (void) pthread_barrier_wait (b2);
+
+  /* Child successfully calls mq_notify SIGEV_SIGNAL now.  */
+
+  result |= mqrecv (q);
+
+  (void) pthread_barrier_wait (b2);
+
+  memset (&ev, 0xbb, sizeof (ev));
+  ev.sigev_notify = SIGEV_SIGNAL;
+  ev.sigev_signo = SIGRTMIN;
+  ev.sigev_value.sival_int = 15;
+  if (mq_notify (q, &ev) == 0)
+    {
+      puts ("fourth mq_notify (q, { SIGEV_SIGNAL }) unexpectedly succeeded");
+      result = 1;
+    }
+  else if (errno != EBUSY)
+    {
+      printf ("fourth mq_notify (q, { SIGEV_SIGNAL }) failed with: %m\n");
+      result = 1;
+    }
+
+  result |= mqsend (q);
+
+  if (mq_notify (q, &ev) != 0)
+    {
+      printf ("fifth mq_notify (q, { SIGEV_SIGNAL }) failed with: %m\n");
+      result = 1;
+    }
+
+  if (rtmin_cnt != 1)
+    {
+      puts ("SIGRTMIN signal caught too early");
+      result = 1;
+    }
+
+  result |= mqrecv (q);
+
+  (void) pthread_barrier_wait (b2);
+
+  /* Child verifies caught SIGRTMIN signal.  */
+  /* Child calls mq_send (q) which triggers SIGRTMIN signal here.  */
+
+  (void) pthread_barrier_wait (b2);
+
+  /* Child mq_open's another mqd_t for the same queue (q2).  */
+
+  if (rtmin_cnt != 2)
+    {
+      puts ("SIGRTMIN signal did not arrive");
+      result = 1;
+    }
+  else if (rtmin_pid != pid
+	   || rtmin_uid != getuid ()
+	   || rtmin_code != SI_MESGQ
+	   || rtmin_sigval.sival_int != 15)
+    {
+      printf ("unexpected siginfo_t fields: pid %u (%u), uid %u (%u), code %d (%d), si_int %d (15)\n",
+	      rtmin_pid, pid, rtmin_uid, getuid (),
+	      rtmin_code, SI_MESGQ, rtmin_sigval.sival_int);
+      result = 1;
+    }
+
+  result |= mqrecv (q);
+
+  (void) pthread_barrier_wait (b2);
+
+  /* Child successfully calls mq_notify { SIGEV_SIGNAL } on q2.  */
+
+  (void) pthread_barrier_wait (b2);
+
+  memset (&ev, 0xbb, sizeof (ev));
+  ev.sigev_notify = SIGEV_NONE;
+  if (mq_notify (q, &ev) == 0)
+    {
+      puts ("fifth mq_notify (q, { SIGEV_NONE }) unexpectedly succeeded");
+      result = 1;
+    }
+  else if (errno != EBUSY)
+    {
+      printf ("fifth mq_notify (q, { SIGEV_NONE }) failed with: %m\n");
+      result = 1;
+    }
+
+  (void) pthread_barrier_wait (b2);
+
+  /* Child calls mq_close on q2, which makes the queue available again for
+     notification.  */
+
+  mqd_t q3 = mq_open (name, O_RDWR);
+  if (q3 == (mqd_t) -1)
+    {
+      printf ("mq_open q3 in parent failed with: %m\n");
+      result = 1;
+    }
+
+  (void) pthread_barrier_wait (b2);
+
+  memset (&ev, 0x12, sizeof (ev));
+  ev.sigev_notify = SIGEV_NONE;
+  if (mq_notify (q3, &ev) != 0)
+    {
+      printf ("mq_notify (q3, { SIGEV_NONE }) failed with: %m\n");
+      result = 1;
+    }
+
+  (void) pthread_barrier_wait (b2);
+
+  /* Child unsuccessfully attempts to mq_notify { SIGEV_SIGNAL } on q.  */
+
+  (void) pthread_barrier_wait (b2);
+
+  if (mq_close (q3) != 0)
+    {
+      printf ("mq_close failed: %m\n");
+      result = 1;
+    }
+
+  (void) pthread_barrier_wait (b2);
+
+  /* Child successfully calls mq_notify { SIGEV_NONE } on q.  */
+  /* Child successfully calls mq_notify NULL on q.  */
+
+  (void) pthread_barrier_wait (b2);
+
+  /* Child creates new thread.  */
+  /* Thread blocks on mqrecv (q).  */
+  /* Child sleeps for 1sec so that thread has time to reach that point.  */
+  /* Child successfully calls mq_notify { SIGEV_SIGNAL } on q.  */
+
+  (void) pthread_barrier_wait (b2);
+
+  result |= mqsend (q);
+
+  (void) pthread_barrier_wait (b3);
+
+  /* Child verifies SIGRTMIN has not been sent.  */
+
+  (void) pthread_barrier_wait (b3);
+
+  result |= mqsend (q);
+
+  (void) pthread_barrier_wait (b3);
+
+  /* Thread verifies SIGRTMIN has been caught.  */
+  /* Thread calls mq_notify (q, { SIGEV_NONE }) to verify notification is now
+     available for registration.  */
+  /* Thread calls mq_notify (q, NULL).  */
+
+  (void) pthread_barrier_wait (b3);
+
+  /* Child calls mq_notify (q, { SIGEV_SIGNAL }).  */
+
+  (void) pthread_barrier_wait (b3);
+
+  /* Thread calls mq_notify (q, NULL). */
+
+  (void) pthread_barrier_wait (b3);
+
+  result |= mqsend (q);
+  result |= mqrecv (q);
+
+  (void) pthread_barrier_wait (b3);
+
+  /* Child verifies SIGRTMIN has not been sent.  */
+  /* Child calls mq_notify (q, { SIGEV_SIGNAL }).  */
+
+  (void) pthread_barrier_wait (b3);
+
+  /* Thread opens a new O_RDONLY mqd_t (q4).  */
+  /* Thread calls mq_notify (q4, NULL). */
+  /* Thread calls mq_close (q4).  */
+
+  (void) pthread_barrier_wait (b3);
+
+  result |= mqsend (q);
+  result |= mqrecv (q);
+
+  (void) pthread_barrier_wait (b3);
+
+  /* Child verifies SIGRTMIN has not been sent.  */
+  /* Child calls mq_notify (q, { SIGEV_SIGNAL }).  */
+
+  (void) pthread_barrier_wait (b3);
+
+  /* Thread opens a new O_WRONLY mqd_t (q5).  */
+  /* Thread calls mq_notify (q5, NULL). */
+  /* Thread calls mq_close (q5).  */
+
+  (void) pthread_barrier_wait (b3);
+
+  result |= mqsend (q);
+  result |= mqrecv (q);
+
+  (void) pthread_barrier_wait (b3);
+
+  /* Child verifies SIGRTMIN has not been sent.  */
+
+  int status;
+  if (TEMP_FAILURE_RETRY (waitpid (pid, &status, 0)) != pid)
+    {
+      puts ("waitpid failed");
+      kill (pid, SIGKILL);
+      result = 1;
+    }
+  else if (!WIFEXITED (status) || WEXITSTATUS (status))
+    {
+      printf ("child failed with status %d\n", status);
+      result = 1;
+    }
+
+  if (mq_unlink (name) != 0)
+    {
+      printf ("mq_unlink failed: %m\n");
+      result = 1;
+    }
+
+  if (mq_close (q) != 0)
+    {
+      printf ("mq_close failed: %m\n");
+      result = 1;
+    }
+
+  if (mq_notify (q, NULL) == 0)
+    {
+      puts ("mq_notify on closed mqd_t unexpectedly succeeded");
+      result = 1;
+    }
+  else if (errno != EBADF)
+    {
+      printf ("mq_notify on closed mqd_t did not fail with EBADF: %m\n");
+      result = 1;
+    }
+
+  memset (&ev, 0x55, sizeof (ev));
+  ev.sigev_notify = SIGEV_NONE;
+  if (mq_notify (q, &ev) == 0)
+    {
+      puts ("mq_notify on closed mqd_t unexpectedly succeeded");
+      result = 1;
+    }
+  else if (errno != EBADF)
+    {
+      printf ("mq_notify on closed mqd_t did not fail with EBADF: %m\n");
+      result = 1;
+    }
+
+  return result;
+}
+#else
+# define TEST_FUNCTION 0
+#endif
+
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-mqueue6.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-mqueue6.c
new file mode 100644
index 00000000..5c9ee69e
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-mqueue6.c
@@ -0,0 +1,305 @@
+/* Test mq_notify.
+   Copyright (C) 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek , 2004.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "tst-mqueue.h"
+
+#if _POSIX_THREADS
+# include 
+
+# define mqsend(q) (mqsend) (q, __LINE__)
+static int
+(mqsend) (mqd_t q, int line)
+{
+  char c;
+  if (mq_send (q, &c, 1, 1) != 0)
+    {
+      printf ("mq_send on line %d failed with: %m\n", line);
+      return 1;
+    }
+  return 0;
+}
+
+# define mqrecv(q) (mqrecv) (q, __LINE__)
+static int
+(mqrecv) (mqd_t q, int line)
+{
+  char c;
+  ssize_t rets = TEMP_FAILURE_RETRY (mq_receive (q, &c, 1, NULL));
+  if (rets != 1)
+    {
+      if (rets == -1)
+	printf ("mq_receive on line %d failed with: %m\n", line);
+      else
+	printf ("mq_receive on line %d returned %zd != 1\n",
+		line, rets);
+      return 1;
+    }
+  return 0;
+}
+
+volatile int fct_cnt, fct_err;
+size_t fct_guardsize;
+
+static void
+fct (union sigval s)
+{
+  mqd_t q = *(mqd_t *) s.sival_ptr;
+
+  pthread_attr_t nattr;
+  int ret = pthread_getattr_np (pthread_self (), &nattr);
+  if (ret)
+    {
+      errno = ret;
+      printf ("pthread_getattr_np failed: %m\n");
+      fct_err = 1;
+    }
+  else
+    {
+      ret = pthread_attr_getguardsize (&nattr, &fct_guardsize);
+      if (ret)
+	{
+	  errno = ret;
+	  printf ("pthread_attr_getguardsize failed: %m\n");
+	  fct_err = 1;
+	}
+      if (pthread_attr_destroy (&nattr) != 0)
+	{
+	  puts ("pthread_attr_destroy failed");
+	  fct_err = 1;
+	}
+    }
+
+  ++fct_cnt;
+  fct_err |= mqsend (q);
+}
+
+# define TEST_FUNCTION do_test ()
+static int
+do_test (void)
+{
+  int result = 0;
+
+  char name[sizeof "/tst-mqueue6-" + sizeof (pid_t) * 3];
+  snprintf (name, sizeof (name), "/tst-mqueue6-%u", getpid ());
+
+  struct mq_attr attr = { .mq_maxmsg = 1, .mq_msgsize = 1 };
+  mqd_t q = mq_open (name, O_CREAT | O_EXCL | O_RDWR, 0600, &attr);
+
+  if (q == (mqd_t) -1)
+    {
+      printf ("mq_open failed with: %m\n");
+      return result;
+    }
+  else
+    add_temp_mq (name);
+
+  pthread_attr_t nattr;
+  if (pthread_attr_init (&nattr)
+      || pthread_attr_setguardsize (&nattr, 0))
+    {
+      puts ("pthread_attr_t setup failed");
+      result = 1;
+    }
+
+  fct_guardsize = 1;
+
+  struct sigevent ev;
+  memset (&ev, 0xaa, sizeof (ev));
+  ev.sigev_notify = SIGEV_THREAD;
+  ev.sigev_notify_function = fct;
+  ev.sigev_notify_attributes = &nattr;
+  ev.sigev_value.sival_ptr = &q;
+  if (mq_notify (q, &ev) != 0)
+    {
+      printf ("mq_notify (q, { SIGEV_THREAD }) failed with: %m\n");
+      result = 1;
+    }
+
+  size_t ps = sysconf (_SC_PAGESIZE);
+  if (pthread_attr_setguardsize (&nattr, 32 * ps))
+    {
+      puts ("pthread_attr_t setup failed");
+      result = 1;
+    }
+
+  if (mq_notify (q, &ev) == 0)
+    {
+      puts ("second mq_notify (q, { SIGEV_NONE }) unexpectedly succeeded");
+      result = 1;
+    }
+  else if (errno != EBUSY)
+    {
+      printf ("second mq_notify (q, { SIGEV_NONE }) failed with: %m\n");
+      result = 1;
+    }
+
+  if (fct_cnt != 0)
+    {
+      printf ("fct called too early (%d on %d)\n", fct_cnt, __LINE__);
+      result = 1;
+    }
+
+  result |= mqsend (q);
+
+  result |= mqrecv (q);
+  result |= mqrecv (q);
+
+  if (fct_cnt != 1)
+    {
+      printf ("fct not called (%d on %d)\n", fct_cnt, __LINE__);
+      result = 1;
+    }
+  else if (fct_guardsize != 0)
+    {
+      printf ("fct_guardsize %zd != 0\n", fct_guardsize);
+      result = 1;
+    }
+
+  if (mq_notify (q, &ev) != 0)
+    {
+      printf ("third mq_notify (q, { SIGEV_NONE }) failed with: %m\n");
+      result = 1;
+    }
+
+  if (mq_notify (q, NULL) != 0)
+    {
+      printf ("mq_notify (q, NULL) failed with: %m\n");
+      result = 1;
+    }
+
+  memset (&ev, 0x11, sizeof (ev));
+  ev.sigev_notify = SIGEV_THREAD;
+  ev.sigev_notify_function = fct;
+  ev.sigev_notify_attributes = &nattr;
+  ev.sigev_value.sival_ptr = &q;
+  if (mq_notify (q, &ev) != 0)
+    {
+      printf ("mq_notify (q, { SIGEV_THREAD }) failed with: %m\n");
+      result = 1;
+    }
+
+  if (pthread_attr_setguardsize (&nattr, 0))
+    {
+      puts ("pthread_attr_t setup failed");
+      result = 1;
+    }
+
+  if (mq_notify (q, &ev) == 0)
+    {
+      puts ("second mq_notify (q, { SIGEV_NONE }) unexpectedly succeeded");
+      result = 1;
+    }
+  else if (errno != EBUSY)
+    {
+      printf ("second mq_notify (q, { SIGEV_NONE }) failed with: %m\n");
+      result = 1;
+    }
+
+  if (fct_cnt != 1)
+    {
+      printf ("fct called too early (%d on %d)\n", fct_cnt, __LINE__);
+      result = 1;
+    }
+
+  result |= mqsend (q);
+
+  result |= mqrecv (q);
+  result |= mqrecv (q);
+
+  if (fct_cnt != 2)
+    {
+      printf ("fct not called (%d on %d)\n", fct_cnt, __LINE__);
+      result = 1;
+    }
+  else if (fct_guardsize != 32 * ps)
+    {
+      printf ("fct_guardsize %zd != %zd\n", fct_guardsize, 32 * ps);
+      result = 1;
+    }
+
+  if (mq_notify (q, &ev) != 0)
+    {
+      printf ("third mq_notify (q, { SIGEV_NONE }) failed with: %m\n");
+      result = 1;
+    }
+
+  if (mq_notify (q, NULL) != 0)
+    {
+      printf ("mq_notify (q, NULL) failed with: %m\n");
+      result = 1;
+    }
+
+  if (pthread_attr_destroy (&nattr) != 0)
+    {
+      puts ("pthread_attr_destroy failed");
+      result = 1;
+    }
+
+  if (mq_unlink (name) != 0)
+    {
+      printf ("mq_unlink failed: %m\n");
+      result = 1;
+    }
+
+  if (mq_close (q) != 0)
+    {
+      printf ("mq_close failed: %m\n");
+      result = 1;
+    }
+
+  memset (&ev, 0x55, sizeof (ev));
+  ev.sigev_notify = SIGEV_THREAD;
+  ev.sigev_notify_function = fct;
+  ev.sigev_notify_attributes = NULL;
+  ev.sigev_value.sival_int = 0;
+  if (mq_notify (q, &ev) == 0)
+    {
+      puts ("mq_notify on closed mqd_t unexpectedly succeeded");
+      result = 1;
+    }
+  else if (errno != EBADF)
+    {
+      printf ("mq_notify on closed mqd_t did not fail with EBADF: %m\n");
+      result = 1;
+    }
+
+  if (fct_err)
+    result = 1;
+  return result;
+}
+#else
+# define TEST_FUNCTION 0
+#endif
+
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-mqueue7.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-mqueue7.c
new file mode 100644
index 00000000..34222f83
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-mqueue7.c
@@ -0,0 +1,109 @@
+/* Test all open message queues descriptors are closed during exec*.
+   Copyright (C) 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek , 2004.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define OPT_AFTEREXEC 20000
+
+static mqd_t after_exec = (mqd_t) -1;
+
+#define CMDLINE_OPTIONS \
+  { "after-exec", required_argument, NULL, OPT_AFTEREXEC },
+
+#define CMDLINE_PROCESS \
+  case OPT_AFTEREXEC:					\
+    after_exec = (mqd_t) strtoul (optarg, NULL, 0);	\
+    break;
+
+static int
+do_after_exec (void)
+{
+  int result = 0;
+
+  struct mq_attr attr;
+  if (mq_getattr (after_exec, &attr) == 0)
+    {
+      puts ("mq_getattr after exec unexpectedly succeeded");
+      result = 1;
+    }
+  else if (errno != EBADF)
+    {
+      printf ("mq_getattr after exec did not fail with EBADF: %m\n");
+      result = 1;
+    }
+
+  return result;
+}
+
+static int
+do_test (int argc, char **argv)
+{
+  if (after_exec != (mqd_t) -1)
+    return do_after_exec ();
+
+  char name[sizeof "/tst-mqueue7-" + sizeof (pid_t) * 3];
+  snprintf (name, sizeof (name), "/tst-mqueue7-%u", getpid ());
+
+  struct mq_attr attr = { .mq_maxmsg = 10, .mq_msgsize = 1 };
+  mqd_t q = mq_open (name, O_CREAT | O_EXCL | O_WRONLY, 0600, &attr);
+
+  if (q == (mqd_t) -1)
+    {
+      printf ("mq_open failed with: %m\n");
+      return 0;
+    }
+  else if (mq_unlink (name) != 0)
+    {
+      printf ("mq_unlink failed with: %m\n");
+      return 1;
+    }
+
+  if (mq_getattr (q, &attr) != 0)
+    {
+      printf ("mq_getattr failed: %m\n");
+      return 1;
+    }
+
+  char after_exec_arg[sizeof "--after-exec=0x" + sizeof (long) * 3];
+  snprintf (after_exec_arg, sizeof (after_exec_arg),
+	    "--after-exec=0x%lx", (long) q);
+
+  const char *newargv[argc + 2];
+  for (int i = 1; i < argc; ++i)
+    newargv[i - 1] = argv[i];
+  newargv[argc - 1] = "--direct";
+  newargv[argc] = after_exec_arg;
+  newargv[argc + 1] = NULL;
+
+  /* Verify that exec* has the effect of mq_close (q).  */
+  execv (newargv[0], (char * const *) newargv);
+  printf ("execv failed: %m\n");
+  return 1;
+}
+
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-mqueue8.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-mqueue8.c
new file mode 100644
index 00000000..7e902aa6
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-mqueue8.c
@@ -0,0 +1,266 @@
+/* Copyright (C) 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek , 2004.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#if _POSIX_THREADS
+# include 
+
+static pthread_barrier_t b;
+
+/* Cleanup handling test.  */
+static int cl_called;
+
+static void
+cl (void *arg)
+{
+  ++cl_called;
+}
+
+#define TF_MQ_RECEIVE		0L
+#define TF_MQ_TIMEDRECEIVE	1L
+#define TF_MQ_SEND		2L
+#define TF_MQ_TIMEDSEND		3L
+
+static const char *names[]
+  = { "mq_receive", "mq_timedreceive", "mq_send", "mq_timedsend" };
+
+static mqd_t q;
+static struct timespec never;
+
+static void *
+tf (void *arg)
+{
+  int r = pthread_barrier_wait (&b);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("tf: barrier_wait failed");
+      exit (1);
+    }
+
+  pthread_cleanup_push (cl, NULL);
+
+  char c = ' ';
+
+  switch ((long) arg)
+    {
+    case TF_MQ_SEND:
+      TEMP_FAILURE_RETRY (mq_send (q, &c, 1, 1));
+      break;
+    case TF_MQ_TIMEDSEND:
+      TEMP_FAILURE_RETRY (mq_timedsend (q, &c, 1, 1, &never));
+      break;
+    case TF_MQ_RECEIVE:
+      TEMP_FAILURE_RETRY (mq_receive (q, &c, 1, NULL));
+      break;
+    case TF_MQ_TIMEDRECEIVE:
+      TEMP_FAILURE_RETRY (mq_timedreceive (q, &c, 1, NULL, &never));
+      break;
+    }
+
+  pthread_cleanup_pop (0);
+
+  printf ("tf: %s returned\n", names[(long) arg]);
+
+  exit (1);
+}
+
+#define TEST_FUNCTION do_test ()
+static int
+do_test (void)
+{
+  char name[sizeof "/tst-mqueue8-" + sizeof (pid_t) * 3];
+  snprintf (name, sizeof (name), "/tst-mqueue8-%u", getpid ());
+
+  struct mq_attr attr = { .mq_maxmsg = 1, .mq_msgsize = 1 };
+  q = mq_open (name, O_CREAT | O_EXCL | O_RDWR, 0600, &attr);
+
+  if (q == (mqd_t) -1)
+    {
+      printf ("mq_open failed with: %m\n");
+      return 0;
+    }
+
+  if (mq_unlink (name) != 0)
+    {
+      printf ("mq_unlink failed with: %m\n");
+      return 1;
+    }
+
+  if (pthread_barrier_init (&b, NULL, 2) != 0)
+    {
+      puts ("barrier_init failed");
+      return 1;
+    }
+
+  if (clock_gettime (CLOCK_REALTIME, &never) == 0)
+    never.tv_sec += 100;
+  else
+    {
+      never.tv_sec = time (NULL) + 100;
+      never.tv_nsec = 0;
+    }
+
+  int result = 0;
+  for (long l = TF_MQ_RECEIVE; l <= TF_MQ_TIMEDSEND; ++l)
+    {
+      cl_called = 0;
+
+      pthread_t th;
+      if (pthread_create (&th, NULL, tf, (void *) l) != 0)
+	{
+	  printf ("1st %s create failed\n", names[l]);
+	  result = 1;
+	  continue;
+	}
+
+      int r = pthread_barrier_wait (&b);
+      if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+	{
+	  puts ("barrier_wait failed");
+	  result = 1;
+	  continue;
+	}
+
+      struct timespec ts = { .tv_sec = 0, .tv_nsec = 100000000 };
+      while (nanosleep (&ts, &ts) != 0)
+	continue;
+
+      printf ("going to cancel %s in-time\n", names[l]);
+      if (pthread_cancel (th) != 0)
+	{
+	  printf ("1st cancel of %s failed\n", names[l]);
+	  result = 1;
+	  continue;
+	}
+
+      void *status;
+      if (pthread_join (th, &status) != 0)
+	{
+	  printf ("1st join of %s failed\n", names[l]);
+	  result = 1;
+	  continue;
+	}
+      if (status != PTHREAD_CANCELED)
+	{
+	  printf ("1st %s thread not canceled\n", names[l]);
+	  result = 1;
+	  continue;
+	}
+
+      if (cl_called == 0)
+	{
+	  printf ("%s cleanup handler not called\n", names[l]);
+	  result = 1;
+	  continue;
+	}
+      if (cl_called > 1)
+	{
+	  printf ("%s cleanup handler called more than once\n", names[l]);
+	  result = 1;
+	  continue;
+	}
+
+      printf ("in-time %s cancellation succeeded\n", names[l]);
+
+      cl_called = 0;
+
+      if (pthread_create (&th, NULL, tf, (void *) l) != 0)
+	{
+	  printf ("2nd %s create failed\n", names[l]);
+	  result = 1;
+	  continue;
+	}
+
+      printf ("going to cancel %s early\n", names[l]);
+      if (pthread_cancel (th) != 0)
+	{
+	  printf ("2nd cancel of %s failed\n", names[l]);
+	  result = 1;
+	  continue;
+	}
+
+      r = pthread_barrier_wait (&b);
+      if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+	{
+	  puts ("barrier_wait failed");
+	  result = 1;
+	  continue;
+	}
+
+      if (pthread_join (th, &status) != 0)
+	{
+	  printf ("2nd join of %s failed\n", names[l]);
+	  result = 1;
+	  continue;
+	}
+      if (status != PTHREAD_CANCELED)
+	{
+	  printf ("2nd %s thread not canceled\n", names[l]);
+	  result = 1;
+	  continue;
+	}
+
+      if (cl_called == 0)
+	{
+	  printf ("%s cleanup handler not called\n", names[l]);
+	  result = 1;
+	  continue;
+	}
+      if (cl_called > 1)
+	{
+	  printf ("%s cleanup handler called more than once\n", names[l]);
+	  result = 1;
+	  continue;
+	}
+
+      printf ("early %s cancellation succeeded\n", names[l]);
+
+      if (l == TF_MQ_TIMEDRECEIVE)
+	{
+	  /* mq_receive and mq_timedreceive are tested on empty mq.
+	     For mq_send and mq_timedsend we need to make it full.
+	     If this fails, there is no point in doing further testing.  */
+	  char c = ' ';
+	  if (mq_send (q, &c, 1, 1) != 0)
+	    {
+	      printf ("mq_send failed: %m\n");
+	      result = 1;
+	      break;
+	    }
+	}
+    }
+
+  if (mq_close (q) != 0)
+    {
+      printf ("mq_close failed: %m\n");
+      result = 1;
+    }
+
+  return result;
+}
+#else
+# define TEST_FUNCTION 0
+#endif
+
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-mqueue9.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-mqueue9.c
new file mode 100644
index 00000000..fb057d4a
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-mqueue9.c
@@ -0,0 +1,92 @@
+/* Copyright (C) 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek , 2004.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "tst-mqueue.h"
+
+#define TEST_FUNCTION do_test ()
+static int
+do_test (void)
+{
+  if (geteuid () != 0)
+    {
+      puts ("this test requires root");
+      return 0;
+    }
+
+  char name[sizeof "/tst-mqueue9-" + sizeof (pid_t) * 3];
+  snprintf (name, sizeof (name), "/tst-mqueue9-%u", getpid ());
+
+  struct mq_attr attr = { .mq_maxmsg = 1, .mq_msgsize = 1 };
+  mqd_t q = mq_open (name, O_CREAT | O_EXCL | O_RDWR, 0600, &attr);
+
+  if (q == (mqd_t) -1)
+    {
+      printf ("mq_open failed with: %m\n");
+      return 0;
+    }
+  else
+    add_temp_mq (name);
+
+  if (seteuid (1) != 0)
+    {
+      printf ("failed to seteuid (1): %m\n");
+      mq_unlink (name);
+      return 0;
+    }
+
+  int result = 0;
+  if (mq_unlink (name) == 0)
+    {
+      puts ("mq_unlink unexpectedly succeeded");
+      result = 1;
+    }
+  else if (errno != EACCES)
+    {
+      printf ("mq_unlink did not fail with EACCES: %m\n");
+      result = 1;;
+    }
+
+  if (seteuid (0) != 0)
+    {
+      printf ("failed to seteuid (0): %m\n");
+      result = 1;
+    }
+
+  if (mq_unlink (name) != 0)
+    {
+      printf ("mq_unlink failed with: %m\n");
+      result = 1;
+    }
+
+  if (mq_close (q) != 0)
+    {
+      printf ("mq_close failed with: %m\n");
+      result = 1;
+    }
+
+  return result;
+}
+
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-mutex1.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-mutex1.c
new file mode 100644
index 00000000..50b5ccaf
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-mutex1.c
@@ -0,0 +1,57 @@
+/* Copyright (C) 2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2002.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+
+
+static int
+do_test (void)
+{
+  pthread_mutex_t m;
+
+  if (pthread_mutex_init (&m, NULL) != 0)
+    {
+      puts ("mutex_init failed");
+      return 1;
+    }
+
+  if (pthread_mutex_lock (&m) != 0)
+    {
+      puts ("mutex_lock failed");
+      return 1;
+    }
+
+  if (pthread_mutex_unlock (&m) != 0)
+    {
+      puts ("mutex_unlock failed");
+      return 1;
+    }
+
+  if (pthread_mutex_destroy (&m) != 0)
+    {
+      puts ("mutex_destroy failed");
+      return 1;
+    }
+
+  return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-mutex2.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-mutex2.c
new file mode 100644
index 00000000..f589a1ea
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-mutex2.c
@@ -0,0 +1,223 @@
+/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2002.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+
+
+static pthread_mutex_t m;
+static pthread_barrier_t b;
+
+
+static void *
+tf (void *arg)
+{
+  int e = pthread_mutex_unlock (&m);
+  if (e == 0)
+    {
+      puts ("child: 1st mutex_unlock succeeded");
+      exit (1);
+    }
+  else if (e != EPERM)
+    {
+      puts ("child: 1st mutex_unlock error != EPERM");
+      exit (1);
+    }
+
+  e = pthread_mutex_trylock (&m);
+  if (e == 0)
+    {
+      puts ("child: 1st trylock suceeded");
+      exit (1);
+    }
+  if (e != EBUSY)
+    {
+      puts ("child: 1st trylock didn't return EBUSY");
+      exit (1);
+    }
+
+  e = pthread_barrier_wait (&b);
+  if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("child: 1st barrier_wait failed");
+      exit (1);
+    }
+
+  e = pthread_barrier_wait (&b);
+  if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("child: 2nd barrier_wait failed");
+      exit (1);
+    }
+
+  e = pthread_mutex_unlock (&m);
+  if (e == 0)
+    {
+      puts ("child: 2nd mutex_unlock succeeded");
+      exit (1);
+    }
+  else if (e != EPERM)
+    {
+      puts ("child: 2nd mutex_unlock error != EPERM");
+      exit (1);
+    }
+
+  if (pthread_mutex_trylock (&m) != 0)
+    {
+      puts ("child: 2nd trylock failed");
+      exit (1);
+    }
+
+  if (pthread_mutex_unlock (&m) != 0)
+    {
+      puts ("child: 3rd mutex_unlock failed");
+      exit (1);
+    }
+
+  return NULL;
+}
+
+
+static int
+do_test (void)
+{
+  pthread_mutexattr_t a;
+  int e;
+
+  if (pthread_mutexattr_init (&a) != 0)
+    {
+      puts ("mutexattr_init failed");
+      exit (1);
+    }
+
+  if (pthread_mutexattr_settype (&a, PTHREAD_MUTEX_ERRORCHECK) != 0)
+    {
+      puts ("mutexattr_settype failed");
+      exit (1);
+    }
+
+  if (pthread_mutex_init (&m, &a) != 0)
+    {
+      puts ("mutex_init failed");
+      exit (1);
+    }
+
+  if (pthread_barrier_init (&b, NULL, 2) != 0)
+    {
+      puts ("barrier_init failed");
+      exit (1);
+    }
+
+  if ((e = pthread_mutex_unlock (&m)) == 0)
+    {
+      puts ("1st mutex_unlock succeeded");
+      exit (1);
+    }
+  else if (e != EPERM)
+    {
+      puts ("1st mutex_unlock error != EPERM");
+      exit (1);
+    }
+
+  if (pthread_mutex_lock (&m) != 0)
+    {
+      puts ("mutex_lock failed");
+      exit (1);
+    }
+
+  if ((e = pthread_mutex_lock (&m)) == 0)
+    {
+      puts ("2nd mutex_lock succeeded");
+      exit (1);
+    }
+  else if (e != EDEADLK)
+    {
+      puts ("2nd mutex_lock error != EDEADLK");
+      exit (1);
+    }
+
+  pthread_t th;
+  if (pthread_create (&th, NULL, tf, NULL) != 0)
+    {
+      puts ("create failed");
+      exit (1);
+    }
+
+  e = pthread_barrier_wait (&b);
+  if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("1st barrier_wait failed");
+      exit (1);
+    }
+
+  if (pthread_mutex_unlock (&m) != 0)
+    {
+      puts ("2nd mutex_unlock failed");
+      exit (1);
+    }
+
+  if ((e = pthread_mutex_unlock (&m)) == 0)
+    {
+      puts ("3rd mutex_unlock succeeded");
+      exit (1);
+    }
+  else if (e != EPERM)
+    {
+      puts ("3rd mutex_unlock error != EPERM");
+      exit (1);
+    }
+
+  e = pthread_barrier_wait (&b);
+  if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("2nd barrier_wait failed");
+      exit (1);
+    }
+
+  if (pthread_join (th, NULL) != 0)
+    {
+      puts ("join failed");
+      exit (1);
+    }
+
+  if (pthread_mutex_destroy (&m) != 0)
+    {
+      puts ("mutex_destroy failed");
+      exit (1);
+    }
+
+  if (pthread_barrier_destroy (&b) != 0)
+    {
+      puts ("barrier_destroy failed");
+      exit (1);
+    }
+
+  if (pthread_mutexattr_destroy (&a) != 0)
+    {
+      puts ("mutexattr_destroy failed");
+      exit (1);
+    }
+
+  return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-mutex3.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-mutex3.c
new file mode 100644
index 00000000..8e57924b
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-mutex3.c
@@ -0,0 +1,225 @@
+/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2002.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+
+
+static pthread_mutex_t m;
+static pthread_barrier_t b;
+
+
+static void *
+tf (void *arg)
+{
+  int e = pthread_mutex_unlock (&m);
+  if (e == 0)
+    {
+      puts ("1st mutex_unlock in child succeeded");
+      exit (1);
+    }
+  if (e != EPERM)
+    {
+      puts ("1st mutex_unlock in child didn't return EPERM");
+      exit (1);
+    }
+
+  e = pthread_mutex_trylock (&m);
+  if (e == 0)
+    {
+      puts ("mutex_trylock in second thread succeeded");
+      exit (1);
+    }
+  if (e != EBUSY)
+    {
+      puts ("mutex_trylock returned wrong value");
+      exit (1);
+    }
+
+  e = pthread_barrier_wait (&b);
+  if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("barrier_wait failed");
+      exit (1);
+    }
+
+  e = pthread_barrier_wait (&b);
+  if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("barrier_wait failed");
+      exit (1);
+    }
+
+  e = pthread_mutex_unlock (&m);
+  if (e == 0)
+    {
+      puts ("2nd mutex_unlock in child succeeded");
+      exit (1);
+    }
+  if (e != EPERM)
+    {
+      puts ("2nd mutex_unlock in child didn't return EPERM");
+      exit (1);
+    }
+
+  if (pthread_mutex_trylock (&m) != 0)
+    {
+      puts ("2nd mutex_trylock in second thread failed");
+      exit (1);
+    }
+
+  if (pthread_mutex_unlock (&m) != 0)
+    {
+      puts ("3rd mutex_unlock in second thread failed");
+      exit (1);
+    }
+
+  return NULL;
+}
+
+
+static int
+do_test (void)
+{
+  pthread_mutexattr_t a;
+
+  if (pthread_mutexattr_init (&a) != 0)
+    {
+      puts ("mutexattr_init failed");
+      return 1;
+    }
+
+  if (pthread_mutexattr_settype (&a, PTHREAD_MUTEX_RECURSIVE) != 0)
+    {
+      puts ("mutexattr_settype failed");
+      return 1;
+    }
+
+  if (pthread_mutex_init (&m, &a) != 0)
+    {
+      puts ("mutex_init failed");
+      return 1;
+    }
+
+  if (pthread_barrier_init (&b, NULL, 2) != 0)
+    {
+      puts ("barrier_init failed");
+      return 1;
+    }
+
+  if (pthread_mutex_lock (&m) != 0)
+    {
+      puts ("mutex_lock failed");
+      return 1;
+    }
+
+  if (pthread_mutex_lock (&m) != 0)
+    {
+      puts ("2nd mutex_lock failed");
+      return 1;
+    }
+
+  if (pthread_mutex_trylock (&m) != 0)
+    {
+      puts ("1st trylock failed");
+      return 1;
+    }
+
+  if (pthread_mutex_unlock (&m) != 0)
+    {
+      puts ("mutex_unlock failed");
+      return 1;
+    }
+
+  if (pthread_mutex_unlock (&m) != 0)
+    {
+      puts ("2nd mutex_unlock failed");
+      return 1;
+    }
+
+  pthread_t th;
+  if (pthread_create (&th, NULL, tf, NULL) != 0)
+    {
+      puts ("create failed");
+      return 1;
+    }
+
+  int e = pthread_barrier_wait (&b);
+  if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("barrier_wait failed");
+      return 1;
+    }
+
+  if (pthread_mutex_unlock (&m) != 0)
+    {
+      puts ("3rd mutex_unlock failed");
+      return 1;
+    }
+
+  e = pthread_mutex_unlock (&m);
+  if (e == 0)
+    {
+      puts ("4th mutex_unlock succeeded");
+      return 1;
+    }
+  if (e != EPERM)
+    {
+      puts ("4th mutex_unlock didn't return EPERM");
+      return 1;
+    }
+
+  e = pthread_barrier_wait (&b);
+  if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("barrier_wait failed");
+      return 1;
+    }
+
+  if (pthread_join (th, NULL) != 0)
+    {
+      puts ("join failed");
+      return 1;
+    }
+
+  if (pthread_barrier_destroy (&b) != 0)
+    {
+      puts ("barrier_destroy failed");
+      return 1;
+    }
+
+  if (pthread_mutex_destroy (&m) != 0)
+    {
+      puts ("mutex_destroy failed");
+      return 1;
+    }
+
+  if (pthread_mutexattr_destroy (&a) != 0)
+    {
+      puts ("mutexattr_destroy failed");
+      return 1;
+    }
+
+  return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-mutex4.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-mutex4.c
new file mode 100644
index 00000000..0ce7313c
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-mutex4.c
@@ -0,0 +1,191 @@
+/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2002.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+static int
+do_test (void)
+{
+  size_t ps = sysconf (_SC_PAGESIZE);
+  char tmpfname[] = "/tmp/tst-mutex4.XXXXXX";
+  char data[ps];
+  void *mem;
+  int fd;
+  pthread_mutex_t *m;
+  pthread_mutexattr_t a;
+  pid_t pid;
+  char *p;
+  int err;
+  int s;
+
+  fd = mkstemp (tmpfname);
+  if (fd == -1)
+    {
+      printf ("cannot open temporary file: %m\n");
+      return 1;
+    }
+
+  /* Make sure it is always removed.  */
+  unlink (tmpfname);
+
+  /* Create one page of data.  */
+  memset (data, '\0', ps);
+
+  /* Write the data to the file.  */
+  if (write (fd, data, ps) != (ssize_t) ps)
+    {
+      puts ("short write");
+      return 1;
+    }
+
+  mem = mmap (NULL, ps, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+  if (mem == MAP_FAILED)
+    {
+      printf ("mmap failed: %m\n");
+      return 1;
+    }
+
+  m = (pthread_mutex_t *) (((uintptr_t) mem + __alignof (pthread_mutex_t))
+			   & ~(__alignof (pthread_mutex_t) - 1));
+  p = (char *) (m + 1);
+
+  if (pthread_mutexattr_init (&a) != 0)
+    {
+      puts ("mutexattr_init failed");
+      return 1;
+    }
+
+  if (pthread_mutexattr_getpshared (&a, &s) != 0)
+    {
+      puts ("1st mutexattr_getpshared failed");
+      return 1;
+    }
+
+  if (s != PTHREAD_PROCESS_PRIVATE)
+    {
+      puts ("default pshared value wrong");
+      return 1;
+    }
+
+  if (pthread_mutexattr_setpshared (&a, PTHREAD_PROCESS_SHARED) != 0)
+    {
+      puts ("mutexattr_setpshared failed");
+      return 1;
+    }
+
+  if (pthread_mutexattr_getpshared (&a, &s) != 0)
+    {
+      puts ("2nd mutexattr_getpshared failed");
+      return 1;
+    }
+
+  if (s != PTHREAD_PROCESS_SHARED)
+    {
+      puts ("pshared value after setpshared call wrong");
+      return 1;
+    }
+
+  if (pthread_mutex_init (m, &a) != 0)
+    {
+      puts ("mutex_init failed");
+      return 1;
+    }
+
+  if (pthread_mutex_lock (m) != 0)
+    {
+      puts ("mutex_lock failed");
+      return 1;
+    }
+
+  if (pthread_mutexattr_destroy (&a) != 0)
+    {
+      puts ("mutexattr_destroy failed");
+      return 1;
+    }
+
+  err = pthread_mutex_trylock (m);
+  if (err == 0)
+    {
+      puts ("mutex_trylock succeeded");
+      return 1;
+    }
+  else if (err != EBUSY)
+    {
+      puts ("mutex_trylock didn't return EBUSY");
+      return 1;
+    }
+
+  *p = 0;
+
+  puts ("going to fork now");
+  pid = fork ();
+  if (pid == -1)
+    {
+      puts ("fork failed");
+      return 1;
+    }
+  else if (pid == 0)
+    {
+      /* Play some lock ping-pong.  It's our turn to unlock first.  */
+      if ((*p)++ != 0)
+	{
+	  puts ("child: *p != 0");
+	  return 1;
+	}
+
+      if (pthread_mutex_unlock (m) != 0)
+	{
+	  puts ("child: 1st mutex_unlock failed");
+	  return 1;
+	}
+
+      puts ("child done");
+    }
+  else
+    {
+      if (pthread_mutex_lock (m) != 0)
+	{
+	  puts ("parent: 2nd mutex_lock failed");
+	  return 1;
+	}
+
+      if (*p != 1)
+	{
+	  puts ("*p != 1");
+	  return 1;
+	}
+
+      puts ("parent done");
+    }
+
+  return 0;
+}
+
+#define TIMEOUT 4
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-mutex5.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-mutex5.c
new file mode 100644
index 00000000..eb35b78d
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-mutex5.c
@@ -0,0 +1,186 @@
+/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2002.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+#ifndef TYPE
+# define TYPE PTHREAD_MUTEX_NORMAL
+#endif
+
+
+static int
+do_test (void)
+{
+  pthread_mutex_t m;
+  struct timespec ts;
+  struct timeval tv;
+  struct timeval tv2;
+  int err;
+  pthread_mutexattr_t a;
+
+  if (pthread_mutexattr_init (&a) != 0)
+    {
+      puts ("mutexattr_init failed");
+      return 1;
+    }
+
+  if (pthread_mutexattr_settype (&a, TYPE) != 0)
+    {
+      puts ("mutexattr_settype failed");
+      return 1;
+    }
+
+  if (pthread_mutex_init (&m, &a) != 0)
+    {
+      puts ("mutex_init failed");
+      return 1;
+    }
+
+  if (pthread_mutexattr_destroy (&a) != 0)
+    {
+      puts ("mutexattr_destroy failed");
+      return 1;
+    }
+
+  if (pthread_mutex_lock (&m) != 0)
+    {
+      puts ("mutex_lock failed");
+      return 1;
+    }
+
+  if (pthread_mutex_trylock (&m) == 0)
+    {
+      puts ("mutex_trylock succeeded");
+      return 1;
+    }
+
+  gettimeofday (&tv, NULL);
+  TIMEVAL_TO_TIMESPEC (&tv, &ts);
+
+  ts.tv_sec += 2;	/* Wait 2 seconds.  */
+
+  err = pthread_mutex_timedlock (&m, &ts);
+  if (err == 0)
+    {
+      puts ("timedlock succeeded");
+      return 1;
+    }
+  else if (err != ETIMEDOUT)
+    {
+      printf ("timedlock error != ETIMEDOUT: %d\n", err);
+      return 1;
+    }
+  else
+    {
+      int clk_tck = sysconf (_SC_CLK_TCK);
+
+      gettimeofday (&tv2, NULL);
+
+      tv2.tv_sec -= tv.tv_sec;
+      tv2.tv_usec -= tv.tv_usec;
+      if (tv2.tv_usec < 0)
+	{
+	  tv2.tv_usec += 1000000;
+	  tv2.tv_sec -= 1;
+	}
+
+      /* Be a bit tolerant, add one CLK_TCK.  */
+      tv2.tv_usec += 1000000 / clk_tck;
+      if (tv2.tv_usec >= 1000000)
+	{
+	  tv2.tv_usec -= 1000000;
+	  ++tv2.tv_sec;
+	}
+
+      if (tv2.tv_sec < 2)
+	{
+	  printf ("premature timeout: %ld.%06ld difference\n",
+		  tv2.tv_sec, tv2.tv_usec);
+	  return 1;
+	}
+    }
+
+  (void) gettimeofday (&tv, NULL);
+  TIMEVAL_TO_TIMESPEC (&tv, &ts);
+
+  ts.tv_sec += 2;	/* Wait 2 seconds.  */
+  /* The following makes the ts value invalid.  */
+  ts.tv_nsec += 1000000000;
+
+  err = pthread_mutex_timedlock (&m, &ts);
+  if (err == 0)
+    {
+      puts ("2nd timedlock succeeded");
+      return 1;
+    }
+  else if (err != EINVAL)
+    {
+      printf ("2nd timedlock error != EINVAL: %d\n", err);
+      return 1;
+    }
+
+  if (pthread_mutex_unlock (&m) != 0)
+    {
+      puts ("mutex_unlock failed");
+      return 1;
+    }
+
+  (void) gettimeofday (&tv, NULL);
+  TIMEVAL_TO_TIMESPEC (&tv, &ts);
+
+  ts.tv_sec += 2;	/* Wait 2 seconds.  */
+  if (pthread_mutex_timedlock (&m, &ts) != 0)
+    {
+      puts ("3rd timedlock failed");
+    }
+
+  (void) gettimeofday (&tv2, NULL);
+
+  /* Check that timedlock didn't delay.  We use a limit of 0.1 secs.  */
+  timersub (&tv2, &tv, &tv2);
+  if (tv2.tv_sec > 0 || tv2.tv_usec > 100000)
+    {
+      puts ("3rd timedlock didn't return right away");
+      return 1;
+    }
+
+  if (pthread_mutex_unlock (&m) != 0)
+    {
+      puts ("final mutex_unlock failed");
+      return 1;
+    }
+
+  if (pthread_mutex_destroy (&m) != 0)
+    {
+      puts ("mutex_destroy failed");
+      return 1;
+    }
+
+  return 0;
+}
+
+#define TIMEOUT 4
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-mutex5a.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-mutex5a.c
new file mode 100644
index 00000000..f91eec0d
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-mutex5a.c
@@ -0,0 +1,2 @@
+#define TYPE PTHREAD_MUTEX_ADAPTIVE_NP
+#include "tst-mutex5.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-mutex6.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-mutex6.c
new file mode 100644
index 00000000..f066c62e
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-mutex6.c
@@ -0,0 +1,55 @@
+/* Copyright (C) 2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2002.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+
+
+static int
+do_test (void)
+{
+  pthread_mutex_t m;
+
+  if (pthread_mutex_init (&m, NULL) != 0)
+    {
+      puts ("mutex_init failed");
+      return 1;
+    }
+
+  if (pthread_mutex_lock (&m) != 0)
+    {
+      puts ("1st mutex_lock failed");
+      return 1;
+    }
+
+  /* Set an alarm for 1 second.  The wrapper will expect this.  */
+  alarm (1);
+
+  /* This call should never return.  */
+  pthread_mutex_lock (&m);
+
+  puts ("2nd mutex_lock returned");
+  return 1;
+}
+
+#define EXPECTED_SIGNAL SIGALRM
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-mutex7.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-mutex7.c
new file mode 100644
index 00000000..a9b9f318
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-mutex7.c
@@ -0,0 +1,121 @@
+/* Copyright (C) 2002, 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2002.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+
+
+#ifndef INIT
+# define INIT PTHREAD_MUTEX_INITIALIZER
+#endif
+
+
+static pthread_mutex_t lock = INIT;
+
+
+#define ROUNDS 1000
+#define N 100
+
+
+static void *
+tf (void *arg)
+{
+  int nr = (long int) arg;
+  int cnt;
+  struct timespec ts = { .tv_sec = 0, .tv_nsec = 11000 };
+
+  for (cnt = 0; cnt < ROUNDS; ++cnt)
+    {
+      if (pthread_mutex_lock (&lock) != 0)
+	{
+	  printf ("thread %d: failed to get the lock\n", nr);
+	  return (void *) 1l;
+	}
+
+      if (pthread_mutex_unlock (&lock) != 0)
+	{
+	  printf ("thread %d: failed to release the lock\n", nr);
+	  return (void *) 1l;
+	}
+
+      nanosleep (&ts, NULL);
+    }
+
+  return NULL;
+}
+
+
+static int
+do_test (void)
+{
+  pthread_attr_t at;
+  pthread_t th[N];
+  int cnt;
+
+  if (pthread_attr_init (&at) != 0)
+    {
+      puts ("attr_init failed");
+      return 1;
+    }
+
+  if (pthread_attr_setstacksize (&at, 1 * 1024 * 1024) != 0)
+    {
+      puts ("attr_setstacksize failed");
+      return 1;
+    }
+
+  if (pthread_mutex_lock (&lock) != 0)
+    {
+      puts ("locking in parent failed");
+      return 1;
+    }
+
+  for (cnt = 0; cnt < N; ++cnt)
+    if (pthread_create (&th[cnt], &at, tf, (void *) (long int) cnt) != 0)
+      {
+	printf ("creating thread %d failed\n", cnt);
+	return 1;
+      }
+
+  if (pthread_attr_destroy (&at) != 0)
+    {
+      puts ("attr_destroy failed");
+      return 1;
+    }
+
+  if (pthread_mutex_unlock (&lock) != 0)
+    {
+      puts ("unlocking in parent failed");
+      return 1;
+    }
+
+  for (cnt = 0; cnt < N; ++cnt)
+    if (pthread_join (th[cnt], NULL) != 0)
+      {
+	printf ("joining thread %d failed\n", cnt);
+	return 1;
+      }
+
+  return 0;
+}
+
+#define TIMEOUT 60
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-mutex7a.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-mutex7a.c
new file mode 100644
index 00000000..f08799ae
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-mutex7a.c
@@ -0,0 +1,2 @@
+#define INIT PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
+#include "tst-mutex7.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-mutex8.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-mutex8.c
new file mode 100644
index 00000000..80ebe71f
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-mutex8.c
@@ -0,0 +1,367 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+/* This test checks behavior not required by POSIX.  */
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+static pthread_mutex_t *m;
+static pthread_barrier_t b;
+static pthread_cond_t c;
+static bool done;
+
+
+static void
+cl (void *arg)
+{
+  if (pthread_mutex_unlock (m) != 0)
+    {
+      puts ("cl: mutex_unlocked failed");
+      exit (1);
+    }
+}
+
+
+static void *
+tf (void *arg)
+{
+  if (pthread_mutex_lock (m) != 0)
+    {
+      puts ("tf: mutex_lock failed");
+      return (void *) 1l;
+    }
+
+  int e = pthread_barrier_wait (&b);
+  if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("barrier_wait failed");
+      return (void *) 1l;
+    }
+
+  if (arg == NULL)
+    do
+      if (pthread_cond_wait (&c, m) != 0)
+	{
+	  puts ("tf: cond_wait failed");
+	  return (void *) 1l;
+	}
+    while (! done);
+  else
+    do
+      {
+	pthread_cleanup_push (cl, NULL);
+
+	if (pthread_cond_wait (&c, m) != 0)
+	  {
+	    puts ("tf: cond_wait failed");
+	    return (void *) 1l;
+	  }
+
+	pthread_cleanup_pop (0);
+      }
+    while (! done);
+
+  if (pthread_mutex_unlock (m) != 0)
+    {
+      puts ("tf: mutex_unlock failed");
+      return (void *) 1l;
+    }
+
+  return NULL;
+}
+
+
+static int
+check_type (const char *mas, pthread_mutexattr_t *ma)
+{
+  if (pthread_mutex_init (m, ma) != 0)
+    {
+      printf ("1st mutex_init failed for %s\n", mas);
+      return 1;
+    }
+
+  if (pthread_mutex_destroy (m) != 0)
+    {
+      printf ("immediate mutex_destroy failed for %s\n", mas);
+      return 1;
+    }
+
+  if (pthread_mutex_init (m, ma) != 0)
+    {
+      printf ("2nd mutex_init failed for %s\n", mas);
+      return 1;
+    }
+
+  if (pthread_mutex_lock (m) != 0)
+    {
+      printf ("1st mutex_lock failed for %s\n", mas);
+      return 1;
+    }
+
+  int e = pthread_mutex_destroy (m);
+  if (e == 0)
+    {
+      printf ("mutex_destroy of self-locked mutex succeeded for %s\n", mas);
+      return 1;
+    }
+  if (e != EBUSY)
+    {
+      printf ("mutex_destroy of self-locked mutex did not return EBUSY %s\n",
+	      mas);
+      return 1;
+    }
+
+  if (pthread_mutex_unlock (m) != 0)
+    {
+      printf ("1st mutex_unlock failed for %s\n", mas);
+      return 1;
+    }
+
+  if (pthread_mutex_trylock (m) != 0)
+    {
+      printf ("mutex_trylock failed for %s\n", mas);
+      return 1;
+    }
+
+  e = pthread_mutex_destroy (m);
+  if (e == 0)
+    {
+      printf ("mutex_destroy of self-trylocked mutex succeeded for %s\n", mas);
+      return 1;
+    }
+  if (e != EBUSY)
+    {
+      printf ("\
+mutex_destroy of self-trylocked mutex did not return EBUSY %s\n",
+	      mas);
+      return 1;
+    }
+
+  if (pthread_mutex_unlock (m) != 0)
+    {
+      printf ("2nd mutex_unlock failed for %s\n", mas);
+      return 1;
+    }
+
+  pthread_t th;
+  if (pthread_create (&th, NULL, tf, NULL) != 0)
+    {
+      puts ("1st create failed");
+      return 1;
+    }
+  done = false;
+
+  e = pthread_barrier_wait (&b);
+  if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("1st barrier_wait failed");
+      return 1;
+    }
+
+  if (pthread_mutex_lock (m) != 0)
+    {
+      printf ("2nd mutex_lock failed for %s\n", mas);
+      return 1;
+    }
+
+  if (pthread_mutex_unlock (m) != 0)
+    {
+      printf ("3rd mutex_unlock failed for %s\n", mas);
+      return 1;
+    }
+
+  e = pthread_mutex_destroy (m);
+  if (e == 0)
+    {
+      printf ("mutex_destroy of condvar-used mutex succeeded for %s\n", mas);
+      return 1;
+    }
+  if (e != EBUSY)
+    {
+      printf ("\
+mutex_destroy of condvar-used mutex did not return EBUSY for %s\n", mas);
+      return 1;
+    }
+
+  done = true;
+  if (pthread_cond_signal (&c) != 0)
+    {
+      puts ("cond_signal failed");
+      return 1;
+    }
+
+  void *r;
+  if (pthread_join (th, &r) != 0)
+    {
+      puts ("join failed");
+      return 1;
+    }
+  if (r != NULL)
+    {
+      puts ("thread didn't return NULL");
+      return 1;
+    }
+
+  if (pthread_mutex_destroy (m) != 0)
+    {
+      printf ("mutex_destroy after condvar-use failed for %s\n", mas);
+      return 1;
+    }
+
+  if (pthread_mutex_init (m, ma) != 0)
+    {
+      printf ("3rd mutex_init failed for %s\n", mas);
+      return 1;
+    }
+
+  if (pthread_create (&th, NULL, tf, (void *) 1) != 0)
+    {
+      puts ("2nd create failed");
+      return 1;
+    }
+  done = false;
+
+  e = pthread_barrier_wait (&b);
+  if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("2nd barrier_wait failed");
+      return 1;
+    }
+
+  if (pthread_mutex_lock (m) != 0)
+    {
+      printf ("3rd mutex_lock failed for %s\n", mas);
+      return 1;
+    }
+
+  if (pthread_mutex_unlock (m) != 0)
+    {
+      printf ("4th mutex_unlock failed for %s\n", mas);
+      return 1;
+    }
+
+  e = pthread_mutex_destroy (m);
+  if (e == 0)
+    {
+      printf ("2nd mutex_destroy of condvar-used mutex succeeded for %s\n",
+	      mas);
+      return 1;
+    }
+  if (e != EBUSY)
+    {
+      printf ("\
+2nd mutex_destroy of condvar-used mutex did not return EBUSY for %s\n",
+	      mas);
+      return 1;
+    }
+
+  if (pthread_cancel (th) != 0)
+    {
+      puts ("cond_cancel failed");
+      return 1;
+    }
+
+  if (pthread_join (th, &r) != 0)
+    {
+      puts ("join failed");
+      return 1;
+    }
+  if (r != PTHREAD_CANCELED)
+    {
+      puts ("thread not canceled");
+      return 1;
+    }
+
+  if (pthread_mutex_destroy (m) != 0)
+    {
+      printf ("mutex_destroy after condvar-canceled failed for %s\n", mas);
+      return 1;
+    }
+
+  return 0;
+}
+
+
+static int
+do_test (void)
+{
+  pthread_mutex_t mm;
+  m = &mm;
+
+  if (pthread_barrier_init (&b, NULL, 2) != 0)
+    {
+      puts ("barrier_init failed");
+      return 1;
+    }
+
+  if (pthread_cond_init (&c, NULL) != 0)
+    {
+      puts ("cond_init failed");
+      return 1;
+    }
+
+  puts ("check normal mutex");
+  int res = check_type ("normal", NULL);
+
+  pthread_mutexattr_t ma;
+  if (pthread_mutexattr_init (&ma) != 0)
+    {
+      puts ("1st mutexattr_init failed");
+      return 1;
+    }
+  if (pthread_mutexattr_settype (&ma, PTHREAD_MUTEX_RECURSIVE) != 0)
+    {
+      puts ("1st mutexattr_settype failed");
+      return 1;
+    }
+  puts ("check recursive mutex");
+  res |= check_type ("recursive", &ma);
+  if (pthread_mutexattr_destroy (&ma) != 0)
+    {
+      puts ("1st mutexattr_destroy failed");
+      return 1;
+    }
+
+  if (pthread_mutexattr_init (&ma) != 0)
+    {
+      puts ("2nd mutexattr_init failed");
+      return 1;
+    }
+  if (pthread_mutexattr_settype (&ma, PTHREAD_MUTEX_ERRORCHECK) != 0)
+    {
+      puts ("2nd mutexattr_settype failed");
+      return 1;
+    }
+  puts ("check error-checking mutex");
+  res |= check_type ("error-checking", &ma);
+  if (pthread_mutexattr_destroy (&ma) != 0)
+    {
+      puts ("2nd mutexattr_destroy failed");
+      return 1;
+    }
+
+  return res;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-mutex9.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-mutex9.c
new file mode 100644
index 00000000..3748584b
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-mutex9.c
@@ -0,0 +1,191 @@
+/* Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+int gettimeofday(struct timeval *tv, struct timezone *tz);
+
+
+static int
+do_test (void)
+{
+  size_t ps = sysconf (_SC_PAGESIZE);
+  char tmpfname[] = "/tmp/tst-mutex9.XXXXXX";
+  char data[ps];
+  void *mem;
+  int fd;
+  pthread_mutex_t *m;
+  pthread_mutexattr_t a;
+  pid_t pid;
+  char *p;
+
+  fd = mkstemp (tmpfname);
+  if (fd == -1)
+    {
+      printf ("cannot open temporary file: %m\n");
+      return 1;
+    }
+
+  /* Make sure it is always removed.  */
+  unlink (tmpfname);
+
+  /* Create one page of data.  */
+  memset (data, '\0', ps);
+
+  /* Write the data to the file.  */
+  if (write (fd, data, ps) != (ssize_t) ps)
+    {
+      puts ("short write");
+      return 1;
+    }
+
+  mem = mmap (NULL, ps, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+  if (mem == MAP_FAILED)
+    {
+      printf ("mmap failed: %m\n");
+      return 1;
+    }
+
+  m = (pthread_mutex_t *) (((uintptr_t) mem + __alignof (pthread_mutex_t))
+			   & ~(__alignof (pthread_mutex_t) - 1));
+  p = (char *) (m + 1);
+
+  if (pthread_mutexattr_init (&a) != 0)
+    {
+      puts ("mutexattr_init failed");
+      return 1;
+    }
+
+  if (pthread_mutexattr_setpshared (&a, PTHREAD_PROCESS_SHARED) != 0)
+    {
+      puts ("mutexattr_setpshared failed");
+      return 1;
+    }
+
+  if (pthread_mutexattr_settype (&a, PTHREAD_MUTEX_RECURSIVE) != 0)
+    {
+      puts ("mutexattr_settype failed");
+      return 1;
+    }
+
+  if (pthread_mutex_init (m, &a) != 0)
+    {
+      puts ("mutex_init failed");
+      return 1;
+    }
+
+  if (pthread_mutex_lock (m) != 0)
+    {
+      puts ("mutex_lock failed");
+      return 1;
+    }
+
+  if (pthread_mutexattr_destroy (&a) != 0)
+    {
+      puts ("mutexattr_destroy failed");
+      return 1;
+    }
+
+  puts ("going to fork now");
+  pid = fork ();
+  if (pid == -1)
+    {
+      puts ("fork failed");
+      return 1;
+    }
+  else if (pid == 0)
+    {
+      if (pthread_mutex_trylock (m) == 0)
+	{
+	  puts ("child: mutex_trylock succeeded");
+	  exit (1);
+	}
+
+      if (pthread_mutex_unlock (m) == 0)
+	{
+	  puts ("child: mutex_unlock succeeded");
+	  exit (1);
+	}
+
+      struct timeval tv;
+      gettimeofday (&tv, NULL);
+      struct timespec ts;
+      TIMEVAL_TO_TIMESPEC (&tv, &ts);
+      ts.tv_nsec += 500000000;
+      if (ts.tv_nsec >= 1000000000)
+	{
+	  ++ts.tv_sec;
+	  ts.tv_nsec -= 1000000000;
+	}
+
+      int e = pthread_mutex_timedlock (m, &ts);
+      if (e == 0)
+	{
+	  puts ("child: mutex_timedlock succeeded");
+	  exit (1);
+	}
+      if (e != ETIMEDOUT)
+	{
+	  puts ("child: mutex_timedlock didn't time out");
+	  exit (1);
+	}
+
+      alarm (1);
+
+      pthread_mutex_lock (m);
+
+      puts ("child: mutex_lock returned");
+
+      exit (0);
+    }
+
+  sleep (2);
+
+  int status;
+  if (TEMP_FAILURE_RETRY (waitpid (pid, &status, 0)) != pid)
+    {
+      puts ("waitpid failed");
+      return 1;
+    }
+  if (! WIFSIGNALED (status))
+    {
+      puts ("child not killed by signal");
+      return 1;
+    }
+  if (WTERMSIG (status) != SIGALRM)
+    {
+      puts ("child not killed by SIGALRM");
+      return 1;
+    }
+
+  return 0;
+}
+
+#define TIMEOUT 3
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-oddstacklimit.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-oddstacklimit.c
new file mode 100644
index 00000000..9fbef188
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-oddstacklimit.c
@@ -0,0 +1 @@
+#include "tst-basic1.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-once1.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-once1.c
new file mode 100644
index 00000000..87ed51c8
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-once1.c
@@ -0,0 +1,51 @@
+/* Copyright (C) 2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2002.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+
+
+static pthread_once_t once = PTHREAD_ONCE_INIT;
+
+static int global;
+
+static void
+once_handler (void)
+{
+  ++global;
+}
+
+
+static int
+do_test (void)
+{
+  pthread_once (&once, once_handler);
+  pthread_once (&once, once_handler);
+
+  if (global != 1)
+    {
+      printf ("global = %d, expected 1\n", global);
+      return 1;
+    }
+
+  return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-once2.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-once2.c
new file mode 100644
index 00000000..c6063453
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-once2.c
@@ -0,0 +1,104 @@
+/* Copyright (C) 2002, 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2002.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+
+
+#define N 100
+
+static pthread_once_t once = PTHREAD_ONCE_INIT;
+
+static int global;
+
+static void
+once_handler (void)
+{
+  struct timespec ts;
+
+  ++global;
+
+  ts.tv_sec = 2;
+  ts.tv_nsec = 0;
+  nanosleep (&ts, NULL);
+}
+
+
+static void *
+tf (void *arg)
+{
+  pthread_once (&once, once_handler);
+
+  if (global != 1)
+    {
+      printf ("thread %ld: global == %d\n", (long int) arg, global);
+      exit (1);
+    }
+
+  return NULL;
+}
+
+
+static int
+do_test (void)
+{
+  pthread_attr_t at;
+  pthread_t th[N];
+  int cnt;
+
+  if (pthread_attr_init (&at) != 0)
+    {
+      puts ("attr_init failed");
+      return 1;
+    }
+
+  if (pthread_attr_setstacksize (&at, 1 * 1024 * 1024) != 0)
+    {
+      puts ("attr_setstacksize failed");
+      return 1;
+    }
+
+  for (cnt = 0; cnt < N; ++cnt)
+    if (pthread_create (&th[cnt], &at, tf, (void *) (long int) cnt) != 0)
+      {
+	printf ("creation of thread %d failed\n", cnt);
+	return 1;
+      }
+
+  if (pthread_attr_destroy (&at) != 0)
+    {
+      puts ("attr_destroy failed");
+      return 1;
+    }
+
+  for (cnt = 0; cnt < N; ++cnt)
+    if (pthread_join (th[cnt], NULL) != 0)
+      {
+	printf ("join of thread %d failed\n", cnt);
+	return 1;
+      }
+
+  return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#define TIMEOUT 4
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-once3.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-once3.c
new file mode 100644
index 00000000..43b354a3
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-once3.c
@@ -0,0 +1,162 @@
+/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2002.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+
+
+#define N 100
+
+static pthread_once_t once = PTHREAD_ONCE_INIT;
+
+static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
+static pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
+
+static pthread_barrier_t bar;
+
+static int global;
+static int cl_called;
+
+static void
+once_handler1 (void)
+{
+  if (pthread_mutex_lock (&mut) != 0)
+    {
+      puts ("once_handler1: mutex_lock failed");
+      exit (1);
+    }
+  puts ("once_handler1: locked");
+
+  int r = pthread_barrier_wait (&bar);
+  if (r != 0 && r!= PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("once_handler1: barrier_wait failed");
+      exit (1);
+    }
+
+  pthread_cond_wait (&cond, &mut);
+
+  /* We should never get here.  */
+  exit (42);
+}
+
+static void
+once_handler2 (void)
+{
+  global = 1;
+}
+
+
+static void
+cl (void *arg)
+{
+  cl_called = 1;
+}
+
+
+static void *
+tf (void *arg)
+{
+  pthread_cleanup_push (cl, NULL)
+
+  pthread_once (&once, once_handler1);
+
+  pthread_cleanup_pop (0);
+
+  /* We should never get here.  */
+  puts ("pthread_once in tf returned");
+  exit (1);
+}
+
+
+static int
+do_test (void)
+{
+  pthread_t th;
+
+  if (pthread_barrier_init (&bar, NULL, 2) != 0)
+    {
+      puts ("barrier_init failed");
+      return 1;
+    }
+
+  if (pthread_create (&th, NULL, tf, NULL) != 0)
+    {
+      puts ("first create failed");
+      return 1;
+    }
+
+  int r = pthread_barrier_wait (&bar);
+  if (r != 0 && r!= PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("barrier_wait failed");
+      return 1;
+    }
+
+  if (pthread_mutex_lock (&mut) != 0)
+    {
+      puts ("mutex_lock failed");
+      return 1;
+    }
+  /* We unlock the mutex so that we catch the case where the pthread_cond_wait
+     call incorrectly resumes and tries to get the mutex.  */
+  if (pthread_mutex_unlock (&mut) != 0)
+    {
+      puts ("mutex_unlock failed");
+      return 1;
+    }
+
+  /* Cancel the thread.  */
+  puts ("going to cancel");
+  if (pthread_cancel (th) != 0)
+    {
+      puts ("cancel failed");
+      return 1;
+    }
+
+  void *result;
+  pthread_join (th, &result);
+  if (result != PTHREAD_CANCELED)
+    {
+      puts ("join didn't return PTHREAD_CANCELED");
+      return 1;
+    }
+
+  if (cl_called != 1)
+    {
+      puts ("cleanup handler not called");
+      return 1;
+    }
+
+  pthread_once (&once, once_handler2);
+
+  if (global != 1)
+    {
+      puts ("global still 0");
+      return 1;
+    }
+
+  return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#define TIMEOUT 4
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-once4.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-once4.c
new file mode 100644
index 00000000..35bae3c0
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-once4.c
@@ -0,0 +1,202 @@
+/* Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+static pthread_once_t once = PTHREAD_ONCE_INIT;
+
+static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
+static pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
+
+static pthread_barrier_t bar;
+
+static int global;
+static int cl_called;
+
+static void
+once_handler1 (void)
+{
+  if (pthread_mutex_lock (&mut) != 0)
+    {
+      puts ("once_handler1: mutex_lock failed");
+      exit (1);
+    }
+
+  int r = pthread_barrier_wait (&bar);
+  if (r != 0 && r!= PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("once_handler1: barrier_wait failed");
+      exit (1);
+    }
+
+  pthread_cond_wait (&cond, &mut);
+
+  /* We should never get here.  */
+}
+
+
+static void
+once_handler2 (void)
+{
+  global = 1;
+}
+
+
+static void
+cl (void *arg)
+{
+  ++cl_called;
+}
+
+
+static void *
+tf1 (void *arg)
+{
+  pthread_cleanup_push (cl, NULL);
+
+  pthread_once (&once, once_handler1);
+
+  pthread_cleanup_pop (0);
+
+  /* We should never get here.  */
+  puts ("pthread_once in tf returned");
+  exit (1);
+}
+
+
+static void *
+tf2 (void *arg)
+{
+  pthread_cleanup_push (cl, NULL);
+
+  int r = pthread_barrier_wait (&bar);
+  if (r != 0 && r!= PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("once_handler2: barrier_wait failed");
+      exit (1);
+    }
+
+  pthread_cleanup_pop (0);
+
+  pthread_once (&once, once_handler2);
+
+  return NULL;
+}
+
+
+static int
+do_test (void)
+{
+  pthread_t th[2];
+
+  if (pthread_barrier_init (&bar, NULL, 2) != 0)
+    {
+      puts ("barrier_init failed");
+      return 1;
+    }
+
+  if (pthread_create (&th[0], NULL, tf1, NULL) != 0)
+    {
+      puts ("first create failed");
+      return 1;
+    }
+
+  int r = pthread_barrier_wait (&bar);
+  if (r != 0 && r!= PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("first barrier_wait failed");
+      return 1;
+    }
+
+  if (pthread_mutex_lock (&mut) != 0)
+    {
+      puts ("mutex_lock failed");
+      return 1;
+    }
+  /* We unlock the mutex so that we catch the case where the pthread_cond_wait
+     call incorrectly resumes and tries to get the mutex.  */
+  if (pthread_mutex_unlock (&mut) != 0)
+    {
+      puts ("mutex_unlock failed");
+      return 1;
+    }
+
+  if (pthread_create (&th[1], NULL, tf2, NULL) != 0)
+    {
+      puts ("second create failed");
+      return 1;
+    }
+
+  r = pthread_barrier_wait (&bar);
+  if (r != 0 && r!= PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("second barrier_wait failed");
+      return 1;
+    }
+
+  /* Give the second thread a chance to reach the pthread_once call.  */
+  sleep (2);
+
+  /* Cancel the thread.  */
+  if (pthread_cancel (th[0]) != 0)
+    {
+      puts ("cancel failed");
+      return 1;
+    }
+
+  void *result;
+  pthread_join (th[0], &result);
+  if (result != PTHREAD_CANCELED)
+    {
+      puts ("first join didn't return PTHREAD_CANCELED");
+      return 1;
+    }
+
+  puts ("joined first thread");
+
+  pthread_join (th[1], &result);
+  if (result != NULL)
+    {
+      puts ("second join didn't return PTHREAD_CANCELED");
+      return 1;
+    }
+
+  if (global != 1)
+    {
+      puts ("global still 0");
+      return 1;
+    }
+
+  if (cl_called != 1)
+    {
+      printf ("cl_called = %d\n", cl_called);
+      return 1;
+    }
+
+  return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#define TIMEOUT 4
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-oncex3.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-oncex3.c
new file mode 100644
index 00000000..08225b88
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-oncex3.c
@@ -0,0 +1 @@
+#include "tst-once3.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-oncex4.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-oncex4.c
new file mode 100644
index 00000000..9b4d98f3
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-oncex4.c
@@ -0,0 +1 @@
+#include "tst-once4.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-popen1.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-popen1.c
new file mode 100644
index 00000000..a9d07737
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-popen1.c
@@ -0,0 +1,60 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek , 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+static void *
+dummy (void *x)
+{
+  return NULL;
+}
+
+static char buf[sizeof "something\n"];
+
+static int
+do_test (void)
+{
+  FILE *f;
+  pthread_t p;
+  int err;
+
+  f = popen ("echo something", "r");
+  if (f == NULL)
+    error (EXIT_FAILURE, errno, "popen failed");
+  if (fgets (buf, sizeof (buf), f) == NULL)
+    error (EXIT_FAILURE, 0, "fgets failed");
+  if (strcmp (buf, "something\n"))
+    error (EXIT_FAILURE, 0, "read wrong data");
+  if (pclose (f))
+    error (EXIT_FAILURE, errno, "pclose returned non-zero");
+  if ((err = pthread_create (&p, NULL, dummy, NULL)))
+    error (EXIT_FAILURE, err, "pthread_create failed");
+  if ((err = pthread_join (p, NULL)))
+    error (EXIT_FAILURE, err, "pthread_join failed");
+  exit (0);
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-raise1.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-raise1.c
new file mode 100644
index 00000000..5ea9886a
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-raise1.c
@@ -0,0 +1,62 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek , 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+volatile int count;
+
+void
+sh (int sig)
+{
+  ++count;
+}
+
+int
+main (void)
+{
+  struct sigaction sa;
+  sa.sa_handler = sh;
+  sigemptyset (&sa.sa_mask);
+  sa.sa_flags = 0;
+  if (sigaction (SIGUSR1, &sa, NULL) < 0)
+    {
+      printf ("sigaction failed: %m\n");
+      exit (1);
+    }
+  if (raise (SIGUSR1) < 0)
+    {
+      printf ("first raise failed: %m\n");
+      exit (1);
+    }
+  if (raise (SIGUSR1) < 0)
+    {
+      printf ("second raise failed: %m\n");
+      exit (1);
+    }
+  if (count != 2)
+    {
+      printf ("signal handler not called 2 times\n");
+      exit (1);
+    }
+  exit (0);
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-rwlock1.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-rwlock1.c
new file mode 100644
index 00000000..c97e0e60
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-rwlock1.c
@@ -0,0 +1,117 @@
+/* Copyright (C) 2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2002.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+
+
+static int
+do_test (void)
+{
+  pthread_rwlock_t r;
+
+  if (pthread_rwlock_init (&r, NULL) != 0)
+    {
+      puts ("rwlock_init failed");
+      return 1;
+    }
+  puts ("rwlock_init succeeded");
+
+  if (pthread_rwlock_rdlock (&r) != 0)
+    {
+      puts ("1st rwlock_rdlock failed");
+      return 1;
+    }
+  puts ("1st rwlock_rdlock succeeded");
+
+  if (pthread_rwlock_rdlock (&r) != 0)
+    {
+      puts ("2nd rwlock_rdlock failed");
+      return 1;
+    }
+  puts ("2nd rwlock_rdlock succeeded");
+
+  if (pthread_rwlock_unlock (&r) != 0)
+    {
+      puts ("1st rwlock_unlock failed");
+      return 1;
+    }
+  puts ("1st rwlock_unlock succeeded");
+
+  if (pthread_rwlock_unlock (&r) != 0)
+    {
+      puts ("2nd rwlock_unlock failed");
+      return 1;
+    }
+  puts ("2nd rwlock_unlock succeeded");
+
+  if (pthread_rwlock_wrlock (&r) != 0)
+    {
+      puts ("1st rwlock_wrlock failed");
+      return 1;
+    }
+  puts ("1st rwlock_wrlock succeeded");
+
+  if (pthread_rwlock_unlock (&r) != 0)
+    {
+      puts ("3rd rwlock_unlock failed");
+      return 1;
+    }
+  puts ("3rd rwlock_unlock succeeded");
+
+  if (pthread_rwlock_wrlock (&r) != 0)
+    {
+      puts ("2nd rwlock_wrlock failed");
+      return 1;
+    }
+  puts ("2nd rwlock_wrlock succeeded");
+
+  if (pthread_rwlock_unlock (&r) != 0)
+    {
+      puts ("4th rwlock_unlock failed");
+      return 1;
+    }
+  puts ("4th rwlock_unlock succeeded");
+
+  if (pthread_rwlock_rdlock (&r) != 0)
+    {
+      puts ("3rd rwlock_rdlock failed");
+      return 1;
+    }
+  puts ("3rd rwlock_rdlock succeeded");
+
+  if (pthread_rwlock_unlock (&r) != 0)
+    {
+      puts ("5th rwlock_unlock failed");
+      return 1;
+    }
+  puts ("5th rwlock_unlock succeeded");
+
+  if (pthread_rwlock_destroy (&r) != 0)
+    {
+      puts ("rwlock_destroy failed");
+      return 1;
+    }
+  puts ("rwlock_destroy succeeded");
+
+  return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-rwlock10.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-rwlock10.c
new file mode 100644
index 00000000..43156eae
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-rwlock10.c
@@ -0,0 +1,21 @@
+/* Test program for timedout read/write lock functions.
+   Copyright (C) 2003 Free Software Foundation, Inc.
+   Contributed by Ulrich Drepper , 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public License as
+   published by the Free Software Foundation; either version 2.1 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#define INIT PTHREAD_RWLOCK_INITIALIZER
+#include "tst-rwlock8.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-rwlock11.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-rwlock11.c
new file mode 100644
index 00000000..ed9af7ed
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-rwlock11.c
@@ -0,0 +1,21 @@
+/* Test program for timedout read/write lock functions.
+   Copyright (C) 2003 Free Software Foundation, Inc.
+   Contributed by Ulrich Drepper , 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public License as
+   published by the Free Software Foundation; either version 2.1 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#define INIT PTHREAD_RWLOCK_INITIALIZER
+#include "tst-rwlock9.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-rwlock12.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-rwlock12.c
new file mode 100644
index 00000000..91f25d3b
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-rwlock12.c
@@ -0,0 +1,208 @@
+/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2002.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+static int
+do_test (void)
+{
+  size_t ps = sysconf (_SC_PAGESIZE);
+  char tmpfname[] = "/tmp/tst-rwlock12.XXXXXX";
+  char data[ps];
+  void *mem;
+  int fd;
+  pthread_mutex_t *m;
+  pthread_mutexattr_t ma;
+  pthread_rwlock_t *r;
+  pthread_rwlockattr_t ra;
+  pid_t pid;
+  int status = 0;
+
+  fd = mkstemp (tmpfname);
+  if (fd == -1)
+    {
+      printf ("cannot open temporary file: %m\n");
+      return 1;
+    }
+
+  /* Make sure it is always removed.  */
+  unlink (tmpfname);
+
+  /* Create one page of data.  */
+  memset (data, '\0', ps);
+
+  /* Write the data to the file.  */
+  if (write (fd, data, ps) != (ssize_t) ps)
+    {
+      puts ("short write");
+      return 1;
+    }
+
+  mem = mmap (NULL, ps, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+  if (mem == MAP_FAILED)
+    {
+      printf ("mmap failed: %m\n");
+      return 1;
+    }
+
+  r = (pthread_rwlock_t *) (((uintptr_t) mem + __alignof (pthread_rwlock_t))
+			    & ~(__alignof (pthread_rwlock_t) - 1));
+  /* The following assumes alignment for a mutex is at least as high
+     as that for a rwlock.  Which is true in our case.  */
+  m = (pthread_mutex_t *) (r + 1);
+
+  if (pthread_rwlockattr_init (&ra) != 0)
+    {
+      puts ("rwlockattr_init failed");
+      return 1;
+    }
+
+  if (pthread_rwlockattr_setpshared (&ra, PTHREAD_PROCESS_SHARED) != 0)
+    {
+      puts ("rwlockattr_setpshared failed");
+      return 1;
+    }
+
+  if (pthread_rwlock_init (r, &ra) != 0)
+    {
+      puts ("rwlock_init failed");
+      return 1;
+    }
+
+  if (pthread_mutexattr_init (&ma) != 0)
+    {
+      puts ("rwlockattr_init failed");
+      return 1;
+    }
+
+  if (pthread_mutexattr_setpshared (&ma, PTHREAD_PROCESS_SHARED) != 0)
+    {
+      puts ("mutexattr_setpshared failed");
+      return 1;
+    }
+
+  if (pthread_mutex_init (m, &ma) != 0)
+    {
+      puts ("mutex_init failed");
+      return 1;
+    }
+
+  /* Lock the mutex.  */
+  if (pthread_mutex_lock (m) != 0)
+    {
+      puts ("mutex_lock failed");
+      return 1;
+    }
+
+  puts ("going to fork now");
+  pid = fork ();
+  if (pid == -1)
+    {
+      puts ("fork failed");
+      return 1;
+    }
+  else if (pid == 0)
+    {
+      /* Lock the mutex.  */
+      if (pthread_mutex_lock (m) != 0)
+	{
+	  puts ("child: mutex_lock failed");
+	  return 1;
+	}
+
+      /* Try to get the rwlock.  */
+      if (pthread_rwlock_trywrlock (r) == 0)
+	{
+	  puts ("rwlock_trywrlock succeeded");
+	  return 1;
+	}
+
+      /* Try again.  */
+      struct timespec ts = { .tv_sec = 0, .tv_nsec = 500000000 };
+      int e = pthread_rwlock_timedwrlock (r, &ts);
+      if (e == 0)
+	{
+	  puts ("rwlock_timedwrlock succeeded");
+	  return 1;
+	}
+      if (e != ETIMEDOUT)
+	{
+	  puts ("rwlock_timedwrlock didn't return ETIMEDOUT");
+	  status = 1;
+	}
+
+      if (pthread_rwlock_tryrdlock (r) == 0)
+	{
+	  puts ("rwlock_tryrdlock succeeded");
+	  return 1;
+	}
+
+      e = pthread_rwlock_timedrdlock (r, &ts);
+      if (e == 0)
+	{
+	  puts ("rwlock_timedrdlock succeeded");
+	  return 1;
+	}
+      if (e != ETIMEDOUT)
+	{
+	  puts ("rwlock_timedrdlock didn't return ETIMEDOUT");
+	  status = 1;
+	}
+    }
+  else
+    {
+      /* Lock the rwlock for writing.  */
+      if (pthread_rwlock_wrlock (r) != 0)
+	{
+	  puts ("rwlock_wrlock failed");
+	  kill (pid, SIGTERM);
+	  return 1;
+	}
+
+      /* Allow the child to run.  */
+      if (pthread_mutex_unlock (m) != 0)
+	{
+	  puts ("mutex_unlock failed");
+	  kill (pid, SIGTERM);
+	  return 1;
+	}
+
+      /* Just wait for the child.  */
+      if (TEMP_FAILURE_RETRY (waitpid (pid, &status, 0)) != pid)
+	{
+	  puts ("waitpid failed");
+	  kill (pid, SIGTERM);
+	  return 1;
+	}
+    }
+
+  return status;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-rwlock13.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-rwlock13.c
new file mode 100644
index 00000000..61d5b83e
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-rwlock13.c
@@ -0,0 +1,71 @@
+/* Copyright (C) 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+
+
+static int
+do_test (void)
+{
+  pthread_rwlock_t r;
+  int ret;
+
+  memset (&r, 0xaa, sizeof (r));
+  if ((ret = pthread_rwlock_init (&r, NULL)) != 0)
+    {
+      printf ("rwlock_init failed: %d\n", ret);
+      return 1;
+    }
+
+  if ((ret = pthread_rwlock_rdlock (&r)) != 0)
+    {
+      printf ("rwlock_rdlock failed: %d\n", ret);
+      return 1;
+    }
+
+  if ((ret = pthread_rwlock_unlock (&r)) != 0)
+    {
+      printf ("rwlock_unlock failed: %d\n", ret);
+      return 1;
+    }
+
+  if ((ret = pthread_rwlock_wrlock (&r)) != 0)
+    {
+      printf ("rwlock_wrlock failed: %d\n", ret);
+      return 1;
+    }
+
+  if ((ret = pthread_rwlock_unlock (&r)) != 0)
+    {
+      printf ("second rwlock_unlock failed: %d\n", ret);
+      return 1;
+    }
+
+  if ((ret = pthread_rwlock_destroy (&r)) != 0)
+    {
+      printf ("second rwlock_destroy failed: %d\n", ret);
+      return 1;
+    }
+
+  return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-rwlock14.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-rwlock14.c
new file mode 100644
index 00000000..fc0d3d21
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-rwlock14.c
@@ -0,0 +1,169 @@
+/* Copyright (C) 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2004.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+static pthread_barrier_t b;
+static pthread_rwlock_t r = PTHREAD_RWLOCK_INITIALIZER;
+
+
+static void *
+tf (void *arg)
+{
+  /* Lock the read-write lock.  */
+  if (pthread_rwlock_wrlock (&r) != 0)
+    {
+      puts ("tf: cannot lock rwlock");
+      exit (EXIT_FAILURE);
+    }
+
+  pthread_t mt = *(pthread_t *) arg;
+
+  pthread_barrier_wait (&b);
+
+  /* This call will never return.  */
+  pthread_join (mt, NULL);
+
+  return NULL;
+}
+
+
+static int
+do_test (void)
+{
+  int result = 0;
+  struct timespec ts;
+
+  if (clock_gettime (CLOCK_REALTIME, &ts) != 0)
+    {
+      puts ("clock_gettime failed");
+      return 1;
+    }
+
+  if (pthread_barrier_init (&b, NULL, 2) != 0)
+    {
+      puts ("barrier_init failed");
+      return 1;
+    }
+
+  pthread_t me = pthread_self ();
+  pthread_t th;
+  if (pthread_create (&th, NULL, tf, &me) != 0)
+    {
+      puts ("create failed");
+      return 1;
+    }
+
+  /* Wait until the rwlock is locked.  */
+  pthread_barrier_wait (&b);
+
+  ts.tv_nsec = -1;
+
+  int e = pthread_rwlock_timedrdlock (&r, &ts);
+  if (e == 0)
+    {
+      puts ("first rwlock_timedrdlock did not fail");
+      result = 1;
+    }
+  else if (e != EINVAL)
+    {
+      puts ("first rwlock_timedrdlock did not return EINVAL");
+      result = 1;
+    }
+
+  e = pthread_rwlock_timedwrlock (&r, &ts);
+  if (e == 0)
+    {
+      puts ("first rwlock_timedwrlock did not fail");
+      result = 1;
+    }
+  else if (e != EINVAL)
+    {
+      puts ("first rwlock_timedwrlock did not return EINVAL");
+      result = 1;
+    }
+
+  ts.tv_nsec = 1000000000;
+
+  e = pthread_rwlock_timedrdlock (&r, &ts);
+  if (e == 0)
+    {
+      puts ("second rwlock_timedrdlock did not fail");
+      result = 1;
+    }
+  else if (e != EINVAL)
+    {
+      puts ("second rwlock_timedrdlock did not return EINVAL");
+      result = 1;
+    }
+
+  e = pthread_rwlock_timedrdlock (&r, &ts);
+  if (e == 0)
+    {
+      puts ("second rwlock_timedrdlock did not fail");
+      result = 1;
+    }
+  else if (e != EINVAL)
+    {
+      puts ("second rwlock_timedrdlock did not return EINVAL");
+      result = 1;
+    }
+
+  ts.tv_nsec = 0x100001000LL;
+  if (ts.tv_nsec != 0x100001000LL)
+    ts.tv_nsec = 2000000000;
+
+  e = pthread_rwlock_timedrdlock (&r, &ts);
+  if (e == 0)
+    {
+      puts ("third rwlock_timedrdlock did not fail");
+      result = 1;
+    }
+  else if (e != EINVAL)
+    {
+      puts ("third rwlock_timedrdlock did not return EINVAL");
+      result = 1;
+    }
+
+  e = pthread_rwlock_timedrdlock (&r, &ts);
+  if (e == 0)
+    {
+      puts ("third rwlock_timedrdlock did not fail");
+      result = 1;
+    }
+  else if (e != EINVAL)
+    {
+      puts ("third rwlock_timedrdlock did not return EINVAL");
+      result = 1;
+    }
+
+  if (result == 0)
+    puts ("no bugs");
+
+  return result;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-rwlock2.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-rwlock2.c
new file mode 100644
index 00000000..6f38682b
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-rwlock2.c
@@ -0,0 +1,143 @@
+/* Copyright (C) 2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2002.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+
+
+static int
+do_test (void)
+{
+  pthread_rwlock_t r;
+  int e;
+
+  if (pthread_rwlock_init (&r, NULL) != 0)
+    {
+      puts ("rwlock_init failed");
+      return 1;
+    }
+  puts ("rwlock_init succeeded");
+
+  if (pthread_rwlock_wrlock (&r) != 0)
+    {
+      puts ("1st rwlock_wrlock failed");
+      return 1;
+    }
+  puts ("1st rwlock_wrlock succeeded");
+
+  e = pthread_rwlock_tryrdlock (&r);
+  if (e == 0)
+    {
+      puts ("rwlock_tryrdlock on rwlock with writer succeeded");
+      return 1;
+    }
+  if (e != EBUSY)
+    {
+      puts ("rwlock_tryrdlock on rwlock with writer return value != EBUSY");
+      return 1;
+    }
+  puts ("rwlock_tryrdlock on rwlock with writer failed with EBUSY");
+
+  e = pthread_rwlock_trywrlock (&r);
+  if (e == 0)
+    {
+      puts ("rwlock_trywrlock on rwlock with writer succeeded");
+      return 1;
+    }
+  if (e != EBUSY)
+    {
+      puts ("rwlock_trywrlock on rwlock with writer return value != EBUSY");
+      return 1;
+    }
+  puts ("rwlock_trywrlock on rwlock with writer failed with EBUSY");
+
+  if (pthread_rwlock_unlock (&r) != 0)
+    {
+      puts ("1st rwlock_unlock failed");
+      return 1;
+    }
+  puts ("1st rwlock_unlock succeeded");
+
+  if (pthread_rwlock_tryrdlock (&r) != 0)
+    {
+      puts ("rwlock_tryrdlock on unlocked rwlock failed");
+      return 1;
+    }
+  puts ("rwlock_tryrdlock on unlocked rwlock succeeded");
+
+  e = pthread_rwlock_trywrlock (&r);
+  if (e == 0)
+    {
+      puts ("rwlock_trywrlock on rwlock with reader succeeded");
+      return 1;
+    }
+  if (e != EBUSY)
+    {
+      puts ("rwlock_trywrlock on rwlock with reader return value != EBUSY");
+      return 1;
+    }
+  puts ("rwlock_trywrlock on rwlock with reader failed with EBUSY");
+
+  if (pthread_rwlock_unlock (&r) != 0)
+    {
+      puts ("2nd rwlock_unlock failed");
+      return 1;
+    }
+  puts ("2nd rwlock_unlock succeeded");
+
+  if (pthread_rwlock_trywrlock (&r) != 0)
+    {
+      puts ("rwlock_trywrlock on unlocked rwlock failed");
+      return 1;
+    }
+  puts ("rwlock_trywrlock on unlocked rwlock succeeded");
+
+  e = pthread_rwlock_tryrdlock (&r);
+  if (e == 0)
+    {
+      puts ("rwlock_tryrdlock on rwlock with writer succeeded");
+      return 1;
+    }
+  if (e != EBUSY)
+    {
+      puts ("rwlock_tryrdlock on rwlock with writer return value != EBUSY");
+      return 1;
+    }
+  puts ("rwlock_tryrdlock on rwlock with writer failed with EBUSY");
+
+  if (pthread_rwlock_unlock (&r) != 0)
+    {
+      puts ("3rd rwlock_unlock failed");
+      return 1;
+    }
+  puts ("3rd rwlock_unlock succeeded");
+
+  if (pthread_rwlock_destroy (&r) != 0)
+    {
+      puts ("rwlock_destroy failed");
+      return 1;
+    }
+  puts ("rwlock_destroy succeeded");
+
+  return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-rwlock2a.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-rwlock2a.c
new file mode 100644
index 00000000..615de5c0
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-rwlock2a.c
@@ -0,0 +1,2 @@
+#define TYPE PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP
+#include "tst-rwlock2.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-rwlock3.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-rwlock3.c
new file mode 100644
index 00000000..c1cac876
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-rwlock3.c
@@ -0,0 +1,93 @@
+/* Copyright (C) 2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2002.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+/* This test case checks more than standard compliance.  An
+   implementation may provide this service but it is not required to
+   do so.  */
+
+#include 
+#include 
+#include 
+
+
+static int
+do_test (void)
+{
+  pthread_rwlock_t r;
+  int e;
+
+  if (pthread_rwlock_init (&r, NULL) != 0)
+    {
+      puts ("rwlock_init failed");
+      return 1;
+    }
+  puts ("rwlock_init succeeded");
+
+  if (pthread_rwlock_trywrlock (&r) != 0)
+    {
+      puts ("rwlock_trywrlock on unlocked rwlock failed");
+      return 1;
+    }
+  puts ("rwlock_trywrlock on unlocked rwlock succeeded");
+
+  e = pthread_rwlock_rdlock (&r);
+  if (e == 0)
+    {
+      puts ("rwlock_rdlock on rwlock with writer succeeded");
+      return 1;
+    }
+  if (e != EDEADLK)
+    {
+      puts ("rwlock_rdlock on rwlock with writer failed != EDEADLK");
+      return 1;
+    }
+  puts ("rwlock_rdlock on rwlock with writer failed with EDEADLK");
+
+  e = pthread_rwlock_wrlock (&r);
+  if (e == 0)
+    {
+      puts ("rwlock_wrlock on rwlock with writer succeeded");
+      return 1;
+    }
+  if (e != EDEADLK)
+    {
+      puts ("rwlock_wrlock on rwlock with writer failed != EDEADLK");
+      return 1;
+    }
+  puts ("rwlock_wrlock on rwlock with writer failed with EDEADLK");
+
+  if (pthread_rwlock_unlock (&r) != 0)
+    {
+      puts ("rwlock_unlock failed");
+      return 1;
+    }
+  puts ("rwlock_unlock succeeded");
+
+  if (pthread_rwlock_destroy (&r) != 0)
+    {
+      puts ("rwlock_destroy failed");
+      return 1;
+    }
+  puts ("rwlock_destroy succeeded");
+
+  return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-rwlock4.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-rwlock4.c
new file mode 100644
index 00000000..8de0121b
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-rwlock4.c
@@ -0,0 +1,190 @@
+/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2002.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+static int
+do_test (void)
+{
+  size_t ps = sysconf (_SC_PAGESIZE);
+  char tmpfname[] = "/tmp/tst-rwlock4.XXXXXX";
+  char data[ps];
+  void *mem;
+  int fd;
+  pthread_rwlock_t *r;
+  pthread_rwlockattr_t a;
+  pid_t pid;
+  char *p;
+  int err;
+  int s;
+
+  fd = mkstemp (tmpfname);
+  if (fd == -1)
+    {
+      printf ("cannot open temporary file: %m\n");
+      return 1;
+    }
+
+  /* Make sure it is always removed.  */
+  unlink (tmpfname);
+
+  /* Create one page of data.  */
+  memset (data, '\0', ps);
+
+  /* Write the data to the file.  */
+  if (write (fd, data, ps) != (ssize_t) ps)
+    {
+      puts ("short write");
+      return 1;
+    }
+
+  mem = mmap (NULL, ps, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+  if (mem == MAP_FAILED)
+    {
+      printf ("mmap failed: %m\n");
+      return 1;
+    }
+
+  r = (pthread_rwlock_t *) (((uintptr_t) mem + __alignof (pthread_rwlock_t))
+			    & ~(__alignof (pthread_rwlock_t) - 1));
+  p = (char *) (r + 1);
+
+  if (pthread_rwlockattr_init (&a) != 0)
+    {
+      puts ("rwlockattr_init failed");
+      return 1;
+    }
+
+  if (pthread_rwlockattr_getpshared (&a, &s) != 0)
+    {
+      puts ("1st rwlockattr_getpshared failed");
+      return 1;
+    }
+
+  if (s != PTHREAD_PROCESS_PRIVATE)
+    {
+      puts ("default pshared value wrong");
+      return 1;
+    }
+
+  if (pthread_rwlockattr_setpshared (&a, PTHREAD_PROCESS_SHARED) != 0)
+    {
+      puts ("rwlockattr_setpshared failed");
+      return 1;
+    }
+
+  if (pthread_rwlockattr_getpshared (&a, &s) != 0)
+    {
+      puts ("2nd rwlockattr_getpshared failed");
+      return 1;
+    }
+
+  if (s != PTHREAD_PROCESS_SHARED)
+    {
+      puts ("pshared value after setpshared call wrong");
+      return 1;
+    }
+
+  if (pthread_rwlock_init (r, &a) != 0)
+    {
+      puts ("rwlock_init failed");
+      return 1;
+    }
+
+  if (pthread_rwlock_rdlock (r) != 0)
+    {
+      puts ("rwlock_rdlock failed");
+      return 1;
+    }
+
+  if (pthread_rwlockattr_destroy (&a) != 0)
+    {
+      puts ("rwlockattr_destroy failed");
+      return 1;
+    }
+
+  err = pthread_rwlock_trywrlock (r);
+  if (err == 0)
+    {
+      puts ("rwlock_trywrlock succeeded");
+      return 1;
+    }
+  else if (err != EBUSY)
+    {
+      puts ("rwlock_trywrlock didn't return EBUSY");
+      return 1;
+    }
+
+  *p = 0;
+
+  puts ("going to fork now");
+  pid = fork ();
+  if (pid == -1)
+    {
+      puts ("fork failed");
+      return 1;
+    }
+  else if (pid == 0)
+    {
+      /* Play some lock ping-pong.  It's our turn to unlock first.  */
+      if ((*p)++ != 0)
+	{
+	  puts ("child: *p != 0");
+	  return 1;
+	}
+
+      if (pthread_rwlock_unlock (r) != 0)
+	{
+	  puts ("child: 1st rwlock_unlock failed");
+	  return 1;
+	}
+
+      puts ("child done");
+    }
+  else
+    {
+      if (pthread_rwlock_wrlock (r) != 0)
+	{
+	  puts ("parent: rwlock_wrlock failed");
+	  return 1;
+	}
+
+      if (*p != 1)
+	{
+	  puts ("*p != 1");
+	  return 1;
+	}
+
+      puts ("parent done");
+    }
+
+  return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-rwlock5.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-rwlock5.c
new file mode 100644
index 00000000..a04eb267
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-rwlock5.c
@@ -0,0 +1,87 @@
+/* Copyright (C) 2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2002.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+static pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
+static pthread_rwlock_t r;
+
+
+static void *
+tf (void *arg)
+{
+  if (pthread_rwlock_wrlock (&r) == 0)
+    {
+      puts ("child: rwlock_wrlock succeeded");
+      exit (1);
+    }
+
+  puts ("child: rwlock_wrlock returned");
+
+  exit (1);
+}
+
+
+static int
+do_test (void)
+{
+  pthread_t th;
+
+  if (pthread_rwlock_init (&r, NULL) != 0)
+    {
+      puts ("rwlock_init failed");
+      return 1;
+    }
+
+  if (pthread_rwlock_wrlock (&r) != 0)
+    {
+      puts ("rwlock_wrlock failed");
+      return 1;
+    }
+
+  if (pthread_mutex_lock (&m) != 0)
+    {
+      puts ("mutex_lock failed");
+      return 1;
+    }
+
+  /* Set an alarm for 1 second.  The wrapper will expect this.  */
+  alarm (1);
+
+  if (pthread_create (&th, NULL, tf, NULL) != 0)
+    {
+      puts ("create failed");
+      return 1;
+    }
+
+  /* This call should never return.  */
+  pthread_mutex_lock (&m);
+
+  puts ("2nd mutex_lock returned");
+  return 1;
+}
+
+#define EXPECTED_SIGNAL SIGALRM
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-rwlock6.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-rwlock6.c
new file mode 100644
index 00000000..3b525b9d
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-rwlock6.c
@@ -0,0 +1,226 @@
+/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2002.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+static int kind[] =
+  {
+    PTHREAD_RWLOCK_PREFER_READER_NP,
+    PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP,
+    PTHREAD_RWLOCK_PREFER_WRITER_NP,
+  };
+
+
+static void *
+tf (void *arg)
+{
+  pthread_rwlock_t *r = arg;
+
+  /* Timeout: 0.3 secs.  */
+  struct timeval tv;
+  (void) gettimeofday (&tv, NULL);
+
+  struct timespec ts;
+  TIMEVAL_TO_TIMESPEC (&tv, &ts);
+  ts.tv_nsec += 300000000;
+  if (ts.tv_nsec >= 1000000000)
+    {
+      ts.tv_nsec -= 1000000000;
+      ++ts.tv_sec;
+    }
+
+  puts ("child calling timedrdlock");
+
+  int err = pthread_rwlock_timedrdlock (r, &ts);
+  if (err == 0)
+    {
+      puts ("rwlock_timedrdlock returned");
+      pthread_exit ((void *) 1l);
+    }
+
+  if (err != ETIMEDOUT)
+    {
+      printf ("err = %s (%d), expected %s (%d)\n",
+	      strerror (err), err, strerror (ETIMEDOUT), ETIMEDOUT);
+      pthread_exit ((void *) 1l);
+    }
+
+  puts ("1st child timedrdlock done");
+
+  struct timeval tv2;
+  (void) gettimeofday (&tv2, NULL);
+
+  timersub (&tv2, &tv, &tv);
+
+  if (tv.tv_usec < 200000)
+    {
+      puts ("timeout too short");
+      pthread_exit ((void *) 1l);
+    }
+
+  (void) gettimeofday (&tv, NULL);
+  TIMEVAL_TO_TIMESPEC (&tv, &ts);
+  ts.tv_sec += 10;
+  /* Note that the following operation makes ts invalid.  */
+  ts.tv_nsec += 1000000000;
+
+  err = pthread_rwlock_timedrdlock (r, &ts);
+  if (err == 0)
+    {
+      puts ("2nd timedrdlock succeeded");
+      pthread_exit ((void *) 1l);
+    }
+  if (err != EINVAL)
+    {
+      puts ("2nd timedrdlock did not return EINVAL");
+      pthread_exit ((void *) 1l);
+    }
+
+  puts ("2nd child timedrdlock done");
+
+  return NULL;
+}
+
+
+static int
+do_test (void)
+{
+  size_t cnt;
+  for (cnt = 0; cnt < sizeof (kind) / sizeof (kind[0]); ++cnt)
+    {
+      pthread_rwlock_t r;
+      pthread_rwlockattr_t a;
+
+      if (pthread_rwlockattr_init (&a) != 0)
+	{
+	  printf ("round %Zu: rwlockattr_t failed\n", cnt);
+	  exit (1);
+	}
+
+      if (pthread_rwlockattr_setkind_np (&a, kind[cnt]) != 0)
+	{
+	  printf ("round %Zu: rwlockattr_setkind failed\n", cnt);
+	  exit (1);
+	}
+
+      if (pthread_rwlock_init (&r, &a) != 0)
+	{
+	  printf ("round %Zu: rwlock_init failed\n", cnt);
+	  exit (1);
+	}
+
+      if (pthread_rwlockattr_destroy (&a) != 0)
+	{
+	  printf ("round %Zu: rwlockattr_destroy failed\n", cnt);
+	  exit (1);
+	}
+
+      struct timeval tv;
+      (void) gettimeofday (&tv, NULL);
+
+      struct timespec ts;
+      TIMEVAL_TO_TIMESPEC (&tv, &ts);
+
+      ++ts.tv_sec;
+
+      /* Get a write lock.  */
+      int e = pthread_rwlock_timedwrlock (&r, &ts);
+      if (e != 0)
+	{
+	  printf ("round %Zu: rwlock_timedwrlock failed (%d)\n", cnt, e);
+	  exit (1);
+	}
+
+      puts ("1st timedwrlock done");
+
+      (void) gettimeofday (&tv, NULL);
+      TIMEVAL_TO_TIMESPEC (&tv, &ts);
+      ++ts.tv_sec;
+      e = pthread_rwlock_timedrdlock (&r, &ts);
+      if (e == 0)
+	{
+	  puts ("timedrdlock succeeded");
+	  exit (1);
+	}
+      if (e != EDEADLK)
+	{
+	  puts ("timedrdlock did not return EDEADLK");
+	  exit (1);
+	}
+
+      puts ("1st timedrdlock done");
+
+      (void) gettimeofday (&tv, NULL);
+      TIMEVAL_TO_TIMESPEC (&tv, &ts);
+      ++ts.tv_sec;
+      e = pthread_rwlock_timedwrlock (&r, &ts);
+      if (e == 0)
+	{
+	  puts ("2nd timedwrlock succeeded");
+	  exit (1);
+	}
+      if (e != EDEADLK)
+	{
+	  puts ("2nd timedwrlock did not return EDEADLK");
+	  exit (1);
+	}
+
+      puts ("2nd timedwrlock done");
+
+      pthread_t th;
+      if (pthread_create (&th, NULL, tf, &r) != 0)
+	{
+	  printf ("round %Zu: create failed\n", cnt);
+	  exit (1);
+	}
+
+      puts ("started thread");
+
+      void *status;
+      if (pthread_join (th, &status) != 0)
+	{
+	  printf ("round %Zu: join failed\n", cnt);
+	  exit (1);
+	}
+      if (status != NULL)
+	{
+	  printf ("failure in round %Zu\n", cnt);
+	  exit (1);
+	}
+
+      puts ("joined thread");
+
+      if (pthread_rwlock_destroy (&r) != 0)
+	{
+	  printf ("round %Zu: rwlock_destroy failed\n", cnt);
+	  exit (1);
+	}
+    }
+
+  return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-rwlock7.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-rwlock7.c
new file mode 100644
index 00000000..1f34c065
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-rwlock7.c
@@ -0,0 +1,179 @@
+/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2002.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+static int kind[] =
+  {
+    PTHREAD_RWLOCK_PREFER_READER_NP,
+    PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP,
+    PTHREAD_RWLOCK_PREFER_WRITER_NP,
+  };
+
+
+static void *
+tf (void *arg)
+{
+  pthread_rwlock_t *r = arg;
+
+  /* Timeout: 0.3 secs.  */
+  struct timeval tv;
+  (void) gettimeofday (&tv, NULL);
+
+  struct timespec ts;
+  TIMEVAL_TO_TIMESPEC (&tv, &ts);
+  ts.tv_nsec += 300000000;
+  if (ts.tv_nsec >= 1000000000)
+    {
+      ts.tv_nsec -= 1000000000;
+      ++ts.tv_sec;
+    }
+
+  int err = pthread_rwlock_timedwrlock (r, &ts);
+  if (err == 0)
+    {
+      puts ("rwlock_timedwrlock returned");
+      pthread_exit ((void *) 1l);
+    }
+
+  if (err != ETIMEDOUT)
+    {
+      printf ("err = %s (%d), expected %s (%d)\n",
+	      strerror (err), err, strerror (ETIMEDOUT), ETIMEDOUT);
+      pthread_exit ((void *) 1l);
+    }
+
+  struct timeval tv2;
+  (void) gettimeofday (&tv2, NULL);
+
+  timersub (&tv2, &tv, &tv);
+
+  if (tv.tv_usec < 200000)
+    {
+      puts ("timeout too short");
+      pthread_exit ((void *) 1l);
+    }
+
+  (void) gettimeofday (&tv, NULL);
+  TIMEVAL_TO_TIMESPEC (&tv, &ts);
+  ts.tv_sec += 10;
+  /* Note that the following operation makes ts invalid.  */
+  ts.tv_nsec += 1000000000;
+
+  err = pthread_rwlock_timedwrlock (r, &ts);
+  if (err == 0)
+    {
+      puts ("2nd timedwrlock succeeded");
+      pthread_exit ((void *) 1l);
+    }
+  if (err != EINVAL)
+    {
+      puts ("2nd timedwrlock did not return EINVAL");
+      pthread_exit ((void *) 1l);
+    }
+
+  return NULL;
+}
+
+
+static int
+do_test (void)
+{
+  size_t cnt;
+  for (cnt = 0; cnt < sizeof (kind) / sizeof (kind[0]); ++cnt)
+    {
+      pthread_rwlock_t r;
+      pthread_rwlockattr_t a;
+
+      if (pthread_rwlockattr_init (&a) != 0)
+	{
+	  printf ("round %Zu: rwlockattr_t failed\n", cnt);
+	  exit (1);
+	}
+
+      if (pthread_rwlockattr_setkind_np (&a, kind[cnt]) != 0)
+	{
+	  printf ("round %Zu: rwlockattr_setkind failed\n", cnt);
+	  exit (1);
+	}
+
+      if (pthread_rwlock_init (&r, &a) != 0)
+	{
+	  printf ("round %Zu: rwlock_init failed\n", cnt);
+	  exit (1);
+	}
+
+      if (pthread_rwlockattr_destroy (&a) != 0)
+	{
+	  printf ("round %Zu: rwlockattr_destroy failed\n", cnt);
+	  exit (1);
+	}
+
+      struct timeval tv;
+      (void) gettimeofday (&tv, NULL);
+
+      struct timespec ts;
+      TIMEVAL_TO_TIMESPEC (&tv, &ts);
+
+      ++ts.tv_sec;
+
+      /* Get a read lock.  */
+      if (pthread_rwlock_timedrdlock (&r, &ts) != 0)
+	{
+	  printf ("round %Zu: rwlock_timedrdlock failed\n", cnt);
+	  exit (1);
+	}
+
+      pthread_t th;
+      if (pthread_create (&th, NULL, tf, &r) != 0)
+	{
+	  printf ("round %Zu: create failed\n", cnt);
+	  exit (1);
+	}
+
+      void *status;
+      if (pthread_join (th, &status) != 0)
+	{
+	  printf ("round %Zu: join failed\n", cnt);
+	  exit (1);
+	}
+      if (status != NULL)
+	{
+	  printf ("failure in round %Zu\n", cnt);
+	  exit (1);
+	}
+
+      if (pthread_rwlock_destroy (&r) != 0)
+	{
+	  printf ("round %Zu: rwlock_destroy failed\n", cnt);
+	  exit (1);
+	}
+    }
+
+  return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-rwlock8.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-rwlock8.c
new file mode 100644
index 00000000..7eeaea88
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-rwlock8.c
@@ -0,0 +1,164 @@
+/* Test program for timedout read/write lock functions.
+   Copyright (C) 2000, 2003 Free Software Foundation, Inc.
+   Contributed by Ulrich Drepper , 2000.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public License as
+   published by the Free Software Foundation; either version 2.1 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+#define NWRITERS 15
+#define WRITETRIES 10
+#define NREADERS 15
+#define READTRIES 15
+
+#define DELAY   1000000
+
+#ifndef INIT
+# define INIT PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP
+#endif
+
+static pthread_rwlock_t lock = INIT;
+
+
+static void *
+writer_thread (void *nr)
+{
+  struct timespec delay;
+  int n;
+
+  delay.tv_sec = 0;
+  delay.tv_nsec = DELAY;
+
+  for (n = 0; n < WRITETRIES; ++n)
+    {
+      printf ("writer thread %ld tries again\n", (long int) nr);
+
+      if (pthread_rwlock_wrlock (&lock) != 0)
+	{
+	  puts ("wrlock failed");
+	  exit (1);
+	}
+
+      printf ("writer thread %ld succeeded\n", (long int) nr);
+
+      nanosleep (&delay, NULL);
+
+      if (pthread_rwlock_unlock (&lock) != 0)
+	{
+	  puts ("unlock for writer failed");
+	  exit (1);
+	}
+
+      printf ("writer thread %ld released\n", (long int) nr);
+    }
+
+  return NULL;
+}
+
+
+static void *
+reader_thread (void *nr)
+{
+  struct timespec delay;
+  int n;
+
+  delay.tv_sec = 0;
+  delay.tv_nsec = DELAY;
+
+  for (n = 0; n < READTRIES; ++n)
+    {
+      printf ("reader thread %ld tries again\n", (long int) nr);
+
+      if (pthread_rwlock_rdlock (&lock) != 0)
+	{
+	  puts ("rdlock failed");
+	  exit (1);
+	}
+
+      printf ("reader thread %ld succeeded\n", (long int) nr);
+
+      nanosleep (&delay, NULL);
+
+      if (pthread_rwlock_unlock (&lock) != 0)
+	{
+	  puts ("unlock for reader failed");
+	  exit (1);
+	}
+
+      printf ("reader thread %ld released\n", (long int) nr);
+    }
+
+  return NULL;
+}
+
+
+static int
+do_test (void)
+{
+  pthread_t thwr[NWRITERS];
+  pthread_t thrd[NREADERS];
+  int n;
+  void *res;
+
+  /* Make standard error the same as standard output.  */
+  dup2 (1, 2);
+
+  /* Make sure we see all message, even those on stdout.  */
+  setvbuf (stdout, NULL, _IONBF, 0);
+
+  for (n = 0; n < NWRITERS; ++n)
+    if (pthread_create (&thwr[n], NULL, writer_thread,
+			(void *) (long int) n) != 0)
+      {
+	puts ("writer create failed");
+	exit (1);
+      }
+
+  for (n = 0; n < NREADERS; ++n)
+    if (pthread_create (&thrd[n], NULL, reader_thread,
+			(void *) (long int) n) != 0)
+      {
+	puts ("reader create failed");
+	exit (1);
+      }
+
+  /* Wait for all the threads.  */
+  for (n = 0; n < NWRITERS; ++n)
+    if (pthread_join (thwr[n], &res) != 0)
+      {
+	puts ("writer join failed");
+	exit (1);
+      }
+  for (n = 0; n < NREADERS; ++n)
+    if (pthread_join (thrd[n], &res) != 0)
+      {
+	puts ("reader join failed");
+	exit (1);
+      }
+
+  return 0;
+}
+
+#define TIMEOUT 30
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-rwlock9.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-rwlock9.c
new file mode 100644
index 00000000..a5522ce4
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-rwlock9.c
@@ -0,0 +1,203 @@
+/* Test program for timedout read/write lock functions.
+   Copyright (C) 2000, 2003 Free Software Foundation, Inc.
+   Contributed by Ulrich Drepper , 2000.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public License as
+   published by the Free Software Foundation; either version 2.1 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+#define NWRITERS 15
+#define WRITETRIES 10
+#define NREADERS 15
+#define READTRIES 15
+
+#define TIMEOUT 1000000
+#define DELAY   1000000
+
+#ifndef INIT
+# define INIT PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP
+#endif
+
+static pthread_rwlock_t lock = INIT;
+
+
+static void *
+writer_thread (void *nr)
+{
+  struct timespec ts;
+  struct timespec delay;
+  int n;
+
+  delay.tv_sec = 0;
+  delay.tv_nsec = DELAY;
+
+  for (n = 0; n < WRITETRIES; ++n)
+    {
+      int e;
+      do
+	{
+	  struct timeval tv;
+	  (void) gettimeofday (&tv, NULL);
+	  TIMEVAL_TO_TIMESPEC (&tv, &ts);
+
+	  ts.tv_nsec += 2 * TIMEOUT;
+	  if (ts.tv_nsec >= 1000000000)
+	    {
+	      ts.tv_nsec -= 1000000000;
+	      ++ts.tv_sec;
+	    }
+
+	  printf ("writer thread %ld tries again\n", (long int) nr);
+
+	  e = pthread_rwlock_timedwrlock (&lock, &ts);
+	  if (e != 0 && e != ETIMEDOUT)
+	    {
+	      puts ("timedwrlock failed");
+	      exit (1);
+	    }
+	}
+      while (e == ETIMEDOUT);
+
+      printf ("writer thread %ld succeeded\n", (long int) nr);
+
+      nanosleep (&delay, NULL);
+
+      if (pthread_rwlock_unlock (&lock) != 0)
+	{
+	  puts ("unlock for writer failed");
+	  exit (1);
+	}
+
+      printf ("writer thread %ld released\n", (long int) nr);
+    }
+
+  return NULL;
+}
+
+
+static void *
+reader_thread (void *nr)
+{
+  struct timespec ts;
+  struct timespec delay;
+  int n;
+
+  delay.tv_sec = 0;
+  delay.tv_nsec = DELAY;
+
+  for (n = 0; n < READTRIES; ++n)
+    {
+      int e;
+      do
+	{
+	  struct timeval tv;
+	  (void) gettimeofday (&tv, NULL);
+	  TIMEVAL_TO_TIMESPEC (&tv, &ts);
+
+	  ts.tv_nsec += TIMEOUT;
+	  if (ts.tv_nsec >= 1000000000)
+	    {
+	      ts.tv_nsec -= 1000000000;
+	      ++ts.tv_sec;
+	    }
+
+	  printf ("reader thread %ld tries again\n", (long int) nr);
+
+	  e = pthread_rwlock_timedrdlock (&lock, &ts);
+	  if (e != 0 && e != ETIMEDOUT)
+	    {
+	      puts ("timedrdlock failed");
+	      exit (1);
+	    }
+	}
+      while (e == ETIMEDOUT);
+
+      printf ("reader thread %ld succeeded\n", (long int) nr);
+
+      nanosleep (&delay, NULL);
+
+      if (pthread_rwlock_unlock (&lock) != 0)
+	{
+	  puts ("unlock for reader failed");
+	  exit (1);
+	}
+
+      printf ("reader thread %ld released\n", (long int) nr);
+    }
+
+  return NULL;
+}
+
+
+static int
+do_test (void)
+{
+  pthread_t thwr[NWRITERS];
+  pthread_t thrd[NREADERS];
+  int n;
+  void *res;
+
+  /* Make standard error the same as standard output.  */
+  dup2 (1, 2);
+
+  /* Make sure we see all message, even those on stdout.  */
+  setvbuf (stdout, NULL, _IONBF, 0);
+
+  for (n = 0; n < NWRITERS; ++n)
+    if (pthread_create (&thwr[n], NULL, writer_thread,
+			(void *) (long int) n) != 0)
+      {
+	puts ("writer create failed");
+	exit (1);
+      }
+
+  for (n = 0; n < NREADERS; ++n)
+    if (pthread_create (&thrd[n], NULL, reader_thread,
+			(void *) (long int) n) != 0)
+      {
+	puts ("reader create failed");
+	exit (1);
+      }
+
+  /* Wait for all the threads.  */
+  for (n = 0; n < NWRITERS; ++n)
+    if (pthread_join (thwr[n], &res) != 0)
+      {
+	puts ("writer join failed");
+	exit (1);
+      }
+  for (n = 0; n < NREADERS; ++n)
+    if (pthread_join (thrd[n], &res) != 0)
+      {
+	puts ("reader join failed");
+	exit (1);
+      }
+
+  return 0;
+}
+
+#undef TIMEOUT
+#define TIMEOUT 30
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-sched1.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-sched1.c
new file mode 100644
index 00000000..4d0702c7
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-sched1.c
@@ -0,0 +1,98 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2002.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+
+
+static int global;
+
+static void *
+tf (void *a)
+{
+  global = 1;
+
+  return 0;
+}
+
+
+int
+do_test (void)
+{
+  pthread_t th;
+  pthread_attr_t at;
+
+  if (pthread_attr_init (&at) != 0)
+    {
+      puts ("attr_init failed");
+      return 1;
+    }
+
+  if (pthread_attr_setschedpolicy (&at, SCHED_OTHER) != 0)
+    {
+      puts ("attr_setschedpolicy failed");
+      return 1;
+    }
+
+  struct sched_param pa;
+  if (sched_getparam (getpid (), &pa) != 0)
+    {
+      puts ("sched_getschedparam failed");
+      return 1;
+    }
+
+  if (pthread_attr_setschedparam (&at, &pa) != 0)
+    {
+      puts ("attr_setschedparam failed");
+      return 1;
+    }
+
+  if (pthread_attr_setinheritsched (&at, PTHREAD_EXPLICIT_SCHED) != 0)
+    {
+      puts ("attr_setinheritsched failed");
+      return 1;
+    }
+
+  if (pthread_create (&th, &at, tf, NULL) != 0)
+    {
+      puts ("create failed");
+      return 1;
+    }
+
+  int e = pthread_join (th, NULL);
+  if (e != 0)
+    {
+      printf ("join failed: %d\n", e);
+      return 1;
+    }
+
+  if (global == 0)
+    {
+      puts ("thread didn't run");
+      return 1;
+    }
+
+  return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-sem1.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-sem1.c
new file mode 100644
index 00000000..32d59eb3
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-sem1.c
@@ -0,0 +1,89 @@
+/* Copyright (C) 2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2002.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+
+
+static int
+do_test (void)
+{
+  sem_t s;
+
+  if (sem_init (&s, 0, 1) == -1)
+    {
+      puts ("init failed");
+      return 1;
+    }
+
+  if (TEMP_FAILURE_RETRY (sem_wait (&s)) == -1)
+    {
+      puts ("1st wait failed");
+      return 1;
+    }
+
+  if (sem_post (&s) == -1)
+    {
+      puts ("1st post failed");
+      return 1;
+    }
+
+  if (TEMP_FAILURE_RETRY (sem_trywait (&s)) == -1)
+    {
+      puts ("1st trywait failed");
+      return 1;
+    }
+
+  errno = 0;
+  if (TEMP_FAILURE_RETRY (sem_trywait (&s)) != -1)
+    {
+      puts ("2nd trywait succeeded");
+      return 1;
+    }
+  else if (errno != EAGAIN)
+    {
+      puts ("2nd trywait did not set errno to EAGAIN");
+      return 1;
+    }
+
+  if (sem_post (&s) == -1)
+    {
+      puts ("2nd post failed");
+      return 1;
+    }
+
+  if (TEMP_FAILURE_RETRY (sem_wait (&s)) == -1)
+    {
+      puts ("2nd wait failed");
+      return 1;
+    }
+
+  if (sem_destroy (&s) == -1)
+    {
+      puts ("destroy failed");
+      return 1;
+    }
+
+  return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-sem10.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-sem10.c
new file mode 100644
index 00000000..9f6e870a
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-sem10.c
@@ -0,0 +1,88 @@
+/* Copyright (C) 2007 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek , 2007.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+static int
+do_test (void)
+{
+  sem_t s;
+  if (sem_init (&s, 0, 0) == -1)
+    {
+      puts ("sem_init failed");
+      return 1;
+    }
+
+  struct timeval tv;
+  if (gettimeofday (&tv, NULL) != 0)
+    {
+      puts ("gettimeofday failed");
+      return 1;
+    }
+
+  struct timespec ts;
+  TIMEVAL_TO_TIMESPEC (&tv, &ts);
+
+  /* Set ts to yesterday.  */
+  ts.tv_sec -= 86400;
+
+  int type_before;
+  if (pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, &type_before) != 0)
+    {
+      puts ("first pthread_setcanceltype failed");
+      return 1;
+    }
+
+  errno = 0;
+  if (TEMP_FAILURE_RETRY (sem_timedwait (&s, &ts)) != -1)
+    {
+      puts ("sem_timedwait succeeded");
+      return 1;
+    }
+  if (errno != ETIMEDOUT)
+    {
+      printf ("sem_timedwait return errno = %d instead of ETIMEDOUT\n",
+	      errno);
+      return 1;
+    }
+
+  int type_after;
+  if (pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, &type_after) != 0)
+    {
+      puts ("second pthread_setcanceltype failed");
+      return 1;
+    }
+  if (type_after != PTHREAD_CANCEL_DEFERRED)
+    {
+      puts ("sem_timedwait changed cancellation type");
+      return 1;
+    }
+
+  return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-sem11.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-sem11.c
new file mode 100644
index 00000000..6633ddd1
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-sem11.c
@@ -0,0 +1,76 @@
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#ifndef SEM_WAIT
+# define SEM_WAIT(s) sem_wait (s)
+#endif
+
+static void *
+tf (void *arg)
+{
+#ifdef PREPARE
+  PREPARE
+#endif
+  SEM_WAIT (arg);
+  return NULL;
+}
+
+int
+main (void)
+{
+  int tries = 5;
+  pthread_t th;
+  sem_t s;
+ again:
+  if (sem_init (&s, 0, 0) != 0)
+    {
+      puts ("sem_init failed");
+      return 1;
+    }
+
+  struct new_sem *is = (struct new_sem *) &s;
+
+  if (is->nwaiters != 0)
+    {
+      puts ("nwaiters not initialized");
+      return 1;
+    }
+
+  if (pthread_create (&th, NULL, tf, &s) != 0)
+    {
+      puts ("pthread_create failed");
+      return 1;
+    }
+
+  sleep (1);
+
+  if (pthread_cancel (th) != 0)
+    {
+      puts ("pthread_cancel failed");
+      return 1;
+    }
+
+  void *r;
+  if (pthread_join (th, &r) != 0)
+    {
+      puts ("pthread_join failed");
+      return 1;
+    }
+  if (r != PTHREAD_CANCELED && --tries > 0)
+    {
+      /* Maybe we get the scheduling right the next time.  */
+      sem_destroy (&s);
+      goto again;
+    }
+
+  if (is->nwaiters != 0)
+    {
+      puts ("nwaiters not reset");
+      return 1;
+    }
+
+  return 0;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-sem12.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-sem12.c
new file mode 100644
index 00000000..71d02b70
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-sem12.c
@@ -0,0 +1,14 @@
+#include 
+#include 
+
+
+#define PREPARE \
+  struct timespec ts; \
+  struct timeval tv; \
+  gettimeofday (&tv, NULL); \
+  TIMEVAL_TO_TIMESPEC (&tv, &ts); \
+  ts.tv_sec += 60;
+
+#define SEM_WAIT(s) sem_timedwait (s, &ts)
+
+#include "tst-sem11.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-sem2.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-sem2.c
new file mode 100644
index 00000000..026939ef
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-sem2.c
@@ -0,0 +1,54 @@
+/* Copyright (C) 2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2002.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+static int
+do_test (void)
+{
+  sem_t s;
+
+  if (sem_init (&s, 0, 0) == -1)
+    {
+      puts ("init failed");
+      return 1;
+    }
+
+  /* Set an alarm for 1 second.  The wrapper will expect this.  */
+  alarm (1);
+
+  if (TEMP_FAILURE_RETRY (sem_wait (&s)) == -1)
+    {
+      puts ("wait failed");
+      return 1;
+    }
+
+  /* We should never get here.  */
+  puts ("wait succeeded");
+  return 1;
+}
+
+#define EXPECTED_SIGNAL SIGALRM
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-sem3.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-sem3.c
new file mode 100644
index 00000000..91b9f087
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-sem3.c
@@ -0,0 +1,142 @@
+/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2002.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+int
+main (void)
+{
+  size_t ps = sysconf (_SC_PAGESIZE);
+  char tmpfname[] = "/tmp/tst-sem3.XXXXXX";
+  char data[ps];
+  void *mem;
+  int fd;
+  sem_t *s;
+  pid_t pid;
+  char *p;
+
+  fd = mkstemp (tmpfname);
+  if (fd == -1)
+    {
+      printf ("cannot open temporary file: %m\n");
+      exit (1);
+    }
+
+  /* Make sure it is always removed.  */
+  unlink (tmpfname);
+
+  /* Create one page of data.  */
+  memset (data, '\0', ps);
+
+  /* Write the data to the file.  */
+  if (write (fd, data, ps) != (ssize_t) ps)
+    {
+      puts ("short write");
+      exit (1);
+    }
+
+  mem = mmap (NULL, ps, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+  if (mem == MAP_FAILED)
+    {
+      printf ("mmap failed: %m\n");
+      exit (1);
+    }
+
+  s = (sem_t *) (((uintptr_t) mem + __alignof (sem_t))
+		 & ~(__alignof (sem_t) - 1));
+  p = (char *) (s + 1);
+
+  if (sem_init (s, 1, 1) == -1)
+    {
+      puts ("init failed");
+      exit (1);
+    }
+
+  if (TEMP_FAILURE_RETRY (sem_wait (s)) == -1)
+    {
+      puts ("1st wait failed");
+      exit (1);
+    }
+
+  errno = 0;
+  if (TEMP_FAILURE_RETRY (sem_trywait (s)) != -1)
+    {
+      puts ("trywait succeeded");
+      exit (1);
+    }
+  else if (errno != EAGAIN)
+    {
+      puts ("trywait didn't return EAGAIN");
+      exit (1);
+    }
+
+  *p = 0;
+
+  puts ("going to fork now");
+  pid = fork ();
+  if (pid == -1)
+    {
+      puts ("fork failed");
+      exit (1);
+    }
+  else if (pid == 0)
+    {
+      /* Play some lock ping-pong.  It's our turn to unlock first.  */
+      if ((*p)++ != 0)
+	{
+	  puts ("child: *p != 0");
+	  exit (1);
+	}
+
+      if (sem_post (s) == -1)
+	{
+	  puts ("child: 1st post failed");
+	  exit (1);
+	}
+
+      puts ("child done");
+    }
+  else
+    {
+      if (TEMP_FAILURE_RETRY (sem_wait (s)) == -1)
+	{
+	  printf ("parent: 2nd wait failed: %m\n");
+	  exit (1);
+	}
+
+      if (*p != 1)
+	{
+	  puts ("*p != 1");
+	  exit (1);
+	}
+
+      puts ("parent done");
+    }
+
+  exit (0);
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-sem4.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-sem4.c
new file mode 100644
index 00000000..ccffbdd7
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-sem4.c
@@ -0,0 +1,147 @@
+/* Copyright (C) 2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2002.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+static void
+remove_sem (int status, void *arg)
+{
+  sem_unlink (arg);
+}
+
+
+int
+main (void)
+{
+  sem_t *s;
+  sem_t *s2;
+  pid_t pid;
+  int val;
+
+  s = sem_open ("/glibc-tst-sem4", O_CREAT, 0600, 1);
+  if (s == SEM_FAILED)
+    {
+      if (errno == ENOSYS)
+	{
+	  puts ("sem_open not supported.  Oh well.");
+	  return 0;
+	}
+
+      /* Maybe the shm filesystem has strict permissions.  */
+      if (errno == EACCES)
+	{
+	  puts ("sem_open not allowed.  Oh well.");
+	  return 0;
+	}
+
+      printf ("sem_open: %m\n");
+      return 1;
+    }
+
+  on_exit (remove_sem, (void *) "/glibc-tst-sem4");
+
+  /* We have the semaphore object.  Now try again with O_EXCL, this
+     should fail.  */
+  s2 = sem_open ("/glibc-tst-sem4", O_CREAT | O_EXCL, 0600, 1);
+  if (s2 != SEM_FAILED)
+    {
+      puts ("2nd sem_open didn't fail");
+      return 1;
+    }
+  if (errno != EEXIST)
+    {
+      puts ("2nd sem_open returned wrong error");
+      return 1;
+    }
+
+  /* Check the value.  */
+  if (sem_getvalue (s, &val) == -1)
+    {
+      puts ("getvalue failed");
+      return 1;
+    }
+  if (val != 1)
+    {
+      printf ("initial value wrong: got %d, expected 1\n", val);
+      return 1;
+    }
+
+  if (TEMP_FAILURE_RETRY (sem_wait (s)) == -1)
+    {
+      puts ("1st sem_wait failed");
+      return 1;
+    }
+
+  pid = fork ();
+  if (pid == -1)
+    {
+      printf ("fork failed: %m\n");
+      return 1;
+    }
+
+  if (pid == 0)
+    {
+      /* Child.  */
+
+      /* Check the value.  */
+      if (sem_getvalue (s, &val) == -1)
+	{
+	  puts ("child: getvalue failed");
+	  return 1;
+	}
+      if (val != 0)
+	{
+	  printf ("child: value wrong: got %d, expect 0\n", val);
+	  return 1;
+	}
+
+      if (sem_post (s) == -1)
+	{
+	  puts ("child: post failed");
+	  return 1;
+	}
+    }
+  else
+    {
+      if (TEMP_FAILURE_RETRY (sem_wait (s)) == -1)
+	{
+	  puts ("2nd sem_wait failed");
+	  return 1;
+	}
+
+      if (sem_getvalue (s, &val) == -1)
+	{
+	  puts ("parent: 2nd getvalue failed");
+	  return 1;
+	}
+      if (val != 0)
+	{
+	  printf ("parent: value wrong: got %d, expected 0\n", val);
+	  return 1;
+	}
+    }
+
+  return 0;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-sem5.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-sem5.c
new file mode 100644
index 00000000..cb85b8e7
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-sem5.c
@@ -0,0 +1,80 @@
+/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2002.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+static int
+do_test (void)
+{
+  sem_t s;
+  struct timespec ts;
+  struct timeval tv;
+
+  if (sem_init (&s, 0, 1) == -1)
+    {
+      puts ("sem_init failed");
+      return 1;
+    }
+
+  if (TEMP_FAILURE_RETRY (sem_wait (&s)) == -1)
+    {
+      puts ("sem_wait failed");
+      return 1;
+    }
+
+  if (gettimeofday (&tv, NULL) != 0)
+    {
+      puts ("gettimeofday failed");
+      return 1;
+    }
+
+  TIMEVAL_TO_TIMESPEC (&tv, &ts);
+
+  /* We wait for half a second.  */
+  ts.tv_nsec += 500000000;
+  if (ts.tv_nsec >= 1000000000)
+    {
+      ++ts.tv_sec;
+      ts.tv_nsec -= 1000000000;
+    }
+
+  errno = 0;
+  if (TEMP_FAILURE_RETRY (sem_timedwait (&s, &ts)) != -1)
+    {
+      puts ("sem_timedwait succeeded");
+      return 1;
+    }
+  if (errno != ETIMEDOUT)
+    {
+      printf ("sem_timedwait return errno = %d instead of ETIMEDOUT\n",
+	      errno);
+      return 1;
+    }
+
+  return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-sem6.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-sem6.c
new file mode 100644
index 00000000..49240d96
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-sem6.c
@@ -0,0 +1,81 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+static void
+handler (int sig)
+{
+  struct sigaction sa;
+
+  sa.sa_handler = SIG_DFL;
+  sa.sa_flags = 0;
+  sigemptyset (&sa.sa_mask);
+
+  sigaction (SIGALRM, &sa, NULL);
+
+  /* Rearm the timer.  */
+  alarm (1);
+}
+
+
+static int
+do_test (void)
+{
+  sem_t s;
+  struct sigaction sa;
+
+  sa.sa_handler = handler;
+  sa.sa_flags = 0;
+  sigemptyset (&sa.sa_mask);
+
+  sigaction (SIGALRM, &sa, NULL);
+
+  if (sem_init (&s, 0, 0) == -1)
+    {
+      puts ("init failed");
+      return 1;
+    }
+
+  /* Set an alarm for 1 second.  The wrapper will expect this.  */
+  alarm (1);
+
+  int res = sem_wait (&s);
+  if (res == 0)
+    {
+      puts ("wait succeeded");
+      return 1;
+    }
+  if (res != -1 || errno != EINTR)
+    {
+      puts ("wait didn't fail with EINTR");
+      return 1;
+    }
+
+  return 0;
+}
+
+#define TIMEOUT 3
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-sem7.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-sem7.c
new file mode 100644
index 00000000..a85c73e7
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-sem7.c
@@ -0,0 +1,109 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+static void
+remove_sem (int status, void *arg)
+{
+  sem_unlink (arg);
+}
+
+
+int
+main (void)
+{
+  sem_t *s;
+  sem_t *s2;
+  sem_t *s3;
+
+  s = sem_open ("/glibc-tst-sem7", O_CREAT, 0600, 1);
+  if (s == SEM_FAILED)
+    {
+      if (errno == ENOSYS)
+	{
+	  puts ("sem_open not supported.  Oh well.");
+	  return 0;
+	}
+
+      /* Maybe the shm filesystem has strict permissions.  */
+      if (errno == EACCES)
+	{
+	  puts ("sem_open not allowed.  Oh well.");
+	  return 0;
+	}
+
+      printf ("sem_open: %m\n");
+      return 1;
+    }
+
+  on_exit (remove_sem, (void *) "/glibc-tst-sem7");
+
+  /* We have the semaphore object.  Now try again.  We should get the
+     same address.  */
+  s2 = sem_open ("/glibc-tst-sem7", O_CREAT, 0600, 1);
+  if (s2 == SEM_FAILED)
+    {
+      puts ("2nd sem_open failed");
+      return 1;
+    }
+  if (s != s2)
+    {
+      puts ("2nd sem_open didn't return the same address");
+      return 1;
+    }
+
+  /* And again, this time without O_CREAT.  */
+  s3 = sem_open ("/glibc-tst-sem7", 0);
+  if (s3 == SEM_FAILED)
+    {
+      puts ("3rd sem_open failed");
+      return 1;
+    }
+  if (s != s3)
+    {
+      puts ("3rd sem_open didn't return the same address");
+      return 1;
+    }
+
+  /* Now close the handle.  Three times.  */
+  if (sem_close (s2) != 0)
+    {
+      puts ("1st sem_close failed");
+      return 1;
+    }
+  if (sem_close (s) != 0)
+    {
+      puts ("2nd sem_close failed");
+      return 1;
+    }
+  if (sem_close (s3) != 0)
+    {
+      puts ("3rd sem_close failed");
+      return 1;
+    }
+
+  return 0;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-sem8.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-sem8.c
new file mode 100644
index 00000000..5dea575e
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-sem8.c
@@ -0,0 +1,74 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+static void
+remove_sem (int status, void *arg)
+{
+  sem_unlink (arg);
+}
+
+
+int
+main (void)
+{
+  sem_t *s;
+  int i;
+
+  on_exit (remove_sem, (void *) "/glibc-tst-sem8");
+
+  for (i = 0; i < 3; ++i)
+    {
+      s = sem_open ("/glibc-tst-sem8", O_CREAT, 0600, 1);
+      if (s == SEM_FAILED)
+	{
+	  if (errno == ENOSYS)
+	    {
+	      puts ("sem_open not supported.  Oh well.");
+	      return 0;
+	    }
+
+	  /* Maybe the shm filesystem has strict permissions.  */
+	  if (errno == EACCES)
+	    {
+	      puts ("sem_open not allowed.  Oh well.");
+	      return 0;
+	    }
+
+	  printf ("sem_open: %m\n");
+	  return 1;
+	}
+
+      /* Now close the handle.  */
+      if (sem_close (s) != 0)
+	{
+	  puts ("sem_close failed");
+	  return 1;
+	}
+    }
+
+  return 0;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-sem9.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-sem9.c
new file mode 100644
index 00000000..cdd8eaa3
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-sem9.c
@@ -0,0 +1,81 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+static void
+remove_sem (int status, void *arg)
+{
+  sem_unlink (arg);
+}
+
+
+int
+main (void)
+{
+  sem_t *s;
+  int i;
+
+  on_exit (remove_sem, (void *) "/glibc-tst-sem9");
+
+  for (i = 0; i < 3; ++i)
+    {
+      s = sem_open ("/glibc-tst-sem9", O_CREAT, 0600, 1);
+      if (s == SEM_FAILED)
+	{
+	  if (errno == ENOSYS)
+	    {
+	      puts ("sem_open not supported.  Oh well.");
+	      return 0;
+	    }
+
+	  /* Maybe the shm filesystem has strict permissions.  */
+	  if (errno == EACCES)
+	    {
+	      puts ("sem_open not allowed.  Oh well.");
+	      return 0;
+	    }
+
+	  printf ("sem_open: %m\n");
+	  return 1;
+	}
+
+      /* Now close the handle.  */
+      if (sem_close (s) != 0)
+	{
+	  puts ("sem_close failed");
+	  return 1;
+	}
+
+      /* And remove it.  */
+      if (sem_unlink ("/glibc-tst-sem9") != 0)
+	{
+	  puts ("sem_unlink failed");
+	  return 1;
+	}
+    }
+
+  return 0;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-signal1.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-signal1.c
new file mode 100644
index 00000000..3022f184
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-signal1.c
@@ -0,0 +1,189 @@
+/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2002.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+static sigset_t ss;
+static pthread_barrier_t *b;
+
+
+static void *
+tf (void *arg)
+{
+  sigdelset (&ss, SIGINT);
+
+  if (pthread_sigmask (SIG_SETMASK, &ss, NULL) != 0)
+    {
+      puts ("2nd pthread_sigmask failed");
+      exit (1);
+    }
+
+  pthread_barrier_wait (b);
+
+  int sig;
+  int res = sigwait (&ss, &sig);
+  if (res == 0)
+    {
+      printf ("sigwait returned successfully with signal %d\n", sig);
+      exit (1);
+    }
+
+  printf ("sigwait returned with %s (%d)\n", strerror (res), res);
+
+  return NULL;
+}
+
+
+static void
+receiver (void)
+{
+  pthread_t th;
+
+  /* Make sure the process doesn't run forever.  */
+  alarm (10);
+
+  sigfillset (&ss);
+
+  if (pthread_sigmask (SIG_SETMASK, &ss, NULL) != 0)
+    {
+      puts ("1st pthread_sigmask failed");
+      exit (1);
+    }
+
+  if (pthread_create (&th, NULL, tf, NULL) != 0)
+    {
+      puts ("pthread_create failed");
+      exit (1);
+    }
+
+  if (pthread_join (th, NULL) == 0)
+    {
+      puts ("thread joined?!");
+      exit (1);
+    }
+
+  _exit (0);
+}
+
+
+static int
+do_test (void)
+{
+  char tmp[] = "/tmp/tst-signal1-XXXXXX";
+
+  int fd = mkstemp (tmp);
+  if (fd == -1)
+    {
+      puts ("mkstemp failed");
+      exit (1);
+    }
+
+  unlink (tmp);
+
+  int i;
+  for (i = 0; i < 20; ++i)
+    write (fd, "foobar xyzzy", 12);
+
+  b = mmap (NULL, sizeof (pthread_barrier_t), PROT_READ | PROT_WRITE,
+	    MAP_SHARED, fd, 0);
+  if (b == MAP_FAILED)
+    {
+      puts ("mmap failed");
+      exit (1);
+    }
+
+  pthread_barrierattr_t ba;
+  if (pthread_barrierattr_init (&ba) != 0)
+    {
+      puts ("barrierattr_init failed");
+      exit (1);
+    }
+
+  if (pthread_barrierattr_setpshared (&ba, PTHREAD_PROCESS_SHARED) != 0)
+    {
+      puts ("barrierattr_setpshared failed");
+      exit (1);
+    }
+
+  if (pthread_barrier_init (b, &ba, 2) != 0)
+    {
+      puts ("barrier_init failed");
+      exit (1);
+    }
+
+  if (pthread_barrierattr_destroy (&ba) != 0)
+    {
+      puts ("barrierattr_destroy failed");
+      exit (1);
+    }
+
+  pid_t pid = fork ();
+  if (pid == -1)
+    {
+      puts ("fork failed");
+      exit (1);
+    }
+
+  if (pid == 0)
+    receiver ();
+
+  pthread_barrier_wait (b);
+
+  /* Wait a bit more.  */
+  struct timespec ts = { .tv_sec = 0, .tv_nsec = 10000000 };
+  nanosleep (&ts, NULL);
+
+  /* Send the signal.  */
+  puts ("sending the signal now");
+  kill (pid, SIGINT);
+
+  /* Wait for the process to terminate.  */
+  int status;
+  if (TEMP_FAILURE_RETRY (waitpid (pid, &status, 0)) != pid)
+    {
+      puts ("wrong child reported terminated");
+      exit (1);
+    }
+
+  if (!WIFSIGNALED (status))
+    {
+      puts ("child wasn't signalled");
+      exit (1);
+    }
+
+  if (WTERMSIG (status) != SIGINT)
+    {
+      puts ("child not terminated with SIGINT");
+      exit (1);
+    }
+
+  return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-signal2.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-signal2.c
new file mode 100644
index 00000000..3f2c75d1
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-signal2.c
@@ -0,0 +1,198 @@
+/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2002.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+static sigset_t ss;
+static pthread_barrier_t *b;
+
+
+static void *
+tf (void *arg)
+{
+  pthread_barrier_wait (b);
+
+  puts ("child: calling sigwait now");
+
+  int sig;
+  int err;
+  err = sigwait (&ss, &sig);
+  if (err != 0)
+    {
+      printf ("sigwait returned unsuccessfully: %s (%d)\n",
+	      strerror (err), err);
+      _exit (1);
+    }
+
+  puts ("sigwait returned");
+
+  if (sig != SIGINT)
+    {
+      printf ("caught signal %d, expected %d (SIGINT)\n", sig, SIGINT);
+      _exit (1);
+    }
+
+  puts ("child thread terminating now");
+
+  return NULL;
+}
+
+
+static void
+receiver (void)
+{
+  pthread_t th;
+
+  /* Make sure the process doesn't run forever.  */
+  alarm (10);
+
+  sigfillset (&ss);
+
+  if (pthread_sigmask (SIG_SETMASK, &ss, NULL) != 0)
+    {
+      puts ("1st pthread_sigmask failed");
+      _exit (1);
+    }
+
+  if (pthread_create (&th, NULL, tf, NULL) != 0)
+    {
+      puts ("pthread_create failed");
+      _exit (1);
+    }
+
+  if (pthread_join (th, NULL) != 0)
+    {
+      puts ("thread didn't join");
+      _exit (1);
+    }
+
+  puts ("join succeeded");
+
+  _exit (0);
+}
+
+
+static int
+do_test (void)
+{
+  char tmp[] = "/tmp/tst-signal1-XXXXXX";
+
+  int fd = mkstemp (tmp);
+  if (fd == -1)
+    {
+      puts ("mkstemp failed");
+      exit (1);
+    }
+
+  unlink (tmp);
+
+  int i;
+  for (i = 0; i < 20; ++i)
+    write (fd, "foobar xyzzy", 12);
+
+  b = mmap (NULL, sizeof (pthread_barrier_t), PROT_READ | PROT_WRITE,
+	    MAP_SHARED, fd, 0);
+  if (b == MAP_FAILED)
+    {
+      puts ("mmap failed");
+      exit (1);
+    }
+
+  pthread_barrierattr_t ba;
+  if (pthread_barrierattr_init (&ba) != 0)
+    {
+      puts ("barrierattr_init failed");
+      exit (1);
+    }
+
+  if (pthread_barrierattr_setpshared (&ba, PTHREAD_PROCESS_SHARED) != 0)
+    {
+      puts ("barrierattr_setpshared failed");
+      exit (1);
+    }
+
+  if (pthread_barrier_init (b, &ba, 2) != 0)
+    {
+      puts ("barrier_init failed");
+      exit (1);
+    }
+
+  if (pthread_barrierattr_destroy (&ba) != 0)
+    {
+      puts ("barrierattr_destroy failed");
+      exit (1);
+    }
+
+  pid_t pid = fork ();
+  if (pid == -1)
+    {
+      puts ("fork failed");
+      exit (1);
+    }
+
+  if (pid == 0)
+    receiver ();
+
+  pthread_barrier_wait (b);
+
+  /* Wait a bit more.  */
+  struct timespec ts = { .tv_sec = 0, .tv_nsec = 10000000 };
+  nanosleep (&ts, NULL);
+
+  /* Send the signal.  */
+  puts ("sending the signal now");
+  kill (pid, SIGINT);
+
+  /* Wait for the process to terminate.  */
+  int status;
+  if (TEMP_FAILURE_RETRY (waitpid (pid, &status, 0)) != pid)
+    {
+      puts ("wrong child reported terminated");
+      exit (1);
+    }
+
+  if (!WIFEXITED (status))
+    {
+      if (WIFSIGNALED (status))
+	printf ("child exited with signal %d\n", WTERMSIG (status));
+      else
+	puts ("child didn't exit normally");
+      exit (1);
+    }
+
+  if (WEXITSTATUS (status) != 0)
+    {
+      printf ("exit status %d != 0\n", WEXITSTATUS (status));
+      exit (1);
+    }
+
+  return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-signal3.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-signal3.c
new file mode 100644
index 00000000..e4756c56
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-signal3.c
@@ -0,0 +1,261 @@
+/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2002.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+/* Number of different signalss to use.  Also is the number of
+   threads.  */
+#define N 10
+/* Maximum number of threads in flight at any one time.  */
+#define INFLIGHT 5
+/* Number of signals sent in total.  */
+#define ROUNDS 10000
+
+
+static int received[N][N];
+static int nsig[N];
+static pthread_t th[N];
+static sem_t sem;
+static pthread_mutex_t lock[N];
+static pthread_t th_main;
+static int sig0;
+
+static void
+handler (int sig)
+{
+  int i;
+  for (i = 0; i < N; ++i)
+    if (pthread_equal (pthread_self (), th[i]))
+      break;
+
+  if (i == N)
+    {
+      if (pthread_equal (pthread_self (), th_main))
+	puts ("signal received by main thread");
+      else
+	printf ("signal received by unknown thread (%lx)\n",
+		(unsigned long int) pthread_self ());
+      exit (1);
+    }
+
+  ++received[i][sig - sig0];
+
+  sem_post (&sem);
+}
+
+
+static void *
+tf (void *arg)
+{
+  int idx = (long int) arg;
+
+  sigset_t ss;
+  sigemptyset (&ss);
+
+  int i;
+  for (i = 0; i <= idx; ++i)
+    sigaddset (&ss, sig0 + i);
+
+  if (pthread_sigmask (SIG_UNBLOCK, &ss, NULL) != 0)
+    {
+      printf ("thread %d: pthread_sigmask failed\n", i);
+      exit (1);
+    }
+
+  pthread_mutex_lock (&lock[idx]);
+
+  return NULL;
+}
+
+
+static int
+do_test (void)
+{
+  /* Block all signals.  */
+  sigset_t ss;
+  sigfillset (&ss);
+
+  th_main = pthread_self ();
+
+  sig0 = SIGRTMIN;
+
+  if (pthread_sigmask (SIG_SETMASK, &ss, NULL) != 0)
+    {
+      puts ("1st pthread_sigmask failed");
+      exit (1);
+    }
+
+  /* Install the handler.  */
+  int i;
+  for (i = 0; i < N; ++i)
+    {
+      struct sigaction sa =
+	{
+	  .sa_handler = handler,
+	  .sa_flags = 0
+	};
+      sigfillset (&sa.sa_mask);
+
+      if (sigaction (sig0 + i, &sa, NULL) != 0)
+	{
+	  printf ("sigaction for signal %d failed\n", i);
+	  exit (1);
+	}
+    }
+
+  if (sem_init (&sem, 0, INFLIGHT) != 0)
+    {
+      puts ("sem_init failed");
+      exit (1);
+    }
+
+  pthread_attr_t a;
+
+  if (pthread_attr_init (&a) != 0)
+    {
+      puts ("attr_init failed");
+      exit (1);
+    }
+
+  if (pthread_attr_setstacksize (&a, 1 * 1024 * 1024) != 0)
+    {
+      puts ("attr_setstacksize failed");
+      return 1;
+    }
+
+  for (i = 0; i < N; ++i)
+    {
+      if (pthread_mutex_init (&lock[i], NULL) != 0)
+	{
+	  printf ("mutex_init[%d] failed\n", i);
+	}
+
+      if (pthread_mutex_lock (&lock[i]) != 0)
+	{
+	  printf ("mutex_lock[%d] failed\n", i);
+	}
+
+      if (pthread_create (&th[i], &a, tf, (void *) (long int) i) != 0)
+	{
+	  printf ("create of thread %d failed\n", i);
+	  exit (1);
+	}
+    }
+
+  if (pthread_attr_destroy (&a) != 0)
+    {
+      puts ("attr_destroy failed");
+      exit (1);
+    }
+
+  int result = 0;
+  unsigned int r = 42;
+  pid_t pid = getpid ();
+
+  for (i = 0; i < ROUNDS; ++i)
+    {
+      if (TEMP_FAILURE_RETRY (sem_wait (&sem)) != 0)
+	{
+	  printf ("sem_wait round %d failed: %m\n", i);
+	  exit (1);
+	}
+
+      int s = rand_r (&r) % N;
+
+      kill (pid, sig0 + s);
+    }
+
+  void *status;
+  for (i = 0; i < N; ++i)
+    {
+      if (pthread_mutex_unlock (&lock[i]) != 0)
+	{
+	  printf ("unlock %d failed\n", i);
+	  exit (1);
+	}
+
+      if (pthread_join (th[i], &status) != 0)
+	{
+	  printf ("join %d failed\n", i);
+	  result = 1;
+	}
+      else if (status != NULL)
+	{
+	  printf ("%d: result != NULL\n", i);
+	  result = 1;
+	}
+    }
+
+  int total = 0;
+  for (i = 0; i < N; ++i)
+    {
+      int j;
+
+      for (j = 0; j <= i; ++j)
+	total += received[i][j];
+
+      for (j = i + 1; j < N; ++j)
+	if (received[i][j] != 0)
+	  {
+	    printf ("thread %d received signal SIGRTMIN+%d\n", i, j);
+	    result = 1;
+	  }
+    }
+
+  if (total != ROUNDS)
+    {
+      printf ("total number of handled signals is %d, expected %d\n",
+	      total, ROUNDS);
+      result = 1;
+    }
+
+  printf ("A total of %d signals sent and received\n", total);
+  for (i = 0; i < N; ++i)
+    {
+      printf ("thread %2d:", i);
+
+      int j;
+      for (j = 0; j <= i; ++j)
+	{
+	  printf (" %5d", received[i][j]);
+	  nsig[j] += received[i][j];
+	}
+
+      putchar ('\n');
+
+    }
+
+  printf ("\nTotal    :");
+  for (i = 0; i < N; ++i)
+    printf (" %5d", nsig[i]);
+  putchar ('\n');
+
+  return result;
+}
+
+#define TIMEOUT 10
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-signal4.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-signal4.c
new file mode 100644
index 00000000..dcb2893a
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-signal4.c
@@ -0,0 +1,60 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+static int
+do_test (void)
+{
+  sigset_t ss;
+
+  sigemptyset (&ss);
+
+  int i;
+  for (i = 0; i < 10000; ++i)
+    {
+      long int r = random ();
+
+      if (r != SIG_BLOCK && r != SIG_SETMASK && r != SIG_UNBLOCK)
+	{
+	  int e = pthread_sigmask (r, &ss, NULL);
+
+	  if (e == 0)
+	    {
+	      printf ("pthread_sigmask succeeded for how = %ld\n", r);
+	      exit (1);
+	    }
+
+	  if (e != EINVAL)
+	    {
+	      puts ("pthread_sigmask didn't return EINVAL");
+	      exit (1);
+	    }
+	}
+    }
+
+  return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-signal5.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-signal5.c
new file mode 100644
index 00000000..cea6ec14
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-signal5.c
@@ -0,0 +1,111 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+static sigset_t ss;
+
+
+static void *
+tf (void *arg)
+{
+  sigset_t ss2;
+  if (pthread_sigmask (SIG_SETMASK, NULL, &ss2) != 0)
+    {
+      puts ("child: sigmask failed");
+      exit (1);
+    }
+
+  int i;
+  for (i = 1; i < 32; ++i)
+    if (sigismember (&ss, i) && ! sigismember (&ss2, i))
+      {
+	printf ("signal %d set in parent mask, but not in child\n", i);
+	exit (1);
+      }
+    else if (! sigismember (&ss, i) && sigismember (&ss2, i))
+      {
+	printf ("signal %d set in child mask, but not in parent\n", i);
+	exit (1);
+      }
+
+  return NULL;
+}
+
+
+static int
+do_test (void)
+{
+  sigemptyset (&ss);
+  sigaddset (&ss, SIGUSR1);
+  if (pthread_sigmask (SIG_SETMASK, &ss, NULL) != 0)
+    {
+      puts ("1st sigmask failed");
+      exit (1);
+    }
+
+  pthread_t th;
+  if (pthread_create (&th, NULL, tf, NULL) != 0)
+    {
+      puts ("1st create failed");
+      exit (1);
+    }
+
+  void *r;
+  if (pthread_join (th, &r) != 0)
+    {
+      puts ("1st join failed");
+      exit (1);
+    }
+
+  sigemptyset (&ss);
+  sigaddset (&ss, SIGUSR2);
+  sigaddset (&ss, SIGFPE);
+  if (pthread_sigmask (SIG_SETMASK, &ss, NULL) != 0)
+    {
+      puts ("2nd sigmask failed");
+      exit (1);
+    }
+
+  if (pthread_create (&th, NULL, tf, NULL) != 0)
+    {
+      puts ("2nd create failed");
+      exit (1);
+    }
+
+  if (pthread_join (th, &r) != 0)
+    {
+      puts ("2nd join failed");
+      exit (1);
+    }
+
+  return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-signal6.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-signal6.c
new file mode 100644
index 00000000..85a86400
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-signal6.c
@@ -0,0 +1,192 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+#define N 2
+static pthread_barrier_t bar;
+static struct
+{
+  void *p;
+  pthread_t s;
+} ti[N];
+static int sig1;
+
+
+static void
+handler (int sig)
+{
+  pthread_t self = pthread_self ();
+  size_t i;
+
+  for (i = 0; i < N; ++i)
+    if (ti[i].s == self)
+      {
+	if ((uintptr_t) ti[i].p <= (uintptr_t) &self
+	    && (uintptr_t) ti[i].p + 2 * MINSIGSTKSZ > (uintptr_t) &self)
+	  {
+	    puts ("alt stack not used");
+	    exit (1);
+	  }
+
+	printf ("thread %zu used alt stack for signal %d\n", i, sig);
+
+	return;
+      }
+
+  puts ("handler: thread not found");
+  exit (1);
+}
+
+
+static void *
+tf (void *arg)
+{
+  size_t nr = (uintptr_t) arg;
+  if (nr >= N)
+    {
+      puts ("wrong nr parameter");
+      exit (1);
+    }
+
+  sigset_t ss;
+  sigemptyset (&ss);
+  size_t i;
+  for (i = 0; i < N; ++i)
+    if (i != nr)
+      if (sigaddset (&ss, sig1 + i) != 0)
+	{
+	  puts ("tf: sigaddset failed");
+	  exit (1);
+	}
+  if (pthread_sigmask (SIG_BLOCK, &ss, NULL) != 0)
+    {
+      puts ("tf: sigmask failed");
+      exit (1);
+    }
+
+  void *p = malloc (2 * MINSIGSTKSZ);
+  if (p == NULL)
+    {
+      puts ("tf: malloc failed");
+      exit (1);
+    }
+
+  stack_t s;
+  s.ss_sp = p;
+  s.ss_size = 2 * MINSIGSTKSZ;
+  s.ss_flags = 0;
+  if (sigaltstack (&s, NULL) != 0)
+    {
+      puts ("tf: sigaltstack failed");
+      exit (1);
+    }
+
+  ti[nr].p = p;
+  ti[nr].s = pthread_self ();
+
+  pthread_barrier_wait (&bar);
+
+  pthread_barrier_wait (&bar);
+
+  return NULL;
+}
+
+
+static int
+do_test (void)
+{
+  sig1 = SIGRTMIN;
+  if (sig1 + N > SIGRTMAX)
+    {
+      puts ("too few RT signals");
+      return 0;
+    }
+
+  struct sigaction sa;
+  sa.sa_handler = handler;
+  sa.sa_flags = 0;
+  sigemptyset (&sa.sa_mask);
+
+  if (sigaction (sig1, &sa, NULL) != 0
+      || sigaction (sig1 + 1, &sa, NULL) != 0
+      || sigaction (sig1 + 2, &sa, NULL) != 0)
+    {
+      puts ("sigaction failed");
+      return 1;
+    }
+
+  if (pthread_barrier_init (&bar, NULL, 1 + N) != 0)
+    {
+      puts ("barrier_init failed");
+      return 1;
+    }
+
+  pthread_t th[N];
+  size_t i;
+  for (i = 0; i < N; ++i)
+    if (pthread_create (&th[i], NULL, tf, (void *) (long int) i) != 0)
+      {
+	puts ("create failed");
+	return 1;
+      }
+
+  /* Block the three signals.  */
+  sigset_t ss;
+  sigemptyset (&ss);
+  for (i = 0; i <= N; ++i)
+    sigaddset (&ss, sig1 + i);
+  if (pthread_sigmask (SIG_BLOCK, &ss, NULL) != 0)
+    {
+      puts ("main: sigmask failed");
+      return 1;
+    }
+
+  pthread_barrier_wait (&bar);
+
+  /* Send some signals.  */
+  pid_t me = getpid ();
+  kill (me, sig1 + N);
+  for (i = 0; i < N; ++i)
+    kill (me, sig1 + i);
+  kill (me, sig1 + N);
+
+  /* Give the signals a chance to be worked on.  */
+  sleep (1);
+
+  pthread_barrier_wait (&bar);
+
+  for (i = 0; i < N; ++i)
+    if (pthread_join (th[i], NULL) != 0)
+      {
+	puts ("join failed");
+	return 1;
+      }
+
+  return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-signal7.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-signal7.c
new file mode 100644
index 00000000..82ef11c2
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-signal7.c
@@ -0,0 +1,59 @@
+/* Copyright (C) 2005 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2005.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+
+
+static int
+do_test (void)
+{
+  int result = 0;
+
+  errno = 0;
+  if (sigaction (SIGCANCEL, NULL, NULL) == 0)
+    {
+      puts ("sigaction(SIGCANCEL) did not fail");
+      result = 1;
+    }
+  else if (errno != EINVAL)
+    {
+      puts ("sigaction(SIGCANCEL) did not set errno to EINVAL");
+      result = 1;
+    }
+
+  errno = 0;
+  if (sigaction (SIGSETXID, NULL, NULL) == 0)
+    {
+      puts ("sigaction(SIGSETXID) did not fail");
+      result = 1;
+    }
+  else if (errno != EINVAL)
+    {
+      puts ("sigaction(SIGSETXID) did not set errno to EINVAL");
+      result = 1;
+    }
+
+  return result;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-spin1.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-spin1.c
new file mode 100644
index 00000000..259b4b4d
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-spin1.c
@@ -0,0 +1,57 @@
+/* Copyright (C) 2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2002.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+
+
+static int
+do_test (void)
+{
+  pthread_spinlock_t s;
+
+  if (pthread_spin_init (&s, PTHREAD_PROCESS_PRIVATE) != 0)
+    {
+      puts ("spin_init failed");
+      return 1;
+    }
+
+  if (pthread_spin_lock (&s) != 0)
+    {
+      puts ("spin_lock failed");
+      return 1;
+    }
+
+  if (pthread_spin_unlock (&s) != 0)
+    {
+      puts ("spin_unlock failed");
+      return 1;
+    }
+
+  if (pthread_spin_destroy (&s) != 0)
+    {
+      puts ("spin_destroy failed");
+      return 1;
+    }
+
+  return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-spin2.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-spin2.c
new file mode 100644
index 00000000..5b1df6c4
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-spin2.c
@@ -0,0 +1,159 @@
+/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2002.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+static int
+do_test (void)
+{
+  size_t ps = sysconf (_SC_PAGESIZE);
+  char tmpfname[] = "/tmp/tst-spin2.XXXXXX";
+  char data[ps];
+  void *mem;
+  int fd;
+  pthread_spinlock_t *s;
+  pid_t pid;
+  char *p;
+  int err;
+
+  fd = mkstemp (tmpfname);
+  if (fd == -1)
+    {
+      printf ("cannot open temporary file: %m\n");
+      return 1;
+    }
+
+  /* Make sure it is always removed.  */
+  unlink (tmpfname);
+
+  /* Create one page of data.  */
+  memset (data, '\0', ps);
+
+  /* Write the data to the file.  */
+  if (write (fd, data, ps) != (ssize_t) ps)
+    {
+      puts ("short write");
+      return 1;
+    }
+
+  mem = mmap (NULL, ps, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+  if (mem == MAP_FAILED)
+    {
+      printf ("mmap failed: %m\n");
+      return 1;
+    }
+
+  s = (pthread_spinlock_t *) (((uintptr_t) mem
+			       + __alignof (pthread_spinlock_t))
+			      & ~(__alignof (pthread_spinlock_t) - 1));
+  p = (char *) (s + 1);
+
+  if (pthread_spin_init (s, PTHREAD_PROCESS_SHARED) != 0)
+    {
+      puts ("spin_init failed");
+      return 1;
+    }
+
+  if (pthread_spin_lock (s) != 0)
+    {
+      puts ("spin_lock failed");
+      return 1;
+    }
+
+  err = pthread_spin_trylock (s);
+  if (err == 0)
+    {
+      puts ("1st spin_trylock succeeded");
+      return 1;
+    }
+  else if (err != EBUSY)
+    {
+      puts ("1st spin_trylock didn't return EBUSY");
+      return 1;
+    }
+
+  err = pthread_spin_unlock (s);
+  if (err != 0)
+    {
+      puts ("parent: spin_unlock failed");
+      return 1;
+    }
+
+  err = pthread_spin_trylock (s);
+  if (err != 0)
+    {
+      puts ("2nd spin_trylock failed");
+      return 1;
+    }
+
+  *p = 0;
+
+  puts ("going to fork now");
+  pid = fork ();
+  if (pid == -1)
+    {
+      puts ("fork failed");
+      return 1;
+    }
+  else if (pid == 0)
+    {
+      /* Play some lock ping-pong.  It's our turn to unlock first.  */
+      if ((*p)++ != 0)
+	{
+	  puts ("child: *p != 0");
+	  return 1;
+	}
+
+      if (pthread_spin_unlock (s) != 0)
+	{
+	  puts ("child: 1st spin_unlock failed");
+	  return 1;
+	}
+
+      puts ("child done");
+    }
+  else
+    {
+      if (pthread_spin_lock (s) != 0)
+	{
+	  puts ("parent: 2nd spin_lock failed");
+	  return 1;
+	}
+
+      puts ("waiting for child");
+
+      waitpid (pid, NULL, 0);
+
+      puts ("parent done");
+    }
+
+  return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-spin3.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-spin3.c
new file mode 100644
index 00000000..44377403
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-spin3.c
@@ -0,0 +1,55 @@
+/* Copyright (C) 2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2002.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+
+
+static int
+do_test (void)
+{
+  pthread_spinlock_t s;
+
+  if (pthread_spin_init (&s, PTHREAD_PROCESS_PRIVATE) != 0)
+    {
+      puts ("spin_init failed");
+      return 1;
+    }
+
+  if (pthread_spin_lock (&s) != 0)
+    {
+      puts ("1st spin_lock failed");
+      return 1;
+    }
+
+  /* Set an alarm for 1 second.  The wrapper will expect this.  */
+  alarm (1);
+
+  /* This call should never return.  */
+  pthread_spin_lock (&s);
+
+  puts ("2nd spin_lock returned");
+  return 1;
+}
+
+#define EXPECTED_SIGNAL SIGALRM
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-stack-align.h b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-stack-align.h
new file mode 100644
index 00000000..59b1e656
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-stack-align.h
@@ -0,0 +1,35 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+
+#define TEST_STACK_ALIGN() \
+  ({									     \
+    double _d = 12.0;							     \
+    long double _ld = 15.0;						     \
+    int _ret = 0;							     \
+    printf ("double:  %g %p %zu\n", _d, &_d, __alignof (double));	     \
+    if ((((uintptr_t) &_d) & (__alignof (double) - 1)) != 0)		     \
+      _ret = 1;								     \
+									     \
+    printf ("ldouble: %Lg %p %zu\n", _ld, &_ld, __alignof (long double));    \
+    if ((((uintptr_t) &_ld) & (__alignof (long double) - 1)) != 0)	     \
+      _ret = 1;								     \
+    _ret;								     \
+    })
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-stack1.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-stack1.c
new file mode 100644
index 00000000..93405981
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-stack1.c
@@ -0,0 +1,146 @@
+/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2002.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+static void *stack;
+static size_t size;
+
+
+static void *
+tf (void *a)
+{
+  int result = 0;
+
+  puts ("child start");
+
+  pthread_attr_t attr;
+  if (pthread_getattr_np (pthread_self (), &attr) != 0)
+    {
+      puts ("getattr_np failed");
+      exit (1);
+    }
+
+  size_t test_size;
+  void *test_stack;
+  if (pthread_attr_getstack (&attr, &test_stack, &test_size) != 0)
+    {
+      puts ("attr_getstack failed");
+      exit (1);
+    }
+
+  if (test_size != size)
+    {
+      printf ("child: reported size differs: is %zu, expected %zu\n",
+	      test_size, size);
+      result = 1;
+    }
+
+  if (test_stack != stack)
+    {
+      printf ("child: reported stack address differs: is %p, expected %p\n",
+	      test_stack, stack);
+      result = 1;
+    }
+
+  puts ("child OK");
+
+  return result ? (void *) 1l : NULL;
+}
+
+
+int
+do_test (void)
+{
+  int result = 0;
+
+  size = MAX (4 * getpagesize (), PTHREAD_STACK_MIN);
+  if (posix_memalign (&stack, getpagesize (), size) != 0)
+    {
+      puts ("out of memory while allocating the stack memory");
+      exit (1);
+    }
+
+  pthread_attr_t attr;
+  if (pthread_attr_init (&attr) != 0)
+    {
+      puts ("attr_init failed");
+      exit (1);
+    }
+
+  puts ("attr_setstack");
+  if (pthread_attr_setstack (&attr, stack, size) != 0)
+    {
+      puts ("attr_setstack failed");
+      exit (1);
+    }
+
+  size_t test_size;
+  void *test_stack;
+  puts ("attr_getstack");
+  if (pthread_attr_getstack (&attr, &test_stack, &test_size) != 0)
+    {
+      puts ("attr_getstack failed");
+      exit (1);
+    }
+
+  if (test_size != size)
+    {
+      printf ("reported size differs: is %zu, expected %zu\n",
+	      test_size, size);
+      result = 1;
+    }
+
+  if (test_stack != stack)
+    {
+      printf ("reported stack address differs: is %p, expected %p\n",
+	      test_stack, stack);
+      result = 1;
+    }
+
+  puts ("create");
+
+  pthread_t th;
+  if (pthread_create (&th, &attr, tf, NULL) != 0)
+    {
+      puts ("failed to create thread");
+      exit (1);
+    }
+
+  void *status;
+  if (pthread_join (th, &status) != 0)
+    {
+      puts ("join failed");
+      exit (1);
+    }
+
+  result |= status != NULL;
+
+  return result;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-stack2.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-stack2.c
new file mode 100644
index 00000000..5fcdb18d
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-stack2.c
@@ -0,0 +1,80 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek , 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+/* Test whether it is possible to create a thread with PTHREAD_STACK_MIN
+   stack size.  */
+
+#include 
+#include 
+#include 
+#include 
+
+static int seen;
+
+static void *
+tf (void *p)
+{
+  ++seen;
+  return NULL;
+}
+
+static int
+do_test (void)
+{
+  pthread_attr_t attr;
+  pthread_attr_init (&attr);
+
+  int result = 0;
+  int res = pthread_attr_setstacksize (&attr, PTHREAD_STACK_MIN);
+  if (res)
+    {
+      printf ("pthread_attr_setstacksize failed %d\n", res);
+      result = 1;
+    }
+
+  /* Create the thread.  */
+  pthread_t th;
+  res = pthread_create (&th, &attr, tf, NULL);
+  if (res)
+    {
+      printf ("pthread_create failed %d\n", res);
+      result = 1;
+    }
+  else
+    {
+      res = pthread_join (th, NULL);
+      if (res)
+	{
+	  printf ("pthread_join failed %d\n", res);
+	  result = 1;
+	}
+    }
+
+  if (seen != 1)
+    {
+      printf ("seen %d != 1\n", seen);
+      result = 1;
+    }
+
+  return result;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-stdio1.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-stdio1.c
new file mode 100644
index 00000000..ebb3e2f0
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-stdio1.c
@@ -0,0 +1,57 @@
+/* Copyright (C) 2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2002.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+
+
+static void *tf (void *a)
+{
+  flockfile (stdout);
+  /* This call should never return.  */
+  return a;
+}
+
+
+int
+do_test (void)
+{
+  pthread_t th;
+
+  flockfile (stdout);
+
+  if (pthread_create (&th, NULL, tf, NULL) != 0)
+    {
+      write (2, "create failed\n", 14);
+      _exit (1);
+    }
+
+  pthread_join (th, NULL);
+
+  puts ("join returned");
+
+  return 0;
+}
+
+
+#define EXPECTED_SIGNAL SIGALRM
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-stdio2.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-stdio2.c
new file mode 100644
index 00000000..08d6addf
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-stdio2.c
@@ -0,0 +1,82 @@
+/* Copyright (C) 2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2002.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+static void *tf (void *a)
+{
+  puts ("start tf");
+
+  /* Multiple locking, implicitly or explicitly, must be possible.  */
+  flockfile (stdout);
+
+  puts ("after first flockfile");
+
+  flockfile (stdout);
+
+  puts ("foo");
+
+  funlockfile (stdout);
+
+  puts ("after first funlockfile");
+
+  funlockfile (stdout);
+
+  puts ("all done");
+
+  return a;
+}
+
+
+int
+do_test (void)
+{
+  pthread_t th;
+
+  if (pthread_create (&th, NULL, tf, NULL) != 0)
+    {
+      write (2, "create failed\n", 14);
+      _exit (1);
+    }
+
+  void *result;
+  if (pthread_join (th, &result) != 0)
+    {
+      puts ("join failed");
+      exit (1);
+    }
+  else if (result != NULL)
+    {
+      printf ("wrong return value: %p, expected %p\n", result, NULL);
+      exit (1);
+    }
+
+  puts ("join returned succsefully");
+
+  return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-sysconf.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-sysconf.c
new file mode 100644
index 00000000..3ad1b6a3
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-sysconf.c
@@ -0,0 +1,48 @@
+/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2002.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+
+
+static int
+do_test (void)
+{
+  puts ("We expect no limits");
+  /* We have no fixed limit on the number of threads.  Make sure the
+     headers tell the right story.  */
+#ifdef PTHREAD_THREADS_MAX
+  printf ("Header report maximum number of threads = %lu\n",
+	  (unsigned long int) PTHREAD_THREADS_MAX);
+  return 1;
+#else
+  long int r = sysconf (_SC_THREAD_THREADS_MAX);
+  if (r != -1)
+    {
+      printf ("sysconf(_SC_THREAD_THREADS_MAX) return %ld\n", r);
+      return 1;
+    }
+#endif
+
+  return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-timer2.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-timer2.c
new file mode 100644
index 00000000..60026c1e
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-timer2.c
@@ -0,0 +1,65 @@
+/* Test for crashing bugs when trying to create too many timers.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#if _POSIX_THREADS
+# include 
+
+void
+thread (union sigval arg)
+{
+  puts ("Timeout");
+}
+
+int
+do_test (void)
+{
+  int i, res;
+  timer_t timerId;
+  struct itimerspec itval;
+  struct sigevent sigev;
+
+  itval.it_interval.tv_sec = 2;
+  itval.it_interval.tv_nsec = 0;
+  itval.it_value.tv_sec = 2;
+  itval.it_value.tv_nsec = 0;
+
+  sigev.sigev_notify = SIGEV_THREAD;
+  sigev.sigev_signo = SIGRTMIN;
+  sigev.sigev_notify_function = thread;
+  sigev.sigev_notify_attributes = 0;
+  sigev.sigev_value.sival_ptr = (void *) &timerId;
+
+  for (i = 0; i < 100; i++)
+    {
+      printf ("cnt = %d\n", i);
+
+      if (timer_create (CLOCK_REALTIME, &sigev, &timerId) < 0)
+	{
+	  perror ("timer_create");
+	  continue;
+	}
+
+      res = timer_settime (timerId, 0, &itval, NULL);
+      if (res < 0)
+	perror ("timer_settime");
+
+      res = timer_delete (timerId);
+      if (res < 0)
+	perror ("timer_delete");
+    }
+
+  return 0;
+}
+
+# define TEST_FUNCTION do_test ()
+#else
+# define TEST_FUNCTION 0
+#endif
+
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-timer3.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-timer3.c
new file mode 100644
index 00000000..8113f669
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-timer3.c
@@ -0,0 +1,86 @@
+/* Test for bogus per-thread deletion of timers.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#if _POSIX_THREADS
+# include 
+
+
+/* Creating timers in another thread should work too.  */
+static void *
+do_timer_create (void *arg)
+{
+  struct sigevent *const sigev = arg;
+  timer_t *const timerId = sigev->sigev_value.sival_ptr;
+  if (timer_create (CLOCK_REALTIME, sigev, timerId) < 0)
+    {
+      printf ("timer_create: %m\n");
+      return NULL;
+    }
+  return timerId;
+}
+
+
+static int
+do_test (void)
+{
+  int i, res;
+  timer_t timerId;
+  struct itimerspec itval;
+  struct sigevent sigev;
+
+  itval.it_interval.tv_sec = 2;
+  itval.it_interval.tv_nsec = 0;
+  itval.it_value.tv_sec = 2;
+  itval.it_value.tv_nsec = 0;
+
+  sigev.sigev_notify = SIGEV_SIGNAL;
+  sigev.sigev_signo = SIGALRM;
+  sigev.sigev_value.sival_ptr = (void *) &timerId;
+
+  for (i = 0; i < 100; i++)
+    {
+      printf ("cnt = %d\n", i);
+
+      pthread_t thr;
+      res = pthread_create (&thr, NULL, &do_timer_create, &sigev);
+      if (res)
+	{
+	  printf ("pthread_create: %s\n", strerror (res));
+	  continue;
+	}
+      void *val;
+      res = pthread_join (thr, &val);
+      if (res)
+	{
+	  printf ("pthread_join: %s\n", strerror (res));
+	  continue;
+	}
+      if (val == NULL)
+	continue;
+
+      res = timer_settime (timerId, 0, &itval, NULL);
+      if (res < 0)
+	printf ("timer_settime: %m\n");
+
+      res = timer_delete (timerId);
+      if (res < 0)
+	printf ("timer_delete: %m\n");
+    }
+
+  return 0;
+}
+
+# define TEST_FUNCTION do_test ()
+#else
+# define TEST_FUNCTION 0
+#endif
+
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-timer4.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-timer4.c
new file mode 100644
index 00000000..5bec0118
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-timer4.c
@@ -0,0 +1,648 @@
+/* Tests for POSIX timer implementation.
+   Copyright (C) 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek , 2004
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public License as
+   published by the Free Software Foundation; either version 2.1 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#if _POSIX_THREADS
+# include 
+
+# ifndef TEST_CLOCK
+#  define TEST_CLOCK		CLOCK_REALTIME
+# endif
+
+pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
+pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
+
+timer_t timer_none, timer_sig1, timer_sig2, timer_thr1, timer_thr2;
+
+int thr1_cnt, thr1_err;
+union sigval thr1_sigval;
+struct timespec thr1_ts;
+
+static void
+thr1 (union sigval sigval)
+{
+  pthread_mutex_lock (&lock);
+  thr1_err = clock_gettime (TEST_CLOCK, &thr1_ts);
+  if (thr1_cnt >= 5)
+    {
+      struct itimerspec it = { };
+      thr1_err |= timer_settime (timer_thr1, 0, &it, NULL);
+    }
+  thr1_sigval = sigval;
+  ++thr1_cnt;
+  pthread_cond_signal (&cond);
+  pthread_mutex_unlock (&lock);
+}
+
+int thr2_cnt, thr2_err;
+union sigval thr2_sigval;
+size_t thr2_guardsize;
+struct timespec thr2_ts;
+
+static void
+thr2 (union sigval sigval)
+{
+  pthread_attr_t nattr;
+  int err = 0;
+  size_t guardsize = -1;
+  int ret = pthread_getattr_np (pthread_self (), &nattr);
+  if (ret)
+    {
+      errno = ret;
+      printf ("*** pthread_getattr_np failed: %m\n");
+      err = 1;
+    }
+  else
+    {
+      ret = pthread_attr_getguardsize (&nattr, &guardsize);
+      if (ret)
+        {
+          errno = ret;
+          printf ("*** pthread_attr_getguardsize failed: %m\n");
+          err = 1;
+        }
+      if (pthread_attr_destroy (&nattr) != 0)
+        {
+          puts ("*** pthread_attr_destroy failed");
+          err = 1;
+        }
+    }
+  pthread_mutex_lock (&lock);
+  thr2_err = clock_gettime (TEST_CLOCK, &thr2_ts) | err;
+  if (thr2_cnt >= 5)
+    {
+      struct itimerspec it = { };
+      thr2_err |= timer_settime (timer_thr2, 0, &it, NULL);
+    }
+  thr2_sigval = sigval;
+  ++thr2_cnt;
+  thr2_guardsize = guardsize;
+  pthread_cond_signal (&cond);
+  pthread_mutex_unlock (&lock);
+}
+
+volatile int sig1_cnt, sig1_err;
+volatile union sigval sig1_sigval;
+struct timespec sig1_ts;
+
+static void
+sig1_handler (int sig, siginfo_t *info, void *ctx)
+{
+  int err = 0;
+  if (sig != SIGRTMIN) err |= 1 << 0;
+  if (info->si_signo != SIGRTMIN) err |= 1 << 1;
+  if (info->si_code != SI_TIMER) err |= 1 << 2;
+  if (clock_gettime (TEST_CLOCK, &sig1_ts) != 0)
+    err |= 1 << 3;
+  if (sig1_cnt >= 5)
+    {
+      struct itimerspec it = { };
+      if (timer_settime (timer_sig1, 0, &it, NULL))
+	err |= 1 << 4;
+    }
+  sig1_err |= err;
+  sig1_sigval = info->si_value;
+  ++sig1_cnt;
+}
+
+volatile int sig2_cnt, sig2_err;
+volatile union sigval sig2_sigval;
+struct timespec sig2_ts;
+
+static void
+sig2_handler (int sig, siginfo_t *info, void *ctx)
+{
+  int err = 0;
+  if (sig != SIGRTMIN + 1) err |= 1 << 0;
+  if (info->si_signo != SIGRTMIN + 1) err |= 1 << 1;
+  if (info->si_code != SI_TIMER) err |= 1 << 2;
+  if (clock_gettime (TEST_CLOCK, &sig2_ts) != 0)
+    err |= 1 << 3;
+  if (sig2_cnt >= 5)
+    {
+      struct itimerspec it = { };
+      if (timer_settime (timer_sig2, 0, &it, NULL))
+	err |= 1 << 4;
+    }
+  sig2_err |= err;
+  sig2_sigval = info->si_value;
+  ++sig2_cnt;
+}
+
+/* Check if end is later or equal to start + nsec.  */
+static int
+check_ts (const char *name, const struct timespec *start,
+	  const struct timespec *end, long msec)
+{
+  struct timespec ts = *start;
+
+  ts.tv_sec += msec / 1000000;
+  ts.tv_nsec += (msec % 1000000) * 1000;
+  if (ts.tv_nsec >= 1000000000)
+    {
+      ++ts.tv_sec;
+      ts.tv_nsec -= 1000000000;
+    }
+  if (end->tv_sec < ts.tv_sec
+      || (end->tv_sec == ts.tv_sec && end->tv_nsec < ts.tv_nsec))
+    {
+      printf ("\
+*** timer %s invoked too soon: %ld.%09ld instead of expected %ld.%09ld\n",
+	      name, (long) end->tv_sec, end->tv_nsec,
+	      (long) ts.tv_sec, ts.tv_nsec);
+      return 1;
+    }
+  else
+    return 0;
+}
+
+#define TIMEOUT 15
+#define TEST_FUNCTION do_test ()
+static int
+do_test (void)
+{
+  int result = 0;
+
+#ifdef TEST_CLOCK_MISSING
+  const char *missing = TEST_CLOCK_MISSING (TEST_CLOCK);
+  if (missing != NULL)
+    {
+      printf ("%s missing, skipping test\n", missing);
+      return 0;
+    }
+#endif
+
+  struct timespec ts;
+  if (clock_gettime (TEST_CLOCK, &ts) != 0)
+    {
+      printf ("*** clock_gettime failed: %m\n");
+      result = 1;
+    }
+  else
+    printf ("clock_gettime returned timespec = { %ld, %ld }\n",
+	    (long) ts.tv_sec, ts.tv_nsec);
+
+  if (clock_getres (TEST_CLOCK, &ts) != 0)
+    {
+      printf ("*** clock_getres failed: %m\n");
+      result = 1;
+    }
+  else
+    printf ("clock_getres returned timespec = { %ld, %ld }\n",
+	    (long) ts.tv_sec, ts.tv_nsec);
+
+  struct sigevent ev;
+  memset (&ev, 0x11, sizeof (ev));
+  ev.sigev_notify = SIGEV_NONE;
+  if (timer_create (TEST_CLOCK, &ev, &timer_none) != 0)
+    {
+      printf ("*** timer_create for timer_none failed: %m\n");
+      return 1;
+    }
+
+  struct sigaction sa = { .sa_sigaction = sig1_handler,
+			  .sa_flags = SA_SIGINFO };
+  sigemptyset (&sa.sa_mask);
+  sigaction (SIGRTMIN, &sa, NULL);
+  sa.sa_sigaction = sig2_handler;
+  sigaction (SIGRTMIN + 1, &sa, NULL);
+
+  memset (&ev, 0x22, sizeof (ev));
+  ev.sigev_notify = SIGEV_SIGNAL;
+  ev.sigev_signo = SIGRTMIN;
+  ev.sigev_value.sival_ptr = &ev;
+  if (timer_create (TEST_CLOCK, &ev, &timer_sig1) != 0)
+    {
+      printf ("*** timer_create for timer_sig1 failed: %m\n");
+      return 1;
+    }
+
+  memset (&ev, 0x33, sizeof (ev));
+  ev.sigev_notify = SIGEV_SIGNAL;
+  ev.sigev_signo = SIGRTMIN + 1;
+  ev.sigev_value.sival_int = 163;
+  if (timer_create (TEST_CLOCK, &ev, &timer_sig2) != 0)
+    {
+      printf ("*** timer_create for timer_sig2 failed: %m\n");
+      return 1;
+    }
+
+  memset (&ev, 0x44, sizeof (ev));
+  ev.sigev_notify = SIGEV_THREAD;
+  ev.sigev_notify_function = thr1;
+  ev.sigev_notify_attributes = NULL;
+  ev.sigev_value.sival_ptr = &ev;
+  if (timer_create (TEST_CLOCK, &ev, &timer_thr1) != 0)
+    {
+      printf ("*** timer_create for timer_thr1 failed: %m\n");
+      return 1;
+    }
+
+  pthread_attr_t nattr;
+  if (pthread_attr_init (&nattr)
+      || pthread_attr_setguardsize (&nattr, 0))
+    {
+      puts ("*** pthread_attr_t setup failed");
+      result = 1;
+    }
+
+  memset (&ev, 0x55, sizeof (ev));
+  ev.sigev_notify = SIGEV_THREAD;
+  ev.sigev_notify_function = thr2;
+  ev.sigev_notify_attributes = &nattr;
+  ev.sigev_value.sival_int = 111;
+  if (timer_create (TEST_CLOCK, &ev, &timer_thr2) != 0)
+    {
+      printf ("*** timer_create for timer_thr2 failed: %m\n");
+      return 1;
+    }
+
+  int ret = timer_getoverrun (timer_thr1);
+  if (ret != 0)
+    {
+      if (ret == -1)
+	printf ("*** timer_getoverrun failed: %m\n");
+      else
+	printf ("*** timer_getoverrun returned %d != 0\n", ret);
+      result = 1;
+    }
+
+  struct itimerspec it;
+  it.it_value.tv_sec = 0;
+  it.it_value.tv_nsec = -26;
+  it.it_interval.tv_sec = 0;
+  it.it_interval.tv_nsec = 0;
+  if (timer_settime (timer_sig1, 0, &it, NULL) == 0)
+    {
+      puts ("*** timer_settime with negative tv_nsec unexpectedly succeeded");
+      result = 1;
+    }
+  else if (errno != EINVAL)
+    {
+      printf ("*** timer_settime with negative tv_nsec did not fail with "
+	      "EINVAL: %m\n");
+      result = 1;
+    }
+
+  it.it_value.tv_nsec = 100000;
+  it.it_interval.tv_nsec = 1000000000;
+  if (timer_settime (timer_sig2, 0, &it, NULL) == 0)
+    {
+      puts ("\
+*** timer_settime with tv_nsec 1000000000 unexpectedly succeeded");
+      result = 1;
+    }
+  else if (errno != EINVAL)
+    {
+      printf ("*** timer_settime with tv_nsec 1000000000 did not fail with "
+	      "EINVAL: %m\n");
+      result = 1;
+    }
+
+#if 0
+  it.it_value.tv_nsec = 0;
+  it.it_interval.tv_nsec = -26;
+  if (timer_settime (timer_thr1, 0, &it, NULL) != 0)
+    {
+      printf ("\
+!!! timer_settime with it_value 0 it_interval invalid failed: %m\n");
+      /* FIXME: is this mandated by POSIX?
+      result = 1; */
+    }
+
+  it.it_interval.tv_nsec = 3000000000;
+  if (timer_settime (timer_thr2, 0, &it, NULL) != 0)
+    {
+      printf ("\
+!!! timer_settime with it_value 0 it_interval invalid failed: %m\n");
+      /* FIXME: is this mandated by POSIX?
+      result = 1; */
+    }
+#endif
+
+  struct timespec startts;
+  if (clock_gettime (TEST_CLOCK, &startts) != 0)
+    {
+      printf ("*** clock_gettime failed: %m\n");
+      result = 1;
+    }
+
+  it.it_value.tv_nsec = 100000000;
+  it.it_interval.tv_nsec = 0;
+  if (timer_settime (timer_none, 0, &it, NULL) != 0)
+    {
+      printf ("*** timer_settime timer_none failed: %m\n");
+      result = 1;
+    }
+
+  it.it_value.tv_nsec = 200000000;
+  if (timer_settime (timer_thr1, 0, &it, NULL) != 0)
+    {
+      printf ("*** timer_settime timer_thr1 failed: %m\n");
+      result = 1;
+    }
+
+  it.it_value.tv_nsec = 300000000;
+  if (timer_settime (timer_thr2, 0, &it, NULL) != 0)
+    {
+      printf ("*** timer_settime timer_thr2 failed: %m\n");
+      result = 1;
+    }
+
+  it.it_value.tv_nsec = 400000000;
+  if (timer_settime (timer_sig1, 0, &it, NULL) != 0)
+    {
+      printf ("*** timer_settime timer_sig1 failed: %m\n");
+      result = 1;
+    }
+
+  it.it_value.tv_nsec = 500000000;
+  if (TEMP_FAILURE_RETRY (timer_settime (timer_sig2, 0, &it, NULL)) != 0)
+    {
+      printf ("*** timer_settime timer_sig2 failed: %m\n");
+      result = 1;
+    }
+
+  pthread_mutex_lock (&lock);
+  while (thr1_cnt == 0 || thr2_cnt == 0)
+    pthread_cond_wait (&cond, &lock);
+  pthread_mutex_unlock (&lock);
+
+  while (sig1_cnt == 0 || sig2_cnt == 0)
+    {
+      ts.tv_sec = 0;
+      ts.tv_nsec = 100000000;
+      nanosleep (&ts, NULL);
+    }
+
+  pthread_mutex_lock (&lock);
+
+  if (thr1_cnt != 1)
+    {
+      printf ("*** thr1 not called exactly once, but %d times\n", thr1_cnt);
+      result = 1;
+    }
+  else if (thr1_err)
+    {
+      puts ("*** an error occurred in thr1");
+      result = 1;
+    }
+  else if (thr1_sigval.sival_ptr != &ev)
+    {
+      printf ("*** thr1_sigval.sival_ptr %p != %p\n",
+	      thr1_sigval.sival_ptr, &ev);
+      result = 1;
+    }
+  else if (check_ts ("thr1", &startts, &thr1_ts, 200000))
+    result = 1;
+
+  if (thr2_cnt != 1)
+    {
+      printf ("*** thr2 not called exactly once, but %d times\n", thr2_cnt);
+      result = 1;
+    }
+  else if (thr2_err)
+    {
+      puts ("*** an error occurred in thr2");
+      result = 1;
+    }
+  else if (thr2_sigval.sival_int != 111)
+    {
+      printf ("*** thr2_sigval.sival_ptr %d != 111\n", thr2_sigval.sival_int);
+      result = 1;
+    }
+  else if (check_ts ("thr2", &startts, &thr2_ts, 300000))
+    result = 1;
+  else if (thr2_guardsize != 0)
+    {
+      printf ("*** thr2 guardsize %zd != 0\n", thr2_guardsize);
+      result = 1;
+    }
+
+  pthread_mutex_unlock (&lock);
+
+  if (sig1_cnt != 1)
+    {
+      printf ("*** sig1 not called exactly once, but %d times\n", sig1_cnt);
+      result = 1;
+    }
+  else if (sig1_err)
+    {
+      printf ("*** errors occurred in sig1 handler %x\n", sig1_err);
+      result = 1;
+    }
+  else if (sig1_sigval.sival_ptr != &ev)
+    {
+      printf ("*** sig1_sigval.sival_ptr %p != %p\n",
+	      sig1_sigval.sival_ptr, &ev);
+      result = 1;
+    }
+  else if (check_ts ("sig1", &startts, &sig1_ts, 400000))
+    result = 1;
+
+  if (sig2_cnt != 1)
+    {
+      printf ("*** sig2 not called exactly once, but %d times\n", sig2_cnt);
+      result = 1;
+    }
+  else if (sig2_err)
+    {
+      printf ("*** errors occurred in sig2 handler %x\n", sig2_err);
+      result = 1;
+    }
+  else if (sig2_sigval.sival_int != 163)
+    {
+      printf ("*** sig2_sigval.sival_ptr %d != 163\n", sig2_sigval.sival_int);
+      result = 1;
+    }
+  else if (check_ts ("sig2", &startts, &sig2_ts, 500000))
+    result = 1;
+
+  if (timer_gettime (timer_none, &it) != 0)
+    {
+      printf ("*** timer_gettime timer_none failed: %m\n");
+      result = 1;
+    }
+  else if (it.it_value.tv_sec || it.it_value.tv_nsec
+	   || it.it_interval.tv_sec || it.it_interval.tv_nsec)
+    {
+      printf ("\
+*** timer_gettime timer_none returned { %ld.%09ld, %ld.%09ld }\n",
+	      (long) it.it_value.tv_sec, it.it_value.tv_nsec,
+	      (long) it.it_interval.tv_sec, it.it_interval.tv_nsec);
+      result = 1;
+    }
+
+  if (clock_gettime (TEST_CLOCK, &startts) != 0)
+    {
+      printf ("*** clock_gettime failed: %m\n");
+      result = 1;
+    }
+
+  it.it_value.tv_sec = 1;
+  it.it_value.tv_nsec = 0;
+  it.it_interval.tv_sec = 0;
+  it.it_interval.tv_nsec = 100000000;
+  if (timer_settime (timer_none, 0, &it, NULL) != 0)
+    {
+      printf ("*** timer_settime timer_none failed: %m\n");
+      result = 1;
+    }
+
+  it.it_value.tv_nsec = 100000000;
+  it.it_interval.tv_nsec = 200000000;
+  if (timer_settime (timer_thr1, 0, &it, NULL) != 0)
+    {
+      printf ("*** timer_settime timer_thr1 failed: %m\n");
+      result = 1;
+    }
+
+  it.it_value.tv_nsec = 200000000;
+  it.it_interval.tv_nsec = 300000000;
+  if (timer_settime (timer_thr2, 0, &it, NULL) != 0)
+    {
+      printf ("*** timer_settime timer_thr2 failed: %m\n");
+      result = 1;
+    }
+
+  it.it_value.tv_nsec = 300000000;
+  it.it_interval.tv_nsec = 400000000;
+  if (timer_settime (timer_sig1, 0, &it, NULL) != 0)
+    {
+      printf ("*** timer_settime timer_sig1 failed: %m\n");
+      result = 1;
+    }
+
+  it.it_value.tv_nsec = 400000000;
+  it.it_interval.tv_nsec = 500000000;
+  if (TEMP_FAILURE_RETRY (timer_settime (timer_sig2, 0, &it, NULL)) != 0)
+    {
+      printf ("*** timer_settime timer_sig2 failed: %m\n");
+      result = 1;
+    }
+
+  pthread_mutex_lock (&lock);
+  while (thr1_cnt < 6 || thr2_cnt < 6)
+    pthread_cond_wait (&cond, &lock);
+  pthread_mutex_unlock (&lock);
+
+  while (sig1_cnt < 6 || sig2_cnt < 6)
+    {
+      ts.tv_sec = 0;
+      ts.tv_nsec = 100000000;
+      nanosleep (&ts, NULL);
+    }
+
+  pthread_mutex_lock (&lock);
+
+  if (thr1_err)
+    {
+      puts ("*** an error occurred in thr1");
+      result = 1;
+    }
+  else if (check_ts ("thr1", &startts, &thr1_ts, 1100000 + 4 * 200000))
+    result = 1;
+
+  if (thr2_err)
+    {
+      puts ("*** an error occurred in thr2");
+      result = 1;
+    }
+  else if (check_ts ("thr2", &startts, &thr2_ts, 1200000 + 4 * 300000))
+    result = 1;
+  else if (thr2_guardsize != 0)
+    {
+      printf ("*** thr2 guardsize %zd != 0\n", thr2_guardsize);
+      result = 1;
+    }
+
+  pthread_mutex_unlock (&lock);
+
+  if (sig1_err)
+    {
+      printf ("*** errors occurred in sig1 handler %x\n", sig1_err);
+      result = 1;
+    }
+  else if (check_ts ("sig1", &startts, &sig1_ts, 1300000 + 4 * 400000))
+    result = 1;
+
+  if (sig2_err)
+    {
+      printf ("*** errors occurred in sig2 handler %x\n", sig2_err);
+      result = 1;
+    }
+  else if (check_ts ("sig2", &startts, &sig2_ts, 1400000 + 4 * 500000))
+    result = 1;
+
+  if (timer_gettime (timer_none, &it) != 0)
+    {
+      printf ("*** timer_gettime timer_none failed: %m\n");
+      result = 1;
+    }
+  else if (it.it_interval.tv_sec || it.it_interval.tv_nsec != 100000000)
+    {
+      printf ("\
+!!! second timer_gettime timer_none returned it_interval %ld.%09ld\n",
+	      (long) it.it_interval.tv_sec, it.it_interval.tv_nsec);
+      /* FIXME: For now disabled.
+      result = 1; */
+    }
+
+  if (timer_delete (timer_none) != 0)
+    {
+      printf ("*** timer_delete for timer_none failed: %m\n");
+      result = 1;
+    }
+
+  if (timer_delete (timer_sig1) != 0)
+    {
+      printf ("*** timer_delete for timer_sig1 failed: %m\n");
+      result = 1;
+    }
+
+  if (timer_delete (timer_sig2) != 0)
+    {
+      printf ("*** timer_delete for timer_sig2 failed: %m\n");
+      result = 1;
+    }
+
+  if (timer_delete (timer_thr1) != 0)
+    {
+      printf ("*** timer_delete for timer_thr1 failed: %m\n");
+      result = 1;
+    }
+
+  if (timer_delete (timer_thr2) != 0)
+    {
+      printf ("*** timer_delete for timer_thr2 failed: %m\n");
+      result = 1;
+    }
+  return result;
+}
+#else
+# define TEST_FUNCTION 0
+#endif
+
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-timer5.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-timer5.c
new file mode 100644
index 00000000..6466c8ef
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-timer5.c
@@ -0,0 +1,38 @@
+/* Timer test using the monotonic clock.  */
+
+#include 
+#include 
+
+#if defined CLOCK_MONOTONIC && defined _POSIX_MONOTONIC_CLOCK
+
+# define TEST_CLOCK	CLOCK_MONOTONIC
+# define TEST_CLOCK_MISSING(clock) \
+  (setup_test () ? "CLOCK_MONOTONIC" : NULL)
+
+# include 
+
+static int
+setup_test (void)
+{
+  if (sysconf (_SC_MONOTONIC_CLOCK) <= 0)
+    return 1;
+
+  /* The user-level timers implementation doesn't support CLOCK_MONOTONIC,
+     even though sysconf claims it will.  */
+  timer_t t;
+  if (timer_create (TEST_CLOCK, NULL, &t) != 0)
+    {
+      printf ("timer_create: %m\n");
+      return 1;
+    }
+  timer_delete (t);
+
+  return 0;
+}
+
+# include "tst-timer4.c"
+
+#else
+# define TEST_FUNCTION	0
+# include "../test-skeleton.c"
+#endif
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-tls1.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-tls1.c
new file mode 100644
index 00000000..541035ea
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-tls1.c
@@ -0,0 +1,122 @@
+/* Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+
+#if HAVE___THREAD
+struct test_s
+{
+  int a;
+  int b;
+};
+
+#define INIT_A 1
+#define INIT_B 42
+/* Deliberately not static.  */
+__thread struct test_s s __attribute__ ((tls_model ("initial-exec"))) =
+{
+  .a = INIT_A,
+  .b = INIT_B
+};
+
+
+static void *
+tf (void *arg)
+{
+  if (s.a != INIT_A || s.b != INIT_B)
+    {
+      puts ("initial value of s in child thread wrong");
+      exit (1);
+    }
+
+  ++s.a;
+
+  return NULL;
+}
+#endif
+
+
+int
+do_test (void)
+{
+#if !HAVE___THREAD
+
+  puts ("No __thread support in compiler, test skipped.");
+
+  return 0;
+#else
+
+  if (s.a != INIT_A || s.b != INIT_B)
+    {
+      puts ("initial value of s in main thread wrong");
+      exit (1);
+    }
+
+  pthread_attr_t a;
+
+  if (pthread_attr_init (&a) != 0)
+    {
+      puts ("attr_init failed");
+      exit (1);
+    }
+
+  if (pthread_attr_setstacksize (&a, 1 * 1024 * 1024) != 0)
+    {
+      puts ("attr_setstacksize failed");
+      return 1;
+    }
+
+#define N 10
+  int i;
+  for (i = 0; i < N; ++i)
+    {
+#define M 10
+      pthread_t th[M];
+      int j;
+      for (j = 0; j < M; ++j, ++s.a)
+	if (pthread_create (&th[j], &a, tf, NULL) != 0)
+	  {
+	    puts ("pthread_create failed");
+	    exit (1);
+	  }
+
+      for (j = 0; j < M; ++j)
+	if (pthread_join (th[j], NULL) != 0)
+	  {
+	    puts ("pthread_join failed");
+	    exit (1);
+	  }
+    }
+
+  if (pthread_attr_destroy (&a) != 0)
+    {
+      puts ("attr_destroy failed");
+      exit (1);
+    }
+
+  return 0;
+#endif
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-tls2.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-tls2.c
new file mode 100644
index 00000000..3615d1b8
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-tls2.c
@@ -0,0 +1,216 @@
+/* Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#if HAVE___THREAD
+
+#define N 10
+static pthread_t th[N];
+
+
+#define CB(n) \
+static void								      \
+cb##n (void)								      \
+{									      \
+  if (th[n] != pthread_self ())						      \
+    {									      \
+      write (STDOUT_FILENO, "wrong callback\n", 15);			      \
+      _exit (1);							      \
+    }									      \
+}
+CB (0)
+CB (1)
+CB (2)
+CB (3)
+CB (4)
+CB (5)
+CB (6)
+CB (7)
+CB (8)
+CB (9)
+static void (*cbs[]) (void) =
+{
+  cb0, cb1, cb2, cb3, cb4, cb5, cb6, cb7, cb8, cb9
+};
+
+
+static __thread void (*fp) (void) __attribute__ ((tls_model ("local-exec")));
+
+
+static sem_t s;
+
+
+#define THE_SIG SIGUSR1
+static void
+handler (int sig)
+{
+  if (sig != THE_SIG)
+    {
+      write (STDOUT_FILENO, "wrong signal\n", 13);
+      _exit (1);
+    }
+
+  fp ();
+
+  if (sem_post (&s) != 0)
+    {
+      write (STDOUT_FILENO, "sem_post failed\n", 16);
+      _exit (1);
+    }
+}
+
+
+static pthread_barrier_t b;
+
+#define TOTAL_SIGS 1000
+static int nsigs;
+
+
+static void *
+tf (void *arg)
+{
+  fp = arg;
+
+  pthread_barrier_wait (&b);
+
+  pthread_barrier_wait (&b);
+
+  if (nsigs != TOTAL_SIGS)
+    {
+      puts ("barrier_wait prematurely returns");
+      exit (1);
+    }
+
+  return NULL;
+}
+#endif
+
+int
+do_test (void)
+{
+#if !HAVE___THREAD
+
+  puts ("No __thread support in compiler, test skipped.");
+
+  return 0;
+#else
+
+  if (pthread_barrier_init (&b, NULL, N + 1) != 0)
+    {
+      puts ("barrier_init failed");
+      exit (1);
+    }
+
+  if (sem_init (&s, 0, 0) != 0)
+    {
+      puts ("sem_init failed");
+      exit (1);
+    }
+
+  struct sigaction sa;
+  sa.sa_handler = handler;
+  sigemptyset (&sa.sa_mask);
+  sa.sa_flags = 0;
+  if (sigaction (THE_SIG, &sa, NULL) != 0)
+    {
+      puts ("sigaction failed");
+      exit (1);
+    }
+
+  pthread_attr_t a;
+
+  if (pthread_attr_init (&a) != 0)
+    {
+      puts ("attr_init failed");
+      exit (1);
+    }
+
+  if (pthread_attr_setstacksize (&a, 1 * 1024 * 1024) != 0)
+    {
+      puts ("attr_setstacksize failed");
+      return 1;
+    }
+
+  int i;
+  for (i = 0; i < N; ++i)
+    if (pthread_create (&th[i], &a, tf, cbs[i]) != 0)
+      {
+	puts ("pthread_create failed");
+	exit (1);
+      }
+
+  if (pthread_attr_destroy (&a) != 0)
+    {
+      puts ("attr_destroy failed");
+      exit (1);
+    }
+
+  pthread_barrier_wait (&b);
+
+  sigset_t ss;
+  sigemptyset (&ss);
+  sigaddset (&ss, THE_SIG);
+  if (pthread_sigmask (SIG_BLOCK, &ss, NULL) != 0)
+    {
+      puts ("pthread_sigmask failed");
+      exit (1);
+    }
+
+  /* Start sending signals.  */
+  for (i = 0; i < TOTAL_SIGS; ++i)
+    {
+      if (kill (getpid (), THE_SIG) != 0)
+	{
+	  puts ("kill failed");
+	  exit (1);
+	}
+
+      if (TEMP_FAILURE_RETRY (sem_wait (&s)) != 0)
+	{
+	  puts ("sem_wait failed");
+	  exit (1);
+	}
+
+      ++nsigs;
+    }
+
+  pthread_barrier_wait (&b);
+
+  for (i = 0; i < N; ++i)
+    if (pthread_join (th[i], NULL) != 0)
+      {
+	puts ("join failed");
+	exit (1);
+      }
+
+  return 0;
+#endif
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-tls3.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-tls3.c
new file mode 100644
index 00000000..abc5f4cb
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-tls3.c
@@ -0,0 +1,225 @@
+/* Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define THE_SIG SIGUSR1
+
+
+#define N 10
+static pthread_t th[N];
+
+
+#define CB(n) \
+static void								      \
+cb##n (void)								      \
+{									      \
+  if (th[n] != pthread_self ())						      \
+    {									      \
+      write (STDOUT_FILENO, "wrong callback\n", 15);			      \
+      _exit (1);							      \
+    }									      \
+}
+CB (0)
+CB (1)
+CB (2)
+CB (3)
+CB (4)
+CB (5)
+CB (6)
+CB (7)
+CB (8)
+CB (9)
+static void (*cbs[]) (void) =
+{
+  cb0, cb1, cb2, cb3, cb4, cb5, cb6, cb7, cb8, cb9
+};
+
+
+sem_t s;
+
+
+pthread_barrier_t b;
+
+#define TOTAL_SIGS 1000
+int nsigs;
+
+
+int
+do_test (void)
+{
+#if !HAVE___THREAD
+
+  puts ("No __thread support in compiler, test skipped.");
+
+  return 0;
+#else
+
+  if ((uintptr_t) pthread_self () & (TCB_ALIGNMENT - 1))
+    {
+      puts ("initial thread's struct pthread not aligned enough");
+      exit (1);
+    }
+
+  if (pthread_barrier_init (&b, NULL, N + 1) != 0)
+    {
+      puts ("barrier_init failed");
+      exit (1);
+    }
+
+  if (sem_init (&s, 0, 0) != 0)
+    {
+      puts ("sem_init failed");
+      exit (1);
+    }
+
+  void *h = dlopen ("tst-tls3mod.so", RTLD_LAZY);
+  if (h == NULL)
+    {
+      puts ("dlopen failed");
+      exit (1);
+    }
+
+  void *(*tf) (void *) = dlsym (h, "tf");
+  if (tf == NULL)
+    {
+      puts ("dlsym for tf failed");
+      exit (1);
+    }
+
+  void (*setup_tf) (pthread_barrier_t*, int*, sem_t*) = dlsym(h, "setup_tf");
+  if (setup_tf == NULL)
+    {
+      puts ("dlsym for setup_tf failed");
+      exit(1);
+    }
+
+  setup_tf (&b, &nsigs, &s);
+
+  struct sigaction sa;
+  sa.sa_handler = dlsym (h, "handler");
+  if (sa.sa_handler == NULL)
+    {
+      puts ("dlsym for handler failed");
+      exit (1);
+    }
+  sigemptyset (&sa.sa_mask);
+  sa.sa_flags = 0;
+  if (sigaction (THE_SIG, &sa, NULL) != 0)
+    {
+      puts ("sigaction failed");
+      exit (1);
+    }
+
+  pthread_attr_t a;
+
+  if (pthread_attr_init (&a) != 0)
+    {
+      puts ("attr_init failed");
+      exit (1);
+    }
+
+  if (pthread_attr_setstacksize (&a, 1 * 1024 * 1024) != 0)
+    {
+      puts ("attr_setstacksize failed");
+      return 1;
+    }
+
+  int r;
+  for (r = 0; r < 10; ++r)
+    {
+      int i;
+      for (i = 0; i < N; ++i)
+	if (pthread_create (&th[i], &a, tf, cbs[i]) != 0)
+	  {
+	    puts ("pthread_create failed");
+	    exit (1);
+	  }
+
+      nsigs = 0;
+
+      pthread_barrier_wait (&b);
+
+      sigset_t ss;
+      sigemptyset (&ss);
+      sigaddset (&ss, THE_SIG);
+      if (pthread_sigmask (SIG_BLOCK, &ss, NULL) != 0)
+	{
+	  puts ("pthread_sigmask failed");
+	  exit (1);
+	}
+
+      /* Start sending signals.  */
+      for (i = 0; i < TOTAL_SIGS; ++i)
+	{
+	  if (kill (getpid (), THE_SIG) != 0)
+	    {
+	      puts ("kill failed");
+	      exit (1);
+	    }
+
+	  if (TEMP_FAILURE_RETRY (sem_wait (&s)) != 0)
+	    {
+	      puts ("sem_wait failed");
+	      exit (1);
+	    }
+
+	  ++nsigs;
+	}
+
+      pthread_barrier_wait (&b);
+
+      if (pthread_sigmask (SIG_UNBLOCK, &ss, NULL) != 0)
+	{
+	  puts ("pthread_sigmask failed");
+	  exit (1);
+	}
+
+      for (i = 0; i < N; ++i)
+	if (pthread_join (th[i], NULL) != 0)
+	  {
+	    puts ("join failed");
+	    exit (1);
+	  }
+    }
+
+  if (pthread_attr_destroy (&a) != 0)
+    {
+      puts ("attr_destroy failed");
+      exit (1);
+    }
+
+  return 0;
+#endif
+}
+
+
+#define TIMEOUT 5
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-tls3mod.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-tls3mod.c
new file mode 100644
index 00000000..53206d30
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-tls3mod.c
@@ -0,0 +1,106 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#if HAVE___THREAD
+
+static pthread_barrier_t* b = NULL;
+
+#define TOTAL_SIGS 1000
+static int* nsigs = NULL;
+
+static sem_t* s = NULL;
+
+static __thread void (*fp) (void);
+
+
+#define THE_SIG SIGUSR1
+void
+handler (int sig)
+{
+  if (sig != THE_SIG)
+    {
+      write (STDOUT_FILENO, "wrong signal\n", 13);
+      _exit (1);
+    }
+
+  fp ();
+
+  if (sem_post (s) != 0)
+    {
+      write (STDOUT_FILENO, "sem_post failed\n", 16);
+      _exit (1);
+    }
+}
+
+void
+setup_tf (pthread_barrier_t* t_b, int* t_nsigs, sem_t* t_s)
+{
+  b = t_b;
+  nsigs = t_nsigs;
+  s = t_s;
+}
+
+void *
+tf (void *arg)
+{
+  if (!b || !s || !nsigs)
+    {
+      puts ("need to call setup_tf first");
+      exit (1);
+    }
+
+  if ((uintptr_t) pthread_self () & (TCB_ALIGNMENT - 1))
+    {
+      puts ("thread's struct pthread not aligned enough");
+      exit (1);
+    }
+
+  if (fp != NULL)
+    {
+      printf("fp=%p\n", (void *)&fp);
+      puts ("fp not initially NULL");
+      exit (1);
+    }
+
+  fp = arg;
+
+  pthread_barrier_wait (b);
+
+  pthread_barrier_wait (b);
+
+  if (*nsigs != TOTAL_SIGS)
+    {
+      puts ("barrier_wait prematurely returns");
+      exit (1);
+    }
+
+  return NULL;
+}
+
+#endif
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-tls4.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-tls4.c
new file mode 100644
index 00000000..52775dee
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-tls4.c
@@ -0,0 +1,191 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek , 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#if HAVE___THREAD && defined HAVE_TLS_MODEL_ATTRIBUTE
+
+#define N 3
+
+void (*test1) (void), (*test2) (void);
+
+pthread_barrier_t b2, b3;
+
+static void *
+tf (void *arg)
+{
+  int i;
+
+  for (i = 0; i <= (uintptr_t) arg; ++i)
+    {
+      int r = pthread_barrier_wait (&b3);
+      if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+	{
+	  puts ("tf: barrier_wait failed");
+	  exit (1);
+	}
+    }
+
+  test1 ();
+
+  for (i = 0; i < 3; ++i)
+    {
+      int r = pthread_barrier_wait (&b3);
+      if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+	{
+	  puts ("tf: barrier_wait failed");
+	  exit (1);
+	}
+    }
+
+  test2 ();
+
+  for (i = 0; i < 3 - (uintptr_t) arg; ++i)
+    {
+      int r = pthread_barrier_wait (&b3);
+      if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+	{
+	  puts ("tf: barrier_wait failed");
+	  exit (1);
+	}
+    }
+
+  return NULL;
+}
+
+static void *
+tf2 (void *arg)
+{
+  int r = pthread_barrier_wait (&b2);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("tf2: barrier_wait failed");
+      exit (1);
+    }
+
+  int i;
+  for (i = 0; i < N; ++i)
+    tf (arg);
+  return NULL;
+}
+
+int
+do_test (void)
+{
+  pthread_t th[2];
+  const char *modules[N]
+    = { "tst-tls4moda.so", "tst-tls4moda.so", "tst-tls4modb.so" };
+
+  if (pthread_barrier_init (&b2, NULL, 2) != 0)
+    {
+      puts ("barrier_init failed");
+      return 1;
+    }
+
+  if (pthread_barrier_init (&b3, NULL, 3) != 0)
+    {
+      puts ("barrier_init failed");
+      return 1;
+    }
+
+  if (pthread_create (&th[0], NULL, tf2, (void *) (uintptr_t) 1))
+    {
+      puts ("pthread_create failed");
+      return 1;
+    }
+
+  int r = pthread_barrier_wait (&b2);
+  if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD)
+    {
+      puts ("barrier_wait failed");
+      return 1;
+    }
+
+  int i;
+  for (i = 0; i < N; ++i)
+    {
+      void *h = dlopen (modules[i], RTLD_LAZY);
+      if (h == NULL)
+	{
+	  printf ("dlopen failed %s\n", dlerror ());
+	  return 1;
+	}
+
+      test1 = dlsym (h, "test1");
+      if (test1 == NULL)
+	{
+	  printf ("dlsym for test1 failed %s\n", dlerror ());
+	  return 1;
+	}
+
+      test2 = dlsym (h, "test2");
+      if (test2 == NULL)
+	{
+	  printf ("dlsym for test2 failed %s\n", dlerror ());
+	  return 1;
+	}
+
+      if (pthread_create (&th[1], NULL, tf, (void *) (uintptr_t) 2))
+	{
+	  puts ("pthread_create failed");
+	  return 1;
+	}
+
+      tf ((void *) (uintptr_t) 0);
+
+      if (pthread_join (th[1], NULL) != 0)
+	{
+	  puts ("join failed");
+	  return 1;
+	}
+
+      if (dlclose (h))
+	{
+	  puts ("dlclose failed");
+	  return 1;
+	}
+
+      printf ("test %d with %s succeeded\n", i, modules[i]);
+    }
+
+  if (pthread_join (th[0], NULL) != 0)
+    {
+      puts ("join failed");
+      return 1;
+    }
+
+  return 0;
+}
+
+#define TIMEOUT 5
+#define TEST_FUNCTION do_test ()
+
+#else
+
+#define TEST_FUNCTION 0
+
+#endif
+
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-tls4moda.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-tls4moda.c
new file mode 100644
index 00000000..ff7ee560
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-tls4moda.c
@@ -0,0 +1,56 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek , 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+
+#if HAVE___THREAD && defined HAVE_TLS_MODEL_ATTRIBUTE
+
+static __thread unsigned char foo [32]
+  __attribute__ ((tls_model ("initial-exec"), aligned (sizeof (void *))));
+
+void
+test1 (void)
+{
+  size_t s;
+
+  for (s = 0; s < sizeof (foo); ++s)
+    {
+      if (foo [s])
+        abort ();
+      foo [s] = s;
+    }
+}
+
+void
+test2 (void)
+{
+  size_t s;
+
+  for (s = 0; s < sizeof (foo); ++s)
+    {
+      if (foo [s] != s)
+        abort ();
+      foo [s] = sizeof (foo) - s;
+    }
+}
+
+#endif
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-tls4modb.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-tls4modb.c
new file mode 100644
index 00000000..99f3b540
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-tls4modb.c
@@ -0,0 +1,65 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek , 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+
+#if HAVE___THREAD && defined HAVE_TLS_MODEL_ATTRIBUTE
+
+static int i;
+int bar;
+
+static __thread void *foo [32 / sizeof (void *)]
+  __attribute__ ((tls_model ("initial-exec"), aligned (sizeof (void *))))
+  = { &i, &bar };
+
+void
+test1 (void)
+{
+  size_t s;
+
+  if (foo [0] != &i || foo [1] != &bar)
+    abort ();
+
+  foo [0] = NULL;
+  foo [1] = NULL;
+  for (s = 0; s < sizeof (foo) / sizeof (void *); ++s)
+    {
+      if (foo [s])
+        abort ();
+      foo [s] = &foo[s];
+    }
+}
+
+void
+test2 (void)
+{
+  size_t s;
+
+  for (s = 0; s < sizeof (foo) / sizeof (void *); ++s)
+    {
+      if (foo [s] != &foo [s])
+        abort ();
+      foo [s] = &foo [s ^ 1];
+    }
+}
+
+#endif
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-tls5.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-tls5.c
new file mode 100644
index 00000000..476f09aa
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-tls5.c
@@ -0,0 +1,119 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Jakub Jelinek , 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+/* Check alignment, overlapping and layout of TLS variables.  */
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "tst-tls5.h"
+
+#ifdef TLS_REGISTER
+
+struct tls_obj tls_registry[64];
+
+static int
+tls_addr_cmp (const void *a, const void *b)
+{
+  if (((struct tls_obj *)a)->addr < ((struct tls_obj *)b)->addr)
+    return -1;
+  if (((struct tls_obj *)a)->addr > ((struct tls_obj *)b)->addr)
+    return 1;
+  return 0;
+}
+
+static int
+do_test (void)
+{
+  size_t cnt, i;
+  int res = 0;
+  uintptr_t min_addr = ~(uintptr_t) 0, max_addr = 0;
+
+  for (cnt = 0; tls_registry[cnt].name; ++cnt);
+  tls_registry[cnt].name = NULL;
+  tls_registry[cnt].addr = (uintptr_t) pthread_self ();
+  tls_registry[cnt].size = sizeof (struct pthread);
+  tls_registry[cnt++].align = __alignof__ (struct pthread);
+
+  qsort (tls_registry, cnt, sizeof (struct tls_obj), tls_addr_cmp);
+
+  for (i = 0; i < cnt; ++i)
+    {
+      printf ("%s%s = %p, size %zd, align %zd",
+	      tls_registry[i].name ? "&" : "",
+	      tls_registry[i].name ?: "pthread_self ()",
+	      (void *) tls_registry[i].addr,
+	      tls_registry[i].size, tls_registry[i].align);
+      if (tls_registry[i].addr & (tls_registry[i].align - 1))
+	{
+	  fputs (", WRONG ALIGNMENT", stdout);
+	  res = 1;
+	}
+      if (i > 0
+	  && (tls_registry[i - 1].addr + tls_registry[i - 1].size
+	      > tls_registry[i].addr))
+	{
+	  fputs (", ADDRESS OVERLAP", stdout);
+	  res = 1;
+	}
+      puts ("");
+      if (tls_registry[i].name)
+	{
+	  min_addr = MIN (tls_registry[i].addr, min_addr);
+	  max_addr = MAX (tls_registry[i].addr + tls_registry[i].size,
+			  max_addr);
+	}
+    }
+
+  if (cnt > 1)
+    {
+#if defined(TLS_TCB_AT_TP)
+      if (tls_registry[cnt - 1].name)
+	{
+	  puts ("pthread_self () not larger than all TLS addresses");
+	  res = 1;
+	}
+      else
+	max_addr = MAX (tls_registry[cnt - 1].addr, max_addr);
+#elif defined(TLS_DTV_AT_TP)
+      if (tls_registry[0].name)
+	{
+	  puts ("pthread_self () not smaller than all TLS addresses");
+	  res = 1;
+	}
+#else
+      abort ();
+#endif
+      printf ("Initial TLS used block size %zd\n",
+	      (size_t) (max_addr - min_addr));
+    }
+  return res;
+}
+
+#define TEST_FUNCTION do_test ()
+
+#else
+
+#define TEST_FUNCTION 0
+
+#endif
+
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-tls5.h b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-tls5.h
new file mode 100644
index 00000000..b7c14eb8
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-tls5.h
@@ -0,0 +1,28 @@
+#include 
+#include 
+#include 
+
+#if USE_TLS && HAVE___THREAD
+
+struct tls_obj
+{
+  const char *name;
+  uintptr_t addr;
+  size_t size;
+  size_t align;
+};
+extern struct tls_obj tls_registry[];
+
+#define TLS_REGISTER(x)				\
+static void __attribute__((constructor))	\
+tls_register_##x (void)				\
+{						\
+  size_t i;					\
+  for (i = 0; tls_registry[i].name; ++i);	\
+  tls_registry[i].name = #x;			\
+  tls_registry[i].addr = (uintptr_t) &x;	\
+  tls_registry[i].size = sizeof (x);		\
+  tls_registry[i].align = __alignof__ (x);	\
+}
+
+#endif
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-tls5mod.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-tls5mod.c
new file mode 100644
index 00000000..4616a20e
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-tls5mod.c
@@ -0,0 +1,6 @@
+#include "tst-tls5.h"
+
+#ifdef TLS_REGISTER
+/* Ensure tls_registry is exported from the binary.  */
+void *tst_tls5mod attribute_hidden = tls_registry;
+#endif
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-tls5moda.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-tls5moda.c
new file mode 100644
index 00000000..4644d763
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-tls5moda.c
@@ -0,0 +1,6 @@
+#include "tst-tls5.h"
+
+#ifdef TLS_REGISTER
+static __thread char a [32] __attribute__ ((aligned (64)));
+TLS_REGISTER (a)
+#endif
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-tls5modb.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-tls5modb.c
new file mode 100644
index 00000000..09b43967
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-tls5modb.c
@@ -0,0 +1,6 @@
+#include "tst-tls5.h"
+
+#ifdef TLS_REGISTER
+static __thread int b;
+TLS_REGISTER (b)
+#endif
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-tls5modc.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-tls5modc.c
new file mode 100644
index 00000000..bbd89633
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-tls5modc.c
@@ -0,0 +1,6 @@
+#include "tst-tls5.h"
+
+#ifdef TLS_REGISTER
+static __thread int c;
+TLS_REGISTER (c)
+#endif
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-tls5modd.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-tls5modd.c
new file mode 100644
index 00000000..8b54d168
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-tls5modd.c
@@ -0,0 +1,6 @@
+#include "tst-tls5.h"
+
+#ifdef TLS_REGISTER
+static __thread int d;
+TLS_REGISTER (d)
+#endif
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-tls5mode.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-tls5mode.c
new file mode 100644
index 00000000..d30b0675
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-tls5mode.c
@@ -0,0 +1,8 @@
+#include "tst-tls5.h"
+
+#ifdef TLS_REGISTER
+static __thread int e1 = 24;
+static __thread char e2 [32] __attribute__ ((aligned (64)));
+TLS_REGISTER (e1)
+TLS_REGISTER (e2)
+#endif
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-tls5modf.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-tls5modf.c
new file mode 100644
index 00000000..52dcb949
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-tls5modf.c
@@ -0,0 +1,9 @@
+#include "tst-tls5.h"
+
+#ifdef TLS_REGISTER
+char tst_tls5modf[60] attribute_hidden = { 26 };
+static __thread int f1 = 24;
+static __thread char f2 [32] __attribute__ ((aligned (64)));
+TLS_REGISTER (f1)
+TLS_REGISTER (f2)
+#endif
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-tsd1.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-tsd1.c
new file mode 100644
index 00000000..51b2d0cb
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-tsd1.c
@@ -0,0 +1,118 @@
+/* Copyright (C) 2002 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2002.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+
+
+static int
+do_test (void)
+{
+  pthread_key_t key1;
+  pthread_key_t key2;
+  void *value;
+  int result = 0;
+  int err;
+
+  err = pthread_key_create (&key1, NULL);
+  if (err != 0)
+    {
+      printf ("1st key_create failed: %s\n", strerror (err));
+      return 1;
+    }
+
+  /* Initial value must be NULL.  */
+  value = pthread_getspecific (key1);
+  if (value != NULL)
+    {
+      puts ("1st getspecific != NULL");
+      result = 1;
+    }
+
+  err = pthread_setspecific (key1, (void *) -2l);
+  if (err != 0)
+    {
+      printf ("1st setspecific failed: %s\n", strerror (err));
+      return 1;
+    }
+
+  value = pthread_getspecific (key1);
+  if (value == NULL)
+    {
+      puts ("2nd getspecific == NULL\n");
+      result = 1;
+    }
+  else if (value != (void *) -2l)
+    {
+      puts ("2nd getspecific != -2l\n");
+      result = 1;
+    }
+
+  err = pthread_setspecific (key1, (void *) -3l);
+  if (err != 0)
+    {
+      printf ("2nd setspecific failed: %s\n", strerror (err));
+      return 1;
+    }
+
+  value = pthread_getspecific (key1);
+  if (value == NULL)
+    {
+      puts ("3rd getspecific == NULL\n");
+      result = 1;
+    }
+  else if (value != (void *) -3l)
+    {
+      puts ("3rd getspecific != -2l\n");
+      result = 1;
+    }
+
+  err = pthread_key_delete (key1);
+  if (err != 0)
+    {
+      printf ("key_delete failed: %s\n", strerror (err));
+      result = 1;
+    }
+
+
+  err = pthread_key_create (&key2, NULL);
+  if (err != 0)
+    {
+      printf ("2nd key_create failed: %s\n", strerror (err));
+      return 1;
+    }
+
+  if (key1 != key2)
+    puts ("key1 != key2; no more tests performed");
+  else
+    {
+      value = pthread_getspecific (key2);
+      if (value != NULL)
+	{
+	  puts ("4th getspecific != NULL");
+	  result = 1;
+	}
+    }
+
+  return result;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-tsd2.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-tsd2.c
new file mode 100644
index 00000000..19d8a69f
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-tsd2.c
@@ -0,0 +1,97 @@
+/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2002.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+
+
+static int result;
+
+
+static void
+destr (void *arg)
+{
+  if (arg != (void *) -2l)
+    result = 2;
+  else
+    result = 0;
+}
+
+
+static void *
+tf (void *arg)
+{
+  pthread_key_t key = (pthread_key_t) (long int) arg;
+  int err;
+
+  err = pthread_setspecific (key, (void *) -2l);
+  if (err != 0)
+    result = 3;
+
+  return NULL;
+}
+
+
+static int
+do_test (void)
+{
+  pthread_key_t key;
+  pthread_t th;
+  int err;
+
+  err = pthread_key_create (&key, destr);
+  if (err != 0)
+    {
+      printf ("key_create failed: %s\n", strerror (err));
+      return 1;
+    }
+
+  result = 1;
+
+  err = pthread_create (&th, NULL, tf, (void *) (long int) key);
+  if (err != 0)
+    {
+      printf ("create failed: %s\n", strerror (err));
+      return 1;
+    }
+
+  /* Wait for the thread to terminate.  */
+  err = pthread_join (th, NULL);
+  if (err != 0)
+    {
+      printf ("join failed: %s\n", strerror (err));
+      return 1;
+    }
+
+  if (result == 1)
+    puts ("destructor not called");
+  else if (result == 2)
+    puts ("destructor got passed a wrong value");
+  else if (result == 3)
+    puts ("setspecific in child failed");
+  else if (result != 0)
+    puts ("result != 0");
+
+  return result;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-tsd3.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-tsd3.c
new file mode 100644
index 00000000..6cdf7499
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-tsd3.c
@@ -0,0 +1,129 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+static pthread_key_t key1;
+static pthread_key_t key2;
+
+
+static int left;
+
+
+static void
+destr1 (void *arg)
+{
+  if (--left > 0)
+    {
+      puts ("set key2");
+
+      if (pthread_setspecific (key2, (void *) 1l) != 0)
+	{
+	  puts ("destr1: setspecific failed");
+	  exit (1);
+	}
+    }
+}
+
+
+static void
+destr2 (void *arg)
+{
+  if (--left > 0)
+    {
+      puts ("set key1");
+
+      if (pthread_setspecific (key1, (void *) 1l) != 0)
+	{
+	  puts ("destr2: setspecific failed");
+	  exit (1);
+	}
+    }
+}
+
+
+static void *
+tf (void *arg)
+{
+  /* Let the destructors work.  */
+  left = 7;
+
+  if (pthread_setspecific (key1, (void *) 1l) != 0
+      || pthread_setspecific (key2, (void *) 1l) != 0)
+    {
+      puts ("tf: setspecific failed");
+      exit (1);
+    }
+
+  return NULL;
+}
+
+
+static int
+do_test (void)
+{
+  /* Allocate two keys, both with destructors.  */
+  if (pthread_key_create (&key1, destr1) != 0
+      || pthread_key_create (&key2, destr2) != 0)
+    {
+      puts ("key_create failed");
+      return 1;
+    }
+
+  pthread_t th;
+  if (pthread_create (&th, NULL, tf, NULL) != 0)
+    {
+      puts ("create failed");
+      return 1;
+    }
+
+  if (pthread_join (th, NULL) != 0)
+    {
+      puts ("join failed");
+      return 1;
+    }
+
+  if (left != 0)
+    {
+      printf ("left == %d\n", left);
+      return 1;
+    }
+
+  if (pthread_getspecific (key1) != NULL)
+    {
+      puts ("key1 data != NULL");
+      return 1;
+    }
+  if (pthread_getspecific (key2) != NULL)
+    {
+      puts ("key2 data != NULL");
+      return 1;
+    }
+
+  return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-tsd4.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-tsd4.c
new file mode 100644
index 00000000..44bbadb4
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-tsd4.c
@@ -0,0 +1,103 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+static pthread_key_t key;
+
+
+static int rounds;
+
+
+static void
+destr (void *arg)
+{
+  ++rounds;
+
+  if (pthread_setspecific (key, (void *) 1l) != 0)
+    {
+      puts ("destr: setspecific failed");
+      exit (1);
+    }
+}
+
+
+static void *
+tf (void *arg)
+{
+  if (pthread_setspecific (key, (void *) 1l) != 0)
+    {
+      puts ("tf: setspecific failed");
+      exit (1);
+    }
+
+  return NULL;
+}
+
+
+/* This test check non-standard behavior.  The standard does not
+   require that the implementation has to stop calling TSD destructors
+   when they are set over and over again.  But NPTL does.  */
+static int
+do_test (void)
+{
+  /* Allocate two keys, both with destructors.  */
+  if (pthread_key_create (&key, destr) != 0)
+    {
+      puts ("key_create failed");
+      return 1;
+    }
+
+  pthread_t th;
+  if (pthread_create (&th, NULL, tf, NULL) != 0)
+    {
+      puts ("create failed");
+      return 1;
+    }
+
+  if (pthread_join (th, NULL) != 0)
+    {
+      puts ("join failed");
+      return 1;
+    }
+
+  if (rounds < PTHREAD_DESTRUCTOR_ITERATIONS)
+    {
+      printf ("rounds == %d, PTHREAD_DESTRUCTOR_ITERATIONS = %d\n",
+	      rounds, PTHREAD_DESTRUCTOR_ITERATIONS);
+      return 1;
+    }
+
+  if (pthread_getspecific (key) != NULL)
+    {
+      puts ("key data != NULL");
+      return 1;
+    }
+
+  return 0;
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-tsd5.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-tsd5.c
new file mode 100644
index 00000000..8793e339
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-tsd5.c
@@ -0,0 +1,81 @@
+/* Copyright (C) 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2004.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+
+
+static pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
+
+
+static void
+cl (void *p)
+{
+  pthread_mutex_unlock (&m);
+}
+
+
+static void *
+tf (void *arg)
+{
+  if (pthread_mutex_lock (&m) != 0)
+    {
+      puts ("2nd mutex_lock failed");
+      exit (1);
+    }
+
+  exit (0);
+}
+
+
+static int
+do_test (void)
+{
+  pthread_key_t k;
+  if (pthread_key_create (&k, cl) != 0)
+    {
+      puts ("key_create failed");
+      return 1;
+    }
+  if (pthread_setspecific (k, (void *) 1) != 0)
+    {
+      puts ("setspecific failed");
+      return 1;
+    }
+
+  if (pthread_mutex_lock (&m) != 0)
+    {
+      puts ("1st mutex_lock failed");
+      return 1;
+    }
+
+  pthread_t th;
+  if (pthread_create (&th, NULL, tf, NULL) != 0)
+    {
+      puts ("create failed");
+      return 1;
+    }
+
+  pthread_exit (NULL);
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-tsd6.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-tsd6.c
new file mode 100644
index 00000000..debb1dd3
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-tsd6.c
@@ -0,0 +1,89 @@
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define NKEYS 100
+static pthread_key_t keys[NKEYS];
+static pthread_barrier_t b;
+
+
+static void *
+tf (void *arg)
+{
+  void *res = NULL;
+  for (int i = 0; i < NKEYS; ++i)
+    {
+      void *p = pthread_getspecific (keys[i]);
+      pthread_setspecific (keys[i], (void *) 7);
+      if (p != NULL)
+	res = p;
+    }
+  if (arg != NULL)
+    {
+      pthread_barrier_wait (arg);
+      pthread_barrier_wait (arg);
+    }
+  return res;
+}
+
+
+static int
+do_test (void)
+{
+  pthread_barrier_init (&b, NULL, 2);
+
+  for (int i = 0; i < NKEYS; ++i)
+    if (pthread_key_create (&keys[i], NULL) != 0)
+      {
+	puts ("cannot create keys");
+	return 1;
+      }
+
+  pthread_t th;
+  if (pthread_create (&th, NULL, tf, &b) != 0)
+    {
+      puts ("cannot create thread in parent");
+      return 1;
+    }
+
+  pthread_barrier_wait (&b);
+
+  pid_t pid = fork ();
+  if (pid == 0)
+    {
+      if (pthread_create (&th, NULL, tf, NULL) != 0)
+	{
+	  puts ("cannot create thread in child");
+	  exit (1);
+	}
+
+      void *res;
+      pthread_join (th, &res);
+
+      exit (res != NULL);
+    }
+  else if (pid == -1)
+    {
+      puts ("cannot create child process");
+      return 1;
+    }
+
+  int s;
+  if (TEMP_FAILURE_RETRY (waitpid (pid, &s, 0)) != pid)
+    {
+      puts ("failing to wait for child process");
+      return 1;
+    }
+
+  pthread_barrier_wait (&b);
+  pthread_join (th, NULL);
+
+  return !WIFEXITED (s) ? 2 : WEXITSTATUS (s);
+}
+
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-typesizes.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-typesizes.c
new file mode 100644
index 00000000..545cee6b
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-typesizes.c
@@ -0,0 +1,96 @@
+/* Copyright (C) 2005, 2007, 2008 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2005.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+
+static const struct
+{
+  const char *name;
+  size_t expected;
+  size_t is;
+} types[] =
+  {
+#define T(t, c) \
+    { #t, c, sizeof (t) }
+    T (pthread_attr_t, __SIZEOF_PTHREAD_ATTR_T),
+    T (pthread_mutex_t, __SIZEOF_PTHREAD_MUTEX_T),
+    T (pthread_mutexattr_t, __SIZEOF_PTHREAD_MUTEXATTR_T),
+    T (pthread_cond_t, __SIZEOF_PTHREAD_COND_T),
+    T (pthread_condattr_t, __SIZEOF_PTHREAD_CONDATTR_T),
+    T (pthread_rwlock_t, __SIZEOF_PTHREAD_RWLOCK_T),
+    T (pthread_rwlockattr_t, __SIZEOF_PTHREAD_RWLOCKATTR_T),
+    T (pthread_barrier_t, __SIZEOF_PTHREAD_BARRIER_T),
+    T (pthread_barrierattr_t, __SIZEOF_PTHREAD_BARRIERATTR_T)
+  };
+
+static int
+do_test (void)
+{
+  int result = 0;
+
+#define TEST_TYPE(name) \
+  printf ("%s: ", #name);						      \
+  if (sizeof (name) != sizeof (((name *) 0)->__size))			      \
+    {									      \
+      printf ("expected %zu, is %zu\n",					      \
+	      sizeof (((name *) 0)->__size), sizeof (name));		      \
+      result = 1;							      \
+    }									      \
+  else									      \
+    puts ("OK")
+
+  TEST_TYPE (pthread_mutex_t);
+  TEST_TYPE (pthread_cond_t);
+  TEST_TYPE (pthread_rwlock_t);
+
+#define TEST_TYPE2(name, internal)					      \
+  printf ("%s: ", #name);						      \
+  if (sizeof (((name *) 0)->__size) < sizeof (internal))		      \
+    {									      \
+      printf ("expected %zu, is %zu\n",					      \
+	      sizeof (((name *) 0)->__size), sizeof (internal));	      \
+      result = 1;							      \
+    }									      \
+  else									      \
+    puts ("OK")
+
+  TEST_TYPE2 (pthread_attr_t, struct pthread_attr);
+  TEST_TYPE2 (pthread_mutexattr_t, struct pthread_mutexattr);
+  TEST_TYPE2 (pthread_condattr_t, struct pthread_condattr);
+  TEST_TYPE2 (pthread_rwlockattr_t, struct pthread_rwlockattr);
+  TEST_TYPE2 (pthread_barrier_t, struct pthread_barrier);
+  TEST_TYPE2 (pthread_barrierattr_t, struct pthread_barrierattr);
+  TEST_TYPE2 (sem_t, struct new_sem);
+  TEST_TYPE2 (sem_t, struct old_sem);
+
+  for (size_t i = 0; i < sizeof (types) / sizeof (types[0]); ++i)
+    if (types[i].expected != types[i].is)
+      {
+	printf ("%s: expected %zu, is %zu\n",
+		types[i].name, types[i].expected, types[i].is);
+	result = 1;
+      }
+
+  return result;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-umask1.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-umask1.c
new file mode 100644
index 00000000..4bbf6d0d
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-umask1.c
@@ -0,0 +1,137 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2003.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+
+static struct
+{
+  int (*fp) (const char *, mode_t);
+  const char *name;
+  bool is_fd;
+} fcts[] =
+{
+  { creat, "creat", true },
+  { mkdir, "mkdir", false },
+  { mkfifo, "mkfifo", false },
+};
+#define nfcts (sizeof (fcts) / sizeof (fcts[0]))
+
+
+static int
+work (const char *fname, int mask)
+{
+  int result = 0;
+  size_t i;
+  for (i = 0; i < nfcts; ++i)
+    {
+      remove (fname);
+      int fd = fcts[i].fp (fname, 0777);
+      if (fd == -1)
+	{
+	  printf ("cannot %s %s: %m\n", fcts[i].name, fname);
+	  exit (1);
+	}
+      if (fcts[i].is_fd)
+	close (fd);
+      struct stat st;
+      if (stat (fname, &st) == -1)
+	{
+	  printf ("cannot stat %s after %s: %m\n", fname, fcts[i].name);
+	  exit (1);
+	}
+
+      if ((st.st_mode & mask) != 0)
+	{
+	  printf ("mask not successful after %s: %x still set\n",
+	      fcts[i].name, (unsigned int) (st.st_mode & mask));
+	  result = 1;
+	}
+    }
+
+  return result;
+}
+
+
+static pthread_barrier_t bar;
+
+
+static void *
+tf (void *arg)
+{
+  pthread_barrier_wait (&bar);
+
+  int result = work (arg, 022);
+
+  pthread_barrier_wait (&bar);
+
+  pthread_barrier_wait (&bar);
+
+  return (work (arg, 0) | result) ? (void *) -1l : NULL;
+}
+
+
+static int
+do_test (const char *fname)
+{
+  int result = 0;
+
+  umask (0);
+  result |= work (fname, 0);
+
+  pthread_barrier_init (&bar, NULL, 2);
+
+  pthread_t th;
+  if (pthread_create (&th, NULL, tf, (void *) fname) != 0)
+    {
+      puts ("cannot create thread");
+      exit (1);
+    }
+
+  umask (022);
+  result |= work (fname, 022);
+
+  pthread_barrier_wait (&bar);
+
+  pthread_barrier_wait (&bar);
+
+  umask (0);
+
+  pthread_barrier_wait (&bar);
+
+  void *res;
+  if (pthread_join (th, &res) != 0)
+    {
+      puts ("join failed");
+      exit (1);
+    }
+
+  remove (fname);
+
+  return result || res != NULL;
+}
+
+#define TEST_FUNCTION do_test (argc < 2 ? "/tmp/tst-umask.tmp" : argv[1])
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-unload.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-unload.c
new file mode 100644
index 00000000..5c552e22
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-unload.c
@@ -0,0 +1,47 @@
+/* Tests for non-unloading of libpthread.
+   Copyright (C) 2000, 2002, 2003, 2004 Free Software Foundation, Inc.
+   Contributed by Ulrich Drepper , 2000.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public License as
+   published by the Free Software Foundation; either version 2.1 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include 
+#include 
+#include 
+
+static int
+do_test (void)
+{
+  void *p = dlopen ("libpthread.so.0", RTLD_LAZY);
+
+  if (p == NULL)
+    {
+      puts ("failed to load libpthread.so.0");
+      return 1;
+    }
+
+  if (dlclose (p) != 0)
+    {
+      puts ("dlclose (libpthread.so.0) failed");
+      return 1;
+    }
+
+  puts ("seems to work");
+
+  return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-vfork1.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-vfork1.c
new file mode 100644
index 00000000..1f36f1ff
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-vfork1.c
@@ -0,0 +1,150 @@
+/* Test for vfork functions.
+   Copyright (C) 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2004.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/* This test relies on non-POSIX functionality since the child
+   processes call write and getpid.  */
+static int
+do_test (void)
+{
+  int result = 0;
+  int fd[2];
+
+  if (pipe (fd) == -1)
+    {
+      puts ("pipe failed");
+      return 1;
+    }
+
+  /* First vfork() without previous getpid().  */
+  pid_t p1;
+  if ((p1 = vfork ()) == 0)
+    {
+      pid_t p = getpid ();
+      _exit (TEMP_FAILURE_RETRY (write (fd[1], &p, sizeof (p))) != sizeof (p));
+    }
+  else if (p1 == -1)
+    {
+      puts ("1st vfork failed");
+      result = 1;
+    }
+
+  pid_t p2 = 0;
+  if (TEMP_FAILURE_RETRY (read (fd[0], &p2, sizeof (pid_t))) != sizeof (pid_t))
+    {
+      puts ("1st read failed");
+      result = 1;
+    }
+  int r;
+  if (TEMP_FAILURE_RETRY (waitpid (p1, &r, 0)) != p1)
+    {
+      puts ("1st waitpid failed");
+      result = 1;
+    }
+  else if (r != 0)
+    {
+      puts ("write in 1st child failed");
+      result = 1;
+    }
+
+  /* Main process' ID.  */
+  pid_t p0 = getpid ();
+
+  /* vfork() again, but after a getpid() in the main process.  */
+  pid_t p3;
+  if ((p3 = vfork ()) == 0)
+    {
+      pid_t p = getpid ();
+      _exit (TEMP_FAILURE_RETRY (write (fd[1], &p, sizeof (p))) != sizeof (p));
+    }
+  else if (p1 == -1)
+    {
+      puts ("2nd vfork failed");
+      result = 1;
+    }
+
+  pid_t p4;
+  if (TEMP_FAILURE_RETRY (read (fd[0], &p4, sizeof (pid_t))) != sizeof (pid_t))
+    {
+      puts ("2nd read failed");
+      result = 1;
+    }
+  if (TEMP_FAILURE_RETRY (waitpid (p3, &r, 0)) != p3)
+    {
+      puts ("2nd waitpid failed");
+      result = 1;
+    }
+  else if (r != 0)
+    {
+      puts ("write in 2nd child failed");
+      result = 1;
+    }
+
+  /* And getpid in the main process again.  */
+  pid_t p5 = getpid ();
+
+  /* Analysis of the results.  */
+  if (p0 != p5)
+    {
+      printf ("p0(%ld) != p5(%ld)\n", (long int) p0, (long int) p5);
+      result = 1;
+    }
+
+  if (p0 == p1)
+    {
+      printf ("p0(%ld) == p1(%ld)\n", (long int) p0, (long int) p1);
+      result = 1;
+    }
+
+  if (p1 != p2)
+    {
+      printf ("p1(%ld) != p2(%ld)\n", (long int) p1, (long int) p2);
+      result = 1;
+    }
+
+  if (p0 == p3)
+    {
+      printf ("p0(%ld) == p3(%ld)\n", (long int) p0, (long int) p3);
+      result = 1;
+    }
+
+  if (p3 != p4)
+    {
+      printf ("p3(%ld) != p4(%ld)\n", (long int) p3, (long int) p4);
+      result = 1;
+    }
+
+  close (fd[0]);
+  close (fd[1]);
+
+  if (result == 0)
+    puts ("All OK");
+
+  return result;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-vfork1x.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-vfork1x.c
new file mode 100644
index 00000000..1f36f1ff
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-vfork1x.c
@@ -0,0 +1,150 @@
+/* Test for vfork functions.
+   Copyright (C) 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2004.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/* This test relies on non-POSIX functionality since the child
+   processes call write and getpid.  */
+static int
+do_test (void)
+{
+  int result = 0;
+  int fd[2];
+
+  if (pipe (fd) == -1)
+    {
+      puts ("pipe failed");
+      return 1;
+    }
+
+  /* First vfork() without previous getpid().  */
+  pid_t p1;
+  if ((p1 = vfork ()) == 0)
+    {
+      pid_t p = getpid ();
+      _exit (TEMP_FAILURE_RETRY (write (fd[1], &p, sizeof (p))) != sizeof (p));
+    }
+  else if (p1 == -1)
+    {
+      puts ("1st vfork failed");
+      result = 1;
+    }
+
+  pid_t p2 = 0;
+  if (TEMP_FAILURE_RETRY (read (fd[0], &p2, sizeof (pid_t))) != sizeof (pid_t))
+    {
+      puts ("1st read failed");
+      result = 1;
+    }
+  int r;
+  if (TEMP_FAILURE_RETRY (waitpid (p1, &r, 0)) != p1)
+    {
+      puts ("1st waitpid failed");
+      result = 1;
+    }
+  else if (r != 0)
+    {
+      puts ("write in 1st child failed");
+      result = 1;
+    }
+
+  /* Main process' ID.  */
+  pid_t p0 = getpid ();
+
+  /* vfork() again, but after a getpid() in the main process.  */
+  pid_t p3;
+  if ((p3 = vfork ()) == 0)
+    {
+      pid_t p = getpid ();
+      _exit (TEMP_FAILURE_RETRY (write (fd[1], &p, sizeof (p))) != sizeof (p));
+    }
+  else if (p1 == -1)
+    {
+      puts ("2nd vfork failed");
+      result = 1;
+    }
+
+  pid_t p4;
+  if (TEMP_FAILURE_RETRY (read (fd[0], &p4, sizeof (pid_t))) != sizeof (pid_t))
+    {
+      puts ("2nd read failed");
+      result = 1;
+    }
+  if (TEMP_FAILURE_RETRY (waitpid (p3, &r, 0)) != p3)
+    {
+      puts ("2nd waitpid failed");
+      result = 1;
+    }
+  else if (r != 0)
+    {
+      puts ("write in 2nd child failed");
+      result = 1;
+    }
+
+  /* And getpid in the main process again.  */
+  pid_t p5 = getpid ();
+
+  /* Analysis of the results.  */
+  if (p0 != p5)
+    {
+      printf ("p0(%ld) != p5(%ld)\n", (long int) p0, (long int) p5);
+      result = 1;
+    }
+
+  if (p0 == p1)
+    {
+      printf ("p0(%ld) == p1(%ld)\n", (long int) p0, (long int) p1);
+      result = 1;
+    }
+
+  if (p1 != p2)
+    {
+      printf ("p1(%ld) != p2(%ld)\n", (long int) p1, (long int) p2);
+      result = 1;
+    }
+
+  if (p0 == p3)
+    {
+      printf ("p0(%ld) == p3(%ld)\n", (long int) p0, (long int) p3);
+      result = 1;
+    }
+
+  if (p3 != p4)
+    {
+      printf ("p3(%ld) != p4(%ld)\n", (long int) p3, (long int) p4);
+      result = 1;
+    }
+
+  close (fd[0]);
+  close (fd[1]);
+
+  if (result == 0)
+    puts ("All OK");
+
+  return result;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-vfork2.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-vfork2.c
new file mode 100644
index 00000000..1d096e14
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-vfork2.c
@@ -0,0 +1,199 @@
+/* Test for vfork functions.
+   Copyright (C) 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2004.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+int raise_fail;
+
+static void
+alrm (int sig)
+{
+  if (raise (SIGUSR1) < 0)
+    raise_fail = 1;
+}
+
+/* This test relies on non-POSIX functionality since the child
+   processes call write, nanosleep and getpid.  */
+static int
+do_test (void)
+{
+  int result = 0;
+  int fd[2];
+
+  signal (SIGUSR1, SIG_IGN);
+
+  struct sigaction sa;
+  sa.sa_handler = alrm;
+  sigemptyset (&sa.sa_mask);
+  sa.sa_flags = 0;
+  if (sigaction (SIGALRM, &sa, NULL) < 0)
+    {
+      puts ("couldn't set up SIGALRM handler");
+      return 1;
+    }
+
+  if (pipe (fd) == -1)
+    {
+      puts ("pipe failed");
+      return 1;
+    }
+
+  struct itimerval it;
+  it.it_value.tv_sec = 0;
+  it.it_value.tv_usec = 200 * 1000;
+  it.it_interval = it.it_value;
+  if (setitimer (ITIMER_REAL, &it, NULL) < 0)
+    {
+      puts ("couldn't set up timer");
+      return 1;
+    }
+
+  /* First vfork() without previous getpid().  */
+  pid_t p1;
+  if ((p1 = vfork ()) == 0)
+    {
+      pid_t p = getpid ();
+
+      struct timespec ts;
+      ts.tv_sec = 1;
+      ts.tv_nsec = 0;
+      TEMP_FAILURE_RETRY (nanosleep (&ts, &ts));
+      _exit (TEMP_FAILURE_RETRY (write (fd[1], &p, sizeof (p))) != sizeof (p));
+    }
+  else if (p1 == -1)
+    {
+      puts ("1st vfork failed");
+      result = 1;
+    }
+
+  memset (&it, 0, sizeof (it));
+  setitimer (ITIMER_REAL, &it, NULL);
+
+  pid_t p2 = 0;
+  if (TEMP_FAILURE_RETRY (read (fd[0], &p2, sizeof (pid_t))) != sizeof (pid_t))
+    {
+      puts ("1st read failed");
+      result = 1;
+    }
+  int r;
+  if (TEMP_FAILURE_RETRY (waitpid (p1, &r, 0)) != p1)
+    {
+      puts ("1st waitpid failed");
+      result = 1;
+    }
+  else if (r != 0)
+    {
+      puts ("write in 1st child failed");
+      result = 1;
+    }
+
+  /* Main process' ID.  */
+  pid_t p0 = getpid ();
+
+  /* vfork() again, but after a getpid() in the main process.  */
+  pid_t p3;
+  if ((p3 = vfork ()) == 0)
+    {
+      pid_t p = getpid ();
+      _exit (TEMP_FAILURE_RETRY (write (fd[1], &p, sizeof (p))) != sizeof (p));
+    }
+  else if (p1 == -1)
+    {
+      puts ("2nd vfork failed");
+      result = 1;
+    }
+
+  pid_t p4;
+  if (TEMP_FAILURE_RETRY (read (fd[0], &p4, sizeof (pid_t))) != sizeof (pid_t))
+    {
+      puts ("2nd read failed");
+      result = 1;
+    }
+  if (TEMP_FAILURE_RETRY (waitpid (p3, &r, 0)) != p3)
+    {
+      puts ("2nd waitpid failed");
+      result = 1;
+    }
+  else if (r != 0)
+    {
+      puts ("write in 2nd child failed");
+      result = 1;
+    }
+
+  /* And getpid in the main process again.  */
+  pid_t p5 = getpid ();
+
+  /* Analysis of the results.  */
+  if (p0 != p5)
+    {
+      printf ("p0(%ld) != p5(%ld)\n", (long int) p0, (long int) p5);
+      result = 1;
+    }
+
+  if (p0 == p1)
+    {
+      printf ("p0(%ld) == p1(%ld)\n", (long int) p0, (long int) p1);
+      result = 1;
+    }
+
+  if (p1 != p2)
+    {
+      printf ("p1(%ld) != p2(%ld)\n", (long int) p1, (long int) p2);
+      result = 1;
+    }
+
+  if (p0 == p3)
+    {
+      printf ("p0(%ld) == p3(%ld)\n", (long int) p0, (long int) p3);
+      result = 1;
+    }
+
+  if (p3 != p4)
+    {
+      printf ("p3(%ld) != p4(%ld)\n", (long int) p3, (long int) p4);
+      result = 1;
+    }
+
+  close (fd[0]);
+  close (fd[1]);
+
+  if (raise_fail)
+    {
+      puts ("raise failed");
+      result = 1;
+    }
+
+  if (result == 0)
+    puts ("All OK");
+
+  return result;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-vfork2x.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-vfork2x.c
new file mode 100644
index 00000000..1d096e14
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/nptl/tst-vfork2x.c
@@ -0,0 +1,199 @@
+/* Test for vfork functions.
+   Copyright (C) 2004 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper , 2004.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+int raise_fail;
+
+static void
+alrm (int sig)
+{
+  if (raise (SIGUSR1) < 0)
+    raise_fail = 1;
+}
+
+/* This test relies on non-POSIX functionality since the child
+   processes call write, nanosleep and getpid.  */
+static int
+do_test (void)
+{
+  int result = 0;
+  int fd[2];
+
+  signal (SIGUSR1, SIG_IGN);
+
+  struct sigaction sa;
+  sa.sa_handler = alrm;
+  sigemptyset (&sa.sa_mask);
+  sa.sa_flags = 0;
+  if (sigaction (SIGALRM, &sa, NULL) < 0)
+    {
+      puts ("couldn't set up SIGALRM handler");
+      return 1;
+    }
+
+  if (pipe (fd) == -1)
+    {
+      puts ("pipe failed");
+      return 1;
+    }
+
+  struct itimerval it;
+  it.it_value.tv_sec = 0;
+  it.it_value.tv_usec = 200 * 1000;
+  it.it_interval = it.it_value;
+  if (setitimer (ITIMER_REAL, &it, NULL) < 0)
+    {
+      puts ("couldn't set up timer");
+      return 1;
+    }
+
+  /* First vfork() without previous getpid().  */
+  pid_t p1;
+  if ((p1 = vfork ()) == 0)
+    {
+      pid_t p = getpid ();
+
+      struct timespec ts;
+      ts.tv_sec = 1;
+      ts.tv_nsec = 0;
+      TEMP_FAILURE_RETRY (nanosleep (&ts, &ts));
+      _exit (TEMP_FAILURE_RETRY (write (fd[1], &p, sizeof (p))) != sizeof (p));
+    }
+  else if (p1 == -1)
+    {
+      puts ("1st vfork failed");
+      result = 1;
+    }
+
+  memset (&it, 0, sizeof (it));
+  setitimer (ITIMER_REAL, &it, NULL);
+
+  pid_t p2 = 0;
+  if (TEMP_FAILURE_RETRY (read (fd[0], &p2, sizeof (pid_t))) != sizeof (pid_t))
+    {
+      puts ("1st read failed");
+      result = 1;
+    }
+  int r;
+  if (TEMP_FAILURE_RETRY (waitpid (p1, &r, 0)) != p1)
+    {
+      puts ("1st waitpid failed");
+      result = 1;
+    }
+  else if (r != 0)
+    {
+      puts ("write in 1st child failed");
+      result = 1;
+    }
+
+  /* Main process' ID.  */
+  pid_t p0 = getpid ();
+
+  /* vfork() again, but after a getpid() in the main process.  */
+  pid_t p3;
+  if ((p3 = vfork ()) == 0)
+    {
+      pid_t p = getpid ();
+      _exit (TEMP_FAILURE_RETRY (write (fd[1], &p, sizeof (p))) != sizeof (p));
+    }
+  else if (p1 == -1)
+    {
+      puts ("2nd vfork failed");
+      result = 1;
+    }
+
+  pid_t p4;
+  if (TEMP_FAILURE_RETRY (read (fd[0], &p4, sizeof (pid_t))) != sizeof (pid_t))
+    {
+      puts ("2nd read failed");
+      result = 1;
+    }
+  if (TEMP_FAILURE_RETRY (waitpid (p3, &r, 0)) != p3)
+    {
+      puts ("2nd waitpid failed");
+      result = 1;
+    }
+  else if (r != 0)
+    {
+      puts ("write in 2nd child failed");
+      result = 1;
+    }
+
+  /* And getpid in the main process again.  */
+  pid_t p5 = getpid ();
+
+  /* Analysis of the results.  */
+  if (p0 != p5)
+    {
+      printf ("p0(%ld) != p5(%ld)\n", (long int) p0, (long int) p5);
+      result = 1;
+    }
+
+  if (p0 == p1)
+    {
+      printf ("p0(%ld) == p1(%ld)\n", (long int) p0, (long int) p1);
+      result = 1;
+    }
+
+  if (p1 != p2)
+    {
+      printf ("p1(%ld) != p2(%ld)\n", (long int) p1, (long int) p2);
+      result = 1;
+    }
+
+  if (p0 == p3)
+    {
+      printf ("p0(%ld) == p3(%ld)\n", (long int) p0, (long int) p3);
+      result = 1;
+    }
+
+  if (p3 != p4)
+    {
+      printf ("p3(%ld) != p4(%ld)\n", (long int) p3, (long int) p4);
+      result = 1;
+    }
+
+  close (fd[0]);
+  close (fd[1]);
+
+  if (raise_fail)
+    {
+      puts ("raise failed");
+      result = 1;
+    }
+
+  if (result == 0)
+    puts ("All OK");
+
+  return result;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/plt/check-plt.sh b/l4/pkg/uclibc/lib/contrib/uclibc/test/plt/check-plt.sh
new file mode 100755
index 00000000..bedc8fd3
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/plt/check-plt.sh
@@ -0,0 +1,38 @@
+#!/bin/sh
+allowed="
+calloc
+free
+malloc
+memalign
+realloc
+"
+
+${OBJDUMP:-objdump} -d ${top_builddir:-../..}/lib/libc.so.? | \
+gawk -v allowed="${allowed}" '
+BEGIN {
+	COUNT = split(" " allowed, ALLOWED);
+}
+
+# Strip away the noise.  The name will be like:
+# :
+# 
+function symstrip(name) {
+	return gensub(/.*<([^>@]*).*/, "\\1", "", name);
+}
+
+{
+# Match the start of the symbol disassembly
+# 00009720 :
+if ($2 ~ />:$/) {
+	f = symstrip($2);
+
+} else if ($NF ~ /@plt>/) {
+	rf = symstrip($NF);
+	for (a in ALLOWED) {
+		a = ALLOWED[a];
+		if (a == rf)
+			next;
+	}
+	print "Func " f " references " rf;
+}
+}' | sort -u
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/pthread/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/test/pthread/Makefile
new file mode 100644
index 00000000..d6f00d64
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/pthread/Makefile
@@ -0,0 +1,7 @@
+# uClibc pthread tests
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+
+top_builddir=../../
+include ../Rules.mak
+-include Makefile.in
+include ../Test.mak
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/pthread/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/test/pthread/Makefile.in
new file mode 100644
index 00000000..c50748d6
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/pthread/Makefile.in
@@ -0,0 +1,8 @@
+# uClibc pthread tests
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+
+TESTS_DISABLED += cancellation-points
+
+EXTRA_LDFLAGS := -lpthread
+
+LDFLAGS_cancellation-points := -lrt
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/pthread/cancellation-points.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/pthread/cancellation-points.c
new file mode 100644
index 00000000..c7e784e4
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/pthread/cancellation-points.c
@@ -0,0 +1,284 @@
+/*
+ * Make sure functions marked as cancellation points actually are.
+ * http://www.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_09.html#tag_02_09_05
+ */
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/* take care of optional things ... */
+#define STUB(func, args) static void func args { sleep(0); }
+#if defined(__UCLIBC_AIO__)
+# include 
+#else
+STUB(aio_suspend, (void *p, int n, const void *p2))
+#endif
+#if defined(__UCLIBC_STROPTS__)
+# include 
+#else
+STUB(getmsg, (int f, void *p, void *p2, void *p3))
+STUB(getpmsg, (int f, void *p, void *p2, void *p3, void *p4))
+STUB(putmsg, (int f, void *p, void *p2, void *p3))
+STUB(putpmsg, (int f, void *p, void *p2, void *p3, void *p4))
+#endif
+#if defined(__UCLIBC__)
+STUB(clock_nanosleep, (int i, int f, const void *p, void *p2))
+#endif
+
+int cnt;
+bool ready;
+
+void cancel_timeout(int sig)
+{
+	ready = false;
+}
+void cancel_thread_cleanup(void *arg)
+{
+	ready = false;
+}
+
+/* some funcs need some help as they wont take NULL args ... */
+const struct timespec zero_sec = { .tv_sec = 0, .tv_nsec = 0 };
+
+sem_t sem;
+void help_sem_setup(void)
+{
+	if (sem_init(&sem, 0, 1) == -1) {
+		perror("sem_init() failed");
+		exit(-1);
+	}
+}
+
+pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
+pthread_mutex_t mutex;
+void help_pthread_setup(void)
+{
+	pthread_mutex_init(&mutex, NULL);
+	pthread_mutex_lock(&mutex);
+}
+
+/* the pthread function that will call the cancellable function over and over */
+#define _MAKE_CANCEL_THREAD_FUNC_EX(func, sysfunc, args, setup) \
+void *cancel_thread_##func(void *arg) \
+{ \
+	if (pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL)) { \
+		perror("unable to set cancel type to deferred; something is seriously broken"); \
+		exit(-1); \
+	} \
+	pthread_cleanup_push(cancel_thread_cleanup, NULL); \
+	setup; \
+	ready = true; \
+	while (ready) \
+		sysfunc args; \
+	pthread_cleanup_pop(1); \
+	return NULL; \
+}
+#define MAKE_CANCEL_THREAD_FUNC_RE(func, sysfunc, args) _MAKE_CANCEL_THREAD_FUNC_EX(func, sysfunc, args, (void)0)
+#define MAKE_CANCEL_THREAD_FUNC_EX(func, args, setup)   _MAKE_CANCEL_THREAD_FUNC_EX(func, func, args, setup)
+#define MAKE_CANCEL_THREAD_FUNC(func, args)             _MAKE_CANCEL_THREAD_FUNC_EX(func, func, args, (void)0)
+
+MAKE_CANCEL_THREAD_FUNC(accept, (-1, NULL, NULL))
+MAKE_CANCEL_THREAD_FUNC(aio_suspend, (NULL, 0, &zero_sec))
+MAKE_CANCEL_THREAD_FUNC(clock_nanosleep, (0, 0, NULL, NULL))
+MAKE_CANCEL_THREAD_FUNC(close, (-1))
+MAKE_CANCEL_THREAD_FUNC(connect, (-1, NULL, 0))
+MAKE_CANCEL_THREAD_FUNC(creat, ("", 0))
+MAKE_CANCEL_THREAD_FUNC(fcntl, (0, F_SETLKW, NULL))
+MAKE_CANCEL_THREAD_FUNC(fdatasync, (-1))
+MAKE_CANCEL_THREAD_FUNC(fsync, (0))
+MAKE_CANCEL_THREAD_FUNC(getmsg, (-1, NULL, NULL, NULL))
+MAKE_CANCEL_THREAD_FUNC(getpmsg, (-1, NULL, NULL, NULL, NULL))
+MAKE_CANCEL_THREAD_FUNC(lockf, (-1, F_TEST, 0))
+MAKE_CANCEL_THREAD_FUNC(mq_receive, (0, NULL, 0, NULL))
+MAKE_CANCEL_THREAD_FUNC(mq_send, (0, NULL, 0, 0))
+MAKE_CANCEL_THREAD_FUNC(mq_timedreceive, (0, NULL, 0, NULL, NULL))
+MAKE_CANCEL_THREAD_FUNC(mq_timedsend, (0, NULL, 0, 0, NULL))
+MAKE_CANCEL_THREAD_FUNC(msgrcv, (-1, NULL, 0, 0, 0))
+MAKE_CANCEL_THREAD_FUNC(msgsnd, (-1, NULL, 0, 0))
+MAKE_CANCEL_THREAD_FUNC(msync, (NULL, 0, 0))
+MAKE_CANCEL_THREAD_FUNC(nanosleep, (NULL, NULL))
+MAKE_CANCEL_THREAD_FUNC(open, ("", 0))
+MAKE_CANCEL_THREAD_FUNC(pause, ())
+MAKE_CANCEL_THREAD_FUNC(poll, (NULL, 0, 0))
+MAKE_CANCEL_THREAD_FUNC(pread, (-1, NULL, 0, 0))
+MAKE_CANCEL_THREAD_FUNC(pselect, (0, NULL, NULL, NULL, NULL, NULL))
+MAKE_CANCEL_THREAD_FUNC_EX(pthread_cond_timedwait, (&cond, &mutex, &zero_sec), help_pthread_setup())
+MAKE_CANCEL_THREAD_FUNC_EX(pthread_cond_wait, (&cond, &mutex), help_pthread_setup())
+/*MAKE_CANCEL_THREAD_FUNC_EX(pthread_join, (0, NULL))*/
+MAKE_CANCEL_THREAD_FUNC(pthread_testcancel, ())
+MAKE_CANCEL_THREAD_FUNC(putmsg, (-1, NULL, NULL, 0))
+MAKE_CANCEL_THREAD_FUNC(putpmsg, (-1, NULL, NULL, 0, 0))
+MAKE_CANCEL_THREAD_FUNC(pwrite, (-1, NULL, 0, 0))
+MAKE_CANCEL_THREAD_FUNC(read, (-1, NULL, 0))
+MAKE_CANCEL_THREAD_FUNC(readv, (-1, NULL, 0))
+MAKE_CANCEL_THREAD_FUNC(recv, (-1, NULL, 0, 0))
+MAKE_CANCEL_THREAD_FUNC(recvfrom, (-1, NULL, 0, 0, NULL, NULL))
+MAKE_CANCEL_THREAD_FUNC(recvmsg, (-1, NULL, 0))
+MAKE_CANCEL_THREAD_FUNC(select, (0, NULL, NULL, NULL, NULL))
+MAKE_CANCEL_THREAD_FUNC_EX(sem_timedwait, (&sem, &zero_sec), help_sem_setup())
+MAKE_CANCEL_THREAD_FUNC_EX(sem_wait, (&sem), help_sem_setup())
+MAKE_CANCEL_THREAD_FUNC(send, (-1, NULL, 0, 0))
+MAKE_CANCEL_THREAD_FUNC(sendmsg, (-1, NULL, 0))
+MAKE_CANCEL_THREAD_FUNC(sendto, (-1, NULL, 0, 0, NULL, 0))
+MAKE_CANCEL_THREAD_FUNC(sigpause, (0))
+MAKE_CANCEL_THREAD_FUNC(sigsuspend, (NULL))
+MAKE_CANCEL_THREAD_FUNC(sigtimedwait, (NULL, NULL, NULL))
+MAKE_CANCEL_THREAD_FUNC(sigwait, (NULL, NULL))
+MAKE_CANCEL_THREAD_FUNC(sigwaitinfo, (NULL, NULL))
+MAKE_CANCEL_THREAD_FUNC(sleep, (0))
+MAKE_CANCEL_THREAD_FUNC(system, (""))
+MAKE_CANCEL_THREAD_FUNC(tcdrain, (-1))
+#ifdef __UCLIBC_SUSV3_LEGACY__
+MAKE_CANCEL_THREAD_FUNC(usleep, (0))
+#endif
+MAKE_CANCEL_THREAD_FUNC(wait, (NULL))
+MAKE_CANCEL_THREAD_FUNC(waitid, (0, 0, NULL, 0))
+MAKE_CANCEL_THREAD_FUNC(waitpid, (-1, NULL, 0))
+MAKE_CANCEL_THREAD_FUNC(write, (-1, NULL, 0))
+MAKE_CANCEL_THREAD_FUNC(writev, (-1, NULL, 0))
+
+/* test a few variations that should not cancel ... */
+MAKE_CANCEL_THREAD_FUNC_RE(fcntl_another, fcntl, (0, F_GETFD))
+
+/* main test that creates thread, cancels it, etc... */
+int _test_func(const char *func_name, void *(*func)(void*), const int should_cancel)
+{
+	int ret;
+	pthread_t cancel_thread_id;
+
+	++cnt;
+
+	printf("testing %-30s ", func_name);
+
+	printf(".");
+	if (signal(SIGALRM, cancel_timeout) == SIG_ERR) {
+		perror("unable to bind SIGALRM");
+		exit(-1);
+	}
+
+	printf(".");
+	ready = false;
+	pthread_create(&cancel_thread_id, NULL, func, NULL);
+
+	printf(".");
+	while (!ready)
+		sched_yield();
+
+	printf(".");
+	if (pthread_cancel(cancel_thread_id)) {
+		perror("unable to cancel thread");
+		exit(-1);
+	}
+
+	printf(".");
+	alarm(5);
+	while (ready)
+		sched_yield();
+
+	printf(".");
+	ret = (!!!alarm(0) == should_cancel);
+
+	if (ret)
+		printf(" failed ;(\n");
+	else
+		printf(" OK!\n");
+
+	return ret;
+}
+#define TEST_FUNC(f)    _test_func(#f, cancel_thread_##f, 1)
+#define TEST_FUNC_RE(f) _test_func(#f, cancel_thread_##f, 0)
+
+int main(int argc, char *argv[])
+{
+	int ret = 0;
+	setbuf(stdout, NULL);
+	cnt = 0;
+
+	ret += TEST_FUNC(accept);
+	ret += TEST_FUNC(aio_suspend);
+	ret += TEST_FUNC(clock_nanosleep);
+	ret += TEST_FUNC(close);
+	ret += TEST_FUNC(connect);
+	ret += TEST_FUNC(creat);
+	ret += TEST_FUNC(fcntl);
+	ret += TEST_FUNC(fdatasync);
+	ret += TEST_FUNC(fsync);
+	ret += TEST_FUNC(getmsg);
+	ret += TEST_FUNC(getpmsg);
+	ret += TEST_FUNC(lockf);
+	ret += TEST_FUNC(mq_receive);
+	ret += TEST_FUNC(mq_send);
+	ret += TEST_FUNC(mq_timedreceive);
+	ret += TEST_FUNC(mq_timedsend);
+	ret += TEST_FUNC(msgrcv);
+	ret += TEST_FUNC(msgsnd);
+	ret += TEST_FUNC(msync);
+	ret += TEST_FUNC(nanosleep);
+	ret += TEST_FUNC(open);
+	ret += TEST_FUNC(pause);
+	ret += TEST_FUNC(poll);
+	ret += TEST_FUNC(pread);
+	ret += TEST_FUNC(pselect);
+	ret += TEST_FUNC(pthread_cond_timedwait);
+	ret += TEST_FUNC(pthread_cond_wait);
+	/*ret += TEST_FUNC(pthread_join);*/
+	ret += TEST_FUNC(pthread_testcancel);
+	ret += TEST_FUNC(putmsg);
+	ret += TEST_FUNC(putpmsg);
+	ret += TEST_FUNC(pwrite);
+	ret += TEST_FUNC(read);
+	ret += TEST_FUNC(readv);
+	ret += TEST_FUNC(recv);
+	ret += TEST_FUNC(recvfrom);
+	ret += TEST_FUNC(recvmsg);
+	ret += TEST_FUNC(select);
+	ret += TEST_FUNC(sem_timedwait);
+	ret += TEST_FUNC(sem_wait);
+	ret += TEST_FUNC(send);
+	ret += TEST_FUNC(sendmsg);
+	ret += TEST_FUNC(sendto);
+	ret += TEST_FUNC(sigpause);
+	ret += TEST_FUNC(sigsuspend);
+	ret += TEST_FUNC(sigtimedwait);
+	ret += TEST_FUNC(sigwait);
+	ret += TEST_FUNC(sigwaitinfo);
+	ret += TEST_FUNC(sleep);
+	ret += TEST_FUNC(system);
+	ret += TEST_FUNC(tcdrain);
+#ifdef __UCLIBC_SUSV3_LEGACY__
+	ret += TEST_FUNC(usleep);
+#endif
+	ret += TEST_FUNC(wait);
+	ret += TEST_FUNC(waitid);
+	ret += TEST_FUNC(waitpid);
+	ret += TEST_FUNC(write);
+	ret += TEST_FUNC(writev);
+
+	ret += TEST_FUNC_RE(fcntl_another);
+
+	if (ret)
+		printf("!!! %i / %i tests failed\n", ret, cnt);
+
+	return ret;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/pthread/ex1.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/pthread/ex1.c
new file mode 100644
index 00000000..4d9de03d
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/pthread/ex1.c
@@ -0,0 +1,35 @@
+/* Creates two threads, one printing 10000 "a"s, the other printing
+   10000 "b"s.
+   Illustrates: thread creation, thread joining. */
+
+#include 
+#include 
+#include 
+#include "pthread.h"
+
+static void *process(void * arg)
+{
+	int i;
+	printf("Starting process %s\n", (char *)arg);
+	for (i = 0; i < 10000; i++)
+		write(1, (char *) arg, 1);
+	return NULL;
+}
+
+#define sucfail(r) (r != 0 ? "failed" : "succeeded")
+int main(void)
+{
+	int pret, ret = 0;
+	pthread_t th_a, th_b;
+	void *retval;
+
+	ret += (pret = pthread_create(&th_a, NULL, process, (void *)"a"));
+	printf("create a %s %d\n", sucfail(pret), pret);
+	ret += (pret = pthread_create(&th_b, NULL, process, (void *)"b"));
+	printf("create b %s %d\n", sucfail(pret), pret);
+	ret += (pret = pthread_join(th_a, &retval));
+	printf("join a %s %d\n", sucfail(pret), pret);
+	ret += (pret = pthread_join(th_b, &retval));
+	printf("join b %s %d\n", sucfail(pret), pret);
+	return ret;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/pthread/ex2.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/pthread/ex2.c
new file mode 100644
index 00000000..98bd4b34
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/pthread/ex2.c
@@ -0,0 +1,113 @@
+/* The classic producer-consumer example.
+   Illustrates mutexes and conditions.
+   All integers between 0 and 9999 should be printed exactly twice,
+   once to the right of the arrow and once to the left. */
+
+#include 
+#include "pthread.h"
+
+#define BUFFER_SIZE 16
+
+/* Circular buffer of integers. */
+
+struct prodcons {
+  int buffer[BUFFER_SIZE];      /* the actual data */
+  pthread_mutex_t lock;         /* mutex ensuring exclusive access to buffer */
+  int readpos, writepos;        /* positions for reading and writing */
+  pthread_cond_t notempty;      /* signaled when buffer is not empty */
+  pthread_cond_t notfull;       /* signaled when buffer is not full */
+};
+
+/* Initialize a buffer */
+
+static void init(struct prodcons * b)
+{
+  pthread_mutex_init(&b->lock, NULL);
+  pthread_cond_init(&b->notempty, NULL);
+  pthread_cond_init(&b->notfull, NULL);
+  b->readpos = 0;
+  b->writepos = 0;
+}
+
+/* Store an integer in the buffer */
+
+static void put(struct prodcons * b, int data)
+{
+  pthread_mutex_lock(&b->lock);
+  /* Wait until buffer is not full */
+  while ((b->writepos + 1) % BUFFER_SIZE == b->readpos) {
+    pthread_cond_wait(&b->notfull, &b->lock);
+    /* pthread_cond_wait reacquired b->lock before returning */
+  }
+  /* Write the data and advance write pointer */
+  b->buffer[b->writepos] = data;
+  b->writepos++;
+  if (b->writepos >= BUFFER_SIZE) b->writepos = 0;
+  /* Signal that the buffer is now not empty */
+  pthread_cond_signal(&b->notempty);
+  pthread_mutex_unlock(&b->lock);
+}
+
+/* Read and remove an integer from the buffer */
+
+static int get(struct prodcons * b)
+{
+  int data;
+  pthread_mutex_lock(&b->lock);
+  /* Wait until buffer is not empty */
+  while (b->writepos == b->readpos) {
+    pthread_cond_wait(&b->notempty, &b->lock);
+  }
+  /* Read the data and advance read pointer */
+  data = b->buffer[b->readpos];
+  b->readpos++;
+  if (b->readpos >= BUFFER_SIZE) b->readpos = 0;
+  /* Signal that the buffer is now not full */
+  pthread_cond_signal(&b->notfull);
+  pthread_mutex_unlock(&b->lock);
+  return data;
+}
+
+/* A test program: one thread inserts integers from 1 to 10000,
+   the other reads them and prints them. */
+
+#define OVER (-1)
+
+struct prodcons buffer;
+
+static void * producer(void * data)
+{
+  int n;
+  for (n = 0; n < 10000; n++) {
+    printf("%d --->\n", n);
+    put(&buffer, n);
+  }
+  put(&buffer, OVER);
+  return NULL;
+}
+
+static void * consumer(void * data)
+{
+  int d;
+  while (1) {
+    d = get(&buffer);
+    if (d == OVER) break;
+    printf("---> %d\n", d);
+  }
+  return NULL;
+}
+
+int main(void)
+{
+  pthread_t th_a, th_b;
+  void * retval;
+
+  init(&buffer);
+  /* Create the threads */
+  pthread_create(&th_a, NULL, producer, 0);
+  pthread_create(&th_b, NULL, consumer, 0);
+  /* Wait until producer and consumer finish. */
+  pthread_join(th_a, &retval);
+  pthread_join(th_b, &retval);
+  return 0;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/pthread/ex3.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/pthread/ex3.c
new file mode 100644
index 00000000..8ef77978
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/pthread/ex3.c
@@ -0,0 +1,152 @@
+/* Multi-thread searching.
+   Illustrates: thread cancellation, cleanup handlers. */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/* Defines the number of searching threads */
+#define NUM_THREADS 5
+
+/* Function prototypes */
+void *search(void *);
+void print_it(void *);
+
+/* Global variables */
+pthread_t threads[NUM_THREADS];
+pthread_mutex_t lock;
+int tries;
+volatile int started;
+
+int main(int argc, char ** argv)
+{
+  unsigned long i;
+  unsigned long pid;
+
+  /* create a number to search for */
+  pid = getpid();
+  printf("Searching for the number = %ld...\n", pid);
+
+  /* Initialize the mutex lock */
+  pthread_mutex_init(&lock, NULL);
+
+  /* Create the searching threads */
+  for (started=0; started
+#include 
+#include 
+#include 
+#include 
+
+/* This is a typical example of a library function that uses
+   static variables to accumulate results between calls.
+   Here, it just returns the concatenation of all string arguments
+   that were given to it. */
+
+#if 0
+
+static char * str_accumulate(char * s)
+{
+  static char accu[1024] = { 0 };
+  strcat(accu, s);
+  return accu;
+}
+
+#endif
+
+/* Of course, this cannot be used in a multi-threaded program
+   because all threads store "accu" at the same location.
+   So, we'll use thread-specific data to have a different "accu"
+   for each thread. */
+
+/* Key identifying the thread-specific data */
+static pthread_key_t str_key;
+/* "Once" variable ensuring that the key for str_alloc will be allocated
+   exactly once. */
+static pthread_once_t str_alloc_key_once = PTHREAD_ONCE_INIT;
+
+/* Forward functions */
+static void str_alloc_key(void);
+static void str_alloc_destroy_accu(void * accu);
+
+/* Thread-safe version of str_accumulate */
+
+static char * str_accumulate(const char * s)
+{
+  char * accu;
+
+  /* Make sure the key is allocated */
+  pthread_once(&str_alloc_key_once, str_alloc_key);
+  /* Get the thread-specific data associated with the key */
+  accu = (char *) pthread_getspecific(str_key);
+  /* It's initially NULL, meaning that we must allocate the buffer first. */
+  if (accu == NULL) {
+    accu = malloc(1024);
+    if (accu == NULL) return NULL;
+    accu[0] = 0;
+    /* Store the buffer pointer in the thread-specific data. */
+    pthread_setspecific(str_key, (void *) accu);
+    printf("Thread %lx: allocating buffer at %p\n", pthread_self(), accu);
+  }
+  /* Now we can use accu just as in the non thread-safe code. */
+  strcat(accu, s);
+  return accu;
+}
+
+/* Function to allocate the key for str_alloc thread-specific data. */
+
+static void str_alloc_key(void)
+{
+  pthread_key_create(&str_key, str_alloc_destroy_accu);
+  printf("Thread %lx: allocated key %d\n", pthread_self(), str_key);
+}
+
+/* Function to free the buffer when the thread exits. */
+/* Called only when the thread-specific data is not NULL. */
+
+static void str_alloc_destroy_accu(void * accu)
+{
+  printf("Thread %lx: freeing buffer at %p\n", pthread_self(), accu);
+  free(accu);
+}
+
+/* Test program */
+
+static void * process(void * arg)
+{
+  char * res;
+  res = str_accumulate("Result of ");
+  res = str_accumulate((char *) arg);
+  res = str_accumulate(" thread");
+  printf("Thread %lx: \"%s\"\n", pthread_self(), res);
+  return NULL;
+}
+
+int main(int argc, char ** argv)
+{
+  char * res;
+  pthread_t th1, th2;
+
+  res = str_accumulate("Result of ");
+  pthread_create(&th1, NULL, process, (void *) "first");
+  pthread_create(&th2, NULL, process, (void *) "second");
+  res = str_accumulate("initial thread");
+  printf("Thread %lx: \"%s\"\n", pthread_self(), res);
+  pthread_join(th1, NULL);
+  pthread_join(th2, NULL);
+  exit(0);
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/pthread/ex5.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/pthread/ex5.c
new file mode 100644
index 00000000..7a293eb0
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/pthread/ex5.c
@@ -0,0 +1,102 @@
+/* The classic producer-consumer example, implemented with semaphores.
+   All integers between 0 and 9999 should be printed exactly twice,
+   once to the right of the arrow and once to the left. */
+
+#include 
+#include "pthread.h"
+#include "semaphore.h"
+
+#define BUFFER_SIZE 16
+
+/* Circular buffer of integers. */
+
+struct prodcons {
+  int buffer[BUFFER_SIZE];      /* the actual data */
+  int readpos, writepos;        /* positions for reading and writing */
+  sem_t sem_read;               /* number of elements available for reading */
+  sem_t sem_write;              /* number of locations available for writing */
+};
+
+/* Initialize a buffer */
+
+static void init(struct prodcons * b)
+{
+  sem_init(&b->sem_write, 0, BUFFER_SIZE - 1);
+  sem_init(&b->sem_read, 0, 0);
+  b->readpos = 0;
+  b->writepos = 0;
+}
+
+/* Store an integer in the buffer */
+
+static void put(struct prodcons * b, int data)
+{
+  /* Wait until buffer is not full */
+  sem_wait(&b->sem_write);
+  /* Write the data and advance write pointer */
+  b->buffer[b->writepos] = data;
+  b->writepos++;
+  if (b->writepos >= BUFFER_SIZE) b->writepos = 0;
+  /* Signal that the buffer contains one more element for reading */
+  sem_post(&b->sem_read);
+}
+
+/* Read and remove an integer from the buffer */
+
+static int get(struct prodcons * b)
+{
+  int data;
+  /* Wait until buffer is not empty */
+  sem_wait(&b->sem_read);
+  /* Read the data and advance read pointer */
+  data = b->buffer[b->readpos];
+  b->readpos++;
+  if (b->readpos >= BUFFER_SIZE) b->readpos = 0;
+  /* Signal that the buffer has now one more location for writing */
+  sem_post(&b->sem_write);
+  return data;
+}
+
+/* A test program: one thread inserts integers from 1 to 10000,
+   the other reads them and prints them. */
+
+#define OVER (-1)
+
+struct prodcons buffer;
+
+static void * producer(void * data)
+{
+  int n;
+  for (n = 0; n < 10000; n++) {
+    printf("%d --->\n", n);
+    put(&buffer, n);
+  }
+  put(&buffer, OVER);
+  return NULL;
+}
+
+static void * consumer(void * data)
+{
+  int d;
+  while (1) {
+    d = get(&buffer);
+    if (d == OVER) break;
+    printf("---> %d\n", d);
+  }
+  return NULL;
+}
+
+int main(void)
+{
+  pthread_t th_a, th_b;
+  void * retval;
+
+  init(&buffer);
+  /* Create the threads */
+  pthread_create(&th_a, NULL, producer, 0);
+  pthread_create(&th_b, NULL, consumer, 0);
+  /* Wait until producer and consumer finish. */
+  pthread_join(th_a, &retval);
+  pthread_join(th_b, &retval);
+  return 0;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/pthread/ex6.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/pthread/ex6.c
new file mode 100644
index 00000000..ffb62877
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/pthread/ex6.c
@@ -0,0 +1,44 @@
+#include 
+#include 
+#include 
+#include 
+#include 
+
+static void *
+test_thread (void *v_param)
+{
+  return NULL;
+}
+
+int
+main (void)
+{
+  unsigned long count;
+  struct timespec ts;
+  ts.tv_sec = 0;
+  ts.tv_nsec = 10 * 1000;
+
+  setvbuf (stdout, NULL, _IONBF, 0);
+
+  for (count = 0; count < 2000; ++count)
+    {
+      pthread_t thread;
+      int status;
+
+      status = pthread_create (&thread, NULL, test_thread, NULL);
+      if (status != 0)
+	{
+	  printf ("status = %d, count = %lu: %s\n", status, count,
+		  strerror (errno));
+	  return 1;
+	}
+      else
+	{
+	  printf ("count = %lu\n", count);
+	}
+      /* pthread_detach (thread); */
+      pthread_join (thread, NULL);
+      nanosleep (&ts, NULL);
+    }
+  return 0;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/pthread/ex7.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/pthread/ex7.c
new file mode 100644
index 00000000..8eeb9a2e
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/pthread/ex7.c
@@ -0,0 +1,106 @@
+/* ex7
+ *
+ * Test case that illustrates a timed wait on a condition variable.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/* Our event variable using a condition variable contruct. */
+typedef struct {
+    pthread_mutex_t	mutex;
+    pthread_cond_t	cond;
+    int			flag;
+} event_t;
+
+
+/* Global event to signal main thread the timeout of the child thread. */
+event_t main_event;
+
+
+static void *
+test_thread (void *ms_param)
+{
+    unsigned long status = 0;
+    event_t foo;
+    struct timespec timeout;
+    struct timeval  now;
+    long ms = (long) ms_param;
+
+    /* initialize cond var */
+    pthread_cond_init(&foo.cond, NULL);
+    pthread_mutex_init(&foo.mutex, NULL);
+    foo.flag = 0;
+
+    /* set the time out value */
+    printf("waiting %ld ms ...\n", ms);
+    gettimeofday(&now, NULL);
+    timeout.tv_sec  = now.tv_sec + ms/1000 + (now.tv_usec + (ms%1000)*1000)/1000000;
+    timeout.tv_nsec = ((now.tv_usec + (ms%1000)*1000) % 1000000) * 1000;
+
+    /* Just use this to test the time out. The cond var is never signaled. */
+    pthread_mutex_lock(&foo.mutex);
+    while (foo.flag == 0 && status != ETIMEDOUT) {
+	status = pthread_cond_timedwait(&foo.cond, &foo.mutex, &timeout);
+    }
+    pthread_mutex_unlock(&foo.mutex);
+
+    /* post the main event */
+    pthread_mutex_lock(&main_event.mutex);
+    main_event.flag = 1;
+    pthread_cond_signal(&main_event.cond);
+    pthread_mutex_unlock(&main_event.mutex);
+
+    /* that's it, bye */
+    return (void*) status;
+}
+
+int
+main (void)
+{
+  unsigned long count;
+  struct timespec ts;
+  ts.tv_sec = 0;
+  ts.tv_nsec = 10 * 1000;
+
+  setvbuf (stdout, NULL, _IONBF, 0);
+
+  /* initialize main event cond var */
+  pthread_cond_init(&main_event.cond, NULL);
+  pthread_mutex_init(&main_event.mutex, NULL);
+  main_event.flag = 0;
+
+  for (count = 0; count < 20; ++count)
+  {
+      pthread_t thread;
+      int status;
+
+      /* pass down the milli-second timeout in the void* param */
+      status = pthread_create (&thread, NULL, test_thread, (void*) (count*100));
+      if (status != 0) {
+	  printf ("status = %d, count = %lu: %s\n", status, count,
+		  strerror (errno));
+	  return 1;
+      }
+      else {
+
+	  /* wait for the event posted by the child thread */
+	  pthread_mutex_lock(&main_event.mutex);
+	  while (main_event.flag == 0) {
+	      pthread_cond_wait(&main_event.cond, &main_event.mutex);
+	  }
+	  main_event.flag = 0;
+	  pthread_mutex_unlock(&main_event.mutex);
+
+	  printf ("count = %lu\n", count);
+      }
+
+      nanosleep (&ts, NULL);
+  }
+
+  return 0;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/pthread/tst-too-many-cleanups.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/pthread/tst-too-many-cleanups.c
new file mode 100644
index 00000000..7828c503
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/pthread/tst-too-many-cleanups.c
@@ -0,0 +1,104 @@
+/*
+ * This illustrates the bug where the cleanup function
+ * of a thread may be called too many times.
+ *
+ * main thread:
+ *  - grab mutex
+ *  - spawn thread1
+ *  - go to sleep
+ * thread1:
+ *  - register cleanup handler via pthread_cleanup_push()
+ *  - try to grab mutex and sleep
+ * main:
+ *  - kill thread1
+ *  - go to sleep
+ * thread1 cleanup handler:
+ *  - try to grab mutex and sleep
+ * main:
+ *  - kill thread1
+ *  - go to sleep
+ * thread1 cleanup handler:
+ *  - wrongly called again
+ */
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define warn(fmt, args...) fprintf(stderr, "[%p] " fmt, (void*)pthread_self(), ## args)
+#define warnf(fmt, args...) warn("%s:%i: " fmt, __FUNCTION__, __LINE__, ## args)
+
+int ok_to_kill_thread;
+
+static void thread_killed(void *arg);
+
+static void *KillMeThread(void *thread_par)
+{
+	pthread_t pthread_id;
+
+	warnf("Starting child thread\n");
+
+	pthread_id = pthread_self();
+	pthread_cleanup_push(thread_killed, (void *)pthread_id);
+
+	pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
+	pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
+
+	/* main code */
+	warnf("please kill me now\n");
+	while (1) {
+		ok_to_kill_thread = 1;
+		sleep(1);
+	}
+
+	pthread_cleanup_pop(0);
+
+	return 0;
+}
+
+static void thread_killed(void *arg)
+{
+	static int num_times_called = 0;
+
+	warnf("killing %p [cnt=%i]\n", arg, ++num_times_called);
+	assert(num_times_called == 1);
+
+	/* pick any cancellation endpoint, sleep() will do just fine */
+	while (1) {
+		warnf("sleeping in cancellation endpoint ...\n");
+		sleep(1);
+	}
+
+	warnf("done cleaning up\n");
+}
+
+int main(int argc, char *argv[])
+{
+	int count = 3;
+	pthread_t app_pthread_id;
+
+	/* need to tweak this test a bit to play nice with signals and LT */
+	return 0;
+
+	ok_to_kill_thread = 0;
+
+	pthread_create(&app_pthread_id, NULL, KillMeThread, NULL);
+
+	warnf("waiting for thread to prepare itself\n");
+	while (!ok_to_kill_thread)
+		sleep(1);
+
+	while (count--) {
+		warnf("killing thread\n");
+		pthread_cancel(app_pthread_id);
+		sleep(3);
+	}
+
+	return 0;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/pwd_grp/.indent.pro b/l4/pkg/uclibc/lib/contrib/uclibc/test/pwd_grp/.indent.pro
new file mode 100644
index 00000000..492ecf1c
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/pwd_grp/.indent.pro
@@ -0,0 +1,33 @@
+--blank-lines-after-declarations
+--blank-lines-after-procedures
+--break-before-boolean-operator
+--no-blank-lines-after-commas
+--braces-on-if-line
+--braces-on-struct-decl-line
+--comment-indentation25
+--declaration-comment-column25
+--no-comment-delimiters-on-blank-lines
+--cuddle-else
+--continuation-indentation4
+--case-indentation0
+--else-endif-column33
+--space-after-cast
+--line-comments-indentation0
+--declaration-indentation1
+--dont-format-first-column-comments
+--dont-format-comments
+--honour-newlines
+--indent-level4
+/* changed from 0 to 4 */
+--parameter-indentation4
+--line-length78 /* changed from 75 */
+--continue-at-parentheses
+--no-space-after-function-call-names
+--dont-break-procedure-type
+--dont-star-comments
+--leave-optional-blank-lines
+--dont-space-special-semicolon
+--tab-size4
+/* additions by Mark */
+--case-brace-indentation0
+--leave-preprocessor-space
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/pwd_grp/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/test/pwd_grp/Makefile
new file mode 100644
index 00000000..21070f4c
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/pwd_grp/Makefile
@@ -0,0 +1,7 @@
+# uClibc pwd_grp tests
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+
+top_builddir=../../
+include ../Rules.mak
+-include Makefile.in
+include ../Test.mak
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/pwd_grp/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/test/pwd_grp/Makefile.in
new file mode 100644
index 00000000..d561f3dc
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/pwd_grp/Makefile.in
@@ -0,0 +1,8 @@
+# uClibc pwd_grp tests
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+
+DODIFF_test_pwd  := 1
+DODIFF_test_grp  := 1
+DODIFF_pwcat     := 1
+DODIFF_grcat     := 1
+DODIFF_getgroups := 1
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/pwd_grp/getgroups.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/pwd_grp/getgroups.c
new file mode 100644
index 00000000..5769b180
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/pwd_grp/getgroups.c
@@ -0,0 +1,99 @@
+/* This test was ripped out of GNU 'id' from coreutils-5.0
+ * by Erik Andersen.
+ *
+ *
+ * id is Copyright (C) 1989-2003 Free Software Foundation, Inc.
+ * and licensed under the GPL v2 or later, and was written by
+ * Arnold Robbins, with a major rewrite by David MacKenzie,
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/* The number of errors encountered so far. */
+static int problems = 0;
+
+/* Print the name or value of group ID GID. */
+static void print_group(gid_t gid)
+{
+	struct group *grp = NULL;
+
+	grp = getgrgid(gid);
+	if (grp == NULL) {
+		warn("cannot find name for group ID %u", gid);
+		problems++;
+	}
+
+	if (grp == NULL)
+		printf("%u", (unsigned)gid);
+	else
+		printf("%s", grp->gr_name);
+}
+
+static int xgetgroups(gid_t gid, int *n_groups, gid_t ** groups)
+{
+	int max_n_groups;
+	int ng;
+	gid_t *g;
+	int fail = 0;
+
+	max_n_groups = getgroups(0, NULL);
+
+	/* Add 1 just in case max_n_groups is zero.  */
+	g = (gid_t *) malloc(max_n_groups * sizeof(gid_t) + 1);
+	if (g == NULL)
+		err(EXIT_FAILURE, "out of memory");
+	ng = getgroups(max_n_groups, g);
+
+	if (ng < 0) {
+		warn("cannot get supplemental group list");
+		++fail;
+		free(g);
+	}
+	if (!fail) {
+		*n_groups = ng;
+		*groups = g;
+	}
+	return fail;
+}
+
+/* Print all of the distinct groups the user is in. */
+int main(int argc, char *argv[])
+{
+	struct passwd *pwd;
+
+	pwd = getpwuid(getuid());
+	if (pwd == NULL)
+		problems++;
+
+	print_group(getgid());
+	if (getegid() != getgid()) {
+		putchar(' ');
+		print_group(getegid());
+	}
+
+	{
+		int n_groups = 0;
+		gid_t *groups;
+		register int i;
+
+		if (xgetgroups((pwd ? pwd->pw_gid : (gid_t) - 1),
+			       &n_groups, &groups)) {
+			return ++problems;
+		}
+
+		for (i = 0; i < n_groups; i++)
+			if (groups[i] != getgid() && groups[i] != getegid()) {
+				putchar(' ');
+				print_group(groups[i]);
+			}
+		free(groups);
+	}
+	putchar('\n');
+	return (problems != 0);
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/pwd_grp/grcat.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/pwd_grp/grcat.c
new file mode 100644
index 00000000..a8961402
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/pwd_grp/grcat.c
@@ -0,0 +1,32 @@
+/*
+ * grcat.c
+ *
+ * Generate a printable version of the group database
+ */
+/*
+ * Arnold Robbins, arnold@gnu.org, May 1993
+ * Public Domain
+ */
+
+#include 
+#include 
+#include 
+
+int main(int argc, char **argv)
+{
+    struct group *g;
+    int i;
+
+    while ((g = getgrent()) != NULL) {
+	printf("%s:%s:%ld:", g->gr_name, g->gr_passwd,
+		(long) g->gr_gid);
+	for (i = 0; g->gr_mem[i] != NULL; i++) {
+	    printf("%s", g->gr_mem[i]);
+	    if (g->gr_mem[i+1] != NULL)
+		putchar(',');
+	}
+	putchar('\n');
+    }
+    endgrent();
+    return 0;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/pwd_grp/pwcat.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/pwd_grp/pwcat.c
new file mode 100644
index 00000000..afad8e18
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/pwd_grp/pwcat.c
@@ -0,0 +1,26 @@
+/*
+ * pwcat.c
+ *
+ * Generate a printable version of the password database
+ */
+/*
+ * Arnold Robbins, arnold@gnu.org, May 1993
+ * Public Domain
+ */
+
+#include 
+#include 
+#include 
+
+int main(int argc, char **argv)
+{
+    struct passwd *p;
+
+    while ((p = getpwent()) != NULL)
+	printf("%s:%s:%ld:%ld:%s:%s:%s\n",
+		p->pw_name, p->pw_passwd, (long) p->pw_uid,
+		(long) p->pw_gid, p->pw_gecos, p->pw_dir, p->pw_shell);
+
+    endpwent();
+    return 0;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/pwd_grp/test_grp.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/pwd_grp/test_grp.c
new file mode 100644
index 00000000..573806cd
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/pwd_grp/test_grp.c
@@ -0,0 +1,87 @@
+/*
+ * test_grp.c - This file is part of the libc-8086/grp package for ELKS,
+ * Copyright (C) 1995, 1996 Nat Friedman .
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+int main(int argc, char **argv)
+{
+	struct group *group;
+	char **tmp_mem;
+	int test_gid;
+
+	fprintf(stdout, "Beginning test of libc/grp...\n");
+
+	fprintf(stdout, "=> Testing setgrent(), getgrent(), endgrent()...\n");
+	fprintf(stdout, "-> setgrent()...\n");
+	setgrent();
+	fprintf(stdout, "-> getgrent()...\n");
+	printf
+		("********************************************************************************\n");
+	while ((group = getgrent()) != NULL) {
+		printf("gr_name\t\t: %s\n", group->gr_name);
+		printf("gr_passwd\t: %s\n", group->gr_passwd);
+		printf("gr_gid\t\t: %d\n", (int) group->gr_gid);
+		printf("gr_mem\t\t: ");
+		fflush(stdout);
+		tmp_mem = group->gr_mem;
+		while (*tmp_mem != NULL) {
+			printf("%s, ", *tmp_mem);
+			tmp_mem++;
+		}
+		printf
+			("\n********************************************************************************\n");
+	}
+	fprintf(stdout, "-> endgrent()...\n");
+	endgrent();
+	fprintf(stdout,
+			"=> Test of setgrent(), getgrent(), endgrent() complete.\n");
+	fprintf(stdout, "=> Testing getgrid(), getgrnam()...\n");
+	fprintf(stdout, "-> getgrgid()...\n");
+	printf
+		("********************************************************************************\n");
+	for (test_gid = 0; test_gid < 100; test_gid++) {
+		fprintf(stdout, "-> getgrgid(%d)...\n", test_gid);
+		group = getgrgid((gid_t) test_gid);
+		if (group != NULL) {
+			printf("gr_name\t: %s\n", group->gr_name);
+			printf("gr_passwd\t: %s\n", group->gr_passwd);
+			printf("gr_gid\t: %d\n", (int) group->gr_gid);
+			printf("gr_mem\t\t: ");
+			fflush(stdout);
+			tmp_mem = group->gr_mem;
+			while (*tmp_mem != NULL) {
+				printf("%s, ", *tmp_mem);
+				tmp_mem++;
+			}
+		}
+		printf
+			("\n********************************************************************************\n");
+	}
+	fprintf(stdout, "-> getgrnam()...\n");
+	group = getgrnam("root");
+	if (group == NULL) {
+		printf(">NULL<\n");
+	} else {
+		printf("gr_name\t: %s\n", group->gr_name);
+		printf("gr_passwd\t: %s\n", group->gr_passwd);
+		printf("gr_gid\t: %d\n", (int) group->gr_gid);
+		printf("gr_mem\t\t: ");
+		fflush(stdout);
+		tmp_mem = group->gr_mem;
+		while (*tmp_mem != NULL) {
+			printf("%s, ", *tmp_mem);
+			tmp_mem++;
+		}
+		printf("\n");
+	}
+
+
+	return 0;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/pwd_grp/test_pwd.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/pwd_grp/test_pwd.c
new file mode 100644
index 00000000..065864e2
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/pwd_grp/test_pwd.c
@@ -0,0 +1,74 @@
+/*
+ * test_pwd.c - This file is part of the libc-8086/pwd package for ELKS,
+ * Copyright (C) 1995, 1996 Nat Friedman .
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+int main(int argc, char **argv)
+{
+	struct passwd *passwd;
+	int test_uid;
+
+	fprintf(stdout, "Beginning test of libc/pwd...\n");
+
+	fprintf(stdout, "=> Testing setpwent(), getpwent(), endpwent()...\n");
+	fprintf(stdout, "-> setpwent()...\n");
+	setpwent();
+	fprintf(stdout, "-> getpwent()...\n");
+	printf
+		("********************************************************************************\n");
+	while ((passwd = getpwent()) != NULL) {
+		printf("pw_name\t\t: %s\n", passwd->pw_name);
+		printf("pw_passwd\t: %s\n", passwd->pw_passwd);
+		printf("pw_uid\t\t: %d\n", (int) passwd->pw_uid);
+		printf("pw_gid\t\t: %d\n", (int) passwd->pw_gid);
+		printf("pw_gecos\t: %s\n", passwd->pw_gecos);
+		printf("pw_dir\t\t: %s\n", passwd->pw_dir);
+		printf("pw_shell\t: %s\n", passwd->pw_shell);
+		printf
+			("********************************************************************************\n");
+	}
+	fprintf(stdout, "-> endpwent()...\n");
+	endpwent();
+	fprintf(stdout,
+			"=> Test of setpwent(), getpwent(), endpwent() complete.\n");
+	fprintf(stdout, "=> Testing getpwuid(), getpwnam()...\n");
+	fprintf(stdout, "-> getpwuid()...\n");
+	printf
+		("********************************************************************************\n");
+	for (test_uid = 0; test_uid < 1000; test_uid++) {
+		fprintf(stdout, "-> getpwuid(%d)...\n", test_uid);
+		passwd = getpwuid((uid_t) test_uid);
+		if (passwd != NULL) {
+			printf("pw_name\t\t: %s\n", passwd->pw_name);
+			printf("pw_passwd\t: %s\n", passwd->pw_passwd);
+			printf("pw_uid\t\t: %d\n", (int) passwd->pw_uid);
+			printf("pw_gid\t\t: %d\n", (int) passwd->pw_gid);
+			printf("pw_gecos\t: %s\n", passwd->pw_gecos);
+			printf("pw_dir\t\t: %s\n", passwd->pw_dir);
+			printf("pw_shell\t: %s\n", passwd->pw_shell);
+			printf
+				("********************************************************************************\n");
+		}
+	}
+	fprintf(stdout, "-> getpwnam()...\n");
+	passwd = getpwnam("root");
+	if (passwd == NULL) {
+		printf(">NULL<\n");
+	} else {
+		printf("pw_name\t\t: %s\n", passwd->pw_name);
+		printf("pw_passwd\t: %s\n", passwd->pw_passwd);
+		printf("pw_uid\t\t: %d\n", (int) passwd->pw_uid);
+		printf("pw_gid\t\t: %d\n", (int) passwd->pw_gid);
+		printf("pw_gecos\t: %s\n", passwd->pw_gecos);
+		printf("pw_dir\t\t: %s\n", passwd->pw_dir);
+		printf("pw_shell\t: %s\n", passwd->pw_shell);
+	}
+	return 0;
+}
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/regex/LICENSE b/l4/pkg/uclibc/lib/contrib/uclibc/test/regex/LICENSE
new file mode 100644
index 00000000..2e5acb9c
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/regex/LICENSE
@@ -0,0 +1,72 @@
+From gsf@research.att.com  Wed Mar  1 20:30:54 2006
+Return-Path: 
+X-Original-To: mps@bridge.intra
+Delivered-To: mps@bridge.intra
+Received: from localhost (localhost [127.0.0.1])
+	by localhost (Postfix) with ESMTP id B8C814E4F
+	for ; Wed,  1 Mar 2006 20:30:53 +0100 (CET)
+Received: from mail.bridge.intra ([127.0.0.1])
+ by localhost (lnx.bridge.intra [127.0.0.1]) (amavisd-new, port 10024)
+ with LMTP id 05987-03 for ;
+ Wed,  1 Mar 2006 20:30:42 +0100 (CET)
+Received: from pop.gmx.net (localhost [127.0.0.1])
+	by mail.bridge.intra (Postfix) with ESMTP id C8C73794D
+	for ; Wed,  1 Mar 2006 20:30:38 +0100 (CET)
+X-Flags: 0000
+Delivered-To: GMX delivery to ps.m@gmx.net
+Received: (qmail invoked by alias); 01 Mar 2006 19:23:46 -0000
+Received: from mail-red.research.att.com (EHLO mail-white.research.att.com) [192.20.225.110]
+  by mx0.gmx.net (mx085) with SMTP; 01 Mar 2006 20:23:46 +0100
+Received: from raptor.research.att.com (raptor.research.att.com [135.207.23.32])
+	by mail-blue.research.att.com (Postfix) with ESMTP id B7929147CBB
+	for ; Wed,  1 Mar 2006 14:23:45 -0500 (EST)
+Received: (from gsf@localhost)
+	by raptor.research.att.com (SGI-8.9.3p2/8.8.7) id OAA86112
+	for ps.m@gmx.net; Wed, 1 Mar 2006 14:23:45 -0500 (EST)
+Date: Wed, 1 Mar 2006 14:23:45 -0500 (EST)
+From: Glenn Fowler 
+Message-Id: <200603011923.OAA86112@raptor.research.att.com>
+Organization: AT&T Research
+X-Mailer: mailx (AT&T/BSD) 9.9 2005-04-21
+Mime-Version: 1.0
+Content-Type: text/plain; charset=us-ascii
+Content-Transfer-Encoding: 7bit
+References: 
+To: mps@bridge.intra
+Subject: Re: testregex licensing question
+X-GMX-Antivirus: -1 (not scanned, may not use virus scanner)
+X-GMX-Antispam: 0 (Mail was not recognized as spam)
+X-GMX-UID: lJF3ZO9DeSEkJ2TcbHQhaXN1IGRvb0Ca
+X-Virus-Scanned: by amavisd-new at localhost
+Status: RO
+X-Status: 
+X-Keywords:                 
+X-UID: 44736
+
+
+you may include it directly
+retain the testregex.c header comment
+it uses a very free license to maximize distribution
+you can copy that .c comment to any test data files you use
+using # comment style to be complete
+
+let me know how it works with your libc
+also pass on any new tests you cook up
+
+On Wed, 1 Mar 2006 20:15:02 +0100 (CET) Peter S. Mazinger wrote:
+> Hello Glenn!
+
+> I would want to add testregex.c and the related *.dat files to the uClibc 
+> testsuite. uClibc is licensed under LGPL v2.1. I haven't found any 
+> licensing related info on testregex.
+
+> Is it allowed to use the code there, or should I accomodate the testsuite 
+> to download the needed files from the original site each time it is ran?
+
+> Thanks, Peter
+
+> -- 
+> Peter S. Mazinger            ID: 0xA5F059F2
+> Key fingerprint = 92A4 31E1 56BC 3D5A 2D08  BB6E C389 975E A5F0 59F2
+
+
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/regex/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/test/regex/Makefile
new file mode 100644
index 00000000..63912221
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/regex/Makefile
@@ -0,0 +1,7 @@
+# uClibc regex tests
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+
+top_builddir=../../
+include ../Rules.mak
+-include Makefile.in
+include ../Test.mak
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/regex/basic.dat b/l4/pkg/uclibc/lib/contrib/uclibc/test/regex/basic.dat
new file mode 100644
index 00000000..5c50f37b
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/regex/basic.dat
@@ -0,0 +1,216 @@
+NOTE	all standard compliant implementations should pass these : 2002-05-31
+
+BE	abracadabra$	abracadabracadabra	(7,18)
+BE	a...b		abababbb		(2,7)
+BE	XXXXXX		..XXXXXX		(2,8)
+E	\)		()	(1,2)
+BE	a]		a]a	(0,2)
+B	}		}	(0,1)
+E	\}		}	(0,1)
+BE	\]		]	(0,1)
+B	]		]	(0,1)
+E	]		]	(0,1)
+B	{		{	(0,1)
+B	}		}	(0,1)
+BE	^a		ax	(0,1)
+BE	\^a		a^a	(1,3)
+BE	a\^		a^	(0,2)
+BE	a$		aa	(1,2)
+BE	a\$		a$	(0,2)
+BE	^$		NULL	(0,0)
+E	$^		NULL	(0,0)
+E	a($)		aa	(1,2)(2,2)
+E	a*(^a)		aa	(0,1)(0,1)
+E	(..)*(...)*		a	(0,0)
+E	(..)*(...)*		abcd	(0,4)(2,4)
+E	(ab|a)(bc|c)		abc	(0,3)(0,2)(2,3)
+E	(ab)c|abc		abc	(0,3)(0,2)
+E	a{0}b		ab			(1,2)
+E	(a*)(b?)(b+)b{3}	aaabbbbbbb	(0,10)(0,3)(3,4)(4,7)
+E	(a*)(b{0,1})(b{1,})b{3}	aaabbbbbbb	(0,10)(0,3)(3,4)(4,7)
+E	a{9876543210}	NULL	BADBR
+E	((a|a)|a)			a	(0,1)(0,1)(0,1)
+E	(a*)(a|aa)			aaaa	(0,4)(0,3)(3,4)
+E	a*(a.|aa)			aaaa	(0,4)(2,4)
+E	a(b)|c(d)|a(e)f			aef	(0,3)(?,?)(?,?)(1,2)
+E	(a|b)?.*			b	(0,1)(0,1)
+E	(a|b)c|a(b|c)			ac	(0,2)(0,1)
+E	(a|b)c|a(b|c)			ab	(0,2)(?,?)(1,2)
+E	(a|b)*c|(a|ab)*c		abc	(0,3)(1,2)
+E	(a|b)*c|(a|ab)*c		xc	(1,2)
+E	(.a|.b).*|.*(.a|.b)		xa	(0,2)(0,2)
+E	a?(ab|ba)ab			abab	(0,4)(0,2)
+E	a?(ac{0}b|ba)ab			abab	(0,4)(0,2)
+E	ab|abab				abbabab	(0,2)
+E	aba|bab|bba			baaabbbaba	(5,8)
+E	aba|bab				baaabbbaba	(6,9)
+E	(aa|aaa)*|(a|aaaaa)		aa	(0,2)(0,2)
+E	(a.|.a.)*|(a|.a...)		aa	(0,2)(0,2)
+E	ab|a				xabc	(1,3)
+E	ab|a				xxabc	(2,4)
+Ei	(Ab|cD)*			aBcD	(0,4)(2,4)
+BE	[^-]			--a		(2,3)
+BE	[a-]*			--a		(0,3)
+BE	[a-m-]*			--amoma--	(0,4)
+E	:::1:::0:|:::1:1:0:	:::0:::1:::1:::0:	(8,17)
+E	:::1:::0:|:::1:1:1:	:::0:::1:::1:::0:	(8,17)
+{E	[[:upper:]]		A		(0,1)	[[]] not supported
+E	[[:lower:]]+		`az{		(1,3)
+E	[[:upper:]]+		@AZ[		(1,3)
+BE	[[-]]			[[-]]		(2,4)
+BE	[[.NIL.]]	NULL	ECOLLATE
+BE	[[=aleph=]]	NULL	ECOLLATE
+}
+BE$	\n		\n	(0,1)
+BEn$	\n		\n	(0,1)
+BE$	[^a]		\n	(0,1)
+BE$	\na		\na	(0,2)
+E	(a)(b)(c)	abc	(0,3)(0,1)(1,2)(2,3)
+BE	xxx		xxx	(0,3)
+E1	(^|[ (,;])((([Ff]eb[^ ]* *|0*2/|\* */?)0*[6-7]))([^0-9]|$)	feb 6,	(0,6)
+E1	(^|[ (,;])((([Ff]eb[^ ]* *|0*2/|\* */?)0*[6-7]))([^0-9]|$)	2/7	(0,3)
+E1	(^|[ (,;])((([Ff]eb[^ ]* *|0*2/|\* */?)0*[6-7]))([^0-9]|$)	feb 1,Feb 6	(5,11)
+E3	((((((((((((((((((((((((((((((x))))))))))))))))))))))))))))))	x	(0,1)(0,1)(0,1)
+E3	((((((((((((((((((((((((((((((x))))))))))))))))))))))))))))))*	xx	(0,2)(1,2)(1,2)
+E	a?(ab|ba)*	ababababababababababababababababababababababababababababababababababababababababa	(0,81)(79,81)
+E	abaa|abbaa|abbbaa|abbbbaa	ababbabbbabbbabbbbabbbbaa	(18,25)
+E	abaa|abbaa|abbbaa|abbbbaa	ababbabbbabbbabbbbabaa	(18,22)
+E	aaac|aabc|abac|abbc|baac|babc|bbac|bbbc	baaabbbabac	(7,11)
+BE$	.*			\x01\xff	(0,2)
+E	aaaa|bbbb|cccc|ddddd|eeeeee|fffffff|gggg|hhhh|iiiii|jjjjj|kkkkk|llll		XaaaXbbbXcccXdddXeeeXfffXgggXhhhXiiiXjjjXkkkXlllXcbaXaaaa	(53,57)
+L	aaaa\nbbbb\ncccc\nddddd\neeeeee\nfffffff\ngggg\nhhhh\niiiii\njjjjj\nkkkkk\nllll		XaaaXbbbXcccXdddXeeeXfffXgggXhhhXiiiXjjjXkkkXlllXcbaXaaaa	NOMATCH
+E	a*a*a*a*a*b		aaaaaaaaab	(0,10)
+BE	^			NULL		(0,0)
+BE	$			NULL		(0,0)
+BE	^$			NULL		(0,0)
+BE	^a$			a		(0,1)
+BE	abc			abc		(0,3)
+BE	abc			xabcy		(1,4)
+BE	abc			ababc		(2,5)
+BE	ab*c			abc		(0,3)
+BE	ab*bc			abc		(0,3)
+BE	ab*bc			abbc		(0,4)
+BE	ab*bc			abbbbc		(0,6)
+E	ab+bc			abbc		(0,4)
+E	ab+bc			abbbbc		(0,6)
+E	ab?bc			abbc		(0,4)
+E	ab?bc			abc		(0,3)
+E	ab?c			abc		(0,3)
+BE	^abc$			abc		(0,3)
+BE	^abc			abcc		(0,3)
+BE	abc$			aabc		(1,4)
+BE	^			abc		(0,0)
+BE	$			abc		(3,3)
+BE	a.c			abc		(0,3)
+BE	a.c			axc		(0,3)
+BE	a.*c			axyzc		(0,5)
+BE	a[bc]d			abd		(0,3)
+BE	a[b-d]e			ace		(0,3)
+BE	a[b-d]			aac		(1,3)
+BE	a[-b]			a-		(0,2)
+BE	a[b-]			a-		(0,2)
+BE	a]			a]		(0,2)
+BE	a[]]b			a]b		(0,3)
+BE	a[^bc]d			aed		(0,3)
+BE	a[^-b]c			adc		(0,3)
+BE	a[^]b]c			adc		(0,3)
+E	ab|cd			abc		(0,2)
+E	ab|cd			abcd		(0,2)
+E	a\(b			a(b		(0,3)
+E	a\(*b			ab		(0,2)
+E	a\(*b			a((b		(0,4)
+E	((a))			abc		(0,1)(0,1)(0,1)
+E	(a)b(c)			abc		(0,3)(0,1)(2,3)
+E	a+b+c			aabbabc		(4,7)
+E	a*			aaa		(0,3)
+E	(a*)*			-		(0,0)(0,0)
+E	(a*)+			-		(0,0)(0,0)
+E	(a*|b)*			-		(0,0)(0,0)
+E	(a+|b)*			ab		(0,2)(1,2)
+E	(a+|b)+			ab		(0,2)(1,2)
+E	(a+|b)?			ab		(0,1)(0,1)
+BE	[^ab]*			cde		(0,3)
+E	(^)*			-		(0,0)(0,0)
+BE	a*			NULL		(0,0)
+E	([abc])*d		abbbcd		(0,6)(4,5)
+E	([abc])*bcd		abcd		(0,4)(0,1)
+E	a|b|c|d|e		e		(0,1)
+E	(a|b|c|d|e)f		ef		(0,2)(0,1)
+E	((a*|b))*		-		(0,0)(0,0)(0,0)
+BE	abcd*efg		abcdefg		(0,7)
+BE	ab*			xabyabbbz	(1,3)
+BE	ab*			xayabbbz	(1,2)
+E	(ab|cd)e		abcde		(2,5)(2,4)
+BE	[abhgefdc]ij		hij		(0,3)
+E	(a|b)c*d		abcd		(1,4)(1,2)
+E	(ab|ab*)bc		abc		(0,3)(0,1)
+E	a([bc]*)c*		abc		(0,3)(1,3)
+E	a([bc]*)(c*d)		abcd		(0,4)(1,3)(3,4)
+E	a([bc]+)(c*d)		abcd		(0,4)(1,3)(3,4)
+E	a([bc]*)(c+d)		abcd		(0,4)(1,2)(2,4)
+E	a[bcd]*dcdcde		adcdcde		(0,7)
+E	(ab|a)b*c		abc		(0,3)(0,2)
+E	((a)(b)c)(d)		abcd		(0,4)(0,3)(0,1)(1,2)(3,4)
+BE	[A-Za-z_][A-Za-z0-9_]*	alpha		(0,5)
+E	^a(bc+|b[eh])g|.h$	abh		(1,3)
+E	(bc+d$|ef*g.|h?i(j|k))	effgz		(0,5)(0,5)
+E	(bc+d$|ef*g.|h?i(j|k))	ij		(0,2)(0,2)(1,2)
+E	(bc+d$|ef*g.|h?i(j|k))	reffgz		(1,6)(1,6)
+E	(((((((((a)))))))))	a		(0,1)(0,1)(0,1)(0,1)(0,1)(0,1)(0,1)(0,1)(0,1)(0,1)
+BE	multiple words		multiple words yeah	(0,14)
+E	(.*)c(.*)		abcde		(0,5)(0,2)(3,5)
+BE	abcd			abcd		(0,4)
+E	a(bc)d			abcd		(0,4)(1,3)
+E	a[-]?c		ac		(0,3)
+E	M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]	Muammar Qaddafi	(0,15)(?,?)(10,12)
+E	M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]	Mo'ammar Gadhafi	(0,16)(?,?)(11,13)
+E	M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]	Muammar Kaddafi	(0,15)(?,?)(10,12)
+E	M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]	Muammar Qadhafi	(0,15)(?,?)(10,12)
+E	M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]	Muammar Gadafi	(0,14)(?,?)(10,11)
+E	M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]	Mu'ammar Qadafi	(0,15)(?,?)(11,12)
+E	M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]	Moamar Gaddafi	(0,14)(?,?)(9,11)
+E	M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]	Mu'ammar Qadhdhafi	(0,18)(?,?)(13,15)
+E	M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]	Muammar Khaddafi	(0,16)(?,?)(11,13)
+E	M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]	Muammar Ghaddafy	(0,16)(?,?)(11,13)
+E	M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]	Muammar Ghadafi	(0,15)(?,?)(11,12)
+E	M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]	Muammar Ghaddafi	(0,16)(?,?)(11,13)
+E	M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]	Muamar Kaddafi	(0,14)(?,?)(9,11)
+E	M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]	Muammar Quathafi	(0,16)(?,?)(11,13)
+E	M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]	Muammar Gheddafi	(0,16)(?,?)(11,13)
+E	M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]	Moammar Khadafy	(0,15)(?,?)(11,12)
+E	M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy]	Moammar Qudhafi	(0,15)(?,?)(10,12)
+E	a+(b|c)*d+		aabcdd			(0,6)(3,4)
+E	^.+$			vivi			(0,4)
+E	^(.+)$			vivi			(0,4)(0,4)
+E	^([^!.]+).att.com!(.+)$	gryphon.att.com!eby	(0,19)(0,7)(16,19)
+E	^([^!]+!)?([^!]+)$	bas			(0,3)(?,?)(0,3)
+E	^([^!]+!)?([^!]+)$	bar!bas			(0,7)(0,4)(4,7)
+E	^([^!]+!)?([^!]+)$	foo!bas			(0,7)(0,4)(4,7)
+E	^.+!([^!]+!)([^!]+)$	foo!bar!bas		(0,11)(4,8)(8,11)
+E	((foo)|(bar))!bas	bar!bas			(0,7)(0,3)(?,?)(0,3)
+E	((foo)|(bar))!bas	foo!bar!bas		(4,11)(4,7)(?,?)(4,7)
+E	((foo)|(bar))!bas	foo!bas			(0,7)(0,3)(0,3)
+E	((foo)|bar)!bas		bar!bas			(0,7)(0,3)
+E	((foo)|bar)!bas		foo!bar!bas		(4,11)(4,7)
+E	((foo)|bar)!bas		foo!bas			(0,7)(0,3)(0,3)
+E	(foo|(bar))!bas		bar!bas			(0,7)(0,3)(0,3)
+E	(foo|(bar))!bas		foo!bar!bas		(4,11)(4,7)(4,7)
+E	(foo|(bar))!bas		foo!bas			(0,7)(0,3)
+E	(foo|bar)!bas		bar!bas			(0,7)(0,3)
+E	(foo|bar)!bas		foo!bar!bas		(4,11)(4,7)
+E	(foo|bar)!bas		foo!bas			(0,7)(0,3)
+E	^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$	foo!bar!bas	(0,11)(0,11)(?,?)(?,?)(4,8)(8,11)
+E	^([^!]+!)?([^!]+)$|^.+!([^!]+!)([^!]+)$	bas		(0,3)(?,?)(0,3)
+E	^([^!]+!)?([^!]+)$|^.+!([^!]+!)([^!]+)$	bar!bas		(0,7)(0,4)(4,7)
+E	^([^!]+!)?([^!]+)$|^.+!([^!]+!)([^!]+)$	foo!bar!bas	(0,11)(?,?)(?,?)(4,8)(8,11)
+E	^([^!]+!)?([^!]+)$|^.+!([^!]+!)([^!]+)$	foo!bas		(0,7)(0,4)(4,7)
+E	^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$	bas		(0,3)(0,3)(?,?)(0,3)
+E	^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$	bar!bas		(0,7)(0,7)(0,4)(4,7)
+E	^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$	foo!bar!bas	(0,11)(0,11)(?,?)(?,?)(4,8)(8,11)
+E	^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$	foo!bas		(0,7)(0,7)(0,4)(4,7)
+E	.*(/XXX).*			/XXX			(0,4)(0,4)
+E	.*(\\XXX).*			\XXX			(0,4)(0,4)
+E	\\XXX				\XXX			(0,4)
+E	.*(/000).*			/000			(0,4)(0,4)
+E	.*(\\000).*			\000			(0,4)(0,4)
+E	\\000				\000			(0,4)
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/regex/categorize.dat b/l4/pkg/uclibc/lib/contrib/uclibc/test/regex/categorize.dat
new file mode 100644
index 00000000..d3485127
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/regex/categorize.dat
@@ -0,0 +1,62 @@
+NOTE	regex implementation categorization 2004-05-31
+
+?E	aa*			xaxaax	(1,2)					POSITION=leftmost
+;										POSITION=bug
+
+?E	(a*)(ab)*(b*)		abc	(0,2)(0,1)(?,?)(1,2)			ASSOCIATIVITY=right
+|E	(a*)(ab)*(b*)		abc	(0,2)(0,0)(0,2)(2,2)			ASSOCIATIVITY=left
+;										ASSOCIATIVITY=bug
+
+?E	((a*)(ab)*)((b*)(a*))	aba	(0,3)(0,2)(0,0)(0,2)(2,3)(2,2)(2,3)	SUBEXPRESSION=precedence
+|E	((a*)(ab)*)((b*)(a*))	aba	(0,3)(0,1)(0,1)(?,?)(1,3)(1,2)(2,3)	SUBEXPRESSION=grouping
+;										SUBEXPRESSION=bug
+
+?E	(...?.?)*		xxxxxx	(0,6)(4,6)				REPEAT_LONGEST=first
+|E	(...?.?)*		xxxxxx	(0,6)(2,6)				REPEAT_LONGEST=last
+|E	(...?.?)*		xxxxxx	OK					REPEAT_LONGEST=unknown
+;										REPEAT_LONGEST=bug
+
+?E	(a|ab)(bc|c)		abcabc	(0,3)(0,2)(2,3)				EXPECTED
+|E	(a|ab)(bc|c)		abcabc	(0,3)(0,1)(1,3)				BUG=alternation-order
+;										BUG=alternation-order-UNKNOWN
+
+?E	(aba|a*b)(aba|a*b)	ababa	(0,5)(0,2)(2,5)				EXPECTED
+|E	(aba|a*b)(aba|a*b)	ababa	(0,4)(0,3)(3,4)				BUG=first-match
+;										BUG=unknown-match
+
+?B	a\(b\)*\1		a	NOMATCH					EXPECTED
+|B	a\(b\)*\1		a	(0,1)					BUG=nomatch-match
+|B	a\(b\)*\1		abab	(0,2)(1,2)				# BUG=repeat-any
+;										BUG=nomatch-match-UNKNOWN
+
+?E	(a*){2}			xxxxx	(0,0)(0,0)				EXPECTED
+|E	(a*){2}			xxxxx	(5,5)(5,5)				BUG=range-null
+;										BUG=range-null-UNKNOWN
+
+?B	a\(b\)*\1		abab	NOMATCH					EXPECTED
+|B	a\(b\)*\1		abab	(0,1)					# BUG=nomatch-match
+|B	a\(b\)*\1		abab	(0,2)(1,2)				BUG=repeat-any
+;										BUG=repeat-any-UNKNOWN
+
+?E	(a*)*			a	(0,1)(0,1)				EXPECTED
+|E	(a*)*			ax	(0,1)(0,1)				BUG=repeat-null-unknown
+|E	(a*)*			a	(0,1)(1,1)				BUG=repeat-null
+;										BUG=repeat-null-UNKNOWN
+
+?E	(aba|a*b)*		ababa	(0,5)(2,5)				EXPECTED
+|E	(aba|a*b)*		ababa	(0,5)(3,4)				BUG=repeat-short
+|E	(aba|a*b)*		ababa	(0,4)(3,4)				# LENGTH=first
+;										BUG=repeat-short-UNKNOWN
+
+?E	(a(b)?)+		aba	(0,3)(2,3)				EXPECTED
+|E	(a(b)?)+		aba	(0,3)(2,3)(1,2)				BUG=repeat-artifact
+;										BUG=repeat-artifact-UNKNOWN
+
+?B	\(a\(b\)*\)*\2		abab	NOMATCH					EXPECTED
+|B	\(a\(b\)*\)*\2		abab	(0,4)(2,3)(1,2)				BUG=repeat-artifact-nomatch
+;										BUG=repeat-artifact-nomatch-UNKNOWN
+
+?E	(a?)((ab)?)(b?)a?(ab)?b?	abab	(0,4)(0,1)(1,1)(?,?)(1,2)(2,4)	BUG=subexpression-first
+|E	.*(.*)				ab	(0,2)(2,2)			EXPECTED
+|E	.*(.*)				ab	(0,2)(0,2)			BUG=subexpression-first
+;										BUG=subexpression-first-UNKNOWN
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/regex/forcedassoc.dat b/l4/pkg/uclibc/lib/contrib/uclibc/test/regex/forcedassoc.dat
new file mode 100644
index 00000000..39f3111d
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/regex/forcedassoc.dat
@@ -0,0 +1,30 @@
+NOTE	left-assoc:pass-all right-assoc:pass-all : 2002-04-29
+
+E	(a|ab)(c|bcd)		abcd	(0,4)(0,1)(1,4)
+E	(a|ab)(bcd|c)		abcd	(0,4)(0,1)(1,4)
+E	(ab|a)(c|bcd)		abcd	(0,4)(0,1)(1,4)
+E	(ab|a)(bcd|c)		abcd	(0,4)(0,1)(1,4)
+E	((a|ab)(c|bcd))(d*)	abcd	(0,4)(0,4)(0,1)(1,4)(4,4)
+E	((a|ab)(bcd|c))(d*)	abcd	(0,4)(0,4)(0,1)(1,4)(4,4)
+E	((ab|a)(c|bcd))(d*)	abcd	(0,4)(0,4)(0,1)(1,4)(4,4)
+E	((ab|a)(bcd|c))(d*)	abcd	(0,4)(0,4)(0,1)(1,4)(4,4)
+E	(a|ab)((c|bcd)(d*))	abcd	(0,4)(0,2)(2,4)(2,3)(3,4)
+E	(a|ab)((bcd|c)(d*))	abcd	(0,4)(0,2)(2,4)(2,3)(3,4)
+E	(ab|a)((c|bcd)(d*))	abcd	(0,4)(0,2)(2,4)(2,3)(3,4)
+E	(ab|a)((bcd|c)(d*))	abcd	(0,4)(0,2)(2,4)(2,3)(3,4)
+E	(a*)(b|abc)		abc	(0,3)(0,0)(0,3)
+E	(a*)(abc|b)		abc	(0,3)(0,0)(0,3)
+E	((a*)(b|abc))(c*)	abc	(0,3)(0,3)(0,0)(0,3)(3,3)
+E	((a*)(abc|b))(c*)	abc	(0,3)(0,3)(0,0)(0,3)(3,3)
+E	(a*)((b|abc)(c*))	abc	(0,3)(0,1)(1,3)(1,2)(2,3)
+E	(a*)((abc|b)(c*))	abc	(0,3)(0,1)(1,3)(1,2)(2,3)
+E	(a*)(b|abc)		abc	(0,3)(0,0)(0,3)
+E	(a*)(abc|b)		abc	(0,3)(0,0)(0,3)
+E	((a*)(b|abc))(c*)	abc	(0,3)(0,3)(0,0)(0,3)(3,3)
+E	((a*)(abc|b))(c*)	abc	(0,3)(0,3)(0,0)(0,3)(3,3)
+E	(a*)((b|abc)(c*))	abc	(0,3)(0,1)(1,3)(1,2)(2,3)
+E	(a*)((abc|b)(c*))	abc	(0,3)(0,1)(1,3)(1,2)(2,3)
+E	(a|ab)			ab	(0,2)(0,2)
+E	(ab|a)			ab	(0,2)(0,2)
+E	(a|ab)(b*)		ab	(0,2)(0,2)(2,2)
+E	(ab|a)(b*)		ab	(0,2)(0,2)(2,2)
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/regex/interpretation.dat b/l4/pkg/uclibc/lib/contrib/uclibc/test/regex/interpretation.dat
new file mode 100644
index 00000000..72e186eb
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/regex/interpretation.dat
@@ -0,0 +1,93 @@
+:RE#01:E	a+			xaax	(1,3)
+:RE#02:B	.\(a*\).		xaax	(0,4)(1,3)
+:RE#03:E	(a?)((ab)?)		ab	(0,2)(0,0)(0,2)(0,2)
+:RE#04:E	(a?)((ab)?)(b?)		ab	(0,2)(0,1)(1,1)(?,?)(1,2)
+:RE#05:E	((a?)((ab)?))(b?)	ab	(0,2)(0,2)(0,0)(0,2)(0,2)(2,2)
+:RE#06:E	(a?)(((ab)?)(b?))	ab	(0,2)(0,1)(1,2)(1,1)(?,?)(1,2)
+:RE#07:E	(.?)			x	(0,1)(0,1)
+:RE#08:E	(.?){1}			x	(0,1)(0,1)
+:RE#09:E	(.?)(.?)		x	(0,1)(0,1)(1,1)
+:RE#10:E	(.?){2}			x	(0,1)(1,1)
+:RE#11:E	(.?)*			x	(0,1)(0,1)
+:RE#12:E	(.?.?)			xxx	(0,2)(0,2)
+:RE#13:E	(.?.?){1}		xxx	(0,2)(0,2)
+:RE#14:E	(.?.?)(.?.?)		xxx	(0,3)(0,2)(2,3)
+:RE#15:E	(.?.?){2}		xxx	(0,3)(2,3)
+:RE#16:E	(.?.?)(.?.?)(.?.?)	xxx	(0,3)(0,2)(2,3)(3,3)
+:RE#17:E	(.?.?){3}		xxx	(0,3)(3,3)
+:RE#18:E	(.?.?)*			xxx	(0,3)(2,3)
+:RE#19:E	a?((ab)?)(b?)		ab	(0,2)(1,1)(?,?)(1,2)
+:RE#20:E	(a?)((ab)?)b?		ab	(0,2)(0,1)(1,1)(?,?)
+:RE#21:E	a?((ab)?)b?		ab	(0,2)(1,1)(?,?)
+:RE#22:E	(a*){2}			xxxxx	(0,0)(0,0)
+:RE#23:E	(ab?)(b?a)		aba	(0,3)(0,2)(2,3)
+:RE#24:E	(a|ab)(ba|a)		aba	(0,3)(0,2)(2,3)
+:RE#25:E	(a|ab|ba)		aba	(0,2)(0,2)
+:RE#26:E	(a|ab|ba)(a|ab|ba)	aba	(0,3)(0,2)(2,3)
+:RE#27:E	(a|ab|ba)*		aba	(0,3)(2,3)
+:RE#28:E	(aba|a*b)		ababa	(0,3)(0,3)
+:RE#29:E	(aba|a*b)(aba|a*b)	ababa	(0,5)(0,2)(2,5)
+:RE#30:E	(aba|a*b)*		ababa	(0,5)(2,5)
+:RE#31:E	(aba|ab|a)		ababa	(0,3)(0,3)
+:RE#32:E	(aba|ab|a)(aba|ab|a)	ababa	(0,5)(0,2)(2,5)
+:RE#33:E	(aba|ab|a)*		ababa	(0,5)(2,5)
+:RE#34:E	(a(b)?)			aba	(0,2)(0,2)(1,2)
+:RE#35:E	(a(b)?)(a(b)?)		aba	(0,3)(0,2)(1,2)(2,3)(?,?)
+:RE#36:E	(a(b)?)+		aba	(0,3)(2,3)(?,?)
+:RE#37:E	(.*)(.*)		xx	(0,2)(0,2)(2,2)
+:RE#38:E	.*(.*)			xx	(0,2)(2,2)
+:RE#39:E	(a.*z|b.*y)		azbazby	(0,5)(0,5)
+:RE#40:E	(a.*z|b.*y)(a.*z|b.*y)	azbazby	(0,7)(0,5)(5,7)
+:RE#41:E	(a.*z|b.*y)*		azbazby	(0,7)(5,7)
+:RE#42:E	(.|..)(.*)		ab	(0,2)(0,2)(2,2)
+:RE#43:E	((..)*(...)*)			xxx		(0,3)(0,3)(?,?)(0,3)
+:RE#44:E	((..)*(...)*)((..)*(...)*)	xxx		(0,3)(0,3)(?,?)(0,3)(3,3)(?,?)
+:RE#45:E	((..)*(...)*)*			xxx		(0,3)(0,3)(?,?)(0,3)
+:RE#46:B	\(a\{0,1\}\)*b\1	ab	(0,2)(1,1)
+:RE#47:B	\(a*\)*b\1		ab	(0,2)(1,1)
+:RE#48:B	\(a*\)b\1*		ab	(0,2)(0,1)
+:RE#49:B	\(a*\)*b\1*		ab	(0,2)(1,1)
+:RE#50:B	\(a\{0,1\}\)*b\(\1\)	ab	(0,2)(1,1)(2,2)
+:RE#51:B	\(a*\)*b\(\1\)		ab	(0,2)(1,1)(2,2)
+:RE#52:B	\(a*\)b\(\1\)*		ab	(0,2)(0,1)(?,?)
+:RE#53:B	\(a*\)*b\(\1\)*		ab	(0,2)(1,1)(2,2)
+:RE#54:B	\(a\{0,1\}\)*b\1	aba	(0,3)(0,1)
+:RE#55:B	\(a*\)*b\1		aba	(0,3)(0,1)
+:RE#56:B	\(a*\)b\1*		aba	(0,3)(0,1)
+:RE#57:B	\(a*\)*b\1*		aba	(0,3)(0,1)
+:RE#58:B	\(a*\)*b\(\1\)*		aba	(0,3)(0,1)(2,3)
+:RE#59:B	\(a\{0,1\}\)*b\1	abaa	(0,3)(0,1)
+:RE#60:B	\(a*\)*b\1		abaa	(0,3)(0,1)
+:RE#61:B	\(a*\)b\1*		abaa	(0,4)(0,1)
+:RE#62:B	\(a*\)*b\1*		abaa	(0,4)(0,1)
+:RE#63:B	\(a*\)*b\(\1\)*		abaa	(0,4)(0,1)(3,4)
+:RE#64:B	\(a\{0,1\}\)*b\1	aab	(0,3)(2,2)
+:RE#65:B	\(a*\)*b\1		aab	(0,3)(2,2)
+:RE#66:B	\(a*\)b\1*		aab	(0,3)(0,2)
+:RE#67:B	\(a*\)*b\1*		aab	(0,3)(2,2)
+:RE#68:B	\(a*\)*b\(\1\)*		aab	(0,3)(2,2)(3,3)
+:RE#69:B	\(a\{0,1\}\)*b\1	aaba	(0,4)(1,2)
+:RE#70:B	\(a*\)*b\1		aaba	(0,4)(1,2)
+:RE#71:B	\(a*\)b\1*		aaba	(0,3)(0,2)
+:RE#72:B	\(a*\)*b\1*		aaba	(0,4)(1,2)
+:RE#73:B	\(a*\)*b\(\1\)*		aaba	(0,4)(1,2)(3,4)
+:RE#74:B	\(a\{0,1\}\)*b\1	aabaa	(0,4)(1,2)
+:RE#75:B	\(a*\)*b\1		aabaa	(0,5)(0,2)
+:RE#76:B	\(a*\)b\1*		aabaa	(0,5)(0,2)
+:RE#77:B	\(a*\)*b\1*		aabaa	(0,5)(0,2)
+:RE#78:B	\(a*\)*b\(\1\)*		aabaa	(0,5)(0,2)(3,5)
+:RE#79:B	\(x\)*a\1		a	NOMATCH
+:RE#80:B	\(x\)*a\1*		a	(0,1)(?,?)
+:RE#81:B	\(x\)*a\(\1\)		a	NOMATCH
+:RE#82:B	\(x\)*a\(\1\)*		a	(0,1)(?,?)(?,?)
+:RE#83:E	(aa(b(b))?)+		aabbaa	(0,6)(4,6)(?,?)(?,?)
+:RE#84:E	(a(b)?)+		aba	(0,3)(2,3)(?,?)
+:RE#85:E	([ab]+)([bc]+)([cd]*)		abcd		(0,4)(0,2)(2,3)(3,4)
+:RE#86:B	\([ab]*\)\([bc]*\)\([cd]*\)\1	abcdaa		(0,5)(0,1)(1,3)(3,4)
+:RE#87:B	\([ab]*\)\([bc]*\)\([cd]*\)\1	abcdab		(0,6)(0,2)(2,3)(3,4)
+:RE#88:B	\([ab]*\)\([bc]*\)\([cd]*\)\1*	abcdaa		(0,6)(0,1)(1,3)(3,4)
+:RE#89:B	\([ab]*\)\([bc]*\)\([cd]*\)\1*	abcdab		(0,6)(0,2)(2,3)(3,4)
+:RE#90:E	^(A([^B]*))?(B(.*))?		Aa		(0,2)(0,2)(1,2)
+:RE#91:E	^(A([^B]*))?(B(.*))?		Bb		(0,2)(?,?)(?,?)(0,2)(1,2)
+:RE#92:B	.*\([AB]\).*\1			ABA		(0,3)(0,1)
+:RE#93:B$	[^A]*A				\nA		(0,2)
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/regex/leftassoc.dat b/l4/pkg/uclibc/lib/contrib/uclibc/test/regex/leftassoc.dat
new file mode 100644
index 00000000..9c068c61
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/regex/leftassoc.dat
@@ -0,0 +1,16 @@
+NOTE	left-assoc:pass-all right-assoc:pass-none : 2002-04-29
+
+E	(a|ab)(c|bcd)(d*)	abcd	(0,4)(0,1)(1,4)(4,4)
+E	(a|ab)(bcd|c)(d*)	abcd	(0,4)(0,1)(1,4)(4,4)
+E	(ab|a)(c|bcd)(d*)	abcd	(0,4)(0,1)(1,4)(4,4)
+E	(ab|a)(bcd|c)(d*)	abcd	(0,4)(0,1)(1,4)(4,4)
+
+E	(a*)(b|abc)(c*)		abc	(0,3)(0,0)(0,3)(3,3)
+E	(a*)(abc|b)(c*)		abc	(0,3)(0,0)(0,3)(3,3)
+E	(a*)(b|abc)(c*)		abc	(0,3)(0,0)(0,3)(3,3)
+E	(a*)(abc|b)(c*)		abc	(0,3)(0,0)(0,3)(3,3)
+
+E	(a|ab)(c|bcd)(d|.*)	abcd	(0,4)(0,1)(1,4)(4,4)
+E	(a|ab)(bcd|c)(d|.*)	abcd	(0,4)(0,1)(1,4)(4,4)
+E	(ab|a)(c|bcd)(d|.*)	abcd	(0,4)(0,1)(1,4)(4,4)
+E	(ab|a)(bcd|c)(d|.*)	abcd	(0,4)(0,1)(1,4)(4,4)
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/regex/nullsubexpr.dat b/l4/pkg/uclibc/lib/contrib/uclibc/test/regex/nullsubexpr.dat
new file mode 100644
index 00000000..c73d8f09
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/regex/nullsubexpr.dat
@@ -0,0 +1,73 @@
+NOTE	null subexpression matches : 2002-06-06
+
+E	(a*)*		a		(0,1)(0,1)
+E	SAME		x		(0,0)(0,0)
+E	SAME		aaaaaa		(0,6)(0,6)
+E	SAME		aaaaaax		(0,6)(0,6)
+E	(a*)+		a		(0,1)(0,1)
+E	SAME		x		(0,0)(0,0)
+E	SAME		aaaaaa		(0,6)(0,6)
+E	SAME		aaaaaax		(0,6)(0,6)
+E	(a+)*		a		(0,1)(0,1)
+E	SAME		x		(0,0)
+E	SAME		aaaaaa		(0,6)(0,6)
+E	SAME		aaaaaax		(0,6)(0,6)
+E	(a+)+		a		(0,1)(0,1)
+E	SAME		x		NOMATCH
+E	SAME		aaaaaa		(0,6)(0,6)
+E	SAME		aaaaaax		(0,6)(0,6)
+
+E	([a]*)*		a		(0,1)(0,1)
+E	SAME		x		(0,0)(0,0)
+E	SAME		aaaaaa		(0,6)(0,6)
+E	SAME		aaaaaax		(0,6)(0,6)
+E	([a]*)+		a		(0,1)(0,1)
+E	SAME		x		(0,0)(0,0)
+E	SAME		aaaaaa		(0,6)(0,6)
+E	SAME		aaaaaax		(0,6)(0,6)
+E	([^b]*)*	a		(0,1)(0,1)
+E	SAME		b		(0,0)(0,0)
+E	SAME		aaaaaa		(0,6)(0,6)
+E	SAME		aaaaaab		(0,6)(0,6)
+E	([ab]*)*	a		(0,1)(0,1)
+E	SAME		aaaaaa		(0,6)(0,6)
+E	SAME		ababab		(0,6)(0,6)
+E	SAME		bababa		(0,6)(0,6)
+E	SAME		b		(0,1)(0,1)
+E	SAME		bbbbbb		(0,6)(0,6)
+E	SAME		aaaabcde	(0,5)(0,5)
+E	([^a]*)*	b		(0,1)(0,1)
+E	SAME		bbbbbb		(0,6)(0,6)
+E	SAME		aaaaaa		(0,0)(0,0)
+E	([^ab]*)*	ccccxx		(0,6)(0,6)
+E	SAME		ababab		(0,0)(0,0)
+
+E	((z)+|a)*	zabcde		(0,2)(1,2)
+
+{E	a+?		aaaaaa		(0,1)	no *? +? mimimal match ops
+E	(a)		aaa		(0,1)(0,1)
+E	(a*?)		aaa		(0,0)(0,0)
+E	(a)*?		aaa		(0,0)
+E	(a*?)*?		aaa		(0,0)
+}
+
+B	\(a*\)*\(x\)		x	(0,1)(0,0)(0,1)
+B	\(a*\)*\(x\)		ax	(0,2)(0,1)(1,2)
+B	\(a*\)*\(x\)		axa	(0,2)(0,1)(1,2)
+B	\(a*\)*\(x\)\(\1\)	x	(0,1)(0,0)(0,1)(1,1)
+B	\(a*\)*\(x\)\(\1\)	ax	(0,2)(1,1)(1,2)(2,2)
+B	\(a*\)*\(x\)\(\1\)	axa	(0,3)(0,1)(1,2)(2,3)
+B	\(a*\)*\(x\)\(\1\)\(x\)	axax	(0,4)(0,1)(1,2)(2,3)(3,4)
+B	\(a*\)*\(x\)\(\1\)\(x\)	axxa	(0,3)(1,1)(1,2)(2,2)(2,3)
+
+E	(a*)*(x)		x	(0,1)(0,0)(0,1)
+E	(a*)*(x)		ax	(0,2)(0,1)(1,2)
+E	(a*)*(x)		axa	(0,2)(0,1)(1,2)
+
+E	(a*)+(x)		x	(0,1)(0,0)(0,1)
+E	(a*)+(x)		ax	(0,2)(0,1)(1,2)
+E	(a*)+(x)		axa	(0,2)(0,1)(1,2)
+
+E	(a*){2}(x)		x	(0,1)(0,0)(0,1)
+E	(a*){2}(x)		ax	(0,2)(1,1)(1,2)
+E	(a*){2}(x)		axa	(0,2)(1,1)(1,2)
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/regex/repetition.dat b/l4/pkg/uclibc/lib/contrib/uclibc/test/regex/repetition.dat
new file mode 100644
index 00000000..b54a2c6f
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/regex/repetition.dat
@@ -0,0 +1,79 @@
+NOTE	implicit vs. explicit repetitions : 2002-08-01
+#
+# Glenn Fowler 
+# conforming matches (column 4) must match one of the following BREs
+#	NOMATCH
+#	(0,.)\((\(.\),\(.\))(?,?)(\2,\3)\)*
+#	(0,.)\((\(.\),\(.\))(\2,\3)(?,?)\)*
+# i.e., each 3-tuple has two identical elements and one (?,?)
+#
+
+E	((..)|(.))				NULL		NOMATCH
+E	((..)|(.))((..)|(.))			NULL		NOMATCH
+E	((..)|(.))((..)|(.))((..)|(.))		NULL		NOMATCH
+
+E	((..)|(.)){1}				NULL		NOMATCH
+E	((..)|(.)){2}				NULL		NOMATCH
+E	((..)|(.)){3}				NULL		NOMATCH
+
+E	((..)|(.))*				NULL		(0,0)
+
+E	((..)|(.))				a		(0,1)(0,1)(?,?)(0,1)
+E	((..)|(.))((..)|(.))			a		NOMATCH
+E	((..)|(.))((..)|(.))((..)|(.))		a		NOMATCH
+
+E	((..)|(.)){1}				a		(0,1)(0,1)(?,?)(0,1)
+E	((..)|(.)){2}				a		NOMATCH
+E	((..)|(.)){3}				a		NOMATCH
+
+E	((..)|(.))*				a		(0,1)(0,1)(?,?)(0,1)
+
+E	((..)|(.))				aa		(0,2)(0,2)(0,2)(?,?)
+E	((..)|(.))((..)|(.))			aa		(0,2)(0,1)(?,?)(0,1)(1,2)(?,?)(1,2)
+E	((..)|(.))((..)|(.))((..)|(.))		aa		NOMATCH
+
+E	((..)|(.)){1}				aa		(0,2)(0,2)(0,2)(?,?)
+E	((..)|(.)){2}				aa		(0,2)(1,2)(?,?)(1,2)
+E	((..)|(.)){3}				aa		NOMATCH
+
+E	((..)|(.))*				aa		(0,2)(0,2)(0,2)(?,?)
+
+E	((..)|(.))				aaa		(0,2)(0,2)(0,2)(?,?)
+E	((..)|(.))((..)|(.))			aaa		(0,3)(0,2)(0,2)(?,?)(2,3)(?,?)(2,3)
+E	((..)|(.))((..)|(.))((..)|(.))		aaa		(0,3)(0,1)(?,?)(0,1)(1,2)(?,?)(1,2)(2,3)(?,?)(2,3)
+
+E	((..)|(.)){1}				aaa		(0,2)(0,2)(0,2)(?,?)
+E	((..)|(.)){2}				aaa		(0,3)(2,3)(?,?)(2,3)
+E	((..)|(.)){3}				aaa		(0,3)(2,3)(?,?)(2,3)
+
+E	((..)|(.))*				aaa		(0,3)(2,3)(?,?)(2,3)
+
+E	((..)|(.))				aaaa		(0,2)(0,2)(0,2)(?,?)
+E	((..)|(.))((..)|(.))			aaaa		(0,4)(0,2)(0,2)(?,?)(2,4)(2,4)(?,?)
+E	((..)|(.))((..)|(.))((..)|(.))		aaaa		(0,4)(0,2)(0,2)(?,?)(2,3)(?,?)(2,3)(3,4)(?,?)(3,4)
+
+E	((..)|(.)){1}				aaaa		(0,2)(0,2)(0,2)(?,?)
+E	((..)|(.)){2}				aaaa		(0,4)(2,4)(2,4)(?,?)
+E	((..)|(.)){3}				aaaa		(0,4)(3,4)(?,?)(3,4)
+
+E	((..)|(.))*				aaaa		(0,4)(2,4)(2,4)(?,?)
+
+E	((..)|(.))				aaaaa		(0,2)(0,2)(0,2)(?,?)
+E	((..)|(.))((..)|(.))			aaaaa		(0,4)(0,2)(0,2)(?,?)(2,4)(2,4)(?,?)
+E	((..)|(.))((..)|(.))((..)|(.))		aaaaa		(0,5)(0,2)(0,2)(?,?)(2,4)(2,4)(?,?)(4,5)(?,?)(4,5)
+
+E	((..)|(.)){1}				aaaaa		(0,2)(0,2)(0,2)(?,?)
+E	((..)|(.)){2}				aaaaa		(0,4)(2,4)(2,4)(?,?)
+E	((..)|(.)){3}				aaaaa		(0,5)(4,5)(?,?)(4,5)
+
+E	((..)|(.))*				aaaaa		(0,5)(4,5)(?,?)(4,5)
+
+E	((..)|(.))				aaaaaa		(0,2)(0,2)(0,2)(?,?)
+E	((..)|(.))((..)|(.))			aaaaaa		(0,4)(0,2)(0,2)(?,?)(2,4)(2,4)(?,?)
+E	((..)|(.))((..)|(.))((..)|(.))		aaaaaa		(0,6)(0,2)(0,2)(?,?)(2,4)(2,4)(?,?)(4,6)(4,6)(?,?)
+
+E	((..)|(.)){1}				aaaaaa		(0,2)(0,2)(0,2)(?,?)
+E	((..)|(.)){2}				aaaaaa		(0,4)(2,4)(2,4)(?,?)
+E	((..)|(.)){3}				aaaaaa		(0,6)(4,6)(4,6)(?,?)
+
+E	((..)|(.))*				aaaaaa		(0,6)(4,6)(4,6)(?,?)
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/regex/rightassoc.dat b/l4/pkg/uclibc/lib/contrib/uclibc/test/regex/rightassoc.dat
new file mode 100644
index 00000000..ed7f28e6
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/regex/rightassoc.dat
@@ -0,0 +1,16 @@
+NOTE	left-assoc:pass-none right-assoc:pass-all : 2002-04-29
+
+E	(a|ab)(c|bcd)(d*)	abcd	(0,4)(0,2)(2,3)(3,4)
+E	(a|ab)(bcd|c)(d*)	abcd	(0,4)(0,2)(2,3)(3,4)
+E	(ab|a)(c|bcd)(d*)	abcd	(0,4)(0,2)(2,3)(3,4)
+E	(ab|a)(bcd|c)(d*)	abcd	(0,4)(0,2)(2,3)(3,4)
+
+E	(a*)(b|abc)(c*)		abc	(0,3)(0,1)(1,2)(2,3)
+E	(a*)(abc|b)(c*)		abc	(0,3)(0,1)(1,2)(2,3)
+E	(a*)(b|abc)(c*)		abc	(0,3)(0,1)(1,2)(2,3)
+E	(a*)(abc|b)(c*)		abc	(0,3)(0,1)(1,2)(2,3)
+
+E	(a|ab)(c|bcd)(d|.*)	abcd	(0,4)(0,2)(2,3)(3,4)
+E	(a|ab)(bcd|c)(d|.*)	abcd	(0,4)(0,2)(2,3)(3,4)
+E	(ab|a)(c|bcd)(d|.*)	abcd	(0,4)(0,2)(2,3)(3,4)
+E	(ab|a)(bcd|c)(d|.*)	abcd	(0,4)(0,2)(2,3)(3,4)
diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/regex/testregex.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/regex/testregex.c
new file mode 100644
index 00000000..993ac268
--- /dev/null
+++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/regex/testregex.c
@@ -0,0 +1,2145 @@
+/*
+ * regex(3) test harness
+ *
+ * build:	cc -o testregex testregex.c
+ * help:	testregex --man
+ * note:	REG_* features are detected by #ifdef; if REG_* are enums
+ *		then supply #define REG_foo REG_foo for each enum REG_foo
+ *
+ *	Glenn Fowler 
+ *	AT&T Labs Research
+ *
+ * PLEASE: publish your tests so everyone can benefit
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of THIS SOFTWARE FILE (the "Software"), to deal in the Software
+ * without restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, and/or sell copies of the
+ * Software, and to permit persons to whom the Software is furnished to do
+ * so, subject to the following disclaimer:
+ *
+ * THIS SOFTWARE IS PROVIDED BY AT&T ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL AT&T BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+static const char id[] = "\n@(#)$Id: testregex (AT&T Research) 2005-05-20 $\0\n";
+
+#if _PACKAGE_ast
+#include 
+#else
+#include 
+#endif
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#ifdef	__STDC__
+#include 
+#include 
+#endif
+
+#if !_PACKAGE_ast
+#undef	REG_DISCIPLINE
+#endif
+
+#ifndef REG_DELIMITED
+#undef	_REG_subcomp
+#endif
+
+#define TEST_ARE		0x00000001
+#define TEST_BRE		0x00000002
+#define TEST_ERE		0x00000004
+#define TEST_KRE		0x00000008
+#define TEST_LRE		0x00000010
+#define TEST_SRE		0x00000020
+
+#define TEST_EXPAND		0x00000040
+#define TEST_LENIENT		0x00000080
+
+#define TEST_QUERY		0x00000100
+#define TEST_SUB		0x00000200
+#define TEST_UNSPECIFIED	0x00000400
+#define TEST_VERIFY		0x00000800
+#define TEST_AND		0x00001000
+#define TEST_OR			0x00002000
+
+#define TEST_DELIMIT		0x00010000
+#define TEST_OK			0x00020000
+#define TEST_SAME		0x00040000
+
+#define TEST_ACTUAL		0x00100000
+#define TEST_BASELINE		0x00200000
+#define TEST_FAIL		0x00400000
+#define TEST_PASS		0x00800000
+#define TEST_SUMMARY		0x01000000
+
+#define TEST_IGNORE_ERROR	0x02000000
+#define TEST_IGNORE_OVER	0x04000000
+#define TEST_IGNORE_POSITION	0x08000000
+
+#define TEST_CATCH		0x10000000
+#define TEST_VERBOSE		0x20000000
+
+#define TEST_GLOBAL		(TEST_ACTUAL|TEST_AND|TEST_BASELINE|TEST_CATCH|TEST_FAIL|TEST_IGNORE_ERROR|TEST_IGNORE_OVER|TEST_IGNORE_POSITION|TEST_OR|TEST_PASS|TEST_SUMMARY|TEST_VERBOSE)
+
+#ifdef REG_DISCIPLINE
+
+
+#include 
+
+typedef struct Disc_s
+{
+	regdisc_t	disc;
+	int		ordinal;
+	Sfio_t*		sp;
+} Disc_t;
+
+static void*
+compf(const regex_t* re, const char* xstr, size_t xlen, regdisc_t* disc)
+{
+	Disc_t*		dp = (Disc_t*)disc;
+
+	return (void*)++dp->ordinal;
+}
+
+static int
+execf(const regex_t* re, void* data, const char* xstr, size_t xlen, const char* sstr, size_t slen, char** snxt, regdisc_t* disc)
+{
+	Disc_t*		dp = (Disc_t*)disc;
+
+	sfprintf(dp->sp, "{%-.*s}(%d:%d)", xlen, xstr, (int)data, slen);
+	return atoi(xstr);
+}
+
+static void*
+resizef(void* handle, void* data, size_t size)
+{
+	if (!size)
+		return 0;
+	return stkalloc((Sfio_t*)handle, size);
+}
+
+#endif
+
+#ifndef NiL
+#ifdef	__STDC__
+#define NiL		0
+#else
+#define NiL		(char*)0
+#endif
+#endif
+
+#define H(x)		do{if(html)fprintf(stderr,x);}while(0)
+#define T(x)		fprintf(stderr,x)
+
+static void
+help(int html)
+{
+H("\n");
+H("\n");
+H("\n");
+H("testregex man document\n");
+H("\n");
+H("\n");
+H("
\n");
+T("NAME\n");
+T("  testregex - regex(3) test harness\n");
+T("\n");
+T("SYNOPSIS\n");
+T("  testregex [ options ]\n");
+T("\n");
+T("DESCRIPTION\n");
+T("  testregex reads regex(3) test specifications, one per line, from the\n");
+T("  standard input and writes one output line for each failed test. A\n");
+T("  summary line is written after all tests are done. Each successful\n");
+T("  test is run again with REG_NOSUB. Unsupported features are noted\n");
+T("  before the first test, and tests requiring these features are\n");
+T("  silently ignored.\n");
+T("\n");
+T("OPTIONS\n");
+T("  -c	catch signals and non-terminating calls\n");
+T("  -e	ignore error return mismatches\n");
+T("  -h	list help on standard error\n");
+T("  -n	do not repeat successful tests with regnexec()\n");
+T("  -o	ignore match[] overrun errors\n");
+T("  -p	ignore negative position mismatches\n");
+T("  -s	use stack instead of malloc\n");
+T("  -x	do not repeat successful tests with REG_NOSUB\n");
+T("  -v	list each test line\n");
+T("  -A	list failed test lines with actual answers\n");
+T("  -B	list all test lines with actual answers\n");
+T("  -F	list failed test lines\n");
+T("  -P	list passed test lines\n");
+T("  -S	output one summary line\n");
+T("\n");
+T("INPUT FORMAT\n");
+T("  Input lines may be blank, a comment beginning with #, or a test\n");
+T("  specification. A specification is five fields separated by one\n");
+T("  or more tabs. NULL denotes the empty string and NIL denotes the\n");
+T("  0 pointer.\n");
+T("\n");
+T("  Field 1: the regex(3) flags to apply, one character per REG_feature\n");
+T("  flag. The test is skipped if REG_feature is not supported by the\n");
+T("  implementation. If the first character is not [BEASKL] then the\n");
+T("  specification is a global control line. One or more of [BEASKL] may be\n");
+T("  specified; the test will be repeated for each mode.\n");
+T("\n");
+T("    B 	basic			BRE	(grep, ed, sed)\n");
+T("    E 	REG_EXTENDED		ERE	(egrep)\n");
+T("    A	REG_AUGMENTED		ARE	(egrep with negation)\n");
+T("    S	REG_SHELL		SRE	(sh glob)\n");
+T("    K	REG_SHELL|REG_AUGMENTED	KRE	(ksh glob)\n");
+T("    L	REG_LITERAL		LRE	(fgrep)\n");
+T("\n");
+T("    a	REG_LEFT|REG_RIGHT	implicit ^...$\n");
+T("    b	REG_NOTBOL		lhs does not match ^\n");
+T("    c	REG_COMMENT		ignore space and #...\\n\n");
+T("    d	REG_SHELL_DOT		explicit leading . match\n");
+T("    e	REG_NOTEOL		rhs does not match $\n");
+T("    f	REG_MULTIPLE		multiple \\n separated patterns\n");
+T("    g	FNM_LEADING_DIR		testfnmatch only -- match until /\n");
+T("    h	REG_MULTIREF		multiple digit backref\n");
+T("    i	REG_ICASE		ignore case\n");
+T("    j	REG_SPAN		. matches \\n\n");
+T("    k	REG_ESCAPE		\\ to ecape [...] delimiter\n");
+T("    l	REG_LEFT		implicit ^...\n");
+T("    m	REG_MINIMAL		minimal match\n");
+T("    n	REG_NEWLINE		explicit \\n match\n");
+T("    o	REG_ENCLOSED		(|&) magic inside [@|&](...)\n");
+T("    p	REG_SHELL_PATH		explicit / match\n");
+T("    q	REG_DELIMITED		delimited pattern\n");
+T("    r	REG_RIGHT		implicit ...$\n");
+T("    s	REG_SHELL_ESCAPED	\\ not special\n");
+T("    t	REG_MUSTDELIM		all delimiters must be specified\n");
+T("    u	standard unspecified behavior -- errors not counted\n");
+T("    w	REG_NOSUB		no subexpression match array\n");
+T("    x	REG_LENIENT		let some errors slide\n");
+T("    y	REG_LEFT		regexec() implicit ^...\n");
+T("    z	REG_NULL		NULL subexpressions ok\n");
+T("    $	                        expand C \\c escapes in fields 2 and 3\n");
+T("    /	                        field 2 is a regsubcomp() expression\n");
+T("\n");
+T("  Field 1 control lines:\n");
+T("\n");
+T("    C		set LC_COLLATE and LC_CTYPE to locale in field 2\n");
+T("\n");
+T("    ?test ...	output field 5 if passed and != EXPECTED, silent otherwise\n");
+T("    &test ...	output field 5 if current and previous passed\n");
+T("    |test ...	output field 5 if current passed and previous failed\n");
+T("    ; ...	output field 2 if previous failed\n");
+T("    {test ...	skip if failed until }\n");
+T("    }		end of skip\n");
+T("\n");
+T("    : comment		comment copied as output NOTE\n");
+T("    :comment:test	:comment: ignored\n");
+T("    N[OTE] comment	comment copied as output NOTE\n");
+T("    T[EST] comment	comment\n");
+T("\n");
+T("    number		use number for nmatch (20 by default)\n");
+T("\n");
+T("  Field 2: the regular expression pattern; SAME uses the pattern from\n");
+T("    the previous specification.\n");
+T("\n");
+T("  Field 3: the string to match.\n");
+T("\n");
+T("  Field 4: the test outcome. This is either one of the posix error\n");
+T("    codes (with REG_ omitted) or the match array, a list of (m,n)\n");
+T("    entries with m and n being first and last+1 positions in the\n");
+T("    field 3 string, or NULL if REG_NOSUB is in effect and success\n");
+T("    is expected. BADPAT is acceptable in place of any regcomp(3)\n");
+T("    error code. The match[] array is initialized to (-2,-2) before\n");
+T("    each test. All array elements from 0 to nmatch-1 must be specified\n");
+T("    in the outcome. Unspecified endpoints (offset -1) are denoted by ?.\n");
+T("    Unset endpoints (offset -2) are denoted by X. {x}(o:n) denotes a\n");
+T("    matched (?{...}) expression, where x is the text enclosed by {...},\n");
+T("    o is the expression ordinal counting from 1, and n is the length of\n");
+T("    the unmatched portion of the subject string. If x starts with a\n");
+T("    number then that is the return value of re_execf(), otherwise 0 is\n");
+T("    returned.\n");
+T("\n");
+T("  Field 5: optional comment appended to the report.\n");
+T("\n");
+T("CAVEAT\n");
+T("    If a regex implementation misbehaves with memory then all bets are off.\n");
+T("\n");
+T("CONTRIBUTORS\n");
+T("  Glenn Fowler    gsf@research.att.com        (ksh strmatch, regex extensions)\n");
+T("  David Korn      dgk@research.att.com        (ksh glob matcher)\n");
+T("  Doug McIlroy    mcilroy@dartmouth.edu       (ast regex/testre in C++)\n");
+T("  Tom Lord        lord@regexps.com            (rx tests)\n");
+T("  Henry Spencer   henry@zoo.toronto.edu       (original public regex)\n");
+T("  Andrew Hume     andrew@research.att.com     (gre tests)\n");
+T("  John Maddock    John_Maddock@compuserve.com (regex++ tests)\n");
+T("  Philip Hazel    ph10@cam.ac.uk              (pcre tests)\n");
+T("  Ville Laurikari vl@iki.fi                   (libtre tests)\n");
+H("
\n"); +H("\n"); +H("\n"); +} + +#ifndef elementsof +#define elementsof(x) (sizeof(x)/sizeof(x[0])) +#endif + +#ifndef streq +#define streq(a,b) (*(a)==*(b)&&!strcmp(a,b)) +#endif + +#define HUNG 5 +#define NOTEST (~0) + +#ifndef REG_TEST_DEFAULT +#define REG_TEST_DEFAULT 0 +#endif + +#ifndef REG_EXEC_DEFAULT +#define REG_EXEC_DEFAULT 0 +#endif + +static const char* unsupported[] = +{ + "BASIC", +#ifndef REG_EXTENDED + "EXTENDED", +#endif +#ifndef REG_AUGMENTED + "AUGMENTED", +#endif +#ifndef REG_SHELL + "SHELL", +#endif + +#ifndef REG_COMMENT + "COMMENT", +#endif +#ifndef REG_DELIMITED + "DELIMITED", +#endif +#ifndef REG_DISCIPLINE + "DISCIPLINE", +#endif +#ifndef REG_ESCAPE + "ESCAPE", +#endif +#ifndef REG_ICASE + "ICASE", +#endif +#ifndef REG_LEFT + "LEFT", +#endif +#ifndef REG_LENIENT + "LENIENT", +#endif +#ifndef REG_LITERAL + "LITERAL", +#endif +#ifndef REG_MINIMAL + "MINIMAL", +#endif +#ifndef REG_MULTIPLE + "MULTIPLE", +#endif +#ifndef REG_MULTIREF + "MULTIREF", +#endif +#ifndef REG_MUSTDELIM + "MUSTDELIM", +#endif +#ifndef REG_NEWLINE + "NEWLINE", +#endif +#ifndef REG_NOTBOL + "NOTBOL", +#endif +#ifndef REG_NOTEOL + "NOTEOL", +#endif +#ifndef REG_NULL + "NULL", +#endif +#ifndef REG_RIGHT + "RIGHT", +#endif +#ifndef REG_SHELL_DOT + "SHELL_DOT", +#endif +#ifndef REG_SHELL_ESCAPED + "SHELL_ESCAPED", +#endif +#ifndef REG_SHELL_GROUP + "SHELL_GROUP", +#endif +#ifndef REG_SHELL_PATH + "SHELL_PATH", +#endif +#ifndef REG_SPAN + "SPAN", +#endif +#if REG_NOSUB & REG_TEST_DEFAULT + "SUBMATCH", +#endif +#if !_REG_nexec + "regnexec", +#endif +#if !_REG_subcomp + "regsubcomp", +#endif + 0 +}; + +#ifndef REG_COMMENT +#define REG_COMMENT NOTEST +#endif +#ifndef REG_DELIMITED +#define REG_DELIMITED NOTEST +#endif +#ifndef REG_ESCAPE +#define REG_ESCAPE NOTEST +#endif +#ifndef REG_ICASE +#define REG_ICASE NOTEST +#endif +#ifndef REG_LEFT +#define REG_LEFT NOTEST +#endif +#ifndef REG_LENIENT +#define REG_LENIENT 0 +#endif +#ifndef REG_MINIMAL +#define REG_MINIMAL NOTEST +#endif +#ifndef REG_MULTIPLE +#define REG_MULTIPLE NOTEST +#endif +#ifndef REG_MULTIREF +#define REG_MULTIREF NOTEST +#endif +#ifndef REG_MUSTDELIM +#define REG_MUSTDELIM NOTEST +#endif +#ifndef REG_NEWLINE +#define REG_NEWLINE NOTEST +#endif +#ifndef REG_NOTBOL +#define REG_NOTBOL NOTEST +#endif +#ifndef REG_NOTEOL +#define REG_NOTEOL NOTEST +#endif +#ifndef REG_NULL +#define REG_NULL NOTEST +#endif +#ifndef REG_RIGHT +#define REG_RIGHT NOTEST +#endif +#ifndef REG_SHELL_DOT +#define REG_SHELL_DOT NOTEST +#endif +#ifndef REG_SHELL_ESCAPED +#define REG_SHELL_ESCAPED NOTEST +#endif +#ifndef REG_SHELL_GROUP +#define REG_SHELL_GROUP NOTEST +#endif +#ifndef REG_SHELL_PATH +#define REG_SHELL_PATH NOTEST +#endif +#ifndef REG_SPAN +#define REG_SPAN NOTEST +#endif + +#define REG_UNKNOWN (-1) + +#ifndef REG_ENEWLINE +#define REG_ENEWLINE (REG_UNKNOWN-1) +#endif +#ifndef REG_ENULL +#ifndef REG_EMPTY +#define REG_ENULL (REG_UNKNOWN-2) +#else +#define REG_ENULL REG_EMPTY +#endif +#endif +#ifndef REG_ECOUNT +#define REG_ECOUNT (REG_UNKNOWN-3) +#endif +#ifndef REG_BADESC +#define REG_BADESC (REG_UNKNOWN-4) +#endif +#ifndef REG_EMEM +#define REG_EMEM (REG_UNKNOWN-5) +#endif +#ifndef REG_EHUNG +#define REG_EHUNG (REG_UNKNOWN-6) +#endif +#ifndef REG_EBUS +#define REG_EBUS (REG_UNKNOWN-7) +#endif +#ifndef REG_EFAULT +#define REG_EFAULT (REG_UNKNOWN-8) +#endif +#ifndef REG_EFLAGS +#define REG_EFLAGS (REG_UNKNOWN-9) +#endif +#ifndef REG_EDELIM +#define REG_EDELIM (REG_UNKNOWN-9) +#endif + +static const struct { int code; char* name; } codes[] = +{ + {REG_UNKNOWN, "UNKNOWN"}, + {REG_NOMATCH, "NOMATCH"}, + {REG_BADPAT, "BADPAT"}, + {REG_ECOLLATE, "ECOLLATE"}, + {REG_ECTYPE, "ECTYPE"}, + {REG_EESCAPE, "EESCAPE"}, + {REG_ESUBREG, "ESUBREG"}, + {REG_EBRACK, "EBRACK"}, + {REG_EPAREN, "EPAREN"}, + {REG_EBRACE, "EBRACE"}, + {REG_BADBR, "BADBR"}, + {REG_ERANGE, "ERANGE"}, + {REG_ESPACE, "ESPACE"}, + {REG_BADRPT, "BADRPT"}, + {REG_ENEWLINE, "ENEWLINE"}, + {REG_ENULL, "ENULL"}, + {REG_ECOUNT, "ECOUNT"}, + {REG_BADESC, "BADESC"}, + {REG_EMEM, "EMEM"}, + {REG_EHUNG, "EHUNG"}, + {REG_EBUS, "EBUS"}, + {REG_EFAULT, "EFAULT"}, + {REG_EFLAGS, "EFLAGS"}, + {REG_EDELIM, "EDELIM"}, +}; + +static struct +{ + regmatch_t NOMATCH; + int errors; + int extracted; + int ignored; + int lineno; + int passed; + int signals; + int unspecified; + int verify; + int warnings; + char* file; + char* stack; + char* which; + jmp_buf gotcha; +#ifdef REG_DISCIPLINE + Disc_t disc; +#endif +} state; + +static void +quote(char* s, int len, unsigned long test) +{ + unsigned char* u = (unsigned char*)s; + unsigned char* e; + int c; + + if (!u) + printf("NIL"); + else if (!*u && len <= 1) + printf("NULL"); + else if (test & TEST_EXPAND) + { + if (len < 0) + len = strlen((char*)u); + e = u + len; + if (test & TEST_DELIMIT) + printf("\""); + while (u < e) + switch (c = *u++) + { + case '\\': + printf("\\\\"); + break; + case '"': + if (test & TEST_DELIMIT) + printf("\\\""); + else + printf("\""); + break; + case '\a': + printf("\\a"); + break; + case '\b': + printf("\\b"); + break; + case 033: + printf("\\e"); + break; + case '\f': + printf("\\f"); + break; + case '\n': + printf("\\n"); + break; + case '\r': + printf("\\r"); + break; + case '\t': + printf("\\t"); + break; + case '\v': + printf("\\v"); + break; + default: + if (!iscntrl(c) && isprint(c)) + putchar(c); + else + printf("\\x%02x", c); + break; + } + if (test & TEST_DELIMIT) + printf("\""); + } + else + printf("%s", s); +} + +static void +report(char* comment, char* fun, char* re, char* s, int len, char* msg, int flags, unsigned long test) +{ + if (state.file) + printf("%s:", state.file); + printf("%d:", state.lineno); + if (re) + { + printf(" "); + quote(re, -1, test|TEST_DELIMIT); + if (s) + { + printf(" versus "); + quote(s, len, test|TEST_DELIMIT); + } + } + if (test & TEST_UNSPECIFIED) + { + state.unspecified++; + printf(" unspecified behavior"); + } + else + state.errors++; + if (state.which) + printf(" %s", state.which); + if (flags & REG_NOSUB) + printf(" NOSUB"); + if (fun) + printf(" %s", fun); + if (comment[strlen(comment)-1] == '\n') + printf(" %s", comment); + else + { + printf(" %s: ", comment); + if (msg) + printf("%s: ", msg); + } +} + +static void +error(regex_t* preg, int code) +{ + char* msg; + char buf[256]; + + switch (code) + { + case REG_EBUS: + msg = "bus error"; + break; + case REG_EFAULT: + msg = "memory fault"; + break; + case REG_EHUNG: + msg = "did not terminate"; + break; + default: + regerror(code, preg, msg = buf, sizeof buf); + break; + } + printf("%s\n", msg); +} + +static void +bad(char* comment, char* re, char* s, int len, unsigned long test) +{ + printf("bad test case "); + report(comment, NiL, re, s, len, NiL, 0, test); + exit(1); +} + +static int +escape(char* s) +{ + char* b; + char* t; + char* q; + char* e; + int c; + + for (b = t = s; (*t = *s); s++, t++) + if (*s == '\\') + switch (*++s) + { + case '\\': + break; + case 'a': + *t = '\a'; + break; + case 'b': + *t = '\b'; + break; + case 'c': + if ((*t = *++s)) + *t &= 037; + else + s--; + break; + case 'e': + case 'E': + *t = 033; + break; + case 'f': + *t = '\f'; + break; + case 'n': + *t = '\n'; + break; + case 'r': + *t = '\r'; + break; + case 's': + *t = ' '; + break; + case 't': + *t = '\t'; + break; + case 'v': + *t = '\v'; + break; + case 'u': + case 'x': + c = 0; + q = c == 'u' ? (s + 5) : (char*)0; + e = s + 1; + while (!e || !q || s < q) + { + switch (*++s) + { + case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': + c = (c << 4) + *s - 'a' + 10; + continue; + case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': + c = (c << 4) + *s - 'A' + 10; + continue; + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + c = (c << 4) + *s - '0'; + continue; + case '{': + case '[': + if (s != e) + { + s--; + break; + } + e = 0; + continue; + case '}': + case ']': + if (e) + s--; + break; + default: + s--; + break; + } + break; + } + *t = c; + break; + case '0': case '1': case '2': case '3': + case '4': case '5': case '6': case '7': + c = *s - '0'; + q = s + 2; + while (s < q) + { + switch (*++s) + { + case '0': case '1': case '2': case '3': + case '4': case '5': case '6': case '7': + c = (c << 3) + *s - '0'; + break; + default: + q = --s; + break; + } + } + *t = c; + break; + default: + *(s + 1) = 0; + bad("invalid C \\ escape\n", s - 1, NiL, 0, 0); + } + return t - b; +} + +static void +matchoffprint(int off) +{ + switch (off) + { + case -2: + printf("X"); + break; + case -1: + printf("?"); + break; + default: + printf("%d", off); + break; + } +} + +static void +matchprint(regmatch_t* match, int nmatch, int nsub, char* ans, unsigned long test) +{ + int i; + + for (; nmatch > nsub + 1; nmatch--) + if ((match[nmatch-1].rm_so != -1 || match[nmatch-1].rm_eo != -1) && (!(test & TEST_IGNORE_POSITION) || (match[nmatch-1].rm_so >= 0 && match[nmatch-1].rm_eo >= 0))) + break; + for (i = 0; i < nmatch; i++) + { + printf("("); + matchoffprint(match[i].rm_so); + printf(","); + matchoffprint(match[i].rm_eo); + printf(")"); + } + if (!(test & (TEST_ACTUAL|TEST_BASELINE))) + { + if (ans) + printf(" expected: %s", ans); + printf("\n"); + } +} + +static int +matchcheck(regmatch_t* match, int nmatch, int nsub, char* ans, char* re, char* s, int len, int flags, unsigned long test) +{ + char* p; + int i; + int m; + int n; + + if (streq(ans, "OK")) + return test & (TEST_BASELINE|TEST_PASS|TEST_VERIFY); + for (i = 0, p = ans; i < nmatch && *p; i++) + { + if (*p == '{') + { +#ifdef REG_DISCIPLINE + char* x; + + x = sfstruse(state.disc.sp); + if (strcmp(p, x)) + { + if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY)) + return 0; + report("callout failed", NiL, re, s, len, NiL, flags, test); + quote(p, -1, test); + printf(" expected, "); + quote(x, -1, test); + printf(" returned\n"); + } +#endif + break; + } + if (*p++ != '(') + bad("improper answer\n", re, s, -1, test); + if (*p == '?') + { + m = -1; + p++; + } + else + m = strtol(p, &p, 10); + if (*p++ != ',') + bad("improper answer\n", re, s, -1, test); + if (*p == '?') + { + n = -1; + p++; + } + else + n = strtol(p, &p, 10); + if (*p++ != ')') + bad("improper answer\n", re, s, -1, test); + if (m!=match[i].rm_so || n!=match[i].rm_eo) + { + if (!(test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY))) + { + report("failed: match was", NiL, re, s, len, NiL, flags, test); + matchprint(match, nmatch, nsub, ans, test); + } + return 0; + } + } + for (; i < nmatch; i++) + { + if (match[i].rm_so!=-1 || match[i].rm_eo!=-1) + { + if (!(test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_VERIFY))) + { + if ((test & TEST_IGNORE_POSITION) && (match[i].rm_so<0 || match[i].rm_eo<0)) + { + state.ignored++; + return 0; + } + if (!(test & TEST_SUMMARY)) + { + report("failed: match was", NiL, re, s, len, NiL, flags, test); + matchprint(match, nmatch, nsub, ans, test); + } + } + return 0; + } + } + if (!(test & TEST_IGNORE_OVER) && match[nmatch].rm_so != state.NOMATCH.rm_so) + { + if (!(test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY))) + { + report("failed: overran match array", NiL, re, s, len, NiL, flags, test); + matchprint(match, nmatch + 1, nsub, NiL, test); + } + return 0; + } + return 1; +} + +static void +sigunblock(int s) +{ +#ifdef SIG_SETMASK + int op; + sigset_t mask; + + sigemptyset(&mask); + if (s) + { + sigaddset(&mask, s); + op = SIG_UNBLOCK; + } + else op = SIG_SETMASK; + sigprocmask(op, &mask, NiL); +#else +#ifdef sigmask + sigsetmask(s ? (sigsetmask(0L) & ~sigmask(s)) : 0L); +#endif +#endif +} + +static void +gotcha(int sig) +{ + int ret; + + signal(sig, gotcha); + alarm(0); + state.signals++; + switch (sig) + { + case SIGALRM: + ret = REG_EHUNG; + break; + case SIGBUS: + ret = REG_EBUS; + break; + default: + ret = REG_EFAULT; + break; + } + sigunblock(sig); + longjmp(state.gotcha, ret); +} + +static char* +my_getline(FILE* fp) +{ + static char buf[32 * 1024]; + + register char* s = buf; + register char* e = &buf[sizeof(buf)]; + register char* b; + + for (;;) + { + if (!(b = fgets(s, e - s, fp))) + return 0; + state.lineno++; + s += strlen(s); + if (s == b || *--s != '\n' || s == b || *(s - 1) != '\\') + { + *s = 0; + break; + } + s--; + } + return buf; +} + +static unsigned long +note(unsigned long level, char* msg, unsigned long skip, unsigned long test) +{ + if (!(test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_SUMMARY)) && !skip) + { + printf("NOTE\t"); + if (msg) + printf("%s: ", msg); + printf("skipping lines %d", state.lineno); + } + return skip | level; +} + +#define TABS(n) &ts[7-((n)&7)] + +static char ts[] = "\t\t\t\t\t\t\t"; + +static unsigned long +extract(int* tabs, char* spec, char* re, char* s, char* ans, char* msg, char* accept, regmatch_t* match, int nmatch, int nsub, unsigned long skip, unsigned long level, unsigned long test) +{ + if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_OK|TEST_PASS|TEST_SUMMARY)) + { + state.extracted = 1; + if (test & TEST_OK) + { + state.passed++; + if ((test & TEST_VERIFY) && !(test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_SUMMARY))) + { + if (msg && strcmp(msg, "EXPECTED")) + printf("NOTE\t%s\n", msg); + return skip; + } + test &= ~(TEST_PASS|TEST_QUERY); + } + if (test & (TEST_QUERY|TEST_VERIFY)) + { + if (test & TEST_BASELINE) + test &= ~(TEST_BASELINE|TEST_PASS); + else + test |= TEST_PASS; + skip |= level; + } + if (!(test & TEST_OK)) + { + if (test & TEST_UNSPECIFIED) + state.unspecified++; + else + state.errors++; + } + if (test & (TEST_PASS|TEST_SUMMARY)) + return skip; + test &= ~TEST_DELIMIT; + printf("%s%s", spec, TABS(*tabs++)); + if ((test & (TEST_BASELINE|TEST_SAME)) == (TEST_BASELINE|TEST_SAME)) + printf("SAME"); + else + quote(re, -1, test); + printf("%s", TABS(*tabs++)); + quote(s, -1, test); + printf("%s", TABS(*tabs++)); + if (!(test & (TEST_ACTUAL|TEST_BASELINE)) || (!accept && !match)) + printf("%s", ans); + else if (accept) + printf("%s", accept); + else + matchprint(match, nmatch, nsub, NiL, test); + if (msg) + printf("%s%s", TABS(*tabs++), msg); + putchar('\n'); + } + else if (test & TEST_QUERY) + skip = note(level, msg, skip, test); + else if (test & TEST_VERIFY) + state.extracted = 1; + return skip; +} + +static int +catchfree(regex_t* preg, int flags, int* tabs, char* spec, char* re, char* s, char* ans, char* msg, char* accept, regmatch_t* match, int nmatch, int nsub, unsigned long skip, unsigned long level, unsigned long test) +{ + int eret; + + if (!(test & TEST_CATCH)) + { + regfree(preg); + eret = 0; + } + else if (!(eret = setjmp(state.gotcha))) + { + alarm(HUNG); + regfree(preg); + alarm(0); + } + else if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY)) + extract(tabs, spec, re, s, ans, msg, NiL, NiL, 0, 0, skip, level, test); + else + { + report("failed", "regfree", re, NiL, -1, msg, flags, test); + error(preg, eret); + } + return eret; +} + +int +old_main(int unused_param_argc, char** argv) +{ + int flags; + int cflags; + int eflags; + int nmatch; + int nexec; + int nstr; + int cret; + int eret; + int nsub; + int i; + int j; + int expected; + int got; + int locale; + int subunitlen = 0; + int testno; + unsigned long level; + unsigned long skip; + char* p; + char* line; + char* spec; + char* re; + char* s; + char* ans; + char* msg; + char* fun; + char* ppat = NULL; + char* subunit = NULL; + char* version; + char* field[6]; + char* delim[6]; + FILE* fp; + int tabs[6]; + char unit[64]; + regmatch_t match[100]; + regex_t preg; + + static char pat[32 * 1024]; + + int nonosub = REG_NOSUB == 0; + int nonexec = 0; + + unsigned long test = 0; + + static char* filter[] = { "-", 0 }; + + state.NOMATCH.rm_so = state.NOMATCH.rm_eo = -2; + p = unit; + version = (char*)id + 10; + while (p < &unit[sizeof(unit)-1] && (*p = *version++) && !isspace(*p)) + p++; + *p = 0; + while ((p = *++argv) && *p == '-') + for (;;) + { + switch (*++p) + { + case 0: + break; + case 'c': + test |= TEST_CATCH; + continue; + case 'e': + test |= TEST_IGNORE_ERROR; + continue; + case 'h': + case '?': + help(0); + return 2; + case '-': + help(p[1] == 'h'); + return 2; + case 'n': + nonexec = 1; + continue; + case 'o': + test |= TEST_IGNORE_OVER; + continue; + case 'p': + test |= TEST_IGNORE_POSITION; + continue; + case 's': +#ifdef REG_DISCIPLINE + if (!(state.stack = stkalloc(stkstd, 0))) + fprintf(stderr, "%s: out of space [stack]", unit); + state.disc.disc.re_resizef = resizef; + state.disc.disc.re_resizehandle = (void*)stkstd; +#endif + continue; + case 'x': + nonosub = 1; + continue; + case 'v': + test |= TEST_VERBOSE; + continue; + case 'A': + test |= TEST_ACTUAL; + continue; + case 'B': + test |= TEST_BASELINE; + continue; + case 'F': + test |= TEST_FAIL; + continue; + case 'P': + test |= TEST_PASS; + continue; + case 'S': + test |= TEST_SUMMARY; + continue; + default: + fprintf(stderr, "%s: %c: invalid option\n", unit, *p); + return 2; + } + break; + } + if (!*argv) + argv = filter; + locale = 0; + while ((state.file = *argv++)) + { + if (streq(state.file, "-") || streq(state.file, "/dev/stdin") || streq(state.file, "/dev/fd/0")) + { + state.file = 0; + fp = stdin; + } + else if (!(fp = fopen(state.file, "r"))) + { + fprintf(stderr, "%s: %s: cannot read\n", unit, state.file); + return 2; + } + testno = state.errors = state.ignored = state.lineno = state.passed = + state.signals = state.unspecified = state.warnings = 0; + skip = 0; + level = 1; + if (!(test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_SUMMARY))) + { + printf("TEST\t%s ", unit); + if ((s = state.file)) + { + subunit = p = 0; + for (;;) + { + switch (*s++) + { + case 0: + break; + case '/': + subunit = s; + continue; + case '.': + p = s - 1; + continue; + default: + continue; + } + break; + } + if (!subunit) + subunit = state.file; + if (p < subunit) + p = s - 1; + subunitlen = p - subunit; + printf("%-.*s ", subunitlen, subunit); + } + else + subunit = 0; + for (s = version; *s && (*s != ' ' || *(s + 1) != '$'); s++) + putchar(*s); + if (test & TEST_CATCH) + printf(", catch"); + if (test & TEST_IGNORE_ERROR) + printf(", ignore error code mismatches"); + if (test & TEST_IGNORE_POSITION) + printf(", ignore negative position mismatches"); +#ifdef REG_DISCIPLINE + if (state.stack) + printf(", stack"); +#endif + if (test & TEST_VERBOSE) + printf(", verbose"); + printf("\n"); +#ifdef REG_VERSIONID + if (regerror(REG_VERSIONID, NiL, pat, sizeof(pat)) > 0) + s = pat; + else +#endif +#ifdef REG_TEST_VERSION + s = REG_TEST_VERSION; +#else + s = "regex"; +#endif + printf("NOTE\t%s\n", s); + if (elementsof(unsupported) > 1) + { +#if (REG_TEST_DEFAULT & (REG_AUGMENTED|REG_EXTENDED|REG_SHELL)) || !defined(REG_EXTENDED) + i = 0; +#else + i = REG_EXTENDED != 0; +#endif + for (got = 0; i < elementsof(unsupported) - 1; i++) + { + if (!got) + { + got = 1; + printf("NOTE\tunsupported: %s", unsupported[i]); + } + else + printf(",%s", unsupported[i]); + } + if (got) + printf("\n"); + } + } +#ifdef REG_DISCIPLINE + state.disc.disc.re_version = REG_VERSION; + state.disc.disc.re_compf = compf; + state.disc.disc.re_execf = execf; + if (!(state.disc.sp = sfstropen())) + bad("out of space [discipline string stream]\n", NiL, NiL, 0, 0); + preg.re_disc = &state.disc.disc; +#endif + if (test & TEST_CATCH) + { + signal(SIGALRM, gotcha); + signal(SIGBUS, gotcha); + signal(SIGSEGV, gotcha); + } + while ((p = my_getline(fp))) + { + + /* parse: */ + + line = p; + if (*p == ':' && !isspace(*(p + 1))) + { + while (*++p && *p != ':'); + if (!*p++) + { + if (test & TEST_BASELINE) + printf("%s\n", line); + continue; + } + } + while (isspace(*p)) + p++; + if (*p == 0 || *p == '#' || *p == 'T') + { + if (test & TEST_BASELINE) + printf("%s\n", line); + continue; + } + if (*p == ':' || *p == 'N') + { + if (test & TEST_BASELINE) + printf("%s\n", line); + else if (!(test & (TEST_ACTUAL|TEST_FAIL|TEST_PASS|TEST_SUMMARY))) + { + while (*++p && !isspace(*p)); + while (isspace(*p)) + p++; + printf("NOTE %s\n", p); + } + continue; + } + j = 0; + i = 0; + field[i++] = p; + for (;;) + { + switch (*p++) + { + case 0: + p--; + j = 0; + goto checkfield; + case '\t': + *(delim[i] = p - 1) = 0; + j = 1; + checkfield: + s = field[i - 1]; + if (streq(s, "NIL")) + field[i - 1] = 0; + else if (streq(s, "NULL")) + *s = 0; + while (*p == '\t') + { + p++; + j++; + } + tabs[i - 1] = j; + if (!*p) + break; + if (i >= elementsof(field)) + bad("too many fields\n", NiL, NiL, 0, 0); + field[i++] = p; + /*FALLTHROUGH*/ + default: + continue; + } + break; + } + if (!(spec = field[0])) + bad("NIL spec\n", NiL, NiL, 0, 0); + + /* interpret: */ + + cflags = REG_TEST_DEFAULT; + eflags = REG_EXEC_DEFAULT; + test &= TEST_GLOBAL; + state.extracted = 0; + nmatch = 20; + nsub = -1; + for (p = spec; *p; p++) + { + if (isdigit(*p)) + { + nmatch = strtol(p, &p, 10); + if (nmatch >= elementsof(match)) + bad("nmatch must be < 100\n", NiL, NiL, 0, 0); + p--; + continue; + } + switch (*p) + { + case 'A': + test |= TEST_ARE; + continue; + case 'B': + test |= TEST_BRE; + continue; + case 'C': + if (!(test & TEST_QUERY) && !(skip & level)) + bad("locale must be nested\n", NiL, NiL, 0, 0); + test &= ~TEST_QUERY; + if (locale) + bad("locale nesting not supported\n", NiL, NiL, 0, 0); + if (i != 2) + bad("locale field expected\n", NiL, NiL, 0, 0); + if (!(skip & level)) + { +#if defined(LC_COLLATE) && defined(LC_CTYPE) + s = field[1]; + if (!s || streq(s, "POSIX")) + s = "C"; + if (!(ans = setlocale(LC_COLLATE, s)) || streq(ans, "C") || streq(ans, "POSIX") || !(ans = setlocale(LC_CTYPE, s)) || streq(ans, "C") || streq(ans, "POSIX")) + skip = note(level, s, skip, test); + else + { + if (!(test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_SUMMARY))) + printf("NOTE \"%s\" locale\n", s); + locale = level; + } +#else + skip = note(level, skip, test, "locales not supported"); +#endif + } + cflags = NOTEST; + continue; + case 'E': + test |= TEST_ERE; + continue; + case 'K': + test |= TEST_KRE; + continue; + case 'L': + test |= TEST_LRE; + continue; + case 'S': + test |= TEST_SRE; + continue; + + case 'a': + cflags |= REG_LEFT|REG_RIGHT; + continue; + case 'b': + eflags |= REG_NOTBOL; + continue; + case 'c': + cflags |= REG_COMMENT; + continue; + case 'd': + cflags |= REG_SHELL_DOT; + continue; + case 'e': + eflags |= REG_NOTEOL; + continue; + case 'f': + cflags |= REG_MULTIPLE; + continue; + case 'g': + cflags |= NOTEST; + continue; + case 'h': + cflags |= REG_MULTIREF; + continue; + case 'i': + cflags |= REG_ICASE; + continue; + case 'j': + cflags |= REG_SPAN; + continue; + case 'k': + cflags |= REG_ESCAPE; + continue; + case 'l': + cflags |= REG_LEFT; + continue; + case 'm': + cflags |= REG_MINIMAL; + continue; + case 'n': + cflags |= REG_NEWLINE; + continue; + case 'o': + cflags |= REG_SHELL_GROUP; + continue; + case 'p': + cflags |= REG_SHELL_PATH; + continue; + case 'q': + cflags |= REG_DELIMITED; + continue; + case 'r': + cflags |= REG_RIGHT; + continue; + case 's': + cflags |= REG_SHELL_ESCAPED; + continue; + case 't': + cflags |= REG_MUSTDELIM; + continue; + case 'u': + test |= TEST_UNSPECIFIED; + continue; + case 'w': + cflags |= REG_NOSUB; + continue; + case 'x': + if (REG_LENIENT) + cflags |= REG_LENIENT; + else + test |= TEST_LENIENT; + continue; + case 'y': + eflags |= REG_LEFT; + continue; + case 'z': + cflags |= REG_NULL; + continue; + + case '$': + test |= TEST_EXPAND; + continue; + + case '/': + test |= TEST_SUB; + continue; + + case '?': + test |= TEST_VERIFY; + test &= ~(TEST_AND|TEST_OR); + state.verify = state.passed; + continue; + case '&': + test |= TEST_VERIFY|TEST_AND; + test &= ~TEST_OR; + continue; + case '|': + test |= TEST_VERIFY|TEST_OR; + test &= ~TEST_AND; + continue; + case ';': + test |= TEST_OR; + test &= ~TEST_AND; + continue; + + case '{': + level <<= 1; + if (skip & (level >> 1)) + { + skip |= level; + cflags = NOTEST; + } + else + { + skip &= ~level; + test |= TEST_QUERY; + } + continue; + case '}': + if (level == 1) + bad("invalid {...} nesting\n", NiL, NiL, 0, 0); + if ((skip & level) && !(skip & (level>>1))) + { + if (!(test & (TEST_BASELINE|TEST_SUMMARY))) + { + if (test & (TEST_ACTUAL|TEST_FAIL)) + printf("}\n"); + else if (!(test & TEST_PASS)) + printf("-%d\n", state.lineno); + } + } +#if defined(LC_COLLATE) && defined(LC_CTYPE) + else if (locale & level) + { + locale = 0; + if (!(skip & level)) + { + s = "C"; + setlocale(LC_COLLATE, s); + setlocale(LC_CTYPE, s); + if (!(test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_SUMMARY))) + printf("NOTE \"%s\" locale\n", s); + else if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_PASS)) + printf("}\n"); + } + else if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL)) + printf("}\n"); + } +#endif + level >>= 1; + cflags = NOTEST; + continue; + + default: + bad("bad spec\n", spec, NiL, 0, test); + break; + + } + break; + } + if ((cflags|eflags) == NOTEST || ((skip & level) && (test & TEST_BASELINE))) + { + if (test & TEST_BASELINE) + { + while (i > 1) + *delim[--i] = '\t'; + printf("%s\n", line); + } + continue; + } + if (test & TEST_OR) + { + if (!(test & TEST_VERIFY)) + { + test &= ~TEST_OR; + if (state.passed == state.verify && i > 1) + printf("NOTE\t%s\n", field[1]); + continue; + } + else if (state.passed > state.verify) + continue; + } + else if (test & TEST_AND) + { + if (state.passed == state.verify) + continue; + state.passed = state.verify; + } + if (i < 4) + bad("too few fields\n", NiL, NiL, 0, test); + while (i < elementsof(field)) + field[i++] = 0; + if ((re = field[1])) + { + if (streq(re, "SAME")) + { + re = ppat; + test |= TEST_SAME; + } + else + { + if (test & TEST_EXPAND) + escape(re); + strcpy(ppat = pat, re); + } + } + else + ppat = 0; + nstr = -1; + if ((s = field[2]) && (test & TEST_EXPAND)) + { + nstr = escape(s); +#if _REG_nexec + if (nstr != strlen(s)) + nexec = nstr; +#endif + } + if (!(ans = field[3])) + bad("NIL answer\n", NiL, NiL, 0, test); + msg = field[4]; + fflush(stdout); + if (test & TEST_SUB) +#if _REG_subcomp + cflags |= REG_DELIMITED; +#else + continue; +#endif + + compile: + + if (state.extracted || (skip & level)) + continue; +#if !(REG_TEST_DEFAULT & (REG_AUGMENTED|REG_EXTENDED|REG_SHELL)) +#ifdef REG_EXTENDED + if (REG_EXTENDED != 0 && (test & TEST_BRE)) +#else + if (test & TEST_BRE) +#endif + { + test &= ~TEST_BRE; + flags = cflags; + state.which = "BRE"; + } + else +#endif +#ifdef REG_EXTENDED + if (test & TEST_ERE) + { + test &= ~TEST_ERE; + flags = cflags | REG_EXTENDED; + state.which = "ERE"; + } + else +#endif +#ifdef REG_AUGMENTED + if (test & TEST_ARE) + { + test &= ~TEST_ARE; + flags = cflags | REG_AUGMENTED; + state.which = "ARE"; + } + else +#endif +#ifdef REG_LITERAL + if (test & TEST_LRE) + { + test &= ~TEST_LRE; + flags = cflags | REG_LITERAL; + state.which = "LRE"; + } + else +#endif +#ifdef REG_SHELL + if (test & TEST_SRE) + { + test &= ~TEST_SRE; + flags = cflags | REG_SHELL; + state.which = "SRE"; + } + else +#ifdef REG_AUGMENTED + if (test & TEST_KRE) + { + test &= ~TEST_KRE; + flags = cflags | REG_SHELL | REG_AUGMENTED; + state.which = "KRE"; + } + else +#endif +#endif + { + if (test & (TEST_BASELINE|TEST_PASS|TEST_VERIFY)) + extract(tabs, line, re, s, ans, msg, NiL, NiL, 0, 0, skip, level, test|TEST_OK); + continue; + } + if ((test & (TEST_QUERY|TEST_VERBOSE|TEST_VERIFY)) == TEST_VERBOSE) + { + printf("test %-3d %s ", state.lineno, state.which); + quote(re, -1, test|TEST_DELIMIT); + printf(" "); + quote(s, nstr, test|TEST_DELIMIT); + printf("\n"); + } + + nosub: + fun = "regcomp"; +#if _REG_nexec + if (nstr >= 0 && nstr != strlen(s)) + nexec = nstr; + + else +#endif + nexec = -1; + if (state.extracted || (skip & level)) + continue; + if (!(test & TEST_QUERY)) + testno++; +#ifdef REG_DISCIPLINE + if (state.stack) + stkset(stkstd, state.stack, 0); + flags |= REG_DISCIPLINE; + state.disc.ordinal = 0; + sfstrseek(state.disc.sp, 0, SEEK_SET); +#endif + if (!(test & TEST_CATCH)) + cret = regcomp(&preg, re, flags); + else if (!(cret = setjmp(state.gotcha))) + { + alarm(HUNG); + cret = regcomp(&preg, re, flags); + alarm(0); + } +#if _REG_subcomp + if (!cret && (test & TEST_SUB)) + { + fun = "regsubcomp"; + p = re + preg.re_npat; + if (!(test & TEST_CATCH)) + cret = regsubcomp(&preg, p, NiL, 0, 0); + else if (!(cret = setjmp(state.gotcha))) + { + alarm(HUNG); + cret = regsubcomp(&preg, p, NiL, 0, 0); + alarm(0); + } + if (!cret && *(p += preg.re_npat) && !(preg.re_sub->re_flags & REG_SUB_LAST)) + { + if (catchfree(&preg, flags, tabs, line, re, s, ans, msg, NiL, NiL, 0, 0, skip, level, test)) + continue; + cret = REG_EFLAGS; + } + } +#endif + if (!cret) + { + if (!(flags & REG_NOSUB) && nsub < 0 && *ans == '(') + { + for (p = ans; *p; p++) + if (*p == '(') + nsub++; + else if (*p == '{') + nsub--; + if (nsub >= 0) + { + if (test & TEST_IGNORE_OVER) + { + if (nmatch > nsub) + nmatch = nsub + 1; + } + else if (nsub != preg.re_nsub) + { + if (nsub > preg.re_nsub) + { + if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY)) + skip = extract(tabs, line, re, s, ans, msg, "OK", NiL, 0, 0, skip, level, test|TEST_DELIMIT); + else + { + report("re_nsub incorrect", fun, re, NiL, -1, msg, flags, test); + printf("at least %d expected, %zd returned\n", nsub, preg.re_nsub); + state.errors++; + } + } + else + nsub = preg.re_nsub; + } + } + } + if (!(test & TEST_SUB) && *ans && *ans != '(' && !streq(ans, "OK") && !streq(ans, "NOMATCH")) + { + if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY)) + skip = extract(tabs, line, re, s, ans, msg, "OK", NiL, 0, 0, skip, level, test|TEST_DELIMIT); + else if (!(test & TEST_LENIENT)) + { + report("failed", fun, re, NiL, -1, msg, flags, test); + printf("%s expected, OK returned\n", ans); + } + catchfree(&preg, flags, tabs, line, re, s, ans, msg, NiL, NiL, 0, 0, skip, level, test); + continue; + } + } + else + { + if (test & TEST_LENIENT) + /* we'll let it go this time */; + else if (!*ans || ans[0]=='(' || (cret == REG_BADPAT && streq(ans, "NOMATCH"))) + { + got = 0; + for (i = 1; i < elementsof(codes); i++) + if (cret==codes[i].code) + got = i; + if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY)) + skip = extract(tabs, line, re, s, ans, msg, codes[got].name, NiL, 0, 0, skip, level, test|TEST_DELIMIT); + else + { + report("failed", fun, re, NiL, -1, msg, flags, test); + printf("%s returned: ", codes[got].name); + error(&preg, cret); + } + } + else + { + expected = got = 0; + for (i = 1; i < elementsof(codes); i++) + { + if (streq(ans, codes[i].name)) + expected = i; + if (cret==codes[i].code) + got = i; + } + if (!expected) + { + if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY)) + skip = extract(tabs, line, re, s, ans, msg, codes[got].name, NiL, 0, 0, skip, level, test|TEST_DELIMIT); + else + { + report("failed: invalid error code", NiL, re, NiL, -1, msg, flags, test); + printf("%s expected, %s returned\n", ans, codes[got].name); + } + } + else if (cret != codes[expected].code && cret != REG_BADPAT) + { + if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY)) + skip = extract(tabs, line, re, s, ans, msg, codes[got].name, NiL, 0, 0, skip, level, test|TEST_DELIMIT); + else if (test & TEST_IGNORE_ERROR) + state.ignored++; + else + { + report("should fail and did", fun, re, NiL, -1, msg, flags, test); + printf("%s expected, %s returned: ", ans, codes[got].name); + state.errors--; + state.warnings++; + error(&preg, cret); + } + } + } + goto compile; + } + +#if _REG_nexec + execute: + if (nexec >= 0) + fun = "regnexec"; + else +#endif + fun = "regexec"; + + for (i = 0; i < elementsof(match); i++) + match[i] = state.NOMATCH; + +#if _REG_nexec + if (nexec >= 0) + { + eret = regnexec(&preg, s, nexec, nmatch, match, eflags); + s[nexec] = 0; + } + else +#endif + { + if (!(test & TEST_CATCH)) + eret = regexec(&preg, s, nmatch, match, eflags); + else if (!(eret = setjmp(state.gotcha))) + { + alarm(HUNG); + eret = regexec(&preg, s, nmatch, match, eflags); + alarm(0); + } + } +#if _REG_subcomp + if ((test & TEST_SUB) && !eret) + { + fun = "regsubexec"; + if (!(test & TEST_CATCH)) + eret = regsubexec(&preg, s, nmatch, match); + else if (!(eret = setjmp(state.gotcha))) + { + alarm(HUNG); + eret = regsubexec(&preg, s, nmatch, match); + alarm(0); + } + } +#endif + if (flags & REG_NOSUB) + { + if (eret) + { + if (eret != REG_NOMATCH || !streq(ans, "NOMATCH")) + { + if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY)) + skip = extract(tabs, line, re, s, ans, msg, "NOMATCH", NiL, 0, 0, skip, level, test|TEST_DELIMIT); + else + { + report("REG_NOSUB failed", fun, re, s, nstr, msg, flags, test); + error(&preg, eret); + } + } + } + else if (streq(ans, "NOMATCH")) + { + if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY)) + skip = extract(tabs, line, re, s, ans, msg, NiL, match, nmatch, nsub, skip, level, test|TEST_DELIMIT); + else + { + report("should fail and didn't", fun, re, s, nstr, msg, flags, test); + error(&preg, eret); + } + } + } + else if (eret) + { + if (eret != REG_NOMATCH || !streq(ans, "NOMATCH")) + { + if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY)) + skip = extract(tabs, line, re, s, ans, msg, "NOMATCH", NiL, 0, nsub, skip, level, test|TEST_DELIMIT); + else + { + report("failed", fun, re, s, nstr, msg, flags, test); + if (eret != REG_NOMATCH) + error(&preg, eret); + else if (*ans) + printf("expected: %s\n", ans); + else + printf("\n"); + } + } + } + else if (streq(ans, "NOMATCH")) + { + if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY)) + skip = extract(tabs, line, re, s, ans, msg, NiL, match, nmatch, nsub, skip, level, test|TEST_DELIMIT); + else + { + report("should fail and didn't", fun, re, s, nstr, msg, flags, test); + matchprint(match, nmatch, nsub, NiL, test); + } + } +#if _REG_subcomp + else if (test & TEST_SUB) + { + p = preg.re_sub->re_buf; + if (strcmp(p, ans)) + { + report("failed", fun, re, s, nstr, msg, flags, test); + quote(ans, -1, test|TEST_DELIMIT); + printf(" expected, "); + quote(p, -1, test|TEST_DELIMIT); + printf(" returned\n"); + } + } +#endif + else if (!*ans) + { + if (match[0].rm_so != state.NOMATCH.rm_so) + { + if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY)) + skip = extract(tabs, line, re, s, ans, msg, NiL, NiL, 0, 0, skip, level, test); + else + { + report("failed: no match but match array assigned", NiL, re, s, nstr, msg, flags, test); + matchprint(match, nmatch, nsub, NiL, test); + } + } + } + else if (matchcheck(match, nmatch, nsub, ans, re, s, nstr, flags, test)) + { +#if _REG_nexec + if (nexec < 0 && !nonexec) + { + nexec = nstr >= 0 ? nstr : strlen(s); + s[nexec] = '\n'; + testno++; + goto execute; + } +#endif + if (!(test & (TEST_SUB|TEST_VERIFY)) && !nonosub) + { + if (catchfree(&preg, flags, tabs, line, re, s, ans, msg, NiL, NiL, 0, 0, skip, level, test)) + continue; + flags |= REG_NOSUB; + goto nosub; + } + if (test & (TEST_BASELINE|TEST_PASS|TEST_VERIFY)) + skip = extract(tabs, line, re, s, ans, msg, NiL, match, nmatch, nsub, skip, level, test|TEST_OK); + } + else if (test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS|TEST_QUERY|TEST_SUMMARY|TEST_VERIFY)) + skip = extract(tabs, line, re, s, ans, msg, NiL, match, nmatch, nsub, skip, level, test|TEST_DELIMIT); + if (catchfree(&preg, flags, tabs, line, re, s, ans, msg, NiL, NiL, 0, 0, skip, level, test)) + continue; + goto compile; + } + if (test & TEST_SUMMARY) + printf("tests=%-4d errors=%-4d warnings=%-2d ignored=%-2d unspecified=%-2d signals=%d\n", testno, state.errors, state.warnings, state.ignored, state.unspecified, state.signals); + else if (!(test & (TEST_ACTUAL|TEST_BASELINE|TEST_FAIL|TEST_PASS))) + { + printf("TEST\t%s", unit); + if (subunit) + printf(" %-.*s", subunitlen, subunit); + printf(", %d test%s", testno, testno == 1 ? "" : "s"); + if (state.ignored) + printf(", %d ignored mismatch%s", state.ignored, state.ignored == 1 ? "" : "es"); + if (state.warnings) + printf(", %d warning%s", state.warnings, state.warnings == 1 ? "" : "s"); + if (state.unspecified) + printf(", %d unspecified difference%s", state.unspecified, state.unspecified == 1 ? "" : "s"); + if (state.signals) + printf(", %d signal%s", state.signals, state.signals == 1 ? "" : "s"); + printf(", %d error%s\n", state.errors, state.errors == 1 ? "" : "s"); + } + if (fp != stdin) + fclose(fp); + } + return 0; +} + +int main(int argc, char **argv) +{ + static char *param[][4] = { + { NULL, "basic.dat" , NULL }, + { NULL, "categorize.dat" , NULL }, + { NULL, "forcedassoc.dat" , NULL }, + { NULL, "-c", "interpretation.dat", NULL }, + { NULL, "leftassoc.dat" , NULL }, + { NULL, "-c", "nullsubexpr.dat" , NULL }, + { NULL, "repetition.dat" , NULL }, + { NULL, "rightassoc.dat" , NULL }, + }; + int r, i; + + if (argv[1]) + return old_main(argc, argv); + + r = 0; + for (i = 0; i < sizeof(param) / sizeof(param[0]); i++) { + param[i][0] = argv[0]; + printf("Testing %s\n", param[i][1][0] != '-' ? param[i][1] : param[i][2]); + r |= old_main(3 /* not used */, param[i]); + } + return r; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/regex/tst-regex2.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/regex/tst-regex2.c new file mode 100644 index 00000000..2e3260a0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/regex/tst-regex2.c @@ -0,0 +1,250 @@ +#define _GNU_SOURCE 1 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int +do_test(void) +{ + static const char *pat[] = { + ".?.?.?.?.?.?.?Log\\.13", + "(.?)(.?)(.?)(.?)(.?)(.?)(.?)Log\\.13", + "((((((((((.?))))))))))((((((((((.?))))))))))((((((((((.?))))))))))" + "((((((((((.?))))))))))((((((((((.?))))))))))((((((((((.?))))))))))" + "((((((((((.?))))))))))Log\\.13" + }; + char *buf, *string; + const char *fname = "tst-regex2.dat"; + struct stat st; + unsigned len; + int testno; + int exitcode = 0; + + int fd = open(fname, O_RDONLY); + if (fd < 0) { + printf("Couldn't open %s: %s\n", fname, strerror(errno)); + return 1; + } + if (fstat(fd, &st) < 0) { + printf("Couldn't fstat %s: %s\n", fname, strerror(errno)); + return 1; + } + len = st.st_size; + string = buf = malloc(len + 1); + if (buf == NULL) { + printf("Couldn't allocate %u bytes\n", len + 1); + return 1; + } + if (read(fd, buf, st.st_size) != (ssize_t) st.st_size) { + printf("Couldn't read %s\n", fname); + return 1; + } + + close(fd); + buf[len] = '\0'; + +#if defined __UCLIBC_HAS_XLOCALE__ || !defined __UCLIBC__ + setlocale(LC_ALL, "de_DE.UTF-8"); +#endif + + for (testno = 0; testno < 2; ++testno) { + int i; + for (i = 0; i < sizeof(pat) / sizeof(pat[0]); ++i) { + struct timeval start, stop; + regex_t rbuf; + int err; + + printf("test %d pattern %d '%s'\n", testno, i, pat[i]); + gettimeofday(&start, NULL); + + err = regcomp(&rbuf, pat[i], + REG_EXTENDED | (testno ? REG_NOSUB : 0)); + if (err != 0) { + char errstr[300]; + regerror(err, &rbuf, errstr, sizeof(errstr)); + puts(errstr); + exitcode = 1; + goto contin1; + } + + regmatch_t pmatch[71]; + err = regexec(&rbuf, string, 71, pmatch, 0); + if (err == REG_NOMATCH) { + puts("regexec failed"); + exitcode = 1; + goto contin1; + } + + if (testno == 0) { + if (pmatch[0].rm_eo != pmatch[0].rm_so + 13 + || pmatch[0].rm_eo > len + || pmatch[0].rm_so < len - 100 + || strncmp(string + pmatch[0].rm_so, + " ChangeLog.13 for earlier changes", + sizeof " ChangeLog.13 for earlier changes" - 1 + ) != 0 + ) { + puts("regexec without REG_NOSUB did not find the correct match"); + exitcode = 1; + goto contin1; + } + + if (i > 0) { + int j, k, l; + for (j = 0, l = 1; j < 7; ++j) { + for (k = 0; k < (i == 1 ? 1 : 10); ++k, ++l) { + if (pmatch[l].rm_so != pmatch[0].rm_so + j + || pmatch[l].rm_eo != pmatch[l].rm_so + 1 + ) { + printf("pmatch[%d] incorrect\n", l); + exitcode = 1; + goto contin1; + } + } + } + } + } + + gettimeofday(&stop, NULL); + stop.tv_sec -= start.tv_sec; + if (stop.tv_usec < start.tv_usec) { + stop.tv_sec--; + stop.tv_usec += 1000000; + } + stop.tv_usec -= start.tv_usec; + printf(" %lu.%06lus\n", (unsigned long) stop.tv_sec, + (unsigned long) stop.tv_usec); + contin1: + regfree(&rbuf); + } + } + + for (testno = 2; testno < 4; ++testno) { + int i; + for (i = 0; i < sizeof(pat) / sizeof(pat[0]); ++i) { + struct timeval start, stop; + struct re_pattern_buffer rpbuf; + struct re_registers regs; + const char *s; + int match; + + printf("test %d pattern %d '%s'\n", testno, i, pat[i]); + gettimeofday(&start, NULL); + + re_set_syntax(RE_SYNTAX_POSIX_EGREP + | (testno == 3 ? RE_NO_SUB : 0)); + memset(&rpbuf, 0, sizeof(rpbuf)); + s = re_compile_pattern(pat[i], strlen(pat[i]), &rpbuf); + if (s != NULL) { + printf("%s\n", s); + exitcode = 1; + goto contin2; + } + + memset(®s, 0, sizeof(regs)); + match = re_search(&rpbuf, string, len, 0, len, ®s); + if (match < 0) { + printf("re_search failed (err:%d)\n", match); + exitcode = 1; + goto contin2; + } + if (match + 13 > len) { + printf("re_search: match+13 > len (%d > %d)\n", match + 13, len); + exitcode = 1; + goto contin2; + } + if (match < len - 100) { + printf("re_search: match < len-100 (%d < %d)\n", match, len - 100); + exitcode = 1; + goto contin2; + } + if (strncmp(string + match, " ChangeLog.13 for earlier changes", + sizeof(" ChangeLog.13 for earlier changes") - 1 + ) != 0 + ) { + printf("re_search did not find the correct match" + "(found '%s' instead)\n", string + match); + exitcode = 1; + goto contin2; + } + + if (testno == 2) { + int expected = 72; + if (i == 0) + expected = 2; + if (i == 1) + expected = 9; + if (regs.num_regs != expected) { + printf("incorrect num_regs %d, expected %d\n", regs.num_regs, expected); + exitcode = 1; + goto contin2; + } + if (regs.start[0] != match || regs.end[0] != match + 13) { + printf("incorrect regs.{start,end}[0] = { %d, %d }," + " expected { %d, %d }\n", + regs.start[0], regs.end[0], + match, match + 13 + ); + exitcode = 1; + goto contin2; + } + if (regs.start[regs.num_regs - 1] != -1 + || regs.end[regs.num_regs - 1] != -1 + ) { + printf("incorrect regs.{start,end}[num_regs - 1] = { %d, %d }," + " expected { -1, -1 }\n", + regs.start[regs.num_regs - 1], regs.end[regs.num_regs - 1] + ); + exitcode = 1; + goto contin2; + } + + if (i > 0) { + int j, k, l; + for (j = 0, l = 1; j < 7; ++j) { + for (k = 0; k < (i == 1 ? 1 : 10); ++k, ++l) { + if (regs.start[l] != match + j + || regs.end[l] != match + j + 1 + ) { + printf("incorrect regs.{start,end}[%d] = { %d, %d }," + " expected { %d, %d }\n", + l, + regs.start[l], regs.end[l], + match + j, match + j + 1 + ); + exitcode = 1; + goto contin2; + } + } + } + } + } + + gettimeofday(&stop, NULL); + stop.tv_sec -= start.tv_sec; + if (stop.tv_usec < start.tv_usec) { + stop.tv_sec--; + stop.tv_usec += 1000000; + } + stop.tv_usec -= start.tv_usec; + printf(" %lu.%06lus\n", (unsigned long) stop.tv_sec, + (unsigned long) stop.tv_usec); + contin2: + regfree(&rpbuf); + } + } + return exitcode; +} + +#define TIMEOUT 20 +#define TEST_FUNCTION do_test() +#include "../test-skeleton.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/regex/tst-regex2.dat b/l4/pkg/uclibc/lib/contrib/uclibc/test/regex/tst-regex2.dat new file mode 100644 index 00000000..ace9f3b6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/regex/tst-regex2.dat @@ -0,0 +1,2176 @@ +2002-11-19 Ulrich Drepper + + * intl/localealias.c (read_alias_file): Use only about 400 bytes + of stack space instead of 16k. + +2002-11-18 Wolfram Gloger + + * malloc/arena.c + (ptmalloc_lock_all, ptmalloc_unlock_all, ptmalloc_unlock_all2): Do + nothing if not initialized. Bug report from Marcus Brinkmann + . + +2002-11-19 Roland McGrath + + * posix/Versions (libc: GLIBC_2.3.2): Add sched_getaffinity and + sched_setaffinity. + + * configure.in (libc_cv_gcc_dwarf2_unwind_info check): Use libraries + `-lgcc -lgcc_eh -lgcc', not just `-lgcc -lgcc_eh' in link commands for + test leading to libc_cv_gcc_dwarf2_unwind_info=no_registry_needed. + * configure: Regenerated. + +2002-11-19 Ulrich Drepper + + * include/dlfcn.h: __libc_dlopen is now a macro calling + __libc_dlopen_mode with the extra parameter RTLD_LAZY. + (__libc_dlopen_mode): New prototype. + * elf/dl-libc.c (__libc_dlopen_mode): Renamed from __libc_dlopen. Add + new parameter. Store new parameter in mode field of structure passed + to do_dlopen. + (struct do_dlopen_args): Add new field mode. + (do_dlopen): Pass mode from parameter structure to _dl_open. + +2002-11-11 Randolf Chung + + * sysdeps/unix/sysv/linux/hppa/bits/fcntl.h [__USE_FILE_OFFSET64] + (F_GETLK, F_SETLK, F_SETLKW): Define to F_*64 versions. + * sysdeps/unix/sysv/linux/hppa/fcntl.c: New file. + + * sysdeps/hppa/fpu/libm-test-ulps: New file (generated). + + * sysdeps/hppa/Makefile (CFLAGS-rtld.c): New variable. + Set -mdisable-fpregs for this file. + +2002-11-11 Carlos O'Donell + + * sysdeps/unix/sysv/linux/configure.in: + Make 2.4.19 minimum linux kernel for hppa, and add unwind symbols + from gcc-3.0 era for backwards compatibility. + * sysdeps/unix/sysv/linux/configure: Regenerate. + + * sysdeps/unix/sysv/linux/hppa/sys/ucontext.h: + Define mcontext_t as a sigcontext. + +2002-11-18 Roland McGrath + + * dlfcn/dlerror.c (fini): New function, __attribute__ ((destructor)). + Free memory in `last_result' if it was used. + + * resolv/nss_dns/dns-network.c (getanswer_r): In BYNAME case, search + all aliases for one that matches the ".IN-ADDR.ARPA" form. + Do the parsing inline instead of copying strings and calling + inet_network, and properly skip all alias names not matching the form. + + * manual/pattern.texi (Variable Substitution): Fix # and ## examples. + +2002-11-17 Ulrich Drepper + + * manual/pattern.texi (Wordexp Example): Fix sample code. + + * sysdeps/unix/sysv/linux/i386/clone.S: Initialize word in the + childs stack which will be loaded into the %esi register. + +2002-11-14 Paul Eggert + + * resolv/nss_dns/dns-network.c (getanswer_r): Check for buffer + overflow when skipping the question part and when unpacking aliases. + +2002-11-15 Roland McGrath + + * math/Makefile (libm-calls): Remove s_copysign, s_isinf, s_isnan, + s_finite, s_modf, s_scalbn, s_frexp, m_ldexp, s_signbit. + Instead add $(calls:s_%=m_%) to get m_* versions of them all. + +2002-11-15 Jakub Jelinek + + * sysdeps/i386/dl-machine.h (elf_machine_rela): Handle R_386_COPY. + * sysdeps/arm/dl-machine.h (elf_machine_rela): Handle R_ARM_COPY. + +2002-11-15 Roland McGrath + + * math/Makefile (libm-calls): Change s_ldexp to m_ldexp. + * Makerules ($(+sysdir_pfx)sysd-rules): Emit pattern rules for m_%.[Sc] + from sysdeps/.../s_%.[Sc] with commands $(+make-include-of-dep). + (+make-include-of-dep): New canned sequence. + + * stdlib/canonicalize.c (__realpath): Check for malloc failure. + From Dmitry V. Levin . + +2002-11-14 Roland McGrath + + * sysdeps/generic/errno.c (__libc_errno): Remove alias. + * inet/herrno.c (__libc_h_errno): Likewise. + * resolv/res_libc.c (__libc_res): Likewise. + [USE___THREAD]: Use this in place of [USE_TLS && HAVE___THREAD]. + (__res_state) [! USE___THREAD]: Don't define as weak. + * csu/Versions: Revert last change. + * resolv/Versions: Revert last change. + + * Makerules ($(common-objpfx)%.make): New pattern rule. + * tls.make.c: New file. + * Makefile (distribute): Add it. + + * sysdeps/generic/errno.c [! USE___THREAD] + [HAVE_ELF && SHARED && DO_VERSIONING] (errno, _errno): Declare these + with compat_symbol so they are not link-time visible. + [! USE___THREAD] (__libc_errno): New alias for errno. + * csu/Versions [!(USE_TLS && HAVE___THREAD)] (libc: GLIBC_PRIVATE): + Add __libc_errno here. + * inet/herrno.c [USE___THREAD]: Use this conditional + in place of [USE_TLS && HAVE___THREAD]. + [! USE___THREAD] [HAVE_ELF && SHARED && DO_VERSIONING] + (h_errno, _h_errno): Declare these with compat_symbol so they are not + link-time visible. + [! USE___THREAD] (__libc_h_errno): New alias for h_errno. + * resolv/res_libc.c [! USE___THREAD] + [HAVE_ELF && SHARED && DO_VERSIONING] (_res): Likewise. + (_res): Use __attribute__ ((section (".bss"))) so we can have an alias. + (__libc_res): Define as alias for _res. + * resolv/Versions [!(USE_TLS && HAVE___THREAD)] (libc: GLIBC_PRIVATE): + Add __libc_h_errno and __libc_res here. + +2002-11-14 Jakub Jelinek + + * csu/Versions (errno): Move STT_TLS symbol to GLIBC_PRIVATE for now. + * resolv/Versions (h_errno, _res): Likewise. + +2002-11-14 Roland McGrath + + * Makerules (%.dynsym): Remove $(objpfx) from target and dep. + (%.symlist): Likewise. + +2002-11-13 Roland McGrath + + * scripts/abilist.awk: New file. + * Makefile (distribute): Add it. + * Makerules ($(objpfx)%.dynsym, $(objpfx)%.symlist): New rules. + (tests): Depend on .symlist file for each $(install-lib.so-versioned). + [$(subdir) = elf] (tests): Depend on libc.symlist. + (generated, common-generated): Add those files. + + * aclocal.m4 (LIBC_PROG_BINUTILS): Check for objdump, set OBJDUMP. + * configure: Regenerated. + * config.make.in (OBJDUMP): New variable, substituted by configure. + + * malloc/mcheck.c (struct hdr): New members `block' and `magic2'. + (mallochook, reallochook): Set them up. + (checkhdr): Check HDR->magic2 value. + (freehook): Reset HDR->magic2. + (memalignhook): New static function. + (old_memalign_hook): New static variable. + (mcheck, reallochook): Set __memalign_hook to memalignhook. + + * sysdeps/generic/dl-tls.c (_dl_allocate_tls_storage): Zero the space + for the new TCB. + +2002-11-13 Andreas Jaeger + + * sysdeps/unix/sysv/linux/x86_64/sigaction.c: Check for visibility + attribute. + * sysdeps/unix/sysv/linux/i386/sigaction.c: Likewise. + +2002-11-11 Paul Eggert + + * manual/crypt.texi (Cryptographic Functions): Mention that + the MD5 one-way algorithm is compatible with BSD's. + +2002-11-11 Isamu Hasegawa + + * posix/regex_internal.c (re_string_skip_chars): Also return the last + wide character. + (re_string_reconstruct): Calculate the context by itself when the + offset points out of the valid range. + (re_string_context_at): Use wide character when MB_CUR_MAX > 1. + * posix/regex_internal.h (WIDE_NEWLINE_CHAR): New macro. + (IS_WIDE_WORD_CHAR): New macro. + (IS_WIDE_NEWLINE): New macro. + +2002-11-12 Andreas Jaeger + + * sysdeps/x86_64/strchr.S: Don't use one register for two + purposes, this fixes a bug noticed by test-strchr.c. + + * sysdeps/x86_64/strcat.S: Fix algorithm to align source pointer + correctly. + +2002-11-12 Roland McGrath + + * libio/libioP.h [_LIBC && !SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1)] + (_G_IO_NO_BACKWARD_COMPAT): Define it. + + * sysdeps/ia64/dl-fptr.c [_LIBC_REENTRANT]: Include + instead of . + [_LIBC_REENTRANT] (lock, unlock): Use __sync_lock_* macros instead of + testandset. + From Ian Wienand . + +2002-11-10 Roland McGrath + + * libio/bug-wfflush.c (do_test): Call rewind instead of fsetpos. + Call fputs instead of fwprintf (simpler to follow in debugger). + + * crypt/md5-crypt.c: Doc fix. + + * sysdeps/unix/make-syscalls.sh: Insert $(make-target-directory) at + the beginning of generated target commands. + + * csu/Makefile ($(objpfx)crti.o, $(objpfx)crtn.o): Add explicit + dependencies for these in case implicit rule search skipped the + nonexistent source directory. + * sysdeps/gnu/Makefile ($(objpfx)errlist.d): Give this rule all the + files with $(object-suffixes) as targets too. + * Makerules [no_deps && objpfx] (before-compile): Add $(objpfx). + and a target for it using $(make-target-directory). + + * Rules (before-compile): Add $(common-objpfx)bits/stdio-lim.h. + +2002-11-10 Roland McGrath + + * sysdeps/unix/sysv/linux/bits/pthreadtypes.h: Moved to ... + * sysdeps/generic/bits/pthreadtypes.h: ... here. + + * sysdeps/mach/hurd/fcntl.c (__libc_fcntl): Treat a struct flock with + l_start == 0 and l_len == 1 as we do l_len == 0. + +2002-11-10 Ulrich Drepper + + * po/da.po: Update from translation team. + +2002-11-10 Roland McGrath + + * config.make.in (includedir): New variable, substituted by configure. + Reported missing by Jocelyn Fournier . + * Makeconfig (includedir): Use $(prefix), not $(exec_prefix). + +2002-11-10 Andreas Jaeger + + * sysdeps/unix/sysv/linux/x86_64/sys/ucontext.h (enum): Add + REG_OLDMASK and REG_CR2 to synch with kernel header. + (NGREG): Increase. + + * nss/getXXent.c (GETFUNC_NAME): Use union type to avoid strict + aliasing problem. + * nss/getXXbyYY_r.c (INTERNAL): Likewise. + * nss/getnssent_r.c (__nss_getent_r): Likewise. + (__nss_setent): Likewise. + (__nss_getent_r): Likewise. + * inet/getnetgrent_r.c (innetgr): Likewise. + (__internal_setnetgrent_reuse): Likewise. + (internal_getnetgrent_r): Likewise. + * inet/ether_hton.c (ether_hostton): Likewise. + * inet/ether_ntoh.c (ether_ntohost): Likewise. + * sunrpc/netname.c (netname2user): Likewise. + * sunrpc/publickey.c (getpublickey): Likewise. + (getsecretkey): Likewise. + +2002-11-09 Marcus Brinkmann + + * sysdeps/mach/hurd/i386/ioperm.c (ioperm): Correct off by one + error in range calculation. + +2002-10-09 Jakub Jelinek + + * string/test-strspn.c (do_test): Ensure zero termination. + * string/test-strpbrk.c (do_test): Likewise. + * string/test-strncmp.c (stupid_strncmp): Use strnlen, not strlen. + * string/test-strncpy.c (stupid_strncpy): Likewise. + * string/test-stpncpy.c (stupid_stpncpy): Likewise. + +2002-10-08 Roland McGrath + + * string/test-string.h (test_init): Fill BUF1 and BUF2 with + nonzero characters. + +2002-09-22 H.J. Lu + + * sysdeps/unix/sysv/linux/mmap64.c (MMAP2_PAGE_SHIFT): Renamed + from PAGE_SHIFT. Define if not defined. Check MMAP2_PAGE_SHIFT + only if __NR_mmap2 is defined. + + * sysdeps/unix/sysv/linux/powerpc/mmap64.c: Moved to ... + * sysdeps/unix/sysv/linux/mmap64.c: ... here. + * sysdeps/unix/sysv/linux/hppa/mmap64.c: File removed. + * sysdeps/unix/sysv/linux/sparc/sparc32/mmap64.c: FIle removed, + +2002-11-08 Jakub Jelinek + + * posix/bug-regex13.c (tests): Add new test. + + * string/test-strchr.c (stupid_strchr): New function. + (do_random_tests): Make sure the string is zero terminated. + * string/test-strpbrk.c (stupid_strpbrk): New function. + (do_random_tests): Make sure the string is zero terminated. + * string/test-strcmp.c (stupid_strcmp): New function. + (do_random_tests): Make sure the strings are zero terminated. + * string/test-strspn.c (stupid_strspn): New function. + (simple_strspn): Rename rej argument to acc. + (do_random_tests): Make sure the string is zero terminated. + * string/test-strcspn.c (stupid_strcspn): New function. + * string/test-strncpy.c (stupid_strncpy): New function. + * string/test-stpncpy.c (stupid_stpncpy): New function. + * string/test-strncmp.c (stupid_strncmp): New function. + (do_random_tests): Make sure the strings are zero terminated. + * string/test-string.h (impl_t): Change test into long. + (IMPL): Add __attribute__((aligned (sizeof (void *)))). + +2002-11-08 Roland McGrath + + * sysdeps/ia64/elf/configure.in: Add TLS check. + From Ian Wienand . + * sysdeps/ia64/elf/configure: Regenerated. + +2002-11-07 Roland McGrath + + * libio/fileops.c (_IO_new_file_overflow): Use INTUSE(_IO_do_write) in + place of _IO_new_do_write. + [_LIBC] (_IO_do_write): Define as macro for _IO_new_do_write and + #undef before versioned_symbol use. + +2002-11-07 Richard Henderson + + * configure.in (ASM_ALPHA_NG_SYMBOL_PREFIX): Remove test. + * configure: Regenerated. + * config.h.in (ASM_ALPHA_NG_SYMBOL_PREFIX): Remove #undef. + * sysdeps/alpha/dl-machine.h (TRAMPOLINE_TEMPLATE): Use !samegp. + (RTLD_START): Likewise. Access _dl_skip_args, _rtld_local, and + _dl_fini via gp-relative relocations. + * sysdeps/alpha/fpu/e_sqrt.c: Use !samegp. + + * elf/tls-macros.h: Add alpha versions. + * sysdeps/alpha/dl-machine.h (elf_machine_rela): Handle TLS relocs. + * sysdeps/unix/alpha/sysdep.S: Support USE___THREAD. + * sysdeps/unix/alpha/sysdep.h: Likewise. Add SYSCALL_ERROR_HANDLER. + * sysdeps/unix/sysv/linux/alpha/brk.S: Use it. + * sysdeps/unix/sysv/linux/alpha/clone.S: Likewise. + * sysdeps/unix/sysv/linux/alpha/getitimer.S: Likewise. + * sysdeps/unix/sysv/linux/alpha/getrusage.S: Likewise. + * sysdeps/unix/sysv/linux/alpha/gettimeofday.S: Likewise. + * sysdeps/unix/sysv/linux/alpha/ieee_get_fp_control.S: Likewise. + * sysdeps/unix/sysv/linux/alpha/ieee_set_fp_control.S: Likewise. + * sysdeps/unix/sysv/linux/alpha/rt_sigaction.S: Likewise. + * sysdeps/unix/sysv/linux/alpha/select.S: Likewise. + * sysdeps/unix/sysv/linux/alpha/setitimer.S: Likewise. + * sysdeps/unix/sysv/linux/alpha/settimeofday.S: Likewise. + * sysdeps/unix/sysv/linux/alpha/sigsuspend.S: Likewise. + * sysdeps/unix/sysv/linux/alpha/syscall.S: Likewise. + * sysdeps/unix/sysv/linux/alpha/utimes.S: Likewise. + * sysdeps/unix/sysv/linux/alpha/wait4.S: Likewise. + + * sysdeps/unix/sysv/linux/alpha/sysdep.h: Re-include protect. + Kill argument registers across the inline syscall. + + * sysdeps/unix/sysv/linux/alpha/clone.S: Add user_tid and tls args. + + * linuxthreads/sysdeps/alpha/tls.h: New file. + * sysdeps/alpha/dl-tls.h: New file. + +2002-10-29 David Mosberger + + * sysdeps/ia64/elf/initfini.c [HAVE_INITFINI_ARRAY] + (gmon_initializer): New function. + (.init prologue): If HAVE_INITFINI_ARRAY is true, don't call + __gmon_start__ here. Call it from gmon_initializer() instead. + +2002-03-12 H.J. Lu + + * elf/Makefile [$(have-initfini-array) = yes] (tests): Add tst-array1, + tst-array2, and tst-array3. + [$(have-initfini-array) = yes] (tests-static): Add tst-array3. + [$(have-initfini-array) = yes] (modules-names): Add tst-array2dep. + ($(objpfx)tst-array1.out): New target. + ($(objpfx)tst-array2): Likewise. + ($(objpfx)tst-array2.out): Likewise. + ($(objpfx)tst-array3.out): Likewise. + * elf/tst-array1.c: New file. + * elf/tst-array1.exp: Likewise. + * elf/tst-array2.c: Likewise. + * elf/tst-array2dep.c: Likewise. + * elf/tst-array2.exp: Likewise. + * elf/tst-array3.c: Likewise. + +2002-10-28 David Mosberger + + * elf/dl-fini.c (_dl_fini): Invoke fini_array in _reverse_ order. + Don't add L->l_addr to array entry values. + +2002-11-07 Jakub Jelinek + + * string/test-string.h: New file. + * string/test-strlen.c: New file. + * string/test-string.h: New file. + * string/test-strcmp.c: New file. + * string/test-strchr.c: New file. + * string/test-strrchr.c: New file. + * string/test-strcpy.c: New file. + * string/test-stpcpy.c: New file. + * string/test-strncpy.c: New file. + * string/test-stpncpy.c: New file. + * string/test-strpbrk.c: New file. + * string/test-strcspn.c: New file. + * string/test-strspn.c: New file. + * string/test-strcat.c: New file. + * string/test-strncmp.c: New file. + * string/test-memchr.c: New file. + * string/test-memcmp.c: New file. + * string/test-memset.c: New file. + * string/test-memcpy.c: New file. + * string/test-mempcpy.c: New file. + * string/test-memmove.c: New file. + * string/Makefile (strop-tests): New variable. + (tests): Add strop-tests. + (distribute): Add test-string.h. + +2002-11-06 Ulrich Drepper + + * posix/regcomp.c: Use tabs instead of spaces. + * posix/regexec.c: Likewise. + * posix/regex_internal.h: Likewise. + + * posix/regcomp.c (re_compile_fastmap_iter): Use __wcrtomb not wctomb. + +2002-11-06 Jakub Jelinek + + * posix/regcomp.c (re_compile_pattern): Don't set regs_allocated + here. + (regcomp): Don't set can_be_null here. + (re_comp): Clear whole re_comp_buf with the exception of fastmap. + (re_compile_internal): Clear can_be_null, set regs_allocated. + + * posix/regcomp.c (re_set_fastmap): New function. + (re_compile_fastmap_iter): Use it. Remove redundant type == + COMPLEX_BRACKET check. + * posix/regexec.c (re_search_internal): Optimize searching with + fastmap. Call re_string_reconstruct even if match_first is + smaller than raw_mbs_idx. + +2002-11-06 Isamu Hasegawa + + * posix/regcomp (free_dfa_content): Use free_state. + * posix/regex_internal.c (re_string_realloc_buffers): Don't edit + pointers in case that realloc failed. + (re_node_set_merge): Likewise. + (register_state): Likewise. + (create_newstate_common): Invoke memory release functions in case of + error conditions. + (create_ci_newstate): Likewise. + (create_cd_newstate): Likewise. + (free_state): New function. + * posix/regexec.c (re_search_internal): Invoke memory release + functions in case of error conditions. + (sift_states_backward): Likewise. + (merge_state_array): Likewise. + (add_epsilon_src_nodes): Likewise. + (sub_epsilon_src_nodes): Likewise. + (search_subexp): Likewise. + (sift_states_bkref): Likewise. + (transit_state_sb): Likewise. + (transit_state_mb): Likewise. + (transit_state_bkref_loop): Likewise. + (group_nodes_into_DFAstates): Likewise. + (push_fail_stack): Don't edit pointers in case that realloc failed. + (extend_buffers): Likewise. + (match_ctx_add_entry): Likewise. + +2002-11-06 Roland McGrath + + * sysdeps/unix/sysv/linux/mips/configure.in: File removed. + * sysdeps/unix/sysv/linux/mips/configure: Likewise. + + * configure.in: Add checks on as and ld for binutils 2.13 or later. + * configure: Regenerated. + +2002-11-06 Ulrich Drepper + + * posix/regcomp.c (regcomp): __re_compile_fastmap can never fail. + If re_compile_internal failed free fastmap buffer. + (free_dfa_content): Broken out of regfree function. Frees all dfa + related data. + (regfree): Add free_dfa_content. + (re_compile_internal): If any of the called functions fails free + all dfa related memory. + +2002-11-05 Ulrich Drepper + + * sysdeps/unix/sysv/linux/sys/sysctl.h: Add ugly hacks to prevent + warnings from the kernel headers. + +2002-11-05 Roland McGrath + + * sysdeps/unix/mips/sysdep.h [! __PIC__] (PSEUDO): Add nop after jump. + From Johannes Stezenbach . + + * sysdeps/unix/sysv/linux/mips/Versions (libc: GLIBC_2.0): Change + #errlist-compat magic comment to give 123 as size. + (libc: GLIBC_2.1): Remove this set, moving #errlist-compat magic to ... + (libc: GLIBC_2.2): ... here. + (libc: GLIBC_2.3): Likewise. + +2002-11-05 Ulrich Drepper + + * elf/dl-fini.c (_dl_fini): Correct the increment of l_opencount + which happens at the beginning so that we can unload modules in + __libc_freeres. + +2002-11-06 Kaz Kojima + + * sysdeps/sh/bits/setjmp.h (JB_SIZE): Define only + under [__USE_MISC || _ASM]. + + * elf/elf.h: Remove the obsolete SH TLS relocations. + +2002-11-05 Ulrich Drepper + + * posix/regcomp.c (regcomp): Initialize preg->can_be_null to zero. + +2002-11-05 Franz Sirl + + * sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h: Handle + __NR_pread64 and __NR_pwrite64. + * sysdeps/unix/sysv/linux/powerpc/powerpc64/sysdep.h: Likewise. + * sysdeps/unix/sysv/linux/powerpc/pread.c: Remove __NR_pread64 + and __NR_pwrite64. + Revert change to use INLINE_SYSCALL. + * sysdeps/unix/sysv/linux/powerpc/pread64.c: Likewise. + * sysdeps/unix/sysv/linux/powerpc/pwrite.c: Likewise. + * sysdeps/unix/sysv/linux/powerpc/pwrite64.c: Likewise. + * sysdeps/unix/sysv/linux/powerpc/ftruncate64.c: Revert change to use + INLINE_SYSCALL. + * sysdeps/unix/sysv/linux/powerpc/truncate64.c: Likewise. + + * sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h (INLINE_SYSCALL): + Update clobber list and add a comment about the syscall ABI. + + * sysdeps/unix/sysv/linux/powerpc/powerpc32/syscalls.list (s_pread64, + s_pwrite64, s_ftruncate, s_truncate): Re-add. + +2002-11-05 Jakub Jelinek + + * iconv/gconv_dl.c (free_mem): Clear loaded. + * locale/loadarchive.c (_nl_archive_subfreeres): Call locale_data's + cleanup if any. + +2002-11-05 Ulrich Drepper + + * sysdeps/unix/sysv/linux/fexecve.c: Include . + + * libio/ioseekoff.c: Remove INTDEF. Define _IO_seekoff_unlocked. Same + as old code without locking. _IO_seekoff calls this function after + locking the stream. + * libio/ioseekpos.c: Likewise for _IO_seekpos. + * libio/libioP.h: Replace _IO_seekoff_internal and _IO_seekpos_internal + prototypes with _IO_seekoff_unlocked and _IO_seekpos_unlocked + prototypes. + * libio/iolibio.h (_IO_fseek): Call _IO_seekoff_unlocked instead + of _IO_seekoff_internal. + (_IO_rewind): Likewise. + * libio/ioftell.c: Likewise. + * libio/ftello.c: Likewise. + * libio/ftello64.c: Likewise. + * libio/iofgetpos.c: Likewise. + * libio/iofgetpos64.c: Likewise. + * libio/oldiofgetpos.c: Likewise. + * libio/oldiofgetpos64.c: Likewise. + * libio/iofsetpos.c: Call _IO_seekpos_unlocked instead of + _IO_seekpos_internal. + * libio/iofsetpos64.c: Likewise. + * libio/oldiofsetpos.c: Likewise. + * libio/oldiofsetpos64.c: Likewise. + +2002-11-04 Roland McGrath + + * sysdeps/unix/sysv/linux/powerpc/chown.c: Use INLINE_SYSCALL macro. + * sysdeps/unix/sysv/linux/powerpc/ftruncate64.c: Likewise. + * sysdeps/unix/sysv/linux/powerpc/ioctl.c: Likewise. + * sysdeps/unix/sysv/linux/powerpc/pread.c: Likewise. + * sysdeps/unix/sysv/linux/powerpc/pread64.c: Likewise. + * sysdeps/unix/sysv/linux/powerpc/pwrite.c: Likewise. + * sysdeps/unix/sysv/linux/powerpc/pwrite64.c: Likewise. + * sysdeps/unix/sysv/linux/powerpc/tcgetattr.c: Likewise. + * sysdeps/unix/sysv/linux/powerpc/tcsetattr.c: Likewise. + * sysdeps/unix/sysv/linux/powerpc/truncate64.c: Likewise. + * sysdeps/unix/sysv/linux/powerpc/powerpc32/syscalls.list (s_ioctl, + s_chown, s_ftruncate64, s_mmap2, s_pread64, s_pwrite64, s_truncate64, + sys_fstat, sys_lstat, sys_mknod, sys_readv, sys_stat, sys_writev): + Remove these, no longer used. + +2002-11-04 Franz Sirl + + * sysdeps/unix/sysv/linux/powerpc/powerpc32/syscalls.list (s_ipc, + s_llseek, s_readahead, s_execve, s_fcntl, s_fcntl64, s_fstat64, + s_getcwd, s_getdents, s_getdents64, s_getpmsg, s_getpriority, + s_getrlimit, s_lstat64, s_poll, s_ptrace, s_putpmsg, s_reboot, + s_setrlimit, s_sigaction, s_sigpending, s_sigprocmask, s_sigsuspend, + s_stat64, s_sysctl, s_ugetrlimit, s_ustat, s_vfork): Remove now unused + syscall stubs. + + * sysdeps/unix/sysv/linux/pwrite.c: Fix typo. + * sysdeps/unix/sysv/linux/pwrite64.c: Likewise. + * sysdeps/unix/sysv/linux/powerpc/pread.c: Handle both __NR_pread64 + and __NR_pread. + * sysdeps/unix/sysv/linux/powerpc/pread64.c: Likewise. + * sysdeps/unix/sysv/linux/powerpc/pwrite.c: Handle both __NR_pwrite64 + and __NR_pwrite. + * sysdeps/unix/sysv/linux/powerpc/pwrite64.c: Likewise. + +2002-11-03 Roland McGrath + + * sysdeps/generic/ldsodefs.h (struct rtld_global): New member + `_dl_tls_static_used'. + * sysdeps/generic/libc-tls.c (_dl_tls_static_used): New variable. + (__libc_setup_tls): Initialize it. Let the initial value of + _dl_tls_static_size indicate some surplus space in the computed value. + * elf/dl-open.c (_dl_tls_static_size): New variable. + * sysdeps/generic/dl-tls.c (_dl_determine_tlsoffset): Initialize + _dl_tls_static_used. Add some surplus space into _dl_tls_static_size. + * elf/dl-reloc.c [USE_TLS] (allocate_static_tls): New function. + (CHECK_STATIC_TLS): Use it. + * elf/dl-close.c (_dl_close): Adjust _dl_tls_static_used when the + closed objects occupied a trailing contiguous chunk of static TLS area. + +2002-10-18 Bruno Haible + + * charmaps/ISO_5428: Use Greek characters introduced in Unicode 3.0. + +2002-11-04 Ulrich Drepper + + * libio/wfileops.c (_IO_wfile_seekoff): Don't modify _offset and + _wide_data->_IO_read_end if adjustment can be made in the current + buffer. + + * sysdeps/unix/sysv/linux/fexecve.c: New file. + + * libio/bug-wfflush.c (do_test): Using fseek is not allowed when + wide oriented streams are used. + + * nss/getXXent_r.c (ENDFUNC_NAME): Don't do anything if the + service hasn't been used [PR libc/4744]. + + * include/features.h: Use __STDC_VERSION__ not __STDC_VERSION. + Reported by Miloslav Trmac [PR libc/4766]. + + * manual/examples/dir.c: Don't include . + * manual/examples/select.c: Include for TEMP_FAILURE_RETRY. + Reported by Frédéric Delanoy . + +2002-11-02 H.J. Lu + + * stdio-common/reg-printf.c: Include . + +2002-11-03 Ulrich Drepper + + * sysdeps/generic/libc-tls.c: Define _dl_tls_static_used. + + * po/ca.po: Update from translation team. + * po/es.po: Likewise. + + * sysdeps/generic/segfault.c (catch_segfault): If HAVE_PROC_SELF + is defined write out memory map. + * sysdeps/unix/sysv/linux/segfault.c: New file. + +2002-11-02 Roland McGrath + + * sysdeps/unix/sysv/linux/getdents.c (__GETDENTS): Use union type for + pointers that can alias. + Reported by Daniel Jacobowitz . + + * sysdeps/unix/bsd/bsd4.4/freebsd/bits/typesizes.h: New file. + +2002-11-02 Roland McGrath + + * manual/filesys.texi (Reading/Closing Directory): Rewrite readdir_r + description to be clearer and to say that *RESULT is set to ENTRY. + +2002-10-30 Jakub Jelinek + + * posix/regexec.c (build_trtable): Alloca or malloc dests_node and + dests_ch arrays together. Alloca or malloc dest_states, + dest_states_word and dest_states_nl arrays together. Free memory on + error exit. + +2002-10-29 Daniel Jacobowitz + + * crypt/crypt_util.c (__init_des_r): Initialize current_salt + and current_saltbits. + +2002-11-02 Roland McGrath + + * stdio-common/reg-printf.c: Include . + +2002-11-02 H.J. Lu + + * sysdeps/unix/sysv/linux/mips/syscalls.list (s_execve): Set + caller to EXTRA instead of execve. + +2002-11-01 Roland McGrath + + * sysdeps/generic/errno-loc.c [! USE___THREAD]: Use this conditional + in place of [!(USE_TLS && HAVE___THREAD)]. + (__errno_location) [! USE___THREAD]: Define as strong, not weak. + +2002-10-31 Roger Sayle + + * sysdeps/i386/soft-fp/sfp-machine.h (_FP_NANFRAC_Q, _FP_NANSIGN_Q): + New macros. + * sysdeps/x86_64/soft-fp/sfp-machine.h: Likewise. + + * soft-fp/soft-fp.h: Allow sfp-machine.h to define FP_RND_NEAREST + without defining FP_ROUNDMODE. + +2002-10-29 Jakub Jelinek + + * sysdeps/gnu/siglist.c (PTR_SIZE_STR): Remove. + (__old_sys_siglist, __old_sys_sigabbrev): Use strong_alias and + declare_symbol. + * sysdeps/mach/hurd/siglist.h (OLD_SIGLIST_SIZE_STR): Remove. + (OLD_SIGLIST_SIZE): Define. + * sysdeps/unix/sysv/linux/siglist.h (OLD_SIGLIST_SIZE_STR): Remove. + (OLD_SIGLIST_SIZE): Define. + * sysdeps/unix/sysv/linux/arm/siglist.c: Remove. + +2002-11-01 Jakub Jelinek + + * sysdeps/ia64/strncpy.S: Fix recovery code. + +2002-10-30 Jakub Jelinek + + * include/libc-symbols.h (__libc_freeres_fn_section, libc_freeres_fn): + New macros. + * elf/dl-close.c (free_mem): Use libc_freeres_fn macro, remove + text_set_element. + * elf/dl-libc.c (free_mem): Likewise. + * iconv/gconv_conf.c (free_mem): Likewise. + * iconv/gconv_db.c (free_mem): Likewise. + * iconv/gconv_dl.c (free_mem): Likewise. + * iconv/gconv_cache.c (free_mem): Likewise. + * intl/finddomain.c (free_mem): Likewise. + * intl/dcigettext.c (free_mem): Likewise. + * locale/setlocale.c (free_mem): Likewise. + * misc/fstab.c (fstab_free): Likewise. + * nss/nsswitch.c (free_mem): Likewise. + * posix/regcomp.c (free_mem): Likewise. + * resolv/gai_misc.c (free_res): Likewise. + * stdlib/fmtmsg.c (free_mem): Likewise. + * sunrpc/clnt_perr.c (free_mem): Likewise. + * sysdeps/generic/setenv.c (free_mem): Likewise. + * sysdeps/unix/sysv/linux/shm_open.c (freeit): Likewise. + * sysdeps/pthread/aio_misc.c (free_res): Likewise. + * time/tzset.c (free_mem): Likewise. + * malloc/mtrace.c (release_libc_mem): Add __libc_freeres_fn_section. + * locale/loadarchive.c (_nl_archive_subfreeres): Likewise. + * malloc/set-freeres.c (__libc_freeres): Likewise. + + * login/getutent.c: Include stdlib.h instead of stddef.h. + (buffer): Change into pointer to utmp, add libc_freeres_ptr. + (__getutent): Allocate buffer the first time it is run. + * login/getutid.c: Include stdlib.h instead of stddef.h. + (buffer): Change into pointer to utmp, add libc_freeres_ptr. + (__getutid): Allocate buffer the first time it is run. + * login/getutline.c: Include stdlib.h instead of stddef.h. + (buffer): Change into pointer to utmp, add libc_freeres_ptr. + (__getutline): Allocate buffer the first time it is run. + * malloc/mtrace.c (malloc_trace_buffer): Change into char *. + (mtrace): Allocate malloc_trace_buffer. + * resolv/nsap_addr.c (inet_nsap_ntoa): Decrease size of tmpbuf. + * resolv/ns_print.c (ns_sprintrrf): Decrease size of t. + * string/strerror.c: Include libintl.h and errno.h. + (buf): New variable. + (strerror): Only allocate buffer if actually needed (unknown error). + * time/tzfile.c (transitions): Add libc_freeres_ptr. + (freeres): Remove. + +2002-10-25 Jakub Jelinek + + * include/libc-symbols.h (libc_freeres_ptr): New macro. + * malloc/set-freeres.c (__libc_freeres_ptrs): Define using + symbol_set_define. + (__libc_freeres): Free all pointers in that section. + * Makerules (build-shlib): Add $(LDSEDCMD-$(@F:lib%.so=%).so) to sed + commands when creating .lds script. + (LDSEDCMD-c.so): New variable. + * inet/rcmd.c (ahostbuf): Change into char *. Add libc_freeres_ptr. + (rcmd_af): Use strdup to allocate ahostbuf. + * inet/rexec.c (ahostbuf): Change into char *. Add libc_freeres_ptr. + (rexec_af): Use strdup to allocate ahostbuf. + * stdio-common/reg-printf.c (printf_funcs): Remove. + (__printf_arginfo_table): Change into printf_arginfo_function **. + Add libc_freeres_ptr. + (__register_printf_function): Allocate __printf_arginfo_table + and __printf_function_table the first time it is called. + * stdio-common/printf-parse.h (__printf_arginfo_table): Change into + printf_arginfo_function **. + (parse_one_spec): Add __builtin_expect. + * grp/fgetgrent.c (buffer): Add libc_freeres_ptr. + (free_mem): Remove. + * inet/getnetgrent.c (buffer): Add libc_freeres_ptr. + (free_mem): Remove. + * intl/localealias.c (libc_freeres_ptr): Define if !_LIBC. + (string_space, map): Add libc_freeres_ptr. + (free_mem): Remove. + * misc/efgcvt.c (FCVT_BUFPTR): Add libc_freeres_ptr. + (free_mem): Remove. + * misc/mntent.c (getmntent_buffer): Add libc_freeres_ptr. + (free_mem): Remove. + * crypt/md5-crypt.c (libc_freeres_ptr): Define if !_LIBC. + (buffer): Add libc_freeres_ptr. + (free_mem): Remove for _LIBC. + * nss/getXXbyYY.c (buffer): Add libc_freeres_ptr. + (free_mem): Remove. + * nss/getXXent.c (buffer): Add libc_freeres_ptr. + (free_mem): Remove. + * pwd/fgetpwent.c (buffer): Add libc_freeres_ptr. + (free_mem): Remove. + * resolv/res_hconf.c (ifaddrs): Add libc_freeres_ptr. + (free_mem): Remove. + * shadow/fgetspent.c (buffer): Add libc_freeres_ptr. + (free_mem): Remove. + * sysdeps/posix/ttyname.c (getttyname_name): Add libc_freeres_ptr. + (free_mem): Remove. + * sysdeps/unix/sysv/linux/getsysstats.c (mount_proc): Add + libc_freeres_ptr. + (free_mem): Remove. + * sysdeps/unix/sysv/linux/ttyname.c (getttyname_name, ttyname_buf): Add + libc_freeres_ptr. + (free_mem): Remove. + +2002-10-30 Jakub Jelinek + + * malloc/obstack.c [_LIBC] (obstack_free): Change into strong_alias + instead of duplicating the whole function in libc. + +2002-10-31 Roland McGrath + + * sysdeps/i386/bits/byteswap.h [__GNUC__ < 2] (__bswap_32): + Renamed from __bswap_16 (typo fix). Reported by . + +2002-10-30 Jakub Jelinek + + * sysdeps/unix/sysv/linux/Makefile (syscall-%.h): Add -D for each + 32bit-predefine when creating .new32 list and -U for each + 32bit-predefine when creating .new64 list. + * sysdeps/unix/sysv/linux/x86_64/Makefile (32bit-predefine): New. + +2002-10-29 Andreas Schwab + + * sysdeps/generic/allocrtsig.c: Include , not + "testrtsig.h". Reported by Daniel Jacobowitz . + +2002-10-25 Roland McGrath + + * sysdeps/unix/sysv/linux/configure.in: Fix typo in last change. + * sysdeps/unix/sysv/linux/configure: Regenerated. + + * sysdeps/generic/ldsodefs.h: Remove [! SHARED] conditional from + _dl_starting_up decl. + +2002-10-20 H.J. Lu + + * sysdeps/unix/sysv/linux/configure.in: Don't check + /lib/modules/`uname -r`/build/include for kernel headers if + cross compiling. + * sysdeps/unix/sysv/linux/configure: Regenerated. + +2002-10-25 Roland McGrath + + * math/math.h (M_LOG2El): Correct the value. + From Stephen L Moshier . + + * sysdeps/unix/sysv/linux/init-first.c (init): Remove [! SHARED] + conditional from __libc_multiple_libcs access. Remove kludge for weak + symbol access with old compilers we no longer support. + * sysdeps/unix/sysv/aix/init-first.c (init): Likewise. + * sysdeps/generic/libc-start.c (__libc_start_main): Likewise. + +2002-10-25 Roland McGrath + + * sysdeps/posix/sigvec.c [SA_RESETHAND]: Disable wrapper hacks and + implement SV_RESETHAND by translating it to SA_RESETHAND. + +2002-10-23 Alexandre Oliva + + * elf/dl-reloc.c (_dl_reloc_bad_use): Print the full 32-bit relocation + type on ELF64 platforms. + +2002-10-24 Ulrich Drepper + + * elf/elf.h (R_X86_64_GOTTPOFF): Renamed from r_x86_64_GOTTPOFF. + + * elf/elf.h: Define ELF_NOTE_OS_FREEBSD and NT_TASKSTRUCT. + +2002-10-24 Jakub Jelinek + + * elf/dl-misc.c: Include . + (_dl_debug_vdprintf): Only take dl_load_lock if not _dl_starting_up. + + * sysdeps/unix/sysv/linux/s390/s390-32/sysdep.h (INTERNAL_SYSCALL, + INTERNAL_SYSCALL_ERROR_P, INTERNAL_SYSCALL_ERRNO): New macros. + (INLINE_SYSCALL): Use that. + * sysdeps/unix/sysv/linux/s390/s390-64/sysdep.h (INTERNAL_SYSCALL, + INTERNAL_SYSCALL_ERROR_P, INTERNAL_SYSCALL_ERRNO): New macros. + (INLINE_SYSCALL): Use that. + * sysdeps/unix/sysv/linux/x86_64/sysdep.h (INTERNAL_SYSCALL, + INTERNAL_SYSCALL_ERROR_P, INTERNAL_SYSCALL_ERRNO): New macros. + (INLINE_SYSCALL): Use that. + * sysdeps/unix/sysv/linux/sparc/sparc32/sysdep.h: Include + dl-sysdep.h. + (SYSCALL_ERROR_HANDLER): Define RTLD_PRIVATE_ERRNO variant. + (__INTERNAL_SYSCALL_STRING): Define. + * sysdeps/unix/sysv/linux/sparc/sparc64/sysdep.h: Include + dl-sysdep.h. + (SYSCALL_ERROR_HANDLER): Define RTLD_PRIVATE_ERRNO variant. + (__INTERNAL_SYSCALL_STRING): Define. + * sysdeps/unix/sysv/linux/sparc/sysdep.h (INLINE_SYSCALL): Pass + __SYSCALL_STRING to inline_syscall*. + (INTERNAL_SYSCALL, INTERNAL_SYSCALL_ERROR_P, INTERNAL_SYSCALL_ERRNO): + New macros. + (inline_syscall0, inline_syscall1, inline_syscall2, inline_syscall3, + inline_syscall4, inline_syscall5, inline_syscall6): Add string + argument. + +2002-10-24 Roland McGrath + + * sysdeps/generic/ldsodefs.h (_dl_starting_up): Declare it here. + * sysdeps/unix/sysv/linux/init-first.c: Not here. + * sysdeps/powerpc/elf/libc-start.c: Or here. + * sysdeps/unix/sysv/aix/libc-start.c: Or here. + * sysdeps/unix/sysv/aix/start-libc.c: Or here. + * sysdeps/unix/sysv/aix/init-first.c: Or here. + * sysdeps/generic/libc-start.c: Or here. + * sysdeps/unix/sysv/linux/init-first.c (init): Protect _dl_starting_up + access with [! SHARED]. + * sysdeps/unix/sysv/aix/init-first.c (init): Likewise. + + * libio/bug-wfflush.c: New file. + * libio/Makefile (tests): Add bug-wfflush. + +2002-10-23 Roland McGrath + + * stdio-common/tst-fphex.c: New file. + * stdio-common/Makefile (tests): Add tst-fphex. + * sysdeps/generic/printf_fphex.c (__printf_fphex): Fix initialization + of WNUMEND. Fix counting of decimal point in WIDTH. Print '0' pad + chars always before the value digits. + Reported by James Antill . + +2002-10-24 Jakub Jelinek + + * posix/regcomp.c (re_comp): Call __regfree on re_comp_buf. + (free_mem): New function. + * posix/Makefile (tests): Add bug-regex14. Add bug-regex14-mem + if not cross compiling. + (generated): Add bug-regex14-mem and bug-regex14.mtrace. + (bug-regex14-ENV): Set. + (bug-regex14-mem): New target. + * posix/bug-regex14.c: New file. + +2002-10-23 Roland McGrath + + * elf/Makefile ($(objpfx)librtld.map): Use temporary file for output + target, so we don't touch it when the link fails. + + * libio/ftello.c (ftello): Use _IO_off64_t for type of POS. + Check for the result overflowing off_t and fail with EOVERFLOW. + * libio/ioftell.c (_IO_ftell): Likewise. + * libio/iofgetpos.c (_IO_new_fgetpos): Likewise. + + * login/logwtmp.c (logwtmp): If sizeof ut_tv != sizeof struct timeval, + use a temporary timeval on the stack for gettimeofday and copy it. + * login/logout.c (logout): Likewise. + Reported by Steven Munroe . + + * sysdeps/unix/sysv/linux/bits/statfs.h (struct statfs): + Use __SWORD_TYPE instead of int for member types. + (struct statfs64): Likewise. + * sysdeps/unix/sysv/linux/alpha/bits/statfs.h: New file. + * sysdeps/unix/sysv/linux/s390/bits/statfs.h: New file. + * sysdeps/unix/sysv/linux/ia64/bits/statfs.h: File removed. + * sysdeps/unix/sysv/linux/sparc/bits/statfs.h: File removed. + * sysdeps/unix/sysv/linux/x86_64/bits/statfs.h: File removed. + + * sysdeps/unix/sysv/linux/sparc/bits/statvfs.h: Moved to ... + * sysdeps/unix/sysv/linux/bits/statvfs.h: ... here. + (ST_NODIRATIME): Restore fixed value of 2048. + * sysdeps/unix/sysv/linux/alpha/bits/statvfs.h: File removed. + * sysdeps/unix/sysv/linux/ia64/bits/statvfs.h: File removed. + + Rearranged definitions to reduce duplication. + * sysdeps/generic/bits/types.h: Rewritten, using macros from + and new header . + * posix/Makefile (headers): Add bits/typesizes.h here. + * sysdeps/generic/bits/typesizes.h: New file. + * sysdeps/unix/sysv/linux/alpha/bits/typesizes.h: New file. + * sysdeps/unix/sysv/linux/sparc/bits/typesizes.h: New file. + * sysdeps/mach/hurd/bits/typesizes.h: New file. + * sysdeps/unix/sysv/linux/alpha/bits/types.h: File removed. + * sysdeps/unix/sysv/linux/bits/types.h: File removed. + * sysdeps/unix/sysv/linux/ia64/bits/types.h: File removed. + * sysdeps/unix/sysv/linux/mips/bits/types.h: File removed. + * sysdeps/unix/sysv/linux/s390/bits/types.h: File removed. + * sysdeps/unix/sysv/linux/sparc/bits/types.h: File removed. + * sysdeps/unix/sysv/linux/x86_64/bits/types.h: File removed. + * posix/sys/types.h [__USE_POSIX199506 || __USE_UNIX98]: Include + here, not in . + * signal/signal.h: Likewise. + + * streams/stropts.h: Include . + * streams/Makefile (headers): Add bits/xtitypes.h here. + * sysdeps/generic/bits/xtitypes.h: New file. + * sysdeps/s390/bits/xtitypes.h: New file. + * sysdeps/ia64/bits/xtitypes.h: New file. + * sysdeps/x86_64/bits/xtitypes.h: New file. + + * sysvipc/Makefile (headers): Add bits/ipctypes.h here. + * sysdeps/generic/bits/ipctypes.h: New file. + * sysdeps/mips/bits/ipctypes.h: New file. + * sysdeps/gnu/bits/shm.h: Include . + * sysdeps/gnu/bits/msq.h: Likewise. + * sysvipc/sys/ipc.h: Likewise. + +2002-10-22 Ulrich Drepper + + * elf/dl-load.c (struct filebuf): For buf element to have the + alignment of ElfXX_Ehdr since this is what will be stored in it. + +2002-10-22 Jakub Jelinek + + * locale/programs/locarchive.c (add_alias): Change locrec_offset arg + into pointer to locrec_offset. + (add_locale_to_archive): Adjust callers. Free normalized_name right + before returning, not immediately after add_locale, pass it to + add_alias if not NULL instead of name. Rename second normalized_name + occurence to nnormalized_codeset_name. + + * locale/programs/locarchive.c (enlarge_archive): Make sure + string_size is always a multiple of 4. + Reported by Andreas Schwab . + +2002-10-21 Andreas Schwab + + * sysdeps/unix/sysv/linux/ia64/syscalls.list (s_execve): Set + caller to EXTRA instead of execve, since the latter has a + higher-priority implementation in linuxthreads. + +2002-10-21 Roland McGrath + + * sysdeps/generic/libc-tls.c (__libc_setup_tls): Initialize the static + slotinfo list's len member to the proper size, not just 1. + Initialize static_map.l_tls_initimage. + + * elf/dl-open.c (dl_open_worker): Fix loop searching for + dtv_slotinfo_list element containing new modules' l_tls_modid. + + * elf/tst-tls9.c, elf/tst-tls9-static.c: New files. + * elf/tst-tlsmod5.c, elf/tst-tlsmod6.c: New files. + * elf/Makefile (tests): Add tst-tls9. + (tests-static): Add tst-tls9-static. + (tst-tls9-static-ENV): New variable. + ($(objpfx)tst-tls9-static, $(objpfx)tst-tls9-static.out): New targets. + + * elf/dl-close.c (remove_slotinfo): Remove an assert; the number of + modids used by partially loaded modules being closed can't be known. + +2002-10-21 Isamu Hasegawa + + * posix/Makefile: Add a test case for the bug reported by Aharon + Robbins . + * posix/bug-regex13.c: New file. + * posix/regcomp.c (peek_token_bracket): Skip the byte already read. + +2002-10-21 Ulrich Drepper + + * csu/gmon-start.c: Pretty printing. + +2002-10-19 Art Haas + + * configure.in: Replace AC_CONFIG_HEADER with AC_CONFIG_HEADERS, + add AC_HELP_STRING to all AC_ARG_WITH and AC_ARG_ENABLE macros, + add autoconf quotes to the AC_CONFIG_AUX_DIR macro. + * configure: Regenerated. + +2002-10-19 Roland McGrath + + * configure.in: Call AC_CONFIG_SUBDIRS with empty argument + and then set $subdirs directly, because the new Autoconf breaks + compatibility in every way imaginable and insists on whining + about usage that worked since the dawn of time. + * configure: Regenerated. + + * configure: Regenerated (using Autoconf 2.54). + * sysdeps/alpha/elf/configure: Likewise. + * sysdeps/generic/configure: Likewise. + * sysdeps/i386/elf/configure: Likewise. + * sysdeps/ia64/elf/configure: Likewise. + * sysdeps/mach/hurd/configure: Likewise. + * sysdeps/mach/configure: Likewise. + * sysdeps/unix/configure: Likewise. + * sysdeps/unix/common/configure: Likewise. + * sysdeps/unix/sysv/aix/configure: Likewise. + * sysdeps/unix/sysv/linux/configure: Likewise. + * sysdeps/unix/sysv/linux/mips/configure: Likewise. + * sysdeps/x86_64/elf/configure: Likewise. + + * config.make.in: Nix completely-soft nonsense. + * configure.in: Likewise. Under --without-fp, use nofpu subdirectory + of machine directories instead of fpu subdirectory. + * sysdeps/powerpc/soft-fp/Makefile: Remove cruft added in last change. + * sysdeps/powerpc/nofpu/Makefile: Put it in this new file instead. + * sysdeps/powerpc/soft-fp/sim-full.c: Moved to ... + * sysdeps/powerpc/nofpu/sim-full.c: ... here. + * sysdeps/powerpc/soft-fp/fraiseexcpt.c: Moved to ... + * sysdeps/powerpc/nofpu/fraiseexcpt.c: ... here. + * sysdeps/powerpc/soft-fp/fegetexcept.c: Moved to ... + * sysdeps/powerpc/nofpu/fegetexcept.c: ... here. + * sysdeps/powerpc/soft-fp/fclrexcpt.c: Moved to ... + * sysdeps/powerpc/nofpu/fclrexcpt.c: ... here. + * sysdeps/powerpc/soft-fp/ftestexcept.c: Moved to ... + * sysdeps/powerpc/nofpu/ftestexcept.c: ... here. + * sysdeps/powerpc/soft-fp/fgetexcptflg.c: Moved to ... + * sysdeps/powerpc/nofpu/fgetexcptflg.c: ... here. + * sysdeps/powerpc/soft-fp/fsetexcptflg.c: Moved to ... + * sysdeps/powerpc/nofpu/fsetexcptflg.c: ... here. + * sysdeps/powerpc/soft-fp/fedisblxcpt.c: Moved to ... + * sysdeps/powerpc/nofpu/fedisblxcpt.c: ... here. + * sysdeps/powerpc/soft-fp/feenablxcpt.c: Moved to ... + * sysdeps/powerpc/nofpu/feenablxcpt.c: ... here. + * sysdeps/powerpc/soft-fp/fegetenv.c: Moved to ... + * sysdeps/powerpc/nofpu/fegetenv.c: ... here. + * sysdeps/powerpc/soft-fp/fesetenv.c: Moved to ... + * sysdeps/powerpc/nofpu/fesetenv.c: ... here. + * sysdeps/powerpc/soft-fp/fegetround.c: Moved to ... + * sysdeps/powerpc/nofpu/fegetround.c: ... here. + * sysdeps/powerpc/soft-fp/fesetround.c: Moved to ... + * sysdeps/powerpc/nofpu/fesetround.c: ... here. + * sysdeps/powerpc/soft-fp/feupdateenv.c: Moved to ... + * sysdeps/powerpc/nofpu/feupdateenv.c: ... here. + * sysdeps/powerpc/soft-fp/feholdexcpt.c: Moved to ... + * sysdeps/powerpc/nofpu/feholdexcpt.c: ... here. + * sysdeps/powerpc/soft-fp/fenv_const.c: Moved to ... + * sysdeps/powerpc/nofpu/fenv_const.c: ... here. + * sysdeps/powerpc/soft-fp/libm-test-ulps: Moved to ... + * sysdeps/powerpc/nofpu/libm-test-ulps: ... here. + * sysdeps/powerpc/soft-fp/soft-supp.h: Moved to ... + * sysdeps/powerpc/nofpu/soft-supp.h: ... here. + * sysdeps/powerpc/soft-fp/Versions (libc: GLIBC_2.3.2): Moved to ... + * sysdeps/powerpc/nofpu/Versions: ... here, new file. + +2002-10-19 Bruno Haible + + * sysdeps/unix/bsd/bsd4.4/freebsd/sys/sysmacros.h: New file. + +2002-10-18 Roland McGrath + + * io/Makefile (routines): Add lchmod. + * io/sys/stat.h [__USE_BSD] (lchmod): Declare it. + * sysdeps/generic/lchmod.c: New file. + * sysdeps/mach/hurd/lchmod.c: New file. + * io/Versions (libc: GLIBC_2.3.2): New set, add lchmod. + +2002-10-18 Art Haas + + * configure.in: Remove remaining AC_FD_CC macros, and replace + AC_FD_MSG with AS_MESSAGE_FD. + +2002-10-18 Roland McGrath + + * sysdeps/powerpc/powerpc32/dl-machine.c (__process_machine_rela): Fix + typos: VALUE -> FINALADDR. + + * sysdeps/unix/alpha/sysdep.h (INLINE_SYSCALL, INLINE_SYSCALL1) + (inline_syscall_clobbers, inline_syscall0, inline_syscall1) + (inline_syscall2, inline_syscall3, inline_syscall4, inline_syscall5) + (inline_syscall6): Move these macros ... + * sysdeps/unix/sysv/linux/alpha/sysdep.h: ... to here. + + * configure.in (libc_link_dests, libc_link_sources): Remove these + variables and the AC_LINK_FILES call. + + * sysdeps/powerpc/soft-fp/Versions (libc: GLIBC_2.3.2): Fix last + change to put new symbols here instead of in GLIBC_2.2. + * sysdeps/powerpc/Subdirs: Move this file ... + * sysdeps/powerpc/soft-fp/Subdirs: ... here. + +2002-10-07 Roland McGrath + + * sysdeps/generic/bits/time.h: Replaced with contents of the + sysdeps/unix/sysv/linux/i386/bits/time.h file. All the following + files were identical except for the absence of CLOCK_THREAD_CPUTIME_ID + and CLOCK_PROCESS_CPUTIME_ID in .../linux/bits/time.h; adding these + macros is ok even for architectures that don't now implement them. + * sysdeps/mach/hurd/bits/time.h: File removed. + * sysdeps/unix/sysv/linux/bits/time.h: File removed. + * sysdeps/unix/sysv/linux/i386/bits/time.h: File removed. + * sysdeps/unix/sysv/linux/ia64/bits/time.h: File removed. + * sysdeps/unix/sysv/linux/sparc/bits/time.h: File removed. + * sysdeps/unix/sysv/linux/x86_64/bits/time.h: File removed. + +2002-10-18 Jeff Bailey + + * configure.in: Replace obsolete AC_OUTPUT syntax with + AC_CONFIG_FILES, AC_CONFIG_COMMANDS, and new-type AC_OUTPUT trio. + + * aclocal.m4 (GLIBC_PROVIDES): Add AC_PROVIDEs for + _AS_PATH_SEPARATOR_PREPARE and _AS_TEST_PREPARE. + + * configure.in: Replace AC_FD_CC with AS_MESSAGE_LOG_FD. + * sysdeps/alpha/elf/configure.in: Likewise. + * sysdeps/i386/elf/configure.in: Likewise. + * sysdeps/mach/hurd/configure.in: Likewise. + * sysdeps/x86_64/elf/configure.in: Likewise. + + * configure.in: Use AC_CONFIG_SRCDIR and new AC_INIT syntax. + + * sysdeps/alpha/elf/configure.in: Remove unneeded sinclude statement. + * sysdeps/generic/configure.in: Likewise. + * sysdeps/i386/elf/configure.in: Likewise. + * sysdeps/ia64/elf/configure.in: Likewise. + * sysdeps/mach/configure.in: Likewise. + * sysdeps/mach/hurd/configure.in: Likewise. + * sysdeps/unix/configure.in: Likewise. + * sysdeps/unix/common/configure.in: Likewise. + * sysdeps/unix/sysv/aix/configure.in: Likewise. + * sysdeps/unix/sysv/linux/configure.in: Likewise. + * sysdeps/unix/sysv/linux/mips/configure.in: Likewise. + * sysdeps/x86_64/elf/configure.in: Likewise. + + * aclocal.m4: Use just the bits from AS_INIT that are needed for the + GLIBC_PROVIDES. Use plain comment instead of HEADER-COMMENT so + that it's obvious when extra autoconf machinery is being dragged in. + +2002-10-18 Roland McGrath + + * configure.in: Remove bogus echo included in + 2002-10-08 Aldy Hernandez change. + * configure: Regenerated. + +2002-10-18 Jakub Jelinek + + * sysdeps/unix/sysv/linux/pathconf.h (statfs_link_max): Add inline. + (statfs_filesize_max): New function. + * sysdeps/unix/sysv/linux/linux_fsinfo.h (JFFS_SUPER_MAGIC, + JFFS2_SUPER_MAGIC, JFS_SUPER_MAGIC, NTFS_SUPER_MAGIC, + ROMFS_SUPER_MAGIC, UDF_SUPER_MAGIC): Define. + * sysdeps/unix/sysv/linux/fpathconf.c (__fpathconf): Use + statfs_filesize_max. + * sysdeps/unix/sysv/linux/pathconf.c (__pathconf): Likewise. + * sysdeps/unix/sysv/linux/alpha/fpathconf.c: Removed. + * sysdeps/unix/sysv/linux/alpha/pathconf.c: Removed. + +2002-10-17 Roland McGrath + + * configure.in (MIG): Just AC_SUBST it here. + * configure: Regenerated. + * sysdeps/mach/configure.in (MIG): Do the AC_CHECK_TOOL here. + Adding final - argument to all AC_CHECK_HEADER uses for .defs files. + * sysdeps/mach/configure: Regenerated. + + * aclocal.m4 (GLIBC_PROVIDES): Add AC_PROVIDE([_AS_TR_SH_PREPARE]) + and AC_PROVIDE([_AS_CR_PREPARE]). + + * aclocal.m4 (GLIBC_PROVIDES): Add AC_PROVIDE([_AS_ECHO_N_PREPARE]). + Remove AC_LANG(C) call, instead just define([_AC_LANG], [C]). + + * elf/dl-support.c: Move _dl_tls_* variables to ... + * sysdeps/generic/libc-tls.c: ... here. + + * elf/dl-close.c (remove_slotinfo): Take new argument. If false, + allow IDX to be one past the current last slotinfo entry. + (_dl_close): Pass IMAP->l_init_called for that parameter. + +2002-10-07 Andreas Schwab + + * aclocal.m4: Fix for autoconf 2.53. + * configure.in: Likewise. Require autoconf 2.53. + +2002-10-08 Richard Henderson + + * soft-fp/op-4.h: Handle carry correctly in + __FP_FRAC_ADD_3, __FP_FRAC_ADD_4, __FP_FRAC_SUB_3, + __FP_FRAC_SUB_4, __FP_FRAC_DEC_3, __FP_FRAC_DEC_4. + * soft-fp/op-common.h: New macros _FP_DIV_MEAT_N_loop. + +2002-10-08 Aldy Hernandez + + * configure.in: Compute completely-soft. + * config.make.in: Make completely-soft available to sub-makes. + * sysdeps/powerpc/soft-fp/Makefile: Add gcc-single-routines and + gcc-double-routines. Add sim-full.c. Add fenv_const and + fe_nomask to libm-support. + * sysdeps/powerpc/soft-fp/sim-full.c: New file. + * sysdeps/powerpc/soft-fp/fraiseexcpt.c: New file. + * sysdeps/powerpc/soft-fp/fegetexcept.c: New file. + * sysdeps/powerpc/soft-fp/fclrexcpt.c: New file. + * sysdeps/powerpc/soft-fp/ftestexcept.c: New file. + * sysdeps/powerpc/soft-fp/fgetexcptflg.c: New file. + * sysdeps/powerpc/soft-fp/fsetexcptflg.c: New file. + * sysdeps/powerpc/soft-fp/fedisblxcpt.c: New file. + * sysdeps/powerpc/soft-fp/feenablxcpt.c: New file. + * sysdeps/powerpc/soft-fp/fegetenv.c: New file. + * sysdeps/powerpc/soft-fp/fesetenv.c: New file. + * sysdeps/powerpc/soft-fp/fegetround.c: New file. + * sysdeps/powerpc/soft-fp/fesetround.c: New file. + * sysdeps/powerpc/soft-fp/feupdateenv.c: New file. + * sysdeps/powerpc/soft-fp/feholdexcpt.c: New file. + * sysdeps/powerpc/soft-fp/fenv_const.c: New file. + * sysdeps/powerpc/soft-fp/libm-test-ulps: New file. + * sysdeps/powerpc/soft-fp/soft-supp.h: New file. + * sysdeps/powerpc/soft-fp/Versions: Add libgcc soft-float + symbols. Add __sim_disabled_exceptions, __sim_exceptions, + __sim_round_mode. + * sysdeps/powerpc/soft-float/Dist: Add sim-full.c, fenv_const.c. + * sysdeps/powerpc/soft-float/sfp-machine.h: Define + FP_HANDLE_EXCEPTIONS. + Define FP_ROUNDMODE. + Redefine FP_* macros to correspond to the FE_* bit positions. + Define FP_DIV_MEAT_S to _FP_DIV_MEAT_1_loop. + Define externs for __sim_exceptions, __sim_disabled_exceptions, + __sim_round_mode, __simulate_exceptions. + * sysdeps/powerpc/fpu/bits/fenv.h: Move file from here... + * sysdeps/powerpc/bits/fenv.h: ...to here. + +2002-10-06 Jakub Jelinek + + * sysdeps/powerpc/powerpc32/dl-machine.c (__process_machine_rela): + Store R_PPC_UADDR32 and R_PPC_UADDR16 one byte at a time. + Use __builtin_expect for R_PPC_ADDR24 overflow check. Fix + R_PPC_ADDR16, R_PPC_UADDR16 and R_PPC_ADDR14* overflow check, use + __builtin_expect. + +2002-10-15 Jakub Jelinek + + * include/resolv.h (__libc_res_nquery, __libc_res_nsearch, + __libc_res_nsend): New prototypes. + * resolv/res_query.c (QUERYSIZE): Define. + (__libc_res_nquery): Renamed from res_nquery. Added answerp + argument. Allocate only QUERYSIZE bytes first, if res_nmkquery + fails use MAXPACKET buffer. Call __libc_res_nsend instead of + res_nsend, pass answerp. + (res_nquery): Changed into wrapper around __libc_res_nquery. + (__libc_res_nsearch): Renamed from res_nsearch. Added answerp + argument. Call __libc_res_nquerydomain and __libc_res_nquery + instead of the non-__libc_ variants, pass them answerp. + (res_nsearch): Changed into wrapper around __libc_res_nsearch. + (__libc_res_nquerydomain): Renamed from res_nquerydomain. + Added answerp argument. Call __libc_res_nquery instead of + res_nquery, pass answerp. + (res_nquerydomain): Changed into wrapper around + __libc_res_nquerydomain. + * resolv/res_send.c: Include sys/ioctl.h. + (MAXPACKET): Define. + (send_vc): Change arguments. Reallocate answer buffer if it is + too small. + (send_dg): Likewise. + (__libc_res_nsend): Renamed from res_nsend. Added ansp argument. + Reallocate answer buffer if it is too small and hooks are in use. + Adjust calls to send_vc and send_dg. + (res_nsend): Changed into wrapper around __libc_res_nsend. + * resolv/nss_dns/dns-host.c (_nss_dns_gethostbyname2_r): Allocate + just 1K answer buffer on the stack, use __libc_res_nsearch instead + of res_nsearch. + (_nss_dns_gethostbyaddr_r): Similarly with __libc_res_nquery. + * resolv/nss_dns/dns-network.c (_nss_dns_getnetbyaddr_r): Likewise. + (_nss_dns_getnetbyname_r): Similarly with __libc_res_nsearch. + * resolv/gethnamaddr.c (gethostbyname2): Likewise. + (gethostbyaddr): Similarly with __libc_res_nquery. + * resolv/Versions (libresolv): Export __libc_res_nquery and + __libc_res_nsearch at GLIBC_PRIVATE. + +2002-10-17 Roland McGrath + + * configure.in: Grok --without-__thread and disable HAVE___THREAD. + * configure: Regenerated. + + * sysdeps/x86_64/dl-machine.h (elf_machine_rela): Do CHECK_STATIC_TLS + before performing the reloc, not after. + * sysdeps/i386/dl-machine.h (elf_machine_rel): Likewise. + +2002-10-17 Ulrich Drepper + + * locale/programs/locale.c (write_locales): Use 'm' flag in fopen call. + * locale/programs/linereader.c (lr_open): Likewise. + * locale/programs/charmap-dir.c (charmap_open): Likewise. + * locale/programs/locarchive.c (add_locale_to_archive): Likewise. + +2002-10-17 Isamu Hasegawa + + * posix/bug-regex11.c: Add a test case for the bug reported by + Paolo Bonzini . + * posix/regexec.c (sift_states_bkref): Use correct destination of + the back reference. + +2002-10-17 Roland McGrath + + * elf/dl-load.c (_dl_map_object_from_fd): Don't check DF_STATIC_TLS. + * elf/dl-reloc.c (_dl_relocate_object: CHECK_STATIC_TLS): New macro + to signal error if an IE-model TLS reloc resolved to a dlopen'd module. + * sysdeps/i386/dl-machine.h (elf_machine_rel, elf_machine_rela): + Call it after performing TPOFF relocs. + * sysdeps/x86_64/dl-machine.h (elf_machine_rela): Likewise. + * sysdeps/sh/dl-machine.h (elf_machine_rela): Likewise. + * elf/dl-conflict.c (CHECK_STATIC_TLS): New macro (no-op). + + * elf/dl-close.c (remove_slotinfo): Change asserts so as not to crash + when closing a partially-initialized object. + + * elf/dl-load.c (_dl_map_object_from_fd) [! USE_TLS]: Call lose + instead of _dl_fatal_printf when we see PT_TLS. + + * Makeconfig (CPPFLAGS): Fix last change to use $(libof-$( + + * cppflags-iterator.mk (CPPFLAGS-$(cpp-src)): Variable removed. + instead of += to append, to be sure $(lib) gets expanded at defn time. + (libof-$(cpp-src)): New variable, define this instead. + * extra-lib.mk (cpp-srcs-left): Reduce duplication in include setup. + (lib): Don't use override. + (CPPFLAGS-$(lib)): New variable, put -D's here. + * Makeconfig (CPPFLAGS): Use basename fn for CPPFLAGS-basename. + Also add $(CPPFLAGS-LIB) before the file-specific flags, for each + LIB found by $(libof-*) for basename, target, or source. + * Makerules (CPPFLAGS-nonlib): New variable. + * nscd/Makefile (lib): Set to nonlib when using cppflags-iterator.mk. + * locale/Makefile (lib): Likewise. + * sunrpc/Makefile (lib): Likewise. + + * sysdeps/unix/sysv/linux/fpathconf.c (LINUX_LINK_MAX): Move macro ... + * sysdeps/unix/sysv/linux/linux_fsinfo.h (LINUX_LINK_MAX): ... here. + * sysdeps/unix/sysv/linux/pathconf.h: New file. + (statfs_link_max): New function, guts from fpathconf.c. + * sysdeps/unix/sysv/linux/fpathconf.c: Rewritten using that. + * sysdeps/unix/sysv/linux/pathconf.c (__pathconf): Likewise. + * sysdeps/unix/sysv/linux/alpha/pathconf.c (__pathconf): Rewritten + to use the linux/pathconf.c code by #include rather than duplication. + * sysdeps/unix/sysv/linux/alpha/fpathconf.c (__pathconf): Likewise. + +2002-10-16 Jakub Jelinek + + * sysdeps/unix/sysv/linux/x86_64/sysdep.h (SYSCALL_ERROR_HANDLER): + Use __libc_errno only for libc itself. + +2002-10-16 Andreas Jaeger + + * sysdeps/x86_64/_mcount.S: Fix off-by-1 error in argument access. + +2002-10-16 Ulrich Drepper + + * sysdeps/unix/sysv/linux/i386/sysdep.h (SYSCALL_ERROR_HANDLER): + Use __libc_errno only for libc itself. + +2002-10-15 Roland McGrath + Jakub Jelinek + + * sysdeps/unix/sysv/linux/Makefile + ($(objpfx)syscall-%.h $(objpfx)syscall-%.d): Take code from + sparc/Makefile to produce a bi-arch file as needed. + That's now parameterized by the variable $(64bit-predefine). + Use LC_ALL=C for `comm' commands in that rule. + No longer conditional on [$(no_syscall_list_h)]. + * sysdeps/unix/sysv/linux/sparc/Makefile: Remove replacement rules. + (64bit-predefine): New variable. + * sysdeps/unix/sysv/linux/x86_64/Makefile: Likewise. + * sysdeps/unix/sysv/linux/s390/Makefile: New file. + * sysdeps/unix/sysv/linux/powerpc/Makefile + (64bit-predefine): New variable. + +2002-10-15 Roland McGrath + + * sysdeps/unix/sysv/linux/Makefile + ($(objpfx)syscall-%.h $(objpfx)syscall-%.d) + + * login/utmp-private.h: Declare __libc_utmp_lock. + * sysdeps/unix/getlogin_r.c (getlogin_r): Take __libc_utmp_lock once + and call __libc_utmp_jump_table functions directly, instead of using + __setutent et al. + + * sysdeps/unix/sysv/linux/configure.in: Use case instead of if. + * sysdeps/unix/sysv/linux/configure: Regenerated. + + * sysdeps/gnu/bits/utmp.h: Include . + (struct lastlog) [__WORDSIZE == 64 && __WORDSIZE_COMPAT32]: + Use int32_t for ll_time. + (struct utmp) [__WORDSIZE == 64 && __WORDSIZE_COMPAT32]: + Use int32_t instead of long int for ut_session. + Use an anonymous struct with 32-bit fields for ut_tv. + * sysdeps/gnu/bits/utmpx.h: Include . + (struct utmpx) [__WORDSIZE == 64 && __WORDSIZE_COMPAT32]: Do the same + here as in utmp.h for `struct utmp'. + * sysdeps/unix/sysv/linux/powerpc/bits/utmp.h: File removed. + * sysdeps/unix/sysv/linux/powerpc/bits/utmpx.h: File removed. + * sysdeps/unix/sysv/linux/sparc/bits/utmp.h: File removed. + * sysdeps/unix/sysv/linux/sparc/bits/utmpx.h: File removed. + * sysdeps/unix/sysv/linux/x86_64/bits/utmp.h: File removed. + * sysdeps/unix/sysv/linux/x86_64/bits/utmpx.h: File removed. + + * sysdeps/unix/sysv/linux/bits/resource.h: Replaced with the contents + of the sysdeps/unix/sysv/linux/i386/bits/resource.h file. + All the following files were identical or equivalent to it. + * sysdeps/unix/sysv/linux/i386/bits/resource.h: File removed. + * sysdeps/unix/sysv/linux/arm/bits/resource.h: File removed. + * sysdeps/unix/sysv/linux/cris/bits/resource.h: File removed. + * sysdeps/unix/sysv/linux/hppa/bits/resource.h: File removed. + * sysdeps/unix/sysv/linux/ia64/bits/resource.h: File removed. + * sysdeps/unix/sysv/linux/m68k/bits/resource.h: File removed. + * sysdeps/unix/sysv/linux/powerpc/bits/resource.h: File removed. + * sysdeps/unix/sysv/linux/s390/bits/resource.h: File removed. + * sysdeps/unix/sysv/linux/sh/bits/resource.h: File removed. + * sysdeps/unix/sysv/linux/x86_64/bits/resource.h: File removed. + + * sysdeps/unix/sysv/linux/bits/socket.h (struct msghdr): Use size_t + instead of int for msg_iovlen, instead of socklen_t for msg_controllen. + Other than the previously incorrect sign of msg_iovlen, this is a + no-op on 32-bit platforms. On 64-bit platforms it makes this header + match their layouts as well, so the following are now identical to it. + * sysdeps/unix/sysv/linux/s390/bits/socket.h: File removed. + * sysdeps/unix/sysv/linux/sparc/bits/socket.h: File removed. + * sysdeps/unix/sysv/linux/x86_64/bits/socket.h: File removed. + * sysdeps/unix/sysv/linux/ia64/bits/socket.h: File removed. + * sysdeps/unix/sysv/linux/alpha/bits/socket.h: File removed. + +2002-10-15 Ulrich Drepper + + * sysdeps/unix/sysv/linux/kernel-features.h (__ASSUME_VFORK_SYSCALL): + Define for 2.4+ kernels. + + * sysdeps/unix/sysv/linux/i386/vfork.S: Optimize for kernels which + are known to have the vfork syscall. Don't confuse the CPUs + branch prediction unit by jumping to the return address. + + * sysdeps/unix/sysv/linux/alpha/fpathconf.c (__fpathconf): Add + support for reiserfs and xfs. + + * sysdeps/unix/sysv/linux/fpathconf.c (__fpathconf): Add case for + XFS link count. + * sysdeps/unix/sysv/linux/linux_fsinfo.h: Define XFS_SUPER_MAGIC + and XFS_LINK_MAX. + Patch by Eric Sandeen [PR libc/4706]. + +2002-10-16 Jakub Jelinek + + * include/libc-symbols.h (attribute_tls_model_ie): Define. + * include/errno.h (errno): Define to __libc_errno in libc.so. + Add attribute_tls_model_ie. + * include/netdb.h (h_errno): Define to __libc_h_errno in libc.so. + Add attribute_tls_model_ie. + * include/resolv.h (_res): Define to __libc_res in libc.so. Add + attribute_tls_model_ie. + * inet/herrno.c (__libc_h_errno): Add hidden alias to h_errno. + (h_errno): Define. + * resolv/res_libc.c (__libc_res): Add hidden alias to _res. + (_res): Define. + * sysdeps/generic/bits/libc-tsd.h (__libc_tsd_define): Add + attribute_tls_model_ie. + * sysdeps/generic/errno-loc.c (errno): Only undefine if not using + __thread. + * sysdeps/generic/errno.c (__libc_errno): Add hidden alias to errno. + * sysdeps/unix/sysv/linux/i386/sysdep.h (SYSCALL_ERROR_HANDLER): Use + __libc_errno in USE___THREAD case. + * sysdeps/unix/sysv/linux/x86_64/sysdep.h (SYSCALL_ERROR_HANDLER): + Likewise. + * configure.in (HAVE_TLS_MODEL_ATTRIBUTE): Check for + __attribute__((tls_model (""))). + * configure: Rebuilt. + * config.h.in (HAVE_TLS_MODEL_ATTRIBUTE): Add. + +2002-10-15 Ulrich Drepper + + * timezone/asia: Update from tzdata2002d. + * timezone/australasia: Likewise. + * timezone/iso3166.tab: Likewise. + * timezone/southamerica: Likewise. + * timezone/zone-tab: Likewise. + +2002-10-15 Roland McGrath + + * sysdeps/generic/dl-tls.c (_dl_deallocate_tls) [TLS_TCB_AT_TP]: + Adjust TCB pointer before calling free, so we get the whole block. + +2002-10-14 Roland McGrath + + * sysdeps/unix/sysv/linux/x86_64/sigaction.c + [HAVE_HIDDEN && !HAVE_BROKEN_VISIBILITY_ATTRIBUTE]: Declare restore_rt + extern using attribute_hidden instead of static, avoids warning. + +2002-10-09 Jakub Jelinek + + * sysdeps/unix/sysv/linux/configure.in: Use */lib64 for s390x too. + * sysdeps/unix/sysv/linux/configure: Rebuilt. + +2002-10-14 Ulrich Drepper + + * po/sv.po: Update from translation team. + +2002-10-12 H.J. Lu + + * sunrpc/thrsvc.c (PROCQUIT): New. + (struct rpc_arg): New. + (dispatch): Call exit (0) if request->rq_proc == PROCQUIT. + (test_one_call): Take struct rpc_arg * instead of CLIENT *c. + (thread_wrapper): Modified for struct rpc_arg * and call PROCQUIT. + (main): Modified for struct rpc_arg *. + +2002-10-14 Ulrich Drepper + + * dirent/scandir.c: Rearrange code a bit to reduce binary size. + +2002-10-14 Jakub Jelinek + + * sysdeps/unix/sysv/linux/x86_64/sysdep.h: Include tls.h. + (SYSCALL_ERROR_HANDLER): Use RTLD_PRIVATE_ERRNO sequence + in ld.so even if __thread is supported. + +2002-10-13 Jakub Jelinek + + * sysdeps/unix/sysv/linux/arm/profil-counter.h (profil_counter): + Add hack to prevent the compiler from clobbering the signal context. + * sysdeps/unix/sysv/linux/sh/profil-counter.h (profil_counter): + Likewise. + * sysdeps/unix/sysv/linux/x86_64/profil-counter.h (profil_counter): + Likewise. + +2002-10-14 Andreas Jaeger + + * sysdeps/mips/fpu/libm-test-ulps: Regenerated by + Guido Guenther . + +2002-10-14 Ulrich Drepper + + * po/sk.po: Update from translation team. + +2002-09-26 Roland McGrath + + * elf/dl-load.c (_dl_dst_count, _dl_dst_substitute): Handle $LIB + dynamic string tag. + * elf/Makefile ($(objpfx)trusted-dirs.st): Make the output define + DL_DST_LIB based on $(slibdir). + +2002-10-13 Roland McGrath + + * elf/rtld-Rules ($(objpfx)rtld-libc.a): Use $(verbose) in ar command. + + * sysdeps/mach/hurd/getresuid.c: New file. + * sysdeps/mach/hurd/getresgid.c: New file. + * sysdeps/mach/hurd/setresuid.c: New file. + * sysdeps/mach/hurd/setresgid.c: New file. + + * posix/unistd.h [__USE_GNU] (getresuid, getresgid, setresuid, + setresgid): Declare them. + * NEWS: Mention it. + * include/unistd.h + (__getresuid, __getresgid, __setresuid, __setresgid): Declare them, + add libc_hidden_proto. + * posix/Versions (libc: GLIBC_2.3.2): New set. Add + getresuid, getresgid, setresuid, setresgid here. + * Versions.def (libc): Define GLIBC_2.3.2 set. + * sysdeps/generic/getresuid.c (__getresuid): Fix argument types. + Add libc_hidden_def. + * sysdeps/generic/getresgid.c (__getresgid): Likewise. + * sysdeps/generic/setresgid.c: New file. + * sysdeps/generic/setresuid.c: New file. + * sysdeps/unix/sysv/linux/Makefile [$(subdir) = misc] + (sysdep_routines): Don't add getresuid and getresgid here. + * sysdeps/unix/sysv/linux/arm/Makefile [$(subdir) = misc] + (sysdep_routines): Don't add setresuid and setresgid here. + * sysdeps/unix/sysv/linux/cris/Makefile: Likewise. + * sysdeps/unix/sysv/linux/sh/Makefile: Likewise. + * sysdeps/unix/sysv/linux/s390/s390-32/Makefile: Likewise. + * sysdeps/unix/sysv/linux/s390/s390-64/Makefile: Likewise. + * sysdeps/unix/sysv/linux/i386/Makefile: Likewise. + * sysdeps/unix/sysv/linux/m68k/Makefile: Likewise. + * posix/Makefile (routines): Add them all here instead. + * sysdeps/unix/sysv/linux/i386/getresuid.c (getresuid): Renamed to + __getresuid. Add libc_hidden_def for that, and weak alias to old name. + * sysdeps/unix/sysv/linux/i386/getresgid.c (getresgid): Renamed to + __getresgid. Add libc_hidden_def for that, and weak alias to old name. + * sysdeps/unix/sysv/linux/i386/setresuid.c: Add libc_hidden_def. + [! __NR_setresuid]: Include generic file. + * sysdeps/unix/sysv/linux/i386/setresgid.c (setresgid): Renamed to + __setresgid. Add libc_hidden_def for that, and weak alias to old name. + [! __NR_setresuid]: Include generic file. + * sysdeps/unix/sysv/linux/syscalls.list (setresuid, setresgid): + Caller is - now, not EXTRA. + * sysdeps/unix/sysv/linux/sparc/sparc32/syscalls.list + (setresuid, setresgid, getresuid, getresgid): Likewise. + * sysdeps/unix/sysv/linux/syscalls.list (getresuid, getresgid): + Add these calls here. + * sysdeps/unix/sysv/linux/alpha/syscalls.list: Remove them here. + * sysdeps/unix/sysv/linux/hppa/syscalls.list: Likewise. + * sysdeps/unix/sysv/linux/sparc/sparc64/syscalls.list: Likewise. + * sysdeps/unix/sysv/linux/s390/s390-64/syscalls.list: Likewise. + * sysdeps/unix/sysv/linux/x86_64/syscalls.list: Likewise. + * sysdeps/unix/sysv/linux/powerpc/powerpc32/syscalls.list: Likewise. + * sysdeps/unix/sysv/linux/powerpc/powerpc64/syscalls.list: Likewise. + * sysdeps/unix/sysv/linux/mips/syscalls.list: Likewise. + * sysdeps/unix/sysv/linux/ia64/syscalls.list: Likewise. + + * sysdeps/unix/sysv/linux/Makefile [$(subdir) = misc] + (sysdep_routines): Add setfsuid and setfsgid here. + * sysdeps/unix/sysv/linux/arm/Makefile: Not here. + * sysdeps/unix/sysv/linux/sparc/sparc32/Makefile: Likewise. + * sysdeps/unix/sysv/linux/cris/Makefile: Likewise. + * sysdeps/unix/sysv/linux/sh/Makefile: Likewise. + * sysdeps/unix/sysv/linux/s390/s390-32/Makefile: Likewise. + * sysdeps/unix/sysv/linux/s390/s390-64/Makefile: Likewise. + * sysdeps/unix/sysv/linux/i386/Makefile: Likewise. + * sysdeps/unix/sysv/linux/m68k/Makefile: Likewise. + + * hurd/errno.c: Renamed to ... + * hurd/errno-loc.c: ... this. + * hurd/Makefile (routines): errno -> errno-loc + +2002-10-13 Ulrich Drepper + + * po/de.po: Update from translation team. + + * MakeTAGS: Add -E flag to xgettext runs. + +2002-10-12 Ulrich Drepper + + * po/fr.po: Update from translation team. + + * sysdeps/posix/system.c: Remove support for old and buggy SCO systems. + Optimize a bit for use in glibc. + +2002-10-12 Roland McGrath + + * stdio-common/tst-rndseek.c (TIMEOUT): Increase to 10 seconds. + Some machines are slow. Guido Guenther has one. + +2002-10-12 Ulrich Drepper + + * po/sv.po: Update from translation team. + +2002-10-11 Isamu Hasegawa + + * posix/regcomp.c (re_compile_fastmap_iter): Remove the handling + OP_CONTEXT_NODE. + (regfree): Likewise. + (create_initial_state): Likewise. + (analyze): Remove the substitutions which became useless. + (calc_first): Likewise. + (calc_epsdest): Use edests of OP_BACK_REF in case that it has + epsilon destination. + (duplicate_node_closure): New function. + (duplicate_node): Remove the handling OP_CONTEXT_NODE. + (calc_inveclosure): Likewise. + (calc_eclosure): Likewise. + (calc_eclosure_iter): Invoke duplicate_node_closure instead of + direct invocation of duplicate_node. + (parse): Don't use comma operator in the return to avoid compiler + warning. + (parse_reg_exp): Likewise. + (parse_branch): Likewise. + (parse_expression): Likewise. + (parse_sub_exp): Likewise. + (parse_dup_op): Likewise. + * posix/regex_internal.c (re_dfa_add_node): Remove the substitutions + which became useless. + (create_ci_newstate): Remove the handling OP_CONTEXT_NODE. + (create_cd_newstate): Likewise. + * posix/regex_internal.h (re_token_type_t): Remove the obsolete type. + (re_token_t): Likewise. + (re_dfa_t): Likewise. + (re_node_set_remove): New macro. + * posix/regexec.c (check_matching): Remove the handling + OP_CONTEXT_NODE. + (check_halt_node_context): Likewise. + (proceed_next_node): Likewise. + (pop_fail_stack): Fix the memory leak. + (set_regs): Likewise. + (free_fail_stack_return): New function. + (sift_states_backward): Fix the memory leak. Remove the handling + OP_CONTEXT_NODE. + (update_cur_sifted_state): Append some if clause to avoid redundant + call. + (sub_epsilon_src_nodes): Use IS_EPSILON_NODE since it might be a + back reference. + (check_dst_limits): Remove the handling OP_CONTEXT_NODE. + (check_subexp_limits): Likewise. + (search_subexp): Likewise. + (sift_states_bkref): Likewise. + (transit_state_mb): Likewise. + (transit_state_bkref_loop): Likewise. + (transit_state_bkref_loop): Likewise. + (group_nodes_into_DFAstates): Likewise. + (check_node_accept): Likewise. + (sift_ctx_init): Add initializing. + +2002-10-12 Ulrich Drepper + + * sysdeps/unix/sysv/linux/i386/sysdep.h (INLINE_SYSCALL): Use + __builtin_expect. + +2002-10-11 Ulrich Drepper + + * elf/dl-load.c (_dl_map_object_from_fd): Remove unnecessarily + duplicated variable c. + + * sysdeps/unix/sysv/linux/sigwait.c (__sigwait): Use INTERNAL_SYSCALL + if possible. + + * sysdeps/unix/sysv/linux/i386/sysdep.h + (INTERNAL_SYSCALL_ERROR_P): New define. + (INTERNAL_SYSCALL_ERRNO): Likewise. + + * sysdeps/unix/sysv/linux/i386/profil-counter.h (profil_counter): + Add hack to prevent the compiler from clobbering the signal context. + +2002-10-11 Roland McGrath + + * sysdeps/unix/sysv/linux/x86_64/sysdep.h (SYSCALL_ERROR_HANDLER): + Fix typos. + + * sysdeps/generic/dl-lookupcfg.h: Include . + * sysdeps/sh/dl-lookupcfg.h: File removed. + * sysdeps/i386/dl-lookupcfg.h: File removed. + + * sysdeps/unix/sysv/linux/x86_64/sysdep.h (SYSCALL_ERROR_HANDLER): Add + missing labels and ; from last change. + + * stdio-common/tst-sscanf.c (val_double): Append .0 to large whole + number literals, so they are doubles instead of ints. + +2002-10-09 Roland McGrath + + * sysdeps/generic/bits/libc-tsd.h [USE___THREAD]: Conditional + changed from [USE_TLS && HAVE___THREAD]. + + * sysdeps/i386/dl-machine.h (elf_machine_type_class, elf_machine_rel): + Disable TLS relocs if [RTLD_BOOTSTRAP && !USE___THREAD]. + * sysdeps/x86_64/dl-machine.h + (elf_machine_type_class, elf_machine_rela): Likewise. + * sysdeps/sh/dl-machine.h (elf_machine_type_class, elf_machine_rela): + Likewise. + + * include/link.h (struct link_map): Remove member l_tls_tp_initialized. + * elf/rtld.c (_dl_start_final, dl_main): Don't use it. + (_dl_start): Conditionalize PT_TLS check on [USE___THREAD]. + + * sysdeps/i386/dl-tls.h (__TLS_GET_ADDR): Use ___tls_get_addr_internal + instead of ___tls_get_addr. + (___tls_get_addr_internal): Add attribute_hidden to decl. + + * sysdeps/generic/ldsodefs.h (struct rtld_global): New variable + _dl_error_catch_tsd. + * elf/rtld.c (startup_error_tsd): New function. + (dl_main): Point _dl_error_catch_tsd at that. + * elf/dl-error.c: Don't use libc-tsd.h for DL_ERROR, + use new function pointer instead. + * elf/dl-tsd.c: New file. + * elf/Makefile (routines): Add it. + +2002-10-07 Roland McGrath + + * elf/dl-misc.c (_dl_debug_vdprintf): Use INTERNAL_SYSCALL macro for + writev if it's available. Otherwise if [RTLD_PRIVATE_ERRNO] then + take _dl_load_lock around calling __writev. + + * sysdeps/unix/sysv/linux/i386/sysdep.h (INTERNAL_SYSCALL): New macro. + (INLINE_SYSCALL): Use that. + + * sysdeps/generic/dl-sysdep.h: New file. + * sysdeps/mach/hurd/dl-sysdep.h: New file. + * sysdeps/generic/ldsodefs.h: Include . + * include/errno.h [IS_IN_rtld]: Include to define ... + [RTLD_PRIVATE_ERRNO]: Use a hidden global variable for errno and + access it directly. + * elf/dl-minimal.c (__errno_location): Removed. + * sysdeps/unix/i386/sysdep.S (__syscall_errno) [RTLD_PRIVATE_ERRNO]: + Use GOTOFF access for errno. + * sysdeps/unix/sysv/linux/i386/sysdep.h + [RTLD_PRIVATE_ERRNO] (SYSCALL_ERROR_HANDLER): Likewise. + + * sysdeps/unix/x86_64/sysdep.S (__syscall_errno) [RTLD_PRIVATE_ERRNO]: + Use PC-relative access for errno. + * sysdeps/unix/sysv/linux/x86_64/sysdep.h + [RTLD_PRIVATE_ERRNO] (SYSCALL_ERROR_HANDLER): Likewise. + + * include/tls.h: New file. + (USE___THREAD): New macro. + Define to 1 under [USE_TLS && HAVE___THREAD] and only when compiling + libc or libpthread. + * sysdeps/unix/sysv/linux/i386/sysdep.h [USE___THREAD]: Conditional + changed from [USE_TLS && HAVE___THREAD]. + * sysdeps/unix/sysv/linux/x86_64/sysdep.h: Likewise. + * sysdeps/unix/i386/sysdep.S: Likewise. + * sysdeps/unix/x86_64/sysdep.S: Likewise. + * include/errno.h: Likewise. + * include/netdb.h: Likewise. + * include/resolv.h: Likewise. + + * sysdeps/generic/errno.c: New file. + * csu/Makefile (aux): New variable, list errno. + * sysdeps/unix/sysv/linux/i386/sysdep.S (errno, _errno): Remove defns. + * sysdeps/unix/sysv/linux/m68k/sysdep.S: Likewise. + * sysdeps/unix/sysv/linux/x86_64/sysdep.S: Likewise. + * sysdeps/unix/sysv/linux/s390/s390-64/sysdep.S: Likewise. + * sysdeps/unix/sysv/linux/s390/s390-32/sysdep.S: Likewise. + * sysdeps/unix/sysv/linux/arm/sysdep.S: Likewise. + * sysdeps/unix/sysv/linux/cris/sysdep.S: Likewise. + * sysdeps/unix/sysv/linux/hppa/sysdep.c: Likewise. + * sysdeps/unix/sysv/linux/ia64/sysdep.S: Likewise. + * sysdeps/unix/sysv/linux/powerpc/sysdep.c: Likewise. + * sysdeps/unix/sysv/linux/sparc/sysdep.S: Likewise. + * sysdeps/unix/sysv/linux/sh/sysdep.S: Likewise. + * sysdeps/unix/alpha/sysdep.S: Likewise. + * sysdeps/generic/start.c: Likewise. + * sysdeps/unix/start.c: Likewise. + * sysdeps/unix/arm/start.c: Likewise. + * sysdeps/unix/bsd/ultrix4/mips/start.S: Likewise. + * sysdeps/unix/sparc/start.c: Likewise. + * sysdeps/unix/sysv/irix4/start.c: Likewise. + * sysdeps/unix/sysv/linux/mips/sysdep.S: File removed. + + * manual/search.texi (Tree Search Function, Hash Search Function): + Mention search.h clearly. + +2002-10-05 Roland McGrath + + * elf/dl-fxstat64.c: File removed. + * elf/dl-xstat64.c: File removed. + * elf/Makefile (rtld-routines): Remove them. + * sysdeps/unix/sysv/linux/xstat64.c: Remove RTLD_STAT64 conditionals. + Instead, use strong_alias instead of versioned_symbol in the + !SHLIB_COMPAT case. + * sysdeps/unix/sysv/linux/fxstat64.c: Likewise. + * sysdeps/unix/sysv/linux/lxstat64.c: Likewise. + + * include/shlib-compat.h + (SHLIB_COMPAT): Require that IS_IN_##lib be defined nonzero. + [! NOT_IN_libc] (IS_IN_libc): Define it. + * cppflags-iterator.mk (CPPFLAGS-$(cpp-src)): Use -Dx=1 not just -Dx. + * elf/Makefile (CPPFLAGS-.os): Likewise. + + * sunrpc/rpc_main.c (main): Don't declare with noreturn attribute. + Return the status instead of calling exit. + + * Makeconfig (CFLAGS): Prepend -std=gnu99. + * Makerules (+make-deps): Use $(CFLAGS) only for .c sources. + Remove superfluous rm command, whose @ plus make bugs hid + all these commands from the make output. + + * include/stubs-prologue.h: New file. Give #error under #ifdef _LIBC. + * Makefile ($(inst_includedir)/gnu/stubs.h): Depend on it. + Use that file's contents instead of literal echo's for the prologue. + * include/features.h: Include unconditionally. + * include/gnu/stubs.h: New file. + +2002-09-30 Roland McGrath + + * elf/rtld-Rules: New file. + * elf/Makefile ($(objpfx)librtld.map, $(objpfx)librtld.mk, + $(objpfx)rtld-libc.a): New targets. + (generated): Add them. + (reloc-link): Remove -o $@ from the variable. + ($(objpfx)dl-allobjs.os): Add -o $@ after $(reloc-link). + (distribute): Add rtld-Rules. + (CPPFLAGS-.os): Define this instead of CFLAGS-.os. + * Makerules ($(+sysdir_pfx)sysd-rules): Emit rules for rtld-% targets. + (common-mostlyclean, common-clean): Clean up rtld-* files. + * sysdeps/unix/make-syscalls.sh: Add rtld-*.os target name to rules. + +2003-05-20 Jakub Jelinek + + * elf/dynamic-link.h (elf_get_dynamic_info): Add temp argument. + If temp != NULL, copy dynamic entries which need relocation to temp + array before relocating. + (DL_RO_DYN_TEMP_CNT): Define. + * elf/dl-load.c (_dl_map_object_from_fd): Adjust caller. + * elf/rtld.c (_dl_start): Likewise. + (dl_main): Likewise. Add dyn_temp static variable. + +2002-10-11 Roland McGrath + + * sysdeps/generic/dl-tls.c (__tls_get_addr): After freeing block in + now-unused dtv slot, reset the slot to TLS_DTV_UNALLOCATED. + + * elf/tls-macros.h [__x86_64__] (TLS_GD): Fix the sequence with the + proper set of no-op insn prefixes. + + * elf/tst-tls8.c (do_test): Use %zd format for l_tls_modid members. + +2002-10-11 Ulrich Drepper + + * sysdeps/unix/sysv/linux/execve.c: Don't try calling + __pthread_kill_other_threads_np. + + * sysdeps/generic/pselect.c: Avoid unnecessary sigprocmask calls. + +2002-10-08 Roland McGrath + + * locale/newlocale.c (__newlocale): If setting all categories to "C", + just return &_nl_C_locobj instead of copying it. + * locale/freelocale.c (__freelocale): Check for &_nl_C_locobj. + * locale/duplocale.c (__duplocale): Likewise. + +2002-10-07 Roland McGrath + + * config.h.in (HAVE_I386_SET_GDT): New #undef. + * sysdeps/mach/configure.in: Define it with new check for i386_set_gdt. + * sysdeps/mach/configure: Regenerated. + +2002-10-06 Franz Sirl + + * sysdeps/unix/sysv/linux/powerpc/powerpc32/sysdep.h (INLINE_SYSCALL): + Add all necessary register outputs for syscall-clobbered registers. + +2002-10-02 David Mosberger + + * sysdeps/ia64/bzero.S: Rewritten by Sverre Jarp to tune for + Itanium 2 (and Itanium). + Fix unwind directives and make it fit in 80 columns. + * sysdeps/ia64/memset.S: Likewise. + * sysdeps/ia64/memcpy.S: Likewise. + Move jump table to .rodata section. + +2002-10-03 Roland McGrath + + * sysdeps/mach/hurd/i386/init-first.c (_hurd_stack_setup): Add + clobbers to asm. + +2002-10-10 Andreas Jaeger + + * sysdeps/x86_64/_mcount.S: Restore correct registers. + +2002-10-10 Ulrich Drepper + + * posix/Versions (libc) [GLIBC_PRIVATE]: Add __pselect. + +2002-10-09 Ulrich Drepper + + * sysdeps/generic/ldsodefs.h: Remove attribute_hidden from + _dl_allocate_tls_init. Add rtld_hidden_proto. + * sysdeps/generic/dl-tls.c (_dl_allocate_tls_init): Add + rtld_hidden_def. + * elf/Versions (ld) [GLIBC_PRIVATE]: Add _dl_allocate_tls_init. + + * version.h (VERSION): Bump to 2.3.1. + + * Make-dist: Add back one of the tar invocations removed before. + + * stdlib/Makefile (distribute): Add allocalim.h. + + * sysdeps/generic/bits/libc-tsd.h [!(USE_TLS && HAVE___THREAD)] + (__libc_tsd_address): Use correct variable name. + Patch by Stefan Jones . + + * sysdeps/unix/sysv/linux/ia64/getcontext.S: Add missing ;;. + Reported by edwardsg@sgi.com [PR libc/4678]. + + * Versions.def (libc): Add GLIBC_2.3.1. + (libpthread): Add GLIBC_2.3.1. + + * include/signal.h: Add libc_hidden_proto for __sigwait, __sigwaitinfo, + and __sigtimedwait. + * signal/Versions: Add __sigtimedwait, __sigwait, and __sigwaitinfo. + * sysdeps/unix/sysv/linux/sigtimedwait.c (__sigtimedwait): Add + libc_hidden_def. + * sysdeps/unix/sysv/linux/sigwait.c (__sigwait): Likewise. + * sysdeps/unix/sysv/linux/sigwaitinfo.c (__sigwaitinfo): Likewise. + + * include/sys/msg.h: Declare __libc_msgrcv and __libc_msgsnd. + * sysdeps/unix/sysv/linux/msgrcv.c (__msgrcv): Rename to __libc_msgrcv + and make old name an alias. + * sysdeps/unix/sysv/linux/msgsnd.c (__msgsnd): Rename to __libc_msgsnd + and make old name an alias. + * sysvipc/Versions (libc) [GLIBC_PRIVATE]: Add __libc_msgrcv and + __libc_msgsnd. + + * include/sys/uio.h: Declare __libc_readv and __libc_writev. + * misc/Versions (libc) [GLIBC_PRIVATE]: Add __libc_readv and + __libc_writev. + * sysdeps/generic/readv.c (__readv): Rename to __libc_readv and make + old name an alias. + * sysdeps/posix/readv.c: Likewise + * sysdeps/unix/sysv/aix/readv.c: Likewise. + * sysdeps/unix/sysv/linux/readv.c: Likewise. + * sysdeps/generic/writev.c (__writev): Rename to __libc_writev and make + old name an alias. + * sysdeps/posix/writev.c: Likewise + * sysdeps/unix/sysv/aix/writev.c: Likewise. + * sysdeps/unix/sysv/linux/writev.c: Likewise. + + * include/sys/wait.h: Declare __waitid. + * posix/Versions (libc) [GLIBC_PRIVATE]: Add __waitid. + * sysdeps/generic/waitid.c (waitid): Rename to __waitid and make old + name an alias. + * sysdeps/posix/waitid.c: Likewise. + * sysdeps/unix/sysv/aix/waitid.c: Likewise. + + * sysdeps/unix/sysv/linux/syscalls.list: Add creat syscall. + +2002-10-07 Jakub Jelinek + + * include/alloca.h (__libc_use_alloca, __libc_alloca_cutoff): New + prototypes. + (__MAX_ALLOCA_CUTOFF): Define. + Include allocalim.h. + * resolv/nss_dns/dns-host.c (_nss_dns_gethostbyname2_r, + _nss_dns_gethostbyaddr_r): Use alloca or malloc to allocate + host_buffer depending on __libc_use_alloca. + * resolv/nss_dns/dns-network.c (_nss_dns_getnetbyname_r, + _nss_dns_getnetbyaddr_r): Use alloca or malloc to allocate + net_buffer depending on __libc_use_alloca. + * resolv/res_query.c (res_nquery): Use alloca or malloc to allocate + buf depending on __libc_use_alloca. + * resolv/gethnamaddr.c (gethostbyname2, gethostbyaddr): Likewise. + * stdio-common/vfprintf.c (vfprintf): Use __libc_use_alloca + instead of hardcoded constants. + Pass proper size argument to alloca and compute end for wide char + version. + * stdio-common/printf_fp.c (__printf_fp): Use __libc_use_alloca + instead of hardcoded constants. + * string/strcoll.c (strcoll): Likewise. + * string/strxfrm.c (strxfrm): Likewise. + * sysdeps/posix/readv.c (__readv): Likewise. + * sysdeps/posix/writev.c (__writev): Likewise. + * sysdeps/generic/allocalim.h: New file. + +2002-10-08 Roland McGrath + + * configure.in (aux_missing warning): Change "too old" to + "incompatible versions", since for autoconf it's "too new" right now. + * configure: Regenerated. + + * configure.in (AUTOCONF): New check to set it. Set to "no" if the + one found doesn't work on our configure.in. + * configure: Regenerated. + * config.make.in (AUTOCONF): New substituted variable. + * Makefile (autoconf-it-cvs): New canned sequence, broken out of ... + (autoconf-it): ... here, use that instead of defining conditionally. + Use $(AUTOCONF) instead of literal autoconf. + [$(AUTOCONF) != no] (configure, %/configure): Protect these rules + with this condition. + * Make-dist (autoconf-it, configure, %/configure): Copy those changes. + +2002-10-08 Ulrich Drepper + + * Make-dist (dist): Cleanup a bit. We are not interested in the + 14 char filename limit anymore. Remove intermediate files and + symlinks. + +2002-10-05 Ulrich Drepper + + * po/sk.po: Update from translation team. + * po/tr.po: Likewise. + * po/gl.po: Likewise. + +2002-10-05 Kaz Kojima + + * elf/tls-macros.h: Fix SH version of macros so as to match ABI syntax. + +2002-10-03 Ulrich Drepper + + * version.h (RELEASE): Change to stable. + +2002-10-03 Jakub Jelinek + + * sysdeps/unix/sysv/linux/_exit.c (__syscall_exit, + __syscall_exit_group): New prototypes. + +2002-10-03 Ulrich Drepper + + * glibc 2.3 released. + + +See ChangeLog.13 for earlier changes. diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/regex/tst-regexloc.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/regex/tst-regexloc.c new file mode 100644 index 00000000..4bc65f66 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/regex/tst-regexloc.c @@ -0,0 +1,54 @@ +/* Copyright (C) 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + +int +main (int argc, char *argv[]) +{ +/* If uclibc has extended locale, or if it's a host build + * (assuming host libc always has locale): */ +#if defined __UCLIBC_HAS_XLOCALE__ || !defined __UCLIBC__ + regex_t re; + regmatch_t mat[1]; + int exitcode = 1; + + if (setlocale (LC_ALL, "de_DE.ISO-8859-1") == NULL) + puts ("cannot set locale"); + else if (regcomp (&re, "[a-f]*", 0) != REG_NOERROR) + puts ("cannot compile expression \"[a-f]*\""); + else if (regexec (&re, "abcdefCDEF", 1, mat, 0) == REG_NOMATCH) + puts ("no match"); + else + { + exitcode = mat[0].rm_so != 0 || mat[0].rm_eo != 6; + printf ("match from %d to %d - %s\n", + mat[0].rm_so, mat[0].rm_eo, + exitcode ? "WRONG!" : "ok" + ); + } + + return exitcode; +#else + puts("Test requires locale; skipping"); + return 0; +#endif +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/rpc/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/test/rpc/Makefile new file mode 100644 index 00000000..47accc62 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/rpc/Makefile @@ -0,0 +1,7 @@ +# uClibc rpc tests +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + +top_builddir=../../ +include ../Rules.mak +-include Makefile.in +include ../Test.mak diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/rpc/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/test/rpc/Makefile.in new file mode 100644 index 00000000..5612ff20 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/rpc/Makefile.in @@ -0,0 +1,11 @@ +# uClibc rpc tests +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + +TESTS := getrpcent + +ifeq ($(UCLIBC_HAS_REENTRANT_RPC),y) +TESTS += getrpcent_r +endif + +DODIFF_getrpcent := 1 + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/rpc/getrpcent.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/rpc/getrpcent.c new file mode 100644 index 00000000..e12e7680 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/rpc/getrpcent.c @@ -0,0 +1,18 @@ +#include +#include + +int main(int argc, char *argv[]) +{ + struct rpcent *ent; + + while ((ent = getrpcent()) != NULL) { + printf("%s: %i", ent->r_name, ent->r_number); + while (ent->r_aliases[0]) + printf(" %s", *ent->r_aliases++); + printf("\n"); + } + + endrpcent(); + + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/rpc/getrpcent_r.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/rpc/getrpcent_r.c new file mode 100644 index 00000000..65ca61cd --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/rpc/getrpcent_r.c @@ -0,0 +1,25 @@ +#include +#include +#include +#include + +int main(int argc, char *argv[]) +{ + int ret; + char rpcdata[1024]; + struct rpcent rpcbuf, *ent; + + while ((ret = getrpcent_r(&rpcbuf, rpcdata, sizeof(rpcdata), &ent)) == 0) { + printf("%s: %i", ent->r_name, ent->r_number); + while (ent->r_aliases[0]) + printf(" %s", *ent->r_aliases++); + printf("\n"); + } + + if (ret != ENOENT) + printf("Test failed: %s\n", strerror(ret)); + + endrpcent(); + + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/setjmp/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/test/setjmp/Makefile new file mode 100644 index 00000000..a26e2d57 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/setjmp/Makefile @@ -0,0 +1,7 @@ +# uClibc setjmp tests +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + +top_builddir=../../ +include ../Rules.mak +-include Makefile.in +include ../Test.mak diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/setjmp/bug269-setjmp.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/setjmp/bug269-setjmp.c new file mode 100644 index 00000000..b11ac7b2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/setjmp/bug269-setjmp.c @@ -0,0 +1,107 @@ +/* Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ ; + +/* Test case for Bugzilla # 269 */ + +#include +#include +#include + +jmp_buf buf1; +jmp_buf buf2; +int *p; +int n_x = 6; + +static int g_counter = 0; + +static int +f (void) +{ + static int counter = 0; + static int way_point1 = 3; + static int way_point2 = 2; + int lose = 0; + + if (setjmp (buf1) != 101) + { + int a[n_x]; /* reallocate stack space */ + g_counter++; + p = &a[0]; + if (g_counter < 5) + longjmp (buf1, 2); + else if (g_counter == 5) + longjmp (buf1, 101); + else + { + _setjmp (buf2); + _longjmp (buf1, 101); + } + } + + way_point1--; + + if (counter == 0) + { + counter++; + { + int a[n_x]; /* reallocate stack space */ + g_counter++; + p = &a[0]; + if (g_counter < 5) + longjmp (buf1, 2); + else if (g_counter == 5) + longjmp (buf1, 101); + else + { + _setjmp (buf2); + _longjmp (buf1, 101); + } + } + } + + way_point2--; + + if (counter == 1) + { + counter++; + longjmp (buf2, 2); + } + + lose = !(way_point1 == 0 && way_point2 == 0 + && g_counter == 6 && counter == 2); + + return lose; +} + +static int +do_test (void) +{ + int lose; + + lose = f (); + + if (lose) + puts ("Test FAILED!"); + else + puts ("Test succeeded!"); + + return lose ? EXIT_FAILURE : EXIT_SUCCESS; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/setjmp/jmpbug.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/setjmp/jmpbug.c new file mode 100644 index 00000000..da087a72 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/setjmp/jmpbug.c @@ -0,0 +1,51 @@ +/* setjmp vs alloca test case. Exercised bug on sparc. */ + +#include +#include +#include + +int ret; +int verbose; + +__attribute__ ((__noreturn__)) +static void +sub5 (jmp_buf buf) +{ + longjmp (buf, 1); +} + +static void +test (int x) +{ + jmp_buf buf; + char *foo; + int arr[100]; + + ++ret; + + arr[77] = x; + if (setjmp (buf)) + { + --ret; + if (verbose) + printf ("made it ok; %d\n", arr[77]); + return; + } + + foo = (char *) alloca (128); + sub5 (buf); +} + +int +main (int argc, char *argv[]) +{ + int i; + + verbose = (argc != 1); + ret = 0; + + for (i = 123; i < 345; ++i) + test (i); + + return ret; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/setjmp/sigjmpbug.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/setjmp/sigjmpbug.c new file mode 100644 index 00000000..5b171818 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/setjmp/sigjmpbug.c @@ -0,0 +1,51 @@ +/* sigsetjmp vs alloca test case. Exercised bug on sparc. */ + +#include +#include +#include + +int ret; +int verbose; + +__attribute__ ((__noreturn__)) +static void +sub5 (jmp_buf buf) +{ + siglongjmp (buf, 1); +} + +static void +test (int x) +{ + sigjmp_buf buf; + char *foo; + int arr[100]; + + ++ret; + + arr[77] = x; + if (sigsetjmp (buf, 1)) + { + --ret; + if (verbose) + printf ("made it ok; %d\n", arr[77]); + return; + } + + foo = (char *) alloca (128); + sub5 (buf); +} + +int +main (int argc, char *argv[]) +{ + int i; + + verbose = (argc != 1); + ret = 0; + + for (i = 123; i < 345; ++i) + test (i); + + return ret; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/setjmp/tst-setjmp.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/setjmp/tst-setjmp.c new file mode 100644 index 00000000..f0feb99a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/setjmp/tst-setjmp.c @@ -0,0 +1,119 @@ +/* Copyright (C) 1991, 1992, 1997, 1998, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +static jmp_buf env; +static int last_value = -1, lose = 0; + +__attribute__ ((__noreturn__)) +static void +jump (int val) +{ + longjmp (env, val); +} + +int +main (void) +{ + int value; + + value = setjmp (env); + if (value != last_value + 1) + { + fputs("Shouldn't have ", stdout); + lose = 1; + } + last_value = value; + switch (value) + { + case 0: + puts("Saved environment."); + jump (0); + default: + printf ("Jumped to %d.\n", value); + if (value < 10) + jump (value + 1); + } + + if (!lose && value == 10) + { + /* Do a second test, this time without `setjmp' being a macro. + This is not required by ISO C but we have this for compatibility. */ +#undef setjmp + extern int setjmp (jmp_buf); + + last_value = -1; + lose = 0; + + value = setjmp (env); + if (value != last_value + 1) + { + fputs("Shouldn't have ", stdout); + lose = 1; + } + last_value = value; + switch (value) + { + case 0: + puts("Saved environment."); + jump (0); + default: + printf ("Jumped to %d.\n", value); + if (value < 10) + jump (value + 1); + } + } + + if (!lose && value == 10) + { + /* And again for the `_setjmp' function. */ +#ifndef _setjmp + extern int _setjmp (jmp_buf); +#endif + last_value = -1; + lose = 0; + + value = _setjmp (env); + if (value != last_value + 1) + { + fputs("Shouldn't have ", stdout); + lose = 1; + } + last_value = value; + switch (value) + { + case 0: + puts("Saved environment."); + jump (0); + default: + printf ("Jumped to %d.\n", value); + if (value < 10) + jump (value + 1); + } + } + + if (lose || value != 10) + puts ("Test FAILED!"); + else + puts ("Test succeeded!"); + + return lose ? EXIT_FAILURE : EXIT_SUCCESS; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/setjmp/tst-vfork-longjmp.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/setjmp/tst-vfork-longjmp.c new file mode 100644 index 00000000..27844247 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/setjmp/tst-vfork-longjmp.c @@ -0,0 +1,108 @@ +/* make sure we can vfork/exec across setjmp/longjmp's + * and make sure signal block masks don't get corrupted + * in the process. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int verbose = 0; + +static int execute_child(const char *prog) +{ + int status; + pid_t child; + child = vfork(); + if (child == 0) { + execlp(prog, prog, NULL); + perror("Could not execute specified prog"); + _exit(1); + } else if (child == 1) + return 1; + wait(&status); + return WEXITSTATUS(status); +} + +sigset_t orig_mask; + +static int check_sig_mask(void) +{ + int status; + pid_t child; + + child = vfork(); + if (child == 0) { + int ret; + sigset_t child_mask; + memset(&child_mask, 0x00, sizeof(child_mask)); + ret = sigprocmask(SIG_BLOCK, NULL, &child_mask); + if (ret != 0) { + perror("could not get child sig block mask"); + _exit(1); + } + ret = memcmp(&orig_mask, &child_mask, sizeof(orig_mask)); + if (verbose) { + printf("sigmsk: %08lx%08lx ", child_mask.__val[1], child_mask.__val[0]); + printf("sigmsk: %08lx%08lx ", orig_mask.__val[1], orig_mask.__val[0]); + printf("%i\n", ret); + } + _exit(ret); + } else if (child == 1) + return 1; + wait(&status); + return WEXITSTATUS(status); +} + +int main(int argc, char *argv[]) +{ + const char *prog; + jmp_buf env; + sigjmp_buf sigenv; + int max; + /* values modified between setjmp/longjmp cannot be local to this func */ + static int cnt, ret; + + memset(&orig_mask, 0x00, sizeof(orig_mask)); + ret = sigprocmask(SIG_BLOCK, NULL, &orig_mask); + if (ret != 0) { + perror("could not get orig sig block mask"); + return 1; + } + + prog = (argc > 1 ? argv[1] : "true"); + ret = 0; + verbose = 0; + max = 10; + + /* test vfork()/exec() inside of sigsetjmp/siglongjmp */ + cnt = 0; + sigsetjmp(sigenv, 1); + ++cnt; + if (verbose) + printf("sigsetjmp loop %i\n", cnt); + ret |= check_sig_mask(); + ret |= execute_child(prog); + if (cnt < max) + siglongjmp(sigenv, 0); + + /* test vfork()/sigprocmask() inside of setjmp/longjmp */ + cnt = 0; + setjmp(env); + ++cnt; + if (verbose) + printf("setjmp loop %i\n", cnt); + ret |= check_sig_mask(); + ret |= execute_child(prog); + if (cnt < max) + longjmp(env, 0); + + return ret; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/signal/.indent.pro b/l4/pkg/uclibc/lib/contrib/uclibc/test/signal/.indent.pro new file mode 100644 index 00000000..492ecf1c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/signal/.indent.pro @@ -0,0 +1,33 @@ +--blank-lines-after-declarations +--blank-lines-after-procedures +--break-before-boolean-operator +--no-blank-lines-after-commas +--braces-on-if-line +--braces-on-struct-decl-line +--comment-indentation25 +--declaration-comment-column25 +--no-comment-delimiters-on-blank-lines +--cuddle-else +--continuation-indentation4 +--case-indentation0 +--else-endif-column33 +--space-after-cast +--line-comments-indentation0 +--declaration-indentation1 +--dont-format-first-column-comments +--dont-format-comments +--honour-newlines +--indent-level4 +/* changed from 0 to 4 */ +--parameter-indentation4 +--line-length78 /* changed from 75 */ +--continue-at-parentheses +--no-space-after-function-call-names +--dont-break-procedure-type +--dont-star-comments +--leave-optional-blank-lines +--dont-space-special-semicolon +--tab-size4 +/* additions by Mark */ +--case-brace-indentation0 +--leave-preprocessor-space diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/signal/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/test/signal/Makefile new file mode 100644 index 00000000..e8293658 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/signal/Makefile @@ -0,0 +1,7 @@ +# uClibc signal tests +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + +top_builddir=../../ +include ../Rules.mak +-include Makefile.in +include ../Test.mak diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/signal/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/test/signal/Makefile.in new file mode 100644 index 00000000..c8e2545f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/signal/Makefile.in @@ -0,0 +1,6 @@ +# uClibc signal tests +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + +ifeq ($(UCLIBC_HAS_OBSOLETE_BSD_SIGNAL),) +TESTS_DISABLED := tst-sigsimple +endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/signal/sigchld.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/signal/sigchld.c new file mode 100644 index 00000000..22febaca --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/signal/sigchld.c @@ -0,0 +1,68 @@ +#include +#include +#include +#include +#include +#include +#include + + +#ifdef __ARCH_USE_MMU__ + +static void test_handler(int signo) +{ + write(1, "caught SIGCHLD\n", 15); + return; +} + +int main(void) +{ + pid_t mypid; + struct sigaction siga; + static sigset_t set; + + /* Set up sighandling */ + sigfillset(&set); + siga.sa_handler = test_handler; + siga.sa_mask = set; + siga.sa_flags = 0; + if (sigaction(SIGCHLD, &siga, (struct sigaction *)NULL) != 0) { + fprintf(stderr, "sigaction choked: %s!", strerror(errno)); + exit(EXIT_FAILURE); + } + + /* Setup a child process to exercise the sig handling for us */ + mypid = getpid(); + if (fork() == 0) { + int i; + + for (i=0; i < 3; i++) { + sleep(2); + kill(mypid, SIGCHLD); + } + _exit(EXIT_SUCCESS); + } + + + /* Wait for signals */ + write(1, "waiting for a SIGCHLD\n",22); + for(;;) { + sleep(10); + if (waitpid(-1, NULL, WNOHANG | WUNTRACED) > 0) + break; + write(1, "after sleep\n", 12); + } + + printf("Bye-bye! All done!\n"); + return 0; +} + +#else + +int main(void) +{ + printf("Skipping test on non-mmu host!\n"); + return 0; +} + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/signal/signal.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/signal/signal.c new file mode 100644 index 00000000..01d1a785 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/signal/signal.c @@ -0,0 +1,95 @@ +/* vi: set sw=4 ts=4: */ +/* + * signal testing function for uClibc + * Copyright (C) 2000-2006 by Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#ifndef _GNU_SOURCE +# define _GNU_SOURCE +#endif +#include +#include +#include +#include +#include +#include +#include + + +/* -------------------------------------------------*/ +/* This stuff is common to all the testing routines */ +/* -------------------------------------------------*/ +const char *it = ""; /* Routine name for message routines. */ +size_t errors = 0; + +static void check(int thing, int number) +{ + if (!thing) { + printf("%s: flunked test %d\n", it, number); + ++errors; + } +} + +#if 0 +static void equal(const char *a, const char *b, int number) +{ + check(a != NULL && b != NULL && (strcmp(a, b) == 0), number); +} +#endif + + +/* -------------------------------------------------*/ +/* Let the tests begin.... */ +/* -------------------------------------------------*/ + +int global_int = 0; + +static void set_global_int_to_one(int signum) +{ + printf ("Received signal %d (%s).\n", signum, strsignal(signum)); + global_int = 1; + return; +} + +static void signal_test_1(void) +{ + global_int = 0; + + it = "global variable set from signal handler"; + if (signal(SIGUSR1, set_global_int_to_one) == SIG_ERR) { + perror("signal(SIGUSR1) failed"); + exit(-1); + } + raise(SIGUSR1); + + /* This should already have jumped to the signal handler */ + check((global_int == 1), 1); + + global_int = 0; + if (signal(SIGUSR1, SIG_IGN) == SIG_ERR) { + perror("signal(SIGUSR1) failed"); + exit(-1); + } + raise(SIGUSR1); + /* This should not go to the signal handler this time since we */ + check((global_int == 0), 1); +} + + +int main(void) +{ + int status; + + signal_test_1(); + + if (errors == 0) { + status = EXIT_SUCCESS; + printf("No errors.\n"); + } else { + status = EXIT_FAILURE; + printf("%lu errors.\n", (unsigned long)errors); + } + exit(status); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/signal/tst-raise.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/signal/tst-raise.c new file mode 100644 index 00000000..d24c316c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/signal/tst-raise.c @@ -0,0 +1,63 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include + +volatile int count; + +static void +sh (int sig) +{ + ++count; +} + +int +main (void) +{ + struct sigaction sa; + sa.sa_handler = sh; + sigemptyset (&sa.sa_mask); + sa.sa_flags = 0; + if (sigaction (SIGUSR1, &sa, NULL) < 0) + { + printf ("sigaction failed: %s\n", strerror(errno)); + exit (1); + } + if (raise (SIGUSR1) < 0) + { + printf ("first raise failed: %s\n", strerror(errno)); + exit (1); + } + if (raise (SIGUSR1) < 0) + { + printf ("second raise failed: %s\n", strerror(errno)); + exit (1); + } + if (count != 2) + { + printf ("signal handler not called 2 times\n"); + exit (1); + } + exit (0); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/signal/tst-signal.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/signal/tst-signal.c new file mode 100644 index 00000000..6d317879 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/signal/tst-signal.c @@ -0,0 +1,44 @@ +#include +#include +#include +#include + +int win = 0; + +static void +handler (int sig) +{ + printf ("Received signal %d (%s).\n", sig, strsignal(sig)); + win = 1; +} + +int +main (void) +{ + if (signal (SIGTERM, handler) == SIG_ERR) + { + perror ("signal: SIGTERM"); + exit (EXIT_FAILURE); + } + + puts ("Set handler."); + + printf ("Sending myself signal %d.\n", SIGTERM); + fflush (stdout); + + if (raise (SIGTERM) < 0) + { + perror ("raise: SIGTERM"); + exit (EXIT_FAILURE); + } + + if (!win) + { + puts ("Didn't get any signal. Test FAILED!"); + exit (EXIT_FAILURE); + } + + puts ("Got a signal. Test succeeded."); + + return EXIT_SUCCESS; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/signal/tst-sigset.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/signal/tst-sigset.c new file mode 100644 index 00000000..bc1b0576 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/signal/tst-sigset.c @@ -0,0 +1,45 @@ +/* Test sig*set functions. */ + +#include +#include +#include +#include + +#define TEST_FUNCTION do_test () +static int +do_test (void) +{ + int result = 0; + int sig = -1; + +#define TRY(call) \ + if (call) \ + { \ + printf ("%s (sig = %d): %s\n", #call, sig, strerror(errno)); \ + result = 1; \ + } \ + else + + + sigset_t set; + TRY (sigemptyset (&set) != 0); + +#ifdef SIGRTMAX + int max_sig = SIGRTMAX; +#else + int max_sig = NSIG - 1; +#endif + + for (sig = 1; sig <= max_sig; ++sig) + { + TRY (sigismember (&set, sig) != 0); + TRY (sigaddset (&set, sig) != 0); + TRY (sigismember (&set, sig) == 0); + TRY (sigdelset (&set, sig) != 0); + TRY (sigismember (&set, sig) != 0); + } + + return result; +} + +#include "../test-skeleton.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/signal/tst-sigsimple.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/signal/tst-sigsimple.c new file mode 100644 index 00000000..22bb85cb --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/signal/tst-sigsimple.c @@ -0,0 +1,57 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + + +static int +do_test (void) +{ + int result = 0; + int e; + +#define RUN(test) \ + errno = 0; \ + e = test; \ + if (e != -1) \ + { \ + printf ("%s returned %d\n", #test, e); \ + result = 1; \ + } \ + else if (errno != EINVAL) \ + { \ + printf ("%s didn't set errno to EINVAL (%s instead)\n", \ + #test, strerror (errno)); \ + result = 1; \ + } + + RUN (sighold (-1)); + RUN (sighold (_NSIG + 100)); + + RUN (sigrelse (-1)); + RUN (sigrelse (_NSIG + 100)); + + return result; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/silly/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/test/silly/Makefile new file mode 100644 index 00000000..4db1850d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/silly/Makefile @@ -0,0 +1,7 @@ +# uClibc silly tests +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + +top_builddir=../../ +include ../Rules.mak +-include Makefile.in +include ../Test.mak diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/silly/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/test/silly/Makefile.in new file mode 100644 index 00000000..bb08e0db --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/silly/Makefile.in @@ -0,0 +1,5 @@ +# uClibc silly tests +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + +RET_hello := 42 +RET_tiny := 42 diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/silly/hello.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/silly/hello.c new file mode 100644 index 00000000..4aba926e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/silly/hello.c @@ -0,0 +1,8 @@ +#include +#include + +int main(void) +{ + printf("hello world\n"); + exit(42); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/silly/tiny.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/silly/tiny.c new file mode 100644 index 00000000..e54c0ff9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/silly/tiny.c @@ -0,0 +1,6 @@ +#include + +int main(void) +{ + _exit(42); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/stat/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/test/stat/Makefile new file mode 100644 index 00000000..ecde416d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/stat/Makefile @@ -0,0 +1,7 @@ +# uClibc stat tests +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + +top_builddir=../../ +include ../Rules.mak +-include Makefile.in +include ../Test.mak diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/stat/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/test/stat/Makefile.in new file mode 100644 index 00000000..9c06dedb --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/stat/Makefile.in @@ -0,0 +1,13 @@ +# uClibc stat tests +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + +ifeq ($(UCLIBC_HAS_LFS),) +TESTS_DISABLED := stat64 +endif +CFLAGS_stat64 := -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 + +DODIFF_stat := 1 +DODIFF_stat64 := 1 + +OPTS_stat := Makefile +OPTS_stat64 := Makefile diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/stat/memcmp-stat.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/stat/memcmp-stat.c new file mode 100644 index 00000000..254c754c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/stat/memcmp-stat.c @@ -0,0 +1,107 @@ +/* Distilled from issue found with tar and symlinks. + * Make sure that the whole stat struct between runs + * is agreeable. + */ + +#ifndef _GNU_SOURCE +# define _GNU_SOURCE +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static void show_stat(struct stat *st) +{ + printf( + "------------------\n" + "st_dev = %li\n" + "st_ino = %li\n" + "st_mode = %li\n" + "st_nlink = %li\n" + "st_uid = %li\n" + "st_gid = %li\n" + "st_rdev = %li\n" + "st_size = %li\n" + "st_blksize = %li\n" + "st_blocks = %li\n" + "st_atime = %li\n" + "st_ansec = %li\n" + "st_mtime = %li\n" + "st_mnsec = %li\n" + "st_ctime = %li\n" + "st_cnsec = %li\n", + (long int)st->st_dev, + (long int)st->st_ino, + (long int)st->st_mode, + (long int)st->st_nlink, + (long int)st->st_uid, + (long int)st->st_gid, + (long int)st->st_rdev, + (long int)st->st_size, + (long int)st->st_blksize, + (long int)st->st_blocks, +#if !defined(__UCLIBC__) || defined(__USE_MISC) + (long int)st->st_atime, + (long int)st->st_atim.tv_nsec, + (long int)st->st_mtime, + (long int)st->st_mtim.tv_nsec, + (long int)st->st_ctime, + (long int)st->st_ctim.tv_nsec +#else + (long int)st->st_atime, + (long int)st->st_atimensec, + (long int)st->st_mtime, + (long int)st->st_mtimensec, + (long int)st->st_ctime, + (long int)st->st_ctimensec +#endif + ); +} + +int main(void) +{ + int ret; + int fd; + struct stat fst, st; + + memset(&fst, 0xAA, sizeof(fst)); + memset(&st, 0x55, sizeof(st)); + + unlink(".testfile"); + fd = open(".testfile", O_WRONLY | O_CREAT | O_EXCL, 0); + if (fd < 0) { + perror("open(.testfile) failed"); + return 1; + } + ret = fstat(fd, &fst); + if (ret != 0) { + perror("fstat(.testfile) failed"); + return 1; + } + close(fd); + + ret = stat(".testfile", &st); + if (ret != 0) { + perror("stat(.testfile) failed"); + return 1; + } + + ret = memcmp(&fst, &st, sizeof(fst)); + if (ret != 0) { + printf("FAILED: memcmp() = %i\n", ret); + show_stat(&fst); + show_stat(&st); + } + + unlink(".testfile"); + + return ret; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/stat/stat.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/stat/stat.c new file mode 100644 index 00000000..4980cdd7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/stat/stat.c @@ -0,0 +1,71 @@ +#include +#include +#include +#include +#include +#include + +static void print_struct_stat(char *msg, struct stat *s) +{ + printf("%s\n", msg); + /* The casts are because glibc thinks it's cool */ + printf("device : 0x%llx\n",(long long)s->st_dev); + printf("inode : %lld\n", (long long)s->st_ino); + printf("mode : 0x%llx\n",(long long)s->st_mode); + printf("nlink : %lld\n", (long long)s->st_nlink); + printf("uid : %lld\n", (long long)s->st_uid); + printf("gid : %lld\n", (long long)s->st_gid); + printf("rdev : 0x%llx\n",(long long)s->st_rdev); + printf("size : %lld\n", (long long)s->st_size); + printf("blksize : %lld\n", (long long)s->st_blksize); + printf("blocks : %lld\n", (long long)s->st_blocks); + printf("atime : %lld\n", (long long)s->st_atime); + printf("mtime : %lld\n", (long long)s->st_mtime); + printf("ctime : %lld\n", (long long)s->st_ctime); +} + +int main(int argc,char **argv) +{ + int fd, ret; + char *file; + struct stat s; + + if (argc < 2) { + fprintf(stderr, "Usage: stat FILE\n"); + exit(1); + } + file = argv[1]; + + memset(&s, 0, sizeof(struct stat)); + ret = stat(file, &s); + if(ret<0){ + perror("stat"); + exit(1); + } + print_struct_stat("\nTesting stat:", &s); + + memset(&s, 0, sizeof(struct stat)); + ret = lstat(file, &s); + if(ret<0){ + perror("lstat"); + exit(1); + } + print_struct_stat("\nTesting lstat:", &s); + + + fd = open(file, O_RDONLY); + if(fd<0){ + perror("open"); + exit(1); + } + memset(&s, 0, sizeof(struct stat)); + ret = fstat(fd,&s); + if(ret<0){ + perror("fstat"); + exit(1); + } + print_struct_stat("\nTesting fstat:", &s); + + exit(0); +} + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/stat/stat64.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/stat/stat64.c new file mode 100644 index 00000000..a0742519 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/stat/stat64.c @@ -0,0 +1 @@ +#include "stat.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/stdio/64bit.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/stdio/64bit.c new file mode 100644 index 00000000..9b94dd86 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/stdio/64bit.c @@ -0,0 +1,12 @@ +#include + +int main(void) +{ + unsigned long long val = -1; + void *ptr = (void *)-1; + printf("%p\n", ptr); + + sscanf("123456789", "%Lx", &val); + printf("val = %Lx\n", val); + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/stdio/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/test/stdio/Makefile new file mode 100644 index 00000000..a5d662a7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/stdio/Makefile @@ -0,0 +1,7 @@ +# uClibc stdio tests +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + +top_builddir=../../ +include ../Rules.mak +-include Makefile.in +include ../Test.mak diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/stdio/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/test/stdio/Makefile.in new file mode 100644 index 00000000..0bfbd136 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/stdio/Makefile.in @@ -0,0 +1,4 @@ +# uClibc stdio tests +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + +DODIFF_64bit := 1 diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/stdio/fclose-loop.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/stdio/fclose-loop.c new file mode 100644 index 00000000..fc0cc424 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/stdio/fclose-loop.c @@ -0,0 +1,21 @@ +/* From: Denis Vlasenko + * With certain combination of .config options fclose() does not + * remove FILE* pointer from _stdio_openlist. As a result, subsequent + * fopen() may allocate new FILE structure exactly in place of one + * freed by previous fclose(), which then makes _stdio_openlist + * circularlt looped. The following program will enter infinite loop + * trying to walk _stdio_openlist in exit(): + */ + +#include +#include + +int main(int argc, char *argv[]) +{ + FILE* fp; + fp = fopen("/dev/null", "r"); + fclose(fp); + fp = fopen("/dev/zero", "r"); + fclose(fp); + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/stdlib/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/test/stdlib/Makefile new file mode 100644 index 00000000..f8a40384 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/stdlib/Makefile @@ -0,0 +1,7 @@ +# uClibc stdlib tests +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + +top_builddir=../../ +include ../Rules.mak +-include Makefile.in +include ../Test.mak diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/stdlib/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/test/stdlib/Makefile.in new file mode 100644 index 00000000..0bb06975 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/stdlib/Makefile.in @@ -0,0 +1,7 @@ +# uClibc stdlib tests +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + +DODIFF_qsort := 1 +DODIFF_testatexit := 1 +DODIFF_teston_exit := 1 +DODIFF_teststrtol := 1 diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/stdlib/ptytest.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/stdlib/ptytest.c new file mode 100644 index 00000000..a7956388 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/stdlib/ptytest.c @@ -0,0 +1,20 @@ +#define _XOPEN_SOURCE +#include +#include +#include +#include +#include + +int main(int argc, char **argv) +{ + int fd; + char *cp; + + fd=open("/dev/ptmx",O_NOCTTY|O_RDWR); + cp=ptsname(fd); + if (cp==NULL) + return EXIT_FAILURE; + printf("ptsname %s\n",cp); + return EXIT_SUCCESS; +} + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/stdlib/qsort.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/stdlib/qsort.c new file mode 100644 index 00000000..74f93315 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/stdlib/qsort.c @@ -0,0 +1,53 @@ +#include +#include +#include +#include + +static int select_files(const struct dirent *dirbuf) +{ + if (dirbuf->d_name[0] == '.') + return 0; + else + return 1; +} + +int main(void) +{ + struct dirent **array; + struct dirent *dirbuf; + + int i, numdir; + + chdir("/"); + numdir = scandir(".", &array, select_files, NULL); + printf("\nGot %d entries from scandir().\n", numdir); + for (i = 0; i < numdir; ++i) { + dirbuf = array[i]; + printf("[%d] %s\n", i, dirbuf->d_name); + free(array[i]); + } + free(array); + numdir = scandir(".", &array, select_files, alphasort); + printf("\nGot %d entries from scandir() using alphasort().\n", numdir); + for (i = 0; i < numdir; ++i) { + dirbuf = array[i]; + printf("[%d] %s\n", i, dirbuf->d_name); + } + printf("\nCalling qsort()\n"); + /* Even though some manpages say that alphasort should be + * int alphasort(const void *a, const void *b), + * in reality glibc and uclibc have const struct dirent** + * instead of const void*. + * Therefore we get a warning here unless we use a cast, + * which makes people think that alphasort prototype + * needs to be fixed in uclibc headers. + */ + qsort(array, numdir, sizeof(struct dirent *), (void*) alphasort); + for (i = 0; i < numdir; ++i) { + dirbuf = array[i]; + printf("[%d] %s\n", i, dirbuf->d_name); + free(array[i]); + } + free(array); + return (0); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/stdlib/test-canon.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/stdlib/test-canon.c new file mode 100644 index 00000000..788754f4 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/stdlib/test-canon.c @@ -0,0 +1,251 @@ +/* Test program for returning the canonical absolute name of a given file. + Copyright (C) 1996,1997,2000,2002,2004,2005,2006 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by David Mosberger . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* This file must be run from within a directory called "stdlib". */ + +#include +#include +#include +#include +#include +#include +#include + +/* Prototype for our test function. */ +extern int do_test (int argc, char *argv[]); +#include "../test-skeleton.c" + +#ifndef PATH_MAX +# define PATH_MAX 4096 +#endif +static char cwd[PATH_MAX]; +static size_t cwd_len; + +struct { + const char * name; + const char * value; +} symlinks[] = { + {"SYMLINK_LOOP", "SYMLINK_LOOP"}, + {"SYMLINK_1", "."}, + {"SYMLINK_2", "//////./../../etc"}, + {"SYMLINK_3", "SYMLINK_1"}, + {"SYMLINK_4", "SYMLINK_2"}, + {"SYMLINK_5", "doesNotExist"}, +}; + +struct { + const char * in; + const char * retval; /* what realpath should return */ + const char * retbuf; /* what realpath should store in buf */ + /* if both of the above are NULL, we won't check for result, + * it's undefined */ + int error; /* expected errno value */ +} tests[] = { + /* 0 */ + {"/", "/"}, + {"/////////////////////////////////", "/"}, + {"/.././.././.././..///", "/"}, + {"/etc", "/etc"}, + {"/etc/../etc", "/etc"}, + /* 5 */ + {"/doesNotExist/../etc", 0, "/doesNotExist", ENOENT}, + {"./././././././././.", "."}, + {"/etc/.//doesNotExist", 0, "/etc/doesNotExist", ENOENT}, + {"./doesExist", "./doesExist"}, + {"./doesExist/", "./doesExist"}, + /* 10 */ + {"./doesExist/../doesExist", "./doesExist"}, + {"foobar", 0, "./foobar", ENOENT}, + {".", "."}, + {"./foobar", 0, "./foobar", ENOENT}, + {"SYMLINK_LOOP", 0, 0, ELOOP}, + /* 15 */ + {"./SYMLINK_LOOP", 0, 0, ELOOP}, + {"SYMLINK_1", "."}, + {"SYMLINK_1/foobar", 0, "./foobar", ENOENT}, + {"SYMLINK_2", "/etc"}, + {"SYMLINK_3", "."}, + /* 20 */ + {"SYMLINK_4", "/etc"}, + {"../stdlib/SYMLINK_1", "."}, + {"../stdlib/SYMLINK_2", "/etc"}, + {"../stdlib/SYMLINK_3", "."}, + {"../stdlib/SYMLINK_4", "/etc"}, + /* 25 */ + {"./SYMLINK_5", 0, "./doesNotExist", ENOENT}, + {"SYMLINK_5", 0, "./doesNotExist", ENOENT}, + {"SYMLINK_5/foobar", 0, "./doesNotExist", ENOENT}, + {"doesExist/../../stdlib/doesExist", "./doesExist"}, + {"doesExist/.././../stdlib/.", "."}, +#ifndef __UCLIBC__ + /* we dont check for ENOTDIR in readlink() which causes failures to + * propogate up to realpath() ... so disable for now ... */ + /* 30 */ + {"./doesExist/someFile/", 0, "./doesExist/someFile", ENOTDIR}, + {"./doesExist/someFile/..", 0, "./doesExist/someFile", ENOTDIR}, +#endif +}; + + +static int +check_path (const char * result, const char * expected) +{ + int good; + + if (!result) + return (expected == NULL); + + if (!expected) + return 0; + + if (expected[0] == '.' && (expected[1] == '/' || expected[1] == '\0')) + good = (strncmp (result, cwd, cwd_len) == 0 + && strcmp (result + cwd_len, expected + 1) == 0); + else + good = (strcmp (expected, result) == 0); + + return good; +} + + +int +do_test (int argc, char ** argv) +{ + char * result; + int i, errors = 0; + char buf[PATH_MAX]; + + getcwd (cwd, sizeof(buf)); + cwd_len = strlen (cwd); + +#ifndef __UCLIBC__ + /* we choose to crash in uClibc when given a NULL */ + errno = 0; + if (realpath (NULL, buf) != NULL || errno != EINVAL) + { + printf ("%s: expected return value NULL and errno set to EINVAL" + " for realpath(NULL,...)\n", argv[0]); + ++errors; + } +#endif + +#if 0 + /* This is now allowed. The test is invalid. */ + errno = 0; + if (realpath ("/", NULL) != NULL || errno != EINVAL) + { + printf ("%s: expected return value NULL and errno set to EINVAL" + " for realpath(...,NULL)\n", argv[0]); + ++errors; + } +#endif + + errno = 0; + if (realpath ("", buf) != NULL || errno != ENOENT) + { + printf ("%s: expected return value NULL and set errno to ENOENT" + " for realpath(\"\",...)\n", argv[0]); + ++errors; + } + + for (i = 0; i < (int) (sizeof (symlinks) / sizeof (symlinks[0])); ++i) + symlink (symlinks[i].value, symlinks[i].name); + + int has_dir = mkdir ("doesExist", 0777) == 0; + + int fd = has_dir ? creat ("doesExist/someFile", 0777) : -1; + + for (i = 0; i < (int) (sizeof (tests) / sizeof (tests[0])); ++i) + { + buf[0] = '\0'; + errno = 0; + result = realpath (tests[i].in, buf); + + if (!check_path (result, tests[i].retval)) + { + printf ("%s: flunked test %d (expected `%s', got `%s')\n", + argv[0], i, tests[i].retval ? tests[i].retval : "NULL", + result ? result : "NULL"); + ++errors; + continue; + } + + if (result && !check_path (buf, tests[i].retval ? tests[i].retval : tests[i].retbuf)) + { + printf ("%s: flunked test %d (expected resolved `%s', got `%s')\n", + argv[0], i, tests[i].retval ? tests[i].retval : tests[i].retbuf, + buf); + ++errors; + continue; + } + + if (errno != tests[i].error) + { + printf ("%s: flunked test %d (expected errno %d, got %d)\n", + argv[0], i, tests[i].error, errno); + ++errors; + continue; + } + +#ifndef __UCLIBC__ + /* we choose to crash in uClibc when given a NULL */ + char *result2 = realpath (tests[i].in, NULL); + if ((result2 == NULL && result != NULL) + || (result2 != NULL && strcmp (result, result2) != 0)) + { + printf ("\ +%s: realpath(..., NULL) produced different result than realpath(..., buf): '%s' vs '%s'\n", + argv[0], result2, result); + ++errors; + } + free (result2); +#endif + } + + getcwd (buf, sizeof(buf)); + if (strcmp (buf, cwd)) + { + printf ("%s: current working directory changed from %s to %s\n", + argv[0], cwd, buf); + ++errors; + } + + if (fd >= 0) + { + close (fd); + unlink ("doesExist/someFile"); + } + + if (has_dir) + rmdir ("doesExist"); + + for (i = 0; i < (int) (sizeof (symlinks) / sizeof (symlinks[0])); ++i) + unlink (symlinks[i].name); + + if (errors != 0) + { + printf ("%d errors.\n", errors); + return EXIT_FAILURE; + } + + puts ("No errors."); + return EXIT_SUCCESS; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/stdlib/test-canon2.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/stdlib/test-canon2.c new file mode 100644 index 00000000..f182e95a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/stdlib/test-canon2.c @@ -0,0 +1,75 @@ +/* Test for realpath/canonicalize function. + Copyright (C) 1998 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + + +/* Prototype for our test function. */ +extern void do_prepare (int argc, char *argv[]); +extern int do_test (int argc, char *argv[]); + +/* We have a preparation function. */ +#define PREPARE do_prepare + +#include + +/* Name of the temporary files we create. */ +char *name1; +char *name2; + +/* Preparation. */ +void +do_prepare (int argc, char *argv[]) +{ + size_t test_dir_len; + + test_dir_len = strlen (test_dir); + + /* Generate the circular symlinks. */ + name1 = malloc (test_dir_len + sizeof ("/canonXXXXXX")); + mempcpy (mempcpy (name1, test_dir, test_dir_len), + "/canonXXXXXX", sizeof ("/canonXXXXXX")); + name2 = strdup (name1); + + add_temp_file (mktemp (name1)); + add_temp_file (mktemp (name2)); +} + + +/* Run the test. */ +int +do_test (int argc, char *argv[]) +{ + char *canon; + + printf ("create symlinks from %s to %s and vice versa\n", name1, name2); + if (symlink (name1, name2) == -1 + || symlink (name2, name1) == -1) + /* We cannot test this. */ + return 0; + + /* Call the function. This is equivalent the using `realpath' but the + function allocates the room for the result. */ + errno = 0; + canon = canonicalize_file_name (name1); + + return canon != NULL || errno != ELOOP; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/stdlib/testatexit.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/stdlib/testatexit.c new file mode 100644 index 00000000..01874fdd --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/stdlib/testatexit.c @@ -0,0 +1,81 @@ +/* + * This test program will register the maximum number of exit functions + * with atexit(). When this program exits, each exit function should get + * called in the reverse order in which it was registered. (If the system + * supports more than 25 exit functions, the function names will loop, but + * the effect will be the same. Feel free to add more functions if desired) + */ +#include +#include + +typedef void (*vfuncp) (void); + +/* All functions call exit(), in order to test that exit functions can call + * exit() without screwing everything up. :) + */ +#define make_exitfunc(num) \ +__attribute__ ((__noreturn__)) static \ +void exitfunc##num(void) \ +{ \ + printf("Executing exitfunc"#num".\n"); \ + exit(0); \ +} +make_exitfunc(0) +make_exitfunc(1) +make_exitfunc(2) +make_exitfunc(3) +make_exitfunc(4) +make_exitfunc(5) +make_exitfunc(6) +make_exitfunc(7) +make_exitfunc(8) +make_exitfunc(9) +make_exitfunc(10) +make_exitfunc(11) +make_exitfunc(12) +make_exitfunc(13) +make_exitfunc(14) +make_exitfunc(15) +make_exitfunc(16) +make_exitfunc(17) +make_exitfunc(18) +make_exitfunc(19) +make_exitfunc(20) +make_exitfunc(21) +make_exitfunc(22) +make_exitfunc(23) +make_exitfunc(24) + +static vfuncp func_table[] = + { + exitfunc0, exitfunc1, exitfunc2, exitfunc3, exitfunc4, + exitfunc5, exitfunc6, exitfunc7, exitfunc8, exitfunc9, + exitfunc10, exitfunc11, exitfunc12, exitfunc13, exitfunc14, + exitfunc15, exitfunc16, exitfunc17, exitfunc18, exitfunc19, + exitfunc20, exitfunc21, exitfunc22, exitfunc23, exitfunc24 + }; + +/* glibc dynamically adds exit functions, so it will keep adding until + * it runs out of memory! So this will limit the number of exit functions + * we add in the loop below. uClibc has a set limit (currently 20), so the + * loop will go until it can't add any more (so it should not hit this limit). + */ +#define ATEXIT_LIMIT 20 + +int +main ( void ) +{ + int i = 0; + int count = 0; + int numfuncs = sizeof(func_table)/sizeof(vfuncp); + + /* loop until no more can be added */ + while(count < ATEXIT_LIMIT && atexit(func_table[i]) >= 0) { + printf("Registered exitfunc%d with atexit()\n", i); + count++; + i = (i+1) % numfuncs; + } + printf("%d functions registered with atexit.\n", count); + + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/stdlib/teston_exit.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/stdlib/teston_exit.c new file mode 100644 index 00000000..f7e8fd00 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/stdlib/teston_exit.c @@ -0,0 +1,82 @@ +/* + * This test program will register the maximum number of exit functions + * with on_exit(). When this program exits, each exit function should get + * called in the reverse order in which it was registered. (If the system + * supports more than 25 exit functions, the function names will loop, but + * the effect will be the same. Feel free to add more functions if desired) + */ +#include +#include + +typedef void (*efuncp) (int, void *); + +/* All functions call exit(), in order to test that exit functions can call + * exit() without screwing everything up. The value passed in through arg gets + * used as the next exit status. + */ +#define make_exitfunc(num) \ +__attribute__ ((__noreturn__)) static \ +void exitfunc##num(int status, void *arg) \ +{ \ + printf("Executing exitfunc"#num" (status=%d, arg=%lu)\n", status, (unsigned long)arg); \ + exit((unsigned long)arg); \ +} +make_exitfunc(0) +make_exitfunc(1) +make_exitfunc(2) +make_exitfunc(3) +make_exitfunc(4) +make_exitfunc(5) +make_exitfunc(6) +make_exitfunc(7) +make_exitfunc(8) +make_exitfunc(9) +make_exitfunc(10) +make_exitfunc(11) +make_exitfunc(12) +make_exitfunc(13) +make_exitfunc(14) +make_exitfunc(15) +make_exitfunc(16) +make_exitfunc(17) +make_exitfunc(18) +make_exitfunc(19) +make_exitfunc(20) +make_exitfunc(21) +make_exitfunc(22) +make_exitfunc(23) +make_exitfunc(24) + +static efuncp func_table[] = + { + exitfunc0, exitfunc1, exitfunc2, exitfunc3, exitfunc4, + exitfunc5, exitfunc6, exitfunc7, exitfunc8, exitfunc9, + exitfunc10, exitfunc11, exitfunc12, exitfunc13, exitfunc14, + exitfunc15, exitfunc16, exitfunc17, exitfunc18, exitfunc19, + exitfunc20, exitfunc21, exitfunc22, exitfunc23, exitfunc24 + }; + +/* glibc dynamically adds exit functions, so it will keep adding until + * it runs out of memory! So this will limit the number of exit functions + * we add in the loop below. uClibc has a set limit (currently 20), so the + * loop will go until it can't add any more (so it should not hit this limit). + */ +#define ON_EXIT_LIMIT 20 + +int +main ( void ) +{ + int i = 0; + unsigned long count = 0; + int numfuncs = sizeof(func_table)/sizeof(efuncp); + + /* loop until no more can be added */ + while(count < ON_EXIT_LIMIT && on_exit(func_table[i], (void *)count) >= 0) { + count++; + printf("Registered exitfunc%d with on_exit()\n", i); + i = (i+1) % numfuncs; + } + printf("%lu functions registered with on_exit.\n", count); + exit(count); +} + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/stdlib/teststrtol.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/stdlib/teststrtol.c new file mode 100644 index 00000000..5b43a9b0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/stdlib/teststrtol.c @@ -0,0 +1,109 @@ + +#include +#include + + +const char *strings[]={ + /* some simple stuff */ + "0", "1", "10", + "100", "1000", "10000", "100000", "1000000", + "10000000", "100000000", "1000000000", + + /* negative */ + "-0", "-1", "-10", + "-100", "-1000", "-10000", "-100000", "-1000000", + "-10000000", "-100000000", "-1000000000", + + /* test base>10 */ + "a", "b", "f", "g", "z", + + /* test hex */ + "0x0", "0x1", "0xa", "0xf", "0x10", + + /* test octal */ + "00", "01", "07", "08", "0a", "010", + + /* other */ + "0x8000000", + + /* check overflow cases: (for 32 bit) */ + "2147483645", + "2147483646", + "2147483647", + "2147483648", + "2147483649", + "-2147483645", + "-2147483646", + "-2147483647", + "-2147483648", + "-2147483649", + "4294967293", + "4294967294", + "4294967295", + "4294967296", + "4294967297", + "-4294967293", + "-4294967294", + "-4294967295", + "-4294967296", + "-4294967297", + + /* bad input tests */ + "", + "00", + "0x", + "0x0", + "-", + "+", + " ", + " -", + " - 0", +}; +int n_tests=sizeof(strings)/sizeof(strings[0]); + +void do_test(int base); +void do_utest(int base); + +int main(int argc,char *argv[]) +{ + do_test(0); + do_test(8); + do_test(10); + do_test(16); + do_test(36); + + do_utest(0); + do_utest(8); + do_utest(10); + do_utest(16); + do_utest(36); + + return 0; +} + +void do_test(int base) +{ + int i; + long n; + char *endptr; + + for(i=0;i +#include + + +const char *strings[]={ + /* some simple stuff */ + "0", "1", "10", + "100", "1000", "10000", "100000", "1000000", + "10000000", "100000000", "1000000000", + + /* negative */ + "-0", "-1", "-10", + "-100", "-1000", "-10000", "-100000", "-1000000", + "-10000000", "-100000000", "-1000000000", + + /* test base>10 */ + "a", "b", "f", "g", "z", + + /* test hex */ + "0x0", "0x1", "0xa", "0xf", "0x10", + + /* test octal */ + "00", "01", "07", "08", "0a", "010", + + /* other */ + "0x8000000", + + /* check overflow cases: (for 32 bit) */ + "2147483645", + "2147483646", + "2147483647", + "2147483648", + "2147483649", + "-2147483645", + "-2147483646", + "-2147483647", + "-2147483648", + "-2147483649", + "4294967293", + "4294967294", + "4294967295", + "4294967296", + "4294967297", + "-4294967293", + "-4294967294", + "-4294967295", + "-4294967296", + "-4294967297", + + /* bad input tests */ + "", + "00", + "0x", + "0x0", + "-", + "+", + " ", + " -", + " - 0", +}; +int n_tests=sizeof(strings)/sizeof(strings[0]); + + + +void do_test(int base); +void do_test(int base) +{ + int i; + quad_t n; + char *endptr; + + for(i=0;i +#include +#include + +int +main (void) +{ + const char t1[] = "0-0-0-0-0-0-0-0-0-0.COM"; + const char t2[] = "00000-00000.COM"; + int res1; + int res2; + + setlocale (LC_ALL, "en_US.ISO-8859-1"); + + res1 = strcoll (t1, t2); + printf ("strcoll (\"%s\", \"%s\") = %d\n", t1, t2, res1); + res2 = strcoll (t2, t1); + printf ("strcoll (\"%s\", \"%s\") = %d\n", t2, t1, res2); + + return ((res1 == 0 && res2 != 0) + || (res1 != 0 && res2 == 0) + || (res1 < 0 && res2 < 0) + || (res1 > 0 && res2 > 0)); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/string/bug-strncat1.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/string/bug-strncat1.c new file mode 100644 index 00000000..f1b5c37c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/string/bug-strncat1.c @@ -0,0 +1,31 @@ +/* Test case by Joseph S. Myers . */ +#undef __USE_STRING_INLINES +#define __USE_STRING_INLINES +#include +#include +#include + +char d[3] = "\0\1\2"; + +int +main (void) +{ + strncat (d, "\5\6", 1); + if (d[0] != '\5') + { + puts ("d[0] != '\\5'"); + exit (1); + } + if (d[1] != '\0') + { + puts ("d[1] != '\\0'"); + exit (1); + } + if (d[2] != '\2') + { + puts ("d[2] != '\\2'"); + exit (1); + } + + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/string/bug-strpbrk1.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/string/bug-strpbrk1.c new file mode 100644 index 00000000..28238b0f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/string/bug-strpbrk1.c @@ -0,0 +1,19 @@ +/* Test case by Joseph S. Myers . */ +#undef __USE_STRING_INLINES +#define __USE_STRING_INLINES +#include +#include +#include + +int +main (void) +{ + const char *a = "abc"; + const char *b = a; + + strpbrk (b++, ""); + if (b != a + 1) + return 1; + + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/string/bug-strspn1.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/string/bug-strspn1.c new file mode 100644 index 00000000..a657bafc --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/string/bug-strspn1.c @@ -0,0 +1,19 @@ +/* Test case by Joseph S. Myers . */ +#undef __USE_STRING_INLINES +#define __USE_STRING_INLINES +#include +#include +#include + +int +main (void) +{ + const char *a = "abc"; + const char *b = a; + + strspn (b++, ""); + if (b != a + 1) + return 1; + + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/string/stratcliff.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/string/stratcliff.c new file mode 100644 index 00000000..41e77468 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/string/stratcliff.c @@ -0,0 +1,349 @@ +/* Test for string function add boundaries of usable memory. + Copyright (C) 1996,1997,1999-2002,2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1996. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define _GNU_SOURCE 1 + +/* Make sure we don't test the optimized inline functions if we want to + test the real implementation. */ +#undef __USE_STRING_INLINES + +#include +#include +#include +#include +#include +#include + +#ifndef MAX +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#endif + +int +main (int argc, char *argv[]) +{ + int size = sysconf (_SC_PAGESIZE); + char *adr, *dest; + int result = 0; + + adr = (char *) mmap (NULL, 3 * size, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANON, -1, 0); + dest = (char *) mmap (NULL, 3 * size, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANON, -1, 0); + if (adr == MAP_FAILED || dest == MAP_FAILED) + { + if (errno == ENOSYS) + puts ("No test, mmap not available."); + else + { + printf ("mmap failed: %s", strerror(errno)); + result = 1; + } + } + else + { + int inner, middle, outer; + + mprotect(adr, size, PROT_NONE); + mprotect(adr + 2 * size, size, PROT_NONE); + adr += size; + + mprotect(dest, size, PROT_NONE); + mprotect(dest + 2 * size, size, PROT_NONE); + dest += size; + + memset (adr, 'T', size); + + /* strlen test */ + for (outer = size - 1; outer >= MAX (0, size - 128); --outer) + { + for (inner = MAX (outer, size - 64); inner < size; ++inner) + { + adr[inner] = '\0'; + + if (strlen (&adr[outer]) != (size_t) (inner - outer)) + { + printf ("strlen flunked for outer = %d, inner = %d\n", + outer, inner); + result = 1; + } + + adr[inner] = 'T'; + } + } + + /* strchr test */ + for (outer = size - 1; outer >= MAX (0, size - 128); --outer) + { + for (middle = MAX (outer, size - 64); middle < size; ++middle) + { + for (inner = middle; inner < size; ++inner) + { + char *cp; + adr[middle] = 'V'; + adr[inner] = '\0'; + + cp = strchr (&adr[outer], 'V'); + + if ((inner == middle && cp != NULL) + || (inner != middle + && (cp - &adr[outer]) != middle - outer)) + { + printf ("strchr flunked for outer = %d, middle = %d, " + "inner = %d\n", outer, middle, inner); + result = 1; + } + + adr[inner] = 'T'; + adr[middle] = 'T'; + } + } + } + + /* Special test. */ + adr[size - 1] = '\0'; + if (strchr (&adr[size - 1], '\n') != NULL) + { + puts ("strchr flunked for test of empty string at end of page"); + result = 1; + } + + /* strrchr test */ + for (outer = size - 1; outer >= MAX (0, size - 128); --outer) + { + for (middle = MAX (outer, size - 64); middle < size; ++middle) + { + for (inner = middle; inner < size; ++inner) + { + char *cp; + adr[middle] = 'V'; + adr[inner] = '\0'; + + cp = strrchr (&adr[outer], 'V'); + + if ((inner == middle && cp != NULL) + || (inner != middle + && (cp - &adr[outer]) != middle - outer)) + { + printf ("strrchr flunked for outer = %d, middle = %d, " + "inner = %d\n", outer, middle, inner); + result = 1; + } + + adr[inner] = 'T'; + adr[middle] = 'T'; + } + } + } + + /* rawmemchr test */ + for (outer = size - 1; outer >= MAX (0, size - 128); --outer) + { + for (middle = MAX (outer, size - 64); middle < size; ++middle) + { + char *cp; + adr[middle] = 'V'; + + cp = rawmemchr (&adr[outer], 'V'); + + if (cp - &adr[outer] != middle - outer) + { + printf ("rawmemchr flunked for outer = %d, middle = %d\n", + outer, middle); + result = 1; + } + + adr[middle] = 'T'; + } + } + + /* strcpy test */ + for (outer = size - 1; outer >= MAX (0, size - 128); --outer) + { + for (inner = MAX (outer, size - 64); inner < size; ++inner) + { + adr[inner] = '\0'; + + if (strcpy (dest, &adr[outer]) != dest + || strlen (dest) != (size_t) (inner - outer)) + { + printf ("strcpy flunked for outer = %d, inner = %d\n", + outer, inner); + result = 1; + } + + adr[inner] = 'T'; + } + } + + /* strncpy tests */ + adr[size-1] = 'T'; + for (outer = size - 1; outer >= MAX (0, size - 128); --outer) + { + size_t len; + + for (len = 0; len < size - outer; ++len) + { + if (strncpy (dest, &adr[outer], len) != dest + || memcmp (dest, &adr[outer], len) != 0) + { + printf ("outer strncpy flunked for outer = %d, len = %Zd\n", + outer, len); + result = 1; + } + } + } + adr[size-1] = '\0'; + + for (outer = size - 1; outer >= MAX (0, size - 128); --outer) + { + for (inner = MAX (outer, size - 64); inner < size; ++inner) + { + size_t len; + + adr[inner] = '\0'; + + for (len = 0; len < size - outer + 64; ++len) + { + if (strncpy (dest, &adr[outer], len) != dest + || memcmp (dest, &adr[outer], + MIN (inner - outer, len)) != 0 + || (inner - outer < len + && strlen (dest) != (inner - outer))) + { + printf ("strncpy flunked for outer = %d, inner = %d, len = %Zd\n", + outer, inner, len); + result = 1; + } + if (strncpy (dest + 1, &adr[outer], len) != dest + 1 + || memcmp (dest + 1, &adr[outer], + MIN (inner - outer, len)) != 0 + || (inner - outer < len + && strlen (dest + 1) != (inner - outer))) + { + printf ("strncpy+1 flunked for outer = %d, inner = %d, len = %Zd\n", + outer, inner, len); + result = 1; + } + } + + adr[inner] = 'T'; + } + } + + /* stpcpy test */ + for (outer = size - 1; outer >= MAX (0, size - 128); --outer) + { + for (inner = MAX (outer, size - 64); inner < size; ++inner) + { + adr[inner] = '\0'; + + if ((stpcpy (dest, &adr[outer]) - dest) != inner - outer) + { + printf ("stpcpy flunked for outer = %d, inner = %d\n", + outer, inner); + result = 1; + } + + adr[inner] = 'T'; + } + } + + /* stpncpy test */ + for (outer = size - 1; outer >= MAX (0, size - 128); --outer) + { + for (middle = MAX (outer, size - 64); middle < size; ++middle) + { + adr[middle] = '\0'; + + for (inner = 0; inner < size - outer; ++ inner) + { + if ((stpncpy (dest, &adr[outer], inner) - dest) + != MIN (inner, middle - outer)) + { + printf ("stpncpy flunked for outer = %d, middle = %d, " + "inner = %d\n", outer, middle, inner); + result = 1; + } + } + + adr[middle] = 'T'; + } + } + + /* memcpy test */ + for (outer = size - 1; outer >= MAX (0, size - 128); --outer) + for (inner = 0; inner < size - outer; ++inner) + if (memcpy (dest, &adr[outer], inner) != dest) + { + printf ("memcpy flunked for outer = %d, inner = %d\n", + outer, inner); + result = 1; + } + + /* mempcpy test */ + for (outer = size - 1; outer >= MAX (0, size - 128); --outer) + for (inner = 0; inner < size - outer; ++inner) + if (mempcpy (dest, &adr[outer], inner) != dest + inner) + { + printf ("mempcpy flunked for outer = %d, inner = %d\n", + outer, inner); + result = 1; + } + + /* memccpy test */ + memset (adr, '\0', size); + for (outer = size - 1; outer >= MAX (0, size - 128); --outer) + for (inner = 0; inner < size - outer; ++inner) + if (memccpy (dest, &adr[outer], '\1', inner) != NULL) + { + printf ("memccpy flunked full copy for outer = %d, inner = %d\n", + outer, inner); + result = 1; + } + for (outer = size - 1; outer >= MAX (0, size - 128); --outer) + for (middle = 0; middle < size - outer; ++middle) + { + memset (dest, '\2', middle + 1); + for (inner = 0; inner < middle; ++inner) + { + adr[outer + inner] = '\1'; + + if (memccpy (dest, &adr[outer], '\1', middle + 128) + != dest + inner + 1) + { + printf ("\ +memccpy flunked partial copy for outer = %d, middle = %d, inner = %d\n", + outer, middle, inner); + result = 1; + } + else if (dest[inner + 1] != '\2') + { + printf ("\ +memccpy copied too much for outer = %d, middle = %d, inner = %d\n", + outer, middle, inner); + result = 1; + } + adr[outer + inner] = '\0'; + } + } + } + + return result; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/string/test-ffs.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/string/test-ffs.c new file mode 100644 index 00000000..86e11758 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/string/test-ffs.c @@ -0,0 +1,66 @@ +/* Copyright (C) 1994, 1997, 2000, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Joel Sherrill (jsherril@redstone-emh2.army.mil), + On-Line Applications Research Corporation. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +int +main (void) +{ + int failures = 0; + int i; + + auto void try (const char *name, long long int param, int value, + int expected); + + void try (const char *name, long long int param, int value, int expected) + { + if (value != expected) + { + printf ("%s(%#llx) expected %d got %d\n", + name, param, expected, value); + ++failures; + } + else + printf ("%s(%#llx) as expected %d\n", name, param, value); + } + +#define TEST(fct, type) \ + try (#fct, 0, fct ((type) 0), 0); \ + for (i=0 ; i < 8 * sizeof (type); i++) \ + try (#fct, 1ll << i, fct (((type) 1) << i), i + 1); \ + for (i=0 ; i < 8 * sizeof (type) ; i++) \ + try (#fct, (~((type) 0) >> i) << i, fct ((~((type) 0) >> i) << i), i + 1);\ + try (#fct, 0x80008000, fct ((type) 0x80008000), 16) + + TEST (ffs, int); +/* Not implemented in uClibc (yet?) + TEST (ffsl, long int); + TEST (ffsll, long long int); +*/ + + if (failures) + printf ("Test FAILED! %d failure%s.\n", failures, &"s"[failures == 1]); + else + puts ("Test succeeded."); + + return failures; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/string/testcopy.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/string/testcopy.c new file mode 100644 index 00000000..60039f79 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/string/testcopy.c @@ -0,0 +1,108 @@ +/* Copyright (C) 1990, 1991, 1992, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Torbjorn Granlund (tege@sics.se). + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + +int +main (void) +{ + char *mem, *memp; + char *rand_mem; + char *lo_around, *hi_around; + int size, max_size; + int src_off, dst_off; + int i; + int space_around = 10; + + max_size = 256; + + mem = malloc (max_size + 2 * max_size + 2 * space_around); + rand_mem = malloc (max_size); + lo_around = malloc (space_around); + hi_around = malloc (space_around); + memp = mem + space_around; + + /* Fill RAND_MEM with random bytes, each non-zero. */ + for (i = 0; i < max_size; i++) + { + int x; + do + x = random (); + while (x == 0); + rand_mem[i] = x; + } + + for (size = 0; size < max_size; size++) + { + printf("phase %d\n", size); + for (src_off = 0; src_off <= 16; src_off++) + { + for (dst_off = 0; dst_off <= 16; dst_off++) + { + /* Put zero around the intended destination, to check + that it's not clobbered. */ + for (i = 1; i < space_around; i++) + { + memp[dst_off - i] = 0; + memp[dst_off + size - 1 + i] = 0; + } + + /* Fill the source area with known contents. */ + for (i = 0; i < size; i++) + memp[src_off + i] = rand_mem[i]; + + /* Remember the contents around the destination area. + (It might not be what we wrote some lines above, since + the src area and the dst area overlap.) */ + for (i = 1; i < space_around; i++) + { + lo_around[i] = memp[dst_off - i]; + hi_around[i] = memp[dst_off + size - 1 + i]; + } + + memmove (memp + dst_off, memp + src_off, size); + + /* Check that the destination area has the same + contents we wrote to the source area. */ + for (i = 0; i < size; i++) + { + if (memp[dst_off + i] != rand_mem[i]) + abort (); + } + + /* Check that the area around the destination is not + clobbered. */ + for (i = 1; i < space_around; i++) + { + if (memp[dst_off - i] != lo_around[i]) + abort (); + if (memp[dst_off + size - 1 + i] != hi_around[i]) + abort (); + } + } + } + } + + puts ("Test succeeded."); + + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/string/tester.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/string/tester.c new file mode 100644 index 00000000..7c8d314d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/string/tester.c @@ -0,0 +1,1647 @@ +/* Tester for string functions. + Copyright (C) 1995-2001, 2003, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif + +/* Make sure we don't test the optimized inline functions if we want to + test the real implementation. */ +#if !defined DO_STRING_INLINES +#undef __USE_STRING_INLINES +#endif + +#include +#include +#include +#include +#include +#include + +#ifdef __UCLIBC__ +# define __TEST_BSD_FUNCS__ +#else +# undef __TEST_BSD_FUNCS__ +#endif + +#if defined(__UCLIBC_SUSV3_LEGACY__) || defined(__UCLIBC_SUSV3_LEGACY_MACROS__) +# define __TEST_SUSV3_LEGACY__ +#else +# undef __TEST_SUSV3_LEGACY__ +#endif + +#define STREQ(a, b) (strcmp((a), (b)) == 0) + +const char *it = ""; /* Routine name for message routines. */ +size_t errors = 0; + +/* Complain if condition is not true. */ +static void +check (int thing, int number) +{ + if (!thing) + { + printf("%s flunked test %d\n", it, number); + ++errors; + } +} + +/* Complain if first two args don't strcmp as equal. */ +static void +equal (const char *a, const char *b, int number) +{ + check(a != NULL && b != NULL && STREQ (a, b), number); +} + +char one[50]; +char two[50]; +char *cp; + +static void +test_strcmp (void) +{ + it = "strcmp"; + check (strcmp ("", "") == 0, 1); /* Trivial case. */ + check (strcmp ("a", "a") == 0, 2); /* Identity. */ + check (strcmp ("abc", "abc") == 0, 3); /* Multicharacter. */ + check (strcmp ("abc", "abcd") < 0, 4); /* Length mismatches. */ + check (strcmp ("abcd", "abc") > 0, 5); + check (strcmp ("abcd", "abce") < 0, 6); /* Honest miscompares. */ + check (strcmp ("abce", "abcd") > 0, 7); + check (strcmp ("a\203", "a") > 0, 8); /* Tricky if char signed. */ + check (strcmp ("a\203", "a\003") > 0, 9); + + { + char buf1[0x40], buf2[0x40]; + int i, j; + for (i=0; i < 0x10; i++) + for (j = 0; j < 0x10; j++) + { + int k; + for (k = 0; k < 0x3f; k++) + { + buf1[k] = '0' ^ (k & 4); + buf2[k] = '4' ^ (k & 4); + } + buf1[i] = buf1[0x3f] = 0; + buf2[j] = buf2[0x3f] = 0; + for (k = 0; k < 0xf; k++) + { + int cnum = 0x10+0x10*k+0x100*j+0x1000*i; + check (strcmp (buf1+i,buf2+j) == 0, cnum); + buf1[i+k] = 'A' + i + k; + buf1[i+k+1] = 0; + check (strcmp (buf1+i,buf2+j) > 0, cnum+1); + check (strcmp (buf2+j,buf1+i) < 0, cnum+2); + buf2[j+k] = 'B' + i + k; + buf2[j+k+1] = 0; + check (strcmp (buf1+i,buf2+j) < 0, cnum+3); + check (strcmp (buf2+j,buf1+i) > 0, cnum+4); + buf2[j+k] = 'A' + i + k; + buf1[i] = 'A' + i + 0x80; + check (strcmp (buf1+i,buf2+j) > 0, cnum+5); + check (strcmp (buf2+j,buf1+i) < 0, cnum+6); + buf1[i] = 'A' + i; + } + } + } +} + +#define SIMPLE_COPY(fn, n, str, ntest) \ + do { \ + int __n; \ + char *cp; \ + for (__n = 0; __n < (int) sizeof (one); ++__n) \ + one[__n] = 'Z'; \ + fn (one, str); \ + for (cp = one, __n = 0; __n < n; ++__n, ++cp) \ + check (*cp == '0' + (n % 10), ntest); \ + check (*cp == '\0', ntest); \ + } while (0) + +static void +test_strcpy (void) +{ + int i; + it = "strcpy"; + check (strcpy (one, "abcd") == one, 1); /* Returned value. */ + equal (one, "abcd", 2); /* Basic test. */ + + (void) strcpy (one, "x"); + equal (one, "x", 3); /* Writeover. */ + equal (one+2, "cd", 4); /* Wrote too much? */ + + (void) strcpy (two, "hi there"); + (void) strcpy (one, two); + equal (one, "hi there", 5); /* Basic test encore. */ + equal (two, "hi there", 6); /* Stomped on source? */ + + (void) strcpy (one, ""); + equal (one, "", 7); /* Boundary condition. */ + + for (i = 0; i < 16; i++) + { + (void) strcpy (one + i, "hi there"); /* Unaligned destination. */ + equal (one + i, "hi there", 8 + (i * 2)); + (void) strcpy (two, one + i); /* Unaligned source. */ + equal (two, "hi there", 9 + (i * 2)); + } + + SIMPLE_COPY(strcpy, 0, "", 41); + SIMPLE_COPY(strcpy, 1, "1", 42); + SIMPLE_COPY(strcpy, 2, "22", 43); + SIMPLE_COPY(strcpy, 3, "333", 44); + SIMPLE_COPY(strcpy, 4, "4444", 45); + SIMPLE_COPY(strcpy, 5, "55555", 46); + SIMPLE_COPY(strcpy, 6, "666666", 47); + SIMPLE_COPY(strcpy, 7, "7777777", 48); + SIMPLE_COPY(strcpy, 8, "88888888", 49); + SIMPLE_COPY(strcpy, 9, "999999999", 50); + SIMPLE_COPY(strcpy, 10, "0000000000", 51); + SIMPLE_COPY(strcpy, 11, "11111111111", 52); + SIMPLE_COPY(strcpy, 12, "222222222222", 53); + SIMPLE_COPY(strcpy, 13, "3333333333333", 54); + SIMPLE_COPY(strcpy, 14, "44444444444444", 55); + SIMPLE_COPY(strcpy, 15, "555555555555555", 56); + SIMPLE_COPY(strcpy, 16, "6666666666666666", 57); + + /* Simple test using implicitly coerced `void *' arguments. */ + const void *src = "frobozz"; + void *dst = one; + check (strcpy (dst, src) == dst, 1); + equal (dst, "frobozz", 2); +} + +static void +test_stpcpy (void) +{ + it = "stpcpy"; + check ((stpcpy (one, "a") - one) == 1, 1); + equal (one, "a", 2); + + check ((stpcpy (one, "ab") - one) == 2, 3); + equal (one, "ab", 4); + + check ((stpcpy (one, "abc") - one) == 3, 5); + equal (one, "abc", 6); + + check ((stpcpy (one, "abcd") - one) == 4, 7); + equal (one, "abcd", 8); + + check ((stpcpy (one, "abcde") - one) == 5, 9); + equal (one, "abcde", 10); + + check ((stpcpy (one, "abcdef") - one) == 6, 11); + equal (one, "abcdef", 12); + + check ((stpcpy (one, "abcdefg") - one) == 7, 13); + equal (one, "abcdefg", 14); + + check ((stpcpy (one, "abcdefgh") - one) == 8, 15); + equal (one, "abcdefgh", 16); + + check ((stpcpy (one, "abcdefghi") - one) == 9, 17); + equal (one, "abcdefghi", 18); + + check ((stpcpy (one, "x") - one) == 1, 19); + equal (one, "x", 20); /* Writeover. */ + equal (one+2, "cdefghi", 21); /* Wrote too much? */ + + check ((stpcpy (one, "xx") - one) == 2, 22); + equal (one, "xx", 23); /* Writeover. */ + equal (one+3, "defghi", 24); /* Wrote too much? */ + + check ((stpcpy (one, "xxx") - one) == 3, 25); + equal (one, "xxx", 26); /* Writeover. */ + equal (one+4, "efghi", 27); /* Wrote too much? */ + + check ((stpcpy (one, "xxxx") - one) == 4, 28); + equal (one, "xxxx", 29); /* Writeover. */ + equal (one+5, "fghi", 30); /* Wrote too much? */ + + check ((stpcpy (one, "xxxxx") - one) == 5, 31); + equal (one, "xxxxx", 32); /* Writeover. */ + equal (one+6, "ghi", 33); /* Wrote too much? */ + + check ((stpcpy (one, "xxxxxx") - one) == 6, 34); + equal (one, "xxxxxx", 35); /* Writeover. */ + equal (one+7, "hi", 36); /* Wrote too much? */ + + check ((stpcpy (one, "xxxxxxx") - one) == 7, 37); + equal (one, "xxxxxxx", 38); /* Writeover. */ + equal (one+8, "i", 39); /* Wrote too much? */ + + check ((stpcpy (stpcpy (stpcpy (one, "a"), "b"), "c") - one) == 3, 40); + equal (one, "abc", 41); + equal (one + 4, "xxx", 42); + + SIMPLE_COPY(stpcpy, 0, "", 43); + SIMPLE_COPY(stpcpy, 1, "1", 44); + SIMPLE_COPY(stpcpy, 2, "22", 45); + SIMPLE_COPY(stpcpy, 3, "333", 46); + SIMPLE_COPY(stpcpy, 4, "4444", 47); + SIMPLE_COPY(stpcpy, 5, "55555", 48); + SIMPLE_COPY(stpcpy, 6, "666666", 49); + SIMPLE_COPY(stpcpy, 7, "7777777", 50); + SIMPLE_COPY(stpcpy, 8, "88888888", 51); + SIMPLE_COPY(stpcpy, 9, "999999999", 52); + SIMPLE_COPY(stpcpy, 10, "0000000000", 53); + SIMPLE_COPY(stpcpy, 11, "11111111111", 54); + SIMPLE_COPY(stpcpy, 12, "222222222222", 55); + SIMPLE_COPY(stpcpy, 13, "3333333333333", 56); + SIMPLE_COPY(stpcpy, 14, "44444444444444", 57); + SIMPLE_COPY(stpcpy, 15, "555555555555555", 58); + SIMPLE_COPY(stpcpy, 16, "6666666666666666", 59); +} + +static void +test_stpncpy (void) +{ + it = "stpncpy"; + memset (one, 'x', sizeof (one)); + check (stpncpy (one, "abc", 2) == one + 2, 1); + check (stpncpy (one, "abc", 3) == one + 3, 2); + check (stpncpy (one, "abc", 4) == one + 3, 3); + check (one[3] == '\0' && one[4] == 'x', 4); + check (stpncpy (one, "abcd", 5) == one + 4, 5); + check (one[4] == '\0' && one[5] == 'x', 6); + check (stpncpy (one, "abcd", 6) == one + 4, 7); + check (one[4] == '\0' && one[5] == '\0' && one[6] == 'x', 8); +} + +static void +test_strcat (void) +{ + it = "strcat"; + (void) strcpy (one, "ijk"); + check (strcat (one, "lmn") == one, 1); /* Returned value. */ + equal (one, "ijklmn", 2); /* Basic test. */ + + (void) strcpy (one, "x"); + (void) strcat (one, "yz"); + equal (one, "xyz", 3); /* Writeover. */ + equal (one+4, "mn", 4); /* Wrote too much? */ + + (void) strcpy (one, "gh"); + (void) strcpy (two, "ef"); + (void) strcat (one, two); + equal (one, "ghef", 5); /* Basic test encore. */ + equal (two, "ef", 6); /* Stomped on source? */ + + (void) strcpy (one, ""); + (void) strcat (one, ""); + equal (one, "", 7); /* Boundary conditions. */ + (void) strcpy (one, "ab"); + (void) strcat (one, ""); + equal (one, "ab", 8); + (void) strcpy (one, ""); + (void) strcat (one, "cd"); + equal (one, "cd", 9); +} + +static void +test_strncat (void) +{ + /* First test it as strcat, with big counts, then test the count + mechanism. */ + it = "strncat"; + (void) strcpy (one, "ijk"); + check (strncat (one, "lmn", 99) == one, 1); /* Returned value. */ + equal (one, "ijklmn", 2); /* Basic test. */ + + (void) strcpy (one, "x"); + (void) strncat (one, "yz", 99); + equal (one, "xyz", 3); /* Writeover. */ + equal (one+4, "mn", 4); /* Wrote too much? */ + + (void) strcpy (one, "gh"); + (void) strcpy (two, "ef"); + (void) strncat (one, two, 99); + equal (one, "ghef", 5); /* Basic test encore. */ + equal (two, "ef", 6); /* Stomped on source? */ + + (void) strcpy (one, ""); + (void) strncat (one, "", 99); + equal (one, "", 7); /* Boundary conditions. */ + (void) strcpy (one, "ab"); + (void) strncat (one, "", 99); + equal (one, "ab", 8); + (void) strcpy (one, ""); + (void) strncat (one, "cd", 99); + equal (one, "cd", 9); + + (void) strcpy (one, "ab"); + (void) strncat (one, "cdef", 2); + equal (one, "abcd", 10); /* Count-limited. */ + + (void) strncat (one, "gh", 0); + equal (one, "abcd", 11); /* Zero count. */ + + (void) strncat (one, "gh", 2); + equal (one, "abcdgh", 12); /* Count and length equal. */ + + (void) strncat (one, "ij", (size_t)-1); /* set sign bit in count */ + equal (one, "abcdghij", 13); +} + +static void +test_strlcat (void) +{ +#ifdef __TEST_BSD_FUNCS__ + /* First test it as strcat, with big counts, then test the count + mechanism. */ + it = "strlcat"; + (void) strcpy (one, "ijk"); + check (strlcat (one, "lmn", 99) == 6, 1); /* Returned value. */ + equal (one, "ijklmn", 2); /* Basic test. */ + + (void) strcpy (one, "x"); + (void) strlcat (one, "yz", 99); + equal (one, "xyz", 3); /* Writeover. */ + equal (one+4, "mn", 4); /* Wrote too much? */ + + (void) strcpy (one, "gh"); + (void) strcpy (two, "ef"); + (void) strlcat (one, two, 99); + equal (one, "ghef", 5); /* Basic test encore. */ + equal (two, "ef", 6); /* Stomped on source? */ + + (void) strcpy (one, ""); + (void) strlcat (one, "", 99); + equal (one, "", 7); /* Boundary conditions. */ + (void) strcpy (one, "ab"); + (void) strlcat (one, "", 99); + equal (one, "ab", 8); + (void) strcpy (one, ""); + (void) strlcat (one, "cd", 99); + equal (one, "cd", 9); + + (void) strcpy (one, "ab"); + (void) strlcat (one, "cdef", 2); + equal (one, "ab", 10); /* Count-limited. */ + + (void) strlcat (one, "gh", 0); + equal (one, "ab", 11); /* Zero count. */ + + (void) strlcat (one, "gh", 4); + equal (one, "abg", 12); /* Count and length equal. */ + + (void) strlcat (one, "ij", (size_t)-1); /* set sign bit in count */ + equal (one, "abgij", 13); +#endif +} + +static void +test_strncmp (void) +{ + /* First test as strcmp with big counts, then test count code. */ + it = "strncmp"; + check (strncmp ("", "", 99) == 0, 1); /* Trivial case. */ + check (strncmp ("a", "a", 99) == 0, 2); /* Identity. */ + check (strncmp ("abc", "abc", 99) == 0, 3); /* Multicharacter. */ + check (strncmp ("abc", "abcd", 99) < 0, 4); /* Length unequal. */ + check (strncmp ("abcd", "abc", 99) > 0, 5); + check (strncmp ("abcd", "abce", 99) < 0, 6); /* Honestly unequal. */ + check (strncmp ("abce", "abcd", 99) > 0, 7); + check (strncmp ("a\203", "a", 2) > 0, 8); /* Tricky if '\203' < 0 */ + check (strncmp ("a\203", "a\003", 2) > 0, 9); + check (strncmp ("abce", "abcd", 3) == 0, 10); /* Count limited. */ + check (strncmp ("abce", "abc", 3) == 0, 11); /* Count == length. */ + check (strncmp ("abcd", "abce", 4) < 0, 12); /* Nudging limit. */ + check (strncmp ("abc", "def", 0) == 0, 13); /* Zero count. */ + check (strncmp ("abc", "", (size_t)-1) > 0, 14); /* set sign bit in count */ + check (strncmp ("abc", "abc", (size_t)-2) == 0, 15); + check (strncmp ("aa", "ab", (size_t)-1) < 0, 16); +} + +static void +test_strncpy (void) +{ + /* Testing is a bit different because of odd semantics. */ + it = "strncpy"; + check (strncpy (one, "abc", 4) == one, 1); /* Returned value. */ + equal (one, "abc", 2); /* Did the copy go right? */ + + (void) strcpy (one, "abcdefgh"); + (void) strncpy (one, "xyz", 2); + equal (one, "xycdefgh", 3); /* Copy cut by count. */ + + (void) strcpy (one, "abcdefgh"); + (void) strncpy (one, "xyz", 3); /* Copy cut just before NUL. */ + equal (one, "xyzdefgh", 4); + + (void) strcpy (one, "abcdefgh"); + (void) strncpy (one, "xyz", 4); /* Copy just includes NUL. */ + equal (one, "xyz", 5); + equal (one+4, "efgh", 6); /* Wrote too much? */ + + (void) strcpy (one, "abcdefgh"); + (void) strncpy (one, "xyz", 5); /* Copy includes padding. */ + equal (one, "xyz", 7); + equal (one+4, "", 8); + equal (one+5, "fgh", 9); + + (void) strcpy (one, "abc"); + (void) strncpy (one, "xyz", 0); /* Zero-length copy. */ + equal (one, "abc", 10); + + (void) strncpy (one, "", 2); /* Zero-length source. */ + equal (one, "", 11); + equal (one+1, "", 12); + equal (one+2, "c", 13); + + (void) strcpy (one, "hi there"); + (void) strncpy (two, one, 9); + equal (two, "hi there", 14); /* Just paranoia. */ + equal (one, "hi there", 15); /* Stomped on source? */ +} + +static void +test_strlcpy (void) +{ +#ifdef __TEST_BSD_FUNCS__ + /* Testing is a bit different because of odd semantics. */ + it = "strlcpy"; + check (strlcpy (one, "abc", sizeof(one)) == 3, 1); /* Returned value. */ + equal (one, "abc", 2); /* Did the copy go right? */ + + (void) strcpy (one, "abcdefgh"); + (void) strlcpy (one, "xyz", 2); + equal (one, "x\0cdefgh", 3); /* Copy cut by count. */ + + (void) strcpy (one, "abcdefgh"); + (void) strlcpy (one, "xyz", 3); /* Copy cut just before NUL. */ + equal (one, "xy\0defgh", 4); + + (void) strcpy (one, "abcdefgh"); + (void) strlcpy (one, "xyz", 4); /* Copy just includes NUL. */ + equal (one, "xyz", 5); + equal (one+4, "efgh", 6); /* Wrote too much? */ + + (void) strcpy (one, "abcdefgh"); + (void) strlcpy (one, "xyz", 5); /* Copy includes padding. */ + equal (one, "xyz", 7); + equal (one+3, "", 8); + equal (one+4, "efgh", 9); + + (void) strcpy (one, "abc"); + (void) strlcpy (one, "xyz", 0); /* Zero-length copy. */ + equal (one, "abc", 10); + + (void) strlcpy (one, "", 2); /* Zero-length source. */ + equal (one, "", 11); + equal (one+1, "bc", 12); + equal (one+2, "c", 13); + + (void) strcpy (one, "hi there"); + (void) strlcpy (two, one, 9); + equal (two, "hi there", 14); /* Just paranoia. */ + equal (one, "hi there", 15); /* Stomped on source? */ +#endif +} + +static void +test_strlen (void) +{ + it = "strlen"; + check (strlen ("") == 0, 1); /* Empty. */ + check (strlen ("a") == 1, 2); /* Single char. */ + check (strlen ("abcd") == 4, 3); /* Multiple chars. */ + { + char buf[4096]; + int i; + char *p; + for (i=0; i < 0x100; i++) + { + p = (char *) ((unsigned long int)(buf + 0xff) & ~0xff) + i; + strcpy (p, "OK"); + strcpy (p+3, "BAD/WRONG"); + check (strlen (p) == 2, 4+i); + } + } +} + +static void +test_strnlen (void) +{ + it = "strnlen"; + check (strnlen ("", 10) == 0, 1); /* Empty. */ + check (strnlen ("a", 10) == 1, 2); /* Single char. */ + check (strnlen ("abcd", 10) == 4, 3); /* Multiple chars. */ + check (strnlen ("foo", (size_t)-1) == 3, 4); /* limits of n. */ + + { + char buf[4096]; + int i; + char *p; + for (i=0; i < 0x100; i++) + { + p = (char *) ((unsigned long int)(buf + 0xff) & ~0xff) + i; + strcpy (p, "OK"); + strcpy (p+3, "BAD/WRONG"); + check (strnlen (p, 100) == 2, 5+i); + } + } +} + +static void +test_strchr (void) +{ + it = "strchr"; + check (strchr ("abcd", 'z') == NULL, 1); /* Not found. */ + (void) strcpy (one, "abcd"); + check (strchr (one, 'c') == one+2, 2); /* Basic test. */ + check (strchr (one, 'd') == one+3, 3); /* End of string. */ + check (strchr (one, 'a') == one, 4); /* Beginning. */ + check (strchr (one, '\0') == one+4, 5); /* Finding NUL. */ + (void) strcpy (one, "ababa"); + check (strchr (one, 'b') == one+1, 6); /* Finding first. */ + (void) strcpy (one, ""); + check (strchr (one, 'b') == NULL, 7); /* Empty string. */ + check (strchr (one, '\0') == one, 8); /* NUL in empty string. */ + { + char buf[4096]; + int i; + char *p; + for (i=0; i < 0x100; i++) + { + p = (char *) ((unsigned long int) (buf + 0xff) & ~0xff) + i; + strcpy (p, "OK"); + strcpy (p+3, "BAD/WRONG"); + check (strchr (p, '/') == NULL, 9+i); + } + } +} + +static void +test_strchrnul (void) +{ + const char *os; + it = "strchrnul"; + cp = strchrnul ((os = "abcd"), 'z'); + check (*cp == '\0', 1); /* Not found. */ + check (cp == os + 4, 2); + (void) strcpy (one, "abcd"); + check (strchrnul (one, 'c') == one+2, 3); /* Basic test. */ + check (strchrnul (one, 'd') == one+3, 4); /* End of string. */ + check (strchrnul (one, 'a') == one, 5); /* Beginning. */ + check (strchrnul (one, '\0') == one+4, 6); /* Finding NUL. */ + (void) strcpy (one, "ababa"); + check (strchrnul (one, 'b') == one+1, 7); /* Finding first. */ + (void) strcpy (one, ""); + check (strchrnul (one, 'b') == one, 8); /* Empty string. */ + check (strchrnul (one, '\0') == one, 9); /* NUL in empty string. */ + { + char buf[4096]; + int i; + char *p; + for (i=0; i < 0x100; i++) + { + p = (char *) ((unsigned long int) (buf + 0xff) & ~0xff) + i; + strcpy (p, "OK"); + strcpy (p+3, "BAD/WRONG"); + cp = strchrnul (p, '/'); + check (*cp == '\0', 9+2*i); + check (cp == p+2, 10+2*i); + } + } +} + +static void +test_rawmemchr (void) +{ + it = "rawmemchr"; + (void) strcpy (one, "abcd"); + check (rawmemchr (one, 'c') == one+2, 1); /* Basic test. */ + check (rawmemchr (one, 'd') == one+3, 2); /* End of string. */ + check (rawmemchr (one, 'a') == one, 3); /* Beginning. */ + check (rawmemchr (one, '\0') == one+4, 4); /* Finding NUL. */ + (void) strcpy (one, "ababa"); + check (rawmemchr (one, 'b') == one+1, 5); /* Finding first. */ + (void) strcpy (one, ""); + check (rawmemchr (one, '\0') == one, 6); /* NUL in empty string. */ + { + char buf[4096]; + int i; + char *p; + for (i=0; i < 0x100; i++) + { + p = (char *) ((unsigned long int) (buf + 0xff) & ~0xff) + i; + strcpy (p, "OK"); + strcpy (p+3, "BAD/WRONG"); + check (rawmemchr (p, 'R') == p+8, 6+i); + } + } +} + +static void +test_index (void) +{ +#ifdef __TEST_SUSV3_LEGACY__ + it = "index"; + check (index ("abcd", 'z') == NULL, 1); /* Not found. */ + (void) strcpy (one, "abcd"); + check (index (one, 'c') == one+2, 2); /* Basic test. */ + check (index (one, 'd') == one+3, 3); /* End of string. */ + check (index (one, 'a') == one, 4); /* Beginning. */ + check (index (one, '\0') == one+4, 5); /* Finding NUL. */ + (void) strcpy (one, "ababa"); + check (index (one, 'b') == one+1, 6); /* Finding first. */ + (void) strcpy (one, ""); + check (index (one, 'b') == NULL, 7); /* Empty string. */ + check (index (one, '\0') == one, 8); /* NUL in empty string. */ +#endif +} + +static void +test_strrchr (void) +{ + it = "strrchr"; + check (strrchr ("abcd", 'z') == NULL, 1); /* Not found. */ + (void) strcpy (one, "abcd"); + check (strrchr (one, 'c') == one+2, 2); /* Basic test. */ + check (strrchr (one, 'd') == one+3, 3); /* End of string. */ + check (strrchr (one, 'a') == one, 4); /* Beginning. */ + check (strrchr (one, '\0') == one+4, 5); /* Finding NUL. */ + (void) strcpy (one, "ababa"); + check (strrchr (one, 'b') == one+3, 6); /* Finding last. */ + (void) strcpy (one, ""); + check (strrchr (one, 'b') == NULL, 7); /* Empty string. */ + check (strrchr (one, '\0') == one, 8); /* NUL in empty string. */ + { + char buf[4096]; + int i; + char *p; + for (i=0; i < 0x100; i++) + { + p = (char *) ((unsigned long int) (buf + 0xff) & ~0xff) + i; + strcpy (p, "OK"); + strcpy (p+3, "BAD/WRONG"); + check (strrchr (p, '/') == NULL, 9+i); + } + } +} + +static void +test_memrchr (void) +{ + size_t l; + it = "memrchr"; + check (memrchr ("abcd", 'z', 5) == NULL, 1); /* Not found. */ + (void) strcpy (one, "abcd"); + l = strlen (one) + 1; + check (memrchr (one, 'c', l) == one+2, 2); /* Basic test. */ + check (memrchr (one, 'd', l) == one+3, 3); /* End of string. */ + check (memrchr (one, 'a', l) == one, 4); /* Beginning. */ + check (memrchr (one, '\0', l) == one+4, 5); /* Finding NUL. */ + (void) strcpy (one, "ababa"); + l = strlen (one) + 1; + check (memrchr (one, 'b', l) == one+3, 6); /* Finding last. */ + (void) strcpy (one, ""); + l = strlen (one) + 1; + check (memrchr (one, 'b', l) == NULL, 7); /* Empty string. */ + check (memrchr (one, '\0', l) == one, 8); /* NUL in empty string. */ + + /* now test all possible alignment and length combinations to catch + bugs due to unrolled loops (assuming unrolling is limited to no + more than 128 byte chunks: */ + { + char buf[128 + sizeof(long)]; + long align, len, i, pos; + + for (align = 0; align < (long) sizeof(long); ++align) { + for (len = 0; len < (long) (sizeof(buf) - align); ++len) { + for (i = 0; i < len; ++i) + buf[align + i] = 'x'; /* don't depend on memset... */ + + for (pos = len - 1; pos >= 0; --pos) { +#if 0 + printf("align %d, len %d, pos %d\n", align, len, pos); +#endif + check(memrchr(buf + align, 'x', len) == buf + align + pos, 9); + check(memrchr(buf + align + pos + 1, 'x', len - (pos + 1)) == NULL, + 10); + buf[align + pos] = '-'; + } + } + } + } +} + +static void +test_rindex (void) +{ +#ifdef __TEST_SUSV3_LEGACY__ + it = "rindex"; + check (rindex ("abcd", 'z') == NULL, 1); /* Not found. */ + (void) strcpy (one, "abcd"); + check (rindex (one, 'c') == one+2, 2); /* Basic test. */ + check (rindex (one, 'd') == one+3, 3); /* End of string. */ + check (rindex (one, 'a') == one, 4); /* Beginning. */ + check (rindex (one, '\0') == one+4, 5); /* Finding NUL. */ + (void) strcpy (one, "ababa"); + check (rindex (one, 'b') == one+3, 6); /* Finding last. */ + (void) strcpy (one, ""); + check (rindex (one, 'b') == NULL, 7); /* Empty string. */ + check (rindex (one, '\0') == one, 8); /* NUL in empty string. */ +#endif +} + +static void +test_strpbrk (void) +{ + it = "strpbrk"; + check(strpbrk("abcd", "z") == NULL, 1); /* Not found. */ + (void) strcpy(one, "abcd"); + check(strpbrk(one, "c") == one+2, 2); /* Basic test. */ + check(strpbrk(one, "d") == one+3, 3); /* End of string. */ + check(strpbrk(one, "a") == one, 4); /* Beginning. */ + check(strpbrk(one, "") == NULL, 5); /* Empty search list. */ + check(strpbrk(one, "cb") == one+1, 6); /* Multiple search. */ + (void) strcpy(one, "abcabdea"); + check(strpbrk(one, "b") == one+1, 7); /* Finding first. */ + check(strpbrk(one, "cb") == one+1, 8); /* With multiple search. */ + check(strpbrk(one, "db") == one+1, 9); /* Another variant. */ + (void) strcpy(one, ""); + check(strpbrk(one, "bc") == NULL, 10); /* Empty string. */ + (void) strcpy(one, ""); + check(strpbrk(one, "bcd") == NULL, 11); /* Empty string. */ + (void) strcpy(one, ""); + check(strpbrk(one, "bcde") == NULL, 12); /* Empty string. */ + check(strpbrk(one, "") == NULL, 13); /* Both strings empty. */ + (void) strcpy(one, "abcabdea"); + check(strpbrk(one, "befg") == one+1, 14); /* Finding first. */ + check(strpbrk(one, "cbr") == one+1, 15); /* With multiple search. */ + check(strpbrk(one, "db") == one+1, 16); /* Another variant. */ + check(strpbrk(one, "efgh") == one+6, 17); /* And yet another. */ +} + +static void +test_strstr (void) +{ + it = "strstr"; + check(strstr("abcd", "z") == NULL, 1); /* Not found. */ + check(strstr("abcd", "abx") == NULL, 2); /* Dead end. */ + (void) strcpy(one, "abcd"); + check(strstr(one, "c") == one+2, 3); /* Basic test. */ + check(strstr(one, "bc") == one+1, 4); /* Multichar. */ + check(strstr(one, "d") == one+3, 5); /* End of string. */ + check(strstr(one, "cd") == one+2, 6); /* Tail of string. */ + check(strstr(one, "abc") == one, 7); /* Beginning. */ + check(strstr(one, "abcd") == one, 8); /* Exact match. */ + check(strstr(one, "abcde") == NULL, 9); /* Too long. */ + check(strstr(one, "de") == NULL, 10); /* Past end. */ + check(strstr(one, "") == one, 11); /* Finding empty. */ + (void) strcpy(one, "ababa"); + check(strstr(one, "ba") == one+1, 12); /* Finding first. */ + (void) strcpy(one, ""); + check(strstr(one, "b") == NULL, 13); /* Empty string. */ + check(strstr(one, "") == one, 14); /* Empty in empty string. */ + (void) strcpy(one, "bcbca"); + check(strstr(one, "bca") == one+2, 15); /* False start. */ + (void) strcpy(one, "bbbcabbca"); + check(strstr(one, "bbca") == one+1, 16); /* With overlap. */ +} + +static void +test_strspn (void) +{ + it = "strspn"; + check(strspn("abcba", "abc") == 5, 1); /* Whole string. */ + check(strspn("abcba", "ab") == 2, 2); /* Partial. */ + check(strspn("abc", "qx") == 0, 3); /* None. */ + check(strspn("", "ab") == 0, 4); /* Null string. */ + check(strspn("abc", "") == 0, 5); /* Null search list. */ +} + +static void +test_strcspn (void) +{ + it = "strcspn"; + check(strcspn("abcba", "qx") == 5, 1); /* Whole string. */ + check(strcspn("abcba", "cx") == 2, 2); /* Partial. */ + check(strcspn("abc", "abc") == 0, 3); /* None. */ + check(strcspn("", "ab") == 0, 4); /* Null string. */ + check(strcspn("abc", "") == 3, 5); /* Null search list. */ +} + +static void +test_strtok (void) +{ + it = "strtok"; + (void) strcpy(one, "first, second, third"); + equal(strtok(one, ", "), "first", 1); /* Basic test. */ + equal(one, "first", 2); + equal(strtok((char *)NULL, ", "), "second", 3); + equal(strtok((char *)NULL, ", "), "third", 4); + check(strtok((char *)NULL, ", ") == NULL, 5); + (void) strcpy(one, ", first, "); + equal(strtok(one, ", "), "first", 6); /* Extra delims, 1 tok. */ + check(strtok((char *)NULL, ", ") == NULL, 7); + (void) strcpy(one, "1a, 1b; 2a, 2b"); + equal(strtok(one, ", "), "1a", 8); /* Changing delim lists. */ + equal(strtok((char *)NULL, "; "), "1b", 9); + equal(strtok((char *)NULL, ", "), "2a", 10); + (void) strcpy(two, "x-y"); + equal(strtok(two, "-"), "x", 11); /* New string before done. */ + equal(strtok((char *)NULL, "-"), "y", 12); + check(strtok((char *)NULL, "-") == NULL, 13); + (void) strcpy(one, "a,b, c,, ,d"); + equal(strtok(one, ", "), "a", 14); /* Different separators. */ + equal(strtok((char *)NULL, ", "), "b", 15); + equal(strtok((char *)NULL, " ,"), "c", 16); /* Permute list too. */ + equal(strtok((char *)NULL, " ,"), "d", 17); + check(strtok((char *)NULL, ", ") == NULL, 18); + check(strtok((char *)NULL, ", ") == NULL, 19); /* Persistence. */ + (void) strcpy(one, ", "); + check(strtok(one, ", ") == NULL, 20); /* No tokens. */ + (void) strcpy(one, ""); + check(strtok(one, ", ") == NULL, 21); /* Empty string. */ + (void) strcpy(one, "abc"); + equal(strtok(one, ", "), "abc", 22); /* No delimiters. */ + check(strtok((char *)NULL, ", ") == NULL, 23); + (void) strcpy(one, "abc"); + equal(strtok(one, ""), "abc", 24); /* Empty delimiter list. */ + check(strtok((char *)NULL, "") == NULL, 25); + (void) strcpy(one, "abcdefgh"); + (void) strcpy(one, "a,b,c"); + equal(strtok(one, ","), "a", 26); /* Basics again... */ + equal(strtok((char *)NULL, ","), "b", 27); + equal(strtok((char *)NULL, ","), "c", 28); + check(strtok((char *)NULL, ",") == NULL, 29); + equal(one+6, "gh", 30); /* Stomped past end? */ + equal(one, "a", 31); /* Stomped old tokens? */ + equal(one+2, "b", 32); + equal(one+4, "c", 33); +} + +static void +test_strtok_r (void) +{ + it = "strtok_r"; + (void) strcpy(one, "first, second, third"); + cp = NULL; /* Always initialize cp to make sure it doesn't point to some old data. */ + equal(strtok_r(one, ", ", &cp), "first", 1); /* Basic test. */ + equal(one, "first", 2); + equal(strtok_r((char *)NULL, ", ", &cp), "second", 3); + equal(strtok_r((char *)NULL, ", ", &cp), "third", 4); + check(strtok_r((char *)NULL, ", ", &cp) == NULL, 5); + (void) strcpy(one, ", first, "); + cp = NULL; + equal(strtok_r(one, ", ", &cp), "first", 6); /* Extra delims, 1 tok. */ + check(strtok_r((char *)NULL, ", ", &cp) == NULL, 7); + (void) strcpy(one, "1a, 1b; 2a, 2b"); + cp = NULL; + equal(strtok_r(one, ", ", &cp), "1a", 8); /* Changing delim lists. */ + equal(strtok_r((char *)NULL, "; ", &cp), "1b", 9); + equal(strtok_r((char *)NULL, ", ", &cp), "2a", 10); + (void) strcpy(two, "x-y"); + cp = NULL; + equal(strtok_r(two, "-", &cp), "x", 11); /* New string before done. */ + equal(strtok_r((char *)NULL, "-", &cp), "y", 12); + check(strtok_r((char *)NULL, "-", &cp) == NULL, 13); + (void) strcpy(one, "a,b, c,, ,d"); + cp = NULL; + equal(strtok_r(one, ", ", &cp), "a", 14); /* Different separators. */ + equal(strtok_r((char *)NULL, ", ", &cp), "b", 15); + equal(strtok_r((char *)NULL, " ,", &cp), "c", 16); /* Permute list too. */ + equal(strtok_r((char *)NULL, " ,", &cp), "d", 17); + check(strtok_r((char *)NULL, ", ", &cp) == NULL, 18); + check(strtok_r((char *)NULL, ", ", &cp) == NULL, 19); /* Persistence. */ + (void) strcpy(one, ", "); + cp = NULL; + check(strtok_r(one, ", ", &cp) == NULL, 20); /* No tokens. */ + (void) strcpy(one, ""); + cp = NULL; + check(strtok_r(one, ", ", &cp) == NULL, 21); /* Empty string. */ + check(strtok_r((char *)NULL, ", ", &cp) == NULL, 22); /* Persistence. */ + (void) strcpy(one, "abc"); + cp = NULL; + equal(strtok_r(one, ", ", &cp), "abc", 23); /* No delimiters. */ + check(strtok_r((char *)NULL, ", ", &cp) == NULL, 24); + (void) strcpy(one, "abc"); + cp = NULL; + equal(strtok_r(one, "", &cp), "abc", 25); /* Empty delimiter list. */ + check(strtok_r((char *)NULL, "", &cp) == NULL, 26); + (void) strcpy(one, "abcdefgh"); + (void) strcpy(one, "a,b,c"); + cp = NULL; + equal(strtok_r(one, ",", &cp), "a", 27); /* Basics again... */ + equal(strtok_r((char *)NULL, ",", &cp), "b", 28); + equal(strtok_r((char *)NULL, ",", &cp), "c", 29); + check(strtok_r((char *)NULL, ",", &cp) == NULL, 30); + equal(one+6, "gh", 31); /* Stomped past end? */ + equal(one, "a", 32); /* Stomped old tokens? */ + equal(one+2, "b", 33); + equal(one+4, "c", 34); +} + +static void +test_strsep (void) +{ + char *ptr; + it = "strsep"; + cp = strcpy(one, "first, second, third"); + equal(strsep(&cp, ", "), "first", 1); /* Basic test. */ + equal(one, "first", 2); + equal(strsep(&cp, ", "), "", 3); + equal(strsep(&cp, ", "), "second", 4); + equal(strsep(&cp, ", "), "", 5); + equal(strsep(&cp, ", "), "third", 6); + check(strsep(&cp, ", ") == NULL, 7); + cp = strcpy(one, ", first, "); + equal(strsep(&cp, ", "), "", 8); + equal(strsep(&cp, ", "), "", 9); + equal(strsep(&cp, ", "), "first", 10); /* Extra delims, 1 tok. */ + equal(strsep(&cp, ", "), "", 11); + equal(strsep(&cp, ", "), "", 12); + check(strsep(&cp, ", ") == NULL, 13); + cp = strcpy(one, "1a, 1b; 2a, 2b"); + equal(strsep(&cp, ", "), "1a", 14); /* Changing delim lists. */ + equal(strsep(&cp, ", "), "", 15); + equal(strsep(&cp, "; "), "1b", 16); + equal(strsep(&cp, ", "), "", 17); + equal(strsep(&cp, ", "), "2a", 18); + cp = strcpy(two, "x-y"); + equal(strsep(&cp, "-"), "x", 19); /* New string before done. */ + equal(strsep(&cp, "-"), "y", 20); + check(strsep(&cp, "-") == NULL, 21); + cp = strcpy(one, "a,b, c,, ,d "); + equal(strsep(&cp, ", "), "a", 22); /* Different separators. */ + equal(strsep(&cp, ", "), "b", 23); + equal(strsep(&cp, " ,"), "", 24); + equal(strsep(&cp, " ,"), "c", 25); /* Permute list too. */ + equal(strsep(&cp, " ,"), "", 26); + equal(strsep(&cp, " ,"), "", 27); + equal(strsep(&cp, " ,"), "", 28); + equal(strsep(&cp, " ,"), "d", 29); + equal(strsep(&cp, " ,"), "", 30); + check(strsep(&cp, ", ") == NULL, 31); + check(strsep(&cp, ", ") == NULL, 32); /* Persistence. */ + cp = strcpy(one, ", "); + equal(strsep(&cp, ", "), "", 33); + equal(strsep(&cp, ", "), "", 34); + equal(strsep(&cp, ", "), "", 35); + check(strsep(&cp, ", ") == NULL, 36); /* No tokens. */ + cp = strcpy(one, ""); + equal(strsep(&cp, ", "), "", 37); + check(strsep(&cp, ", ") == NULL, 38); /* Empty string. */ + cp = strcpy(one, "abc"); + equal(strsep(&cp, ", "), "abc", 39); /* No delimiters. */ + check(strsep(&cp, ", ") == NULL, 40); + cp = strcpy(one, "abc"); + equal(strsep(&cp, ""), "abc", 41); /* Empty delimiter list. */ + check(strsep(&cp, "") == NULL, 42); + (void) strcpy(one, "abcdefgh"); + cp = strcpy(one, "a,b,c"); + equal(strsep(&cp, ","), "a", 43); /* Basics again... */ + equal(strsep(&cp, ","), "b", 44); + equal(strsep(&cp, ","), "c", 45); + check(strsep(&cp, ",") == NULL, 46); + equal(one+6, "gh", 47); /* Stomped past end? */ + equal(one, "a", 48); /* Stomped old tokens? */ + equal(one+2, "b", 49); + equal(one+4, "c", 50); + + { + char text[] = "This,is,a,test"; + char *list = strdupa (text); + equal (strsep (&list, ","), "This", 51); + equal (strsep (&list, ","), "is", 52); + equal (strsep (&list, ","), "a", 53); + equal (strsep (&list, ","), "test", 54); + check (strsep (&list, ",") == NULL, 55); + } + + cp = strcpy(one, "a,b, c,, ,d,"); + equal(strsep(&cp, ","), "a", 56); /* Different separators. */ + equal(strsep(&cp, ","), "b", 57); + equal(strsep(&cp, ","), " c", 58); /* Permute list too. */ + equal(strsep(&cp, ","), "", 59); + equal(strsep(&cp, ","), " ", 60); + equal(strsep(&cp, ","), "d", 61); + equal(strsep(&cp, ","), "", 62); + check(strsep(&cp, ",") == NULL, 63); + check(strsep(&cp, ",") == NULL, 64); /* Persistence. */ + + cp = strcpy(one, "a,b, c,, ,d,"); + equal(strsep(&cp, "xy,"), "a", 65); /* Different separators. */ + equal(strsep(&cp, "x,y"), "b", 66); + equal(strsep(&cp, ",xy"), " c", 67); /* Permute list too. */ + equal(strsep(&cp, "xy,"), "", 68); + equal(strsep(&cp, "x,y"), " ", 69); + equal(strsep(&cp, ",xy"), "d", 70); + equal(strsep(&cp, "xy,"), "", 71); + check(strsep(&cp, "x,y") == NULL, 72); + check(strsep(&cp, ",xy") == NULL, 73); /* Persistence. */ + + cp = strcpy(one, "ABC"); + one[4] = ':'; + equal(strsep(&cp, "C"), "AB", 74); /* Access beyond NUL. */ + ptr = strsep(&cp, ":"); + equal(ptr, "", 75); + check(ptr == one + 3, 76); + check(cp == NULL, 77); + + cp = strcpy(one, "ABC"); + one[4] = ':'; + equal(strsep(&cp, "CD"), "AB", 78); /* Access beyond NUL. */ + ptr = strsep(&cp, ":."); + equal(ptr, "", 79); + check(ptr == one + 3, 80); + + cp = strcpy(one, "ABC"); /* No token in string. */ + equal(strsep(&cp, ","), "ABC", 81); + check(cp == NULL, 82); + + *one = '\0'; /* Empty string. */ + cp = one; + ptr = strsep(&cp, ","); + equal(ptr, "", 83); + check(ptr == one, 84); + check(cp == NULL, 85); + + *one = '\0'; /* Empty string and no token. */ + cp = one; + ptr = strsep(&cp, ""); + equal(ptr, "", 86); + check(ptr == one , 87); + check(cp == NULL, 88); +} + +static void +test_memcmp (void) +{ + int i, cnt = 1; + char one[21], two[21]; + + it = "memcmp"; + check(memcmp("a", "a", 1) == 0, cnt++); /* Identity. */ + check(memcmp("abc", "abc", 3) == 0, cnt++); /* Multicharacter. */ + check(memcmp("abcd", "abcf", 4) < 0, cnt++); /* Honestly unequal. */ + check(memcmp("abcf", "abcd", 4) > 0, cnt++); + check(memcmp("alph", "cold", 4) < 0, cnt++); + check(memcmp("a\203", "a\003", 2) > 0, cnt++); + check(memcmp("a\003", "a\203", 2) < 0, cnt++); + check(memcmp("a\003bc", "a\203bc", 2) < 0, cnt++); + check(memcmp("abc\203", "abc\003", 4) > 0, cnt++); + check(memcmp("abc\003", "abc\203", 4) < 0, cnt++); + check(memcmp("abcf", "abcd", 3) == 0, cnt++); /* Count limited. */ + check(memcmp("abc", "def", 0) == 0, cnt++); /* Zero count. */ + /* Comparisons with shifting 4-byte boundaries. */ + for (i=0; i<4; i++) + { + char *a = one + i, *b = two + i; + strncpy( a, "--------11112222", 16); + strncpy( b, "--------33334444", 16); + check( memcmp(b, a, 16) > 0, cnt++); + check( memcmp(a, b, 16) < 0, cnt++); + } +} + +static void +test_memchr (void) +{ + it = "memchr"; + check(memchr("abcd", 'z', 4) == NULL, 1); /* Not found. */ + (void) strcpy(one, "abcd"); + check(memchr(one, 'c', 4) == one+2, 2); /* Basic test. */ + check(memchr(one, ~0xff|'c', 4) == one+2, 2); /* ignore highorder bits. */ + check(memchr(one, 'd', 4) == one+3, 3); /* End of string. */ + check(memchr(one, 'a', 4) == one, 4); /* Beginning. */ + check(memchr(one, '\0', 5) == one+4, 5); /* Finding NUL. */ + (void) strcpy(one, "ababa"); + check(memchr(one, 'b', 5) == one+1, 6); /* Finding first. */ + check(memchr(one, 'b', 0) == NULL, 7); /* Zero count. */ + check(memchr(one, 'a', 1) == one, 8); /* Singleton case. */ + (void) strcpy(one, "a\203b"); + check(memchr(one, 0203, 3) == one+1, 9); /* Unsignedness. */ + + /* now test all possible alignment and length combinations to catch + bugs due to unrolled loops (assuming unrolling is limited to no + more than 128 byte chunks: */ + { + char buf[128 + sizeof(long)]; + long align, len, i, pos; + + for (align = 0; align < (long) sizeof(long); ++align) { + for (len = 0; len < (long) (sizeof(buf) - align); ++len) { + for (i = 0; i < len; ++i) { + buf[align + i] = 'x'; /* don't depend on memset... */ + } + for (pos = 0; pos < len; ++pos) { +#if 0 + printf("align %d, len %d, pos %d\n", align, len, pos); +#endif + check(memchr(buf + align, 'x', len) == buf + align + pos, 10); + check(memchr(buf + align, 'x', pos) == NULL, 11); + buf[align + pos] = '-'; + } + } + } + } +} + +static void +test_memcpy (void) +{ + int i; + it = "memcpy"; + check(memcpy(one, "abc", 4) == one, 1); /* Returned value. */ + equal(one, "abc", 2); /* Did the copy go right? */ + + (void) strcpy(one, "abcdefgh"); + (void) memcpy(one+1, "xyz", 2); + equal(one, "axydefgh", 3); /* Basic test. */ + + (void) strcpy(one, "abc"); + (void) memcpy(one, "xyz", 0); + equal(one, "abc", 4); /* Zero-length copy. */ + + (void) strcpy(one, "hi there"); + (void) strcpy(two, "foo"); + (void) memcpy(two, one, 9); + equal(two, "hi there", 5); /* Just paranoia. */ + equal(one, "hi there", 6); /* Stomped on source? */ + + for (i = 0; i < 16; i++) + { + const char *x = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; + strcpy (one, x); + check (memcpy (one + i, "hi there", 9) == one + i, + 7 + (i * 6)); /* Unaligned destination. */ + check (memcmp (one, x, i) == 0, 8 + (i * 6)); /* Wrote under? */ + equal (one + i, "hi there", 9 + (i * 6)); + check (one[i + 9] == 'x', 10 + (i * 6)); /* Wrote over? */ + check (memcpy (two, one + i, 9) == two, + 11 + (i * 6)); /* Unaligned source. */ + equal (two, "hi there", 12 + (i * 6)); + } +} + +static void +test_mempcpy (void) +{ + int i; + it = "mempcpy"; + check(mempcpy(one, "abc", 4) == one + 4, 1); /* Returned value. */ + equal(one, "abc", 2); /* Did the copy go right? */ + + (void) strcpy(one, "abcdefgh"); + (void) mempcpy(one+1, "xyz", 2); + equal(one, "axydefgh", 3); /* Basic test. */ + + (void) strcpy(one, "abc"); + (void) mempcpy(one, "xyz", 0); + equal(one, "abc", 4); /* Zero-length copy. */ + + (void) strcpy(one, "hi there"); + (void) strcpy(two, "foo"); + (void) mempcpy(two, one, 9); + equal(two, "hi there", 5); /* Just paranoia. */ + equal(one, "hi there", 6); /* Stomped on source? */ + + for (i = 0; i < 16; i++) + { + const char *x = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; + strcpy (one, x); + check (mempcpy (one + i, "hi there", 9) == one + i + 9, + 7 + (i * 6)); /* Unaligned destination. */ + check (memcmp (one, x, i) == 0, 8 + (i * 6)); /* Wrote under? */ + equal (one + i, "hi there", 9 + (i * 6)); + check (one[i + 9] == 'x', 10 + (i * 6)); /* Wrote over? */ + check (mempcpy (two, one + i, 9) == two + 9, + 11 + (i * 6)); /* Unaligned source. */ + equal (two, "hi there", 12 + (i * 6)); + } +} + +static void +test_memmove (void) +{ + it = "memmove"; + check(memmove(one, "abc", 4) == one, 1); /* Returned value. */ + equal(one, "abc", 2); /* Did the copy go right? */ + + (void) strcpy(one, "abcdefgh"); + (void) memmove(one+1, "xyz", 2); + equal(one, "axydefgh", 3); /* Basic test. */ + + (void) strcpy(one, "abc"); + (void) memmove(one, "xyz", 0); + equal(one, "abc", 4); /* Zero-length copy. */ + + (void) strcpy(one, "hi there"); + (void) strcpy(two, "foo"); + (void) memmove(two, one, 9); + equal(two, "hi there", 5); /* Just paranoia. */ + equal(one, "hi there", 6); /* Stomped on source? */ + + (void) strcpy(one, "abcdefgh"); + (void) memmove(one+1, one, 9); + equal(one, "aabcdefgh", 7); /* Overlap, right-to-left. */ + + (void) strcpy(one, "abcdefgh"); + (void) memmove(one+1, one+2, 7); + equal(one, "acdefgh", 8); /* Overlap, left-to-right. */ + + (void) strcpy(one, "abcdefgh"); + (void) memmove(one, one, 9); + equal(one, "abcdefgh", 9); /* 100% overlap. */ +} + +static void +test_memccpy (void) +{ + /* First test like memcpy, then the search part The SVID, the only + place where memccpy is mentioned, says overlap might fail, so we + don't try it. Besides, it's hard to see the rationale for a + non-left-to-right memccpy. */ + it = "memccpy"; + check(memccpy(one, "abc", 'q', 4) == NULL, 1); /* Returned value. */ + equal(one, "abc", 2); /* Did the copy go right? */ + + (void) strcpy(one, "abcdefgh"); + (void) memccpy(one+1, "xyz", 'q', 2); + equal(one, "axydefgh", 3); /* Basic test. */ + + (void) strcpy(one, "abc"); + (void) memccpy(one, "xyz", 'q', 0); + equal(one, "abc", 4); /* Zero-length copy. */ + + (void) strcpy(one, "hi there"); + (void) strcpy(two, "foo"); + (void) memccpy(two, one, 'q', 9); + equal(two, "hi there", 5); /* Just paranoia. */ + equal(one, "hi there", 6); /* Stomped on source? */ + + (void) strcpy(one, "abcdefgh"); + (void) strcpy(two, "horsefeathers"); + check(memccpy(two, one, 'f', 9) == two+6, 7); /* Returned value. */ + equal(one, "abcdefgh", 8); /* Source intact? */ + equal(two, "abcdefeathers", 9); /* Copy correct? */ + + (void) strcpy(one, "abcd"); + (void) strcpy(two, "bumblebee"); + check(memccpy(two, one, 'a', 4) == two+1, 10); /* First char. */ + equal(two, "aumblebee", 11); + check(memccpy(two, one, 'd', 4) == two+4, 12); /* Last char. */ + equal(two, "abcdlebee", 13); + (void) strcpy(one, "xyz"); + check(memccpy(two, one, 'x', 1) == two+1, 14); /* Singleton. */ + equal(two, "xbcdlebee", 15); +} + +static void +test_memset (void) +{ + int i; + + it = "memset"; + (void) strcpy(one, "abcdefgh"); + check(memset(one+1, 'x', 3) == one+1, 1); /* Return value. */ + equal(one, "axxxefgh", 2); /* Basic test. */ + + (void) memset(one+2, 'y', 0); + equal(one, "axxxefgh", 3); /* Zero-length set. */ + + (void) memset(one+5, 0, 1); + equal(one, "axxxe", 4); /* Zero fill. */ + equal(one+6, "gh", 5); /* And the leftover. */ + + (void) memset(one+2, 010045, 1); + equal(one, "ax\045xe", 6); /* Unsigned char convert. */ + + /* Non-8bit fill character. */ + memset (one, 0x101, sizeof (one)); + for (i = 0; i < (int) sizeof (one); ++i) + check (one[i] == '\01', 7); + + /* Test for more complex versions of memset, for all alignments and + lengths up to 256. This test takes a little while, perhaps it should + be made weaker? */ + { + char data[512]; + int j; + int k; + int c; + + for (i = 0; i < 512; i++) + data[i] = 'x'; + for (c = 0; c <= 'y'; c += 'y') /* check for memset(,0,) and + memset(,'y',) */ + for (j = 0; j < 256; j++) + for (i = 0; i < 256; i++) + { + memset (data + i, c, j); + for (k = 0; k < i; k++) + if (data[k] != 'x') + goto fail; + for (k = i; k < i+j; k++) + { + if (data[k] != c) + goto fail; + data[k] = 'x'; + } + for (k = i+j; k < 512; k++) + if (data[k] != 'x') + goto fail; + continue; + + fail: + check (0, 8 + i + j * 256 + (c != 0) * 256 * 256); + } + } +} + +static void +test_bcopy (void) +{ +#ifdef __TEST_SUSV3_LEGACY__ + /* Much like memcpy. Berklix manual is silent about overlap, so + don't test it. */ + it = "bcopy"; + (void) bcopy("abc", one, 4); + equal(one, "abc", 1); /* Simple copy. */ + + (void) strcpy(one, "abcdefgh"); + (void) bcopy("xyz", one+1, 2); + equal(one, "axydefgh", 2); /* Basic test. */ + + (void) strcpy(one, "abc"); + (void) bcopy("xyz", one, 0); + equal(one, "abc", 3); /* Zero-length copy. */ + + (void) strcpy(one, "hi there"); + (void) strcpy(two, "foo"); + (void) bcopy(one, two, 9); + equal(two, "hi there", 4); /* Just paranoia. */ + equal(one, "hi there", 5); /* Stomped on source? */ +#endif +} + +static void +test_bzero (void) +{ +#ifdef __TEST_SUSV3_LEGACY__ + it = "bzero"; + (void) strcpy(one, "abcdef"); + bzero(one+2, 2); + equal(one, "ab", 1); /* Basic test. */ + equal(one+3, "", 2); + equal(one+4, "ef", 3); + + (void) strcpy(one, "abcdef"); + bzero(one+2, 0); + equal(one, "abcdef", 4); /* Zero-length copy. */ +#endif +} + +static void +test_strndup (void) +{ + char *p, *q; + it = "strndup"; + p = strndup("abcdef", 12); + check(p != NULL, 1); + if (p != NULL) + { + equal(p, "abcdef", 2); + q = strndup(p + 1, 2); + check(q != NULL, 3); + if (q != NULL) + equal(q, "bc", 4); + free (q); + } + free (p); + p = strndup("abc def", 3); + check(p != NULL, 5); + if (p != NULL) + equal(p, "abc", 6); + free (p); +} + +static void +test_bcmp (void) +{ +#ifdef __TEST_SUSV3_LEGACY__ + it = "bcmp"; + check(bcmp("a", "a", 1) == 0, 1); /* Identity. */ + check(bcmp("abc", "abc", 3) == 0, 2); /* Multicharacter. */ + check(bcmp("abcd", "abce", 4) != 0, 3); /* Honestly unequal. */ + check(bcmp("abce", "abcd", 4) != 0, 4); + check(bcmp("alph", "beta", 4) != 0, 5); + check(bcmp("abce", "abcd", 3) == 0, 6); /* Count limited. */ + check(bcmp("abc", "def", 0) == 0, 8); /* Zero count. */ +#endif +} + +static void +test_strerror (void) +{ + it = "strerror"; + check(strerror(EDOM) != 0, 1); + check(strerror(ERANGE) != 0, 2); + check(strerror(ENOENT) != 0, 3); +} + +static void +test_strcasecmp (void) +{ + it = "strcasecmp"; + /* Note that the locale is "C". */ + check(strcasecmp("a", "a") == 0, 1); + check(strcasecmp("a", "A") == 0, 2); + check(strcasecmp("A", "a") == 0, 3); + check(strcasecmp("a", "b") < 0, 4); + check(strcasecmp("c", "b") > 0, 5); + check(strcasecmp("abc", "AbC") == 0, 6); + check(strcasecmp("0123456789", "0123456789") == 0, 7); + check(strcasecmp("", "0123456789") < 0, 8); + check(strcasecmp("AbC", "") > 0, 9); + check(strcasecmp("AbC", "A") > 0, 10); + check(strcasecmp("AbC", "Ab") > 0, 11); + check(strcasecmp("AbC", "ab") > 0, 12); +} + +static void +test_strncasecmp (void) +{ + it = "strncasecmp"; + /* Note that the locale is "C". */ + check(strncasecmp("a", "a", 5) == 0, 1); + check(strncasecmp("a", "A", 5) == 0, 2); + check(strncasecmp("A", "a", 5) == 0, 3); + check(strncasecmp("a", "b", 5) < 0, 4); + check(strncasecmp("c", "b", 5) > 0, 5); + check(strncasecmp("abc", "AbC", 5) == 0, 6); + check(strncasecmp("0123456789", "0123456789", 10) == 0, 7); + check(strncasecmp("", "0123456789", 10) < 0, 8); + check(strncasecmp("AbC", "", 5) > 0, 9); + check(strncasecmp("AbC", "A", 5) > 0, 10); + check(strncasecmp("AbC", "Ab", 5) > 0, 11); + check(strncasecmp("AbC", "ab", 5) > 0, 12); + check(strncasecmp("0123456789", "AbC", 0) == 0, 13); + check(strncasecmp("AbC", "abc", 1) == 0, 14); + check(strncasecmp("AbC", "abc", 2) == 0, 15); + check(strncasecmp("AbC", "abc", 3) == 0, 16); + check(strncasecmp("AbC", "abcd", 3) == 0, 17); + check(strncasecmp("AbC", "abcd", 4) < 0, 18); + check(strncasecmp("ADC", "abcd", 1) == 0, 19); + check(strncasecmp("ADC", "abcd", 2) > 0, 20); +} + +int +main (void) +{ + int status; + + /* Test strcmp first because we use it to test other things. */ + test_strcmp (); + + /* Test strcpy next because we need it to set up other tests. */ + test_strcpy (); + + /* A closely related function is stpcpy. */ + test_stpcpy (); + + /* stpncpy. */ + test_stpncpy (); + + /* strcat. */ + test_strcat (); + + /* strncat. */ + test_strncat (); + + /* strlcat. */ + test_strlcat (); + + /* strncmp. */ + test_strncmp (); + + /* strncpy. */ + test_strncpy (); + + /* strlcpy. */ + test_strlcpy (); + + /* strlen. */ + test_strlen (); + + /* strnlen. */ + test_strnlen (); + + /* strchr. */ + test_strchr (); + + /* strchrnul. */ + test_strchrnul (); + + /* rawmemchr. */ + test_rawmemchr (); + + /* index - just like strchr. */ + test_index (); + + /* strrchr. */ + test_strrchr (); + + /* memrchr. */ + test_memrchr (); + + /* rindex - just like strrchr. */ + test_rindex (); + + /* strpbrk - somewhat like strchr. */ + test_strpbrk (); + + /* strstr - somewhat like strchr. */ + test_strstr (); + + /* strspn. */ + test_strspn (); + + /* strcspn. */ + test_strcspn (); + + /* strtok - the hard one. */ + test_strtok (); + + /* strtok_r. */ + test_strtok_r (); + + /* strsep. */ + test_strsep (); + + /* memcmp. */ + test_memcmp (); + + /* memchr. */ + test_memchr (); + + /* memcpy - need not work for overlap. */ + test_memcpy (); + + /* memmove - must work on overlap. */ + test_memmove (); + + /* mempcpy */ + test_mempcpy (); + + /* memccpy. */ + test_memccpy (); + + /* memset. */ + test_memset (); + + /* bcopy. */ + test_bcopy (); + + /* bzero. */ + test_bzero (); + + /* bcmp - somewhat like memcmp. */ + test_bcmp (); + + /* strndup. */ + test_strndup (); + + /* strerror - VERY system-dependent. */ + test_strerror (); + + /* strcasecmp. Without locale dependencies. */ + test_strcasecmp (); + + /* strncasecmp. Without locale dependencies. */ + test_strncasecmp (); + + if (errors == 0) + { + status = EXIT_SUCCESS; + puts("No errors."); + } + else + { + status = EXIT_FAILURE; + printf("%Zd errors.\n", errors); + } + + return status; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/string/tst-bswap.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/string/tst-bswap.c new file mode 100644 index 00000000..b2b4ef08 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/string/tst-bswap.c @@ -0,0 +1,74 @@ +/* Copyright (C) 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include + +extern unsigned long long int wash (unsigned long long int a); + +int +main (void) +{ + int result = 0; + + /* Test the functions with constant arguments. */ + if (bswap_16 (0x1234) != 0x3412) + { + puts ("bswap_16 (constant) flunked"); + result = 1; + } + if (bswap_32 (0x12345678) != 0x78563412) + { + puts ("bswap_32 (constant) flunked"); + result = 1; + } + if (bswap_64 (0x1234567890abcdefULL) != 0xefcdab9078563412ULL) + { + puts ("bswap_64 (constant) flunked"); + result = 1; + } + + /* Test the functions with non-constant arguments. */ + if (bswap_16 (wash (0x1234)) != 0x3412) + { + puts ("bswap_16 (non-constant) flunked"); + result = 1; + } + if (bswap_32 (wash (0x12345678)) != 0x78563412) + { + puts ("bswap_32 (non-constant) flunked"); + result = 1; + } + if (bswap_64 (wash (0x1234567890abcdefULL)) != 0xefcdab9078563412ULL) + { + puts ("bswap_64 (non-constant) flunked"); + result = 1; + } + + return result; +} + + +unsigned long long int +wash (unsigned long long int a) +{ + /* Do nothing. This function simply exists to avoid that the compiler + regards the argument to the bswap_*() functions as constant. */ + return a + 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/string/tst-inlcall.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/string/tst-inlcall.c new file mode 100644 index 00000000..2a4124ea --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/string/tst-inlcall.c @@ -0,0 +1,83 @@ +/* Tester for calling inline string functions. + Copyright (C) 1998, 2000, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif + +/* Make sure we test the optimized inline functions. */ +#define __USE_STRING_INLINES 1 + +#include +#include +#include +#include +#include +#include + + +int +main (void) +{ + int status; + int errors = 0; + char buf1[1000]; + char *cp; + char ch; + + cp = strcpy (buf1, "hello world"); + if (strcmp ("hello world", cp++) != 0) + { + puts ("strcmp test 1 failed"); + ++errors; + } + + cp = buf1; + if (strcmp (cp++, "hello world") != 0) + { + puts ("strcmp test 2 failed"); + ++errors; + } + + ch = 'h'; + if (strchr ("hello world", ch++) == NULL) + { + puts ("strchr test 1 failed"); + ++errors; + } + + const char * const hw = "hello world"; + if (strpbrk (hw, "o") - hw != 4) + { + puts ("strpbrk test 1 failed"); + ++errors; + } + + if (errors == 0) + { + status = EXIT_SUCCESS; + puts ("No errors."); + } + else + { + status = EXIT_FAILURE; + printf ("%d errors.\n", errors); + } + return status; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/string/tst-strlen.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/string/tst-strlen.c new file mode 100644 index 00000000..a1e11592 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/string/tst-strlen.c @@ -0,0 +1,45 @@ +/* Make sure we don't test the optimized inline functions if we want to + test the real implementation. */ +#undef __USE_STRING_INLINES + +#include +#include + +int +main(int argc, char *argv[]) +{ + static const size_t lens[] = { 0, 1, 0, 2, 0, 1, 0, 3, + 0, 1, 0, 2, 0, 1, 0, 4 }; + char basebuf[24 + 32]; + size_t base; + + for (base = 0; base < 32; ++base) + { + char *buf = basebuf + base; + size_t words; + + for (words = 0; words < 4; ++words) + { + size_t last; + memset (buf, 'a', words * 4); + + for (last = 0; last < 16; ++last) + { + buf[words * 4 + 0] = (last & 1) != 0 ? 'b' : '\0'; + buf[words * 4 + 1] = (last & 2) != 0 ? 'c' : '\0'; + buf[words * 4 + 2] = (last & 4) != 0 ? 'd' : '\0'; + buf[words * 4 + 3] = (last & 8) != 0 ? 'e' : '\0'; + buf[words * 4 + 4] = '\0'; + + if (strlen (buf) != words * 4 + lens[last] + || strnlen (buf, -1) != words * 4 + lens[last]) + { + printf ("failed for base=%Zu, words=%Zu, and last=%Zu\n", + base, words, last); + return 1; + } + } + } + } + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/string/tst-strtok.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/string/tst-strtok.c new file mode 100644 index 00000000..7e34aeef --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/string/tst-strtok.c @@ -0,0 +1,23 @@ +/* Testcase for strtok reported by Andrew Church . */ +#include +#include + +int +main (void) +{ + char buf[1] = { 0 }; + int result = 0; + + if (strtok (buf, " ") != NULL) + { + puts ("first strtok call did not return NULL"); + result = 1; + } + else if (strtok (NULL, " ") != NULL) + { + puts ("second strtok call did not return NULL"); + result = 1; + } + + return result; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/string/tst-strxfrm.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/string/tst-strxfrm.c new file mode 100644 index 00000000..ff1b396b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/string/tst-strxfrm.c @@ -0,0 +1,80 @@ +/* Based on a test case by Paul Eggert. */ +#include +#ifdef __UCLIBC_HAS_XLOCALE__ +#include +#include +#include +#include + + +char const string[] = ""; + + +static int +test (const char *locale) +{ + size_t bufsize; + size_t r; + size_t l; + char *buf; + locale_t loc; + int result = 0; + + if (setlocale (LC_COLLATE, locale) == NULL) + { + printf ("cannot set locale \"%s\"\n", locale); + return 1; + } + bufsize = strxfrm (NULL, string, 0) + 1; + buf = malloc (bufsize); + if (buf == NULL) + { + printf ("cannot allocate %zd bytes\n", bufsize); + return 1; + } + r = strxfrm (buf, string, bufsize); + l = strlen (buf); + if (r != l) + { + printf ("locale \"%s\": strxfrm returned %zu, strlen returned %zu\n", + locale, r, l); + result = 1; + } + + loc = newlocale (1 << LC_ALL, locale, NULL); + + r = strxfrm_l (buf, string, bufsize, loc); + l = strlen (buf); + if (r != l) + { + printf ("locale \"%s\": strxfrm_l returned %zu, strlen returned %zu\n", + locale, r, l); + result = 1; + } + + freelocale (loc); + + free (buf); + + return result; +} + + +int +main (void) +{ + int result = 0; + + result |= test ("C"); + result |= test ("en_US.ISO-8859-1"); + result |= test ("de_DE.UTF-8"); + + return result; +} + +#else +int main(void) +{ + return 0; +} +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/termios/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/test/termios/Makefile new file mode 100644 index 00000000..926e0521 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/termios/Makefile @@ -0,0 +1,7 @@ +# uClibc termios tests +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + +top_builddir=../../ +include ../Rules.mak +-include Makefile.in +include ../Test.mak diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/termios/termios.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/termios/termios.c new file mode 100644 index 00000000..5fbc344c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/termios/termios.c @@ -0,0 +1,25 @@ +#include +#include +#include +#include +#include +#include + +int main(int argc,char *argv[]) +{ + struct termios t; + int ret; + + printf("TCGETS = 0x%08x\n",TCGETS); + printf("sizeof(struct termios) = %ld\n",(long)sizeof(struct termios)); + + ret = ioctl(fileno(stdout),TCGETS,&t); + + if(ret<0){ + perror("ioctl"); + }else{ + printf("ioctl returned %d\n",ret); + } + + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/test-skeleton.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/test-skeleton.c new file mode 100644 index 00000000..75215840 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/test-skeleton.c @@ -0,0 +1,411 @@ +/* Skeleton for test programs. + Copyright (C) 1998,2000-2004, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* The test function is normally called `do_test' and it is called + with argc and argv as the arguments. We nevertheless provide the + possibility to overwrite this name. */ +#ifndef TEST_FUNCTION +# define TEST_FUNCTION do_test (argc, argv) +#endif + +#ifndef TEST_DATA_LIMIT +# define TEST_DATA_LIMIT (64 << 20) /* Data limit (bytes) to run with. */ +#endif + +#define OPT_DIRECT 1000 +#define OPT_TESTDIR 1001 + +static struct option options[] = +{ +#ifdef CMDLINE_OPTIONS + CMDLINE_OPTIONS +#endif + { "direct", no_argument, NULL, OPT_DIRECT }, + { "test-dir", required_argument, NULL, OPT_TESTDIR }, + { NULL, 0, NULL, 0 } +}; + +/* PID of the test itself. */ +static pid_t pid; + +/* Directory to place temporary files in. */ +static const char *test_dir; + +/* List of temporary files. */ +struct temp_name_list +{ + struct qelem q; + const char *name; +} *temp_name_list; + +/* Add temporary files in list. */ +static void +__attribute__ ((unused)) +add_temp_file (const char *name) +{ + struct temp_name_list *newp + = (struct temp_name_list *) calloc (sizeof (*newp), 1); + if (newp != NULL) + { + newp->name = name; + if (temp_name_list == NULL) + temp_name_list = (struct temp_name_list *) &newp->q; + else + insque (newp, temp_name_list); + } +} + +/* Delete all temporary files. */ +static void +delete_temp_files (void) +{ + while (temp_name_list != NULL) + { + remove (temp_name_list->name); + temp_name_list = (struct temp_name_list *) temp_name_list->q.q_forw; + } +} + +/* Create a temporary file. */ +static int +__attribute__ ((unused)) +create_temp_file (const char *base, char **filename) +{ + char *fname; + int fd; + + fname = (char *) malloc (strlen (test_dir) + 1 + strlen (base) + + sizeof ("XXXXXX")); + if (fname == NULL) + { + puts ("out of memory"); + return -1; + } + strcpy (stpcpy (stpcpy (stpcpy (fname, test_dir), "/"), base), "XXXXXX"); + + fd = mkstemp (fname); + if (fd == -1) + { + printf ("cannot open temporary file '%s': %s\n", fname, strerror(errno)); + free (fname); + return -1; + } + + add_temp_file (fname); + if (filename != NULL) + *filename = fname; + + return fd; +} + +/* Timeout handler. We kill the child and exit with an error. */ +static void +__attribute__ ((noreturn)) +timeout_handler (int sig __attribute__ ((unused))) +{ + int killed = 0; + int status; + int i; + + /* Send signal. */ + kill (pid, SIGKILL); + + /* Wait for it to terminate. */ + for (i = 0; i < 5; ++i) + { + struct timespec ts; + killed = waitpid (pid, &status, WNOHANG|WUNTRACED); + if (killed != 0) + break; + + /* Delay, give the system time to process the kill. If the + nanosleep() call return prematurely, all the better. We + won't restart it since this probably means the child process + finally died. */ + ts.tv_sec = 0; + ts.tv_nsec = 100000000; + nanosleep (&ts, NULL); + } + if (killed != 0 && killed != pid) + { + perror ("Failed to kill test process"); + exit (1); + } + +#ifdef CLEANUP_HANDLER + CLEANUP_HANDLER; +#endif + + /* If we expected this signal: good! */ +#ifdef EXPECTED_SIGNAL + if (EXPECTED_SIGNAL == SIGALRM) + exit (0); +#endif + + if (killed == 0 || (WIFSIGNALED (status) && WTERMSIG (status) == SIGKILL)) + fputs ("Timed out: killed the child process\n", stderr); + else if (WIFSTOPPED (status)) + fprintf (stderr, "Timed out: the child process was %s\n", + strsignal (WSTOPSIG (status))); + else if (WIFSIGNALED (status)) + fprintf (stderr, "Timed out: the child process got signal %s\n", + strsignal (WTERMSIG (status))); + else + fprintf (stderr, "Timed out: killed the child process but it exited %d\n", + WEXITSTATUS (status)); + + /* Exit with an error. */ + exit (1); +} + +static void +__attribute__ ((noreturn)) +handler_killpid(int sig) +{ + kill(pid, SIGKILL); /* kill test */ + signal(sig, SIG_DFL); + raise(sig); /* kill ourself */ + _exit(128 + sig); /* paranoia */ +} + +/* We provide the entry point here. */ +int +main (int argc, char *argv[]) +{ +#ifdef __ARCH_USE_MMU__ + int direct = 0; /* Directly call the test function? */ +#else + int direct = 1; +#endif + int status; + int opt; + unsigned int timeoutfactor = 1; + pid_t termpid; + char *envstr_timeoutfactor; + + /* Make uses of freed and uninitialized memory known. */ +#ifdef __MALLOC_STANDARD__ +#ifndef M_PERTURB +# define M_PERTURB -6 +#endif + mallopt (M_PERTURB, 42); +#endif + +#ifdef STDOUT_UNBUFFERED + setbuf (stdout, NULL); +#endif + + while ((opt = getopt_long (argc, argv, "+", options, NULL)) != -1) + switch (opt) + { + case '?': + exit (1); + case OPT_DIRECT: + direct = 1; + break; + case OPT_TESTDIR: + test_dir = optarg; + break; +#ifdef CMDLINE_PROCESS + CMDLINE_PROCESS +#endif + } + + /* If set, read the test TIMEOUTFACTOR value from the environment. + This value is used to scale the default test timeout values. */ + envstr_timeoutfactor = getenv ("TIMEOUTFACTOR"); + if (envstr_timeoutfactor != NULL) + { + char *envstr_conv = envstr_timeoutfactor; + unsigned long int env_fact; + + env_fact = strtoul (envstr_timeoutfactor, &envstr_conv, 0); + if (*envstr_conv == '\0' && envstr_conv != envstr_timeoutfactor) + timeoutfactor = MAX (env_fact, 1); + } + + /* Set TMPDIR to specified test directory. */ + if (test_dir != NULL) + { + setenv ("TMPDIR", test_dir, 1); + + if (chdir (test_dir) < 0) + { + perror ("chdir"); + exit (1); + } + } + else + { + test_dir = getenv ("TMPDIR"); + if (test_dir == NULL || test_dir[0] == '\0') + test_dir = "/tmp"; + } + + /* Make sure we see all message, even those on stdout. */ + setvbuf (stdout, NULL, _IONBF, 0); + + /* make sure temporary files are deleted. */ + atexit (delete_temp_files); + + /* Correct for the possible parameters. */ + argv[optind - 1] = argv[0]; + argv += optind - 1; + argc -= optind - 1; + + /* Call the initializing function, if one is available. */ +#ifdef PREPARE + PREPARE (argc, argv); +#endif + + /* If we are not expected to fork run the function immediately. */ + if (direct) + return TEST_FUNCTION; + + /* Set up the test environment: + - prevent core dumps + - set up the timer + - fork and execute the function. */ + +#if defined __ARCH_USE_MMU__ || ! defined __UCLIBC__ + pid = fork (); + if (pid == 0) + { + /* This is the child. */ +#ifdef RLIMIT_DATA + struct rlimit data_limit; +#endif +#ifdef RLIMIT_CORE + /* Try to avoid dumping core. */ + struct rlimit core_limit; + core_limit.rlim_cur = 0; + core_limit.rlim_max = 0; + setrlimit (RLIMIT_CORE, &core_limit); +#endif + +#ifdef RLIMIT_DATA + /* Try to avoid eating all memory if a test leaks. */ + if (getrlimit (RLIMIT_DATA, &data_limit) == 0) + { + if (TEST_DATA_LIMIT == RLIM_INFINITY) + data_limit.rlim_cur = data_limit.rlim_max; + else if (data_limit.rlim_cur > (rlim_t) TEST_DATA_LIMIT) + data_limit.rlim_cur = MIN ((rlim_t) TEST_DATA_LIMIT, + data_limit.rlim_max); + if (setrlimit (RLIMIT_DATA, &data_limit) < 0) + perror ("setrlimit: RLIMIT_DATA"); + } + else + perror ("getrlimit: RLIMIT_DATA"); +#endif + + /* We put the test process in its own pgrp so that if it bogusly + generates any job control signals, they won't hit the whole build. */ + setpgid (0, 0); + + /* Execute the test function and exit with the return value. */ + exit (TEST_FUNCTION); + } + else if (pid < 0) +#endif + { + perror ("Cannot fork test program"); + exit (1); + } + + signal (SIGTERM, handler_killpid); + signal (SIGINT, handler_killpid); + signal (SIGQUIT, handler_killpid); + + /* Set timeout. */ +#ifndef TIMEOUT + /* Default timeout is two seconds. */ +# define TIMEOUT 2 +#endif + signal (SIGALRM, timeout_handler); + alarm (TIMEOUT * timeoutfactor); + + /* Wait for the regular termination. */ + termpid = TEMP_FAILURE_RETRY (waitpid (pid, &status, 0)); + if (termpid == -1) + { + printf ("Waiting for test program failed: %s\n", strerror(errno)); + exit (1); + } + if (termpid != pid) + { + printf ("Oops, wrong test program terminated: expected %ld, got %ld\n", + (long int) pid, (long int) termpid); + exit (1); + } + +#ifndef EXPECTED_SIGNAL + /* We don't expect any signal. */ +# define EXPECTED_SIGNAL 0 +#endif + if (WTERMSIG (status) != EXPECTED_SIGNAL) + { + if (EXPECTED_SIGNAL != 0) + { + if (WTERMSIG (status) == 0) + fprintf (stderr, + "Expected signal '%s' from child, got none\n", + strsignal (EXPECTED_SIGNAL)); + else + fprintf (stderr, + "Incorrect signal from child: got `%s', need `%s'\n", + strsignal (WTERMSIG (status)), + strsignal (EXPECTED_SIGNAL)); + } + else + fprintf (stderr, "Didn't expect signal from child: got `%s'\n", + strsignal (WTERMSIG (status))); + exit (1); + } + + /* Simply exit with the return value of the test. */ +#ifndef EXPECTED_STATUS + return WEXITSTATUS (status); +#else + if (WEXITSTATUS (status) != EXPECTED_STATUS) + { + fprintf (stderr, "Expected status %d, got %d\n", + EXPECTED_STATUS, WEXITSTATUS (status)); + exit (1); + } + + return 0; +#endif +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/testsuite.h b/l4/pkg/uclibc/lib/contrib/uclibc/test/testsuite.h new file mode 100644 index 00000000..afc45b0c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/testsuite.h @@ -0,0 +1,100 @@ +/* vi: set sw=4 ts=4: */ +/* + * Some simple macros for use in test applications. + * Copyright (C) 2000-2006 by Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#ifndef TESTSUITE_H +#define TESTSUITE_H + +#ifdef __NO_TESTCODE__ +extern size_t test_number; +#endif + +extern void init_testsuite(const char* testname); +extern void done_testing(void) __attribute__((noreturn)); +extern void success_msg(int result, const char* command); +extern void error_msg(int result, int line, const char* file, const char* command); + +#ifndef __NO_TESTCODE__ + +size_t test_number = 0; +static int failures = 0; + +void error_msg(int result, int line, const char* file, const char* command) +{ + failures++; + + printf("\nFAILED TEST %lu: \n\t%s\n", (unsigned long)test_number, command); + printf("AT LINE: %d, FILE: %s\n\n", line, file); +} + +void success_msg(int result, const char* command) +{ +#if 0 + printf("passed test: %s == 0\n", command); +#endif +} + +void done_testing(void) +{ + if (0 < failures) { + printf("Failed %d tests\n", failures); + exit(EXIT_FAILURE); + } else { + printf("All functions tested sucessfully\n"); + exit(EXIT_SUCCESS); + } +} + +void init_testsuite(const char* testname) +{ + printf("%s", testname); + test_number = 0; + failures = 0; +#if !defined(__UCLIBC__) || defined(__UCLIBC_DYNAMIC_ATEXIT__) + atexit(done_testing); +#endif +} + +#endif /* __NO_TESTCODE__ */ + + +#define TEST_STRING_OUTPUT(command, expected_result) \ + do { \ + int result = strcmp(command, expected_result); \ + test_number++; \ + if (result == expected_result) { \ + success_msg(result, "command"); \ + } else { \ + error_msg(result, __LINE__, __FILE__, command); \ + }; \ + } while (0) + +#define TEST_NUMERIC(command, expected_result) \ + do { \ + int result = (command); \ + test_number++; \ + if (result == expected_result) { \ + success_msg(result, # command); \ + } else { \ + error_msg(result, __LINE__, __FILE__, # command); \ + }; \ + } while (0) + +#define TEST(command) \ + do { \ + int result = (command); \ + test_number++; \ + if (result == 1) { \ + success_msg(result, # command); \ + } else { \ + error_msg(result, __LINE__, __FILE__, # command); \ + }; \ + } while (0) + +#define STR_CMD(cmd) cmd + +#endif /* TESTSUITE_H */ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/time/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/test/time/Makefile new file mode 100644 index 00000000..103acb88 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/time/Makefile @@ -0,0 +1,7 @@ +# uClibc time tests +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + +top_builddir=../../ +include ../Rules.mak +-include Makefile.in +include ../Test.mak diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/time/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/test/time/Makefile.in new file mode 100644 index 00000000..05f73a45 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/time/Makefile.in @@ -0,0 +1,12 @@ +# uClibc time tests +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + +TESTS_DISABLED := bug-asctime bug-asctime_r time tst-mktime2 tst-posixtz \ + tst-strftime tst-strptime tst-timezone + +ifneq ($(UCLIBC_HAS_XLOCALE),y) +TESTS_DISABLED += tst-ftime_l +endif + +CFLAGS_tst-strptime2 := -std=c99 +DODIFF_futimens1 := 1 diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/time/bug-asctime.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/time/bug-asctime.c new file mode 100644 index 00000000..149e4e0a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/time/bug-asctime.c @@ -0,0 +1,40 @@ +/* Note: we disable this on uClibc because we dont bother + * verifying if the year is sane ... we just return ???? + * for the year value ... + */ + +#include +#include +#include +#include + + +static int +do_test (void) +{ + int result = 0; + time_t t = time (NULL); + struct tm *tp = localtime (&t); + tp->tm_year = INT_MAX; + errno = 0; + char *s = asctime (tp); + if (s != NULL || errno != EOVERFLOW) + { + printf ("asctime did not fail correctly: s=%p, wanted %p; errno=%i, wanted %i\n", + s, NULL, errno, EOVERFLOW); + result = 1; + } + char buf[1000]; + errno = 0; + s = asctime_r (tp, buf); + if (s != NULL || errno != EOVERFLOW) + { + printf ("asctime_r did not fail correctly: s=%p, wanted %p; errno=%i, wanted %i\n", + s, NULL, errno, EOVERFLOW); + result = 1; + } + return result; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/time/bug-asctime_r.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/time/bug-asctime_r.c new file mode 100644 index 00000000..1fcc4659 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/time/bug-asctime_r.c @@ -0,0 +1,37 @@ +/* Note: we disable this on uClibc because we dont bother + * verifying if the year is sane ... we just return ???? + * for the year value ... + */ + +#include +#include +#include +#include + + +static int +do_test (void) +{ + int result = 0; + time_t t = time (NULL); + struct tm *tp = localtime (&t); + tp->tm_year = 10000 - 1900; + char buf[1000]; + errno = 0; + buf[26] = '\xff'; + char *s = asctime_r (tp, buf); + if (s != NULL || errno != EOVERFLOW) + { + puts ("asctime_r did not fail correctly"); + result = 1; + } + if (buf[26] != '\xff') + { + puts ("asctime_r overwrote 27th byte in buffer"); + result = 1; + } + return result; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/time/clocktest.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/time/clocktest.c new file mode 100644 index 00000000..a5b2c09e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/time/clocktest.c @@ -0,0 +1,36 @@ +#include +#include +#include +#include +#include + +volatile int gotit = 0; + +static void +alarm_handler (int signum) +{ + gotit = 1; +} + + +int +main (int argc, char ** argv) +{ + clock_t start, stop; + + if (signal(SIGALRM, alarm_handler) == SIG_ERR) + { + perror ("signal"); + exit (1); + } + alarm(1); + start = clock (); + while (!gotit); + stop = clock (); + + printf ("%ld clock ticks per second (start=%ld,stop=%ld)\n", + stop - start, start, stop); + printf ("CLOCKS_PER_SEC=%ld, sysconf(_SC_CLK_TCK)=%ld\n", + CLOCKS_PER_SEC, sysconf(_SC_CLK_TCK)); + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/time/test_time.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/time/test_time.c new file mode 100644 index 00000000..2ce819a3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/time/test_time.c @@ -0,0 +1,116 @@ +/* Copyright (C) 1991, 1992, 1994, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + + +int +main (int argc, char **argv) +{ + time_t t; + register struct tm *tp; + struct tm tbuf; + int lose = 0; + + --argc; + ++argv; + + do + { + char buf[BUFSIZ]; + if (argc > 0) + { + static char tzenvbuf[BUFSIZ]; + sprintf(tzenvbuf, "TZ=%s", *argv); + if (putenv(tzenvbuf)) + { + puts("putenv failed."); + lose = 1; + } + else + puts (tzenvbuf); + } + tzset(); + tbuf.tm_year = 72; + tbuf.tm_mon = 0; + tbuf.tm_mday = 31; + tbuf.tm_hour = 6; + tbuf.tm_min = 14; + tbuf.tm_sec = 50; + tbuf.tm_isdst = -1; + doit:; + t = mktime(&tbuf); + if (t == (time_t) -1) + { + puts("mktime() failed?"); + lose = 1; + } + tp = localtime(&t); + if (tp == NULL) + { + puts("localtime() failed."); + lose = 1; + } + else if (strftime(buf, sizeof(buf), "%a %b %d %X %Z %Y", tp) == 0) + { + puts("strftime() failed."); + lose = 1; + } + else + puts(buf); + if (tbuf.tm_year == 101) + { + tbuf.tm_year = 97; + tbuf.tm_mon = 0; + goto doit; + } + ++argv; + } while (--argc > 0); + + { +#define SIZE 256 + char buffer[SIZE]; + time_t curtime; + struct tm *loctime; + + curtime = time (NULL); + + loctime = localtime (&curtime); + + fputs (asctime (loctime), stdout); + + strftime (buffer, SIZE, "Today is %A, %B %d.\n", loctime); + fputs (buffer, stdout); + strftime (buffer, SIZE, "The time is %I:%M %p.\n", loctime); + fputs (buffer, stdout); + + loctime->tm_year = 72; + loctime->tm_mon = 8; + loctime->tm_mday = 12; + loctime->tm_hour = 20; + loctime->tm_min = 49; + loctime->tm_sec = 05; + curtime = mktime (loctime); + strftime (buffer, SIZE, "%D %T was %w the %jth.\n", loctime); + fputs (buffer, stdout); + } + + return (lose ? EXIT_FAILURE : EXIT_SUCCESS); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/time/time.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/time/time.c new file mode 100644 index 00000000..a4d68d50 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/time/time.c @@ -0,0 +1,76 @@ +#include +#include +#include + +/* We use this instead of memcmp because some broken C libraries + * add additional nonstandard fields to struct tm... */ + +int tm_cmp(struct tm tm1, struct tm tm2) +{ + return tm1.tm_sec != tm2.tm_sec || + tm1.tm_min != tm2.tm_min || + tm1.tm_hour != tm2.tm_hour || + tm1.tm_mday != tm2.tm_mday || + tm1.tm_mon != tm2.tm_mon || + tm1.tm_year != tm2.tm_year || + tm1.tm_wday != tm2.tm_wday || + tm1.tm_yday != tm2.tm_yday || + tm1.tm_isdst!= tm2.tm_isdst; +} + +char *tm_str(struct tm tm) +{ + static int i; + static char b[4][64]; + i = (i+1)%4; + snprintf(b[i], sizeof b[i], + "s=%.2d m=%.2d h=%.2d mday=%.2d mon=%.2d year=%.4d wday=%d yday=%d isdst=%d", + tm.tm_sec, tm.tm_min, tm.tm_hour, + tm.tm_mday, tm.tm_mon, tm.tm_year, + tm.tm_wday, tm.tm_yday, tm.tm_isdst); + return b[i]; +} + +#define TM(ss,mm,hh,md,mo,yr,wd,yd,dst) (struct tm){ \ + .tm_sec = ss, .tm_min = mm, .tm_hour = hh, \ + .tm_mday = md, .tm_mon = mo, .tm_year = yr, \ + .tm_wday = wd, .tm_yday = yd, .tm_isdst = dst } + +#define TM_EPOCH TM(0,0,0,1,0,70,4,0,0) +#define TM_Y2038_1S TM(7,14,3,19,0,138,2,18,0) +#define TM_Y2038 TM(8,14,3,19,0,138,2,18,0) + +#define TEST_TM(r,x,m) (!tm_cmp((r),(x)) || \ +(printf(__FILE__ ":%d: %s failed:\n\tresult: %s\n\texpect: %s\n", __LINE__, \ +m, tm_str((r)), tm_str((x))), err++, 0) ) + +#define TEST(r, f, x, m) ( \ +((r) = (f)) == (x) || \ +(printf(__FILE__ ":%d: %s failed (" m ")\n", __LINE__, #f, r, x), err++, 0) ) + +int main(void) +{ + struct tm tm, *tm_p; + time_t t; + int err=0; + + putenv("TZ=GMT"); + tzset(); + + t=0; tm_p = gmtime(&t); + TEST_TM(*tm_p, TM_EPOCH, "gmtime(0)"); + + tm = TM_Y2038_1S; + t = mktime(&tm); + tm = *(gmtime(&t)); + TEST_TM(*tm_p, TM_Y2038_1S, "mktime/gmtime(Y2038-1)"); + + tm = TM_Y2038; + t = mktime(&tm); + tm = *(gmtime(&t)); + TEST_TM(*tm_p, TM_Y2038, "mktime/gmtime(Y2038)"); + + /* FIXME: set a TZ var and check DST boundary conditions */ + + return err; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/time/tst-ctime.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/time/tst-ctime.c new file mode 100644 index 00000000..91d827aa --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/time/tst-ctime.c @@ -0,0 +1,44 @@ +/* vi: set sw=4 ts=4: */ +/* testcase for ctime(3) with large time + * Copyright (C) 2010 David A Ramos + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include + +#define MAX_POSITIVE(type) (~0 & ~((type) 1 << (sizeof(type)*8 - 1))) + +int do_test(int argc, char **argv) { + char *correct = 0, *s; + int status; + + /* need a very high positive number (e.g., max - 1024) */ + time_t test = MAX_POSITIVE(time_t) - 1024; + + s = asctime(localtime(&test)); + + if (s) { + // copy static buffer to heap + correct = malloc(strlen(s)+1); + strcpy(correct, s); + } + + s = ctime(&test); + + printf("ANSI:\t%suClibc:\t%s", correct, s); + + if (s != correct && strcmp(correct, s)) + status = EXIT_FAILURE; + else + status = EXIT_SUCCESS; + + if (correct) + free(correct); + + return status; +} + +#include diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/time/tst-ftime_l.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/time/tst-ftime_l.c new file mode 100644 index 00000000..95017f1f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/time/tst-ftime_l.c @@ -0,0 +1,136 @@ +#include +#include +#include +#include +#include +#ifdef __UCLIBC_HAS_XLOCALE__ +#include +#include + + +int +main (void) +{ + locale_t l; + locale_t old; + struct tm tm; + char buf[1000]; + wchar_t wbuf[1000]; + int result = 0; + size_t n; + + l = newlocale (LC_ALL_MASK, "de_DE.ISO-8859-1", NULL); + if (l == NULL) + { + puts ("newlocale failed"); + exit (1); + } + + memset (&tm, '\0', sizeof (tm)); + + tm.tm_year = 102; + tm.tm_mon = 2; + tm.tm_mday = 1; + + if (strftime (buf, sizeof (buf), "%e %^B %Y", &tm) == 0) + { + puts ("initial strftime failed"); + exit (1); + } + if (strcmp (buf, " 1 MARCH 2002") != 0) + { + printf ("initial strftime: expected \"%s\", got \"%s\"\n", + " 1 MARCH 2002", buf); + result = 1; + } + else + printf ("got \"%s\"\n", buf); + + /* Now using the extended locale model. */ + if (strftime_l (buf, sizeof (buf), "%e %^B %Y", &tm, l) == 0) + { + puts ("strftime_l failed"); + result = 1; + } + else if (strcmp (buf, " 1 M\xc4RZ 2002") != 0) + { + printf ("strftime_l: expected \"%s\", got \"%s\"\n", + " 1 M\xc4RZ 2002", buf); + result = 1; + } + else + { + setlocale (LC_ALL, "de_DE.ISO-8859-1"); + printf ("got \"%s\"\n", buf); + setlocale (LC_ALL, "C"); + } + + /* And the wide character version. */ + if (wcsftime_l (wbuf, sizeof (wbuf) / sizeof (wbuf[0]), L"%e %^B %Y", &tm, l) + == 0) + { + puts ("wcsftime_l failed"); + result = 1; + } + else if (wcscmp (wbuf, L" 1 M\x00c4RZ 2002") != 0) + { + printf ("wcsftime_l: expected \"%ls\", got \"%ls\"\n", + L" 1 M\x00c4RZ 2002", wbuf); + result = 1; + } + else + { + setlocale (LC_ALL, "de_DE.ISO-8859-1"); + printf ("got \"%ls\"\n", wbuf); + setlocale (LC_ALL, "C"); + } + + old = uselocale (l); + + n = strftime (buf, sizeof (buf), "%e %^B %Y", &tm); + + /* Switch back. */ + (void) uselocale (old); + + if (n == 0) + { + puts ("strftime after first uselocale failed"); + result = 1; + } + else if (strcmp (buf, " 1 M\xc4RZ 2002") != 0) + { + printf ("strftime in non-C locale: expected \"%s\", got \"%s\"\n", + " 1 M\xc4RZ 2002", buf); + result = 1; + } + else + { + setlocale (LC_ALL, "de_DE.ISO-8859-1"); + printf ("got \"%s\"\n", buf); + setlocale (LC_ALL, "C"); + } + + if (strftime (buf, sizeof (buf), "%e %^B %Y", &tm) == 0) + { + puts ("strftime after second uselocale failed"); + result = 1; + } + else if (strcmp (buf, " 1 MARCH 2002") != 0) + { + printf ("initial strftime: expected \"%s\", got \"%s\"\n", + " 1 MARCH 2002", buf); + result = 1; + } + else + printf ("got \"%s\"\n", buf); + + return result; +} + +#else +int main(void) +{ + puts("Test requires WCHAR support; skipping"); + return 0; +} +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/time/tst-futimens1.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/time/tst-futimens1.c new file mode 100644 index 00000000..ed7f44fe --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/time/tst-futimens1.c @@ -0,0 +1,105 @@ +/* vi: set sw=4 ts=4: */ +/* testcase for futimens(2) + * Copyright (C) 2009 Bernhard Reutner-Fischer + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ +#include +#include +#include +#include +#include +#include +#include + +struct +{ + char *name; /* name of file to open */ + int flags; /* flags for file descriptor */ + const struct timespec ts[2]; + int err; /* expected errno */ +} tests [] = +{ + {"futimens.tst", (O_CREAT|O_TRUNC), {{0,0},{0,0}}, 0}, + {"futimens.tst", (O_CREAT|O_TRUNC), {{99,0},{0,0}}, 0}, + {"futimens.tst", (O_CREAT|O_TRUNC), {{0,99},{0,0}}, 0}, + {"futimens.tst", (O_CREAT|O_TRUNC), {{0,0},{99,0}}, 0}, + {"futimens.tst", (O_CREAT|O_TRUNC), {{0,0},{0,99}}, 0}, + {"futimens.tst", (O_CREAT|O_TRUNC), {{11,2},{3,4}}, 0}, +}; +int do_test(int argc, char **argv) { + char *name; + int i, errors; + errors = argc - argc + 0; + unsigned has_stat_nsec = 0; + { + struct stat probe; + /* Let's attempt an educated guess if this filesystem supports + * nanosecond mtime. */ + if ((!stat(".", &probe)) && probe.st_mtim.tv_nsec) + has_stat_nsec = 1; + else if ((!stat(argv[0], &probe)) && probe.st_mtim.tv_nsec) + has_stat_nsec = 1; + } + for (i=0; i < (int) (sizeof(tests)/sizeof(tests[0])); ++i) { + int err, fd; + struct stat sb; + name = tests[i].name; + if (*name != '.') + unlink(name); + fd = open(name, tests[i].flags); + if (fd < 0) + abort(); + errno = 0; + err = futimens(fd, tests[i].ts); + if ((errno && !err) || (!errno && err)) { + err = errno; + printf("FAILED test %d (errno and return value disagree)\n", i); + ++errors; + } else + err = errno; + if (err != tests[i].err) { + printf("FAILED test %d (expected errno %d, got %d)\n", + i, tests[i].err, err); + ++errors; + continue; + } + if (stat(name, &sb) < 0) { + printf("FAILED test %d (verification)\n", i); + ++errors; + continue; + } else { + unsigned wrong = tests[i].ts[0].tv_sec != sb.st_atim.tv_sec || + tests[i].ts[0].tv_nsec != sb.st_atim.tv_nsec || + tests[i].ts[1].tv_sec != sb.st_mtim.tv_sec || + tests[i].ts[1].tv_nsec != sb.st_mtim.tv_nsec; + if (wrong) { + if (tests[i].ts[0].tv_sec != sb.st_atim.tv_sec) { + printf("FAILED test %d (access time, sec: expected %ld, got %ld)\n", + i, tests[i].ts[0].tv_sec, sb.st_atim.tv_sec); + ++errors; + } + if (tests[i].ts[0].tv_nsec != sb.st_atim.tv_nsec) { + printf("FAILED test %d (access time, nsec: expected %ld, got %ld)\n", + i, tests[i].ts[0].tv_nsec, sb.st_atim.tv_nsec); + errors += has_stat_nsec; + } + + if (tests[i].ts[1].tv_sec != sb.st_mtim.tv_sec) { + printf("FAILED test %d (modification time, sec: expected %ld, got %ld)\n", + i, tests[i].ts[1].tv_sec, sb.st_mtim.tv_sec); + ++errors; + } + if (tests[i].ts[1].tv_nsec != sb.st_mtim.tv_nsec) { + printf("FAILED test %d (modification time, nsec: expected %ld, got %ld)\n", + i, tests[i].ts[1].tv_nsec, sb.st_mtim.tv_nsec); + errors += has_stat_nsec; + } + } + } + } + if (*name != '.') + unlink(name); + printf("%d errors.\n", errors); + return (!errors) ? EXIT_SUCCESS : EXIT_FAILURE; +} +#include diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/time/tst-mktime.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/time/tst-mktime.c new file mode 100644 index 00000000..416a8561 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/time/tst-mktime.c @@ -0,0 +1,70 @@ +#include +#include +#include +#include + +int +main (void) +{ + struct tm time_str, *tm; + time_t t; + char daybuf[20]; + int result; + + time_str.tm_year = 2001 - 1900; + time_str.tm_mon = 7 - 1; + time_str.tm_mday = 4; + time_str.tm_hour = 0; + time_str.tm_min = 0; + time_str.tm_sec = 1; + time_str.tm_isdst = -1; + + if (mktime (&time_str) == -1) + { + (void) puts ("-unknown-"); + result = 1; + } + else + { + (void) strftime (daybuf, sizeof (daybuf), "%A", &time_str); + (void) puts (daybuf); + result = strcmp (daybuf, "Wednesday") != 0; + } + + setenv ("TZ", "EST+5", 1); +#define EVENING69 1 * 60 * 60 + 2 * 60 + 29 + t = EVENING69; + tm = localtime (&t); + if (tm == NULL) + { + (void) puts ("localtime returned NULL"); + result = 1; + } + else + { + time_str = *tm; + t = mktime (&time_str); + if (t != EVENING69) + { + printf ("mktime returned %ld, expected %d\n", + (long) t, EVENING69); + result = 1; + } + else + (void) puts ("Dec 31 1969 EST test passed"); + + setenv ("TZ", "CET-1", 1); + t = mktime (&time_str); +#define EVENING69_CET (EVENING69 - (5 - -1) * 60 * 60) + if (t != EVENING69_CET) + { + printf ("mktime returned %ld, expected %ld\n", + (long) t, (long) EVENING69_CET); + result = 1; + } + else + (void) puts ("Dec 31 1969 CET test passed"); + } + + return result; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/time/tst-mktime2.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/time/tst-mktime2.c new file mode 100644 index 00000000..6279218c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/time/tst-mktime2.c @@ -0,0 +1,141 @@ +/* Test program from Paul Eggert and Tony Leneis. */ +#include +#include +#include + +static time_t time_t_max; +static time_t time_t_min; + +/* Values we'll use to set the TZ environment variable. */ +static const char *tz_strings[] = + { + (const char *) 0, "GMT0", "JST-9", + "EST+3EDT+2,M10.1.0/00:00:00,M2.3.0/00:00:00" + }; +#define N_STRINGS ((int) (sizeof (tz_strings) / sizeof (tz_strings[0]))) + +/* Fail if mktime fails to convert a date in the spring-forward gap. + Based on a problem report from Andreas Jaeger. */ +static void +spring_forward_gap (void) +{ + /* glibc (up to about 1998-10-07) failed this test. */ + struct tm tm; + + /* Use the portable POSIX.1 specification "TZ=PST8PDT,M4.1.0,M10.5.0" + instead of "TZ=America/Vancouver" in order to detect the bug even + on systems that don't support the Olson extension, or don't have the + full zoneinfo tables installed. */ + setenv ("TZ", "PST8PDT,M4.1.0,M10.5.0", 1); + + tm.tm_year = 98; + tm.tm_mon = 3; + tm.tm_mday = 5; + tm.tm_hour = 2; + tm.tm_min = 0; + tm.tm_sec = 0; + tm.tm_isdst = -1; + if (mktime (&tm) == (time_t)-1) + exit (1); +} + +static void +mktime_test1 (time_t now) +{ + struct tm *lt = localtime (&now); + if (lt && mktime (lt) != now) + exit (2); +} + +static void +mktime_test (time_t now) +{ + mktime_test1 (now); + mktime_test1 ((time_t) (time_t_max - now)); + mktime_test1 ((time_t) (time_t_min + now)); +} + +static void +irix_6_4_bug (void) +{ + /* Based on code from Ariel Faigon. */ + struct tm tm; + tm.tm_year = 96; + tm.tm_mon = 3; + tm.tm_mday = 0; + tm.tm_hour = 0; + tm.tm_min = 0; + tm.tm_sec = 0; + tm.tm_isdst = -1; + mktime (&tm); + if (tm.tm_mon != 2 || tm.tm_mday != 31) + exit (3); +} + +static void +bigtime_test (int j) +{ + struct tm tm; + time_t now; + tm.tm_year = tm.tm_mon = tm.tm_mday = tm.tm_hour = tm.tm_min = tm.tm_sec = j; + tm.tm_isdst = -1; + now = mktime (&tm); + if (now != (time_t) -1) + { + struct tm *lt = localtime (&now); + if (! (lt + && lt->tm_year == tm.tm_year + && lt->tm_mon == tm.tm_mon + && lt->tm_mday == tm.tm_mday + && lt->tm_hour == tm.tm_hour + && lt->tm_min == tm.tm_min + && lt->tm_sec == tm.tm_sec + && lt->tm_yday == tm.tm_yday + && lt->tm_wday == tm.tm_wday + && ((lt->tm_isdst < 0 ? -1 : 0 < lt->tm_isdst) + == (tm.tm_isdst < 0 ? -1 : 0 < tm.tm_isdst)))) + exit (4); + } +} + +static int +do_test (void) +{ + time_t t, delta; + int i, j; + + setenv ("TZ", "America/Sao_Paulo", 1); + /* This test makes some buggy mktime implementations loop. + Give up after 60 seconds; a mktime slower than that + isn't worth using anyway. */ + alarm (60); + + for (time_t_max = 1; 0 < time_t_max; time_t_max *= 2) + continue; + time_t_max--; + if ((time_t) -1 < 0) + for (time_t_min = -1; (time_t) (time_t_min * 2) < 0; time_t_min *= 2) + continue; + delta = time_t_max / 997; /* a suitable prime number */ + for (i = 0; i < N_STRINGS; i++) + { + if (tz_strings[i]) + setenv ("TZ", tz_strings[i], 1); + + for (t = 0; t <= time_t_max - delta; t += delta) + mktime_test (t); + mktime_test ((time_t) 1); + mktime_test ((time_t) (60 * 60)); + mktime_test ((time_t) (60 * 60 * 24)); + + for (j = 1; 0 < j; j *= 2) + bigtime_test (j); + bigtime_test (j - 1); + } + irix_6_4_bug (); + spring_forward_gap (); + return 0; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/time/tst-mktime3.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/time/tst-mktime3.c new file mode 100644 index 00000000..60d0e0b3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/time/tst-mktime3.c @@ -0,0 +1,50 @@ +/* Test program for mktime bugs with out-of-range tm_sec values. */ + +#include +#include +#include + +struct tm tests[] = +{ + { .tm_sec = -1, .tm_mday = 1, .tm_year = 104 }, + { .tm_sec = 65, .tm_min = 59, .tm_hour = 23, .tm_mday = 31, + .tm_mon = 11, .tm_year = 101 } +}; +struct tm expected[] = +{ + { .tm_sec = 59, .tm_min = 59, .tm_hour = 23, .tm_mday = 31, + .tm_mon = 11, .tm_year = 103, .tm_wday = 3, .tm_yday = 364 }, + { .tm_sec = 5, .tm_mday = 1, .tm_year = 102, .tm_wday = 2 } +}; + +int +main (void) +{ + setenv ("TZ", "UTC", 1); + int i; + for (i = 0; i < sizeof (tests) / sizeof (tests[0]); ++i) + { + if (mktime (&tests[i]) < 0) + { + printf ("mktime %d failed\n", i); + return 1; + } +#define CHECK(name) \ + if (tests[i].name != expected[i].name) \ + { \ + printf ("test %d " #name " got %d expected %d\n", \ + i, tests[i].name, expected[i].name); \ + return 1; \ + } + CHECK (tm_sec) + CHECK (tm_min) + CHECK (tm_hour) + CHECK (tm_mday) + CHECK (tm_mon) + CHECK (tm_year) + CHECK (tm_wday) + CHECK (tm_yday) + CHECK (tm_isdst) + } + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/time/tst-posixtz.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/time/tst-posixtz.c new file mode 100644 index 00000000..ccba63e5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/time/tst-posixtz.c @@ -0,0 +1,88 @@ +#include +#include +#include +#include + +struct +{ + time_t when; + const char *tz; + const char *result; +} tests[] = +{ + { 909312849L, "AEST-10AEDST-11,M10.5.0,M3.5.0", + "1998/10/25 21:54:09 dst=1 zone=AEDST" }, + { 924864849L, "AEST-10AEDST-11,M10.5.0,M3.5.0", + "1999/04/23 20:54:09 dst=0 zone=AEST" }, + { 919973892L, "AEST-10AEDST-11,M10.5.0,M3.5.0", + "1999/02/26 07:18:12 dst=1 zone=AEDST" }, + { 909312849L, "EST+5EDT,M4.1.0/2,M10.5.0/2", + "1998/10/25 05:54:09 dst=0 zone=EST" }, + { 924864849L, "EST+5EDT,M4.1.0/2,M10.5.0/2", + "1999/04/23 06:54:09 dst=1 zone=EDT" }, + { 919973892L, "EST+5EDT,M4.1.0/2,M10.5.0/2", + "1999/02/25 15:18:12 dst=0 zone=EST" }, +}; + +int +main (void) +{ + int result = 0; + size_t cnt; + + for (cnt = 0; cnt < sizeof (tests) / sizeof (tests[0]); ++cnt) + { + char buf[100]; + struct tm *tmp; + + printf ("TZ = \"%s\", time = %ld => ", tests[cnt].tz, tests[cnt].when); + fflush (stdout); + + setenv ("TZ", tests[cnt].tz, 1); + + tmp = localtime (&tests[cnt].when); + + snprintf (buf, sizeof (buf), + "%04d/%02d/%02d %02d:%02d:%02d dst=%d zone=%s", + tmp->tm_year + 1900, tmp->tm_mon + 1, tmp->tm_mday, + tmp->tm_hour, tmp->tm_min, tmp->tm_sec, tmp->tm_isdst, + tzname[tmp->tm_isdst ? 1 : 0]); + + fputs (buf, stdout); + + if (strcmp (buf, tests[cnt].result) == 0) + puts (", OK"); + else + { + result = 1; + puts (", FAIL"); + } + } + + setenv ("TZ", "Universal", 1); + localtime (&tests[0].when); + printf ("TZ = \"Universal\" daylight %d tzname = { \"%s\", \"%s\" }", + daylight, tzname[0], tzname[1]); + if (! daylight) + puts (", OK"); + else + { + result = 1; + puts (", FAIL"); + } + + setenv ("TZ", "AEST-10AEDST-11,M10.5.0,M3.5.0", 1); + tzset (); + printf ("TZ = \"AEST-10AEDST-11,M10.5.0,M3.5.0\" daylight %d" + " tzname = { \"%s\", \"%s\" }", daylight, tzname[0], tzname[1]); + if (daylight + && strcmp (tzname[0], "AEST") == 0 && strcmp (tzname[1], "AEDST") == 0) + puts (", OK"); + else + { + result = 1; + puts (", FAIL"); + } + + return result; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/time/tst-strftime.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/time/tst-strftime.c new file mode 100644 index 00000000..374fba42 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/time/tst-strftime.c @@ -0,0 +1,111 @@ +#include +#include +#include +#include + + +static struct +{ + const char *fmt; + size_t min; + size_t max; +} tests[] = + { + { "%2000Y", 2000, 4000 }, + { "%02000Y", 2000, 4000 }, + { "%_2000Y", 2000, 4000 }, + { "%-2000Y", 2000, 4000 }, + }; +#define ntests (sizeof (tests) / sizeof (tests[0])) + + +static int +do_test (void) +{ + size_t cnt; + int result = 0; + + time_t tnow = time (NULL); + struct tm *now = localtime (&tnow); + + for (cnt = 0; cnt < ntests; ++cnt) + { + size_t size = 0; + int res; + char *buf = NULL; + + do + { + size += 500; + buf = (char *) realloc (buf, size); + if (buf == NULL) + { + puts ("out of memory"); + exit (1); + } + + res = strftime (buf, size, tests[cnt].fmt, now); + if (res != 0) + break; + } + while (size < tests[cnt].max); + + if (res == 0) + { + printf ("%Zu: %s: res == 0 despite size == %Zu\n", + cnt, tests[cnt].fmt, size); + result = 1; + } + else if (size < tests[cnt].min) + { + printf ("%Zu: %s: size == %Zu was enough\n", + cnt, tests[cnt].fmt, size); + result = 1; + } + else + printf ("%Zu: %s: size == %Zu: OK\n", cnt, tests[cnt].fmt, size); + + free (buf); + } + + struct tm ttm = + { + /* Initialize the fields which are needed in the tests. */ + .tm_mday = 1, + .tm_hour = 2 + }; + const struct + { + const char *fmt; + const char *exp; + size_t n; + } ftests[] = + { + { "%-e", "1", 1 }, + { "%-k", "2", 1 }, + { "%-l", "2", 1 }, + }; +#define nftests (sizeof (ftests) / sizeof (ftests[0])) + for (cnt = 0; cnt < nftests; ++cnt) + { + char buf[100]; + size_t r = strftime (buf, sizeof (buf), ftests[cnt].fmt, &ttm); + if (r != ftests[cnt].n) + { + printf ("strftime(\"%s\") returned %zu not %zu\n", + ftests[cnt].fmt, r, ftests[cnt].n); + result = 1; + } + if (strcmp (buf, ftests[cnt].exp) != 0) + { + printf ("strftime(\"%s\") produced \"%s\" not \"%s\"\n", + ftests[cnt].fmt, buf, ftests[cnt].exp); + result = 1; + } + } + + return result; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/time/tst-strptime.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/time/tst-strptime.c new file mode 100644 index 00000000..6356aa0d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/time/tst-strptime.c @@ -0,0 +1,193 @@ +/* Test for strptime. + Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include + + +static const struct +{ + const char *locale; + const char *input; + const char *format; + int wday; + int yday; + int mon; + int mday; +} day_tests[] = +{ + { "C", "2000-01-01", "%Y-%m-%d", 6, 0, 0, 1 }, + { "C", "03/03/00", "%D", 5, 62, 2, 3 }, + { "C", "9/9/99", "%x", 4, 251, 8, 9 }, + { "C", "19990502123412", "%Y%m%d%H%M%S", 0, 121, 4, 2 }, + { "C", "2001 20 Mon", "%Y %U %a", 1, 140, 4, 21 }, + { "C", "2001 21 Mon", "%Y %W %a", 1, 140, 4, 21 }, + { "ja_JP.EUC-JP", "2000-01-01 08:12:21 AM", "%Y-%m-%d %I:%M:%S %p", + 6, 0, 0, 1 }, + { "en_US.ISO-8859-1", "2000-01-01 08:12:21 PM", "%Y-%m-%d %I:%M:%S %p", + 6, 0, 0, 1 }, + { "ja_JP.EUC-JP", "2001 20 \xb7\xee", "%Y %U %a", 1, 140, 4, 21 }, + { "ja_JP.EUC-JP", "2001 21 \xb7\xee", "%Y %W %a", 1, 140, 4, 21 }, +}; + + +static const struct +{ + const char *input; + const char *format; + const char *output; + int wday; + int yday; +} tm_tests [] = +{ + {"17410105012000", "%H%M%S%d%m%Y", "2000-01-05 17:41:01", 3, 4} +}; + + + +static int +test_tm (void) +{ + struct tm tm; + size_t i; + int result = 0; + char buf[100]; + + for (i = 0; i < sizeof (tm_tests) / sizeof (tm_tests[0]); ++i) + { + memset (&tm, '\0', sizeof (tm)); + + char *ret = strptime (tm_tests[i].input, tm_tests[i].format, &tm); + if (ret == NULL) + { + printf ("strptime returned NULL for `%s'\n", tm_tests[i].input); + result = 1; + continue; + } + else if (*ret != '\0') + { + printf ("not all of `%s' read\n", tm_tests[i].input); + result = 1; + } + strftime (buf, sizeof (buf), "%F %T", &tm); + printf ("strptime (\"%s\", \"%s\", ...)\n" + "\tshould be: %s, wday = %d, yday = %3d\n" + "\t is: %s, wday = %d, yday = %3d\n", + tm_tests[i].input, tm_tests[i].format, + tm_tests[i].output, + tm_tests[i].wday, tm_tests[i].yday, + buf, tm.tm_wday, tm.tm_yday); + + if (strcmp (buf, tm_tests[i].output) != 0) + { + printf ("Time and date are not correct.\n"); + result = 1; + } + if (tm.tm_wday != tm_tests[i].wday) + { + printf ("weekday for `%s' incorrect: %d instead of %d\n", + tm_tests[i].input, tm.tm_wday, tm_tests[i].wday); + result = 1; + } + if (tm.tm_yday != tm_tests[i].yday) + { + printf ("yearday for `%s' incorrect: %d instead of %d\n", + tm_tests[i].input, tm.tm_yday, tm_tests[i].yday); + result = 1; + } + } + + return result; +} + + +int +main (int argc, char *argv[]) +{ + struct tm tm; + size_t i; + int result = 0; + + for (i = 0; i < sizeof (day_tests) / sizeof (day_tests[0]); ++i) + { + memset (&tm, '\0', sizeof (tm)); + + if (setlocale (LC_ALL, day_tests[i].locale) == NULL) + { + printf ("cannot set locale %s: %m\n", day_tests[i].locale); + exit (EXIT_FAILURE); + } + + char *ret = strptime (day_tests[i].input, day_tests[i].format, &tm); + if (ret == NULL) + { + printf ("strptime returned NULL for `%s'\n", day_tests[i].input); + result = 1; + continue; + } + else if (*ret != '\0') + { + printf ("not all of `%s' read\n", day_tests[i].input); + result = 1; + } + + printf ("strptime (\"%s\", \"%s\", ...)\n" + "\tshould be: wday = %d, yday = %3d, mon = %2d, mday = %2d\n" + "\t is: wday = %d, yday = %3d, mon = %2d, mday = %2d\n", + day_tests[i].input, day_tests[i].format, + day_tests[i].wday, day_tests[i].yday, + day_tests[i].mon, day_tests[i].mday, + tm.tm_wday, tm.tm_yday, tm.tm_mon, tm.tm_mday); + + if (tm.tm_wday != day_tests[i].wday) + { + printf ("weekday for `%s' incorrect: %d instead of %d\n", + day_tests[i].input, tm.tm_wday, day_tests[i].wday); + result = 1; + } + if (tm.tm_yday != day_tests[i].yday) + { + printf ("yearday for `%s' incorrect: %d instead of %d\n", + day_tests[i].input, tm.tm_yday, day_tests[i].yday); + result = 1; + } + if (tm.tm_mon != day_tests[i].mon) + { + printf ("month for `%s' incorrect: %d instead of %d\n", + day_tests[i].input, tm.tm_mon, day_tests[i].mon); + result = 1; + } + if (tm.tm_mday != day_tests[i].mday) + { + printf ("monthday for `%s' incorrect: %d instead of %d\n", + day_tests[i].input, tm.tm_mday, day_tests[i].mday); + result = 1; + } + } + + setlocale (LC_ALL, "C"); + + result |= test_tm (); + + return result; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/time/tst-strptime2.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/time/tst-strptime2.c new file mode 100644 index 00000000..73552bb8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/time/tst-strptime2.c @@ -0,0 +1,59 @@ +#include +#include +#include + + +static const struct +{ + const char *fmt; + long int gmtoff; +} tests[] = + { + { "1113472456 +1000", 36000 }, + { "1113472456 -1000", -36000 }, + { "1113472456 +10", 36000 }, + { "1113472456 -10", -36000 }, + { "1113472456 +1030", 37800 }, + { "1113472456 -1030", -37800 }, + { "1113472456 +0030", 1800 }, + { "1113472456 -0030", -1800 }, + { "1113472456 -1330", LONG_MAX }, + { "1113472456 +1330", LONG_MAX }, + { "1113472456 -1060", LONG_MAX }, + { "1113472456 +1060", LONG_MAX }, + { "1113472456 1030", LONG_MAX }, + }; +#define ntests (sizeof (tests) / sizeof (tests[0])) + + +int +main (void) +{ + int result = 0; + + for (int i = 0; i < ntests; ++i) + { + struct tm tm; + + if (strptime (tests[i].fmt, "%s %z", &tm) == NULL) + { + if (tests[i].gmtoff != LONG_MAX) + { + printf ("round %d: strptime unexpectedly failed\n", i); + result = 1; + } + continue; + } + + if (tm.tm_gmtoff != tests[i].gmtoff) + { + printf ("round %d: tm_gmtoff is %ld\n", i, (long int) tm.tm_gmtoff); + result = 1; + } + } + + if (result == 0) + puts ("all OK"); + + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/time/tst-timezone.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/time/tst-timezone.c new file mode 100644 index 00000000..4c879163 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/time/tst-timezone.c @@ -0,0 +1,170 @@ +/* Copyright (C) 1998, 1999, 2000, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Andreas Jaeger , 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include + +int failed = 0; + +struct test_times +{ + const char *name; + int daylight; + int timezone; + const char *tzname[2]; +}; + +static const struct test_times tests[] = +{ + { "Europe/Amsterdam", 1, -3600, { "CET", "CEST" }}, + { "Europe/Berlin", 1, -3600, { "CET", "CEST" }}, + { "Europe/London", 1, 0, { "GMT", "BST" }}, + { "Universal", 0, 0, {"UTC", "UTC" }}, + { "Australia/Melbourne", 1, -36000, { "EST", "EST" }}, + { "America/Sao_Paulo", 1, 10800, {"BRT", "BRST" }}, + { "America/Chicago", 1, 21600, {"CST", "CDT" }}, + { "America/Indiana/Indianapolis", 1, 18000, {"EST", "EDT" }}, + { "America/Los_Angeles", 1, 28800, {"PST", "PDT" }}, + { "Asia/Tokyo", 1, -32400, {"JST", "JDT" }}, + { "Pacific/Auckland", 1, -43200, { "NZST", "NZDT" }}, + { NULL, 0, 0 } +}; + +/* This string will be used for `putenv' calls. */ +char envstring[100]; + +static void +print_tzvars (void) +{ + printf ("tzname[0]: %s\n", tzname[0]); + printf ("tzname[1]: %s\n", tzname[1]); + printf ("daylight: %d\n", daylight); + printf ("timezone: %ld\n", timezone); +} + + +static void +check_tzvars (const char *name, int dayl, int timez, const char *const tznam[]) +{ + int i; + + if (daylight != dayl) + { + printf ("*** Timezone: %s, daylight is: %d but should be: %d\n", + name, daylight, dayl); + ++failed; + } + if (timezone != timez) + { + printf ("*** Timezone: %s, timezone is: %ld but should be: %d\n", + name, timezone, timez); + ++failed; + } + for (i = 0; i <= 1; ++i) + if (strcmp (tzname[i], tznam[i]) != 0) + { + printf ("*** Timezone: %s, tzname[%d] is: %s but should be: %s\n", + name, i, tzname[i], tznam[i]); + ++failed; + } +} + + +int +main (int argc, char ** argv) +{ + time_t t; + const struct test_times *pt; + char buf[BUFSIZ]; + + /* This should be: Fri May 15 01:02:16 1998 (UTC). */ + t = 895194136; + printf ("We use this date: %s\n", asctime (gmtime (&t))); + + for (pt = tests; pt->name != NULL; ++pt) + { + /* Start with a known state */ + printf ("Checking timezone %s\n", pt->name); + sprintf (buf, "TZ=%s", pt->name); + if (putenv (buf)) + { + puts ("putenv failed."); + failed = 1; + } + tzset (); + print_tzvars (); + check_tzvars (pt->name, pt->daylight, pt->timezone, pt->tzname); + + /* calling localtime shouldn't make a difference */ + localtime (&t); + print_tzvars (); + check_tzvars (pt->name, pt->daylight, pt->timezone, pt->tzname); + } + + /* From a post of Scott Harrington to the timezone + mailing list. */ + { + struct tm tmBuf = {0, 0, 0, 10, 3, 98, 0, 0, -1}; + char buf[200]; + strcpy (envstring, "TZ=Europe/London"); + putenv (envstring); + t = mktime (&tmBuf); + snprintf (buf, sizeof (buf), "TZ=%s %ld %d %d %d %d %d %d %d %d %d", + getenv ("TZ"), t, + tmBuf.tm_sec, tmBuf.tm_min, tmBuf.tm_hour, + tmBuf.tm_mday, tmBuf.tm_mon, tmBuf.tm_year, + tmBuf.tm_wday, tmBuf.tm_yday, tmBuf.tm_isdst); + fputs (buf, stdout); + puts (" should be"); + puts ("TZ=Europe/London 892162800 0 0 0 10 3 98 5 99 1"); + if (strcmp (buf, "TZ=Europe/London 892162800 0 0 0 10 3 98 5 99 1") != 0) + { + failed = 1; + fputs (" FAILED ***", stdout); + } + } + + printf("\n"); + + { + struct tm tmBuf = {0, 0, 0, 10, 3, 98, 0, 0, -1}; + char buf[200]; + strcpy (envstring, "TZ=GMT"); + /* No putenv call needed! */ + t = mktime (&tmBuf); + snprintf (buf, sizeof (buf), "TZ=%s %ld %d %d %d %d %d %d %d %d %d", + getenv ("TZ"), t, + tmBuf.tm_sec, tmBuf.tm_min, tmBuf.tm_hour, + tmBuf.tm_mday, tmBuf.tm_mon, tmBuf.tm_year, + tmBuf.tm_wday, tmBuf.tm_yday, tmBuf.tm_isdst); + fputs (buf, stdout); + puts (" should be"); + puts ("TZ=GMT 892166400 0 0 0 10 3 98 5 99 0"); + if (strcmp (buf, "TZ=GMT 892166400 0 0 0 10 3 98 5 99 0") != 0) + { + failed = 1; + fputs (" FAILED ***", stdout); + } + } + + return failed ? EXIT_FAILURE : EXIT_SUCCESS; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/time/tst_wcsftime.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/time/tst_wcsftime.c new file mode 100644 index 00000000..6e35f1e6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/time/tst_wcsftime.c @@ -0,0 +1,39 @@ +#include +#include +#include +#ifdef __UCLIBC_HAS_WCHAR__ +#include + +int +main (int argc, char *argv[]) +{ + wchar_t buf[200]; + time_t t; + struct tm *tp; + int result = 0; + size_t n; + + time (&t); + tp = gmtime (&t); + + n = wcsftime (buf, sizeof (buf) / sizeof (buf[0]), + L"%H:%M:%S %Y-%m-%d\n", tp); + if (n != 21) + result = 1; + + wprintf (L"It is now %ls", buf); + + wcsftime (buf, sizeof (buf) / sizeof (buf[0]), L"%A\n", tp); + + wprintf (L"The weekday is %ls", buf); + + return result; +} + +#else +int main(void) +{ + puts("Test requires WCHAR support; skipping"); + return 0; +} +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/Makefile new file mode 100644 index 00000000..607fec2c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/Makefile @@ -0,0 +1,8 @@ +# uClibc TLS tests +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + +top_builddir=../../ +top_srcdir=../../ +include ../Rules.mak +-include Makefile.in +include ../Test.mak diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/Makefile.in new file mode 100644 index 00000000..d19d347f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/Makefile.in @@ -0,0 +1,148 @@ +# uClibc TLS tests +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + +TESTS := tst-tls1 tst-tls2 tst-tls3 tst-tls4 tst-tls5 tst-tls6 tst-tls7 \ + tst-tls8 tst-tls9 tst-tls10 tst-tls11 tst-tls12 tst-tls13 \ + tst-tls14 tst-tls15 tst-tls16 tst-tls17 tst-tls18 tst-tls-at-ctor \ + tst-tls1-static tst-tls2-static tst-tls9-static +TESTS_DISABLED := tst-tls1-static tst-tls2-static tst-tls9-static + +#all these tests require shared libraries +ifeq ($(HAVE_SHARED),) +TESTS_DISABLED := $(TESTS) +endif + +# All these tests need tls.h, which is not installed with glibc +GLIBC_TESTS_DISABLED := $(addsuffix _glibc,$(filter-out $(TESTS_DISABLED),$(TESTS))) + + + +PTDIR := $(top_builddir)libpthread/nptl +SYSDEPS_DIR := $(top_srcdir)libc/sysdeps + +EXTRA_CFLAGS := -DNOT_IN_libc=1 \ + -std=gnu99 -I. \ + -I$(SYSDEPS_DIR)/linux \ + -I$(SYSDEPS_DIR)/linux/$(TARGET_ARCH) \ + -I$(PTDIR) \ + -I$(PTDIR)/sysdeps/unix/sysv/linux/$(TARGET_ARCH) \ + -I$(PTDIR)/sysdeps/$(TARGET_ARCH) \ + -I$(PTDIR)/sysdeps/unix/sysv/linux \ + -I$(PTDIR)/sysdeps/pthread \ + -I$(PTDIR)/sysdeps/pthread/bits \ + -I$(PTDIR)/sysdeps/generic \ + -I$(top_builddir)ldso/include \ + -I$(top_builddir)ldso/ldso/$(TARGET_ARCH) \ + -I$(top_builddir)include \ + -include $(top_builddir)include/libc-symbols.h + +tlsmod17a-suffixes := 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 +tlsmod18a-suffixes := 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 +CFLAGS_tst-tlsmod1.so := -fPIC -DSHARED -shared +CFLAGS_tst-tlsmod2.so := -fPIC -DSHARED -shared +CFLAGS_tst-tlsmod3.so := -fPIC -DSHARED -shared +CFLAGS_tst-tlsmod4.so := -fPIC -DSHARED -shared +CFLAGS_tst-tlsmod5.so := -fPIC -DSHARED -shared +CFLAGS_tst-tlsmod6.so := -fPIC -DSHARED -shared +CFLAGS_tst-tlsmod7.so := -fPIC -DSHARED -shared +CFLAGS_tst-tlsmod8.so := -fPIC -DSHARED -shared +CFLAGS_tst-tlsmod9.so := -fPIC -DSHARED -shared +CFLAGS_tst-tlsmod10.so := -fPIC -DSHARED -shared +CFLAGS_tst-tlsmod11.so := -fPIC -DSHARED -shared +CFLAGS_tst-tlsmod12.so := -fPIC -DSHARED -shared +CFLAGS_tst-tlsmod13.so := -fPIC -DSHARED -shared +CFLAGS_tst-tlsmod13a.so := -fPIC -DSHARED -shared +CFLAGS_tst-tlsmod14a.so := -fPIC -DSHARED -shared +CFLAGS_tst-tlsmod14b.so := -fPIC -DSHARED -shared +CFLAGS_tst-tlsmod15a.so := -fPIC -DSHARED -shared +CFLAGS_tst-tlsmod15b.so := -fPIC -DSHARED -shared +CFLAGS_tst-tlsmod16a.so := -fPIC -DSHARED -shared +CFLAGS_tst-tlsmod16b.so := -fPIC -DSHARED -shared +CFLAGS_tst-tlsmod17a.so := -fPIC -DSHARED -shared +CFLAGS_tst-tlsmod17b.so := -fPIC -DSHARED -shared +CFLAGS_tst-tlsmod18a.so := -fPIC -DSHARED -shared +CFLAGS_tst-tlsmod-at-ctor.so := -fPIC -DSHARED -shared + +LDFLAGS_tst-tlsmod1.so := -shared -static-libgcc -L$(top_builddir)lib +LDFLAGS_tst-tlsmod2.so := -shared -static-libgcc -L$(top_builddir)lib +LDFLAGS_tst-tlsmod3.so := -shared -static-libgcc -L$(top_builddir)lib \ + tst-tlsmod2.so +LDFLAGS_tst-tlsmod4.so := -shared -static-libgcc -L$(top_builddir)lib +LDFLAGS_tst-tlsmod5.so := -shared -static-libgcc -L$(top_builddir)lib +LDFLAGS_tst-tlsmod6.so := -shared -static-libgcc -L$(top_builddir)lib +LDFLAGS_tst-tlsmod7.so := -shared -static-libgcc -L$(top_builddir)lib +LDFLAGS_tst-tlsmod8.so := -shared -static-libgcc -L$(top_builddir)lib \ + tst-tlsmod7.so +LDFLAGS_tst-tlsmod9.so := -shared -static-libgcc -L$(top_builddir)lib \ + tst-tlsmod8.so +LDFLAGS_tst-tlsmod10.so := -shared -static-libgcc -L$(top_builddir)lib \ + tst-tlsmod9.so +LDFLAGS_tst-tlsmod11.so := -shared -static-libgcc -L$(top_builddir)lib +LDFLAGS_tst-tlsmod12.so := -shared -static-libgcc -L$(top_builddir)lib \ + tst-tlsmod11.so +LDFLAGS_tst-tlsmod13.so := -shared -static-libgcc -L$(top_builddir)lib +LDFLAGS_tst-tlsmod13a.so := -shared -static-libgcc -L$(top_builddir)lib \ + tst-tlsmod13.so +LDFLAGS_tst-tlsmod14a.so := -shared -static-libgcc -L$(top_builddir)lib +LDFLAGS_tst-tlsmod14b.so := -shared -static-libgcc -L$(top_builddir)lib +LDFLAGS_tst-tlsmod15a.so := -shared -static-libgcc -L$(top_builddir)lib +LDFLAGS_tst-tlsmod15b.so := -shared -static-libgcc -L$(top_builddir)lib +LDFLAGS_tst-tlsmod16a.so := -shared -static-libgcc -L$(top_builddir)lib +LDFLAGS_tst-tlsmod16b.so := -shared -static-libgcc -L$(top_builddir)lib +LDFLAGS_tst-tlsmod17a.so := -shared -static-libgcc -L$(top_builddir)lib +LDFLAGS_tst-tlsmod17b.so := -shared -static-libgcc -L$(top_builddir)lib \ + $(patsubst %,tst-tlsmod17a%.so,$(tlsmod17a-suffixes)) +LDFLAGS_tst-tlsmod18a.so := -shared -static-libgcc -L$(top_builddir)lib +LDFLAGS_tst-tlsmod-at-ctor.so := -shared -static-libgcc -L$(top_builddir)lib + +LDFLAGS_tst-tls3 := tst-tlsmod1.so tst-tlsmod4.so +LDFLAGS_tst-tls4 := -ldl +LDFLAGS_tst-tls5 := -ldl +LDFLAGS_tst-tls6 := -ldl +LDFLAGS_tst-tls7 := -ldl +LDFLAGS_tst-tls8 := -ldl +LDFLAGS_tst-tls9 := -ldl +LDFLAGS_tst-tls10 := -Wl,-rpath-link=. tst-tlsmod8.so +LDFLAGS_tst-tls11 := -Wl,-rpath-link=. tst-tlsmod10.so +LDFLAGS_tst-tls12 := -Wl,-rpath-link=. tst-tlsmod12.so +LDFLAGS_tst-tls13 := -ldl -Wl,-rpath-link=. +LDFLAGS_tst-tls14 := -ldl -Wl,-rpath-link=. tst-tlsmod14a.so +LDFLAGS_tst-tls15 := -ldl -Wl,-rpath-link=. +LDFLAGS_tst-tls16 := -ldl -Wl,-rpath-link=. +LDFLAGS_tst-tls17 := -ldl -Wl,-rpath-link=. +LDFLAGS_tst-tls18 := -ldl -Wl,-rpath-link=. +LDFLAGS_tst-tls-at-ctor := tst-tlsmod-at-ctor.so + +tst-tls3: tst-tlsmod1.so tst-tlsmod4.so +tst-tls4: tst-tlsmod2.so +tst-tls5: tst-tlsmod2.so +tst-tls6: tst-tlsmod2.so +tst-tls7: tst-tlsmod2.so tst-tlsmod3.so +tst-tls8: tst-tlsmod2.so tst-tlsmod3.so tst-tlsmod4.so +tst-tls9: tst-tlsmod5.so tst-tlsmod6.so +tst-tls10: tst-tlsmod7.so tst-tlsmod8.so +tst-tls11: tst-tlsmod9.so tst-tlsmod10.so +tst-tls12: tst-tlsmod11.so tst-tlsmod12.so +tst-tls13: tst-tlsmod13.so tst-tlsmod13a.so +tst-tls14: tst-tlsmod14a.so tst-tlsmod14b.so +tst-tls15: tst-tlsmod15b.so +tst-tls16: tst-tlsmod16a.so tst-tlsmod16b.so +tst-tls17: tst-tlsmod17b.so +tst-tlsmod17b.so: $(patsubst %,tst-tlsmod17a%.so,$(tlsmod17a-suffixes)) +tst-tlsmod17a%.so: tst-tlsmod17a.c + $(Q)$(CC) $(CFLAGS) $(EXTRA_CFLAGS) $(CFLAGS_tst-tlsmod17a.so) $< -o $@ \ + -DN=$* -Wl,-soname,$@ $(LDFLAGS) $(EXTRA_LIBS) \ + $(LDFLAGS_tst-tlsmod17a.so) +tst-tls18: $(patsubst %,tst-tlsmod18a%.so,$(tlsmod18a-suffixes)) +tst-tlsmod18a%.so: tst-tlsmod18a.c + $(Q)$(CC) $(CFLAGS) $(EXTRA_CFLAGS) $(CFLAGS_tst-tlsmod18a.so) $< -o $@ \ + -DN=$* -Wl,-soname,$@ $(LDFLAGS) $(EXTRA_LIBS) \ + $(LDFLAGS_tst-tlsmod18a.so) +tst-tls-at-ctor: tst-tlsmod-at-ctor.so + +RET_tst-tls13 := 1 +ifeq ($(TARGET_ARCH),mips) +RET_tst-tls15 := 1 +endif + +WRAPPER := env LD_LIBRARY_PATH="$$PWD:.:$(LD_LIBRARY_PATH)" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/README b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/README new file mode 100644 index 00000000..06c9eb74 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/README @@ -0,0 +1,8 @@ +These tests were imported from 'glibc/elf' and are responsible for testing +the TLS functionality of the dynamic loader. The file 'tls-macros-mips.h' +is a copy of 'glibc/sysdeps/mips/tls-macros.h'. Dependency and link orders +are critical and should NOT be changed. Even if you think you know what +you are doing, do not touch the Makefile without posting to the uClibc +development mailing list. + +-Steve diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tls-macros-arm.h b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tls-macros-arm.h new file mode 100644 index 00000000..13d0f975 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tls-macros-arm.h @@ -0,0 +1,51 @@ +#define TLS_LE(x) \ + ({ int *__result; \ + void *tp = __builtin_thread_pointer (); \ + __asm__ ("ldr %0, 1f; " \ + "add %0, %1, %0; " \ + "b 2f; " \ + "1: .word " #x "(tpoff); " \ + "2: " \ + : "=&r" (__result) : "r" (tp)); \ + __result; }) + +#define TLS_IE(x) \ + ({ int *__result; \ + void *tp = __builtin_thread_pointer (); \ + __asm__ ("ldr %0, 1f; " \ + "3: ldr %0, [pc, %0];" \ + "add %0, %1, %0; " \ + "b 2f; " \ + "1: .word " #x "(gottpoff) + (. - 3b - 8); " \ + "2: " \ + : "=&r" (__result) : "r" (tp)); \ + __result; }) + +#define TLS_LD(x) \ + ({ char *__result; \ + int __offset; \ + extern void *__tls_get_addr (void *); \ + __asm__ ("ldr %0, 2f; " \ + "1: add %0, pc, %0; " \ + "b 3f; " \ + "2: .word " #x "(tlsldm) + (. - 1b - 8); " \ + "3: " \ + : "=r" (__result)); \ + __result = (char *)__tls_get_addr (__result); \ + __asm__ ("ldr %0, 1f; " \ + "b 2f; " \ + "1: .word " #x "(tlsldo); " \ + "2: " \ + : "=r" (__offset)); \ + (int *) (__result + __offset); }) + +#define TLS_GD(x) \ + ({ int *__result; \ + extern void *__tls_get_addr (void *); \ + __asm__ ("ldr %0, 2f; " \ + "1: add %0, pc, %0; " \ + "b 3f; " \ + "2: .word " #x "(tlsgd) + (. - 1b - 8); " \ + "3: " \ + : "=r" (__result)); \ + (int *)__tls_get_addr (__result); }) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tls-macros-mips.h b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tls-macros-mips.h new file mode 100644 index 00000000..0db38303 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tls-macros-mips.h @@ -0,0 +1,88 @@ +/* Macros to support TLS testing in times of missing compiler support. */ + +#if _MIPS_SIM != _ABI64 + +/* These versions are for o32 and n32. */ + +# define TLS_GD(x) \ + ({ void *__result; \ + extern void *__tls_get_addr (void *); \ + __asm__ ("addiu %0, $28, %%tlsgd(" #x ")" \ + : "=r" (__result)); \ + (int *)__tls_get_addr (__result); }) +#else +# define TLS_GD(x) \ + ({ void *__result; \ + extern void *__tls_get_addr (void *); \ + __asm__ ("daddiu %0, $28, %%tlsgd(" #x ")" \ + : "=r" (__result)); \ + (int *)__tls_get_addr (__result); }) +#endif + +#if _MIPS_SIM != _ABI64 +# define TLS_LD(x) \ + ({ void *__result; \ + extern void *__tls_get_addr (void *); \ + __asm__ ("addiu %0, $28, %%tlsldm(" #x ")" \ + : "=r" (__result)); \ + __result = __tls_get_addr (__result); \ + __asm__ ("lui $3,%%dtprel_hi(" #x ")\n\t" \ + "addiu $3,$3,%%dtprel_lo(" #x ")\n\t" \ + "addu %0,%0,$3" \ + : "+r" (__result) : : "$3"); \ + __result; }) +# define TLS_IE(x) \ + ({ void *__result; \ + __asm__ (".set push\n\t.set mips32r2\n\t" \ + "rdhwr\t%0,$29\n\t.set pop" \ + : "=v" (__result)); \ + __asm__ ("lw $3,%%gottprel(" #x ")($28)\n\t" \ + "addu %0,%0,$3" \ + : "+r" (__result) : : "$3"); \ + __result; }) +# define TLS_LE(x) \ + ({ void *__result; \ + __asm__ (".set push\n\t.set mips32r2\n\t" \ + "rdhwr\t%0,$29\n\t.set pop" \ + : "=v" (__result)); \ + __asm__ ("lui $3,%%tprel_hi(" #x ")\n\t" \ + "addiu $3,$3,%%tprel_lo(" #x ")\n\t" \ + "addu %0,%0,$3" \ + : "+r" (__result) : : "$3"); \ + __result; }) + +#else + +/* These versions are for n64. */ + +# define TLS_LD(x) \ + ({ void *__result; \ + extern void *__tls_get_addr (void *); \ + __asm__ ("daddiu %0, $28, %%tlsldm(" #x ")" \ + : "=r" (__result)); \ + __result = __tls_get_addr (__result); \ + __asm__ ("lui $3,%%dtprel_hi(" #x ")\n\t" \ + "daddiu $3,$3,%%dtprel_lo(" #x ")\n\t" \ + "daddu %0,%0,$3" \ + : "+r" (__result) : : "$3"); \ + __result; }) +# define TLS_IE(x) \ + ({ void *__result; \ + __asm__ (".set push\n\t.set mips32r2\n\t" \ + "rdhwr\t%0,$29\n\t.set pop" \ + : "=v" (__result)); \ + __asm__ ("ld $3,%%gottprel(" #x ")($28)\n\t" \ + "daddu %0,%0,$3" \ + : "+r" (__result) : : "$3"); \ + __result; }) +# define TLS_LE(x) \ + ({ void *__result; \ + __asm__ (".set push\n\t.set mips32r2\n\t" \ + "rdhwr\t%0,$29\n\t.set pop" \ + : "=v" (__result)); \ + __asm__ ("lui $3,%%tprel_hi(" #x ")\n\t" \ + "daddiu $3,$3,%%tprel_lo(" #x ")\n\t" \ + "daddu %0,%0,$3" \ + : "+r" (__result) : : "$3"); \ + __result; }) +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tls-macros-thumb.h b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tls-macros-thumb.h new file mode 100644 index 00000000..dfa6582a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tls-macros-thumb.h @@ -0,0 +1,57 @@ +#define TLS_LE(x) \ + ({ int *__result; \ + void *tp = __builtin_thread_pointer (); \ + __asm__ ("ldr %0, 1f; " \ + "add %0, %1, %0; " \ + "b 2f; " \ + ".align 2; " \ + "1: .word " #x "(tpoff); " \ + "2: " \ + : "=&r" (__result) : "r" (tp)); \ + __result; }) + +#define TLS_IE(x) \ + ({ int *__result; \ + int tmp; \ + void *tp = __builtin_thread_pointer (); \ + __asm__ ("ldr %0, 1f; " \ + "adr %1, 1f; " \ + "ldr %0, [%1, %0]; " \ + "add %0, %2, %0; " \ + "b 2f; " \ + ".align 2; " \ + "1: .word " #x "(gottpoff); " \ + "2: " \ + : "=&r" (__result), "=&r"(tmp) : "r" (tp)); \ + __result; }) + +#define TLS_LD(x) \ + ({ char *__result; \ + int __offset; \ + extern void *__tls_get_addr (void *); \ + __asm__ ("ldr %0, 2f; " \ + ".align 2; " \ + "1: add %0, pc, %0; " \ + "b 3f; " \ + "2: .word " #x "(tlsldm) + (. - 1b - 4); " \ + "3: " \ + : "=r" (__result)); \ + __result = (char *)__tls_get_addr (__result); \ + __asm__ ("ldr %0, 1f; " \ + "b 2f; " \ + "1: .word " #x "(tlsldo); " \ + "2: " \ + : "=r" (__offset)); \ + (int *) (__result + __offset); }) + +#define TLS_GD(x) \ + ({ int *__result; \ + extern void *__tls_get_addr (void *); \ + __asm__ ("ldr %0, 2f; " \ + ".align 2; " \ + "1: add %0, pc, %0; " \ + "b 3f; " \ + "2: .word " #x "(tlsgd) + (. - 1b - 4); " \ + "3: " \ + : "=r" (__result)); \ + (int *)__tls_get_addr (__result); }) diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tls-macros.h b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tls-macros.h new file mode 100644 index 00000000..3a9a21ad --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tls-macros.h @@ -0,0 +1,861 @@ +/* Macros to support TLS testing in times of missing compiler support. */ + +#define COMMON_INT_DEF(x) \ + __asm__ (".tls_common " #x ",4,4") +/* XXX Until we get compiler support we don't need declarations. */ +#define COMMON_INT_DECL(x) + +/* XXX This definition will probably be machine specific, too. */ +#define VAR_INT_DEF(x) \ + __asm__ (".section .tdata\n\t" \ + ".globl " #x "\n" \ + ".balign 4\n" \ + #x ":\t.long 0\n\t" \ + ".size " #x ",4\n\t" \ + ".previous") +/* XXX Until we get compiler support we don't need declarations. */ +#define VAR_INT_DECL(x) + +#ifdef __mips__ +#include +#endif + +#ifdef __arm__ +#ifdef __thumb__ +#include +#else +#include +#endif +#endif + + /* XXX Each architecture must have its own asm for now. */ +#ifdef __i386__ +# define TLS_LE(x) \ + ({ int *__l; \ + __asm__ ("movl %%gs:0,%0\n\t" \ + "subl $" #x "@tpoff,%0" \ + : "=r" (__l)); \ + __l; }) + +# ifdef __PIC__ +# define TLS_IE(x) \ + ({ int *__l; \ + __asm__ ("movl %%gs:0,%0\n\t" \ + "subl " #x "@gottpoff(%%ebx),%0" \ + : "=r" (__l)); \ + __l; }) +# else +# define TLS_IE(x) \ + ({ int *__l; \ + __asm__ ("call 1f\n\t" \ + ".subsection 1\n" \ + "1:\tmovl (%%esp), %%ebx\n\t" \ + "ret\n\t" \ + ".previous\n\t" \ + "addl $_GLOBAL_OFFSET_TABLE_, %%ebx\n\t" \ + "movl %%gs:0,%0\n\t" \ + "subl " #x "@gottpoff(%%ebx),%0" \ + : "=r" (__l)); \ + __l; }) +# endif + +# ifdef __PIC__ +# define TLS_LD(x) \ + ({ int *__l, __c, __d; \ + __asm__ ("leal " #x "@tlsldm(%%ebx),%%eax\n\t" \ + "call ___tls_get_addr@plt\n\t" \ + "leal " #x "@dtpoff(%%eax), %%eax" \ + : "=a" (__l), "=&c" (__c), "=&d" (__d)); \ + __l; }) +# else +# define TLS_LD(x) \ + ({ int *__l, __b, __c, __d; \ + __asm__ ("call 1f\n\t" \ + ".subsection 1\n" \ + "1:\tmovl (%%esp), %%ebx\n\t" \ + "ret\n\t" \ + ".previous\n\t" \ + "addl $_GLOBAL_OFFSET_TABLE_, %%ebx\n\t" \ + "leal " #x "@tlsldm(%%ebx),%%eax\n\t" \ + "call ___tls_get_addr@plt\n\t" \ + "leal " #x "@dtpoff(%%eax), %%eax" \ + : "=a" (__l), "=&b" (__b), "=&c" (__c), "=&d" (__d)); \ + __l; }) +# endif + +# ifdef __PIC__ +# define TLS_GD(x) \ + ({ int *__l, __c, __d; \ + __asm__ ("leal " #x "@tlsgd(%%ebx),%%eax\n\t" \ + "call ___tls_get_addr@plt\n\t" \ + "nop" \ + : "=a" (__l), "=&c" (__c), "=&d" (__d)); \ + __l; }) +# else +# define TLS_GD(x) \ + ({ int *__l, __c, __d; \ + __asm__ ("call 1f\n\t" \ + ".subsection 1\n" \ + "1:\tmovl (%%esp), %%ebx\n\t" \ + "ret\n\t" \ + ".previous\n\t" \ + "addl $_GLOBAL_OFFSET_TABLE_, %%ebx\n\t" \ + "leal " #x "@tlsgd(%%ebx),%%eax\n\t" \ + "call ___tls_get_addr@plt\n\t" \ + "nop" \ + : "=a" (__l), "=&c" (__c), "=&d" (__d)); \ + __l; }) +# endif + +#elif defined __x86_64__ + +# define TLS_LE(x) \ + ({ int *__l; \ + __asm__ ("movq %%fs:0,%0\n\t" \ + "leaq " #x "@tpoff(%0), %0" \ + : "=r" (__l)); \ + __l; }) + +# define TLS_IE(x) \ + ({ int *__l; \ + __asm__ ("movq %%fs:0,%0\n\t" \ + "addq " #x "@gottpoff(%%rip),%0" \ + : "=r" (__l)); \ + __l; }) + +# define TLS_LD(x) \ + ({ int *__l, __c, __d; \ + __asm__ ("leaq " #x "@tlsld(%%rip),%%rdi\n\t" \ + "call __tls_get_addr@plt\n\t" \ + "leaq " #x "@dtpoff(%%rax), %%rax" \ + : "=a" (__l), "=&c" (__c), "=&d" (__d) \ + : : "rdi", "rsi", "r8", "r9", "r10", "r11"); \ + __l; }) + +# define TLS_GD(x) \ + ({ int *__l, __c, __d; \ + __asm__ (".byte 0x66\n\t" \ + "leaq " #x "@tlsgd(%%rip),%%rdi\n\t" \ + ".word 0x6666\n\t" \ + "rex64\n\t" \ + "call __tls_get_addr@plt" \ + : "=a" (__l), "=&c" (__c), "=&d" (__d) \ + : : "rdi", "rsi", "r8", "r9", "r10", "r11"); \ + __l; }) + +#elif defined __sh__ + +# define TLS_LE(x) \ + ({ int *__l; void *__tp; \ + __asm__ ("stc gbr,%1\n\t" \ + "mov.l 1f,%0\n\t" \ + "bra 2f\n\t" \ + " add %1,%0\n\t" \ + ".align 2\n\t" \ + "1: .long " #x "@tpoff\n\t" \ + "2:" \ + : "=r" (__l), "=r" (__tp)); \ + __l; }) + +# ifdef __PIC__ +# define TLS_IE(x) \ + ({ int *__l; void *__tp; \ + register void *__gp __asm__("r12"); \ + __asm__ ("mov.l 1f,r0\n\t" \ + "stc gbr,%1\n\t" \ + "mov.l @(r0,r12),%0\n\t" \ + "bra 2f\n\t" \ + " add %1,%0\n\t" \ + ".align 2\n\t" \ + "1: .long " #x "@gottpoff\n\t" \ + "2:" \ + : "=r" (__l), "=r" (__tp) : "r" (__gp) : "r0"); \ + __l; }) +# else +# define TLS_IE(x) \ + ({ int *__l; void *__tp; \ + __asm__ ("mov.l r12,@-r15\n\t" \ + "mova 0f,r0\n\t" \ + "mov.l 0f,r12\n\t" \ + "add r0,r12\n\t" \ + "mov.l 1f,r0\n\t" \ + "stc gbr,%1\n\t" \ + "mov.l @(r0,r12),%0\n\t" \ + "bra 2f\n\t" \ + " add %1,%0\n\t" \ + ".align 2\n\t" \ + "1: .long " #x "@gottpoff\n\t" \ + "0: .long _GLOBAL_OFFSET_TABLE_\n\t" \ + "2: mov.l @r15+,r12" \ + : "=r" (__l), "=r" (__tp) : : "r0"); \ + __l; }) +#endif + +# ifdef __PIC__ +# define TLS_LD(x) \ + ({ int *__l; \ + register void *__gp __asm__("r12"); \ + __asm__ ("mov.l 1f,r4\n\t" \ + "mova 2f,r0\n\t" \ + "mov.l 2f,r1\n\t" \ + "add r0,r1\n\t" \ + "jsr @r1\n\t" \ + " add r12,r4\n\t" \ + "bra 4f\n\t" \ + " nop\n\t" \ + ".align 2\n\t" \ + "1: .long " #x "@tlsldm\n\t" \ + "2: .long __tls_get_addr@plt\n\t" \ + "4: mov.l 3f,%0\n\t" \ + "bra 5f\n\t" \ + " add r0,%0\n\t" \ + ".align 2\n\t" \ + "3: .long " #x "@dtpoff\n\t" \ + "5:" \ + : "=r" (__l) : "r" (__gp) : "r0", "r1", "r2", "r3", "r4", "r5", \ + "r6", "r7", "pr", "t"); \ + __l; }) +# else +# define TLS_LD(x) \ + ({ int *__l; \ + __asm__ ("mov.l r12,@-r15\n\t" \ + "mova 0f,r0\n\t" \ + "mov.l 0f,r12\n\t" \ + "add r0,r12\n\t" \ + "mov.l 1f,r4\n\t" \ + "mova 2f,r0\n\t" \ + "mov.l 2f,r1\n\t" \ + "add r0,r1\n\t" \ + "jsr @r1\n\t" \ + " add r12,r4\n\t" \ + "bra 4f\n\t" \ + " nop\n\t" \ + ".align 2\n\t" \ + "1: .long " #x "@tlsldm\n\t" \ + "2: .long __tls_get_addr@plt\n\t" \ + "0: .long _GLOBAL_OFFSET_TABLE_\n\t" \ + "4: mov.l 3f,%0\n\t" \ + "bra 5f\n\t" \ + " add r0,%0\n\t" \ + ".align 2\n\t" \ + "3: .long " #x "@dtpoff\n\t" \ + "5: mov.l @r15+,r12" \ + : "=r" (__l) : : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \ + "pr", "t"); \ + __l; }) +#endif + +# ifdef __PIC__ +# define TLS_GD(x) \ + ({ int *__l; \ + register void *__gp __asm__("r12"); \ + __asm__ ("mov.l 1f,r4\n\t" \ + "mova 2f,r0\n\t" \ + "mov.l 2f,r1\n\t" \ + "add r0,r1\n\t" \ + "jsr @r1\n\t" \ + " add r12,r4\n\t" \ + "bra 3f\n\t" \ + " mov r0,%0\n\t" \ + ".align 2\n\t" \ + "1: .long " #x "@tlsgd\n\t" \ + "2: .long __tls_get_addr@plt\n\t" \ + "3:" \ + : "=r" (__l) : "r" (__gp) : "r0", "r1", "r2", "r3", "r4", "r5", \ + "r6", "r7", "pr", "t"); \ + __l; }) +# else +# define TLS_GD(x) \ + ({ int *__l; \ + __asm__ ("mov.l r12,@-r15\n\t" \ + "mova 0f,r0\n\t" \ + "mov.l 0f,r12\n\t" \ + "add r0,r12\n\t" \ + "mov.l 1f,r4\n\t" \ + "mova 2f,r0\n\t" \ + "mov.l 2f,r1\n\t" \ + "add r0,r1\n\t" \ + "jsr @r1\n\t" \ + " add r12,r4\n\t" \ + "bra 3f\n\t" \ + " mov r0,%0\n\t" \ + ".align 2\n\t" \ + "1: .long " #x "@tlsgd\n\t" \ + "2: .long __tls_get_addr@plt\n\t" \ + "0: .long _GLOBAL_OFFSET_TABLE_\n\t" \ + "3: mov.l @r15+,r12" \ + : "=r" (__l) : : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \ + "pr", "t"); \ + __l; }) +#endif + +#elif defined __alpha__ + +register void *__gp __asm__("$29"); + +# define TLS_LE(x) \ + ({ int *__l; \ + __asm__ ("call_pal 158\n\tlda $0," #x "($0)\t\t!tprel" : "=v"(__l)); \ + __l; }) + +# define TLS_IE(x) \ + ({ char *__tp; unsigned long __o; \ + __asm__ ("call_pal 158\n\tldq %1," #x "($gp)\t\t!gottprel" \ + : "=v"(__tp), "=r"(__o) : "r"(__gp)); \ + (int *)(__tp + __o); }) + +# define TLS_LD(x) \ + ({ extern void *__tls_get_addr(void *); int *__l; void *__i; \ + __asm__ ("lda %0," #x "($gp)\t\t!tlsldm" : "=r" (__i) : "r"(__gp)); \ + __i = __tls_get_addr(__i); \ + __asm__ ("lda %0, " #x "(%1)\t\t!dtprel" : "=r"(__l) : "r"(__i)); \ + __l; }) + +# define TLS_GD(x) \ + ({ extern void *__tls_get_addr(void *); void *__i; \ + __asm__ ("lda %0," #x "($gp)\t\t!tlsgd" : "=r" (__i) : "r"(__gp)); \ + (int *) __tls_get_addr(__i); }) + + +#elif defined __ia64__ + +# define TLS_LE(x) \ + ({ void *__l; \ + __asm__ ("mov r2=r13\n\t" \ + ";;\n\t" \ + "addl %0=@tprel(" #x "),r2\n\t" \ + : "=r" (__l) : : "r2" ); __l; }) + +# define TLS_IE(x) \ + ({ void *__l; \ + register long __gp __asm__ ("gp"); \ + __asm__ (";;\n\t" \ + "addl r16=@ltoff(@tprel(" #x ")),gp\n\t" \ + ";;\n\t" \ + "ld8 r17=[r16]\n\t" \ + ";;\n\t" \ + "add %0=r13,r17\n\t" \ + ";;\n\t" \ + : "=r" (__l) : "r" (__gp) : "r16", "r17" ); __l; }) + +# define __TLS_CALL_CLOBBERS \ + "r2", "r3", "r8", "r9", "r10", "r11", "r14", "r15", "r16", "r17", \ + "r18", "r19", "r20", "r21", "r22", "r23", "r24", "r25", "r26", \ + "r27", "r28", "r29", "r30", "r31", \ + "p6", "p7", "p8", "p9", "p10", "p11", "p12", "p13", "p14", "p15", \ + "f6", "f7", "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", \ + "b6", "b7", \ + "out0", "out1", "out2", "out3", "out4", "out5", "out6", "out7" + +# define TLS_LD(x) \ + ({ void *__l; \ + register long __gp __asm__ ("gp"); \ + __asm__ (";;\n\t" \ + "mov loc0=gp\n\t" \ + "addl r16=@ltoff(@dtpmod(" #x ")),gp\n\t" \ + "addl out1=@dtprel(" #x "),r0\n\t" \ + ";;\n\t" \ + "ld8 out0=[r16]\n\t" \ + "br.call.sptk.many b0=__tls_get_addr" \ + ";;\n\t" \ + "mov gp=loc0\n\t" \ + "mov %0=r8\n\t" \ + ";;\n\t" \ + : "=r" (__l) : "r" (__gp) : "loc0", __TLS_CALL_CLOBBERS); \ + __l; }) + +# define TLS_GD(x) \ + ({ void *__l; \ + register long __gp __asm__ ("gp"); \ + __asm__ (";;\n\t" \ + "mov loc0=gp\n\t" \ + "addl r16=@ltoff(@dtpmod(" #x ")),gp\n\t" \ + "addl r17=@ltoff(@dtprel(" #x ")),gp\n\t" \ + ";;\n\t" \ + "ld8 out0=[r16]\n\t" \ + "ld8 out1=[r17]\n\t" \ + "br.call.sptk.many b0=__tls_get_addr" \ + ";;\n\t" \ + "mov gp=loc0\n\t" \ + "mov %0=r8\n\t" \ + ";;\n\t" \ + : "=r" (__l) : "r" (__gp) : "loc0", __TLS_CALL_CLOBBERS); \ + __l; }) + +#elif defined __sparc__ && !defined __arch64__ + +# define TLS_LE(x) \ + ({ int *__l; \ + __asm__ ("sethi %%tle_hix22(" #x "), %0" : "=r" (__l)); \ + __asm__ ("xor %1, %%tle_lox10(" #x "), %0" : "=r" (__l) : "r" (__l)); \ + __asm__ ("add %%g7, %1, %0" : "=r" (__l) : "r" (__l)); \ + __l; }) + +# ifdef __PIC__ +# define TLS_LOAD_PIC \ + ({ register long pc __asm__ ("%o7"); \ + long got; \ + __asm__ ("sethi %%hi(_GLOBAL_OFFSET_TABLE_-4), %1\n\t" \ + "call .+8\n\t" \ + "add %1, %%lo(_GLOBAL_OFFSET_TABLE_+4), %1\n\t" \ + "add %1, %0, %1\n\t" \ + : "=r" (pc), "=r" (got)); \ + got; }) +# else +# define TLS_LOAD_PIC \ + ({ long got; \ + __asm__ (".hidden _GLOBAL_OFFSET_TABLE_\n\t" \ + "sethi %%hi(_GLOBAL_OFFSET_TABLE_), %0\n\t" \ + "or %0, %%lo(_GLOBAL_OFFSET_TABLE_), %0" \ + : "=r" (got)); \ + got; }) +# endif + +# define TLS_IE(x) \ + ({ int *__l; \ + __asm__ ("sethi %%tie_hi22(" #x "), %0" : "=r" (__l)); \ + __asm__ ("add %1, %%tie_lo10(" #x "), %0" : "=r" (__l) : "r" (__l)); \ + __asm__ ("ld [%1 + %2], %0, %%tie_ld(" #x ")" \ + : "=r" (__l) : "r" (TLS_LOAD_PIC), "r" (__l)); \ + __asm__ ("add %%g7, %1, %0, %%tie_add(" #x ")" : "=r" (__l) : "r" (__l)); \ + __l; }) + +# define TLS_LD(x) \ + ({ int *__l; register void *__o0 __asm__ ("%o0"); \ + long __o; \ + __asm__ ("sethi %%tldm_hi22(" #x "), %0" : "=r" (__l)); \ + __asm__ ("add %1, %%tldm_lo10(" #x "), %0" : "=r" (__l) : "r" (__l)); \ + __asm__ ("add %1, %2, %0, %%tldm_add(" #x ")" \ + : "=r" (__o0) : "r" (TLS_LOAD_PIC), "r" (__l)); \ + __asm__ ("call __tls_get_addr, %%tgd_call(" #x ")\n\t" \ + " nop" \ + : "=r" (__o0) : "0" (__o0) \ + : "g1", "g2", "g3", "g4", "g5", "g6", "o1", "o2", "o3", "o4", \ + "o5", "o7", "cc"); \ + __asm__ ("sethi %%tldo_hix22(" #x "), %0" : "=r" (__o)); \ + __asm__ ("xor %1, %%tldo_lox10(" #x "), %0" : "=r" (__o) : "r" (__o)); \ + __asm__ ("add %1, %2, %0, %%tldo_add(" #x ")" : "=r" (__l) \ + : "r" (__o0), "r" (__o)); \ + __l; }) + +# define TLS_GD(x) \ + ({ int *__l; register void *__o0 __asm__ ("%o0"); \ + __asm__ ("sethi %%tgd_hi22(" #x "), %0" : "=r" (__l)); \ + __asm__ ("add %1, %%tgd_lo10(" #x "), %0" : "=r" (__l) : "r" (__l)); \ + __asm__ ("add %1, %2, %0, %%tgd_add(" #x ")" \ + : "=r" (__o0) : "r" (TLS_LOAD_PIC), "r" (__l)); \ + __asm__ ("call __tls_get_addr, %%tgd_call(" #x ")\n\t" \ + " nop" \ + : "=r" (__o0) : "0" (__o0) \ + : "g1", "g2", "g3", "g4", "g5", "g6", "o1", "o2", "o3", "o4", \ + "o5", "o7", "cc"); \ + __o0; }) + +#elif defined __sparc__ && defined __arch64__ + +# define TLS_LE(x) \ + ({ int *__l; \ + __asm__ ("sethi %%tle_hix22(" #x "), %0" : "=r" (__l)); \ + __asm__ ("xor %1, %%tle_lox10(" #x "), %0" : "=r" (__l) : "r" (__l)); \ + __asm__ ("add %%g7, %1, %0" : "=r" (__l) : "r" (__l)); \ + __l; }) + +# ifdef __PIC__ +# define TLS_LOAD_PIC \ + ({ long pc, got; \ + __asm__ ("sethi %%hi(_GLOBAL_OFFSET_TABLE_-4), %1\n\t" \ + "rd %%pc, %0\n\t" \ + "add %1, %%lo(_GLOBAL_OFFSET_TABLE_+4), %1\n\t" \ + "add %1, %0, %1\n\t" \ + : "=r" (pc), "=r" (got)); \ + got; }) +# else +# define TLS_LOAD_PIC \ + ({ long got; \ + __asm__ (".hidden _GLOBAL_OFFSET_TABLE_\n\t" \ + "sethi %%hi(_GLOBAL_OFFSET_TABLE_), %0\n\t" \ + "or %0, %%lo(_GLOBAL_OFFSET_TABLE_), %0" \ + : "=r" (got)); \ + got; }) +# endif + +# define TLS_IE(x) \ + ({ int *__l; \ + __asm__ ("sethi %%tie_hi22(" #x "), %0" : "=r" (__l)); \ + __asm__ ("add %1, %%tie_lo10(" #x "), %0" : "=r" (__l) : "r" (__l)); \ + __asm__ ("ldx [%1 + %2], %0, %%tie_ldx(" #x ")" \ + : "=r" (__l) : "r" (TLS_LOAD_PIC), "r" (__l)); \ + __asm__ ("add %%g7, %1, %0, %%tie_add(" #x ")" : "=r" (__l) : "r" (__l)); \ + __l; }) + +# define TLS_LD(x) \ + ({ int *__l; register void *__o0 __asm__ ("%o0"); \ + long __o; \ + __asm__ ("sethi %%tldm_hi22(" #x "), %0" : "=r" (__l)); \ + __asm__ ("add %1, %%tldm_lo10(" #x "), %0" : "=r" (__l) : "r" (__l)); \ + __asm__ ("add %1, %2, %0, %%tldm_add(" #x ")" \ + : "=r" (__o0) : "r" (TLS_LOAD_PIC), "r" (__l)); \ + __asm__ ("call __tls_get_addr, %%tgd_call(" #x ")\n\t" \ + " nop" \ + : "=r" (__o0) : "0" (__o0) \ + : "g1", "g2", "g3", "g4", "g5", "g6", "o1", "o2", "o3", "o4", \ + "o5", "o7", "cc"); \ + __asm__ ("sethi %%tldo_hix22(" #x "), %0" : "=r" (__o)); \ + __asm__ ("xor %1, %%tldo_lox10(" #x "), %0" : "=r" (__o) : "r" (__o)); \ + __asm__ ("add %1, %2, %0, %%tldo_add(" #x ")" : "=r" (__l) \ + : "r" (__o0), "r" (__o)); \ + __l; }) + +# define TLS_GD(x) \ + ({ int *__l; register void *__o0 __asm__ ("%o0"); \ + __asm__ ("sethi %%tgd_hi22(" #x "), %0" : "=r" (__l)); \ + __asm__ ("add %1, %%tgd_lo10(" #x "), %0" : "=r" (__l) : "r" (__l)); \ + __asm__ ("add %1, %2, %0, %%tgd_add(" #x ")" \ + : "=r" (__o0) : "r" (TLS_LOAD_PIC), "r" (__l)); \ + __asm__ ("call __tls_get_addr, %%tgd_call(" #x ")\n\t" \ + " nop" \ + : "=r" (__o0) : "0" (__o0) \ + : "g1", "g2", "g3", "g4", "g5", "g6", "o1", "o2", "o3", "o4", \ + "o5", "o7", "cc"); \ + __o0; }) + +#elif defined __s390x__ + +# define TLS_LE(x) \ + ({ unsigned long __offset; \ + __asm__ ("bras %0,1f\n" \ + "0:\t.quad " #x "@ntpoff\n" \ + "1:\tlg %0,0(%0)" \ + : "=a" (__offset) : : "cc" ); \ + (int *) (__builtin_thread_pointer() + __offset); }) + +# ifdef __PIC__ +# define TLS_IE(x) \ + ({ unsigned long __offset; \ + __asm__ ("bras %0,1f\n" \ + "0:\t.quad " #x "@gotntpoff\n" \ + "1:\tlg %0,0(%0)\n\t" \ + "lg %0,0(%0,%%r12):tls_load:" #x \ + : "=&a" (__offset) : : "cc" ); \ + (int *) (__builtin_thread_pointer() + __offset); }) +# else +# define TLS_IE(x) \ + ({ unsigned long __offset; \ + __asm__ ("bras %0,1f\n" \ + "0:\t.quad " #x "@indntpoff\n" \ + "1:\t lg %0,0(%0)\n\t" \ + "lg %0,0(%0):tls_load:" #x \ + : "=&a" (__offset) : : "cc" ); \ + (int *) (__builtin_thread_pointer() + __offset); }) +# endif + +# ifdef __PIC__ +# define TLS_LD(x) \ + ({ unsigned long __offset, __save12; \ + __asm__ ("bras %0,1f\n" \ + "0:\t.quad " #x "@tlsldm\n\t" \ + ".quad " #x "@dtpoff\n" \ + "1:\tlgr %1,%%r12\n\t" \ + "larl %%r12,_GLOBAL_OFFSET_TABLE_\n\t" \ + "lg %%r2,0(%0)\n\t" \ + "brasl %%r14,__tls_get_offset@plt:tls_ldcall:" #x "\n\t" \ + "lg %0,8(%0)\n\t" \ + "algr %0,%%r2\n\t" \ + "lgr %%r12,%1" \ + : "=&a" (__offset), "=&a" (__save12) \ + : : "cc", "0", "1", "2", "3", "4", "5", "14" ); \ + (int *) (__builtin_thread_pointer() + __offset); }) +# else +# define TLS_LD(x) \ + ({ unsigned long __offset; \ + __asm__ ("bras %0,1f\n" \ + "0:\t.quad " #x "@tlsldm\n\t" \ + ".quad " #x "@dtpoff\n" \ + "1:\tlarl %%r12,_GLOBAL_OFFSET_TABLE_\n\t" \ + "lg %%r2,0(%0)\n\t" \ + "brasl %%r14,__tls_get_offset@plt:tls_ldcall:" #x "\n\t" \ + "lg %0,8(%0)\n\t" \ + "algr %0,%%r2" \ + : "=&a" (__offset) \ + : : "cc", "0", "1", "2", "3", "4", "5", "12", "14" ); \ + (int *) (__builtin_thread_pointer() + __offset); }) +# endif + +# ifdef __PIC__ +# define TLS_GD(x) \ + ({ unsigned long __offset, __save12; \ + __asm__ ("bras %0,1f\n" \ + "0:\t.quad " #x "@tlsgd\n" \ + "1:\tlgr %1,%%r12\n\t" \ + "larl %%r12,_GLOBAL_OFFSET_TABLE_\n\t" \ + "lg %%r2,0(%0)\n\t" \ + "brasl %%r14,__tls_get_offset@plt:tls_gdcall:" #x "\n\t" \ + "lgr %0,%%r2\n\t" \ + "lgr %%r12,%1" \ + : "=&a" (__offset), "=&a" (__save12) \ + : : "cc", "0", "1", "2", "3", "4", "5", "14" ); \ + (int *) (__builtin_thread_pointer() + __offset); }) +# else +# define TLS_GD(x) \ + ({ unsigned long __offset; \ + __asm__ ("bras %0,1f\n" \ + "0:\t.quad " #x "@tlsgd\n" \ + "1:\tlarl %%r12,_GLOBAL_OFFSET_TABLE_\n\t" \ + "lg %%r2,0(%0)\n\t" \ + "brasl %%r14,__tls_get_offset@plt:tls_gdcall:" #x "\n\t" \ + "lgr %0,%%r2" \ + : "=&a" (__offset) \ + : : "cc", "0", "1", "2", "3", "4", "5", "12", "14" ); \ + (int *) (__builtin_thread_pointer() + __offset); }) +# endif + +#elif defined __s390__ + +# define TLS_LE(x) \ + ({ unsigned long __offset; \ + __asm__ ("bras %0,1f\n" \ + "0:\t.long " #x "@ntpoff\n" \ + "1:\tl %0,0(%0)" \ + : "=a" (__offset) : : "cc" ); \ + (int *) (__builtin_thread_pointer() + __offset); }) + +# ifdef __PIC__ +# define TLS_IE(x) \ + ({ unsigned long __offset; \ + __asm__ ("bras %0,1f\n" \ + "0:\t.long " #x "@gotntpoff\n" \ + "1:\tl %0,0(%0)\n\t" \ + "l %0,0(%0,%%r12):tls_load:" #x \ + : "=&a" (__offset) : : "cc" ); \ + (int *) (__builtin_thread_pointer() + __offset); }) +# else +# define TLS_IE(x) \ + ({ unsigned long __offset; \ + __asm__ ("bras %0,1f\n" \ + "0:\t.long " #x "@indntpoff\n" \ + "1:\t l %0,0(%0)\n\t" \ + "l %0,0(%0):tls_load:" #x \ + : "=&a" (__offset) : : "cc" ); \ + (int *) (__builtin_thread_pointer() + __offset); }) +# endif + +# ifdef __PIC__ +# define TLS_LD(x) \ + ({ unsigned long __offset, __save12; \ + __asm__ ("bras %0,1f\n" \ + "0:\t.long _GLOBAL_OFFSET_TABLE_-0b\n\t" \ + ".long __tls_get_offset@plt-0b\n\t" \ + ".long " #x "@tlsldm\n\t" \ + ".long " #x "@dtpoff\n" \ + "1:\tlr %1,%%r12\n\t" \ + "l %%r12,0(%0)\n\t" \ + "la %%r12,0(%%r12,%0)\n\t" \ + "l %%r1,4(%0)\n\t" \ + "l %%r2,8(%0)\n\t" \ + "bas %%r14,0(%%r1,%0):tls_ldcall:" #x "\n\t" \ + "l %0,12(%0)\n\t" \ + "alr %0,%%r2\n\t" \ + "lr %%r12,%1" \ + : "=&a" (__offset), "=&a" (__save12) \ + : : "cc", "0", "1", "2", "3", "4", "5" ); \ + (int *) (__builtin_thread_pointer() + __offset); }) +# else +# define TLS_LD(x) \ + ({ unsigned long __offset; \ + __asm__ ("bras %0,1f\n" \ + "0:\t.long _GLOBAL_OFFSET_TABLE_\n\t" \ + ".long __tls_get_offset@plt\n\t" \ + ".long " #x "@tlsldm\n\t" \ + ".long " #x "@dtpoff\n" \ + "1:\tl %%r12,0(%0)\n\t" \ + "l %%r1,4(%0)\n\t" \ + "l %%r2,8(%0)\n\t" \ + "bas %%r14,0(%%r1):tls_ldcall:" #x "\n\t" \ + "l %0,12(%0)\n\t" \ + "alr %0,%%r2" \ + : "=&a" (__offset) : : "cc", "0", "1", "2", "3", "4", "5", "12" ); \ + (int *) (__builtin_thread_pointer() + __offset); }) +# endif + +# ifdef __PIC__ +# define TLS_GD(x) \ + ({ unsigned long __offset, __save12; \ + __asm__ ("bras %0,1f\n" \ + "0:\t.long _GLOBAL_OFFSET_TABLE_-0b\n\t" \ + ".long __tls_get_offset@plt-0b\n\t" \ + ".long " #x "@tlsgd\n" \ + "1:\tlr %1,%%r12\n\t" \ + "l %%r12,0(%0)\n\t" \ + "la %%r12,0(%%r12,%0)\n\t" \ + "l %%r1,4(%0)\n\t" \ + "l %%r2,8(%0)\n\t" \ + "bas %%r14,0(%%r1,%0):tls_gdcall:" #x "\n\t" \ + "lr %0,%%r2\n\t" \ + "lr %%r12,%1" \ + : "=&a" (__offset), "=&a" (__save12) \ + : : "cc", "0", "1", "2", "3", "4", "5" ); \ + (int *) (__builtin_thread_pointer() + __offset); }) +# else +# define TLS_GD(x) \ + ({ unsigned long __offset; \ + __asm__ ("bras %0,1f\n" \ + "0:\t.long _GLOBAL_OFFSET_TABLE_\n\t" \ + ".long __tls_get_offset@plt\n\t" \ + ".long " #x "@tlsgd\n" \ + "1:\tl %%r12,0(%0)\n\t" \ + "l %%r1,4(%0)\n\t" \ + "l %%r2,8(%0)\n\t" \ + "bas %%r14,0(%%r1):tls_gdcall:" #x "\n\t" \ + "lr %0,%%r2" \ + : "=&a" (__offset) : : "cc", "0", "1", "2", "3", "4", "5", "12" ); \ + (int *) (__builtin_thread_pointer() + __offset); }) +# endif + +#elif defined __powerpc__ && !defined __powerpc64__ + +/*#include "config.h"*/ + +# define __TLS_CALL_CLOBBERS \ + "0", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", \ + "lr", "ctr", "cr0", "cr1", "cr5", "cr6", "cr7" + +/* PowerPC32 Local Exec TLS access. */ +# define TLS_LE(x) \ + ({ int *__result; \ + __asm__ ("addi %0,2," #x "@tprel" \ + : "=r" (__result)); \ + __result; }) + +/* PowerPC32 Initial Exec TLS access. */ +# ifdef HAVE_ASM_PPC_REL16 +# define TLS_IE(x) \ + ({ int *__result; \ + __asm__ ("bcl 20,31,1f\n1:\t" \ + "mflr %0\n\t" \ + "addis %0,%0,_GLOBAL_OFFSET_TABLE_-1b@ha\n\t" \ + "addi %0,%0,_GLOBAL_OFFSET_TABLE_-1b@l\n\t" \ + "lwz %0," #x "@got@tprel(%0)\n\t" \ + "add %0,%0," #x "@tls" \ + : "=b" (__result) : \ + : "lr"); \ + __result; }) +# else +# define TLS_IE(x) \ + ({ int *__result; \ + __asm__ ("bl _GLOBAL_OFFSET_TABLE_@local-4\n\t" \ + "mflr %0\n\t" \ + "lwz %0," #x "@got@tprel(%0)\n\t" \ + "add %0,%0," #x "@tls" \ + : "=b" (__result) : \ + : "lr"); \ + __result; }) +# endif + +/* PowerPC32 Local Dynamic TLS access. */ +# ifdef HAVE_ASM_PPC_REL16 +# define TLS_LD(x) \ + ({ int *__result; \ + __asm__ ("bcl 20,31,1f\n1:\t" \ + "mflr 3\n\t" \ + "addis 3,3,_GLOBAL_OFFSET_TABLE_-1b@ha\n\t" \ + "addi 3,3,_GLOBAL_OFFSET_TABLE_-1b@l\n\t" \ + "addi 3,3," #x "@got@tlsld\n\t" \ + "bl __tls_get_addr@plt\n\t" \ + "addi %0,3," #x "@dtprel" \ + : "=r" (__result) : \ + : __TLS_CALL_CLOBBERS); \ + __result; }) +# else +# define TLS_LD(x) \ + ({ int *__result; \ + __asm__ ("bl _GLOBAL_OFFSET_TABLE_@local-4\n\t" \ + "mflr 3\n\t" \ + "addi 3,3," #x "@got@tlsld\n\t" \ + "bl __tls_get_addr@plt\n\t" \ + "addi %0,3," #x "@dtprel" \ + : "=r" (__result) : \ + : __TLS_CALL_CLOBBERS); \ + __result; }) +# endif + +/* PowerPC32 General Dynamic TLS access. */ +# ifdef HAVE_ASM_PPC_REL16 +# define TLS_GD(x) \ + ({ register int *__result __asm__ ("r3"); \ + __asm__ ("bcl 20,31,1f\n1:\t" \ + "mflr 3\n\t" \ + "addis 3,3,_GLOBAL_OFFSET_TABLE_-1b@ha\n\t" \ + "addi 3,3,_GLOBAL_OFFSET_TABLE_-1b@l\n\t" \ + "addi 3,3," #x "@got@tlsgd\n\t" \ + "bl __tls_get_addr@plt" \ + : : \ + : __TLS_CALL_CLOBBERS); \ + __result; }) +# else +# define TLS_GD(x) \ + ({ register int *__result __asm__ ("r3"); \ + __asm__ ("bl _GLOBAL_OFFSET_TABLE_@local-4\n\t" \ + "mflr 3\n\t" \ + "addi 3,3," #x "@got@tlsgd\n\t" \ + "bl __tls_get_addr@plt" \ + : : \ + : __TLS_CALL_CLOBBERS); \ + __result; }) +# endif + +#elif defined __powerpc__ && defined __powerpc64__ + +/* PowerPC64 Local Exec TLS access. */ +# define TLS_LE(x) \ + ({ int * __result; \ + __asm__ ( \ + " addis %0,13," #x "@tprel@ha\n" \ + " addi %0,%0," #x "@tprel@l\n" \ + : "=b" (__result) ); \ + __result; \ + }) +/* PowerPC64 Initial Exec TLS access. */ +# define TLS_IE(x) \ + ({ int * __result; \ + __asm__ ( \ + " ld %0," #x "@got@tprel(2)\n" \ + " add %0,%0," #x "@tls\n" \ + : "=b" (__result) ); \ + __result; \ + }) +/* PowerPC64 Local Dynamic TLS access. */ +# define TLS_LD(x) \ + ({ int * __result; \ + __asm__ ( \ + " addi 3,2," #x "@got@tlsld\n" \ + " bl .__tls_get_addr\n" \ + " nop \n" \ + " addis %0,3," #x "@dtprel@ha\n" \ + " addi %0,%0," #x "@dtprel@l\n" \ + : "=b" (__result) : \ + : "0", "3", "4", "5", "6", "7", \ + "8", "9", "10", "11", "12", \ + "lr", "ctr", \ + "cr0", "cr1", "cr5", "cr6", "cr7"); \ + __result; \ + }) +/* PowerPC64 General Dynamic TLS access. */ +# define TLS_GD(x) \ + ({ int * __result; \ + __asm__ ( \ + " addi 3,2," #x "@got@tlsgd\n" \ + " bl .__tls_get_addr\n" \ + " nop \n" \ + " mr %0,3\n" \ + : "=b" (__result) : \ + : "0", "3", "4", "5", "6", "7", \ + "8", "9", "10", "11", "12", \ + "lr", "ctr", \ + "cr0", "cr1", "cr5", "cr6", "cr7"); \ + __result; \ + }) + +#elif !defined TLS_LE || !defined TLS_IE \ + || !defined TLS_LD || !defined TLS_GD +# error "No support for this architecture so far." +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls-at-ctor.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls-at-ctor.c new file mode 100644 index 00000000..53aece18 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls-at-ctor.c @@ -0,0 +1,21 @@ +#include +#include +#include + +#define TLS_VAR_INIT_VALUE 99 + +#ifdef USE_TLS +extern __thread int tls_var; +#endif + +int main(void) +{ + int ret = EXIT_SUCCESS; +#ifdef USE_TLS + if (tls_var != TLS_VAR_INIT_VALUE) { + printf("tls_var = %d - Expected value = %d\n", tls_var, TLS_VAR_INIT_VALUE); + ret = EXIT_FAILURE; + } +#endif + return ret; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls1-static.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls1-static.c new file mode 100644 index 00000000..a0100807 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls1-static.c @@ -0,0 +1 @@ +#include "tst-tls1.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls1.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls1.c new file mode 100644 index 00000000..f5ac6d2b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls1.c @@ -0,0 +1,92 @@ +/* glibc test for TLS in ld.so. */ +#undef _LIBC +#include + +#include + +#ifdef USE_TLS +# include "tls-macros.h" + + +/* Two common 'int' variables in TLS. */ +COMMON_INT_DEF(foo); +COMMON_INT_DEF(bar); +#endif + + +#define TEST_FUNCTION do_test () +static int +do_test (void) +{ +#ifdef USE_TLS + int result = 0; + int *ap, *bp; + + + /* Set the variable using the local exec model. */ + puts ("set bar to 1 (LE)"); + ap = TLS_LE (bar); + *ap = 1; + + + /* Get variables using initial exec model. */ + fputs ("get sum of foo and bar (IE)", stdout); + ap = TLS_IE (foo); + bp = TLS_IE (bar); + printf (" = %d\n", *ap + *bp); + result |= *ap + *bp != 1; + if (*ap != 0) + { + printf ("foo = %d\n", *ap); + result = 1; + } + if (*bp != 1) + { + printf ("bar = %d\n", *bp); + result = 1; + } + + + /* Get variables using local dynamic model. */ + fputs ("get sum of foo and bar (LD)", stdout); + ap = TLS_LD (foo); + bp = TLS_LD (bar); + printf (" = %d\n", *ap + *bp); + result |= *ap + *bp != 1; + if (*ap != 0) + { + printf ("foo = %d\n", *ap); + result = 1; + } + if (*bp != 1) + { + printf ("bar = %d\n", *bp); + result = 1; + } + + + /* Get variables using generic dynamic model. */ + fputs ("get sum of foo and bar (GD)", stdout); + ap = TLS_GD (foo); + bp = TLS_GD (bar); + printf (" = %d\n", *ap + *bp); + result |= *ap + *bp != 1; + if (*ap != 0) + { + printf ("foo = %d\n", *ap); + result = 1; + } + if (*bp != 1) + { + printf ("bar = %d\n", *bp); + result = 1; + } + + return result; +#else + return 0; +#endif +} + + +#include "../test-skeleton.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls10.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls10.c new file mode 100644 index 00000000..fc067707 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls10.c @@ -0,0 +1,40 @@ +#include "tst-tls10.h" + +#ifdef USE_TLS__THREAD +__thread int dummy __attribute__((visibility ("hidden"))) = 12; +__thread struct A local = { 1, 2, 3 }; +#endif + +#define CHECK(N, S) \ + p = f##N##a (); \ + if (p->a != S || p->b != S + 1 || p->c != S + 2) \ + abort () + +int +main (void) +{ + struct A *p; + if (local.a != 1 || local.b != 2 || local.c != 3) + abort (); +#ifdef USE_TLS__THREAD + if (a1.a != 4 || a1.b != 5 || a1.c != 6) + abort (); + if (a2.a != 22 || a2.b != 23 || a2.c != 24) + abort (); + if (a3.a != 10 || a3.b != 11 || a3.c != 12) + abort (); + if (a4.a != 25 || a4.b != 26 || a4.c != 27) + abort (); + check1 (); + check2 (); + if (f1a () != &a1 || f2a () != &a2 || f3a () != &a3 || f4a () != &a4) + abort (); + CHECK (5, 16); + CHECK (6, 19); + if (f7a () != &a2 || f8a () != &a4) + abort (); + CHECK (9, 28); + CHECK (10, 31); +#endif + exit (0); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls10.h b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls10.h new file mode 100644 index 00000000..1be6adc2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls10.h @@ -0,0 +1,38 @@ +#include +#include + +#if defined USE_TLS && defined HAVE___THREAD \ + && defined HAVE_TLS_MODEL_ATTRIBUTE +# define USE_TLS__THREAD + +struct A +{ + char a; + int b; + long long c; +}; + +extern __thread struct A a1, a2, a3, a4; +extern struct A *f1a (void); +extern struct A *f2a (void); +extern struct A *f3a (void); +extern struct A *f4a (void); +extern struct A *f5a (void); +extern struct A *f6a (void); +extern struct A *f7a (void); +extern struct A *f8a (void); +extern struct A *f9a (void); +extern struct A *f10a (void); +extern int f1b (void); +extern int f2b (void); +extern int f3b (void); +extern int f4b (void); +extern int f5b (void); +extern int f6b (void); +extern int f7b (void); +extern int f8b (void); +extern int f9b (void); +extern int f10b (void); +extern void check1 (void); +extern void check2 (void); +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls11.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls11.c new file mode 100644 index 00000000..816cf5cc --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls11.c @@ -0,0 +1,27 @@ +#include "tst-tls10.h" + +#define CHECK(N, S) \ + p = f##N##a (); \ + if (p->a != S || p->b != S + 1 || p->c != S + 2) \ + abort () + +int +main (void) +{ +#ifdef USE_TLS__THREAD + struct A *p; + check1 (); + check2 (); + CHECK (1, 4); + CHECK (2, 22); + CHECK (3, 10); + CHECK (4, 25); + CHECK (5, 16); + CHECK (6, 19); + CHECK (7, 22); + CHECK (8, 25); + CHECK (9, 28); + CHECK (10, 31); +#endif + exit (0); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls12.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls12.c new file mode 100644 index 00000000..84aa7d35 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls12.c @@ -0,0 +1,18 @@ +#include "tst-tls10.h" + +#define CHECK(N, S) \ + p = &a##N; \ + if (p->a != S || p->b != S + 1 || p->c != S + 2) \ + abort () + +int +main (void) +{ +#ifdef USE_TLS__THREAD + struct A *p; + check1 (); + CHECK (1, 4); + CHECK (2, 7); +#endif + exit (0); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls13.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls13.c new file mode 100644 index 00000000..55fb62e5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls13.c @@ -0,0 +1,30 @@ +/* Check unloading modules with data in static TLS block. */ +#include +#include +#include + + +static int +do_test (void) +{ + int i; + for (i = 0; i < 1000;) + { + printf ("round %d\n",++i); + + void *h = dlopen ("tst-tlsmod13a.so", RTLD_LAZY); + if (h == NULL) + { + printf ("cannot load: %s\n", dlerror ()); + exit (1); + } + + dlclose (h); + } + + return 0; +} + +#define TEST_FUNCTION do_test () +#define TIMEOUT 3 +#include "../test-skeleton.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls14.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls14.c new file mode 100644 index 00000000..428fd529 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls14.c @@ -0,0 +1,66 @@ +/* Check alignment of TLS variable. */ +#include +#include +#include +#include + +#include + +#if USE_TLS && HAVE___THREAD + +#define AL 4096 +struct foo +{ + int i; +} __attribute ((aligned (AL))); + +static __thread struct foo f; +static struct foo g; + + +extern int in_dso1 (void); + + +static int +do_test (void) +{ + int result = 0; + + int fail = (((uintptr_t) &f) & (AL - 1)) != 0; + printf ("&f = %p %s\n", &f, fail ? "FAIL" : "OK"); + result |= fail; + + fail = (((uintptr_t) &g) & (AL - 1)) != 0; + printf ("&g = %p %s\n", &g, fail ? "FAIL" : "OK"); + result |= fail; + + result |= in_dso1 (); + + void *h = dlopen ("tst-tlsmod14b.so", RTLD_LAZY); + if (h == NULL) + { + printf ("cannot open tst-tlsmod14b.so: %m\n"); + exit (1); + } + + int (*fp) (void) = (int (*) (void)) dlsym (h, "in_dso2"); + if (fp == NULL) + { + puts ("cannot find in_dso2"); + exit (1); + } + + result |= fp (); + + return result; +} + +#define TEST_FUNCTION do_test () + +#else + +#define TEST_FUNCTION 0 + +#endif + +#include "../test-skeleton.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls15.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls15.c new file mode 100644 index 00000000..2c2df251 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls15.c @@ -0,0 +1,33 @@ +#include +#include +#include + +static int +do_test (void) +{ + void *h = dlopen ("tst-tlsmod15a.so", RTLD_NOW); + if (h != NULL) + { + puts ("unexpectedly succeeded to open tst-tlsmod15a.so"); + exit (1); + } + + h = dlopen ("tst-tlsmod15b.so", RTLD_NOW); + if (h == NULL) + { + puts ("failed to open tst-tlsmod15b.so"); + exit (1); + } + + int (*fp) (void) = (int (*) (void)) dlsym (h, "in_dso"); + if (fp == NULL) + { + puts ("cannot find in_dso"); + exit (1); + } + + return fp (); +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls16.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls16.c new file mode 100644 index 00000000..17912dc3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls16.c @@ -0,0 +1,53 @@ +#include +#include +#include + +static int +do_test (void) +{ + void *h = dlopen ("tst-tlsmod16a.so", RTLD_LAZY | RTLD_GLOBAL); + if (h == NULL) + { + puts ("unexpectedly failed to open tst-tlsmod16a.so"); + exit (1); + } + + void *p = dlsym (h, "tlsvar"); + + /* This dlopen should indeed fail, because tlsvar was assigned to + dynamic TLS, and the new module requests it to be in static TLS. + However, there's a possibility that dlopen succeeds if the + variable is, for whatever reason, assigned to static TLS, or if + the module fails to require static TLS, or even if TLS is not + supported. */ + h = dlopen ("tst-tlsmod16b.so", RTLD_NOW | RTLD_GLOBAL); + if (h == NULL) + { + return 0; + } + + puts ("unexpectedly succeeded to open tst-tlsmod16b.so"); + + + void *(*fp) (void) = (void *(*) (void)) dlsym (h, "in_dso"); + if (fp == NULL) + { + puts ("cannot find in_dso"); + exit (1); + } + + /* If the dlopen passes, at least make sure the address returned by + dlsym is the same as that returned by the initial-exec access. + If the variable was assigned to dynamic TLS during dlsym, this + portion will fail. */ + if (fp () != p) + { + puts ("returned values do not match"); + exit (1); + } + + return 0; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls17.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls17.c new file mode 100644 index 00000000..c1bc7d8f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls17.c @@ -0,0 +1,29 @@ +#include +#include +#include + +static int +do_test (void) +{ + void *h = dlopen ("tst-tlsmod17b.so", RTLD_LAZY); + if (h == NULL) + { + puts ("unexpectedly failed to open tst-tlsmod17b.so"); + exit (1); + } + + int (*fp) (void) = (int (*) (void)) dlsym (h, "tlsmod17b"); + if (fp == NULL) + { + puts ("cannot find tlsmod17b"); + exit (1); + } + + if (fp ()) + exit (1); + + return 0; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls18.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls18.c new file mode 100644 index 00000000..00dcdff4 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls18.c @@ -0,0 +1,38 @@ +#include +#include +#include + +static int +do_test (void) +{ + char modname[sizeof "tst-tlsmod18aXX.so"]; + void *h[20]; + for (int i = 0; i < 20; i++) + { + snprintf (modname, sizeof modname, "tst-tlsmod18a%d.so", i); + h[i] = dlopen (modname, RTLD_LAZY); + if (h[i] == NULL) + { + printf ("unexpectedly failed to open %s", modname); + exit (1); + } + } + + for (int i = 0; i < 20; i++) + { + int (*fp) (void) = (int (*) (void)) dlsym (h[i], "test"); + if (fp == NULL) + { + printf ("cannot find test in tst-tlsmod18a%d.so", i); + exit (1); + } + + if (fp ()) + exit (1); + } + + return 0; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls2-static.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls2-static.c new file mode 100644 index 00000000..55ffa574 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls2-static.c @@ -0,0 +1 @@ +#include "tst-tls2.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls2.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls2.c new file mode 100644 index 00000000..41748996 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls2.c @@ -0,0 +1,91 @@ +/* glibc test for TLS in ld.so. */ +#include + +#include + +#ifdef USE_TLS +# include "tls-macros.h" + + +/* Two 'int' variables in TLS. */ +VAR_INT_DEF(foo); +VAR_INT_DEF(bar); +#endif + + +#define TEST_FUNCTION do_test () +static int +do_test (void) +{ +#ifdef USE_TLS + int result = 0; + int *ap, *bp; + + + /* Set the variable using the local exec model. */ + puts ("set bar to 1 (LE)"); + ap = TLS_LE (bar); + *ap = 1; + + + /* Get variables using initial exec model. */ + fputs ("get sum of foo and bar (IE)", stdout); + ap = TLS_IE (foo); + bp = TLS_IE (bar); + printf (" = %d\n", *ap + *bp); + result |= *ap + *bp != 1; + if (*ap != 0) + { + printf ("foo = %d\n", *ap); + result = 1; + } + if (*bp != 1) + { + printf ("bar = %d\n", *bp); + result = 1; + } + + + /* Get variables using local dynamic model. */ + fputs ("get sum of foo and bar (LD)", stdout); + ap = TLS_LD (foo); + bp = TLS_LD (bar); + printf (" = %d\n", *ap + *bp); + result |= *ap + *bp != 1; + if (*ap != 0) + { + printf ("foo = %d\n", *ap); + result = 1; + } + if (*bp != 1) + { + printf ("bar = %d\n", *bp); + result = 1; + } + + + /* Get variables using generic dynamic model. */ + fputs ("get sum of foo and bar (GD)", stdout); + ap = TLS_GD (foo); + bp = TLS_GD (bar); + printf (" = %d\n", *ap + *bp); + result |= *ap + *bp != 1; + if (*ap != 0) + { + printf ("foo = %d\n", *ap); + result = 1; + } + if (*bp != 1) + { + printf ("bar = %d\n", *bp); + result = 1; + } + + return result; +#else + return 0; +#endif +} + + +#include "../test-skeleton.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls3.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls3.c new file mode 100644 index 00000000..84be4357 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls3.c @@ -0,0 +1,76 @@ +/* glibc test for TLS in ld.so. */ +#include + +#include + +#ifdef USE_TLS +# include "tls-macros.h" + + +/* One define int variable, two externs. */ +COMMON_INT_DECL(foo); +VAR_INT_DECL(bar); +VAR_INT_DEF(baz); +#endif + + +extern int in_dso (void); + + +#define TEST_FUNCTION do_test () +static int +do_test (void) +{ +#ifdef USE_TLS + int result = 0; + int *ap, *bp, *cp; + + + /* Set the variable using the local exec model. */ + puts ("set baz to 3 (LE)"); + ap = TLS_LE (baz); + *ap = 3; + + + /* Get variables using initial exec model. */ + puts ("set variables foo and bar (IE)"); + ap = TLS_IE (foo); + *ap = 1; + bp = TLS_IE (bar); + *bp = 2; + + + /* Get variables using local dynamic model. */ + fputs ("get sum of foo, bar (GD) and baz (LD)", stdout); + ap = TLS_GD (foo); + bp = TLS_GD (bar); + cp = TLS_LD (baz); + printf (" = %d\n", *ap + *bp + *cp); + result |= *ap + *bp + *cp != 6; + if (*ap != 1) + { + printf ("foo = %d\n", *ap); + result = 1; + } + if (*bp != 2) + { + printf ("bar = %d\n", *bp); + result = 1; + } + if (*cp != 3) + { + printf ("baz = %d\n", *cp); + result = 1; + } + + + result |= in_dso (); + + return result; +#else + return 0; +#endif +} + + +#include "../test-skeleton.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls4.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls4.c new file mode 100644 index 00000000..f92ee53c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls4.c @@ -0,0 +1,56 @@ +#include +#include +#include + +#include + + +#define TEST_FUNCTION do_test () +static int +do_test (void) +{ +#ifdef USE_TLS + static const char modname[] = "tst-tlsmod2.so"; + int result = 0; + int *foop; + int (*fp) (int, int *); + void *h; + + h = dlopen (modname, RTLD_LAZY); + if (h == NULL) + { + printf ("cannot open '%s': %s\n", modname, dlerror ()); + exit (1); + } + + fp = dlsym (h, "in_dso"); + if (fp == NULL) + { + printf ("cannot get symbol 'in_dso': %s\n", dlerror ()); + exit (1); + } + + result |= fp (0, NULL); + + foop = dlsym (h, "foo"); + if (foop == NULL) + { + printf ("cannot get symbol 'foo' the second time: %s\n", dlerror ()); + exit (1); + } + if (*foop != 16) + { + puts ("foo != 16"); + result = 1; + } + + dlclose (h); + + return result; +#else + return 0; +#endif +} + + +#include "../test-skeleton.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls5.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls5.c new file mode 100644 index 00000000..a571d2cd --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls5.c @@ -0,0 +1,72 @@ +#include +#include +#include + +#include + + +#define TEST_FUNCTION do_test () +static int +do_test (void) +{ +#ifdef USE_TLS + static const char modname[] = "tst-tlsmod2.so"; + int result = 0; + int *foop; + int *foop2; + int (*fp) (int, int *); + void *h; + + h = dlopen (modname, RTLD_LAZY); + if (h == NULL) + { + printf ("cannot open '%s': %s\n", modname, dlerror ()); + exit (1); + } + + foop = dlsym (h, "foo"); + if (foop == NULL) + { + printf ("cannot get symbol 'foo': %s\n", dlerror ()); + exit (1); + } + + *foop = 42; + + fp = dlsym (h, "in_dso"); + if (fp == NULL) + { + printf ("cannot get symbol 'in_dso': %s\n", dlerror ()); + exit (1); + } + + result |= fp (42, foop); + + foop2 = dlsym (h, "foo"); + if (foop2 == NULL) + { + printf ("cannot get symbol 'foo' the second time: %s\n", dlerror ()); + exit (1); + } + + if (foop != foop2) + { + puts ("address of 'foo' different the second time"); + result = 1; + } + else if (*foop != 16) + { + puts ("foo != 16"); + result = 1; + } + + dlclose (h); + + return result; +#else + return 0; +#endif +} + + +#include "../test-skeleton.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls6.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls6.c new file mode 100644 index 00000000..e692aca6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls6.c @@ -0,0 +1,108 @@ +#include +#include +#include + +#include +#include +#ifdef __UCLIBC__ +#include "dl-elf.h" +#include "dl-hash.h" +#endif + + +#define TEST_FUNCTION do_test () +static int +do_test (void) +{ +#ifdef USE_TLS + static const char modname[] = "tst-tlsmod2.so"; + int result = 0; + int *foop; + int *foop2; + int (*fp) (int, int *); + void *h; + int i; + int modid = -1; + + for (i = 0; i < 10; ++i) + { + h = dlopen (modname, RTLD_LAZY); + if (h == NULL) + { + printf ("cannot open '%s': %s\n", modname, dlerror ()); + exit (1); + } + + /* Dirty test code here: we peek into a private data structure. + We make sure that the module gets assigned the same ID every + time. The value of the first round is used. */ +#ifdef __UCLIBC__ + if (modid == -1) + modid = ((struct link_map *)((struct dyn_elf *)h)->dyn)->l_tls_modid; + else if (((struct link_map *)((struct dyn_elf *)h)->dyn)->l_tls_modid + != (size_t) modid) + { + printf ("round %d: modid now %zu, initially %d\n", + i, + ((struct link_map *)((struct dyn_elf *)h)->dyn)->l_tls_modid, + modid); + result = 1; + } +#else + if (modid == -1) + modid = ((struct link_map *) h)->l_tls_modid; + else if (((struct link_map *) h)->l_tls_modid != modid) + { + printf ("round %d: modid now %zd, initially %d\n", + i, ((struct link_map *) h)->l_tls_modid, modid); + result = 1; + } +#endif + + foop = dlsym (h, "foo"); + if (foop == NULL) + { + printf ("cannot get symbol 'foo': %s\n", dlerror ()); + exit (1); + } + + *foop = 42 + i; + + fp = dlsym (h, "in_dso"); + if (fp == NULL) + { + printf ("cannot get symbol 'in_dso': %s\n", dlerror ()); + exit (1); + } + + result |= fp (42 + i, foop); + + foop2 = dlsym (h, "foo"); + if (foop2 == NULL) + { + printf ("cannot get symbol 'foo' the second time: %s\n", dlerror ()); + exit (1); + } + + if (foop != foop2) + { + puts ("address of 'foo' different the second time"); + result = 1; + } + else if (*foop != 16) + { + puts ("foo != 16"); + result = 1; + } + + dlclose (h); + } + + return result; +#else + return 0; +#endif +} + + +#include "../test-skeleton.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls7.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls7.c new file mode 100644 index 00000000..41da2708 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls7.c @@ -0,0 +1,79 @@ +#include +#include +#include + +#include +#include +#ifdef __UCLIBC__ +#include "dl-elf.h" +#include "dl-hash.h" +#endif + + +#define TEST_FUNCTION do_test () +static int +do_test (void) +{ +#ifdef USE_TLS + static const char modname[] = "tst-tlsmod3.so"; + int result = 0; + int (*fp) (void); + void *h; + int i; + int modid = -1; + + for (i = 0; i < 10; ++i) + { + h = dlopen (modname, RTLD_LAZY); + if (h == NULL) + { + printf ("cannot open '%s': %s\n", modname, dlerror ()); + exit (1); + } + + /* Dirty test code here: we peek into a private data structure. + We make sure that the module gets assigned the same ID every + time. The value of the first round is used. */ +#ifdef __UCLIBC__ + if (modid == -1) + modid = ((struct link_map *)((struct dyn_elf *)h)->dyn)->l_tls_modid; + else if (((struct link_map *)((struct dyn_elf *)h)->dyn)->l_tls_modid + != (size_t) modid) + { + printf ("round %d: modid now %zu, initially %d\n", + i, + ((struct link_map *)((struct dyn_elf *)h)->dyn)->l_tls_modid, + modid); + result = 1; + } +#else + if (modid == -1) + modid = ((struct link_map *) h)->l_tls_modid; + else if (((struct link_map *) h)->l_tls_modid != (size_t) modid) + { + printf ("round %d: modid now %zu, initially %d\n", + i, ((struct link_map *) h)->l_tls_modid, modid); + result = 1; + } +#endif + + fp = dlsym (h, "in_dso2"); + if (fp == NULL) + { + printf ("cannot get symbol 'in_dso2': %s\n", dlerror ()); + exit (1); + } + + result |= fp (); + + dlclose (h); + } + + return result; +#else + return 0; +#endif +} + + +#include "../test-skeleton.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls8.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls8.c new file mode 100644 index 00000000..2541609f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls8.c @@ -0,0 +1,230 @@ +#include +#include +#include + +#include +#include +#ifdef __UCLIBC__ +#include "dl-elf.h" +#include "dl-hash.h" +#endif + + +#define TEST_FUNCTION do_test () +static int +do_test (void) +{ +#ifdef USE_TLS + static const char modname1[] = "tst-tlsmod3.so"; + static const char modname2[] = "tst-tlsmod4.so"; + int result = 0; + int (*fp1) (void); + int (*fp2) (int, int *); + void *h1; + void *h2; + int i; + size_t modid1 = (size_t) -1; + size_t modid2 = (size_t) -1; + int *bazp; + + for (i = 0; i < 10; ++i) + { + h1 = dlopen (modname1, RTLD_LAZY); + if (h1 == NULL) + { + printf ("cannot open '%s': %s\n", modname1, dlerror ()); + exit (1); + } + + /* Dirty test code here: we peek into a private data structure. + We make sure that the module gets assigned the same ID every + time. The value of the first round is used. */ +#ifdef __UCLIBC__ + if (modid1 == (size_t) -1) + modid1 = ((struct link_map *)((struct dyn_elf *)h1)->dyn)->l_tls_modid; + else if (((struct link_map *)((struct dyn_elf *)h1)->dyn)->l_tls_modid + != (size_t) modid1) + { + printf ("round %d: modid now %zd, initially %zd\n", + i, + ((struct link_map *)((struct dyn_elf *)h1)->dyn)->l_tls_modid, + modid1); + result = 1; + } +#else + if (modid1 == (size_t) -1) + modid1 = ((struct link_map *) h1)->l_tls_modid; + else if (((struct link_map *) h1)->l_tls_modid != modid1) + { + printf ("round %d: modid now %zd, initially %zd\n", + i, ((struct link_map *) h1)->l_tls_modid, modid1); + result = 1; + } +#endif + + fp1 = dlsym (h1, "in_dso2"); + if (fp1 == NULL) + { + printf ("cannot get symbol 'in_dso2' in %s\n", modname1); + exit (1); + } + + result |= fp1 (); + + + + h2 = dlopen (modname2, RTLD_LAZY); + if (h2 == NULL) + { + printf ("cannot open '%s': %s\n", modname2, dlerror ()); + exit (1); + } + + /* Dirty test code here: we peek into a private data structure. + We make sure that the module gets assigned the same ID every + time. The value of the first round is used. */ +#ifdef __UCLIBC__ + if (modid2 == (size_t) -1) + modid2 = ((struct link_map *)((struct dyn_elf *)h1)->dyn)->l_tls_modid; + else if (((struct link_map *)((struct dyn_elf *)h1)->dyn)->l_tls_modid + != (size_t) modid2) + { + printf ("round %d: modid now %zd, initially %zd\n", + i, + ((struct link_map *)((struct dyn_elf *)h1)->dyn)->l_tls_modid, + modid2); + result = 1; + } +#else + if (modid2 == (size_t) -1) + modid2 = ((struct link_map *) h1)->l_tls_modid; + else if (((struct link_map *) h1)->l_tls_modid != modid2) + { + printf ("round %d: modid now %zd, initially %zd\n", + i, ((struct link_map *) h1)->l_tls_modid, modid2); + result = 1; + } +#endif + + bazp = dlsym (h2, "baz"); + if (bazp == NULL) + { + printf ("cannot get symbol 'baz' in %s\n", modname2); + exit (1); + } + + *bazp = 42 + i; + + fp2 = dlsym (h2, "in_dso"); + if (fp2 == NULL) + { + printf ("cannot get symbol 'in_dso' in %s\n", modname2); + exit (1); + } + + result |= fp2 (42 + i, bazp); + + dlclose (h1); + dlclose (h2); + + + h1 = dlopen (modname1, RTLD_LAZY); + if (h1 == NULL) + { + printf ("cannot open '%s': %s\n", modname1, dlerror ()); + exit (1); + } + + /* Dirty test code here: we peek into a private data structure. + We make sure that the module gets assigned the same ID every + time. The value of the first round is used. */ +#ifdef __UCLIBC__ + if (((struct link_map *)((struct dyn_elf *)h1)->dyn)->l_tls_modid + != modid1) + { + printf ("round %d: modid now %zd, initially %zd\n", + i, + ((struct link_map *)((struct dyn_elf *)h1)->dyn)->l_tls_modid, + modid1); + result = 1; + } +#else + if (((struct link_map *) h1)->l_tls_modid != modid1) + { + printf ("round %d: modid now %zd, initially %zd\n", + i, ((struct link_map *) h1)->l_tls_modid, modid1); + result = 1; + } +#endif + + fp1 = dlsym (h1, "in_dso2"); + if (fp1 == NULL) + { + printf ("cannot get symbol 'in_dso2' in %s\n", modname1); + exit (1); + } + + result |= fp1 (); + + + + h2 = dlopen (modname2, RTLD_LAZY); + if (h2 == NULL) + { + printf ("cannot open '%s': %s\n", modname2, dlerror ()); + exit (1); + } + + /* Dirty test code here: we peek into a private data structure. + We make sure that the module gets assigned the same ID every + time. The value of the first round is used. */ +#ifdef __UCLIBC__ + if (((struct link_map *)((struct dyn_elf *)h1)->dyn)->l_tls_modid + != modid2) + { + printf ("round %d: modid now %zd, initially %zd\n", + i, + ((struct link_map *)((struct dyn_elf *)h1)->dyn)->l_tls_modid, + modid2); + result = 1; + } +#else + if (((struct link_map *) h1)->l_tls_modid != modid2) + { + printf ("round %d: modid now %zd, initially %zd\n", + i, ((struct link_map *) h1)->l_tls_modid, modid2); + result = 1; + } +#endif + + bazp = dlsym (h2, "baz"); + if (bazp == NULL) + { + printf ("cannot get symbol 'baz' in %s\n", modname2); + exit (1); + } + + *bazp = 62 + i; + + fp2 = dlsym (h2, "in_dso"); + if (fp2 == NULL) + { + printf ("cannot get symbol 'in_dso' in %s\n", modname2); + exit (1); + } + + result |= fp2 (62 + i, bazp); + + /* This time the dlclose calls are in reverse order. */ + dlclose (h2); + dlclose (h1); + } + + return result; +#else + return 0; +#endif +} + + +#include "../test-skeleton.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls9-static.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls9-static.c new file mode 100644 index 00000000..51812ccc --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls9-static.c @@ -0,0 +1 @@ +#include "tst-tls9.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls9.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls9.c new file mode 100644 index 00000000..e317696d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tls9.c @@ -0,0 +1,42 @@ +#include +#include +#include + +#include +#include + +#define TEST_FUNCTION do_test () +static int +do_test (void) +{ +#ifdef USE_TLS + static const char modname1[] = "tst-tlsmod5.so"; + static const char modname2[] = "tst-tlsmod6.so"; + int result = 0; + + void *h1 = dlopen (modname1, RTLD_LAZY); + if (h1 == NULL) + { + printf ("cannot open '%s': %s\n", modname1, dlerror ()); + result = 1; + } + void *h2 = dlopen (modname2, RTLD_LAZY); + if (h2 == NULL) + { + printf ("cannot open '%s': %s\n", modname2, dlerror ()); + result = 1; + } + + if (h1 != NULL) + dlclose (h1); + if (h2 != NULL) + dlclose (h2); + + return result; +#else + return 0; +#endif +} + + +#include "../test-skeleton.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod-at-ctor.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod-at-ctor.c new file mode 100644 index 00000000..bd04b508 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod-at-ctor.c @@ -0,0 +1,25 @@ +#include +#include + +#define TLS_VAR_INIT_VALUE 99 + +#ifdef USE_TLS +__thread int tls_var __attribute__((tls_model("global-dynamic"))); +static __thread int local_tls_var __attribute__((tls_model("local-dynamic"))); +#endif + +void __attribute__((constructor)) libtls_ctor(void); +void libtls_ctor(void) +{ + printf("libtls: constructor!\n"); +#ifdef USE_TLS + local_tls_var = TLS_VAR_INIT_VALUE; + tls_var = local_tls_var; +#endif +} + +void __attribute__((destructor)) libtls_dtor(void); +void libtls_dtor(void) +{ + printf("libtls: destructor!\n"); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod1.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod1.c new file mode 100644 index 00000000..b4954ca3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod1.c @@ -0,0 +1,68 @@ +#include + +#include + +#ifdef USE_TLS +#include "tls-macros.h" + + +/* One define int variable, two externs. */ +COMMON_INT_DEF(foo); +VAR_INT_DEF(bar); +VAR_INT_DECL(baz); +#endif + +extern int in_dso (void); + +int +in_dso (void) +{ + int result = 0; +#ifdef USE_TLS + int *ap, *bp, *cp; + + /* Get variables using initial exec model. */ + fputs ("get sum of foo and bar (IE)", stdout); + __asm__ ("" ::: "memory"); + ap = TLS_IE (foo); + bp = TLS_IE (bar); + printf (" = %d\n", *ap + *bp); + result |= *ap + *bp != 3; + if (*ap != 1) + { + printf ("foo = %d\n", *ap); + result = 1; + } + if (*bp != 2) + { + printf ("bar = %d\n", *bp); + result = 1; + } + + + /* Get variables using generic dynamic model. */ + fputs ("get sum of foo and bar and baz (GD)", stdout); + ap = TLS_GD (foo); + bp = TLS_GD (bar); + cp = TLS_GD (baz); + printf (" = %d\n", *ap + *bp + *cp); + result |= *ap + *bp + *cp != 6; + if (*ap != 1) + { + printf ("foo = %d\n", *ap); + result = 1; + } + if (*bp != 2) + { + printf ("bar = %d\n", *bp); + result = 1; + } + if (*cp != 3) + { + printf ("baz = %d\n", *cp); + result = 1; + } +#endif + + return result; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod10.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod10.c new file mode 100644 index 00000000..32e54f3c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod10.c @@ -0,0 +1 @@ +#include "tst-tlsmod8.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod11.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod11.c new file mode 100644 index 00000000..9938b575 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod11.c @@ -0,0 +1,6 @@ +#include "tst-tls10.h" + +#ifdef USE_TLS__THREAD +__thread struct A a1 = { 4, 5, 6 }; +__thread struct A a2 = { 7, 8, 9 }; +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod12.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod12.c new file mode 100644 index 00000000..4602709a --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod12.c @@ -0,0 +1,14 @@ +#include "tst-tls10.h" + +#ifdef USE_TLS__THREAD +extern __thread struct A a2 __attribute__((tls_model("initial-exec"))); + +void +check1 (void) +{ + if (a1.a != 4 || a1.b != 5 || a1.c != 6) + abort (); + if (a2.a != 7 || a2.b != 8 || a2.c != 9) + abort (); +} +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod13.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod13.c new file mode 100644 index 00000000..beca89f6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod13.c @@ -0,0 +1,14 @@ +#include + +#if defined USE_TLS && defined HAVE___THREAD \ + && defined HAVE_TLS_MODEL_ATTRIBUTE +__thread int a[2] __attribute__ ((tls_model ("initial-exec"))); +#else +int a[2]; +#endif + +int +foo (void) +{ + return a[0]; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod13a.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod13a.c new file mode 100644 index 00000000..14b12b03 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod13a.c @@ -0,0 +1,16 @@ +#include + +#if defined USE_TLS && defined HAVE___THREAD \ + && defined HAVE_TLS_MODEL_ATTRIBUTE +__thread int b[2] __attribute__ ((tls_model ("initial-exec"))); +#else +int b[2]; +#endif + +extern int foo (void); + +int +bar (void) +{ + return foo () + b[0]; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod14a.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod14a.c new file mode 100644 index 00000000..0bb393d9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod14a.c @@ -0,0 +1,41 @@ +#include +#include + +#include + +#if USE_TLS && HAVE___THREAD + +#define AL 4096 +struct foo +{ + int i; +} __attribute ((aligned (AL))); + +static __thread struct foo f; +static struct foo g; + + +#ifndef FCT +# define FCT in_dso1 +#endif + + +int +FCT (void) +{ + puts (__func__); + + int result = 0; + + int fail = (((uintptr_t) &f) & (AL - 1)) != 0; + printf ("&f = %p %s\n", &f, fail ? "FAIL" : "OK"); + result |= fail; + + fail = (((uintptr_t) &g) & (AL - 1)) != 0; + printf ("&g = %p %s\n", &g, fail ? "FAIL" : "OK"); + result |= fail; + + return result; +} + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod14b.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod14b.c new file mode 100644 index 00000000..24d9ceaf --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod14b.c @@ -0,0 +1,2 @@ +#define FCT in_dso2 +#include "tst-tlsmod14a.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod15a.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod15a.c new file mode 100644 index 00000000..66c70712 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod15a.c @@ -0,0 +1,6 @@ +extern int nonexistent_dummy_var; +int * +foo (void) +{ + return &nonexistent_dummy_var; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod15b.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod15b.c new file mode 100644 index 00000000..4f63eab1 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod15b.c @@ -0,0 +1,17 @@ +#include "tst-tls10.h" + +#ifdef USE_TLS__THREAD +__thread int mod15b_var __attribute__((tls_model("initial-exec"))); + +int +in_dso (void) +{ + return mod15b_var; +} +#else +int +in_dso (void) +{ + return 0; +} +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod16a.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod16a.c new file mode 100644 index 00000000..847c8090 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod16a.c @@ -0,0 +1,7 @@ +#include + +#if defined HAVE___THREAD && defined HAVE_TLS_MODEL_ATTRIBUTE +int __thread tlsvar; +#else +int tlsvar; +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod16b.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod16b.c new file mode 100644 index 00000000..308e6bae --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod16b.c @@ -0,0 +1,13 @@ +#include + +#if defined HAVE___THREAD && defined HAVE_TLS_MODEL_ATTRIBUTE +extern __thread int tlsvar __attribute__((tls_model("initial-exec"))); +#else +extern int tlsvar; +#endif + +void * +in_dso (void) +{ + return &tlsvar; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod17a.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod17a.c new file mode 100644 index 00000000..4d396500 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod17a.c @@ -0,0 +1,23 @@ +#include + +#ifndef N +#define N 0 +#endif +#define CONCAT1(s, n) s##n +#define CONCAT(s, n) CONCAT1(s, n) + +__thread int CONCAT (v, N) = 4; + +int +CONCAT (tlsmod17a, N) (void) +{ + int *p = &CONCAT (v, N); + /* GCC assumes &var is never NULL, add optimization barrier. */ + __asm__ __volatile__ ("" : "+r" (p)); + if (p == NULL || *p != 4) + { + printf ("fail %d %p\n", N, p); + return 1; + } + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod17b.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod17b.c new file mode 100644 index 00000000..61788287 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod17b.c @@ -0,0 +1,15 @@ +#define P(N) extern int tlsmod17a##N (void); +#define PS P(0) P(1) P(2) P(3) P(4) P(5) P(6) P(7) P(8) P(9) \ + P(10) P(12) P(13) P(14) P(15) P(16) P(17) P(18) P(19) +PS +#undef P + +int +tlsmod17b (void) +{ + int res = 0; +#define P(N) res |= tlsmod17a##N (); + PS +#undef P + return res; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod18a.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod18a.c new file mode 100644 index 00000000..e0ae65a8 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod18a.c @@ -0,0 +1,21 @@ +#include + +#ifndef N +# define N 0 +#endif + +static __thread int var = 4; + +int +test (void) +{ + int *p = &var; + /* GCC assumes &var is never NULL, add optimization barrier. */ + __asm__ __volatile__ ("" : "+r" (p)); + if (p == NULL || *p != 4) + { + printf ("fail %d %p\n", N, p); + return 1; + } + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod2.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod2.c new file mode 100644 index 00000000..4547c971 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod2.c @@ -0,0 +1,38 @@ +#include + +#include + +#ifdef USE_TLS +#include "tls-macros.h" + + +COMMON_INT_DEF(foo); + + +int +in_dso (int n, int *caller_foop) +{ + int *foop; + int result = 0; + + puts ("foo"); /* Make sure PLT is used before macros. */ + __asm__ ("" ::: "memory"); + + foop = TLS_GD (foo); + + if (caller_foop != NULL && foop != caller_foop) + { + printf ("callers address of foo differs: %p vs %p\n", caller_foop, foop); + result = 1; + } + else if (*foop != n) + { + printf ("foo != %d\n", n); + result = 1; + } + + *foop = 16; + + return result; +} +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod3.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod3.c new file mode 100644 index 00000000..12505f62 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod3.c @@ -0,0 +1,41 @@ +#include + +#include + +#ifdef USE_TLS +# include "tls-macros.h" + +extern int in_dso (int n, int *caller_foop); + +COMMON_INT_DEF(comm_n); + + + + +int +in_dso2 (void) +{ + int *foop; + int result = 0; + static int n; + int *np; + + puts ("foo"); /* Make sure PLT is used before macros. */ + __asm__ ("" ::: "memory"); + + foop = TLS_GD (foo); + np = TLS_GD (comm_n); + + if (n != *np) + { + printf ("n = %d != comm_n = %d\n", n, *np); + result = 1; + } + + result |= in_dso (*foop = 42 + n++, foop); + + *foop = 16; + + return result; +} +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod4.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod4.c new file mode 100644 index 00000000..4893cdae --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod4.c @@ -0,0 +1,38 @@ +#include + +#include + +#ifdef USE_TLS +# include "tls-macros.h" + + +COMMON_INT_DEF(baz); + + +int +in_dso (int n, int *caller_bazp) +{ + int *bazp; + int result = 0; + + puts ("foo"); /* Make sure PLT is used before macros. */ + __asm__ ("" ::: "memory"); + + bazp = TLS_GD (baz); + + if (caller_bazp != NULL && bazp != caller_bazp) + { + printf ("callers address of baz differs: %p vs %p\n", caller_bazp, bazp); + result = 1; + } + else if (*bazp != n) + { + printf ("baz != %d\n", n); + result = 1; + } + + *bazp = 16; + + return result; +} +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod5.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod5.c new file mode 100644 index 00000000..2ec69e13 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod5.c @@ -0,0 +1,7 @@ +#include + +#ifdef USE_TLS +#include "tls-macros.h" + +COMMON_INT_DEF(foo); +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod6.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod6.c new file mode 100644 index 00000000..0fda51b2 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod6.c @@ -0,0 +1,7 @@ +#include + +#ifdef USE_TLS +#include "tls-macros.h" + +COMMON_INT_DEF(bar); +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod7.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod7.c new file mode 100644 index 00000000..944b97f9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod7.c @@ -0,0 +1,103 @@ +#include "tst-tls10.h" + +#ifdef USE_TLS__THREAD +__thread int dummy __attribute__((visibility ("hidden"))) = 12; +__thread struct A a1 = { 4, 5, 6 }; +__thread struct A a2 = { 7, 8, 9 }; +__thread struct A a3 __attribute__((tls_model("initial-exec"))) + = { 10, 11, 12 }; +__thread struct A a4 __attribute__((tls_model("initial-exec"))) + = { 13, 14, 15 }; +static __thread struct A local1 = { 16, 17, 18 }; +static __thread struct A local2 __attribute__((tls_model("initial-exec"))) + = { 19, 20, 21 }; + +void +check1 (void) +{ + if (a1.a != 4 || a1.b != 5 || a1.c != 6) + abort (); + if (a2.a != 22 || a2.b != 23 || a2.c != 24) + abort (); + if (a3.a != 10 || a3.b != 11 || a3.c != 12) + abort (); + if (a4.a != 25 || a4.b != 26 || a4.c != 27) + abort (); + if (local1.a != 16 || local1.b != 17 || local1.c != 18) + abort (); + if (local2.a != 19 || local2.b != 20 || local2.c != 21) + abort (); +} + +struct A * +f1a (void) +{ + return &a1; +} + +struct A * +f2a (void) +{ + return &a2; +} + +struct A * +f3a (void) +{ + return &a3; +} + +struct A * +f4a (void) +{ + return &a4; +} + +struct A * +f5a (void) +{ + return &local1; +} + +struct A * +f6a (void) +{ + return &local2; +} + +int +f1b (void) +{ + return a1.a; +} + +int +f2b (void) +{ + return a2.b; +} + +int +f3b (void) +{ + return a3.c; +} + +int +f4b (void) +{ + return a4.a; +} + +int +f5b (void) +{ + return local1.b; +} + +int +f6b (void) +{ + return local2.c; +} +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod8.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod8.c new file mode 100644 index 00000000..c1822fc0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod8.c @@ -0,0 +1,72 @@ +#include "tst-tls10.h" + +#ifdef USE_TLS__THREAD +__thread long long dummy __attribute__((visibility ("hidden"))) = 12; +__thread struct A a2 = { 22, 23, 24 }; +__thread struct A a4 __attribute__((tls_model("initial-exec"))) + = { 25, 26, 27 }; +static __thread struct A local1 = { 28, 29, 30 }; +static __thread struct A local2 __attribute__((tls_model("initial-exec"))) + = { 31, 32, 33 }; + +void +check2 (void) +{ + if (a2.a != 22 || a2.b != 23 || a2.c != 24) + abort (); + if (a4.a != 25 || a4.b != 26 || a4.c != 27) + abort (); + if (local1.a != 28 || local1.b != 29 || local1.c != 30) + abort (); + if (local2.a != 31 || local2.b != 32 || local2.c != 33) + abort (); +} + +struct A * +f7a (void) +{ + return &a2; +} + +struct A * +f8a (void) +{ + return &a4; +} + +struct A * +f9a (void) +{ + return &local1; +} + +struct A * +f10a (void) +{ + return &local2; +} + +int +f7b (void) +{ + return a2.b; +} + +int +f8b (void) +{ + return a4.a; +} + +int +f9b (void) +{ + return local1.b; +} + +int +f10b (void) +{ + return local2.c; +} +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod9.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod9.c new file mode 100644 index 00000000..e124144e --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/tls/tst-tlsmod9.c @@ -0,0 +1,101 @@ +#include "tst-tls10.h" + +#ifdef USE_TLS__THREAD +__thread int dummy __attribute__((visibility ("hidden"))) = 12; +__thread struct A a1 = { 4, 5, 6 }; +__thread struct A a3 __attribute__((tls_model("initial-exec"))) + = { 10, 11, 12 }; +extern __thread struct A a4 __attribute__((tls_model("initial-exec"))); +static __thread struct A local1 = { 16, 17, 18 }; +static __thread struct A local2 __attribute__((tls_model("initial-exec"))) + = { 19, 20, 21 }; + +void +check1 (void) +{ + if (a1.a != 4 || a1.b != 5 || a1.c != 6) + abort (); + if (a2.a != 22 || a2.b != 23 || a2.c != 24) + abort (); + if (a3.a != 10 || a3.b != 11 || a3.c != 12) + abort (); + if (a4.a != 25 || a4.b != 26 || a4.c != 27) + abort (); + if (local1.a != 16 || local1.b != 17 || local1.c != 18) + abort (); + if (local2.a != 19 || local2.b != 20 || local2.c != 21) + abort (); +} + +struct A * +f1a (void) +{ + return &a1; +} + +struct A * +f2a (void) +{ + return &a2; +} + +struct A * +f3a (void) +{ + return &a3; +} + +struct A * +f4a (void) +{ + return &a4; +} + +struct A * +f5a (void) +{ + return &local1; +} + +struct A * +f6a (void) +{ + return &local2; +} + +int +f1b (void) +{ + return a1.a; +} + +int +f2b (void) +{ + return a2.b; +} + +int +f3b (void) +{ + return a3.c; +} + +int +f4b (void) +{ + return a4.a; +} + +int +f5b (void) +{ + return local1.b; +} + +int +f6b (void) +{ + return local2.c; +} +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/unistd/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/test/unistd/Makefile new file mode 100644 index 00000000..0dbd52e9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/unistd/Makefile @@ -0,0 +1,7 @@ +# uClibc unistd tests +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + +top_builddir=../../ +include ../Rules.mak +-include Makefile.in +include ../Test.mak diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/unistd/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/test/unistd/Makefile.in new file mode 100644 index 00000000..c542f98f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/unistd/Makefile.in @@ -0,0 +1,23 @@ +# uClibc unistd tests +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + +ifeq ($(UCLIBC_HAS_LFS),) +TESTS_DISABLED := tst-preadwrite64 +endif +OPTS_getopt := -abcXXX -9 +OPTS_getopt_long := --add XXX --delete YYY --verbose +ifeq ($(UCLIBC_HAS_GNU_GETOPT),y) +OPTS_tstgetopt := -a -b -cfoobar --required foobar --optional=bazbug --none random --col --color --colour +else +# reordering is not supported, behaves as if POSIXLY_CORRECT would be set +OPTS_tstgetopt := -a -b -cfoobar --required foobar --optional=bazbug --none --colou --color --colour random +endif + +# getconf.c lives in utils/ +# Testsuite cannot currently be built with O= anyway, so hardcode path here +getconf.c: + $(LN_S) ../../utils/$(@F) . +EXTRA_CLEAN += getconf.c +TESTS_DISABLED += getconf +CFLAGS_getconf = -DGETCONF_DIR='"$(CURDIR)"' +shell_tst-getconf: getconf getconf_glibc diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/unistd/clone.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/unistd/clone.c new file mode 100644 index 00000000..ea7e6ac6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/unistd/clone.c @@ -0,0 +1,101 @@ +/* vi: set sw=4 ts=4: */ +/* + * clone test for uClibc + * Copyright (C) 2000-2006 by Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include +#include +#include +#include "clone_cruft.h" + +#define GOT1 (1 << 1) +#define GOT2 (1 << 2) +#define GOT3 (1 << 3) +#define ALLGOT (GOT1|GOT2|GOT3) + +static void child_handler(int sig) +{ + printf("I got a SIGCHLD\n"); +} + +static int clone_main(void *arg) +{ + unsigned long input = (unsigned long)arg; + int secs = (input / 10) * 4; + printf("Clone got %lu, sleeping for %i secs\n", input, secs); + sleep(secs); + return input + 20; +} + +int main(void) +{ + int clone1, clone2, clone3; + char clone1_stack[8192], clone2_stack[8192], clone3_stack[8192]; + int status, nostatus, result, wpid; + + signal(SIGCHLD, child_handler); + + if ((clone1 = do_clone(clone_main, clone1_stack, 0, (void*)11)) == -1) { + perror("Clone 1 failed"); + exit(-1); + } + if ((clone2 = do_clone(clone_main, clone2_stack, 0, (void*)22)) == -1) { + perror("Clone 2 failed"); + exit(-2); + } + if ((clone3 = do_clone(clone_main, clone3_stack, 0, (void*)33)) == -1) { + perror("Clone 3 failed"); + exit(-3); + } + + sleep(1); + printf("Parent: waiting for the clones to die.\n"); + nostatus = status = 0; + while (1) { + if ((wpid = waitpid(clone1, &result, WNOHANG|__WCLONE)) == -1) + nostatus |= GOT1; + if (wpid == clone1) { + status |= GOT1; + printf("Clone1 gave back %i\n", WEXITSTATUS(result)); + } + + if ((wpid = waitpid(clone2, &result, WNOHANG|__WCLONE)) == -1) + nostatus |= GOT2; + if (wpid == clone2) { + status |= GOT2; + printf("Clone2 gave back %i\n", WEXITSTATUS(result)); + } + + if ((wpid = waitpid(clone3, &result, WNOHANG|__WCLONE)) == -1) + nostatus |= GOT3; + if (wpid == clone3) { + status |= GOT3; + printf("Clone3 gave back %i\n", WEXITSTATUS(result)); + } + + if (status == ALLGOT || nostatus == ALLGOT) + break; + } + + if (status == ALLGOT) { + printf("Clones exited.\nGoodbye.\n"); + return EXIT_SUCCESS; + } else { + perror("Waiting for clones failed"); + return EXIT_FAILURE; + } +} + +/* +Local Variables: +c-file-style: "linux" +c-basic-offset: 4 +tab-width: 4 +End: +*/ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/unistd/clone_cruft.h b/l4/pkg/uclibc/lib/contrib/uclibc/test/unistd/clone_cruft.h new file mode 100644 index 00000000..b6a395d0 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/unistd/clone_cruft.h @@ -0,0 +1,24 @@ +/* because people like to make things difficult */ + +#undef do_clone + +#define crappy_sizeof(s) (s == NULL ? 0 : sizeof(s)) + +#if defined __ia64__ + +extern int __clone2 (int (*__fn) (void *__arg), void *__child_stack_base, + size_t __child_stack_size, int __flags, void *__arg, ...); +# define do_clone(fn, stack, flags, arg) \ + __clone2(fn, stack, crappy_sizeof(stack), flags, arg, NULL, NULL, NULL) + +#elif defined __hppa__ + +# define do_clone(fn, stack, flags, arg) \ + clone(fn, stack, flags, arg) + +#else + +# define do_clone(fn, stack, flags, arg) \ + clone(fn, stack+crappy_sizeof(stack), flags, arg) + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/unistd/errno.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/unistd/errno.c new file mode 100644 index 00000000..5d4fc726 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/unistd/errno.c @@ -0,0 +1,29 @@ +/* based originally on one the clone tests in the LTP */ + +#include +#include +#include +#include +#include "clone_cruft.h" + +__attribute__ ((__noreturn__)) +static int child_fn(void *arg) +{ + fprintf(stderr, "in child_fn\n"); + exit(1); +} + +int main(void) +{ + int r_clone, ret_errno; + + r_clone = do_clone(child_fn, NULL, 0, NULL); + ret_errno = errno; + if (ret_errno != EINVAL || r_clone != -1) { + fprintf(stderr, "clone: res=%d (wanted -1) errno=%d (wanted %d)\n", + r_clone, errno, EINVAL); + return 1; + } + + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/unistd/exec-null.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/unistd/exec-null.c new file mode 100644 index 00000000..3df99f3c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/unistd/exec-null.c @@ -0,0 +1,13 @@ +/* make sure we handle argv[0] == NULL */ + +#include + +int main(int argc, char *argv[]) +{ + if (argc == 0) + return 0; + + char *exec_argv[1], *exec_envp[1]; + exec_argv[0] = exec_envp[0] = NULL; + return execve("./exec-null", exec_argv, exec_envp); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/unistd/fork.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/unistd/fork.c new file mode 100644 index 00000000..6d132d6d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/unistd/fork.c @@ -0,0 +1,91 @@ +/* vi: set sw=4 ts=4: */ +/* + * fork test for uClibc + * Copyright (C) 2000-2006 by Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include +#include + +#define GOT1 (1 << 1) +#define GOT2 (1 << 2) +#define GOT3 (1 << 3) + +#ifdef __ARCH_USE_MMU__ + +static void child_handler(int sig) +{ + fprintf(stderr, "I got a SIGCHLD\n"); +} + +int main(void) +{ + pid_t pid1, pid2, pid3; + int status, result, wpid; + + signal(SIGCHLD, child_handler); + + if ((pid1 = fork()) == 0) { + fprintf(stderr, "The child process sleeps 2 seconds...\n"); + sleep(4); + fprintf(stderr, "Child exiting.\n"); + exit(-1); + } + if ((pid2 = fork()) == 0) { + fprintf(stderr, "The child process sleeps 3 seconds...\n"); + sleep(3); + fprintf(stderr, "Child exiting.\n"); + exit(-1); + } + if ((pid3 = fork()) == 0) { + fprintf(stderr, "The child process sleeps 4 seconds...\n"); + sleep(2); + fprintf(stderr, "Child exiting.\n"); + exit(-1); + } + + fprintf(stderr, "Parent: waiting for the child to die.\n"); + status = 0; + while (1) { + wpid = waitpid(pid1, &result, WNOHANG); + if (wpid == pid1) + status |= GOT1; + + wpid = waitpid(pid2, &result, WNOHANG); + if (wpid == pid2) + status |= GOT2; + + wpid = waitpid(pid3, &result, WNOHANG); + if (wpid == pid3) + status |= GOT3; + + if (status == (GOT1 | GOT2 | GOT3)) + break; + } + + fprintf(stderr, "Child process exited.\nGoodbye.\n"); + return EXIT_SUCCESS; +} + +#else + +int main(void) +{ + printf("Skipping test on non-mmu host!\n"); + return EXIT_SUCCESS; +} + +#endif + +/* +Local Variables: +c-file-style: "linux" +c-basic-offset: 4 +tab-width: 4 +End: +*/ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/unistd/getcwd.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/unistd/getcwd.c new file mode 100644 index 00000000..bcecec7b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/unistd/getcwd.c @@ -0,0 +1,39 @@ +/* vi: set sw=4 ts=4: */ +/* + * fork test for uClibc + * Copyright (C) 2000-2006 by Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include + +int main(void) +{ + char *foo; + char junk[12]; + char crap[100]; + foo = getcwd(NULL, 0); + printf("getcwd(NULL, 0)='%s'\n", foo); + if (foo) { free(foo); } + foo = getcwd(NULL, 100); + printf("\ngetcwd(NULL, 100)='%s'\n", foo); + if (foo) { free(foo); } + foo = getcwd(junk, sizeof(junk)); + printf("\nchar junk[12];\n"); + printf("getcwd(junk, sizeof(junk))='%s'\n", foo); + foo = getcwd(crap, sizeof(crap)); + printf("\nchar crap[100];\n"); + printf("getcwd(crap, sizeof(crap))='%s'\n", foo); + return EXIT_SUCCESS; +} + +/* +Local Variables: +c-file-style: "linux" +c-basic-offset: 4 +tab-width: 4 +End: +*/ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/unistd/getopt.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/unistd/getopt.c new file mode 100644 index 00000000..401765cc --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/unistd/getopt.c @@ -0,0 +1,69 @@ +/* Getopt tests */ + +#include +#include +#include +#include + + +int main (int argc, char **argv) +{ + int c; + int digit_optind = 0; + + while (1) + { + int this_option_optind = optind ? optind : 1; + + c = getopt (argc, argv, "abc:d:0123456789"); + if (c == EOF) + break; + + switch (c) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if (digit_optind != 0 && digit_optind != this_option_optind) + printf ("digits occur in two different argv-elements.\n"); + digit_optind = this_option_optind; + printf ("option %c\n", c); + break; + + case 'a': + printf ("option a\n"); + break; + + case 'b': + printf ("option b\n"); + break; + + case 'c': + printf ("option c with value `%s'\n", optarg); + break; + + case '?': + break; + + default: + printf ("?? getopt returned character code 0%o ??\n", c); + } + } + + if (optind < argc) + { + printf ("non-option ARGV-elements: "); + while (optind < argc) + printf ("%s ", argv[optind++]); + printf ("\n"); + } + exit (0); +} + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/unistd/getopt_long.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/unistd/getopt_long.c new file mode 100644 index 00000000..4064e224 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/unistd/getopt_long.c @@ -0,0 +1,93 @@ +/* Getopt tests */ + +#include +#include +#include +#include + + +int main (int argc, char **argv) +{ + int c; + int digit_optind = 0; + + while (1) + { + int this_option_optind = optind ? optind : 1; + int option_index = 0; + static struct option long_options[] = + { + {"add", 1, 0, 0}, + {"append", 0, 0, 0}, + {"delete", 1, 0, 0}, + {"verbose", 0, 0, 0}, + {"create", 0, 0, 0}, + {"file", 1, 0, 0}, + {0, 0, 0, 0} + }; + + c = getopt_long (argc, argv, "abc:d:0123456789", + long_options, &option_index); + if (c == EOF) + break; + + switch (c) + { + case 0: + printf ("option %s", long_options[option_index].name); + if (optarg) + printf (" with arg %s", optarg); + printf ("\n"); + break; + + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if (digit_optind != 0 && digit_optind != this_option_optind) + printf ("digits occur in two different argv-elements.\n"); + digit_optind = this_option_optind; + printf ("option %c\n", c); + break; + + case 'a': + printf ("option a\n"); + break; + + case 'b': + printf ("option b\n"); + break; + + case 'c': + printf ("option c with value `%s'\n", optarg); + break; + + case 'd': + printf ("option d with value `%s'\n", optarg); + break; + + case '?': + break; + + default: + printf ("?? getopt returned character code 0%o ??\n", c); + } + } + + if (optind < argc) + { + printf ("non-option ARGV-elements: "); + while (optind < argc) + printf ("%s ", argv[optind++]); + printf ("\n"); + } + + exit (0); +} + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/unistd/tst-getconf.sh b/l4/pkg/uclibc/lib/contrib/uclibc/test/unistd/tst-getconf.sh new file mode 100644 index 00000000..3a2aa4ea --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/unistd/tst-getconf.sh @@ -0,0 +1,240 @@ +#! /bin/sh + +basedir="." + +# make sure to use the same locale everywhere. +LC_ALL=C +export LC_ALL +LANG=C +export LANG + +for suffix in _glibc '' +do +binary=$basedir/getconf$suffix +logfile=$basedir/tst-getconf$suffix.out +rm -f $logfile + +result=0 +while read name; do + case "$name" in + "#"*) continue;; + esac + echo -n "getconf $name: " >> $logfile + $binary "$name" 2>> $logfile >> $logfile + if test $? -ne 0; then + echo "*** $name FAILED" >> $logfile + result=1 + fi +done <> $logfile + $binary "$name" / 2>> $logfile >> $logfile + if test $? -ne 0; then + echo "*** $name FAILED" >> $logfile + result=1 + fi +done <, 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + + +/* Allow testing of the 64-bit versions as well. */ +#ifndef PREAD +# define PREAD pread +# define PWRITE pwrite +#endif + +#define STRINGIFY(s) STRINGIFY2 (s) +#define STRINGIFY2(s) #s + +/* Prototype for our test function. */ +extern void do_prepare (int argc, char *argv[]); +extern int do_test (int argc, char *argv[]); + +/* We have a preparation function. */ +#define PREPARE do_prepare + +/* We might need a bit longer timeout. */ +#define TIMEOUT 20 /* sec */ + +/* This defines the `main' function and some more. */ +#include "../test-skeleton.c" + +/* These are for the temporary file we generate. */ +char *name; +int fd; + +void +do_prepare (int argc, char *argv[]) +{ + char name_len; + +#define FNAME FNAME2(TRUNCATE) +#define FNAME2(s) "/" STRINGIFY(s) "XXXXXX" + + name_len = strlen (test_dir); + name = malloc (name_len + sizeof (FNAME)); + if (name == NULL) + error (EXIT_FAILURE, errno, "cannot allocate file name"); + mempcpy (mempcpy (name, test_dir, name_len), FNAME, sizeof (FNAME)); + add_temp_file (name); + + /* Open our test file. */ + fd = mkstemp (name); + if (fd == -1) + error (EXIT_FAILURE, errno, "cannot open test file `%s'", name); +} + + +int +do_test (int argc, char *argv[]) +{ + char buf[1000]; + char res[1000]; + int i; + + memset (buf, '\0', sizeof (buf)); + memset (res, '\xff', sizeof (res)); + + if (write (fd, buf, sizeof (buf)) != sizeof (buf)) + error (EXIT_FAILURE, errno, "during write"); + + for (i = 100; i < 200; ++i) + buf[i] = i; + if (PWRITE (fd, buf + 100, 100, 100) != 100) + error (EXIT_FAILURE, errno, "during %s", STRINGIFY (PWRITE)); + + for (i = 450; i < 600; ++i) + buf[i] = i; + if (PWRITE (fd, buf + 450, 150, 450) != 150) + error (EXIT_FAILURE, errno, "during %s", STRINGIFY (PWRITE)); + + if (PREAD (fd, res, sizeof (buf) - 50, 50) != sizeof (buf) - 50) + error (EXIT_FAILURE, errno, "during %s", STRINGIFY (PREAD)); + + close (fd); + unlink (name); + + return memcmp (buf + 50, res, sizeof (buf) - 50); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/unistd/tst-preadwrite64.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/unistd/tst-preadwrite64.c new file mode 100644 index 00000000..57098e86 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/unistd/tst-preadwrite64.c @@ -0,0 +1,24 @@ +/* Tests for pread64 and pwrite64. + Copyright (C) 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#define PREAD pread64 +#define PWRITE pwrite64 + +#include "tst-preadwrite.c" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/unistd/tstgetopt.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/unistd/tstgetopt.c new file mode 100644 index 00000000..1c1263e6 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/unistd/tstgetopt.c @@ -0,0 +1,76 @@ +#include +#include +#include +#include + +int +main (int argc, char **argv) +{ + static const struct option options[] = + { + {"required", required_argument, NULL, 'r'}, + {"optional", optional_argument, NULL, 'o'}, + {"none", no_argument, NULL, 'n'}, + {"color", no_argument, NULL, 'C'}, + {"colour", no_argument, NULL, 'C'}, + {NULL, 0, NULL, 0 } + }; + + int aflag = 0; + int bflag = 0; + char *cvalue = NULL; + int Cflag = 0; + int nflag = 0; + int idx; + int c; + int result = 0; + + while ((c = getopt_long (argc, argv, "abc:", options, NULL)) >= 0) + switch (c) + { + case 'a': + aflag = 1; + break; + case 'b': + bflag = 1; + break; + case 'c': + cvalue = optarg; + break; + case 'C': + ++Cflag; + break; + case '?': + fputs ("Unknown option.\n", stderr); + return 1; + default: + fprintf (stderr, "This should never happen!\n"); + return 1; + + case 'r': + printf ("--required %s\n", optarg); + result |= strcmp (optarg, "foobar") != 0; + break; + case 'o': + printf ("--optional %s\n", optarg); + result |= optarg == NULL || strcmp (optarg, "bazbug") != 0; + break; + case 'n': + puts ("--none"); + nflag = 1; + break; + } + + printf ("aflag = %d, bflag = %d, cvalue = %s, Cflags = %d, nflag = %d\n", + aflag, bflag, cvalue, Cflag, nflag); + + result |= (aflag != 1 || bflag != 1 || cvalue == NULL + || strcmp (cvalue, "foobar") != 0 || Cflag != 3 || nflag != 1); + + for (idx = optind; idx < argc; idx++) + printf ("Non-option argument %s\n", argv[idx]); + + result |= optind + 1 != argc || strcmp (argv[optind], "random") != 0; + + return result; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/test/unistd/vfork.c b/l4/pkg/uclibc/lib/contrib/uclibc/test/unistd/vfork.c new file mode 100644 index 00000000..29558394 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/test/unistd/vfork.c @@ -0,0 +1,53 @@ +/* vi: set sw=4 ts=4: */ +/* + * vfork test for uClibc + * Copyright (C) 2000-2006 by Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include +#include + + +int main(void) +{ + pid_t pid; + int status, wpid; + char *argv[] = { + "/bin/ls", + "-laF", + NULL, + }; + + clearenv(); + if ((pid = vfork()) == 0) { + printf("Hi. I'm the child process...\n"); + execvp(argv[0], argv); + _exit(0); + } + + printf("Hello. I'm the parent process.\n"); + while (1) { + wpid = wait(&status); + if (wpid > 0 && wpid != pid) { + continue; + } + if (wpid == pid) + break; + } + + printf("Child process exited.\nGoodbye.\n"); + return EXIT_SUCCESS; +} + +/* +Local Variables: +c-file-style: "linux" +c-basic-offset: 4 +tab-width: 4 +End: +*/ diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/utils/.gitignore b/l4/pkg/uclibc/lib/contrib/uclibc/utils/.gitignore new file mode 100644 index 00000000..7cdfa90c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/utils/.gitignore @@ -0,0 +1,12 @@ +getconf +getconf.host +iconv +iconv.host +ldconfig +ldconfig.host +ldd +ldd.host +locale +locale.host +getconf +getconf.host diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/utils/Makefile b/l4/pkg/uclibc/lib/contrib/uclibc/utils/Makefile new file mode 100644 index 00000000..bdaea9fd --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/utils/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../ +top_builddir=../ +include $(top_builddir)Rules.mak +all: utils +include Makefile.in +include $(top_srcdir)Makerules diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/utils/Makefile.in b/l4/pkg/uclibc/lib/contrib/uclibc/utils/Makefile.in new file mode 100644 index 00000000..65364d77 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/utils/Makefile.in @@ -0,0 +1,138 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2009 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + +subdirs += utils + +# "make utils" flags + +CFLAGS-utils := \ + $(SSP_ALL_CFLAGS) \ + -I$(top_srcdir)ldso/include \ + -DUCLIBC_RUNTIME_PREFIX=\"$(RUNTIME_PREFIX)\" \ + -DUCLIBC_LDSO=$(UCLIBC_LDSO) \ + -I$(top_srcdir)/$(KERNEL_HEADERS) \ + -DNOT_IN_libc \ + -B$(top_builddir)lib \ + -Wl,-rpath-link,$(top_builddir)lib + +ifeq ($(UCLIBC_BUILD_PIE),y) +CFLAGS-utils-shared := $(PIEFLAG) $(LDPIEFLAG) +else +CFLAGS-utils-shared := +endif + +CFLAGS-ldconfig := -DBUILDING_LINKAGE +ifeq ($(UCLIBC_STATIC_LDCONFIG),y) +CFLAGS-ldconfig += -static +else +CFLAGS-ldconfig += $(CFLAGS-utils-shared) +endif + +CFLAGS-ldd := $(CFLAGS-utils-shared) -DBUILDING_LINKAGE + +# Need CFLAGS-utils explicitly, because the source file is not located in utils +CFLAGS-iconv := $(CFLAGS-utils) \ + $(CFLAGS-utils-shared) \ + -I$(top_srcdir)libc/misc/wchar \ + -DL_iconv_main \ + +CFLAGS-locale := $(CFLAGS-utils) +CFLAGS-getconf :=$(CFLAGS-utils) \ + -DGETCONF_DIR='"$(CURDIR)"' + +# "make hostutils" flags + +ifeq ($(LDSO_CACHE_SUPPORT),y) +LDSO_CACHE_SUPPORT := -D__LDSO_CACHE_SUPPORT__=1 +endif + +BUILD_CFLAGS-utils := \ + -DUCLIBC_RUNTIME_PREFIX=\"$(RUNTIME_PREFIX)\" \ + -DUCLIBC_LDSO=$(UCLIBC_LDSO) \ + $(LDSO_CACHE_SUPPORT) +BUILD_CFLAGS-ldconfig.host := $(BUILD_CFLAGS-utils) \ + -DBUILDING_LINKAGE \ + -I$(top_srcdir)ldso/include +BUILD_CFLAGS-ldd.host := $(BUILD_CFLAGS-utils) \ + -DBUILDING_LINKAGE \ + -I$(top_srcdir)ldso/include \ + -include $(top_srcdir)include/elf.h +BUILD_CFLAGS-locale.host := $(BUILD_CFLAGS-utils) \ + -DNOT_IN_libc \ + -I$(top_srcdir)utils/ \ + -I. +BUILD_CFLAGS-iconv.host := $(BUILD_CFLAGS-utils) \ + -include $(top_builddir)extra/locale/c8tables.h \ + -I$(top_srcdir)libc/misc/wchar -DL_iconv_main + +BUILD_CFLAGS-getconf.host := $(BUILD_CFLAGS-utils) \ + -DGETCONF_DIR='"$(CURDIR)"' + +# Rules + +utils_DIR := $(top_srcdir)utils +utils_OUT := $(top_builddir)utils + +DEPS-ldconfig := $(utils_DIR)/chroot_realpath.c +DEPS-ldconfig.host := $(DEPS-ldconfig) + +utils_OBJ := getconf +ifeq ($(HAVE_SHARED),y) +utils_OBJ += ldconfig ldd +endif + +utils_LOCALE_OBJ := +ifeq ($(UCLIBC_HAS_LOCALE),y) +utils_OBJ += iconv +#utils_LOCALE_OBJ += $(utils_OUT)/locale +endif + +utils_OBJ := $(patsubst %,$(utils_OUT)/%,$(utils_OBJ)) + +hostutils_OBJ := $(patsubst %,%.host,$(utils_OBJ)) +hostutils_LOCALE_OBJ := $(patsubst %,%.host,$(utils_LOCALE_OBJ)) + +utils: $(utils_OBJ) $(utils_LOCALE_OBJ) + +# NOTE: We build the utils AFTER we have a uClibc-targeted toolchain. + +$(utils_OBJ): $(utils_OUT)/% : $(utils_DIR)/%.c | $(libc) + $(compile.u) + +$(utils_OUT)/locale: $(top_srcdir)extra/locale/programs/locale.c | $(libc) + $(compile.u) + +$(utils_OUT)/locale.host: $(top_srcdir)extra/locale/programs/locale.c | $(libc) + $(hcompile.u) + +hostutils: $(hostutils_OBJ) $(hostutils_LOCALE_OBJ) + +$(hostutils_OBJ): $(utils_OUT)/%.host : $(utils_DIR)/%.c + $(hcompile.u) + + +install-y += utils_install + +# This installs both utils and hostutils, so doesn't depend on either. + +utils_install: $(addsuffix $(DOTHOST), $(utils_OBJ) $(utils_LOCALE_OBJ)) + $(Q)$(INSTALL) -D -m 755 $(utils_OUT)/getconf$(DOTHOST) $(PREFIX)$(DEVEL_PREFIX)bin/getconf +ifeq ($(HAVE_SHARED),y) + $(Q)$(INSTALL) -D -m 755 $(utils_OUT)/ldd$(DOTHOST) $(PREFIX)$(DEVEL_PREFIX)bin/ldd + $(Q)$(INSTALL) -D -m 755 $(utils_OUT)/ldconfig$(DOTHOST) $(PREFIX)$(RUNTIME_PREFIX)sbin/ldconfig +endif +ifeq ($(UCLIBC_HAS_LOCALE),y) + $(Q)$(INSTALL) -D -m 755 $(utils_OUT)/iconv$(DOTHOST) $(PREFIX)$(DEVEL_PREFIX)bin/iconv + #$(Q)$(INSTALL) -m 755 $(utils_OUT)/locale$(DOTHOST) $(PREFIX)$(DEVEL_PREFIX)bin/locale +endif + + +objclean-y += CLEAN_utils + +CLEAN_utils: + $(do_rm) $(addprefix $(utils_OUT)/, getconf iconv ldconfig ldd locale *.host) + $(Q)# This is a hack.. + $(Q)$(RM) $(utils_OUT)/.*.dep diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/utils/bswap.h b/l4/pkg/uclibc/lib/contrib/uclibc/utils/bswap.h new file mode 100644 index 00000000..0047e4e9 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/utils/bswap.h @@ -0,0 +1,45 @@ +/* + * Lame bswap replacements as we can't assume the host is sane and provides + * working versions of these. + */ + +#ifndef _BSWAP_H +#define _BSWAP_H 1 + +#ifdef __linux__ +# include +#else + +static __inline__ uint16_t bswap_16(uint16_t x) +{ + return ((((x) & 0xff00) >> 8) | \ + (((x) & 0x00ff) << 8)); +} +static __inline__ uint32_t bswap_32(uint32_t x) +{ + return ((((x) & 0xff000000) >> 24) | \ + (((x) & 0x00ff0000) >> 8) | \ + (((x) & 0x0000ff00) << 8) | \ + (((x) & 0x000000ff) << 24)); +} +static __inline__ uint64_t bswap_64(uint64_t x) +{ +#define _uswap_64(x, sfx) \ + return ((((x) & 0xff00000000000000##sfx) >> 56) | \ + (((x) & 0x00ff000000000000##sfx) >> 40) | \ + (((x) & 0x0000ff0000000000##sfx) >> 24) | \ + (((x) & 0x000000ff00000000##sfx) >> 8) | \ + (((x) & 0x00000000ff000000##sfx) << 8) | \ + (((x) & 0x0000000000ff0000##sfx) << 24) | \ + (((x) & 0x000000000000ff00##sfx) << 40) | \ + (((x) & 0x00000000000000ff##sfx) << 56)); +#if defined(__GNUC__) + _uswap_64(x, ull) +#else + _uswap_64(x, ) +#endif +#undef _uswap_64 +} +#endif + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/utils/chroot_realpath.c b/l4/pkg/uclibc/lib/contrib/uclibc/utils/chroot_realpath.c new file mode 100644 index 00000000..0be57bf1 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/utils/chroot_realpath.c @@ -0,0 +1,152 @@ +/* + * chroot_realpath.c -- resolve pathname as if inside chroot + * Based on realpath.c Copyright (C) 1993 Rick Sladkey + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; see the file COPYING.LIB. If not, + * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * 2005/09/12: Dan Howell (modified from realpath.c to emulate chroot) + */ + +#include "porting.h" + +#define MAX_READLINKS 32 + +char *chroot_realpath(const char *root, const char *path, + char resolved_path[]); + +char *chroot_realpath(const char *root, const char *path, + char resolved_path[]) +{ + char copy_path[PATH_MAX]; + char link_path[PATH_MAX]; + char got_path[PATH_MAX]; + char *got_path_root = got_path; + char *new_path = got_path; + char *max_path; + int readlinks = 0; + int n; + int chroot_len; + + /* Trivial case. */ + if (root == NULL || *root == '\0' || + (*root == '/' && root[1] == '\0')) { + strcpy(resolved_path, path); + return resolved_path; + } + + chroot_len = strlen(root); + + if (chroot_len + strlen(path) >= PATH_MAX - 3) { + errno = ENAMETOOLONG; + return NULL; + } + + /* Make a copy of the source path since we may need to modify it. */ + strcpy(copy_path, path); + path = copy_path; + max_path = copy_path + PATH_MAX - chroot_len - 3; + + /* Start with the chroot path. */ + strcpy(new_path, root); + new_path += chroot_len; + while (*new_path == '/' && new_path > got_path) + new_path--; + got_path_root = new_path; + *new_path++ = '/'; + + /* Expand each slash-separated pathname component. */ + while (*path != '\0') { + /* Ignore stray "/". */ + if (*path == '/') { + path++; + continue; + } + if (*path == '.') { + /* Ignore ".". */ + if (path[1] == '\0' || path[1] == '/') { + path++; + continue; + } + if (path[1] == '.') { + if (path[2] == '\0' || path[2] == '/') { + path += 2; + /* Ignore ".." at root. */ + if (new_path == got_path_root + 1) + continue; + /* Handle ".." by backing up. */ + while ((--new_path)[-1] != '/') ; + continue; + } + } + } + /* Safely copy the next pathname component. */ + while (*path != '\0' && *path != '/') { + if (path > max_path) { + errno = ENAMETOOLONG; + return NULL; + } + *new_path++ = *path++; + } + if (*path == '\0') + /* Don't follow symlink for last pathname component. */ + break; +#ifdef S_IFLNK + /* Protect against infinite loops. */ + if (readlinks++ > MAX_READLINKS) { + errno = ELOOP; + return NULL; + } + /* See if latest pathname component is a symlink. */ + *new_path = '\0'; + n = readlink(got_path, link_path, PATH_MAX - 1); + if (n < 0) { + /* EINVAL means the file exists but isn't a symlink. */ + if (errno != EINVAL) { + /* Make sure it's null terminated. */ + *new_path = '\0'; + strcpy(resolved_path, got_path); + return NULL; + } + } else { + /* Note: readlink doesn't add the null byte. */ + link_path[n] = '\0'; + if (*link_path == '/') + /* Start over for an absolute symlink. */ + new_path = got_path_root; + else + /* Otherwise back up over this component. */ + while (*(--new_path) != '/') ; + /* Safe sex check. */ + if (strlen(path) + n >= PATH_MAX - 2) { + errno = ENAMETOOLONG; + return NULL; + } + /* Insert symlink contents into path. */ + strcat(link_path, path); + strcpy(copy_path, link_path); + path = copy_path; + } +#endif /* S_IFLNK */ + *new_path++ = '/'; + } + /* Delete trailing slash but don't whomp a lone slash. */ + if (new_path != got_path + 1 && new_path[-1] == '/') + new_path--; + /* Make sure it's null terminated. */ + *new_path = '\0'; + strcpy(resolved_path, got_path); + return resolved_path; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/utils/getconf.c b/l4/pkg/uclibc/lib/contrib/uclibc/utils/getconf.c new file mode 100644 index 00000000..812783ec --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/utils/getconf.c @@ -0,0 +1,1337 @@ +/* Copyright (C) 1991, 92, 1995-2008, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include +#include + +#define PACKAGE "getconf regression test" +#define VERSION "" +#ifndef _ +# define _ +#endif +#define error(status, errnum,...) \ + {fprintf(stderr, __VA_ARGS__); exit(status);} + + +struct conf + { + const char *name; + const int call_name; + const enum { SYSCONF, CONFSTR, PATHCONF } call; + }; + +static const struct conf vars[] = + { +#ifdef _PC_LINK_MAX + { "LINK_MAX", _PC_LINK_MAX, PATHCONF }, +#endif +#ifdef _PC_LINK_MAX + { "_POSIX_LINK_MAX", _PC_LINK_MAX, PATHCONF }, +#endif +#ifdef _PC_MAX_CANON + { "MAX_CANON", _PC_MAX_CANON, PATHCONF }, +#endif +#ifdef _PC_MAX_CANON + { "_POSIX_MAX_CANON", _PC_MAX_CANON, PATHCONF }, +#endif +#ifdef _PC_MAX_INPUT + { "MAX_INPUT", _PC_MAX_INPUT, PATHCONF }, +#endif +#ifdef _PC_MAX_INPUT + { "_POSIX_MAX_INPUT", _PC_MAX_INPUT, PATHCONF }, +#endif +#ifdef _PC_NAME_MAX + { "NAME_MAX", _PC_NAME_MAX, PATHCONF }, +#endif +#ifdef _PC_NAME_MAX + { "_POSIX_NAME_MAX", _PC_NAME_MAX, PATHCONF }, +#endif +#ifdef _PC_PATH_MAX + { "PATH_MAX", _PC_PATH_MAX, PATHCONF }, +#endif +#ifdef _PC_PATH_MAX + { "_POSIX_PATH_MAX", _PC_PATH_MAX, PATHCONF }, +#endif +#ifdef _PC_PIPE_BUF + { "PIPE_BUF", _PC_PIPE_BUF, PATHCONF }, +#endif +#ifdef _PC_PIPE_BUF + { "_POSIX_PIPE_BUF", _PC_PIPE_BUF, PATHCONF }, +#endif +#ifdef _PC_SOCK_MAXBUF + { "SOCK_MAXBUF", _PC_SOCK_MAXBUF, PATHCONF }, +#endif +#ifdef _PC_ASYNC_IO + { "_POSIX_ASYNC_IO", _PC_ASYNC_IO, PATHCONF }, +#endif +#ifdef _PC_CHOWN_RESTRICTED + { "_POSIX_CHOWN_RESTRICTED", _PC_CHOWN_RESTRICTED, PATHCONF }, +#endif +#ifdef _PC_NO_TRUNC + { "_POSIX_NO_TRUNC", _PC_NO_TRUNC, PATHCONF }, +#endif +#ifdef _PC_PRIO_IO + { "_POSIX_PRIO_IO", _PC_PRIO_IO, PATHCONF }, +#endif +#ifdef _PC_SYNC_IO + { "_POSIX_SYNC_IO", _PC_SYNC_IO, PATHCONF }, +#endif +#ifdef _PC_VDISABLE + { "_POSIX_VDISABLE", _PC_VDISABLE, PATHCONF }, +#endif + +#ifdef _SC_ARG_MAX + { "ARG_MAX", _SC_ARG_MAX, SYSCONF }, +#endif +#ifdef _SC_ATEXIT_MAX + { "ATEXIT_MAX", _SC_ATEXIT_MAX, SYSCONF }, +#endif +#ifdef _SC_CHAR_BIT + { "CHAR_BIT", _SC_CHAR_BIT, SYSCONF }, +#endif +#ifdef _SC_CHAR_MAX + { "CHAR_MAX", _SC_CHAR_MAX, SYSCONF }, +#endif +#ifdef _SC_CHAR_MIN + { "CHAR_MIN", _SC_CHAR_MIN, SYSCONF }, +#endif +#ifdef _SC_CHILD_MAX + { "CHILD_MAX", _SC_CHILD_MAX, SYSCONF }, +#endif +#ifdef _SC_CLK_TCK + { "CLK_TCK", _SC_CLK_TCK, SYSCONF }, +#endif +#ifdef _SC_INT_MAX + { "INT_MAX", _SC_INT_MAX, SYSCONF }, +#endif +#ifdef _SC_INT_MIN + { "INT_MIN", _SC_INT_MIN, SYSCONF }, +#endif +#ifdef _SC_UIO_MAXIOV + { "IOV_MAX", _SC_UIO_MAXIOV, SYSCONF }, +#endif +#ifdef _SC_LOGIN_NAME_MAX + { "LOGNAME_MAX", _SC_LOGIN_NAME_MAX, SYSCONF }, +#endif +#ifdef _SC_LONG_BIT + { "LONG_BIT", _SC_LONG_BIT, SYSCONF }, +#endif +#ifdef _SC_MB_LEN_MAX + { "MB_LEN_MAX", _SC_MB_LEN_MAX, SYSCONF }, +#endif +#ifdef _SC_NGROUPS_MAX + { "NGROUPS_MAX", _SC_NGROUPS_MAX, SYSCONF }, +#endif +#ifdef _SC_NL_ARGMAX + { "NL_ARGMAX", _SC_NL_ARGMAX, SYSCONF }, +#endif +#ifdef _SC_NL_LANGMAX + { "NL_LANGMAX", _SC_NL_LANGMAX, SYSCONF }, +#endif +#ifdef _SC_NL_MSGMAX + { "NL_MSGMAX", _SC_NL_MSGMAX, SYSCONF }, +#endif +#ifdef _SC_NL_NMAX + { "NL_NMAX", _SC_NL_NMAX, SYSCONF }, +#endif +#ifdef _SC_NL_SETMAX + { "NL_SETMAX", _SC_NL_SETMAX, SYSCONF }, +#endif +#ifdef _SC_NL_TEXTMAX + { "NL_TEXTMAX", _SC_NL_TEXTMAX, SYSCONF }, +#endif +#ifdef _SC_GETGR_R_SIZE_MAX + { "NSS_BUFLEN_GROUP", _SC_GETGR_R_SIZE_MAX, SYSCONF }, +#endif +#ifdef _SC_GETPW_R_SIZE_MAX + { "NSS_BUFLEN_PASSWD", _SC_GETPW_R_SIZE_MAX, SYSCONF }, +#endif +#ifdef _SC_NZERO + { "NZERO", _SC_NZERO, SYSCONF }, +#endif +#ifdef _SC_OPEN_MAX + { "OPEN_MAX", _SC_OPEN_MAX, SYSCONF }, +#endif +#ifdef _SC_PAGESIZE + { "PAGESIZE", _SC_PAGESIZE, SYSCONF }, +#endif +#ifdef _SC_PAGESIZE + { "PAGE_SIZE", _SC_PAGESIZE, SYSCONF }, +#endif +#ifdef _SC_PASS_MAX + { "PASS_MAX", _SC_PASS_MAX, SYSCONF }, +#endif +#ifdef _SC_THREAD_DESTRUCTOR_ITERATIONS + { "PTHREAD_DESTRUCTOR_ITERATIONS", _SC_THREAD_DESTRUCTOR_ITERATIONS, SYSCONF }, +#endif +#ifdef _SC_THREAD_KEYS_MAX + { "PTHREAD_KEYS_MAX", _SC_THREAD_KEYS_MAX, SYSCONF }, +#endif +#ifdef _SC_THREAD_STACK_MIN + { "PTHREAD_STACK_MIN", _SC_THREAD_STACK_MIN, SYSCONF }, +#endif +#ifdef _SC_THREAD_THREADS_MAX + { "PTHREAD_THREADS_MAX", _SC_THREAD_THREADS_MAX, SYSCONF }, +#endif +#ifdef _SC_SCHAR_MAX + { "SCHAR_MAX", _SC_SCHAR_MAX, SYSCONF }, +#endif +#ifdef _SC_SCHAR_MIN + { "SCHAR_MIN", _SC_SCHAR_MIN, SYSCONF }, +#endif +#ifdef _SC_SHRT_MAX + { "SHRT_MAX", _SC_SHRT_MAX, SYSCONF }, +#endif +#ifdef _SC_SHRT_MIN + { "SHRT_MIN", _SC_SHRT_MIN, SYSCONF }, +#endif +#ifdef _SC_SSIZE_MAX + { "SSIZE_MAX", _SC_SSIZE_MAX, SYSCONF }, +#endif +#ifdef _SC_TTY_NAME_MAX + { "TTY_NAME_MAX", _SC_TTY_NAME_MAX, SYSCONF }, +#endif +#ifdef _SC_TZNAME_MAX + { "TZNAME_MAX", _SC_TZNAME_MAX, SYSCONF }, +#endif +#ifdef _SC_UCHAR_MAX + { "UCHAR_MAX", _SC_UCHAR_MAX, SYSCONF }, +#endif +#ifdef _SC_UINT_MAX + { "UINT_MAX", _SC_UINT_MAX, SYSCONF }, +#endif +#ifdef _SC_UIO_MAXIOV + { "UIO_MAXIOV", _SC_UIO_MAXIOV, SYSCONF }, +#endif +#ifdef _SC_ULONG_MAX + { "ULONG_MAX", _SC_ULONG_MAX, SYSCONF }, +#endif +#ifdef _SC_USHRT_MAX + { "USHRT_MAX", _SC_USHRT_MAX, SYSCONF }, +#endif +#ifdef _SC_WORD_BIT + { "WORD_BIT", _SC_WORD_BIT, SYSCONF }, +#endif +#ifdef _SC_AVPHYS_PAGES + { "_AVPHYS_PAGES", _SC_AVPHYS_PAGES, SYSCONF }, +#endif +#ifdef _SC_NPROCESSORS_CONF + { "_NPROCESSORS_CONF", _SC_NPROCESSORS_CONF, SYSCONF }, +#endif +#ifdef _SC_NPROCESSORS_ONLN + { "_NPROCESSORS_ONLN", _SC_NPROCESSORS_ONLN, SYSCONF }, +#endif +#ifdef _SC_PHYS_PAGES + { "_PHYS_PAGES", _SC_PHYS_PAGES, SYSCONF }, +#endif +#ifdef _SC_ARG_MAX + { "_POSIX_ARG_MAX", _SC_ARG_MAX, SYSCONF }, +#endif +#ifdef _SC_ASYNCHRONOUS_IO + { "_POSIX_ASYNCHRONOUS_IO", _SC_ASYNCHRONOUS_IO, SYSCONF }, +#endif +#ifdef _SC_CHILD_MAX + { "_POSIX_CHILD_MAX", _SC_CHILD_MAX, SYSCONF }, +#endif +#ifdef _SC_FSYNC + { "_POSIX_FSYNC", _SC_FSYNC, SYSCONF }, +#endif +#ifdef _SC_JOB_CONTROL + { "_POSIX_JOB_CONTROL", _SC_JOB_CONTROL, SYSCONF }, +#endif +#ifdef _SC_MAPPED_FILES + { "_POSIX_MAPPED_FILES", _SC_MAPPED_FILES, SYSCONF }, +#endif +#ifdef _SC_MEMLOCK + { "_POSIX_MEMLOCK", _SC_MEMLOCK, SYSCONF }, +#endif +#ifdef _SC_MEMLOCK_RANGE + { "_POSIX_MEMLOCK_RANGE", _SC_MEMLOCK_RANGE, SYSCONF }, +#endif +#ifdef _SC_MEMORY_PROTECTION + { "_POSIX_MEMORY_PROTECTION", _SC_MEMORY_PROTECTION, SYSCONF }, +#endif +#ifdef _SC_MESSAGE_PASSING + { "_POSIX_MESSAGE_PASSING", _SC_MESSAGE_PASSING, SYSCONF }, +#endif +#ifdef _SC_NGROUPS_MAX + { "_POSIX_NGROUPS_MAX", _SC_NGROUPS_MAX, SYSCONF }, +#endif +#ifdef _SC_OPEN_MAX + { "_POSIX_OPEN_MAX", _SC_OPEN_MAX, SYSCONF }, +#endif +#ifdef _SC_PII + { "_POSIX_PII", _SC_PII, SYSCONF }, +#endif +#ifdef _SC_PII_INTERNET + { "_POSIX_PII_INTERNET", _SC_PII_INTERNET, SYSCONF }, +#endif +#ifdef _SC_PII_INTERNET_DGRAM + { "_POSIX_PII_INTERNET_DGRAM", _SC_PII_INTERNET_DGRAM, SYSCONF }, +#endif +#ifdef _SC_PII_INTERNET_STREAM + { "_POSIX_PII_INTERNET_STREAM", _SC_PII_INTERNET_STREAM, SYSCONF }, +#endif +#ifdef _SC_PII_OSI + { "_POSIX_PII_OSI", _SC_PII_OSI, SYSCONF }, +#endif +#ifdef _SC_PII_OSI_CLTS + { "_POSIX_PII_OSI_CLTS", _SC_PII_OSI_CLTS, SYSCONF }, +#endif +#ifdef _SC_PII_OSI_COTS + { "_POSIX_PII_OSI_COTS", _SC_PII_OSI_COTS, SYSCONF }, +#endif +#ifdef _SC_PII_OSI_M + { "_POSIX_PII_OSI_M", _SC_PII_OSI_M, SYSCONF }, +#endif +#ifdef _SC_PII_SOCKET + { "_POSIX_PII_SOCKET", _SC_PII_SOCKET, SYSCONF }, +#endif +#ifdef _SC_PII_XTI + { "_POSIX_PII_XTI", _SC_PII_XTI, SYSCONF }, +#endif +#ifdef _SC_POLL + { "_POSIX_POLL", _SC_POLL, SYSCONF }, +#endif +#ifdef _SC_PRIORITIZED_IO + { "_POSIX_PRIORITIZED_IO", _SC_PRIORITIZED_IO, SYSCONF }, +#endif +#ifdef _SC_PRIORITY_SCHEDULING + { "_POSIX_PRIORITY_SCHEDULING", _SC_PRIORITY_SCHEDULING, SYSCONF }, +#endif +#ifdef _SC_REALTIME_SIGNALS + { "_POSIX_REALTIME_SIGNALS", _SC_REALTIME_SIGNALS, SYSCONF }, +#endif +#ifdef _SC_SAVED_IDS + { "_POSIX_SAVED_IDS", _SC_SAVED_IDS, SYSCONF }, +#endif +#ifdef _SC_SELECT + { "_POSIX_SELECT", _SC_SELECT, SYSCONF }, +#endif +#ifdef _SC_SEMAPHORES + { "_POSIX_SEMAPHORES", _SC_SEMAPHORES, SYSCONF }, +#endif +#ifdef _SC_SHARED_MEMORY_OBJECTS + { "_POSIX_SHARED_MEMORY_OBJECTS", _SC_SHARED_MEMORY_OBJECTS, SYSCONF }, +#endif +#ifdef _SC_SSIZE_MAX + { "_POSIX_SSIZE_MAX", _SC_SSIZE_MAX, SYSCONF }, +#endif +#ifdef _SC_STREAM_MAX + { "_POSIX_STREAM_MAX", _SC_STREAM_MAX, SYSCONF }, +#endif +#ifdef _SC_SYNCHRONIZED_IO + { "_POSIX_SYNCHRONIZED_IO", _SC_SYNCHRONIZED_IO, SYSCONF }, +#endif +#ifdef _SC_THREADS + { "_POSIX_THREADS", _SC_THREADS, SYSCONF }, +#endif +#ifdef _SC_THREAD_ATTR_STACKADDR + { "_POSIX_THREAD_ATTR_STACKADDR", _SC_THREAD_ATTR_STACKADDR, SYSCONF }, +#endif +#ifdef _SC_THREAD_ATTR_STACKSIZE + { "_POSIX_THREAD_ATTR_STACKSIZE", _SC_THREAD_ATTR_STACKSIZE, SYSCONF }, +#endif +#ifdef _SC_THREAD_PRIORITY_SCHEDULING + { "_POSIX_THREAD_PRIORITY_SCHEDULING", _SC_THREAD_PRIORITY_SCHEDULING, SYSCONF }, +#endif +#ifdef _SC_THREAD_PRIO_INHERIT + { "_POSIX_THREAD_PRIO_INHERIT", _SC_THREAD_PRIO_INHERIT, SYSCONF }, +#endif +#ifdef _SC_THREAD_PRIO_PROTECT + { "_POSIX_THREAD_PRIO_PROTECT", _SC_THREAD_PRIO_PROTECT, SYSCONF }, +#endif +#ifdef _SC_THREAD_ROBUST_PRIO_INHERIT + { "_POSIX_THREAD_ROBUST_PRIO_INHERIT", _SC_THREAD_ROBUST_PRIO_INHERIT, + SYSCONF }, +#endif +#ifdef _SC_THREAD_ROBUST_PRIO_PROTECT + { "_POSIX_THREAD_ROBUST_PRIO_PROTECT", _SC_THREAD_ROBUST_PRIO_PROTECT, + SYSCONF }, +#endif +#ifdef _SC_THREAD_PROCESS_SHARED + { "_POSIX_THREAD_PROCESS_SHARED", _SC_THREAD_PROCESS_SHARED, SYSCONF }, +#endif +#ifdef _SC_THREAD_SAFE_FUNCTIONS + { "_POSIX_THREAD_SAFE_FUNCTIONS", _SC_THREAD_SAFE_FUNCTIONS, SYSCONF }, +#endif +#ifdef _SC_TIMERS + { "_POSIX_TIMERS", _SC_TIMERS, SYSCONF }, +#endif +#ifdef _SC_TIMER_MAX + { "TIMER_MAX", _SC_TIMER_MAX, SYSCONF }, +#endif +#ifdef _SC_TZNAME_MAX + { "_POSIX_TZNAME_MAX", _SC_TZNAME_MAX, SYSCONF }, +#endif +#ifdef _SC_VERSION + { "_POSIX_VERSION", _SC_VERSION, SYSCONF }, +#endif +#ifdef _SC_T_IOV_MAX + { "_T_IOV_MAX", _SC_T_IOV_MAX, SYSCONF }, +#endif +#ifdef _SC_XOPEN_CRYPT + { "_XOPEN_CRYPT", _SC_XOPEN_CRYPT, SYSCONF }, +#endif +#ifdef _SC_XOPEN_ENH_I18N + { "_XOPEN_ENH_I18N", _SC_XOPEN_ENH_I18N, SYSCONF }, +#endif +#ifdef _SC_XOPEN_LEGACY + { "_XOPEN_LEGACY", _SC_XOPEN_LEGACY, SYSCONF }, +#endif +#ifdef _SC_XOPEN_REALTIME + { "_XOPEN_REALTIME", _SC_XOPEN_REALTIME, SYSCONF }, +#endif +#ifdef _SC_XOPEN_REALTIME_THREADS + { "_XOPEN_REALTIME_THREADS", _SC_XOPEN_REALTIME_THREADS, SYSCONF }, +#endif +#ifdef _SC_XOPEN_SHM + { "_XOPEN_SHM", _SC_XOPEN_SHM, SYSCONF }, +#endif +#ifdef _SC_XOPEN_UNIX + { "_XOPEN_UNIX", _SC_XOPEN_UNIX, SYSCONF }, +#endif +#ifdef _SC_XOPEN_VERSION + { "_XOPEN_VERSION", _SC_XOPEN_VERSION, SYSCONF }, +#endif +#ifdef _SC_XOPEN_XCU_VERSION + { "_XOPEN_XCU_VERSION", _SC_XOPEN_XCU_VERSION, SYSCONF }, +#endif +#ifdef _SC_XOPEN_XPG2 + { "_XOPEN_XPG2", _SC_XOPEN_XPG2, SYSCONF }, +#endif +#ifdef _SC_XOPEN_XPG3 + { "_XOPEN_XPG3", _SC_XOPEN_XPG3, SYSCONF }, +#endif +#ifdef _SC_XOPEN_XPG4 + { "_XOPEN_XPG4", _SC_XOPEN_XPG4, SYSCONF }, +#endif + /* POSIX.2 */ +#ifdef _SC_BC_BASE_MAX + { "BC_BASE_MAX", _SC_BC_BASE_MAX, SYSCONF }, +#endif +#ifdef _SC_BC_DIM_MAX + { "BC_DIM_MAX", _SC_BC_DIM_MAX, SYSCONF }, +#endif +#ifdef _SC_BC_SCALE_MAX + { "BC_SCALE_MAX", _SC_BC_SCALE_MAX, SYSCONF }, +#endif +#ifdef _SC_BC_STRING_MAX + { "BC_STRING_MAX", _SC_BC_STRING_MAX, SYSCONF }, +#endif + { "CHARCLASS_NAME_MAX", _SC_CHARCLASS_NAME_MAX, SYSCONF }, +#ifdef _SC_COLL_WEIGHTS_MAX + { "COLL_WEIGHTS_MAX", _SC_COLL_WEIGHTS_MAX, SYSCONF }, +#endif +#ifdef _SC_EQUIV_CLASS_MAX + { "EQUIV_CLASS_MAX", _SC_EQUIV_CLASS_MAX, SYSCONF }, +#endif +#ifdef _SC_EXPR_NEST_MAX + { "EXPR_NEST_MAX", _SC_EXPR_NEST_MAX, SYSCONF }, +#endif +#ifdef _SC_LINE_MAX + { "LINE_MAX", _SC_LINE_MAX, SYSCONF }, +#endif +#ifdef _SC_BC_BASE_MAX + { "POSIX2_BC_BASE_MAX", _SC_BC_BASE_MAX, SYSCONF }, +#endif +#ifdef _SC_BC_DIM_MAX + { "POSIX2_BC_DIM_MAX", _SC_BC_DIM_MAX, SYSCONF }, +#endif +#ifdef _SC_BC_SCALE_MAX + { "POSIX2_BC_SCALE_MAX", _SC_BC_SCALE_MAX, SYSCONF }, +#endif +#ifdef _SC_BC_STRING_MAX + { "POSIX2_BC_STRING_MAX", _SC_BC_STRING_MAX, SYSCONF }, +#endif +#ifdef _SC_2_CHAR_TERM + { "POSIX2_CHAR_TERM", _SC_2_CHAR_TERM, SYSCONF }, +#endif +#ifdef _SC_COLL_WEIGHTS_MAX + { "POSIX2_COLL_WEIGHTS_MAX", _SC_COLL_WEIGHTS_MAX, SYSCONF }, +#endif +#ifdef _SC_2_C_BIND + { "POSIX2_C_BIND", _SC_2_C_BIND, SYSCONF }, +#endif +#ifdef _SC_2_C_DEV + { "POSIX2_C_DEV", _SC_2_C_DEV, SYSCONF }, +#endif +#ifdef _SC_2_C_VERSION + { "POSIX2_C_VERSION", _SC_2_C_VERSION, SYSCONF }, +#endif +#ifdef _SC_EXPR_NEST_MAX + { "POSIX2_EXPR_NEST_MAX", _SC_EXPR_NEST_MAX, SYSCONF }, +#endif +#ifdef _SC_2_FORT_DEV + { "POSIX2_FORT_DEV", _SC_2_FORT_DEV, SYSCONF }, +#endif +#ifdef _SC_2_FORT_RUN + { "POSIX2_FORT_RUN", _SC_2_FORT_RUN, SYSCONF }, +#endif +#ifdef _SC_LINE_MAX + { "_POSIX2_LINE_MAX", _SC_LINE_MAX, SYSCONF }, + { "POSIX2_LINE_MAX", _SC_LINE_MAX, SYSCONF }, +#endif +#ifdef _SC_2_LOCALEDEF + { "POSIX2_LOCALEDEF", _SC_2_LOCALEDEF, SYSCONF }, +#endif +#ifdef _SC_RE_DUP_MAX + { "POSIX2_RE_DUP_MAX", _SC_RE_DUP_MAX, SYSCONF }, +#endif +#ifdef _SC_2_SW_DEV + { "POSIX2_SW_DEV", _SC_2_SW_DEV, SYSCONF }, +#endif +#ifdef _SC_2_UPE + { "POSIX2_UPE", _SC_2_UPE, SYSCONF }, +#endif +#ifdef _SC_2_VERSION + { "POSIX2_VERSION", _SC_2_VERSION, SYSCONF }, +#endif +#ifdef _SC_RE_DUP_MAX + { "RE_DUP_MAX", _SC_RE_DUP_MAX, SYSCONF }, +#endif + +#ifdef _CS_PATH + { "PATH", _CS_PATH, CONFSTR }, + { "CS_PATH", _CS_PATH, CONFSTR }, +#endif + + /* LFS */ +#ifdef _CS_LFS_CFLAGS + { "LFS_CFLAGS", _CS_LFS_CFLAGS, CONFSTR }, +#endif +#ifdef _CS_LFS_LDFLAGS + { "LFS_LDFLAGS", _CS_LFS_LDFLAGS, CONFSTR }, +#endif +#ifdef _CS_LFS_LIBS + { "LFS_LIBS", _CS_LFS_LIBS, CONFSTR }, +#endif +#ifdef _CS_LFS_LINTFLAGS + { "LFS_LINTFLAGS", _CS_LFS_LINTFLAGS, CONFSTR }, +#endif +#ifdef _CS_LFS64_CFLAGS + { "LFS64_CFLAGS", _CS_LFS64_CFLAGS, CONFSTR }, +#endif +#ifdef _CS_LFS64_LDFLAGS + { "LFS64_LDFLAGS", _CS_LFS64_LDFLAGS, CONFSTR }, +#endif +#ifdef _CS_LFS64_LIBS + { "LFS64_LIBS", _CS_LFS64_LIBS, CONFSTR }, +#endif +#ifdef _CS_LFS64_LINTFLAGS + { "LFS64_LINTFLAGS", _CS_LFS64_LINTFLAGS, CONFSTR }, +#endif + + /* Programming environments. */ +#ifdef _CS_V5_WIDTH_RESTRICTED_ENVS + { "_XBS5_WIDTH_RESTRICTED_ENVS", _CS_V5_WIDTH_RESTRICTED_ENVS, CONFSTR }, + { "XBS5_WIDTH_RESTRICTED_ENVS", _CS_V5_WIDTH_RESTRICTED_ENVS, CONFSTR }, +#endif + +#ifdef _SC_XBS5_ILP32_OFF32 + { "_XBS5_ILP32_OFF32", _SC_XBS5_ILP32_OFF32, SYSCONF }, +#endif +#ifdef _CS_XBS5_ILP32_OFF32_CFLAGS + { "XBS5_ILP32_OFF32_CFLAGS", _CS_XBS5_ILP32_OFF32_CFLAGS, CONFSTR }, +#endif +#ifdef _CS_XBS5_ILP32_OFF32_LDFLAGS + { "XBS5_ILP32_OFF32_LDFLAGS", _CS_XBS5_ILP32_OFF32_LDFLAGS, CONFSTR }, +#endif +#ifdef _CS_XBS5_ILP32_OFF32_LIBS + { "XBS5_ILP32_OFF32_LIBS", _CS_XBS5_ILP32_OFF32_LIBS, CONFSTR }, +#endif +#ifdef _CS_XBS5_ILP32_OFF32_LINTFLAGS + { "XBS5_ILP32_OFF32_LINTFLAGS", _CS_XBS5_ILP32_OFF32_LINTFLAGS, CONFSTR }, +#endif + +#ifdef _SC_XBS5_ILP32_OFFBIG + { "_XBS5_ILP32_OFFBIG", _SC_XBS5_ILP32_OFFBIG, SYSCONF }, +#endif +#ifdef _CS_XBS5_ILP32_OFFBIG_CFLAGS + { "XBS5_ILP32_OFFBIG_CFLAGS", _CS_XBS5_ILP32_OFFBIG_CFLAGS, CONFSTR }, +#endif +#ifdef _CS_XBS5_ILP32_OFFBIG_LDFLAGS + { "XBS5_ILP32_OFFBIG_LDFLAGS", _CS_XBS5_ILP32_OFFBIG_LDFLAGS, CONFSTR }, +#endif +#ifdef _CS_XBS5_ILP32_OFFBIG_LIBS + { "XBS5_ILP32_OFFBIG_LIBS", _CS_XBS5_ILP32_OFFBIG_LIBS, CONFSTR }, +#endif +#ifdef _CS_XBS5_ILP32_OFFBIG_LINTFLAGS + { "XBS5_ILP32_OFFBIG_LINTFLAGS", _CS_XBS5_ILP32_OFFBIG_LINTFLAGS, CONFSTR }, +#endif + +#ifdef _SC_XBS5_LP64_OFF64 + { "_XBS5_LP64_OFF64", _SC_XBS5_LP64_OFF64, SYSCONF }, +#endif +#ifdef _CS_XBS5_LP64_OFF64_CFLAGS + { "XBS5_LP64_OFF64_CFLAGS", _CS_XBS5_LP64_OFF64_CFLAGS, CONFSTR }, +#endif +#ifdef _CS_XBS5_LP64_OFF64_LDFLAGS + { "XBS5_LP64_OFF64_LDFLAGS", _CS_XBS5_LP64_OFF64_LDFLAGS, CONFSTR }, +#endif +#ifdef _CS_XBS5_LP64_OFF64_LIBS + { "XBS5_LP64_OFF64_LIBS", _CS_XBS5_LP64_OFF64_LIBS, CONFSTR }, +#endif +#ifdef _CS_XBS5_LP64_OFF64_LINTFLAGS + { "XBS5_LP64_OFF64_LINTFLAGS", _CS_XBS5_LP64_OFF64_LINTFLAGS, CONFSTR }, +#endif + +#ifdef _SC_XBS5_LPBIG_OFFBIG + { "_XBS5_LPBIG_OFFBIG", _SC_XBS5_LPBIG_OFFBIG, SYSCONF }, +#endif +#ifdef _CS_XBS5_LPBIG_OFFBIG_CFLAGS + { "XBS5_LPBIG_OFFBIG_CFLAGS", _CS_XBS5_LPBIG_OFFBIG_CFLAGS, CONFSTR }, +#endif +#ifdef _CS_XBS5_LPBIG_OFFBIG_LDFLAGS + { "XBS5_LPBIG_OFFBIG_LDFLAGS", _CS_XBS5_LPBIG_OFFBIG_LDFLAGS, CONFSTR }, +#endif +#ifdef _CS_XBS5_LPBIG_OFFBIG_LIBS + { "XBS5_LPBIG_OFFBIG_LIBS", _CS_XBS5_LPBIG_OFFBIG_LIBS, CONFSTR }, +#endif +#ifdef _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS + { "XBS5_LPBIG_OFFBIG_LINTFLAGS", _CS_XBS5_LPBIG_OFFBIG_LINTFLAGS, CONFSTR }, +#endif + +#ifdef _SC_V6_ILP32_OFF32 + { "_POSIX_V6_ILP32_OFF32", _SC_V6_ILP32_OFF32, SYSCONF }, +#endif +#ifdef _CS_POSIX_V6_ILP32_OFF32_CFLAGS + { "POSIX_V6_ILP32_OFF32_CFLAGS", _CS_POSIX_V6_ILP32_OFF32_CFLAGS, CONFSTR }, +#endif +#ifdef _CS_POSIX_V6_ILP32_OFF32_LDFLAGS + { "POSIX_V6_ILP32_OFF32_LDFLAGS", _CS_POSIX_V6_ILP32_OFF32_LDFLAGS, CONFSTR }, +#endif +#ifdef _CS_POSIX_V6_ILP32_OFF32_LIBS + { "POSIX_V6_ILP32_OFF32_LIBS", _CS_POSIX_V6_ILP32_OFF32_LIBS, CONFSTR }, +#endif +#ifdef _CS_POSIX_V6_ILP32_OFF32_LINTFLAGS + { "POSIX_V6_ILP32_OFF32_LINTFLAGS", _CS_POSIX_V6_ILP32_OFF32_LINTFLAGS, CONFSTR }, +#endif + +#ifdef _CS_V6_WIDTH_RESTRICTED_ENVS + { "_POSIX_V6_WIDTH_RESTRICTED_ENVS", _CS_V6_WIDTH_RESTRICTED_ENVS, CONFSTR }, + { "POSIX_V6_WIDTH_RESTRICTED_ENVS", _CS_V6_WIDTH_RESTRICTED_ENVS, CONFSTR }, +#endif + +#ifdef _SC_V6_ILP32_OFFBIG + { "_POSIX_V6_ILP32_OFFBIG", _SC_V6_ILP32_OFFBIG, SYSCONF }, +#endif +#ifdef _CS_POSIX_V6_ILP32_OFFBIG_CFLAGS + { "POSIX_V6_ILP32_OFFBIG_CFLAGS", _CS_POSIX_V6_ILP32_OFFBIG_CFLAGS, CONFSTR }, +#endif +#ifdef _CS_POSIX_V6_ILP32_OFFBIG_LDFLAGS + { "POSIX_V6_ILP32_OFFBIG_LDFLAGS", _CS_POSIX_V6_ILP32_OFFBIG_LDFLAGS, CONFSTR }, +#endif +#ifdef _CS_POSIX_V6_ILP32_OFFBIG_LIBS + { "POSIX_V6_ILP32_OFFBIG_LIBS", _CS_POSIX_V6_ILP32_OFFBIG_LIBS, CONFSTR }, +#endif +#ifdef _CS_POSIX_V6_ILP32_OFFBIG_LINTFLAGS + { "POSIX_V6_ILP32_OFFBIG_LINTFLAGS", _CS_POSIX_V6_ILP32_OFFBIG_LINTFLAGS, CONFSTR }, +#endif + +#ifdef _SC_V6_LP64_OFF64 + { "_POSIX_V6_LP64_OFF64", _SC_V6_LP64_OFF64, SYSCONF }, +#endif +#ifdef _CS_POSIX_V6_LP64_OFF64_CFLAGS + { "POSIX_V6_LP64_OFF64_CFLAGS", _CS_POSIX_V6_LP64_OFF64_CFLAGS, CONFSTR }, +#endif +#ifdef _CS_POSIX_V6_LP64_OFF64_LDFLAGS + { "POSIX_V6_LP64_OFF64_LDFLAGS", _CS_POSIX_V6_LP64_OFF64_LDFLAGS, CONFSTR }, +#endif +#ifdef _CS_POSIX_V6_LP64_OFF64_LIBS + { "POSIX_V6_LP64_OFF64_LIBS", _CS_POSIX_V6_LP64_OFF64_LIBS, CONFSTR }, +#endif +#ifdef _CS_POSIX_V6_LP64_OFF64_LINTFLAGS + { "POSIX_V6_LP64_OFF64_LINTFLAGS", _CS_POSIX_V6_LP64_OFF64_LINTFLAGS, CONFSTR }, +#endif + +#ifdef _SC_V6_LPBIG_OFFBIG + { "_POSIX_V6_LPBIG_OFFBIG", _SC_V6_LPBIG_OFFBIG, SYSCONF }, +#endif +#ifdef _CS_POSIX_V6_LPBIG_OFFBIG_CFLAGS + { "POSIX_V6_LPBIG_OFFBIG_CFLAGS", _CS_POSIX_V6_LPBIG_OFFBIG_CFLAGS, CONFSTR }, +#endif +#ifdef _CS_POSIX_V6_LPBIG_OFFBIG_LDFLAGS + { "POSIX_V6_LPBIG_OFFBIG_LDFLAGS", _CS_POSIX_V6_LPBIG_OFFBIG_LDFLAGS, CONFSTR }, +#endif +#ifdef _CS_POSIX_V6_LPBIG_OFFBIG_LIBS + { "POSIX_V6_LPBIG_OFFBIG_LIBS", _CS_POSIX_V6_LPBIG_OFFBIG_LIBS, CONFSTR }, +#endif +#ifdef _CS_POSIX_V6_LPBIG_OFFBIG_LINTFLAGS + { "POSIX_V6_LPBIG_OFFBIG_LINTFLAGS", _CS_POSIX_V6_LPBIG_OFFBIG_LINTFLAGS, CONFSTR }, +#endif + +#ifdef _SC_V7_ILP32_OFF32 + { "_POSIX_V7_ILP32_OFF32", _SC_V7_ILP32_OFF32, SYSCONF }, +#endif +#ifdef _CS_POSIX_V7_ILP32_OFF32_CFLAGS + { "POSIX_V7_ILP32_OFF32_CFLAGS", _CS_POSIX_V7_ILP32_OFF32_CFLAGS, CONFSTR }, +#endif +#ifdef _CS_POSIX_V7_ILP32_OFF32_LDFLAGS + { "POSIX_V7_ILP32_OFF32_LDFLAGS", _CS_POSIX_V7_ILP32_OFF32_LDFLAGS, CONFSTR }, +#endif +#ifdef _CS_POSIX_V7_ILP32_OFF32_LIBS + { "POSIX_V7_ILP32_OFF32_LIBS", _CS_POSIX_V7_ILP32_OFF32_LIBS, CONFSTR }, +#endif +#ifdef _CS_POSIX_V7_ILP32_OFF32_LINTFLAGS + { "POSIX_V7_ILP32_OFF32_LINTFLAGS", _CS_POSIX_V7_ILP32_OFF32_LINTFLAGS, CONFSTR }, +#endif + +#ifdef _CS_V7_WIDTH_RESTRICTED_ENVS + { "_POSIX_V7_WIDTH_RESTRICTED_ENVS", _CS_V7_WIDTH_RESTRICTED_ENVS, CONFSTR }, + { "POSIX_V7_WIDTH_RESTRICTED_ENVS", _CS_V7_WIDTH_RESTRICTED_ENVS, CONFSTR }, +#endif + +#ifdef _SC_V7_ILP32_OFFBIG + { "_POSIX_V7_ILP32_OFFBIG", _SC_V7_ILP32_OFFBIG, SYSCONF }, +#endif +#ifdef _CS_POSIX_V7_ILP32_OFFBIG_CFLAGS + { "POSIX_V7_ILP32_OFFBIG_CFLAGS", _CS_POSIX_V7_ILP32_OFFBIG_CFLAGS, CONFSTR }, +#endif +#ifdef _CS_POSIX_V7_ILP32_OFFBIG_LDFLAGS + { "POSIX_V7_ILP32_OFFBIG_LDFLAGS", _CS_POSIX_V7_ILP32_OFFBIG_LDFLAGS, CONFSTR }, +#endif +#ifdef _CS_POSIX_V7_ILP32_OFFBIG_LIBS + { "POSIX_V7_ILP32_OFFBIG_LIBS", _CS_POSIX_V7_ILP32_OFFBIG_LIBS, CONFSTR }, +#endif +#ifdef _CS_POSIX_V7_ILP32_OFFBIG_LINTFLAGS + { "POSIX_V7_ILP32_OFFBIG_LINTFLAGS", _CS_POSIX_V7_ILP32_OFFBIG_LINTFLAGS, CONFSTR }, +#endif + +#ifdef _SC_V7_LP64_OFF64 + { "_POSIX_V7_LP64_OFF64", _SC_V7_LP64_OFF64, SYSCONF }, +#endif +#ifdef _CS_POSIX_V7_LP64_OFF64_CFLAGS + { "POSIX_V7_LP64_OFF64_CFLAGS", _CS_POSIX_V7_LP64_OFF64_CFLAGS, CONFSTR }, +#endif +#ifdef _CS_POSIX_V7_LP64_OFF64_LDFLAGS + { "POSIX_V7_LP64_OFF64_LDFLAGS", _CS_POSIX_V7_LP64_OFF64_LDFLAGS, CONFSTR }, +#endif +#ifdef _CS_POSIX_V7_LP64_OFF64_LIBS + { "POSIX_V7_LP64_OFF64_LIBS", _CS_POSIX_V7_LP64_OFF64_LIBS, CONFSTR }, +#endif +#ifdef _CS_POSIX_V7_LP64_OFF64_LINTFLAGS + { "POSIX_V7_LP64_OFF64_LINTFLAGS", _CS_POSIX_V7_LP64_OFF64_LINTFLAGS, CONFSTR }, +#endif + +#ifdef _SC_V7_LPBIG_OFFBIG + { "_POSIX_V7_LPBIG_OFFBIG", _SC_V7_LPBIG_OFFBIG, SYSCONF }, +#endif +#ifdef _CS_POSIX_V7_LPBIG_OFFBIG_CFLAGS + { "POSIX_V7_LPBIG_OFFBIG_CFLAGS", _CS_POSIX_V7_LPBIG_OFFBIG_CFLAGS, CONFSTR }, +#endif +#ifdef _CS_POSIX_V7_LPBIG_OFFBIG_LDFLAGS + { "POSIX_V7_LPBIG_OFFBIG_LDFLAGS", _CS_POSIX_V7_LPBIG_OFFBIG_LDFLAGS, CONFSTR }, +#endif +#ifdef _CS_POSIX_V7_LPBIG_OFFBIG_LIBS + { "POSIX_V7_LPBIG_OFFBIG_LIBS", _CS_POSIX_V7_LPBIG_OFFBIG_LIBS, CONFSTR }, +#endif +#ifdef _CS_POSIX_V7_LPBIG_OFFBIG_LINTFLAGS + { "POSIX_V7_LPBIG_OFFBIG_LINTFLAGS", _CS_POSIX_V7_LPBIG_OFFBIG_LINTFLAGS, CONFSTR }, +#endif + +#ifdef _SC_ADVISORY_INFO + { "_POSIX_ADVISORY_INFO", _SC_ADVISORY_INFO, SYSCONF }, +#endif +#ifdef _SC_BARRIERS + { "_POSIX_BARRIERS", _SC_BARRIERS, SYSCONF }, +#endif +#ifdef _SC_BASE + { "_POSIX_BASE", _SC_BASE, SYSCONF }, +#endif +#ifdef _SC_C_LANG_SUPPORT + { "_POSIX_C_LANG_SUPPORT", _SC_C_LANG_SUPPORT, SYSCONF }, +#endif +#ifdef _SC_C_LANG_SUPPORT_R + { "_POSIX_C_LANG_SUPPORT_R", _SC_C_LANG_SUPPORT_R, SYSCONF }, +#endif +#ifdef _SC_CLOCK_SELECTION + { "_POSIX_CLOCK_SELECTION", _SC_CLOCK_SELECTION, SYSCONF }, +#endif +#ifdef _SC_CPUTIME + { "_POSIX_CPUTIME", _SC_CPUTIME, SYSCONF }, +#endif +#ifdef _SC_THREAD_CPUTIME + { "_POSIX_THREAD_CPUTIME", _SC_THREAD_CPUTIME, SYSCONF }, +#endif +#ifdef _SC_DEVICE_SPECIFIC + { "_POSIX_DEVICE_SPECIFIC", _SC_DEVICE_SPECIFIC, SYSCONF }, +#endif +#ifdef _SC_DEVICE_SPECIFIC_R + { "_POSIX_DEVICE_SPECIFIC_R", _SC_DEVICE_SPECIFIC_R, SYSCONF }, +#endif +#ifdef _SC_FD_MGMT + { "_POSIX_FD_MGMT", _SC_FD_MGMT, SYSCONF }, +#endif +#ifdef _SC_FIFO + { "_POSIX_FIFO", _SC_FIFO, SYSCONF }, +#endif +#ifdef _SC_PIPE + { "_POSIX_PIPE", _SC_PIPE, SYSCONF }, +#endif +#ifdef _SC_FILE_ATTRIBUTES + { "_POSIX_FILE_ATTRIBUTES", _SC_FILE_ATTRIBUTES, SYSCONF }, +#endif +#ifdef _SC_FILE_LOCKING + { "_POSIX_FILE_LOCKING", _SC_FILE_LOCKING, SYSCONF }, +#endif +#ifdef _SC_FILE_SYSTEM + { "_POSIX_FILE_SYSTEM", _SC_FILE_SYSTEM, SYSCONF }, +#endif +#ifdef _SC_MONOTONIC_CLOCK + { "_POSIX_MONOTONIC_CLOCK", _SC_MONOTONIC_CLOCK, SYSCONF }, +#endif +#ifdef _SC_MULTI_PROCESS + { "_POSIX_MULTI_PROCESS", _SC_MULTI_PROCESS, SYSCONF }, +#endif +#ifdef _SC_SINGLE_PROCESS + { "_POSIX_SINGLE_PROCESS", _SC_SINGLE_PROCESS, SYSCONF }, +#endif +#ifdef _SC_NETWORKING + { "_POSIX_NETWORKING", _SC_NETWORKING, SYSCONF }, +#endif +#ifdef _SC_READER_WRITER_LOCKS + { "_POSIX_READER_WRITER_LOCKS", _SC_READER_WRITER_LOCKS, SYSCONF }, +#endif +#ifdef _SC_SPIN_LOCKS + { "_POSIX_SPIN_LOCKS", _SC_SPIN_LOCKS, SYSCONF }, +#endif +#ifdef _SC_REGEXP + { "_POSIX_REGEXP", _SC_REGEXP, SYSCONF }, +#endif +#ifdef _SC_REGEX_VERSION + { "_REGEX_VERSION", _SC_REGEX_VERSION, SYSCONF }, +#endif +#ifdef _SC_SHELL + { "_POSIX_SHELL", _SC_SHELL, SYSCONF }, +#endif +#ifdef _SC_SIGNALS + { "_POSIX_SIGNALS", _SC_SIGNALS, SYSCONF }, +#endif +#ifdef _SC_SPAWN + { "_POSIX_SPAWN", _SC_SPAWN, SYSCONF }, +#endif +#ifdef _SC_SPORADIC_SERVER + { "_POSIX_SPORADIC_SERVER", _SC_SPORADIC_SERVER, SYSCONF }, +#endif +#ifdef _SC_THREAD_SPORADIC_SERVER + { "_POSIX_THREAD_SPORADIC_SERVER", _SC_THREAD_SPORADIC_SERVER, SYSCONF }, +#endif +#ifdef _SC_SYSTEM_DATABASE + { "_POSIX_SYSTEM_DATABASE", _SC_SYSTEM_DATABASE, SYSCONF }, +#endif +#ifdef _SC_SYSTEM_DATABASE_R + { "_POSIX_SYSTEM_DATABASE_R", _SC_SYSTEM_DATABASE_R, SYSCONF }, +#endif +#ifdef _SC_TIMEOUTS + { "_POSIX_TIMEOUTS", _SC_TIMEOUTS, SYSCONF }, +#endif +#ifdef _SC_TYPED_MEMORY_OBJECTS + { "_POSIX_TYPED_MEMORY_OBJECTS", _SC_TYPED_MEMORY_OBJECTS, SYSCONF }, +#endif +#ifdef _SC_USER_GROUPS + { "_POSIX_USER_GROUPS", _SC_USER_GROUPS, SYSCONF }, +#endif +#ifdef _SC_USER_GROUPS_R + { "_POSIX_USER_GROUPS_R", _SC_USER_GROUPS_R, SYSCONF }, +#endif +#ifdef _SC_2_PBS + { "POSIX2_PBS", _SC_2_PBS, SYSCONF }, +#endif +#ifdef _SC_2_PBS_ACCOUNTING + { "POSIX2_PBS_ACCOUNTING", _SC_2_PBS_ACCOUNTING, SYSCONF }, +#endif +#ifdef _SC_2_PBS_LOCATE + { "POSIX2_PBS_LOCATE", _SC_2_PBS_LOCATE, SYSCONF }, +#endif +#ifdef _SC_2_PBS_TRACK + { "POSIX2_PBS_TRACK", _SC_2_PBS_TRACK, SYSCONF }, +#endif +#ifdef _SC_2_PBS_MESSAGE + { "POSIX2_PBS_MESSAGE", _SC_2_PBS_MESSAGE, SYSCONF }, +#endif +#ifdef _SC_SYMLOOP_MAX + { "SYMLOOP_MAX", _SC_SYMLOOP_MAX, SYSCONF }, +#endif +#ifdef _SC_STREAM_MAX + { "STREAM_MAX", _SC_STREAM_MAX, SYSCONF }, +#endif +#ifdef _SC_AIO_LISTIO_MAX + { "AIO_LISTIO_MAX", _SC_AIO_LISTIO_MAX, SYSCONF }, +#endif +#ifdef _SC_AIO_MAX + { "AIO_MAX", _SC_AIO_MAX, SYSCONF }, +#endif +#ifdef _SC_AIO_PRIO_DELTA_MAX + { "AIO_PRIO_DELTA_MAX", _SC_AIO_PRIO_DELTA_MAX, SYSCONF }, +#endif +#ifdef _SC_DELAYTIMER_MAX + { "DELAYTIMER_MAX", _SC_DELAYTIMER_MAX, SYSCONF }, +#endif +#ifdef _SC_HOST_NAME_MAX + { "HOST_NAME_MAX", _SC_HOST_NAME_MAX, SYSCONF }, +#endif +#ifdef _SC_LOGIN_NAME_MAX + { "LOGIN_NAME_MAX", _SC_LOGIN_NAME_MAX, SYSCONF }, +#endif +#ifdef _SC_MQ_OPEN_MAX + { "MQ_OPEN_MAX", _SC_MQ_OPEN_MAX, SYSCONF }, +#endif +#ifdef _SC_MQ_PRIO_MAX + { "MQ_PRIO_MAX", _SC_MQ_PRIO_MAX, SYSCONF }, +#endif +#ifdef _SC_DEVICE_IO + { "_POSIX_DEVICE_IO", _SC_DEVICE_IO, SYSCONF }, +#endif +#ifdef _SC_TRACE + { "_POSIX_TRACE", _SC_TRACE, SYSCONF }, +#endif +#ifdef _SC_TRACE_EVENT_FILTER + { "_POSIX_TRACE_EVENT_FILTER", _SC_TRACE_EVENT_FILTER, SYSCONF }, +#endif +#ifdef _SC_TRACE_INHERIT + { "_POSIX_TRACE_INHERIT", _SC_TRACE_INHERIT, SYSCONF }, +#endif +#ifdef _SC_TRACE_LOG + { "_POSIX_TRACE_LOG", _SC_TRACE_LOG, SYSCONF }, +#endif +#ifdef _SC_RTSIG_MAX + { "RTSIG_MAX", _SC_RTSIG_MAX, SYSCONF }, +#endif +#ifdef _SC_SEM_NSEMS_MAX + { "SEM_NSEMS_MAX", _SC_SEM_NSEMS_MAX, SYSCONF }, +#endif +#ifdef _SC_SEM_VALUE_MAX + { "SEM_VALUE_MAX", _SC_SEM_VALUE_MAX, SYSCONF }, +#endif +#ifdef _SC_SIGQUEUE_MAX + { "SIGQUEUE_MAX", _SC_SIGQUEUE_MAX, SYSCONF }, +#endif +#ifdef _PC_FILESIZEBITS + { "FILESIZEBITS", _PC_FILESIZEBITS, PATHCONF }, +#endif +#ifdef _PC_ALLOC_SIZE_MIN + { "POSIX_ALLOC_SIZE_MIN", _PC_ALLOC_SIZE_MIN, PATHCONF }, +#endif +#ifdef _PC_REC_INCR_XFER_SIZE + { "POSIX_REC_INCR_XFER_SIZE", _PC_REC_INCR_XFER_SIZE, PATHCONF }, +#endif +#ifdef _PC_REC_MAX_XFER_SIZE + { "POSIX_REC_MAX_XFER_SIZE", _PC_REC_MAX_XFER_SIZE, PATHCONF }, +#endif +#ifdef _PC_REC_MIN_XFER_SIZE + { "POSIX_REC_MIN_XFER_SIZE", _PC_REC_MIN_XFER_SIZE, PATHCONF }, +#endif +#ifdef _PC_REC_XFER_ALIGN + { "POSIX_REC_XFER_ALIGN", _PC_REC_XFER_ALIGN, PATHCONF }, +#endif +#ifdef _PC_SYMLINK_MAX + { "SYMLINK_MAX", _PC_SYMLINK_MAX, PATHCONF }, +#endif +#ifdef _CS_GNU_LIBC_VERSION + { "GNU_LIBC_VERSION", _CS_GNU_LIBC_VERSION, CONFSTR }, +#endif +#ifdef _CS_GNU_LIBPTHREAD_VERSION + { "GNU_LIBPTHREAD_VERSION", _CS_GNU_LIBPTHREAD_VERSION, CONFSTR }, +#endif +#ifdef _PC_2_SYMLINKS + { "POSIX2_SYMLINKS", _PC_2_SYMLINKS, PATHCONF }, +#endif + +#ifdef _SC_LEVEL1_ICACHE_SIZE + { "LEVEL1_ICACHE_SIZE", _SC_LEVEL1_ICACHE_SIZE, SYSCONF }, +#endif +#ifdef _SC_LEVEL1_ICACHE_ASSOC + { "LEVEL1_ICACHE_ASSOC", _SC_LEVEL1_ICACHE_ASSOC, SYSCONF }, +#endif +#ifdef _SC_LEVEL1_ICACHE_LINESIZE + { "LEVEL1_ICACHE_LINESIZE", _SC_LEVEL1_ICACHE_LINESIZE, SYSCONF }, +#endif +#ifdef _SC_LEVEL1_DCACHE_SIZE + { "LEVEL1_DCACHE_SIZE", _SC_LEVEL1_DCACHE_SIZE, SYSCONF }, +#endif +#ifdef _SC_LEVEL1_DCACHE_ASSOC + { "LEVEL1_DCACHE_ASSOC", _SC_LEVEL1_DCACHE_ASSOC, SYSCONF }, +#endif +#ifdef _SC_LEVEL1_DCACHE_LINESIZE + { "LEVEL1_DCACHE_LINESIZE", _SC_LEVEL1_DCACHE_LINESIZE, SYSCONF }, +#endif +#ifdef _SC_LEVEL2_CACHE_SIZE + { "LEVEL2_CACHE_SIZE", _SC_LEVEL2_CACHE_SIZE, SYSCONF }, +#endif +#ifdef _SC_LEVEL2_CACHE_ASSOC + { "LEVEL2_CACHE_ASSOC", _SC_LEVEL2_CACHE_ASSOC, SYSCONF }, +#endif +#ifdef _SC_LEVEL2_CACHE_LINESIZE + { "LEVEL2_CACHE_LINESIZE", _SC_LEVEL2_CACHE_LINESIZE, SYSCONF }, +#endif +#ifdef _SC_LEVEL3_CACHE_SIZE + { "LEVEL3_CACHE_SIZE", _SC_LEVEL3_CACHE_SIZE, SYSCONF }, +#endif +#ifdef _SC_LEVEL3_CACHE_ASSOC + { "LEVEL3_CACHE_ASSOC", _SC_LEVEL3_CACHE_ASSOC, SYSCONF }, +#endif +#ifdef _SC_LEVEL3_CACHE_LINESIZE + { "LEVEL3_CACHE_LINESIZE", _SC_LEVEL3_CACHE_LINESIZE, SYSCONF }, +#endif +#ifdef _SC_LEVEL4_CACHE_SIZE + { "LEVEL4_CACHE_SIZE", _SC_LEVEL4_CACHE_SIZE, SYSCONF }, +#endif +#ifdef _SC_LEVEL4_CACHE_ASSOC + { "LEVEL4_CACHE_ASSOC", _SC_LEVEL4_CACHE_ASSOC, SYSCONF }, +#endif +#ifdef _SC_LEVEL4_CACHE_LINESIZE + { "LEVEL4_CACHE_LINESIZE", _SC_LEVEL4_CACHE_LINESIZE, SYSCONF }, +#endif + +#ifdef _SC_IPV6 + { "IPV6", _SC_IPV6, SYSCONF }, +#endif +#ifdef _SC_RAW_SOCKETS + { "RAW_SOCKETS", _SC_RAW_SOCKETS, SYSCONF }, +#endif + + { NULL, 0, SYSCONF } + }; + + +static const struct { const char *name; int num; } specs[] = + { +#ifdef _SC_XBS5_ILP32_OFF32 + { "XBS5_ILP32_OFF32", _SC_XBS5_ILP32_OFF32 }, +#endif +#ifdef _SC_XBS5_ILP32_OFFBIG + { "XBS5_ILP32_OFFBIG", _SC_XBS5_ILP32_OFFBIG }, +#endif +#ifdef _SC_XBS5_LP64_OFF64 + { "XBS5_LP64_OFF64", _SC_XBS5_LP64_OFF64 }, +#endif +#ifdef _SC_XBS5_LPBIG_OFFBIG + { "XBS5_LPBIG_OFFBIG", _SC_XBS5_LPBIG_OFFBIG }, +#endif +#ifdef _SC_V6_ILP32_OFF32 + { "POSIX_V6_ILP32_OFF32", _SC_V6_ILP32_OFF32 }, +#endif +#ifdef _SC_V6_ILP32_OFFBIG + { "POSIX_V6_ILP32_OFFBIG", _SC_V6_ILP32_OFFBIG }, +#endif +#ifdef _SC_V6_LP64_OFF64 + { "POSIX_V6_LP64_OFF64", _SC_V6_LP64_OFF64 }, +#endif +#ifdef _SC_V6_LPBIG_OFFBIG + { "POSIX_V6_LPBIG_OFFBIG", _SC_V6_LPBIG_OFFBIG }, +#endif +#ifdef _SC_V7_ILP32_OFF32 + { "POSIX_V7_ILP32_OFF32", _SC_V7_ILP32_OFF32 }, +#endif +#ifdef _SC_V7_ILP32_OFFBIG + { "POSIX_V7_ILP32_OFFBIG", _SC_V7_ILP32_OFFBIG }, +#endif +#ifdef _SC_V7_LP64_OFF64 + { "POSIX_V7_LP64_OFF64", _SC_V7_LP64_OFF64 }, +#endif +#ifdef _SC_V7_LPBIG_OFFBIG + { "POSIX_V7_LPBIG_OFFBIG", _SC_V7_LPBIG_OFFBIG }, +#endif + }; +static const int nspecs = sizeof (specs) / sizeof (specs[0]); + +#ifdef __UCLIBC_HAS___PROGNAME__ +extern const char *__progname; +#else +#define __progname "foo" +#endif + +static void +usage (void) +{ + fprintf (stderr, + _("Usage: %s [-v specification] variable_name [pathname]\n"), + __progname); + fprintf (stderr, + _(" %s -a [pathname]\n"), __progname); + exit (2); +} + + +static void +print_all (const char *path) +{ + register const struct conf *c; + size_t clen; + long int value; + char *cvalue; + for (c = vars; c->name != NULL; ++c) { + printf("%-35s", c->name); + switch (c->call) { + case PATHCONF: + value = pathconf (path, c->call_name); + if (value != -1) { + printf("%ld", value); + } + printf("\n"); + break; + case SYSCONF: + value = sysconf (c->call_name); + if (value == -1l) { + if (c->call_name == _SC_UINT_MAX + || c->call_name == _SC_ULONG_MAX) + printf ("%lu", value); + } + else { + printf ("%ld", value); + } + printf ("\n"); + break; + case CONFSTR: + clen = confstr (c->call_name, (char *) NULL, 0); + cvalue = (char *) malloc (clen); + if (cvalue == NULL) + error (3, 0, _("memory exhausted")); + if (confstr (c->call_name, cvalue, clen) != clen) + error (3, errno, "confstr"); + printf ("%.*s\n", (int) clen, cvalue); + free (cvalue); + break; + } + } + exit (0); +} + +int +main (int argc, char *argv[]) +{ + register const struct conf *c; + + /* Set locale. Do not set LC_ALL because the other categories must + not be affected (according to POSIX.2). */ + + /* Initialize the message catalog. */ + + if (argc > 1 && strcmp (argv[1], "--version") == 0) + { + printf ("getconf (GNU %s) %s\n", PACKAGE, VERSION); + printf ("\ +Copyright (C) %s Free Software Foundation, Inc.\n\ +This is free software; see the source for copying conditions. There is NO\n\ +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\ +", "2009"); + printf ("Written by %s.\n", "Roland McGrath"); + return 0; + } + + if (argc > 1 && strcmp (argv[1], "--help") == 0) + { + printf ("\ +Usage: getconf [-v SPEC] VAR\n\ + or: getconf [-v SPEC] PATH_VAR PATH\n\ +\n\ +Get the configuration value for variable VAR, or for variable PATH_VAR\n\ +for path PATH. If SPEC is given, give values for compilation\n\ +environment SPEC.\n\n"); + fputs ("For bug reporting instructions, please see:\n\ +.\n", stdout); + return 0; + } + + const char *getconf_dir = getenv ("GETCONF_DIR") ?: GETCONF_DIR; + size_t getconf_dirlen = strlen (getconf_dir); + + const char *spec = NULL; + char buf[sizeof "POSIX_V6_LPBIG_OFFBIG"]; + char *argv0 = argv[0]; + if (argc > 1 && strncmp (argv[1], "-v", 2) == 0) + { + if (argv[1][2] == '\0') + { + if (argc < 3) + usage (); + + spec = argv[2]; + argv += 2; + argc -= 2; + } + else + { + spec = &argv[1][2]; + argv += 1; + argc += 1; + } + } + else + { + char default_name[getconf_dirlen + sizeof "/default"]; + memcpy (mempcpy (default_name, getconf_dir, getconf_dirlen), + "/default", sizeof "/default"); + int len = readlink (default_name, buf, sizeof buf - 1); + if (len > 0) + { + buf[len] = '\0'; + spec = buf; + } + } + + /* Check for the specifications we know. */ + if (spec != NULL) + { + int i; + for (i = 0; i < nspecs; ++i) + if (strcmp (spec, specs[i].name) == 0) + break; + + if (i == nspecs) + error (2, 0, _("unknown specification \"%s\""), spec); + + switch (specs[i].num) + { +#if !defined(_XBS5_ILP32_OFF32) && defined(_SC_XBS5_ILP32_OFF32) + case _SC_XBS5_ILP32_OFF32: +#endif +#if !defined(_XBS5_ILP32_OFFBIG) && defined(_SC_XBS5_ILP32_OFFBIG) + case _SC_XBS5_ILP32_OFFBIG: +#endif +#if !defined(_XBS5_LP64_OFF64) && defined(_SC_XBS5_LP64_OFF64) + case _SC_XBS5_LP64_OFF64: +#endif +#if !defined(_XBS5_LPBIG_OFFBIG) && defined(_SC_XBS5_LPBIG_OFFBIG) + case _SC_XBS5_LPBIG_OFFBIG: +#endif +#if !defined(_POSIX_V6_ILP32_OFF32) && defined(_SC_V6_ILP32_OFF32) + case _SC_V6_ILP32_OFF32: +#endif +#if !defined(_POSIX_V6_ILP32_OFFBIG) && defined(_SC_V6_ILP32_OFFBIG) + case _SC_V6_ILP32_OFFBIG: +#endif +#if !defined(_POSIX_V6_LP64_OFF64) && defined(_SC_V6_LP64_OFF64) + case _SC_V6_LP64_OFF64: +#endif +#if !defined(_POSIX_V6_LPBIG_OFFBIG) && defined(_SC_V6_LPBIG_OFFBIG) + case _SC_V6_LPBIG_OFFBIG: +#endif +#if !defined(_POSIX_V7_ILP32_OFF32) && defined(_SC_V7_ILP32_OFF32) + case _SC_V7_ILP32_OFF32: +#endif +#if !defined(_POSIX_V7_ILP32_OFFBIG) && defined(_SC_V7_ILP32_OFFBIG) + case _SC_V7_ILP32_OFFBIG: +#endif +#if !defined(_POSIX_V7_LP64_OFF64) && defined(_SC_V7_LP64_OFF64) + case _SC_V7_LP64_OFF64: +#endif +#if !defined(_POSIX_V7_LPBIG_OFFBIG) && defined(_SC_V7_LPBIG_OFFBIG) + case _SC_V7_LPBIG_OFFBIG: +#endif + { + const char *args[argc + 3]; + size_t spec_len = strlen (spec); + char getconf_name[getconf_dirlen + 1 + spec_len + 1]; + memcpy (mempcpy (mempcpy (getconf_name, getconf_dir, + getconf_dirlen), + "/", 1), spec, spec_len + 1); + args[0] = argv0; + args[1] = "-v"; + args[2] = spec; + memcpy (&args[3], &argv[1], argc * sizeof (argv[1])); + execv (getconf_name, (char * const *) args); + error (4, errno, _("Couldn't execute %s"), getconf_name); + } + default: + break; + } + } + + if (argc > 1 && strcmp (argv[1], "-a") == 0) + { + if (argc == 2) + print_all ("/"); + else if (argc == 3) + print_all (argv[2]); + else + usage (); + } + + int ai = 1; + if (argc > ai && strcmp (argv[ai], "--") == 0) + ++ai; + + if (argc - ai < 1 || argc - ai > 2) + usage (); + + for (c = vars; c->name != NULL; ++c) + if (strcmp (c->name, argv[ai]) == 0 + || (strncmp (c->name, "_POSIX_", 7) == 0 + && strcmp (c->name + 7, argv[ai]) == 0)) + { + long int value; + size_t clen; + char *cvalue; + switch (c->call) + { + case PATHCONF: + if (argc - ai < 2) + usage (); + errno = 0; + value = pathconf (argv[ai + 1], c->call_name); + if (value == -1) + { + if (errno) { + error (3, errno, "pathconf: %s", argv[ai + 1]); + } else + puts (_("undefined")); + } + else + printf ("%ld\n", value); + exit (0); + + case SYSCONF: + if (argc - ai > 1) + usage (); + value = sysconf (c->call_name); + if (value == -1l) + { + if (c->call_name == _SC_UINT_MAX + || c->call_name == _SC_ULONG_MAX) + printf ("%lu\n", value); + else + puts (_("undefined")); + } + else + printf ("%ld\n", value); + exit (0); + + case CONFSTR: + if (argc - ai > 1) + usage (); + clen = confstr (c->call_name, (char *) NULL, 0); + cvalue = (char *) malloc (clen); + if (cvalue == NULL) + error (3, 0, _("memory exhausted")); + + if (confstr (c->call_name, cvalue, clen) != clen) + error (3, errno, "confstr"); + + printf ("%.*s\n", (int) clen, cvalue); + exit (0); + } + } + + error (2, 0, _("Unrecognized variable `%s'"), argv[ai]); + /* NOTREACHED */ + return 2; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/utils/iconv.c b/l4/pkg/uclibc/lib/contrib/uclibc/utils/iconv.c new file mode 100644 index 00000000..589c64cb --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/utils/iconv.c @@ -0,0 +1,264 @@ + +/* Copyright (C) 2002, 2003, 2004 Manuel Novoa III + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION! + * + * Besides uClibc, I'm using this code in my libc for elks, which is + * a 16-bit environment with a fairly limited compiler. It would make + * things much easier for me if this file isn't modified unnecessarily. + * In particular, please put any new or replacement functions somewhere + * else, and modify the makefile to use your version instead. + * Thanks. Manuel + * + * ATTENTION! ATTENTION! ATTENTION! ATTENTION! ATTENTION! */ + + +/* May 23, 2002 Initial Notes: + * + * I'm still tweaking this stuff, but it passes the tests I've thrown + * at it, and Erik needs it for the gcc port. The glibc extension + * __wcsnrtombs() hasn't been tested, as I didn't find a test for it + * in the glibc source. I also need to fix the behavior of + * _wchar_utf8sntowcs() if the max number of wchars to convert is 0. + * + * UTF-8 -> wchar -> UTF-8 conversion tests on Markus Kuhn's UTF-8-demo.txt + * file on my platform (x86) show about 5-10% faster conversion speed than + * glibc with mbsrtowcs()/wcsrtombs() and almost twice as fast as glibc with + * individual mbrtowc()/wcrtomb() calls. + * + * If 'DECODER' is defined, then _wchar_utf8sntowcs() will be compiled + * as a fail-safe UTF-8 decoder appropriate for a terminal, etc. which + * needs to deal gracefully with whatever is sent to it. In that mode, + * it passes Markus Kuhn's UTF-8-test.txt stress test. I plan to add + * an arg to force that behavior, so the interface will be changing. + * + * I need to fix the error checking for 16-bit wide chars. This isn't + * an issue for uClibc, but may be for ELKS. I'm currently not sure + * if I'll use 16-bit, 32-bit, or configureable wchars in ELKS. + * + * July 1, 2002 + * + * Fixed _wchar_utf8sntowcs() for the max number of wchars == 0 case. + * Fixed nul-char bug in btowc(), and another in __mbsnrtowcs() for 8-bit + * locales. + * Enabled building of a C/POSIX-locale-only version, so full locale support + * no longer needs to be enabled. + * + * Nov 4, 2002 + * + * Fixed a bug in _wchar_wcsntoutf8s(). Don't store wcs position if dst is NULL. + * Also, introduce an awful hack into _wchar_wcsntoutf8s() and wcsrtombs() in + * order to support %ls in printf. See comments below for details. + * Change behaviour of wc<->mb functions when in the C locale. Now they do + * a 1-1 map for the range 0x80-UCHAR_MAX. This is for backwards compatibility + * and consistency with the stds requirements that a printf format string by + * a valid multibyte string beginning and ending in it's initial shift state. + * + * Nov 5, 2002 + * + * Forgot to change btowc and wctob when I changed the wc<->mb functions yesterday. + * + * Nov 7, 2002 + * + * Add wcwidth and wcswidth, based on Markus Kuhn's wcwidth of 2002-05-08. + * Added some size/speed optimizations and integrated it into my locale + * framework. Minimally tested at the moment, but the stub C-locale + * version (which most people would probably be using) should be fine. + * + * Nov 21, 2002 + * + * Revert the wc<->mb changes from earlier this month involving the C-locale. + * Add a couple of ugly hacks to support *wprintf. + * Add a mini iconv() and iconv implementation (requires locale support). + * + * Aug 1, 2003 + * Bug fix for mbrtowc. + * + * Aug 18, 2003 + * Bug fix: _wchar_utf8sntowcs and _wchar_wcsntoutf8s now set errno if EILSEQ. + * + * Feb 11, 2004 + * Bug fix: Fix size check for remaining output space in iconv(). + * + * Manuel + */ + +#include "porting.h" +#include +#include +#include +#include +#include +#include "wchar.c" /* for _UC_iconv_t and __iconv_codesets */ + +extern const unsigned char __iconv_codesets[]; + +#define IBUF BUFSIZ +#define OBUF BUFSIZ + +static char *progname; +static int hide_errors; + +static void error_msg(const char *fmt, ...) + __attribute__ ((noreturn, format (printf, 1, 2))); + +static void error_msg(const char *fmt, ...) +{ + va_list arg; + + if (!hide_errors) { + fprintf(stderr, "%s: ", progname); + va_start(arg, fmt); + vfprintf(stderr, fmt, arg); + va_end(arg); + } + + exit(EXIT_FAILURE); +} + +int main(int argc, char **argv) +{ + FILE *ifile; + FILE *ofile = stdout; + const char *p; + const char *s; + static const char opt_chars[] = "tfocsl"; + /* 012345 */ + const char *opts[sizeof(opt_chars)]; /* last is infile name */ + iconv_t ic; + char ibuf[IBUF]; + char obuf[OBUF]; + char *pi; + char *po; + size_t ni, no, r, pos; + + hide_errors = 0; + + for (s = opt_chars ; *s ; s++) { + opts[ s - opt_chars ] = NULL; + } + + progname = *argv; + while (--argc) { + p = *++argv; + if ((*p != '-') || (*++p == 0)) { + break; + } + do { + if ((s = strchr(opt_chars,*p)) == NULL) { + USAGE: + s = basename(progname); + fprintf(stderr, + "%s [-cs] -f fromcode -t tocode [-o outputfile] [inputfile ...]\n" + " or\n%s -l\n", s, s); + return EXIT_FAILURE; + } + if ((s - opt_chars) < 3) { + if ((--argc == 0) || opts[s - opt_chars]) { + goto USAGE; + } + opts[s - opt_chars] = *++argv; + } else { + opts[s - opt_chars] = p; + } + } while (*++p); + } + + if (opts[5]) { /* -l */ + fprintf(stderr, "Recognized codesets:\n"); + for (s = (char *)__iconv_codesets ; *s ; s += *s) { + fprintf(stderr," %s\n", s+2); + } + s = __LOCALE_DATA_CODESET_LIST; + do { + fprintf(stderr," %s\n", __LOCALE_DATA_CODESET_LIST+ (unsigned char)(*s)); + } while (*++s); + + return EXIT_SUCCESS; + } + + if (opts[4]) { + hide_errors = 1; + } + + if (!opts[0] || !opts[1]) { + goto USAGE; + } + if ((ic = iconv_open(opts[0],opts[1])) == ((iconv_t)(-1))) { + error_msg( "unsupported codeset in %s -> %s conversion\n", opts[1], opts[0]); + } + if (opts[3]) { /* -c */ + ((_UC_iconv_t *) ic)->skip_invalid_input = 1; + } + + if ((s = opts[2]) != NULL) { + if (!(ofile = fopen(s, "w"))) { + error_msg( "couldn't open %s for writing\n", s); + } + } + + pos = ni = 0; + do { + if (!argc || ((**argv == '-') && !((*argv)[1]))) { + ifile = stdin; /* we don't check for duplicates */ + } else if (!(ifile = fopen(*argv, "r"))) { + error_msg( "couldn't open %s for reading\n", *argv); + } + + while ((r = fread(ibuf + ni, 1, IBUF - ni, ifile)) > 0) { + pos += r; + ni += r; + no = OBUF; + pi = ibuf; + po = obuf; + if ((r = iconv(ic, &pi, &ni, &po, &no)) == ((size_t)(-1))) { + if ((errno != EINVAL) && (errno != E2BIG)) { + error_msg( "iconv failed at pos %lu : %m\n", (unsigned long) (pos - ni)); + } + } + if ((r = OBUF - no) > 0) { + if (fwrite(obuf, 1, OBUF - no, ofile) < r) { + error_msg( "write error\n"); + } + } + if (ni) { /* still bytes in buffer! */ + memmove(ibuf, pi, ni); + } + } + + if (ferror(ifile)) { + error_msg( "read error\n"); + } + + ++argv; + + if (ifile != stdin) { + fclose(ifile); + } + + } while (--argc > 0); + + iconv_close(ic); + + if (ni) { + error_msg( "incomplete sequence\n"); + } + + return (((_UC_iconv_t *) ic)->skip_invalid_input < 2) + ? EXIT_SUCCESS : EXIT_FAILURE; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/utils/ldconfig.c b/l4/pkg/uclibc/lib/contrib/uclibc/utils/ldconfig.c new file mode 100644 index 00000000..a25de260 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/utils/ldconfig.c @@ -0,0 +1,984 @@ +/* + * ldconfig - update shared library symlinks + * + * usage: ldconfig [-DvqnNX] [-f conf] [-C cache] [-r root] dir ... + * ldconfig -l [-Dv] lib ... + * ldconfig -p + * -D: debug mode, don't update links + * -v: verbose mode, print things as we go + * -q: quiet mode, don't print warnings + * -n: don't process standard directories + * -N: don't update the library cache + * -X: don't update the library links + * -l: library mode, manually link libraries + * -p: print the current library cache + * -f conf: use conf instead of /etc/ld.so.conf + * -C cache: use cache instead of /etc/ld.so.cache + * -r root: first, do a chroot to the indicated directory + * dir ...: directories to process + * lib ...: libraries to link + * + * Copyright 1994-2000 David Engel and Mitch D'Souza + * + * This program may be used for any purpose as long as this + * copyright notice is kept. + * + * 2005/09/16: Dan Howell (modified for cross-development) + */ + +#include "porting.h" + +#define BUFFER_SIZE 4096 + +struct exec { + unsigned long a_info; /* Use macros N_MAGIC, etc for access */ + unsigned a_text; /* length of text, in bytes */ + unsigned a_data; /* length of data, in bytes */ + unsigned a_bss; /* length of uninitialized data area for file, in bytes */ + unsigned a_syms; /* length of symbol table data in file, in bytes */ + unsigned a_entry; /* start address */ + unsigned a_trsize; /* length of relocation info for text, in bytes */ + unsigned a_drsize; /* length of relocation info for data, in bytes */ +}; + +#if !defined (N_MAGIC) +#define N_MAGIC(exec) ((exec).a_info & 0xffff) +#endif +#define N_MAGIC_SWAP(exec) (bswap_32((exec).a_info) & 0xffff) +/* Code indicating object file or impure executable. */ +#define OMAGIC 0407 +/* Code indicating pure executable. */ +#define NMAGIC 0410 +/* Code indicating demand-paged executable. */ +#define ZMAGIC 0413 +/* This indicates a demand-paged executable with the header in the text. + The first page is unmapped to help trap NULL pointer references */ +#define QMAGIC 0314 +/* Code indicating core file. */ +#define CMAGIC 0421 + +char *___strtok = NULL; + +char *prog = NULL; +int debug = 0; /* debug mode */ +int verbose = 0; /* verbose mode */ +int libmode = 0; /* library mode */ +int nolinks = 0; /* don't update links */ +int nocache = 0; /* don't build cache */ +void cache_print(void); +void cache_write(void); +void cache_dolib(const char *dir, const char *so, int libtype); +#ifdef __LDSO_CACHE_SUPPORT__ +char *conffile = LDSO_CONF; /* default conf file */ +char *cachefile = LDSO_CACHE; /* default cache file */ +#endif +char *chroot_dir = NULL; +int byteswap = 0; + +struct needed_tab { + char *soname; + int type; +}; + +struct needed_tab needed_tab[] = { + {"libc.so.0", LIB_ELF_LIBC0}, + {"libm.so.0", LIB_ELF_LIBC0}, + {"libdl.so.0", LIB_ELF_LIBC0}, + {"libc.so.5", LIB_ELF_LIBC5}, + {"libm.so.5", LIB_ELF_LIBC5}, + {"libdl.so.1", LIB_ELF_LIBC5}, + {"libc.so.6", LIB_ELF_LIBC6}, + {"libm.so.6", LIB_ELF_LIBC6}, + {"libdl.so.2", LIB_ELF_LIBC6}, + {NULL, LIB_ELF} +}; + +extern char *chroot_realpath(const char *chroot, const char *path, + char resolved_path[]); + +/* These two are used internally -- you shouldn't need to use them */ +static void verror_msg(const char *s, va_list p) +{ + fflush(stdout); + fprintf(stderr, "%s: ", prog); + vfprintf(stderr, s, p); +} + +static void warnx(const char *s, ...) +{ + va_list p; + + va_start(p, s); + verror_msg(s, p); + va_end(p); + fprintf(stderr, "\n"); +} + +static void err(int errnum, const char *s, ...) attribute_noreturn; +static void err(int errnum, const char *s, ...) +{ + va_list p; + + va_start(p, s); + verror_msg(s, p); + va_end(p); + fprintf(stderr, "\n"); + exit(errnum); +} + +static void vperror_msg(const char *s, va_list p) +{ + int e = errno; + + if (s == 0) + s = ""; + verror_msg(s, p); + if (*s) + s = ": "; + fprintf(stderr, "%s%s\n", s, strerror(e)); +} + +static void warn(const char *s, ...) +{ + va_list p; + + va_start(p, s); + vperror_msg(s, p); + va_end(p); +} + +static void *xmalloc(size_t size) +{ + void *ptr; + if ((ptr = malloc(size)) == NULL) + err(EXIT_FAILURE, "out of memory"); + return ptr; +} + +static char *xstrdup(const char *str) +{ + char *ptr; + if ((ptr = strdup(str)) == NULL) + err(EXIT_FAILURE, "out of memory"); + return ptr; +} + +#undef __ELF_NATIVE_CLASS +#undef readsonameXX +#define readsonameXX readsoname32 +#define __ELF_NATIVE_CLASS 32 +#include "readsoname2.c" + +#undef __ELF_NATIVE_CLASS +#undef readsonameXX +#define readsonameXX readsoname64 +#define __ELF_NATIVE_CLASS 64 +#include "readsoname2.c" +static char *readsoname(char *name, FILE *infile, int expected_type, + int *type, int elfclass) +{ + char *res; + + if (elfclass == ELFCLASS32) + res = readsoname32(name, infile, expected_type, type); + else { + res = readsoname64(name, infile, expected_type, type); +#if 0 + /* relies on multilib support which we dont have ... */ + *type |= LIB_ELF64; +#endif + } + + return res; +} + +/* If shared library, return a malloced copy of the soname and set the + * type, else return NULL. + * + * expected_type should be either LIB_ANY or one of the following:- + * LIB_DLL + * LIB_ELF + * LIB_ELF_LIBC5 + * LIB_ELF_LIBC6 + * + * If the lib is ELF and we can not deduce the type the type will + * be set based on expected_type. + * + * If the expected, actual/deduced types missmatch we display a warning + * and use the actual/deduced type. + */ +static char *is_shlib(const char *dir, const char *name, int *type, + int *islink, int expected_type) +{ + char *good = NULL; + char *cp, *cp2; + FILE *file; + struct exec exec; + ElfW(Ehdr) *elf_hdr; + struct stat statbuf; + char buff[BUFFER_SIZE]; + char real[BUFFER_SIZE]; + static int byteswapflag = -1; /* start with byte-order unknown */ + + /* see if name is of the form *.so* */ + if (name[strlen(name) - 1] != '~' && (cp = strstr(name, ".so"))) { + /* find the start of the Vminor part, if any */ + if (cp[3] == '.' && (cp2 = strchr(cp + 4, '.'))) + cp = cp2; + else + cp = cp + strlen(cp); + + /* construct the full path name */ + sprintf(buff, "%s%s%s", dir, (*dir && strcmp(dir, "/")) ? "/" : "", name); + + /* get real path in case of chroot */ + if (!chroot_realpath(chroot_dir, buff, real)) + warn("can't resolve %s in chroot %s", buff, chroot_dir); + + /* first, make sure it's a regular file */ + if (lstat(real, &statbuf)) + warn("skipping %s", buff); + else if (!S_ISREG(statbuf.st_mode) && !S_ISLNK(statbuf.st_mode)) + warnx("%s is not a regular file or symlink, skipping", buff); + else { + /* is it a regular file or a symlink */ + *islink = S_ISLNK(statbuf.st_mode); + + /* then try opening it */ + if (!(file = fopen(real, "rb"))) + warn("skipping %s", buff); + else { + /* now make sure it's a shared library */ + if (fread(&exec, sizeof exec, 1, file) < 1) + warnx("can't read header from %s, skipping", buff); + else if (N_MAGIC(exec) != ZMAGIC + && N_MAGIC(exec) != QMAGIC + && N_MAGIC_SWAP(exec) != ZMAGIC + && N_MAGIC_SWAP(exec) != QMAGIC) { + elf_hdr = (ElfW(Ehdr) *) & exec; + if (elf_hdr->e_ident[0] != 0x7f || + strncmp((char *)elf_hdr->e_ident + 1, "ELF", 3) != 0) + { + /* silently ignore linker scripts */ + if (strncmp((char *)&exec, "/* GNU ld", 9) != 0) + warnx("%s is not a shared library, skipping", buff); + } else { + /* always call readsoname to update type */ + if (expected_type == LIB_DLL) { + warnx("%s is not an a.out library, it's ELF!", buff); + expected_type = LIB_ANY; + } + *type = LIB_ELF; + good = readsoname(buff, file, expected_type, type, + elf_hdr->e_ident[EI_CLASS]); + if (byteswapflag == -1) + /* byte-order detected */ + byteswapflag = byteswap; + if (good == NULL || *islink) { + if (good != NULL) + free(good); + good = xstrdup(name); + } else { + /* if the soname does not match the filename, + issue a warning, but only in debug mode. */ + int len = strlen(good); + if (debug && (strncmp(good, name, len) != 0 + || (name[len] != '\0' && name[len] != '.'))) + warnx("%s has inconsistent soname (%s)", buff, good); + } + } + } else { + /* Determine byte-order */ + byteswap = (N_MAGIC(exec) == ZMAGIC || N_MAGIC(exec) == QMAGIC) ? 0 : 1; + if (byteswapflag == -1) + /* byte-order detected */ + byteswapflag = byteswap; + + if (*islink) + good = xstrdup(name); + else { + good = xmalloc(cp - name + 1); + strncpy(good, name, cp - name); + good[cp - name] = '\0'; + } + if (expected_type != LIB_ANY && expected_type != LIB_DLL) { + warnx("%s is not an ELF library, its an a.out DLL!", buff); + expected_type = LIB_ANY; + } + + *type = LIB_DLL; + } + fclose(file); + + if (byteswapflag >= 0 && byteswap != byteswapflag) { + byteswapflag = -2; + warnx("mixed byte-order detected, using host byte-order..."); + } + if (byteswapflag == -2) + byteswap = 0; + } + } + } + + return good; +} + +/* update the symlink to new library */ +static void link_shlib(const char *dir, const char *file, const char *so) +{ + int change = 1; + char libname[BUFFER_SIZE]; + char linkname[BUFFER_SIZE]; + char reallibname[BUFFER_SIZE]; + char reallinkname[BUFFER_SIZE]; + struct stat libstat; + struct stat linkstat; + + /* construct the full path names */ + sprintf(libname, "%s/%s", dir, file); + sprintf(linkname, "%s/%s", dir, so); + if (!chroot_realpath(chroot_dir, libname, reallibname)) + warn("can't resolve %s in chroot %s", libname, chroot_dir); + if (!chroot_realpath(chroot_dir, linkname, reallinkname)) + warn("can't resolve %s in chroot %s", linkname, chroot_dir); + + /* see if a link already exists */ + if (!stat(reallinkname, &linkstat)) { + /* now see if it's the one we want */ + if (stat(reallibname, &libstat)) + warn("can't stat %s", libname); + else if (libstat.st_dev == linkstat.st_dev && + libstat.st_ino == linkstat.st_ino) + change = 0; + } + + /* then update the link, if required */ + if (change > 0 && !nolinks) { + if (!lstat(reallinkname, &linkstat)) { + if (!S_ISLNK(linkstat.st_mode)) { + warnx("%s is not a symlink", linkname); + change = -1; + } else if (remove(reallinkname)) { + warn("can't unlink %s", linkname); + change = -1; + } + } + if (change > 0) { + if (symlink(file, reallinkname)) { + warn("can't link %s to %s", linkname, file); + change = -1; + } + } + } + + /* some people like to know what we're doing */ + if (verbose > 0) + printf("\t%s => %s%s\n", so, file, + change < 0 ? " (SKIPPED)" : + (change > 0 ? " (changed)" : "")); + + return; +} + +/* figure out which library is greater */ +static int libcmp(char *p1, char *p2) +{ + while (*p1) { + if (isdigit(*p1) && isdigit(*p2)) { + /* must compare this numerically */ + int v1, v2; + v1 = strtoul(p1, &p1, 10); + v2 = strtoul(p2, &p2, 10); + if (v1 != v2) + return v1 - v2; + } else if (isdigit(*p1) && !isdigit(*p2)) + return 1; + else if (!isdigit(*p1) && isdigit(*p2)) + return -1; + else if (*p1 != *p2) + return *p1 - *p2; + else + p1++, p2++; + } + + return *p1 - *p2; +} + +struct lib { + char *so; /* soname of a library */ + char *name; /* name of a library */ + int libtype; /* type of a library */ + int islink; /* is it a symlink */ + struct lib *next; /* next library in list */ +}; + +/* update all shared library links in a directory */ +static void scan_dir(const char *rawname) +{ + DIR *dir; + const char *name; + struct dirent *ent; + char *so, *path, *path_n; + struct lib *lp, *libs = NULL; + int i, libtype, islink, expected_type = LIB_ANY; + char realname[BUFFER_SIZE]; + + /* We need a writable copy of this string */ + path = strdup(rawname); + if (!path) { + err(EXIT_FAILURE, "Out of memory!\n"); + } + /* Eliminate all double //s */ + path_n = path; + while ((path_n = strstr(path_n, "//"))) { + i = strlen(path_n); + memmove(path_n, path_n + 1, i - 1); + *(path_n + i - 1) = '\0'; + } + name = path; + +#if 0 + char *t; + /* Check for an embedded expected type */ + t = strrchr(name, '='); + if (t) { + *t++ = '\0'; /* Skip = char */ + if (strcasecmp(t, "libc4") == 0) { + expected_type = LIB_DLL; + } else { + if (strcasecmp(t, "libc5") == 0) { + expected_type = LIB_ELF_LIBC5; + } else { + if (strcasecmp(t, "libc6") == 0) { + expected_type = LIB_ELF_LIBC6; + } else { + if (strcasecmp(t, "libc0") == 0) { + expected_type = LIB_ELF_LIBC0; + } else { + warnx("Unknown type field '%s' for dir '%s' - ignored", t, name); + expected_type = LIB_ANY; + } + } + } + } + } +#endif + + /* let 'em know what's going on */ + if (verbose > 0) + printf("%s:\n", name); + + /* get real path in case of chroot */ + if (!chroot_realpath(chroot_dir, name, realname)) + warn("can't resolve %s in chroot %s", name, chroot_dir); + + /* if we can't open it, we can't do anything */ + if ((dir = opendir(realname)) == NULL) { + warn("skipping %s", name); + free(path); + return; + } + + /* yes, we have to look at every single file */ + while ((ent = readdir(dir)) != NULL) { + /* if it's not a shared library, don't bother */ + if ((so = is_shlib(name, ent->d_name, &libtype, &islink, expected_type)) == NULL) + continue; + + /* have we already seen one with the same so name? */ + for (lp = libs; lp; lp = lp->next) { + if (strcmp(so, lp->so) == 0) { + /* we have, which one do we want to use? */ + if ((!islink && lp->islink) || + (islink == lp->islink && + libcmp(ent->d_name, lp->name) > 0)) { + /* let's use the new one */ + free(lp->name); + lp->name = xstrdup(ent->d_name); + lp->libtype = libtype; + lp->islink = islink; + } + break; + } + } + + /* congratulations, you're the first one we've seen */ + if (!lp) { + lp = xmalloc(sizeof *lp); + lp->so = xstrdup(so); + lp->name = xstrdup(ent->d_name); + lp->libtype = libtype; + lp->islink = islink; + lp->next = libs; + libs = lp; + } + + free(so); + } + + /* don't need this any more */ + closedir(dir); + + /* now we have all the latest libs, update the links */ + for (lp = libs; lp; lp = lp->next) { + if (!lp->islink) + link_shlib(name, lp->name, lp->so); + if (!nocache) + cache_dolib(name, lp->so, lp->libtype); + } + + /* always try to clean up after ourselves */ + while (libs) { + lp = libs->next; + free(libs->so); + free(libs->name); + free(libs); + libs = lp; + } + + free(path); + return; +} + +#ifndef __LDSO_CACHE_SUPPORT__ +void cache_print(void) +{ + printf("Library cache disabled\n"); +} +void cache_dolib(const char *dir, const char *so, int libtype) +{ + return; +} +void cache_write(void) +{ + return; +} +#else +/* return the list of system-specific directories */ +static char *get_extpath(void) +{ + char *res = NULL, *cp; + FILE *file; + struct stat st; + char realconffile[BUFFER_SIZE]; + + if (!chroot_realpath(chroot_dir, conffile, realconffile)) + return NULL; + + if ((file = fopen(realconffile, "r")) != NULL) { + fstat(fileno(file), &st); + res = xmalloc(st.st_size + 1); + fread(res, 1, st.st_size, file); + fclose(file); + res[st.st_size] = '\0'; + + /* convert comments fo spaces */ + for (cp = res; *cp; /*nada */ ) { + if (*cp == '#') { + do + *cp++ = ' '; + while (*cp && *cp != '\n'); + } else { + cp++; + } + } + } + + return res; +} + +typedef struct liblist { + int flags; + int sooffset; + int liboffset; + char *soname; + char *libname; + struct liblist *next; +} liblist_t; + +static header_t magic = { LDSO_CACHE_MAGIC, LDSO_CACHE_VER, 0 }; +static liblist_t *lib_head = NULL; + +static int liblistcomp(liblist_t *x, liblist_t *y) +{ + int res; + + if ((res = libcmp(x->soname, y->soname)) == 0) { + res = libcmp(strrchr(x->libname, '/') + 1, + strrchr(y->libname, '/') + 1); + } + + return res; +} + +void cache_dolib(const char *dir, const char *so, int libtype) +{ + char fullpath[PATH_MAX]; + liblist_t *new_lib, *cur_lib; + + magic.nlibs++; + sprintf(fullpath, "%s/%s", dir, so); + new_lib = xmalloc(sizeof(liblist_t)); + new_lib->flags = libtype; + new_lib->soname = xstrdup(so); + new_lib->libname = xstrdup(fullpath); + + if (lib_head == NULL || liblistcomp(new_lib, lib_head) > 0) { + new_lib->next = lib_head; + lib_head = new_lib; + } else { + for (cur_lib = lib_head; cur_lib->next != NULL && + liblistcomp(new_lib, cur_lib->next) <= 0; + cur_lib = cur_lib->next) + /* nothing */ ; + new_lib->next = cur_lib->next; + cur_lib->next = new_lib; + } +} + +void cache_write(void) +{ + int cachefd; + int stroffset = 0; + char realcachefile[BUFFER_SIZE]; + char tempfile[BUFFER_SIZE]; + header_t swap_magic; + header_t *magic_ptr; + libentry_t swap_lib; + libentry_t *lib_ptr; + liblist_t *cur_lib; + + if (!magic.nlibs) + return; + + if (!chroot_realpath(chroot_dir, cachefile, realcachefile)) + err(EXIT_FAILURE, "can't resolve %s in chroot %s (%s)", + cachefile, chroot_dir, strerror(errno)); + + sprintf(tempfile, "%s~", realcachefile); + + if (unlink(tempfile) && errno != ENOENT) + err(EXIT_FAILURE, "can't unlink %s~ (%s)", cachefile, + strerror(errno)); + + if ((cachefd = creat(tempfile, 0644)) < 0) + err(EXIT_FAILURE, "can't create %s~ (%s)", cachefile, + strerror(errno)); + + if (byteswap) { + swap_magic = magic; + swap_magic.nlibs = bswap_32(swap_magic.nlibs); + magic_ptr = &swap_magic; + } else { + magic_ptr = &magic; + } + if (write(cachefd, magic_ptr, sizeof(header_t)) != sizeof(header_t)) + err(EXIT_FAILURE, "can't write %s~ (%s)", cachefile, + strerror(errno)); + + for (cur_lib = lib_head; cur_lib != NULL; cur_lib = cur_lib->next) { + cur_lib->sooffset = stroffset; + stroffset += strlen(cur_lib->soname) + 1; + cur_lib->liboffset = stroffset; + stroffset += strlen(cur_lib->libname) + 1; + if (byteswap) { + swap_lib.flags = bswap_32(cur_lib->flags); + swap_lib.sooffset = bswap_32(cur_lib->sooffset); + swap_lib.liboffset = bswap_32(cur_lib->liboffset); + lib_ptr = &swap_lib; + } else { + lib_ptr = (libentry_t *) cur_lib; + } + if (write(cachefd, lib_ptr, sizeof(libentry_t)) != + sizeof(libentry_t)) + err(EXIT_FAILURE, "can't write %s~ (%s)", cachefile, + strerror(errno)); + } + + for (cur_lib = lib_head; cur_lib != NULL; cur_lib = cur_lib->next) { + if ((size_t)write(cachefd, cur_lib->soname, strlen(cur_lib->soname) + 1) + != strlen(cur_lib->soname) + 1) + err(EXIT_FAILURE, "can't write %s~ (%s)", cachefile, + strerror(errno)); + if ((size_t)write(cachefd, cur_lib->libname, strlen(cur_lib->libname) + 1) + != strlen(cur_lib->libname) + 1) + err(EXIT_FAILURE, "can't write %s~ (%s)", cachefile, + strerror(errno)); + } + + if (close(cachefd)) + err(EXIT_FAILURE, "can't close %s~ (%s)", cachefile, + strerror(errno)); + + if (chmod(tempfile, 0644)) + err(EXIT_FAILURE, "can't chmod %s~ (%s)", cachefile, + strerror(errno)); + + if (rename(tempfile, realcachefile)) + err(EXIT_FAILURE, "can't rename %s~ (%s)", cachefile, + strerror(errno)); +} + +void cache_print(void) +{ + caddr_t c; + struct stat st; + int fd = 0; + char *strs; + header_t *header; + libentry_t *libent; + char realcachefile[BUFFER_SIZE]; + + if (!chroot_realpath(chroot_dir, cachefile, realcachefile)) + err(EXIT_FAILURE, "can't resolve %s in chroot %s (%s)", + cachefile, chroot_dir, strerror(errno)); + + if (stat(realcachefile, &st) || (fd = open(realcachefile, O_RDONLY)) < 0) + err(EXIT_FAILURE, "can't read %s (%s)", cachefile, strerror(errno)); + + c = mmap(0, st.st_size, PROT_READ, LDSO_CACHE_MMAP_FLAGS, fd, 0); + if (c == MAP_FAILED) + err(EXIT_FAILURE, "can't map %s (%s)", cachefile, strerror(errno)); + close(fd); + + if (memcmp(((header_t *) c)->magic, LDSO_CACHE_MAGIC, LDSO_CACHE_MAGIC_LEN)) + err(EXIT_FAILURE, "%s cache corrupt", cachefile); + + if (memcmp(((header_t *) c)->version, LDSO_CACHE_VER, LDSO_CACHE_VER_LEN)) + err(EXIT_FAILURE, "wrong cache version - expected %s", + LDSO_CACHE_VER); + + header = (header_t *) c; + libent = (libentry_t *) (c + sizeof(header_t)); + strs = (char *)&libent[header->nlibs]; + + printf("%d libs found in cache `%s' (version %s)\n", + header->nlibs, cachefile, LDSO_CACHE_VER); + + for (fd = 0; fd < header->nlibs; fd++) { + printf("\t%s ", strs + libent[fd].sooffset); + switch (libent[fd].flags & ~LIB_ELF64) { + case LIB_DLL: + printf("(libc4)"); + break; + case LIB_ELF: + printf("(ELF%s)", libent[fd].flags & LIB_ELF64 ? "/64" : ""); + break; + case LIB_ELF_LIBC0: + printf("(libc0%s)", libent[fd].flags & LIB_ELF64 ? "/64" : ""); + break; + case LIB_ELF_LIBC5: + case LIB_ELF_LIBC6: + printf("(libc%d%s)", + (libent[fd].flags & ~LIB_ELF64) + 3, + libent[fd].flags & LIB_ELF64 ? "/64" : ""); + break; + default: + printf("(unknown)"); + break; + } + printf(" => %s\n", strs + libent[fd].liboffset); + } + + munmap(c, st.st_size); +} +#endif + +static void usage(void) attribute_noreturn; +static void usage(void) +{ + fprintf(stderr, +#ifdef __LDSO_CACHE_SUPPORT__ + "ldconfig - updates symlinks and cache for shared libraries\n\n" + "Usage: ldconfig [-DvqnNX] [-f conf] [-C cache] [-r root] dir ...\n" + " ldconfig -l [-Dv] lib ...\n" + " ldconfig -p\n\nOptions:\n" +#else + "ldconfig - updates symlinks for shared libraries\n\n" + "Usage: ldconfig [-DvqnX] [-r root] dir ...\n" + " ldconfig -l [-Dv] lib ...\n\nOptions:\n" +#endif + "\t-D:\t\tdebug mode, don't update links\n" + "\t-v:\t\tverbose mode, print things as we go\n" + "\t-q:\t\tquiet mode, don't print warnings\n" + "\t-n:\t\tdon't process standard directories\n" + "\t-N:\t\tdon't update the library cache\n" + "\t-X:\t\tdon't update the library links\n" + "\t-l:\t\tlibrary mode, manually link libraries\n" + "\t-p:\t\tprint the current library cache\n" +#ifdef __LDSO_CACHE_SUPPORT__ + "\t-f conf :\tuse conf instead of %s\n" + "\t-C cache:\tuse cache instead of %s\n" +#endif + "\t-r root :\tfirst, do a chroot to the indicated directory\n" + "\tdir ... :\tdirectories to process\n" +#ifdef __LDSO_CACHE_SUPPORT__ + "\tlib ... :\tlibraries to link\n\n", LDSO_CONF, LDSO_CACHE +#else + "\tlib ... :\tlibraries to link\n\n" +#endif + ); + exit(EXIT_FAILURE); +} + +#define DIR_SEP ":, \t\n" +int main(int argc, char **argv) +{ + int i, c; + int nodefault = 0; + char *cp, *dir, *so; + int libtype, islink; + int printcache = 0; +#ifdef __LDSO_CACHE_SUPPORT__ + char *extpath; +#endif + + prog = argv[0]; + opterr = 0; + + while ((c = getopt(argc, argv, "DvqnNXlpf:C:r:")) != EOF) + switch (c) { + case 'D': + debug = 1; /* debug mode */ + nocache = 1; + nolinks = 1; + verbose = 1; + break; + case 'v': + verbose = 1; /* verbose mode */ + break; + case 'q': + if (verbose <= 0) + verbose = -1; /* quiet mode */ + break; + case 'n': + nodefault = 1; /* no default dirs */ + nocache = 1; + break; + case 'N': + nocache = 1; /* don't build cache */ + break; + case 'X': + nolinks = 1; /* don't update links */ + break; + case 'l': + libmode = 1; /* library mode */ + break; + case 'p': + printcache = 1; /* print cache */ + break; + case 'f': +#ifdef __LDSO_CACHE_SUPPORT__ + conffile = optarg; /* alternate conf file */ +#endif + break; + case 'C': +#ifdef __LDSO_CACHE_SUPPORT__ + cachefile = optarg; /* alternate cache file */ +#endif + break; + case 'r': + chroot_dir = optarg; + break; + default: + usage(); + break; + + /* THE REST OF THESE ARE UNDOCUMENTED AND MAY BE REMOVED + IN FUTURE VERSIONS. */ + } + + if (chroot_dir && *chroot_dir) { + if (chroot(chroot_dir) < 0) { + if (chdir(chroot_dir) < 0) + err(EXIT_FAILURE, "couldn't chroot to %s (%s)", chroot_dir, strerror(errno)); + chroot_dir = "."; + } else { + if (chdir("/") < 0) + err(EXIT_FAILURE, "couldn't chdir to / (%s)", strerror(errno)); + chroot_dir = NULL; + } + } + + /* allow me to introduce myself, hi, my name is ... */ + if (verbose > 0) + printf("%s: uClibc version\n", argv[0]); + + if (printcache) { + /* print the cache -- don't you trust me? */ + cache_print(); + exit(EXIT_SUCCESS); + } else if (libmode) { + /* so you want to do things manually, eh? */ + + /* ok, if you're so smart, which libraries do we link? */ + for (i = optind; i < argc; i++) { + /* split into directory and file parts */ + if (!(cp = strrchr(argv[i], '/'))) { + dir = "."; /* no dir, only a filename */ + cp = argv[i]; + } else { + if (cp == argv[i]) + dir = "/"; /* file in root directory */ + else + dir = argv[i]; + *cp++ = '\0'; /* neither of the above */ + } + + /* we'd better do a little bit of checking */ + if ((so = is_shlib(dir, cp, &libtype, &islink, LIB_ANY)) == NULL) + err(EXIT_FAILURE, "%s%s%s is not a shared library", + dir, (*dir && strcmp(dir, "/")) ? "/" : "", cp); + + /* so far, so good, maybe he knows what he's doing */ + link_shlib(dir, cp, so); + } + } else { + /* the lazy bum want's us to do all the work for him */ + + /* don't cache dirs on the command line */ + int nocache_save = nocache; + nocache = 1; + + /* OK, which directories should we do? */ + for (i = optind; i < argc; i++) + scan_dir(argv[i]); + + /* restore the desired caching state */ + nocache = nocache_save; + + /* look ma, no defaults */ + if (!nodefault) { + scan_dir(UCLIBC_RUNTIME_PREFIX "lib"); + scan_dir(UCLIBC_RUNTIME_PREFIX "usr/lib"); +#ifndef __LDSO_CACHE_SUPPORT__ + scan_dir(UCLIBC_RUNTIME_PREFIX "usr/X11R6/lib"); +#else + /* I guess the defaults aren't good enough */ + if ((extpath = get_extpath())) { + for (cp = strtok(extpath, DIR_SEP); cp; cp = strtok(NULL, DIR_SEP)) { + /* strip trailing slashes */ + int len = strlen(cp); + if (len) + while (cp[--len] == '/' && len) + cp[len] = 0; + /* we do the redundancy check only if cache usage is enabled */ + if (strcmp(UCLIBC_RUNTIME_PREFIX "lib", cp) == 0 + || strcmp(UCLIBC_RUNTIME_PREFIX "usr/lib", cp) == 0) { + if (verbose >= 0) + warnx("You should remove `%s' from `%s'", cp, LDSO_CONF); + continue; + } + scan_dir(cp); + } + free(extpath); + } +#endif + } + + if (!nocache) + cache_write(); + } + + exit(EXIT_SUCCESS); +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/utils/ldd.c b/l4/pkg/uclibc/lib/contrib/uclibc/utils/ldd.c new file mode 100644 index 00000000..3858c815 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/utils/ldd.c @@ -0,0 +1,808 @@ +/* vi: set sw=4 ts=4: */ +/* + * A small little ldd implementation for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Several functions in this file (specifically, elf_find_section_type(), + * elf_find_phdr_type(), and elf_find_dynamic(), were stolen from elflib.c from + * elfvector (http://www.BitWagon.com/elfvector.html) by John F. Reiser + * , which is copyright 2000 BitWagon Software LLC + * (GPL2). + * + * Licensed under GPLv2 or later + */ + +#include "porting.h" + +#if defined(__alpha__) +#define MATCH_MACHINE(x) (x == EM_ALPHA) +#define ELFCLASSM ELFCLASS64 +#endif + +#if defined(__arm__) || defined(__thumb__) +#define MATCH_MACHINE(x) (x == EM_ARM) +#define ELFCLASSM ELFCLASS32 +#endif + +#if defined(__avr32__) +#define MATCH_MACHINE(x) (x == EM_AVR32) +#define ELFCLASSM ELFCLASS32 +#endif + +#if defined(__s390__) +#define MATCH_MACHINE(x) (x == EM_S390) +#define ELFCLASSM ELFCLASS32 +#endif + +#if defined(__hppa__) +#define MATCH_MACHINE(x) (x == EM_PARISC) +#if defined(__LP64__) +#define ELFCLASSM ELFCLASS64 +#else +#define ELFCLASSM ELFCLASS32 +#endif +#endif + +#if defined(__i386__) +#ifndef EM_486 +#define MATCH_MACHINE(x) (x == EM_386) +#else +#define MATCH_MACHINE(x) (x == EM_386 || x == EM_486) +#endif +#define ELFCLASSM ELFCLASS32 +#endif + +#if defined(__ia64__) +#define MATCH_MACHINE(x) (x == EM_IA_64) +#define ELFCLASSM ELFCLASS64 +#endif + +#if defined(__mc68000__) +#define MATCH_MACHINE(x) (x == EM_68K) +#define ELFCLASSM ELFCLASS32 +#endif + +#if defined(__mips__) +#define MATCH_MACHINE(x) (x == EM_MIPS || x == EM_MIPS_RS3_LE) +#define ELFCLASSM ELFCLASS32 +#endif + +#if defined(__powerpc64__) +#define MATCH_MACHINE(x) (x == EM_PPC64) +#define ELFCLASSM ELFCLASS64 +#elif defined(__powerpc__) +#define MATCH_MACHINE(x) (x == EM_PPC) +#define ELFCLASSM ELFCLASS32 +#endif + +#if defined(__sh__) +#define MATCH_MACHINE(x) (x == EM_SH) +#define ELFCLASSM ELFCLASS32 +#endif + +#if defined(__v850e__) +#define MATCH_MACHINE(x) ((x) == EM_V850 || (x) == EM_CYGNUS_V850) +#define ELFCLASSM ELFCLASS32 +#endif + +#if defined(__sparc__) +#define MATCH_MACHINE(x) ((x) == EM_SPARC || (x) == EM_SPARC32PLUS) +#define ELFCLASSM ELFCLASS32 +#endif + +#if defined(__cris__) +#define MATCH_MACHINE(x) (x == EM_CRIS) +#define ELFCLASSM ELFCLASS32 +#endif + +#if defined(__x86_64__) +#define MATCH_MACHINE(x) (x == EM_X86_64) +#define ELFCLASSM ELFCLASS64 +#endif + +#ifndef MATCH_MACHINE +# ifdef __linux__ +# include +# endif +# ifdef ELF_ARCH +# define MATCH_MACHINE(x) (x == ELF_ARCH) +# endif +# ifdef ELF_CLASS +# define ELFCLASSM ELF_CLASS +# endif +#endif +#ifndef MATCH_MACHINE +# warning "You really should add a MATCH_MACHINE() macro for your architecture" +#endif + +#if UCLIBC_ENDIAN_HOST == UCLIBC_ENDIAN_LITTLE +#define ELFDATAM ELFDATA2LSB +#elif UCLIBC_ENDIAN_HOST == UCLIBC_ENDIAN_BIG +#define ELFDATAM ELFDATA2MSB +#endif + +struct library { + char *name; + int resolved; + char *path; + struct library *next; +}; +static struct library *lib_list = NULL; +static char not_found[] = "not found"; +static char *interp_name = NULL; +static char *interp_dir = NULL; +static int byteswap; +static int interpreter_already_found = 0; + +static __inline__ uint32_t byteswap32_to_host(uint32_t value) +{ + if (byteswap == 1) { + return (bswap_32(value)); + } else { + return (value); + } +} +static __inline__ uint64_t byteswap64_to_host(uint64_t value) +{ + if (byteswap == 1) { + return (bswap_64(value)); + } else { + return (value); + } +} + +#if ELFCLASSM == ELFCLASS32 +# define byteswap_to_host(x) byteswap32_to_host(x) +#else +# define byteswap_to_host(x) byteswap64_to_host(x) +#endif + +static ElfW(Shdr) *elf_find_section_type(uint32_t key, ElfW(Ehdr) *ehdr) +{ + int j; + ElfW(Shdr) *shdr; + shdr = (ElfW(Shdr) *) (ehdr->e_shoff + (char *)ehdr); + for (j = ehdr->e_shnum; --j >= 0; ++shdr) { + if (key == byteswap32_to_host(shdr->sh_type)) { + return shdr; + } + } + return NULL; +} + +static ElfW(Phdr) *elf_find_phdr_type(uint32_t type, ElfW(Ehdr) *ehdr) +{ + int j; + ElfW(Phdr) *phdr = (ElfW(Phdr) *) (ehdr->e_phoff + (char *)ehdr); + for (j = ehdr->e_phnum; --j >= 0; ++phdr) { + if (type == byteswap32_to_host(phdr->p_type)) { + return phdr; + } + } + return NULL; +} + +/* Returns value if return_val==1, ptr otherwise */ +static void *elf_find_dynamic(int64_t const key, ElfW(Dyn) *dynp, + ElfW(Ehdr) *ehdr, int return_val) +{ + ElfW(Phdr) *pt_text = elf_find_phdr_type(PT_LOAD, ehdr); + unsigned tx_reloc = byteswap_to_host(pt_text->p_vaddr) - byteswap_to_host(pt_text->p_offset); + for (; DT_NULL != byteswap_to_host(dynp->d_tag); ++dynp) { + if (key == byteswap_to_host(dynp->d_tag)) { + if (return_val == 1) + return (void *)byteswap_to_host(dynp->d_un.d_val); + else + return (void *)(byteswap_to_host(dynp->d_un.d_val) - tx_reloc + (char *)ehdr); + } + } + return NULL; +} + +static char *elf_find_rpath(ElfW(Ehdr) *ehdr, ElfW(Dyn) *dynamic) +{ + ElfW(Dyn) *dyns; + + for (dyns = dynamic; byteswap_to_host(dyns->d_tag) != DT_NULL; ++dyns) { + if (DT_RPATH == byteswap_to_host(dyns->d_tag)) { + char *strtab; + strtab = (char *)elf_find_dynamic(DT_STRTAB, dynamic, ehdr, 0); + return ((char *)strtab + byteswap_to_host(dyns->d_un.d_val)); + } + } + return NULL; +} + +static int check_elf_header(ElfW(Ehdr) *const ehdr) +{ + if (!ehdr || *(uint32_t*)ehdr != ELFMAG_U32 + || ehdr->e_ident[EI_CLASS] != ELFCLASSM + || ehdr->e_ident[EI_VERSION] != EV_CURRENT + ) { + return 1; + } + + /* Check if the target endianness matches the host's endianness */ + byteswap = 0; + if (UCLIBC_ENDIAN_HOST == UCLIBC_ENDIAN_LITTLE) { + if (ehdr->e_ident[5] == ELFDATA2MSB) + byteswap = 1; + } else if (UCLIBC_ENDIAN_HOST == UCLIBC_ENDIAN_BIG) { + if (ehdr->e_ident[5] == ELFDATA2LSB) + byteswap = 1; + } + + /* Be very lazy, and only byteswap the stuff we use */ + if (byteswap) { + ehdr->e_type = bswap_16(ehdr->e_type); + ehdr->e_phoff = byteswap_to_host(ehdr->e_phoff); + ehdr->e_shoff = byteswap_to_host(ehdr->e_shoff); + ehdr->e_phnum = bswap_16(ehdr->e_phnum); + ehdr->e_shnum = bswap_16(ehdr->e_shnum); + } + + return 0; +} + +#ifdef __LDSO_CACHE_SUPPORT__ +static caddr_t cache_addr = NULL; +static size_t cache_size = 0; + +static int map_cache(void) +{ + int fd; + struct stat st; + header_t *header; + libentry_t *libent; + int i, strtabsize; + + if (cache_addr == (caddr_t) - 1) + return -1; + else if (cache_addr != NULL) + return 0; + + if (stat(LDSO_CACHE, &st) || (fd = open(LDSO_CACHE, O_RDONLY)) < 0) { + fprintf(stderr, "ldd: can't open cache '%s'\n", LDSO_CACHE); + cache_addr = (caddr_t) - 1; /* so we won't try again */ + return -1; + } + + cache_size = st.st_size; + cache_addr = mmap(0, cache_size, PROT_READ, MAP_SHARED, fd, 0); + close(fd); + if (cache_addr == MAP_FAILED) { + fprintf(stderr, "ldd: can't map cache '%s'\n", LDSO_CACHE); + return -1; + } + + header = (header_t *) cache_addr; + + if (cache_size < sizeof(header_t) + || memcmp(header->magic, LDSO_CACHE_MAGIC, LDSO_CACHE_MAGIC_LEN) + || memcmp(header->version, LDSO_CACHE_VER, LDSO_CACHE_VER_LEN) + || cache_size < (sizeof(header_t) + header->nlibs * sizeof(libentry_t)) + || cache_addr[cache_size - 1] != '\0') + { + fprintf(stderr, "ldd: cache '%s' is corrupt\n", LDSO_CACHE); + goto fail; + } + + strtabsize = cache_size - sizeof(header_t) - header->nlibs * sizeof(libentry_t); + libent = (libentry_t *) & header[1]; + + for (i = 0; i < header->nlibs; i++) { + if (libent[i].sooffset >= strtabsize || libent[i].liboffset >= strtabsize) { + fprintf(stderr, "ldd: cache '%s' is corrupt\n", LDSO_CACHE); + goto fail; + } + } + + return 0; + +fail: + munmap(cache_addr, cache_size); + cache_addr = (caddr_t) - 1; + return -1; +} + +static int unmap_cache(void) +{ + if (cache_addr == NULL || cache_addr == (caddr_t) - 1) + return -1; + +#if 1 + munmap(cache_addr, cache_size); + cache_addr = NULL; +#endif + + return 0; +} +#else +static __inline__ void map_cache(void) +{ +} +static __inline__ void unmap_cache(void) +{ +} +#endif + +/* This function's behavior must exactly match that + * in uClibc/ldso/ldso/dl-elf.c */ +static void search_for_named_library(char *name, char *result, + const char *path_list) +{ + int i, count = 1; + char *path, *path_n; + struct stat filestat; + + /* We need a writable copy of this string */ + path = strdup(path_list); + if (!path) { + fprintf(stderr, "%s: Out of memory!\n", __func__); + exit(EXIT_FAILURE); + } + /* Eliminate all double //s */ + path_n = path; + while ((path_n = strstr(path_n, "//"))) { + i = strlen(path_n); + memmove(path_n, path_n + 1, i - 1); + *(path_n + i - 1) = '\0'; + } + + /* Replace colons with zeros in path_list and count them */ + for (i = strlen(path); i > 0; i--) { + if (path[i] == ':') { + path[i] = 0; + count++; + } + } + path_n = path; + for (i = 0; i < count; i++) { + strcpy(result, path_n); + strcat(result, "/"); + strcat(result, name); + if (stat(result, &filestat) == 0 && filestat.st_mode & S_IRUSR) { + free(path); + return; + } + path_n += (strlen(path_n) + 1); + } + free(path); + *result = '\0'; +} + +static void locate_library_file(ElfW(Ehdr) *ehdr, ElfW(Dyn) *dynamic, + int is_suid, struct library *lib) +{ + char *buf; + char *path; + struct stat filestat; + + /* If this is a fully resolved name, our job is easy */ + if (stat(lib->name, &filestat) == 0) { + lib->path = strdup(lib->name); + return; + } + + /* We need some elbow room here. Make some room... */ + buf = malloc(1024); + if (!buf) { + fprintf(stderr, "%s: Out of memory!\n", __func__); + exit(EXIT_FAILURE); + } + + /* This function must match the behavior of _dl_load_shared_library + * in readelflib1.c or things won't work out as expected... */ + + /* The ABI specifies that RPATH is searched first, so do that now. */ + path = elf_find_rpath(ehdr, dynamic); + if (path) { + search_for_named_library(lib->name, buf, path); + if (*buf != '\0') { + lib->path = buf; + return; + } + } + + /* Next check LD_{ELF_}LIBRARY_PATH if specified and allowed. + * Since this app doesn't actually run an executable I will skip + * the suid check, and just use LD_{ELF_}LIBRARY_PATH if set */ + if (is_suid == 1) + path = NULL; + else + path = getenv("LD_LIBRARY_PATH"); + if (path) { + search_for_named_library(lib->name, buf, path); + if (*buf != '\0') { + lib->path = buf; + return; + } + } +#ifdef __LDSO_CACHE_SUPPORT__ + if (cache_addr != NULL && cache_addr != (caddr_t) - 1) { + int i; + header_t *header = (header_t *) cache_addr; + libentry_t *libent = (libentry_t *) & header[1]; + char *strs = (char *)&libent[header->nlibs]; + + for (i = 0; i < header->nlibs; i++) { + if ((libent[i].flags == LIB_ELF || + libent[i].flags == LIB_ELF_LIBC0 || + libent[i].flags == LIB_ELF_LIBC5) && + strcmp(lib->name, strs + libent[i].sooffset) == 0) + { + lib->path = strdup(strs + libent[i].liboffset); + return; + } + } + } +#endif + + /* Next look for libraries wherever the shared library + * loader was installed -- this is usually where we + * should find things... */ + if (interp_dir) { + search_for_named_library(lib->name, buf, interp_dir); + if (*buf != '\0') { + lib->path = buf; + return; + } + } + + /* Lastly, search the standard list of paths for the library. + This list must exactly match the list in uClibc/ldso/ldso/dl-elf.c */ + path = UCLIBC_RUNTIME_PREFIX "lib:" UCLIBC_RUNTIME_PREFIX "usr/lib" +#ifndef __LDSO_CACHE_SUPPORT__ + ":" UCLIBC_RUNTIME_PREFIX "usr/X11R6/lib" +#endif + ; + search_for_named_library(lib->name, buf, path); + if (*buf != '\0') { + lib->path = buf; + } else { + free(buf); + lib->path = not_found; + } +} + +static int add_library(ElfW(Ehdr) *ehdr, ElfW(Dyn) *dynamic, int is_setuid, char *s) +{ + char *tmp, *tmp1, *tmp2; + struct library *cur, *newlib = lib_list; + + if (!s || !strlen(s)) + return 1; + + tmp = s; + while (*tmp) { + if (*tmp == '/') + s = tmp + 1; + tmp++; + } + + /* We add ldso elsewhere */ + if (interpreter_already_found && (tmp = strrchr(interp_name, '/')) != NULL) { + int len = strlen(interp_dir); + if (strcmp(s, interp_name + 1 + len) == 0) + return 1; + } + + for (cur = lib_list; cur; cur = cur->next) { + /* Check if this library is already in the list */ + tmp1 = tmp2 = cur->name; + while (*tmp1) { + if (*tmp1 == '/') + tmp2 = tmp1 + 1; + tmp1++; + } + if (strcmp(tmp2, s) == 0) { + /*printf("find_elf_interpreter is skipping '%s' (already in list)\n", cur->name); */ + return 0; + } + } + + /* Ok, this lib needs to be added to the list */ + newlib = malloc(sizeof(struct library)); + if (!newlib) + return 1; + newlib->name = malloc(strlen(s) + 1); + strcpy(newlib->name, s); + newlib->resolved = 0; + newlib->path = NULL; + newlib->next = NULL; + + /* Now try and locate where this library might be living... */ + locate_library_file(ehdr, dynamic, is_setuid, newlib); + + /*printf("add_library is adding '%s' to '%s'\n", newlib->name, newlib->path); */ + if (!lib_list) { + lib_list = newlib; + } else { + for (cur = lib_list; cur->next; cur = cur->next) ; /* nothing */ + cur->next = newlib; + } + return 0; +} + +static void find_needed_libraries(ElfW(Ehdr) *ehdr, ElfW(Dyn) *dynamic, int is_setuid) +{ + ElfW(Dyn) *dyns; + + for (dyns = dynamic; byteswap_to_host(dyns->d_tag) != DT_NULL; ++dyns) { + if (DT_NEEDED == byteswap_to_host(dyns->d_tag)) { + char *strtab; + strtab = (char *)elf_find_dynamic(DT_STRTAB, dynamic, ehdr, 0); + add_library(ehdr, dynamic, is_setuid, (char *)strtab + byteswap_to_host(dyns->d_un.d_val)); + } + } +} + +static struct library *find_elf_interpreter(ElfW(Ehdr) *ehdr) +{ + ElfW(Phdr) *phdr; + + if (interpreter_already_found == 1) + return NULL; + phdr = elf_find_phdr_type(PT_INTERP, ehdr); + if (phdr) { + struct library *cur, *newlib = NULL; + char *s = (char *)ehdr + byteswap_to_host(phdr->p_offset); + + char *tmp, *tmp1; + interp_name = strdup(s); + interp_dir = strdup(s); + tmp = strrchr(interp_dir, '/'); + if (*tmp) + *tmp = '\0'; + else { + free(interp_dir); + interp_dir = interp_name; + } + tmp1 = tmp = s; + while (*tmp) { + if (*tmp == '/') + tmp1 = tmp + 1; + tmp++; + } + for (cur = lib_list; cur; cur = cur->next) { + /* Check if this library is already in the list */ + if (strcmp(cur->name, tmp1) == 0) { + /*printf("find_elf_interpreter is replacing '%s' (already in list)\n", cur->name); */ + newlib = cur; + free(newlib->name); + if (newlib->path != not_found) { + free(newlib->path); + } + newlib->name = NULL; + newlib->path = NULL; + break; + } + } + if (newlib == NULL) + newlib = malloc(sizeof(struct library)); + if (!newlib) + return NULL; + newlib->name = malloc(strlen(s) + 1); + strcpy(newlib->name, s); + newlib->path = strdup(newlib->name); + newlib->resolved = 1; + newlib->next = NULL; + +#if 0 + /*printf("find_elf_interpreter is adding '%s' to '%s'\n", newlib->name, newlib->path); */ + if (!lib_list) { + lib_list = newlib; + } else { + for (cur = lib_list; cur->next; cur = cur->next) ; /* nothing */ + cur->next = newlib; + } +#endif + interpreter_already_found = 1; + return newlib; + } + return NULL; +} + +/* map the .so, and locate interesting pieces */ +/* +#warning "There may be two warnings here about vfork() clobbering, ignore them" +*/ +static int find_dependencies(char *filename) +{ + int is_suid = 0; + FILE *thefile; + struct library *interp; + struct stat statbuf; + ElfW(Ehdr) *ehdr = NULL; + ElfW(Shdr) *dynsec = NULL; + ElfW(Dyn) *dynamic = NULL; + + if (filename == not_found) + return 0; + + if (!filename) { + fprintf(stderr, "No filename specified.\n"); + return -1; + } + if (!(thefile = fopen(filename, "r"))) { + perror(filename); + return -1; + } + if (fstat(fileno(thefile), &statbuf) < 0) { + perror(filename); + fclose(thefile); + return -1; + } + + if ((size_t) statbuf.st_size < sizeof(ElfW(Ehdr))) + goto foo; + + if (!S_ISREG(statbuf.st_mode)) + goto foo; + + /* mmap the file to make reading stuff from it effortless */ + ehdr = mmap(0, statbuf.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fileno(thefile), 0); + if (ehdr == MAP_FAILED) { + fclose(thefile); + fprintf(stderr, "mmap(%s) failed: %s\n", filename, strerror(errno)); + return -1; + } + +foo: + fclose(thefile); + + /* Check if this looks like a legit ELF file */ + if (check_elf_header(ehdr)) { + fprintf(stderr, "%s: not an ELF file.\n", filename); + return -1; + } + /* Check if this is the right kind of ELF file */ + if (ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN) { + fprintf(stderr, "%s: not a dynamic executable\n", filename); + return -1; + } + if (ehdr->e_type == ET_EXEC || ehdr->e_type == ET_DYN) { + if (statbuf.st_mode & S_ISUID) + is_suid = 1; + if ((statbuf.st_mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) + is_suid = 1; + /* FIXME */ + if (is_suid) + fprintf(stderr, "%s: is setuid\n", filename); + } + + interpreter_already_found = 0; + interp = find_elf_interpreter(ehdr); + +#ifdef __LDSO_LDD_SUPPORT__ + if (interp + && (ehdr->e_type == ET_EXEC || ehdr->e_type == ET_DYN) + && ehdr->e_ident[EI_CLASS] == ELFCLASSM + && ehdr->e_ident[EI_DATA] == ELFDATAM + && ehdr->e_ident[EI_VERSION] == EV_CURRENT + && MATCH_MACHINE(ehdr->e_machine)) + { + struct stat st; + if (stat(interp->path, &st) == 0 && S_ISREG(st.st_mode)) { + pid_t pid; + int status; + static const char *const environment[] = { + "PATH=/usr/bin:/bin:/usr/sbin:/sbin", + "SHELL=/bin/sh", + "LD_TRACE_LOADED_OBJECTS=1", + NULL + }; + + if ((pid = vfork()) == 0) { + /* Cool, it looks like we should be able to actually + * run this puppy. Do so now... */ + execle(filename, filename, NULL, environment); + _exit(0xdead); + } + + /* Wait till it returns */ + waitpid(pid, &status, 0); + if (WIFEXITED(status) && WEXITSTATUS(status) == 0) { + return 1; + } + + /* If the exec failed, we fall through to trying to find + * all the needed libraries ourselves by rummaging about + * in the ELF headers... */ + } + } +#endif + + dynsec = elf_find_section_type(SHT_DYNAMIC, ehdr); + if (dynsec) { + dynamic = (ElfW(Dyn) *) (byteswap_to_host(dynsec->sh_offset) + (char *)ehdr); + find_needed_libraries(ehdr, dynamic, is_suid); + } + + return 0; +} + +int main(int argc, char **argv) +{ + int multi = 0; + int got_em_all = 1; + char *filename = NULL; + struct library *cur; + + if (argc < 2) { + fprintf(stderr, "ldd: missing file arguments\n" + "Try `ldd --help' for more information.\n"); + exit(EXIT_FAILURE); + } + if (argc > 2) + multi++; + + while (--argc > 0) { + ++argv; + + if (strcmp(*argv, "--") == 0) { + /* Ignore "--" */ + continue; + } + + if (strcmp(*argv, "--help") == 0 || strcmp(*argv, "-h") == 0) { + fprintf(stderr, "Usage: ldd [OPTION]... FILE...\n" + "\t--help\t\tprint this help and exit\n"); + exit(EXIT_SUCCESS); + } + + filename = *argv; + if (!filename) { + fprintf(stderr, "No filename specified.\n"); + exit(EXIT_FAILURE); + } + + if (multi) { + printf("%s:\n", *argv); + } + + map_cache(); + + if (find_dependencies(filename) != 0) + continue; + + while (got_em_all) { + got_em_all = 0; + /* Keep walking the list till everybody is resolved */ + for (cur = lib_list; cur; cur = cur->next) { + if (cur->resolved == 0 && cur->path) { + got_em_all = 1; + printf("checking sub-depends for '%s'\n", cur->path); + find_dependencies(cur->path); + cur->resolved = 1; + } + } + } + + unmap_cache(); + + /* Print the list */ + got_em_all = 0; + for (cur = lib_list; cur; cur = cur->next) { + got_em_all = 1; + printf("\t%s => %s (0x00000000)\n", cur->name, cur->path); + } + if (interp_name && interpreter_already_found == 1) + printf("\t%s => %s (0x00000000)\n", interp_name, interp_name); + else + printf("\tnot a dynamic executable\n"); + + for (cur = lib_list; cur; cur = cur->next) { + free(cur->name); + cur->name = NULL; + if (cur->path && cur->path != not_found) { + free(cur->path); + cur->path = NULL; + } + } + lib_list = NULL; + } + + return 0; +} diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/utils/mmap-windows.c b/l4/pkg/uclibc/lib/contrib/uclibc/utils/mmap-windows.c new file mode 100644 index 00000000..1799392f --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/utils/mmap-windows.c @@ -0,0 +1,100 @@ +/* mmap() replacement for Windows + * + * Author: Mike Frysinger + * Placed into the public domain + */ + +/* References: + * CreateFileMapping: http://msdn.microsoft.com/en-us/library/aa366537(VS.85).aspx + * CloseHandle: http://msdn.microsoft.com/en-us/library/ms724211(VS.85).aspx + * MapViewOfFile: http://msdn.microsoft.com/en-us/library/aa366761(VS.85).aspx + * UnmapViewOfFile: http://msdn.microsoft.com/en-us/library/aa366882(VS.85).aspx + */ + +#include +#include +#include + +#define PROT_READ 0x1 +#define PROT_WRITE 0x2 +/* This flag is only available in WinXP+ */ +#ifdef FILE_MAP_EXECUTE +#define PROT_EXEC 0x4 +#else +#define PROT_EXEC 0x0 +#define FILE_MAP_EXECUTE 0 +#endif + +#define MAP_SHARED 0x01 +#define MAP_PRIVATE 0x02 +#define MAP_ANONYMOUS 0x20 +#define MAP_ANON MAP_ANONYMOUS +#define MAP_FAILED ((void *) -1) + +#ifdef __USE_FILE_OFFSET64 +# define DWORD_HI(x) (x >> 32) +# define DWORD_LO(x) ((x) & 0xffffffff) +#else +# define DWORD_HI(x) (0) +# define DWORD_LO(x) (x) +#endif + +static void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset) +{ + if (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC)) + return MAP_FAILED; + if (fd == -1) { + if (!(flags & MAP_ANON) || offset) + return MAP_FAILED; + } else if (flags & MAP_ANON) + return MAP_FAILED; + + DWORD flProtect; + if (prot & PROT_WRITE) { + if (prot & PROT_EXEC) + flProtect = PAGE_EXECUTE_READWRITE; + else + flProtect = PAGE_READWRITE; + } else if (prot & PROT_EXEC) { + if (prot & PROT_READ) + flProtect = PAGE_EXECUTE_READ; + else if (prot & PROT_EXEC) + flProtect = PAGE_EXECUTE; + } else + flProtect = PAGE_READONLY; + + off_t end = length + offset; + HANDLE mmap_fd, h; + if (fd == -1) + mmap_fd = INVALID_HANDLE_VALUE; + else + mmap_fd = (HANDLE)_get_osfhandle(fd); + h = CreateFileMapping(mmap_fd, NULL, flProtect, DWORD_HI(end), DWORD_LO(end), NULL); + if (h == NULL) + return MAP_FAILED; + + DWORD dwDesiredAccess; + if (prot & PROT_WRITE) + dwDesiredAccess = FILE_MAP_WRITE; + else + dwDesiredAccess = FILE_MAP_READ; + if (prot & PROT_EXEC) + dwDesiredAccess |= FILE_MAP_EXECUTE; + if (flags & MAP_PRIVATE) + dwDesiredAccess |= FILE_MAP_COPY; + void *ret = MapViewOfFile(h, dwDesiredAccess, DWORD_HI(offset), DWORD_LO(offset), length); + if (ret == NULL) { + CloseHandle(h); + ret = MAP_FAILED; + } + return ret; +} + +static void munmap(void *addr, size_t length) +{ + UnmapViewOfFile(addr); + /* ruh-ro, we leaked handle from CreateFileMapping() ... */ +} + +#undef DWORD_HI +#undef DWORD_LO diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/utils/porting.h b/l4/pkg/uclibc/lib/contrib/uclibc/utils/porting.h new file mode 100644 index 00000000..d4ead17d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/utils/porting.h @@ -0,0 +1,83 @@ +/* Misc system-specific crap */ + +#ifndef _PORTING_H_ +#define _PORTING_H_ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __LDSO_LDD_SUPPORT__ +# include +#endif + +#if defined(_WIN32) || defined(_WINNT) +# include "mmap-windows.c" +#else +# include +#endif + +#ifdef BUILDING_LINKAGE +#include +/* makefile will include elf.h for us */ + +#include "bswap.h" +#include "dl-defs.h" +#endif + +#ifdef DMALLOC +#include +#endif + +/* For SunOS */ +#ifndef PATH_MAX +#define PATH_MAX _POSIX_PATH_MAX +#endif + +#ifndef UCLIBC_RUNTIME_PREFIX +# define UCLIBC_RUNTIME_PREFIX "/" +#endif + +#undef UCLIBC_ENDIAN_HOST +#define UCLIBC_ENDIAN_LITTLE 1234 +#define UCLIBC_ENDIAN_BIG 4321 +#if defined(BYTE_ORDER) +# if BYTE_ORDER == LITTLE_ENDIAN +# define UCLIBC_ENDIAN_HOST UCLIBC_ENDIAN_LITTLE +# elif BYTE_ORDER == BIG_ENDIAN +# define UCLIBC_ENDIAN_HOST UCLIBC_ENDIAN_BIG +# endif +#elif defined(__BYTE_ORDER) +# if __BYTE_ORDER == __LITTLE_ENDIAN +# define UCLIBC_ENDIAN_HOST UCLIBC_ENDIAN_LITTLE +# elif __BYTE_ORDER == __BIG_ENDIAN +# define UCLIBC_ENDIAN_HOST UCLIBC_ENDIAN_BIG +# endif +#endif +#if !defined(UCLIBC_ENDIAN_HOST) +# error "Unknown host byte order!" +#endif + +#if defined __GNUC__ || defined __ICC +# define attribute_noreturn __attribute__ ((__noreturn__)) +#else +# define attribute_noreturn +#endif + +#endif diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/utils/readsoname2.c b/l4/pkg/uclibc/lib/contrib/uclibc/utils/readsoname2.c new file mode 100644 index 00000000..5cda3318 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/utils/readsoname2.c @@ -0,0 +1,141 @@ +static char *readsonameXX(char *name, FILE *infile, int expected_type, int *type) +{ + ElfW(Ehdr) *epnt; + ElfW(Phdr) *ppnt; + unsigned int i, j; + char *header; + ElfW(Addr) dynamic_addr = 0; + ElfW(Addr) dynamic_size = 0; + unsigned long page_size = getpagesize(); + ElfW(Addr) strtab_val = 0; + ElfW(Addr) needed_val; + ElfW(Addr) loadaddr = -1; + ElfW(Dyn) *dpnt; + struct stat st; + char *needed; + char *soname = NULL; + int multi_libcs = 0; + + if (expected_type == LIB_DLL) { + warn("%s does not match type specified for directory!", name); + expected_type = LIB_ANY; + } + + *type = LIB_ELF; + + if (fstat(fileno(infile), &st)) + return NULL; + header = + mmap(0, st.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, + fileno(infile), 0); + if (header == (caddr_t) - 1) + return NULL; + + epnt = (ElfW(Ehdr) *) header; + if ((char *)(epnt + 1) > (char *)(header + st.st_size)) + goto skip; + + if (UCLIBC_ENDIAN_HOST == UCLIBC_ENDIAN_LITTLE) + byteswap = (epnt->e_ident[5] == ELFDATA2MSB) ? 1 : 0; + else if (UCLIBC_ENDIAN_HOST == UCLIBC_ENDIAN_BIG) + byteswap = (epnt->e_ident[5] == ELFDATA2LSB) ? 1 : 0; + + /* Be very lazy, and only byteswap the stuff we use */ + if (byteswap == 1) { + epnt->e_phoff = bswap_32(epnt->e_phoff); + epnt->e_phnum = bswap_16(epnt->e_phnum); + } + + ppnt = (ElfW(Phdr) *) & header[epnt->e_phoff]; + if ((char *)ppnt < (char *)header || + (char *)(ppnt + epnt->e_phnum) > (char *)(header + st.st_size)) + goto skip; + + for (i = 0; i < epnt->e_phnum; i++) { + /* Be very lazy, and only byteswap the stuff we use */ + if (byteswap == 1) { + ppnt->p_type = bswap_32(ppnt->p_type); + ppnt->p_vaddr = bswap_32(ppnt->p_vaddr); + ppnt->p_offset = bswap_32(ppnt->p_offset); + ppnt->p_filesz = bswap_32(ppnt->p_filesz); + } + + if (loadaddr == (ElfW(Addr)) - 1 && ppnt->p_type == PT_LOAD) + loadaddr = (ppnt->p_vaddr & ~(page_size - 1)) - + (ppnt->p_offset & ~(page_size - 1)); + if (ppnt->p_type == 2) { + dynamic_addr = ppnt->p_offset; + dynamic_size = ppnt->p_filesz; + }; + ppnt++; + }; + + dpnt = (ElfW(Dyn) *) & header[dynamic_addr]; + dynamic_size = dynamic_size / sizeof(ElfW(Dyn)); + if ((char *)dpnt < (char *)header || + (char *)(dpnt + dynamic_size) > (char *)(header + st.st_size)) + goto skip; + + if (byteswap == 1) { + dpnt->d_tag = bswap_32(dpnt->d_tag); + dpnt->d_un.d_val = bswap_32(dpnt->d_un.d_val); + } + + while (dpnt->d_tag != DT_NULL) { + if (dpnt->d_tag == DT_STRTAB) + strtab_val = dpnt->d_un.d_val; + dpnt++; + if (byteswap == 1) { + dpnt->d_tag = bswap_32(dpnt->d_tag); + dpnt->d_un.d_val = bswap_32(dpnt->d_un.d_val); + } + }; + + if (!strtab_val) + goto skip; + + dpnt = (ElfW(Dyn) *) & header[dynamic_addr]; + while (dpnt->d_tag != DT_NULL) { + if (dpnt->d_tag == DT_SONAME || dpnt->d_tag == DT_NEEDED) { + needed_val = dpnt->d_un.d_val; + if (needed_val + strtab_val >= loadaddr || + needed_val + strtab_val < st.st_size - loadaddr) { + needed = + (char *)(header - loadaddr + strtab_val + + needed_val); + + if (dpnt->d_tag == DT_SONAME) + soname = xstrdup(needed); + + for (j = 0; needed_tab[j].soname != NULL; j++) { + if (strcmp(needed, needed_tab[j].soname) + == 0) { + if (*type != LIB_ELF + && *type != + needed_tab[j].type) + multi_libcs = 1; + *type = needed_tab[j].type; + } + } + } + } + dpnt++; + }; + + if (multi_libcs) + warn("%s appears to be for multiple libc's", name); + + /* If we could not deduce the libc type, and we know what to expect, set the type */ + if (*type == LIB_ELF && expected_type != LIB_ANY) + *type = expected_type; + + if (expected_type != LIB_ANY && expected_type != LIB_ELF && + expected_type != *type) { + warn("%s does not match type specified for directory!", name); + } + + skip: + munmap(header, st.st_size); + + return soname; +} diff --git a/l4/pkg/uclibc/lib/libpthread/Makefile b/l4/pkg/uclibc/lib/libpthread/Makefile new file mode 100644 index 00000000..82db97d0 --- /dev/null +++ b/l4/pkg/uclibc/lib/libpthread/Makefile @@ -0,0 +1,8 @@ +PKGDIR = ../.. +L4DIR ?= $(PKGDIR)/../.. + +TARGET = include src + +include $(L4DIR)/mk/subdir.mk + +src: include diff --git a/l4/pkg/uclibc/lib/libpthread/include/Makefile b/l4/pkg/uclibc/lib/libpthread/include/Makefile new file mode 100644 index 00000000..d6498cae --- /dev/null +++ b/l4/pkg/uclibc/lib/libpthread/include/Makefile @@ -0,0 +1,7 @@ +PKGDIR = ../../.. +L4DIR ?= $(PKGDIR)/../.. + +INSTALL_INC_PREFIX := uclibc + +include $(L4DIR)/mk/include.mk + diff --git a/l4/pkg/uclibc/lib/libpthread/include/bits/initspin.h b/l4/pkg/uclibc/lib/libpthread/include/bits/initspin.h new file mode 100644 index 00000000..a19ec077 --- /dev/null +++ b/l4/pkg/uclibc/lib/libpthread/include/bits/initspin.h @@ -0,0 +1,28 @@ +/* Generic definitions for spinlock initializers. + Copyright (C) 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* Initial value of a spinlock. Most platforms should use zero, + unless they only implement a "test and clear" operation instead of + the usual "test and set". */ +#define __LT_SPINLOCK_INIT 0 + +/* Macros for lock initializers, using the above definition. */ +#define __LOCK_INITIALIZER { 0, __LT_SPINLOCK_INIT } +#define __ALT_LOCK_INITIALIZER { 0, __LT_SPINLOCK_INIT } +#define __ATOMIC_INITIALIZER { 0, __LT_SPINLOCK_INIT } diff --git a/l4/pkg/uclibc/lib/libpthread/include/bits/libc-lock.h b/l4/pkg/uclibc/lib/libpthread/include/bits/libc-lock.h new file mode 100644 index 00000000..e5c0df64 --- /dev/null +++ b/l4/pkg/uclibc/lib/libpthread/include/bits/libc-lock.h @@ -0,0 +1,419 @@ +/* libc-internal interface for mutex locks. LinuxThreads version. + Copyright (C) 1996,1997,1998,1999,2000,2001,2002,2003,2006 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _BITS_LIBC_LOCK_H +#define _BITS_LIBC_LOCK_H 1 + +#include + +#ifdef NOT_FOR_L4 +#if defined _LIBC && !defined NOT_IN_libc +#include +#endif +#endif + +/* Mutex type. */ +#if defined(_LIBC) || defined(_IO_MTSAFE_IO) +typedef pthread_mutex_t __libc_lock_t; +typedef struct { pthread_mutex_t mutex; } __libc_lock_recursive_t; +# ifdef __USE_UNIX98 +typedef pthread_rwlock_t __libc_rwlock_t; +# else +typedef struct __libc_rwlock_opaque__ __libc_rwlock_t; +# endif +typedef __libc_lock_recursive_t __rtld_lock_recursive_t; +#else +typedef struct __libc_lock_opaque__ __libc_lock_t; +typedef struct __libc_lock_recursive_opaque__ __libc_lock_recursive_t; +typedef struct __libc_rwlock_opaque__ __libc_rwlock_t; +#endif + +/* Type for key to thread-specific data. */ +typedef pthread_key_t __libc_key_t; + +/* Define a lock variable NAME with storage class CLASS. The lock must be + initialized with __libc_lock_init before it can be used (or define it + with __libc_lock_define_initialized, below). Use `extern' for CLASS to + declare a lock defined in another module. In public structure + definitions you must use a pointer to the lock structure (i.e., NAME + begins with a `*'), because its storage size will not be known outside + of libc. */ +#define __libc_lock_define(CLASS,NAME) \ + CLASS __libc_lock_t NAME; +#define __libc_rwlock_define(CLASS,NAME) \ + CLASS __libc_rwlock_t NAME; +#define __libc_lock_define_recursive(CLASS,NAME) \ + CLASS __libc_lock_recursive_t NAME; +#define __rtld_lock_define_recursive(CLASS,NAME) \ + CLASS __rtld_lock_recursive_t NAME; + +/* Define an initialized lock variable NAME with storage class CLASS. + + For the C library we take a deeper look at the initializer. For + this implementation all fields are initialized to zero. Therefore + we don't initialize the variable which allows putting it into the + BSS section. (Except on PA-RISC and other odd architectures, where + initialized locks must be set to one due to the lack of normal + atomic operations.) */ + +#if __LT_SPINLOCK_INIT == 0 +# define __libc_lock_define_initialized(CLASS,NAME) \ + CLASS __libc_lock_t NAME; +#else +# define __libc_lock_define_initialized(CLASS,NAME) \ + CLASS __libc_lock_t NAME = PTHREAD_MUTEX_INITIALIZER; +#endif + +#define __libc_rwlock_define_initialized(CLASS,NAME) \ + CLASS __libc_rwlock_t NAME = PTHREAD_RWLOCK_INITIALIZER; + +/* Define an initialized recursive lock variable NAME with storage + class CLASS. */ +#define __libc_lock_define_initialized_recursive(CLASS,NAME) \ + CLASS __libc_lock_recursive_t NAME = _LIBC_LOCK_RECURSIVE_INITIALIZER; +#define _LIBC_LOCK_RECURSIVE_INITIALIZER \ + {PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP} + +#define __rtld_lock_define_initialized_recursive(CLASS,NAME) \ + CLASS __rtld_lock_recursive_t NAME = _RTLD_LOCK_RECURSIVE_INITIALIZER; +#define _RTLD_LOCK_RECURSIVE_INITIALIZER \ + {PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP} + +#if defined _LIBC && defined IS_IN_libpthread +# define __libc_maybe_call(FUNC, ARGS, ELSE) FUNC ARGS +#else +# if defined __PIC__ || (defined _LIBC && defined SHARED) +# define __libc_maybe_call(FUNC, ARGS, ELSE) \ + (__extension__ ({ __typeof (FUNC) *_fn = (FUNC); \ + _fn != NULL ? (*_fn) ARGS : ELSE; })) +# else +# define __libc_maybe_call(FUNC, ARGS, ELSE) \ + (FUNC != NULL ? FUNC ARGS : ELSE) +# endif +#endif +#if defined _LIBC && !defined NOT_IN_libc && defined SHARED +# define __libc_maybe_call2(FUNC, ARGS, ELSE) \ + ({__builtin_expect (__libc_pthread_functions.ptr_##FUNC != NULL, 0) \ + ? __libc_pthread_functions.ptr_##FUNC ARGS : ELSE; }) +#else +# define __libc_maybe_call2(FUNC, ARGS, ELSE) __libc_maybe_call (__##FUNC, ARGS, ELSE) +#endif + +/* Initialize the named lock variable, leaving it in a consistent, unlocked + state. */ +#if defined _LIBC && !defined NOT_IN_libc && defined SHARED +#define __libc_lock_init(NAME) \ + ({ \ + (NAME).__m_count = 0; \ + (NAME).__m_owner = NULL; \ + (NAME).__m_kind = PTHREAD_MUTEX_TIMED_NP; \ + (NAME).__m_lock.__status = 0; \ + (NAME).__m_lock.__spinlock = __LT_SPINLOCK_INIT; \ + 0; }) +#else +#define __libc_lock_init(NAME) \ + (__libc_maybe_call2 (pthread_mutex_init, (&(NAME), NULL), 0)) +#endif +#define __libc_rwlock_init(NAME) \ + (__libc_maybe_call (__pthread_rwlock_init, (&(NAME), NULL), 0)); + +/* Same as last but this time we initialize a recursive mutex. */ +#if defined _LIBC && !defined NOT_IN_libc && defined SHARED +#define __libc_lock_init_recursive(NAME) \ + ({ \ + (NAME).mutex.__m_count = 0; \ + (NAME).mutex.__m_owner = NULL; \ + (NAME).mutex.__m_kind = PTHREAD_MUTEX_RECURSIVE_NP; \ + (NAME).mutex.__m_lock.__status = 0; \ + (NAME).mutex.__m_lock.__spinlock = __LT_SPINLOCK_INIT; \ + 0; }) +#else +#define __libc_lock_init_recursive(NAME) \ + do { \ + if (__pthread_mutex_init != NULL) \ + { \ + pthread_mutexattr_t __attr; \ + __pthread_mutexattr_init (&__attr); \ + __pthread_mutexattr_settype (&__attr, PTHREAD_MUTEX_RECURSIVE_NP); \ + __pthread_mutex_init (&(NAME).mutex, &__attr); \ + __pthread_mutexattr_destroy (&__attr); \ + } \ + } while (0); +#endif +#define __rtld_lock_init_recursive(NAME) \ + __libc_lock_init_recursive (NAME) + +/* Finalize the named lock variable, which must be locked. It cannot be + used again until __libc_lock_init is called again on it. This must be + called on a lock variable before the containing storage is reused. */ +#define __libc_lock_fini(NAME) \ + (__libc_maybe_call2 (pthread_mutex_destroy, (&(NAME)), 0)); +#define __libc_rwlock_fini(NAME) \ + (__libc_maybe_call (__pthread_rwlock_destroy, (&(NAME)), 0)); + +/* Finalize recursive named lock. */ +#define __libc_lock_fini_recursive(NAME) __libc_lock_fini ((NAME).mutex) +#define __rtld_lock_fini_recursive(NAME) __libc_lock_fini_recursive (NAME) + +/* Lock the named lock variable. */ +#define __libc_lock_lock(NAME) \ + (__libc_maybe_call2 (pthread_mutex_lock, (&(NAME)), 0)); +#define __libc_rwlock_rdlock(NAME) \ + (__libc_maybe_call (__pthread_rwlock_rdlock, (&(NAME)), 0)); +#define __libc_rwlock_wrlock(NAME) \ + (__libc_maybe_call (__pthread_rwlock_wrlock, (&(NAME)), 0)); + +/* Lock the recursive named lock variable. */ +#define __libc_lock_lock_recursive(NAME) __libc_lock_lock ((NAME).mutex) + +/* Try to lock the named lock variable. */ +#define __libc_lock_trylock(NAME) \ + (__libc_maybe_call2 (pthread_mutex_trylock, (&(NAME)), 0)) +#define __libc_rwlock_tryrdlock(NAME) \ + (__libc_maybe_call (__pthread_rwlock_tryrdlock, (&(NAME)), 0)) +#define __libc_rwlock_trywrlock(NAME) \ + (__libc_maybe_call (__pthread_rwlock_trywrlock, (&(NAME)), 0)) + +/* Try to lock the recursive named lock variable. */ +#define __libc_lock_trylock_recursive(NAME) __libc_lock_trylock ((NAME).mutex) +#define __rtld_lock_trylock_recursive(NAME) \ + __libc_lock_trylock_recursive (NAME) + +/* Unlock the named lock variable. */ +#define __libc_lock_unlock(NAME) \ + (__libc_maybe_call2 (pthread_mutex_unlock, (&(NAME)), 0)); +#define __libc_rwlock_unlock(NAME) \ + (__libc_maybe_call (__pthread_rwlock_unlock, (&(NAME)), 0)); + +/* Unlock the recursive named lock variable. */ +#define __libc_lock_unlock_recursive(NAME) __libc_lock_unlock ((NAME).mutex) + +#if defined _LIBC && defined SHARED +# define __rtld_lock_default_lock_recursive(lock) \ + ++((pthread_mutex_t *)(lock))->__m_count; + +# define __rtld_lock_default_unlock_recursive(lock) \ + --((pthread_mutex_t *)(lock))->__m_count; + +# define __rtld_lock_lock_recursive(NAME) \ + GL(dl_rtld_lock_recursive) (&(NAME).mutex) + +# define __rtld_lock_unlock_recursive(NAME) \ + GL(dl_rtld_unlock_recursive) (&(NAME).mutex) +#else +#define __rtld_lock_lock_recursive(NAME) __libc_lock_lock_recursive (NAME) +#define __rtld_lock_unlock_recursive(NAME) __libc_lock_unlock_recursive (NAME) +#endif + +/* Define once control variable. */ +#if PTHREAD_ONCE_INIT == 0 +/* Special case for static variables where we can avoid the initialization + if it is zero. */ +# define __libc_once_define(CLASS, NAME) \ + CLASS pthread_once_t NAME +#else +# define __libc_once_define(CLASS, NAME) \ + CLASS pthread_once_t NAME = PTHREAD_ONCE_INIT +#endif + +/* Call handler iff the first call. */ +#define __libc_once(ONCE_CONTROL, INIT_FUNCTION) \ + do { \ + if (__pthread_once != NULL) \ + __pthread_once (&(ONCE_CONTROL), (INIT_FUNCTION)); \ + else if ((ONCE_CONTROL) == PTHREAD_ONCE_INIT) { \ + INIT_FUNCTION (); \ + (ONCE_CONTROL) = 2; \ + } \ + } while (0) + + +/* Start critical region with cleanup. */ +#define __libc_cleanup_region_start(DOIT, FCT, ARG) \ + { struct _pthread_cleanup_buffer _buffer; \ + int _avail = (DOIT) && _pthread_cleanup_push_defer != NULL; \ + if (_avail) { \ + _pthread_cleanup_push_defer (&_buffer, (FCT), (ARG)); \ + } + +/* End critical region with cleanup. */ +#define __libc_cleanup_region_end(DOIT) \ + if (_avail) { \ + _pthread_cleanup_pop_restore (&_buffer, (DOIT)); \ + } \ + } + +/* Sometimes we have to exit the block in the middle. */ +#define __libc_cleanup_end(DOIT) \ + if (_avail) { \ + _pthread_cleanup_pop_restore (&_buffer, (DOIT)); \ + } + +#define __libc_cleanup_push(fct, arg) \ + { struct _pthread_cleanup_buffer _buffer; \ + __libc_maybe_call (_pthread_cleanup_push, (&_buffer, (fct), (arg)), 0) + +#define __libc_cleanup_pop(execute) \ + __libc_maybe_call (_pthread_cleanup_pop, (&_buffer, execute), 0); \ + } + +/* Create thread-specific key. */ +#define __libc_key_create(KEY, DESTRUCTOR) \ + (__libc_maybe_call (__pthread_key_create, (KEY, DESTRUCTOR), 1)) + +/* Get thread-specific data. */ +#define __libc_getspecific(KEY) \ + (__libc_maybe_call (__pthread_getspecific, (KEY), NULL)) + +/* Set thread-specific data. */ +#define __libc_setspecific(KEY, VALUE) \ + (__libc_maybe_call (__pthread_setspecific, (KEY, VALUE), 0)) + + +/* Register handlers to execute before and after `fork'. */ +#define __libc_atfork(PREPARE, PARENT, CHILD) \ + (__libc_maybe_call (__pthread_atfork, (PREPARE, PARENT, CHILD), 0)) + +/* Functions that are used by this file and are internal to the GNU C + library. */ + +// Aw11: made things c++ compatible +__BEGIN_DECLS +// Aw11: end + +extern int __pthread_mutex_init (pthread_mutex_t *__mutex, + __const pthread_mutexattr_t *__mutex_attr); + +extern int __pthread_mutex_destroy (pthread_mutex_t *__mutex); + +extern int __pthread_mutex_trylock (pthread_mutex_t *__mutex); + +extern int __pthread_mutex_lock (pthread_mutex_t *__mutex); + +extern int __pthread_mutex_unlock (pthread_mutex_t *__mutex); + +extern int __pthread_mutexattr_init (pthread_mutexattr_t *__attr); + +extern int __pthread_mutexattr_destroy (pthread_mutexattr_t *__attr); + +extern int __pthread_mutexattr_settype (pthread_mutexattr_t *__attr, + int __kind); + +#ifdef __USE_UNIX98 +extern int __pthread_rwlock_init (pthread_rwlock_t *__rwlock, + __const pthread_rwlockattr_t *__attr); + +extern int __pthread_rwlock_destroy (pthread_rwlock_t *__rwlock); + +extern int __pthread_rwlock_rdlock (pthread_rwlock_t *__rwlock); + +extern int __pthread_rwlock_tryrdlock (pthread_rwlock_t *__rwlock); + +extern int __pthread_rwlock_wrlock (pthread_rwlock_t *__rwlock); + +extern int __pthread_rwlock_trywrlock (pthread_rwlock_t *__rwlock); + +extern int __pthread_rwlock_unlock (pthread_rwlock_t *__rwlock); +#endif + +extern int __pthread_key_create (pthread_key_t *__key, + void (*__destr_function) (void *)); + +extern int __pthread_setspecific (pthread_key_t __key, + __const void *__pointer); + +extern void *__pthread_getspecific (pthread_key_t __key); + +extern int __pthread_once (pthread_once_t *__once_control, + void (*__init_routine) (void)); + +extern int __pthread_atfork (void (*__prepare) (void), + void (*__parent) (void), + void (*__child) (void)); + + + +/* Make the pthread functions weak so that we can elide them from + single-threaded processes. */ +#ifndef __NO_WEAK_PTHREAD_ALIASES +# ifdef weak_extern +# define BP_SYM(sym) sym +weak_extern (BP_SYM (__pthread_mutex_init)) +weak_extern (BP_SYM (__pthread_mutex_destroy)) +weak_extern (BP_SYM (__pthread_mutex_lock)) +weak_extern (BP_SYM (__pthread_mutex_trylock)) +weak_extern (BP_SYM (__pthread_mutex_unlock)) +weak_extern (BP_SYM (__pthread_mutexattr_init)) +weak_extern (BP_SYM (__pthread_mutexattr_destroy)) +weak_extern (BP_SYM (__pthread_mutexattr_settype)) +weak_extern (BP_SYM (__pthread_rwlock_init)) +weak_extern (BP_SYM (__pthread_rwlock_destroy)) +weak_extern (BP_SYM (__pthread_rwlock_rdlock)) +weak_extern (BP_SYM (__pthread_rwlock_tryrdlock)) +weak_extern (BP_SYM (__pthread_rwlock_wrlock)) +weak_extern (BP_SYM (__pthread_rwlock_trywrlock)) +weak_extern (BP_SYM (__pthread_rwlock_unlock)) +weak_extern (BP_SYM (__pthread_key_create)) +weak_extern (BP_SYM (__pthread_setspecific)) +weak_extern (BP_SYM (__pthread_getspecific)) +weak_extern (BP_SYM (__pthread_once)) +weak_extern (__pthread_initialize) +weak_extern (__pthread_atfork) +weak_extern (BP_SYM (_pthread_cleanup_push)) +weak_extern (BP_SYM (_pthread_cleanup_pop)) +weak_extern (BP_SYM (_pthread_cleanup_push_defer)) +weak_extern (BP_SYM (_pthread_cleanup_pop_restore)) +# else +# pragma weak __pthread_mutex_init +# pragma weak __pthread_mutex_destroy +# pragma weak __pthread_mutex_lock +# pragma weak __pthread_mutex_trylock +# pragma weak __pthread_mutex_unlock +# pragma weak __pthread_mutexattr_init +# pragma weak __pthread_mutexattr_destroy +# pragma weak __pthread_mutexattr_settype +# pragma weak __pthread_rwlock_destroy +# pragma weak __pthread_rwlock_rdlock +# pragma weak __pthread_rwlock_tryrdlock +# pragma weak __pthread_rwlock_wrlock +# pragma weak __pthread_rwlock_trywrlock +# pragma weak __pthread_rwlock_unlock +# pragma weak __pthread_key_create +# pragma weak __pthread_setspecific +# pragma weak __pthread_getspecific +# pragma weak __pthread_once +# pragma weak __pthread_initialize +# pragma weak __pthread_atfork +# pragma weak _pthread_cleanup_push_defer +# pragma weak _pthread_cleanup_pop_restore +# pragma weak _pthread_cleanup_push +# pragma weak _pthread_cleanup_pop +# endif +#endif + +// Aw11: made things c++ compatible +__END_DECLS +// Aw11: end + +/* We need portable names for some functions. E.g., when they are + used as argument to __libc_cleanup_region_start. */ +#define __libc_mutex_unlock __pthread_mutex_unlock + +#endif /* bits/libc-lock.h */ diff --git a/l4/pkg/uclibc/lib/libpthread/include/bits/pthreadtypes.h b/l4/pkg/uclibc/lib/libpthread/include/bits/pthreadtypes.h new file mode 100644 index 00000000..504c0b19 --- /dev/null +++ b/l4/pkg/uclibc/lib/libpthread/include/bits/pthreadtypes.h @@ -0,0 +1,148 @@ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +/* 2008 Alexander Warg --- L4 adaption */ + +#pragma once + +#include +#include + +#define __need_schedparam +#include + +/* Fast locks (not abstract because mutexes and conditions aren't abstract). */ +struct _pthread_fastlock +{ + long int __status; /* "Free" or "taken" or head of waiting list */ + int __spinlock; /* Used by compare_and_swap emulation. Also, + adaptive SMP lock stores spin count here. */ +}; + +#ifndef _PTHREAD_DESCR_DEFINED +/* Thread descriptors */ +typedef struct _pthread_descr_struct *_pthread_descr; +# define _PTHREAD_DESCR_DEFINED +#endif + + +/* Attributes for threads. */ +typedef struct __pthread_attr_s +{ + int __detachstate; + int __schedpolicy; + struct __sched_param __schedparam; + int __inheritsched; + int __scope; + size_t __guardsize; + int __stackaddr_set; + void *__stackaddr; + size_t __stacksize; +} pthread_attr_t; + + +/* Conditions (not abstract because of PTHREAD_COND_INITIALIZER */ + +#ifdef __GLIBC_HAVE_LONG_LONG +__extension__ typedef long long __pthread_cond_align_t; +#else +typedef long __pthread_cond_align_t; +#endif + +typedef struct +{ + struct _pthread_fastlock __c_lock; /* Protect against concurrent access */ + _pthread_descr __c_waiting; /* Threads waiting on this condition */ + char __padding[48 - sizeof (struct _pthread_fastlock) + - sizeof (_pthread_descr) - sizeof (__pthread_cond_align_t)]; + __pthread_cond_align_t __align; +} pthread_cond_t; + + +/* Attribute for conditionally variables. */ +typedef struct +{ + int __dummy; +} pthread_condattr_t; + +/* Keys for thread-specific data */ +typedef unsigned int pthread_key_t; + + +/* Mutexes (not abstract because of PTHREAD_MUTEX_INITIALIZER). */ +/* (The layout is unnatural to maintain binary compatibility + with earlier releases of LinuxThreads.) */ +typedef struct +{ + int __m_reserved; /* Reserved for future use */ + int __m_count; /* Depth of recursive locking */ + _pthread_descr __m_owner; /* Owner thread (if recursive or errcheck) */ + int __m_kind; /* Mutex kind: fast, recursive or errcheck */ + struct _pthread_fastlock __m_lock; /* Underlying fast lock */ +} pthread_mutex_t; + + +/* Attribute for mutex. */ +typedef struct +{ + int __mutexkind; +} pthread_mutexattr_t; + + +/* Once-only execution */ +typedef int pthread_once_t; + + +#if defined __USE_UNIX98 || defined __USE_XOPEN2K +/* Read-write locks. */ +typedef struct _pthread_rwlock_t +{ + struct _pthread_fastlock __rw_lock; /* Lock to guarantee mutual exclusion */ + int __rw_readers; /* Number of readers */ + _pthread_descr __rw_writer; /* Identity of writer, or NULL if none */ + _pthread_descr __rw_read_waiting; /* Threads waiting for reading */ + _pthread_descr __rw_write_waiting; /* Threads waiting for writing */ + int __rw_kind; /* Reader/Writer preference selection */ + int __rw_pshared; /* Shared between processes or not */ +} pthread_rwlock_t; + + +/* Attribute for read-write locks. */ +typedef struct +{ + int __lockkind; + int __pshared; +} pthread_rwlockattr_t; +#endif + +#ifdef __USE_XOPEN2K +/* POSIX spinlock data type. */ +typedef __volatile__ int pthread_spinlock_t; + +/* POSIX barrier. */ +typedef struct { + struct _pthread_fastlock __ba_lock; /* Lock to guarantee mutual exclusion */ + int __ba_required; /* Threads needed for completion */ + int __ba_present; /* Threads waiting */ + _pthread_descr __ba_waiting; /* Queue of waiting threads */ +} pthread_barrier_t; + +/* barrier attribute */ +typedef struct { + int __pshared; +} pthread_barrierattr_t; + +#endif + + +/* Thread identifiers */ +typedef void *pthread_t; diff --git a/l4/pkg/uclibc/lib/libpthread/include/pthread-l4.h b/l4/pkg/uclibc/lib/libpthread/include/pthread-l4.h new file mode 100644 index 00000000..d6f8898d --- /dev/null +++ b/l4/pkg/uclibc/lib/libpthread/include/pthread-l4.h @@ -0,0 +1,12 @@ +#pragma once + +#include +#include +#include + +__BEGIN_DECLS + +l4_cap_idx_t pthread_getl4cap(pthread_t t); +void pthread_l4_for_each_thread(void (*fn)(pthread_t)); + +__END_DECLS diff --git a/l4/pkg/uclibc/lib/libpthread/include/pthread.h b/l4/pkg/uclibc/lib/libpthread/include/pthread.h new file mode 100644 index 00000000..3bc42d0e --- /dev/null +++ b/l4/pkg/uclibc/lib/libpthread/include/pthread.h @@ -0,0 +1,689 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +/* This file is derived from uclibc/libpthreads/linuxthreads/sysdeps/pthread/pthread.h */ +#ifndef _PTHREAD_H +#define _PTHREAD_H 1 + +#include + +#include +#include + +#define __need_sigset_t +#include +#include +#include + +/* Aw11: schduling constants */ +enum +{ + SCHED_IDLE = 5, + SCHED_L4 = 6, +}; + +__BEGIN_DECLS + +/* Initializers. */ + +#define PTHREAD_MUTEX_INITIALIZER \ + {0, 0, 0, PTHREAD_MUTEX_TIMED_NP, __LOCK_INITIALIZER} +#ifdef __USE_GNU +# define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP \ + {0, 0, 0, PTHREAD_MUTEX_RECURSIVE_NP, __LOCK_INITIALIZER} +# define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP \ + {0, 0, 0, PTHREAD_MUTEX_ERRORCHECK_NP, __LOCK_INITIALIZER} +# define PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP \ + {0, 0, 0, PTHREAD_MUTEX_ADAPTIVE_NP, __LOCK_INITIALIZER} +#endif + +#define PTHREAD_COND_INITIALIZER {__LOCK_INITIALIZER, 0, "", 0} + +#if defined __USE_UNIX98 || defined __USE_XOPEN2K +# define PTHREAD_RWLOCK_INITIALIZER \ + { __LOCK_INITIALIZER, 0, NULL, NULL, NULL, \ + PTHREAD_RWLOCK_DEFAULT_NP, PTHREAD_PROCESS_PRIVATE } +#endif +#ifdef __USE_GNU +# define PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP \ + { __LOCK_INITIALIZER, 0, NULL, NULL, NULL, \ + PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP, PTHREAD_PROCESS_PRIVATE } +#endif + +/* Values for attributes. */ + +enum +{ + PTHREAD_CREATE_JOINABLE, +#define PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_JOINABLE + PTHREAD_CREATE_DETACHED +#define PTHREAD_CREATE_DETACHED PTHREAD_CREATE_DETACHED +}; + +enum +{ + PTHREAD_INHERIT_SCHED, +#define PTHREAD_INHERIT_SCHED PTHREAD_INHERIT_SCHED + PTHREAD_EXPLICIT_SCHED +#define PTHREAD_EXPLICIT_SCHED PTHREAD_EXPLICIT_SCHED +}; + +enum +{ + PTHREAD_SCOPE_SYSTEM, +#define PTHREAD_SCOPE_SYSTEM PTHREAD_SCOPE_SYSTEM + PTHREAD_SCOPE_PROCESS +#define PTHREAD_SCOPE_PROCESS PTHREAD_SCOPE_PROCESS +}; + +enum +{ + PTHREAD_MUTEX_TIMED_NP, + PTHREAD_MUTEX_RECURSIVE_NP, + PTHREAD_MUTEX_ERRORCHECK_NP, + PTHREAD_MUTEX_ADAPTIVE_NP +#ifdef __USE_UNIX98 + , + PTHREAD_MUTEX_NORMAL = PTHREAD_MUTEX_TIMED_NP, + PTHREAD_MUTEX_RECURSIVE = PTHREAD_MUTEX_RECURSIVE_NP, + PTHREAD_MUTEX_ERRORCHECK = PTHREAD_MUTEX_ERRORCHECK_NP, + PTHREAD_MUTEX_DEFAULT = PTHREAD_MUTEX_NORMAL +#endif +#ifdef __USE_GNU + /* For compatibility. */ + , PTHREAD_MUTEX_FAST_NP = PTHREAD_MUTEX_ADAPTIVE_NP +#endif +}; + +enum +{ + PTHREAD_PROCESS_PRIVATE, +#define PTHREAD_PROCESS_PRIVATE PTHREAD_PROCESS_PRIVATE + PTHREAD_PROCESS_SHARED +#define PTHREAD_PROCESS_SHARED PTHREAD_PROCESS_SHARED +}; + +#if defined __USE_UNIX98 || defined __USE_XOPEN2K +enum +{ + PTHREAD_RWLOCK_PREFER_READER_NP, + PTHREAD_RWLOCK_PREFER_WRITER_NP, + PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP, + PTHREAD_RWLOCK_DEFAULT_NP = PTHREAD_RWLOCK_PREFER_WRITER_NP +}; +#endif /* Unix98 */ + +#define PTHREAD_ONCE_INIT 0 + +/* Special constants */ + +#ifdef __USE_XOPEN2K +/* -1 is distinct from 0 and all errno constants */ +# define PTHREAD_BARRIER_SERIAL_THREAD -1 +#endif + +/* Cleanup buffers */ + +struct _pthread_cleanup_buffer +{ + void (*__routine) (void *); /* Function to call. */ + void *__arg; /* Its argument. */ + int __canceltype; /* Saved cancellation type. */ + struct _pthread_cleanup_buffer *__prev; /* Chaining of cleanup functions. */ +}; + +/* Cancellation */ + +enum +{ + PTHREAD_CANCEL_ENABLE, +#define PTHREAD_CANCEL_ENABLE PTHREAD_CANCEL_ENABLE + PTHREAD_CANCEL_DISABLE +#define PTHREAD_CANCEL_DISABLE PTHREAD_CANCEL_DISABLE +}; +enum +{ + PTHREAD_CANCEL_DEFERRED, +#define PTHREAD_CANCEL_DEFERRED PTHREAD_CANCEL_DEFERRED + PTHREAD_CANCEL_ASYNCHRONOUS +#define PTHREAD_CANCEL_ASYNCHRONOUS PTHREAD_CANCEL_ASYNCHRONOUS +}; +#define PTHREAD_CANCELED ((void *) -1) + + +/* Function for handling threads. */ + +/* Create a thread with given attributes ATTR (or default attributes + if ATTR is NULL), and call function START_ROUTINE with given + arguments ARG. */ +extern int pthread_create (pthread_t *__restrict __threadp, + __const pthread_attr_t *__restrict __attr, + void *(*__start_routine) (void *), + void *__restrict __arg) __THROW; + +/* Obtain the identifier of the current thread. */ +extern pthread_t pthread_self (void) __THROW; + +/* Compare two thread identifiers. */ +extern int pthread_equal (pthread_t __thread1, pthread_t __thread2) __THROW; + +/* Terminate calling thread. */ +extern void pthread_exit (void *__retval) __attribute__ ((__noreturn__)); + +/* Make calling thread wait for termination of the thread TH. The + exit status of the thread is stored in *THREAD_RETURN, if THREAD_RETURN + is not NULL. */ +extern int pthread_join (pthread_t __th, void **__thread_return); + +/* Indicate that the thread TH is never to be joined with PTHREAD_JOIN. + The resources of TH will therefore be freed immediately when it + terminates, instead of waiting for another thread to perform PTHREAD_JOIN + on it. */ +extern int pthread_detach (pthread_t __th) __THROW; + + +/* Functions for handling attributes. */ + +/* Initialize thread attribute *ATTR with default attributes + (detachstate is PTHREAD_JOINABLE, scheduling policy is SCHED_OTHER, + no user-provided stack). */ +extern int pthread_attr_init (pthread_attr_t *__attr) __THROW; + +/* Destroy thread attribute *ATTR. */ +extern int pthread_attr_destroy (pthread_attr_t *__attr) __THROW; + +/* Set the `detachstate' attribute in *ATTR according to DETACHSTATE. */ +extern int pthread_attr_setdetachstate (pthread_attr_t *__attr, + int __detachstate) __THROW; + +/* Return in *DETACHSTATE the `detachstate' attribute in *ATTR. */ +extern int pthread_attr_getdetachstate (__const pthread_attr_t *__attr, + int *__detachstate) __THROW; + +/* Set scheduling parameters (priority, etc) in *ATTR according to PARAM. */ +extern int pthread_attr_setschedparam (pthread_attr_t *__restrict __attr, + __const struct sched_param *__restrict + __param) __THROW; + +/* Return in *PARAM the scheduling parameters of *ATTR. */ +extern int pthread_attr_getschedparam (__const pthread_attr_t *__restrict + __attr, + struct sched_param *__restrict __param) + __THROW; + +/* Set scheduling policy in *ATTR according to POLICY. */ +extern int pthread_attr_setschedpolicy (pthread_attr_t *__attr, int __policy) + __THROW; + +/* Return in *POLICY the scheduling policy of *ATTR. */ +extern int pthread_attr_getschedpolicy (__const pthread_attr_t *__restrict + __attr, int *__restrict __policy) + __THROW; + +/* Set scheduling inheritance mode in *ATTR according to INHERIT. */ +extern int pthread_attr_setinheritsched (pthread_attr_t *__attr, + int __inherit) __THROW; + +/* Return in *INHERIT the scheduling inheritance mode of *ATTR. */ +extern int pthread_attr_getinheritsched (__const pthread_attr_t *__restrict + __attr, int *__restrict __inherit) + __THROW; + +/* Set scheduling contention scope in *ATTR according to SCOPE. */ +extern int pthread_attr_setscope (pthread_attr_t *__attr, int __scope) + __THROW; + +/* Return in *SCOPE the scheduling contention scope of *ATTR. */ +extern int pthread_attr_getscope (__const pthread_attr_t *__restrict __attr, + int *__restrict __scope) __THROW; + +#ifdef __USE_UNIX98 +/* Set the size of the guard area at the bottom of the thread. */ +extern int pthread_attr_setguardsize (pthread_attr_t *__attr, + size_t __guardsize) __THROW; + +/* Get the size of the guard area at the bottom of the thread. */ +extern int pthread_attr_getguardsize (__const pthread_attr_t *__restrict + __attr, size_t *__restrict __guardsize) + __THROW; +#endif + +#if 0 /* uClibc: deprecated stuff disabled. def __UCLIBC_SUSV3_LEGACY__ */ +/* Set the starting address of the stack of the thread to be created. + Depending on whether the stack grows up or down the value must either + be higher or lower than all the address in the memory block. The + minimal size of the block must be PTHREAD_STACK_MIN. */ +extern int pthread_attr_setstackaddr (pthread_attr_t *__attr, + void *__stackaddr) __THROW; + +/* Return the previously set address for the stack. */ +extern int pthread_attr_getstackaddr (__const pthread_attr_t *__restrict + __attr, void **__restrict __stackaddr) + __THROW; +#endif + +#ifdef __USE_XOPEN2K +/* The following two interfaces are intended to replace the last two. They + require setting the address as well as the size since only setting the + address will make the implementation on some architectures impossible. */ +extern int pthread_attr_setstack (pthread_attr_t *__attr, void *__stackaddr, + size_t __stacksize) __THROW; + +/* Return the previously set address for the stack. */ +extern int pthread_attr_getstack (__const pthread_attr_t *__restrict __attr, + void **__restrict __stackaddr, + size_t *__restrict __stacksize) __THROW; +#endif + +/* Add information about the minimum stack size needed for the thread + to be started. This size must never be less than PTHREAD_STACK_MIN + and must also not exceed the system limits. */ +extern int pthread_attr_setstacksize (pthread_attr_t *__attr, + size_t __stacksize) __THROW; + +/* Return the currently used minimal stack size. */ +extern int pthread_attr_getstacksize (__const pthread_attr_t *__restrict + __attr, size_t *__restrict __stacksize) + __THROW; + +#ifdef __USE_GNU +/* Initialize thread attribute *ATTR with attributes corresponding to the + already running thread TH. It shall be called on uninitialized ATTR + and destroyed with pthread_attr_destroy when no longer needed. */ +extern int pthread_getattr_np (pthread_t __th, pthread_attr_t *__attr) __THROW; +#endif + +/* Functions for scheduling control. */ + +/* Set the scheduling parameters for TARGET_THREAD according to POLICY + and *PARAM. */ +extern int pthread_setschedparam (pthread_t __target_thread, int __policy, + __const struct sched_param *__param) + __THROW; + +/* Return in *POLICY and *PARAM the scheduling parameters for TARGET_THREAD. */ +extern int pthread_getschedparam (pthread_t __target_thread, + int *__restrict __policy, + struct sched_param *__restrict __param) + __THROW; + +#ifdef __USE_UNIX98 +/* Determine level of concurrency. */ +extern int pthread_getconcurrency (void) __THROW; + +/* Set new concurrency level to LEVEL. */ +extern int pthread_setconcurrency (int __level) __THROW; +#endif + +/* Functions for mutex handling. */ + +/* Initialize MUTEX using attributes in *MUTEX_ATTR, or use the + default values if later is NULL. */ +extern int pthread_mutex_init (pthread_mutex_t *__restrict __mutex, + __const pthread_mutexattr_t *__restrict + __mutex_attr) __THROW; + +/* Destroy MUTEX. */ +extern int pthread_mutex_destroy (pthread_mutex_t *__mutex) __THROW; + +/* Try to lock MUTEX. */ +extern int pthread_mutex_trylock (pthread_mutex_t *__mutex) __THROW; + +/* Wait until lock for MUTEX becomes available and lock it. */ +extern int pthread_mutex_lock (pthread_mutex_t *__mutex) __THROW; + +#ifdef __USE_XOPEN2K +/* Wait until lock becomes available, or specified time passes. */ +extern int pthread_mutex_timedlock (pthread_mutex_t *__restrict __mutex, + __const struct timespec *__restrict + __abstime) __THROW; +#endif + +/* Unlock MUTEX. */ +extern int pthread_mutex_unlock (pthread_mutex_t *__mutex) __THROW; + + +/* Functions for handling mutex attributes. */ + +/* Initialize mutex attribute object ATTR with default attributes + (kind is PTHREAD_MUTEX_TIMED_NP). */ +extern int pthread_mutexattr_init (pthread_mutexattr_t *__attr) __THROW; + +/* Destroy mutex attribute object ATTR. */ +extern int pthread_mutexattr_destroy (pthread_mutexattr_t *__attr) __THROW; + +/* Get the process-shared flag of the mutex attribute ATTR. */ +extern int pthread_mutexattr_getpshared (__const pthread_mutexattr_t * + __restrict __attr, + int *__restrict __pshared) __THROW; + +/* Set the process-shared flag of the mutex attribute ATTR. */ +extern int pthread_mutexattr_setpshared (pthread_mutexattr_t *__attr, + int __pshared) __THROW; + +#ifdef __USE_UNIX98 +/* Set the mutex kind attribute in *ATTR to KIND (either PTHREAD_MUTEX_NORMAL, + PTHREAD_MUTEX_RECURSIVE, PTHREAD_MUTEX_ERRORCHECK, or + PTHREAD_MUTEX_DEFAULT). */ +extern int pthread_mutexattr_settype (pthread_mutexattr_t *__attr, int __kind) + __THROW; + +/* Return in *KIND the mutex kind attribute in *ATTR. */ +extern int pthread_mutexattr_gettype (__const pthread_mutexattr_t *__restrict + __attr, int *__restrict __kind) __THROW; +#endif + + +/* Functions for handling conditional variables. */ + +/* Initialize condition variable COND using attributes ATTR, or use + the default values if later is NULL. */ +extern int pthread_cond_init (pthread_cond_t *__restrict __cond, + __const pthread_condattr_t *__restrict + __cond_attr) __THROW; + +/* Destroy condition variable COND. */ +extern int pthread_cond_destroy (pthread_cond_t *__cond) __THROW; + +/* Wake up one thread waiting for condition variable COND. */ +extern int pthread_cond_signal (pthread_cond_t *__cond) __THROW; + +/* Wake up all threads waiting for condition variables COND. */ +extern int pthread_cond_broadcast (pthread_cond_t *__cond) __THROW; + +/* Wait for condition variable COND to be signaled or broadcast. + MUTEX is assumed to be locked before. */ +extern int pthread_cond_wait (pthread_cond_t *__restrict __cond, + pthread_mutex_t *__restrict __mutex); + +/* Wait for condition variable COND to be signaled or broadcast until + ABSTIME. MUTEX is assumed to be locked before. ABSTIME is an + absolute time specification; zero is the beginning of the epoch + (00:00:00 GMT, January 1, 1970). */ +extern int pthread_cond_timedwait (pthread_cond_t *__restrict __cond, + pthread_mutex_t *__restrict __mutex, + __const struct timespec *__restrict + __abstime); + +/* Functions for handling condition variable attributes. */ + +/* Initialize condition variable attribute ATTR. */ +extern int pthread_condattr_init (pthread_condattr_t *__attr) __THROW; + +/* Destroy condition variable attribute ATTR. */ +extern int pthread_condattr_destroy (pthread_condattr_t *__attr) __THROW; + +/* Get the process-shared flag of the condition variable attribute ATTR. */ +extern int pthread_condattr_getpshared (__const pthread_condattr_t * + __restrict __attr, + int *__restrict __pshared) __THROW; + +/* Set the process-shared flag of the condition variable attribute ATTR. */ +extern int pthread_condattr_setpshared (pthread_condattr_t *__attr, + int __pshared) __THROW; + + +#if defined __USE_UNIX98 || defined __USE_XOPEN2K +/* Functions for handling read-write locks. */ + +/* Initialize read-write lock RWLOCK using attributes ATTR, or use + the default values if later is NULL. */ +extern int pthread_rwlock_init (pthread_rwlock_t *__restrict __rwlock, + __const pthread_rwlockattr_t *__restrict + __attr) __THROW; + +/* Destroy read-write lock RWLOCK. */ +extern int pthread_rwlock_destroy (pthread_rwlock_t *__rwlock) __THROW; + +/* Acquire read lock for RWLOCK. */ +extern int pthread_rwlock_rdlock (pthread_rwlock_t *__rwlock) __THROW; + +/* Try to acquire read lock for RWLOCK. */ +extern int pthread_rwlock_tryrdlock (pthread_rwlock_t *__rwlock) __THROW; + +# ifdef __USE_XOPEN2K +/* Try to acquire read lock for RWLOCK or return after specfied time. */ +extern int pthread_rwlock_timedrdlock (pthread_rwlock_t *__restrict __rwlock, + __const struct timespec *__restrict + __abstime) __THROW; +# endif + +/* Acquire write lock for RWLOCK. */ +extern int pthread_rwlock_wrlock (pthread_rwlock_t *__rwlock) __THROW; + +/* Try to acquire write lock for RWLOCK. */ +extern int pthread_rwlock_trywrlock (pthread_rwlock_t *__rwlock) __THROW; + +# ifdef __USE_XOPEN2K +/* Try to acquire write lock for RWLOCK or return after specfied time. */ +extern int pthread_rwlock_timedwrlock (pthread_rwlock_t *__restrict __rwlock, + __const struct timespec *__restrict + __abstime) __THROW; +# endif + +/* Unlock RWLOCK. */ +extern int pthread_rwlock_unlock (pthread_rwlock_t *__rwlock) __THROW; + + +/* Functions for handling read-write lock attributes. */ + +/* Initialize attribute object ATTR with default values. */ +extern int pthread_rwlockattr_init (pthread_rwlockattr_t *__attr) __THROW; + +/* Destroy attribute object ATTR. */ +extern int pthread_rwlockattr_destroy (pthread_rwlockattr_t *__attr) __THROW; + +/* Return current setting of process-shared attribute of ATTR in PSHARED. */ +extern int pthread_rwlockattr_getpshared (__const pthread_rwlockattr_t * + __restrict __attr, + int *__restrict __pshared) __THROW; + +/* Set process-shared attribute of ATTR to PSHARED. */ +extern int pthread_rwlockattr_setpshared (pthread_rwlockattr_t *__attr, + int __pshared) __THROW; + +/* Return current setting of reader/writer preference. */ +extern int pthread_rwlockattr_getkind_np (__const pthread_rwlockattr_t *__attr, + int *__pref) __THROW; + +/* Set reader/write preference. */ +extern int pthread_rwlockattr_setkind_np (pthread_rwlockattr_t *__attr, + int __pref) __THROW; +#endif + +#ifdef __USE_XOPEN2K +/* The IEEE Std. 1003.1j-2000 introduces functions to implement + spinlocks. */ + +/* Initialize the spinlock LOCK. If PSHARED is nonzero the spinlock can + be shared between different processes. */ +extern int pthread_spin_init (pthread_spinlock_t *__lock, int __pshared) + __THROW; + +/* Destroy the spinlock LOCK. */ +extern int pthread_spin_destroy (pthread_spinlock_t *__lock) __THROW; + +/* Wait until spinlock LOCK is retrieved. */ +extern int pthread_spin_lock (pthread_spinlock_t *__lock) __THROW; + +/* Try to lock spinlock LOCK. */ +extern int pthread_spin_trylock (pthread_spinlock_t *__lock) __THROW; + +/* Release spinlock LOCK. */ +extern int pthread_spin_unlock (pthread_spinlock_t *__lock) __THROW; + + +/* Barriers are a also a new feature in 1003.1j-2000. */ + +extern int pthread_barrier_init (pthread_barrier_t *__restrict __barrier, + __const pthread_barrierattr_t *__restrict + __attr, unsigned int __count) __THROW; + +extern int pthread_barrier_destroy (pthread_barrier_t *__barrier) __THROW; + +extern int pthread_barrierattr_init (pthread_barrierattr_t *__attr) __THROW; + +extern int pthread_barrierattr_destroy (pthread_barrierattr_t *__attr) __THROW; + +extern int pthread_barrierattr_getpshared (__const pthread_barrierattr_t * + __restrict __attr, + int *__restrict __pshared) __THROW; + +extern int pthread_barrierattr_setpshared (pthread_barrierattr_t *__attr, + int __pshared) __THROW; + +extern int pthread_barrier_wait (pthread_barrier_t *__barrier) __THROW; +#endif + + +/* Functions for handling thread-specific data. */ + +/* Create a key value identifying a location in the thread-specific + data area. Each thread maintains a distinct thread-specific data + area. DESTR_FUNCTION, if non-NULL, is called with the value + associated to that key when the key is destroyed. + DESTR_FUNCTION is not called if the value associated is NULL when + the key is destroyed. */ +extern int pthread_key_create (pthread_key_t *__key, + void (*__destr_function) (void *)) __THROW; + +/* Destroy KEY. */ +extern int pthread_key_delete (pthread_key_t __key) __THROW; + +/* Store POINTER in the thread-specific data slot identified by KEY. */ +extern int pthread_setspecific (pthread_key_t __key, + __const void *__pointer) __THROW; + +/* Return current value of the thread-specific data slot identified by KEY. */ +extern void *pthread_getspecific (pthread_key_t __key) __THROW; + + +/* Functions for handling initialization. */ + +/* Guarantee that the initialization function INIT_ROUTINE will be called + only once, even if pthread_once is executed several times with the + same ONCE_CONTROL argument. ONCE_CONTROL must point to a static or + extern variable initialized to PTHREAD_ONCE_INIT. + + The initialization functions might throw exception which is why + this function is not marked with __THROW. */ +extern int pthread_once (pthread_once_t *__once_control, + void (*__init_routine) (void)); + + +/* Functions for handling cancellation. */ + +/* Set cancelability state of current thread to STATE, returning old + state in *OLDSTATE if OLDSTATE is not NULL. */ +extern int pthread_setcancelstate (int __state, int *__oldstate); + +/* Set cancellation state of current thread to TYPE, returning the old + type in *OLDTYPE if OLDTYPE is not NULL. */ +extern int pthread_setcanceltype (int __type, int *__oldtype); + +/* Cancel THREAD immediately or at the next possibility. */ +extern int pthread_cancel (pthread_t __cancelthread); + +/* Test for pending cancellation for the current thread and terminate + the thread as per pthread_exit(PTHREAD_CANCELED) if it has been + cancelled. */ +extern void pthread_testcancel (void); + + +/* Install a cleanup handler: ROUTINE will be called with arguments ARG + when the thread is cancelled or calls pthread_exit. ROUTINE will also + be called with arguments ARG when the matching pthread_cleanup_pop + is executed with non-zero EXECUTE argument. + pthread_cleanup_push and pthread_cleanup_pop are macros and must always + be used in matching pairs at the same nesting level of braces. */ + +#define pthread_cleanup_push(routine,arg) \ + { struct _pthread_cleanup_buffer _buffer; \ + _pthread_cleanup_push (&_buffer, (routine), (arg)); + +extern void _pthread_cleanup_push (struct _pthread_cleanup_buffer *__buffer, + void (*__routine) (void *), + void *__arg) __THROW; + +/* Remove a cleanup handler installed by the matching pthread_cleanup_push. + If EXECUTE is non-zero, the handler function is called. */ + +#define pthread_cleanup_pop(execute) \ + _pthread_cleanup_pop (&_buffer, (execute)); } + +extern void _pthread_cleanup_pop (struct _pthread_cleanup_buffer *__buffer, + int __execute) __THROW; + +/* Install a cleanup handler as pthread_cleanup_push does, but also + saves the current cancellation type and set it to deferred cancellation. */ + +#ifdef __USE_GNU +# define pthread_cleanup_push_defer_np(routine,arg) \ + { struct _pthread_cleanup_buffer _buffer; \ + _pthread_cleanup_push_defer (&_buffer, (routine), (arg)); + +extern void _pthread_cleanup_push_defer (struct _pthread_cleanup_buffer *__buffer, + void (*__routine) (void *), + void *__arg) __THROW; + +/* Remove a cleanup handler as pthread_cleanup_pop does, but also + restores the cancellation type that was in effect when the matching + pthread_cleanup_push_defer was called. */ + +# define pthread_cleanup_pop_restore_np(execute) \ + _pthread_cleanup_pop_restore (&_buffer, (execute)); } + +extern void _pthread_cleanup_pop_restore (struct _pthread_cleanup_buffer *__buffer, + int __execute) __THROW; +#endif + + +#ifdef __USE_XOPEN2K +/* Get ID of CPU-time clock for thread THREAD_ID. */ +extern int pthread_getcpuclockid (pthread_t __thread_id, + __clockid_t *__clock_id) __THROW; +#endif + + +#ifdef L4_DISABLED +/* Functions for handling signals. */ +#include + + +/* Functions for handling process creation and process execution. */ + +/* Install handlers to be called when a new process is created with FORK. + The PREPARE handler is called in the parent process just before performing + FORK. The PARENT handler is called in the parent process just after FORK. + The CHILD handler is called in the child process. Each of the three + handlers can be NULL, meaning that no handler needs to be called at that + point. + PTHREAD_ATFORK can be called several times, in which case the PREPARE + handlers are called in LIFO order (last added with PTHREAD_ATFORK, + first called before FORK), and the PARENT and CHILD handlers are called + in FIFO (first added, first called). */ + +extern int pthread_atfork (void (*__prepare) (void), + void (*__parent) (void), + void (*__child) (void)) __THROW; +#endif + +/* Terminate all threads in the program except the calling process. + Should be called just before invoking one of the exec*() functions. */ + +extern void pthread_kill_other_threads_np (void) __THROW; + +__END_DECLS + +#endif /* pthread.h */ diff --git a/l4/pkg/uclibc/lib/libpthread/include/semaphore.h b/l4/pkg/uclibc/lib/libpthread/include/semaphore.h new file mode 100644 index 00000000..3084209f --- /dev/null +++ b/l4/pkg/uclibc/lib/libpthread/include/semaphore.h @@ -0,0 +1,94 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +#ifndef _SEMAPHORE_H +#define _SEMAPHORE_H 1 + +#include +#include +#ifdef __USE_XOPEN2K +# define __need_timespec +# include +#endif + +#ifndef _PTHREAD_DESCR_DEFINED +/* Thread descriptors. Needed for `sem_t' definition. */ +typedef struct _pthread_descr_struct *_pthread_descr; +# define _PTHREAD_DESCR_DEFINED +#endif + +/* System specific semaphore definition. */ +typedef struct +{ + struct _pthread_fastlock __sem_lock; + int __sem_value; + _pthread_descr __sem_waiting; +} sem_t; + + + +/* Value returned if `sem_open' failed. */ +#define SEM_FAILED ((sem_t *) 0) + +/* Maximum value the semaphore can have. */ +#define SEM_VALUE_MAX (2147483647) + + +__BEGIN_DECLS + +/* Initialize semaphore object SEM to VALUE. If PSHARED then share it + with other processes. */ +extern int sem_init (sem_t *__sem, int __pshared, unsigned int __value) __THROW; + +/* Free resources associated with semaphore object SEM. */ +extern int sem_destroy (sem_t *__sem) __THROW; + +/* Open a named semaphore NAME with open flags OFLAG. */ +extern sem_t *sem_open (__const char *__name, int __oflag, ...) __THROW; + +/* Close descriptor for named semaphore SEM. */ +extern int sem_close (sem_t *__sem) __THROW; + +/* Remove named semaphore NAME. */ +extern int sem_unlink (__const char *__name) __THROW; + +/* Wait for SEM being posted. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern int sem_wait (sem_t *__sem); + +#ifdef __USE_XOPEN2K +/* Similar to `sem_wait' but wait only until ABSTIME. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern int sem_timedwait (sem_t *__restrict __sem, + __const struct timespec *__restrict __abstime); +#endif + +/* Test whether SEM is posted. */ +extern int sem_trywait (sem_t *__sem) __THROW; + +/* Post SEM. */ +extern int sem_post (sem_t *__sem) __THROW; + +/* Get current value of SEM and store it in *SVAL. */ +extern int sem_getvalue (sem_t *__restrict __sem, int *__restrict __sval) + __THROW; + + +__END_DECLS + +#endif /* semaphore.h */ diff --git a/l4/pkg/uclibc/lib/libpthread/include/smp.h b/l4/pkg/uclibc/lib/libpthread/include/smp.h new file mode 100644 index 00000000..4cc20f3c --- /dev/null +++ b/l4/pkg/uclibc/lib/libpthread/include/smp.h @@ -0,0 +1,54 @@ +/* Determine whether the host has multiple processors. Linux version. + Copyright (C) 1996, 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifdef NOT_FOR_L4 +#include +#endif + +/* Test whether the machine has more than one processor. This is not the + best test but good enough. More complicated tests would require `malloc' + which is not available at that time. */ +static __inline__ int +is_smp_system (void) +{ +#ifdef NOT_FOR_L4 + static const int sysctl_args[] = { CTL_KERN, KERN_VERSION }; + char buf[512]; + size_t reslen = sizeof (buf); + + /* Try reading the number using `sysctl' first. */ + if (__sysctl ((int *) sysctl_args, + sizeof (sysctl_args) / sizeof (sysctl_args[0]), + buf, &reslen, NULL, 0) < 0) + { + /* This was not successful. Now try reading the /proc filesystem. */ + int fd = __open ("/proc/sys/kernel/version", O_RDONLY); + if (__builtin_expect (fd, 0) == -1 + || (reslen = __read (fd, buf, sizeof (buf))) <= 0) + /* This also didn't work. We give up and say it's a UP machine. */ + buf[0] = '\0'; + + __close (fd); + } + + return strstr (buf, "SMP") != NULL; +#else + return 1; +#endif +} diff --git a/l4/pkg/uclibc/lib/libpthread/src/Makefile b/l4/pkg/uclibc/lib/libpthread/src/Makefile new file mode 100644 index 00000000..57f52b2d --- /dev/null +++ b/l4/pkg/uclibc/lib/libpthread/src/Makefile @@ -0,0 +1,61 @@ +PKGDIR ?= ../../.. +L4DIR ?= $(PKGDIR)/../.. + +TARGET = libpthread.a libpthread.so + +PC_FILENAME = libpthread +PC_LIBS_libpthread := -lpthread + +CONTRIBDIR = $(PKGDIR)/../uclibc/lib/contrib/uclibc +LDSODIR = $(CONTRIBDIR)/ldso/ldso + +SRC_CC = manager.cc l4.cc +SRC_C += spinlock.c mutex.c condvar.c rwlock.c errno.c specific.c \ + semaphore.c attr.c barrier.c join.c pthread.c \ + cancel.c ptcleanup.c errno-loc.c +SRC_C_libpthread.a += libc_pthread_init.c +SRC_S = tramp-$(ARCH).S +SO_INIT = so_init-$(ARCH) + +vpath %.c $(SRC_DIR)/sysdeps/generic +#vpath dl-tls.c $(PKGDIR)/lib/contrib/uclibc/ldso/ldso + +DIR_amd64 := x86_64 +DIR_x86 := i386 +DIR_arm := arm +DIR_ppc32 := powerpc +DIR_sparc := sparc + + +INCDIR-x86 = $(SRC_DIR)/sysdeps/i386/i686 $(SRC_DIR)/sysdeps/i386 \ + $(CONTRIBDIR)/libc \ + $(LDSODIR)/$(DIR_$(ARCH)) +INCDIR-amd64 = $(SRC_DIR)/sysdeps/$(DIR_$(ARCH)) +INCDIR-arm = $(SRC_DIR)/sysdeps/arm +INCDIR-ppc32 = $(SRC_DIR)/sysdeps/powerpc +INCDIR-sparc = $(SRC_DIR)/sysdeps/sparc + +PRIVATE_INCDIR = $(SRC_DIR) $(INCDIR-$(ARCH)) $(CONTRIBDIR)/ldso/include + +DEFINES := -DL4_THREAD_SAFE -D__USE_XOPEN2K -D_POSIX_C_SOURCE=200112L \ + -D_GNU_SOURCE=1 -D__NO_WEAK_PTHREAD_ALIASES=1 \ + -D_LIBC=1 -DIS_IN_libpthread=1 -DNOT_IN_libc=1 + +DEFINES_x86-l4f := -DUSE___THREAD=1 +DEFINES_amd64-l4f := -DUSE___THREAD=1 +DEFINES_arm-l4f := -DUSE___THREAD=1 +DEFINES_ppc32-l4f := -DUSE___THREAD=1 +DEFINES_sparc-l4f := -DUSE___THREAD=1 + +CFLAGS += -include $(CONTRIBDIR)/include/libc-symbols.h +CXXFLAGS += -include $(CONTRIBDIR)/include/libc-symbols.h +CXXFLAGS += -fno-exceptions + +include $(L4DIR)/mk/lib.mk +CRT0 = $(CRTI_so) $(SO_INIT).s.o $(CRTBEGIN_so) $(CRT1_so) + +CFLAGS := $(filter-out -Wextra,$(CFLAGS)) +CXXFLAGS := $(filter-out -Wextra,$(CXXFLAGS)) +PICFLAGS += -DSHARED + +libpthread.so: $(SO_INIT).s.o diff --git a/l4/pkg/uclibc/lib/libpthread/src/attr.c b/l4/pkg/uclibc/lib/libpthread/src/attr.c new file mode 100644 index 00000000..1f00a673 --- /dev/null +++ b/l4/pkg/uclibc/lib/libpthread/src/attr.c @@ -0,0 +1,505 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +/* Handling of thread attributes */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "pthread.h" +#include "internals.h" + + +#define __sched_get_priority_max(x) (L4_SCHED_MAX_PRIO) +#define __sched_get_priority_min(x) (1) + +int +attribute_hidden +__pthread_attr_init(pthread_attr_t *attr) +{ + size_t ps = L4_PAGESIZE; + + attr->__detachstate = PTHREAD_CREATE_JOINABLE; + attr->__schedpolicy = SCHED_OTHER; + attr->__schedparam.sched_priority = 0; + attr->__inheritsched = PTHREAD_EXPLICIT_SCHED; + attr->__scope = PTHREAD_SCOPE_SYSTEM; +#ifdef NEED_SEPARATE_REGISTER_STACK + attr->__guardsize = ps + ps; +#else + attr->__guardsize = ps; +#endif + attr->__stackaddr = NULL; + attr->__stackaddr_set = 0; + attr->__stacksize = STACK_SIZE - ps; + return 0; +} +strong_alias (__pthread_attr_init, pthread_attr_init) + +int +attribute_hidden +__pthread_attr_destroy(pthread_attr_t *attr) +{ + return 0; +} +strong_alias (__pthread_attr_destroy, pthread_attr_destroy) + +int +attribute_hidden +__pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate) +{ + if (detachstate < PTHREAD_CREATE_JOINABLE || + detachstate > PTHREAD_CREATE_DETACHED) + return EINVAL; + attr->__detachstate = detachstate; + return 0; +} +strong_alias (__pthread_attr_setdetachstate, pthread_attr_setdetachstate) + +int +attribute_hidden +__pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate) +{ + *detachstate = attr->__detachstate; + return 0; +} +strong_alias (__pthread_attr_getdetachstate, pthread_attr_getdetachstate) + +int +attribute_hidden +__pthread_attr_setschedparam(pthread_attr_t *attr, + const struct sched_param *param) +{ + int max_prio = __sched_get_priority_max(attr->__schedpolicy); + int min_prio = __sched_get_priority_min(attr->__schedpolicy); + + if (param->sched_priority < min_prio || param->sched_priority > max_prio) + return EINVAL; + memcpy (&attr->__schedparam, param, sizeof (struct sched_param)); + return 0; +} +strong_alias (__pthread_attr_setschedparam, pthread_attr_setschedparam) + +int +attribute_hidden +__pthread_attr_getschedparam(const pthread_attr_t *attr, + struct sched_param *param) +{ + memcpy (param, &attr->__schedparam, sizeof (struct sched_param)); + return 0; +} +strong_alias (__pthread_attr_getschedparam, pthread_attr_getschedparam) + +int +attribute_hidden +__pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy) +{ + if (policy != SCHED_OTHER && policy != SCHED_FIFO && policy != SCHED_RR + && policy != SCHED_L4) + return EINVAL; + attr->__schedpolicy = policy; + return 0; +} +strong_alias (__pthread_attr_setschedpolicy, pthread_attr_setschedpolicy) + +int +attribute_hidden +__pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy) +{ + *policy = attr->__schedpolicy; + return 0; +} +strong_alias (__pthread_attr_getschedpolicy, pthread_attr_getschedpolicy) + +int +attribute_hidden +__pthread_attr_setinheritsched(pthread_attr_t *attr, int inherit) +{ + if (inherit != PTHREAD_INHERIT_SCHED && inherit != PTHREAD_EXPLICIT_SCHED) + return EINVAL; + attr->__inheritsched = inherit; + return 0; +} +strong_alias (__pthread_attr_setinheritsched, pthread_attr_setinheritsched) + +int +attribute_hidden +__pthread_attr_getinheritsched(const pthread_attr_t *attr, int *inherit) +{ + *inherit = attr->__inheritsched; + return 0; +} +strong_alias (__pthread_attr_getinheritsched, pthread_attr_getinheritsched) + +int +attribute_hidden +__pthread_attr_setscope(pthread_attr_t *attr, int scope) +{ + switch (scope) { + case PTHREAD_SCOPE_SYSTEM: + attr->__scope = scope; + return 0; + case PTHREAD_SCOPE_PROCESS: + return ENOTSUP; + default: + return EINVAL; + } +} +strong_alias (__pthread_attr_setscope, pthread_attr_setscope) + +int +attribute_hidden +__pthread_attr_getscope(const pthread_attr_t *attr, int *scope) +{ + *scope = attr->__scope; + return 0; +} +strong_alias (__pthread_attr_getscope, pthread_attr_getscope) + +int +attribute_hidden +__pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize) +{ + /* The guard size must not be larger than the stack itself */ + if (guardsize >= attr->__stacksize) return EINVAL; + + attr->__guardsize = guardsize; + + return 0; +} +weak_alias (__pthread_attr_setguardsize, pthread_attr_setguardsize) + +int +attribute_hidden +__pthread_attr_getguardsize(const pthread_attr_t *attr, size_t *guardsize) +{ + *guardsize = attr->__guardsize; + return 0; +} +weak_alias (__pthread_attr_getguardsize, pthread_attr_getguardsize) + +#if 0 /* uClibc: deprecated stuff disabled */ +int __pthread_attr_setstackaddr(pthread_attr_t *attr, void *stackaddr) +{ + attr->__stackaddr = stackaddr; + attr->__stackaddr_set = 1; + return 0; +} +weak_alias (__pthread_attr_setstackaddr, pthread_attr_setstackaddr) + +link_warning (pthread_attr_setstackaddr, + "the use of `pthread_attr_setstackaddr' is deprecated, use `pthread_attr_setstack'") + +int __pthread_attr_getstackaddr(const pthread_attr_t *attr, void **stackaddr) +{ + /* XXX This function has a stupid definition. The standard specifies + no error value but what is if no stack address was set? We simply + return the value we have in the member. */ + *stackaddr = attr->__stackaddr; + return 0; +} +weak_alias (__pthread_attr_getstackaddr, pthread_attr_getstackaddr) + +link_warning (pthread_attr_getstackaddr, + "the use of `pthread_attr_getstackaddr' is deprecated, use `pthread_attr_getstack'") +#endif + + +int +attribute_hidden +__pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize) +{ + /* We have to check against the maximum allowed stack size. This is no + problem if the manager is already started and we determined it. If + this hasn't happened, we have to find the limit outself. */ + if (__pthread_max_stacksize == 0) + __pthread_init_max_stacksize (); + + if (stacksize > __pthread_max_stacksize) + return EINVAL; + + /* We don't accept value smaller than PTHREAD_STACK_MIN. */ + if (stacksize < PTHREAD_STACK_MIN) + return EINVAL; + + attr->__stacksize = stacksize; + return 0; +} + +#if PTHREAD_STACK_MIN == 16384 || defined __UCLIBC__ +weak_alias (__pthread_attr_setstacksize, pthread_attr_setstacksize) +#else +versioned_symbol (libpthread, __pthread_attr_setstacksize, + pthread_attr_setstacksize, GLIBC_2_3_3); + +# if SHLIB_COMPAT(libpthread, GLIBC_2_1, GLIBC_2_3_3) + +int +attribute_hidden +__old_pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize) +{ + /* We have to check against the maximum allowed stack size. This is no + problem if the manager is already started and we determined it. If + this hasn't happened, we have to find the limit outself. */ + if (__pthread_max_stacksize == 0) + __pthread_init_max_stacksize (); + + if (stacksize > __pthread_max_stacksize) + return EINVAL; + + /* We don't accept value smaller than old PTHREAD_STACK_MIN. */ + if (stacksize < 16384) + return EINVAL; + + attr->__stacksize = stacksize; + return 0; +} +compat_symbol (libpthread, __old_pthread_attr_setstacksize, + pthread_attr_setstacksize, GLIBC_2_1); +# endif +#endif + + +int +attribute_hidden +__pthread_attr_getstacksize(const pthread_attr_t *attr, size_t *stacksize) +{ + *stacksize = attr->__stacksize; + return 0; +} +weak_alias (__pthread_attr_getstacksize, pthread_attr_getstacksize) + +int +attribute_hidden +__pthread_attr_setstack (pthread_attr_t *attr, void *stackaddr, + size_t stacksize) +{ + int err; + + if ((((uintptr_t) stackaddr) + & (__alignof__ (struct _pthread_descr_struct) - 1)) != 0) + err = EINVAL; + else + err = __pthread_attr_setstacksize (attr, stacksize); + if (err == 0) + { +#ifndef _STACK_GROWS_UP + attr->__stackaddr = (char *) stackaddr + stacksize; +#else + attr->__stackaddr = stackaddr; +#endif + attr->__stackaddr_set = 1; + } + + return err; +} + +#if PTHREAD_STACK_MIN == 16384 || defined __UCLIBC__ +weak_alias (__pthread_attr_setstack, pthread_attr_setstack) +#else +versioned_symbol (libpthread, __pthread_attr_setstack, pthread_attr_setstack, + GLIBC_2_3_3); +# if SHLIB_COMPAT(libpthread, GLIBC_2_2, GLIBC_2_3_3) +int +attribute_hidden +__old_pthread_attr_setstack (pthread_attr_t *attr, void *stackaddr, + size_t stacksize) +{ + int err; + + if ((((uintptr_t) stackaddr) + & (__alignof__ (struct _pthread_descr_struct) - 1)) != 0) + err = EINVAL; + else + err = __old_pthread_attr_setstacksize (attr, stacksize); + if (err == 0) + { +# ifndef _STACK_GROWS_UP + attr->__stackaddr = (char *) stackaddr + stacksize; +# else + attr->__stackaddr = stackaddr; +# endif + attr->__stackaddr_set = 1; + } + + return err; +} + +compat_symbol (libpthread, __old_pthread_attr_setstack, pthread_attr_setstack, + GLIBC_2_2); + +# endif +#endif + +int +attribute_hidden +__pthread_attr_getstack (const pthread_attr_t *attr, void **stackaddr, + size_t *stacksize) +{ + /* XXX This function has a stupid definition. The standard specifies + no error value but what is if no stack address was set? We simply + return the value we have in the member. */ +#ifndef _STACK_GROWS_UP + *stackaddr = (char *) attr->__stackaddr - attr->__stacksize; +#else + *stackaddr = attr->__stackaddr; +#endif + *stacksize = attr->__stacksize; + return 0; +} +weak_alias (__pthread_attr_getstack, pthread_attr_getstack) + +int pthread_getattr_np (pthread_t thread, pthread_attr_t *attr) +{ + pthread_handle handle = thread_handle (thread); + pthread_descr descr; +#ifdef NOT_FOR_L4 + int ret = 0; +#endif + + if (handle == NULL) + return ENOENT; + + descr = handle_to_descr(handle); + + attr->__detachstate = (descr->p_detached + ? PTHREAD_CREATE_DETACHED + : PTHREAD_CREATE_JOINABLE); + + attr->__schedpolicy = descr->p_sched_policy; + if (attr->__schedpolicy == -1) + return EINVAL; + attr->__schedparam.sched_priority = descr->p_priority; + + if (attr->__schedparam.sched_priority < 0) + return EINVAL; + + attr->__inheritsched = descr->p_inheritsched; + attr->__scope = PTHREAD_SCOPE_SYSTEM; + +#ifdef _STACK_GROWS_DOWN +# ifdef USE_TLS + attr->__stacksize = descr->p_stackaddr - (char *)descr->p_guardaddr + - descr->p_guardsize; +# else + attr->__stacksize = (char *)(descr + 1) - (char *)descr->p_guardaddr + - descr->p_guardsize; +# endif +#else +# ifdef USE_TLS + attr->__stacksize = (char *)descr->p_guardaddr - descr->p_stackaddr; +# else + attr->__stacksize = (char *)descr->p_guardaddr - (char *)descr; +# endif +#endif + attr->__guardsize = descr->p_guardsize; + attr->__stackaddr_set = descr->p_userstack; +#ifdef NEED_SEPARATE_REGISTER_STACK + if (descr->p_userstack == 0) + attr->__stacksize *= 2; + /* XXX This is awkward. The guard pages are in the middle of the + two stacks. We must count the guard size in the stack size since + otherwise the range of the stack area cannot be computed. */ + attr->__stacksize += attr->__guardsize; +#endif +#ifdef USE_TLS + attr->__stackaddr = descr->p_stackaddr; +#else +# ifndef _STACK_GROWS_UP + attr->__stackaddr = (char *)(descr + 1); +# else + attr->__stackaddr = (char *)descr; +# endif +#endif + + +#ifdef NOT_FOR_L4 // XXX: fix for initial thread +#ifdef USE_TLS + if (attr->__stackaddr == NULL) +#else + if (descr == &__pthread_initial_thread) +#endif + { + /* Stack size limit. */ + struct rlimit rl; + + /* The safest way to get the top of the stack is to read + /proc/self/maps and locate the line into which + __libc_stack_end falls. */ + FILE *fp = fopen ("/proc/self/maps", "rc"); + if (fp == NULL) + ret = errno; + /* We need the limit of the stack in any case. */ + else if (getrlimit (RLIMIT_STACK, &rl) != 0) + ret = errno; + else + { + /* We need no locking. */ + __fsetlocking (fp, FSETLOCKING_BYCALLER); + + /* Until we found an entry (which should always be the case) + mark the result as a failure. */ + ret = ENOENT; + + char *line = NULL; + size_t linelen = 0; + uintptr_t last_to = 0; + + while (! feof_unlocked (fp)) + { + if (getdelim (&line, &linelen, '\n', fp) <= 0) + break; + + uintptr_t from; + uintptr_t to; + if (sscanf (line, "%" SCNxPTR "-%" SCNxPTR, &from, &to) != 2) + continue; + if (from <= (uintptr_t) __libc_stack_end + && (uintptr_t) __libc_stack_end < to) + { + /* Found the entry. Now we have the info we need. */ + attr->__stacksize = rl.rlim_cur; +#ifdef _STACK_GROWS_UP + /* Don't check to enforce a limit on the __stacksize */ + attr->__stackaddr = (void *) from; +#else + attr->__stackaddr = (void *) to; + + /* The limit might be too high. */ + if ((size_t) attr->__stacksize + > (size_t) attr->__stackaddr - last_to) + attr->__stacksize = (size_t) attr->__stackaddr - last_to; +#endif + + /* We succeed and no need to look further. */ + ret = 0; + break; + } + last_to = to; + } + + fclose (fp); + free (line); + } + } +#endif + return 0; + +} diff --git a/l4/pkg/uclibc/lib/libpthread/src/barrier.c b/l4/pkg/uclibc/lib/libpthread/src/barrier.c new file mode 100644 index 00000000..37d997cf --- /dev/null +++ b/l4/pkg/uclibc/lib/libpthread/src/barrier.c @@ -0,0 +1,128 @@ +/* POSIX barrier implementation for LinuxThreads. + Copyright (C) 2000, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Kaz Kylheku , 2000. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include "pthread.h" +#include "internals.h" +#include "spinlock.h" +#include "queue.h" +#include "restart.h" + +int +pthread_barrier_wait(pthread_barrier_t *barrier) +{ + pthread_descr self = thread_self(); + pthread_descr temp_wake_queue, th; + int result = 0; + + __pthread_lock(&barrier->__ba_lock, self); + + /* If the required number of threads have achieved rendezvous... */ + if (barrier->__ba_present >= barrier->__ba_required - 1) + { + /* ... then this last caller shall be the serial thread */ + result = PTHREAD_BARRIER_SERIAL_THREAD; + /* Copy and clear wait queue and reset barrier. */ + temp_wake_queue = barrier->__ba_waiting; + barrier->__ba_waiting = NULL; + barrier->__ba_present = 0; + } + else + { + result = 0; + barrier->__ba_present++; + enqueue(&barrier->__ba_waiting, self); + } + + __pthread_unlock(&barrier->__ba_lock); + + if (result == 0) + { + /* Non-serial threads have to suspend */ + suspend(self); + /* We don't bother dealing with cancellation because the POSIX + spec for barriers doesn't mention that pthread_barrier_wait + is a cancellation point. */ + } + else + { + /* Serial thread wakes up all others. */ + while ((th = dequeue(&temp_wake_queue)) != NULL) + restart(th); + } + + return result; +} + +int +pthread_barrier_init(pthread_barrier_t *barrier, + const pthread_barrierattr_t *attr, + unsigned int count) +{ + if (count == 0) + return EINVAL; + + __pthread_init_lock(&barrier->__ba_lock); + barrier->__ba_required = count; + barrier->__ba_present = 0; + barrier->__ba_waiting = NULL; + return 0; +} + +int +pthread_barrier_destroy(pthread_barrier_t *barrier) +{ + if (barrier->__ba_waiting != NULL) return EBUSY; + return 0; +} + +int +pthread_barrierattr_init(pthread_barrierattr_t *attr) +{ + attr->__pshared = PTHREAD_PROCESS_PRIVATE; + return 0; +} + +int +pthread_barrierattr_destroy(pthread_barrierattr_t *attr) +{ + return 0; +} + +int +__pthread_barrierattr_getpshared(const pthread_barrierattr_t *attr, + int *pshared) +{ + *pshared = PTHREAD_PROCESS_PRIVATE; + return 0; +} + +int +pthread_barrierattr_setpshared(pthread_barrierattr_t *attr, int pshared) +{ + if (pshared != PTHREAD_PROCESS_PRIVATE && pshared != PTHREAD_PROCESS_SHARED) + return EINVAL; + + /* For now it is not possible to shared a conditional variable. */ + if (pshared != PTHREAD_PROCESS_PRIVATE) + return ENOSYS; + + return 0; +} diff --git a/l4/pkg/uclibc/lib/libpthread/src/cancel.c b/l4/pkg/uclibc/lib/libpthread/src/cancel.c new file mode 100644 index 00000000..207303a6 --- /dev/null +++ b/l4/pkg/uclibc/lib/libpthread/src/cancel.c @@ -0,0 +1,304 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +/* Thread cancellation */ + +#include +#include +#include "pthread.h" +#include "internals.h" +#include "spinlock.h" +#include "restart.h" + +#include + +#ifdef _STACK_GROWS_DOWN +# define FRAME_LEFT(frame, other) ((char *) frame >= (char *) other) +#elif _STACK_GROWS_UP +# define FRAME_LEFT(frame, other) ((char *) frame <= (char *) other) +#else +# error "Define either _STACK_GROWS_DOWN or _STACK_GROWS_UP" +#endif + + +int +attribute_hidden +__pthread_setcancelstate(int state, int * oldstate) +{ + pthread_descr self = thread_self(); + if (state < PTHREAD_CANCEL_ENABLE || state > PTHREAD_CANCEL_DISABLE) + return EINVAL; + if (oldstate != NULL) *oldstate = THREAD_GETMEM(self, p_cancelstate); + THREAD_SETMEM(self, p_cancelstate, state); + if (THREAD_GETMEM(self, p_canceled) && + THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE && + THREAD_GETMEM(self, p_canceltype) == PTHREAD_CANCEL_ASYNCHRONOUS) + __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); + return 0; +} +strong_alias (__pthread_setcancelstate, pthread_setcancelstate) + +int +attribute_hidden +__pthread_setcanceltype(int type, int * oldtype) +{ + pthread_descr self = thread_self(); + if (type < PTHREAD_CANCEL_DEFERRED || type > PTHREAD_CANCEL_ASYNCHRONOUS) + return EINVAL; + if (oldtype != NULL) *oldtype = THREAD_GETMEM(self, p_canceltype); + THREAD_SETMEM(self, p_canceltype, type); + if (THREAD_GETMEM(self, p_canceled) && + THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE && + THREAD_GETMEM(self, p_canceltype) == PTHREAD_CANCEL_ASYNCHRONOUS) + __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); + return 0; +} +strong_alias (__pthread_setcanceltype, pthread_setcanceltype) + + +/* The next two functions are similar to pthread_setcanceltype() but + more specialized for the use in the cancelable functions like write(). + They do not need to check parameters etc. */ +int +attribute_hidden +__pthread_enable_asynccancel (void) +{ + pthread_descr self = thread_self(); + int oldtype = THREAD_GETMEM(self, p_canceltype); + THREAD_SETMEM(self, p_canceltype, PTHREAD_CANCEL_ASYNCHRONOUS); + if (__builtin_expect (THREAD_GETMEM(self, p_canceled), 0) && + THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) + __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); + return oldtype; +} + +void +internal_function attribute_hidden +__pthread_disable_asynccancel (int oldtype) +{ + pthread_descr self = thread_self(); + THREAD_SETMEM(self, p_canceltype, oldtype); +} + + + +static void pthread_handle_sigcancel(void) +{ + pthread_descr self = check_thread_self(); + sigjmp_buf * jmpbuf; + + if (self == __manager_thread) + { + enter_kdebug("cancel of the manager hooooo"); +#if 0 + __pthread_manager_sighandler(sig); +#endif + return; + } + if (__builtin_expect (__pthread_exit_requested, 0)) { +#ifdef NOT_FOR_L4 + /* Main thread should accumulate times for thread manager and its + children, so that timings for main thread account for all threads. */ + if (self == __pthread_main_thread) { +#ifdef USE_TLS + waitpid(manager_thread->p_pid, NULL, __WCLONE); +#else + waitpid(__pthread_manager_thread.p_pid, NULL, __WCLONE); +#endif + } +#endif + _exit(__pthread_exit_code); + } + if (__builtin_expect (THREAD_GETMEM(self, p_canceled), 0) + && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) { + if (THREAD_GETMEM(self, p_canceltype) == PTHREAD_CANCEL_ASYNCHRONOUS) + __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); + jmpbuf = THREAD_GETMEM(self, p_cancel_jmp); + if (jmpbuf != NULL) { + THREAD_SETMEM(self, p_cancel_jmp, NULL); + siglongjmp(*jmpbuf, 1); + } + } +} + + +int pthread_cancel(pthread_t thread) +{ + pthread_handle handle = thread_handle(thread); + int dorestart = 0; + pthread_descr th; + pthread_extricate_if *pextricate; + int already_canceled; + + __pthread_lock(handle_to_lock(handle), NULL); + if (invalid_handle(handle, thread)) { + __pthread_unlock(handle_to_lock(handle)); + return ESRCH; + } + + th = handle_to_descr(handle); + + already_canceled = th->p_canceled; + th->p_canceled = 1; + + if (th->p_cancelstate == PTHREAD_CANCEL_DISABLE || already_canceled) { + __pthread_unlock(handle_to_lock(handle)); + return 0; + } + + pextricate = th->p_extricate; + + /* If the thread has registered an extrication interface, then + invoke the interface. If it returns 1, then we succeeded in + dequeuing the thread from whatever waiting object it was enqueued + with. In that case, it is our responsibility to wake it up. + And also to set the p_woken_by_cancel flag so the woken thread + can tell that it was woken by cancellation. */ + + if (pextricate != NULL) { + dorestart = pextricate->pu_extricate_func(pextricate->pu_object, th); + th->p_woken_by_cancel = dorestart; + } + + __pthread_unlock(handle_to_lock(handle)); + + /* If the thread has suspended or is about to, then we unblock it by + issuing a restart, instead of a cancel signal. Otherwise we send + the cancel signal to unblock the thread from a cancellation point, + or to initiate asynchronous cancellation. The restart is needed so + we have proper accounting of restarts; suspend decrements the thread's + resume count, and restart() increments it. This also means that suspend's + handling of the cancel signal is obsolete. */ + + if (dorestart) + restart(th); + else if (th->p_canceltype == PTHREAD_CANCEL_ASYNCHRONOUS) + { + l4_thread_ex_regs(th->p_th_cap, (l4_umword_t)&pthread_handle_sigcancel, + ~0UL, L4_THREAD_EX_REGS_CANCEL); + } + + return 0; +} + +void pthread_testcancel(void) +{ + pthread_descr self = thread_self(); + if (THREAD_GETMEM(self, p_canceled) + && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) + __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); +} + +void +attribute_hidden +__pthread_cleanup_push(struct _pthread_cleanup_buffer * buffer, + void (*routine)(void *), void * arg) +{ + pthread_descr self = thread_self(); + buffer->__routine = routine; + buffer->__arg = arg; + buffer->__prev = THREAD_GETMEM(self, p_cleanup); + if (buffer->__prev != NULL && FRAME_LEFT (buffer, buffer->__prev)) + buffer->__prev = NULL; + THREAD_SETMEM(self, p_cleanup, buffer); +} + +strong_alias(__pthread_cleanup_push, _pthread_cleanup_push) + +void +attribute_hidden +__pthread_cleanup_pop(struct _pthread_cleanup_buffer * buffer, + int execute) +{ + pthread_descr self = thread_self(); + if (execute) buffer->__routine(buffer->__arg); + THREAD_SETMEM(self, p_cleanup, buffer->__prev); +} + +strong_alias(__pthread_cleanup_pop, _pthread_cleanup_pop) + +void +attribute_hidden +__pthread_cleanup_push_defer(struct _pthread_cleanup_buffer * buffer, + void (*routine)(void *), void * arg) +{ + pthread_descr self = thread_self(); + buffer->__routine = routine; + buffer->__arg = arg; + buffer->__canceltype = THREAD_GETMEM(self, p_canceltype); + buffer->__prev = THREAD_GETMEM(self, p_cleanup); + if (buffer->__prev != NULL && FRAME_LEFT (buffer, buffer->__prev)) + buffer->__prev = NULL; + THREAD_SETMEM(self, p_canceltype, PTHREAD_CANCEL_DEFERRED); + THREAD_SETMEM(self, p_cleanup, buffer); +} + +strong_alias(__pthread_cleanup_push_defer, _pthread_cleanup_push_defer) + +void +attribute_hidden +__pthread_cleanup_pop_restore(struct _pthread_cleanup_buffer * buffer, + int execute) +{ + pthread_descr self = thread_self(); + if (execute) buffer->__routine(buffer->__arg); + THREAD_SETMEM(self, p_cleanup, buffer->__prev); + THREAD_SETMEM(self, p_canceltype, buffer->__canceltype); + if (THREAD_GETMEM(self, p_canceled) && + THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE && + THREAD_GETMEM(self, p_canceltype) == PTHREAD_CANCEL_ASYNCHRONOUS) + __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); +} + +strong_alias(__pthread_cleanup_pop_restore, _pthread_cleanup_pop_restore) + +extern void __rpc_thread_destroy(void); +void +attribute_hidden internal_function +__pthread_perform_cleanup(char *currentframe) +{ + pthread_descr self = thread_self(); + struct _pthread_cleanup_buffer *c = THREAD_GETMEM(self, p_cleanup); + struct _pthread_cleanup_buffer *last; + + if (c != NULL) + while (FRAME_LEFT (currentframe, c)) + { + last = c; + c = c->__prev; + + if (c == NULL || FRAME_LEFT (last, c)) + { + c = NULL; + break; + } + } + + while (c != NULL) + { + c->__routine(c->__arg); + + last = c; + c = c->__prev; + + if (FRAME_LEFT (last, c)) + break; + } + +#ifdef __UCLIBC_HAS_RPC__ + /* And the TSD which needs special help. */ + if (THREAD_GETMEM(self, p_libc_specific[_LIBC_TSD_KEY_RPC_VARS]) != NULL) + __rpc_thread_destroy (); +#endif +} diff --git a/l4/pkg/uclibc/lib/libpthread/src/condvar.c b/l4/pkg/uclibc/lib/libpthread/src/condvar.c new file mode 100644 index 00000000..d8a90c3c --- /dev/null +++ b/l4/pkg/uclibc/lib/libpthread/src/condvar.c @@ -0,0 +1,317 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* and Pavel Krauz (krauz@fsid.cvut.cz). */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +/* Condition variables */ + +#include +#include +#include +#include "pthread.h" +#include "internals.h" +#include "spinlock.h" +#include "queue.h" +#include "restart.h" + +int +attribute_hidden +__pthread_cond_init(pthread_cond_t *cond, + const pthread_condattr_t *cond_attr) +{ + __pthread_init_lock(&cond->__c_lock); + cond->__c_waiting = NULL; + return 0; +} +strong_alias (__pthread_cond_init, pthread_cond_init) + +int +attribute_hidden +__pthread_cond_destroy(pthread_cond_t *cond) +{ + if (cond->__c_waiting != NULL) return EBUSY; + return 0; +} +strong_alias (__pthread_cond_destroy, pthread_cond_destroy) + +/* Function called by pthread_cancel to remove the thread from + waiting on a condition variable queue. */ + +static int cond_extricate_func(void *obj, pthread_descr th) +{ + __volatile__ pthread_descr self = thread_self(); + pthread_cond_t *cond = obj; + int did_remove = 0; + + __pthread_lock(&cond->__c_lock, self); + did_remove = remove_from_queue(&cond->__c_waiting, th); + __pthread_unlock(&cond->__c_lock); + + return did_remove; +} + +int +attribute_hidden +__pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) +{ + __volatile__ pthread_descr self = thread_self(); + pthread_extricate_if extr; + int already_canceled = 0; + int spurious_wakeup_count; + + /* Check whether the mutex is locked and owned by this thread. */ + if (mutex->__m_kind != PTHREAD_MUTEX_TIMED_NP + && mutex->__m_kind != PTHREAD_MUTEX_ADAPTIVE_NP + && mutex->__m_owner != self) + return EINVAL; + + /* Set up extrication interface */ + extr.pu_object = cond; + extr.pu_extricate_func = cond_extricate_func; + + /* Register extrication interface */ + THREAD_SETMEM(self, p_condvar_avail, 0); + __pthread_set_own_extricate_if(self, &extr); + + /* Atomically enqueue thread for waiting, but only if it is not + canceled. If the thread is canceled, then it will fall through the + suspend call below, and then call pthread_exit without + having to worry about whether it is still on the condition variable queue. + This depends on pthread_cancel setting p_canceled before calling the + extricate function. */ + + __pthread_lock(&cond->__c_lock, self); + if (!(THREAD_GETMEM(self, p_canceled) + && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE)) + enqueue(&cond->__c_waiting, self); + else + already_canceled = 1; + __pthread_unlock(&cond->__c_lock); + + if (already_canceled) { + __pthread_set_own_extricate_if(self, 0); + __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); + } + + pthread_mutex_unlock(mutex); + + spurious_wakeup_count = 0; + while (1) + { + suspend(self); + if (THREAD_GETMEM(self, p_condvar_avail) == 0 + && (THREAD_GETMEM(self, p_woken_by_cancel) == 0 + || THREAD_GETMEM(self, p_cancelstate) != PTHREAD_CANCEL_ENABLE)) + { + /* Count resumes that don't belong to us. */ + spurious_wakeup_count++; + continue; + } + break; + } + + __pthread_set_own_extricate_if(self, 0); + + /* Check for cancellation again, to provide correct cancellation + point behavior */ + + if (THREAD_GETMEM(self, p_woken_by_cancel) + && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) { + THREAD_SETMEM(self, p_woken_by_cancel, 0); + pthread_mutex_lock(mutex); + __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); + } + + /* Put back any resumes we caught that don't belong to us. */ + while (spurious_wakeup_count--) + restart(self); + + pthread_mutex_lock(mutex); + return 0; +} +strong_alias (__pthread_cond_wait, pthread_cond_wait) + +static int +pthread_cond_timedwait_relative(pthread_cond_t *cond, + pthread_mutex_t *mutex, + const struct timespec * abstime) +{ + __volatile__ pthread_descr self = thread_self(); + int already_canceled = 0; + pthread_extricate_if extr; + int spurious_wakeup_count; + + /* Check whether the mutex is locked and owned by this thread. */ + if (mutex->__m_kind != PTHREAD_MUTEX_TIMED_NP + && mutex->__m_kind != PTHREAD_MUTEX_ADAPTIVE_NP + && mutex->__m_owner != self) + return EINVAL; + + /* Set up extrication interface */ + extr.pu_object = cond; + extr.pu_extricate_func = cond_extricate_func; + + /* Register extrication interface */ + THREAD_SETMEM(self, p_condvar_avail, 0); + __pthread_set_own_extricate_if(self, &extr); + + /* Enqueue to wait on the condition and check for cancellation. */ + __pthread_lock(&cond->__c_lock, self); + if (!(THREAD_GETMEM(self, p_canceled) + && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE)) + enqueue(&cond->__c_waiting, self); + else + already_canceled = 1; + __pthread_unlock(&cond->__c_lock); + + if (already_canceled) { + __pthread_set_own_extricate_if(self, 0); + __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); + } + + pthread_mutex_unlock(mutex); + + spurious_wakeup_count = 0; + while (1) + { + if (!timedsuspend(self, abstime)) { + int was_on_queue; + + /* __pthread_lock will queue back any spurious restarts that + may happen to it. */ + + __pthread_lock(&cond->__c_lock, self); + was_on_queue = remove_from_queue(&cond->__c_waiting, self); + __pthread_unlock(&cond->__c_lock); + + if (was_on_queue) { + __pthread_set_own_extricate_if(self, 0); + pthread_mutex_lock(mutex); + return ETIMEDOUT; + } + + /* Eat the outstanding restart() from the signaller */ + suspend(self); + } + + if (THREAD_GETMEM(self, p_condvar_avail) == 0 + && (THREAD_GETMEM(self, p_woken_by_cancel) == 0 + || THREAD_GETMEM(self, p_cancelstate) != PTHREAD_CANCEL_ENABLE)) + { + /* Count resumes that don't belong to us. */ + spurious_wakeup_count++; + continue; + } + break; + } + + __pthread_set_own_extricate_if(self, 0); + + /* The remaining logic is the same as in other cancellable waits, + such as pthread_join sem_wait or pthread_cond wait. */ + + if (THREAD_GETMEM(self, p_woken_by_cancel) + && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) { + THREAD_SETMEM(self, p_woken_by_cancel, 0); + pthread_mutex_lock(mutex); + __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); + } + + /* Put back any resumes we caught that don't belong to us. */ + while (spurious_wakeup_count--) + restart(self); + + pthread_mutex_lock(mutex); + return 0; +} + +int +attribute_hidden +__pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, + const struct timespec * abstime) +{ + /* Indirect call through pointer! */ + return pthread_cond_timedwait_relative(cond, mutex, abstime); +} +strong_alias (__pthread_cond_timedwait, pthread_cond_timedwait) + +int __pthread_cond_signal(pthread_cond_t *cond) +{ + pthread_descr th; + + __pthread_lock(&cond->__c_lock, NULL); + th = dequeue(&cond->__c_waiting); + __pthread_unlock(&cond->__c_lock); + if (th != NULL) { + th->p_condvar_avail = 1; + WRITE_MEMORY_BARRIER(); + restart(th); + } + return 0; +} +strong_alias (__pthread_cond_signal, pthread_cond_signal) + +int +attribute_hidden +__pthread_cond_broadcast(pthread_cond_t *cond) +{ + pthread_descr tosignal, th; + + __pthread_lock(&cond->__c_lock, NULL); + /* Copy the current state of the waiting queue and empty it */ + tosignal = cond->__c_waiting; + cond->__c_waiting = NULL; + __pthread_unlock(&cond->__c_lock); + /* Now signal each process in the queue */ + while ((th = dequeue(&tosignal)) != NULL) { + th->p_condvar_avail = 1; + WRITE_MEMORY_BARRIER(); + restart(th); + } + return 0; +} +strong_alias (__pthread_cond_broadcast, pthread_cond_broadcast) + +int +attribute_hidden +__pthread_condattr_init(pthread_condattr_t *attr) +{ + return 0; +} +strong_alias (__pthread_condattr_init, pthread_condattr_init) + +int +attribute_hidden +__pthread_condattr_destroy(pthread_condattr_t *attr) +{ + return 0; +} +strong_alias (__pthread_condattr_destroy, pthread_condattr_destroy) + +int pthread_condattr_getpshared (const pthread_condattr_t *attr, int *pshared) +{ + *pshared = PTHREAD_PROCESS_PRIVATE; + return 0; +} + +int pthread_condattr_setpshared (pthread_condattr_t *attr, int pshared) +{ + if (pshared != PTHREAD_PROCESS_PRIVATE && pshared != PTHREAD_PROCESS_SHARED) + return EINVAL; + + /* For now it is not possible to shared a conditional variable. */ + if (pshared != PTHREAD_PROCESS_PRIVATE) + return ENOSYS; + + return 0; +} diff --git a/l4/pkg/uclibc/lib/libpthread/src/descr.h b/l4/pkg/uclibc/lib/libpthread/src/descr.h new file mode 100644 index 00000000..a70b8d37 --- /dev/null +++ b/l4/pkg/uclibc/lib/libpthread/src/descr.h @@ -0,0 +1,236 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +#ifndef _DESCR_H +#define _DESCR_H 1 + +#define __need_res_state +#include +#include +#include +#include +#include +#include + +/* Fast thread-specific data internal to libc. */ +enum __libc_tsd_key_t { _LIBC_TSD_KEY_MALLOC = 0, + _LIBC_TSD_KEY_DL_ERROR, + _LIBC_TSD_KEY_RPC_VARS, + _LIBC_TSD_KEY_LOCALE, + _LIBC_TSD_KEY_CTYPE_B, + _LIBC_TSD_KEY_CTYPE_TOLOWER, + _LIBC_TSD_KEY_CTYPE_TOUPPER, + _LIBC_TSD_KEY_N }; + +/* The type of thread descriptors */ +typedef struct _pthread_descr_struct *pthread_descr; + + +/* Some more includes. */ +#include +//#include + + +/* Arguments passed to thread creation routine */ +struct pthread_start_args { + void *(*start_routine)(void *); /* function to run */ + void *arg; /* its argument */ +}; + + +/* Callback interface for removing the thread from waiting on an + object if it is cancelled while waiting or about to wait. + This hold a pointer to the object, and a pointer to a function + which ``extricates'' the thread from its enqueued state. + The function takes two arguments: pointer to the wait object, + and a pointer to the thread. It returns 1 if an extrication + actually occured, and hence the thread must also be signalled. + It returns 0 if the thread had already been extricated. */ +typedef struct _pthread_extricate_struct { + void *pu_object; + int (*pu_extricate_func)(void *, pthread_descr); +} pthread_extricate_if; + + +/* Atomic counter made possible by compare_and_swap */ +struct pthread_atomic { + long p_count; + int p_spinlock; +}; + + +/* Context info for read write locks. The pthread_rwlock_info structure + is information about a lock that has been read-locked by the thread + in whose list this structure appears. The pthread_rwlock_context + is embedded in the thread context and contains a pointer to the + head of the list of lock info structures, as well as a count of + read locks that are untracked, because no info structure could be + allocated for them. */ +struct _pthread_rwlock_t; +typedef struct _pthread_rwlock_info { + struct _pthread_rwlock_info *pr_next; + struct _pthread_rwlock_t *pr_lock; + int pr_lock_count; +} pthread_readlock_info; + + +/* We keep thread specific data in a special data structure, a two-level + array. The top-level array contains pointers to dynamically allocated + arrays of a certain number of data pointers. So we can implement a + sparse array. Each dynamic second-level array has + PTHREAD_KEY_2NDLEVEL_SIZE + entries. This value shouldn't be too large. */ +#define PTHREAD_KEY_2NDLEVEL_SIZE 32 + +/* We need to address PTHREAD_KEYS_MAX key with PTHREAD_KEY_2NDLEVEL_SIZE + keys in each subarray. */ +#define PTHREAD_KEY_1STLEVEL_SIZE \ + ((PTHREAD_KEYS_MAX + PTHREAD_KEY_2NDLEVEL_SIZE - 1) \ + / PTHREAD_KEY_2NDLEVEL_SIZE) + + +union dtv; + +struct _pthread_descr_struct +{ +#if !defined USE_TLS || !TLS_DTV_AT_TP || INCLUDE_TLS_PADDING + /* This overlaps tcbhead_t (see tls.h), as used for TLS without threads. */ + union + { + struct + { + void *tcb; /* Pointer to the TCB. This is not always + the address of this thread descriptor. */ + union dtv *dtvp; + pthread_descr self; /* Pointer to this structure */ + int multiple_threads; + uintptr_t sysinfo; + } data; + void *__padding[16]; + } p_header; +# define p_multiple_threads p_header.data.multiple_threads +#elif defined TLS_MULTIPLE_THREADS_IN_TCB && TLS_MULTIPLE_THREADS_IN_TCB + int p_multiple_threads; +#endif + + pthread_descr p_nextlive, p_prevlive; + /* Double chaining of active threads */ + pthread_descr p_nextwaiting; /* Next element in the queue holding the thr */ + pthread_descr p_nextlock; /* can be on a queue and waiting on a lock */ + pthread_t p_tid; /* Thread identifier */ + + int p_priority; /* Thread priority (== 0 if not realtime) */ + int p_sched_policy; + + + l4_cap_idx_t p_thsem_cap; + l4_cap_idx_t p_th_cap; + struct _pthread_fastlock * p_lock; /* Spinlock for synchronized accesses */ + sigjmp_buf * p_cancel_jmp; /* where to siglongjmp on a cancel or NULL */ + char p_terminated; /* true if terminated e.g. by pthread_exit */ + char p_detached; /* true if detached */ + char p_exited; /* true if the assoc. process terminated */ + void * p_retval; /* placeholder for return value */ + int p_retcode; /* placeholder for return code */ + pthread_descr p_joining; /* thread joining on that thread or NULL */ + struct _pthread_cleanup_buffer * p_cleanup; /* cleanup functions */ + char p_cancelstate; /* cancellation state */ + char p_canceltype; /* cancellation type (deferred/async) */ + char p_canceled; /* cancellation request pending */ + struct pthread_start_args p_start_args; /* arguments for thread creation */ + void ** p_specific[PTHREAD_KEY_1STLEVEL_SIZE]; /* thread-specific data */ +#if !(USE_TLS && HAVE___THREAD) + void * p_libc_specific[_LIBC_TSD_KEY_N]; /* thread-specific data for libc */ + int * p_errnop; /* pointer to used errno variable */ + int p_errno; /* error returned by last system call */ + int * p_h_errnop; /* pointer to used h_errno variable */ + int p_h_errno; /* error returned by last netdb function */ + struct __res_state *p_resp; /* Pointer to resolver state */ +#endif + struct __res_state p_res; /* per-thread resolver state */ + int p_userstack; /* nonzero if the user provided the stack */ + void *p_guardaddr; /* address of guard area or NULL */ + size_t p_guardsize; /* size of guard area */ + struct pthread_atomic p_resume_count; /* number of times restart() was + called on thread */ + char p_woken_by_cancel; /* cancellation performed wakeup */ + char p_condvar_avail; /* flag if conditional variable became avail */ + char p_sem_avail; /* flag if semaphore became available */ + pthread_extricate_if *p_extricate; /* See above */ + pthread_readlock_info *p_readlock_list; /* List of readlock info structs */ + pthread_readlock_info *p_readlock_free; /* Free list of structs */ + int p_untracked_readlock_count; /* Readlocks not tracked by list */ + int p_inheritsched; /* copied from the thread attribute */ +#ifdef USE_TLS + char *p_stackaddr; /* Stack address. */ +#endif + size_t p_alloca_cutoff; /* Maximum size which should be allocated + using alloca() instead of malloc(). */ + /* New elements must be added at the end. */ +} __attribute__ ((aligned(32))); /* We need to align the structure so that + doubles are aligned properly. This is 8 + bytes on MIPS and 16 bytes on MIPS64. + 32 bytes might give better cache + utilization. */ + + + +/* Limit between the stack of the initial thread (above) and the + stacks of other threads (below). Aligned on a STACK_SIZE boundary. + Initially 0, meaning that the current thread is (by definition) + the initial thread. */ + +extern char *__pthread_initial_thread_bos; + +/* Descriptor of the initial thread */ + +extern struct _pthread_descr_struct __pthread_initial_thread; + +/* Limits of the thread manager stack. */ + +extern char *__pthread_manager_thread_bos; +extern char *__pthread_manager_thread_tos; + +/* Descriptor of the manager thread */ + +extern struct _pthread_descr_struct __pthread_manager_thread; +extern pthread_descr __pthread_manager_threadp L4_HIDDEN; + +/* Indicate whether at least one thread has a user-defined stack (if 1), + or all threads have stacks supplied by LinuxThreads (if 0). */ + +extern int __pthread_nonstandard_stacks; + +/* The max size of the thread stack segments. If the default + THREAD_SELF implementation is used, this must be a power of two and + a multiple of PAGE_SIZE. */ +#ifndef STACK_SIZE +#define STACK_SIZE (2 * 1024 * 1024) +#endif + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#ifndef CURRENT_STACK_FRAME +#define CURRENT_STACK_FRAME ({ char __csf; &__csf; }) +#endif + +/* Recover thread descriptor for the current thread */ + +extern pthread_descr __pthread_find_self (void) __attribute__ ((pure)); + +static __inline__ pthread_descr thread_self (void) __attribute__ ((pure)); +static __inline__ pthread_descr thread_self (void) +{ return (pthread_descr)(l4_utcb_tcr()->user[0]); } + +#endif /* descr.h */ diff --git a/l4/pkg/uclibc/lib/libpthread/src/errno-loc.c b/l4/pkg/uclibc/lib/libpthread/src/errno-loc.c new file mode 100644 index 00000000..79248c0c --- /dev/null +++ b/l4/pkg/uclibc/lib/libpthread/src/errno-loc.c @@ -0,0 +1,53 @@ +/* MT support function to get address of `errno' variable, linuxthreads + version. + Copyright (C) 1996, 1998, 2002, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include "internals.h" +#include +//#include +#if defined USE_TLS && USE_TLS +#define USE___THREAD 1 +#endif + +#define SINGLE_THREAD_P \ + __builtin_expect (THREAD_GETMEM (thread_self(), \ + p_header.data.multiple_threads) == 0, 1) + +#if ! USE___THREAD && !RTLD_PRIVATE_ERRNO +#undef errno +extern int errno; +#endif + +int * +#if ! USE___THREAD +weak_const_function +#endif +__errno_location (void) +{ +#if ! USE___THREAD && !defined NOT_IN_libc + if (! SINGLE_THREAD_P) + { + pthread_descr self = thread_self(); + return LIBC_THREAD_GETMEM (self, p_errnop); + } +#endif + return &errno; +} +libc_hidden_def (__errno_location) diff --git a/l4/pkg/uclibc/lib/libpthread/src/errno.c b/l4/pkg/uclibc/lib/libpthread/src/errno.c new file mode 100644 index 00000000..03c23f86 --- /dev/null +++ b/l4/pkg/uclibc/lib/libpthread/src/errno.c @@ -0,0 +1,48 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +/* Define the location of errno for the remainder of the C library */ + +#include +#include +#include +#include "pthread.h" +#include "internals.h" + +#if !USE_TLS || !HAVE___THREAD +/* The definition in libc is sufficient if we use TLS. */ +int * +__errno_location (void) +{ + pthread_descr self = thread_self(); + return THREAD_GETMEM (self, p_errnop); +} + +int * +__h_errno_location (void) +{ + pthread_descr self = thread_self(); + return THREAD_GETMEM (self, p_h_errnop); +} + +#if 0 +/* Return thread specific resolver state. */ +struct __res_state * +__res_state (void) +{ + pthread_descr self = thread_self(); + return THREAD_GETMEM (self, p_resp); +} +#endif +#endif diff --git a/l4/pkg/uclibc/lib/libpthread/src/forward.c b/l4/pkg/uclibc/lib/libpthread/src/forward.c new file mode 100644 index 00000000..9d25d9a0 --- /dev/null +++ b/l4/pkg/uclibc/lib/libpthread/src/forward.c @@ -0,0 +1,145 @@ +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + +/* psm: keep this before internals.h */ + +#include "internals.h" + +/* Pointers to the libc functions. */ +struct pthread_functions __libc_pthread_functions attribute_hidden; + + +# define FORWARD2(name, rettype, decl, params, defaction) \ +rettype \ +name decl \ +{ \ + if (__libc_pthread_functions.ptr_##name == NULL) \ + defaction; \ + \ + return __libc_pthread_functions.ptr_##name params; \ +} + +# define FORWARD(name, decl, params, defretval) \ + FORWARD2 (name, int, decl, params, return defretval) + +FORWARD (pthread_attr_destroy, (pthread_attr_t *attr), (attr), 0) + +FORWARD (pthread_attr_init, (pthread_attr_t *attr), (attr), 0) + +FORWARD (pthread_attr_getdetachstate, + (const pthread_attr_t *attr, int *detachstate), (attr, detachstate), + 0) +FORWARD (pthread_attr_setdetachstate, (pthread_attr_t *attr, int detachstate), + (attr, detachstate), 0) + +FORWARD (pthread_attr_getinheritsched, + (const pthread_attr_t *attr, int *inherit), (attr, inherit), 0) +FORWARD (pthread_attr_setinheritsched, (pthread_attr_t *attr, int inherit), + (attr, inherit), 0) + +FORWARD (pthread_attr_getschedparam, + (const pthread_attr_t *attr, struct sched_param *param), + (attr, param), 0) +FORWARD (pthread_attr_setschedparam, + (pthread_attr_t *attr, const struct sched_param *param), + (attr, param), 0) + +FORWARD (pthread_attr_getschedpolicy, + (const pthread_attr_t *attr, int *policy), (attr, policy), 0) +FORWARD (pthread_attr_setschedpolicy, (pthread_attr_t *attr, int policy), + (attr, policy), 0) + +FORWARD (pthread_attr_getscope, + (const pthread_attr_t *attr, int *scope), (attr, scope), 0) +FORWARD (pthread_attr_setscope, (pthread_attr_t *attr, int scope), + (attr, scope), 0) + + +FORWARD (pthread_condattr_destroy, (pthread_condattr_t *attr), (attr), 0) +FORWARD (pthread_condattr_init, (pthread_condattr_t *attr), (attr), 0) + + +FORWARD (pthread_cond_broadcast, (pthread_cond_t *cond), (cond), 0) + +FORWARD (pthread_cond_destroy, (pthread_cond_t *cond), (cond), 0) + +FORWARD (pthread_cond_init, + (pthread_cond_t *cond, const pthread_condattr_t *cond_attr), + (cond, cond_attr), 0) + +FORWARD (pthread_cond_signal, (pthread_cond_t *cond), (cond), 0) + +FORWARD (pthread_cond_wait, (pthread_cond_t *cond, pthread_mutex_t *mutex), + (cond, mutex), 0) + +FORWARD (pthread_cond_timedwait, + (pthread_cond_t *cond, pthread_mutex_t *mutex, + const struct timespec *abstime), (cond, mutex, abstime), 0) + + +FORWARD (pthread_equal, (pthread_t thread1, pthread_t thread2), + (thread1, thread2), 1) + + +/* Use an alias to avoid warning, as pthread_exit is declared noreturn. */ +FORWARD2 (__pthread_exit, void, (void *retval), (retval), exit (EXIT_SUCCESS)) +strong_alias (__pthread_exit, pthread_exit) + + +FORWARD (pthread_getschedparam, + (pthread_t target_thread, int *policy, struct sched_param *param), + (target_thread, policy, param), 0) +FORWARD (pthread_setschedparam, + (pthread_t target_thread, int policy, + const struct sched_param *param), (target_thread, policy, param), 0) + + +FORWARD (pthread_mutex_destroy, (pthread_mutex_t *mutex), (mutex), 0) + +FORWARD (pthread_mutex_init, + (pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr), + (mutex, mutexattr), 0) +strong_alias(pthread_mutex_init, __pthread_mutex_init) + +FORWARD (pthread_mutex_lock, (pthread_mutex_t *mutex), (mutex), 0) +strong_alias(pthread_mutex_lock, __pthread_mutex_lock) + +FORWARD (pthread_mutex_trylock, (pthread_mutex_t *mutex), (mutex), 0) +strong_alias(pthread_mutex_trylock, __pthread_mutex_trylock) + +FORWARD (pthread_mutex_unlock, (pthread_mutex_t *mutex), (mutex), 0) +strong_alias(pthread_mutex_unlock, __pthread_mutex_unlock) + +FORWARD2 (pthread_self, pthread_t, (void), (), return 0) + + +FORWARD (pthread_setcancelstate, (int state, int *oldstate), (state, oldstate), + 0) + +FORWARD (pthread_setcanceltype, (int type, int *oldtype), (type, oldtype), 0) + +FORWARD2 (_pthread_cleanup_push, void, (struct _pthread_cleanup_buffer * buffer, void (*routine)(void *), void * arg), (buffer, routine, arg), return) +FORWARD2 (_pthread_cleanup_push_defer, void, (struct _pthread_cleanup_buffer * buffer, void (*routine)(void *), void * arg), (buffer, routine, arg), return) + +FORWARD2 (_pthread_cleanup_pop, void, (struct _pthread_cleanup_buffer * buffer, int execute), (buffer, execute), return) +FORWARD2 (_pthread_cleanup_pop_restore, void, (struct _pthread_cleanup_buffer * buffer, int execute), (buffer, execute), return) diff --git a/l4/pkg/uclibc/lib/libpthread/src/internals.h b/l4/pkg/uclibc/lib/libpthread/src/internals.h new file mode 100644 index 00000000..94883d9c --- /dev/null +++ b/l4/pkg/uclibc/lib/libpthread/src/internals.h @@ -0,0 +1,601 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +#ifndef _INTERNALS_H +#define _INTERNALS_H 1 + +#include "uClibc-glue.h" + +/* Internal data structures */ + +/* Includes */ + +#include +//l4/#include +#include +#include +//l4/#include +#include +//l4/#include +#include + +#include + +#include + +#ifdef USE_TLS +#include +#endif +#include "descr.h" + +#include "semaphore.h" +#include + +#ifndef THREAD_GETMEM +# define THREAD_GETMEM(descr, member) descr->member +#endif +#ifndef THREAD_GETMEM_NC +# define THREAD_GETMEM_NC(descr, member, idx) descr->member[idx] +#endif +#ifndef THREAD_SETMEM +# define THREAD_SETMEM(descr, member, value) descr->member = (value) +#endif +#ifndef THREAD_SETMEM_NC +# define THREAD_SETMEM_NC(descr, member, idx, value) descr->member[idx] = (value) +#endif + +#if !defined NOT_IN_libc +# define LIBC_THREAD_GETMEM(descr, member) THREAD_GETMEM (descr, member) +# define LIBC_THREAD_SETMEM(descr, member, value) \ + THREAD_SETMEM (descr, member, value) +#else +# define LIBC_THREAD_GETMEM(descr, member) descr->member +# define LIBC_THREAD_SETMEM(descr, member, value) descr->member = (value) +#endif + +typedef void (*destr_function)(void *); + +struct pthread_key_struct { + int in_use; /* already allocated? */ + destr_function destr; /* destruction routine */ +}; + +#include +#define UNIMPL(x...) do { outstring("UNIMPL: " x "\n"); } while(0) + + +#define PTHREAD_START_ARGS_INITIALIZER(fct) \ + { (void *(*) (void *)) fct, NULL } + + +/* The type of thread handles. */ +typedef l4_utcb_t *pthread_handle; + + +/* The type of messages sent to the thread manager thread */ + +enum pthread_request_rq { /* Request kind */ + REQ_CREATE, REQ_FREE, REQ_PROCESS_EXIT, REQ_MAIN_THREAD_EXIT, + REQ_POST, REQ_DEBUG, REQ_KICK, REQ_FOR_EACH_THREAD, + REQ_THREAD_EXIT +}; + +struct pthread_request { + pthread_descr req_thread; /* Thread doing the request */ + enum pthread_request_rq req_kind; + union { /* Arguments for request */ + struct { /* For REQ_CREATE: */ + const pthread_attr_t * attr; /* thread attributes */ + void * (*fn)(void *); /* start function */ + void * arg; /* argument to start function */ + } create; + struct { /* For REQ_FREE: */ + pthread_t thread_id; /* identifier of thread to free */ + } free; + struct { /* For REQ_PROCESS_EXIT: */ + int code; /* exit status */ + } exit; + void * post; /* For REQ_POST: the semaphore */ + struct { /* For REQ_FOR_EACH_THREAD: callback */ + void (*fn)(void *, pthread_descr); + void *arg; + } for_each; + } req_args; +}; + + +/* First free thread */ +extern l4_utcb_t *__pthread_first_free_handle attribute_hidden; + +/* Descriptor of the main thread */ + +extern pthread_descr __pthread_main_thread; + +/* File descriptor for sending requests to the thread manager. + Initially -1, meaning that __pthread_initialize_manager must be called. */ + +extern l4_cap_idx_t __pthread_manager_request; + +/* Other end of the pipe for sending requests to the thread manager. */ + +/* Maximum stack size. */ +extern size_t __pthread_max_stacksize; + +/* Default stack size for new threads. */ +extern size_t __pthread_default_stacksize; + +/* Pending request for a process-wide exit */ + +extern int __pthread_exit_requested, __pthread_exit_code; + +/* Set to 1 by gdb if we're debugging */ + +extern __volatile__ int __pthread_threads_debug; + +/* Globally enabled events. */ +//extern __volatile__ td_thr_events_t __pthread_threads_events; + +/* Pointer to descriptor of thread with last event. */ +//extern __volatile__ pthread_descr __pthread_last_event; + +/* Flag which tells whether we are executing on SMP kernel. */ +extern int __pthread_smp_kernel; + +inline static void __pthread_send_manager_rq(struct pthread_request *r, int block) +{ + if (l4_is_invalid_cap(__pthread_manager_request)) + return; + __builtin_memcpy(l4_utcb_mr()->mr, r, sizeof(struct pthread_request)); + l4_msgtag_t tag + = l4_msgtag(0, + (sizeof(struct pthread_request) + sizeof(l4_umword_t) - 1) / sizeof(l4_umword_t), + 0, L4_MSGTAG_SCHEDULE); + if (block) + l4_ipc_call(__pthread_manager_request, l4_utcb(), tag, L4_IPC_NEVER); + else + l4_ipc_send(__pthread_manager_request, l4_utcb(), tag, L4_IPC_NEVER); +} + +/* Return the handle corresponding to a thread id */ + +static __inline__ pthread_handle thread_handle(pthread_t id) +{ + return (l4_utcb_t*)id; //&__pthread_handles[id % PTHREAD_THREADS_MAX]; +} + +static inline pthread_descr handle_to_descr(pthread_handle h) +{ return (pthread_descr)(l4_utcb_tcr_u(h)->user[0]); } + +static inline struct _pthread_fastlock *handle_to_lock(pthread_handle h) +{ return (struct _pthread_fastlock *)(&l4_utcb_tcr_u(h)->user[1]); } + +/* Validate a thread handle. Must have acquired h->h_spinlock before. */ + +static __inline__ int invalid_handle(pthread_handle h, pthread_t id) +{ + return h != id || handle_to_descr(h) == NULL + || handle_to_descr(h)->p_tid != id || handle_to_descr(h)->p_terminated; +} + +static __inline__ int nonexisting_handle(pthread_handle h, pthread_t id) +{ + return handle_to_descr(h) == NULL || handle_to_descr(h)->p_tid != id; +} + +/* Fill in defaults left unspecified by pt-machine.h. */ + +/* We round up a value with page size. */ +#ifndef page_roundup +#define page_roundup(v,p) ((((size_t) (v)) + (p) - 1) & ~((p) - 1)) +#endif + +/* The page size we can get from the system. This should likely not be + changed by the machine file but, you never know. */ +#ifndef PAGE_SIZE +#define PAGE_SIZE (L4_PAGESIZE) +#endif + +/* The initial size of the thread stack. Must be a multiple of PAGE_SIZE. */ +#ifndef INITIAL_STACK_SIZE +#define INITIAL_STACK_SIZE (4 * PAGE_SIZE) +#endif + +/* Size of the thread manager stack. The "- 32" avoids wasting space + with some malloc() implementations. */ +#ifndef THREAD_MANAGER_STACK_SIZE +#define THREAD_MANAGER_STACK_SIZE (2 * PAGE_SIZE - 32) +#endif + +/* The base of the "array" of thread stacks. The array will grow down from + here. Defaults to the calculated bottom of the initial application + stack. */ +#ifndef THREAD_STACK_START_ADDRESS +#define THREAD_STACK_START_ADDRESS __pthread_initial_thread_bos +#endif + +/* If MEMORY_BARRIER isn't defined in pt-machine.h, assume the + architecture doesn't need a memory barrier instruction (e.g. Intel + x86). Still we need the compiler to respect the barrier and emit + all outstanding operations which modify memory. Some architectures + distinguish between full, read and write barriers. */ + +#ifndef MEMORY_BARRIER +#define MEMORY_BARRIER() __asm__ ("" : : : "memory") +#endif +#ifndef READ_MEMORY_BARRIER +#define READ_MEMORY_BARRIER() MEMORY_BARRIER() +#endif +#ifndef WRITE_MEMORY_BARRIER +#define WRITE_MEMORY_BARRIER() MEMORY_BARRIER() +#endif + +/* Max number of times we must spin on a spinlock calling sched_yield(). + After MAX_SPIN_COUNT iterations, we put the calling thread to sleep. */ + +#ifndef MAX_SPIN_COUNT +#define MAX_SPIN_COUNT 50 +#endif + +/* Max number of times the spinlock in the adaptive mutex implementation + spins actively on SMP systems. */ + +#ifndef MAX_ADAPTIVE_SPIN_COUNT +#define MAX_ADAPTIVE_SPIN_COUNT 100 +#endif + +/* Duration of sleep (in nanoseconds) when we can't acquire a spinlock + after MAX_SPIN_COUNT iterations of sched_yield(). + With the 2.0 and 2.1 kernels, this MUST BE > 2ms. + (Otherwise the kernel does busy-waiting for realtime threads, + giving other threads no chance to run.) */ + +#ifndef SPIN_SLEEP_DURATION +#define SPIN_SLEEP_DURATION 2000001 +#endif + +/* Defined and used in libc.so. */ +extern int __libc_multiple_threads L4_HIDDEN; +extern int __librt_multiple_threads; + +/* Debugging */ + +#ifdef DEBUG +#include +#define ASSERT assert +#define MSG __pthread_message +#else +#define ASSERT(x) +#define MSG(msg,arg...) +#endif + +# define INIT_THREAD_SELF(descr, nr) do { l4_utcb_tcr()->user[0] = (l4_umword_t)descr; } while (0) + + + +/* Internal global functions */ +__BEGIN_DECLS +extern int __pthread_l4_initialize_main_thread(pthread_descr th) attribute_hidden; +extern void __l4_add_utcbs(l4_addr_t start, l4_addr_t utcbs_end); + + +extern int __pthread_sched_idle_prio; +extern int __pthread_sched_other_prio; +extern int __pthread_sched_rr_prio_min; +extern int __pthread_sched_rr_prio_max; + + +extern void __pthread_cleanup_push(struct _pthread_cleanup_buffer * buffer, + void (*routine)(void *), void * arg); +extern void __pthread_cleanup_pop(struct _pthread_cleanup_buffer * buffer, + int execute); +extern void __pthread_cleanup_pop_restore(struct _pthread_cleanup_buffer * buffer, + int execute); +extern void __pthread_cleanup_push_defer(struct _pthread_cleanup_buffer * buffer, + void (*routine)(void *), void * arg); + +extern void __pthread_do_exit (void *retval, char *currentframe) + __attribute__ ((__noreturn__)); +extern void __pthread_destroy_specifics (void); +extern void __pthread_perform_cleanup (char *currentframe) internal_function; +extern void __pthread_init_max_stacksize (void); +extern int __pthread_initialize_manager (void); +extern void __pthread_message (const char * fmt, ...); +extern int __pthread_manager (void *reqfd); +extern int __pthread_start_manager (pthread_descr mgr) L4_HIDDEN; +extern int __pthread_manager_event (void *reqfd); +extern void __pthread_manager_sighandler (int sig); +extern void __pthread_reset_main_thread (void); +extern void __pthread_once_fork_prepare (void); +extern void __pthread_once_fork_parent (void); +extern void __pthread_once_fork_child (void); +extern void __flockfilelist (void); +extern void __funlockfilelist (void); +extern void __fresetlockfiles (void); +extern void __pthread_manager_adjust_prio (int thread_prio); +extern void __pthread_initialize_minimal (void); + +extern int __pthread_attr_setguardsize (pthread_attr_t *__attr, + size_t __guardsize); +extern int __pthread_attr_getguardsize (const pthread_attr_t *__attr, + size_t *__guardsize); +#if 0 /* uClibc: deprecated stuff disabled */ +extern int __pthread_attr_setstackaddr (pthread_attr_t *__attr, + void *__stackaddr); +extern int __pthread_attr_getstackaddr (const pthread_attr_t *__attr, + void **__stackaddr); +#endif +extern int __pthread_attr_setstacksize (pthread_attr_t *__attr, + size_t __stacksize); +extern int __pthread_attr_getstacksize (const pthread_attr_t *__attr, + size_t *__stacksize); +extern int __pthread_attr_setstack (pthread_attr_t *__attr, void *__stackaddr, + size_t __stacksize); +extern int __pthread_attr_getstack (const pthread_attr_t *__attr, void **__stackaddr, + size_t *__stacksize); +extern int __pthread_attr_destroy (pthread_attr_t *attr); +extern int __pthread_attr_setdetachstate (pthread_attr_t *attr, + int detachstate); +extern int __pthread_attr_getdetachstate (const pthread_attr_t *attr, + int *detachstate); +extern int __pthread_attr_setschedparam (pthread_attr_t *attr, + const struct sched_param *param); +extern int __pthread_attr_getschedparam (const pthread_attr_t *attr, + struct sched_param *param); +extern int __pthread_attr_setschedpolicy (pthread_attr_t *attr, int policy); +extern int __pthread_attr_getschedpolicy (const pthread_attr_t *attr, + int *policy); +extern int __pthread_attr_setinheritsched (pthread_attr_t *attr, int inherit); +extern int __pthread_attr_getinheritsched (const pthread_attr_t *attr, + int *inherit); +extern int __pthread_attr_setscope (pthread_attr_t *attr, int scope); +extern int __pthread_attr_getscope (const pthread_attr_t *attr, int *scope); + +extern int __pthread_getconcurrency (void); +extern int __pthread_setconcurrency (int __level); +extern int __pthread_mutex_timedlock (pthread_mutex_t *__mutex, + const struct timespec *__abstime); +extern int __pthread_mutexattr_getpshared (const pthread_mutexattr_t *__attr, + int *__pshared); +extern int __pthread_mutexattr_setpshared (pthread_mutexattr_t *__attr, + int __pshared); +extern int __pthread_mutexattr_gettype (const pthread_mutexattr_t *__attr, + int *__kind); +extern void __pthread_kill_other_threads_np (void); +extern int __pthread_mutex_init (pthread_mutex_t *__mutex, + __const pthread_mutexattr_t *__mutex_attr); +extern int __pthread_mutex_destroy (pthread_mutex_t *__mutex); +extern int __pthread_mutex_lock (pthread_mutex_t *__mutex); +extern int __pthread_mutex_trylock (pthread_mutex_t *__mutex); +extern int __pthread_mutex_unlock (pthread_mutex_t *__mutex); + +extern int __pthread_cond_init (pthread_cond_t *cond, + const pthread_condattr_t *cond_attr); +extern int __pthread_cond_destroy (pthread_cond_t *cond); +extern int __pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex); +extern int __pthread_cond_timedwait (pthread_cond_t *cond, + pthread_mutex_t *mutex, + const struct timespec *abstime); +extern int __pthread_cond_signal (pthread_cond_t *cond); +extern int __pthread_cond_broadcast (pthread_cond_t *cond); +extern int __pthread_condattr_init (pthread_condattr_t *attr); +extern int __pthread_condattr_destroy (pthread_condattr_t *attr); +extern pthread_t __pthread_self (void); +extern pthread_descr __pthread_thread_self (void); +extern pthread_descr __pthread_self_stack (void) L4_HIDDEN; +extern int __pthread_equal (pthread_t thread1, pthread_t thread2); +extern void __pthread_exit (void *retval) +#if defined NOT_IN_libc && defined IS_IN_libpthread + attribute_noreturn +#endif + ; +extern int __pthread_getschedparam (pthread_t thread, int *policy, + struct sched_param *param) __THROW; +extern int __pthread_setschedparam (pthread_t thread, int policy, + const struct sched_param *param) __THROW; +extern int __pthread_setcancelstate (int state, int * oldstate); +extern int __pthread_setcanceltype (int type, int * oldtype); + +extern int __pthread_rwlock_timedrdlock (pthread_rwlock_t *__restrict __rwlock, + __const struct timespec *__restrict + __abstime); +extern int __pthread_rwlock_timedwrlock (pthread_rwlock_t *__restrict __rwlock, + __const struct timespec *__restrict + __abstime); +extern int __pthread_rwlockattr_destroy (pthread_rwlockattr_t *__attr); + +extern int __pthread_barrierattr_getpshared (__const pthread_barrierattr_t * + __restrict __attr, + int *__restrict __pshared); + +extern int __pthread_spin_lock (pthread_spinlock_t *__lock); +extern int __pthread_spin_trylock (pthread_spinlock_t *__lock); +extern int __pthread_spin_unlock (pthread_spinlock_t *__lock); +extern int __pthread_spin_init (pthread_spinlock_t *__lock, int __pshared); +extern int __pthread_spin_destroy (pthread_spinlock_t *__lock); + +/* Global pointers to old or new suspend functions */ + +extern void (*__pthread_restart)(pthread_descr); +extern void (*__pthread_suspend)(pthread_descr); +extern int (*__pthread_timedsuspend)(pthread_descr, const struct timespec *); + +/* Prototypes for some of the new semaphore functions. */ +extern int sem_post (sem_t * sem) __THROW; +extern int sem_init (sem_t *__sem, int __pshared, unsigned int __value) __THROW; +extern int sem_wait (sem_t *__sem); +extern int sem_trywait (sem_t *__sem) __THROW; +extern int sem_getvalue (sem_t *__restrict __sem, int *__restrict __sval) __THROW; +extern int sem_destroy (sem_t *__sem) __THROW; + +/* Prototypes for compatibility functions. */ +extern int __pthread_attr_init (pthread_attr_t *__attr); +extern int __pthread_create (pthread_t *__restrict __threadp, + const pthread_attr_t *__attr, + void *(*__start_routine) (void *), + void *__restrict __arg); + +/* The functions called the signal events. */ +extern void __linuxthreads_create_event (void); +extern void __linuxthreads_death_event (void); +extern void __linuxthreads_reap_event (void); + +/* This function is called to initialize the pthread library. */ +extern void __pthread_initialize (void); + +/* TSD. */ +extern int __pthread_internal_tsd_set (int key, const void * pointer); +extern void * __pthread_internal_tsd_get (int key); +extern void ** __attribute__ ((__const__)) + __pthread_internal_tsd_address (int key); +#if 0 +/* Sighandler wrappers. */ +extern void __pthread_sighandler(int signo, SIGCONTEXT ctx); +extern void __pthread_sighandler_rt(int signo, struct siginfo *si, + struct ucontext *uc); +extern void __pthread_null_sighandler(int sig); +extern int __pthread_sigaction (int sig, const struct sigaction *act, + struct sigaction *oact); +extern int __pthread_sigwait (const sigset_t *set, int *sig); +extern int __pthread_raise (int sig); +#endif +/* Cancellation. */ +extern int __pthread_enable_asynccancel (void) L4_HIDDEN; +extern void __pthread_disable_asynccancel (int oldtype) + internal_function L4_HIDDEN; + +/* The two functions are in libc.so and not exported. */ +extern int __libc_enable_asynccancel (void) L4_HIDDEN; +extern void __libc_disable_asynccancel (int oldtype) + internal_function L4_HIDDEN; + +/* The two functions are in libc.so and are exported. */ +extern int __librt_enable_asynccancel (void); +extern void __librt_disable_asynccancel (int oldtype) internal_function; + +extern void __pthread_cleanup_upto (__jmp_buf target, + char *targetframe) L4_HIDDEN; +#if 0 +extern pid_t __pthread_fork (struct fork_block *b) L4_HIDDEN; +#endif + +#define asm_handle(name) _asm_handle(name) +#define _asm_handle(name) #name +#define ASM_GLOBAL asm_handle(ASM_GLOBAL_DIRECTIVE) +#define ASM_CANCEL(name) asm_handle(C_SYMBOL_NAME(name)) + +#if !defined NOT_IN_libc +# define LIBC_CANCEL_ASYNC() \ + __libc_enable_asynccancel () +# define LIBC_CANCEL_RESET(oldtype) \ + __libc_disable_asynccancel (oldtype) +# define LIBC_CANCEL_HANDLED() \ + __asm__ (ASM_GLOBAL " " ASM_CANCEL(__libc_enable_asynccancel)); \ + __asm__ (ASM_GLOBAL " " ASM_CANCEL(__libc_disable_asynccancel)) +#elif defined IS_IN_libpthread +# define LIBC_CANCEL_ASYNC() \ + __pthread_enable_asynccancel () +# define LIBC_CANCEL_RESET(oldtype) \ + __pthread_disable_asynccancel (oldtype) +# define LIBC_CANCEL_HANDLED() \ + __asm__ (ASM_GLOBAL " " ASM_CANCEL(__pthread_enable_asynccancel)); \ + __asm__ (ASM_GLOBAL " " ASM_CANCEL(__pthread_disable_asynccancel)) +#elif defined IS_IN_librt +# define LIBC_CANCEL_ASYNC() \ + __librt_enable_asynccancel () +# define LIBC_CANCEL_RESET(oldtype) \ + __librt_disable_asynccancel (oldtype) +# define LIBC_CANCEL_HANDLED() \ + __asm__ (ASM_GLOBAL " " ASM_CANCEL(__librt_enable_asynccancel)); \ + __asm__ (ASM_GLOBAL " " ASM_CANCEL(__librt_disable_asynccancel)) +#else +# define LIBC_CANCEL_ASYNC() 0 /* Just a dummy value. */ +# define LIBC_CANCEL_RESET(val) ((void)(val)) /* Nothing, but evaluate it. */ +# define LIBC_CANCEL_HANDLED() /* Nothing. */ +#endif +extern int * __libc_pthread_init (const struct pthread_functions *functions); +__END_DECLS + + +#ifndef USE_TLS +# define __manager_thread (&__pthread_manager_thread) +#else +# define __manager_thread __pthread_manager_threadp +#endif + + +static inline int __pthread_getprio(int policy, int prio); +static inline int __pthread_getprio(int policy, int prio) +{ + switch (policy) + { + case SCHED_OTHER: + prio = 0; + break; + case SCHED_IDLE: + prio = 0; + break; + case SCHED_RR: + prio -= __pthread_sched_rr_prio_min; + break; + case SCHED_L4: + break; + default: + return -1; + } + + return prio; +} + +static inline int __pthread_l4_getprio(int policy, int posix_prio); +static inline int __pthread_l4_getprio(int policy, int posix_prio) +{ + switch (policy) + { + case SCHED_OTHER: + return __pthread_sched_other_prio; + case SCHED_IDLE: + return __pthread_sched_idle_prio; + case SCHED_RR: + return __pthread_sched_rr_prio_min + posix_prio; + case SCHED_L4: + return posix_prio; + default: + return -1; + } +} + + +static inline pthread_descr +check_thread_self (void); +static inline pthread_descr +check_thread_self (void) +{ + pthread_descr self = thread_self (); +#if defined THREAD_SELF && defined INIT_THREAD_SELF + if (self == __manager_thread) + { + /* A new thread might get a cancel signal before it is fully + initialized, so that the thread register might still point to the + manager thread. Double check that this is really the manager + thread. */ + self = handle_to_descr(l4_utcb()); + if (self != __manager_thread) + /* Oops, thread_self() isn't working yet.. */ + INIT_THREAD_SELF(self, self->p_nr); + } +#endif + return self; +} + +#endif /* internals.h */ diff --git a/l4/pkg/uclibc/lib/libpthread/src/join.c b/l4/pkg/uclibc/lib/libpthread/src/join.c new file mode 100644 index 00000000..0485bc8f --- /dev/null +++ b/l4/pkg/uclibc/lib/libpthread/src/join.c @@ -0,0 +1,208 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +/* Thread termination and joining */ + +#include +#include +#include +#include "pthread.h" +#include "internals.h" +#include "spinlock.h" +#include "restart.h" + +#include + +void __pthread_exit(void * retval) +{ + __pthread_do_exit (retval, CURRENT_STACK_FRAME); +} +strong_alias (__pthread_exit, pthread_exit) + +void __pthread_do_exit(void *retval, char *currentframe) +{ + pthread_descr self = thread_self(); + pthread_descr joining; + struct pthread_request request; + + /* Reset the cancellation flag to avoid looping if the cleanup handlers + contain cancellation points */ + THREAD_SETMEM(self, p_canceled, 0); + /* Call cleanup functions and destroy the thread-specific data */ + __pthread_perform_cleanup(currentframe); + __pthread_destroy_specifics(); + /* Store return value */ + __pthread_lock(THREAD_GETMEM(self, p_lock), self); + THREAD_SETMEM(self, p_retval, retval); + /* Say that we've terminated */ + THREAD_SETMEM(self, p_terminated, 1); + /* See if someone is joining on us */ + joining = THREAD_GETMEM(self, p_joining); + __pthread_unlock(THREAD_GETMEM(self, p_lock)); + /* Restart joining thread if any */ + if (joining != NULL) + { + restart(joining); + l4_sleep_forever(); + } + + /* If this is the initial thread, block until all threads have terminated. + If another thread calls exit, we'll be terminated from our signal + handler. */ + if (self == __pthread_main_thread && __pthread_manager_request >= 0) + { + request.req_thread = self; + request.req_kind = REQ_MAIN_THREAD_EXIT; + __pthread_send_manager_rq(&request, 1); + /* Main thread flushes stdio streams and runs atexit functions. + It also calls a handler within LinuxThreads which sends a process exit + request to the thread manager. */ + exit(0); + } + /* Threads other than the main one terminate without flushing stdio streams + or running atexit functions. */ + + //_exit(0); + + request.req_thread = self; + request.req_kind = REQ_THREAD_EXIT; + __pthread_send_manager_rq(&request, 1); + + l4_sleep_forever(); +} + +/* Function called by pthread_cancel to remove the thread from + waiting on a condition variable queue. */ + +static int join_extricate_func(void *obj, pthread_descr th) +{ + __volatile__ pthread_descr self = thread_self(); + pthread_handle handle = obj; + pthread_descr jo; + int did_remove = 0; + + __pthread_lock(handle_to_lock(handle), self); + jo = handle_to_descr(handle); + did_remove = jo->p_joining != NULL; + jo->p_joining = NULL; + __pthread_unlock(handle_to_lock(handle)); + + return did_remove; +} + +int pthread_join(pthread_t thread_id, void ** thread_return) +{ + __volatile__ pthread_descr self = thread_self(); + struct pthread_request request; + pthread_handle handle = thread_handle(thread_id); + pthread_descr th; + pthread_extricate_if extr; + int already_canceled = 0; + + /* Set up extrication interface */ + extr.pu_object = handle; + extr.pu_extricate_func = join_extricate_func; + + __pthread_lock(handle_to_lock(handle), self); + if (nonexisting_handle(handle, thread_id)) { + __pthread_unlock(handle_to_lock(handle)); + return ESRCH; + } + th = handle_to_descr(handle); + if (th == self) { + __pthread_unlock(handle_to_lock(handle)); + return EDEADLK; + } + /* If detached or already joined, error */ + if (th->p_detached || th->p_joining != NULL) { + __pthread_unlock(handle_to_lock(handle)); + return EINVAL; + } + /* If not terminated yet, suspend ourselves. */ + if (! th->p_terminated) { + /* Register extrication interface */ + __pthread_set_own_extricate_if(self, &extr); + if (!(THREAD_GETMEM(self, p_canceled) + && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE)) + th->p_joining = self; + else + already_canceled = 1; + __pthread_unlock(handle_to_lock(handle)); + + if (already_canceled) { + __pthread_set_own_extricate_if(self, 0); + __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); + } + + suspend(self); + /* Deregister extrication interface */ + __pthread_set_own_extricate_if(self, 0); + + /* This is a cancellation point */ + if (THREAD_GETMEM(self, p_woken_by_cancel) + && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) { + THREAD_SETMEM(self, p_woken_by_cancel, 0); + __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); + } + __pthread_lock(handle_to_lock(handle), self); + } + /* Get return value */ + if (thread_return != NULL) *thread_return = th->p_retval; + __pthread_unlock(handle_to_lock(handle)); + /* Send notification to thread manager */ + if (__pthread_manager_request >= 0) { + request.req_thread = self; + request.req_kind = REQ_FREE; + request.req_args.free.thread_id = thread_id; + __pthread_send_manager_rq(&request, 0); + } + return 0; +} + +int pthread_detach(pthread_t thread_id) +{ + int terminated; + struct pthread_request request; + pthread_handle handle = thread_handle(thread_id); + pthread_descr th; + + __pthread_lock(handle_to_lock(handle), NULL); + if (nonexisting_handle(handle, thread_id)) { + __pthread_unlock(handle_to_lock(handle)); + return ESRCH; + } + th = handle_to_descr(handle); + /* If already detached, error */ + if (th->p_detached) { + __pthread_unlock(handle_to_lock(handle)); + return EINVAL; + } + /* If already joining, don't do anything. */ + if (th->p_joining != NULL) { + __pthread_unlock(handle_to_lock(handle)); + return 0; + } + /* Mark as detached */ + th->p_detached = 1; + terminated = th->p_terminated; + __pthread_unlock(handle_to_lock(handle)); + /* If already terminated, notify thread manager to reclaim resources */ + if (terminated && __pthread_manager_request >= 0) { + request.req_thread = thread_self(); + request.req_kind = REQ_FREE; + request.req_args.free.thread_id = thread_id; + __pthread_send_manager_rq(&request, 0); + } + return 0; +} diff --git a/l4/pkg/uclibc/lib/libpthread/src/l4.cc b/l4/pkg/uclibc/lib/libpthread/src/l4.cc new file mode 100644 index 00000000..7fa3c506 --- /dev/null +++ b/l4/pkg/uclibc/lib/libpthread/src/l4.cc @@ -0,0 +1,154 @@ +#ifndef PT_EI +#define PT_EI inline +#endif + +#include "internals.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include "spinlock.h" + +#include "l4.h" + + +l4_cap_idx_t pthread_getl4cap(pthread_t thread_id) +{ + __volatile__ pthread_descr self = thread_self(); + pthread_handle handle = thread_handle(thread_id); + pthread_descr th; + + __pthread_lock(handle_to_lock(handle), self); + if (nonexisting_handle(handle, thread_id)) { + __pthread_unlock(handle_to_lock(handle)); + return L4_INVALID_CAP; + } + l4_cap_idx_t c; + th = handle_to_descr(handle); + c = th->p_th_cap; + __pthread_unlock(handle_to_lock(handle)); + return c; +} + +static void cb(void *arg, pthread_descr th) +{ + void (*fn)(pthread_t) = (void (*)(pthread_t))arg; + + fn(th->p_tid); +} + +void pthread_l4_for_each_thread(void (*fn)(pthread_t)) +{ + struct pthread_request request; + + request.req_thread = thread_self(); + request.req_kind = REQ_FOR_EACH_THREAD; + request.req_args.for_each.arg = (void *)fn; + request.req_args.for_each.fn = cb; + + __pthread_send_manager_rq(&request, 1); +} + +int __pthread_l4_initialize_main_thread(pthread_descr th) +{ + L4Re::Env *env = const_cast(L4Re::Env::env()); + if (!env) + return -L4_ENODEV; + + L4::Cap s(env->first_free_cap() << L4_CAP_SHIFT); + if (!s.is_valid() || !s.cap()) + return -L4_ENOMEM; + + // needed by __alloc_thread_sem + th->p_th_cap = env->main_thread().cap(); + + int err = __alloc_thread_sem(th, s); + if (err < 0) + return err; + + env->first_free_cap((s.cap() + L4_CAP_OFFSET) >> L4_CAP_SHIFT); + + th->p_thsem_cap = s.cap(); + + th->p_sched_policy = SCHED_L4; + th->p_priority = 0x10; + + th->p_lock = handle_to_lock(l4_utcb()); + th->p_tid = l4_utcb(); + l4_utcb_tcr()->user[0] = l4_addr_t(th); + + return 0; +} + + +int __attribute__((weak)) __pthread_sched_idle_prio = 0x01; +int __attribute__((weak)) __pthread_sched_other_prio = 0x02; +int __attribute__((weak)) __pthread_sched_rr_prio_min = 0x40; +int __attribute__((weak)) __pthread_sched_rr_prio_max = 0xf0; + + +int __pthread_setschedparam(pthread_t thread, int policy, + const struct sched_param *param) throw() +{ + pthread_handle handle = thread_handle(thread); + pthread_descr th; + + __pthread_lock(handle_to_lock(handle), NULL); + if (__builtin_expect (invalid_handle(handle, thread), 0)) { + __pthread_unlock(handle_to_lock(handle)); + return ESRCH; + } + th = handle_to_descr(handle); + int prio = __pthread_l4_getprio(policy, param->sched_priority); + if (prio < 0) + { + __pthread_unlock(handle_to_lock(handle)); + return EINVAL; + } + + th->p_sched_policy = policy; + th->p_priority = param->sched_priority; + + { + L4::Cap t(th->p_th_cap); + l4_sched_param_t sp = l4_sched_param(prio, 0); + L4Re::Env::env()->scheduler()->run_thread(t, sp); + } + __pthread_unlock(handle_to_lock(handle)); + + if (__pthread_manager_request > 0) + __pthread_manager_adjust_prio(prio); + + return 0; +} +strong_alias (__pthread_setschedparam, pthread_setschedparam) + +int __pthread_getschedparam(pthread_t thread, int *policy, + struct sched_param *param) throw() +{ + pthread_handle handle = thread_handle(thread); + int pol, prio; + + __pthread_lock(handle_to_lock(handle), NULL); + if (__builtin_expect (invalid_handle(handle, thread), 0)) { + __pthread_unlock(handle_to_lock(handle)); + return ESRCH; + } + + pol = handle_to_descr(handle)->p_sched_policy; + prio = handle_to_descr(handle)->p_priority; + __pthread_unlock(handle_to_lock(handle)); + + *policy = pol; + param->sched_priority = prio; + + return 0; +} +strong_alias (__pthread_getschedparam, pthread_getschedparam) diff --git a/l4/pkg/uclibc/lib/libpthread/src/l4.h b/l4/pkg/uclibc/lib/libpthread/src/l4.h new file mode 100644 index 00000000..b75202cd --- /dev/null +++ b/l4/pkg/uclibc/lib/libpthread/src/l4.h @@ -0,0 +1,15 @@ +#pragma once + +#include + +typedef L4::Irq Th_sem_cap; + +inline int __alloc_thread_sem(pthread_descr th, L4::Cap const &c) +{ + int err = l4_error(L4Re::Env::env()->factory()->create_irq(c)); + if (err < 0) + return err; + + err = l4_error(c->attach(16, L4::Cap(th->p_th_cap))); + return err; +} diff --git a/l4/pkg/uclibc/lib/libpthread/src/libc_pthread_init.c b/l4/pkg/uclibc/lib/libpthread/src/libc_pthread_init.c new file mode 100644 index 00000000..afe995ae --- /dev/null +++ b/l4/pkg/uclibc/lib/libpthread/src/libc_pthread_init.c @@ -0,0 +1,52 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#ifdef USE_TLS +#include +#endif +#include "internals.h" + + +int __libc_multiple_threads attribute_hidden __attribute__((nocommon)); +strong_alias (__libc_multiple_threads, __librt_multiple_threads) + + +int * +__libc_pthread_init (functions) + const struct pthread_functions *functions; +{ +#ifdef SHARED + /* We copy the content of the variable pointed to by the FUNCTIONS + parameter to one in libc.so since this means access to the array + can be done with one memory access instead of two. */ + memcpy (&__libc_pthread_functions, functions, + sizeof (__libc_pthread_functions)); +#endif + +#if !(USE_TLS && HAVE___THREAD) + /* Initialize thread-locale current locale to point to the global one. + With __thread support, the variable's initializer takes care of this. */ + __uselocale (LC_GLOBAL_LOCALE); +#endif + + return &__libc_multiple_threads; +} diff --git a/l4/pkg/uclibc/lib/libpthread/src/manager.cc b/l4/pkg/uclibc/lib/libpthread/src/manager.cc new file mode 100644 index 00000000..151b5ee8 --- /dev/null +++ b/l4/pkg/uclibc/lib/libpthread/src/manager.cc @@ -0,0 +1,1071 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +/* The "thread manager" thread: manages creation and termination of threads */ + +#ifndef PT_EI +#define PT_EI inline +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* for __uselocale */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern "C" { +#include "pthread.h" +#include "internals.h" +#include "spinlock.h" +#include "restart.h" +#include "semaphore.h" +#include "l4.h" +#include +} + +#define USE_L4RE_FOR_STACK + +#ifndef MIN +# define MIN(a,b) (((a) < (b)) ? (a) : (b)) +#endif + +extern "C" void __pthread_new_thread_entry(void); + +#ifndef THREAD_SELF +/* Indicate whether at least one thread has a user-defined stack (if 1), + or if all threads have stacks supplied by LinuxThreads (if 0). */ +int __pthread_nonstandard_stacks; +#endif + +/* Number of active entries in __pthread_handles (used by gdb) */ +__volatile__ int __pthread_handles_num = 2; + +/* Whether to use debugger additional actions for thread creation + (set to 1 by gdb) */ +__volatile__ int __pthread_threads_debug; + +static pthread_descr manager_thread; + +/* Mapping from stack segment to thread descriptor. */ +/* Stack segment numbers are also indices into the __pthread_handles array. */ +/* Stack segment number 0 is reserved for the initial thread. */ + +# define thread_segment(seq) NULL + +/* Flag set in signal handler to record child termination */ + +static __volatile__ int terminated_children; + +/* Flag set when the initial thread is blocked on pthread_exit waiting + for all other threads to terminate */ + +static int main_thread_exiting; + +/* Counter used to generate unique thread identifier. + Thread identifier is pthread_threads_counter + segment. */ + +//l4/static pthread_t pthread_threads_counter; + +/* Forward declarations */ + +static int pthread_handle_create(pthread_t *thread, const pthread_attr_t *attr, + void * (*start_routine)(void *), void *arg); +static void pthread_handle_free(pthread_t th_id); +static void pthread_handle_exit(pthread_descr issuing_thread, int exitcode) + __attribute__ ((noreturn)); +//l4/static void pthread_kill_all_threads(int main_thread_also); +static void pthread_for_each_thread(void *arg, + void (*fn)(void *, pthread_descr)); + +static void pthread_exited(pthread_descr th); + +/* The server thread managing requests for thread creation and termination */ + +int +__attribute__ ((noreturn)) +__pthread_manager(void *arg) +{ + pthread_descr self = manager_thread = (pthread_descr)arg; + struct pthread_request request; + +#ifdef USE_TLS +# if defined(TLS_TCB_AT_TP) + TLS_INIT_TP(self, 0); +#elif defined(TLS_DTV_AT_TP) + TLS_INIT_TP(self + 1, 0); +#else +# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined" +#endif +#endif + /* If we have special thread_self processing, initialize it. */ +#ifdef INIT_THREAD_SELF + INIT_THREAD_SELF(self, 1); +#endif +#if !(USE_TLS && HAVE___THREAD) + /* Set the error variable. */ + self->p_errnop = &self->p_errno; + self->p_h_errnop = &self->p_h_errno; +#endif + /* Raise our priority to match that of main thread */ + __pthread_manager_adjust_prio(__pthread_main_thread->p_priority); + + l4_umword_t src; + l4_msgtag_t tag = l4_msgtag(0, 0, 0, L4_MSGTAG_SCHEDULE); + int do_reply = 0; + /* Enter server loop */ + while (1) + { + if (do_reply) + tag = l4_ipc_reply_and_wait(l4_utcb(), tag, &src, L4_IPC_NEVER); + else + tag = l4_ipc_wait(l4_utcb(), &src, L4_IPC_NEVER); + + if (l4_msgtag_has_error(tag)) + { + do_reply = 0; + continue; + } + + memcpy(&request, l4_utcb_mr()->mr, sizeof(request)); + + do_reply = 0; + switch(request.req_kind) + { + case REQ_CREATE: + request.req_thread->p_retcode = + pthread_handle_create((pthread_t *) &request.req_thread->p_retval, + request.req_args.create.attr, + request.req_args.create.fn, + request.req_args.create.arg); + do_reply = 1; + break; + case REQ_FREE: + pthread_handle_free(request.req_args.free.thread_id); + break; + case REQ_PROCESS_EXIT: + pthread_handle_exit(request.req_thread, + request.req_args.exit.code); + /* NOTREACHED */ + break; + case REQ_MAIN_THREAD_EXIT: + main_thread_exiting = 1; + /* Reap children in case all other threads died and the signal handler + went off before we set main_thread_exiting to 1, and therefore did + not do REQ_KICK. */ + //l4/pthread_reap_children(); + + if (__pthread_main_thread->p_nextlive == __pthread_main_thread) { + restart(__pthread_main_thread); + /* The main thread will now call exit() which will trigger an + __on_exit handler, which in turn will send REQ_PROCESS_EXIT + to the thread manager. In case you are wondering how the + manager terminates from its loop here. */ + } + break; + case REQ_POST: + sem_post((sem_t*)request.req_args.post); + break; + case REQ_DEBUG: +#ifdef NOT_FOR_L4 + /* Make gdb aware of new thread and gdb will restart the + new thread when it is ready to handle the new thread. */ + if (__pthread_threads_debug && __pthread_sig_debug > 0) + raise(__pthread_sig_debug); +#else + do_reply = 1; +#endif + break; + case REQ_KICK: + /* This is just a prod to get the manager to reap some + threads right away, avoiding a potential delay at shutdown. */ + break; + case REQ_FOR_EACH_THREAD: + pthread_for_each_thread(request.req_args.for_each.arg, + request.req_args.for_each.fn); + restart(request.req_thread); + do_reply = 1; + break; + case REQ_THREAD_EXIT: + { + l4_msgtag_t e; + L4::Cap c; + + pthread_exited(request.req_thread); + + c = L4::Cap(request.req_thread->p_thsem_cap); + e = L4::Cap(L4Re::This_task) + ->unmap(c.fpage(), L4_FP_ALL_SPACES); + + c = L4::Cap(request.req_thread->p_th_cap); + e = L4::Cap(L4Re::This_task) + ->unmap(c.fpage(), L4_FP_ALL_SPACES); + } + break; + } + tag = l4_msgtag(0, 0, 0, L4_MSGTAG_SCHEDULE); + } +} + +int __pthread_manager_event(void *arg) +{ + pthread_descr self = (pthread_descr)arg; + /* If we have special thread_self processing, initialize it. */ +#ifdef INIT_THREAD_SELF + INIT_THREAD_SELF(self, 1); +#endif + + /* Get the lock the manager will free once all is correctly set up. */ + __pthread_lock (THREAD_GETMEM(self, p_lock), NULL); + /* Free it immediately. */ + __pthread_unlock (THREAD_GETMEM(self, p_lock)); + + return __pthread_manager(arg); +} + +/* Process creation */ + +static int +__attribute__ ((noreturn)) +pthread_start_thread(void *arg) +{ + pthread_descr self = (pthread_descr) arg; +#ifdef USE_TLS +# if defined(TLS_TCB_AT_TP) + TLS_INIT_TP(self, 0); +#elif defined(TLS_DTV_AT_TP) + TLS_INIT_TP(self + 1, 0); +#else +# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined" +#endif +#endif + +#ifdef NOT_FOR_L4 + struct pthread_request request; +#endif + void * outcome; +#if HP_TIMING_AVAIL + hp_timing_t tmpclock; +#endif + /* Initialize special thread_self processing, if any. */ +#ifdef INIT_THREAD_SELF + INIT_THREAD_SELF(self, self->p_nr); +#endif +#if HP_TIMING_AVAIL + HP_TIMING_NOW (tmpclock); + THREAD_SETMEM (self, p_cpuclock_offset, tmpclock); +#endif + +#ifdef NOT_FOR_L4 + /* Set the scheduling policy and priority for the new thread, if needed */ + if (THREAD_GETMEM(self, p_start_args.schedpolicy) >= 0) + /* Explicit scheduling attributes were provided: apply them */ + __sched_setscheduler(THREAD_GETMEM(self, p_pid), + THREAD_GETMEM(self, p_start_args.schedpolicy), + &self->p_start_args.schedparam); + else if (manager_thread->p_priority > 0) + /* Default scheduling required, but thread manager runs in realtime + scheduling: switch new thread to SCHED_OTHER policy */ + { + struct sched_param default_params; + default_params.sched_priority = 0; + __sched_setscheduler(THREAD_GETMEM(self, p_pid), + SCHED_OTHER, &default_params); + } +#if !(USE_TLS && HAVE___THREAD) + /* Initialize thread-locale current locale to point to the global one. + With __thread support, the variable's initializer takes care of this. */ + __uselocale (LC_GLOBAL_LOCALE); +#else + /* Initialize __resp. */ + __resp = &self->p_res; +#endif + /* Make gdb aware of new thread */ + if (__pthread_threads_debug && __pthread_sig_debug > 0) { + request.req_thread = self; + request.req_kind = REQ_DEBUG; + TEMP_FAILURE_RETRY(write_not_cancel(__pthread_manager_request, + (char *) &request, sizeof(request))); + suspend(self); + } +#endif + /* Run the thread code */ + outcome = self->p_start_args.start_routine(THREAD_GETMEM(self, + p_start_args.arg)); + /* Exit with the given return value */ + __pthread_do_exit(outcome, (char *)CURRENT_STACK_FRAME); +} + +#ifdef NOT_FOR_L4 +static int +__attribute__ ((noreturn)) +pthread_start_thread_event(void *arg) +{ + pthread_descr self = (pthread_descr) arg; + +#ifdef INIT_THREAD_SELF + INIT_THREAD_SELF(self, self->p_nr); +#endif + /* Make sure our pid field is initialized, just in case we get there + before our father has initialized it. */ + THREAD_SETMEM(self, p_pid, __getpid()); + /* Get the lock the manager will free once all is correctly set up. */ + __pthread_lock (THREAD_GETMEM(self, p_lock), NULL); + /* Free it immediately. */ + __pthread_unlock (THREAD_GETMEM(self, p_lock)); + + /* Continue with the real function. */ + pthread_start_thread (arg); +} +#endif + +#ifdef USE_L4RE_FOR_STACK +static int pthread_l4_free_stack(void *stack_addr, void *guardaddr) +{ + L4Re::Env const *e = L4Re::Env::env(); + int err; + L4::Cap ds; + + err = e->rm()->detach(stack_addr, &ds); + if (err < 0) + return err; + + if (ds.is_valid()) + { + err = ds->release(); + if (err < 0) + return err; + } + + L4Re::Util::cap_alloc.free(ds); + + return e->rm()->free_area((l4_addr_t)guardaddr); +} +#endif + +static int pthread_allocate_stack(const pthread_attr_t *attr, + pthread_descr default_new_thread, + int pagesize, + char ** out_new_thread, + char ** out_new_thread_bottom, + char ** out_guardaddr, + size_t * out_guardsize, + size_t * out_stacksize) +{ + pthread_descr new_thread; + char * new_thread_bottom; + char * guardaddr; + size_t stacksize, guardsize; + +#ifdef USE_TLS + /* TLS cannot work with fixed thread descriptor addresses. */ + assert (default_new_thread == NULL); +#endif + + if (attr != NULL && attr->__stackaddr_set) + { +#ifdef _STACK_GROWS_UP + /* The user provided a stack. */ +# ifdef USE_TLS + /* This value is not needed. */ + new_thread = (pthread_descr) attr->__stackaddr; + new_thread_bottom = (char *) new_thread; +# else + new_thread = (pthread_descr) attr->__stackaddr; + new_thread_bottom = (char *) (new_thread + 1); +# endif + guardaddr = attr->__stackaddr + attr->__stacksize; + guardsize = 0; +#else + /* The user provided a stack. For now we interpret the supplied + address as 1 + the highest addr. in the stack segment. If a + separate register stack is needed, we place it at the low end + of the segment, relying on the associated stacksize to + determine the low end of the segment. This differs from many + (but not all) other pthreads implementations. The intent is + that on machines with a single stack growing toward higher + addresses, stackaddr would be the lowest address in the stack + segment, so that it is consistently close to the initial sp + value. */ +# ifdef USE_TLS + new_thread = (pthread_descr) attr->__stackaddr; +# else + new_thread = + (pthread_descr) ((long)(attr->__stackaddr) & -sizeof(void *)) - 1; +# endif + new_thread_bottom = (char *) attr->__stackaddr - attr->__stacksize; + guardaddr = new_thread_bottom; + guardsize = 0; +#endif +#ifndef THREAD_SELF + __pthread_nonstandard_stacks = 1; +#endif +#ifndef USE_TLS + /* Clear the thread data structure. */ + memset (new_thread, '\0', sizeof (*new_thread)); +#endif + stacksize = attr->__stacksize; + } + else + { + const size_t granularity = pagesize; + void *map_addr; + + /* Allocate space for stack and thread descriptor at default address */ + if (attr != NULL) + { + guardsize = page_roundup (attr->__guardsize, granularity); + stacksize = __pthread_max_stacksize - guardsize; + stacksize = MIN (stacksize, + page_roundup (attr->__stacksize, granularity)); + } + else + { + guardsize = granularity; + stacksize = __pthread_max_stacksize - guardsize; + } + +#ifdef USE_L4RE_FOR_STACK + map_addr = 0; + L4Re::Env const *e = L4Re::Env::env(); + long err; + + if (e->rm()->reserve_area(&map_addr, stacksize + guardsize, + L4Re::Rm::Search_addr) < 0) + return -1; + + guardaddr = (char*)map_addr; + + L4::Cap ds = L4Re::Util::cap_alloc.alloc(); + if (!ds.is_valid()) + return -1; + + err = e->mem_alloc()->alloc(stacksize, ds); + + if (err < 0) + { + L4Re::Util::cap_alloc.free(ds); + e->rm()->free_area(l4_addr_t(map_addr)); + return -1; + } + + new_thread_bottom = (char *) map_addr + guardsize; + err = e->rm()->attach(&new_thread_bottom, stacksize, L4Re::Rm::In_area, + ds, 0); + + if (err < 0) + { + L4Re::Util::cap_alloc.free(ds); + e->rm()->free_area(l4_addr_t(map_addr)); + return -1; + } +#else + map_addr = mmap(NULL, stacksize + guardsize, + PROT_READ | PROT_WRITE | PROT_EXEC, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (map_addr == MAP_FAILED) + /* No more memory available. */ + return -1; + + guardaddr = (char *)map_addr; + if (guardsize > 0) + mprotect (guardaddr, guardsize, PROT_NONE); + + new_thread_bottom = (char *) map_addr + guardsize; +#endif + +#ifdef USE_TLS + new_thread = ((pthread_descr) (new_thread_bottom + stacksize)); +#else + new_thread = ((pthread_descr) (new_thread_bottom + stacksize)) - 1; +#endif + } + *out_new_thread = (char *) new_thread; + *out_new_thread_bottom = new_thread_bottom; + *out_guardaddr = guardaddr; + *out_guardsize = guardsize; + *out_stacksize = stacksize; + return 0; +} + +static inline +int __pthread_mgr_create_thread(pthread_descr thread, char **tos, + int (*f)(void*), int prio) +{ + using namespace L4Re; + Env const *e = Env::env(); + L4Re::Util::Auto_cap::Cap _t = L4Re::Util::cap_alloc.alloc(); + if (!_t.is_valid()) + return ENOMEM; + + L4Re::Util::Auto_cap::Cap th_sem + = L4Re::Util::cap_alloc.alloc(); + if (!th_sem.is_valid()) + return ENOMEM; + + int err = l4_error(e->factory()->create_thread(_t.get())); + if (err < 0) + return -err; + + // needed by __alloc_thread_sem + thread->p_th_cap = _t.cap(); + + err = __alloc_thread_sem(thread, th_sem.get()); + if (err < 0) + return -err; + + thread->p_thsem_cap = th_sem.cap(); + + L4::Thread::Attr attr; + l4_utcb_t *nt_utcb = (l4_utcb_t*)thread->p_tid; + + attr.bind(nt_utcb, L4Re::This_task); + attr.pager(e->rm()); + attr.exc_handler(e->rm()); + if ((err = l4_error(_t->control(attr))) < 0) + fprintf(stderr, "ERROR: l4 thread control returned: %d\n", err); + + l4_utcb_tcr_u(nt_utcb)->user[0] = l4_addr_t(thread); + + + l4_umword_t *&_tos = (l4_umword_t*&)*tos; + + *(--_tos) = l4_addr_t(thread); + *(--_tos) = 0; /* ret addr */ + *(--_tos) = l4_addr_t(f); + + + _t->ex_regs(l4_addr_t(__pthread_new_thread_entry), l4_addr_t(_tos), 0); + + l4_sched_param_t sp = l4_sched_param(prio >= 0 ? prio : 2); + e->scheduler()->run_thread(_t.get(), sp); + + // release the automatic capabilities + _t.release(); + th_sem.release(); + return 0; +} + +static int l4pthr_get_more_utcb() +{ + using namespace L4Re; + + l4_addr_t kumem = 0; + Env const *e = Env::env(); + + if (e->rm()->reserve_area(&kumem, L4_PAGESIZE, + Rm::Reserved | Rm::Search_addr)) + return 1; + + if (l4_error(e->task()->add_ku_mem(l4_fpage(kumem, L4_PAGESHIFT, + L4_FPAGE_RW)))) + { + e->rm()->free_area(kumem); + return 1; + } + + __l4_add_utcbs(kumem, kumem + L4_PAGESIZE); + return 0; +} + + +static inline l4_utcb_t *mgr_alloc_utcb() +{ + l4_utcb_t *new_utcb = __pthread_first_free_handle; + if (!new_utcb) + return 0; + + __pthread_first_free_handle = (l4_utcb_t*)l4_utcb_tcr_u(new_utcb)->user[0]; + return new_utcb; +} + +static inline void mgr_free_utcb(l4_utcb_t *u) +{ + if (!u) + return; + + l4_utcb_tcr_u(u)->user[0] = l4_addr_t(__pthread_first_free_handle); + __pthread_first_free_handle = u; +} + +int __pthread_start_manager(pthread_descr mgr) +{ + int err; + + mgr->p_tid = mgr_alloc_utcb(); + + err = __pthread_mgr_create_thread(mgr, &__pthread_manager_thread_tos, + __pthread_manager, -1); + if (err < 0) + { + fprintf(stderr, "ERROR: could not start pthread manager thread\n"); + exit(100); + } + + __pthread_manager_request = mgr->p_th_cap; + return 0; +} + + +static int pthread_handle_create(pthread_t *thread, const pthread_attr_t *attr, + void * (*start_routine)(void *), void *arg) +{ + int err; + pthread_descr new_thread; + char *stack_addr; + char * new_thread_bottom; + pthread_t new_thread_id; + char *guardaddr = NULL; + size_t guardsize = 0, stksize = 0; + int pagesize = L4_PAGESIZE; + int saved_errno = 0; + +#ifdef USE_TLS + new_thread = (_pthread_descr_struct*)_dl_allocate_tls (NULL); + if (new_thread == NULL) + return EAGAIN; +# if defined(TLS_DTV_AT_TP) + /* pthread_descr is below TP. */ + new_thread = (pthread_descr) ((char *) new_thread - TLS_PRE_TCB_SIZE); +# endif +#else + /* Prevent warnings. */ + new_thread = NULL; +#endif +#ifdef __NOT_FOR_L4__ + /* First check whether we have to change the policy and if yes, whether + we can do this. Normally this should be done by examining the + return value of the __sched_setscheduler call in pthread_start_thread + but this is hard to implement. FIXME */ + if (attr != NULL && attr->__schedpolicy != SCHED_OTHER && geteuid () != 0) + return EPERM; +#endif + /* Find a free segment for the thread, and allocate a stack if needed */ + + if (__pthread_first_free_handle == 0 && l4pthr_get_more_utcb()) + { +#ifdef USE_TLS +# if defined(TLS_DTV_AT_TP) + new_thread = (pthread_descr) ((char *) new_thread + TLS_PRE_TCB_SIZE); +# endif + _dl_deallocate_tls (new_thread, true); +#endif + + return EAGAIN; + } + + l4_utcb_t *new_utcb = mgr_alloc_utcb(); + if (!new_utcb) + return EAGAIN; + + new_thread_id = new_utcb; + + if (pthread_allocate_stack(attr, thread_segment(sseg), + pagesize, &stack_addr, &new_thread_bottom, + &guardaddr, &guardsize, &stksize) == 0) + { +#ifdef USE_TLS + new_thread->p_stackaddr = stack_addr; +#else + new_thread = (pthread_descr) stack_addr; +#endif + } + else + { + mgr_free_utcb(new_utcb); + return EAGAIN; + } + + /* Allocate new thread identifier */ + /* Initialize the thread descriptor. Elements which have to be + initialized to zero already have this value. */ +#if !defined USE_TLS || !TLS_DTV_AT_TP + new_thread->p_header.data.tcb = new_thread; + new_thread->p_header.data.self = new_thread; +#endif +#if TLS_MULTIPLE_THREADS_IN_TCB || !defined USE_TLS || !TLS_DTV_AT_TP + new_thread->p_multiple_threads = 1; +#endif + new_thread->p_tid = new_thread_id; + new_thread->p_lock = handle_to_lock(new_utcb); + new_thread->p_cancelstate = PTHREAD_CANCEL_ENABLE; + new_thread->p_canceltype = PTHREAD_CANCEL_DEFERRED; +#if !(USE_TLS && HAVE___THREAD) + new_thread->p_errnop = &new_thread->p_errno; + new_thread->p_h_errnop = &new_thread->p_h_errno; +#endif + new_thread->p_guardaddr = guardaddr; + new_thread->p_guardsize = guardsize; + new_thread->p_inheritsched = attr ? attr->__inheritsched : 0; + new_thread->p_alloca_cutoff = stksize / 4 > __MAX_ALLOCA_CUTOFF + ? __MAX_ALLOCA_CUTOFF : stksize / 4; + /* Initialize the thread handle */ + __pthread_init_lock(handle_to_lock(new_utcb)); + /* Determine scheduling parameters for the thread */ + new_thread->p_sched_policy = -1; + if (attr != NULL) + { + new_thread->p_detached = attr->__detachstate; + new_thread->p_userstack = attr->__stackaddr_set; + + switch(attr->__inheritsched) + { + case PTHREAD_EXPLICIT_SCHED: + new_thread->p_sched_policy = attr->__schedpolicy; + new_thread->p_priority = attr->__schedparam.sched_priority; + break; + case PTHREAD_INHERIT_SCHED: + break; + } + } + int prio = -1; + /* Set the scheduling policy and priority for the new thread, if needed */ + if (new_thread->p_sched_policy >= 0) + { + /* Explicit scheduling attributes were provided: apply them */ + prio = __pthread_l4_getprio(new_thread->p_sched_policy, + new_thread->p_priority); + /* Raise priority of thread manager if needed */ + __pthread_manager_adjust_prio(prio); + } + else if (manager_thread->p_sched_policy > 3) + { + /* Default scheduling required, but thread manager runs in realtime + scheduling: switch new thread to SCHED_OTHER policy */ + prio = __pthread_l4_getprio(SCHED_OTHER, 0); + } + /* Finish setting up arguments to pthread_start_thread */ + new_thread->p_start_args.start_routine = start_routine; + new_thread->p_start_args.arg = arg; + /* Make the new thread ID available already now. If any of the later + functions fail we return an error value and the caller must not use + the stored thread ID. */ + *thread = new_thread_id; + /* Do the cloning. We have to use two different functions depending + on whether we are debugging or not. */ + err = __pthread_mgr_create_thread(new_thread, &stack_addr, + pthread_start_thread, prio); + saved_errno = err; + + /* Check if cloning succeeded */ + if (err < 0) { + /* Free the stack if we allocated it */ + if (attr == NULL || !attr->__stackaddr_set) + { +#ifdef NEED_SEPARATE_REGISTER_STACK + size_t stacksize = ((char *)(new_thread->p_guardaddr) + - new_thread_bottom); + munmap((caddr_t)new_thread_bottom, + 2 * stacksize + new_thread->p_guardsize); +#elif _STACK_GROWS_UP +# ifdef USE_TLS + size_t stacksize = guardaddr - stack_addr; + munmap(stack_addr, stacksize + guardsize); +# else + + size_t stacksize = guardaddr - (char *)new_thread; + munmap(new_thread, stacksize + guardsize); +# endif +#else +#ifdef USE_L4RE_FOR_STACK + if (pthread_l4_free_stack(new_thread_bottom, guardaddr)) + fprintf(stderr, "ERROR: failed to free stack\n"); +#else +# ifdef USE_TLS + size_t stacksize = stack_addr - new_thread_bottom; +# else + size_t stacksize = (char *)(new_thread+1) - new_thread_bottom; +# endif + munmap(new_thread_bottom - guardsize, guardsize + stacksize); +#endif +#endif + } +#ifdef USE_TLS +# if defined(TLS_DTV_AT_TP) + new_thread = (pthread_descr) ((char *) new_thread + TLS_PRE_TCB_SIZE); +# endif + _dl_deallocate_tls (new_thread, true); +#endif + mgr_free_utcb(new_utcb); + return saved_errno; + } + /* Insert new thread in doubly linked list of active threads */ + new_thread->p_prevlive = __pthread_main_thread; + new_thread->p_nextlive = __pthread_main_thread->p_nextlive; + __pthread_main_thread->p_nextlive->p_prevlive = new_thread; + __pthread_main_thread->p_nextlive = new_thread; + /* Set pid field of the new thread, in case we get there before the + child starts. */ + return 0; +} + + +/* Try to free the resources of a thread when requested by pthread_join + or pthread_detach on a terminated thread. */ + +static void pthread_free(pthread_descr th) +{ + pthread_handle handle; + pthread_readlock_info *iter, *next; + + ASSERT(th->p_exited); + /* Make the handle invalid */ + handle = thread_handle(th->p_tid); + __pthread_lock(handle_to_lock(handle), NULL); + mgr_free_utcb(handle); + __pthread_unlock(handle_to_lock(handle)); + + { + // free the semaphore and the thread + L4Re::Util::Auto_cap::Cap s = L4::Cap(th->p_thsem_cap); + L4Re::Util::Auto_cap::Cap t = L4::Cap(th->p_th_cap); + } + + /* One fewer threads in __pthread_handles */ + + /* Destroy read lock list, and list of free read lock structures. + If the former is not empty, it means the thread exited while + holding read locks! */ + + for (iter = th->p_readlock_list; iter != NULL; iter = next) + { + next = iter->pr_next; + free(iter); + } + + for (iter = th->p_readlock_free; iter != NULL; iter = next) + { + next = iter->pr_next; + free(iter); + } + + /* If initial thread, nothing to free */ + if (!th->p_userstack) + { + size_t guardsize = th->p_guardsize; + /* Free the stack and thread descriptor area */ + char *guardaddr = (char*)th->p_guardaddr; +#ifdef _STACK_GROWS_UP +# ifdef USE_TLS + size_t stacksize = guardaddr - th->p_stackaddr; +# else + size_t stacksize = guardaddr - (char *)th; +# endif + guardaddr = (char *)th; +#else + /* Guardaddr is always set, even if guardsize is 0. This allows + us to compute everything else. */ +# ifdef USE_TLS + //l4/size_t stacksize = th->p_stackaddr - guardaddr - guardsize; +# else + //l4/size_t stacksize = (char *)(th+1) - guardaddr - guardsize; +# endif +# ifdef NEED_SEPARATE_REGISTER_STACK + /* Take account of the register stack, which is below guardaddr. */ + guardaddr -= stacksize; + stacksize *= 2; +# endif +#endif +#ifdef USE_L4RE_FOR_STACK + pthread_l4_free_stack(guardaddr + guardsize, guardaddr); +#else + munmap(guardaddr, stacksize + guardsize); +#endif + + } + +#ifdef USE_TLS +# if defined(TLS_DTV_AT_TP) + th = (pthread_descr) ((char *) th + TLS_PRE_TCB_SIZE); +# endif + _dl_deallocate_tls (th, true); +#endif +} + +/* Handle threads that have exited */ + +static void pthread_exited(pthread_descr th) +{ + int detached; + /* Remove thread from list of active threads */ + th->p_nextlive->p_prevlive = th->p_prevlive; + th->p_prevlive->p_nextlive = th->p_nextlive; + /* Mark thread as exited, and if detached, free its resources */ + __pthread_lock(th->p_lock, NULL); + th->p_exited = 1; + /* If we have to signal this event do it now. */ + detached = th->p_detached; + __pthread_unlock(th->p_lock); + if (detached) + pthread_free(th); + /* If all threads have exited and the main thread is pending on a + pthread_exit, wake up the main thread and terminate ourselves. */ + if (main_thread_exiting && + __pthread_main_thread->p_nextlive == __pthread_main_thread) { + restart(__pthread_main_thread); + /* Same logic as REQ_MAIN_THREAD_EXIT. */ + } +} + + +/* Try to free the resources of a thread when requested by pthread_join + or pthread_detach on a terminated thread. */ + +static void pthread_handle_free(pthread_t th_id) +{ + pthread_handle handle = thread_handle(th_id); + pthread_descr th; + + __pthread_lock(handle_to_lock(handle), NULL); + if (nonexisting_handle(handle, th_id)) { + /* pthread_reap_children has deallocated the thread already, + nothing needs to be done */ + __pthread_unlock(handle_to_lock(handle)); + return; + } + th = handle_to_descr(handle); + __pthread_unlock(handle_to_lock(handle)); + pthread_exited(th); + pthread_free(th); +} + +/* Send a signal to all running threads */ + +#if 0 +static void pthread_kill_all_threads(int main_thread_also) +{ + UNIMPL("pthread_kill_all_threads"); +#if 0 + pthread_descr th; + for (th = __pthread_main_thread->p_nextlive; + th != __pthread_main_thread; + th = th->p_nextlive) { + kill(th->p_pid, sig); + } + if (main_thread_also) { + kill(__pthread_main_thread->p_pid, sig); + } +#endif +} +#endif + +static void pthread_for_each_thread(void *arg, + void (*fn)(void *, pthread_descr)) +{ + pthread_descr th; + + for (th = __pthread_main_thread->p_nextlive; + th != __pthread_main_thread; + th = th->p_nextlive) { + fn(arg, th); + } + + fn(arg, __pthread_main_thread); +} + +/* Process-wide exit() */ + +static void pthread_handle_exit(pthread_descr issuing_thread, int exitcode) +{ + //l4/pthread_descr th; + __pthread_exit_requested = 1; + __pthread_exit_code = exitcode; +#if 0 + /* A forced asynchronous cancellation follows. Make sure we won't + get stuck later in the main thread with a system lock being held + by one of the cancelled threads. Ideally one would use the same + code as in pthread_atfork(), but we can't distinguish system and + user handlers there. */ + __flockfilelist(); + /* Send the CANCEL signal to all running threads, including the main + thread, but excluding the thread from which the exit request originated + (that thread must complete the exit, e.g. calling atexit functions + and flushing stdio buffers). */ + for (th = issuing_thread->p_nextlive; + th != issuing_thread; + th = th->p_nextlive) { + kill(th->p_pid, __pthread_sig_cancel); + } + /* Now, wait for all these threads, so that they don't become zombies + and their times are properly added to the thread manager's times. */ + for (th = issuing_thread->p_nextlive; + th != issuing_thread; + th = th->p_nextlive) { + waitpid(th->p_pid, NULL, __WCLONE); + } + __fresetlockfiles(); +#endif + restart(issuing_thread); +#ifdef THIS_IS_THE_ORIGINAL + _exit(0); +#else + // we do not do the exit path with kill and waitpid, so give the code here + _exit(exitcode); +#endif +} + +#if 0 +/* Handler for __pthread_sig_cancel in thread manager thread */ + +void __pthread_manager_sighandler(int sig) +{ + int kick_manager = terminated_children == 0 && main_thread_exiting; + terminated_children = 1; + + /* If the main thread is terminating, kick the thread manager loop + each time some threads terminate. This eliminates a two second + shutdown delay caused by the thread manager sleeping in the + call to __poll(). Instead, the thread manager is kicked into + action, reaps the outstanding threads and resumes the main thread + so that it can complete the shutdown. */ + + if (kick_manager) { + struct pthread_request request; + request.req_thread = 0; + request.req_kind = REQ_KICK; + TEMP_FAILURE_RETRY(write_not_cancel(__pthread_manager_request, + (char *) &request, sizeof(request))); + } +} +#endif +/* Adjust priority of thread manager so that it always run at a priority + higher than all threads */ + +void __pthread_manager_adjust_prio(int thread_prio) +{ + if (!manager_thread) + return; + + if (thread_prio <= manager_thread->p_priority) + return; + + l4_sched_param_t sp = l4_sched_param(thread_prio, 0); + L4Re::Env::env()->scheduler()->run_thread(L4::Cap(manager_thread->p_th_cap), sp); + manager_thread->p_priority = thread_prio; +} diff --git a/l4/pkg/uclibc/lib/libpthread/src/mutex.c b/l4/pkg/uclibc/lib/libpthread/src/mutex.c new file mode 100644 index 00000000..fca6ea8a --- /dev/null +++ b/l4/pkg/uclibc/lib/libpthread/src/mutex.c @@ -0,0 +1,393 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +/* Mutexes */ + +#include +#include +#ifdef NOT_FOR_L4 +#include +#endif +#include +#include +#include "pthread.h" +#include "internals.h" +#include "spinlock.h" +#include "queue.h" +#include "restart.h" + +int +attribute_hidden +__pthread_mutex_init(pthread_mutex_t * mutex, + const pthread_mutexattr_t * mutex_attr) +{ + __pthread_init_lock(&mutex->__m_lock); + mutex->__m_kind = + mutex_attr == NULL ? PTHREAD_MUTEX_TIMED_NP : mutex_attr->__mutexkind; + mutex->__m_count = 0; + mutex->__m_owner = NULL; + return 0; +} +strong_alias (__pthread_mutex_init, pthread_mutex_init) + +int +attribute_hidden +__pthread_mutex_destroy(pthread_mutex_t * mutex) +{ + switch (mutex->__m_kind) { + case PTHREAD_MUTEX_ADAPTIVE_NP: + case PTHREAD_MUTEX_RECURSIVE_NP: + if ((mutex->__m_lock.__status & 1) != 0) + return EBUSY; + return 0; + case PTHREAD_MUTEX_ERRORCHECK_NP: + case PTHREAD_MUTEX_TIMED_NP: + if (mutex->__m_lock.__status != 0) + return EBUSY; + return 0; + default: + return EINVAL; + } +} +strong_alias (__pthread_mutex_destroy, pthread_mutex_destroy) + +int +attribute_hidden +__pthread_mutex_trylock(pthread_mutex_t * mutex) +{ + pthread_descr self; + int retcode; + + switch(mutex->__m_kind) { + case PTHREAD_MUTEX_ADAPTIVE_NP: + retcode = __pthread_trylock(&mutex->__m_lock); + return retcode; + case PTHREAD_MUTEX_RECURSIVE_NP: + self = thread_self(); + if (mutex->__m_owner == self) { + mutex->__m_count++; + return 0; + } + retcode = __pthread_trylock(&mutex->__m_lock); + if (retcode == 0) { + mutex->__m_owner = self; + mutex->__m_count = 0; + } + return retcode; + case PTHREAD_MUTEX_ERRORCHECK_NP: + retcode = __pthread_alt_trylock(&mutex->__m_lock); + if (retcode == 0) { + mutex->__m_owner = thread_self(); + } + return retcode; + case PTHREAD_MUTEX_TIMED_NP: + retcode = __pthread_alt_trylock(&mutex->__m_lock); + return retcode; + default: + return EINVAL; + } +} +strong_alias (__pthread_mutex_trylock, pthread_mutex_trylock) + +int +attribute_hidden +__pthread_mutex_lock(pthread_mutex_t * mutex) +{ + pthread_descr self; + + switch(mutex->__m_kind) { + case PTHREAD_MUTEX_ADAPTIVE_NP: + __pthread_lock(&mutex->__m_lock, NULL); + return 0; + case PTHREAD_MUTEX_RECURSIVE_NP: + self = thread_self(); + if (mutex->__m_owner == self) { + mutex->__m_count++; + return 0; + } + __pthread_lock(&mutex->__m_lock, self); + mutex->__m_owner = self; + mutex->__m_count = 0; + return 0; + case PTHREAD_MUTEX_ERRORCHECK_NP: + self = thread_self(); + if (mutex->__m_owner == self) return EDEADLK; + __pthread_alt_lock(&mutex->__m_lock, self); + mutex->__m_owner = self; + return 0; + case PTHREAD_MUTEX_TIMED_NP: + __pthread_alt_lock(&mutex->__m_lock, NULL); + return 0; + default: + return EINVAL; + } +} + +strong_alias (__pthread_mutex_lock, pthread_mutex_lock) + + +int +attribute_hidden +__pthread_mutex_timedlock (pthread_mutex_t *mutex, + const struct timespec *abstime) +{ + pthread_descr self; + int res; + + if (__builtin_expect (abstime->tv_nsec, 0) < 0 + || __builtin_expect (abstime->tv_nsec, 0) >= 1000000000) + return EINVAL; + + switch(mutex->__m_kind) { + case PTHREAD_MUTEX_ADAPTIVE_NP: + __pthread_lock(&mutex->__m_lock, NULL); + return 0; + case PTHREAD_MUTEX_RECURSIVE_NP: + self = thread_self(); + if (mutex->__m_owner == self) { + mutex->__m_count++; + return 0; + } + __pthread_lock(&mutex->__m_lock, self); + mutex->__m_owner = self; + mutex->__m_count = 0; + return 0; + case PTHREAD_MUTEX_ERRORCHECK_NP: + self = thread_self(); + if (mutex->__m_owner == self) return EDEADLK; + res = __pthread_alt_timedlock(&mutex->__m_lock, self, abstime); + if (res != 0) + { + mutex->__m_owner = self; + return 0; + } + return ETIMEDOUT; + case PTHREAD_MUTEX_TIMED_NP: + /* Only this type supports timed out lock. */ + return (__pthread_alt_timedlock(&mutex->__m_lock, NULL, abstime) + ? 0 : ETIMEDOUT); + default: + return EINVAL; + } +} +strong_alias (__pthread_mutex_timedlock, pthread_mutex_timedlock) + +int +attribute_hidden +__pthread_mutex_unlock(pthread_mutex_t * mutex) +{ + switch (mutex->__m_kind) { + case PTHREAD_MUTEX_ADAPTIVE_NP: + __pthread_unlock(&mutex->__m_lock); + return 0; + case PTHREAD_MUTEX_RECURSIVE_NP: + if (mutex->__m_owner != thread_self()) + return EPERM; + if (mutex->__m_count > 0) { + mutex->__m_count--; + return 0; + } + mutex->__m_owner = NULL; + __pthread_unlock(&mutex->__m_lock); + return 0; + case PTHREAD_MUTEX_ERRORCHECK_NP: + if (mutex->__m_owner != thread_self() || mutex->__m_lock.__status == 0) + return EPERM; + mutex->__m_owner = NULL; + __pthread_alt_unlock(&mutex->__m_lock); + return 0; + case PTHREAD_MUTEX_TIMED_NP: + __pthread_alt_unlock(&mutex->__m_lock); + return 0; + default: + return EINVAL; + } +} +strong_alias (__pthread_mutex_unlock, pthread_mutex_unlock) + +int +attribute_hidden +__pthread_mutexattr_init(pthread_mutexattr_t *attr) +{ + attr->__mutexkind = PTHREAD_MUTEX_TIMED_NP; + return 0; +} +strong_alias (__pthread_mutexattr_init, pthread_mutexattr_init) + +int +attribute_hidden +__pthread_mutexattr_destroy(pthread_mutexattr_t *attr) +{ + return 0; +} +strong_alias (__pthread_mutexattr_destroy, pthread_mutexattr_destroy) + +int +attribute_hidden +__pthread_mutexattr_settype(pthread_mutexattr_t *attr, int kind) +{ + if (kind != PTHREAD_MUTEX_ADAPTIVE_NP + && kind != PTHREAD_MUTEX_RECURSIVE_NP + && kind != PTHREAD_MUTEX_ERRORCHECK_NP + && kind != PTHREAD_MUTEX_TIMED_NP) + return EINVAL; + attr->__mutexkind = kind; + return 0; +} +weak_alias (__pthread_mutexattr_settype, pthread_mutexattr_settype) +strong_alias ( __pthread_mutexattr_settype, __pthread_mutexattr_setkind_np) +weak_alias (__pthread_mutexattr_setkind_np, pthread_mutexattr_setkind_np) + +int +attribute_hidden +__pthread_mutexattr_gettype(const pthread_mutexattr_t *attr, int *kind) +{ + *kind = attr->__mutexkind; + return 0; +} +weak_alias (__pthread_mutexattr_gettype, pthread_mutexattr_gettype) +strong_alias (__pthread_mutexattr_gettype, __pthread_mutexattr_getkind_np) +weak_alias (__pthread_mutexattr_getkind_np, pthread_mutexattr_getkind_np) + +int +attribute_hidden +__pthread_mutexattr_getpshared (const pthread_mutexattr_t *attr, + int *pshared) +{ + *pshared = PTHREAD_PROCESS_PRIVATE; + return 0; +} +weak_alias (__pthread_mutexattr_getpshared, pthread_mutexattr_getpshared) + +int +attribute_hidden +__pthread_mutexattr_setpshared (pthread_mutexattr_t *attr, int pshared) +{ + if (pshared != PTHREAD_PROCESS_PRIVATE && pshared != PTHREAD_PROCESS_SHARED) + return EINVAL; + + /* For now it is not possible to shared a conditional variable. */ + if (pshared != PTHREAD_PROCESS_PRIVATE) + return ENOSYS; + + return 0; +} +weak_alias (__pthread_mutexattr_setpshared, pthread_mutexattr_setpshared) + +/* Once-only execution */ + +static pthread_mutex_t once_masterlock = PTHREAD_MUTEX_INITIALIZER; +static pthread_cond_t once_finished = PTHREAD_COND_INITIALIZER; +static int fork_generation = 0; /* Child process increments this after fork. */ + +enum { NEVER = 0, IN_PROGRESS = 1, DONE = 2 }; + +/* If a thread is canceled while calling the init_routine out of + pthread once, this handler will reset the once_control variable + to the NEVER state. */ + +static void pthread_once_cancelhandler(void *arg) +{ + pthread_once_t *once_control = arg; + + pthread_mutex_lock(&once_masterlock); + *once_control = NEVER; + pthread_mutex_unlock(&once_masterlock); + pthread_cond_broadcast(&once_finished); +} + +int +attribute_hidden +__pthread_once(pthread_once_t * once_control, void (*init_routine)(void)) +{ + /* flag for doing the condition broadcast outside of mutex */ + int state_changed; + + /* Test without locking first for speed */ + if (*once_control == DONE) { + READ_MEMORY_BARRIER(); + return 0; + } + /* Lock and test again */ + + state_changed = 0; + + pthread_mutex_lock(&once_masterlock); + + /* If this object was left in an IN_PROGRESS state in a parent + process (indicated by stale generation field), reset it to NEVER. */ + if ((*once_control & 3) == IN_PROGRESS && (*once_control & ~3) != fork_generation) + *once_control = NEVER; + + /* If init_routine is being called from another routine, wait until + it completes. */ + while ((*once_control & 3) == IN_PROGRESS) { + pthread_cond_wait(&once_finished, &once_masterlock); + } + /* Here *once_control is stable and either NEVER or DONE. */ + if (*once_control == NEVER) { + *once_control = IN_PROGRESS | fork_generation; + pthread_mutex_unlock(&once_masterlock); + pthread_cleanup_push(pthread_once_cancelhandler, once_control); + init_routine(); + pthread_cleanup_pop(0); + pthread_mutex_lock(&once_masterlock); + WRITE_MEMORY_BARRIER(); + *once_control = DONE; + state_changed = 1; + } + pthread_mutex_unlock(&once_masterlock); + + if (state_changed) + pthread_cond_broadcast(&once_finished); + + return 0; +} +strong_alias (__pthread_once, pthread_once) + +/* + * Handle the state of the pthread_once mechanism across forks. The + * once_masterlock is acquired in the parent process prior to a fork to ensure + * that no thread is in the critical region protected by the lock. After the + * fork, the lock is released. In the child, the lock and the condition + * variable are simply reset. The child also increments its generation + * counter which lets pthread_once calls detect stale IN_PROGRESS states + * and reset them back to NEVER. + */ + +void +attribute_hidden +__pthread_once_fork_prepare(void) +{ + pthread_mutex_lock(&once_masterlock); +} + +void +attribute_hidden +__pthread_once_fork_parent(void) +{ + pthread_mutex_unlock(&once_masterlock); +} + +void +attribute_hidden +__pthread_once_fork_child(void) +{ + pthread_mutex_init(&once_masterlock, NULL); + pthread_cond_init(&once_finished, NULL); + if (fork_generation <= INT_MAX - 4) + fork_generation += 4; /* leave least significant two bits zero */ + else + fork_generation = 0; +} diff --git a/l4/pkg/uclibc/lib/libpthread/src/pt-initfini.c b/l4/pkg/uclibc/lib/libpthread/src/pt-initfini.c new file mode 100644 index 00000000..15aeb216 --- /dev/null +++ b/l4/pkg/uclibc/lib/libpthread/src/pt-initfini.c @@ -0,0 +1,124 @@ +/* Special .init and .fini section support. Linuxthread version. + Copyright (C) 1995, 1996, 1997, 2000, 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it + and/or modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file with other + programs, and to distribute those programs without any restriction + coming from the use of this file. (The Lesser General Public + License restrictions do apply in other respects; for example, they + cover modification of the file, and distribution when not linked + into another program.) + + The GNU C Library is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* This file is compiled into assembly code which is then munged by a sed + script into two files: crti.s and crtn.s. + + * crti.s puts a function prologue at the beginning of the + .init and .fini sections and defines global symbols for + those addresses, so they can be called as functions. + + * crtn.s puts the corresponding function epilogues + in the .init and .fini sections. */ + +#include + +/* We use embedded asm for .section unconditionally, as this makes it + easier to insert the necessary directives into crtn.S. */ +#define SECTION(x) __asm__ (".section " x ) + +/* Embed an #include to pull in the alignment and .end directives. */ +__asm__ ("\n#include \"defs.h\""); + +/* The initial common code ends here. */ +__asm__ ("\n/*@HEADER_ENDS*/"); + +/* To determine whether we need .end and .align: */ +__asm__ ("\n/*@TESTS_BEGIN*/"); +extern void dummy (void (*foo) (void)); +void +dummy (void (*foo) (void)) +{ + if (foo) + (*foo) (); +} +__asm__ ("\n/*@TESTS_END*/"); + +/* The beginning of _init: */ +__asm__ ("\n/*@_init_PROLOG_BEGINS*/"); + +static void +call_initialize_minimal (void) +{ + extern void __pthread_initialize_minimal (void); + + __pthread_initialize_minimal (); +} + +SECTION (".init"); +extern void _init (void); +void +_init (void) +{ + /* The very first thing we must do is to set up the registers. */ + call_initialize_minimal (); + + __asm__ ("ALIGN"); + __asm__("END_INIT"); + /* Now the epilog. */ + __asm__ ("\n/*@_init_PROLOG_ENDS*/"); + __asm__ ("\n/*@_init_EPILOG_BEGINS*/"); + SECTION(".init"); +} +__asm__ ("END_INIT"); + +/* End of the _init epilog, beginning of the _fini prolog. */ +__asm__ ("\n/*@_init_EPILOG_ENDS*/"); +__asm__ ("\n/*@_fini_PROLOG_BEGINS*/"); + +SECTION (".fini"); +extern void _fini (void); +void +_fini (void) +{ + + /* End of the _fini prolog. */ + __asm__ ("ALIGN"); + __asm__ ("END_FINI"); + __asm__ ("\n/*@_fini_PROLOG_ENDS*/"); + + { + /* Let GCC know that _fini is not a leaf function by having a dummy + function call here. We arrange for this call to be omitted from + either crt file. */ + extern void i_am_not_a_leaf (void); + i_am_not_a_leaf (); + } + + /* Beginning of the _fini epilog. */ + __asm__ ("\n/*@_fini_EPILOG_BEGINS*/"); + SECTION (".fini"); +} +__asm__ ("END_FINI"); + +/* End of the _fini epilog. Any further generated assembly (e.g. .ident) + is shared between both crt files. */ +__asm__ ("\n/*@_fini_EPILOG_ENDS*/"); +__asm__ ("\n/*@TRAILER_BEGINS*/"); + +/* End of file. */ diff --git a/l4/pkg/uclibc/lib/libpthread/src/ptcleanup.c b/l4/pkg/uclibc/lib/libpthread/src/ptcleanup.c new file mode 100644 index 00000000..3aa821ad --- /dev/null +++ b/l4/pkg/uclibc/lib/libpthread/src/ptcleanup.c @@ -0,0 +1,78 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1998 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +/* Redefine siglongjmp and longjmp so that they interact correctly + with cleanup handlers */ + +#define NO_PTR_DEMANGLE + +#include +#include "pthread.h" +#include "internals.h" +#ifndef NO_PTR_DEMANGLE +#include +#define __JMPBUF_UNWINDS(a,b,c) _JMPBUF_UNWINDS(a,b,c) +#else +#define __JMPBUF_UNWINDS(a,b,c) _JMPBUF_UNWINDS(a,b) +#endif + +#ifndef NO_PTR_DEMANGLE +static __inline__ uintptr_t +demangle_ptr (uintptr_t x) +{ +#ifdef PTR_DEMANGLE + PTR_DEMANGLE (x); +#endif + return x; +} +#else +#define demangle_ptr(x) x +#endif + +void +attribute_hidden +__pthread_cleanup_upto (__jmp_buf target, char *targetframe) +{ + pthread_descr self = thread_self(); + struct _pthread_cleanup_buffer * c; + + for (c = THREAD_GETMEM(self, p_cleanup); + c != NULL && __JMPBUF_UNWINDS(target, c, demangle_ptr); + c = c->__prev) + { +#if _STACK_GROWS_DOWN + if ((char *) c <= targetframe) + { + c = NULL; + break; + } +#elif _STACK_GROWS_UP + if ((char *) c >= targetframe) + { + c = NULL; + break; + } +#else +# error "Define either _STACK_GROWS_DOWN or _STACK_GROWS_UP" +#endif + c->__routine(c->__arg); + } + THREAD_SETMEM(self, p_cleanup, c); +#ifdef NOT_FOR_L4 + if (THREAD_GETMEM(self, p_in_sighandler) + && __JMPBUF_UNWINDS(target, THREAD_GETMEM(self, p_in_sighandler), + demangle_ptr)) + THREAD_SETMEM(self, p_in_sighandler, NULL); +#endif +} diff --git a/l4/pkg/uclibc/lib/libpthread/src/pthread-functions.h b/l4/pkg/uclibc/lib/libpthread/src/pthread-functions.h new file mode 100644 index 00000000..69e3639c --- /dev/null +++ b/l4/pkg/uclibc/lib/libpthread/src/pthread-functions.h @@ -0,0 +1,104 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2003. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _PTHREAD_FUNCTIONS_H +#define _PTHREAD_FUNCTIONS_H 1 + +#include +#include +#include "descr.h" + +struct fork_block; + +/* Data type shared with libc. The libc uses it to pass on calls to + the thread functions. Wine pokes directly into this structure, + so if possible avoid breaking it and append new hooks to the end. */ +struct pthread_functions +{ + pid_t (*ptr_pthread_fork) (struct fork_block *); + int (*ptr_pthread_attr_destroy) (pthread_attr_t *); + int (*ptr_pthread_attr_init) (pthread_attr_t *); + int (*ptr_pthread_attr_getdetachstate) (const pthread_attr_t *, int *); + int (*ptr_pthread_attr_setdetachstate) (pthread_attr_t *, int); + int (*ptr_pthread_attr_getinheritsched) (const pthread_attr_t *, int *); + int (*ptr_pthread_attr_setinheritsched) (pthread_attr_t *, int); + int (*ptr_pthread_attr_getschedparam) (const pthread_attr_t *, + struct sched_param *); + int (*ptr_pthread_attr_setschedparam) (pthread_attr_t *, + const struct sched_param *); + int (*ptr_pthread_attr_getschedpolicy) (const pthread_attr_t *, int *); + int (*ptr_pthread_attr_setschedpolicy) (pthread_attr_t *, int); + int (*ptr_pthread_attr_getscope) (const pthread_attr_t *, int *); + int (*ptr_pthread_attr_setscope) (pthread_attr_t *, int); + int (*ptr_pthread_condattr_destroy) (pthread_condattr_t *); + int (*ptr_pthread_condattr_init) (pthread_condattr_t *); + int (*ptr_pthread_cond_broadcast) (pthread_cond_t *); + int (*ptr_pthread_cond_destroy) (pthread_cond_t *); + int (*ptr_pthread_cond_init) (pthread_cond_t *, + const pthread_condattr_t *); + int (*ptr_pthread_cond_signal) (pthread_cond_t *); + int (*ptr_pthread_cond_wait) (pthread_cond_t *, pthread_mutex_t *); + int (*ptr_pthread_equal) (pthread_t, pthread_t); + void (*ptr___pthread_exit) (void *); + int (*ptr_pthread_getschedparam) (pthread_t, int *, struct sched_param *); + int (*ptr_pthread_setschedparam) (pthread_t, int, + const struct sched_param *); + int (*ptr_pthread_mutex_destroy) (pthread_mutex_t *); + int (*ptr_pthread_mutex_init) (pthread_mutex_t *, + const pthread_mutexattr_t *); + int (*ptr_pthread_mutex_lock) (pthread_mutex_t *); + int (*ptr_pthread_mutex_trylock) (pthread_mutex_t *); + int (*ptr_pthread_mutex_unlock) (pthread_mutex_t *); + pthread_t (*ptr_pthread_self) (void); + int (*ptr_pthread_setcancelstate) (int, int *); + int (*ptr_pthread_setcanceltype) (int, int *); + void (*ptr_pthread_do_exit) (void *retval, char *currentframe); + void (*ptr_pthread_cleanup_upto) (__jmp_buf target, + char *targetframe); + pthread_descr (*ptr_pthread_thread_self) (void); + int (*ptr_pthread_internal_tsd_set) (int key, const void *pointer); + void * (*ptr_pthread_internal_tsd_get) (int key); + void ** __attribute__ ((__const__)) + (*ptr_pthread_internal_tsd_address) (int key); +#ifdef __NOT_FOR_L4__ + int (*ptr_pthread_sigaction) (int sig, const struct sigaction * act, + struct sigaction *oact); + int (*ptr_pthread_sigwait) (const sigset_t *set, int *sig); + int (*ptr_pthread_raise) (int sig); +#else + void *ptr_pthread_sigaction; + void *ptr_pthread_sigwait; + void *ptr_pthread_raise; +#endif + int (*ptr_pthread_cond_timedwait) (pthread_cond_t *, pthread_mutex_t *, + const struct timespec *); + void (*ptr__pthread_cleanup_push) (struct _pthread_cleanup_buffer * buffer, + void (*routine)(void *), void * arg); + void (*ptr__pthread_cleanup_push_defer) (struct _pthread_cleanup_buffer * buffer, + void (*routine)(void *), void * arg); + void (*ptr__pthread_cleanup_pop) (struct _pthread_cleanup_buffer * buffer, + int execute); + void (*ptr__pthread_cleanup_pop_restore) (struct _pthread_cleanup_buffer * buffer, + int execute); +}; + +/* Variable in libc.so. */ +extern struct pthread_functions __libc_pthread_functions attribute_hidden; + +#endif /* pthread-functions.h */ diff --git a/l4/pkg/uclibc/lib/libpthread/src/pthread.c b/l4/pkg/uclibc/lib/libpthread/src/pthread.c new file mode 100644 index 00000000..abe67bad --- /dev/null +++ b/l4/pkg/uclibc/lib/libpthread/src/pthread.c @@ -0,0 +1,1502 @@ + +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +/* Thread creation, initialization, and basic low-level routines */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "pthread.h" +#include "internals.h" +#include "spinlock.h" +#include "restart.h" +#include "smp.h" +#include +#include +#include + +/* Sanity check. */ +#if !defined __SIGRTMIN || (__SIGRTMAX - __SIGRTMIN) < 3 +# error "This must not happen" +#endif + +/* mods for uClibc: __libc_sigaction is not in any standard headers */ +extern __typeof(sigaction) __libc_sigaction; + +#if !(USE_TLS && HAVE___THREAD) +/* These variables are used by the setup code. */ +extern int _errno; +extern int _h_errno; + +# if defined __UCLIBC_HAS_IPv4__ || defined __UCLIBC_HAS_IPV6__ +/* We need the global/static resolver state here. */ +# include +# undef _res +extern struct __res_state *__resp; +# endif +#endif + +#ifdef USE_TLS + +/* We need only a few variables. */ +#define manager_thread __pthread_manager_threadp +pthread_descr __pthread_manager_threadp attribute_hidden; + +#else + +/* Descriptor of the initial thread */ + +struct _pthread_descr_struct __pthread_initial_thread = { + .p_header.data.self = &__pthread_initial_thread, + .p_nextlive = &__pthread_initial_thread, + .p_prevlive = &__pthread_initial_thread, +#ifdef NOT_FOR_L4 + .p_tid = PTHREAD_THREADS_MAX, + .p_lock = &__pthread_handles[0].h_lock, +#endif + .p_start_args = PTHREAD_START_ARGS_INITIALIZER(NULL), +#if !(USE_TLS && HAVE___THREAD) + .p_errnop = &_errno, + .p_h_errnop = &_h_errno, +#endif + .p_userstack = 1, + .p_resume_count = __ATOMIC_INITIALIZER, + .p_alloca_cutoff = __MAX_ALLOCA_CUTOFF +}; + +/* Descriptor of the manager thread; none of this is used but the error + variables, the p_pid and p_priority fields, + and the address for identification. */ + +#define manager_thread (&__pthread_manager_thread) +struct _pthread_descr_struct __pthread_manager_thread = { + .p_header.data.self = &__pthread_manager_thread, + .p_header.data.multiple_threads = 1, +#ifdef NOT_FOR_L4 + .p_lock = &__pthread_handles[1].h_lock, +#endif + .p_start_args = PTHREAD_START_ARGS_INITIALIZER(__pthread_manager), +#if !(USE_TLS && HAVE___THREAD) + .p_errnop = &__pthread_manager_thread.p_errno, +#endif +#ifdef NOT_FOR_L4 + .p_nr = 1, +#endif + .p_resume_count = __ATOMIC_INITIALIZER, + .p_alloca_cutoff = PTHREAD_STACK_MIN / 4 +}; +#endif + +/* Pointer to the main thread (the father of the thread manager thread) */ +/* Originally, this is the initial thread, but this changes after fork() */ + +#ifdef USE_TLS +pthread_descr __pthread_main_thread; +#else +pthread_descr __pthread_main_thread = &__pthread_initial_thread; +#endif + +/* Limit between the stack of the initial thread (above) and the + stacks of other threads (below). Aligned on a STACK_SIZE boundary. */ + +char *__pthread_initial_thread_bos; + +/* File descriptor for sending requests to the thread manager. */ +/* Initially -1, meaning that the thread manager is not running. */ + +l4_cap_idx_t __pthread_manager_request = L4_INVALID_CAP; + +int __pthread_multiple_threads attribute_hidden; + +/* Other end of the pipe for sending requests to the thread manager. */ + +int __pthread_manager_reader; + +/* Limits of the thread manager stack */ + +char *__pthread_manager_thread_bos; +char *__pthread_manager_thread_tos; + +/* For process-wide exit() */ + +int __pthread_exit_requested; +int __pthread_exit_code; + +/* Maximum stack size. */ +size_t __pthread_max_stacksize; + +/* Nozero if the machine has more than one processor. */ +int __pthread_smp_kernel; + + +#if !__ASSUME_REALTIME_SIGNALS +/* Pointers that select new or old suspend/resume functions + based on availability of rt signals. */ + +#ifdef NOT_FOR_L4 +void (*__pthread_restart)(pthread_descr) = __pthread_restart_old; +void (*__pthread_suspend)(pthread_descr) = __pthread_suspend_old; +int (*__pthread_timedsuspend)(pthread_descr, const struct timespec *) = __pthread_timedsuspend_old; +#endif +#endif /* __ASSUME_REALTIME_SIGNALS */ + +/* Communicate relevant LinuxThreads constants to gdb */ + +#ifdef NOT_FOR_L4 +const int __pthread_threads_max = PTHREAD_THREADS_MAX; +const int __pthread_sizeof_handle = sizeof(struct pthread_handle_struct); +const int __pthread_offsetof_descr = offsetof(struct pthread_handle_struct, + h_descr); +const int __pthread_offsetof_pid = offsetof(struct _pthread_descr_struct, + p_pid); +#endif +const int __linuxthreads_pthread_sizeof_descr + = sizeof(struct _pthread_descr_struct); + +const int __linuxthreads_initial_report_events; + +const char __linuxthreads_version[] = VERSION; + +/* Forward declarations */ + +static void pthread_onexit_process(int retcode, void *arg); +#ifndef HAVE_Z_NODELETE +static void pthread_atexit_process(void *arg, int retcode); +static void pthread_atexit_retcode(void *arg, int retcode); +#endif +#ifdef NOT_FOR_L4 +static void pthread_handle_sigcancel(int sig); +static void pthread_handle_sigrestart(int sig); +static void pthread_handle_sigdebug(int sig); +#endif + +/* Signal numbers used for the communication. + In these variables we keep track of the used variables. If the + platform does not support any real-time signals we will define the + values to some unreasonable value which will signal failing of all + the functions below. */ +int __pthread_sig_restart = __SIGRTMIN; +int __pthread_sig_cancel = __SIGRTMIN + 1; +int __pthread_sig_debug = __SIGRTMIN + 2; + +extern int __libc_current_sigrtmin_private (void); + +#ifdef NOT_FOR_L4 +#if !__ASSUME_REALTIME_SIGNALS +static int rtsigs_initialized; + +static void +init_rtsigs (void) +{ + if (rtsigs_initialized) + return; + + if (__libc_current_sigrtmin_private () == -1) + { + __pthread_sig_restart = SIGUSR1; + __pthread_sig_cancel = SIGUSR2; + __pthread_sig_debug = 0; + } + else + { + __pthread_restart = __pthread_restart_new; + __pthread_suspend = __pthread_wait_for_restart_signal; + __pthread_timedsuspend = __pthread_timedsuspend_new; + } + + rtsigs_initialized = 1; +} +#endif +#endif + + +/* Initialize the pthread library. + Initialization is split in two functions: + - a constructor function that blocks the __pthread_sig_restart signal + (must do this very early, since the program could capture the signal + mask with e.g. sigsetjmp before creating the first thread); + - a regular function called from pthread_create when needed. */ + +static void pthread_initialize(void) __attribute__((constructor)); + +#ifndef HAVE_Z_NODELETE +extern void *__dso_handle __attribute__ ((weak)); +#endif + + +#if defined USE_TLS && !defined SHARED +extern void __libc_setup_tls (size_t tcbsize, size_t tcbalign); +#endif + +struct pthread_functions __pthread_functions = + { +#if !(USE_TLS && HAVE___THREAD) + .ptr_pthread_internal_tsd_set = __pthread_internal_tsd_set, + .ptr_pthread_internal_tsd_get = __pthread_internal_tsd_get, + .ptr_pthread_internal_tsd_address = __pthread_internal_tsd_address, +#endif +#ifdef __NOT_FOR_L4__ + .ptr_pthread_fork = __pthread_fork, +#else + .ptr_pthread_fork = NULL, +#endif + .ptr_pthread_attr_destroy = __pthread_attr_destroy, + .ptr_pthread_attr_init = __pthread_attr_init, + .ptr_pthread_attr_getdetachstate = __pthread_attr_getdetachstate, + .ptr_pthread_attr_setdetachstate = __pthread_attr_setdetachstate, + .ptr_pthread_attr_getinheritsched = __pthread_attr_getinheritsched, + .ptr_pthread_attr_setinheritsched = __pthread_attr_setinheritsched, + .ptr_pthread_attr_getschedparam = __pthread_attr_getschedparam, + .ptr_pthread_attr_setschedparam = __pthread_attr_setschedparam, + .ptr_pthread_attr_getschedpolicy = __pthread_attr_getschedpolicy, + .ptr_pthread_attr_setschedpolicy = __pthread_attr_setschedpolicy, + .ptr_pthread_attr_getscope = __pthread_attr_getscope, + .ptr_pthread_attr_setscope = __pthread_attr_setscope, + .ptr_pthread_condattr_destroy = __pthread_condattr_destroy, + .ptr_pthread_condattr_init = __pthread_condattr_init, + .ptr_pthread_cond_broadcast = __pthread_cond_broadcast, + .ptr_pthread_cond_destroy = __pthread_cond_destroy, + .ptr_pthread_cond_init = __pthread_cond_init, + .ptr_pthread_cond_signal = __pthread_cond_signal, + .ptr_pthread_cond_wait = __pthread_cond_wait, + .ptr_pthread_cond_timedwait = __pthread_cond_timedwait, + .ptr_pthread_equal = __pthread_equal, + .ptr___pthread_exit = __pthread_exit, + .ptr_pthread_getschedparam = __pthread_getschedparam, + .ptr_pthread_setschedparam = __pthread_setschedparam, + .ptr_pthread_mutex_destroy = __pthread_mutex_destroy, + .ptr_pthread_mutex_init = __pthread_mutex_init, + .ptr_pthread_mutex_lock = __pthread_mutex_lock, + .ptr_pthread_mutex_trylock = __pthread_mutex_trylock, + .ptr_pthread_mutex_unlock = __pthread_mutex_unlock, + .ptr_pthread_self = __pthread_self, + .ptr_pthread_setcancelstate = __pthread_setcancelstate, + .ptr_pthread_setcanceltype = __pthread_setcanceltype, + .ptr_pthread_do_exit = __pthread_do_exit, + .ptr_pthread_thread_self = __pthread_thread_self, + .ptr_pthread_cleanup_upto = __pthread_cleanup_upto, +#ifdef __NOT_FOR_L4__ + .ptr_pthread_sigaction = __pthread_sigaction, + .ptr_pthread_sigwait = __pthread_sigwait, + .ptr_pthread_raise = __pthread_raise, +#else + .ptr_pthread_sigaction = NULL, + .ptr_pthread_sigwait = NULL, + .ptr_pthread_raise = NULL, +#endif + .ptr__pthread_cleanup_push = __pthread_cleanup_push, + .ptr__pthread_cleanup_push_defer = __pthread_cleanup_push_defer, + .ptr__pthread_cleanup_pop = __pthread_cleanup_pop, + .ptr__pthread_cleanup_pop_restore = __pthread_cleanup_pop_restore, + }; +#ifdef SHARED +# define ptr_pthread_functions &__pthread_functions +#else +# define ptr_pthread_functions NULL +#endif + +static int *__libc_multiple_threads_ptr; +l4_utcb_t *__pthread_first_free_handle attribute_hidden; + +void +__l4_add_utcbs(l4_addr_t start, l4_addr_t utcbs_end) +{ + l4_addr_t free_utcb = start; + + l4_utcb_t **last_free = &__pthread_first_free_handle; + while ((l4_addr_t)free_utcb + L4_UTCB_OFFSET <= utcbs_end) + { + l4_utcb_t *u = (l4_utcb_t*)free_utcb; + l4_thread_regs_t *tcr = l4_utcb_tcr_u(u); + tcr->user[0] = 0; + __pthread_init_lock(handle_to_lock(u)); + *last_free = u; + last_free = (l4_utcb_t**)(&tcr->user[0]); + free_utcb += L4_UTCB_OFFSET; + } + +} + +/* Do some minimal initialization which has to be done during the + startup of the C library. */ +void +__pthread_initialize_minimal(void) +{ + static int initialized; + if (initialized) + return; + + initialized = 1; + + /* initialize free list */ + l4_fpage_t utcb_area = l4re_env()->utcb_area; + l4_addr_t free_utcb = l4re_env()->first_free_utcb; + l4_addr_t utcbs_end = ((l4_addr_t)l4_fpage_page(utcb_area) << 12UL) + + (1UL << (l4_addr_t)l4_fpage_size(utcb_area)); + __l4_add_utcbs(free_utcb, utcbs_end); + /* All in the free pool now so indicate that first_free_utcb not available + * anymore */ + l4re_env()->first_free_utcb = ~0UL; + + __pthread_init_lock(handle_to_lock(l4_utcb())); + +#ifdef USE_TLS + pthread_descr self; + + /* First of all init __pthread_handles[0] and [1] if needed. */ +# if __LT_SPINLOCK_INIT != 0 + __pthread_handles[0].h_lock = __LOCK_INITIALIZER; + __pthread_handles[1].h_lock = __LOCK_INITIALIZER; +# endif +# ifndef SHARED + /* Unlike in the dynamically linked case the dynamic linker has not + taken care of initializing the TLS data structures. */ + __libc_setup_tls (TLS_TCB_SIZE, TLS_TCB_ALIGN); +# elif !USE___THREAD + if (__builtin_expect (GL(dl_tls_dtv_slotinfo_list) == NULL, 0)) + { + tcbhead_t *tcbp; + + /* There is no actual TLS being used, so the thread register + was not initialized in the dynamic linker. */ + + /* We need to install special hooks so that the malloc and memalign + calls in _dl_tls_setup and _dl_allocate_tls won't cause full + malloc initialization that will try to set up its thread state. */ + + extern void __libc_malloc_pthread_startup (bool first_time); + __libc_malloc_pthread_startup (true); + + if (__builtin_expect (_dl_tls_setup (), 0) + || __builtin_expect ((tcbp = _dl_allocate_tls (NULL)) == NULL, 0)) + { + static const char msg[] = "\ +cannot allocate TLS data structures for initial thread\n"; + TEMP_FAILURE_RETRY (write_not_cancel (STDERR_FILENO, + msg, sizeof msg - 1)); + abort (); + } + const char *lossage = TLS_INIT_TP (tcbp, 0); + if (__builtin_expect (lossage != NULL, 0)) + { + static const char msg[] = "cannot set up thread-local storage: "; + const char nl = '\n'; + TEMP_FAILURE_RETRY (write_not_cancel (STDERR_FILENO, + msg, sizeof msg - 1)); + TEMP_FAILURE_RETRY (write_not_cancel (STDERR_FILENO, + lossage, strlen (lossage))); + TEMP_FAILURE_RETRY (write_not_cancel (STDERR_FILENO, &nl, 1)); + } + + /* Though it was allocated with libc's malloc, that was done without + the user's __malloc_hook installed. A later realloc that uses + the hooks might not work with that block from the plain malloc. + So we record this block as unfreeable just as the dynamic linker + does when it allocates the DTV before the libc malloc exists. */ + GL(dl_initial_dtv) = GET_DTV (tcbp); + + __libc_malloc_pthread_startup (false); + } +# endif + + self = THREAD_SELF; + + /* The memory for the thread descriptor was allocated elsewhere as + part of the TLS allocation. We have to initialize the data + structure by hand. This initialization must mirror the struct + definition above. */ + self->p_nextlive = self->p_prevlive = self; +#if defined NOT_FOR_L4 + self->p_tid = PTHREAD_THREADS_MAX; + self->p_lock = &__pthread_handles[0].h_lock; +#endif +# ifndef HAVE___THREAD + self->p_errnop = &_errno; + self->p_h_errnop = &_h_errno; +# endif + /* self->p_start_args need not be initialized, it's all zero. */ + self->p_userstack = 1; +# if __LT_SPINLOCK_INIT != 0 + self->p_resume_count = (struct pthread_atomic) __ATOMIC_INITIALIZER; +# endif + self->p_alloca_cutoff = __MAX_ALLOCA_CUTOFF; + + /* Another variable which points to the thread descriptor. */ + __pthread_main_thread = self; + + /* And fill in the pointer the the thread __pthread_handles array. */ +#ifdef NOT_FOR_L4 + __pthread_handles[0].h_descr = self; +#endif + +#else /* USE_TLS */ + + /* First of all init __pthread_handles[0] and [1]. */ +# if __LT_SPINLOCK_INIT != 0 + __pthread_handles[0].h_lock = __LOCK_INITIALIZER; + __pthread_handles[1].h_lock = __LOCK_INITIALIZER; +# endif +#ifdef NOT_FOR_L4 + __pthread_handles[0].h_descr = &__pthread_initial_thread; + __pthread_handles[1].h_descr = &__pthread_manager_thread; +#endif + + /* If we have special thread_self processing, initialize that for the + main thread now. */ +# ifdef INIT_THREAD_SELF + INIT_THREAD_SELF(&__pthread_initial_thread, 0); +# endif +#endif + +#if HP_TIMING_AVAIL +# ifdef USE_TLS + self->p_cpuclock_offset = GL(dl_cpuclock_offset); +# else + __pthread_initial_thread.p_cpuclock_offset = GL(dl_cpuclock_offset); +# endif +#endif +#ifndef NOT_FOR_L4 +# ifdef USE_TLS + if (__pthread_l4_initialize_main_thread(self)) +# else + if (__pthread_l4_initialize_main_thread(&__pthread_initial_thread)) +# endif + exit(1); +#endif + __libc_multiple_threads_ptr = __libc_pthread_init (ptr_pthread_functions); +} + + +void +__pthread_init_max_stacksize(void) +{ +#ifdef NOT_FOR_L4 + struct rlimit limit; +#endif + size_t max_stack; + +#ifdef NOT_FOR_L4 + getrlimit(RLIMIT_STACK, &limit); +#ifdef FLOATING_STACKS + if (limit.rlim_cur == RLIM_INFINITY) + limit.rlim_cur = ARCH_STACK_MAX_SIZE; +# ifdef NEED_SEPARATE_REGISTER_STACK + max_stack = limit.rlim_cur / 2; +# else + max_stack = limit.rlim_cur; +# endif +#else + /* Play with the stack size limit to make sure that no stack ever grows + beyond STACK_SIZE minus one page (to act as a guard page). */ +# ifdef NEED_SEPARATE_REGISTER_STACK + /* STACK_SIZE bytes hold both the main stack and register backing + store. The rlimit value applies to each individually. */ + max_stack = STACK_SIZE/2 - __getpagesize (); +# else + max_stack = STACK_SIZE - __getpagesize(); +# endif + if (limit.rlim_cur > max_stack) { + limit.rlim_cur = max_stack; + setrlimit(RLIMIT_STACK, &limit); + } +#endif +#endif + + // L4 + max_stack = STACK_SIZE - L4_PAGESIZE; + + __pthread_max_stacksize = max_stack; + if (max_stack / 4 < __MAX_ALLOCA_CUTOFF) + { +#ifdef USE_TLS + pthread_descr self = THREAD_SELF; + self->p_alloca_cutoff = max_stack / 4; +#else + __pthread_initial_thread.p_alloca_cutoff = max_stack / 4; +#endif + } +} + +/* psm: we do not have any ld.so support yet + * remove the USE_TLS guard if nptl is added */ +#if defined SHARED && defined USE_TLS +# if USE___THREAD +/* When using __thread for this, we do it in libc so as not + to give libpthread its own TLS segment just for this. */ +extern void **__libc_dl_error_tsd (void) __attribute__ ((const)); +# else +static void ** __attribute__ ((const)) +__libc_dl_error_tsd (void) +{ + return &thread_self ()->p_libc_specific[_LIBC_TSD_KEY_DL_ERROR]; +} +# endif +#endif + +#ifdef USE_TLS +static __inline__ void __attribute__((always_inline)) +init_one_static_tls (pthread_descr descr, struct link_map *map) +{ +# if defined(TLS_TCB_AT_TP) + dtv_t *dtv = GET_DTV (descr); + void *dest = (char *) descr - map->l_tls_offset; +# elif defined(TLS_DTV_AT_TP) + dtv_t *dtv = GET_DTV ((pthread_descr) ((char *) descr + TLS_PRE_TCB_SIZE)); + void *dest = (char *) descr + map->l_tls_offset + TLS_PRE_TCB_SIZE; +# else +# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined" +# endif + + /* Fill in the DTV slot so that a later LD/GD access will find it. */ + dtv[map->l_tls_modid].pointer.val = dest; + dtv[map->l_tls_modid].pointer.is_static = true; + + /* Initialize the memory. */ + memset (mempcpy (dest, map->l_tls_initimage, map->l_tls_initimage_size), + '\0', map->l_tls_blocksize - map->l_tls_initimage_size); +} + +static void +__pthread_init_static_tls (struct link_map *map) +{ + pthread_descr th; + + for (th = __pthread_main_thread->p_nextlive; + th != __pthread_main_thread; + th = th->p_nextlive) + { + init_one_static_tls(th, map); + } +} +#endif + +static void pthread_initialize(void) +{ +#ifdef NOT_USED + struct sigaction sa; + sigset_t mask; +#endif + + /* If already done (e.g. by a constructor called earlier!), bail out */ + if (__pthread_initial_thread_bos != NULL) return; +#ifdef TEST_FOR_COMPARE_AND_SWAP + /* Test if compare-and-swap is available */ + __pthread_has_cas = compare_and_swap_is_available(); +#endif + /* We don't need to know the bottom of the stack. Give the pointer some + value to signal that initialization happened. */ + __pthread_initial_thread_bos = (void *) -1l; +#ifdef USE_TLS +#ifdef NOT_FOR_L4 + /* Update the descriptor for the initial thread. */ + THREAD_SETMEM (((pthread_descr) NULL), p_pid, __getpid()); +#endif +# if !defined HAVE___THREAD && (defined __UCLIBC_HAS_IPv4__ || defined __UCLIBC_HAS_IPV6__) + /* Likewise for the resolver state _res. */ + THREAD_SETMEM (((pthread_descr) NULL), p_resp, __resp); +# endif +#else +#endif + /* Register an exit function to kill all other threads. */ + /* Do it early so that user-registered atexit functions are called + before pthread_*exit_process. */ +#ifndef HAVE_Z_NODELETE + if (__builtin_expect (&__dso_handle != NULL, 1)) + __cxa_atexit ((void (*) (void *)) pthread_atexit_process, NULL, + __dso_handle); + else +#endif + __on_exit (pthread_onexit_process, NULL); + /* How many processors. */ + __pthread_smp_kernel = is_smp_system (); + +/* psm: we do not have any ld.so support yet + * remove the USE_TLS guard if nptl is added */ +#if defined SHARED && defined USE_TLS + /* Transfer the old value from the dynamic linker's internal location. */ + *__libc_dl_error_tsd () = *(*GL(dl_error_catch_tsd)) (); + GL(dl_error_catch_tsd) = &__libc_dl_error_tsd; + +#endif + +#ifdef USE_TLS + GL(dl_init_static_tls) = &__pthread_init_static_tls; +#endif + + /* uClibc-specific stdio initialization for threads. */ + { + FILE *fp; + _stdio_user_locking = 0; /* 2 if threading not initialized */ + for (fp = _stdio_openlist; fp != NULL; fp = fp->__nextopen) { + if (fp->__user_locking != 1) { + fp->__user_locking = 0; + } + } + } +} + +void __pthread_initialize(void) +{ + pthread_initialize(); +} + +int __pthread_initialize_manager(void) +{ +#ifdef NOT_FOR_L4 + int manager_pipe[2]; + int pid; + struct pthread_request request; + int report_events; +#endif + pthread_descr mgr; +#ifdef USE_TLS + tcbhead_t *tcbp; +#endif + + __pthread_multiple_threads = 1; +#if TLS_MULTIPLE_THREADS_IN_TCB || !defined USE_TLS || !TLS_DTV_AT_TP + __pthread_main_thread->p_multiple_threads = 1; +#endif + *__libc_multiple_threads_ptr = 1; + +#ifndef HAVE_Z_NODELETE + if (__builtin_expect (&__dso_handle != NULL, 1)) + __cxa_atexit ((void (*) (void *)) pthread_atexit_retcode, NULL, + __dso_handle); +#endif + + if (__pthread_max_stacksize == 0) + __pthread_init_max_stacksize (); + /* If basic initialization not done yet (e.g. we're called from a + constructor run before our constructor), do it now */ + if (__pthread_initial_thread_bos == NULL) pthread_initialize(); + /* Setup stack for thread manager */ + __pthread_manager_thread_bos = malloc(THREAD_MANAGER_STACK_SIZE); + if (__pthread_manager_thread_bos == NULL) + return -1; + __pthread_manager_thread_tos = + __pthread_manager_thread_bos + THREAD_MANAGER_STACK_SIZE; +#ifdef NOT_FOR_L4 + /* Setup pipe to communicate with thread manager */ + if (pipe(manager_pipe) == -1) { + free(__pthread_manager_thread_bos); + return -1; + } +#endif + +#ifdef USE_TLS + /* Allocate memory for the thread descriptor and the dtv. */ + tcbp = _dl_allocate_tls (NULL); + if (tcbp == NULL) { + free(__pthread_manager_thread_bos); +#ifdef NOT_FOR_L4 + close_not_cancel(manager_pipe[0]); + close_not_cancel(manager_pipe[1]); +#endif + return -1; + } + +# if defined(TLS_TCB_AT_TP) + mgr = (pthread_descr) tcbp; +# elif defined(TLS_DTV_AT_TP) + /* pthread_descr is located right below tcbhead_t which _dl_allocate_tls + returns. */ + mgr = (pthread_descr) ((char *) tcbp - TLS_PRE_TCB_SIZE); +# endif +#ifdef NOT_FOR_L4 + __pthread_handles[1].h_descr = manager_thread = mgr; +#endif + + /* Initialize the descriptor. */ +#if !defined USE_TLS || !TLS_DTV_AT_TP + mgr->p_header.data.tcb = tcbp; + mgr->p_header.data.self = mgr; + mgr->p_header.data.multiple_threads = 1; +#elif TLS_MULTIPLE_THREADS_IN_TCB + mgr->p_multiple_threads = 1; +#endif +#ifdef NOT_FOR_L4 + mgr->p_lock = &__pthread_handles[1].h_lock; +#endif +# ifndef HAVE___THREAD + mgr->p_errnop = &mgr->p_errno; +# endif + mgr->p_start_args = (struct pthread_start_args) PTHREAD_START_ARGS_INITIALIZER(__pthread_manager); +#ifdef NOT_FOR_L4 + mgr->p_nr = 1; +#endif +# if __LT_SPINLOCK_INIT != 0 + self->p_resume_count = (struct pthread_atomic) __ATOMIC_INITIALIZER; +# endif + mgr->p_alloca_cutoff = PTHREAD_STACK_MIN / 4; +#else + mgr = &__pthread_manager_thread; +#endif + +#ifdef NOT_FOR_L4 + __pthread_manager_request = manager_pipe[1]; /* writing end */ + __pthread_manager_reader = manager_pipe[0]; /* reading end */ +#endif + + /* Start the thread manager */ +#ifdef NOT_FOR_L4 + pid = 0; +#ifdef USE_TLS + if (__linuxthreads_initial_report_events != 0) + THREAD_SETMEM (((pthread_descr) NULL), p_report_events, + __linuxthreads_initial_report_events); + report_events = THREAD_GETMEM (((pthread_descr) NULL), p_report_events); +#else + if (__linuxthreads_initial_report_events != 0) + __pthread_initial_thread.p_report_events + = __linuxthreads_initial_report_events; + report_events = __pthread_initial_thread.p_report_events; +#endif + if (__builtin_expect (report_events, 0)) + { + /* It's a bit more complicated. We have to report the creation of + the manager thread. */ + int idx = __td_eventword (TD_CREATE); + uint32_t mask = __td_eventmask (TD_CREATE); + uint32_t event_bits; + +#ifdef USE_TLS + event_bits = THREAD_GETMEM_NC (((pthread_descr) NULL), + p_eventbuf.eventmask.event_bits[idx]); +#else + event_bits = __pthread_initial_thread.p_eventbuf.eventmask.event_bits[idx]; +#endif + + if ((mask & (__pthread_threads_events.event_bits[idx] | event_bits)) + != 0) + { + __pthread_lock(mgr->p_lock, NULL); + +#ifdef NEED_SEPARATE_REGISTER_STACK + pid = __clone2(__pthread_manager_event, + (void **) __pthread_manager_thread_bos, + THREAD_MANAGER_STACK_SIZE, + CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_SYSVSEM, + mgr); +#elif _STACK_GROWS_UP + pid = __clone(__pthread_manager_event, + (void **) __pthread_manager_thread_bos, + CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_SYSVSEM, + mgr); +#else + pid = __clone(__pthread_manager_event, + (void **) __pthread_manager_thread_tos, + CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_SYSVSEM, + mgr); +#endif + + if (pid != -1) + { + /* Now fill in the information about the new thread in + the newly created thread's data structure. We cannot let + the new thread do this since we don't know whether it was + already scheduled when we send the event. */ + mgr->p_eventbuf.eventdata = mgr; + mgr->p_eventbuf.eventnum = TD_CREATE; + __pthread_last_event = mgr; + mgr->p_tid = 2* PTHREAD_THREADS_MAX + 1; + mgr->p_pid = pid; + + /* Now call the function which signals the event. */ + __linuxthreads_create_event (); + } + + /* Now restart the thread. */ + __pthread_unlock(mgr->p_lock); + } + } + + if (__builtin_expect (pid, 0) == 0) + { +#ifdef NEED_SEPARATE_REGISTER_STACK + pid = __clone2(__pthread_manager, (void **) __pthread_manager_thread_bos, + THREAD_MANAGER_STACK_SIZE, + CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_SYSVSEM, mgr); +#elif _STACK_GROWS_UP + pid = __clone(__pthread_manager, (void **) __pthread_manager_thread_bos, + CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_SYSVSEM, mgr); +#else + pid = __clone(__pthread_manager, (void **) __pthread_manager_thread_tos, + CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_SYSVSEM, mgr); +#endif + } +#else + // l4 + int err = __pthread_start_manager(mgr); +#endif + + if (__builtin_expect (err, 0) == -1) { +#ifdef USE_TLS + _dl_deallocate_tls (tcbp, true); +#endif + free(__pthread_manager_thread_bos); +#ifdef NOT_FOR_L4 + close_not_cancel(manager_pipe[0]); + close_not_cancel(manager_pipe[1]); +#endif + return -1; + } +#ifdef NOT_FOR_L4 + mgr->p_tid = 2* PTHREAD_THREADS_MAX + 1; + mgr->p_pid = pid; + /* Make gdb aware of new thread manager */ + if (__builtin_expect (__pthread_threads_debug, 0) && __pthread_sig_debug > 0) + { + raise(__pthread_sig_debug); + /* We suspend ourself and gdb will wake us up when it is + ready to handle us. */ + __pthread_wait_for_restart_signal(thread_self()); + } + /* Synchronize debugging of the thread manager */ + request.req_kind = REQ_DEBUG; + TEMP_FAILURE_RETRY(write_not_cancel(__pthread_manager_request, + (char *) &request, sizeof(request))); +#endif + return 0; +} + +/* Thread creation */ + +int +attribute_hidden +__pthread_create(pthread_t *thread, const pthread_attr_t *attr, + void * (*start_routine)(void *), void *arg) +{ + pthread_descr self = thread_self(); + struct pthread_request request; + int retval; + if (__builtin_expect (l4_is_invalid_cap(__pthread_manager_request), 0)) { + if (__pthread_initialize_manager() < 0) + return EAGAIN; + } + request.req_thread = self; + request.req_kind = REQ_CREATE; + request.req_args.create.attr = attr; + request.req_args.create.fn = start_routine; + request.req_args.create.arg = arg; +#ifdef NOT_FOR_L4 + sigprocmask(SIG_SETMASK, NULL, &request.req_args.create.mask); + TEMP_FAILURE_RETRY(write_not_cancel(__pthread_manager_request, + (char *) &request, sizeof(request))); + suspend(self); +#else + __pthread_send_manager_rq(&request, 1); +#endif + retval = THREAD_GETMEM(self, p_retcode); + if (__builtin_expect (retval, 0) == 0) + *thread = (pthread_t) THREAD_GETMEM(self, p_retval); + return retval; +} +strong_alias (__pthread_create, pthread_create) + +/* Simple operations on thread identifiers */ + +pthread_descr __pthread_thread_self(void) +{ + return thread_self(); +} + +pthread_t +attribute_hidden +__pthread_self(void) +{ + pthread_descr self = thread_self(); + return THREAD_GETMEM(self, p_tid); +} +strong_alias (__pthread_self, pthread_self) + +int +attribute_hidden +__pthread_equal(pthread_t thread1, pthread_t thread2) +{ + return thread1 == thread2; +} +strong_alias (__pthread_equal, pthread_equal) + +#ifdef NOT_FOR_L4 +/* Helper function for thread_self in the case of user-provided stacks */ + +#ifndef THREAD_SELF + +pthread_descr +attribute_hidden internal_function +__pthread_find_self(void) +{ + char * sp = CURRENT_STACK_FRAME; + pthread_handle h; + + /* __pthread_handles[0] is the initial thread, __pthread_handles[1] is + the manager threads handled specially in thread_self(), so start at 2 */ + h = __pthread_handles + 2; +# ifdef _STACK_GROWS_UP + while (! (sp >= (char *) h->h_descr && sp < (char *) h->h_descr->p_guardaddr)) h++; +# else + while (! (sp <= (char *) h->h_descr && sp >= h->h_bottom)) h++; +# endif + return h->h_descr; +} + +#else + +pthread_descr +attribute_hidden internal_function +__pthread_self_stack(void) +{ + char *sp = CURRENT_STACK_FRAME; + pthread_handle h; + + if (sp >= __pthread_manager_thread_bos && sp < __pthread_manager_thread_tos) + return manager_thread; + h = __pthread_handles + 2; +# ifdef USE_TLS +# ifdef _STACK_GROWS_UP + while (h->h_descr == NULL + || ! (sp >= h->h_descr->p_stackaddr && sp < h->h_descr->p_guardaddr)) + h++; +# else + while (h->h_descr == NULL + || ! (sp <= (char *) h->h_descr->p_stackaddr && sp >= h->h_bottom)) + h++; +# endif +# else +# ifdef _STACK_GROWS_UP + while (! (sp >= (char *) h->h_descr && sp < h->h_descr->p_guardaddr)) + h++; +# else + while (! (sp <= (char *) h->h_descr && sp >= h->h_bottom)) + h++; +# endif +# endif + return h->h_descr; +} + +#endif + +/* Thread scheduling */ + +int +attribute_hidden internal_function +__pthread_setschedparam(pthread_t thread, int policy, + const struct sched_param *param) +{ + pthread_handle handle = thread_handle(thread); + pthread_descr th; + + __pthread_lock(&handle->h_lock, NULL); + if (__builtin_expect (invalid_handle(handle, thread), 0)) { + __pthread_unlock(&handle->h_lock); + return ESRCH; + } + th = handle->h_descr; + if (__builtin_expect (__sched_setscheduler(th->p_pid, policy, param) == -1, + 0)) { + __pthread_unlock(&handle->h_lock); + return errno; + } + th->p_priority = policy == SCHED_OTHER ? 0 : param->sched_priority; + __pthread_unlock(&handle->h_lock); + if (__pthread_manager_request >= 0) + __pthread_manager_adjust_prio(th->p_priority); + return 0; +} +strong_alias (__pthread_setschedparam, pthread_setschedparam) + +int +attribute_hidden internal_function +__pthread_getschedparam(pthread_t thread, int *policy, + struct sched_param *param) +{ + pthread_handle handle = thread_handle(thread); + int pid, pol; + + __pthread_lock(&handle->h_lock, NULL); + if (__builtin_expect (invalid_handle(handle, thread), 0)) { + __pthread_unlock(&handle->h_lock); + return ESRCH; + } + pid = handle->h_descr->p_pid; + __pthread_unlock(&handle->h_lock); + pol = __sched_getscheduler(pid); + if (__builtin_expect (pol, 0) == -1) return errno; + if (__sched_getparam(pid, param) == -1) return errno; + *policy = pol; + return 0; +} +strong_alias (__pthread_getschedparam, pthread_getschedparam) +#endif + +/* Process-wide exit() request */ + +static void pthread_onexit_process(int retcode, void *arg) +{ + //l4/if (__builtin_expect (__pthread_manager_request, 0) >= 0) { + if (!l4_is_invalid_cap(__pthread_manager_request)) { + struct pthread_request request; + pthread_descr self = thread_self(); + + /* Make sure we come back here after suspend(), in case we entered + from a signal handler. */ + //l4/THREAD_SETMEM(self, p_signal_jmp, NULL); + + request.req_thread = self; + request.req_kind = REQ_PROCESS_EXIT; + request.req_args.exit.code = retcode; +#ifdef NOT_FOR_L4 + TEMP_FAILURE_RETRY(write_not_cancel(__pthread_manager_request, + (char *) &request, sizeof(request))); + suspend(self); +#else + __pthread_send_manager_rq(&request, 1); +#endif + /* Main thread should accumulate times for thread manager and its + children, so that timings for main thread account for all threads. */ + if (self == __pthread_main_thread) + { + UNIMPL(); +#if 0 +#ifdef USE_TLS + waitpid(manager_thread->p_pid, NULL, __WCLONE); +#else + waitpid(__pthread_manager_thread.p_pid, NULL, __WCLONE); +#endif + /* Since all threads have been asynchronously terminated + (possibly holding locks), free cannot be used any more. + For mtrace, we'd like to print something though. */ + /* #ifdef USE_TLS + tcbhead_t *tcbp = (tcbhead_t *) manager_thread; + # if defined(TLS_DTV_AT_TP) + tcbp = (tcbhead_t) ((char *) tcbp + TLS_PRE_TCB_SIZE); + # endif + _dl_deallocate_tls (tcbp, true); + #endif + free (__pthread_manager_thread_bos); */ +#endif + __pthread_manager_thread_bos = __pthread_manager_thread_tos = NULL; + } + } +} + +#ifndef HAVE_Z_NODELETE +static int __pthread_atexit_retcode; + +static void pthread_atexit_process(void *arg, int retcode) +{ + pthread_onexit_process (retcode ?: __pthread_atexit_retcode, arg); +} + +static void pthread_atexit_retcode(void *arg, int retcode) +{ + __pthread_atexit_retcode = retcode; +} +#endif + +#ifdef NOT_FOR_L4 +/* The handler for the RESTART signal just records the signal received + in the thread descriptor, and optionally performs a siglongjmp + (for pthread_cond_timedwait). */ + +static void pthread_handle_sigrestart(int sig) +{ + pthread_descr self = check_thread_self(); + THREAD_SETMEM(self, p_signal, sig); + if (THREAD_GETMEM(self, p_signal_jmp) != NULL) + siglongjmp(*THREAD_GETMEM(self, p_signal_jmp), 1); +} + +/* The handler for the CANCEL signal checks for cancellation + (in asynchronous mode), for process-wide exit and exec requests. + For the thread manager thread, redirect the signal to + __pthread_manager_sighandler. */ + +static void pthread_handle_sigcancel(int sig) +{ + pthread_descr self = check_thread_self(); + sigjmp_buf * jmpbuf; + + if (self == manager_thread) + { + __pthread_manager_sighandler(sig); + return; + } + if (__builtin_expect (__pthread_exit_requested, 0)) { + /* Main thread should accumulate times for thread manager and its + children, so that timings for main thread account for all threads. */ + if (self == __pthread_main_thread) { +#ifdef USE_TLS + waitpid(manager_thread->p_pid, NULL, __WCLONE); +#else + waitpid(__pthread_manager_thread.p_pid, NULL, __WCLONE); +#endif + } + _exit(__pthread_exit_code); + } + if (__builtin_expect (THREAD_GETMEM(self, p_canceled), 0) + && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) { + if (THREAD_GETMEM(self, p_canceltype) == PTHREAD_CANCEL_ASYNCHRONOUS) + __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); + jmpbuf = THREAD_GETMEM(self, p_cancel_jmp); + if (jmpbuf != NULL) { + THREAD_SETMEM(self, p_cancel_jmp, NULL); + siglongjmp(*jmpbuf, 1); + } + } +} + +/* Handler for the DEBUG signal. + The debugging strategy is as follows: + On reception of a REQ_DEBUG request (sent by new threads created to + the thread manager under debugging mode), the thread manager throws + __pthread_sig_debug to itself. The debugger (if active) intercepts + this signal, takes into account new threads and continue execution + of the thread manager by propagating the signal because it doesn't + know what it is specifically done for. In the current implementation, + the thread manager simply discards it. */ + +static void pthread_handle_sigdebug(int sig) +{ + /* Nothing */ +} +#endif + +/* Reset the state of the thread machinery after a fork(). + Close the pipe used for requests and set the main thread to the forked + thread. + Notice that we can't free the stack segments, as the forked thread + may hold pointers into them. */ + +#ifdef NOT_FOR_L4 +void __pthread_reset_main_thread(void) +{ + pthread_descr self = thread_self(); + + if (__pthread_manager_request != -1) { + /* Free the thread manager stack */ + free(__pthread_manager_thread_bos); + __pthread_manager_thread_bos = __pthread_manager_thread_tos = NULL; + /* Close the two ends of the pipe */ + close_not_cancel(__pthread_manager_request); + close_not_cancel(__pthread_manager_reader); + __pthread_manager_request = __pthread_manager_reader = -1; + } + + /* Update the pid of the main thread */ + THREAD_SETMEM(self, p_pid, __getpid()); + /* Make the forked thread the main thread */ + __pthread_main_thread = self; + THREAD_SETMEM(self, p_nextlive, self); + THREAD_SETMEM(self, p_prevlive, self); +#if !(USE_TLS && HAVE___THREAD) + /* Now this thread modifies the global variables. */ + THREAD_SETMEM(self, p_errnop, &_errno); + THREAD_SETMEM(self, p_h_errnop, &_h_errno); +# if defined __UCLIBC_HAS_IPv4__ || defined __UCLIBC_HAS_IPV6__ + THREAD_SETMEM(self, p_resp, __resp); +# endif +#endif + +#ifndef FLOATING_STACKS + /* This is to undo the setrlimit call in __pthread_init_max_stacksize. + XXX This can be wrong if the user set the limit during the run. */ + { + struct rlimit limit; + if (getrlimit (RLIMIT_STACK, &limit) == 0 + && limit.rlim_cur != limit.rlim_max) + { + limit.rlim_cur = limit.rlim_max; + setrlimit(RLIMIT_STACK, &limit); + } + } +#endif +} + +/* Process-wide exec() request */ + +void +attribute_hidden internal_function +__pthread_kill_other_threads_np(void) +{ + struct sigaction sa; + /* Terminate all other threads and thread manager */ + pthread_onexit_process(0, NULL); + /* Make current thread the main thread in case the calling thread + changes its mind, does not exec(), and creates new threads instead. */ + __pthread_reset_main_thread(); + + /* Reset the signal handlers behaviour for the signals the + implementation uses since this would be passed to the new + process. */ + memset(&sa, 0, sizeof(sa)); + if (SIG_DFL) /* if it's constant zero, it's already done */ + sa.sa_handler = SIG_DFL; + __libc_sigaction(__pthread_sig_restart, &sa, NULL); + __libc_sigaction(__pthread_sig_cancel, &sa, NULL); + if (__pthread_sig_debug > 0) + __libc_sigaction(__pthread_sig_debug, &sa, NULL); +} +weak_alias (__pthread_kill_other_threads_np, pthread_kill_other_threads_np) +#endif + +/* Concurrency symbol level. */ +static int current_level; + +int +attribute_hidden +__pthread_setconcurrency(int level) +{ + /* We don't do anything unless we have found a useful interpretation. */ + current_level = level; + return 0; +} +weak_alias (__pthread_setconcurrency, pthread_setconcurrency) + +int +attribute_hidden +__pthread_getconcurrency(void) +{ + return current_level; +} +weak_alias (__pthread_getconcurrency, pthread_getconcurrency) + +/* Primitives for controlling thread execution */ + +#ifdef NOT_FOR_L4 +void +attribute_hidden +__pthread_wait_for_restart_signal(pthread_descr self) +{ + sigset_t mask; + + sigprocmask(SIG_SETMASK, NULL, &mask); /* Get current signal mask */ + sigdelset(&mask, __pthread_sig_restart); /* Unblock the restart signal */ + THREAD_SETMEM(self, p_signal, 0); + do { + __pthread_sigsuspend(&mask); /* Wait for signal. Must not be a + cancellation point. */ + } while (THREAD_GETMEM(self, p_signal) !=__pthread_sig_restart); + + READ_MEMORY_BARRIER(); /* See comment in __pthread_restart_new */ +} + +#if !__ASSUME_REALTIME_SIGNALS +/* The _old variants are for 2.0 and early 2.1 kernels which don't have RT + signals. + On these kernels, we use SIGUSR1 and SIGUSR2 for restart and cancellation. + Since the restart signal does not queue, we use an atomic counter to create + queuing semantics. This is needed to resolve a rare race condition in + pthread_cond_timedwait_relative. */ + +void +attribute_hidden internal_function +__pthread_restart_old(pthread_descr th) +{ + if (pthread_atomic_increment(&th->p_resume_count) == -1) + kill(th->p_pid, __pthread_sig_restart); +} + +void +attribute_hidden internal_function +__pthread_suspend_old(pthread_descr self) +{ + if (pthread_atomic_decrement(&self->p_resume_count) <= 0) + __pthread_wait_for_restart_signal(self); +} + +int +attribute_hidden internal_function +__pthread_timedsuspend_old(pthread_descr self, const struct timespec *abstime) +{ + sigset_t unblock, initial_mask; + int was_signalled = 0; + sigjmp_buf jmpbuf; + + if (pthread_atomic_decrement(&self->p_resume_count) == 0) { + /* Set up a longjmp handler for the restart signal, unblock + the signal and sleep. */ + + if (sigsetjmp(jmpbuf, 1) == 0) { + THREAD_SETMEM(self, p_signal_jmp, &jmpbuf); + THREAD_SETMEM(self, p_signal, 0); + /* Unblock the restart signal */ + __sigemptyset(&unblock); + sigaddset(&unblock, __pthread_sig_restart); + sigprocmask(SIG_UNBLOCK, &unblock, &initial_mask); + + while (1) { + struct timeval now; + struct timespec reltime; + + /* Compute a time offset relative to now. */ + __gettimeofday (&now, NULL); + reltime.tv_nsec = abstime->tv_nsec - now.tv_usec * 1000; + reltime.tv_sec = abstime->tv_sec - now.tv_sec; + if (reltime.tv_nsec < 0) { + reltime.tv_nsec += 1000000000; + reltime.tv_sec -= 1; + } + + /* Sleep for the required duration. If woken by a signal, + resume waiting as required by Single Unix Specification. */ + if (reltime.tv_sec < 0 || nanosleep(&reltime, NULL) == 0) + break; + } + + /* Block the restart signal again */ + sigprocmask(SIG_SETMASK, &initial_mask, NULL); + was_signalled = 0; + } else { + was_signalled = 1; + } + THREAD_SETMEM(self, p_signal_jmp, NULL); + } + + /* Now was_signalled is true if we exited the above code + due to the delivery of a restart signal. In that case, + we know we have been dequeued and resumed and that the + resume count is balanced. Otherwise, there are some + cases to consider. First, try to bump up the resume count + back to zero. If it goes to 1, it means restart() was + invoked on this thread. The signal must be consumed + and the count bumped down and everything is cool. We + can return a 1 to the caller. + Otherwise, no restart was delivered yet, so a potential + race exists; we return a 0 to the caller which must deal + with this race in an appropriate way; for example by + atomically removing the thread from consideration for a + wakeup---if such a thing fails, it means a restart is + being delivered. */ + + if (!was_signalled) { + if (pthread_atomic_increment(&self->p_resume_count) != -1) { + __pthread_wait_for_restart_signal(self); + pthread_atomic_decrement(&self->p_resume_count); /* should be zero now! */ + /* woke spontaneously and consumed restart signal */ + return 1; + } + /* woke spontaneously but did not consume restart---caller must resolve */ + return 0; + } + /* woken due to restart signal */ + return 1; +} +#endif /* __ASSUME_REALTIME_SIGNALS */ + +void +attribute_hidden internal_function +__pthread_restart_new(pthread_descr th) +{ + /* The barrier is proabably not needed, in which case it still documents + our assumptions. The intent is to commit previous writes to shared + memory so the woken thread will have a consistent view. Complementary + read barriers are present to the suspend functions. */ + WRITE_MEMORY_BARRIER(); + kill(th->p_pid, __pthread_sig_restart); +} + +/* There is no __pthread_suspend_new because it would just + be a wasteful wrapper for __pthread_wait_for_restart_signal */ + +int +attribute_hidden internal_function +__pthread_timedsuspend_new(pthread_descr self, const struct timespec *abstime) +{ + sigset_t unblock, initial_mask; + int was_signalled = 0; + sigjmp_buf jmpbuf; + + if (sigsetjmp(jmpbuf, 1) == 0) { + THREAD_SETMEM(self, p_signal_jmp, &jmpbuf); + THREAD_SETMEM(self, p_signal, 0); + /* Unblock the restart signal */ + __sigemptyset(&unblock); + sigaddset(&unblock, __pthread_sig_restart); + sigprocmask(SIG_UNBLOCK, &unblock, &initial_mask); + + while (1) { + struct timeval now; + struct timespec reltime; + + /* Compute a time offset relative to now. */ + __gettimeofday (&now, NULL); + reltime.tv_nsec = abstime->tv_nsec - now.tv_usec * 1000; + reltime.tv_sec = abstime->tv_sec - now.tv_sec; + if (reltime.tv_nsec < 0) { + reltime.tv_nsec += 1000000000; + reltime.tv_sec -= 1; + } + + /* Sleep for the required duration. If woken by a signal, + resume waiting as required by Single Unix Specification. */ + if (reltime.tv_sec < 0 || nanosleep(&reltime, NULL) == 0) + break; + } + + /* Block the restart signal again */ + sigprocmask(SIG_SETMASK, &initial_mask, NULL); + was_signalled = 0; + } else { + was_signalled = 1; + } + THREAD_SETMEM(self, p_signal_jmp, NULL); + + /* Now was_signalled is true if we exited the above code + due to the delivery of a restart signal. In that case, + everything is cool. We have been removed from whatever + we were waiting on by the other thread, and consumed its signal. + + Otherwise we this thread woke up spontaneously, or due to a signal other + than restart. This is an ambiguous case that must be resolved by + the caller; the thread is still eligible for a restart wakeup + so there is a race. */ + + READ_MEMORY_BARRIER(); /* See comment in __pthread_restart_new */ + return was_signalled; +} +#endif + + +/* Debugging aid */ + +#ifdef DEBUG +#include + +void +attribute_hidden internal_function +__pthread_message(const char * fmt, ...) +{ + char buffer[1024]; + va_list args; + sprintf(buffer, "%05d : ", __getpid()); + va_start(args, fmt); + vsnprintf(buffer + 8, sizeof(buffer) - 8, fmt, args); + va_end(args); + TEMP_FAILURE_RETRY(write_not_cancel(2, buffer, strlen(buffer))); +} + +#endif diff --git a/l4/pkg/uclibc/lib/libpthread/src/queue.h b/l4/pkg/uclibc/lib/libpthread/src/queue.h new file mode 100644 index 00000000..e50517f7 --- /dev/null +++ b/l4/pkg/uclibc/lib/libpthread/src/queue.h @@ -0,0 +1,61 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +/* Waiting queues */ + +/* Waiting queues are represented by lists of thread descriptors + linked through their p_nextwaiting field. The lists are kept + sorted by decreasing priority, and then decreasing waiting time. */ + +static __inline__ void enqueue(pthread_descr * q, pthread_descr th) +{ + int prio = th->p_priority; + ASSERT(th->p_nextwaiting == NULL); + for (; *q != NULL; q = &((*q)->p_nextwaiting)) { + if (prio > (*q)->p_priority) { + th->p_nextwaiting = *q; + *q = th; + return; + } + } + *q = th; +} + +static __inline__ pthread_descr dequeue(pthread_descr * q) +{ + pthread_descr th; + th = *q; + if (th != NULL) { + *q = th->p_nextwaiting; + th->p_nextwaiting = NULL; + } + return th; +} + +static __inline__ int remove_from_queue(pthread_descr * q, pthread_descr th) +{ + for (; *q != NULL; q = &((*q)->p_nextwaiting)) { + if (*q == th) { + *q = th->p_nextwaiting; + th->p_nextwaiting = NULL; + return 1; + } + } + return 0; +} + +static __inline__ int queue_is_empty(pthread_descr * q) +{ + return *q == NULL; +} diff --git a/l4/pkg/uclibc/lib/libpthread/src/restart.h b/l4/pkg/uclibc/lib/libpthread/src/restart.h new file mode 100644 index 00000000..8eaedc80 --- /dev/null +++ b/l4/pkg/uclibc/lib/libpthread/src/restart.h @@ -0,0 +1,48 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +//#include +//#include +#include +#include + +#include +#include + +/* Primitives for controlling thread execution */ + +static __inline__ void restart(pthread_descr th) +{ + l4_irq_trigger(th->p_thsem_cap); +} + +static __inline__ void suspend(pthread_descr self) +{ + l4_irq_receive(self->p_thsem_cap, L4_IPC_NEVER); +} + +static __inline__ int timedsuspend(pthread_descr self, + const struct timespec *abstime) +{ + extern uint64_t __attribute__((weak)) __libc_l4_kclock_offset; + uint64_t clock = abstime->tv_sec * 1000000ULL + abstime->tv_nsec / 1000; + if (&__libc_l4_kclock_offset) + clock -= __libc_l4_kclock_offset; + l4_timeout_t timeout = L4_IPC_NEVER; + l4_rcv_timeout(l4_timeout_abs_u(clock, 4, l4_utcb()), &timeout); + l4_msgtag_t res = l4_irq_receive(self->p_thsem_cap, timeout); + if (l4_error(res) == -(L4_EIPC_LO + L4_IPC_RETIMEOUT)) + return 0; + return 1; +} diff --git a/l4/pkg/uclibc/lib/libpthread/src/rwlock.c b/l4/pkg/uclibc/lib/libpthread/src/rwlock.c new file mode 100644 index 00000000..f565f187 --- /dev/null +++ b/l4/pkg/uclibc/lib/libpthread/src/rwlock.c @@ -0,0 +1,658 @@ +/* Read-write lock implementation. + Copyright (C) 1998, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Xavier Leroy + and Ulrich Drepper , 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#include +#include +#include +#include "internals.h" +#include "queue.h" +#include "spinlock.h" +#include "restart.h" + +/* Function called by pthread_cancel to remove the thread from + waiting inside pthread_rwlock_timedrdlock or pthread_rwlock_timedwrlock. */ + +static int rwlock_rd_extricate_func(void *obj, pthread_descr th) +{ + pthread_rwlock_t *rwlock = obj; + int did_remove = 0; + + __pthread_lock(&rwlock->__rw_lock, NULL); + did_remove = remove_from_queue(&rwlock->__rw_read_waiting, th); + __pthread_unlock(&rwlock->__rw_lock); + + return did_remove; +} + +static int rwlock_wr_extricate_func(void *obj, pthread_descr th) +{ + pthread_rwlock_t *rwlock = obj; + int did_remove = 0; + + __pthread_lock(&rwlock->__rw_lock, NULL); + did_remove = remove_from_queue(&rwlock->__rw_write_waiting, th); + __pthread_unlock(&rwlock->__rw_lock); + + return did_remove; +} + +/* + * Check whether the calling thread already owns one or more read locks on the + * specified lock. If so, return a pointer to the read lock info structure + * corresponding to that lock. + */ + +static pthread_readlock_info * +rwlock_is_in_list(pthread_descr self, pthread_rwlock_t *rwlock) +{ + pthread_readlock_info *info; + + for (info = THREAD_GETMEM (self, p_readlock_list); info != NULL; + info = info->pr_next) + { + if (info->pr_lock == rwlock) + return info; + } + + return NULL; +} + +/* + * Add a new lock to the thread's list of locks for which it has a read lock. + * A new info node must be allocated for this, which is taken from the thread's + * free list, or by calling malloc. If malloc fails, a null pointer is + * returned. Otherwise the lock info structure is initialized and pushed + * onto the thread's list. + */ + +static pthread_readlock_info * +rwlock_add_to_list(pthread_descr self, pthread_rwlock_t *rwlock) +{ + pthread_readlock_info *info = THREAD_GETMEM (self, p_readlock_free); + + if (info != NULL) + THREAD_SETMEM (self, p_readlock_free, info->pr_next); + else + info = malloc(sizeof *info); + + if (info == NULL) + return NULL; + + info->pr_lock_count = 1; + info->pr_lock = rwlock; + info->pr_next = THREAD_GETMEM (self, p_readlock_list); + THREAD_SETMEM (self, p_readlock_list, info); + + return info; +} + +/* + * If the thread owns a read lock over the given pthread_rwlock_t, + * and this read lock is tracked in the thread's lock list, + * this function returns a pointer to the info node in that list. + * It also decrements the lock count within that node, and if + * it reaches zero, it removes the node from the list. + * If nothing is found, it returns a null pointer. + */ + +static pthread_readlock_info * +rwlock_remove_from_list(pthread_descr self, pthread_rwlock_t *rwlock) +{ + pthread_readlock_info **pinfo; + + for (pinfo = &self->p_readlock_list; *pinfo != NULL; pinfo = &(*pinfo)->pr_next) + { + if ((*pinfo)->pr_lock == rwlock) + { + pthread_readlock_info *info = *pinfo; + if (--info->pr_lock_count == 0) + *pinfo = info->pr_next; + return info; + } + } + + return NULL; +} + +/* + * This function checks whether the conditions are right to place a read lock. + * It returns 1 if so, otherwise zero. The rwlock's internal lock must be + * locked upon entry. + */ + +static int +rwlock_can_rdlock(pthread_rwlock_t *rwlock, int have_lock_already) +{ + /* Can't readlock; it is write locked. */ + if (rwlock->__rw_writer != NULL) + return 0; + + /* Lock prefers readers; get it. */ + if (rwlock->__rw_kind == PTHREAD_RWLOCK_PREFER_READER_NP) + return 1; + + /* Lock prefers writers, but none are waiting. */ + if (queue_is_empty(&rwlock->__rw_write_waiting)) + return 1; + + /* Writers are waiting, but this thread already has a read lock */ + if (have_lock_already) + return 1; + + /* Writers are waiting, and this is a new lock */ + return 0; +} + +/* + * This function helps support brain-damaged recursive read locking + * semantics required by Unix 98, while maintaining write priority. + * This basically determines whether this thread already holds a read lock + * already. It returns 1 if so, otherwise it returns 0. + * + * If the thread has any ``untracked read locks'' then it just assumes + * that this lock is among them, just to be safe, and returns 1. + * + * Also, if it finds the thread's lock in the list, it sets the pointer + * referenced by pexisting to refer to the list entry. + * + * If the thread has no untracked locks, and the lock is not found + * in its list, then it is added to the list. If this fails, + * then *pout_of_mem is set to 1. + */ + +static int +rwlock_have_already(pthread_descr *pself, pthread_rwlock_t *rwlock, + pthread_readlock_info **pexisting, int *pout_of_mem) +{ + pthread_readlock_info *existing = NULL; + int out_of_mem = 0, have_lock_already = 0; + pthread_descr self = *pself; + + if (rwlock->__rw_kind == PTHREAD_RWLOCK_PREFER_WRITER_NP) + { + if (!self) + *pself = self = thread_self(); + + existing = rwlock_is_in_list(self, rwlock); + + if (existing != NULL + || THREAD_GETMEM (self, p_untracked_readlock_count) > 0) + have_lock_already = 1; + else + { + existing = rwlock_add_to_list(self, rwlock); + if (existing == NULL) + out_of_mem = 1; + } + } + + *pout_of_mem = out_of_mem; + *pexisting = existing; + + return have_lock_already; +} + +int +__pthread_rwlock_init (pthread_rwlock_t *rwlock, + const pthread_rwlockattr_t *attr) +{ + __pthread_init_lock(&rwlock->__rw_lock); + rwlock->__rw_readers = 0; + rwlock->__rw_writer = NULL; + rwlock->__rw_read_waiting = NULL; + rwlock->__rw_write_waiting = NULL; + + if (attr == NULL) + { + rwlock->__rw_kind = PTHREAD_RWLOCK_DEFAULT_NP; + rwlock->__rw_pshared = PTHREAD_PROCESS_PRIVATE; + } + else + { + rwlock->__rw_kind = attr->__lockkind; + rwlock->__rw_pshared = attr->__pshared; + } + + return 0; +} +strong_alias (__pthread_rwlock_init, pthread_rwlock_init) + + +int +__pthread_rwlock_destroy (pthread_rwlock_t *rwlock) +{ + int readers; + _pthread_descr writer; + + __pthread_lock (&rwlock->__rw_lock, NULL); + readers = rwlock->__rw_readers; + writer = rwlock->__rw_writer; + __pthread_unlock (&rwlock->__rw_lock); + + if (readers > 0 || writer != NULL) + return EBUSY; + + return 0; +} +strong_alias (__pthread_rwlock_destroy, pthread_rwlock_destroy) + +int +__pthread_rwlock_rdlock (pthread_rwlock_t *rwlock) +{ + pthread_descr self = NULL; + pthread_readlock_info *existing; + int out_of_mem, have_lock_already; + + have_lock_already = rwlock_have_already(&self, rwlock, + &existing, &out_of_mem); + + if (self == NULL) + self = thread_self (); + + for (;;) + { + __pthread_lock (&rwlock->__rw_lock, self); + + if (rwlock_can_rdlock(rwlock, have_lock_already)) + break; + + enqueue (&rwlock->__rw_read_waiting, self); + __pthread_unlock (&rwlock->__rw_lock); + suspend (self); /* This is not a cancellation point */ + } + + ++rwlock->__rw_readers; + __pthread_unlock (&rwlock->__rw_lock); + + if (have_lock_already || out_of_mem) + { + if (existing != NULL) + ++existing->pr_lock_count; + else + ++self->p_untracked_readlock_count; + } + + return 0; +} +strong_alias (__pthread_rwlock_rdlock, pthread_rwlock_rdlock) + +int +__pthread_rwlock_timedrdlock (pthread_rwlock_t *rwlock, + const struct timespec *abstime) +{ + pthread_descr self = NULL; + pthread_readlock_info *existing; + int out_of_mem, have_lock_already; + pthread_extricate_if extr; + + if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) + return EINVAL; + + have_lock_already = rwlock_have_already(&self, rwlock, + &existing, &out_of_mem); + + if (self == NULL) + self = thread_self (); + + /* Set up extrication interface */ + extr.pu_object = rwlock; + extr.pu_extricate_func = rwlock_rd_extricate_func; + + /* Register extrication interface */ + __pthread_set_own_extricate_if (self, &extr); + + for (;;) + { + __pthread_lock (&rwlock->__rw_lock, self); + + if (rwlock_can_rdlock(rwlock, have_lock_already)) + break; + + enqueue (&rwlock->__rw_read_waiting, self); + __pthread_unlock (&rwlock->__rw_lock); + /* This is not a cancellation point */ + if (timedsuspend (self, abstime) == 0) + { + int was_on_queue; + + __pthread_lock (&rwlock->__rw_lock, self); + was_on_queue = remove_from_queue (&rwlock->__rw_read_waiting, self); + __pthread_unlock (&rwlock->__rw_lock); + + if (was_on_queue) + { + __pthread_set_own_extricate_if (self, 0); + return ETIMEDOUT; + } + + /* Eat the outstanding restart() from the signaller */ + suspend (self); + } + } + + __pthread_set_own_extricate_if (self, 0); + + ++rwlock->__rw_readers; + __pthread_unlock (&rwlock->__rw_lock); + + if (have_lock_already || out_of_mem) + { + if (existing != NULL) + ++existing->pr_lock_count; + else + ++self->p_untracked_readlock_count; + } + + return 0; +} +strong_alias (__pthread_rwlock_timedrdlock, pthread_rwlock_timedrdlock) + +int +__pthread_rwlock_tryrdlock (pthread_rwlock_t *rwlock) +{ + pthread_descr self = thread_self(); + pthread_readlock_info *existing; + int out_of_mem, have_lock_already; + int retval = EBUSY; + + have_lock_already = rwlock_have_already(&self, rwlock, + &existing, &out_of_mem); + + __pthread_lock (&rwlock->__rw_lock, self); + + /* 0 is passed to here instead of have_lock_already. + This is to meet Single Unix Spec requirements: + if writers are waiting, pthread_rwlock_tryrdlock + does not acquire a read lock, even if the caller has + one or more read locks already. */ + + if (rwlock_can_rdlock(rwlock, 0)) + { + ++rwlock->__rw_readers; + retval = 0; + } + + __pthread_unlock (&rwlock->__rw_lock); + + if (retval == 0) + { + if (have_lock_already || out_of_mem) + { + if (existing != NULL) + ++existing->pr_lock_count; + else + ++self->p_untracked_readlock_count; + } + } + + return retval; +} +strong_alias (__pthread_rwlock_tryrdlock, pthread_rwlock_tryrdlock) + + +int +__pthread_rwlock_wrlock (pthread_rwlock_t *rwlock) +{ + pthread_descr self = thread_self (); + + while(1) + { + __pthread_lock (&rwlock->__rw_lock, self); + if (rwlock->__rw_readers == 0 && rwlock->__rw_writer == NULL) + { + rwlock->__rw_writer = self; + __pthread_unlock (&rwlock->__rw_lock); + return 0; + } + + /* Suspend ourselves, then try again */ + enqueue (&rwlock->__rw_write_waiting, self); + __pthread_unlock (&rwlock->__rw_lock); + suspend (self); /* This is not a cancellation point */ + } +} +strong_alias (__pthread_rwlock_wrlock, pthread_rwlock_wrlock) + + +int +__pthread_rwlock_timedwrlock (pthread_rwlock_t *rwlock, + const struct timespec *abstime) +{ + pthread_descr self; + pthread_extricate_if extr; + + if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) + return EINVAL; + + self = thread_self (); + + /* Set up extrication interface */ + extr.pu_object = rwlock; + extr.pu_extricate_func = rwlock_wr_extricate_func; + + /* Register extrication interface */ + __pthread_set_own_extricate_if (self, &extr); + + while(1) + { + __pthread_lock (&rwlock->__rw_lock, self); + + if (rwlock->__rw_readers == 0 && rwlock->__rw_writer == NULL) + { + rwlock->__rw_writer = self; + __pthread_set_own_extricate_if (self, 0); + __pthread_unlock (&rwlock->__rw_lock); + return 0; + } + + /* Suspend ourselves, then try again */ + enqueue (&rwlock->__rw_write_waiting, self); + __pthread_unlock (&rwlock->__rw_lock); + /* This is not a cancellation point */ + if (timedsuspend (self, abstime) == 0) + { + int was_on_queue; + + __pthread_lock (&rwlock->__rw_lock, self); + was_on_queue = remove_from_queue (&rwlock->__rw_write_waiting, self); + __pthread_unlock (&rwlock->__rw_lock); + + if (was_on_queue) + { + __pthread_set_own_extricate_if (self, 0); + return ETIMEDOUT; + } + + /* Eat the outstanding restart() from the signaller */ + suspend (self); + } + } +} +strong_alias (__pthread_rwlock_timedwrlock, pthread_rwlock_timedwrlock) + + +int +__pthread_rwlock_trywrlock (pthread_rwlock_t *rwlock) +{ + int result = EBUSY; + + __pthread_lock (&rwlock->__rw_lock, NULL); + if (rwlock->__rw_readers == 0 && rwlock->__rw_writer == NULL) + { + rwlock->__rw_writer = thread_self (); + result = 0; + } + __pthread_unlock (&rwlock->__rw_lock); + + return result; +} +strong_alias (__pthread_rwlock_trywrlock, pthread_rwlock_trywrlock) + + +int +__pthread_rwlock_unlock (pthread_rwlock_t *rwlock) +{ + pthread_descr torestart; + pthread_descr th; + + __pthread_lock (&rwlock->__rw_lock, NULL); + if (rwlock->__rw_writer != NULL) + { + /* Unlocking a write lock. */ + if (rwlock->__rw_writer != thread_self ()) + { + __pthread_unlock (&rwlock->__rw_lock); + return EPERM; + } + rwlock->__rw_writer = NULL; + + if ((rwlock->__rw_kind == PTHREAD_RWLOCK_PREFER_READER_NP + && !queue_is_empty(&rwlock->__rw_read_waiting)) + || (th = dequeue(&rwlock->__rw_write_waiting)) == NULL) + { + /* Restart all waiting readers. */ + torestart = rwlock->__rw_read_waiting; + rwlock->__rw_read_waiting = NULL; + __pthread_unlock (&rwlock->__rw_lock); + while ((th = dequeue (&torestart)) != NULL) + restart (th); + } + else + { + /* Restart one waiting writer. */ + __pthread_unlock (&rwlock->__rw_lock); + restart (th); + } + } + else + { + /* Unlocking a read lock. */ + if (rwlock->__rw_readers == 0) + { + __pthread_unlock (&rwlock->__rw_lock); + return EPERM; + } + + --rwlock->__rw_readers; + if (rwlock->__rw_readers == 0) + /* Restart one waiting writer, if any. */ + th = dequeue (&rwlock->__rw_write_waiting); + else + th = NULL; + + __pthread_unlock (&rwlock->__rw_lock); + if (th != NULL) + restart (th); + + /* Recursive lock fixup */ + + if (rwlock->__rw_kind == PTHREAD_RWLOCK_PREFER_WRITER_NP) + { + pthread_descr self = thread_self(); + pthread_readlock_info *victim = rwlock_remove_from_list(self, rwlock); + + if (victim != NULL) + { + if (victim->pr_lock_count == 0) + { + victim->pr_next = THREAD_GETMEM (self, p_readlock_free); + THREAD_SETMEM (self, p_readlock_free, victim); + } + } + else + { + int val = THREAD_GETMEM (self, p_untracked_readlock_count); + if (val > 0) + THREAD_SETMEM (self, p_untracked_readlock_count, val - 1); + } + } + } + + return 0; +} +strong_alias (__pthread_rwlock_unlock, pthread_rwlock_unlock) + + + +int +pthread_rwlockattr_init (pthread_rwlockattr_t *attr) +{ + attr->__lockkind = 0; + attr->__pshared = PTHREAD_PROCESS_PRIVATE; + + return 0; +} + + +int +__pthread_rwlockattr_destroy (pthread_rwlockattr_t *attr) +{ + return 0; +} +strong_alias (__pthread_rwlockattr_destroy, pthread_rwlockattr_destroy) + + +int +pthread_rwlockattr_getpshared (const pthread_rwlockattr_t *attr, int *pshared) +{ + *pshared = attr->__pshared; + return 0; +} + + +int +pthread_rwlockattr_setpshared (pthread_rwlockattr_t *attr, int pshared) +{ + if (pshared != PTHREAD_PROCESS_PRIVATE && pshared != PTHREAD_PROCESS_SHARED) + return EINVAL; + + /* For now it is not possible to shared a conditional variable. */ + if (pshared != PTHREAD_PROCESS_PRIVATE) + return ENOSYS; + + attr->__pshared = pshared; + + return 0; +} + + +int +pthread_rwlockattr_getkind_np (const pthread_rwlockattr_t *attr, int *pref) +{ + *pref = attr->__lockkind; + return 0; +} + + +int +pthread_rwlockattr_setkind_np (pthread_rwlockattr_t *attr, int pref) +{ + if (pref != PTHREAD_RWLOCK_PREFER_READER_NP + && pref != PTHREAD_RWLOCK_PREFER_WRITER_NP + && pref != PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP + && pref != PTHREAD_RWLOCK_DEFAULT_NP) + return EINVAL; + + attr->__lockkind = pref; + + return 0; +} diff --git a/l4/pkg/uclibc/lib/libpthread/src/semaphore.c b/l4/pkg/uclibc/lib/libpthread/src/semaphore.c new file mode 100644 index 00000000..b2c075c9 --- /dev/null +++ b/l4/pkg/uclibc/lib/libpthread/src/semaphore.c @@ -0,0 +1,304 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +/* Semaphores a la POSIX 1003.1b */ + +#include +#include "pthread.h" +#include "semaphore.h" +#include "internals.h" +#include "spinlock.h" +#include "restart.h" +#include "queue.h" + +#include + +int sem_init(sem_t *sem, int pshared, unsigned int value) +{ + if (value > SEM_VALUE_MAX) { + __set_errno(EINVAL); + return -1; + } + if (pshared) { + __set_errno(ENOSYS); + return -1; + } + __pthread_init_lock(&sem->__sem_lock); + sem->__sem_value = value; + sem->__sem_waiting = NULL; + return 0; +} + +/* Function called by pthread_cancel to remove the thread from + waiting inside sem_wait. */ + +static int new_sem_extricate_func(void *obj, pthread_descr th) +{ + __volatile__ pthread_descr self = thread_self(); + sem_t *sem = obj; + int did_remove = 0; + + __pthread_lock(&sem->__sem_lock, self); + did_remove = remove_from_queue(&sem->__sem_waiting, th); + __pthread_unlock(&sem->__sem_lock); + + return did_remove; +} + +int sem_wait(sem_t * sem) +{ + __volatile__ pthread_descr self = thread_self(); + pthread_extricate_if extr; + int already_canceled = 0; + int spurious_wakeup_count; + + /* Set up extrication interface */ + extr.pu_object = sem; + extr.pu_extricate_func = new_sem_extricate_func; + + __pthread_lock(&sem->__sem_lock, self); + if (sem->__sem_value > 0) { + sem->__sem_value--; + __pthread_unlock(&sem->__sem_lock); + return 0; + } + /* Register extrication interface */ + THREAD_SETMEM(self, p_sem_avail, 0); + __pthread_set_own_extricate_if(self, &extr); + /* Enqueue only if not already cancelled. */ + if (!(THREAD_GETMEM(self, p_canceled) + && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE)) + enqueue(&sem->__sem_waiting, self); + else + already_canceled = 1; + __pthread_unlock(&sem->__sem_lock); + + if (already_canceled) { + __pthread_set_own_extricate_if(self, 0); + __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); + } + + /* Wait for sem_post or cancellation, or fall through if already canceled */ + spurious_wakeup_count = 0; + while (1) + { + suspend(self); + if (THREAD_GETMEM(self, p_sem_avail) == 0 + && (THREAD_GETMEM(self, p_woken_by_cancel) == 0 + || THREAD_GETMEM(self, p_cancelstate) != PTHREAD_CANCEL_ENABLE)) + { + /* Count resumes that don't belong to us. */ + spurious_wakeup_count++; + continue; + } + break; + } + __pthread_set_own_extricate_if(self, 0); + + /* Terminate only if the wakeup came from cancellation. */ + /* Otherwise ignore cancellation because we got the semaphore. */ + + if (THREAD_GETMEM(self, p_woken_by_cancel) + && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) { + THREAD_SETMEM(self, p_woken_by_cancel, 0); + __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); + } + /* We got the semaphore */ + return 0; +} + +int sem_trywait(sem_t * sem) +{ + int retval; + + __pthread_lock(&sem->__sem_lock, NULL); + if (sem->__sem_value == 0) { + __set_errno(EAGAIN); + retval = -1; + } else { + sem->__sem_value--; + retval = 0; + } + __pthread_unlock(&sem->__sem_lock); + return retval; +} + +int sem_post(sem_t * sem) +{ + pthread_descr self = thread_self(); + pthread_descr th; +#if 0 // AW11 + struct pthread_request request; + if (THREAD_GETMEM(self, p_in_sighandler) == NULL) +#endif + { + __pthread_lock(&sem->__sem_lock, self); + if (sem->__sem_waiting == NULL) { + if (sem->__sem_value >= SEM_VALUE_MAX) { + /* Overflow */ + __set_errno(ERANGE); + __pthread_unlock(&sem->__sem_lock); + return -1; + } + sem->__sem_value++; + __pthread_unlock(&sem->__sem_lock); + } else { + th = dequeue(&sem->__sem_waiting); + __pthread_unlock(&sem->__sem_lock); + th->p_sem_avail = 1; + WRITE_MEMORY_BARRIER(); + restart(th); + } + } +#if 0 // AW11 + else { + /* If we're in signal handler, delegate post operation to + the thread manager. */ + if (__pthread_manager_request < 0) { + if (__pthread_initialize_manager() < 0) { + __set_errno(EAGAIN); + return -1; + } + } + request.req_kind = REQ_POST; + request.req_args.post = sem; + TEMP_FAILURE_RETRY(write_not_cancel(__pthread_manager_request, + (char *) &request, sizeof(request))); + } +#endif + return 0; +} + +int sem_getvalue(sem_t * sem, int * sval) +{ + *sval = sem->__sem_value; + return 0; +} + +int sem_destroy(sem_t * sem) +{ + if (sem->__sem_waiting != NULL) { + __set_errno (EBUSY); + return -1; + } + return 0; +} + +sem_t *sem_open(const char *name, int oflag, ...) +{ + __set_errno (ENOSYS); + return SEM_FAILED; +} + +int sem_close(sem_t *sem) +{ + __set_errno (ENOSYS); + return -1; +} + +int sem_unlink(const char *name) +{ + __set_errno (ENOSYS); + return -1; +} + +int sem_timedwait(sem_t *sem, const struct timespec *abstime) +{ + pthread_descr self = thread_self(); + pthread_extricate_if extr; + int already_canceled = 0; + int spurious_wakeup_count; + + __pthread_lock(&sem->__sem_lock, self); + if (sem->__sem_value > 0) { + --sem->__sem_value; + __pthread_unlock(&sem->__sem_lock); + return 0; + } + + if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) { + /* The standard requires that if the function would block and the + time value is illegal, the function returns with an error. */ + __pthread_unlock(&sem->__sem_lock); + __set_errno (EINVAL); + return -1; + } + + /* Set up extrication interface */ + extr.pu_object = sem; + extr.pu_extricate_func = new_sem_extricate_func; + + /* Register extrication interface */ + THREAD_SETMEM(self, p_sem_avail, 0); + __pthread_set_own_extricate_if(self, &extr); + /* Enqueue only if not already cancelled. */ + if (!(THREAD_GETMEM(self, p_canceled) + && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE)) + enqueue(&sem->__sem_waiting, self); + else + already_canceled = 1; + __pthread_unlock(&sem->__sem_lock); + + if (already_canceled) { + __pthread_set_own_extricate_if(self, 0); + __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); + } + + spurious_wakeup_count = 0; + while (1) + { + if (timedsuspend(self, abstime) == 0) { + int was_on_queue; + + /* __pthread_lock will queue back any spurious restarts that + may happen to it. */ + + __pthread_lock(&sem->__sem_lock, self); + was_on_queue = remove_from_queue(&sem->__sem_waiting, self); + __pthread_unlock(&sem->__sem_lock); + + if (was_on_queue) { + __pthread_set_own_extricate_if(self, 0); + __set_errno (ETIMEDOUT); + return -1; + } + + /* Eat the outstanding restart() from the signaller */ + suspend(self); + } + + if (THREAD_GETMEM(self, p_sem_avail) == 0 + && (THREAD_GETMEM(self, p_woken_by_cancel) == 0 + || THREAD_GETMEM(self, p_cancelstate) != PTHREAD_CANCEL_ENABLE)) + { + /* Count resumes that don't belong to us. */ + spurious_wakeup_count++; + continue; + } + break; + } + + __pthread_set_own_extricate_if(self, 0); + + /* Terminate only if the wakeup came from cancellation. */ + /* Otherwise ignore cancellation because we got the semaphore. */ + + if (THREAD_GETMEM(self, p_woken_by_cancel) + && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) { + THREAD_SETMEM(self, p_woken_by_cancel, 0); + __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); + } + /* We got the semaphore */ + return 0; +} diff --git a/l4/pkg/uclibc/lib/libpthread/src/so_init-amd64.S b/l4/pkg/uclibc/lib/libpthread/src/so_init-amd64.S new file mode 100644 index 00000000..690ea483 --- /dev/null +++ b/l4/pkg/uclibc/lib/libpthread/src/so_init-amd64.S @@ -0,0 +1,4 @@ +.section ".init" + +call __pthread_initialize_minimal@plt + diff --git a/l4/pkg/uclibc/lib/libpthread/src/so_init-arm.S b/l4/pkg/uclibc/lib/libpthread/src/so_init-arm.S new file mode 100644 index 00000000..744c8c09 --- /dev/null +++ b/l4/pkg/uclibc/lib/libpthread/src/so_init-arm.S @@ -0,0 +1,4 @@ +.section ".init" + +bl __pthread_initialize_minimal@plt + diff --git a/l4/pkg/uclibc/lib/libpthread/src/so_init-ppc32.S b/l4/pkg/uclibc/lib/libpthread/src/so_init-ppc32.S new file mode 100644 index 00000000..744c8c09 --- /dev/null +++ b/l4/pkg/uclibc/lib/libpthread/src/so_init-ppc32.S @@ -0,0 +1,4 @@ +.section ".init" + +bl __pthread_initialize_minimal@plt + diff --git a/l4/pkg/uclibc/lib/libpthread/src/so_init-sparc.S b/l4/pkg/uclibc/lib/libpthread/src/so_init-sparc.S new file mode 100644 index 00000000..6840e884 --- /dev/null +++ b/l4/pkg/uclibc/lib/libpthread/src/so_init-sparc.S @@ -0,0 +1,4 @@ +.section ".init" + +call __pthread_initialize_minimal /*@plt*/ +nop diff --git a/l4/pkg/uclibc/lib/libpthread/src/so_init-x86.S b/l4/pkg/uclibc/lib/libpthread/src/so_init-x86.S new file mode 100644 index 00000000..690ea483 --- /dev/null +++ b/l4/pkg/uclibc/lib/libpthread/src/so_init-x86.S @@ -0,0 +1,4 @@ +.section ".init" + +call __pthread_initialize_minimal@plt + diff --git a/l4/pkg/uclibc/lib/libpthread/src/specific.c b/l4/pkg/uclibc/lib/libpthread/src/specific.c new file mode 100644 index 00000000..a1416168 --- /dev/null +++ b/l4/pkg/uclibc/lib/libpthread/src/specific.c @@ -0,0 +1,258 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +/* Thread-specific data */ + +#include +#include +#include +#include "pthread.h" +#include "internals.h" +#include "spinlock.h" +#include "restart.h" +#include + +#include + +/* Table of keys. */ + +static struct pthread_key_struct pthread_keys[PTHREAD_KEYS_MAX] = + { { 0, NULL } }; + +/* For debugging purposes put the maximum number of keys in a variable. */ +const int __linuxthreads_pthread_keys_max = PTHREAD_KEYS_MAX; +const int __linuxthreads_pthread_key_2ndlevel_size = PTHREAD_KEY_2NDLEVEL_SIZE; + +/* Mutex to protect access to pthread_keys */ + +static pthread_mutex_t pthread_keys_mutex = PTHREAD_MUTEX_INITIALIZER; + +/* Create a new key */ + +int +attribute_hidden +__pthread_key_create(pthread_key_t * key, destr_function destr) +{ + int i; + + pthread_mutex_lock(&pthread_keys_mutex); + for (i = 0; i < PTHREAD_KEYS_MAX; i++) { + if (! pthread_keys[i].in_use) { + /* Mark key in use */ + pthread_keys[i].in_use = 1; + pthread_keys[i].destr = destr; + pthread_mutex_unlock(&pthread_keys_mutex); + *key = i; + return 0; + } + } + pthread_mutex_unlock(&pthread_keys_mutex); + return EAGAIN; +} +strong_alias (__pthread_key_create, pthread_key_create) + +/* Reset deleted key's value to NULL in each live thread. + * NOTE: this executes in the context of the thread manager! */ + +struct pthread_key_delete_helper_args { + /* Damn, we need lexical closures in C! ;) */ + unsigned int idx1st, idx2nd; + pthread_descr self; +}; + +static void pthread_key_delete_helper(void *arg, pthread_descr th) +{ + struct pthread_key_delete_helper_args *args = arg; + unsigned int idx1st = args->idx1st; + unsigned int idx2nd = args->idx2nd; + pthread_descr self = args->self; + + if (self == 0) + self = args->self = thread_self(); + + if (!th->p_terminated) { + /* pthread_exit() may try to free th->p_specific[idx1st] concurrently. */ + __pthread_lock(th->p_lock, self); + if (th->p_specific[idx1st] != NULL) + th->p_specific[idx1st][idx2nd] = NULL; + __pthread_unlock(th->p_lock); + } +} + +/* Delete a key */ +int pthread_key_delete(pthread_key_t key) +{ + pthread_descr self = thread_self(); + + pthread_mutex_lock(&pthread_keys_mutex); + if (key >= PTHREAD_KEYS_MAX || !pthread_keys[key].in_use) { + pthread_mutex_unlock(&pthread_keys_mutex); + return EINVAL; + } + pthread_keys[key].in_use = 0; + pthread_keys[key].destr = NULL; + + /* Set the value of the key to NULL in all running threads, so + that if the key is reallocated later by pthread_key_create, its + associated values will be NULL in all threads. + + If no threads have been created yet, or if we are exiting, clear + it just in the current thread. */ + + struct pthread_key_delete_helper_args args; + args.idx1st = key / PTHREAD_KEY_2NDLEVEL_SIZE; + args.idx2nd = key % PTHREAD_KEY_2NDLEVEL_SIZE; + if (!l4_is_invalid_cap(__pthread_manager_request) + && !(__builtin_expect (__pthread_exit_requested, 0))) + { + struct pthread_request request; + + args.self = 0; + + request.req_thread = self; + request.req_kind = REQ_FOR_EACH_THREAD; + request.req_args.for_each.arg = &args; + request.req_args.for_each.fn = pthread_key_delete_helper; +#if 1 + __pthread_send_manager_rq(&request, 1); +#else + TEMP_FAILURE_RETRY(write_not_cancel(__pthread_manager_request, + (char *) &request, sizeof(request))); +#endif + suspend(self); + } + else + { + if (self->p_specific[args.idx1st] != NULL) + self->p_specific[args.idx1st][args.idx2nd] = NULL; + } + + pthread_mutex_unlock(&pthread_keys_mutex); + return 0; +} + +/* Set the value of a key */ + +int +attribute_hidden +__pthread_setspecific(pthread_key_t key, const void * pointer) +{ + pthread_descr self = thread_self(); + unsigned int idx1st, idx2nd; + + if (key >= PTHREAD_KEYS_MAX || !pthread_keys[key].in_use) + return EINVAL; + idx1st = key / PTHREAD_KEY_2NDLEVEL_SIZE; + idx2nd = key % PTHREAD_KEY_2NDLEVEL_SIZE; + if (THREAD_GETMEM_NC(self, p_specific, idx1st) == NULL) { + void *newp = calloc(PTHREAD_KEY_2NDLEVEL_SIZE, sizeof (void *)); + if (newp == NULL) + return ENOMEM; + THREAD_SETMEM_NC(self, p_specific ,idx1st, newp); + } + THREAD_GETMEM_NC(self, p_specific, idx1st)[idx2nd] = (void *) pointer; + return 0; +} +strong_alias (__pthread_setspecific, pthread_setspecific) + +/* Get the value of a key */ + +attribute_hidden +void * +__pthread_getspecific(pthread_key_t key) +{ + pthread_descr self = thread_self(); + unsigned int idx1st, idx2nd; + + if (key >= PTHREAD_KEYS_MAX) + return NULL; + idx1st = key / PTHREAD_KEY_2NDLEVEL_SIZE; + idx2nd = key % PTHREAD_KEY_2NDLEVEL_SIZE; + if (THREAD_GETMEM_NC(self, p_specific, idx1st) == NULL + || !pthread_keys[key].in_use) + return NULL; + return THREAD_GETMEM_NC(self, p_specific, idx1st)[idx2nd]; +} +strong_alias (__pthread_getspecific, pthread_getspecific) + +/* Call the destruction routines on all keys */ + +void +attribute_hidden +__pthread_destroy_specifics() +{ + pthread_descr self = thread_self(); + int i, j, round, found_nonzero; + destr_function destr; + void * data; + + for (round = 0, found_nonzero = 1; + found_nonzero && round < PTHREAD_DESTRUCTOR_ITERATIONS; + round++) { + found_nonzero = 0; + for (i = 0; i < PTHREAD_KEY_1STLEVEL_SIZE; i++) + if (THREAD_GETMEM_NC(self, p_specific, i) != NULL) + for (j = 0; j < PTHREAD_KEY_2NDLEVEL_SIZE; j++) { + destr = pthread_keys[i * PTHREAD_KEY_2NDLEVEL_SIZE + j].destr; + data = THREAD_GETMEM_NC(self, p_specific, i)[j]; + if (destr != NULL && data != NULL) { + THREAD_GETMEM_NC(self, p_specific, i)[j] = NULL; + destr(data); + found_nonzero = 1; + } + } + } + __pthread_lock(THREAD_GETMEM(self, p_lock), self); + for (i = 0; i < PTHREAD_KEY_1STLEVEL_SIZE; i++) { + if (THREAD_GETMEM_NC(self, p_specific, i) != NULL) { + void *p = THREAD_GETMEM_NC(self, p_specific, i); + THREAD_SETMEM_NC(self, p_specific, i, NULL); + free(p); + } + } + __pthread_unlock(THREAD_GETMEM(self, p_lock)); +} + +#if !(USE_TLS && HAVE___THREAD) + +/* Thread-specific data for libc. */ + +int +attribute_hidden +__pthread_internal_tsd_set (int key, const void * pointer) +{ + pthread_descr self = thread_self(); + + THREAD_SETMEM_NC(self, p_libc_specific, key, (void *) pointer); + return 0; +} + +void * +attribute_hidden +__pthread_internal_tsd_get (int key) +{ + pthread_descr self = thread_self(); + + return THREAD_GETMEM_NC(self, p_libc_specific, key); +} + +void ** __attribute__ ((__const__)) +attribute_hidden +__pthread_internal_tsd_address (int key) +{ + pthread_descr self = thread_self(); + return &self->p_libc_specific[key]; +} + +#endif diff --git a/l4/pkg/uclibc/lib/libpthread/src/spinlock.c b/l4/pkg/uclibc/lib/libpthread/src/spinlock.c new file mode 100644 index 00000000..06855ff6 --- /dev/null +++ b/l4/pkg/uclibc/lib/libpthread/src/spinlock.c @@ -0,0 +1,732 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1998 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +/* Internal locks */ + +#include +//l4/#include +#include +#include +#include +#include "pthread.h" +#include "internals.h" +#include "spinlock.h" +#include "restart.h" + +#include +#include + +static void __pthread_acquire(int * spinlock); + +static __inline__ void __pthread_release(int * spinlock) +{ + WRITE_MEMORY_BARRIER(); + *spinlock = __LT_SPINLOCK_INIT; + __asm__ __volatile__ ("" : "=m" (*spinlock) : "m" (*spinlock)); +} + + +/* The status field of a spinlock is a pointer whose least significant + bit is a locked flag. + + Thus the field values have the following meanings: + + status == 0: spinlock is free + status == 1: spinlock is taken; no thread is waiting on it + + (status & 1) == 1: spinlock is taken and (status & ~1L) is a + pointer to the first waiting thread; other + waiting threads are linked via the p_nextlock + field. + (status & 1) == 0: same as above, but spinlock is not taken. + + The waiting list is not sorted by priority order. + Actually, we always insert at top of list (sole insertion mode + that can be performed without locking). + For __pthread_unlock, we perform a linear search in the list + to find the highest-priority, oldest waiting thread. + This is safe because there are no concurrent __pthread_unlock + operations -- only the thread that locked the mutex can unlock it. */ + + +void internal_function __pthread_lock(struct _pthread_fastlock * lock, + pthread_descr self) +{ +#if defined HAS_COMPARE_AND_SWAP + long oldstatus, newstatus; + int successful_seizure, spurious_wakeup_count; + int spin_count; +#endif + +#if defined TEST_FOR_COMPARE_AND_SWAP + if (!__pthread_has_cas) +#endif +#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP + { + __pthread_acquire(&lock->__spinlock); + return; + } +#endif + +#if defined HAS_COMPARE_AND_SWAP + /* First try it without preparation. Maybe it's a completely + uncontested lock. */ + if (lock->__status == 0 && __compare_and_swap (&lock->__status, 0, 1)) + return; + + spurious_wakeup_count = 0; + spin_count = 0; + + /* On SMP, try spinning to get the lock. */ + + if (__pthread_smp_kernel) { + int max_count = lock->__spinlock * 2 + 10; + + if (max_count > MAX_ADAPTIVE_SPIN_COUNT) + max_count = MAX_ADAPTIVE_SPIN_COUNT; + + for (spin_count = 0; spin_count < max_count; spin_count++) { + if (((oldstatus = lock->__status) & 1) == 0) { + if(__compare_and_swap(&lock->__status, oldstatus, oldstatus | 1)) + { + if (spin_count) + lock->__spinlock += (spin_count - lock->__spinlock) / 8; + READ_MEMORY_BARRIER(); + return; + } + } +#ifdef BUSY_WAIT_NOP + BUSY_WAIT_NOP; +#endif + __asm__ __volatile__ ("" : "=m" (lock->__status) : "m" (lock->__status)); + } + + lock->__spinlock += (spin_count - lock->__spinlock) / 8; + } + +again: + + /* No luck, try once more or suspend. */ + + do { + oldstatus = lock->__status; + successful_seizure = 0; + + if ((oldstatus & 1) == 0) { + newstatus = oldstatus | 1; + successful_seizure = 1; + } else { + if (self == NULL) + self = thread_self(); + newstatus = (long) self | 1; + } + + if (self != NULL) { + THREAD_SETMEM(self, p_nextlock, (pthread_descr) (oldstatus)); + /* Make sure the store in p_nextlock completes before performing + the compare-and-swap */ + MEMORY_BARRIER(); + } + } while(! __compare_and_swap(&lock->__status, oldstatus, newstatus)); + + /* Suspend with guard against spurious wakeup. + This can happen in pthread_cond_timedwait_relative, when the thread + wakes up due to timeout and is still on the condvar queue, and then + locks the queue to remove itself. At that point it may still be on the + queue, and may be resumed by a condition signal. */ + + if (!successful_seizure) { + for (;;) { + suspend(self); + if (self->p_nextlock != NULL) { + /* Count resumes that don't belong to us. */ + spurious_wakeup_count++; + continue; + } + break; + } + goto again; + } + + /* Put back any resumes we caught that don't belong to us. */ + while (spurious_wakeup_count--) + restart(self); + + READ_MEMORY_BARRIER(); +#endif +} + +int __pthread_unlock(struct _pthread_fastlock * lock) +{ +#if defined HAS_COMPARE_AND_SWAP + long oldstatus; + pthread_descr thr, * ptr, * maxptr; + int maxprio; +#endif + +#if defined TEST_FOR_COMPARE_AND_SWAP + if (!__pthread_has_cas) +#endif +#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP + { + __pthread_release(&lock->__spinlock); + return 0; + } +#endif + +#if defined HAS_COMPARE_AND_SWAP + WRITE_MEMORY_BARRIER(); + +again: + while ((oldstatus = lock->__status) == 1) { + if (__compare_and_swap_with_release_semantics(&lock->__status, + oldstatus, 0)) + return 0; + } + + /* Find thread in waiting queue with maximal priority */ + ptr = (pthread_descr *) &lock->__status; + thr = (pthread_descr) (oldstatus & ~1L); + maxprio = 0; + maxptr = ptr; + + /* Before we iterate over the wait queue, we need to execute + a read barrier, otherwise we may read stale contents of nodes that may + just have been inserted by other processors. One read barrier is enough to + ensure we have a stable list; we don't need one for each pointer chase + through the list, because we are the owner of the lock; other threads + can only add nodes at the front; if a front node is consistent, + the ones behind it must also be. */ + + READ_MEMORY_BARRIER(); + + while (thr != 0) { + if (thr->p_priority >= maxprio) { + maxptr = ptr; + maxprio = thr->p_priority; + } + ptr = &(thr->p_nextlock); + thr = (pthread_descr)((long)(thr->p_nextlock) & ~1L); + } + + /* Remove max prio thread from waiting list. */ + if (maxptr == (pthread_descr *) &lock->__status) { + /* If max prio thread is at head, remove it with compare-and-swap + to guard against concurrent lock operation. This removal + also has the side effect of marking the lock as released + because the new status comes from thr->p_nextlock whose + least significant bit is clear. */ + thr = (pthread_descr) (oldstatus & ~1L); + if (! __compare_and_swap_with_release_semantics + (&lock->__status, oldstatus, (long)(thr->p_nextlock) & ~1L)) + goto again; + } else { + /* No risk of concurrent access, remove max prio thread normally. + But in this case we must also flip the least significant bit + of the status to mark the lock as released. */ + thr = (pthread_descr)((long)*maxptr & ~1L); + *maxptr = thr->p_nextlock; + + /* Ensure deletion from linked list completes before we + release the lock. */ + WRITE_MEMORY_BARRIER(); + + do { + oldstatus = lock->__status; + } while (!__compare_and_swap_with_release_semantics(&lock->__status, + oldstatus, oldstatus & ~1L)); + } + + /* Wake up the selected waiting thread. Woken thread can check + its own p_nextlock field for NULL to detect that it has been removed. No + barrier is needed here, since restart() and suspend() take + care of memory synchronization. */ + + thr->p_nextlock = NULL; + restart(thr); + + return 0; +#endif +} + +/* + * Alternate fastlocks do not queue threads directly. Instead, they queue + * these wait queue node structures. When a timed wait wakes up due to + * a timeout, it can leave its wait node in the queue (because there + * is no safe way to remove from the quue). Some other thread will + * deallocate the abandoned node. + */ + + +struct wait_node { + struct wait_node *next; /* Next node in null terminated linked list */ + pthread_descr thr; /* The thread waiting with this node */ + int abandoned; /* Atomic flag */ +}; + +static long wait_node_free_list; +static int wait_node_free_list_spinlock; + +/* Allocate a new node from the head of the free list using an atomic + operation, or else using malloc if that list is empty. A fundamental + assumption here is that we can safely access wait_node_free_list->next. + That's because we never free nodes once we allocate them, so a pointer to a + node remains valid indefinitely. */ + +static struct wait_node *wait_node_alloc(void) +{ + struct wait_node *new_node = 0; + + __pthread_acquire(&wait_node_free_list_spinlock); + if (wait_node_free_list != 0) { + new_node = (struct wait_node *) wait_node_free_list; + wait_node_free_list = (long) new_node->next; + } + WRITE_MEMORY_BARRIER(); + __pthread_release(&wait_node_free_list_spinlock); + + if (new_node == 0) + return malloc(sizeof *wait_node_alloc()); + + return new_node; +} + +/* Return a node to the head of the free list using an atomic + operation. */ + +static void wait_node_free(struct wait_node *wn) +{ + __pthread_acquire(&wait_node_free_list_spinlock); + wn->next = (struct wait_node *) wait_node_free_list; + wait_node_free_list = (long) wn; + WRITE_MEMORY_BARRIER(); + __pthread_release(&wait_node_free_list_spinlock); + return; +} + +#if defined HAS_COMPARE_AND_SWAP + +/* Remove a wait node from the specified queue. It is assumed + that the removal takes place concurrently with only atomic insertions at the + head of the queue. */ + +static void wait_node_dequeue(struct wait_node **pp_head, + struct wait_node **pp_node, + struct wait_node *p_node) +{ + /* If the node is being deleted from the head of the + list, it must be deleted using atomic compare-and-swap. + Otherwise it can be deleted in the straightforward way. */ + + if (pp_node == pp_head) { + /* We don't need a read barrier between these next two loads, + because it is assumed that the caller has already ensured + the stability of *p_node with respect to p_node. */ + + long oldvalue = (long) p_node; + long newvalue = (long) p_node->next; + + if (__compare_and_swap((long *) pp_node, oldvalue, newvalue)) + return; + + /* Oops! Compare and swap failed, which means the node is + no longer first. We delete it using the ordinary method. But we don't + know the identity of the node which now holds the pointer to the node + being deleted, so we must search from the beginning. */ + + for (pp_node = pp_head; p_node != *pp_node; ) { + pp_node = &(*pp_node)->next; + READ_MEMORY_BARRIER(); /* Stabilize *pp_node for next iteration. */ + } + } + + *pp_node = p_node->next; + return; +} + +#endif + +void __pthread_alt_lock(struct _pthread_fastlock * lock, + pthread_descr self) +{ +#if defined HAS_COMPARE_AND_SWAP + long oldstatus, newstatus; +#endif + struct wait_node wait_node; + +#if defined TEST_FOR_COMPARE_AND_SWAP + if (!__pthread_has_cas) +#endif +#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP + { + int suspend_needed = 0; + __pthread_acquire(&lock->__spinlock); + + if (lock->__status == 0) + lock->__status = 1; + else { + if (self == NULL) + self = thread_self(); + + wait_node.abandoned = 0; + wait_node.next = (struct wait_node *) lock->__status; + wait_node.thr = self; + lock->__status = (long) &wait_node; + suspend_needed = 1; + } + + __pthread_release(&lock->__spinlock); + + if (suspend_needed) + suspend (self); + return; + } +#endif + +#if defined HAS_COMPARE_AND_SWAP + do { + oldstatus = lock->__status; + if (oldstatus == 0) { + newstatus = 1; + } else { + if (self == NULL) + self = thread_self(); + wait_node.thr = self; + newstatus = (long) &wait_node; + } + wait_node.abandoned = 0; + wait_node.next = (struct wait_node *) oldstatus; + /* Make sure the store in wait_node.next completes before performing + the compare-and-swap */ + MEMORY_BARRIER(); + } while(! __compare_and_swap(&lock->__status, oldstatus, newstatus)); + + /* Suspend. Note that unlike in __pthread_lock, we don't worry + here about spurious wakeup. That's because this lock is not + used in situations where that can happen; the restart can + only come from the previous lock owner. */ + + if (oldstatus != 0) + suspend(self); + + READ_MEMORY_BARRIER(); +#endif +} + +/* Timed-out lock operation; returns 0 to indicate timeout. */ + +int __pthread_alt_timedlock(struct _pthread_fastlock * lock, + pthread_descr self, const struct timespec *abstime) +{ + long oldstatus = 0; +#if defined HAS_COMPARE_AND_SWAP + long newstatus; +#endif + struct wait_node *p_wait_node = wait_node_alloc(); + + /* Out of memory, just give up and do ordinary lock. */ + if (p_wait_node == 0) { + __pthread_alt_lock(lock, self); + return 1; + } + +#if defined TEST_FOR_COMPARE_AND_SWAP + if (!__pthread_has_cas) +#endif +#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP + { + __pthread_acquire(&lock->__spinlock); + + if (lock->__status == 0) + lock->__status = 1; + else { + if (self == NULL) + self = thread_self(); + + p_wait_node->abandoned = 0; + p_wait_node->next = (struct wait_node *) lock->__status; + p_wait_node->thr = self; + lock->__status = (long) p_wait_node; + oldstatus = 1; /* force suspend */ + } + + __pthread_release(&lock->__spinlock); + goto suspend; + } +#endif + +#if defined HAS_COMPARE_AND_SWAP + do { + oldstatus = lock->__status; + if (oldstatus == 0) { + newstatus = 1; + } else { + if (self == NULL) + self = thread_self(); + p_wait_node->thr = self; + newstatus = (long) p_wait_node; + } + p_wait_node->abandoned = 0; + p_wait_node->next = (struct wait_node *) oldstatus; + /* Make sure the store in wait_node.next completes before performing + the compare-and-swap */ + MEMORY_BARRIER(); + } while(! __compare_and_swap(&lock->__status, oldstatus, newstatus)); +#endif + +#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP + suspend: +#endif + + /* If we did not get the lock, do a timed suspend. If we wake up due + to a timeout, then there is a race; the old lock owner may try + to remove us from the queue. This race is resolved by us and the owner + doing an atomic testandset() to change the state of the wait node from 0 + to 1. If we succeed, then it's a timeout and we abandon the node in the + queue. If we fail, it means the owner gave us the lock. */ + + if (oldstatus != 0) { + if (timedsuspend(self, abstime) == 0) { + if (!testandset(&p_wait_node->abandoned)) + return 0; /* Timeout! */ + + /* Eat oustanding resume from owner, otherwise wait_node_free() below + will race with owner's wait_node_dequeue(). */ + suspend(self); + } + } + + wait_node_free(p_wait_node); + + READ_MEMORY_BARRIER(); + + return 1; /* Got the lock! */ +} + +void __pthread_alt_unlock(struct _pthread_fastlock *lock) +{ + struct wait_node *p_node, **pp_node, *p_max_prio, **pp_max_prio; + struct wait_node ** const pp_head = (struct wait_node **) &lock->__status; + int maxprio; + + WRITE_MEMORY_BARRIER(); + +#if defined TEST_FOR_COMPARE_AND_SWAP + if (!__pthread_has_cas) +#endif +#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP + { + __pthread_acquire(&lock->__spinlock); + } +#endif + + while (1) { + + /* If no threads are waiting for this lock, try to just + atomically release it. */ +#if defined TEST_FOR_COMPARE_AND_SWAP + if (!__pthread_has_cas) +#endif +#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP + { + if (lock->__status == 0 || lock->__status == 1) { + lock->__status = 0; + break; + } + } +#endif + +#if defined TEST_FOR_COMPARE_AND_SWAP + else +#endif + +#if defined HAS_COMPARE_AND_SWAP + { + long oldstatus = lock->__status; + if (oldstatus == 0 || oldstatus == 1) { + if (__compare_and_swap_with_release_semantics (&lock->__status, oldstatus, 0)) + break; + else + continue; + } + } +#endif + + /* Process the entire queue of wait nodes. Remove all abandoned + wait nodes and put them into the global free queue, and + remember the one unabandoned node which refers to the thread + having the highest priority. */ + + pp_max_prio = pp_node = pp_head; + p_max_prio = p_node = *pp_head; + maxprio = INT_MIN; + + READ_MEMORY_BARRIER(); /* Prevent access to stale data through p_node */ + + while (p_node != (struct wait_node *) 1) { + int prio; + + if (p_node->abandoned) { + /* Remove abandoned node. */ +#if defined TEST_FOR_COMPARE_AND_SWAP + if (!__pthread_has_cas) +#endif +#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP + *pp_node = p_node->next; +#endif +#if defined TEST_FOR_COMPARE_AND_SWAP + else +#endif +#if defined HAS_COMPARE_AND_SWAP + wait_node_dequeue(pp_head, pp_node, p_node); +#endif + wait_node_free(p_node); + /* Note that the next assignment may take us to the beginning + of the queue, to newly inserted nodes, if pp_node == pp_head. + In that case we need a memory barrier to stabilize the first of + these new nodes. */ + p_node = *pp_node; + if (pp_node == pp_head) + READ_MEMORY_BARRIER(); /* No stale reads through p_node */ + continue; + } else if ((prio = p_node->thr->p_priority) >= maxprio) { + /* Otherwise remember it if its thread has a higher or equal priority + compared to that of any node seen thus far. */ + maxprio = prio; + pp_max_prio = pp_node; + p_max_prio = p_node; + } + + /* This canno6 jump backward in the list, so no further read + barrier is needed. */ + pp_node = &p_node->next; + p_node = *pp_node; + } + + /* If all threads abandoned, go back to top */ + if (maxprio == INT_MIN) + continue; + + ASSERT (p_max_prio != (struct wait_node *) 1); + + /* Now we want to to remove the max priority thread's wait node from + the list. Before we can do this, we must atomically try to change the + node's abandon state from zero to nonzero. If we succeed, that means we + have the node that we will wake up. If we failed, then it means the + thread timed out and abandoned the node in which case we repeat the + whole unlock operation. */ + + if (!testandset(&p_max_prio->abandoned)) { +#if defined TEST_FOR_COMPARE_AND_SWAP + if (!__pthread_has_cas) +#endif +#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP + *pp_max_prio = p_max_prio->next; +#endif +#if defined TEST_FOR_COMPARE_AND_SWAP + else +#endif +#if defined HAS_COMPARE_AND_SWAP + wait_node_dequeue(pp_head, pp_max_prio, p_max_prio); +#endif + + /* Release the spinlock *before* restarting. */ +#if defined TEST_FOR_COMPARE_AND_SWAP + if (!__pthread_has_cas) +#endif +#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP + { + __pthread_release(&lock->__spinlock); + } +#endif + + restart(p_max_prio->thr); + + return; + } + } + +#if defined TEST_FOR_COMPARE_AND_SWAP + if (!__pthread_has_cas) +#endif +#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP + { + __pthread_release(&lock->__spinlock); + } +#endif +} + + +/* Compare-and-swap emulation with a spinlock */ + +#ifdef TEST_FOR_COMPARE_AND_SWAP +int __pthread_has_cas = 0; +#endif + +#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP + +int __pthread_compare_and_swap(long * ptr, long oldval, long newval, + int * spinlock) +{ + int res; + + __pthread_acquire(spinlock); + + if (*ptr == oldval) { + *ptr = newval; res = 1; + } else { + res = 0; + } + + __pthread_release(spinlock); + + return res; +} + +#endif + +/* The retry strategy is as follows: + - We test and set the spinlock MAX_SPIN_COUNT times, calling + sched_yield() each time. This gives ample opportunity for other + threads with priority >= our priority to make progress and + release the spinlock. + - If a thread with priority < our priority owns the spinlock, + calling sched_yield() repeatedly is useless, since we're preventing + the owning thread from making progress and releasing the spinlock. + So, after MAX_SPIN_LOCK attemps, we suspend the calling thread + using nanosleep(). This again should give time to the owning thread + for releasing the spinlock. + Notice that the nanosleep() interval must not be too small, + since the kernel does busy-waiting for short intervals in a realtime + process (!). The smallest duration that guarantees thread + suspension is currently 2ms. + - When nanosleep() returns, we try again, doing MAX_SPIN_COUNT + sched_yield(), then sleeping again if needed. */ + +static void __pthread_acquire(int * spinlock) +{ + int cnt = 0; + + READ_MEMORY_BARRIER(); + + while (testandset(spinlock)) { + if (cnt < MAX_SPIN_COUNT) { + l4_thread_yield(); + cnt++; + } else { + l4_usleep(SPIN_SLEEP_DURATION / 1000); + cnt = 0; + } + } +} diff --git a/l4/pkg/uclibc/lib/libpthread/src/spinlock.h b/l4/pkg/uclibc/lib/libpthread/src/spinlock.h new file mode 100644 index 00000000..a76f119a --- /dev/null +++ b/l4/pkg/uclibc/lib/libpthread/src/spinlock.h @@ -0,0 +1,223 @@ +/* Linuxthreads - a simple clone()-based implementation of Posix */ +/* threads for Linux. */ +/* Copyright (C) 1998 Xavier Leroy (Xavier.Leroy@inria.fr) */ +/* */ +/* This program is free software; you can redistribute it and/or */ +/* modify it under the terms of the GNU Library General Public License */ +/* as published by the Free Software Foundation; either version 2 */ +/* of the License, or (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Library General Public License for more details. */ + +#include + + +/* There are 2 compare and swap synchronization primitives with + different semantics: + + 1. compare_and_swap, which has acquire semantics (i.e. it + completes befor subsequent writes.) + 2. compare_and_swap_with_release_semantics, which has release + semantics (it completes after previous writes.) + + For those platforms on which they are the same. HAS_COMPARE_AND_SWAP + should be defined. For those platforms on which they are different, + HAS_COMPARE_AND_SWAP_WITH_RELEASE_SEMANTICS has to be defined. */ + +#ifndef HAS_COMPARE_AND_SWAP +#ifdef HAS_COMPARE_AND_SWAP_WITH_RELEASE_SEMANTICS +#define HAS_COMPARE_AND_SWAP +#endif +#endif + +__BEGIN_DECLS + +#if defined(TEST_FOR_COMPARE_AND_SWAP) +extern int __pthread_has_cas; +extern int __pthread_compare_and_swap(long * ptr, long oldval, long newval, + int * spinlock); + +static __inline__ int compare_and_swap(long * ptr, long oldval, long newval, + int * spinlock) +{ + if (__builtin_expect (__pthread_has_cas, 1)) + return __compare_and_swap(ptr, oldval, newval); + else + return __pthread_compare_and_swap(ptr, oldval, newval, spinlock); +} + +#elif defined(HAS_COMPARE_AND_SWAP) + +#ifdef IMPLEMENT_TAS_WITH_CAS +#define testandset(p) !__compare_and_swap((long int *) p, 0, 1) +#endif + +#ifdef HAS_COMPARE_AND_SWAP_WITH_RELEASE_SEMANTICS + +static __inline__ int +compare_and_swap_with_release_semantics (long * ptr, long oldval, + long newval, int * spinlock) +{ + return __compare_and_swap_with_release_semantics (ptr, oldval, + newval); +} + +#endif + +static __inline__ int compare_and_swap(long * ptr, long oldval, long newval, + int * spinlock) +{ + return __compare_and_swap(ptr, oldval, newval); +} + +#else + +extern int __pthread_compare_and_swap(long * ptr, long oldval, long newval, + int * spinlock); + +static __inline__ int compare_and_swap(long * ptr, long oldval, long newval, + int * spinlock) +{ + return __pthread_compare_and_swap(ptr, oldval, newval, spinlock); +} + +#endif + +#ifndef HAS_COMPARE_AND_SWAP_WITH_RELEASE_SEMANTICS +#define compare_and_swap_with_release_semantics compare_and_swap +#define __compare_and_swap_with_release_semantics __compare_and_swap +#endif + +/* Internal locks */ + +extern void internal_function __pthread_lock(struct _pthread_fastlock * lock, + pthread_descr self); +extern int __pthread_unlock(struct _pthread_fastlock *lock); + +static __inline__ void __pthread_init_lock(struct _pthread_fastlock * lock) +{ + lock->__status = 0; + lock->__spinlock = __LT_SPINLOCK_INIT; +} + +static __inline__ int __pthread_trylock (struct _pthread_fastlock * lock) +{ +#if defined TEST_FOR_COMPARE_AND_SWAP + if (!__pthread_has_cas) +#endif +#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP + { + return (testandset(&lock->__spinlock) ? EBUSY : 0); + } +#endif + +#if defined HAS_COMPARE_AND_SWAP + do { + if (lock->__status != 0) return EBUSY; + } while(! __compare_and_swap(&lock->__status, 0, 1)); + return 0; +#endif +} + +/* Variation of internal lock used for pthread_mutex_t, supporting + timed-out waits. Warning: do not mix these operations with the above ones + over the same lock object! */ + +extern void __pthread_alt_lock(struct _pthread_fastlock * lock, + pthread_descr self); + +extern int __pthread_alt_timedlock(struct _pthread_fastlock * lock, + pthread_descr self, const struct timespec *abstime); + +extern void __pthread_alt_unlock(struct _pthread_fastlock *lock); + +static __inline__ void __pthread_alt_init_lock(struct _pthread_fastlock * lock) +{ + lock->__status = 0; + lock->__spinlock = __LT_SPINLOCK_INIT; +} + +static __inline__ int __pthread_alt_trylock (struct _pthread_fastlock * lock) +{ +#if defined TEST_FOR_COMPARE_AND_SWAP + if (!__pthread_has_cas) +#endif +#if !defined HAS_COMPARE_AND_SWAP || defined TEST_FOR_COMPARE_AND_SWAP + { + int res = EBUSY; + + if (testandset(&lock->__spinlock) == 0) + { + if (lock->__status == 0) + { + lock->__status = 1; + WRITE_MEMORY_BARRIER(); + res = 0; + } + lock->__spinlock = __LT_SPINLOCK_INIT; + } + return res; + } +#endif + +#if defined HAS_COMPARE_AND_SWAP + do { + if (lock->__status != 0) return EBUSY; + } while(! compare_and_swap(&lock->__status, 0, 1, &lock->__spinlock)); + return 0; +#endif +} + +/* Operations on pthread_atomic, which is defined in internals.h */ + +static __inline__ long +pthread_atomic_increment (struct pthread_atomic *pa) +{ + long oldval; + + do { + oldval = pa->p_count; + } while (!compare_and_swap(&pa->p_count, oldval, oldval + 1, &pa->p_spinlock)); + + return oldval; +} + + +static __inline__ long +pthread_atomic_decrement (struct pthread_atomic *pa) +{ + long oldval; + + do { + oldval = pa->p_count; + } while (!compare_and_swap(&pa->p_count, oldval, oldval - 1, &pa->p_spinlock)); + + return oldval; +} + + +static __inline__ __attribute__((always_inline)) void +__pthread_set_own_extricate_if (pthread_descr self, pthread_extricate_if *peif) +{ + /* Only store a non-null peif if the thread has cancellation enabled. + Otherwise pthread_cancel will unconditionally call the extricate handler, + and restart the thread giving rise to forbidden spurious wakeups. */ + if (peif == NULL + || THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) + { + /* If we are removing the extricate interface, we need to synchronize + against pthread_cancel so that it does not continue with a pointer + to a deallocated pthread_extricate_if struct! The thread lock + is (ab)used for this synchronization purpose. */ + if (peif == NULL) + __pthread_lock (THREAD_GETMEM(self, p_lock), self); + THREAD_SETMEM(self, p_extricate, peif); + if (peif == NULL) + __pthread_unlock (THREAD_GETMEM(self, p_lock)); + } +} + +__END_DECLS diff --git a/l4/pkg/uclibc/lib/libpthread/src/sysdeps/alpha/dl-tls.h b/l4/pkg/uclibc/lib/libpthread/src/sysdeps/alpha/dl-tls.h new file mode 100644 index 00000000..f81f95d7 --- /dev/null +++ b/l4/pkg/uclibc/lib/libpthread/src/sysdeps/alpha/dl-tls.h @@ -0,0 +1,29 @@ +/* Thread-local storage handling in the ELF dynamic linker. Alpha version. + Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + + +/* Type used for the representation of TLS information in the GOT. */ +typedef struct +{ + unsigned long int ti_module; + unsigned long int ti_offset; +} tls_index; + + +extern void *__tls_get_addr (tls_index *ti); diff --git a/l4/pkg/uclibc/lib/libpthread/src/sysdeps/alpha/tls.h b/l4/pkg/uclibc/lib/libpthread/src/sysdeps/alpha/tls.h new file mode 100644 index 00000000..99cd27a0 --- /dev/null +++ b/l4/pkg/uclibc/lib/libpthread/src/sysdeps/alpha/tls.h @@ -0,0 +1,127 @@ +/* Definition for thread-local data handling. NPTL/Alpha version. + Copyright (C) 2003, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _TLS_H +#define _TLS_H 1 + +#ifndef __ASSEMBLER__ +# include +# include +# include + +/* Type for the dtv. */ +typedef union dtv +{ + size_t counter; + struct + { + void *val; + bool is_static; + } pointer; +} dtv_t; + +#else /* __ASSEMBLER__ */ +# include +#endif /* __ASSEMBLER__ */ + + +/* We require TLS support in the tools. */ +#ifndef HAVE_TLS_SUPPORT +# error "TLS support is required." +#endif + +/* Signal that TLS support is available. */ +# define USE_TLS 1 + +#ifndef __ASSEMBLER__ + +/* Get system call information. */ +# include + +/* The TP points to the start of the thread blocks. */ +# define TLS_DTV_AT_TP 1 + +/* Get the thread descriptor definition. */ +# include + +typedef struct +{ + dtv_t *dtv; + void *private; +} tcbhead_t; + +/* This is the size of the initial TCB. */ +# define TLS_INIT_TCB_SIZE sizeof (tcbhead_t) + +/* Alignment requirements for the initial TCB. */ +# define TLS_INIT_TCB_ALIGN 16 + +/* This is the size of the TCB. */ +# define TLS_TCB_SIZE sizeof (tcbhead_t) + +/* This is the size we need before TCB. */ +# define TLS_PRE_TCB_SIZE sizeof (struct pthread) + +/* Alignment requirements for the TCB. */ +# define TLS_TCB_ALIGN 16 + +/* Install the dtv pointer. The pointer passed is to the element with + index -1 which contain the length. */ +# define INSTALL_DTV(tcbp, dtvp) \ + (((tcbhead_t *) (tcbp))->dtv = (dtvp) + 1) + +/* Install new dtv for current thread. */ +# define INSTALL_NEW_DTV(dtv) \ + (THREAD_DTV() = (dtv)) + +/* Return dtv of given thread descriptor. */ +# define GET_DTV(tcbp) \ + (((tcbhead_t *) (tcbp))->dtv) + +/* Code to initially initialize the thread pointer. This might need + special attention since 'errno' is not yet available and if the + operation can cause a failure 'errno' must not be touched. */ +# define TLS_INIT_TP(tcbp, secondcall) \ + (__builtin_set_thread_pointer ((void *)(tcbp)), NULL) + +/* Return the address of the dtv for the current thread. */ +# define THREAD_DTV() \ + (((tcbhead_t *) __builtin_thread_pointer ())->dtv) + +/* Return the thread descriptor for the current thread. */ +# define THREAD_SELF \ + ((struct pthread *)__builtin_thread_pointer () - 1) + +/* Magic for libthread_db to know how to do THREAD_SELF. */ +# define DB_THREAD_SELF \ + REGISTER (64, 64, 32 * 8, -sizeof (struct pthread)) + +/* Access to data in the thread descriptor is easy. */ +#define THREAD_GETMEM(descr, member) \ + descr->member +#define THREAD_GETMEM_NC(descr, member, idx) \ + descr->member[idx] +#define THREAD_SETMEM(descr, member, value) \ + descr->member = (value) +#define THREAD_SETMEM_NC(descr, member, idx, value) \ + descr->member[idx] = (value) + +#endif /* __ASSEMBLER__ */ + +#endif /* tls.h */ diff --git a/l4/pkg/uclibc/lib/libpthread/src/sysdeps/arm/dl-tls.h b/l4/pkg/uclibc/lib/libpthread/src/sysdeps/arm/dl-tls.h new file mode 100644 index 00000000..e0324a7b --- /dev/null +++ b/l4/pkg/uclibc/lib/libpthread/src/sysdeps/arm/dl-tls.h @@ -0,0 +1,29 @@ +/* Thread-local storage handling in the ELF dynamic linker. ARM version. + Copyright (C) 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + + +/* Type used for the representation of TLS information in the GOT. */ +typedef struct +{ + unsigned long int ti_module; + unsigned long int ti_offset; +} tls_index; + + +extern void *__tls_get_addr (tls_index *ti); diff --git a/l4/pkg/uclibc/lib/libpthread/src/sysdeps/arm/pt-machine.h b/l4/pkg/uclibc/lib/libpthread/src/sysdeps/arm/pt-machine.h new file mode 100644 index 00000000..c942f9dd --- /dev/null +++ b/l4/pkg/uclibc/lib/libpthread/src/sysdeps/arm/pt-machine.h @@ -0,0 +1,62 @@ +/* Machine-dependent pthreads configuration and inline functions. + ARM version. + Copyright (C) 1997, 1998, 2000, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Philip Blundell . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _PT_MACHINE_H +#define _PT_MACHINE_H 1 + +#include +#include + +/* This will not work on ARM1 or ARM2 because SWP is lacking on those + machines. Unfortunately we have no way to detect this at compile + time; let's hope nobody tries to use one. */ + +/* Spinlock implementation; required. */ +L4_INLINE long int +testandset (int *spinlock) +{ + register unsigned int ret; + +#if 0 + __asm__ __volatile__("swp %0, %1, [%2]" + : "=r"(ret) + : "0"(1), "r"(spinlock)); +#else + ret = l4_atomic_xchg((volatile long int *)spinlock, 1); +#endif + + return ret; +} + + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#define CURRENT_STACK_FRAME stack_pointer +register char * stack_pointer __asm__ ("sp"); + +/* Compare-and-swap for semaphores. It's always available on i686. */ +#define HAS_COMPARE_AND_SWAP + +L4_INLINE int +__compare_and_swap (long int *p, long int oldval, long int newval) +{ return l4util_cmpxchg32((l4_uint32_t*)p,oldval,newval); } + +#endif /* pt-machine.h */ diff --git a/l4/pkg/uclibc/lib/libpthread/src/sysdeps/arm/tls.h b/l4/pkg/uclibc/lib/libpthread/src/sysdeps/arm/tls.h new file mode 100644 index 00000000..96aeffdc --- /dev/null +++ b/l4/pkg/uclibc/lib/libpthread/src/sysdeps/arm/tls.h @@ -0,0 +1,178 @@ +/* Definition for thread-local data handling. NPTL/ARM version. + Copyright (C) 2005,2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _TLS_H +#define _TLS_H 1 +#ifndef __ASSEMBLER__ + +# include +# include +# include + +/* Type for the dtv. */ +typedef union dtv +{ + size_t counter; + struct + { + void *val; + bool is_static; + } pointer; +} dtv_t; + +#else /* __ASSEMBLER__ */ +# include +#endif /* __ASSEMBLER__ */ + + +/* We require TLS support in the tools. */ +#define HAVE_TLS_SUPPORT 1 +#define HAVE_TLS_MODEL_ATTRIBUTE 1 +#define HAVE___THREAD 1 + +/* Signal that TLS support is available. */ +#define USE_TLS 1 + +#ifndef __ASSEMBLER__ + +/* Get system call information. */ +//# include + +/* The TP points to the start of the thread blocks. */ +# define TLS_DTV_AT_TP 1 + +/* Get the thread descriptor definition. */ +# include <../../descr.h> + +typedef struct +{ + dtv_t *dtv; + void *private_data; +} tcbhead_t; + +/* This is the size of the initial TCB. */ +# define TLS_INIT_TCB_SIZE sizeof (tcbhead_t) + +/* Alignment requirements for the initial TCB. */ +# define TLS_INIT_TCB_ALIGN 16 + +/* This is the size of the TCB. */ +# define TLS_TCB_SIZE sizeof (tcbhead_t) + +/* This is the size we need before TCB. */ +# define TLS_PRE_TCB_SIZE sizeof (struct _pthread_descr_struct) + +/* Alignment requirements for the TCB. */ +# define TLS_TCB_ALIGN 16 + +/* Install the dtv pointer. The pointer passed is to the element with + index -1 which contain the length. */ +# define INSTALL_DTV(tcbp, dtvp) \ + (((tcbhead_t *) (tcbp))->dtv = (dtvp) + 1) + +/* Install new dtv for current thread. */ +# define INSTALL_NEW_DTV(dtv) \ + (THREAD_DTV() = (dtv)) + +/* Return dtv of given thread descriptor. */ +# define GET_DTV(tcbp) \ + (((tcbhead_t *) (tcbp))->dtv) + +/* Code to initially initialize the thread pointer. This might need + special attention since 'errno' is not yet available and if the + operation can cause a failure 'errno' must not be touched. */ +# define TLS_INIT_TP_ORIG(tcbp, secondcall) \ + ({ INTERNAL_SYSCALL_DECL (err); \ + long result_var; \ + result_var = INTERNAL_SYSCALL_ARM (set_tls, err, 1, (tcbp)); \ + INTERNAL_SYSCALL_ERROR_P (result_var, err) \ + ? "unknown error" : NULL; }) + +# define TLS_INIT_TP_v6p(tcbp, secondcall) \ + ({ asm volatile ("mcr p15, 0, %0, c13, c0, 2" : : "r" (tcbp)); NULL; }) + +# define TLS_INIT_TP_generic(tcbp, secondcall) \ + ({ l4_utcb_tcr()->user[0] = (l4_addr_t)tcbp - TLS_PRE_TCB_SIZE; NULL; }) + +# define TLS_INIT_TP(tcbp, secondcall) TLS_INIT_TP_generic(tcbp, secondcall) + + +# define TLS_get_thread_pointer_v6p() \ + ({ tcbhead_t *x; asm volatile ("mrc p15, 0, %0, c13, c0, 2" : "=r" (x)); x; }) + +# define TLS_get_thread_pointer_generic() \ + ({ (tcbhead_t *)(l4_utcb_tcr()->user[0] + TLS_PRE_TCB_SIZE); }) + +# define TLS_get_thread_pointer() TLS_get_thread_pointer_generic() + +/* Return the address of the dtv for the current thread. */ +# define THREAD_DTV_ORIG() \ + (((tcbhead_t *) __builtin_thread_pointer ())->dtv) +# define THREAD_DTV() \ + (((tcbhead_t *) TLS_get_thread_pointer())->dtv) + +/* Return the thread descriptor for the current thread. */ +# define THREAD_SELF_ORIG \ + ((struct _pthread_descr_struct *)__builtin_thread_pointer () - 1) +# define THREAD_SELF \ + ((struct _pthread_descr_struct *)TLS_get_thread_pointer() - 1) + +/* Magic for libthread_db to know how to do THREAD_SELF. */ +# define DB_THREAD_SELF \ + CONST_THREAD_AREA (32, sizeof (struct pthread)) + +/* Access to data in the thread descriptor is easy. */ +#define THREAD_GETMEM(descr, member) \ + descr->member +#define THREAD_GETMEM_NC(descr, member, idx) \ + descr->member[idx] +#define THREAD_SETMEM(descr, member, value) \ + descr->member = (value) +#define THREAD_SETMEM_NC(descr, member, idx, value) \ + descr->member[idx] = (value) + +/* Initializing the thread pointer will generate a SIGILL if the syscall + is not available. */ +#define TLS_INIT_TP_EXPENSIVE 1 + +/* Get and set the global scope generation counter in struct pthread. */ +#define THREAD_GSCOPE_FLAG_UNUSED 0 +#define THREAD_GSCOPE_FLAG_USED 1 +#define THREAD_GSCOPE_FLAG_WAIT 2 +#define THREAD_GSCOPE_RESET_FLAG() \ + do \ + { int __res \ + = atomic_exchange_rel (&THREAD_SELF->header.gscope_flag, \ + THREAD_GSCOPE_FLAG_UNUSED); \ + if (__res == THREAD_GSCOPE_FLAG_WAIT) \ + lll_futex_wake (&THREAD_SELF->header.gscope_flag, 1, LLL_PRIVATE); \ + } \ + while (0) +#define THREAD_GSCOPE_SET_FLAG() \ + do \ + { \ + THREAD_SELF->header.gscope_flag = THREAD_GSCOPE_FLAG_USED; \ + atomic_write_barrier (); \ + } \ + while (0) +#define THREAD_GSCOPE_WAIT() \ + GL(dl_wait_lookup_done) () + +#endif /* __ASSEMBLER__ */ +#endif /* tls.h */ diff --git a/l4/pkg/uclibc/lib/libpthread/src/sysdeps/generic/dl-tls.c b/l4/pkg/uclibc/lib/libpthread/src/sysdeps/generic/dl-tls.c new file mode 100644 index 00000000..4acfa4ba --- /dev/null +++ b/l4/pkg/uclibc/lib/libpthread/src/sysdeps/generic/dl-tls.c @@ -0,0 +1,899 @@ +/* Thread-local storage handling in the ELF dynamic linker. Generic version. + Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#if defined SHARED || defined NOT_IN_libc +# error in buildsystem: This file is for libc.a +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#define _dl_malloc malloc +#define _dl_memset memset +#define _dl_mempcpy mempcpy +#define _dl_dprintf fprintf +#define _dl_debug_file stderr +#define _dl_exit exit + +/* Amount of excess space to allocate in the static TLS area + to allow dynamic loading of modules defining IE-model TLS data. */ +# define TLS_STATIC_SURPLUS 64 + DL_NNS * 100 + +/* Value used for dtv entries for which the allocation is delayed. */ +# define TLS_DTV_UNALLOCATED ((void *) -1l) + + +/* Out-of-memory handler. */ +# ifdef SHARED +static void +__attribute__ ((__noreturn__)) +oom (void) +{ + do { + _dl_dprintf (_dl_debug_file, + "cannot allocate thread-local memory: ABORT\n"); + _dl_exit (127); + } while (1); +} +# endif + + +void *_dl_memalign(size_t alignment, size_t bytes) +{ + return _dl_malloc(bytes); +} + + +/* + * We are trying to perform a static TLS relocation in MAP, but it was + * dynamically loaded. This can only work if there is enough surplus in + * the static TLS area already allocated for each running thread. If this + * object's TLS segment is too big to fit, we fail. If it fits, + * we set MAP->l_tls_offset and return. + * This function intentionally does not return any value but signals error + * directly, as static TLS should be rare and code handling it should + * not be inlined as much as possible. + */ + + +void +internal_function __attribute_noinline__ +_dl_allocate_static_tls (struct link_map *map) +{ + /* If the alignment requirements are too high fail. */ + if (map->l_tls_align > _dl_tls_static_align) + { +fail: + _dl_dprintf(_dl_debug_file, "cannot allocate memory in static TLS block"); + _dl_exit(30); + } + +# if defined(TLS_TCB_AT_TP) + size_t freebytes; + size_t n; + size_t blsize; + + freebytes = _dl_tls_static_size - _dl_tls_static_used - TLS_TCB_SIZE; + + blsize = map->l_tls_blocksize + map->l_tls_firstbyte_offset; + if (freebytes < blsize) + goto fail; + + n = (freebytes - blsize) / map->l_tls_align; + + size_t offset = _dl_tls_static_used + (freebytes - n * map->l_tls_align + - map->l_tls_firstbyte_offset); + + map->l_tls_offset = _dl_tls_static_used = offset; +# elif defined(TLS_DTV_AT_TP) + size_t used; + size_t check; + + size_t offset = roundup (_dl_tls_static_used, map->l_tls_align); + used = offset + map->l_tls_blocksize; + check = used; + + /* dl_tls_static_used includes the TCB at the beginning. */ + if (check > _dl_tls_static_size) + goto fail; + + map->l_tls_offset = offset; + _dl_tls_static_used = used; +# else +# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined" +# endif + + /* + * If the object is not yet relocated we cannot initialize the + * static TLS region. Delay it. + */ + if (((struct elf_resolve *) map)->init_flag & RELOCS_DONE) + { +#ifdef SHARED + /* + * Update the slot information data for at least the generation of + * the DSO we are allocating data for. + */ + if (__builtin_expect (THREAD_DTV()[0].counter != _dl_tls_generation, 0)) + (void) _dl_update_slotinfo (map->l_tls_modid); +#endif + _dl_init_static_tls (map); + } + else + map->l_need_tls_init = 1; +} + +size_t +internal_function +_dl_next_tls_modid (void) +{ + size_t result; + + if (__builtin_expect (GL(dl_tls_dtv_gaps), false)) + { + size_t disp = 0; + struct dtv_slotinfo_list *runp = GL(dl_tls_dtv_slotinfo_list); + + /* Note that this branch will never be executed during program + start since there are no gaps at that time. Therefore it + does not matter that the dl_tls_dtv_slotinfo is not allocated + yet when the function is called for the first times. + + NB: the offset +1 is due to the fact that DTV[0] is used + for something else. */ + result = GL(dl_tls_static_nelem) + 1; + if (result <= GL(dl_tls_max_dtv_idx)) + do + { + while (result - disp < runp->len) + { + if (runp->slotinfo[result - disp].map == NULL) + break; + + ++result; + assert (result <= GL(dl_tls_max_dtv_idx) + 1); + } + + if (result - disp < runp->len) + break; + + disp += runp->len; + } + while ((runp = runp->next) != NULL); + + if (result > GL(dl_tls_max_dtv_idx)) + { + /* The new index must indeed be exactly one higher than the + previous high. */ + assert (result == GL(dl_tls_max_dtv_idx) + 1); + /* There is no gap anymore. */ + GL(dl_tls_dtv_gaps) = false; + + goto nogaps; + } + } + else + { + /* No gaps, allocate a new entry. */ + nogaps: + + result = ++GL(dl_tls_max_dtv_idx); + } + + return result; +} + + +# ifdef SHARED +void +internal_function +_dl_determine_tlsoffset (void) +{ + size_t max_align = TLS_TCB_ALIGN; + size_t freetop = 0; + size_t freebottom = 0; + + /* The first element of the dtv slot info list is allocated. */ + assert (GL(dl_tls_dtv_slotinfo_list) != NULL); + /* There is at this point only one element in the + dl_tls_dtv_slotinfo_list list. */ + assert (GL(dl_tls_dtv_slotinfo_list)->next == NULL); + + struct dtv_slotinfo *slotinfo = GL(dl_tls_dtv_slotinfo_list)->slotinfo; + + /* Determining the offset of the various parts of the static TLS + block has several dependencies. In addition we have to work + around bugs in some toolchains. + + Each TLS block from the objects available at link time has a size + and an alignment requirement. The GNU ld computes the alignment + requirements for the data at the positions *in the file*, though. + I.e, it is not simply possible to allocate a block with the size + of the TLS program header entry. The data is layed out assuming + that the first byte of the TLS block fulfills + + p_vaddr mod p_align == &TLS_BLOCK mod p_align + + This means we have to add artificial padding at the beginning of + the TLS block. These bytes are never used for the TLS data in + this module but the first byte allocated must be aligned + according to mod p_align == 0 so that the first byte of the TLS + block is aligned according to p_vaddr mod p_align. This is ugly + and the linker can help by computing the offsets in the TLS block + assuming the first byte of the TLS block is aligned according to + p_align. + + The extra space which might be allocated before the first byte of + the TLS block need not go unused. The code below tries to use + that memory for the next TLS block. This can work if the total + memory requirement for the next TLS block is smaller than the + gap. */ + +# if defined(TLS_TCB_AT_TP) + /* We simply start with zero. */ + size_t offset = 0; + + size_t cnt; + for (cnt = 0; slotinfo[cnt].map != NULL; ++cnt) + { + assert (cnt < GL(dl_tls_dtv_slotinfo_list)->len); + + size_t firstbyte = (-slotinfo[cnt].map->l_tls_firstbyte_offset + & (slotinfo[cnt].map->l_tls_align - 1)); + size_t off; + max_align = MAX (max_align, slotinfo[cnt].map->l_tls_align); + + if (freebottom - freetop >= slotinfo[cnt].map->l_tls_blocksize) + { + off = roundup (freetop + slotinfo[cnt].map->l_tls_blocksize + - firstbyte, slotinfo[cnt].map->l_tls_align) + + firstbyte; + if (off <= freebottom) + { + freetop = off; + + /* XXX For some architectures we perhaps should store the + negative offset. */ + slotinfo[cnt].map->l_tls_offset = off; + continue; + } + } + + off = roundup (offset + slotinfo[cnt].map->l_tls_blocksize - firstbyte, + slotinfo[cnt].map->l_tls_align) + firstbyte; + if (off > offset + slotinfo[cnt].map->l_tls_blocksize + + (freebottom - freetop)) + { + freetop = offset; + freebottom = off - slotinfo[cnt].map->l_tls_blocksize; + } + offset = off; + + /* XXX For some architectures we perhaps should store the + negative offset. */ + slotinfo[cnt].map->l_tls_offset = off; + } + + GL(dl_tls_static_used) = offset; + GL(dl_tls_static_size) = (roundup (offset + TLS_STATIC_SURPLUS, max_align) + + TLS_TCB_SIZE); +# elif defined(TLS_DTV_AT_TP) + /* The TLS blocks start right after the TCB. */ + size_t offset = TLS_TCB_SIZE; + size_t cnt; + + for (cnt = 0; slotinfo[cnt].map != NULL; ++cnt) + { + assert (cnt < GL(dl_tls_dtv_slotinfo_list)->len); + + size_t firstbyte = (-slotinfo[cnt].map->l_tls_firstbyte_offset + & (slotinfo[cnt].map->l_tls_align - 1)); + size_t off; + max_align = MAX (max_align, slotinfo[cnt].map->l_tls_align); + + if (slotinfo[cnt].map->l_tls_blocksize <= freetop - freebottom) + { + off = roundup (freebottom, slotinfo[cnt].map->l_tls_align); + if (off - freebottom < firstbyte) + off += slotinfo[cnt].map->l_tls_align; + if (off + slotinfo[cnt].map->l_tls_blocksize - firstbyte <= freetop) + { + slotinfo[cnt].map->l_tls_offset = off - firstbyte; + freebottom = (off + slotinfo[cnt].map->l_tls_blocksize + - firstbyte); + continue; + } + } + + off = roundup (offset, slotinfo[cnt].map->l_tls_align); + if (off - offset < firstbyte) + off += slotinfo[cnt].map->l_tls_align; + + slotinfo[cnt].map->l_tls_offset = off - firstbyte; + if (off - firstbyte - offset > freetop - freebottom) + { + freebottom = offset; + freetop = off - firstbyte; + } + + offset = off + slotinfo[cnt].map->l_tls_blocksize - firstbyte; + } + + GL(dl_tls_static_used) = offset; + GL(dl_tls_static_size) = roundup (offset + TLS_STATIC_SURPLUS, + TLS_TCB_ALIGN); +# else +# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined" +# endif + + /* The alignment requirement for the static TLS block. */ + GL(dl_tls_static_align) = max_align; +} + + +/* This is called only when the data structure setup was skipped at startup, + when there was no need for it then. Now we have dynamically loaded + something needing TLS, or libpthread needs it. */ +int +internal_function +_dl_tls_setup (void) +{ + assert (GL(dl_tls_dtv_slotinfo_list) == NULL); + assert (GL(dl_tls_max_dtv_idx) == 0); + + const size_t nelem = 2 + TLS_SLOTINFO_SURPLUS; + + GL(dl_tls_dtv_slotinfo_list) + = calloc (1, (sizeof (struct dtv_slotinfo_list) + + nelem * sizeof (struct dtv_slotinfo))); + if (GL(dl_tls_dtv_slotinfo_list) == NULL) + return -1; + + GL(dl_tls_dtv_slotinfo_list)->len = nelem; + + /* Number of elements in the static TLS block. It can't be zero + because of various assumptions. The one element is null. */ + GL(dl_tls_static_nelem) = GL(dl_tls_max_dtv_idx) = 1; + + /* This initializes more variables for us. */ + _dl_determine_tlsoffset (); + + return 0; +} +# endif + +static void * +internal_function +allocate_dtv (void *result) +{ + dtv_t *dtv; + size_t dtv_length; + + /* We allocate a few more elements in the dtv than are needed for the + initial set of modules. This should avoid in most cases expansions + of the dtv. */ + dtv_length = GL(dl_tls_max_dtv_idx) + DTV_SURPLUS; + dtv = calloc (dtv_length + 2, sizeof (dtv_t)); + if (dtv != NULL) + { + /* This is the initial length of the dtv. */ + dtv[0].counter = dtv_length; + + /* The rest of the dtv (including the generation counter) is + Initialize with zero to indicate nothing there. */ + + /* Add the dtv to the thread data structures. */ + INSTALL_DTV (result, dtv); + } + else + result = NULL; + + return result; +} + + +/* Get size and alignment requirements of the static TLS block. */ +void +internal_function +_dl_get_tls_static_info (size_t *sizep, size_t *alignp) +{ + *sizep = GL(dl_tls_static_size); + *alignp = GL(dl_tls_static_align); +} + + +void * +internal_function +_dl_allocate_tls_storage (void) +{ + void *result; + size_t size = GL(dl_tls_static_size); + +# if defined(TLS_DTV_AT_TP) + /* Memory layout is: + [ TLS_PRE_TCB_SIZE ] [ TLS_TCB_SIZE ] [ TLS blocks ] + ^ This should be returned. */ + size += (TLS_PRE_TCB_SIZE + GL(dl_tls_static_align) - 1) + & ~(GL(dl_tls_static_align) - 1); +# endif + + /* Allocate a correctly aligned chunk of memory. */ + result = _dl_memalign (GL(dl_tls_static_align), size); + if (__builtin_expect (result != NULL, 1)) + { + /* Allocate the DTV. */ + void *allocated = result; + +# if defined(TLS_TCB_AT_TP) + /* The TCB follows the TLS blocks. */ + result = (char *) result + size - TLS_TCB_SIZE; + + /* Clear the TCB data structure. We can't ask the caller (i.e. + libpthread) to do it, because we will initialize the DTV et al. */ + _dl_memset (result, '\0', TLS_TCB_SIZE); +# elif defined(TLS_DTV_AT_TP) + result = (char *) result + size - GL(dl_tls_static_size); + + /* Clear the TCB data structure and TLS_PRE_TCB_SIZE bytes before it. + We can't ask the caller (i.e. libpthread) to do it, because we will + initialize the DTV et al. */ + _dl_memset ((char *) result - TLS_PRE_TCB_SIZE, '\0', + TLS_PRE_TCB_SIZE + TLS_TCB_SIZE); +# endif + + result = allocate_dtv (result); + if (result == NULL) + free (allocated); + } + + return result; +} + + +void * +internal_function +_dl_allocate_tls_init (void *result) +{ + if (result == NULL) + /* The memory allocation failed. */ + return NULL; + + dtv_t *dtv = GET_DTV (result); + struct dtv_slotinfo_list *listp; + size_t total = 0; + size_t maxgen = 0; + + /* We have to prepare the dtv for all currently loaded modules using + TLS. For those which are dynamically loaded we add the values + indicating deferred allocation. */ + listp = GL(dl_tls_dtv_slotinfo_list); + while (1) + { + size_t cnt; + + for (cnt = total == 0 ? 1 : 0; cnt < listp->len; ++cnt) + { + struct link_map *map; + void *dest; + + /* Check for the total number of used slots. */ + if (total + cnt > GL(dl_tls_max_dtv_idx)) + break; + + map = listp->slotinfo[cnt].map; + if (map == NULL) + /* Unused entry. */ + continue; + + /* Keep track of the maximum generation number. This might + not be the generation counter. */ + maxgen = MAX (maxgen, listp->slotinfo[cnt].gen); + + if (map->l_tls_offset == NO_TLS_OFFSET) + { + /* For dynamically loaded modules we simply store + the value indicating deferred allocation. */ + dtv[map->l_tls_modid].pointer.val = TLS_DTV_UNALLOCATED; + dtv[map->l_tls_modid].pointer.is_static = false; + continue; + } + + assert (map->l_tls_modid == cnt); + assert (map->l_tls_blocksize >= map->l_tls_initimage_size); +# if defined(TLS_TCB_AT_TP) + assert ((size_t) map->l_tls_offset >= map->l_tls_blocksize); + dest = (char *) result - map->l_tls_offset; +# elif defined(TLS_DTV_AT_TP) + dest = (char *) result + map->l_tls_offset; +# else +# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined" +# endif + + /* Copy the initialization image and clear the BSS part. */ + dtv[map->l_tls_modid].pointer.val = dest; + dtv[map->l_tls_modid].pointer.is_static = true; + _dl_memset (_dl_mempcpy (dest, map->l_tls_initimage, + map->l_tls_initimage_size), '\0', + map->l_tls_blocksize - map->l_tls_initimage_size); + } + + total += cnt; + if (total >= GL(dl_tls_max_dtv_idx)) + break; + + listp = listp->next; + assert (listp != NULL); + } + + /* The DTV version is up-to-date now. */ + dtv[0].counter = maxgen; + + return result; +} + +void * +internal_function +_dl_allocate_tls (void *mem) +{ + return _dl_allocate_tls_init (mem == NULL + ? _dl_allocate_tls_storage () + : allocate_dtv (mem)); +} + + +void +internal_function +_dl_deallocate_tls (void *tcb, bool dealloc_tcb) +{ + dtv_t *dtv = GET_DTV (tcb); + size_t cnt; + + /* We need to free the memory allocated for non-static TLS. */ + for (cnt = 0; cnt < dtv[-1].counter; ++cnt) + if (! dtv[1 + cnt].pointer.is_static + && dtv[1 + cnt].pointer.val != TLS_DTV_UNALLOCATED) + free (dtv[1 + cnt].pointer.val); + + /* The array starts with dtv[-1]. */ +#ifdef SHARED + if (dtv != GL(dl_initial_dtv)) +#endif + free (dtv - 1); + + if (dealloc_tcb) + { +# if defined(TLS_TCB_AT_TP) + /* The TCB follows the TLS blocks. Back up to free the whole block. */ + tcb -= GL(dl_tls_static_size) - TLS_TCB_SIZE; +# elif defined(TLS_DTV_AT_TP) + /* Back up the TLS_PRE_TCB_SIZE bytes. */ + tcb -= (TLS_PRE_TCB_SIZE + GL(dl_tls_static_align) - 1) + & ~(GL(dl_tls_static_align) - 1); +# endif + free (tcb); + } +} + + +# ifdef SHARED +/* The __tls_get_addr function has two basic forms which differ in the + arguments. The IA-64 form takes two parameters, the module ID and + offset. The form used, among others, on IA-32 takes a reference to + a special structure which contain the same information. The second + form seems to be more often used (in the moment) so we default to + it. Users of the IA-64 form have to provide adequate definitions + of the following macros. */ +# ifndef GET_ADDR_ARGS +# define GET_ADDR_ARGS tls_index *ti +# endif +# ifndef GET_ADDR_MODULE +# define GET_ADDR_MODULE ti->ti_module +# endif +# ifndef GET_ADDR_OFFSET +# define GET_ADDR_OFFSET ti->ti_offset +# endif + + +static void * +allocate_and_init (struct link_map *map) +{ + void *newp; + + newp = _dl_memalign (map->l_tls_align, map->l_tls_blocksize); + if (newp == NULL) + oom (); + + /* Initialize the memory. */ + _dl_memset (_dl_mempcpy (newp, map->l_tls_initimage, map->l_tls_initimage_size), + '\0', map->l_tls_blocksize - map->l_tls_initimage_size); + + return newp; +} + + +struct link_map * +_dl_update_slotinfo (unsigned long int req_modid) +{ + struct link_map *the_map = NULL; + dtv_t *dtv = THREAD_DTV (); + + /* The global dl_tls_dtv_slotinfo array contains for each module + index the generation counter current when the entry was created. + This array never shrinks so that all module indices which were + valid at some time can be used to access it. Before the first + use of a new module index in this function the array was extended + appropriately. Access also does not have to be guarded against + modifications of the array. It is assumed that pointer-size + values can be read atomically even in SMP environments. It is + possible that other threads at the same time dynamically load + code and therefore add to the slotinfo list. This is a problem + since we must not pick up any information about incomplete work. + The solution to this is to ignore all dtv slots which were + created after the one we are currently interested. We know that + dynamic loading for this module is completed and this is the last + load operation we know finished. */ + unsigned long int idx = req_modid; + struct dtv_slotinfo_list *listp = GL(dl_tls_dtv_slotinfo_list); + + while (idx >= listp->len) + { + idx -= listp->len; + listp = listp->next; + } + + if (dtv[0].counter < listp->slotinfo[idx].gen) + { + /* The generation counter for the slot is higher than what the + current dtv implements. We have to update the whole dtv but + only those entries with a generation counter <= the one for + the entry we need. */ + size_t new_gen = listp->slotinfo[idx].gen; + size_t total = 0; + + /* We have to look through the entire dtv slotinfo list. */ + listp = GL(dl_tls_dtv_slotinfo_list); + do + { + size_t cnt; + + for (cnt = total == 0 ? 1 : 0; cnt < listp->len; ++cnt) + { + size_t gen = listp->slotinfo[cnt].gen; + + if (gen > new_gen) + /* This is a slot for a generation younger than the + one we are handling now. It might be incompletely + set up so ignore it. */ + continue; + + /* If the entry is older than the current dtv layout we + know we don't have to handle it. */ + if (gen <= dtv[0].counter) + continue; + + /* If there is no map this means the entry is empty. */ + struct link_map *map = listp->slotinfo[cnt].map; + if (map == NULL) + { + /* If this modid was used at some point the memory + might still be allocated. */ + if (! dtv[total + cnt].pointer.is_static + && dtv[total + cnt].pointer.val != TLS_DTV_UNALLOCATED) + { + free (dtv[total + cnt].pointer.val); + dtv[total + cnt].pointer.val = TLS_DTV_UNALLOCATED; + } + + continue; + } + + /* Check whether the current dtv array is large enough. */ + size_t modid = map->l_tls_modid; + assert (total + cnt == modid); + if (dtv[-1].counter < modid) + { + /* Reallocate the dtv. */ + dtv_t *newp; + size_t newsize = GL(dl_tls_max_dtv_idx) + DTV_SURPLUS; + size_t oldsize = dtv[-1].counter; + + assert (map->l_tls_modid <= newsize); + + if (dtv == GL(dl_initial_dtv)) + { + /* This is the initial dtv that was allocated + during rtld startup using the dl-minimal.c + malloc instead of the real malloc. We can't + free it, we have to abandon the old storage. */ + + newp = malloc ((2 + newsize) * sizeof (dtv_t)); + if (newp == NULL) + oom (); + _dl_memcpy (newp, &dtv[-1], oldsize * sizeof (dtv_t)); + } + else + { + newp = realloc (&dtv[-1], + (2 + newsize) * sizeof (dtv_t)); + if (newp == NULL) + oom (); + } + + newp[0].counter = newsize; + + /* Clear the newly allocated part. */ + _dl_memset (newp + 2 + oldsize, '\0', + (newsize - oldsize) * sizeof (dtv_t)); + + /* Point dtv to the generation counter. */ + dtv = &newp[1]; + + /* Install this new dtv in the thread data + structures. */ + INSTALL_NEW_DTV (dtv); + } + + /* If there is currently memory allocate for this + dtv entry free it. */ + /* XXX Ideally we will at some point create a memory + pool. */ + if (! dtv[modid].pointer.is_static + && dtv[modid].pointer.val != TLS_DTV_UNALLOCATED) + /* Note that free is called for NULL is well. We + deallocate even if it is this dtv entry we are + supposed to load. The reason is that we call + memalign and not malloc. */ + free (dtv[modid].pointer.val); + + /* This module is loaded dynamically- We defer memory + allocation. */ + dtv[modid].pointer.is_static = false; + dtv[modid].pointer.val = TLS_DTV_UNALLOCATED; + + if (modid == req_modid) + the_map = map; + } + + total += listp->len; + } + while ((listp = listp->next) != NULL); + + /* This will be the new maximum generation counter. */ + dtv[0].counter = new_gen; + } + + return the_map; +} + + +/* The generic dynamic and local dynamic model cannot be used in + statically linked applications. */ +void * +__tls_get_addr (GET_ADDR_ARGS) +{ + dtv_t *dtv = THREAD_DTV (); + struct link_map *the_map = NULL; + void *p; + + if (__builtin_expect (dtv[0].counter != GL(dl_tls_generation), 0)) + the_map = _dl_update_slotinfo (GET_ADDR_MODULE); + + p = dtv[GET_ADDR_MODULE].pointer.val; + + if (__builtin_expect (p == TLS_DTV_UNALLOCATED, 0)) + { + /* The allocation was deferred. Do it now. */ + if (the_map == NULL) + { + /* Find the link map for this module. */ + size_t idx = GET_ADDR_MODULE; + struct dtv_slotinfo_list *listp = GL(dl_tls_dtv_slotinfo_list); + + while (idx >= listp->len) + { + idx -= listp->len; + listp = listp->next; + } + + the_map = listp->slotinfo[idx].map; + } + + p = dtv[GET_ADDR_MODULE].pointer.val = allocate_and_init (the_map); + dtv[GET_ADDR_MODULE].pointer.is_static = false; + } + + return (char *) p + GET_ADDR_OFFSET; +} +# endif + + + +void +_dl_add_to_slotinfo (struct link_map *l) +{ + /* Now that we know the object is loaded successfully add + modules containing TLS data to the dtv info table. We + might have to increase its size. */ + struct dtv_slotinfo_list *listp; + struct dtv_slotinfo_list *prevp; + size_t idx = l->l_tls_modid; + + /* Find the place in the dtv slotinfo list. */ + listp = GL(dl_tls_dtv_slotinfo_list); + prevp = NULL; /* Needed to shut up gcc. */ + do + { + /* Does it fit in the array of this list element? */ + if (idx < listp->len) + break; + idx -= listp->len; + prevp = listp; + listp = listp->next; + } + while (listp != NULL); + + if (listp == NULL) + { + /* When we come here it means we have to add a new element + to the slotinfo list. And the new module must be in + the first slot. */ + assert (idx == 0); + + listp = prevp->next = (struct dtv_slotinfo_list *) + malloc (sizeof (struct dtv_slotinfo_list) + + TLS_SLOTINFO_SURPLUS * sizeof (struct dtv_slotinfo)); + if (listp == NULL) + { + /* We ran out of memory. We will simply fail this + call but don't undo anything we did so far. The + application will crash or be terminated anyway very + soon. */ + + /* We have to do this since some entries in the dtv + slotinfo array might already point to this + generation. */ + ++GL(dl_tls_generation); + + _dl_dprintf (_dl_debug_file, + "cannot create TLS data structures: ABORT\n"); + _dl_exit (127); + } + + listp->len = TLS_SLOTINFO_SURPLUS; + listp->next = NULL; + _dl_memset (listp->slotinfo, '\0', + TLS_SLOTINFO_SURPLUS * sizeof (struct dtv_slotinfo)); + } + + /* Add the information into the slotinfo data structure. */ + listp->slotinfo[idx].map = l; + listp->slotinfo[idx].gen = GL(dl_tls_generation) + 1; +} diff --git a/l4/pkg/uclibc/lib/libpthread/src/sysdeps/generic/dl-tls.h b/l4/pkg/uclibc/lib/libpthread/src/sysdeps/generic/dl-tls.h new file mode 100644 index 00000000..7703a975 --- /dev/null +++ b/l4/pkg/uclibc/lib/libpthread/src/sysdeps/generic/dl-tls.h @@ -0,0 +1,2 @@ +/* There has to be an architecture specific version of this file. */ +#error "architecture-specific version of missing" diff --git a/l4/pkg/uclibc/lib/libpthread/src/sysdeps/generic/libc-tls.cc b/l4/pkg/uclibc/lib/libpthread/src/sysdeps/generic/libc-tls.cc new file mode 100644 index 00000000..02594c04 --- /dev/null +++ b/l4/pkg/uclibc/lib/libpthread/src/sysdeps/generic/libc-tls.cc @@ -0,0 +1,289 @@ +/* Initialization code for TLS in statically linked application. + Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#ifdef SHARED + #error makefile bug, this file is for static only +#endif + +#if USE_TLS +extern ElfW(Phdr) *_dl_phdr; +extern size_t _dl_phnum; + +extern "C" +__attribute__ ((weak)) +void *__libc_alloc_initial_tls(unsigned long size) __THROW; + +static dtv_t static_dtv[2 + TLS_SLOTINFO_SURPLUS]; + + +static struct +{ + struct dtv_slotinfo_list si; + /* The dtv_slotinfo_list data structure does not include the actual + information since it is defined as an array of size zero. We define + here the necessary entries. Note that it is not important whether + there is padding or not since we will always access the information + through the 'si' element. */ + dtv_slotinfo_list::dtv_slotinfo info[2 + TLS_SLOTINFO_SURPLUS]; +} static_slotinfo; + +/* Fake link map for the application. */ +static struct link_map static_map; + + +/* Highest dtv index currently needed. */ +size_t _dl_tls_max_dtv_idx; +/* Flag signalling whether there are gaps in the module ID allocation. */ +bool _dl_tls_dtv_gaps; +/* Information about the dtv slots. */ +struct dtv_slotinfo_list *_dl_tls_dtv_slotinfo_list; +/* Number of modules in the static TLS block. */ +size_t _dl_tls_static_nelem; +/* Size of the static TLS block. */ +size_t _dl_tls_static_size __attribute__((weak)) = TLS_TCB_SIZE; +/* Size actually allocated in the static TLS block. */ +size_t _dl_tls_static_used; +/* Alignment requirement of the static TLS block. */ +size_t _dl_tls_static_align; + +/* Generation counter for the dtv. */ +size_t _dl_tls_generation; + + +/* Additional definitions needed by TLS initialization. */ +#ifdef TLS_INIT_HELPER +TLS_INIT_HELPER +#endif + +static inline void +init_slotinfo (void) +{ + /* Create the slotinfo list. */ + static_slotinfo.si.len = (((char *) (&static_slotinfo + 1) + - (char *) &static_slotinfo.si.slotinfo[0]) + / sizeof static_slotinfo.si.slotinfo[0]); + // static_slotinfo.si.next = NULL; already zero + + /* The slotinfo list. Will be extended by the code doing dynamic + linking. */ + GL(dl_tls_max_dtv_idx) = 1; + GL(dl_tls_dtv_slotinfo_list) = &static_slotinfo.si; +} + +static inline void +init_static_tls (size_t memsz, size_t align) +{ + /* That is the size of the TLS memory for this object. The initialized + value of _dl_tls_static_size is provided by dl-open.c to request some + surplus that permits dynamic loading of modules with IE-model TLS. */ + GL(dl_tls_static_size) = roundup (memsz + GL(dl_tls_static_size), + TLS_TCB_ALIGN); + GL(dl_tls_static_used) = memsz; + /* The alignment requirement for the static TLS block. */ + GL(dl_tls_static_align) = align; + /* Number of elements in the static TLS block. */ + GL(dl_tls_static_nelem) = GL(dl_tls_max_dtv_idx); +} + +__attribute__ ((weak)) +void *__libc_alloc_initial_tls(unsigned long size) __THROW +{ + using namespace L4; + using namespace L4Re; + Cap ds(Env::env()->first_free_cap() << L4_CAP_SHIFT); + ::l4re_global_env->first_free_cap += 1; + if (Env::env()->mem_alloc()->alloc(size, ds, 0) < 0) + return NULL; + + void *addr = NULL; + if(Env::env()->rm()->attach(&addr, size, Rm::Search_addr, ds, 0, 0) < 0) + return NULL; + + return addr; +} +extern "C" +void +__libc_setup_tls (size_t tcbsize, size_t tcbalign) +{ + void *tlsblock; + size_t memsz = 0; + size_t filesz = 0; + void *initimage = NULL; + size_t align = 0; + size_t max_align = tcbalign; + size_t tcb_offset; + ElfW(Phdr) *phdr; + /* Look through the TLS segment if there is any. */ + if (_dl_phdr != NULL) + for (phdr = _dl_phdr; phdr < &_dl_phdr[_dl_phnum]; ++phdr) + if (phdr->p_type == PT_TLS) + { + /* Remember the values we need. */ + memsz = phdr->p_memsz; + filesz = phdr->p_filesz; + initimage = (void *) phdr->p_vaddr; + align = phdr->p_align; + if (phdr->p_align > max_align) + max_align = phdr->p_align; + break; + } + /* We have to set up the TCB block which also (possibly) contains + 'errno'. Therefore we avoid 'malloc' which might touch 'errno'. + Instead we use 'sbrk' which would only uses 'errno' if it fails. + In this case we are right away out of memory and the user gets + what she/he deserves. + + The initialized value of _dl_tls_static_size is provided by dl-open.c + to request some surplus that permits dynamic loading of modules with + IE-model TLS. */ +# if defined(TLS_TCB_AT_TP) + tcb_offset = roundup (memsz + GL(dl_tls_static_size), tcbalign); + tlsblock = __libc_alloc_initial_tls(tcb_offset + tcbsize + max_align); +# elif defined(TLS_DTV_AT_TP) + tcb_offset = roundup (tcbsize, align ?: 1); + tlsblock = __libc_alloc_initial_tls(tcb_offset + memsz + max_align + + TLS_PRE_TCB_SIZE + GL(dl_tls_static_size)); + //tlsblock += TLS_PRE_TCB_SIZE; + tlsblock = (char *)tlsblock + TLS_PRE_TCB_SIZE; +# else + /* In case a model with a different layout for the TCB and DTV + is defined add another #elif here and in the following #ifs. */ +# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined" +# endif + + /* Align the TLS block. */ + tlsblock = (void *) (((uintptr_t) tlsblock + max_align - 1) + & ~(max_align - 1)); + + /* Initialize the dtv. [0] is the length, [1] the generation counter. */ + static_dtv[0].counter = (sizeof (static_dtv) / sizeof (static_dtv[0])) - 2; + // static_dtv[1].counter = 0; would be needed if not already done + + /* Initialize the TLS block. */ +# if defined(TLS_TCB_AT_TP) + static_dtv[2].pointer.val = ((char *) tlsblock + tcb_offset + - roundup (memsz, align ?: 1)); + static_map.l_tls_offset = roundup (memsz, align ?: 1); +# elif defined(TLS_DTV_AT_TP) + static_dtv[2].pointer.val = (char *) tlsblock + tcb_offset; + static_map.l_tls_offset = tcb_offset; +# else +# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined" +# endif + static_dtv[2].pointer.is_static = true; + /* sbrk gives us zero'd memory, so we don't need to clear the remainder. */ + memcpy (static_dtv[2].pointer.val, initimage, filesz); + + /* Install the pointer to the dtv. */ + + /* Initialize the thread pointer. */ +# if defined(TLS_TCB_AT_TP) + INSTALL_DTV ((char *) tlsblock + tcb_offset, static_dtv); + const char *lossage = TLS_INIT_TP ((char *) tlsblock + tcb_offset, 0); +# elif defined(TLS_DTV_AT_TP) + INSTALL_DTV (tlsblock, static_dtv); + const char *lossage = (char *)TLS_INIT_TP (tlsblock, 0); +# else +# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined" +# endif + if (__builtin_expect (lossage != NULL, 0)) + abort(); + + /* We have to create a fake link map which normally would be created + by the dynamic linker. It just has to have enough information to + make the TLS routines happy. */ + static_map.l_tls_align = align; + static_map.l_tls_blocksize = memsz; + static_map.l_tls_initimage = initimage; + static_map.l_tls_initimage_size = filesz; + static_map.l_tls_modid = 1; + + init_slotinfo (); + // static_slotinfo.si.slotinfo[1].gen = 0; already zero + static_slotinfo.si.slotinfo[1].map = &static_map; + + memsz = roundup (memsz, align ?: 1); + +# if defined(TLS_TCB_AT_TP) + memsz += tcbsize; +# elif defined(TLS_DTV_AT_TP) + memsz += tcb_offset; +# endif + + init_static_tls (memsz, MAX (TLS_TCB_ALIGN, max_align)); +} + +/* This is called only when the data structure setup was skipped at startup, + when there was no need for it then. Now we have dynamically loaded + something needing TLS, or libpthread needs it. */ +int +internal_function +_dl_tls_setup (void) +{ + init_slotinfo (); + init_static_tls ( +# if defined(TLS_TCB_AT_TP) + TLS_TCB_SIZE, +# else + 0, +# endif + TLS_TCB_ALIGN); + return 0; +} + + +/* This is the minimal initialization function used when libpthread is + not used. */ +extern "C" +void +__attribute__ ((weak)) +__pthread_initialize_minimal (void) +{ + __libc_setup_tls (TLS_INIT_TCB_SIZE, TLS_INIT_TCB_ALIGN); +} + +#elif defined NONTLS_INIT_TP + +/* This is the minimal initialization function used when libpthread is + not used. */ +extern "C" +void +__attribute__ ((weak)) +__pthread_initialize_minimal (void) +{ + NONTLS_INIT_TP; +} + +#endif diff --git a/l4/pkg/uclibc/lib/libpthread/src/sysdeps/i386/dl-tls.h b/l4/pkg/uclibc/lib/libpthread/src/sysdeps/i386/dl-tls.h new file mode 100644 index 00000000..e94f9654 --- /dev/null +++ b/l4/pkg/uclibc/lib/libpthread/src/sysdeps/i386/dl-tls.h @@ -0,0 +1,62 @@ +/* Thread-local storage handling in the ELF dynamic linker. i386 version. + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + + +/* Type used for the representation of TLS information in the GOT. */ +typedef struct +{ + unsigned long int ti_module; + unsigned long int ti_offset; +} tls_index; + + +extern void *__tls_get_addr (tls_index *ti); + +#ifdef SHARED +/* This is the prototype for the GNU version. */ +extern void *___tls_get_addr (tls_index *ti) + __attribute__ ((__regparm__ (1))); +extern void *___tls_get_addr_internal (tls_index *ti) + __attribute__ ((__regparm__ (1))) attribute_hidden; + +# ifdef IS_IN_rtld +/* The special thing about the x86 TLS ABI is that we have two + variants of the __tls_get_addr function with different calling + conventions. The GNU version, which we are mostly concerned here, + takes the parameter in a register. The name is changed by adding + an additional underscore at the beginning. The Sun version uses + the normal calling convention. */ +void * +__tls_get_addr (tls_index *ti) +{ + return ___tls_get_addr_internal (ti); +} + + +/* Prepare using the definition of __tls_get_addr in the generic + version of this file. */ +# define __tls_get_addr __attribute__ ((__regparm__ (1))) ___tls_get_addr +strong_alias (___tls_get_addr, ___tls_get_addr_internal) +#else + +/* Users should get the better interface. */ +# define __tls_get_addr ___tls_get_addr + +# endif +#endif diff --git a/l4/pkg/uclibc/lib/libpthread/src/sysdeps/i386/i686/pt-machine.h b/l4/pkg/uclibc/lib/libpthread/src/sysdeps/i386/i686/pt-machine.h new file mode 100644 index 00000000..28e0bcc3 --- /dev/null +++ b/l4/pkg/uclibc/lib/libpthread/src/sysdeps/i386/i686/pt-machine.h @@ -0,0 +1,79 @@ +/* Machine-dependent pthreads configuration and inline functions. + i686 version. + Copyright (C) 1996-2001, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _PT_MACHINE_H +#define _PT_MACHINE_H 1 + +#ifndef PT_EI +# define PT_EI __extern_always_inline +#endif +//l4/#include + +#ifndef __ASSEMBLER__ +extern long int testandset (int *spinlock); +extern int __compare_and_swap (long int *p, long int oldval, long int newval); + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#define CURRENT_STACK_FRAME __builtin_frame_address (0) + + +/* Spinlock implementation; required. */ +PT_EI long int +testandset (int *spinlock) +{ + long int ret; + + __asm__ __volatile__ ( + "xchgl %0, %1" + : "=r" (ret), "=m" (*spinlock) + : "0" (1), "m" (*spinlock) + : "memory"); + + return ret; +} + + +/* Compare-and-swap for semaphores. It's always available on i686. */ +#define HAS_COMPARE_AND_SWAP + +PT_EI int +__compare_and_swap (long int *p, long int oldval, long int newval) +{ + char ret; + long int readval; + + __asm__ __volatile__ ("lock; cmpxchgl %3, %1; sete %0" + : "=q" (ret), "=m" (*p), "=a" (readval) + : "r" (newval), "m" (*p), "a" (oldval) + : "memory"); + return ret; +} +#endif + +#if __ASSUME_LDT_WORKS > 0 +#include "../useldt.h" +#endif + +/* The P4 and above really want some help to prevent overheating. */ +#define BUSY_WAIT_NOP __asm__ ("rep; nop") + +#endif /* pt-machine.h */ diff --git a/l4/pkg/uclibc/lib/libpthread/src/sysdeps/i386/i686/tls.h b/l4/pkg/uclibc/lib/libpthread/src/sysdeps/i386/i686/tls.h new file mode 100644 index 00000000..928d269d --- /dev/null +++ b/l4/pkg/uclibc/lib/libpthread/src/sysdeps/i386/i686/tls.h @@ -0,0 +1,36 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _TLS_H + +/* Additional definitions for on i686 and up. */ + + +/* Macros to load from and store into segment registers. We can use + the 32-bit instructions. */ +#define TLS_GET_GS() \ + ({ int __seg; __asm__ ("movl %%gs, %0" : "=q" (__seg)); __seg; }) +#define TLS_SET_GS(val) \ + __asm__ ("movl %0, %%gs" :: "q" (val)) + + +/* Get the full set of definitions. */ +#include "../tls.h" + +#endif /* tls.h */ diff --git a/l4/pkg/uclibc/lib/libpthread/src/sysdeps/i386/pt-machine.h b/l4/pkg/uclibc/lib/libpthread/src/sysdeps/i386/pt-machine.h new file mode 100644 index 00000000..0a12b2b8 --- /dev/null +++ b/l4/pkg/uclibc/lib/libpthread/src/sysdeps/i386/pt-machine.h @@ -0,0 +1,119 @@ +/* Machine-dependent pthreads configuration and inline functions. + i386 version. + Copyright (C) 1996-2001, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#if defined __pentiumpro__ || defined __pentium4__ || defined __athlon__ || \ + defined __k8__ +# include "i686/pt-machine.h" +#else + +#ifndef _PT_MACHINE_H +#define _PT_MACHINE_H 1 + +#ifndef __ASSEMBLER__ +#ifndef PT_EI +# define PT_EI __extern_always_inline +#endif + +#ifdef not_for_l4 +extern long int testandset (int *spinlock); +extern int __compare_and_swap (long int *p, long int oldval, long int newval); +#endif +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#define CURRENT_STACK_FRAME __builtin_frame_address (0) + + +/* Spinlock implementation; required. */ +PT_EI long int +testandset (int *spinlock) +{ + long int ret; + + __asm__ __volatile__( + "xchgl %0, %1" + : "=r"(ret), "=m"(*spinlock) + : "0"(1), "m"(*spinlock) + : "memory"); + + return ret; +} + + +/* Compare-and-swap for semaphores. + Available on the 486 and above, but not on the 386. + We test dynamically whether it's available or not. */ + +#define HAS_COMPARE_AND_SWAP +#define TEST_FOR_COMPARE_AND_SWAP + +PT_EI int +__compare_and_swap (long int *p, long int oldval, long int newval) +{ + char ret; + long int readval; + + __asm__ __volatile__ ("lock; cmpxchgl %3, %1; sete %0" + : "=q" (ret), "=m" (*p), "=a" (readval) + : "r" (newval), "m" (*p), "a" (oldval) + : "memory"); + return ret; +} + + +PT_EI int get_eflags (void); +PT_EI int +get_eflags (void) +{ + int res; + __asm__ __volatile__ ("pushfl; popl %0" : "=r" (res) : ); + return res; +} + + +PT_EI void set_eflags (int newflags); +PT_EI void +set_eflags (int newflags) +{ + __asm__ __volatile__ ("pushl %0; popfl" : : "r" (newflags) : "cc"); +} + + +PT_EI int compare_and_swap_is_available (void); +PT_EI int +compare_and_swap_is_available (void) +{ + int oldflags = get_eflags (); + int changed; + /* Flip AC bit in EFLAGS. */ + set_eflags (oldflags ^ 0x40000); + /* See if bit changed. */ + changed = (get_eflags () ^ oldflags) & 0x40000; + /* Restore EFLAGS. */ + set_eflags (oldflags); + /* If the AC flag did not change, it's a 386 and it lacks cmpxchg. + Otherwise, it's a 486 or above and it has cmpxchg. */ + return changed != 0; +} +#endif /* __ASSEMBLER__ */ + +#endif /* pt-machine.h */ + +#endif diff --git a/l4/pkg/uclibc/lib/libpthread/src/sysdeps/i386/sysdep-cancel.h b/l4/pkg/uclibc/lib/libpthread/src/sysdeps/i386/sysdep-cancel.h new file mode 100644 index 00000000..22bf5833 --- /dev/null +++ b/l4/pkg/uclibc/lib/libpthread/src/sysdeps/i386/sysdep-cancel.h @@ -0,0 +1,187 @@ +/* Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#ifndef __ASSEMBLER__ +# include "internals.h" +#endif + +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + +# undef PSEUDO +# define PSEUDO(name, syscall_name, args) \ + .text; \ + ENTRY (name) \ + SINGLE_THREAD_P; \ + jne L(pseudo_cancel); \ + DO_CALL (syscall_name, args); \ + cmpl $-4095, %eax; \ + jae SYSCALL_ERROR_LABEL; \ + ret; \ + L(pseudo_cancel): \ + CENABLE \ + SAVE_OLDTYPE_##args \ + PUSHCARGS_##args \ + DOCARGS_##args \ + movl $SYS_ify (syscall_name), %eax; \ + int $0x80 \ + POPCARGS_##args; \ + POPSTATE_##args \ + cmpl $-4095, %eax; \ + jae SYSCALL_ERROR_LABEL; \ + L(pseudo_end): + +# define SAVE_OLDTYPE_0 movl %eax, %ecx; +# define SAVE_OLDTYPE_1 SAVE_OLDTYPE_0 +# define SAVE_OLDTYPE_2 pushl %eax; cfi_adjust_cfa_offset (4); +# define SAVE_OLDTYPE_3 SAVE_OLDTYPE_2 +# define SAVE_OLDTYPE_4 SAVE_OLDTYPE_2 +# define SAVE_OLDTYPE_5 SAVE_OLDTYPE_2 + +# define PUSHCARGS_0 /* No arguments to push. */ +# define DOCARGS_0 /* No arguments to frob. */ +# define POPCARGS_0 /* No arguments to pop. */ +# define _PUSHCARGS_0 /* No arguments to push. */ +# define _POPCARGS_0 /* No arguments to pop. */ + +# define PUSHCARGS_1 movl %ebx, %edx; cfi_register (ebx, edx); PUSHCARGS_0 +# define DOCARGS_1 _DOARGS_1 (4) +# define POPCARGS_1 POPCARGS_0; movl %edx, %ebx; cfi_restore (ebx); +# define _PUSHCARGS_1 pushl %ebx; cfi_adjust_cfa_offset (4); \ + cfi_rel_offset (ebx, 0); _PUSHCARGS_0 +# define _POPCARGS_1 _POPCARGS_0; popl %ebx; \ + cfi_adjust_cfa_offset (-4); cfi_restore (ebx); + +# define PUSHCARGS_2 PUSHCARGS_1 +# define DOCARGS_2 _DOARGS_2 (12) +# define POPCARGS_2 POPCARGS_1 +# define _PUSHCARGS_2 _PUSHCARGS_1 +# define _POPCARGS_2 _POPCARGS_1 + +# define PUSHCARGS_3 _PUSHCARGS_2 +# define DOCARGS_3 _DOARGS_3 (20) +# define POPCARGS_3 _POPCARGS_3 +# define _PUSHCARGS_3 _PUSHCARGS_2 +# define _POPCARGS_3 _POPCARGS_2 + +# define PUSHCARGS_4 _PUSHCARGS_4 +# define DOCARGS_4 _DOARGS_4 (28) +# define POPCARGS_4 _POPCARGS_4 +# define _PUSHCARGS_4 pushl %esi; cfi_adjust_cfa_offset (4); \ + cfi_rel_offset (esi, 0); _PUSHCARGS_3 +# define _POPCARGS_4 _POPCARGS_3; popl %esi; \ + cfi_adjust_cfa_offset (-4); cfi_restore (esi); + +# define PUSHCARGS_5 _PUSHCARGS_5 +# define DOCARGS_5 _DOARGS_5 (36) +# define POPCARGS_5 _POPCARGS_5 +# define _PUSHCARGS_5 pushl %edi; cfi_adjust_cfa_offset (4); \ + cfi_rel_offset (edi, 0); _PUSHCARGS_4 +# define _POPCARGS_5 _POPCARGS_4; popl %edi; \ + cfi_adjust_cfa_offset (-4); cfi_restore (edi); + +# ifdef IS_IN_libpthread +# define CENABLE call __pthread_enable_asynccancel; +# define CDISABLE call __pthread_disable_asynccancel +# elif defined IS_IN_librt +# ifdef __PIC__ +# define CENABLE pushl %ebx; \ + call __i686.get_pc_thunk.bx; \ + addl $_GLOBAL_OFFSET_TABLE_, %ebx; \ + call __librt_enable_asynccancel@PLT; \ + popl %ebx; +# define CDISABLE pushl %ebx; \ + call __i686.get_pc_thunk.bx; \ + addl $_GLOBAL_OFFSET_TABLE_, %ebx; \ + call __librt_disable_asynccancel@PLT; \ + popl %ebx; +# else +# define CENABLE call __librt_enable_asynccancel; +# define CDISABLE call __librt_disable_asynccancel +# endif +# else +# define CENABLE call __libc_enable_asynccancel; +# define CDISABLE call __libc_disable_asynccancel +# endif +# define POPSTATE_0 \ + pushl %eax; cfi_adjust_cfa_offset (4); movl %ecx, %eax; \ + CDISABLE; popl %eax; cfi_adjust_cfa_offset (-4); +# define POPSTATE_1 POPSTATE_0 +# define POPSTATE_2 xchgl (%esp), %eax; CDISABLE; popl %eax; \ + cfi_adjust_cfa_offset (-4); +# define POPSTATE_3 POPSTATE_2 +# define POPSTATE_4 POPSTATE_3 +# define POPSTATE_5 POPSTATE_4 + +#if !defined NOT_IN_libc +# define __local_multiple_threads __libc_multiple_threads +#elif defined IS_IN_libpthread +# define __local_multiple_threads __pthread_multiple_threads +#else +# define __local_multiple_threads __librt_multiple_threads +#endif + +# ifndef __ASSEMBLER__ +# if defined FLOATING_STACKS && USE___THREAD && defined __PIC__ +# define SINGLE_THREAD_P \ + __builtin_expect (THREAD_GETMEM (THREAD_SELF, \ + p_header.data.multiple_threads) == 0, 1) +# else +extern int __local_multiple_threads +# if !defined NOT_IN_libc || defined IS_IN_libpthread + attribute_hidden; +# else + ; +# endif +# define SINGLE_THREAD_P __builtin_expect (__local_multiple_threads == 0, 1) +# endif +# else +# if !defined __PIC__ +# define SINGLE_THREAD_P cmpl $0, __local_multiple_threads +# elif defined FLOATING_STACKS && USE___THREAD +# define SINGLE_THREAD_P cmpl $0, %gs:MULTIPLE_THREADS_OFFSET +# else +# if !defined NOT_IN_libc || defined IS_IN_libpthread +# define __SINGLE_THREAD_CMP cmpl $0, __local_multiple_threads@GOTOFF(%ecx) +# else +# define __SINGLE_THREAD_CMP \ + movl __local_multiple_threads@GOT(%ecx), %ecx;\ + cmpl $0, (%ecx) +# endif +# if !defined HAVE_HIDDEN || !USE___THREAD +# define SINGLE_THREAD_P \ + SETUP_PIC_REG (cx); \ + addl $_GLOBAL_OFFSET_TABLE_, %ecx; \ + __SINGLE_THREAD_CMP +# else +# define SINGLE_THREAD_P \ + call __i686.get_pc_thunk.cx; \ + addl $_GLOBAL_OFFSET_TABLE_, %ecx; \ + __SINGLE_THREAD_CMP +# endif +# endif +# endif + +#elif !defined __ASSEMBLER__ + +/* This code should never be used but we define it anyhow. */ +# define SINGLE_THREAD_P (1) + +#endif diff --git a/l4/pkg/uclibc/lib/libpthread/src/sysdeps/i386/tls.h b/l4/pkg/uclibc/lib/libpthread/src/sysdeps/i386/tls.h new file mode 100644 index 00000000..761fad48 --- /dev/null +++ b/l4/pkg/uclibc/lib/libpthread/src/sysdeps/i386/tls.h @@ -0,0 +1,507 @@ +/* Definition for thread-local data handling. nptl/i386 version. + Copyright (C) 2002-2007, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _TLS_H +#define _TLS_H 1 + +#ifndef __ASSEMBLER__ +# include +# include +# include +# include +//# include +# include + + +/* Type for the dtv. */ +typedef union dtv +{ + size_t counter; + struct + { + void *val; + bool is_static; + } pointer; +} dtv_t; + + +typedef struct +{ + void *tcb; /* Pointer to the TCB. Not necessarily the + thread descriptor used by libpthread. */ + dtv_t *dtv; + void *self; /* Pointer to the thread descriptor. */ + int multiple_threads; + uintptr_t sysinfo; + uintptr_t stack_guard; + uintptr_t pointer_guard; + int gscope_flag; +#ifndef __ASSUME_PRIVATE_FUTEX + int private_futex; +#else + int __unused1; +#endif + /* Reservation of some values for the TM ABI. */ + void *__private_tm[5]; +} tcbhead_t; + +# define TLS_MULTIPLE_THREADS_IN_TCB 1 + +#else /* __ASSEMBLER__ */ +# include +#endif + + +/* We require TLS support in the tools. */ +#define HAVE_TLS_SUPPORT +#define HAVE___THREAD 1 +#define HAVE_TLS_MODEL_ATTRIBUTE 1 + +/* Signal that TLS support is available. */ +#define USE_TLS 1 + + +/* Alignment requirement for the stack. For IA-32 this is governed by + the SSE memory functions. */ +#define STACK_ALIGN 16 + +#ifndef __ASSEMBLER__ +/* Get system call information. */ +//# include + +/* The old way: using LDT. */ + +struct x86_descr { + union { + struct { + unsigned int a; + unsigned int b; + }; + struct { + uint16_t limit0; + uint16_t base0; + unsigned base1: 8, type: 4, s: 1, dpl: 2, p: 1; + unsigned limit: 4, avl: 1, l: 1, d: 1, g: 1, base2: 8; + }; + }; +} __attribute__((packed)); + + + +/* Get the thread descriptor definition. */ +# include +# include +# include + +/* This is the size of the initial TCB. Can't be just sizeof (tcbhead_t), + because NPTL getpid, __libc_alloca_cutoff etc. need (almost) the whole + struct pthread even when not linked with -lpthread. */ +# define TLS_INIT_TCB_SIZE sizeof (struct _pthread_descr_struct) + +/* Alignment requirements for the initial TCB. */ +# define TLS_INIT_TCB_ALIGN __alignof__ (struct _pthread_descr_struct) + +/* This is the size of the TCB. */ +# define TLS_TCB_SIZE sizeof (struct _pthread_descr_struct) + +/* Alignment requirements for the TCB. */ +# define TLS_TCB_ALIGN __alignof__ (struct _pthread_descr_struct) + +/* The TCB can have any size and the memory following the address the + thread pointer points to is unspecified. Allocate the TCB there. */ +# define TLS_TCB_AT_TP 1 + + +/* Install the dtv pointer. The pointer passed is to the element with + index -1 which contain the length. */ +# define INSTALL_DTV(descr, dtvp) \ + ((tcbhead_t *) (descr))->dtv = (dtvp) + 1 + +/* Install new dtv for current thread. */ +# define INSTALL_NEW_DTV(dtvpx) \ + ({ struct _pthread_descr_struct *__pd; \ + THREAD_SETMEM (__pd, p_header.data.dtvp, (dtvpx)); }) + +/* Return dtv of given thread descriptor. */ +# define GET_DTV(descr) \ + (((tcbhead_t *) (descr))->dtv) + +#define THREAD_SELF_SYSINFO THREAD_GETMEM (THREAD_SELF, header.sysinfo) +#define THREAD_SYSINFO(pd) ((pd)->header.sysinfo) + +/* Macros to load from and store into segment registers. */ +# ifndef TLS_GET_GS +# define TLS_GET_GS() \ + ({ int __seg; __asm__ ("movw %%gs, %w0" : "=q" (__seg)); __seg & 0xffff; }) +# endif +# ifndef TLS_SET_GS +# define TLS_SET_GS(val) \ + __asm__ ("movw %w0, %%gs" :: "q" (val)) +# endif + + +# ifndef __NR_set_thread_area +# define __NR_set_thread_area 243 +# endif +# ifndef TLS_FLAG_WRITABLE +# define TLS_FLAG_WRITABLE 0x00000001 +# endif + +// XXX Enable for the real world. +#if 0 +# ifndef __ASSUME_SET_THREAD_AREA +# error "we need set_thread_area" +# endif +#endif + +# ifdef __PIC__ +# define TLS_EBX_ARG "r" +# define TLS_LOAD_EBX "xchgl %3, %%ebx\n\t" +# else +# define TLS_EBX_ARG "b" +# define TLS_LOAD_EBX +# endif + +#if defined NEED_DL_SYSINFO +# define INIT_SYSINFO \ + _head->sysinfo = GLRO(dl_sysinfo) +#else +# define INIT_SYSINFO +#endif + +#ifndef LOCK_PREFIX +# ifdef UP +# define LOCK_PREFIX /* nothing */ +# else +# define LOCK_PREFIX "lock;" +# endif +#endif + +static inline char const *TLS_INIT_TP(void *thrdescr, int secondcall) +{ + (void)secondcall; + tcbhead_t *_head = (tcbhead_t *)thrdescr; + struct x86_descr segdesc; + long seg; + + _head->tcb = thrdescr; + _head->self = thrdescr; + INIT_SYSINFO; + segdesc.limit0 = 0xffff; + segdesc.base0 = ((unsigned long)thrdescr) & 0x0ffff; + segdesc.base1 = (((unsigned long)thrdescr) & 0x0ff0000) >> 16; + segdesc.type = 2; + segdesc.s = 1; + segdesc.dpl = 3; + segdesc.p = 1; + segdesc.limit = 0xf; + segdesc.avl = 1; + segdesc.d = 1; // 32bit + segdesc.g = 1; // pages + segdesc.base2 = (((unsigned long)thrdescr) & 0xff000000) >> 24; + segdesc.l = 0; + seg = fiasco_gdt_set(L4_INVALID_CAP, &segdesc, 8, 0, l4_utcb()); + if (seg < 0) + return "ERROR"; + + TLS_SET_GS(seg); + + return NULL; +} +#if 0 +/* Code to initially initialize the thread pointer. This might need + special attention since 'errno' is not yet available and if the + operation can cause a failure 'errno' must not be touched. */ +# define TLS_INIT_TP(thrdescr, secondcall) \ + ({ void *_thrdescr = (thrdescr); \ + tcbhead_t *_head = _thrdescr; \ + union user_desc_init _segdescr; \ + int _result; \ + \ + _head->tcb = _thrdescr; \ + /* For now the thread descriptor is at the same address. */ \ + _head->self = _thrdescr; \ + /* New syscall handling support. */ \ + INIT_SYSINFO; \ + \ + /* The 'entry_number' field. Let the kernel pick a value. */ \ + if (secondcall) \ + _segdescr.vals[0] = TLS_GET_GS () >> 3; \ + else \ + _segdescr.vals[0] = -1; \ + /* The 'base_addr' field. Pointer to the TCB. */ \ + _segdescr.vals[1] = (unsigned long int) _thrdescr; \ + /* The 'limit' field. We use 4GB which is 0xfffff pages. */ \ + _segdescr.vals[2] = 0xfffff; \ + /* Collapsed value of the bitfield: \ + .seg_32bit = 1 \ + .contents = 0 \ + .read_exec_only = 0 \ + .limit_in_pages = 1 \ + .seg_not_present = 0 \ + .useable = 1 */ \ + _segdescr.vals[3] = 0x51; \ + \ + /* Install the TLS. */ \ + __asm__ __volatile__ (TLS_LOAD_EBX \ + "int $0x80\n\t" \ + TLS_LOAD_EBX \ + : "=a" (_result), "=m" (_segdescr.desc.entry_number) \ + : "0" (__NR_set_thread_area), \ + TLS_EBX_ARG (&_segdescr.desc), "m" (_segdescr.desc)); \ + \ + if (_result == 0) \ + /* We know the index in the GDT, now load the segment register. \ + The use of the GDT is described by the value 3 in the lower \ + three bits of the segment descriptor value. \ + \ + Note that we have to do this even if the numeric value of \ + the descriptor does not change. Loading the segment register \ + causes the segment information from the GDT to be loaded \ + which is necessary since we have changed it. */ \ + TLS_SET_GS (_segdescr.desc.entry_number * 8 + 3); \ + \ + _result == 0 ? NULL \ + : "set_thread_area failed when setting up thread-local storage\n"; }) + +#endif +/* Return the address of the dtv for the current thread. */ +# define THREAD_DTV() \ + ({ struct _pthread_descr_struct *__pd; \ + THREAD_GETMEM (__pd, p_header.data.dtvp); }) + + +/* Return the thread descriptor for the current thread. + + The contained asm must *not* be marked __volatile__ since otherwise + assignments like + pthread_descr self = thread_self(); + do not get optimized away. */ +# define THREAD_SELF \ + ({ struct _pthread_descr_struct *__self; \ + __asm__ ("movl %%gs:%c1,%0" : "=r" (__self) \ + : "i" (offsetof (struct _pthread_descr_struct, p_header.data.self))); \ + __self;}) + +/* Magic for libthread_db to know how to do THREAD_SELF. */ +# define DB_THREAD_SELF \ + REGISTER_THREAD_AREA (32, offsetof (struct user_regs_struct, xgs), 3) \ + REGISTER_THREAD_AREA (64, 26 * 8, 3) /* x86-64's user_regs_struct->gs */ + + +/* Read member of the thread descriptor directly. */ +# define THREAD_GETMEM(descr, member) \ + ({ __typeof (descr->member) __value; \ + if (sizeof (__value) == 1) \ + __asm__ __volatile__ ("movb %%gs:%P2,%b0" \ + : "=q" (__value) \ + : "0" (0), "i" (offsetof (struct _pthread_descr_struct, member))); \ + else if (sizeof (__value) == 4) \ + __asm__ __volatile__ ("movl %%gs:%P1,%0" \ + : "=r" (__value) \ + : "i" (offsetof (struct _pthread_descr_struct, member))); \ + else \ + { \ + if (sizeof (__value) != 8) \ + /* There should not be any value with a size other than 1, \ + 4 or 8. */ \ + abort (); \ + \ + __asm__ __volatile__ ("movl %%gs:%P1,%%eax\n\t" \ + "movl %%gs:%P2,%%edx" \ + : "=A" (__value) \ + : "i" (offsetof (struct _pthread_descr_struct, member)), \ + "i" (offsetof (struct _pthread_descr_struct, member) + 4)); \ + } \ + __value; }) + + +/* Same as THREAD_GETMEM, but the member offset can be non-constant. */ +# define THREAD_GETMEM_NC(descr, member, idx) \ + ({ __typeof (descr->member[0]) __value; \ + if (sizeof (__value) == 1) \ + __asm__ __volatile__ ("movb %%gs:%P2(%3),%b0" \ + : "=q" (__value) \ + : "0" (0), "i" (offsetof (struct _pthread_descr_struct, member[0])), \ + "r" (idx)); \ + else if (sizeof (__value) == 4) \ + __asm__ __volatile__ ("movl %%gs:%P1(,%2,4),%0" \ + : "=r" (__value) \ + : "i" (offsetof (struct _pthread_descr_struct, member[0])), \ + "r" (idx)); \ + else \ + { \ + if (sizeof (__value) != 8) \ + /* There should not be any value with a size other than 1, \ + 4 or 8. */ \ + abort (); \ + \ + __asm__ __volatile__ ("movl %%gs:%P1(,%2,8),%%eax\n\t" \ + "movl %%gs:4+%P1(,%2,8),%%edx" \ + : "=&A" (__value) \ + : "i" (offsetof (struct _pthread_descr_struct, member[0])), \ + "r" (idx)); \ + } \ + __value; }) + + +/* Same as THREAD_SETMEM, but the member offset can be non-constant. */ +# define THREAD_SETMEM(descr, member, value) \ + ({ if (sizeof (descr->member) == 1) \ + __asm__ __volatile__ ("movb %b0,%%gs:%P1" : \ + : "iq" (value), \ + "i" (offsetof (struct _pthread_descr_struct, member))); \ + else if (sizeof (descr->member) == 4) \ + __asm__ __volatile__ ("movl %0,%%gs:%P1" : \ + : "ir" (value), \ + "i" (offsetof (struct _pthread_descr_struct, member))); \ + else \ + { \ + if (sizeof (descr->member) != 8) \ + /* There should not be any value with a size other than 1, \ + 4 or 8. */ \ + abort (); \ + \ + __asm__ __volatile__ ("movl %%eax,%%gs:%P1\n\t" \ + "movl %%edx,%%gs:%P2" : \ + : "A" (value), \ + "i" (offsetof (struct _pthread_descr_struct, member)), \ + "i" (offsetof (struct _pthread_descr_struct, member) + 4)); \ + }}) + + +/* Set member of the thread descriptor directly. */ +# define THREAD_SETMEM_NC(descr, member, idx, value) \ + ({ if (sizeof (descr->member[0]) == 1) \ + __asm__ __volatile__ ("movb %b0,%%gs:%P1(%2)" : \ + : "iq" (value), \ + "i" (offsetof (struct _pthread_descr_struct, member)), \ + "r" (idx)); \ + else if (sizeof (descr->member[0]) == 4) \ + __asm__ __volatile__ ("movl %0,%%gs:%P1(,%2,4)" : \ + : "ir" (value), \ + "i" (offsetof (struct _pthread_descr_struct, member)), \ + "r" (idx)); \ + else \ + { \ + if (sizeof (descr->member[0]) != 8) \ + /* There should not be any value with a size other than 1, \ + 4 or 8. */ \ + abort (); \ + \ + __asm__ __volatile__ ("movl %%eax,%%gs:%P1(,%2,8)\n\t" \ + "movl %%edx,%%gs:4+%P1(,%2,8)" : \ + : "A" (value), \ + "i" (offsetof (struct _pthread_descr_struct, member)), \ + "r" (idx)); \ + }}) + + +/* Atomic compare and exchange on TLS, returning old value. */ +#define THREAD_ATOMIC_CMPXCHG_VAL(descr, member, newval, oldval) \ + ({ __typeof (descr->member) __ret; \ + __typeof (oldval) __old = (oldval); \ + if (sizeof (descr->member) == 4) \ + __asm__ __volatile__ (LOCK_PREFIX "cmpxchgl %2, %%gs:%P3" \ + : "=a" (__ret) \ + : "0" (__old), "r" (newval), \ + "i" (offsetof (struct _pthread_descr_struct, member))); \ + else \ + /* Not necessary for other sizes in the moment. */ \ + abort (); \ + __ret; }) + + +/* Atomic logical and. */ +#define THREAD_ATOMIC_AND(descr, member, val) \ + (void) ({ if (sizeof ((descr)->member) == 4) \ + __asm__ __volatile__ (LOCK_PREFIX "andl %1, %%gs:%P0" \ + :: "i" (offsetof (struct _pthread_descr_struct, member)), \ + "ir" (val)); \ + else \ + /* Not necessary for other sizes in the moment. */ \ + abort (); }) + + +/* Atomic set bit. */ +#define THREAD_ATOMIC_BIT_SET(descr, member, bit) \ + (void) ({ if (sizeof ((descr)->member) == 4) \ + __asm__ __volatile__ (LOCK_PREFIX "orl %1, %%gs:%P0" \ + :: "i" (offsetof (struct _pthread_descr_struct, member)), \ + "ir" (1 << (bit))); \ + else \ + /* Not necessary for other sizes in the moment. */ \ + abort (); }) + + +/* Call the user-provided thread function. */ +#define CALL_THREAD_FCT(descr) \ + ({ void *__res; \ + int __ignore1, __ignore2; \ + __asm__ __volatile__ ("pushl %%eax\n\t" \ + "pushl %%eax\n\t" \ + "pushl %%eax\n\t" \ + "pushl %%gs:%P4\n\t" \ + "call *%%gs:%P3\n\t" \ + "addl $16, %%esp" \ + : "=a" (__res), "=c" (__ignore1), "=d" (__ignore2) \ + : "i" (offsetof (struct _pthread_descr_struct, start_routine)), \ + "i" (offsetof (struct _pthread_descr_struct, arg))); \ + __res; }) + + +/* Set the stack guard field in TCB head. */ +#define THREAD_SET_STACK_GUARD(value) \ + THREAD_SETMEM (THREAD_SELF, header.stack_guard, value) +#define THREAD_COPY_STACK_GUARD(descr) \ + ((descr)->header.stack_guard \ + = THREAD_GETMEM (THREAD_SELF, header.stack_guard)) + + +/* Set the pointer guard field in the TCB head. */ +#define THREAD_SET_POINTER_GUARD(value) \ + THREAD_SETMEM (THREAD_SELF, header.pointer_guard, value) +#define THREAD_COPY_POINTER_GUARD(descr) \ + ((descr)->header.pointer_guard \ + = THREAD_GETMEM (THREAD_SELF, header.pointer_guard)) + + +/* Get and set the global scope generation counter in the TCB head. */ +#define THREAD_GSCOPE_FLAG_UNUSED 0 +#define THREAD_GSCOPE_FLAG_USED 1 +#define THREAD_GSCOPE_FLAG_WAIT 2 +#define THREAD_GSCOPE_RESET_FLAG() \ + do \ + { int __res; \ + __asm__ __volatile__ ("xchgl %0, %%gs:%P1" \ + : "=r" (__res) \ + : "i" (offsetof (struct _pthread_descr_struct, header.gscope_flag)), \ + "0" (THREAD_GSCOPE_FLAG_UNUSED)); \ + if (__res == THREAD_GSCOPE_FLAG_WAIT) \ + lll_futex_wake (&THREAD_SELF->header.gscope_flag, 1, LLL_PRIVATE); \ + } \ + while (0) +#define THREAD_GSCOPE_SET_FLAG() \ + THREAD_SETMEM (THREAD_SELF, header.gscope_flag, THREAD_GSCOPE_FLAG_USED) +#define THREAD_GSCOPE_WAIT() \ + GL(dl_wait_lookup_done) () + +#endif /* __ASSEMBLER__ */ + +#endif /* tls.h */ diff --git a/l4/pkg/uclibc/lib/libpthread/src/sysdeps/mips/dl-tls.h b/l4/pkg/uclibc/lib/libpthread/src/sysdeps/mips/dl-tls.h new file mode 100644 index 00000000..3ad3b2bc --- /dev/null +++ b/l4/pkg/uclibc/lib/libpthread/src/sysdeps/mips/dl-tls.h @@ -0,0 +1,46 @@ +/* Thread-local storage handling in the ELF dynamic linker. MIPS version. + Copyright (C) 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + + +/* Type used for the representation of TLS information in the GOT. */ +typedef struct +{ + unsigned long int ti_module; + unsigned long int ti_offset; +} tls_index; + +/* The thread pointer points 0x7000 past the first static TLS block. */ +#define TLS_TP_OFFSET 0x7000 + +/* Dynamic thread vector pointers point 0x8000 past the start of each + TLS block. */ +#define TLS_DTV_OFFSET 0x8000 + +/* Compute the value for a GOTTPREL reloc. */ +#define TLS_TPREL_VALUE(sym_map, sym_val) \ + ((sym_map)->l_tls_offset + sym_val - TLS_TP_OFFSET) + +/* Compute the value for a DTPREL reloc. */ +#define TLS_DTPREL_VALUE(sym_val) \ + (sym_val - TLS_DTV_OFFSET) + +extern void *__tls_get_addr (tls_index *ti); + +# define GET_ADDR_OFFSET (ti->ti_offset + TLS_DTV_OFFSET) +# define __TLS_GET_ADDR(__ti) (__tls_get_addr (__ti) - TLS_DTV_OFFSET) diff --git a/l4/pkg/uclibc/lib/libpthread/src/sysdeps/mips/tls.h b/l4/pkg/uclibc/lib/libpthread/src/sysdeps/mips/tls.h new file mode 100644 index 00000000..27b1c15d --- /dev/null +++ b/l4/pkg/uclibc/lib/libpthread/src/sysdeps/mips/tls.h @@ -0,0 +1,181 @@ +/* Definition for thread-local data handling. NPTL/MIPS version. + Copyright (C) 2005, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _TLS_H +#define _TLS_H 1 + +#ifndef __ASSEMBLER__ +# include +# include +# include + +/* Type for the dtv. */ +typedef union dtv +{ + size_t counter; + struct + { + void *val; + bool is_static; + } pointer; +} dtv_t; + +/* Note: rd must be $v1 to be ABI-conformant. */ +# define READ_THREAD_POINTER() \ + ({ void *__result; \ + __asm__ __volatile__ (".set\tpush\n\t.set\tmips32r2\n\t" \ + "rdhwr\t%0, $29\n\t.set\tpop" : "=v" (__result)); \ + __result; }) + +#else /* __ASSEMBLER__ */ +# include + +# define READ_THREAD_POINTER(rd) \ + .set push; \ + .set mips32r2; \ + rdhwr rd, $29; \ + .set pop +#endif /* __ASSEMBLER__ */ + + +/* We require TLS support in the tools. */ +#define HAVE_TLS_SUPPORT 1 +#define HAVE_TLS_MODEL_ATTRIBUTE 1 +#define HAVE___THREAD 1 + +/* Signal that TLS support is available. */ +#define USE_TLS 1 + +#ifndef __ASSEMBLER__ + +/* Get system call information. */ +# include + +/* The TP points to the start of the thread blocks. */ +# define TLS_DTV_AT_TP 1 + +/* Get the thread descriptor definition. */ +#include <../../descr.h> + +typedef struct +{ + dtv_t *dtv; + void *private; +} tcbhead_t; + +/* This is the size of the initial TCB. Because our TCB is before the thread + pointer, we don't need this. */ +# define TLS_INIT_TCB_SIZE 0 + +/* Alignment requirements for the initial TCB. */ +# define TLS_INIT_TCB_ALIGN __alignof__ (struct pthread) + +/* This is the size of the TCB. Because our TCB is before the thread + pointer, we don't need this. */ +# define TLS_TCB_SIZE 0 + +/* Alignment requirements for the TCB. */ +# define TLS_TCB_ALIGN __alignof__ (struct pthread) + +/* This is the size we need before TCB - actually, it includes the TCB. */ +# define TLS_PRE_TCB_SIZE \ + (sizeof (struct pthread) \ + + ((sizeof (tcbhead_t) + TLS_TCB_ALIGN - 1) & ~(TLS_TCB_ALIGN - 1))) + +/* The thread pointer (in hardware register $29) points to the end of + the TCB + 0x7000, as for PowerPC. The pthread_descr structure is + immediately in front of the TCB. */ +# define TLS_TCB_OFFSET 0x7000 + +/* Install the dtv pointer. The pointer passed is to the element with + index -1 which contain the length. */ +# define INSTALL_DTV(tcbp, dtvp) \ + (((tcbhead_t *) (tcbp))[-1].dtv = (dtvp) + 1) + +/* Install new dtv for current thread. */ +# define INSTALL_NEW_DTV(dtv) \ + (THREAD_DTV() = (dtv)) + +/* Return dtv of given thread descriptor. */ +# define GET_DTV(tcbp) \ + (((tcbhead_t *) (tcbp))[-1].dtv) + +/* Code to initially initialize the thread pointer. This might need + special attention since 'errno' is not yet available and if the + operation can cause a failure 'errno' must not be touched. */ +# define TLS_INIT_TP(tcbp, secondcall) \ + ({ INTERNAL_SYSCALL_DECL (err); \ + long result_var; \ + result_var = INTERNAL_SYSCALL (set_thread_area, err, 1, \ + (char *) (tcbp) + TLS_TCB_OFFSET); \ + INTERNAL_SYSCALL_ERROR_P (result_var, err) \ + ? "unknown error" : NULL; }) + +/* Return the address of the dtv for the current thread. */ +# define THREAD_DTV() \ + (((tcbhead_t *) (READ_THREAD_POINTER () - TLS_TCB_OFFSET))[-1].dtv) + +/* Return the thread descriptor for the current thread. */ +# define THREAD_SELF \ + ((struct pthread *) (READ_THREAD_POINTER () \ + - TLS_TCB_OFFSET - TLS_PRE_TCB_SIZE)) + +/* Magic for libthread_db to know how to do THREAD_SELF. */ +# define DB_THREAD_SELF \ + CONST_THREAD_AREA (32, TLS_TCB_OFFSET + TLS_PRE_TCB_SIZE) + +/* Access to data in the thread descriptor is easy. */ +# define THREAD_GETMEM(descr, member) \ + descr->member +# define THREAD_GETMEM_NC(descr, member, idx) \ + descr->member[idx] +# define THREAD_SETMEM(descr, member, value) \ + descr->member = (value) +# define THREAD_SETMEM_NC(descr, member, idx, value) \ + descr->member[idx] = (value) + +/* l_tls_offset == 0 is perfectly valid on MIPS, so we have to use some + different value to mean unset l_tls_offset. */ +# define NO_TLS_OFFSET -1 +/* Get and set the global scope generation counter in struct pthread. */ +#define THREAD_GSCOPE_FLAG_UNUSED 0 +#define THREAD_GSCOPE_FLAG_USED 1 +#define THREAD_GSCOPE_FLAG_WAIT 2 +#define THREAD_GSCOPE_RESET_FLAG() \ + do \ + { int __res \ + = atomic_exchange_rel (&THREAD_SELF->header.gscope_flag, \ + THREAD_GSCOPE_FLAG_UNUSED); \ + if (__res == THREAD_GSCOPE_FLAG_WAIT) \ + lll_futex_wake (&THREAD_SELF->header.gscope_flag, 1, LLL_PRIVATE); \ + } \ + while (0) +#define THREAD_GSCOPE_SET_FLAG() \ + do \ + { \ + THREAD_SELF->header.gscope_flag = THREAD_GSCOPE_FLAG_USED; \ + atomic_write_barrier (); \ + } \ + while (0) +#define THREAD_GSCOPE_WAIT() \ + GL(dl_wait_lookup_done) () + +#endif /* __ASSEMBLER__ */ + +#endif /* tls.h */ diff --git a/l4/pkg/uclibc/lib/libpthread/src/sysdeps/powerpc/dl-tls.h b/l4/pkg/uclibc/lib/libpthread/src/sysdeps/powerpc/dl-tls.h new file mode 100644 index 00000000..957d4b4b --- /dev/null +++ b/l4/pkg/uclibc/lib/libpthread/src/sysdeps/powerpc/dl-tls.h @@ -0,0 +1,49 @@ +/* Thread-local storage handling in the ELF dynamic linker. PowerPC version. + Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + + +/* Type used for the representation of TLS information in the TOC. */ +typedef struct +{ + unsigned long int ti_module; + unsigned long int ti_offset; +} tls_index; + +/* The thread pointer points 0x7000 past the first static TLS block. */ +#define TLS_TP_OFFSET 0x7000 + +/* Dynamic thread vector pointers point 0x8000 past the start of each + TLS block. */ +#define TLS_DTV_OFFSET 0x8000 + +/* Compute the value for a @tprel reloc. */ +#define TLS_TPREL_VALUE(sym_map, sym, reloc) \ + ((sym_map)->l_tls_offset + (sym)->st_value + (reloc)->r_addend \ + - TLS_TP_OFFSET) + +/* Compute the value for a @dtprel reloc. */ +#define TLS_DTPREL_VALUE(sym, reloc) \ + ((sym)->st_value + (reloc)->r_addend - TLS_DTV_OFFSET) + +#ifdef SHARED +extern void *__tls_get_addr (tls_index *ti); + +# define GET_ADDR_OFFSET (ti->ti_offset + TLS_DTV_OFFSET) +# define __TLS_GET_ADDR(__ti) (__tls_get_addr (__ti) - TLS_DTV_OFFSET) +#endif diff --git a/l4/pkg/uclibc/lib/libpthread/src/sysdeps/powerpc/powerpc32/pt-machine.h b/l4/pkg/uclibc/lib/libpthread/src/sysdeps/powerpc/powerpc32/pt-machine.h new file mode 100644 index 00000000..c9ec5e76 --- /dev/null +++ b/l4/pkg/uclibc/lib/libpthread/src/sysdeps/powerpc/powerpc32/pt-machine.h @@ -0,0 +1,123 @@ +/* Machine-dependent pthreads configuration and inline functions. + powerpc version. + Copyright (C) 1996, 1997, 1998, 2000, 2001, 2002, 2003 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If + not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* These routines are from Appendix G of the 'PowerPC 601 RISC Microprocessor + User's Manual', by IBM and Motorola. */ + +#ifndef _PT_MACHINE_H +#define _PT_MACHINE_H 1 + +#ifndef PT_EI +# define PT_EI __extern_always_inline +#endif + +extern long int testandset (int *spinlock); +extern int __compare_and_swap (long int *p, long int oldval, long int newval); + +/* For multiprocessor systems, we want to ensure all memory accesses + are completed before we reset a lock. On other systems, we still + need to make sure that the compiler has flushed everything to memory. */ +#define MEMORY_BARRIER() __asm__ __volatile__ ("sync" : : : "memory") + +/* We want the OS to assign stack addresses. */ +#define FLOATING_STACKS 1 + +/* Maximum size of the stack if the rlimit is unlimited. */ +#define ARCH_STACK_MAX_SIZE 8*1024*1024 + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#define CURRENT_STACK_FRAME stack_pointer +register char * stack_pointer __asm__ ("r1"); + +/* Register r2 (tp) is reserved by the ABI as "thread pointer". */ +struct _pthread_descr_struct; +register struct _pthread_descr_struct *__thread_self __asm__("r2"); + +#ifdef NOT_FOR_L4 +/* Return the thread descriptor for the current thread. */ +#define THREAD_SELF __thread_self + +/* Initialize the thread-unique value. */ +l4/#define INIT_THREAD_SELF(descr, nr) (__thread_self = (descr)) + +/* Access to data in the thread descriptor is easy. */ +#define THREAD_GETMEM(descr, member) \ + ((void) (descr), THREAD_SELF->member) +#define THREAD_GETMEM_NC(descr, member) \ + ((void) (descr), THREAD_SELF->member) +#define THREAD_SETMEM(descr, member, value) \ + ((void) (descr), THREAD_SELF->member = (value)) +#define THREAD_SETMEM_NC(descr, member, value) \ + ((void) (descr), THREAD_SELF->member = (value)) + +#endif /* L4 */ + +/* Compare-and-swap for semaphores. */ +/* note that test-and-set(x) is the same as !compare-and-swap(x, 0, 1) */ + +#define HAS_COMPARE_AND_SWAP_WITH_RELEASE_SEMANTICS +#define IMPLEMENT_TAS_WITH_CAS + +PT_EI int +__compare_and_swap (long int *p, long int oldval, long int newval) +{ + int ret; + + __asm__ __volatile__ ( + "0: lwarx %0,0,%1 ;" + " xor. %0,%3,%0;" + " bne 1f;" + " stwcx. %2,0,%1;" + " bne- 0b;" + "1: " + : "=&r"(ret) + : "r"(p), "r"(newval), "r"(oldval) + : "cr0", "memory"); + /* This version of __compare_and_swap is to be used when acquiring + a lock, so we don't need to worry about whether other memory + operations have completed, but we do need to be sure that any loads + after this point really occur after we have acquired the lock. */ + __asm__ __volatile__ ("isync" : : : "memory"); + return ret == 0; +} + +PT_EI int +__compare_and_swap_with_release_semantics (long int *p, + long int oldval, long int newval) +{ + int ret; + + MEMORY_BARRIER (); + __asm__ __volatile__ ( + "0: lwarx %0,0,%1 ;" + " xor. %0,%3,%0;" + " bne 1f;" + " stwcx. %2,0,%1;" + " bne- 0b;" + "1: " + : "=&r"(ret) + : "r"(p), "r"(newval), "r"(oldval) + : "cr0", "memory"); + return ret == 0; +} + +#endif /* pt-machine.h */ diff --git a/l4/pkg/uclibc/lib/libpthread/src/sysdeps/powerpc/powerpc64/pt-machine.h b/l4/pkg/uclibc/lib/libpthread/src/sysdeps/powerpc/powerpc64/pt-machine.h new file mode 100644 index 00000000..89ee614e --- /dev/null +++ b/l4/pkg/uclibc/lib/libpthread/src/sysdeps/powerpc/powerpc64/pt-machine.h @@ -0,0 +1,187 @@ +/* Machine-dependent pthreads configuration and inline functions. + powerpc version. + Copyright (C) 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If + not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* These routines are from Appendix G of the 'PowerPC 601 RISC Microprocessor + User's Manual', by IBM and Motorola. */ + +#ifndef _PT_MACHINE_H +#define _PT_MACHINE_H 1 + +#ifndef PT_EI +# define PT_EI __extern_always_inline +#endif + +extern long int testandset (int *spinlock); +extern int __compare_and_swap (long int *p, long int oldval, long int newval); +extern int __compare_and_swap32 (int *p, int oldval, int newval); + +/* For multiprocessor systems, we want to ensure all memory accesses + are completed before we reset a lock. On other systems, we still + need to make sure that the compiler has flushed everything to memory. */ +#define MEMORY_BARRIER() __asm__ __volatile__ ("lwsync" : : : "memory") +#define READ_MEMORY_BARRIER() __asm__ __volatile__ ("lwsync" : : : "memory") +#define WRITE_MEMORY_BARRIER() __asm__ __volatile__ ("eieio" : : : "memory") + +/* We want the OS to assign stack addresses. */ +#define FLOATING_STACKS 1 + +/* Maximum size of the stack if the rlimit is unlimited. */ +#define ARCH_STACK_MAX_SIZE 16*1024*1024 + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#define CURRENT_STACK_FRAME stack_pointer +register char * stack_pointer __asm__ ("r1"); + +/* Register r13 (tp) is reserved by the ABI as "thread pointer". */ +struct _pthread_descr_struct; +register struct _pthread_descr_struct *__thread_self __asm__("r13"); + +#ifdef NOT_FOR_L4 +/* Return the thread descriptor for the current thread. */ +#define THREAD_SELF __thread_self + +/* Initialize the thread-unique value. */ +#define INIT_THREAD_SELF(descr, nr) (__thread_self = (descr)) + +/* Access to data in the thread descriptor is easy. */ +#define THREAD_GETMEM(descr, member) \ + ((void) (descr), THREAD_SELF->member) +#define THREAD_GETMEM_NC(descr, member) \ + ((void) (descr), THREAD_SELF->member) +#define THREAD_SETMEM(descr, member, value) \ + ((void) (descr), THREAD_SELF->member = (value)) +#define THREAD_SETMEM_NC(descr, member, value) \ + ((void) (descr), THREAD_SELF->member = (value)) +#endif /* L4 */ + +/* Compare-and-swap for semaphores. */ +/* note that test-and-set(x) is the same as !compare-and-swap(x, 0, 1) */ + +#define HAS_COMPARE_AND_SWAP +#define HAS_COMPARE_AND_SWAP_WITH_RELEASE_SEMANTICS + +PT_EI int +__compare_and_swap (long int *p, long int oldval, long int newval) +{ + long int ret; + + __asm__ __volatile__ ( + "0: ldarx %0,0,%1 ;" + " xor. %0,%3,%0;" + " bne 1f;" + " stdcx. %2,0,%1;" + " bne- 0b;" + "1: " + : "=&r"(ret) + : "r"(p), "r"(newval), "r"(oldval) + : "cr0", "memory"); + /* This version of __compare_and_swap is to be used when acquiring + a lock, so we don't need to worry about whether other memory + operations have completed, but we do need to be sure that any loads + after this point really occur after we have acquired the lock. */ + __asm__ __volatile__ ("isync" : : : "memory"); + return (int)(ret == 0); +} + +PT_EI int +__compare_and_swap_with_release_semantics (long int *p, + long int oldval, long int newval) +{ + long int ret; + + MEMORY_BARRIER (); + __asm__ __volatile__ ( + "0: ldarx %0,0,%1 ;" + " xor. %0,%3,%0;" + " bne 1f;" + " stdcx. %2,0,%1;" + " bne- 0b;" + "1: " + : "=&r"(ret) + : "r"(p), "r"(newval), "r"(oldval) + : "cr0", "memory"); + return (int)(ret == 0); +} + +PT_EI int +__compare_and_swap32 (int *p, int oldval, int newval) +{ + int ret; + + __asm__ __volatile__ ( + "0: lwarx %0,0,%1 ;" + " xor. %0,%3,%0;" + " bne 1f;" + " stwcx. %2,0,%1;" + " bne- 0b;" + "1: " + : "=&r"(ret) + : "r"(p), "r"(newval), "r"(oldval) + : "cr0", "memory"); + /* This version of __compare_and_swap is to be used when acquiring + a lock, so we don't need to worry about whether other memory + operations have completed, but we do need to be sure that any loads + after this point really occur after we have acquired the lock. */ + __asm__ __volatile__ ("isync" : : : "memory"); + return (int)(ret == 0); +} + +PT_EI int +__compare_and_swap32_with_release_semantics (long int *p, + long int oldval, long int newval) +{ + long int ret; + + MEMORY_BARRIER (); + __asm__ __volatile__ ( + "0: lwarx %0,0,%1 ;" + " xor. %0,%3,%0;" + " bne 1f;" + " stwcx. %2,0,%1;" + " bne- 0b;" + "1: " + : "=&r"(ret) + : "r"(p), "r"(newval), "r"(oldval) + : "cr0", "memory"); + return (int)(ret == 0); +} + +PT_EI long int +testandset (int *p) +{ + long int ret, val = 1; + + MEMORY_BARRIER (); + __asm__ __volatile__ ( + "0: lwarx %0,0,%1 ;" + " cmpwi 0,%0,0;" + " bne 1f;" + " stwcx. %2,0,%1;" + " bne- 0b;" + "1: " + : "=&r"(ret) + : "r"(p), "r" (val) + : "cr0", "memory"); + MEMORY_BARRIER (); + return ret != 0; +} + +#endif /* pt-machine.h */ diff --git a/l4/pkg/uclibc/lib/libpthread/src/sysdeps/powerpc/pt-machine.h b/l4/pkg/uclibc/lib/libpthread/src/sysdeps/powerpc/pt-machine.h new file mode 100644 index 00000000..55e922ef --- /dev/null +++ b/l4/pkg/uclibc/lib/libpthread/src/sysdeps/powerpc/pt-machine.h @@ -0,0 +1,8 @@ +#include +#include + +#if __WORDSIZE == 32 +# include "powerpc32/pt-machine.h" +#else +# include "powerpc64/pt-machine.h" +#endif diff --git a/l4/pkg/uclibc/lib/libpthread/src/sysdeps/powerpc/tls.h b/l4/pkg/uclibc/lib/libpthread/src/sysdeps/powerpc/tls.h new file mode 100644 index 00000000..3f9a7a43 --- /dev/null +++ b/l4/pkg/uclibc/lib/libpthread/src/sysdeps/powerpc/tls.h @@ -0,0 +1,216 @@ +/* Definition for thread-local data handling. NPTL/PowerPC version. + Copyright (C) 2003, 2005, 2006, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _TLS_H +#define _TLS_H 1 + +#ifndef __ASSEMBLER__ +# include +# include +# include + +/* Type for the dtv. */ +typedef union dtv +{ + size_t counter; + struct + { + void *val; + bool is_static; + } pointer; +} dtv_t; + +#else /* __ASSEMBLER__ */ +# include +#endif /* __ASSEMBLER__ */ + +/* We require TLS support in the tools. */ +#define HAVE_TLS_SUPPORT 1 +#define HAVE_TLS_MODEL_ATTRIBUTE 1 +#define HAVE___THREAD 1 + +/* Signal that TLS support is available. */ +#define USE_TLS 1 + +/* We require TLS support in the tools. */ +#ifndef HAVE_TLS_SUPPORT +# error "TLS support is required." +#endif + +/* Signal that TLS support is available. */ +# define USE_TLS 1 + +#ifndef __ASSEMBLER__ + +/* Get system call information. */ +//# include + +/* The TP points to the start of the thread blocks. */ +# define TLS_DTV_AT_TP 1 + +/* We use the multiple_threads field in the pthread struct */ +#define TLS_MULTIPLE_THREADS_IN_TCB 1 + +/* Get the thread descriptor definition. */ +# include <../../descr.h> + +/* The stack_guard is accessed directly by GCC -fstack-protector code, + so it is a part of public ABI. The dtv and pointer_guard fields + are private. */ +typedef struct +{ + uintptr_t pointer_guard; + uintptr_t stack_guard; + dtv_t *dtv; +} tcbhead_t; + + +/* This is the size of the initial TCB. */ +# define TLS_INIT_TCB_SIZE 0 + +/* Alignment requirements for the initial TCB. */ +# define TLS_INIT_TCB_ALIGN __alignof__ (struct _pthread_descr_struct) //pthread) + +/* This is the size of the TCB. */ +# define TLS_TCB_SIZE 0 + +/* Alignment requirements for the TCB. */ +# define TLS_TCB_ALIGN __alignof__ (struct _pthread_descr_struct) //pthread) + +/* This is the size we need before TCB. */ +# define TLS_PRE_TCB_SIZE \ + (sizeof (struct _pthread_descr_struct) \ + + ((sizeof (tcbhead_t) + TLS_TCB_ALIGN - 1) & ~(TLS_TCB_ALIGN - 1))) + +# ifndef __powerpc64__ +/* Register r2 (tp) is reserved by the ABI as "thread pointer". */ +register void *__thread_register __asm__ ("r2"); +# define PT_THREAD_POINTER PT_R2 +# else +/* Register r13 (tp) is reserved by the ABI as "thread pointer". */ +register void *__thread_register __asm__ ("r13"); +# define PT_THREAD_POINTER PT_R13 +# endif + +/* The following assumes that TP (R2 or R13) points to the end of the + TCB + 0x7000 (per the ABI). This implies that TCB address is + TP - 0x7000. As we define TLS_DTV_AT_TP we can + assume that the pthread struct is allocated immediately ahead of the + TCB. This implies that the pthread_descr address is + TP - (TLS_PRE_TCB_SIZE + 0x7000). */ +# define TLS_TCB_OFFSET 0x7000 + +/* Install the dtv pointer. The pointer passed is to the element with + index -1 which contain the length. */ +# define INSTALL_DTV(tcbp, dtvp) \ + ((tcbhead_t *) (tcbp))[-1].dtv = dtvp + 1 + +/* Install new dtv for current thread. */ +# define INSTALL_NEW_DTV(dtv) (THREAD_DTV() = (dtv)) + +/* Return dtv of given thread descriptor. */ +# define GET_DTV(tcbp) (((tcbhead_t *) (tcbp))[-1].dtv) + +/* Code to initially initialize the thread pointer. This might need + special attention since 'errno' is not yet available and if the + operation can cause a failure 'errno' must not be touched. */ +# define TLS_INIT_TP(tcbp, secondcall) \ + (__thread_register = (void *) (tcbp) + TLS_TCB_OFFSET, NULL) + +/* Return the address of the dtv for the current thread. */ +# define THREAD_DTV() \ + (((tcbhead_t *) (__thread_register - TLS_TCB_OFFSET))[-1].dtv) + +/* Return the thread descriptor for the current thread. */ +# define THREAD_SELF \ + ((struct _pthread_descr_struct *) (__thread_register \ + - TLS_TCB_OFFSET - TLS_PRE_TCB_SIZE)) + +/* Magic for libthread_db to know how to do THREAD_SELF. */ +# define DB_THREAD_SELF \ + REGISTER (32, 32, PT_THREAD_POINTER * 4, \ + - TLS_TCB_OFFSET - TLS_PRE_TCB_SIZE) \ + REGISTER (64, 64, PT_THREAD_POINTER * 8, \ + - TLS_TCB_OFFSET - TLS_PRE_TCB_SIZE) + +/* Read member of the thread descriptor directly. */ +# define THREAD_GETMEM(descr, member) ((void)(descr), (THREAD_SELF)->member) + +/* Same as THREAD_GETMEM, but the member offset can be non-constant. */ +# define THREAD_GETMEM_NC(descr, member, idx) \ + ((void)(descr), (THREAD_SELF)->member[idx]) + +/* Set member of the thread descriptor directly. */ +# define THREAD_SETMEM(descr, member, value) \ + ((void)(descr), (THREAD_SELF)->member = (value)) + +/* Same as THREAD_SETMEM, but the member offset can be non-constant. */ +# define THREAD_SETMEM_NC(descr, member, idx, value) \ + ((void)(descr), (THREAD_SELF)->member[idx] = (value)) + +/* Set the stack guard field in TCB head. */ +# define THREAD_SET_STACK_GUARD(value) \ + (((tcbhead_t *) ((char *) __thread_register \ + - TLS_TCB_OFFSET))[-1].stack_guard = (value)) +# define THREAD_COPY_STACK_GUARD(descr) \ + (((tcbhead_t *) ((char *) (descr) \ + + TLS_PRE_TCB_SIZE))[-1].stack_guard \ + = ((tcbhead_t *) ((char *) __thread_register \ + - TLS_TCB_OFFSET))[-1].stack_guard) + +/* Set the stack guard field in TCB head. */ +# define THREAD_GET_POINTER_GUARD() \ + (((tcbhead_t *) ((char *) __thread_register \ + - TLS_TCB_OFFSET))[-1].pointer_guard) +# define THREAD_SET_POINTER_GUARD(value) \ + (THREAD_GET_POINTER_GUARD () = (value)) +# define THREAD_COPY_POINTER_GUARD(descr) \ + (((tcbhead_t *) ((char *) (descr) \ + + TLS_PRE_TCB_SIZE))[-1].pointer_guard \ + = THREAD_GET_POINTER_GUARD()) + +/* l_tls_offset == 0 is perfectly valid on PPC, so we have to use some + different value to mean unset l_tls_offset. */ +# define NO_TLS_OFFSET -1 + +/* Get and set the global scope generation counter in struct pthread. */ +#define THREAD_GSCOPE_FLAG_UNUSED 0 +#define THREAD_GSCOPE_FLAG_USED 1 +#define THREAD_GSCOPE_FLAG_WAIT 2 +#define THREAD_GSCOPE_RESET_FLAG() \ + do \ + { int __res \ + = atomic_exchange_rel (&THREAD_SELF->header.gscope_flag, \ + THREAD_GSCOPE_FLAG_UNUSED); \ + if (__res == THREAD_GSCOPE_FLAG_WAIT) \ + lll_futex_wake (&THREAD_SELF->header.gscope_flag, 1, LLL_PRIVATE); \ + } \ + while (0) +#define THREAD_GSCOPE_SET_FLAG() \ + do \ + { \ + THREAD_SELF->header.gscope_flag = THREAD_GSCOPE_FLAG_USED; \ + atomic_write_barrier (); \ + } \ + while (0) +#define THREAD_GSCOPE_WAIT() \ + GL(dl_wait_lookup_done) () + +#endif /* __ASSEMBLER__ */ +#endif /* tls.h */ diff --git a/l4/pkg/uclibc/lib/libpthread/src/sysdeps/sh/dl-tls.h b/l4/pkg/uclibc/lib/libpthread/src/sysdeps/sh/dl-tls.h new file mode 100644 index 00000000..98e2f190 --- /dev/null +++ b/l4/pkg/uclibc/lib/libpthread/src/sysdeps/sh/dl-tls.h @@ -0,0 +1,29 @@ +/* Thread-local storage handling in the ELF dynamic linker. SH version. + Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + + +/* Type used for the representation of TLS information in the GOT. */ +typedef struct +{ + unsigned long int ti_module; + unsigned long int ti_offset; +} tls_index; + + +extern void *__tls_get_addr (tls_index *ti); diff --git a/l4/pkg/uclibc/lib/libpthread/src/sysdeps/sh/tls.h b/l4/pkg/uclibc/lib/libpthread/src/sysdeps/sh/tls.h new file mode 100644 index 00000000..bbb11187 --- /dev/null +++ b/l4/pkg/uclibc/lib/libpthread/src/sysdeps/sh/tls.h @@ -0,0 +1,182 @@ +/* Definition for thread-local data handling. NPTL/SH version. + Copyright (C) 2003, 2005, 2006, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _TLS_H +#define _TLS_H + +#ifndef __ASSEMBLER__ +# include +# include +# include +# include +# include +# include +# include + +/* Type for the dtv. */ +typedef union dtv +{ + size_t counter; + struct + { + void *val; + bool is_static; + } pointer; +} dtv_t; + +typedef struct +{ + dtv_t *dtv; + uintptr_t pointer_guard; +} tcbhead_t; + +# define TLS_MULTIPLE_THREADS_IN_TCB 1 + +#else /* __ASSEMBLER__ */ +# include +#endif /* __ASSEMBLER__ */ + + +/* We require TLS support in the tools. */ +#define HAVE_TLS_SUPPORT +#define HAVE___THREAD 1 +#define HAVE_TLS_MODEL_ATTRIBUTE 1 +/* Signal that TLS support is available. */ +# define USE_TLS 1 + +#ifndef __ASSEMBLER__ + +/* Get system call information. */ +# include + +/* This is the size of the initial TCB. */ +# define TLS_INIT_TCB_SIZE sizeof (tcbhead_t) + +/* Alignment requirements for the initial TCB. */ +# define TLS_INIT_TCB_ALIGN __alignof__ (tcbhead_t) + +/* This is the size of the TCB. */ +# define TLS_TCB_SIZE sizeof (tcbhead_t) + +/* This is the size we need before TCB. */ +# define TLS_PRE_TCB_SIZE sizeof (struct pthread) + +/* Alignment requirements for the TCB. */ +# define TLS_TCB_ALIGN __alignof__ (struct pthread) + +/* The TLS blocks start right after the TCB. */ +# define TLS_DTV_AT_TP 1 + +/* Get the thread descriptor definition. */ +# include + +/* Install the dtv pointer. The pointer passed is to the element with + index -1 which contain the length. */ +# define INSTALL_DTV(tcbp, dtvp) \ + ((tcbhead_t *) (tcbp))->dtv = (dtvp) + 1 + +/* Install new dtv for current thread. */ +# define INSTALL_NEW_DTV(dtv) \ + ({ tcbhead_t *__tcbp; \ + __asm__ __volatile__ ("stc gbr,%0" : "=r" (__tcbp)); \ + __tcbp->dtv = (dtv);}) + +/* Return dtv of given thread descriptor. */ +# define GET_DTV(tcbp) \ + (((tcbhead_t *) (tcbp))->dtv) + +/* Code to initially initialize the thread pointer. This might need + special attention since 'errno' is not yet available and if the + operation can cause a failure 'errno' must not be touched. */ +# define TLS_INIT_TP(tcbp, secondcall) \ + ({ __asm__ __volatile__ ("ldc %0,gbr" : : "r" (tcbp)); 0; }) + +/* Return the address of the dtv for the current thread. */ +# define THREAD_DTV() \ + ({ tcbhead_t *__tcbp; \ + __asm__ __volatile__ ("stc gbr,%0" : "=r" (__tcbp)); \ + __tcbp->dtv;}) + +/* Return the thread descriptor for the current thread. + The contained asm must *not* be marked volatile since otherwise + assignments like + struct pthread *self = thread_self(); + do not get optimized away. */ +# define THREAD_SELF \ + ({ struct pthread *__self; \ + __asm__ ("stc gbr,%0" : "=r" (__self)); \ + __self - 1;}) + +/* Magic for libthread_db to know how to do THREAD_SELF. */ +# define DB_THREAD_SELF \ + REGISTER (32, 32, REG_GBR * 4, -sizeof (struct pthread)) + +/* Read member of the thread descriptor directly. */ +# define THREAD_GETMEM(descr, member) (descr->member) + +/* Same as THREAD_GETMEM, but the member offset can be non-constant. */ +# define THREAD_GETMEM_NC(descr, member, idx) (descr->member[idx]) + +/* Set member of the thread descriptor directly. */ +# define THREAD_SETMEM(descr, member, value) \ + descr->member = (value) + +/* Same as THREAD_SETMEM, but the member offset can be non-constant. */ +# define THREAD_SETMEM_NC(descr, member, idx, value) \ + descr->member[idx] = (value) + +#define THREAD_GET_POINTER_GUARD() \ + ({ tcbhead_t *__tcbp; \ + __asm__ __volatile__ ("stc gbr,%0" : "=r" (__tcbp)); \ + __tcbp->pointer_guard;}) + #define THREAD_SET_POINTER_GUARD(value) \ + ({ tcbhead_t *__tcbp; \ + __asm__ __volatile__ ("stc gbr,%0" : "=r" (__tcbp)); \ + __tcbp->pointer_guard = (value);}) +#define THREAD_COPY_POINTER_GUARD(descr) \ + ({ tcbhead_t *__tcbp; \ + __asm__ __volatile__ ("stc gbr,%0" : "=r" (__tcbp)); \ + ((tcbhead_t *) (descr + 1))->pointer_guard = __tcbp->pointer_guard;}) + +/* Get and set the global scope generation counter in struct pthread. */ +#define THREAD_GSCOPE_FLAG_UNUSED 0 +#define THREAD_GSCOPE_FLAG_USED 1 +#define THREAD_GSCOPE_FLAG_WAIT 2 +#define THREAD_GSCOPE_RESET_FLAG() \ + do \ + { int __res \ + = atomic_exchange_rel (&THREAD_SELF->header.gscope_flag, \ + THREAD_GSCOPE_FLAG_UNUSED); \ + if (__res == THREAD_GSCOPE_FLAG_WAIT) \ + lll_futex_wake (&THREAD_SELF->header.gscope_flag, 1, LLL_PRIVATE); \ + } \ + while (0) +#define THREAD_GSCOPE_SET_FLAG() \ + do \ + { \ + THREAD_SELF->header.gscope_flag = THREAD_GSCOPE_FLAG_USED; \ + atomic_write_barrier (); \ + } \ + while (0) +#define THREAD_GSCOPE_WAIT() \ + GL(dl_wait_lookup_done) () + +#endif /* __ASSEMBLER__ */ + +#endif /* tls.h */ diff --git a/l4/pkg/uclibc/lib/libpthread/src/sysdeps/sparc/dl-tls.h b/l4/pkg/uclibc/lib/libpthread/src/sysdeps/sparc/dl-tls.h new file mode 100644 index 00000000..6edf8d52 --- /dev/null +++ b/l4/pkg/uclibc/lib/libpthread/src/sysdeps/sparc/dl-tls.h @@ -0,0 +1,29 @@ +/* Thread-local storage handling in the ELF dynamic linker. SPARC version. + Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + + +/* Type used for the representation of TLS information in the GOT. */ +typedef struct +{ + unsigned long int ti_module; + unsigned long int ti_offset; +} tls_index; + + +extern void *__tls_get_addr (tls_index *ti); diff --git a/l4/pkg/uclibc/lib/libpthread/src/sysdeps/sparc/pt-machine.h b/l4/pkg/uclibc/lib/libpthread/src/sysdeps/sparc/pt-machine.h new file mode 100644 index 00000000..ab90810f --- /dev/null +++ b/l4/pkg/uclibc/lib/libpthread/src/sysdeps/sparc/pt-machine.h @@ -0,0 +1,8 @@ +#include +#include + +#if __WORDSIZE == 32 +# include "sparc32/pt-machine.h" +#else +# include "sparc64/pt-machine.h" +#endif diff --git a/l4/pkg/uclibc/lib/libpthread/src/sysdeps/sparc/sparc32/pt-machine.h b/l4/pkg/uclibc/lib/libpthread/src/sysdeps/sparc/sparc32/pt-machine.h new file mode 100644 index 00000000..09ff226c --- /dev/null +++ b/l4/pkg/uclibc/lib/libpthread/src/sysdeps/sparc/sparc32/pt-machine.h @@ -0,0 +1,85 @@ +/* Machine-dependent pthreads configuration and inline functions. + sparc version. + Copyright (C) 1996-1998, 2000-2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _PT_MACHINE_H +#define _PT_MACHINE_H 1 + +#ifndef PT_EI +# define PT_EI __extern_always_inline +#endif + +extern long int testandset (int *spinlock); +extern int __compare_and_swap (long int *p, long int oldval, long int newval); + +/* Spinlock implementation; required. */ +PT_EI long int +testandset (int *spinlock) +{ + int ret; + + __asm__ __volatile__("ldstub %1,%0" + : "=r"(ret), "=m"(*spinlock) + : "m"(*spinlock)); + + return ret; +} + + +/* Memory barrier; default is to do nothing */ +#define MEMORY_BARRIER() __asm__ __volatile__("stbar" : : : "memory") + + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#define CURRENT_STACK_FRAME (stack_pointer + (2 * 64)) +register char *stack_pointer __asm__("%sp"); + + +/* Registers %g6 and %g7 are reserved by the ABI for "system use". + %g7 is specified in the TLS ABI as thread pointer -- we do the same. */ +struct _pthread_descr_struct; +register struct _pthread_descr_struct *__thread_self __asm__("%g7"); + +#ifdef not_for_l4 +/* Return the thread descriptor for the current thread. */ +#define THREAD_SELF __thread_self + +/* Initialize the thread-unique value. */ +#define INIT_THREAD_SELF(descr, nr) (__thread_self = (descr)) + +/* Access to data in the thread descriptor is easy. */ +#define THREAD_GETMEM(descr, member) \ + ((void) sizeof (descr), THREAD_SELF->member) +#define THREAD_GETMEM_NC(descr, member) \ + ((void) sizeof (descr), THREAD_SELF->member) +#define THREAD_SETMEM(descr, member, value) \ + ((void) sizeof (descr), THREAD_SELF->member = (value)) +#define THREAD_SETMEM_NC(descr, member, value) \ + ((void) sizeof (descr), THREAD_SELF->member = (value)) +#endif + +/* We want the OS to assign stack addresses. */ +#define FLOATING_STACKS 1 + +/* Maximum size of the stack if the rlimit is unlimited. */ +#define ARCH_STACK_MAX_SIZE 8*1024*1024 + +#endif /* pt-machine.h */ diff --git a/l4/pkg/uclibc/lib/libpthread/src/sysdeps/sparc/sparc64/pt-machine.h b/l4/pkg/uclibc/lib/libpthread/src/sysdeps/sparc/sparc64/pt-machine.h new file mode 100644 index 00000000..815d70e8 --- /dev/null +++ b/l4/pkg/uclibc/lib/libpthread/src/sysdeps/sparc/sparc64/pt-machine.h @@ -0,0 +1,105 @@ +/* Machine-dependent pthreads configuration and inline functions. + Sparc v9 version. + Copyright (C) 1997-2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Richard Henderson . + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If + not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef _PT_MACHINE_H +#define _PT_MACHINE_H 1 + +#ifndef PT_EI +# define PT_EI __extern_always_inline +#endif + +extern long int testandset (int *spinlock); +extern int __compare_and_swap (long int *p, long int oldval, long int newval); + +/* Spinlock implementation; required. */ +PT_EI long int +testandset (int *spinlock) +{ + int ret; + + __asm__ __volatile__("ldstub %1,%0" + : "=r" (ret), "=m" (*spinlock) : "m" (*spinlock)); + + return ret; +} + + +/* Memory barrier; default is to do nothing */ +#define MEMORY_BARRIER() \ + __asm__ __volatile__("membar #LoadLoad | #LoadStore | #StoreLoad | #StoreStore" : : : "memory") +/* Read barrier. */ +#define READ_MEMORY_BARRIER() \ + __asm__ __volatile__("membar #LoadLoad | #LoadStore" : : : "memory") +/* Write barrier. */ +#define WRITE_MEMORY_BARRIER() \ + __asm__ __volatile__("membar #StoreLoad | #StoreStore" : : : "memory") + + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +#define CURRENT_STACK_FRAME (stack_pointer + (2 * 128)) +register char *stack_pointer __asm__ ("%sp"); + + +/* Registers %g6 and %g7 are reserved by the ABI for "system use". The + TLS ABI specifies %g7 as the thread pointer. */ +struct _pthread_descr_struct; +register struct _pthread_descr_struct *__thread_self __asm__ ("%g7"); + +/* Return the thread descriptor for the current thread. */ +#define THREAD_SELF __thread_self + +/* Initialize the thread-unique value. */ +#define INIT_THREAD_SELF(descr, nr) (__thread_self = (descr)) + + +/* Compare-and-swap for semaphores. */ + +#define HAS_COMPARE_AND_SWAP +PT_EI int +__compare_and_swap (long int *p, long int oldval, long int newval) +{ + long int readval; + + __asm__ __volatile__ ("casx [%4], %2, %0" + : "=r"(readval), "=m"(*p) + : "r"(oldval), "m"(*p), "r"(p), "0"(newval)); + MEMORY_BARRIER(); + return readval == oldval; +} + +/* Access to data in the thread descriptor is easy. */ +#define THREAD_GETMEM(descr, member) \ + ((void) sizeof (descr), THREAD_SELF->member) +#define THREAD_GETMEM_NC(descr, member) \ + ((void) sizeof (descr), THREAD_SELF->member) +#define THREAD_SETMEM(descr, member, value) \ + ((void) sizeof (descr), THREAD_SELF->member = (value)) +#define THREAD_SETMEM_NC(descr, member, value) \ + ((void) sizeof (descr), THREAD_SELF->member = (value)) + +/* We want the OS to assign stack addresses. */ +#define FLOATING_STACKS 1 + +/* Maximum size of the stack if the rlimit is unlimited. */ +#define ARCH_STACK_MAX_SIZE 32*1024*1024 + +#endif /* pt-machine.h */ diff --git a/l4/pkg/uclibc/lib/libpthread/src/sysdeps/sparc/tls.h b/l4/pkg/uclibc/lib/libpthread/src/sysdeps/sparc/tls.h new file mode 100644 index 00000000..61c3c74b --- /dev/null +++ b/l4/pkg/uclibc/lib/libpthread/src/sysdeps/sparc/tls.h @@ -0,0 +1,182 @@ +/* Definitions for thread-local data handling. NPTL/sparc version. + Copyright (C) 2003, 2005, 2006, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _TLS_H +#define _TLS_H +#ifndef __ASSEMBLER__ +# include +# include +# include +# include +//# include +# include + +/* Type for the dtv. */ +typedef union dtv +{ + size_t counter; + struct + { + void *val; + bool is_static; + } pointer; +} dtv_t; + +typedef struct +{ + void *tcb; /* Pointer to the TCB. Not necessary the + thread descriptor used by libpthread. */ + dtv_t *dtv; + void *self; + int multiple_threads; +#if __WORDSIZE == 64 + int gscope_flag; +#endif + uintptr_t sysinfo; + uintptr_t stack_guard; + uintptr_t pointer_guard; +#if __WORDSIZE != 64 + int gscope_flag; +#endif +#ifndef __ASSUME_PRIVATE_FUTEX + int private_futex; +#endif +} tcbhead_t; + +#else /* __ASSEMBLER__ */ +# include +#endif /* __ASSEMBLER__ */ + +/* We require TLS support in the tools. */ +#define HAVE_TLS_SUPPORT +#define HAVE___THREAD 1 +#define HAVE_TLS_MODEL_ATTRIBUTE 1 + +/* Signal that TLS support is available. */ +#define USE_TLS 1 + +#ifndef __ASSEMBLER__ +/* Get system call information. */ +//al//# include + +/* Get the thread descriptor definition. */ +# include + +// al -- uhh... +#define pthread _pthread_descr_struct + +//al//register struct pthread *__thread_self __asm__("%g7"); + +/* This is the size of the initial TCB. Can't be just sizeof (tcbhead_t), + because NPTL getpid, __libc_alloca_cutoff etc. need (almost) the whole + struct pthread even when not linked with -lpthread. */ +# define TLS_INIT_TCB_SIZE sizeof (struct pthread) + +/* Alignment requirements for the initial TCB. */ +# define TLS_INIT_TCB_ALIGN __alignof__ (struct pthread) + +/* This is the size of the TCB. */ +# define TLS_TCB_SIZE sizeof (struct pthread) + +/* Alignment requirements for the TCB. */ +# define TLS_TCB_ALIGN __alignof__ (struct pthread) + +/* The TCB can have any size and the memory following the address the + thread pointer points to is unspecified. Allocate the TCB there. */ +# define TLS_TCB_AT_TP 1 + +/* Install the dtv pointer. The pointer passed is to the element with + index -1 which contain the length. */ +# define INSTALL_DTV(descr, dtvp) \ + ((tcbhead_t *) (descr))->dtv = (dtvp) + 1 + +/* Install new dtv for current thread. */ +# define INSTALL_NEW_DTV(DTV) \ + (((tcbhead_t *) __thread_self)->dtv = (DTV)) + +/* Return dtv of given thread descriptor. */ +# define GET_DTV(descr) \ + (((tcbhead_t *) (descr))->dtv) + +/* Code to initially initialize the thread pointer. */ +# define TLS_INIT_TP(descr, secondcall) \ + ({ __thread_self = (__typeof (__thread_self)) (descr); (char *)0; }) + +/* Return the address of the dtv for the current thread. */ +# define THREAD_DTV() \ + (((tcbhead_t *) __thread_self)->dtv) + +/* Return the thread descriptor for the current thread. */ +#define THREAD_SELF __thread_self + +/* Magic for libthread_db to know how to do THREAD_SELF. */ +# define DB_THREAD_SELF_INCLUDE +# define DB_THREAD_SELF \ + REGISTER (32, 32, REG_G7 * 4, 0) REGISTER (64, 64, REG_G7 * 8, 0) + +/* Access to data in the thread descriptor is easy. */ +#define THREAD_GETMEM(descr, member) \ + descr->member +#define THREAD_GETMEM_NC(descr, member, idx) \ + descr->member[idx] +#define THREAD_SETMEM(descr, member, value) \ + descr->member = (value) +#define THREAD_SETMEM_NC(descr, member, idx, value) \ + descr->member[idx] = (value) + +/* Set the stack guard field in TCB head. */ +#define THREAD_SET_STACK_GUARD(value) \ + THREAD_SETMEM (THREAD_SELF, header.stack_guard, value) +# define THREAD_COPY_STACK_GUARD(descr) \ + ((descr)->header.stack_guard \ + = THREAD_GETMEM (THREAD_SELF, header.stack_guard)) + +/* Get/set the stack guard field in TCB head. */ +#define THREAD_GET_POINTER_GUARD() \ + THREAD_GETMEM (THREAD_SELF, header.pointer_guard) +#define THREAD_SET_POINTER_GUARD(value) \ + THREAD_SETMEM (THREAD_SELF, header.pointer_guard, value) +# define THREAD_COPY_POINTER_GUARD(descr) \ + ((descr)->header.pointer_guard = THREAD_GET_POINTER_GUARD ()) + +/* Get and set the global scope generation counter in struct pthread. */ +#define THREAD_GSCOPE_FLAG_UNUSED 0 +#define THREAD_GSCOPE_FLAG_USED 1 +#define THREAD_GSCOPE_FLAG_WAIT 2 +#define THREAD_GSCOPE_RESET_FLAG() \ + do \ + { int __res \ + = atomic_exchange_rel (&THREAD_SELF->header.gscope_flag, \ + THREAD_GSCOPE_FLAG_UNUSED); \ + if (__res == THREAD_GSCOPE_FLAG_WAIT) \ + lll_futex_wake (&THREAD_SELF->header.gscope_flag, 1, LLL_PRIVATE); \ + } \ + while (0) +#define THREAD_GSCOPE_SET_FLAG() \ + do \ + { \ + THREAD_SELF->header.gscope_flag = THREAD_GSCOPE_FLAG_USED; \ + atomic_write_barrier (); \ + } \ + while (0) +#define THREAD_GSCOPE_WAIT() \ + GL(dl_wait_lookup_done) () + +#endif /* !ASSEMBLER */ +#endif /* tls.h */ diff --git a/l4/pkg/uclibc/lib/libpthread/src/sysdeps/x86_64/dl-tls.h b/l4/pkg/uclibc/lib/libpthread/src/sysdeps/x86_64/dl-tls.h new file mode 100644 index 00000000..3e4768dc --- /dev/null +++ b/l4/pkg/uclibc/lib/libpthread/src/sysdeps/x86_64/dl-tls.h @@ -0,0 +1,29 @@ +/* Thread-local storage handling in the ELF dynamic linker. x86-64 version. + Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + + +/* Type used for the representation of TLS information in the GOT. */ +typedef struct +{ + unsigned long int ti_module; + unsigned long int ti_offset; +} tls_index; + + +extern void *__tls_get_addr (tls_index *ti); diff --git a/l4/pkg/uclibc/lib/libpthread/src/sysdeps/x86_64/pt-machine.h b/l4/pkg/uclibc/lib/libpthread/src/sysdeps/x86_64/pt-machine.h new file mode 100644 index 00000000..fe28c4e8 --- /dev/null +++ b/l4/pkg/uclibc/lib/libpthread/src/sysdeps/x86_64/pt-machine.h @@ -0,0 +1,228 @@ +/* Machine-dependent pthreads configuration and inline functions. + x86-64 version. + Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _PT_MACHINE_H +#define _PT_MACHINE_H 1 + +# include + +#ifndef __ASSEMBLER__ +# include /* For offsetof. */ +# include /* For abort(). */ +//# include + + +# ifndef PT_EI +# define PT_EI __extern_always_inline +# endif + +/* Get some notion of the current stack. Need not be exactly the top + of the stack, just something somewhere in the current frame. */ +# define CURRENT_STACK_FRAME stack_pointer +register char * stack_pointer __asm__ ("%rsp") __attribute_used__; + + +/* Spinlock implementation; required. */ +PT_EI long int +testandset (int *spinlock) +{ + long int ret; + + __asm__ __volatile__ ( + "xchgl %k0, %1" + : "=r"(ret), "=m"(*spinlock) + : "0"(1), "m"(*spinlock) + : "memory"); + + return ret; +} + + +/* Compare-and-swap for semaphores. */ +# define HAS_COMPARE_AND_SWAP + +PT_EI int +__compare_and_swap (long int *p, long int oldval, long int newval) +{ + char ret; + long int readval; + + __asm__ __volatile__ ("lock; cmpxchgq %3, %1; sete %0" + : "=q" (ret), "=m" (*p), "=a" (readval) + : "r" (newval), "m" (*p), "a" (oldval) + : "memory"); + return ret; +} + +/* Return the thread descriptor for the current thread. + + The contained asm must *not* be marked volatile since otherwise + assignments like + pthread_descr self = thread_self(); + do not get optimized away. */ +#ifdef NOT_FOR_L4 +# define THREAD_SELF \ +({ \ + register pthread_descr __self; \ + __asm__ ("movq %%fs:%c1,%0" : "=r" (__self) \ + : "i" (offsetof (struct _pthread_descr_struct, \ + p_header.data.self))); \ + __self; \ +}) + +/* Prototype for the system call. */ +extern int arch_prctl (int __code, unsigned long __addr); + +/* Initialize the thread-unique value. */ +# define INIT_THREAD_SELF(descr, nr) \ +{ \ + if (arch_prctl (ARCH_SET_FS, (unsigned long)descr) != 0) \ + abort (); \ +} + +/* Read member of the thread descriptor directly. */ +# define THREAD_GETMEM(descr, member) \ +({ \ + __typeof__ (descr->member) __value; \ + if (sizeof (__value) == 1) \ + __asm__ __volatile__ ("movb %%fs:%P2,%b0" \ + : "=q" (__value) \ + : "0" (0), \ + "i" (offsetof (struct _pthread_descr_struct, \ + member))); \ + else if (sizeof (__value) == 4) \ + __asm__ __volatile__ ("movl %%fs:%P2,%k0" \ + : "=r" (__value) \ + : "0" (0), \ + "i" (offsetof (struct _pthread_descr_struct, \ + member))); \ + else \ + { \ + if (sizeof (__value) != 8) \ + /* There should not be any value with a size other than 1, 4 or 8. */\ + abort (); \ + \ + __asm__ __volatile__ ("movq %%fs:%P1,%0" \ + : "=r" (__value) \ + : "i" (offsetof (struct _pthread_descr_struct, \ + member))); \ + } \ + __value; \ +}) + +/* Same as THREAD_GETMEM, but the member offset can be non-constant. */ +# define THREAD_GETMEM_NC(descr, member) \ +({ \ + __typeof__ (descr->member) __value; \ + if (sizeof (__value) == 1) \ + __asm__ __volatile__ ("movb %%fs:(%2),%b0" \ + : "=q" (__value) \ + : "0" (0), \ + "r" (offsetof (struct _pthread_descr_struct, \ + member))); \ + else if (sizeof (__value) == 4) \ + __asm__ __volatile__ ("movl %%fs:(%2),%k0" \ + : "=r" (__value) \ + : "0" (0), \ + "r" (offsetof (struct _pthread_descr_struct, \ + member))); \ + else \ + { \ + if (sizeof (__value) != 8) \ + /* There should not be any value with a size other than 1, 4 or 8. */\ + abort (); \ + \ + __asm__ __volatile__ ("movq %%fs:(%1),%0" \ + : "=r" (__value) \ + : "r" (offsetof (struct _pthread_descr_struct, \ + member))); \ + } \ + __value; \ +}) + +/* Set member of the thread descriptor directly. */ +# define THREAD_SETMEM(descr, member, value) \ +({ \ + __typeof__ (descr->member) __value = (value); \ + if (sizeof (__value) == 1) \ + __asm__ __volatile__ ("movb %0,%%fs:%P1" : \ + : "q" (__value), \ + "i" (offsetof (struct _pthread_descr_struct, \ + member))); \ + else if (sizeof (__value) == 4) \ + __asm__ __volatile__ ("movl %k0,%%fs:%P1" : \ + : "r" (__value), \ + "i" (offsetof (struct _pthread_descr_struct, \ + member))); \ + else \ + { \ + if (sizeof (__value) != 8) \ + /* There should not be any value with a size other than 1, 4 or 8. */\ + abort (); \ + \ + __asm__ __volatile__ ("movq %0,%%fs:%P1" : \ + : "r" (__value), \ + "i" (offsetof (struct _pthread_descr_struct, \ + member))); \ + } \ +}) + +/* Same as THREAD_SETMEM, but the member offset can be non-constant. */ +# define THREAD_SETMEM_NC(descr, member, value) \ +({ \ + __typeof__ (descr->member) __value = (value); \ + if (sizeof (__value) == 1) \ + __asm__ __volatile__ ("movb %0,%%fs:(%1)" : \ + : "q" (__value), \ + "r" (offsetof (struct _pthread_descr_struct, \ + member))); \ + else if (sizeof (__value) == 4) \ + __asm__ __volatile__ ("movl %k0,%%fs:(%1)" : \ + : "r" (__value), \ + "r" (offsetof (struct _pthread_descr_struct, \ + member))); \ + else \ + { \ + if (sizeof (__value) != 8) \ + /* There should not be any value with a size other than 1, 4 or 8. */\ + abort (); \ + \ + __asm__ __volatile__ ("movq %0,%%fs:(%1)" : \ + : "r" (__value), \ + "r" (offsetof (struct _pthread_descr_struct, \ + member))); \ + } \ +}) + +#endif /* NOT_FOR_L4 */ + + +#endif /* !__ASSEMBLER__ */ + +/* We want the OS to assign stack addresses. */ +#define FLOATING_STACKS 1 + +/* Maximum size of the stack if the rlimit is unlimited. */ +#define ARCH_STACK_MAX_SIZE 32*1024*1024 + +/* The ia32e really want some help to prevent overheating. */ +#define BUSY_WAIT_NOP __asm__ ("rep; nop") + +#endif /* pt-machine.h */ diff --git a/l4/pkg/uclibc/lib/libpthread/src/sysdeps/x86_64/sysdep-cancel.h b/l4/pkg/uclibc/lib/libpthread/src/sysdeps/x86_64/sysdep-cancel.h new file mode 100644 index 00000000..21e8eb2d --- /dev/null +++ b/l4/pkg/uclibc/lib/libpthread/src/sysdeps/x86_64/sysdep-cancel.h @@ -0,0 +1,131 @@ +/* Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#ifndef __ASSEMBLER__ +# include +#endif + +#if !defined NOT_IN_libc || defined IS_IN_libpthread || defined IS_IN_librt + +# undef PSEUDO +# define PSEUDO(name, syscall_name, args) \ + .text; \ + ENTRY (name) \ + SINGLE_THREAD_P; \ + jne L(pseudo_cancel); \ + DO_CALL (syscall_name, args); \ + cmpq $-4095, %rax; \ + jae SYSCALL_ERROR_LABEL; \ + ret; \ + L(pseudo_cancel): \ + /* Save registers that might get destroyed. */ \ + SAVESTK_##args \ + PUSHARGS_##args \ + CENABLE \ + /* Restore registers. */ \ + POPARGS_##args \ + /* The return value from CENABLE is argument for CDISABLE. */ \ + movq %rax, (%rsp); \ + movl $SYS_ify (syscall_name), %eax; \ + syscall; \ + movq (%rsp), %rdi; \ + /* Save %rax since it's the error code from the syscall. */ \ + movq %rax, 8(%rsp); \ + CDISABLE \ + movq 8(%rsp), %rax; \ + RESTSTK_##args \ + cmpq $-4095, %rax; \ + jae SYSCALL_ERROR_LABEL; \ + L(pseudo_end): + +# define PUSHARGS_0 /* Nothing. */ +# define PUSHARGS_1 PUSHARGS_0 movq %rdi, 8(%rsp); +# define PUSHARGS_2 PUSHARGS_1 movq %rsi, 16(%rsp); +# define PUSHARGS_3 PUSHARGS_2 movq %rdx, 24(%rsp); +# define PUSHARGS_4 PUSHARGS_3 movq %rcx, 32(%rsp); +# define PUSHARGS_5 PUSHARGS_4 movq %r8, 40(%rsp); +# define PUSHARGS_6 PUSHARGS_5 movq %r9, 48(%rsp); + +# define POPARGS_0 /* Nothing. */ +# define POPARGS_1 POPARGS_0 movq 8(%rsp), %rdi; +# define POPARGS_2 POPARGS_1 movq 16(%rsp), %rsi; +# define POPARGS_3 POPARGS_2 movq 24(%rsp), %rdx; +# define POPARGS_4 POPARGS_3 movq 32(%rsp), %r10; +# define POPARGS_5 POPARGS_4 movq 40(%rsp), %r8; +# define POPARGS_6 POPARGS_5 movq 48(%rsp), %r9; + +/* We always have to align the stack before calling a function. */ +# define SAVESTK_0 subq $24, %rsp;cfi_adjust_cfa_offset(24); +# define SAVESTK_1 SAVESTK_0 +# define SAVESTK_2 SAVESTK_1 +# define SAVESTK_3 subq $40, %rsp;cfi_adjust_cfa_offset(40); +# define SAVESTK_4 SAVESTK_3 +# define SAVESTK_5 subq $56, %rsp;cfi_adjust_cfa_offset(56); +# define SAVESTK_6 SAVESTK_5 + +# define RESTSTK_0 addq $24,%rsp;cfi_adjust_cfa_offset(-24); +# define RESTSTK_1 RESTSTK_0 +# define RESTSTK_2 RESTSTK_1 +# define RESTSTK_3 addq $40, %rsp;cfi_adjust_cfa_offset(-40); +# define RESTSTK_4 RESTSTK_3 +# define RESTSTK_5 addq $56, %rsp;cfi_adjust_cfa_offset(-56); +# define RESTSTK_6 RESTSTK_5 + +# ifdef IS_IN_libpthread +# define CENABLE call __pthread_enable_asynccancel; +# define CDISABLE call __pthread_disable_asynccancel; +# define __local_multiple_threads __pthread_multiple_threads +# elif !defined NOT_IN_libc +# define CENABLE call __libc_enable_asynccancel; +# define CDISABLE call __libc_disable_asynccancel; +# define __local_multiple_threads __libc_multiple_threads +# else +# define CENABLE call __librt_enable_asynccancel@plt; +# define CDISABLE call __librt_disable_asynccancel@plt; +# endif + +# if defined IS_IN_libpthread || !defined NOT_IN_libc +# ifndef __ASSEMBLER__ +extern int __local_multiple_threads attribute_hidden; +# define SINGLE_THREAD_P \ + __builtin_expect (__local_multiple_threads == 0, 1) +# else +# define SINGLE_THREAD_P cmpl $0, __local_multiple_threads(%rip) +# endif + +# else + +# ifndef __ASSEMBLER__ +# define SINGLE_THREAD_P \ + __builtin_expect (THREAD_GETMEM (THREAD_SELF, \ + p_header.data.multiple_threads) == 0, 1) +# else +# define SINGLE_THREAD_P cmpl $0, %fs:MULTIPLE_THREADS_OFFSET +# endif + +# endif + +#elif !defined __ASSEMBLER__ + +/* This code should never be used but we define it anyhow. */ +# define SINGLE_THREAD_P (1) + +#endif diff --git a/l4/pkg/uclibc/lib/libpthread/src/sysdeps/x86_64/tls.h b/l4/pkg/uclibc/lib/libpthread/src/sysdeps/x86_64/tls.h new file mode 100644 index 00000000..5c0feec5 --- /dev/null +++ b/l4/pkg/uclibc/lib/libpthread/src/sysdeps/x86_64/tls.h @@ -0,0 +1,463 @@ +/* Definition for thread-local data handling. nptl/x86_64 version. + Copyright (C) 2002-2007, 2008, 2009 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _TLS_H +#define _TLS_H 1 +#ifndef __ASSEMBLER__ +//l4/# include /* For ARCH_SET_FS. */ +# include +# include +# include +# include +//l4/# include +# include +# include +# include + + +/* Type for the dtv. */ +typedef union dtv +{ + size_t counter; + struct + { + void *val; + bool is_static; + } pointer; +} dtv_t; + + +typedef struct +{ + void *tcb; /* Pointer to the TCB. Not necessarily the + thread descriptor used by libpthread. */ + dtv_t *dtv; + void *self; /* Pointer to the thread descriptor. */ + int multiple_threads; + int gscope_flag; + uintptr_t sysinfo; + uintptr_t stack_guard; + uintptr_t pointer_guard; + unsigned long int vgetcpu_cache[2]; +# ifndef __ASSUME_PRIVATE_FUTEX + int private_futex; +# else + int __unused1; +# endif +# if __WORDSIZE == 64 + int rtld_must_xmm_save; +# endif + /* Reservation of some values for the TM ABI. */ + void *__private_tm[5]; +# if __WORDSIZE == 64 + long int __unused2; + /* Have space for the post-AVX register size. */ + __m128 rtld_savespace_sse[8][4]; + + void *__padding[8]; +# endif +} tcbhead_t; + +#else /* __ASSEMBLER__ */ +# include +#endif + + +/* We require TLS support in the tools. */ +#define HAVE_TLS_SUPPORT 1 +#define HAVE___THREAD 1 +#define HAVE_TLS_MODEL_ATTRIBUTE 1 + +/* Signal that TLS support is available. */ +#define USE_TLS 1 + +/* Alignment requirement for the stack. */ +#define STACK_ALIGN 16 + + +#ifndef __ASSEMBLER__ +/* Get system call information. */ +//l4/# include + + +/* Get the thread descriptor definition. */ +# include +# include +# include + +#ifndef LOCK_PREFIX +# ifdef UP +# define LOCK_PREFIX /* nothing */ +# else +# define LOCK_PREFIX "lock;" +# endif +#endif + +/* This is the size of the initial TCB. Can't be just sizeof (tcbhead_t), + because NPTL getpid, __libc_alloca_cutoff etc. need (almost) the whole + struct pthread even when not linked with -lpthread. */ +# define TLS_INIT_TCB_SIZE sizeof (struct _pthread_descr_struct) + +/* Alignment requirements for the initial TCB. */ +# define TLS_INIT_TCB_ALIGN __alignof__ (struct _pthread_descr_struct) + +/* This is the size of the TCB. */ +# define TLS_TCB_SIZE sizeof (struct _pthread_descr_struct) + +/* Alignment requirements for the TCB. */ +//# define TLS_TCB_ALIGN __alignof__ (struct pthread) +// Normally the above would be correct But we have to store post-AVX +// vector registers in the TCB and we want the storage to be aligned. +// unfortunately there isn't yet a type for these values and hence no +// 32-byte alignment requirement. Make this explicit, for now. +# define TLS_TCB_ALIGN 32 + +/* The TCB can have any size and the memory following the address the + thread pointer points to is unspecified. Allocate the TCB there. */ +# define TLS_TCB_AT_TP 1 + + +/* Install the dtv pointer. The pointer passed is to the element with + index -1 which contain the length. */ +# define INSTALL_DTV(descr, dtvp) \ + ((tcbhead_t *) (descr))->dtv = (dtvp) + 1 + +/* Install new dtv for current thread. */ +# define INSTALL_NEW_DTV_ORIG(dtvp) \ + ({ struct pthread *__pd; \ + THREAD_SETMEM (__pd, header.dtv, (dtvp)); }) +# define INSTALL_NEW_DTV(dtvpx) \ + ({ struct _pthread_descr_struct *__pd; \ + THREAD_SETMEM (__pd, p_header.data.dtvp, (dtvpx)); }) + +/* Return dtv of given thread descriptor. */ +# define GET_DTV(descr) \ + (((tcbhead_t *) (descr))->dtv) + + +/* Macros to load from and store into segment registers. */ +# define TLS_GET_FS() \ + ({ int __seg; __asm__ ("movl %%fs, %0" : "=q" (__seg)); __seg; }) +# define TLS_SET_FS(val) \ + __asm__ ("movl %0, %%fs" :: "q" (val)) + + +static inline char const *TLS_INIT_TP(void *thrdescr, int secondcall) +{ + (void)secondcall; + tcbhead_t *_head = (tcbhead_t *)thrdescr; + _head->tcb = thrdescr; + _head->self = thrdescr; + if (fiasco_amd64_set_fs(L4_INVALID_CAP, (l4_umword_t)thrdescr, l4_utcb()) < 0) + return "ERROR"; + + return NULL; +} +#if 0 +/* Code to initially initialize the thread pointer. This might need + special attention since 'errno' is not yet available and if the + operation can cause a failure 'errno' must not be touched. + + We have to make the syscall for both uses of the macro since the + address might be (and probably is) different. */ +# define TLS_INIT_TP(thrdescr, secondcall) \ + ({ void *_thrdescr = (thrdescr); \ + tcbhead_t *_head = _thrdescr; \ + int _result; \ + \ + _head->tcb = _thrdescr; \ + /* For now the thread descriptor is at the same address. */ \ + _head->self = _thrdescr; \ + \ + /* It is a simple syscall to set the %fs value for the thread. */ \ + __asm__ __volatile__ ("syscall" \ + : "=a" (_result) \ + : "0" ((unsigned long int) __NR_arch_prctl), \ + "D" ((unsigned long int) ARCH_SET_FS), \ + "S" (_thrdescr) \ + : "memory", "cc", "r11", "cx"); \ + \ + _result ? "cannot set %fs base address for thread-local storage" : 0; \ + }) +#endif + + +/* Return the address of the dtv for the current thread. */ +# define THREAD_DTV_ORIG() \ + ({ struct pthread *__pd; \ + THREAD_GETMEM (__pd, header.dtv); }) + +# define THREAD_DTV() \ + ({ struct _pthread_descr_struct *__pd; \ + THREAD_GETMEM (__pd, p_header.data.dtvp); }) + + +/* Return the thread descriptor for the current thread. + + The contained asm must *not* be marked __volatile__ since otherwise + assignments like + pthread_descr self = thread_self(); + do not get optimized away. */ +# define THREAD_SELF_ORIG \ + ({ struct pthread *__self; \ + __asm__ ("movq %%fs:%c1,%q0" : "=r" (__self) \ + : "i" (offsetof (struct pthread, header.self))); \ + __self;}) +# define THREAD_SELF \ + ({ struct _pthread_descr_struct *__self; \ + __asm__ ("movq %%fs:%c1,%q0" : "=r" (__self) \ + : "i" (offsetof (struct _pthread_descr_struct, p_header.data.self))); \ + __self;}) + +/* Magic for libthread_db to know how to do THREAD_SELF. */ +# define DB_THREAD_SELF_INCLUDE /* For the FS constant. */ +# define DB_THREAD_SELF CONST_THREAD_AREA (64, FS) + +/* Read member of the thread descriptor directly. */ +# define THREAD_GETMEM(descr, member) \ + ({ __typeof (descr->member) __value; \ + if (sizeof (__value) == 1) \ + __asm__ __volatile__ ("movb %%fs:%P2,%b0" \ + : "=q" (__value) \ + : "0" (0), "i" (offsetof (struct _pthread_descr_struct, member))); \ + else if (sizeof (__value) == 4) \ + __asm__ __volatile__ ("movl %%fs:%P1,%0" \ + : "=r" (__value) \ + : "i" (offsetof (struct _pthread_descr_struct, member))); \ + else \ + { \ + if (sizeof (__value) != 8) \ + /* There should not be any value with a size other than 1, \ + 4 or 8. */ \ + abort (); \ + \ + __asm__ __volatile__ ("movq %%fs:%P1,%q0" \ + : "=r" (__value) \ + : "i" (offsetof (struct _pthread_descr_struct, member))); \ + } \ + __value; }) + + +/* Same as THREAD_GETMEM, but the member offset can be non-constant. */ +# define THREAD_GETMEM_NC(descr, member, idx) \ + ({ __typeof (descr->member[0]) __value; \ + if (sizeof (__value) == 1) \ + __asm__ __volatile__ ("movb %%fs:%P2(%q3),%b0" \ + : "=q" (__value) \ + : "0" (0), "i" (offsetof (struct _pthread_descr_struct, member[0])), \ + "r" (idx)); \ + else if (sizeof (__value) == 4) \ + __asm__ __volatile__ ("movl %%fs:%P1(,%q2,4),%0" \ + : "=r" (__value) \ + : "i" (offsetof (struct _pthread_descr_struct, member[0])), "r" (idx));\ + else \ + { \ + if (sizeof (__value) != 8) \ + /* There should not be any value with a size other than 1, \ + 4 or 8. */ \ + abort (); \ + \ + __asm__ __volatile__ ("movq %%fs:%P1(,%q2,8),%q0" \ + : "=r" (__value) \ + : "i" (offsetof (struct _pthread_descr_struct, member[0])), \ + "r" (idx)); \ + } \ + __value; }) + + +/* Loading addresses of objects on x86-64 needs to be treated special + when generating PIC code. */ +#ifdef __pic__ +# define IMM_MODE "nr" +#else +# define IMM_MODE "ir" +#endif + + +/* Same as THREAD_SETMEM, but the member offset can be non-constant. */ +# define THREAD_SETMEM(descr, member, value) \ + ({ if (sizeof (descr->member) == 1) \ + __asm__ __volatile__ ("movb %b0,%%fs:%P1" : \ + : "iq" (value), \ + "i" (offsetof (struct _pthread_descr_struct, member))); \ + else if (sizeof (descr->member) == 4) \ + __asm__ __volatile__ ("movl %0,%%fs:%P1" : \ + : IMM_MODE (value), \ + "i" (offsetof (struct _pthread_descr_struct, member))); \ + else \ + { \ + if (sizeof (descr->member) != 8) \ + /* There should not be any value with a size other than 1, \ + 4 or 8. */ \ + abort (); \ + \ + __asm__ __volatile__ ("movq %q0,%%fs:%P1" : \ + : IMM_MODE ((unsigned long int) value), \ + "i" (offsetof (struct _pthread_descr_struct, member))); \ + }}) + + +/* Set member of the thread descriptor directly. */ +# define THREAD_SETMEM_NC(descr, member, idx, value) \ + ({ if (sizeof (descr->member[0]) == 1) \ + __asm__ __volatile__ ("movb %b0,%%fs:%P1(%q2)" : \ + : "iq" (value), \ + "i" (offsetof (struct _pthread_descr_struct, member[0])), \ + "r" (idx)); \ + else if (sizeof (descr->member[0]) == 4) \ + __asm__ __volatile__ ("movl %0,%%fs:%P1(,%q2,4)" : \ + : IMM_MODE (value), \ + "i" (offsetof (struct _pthread_descr_struct, member[0])), \ + "r" (idx)); \ + else \ + { \ + if (sizeof (descr->member[0]) != 8) \ + /* There should not be any value with a size other than 1, \ + 4 or 8. */ \ + abort (); \ + \ + __asm__ __volatile__ ("movq %q0,%%fs:%P1(,%q2,8)" : \ + : IMM_MODE ((unsigned long int) value), \ + "i" (offsetof (struct _pthread_descr_struct, member[0])), \ + "r" (idx)); \ + }}) + + +/* Atomic compare and exchange on TLS, returning old value. */ +# define THREAD_ATOMIC_CMPXCHG_VAL(descr, member, newval, oldval) \ + ({ __typeof (descr->member) __ret; \ + __typeof (oldval) __old = (oldval); \ + if (sizeof (descr->member) == 4) \ + __asm__ __volatile__ (LOCK_PREFIX "cmpxchgl %2, %%fs:%P3" \ + : "=a" (__ret) \ + : "0" (__old), "r" (newval), \ + "i" (offsetof (struct pthread, member))); \ + else \ + /* Not necessary for other sizes in the moment. */ \ + abort (); \ + __ret; }) + + +/* Atomic logical and. */ +# define THREAD_ATOMIC_AND(descr, member, val) \ + (void) ({ if (sizeof ((descr)->member) == 4) \ + __asm__ __volatile__ (LOCK_PREFIX "andl %1, %%fs:%P0" \ + :: "i" (offsetof (struct pthread, member)), \ + "ir" (val)); \ + else \ + /* Not necessary for other sizes in the moment. */ \ + abort (); }) + + +/* Atomic set bit. */ +# define THREAD_ATOMIC_BIT_SET(descr, member, bit) \ + (void) ({ if (sizeof ((descr)->member) == 4) \ + __asm__ __volatile__ (LOCK_PREFIX "orl %1, %%fs:%P0" \ + :: "i" (offsetof (struct pthread, member)), \ + "ir" (1 << (bit))); \ + else \ + /* Not necessary for other sizes in the moment. */ \ + abort (); }) + + +# define CALL_THREAD_FCT(descr) \ + ({ void *__res; \ + __asm__ __volatile__ ("movq %%fs:%P2, %%rdi\n\t" \ + "callq *%%fs:%P1" \ + : "=a" (__res) \ + : "i" (offsetof (struct pthread, start_routine)), \ + "i" (offsetof (struct pthread, arg)) \ + : "di", "si", "cx", "dx", "r8", "r9", "r10", "r11", \ + "memory", "cc"); \ + __res; }) + + +/* Set the stack guard field in TCB head. */ +# define THREAD_SET_STACK_GUARD(value) \ + THREAD_SETMEM (THREAD_SELF, header.stack_guard, value) +# define THREAD_COPY_STACK_GUARD(descr) \ + ((descr)->header.stack_guard \ + = THREAD_GETMEM (THREAD_SELF, header.stack_guard)) + + +/* Set the pointer guard field in the TCB head. */ +# define THREAD_SET_POINTER_GUARD(value) \ + THREAD_SETMEM (THREAD_SELF, header.pointer_guard, value) +# define THREAD_COPY_POINTER_GUARD(descr) \ + ((descr)->header.pointer_guard \ + = THREAD_GETMEM (THREAD_SELF, header.pointer_guard)) + + +/* Get and set the global scope generation counter in the TCB head. */ +# define THREAD_GSCOPE_FLAG_UNUSED 0 +# define THREAD_GSCOPE_FLAG_USED 1 +# define THREAD_GSCOPE_FLAG_WAIT 2 +# define THREAD_GSCOPE_RESET_FLAG() \ + do \ + { int __res; \ + __asm__ __volatile__ ("xchgl %0, %%fs:%P1" \ + : "=r" (__res) \ + : "i" (offsetof (struct pthread, header.gscope_flag)), \ + "0" (THREAD_GSCOPE_FLAG_UNUSED)); \ + if (__res == THREAD_GSCOPE_FLAG_WAIT) \ + lll_futex_wake (&THREAD_SELF->header.gscope_flag, 1, LLL_PRIVATE); \ + } \ + while (0) +# define THREAD_GSCOPE_SET_FLAG() \ + THREAD_SETMEM (THREAD_SELF, header.gscope_flag, THREAD_GSCOPE_FLAG_USED) +# define THREAD_GSCOPE_WAIT() \ + GL(dl_wait_lookup_done) () + + +# ifdef SHARED +/* Defined in dl-trampoline.S. */ +extern void _dl_x86_64_save_sse (void); +extern void _dl_x86_64_restore_sse (void); + +# define RTLD_CHECK_FOREIGN_CALL \ + (THREAD_GETMEM (THREAD_SELF, header.rtld_must_xmm_save) != 0) + +/* NB: Don't use the xchg operation because that would imply a lock + prefix which is expensive and unnecessary. The cache line is also + not contested at all. */ +# define RTLD_ENABLE_FOREIGN_CALL \ + int old_rtld_must_xmm_save = THREAD_GETMEM (THREAD_SELF, \ + header.rtld_must_xmm_save); \ + THREAD_SETMEM (THREAD_SELF, header.rtld_must_xmm_save, 1) + +# define RTLD_PREPARE_FOREIGN_CALL \ + do if (THREAD_GETMEM (THREAD_SELF, header.rtld_must_xmm_save)) \ + { \ + _dl_x86_64_save_sse (); \ + THREAD_SETMEM (THREAD_SELF, header.rtld_must_xmm_save, 0); \ + } \ + while (0) + +# define RTLD_FINALIZE_FOREIGN_CALL \ + do { \ + if (THREAD_GETMEM (THREAD_SELF, header.rtld_must_xmm_save) == 0) \ + _dl_x86_64_restore_sse (); \ + THREAD_SETMEM (THREAD_SELF, header.rtld_must_xmm_save, \ + old_rtld_must_xmm_save); \ + } while (0) +# endif + + +#endif /* __ASSEMBLER__ */ +#endif /* tls.h */ diff --git a/l4/pkg/uclibc/lib/libpthread/src/tramp-amd64.S b/l4/pkg/uclibc/lib/libpthread/src/tramp-amd64.S new file mode 100644 index 00000000..f8e17a21 --- /dev/null +++ b/l4/pkg/uclibc/lib/libpthread/src/tramp-amd64.S @@ -0,0 +1,9 @@ +.text +.global __pthread_new_thread_entry +__pthread_new_thread_entry: + mov 16(%rsp), %rdi + mov 0(%rsp), %rsi + addq $24, %rsp + andq $~15, %rsp + pushq $0 + jmp *%rsi diff --git a/l4/pkg/uclibc/lib/libpthread/src/tramp-arm.S b/l4/pkg/uclibc/lib/libpthread/src/tramp-arm.S new file mode 100644 index 00000000..9060aece --- /dev/null +++ b/l4/pkg/uclibc/lib/libpthread/src/tramp-arm.S @@ -0,0 +1,9 @@ +.text +.global __pthread_new_thread_entry +__pthread_new_thread_entry: + ldr r0, [sp, #8] + ldr r1, [sp, #0] + add sp, sp, #12 + bic sp, sp, #7 + mov lr, #0 + mov pc, r1 diff --git a/l4/pkg/uclibc/lib/libpthread/src/tramp-ppc32.S b/l4/pkg/uclibc/lib/libpthread/src/tramp-ppc32.S new file mode 100644 index 00000000..9bb7580d --- /dev/null +++ b/l4/pkg/uclibc/lib/libpthread/src/tramp-ppc32.S @@ -0,0 +1,6 @@ +.text +.global __pthread_new_thread_entry +__pthread_new_thread_entry: + // implement me + // align stack here + trap diff --git a/l4/pkg/uclibc/lib/libpthread/src/tramp-sparc.S b/l4/pkg/uclibc/lib/libpthread/src/tramp-sparc.S new file mode 100644 index 00000000..aa2c83e8 --- /dev/null +++ b/l4/pkg/uclibc/lib/libpthread/src/tramp-sparc.S @@ -0,0 +1,6 @@ +.text +.global __pthread_new_thread_entry +__pthread_new_thread_entry: +// align stack here + ret + diff --git a/l4/pkg/uclibc/lib/libpthread/src/tramp-x86.S b/l4/pkg/uclibc/lib/libpthread/src/tramp-x86.S new file mode 100644 index 00000000..aa073379 --- /dev/null +++ b/l4/pkg/uclibc/lib/libpthread/src/tramp-x86.S @@ -0,0 +1,4 @@ +.text +.global __pthread_new_thread_entry +__pthread_new_thread_entry: + ret diff --git a/l4/pkg/uclibc/lib/libpthread/src/uClibc-glue.h b/l4/pkg/uclibc/lib/libpthread/src/uClibc-glue.h new file mode 100644 index 00000000..ed3b5b91 --- /dev/null +++ b/l4/pkg/uclibc/lib/libpthread/src/uClibc-glue.h @@ -0,0 +1,46 @@ +#ifndef _UCLIBC_GLUE_H +#define _UCLIBC_GLUE_H 1 + +#include +#include +#include + +#ifdef IS_IN_libpthread + +#ifndef __GLIBC_HAVE_LONG_LONG +# define __GLIBC_HAVE_LONG_LONG +#endif + +#define __getpagesize getpagesize +#define __sched_getscheduler sched_getscheduler +#define __sched_setscheduler sched_setscheduler +#define __sched_getparam sched_getparam +#define __getpid getpid +#define __gettimeofday gettimeofday +#define __poll poll +#define __sysctl sysctl +#define __open open +#define __read read +#define __close close +#define __on_exit on_exit +#define __libc_current_sigrtmin_private __libc_current_sigrtmin +#define __clone clone + +extern void *__libc_stack_end; +extern int __cxa_atexit (void (*func) (void *), void *arg, void *d); + +#endif /* IS_IN_libpthread */ + +#ifdef __UCLIBC_HAS_XLOCALE__ +# define __uselocale(x) uselocale(x) +#else +# define __uselocale(x) ((void)0) +#endif + +/* Use a funky version in a probably vein attempt at preventing gdb + * from dlopen()'ing glibc's libthread_db library... */ +#define STRINGIFY(s) STRINGIFY2 (s) +#define STRINGIFY2(s) #s +#define VERSION STRINGIFY(__UCLIBC_MAJOR__) "." STRINGIFY(__UCLIBC_MINOR__) "." STRINGIFY(__UCLIBC_SUBLEVEL__) + +#endif diff --git a/l4/pkg/uclibc/lib/minimal_l4re/Makefile b/l4/pkg/uclibc/lib/minimal_l4re/Makefile new file mode 100644 index 00000000..65c86a12 --- /dev/null +++ b/l4/pkg/uclibc/lib/minimal_l4re/Makefile @@ -0,0 +1,12 @@ +# vi:ft=make +PKGDIR ?= ../.. +L4DIR ?= $(PKGDIR)/../.. + +TARGET := libuc_c_minimal_l4re.a +PC_FILENAME := libc_minimal_l4re +DEFINES := -DL4_MINIMAL_LIBC +SRC_CC := _exit.cc + +vpath _exit.cc $(SRC_DIR)/../uclibc + +include $(L4DIR)/mk/lib.mk diff --git a/l4/pkg/uclibc/lib/uclibc/ARCH-all/include/bits/kernel-features.h b/l4/pkg/uclibc/lib/uclibc/ARCH-all/include/bits/kernel-features.h new file mode 100644 index 00000000..710cecca --- /dev/null +++ b/l4/pkg/uclibc/lib/uclibc/ARCH-all/include/bits/kernel-features.h @@ -0,0 +1 @@ +/* Empty */ diff --git a/l4/pkg/uclibc/lib/uclibc/ARCH-all/include/bits/sigthread.h b/l4/pkg/uclibc/lib/uclibc/ARCH-all/include/bits/sigthread.h new file mode 100644 index 00000000..e69de29b diff --git a/l4/pkg/uclibc/lib/uclibc/ARCH-all/include/linux/errno.h b/l4/pkg/uclibc/lib/uclibc/ARCH-all/include/linux/errno.h new file mode 100644 index 00000000..70f2bd34 --- /dev/null +++ b/l4/pkg/uclibc/lib/uclibc/ARCH-all/include/linux/errno.h @@ -0,0 +1 @@ +#include diff --git a/l4/pkg/uclibc/lib/uclibc/ARCH-all/include/linux/if_ether.h b/l4/pkg/uclibc/lib/uclibc/ARCH-all/include/linux/if_ether.h new file mode 100644 index 00000000..b3ba6845 --- /dev/null +++ b/l4/pkg/uclibc/lib/uclibc/ARCH-all/include/linux/if_ether.h @@ -0,0 +1,10 @@ +#ifndef _LINUX_IF_ETHER_H +#define _LINUX_IF_ETHER_H + +#define ETH_ALEN 6 +#define ETH_HLEN 14 +#define ETH_ZLEN 60 +#define ETH_DATA_LEN 1500 +#define ETH_FRAME_LEN 1514 + +#endif diff --git a/l4/pkg/uclibc/lib/uclibc/ARCH-all/include/not-cancel.h b/l4/pkg/uclibc/lib/uclibc/ARCH-all/include/not-cancel.h new file mode 100644 index 00000000..ea2416f4 --- /dev/null +++ b/l4/pkg/uclibc/lib/uclibc/ARCH-all/include/not-cancel.h @@ -0,0 +1,13 @@ +#pragma once + +#define close_not_cancel(fd) \ + close(fd) + +#define open_not_cancel_2(name, flags) \ + open(name, flags) + +#define fcntl_not_cancel(fd, cmd, val) \ + fcntl(fd, cmd, val) + +#define close_not_cancel_no_status(fd) \ + close(fd) diff --git a/l4/pkg/uclibc/lib/uclibc/ARCH-all/include/sys/syscall.h b/l4/pkg/uclibc/lib/uclibc/ARCH-all/include/sys/syscall.h new file mode 100644 index 00000000..e69de29b diff --git a/l4/pkg/uclibc/lib/uclibc/ARCH-all/libc/misc/dirent/dirstream.h b/l4/pkg/uclibc/lib/uclibc/ARCH-all/libc/misc/dirent/dirstream.h new file mode 100644 index 00000000..da37cd20 --- /dev/null +++ b/l4/pkg/uclibc/lib/uclibc/ARCH-all/libc/misc/dirent/dirstream.h @@ -0,0 +1,78 @@ +/* Copyright (C) 1991, 1992 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +The GNU C Library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the, 1992 Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +/* + * POSIX Standard: 5.1.2 Directory Operations + */ + +#ifndef _DIRSTREAM_H + +#define _DIRSTREAM_H 1 + +#include +#include + +#include + +/* For now, syscall readdir () only supports one entry at a time. It + * will be changed in the future. +#define NUMENT 3 +*/ +#ifndef NUMENT +#define NUMENT 1 +#endif + +#define SINGLE_READDIR 11 +#define MULTI_READDIR 12 +#define NEW_READDIR 13 + +/* Directory stream type. */ +struct __dirstream { + /* file descriptor */ + int dd_fd; + + /* offset of the next dir entry in buffer */ + size_t dd_nextloc; + + /* bytes of valid entries in buffer */ + size_t dd_size; + + /* -> directory buffer */ + void *dd_buf; + + /* offset of the next dir entry in directory. */ + off_t dd_nextoff; + + /* total size of buffer */ + size_t dd_max; + + /* lock */ + __UCLIBC_MUTEX(dd_lock); +}; /* stream data from opendir() */ + + +#ifdef ARCH_amd64 +extern ssize_t __getdents(int fd, char *buf, size_t count); +#else +extern ssize_t __getdents(int fd, char *buf, size_t count) attribute_hidden; +#endif +#ifdef __UCLIBC_HAS_LFS__ +extern ssize_t __getdents64 (int fd, char *buf, size_t count) /* l4: in libc_be: attribute_hidden */; +#endif + +#endif /* dirent.h */ diff --git a/l4/pkg/uclibc/lib/uclibc/ARCH-all/libc/signal/raise.c b/l4/pkg/uclibc/lib/uclibc/ARCH-all/libc/signal/raise.c new file mode 100644 index 00000000..b96a7fea --- /dev/null +++ b/l4/pkg/uclibc/lib/uclibc/ARCH-all/libc/signal/raise.c @@ -0,0 +1,18 @@ +/* Copyright (C) 1995,1996 Robert de Bath + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include +#include +#include + +int raise(int signo) +{ +#ifdef l4___this_is_the_original_uclibc_needed_with_gnu_linux_compiler + return kill(getpid(), signo); +#else + __builtin_trap(); +#endif +} +libc_hidden_def(raise) diff --git a/l4/pkg/uclibc/lib/uclibc/ARCH-all/libc/signal/sigjmp.c b/l4/pkg/uclibc/lib/uclibc/ARCH-all/libc/signal/sigjmp.c new file mode 100644 index 00000000..f2dc3794 --- /dev/null +++ b/l4/pkg/uclibc/lib/uclibc/ARCH-all/libc/signal/sigjmp.c @@ -0,0 +1,39 @@ +/* Copyright (C) 1992, 1994, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + + +/* This function is called by the `sigsetjmp' macro + before doing a `__setjmp' on ENV[0].__jmpbuf. + Always return zero. */ + +int __sigjmp_save (sigjmp_buf env, int savemask) attribute_hidden; +int __sigjmp_save (sigjmp_buf env, int savemask) +{ + /* FM3: We don't support signals. */ +#if 0 + env[0].__mask_was_saved = (savemask && + sigprocmask (SIG_BLOCK, NULL, &env[0].__saved_mask) == 0); +#endif + + return 0; +} diff --git a/l4/pkg/uclibc/lib/uclibc/ARCH-all/libc/stdlib/_atexit.c b/l4/pkg/uclibc/lib/uclibc/ARCH-all/libc/stdlib/_atexit.c new file mode 100644 index 00000000..6a86cc42 --- /dev/null +++ b/l4/pkg/uclibc/lib/uclibc/ARCH-all/libc/stdlib/_atexit.c @@ -0,0 +1,343 @@ +/* Copyright (C) 1995,1996 Robert de Bath + * This file is part of the Linux-8086 C library and is distributed + * under the GNU Library General Public License. + */ + +/* + * Dec 2000 Manuel Novoa III + * + * Made atexit handling conform to standards... i.e. no args. + * Removed on_exit since it did not match gnu libc definition. + * Combined atexit and __do_exit into one object file. + * + * Feb 2001 Manuel Novoa III + * + * Reworked file after addition of __uClibc_main. + * Changed name of __do_exit to atexit_handler. + * Changed name of __cleanup to __uClibc_cleanup. + * Moved declaration of __uClibc_cleanup to __uClibc_main + * where it is initialized with (possibly weak alias) + * _stdio_term. + * + * Jul 2001 Steve Thayer + * + * Added an on_exit implementation (that now matches gnu libc definition.) + * Pulled atexit_handler out of the atexit object since it is now required by + * on_exit as well. Renamed it to __exit_handler. + * Fixed a problem where exit functions stop getting called if one of + * them calls exit(). + * As a side effect of these changes, abort() no longer calls the exit + * functions (it now matches the gnu libc definition). + * + * August 2002 Erik Andersen + * Added locking so atexit and friends can be thread safe + * + * August 2005 Stephen Warren + * Added __cxa_atexit and __cxa_finalize support + * + */ + +#include +#include +#include +#include +#include + +#include +__UCLIBC_MUTEX_EXTERN(__atexit_lock); + + + +typedef void (*aefuncp) (void); /* atexit function pointer */ +typedef void (*oefuncp) (int, void *); /* on_exit function pointer */ +typedef void (*cxaefuncp) (void *); /* __cxa_atexit function pointer */ +typedef enum { + ef_free, + ef_in_use, + ef_on_exit, + ef_cxa_atexit +} ef_type; /* exit function types */ + +/* this is in the L_exit object */ +extern void (*__exit_cleanup) (int) attribute_hidden; + +/* these are in the L___do_exit object */ +extern int __exit_slots attribute_hidden; +extern int __exit_count attribute_hidden; +extern void __exit_handler(int) attribute_hidden; +struct exit_function { + /* + * 'type' should be of type of the 'enum ef_type' above but since we + * need this element in an atomic operation we have to use 'long int'. + */ + long int type; /* enum ef_type */ + union { + struct { + oefuncp func; + void *arg; + } on_exit; + struct { + cxaefuncp func; + void *arg; + void* dso_handle; + } cxa_atexit; + } funcs; +}; +#ifdef __UCLIBC_DYNAMIC_ATEXIT__ +extern struct exit_function *__exit_function_table attribute_hidden; +#else +extern struct exit_function __exit_function_table[__UCLIBC_MAX_ATEXIT] attribute_hidden; +#endif +extern struct exit_function *__new_exitfn (void) attribute_hidden; + +/* this is in the L___cxa_atexit object */ +extern int __cxa_atexit (cxaefuncp, void *arg, void *dso_handle); + + +/* remove old_atexit after 0.9.29 */ +#if defined(L_atexit) || defined(L_old_atexit) +extern void *__dso_handle __attribute__ ((__weak__)); + +/* + * register a function to be called at normal program termination + * (the registered function takes no arguments) + */ +#ifdef L_atexit +int attribute_hidden atexit(aefuncp func) +#else +int old_atexit(aefuncp func); +int old_atexit(aefuncp func) +#endif +{ + /* + * glibc casts aefuncp to cxaefuncp. + * This seems dodgy, but I guess calling a function with more + * parameters than it needs will work everywhere? + */ + return __cxa_atexit((cxaefuncp)func, NULL, + &__dso_handle == NULL ? NULL : __dso_handle); +} +#ifndef L_atexit +weak_alias(old_atexit,atexit) +#endif +#endif + +#ifdef L_on_exit +/* + * register a function to be called at normal program termination + * the registered function takes two arguments: + * status - the exit status that was passed to the exit() function + * arg - generic argument + */ +int on_exit(oefuncp func, void *arg) +{ + struct exit_function *efp; + + if (func == NULL) { + return 0; + } + + efp = __new_exitfn(); + if (efp == NULL) { + return -1; + } + + efp->funcs.on_exit.func = func; + efp->funcs.on_exit.arg = arg; + /* assign last for thread safety, since we're now unlocked */ + efp->type = ef_on_exit; + + return 0; +} +#endif + +#ifdef L___cxa_atexit +libc_hidden_proto(__cxa_atexit) +int __cxa_atexit (cxaefuncp func, void *arg, void *dso_handle) +{ + struct exit_function *efp; + + if (func == NULL) { + return 0; + } + + efp = __new_exitfn(); + if (efp == NULL) { + return -1; + } + + efp->funcs.cxa_atexit.func = func; + efp->funcs.cxa_atexit.arg = arg; + efp->funcs.cxa_atexit.dso_handle = dso_handle; + /* assign last for thread safety, since we're now unlocked */ + efp->type = ef_cxa_atexit; + + return 0; +} +libc_hidden_def(__cxa_atexit) +#endif + +#ifdef L___cxa_finalize +/* + * If D is non-NULL, call all functions registered with `__cxa_atexit' + * with the same dso handle. Otherwise, if D is NULL, call all of the + * registered handlers. + */ +void __cxa_finalize (void *dso_handle); +void __cxa_finalize (void *dso_handle) +{ + struct exit_function *efp; + int exit_count_snapshot = __exit_count; + + /* In reverse order */ + while (exit_count_snapshot) { + efp = &__exit_function_table[--exit_count_snapshot]; + + /* + * We check dso_handle match before we verify the type of the union entry. + * However, the atomic_exchange will validate that we were really "allowed" + * to read dso_handle... + */ + if ((dso_handle == NULL || dso_handle == efp->funcs.cxa_atexit.dso_handle) + /* We don't want to run this cleanup more than once. */ + && !atomic_compare_and_exchange_bool_acq(&efp->type, ef_free, ef_cxa_atexit) + ) { + /* glibc passes status (0) too, but that's not in the prototype */ + (*efp->funcs.cxa_atexit.func)(efp->funcs.cxa_atexit.arg); + } + } + +#if 0 /* haven't looked into this yet... */ + /* + * Remove the registered fork handlers. We do not have to + * unregister anything if the program is going to terminate anyway. + */ +#ifdef UNREGISTER_ATFORK + if (d != NULL) { + UNREGISTER_ATFORK (d); + } +#endif +#endif +} +#endif + +#ifdef L___exit_handler +int __exit_count = 0; /* Number of registered exit functions */ +#ifdef __UCLIBC_DYNAMIC_ATEXIT__ +struct exit_function *__exit_function_table = NULL; +int __exit_slots = 0; /* Size of __exit_function_table */ +#else +struct exit_function __exit_function_table[__UCLIBC_MAX_ATEXIT]; +#endif + +/* + * Find and return a new exit_function pointer, for atexit, + * onexit and __cxa_atexit to initialize + */ +struct exit_function attribute_hidden *__new_exitfn(void) +{ + struct exit_function *efp; + + __UCLIBC_MUTEX_LOCK(__atexit_lock); + +#ifdef __UCLIBC_DYNAMIC_ATEXIT__ + /* If we are out of function table slots, make some more */ + if (__exit_slots < __exit_count+1) { + efp=realloc(__exit_function_table, + (__exit_slots+20)*sizeof(struct exit_function)); + if (efp == NULL) { + __set_errno(ENOMEM); + goto DONE; + } + __exit_function_table = efp; + __exit_slots += 20; + } +#else + if (__exit_count >= __UCLIBC_MAX_ATEXIT) { + __set_errno(ENOMEM); + efp = NULL; + goto DONE; + } +#endif + + __exit_cleanup = __exit_handler; /* enable cleanup */ + efp = &__exit_function_table[__exit_count++]; + efp->type = ef_in_use; + +DONE: + __UCLIBC_MUTEX_UNLOCK(__atexit_lock); + return efp; +} + +/* + * Handle the work of executing the registered exit functions + * This is called while we are locked, so no additional locking + * is needed... + */ +void __exit_handler(int status) +{ + struct exit_function *efp; + + /* In reverse order */ + while ( __exit_count ) { + efp = &__exit_function_table[--__exit_count]; + switch (efp->type) { + case ef_on_exit: + if (efp->funcs.on_exit.func) { + (efp->funcs.on_exit.func) (status, efp->funcs.on_exit.arg); + } + break; + case ef_cxa_atexit: + if (efp->funcs.cxa_atexit.func) { + /* glibc passes status too, but that's not in the prototype */ +#ifdef FOR_L4_WE_PASS_THE_STATUS + (efp->funcs.cxa_atexit.func) (efp->funcs.cxa_atexit.arg); +#else + void (*f)(void *a, int status) = (void *)efp->funcs.cxa_atexit.func; + f(efp->funcs.cxa_atexit.arg, status); + +#endif + } + break; + } + } +#ifdef __UCLIBC_DYNAMIC_ATEXIT__ + /* Free up memory used by the __exit_function_table structure */ + free(__exit_function_table); +#endif +} +#endif + +#ifdef L_exit +extern void weak_function _stdio_term(void) attribute_hidden; +attribute_hidden void (*__exit_cleanup) (int) = 0; +__UCLIBC_MUTEX_INIT(__atexit_lock, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP); + +extern void __uClibc_fini(void); +libc_hidden_proto(__uClibc_fini) + +/* + * Normal program termination + */ +void exit(int rv) +{ + /* Perform exit-specific cleanup (atexit and on_exit) */ + __UCLIBC_MUTEX_LOCK(__atexit_lock); + if (__exit_cleanup) { + __exit_cleanup(rv); + } + __UCLIBC_MUTEX_UNLOCK(__atexit_lock); + + __uClibc_fini(); + + /* If we are using stdio, try to shut it down. At the very least, + * this will attempt to commit all buffered writes. It may also + * unbuffer all writable files, or close them outright. + * Check the stdio routines for details. */ + if (_stdio_term) + _stdio_term(); + + _exit(rv); +} +libc_hidden_def(exit) +#endif diff --git a/l4/pkg/uclibc/lib/uclibc/ARCH-all/libc/stdlib/abort.c b/l4/pkg/uclibc/lib/uclibc/ARCH-all/libc/stdlib/abort.c new file mode 100644 index 00000000..377fc350 --- /dev/null +++ b/l4/pkg/uclibc/lib/uclibc/ARCH-all/libc/stdlib/abort.c @@ -0,0 +1,10 @@ +#include +// #include + +void abort(void) +{ + // enter_kdebug("ABORT"); + _exit(127); + while (1) + ; +} diff --git a/l4/pkg/uclibc/lib/uclibc/ARCH-all/libc/stdlib/malloc-standard/malloc.h b/l4/pkg/uclibc/lib/uclibc/ARCH-all/libc/stdlib/malloc-standard/malloc.h new file mode 100644 index 00000000..01832d0f --- /dev/null +++ b/l4/pkg/uclibc/lib/uclibc/ARCH-all/libc/stdlib/malloc-standard/malloc.h @@ -0,0 +1,972 @@ +/* + This is a version (aka dlmalloc) of malloc/free/realloc written by + Doug Lea and released to the public domain. Use, modify, and + redistribute this code without permission or acknowledgement in any + way you wish. Send questions, comments, complaints, performance + data, etc to dl@cs.oswego.edu + + VERSION 2.7.2 Sat Aug 17 09:07:30 2002 Doug Lea (dl at gee) + + Note: There may be an updated version of this malloc obtainable at + ftp://gee.cs.oswego.edu/pub/misc/malloc.c + Check before installing! + + Hacked up for uClibc by Erik Andersen +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef L4_MINIMAL_LIBC +#include +#endif + + +__UCLIBC_MUTEX_EXTERN(__malloc_lock); +#define __MALLOC_LOCK __UCLIBC_MUTEX_LOCK(__malloc_lock) +#define __MALLOC_UNLOCK __UCLIBC_MUTEX_UNLOCK(__malloc_lock) + + + +/* + MALLOC_ALIGNMENT is the minimum alignment for malloc'ed chunks. + It must be a power of two at least 2 * (sizeof(size_t)), even on machines + for which smaller alignments would suffice. It may be defined as + larger than this though. Note however that code and data structures + are optimized for the case of 8-byte alignment. +*/ +#ifndef MALLOC_ALIGNMENT +#define MALLOC_ALIGNMENT (2 * (sizeof(size_t))) +#endif + +/* The corresponding bit mask value */ +#define MALLOC_ALIGN_MASK (MALLOC_ALIGNMENT - 1) + +/* + TRIM_FASTBINS controls whether free() of a very small chunk can + immediately lead to trimming. Setting to true (1) can reduce memory + footprint, but will almost always slow down programs that use a lot + of small chunks. + + Define this only if you are willing to give up some speed to more + aggressively reduce system-level memory footprint when releasing + memory in programs that use many small chunks. You can get + essentially the same effect by setting MXFAST to 0, but this can + lead to even greater slowdowns in programs using many small chunks. + TRIM_FASTBINS is an in-between compile-time option, that disables + only those chunks bordering topmost memory from being placed in + fastbins. +*/ +#ifndef TRIM_FASTBINS +#define TRIM_FASTBINS 0 +#endif + + +/* + MORECORE-related declarations. By default, rely on sbrk +*/ + + +/* + MORECORE is the name of the routine to call to obtain more memory + from the system. See below for general guidance on writing + alternative MORECORE functions, as well as a version for WIN32 and a + sample version for pre-OSX macos. +*/ +#ifndef MORECORE +#define MORECORE(x) ({ -1; }) +#endif + +/* + MORECORE_FAILURE is the value returned upon failure of MORECORE + as well as mmap. Since it cannot be an otherwise valid memory address, + and must reflect values of standard sys calls, you probably ought not + try to redefine it. +*/ +#ifndef MORECORE_FAILURE +#define MORECORE_FAILURE (-1) +#endif + +/* + If MORECORE_CONTIGUOUS is true, take advantage of fact that + consecutive calls to MORECORE with positive arguments always return + contiguous increasing addresses. This is true of unix sbrk. Even + if not defined, when regions happen to be contiguous, malloc will + permit allocations spanning regions obtained from different + calls. But defining this when applicable enables some stronger + consistency checks and space efficiencies. +*/ +#ifndef MORECORE_CONTIGUOUS +#define MORECORE_CONTIGUOUS 1 +#endif + +/* + MMAP_AS_MORECORE_SIZE is the minimum mmap size argument to use if + sbrk fails, and mmap is used as a backup (which is done only if + HAVE_MMAP). The value must be a multiple of page size. This + backup strategy generally applies only when systems have "holes" in + address space, so sbrk cannot perform contiguous expansion, but + there is still space available on system. On systems for which + this is known to be useful (i.e. most linux kernels), this occurs + only when programs allocate huge amounts of memory. Between this, + and the fact that mmap regions tend to be limited, the size should + be large, to avoid too many mmap calls and thus avoid running out + of kernel resources. +*/ +#ifndef MMAP_AS_MORECORE_SIZE +#define MMAP_AS_MORECORE_SIZE (1024 * 1024) +#endif + +/* + The system page size. To the extent possible, this malloc manages + memory from the system in page-size units. Note that this value is + cached during initialization into a field of malloc_state. So even + if malloc_getpagesize is a function, it is only called once. + + The following mechanics for getpagesize were adapted from bsd/gnu + getpagesize.h. If none of the system-probes here apply, a value of + 4096 is used, which should be OK: If they don't apply, then using + the actual value probably doesn't impact performance. +*/ +#ifndef malloc_getpagesize +//# include +//# define malloc_getpagesize sysconf(_SC_PAGESIZE) +//#else /* just guess */ +#ifdef L4_MINIMAL_LIBC +# define malloc_getpagesize (4096) +#else +# define malloc_getpagesize (L4_PAGESIZE) +#if L4_PAGESIZE != 4096 +# error Adapt this code for minimal libc version +#endif +#endif +#endif + + +/* mallopt tuning options */ + +/* + M_MXFAST is the maximum request size used for "fastbins", special bins + that hold returned chunks without consolidating their spaces. This + enables future requests for chunks of the same size to be handled + very quickly, but can increase fragmentation, and thus increase the + overall memory footprint of a program. + + This malloc manages fastbins very conservatively yet still + efficiently, so fragmentation is rarely a problem for values less + than or equal to the default. The maximum supported value of MXFAST + is 80. You wouldn't want it any higher than this anyway. Fastbins + are designed especially for use with many small structs, objects or + strings -- the default handles structs/objects/arrays with sizes up + to 16 4byte fields, or small strings representing words, tokens, + etc. Using fastbins for larger objects normally worsens + fragmentation without improving speed. + + M_MXFAST is set in REQUEST size units. It is internally used in + chunksize units, which adds padding and alignment. You can reduce + M_MXFAST to 0 to disable all use of fastbins. This causes the malloc + algorithm to be a closer approximation of fifo-best-fit in all cases, + not just for larger requests, but will generally cause it to be + slower. +*/ + + +/* M_MXFAST is a standard SVID/XPG tuning option, usually listed in malloc.h */ +#ifndef M_MXFAST +#define M_MXFAST 1 +#endif + +#ifndef DEFAULT_MXFAST +#define DEFAULT_MXFAST 64 +#endif + + +/* + M_TRIM_THRESHOLD is the maximum amount of unused top-most memory + to keep before releasing via malloc_trim in free(). + + Automatic trimming is mainly useful in long-lived programs. + Because trimming via sbrk can be slow on some systems, and can + sometimes be wasteful (in cases where programs immediately + afterward allocate more large chunks) the value should be high + enough so that your overall system performance would improve by + releasing this much memory. + + The trim threshold and the mmap control parameters (see below) + can be traded off with one another. Trimming and mmapping are + two different ways of releasing unused memory back to the + system. Between these two, it is often possible to keep + system-level demands of a long-lived program down to a bare + minimum. For example, in one test suite of sessions measuring + the XF86 X server on Linux, using a trim threshold of 128K and a + mmap threshold of 192K led to near-minimal long term resource + consumption. + + If you are using this malloc in a long-lived program, it should + pay to experiment with these values. As a rough guide, you + might set to a value close to the average size of a process + (program) running on your system. Releasing this much memory + would allow such a process to run in memory. Generally, it's + worth it to tune for trimming rather tham memory mapping when a + program undergoes phases where several large chunks are + allocated and released in ways that can reuse each other's + storage, perhaps mixed with phases where there are no such + chunks at all. And in well-behaved long-lived programs, + controlling release of large blocks via trimming versus mapping + is usually faster. + + However, in most programs, these parameters serve mainly as + protection against the system-level effects of carrying around + massive amounts of unneeded memory. Since frequent calls to + sbrk, mmap, and munmap otherwise degrade performance, the default + parameters are set to relatively high values that serve only as + safeguards. + + The trim value must be greater than page size to have any useful + effect. To disable trimming completely, you can set to + (unsigned long)(-1) + + Trim settings interact with fastbin (MXFAST) settings: Unless + TRIM_FASTBINS is defined, automatic trimming never takes place upon + freeing a chunk with size less than or equal to MXFAST. Trimming is + instead delayed until subsequent freeing of larger chunks. However, + you can still force an attempted trim by calling malloc_trim. + + Also, trimming is not generally possible in cases where + the main arena is obtained via mmap. + + Note that the trick some people use of mallocing a huge space and + then freeing it at program startup, in an attempt to reserve system + memory, doesn't have the intended effect under automatic trimming, + since that memory will immediately be returned to the system. +*/ +#define M_TRIM_THRESHOLD -1 + +#ifndef DEFAULT_TRIM_THRESHOLD +#define DEFAULT_TRIM_THRESHOLD (256 * 1024) +#endif + +/* + M_TOP_PAD is the amount of extra `padding' space to allocate or + retain whenever sbrk is called. It is used in two ways internally: + + * When sbrk is called to extend the top of the arena to satisfy + a new malloc request, this much padding is added to the sbrk + request. + + * When malloc_trim is called automatically from free(), + it is used as the `pad' argument. + + In both cases, the actual amount of padding is rounded + so that the end of the arena is always a system page boundary. + + The main reason for using padding is to avoid calling sbrk so + often. Having even a small pad greatly reduces the likelihood + that nearly every malloc request during program start-up (or + after trimming) will invoke sbrk, which needlessly wastes + time. + + Automatic rounding-up to page-size units is normally sufficient + to avoid measurable overhead, so the default is 0. However, in + systems where sbrk is relatively slow, it can pay to increase + this value, at the expense of carrying around more memory than + the program needs. +*/ +#define M_TOP_PAD -2 + +#ifndef DEFAULT_TOP_PAD +#define DEFAULT_TOP_PAD (0) +#endif + +/* + M_MMAP_THRESHOLD is the request size threshold for using mmap() + to service a request. Requests of at least this size that cannot + be allocated using already-existing space will be serviced via mmap. + (If enough normal freed space already exists it is used instead.) + + Using mmap segregates relatively large chunks of memory so that + they can be individually obtained and released from the host + system. A request serviced through mmap is never reused by any + other request (at least not directly; the system may just so + happen to remap successive requests to the same locations). + + Segregating space in this way has the benefits that: + + 1. Mmapped space can ALWAYS be individually released back + to the system, which helps keep the system level memory + demands of a long-lived program low. + 2. Mapped memory can never become `locked' between + other chunks, as can happen with normally allocated chunks, which + means that even trimming via malloc_trim would not release them. + 3. On some systems with "holes" in address spaces, mmap can obtain + memory that sbrk cannot. + + However, it has the disadvantages that: + + 1. The space cannot be reclaimed, consolidated, and then + used to service later requests, as happens with normal chunks. + 2. It can lead to more wastage because of mmap page alignment + requirements + 3. It causes malloc performance to be more dependent on host + system memory management support routines which may vary in + implementation quality and may impose arbitrary + limitations. Generally, servicing a request via normal + malloc steps is faster than going through a system's mmap. + + The advantages of mmap nearly always outweigh disadvantages for + "large" chunks, but the value of "large" varies across systems. The + default is an empirically derived value that works well in most + systems. +*/ +#define M_MMAP_THRESHOLD -3 + +#ifndef DEFAULT_MMAP_THRESHOLD +#define DEFAULT_MMAP_THRESHOLD (256 * 1024) +#endif + +/* + M_MMAP_MAX is the maximum number of requests to simultaneously + service using mmap. This parameter exists because +. Some systems have a limited number of internal tables for + use by mmap, and using more than a few of them may degrade + performance. + + The default is set to a value that serves only as a safeguard. + Setting to 0 disables use of mmap for servicing large requests. If + HAVE_MMAP is not set, the default value is 0, and attempts to set it + to non-zero values in mallopt will fail. +*/ +#define M_MMAP_MAX -4 + +#ifndef DEFAULT_MMAP_MAX +#define DEFAULT_MMAP_MAX (65536) +#endif + + +/* ------------------ MMAP support ------------------ */ +#include +#include + +#if !defined(MAP_ANONYMOUS) && defined(MAP_ANON) +#define MAP_ANONYMOUS MAP_ANON +#endif + +#ifdef __ARCH_USE_MMU__ + +#define MMAP(addr, size, prot) \ + (mmap((addr), (size), (prot), MAP_PRIVATE|MAP_ANONYMOUS, 0, 0)) + +#else + +#define MMAP(addr, size, prot) \ + (mmap((addr), (size), (prot), MAP_SHARED|MAP_ANONYMOUS|MAP_UNINITIALIZE, 0, 0)) + +#endif + + +/* ----------------------- Chunk representations ----------------------- */ + + +/* + This struct declaration is misleading (but accurate and necessary). + It declares a "view" into memory allowing access to necessary + fields at known offsets from a given base. See explanation below. +*/ + +struct malloc_chunk { + + size_t prev_size; /* Size of previous chunk (if free). */ + size_t size; /* Size in bytes, including overhead. */ + + struct malloc_chunk* fd; /* double links -- used only if free. */ + struct malloc_chunk* bk; +}; + + +typedef struct malloc_chunk* mchunkptr; + +/* + malloc_chunk details: + + (The following includes lightly edited explanations by Colin Plumb.) + + Chunks of memory are maintained using a `boundary tag' method as + described in e.g., Knuth or Standish. (See the paper by Paul + Wilson ftp://ftp.cs.utexas.edu/pub/garbage/allocsrv.ps for a + survey of such techniques.) Sizes of free chunks are stored both + in the front of each chunk and at the end. This makes + consolidating fragmented chunks into bigger chunks very fast. The + size fields also hold bits representing whether chunks are free or + in use. + + An allocated chunk looks like this: + + + chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Size of previous chunk, if allocated | | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Size of chunk, in bytes |P| + mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | User data starts here... . + . . + . (malloc_usable_space() bytes) . + . | +nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Size of chunk | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + + Where "chunk" is the front of the chunk for the purpose of most of + the malloc code, but "mem" is the pointer that is returned to the + user. "Nextchunk" is the beginning of the next contiguous chunk. + + Chunks always begin on even word boundries, so the mem portion + (which is returned to the user) is also on an even word boundary, and + thus at least double-word aligned. + + Free chunks are stored in circular doubly-linked lists, and look like this: + + chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Size of previous chunk | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + `head:' | Size of chunk, in bytes |P| + mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Forward pointer to next chunk in list | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Back pointer to previous chunk in list | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Unused space (may be 0 bytes long) . + . . + . | +nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + `foot:' | Size of chunk, in bytes | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + The P (PREV_INUSE) bit, stored in the unused low-order bit of the + chunk size (which is always a multiple of two words), is an in-use + bit for the *previous* chunk. If that bit is *clear*, then the + word before the current chunk size contains the previous chunk + size, and can be used to find the front of the previous chunk. + The very first chunk allocated always has this bit set, + preventing access to non-existent (or non-owned) memory. If + prev_inuse is set for any given chunk, then you CANNOT determine + the size of the previous chunk, and might even get a memory + addressing fault when trying to do so. + + Note that the `foot' of the current chunk is actually represented + as the prev_size of the NEXT chunk. This makes it easier to + deal with alignments etc but can be very confusing when trying + to extend or adapt this code. + + The two exceptions to all this are + + 1. The special chunk `top' doesn't bother using the + trailing size field since there is no next contiguous chunk + that would have to index off it. After initialization, `top' + is forced to always exist. If it would become less than + MINSIZE bytes long, it is replenished. + + 2. Chunks allocated via mmap, which have the second-lowest-order + bit (IS_MMAPPED) set in their size fields. Because they are + allocated one-by-one, each must contain its own trailing size field. + +*/ + +/* + ---------- Size and alignment checks and conversions ---------- +*/ + +/* conversion from malloc headers to user pointers, and back */ + +#define chunk2mem(p) ((void*)((char*)(p) + 2*(sizeof(size_t)))) +#define mem2chunk(mem) ((mchunkptr)((char*)(mem) - 2*(sizeof(size_t)))) + +/* The smallest possible chunk */ +#define MIN_CHUNK_SIZE (sizeof(struct malloc_chunk)) + +/* The smallest size we can malloc is an aligned minimal chunk */ + +#define MINSIZE \ + (unsigned long)(((MIN_CHUNK_SIZE+MALLOC_ALIGN_MASK) & ~MALLOC_ALIGN_MASK)) + +/* Check if m has acceptable alignment */ + +#define aligned_OK(m) (((unsigned long)((m)) & (MALLOC_ALIGN_MASK)) == 0) + + +/* Check if a request is so large that it would wrap around zero when + padded and aligned. To simplify some other code, the bound is made + low enough so that adding MINSIZE will also not wrap around sero. +*/ + +#define REQUEST_OUT_OF_RANGE(req) \ + ((unsigned long)(req) >= \ + (unsigned long)(size_t)(-2 * MINSIZE)) + +/* pad request bytes into a usable size -- internal version */ + +#define request2size(req) \ + (((req) + (sizeof(size_t)) + MALLOC_ALIGN_MASK < MINSIZE) ? \ + MINSIZE : \ + ((req) + (sizeof(size_t)) + MALLOC_ALIGN_MASK) & ~MALLOC_ALIGN_MASK) + +/* Same, except also perform argument check */ + +#define checked_request2size(req, sz) \ + if (REQUEST_OUT_OF_RANGE(req)) { \ + errno = ENOMEM; \ + return 0; \ + } \ + (sz) = request2size(req); + +/* + --------------- Physical chunk operations --------------- +*/ + + +/* size field is or'ed with PREV_INUSE when previous adjacent chunk in use */ +#define PREV_INUSE 0x1 + +/* extract inuse bit of previous chunk */ +#define prev_inuse(p) ((p)->size & PREV_INUSE) + + +/* size field is or'ed with IS_MMAPPED if the chunk was obtained with mmap() */ +#define IS_MMAPPED 0x2 + +/* check for mmap()'ed chunk */ +#define chunk_is_mmapped(p) ((p)->size & IS_MMAPPED) + +/* Bits to mask off when extracting size + + Note: IS_MMAPPED is intentionally not masked off from size field in + macros for which mmapped chunks should never be seen. This should + cause helpful core dumps to occur if it is tried by accident by + people extending or adapting this malloc. +*/ +#define SIZE_BITS (PREV_INUSE|IS_MMAPPED) + +/* Get size, ignoring use bits */ +#define chunksize(p) ((p)->size & ~(SIZE_BITS)) + + +/* Ptr to next physical malloc_chunk. */ +#define next_chunk(p) ((mchunkptr)( ((char*)(p)) + ((p)->size & ~PREV_INUSE) )) + +/* Ptr to previous physical malloc_chunk */ +#define prev_chunk(p) ((mchunkptr)( ((char*)(p)) - ((p)->prev_size) )) + +/* Treat space at ptr + offset as a chunk */ +#define chunk_at_offset(p, s) ((mchunkptr)(((char*)(p)) + (s))) + +/* extract p's inuse bit */ +#define inuse(p)\ +((((mchunkptr)(((char*)(p))+((p)->size & ~PREV_INUSE)))->size) & PREV_INUSE) + +/* set/clear chunk as being inuse without otherwise disturbing */ +#define set_inuse(p)\ +((mchunkptr)(((char*)(p)) + ((p)->size & ~PREV_INUSE)))->size |= PREV_INUSE + +#define clear_inuse(p)\ +((mchunkptr)(((char*)(p)) + ((p)->size & ~PREV_INUSE)))->size &= ~(PREV_INUSE) + + +/* check/set/clear inuse bits in known places */ +#define inuse_bit_at_offset(p, s)\ + (((mchunkptr)(((char*)(p)) + (s)))->size & PREV_INUSE) + +#define set_inuse_bit_at_offset(p, s)\ + (((mchunkptr)(((char*)(p)) + (s)))->size |= PREV_INUSE) + +#define clear_inuse_bit_at_offset(p, s)\ + (((mchunkptr)(((char*)(p)) + (s)))->size &= ~(PREV_INUSE)) + + +/* Set size at head, without disturbing its use bit */ +#define set_head_size(p, s) ((p)->size = (((p)->size & PREV_INUSE) | (s))) + +/* Set size/use field */ +#define set_head(p, s) ((p)->size = (s)) + +/* Set size at footer (only when chunk is not in use) */ +#define set_foot(p, s) (((mchunkptr)((char*)(p) + (s)))->prev_size = (s)) + + +/* -------------------- Internal data structures -------------------- */ + +/* + Bins + + An array of bin headers for free chunks. Each bin is doubly + linked. The bins are approximately proportionally (log) spaced. + There are a lot of these bins (128). This may look excessive, but + works very well in practice. Most bins hold sizes that are + unusual as malloc request sizes, but are more usual for fragments + and consolidated sets of chunks, which is what these bins hold, so + they can be found quickly. All procedures maintain the invariant + that no consolidated chunk physically borders another one, so each + chunk in a list is known to be preceeded and followed by either + inuse chunks or the ends of memory. + + Chunks in bins are kept in size order, with ties going to the + approximately least recently used chunk. Ordering isn't needed + for the small bins, which all contain the same-sized chunks, but + facilitates best-fit allocation for larger chunks. These lists + are just sequential. Keeping them in order almost never requires + enough traversal to warrant using fancier ordered data + structures. + + Chunks of the same size are linked with the most + recently freed at the front, and allocations are taken from the + back. This results in LRU (FIFO) allocation order, which tends + to give each chunk an equal opportunity to be consolidated with + adjacent freed chunks, resulting in larger free chunks and less + fragmentation. + + To simplify use in double-linked lists, each bin header acts + as a malloc_chunk. This avoids special-casing for headers. + But to conserve space and improve locality, we allocate + only the fd/bk pointers of bins, and then use repositioning tricks + to treat these as the fields of a malloc_chunk*. +*/ + +typedef struct malloc_chunk* mbinptr; + +/* addressing -- note that bin_at(0) does not exist */ +#define bin_at(m, i) ((mbinptr)((char*)&((m)->bins[(i)<<1]) - ((sizeof(size_t))<<1))) + +/* analog of ++bin */ +#define next_bin(b) ((mbinptr)((char*)(b) + (sizeof(mchunkptr)<<1))) + +/* Reminders about list directionality within bins */ +#define first(b) ((b)->fd) +#define last(b) ((b)->bk) + +/* Take a chunk off a bin list */ +#define unlink(P, BK, FD) { \ + FD = P->fd; \ + BK = P->bk; \ + if (FD->bk != P || BK->fd != P) \ + abort(); \ + FD->bk = BK; \ + BK->fd = FD; \ +} + +/* + Indexing + + Bins for sizes < 512 bytes contain chunks of all the same size, spaced + 8 bytes apart. Larger bins are approximately logarithmically spaced: + + 64 bins of size 8 + 32 bins of size 64 + 16 bins of size 512 + 8 bins of size 4096 + 4 bins of size 32768 + 2 bins of size 262144 + 1 bin of size what's left + + The bins top out around 1MB because we expect to service large + requests via mmap. +*/ + +#define NBINS 96 +#define NSMALLBINS 32 +#define SMALLBIN_WIDTH 8 +#define MIN_LARGE_SIZE 256 + +#define in_smallbin_range(sz) \ + ((unsigned long)(sz) < (unsigned long)MIN_LARGE_SIZE) + +#define smallbin_index(sz) (((unsigned)(sz)) >> 3) + +#define bin_index(sz) \ + ((in_smallbin_range(sz)) ? smallbin_index(sz) : __malloc_largebin_index(sz)) + +/* + FIRST_SORTED_BIN_SIZE is the chunk size corresponding to the + first bin that is maintained in sorted order. This must + be the smallest size corresponding to a given bin. + + Normally, this should be MIN_LARGE_SIZE. But you can weaken + best fit guarantees to sometimes speed up malloc by increasing value. + Doing this means that malloc may choose a chunk that is + non-best-fitting by up to the width of the bin. + + Some useful cutoff values: + 512 - all bins sorted + 2560 - leaves bins <= 64 bytes wide unsorted + 12288 - leaves bins <= 512 bytes wide unsorted + 65536 - leaves bins <= 4096 bytes wide unsorted + 262144 - leaves bins <= 32768 bytes wide unsorted + -1 - no bins sorted (not recommended!) +*/ + +#define FIRST_SORTED_BIN_SIZE MIN_LARGE_SIZE +/* #define FIRST_SORTED_BIN_SIZE 65536 */ + +/* + Unsorted chunks + + All remainders from chunk splits, as well as all returned chunks, + are first placed in the "unsorted" bin. They are then placed + in regular bins after malloc gives them ONE chance to be used before + binning. So, basically, the unsorted_chunks list acts as a queue, + with chunks being placed on it in free (and __malloc_consolidate), + and taken off (to be either used or placed in bins) in malloc. +*/ + +/* The otherwise unindexable 1-bin is used to hold unsorted chunks. */ +#define unsorted_chunks(M) (bin_at(M, 1)) + +/* + Top + + The top-most available chunk (i.e., the one bordering the end of + available memory) is treated specially. It is never included in + any bin, is used only if no other chunk is available, and is + released back to the system if it is very large (see + M_TRIM_THRESHOLD). Because top initially + points to its own bin with initial zero size, thus forcing + extension on the first malloc request, we avoid having any special + code in malloc to check whether it even exists yet. But we still + need to do so when getting memory from system, so we make + initial_top treat the bin as a legal but unusable chunk during the + interval between initialization and the first call to + __malloc_alloc. (This is somewhat delicate, since it relies on + the 2 preceding words to be zero during this interval as well.) +*/ + +/* Conveniently, the unsorted bin can be used as dummy top on first call */ +#define initial_top(M) (unsorted_chunks(M)) + +/* + Binmap + + To help compensate for the large number of bins, a one-level index + structure is used for bin-by-bin searching. `binmap' is a + bitvector recording whether bins are definitely empty so they can + be skipped over during during traversals. The bits are NOT always + cleared as soon as bins are empty, but instead only + when they are noticed to be empty during traversal in malloc. +*/ + +/* Conservatively use 32 bits per map word, even if on 64bit system */ +#define BINMAPSHIFT 5 +#define BITSPERMAP (1U << BINMAPSHIFT) +#define BINMAPSIZE (NBINS / BITSPERMAP) + +#define idx2block(i) ((i) >> BINMAPSHIFT) +#define idx2bit(i) ((1U << ((i) & ((1U << BINMAPSHIFT)-1)))) + +#define mark_bin(m,i) ((m)->binmap[idx2block(i)] |= idx2bit(i)) +#define unmark_bin(m,i) ((m)->binmap[idx2block(i)] &= ~(idx2bit(i))) +#define get_binmap(m,i) ((m)->binmap[idx2block(i)] & idx2bit(i)) + +/* + Fastbins + + An array of lists holding recently freed small chunks. Fastbins + are not doubly linked. It is faster to single-link them, and + since chunks are never removed from the middles of these lists, + double linking is not necessary. Also, unlike regular bins, they + are not even processed in FIFO order (they use faster LIFO) since + ordering doesn't much matter in the transient contexts in which + fastbins are normally used. + + Chunks in fastbins keep their inuse bit set, so they cannot + be consolidated with other free chunks. __malloc_consolidate + releases all chunks in fastbins and consolidates them with + other free chunks. +*/ + +typedef struct malloc_chunk* mfastbinptr; + +/* offset 2 to use otherwise unindexable first 2 bins */ +#define fastbin_index(sz) ((((unsigned int)(sz)) >> 3) - 2) + +/* The maximum fastbin request size we support */ +#define MAX_FAST_SIZE 80 + +#define NFASTBINS (fastbin_index(request2size(MAX_FAST_SIZE))+1) + +/* + FASTBIN_CONSOLIDATION_THRESHOLD is the size of a chunk in free() + that triggers automatic consolidation of possibly-surrounding + fastbin chunks. This is a heuristic, so the exact value should not + matter too much. It is defined at half the default trim threshold as a + compromise heuristic to only attempt consolidation if it is likely + to lead to trimming. However, it is not dynamically tunable, since + consolidation reduces fragmentation surrounding loarge chunks even + if trimming is not used. +*/ + +#define FASTBIN_CONSOLIDATION_THRESHOLD \ + ((unsigned long)(DEFAULT_TRIM_THRESHOLD) >> 1) + +/* + Since the lowest 2 bits in max_fast don't matter in size comparisons, + they are used as flags. +*/ + +/* + ANYCHUNKS_BIT held in max_fast indicates that there may be any + freed chunks at all. It is set true when entering a chunk into any + bin. +*/ + +#define ANYCHUNKS_BIT (1U) + +#define have_anychunks(M) (((M)->max_fast & ANYCHUNKS_BIT)) +#define set_anychunks(M) ((M)->max_fast |= ANYCHUNKS_BIT) +#define clear_anychunks(M) ((M)->max_fast &= ~ANYCHUNKS_BIT) + +/* + FASTCHUNKS_BIT held in max_fast indicates that there are probably + some fastbin chunks. It is set true on entering a chunk into any + fastbin, and cleared only in __malloc_consolidate. +*/ + +#define FASTCHUNKS_BIT (2U) + +#define have_fastchunks(M) (((M)->max_fast & FASTCHUNKS_BIT)) +#define set_fastchunks(M) ((M)->max_fast |= (FASTCHUNKS_BIT|ANYCHUNKS_BIT)) +#define clear_fastchunks(M) ((M)->max_fast &= ~(FASTCHUNKS_BIT)) + +/* Set value of max_fast. Use impossibly small value if 0. */ +#define set_max_fast(M, s) \ + (M)->max_fast = (((s) == 0)? SMALLBIN_WIDTH: request2size(s)) | \ + ((M)->max_fast & (FASTCHUNKS_BIT|ANYCHUNKS_BIT)) + +#define get_max_fast(M) \ + ((M)->max_fast & ~(FASTCHUNKS_BIT | ANYCHUNKS_BIT)) + + +/* + morecore_properties is a status word holding dynamically discovered + or controlled properties of the morecore function +*/ + +#define MORECORE_CONTIGUOUS_BIT (1U) + +#define contiguous(M) \ + (((M)->morecore_properties & MORECORE_CONTIGUOUS_BIT)) +#define noncontiguous(M) \ + (((M)->morecore_properties & MORECORE_CONTIGUOUS_BIT) == 0) +#define set_contiguous(M) \ + ((M)->morecore_properties |= MORECORE_CONTIGUOUS_BIT) +#define set_noncontiguous(M) \ + ((M)->morecore_properties &= ~MORECORE_CONTIGUOUS_BIT) + + +/* + ----------- Internal state representation and initialization ----------- +*/ + +struct malloc_state { + + /* The maximum chunk size to be eligible for fastbin */ + size_t max_fast; /* low 2 bits used as flags */ + + /* Fastbins */ + mfastbinptr fastbins[NFASTBINS]; + + /* Base of the topmost chunk -- not otherwise kept in a bin */ + mchunkptr top; + + /* The remainder from the most recent split of a small request */ + mchunkptr last_remainder; + + /* Normal bins packed as described above */ + mchunkptr bins[NBINS * 2]; + + /* Bitmap of bins. Trailing zero map handles cases of largest binned size */ + unsigned int binmap[BINMAPSIZE+1]; + + /* Tunable parameters */ + unsigned long trim_threshold; + size_t top_pad; + size_t mmap_threshold; + + /* Memory map support */ + int n_mmaps; + int n_mmaps_max; + int max_n_mmaps; + + /* Cache malloc_getpagesize */ + unsigned int pagesize; + + /* Track properties of MORECORE */ + unsigned int morecore_properties; + + /* Statistics */ + size_t mmapped_mem; + size_t sbrked_mem; + size_t max_sbrked_mem; + size_t max_mmapped_mem; + size_t max_total_mem; +}; + +typedef struct malloc_state *mstate; + +/* + There is exactly one instance of this struct in this malloc. + If you are adapting this malloc in a way that does NOT use a static + malloc_state, you MUST explicitly zero-fill it before using. This + malloc relies on the property that malloc_state is initialized to + all zeroes (as is true of C statics). +*/ +extern struct malloc_state __malloc_state; /* never directly referenced */ + +/* + All uses of av_ are via get_malloc_state(). + At most one "call" to get_malloc_state is made per invocation of + the public versions of malloc and free, but other routines + that in turn invoke malloc and/or free may call more then once. + Also, it is called in check* routines if __UCLIBC_MALLOC_DEBUGGING__ is set. +*/ + +#define get_malloc_state() (&(__malloc_state)) + +/* External internal utilities operating on mstates */ +void __malloc_consolidate(mstate) attribute_hidden; + + +/* Debugging support */ +#ifndef __UCLIBC_MALLOC_DEBUGGING__ + +#define check_chunk(P) +#define check_free_chunk(P) +#define check_inuse_chunk(P) +#define check_remalloced_chunk(P,N) +#define check_malloced_chunk(P,N) +#define check_malloc_state() +#define assert(x) ((void)0) + + +#else + +#define check_chunk(P) __do_check_chunk(P) +#define check_free_chunk(P) __do_check_free_chunk(P) +#define check_inuse_chunk(P) __do_check_inuse_chunk(P) +#define check_remalloced_chunk(P,N) __do_check_remalloced_chunk(P,N) +#define check_malloced_chunk(P,N) __do_check_malloced_chunk(P,N) +#define check_malloc_state() __do_check_malloc_state() + +extern void __do_check_chunk(mchunkptr p); +extern void __do_check_free_chunk(mchunkptr p); +extern void __do_check_inuse_chunk(mchunkptr p); +extern void __do_check_remalloced_chunk(mchunkptr p, size_t s); +extern void __do_check_malloced_chunk(mchunkptr p, size_t s); +extern void __do_check_malloc_state(void); + +#include + +#endif diff --git a/l4/pkg/uclibc/lib/uclibc/ARCH-all/libc/sysdeps/linux/common/getdents.c b/l4/pkg/uclibc/lib/uclibc/ARCH-all/libc/sysdeps/linux/common/getdents.c new file mode 100644 index 00000000..4a2a1201 --- /dev/null +++ b/l4/pkg/uclibc/lib/uclibc/ARCH-all/libc/sysdeps/linux/common/getdents.c @@ -0,0 +1,174 @@ +/* + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* L4: Just shortcut getdents* for now... */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if !(defined __UCLIBC_HAS_LFS__ && defined __NR_getdents64 && __WORDSIZE == 64) +/* If the condition above is met, __getdents is defined as an alias + * for __getdents64 (see getdents64.c). Otherwise... + */ + +/* With newer versions of linux, the getdents syscall returns d_type + * information after the name field. + * + * See __ASSUME_GETDENTS32_D_TYPE in glibc's kernel-features.h for specific + * version / arch details. + */ + +#ifndef offsetof +# define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) +#endif + +struct kernel_dirent +{ + long int d_ino; + __kernel_off_t d_off; + unsigned short int d_reclen; + char d_name[256]; +}; + +ssize_t __getdents (int fd, char *buf, size_t nbytes) attribute_hidden; + +#define __NR___syscall_getdents __NR_getdents +#ifdef NOT_FOR_L4 +static __always_inline _syscall3(int, __syscall_getdents, int, fd, unsigned char *, kdirp, size_t, count) +#endif + +#if defined __ASSUME_GETDENTS32_D_TYPE +#error foo1 +ssize_t __getdents (int fd, char *buf, size_t nbytes) +{ + ssize_t retval; + + retval = __syscall_getdents(fd, (unsigned char *)buf, nbytes); + + /* The kernel added the d_type value after the name. Change + this now. */ + if (retval != -1) { + union { + struct kernel_dirent k; + struct dirent u; + } *kbuf = (void *) buf; + + while ((char *) kbuf < buf + retval) { + char d_type = *((char *) kbuf + kbuf->k.d_reclen - 1); + memmove (kbuf->u.d_name, kbuf->k.d_name, + strlen (kbuf->k.d_name) + 1); + kbuf->u.d_type = d_type; + + kbuf = (void *) ((char *) kbuf + kbuf->k.d_reclen); + } + } + + return retval; +} + +#elif defined NOT_FOR_L4 && (! defined __UCLIBC_HAS_LFS__ || ! defined __NR_getdents64) + +ssize_t __getdents (int fd, char *buf, size_t nbytes) +{ + struct dirent *dp; + off_t last_offset = -1; + ssize_t retval; + size_t red_nbytes; + struct kernel_dirent *skdp, *kdp; + const size_t size_diff = (offsetof (struct dirent, d_name) + - offsetof (struct kernel_dirent, d_name)); + + red_nbytes = MIN (nbytes - ((nbytes / + (offsetof (struct dirent, d_name) + 14)) * size_diff), + nbytes - size_diff); + + dp = (struct dirent *) buf; + skdp = kdp = alloca (red_nbytes); + + retval = __syscall_getdents(fd, (unsigned char *)kdp, red_nbytes); + if (retval == -1) + return -1; + + while ((char *) kdp < (char *) skdp + retval) { + const size_t alignment = __alignof__ (struct dirent); + /* Since kdp->d_reclen is already aligned for the kernel structure + this may compute a value that is bigger than necessary. */ + size_t new_reclen = ((kdp->d_reclen + size_diff + alignment - 1) + & ~(alignment - 1)); + if ((char *) dp + new_reclen > buf + nbytes) { + /* Our heuristic failed. We read too many entries. Reset + the stream. */ + assert (last_offset != -1); + lseek(fd, last_offset, SEEK_SET); + + if ((char *) dp == buf) { + /* The buffer the user passed in is too small to hold even + one entry. */ + __set_errno (EINVAL); + return -1; + } + break; + } + + last_offset = kdp->d_off; + dp->d_ino = kdp->d_ino; + dp->d_off = kdp->d_off; + dp->d_reclen = new_reclen; + dp->d_type = DT_UNKNOWN; + memcpy (dp->d_name, kdp->d_name, + kdp->d_reclen - offsetof (struct kernel_dirent, d_name)); + dp = (struct dirent *) ((char *) dp + new_reclen); + kdp = (struct kernel_dirent *) (((char *) kdp) + kdp->d_reclen); + } + return (char *) dp - buf; +} + +#elif __WORDSIZE == 32 && defined __UCLIBC_HAS_LFS__ + +extern __typeof(__getdents) __getdents64 /* attribute_hidden*/; +ssize_t __getdents (int fd, char *buf, size_t nbytes) +{ + struct dirent *dp; + struct dirent64 *dp64; + ssize_t ret = __getdents64 (fd, buf, nbytes); + + if (ret <= 0) + return ret; + + dp64 = (struct dirent64 *) buf; + buf += ret; + while ((void *) dp64 < (void *) buf) { + dp = (struct dirent *) dp64; + dp->d_ino = dp64->d_ino; + dp->d_off = dp64->d_off; + dp->d_reclen = dp64->d_reclen; + dp->d_type = dp64->d_type; + memmove (dp->d_name, dp64->d_name, dp->d_reclen - offsetof (struct dirent64, d_name)); + memmove (dp64, dp, dp->d_reclen); + dp64 = ((void *) dp64) + dp->d_reclen; + } + + return ret; +} + +#endif + +#if defined NOT_FOR_L4 && (defined __UCLIBC_HAS_LFS__ && ! defined __NR_getdents64) +attribute_hidden strong_alias(__getdents,__getdents64) +#endif + +#endif diff --git a/l4/pkg/uclibc/lib/uclibc/ARCH-all/libc/sysdeps/linux/common/getsid.c b/l4/pkg/uclibc/lib/uclibc/ARCH-all/libc/sysdeps/linux/common/getsid.c new file mode 100644 index 00000000..619302fd --- /dev/null +++ b/l4/pkg/uclibc/lib/uclibc/ARCH-all/libc/sysdeps/linux/common/getsid.c @@ -0,0 +1,19 @@ +/* vi: set sw=4 ts=4: */ +/* + * getsid() for uClibc + * + * Copyright (C) 2000-2006 Erik Andersen + * + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include + +#ifdef __USE_XOPEN_EXTENDED + +pid_t getsid(pid_t pid) +{ + return 1; +} +libc_hidden_def(getsid) +#endif diff --git a/l4/pkg/uclibc/lib/uclibc/ARCH-all/libc/sysdeps/linux/common/longjmp.c b/l4/pkg/uclibc/lib/uclibc/ARCH-all/libc/sysdeps/linux/common/longjmp.c new file mode 100644 index 00000000..01e6fe07 --- /dev/null +++ b/l4/pkg/uclibc/lib/uclibc/ARCH-all/libc/sysdeps/linux/common/longjmp.c @@ -0,0 +1,52 @@ +/* Copyright (C) 1991, 92, 94, 95, 97, 98, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include + + +extern void __longjmp (__jmp_buf __env, int __val) attribute_noreturn; +libc_hidden_proto(__longjmp) + +extern __typeof(longjmp) __libc_longjmp attribute_noreturn; +/* Set the signal mask to the one specified in ENV, and jump + to the position specified in ENV, causing the setjmp + call there to return VAL, or 1 if VAL is 0. */ +void __libc_longjmp (sigjmp_buf env, int val) +{ +#if 0 + /* Perform any cleanups needed by the frames being unwound. */ + _longjmp_unwind (env, val); +#endif + +#if 0 + /* FM3: signals not supported */ + if (env[0].__mask_was_saved) + /* Restore the saved signal mask. */ + (void) sigprocmask (SIG_SETMASK, &env[0].__saved_mask, NULL); +#endif + + /* Call the machine-dependent function to restore machine state. */ + __longjmp (env[0].__jmpbuf, val ?: 1); +} + +weak_alias(__libc_longjmp,longjmp) +weak_alias(__libc_longjmp,siglongjmp) +strong_alias(__libc_longjmp,__libc_siglongjmp) +strong_alias(__libc_longjmp,_longjmp) diff --git a/l4/pkg/uclibc/lib/uclibc/ARCH-all/libc/unistd/sleep.c b/l4/pkg/uclibc/lib/uclibc/ARCH-all/libc/unistd/sleep.c new file mode 100644 index 00000000..c6d6bbbb --- /dev/null +++ b/l4/pkg/uclibc/lib/uclibc/ARCH-all/libc/unistd/sleep.c @@ -0,0 +1,12 @@ +#include +#include + +unsigned int sleep (unsigned int seconds) +{ + unsigned int res; + struct timespec ts = { .tv_sec = (long int) seconds, .tv_nsec = 0 }; + res = nanosleep(&ts, &ts); + if (res) res = (unsigned int) ts.tv_sec + (ts.tv_nsec >= 500000000L); + return res; +} + diff --git a/l4/pkg/uclibc/lib/uclibc/ARCH-amd64/include/asm/errno.h b/l4/pkg/uclibc/lib/uclibc/ARCH-amd64/include/asm/errno.h new file mode 100644 index 00000000..7606c278 --- /dev/null +++ b/l4/pkg/uclibc/lib/uclibc/ARCH-amd64/include/asm/errno.h @@ -0,0 +1,147 @@ +#ifndef _ASM_GENERIC_ERRNO_H +#define _ASM_GENERIC_ERRNO_H + + +#ifndef _ASM_GENERIC_ERRNO_BASE_H +#define _ASM_GENERIC_ERRNO_BASE_H + +#define EPERM 1 /* Operation not permitted */ +#define ENOENT 2 /* No such file or directory */ +#define ESRCH 3 /* No such process */ +#define EINTR 4 /* Interrupted system call */ +#define EIO 5 /* I/O error */ +#define ENXIO 6 /* No such device or address */ +#define E2BIG 7 /* Argument list too long */ +#define ENOEXEC 8 /* Exec format error */ +#define EBADF 9 /* Bad file number */ +#define ECHILD 10 /* No child processes */ +#define EAGAIN 11 /* Try again */ +#define ENOMEM 12 /* Out of memory */ +#define EACCES 13 /* Permission denied */ +#define EFAULT 14 /* Bad address */ +#define ENOTBLK 15 /* Block device required */ +#define EBUSY 16 /* Device or resource busy */ +#define EEXIST 17 /* File exists */ +#define EXDEV 18 /* Cross-device link */ +#define ENODEV 19 /* No such device */ +#define ENOTDIR 20 /* Not a directory */ +#define EISDIR 21 /* Is a directory */ +#define EINVAL 22 /* Invalid argument */ +#define ENFILE 23 /* File table overflow */ +#define EMFILE 24 /* Too many open files */ +#define ENOTTY 25 /* Not a typewriter */ +#define ETXTBSY 26 /* Text file busy */ +#define EFBIG 27 /* File too large */ +#define ENOSPC 28 /* No space left on device */ +#define ESPIPE 29 /* Illegal seek */ +#define EROFS 30 /* Read-only file system */ +#define EMLINK 31 /* Too many links */ +#define EPIPE 32 /* Broken pipe */ +#define EDOM 33 /* Math argument out of domain of func */ +#define ERANGE 34 /* Math result not representable */ + +#endif +#define EDEADLK 35 /* Resource deadlock would occur */ +#define ENAMETOOLONG 36 /* File name too long */ +#define ENOLCK 37 /* No record locks available */ +#define ENOSYS 38 /* Function not implemented */ +#define ENOTEMPTY 39 /* Directory not empty */ +#define ELOOP 40 /* Too many symbolic links encountered */ +#define EWOULDBLOCK EAGAIN /* Operation would block */ +#define ENOMSG 42 /* No message of desired type */ +#define EIDRM 43 /* Identifier removed */ +#define ECHRNG 44 /* Channel number out of range */ +#define EL2NSYNC 45 /* Level 2 not synchronized */ +#define EL3HLT 46 /* Level 3 halted */ +#define EL3RST 47 /* Level 3 reset */ +#define ELNRNG 48 /* Link number out of range */ +#define EUNATCH 49 /* Protocol driver not attached */ +#define ENOCSI 50 /* No CSI structure available */ +#define EL2HLT 51 /* Level 2 halted */ +#define EBADE 52 /* Invalid exchange */ +#define EBADR 53 /* Invalid request descriptor */ +#define EXFULL 54 /* Exchange full */ +#define ENOANO 55 /* No anode */ +#define EBADRQC 56 /* Invalid request code */ +#define EBADSLT 57 /* Invalid slot */ + +#define EDEADLOCK EDEADLK + +#define EBFONT 59 /* Bad font file format */ +#define ENOSTR 60 /* Device not a stream */ +#define ENODATA 61 /* No data available */ +#define ETIME 62 /* Timer expired */ +#define ENOSR 63 /* Out of streams resources */ +#define ENONET 64 /* Machine is not on the network */ +#define ENOPKG 65 /* Package not installed */ +#define EREMOTE 66 /* Object is remote */ +#define ENOLINK 67 /* Link has been severed */ +#define EADV 68 /* Advertise error */ +#define ESRMNT 69 /* Srmount error */ +#define ECOMM 70 /* Communication error on send */ +#define EPROTO 71 /* Protocol error */ +#define EMULTIHOP 72 /* Multihop attempted */ +#define EDOTDOT 73 /* RFS specific error */ +#define EBADMSG 74 /* Not a data message */ +#define EOVERFLOW 75 /* Value too large for defined data type */ +#define ENOTUNIQ 76 /* Name not unique on network */ +#define EBADFD 77 /* File descriptor in bad state */ +#define EREMCHG 78 /* Remote address changed */ +#define ELIBACC 79 /* Can not access a needed shared library */ +#define ELIBBAD 80 /* Accessing a corrupted shared library */ +#define ELIBSCN 81 /* .lib section in a.out corrupted */ +#define ELIBMAX 82 /* Attempting to link in too many shared libraries */ +#define ELIBEXEC 83 /* Cannot exec a shared library directly */ +#define EILSEQ 84 /* Illegal byte sequence */ +#define ERESTART 85 /* Interrupted system call should be restarted */ +#define ESTRPIPE 86 /* Streams pipe error */ +#define EUSERS 87 /* Too many users */ +#define ENOTSOCK 88 /* Socket operation on non-socket */ +#define EDESTADDRREQ 89 /* Destination address required */ +#define EMSGSIZE 90 /* Message too long */ +#define EPROTOTYPE 91 /* Protocol wrong type for socket */ +#define ENOPROTOOPT 92 /* Protocol not available */ +#define EPROTONOSUPPORT 93 /* Protocol not supported */ +#define ESOCKTNOSUPPORT 94 /* Socket type not supported */ +#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */ +#define EPFNOSUPPORT 96 /* Protocol family not supported */ +#define EAFNOSUPPORT 97 /* Address family not supported by protocol */ +#define EADDRINUSE 98 /* Address already in use */ +#define EADDRNOTAVAIL 99 /* Cannot assign requested address */ +#define ENETDOWN 100 /* Network is down */ +#define ENETUNREACH 101 /* Network is unreachable */ +#define ENETRESET 102 /* Network dropped connection because of reset */ +#define ECONNABORTED 103 /* Software caused connection abort */ +#define ECONNRESET 104 /* Connection reset by peer */ +#define ENOBUFS 105 /* No buffer space available */ +#define EISCONN 106 /* Transport endpoint is already connected */ +#define ENOTCONN 107 /* Transport endpoint is not connected */ +#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */ +#define ETOOMANYREFS 109 /* Too many references: cannot splice */ +#define ETIMEDOUT 110 /* Connection timed out */ +#define ECONNREFUSED 111 /* Connection refused */ +#define EHOSTDOWN 112 /* Host is down */ +#define EHOSTUNREACH 113 /* No route to host */ +#define EALREADY 114 /* Operation already in progress */ +#define EINPROGRESS 115 /* Operation now in progress */ +#define ESTALE 116 /* Stale NFS file handle */ +#define EUCLEAN 117 /* Structure needs cleaning */ +#define ENOTNAM 118 /* Not a XENIX named type file */ +#define ENAVAIL 119 /* No XENIX semaphores available */ +#define EISNAM 120 /* Is a named type file */ +#define EREMOTEIO 121 /* Remote I/O error */ +#define EDQUOT 122 /* Quota exceeded */ + +#define ENOMEDIUM 123 /* No medium found */ +#define EMEDIUMTYPE 124 /* Wrong medium type */ +#define ECANCELED 125 /* Operation Canceled */ +#define ENOKEY 126 /* Required key not available */ +#define EKEYEXPIRED 127 /* Key has expired */ +#define EKEYREVOKED 128 /* Key has been revoked */ +#define EKEYREJECTED 129 /* Key was rejected by service */ + +/* for robust mutexes */ +#define EOWNERDEAD 130 /* Owner died */ +#define ENOTRECOVERABLE 131 /* State not recoverable */ + +#endif diff --git a/l4/pkg/uclibc/lib/uclibc/ARCH-amd64/include/asm/ioctls.h b/l4/pkg/uclibc/lib/uclibc/ARCH-amd64/include/asm/ioctls.h new file mode 100644 index 00000000..c9aa270d --- /dev/null +++ b/l4/pkg/uclibc/lib/uclibc/ARCH-amd64/include/asm/ioctls.h @@ -0,0 +1,141 @@ + +/* + * The following is for compatibility across the various Linux + * platforms. The i386 ioctl numbering scheme doesn't really enforce + * a type field. De facto, however, the top 8 bits of the lower 16 + * bits are indeed used as a type field, so we might just as well make + * this explicit here. Please be sure to use the decoding macros + * below from now on. + */ +#define _IOC_NRBITS 8 +#define _IOC_TYPEBITS 8 +#define _IOC_SIZEBITS 14 +#define _IOC_DIRBITS 2 + +#define _IOC_NRMASK ((1 << _IOC_NRBITS)-1) +#define _IOC_TYPEMASK ((1 << _IOC_TYPEBITS)-1) +#define _IOC_SIZEMASK ((1 << _IOC_SIZEBITS)-1) +#define _IOC_DIRMASK ((1 << _IOC_DIRBITS)-1) + +#define _IOC_NRSHIFT 0 +#define _IOC_TYPESHIFT (_IOC_NRSHIFT+_IOC_NRBITS) +#define _IOC_SIZESHIFT (_IOC_TYPESHIFT+_IOC_TYPEBITS) +#define _IOC_DIRSHIFT (_IOC_SIZESHIFT+_IOC_SIZEBITS) + +/* + * Direction bits. + */ +#define _IOC_NONE 0U +#define _IOC_WRITE 1U +#define _IOC_READ 2U + +#define _IOC(dir,type,nr,size) \ + (((dir) << _IOC_DIRSHIFT) | \ + ((type) << _IOC_TYPESHIFT) | \ + ((nr) << _IOC_NRSHIFT) | \ + ((size) << _IOC_SIZESHIFT)) + +/* used to create numbers */ +#define _IO(type,nr) _IOC(_IOC_NONE,(type),(nr),0) +#define _IOR(type,nr,size) _IOC(_IOC_READ,(type),(nr),sizeof(size)) +#define _IOW(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),sizeof(size)) +#define _IOWR(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size)) + +/* used to decode ioctl numbers.. */ +#define _IOC_DIR(nr) (((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK) +#define _IOC_TYPE(nr) (((nr) >> _IOC_TYPESHIFT) & _IOC_TYPEMASK) +#define _IOC_NR(nr) (((nr) >> _IOC_NRSHIFT) & _IOC_NRMASK) +#define _IOC_SIZE(nr) (((nr) >> _IOC_SIZESHIFT) & _IOC_SIZEMASK) + +/* ...and for the drivers/sound files... */ + +#define IOC_IN (_IOC_WRITE << _IOC_DIRSHIFT) +#define IOC_OUT (_IOC_READ << _IOC_DIRSHIFT) +#define IOC_INOUT ((_IOC_WRITE|_IOC_READ) << _IOC_DIRSHIFT) +#define IOCSIZE_MASK (_IOC_SIZEMASK << _IOC_SIZESHIFT) +#define IOCSIZE_SHIFT (_IOC_SIZESHIFT) + +/* 0x54 is just a magic number to make these relatively unique ('T') */ + +#define TCGETS 0x5401 +#define TCSETS 0x5402 +#define TCSETSW 0x5403 +#define TCSETSF 0x5404 +#define TCGETA 0x5405 +#define TCSETA 0x5406 +#define TCSETAW 0x5407 +#define TCSETAF 0x5408 +#define TCSBRK 0x5409 +#define TCXONC 0x540A +#define TCFLSH 0x540B +#define TIOCEXCL 0x540C +#define TIOCNXCL 0x540D +#define TIOCSCTTY 0x540E +#define TIOCGPGRP 0x540F +#define TIOCSPGRP 0x5410 +#define TIOCOUTQ 0x5411 +#define TIOCSTI 0x5412 +#define TIOCGWINSZ 0x5413 +#define TIOCSWINSZ 0x5414 +#define TIOCMGET 0x5415 +#define TIOCMBIS 0x5416 +#define TIOCMBIC 0x5417 +#define TIOCMSET 0x5418 +#define TIOCGSOFTCAR 0x5419 +#define TIOCSSOFTCAR 0x541A +#define FIONREAD 0x541B +#define TIOCINQ FIONREAD +#define TIOCLINUX 0x541C +#define TIOCCONS 0x541D +#define TIOCGSERIAL 0x541E +#define TIOCSSERIAL 0x541F +#define TIOCPKT 0x5420 +#define FIONBIO 0x5421 +#define TIOCNOTTY 0x5422 +#define TIOCSETD 0x5423 +#define TIOCGETD 0x5424 +#define TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */ +#define TIOCTTYGSTRUCT 0x5426 /* For debugging only */ +#define TIOCSBRK 0x5427 /* BSD compatibility */ +#define TIOCCBRK 0x5428 /* BSD compatibility */ +#define TIOCGSID 0x5429 /* Return the session ID of FD */ +#define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */ +#define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */ + +#define FIONCLEX 0x5450 /* these numbers need to be adjusted. */ +#define FIOCLEX 0x5451 +#define FIOASYNC 0x5452 +#define TIOCSERCONFIG 0x5453 +#define TIOCSERGWILD 0x5454 +#define TIOCSERSWILD 0x5455 +#define TIOCGLCKTRMIOS 0x5456 +#define TIOCSLCKTRMIOS 0x5457 +#define TIOCSERGSTRUCT 0x5458 /* For debugging only */ +#define TIOCSERGETLSR 0x5459 /* Get line status register */ +#define TIOCSERGETMULTI 0x545A /* Get multiport config */ +#define TIOCSERSETMULTI 0x545B /* Set multiport config */ + +#define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */ +#define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */ +#define TIOCGHAYESESP 0x545E /* Get Hayes ESP configuration */ +#define TIOCSHAYESESP 0x545F /* Set Hayes ESP configuration */ +#define FIOQSIZE 0x5460 + +/* Used for packet mode */ +#define TIOCPKT_DATA 0 +#define TIOCPKT_FLUSHREAD 1 +#define TIOCPKT_FLUSHWRITE 2 +#define TIOCPKT_STOP 4 +#define TIOCPKT_START 8 +#define TIOCPKT_NOSTOP 16 +#define TIOCPKT_DOSTOP 32 + +#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */ + +/* Socket-level I/O control calls. */ +#define FIOSETOWN 0x8901 +#define SIOCSPGRP 0x8902 +#define FIOGETOWN 0x8903 +#define SIOCGPGRP 0x8904 +#define SIOCATMARK 0x8905 +#define SIOCGSTAMP 0x8906 /* Get stamp */ diff --git a/l4/pkg/uclibc/lib/uclibc/ARCH-amd64/include/asm/sigcontext.h b/l4/pkg/uclibc/lib/uclibc/ARCH-amd64/include/asm/sigcontext.h new file mode 100644 index 00000000..3f99d015 --- /dev/null +++ b/l4/pkg/uclibc/lib/uclibc/ARCH-amd64/include/asm/sigcontext.h @@ -0,0 +1,45 @@ + +struct _fpstate { + unsigned short cwd; + unsigned short swd; + unsigned short twd; /* Note this is not the same as the 32bit/x87/FSAVE twd */ + unsigned short fop; + unsigned long long rip; + unsigned long long rdp; + unsigned int mxcsr; + unsigned int mxcsr_mask; + unsigned int st_space[32]; /* 8*16 bytes for each FP-reg */ + unsigned int xmm_space[64]; /* 16*16 bytes for each XMM-reg */ + unsigned int reserved2[24]; +}; + +struct sigcontext { + unsigned long r8; + unsigned long r9; + unsigned long r10; + unsigned long r11; + unsigned long r12; + unsigned long r13; + unsigned long r14; + unsigned long r15; + unsigned long rdi; + unsigned long rsi; + unsigned long rbp; + unsigned long rbx; + unsigned long rdx; + unsigned long rax; + unsigned long rcx; + unsigned long rsp; + unsigned long rip; + unsigned long eflags; /* RFLAGS */ + unsigned short cs; + unsigned short gs; + unsigned short fs; + unsigned short __pad0; + unsigned long err; + unsigned long trapno; + unsigned long oldmask; + unsigned long cr2; + struct _fpstate *fpstate; /* zero when no FPU context */ + unsigned long reserved1[8]; +}; diff --git a/l4/pkg/uclibc/lib/uclibc/ARCH-amd64/include/asm/socket.h b/l4/pkg/uclibc/lib/uclibc/ARCH-amd64/include/asm/socket.h new file mode 100644 index 00000000..0ce1b865 --- /dev/null +++ b/l4/pkg/uclibc/lib/uclibc/ARCH-amd64/include/asm/socket.h @@ -0,0 +1,48 @@ +#ifndef _ASM_SOCKET_H +#define _ASM_SOCKET_H + +/* For setsockopt(2) */ +#define SOL_SOCKET 1 + +#define SO_DEBUG 1 +#define SO_REUSEADDR 2 +#define SO_TYPE 3 +#define SO_ERROR 4 +#define SO_DONTROUTE 5 +#define SO_BROADCAST 6 +#define SO_SNDBUF 7 +#define SO_RCVBUF 8 +#define SO_KEEPALIVE 9 +#define SO_OOBINLINE 10 +#define SO_NO_CHECK 11 +#define SO_PRIORITY 12 +#define SO_LINGER 13 +#define SO_BSDCOMPAT 14 +/* To add :#define SO_REUSEPORT 15 */ +#define SO_PASSCRED 16 +#define SO_PEERCRED 17 +#define SO_RCVLOWAT 18 +#define SO_SNDLOWAT 19 +#define SO_RCVTIMEO 20 +#define SO_SNDTIMEO 21 + +/* Security levels - as per NRL IPv6 - don't actually do anything */ +#define SO_SECURITY_AUTHENTICATION 22 +#define SO_SECURITY_ENCRYPTION_TRANSPORT 23 +#define SO_SECURITY_ENCRYPTION_NETWORK 24 + +#define SO_BINDTODEVICE 25 + +/* Socket filtering */ +#define SO_ATTACH_FILTER 26 +#define SO_DETACH_FILTER 27 + +#define SO_PEERNAME 28 +#define SO_TIMESTAMP 29 +#define SCM_TIMESTAMP SO_TIMESTAMP + +#define SO_ACCEPTCONN 30 + +#define SO_PEERSEC 31 + +#endif /* _ASM_SOCKET_H */ diff --git a/l4/pkg/uclibc/lib/uclibc/ARCH-amd64/include/bits/uClibc_config.h b/l4/pkg/uclibc/lib/uclibc/ARCH-amd64/include/bits/uClibc_config.h new file mode 100644 index 00000000..d4a5c619 --- /dev/null +++ b/l4/pkg/uclibc/lib/uclibc/ARCH-amd64/include/bits/uClibc_config.h @@ -0,0 +1,291 @@ +#if !defined __FEATURES_H && !defined __need_uClibc_config_h +# error Never include directly; use instead +#endif + +#ifndef libc_hidden_proto +#define libc_hidden_proto(x) +#endif +#ifndef libm_hidden_proto +#define libm_hidden_proto(x) +#endif +#ifndef librt_hidden_proto +#define librt_hidden_proto(x) +#endif + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE 1 +#endif + +#define __UCLIBC_MAJOR__ 0 +#define __UCLIBC_MINOR__ 9 +#define __UCLIBC_SUBLEVEL__ 29 +/* Automatically generated make config: don't edit */ +/* Sun Feb 10 18:15:17 2008 */ +#undef __TARGET_alpha__ +#undef __TARGET_arm__ +#undef __TARGET_avr32__ +#undef __TARGET_bfin__ +#undef __TARGET_cris__ +#undef __TARGET_e1__ +#undef __TARGET_frv__ +#undef __TARGET_h8300__ +#undef __TARGET_hppa__ +#undef __TARGET_i386__ +#undef __TARGET_i960__ +#undef __TARGET_ia64__ +#undef __TARGET_m68k__ +#undef __TARGET_microblaze__ +#undef __TARGET_mips__ +#undef __TARGET_nios__ +#undef __TARGET_nios2__ +#undef __TARGET_powerpc__ +#undef __TARGET_sh__ +#undef __TARGET_sh64__ +#undef __TARGET_sparc__ +#undef __TARGET_v850__ +#undef __TARGET_vax__ +#define __TARGET_x86_64__ 1 +#undef __TARGET_xtensa__ + +/* Target Architecture Features and Options */ +#define __TARGET_ARCH__ "x86_64" +#define __FORCE_OPTIONS_FOR_ARCH__ 1 +#define __CONFIG_GENERIC_386__ 1 +#undef __CONFIG_386__ +#undef __CONFIG_486__ +#undef __CONFIG_586__ +#undef __CONFIG_586MMX__ +#undef __CONFIG_686__ +#undef __CONFIG_PENTIUMII__ +#undef __CONFIG_PENTIUMIII__ +#undef __CONFIG_PENTIUM4__ +#undef __CONFIG_K6__ +#undef __CONFIG_K7__ +#undef __CONFIG_ELAN__ +#undef __CONFIG_CRUSOE__ +#undef __CONFIG_WINCHIPC6__ +#undef __CONFIG_WINCHIP2__ +#undef __CONFIG_CYRIXIII__ +#undef __CONFIG_NEHEMIAH__ +#define __TARGET_SUBARCH__ "" + +/* Using ELF file format */ +#define __ARCH_LITTLE_ENDIAN__ 1 + +/* Using Little Endian */ +#define __ARCH_HAS_MMU__ 1 +#define __ARCH_USE_MMU__ 1 +#define __UCLIBC_HAS_FLOATS__ 1 +/* FM3: For arm. Does not influence x86. */ +#define __UCLIBC_HAS_SOFT_FLOAT__ 1 +#define __HAS_FPU__ 1 +#define __DO_C99_MATH__ 1 +#define __UCLIBC_HAS_LONG_DOUBLE_MATH__ 1 +#define __KERNEL_SOURCE__ "/home/linux" +#define __C_SYMBOL_PREFIX__ "" +#define __HAVE_DOT_CONFIG__ 1 + +/* + * General Library Settings + */ +#undef __HAVE_NO_PIC__ +#define __DOPIC__ 1 +#undef __HAVE_NO_SHARED__ +#define __HAVE_SHARED__ +#undef __ARCH_HAS_NO_LDSO__ +#undef __BUILD_UCLIBC_LDSO__ +#undef __DL_FINI_CRT_COMPAT__ +#define __UCLIBC_CTOR_DTOR__ 1 +#undef __HAS_NO_THREADS__ +#ifndef L4_MINIMAL_LIBC +#define __UCLIBC_HAS_THREADS__ 1 +#define __LINUXTHREADS_OLD__ 1 +#define __UCLIBC_HAS_TLS__ 1 +#define __UCLIBC_HAS_THREADS_NATIVE__ 1 + +#define __UCLIBC_HAS_LFS__ 1 +#define __UCLIBC_STATIC_LDCONFIG__ 1 + +/* + * Networking Support + */ +#define __UCLIBC_HAS_COMPAT_RES_STATE__ 1 +#define __UCLIBC_HAS_IPV4__ 1 + +/* + * String and Stdio Support + */ +#define __UCLIBC_HAS_STRING_GENERIC_OPT__ 1 +#define __UCLIBC_HAS_STRING_ARCH_OPT__ 1 +#define __UCLIBC_HAS_CTYPE_TABLES__ 1 +#define __UCLIBC_HAS_CTYPE_SIGNED__ 1 +#define __UCLIBC_HAS_CTYPE_UNSAFE__ 1 +#undef __UCLIBC_HAS_CTYPE_CHECKED__ +#undef __UCLIBC_HAS_CTYPE_ENFORCED__ +#define __UCLIBC_HAS_WCHAR__ 1 +#undef __UCLIBC_HAS_LOCALE__ +#undef __UCLIBC_HAS_HEXADECIMAL_FLOATS__ +#undef __UCLIBC_HAS_GLIBC_CUSTOM_PRINTF__ +#undef __USE_OLD_VFPRINTF__ +#define __UCLIBC_PRINTF_SCANF_POSITIONAL_ARGS__ 9 +#undef __UCLIBC_HAS_SCANF_GLIBC_A_FLAG__ +#undef __UCLIBC_HAS_STDIO_BUFSIZ_NONE__ +#define __UCLIBC_HAS_STDIO_BUFSIZ_256__ 1 +#undef __UCLIBC_HAS_STDIO_BUFSIZ_512__ +#undef __UCLIBC_HAS_STDIO_BUFSIZ_1024__ +#undef __UCLIBC_HAS_STDIO_BUFSIZ_2048__ +#undef __UCLIBC_HAS_STDIO_BUFSIZ_4096__ +#undef __UCLIBC_HAS_STDIO_BUFSIZ_8192__ +#define __UCLIBC_HAS_STDIO_BUILTIN_BUFFER_NONE__ 1 +#undef __UCLIBC_HAS_STDIO_BUILTIN_BUFFER_4__ +#undef __UCLIBC_HAS_STDIO_BUILTIN_BUFFER_8__ +#undef __UCLIBC_HAS_STDIO_SHUTDOWN_ON_ABORT__ +#define __UCLIBC_HAS_STDIO_GETC_MACRO__ 1 +#define __UCLIBC_HAS_STDIO_PUTC_MACRO__ 1 +#define __UCLIBC_HAS_STDIO_AUTO_RW_TRANSITION__ 1 +#undef __UCLIBC_HAS_FOPEN_LARGEFILE_MODE__ +#undef __UCLIBC_HAS_FOPEN_EXCLUSIVE_MODE__ +#undef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ +#undef __UCLIBC_HAS_PRINTF_M_SPEC__ +#define __UCLIBC_HAS_ERRNO_MESSAGES__ 1 +#undef __UCLIBC_HAS_SYS_ERRLIST__ +#define __UCLIBC_HAS_SIGNUM_MESSAGES__ 1 +#undef __UCLIBC_HAS_SYS_SIGLIST__ +#define __UCLIBC_HAS_GNU_GETOPT__ 1 +#define __UCLIBC_HAS_GNU_GETSUBOPT__ 1 + +/* Big and Tall */ +#define __UCLIBC_HAS_REGEX__ 1 +#define __UCLIBC_HAS_REGEX_OLD__ 1 +#define __UCLIBC_HAS_FNMATCH__ 1 +#define __UCLIBC_HAS_FNMATCH_OLD__ 1 +#undef __UCLIBC_HAS_WORDEXP__ +#undef __UCLIBC_HAS_FTW__ +#define __UCLIBC_HAS_GLOB__ 1 +#define __UCLIBC_HAS_GNU_GLOB__ 1 + +#else /* The minimal version, w/o threads etc. */ + +#define __HAS_NO_THREADS__ 1 +#undef __UCLIBC_HAS_LFS__ +#undef __UCLIBC_STATIC_LDCONFIG__ + +/* + * Networking Support + */ +#undef __UCLIBC_HAS_COMPAT_RES_STATE__ +#undef __UCLIBC_HAS_IPV4__ + +/* + * String and Stdio Support + */ +#define __UCLIBC_HAS_STRING_GENERIC_OPT__ 1 +#define __UCLIBC_HAS_STRING_ARCH_OPT__ 1 +#define __UCLIBC_HAS_CTYPE_TABLES__ 1 +#define __UCLIBC_HAS_CTYPE_SIGNED__ 1 +#define __UCLIBC_HAS_CTYPE_UNSAFE__ 1 +#undef __UCLIBC_HAS_CTYPE_CHECKED__ +#undef __UCLIBC_HAS_CTYPE_ENFORCED__ +#undef __UCLIBC_HAS_WCHAR__ +#undef __UCLIBC_HAS_LOCALE__ +#undef __UCLIBC_HAS_HEXADECIMAL_FLOATS__ +#undef __UCLIBC_HAS_GLIBC_CUSTOM_PRINTF__ +#undef __USE_OLD_VFPRINTF__ +#define __UCLIBC_PRINTF_SCANF_POSITIONAL_ARGS__ 9 +#undef __UCLIBC_HAS_SCANF_GLIBC_A_FLAG__ +#undef __UCLIBC_HAS_STDIO_BUFSIZ_NONE__ +#define __UCLIBC_HAS_STDIO_BUFSIZ_256__ 1 +#undef __UCLIBC_HAS_STDIO_BUFSIZ_512__ +#undef __UCLIBC_HAS_STDIO_BUFSIZ_1024__ +#undef __UCLIBC_HAS_STDIO_BUFSIZ_2048__ +#undef __UCLIBC_HAS_STDIO_BUFSIZ_4096__ +#undef __UCLIBC_HAS_STDIO_BUFSIZ_8192__ +#define __UCLIBC_HAS_STDIO_BUILTIN_BUFFER_NONE__ 1 +#undef __UCLIBC_HAS_STDIO_BUILTIN_BUFFER_4__ +#undef __UCLIBC_HAS_STDIO_BUILTIN_BUFFER_8__ +#undef __UCLIBC_HAS_STDIO_SHUTDOWN_ON_ABORT__ +#define __UCLIBC_HAS_STDIO_GETC_MACRO__ 1 +#define __UCLIBC_HAS_STDIO_PUTC_MACRO__ 1 +#define __UCLIBC_HAS_STDIO_AUTO_RW_TRANSITION__ 1 +#undef __UCLIBC_HAS_FOPEN_LARGEFILE_MODE__ +#undef __UCLIBC_HAS_FOPEN_EXCLUSIVE_MODE__ +#undef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ +#undef __UCLIBC_HAS_PRINTF_M_SPEC__ +#undef __UCLIBC_HAS_ERRNO_MESSAGES__ +#undef __UCLIBC_HAS_SYS_ERRLIST__ +#define __UCLIBC_HAS_SIGNUM_MESSAGES__ 1 +#undef __UCLIBC_HAS_SYS_SIGLIST__ +#define __UCLIBC_HAS_GNU_GETOPT__ 1 +#define __UCLIBC_HAS_GNU_GETSUBOPT__ 1 + +/* Big and Tall */ +#undef __UCLIBC_HAS_REGEX__ +#undef __UCLIBC_HAS_REGEX_OLD__ +#undef __UCLIBC_HAS_FNMATCH__ +#undef __UCLIBC_HAS_FNMATCH_OLD__ +#undef __UCLIBC_HAS_WORDEXP__ +#undef __UCLIBC_HAS_FTW__ +#define __UCLIBC_HAS_GLOB__ 1 +#define __UCLIBC_HAS_GNU_GLOB__ 1 + +#endif + +#undef __MALLOC__ +#undef __MALLOC_SIMPLE__ +#define __MALLOC_STANDARD__ 1 +#undef __MALLOC_GLIBC_COMPAT__ +#undef __UCLIBC_DYNAMIC_ATEXIT__ +#define __UCLIBC_SUSV3_LEGACY__ +#define __UCLIBC_SUSV3_LEGACY_MACROS__ +#define __UCLIBC_SUSV4_LEGACY__ 1 +#undef __HAS_SHADOW__ +#define __UNIX98PTY_ONLY__ 1 +#define __ASSUME_DEVPTS__ 1 +#define __UCLIBC_HAS_TM_EXTENSIONS__ 1 +#define __UCLIBC_HAS_TZ_CACHING__ 1 +#undef __UCLIBC_HAS_TZ_FILE__ +#undef __UCLIBC_HAS_TZ_FILE_READ_MANY__ +#undef __UCLIBC_TZ_FILE_PATH__ + +/* Advanced Library Settings */ +#define __UCLIBC_PWD_BUFFER_SIZE__ 256 +#define __UCLIBC_GRP_BUFFER_SIZE__ 256 + +#define __UCLIBC_HAS_REALTIME__ +#define __UCLIBC_HAS_ADVANCED_REALTIME__ + +/* + * Networking Support + */ +#define __UCLIBC_HAS_IPV6__ 1 +#undef __UCLIBC_HAS_RPC__ +#undef __UCLIBC_USE_NETLINK__ + + +/* Library Installation Options */ +#define __SYSTEM_LDSO__ "/lib/ld-linux.so.2" +#define __RUNTIME_PREFIX__ "/usr/$(TARGET_ARCH)-linux-uclibc/" +#define __DEVEL_PREFIX__ "/usr/$(TARGET_ARCH)-linux-uclibc/usr/" + +/* + * uClibc security related options + */ +#undef __UCLIBC_SECURITY__ + + +/* uClibc development/debugging options */ +#define __CROSS_COMPILER_PREFIX__ "" +#define __UCLIBC_EXTRA_CFLAGS__ "" +#undef __DODEBUG__ +#undef __DODEBUG_PT__ +#define __DOSTRIP__ 1 +#undef __DOASSERTS__ +#define __SUPPORT_LD_DEBUG__ 1 +#undef __SUPPORT_LD_DEBUG_EARLY__ +//#define __SUPPORT_LD_DEBUG_EARLY__ 1 +#define __LDSO_GNU_HASH_SUPPORT__ 1 +#define __UCLIBC_MALLOC_DEBUGGING__ 1 +#define __WARNINGS__ "-Wall" +#undef __EXTRA_WARNINGS__ +#undef __DOMULTI__ +#undef __UCLIBC_MJN3_ONLY__ diff --git a/l4/pkg/uclibc/lib/uclibc/ARCH-amd64/include/linux/limits.h b/l4/pkg/uclibc/lib/uclibc/ARCH-amd64/include/linux/limits.h new file mode 100644 index 00000000..e2074719 --- /dev/null +++ b/l4/pkg/uclibc/lib/uclibc/ARCH-amd64/include/linux/limits.h @@ -0,0 +1,7 @@ +#ifndef _LINUX_LIMITS_H +#define _LINUX_LIMITS_H + +#define PATH_MAX 4096 +#define NAME_MAX 255 + +#endif diff --git a/l4/pkg/uclibc/lib/uclibc/ARCH-amd64/include/linux/param.h b/l4/pkg/uclibc/lib/uclibc/ARCH-amd64/include/linux/param.h new file mode 100644 index 00000000..add9bbd4 --- /dev/null +++ b/l4/pkg/uclibc/lib/uclibc/ARCH-amd64/include/linux/param.h @@ -0,0 +1,6 @@ +#ifndef _LINUX_PARAM_H +#define _LINUX_PARAM_H + +#define MAXHOSTNAMELEN 64 + +#endif diff --git a/l4/pkg/uclibc/lib/uclibc/ARCH-arm/aeabi_read_tp-v6p.S b/l4/pkg/uclibc/lib/uclibc/ARCH-arm/aeabi_read_tp-v6p.S new file mode 100644 index 00000000..49f2ee5b --- /dev/null +++ b/l4/pkg/uclibc/lib/uclibc/ARCH-arm/aeabi_read_tp-v6p.S @@ -0,0 +1,67 @@ + +/* Copyright (C) 2005 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + In addition to the permissions in the GNU Lesser General Public + License, the Free Software Foundation gives you unlimited + permission to link the compiled version of this file with other + programs, and to distribute those programs without any restriction + coming from the use of this file. (The GNU Lesser General Public + License restrictions do apply in other respects; for example, they + cover modification of the file, and distribution when not linked + into another program.) + + Note that people who make modified versions of this file are not + obligated to grant this special exception for their modified + versions; it is their choice whether to do so. The GNU Lesser + General Public License gives permission to release a modified + version without this exception; this exception also makes it + possible to release a modified version which carries forward this + exception. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#ifdef __UCLIBC_HAS_THREADS_NATIVE__ + +//#include + +/* GCC will emit calls to this routine under -mtp=soft. Linux has an + equivalent helper function (which clobbers fewer registers than + a normal function call) in a high page of memory; tail call to the + helper. + + This function is exported from libc for use by user code. libpthread, librt, + and the dynamic linker get their own private copies, for + performance (and in the case of ld.so, out of necessity); those are + all hidden. */ + +#ifndef NOT_IN_libc + .global __aeabi_read_tp +#else + .hidden __aeabi_read_tp +#endif +.global __aeabi_read_tp +.type __aeabi_read_tp,function +.align 4 +__aeabi_read_tp: + mrc p15, 0, r0, c13, c0, 2 + bx lr +.size __aeabi_read_tp,.-__aeabi_read_tp + +#endif /* __UCLIBC_HAS_THREADS_NATIVE__ */ + diff --git a/l4/pkg/uclibc/lib/uclibc/ARCH-arm/aeabi_read_tp_generic.c b/l4/pkg/uclibc/lib/uclibc/ARCH-arm/aeabi_read_tp_generic.c new file mode 100644 index 00000000..8536653c --- /dev/null +++ b/l4/pkg/uclibc/lib/uclibc/ARCH-arm/aeabi_read_tp_generic.c @@ -0,0 +1,15 @@ + +#include +#include + +#ifdef NOT_IN_libc +#define HIDDEN __attribute__((visibility("hidden"),nothrow)) +#else +#define HIDDEN __attribute__((nothrow)) +#endif + +unsigned long HIDDEN __aeabi_read_tp(void); +unsigned long HIDDEN __aeabi_read_tp(void) +{ + return l4_utcb_tcr()->user[0] + TLS_PRE_TCB_SIZE; +} diff --git a/l4/pkg/uclibc/lib/uclibc/ARCH-arm/include/asm/errno.h b/l4/pkg/uclibc/lib/uclibc/ARCH-arm/include/asm/errno.h new file mode 100644 index 00000000..7606c278 --- /dev/null +++ b/l4/pkg/uclibc/lib/uclibc/ARCH-arm/include/asm/errno.h @@ -0,0 +1,147 @@ +#ifndef _ASM_GENERIC_ERRNO_H +#define _ASM_GENERIC_ERRNO_H + + +#ifndef _ASM_GENERIC_ERRNO_BASE_H +#define _ASM_GENERIC_ERRNO_BASE_H + +#define EPERM 1 /* Operation not permitted */ +#define ENOENT 2 /* No such file or directory */ +#define ESRCH 3 /* No such process */ +#define EINTR 4 /* Interrupted system call */ +#define EIO 5 /* I/O error */ +#define ENXIO 6 /* No such device or address */ +#define E2BIG 7 /* Argument list too long */ +#define ENOEXEC 8 /* Exec format error */ +#define EBADF 9 /* Bad file number */ +#define ECHILD 10 /* No child processes */ +#define EAGAIN 11 /* Try again */ +#define ENOMEM 12 /* Out of memory */ +#define EACCES 13 /* Permission denied */ +#define EFAULT 14 /* Bad address */ +#define ENOTBLK 15 /* Block device required */ +#define EBUSY 16 /* Device or resource busy */ +#define EEXIST 17 /* File exists */ +#define EXDEV 18 /* Cross-device link */ +#define ENODEV 19 /* No such device */ +#define ENOTDIR 20 /* Not a directory */ +#define EISDIR 21 /* Is a directory */ +#define EINVAL 22 /* Invalid argument */ +#define ENFILE 23 /* File table overflow */ +#define EMFILE 24 /* Too many open files */ +#define ENOTTY 25 /* Not a typewriter */ +#define ETXTBSY 26 /* Text file busy */ +#define EFBIG 27 /* File too large */ +#define ENOSPC 28 /* No space left on device */ +#define ESPIPE 29 /* Illegal seek */ +#define EROFS 30 /* Read-only file system */ +#define EMLINK 31 /* Too many links */ +#define EPIPE 32 /* Broken pipe */ +#define EDOM 33 /* Math argument out of domain of func */ +#define ERANGE 34 /* Math result not representable */ + +#endif +#define EDEADLK 35 /* Resource deadlock would occur */ +#define ENAMETOOLONG 36 /* File name too long */ +#define ENOLCK 37 /* No record locks available */ +#define ENOSYS 38 /* Function not implemented */ +#define ENOTEMPTY 39 /* Directory not empty */ +#define ELOOP 40 /* Too many symbolic links encountered */ +#define EWOULDBLOCK EAGAIN /* Operation would block */ +#define ENOMSG 42 /* No message of desired type */ +#define EIDRM 43 /* Identifier removed */ +#define ECHRNG 44 /* Channel number out of range */ +#define EL2NSYNC 45 /* Level 2 not synchronized */ +#define EL3HLT 46 /* Level 3 halted */ +#define EL3RST 47 /* Level 3 reset */ +#define ELNRNG 48 /* Link number out of range */ +#define EUNATCH 49 /* Protocol driver not attached */ +#define ENOCSI 50 /* No CSI structure available */ +#define EL2HLT 51 /* Level 2 halted */ +#define EBADE 52 /* Invalid exchange */ +#define EBADR 53 /* Invalid request descriptor */ +#define EXFULL 54 /* Exchange full */ +#define ENOANO 55 /* No anode */ +#define EBADRQC 56 /* Invalid request code */ +#define EBADSLT 57 /* Invalid slot */ + +#define EDEADLOCK EDEADLK + +#define EBFONT 59 /* Bad font file format */ +#define ENOSTR 60 /* Device not a stream */ +#define ENODATA 61 /* No data available */ +#define ETIME 62 /* Timer expired */ +#define ENOSR 63 /* Out of streams resources */ +#define ENONET 64 /* Machine is not on the network */ +#define ENOPKG 65 /* Package not installed */ +#define EREMOTE 66 /* Object is remote */ +#define ENOLINK 67 /* Link has been severed */ +#define EADV 68 /* Advertise error */ +#define ESRMNT 69 /* Srmount error */ +#define ECOMM 70 /* Communication error on send */ +#define EPROTO 71 /* Protocol error */ +#define EMULTIHOP 72 /* Multihop attempted */ +#define EDOTDOT 73 /* RFS specific error */ +#define EBADMSG 74 /* Not a data message */ +#define EOVERFLOW 75 /* Value too large for defined data type */ +#define ENOTUNIQ 76 /* Name not unique on network */ +#define EBADFD 77 /* File descriptor in bad state */ +#define EREMCHG 78 /* Remote address changed */ +#define ELIBACC 79 /* Can not access a needed shared library */ +#define ELIBBAD 80 /* Accessing a corrupted shared library */ +#define ELIBSCN 81 /* .lib section in a.out corrupted */ +#define ELIBMAX 82 /* Attempting to link in too many shared libraries */ +#define ELIBEXEC 83 /* Cannot exec a shared library directly */ +#define EILSEQ 84 /* Illegal byte sequence */ +#define ERESTART 85 /* Interrupted system call should be restarted */ +#define ESTRPIPE 86 /* Streams pipe error */ +#define EUSERS 87 /* Too many users */ +#define ENOTSOCK 88 /* Socket operation on non-socket */ +#define EDESTADDRREQ 89 /* Destination address required */ +#define EMSGSIZE 90 /* Message too long */ +#define EPROTOTYPE 91 /* Protocol wrong type for socket */ +#define ENOPROTOOPT 92 /* Protocol not available */ +#define EPROTONOSUPPORT 93 /* Protocol not supported */ +#define ESOCKTNOSUPPORT 94 /* Socket type not supported */ +#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */ +#define EPFNOSUPPORT 96 /* Protocol family not supported */ +#define EAFNOSUPPORT 97 /* Address family not supported by protocol */ +#define EADDRINUSE 98 /* Address already in use */ +#define EADDRNOTAVAIL 99 /* Cannot assign requested address */ +#define ENETDOWN 100 /* Network is down */ +#define ENETUNREACH 101 /* Network is unreachable */ +#define ENETRESET 102 /* Network dropped connection because of reset */ +#define ECONNABORTED 103 /* Software caused connection abort */ +#define ECONNRESET 104 /* Connection reset by peer */ +#define ENOBUFS 105 /* No buffer space available */ +#define EISCONN 106 /* Transport endpoint is already connected */ +#define ENOTCONN 107 /* Transport endpoint is not connected */ +#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */ +#define ETOOMANYREFS 109 /* Too many references: cannot splice */ +#define ETIMEDOUT 110 /* Connection timed out */ +#define ECONNREFUSED 111 /* Connection refused */ +#define EHOSTDOWN 112 /* Host is down */ +#define EHOSTUNREACH 113 /* No route to host */ +#define EALREADY 114 /* Operation already in progress */ +#define EINPROGRESS 115 /* Operation now in progress */ +#define ESTALE 116 /* Stale NFS file handle */ +#define EUCLEAN 117 /* Structure needs cleaning */ +#define ENOTNAM 118 /* Not a XENIX named type file */ +#define ENAVAIL 119 /* No XENIX semaphores available */ +#define EISNAM 120 /* Is a named type file */ +#define EREMOTEIO 121 /* Remote I/O error */ +#define EDQUOT 122 /* Quota exceeded */ + +#define ENOMEDIUM 123 /* No medium found */ +#define EMEDIUMTYPE 124 /* Wrong medium type */ +#define ECANCELED 125 /* Operation Canceled */ +#define ENOKEY 126 /* Required key not available */ +#define EKEYEXPIRED 127 /* Key has expired */ +#define EKEYREVOKED 128 /* Key has been revoked */ +#define EKEYREJECTED 129 /* Key was rejected by service */ + +/* for robust mutexes */ +#define EOWNERDEAD 130 /* Owner died */ +#define ENOTRECOVERABLE 131 /* State not recoverable */ + +#endif diff --git a/l4/pkg/uclibc/lib/uclibc/ARCH-arm/include/asm/ioctls.h b/l4/pkg/uclibc/lib/uclibc/ARCH-arm/include/asm/ioctls.h new file mode 100644 index 00000000..ab8b844a --- /dev/null +++ b/l4/pkg/uclibc/lib/uclibc/ARCH-arm/include/asm/ioctls.h @@ -0,0 +1,149 @@ + +/* ioctl command encoding: 32 bits total, command in lower 16 bits, + * size of the parameter structure in the lower 14 bits of the + * upper 16 bits. + * Encoding the size of the parameter structure in the ioctl request + * is useful for catching programs compiled with old versions + * and to avoid overwriting user space outside the user buffer area. + * The highest 2 bits are reserved for indicating the ``access mode''. + * NOTE: This limits the max parameter size to 16kB -1 ! + */ + +/* + * The following is for compatibility across the various Linux + * platforms. The i386 ioctl numbering scheme doesn't really enforce + * a type field. De facto, however, the top 8 bits of the lower 16 + * bits are indeed used as a type field, so we might just as well make + * this explicit here. Please be sure to use the decoding macros + * below from now on. + */ +#define _IOC_NRBITS 8 +#define _IOC_TYPEBITS 8 +#define _IOC_SIZEBITS 14 +#define _IOC_DIRBITS 2 + +#define _IOC_NRMASK ((1 << _IOC_NRBITS)-1) +#define _IOC_TYPEMASK ((1 << _IOC_TYPEBITS)-1) +#define _IOC_SIZEMASK ((1 << _IOC_SIZEBITS)-1) +#define _IOC_DIRMASK ((1 << _IOC_DIRBITS)-1) + +#define _IOC_NRSHIFT 0 +#define _IOC_TYPESHIFT (_IOC_NRSHIFT+_IOC_NRBITS) +#define _IOC_SIZESHIFT (_IOC_TYPESHIFT+_IOC_TYPEBITS) +#define _IOC_DIRSHIFT (_IOC_SIZESHIFT+_IOC_SIZEBITS) + +/* + * Direction bits. + */ +#define _IOC_NONE 0U +#define _IOC_WRITE 1U +#define _IOC_READ 2U + +#define _IOC(dir,type,nr,size) \ + (((dir) << _IOC_DIRSHIFT) | \ + ((type) << _IOC_TYPESHIFT) | \ + ((nr) << _IOC_NRSHIFT) | \ + ((size) << _IOC_SIZESHIFT)) + +/* used to create numbers */ +#define _IO(type,nr) _IOC(_IOC_NONE,(type),(nr),0) +#define _IOR(type,nr,size) _IOC(_IOC_READ,(type),(nr),sizeof(size)) +#define _IOW(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),sizeof(size)) +#define _IOWR(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size)) + +/* used to decode ioctl numbers.. */ +#define _IOC_DIR(nr) (((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK) +#define _IOC_TYPE(nr) (((nr) >> _IOC_TYPESHIFT) & _IOC_TYPEMASK) +#define _IOC_NR(nr) (((nr) >> _IOC_NRSHIFT) & _IOC_NRMASK) +#define _IOC_SIZE(nr) (((nr) >> _IOC_SIZESHIFT) & _IOC_SIZEMASK) + +/* ...and for the drivers/sound files... */ + +#define IOC_IN (_IOC_WRITE << _IOC_DIRSHIFT) +#define IOC_OUT (_IOC_READ << _IOC_DIRSHIFT) +#define IOC_INOUT ((_IOC_WRITE|_IOC_READ) << _IOC_DIRSHIFT) +#define IOCSIZE_MASK (_IOC_SIZEMASK << _IOC_SIZESHIFT) +#define IOCSIZE_SHIFT (_IOC_SIZESHIFT) + +/* 0x54 is just a magic number to make these relatively unique ('T') */ + +#define TCGETS 0x5401 +#define TCSETS 0x5402 +#define TCSETSW 0x5403 +#define TCSETSF 0x5404 +#define TCGETA 0x5405 +#define TCSETA 0x5406 +#define TCSETAW 0x5407 +#define TCSETAF 0x5408 +#define TCSBRK 0x5409 +#define TCXONC 0x540A +#define TCFLSH 0x540B +#define TIOCEXCL 0x540C +#define TIOCNXCL 0x540D +#define TIOCSCTTY 0x540E +#define TIOCGPGRP 0x540F +#define TIOCSPGRP 0x5410 +#define TIOCOUTQ 0x5411 +#define TIOCSTI 0x5412 +#define TIOCGWINSZ 0x5413 +#define TIOCSWINSZ 0x5414 +#define TIOCMGET 0x5415 +#define TIOCMBIS 0x5416 +#define TIOCMBIC 0x5417 +#define TIOCMSET 0x5418 +#define TIOCGSOFTCAR 0x5419 +#define TIOCSSOFTCAR 0x541A +#define FIONREAD 0x541B +#define TIOCINQ FIONREAD +#define TIOCLINUX 0x541C +#define TIOCCONS 0x541D +#define TIOCGSERIAL 0x541E +#define TIOCSSERIAL 0x541F +#define TIOCPKT 0x5420 +#define FIONBIO 0x5421 +#define TIOCNOTTY 0x5422 +#define TIOCSETD 0x5423 +#define TIOCGETD 0x5424 +#define TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */ +#define TIOCTTYGSTRUCT 0x5426 /* For debugging only */ +#define TIOCSBRK 0x5427 /* BSD compatibility */ +#define TIOCCBRK 0x5428 /* BSD compatibility */ +#define TIOCGSID 0x5429 /* Return the session ID of FD */ +#define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */ +#define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */ + +#define FIONCLEX 0x5450 /* these numbers need to be adjusted. */ +#define FIOCLEX 0x5451 +#define FIOASYNC 0x5452 +#define TIOCSERCONFIG 0x5453 +#define TIOCSERGWILD 0x5454 +#define TIOCSERSWILD 0x5455 +#define TIOCGLCKTRMIOS 0x5456 +#define TIOCSLCKTRMIOS 0x5457 +#define TIOCSERGSTRUCT 0x5458 /* For debugging only */ +#define TIOCSERGETLSR 0x5459 /* Get line status register */ +#define TIOCSERGETMULTI 0x545A /* Get multiport config */ +#define TIOCSERSETMULTI 0x545B /* Set multiport config */ + +#define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */ +#define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */ +#define FIOQSIZE 0x545E + +/* Used for packet mode */ +#define TIOCPKT_DATA 0 +#define TIOCPKT_FLUSHREAD 1 +#define TIOCPKT_FLUSHWRITE 2 +#define TIOCPKT_STOP 4 +#define TIOCPKT_START 8 +#define TIOCPKT_NOSTOP 16 +#define TIOCPKT_DOSTOP 32 + +#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */ + +/* Socket-level I/O control calls. */ +#define FIOSETOWN 0x8901 +#define SIOCSPGRP 0x8902 +#define FIOGETOWN 0x8903 +#define SIOCGPGRP 0x8904 +#define SIOCATMARK 0x8905 +#define SIOCGSTAMP 0x8906 /* Get stamp */ diff --git a/l4/pkg/uclibc/lib/uclibc/ARCH-arm/include/asm/sigcontext.h b/l4/pkg/uclibc/lib/uclibc/ARCH-arm/include/asm/sigcontext.h new file mode 100644 index 00000000..26fa04e6 --- /dev/null +++ b/l4/pkg/uclibc/lib/uclibc/ARCH-arm/include/asm/sigcontext.h @@ -0,0 +1,32 @@ + +#define PC(ctx) (ctx.arm_pc) + +/* + * Signal context structure - contains all info to do with the state + * before the signal handler was invoked. Note: only add new entries + * to the end of the structure. + */ +struct sigcontext { + unsigned long trap_no; + unsigned long error_code; + unsigned long oldmask; + unsigned long arm_r0; + unsigned long arm_r1; + unsigned long arm_r2; + unsigned long arm_r3; + unsigned long arm_r4; + unsigned long arm_r5; + unsigned long arm_r6; + unsigned long arm_r7; + unsigned long arm_r8; + unsigned long arm_r9; + unsigned long arm_r10; + unsigned long arm_fp; + unsigned long arm_ip; + unsigned long arm_sp; + unsigned long arm_lr; + unsigned long arm_pc; + unsigned long arm_cpsr; + unsigned long fault_address; +}; + diff --git a/l4/pkg/uclibc/lib/uclibc/ARCH-arm/include/asm/socket.h b/l4/pkg/uclibc/lib/uclibc/ARCH-arm/include/asm/socket.h new file mode 100644 index 00000000..73a636ce --- /dev/null +++ b/l4/pkg/uclibc/lib/uclibc/ARCH-arm/include/asm/socket.h @@ -0,0 +1,48 @@ +#ifndef _ASM_SOCKET_H +#define _ASM_SOCKET_H + +/* For setsockopt(2) */ +#define SOL_SOCKET 1 + +#define SO_DEBUG 1 +#define SO_REUSEADDR 2 +#define SO_TYPE 3 +#define SO_ERROR 4 +#define SO_DONTROUTE 5 +#define SO_BROADCAST 6 +#define SO_SNDBUF 7 +#define SO_RCVBUF 8 +#define SO_KEEPALIVE 9 +#define SO_OOBINLINE 10 +#define SO_NO_CHECK 11 +#define SO_PRIORITY 12 +#define SO_LINGER 13 +#define SO_BSDCOMPAT 14 +/* To add :#define SO_REUSEPORT 15 */ +#define SO_PASSCRED 16 +#define SO_PEERCRED 17 +#define SO_RCVLOWAT 18 +#define SO_SNDLOWAT 19 +#define SO_RCVTIMEO 20 +#define SO_SNDTIMEO 21 + +/* Security levels - as per NRL IPv6 - don't actually do anything */ +#define SO_SECURITY_AUTHENTICATION 22 +#define SO_SECURITY_ENCRYPTION_TRANSPORT 23 +#define SO_SECURITY_ENCRYPTION_NETWORK 24 + +#define SO_BINDTODEVICE 25 + +/* Socket filtering */ +#define SO_ATTACH_FILTER 26 +#define SO_DETACH_FILTER 27 + +#define SO_PEERNAME 28 +#define SO_TIMESTAMP 29 +#define SCM_TIMESTAMP SO_TIMESTAMP + +#define SO_ACCEPTCONN 30 + +#define SO_PEERSEC 31 + +#endif /* _ASM_SOCKET_H */ diff --git a/l4/pkg/uclibc/lib/uclibc/ARCH-arm/include/bits/uClibc_config.h b/l4/pkg/uclibc/lib/uclibc/ARCH-arm/include/bits/uClibc_config.h new file mode 100644 index 00000000..e9a7e719 --- /dev/null +++ b/l4/pkg/uclibc/lib/uclibc/ARCH-arm/include/bits/uClibc_config.h @@ -0,0 +1,290 @@ +#if !defined __FEATURES_H && !defined __need_uClibc_config_h +# error Never include directly; use instead +#endif + +#ifndef libc_hidden_proto +#define libc_hidden_proto(x) +#endif +#ifndef libm_hidden_proto +#define libm_hidden_proto(x) +#endif +#ifndef librt_hidden_proto +#define librt_hidden_proto(x) +#endif + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE 1 +#endif + +#define __UCLIBC_MAJOR__ 0 +#define __UCLIBC_MINOR__ 9 +#define __UCLIBC_SUBLEVEL__ 29 +/* Automatically generated make config: don't edit */ +/* Sun Feb 10 18:15:17 2008 */ +#undef __TARGET_alpha__ +#define __TARGET_arm__ 1 +#undef __TARGET_avr32__ +#undef __TARGET_bfin__ +#undef __TARGET_cris__ +#undef __TARGET_e1__ +#undef __TARGET_frv__ +#undef __TARGET_h8300__ +#undef __TARGET_hppa__ +#undef __TARGET_i386__ +#undef __TARGET_i960__ +#undef __TARGET_ia64__ +#undef __TARGET_m68k__ +#undef __TARGET_microblaze__ +#undef __TARGET_mips__ +#undef __TARGET_nios__ +#undef __TARGET_nios2__ +#undef __TARGET_powerpc__ +#undef __TARGET_sh__ +#undef __TARGET_sh64__ +#undef __TARGET_sparc__ +#undef __TARGET_v850__ +#undef __TARGET_vax__ +#undef __TARGET_x86_64__ +#undef __TARGET_xtensa__ + +/* Target Architecture Features and Options */ +#define __TARGET_ARCH__ "arm" +#define __FORCE_OPTIONS_FOR_ARCH__ 1 +#undef __CONFIG_GENERIC_386__ +#undef __CONFIG_386__ +#undef __CONFIG_486__ +#undef __CONFIG_586__ +#undef __CONFIG_586MMX__ +#undef __CONFIG_686__ +#undef __CONFIG_PENTIUMII__ +#undef __CONFIG_PENTIUMIII__ +#undef __CONFIG_PENTIUM4__ +#undef __CONFIG_K6__ +#undef __CONFIG_K7__ +#undef __CONFIG_ELAN__ +#undef __CONFIG_CRUSOE__ +#undef __CONFIG_WINCHIPC6__ +#undef __CONFIG_WINCHIP2__ +#undef __CONFIG_CYRIXIII__ +#undef __CONFIG_NEHEMIAH__ +#define __TARGET_SUBARCH__ "" + +/* Using ELF file format */ +#define __ARCH_LITTLE_ENDIAN__ 1 + +/* Using Little Endian */ +#define __ARCH_HAS_MMU__ 1 +#define __ARCH_USE_MMU__ 1 +#define __UCLIBC_HAS_FLOATS__ 1 +#define __UCLIBC_HAS_SOFT_FLOAT__ 1 +#define __HAS_FPU__ 1 +#define __DO_C99_MATH__ 1 +#define __UCLIBC_HAS_LONG_DOUBLE_MATH__ 1 +#define __KERNEL_SOURCE__ "/home/linux" +#define __C_SYMBOL_PREFIX__ "" +#define __HAVE_DOT_CONFIG__ 1 + +/* + * General Library Settings + */ +#undef __HAVE_NO_PIC__ +#define __DOPIC__ 1 +#undef __HAVE_NO_SHARED__ +#define __HAVE_SHARED__ +#undef __ARCH_HAS_NO_LDSO__ +#undef __BUILD_UCLIBC_LDSO__ +#undef __DL_FINI_CRT_COMPAT__ +#define __UCLIBC_CTOR_DTOR__ 1 +#undef __HAS_NO_THREADS__ +#ifndef L4_MINIMAL_LIBC +#define __UCLIBC_HAS_THREADS__ 1 +#define __LINUXTHREADS_OLD__ 1 +#define __UCLIBC_HAS_TLS__ 1 +#define __UCLIBC_HAS_THREADS_NATIVE__ 1 + +#define __UCLIBC_HAS_LFS__ 1 +#define __UCLIBC_STATIC_LDCONFIG__ 1 + +/* + * Networking Support + */ +#define __UCLIBC_HAS_COMPAT_RES_STATE__ 1 +#define __UCLIBC_HAS_IPV4__ 1 + +/* + * String and Stdio Support + */ +#define __UCLIBC_HAS_STRING_GENERIC_OPT__ 1 +#define __UCLIBC_HAS_STRING_ARCH_OPT__ 1 +#define __UCLIBC_HAS_CTYPE_TABLES__ 1 +#define __UCLIBC_HAS_CTYPE_SIGNED__ 1 +#define __UCLIBC_HAS_CTYPE_UNSAFE__ 1 +#undef __UCLIBC_HAS_CTYPE_CHECKED__ +#undef __UCLIBC_HAS_CTYPE_ENFORCED__ +#define __UCLIBC_HAS_WCHAR__ 1 +#undef __UCLIBC_HAS_LOCALE__ +#undef __UCLIBC_HAS_HEXADECIMAL_FLOATS__ +#undef __UCLIBC_HAS_GLIBC_CUSTOM_PRINTF__ +#undef __USE_OLD_VFPRINTF__ +#define __UCLIBC_PRINTF_SCANF_POSITIONAL_ARGS__ 9 +#undef __UCLIBC_HAS_SCANF_GLIBC_A_FLAG__ +#undef __UCLIBC_HAS_STDIO_BUFSIZ_NONE__ +#define __UCLIBC_HAS_STDIO_BUFSIZ_256__ 1 +#undef __UCLIBC_HAS_STDIO_BUFSIZ_512__ +#undef __UCLIBC_HAS_STDIO_BUFSIZ_1024__ +#undef __UCLIBC_HAS_STDIO_BUFSIZ_2048__ +#undef __UCLIBC_HAS_STDIO_BUFSIZ_4096__ +#undef __UCLIBC_HAS_STDIO_BUFSIZ_8192__ +#define __UCLIBC_HAS_STDIO_BUILTIN_BUFFER_NONE__ 1 +#undef __UCLIBC_HAS_STDIO_BUILTIN_BUFFER_4__ +#undef __UCLIBC_HAS_STDIO_BUILTIN_BUFFER_8__ +#undef __UCLIBC_HAS_STDIO_SHUTDOWN_ON_ABORT__ +#define __UCLIBC_HAS_STDIO_GETC_MACRO__ 1 +#define __UCLIBC_HAS_STDIO_PUTC_MACRO__ 1 +#define __UCLIBC_HAS_STDIO_AUTO_RW_TRANSITION__ 1 +#undef __UCLIBC_HAS_FOPEN_LARGEFILE_MODE__ +#undef __UCLIBC_HAS_FOPEN_EXCLUSIVE_MODE__ +#undef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ +#undef __UCLIBC_HAS_PRINTF_M_SPEC__ +#define __UCLIBC_HAS_ERRNO_MESSAGES__ 1 +#undef __UCLIBC_HAS_SYS_ERRLIST__ +#define __UCLIBC_HAS_SIGNUM_MESSAGES__ 1 +#undef __UCLIBC_HAS_SYS_SIGLIST__ +#define __UCLIBC_HAS_GNU_GETOPT__ 1 +#define __UCLIBC_HAS_GNU_GETSUBOPT__ 1 + +/* Big and Tall */ +#define __UCLIBC_HAS_REGEX__ 1 +#define __UCLIBC_HAS_REGEX_OLD__ 1 +#define __UCLIBC_HAS_FNMATCH__ 1 +#define __UCLIBC_HAS_FNMATCH_OLD__ 1 +#undef __UCLIBC_HAS_WORDEXP__ +#undef __UCLIBC_HAS_FTW__ +#define __UCLIBC_HAS_GLOB__ 1 +#define __UCLIBC_HAS_GNU_GLOB__ 1 + +#else /* The minimal version, w/o threads etc. */ + +#define __HAS_NO_THREADS__ 1 +#undef __UCLIBC_HAS_LFS__ +#undef __UCLIBC_STATIC_LDCONFIG__ + +/* + * Networking Support + */ +#undef __UCLIBC_HAS_COMPAT_RES_STATE__ +#undef __UCLIBC_HAS_IPV4__ + +/* + * String and Stdio Support + */ +#define __UCLIBC_HAS_STRING_GENERIC_OPT__ 1 +#define __UCLIBC_HAS_STRING_ARCH_OPT__ 1 +#define __UCLIBC_HAS_CTYPE_TABLES__ 1 +#define __UCLIBC_HAS_CTYPE_SIGNED__ 1 +#define __UCLIBC_HAS_CTYPE_UNSAFE__ 1 +#undef __UCLIBC_HAS_CTYPE_CHECKED__ +#undef __UCLIBC_HAS_CTYPE_ENFORCED__ +#undef __UCLIBC_HAS_WCHAR__ +#undef __UCLIBC_HAS_LOCALE__ +#undef __UCLIBC_HAS_HEXADECIMAL_FLOATS__ +#undef __UCLIBC_HAS_GLIBC_CUSTOM_PRINTF__ +#undef __USE_OLD_VFPRINTF__ +#define __UCLIBC_PRINTF_SCANF_POSITIONAL_ARGS__ 9 +#undef __UCLIBC_HAS_SCANF_GLIBC_A_FLAG__ +#undef __UCLIBC_HAS_STDIO_BUFSIZ_NONE__ +#define __UCLIBC_HAS_STDIO_BUFSIZ_256__ 1 +#undef __UCLIBC_HAS_STDIO_BUFSIZ_512__ +#undef __UCLIBC_HAS_STDIO_BUFSIZ_1024__ +#undef __UCLIBC_HAS_STDIO_BUFSIZ_2048__ +#undef __UCLIBC_HAS_STDIO_BUFSIZ_4096__ +#undef __UCLIBC_HAS_STDIO_BUFSIZ_8192__ +#define __UCLIBC_HAS_STDIO_BUILTIN_BUFFER_NONE__ 1 +#undef __UCLIBC_HAS_STDIO_BUILTIN_BUFFER_4__ +#undef __UCLIBC_HAS_STDIO_BUILTIN_BUFFER_8__ +#undef __UCLIBC_HAS_STDIO_SHUTDOWN_ON_ABORT__ +#define __UCLIBC_HAS_STDIO_GETC_MACRO__ 1 +#define __UCLIBC_HAS_STDIO_PUTC_MACRO__ 1 +#define __UCLIBC_HAS_STDIO_AUTO_RW_TRANSITION__ 1 +#undef __UCLIBC_HAS_FOPEN_LARGEFILE_MODE__ +#undef __UCLIBC_HAS_FOPEN_EXCLUSIVE_MODE__ +#undef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ +#undef __UCLIBC_HAS_PRINTF_M_SPEC__ +#undef __UCLIBC_HAS_ERRNO_MESSAGES__ +#undef __UCLIBC_HAS_SYS_ERRLIST__ +#define __UCLIBC_HAS_SIGNUM_MESSAGES__ 1 +#undef __UCLIBC_HAS_SYS_SIGLIST__ +#define __UCLIBC_HAS_GNU_GETOPT__ 1 +#define __UCLIBC_HAS_GNU_GETSUBOPT__ 1 + +/* Big and Tall */ +#undef __UCLIBC_HAS_REGEX__ +#undef __UCLIBC_HAS_REGEX_OLD__ +#undef __UCLIBC_HAS_FNMATCH__ +#undef __UCLIBC_HAS_FNMATCH_OLD__ +#undef __UCLIBC_HAS_WORDEXP__ +#undef __UCLIBC_HAS_FTW__ +#define __UCLIBC_HAS_GLOB__ 1 +#define __UCLIBC_HAS_GNU_GLOB__ 1 + +#endif + +#undef __MALLOC__ +#undef __MALLOC_SIMPLE__ +#define __MALLOC_STANDARD__ 1 +#undef __MALLOC_GLIBC_COMPAT__ +#undef __UCLIBC_DYNAMIC_ATEXIT__ +#define __UCLIBC_SUSV3_LEGACY__ +#define __UCLIBC_SUSV3_LEGACY_MACROS__ +#define __UCLIBC_SUSV4_LEGACY__ 1 +#undef __HAS_SHADOW__ +#define __UNIX98PTY_ONLY__ 1 +#define __ASSUME_DEVPTS__ 1 +#define __UCLIBC_HAS_TM_EXTENSIONS__ 1 +#define __UCLIBC_HAS_TZ_CACHING__ 1 +#undef __UCLIBC_HAS_TZ_FILE__ +#undef __UCLIBC_HAS_TZ_FILE_READ_MANY__ +#undef __UCLIBC_TZ_FILE_PATH__ + +/* Advanced Library Settings */ +#define __UCLIBC_PWD_BUFFER_SIZE__ 256 +#define __UCLIBC_GRP_BUFFER_SIZE__ 256 + +#define __UCLIBC_HAS_REALTIME__ +#define __UCLIBC_HAS_ADVANCED_REALTIME__ + +/* + * Networking Support + */ +#define __UCLIBC_HAS_IPV6__ 1 +#undef __UCLIBC_HAS_RPC__ +#undef __UCLIBC_USE_NETLINK__ + + +/* Library Installation Options */ +#define __SYSTEM_LDSO__ "/lib/ld-linux.so.2" +#define __RUNTIME_PREFIX__ "/usr/$(TARGET_ARCH)-linux-uclibc/" +#define __DEVEL_PREFIX__ "/usr/$(TARGET_ARCH)-linux-uclibc/usr/" + +/* + * uClibc security related options + */ +#undef __UCLIBC_SECURITY__ + + +/* uClibc development/debugging options */ +#define __CROSS_COMPILER_PREFIX__ "" +#define __UCLIBC_EXTRA_CFLAGS__ "" +#undef __DODEBUG__ +#undef __DODEBUG_PT__ +#define __DOSTRIP__ 1 +#undef __DOASSERTS__ +#define __SUPPORT_LD_DEBUG__ 1 +#undef __SUPPORT_LD_DEBUG_EARLY__ +//#define __SUPPORT_LD_DEBUG_EARLY__ 1 +#define __LDSO_GNU_HASH_SUPPORT__ 1 +#define __UCLIBC_MALLOC_DEBUGGING__ 1 +#define __WARNINGS__ "-Wall" +#undef __EXTRA_WARNINGS__ +#undef __DOMULTI__ +#undef __UCLIBC_MJN3_ONLY__ diff --git a/l4/pkg/uclibc/lib/uclibc/ARCH-arm/include/linux/limits.h b/l4/pkg/uclibc/lib/uclibc/ARCH-arm/include/linux/limits.h new file mode 100644 index 00000000..e2074719 --- /dev/null +++ b/l4/pkg/uclibc/lib/uclibc/ARCH-arm/include/linux/limits.h @@ -0,0 +1,7 @@ +#ifndef _LINUX_LIMITS_H +#define _LINUX_LIMITS_H + +#define PATH_MAX 4096 +#define NAME_MAX 255 + +#endif diff --git a/l4/pkg/uclibc/lib/uclibc/ARCH-arm/include/linux/param.h b/l4/pkg/uclibc/lib/uclibc/ARCH-arm/include/linux/param.h new file mode 100644 index 00000000..add9bbd4 --- /dev/null +++ b/l4/pkg/uclibc/lib/uclibc/ARCH-arm/include/linux/param.h @@ -0,0 +1,6 @@ +#ifndef _LINUX_PARAM_H +#define _LINUX_PARAM_H + +#define MAXHOSTNAMELEN 64 + +#endif diff --git a/l4/pkg/uclibc/lib/uclibc/ARCH-ppc32/include/asm/errno.h b/l4/pkg/uclibc/lib/uclibc/ARCH-ppc32/include/asm/errno.h new file mode 100644 index 00000000..7606c278 --- /dev/null +++ b/l4/pkg/uclibc/lib/uclibc/ARCH-ppc32/include/asm/errno.h @@ -0,0 +1,147 @@ +#ifndef _ASM_GENERIC_ERRNO_H +#define _ASM_GENERIC_ERRNO_H + + +#ifndef _ASM_GENERIC_ERRNO_BASE_H +#define _ASM_GENERIC_ERRNO_BASE_H + +#define EPERM 1 /* Operation not permitted */ +#define ENOENT 2 /* No such file or directory */ +#define ESRCH 3 /* No such process */ +#define EINTR 4 /* Interrupted system call */ +#define EIO 5 /* I/O error */ +#define ENXIO 6 /* No such device or address */ +#define E2BIG 7 /* Argument list too long */ +#define ENOEXEC 8 /* Exec format error */ +#define EBADF 9 /* Bad file number */ +#define ECHILD 10 /* No child processes */ +#define EAGAIN 11 /* Try again */ +#define ENOMEM 12 /* Out of memory */ +#define EACCES 13 /* Permission denied */ +#define EFAULT 14 /* Bad address */ +#define ENOTBLK 15 /* Block device required */ +#define EBUSY 16 /* Device or resource busy */ +#define EEXIST 17 /* File exists */ +#define EXDEV 18 /* Cross-device link */ +#define ENODEV 19 /* No such device */ +#define ENOTDIR 20 /* Not a directory */ +#define EISDIR 21 /* Is a directory */ +#define EINVAL 22 /* Invalid argument */ +#define ENFILE 23 /* File table overflow */ +#define EMFILE 24 /* Too many open files */ +#define ENOTTY 25 /* Not a typewriter */ +#define ETXTBSY 26 /* Text file busy */ +#define EFBIG 27 /* File too large */ +#define ENOSPC 28 /* No space left on device */ +#define ESPIPE 29 /* Illegal seek */ +#define EROFS 30 /* Read-only file system */ +#define EMLINK 31 /* Too many links */ +#define EPIPE 32 /* Broken pipe */ +#define EDOM 33 /* Math argument out of domain of func */ +#define ERANGE 34 /* Math result not representable */ + +#endif +#define EDEADLK 35 /* Resource deadlock would occur */ +#define ENAMETOOLONG 36 /* File name too long */ +#define ENOLCK 37 /* No record locks available */ +#define ENOSYS 38 /* Function not implemented */ +#define ENOTEMPTY 39 /* Directory not empty */ +#define ELOOP 40 /* Too many symbolic links encountered */ +#define EWOULDBLOCK EAGAIN /* Operation would block */ +#define ENOMSG 42 /* No message of desired type */ +#define EIDRM 43 /* Identifier removed */ +#define ECHRNG 44 /* Channel number out of range */ +#define EL2NSYNC 45 /* Level 2 not synchronized */ +#define EL3HLT 46 /* Level 3 halted */ +#define EL3RST 47 /* Level 3 reset */ +#define ELNRNG 48 /* Link number out of range */ +#define EUNATCH 49 /* Protocol driver not attached */ +#define ENOCSI 50 /* No CSI structure available */ +#define EL2HLT 51 /* Level 2 halted */ +#define EBADE 52 /* Invalid exchange */ +#define EBADR 53 /* Invalid request descriptor */ +#define EXFULL 54 /* Exchange full */ +#define ENOANO 55 /* No anode */ +#define EBADRQC 56 /* Invalid request code */ +#define EBADSLT 57 /* Invalid slot */ + +#define EDEADLOCK EDEADLK + +#define EBFONT 59 /* Bad font file format */ +#define ENOSTR 60 /* Device not a stream */ +#define ENODATA 61 /* No data available */ +#define ETIME 62 /* Timer expired */ +#define ENOSR 63 /* Out of streams resources */ +#define ENONET 64 /* Machine is not on the network */ +#define ENOPKG 65 /* Package not installed */ +#define EREMOTE 66 /* Object is remote */ +#define ENOLINK 67 /* Link has been severed */ +#define EADV 68 /* Advertise error */ +#define ESRMNT 69 /* Srmount error */ +#define ECOMM 70 /* Communication error on send */ +#define EPROTO 71 /* Protocol error */ +#define EMULTIHOP 72 /* Multihop attempted */ +#define EDOTDOT 73 /* RFS specific error */ +#define EBADMSG 74 /* Not a data message */ +#define EOVERFLOW 75 /* Value too large for defined data type */ +#define ENOTUNIQ 76 /* Name not unique on network */ +#define EBADFD 77 /* File descriptor in bad state */ +#define EREMCHG 78 /* Remote address changed */ +#define ELIBACC 79 /* Can not access a needed shared library */ +#define ELIBBAD 80 /* Accessing a corrupted shared library */ +#define ELIBSCN 81 /* .lib section in a.out corrupted */ +#define ELIBMAX 82 /* Attempting to link in too many shared libraries */ +#define ELIBEXEC 83 /* Cannot exec a shared library directly */ +#define EILSEQ 84 /* Illegal byte sequence */ +#define ERESTART 85 /* Interrupted system call should be restarted */ +#define ESTRPIPE 86 /* Streams pipe error */ +#define EUSERS 87 /* Too many users */ +#define ENOTSOCK 88 /* Socket operation on non-socket */ +#define EDESTADDRREQ 89 /* Destination address required */ +#define EMSGSIZE 90 /* Message too long */ +#define EPROTOTYPE 91 /* Protocol wrong type for socket */ +#define ENOPROTOOPT 92 /* Protocol not available */ +#define EPROTONOSUPPORT 93 /* Protocol not supported */ +#define ESOCKTNOSUPPORT 94 /* Socket type not supported */ +#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */ +#define EPFNOSUPPORT 96 /* Protocol family not supported */ +#define EAFNOSUPPORT 97 /* Address family not supported by protocol */ +#define EADDRINUSE 98 /* Address already in use */ +#define EADDRNOTAVAIL 99 /* Cannot assign requested address */ +#define ENETDOWN 100 /* Network is down */ +#define ENETUNREACH 101 /* Network is unreachable */ +#define ENETRESET 102 /* Network dropped connection because of reset */ +#define ECONNABORTED 103 /* Software caused connection abort */ +#define ECONNRESET 104 /* Connection reset by peer */ +#define ENOBUFS 105 /* No buffer space available */ +#define EISCONN 106 /* Transport endpoint is already connected */ +#define ENOTCONN 107 /* Transport endpoint is not connected */ +#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */ +#define ETOOMANYREFS 109 /* Too many references: cannot splice */ +#define ETIMEDOUT 110 /* Connection timed out */ +#define ECONNREFUSED 111 /* Connection refused */ +#define EHOSTDOWN 112 /* Host is down */ +#define EHOSTUNREACH 113 /* No route to host */ +#define EALREADY 114 /* Operation already in progress */ +#define EINPROGRESS 115 /* Operation now in progress */ +#define ESTALE 116 /* Stale NFS file handle */ +#define EUCLEAN 117 /* Structure needs cleaning */ +#define ENOTNAM 118 /* Not a XENIX named type file */ +#define ENAVAIL 119 /* No XENIX semaphores available */ +#define EISNAM 120 /* Is a named type file */ +#define EREMOTEIO 121 /* Remote I/O error */ +#define EDQUOT 122 /* Quota exceeded */ + +#define ENOMEDIUM 123 /* No medium found */ +#define EMEDIUMTYPE 124 /* Wrong medium type */ +#define ECANCELED 125 /* Operation Canceled */ +#define ENOKEY 126 /* Required key not available */ +#define EKEYEXPIRED 127 /* Key has expired */ +#define EKEYREVOKED 128 /* Key has been revoked */ +#define EKEYREJECTED 129 /* Key was rejected by service */ + +/* for robust mutexes */ +#define EOWNERDEAD 130 /* Owner died */ +#define ENOTRECOVERABLE 131 /* State not recoverable */ + +#endif diff --git a/l4/pkg/uclibc/lib/uclibc/ARCH-ppc32/include/asm/ioctl.h b/l4/pkg/uclibc/lib/uclibc/ARCH-ppc32/include/asm/ioctl.h new file mode 100644 index 00000000..c76795ff --- /dev/null +++ b/l4/pkg/uclibc/lib/uclibc/ARCH-ppc32/include/asm/ioctl.h @@ -0,0 +1,73 @@ +#ifndef _ASM_POWERPC_IOCTL_H +#define _ASM_POWERPC_IOCTL_H + + +/* + * this was copied from the alpha as it's a bit cleaner there. + * -- Cort + */ + +#define _IOC_NRBITS 8 +#define _IOC_TYPEBITS 8 +#define _IOC_SIZEBITS 13 +#define _IOC_DIRBITS 3 + +#define _IOC_NRMASK ((1 << _IOC_NRBITS)-1) +#define _IOC_TYPEMASK ((1 << _IOC_TYPEBITS)-1) +#define _IOC_SIZEMASK ((1 << _IOC_SIZEBITS)-1) +#define _IOC_DIRMASK ((1 << _IOC_DIRBITS)-1) + +#define _IOC_NRSHIFT 0 +#define _IOC_TYPESHIFT (_IOC_NRSHIFT+_IOC_NRBITS) +#define _IOC_SIZESHIFT (_IOC_TYPESHIFT+_IOC_TYPEBITS) +#define _IOC_DIRSHIFT (_IOC_SIZESHIFT+_IOC_SIZEBITS) + +/* + * Direction bits _IOC_NONE could be 0, but OSF/1 gives it a bit. + * And this turns out useful to catch old ioctl numbers in header + * files for us. + */ +#define _IOC_NONE 1U +#define _IOC_READ 2U +#define _IOC_WRITE 4U + +#define _IOC(dir,type,nr,size) \ + (((dir) << _IOC_DIRSHIFT) | \ + ((type) << _IOC_TYPESHIFT) | \ + ((nr) << _IOC_NRSHIFT) | \ + ((size) << _IOC_SIZESHIFT)) + +#ifdef __KERNEL__ +/* provoke compile error for invalid uses of size argument */ +extern unsigned int __invalid_size_argument_for_IOC; +#define _IOC_TYPECHECK(t) \ + ((sizeof(t) == sizeof(t[1]) && \ + sizeof(t) < (1 << _IOC_SIZEBITS)) ? \ + sizeof(t) : __invalid_size_argument_for_IOC) +#else +#define _IOC_TYPECHECK(t) sizeof(t) +#endif + +/* used to create numbers */ +#define _IO(type,nr) _IOC(_IOC_NONE,(type),(nr),0) +#define _IOR(type,nr,size) _IOC(_IOC_READ,(type),(nr),(_IOC_TYPECHECK(size))) +#define _IOW(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size))) +#define _IOWR(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size))) +#define _IOR_BAD(type,nr,size) _IOC(_IOC_READ,(type),(nr),sizeof(size)) +#define _IOW_BAD(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),sizeof(size)) +#define _IOWR_BAD(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size)) + +/* used to decode them.. */ +#define _IOC_DIR(nr) (((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK) +#define _IOC_TYPE(nr) (((nr) >> _IOC_TYPESHIFT) & _IOC_TYPEMASK) +#define _IOC_NR(nr) (((nr) >> _IOC_NRSHIFT) & _IOC_NRMASK) +#define _IOC_SIZE(nr) (((nr) >> _IOC_SIZESHIFT) & _IOC_SIZEMASK) + +/* various drivers, such as the pcmcia stuff, need these... */ +#define IOC_IN (_IOC_WRITE << _IOC_DIRSHIFT) +#define IOC_OUT (_IOC_READ << _IOC_DIRSHIFT) +#define IOC_INOUT ((_IOC_WRITE|_IOC_READ) << _IOC_DIRSHIFT) +#define IOCSIZE_MASK (_IOC_SIZEMASK << _IOC_SIZESHIFT) +#define IOCSIZE_SHIFT (_IOC_SIZESHIFT) + +#endif /* _ASM_POWERPC_IOCTL_H */ diff --git a/l4/pkg/uclibc/lib/uclibc/ARCH-ppc32/include/asm/ioctls.h b/l4/pkg/uclibc/lib/uclibc/ARCH-ppc32/include/asm/ioctls.h new file mode 100644 index 00000000..279a6229 --- /dev/null +++ b/l4/pkg/uclibc/lib/uclibc/ARCH-ppc32/include/asm/ioctls.h @@ -0,0 +1,110 @@ +#ifndef _ASM_POWERPC_IOCTLS_H +#define _ASM_POWERPC_IOCTLS_H + +#include + +#define FIOCLEX _IO('f', 1) +#define FIONCLEX _IO('f', 2) +#define FIOASYNC _IOW('f', 125, int) +#define FIONBIO _IOW('f', 126, int) +#define FIONREAD _IOR('f', 127, int) +#define TIOCINQ FIONREAD +#define FIOQSIZE _IOR('f', 128, loff_t) + +#define TIOCGETP _IOR('t', 8, struct sgttyb) +#define TIOCSETP _IOW('t', 9, struct sgttyb) +#define TIOCSETN _IOW('t', 10, struct sgttyb) /* TIOCSETP wo flush */ + +#define TIOCSETC _IOW('t', 17, struct tchars) +#define TIOCGETC _IOR('t', 18, struct tchars) +#define TCGETS _IOR('t', 19, struct termios) +#define TCSETS _IOW('t', 20, struct termios) +#define TCSETSW _IOW('t', 21, struct termios) +#define TCSETSF _IOW('t', 22, struct termios) + +#define TCGETA _IOR('t', 23, struct termio) +#define TCSETA _IOW('t', 24, struct termio) +#define TCSETAW _IOW('t', 25, struct termio) +#define TCSETAF _IOW('t', 28, struct termio) + +#define TCSBRK _IO('t', 29) +#define TCXONC _IO('t', 30) +#define TCFLSH _IO('t', 31) + +#define TIOCSWINSZ _IOW('t', 103, struct winsize) +#define TIOCGWINSZ _IOR('t', 104, struct winsize) +#define TIOCSTART _IO('t', 110) /* start output, like ^Q */ +#define TIOCSTOP _IO('t', 111) /* stop output, like ^S */ +#define TIOCOUTQ _IOR('t', 115, int) /* output queue size */ + +#define TIOCGLTC _IOR('t', 116, struct ltchars) +#define TIOCSLTC _IOW('t', 117, struct ltchars) +#define TIOCSPGRP _IOW('t', 118, int) +#define TIOCGPGRP _IOR('t', 119, int) + +#define TIOCEXCL 0x540C +#define TIOCNXCL 0x540D +#define TIOCSCTTY 0x540E + +#define TIOCSTI 0x5412 +#define TIOCMGET 0x5415 +#define TIOCMBIS 0x5416 +#define TIOCMBIC 0x5417 +#define TIOCMSET 0x5418 +# define TIOCM_LE 0x001 +# define TIOCM_DTR 0x002 +# define TIOCM_RTS 0x004 +# define TIOCM_ST 0x008 +# define TIOCM_SR 0x010 +# define TIOCM_CTS 0x020 +# define TIOCM_CAR 0x040 +# define TIOCM_RNG 0x080 +# define TIOCM_DSR 0x100 +# define TIOCM_CD TIOCM_CAR +# define TIOCM_RI TIOCM_RNG +#define TIOCM_OUT1 0x2000 +#define TIOCM_OUT2 0x4000 +#define TIOCM_LOOP 0x8000 + +#define TIOCGSOFTCAR 0x5419 +#define TIOCSSOFTCAR 0x541A +#define TIOCLINUX 0x541C +#define TIOCCONS 0x541D +#define TIOCGSERIAL 0x541E +#define TIOCSSERIAL 0x541F +#define TIOCPKT 0x5420 +# define TIOCPKT_DATA 0 +# define TIOCPKT_FLUSHREAD 1 +# define TIOCPKT_FLUSHWRITE 2 +# define TIOCPKT_STOP 4 +# define TIOCPKT_START 8 +# define TIOCPKT_NOSTOP 16 +# define TIOCPKT_DOSTOP 32 + + +#define TIOCNOTTY 0x5422 +#define TIOCSETD 0x5423 +#define TIOCGETD 0x5424 +#define TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */ +#define TIOCSBRK 0x5427 /* BSD compatibility */ +#define TIOCCBRK 0x5428 /* BSD compatibility */ +#define TIOCGSID 0x5429 /* Return the session ID of FD */ +#define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */ +#define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */ + +#define TIOCSERCONFIG 0x5453 +#define TIOCSERGWILD 0x5454 +#define TIOCSERSWILD 0x5455 +#define TIOCGLCKTRMIOS 0x5456 +#define TIOCSLCKTRMIOS 0x5457 +#define TIOCSERGSTRUCT 0x5458 /* For debugging only */ +#define TIOCSERGETLSR 0x5459 /* Get line status register */ + /* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */ +# define TIOCSER_TEMT 0x01 /* Transmitter physically empty */ +#define TIOCSERGETMULTI 0x545A /* Get multiport config */ +#define TIOCSERSETMULTI 0x545B /* Set multiport config */ + +#define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */ +#define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */ + +#endif /* _ASM_POWERPC_IOCTLS_H */ diff --git a/l4/pkg/uclibc/lib/uclibc/ARCH-ppc32/include/asm/sigcontext.h b/l4/pkg/uclibc/lib/uclibc/ARCH-ppc32/include/asm/sigcontext.h new file mode 100644 index 00000000..51600204 --- /dev/null +++ b/l4/pkg/uclibc/lib/uclibc/ARCH-ppc32/include/asm/sigcontext.h @@ -0,0 +1,40 @@ +#ifndef _ASM_POWERPC_SIGCONTEXT_H +#define _ASM_POWERPC_SIGCONTEXT_H + +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +struct pt_regs { + unsigned long gpr[32]; + unsigned long nip; + unsigned long msr; + unsigned long orig_gpr3; /* Used for restarting system calls */ + unsigned long ctr; + unsigned long link; + unsigned long xer; + unsigned long ccr; + unsigned long mq; /* 601 only (not used at present) */ + unsigned long trap; /* Reason for being here */ + /* N.B. for critical exceptions on 4xx, the dar and dsisr + fields are overloaded to hold srr0 and srr1. */ + unsigned long dar; /* Fault registers */ + unsigned long dsisr; /* on 4xx/Book-E used for ESR */ + unsigned long result; /* Result of a system call */ +}; + +struct sigcontext { + unsigned long _unused[4]; + int signal; +#ifdef __powerpc64__ + int _pad0; +#endif + unsigned long handler; + unsigned long oldmask; + struct pt_regs *regs; +}; + +#endif /* _ASM_POWERPC_SIGCONTEXT_H */ diff --git a/l4/pkg/uclibc/lib/uclibc/ARCH-ppc32/include/asm/socket.h b/l4/pkg/uclibc/lib/uclibc/ARCH-ppc32/include/asm/socket.h new file mode 100644 index 00000000..403e9fde --- /dev/null +++ b/l4/pkg/uclibc/lib/uclibc/ARCH-ppc32/include/asm/socket.h @@ -0,0 +1,62 @@ +#ifndef _ASM_POWERPC_SOCKET_H +#define _ASM_POWERPC_SOCKET_H + +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include + +/* For setsockopt(2) */ +#define SOL_SOCKET 1 + +#define SO_DEBUG 1 +#define SO_REUSEADDR 2 +#define SO_TYPE 3 +#define SO_ERROR 4 +#define SO_DONTROUTE 5 +#define SO_BROADCAST 6 +#define SO_SNDBUF 7 +#define SO_RCVBUF 8 +#define SO_SNDBUFFORCE 32 +#define SO_RCVBUFFORCE 33 +#define SO_KEEPALIVE 9 +#define SO_OOBINLINE 10 +#define SO_NO_CHECK 11 +#define SO_PRIORITY 12 +#define SO_LINGER 13 +#define SO_BSDCOMPAT 14 +/* To add :#define SO_REUSEPORT 15 */ +#define SO_RCVLOWAT 16 +#define SO_SNDLOWAT 17 +#define SO_RCVTIMEO 18 +#define SO_SNDTIMEO 19 +#define SO_PASSCRED 20 +#define SO_PEERCRED 21 + +/* Security levels - as per NRL IPv6 - don't actually do anything */ +#define SO_SECURITY_AUTHENTICATION 22 +#define SO_SECURITY_ENCRYPTION_TRANSPORT 23 +#define SO_SECURITY_ENCRYPTION_NETWORK 24 + +#define SO_BINDTODEVICE 25 + +/* Socket filtering */ +#define SO_ATTACH_FILTER 26 +#define SO_DETACH_FILTER 27 + +#define SO_PEERNAME 28 +#define SO_TIMESTAMP 29 +#define SCM_TIMESTAMP SO_TIMESTAMP + +#define SO_ACCEPTCONN 30 + +#define SO_PEERSEC 31 +#define SO_PASSSEC 34 +#define SO_TIMESTAMPNS 35 +#define SCM_TIMESTAMPNS SO_TIMESTAMPNS + +#endif /* _ASM_POWERPC_SOCKET_H */ diff --git a/l4/pkg/uclibc/lib/uclibc/ARCH-ppc32/include/asm/sockios.h b/l4/pkg/uclibc/lib/uclibc/ARCH-ppc32/include/asm/sockios.h new file mode 100644 index 00000000..55cef767 --- /dev/null +++ b/l4/pkg/uclibc/lib/uclibc/ARCH-ppc32/include/asm/sockios.h @@ -0,0 +1,20 @@ +#ifndef _ASM_POWERPC_SOCKIOS_H +#define _ASM_POWERPC_SOCKIOS_H + +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +/* Socket-level I/O control calls. */ +#define FIOSETOWN 0x8901 +#define SIOCSPGRP 0x8902 +#define FIOGETOWN 0x8903 +#define SIOCGPGRP 0x8904 +#define SIOCATMARK 0x8905 +#define SIOCGSTAMP 0x8906 /* Get stamp (timeval) */ +#define SIOCGSTAMPNS 0x8907 /* Get stamp (timespec) */ + +#endif /* _ASM_POWERPC_SOCKIOS_H */ diff --git a/l4/pkg/uclibc/lib/uclibc/ARCH-ppc32/include/bits/uClibc_config.h b/l4/pkg/uclibc/lib/uclibc/ARCH-ppc32/include/bits/uClibc_config.h new file mode 100644 index 00000000..0d8e0e81 --- /dev/null +++ b/l4/pkg/uclibc/lib/uclibc/ARCH-ppc32/include/bits/uClibc_config.h @@ -0,0 +1,290 @@ +#if !defined __FEATURES_H && !defined __need_uClibc_config_h +# error Never include directly; use instead +#endif + +#ifndef libc_hidden_proto +#define libc_hidden_proto(x) +#endif +#ifndef libm_hidden_proto +#define libm_hidden_proto(x) +#endif +#ifndef librt_hidden_proto +#define librt_hidden_proto(x) +#endif + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE 1 +#endif + +#define __UCLIBC_MAJOR__ 0 +#define __UCLIBC_MINOR__ 9 +#define __UCLIBC_SUBLEVEL__ 29 +/* Automatically generated make config: don't edit */ +/* Sun Feb 10 18:15:17 2008 */ +#undef __TARGET_alpha__ +#undef __TARGET_arm__ +#undef __TARGET_avr32__ +#undef __TARGET_bfin__ +#undef __TARGET_cris__ +#undef __TARGET_e1__ +#undef __TARGET_frv__ +#undef __TARGET_h8300__ +#undef __TARGET_hppa__ +#undef __TARGET_i386__ +#undef __TARGET_i960__ +#undef __TARGET_ia64__ +#undef __TARGET_m68k__ +#undef __TARGET_microblaze__ +#undef __TARGET_mips__ +#undef __TARGET_nios__ +#undef __TARGET_nios2__ +#define __TARGET_powerpc__ 1 +#undef __TARGET_sh__ +#undef __TARGET_sh64__ +#undef __TARGET_sparc__ +#undef __TARGET_v850__ +#undef __TARGET_vax__ +#undef __TARGET_x86_64__ +#undef __TARGET_xtensa__ + +/* Target Architecture Features and Options */ +#define __TARGET_ARCH__ "powerpc" +#define __FORCE_OPTIONS_FOR_ARCH__ 1 +#undef __CONFIG_GENERIC_386__ +#undef __CONFIG_386__ +#undef __CONFIG_486__ +#undef __CONFIG_586__ +#undef __CONFIG_586MMX__ +#undef __CONFIG_686__ +#undef __CONFIG_PENTIUMII__ +#undef __CONFIG_PENTIUMIII__ +#undef __CONFIG_PENTIUM4__ +#undef __CONFIG_K6__ +#undef __CONFIG_K7__ +#undef __CONFIG_ELAN__ +#undef __CONFIG_CRUSOE__ +#undef __CONFIG_WINCHIPC6__ +#undef __CONFIG_WINCHIP2__ +#undef __CONFIG_CYRIXIII__ +#undef __CONFIG_NEHEMIAH__ +#define __TARGET_SUBARCH__ "" + +/* Using ELF file format */ +#define __ARCH_LITTLE_ENDIAN__ 1 + +/* Using Little Endian */ +#define __ARCH_HAS_MMU__ 1 +#define __ARCH_USE_MMU__ 1 +#define __UCLIBC_HAS_FLOATS__ 1 +#define __UCLIBC_HAS_SOFT_FLOAT__ 1 +#define __HAS_FPU__ 1 +#define __DO_C99_MATH__ 1 +#define __UCLIBC_HAS_LONG_DOUBLE_MATH__ 1 +#define __KERNEL_SOURCE__ "/home/linux" +#define __C_SYMBOL_PREFIX__ "" +#define __HAVE_DOT_CONFIG__ 1 + +/* + * General Library Settings + */ +#undef __HAVE_NO_PIC__ +#define __DOPIC__ 1 +#undef __HAVE_NO_SHARED__ +#define __HAVE_SHARED__ +#undef __ARCH_HAS_NO_LDSO__ +#undef __BUILD_UCLIBC_LDSO__ +#undef __DL_FINI_CRT_COMPAT__ +#define __UCLIBC_CTOR_DTOR__ 1 +#undef __HAS_NO_THREADS__ +#ifndef L4_MINIMAL_LIBC +#define __UCLIBC_HAS_THREADS__ 1 +#define __LINUXTHREADS_OLD__ 1 +#define __UCLIBC_HAS_TLS__ 1 +#define __UCLIBC_HAS_THREADS_NATIVE__ 1 + +#define __UCLIBC_HAS_LFS__ 1 +#define __UCLIBC_STATIC_LDCONFIG__ 1 + +/* + * Networking Support + */ +#define __UCLIBC_HAS_COMPAT_RES_STATE__ 1 +#define __UCLIBC_HAS_IPV4__ 1 + +/* + * String and Stdio Support + */ +#define __UCLIBC_HAS_STRING_GENERIC_OPT__ 1 +#define __UCLIBC_HAS_STRING_ARCH_OPT__ 1 +#define __UCLIBC_HAS_CTYPE_TABLES__ 1 +#define __UCLIBC_HAS_CTYPE_SIGNED__ 1 +#define __UCLIBC_HAS_CTYPE_UNSAFE__ 1 +#undef __UCLIBC_HAS_CTYPE_CHECKED__ +#undef __UCLIBC_HAS_CTYPE_ENFORCED__ +#define __UCLIBC_HAS_WCHAR__ 1 +#undef __UCLIBC_HAS_LOCALE__ +#undef __UCLIBC_HAS_HEXADECIMAL_FLOATS__ +#undef __UCLIBC_HAS_GLIBC_CUSTOM_PRINTF__ +#undef __USE_OLD_VFPRINTF__ +#define __UCLIBC_PRINTF_SCANF_POSITIONAL_ARGS__ 9 +#undef __UCLIBC_HAS_SCANF_GLIBC_A_FLAG__ +#undef __UCLIBC_HAS_STDIO_BUFSIZ_NONE__ +#define __UCLIBC_HAS_STDIO_BUFSIZ_256__ 1 +#undef __UCLIBC_HAS_STDIO_BUFSIZ_512__ +#undef __UCLIBC_HAS_STDIO_BUFSIZ_1024__ +#undef __UCLIBC_HAS_STDIO_BUFSIZ_2048__ +#undef __UCLIBC_HAS_STDIO_BUFSIZ_4096__ +#undef __UCLIBC_HAS_STDIO_BUFSIZ_8192__ +#define __UCLIBC_HAS_STDIO_BUILTIN_BUFFER_NONE__ 1 +#undef __UCLIBC_HAS_STDIO_BUILTIN_BUFFER_4__ +#undef __UCLIBC_HAS_STDIO_BUILTIN_BUFFER_8__ +#undef __UCLIBC_HAS_STDIO_SHUTDOWN_ON_ABORT__ +#define __UCLIBC_HAS_STDIO_GETC_MACRO__ 1 +#define __UCLIBC_HAS_STDIO_PUTC_MACRO__ 1 +#define __UCLIBC_HAS_STDIO_AUTO_RW_TRANSITION__ 1 +#undef __UCLIBC_HAS_FOPEN_LARGEFILE_MODE__ +#undef __UCLIBC_HAS_FOPEN_EXCLUSIVE_MODE__ +#undef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ +#undef __UCLIBC_HAS_PRINTF_M_SPEC__ +#define __UCLIBC_HAS_ERRNO_MESSAGES__ 1 +#undef __UCLIBC_HAS_SYS_ERRLIST__ +#define __UCLIBC_HAS_SIGNUM_MESSAGES__ 1 +#undef __UCLIBC_HAS_SYS_SIGLIST__ +#define __UCLIBC_HAS_GNU_GETOPT__ 1 +#define __UCLIBC_HAS_GNU_GETSUBOPT__ 1 + +/* Big and Tall */ +#define __UCLIBC_HAS_REGEX__ 1 +#define __UCLIBC_HAS_REGEX_OLD__ 1 +#define __UCLIBC_HAS_FNMATCH__ 1 +#define __UCLIBC_HAS_FNMATCH_OLD__ 1 +#undef __UCLIBC_HAS_WORDEXP__ +#undef __UCLIBC_HAS_FTW__ +#define __UCLIBC_HAS_GLOB__ 1 +#define __UCLIBC_HAS_GNU_GLOB__ 1 + +#else /* The minimal version, w/o threads etc. */ + +#define __HAS_NO_THREADS__ 1 +#undef __UCLIBC_HAS_LFS__ +#undef __UCLIBC_STATIC_LDCONFIG__ + +/* + * Networking Support + */ +#undef __UCLIBC_HAS_COMPAT_RES_STATE__ +#undef __UCLIBC_HAS_IPV4__ + +/* + * String and Stdio Support + */ +#define __UCLIBC_HAS_STRING_GENERIC_OPT__ 1 +#define __UCLIBC_HAS_STRING_ARCH_OPT__ 1 +#define __UCLIBC_HAS_CTYPE_TABLES__ 1 +#define __UCLIBC_HAS_CTYPE_SIGNED__ 1 +#define __UCLIBC_HAS_CTYPE_UNSAFE__ 1 +#undef __UCLIBC_HAS_CTYPE_CHECKED__ +#undef __UCLIBC_HAS_CTYPE_ENFORCED__ +#undef __UCLIBC_HAS_WCHAR__ +#undef __UCLIBC_HAS_LOCALE__ +#undef __UCLIBC_HAS_HEXADECIMAL_FLOATS__ +#undef __UCLIBC_HAS_GLIBC_CUSTOM_PRINTF__ +#undef __USE_OLD_VFPRINTF__ +#define __UCLIBC_PRINTF_SCANF_POSITIONAL_ARGS__ 9 +#undef __UCLIBC_HAS_SCANF_GLIBC_A_FLAG__ +#undef __UCLIBC_HAS_STDIO_BUFSIZ_NONE__ +#define __UCLIBC_HAS_STDIO_BUFSIZ_256__ 1 +#undef __UCLIBC_HAS_STDIO_BUFSIZ_512__ +#undef __UCLIBC_HAS_STDIO_BUFSIZ_1024__ +#undef __UCLIBC_HAS_STDIO_BUFSIZ_2048__ +#undef __UCLIBC_HAS_STDIO_BUFSIZ_4096__ +#undef __UCLIBC_HAS_STDIO_BUFSIZ_8192__ +#define __UCLIBC_HAS_STDIO_BUILTIN_BUFFER_NONE__ 1 +#undef __UCLIBC_HAS_STDIO_BUILTIN_BUFFER_4__ +#undef __UCLIBC_HAS_STDIO_BUILTIN_BUFFER_8__ +#undef __UCLIBC_HAS_STDIO_SHUTDOWN_ON_ABORT__ +#define __UCLIBC_HAS_STDIO_GETC_MACRO__ 1 +#define __UCLIBC_HAS_STDIO_PUTC_MACRO__ 1 +#define __UCLIBC_HAS_STDIO_AUTO_RW_TRANSITION__ 1 +#undef __UCLIBC_HAS_FOPEN_LARGEFILE_MODE__ +#undef __UCLIBC_HAS_FOPEN_EXCLUSIVE_MODE__ +#undef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ +#undef __UCLIBC_HAS_PRINTF_M_SPEC__ +#undef __UCLIBC_HAS_ERRNO_MESSAGES__ +#undef __UCLIBC_HAS_SYS_ERRLIST__ +#define __UCLIBC_HAS_SIGNUM_MESSAGES__ 1 +#undef __UCLIBC_HAS_SYS_SIGLIST__ +#define __UCLIBC_HAS_GNU_GETOPT__ 1 +#define __UCLIBC_HAS_GNU_GETSUBOPT__ 1 + +/* Big and Tall */ +#undef __UCLIBC_HAS_REGEX__ +#undef __UCLIBC_HAS_REGEX_OLD__ +#undef __UCLIBC_HAS_FNMATCH__ +#undef __UCLIBC_HAS_FNMATCH_OLD__ +#undef __UCLIBC_HAS_WORDEXP__ +#undef __UCLIBC_HAS_FTW__ +#define __UCLIBC_HAS_GLOB__ 1 +#define __UCLIBC_HAS_GNU_GLOB__ 1 + +#endif + +#undef __MALLOC__ +#undef __MALLOC_SIMPLE__ +#define __MALLOC_STANDARD__ 1 +#undef __MALLOC_GLIBC_COMPAT__ +#undef __UCLIBC_DYNAMIC_ATEXIT__ +#define __UCLIBC_SUSV3_LEGACY__ +#define __UCLIBC_SUSV3_LEGACY_MACROS__ +#define __UCLIBC_SUSV4_LEGACY__ 1 +#undef __HAS_SHADOW__ +#define __UNIX98PTY_ONLY__ 1 +#define __ASSUME_DEVPTS__ 1 +#define __UCLIBC_HAS_TM_EXTENSIONS__ 1 +#define __UCLIBC_HAS_TZ_CACHING__ 1 +#undef __UCLIBC_HAS_TZ_FILE__ +#undef __UCLIBC_HAS_TZ_FILE_READ_MANY__ +#undef __UCLIBC_TZ_FILE_PATH__ + +/* Advanced Library Settings */ +#define __UCLIBC_PWD_BUFFER_SIZE__ 256 +#define __UCLIBC_GRP_BUFFER_SIZE__ 256 + +#define __UCLIBC_HAS_REALTIME__ +#define __UCLIBC_HAS_ADVANCED_REALTIME__ + +/* + * Networking Support + */ +#define __UCLIBC_HAS_IPV6__ 1 +#undef __UCLIBC_HAS_RPC__ +#undef __UCLIBC_USE_NETLINK__ + + +/* Library Installation Options */ +#define __SYSTEM_LDSO__ "/lib/ld-linux.so.2" +#define __RUNTIME_PREFIX__ "/usr/$(TARGET_ARCH)-linux-uclibc/" +#define __DEVEL_PREFIX__ "/usr/$(TARGET_ARCH)-linux-uclibc/usr/" + +/* + * uClibc security related options + */ +#undef __UCLIBC_SECURITY__ + + +/* uClibc development/debugging options */ +#define __CROSS_COMPILER_PREFIX__ "" +#define __UCLIBC_EXTRA_CFLAGS__ "" +#undef __DODEBUG__ +#undef __DODEBUG_PT__ +#define __DOSTRIP__ 1 +#undef __DOASSERTS__ +#define __SUPPORT_LD_DEBUG__ 1 +#undef __SUPPORT_LD_DEBUG_EARLY__ +//#define __SUPPORT_LD_DEBUG_EARLY__ 1 +#define __LDSO_GNU_HASH_SUPPORT__ 1 +#define __UCLIBC_MALLOC_DEBUGGING__ 1 +#define __WARNINGS__ "-Wall" +#undef __EXTRA_WARNINGS__ +#undef __DOMULTI__ +#undef __UCLIBC_MJN3_ONLY__ diff --git a/l4/pkg/uclibc/lib/uclibc/ARCH-ppc32/include/linux/limits.h b/l4/pkg/uclibc/lib/uclibc/ARCH-ppc32/include/linux/limits.h new file mode 100644 index 00000000..eaf2e099 --- /dev/null +++ b/l4/pkg/uclibc/lib/uclibc/ARCH-ppc32/include/linux/limits.h @@ -0,0 +1,22 @@ +#ifndef _LINUX_LIMITS_H +#define _LINUX_LIMITS_H + +#define NR_OPEN 1024 + +#define NGROUPS_MAX 65536 /* supplemental group IDs are available */ +#define ARG_MAX 131072 /* # bytes of args + environ for exec() */ +#define CHILD_MAX 999 /* no limit :-) */ +#define OPEN_MAX 256 /* # open files a process may have */ +#define LINK_MAX 127 /* # links a file may have */ +#define MAX_CANON 255 /* size of the canonical input queue */ +#define MAX_INPUT 255 /* size of the type-ahead buffer */ +#define NAME_MAX 255 /* # chars in a file name */ +#define PATH_MAX 4096 /* # chars in a path name including nul */ +#define PIPE_BUF 4096 /* # bytes in atomic write to a pipe */ +#define XATTR_NAME_MAX 255 /* # chars in an extended attribute name */ +#define XATTR_SIZE_MAX 65536 /* size of an extended attribute value (64k) */ +#define XATTR_LIST_MAX 65536 /* size of extended attribute namelist (64k) */ + +#define RTSIG_MAX 32 + +#endif diff --git a/l4/pkg/uclibc/lib/uclibc/ARCH-ppc32/include/linux/param.h b/l4/pkg/uclibc/lib/uclibc/ARCH-ppc32/include/linux/param.h new file mode 100644 index 00000000..094f63d4 --- /dev/null +++ b/l4/pkg/uclibc/lib/uclibc/ARCH-ppc32/include/linux/param.h @@ -0,0 +1,22 @@ +#ifndef _ASM_POWERPC_PARAM_H +#define _ASM_POWERPC_PARAM_H + +#ifdef __KERNEL__ +#define HZ CONFIG_HZ /* internal kernel timer frequency */ +#define USER_HZ 100 /* for user interfaces in "ticks" */ +#define CLOCKS_PER_SEC (USER_HZ) /* frequency at which times() counts */ +#endif /* __KERNEL__ */ + +#ifndef HZ +#define HZ 100 +#endif + +#define EXEC_PAGESIZE 4096 + +#ifndef NOGROUP +#define NOGROUP (-1) +#endif + +#define MAXHOSTNAMELEN 64 /* max length of hostname */ + +#endif /* _ASM_POWERPC_PARAM_H */ diff --git a/l4/pkg/uclibc/lib/uclibc/ARCH-sparc/include/asm/errno.h b/l4/pkg/uclibc/lib/uclibc/ARCH-sparc/include/asm/errno.h new file mode 100644 index 00000000..7606c278 --- /dev/null +++ b/l4/pkg/uclibc/lib/uclibc/ARCH-sparc/include/asm/errno.h @@ -0,0 +1,147 @@ +#ifndef _ASM_GENERIC_ERRNO_H +#define _ASM_GENERIC_ERRNO_H + + +#ifndef _ASM_GENERIC_ERRNO_BASE_H +#define _ASM_GENERIC_ERRNO_BASE_H + +#define EPERM 1 /* Operation not permitted */ +#define ENOENT 2 /* No such file or directory */ +#define ESRCH 3 /* No such process */ +#define EINTR 4 /* Interrupted system call */ +#define EIO 5 /* I/O error */ +#define ENXIO 6 /* No such device or address */ +#define E2BIG 7 /* Argument list too long */ +#define ENOEXEC 8 /* Exec format error */ +#define EBADF 9 /* Bad file number */ +#define ECHILD 10 /* No child processes */ +#define EAGAIN 11 /* Try again */ +#define ENOMEM 12 /* Out of memory */ +#define EACCES 13 /* Permission denied */ +#define EFAULT 14 /* Bad address */ +#define ENOTBLK 15 /* Block device required */ +#define EBUSY 16 /* Device or resource busy */ +#define EEXIST 17 /* File exists */ +#define EXDEV 18 /* Cross-device link */ +#define ENODEV 19 /* No such device */ +#define ENOTDIR 20 /* Not a directory */ +#define EISDIR 21 /* Is a directory */ +#define EINVAL 22 /* Invalid argument */ +#define ENFILE 23 /* File table overflow */ +#define EMFILE 24 /* Too many open files */ +#define ENOTTY 25 /* Not a typewriter */ +#define ETXTBSY 26 /* Text file busy */ +#define EFBIG 27 /* File too large */ +#define ENOSPC 28 /* No space left on device */ +#define ESPIPE 29 /* Illegal seek */ +#define EROFS 30 /* Read-only file system */ +#define EMLINK 31 /* Too many links */ +#define EPIPE 32 /* Broken pipe */ +#define EDOM 33 /* Math argument out of domain of func */ +#define ERANGE 34 /* Math result not representable */ + +#endif +#define EDEADLK 35 /* Resource deadlock would occur */ +#define ENAMETOOLONG 36 /* File name too long */ +#define ENOLCK 37 /* No record locks available */ +#define ENOSYS 38 /* Function not implemented */ +#define ENOTEMPTY 39 /* Directory not empty */ +#define ELOOP 40 /* Too many symbolic links encountered */ +#define EWOULDBLOCK EAGAIN /* Operation would block */ +#define ENOMSG 42 /* No message of desired type */ +#define EIDRM 43 /* Identifier removed */ +#define ECHRNG 44 /* Channel number out of range */ +#define EL2NSYNC 45 /* Level 2 not synchronized */ +#define EL3HLT 46 /* Level 3 halted */ +#define EL3RST 47 /* Level 3 reset */ +#define ELNRNG 48 /* Link number out of range */ +#define EUNATCH 49 /* Protocol driver not attached */ +#define ENOCSI 50 /* No CSI structure available */ +#define EL2HLT 51 /* Level 2 halted */ +#define EBADE 52 /* Invalid exchange */ +#define EBADR 53 /* Invalid request descriptor */ +#define EXFULL 54 /* Exchange full */ +#define ENOANO 55 /* No anode */ +#define EBADRQC 56 /* Invalid request code */ +#define EBADSLT 57 /* Invalid slot */ + +#define EDEADLOCK EDEADLK + +#define EBFONT 59 /* Bad font file format */ +#define ENOSTR 60 /* Device not a stream */ +#define ENODATA 61 /* No data available */ +#define ETIME 62 /* Timer expired */ +#define ENOSR 63 /* Out of streams resources */ +#define ENONET 64 /* Machine is not on the network */ +#define ENOPKG 65 /* Package not installed */ +#define EREMOTE 66 /* Object is remote */ +#define ENOLINK 67 /* Link has been severed */ +#define EADV 68 /* Advertise error */ +#define ESRMNT 69 /* Srmount error */ +#define ECOMM 70 /* Communication error on send */ +#define EPROTO 71 /* Protocol error */ +#define EMULTIHOP 72 /* Multihop attempted */ +#define EDOTDOT 73 /* RFS specific error */ +#define EBADMSG 74 /* Not a data message */ +#define EOVERFLOW 75 /* Value too large for defined data type */ +#define ENOTUNIQ 76 /* Name not unique on network */ +#define EBADFD 77 /* File descriptor in bad state */ +#define EREMCHG 78 /* Remote address changed */ +#define ELIBACC 79 /* Can not access a needed shared library */ +#define ELIBBAD 80 /* Accessing a corrupted shared library */ +#define ELIBSCN 81 /* .lib section in a.out corrupted */ +#define ELIBMAX 82 /* Attempting to link in too many shared libraries */ +#define ELIBEXEC 83 /* Cannot exec a shared library directly */ +#define EILSEQ 84 /* Illegal byte sequence */ +#define ERESTART 85 /* Interrupted system call should be restarted */ +#define ESTRPIPE 86 /* Streams pipe error */ +#define EUSERS 87 /* Too many users */ +#define ENOTSOCK 88 /* Socket operation on non-socket */ +#define EDESTADDRREQ 89 /* Destination address required */ +#define EMSGSIZE 90 /* Message too long */ +#define EPROTOTYPE 91 /* Protocol wrong type for socket */ +#define ENOPROTOOPT 92 /* Protocol not available */ +#define EPROTONOSUPPORT 93 /* Protocol not supported */ +#define ESOCKTNOSUPPORT 94 /* Socket type not supported */ +#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */ +#define EPFNOSUPPORT 96 /* Protocol family not supported */ +#define EAFNOSUPPORT 97 /* Address family not supported by protocol */ +#define EADDRINUSE 98 /* Address already in use */ +#define EADDRNOTAVAIL 99 /* Cannot assign requested address */ +#define ENETDOWN 100 /* Network is down */ +#define ENETUNREACH 101 /* Network is unreachable */ +#define ENETRESET 102 /* Network dropped connection because of reset */ +#define ECONNABORTED 103 /* Software caused connection abort */ +#define ECONNRESET 104 /* Connection reset by peer */ +#define ENOBUFS 105 /* No buffer space available */ +#define EISCONN 106 /* Transport endpoint is already connected */ +#define ENOTCONN 107 /* Transport endpoint is not connected */ +#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */ +#define ETOOMANYREFS 109 /* Too many references: cannot splice */ +#define ETIMEDOUT 110 /* Connection timed out */ +#define ECONNREFUSED 111 /* Connection refused */ +#define EHOSTDOWN 112 /* Host is down */ +#define EHOSTUNREACH 113 /* No route to host */ +#define EALREADY 114 /* Operation already in progress */ +#define EINPROGRESS 115 /* Operation now in progress */ +#define ESTALE 116 /* Stale NFS file handle */ +#define EUCLEAN 117 /* Structure needs cleaning */ +#define ENOTNAM 118 /* Not a XENIX named type file */ +#define ENAVAIL 119 /* No XENIX semaphores available */ +#define EISNAM 120 /* Is a named type file */ +#define EREMOTEIO 121 /* Remote I/O error */ +#define EDQUOT 122 /* Quota exceeded */ + +#define ENOMEDIUM 123 /* No medium found */ +#define EMEDIUMTYPE 124 /* Wrong medium type */ +#define ECANCELED 125 /* Operation Canceled */ +#define ENOKEY 126 /* Required key not available */ +#define EKEYEXPIRED 127 /* Key has expired */ +#define EKEYREVOKED 128 /* Key has been revoked */ +#define EKEYREJECTED 129 /* Key was rejected by service */ + +/* for robust mutexes */ +#define EOWNERDEAD 130 /* Owner died */ +#define ENOTRECOVERABLE 131 /* State not recoverable */ + +#endif diff --git a/l4/pkg/uclibc/lib/uclibc/ARCH-sparc/include/asm/ioctls.h b/l4/pkg/uclibc/lib/uclibc/ARCH-sparc/include/asm/ioctls.h new file mode 100644 index 00000000..ab8b844a --- /dev/null +++ b/l4/pkg/uclibc/lib/uclibc/ARCH-sparc/include/asm/ioctls.h @@ -0,0 +1,149 @@ + +/* ioctl command encoding: 32 bits total, command in lower 16 bits, + * size of the parameter structure in the lower 14 bits of the + * upper 16 bits. + * Encoding the size of the parameter structure in the ioctl request + * is useful for catching programs compiled with old versions + * and to avoid overwriting user space outside the user buffer area. + * The highest 2 bits are reserved for indicating the ``access mode''. + * NOTE: This limits the max parameter size to 16kB -1 ! + */ + +/* + * The following is for compatibility across the various Linux + * platforms. The i386 ioctl numbering scheme doesn't really enforce + * a type field. De facto, however, the top 8 bits of the lower 16 + * bits are indeed used as a type field, so we might just as well make + * this explicit here. Please be sure to use the decoding macros + * below from now on. + */ +#define _IOC_NRBITS 8 +#define _IOC_TYPEBITS 8 +#define _IOC_SIZEBITS 14 +#define _IOC_DIRBITS 2 + +#define _IOC_NRMASK ((1 << _IOC_NRBITS)-1) +#define _IOC_TYPEMASK ((1 << _IOC_TYPEBITS)-1) +#define _IOC_SIZEMASK ((1 << _IOC_SIZEBITS)-1) +#define _IOC_DIRMASK ((1 << _IOC_DIRBITS)-1) + +#define _IOC_NRSHIFT 0 +#define _IOC_TYPESHIFT (_IOC_NRSHIFT+_IOC_NRBITS) +#define _IOC_SIZESHIFT (_IOC_TYPESHIFT+_IOC_TYPEBITS) +#define _IOC_DIRSHIFT (_IOC_SIZESHIFT+_IOC_SIZEBITS) + +/* + * Direction bits. + */ +#define _IOC_NONE 0U +#define _IOC_WRITE 1U +#define _IOC_READ 2U + +#define _IOC(dir,type,nr,size) \ + (((dir) << _IOC_DIRSHIFT) | \ + ((type) << _IOC_TYPESHIFT) | \ + ((nr) << _IOC_NRSHIFT) | \ + ((size) << _IOC_SIZESHIFT)) + +/* used to create numbers */ +#define _IO(type,nr) _IOC(_IOC_NONE,(type),(nr),0) +#define _IOR(type,nr,size) _IOC(_IOC_READ,(type),(nr),sizeof(size)) +#define _IOW(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),sizeof(size)) +#define _IOWR(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size)) + +/* used to decode ioctl numbers.. */ +#define _IOC_DIR(nr) (((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK) +#define _IOC_TYPE(nr) (((nr) >> _IOC_TYPESHIFT) & _IOC_TYPEMASK) +#define _IOC_NR(nr) (((nr) >> _IOC_NRSHIFT) & _IOC_NRMASK) +#define _IOC_SIZE(nr) (((nr) >> _IOC_SIZESHIFT) & _IOC_SIZEMASK) + +/* ...and for the drivers/sound files... */ + +#define IOC_IN (_IOC_WRITE << _IOC_DIRSHIFT) +#define IOC_OUT (_IOC_READ << _IOC_DIRSHIFT) +#define IOC_INOUT ((_IOC_WRITE|_IOC_READ) << _IOC_DIRSHIFT) +#define IOCSIZE_MASK (_IOC_SIZEMASK << _IOC_SIZESHIFT) +#define IOCSIZE_SHIFT (_IOC_SIZESHIFT) + +/* 0x54 is just a magic number to make these relatively unique ('T') */ + +#define TCGETS 0x5401 +#define TCSETS 0x5402 +#define TCSETSW 0x5403 +#define TCSETSF 0x5404 +#define TCGETA 0x5405 +#define TCSETA 0x5406 +#define TCSETAW 0x5407 +#define TCSETAF 0x5408 +#define TCSBRK 0x5409 +#define TCXONC 0x540A +#define TCFLSH 0x540B +#define TIOCEXCL 0x540C +#define TIOCNXCL 0x540D +#define TIOCSCTTY 0x540E +#define TIOCGPGRP 0x540F +#define TIOCSPGRP 0x5410 +#define TIOCOUTQ 0x5411 +#define TIOCSTI 0x5412 +#define TIOCGWINSZ 0x5413 +#define TIOCSWINSZ 0x5414 +#define TIOCMGET 0x5415 +#define TIOCMBIS 0x5416 +#define TIOCMBIC 0x5417 +#define TIOCMSET 0x5418 +#define TIOCGSOFTCAR 0x5419 +#define TIOCSSOFTCAR 0x541A +#define FIONREAD 0x541B +#define TIOCINQ FIONREAD +#define TIOCLINUX 0x541C +#define TIOCCONS 0x541D +#define TIOCGSERIAL 0x541E +#define TIOCSSERIAL 0x541F +#define TIOCPKT 0x5420 +#define FIONBIO 0x5421 +#define TIOCNOTTY 0x5422 +#define TIOCSETD 0x5423 +#define TIOCGETD 0x5424 +#define TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */ +#define TIOCTTYGSTRUCT 0x5426 /* For debugging only */ +#define TIOCSBRK 0x5427 /* BSD compatibility */ +#define TIOCCBRK 0x5428 /* BSD compatibility */ +#define TIOCGSID 0x5429 /* Return the session ID of FD */ +#define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */ +#define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */ + +#define FIONCLEX 0x5450 /* these numbers need to be adjusted. */ +#define FIOCLEX 0x5451 +#define FIOASYNC 0x5452 +#define TIOCSERCONFIG 0x5453 +#define TIOCSERGWILD 0x5454 +#define TIOCSERSWILD 0x5455 +#define TIOCGLCKTRMIOS 0x5456 +#define TIOCSLCKTRMIOS 0x5457 +#define TIOCSERGSTRUCT 0x5458 /* For debugging only */ +#define TIOCSERGETLSR 0x5459 /* Get line status register */ +#define TIOCSERGETMULTI 0x545A /* Get multiport config */ +#define TIOCSERSETMULTI 0x545B /* Set multiport config */ + +#define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */ +#define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */ +#define FIOQSIZE 0x545E + +/* Used for packet mode */ +#define TIOCPKT_DATA 0 +#define TIOCPKT_FLUSHREAD 1 +#define TIOCPKT_FLUSHWRITE 2 +#define TIOCPKT_STOP 4 +#define TIOCPKT_START 8 +#define TIOCPKT_NOSTOP 16 +#define TIOCPKT_DOSTOP 32 + +#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */ + +/* Socket-level I/O control calls. */ +#define FIOSETOWN 0x8901 +#define SIOCSPGRP 0x8902 +#define FIOGETOWN 0x8903 +#define SIOCGPGRP 0x8904 +#define SIOCATMARK 0x8905 +#define SIOCGSTAMP 0x8906 /* Get stamp */ diff --git a/l4/pkg/uclibc/lib/uclibc/ARCH-sparc/include/asm/sigcontext.h b/l4/pkg/uclibc/lib/uclibc/ARCH-sparc/include/asm/sigcontext.h new file mode 100644 index 00000000..42eca544 --- /dev/null +++ b/l4/pkg/uclibc/lib/uclibc/ARCH-sparc/include/asm/sigcontext.h @@ -0,0 +1,78 @@ +/* Copyright (C) 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#if !defined _SIGNAL_H && !defined _SYS_UCONTEXT_H +# error "Never use directly; include instead." +#endif + +#include + +#if __WORDSIZE == 32 + +/* It is quite hard to choose what to put here, because + Linux/sparc32 had at least 3 totally incompatible + signal stack layouts. + This one is for the "new" style signals, which are + now delivered unless SA_SIGINFO is requested. */ + +struct sigcontext + { + struct + { + unsigned int psr; + unsigned int pc; + unsigned int npc; + unsigned int y; + unsigned int u_regs[16]; /* globals and ins */ + } si_regs; + int si_mask; + }; + +#else /* sparc64 */ + +typedef struct + { + unsigned int si_float_regs [64]; + unsigned long si_fsr; + unsigned long si_gsr; + unsigned long si_fprs; + } __siginfo_fpu_t; + +struct sigcontext + { + char sigc_info[128]; + struct + { + unsigned long u_regs[16]; /* globals and ins */ + unsigned long tstate; + unsigned long tpc; + unsigned long tnpc; + unsigned int y; + unsigned int fprs; + } sigc_regs; + __siginfo_fpu_t * sigc_fpu_save; + struct + { + void * ss_sp; + int ss_flags; + unsigned long ss_size; + } sigc_stack; + unsigned long sigc_mask; +}; + +#endif /* sparc64 */ diff --git a/l4/pkg/uclibc/lib/uclibc/ARCH-sparc/include/asm/socket.h b/l4/pkg/uclibc/lib/uclibc/ARCH-sparc/include/asm/socket.h new file mode 100644 index 00000000..aea42a92 --- /dev/null +++ b/l4/pkg/uclibc/lib/uclibc/ARCH-sparc/include/asm/socket.h @@ -0,0 +1,4 @@ +#ifndef __ASM_SPARC_SOCKET_H +#define __ASM_SPARC_SOCKET_H + +#endif /* __ASM_SPARC_SOCKET_H */ diff --git a/l4/pkg/uclibc/lib/uclibc/ARCH-sparc/include/bits/uClibc_config.h b/l4/pkg/uclibc/lib/uclibc/ARCH-sparc/include/bits/uClibc_config.h new file mode 100644 index 00000000..d397bc8c --- /dev/null +++ b/l4/pkg/uclibc/lib/uclibc/ARCH-sparc/include/bits/uClibc_config.h @@ -0,0 +1,290 @@ +#if !defined __FEATURES_H && !defined __need_uClibc_config_h +# error Never include directly; use instead +#endif + +#ifndef libc_hidden_proto +#define libc_hidden_proto(x) +#endif +#ifndef libm_hidden_proto +#define libm_hidden_proto(x) +#endif +#ifndef librt_hidden_proto +#define librt_hidden_proto(x) +#endif + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE 1 +#endif + +#define __UCLIBC_MAJOR__ 0 +#define __UCLIBC_MINOR__ 9 +#define __UCLIBC_SUBLEVEL__ 29 +/* Automatically generated make config: don't edit */ +/* Sun Feb 10 18:15:17 2008 */ +#undef __TARGET_alpha__ +#undef __TARGET_arm__ +#undef __TARGET_avr32__ +#undef __TARGET_bfin__ +#undef __TARGET_cris__ +#undef __TARGET_e1__ +#undef __TARGET_frv__ +#undef __TARGET_h8300__ +#undef __TARGET_hppa__ +#undef __TARGET_i386__ +#undef __TARGET_i960__ +#undef __TARGET_ia64__ +#undef __TARGET_m68k__ +#undef __TARGET_microblaze__ +#undef __TARGET_mips__ +#undef __TARGET_nios__ +#undef __TARGET_nios2__ +#undef __TARGET_powerpc__ +#undef __TARGET_sh__ +#undef __TARGET_sh64__ +#define __TARGET_sparc__ 1 +#undef __TARGET_v850__ +#undef __TARGET_vax__ +#undef __TARGET_x86_64__ +#undef __TARGET_xtensa__ + +/* Target Architecture Features and Options */ +#define __TARGET_ARCH__ "sparc" +#define __FORCE_OPTIONS_FOR_ARCH__ 1 +#undef __CONFIG_GENERIC_386__ +#undef __CONFIG_386__ +#undef __CONFIG_486__ +#undef __CONFIG_586__ +#undef __CONFIG_586MMX__ +#undef __CONFIG_686__ +#undef __CONFIG_PENTIUMII__ +#undef __CONFIG_PENTIUMIII__ +#undef __CONFIG_PENTIUM4__ +#undef __CONFIG_K6__ +#undef __CONFIG_K7__ +#undef __CONFIG_ELAN__ +#undef __CONFIG_CRUSOE__ +#undef __CONFIG_WINCHIPC6__ +#undef __CONFIG_WINCHIP2__ +#undef __CONFIG_CYRIXIII__ +#undef __CONFIG_NEHEMIAH__ +#define __TARGET_SUBARCH__ "" + +/* Using ELF file format */ +#define __ARCH_LITTLE_ENDIAN__ 1 + +/* Using Little Endian */ +#define __ARCH_HAS_MMU__ 1 +#define __ARCH_USE_MMU__ 1 +#define __UCLIBC_HAS_FLOATS__ 1 +#define __UCLIBC_HAS_SOFT_FLOAT__ 1 +#define __HAS_FPU__ 1 +#define __DO_C99_MATH__ 1 +#define __UCLIBC_HAS_LONG_DOUBLE_MATH__ 1 +#define __KERNEL_SOURCE__ "/home/linux" +#define __C_SYMBOL_PREFIX__ "" +#define __HAVE_DOT_CONFIG__ 1 + +/* + * General Library Settings + */ +#undef __HAVE_NO_PIC__ +#define __DOPIC__ 1 +#undef __HAVE_NO_SHARED__ +#define __HAVE_SHARED__ +#undef __ARCH_HAS_NO_LDSO__ +#undef __BUILD_UCLIBC_LDSO__ +#undef __DL_FINI_CRT_COMPAT__ +#define __UCLIBC_CTOR_DTOR__ 1 +#undef __HAS_NO_THREADS__ +#ifndef L4_MINIMAL_LIBC +#define __UCLIBC_HAS_THREADS__ 1 +#define __LINUXTHREADS_OLD__ 1 +#define __UCLIBC_HAS_TLS__ 1 +#define __UCLIBC_HAS_THREADS_NATIVE__ 1 + +#define __UCLIBC_HAS_LFS__ 1 +#define __UCLIBC_STATIC_LDCONFIG__ 1 + +/* + * Networking Support + */ +#define __UCLIBC_HAS_COMPAT_RES_STATE__ 1 +#define __UCLIBC_HAS_IPV4__ 1 + +/* + * String and Stdio Support + */ +#define __UCLIBC_HAS_STRING_GENERIC_OPT__ 1 +#define __UCLIBC_HAS_STRING_ARCH_OPT__ 1 +#define __UCLIBC_HAS_CTYPE_TABLES__ 1 +#define __UCLIBC_HAS_CTYPE_SIGNED__ 1 +#define __UCLIBC_HAS_CTYPE_UNSAFE__ 1 +#undef __UCLIBC_HAS_CTYPE_CHECKED__ +#undef __UCLIBC_HAS_CTYPE_ENFORCED__ +#define __UCLIBC_HAS_WCHAR__ 1 +#undef __UCLIBC_HAS_LOCALE__ +#undef __UCLIBC_HAS_HEXADECIMAL_FLOATS__ +#undef __UCLIBC_HAS_GLIBC_CUSTOM_PRINTF__ +#undef __USE_OLD_VFPRINTF__ +#define __UCLIBC_PRINTF_SCANF_POSITIONAL_ARGS__ 9 +#undef __UCLIBC_HAS_SCANF_GLIBC_A_FLAG__ +#undef __UCLIBC_HAS_STDIO_BUFSIZ_NONE__ +#define __UCLIBC_HAS_STDIO_BUFSIZ_256__ 1 +#undef __UCLIBC_HAS_STDIO_BUFSIZ_512__ +#undef __UCLIBC_HAS_STDIO_BUFSIZ_1024__ +#undef __UCLIBC_HAS_STDIO_BUFSIZ_2048__ +#undef __UCLIBC_HAS_STDIO_BUFSIZ_4096__ +#undef __UCLIBC_HAS_STDIO_BUFSIZ_8192__ +#define __UCLIBC_HAS_STDIO_BUILTIN_BUFFER_NONE__ 1 +#undef __UCLIBC_HAS_STDIO_BUILTIN_BUFFER_4__ +#undef __UCLIBC_HAS_STDIO_BUILTIN_BUFFER_8__ +#undef __UCLIBC_HAS_STDIO_SHUTDOWN_ON_ABORT__ +#define __UCLIBC_HAS_STDIO_GETC_MACRO__ 1 +#define __UCLIBC_HAS_STDIO_PUTC_MACRO__ 1 +#define __UCLIBC_HAS_STDIO_AUTO_RW_TRANSITION__ 1 +#undef __UCLIBC_HAS_FOPEN_LARGEFILE_MODE__ +#undef __UCLIBC_HAS_FOPEN_EXCLUSIVE_MODE__ +#undef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ +#undef __UCLIBC_HAS_PRINTF_M_SPEC__ +#define __UCLIBC_HAS_ERRNO_MESSAGES__ 1 +#undef __UCLIBC_HAS_SYS_ERRLIST__ +#define __UCLIBC_HAS_SIGNUM_MESSAGES__ 1 +#undef __UCLIBC_HAS_SYS_SIGLIST__ +#define __UCLIBC_HAS_GNU_GETOPT__ 1 +#define __UCLIBC_HAS_GNU_GETSUBOPT__ 1 + +/* Big and Tall */ +#define __UCLIBC_HAS_REGEX__ 1 +#define __UCLIBC_HAS_REGEX_OLD__ 1 +#define __UCLIBC_HAS_FNMATCH__ 1 +#define __UCLIBC_HAS_FNMATCH_OLD__ 1 +#undef __UCLIBC_HAS_WORDEXP__ +#undef __UCLIBC_HAS_FTW__ +#define __UCLIBC_HAS_GLOB__ 1 +#define __UCLIBC_HAS_GNU_GLOB__ 1 + +#else /* The minimal version, w/o threads etc. */ + +#define __HAS_NO_THREADS__ 1 +#undef __UCLIBC_HAS_LFS__ +#undef __UCLIBC_STATIC_LDCONFIG__ + +/* + * Networking Support + */ +#undef __UCLIBC_HAS_COMPAT_RES_STATE__ +#undef __UCLIBC_HAS_IPV4__ + +/* + * String and Stdio Support + */ +#define __UCLIBC_HAS_STRING_GENERIC_OPT__ 1 +#define __UCLIBC_HAS_STRING_ARCH_OPT__ 1 +#define __UCLIBC_HAS_CTYPE_TABLES__ 1 +#define __UCLIBC_HAS_CTYPE_SIGNED__ 1 +#define __UCLIBC_HAS_CTYPE_UNSAFE__ 1 +#undef __UCLIBC_HAS_CTYPE_CHECKED__ +#undef __UCLIBC_HAS_CTYPE_ENFORCED__ +#undef __UCLIBC_HAS_WCHAR__ +#undef __UCLIBC_HAS_LOCALE__ +#undef __UCLIBC_HAS_HEXADECIMAL_FLOATS__ +#undef __UCLIBC_HAS_GLIBC_CUSTOM_PRINTF__ +#undef __USE_OLD_VFPRINTF__ +#define __UCLIBC_PRINTF_SCANF_POSITIONAL_ARGS__ 9 +#undef __UCLIBC_HAS_SCANF_GLIBC_A_FLAG__ +#undef __UCLIBC_HAS_STDIO_BUFSIZ_NONE__ +#define __UCLIBC_HAS_STDIO_BUFSIZ_256__ 1 +#undef __UCLIBC_HAS_STDIO_BUFSIZ_512__ +#undef __UCLIBC_HAS_STDIO_BUFSIZ_1024__ +#undef __UCLIBC_HAS_STDIO_BUFSIZ_2048__ +#undef __UCLIBC_HAS_STDIO_BUFSIZ_4096__ +#undef __UCLIBC_HAS_STDIO_BUFSIZ_8192__ +#define __UCLIBC_HAS_STDIO_BUILTIN_BUFFER_NONE__ 1 +#undef __UCLIBC_HAS_STDIO_BUILTIN_BUFFER_4__ +#undef __UCLIBC_HAS_STDIO_BUILTIN_BUFFER_8__ +#undef __UCLIBC_HAS_STDIO_SHUTDOWN_ON_ABORT__ +#define __UCLIBC_HAS_STDIO_GETC_MACRO__ 1 +#define __UCLIBC_HAS_STDIO_PUTC_MACRO__ 1 +#define __UCLIBC_HAS_STDIO_AUTO_RW_TRANSITION__ 1 +#undef __UCLIBC_HAS_FOPEN_LARGEFILE_MODE__ +#undef __UCLIBC_HAS_FOPEN_EXCLUSIVE_MODE__ +#undef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ +#undef __UCLIBC_HAS_PRINTF_M_SPEC__ +#undef __UCLIBC_HAS_ERRNO_MESSAGES__ +#undef __UCLIBC_HAS_SYS_ERRLIST__ +#define __UCLIBC_HAS_SIGNUM_MESSAGES__ 1 +#undef __UCLIBC_HAS_SYS_SIGLIST__ +#define __UCLIBC_HAS_GNU_GETOPT__ 1 +#define __UCLIBC_HAS_GNU_GETSUBOPT__ 1 + +/* Big and Tall */ +#undef __UCLIBC_HAS_REGEX__ +#undef __UCLIBC_HAS_REGEX_OLD__ +#undef __UCLIBC_HAS_FNMATCH__ +#undef __UCLIBC_HAS_FNMATCH_OLD__ +#undef __UCLIBC_HAS_WORDEXP__ +#undef __UCLIBC_HAS_FTW__ +#define __UCLIBC_HAS_GLOB__ 1 +#define __UCLIBC_HAS_GNU_GLOB__ 1 + +#endif + +#undef __MALLOC__ +#undef __MALLOC_SIMPLE__ +#define __MALLOC_STANDARD__ 1 +#undef __MALLOC_GLIBC_COMPAT__ +#undef __UCLIBC_DYNAMIC_ATEXIT__ +#define __UCLIBC_SUSV3_LEGACY__ +#define __UCLIBC_SUSV3_LEGACY_MACROS__ +#define __UCLIBC_SUSV4_LEGACY__ 1 +#undef __HAS_SHADOW__ +#define __UNIX98PTY_ONLY__ 1 +#define __ASSUME_DEVPTS__ 1 +#define __UCLIBC_HAS_TM_EXTENSIONS__ 1 +#define __UCLIBC_HAS_TZ_CACHING__ 1 +#undef __UCLIBC_HAS_TZ_FILE__ +#undef __UCLIBC_HAS_TZ_FILE_READ_MANY__ +#undef __UCLIBC_TZ_FILE_PATH__ + +/* Advanced Library Settings */ +#define __UCLIBC_PWD_BUFFER_SIZE__ 256 +#define __UCLIBC_GRP_BUFFER_SIZE__ 256 + +#define __UCLIBC_HAS_REALTIME__ +#define __UCLIBC_HAS_ADVANCED_REALTIME__ + +/* + * Networking Support + */ +#define __UCLIBC_HAS_IPV6__ 1 +#undef __UCLIBC_HAS_RPC__ +#undef __UCLIBC_USE_NETLINK__ + + +/* Library Installation Options */ +#define __SYSTEM_LDSO__ "/lib/ld-linux.so.2" +#define __RUNTIME_PREFIX__ "/usr/$(TARGET_ARCH)-linux-uclibc/" +#define __DEVEL_PREFIX__ "/usr/$(TARGET_ARCH)-linux-uclibc/usr/" + +/* + * uClibc security related options + */ +#undef __UCLIBC_SECURITY__ + + +/* uClibc development/debugging options */ +#define __CROSS_COMPILER_PREFIX__ "" +#define __UCLIBC_EXTRA_CFLAGS__ "" +#undef __DODEBUG__ +#undef __DODEBUG_PT__ +#define __DOSTRIP__ 1 +#undef __DOASSERTS__ +#define __SUPPORT_LD_DEBUG__ 1 +#undef __SUPPORT_LD_DEBUG_EARLY__ +//#define __SUPPORT_LD_DEBUG_EARLY__ 1 +#define __LDSO_GNU_HASH_SUPPORT__ 1 +#define __UCLIBC_MALLOC_DEBUGGING__ 1 +#define __WARNINGS__ "-Wall" +#undef __EXTRA_WARNINGS__ +#undef __DOMULTI__ +#undef __UCLIBC_MJN3_ONLY__ diff --git a/l4/pkg/uclibc/lib/uclibc/ARCH-sparc/include/linux/bits/ioctls.h b/l4/pkg/uclibc/lib/uclibc/ARCH-sparc/include/linux/bits/ioctls.h new file mode 100644 index 00000000..92bf0a24 --- /dev/null +++ b/l4/pkg/uclibc/lib/uclibc/ARCH-sparc/include/linux/bits/ioctls.h @@ -0,0 +1,35 @@ +/* Copyright (C) 1996, 1997 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _SYS_IOCTL_H +# error "Never use directly; include instead." +#endif + +/* Use the definitions from the kernel header files. */ +#include + +/* Oh well, this is necessary since the kernel data structure is + different from the user-level version. */ +#undef TCGETS +#undef TCSETS +#undef TCSETSW +#undef TCSETSF +#define TCGETS _IOR ('T', 8, char[36]) +#define TCSETS _IOW ('T', 9, char[36]) +#define TCSETSW _IOW ('T', 10, char[36]) +#define TCSETSF _IOW ('T', 11, char[36]) diff --git a/l4/pkg/uclibc/lib/uclibc/ARCH-sparc/include/linux/bits/socket.h b/l4/pkg/uclibc/lib/uclibc/ARCH-sparc/include/linux/bits/socket.h new file mode 100644 index 00000000..e41527fd --- /dev/null +++ b/l4/pkg/uclibc/lib/uclibc/ARCH-sparc/include/linux/bits/socket.h @@ -0,0 +1,356 @@ +/* System-specific socket constants and types. Linux version. + Copyright (C) 1991,1992,1994-2001,2004,2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef __BITS_SOCKET_H +#define __BITS_SOCKET_H + +#if !defined _SYS_SOCKET_H && !defined _NETINET_IN_H +# error "Never include directly; use instead." +#endif + +#define __need_size_t +#define __need_NULL +#include + +#include +#include + +/* Type for length arguments in socket calls. */ +#ifndef __socklen_t_defined +typedef __socklen_t socklen_t; +# define __socklen_t_defined +#endif + +/* Types of sockets. */ +enum __socket_type +{ + SOCK_STREAM = 1, /* Sequenced, reliable, connection-based + byte streams. */ +#define SOCK_STREAM SOCK_STREAM + SOCK_DGRAM = 2, /* Connectionless, unreliable datagrams + of fixed maximum length. */ +#define SOCK_DGRAM SOCK_DGRAM + SOCK_RAW = 3, /* Raw protocol interface. */ +#define SOCK_RAW SOCK_RAW + SOCK_RDM = 4, /* Reliably-delivered messages. */ +#define SOCK_RDM SOCK_RDM + SOCK_SEQPACKET = 5, /* Sequenced, reliable, connection-based, + datagrams of fixed maximum length. */ +#define SOCK_SEQPACKET SOCK_SEQPACKET + SOCK_PACKET = 10 /* Linux specific way of getting packets + at the dev level. For writing rarp and + other similar things on the user level. */ +#define SOCK_PACKET SOCK_PACKET +}; + +/* Protocol families. */ +#define PF_UNSPEC 0 /* Unspecified. */ +#define PF_LOCAL 1 /* Local to host (pipes and file-domain). */ +#define PF_UNIX PF_LOCAL /* Old BSD name for PF_LOCAL. */ +#define PF_FILE PF_LOCAL /* Another non-standard name for PF_LOCAL. */ +#define PF_INET 2 /* IP protocol family. */ +#define PF_AX25 3 /* Amateur Radio AX.25. */ +#define PF_IPX 4 /* Novell Internet Protocol. */ +#define PF_APPLETALK 5 /* Appletalk DDP. */ +#define PF_NETROM 6 /* Amateur radio NetROM. */ +#define PF_BRIDGE 7 /* Multiprotocol bridge. */ +#define PF_ATMPVC 8 /* ATM PVCs. */ +#define PF_X25 9 /* Reserved for X.25 project. */ +#define PF_INET6 10 /* IP version 6. */ +#define PF_ROSE 11 /* Amateur Radio X.25 PLP. */ +#define PF_DECnet 12 /* Reserved for DECnet project. */ +#define PF_NETBEUI 13 /* Reserved for 802.2LLC project. */ +#define PF_SECURITY 14 /* Security callback pseudo AF. */ +#define PF_KEY 15 /* PF_KEY key management API. */ +#define PF_NETLINK 16 +#define PF_ROUTE PF_NETLINK /* Alias to emulate 4.4BSD. */ +#define PF_PACKET 17 /* Packet family. */ +#define PF_ASH 18 /* Ash. */ +#define PF_ECONET 19 /* Acorn Econet. */ +#define PF_ATMSVC 20 /* ATM SVCs. */ +#define PF_SNA 22 /* Linux SNA Project */ +#define PF_IRDA 23 /* IRDA sockets. */ +#define PF_PPPOX 24 /* PPPoX sockets. */ +#define PF_WANPIPE 25 /* Wanpipe API sockets. */ +#define PF_BLUETOOTH 31 /* Bluetooth sockets. */ +#define PF_MAX 32 /* For now.. */ + +/* Address families. */ +#define AF_UNSPEC PF_UNSPEC +#define AF_LOCAL PF_LOCAL +#define AF_UNIX PF_UNIX +#define AF_FILE PF_FILE +#define AF_INET PF_INET +#define AF_AX25 PF_AX25 +#define AF_IPX PF_IPX +#define AF_APPLETALK PF_APPLETALK +#define AF_NETROM PF_NETROM +#define AF_BRIDGE PF_BRIDGE +#define AF_ATMPVC PF_ATMPVC +#define AF_X25 PF_X25 +#define AF_INET6 PF_INET6 +#define AF_ROSE PF_ROSE +#define AF_DECnet PF_DECnet +#define AF_NETBEUI PF_NETBEUI +#define AF_SECURITY PF_SECURITY +#define AF_KEY PF_KEY +#define AF_NETLINK PF_NETLINK +#define AF_ROUTE PF_ROUTE +#define AF_PACKET PF_PACKET +#define AF_ASH PF_ASH +#define AF_ECONET PF_ECONET +#define AF_ATMSVC PF_ATMSVC +#define AF_SNA PF_SNA +#define AF_IRDA PF_IRDA +#define AF_PPPOX PF_PPPOX +#define AF_WANPIPE PF_WANPIPE +#define AF_BLUETOOTH PF_BLUETOOTH +#define AF_MAX PF_MAX + +/* Socket level values. Others are defined in the appropriate headers. + + XXX These definitions also should go into the appropriate headers as + far as they are available. */ +#define SOL_RAW 255 +#define SOL_DECNET 261 +#define SOL_X25 262 +#define SOL_PACKET 263 +#define SOL_ATM 264 /* ATM layer (cell level). */ +#define SOL_AAL 265 /* ATM Adaption Layer (packet level). */ +#define SOL_IRDA 266 + +/* Maximum queue length specifiable by listen. */ +#define SOMAXCONN 128 + +/* Get the definition of the macro to define the common sockaddr members. */ +#include + +/* Structure describing a generic socket address. */ +struct sockaddr + { + __SOCKADDR_COMMON (sa_); /* Common data: address family and length. */ + char sa_data[14]; /* Address data. */ + }; + + +/* Structure large enough to hold any socket address (with the historical + exception of AF_UNIX). We reserve 128 bytes. */ +#if ULONG_MAX > 0xffffffff +# define __ss_aligntype __uint64_t +#else +# define __ss_aligntype __uint32_t +#endif +#define _SS_SIZE 128 +#define _SS_PADSIZE (_SS_SIZE - (2 * sizeof (__ss_aligntype))) + +struct sockaddr_storage + { + __SOCKADDR_COMMON (ss_); /* Address family, etc. */ + __ss_aligntype __ss_align; /* Force desired alignment. */ + char __ss_padding[_SS_PADSIZE]; + }; + + +/* Bits in the FLAGS argument to `send', `recv', et al. */ +enum + { + MSG_OOB = 0x01, /* Process out-of-band data. */ +#define MSG_OOB MSG_OOB + MSG_PEEK = 0x02, /* Peek at incoming messages. */ +#define MSG_PEEK MSG_PEEK + MSG_DONTROUTE = 0x04, /* Don't use local routing. */ +#define MSG_DONTROUTE MSG_DONTROUTE +#ifdef __USE_GNU + /* DECnet uses a different name. */ + MSG_TRYHARD = MSG_DONTROUTE, +# define MSG_TRYHARD MSG_DONTROUTE +#endif + MSG_CTRUNC = 0x08, /* Control data lost before delivery. */ +#define MSG_CTRUNC MSG_CTRUNC + MSG_PROXY = 0x10, /* Supply or ask second address. */ +#define MSG_PROXY MSG_PROXY + MSG_TRUNC = 0x20, +#define MSG_TRUNC MSG_TRUNC + MSG_DONTWAIT = 0x40, /* Nonblocking IO. */ +#define MSG_DONTWAIT MSG_DONTWAIT + MSG_EOR = 0x80, /* End of record. */ +#define MSG_EOR MSG_EOR + MSG_WAITALL = 0x100, /* Wait for a full request. */ +#define MSG_WAITALL MSG_WAITALL + MSG_FIN = 0x200, +#define MSG_FIN MSG_FIN + MSG_SYN = 0x400, +#define MSG_SYN MSG_SYN + MSG_CONFIRM = 0x800, /* Confirm path validity. */ +#define MSG_CONFIRM MSG_CONFIRM + MSG_RST = 0x1000, +#define MSG_RST MSG_RST + MSG_ERRQUEUE = 0x2000, /* Fetch message from error queue. */ +#define MSG_ERRQUEUE MSG_ERRQUEUE + MSG_NOSIGNAL = 0x4000, /* Do not generate SIGPIPE. */ +#define MSG_NOSIGNAL MSG_NOSIGNAL + MSG_MORE = 0x8000 /* Sender will send more. */ +#define MSG_MORE MSG_MORE + }; + + +/* Structure describing messages sent by + `sendmsg' and received by `recvmsg'. */ +/* Note: do not change these members to match glibc; these match the + SuSv3 spec already (e.g. msg_iovlen/msg_controllen). + http://www.opengroup.org/onlinepubs/009695399/basedefs/sys/socket.h.html */ +/* Note: linux kernel uses __kernel_size_t (which is 8bytes on 64bit + platforms, and 4bytes on 32bit platforms) for msg_iovlen/msg_controllen */ +struct msghdr + { + void *msg_name; /* Address to send to/receive from. */ + socklen_t msg_namelen; /* Length of address data. */ + + struct iovec *msg_iov; /* Vector of data to send/receive into. */ +#if __WORDSIZE == 32 + int msg_iovlen; /* Number of elements in the vector. */ +#else + size_t msg_iovlen; /* Number of elements in the vector. */ +#endif + + void *msg_control; /* Ancillary data (eg BSD filedesc passing). */ +#if __WORDSIZE == 32 + socklen_t msg_controllen; /* Ancillary data buffer length. */ +#else + size_t msg_controllen; /* Ancillary data buffer length. */ +#endif + + int msg_flags; /* Flags on received message. */ + }; + +/* Structure used for storage of ancillary data object information. */ +struct cmsghdr + { + size_t cmsg_len; /* Length of data in cmsg_data plus length + of cmsghdr structure. */ + int cmsg_level; /* Originating protocol. */ + int cmsg_type; /* Protocol specific type. */ +#if (!defined __STRICT_ANSI__ && __GNUC__ >= 2) || __STDC_VERSION__ >= 199901L + __extension__ unsigned char __cmsg_data __flexarr; /* Ancillary data. */ +#endif + }; + +/* Ancillary data object manipulation macros. */ +#if (!defined __STRICT_ANSI__ && __GNUC__ >= 2) || __STDC_VERSION__ >= 199901L +# define CMSG_DATA(cmsg) ((cmsg)->__cmsg_data) +#else +# define CMSG_DATA(cmsg) ((unsigned char *) ((struct cmsghdr *) (cmsg) + 1)) +#endif +#define CMSG_NXTHDR(mhdr, cmsg) __cmsg_nxthdr (mhdr, cmsg) +#define CMSG_FIRSTHDR(mhdr) \ + ((size_t) (mhdr)->msg_controllen >= sizeof (struct cmsghdr) \ + ? (struct cmsghdr *) (mhdr)->msg_control : (struct cmsghdr *) NULL) +#define CMSG_ALIGN(len) (((len) + sizeof (size_t) - 1) \ + & (size_t) ~(sizeof (size_t) - 1)) +#define CMSG_SPACE(len) (CMSG_ALIGN (len) \ + + CMSG_ALIGN (sizeof (struct cmsghdr))) +#define CMSG_LEN(len) (CMSG_ALIGN (sizeof (struct cmsghdr)) + (len)) + +extern struct cmsghdr *__cmsg_nxthdr (struct msghdr *__mhdr, + struct cmsghdr *__cmsg) __THROW; +libc_hidden_proto(__cmsg_nxthdr) +#ifdef __USE_EXTERN_INLINES +# ifndef _EXTERN_INLINE +# define _EXTERN_INLINE extern __inline +# endif +_EXTERN_INLINE struct cmsghdr * +__NTH (__cmsg_nxthdr (struct msghdr *__mhdr, struct cmsghdr *__cmsg)) +{ + if ((size_t) __cmsg->cmsg_len < sizeof (struct cmsghdr)) + /* The kernel header does this so there may be a reason. */ + return 0; + + __cmsg = (struct cmsghdr *) ((unsigned char *) __cmsg + + CMSG_ALIGN (__cmsg->cmsg_len)); + if ((unsigned char *) (__cmsg + 1) > ((unsigned char *) __mhdr->msg_control + + __mhdr->msg_controllen) + || ((unsigned char *) __cmsg + CMSG_ALIGN (__cmsg->cmsg_len) + > ((unsigned char *) __mhdr->msg_control + __mhdr->msg_controllen))) + /* No more entries. */ + return 0; + return __cmsg; +} +#endif /* Use `extern inline'. */ + +/* Socket level message types. This must match the definitions in + . */ +enum + { + SCM_RIGHTS = 0x01 /* Transfer file descriptors. */ +#define SCM_RIGHTS SCM_RIGHTS +#ifdef __USE_BSD + , SCM_CREDENTIALS = 0x02 /* Credentials passing. */ +# define SCM_CREDENTIALS SCM_CREDENTIALS +#endif + }; + +/* User visible structure for SCM_CREDENTIALS message */ + +struct ucred +{ + pid_t pid; /* PID of sending process. */ + uid_t uid; /* UID of sending process. */ + gid_t gid; /* GID of sending process. */ +}; + +/* Get socket manipulation related informations from kernel headers. */ +#ifndef __GLIBC__ +#define __GLIBC__ 2 +#include +#undef __GLIBC__ +#else +#include +#endif + + +/* Structure used to manipulate the SO_LINGER option. */ +struct linger + { + int l_onoff; /* Nonzero to linger on close. */ + int l_linger; /* Time to linger. */ + }; + +/* Prefer socketcall over all these for sparc32, + since it only has socketcall */ +#ifndef __arch64__ + #undef __NR_accept + #undef __NR_bind + #undef __NR_connect + #undef __NR_getpeername + #undef __NR_getsockname + #undef __NR_getsockopt + #undef __NR_listen + #undef __NR_recv + #undef __NR_recvfrom + #undef __NR_recvmsg + #undef __NR_send + #undef __NR_sendmsg + #undef __NR_sendto + #undef __NR_setsockopt + #undef __NR_shutdown + #undef __NR_socket + #undef __NR_socketpair +#endif + +#endif /* bits/socket.h */ diff --git a/l4/pkg/uclibc/lib/uclibc/ARCH-sparc/include/linux/limits.h b/l4/pkg/uclibc/lib/uclibc/ARCH-sparc/include/linux/limits.h new file mode 100644 index 00000000..eaf2e099 --- /dev/null +++ b/l4/pkg/uclibc/lib/uclibc/ARCH-sparc/include/linux/limits.h @@ -0,0 +1,22 @@ +#ifndef _LINUX_LIMITS_H +#define _LINUX_LIMITS_H + +#define NR_OPEN 1024 + +#define NGROUPS_MAX 65536 /* supplemental group IDs are available */ +#define ARG_MAX 131072 /* # bytes of args + environ for exec() */ +#define CHILD_MAX 999 /* no limit :-) */ +#define OPEN_MAX 256 /* # open files a process may have */ +#define LINK_MAX 127 /* # links a file may have */ +#define MAX_CANON 255 /* size of the canonical input queue */ +#define MAX_INPUT 255 /* size of the type-ahead buffer */ +#define NAME_MAX 255 /* # chars in a file name */ +#define PATH_MAX 4096 /* # chars in a path name including nul */ +#define PIPE_BUF 4096 /* # bytes in atomic write to a pipe */ +#define XATTR_NAME_MAX 255 /* # chars in an extended attribute name */ +#define XATTR_SIZE_MAX 65536 /* size of an extended attribute value (64k) */ +#define XATTR_LIST_MAX 65536 /* size of extended attribute namelist (64k) */ + +#define RTSIG_MAX 32 + +#endif diff --git a/l4/pkg/uclibc/lib/uclibc/ARCH-sparc/include/linux/param.h b/l4/pkg/uclibc/lib/uclibc/ARCH-sparc/include/linux/param.h new file mode 100644 index 00000000..f696a198 --- /dev/null +++ b/l4/pkg/uclibc/lib/uclibc/ARCH-sparc/include/linux/param.h @@ -0,0 +1,22 @@ +#ifndef _ASM_SPARC_PARAM_H +#define _ASM_SPARC_PARAM_H + +#ifdef __KERNEL__ +#define HZ CONFIG_HZ /* internal kernel timer frequency */ +#define USER_HZ 100 /* for user interfaces in "ticks" */ +#define CLOCKS_PER_SEC (USER_HZ) /* frequency at which times() counts */ +#endif /* __KERNEL__ */ + +#ifndef HZ +#define HZ 100 +#endif + +#define EXEC_PAGESIZE 4096 + +#ifndef NOGROUP +#define NOGROUP (-1) +#endif + +#define MAXHOSTNAMELEN 64 /* max length of hostname */ + +#endif /* _ASM_SPARC_PARAM_H */ diff --git a/l4/pkg/uclibc/lib/uclibc/ARCH-sparc/include/linux/sockios.h b/l4/pkg/uclibc/lib/uclibc/ARCH-sparc/include/linux/sockios.h new file mode 100644 index 00000000..e69de29b diff --git a/l4/pkg/uclibc/lib/uclibc/ARCH-x86/include/asm/errno.h b/l4/pkg/uclibc/lib/uclibc/ARCH-x86/include/asm/errno.h new file mode 100644 index 00000000..7606c278 --- /dev/null +++ b/l4/pkg/uclibc/lib/uclibc/ARCH-x86/include/asm/errno.h @@ -0,0 +1,147 @@ +#ifndef _ASM_GENERIC_ERRNO_H +#define _ASM_GENERIC_ERRNO_H + + +#ifndef _ASM_GENERIC_ERRNO_BASE_H +#define _ASM_GENERIC_ERRNO_BASE_H + +#define EPERM 1 /* Operation not permitted */ +#define ENOENT 2 /* No such file or directory */ +#define ESRCH 3 /* No such process */ +#define EINTR 4 /* Interrupted system call */ +#define EIO 5 /* I/O error */ +#define ENXIO 6 /* No such device or address */ +#define E2BIG 7 /* Argument list too long */ +#define ENOEXEC 8 /* Exec format error */ +#define EBADF 9 /* Bad file number */ +#define ECHILD 10 /* No child processes */ +#define EAGAIN 11 /* Try again */ +#define ENOMEM 12 /* Out of memory */ +#define EACCES 13 /* Permission denied */ +#define EFAULT 14 /* Bad address */ +#define ENOTBLK 15 /* Block device required */ +#define EBUSY 16 /* Device or resource busy */ +#define EEXIST 17 /* File exists */ +#define EXDEV 18 /* Cross-device link */ +#define ENODEV 19 /* No such device */ +#define ENOTDIR 20 /* Not a directory */ +#define EISDIR 21 /* Is a directory */ +#define EINVAL 22 /* Invalid argument */ +#define ENFILE 23 /* File table overflow */ +#define EMFILE 24 /* Too many open files */ +#define ENOTTY 25 /* Not a typewriter */ +#define ETXTBSY 26 /* Text file busy */ +#define EFBIG 27 /* File too large */ +#define ENOSPC 28 /* No space left on device */ +#define ESPIPE 29 /* Illegal seek */ +#define EROFS 30 /* Read-only file system */ +#define EMLINK 31 /* Too many links */ +#define EPIPE 32 /* Broken pipe */ +#define EDOM 33 /* Math argument out of domain of func */ +#define ERANGE 34 /* Math result not representable */ + +#endif +#define EDEADLK 35 /* Resource deadlock would occur */ +#define ENAMETOOLONG 36 /* File name too long */ +#define ENOLCK 37 /* No record locks available */ +#define ENOSYS 38 /* Function not implemented */ +#define ENOTEMPTY 39 /* Directory not empty */ +#define ELOOP 40 /* Too many symbolic links encountered */ +#define EWOULDBLOCK EAGAIN /* Operation would block */ +#define ENOMSG 42 /* No message of desired type */ +#define EIDRM 43 /* Identifier removed */ +#define ECHRNG 44 /* Channel number out of range */ +#define EL2NSYNC 45 /* Level 2 not synchronized */ +#define EL3HLT 46 /* Level 3 halted */ +#define EL3RST 47 /* Level 3 reset */ +#define ELNRNG 48 /* Link number out of range */ +#define EUNATCH 49 /* Protocol driver not attached */ +#define ENOCSI 50 /* No CSI structure available */ +#define EL2HLT 51 /* Level 2 halted */ +#define EBADE 52 /* Invalid exchange */ +#define EBADR 53 /* Invalid request descriptor */ +#define EXFULL 54 /* Exchange full */ +#define ENOANO 55 /* No anode */ +#define EBADRQC 56 /* Invalid request code */ +#define EBADSLT 57 /* Invalid slot */ + +#define EDEADLOCK EDEADLK + +#define EBFONT 59 /* Bad font file format */ +#define ENOSTR 60 /* Device not a stream */ +#define ENODATA 61 /* No data available */ +#define ETIME 62 /* Timer expired */ +#define ENOSR 63 /* Out of streams resources */ +#define ENONET 64 /* Machine is not on the network */ +#define ENOPKG 65 /* Package not installed */ +#define EREMOTE 66 /* Object is remote */ +#define ENOLINK 67 /* Link has been severed */ +#define EADV 68 /* Advertise error */ +#define ESRMNT 69 /* Srmount error */ +#define ECOMM 70 /* Communication error on send */ +#define EPROTO 71 /* Protocol error */ +#define EMULTIHOP 72 /* Multihop attempted */ +#define EDOTDOT 73 /* RFS specific error */ +#define EBADMSG 74 /* Not a data message */ +#define EOVERFLOW 75 /* Value too large for defined data type */ +#define ENOTUNIQ 76 /* Name not unique on network */ +#define EBADFD 77 /* File descriptor in bad state */ +#define EREMCHG 78 /* Remote address changed */ +#define ELIBACC 79 /* Can not access a needed shared library */ +#define ELIBBAD 80 /* Accessing a corrupted shared library */ +#define ELIBSCN 81 /* .lib section in a.out corrupted */ +#define ELIBMAX 82 /* Attempting to link in too many shared libraries */ +#define ELIBEXEC 83 /* Cannot exec a shared library directly */ +#define EILSEQ 84 /* Illegal byte sequence */ +#define ERESTART 85 /* Interrupted system call should be restarted */ +#define ESTRPIPE 86 /* Streams pipe error */ +#define EUSERS 87 /* Too many users */ +#define ENOTSOCK 88 /* Socket operation on non-socket */ +#define EDESTADDRREQ 89 /* Destination address required */ +#define EMSGSIZE 90 /* Message too long */ +#define EPROTOTYPE 91 /* Protocol wrong type for socket */ +#define ENOPROTOOPT 92 /* Protocol not available */ +#define EPROTONOSUPPORT 93 /* Protocol not supported */ +#define ESOCKTNOSUPPORT 94 /* Socket type not supported */ +#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */ +#define EPFNOSUPPORT 96 /* Protocol family not supported */ +#define EAFNOSUPPORT 97 /* Address family not supported by protocol */ +#define EADDRINUSE 98 /* Address already in use */ +#define EADDRNOTAVAIL 99 /* Cannot assign requested address */ +#define ENETDOWN 100 /* Network is down */ +#define ENETUNREACH 101 /* Network is unreachable */ +#define ENETRESET 102 /* Network dropped connection because of reset */ +#define ECONNABORTED 103 /* Software caused connection abort */ +#define ECONNRESET 104 /* Connection reset by peer */ +#define ENOBUFS 105 /* No buffer space available */ +#define EISCONN 106 /* Transport endpoint is already connected */ +#define ENOTCONN 107 /* Transport endpoint is not connected */ +#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */ +#define ETOOMANYREFS 109 /* Too many references: cannot splice */ +#define ETIMEDOUT 110 /* Connection timed out */ +#define ECONNREFUSED 111 /* Connection refused */ +#define EHOSTDOWN 112 /* Host is down */ +#define EHOSTUNREACH 113 /* No route to host */ +#define EALREADY 114 /* Operation already in progress */ +#define EINPROGRESS 115 /* Operation now in progress */ +#define ESTALE 116 /* Stale NFS file handle */ +#define EUCLEAN 117 /* Structure needs cleaning */ +#define ENOTNAM 118 /* Not a XENIX named type file */ +#define ENAVAIL 119 /* No XENIX semaphores available */ +#define EISNAM 120 /* Is a named type file */ +#define EREMOTEIO 121 /* Remote I/O error */ +#define EDQUOT 122 /* Quota exceeded */ + +#define ENOMEDIUM 123 /* No medium found */ +#define EMEDIUMTYPE 124 /* Wrong medium type */ +#define ECANCELED 125 /* Operation Canceled */ +#define ENOKEY 126 /* Required key not available */ +#define EKEYEXPIRED 127 /* Key has expired */ +#define EKEYREVOKED 128 /* Key has been revoked */ +#define EKEYREJECTED 129 /* Key was rejected by service */ + +/* for robust mutexes */ +#define EOWNERDEAD 130 /* Owner died */ +#define ENOTRECOVERABLE 131 /* State not recoverable */ + +#endif diff --git a/l4/pkg/uclibc/lib/uclibc/ARCH-x86/include/asm/ioctls.h b/l4/pkg/uclibc/lib/uclibc/ARCH-x86/include/asm/ioctls.h new file mode 100644 index 00000000..c9aa270d --- /dev/null +++ b/l4/pkg/uclibc/lib/uclibc/ARCH-x86/include/asm/ioctls.h @@ -0,0 +1,141 @@ + +/* + * The following is for compatibility across the various Linux + * platforms. The i386 ioctl numbering scheme doesn't really enforce + * a type field. De facto, however, the top 8 bits of the lower 16 + * bits are indeed used as a type field, so we might just as well make + * this explicit here. Please be sure to use the decoding macros + * below from now on. + */ +#define _IOC_NRBITS 8 +#define _IOC_TYPEBITS 8 +#define _IOC_SIZEBITS 14 +#define _IOC_DIRBITS 2 + +#define _IOC_NRMASK ((1 << _IOC_NRBITS)-1) +#define _IOC_TYPEMASK ((1 << _IOC_TYPEBITS)-1) +#define _IOC_SIZEMASK ((1 << _IOC_SIZEBITS)-1) +#define _IOC_DIRMASK ((1 << _IOC_DIRBITS)-1) + +#define _IOC_NRSHIFT 0 +#define _IOC_TYPESHIFT (_IOC_NRSHIFT+_IOC_NRBITS) +#define _IOC_SIZESHIFT (_IOC_TYPESHIFT+_IOC_TYPEBITS) +#define _IOC_DIRSHIFT (_IOC_SIZESHIFT+_IOC_SIZEBITS) + +/* + * Direction bits. + */ +#define _IOC_NONE 0U +#define _IOC_WRITE 1U +#define _IOC_READ 2U + +#define _IOC(dir,type,nr,size) \ + (((dir) << _IOC_DIRSHIFT) | \ + ((type) << _IOC_TYPESHIFT) | \ + ((nr) << _IOC_NRSHIFT) | \ + ((size) << _IOC_SIZESHIFT)) + +/* used to create numbers */ +#define _IO(type,nr) _IOC(_IOC_NONE,(type),(nr),0) +#define _IOR(type,nr,size) _IOC(_IOC_READ,(type),(nr),sizeof(size)) +#define _IOW(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),sizeof(size)) +#define _IOWR(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size)) + +/* used to decode ioctl numbers.. */ +#define _IOC_DIR(nr) (((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK) +#define _IOC_TYPE(nr) (((nr) >> _IOC_TYPESHIFT) & _IOC_TYPEMASK) +#define _IOC_NR(nr) (((nr) >> _IOC_NRSHIFT) & _IOC_NRMASK) +#define _IOC_SIZE(nr) (((nr) >> _IOC_SIZESHIFT) & _IOC_SIZEMASK) + +/* ...and for the drivers/sound files... */ + +#define IOC_IN (_IOC_WRITE << _IOC_DIRSHIFT) +#define IOC_OUT (_IOC_READ << _IOC_DIRSHIFT) +#define IOC_INOUT ((_IOC_WRITE|_IOC_READ) << _IOC_DIRSHIFT) +#define IOCSIZE_MASK (_IOC_SIZEMASK << _IOC_SIZESHIFT) +#define IOCSIZE_SHIFT (_IOC_SIZESHIFT) + +/* 0x54 is just a magic number to make these relatively unique ('T') */ + +#define TCGETS 0x5401 +#define TCSETS 0x5402 +#define TCSETSW 0x5403 +#define TCSETSF 0x5404 +#define TCGETA 0x5405 +#define TCSETA 0x5406 +#define TCSETAW 0x5407 +#define TCSETAF 0x5408 +#define TCSBRK 0x5409 +#define TCXONC 0x540A +#define TCFLSH 0x540B +#define TIOCEXCL 0x540C +#define TIOCNXCL 0x540D +#define TIOCSCTTY 0x540E +#define TIOCGPGRP 0x540F +#define TIOCSPGRP 0x5410 +#define TIOCOUTQ 0x5411 +#define TIOCSTI 0x5412 +#define TIOCGWINSZ 0x5413 +#define TIOCSWINSZ 0x5414 +#define TIOCMGET 0x5415 +#define TIOCMBIS 0x5416 +#define TIOCMBIC 0x5417 +#define TIOCMSET 0x5418 +#define TIOCGSOFTCAR 0x5419 +#define TIOCSSOFTCAR 0x541A +#define FIONREAD 0x541B +#define TIOCINQ FIONREAD +#define TIOCLINUX 0x541C +#define TIOCCONS 0x541D +#define TIOCGSERIAL 0x541E +#define TIOCSSERIAL 0x541F +#define TIOCPKT 0x5420 +#define FIONBIO 0x5421 +#define TIOCNOTTY 0x5422 +#define TIOCSETD 0x5423 +#define TIOCGETD 0x5424 +#define TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */ +#define TIOCTTYGSTRUCT 0x5426 /* For debugging only */ +#define TIOCSBRK 0x5427 /* BSD compatibility */ +#define TIOCCBRK 0x5428 /* BSD compatibility */ +#define TIOCGSID 0x5429 /* Return the session ID of FD */ +#define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */ +#define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */ + +#define FIONCLEX 0x5450 /* these numbers need to be adjusted. */ +#define FIOCLEX 0x5451 +#define FIOASYNC 0x5452 +#define TIOCSERCONFIG 0x5453 +#define TIOCSERGWILD 0x5454 +#define TIOCSERSWILD 0x5455 +#define TIOCGLCKTRMIOS 0x5456 +#define TIOCSLCKTRMIOS 0x5457 +#define TIOCSERGSTRUCT 0x5458 /* For debugging only */ +#define TIOCSERGETLSR 0x5459 /* Get line status register */ +#define TIOCSERGETMULTI 0x545A /* Get multiport config */ +#define TIOCSERSETMULTI 0x545B /* Set multiport config */ + +#define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */ +#define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */ +#define TIOCGHAYESESP 0x545E /* Get Hayes ESP configuration */ +#define TIOCSHAYESESP 0x545F /* Set Hayes ESP configuration */ +#define FIOQSIZE 0x5460 + +/* Used for packet mode */ +#define TIOCPKT_DATA 0 +#define TIOCPKT_FLUSHREAD 1 +#define TIOCPKT_FLUSHWRITE 2 +#define TIOCPKT_STOP 4 +#define TIOCPKT_START 8 +#define TIOCPKT_NOSTOP 16 +#define TIOCPKT_DOSTOP 32 + +#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */ + +/* Socket-level I/O control calls. */ +#define FIOSETOWN 0x8901 +#define SIOCSPGRP 0x8902 +#define FIOGETOWN 0x8903 +#define SIOCGPGRP 0x8904 +#define SIOCATMARK 0x8905 +#define SIOCGSTAMP 0x8906 /* Get stamp */ diff --git a/l4/pkg/uclibc/lib/uclibc/ARCH-x86/include/asm/sigcontext.h b/l4/pkg/uclibc/lib/uclibc/ARCH-x86/include/asm/sigcontext.h new file mode 100644 index 00000000..e830b9b9 --- /dev/null +++ b/l4/pkg/uclibc/lib/uclibc/ARCH-x86/include/asm/sigcontext.h @@ -0,0 +1,66 @@ + +struct _fpreg { + unsigned short significand[4]; + unsigned short exponent; +}; + +struct _fpxreg { + unsigned short significand[4]; + unsigned short exponent; + unsigned short padding[3]; +}; + +struct _xmmreg { + unsigned long element[4]; +}; + +struct _fpstate { + /* Regular FPU environment */ + unsigned long cw; + unsigned long sw; + unsigned long tag; + unsigned long ipoff; + unsigned long cssel; + unsigned long dataoff; + unsigned long datasel; + struct _fpreg _st[8]; + unsigned short status; + unsigned short magic; /* 0xffff = regular FPU data only */ + + /* FXSR FPU environment */ + unsigned long _fxsr_env[6]; /* FXSR FPU env is ignored */ + unsigned long mxcsr; + unsigned long reserved; + struct _fpxreg _fxsr_st[8]; /* FXSR FPU reg data is ignored */ + struct _xmmreg _xmm[8]; + unsigned long padding[56]; +}; + +#define X86_FXSR_MAGIC 0x0000 +#define PC(ctx) (ctx.eip) + +struct sigcontext { + unsigned short gs, __gsh; + unsigned short fs, __fsh; + unsigned short es, __esh; + unsigned short ds, __dsh; + unsigned long edi; + unsigned long esi; + unsigned long ebp; + unsigned long esp; + unsigned long ebx; + unsigned long edx; + unsigned long ecx; + unsigned long eax; + unsigned long trapno; + unsigned long err; + unsigned long eip; + unsigned short cs, __csh; + unsigned long eflags; + unsigned long esp_at_signal; + unsigned short ss, __ssh; + struct _fpstate * fpstate; + unsigned long oldmask; + unsigned long cr2; +}; + diff --git a/l4/pkg/uclibc/lib/uclibc/ARCH-x86/include/asm/socket.h b/l4/pkg/uclibc/lib/uclibc/ARCH-x86/include/asm/socket.h new file mode 100644 index 00000000..0ce1b865 --- /dev/null +++ b/l4/pkg/uclibc/lib/uclibc/ARCH-x86/include/asm/socket.h @@ -0,0 +1,48 @@ +#ifndef _ASM_SOCKET_H +#define _ASM_SOCKET_H + +/* For setsockopt(2) */ +#define SOL_SOCKET 1 + +#define SO_DEBUG 1 +#define SO_REUSEADDR 2 +#define SO_TYPE 3 +#define SO_ERROR 4 +#define SO_DONTROUTE 5 +#define SO_BROADCAST 6 +#define SO_SNDBUF 7 +#define SO_RCVBUF 8 +#define SO_KEEPALIVE 9 +#define SO_OOBINLINE 10 +#define SO_NO_CHECK 11 +#define SO_PRIORITY 12 +#define SO_LINGER 13 +#define SO_BSDCOMPAT 14 +/* To add :#define SO_REUSEPORT 15 */ +#define SO_PASSCRED 16 +#define SO_PEERCRED 17 +#define SO_RCVLOWAT 18 +#define SO_SNDLOWAT 19 +#define SO_RCVTIMEO 20 +#define SO_SNDTIMEO 21 + +/* Security levels - as per NRL IPv6 - don't actually do anything */ +#define SO_SECURITY_AUTHENTICATION 22 +#define SO_SECURITY_ENCRYPTION_TRANSPORT 23 +#define SO_SECURITY_ENCRYPTION_NETWORK 24 + +#define SO_BINDTODEVICE 25 + +/* Socket filtering */ +#define SO_ATTACH_FILTER 26 +#define SO_DETACH_FILTER 27 + +#define SO_PEERNAME 28 +#define SO_TIMESTAMP 29 +#define SCM_TIMESTAMP SO_TIMESTAMP + +#define SO_ACCEPTCONN 30 + +#define SO_PEERSEC 31 + +#endif /* _ASM_SOCKET_H */ diff --git a/l4/pkg/uclibc/lib/uclibc/ARCH-x86/include/bits/uClibc_config.h b/l4/pkg/uclibc/lib/uclibc/ARCH-x86/include/bits/uClibc_config.h new file mode 100644 index 00000000..cf2c9f70 --- /dev/null +++ b/l4/pkg/uclibc/lib/uclibc/ARCH-x86/include/bits/uClibc_config.h @@ -0,0 +1,291 @@ +#if !defined __FEATURES_H && !defined __need_uClibc_config_h +# error Never include directly; use instead +#endif + +#ifndef libc_hidden_proto +#define libc_hidden_proto(x) +#endif +#ifndef libm_hidden_proto +#define libm_hidden_proto(x) +#endif +#ifndef librt_hidden_proto +#define librt_hidden_proto(x) +#endif + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE 1 +#endif + +#define __UCLIBC_MAJOR__ 0 +#define __UCLIBC_MINOR__ 9 +#define __UCLIBC_SUBLEVEL__ 29 +/* Automatically generated make config: don't edit */ +/* Sun Feb 10 18:15:17 2008 */ +#undef __TARGET_alpha__ +#undef __TARGET_arm__ +#undef __TARGET_avr32__ +#undef __TARGET_bfin__ +#undef __TARGET_cris__ +#undef __TARGET_e1__ +#undef __TARGET_frv__ +#undef __TARGET_h8300__ +#undef __TARGET_hppa__ +#define __TARGET_i386__ 1 +#undef __TARGET_i960__ +#undef __TARGET_ia64__ +#undef __TARGET_m68k__ +#undef __TARGET_microblaze__ +#undef __TARGET_mips__ +#undef __TARGET_nios__ +#undef __TARGET_nios2__ +#undef __TARGET_powerpc__ +#undef __TARGET_sh__ +#undef __TARGET_sh64__ +#undef __TARGET_sparc__ +#undef __TARGET_v850__ +#undef __TARGET_vax__ +#undef __TARGET_x86_64__ +#undef __TARGET_xtensa__ + +/* Target Architecture Features and Options */ +#define __TARGET_ARCH__ "i386" +#define __FORCE_OPTIONS_FOR_ARCH__ 1 +#define __CONFIG_GENERIC_386__ 1 +#undef __CONFIG_386__ +#undef __CONFIG_486__ +#undef __CONFIG_586__ +#undef __CONFIG_586MMX__ +#undef __CONFIG_686__ +#undef __CONFIG_PENTIUMII__ +#undef __CONFIG_PENTIUMIII__ +#undef __CONFIG_PENTIUM4__ +#undef __CONFIG_K6__ +#undef __CONFIG_K7__ +#undef __CONFIG_ELAN__ +#undef __CONFIG_CRUSOE__ +#undef __CONFIG_WINCHIPC6__ +#undef __CONFIG_WINCHIP2__ +#undef __CONFIG_CYRIXIII__ +#undef __CONFIG_NEHEMIAH__ +#define __TARGET_SUBARCH__ "" + +/* Using ELF file format */ +#define __ARCH_LITTLE_ENDIAN__ 1 + +/* Using Little Endian */ +#define __ARCH_HAS_MMU__ 1 +#define __ARCH_USE_MMU__ 1 +#define __UCLIBC_HAS_FLOATS__ 1 +/* FM3: For arm. Does not influence x86. */ +#define __UCLIBC_HAS_SOFT_FLOAT__ 1 +#define __HAS_FPU__ 1 +#define __DO_C99_MATH__ 1 +#define __UCLIBC_HAS_LONG_DOUBLE_MATH__ 1 +#define __KERNEL_SOURCE__ "/home/linux" +#define __C_SYMBOL_PREFIX__ "" +#define __HAVE_DOT_CONFIG__ 1 + +/* + * General Library Settings + */ +#undef __HAVE_NO_PIC__ +#define __DOPIC__ 1 +#undef __HAVE_NO_SHARED__ +#define __HAVE_SHARED__ +#undef __ARCH_HAS_NO_LDSO__ +#undef __BUILD_UCLIBC_LDSO__ +#undef __DL_FINI_CRT_COMPAT__ +#define __UCLIBC_CTOR_DTOR__ 1 +#undef __HAS_NO_THREADS__ +#ifndef L4_MINIMAL_LIBC +#define __UCLIBC_HAS_THREADS__ 1 +#define __LINUXTHREADS_OLD__ 1 +#define __UCLIBC_HAS_TLS__ 1 +#define __UCLIBC_HAS_THREADS_NATIVE__ 1 + +#define __UCLIBC_HAS_LFS__ 1 +#define __UCLIBC_STATIC_LDCONFIG__ 1 + +/* + * Networking Support + */ +#define __UCLIBC_HAS_COMPAT_RES_STATE__ 1 +#define __UCLIBC_HAS_IPV4__ 1 + +/* + * String and Stdio Support + */ +#define __UCLIBC_HAS_STRING_GENERIC_OPT__ 1 +#define __UCLIBC_HAS_STRING_ARCH_OPT__ 1 +#define __UCLIBC_HAS_CTYPE_TABLES__ 1 +#define __UCLIBC_HAS_CTYPE_SIGNED__ 1 +#define __UCLIBC_HAS_CTYPE_UNSAFE__ 1 +#undef __UCLIBC_HAS_CTYPE_CHECKED__ +#undef __UCLIBC_HAS_CTYPE_ENFORCED__ +#define __UCLIBC_HAS_WCHAR__ 1 +#undef __UCLIBC_HAS_LOCALE__ +#undef __UCLIBC_HAS_HEXADECIMAL_FLOATS__ +#undef __UCLIBC_HAS_GLIBC_CUSTOM_PRINTF__ +#undef __USE_OLD_VFPRINTF__ +#define __UCLIBC_PRINTF_SCANF_POSITIONAL_ARGS__ 9 +#undef __UCLIBC_HAS_SCANF_GLIBC_A_FLAG__ +#undef __UCLIBC_HAS_STDIO_BUFSIZ_NONE__ +#define __UCLIBC_HAS_STDIO_BUFSIZ_256__ 1 +#undef __UCLIBC_HAS_STDIO_BUFSIZ_512__ +#undef __UCLIBC_HAS_STDIO_BUFSIZ_1024__ +#undef __UCLIBC_HAS_STDIO_BUFSIZ_2048__ +#undef __UCLIBC_HAS_STDIO_BUFSIZ_4096__ +#undef __UCLIBC_HAS_STDIO_BUFSIZ_8192__ +#define __UCLIBC_HAS_STDIO_BUILTIN_BUFFER_NONE__ 1 +#undef __UCLIBC_HAS_STDIO_BUILTIN_BUFFER_4__ +#undef __UCLIBC_HAS_STDIO_BUILTIN_BUFFER_8__ +#undef __UCLIBC_HAS_STDIO_SHUTDOWN_ON_ABORT__ +#define __UCLIBC_HAS_STDIO_GETC_MACRO__ 1 +#define __UCLIBC_HAS_STDIO_PUTC_MACRO__ 1 +#define __UCLIBC_HAS_STDIO_AUTO_RW_TRANSITION__ 1 +#undef __UCLIBC_HAS_FOPEN_LARGEFILE_MODE__ +#undef __UCLIBC_HAS_FOPEN_EXCLUSIVE_MODE__ +#undef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ +#undef __UCLIBC_HAS_PRINTF_M_SPEC__ +#define __UCLIBC_HAS_ERRNO_MESSAGES__ 1 +#undef __UCLIBC_HAS_SYS_ERRLIST__ +#define __UCLIBC_HAS_SIGNUM_MESSAGES__ 1 +#undef __UCLIBC_HAS_SYS_SIGLIST__ +#define __UCLIBC_HAS_GNU_GETOPT__ 1 +#define __UCLIBC_HAS_GNU_GETSUBOPT__ 1 + +/* Big and Tall */ +#define __UCLIBC_HAS_REGEX__ 1 +#define __UCLIBC_HAS_REGEX_OLD__ 1 +#define __UCLIBC_HAS_FNMATCH__ 1 +#define __UCLIBC_HAS_FNMATCH_OLD__ 1 +#undef __UCLIBC_HAS_WORDEXP__ +#undef __UCLIBC_HAS_FTW__ +#define __UCLIBC_HAS_GLOB__ 1 +#define __UCLIBC_HAS_GNU_GLOB__ 1 + +#else /* The minimal version, w/o threads etc. */ + +#define __HAS_NO_THREADS__ 1 +#undef __UCLIBC_HAS_LFS__ +#undef __UCLIBC_STATIC_LDCONFIG__ + +/* + * Networking Support + */ +#undef __UCLIBC_HAS_COMPAT_RES_STATE__ +#undef __UCLIBC_HAS_IPV4__ + +/* + * String and Stdio Support + */ +#define __UCLIBC_HAS_STRING_GENERIC_OPT__ 1 +#define __UCLIBC_HAS_STRING_ARCH_OPT__ 1 +#define __UCLIBC_HAS_CTYPE_TABLES__ 1 +#define __UCLIBC_HAS_CTYPE_SIGNED__ 1 +#define __UCLIBC_HAS_CTYPE_UNSAFE__ 1 +#undef __UCLIBC_HAS_CTYPE_CHECKED__ +#undef __UCLIBC_HAS_CTYPE_ENFORCED__ +#undef __UCLIBC_HAS_WCHAR__ +#undef __UCLIBC_HAS_LOCALE__ +#undef __UCLIBC_HAS_HEXADECIMAL_FLOATS__ +#undef __UCLIBC_HAS_GLIBC_CUSTOM_PRINTF__ +#undef __USE_OLD_VFPRINTF__ +#define __UCLIBC_PRINTF_SCANF_POSITIONAL_ARGS__ 9 +#undef __UCLIBC_HAS_SCANF_GLIBC_A_FLAG__ +#undef __UCLIBC_HAS_STDIO_BUFSIZ_NONE__ +#define __UCLIBC_HAS_STDIO_BUFSIZ_256__ 1 +#undef __UCLIBC_HAS_STDIO_BUFSIZ_512__ +#undef __UCLIBC_HAS_STDIO_BUFSIZ_1024__ +#undef __UCLIBC_HAS_STDIO_BUFSIZ_2048__ +#undef __UCLIBC_HAS_STDIO_BUFSIZ_4096__ +#undef __UCLIBC_HAS_STDIO_BUFSIZ_8192__ +#define __UCLIBC_HAS_STDIO_BUILTIN_BUFFER_NONE__ 1 +#undef __UCLIBC_HAS_STDIO_BUILTIN_BUFFER_4__ +#undef __UCLIBC_HAS_STDIO_BUILTIN_BUFFER_8__ +#undef __UCLIBC_HAS_STDIO_SHUTDOWN_ON_ABORT__ +#define __UCLIBC_HAS_STDIO_GETC_MACRO__ 1 +#define __UCLIBC_HAS_STDIO_PUTC_MACRO__ 1 +#define __UCLIBC_HAS_STDIO_AUTO_RW_TRANSITION__ 1 +#undef __UCLIBC_HAS_FOPEN_LARGEFILE_MODE__ +#undef __UCLIBC_HAS_FOPEN_EXCLUSIVE_MODE__ +#undef __UCLIBC_HAS_GLIBC_CUSTOM_STREAMS__ +#undef __UCLIBC_HAS_PRINTF_M_SPEC__ +#undef __UCLIBC_HAS_ERRNO_MESSAGES__ +#undef __UCLIBC_HAS_SYS_ERRLIST__ +#define __UCLIBC_HAS_SIGNUM_MESSAGES__ 1 +#undef __UCLIBC_HAS_SYS_SIGLIST__ +#define __UCLIBC_HAS_GNU_GETOPT__ 1 +#define __UCLIBC_HAS_GNU_GETSUBOPT__ 1 + +/* Big and Tall */ +#undef __UCLIBC_HAS_REGEX__ +#undef __UCLIBC_HAS_REGEX_OLD__ +#undef __UCLIBC_HAS_FNMATCH__ +#undef __UCLIBC_HAS_FNMATCH_OLD__ +#undef __UCLIBC_HAS_WORDEXP__ +#undef __UCLIBC_HAS_FTW__ +#define __UCLIBC_HAS_GLOB__ 1 +#define __UCLIBC_HAS_GNU_GLOB__ 1 + +#endif + +#undef __MALLOC__ +#undef __MALLOC_SIMPLE__ +#define __MALLOC_STANDARD__ 1 +#undef __MALLOC_GLIBC_COMPAT__ +#undef __UCLIBC_DYNAMIC_ATEXIT__ +#define __UCLIBC_SUSV3_LEGACY__ +#define __UCLIBC_SUSV3_LEGACY_MACROS__ +#define __UCLIBC_SUSV4_LEGACY__ 1 +#undef __HAS_SHADOW__ +#define __UNIX98PTY_ONLY__ 1 +#define __ASSUME_DEVPTS__ 1 +#define __UCLIBC_HAS_TM_EXTENSIONS__ 1 +#define __UCLIBC_HAS_TZ_CACHING__ 1 +#undef __UCLIBC_HAS_TZ_FILE__ +#undef __UCLIBC_HAS_TZ_FILE_READ_MANY__ +#undef __UCLIBC_TZ_FILE_PATH__ + +/* Advanced Library Settings */ +#define __UCLIBC_PWD_BUFFER_SIZE__ 256 +#define __UCLIBC_GRP_BUFFER_SIZE__ 256 + +#define __UCLIBC_HAS_REALTIME__ +#define __UCLIBC_HAS_ADVANCED_REALTIME__ + +/* + * Networking Support + */ +#define __UCLIBC_HAS_IPV6__ 1 +#undef __UCLIBC_HAS_RPC__ +#undef __UCLIBC_USE_NETLINK__ + + +/* Library Installation Options */ +#define __SYSTEM_LDSO__ "/lib/ld-linux.so.2" +#define __RUNTIME_PREFIX__ "/usr/$(TARGET_ARCH)-linux-uclibc/" +#define __DEVEL_PREFIX__ "/usr/$(TARGET_ARCH)-linux-uclibc/usr/" + +/* + * uClibc security related options + */ +#undef __UCLIBC_SECURITY__ + + +/* uClibc development/debugging options */ +#define __CROSS_COMPILER_PREFIX__ "" +#define __UCLIBC_EXTRA_CFLAGS__ "" +#undef __DODEBUG__ +#undef __DODEBUG_PT__ +#define __DOSTRIP__ 1 +#undef __DOASSERTS__ +#define __SUPPORT_LD_DEBUG__ 1 +#undef __SUPPORT_LD_DEBUG_EARLY__ +//#define __SUPPORT_LD_DEBUG_EARLY__ 1 +#define __LDSO_GNU_HASH_SUPPORT__ 1 +#define __UCLIBC_MALLOC_DEBUGGING__ 1 +#define __WARNINGS__ "-Wall" +#undef __EXTRA_WARNINGS__ +#undef __DOMULTI__ +#undef __UCLIBC_MJN3_ONLY__ diff --git a/l4/pkg/uclibc/lib/uclibc/ARCH-x86/include/linux/limits.h b/l4/pkg/uclibc/lib/uclibc/ARCH-x86/include/linux/limits.h new file mode 100644 index 00000000..e2074719 --- /dev/null +++ b/l4/pkg/uclibc/lib/uclibc/ARCH-x86/include/linux/limits.h @@ -0,0 +1,7 @@ +#ifndef _LINUX_LIMITS_H +#define _LINUX_LIMITS_H + +#define PATH_MAX 4096 +#define NAME_MAX 255 + +#endif diff --git a/l4/pkg/uclibc/lib/uclibc/ARCH-x86/include/linux/param.h b/l4/pkg/uclibc/lib/uclibc/ARCH-x86/include/linux/param.h new file mode 100644 index 00000000..add9bbd4 --- /dev/null +++ b/l4/pkg/uclibc/lib/uclibc/ARCH-x86/include/linux/param.h @@ -0,0 +1,6 @@ +#ifndef _LINUX_PARAM_H +#define _LINUX_PARAM_H + +#define MAXHOSTNAMELEN 64 + +#endif diff --git a/l4/pkg/uclibc/lib/uclibc/Make.rules b/l4/pkg/uclibc/lib/uclibc/Make.rules new file mode 100644 index 00000000..e3e90f3f --- /dev/null +++ b/l4/pkg/uclibc/lib/uclibc/Make.rules @@ -0,0 +1,84 @@ +# vi:ft=make +LIBCSRC_DIR ?= $(SRC_DIR) + +DEFINES += -DL4_THREAD_SAFE -DL4_NO_RTTI=1 +DEFINES_x86-l4f += -DUSE_TLS=1 +DEFINES_amd64-l4f += -DUSE_TLS=1 +DEFINES_arm-l4f += -DUSE_TLS=1 +DEFINES_ppc32-l4f += -DUSE_TLS=1 +DEFINES_sparc-l4f += -DUSE_TLS=1 +TARGET := libuc_c.a libuc_c.so libuc_c_nonshared.p.a +PC_FILENAME := libc +PC_LIBS := -luc_c + +include $(LIBCSRC_DIR)/make_vars.mk +include $(LIBCSRC_DIR)/make_rules.mk +include $(LIBCSRC_DIR)/contrib_files.mk + +LDFLAGS = -z combreloc -z relro --sort-common \ + --warn-common + +LDFLAGS_NONGOLD = --warn-once --sort-section=alignment +LDFLAGS += $(LDFLAGS_NONGOLD) + +LDFLAGS_libuc_c.so := -init __uClibc_init + +DIRS := libc/string libc/inet libc/pwd_grp libc/unistd libc/signal \ + libc/stdlib libc/stdlib/malloc-standard libc/stdio \ + libc/misc libc/sysdeps/linux libc/termios libm libcrypt + +SUB_MODULES := wchar large_file + +# process all sources for the libc +$(eval $(call PROCESS_src_lists, $(DIRS), $(SUB_MODULES))) +# libm stuff +$(eval $(call PROCESS_template_src, libm, float double)) + +UCLIBC_SRC_CC += _exit.cc + +SRC_C_libuc_c.so += $(UCLIBC_SRC_C) $(UCLIBC_SRC_C_libuc_c.so) +SRC_C_libuc_c.a += $(UCLIBC_SRC_C) $(UCLIBC_SRC_C_libuc_c.a) +SRC_S_libuc_c.so += $(UCLIBC_SRC_S) $(UCLIBC_SRC_S_libuc_c.so) +SRC_S_libuc_c.a += $(UCLIBC_SRC_S) $(UCLIBC_SRC_S_libuc_c.a) +SRC_CC_libuc_c.so += $(UCLIBC_SRC_CC) $(UCLIBC_SRC_CC_libuc_c.so) +SRC_CC_libuc_c.a += $(UCLIBC_SRC_CC) $(UCLIBC_SRC_CC_libuc_c.a) + +SRC_C_libuc_c.so += $(PTHOBJ_PFX)/forward.c $(PTHOBJ_PFX)/libc_pthread_init.c +SRC_CC_libuc_c.a_x86-l4f += $(PTHOBJ_PFX)/sysdeps/generic/libc-tls.cc +SRC_C_libuc_c.a_x86-l4f += $(PTHOBJ_PFX)/sysdeps/generic/dl-tls.c +SRC_CC_libuc_c.a_amd64-l4f += $(PTHOBJ_PFX)/sysdeps/generic/libc-tls.cc +SRC_C_libuc_c.a_amd64-l4f += $(PTHOBJ_PFX)/sysdeps/generic/dl-tls.c +SRC_CC_libuc_c.a_arm-l4f += $(PTHOBJ_PFX)/sysdeps/generic/libc-tls.cc +SRC_C_libuc_c.a_arm-l4f += $(PTHOBJ_PFX)/sysdeps/generic/dl-tls.c +SRC_CC_libuc_c.a_ppc32-l4f += $(PTHOBJ_PFX)/sysdeps/generic/libc-tls.cc +SRC_C_libuc_c.a_ppc32-l4f += $(PTHOBJ_PFX)/sysdeps/generic/dl-tls.c +SRC_CC_libuc_c.a_sparc-l4f += $(PTHOBJ_PFX)/sysdeps/generic/libc-tls.cc +SRC_C_libuc_c.a_sparc-l4f += $(PTHOBJ_PFX)/sysdeps/generic/dl-tls.c + +SRC_C_libuc_c_nonshared.p.a += libc/stdlib/atexit.c +SRC_C_libuc_c.a += libc/stdlib/atexit.c + +SRC_C_libuc_c.so_x86-l4f += libc/misc/pthread/tsd.c +SRC_C_libuc_c.a_x86-l4f += libc/misc/pthread/tsd.c +SRC_C_libuc_c.so_amd64-l4f += libc/misc/pthread/tsd.c +SRC_C_libuc_c.a_amd64-l4f += libc/misc/pthread/tsd.c +SRC_C_libuc_c.so_arm-l4f += libc/misc/pthread/tsd.c +SRC_C_libuc_c.a_arm-l4f += libc/misc/pthread/tsd.c +SRC_C_libuc_c.so_ppc32-l4f += libc/misc/pthread/tsd.c +SRC_C_libuc_c.a_ppc32-l4f += libc/misc/pthread/tsd.c +SRC_C_libuc_c.so_sparc-l4f += libc/misc/pthread/tsd.c +SRC_C_libuc_c.a_sparc-l4f += libc/misc/pthread/tsd.c + +SRC_C_libuc_c.so_arm-l4f += ARCH-arm/aeabi_read_tp_generic.c +SRC_C_libuc_c.a_arm-l4f += ARCH-arm/aeabi_read_tp_generic.c +#SRC_S_libuc_c.so_arm-l4f += ARCH-arm/aeabi_read_tp-v6p.S +#SRC_S_libuc_c.a_arm-l4f += ARCH-arm/aeabi_read_tp-v6p.S + +CXXFLAGS_libc-tls.cc += -fno-rtti -fno-exceptions + +CPPFLAGS_libc-tls.cc += $(LDSO_INC) +CPPFLAGS_dl-tls.c += $(LDSO_INC) + +$(GENERAL_D_LOC): $(LIBCSRC_DIR_ABS)/Make.rules $(LIBCSRC_DIR)/contrib_files.mk \ + $(LIBCSRC_DIR)/make_vars.mk $(LIBCSRC_DIR)/make_rules.mk + diff --git a/l4/pkg/uclibc/lib/uclibc/Makefile b/l4/pkg/uclibc/lib/uclibc/Makefile new file mode 100644 index 00000000..2514faba --- /dev/null +++ b/l4/pkg/uclibc/lib/uclibc/Makefile @@ -0,0 +1,6 @@ +PKGDIR ?= ../.. +L4DIR ?= $(PKGDIR)/../.. + +include $(L4DIR)/mk/Makeconf +include src_rules.mk + diff --git a/l4/pkg/uclibc/lib/uclibc/_exit.cc b/l4/pkg/uclibc/lib/uclibc/_exit.cc new file mode 100644 index 00000000..d6cdc64e --- /dev/null +++ b/l4/pkg/uclibc/lib/uclibc/_exit.cc @@ -0,0 +1,14 @@ +#include +#include +#include + +extern "C" void _exit(int code) __attribute__ ((__noreturn__, __weak__)); + +void _exit(int code) +{ + L4Re::Env const *e; + if (l4re_global_env && (e = L4Re::Env::env()) && e->parent().is_valid()) + e->parent()->signal(0, code); + for (;;) + l4_ipc_sleep(L4_IPC_NEVER); +} diff --git a/l4/pkg/uclibc/lib/uclibc/contrib_files.mk b/l4/pkg/uclibc/lib/uclibc/contrib_files.mk new file mode 100644 index 00000000..ee2e6942 --- /dev/null +++ b/l4/pkg/uclibc/lib/uclibc/contrib_files.mk @@ -0,0 +1,740 @@ + +define SRC_libc/sysdeps/linux + setjmp + bsd-setjmp + bsd-_setjmp + creat + longjmp + __longjmp + getdents + getsid + common/gethostname +endef + +define SRC_libc/sysdeps/linux_large_file + creat64 +endef + +SRC_libc/sysdeps/linux_arm += aeabi_atexit + +define SRC_libc/sysdeps/linux_sparc__with_soft_fp + soft-fp/q_add + soft-fp/q_cmp + soft-fp/q_cmpe + soft-fp/q_div + soft-fp/q_dtoq + soft-fp/q_feq + soft-fp/q_fge + soft-fp/q_fgt + soft-fp/q_fle + soft-fp/q_flt + soft-fp/q_fne + soft-fp/q_itoq + soft-fp/q_lltoq + soft-fp/q_mul + soft-fp/q_neg + soft-fp/q_qtod + soft-fp/q_qtoi + soft-fp/q_qtoll + soft-fp/q_qtos + soft-fp/q_qtou + soft-fp/q_qtoull + soft-fp/q_sqrt + soft-fp/q_stoq + soft-fp/q_sub + soft-fp/q_ulltoq + soft-fp/q_util + soft-fp/q_utoq +endef + +ifeq ($(GCCIS_sparc_leon),) + SRC_libc/sysdeps/linux_sparc := $(SRC_libc/sysdeps/linux_sparc__with_soft_fp) +endif + +define SRC_libc/termios + isatty + speed + tcflush + tcgetattr + tcgetpgrp + tcgetsid + tcsetattr + tcsetpgrp + ttyname +endef + +define SRC_libc/stdlib + __cxa_atexit + __exit_handler + __fp_range_check + __strtofpmax + __uc_malloc + _stdlib_mb_cur_max + _stdlib_strto_l + _stdlib_strto_ll + _strtod + abort + abs + atof + atoi + atol + atoll + bsearch + div + drand48-iter + drand48 + drand48_r + erand48 + erand48_r + exit + getenv + jrand48 + jrand48_r + labs + ldiv + llabs + lldiv + lrand48 + lrand48_r + mkstemp + nrand48 + nrand48_r + on_exit + posix_memalign + qsort + rand + rand_r + random + random_r + realpath + setenv + stdlib + strtod + strtof + strtol + strtold + strtoll + strtoul + strtoull +endef + +define SRC_libc/stdlib/malloc-standard + calloc + free + mallinfo + malloc + mallopt + memalign + realloc +endef + +define SRC_libc/stdlib/malloc-simple + alloc + calloc + free + malloc + memalign + realloc +endef + +define SRC_libc/stdlib_wchar + wcstombs + mblen + mbstowcs +endef + +define SRC_libc/string + basename + dirname + ffs + memccpy + stpcpy + stpncpy + strcasecmp + strcasestr + strdup + strerror + __xpg_strerror_r + _string_syserrmsgs + __glibc_strerror_r + _string_syssigmsgs + sys_siglist + strsignal + psignal + __xpg_basename + strlcat + strlcpy + sys_errlist + strndup + strncasecmp + strtok + bcopy + bzero + memchr + memcpy + memmove + memset + strcat + strchr + strcmp + strcpy + strlen + strncat + strncmp + strncpy + strnlen + strrchr + memcmp + memmem + mempcpy + memrchr + rawmemchr + strchrnul + strcspn + strsep + strspn + strstr + strtok_r + strpbrk +endef + +define SRC_libc/string_wchar + wcsnlen + wcslen + wmemcpy +endef + +SRC_libc/string_arm := _memcpy + +define SRC_libc/misc + assert/__assert + ctype/ctype + ctype/isalnum + ctype/isalpha + ctype/isblank + ctype/iscntrl + ctype/isdigit + ctype/isgraph + ctype/islower + ctype/isprint + ctype/ispunct + ctype/isspace + ctype/isupper + ctype/isxdigit + ctype/tolower + ctype/toupper + ctype/__C_ctype_b + ctype/__C_ctype_tolower + ctype/__C_ctype_toupper + ctype/__ctype_b_loc + ctype/__ctype_tolower_loc + ctype/__ctype_toupper_loc + ctype/__ctype_assert + ctype/isctype + dirent/alphasort + dirent/closedir + dirent/dirfd + dirent/opendir + dirent/readdir + dirent/readdir_r + dirent/rewinddir + dirent/scandir + dirent/seekdir + dirent/telldir + error/err + fnmatch/fnmatch + glob/glob + internals/errno + internals/__errno_location + internals/__h_errno_location + internals/__uClibc_main + internals/parse_config + internals/tempname + locale/locale + locale/localeconv + locale/nl_langinfo + locale/setlocale + search/hcreate_r + search/hdestroy_r + search/hsearch + search/hsearch_r + search/insque + search/insremque + search/lfind + search/lsearch + search/remque + search/tdelete + search/tdestroy + search/tfind + search/tsearch + search/twalk + time/time + time/asctime + time/asctime_r + time/ctime + time/ctime_r + time/ftime + time/gmtime + time/gmtime_r + time/localtime + time/localtime_r + time/mktime + time/strftime + time/strptime + time/tzset + time/_time_t2tm + time/__time_tm + time/_time_mktime + time/dysize + time/timegm + time/_time_mktime_tzi + time/_time_localtime_tzi + time/difftime + wordexp/wordexp + elf/dl-iterate-phdr +endef + +define SRC_libc/misc_large_file + dirent/alphasort64 + dirent/readdir64 + dirent/readdir64_r + dirent/scandir64 + glob/glob64 +endef + +define SRC_libc/misc_libuc_c.a + elf/dl-support + elf/dl-core +endef + +SRC_libc/misc_libuc_c_minimal.a = $(SRC_libc/misc_libuc_c.a) + +define SRC_libc/misc_wchar + wchar/btowc + wchar/mbrlen + wchar/mbrtowc + wchar/mbsnrtowcs + wchar/mbsrtowcs + wchar/wchar + wchar/wcrtomb + wchar/wcsnrtombs + wchar/wcsrtombs + wctype/iswctype + wctype/wctype + wctype/_wctype +endef + +define SRC_libc/stdio + __fsetlocking + _adjust_pos + _cs_funcs + _fopen + _fpmaxtostr + _fwrite + _READ + _WRITE + _load_inttype + _rfill + _stdio + _store_inttype + _trans2r + _trans2w + _uintmaxtostr + _wcommit + asprintf + clearerr + clearerr.__DO_UNLOCKED + dprintf + fclose + fcloseall + fdopen + feof + feof.__DO_UNLOCKED + ferror + ferror.__DO_UNLOCKED + fflush + fflush.__DO_UNLOCKED + fgetc + fgetc.__DO_UNLOCKED + fgetpos + fgets + fgets.__DO_UNLOCKED + fileno + fileno.__DO_UNLOCKED + flockfile + fopen + freopen + fputs + fputs.__DO_UNLOCKED + fputc + fputc.__DO_UNLOCKED + fprintf + fread + fread.__DO_UNLOCKED + fseeko + fsetpos + ftello + funlockfile + fwrite + fwrite.__DO_UNLOCKED + getdelim + getline + perror + printf + putchar + putchar.__DO_UNLOCKED + puts + remove + rewind + _scanf + vfscanf + __scan_cookie + __psfs_parse_spec + __psfs_do_numeric + scanf + sscanf + fscanf + vscanf + vsscanf + setvbuf + setbuf + setbuffer + setlinebuf + snprintf + sprintf + ungetc + vasprintf + vdprintf + _vfprintf + _vfprintf_internal + vfprintf + _ppfs_init + _ppfs_prepargs + _ppfs_setargs + _ppfs_parsespec + vsnprintf + vsprintf + vprintf +endef + +define SRC_libc/stdio_large_file + fgetpos64 + fopen64 + freopen64 + fseeko64 + fsetpos64 + ftello64 +endef + +define SRC_libc/stdio_wchar + _wfwrite + fputws + fputws.__DO_UNLOCKED + fwprintf + swprintf + _vfwprintf_internal + vfwprintf + vswprintf + vwprintf + wprintf +endef + +define SRC_libc/inet + _res_state + addr + closenameservers + decodea + decoded + decodeh + decodep + decodeq + dnslookup + encodea + encoded + encodeh + encodep + encodeq + ether_addr + formquery + gai_strerror + get_hosts_byaddr_r + get_hosts_byname_r + getaddrinfo + gethostbyaddr + gethostbyaddr_r + gethostbyname + gethostbyname2 + gethostbyname2_r + gethostbyname_r + gethostent + gethostent_r + getnet + getproto + getservice + herror + if_index + inet_addr + inet_aton + inet_lnaof + inet_makeaddr + inet_net + inet_netof + inet_ntoa + in6_addr + lengthd + lengthq + ns_name + ntohl + ntop + opennameservers + opensock + read_etc_hosts_r + res_comp + res_init + res_query + resolv +endef + +define SRC_libc/pwd_grp + pwd_grp + getgrgid + getgrgid_r + getgrnam + getgrnam_r + getpwuid + getpwuid_r + getpwnam + getpwnam_r + getpwent + getpwent_r + __parsepwent + __parsegrent + __pgsreader +endef + +define SRC_libc/unistd + getlogin + getopt + sleep +endef + +define SRC_libc/signal + allocrtsig + raise + sigaddset + sigandset + sigdelset + sigempty + sigfillset + sigismem + sigsetops + sigjmp +endef + +define SRC_libcrypt + crypt + des + md5 +endef + +define SRC_libm + carg + e_acos + e_acosh + e_asin + e_atan2 + e_atanh + e_cosh + e_exp + e_fmod + e_hypot + e_j0 + e_j1 + e_jn + e_lgamma_r + e_log + e_log10 + e_log2 + e_pow + e_remainder + e_rem_pio2 + e_scalb + e_sinh + e_sqrt + k_cos + k_rem_pio2 + k_sin + k_standard + k_tan + s_asinh + s_atan + s_cbrt + s_ceil + s_copysign + s_cos + s_erf + s_expm1 + s_fabs + s_fpclassify + s_fdim + s_finite + s_finitef + s_floor + s_fma + s_fmax + s_fmin + s_frexp + s_ilogb + s_isnan + s_isnanf + s_isinf + s_isinff + s_ldexp + s_lib_version + s_llrint + s_llround + s_log1p + s_logb + s_lrint + s_lround + s_matherr + s_modf + s_nextafter + s_nextafterf + s_remquo + s_rint + s_round + s_scalbn + s_signbit + s_signbitf + s_signgam + s_significand + s_sin + s_tan + s_tanh + s_trunc + w_cabs + w_exp2 + nan +endef + +SRC_libm_float_src = float_wrappers.c +define SRC_libm_float + acos + acosf + acoshf + asinf + asinhf + atan2f + atanf + atanhf + cbrtf + ceilf + copysignf + cosf + coshf + erfcf + erff + exp2f + expf + expm1f + fabsf + fdimf + floorf + fmaf + fmaxf + fminf + fmodf + frexpf + hypotf + ilogbf + ldexpf + lgammaf + llrintf + log10f + log1pf + log2f + logbf + logf + lrintf + lroundf + modff + nearbyintf + nextafterf + powf + remainderf + remquof + rintf + roundf + scalblnf + scalbnf + sinf + sinhf + sqrtf + tanf + tanhf + tgammaf + truncf +endef + +SRC_libm_double_src = ldouble_wrappers.c +define SRC_libm_double + acoshl + acosl + asinhl + asinl + atan2l + atanhl + atanl + cargl + cbrtl + ceill + copysignl + coshl + cosl + erfcl + erfl + expl + expm1l + fabsl + fdiml + floorl + fmal + fmaxl + fminl + fmodl + frexpl + gammal + hypotl + ilogbl + ldexpl + lgammal + llrintl + llroundl + log10l + log1pl + log2l + logbl + logl + lrintl + lroundl + modfl + nearbyintl + nextafterl + powl + remainderl + remquol + rintl + roundl + scalblnl + scalbnl + sinhl + sinl + sqrtl + tanhl + tanl + tgammal + truncl + significandl +endef + diff --git a/l4/pkg/uclibc/lib/uclibc/make_diff.sh b/l4/pkg/uclibc/lib/uclibc/make_diff.sh new file mode 100755 index 00000000..8489452a --- /dev/null +++ b/l4/pkg/uclibc/lib/uclibc/make_diff.sh @@ -0,0 +1,6 @@ +for i in `find . -type f | grep -v "\/.svn\/" | grep -v "\.keep$" | grep -v "~$" | grep "\.[ch]$"` +do +diff -u $i ../contrib/uclibc/$i +done > diff.txt + +find . -type f | grep -v "\/.svn\/" | grep -v "\.keep$" | grep -v "~$" | grep "\.[ch]$" > diff.lst diff --git a/l4/pkg/uclibc/lib/uclibc/make_rules.mk b/l4/pkg/uclibc/lib/uclibc/make_rules.mk new file mode 100644 index 00000000..496b685e --- /dev/null +++ b/l4/pkg/uclibc/lib/uclibc/make_rules.mk @@ -0,0 +1,115 @@ +# vi:ft=make + +CXXFLAGS_amd64 += -mcmodel=medium +CFLAGS_amd64 += -mcmodel=medium + +CPPFLAGS += -nostdinc -include \ + $(CONTRIB_DIR)/include/libc-symbols.h +CFLAGS += -fno-builtin +CFLAGS += -DUCLIBC_INTERNAL +# CFLAGS += -std=iso9899:199901 +DEFINES += -DNDEBUG -D_LIBC -D__UCLIBC_CTOR_DTOR__ +WARNINGS = -Wall -Wstrict-prototypes + +# for building the C library we access internal headers +PRIVATE_INCDIR += $(CONTRIB_DIR)/libc/sysdeps/linux/$(BUILD_ARCH) +PRIVATE_INCDIR += $(CONTRIB_DIR)/libc/sysdeps/linux +# here we cheat a little and allow ../ includes from internal headers +PRIVATE_INCDIR += $(LIBC_DST_DIR)/libc $(PTHREAD_INCDIR) + +# the inet subsystem needs the RESOLVER define to be set +CPPFLAGS_$(LIBC_DST_DIR)/libc/inet += -DRESOLVER="\"resolv.c\"" + +# elf subsystem may access ldso internals +CPPFLAGS_$(LIBC_DST_DIR)/libc/misc/elf += $(LDSO_INC) + +# pthread support from libpthread uses libpthread internals +CPPFLAGS_$(LIBCSRC_DIR_ABS)/../$(PTHOBJ_PFX) += $(addprefix -I,$(PTHREAD_INCDIR)) + +# setup search paths for our sources +vpath %.c $(LIBC_DST_DIR) +vpath %.cc $(LIBC_DST_DIR) +vpath %.S $(LIBC_DST_DIR) +# libpthread support +vpath $(PTHOBJ_PFX)/% $(LIBCSRC_DIR_ABS)/.. + +PICFLAGS += -DSHARED=1 + + +# NOTE the two newlines in the define are essential!! +define NEWLINE + + +endef + + +define add_source_file_x + UCLIBC_SRC_$(1)+=$(2) +endef + +# add a source file to the BID list of sources +add_source_file = $(if $(filter %.c,$(1)), $(eval $(call add_source_file_x,C$(2),$(1))), \ + $(if $(filter %.cc,$(1)), $(eval $(call add_source_file_x,CC$(2),$(1))), \ + $(if $(filter %.S,$(1)), $(eval $(call add_source_file_x,S$(2),$(1))), \ + $(error unknown source file: $(1))))) + +# generate the search path value for source files +gen_search_path = $(LIBC_DST_DIR)/$(1)/$(UCLIBC_ARCH) \ + $(LIBC_DST_DIR)/$(1)/generic \ + $(LIBC_DST_DIR)/$(1)/common \ + $(LIBC_DST_DIR)/$(1) + +# search for a .c, a .S, or a .cc file for the given basename +search_source_file = $(or $(firstword $(foreach d,$(1),$(wildcard $(d)/$(2).[cS] $(d)/$(2).cc))), \ + $(patsubst %.c,%$(suffix $(2)).c,$(firstword $(wildcard $(addsuffix /$(basename $(2)).c,$(1))))), \ + $(error source file for $(2) not found)) + +# arg 1: directory of the subsystem (e.g., libc/string) +# arg 2: the basename of the file to look for (e.g. memcpy, for memcpy.c, memcpy.cc, or +# memcpy.S). +# arg 3: the additional suffix for the SRC_ variable +define HANDLE_file + $(call add_source_file,$(subst $(LIBC_DST_DIR)/,,$(call search_source_file,$(1),$(2))),$(3)) +endef + +HANDLE_dir = $(foreach f,$(subst $(NEWLINE), ,$(SRC_$(1)$(2))),$(call HANDLE_file,$(call gen_search_path,$(1)),$(f),$(3))) + +include $(L4DIR)/mk/rules.inc + +##################### +# Generate pseudo rules for compiling the a template source file to a specific +# object file using a command line define -DL_. This is for example used +# for libm, where all kinds of functions are compiled from float_wrappers.c. +# +# arg 1: subsystem name (e.g. libm) -- +# arg 2: module name (e.g. float, or double) -- +# +# Uses: +# SRC_ as list of target objects to generate +# SRC__src as the source file for the objects +# +define OBJS_FN_templ + OBJS_FN_$(1)$(2) = $(addprefix $(1)/,$(patsubst %,%.o,$(subst $(NEWLINE), ,$(SRC_$(1)$(2))))) + UCLIBC_SRC_C += $$(OBJS_FN_$(1)$(2):.o=.c) + $(call BID_MAKE_RULE_template,$$(OBJS_FN_$(1)$(2)): %.o,$(1)/$$(SRC_$(1)$(2)_src),C,-DL_$$(patsubst %.o,%,$$(notdir $$@))) + $(call BID_MAKE_RULE_template,$$(OBJS_FN_$(1)$(2):.o=.s.o): %.s.o,$(1)/$$(SRC_$(1)$(2)_src),C,$$(PICFLAGS) -DL_$$(patsubst %.s.o,%,$$(notdir $$@))) +endef + + +$(eval $(call BID_GENERATE_DEFAULT_MAKE_RULES,%.__DO_UNLOCKED,%.c,C,-D__DO_UNLOCKED)) + + +define PROCESS_src_lists + # SRC_ (e.g. SRC_libc/string) + $(foreach d,$(1),$(call HANDLE_dir,$(d),,)) + # SRC__ (e.g. SRC_libc/string_arm) + $(foreach d,$(1),$(call HANDLE_dir,$(d),_$(BUILD_ARCH),)) + # SRC__ (e.g. SRC_libc/string_libuc_c.a) + $(foreach t,$(TARGET),$(foreach d,$(1),$(call HANDLE_dir,$(d),_$(t),_$(t)))) + # SRC__ (e.g. SRC_libc/stdio_wchar) + $(foreach t,$(2),$(foreach d,$(1),$(call HANDLE_dir,$(d),_$(t),))) +endef + +define PROCESS_template_src + $(foreach d,$(1),$(foreach m,$(2),$(eval $(call OBJS_FN_templ,$(d),_$(m))))) +endef diff --git a/l4/pkg/uclibc/lib/uclibc/make_vars.mk b/l4/pkg/uclibc/lib/uclibc/make_vars.mk new file mode 100644 index 00000000..85379b35 --- /dev/null +++ b/l4/pkg/uclibc/lib/uclibc/make_vars.mk @@ -0,0 +1,36 @@ +include $(L4DIR)/mk/Makeconf + +LIBCSRC_DIR ?= $(SRC_DIR) +LIBCSRC_DIR_ABS := $(call absfilename,$(LIBCSRC_DIR)) + +SYSDEPS := libc/sysdeps/linux + +# directory to the libc contrib files +CONTRIB_DIR := $(LIBCSRC_DIR_ABS)/../contrib/uclibc + +# destination directory for linking libc sources, with our overlay +LIBC_DST_DIR := $(OBJ_DIR)/src + +# build prefix for pthread sources +PTHOBJ_PFX := libpthread/src + +# pthread source file directory +PTHLIB_DIR := $(LIBCSRC_DIR_ABS)/../libpthread + +# include directory for pthread internals +PTHREAD_INCDIR = $(PTHLIB_DIR)/src/sysdeps/$(UCLIBC_ARCH_$(ARCH)) \ + $(PTHLIB_DIR)/src + +# include dir for accessing ldso internals +LDSO_INC = -I$(CONTRIB_DIR)/ldso/ldso/$(UCLIBC_ARCH) -I$(CONTRIB_DIR)/ldso/include + + +UCLIBC_ARCH_x86 := i386 +UCLIBC_ARCH_arm := arm +UCLIBC_ARCH_amd64 := x86_64 +UCLIBC_ARCH_ppc32 := powerpc +UCLIBC_ARCH_sparc := sparc + +UCLIBC_ARCH := $(UCLIBC_ARCH_$(BUILD_ARCH)) + + diff --git a/l4/pkg/uclibc/lib/uclibc/src_rules.mk b/l4/pkg/uclibc/lib/uclibc/src_rules.mk new file mode 100644 index 00000000..b56dab5c --- /dev/null +++ b/l4/pkg/uclibc/lib/uclibc/src_rules.mk @@ -0,0 +1,21 @@ +LIBCSRC_DIR ?= $(SRC_DIR) + +include $(LIBCSRC_DIR)/make_vars.mk + +LIBC_SRC_DIRS := $(CONTRIB_DIR)/libc \ + $(LIBCSRC_DIR_ABS)/ARCH-all/libc #$(LIBCSRC_DIR)/ARCH-$(BUILD_ARCH)/libc + +LIBC_SRC_DIRS += $(CONTRIB_DIR)/libm \ + $(CONTRIB_DIR)/libcrypt + +LIBC_DST_DIR := $(OBJ_DIR)/src + +$(LIBC_DST_DIR)/.links-done: Makefile + $(MKDIR) -p $(LIBC_DST_DIR) + $(CP) -sfr $(LIBC_SRC_DIRS) $(LIBC_DST_DIR) + touch $@ + +include $(L4DIR)/mk/lib.mk + +$(OBJ_DIR)/.general.d: $(LIBC_DST_DIR)/.links-done + diff --git a/l4/pkg/uclibc/lib/uclibc/target_headers.lst b/l4/pkg/uclibc/lib/uclibc/target_headers.lst new file mode 100644 index 00000000..77e320db --- /dev/null +++ b/l4/pkg/uclibc/lib/uclibc/target_headers.lst @@ -0,0 +1,216 @@ +alloca.h +arpa/inet.h +arpa/nameser_compat.h +arpa/nameser.h +asm/errno.h +asm/socket.h +asm/ioctls.h +asm/sigcontext.h +assert.h +atomic.h +bits/atomic.h +bits/byteswap-common.h +bits/byteswap.h +bits/cmathcalls.h +bits/confname.h +bits/dirent.h +bits/dlfcn.h +bits/elfclass.h +bits/endian.h +bits/environments.h +bits/errno.h +bits/fcntl.h +bits/fenv.h +bits/fenvinline.h +bits/getopt.h +bits/huge_valf.h +bits/huge_val.h +bits/huge_vall.h +bits/inf.h +bits/in.h +bits/ioctls.h +bits/ioctl-types.h +bits/ipc.h +bits/kernel_stat.h +bits/kernel_types.h +bits/kernel-features.h +bits/locale.h +bits/local_lim.h +bits/mathcalls.h +bits/mathdef.h +bits/mathinline.h +bits/mman-common.h +bits/mman.h +bits/msq.h +bits/nan.h +bits/netdb.h +bits/poll.h +bits/posix1_lim.h +bits/posix2_lim.h +bits/posix_opt.h +bits/resource.h +bits/sched.h +bits/select.h +bits/sem.h +bits/setjmp.h +bits/shm.h +bits/sigaction.h +bits/sigcontext.h +bits/sigcontextinfo.h +bits/siginfo.h +bits/signum.h +bits/sigset.h +bits/sigstack.h +bits/sigthread.h +bits/sockaddr.h +bits/socket.h +bits/stackinfo.h +bits/statfs.h +bits/stat.h +bits/stdio_lim.h +bits/syscalls.h +bits/termios.h +bits/time.h +bits/types.h +bits/typesizes.h +bits/uClibc_arch_features.h +bits/uClibc_charclass.h +bits/uClibc_clk_tck.h +bits/uClibc_config.h +bits/uClibc_errno.h +bits/uClibc_fpmax.h +bits/uClibc_locale.h +bits/uClibc_local_lim.h +bits/uClibc_mutex.h +bits/uClibc_page.h +bits/uClibc_pthread.h +bits/uClibc_stdio.h +bits/uClibc_touplow.h +bits/uClibc_uintmaxtostr.h +bits/uClibc_uwchar.h +bits/uClibc_va_copy.h +bits/uio.h +bits/utsname.h +bits/waitflags.h +bits/waitstatus.h +bits/wchar.h +bits/wordsize.h +bits/xopen_lim.h +byteswap.h +complex.h +crypt.h +ctype.h +dirent.h +dlfcn.h +elf.h +endian.h +err.h +errno.h +fcntl.h +features.h +fenv.h +fnmatch.h +fpu_control.h +getopt.h +glob.h +grp.h +ieee754.h +ifaddrs.h +internal/parse_config.h +inttypes.h +langinfo.h +_lfs_64.h +libc-internal.h +libc-symbols.h +libgen.h +libintl.h +limits.h +link.h +linux/errno.h +linux/limits.h +linux/if_ether.h +linux/param.h +locale.h +malloc.h +math.h +memory.h +netdb.h +net/ethernet.h +net/if_arp.h +net/if.h +netinet/ether.h +netinet/if_ether.h +netinet/in.h +netinet/in_systm.h +netinet/ip.h +netinet/ip_icmp.h +netinet/tcp.h +netinet/udp.h +net/route.h +nl_types.h +not-cancel.h +paths.h +poll.h +printf.h +pty.h +pwd.h +resolv.h +rpc/netdb.h +sched.h +search.h +setjmp.h +shadow.h +signal.h +stdint.h +stdio_ext.h +stdio.h +stdlib.h +string.h +strings.h +sys/bitypes.h +sys/cdefs.h +sys/dir.h +sysexits.h +sys/fcntl.h +sys/file.h +sys/ioctl.h +sys/ipc.h +syslog.h +sys/mman.h +sys/mount.h +sys/param.h +sys/poll.h +sys/procfs.h +sys/resource.h +sys/select.h +sys/sem.h +sys/shm.h +sys/socket.h +sys/soundcard.h +sys/statfs.h +sys/stat.h +sys/syscall.h +sys/syslog.h +sys/sysmacros.h +sys/timeb.h +sys/time.h +sys/times.h +sys/ttydefaults.h +sys/types.h +sys/ucontext.h +sys/uio.h +sys/un.h +sys/user.h +sys/utsname.h +sys/vfs.h +sys/wait.h +tar.h +termios.h +time.h +tls.h +ucontext.h +unistd.h +utime.h +wchar.h +wctype.h +wordexp.h diff --git a/l4/tool/Makefile b/l4/tool/Makefile new file mode 100644 index 00000000..53d9a720 --- /dev/null +++ b/l4/tool/Makefile @@ -0,0 +1,13 @@ +L4DIR ?= .. + +# Be sure to add a "/" to config to make the target different from +# BID's "config" target +TARGET := $(wildcard config/ gendep elf-patcher) +TARGET_doc := $(wildcard gendep) + +all:: +doc: + $(if $(TARGET_doc), $(VERBOSE)set -e ; for d in $(TARGET_doc) ; do \ + PWD=$(PWD)/$$d $(MAKE) -C $$d $@ ; done ) + +include $(L4DIR)/mk/subdir.mk diff --git a/l4/tool/bin/entry-selector b/l4/tool/bin/entry-selector new file mode 100755 index 00000000..00dc66e6 --- /dev/null +++ b/l4/tool/bin/entry-selector @@ -0,0 +1,67 @@ +#! /usr/bin/perl -W +# +# (c) 2009-2011 Technische Universität Dresden +# This file is part of TUD:OS and distributed under the terms of the +# GNU General Public License 2. +# Please see the COPYING-GPL-2 file for details. +# +# Adam Lackorzynski +# + +use strict; +use File::Temp qw/tempfile/; + +BEGIN { unshift @INC, $ENV{L4DIR}.'/tool/lib' + if $ENV{L4DIR} && -d $ENV{L4DIR}.'/tool/lib/L4';} + +use L4::ModList; + +unless (defined $ARGV[1]) { + print "ERROR: Need to give command and modules file!\n"; + exit 1; +} + +my @e = L4::ModList::get_entries($ARGV[1]); + +if ($ARGV[0] eq 'menu') + { + my ($tmpfd, $tmpfilename) = tempfile(); + + my $backtitle = ''; + if (defined $ENV{BACKTITLE}) + { + $backtitle = $ENV{BACKTITLE}; + $backtitle =~ s/"/\\"/g; + $backtitle = "--backtitle \"$backtitle\""; + } + + system("dialog $backtitle --title 'Entry selection' " + ." --menu 'Select entry to launch' 18 65 18 ". + join(' ', map { "$_ '$e[$_]'" } (0 .. $#e) )." 2> $tmpfilename"); + + if ($?) + { + print "ERROR: dialog aborted!\n"; + exit 1; + } + + my $o; + read $tmpfd, $o, 100; + close $tmpfd; + unlink $tmpfilename; + + chomp $o; + + if ($o !~ /^\d+$/) + { + print "ERROR: Invalid return value from dialog!\n"; + exit 1; + } + + print STDERR $e[$o]; + exit 0; + } +elsif ($ARGV[0] eq 'list') + { + print join("\n ", "Entries in modules file:", @e), "\n"; + } diff --git a/l4/tool/bin/genexportpack b/l4/tool/bin/genexportpack new file mode 100755 index 00000000..8ac02cc2 --- /dev/null +++ b/l4/tool/bin/genexportpack @@ -0,0 +1,103 @@ +#! /usr/bin/perl -w +# +# (c) 2011 Technische Universität Dresden +# This file is part of TUD:OS and distributed under the terms of the +# GNU General Public License 2. +# Please see the COPYING-GPL-2 file for details. +# +# Adam Lackorzynski +# + +use strict; + +BEGIN { unshift @INC, $ENV{L4DIR}.'/tool/lib' + if $ENV{L4DIR} && -d $ENV{L4DIR}.'/tool/lib/L4';} + +use L4::ModList; +use L4::Grub; +use File::Temp qw/tempdir/; + +my $qemu = $ENV{QEMU} || 'qemu'; +my $module_path = $ENV{SEARCHPATH} || "."; +my %opts = L4::Grub::parse_gengrub_args(); +my $qemu_options = $ENV{QEMU_OPTIONS} || ""; +my $modulesfile = shift; +my $targetdir = shift; +my $unzip_tmp = tempdir(CLEANUP => 1); + +unless (defined $targetdir) { + print "usage: $0 MODULESFILE TARGETDIR entry1 [entry2] ...\n"; + exit(1); +} + +system("mkdir -p \"$targetdir\""); + +open(GRUB1, ">$targetdir/menu.lst") + || die "Cannot create '$targetdir/menu.lst': $!!"; + +open(GRUB2, ">$targetdir/grub.cfg") + || die "Cannot create '$targetdir/grub.cfg': $!!"; + +open(QEMU, ">$targetdir/qemu.sh") + || die "Cannot create '$targetdir/qemu.sh': $!!"; + +delete $opts{timeout} + if @ARGV > 1 and defined $opts{timeout} and $opts{timeout} == 0; + +print GRUB1 L4::Grub::grub1_config_prolog(%opts); +print GRUB2 L4::Grub::grub2_config_prolog(%opts); +print QEMU "#! /bin/sh\n". + "case \"\$1\" in\n"; + +$qemu =~ s@.*/@@; + +my %files; + +sub qemu_get_file($$) +{ + my $command = shift; + my $cmdline = shift; + + my $fp = L4::ModList::get_file_uncompressed_or_die($command, $module_path, + $unzip_tmp); + + $fp = (reverse split(/\/+/, $fp))[0]; + + $cmdline =~ s/^\S+\s*//; + $cmdline =~ s/,/,,/g; + $fp.' '.$cmdline; +} + +foreach my $entryname (@ARGV) + { + print "Processing entry '$entryname'\n"; + my %entry = L4::ModList::get_module_entry($modulesfile, $entryname); + print GRUB1 L4::ModList::generate_grub1_entry($entryname, '', %entry), "\n"; + print GRUB2 L4::ModList::generate_grub2_entry($entryname, '', %entry); + + my @mods = @{$entry{mods}}; + my $kernel = L4::ModList::search_file_or_die($entry{bootstrap}{command}, $module_path); + my $initrd = join(',', map { qemu_get_file($_->{command}, $_->{cmdline}) } @mods); + + $kernel =~ s@.*/@@; + + print QEMU + " $entryname) $qemu -kernel $kernel -append \"$entry{bootstrap}{cmdline}\" ". + "-initrd \"$initrd\" $qemu_options ;;\n"; + + $files{$_} = 1 foreach @{$entry{files}}; + } + +L4::ModList::copy_file_uncompressed_or_die($_, $module_path, $targetdir) + foreach keys %files; + +print QEMU " *) echo \"Give entry:\"\n"; +print QEMU map { " echo \" $_\"\n" } @ARGV; +print QEMU " exit 1;;\n"; +print QEMU "esac\n"; + +close GRUB1; +close GRUB2; +close QEMU; + +chmod 0755, "$targetdir/qemu.sh"; diff --git a/l4/tool/bin/gengrub1iso b/l4/tool/bin/gengrub1iso new file mode 100755 index 00000000..cc48b9ba --- /dev/null +++ b/l4/tool/bin/gengrub1iso @@ -0,0 +1,57 @@ +#! /usr/bin/perl -w +# +# (c) 2009 Technische Universität Dresden +# This file is part of TUD:OS and distributed under the terms of the +# GNU General Public License 2. +# Please see the COPYING-GPL-2 file for details. +# +# Adam Lackorzynski +# + +use strict; + +BEGIN { unshift @INC, $ENV{L4DIR}.'/tool/lib' + if $ENV{L4DIR} && -d $ENV{L4DIR}.'/tool/lib/L4';} + +use L4::ModList; +use L4::Grub; +use File::Temp qw/tempdir/; + +my $module_path = $ENV{SEARCHPATH} || "."; +my %opts = L4::Grub::parse_gengrub_args(); +my $modulesfile = shift; +my $isofilename = shift; + +unless (defined $isofilename) { + print "usage: $0 MODULESFILE ISOFILENAME entry1 [entry2] ...\n"; + exit(1); +} + +my $tmpdir = tempdir(CLEANUP => 1); + +system("mkdir -p \"$tmpdir\""); + +L4::Grub::prepare_grub1_dir($tmpdir); + +open(A, ">$tmpdir/boot/grub/menu.lst") + || die "Cannot create '$tmpdir/boot/grub/menu.lst': $!!"; + +delete $opts{timeout} + if @ARGV > 1 and defined $opts{timeout} and $opts{timeout} == 0; + +print A L4::Grub::grub1_config_prolog(%opts); + +my %files; + +foreach my $entryname (@ARGV) + { + print "Processing entry '$entryname'\n"; + my %entry = L4::ModList::get_module_entry($modulesfile, $entryname); + print A L4::ModList::generate_grub1_entry($entryname, '', %entry); + $files{$_} = 1 foreach map { L4::ModList::search_file_or_die($_, $module_path) } @{$entry{files}}; + } +close A; + +#system("cat $tmpdir/boot/grub/menu.lst"); +system("cp -v ".join(' ', keys %files)." $tmpdir"); +L4::Grub::grub1_mkisofs($isofilename, $tmpdir); diff --git a/l4/tool/bin/gengrub2iso b/l4/tool/bin/gengrub2iso new file mode 100755 index 00000000..8894ce4a --- /dev/null +++ b/l4/tool/bin/gengrub2iso @@ -0,0 +1,54 @@ +#! /usr/bin/perl -W +# +# (c) 2009 Technische Universität Dresden +# This file is part of TUD:OS and distributed under the terms of the +# GNU General Public License 2. +# Please see the COPYING-GPL-2 file for details. +# +# Adam Lackorzynski +# + +use strict; + +BEGIN { unshift @INC, $ENV{L4DIR}.'/tool/lib' + if $ENV{L4DIR} && -d $ENV{L4DIR}.'/tool/lib/L4';} + +use L4::ModList; +use L4::Grub; +use File::Temp qw/tempdir/; + +my $module_path = $ENV{SEARCHPATH} || "."; +my %opts = L4::Grub::parse_gengrub_args(); +my $modulesfile = shift; +my $isofilename = shift; + +unless (defined $isofilename) { + print "usage: $0 MODULESFILE ISOFILENAME entry1 [entry2] ...\n"; + exit(1); +} + +my $tmpdir = tempdir(CLEANUP => 1); + +L4::Grub::prepare_grub2_dir($tmpdir); +open(A, ">$tmpdir/boot/grub/grub.cfg") + || die "Cannot create '$tmpdir/boot/grub/grub.cfg': $!!"; + +delete $opts{timeout} + if @ARGV > 1 and defined $opts{timeout} and $opts{timeout} == 0; + +print A L4::Grub::grub2_config_prolog(%opts); + +my %files; + +foreach my $entryname (@ARGV) + { + print "Processing entry '$entryname'\n"; + my %entry = L4::ModList::get_module_entry($modulesfile, $entryname); + print A L4::ModList::generate_grub2_entry($entryname, '', %entry); + $files{$_} = 1 foreach map { L4::ModList::search_file_or_die($_, $module_path) } @{$entry{files}}; + } +close A; + +#system("cat $tmpdir/boot/grub/grub.cfg"); +print "Using the following files:\n", join("\n", keys %files), "\n"; +L4::Grub::grub2_mkisofs($isofilename, $tmpdir, keys %files); diff --git a/l4/tool/bin/isocreator b/l4/tool/bin/isocreator new file mode 100755 index 00000000..edc53c5b --- /dev/null +++ b/l4/tool/bin/isocreator @@ -0,0 +1,76 @@ +#! /bin/sh +# +# ISO Creator with GRUB +# +# Adam Lackorzynski +# + +set -e + +if [ "$(id -u)" = 0 ]; then + echo "Do not run me as root, it's not necessary" + exit 1 +fi + +if [ -z "$2" ]; then + echo "Usage: $0 systemdir iso-image-file [ mkisofs-options ]" + exit 1 +fi + +systemdir=$1 +isoimage=$2 +shift; shift + +[ "${isoimage#/}" = "$isoimage" ] && isoimage=$(pwd)/$isoimage + +mkdir -p "$systemdir" + +if [ ! -e "$systemdir/boot/grub/stage2_eltorito" ]; then + if [ -e /usr/lib/grub/i386-pc/stage2_eltorito ]; then + COPYPATH=/usr/lib/grub/i386-pc + elif [ -e /usr/share/grub/i386-pc/stage2_eltorito ]; then + COPYPATH=/usr/share/grub/i386-pc + elif [ -e /boot/grub/stage2_eltorito ]; then + COPYPATH=/boot/grub + elif [ -e /usr/local/lib/grub/i386-pc/stage2_eltorito ]; then + COPYPATH=/usr/local/lib/grub/i386-pc + fi + if [ -z "$COPYPATH" ]; then + echo "Cannot find a stage2_eltorito file..." + exit 1 + fi + + # copy files + mkdir -p "$systemdir/boot/grub" + cp $COPYPATH/stage2_eltorito "$systemdir/boot/grub" + chmod 644 "$systemdir/boot/grub/stage2_eltorito" +fi + +if ! grep -q modaddr $systemdir/boot/grub/stage2_eltorito; then + echo + echo "WARNING: The GRUB version you're using does not seem to support" + echo " the 'modaddr' command. You may want to fix this." + echo +fi + +if [ ! -e "$systemdir/boot/grub/menu.lst" ]; then + cat -< "$systemdir/boot/grub/menu.lst" +color 23 52 + +title Example entry +kernel /bootstrap -serial +modaddr 0x2000000 +module /fiasco -serial_esc -comspeed 115200 -comport 1 -nokdb +module /sigma0 +module /moe rom/hello +module /l4re +module /hello +EOF +fi + +cd "$systemdir" +mkisofs "$@" -R -b boot/grub/stage2_eltorito \ + -no-emul-boot -boot-load-size 4 -boot-info-table \ + -hide-rr-moved \ + -J -joliet-long \ + -o "$isoimage" . diff --git a/l4/tool/bin/mkspafs b/l4/tool/bin/mkspafs new file mode 100755 index 00000000..0f26eb89 --- /dev/null +++ b/l4/tool/bin/mkspafs @@ -0,0 +1,169 @@ +#! /usr/bin/perl -W + +# This program generates an image from a list of files, where every +# file is aligned to PAGE_SIZE boundaries. +# The image starts with an offset table followed by a list of the filenames. +# +# The offset table contain one entry for every file has the following format: +# [4 bytes] offset of the file in the image (should be aligned to PAGE_SIZE!) +# [4 bytes] size of the file +# [4 bytes] offset of the filename in the image +# A file offset with the value zero indicates the end of the offset table. +# + +use strict; + +my $OUT_FILE = shift; +my $PAGE_SIZE = 4096; +my $BLOCK_SIZE = 4096; + +my @file_name; +my @file_name_ptr; +my @file_offset; +my @file_size; + +my $count_files = 0; + +my $zero_buffer = "\0" x $BLOCK_SIZE; + +my $off_archive = 0; +my $off_binary = 0; + +my $count_padding = 0; # just for statistics + +sub write_file($$$$) +{ + my $file = shift; + my $off = shift; + my $buffer = shift; + my $buffer_size = shift; + + syswrite($file, $buffer, $buffer_size); + $off = $off + $buffer_size; + + return $off; +} + +die "no output file specified, usage: $0 OUT_FILE \n" + unless defined $OUT_FILE; + +print "Generating archive: $OUT_FILE\n"; + +sub read_dir($$) +{ + my $dir = shift; + my $file_list = shift; + my $count_files = 0; + my $fh; + + opendir($fh, $dir) || die("Cannot open directory"); + + # skip over current and parent directory + foreach my $i (readdir($fh)) + { + next if $i eq '.' or $i eq '..' or $i eq '.svn'; + + if (-d "$dir/$i") + { + print "found dir: $dir/$i\n"; + $count_files += &read_dir("$dir/$i", $file_list); + } + else + { + print "found file: $dir/$i\n"; + push @{$file_list}, "$dir/$i"; + $count_files++; + } + } + + closedir $fh; + + return $count_files; +} + +# scrap up all files in directories +foreach my $i (@ARGV) +{ + if (-d $i) + { + printf("found dir: %s\n", $i); + $count_files += read_dir($i, \@file_name); + } + else + { + printf("found file:%s\n", $i); + push(@file_name, $i); + $count_files++; + } +} + +my $archive; +open($archive, "+>", $OUT_FILE) or die $!; +binmode($archive); + +# reserve space for the offset table +$off_archive = write_file($archive, $off_archive, "\0" x ($count_files * 12 + 4), ($count_files * 12 + 4)); + +# write filenames into the archive +my $i; +for ($i = 0; $i < $count_files; ++$i) +{ + $file_name_ptr[$i] = $off_archive; + +# write filename and add string termination + $off_archive = write_file($archive, $off_archive, $file_name[$i], length($file_name[$i])); + $off_archive = write_file($archive, $off_archive, "\0", 1); +} + +# add padding to PAGE_SIZE granularity +if ($off_archive % $PAGE_SIZE) +{ + $count_padding += $PAGE_SIZE - ($off_archive % $PAGE_SIZE); + $off_archive = write_file($archive, $off_archive, $zero_buffer, $PAGE_SIZE - ($off_archive % $PAGE_SIZE)); +} + +# write files into the archive +for ($i = 0; $i < $count_files; ++$i) +{ + open(BINARY, '<', $file_name[$i]) or die $!; + binmode(BINARY); + $file_offset[$i] = $off_archive; + $file_size[$i] = -s $file_name[$i]; + + my $read_bytes; + do + { + my $buffer; + $read_bytes = sysread(BINARY, $buffer, $BLOCK_SIZE); + $off_binary += $read_bytes; + + $off_archive = write_file($archive, $off_archive, $buffer, $read_bytes); + } + while ($read_bytes == $BLOCK_SIZE); + + close(BINARY); + +# add padding to PAGE_SIZE granularity + if ($off_archive % $PAGE_SIZE) + { + $count_padding += $PAGE_SIZE - ($off_archive % $PAGE_SIZE); + $off_archive = write_file($archive, $off_archive, $zero_buffer, $PAGE_SIZE - ($off_archive % $PAGE_SIZE)); + } +} + +seek($archive, 0, 0); +$off_archive = 0; + +# write offset table into the archive +for ($i = 0; $i < $count_files; ++$i) +{ +# printf("offset:%x\n", $file_offset[$i]); + + #printf("file offset:%x size:%x\n", $file_offset[$i], $file_size[$i]); + my $val = pack("lll", $file_offset[$i], $file_size[$i], $file_name_ptr[$i]); + $off_archive = write_file($archive, $off_archive, $val, 12); +} + +close($archive); +printf "Done, generating archive. Blowup factor is %3.2f\n", + ((-s $OUT_FILE)/((-s $OUT_FILE)-$count_padding)-1)*100; diff --git a/l4/tool/bin/qemu-x86-launch b/l4/tool/bin/qemu-x86-launch new file mode 100755 index 00000000..56cc2437 --- /dev/null +++ b/l4/tool/bin/qemu-x86-launch @@ -0,0 +1,68 @@ +#! /usr/bin/perl -W +# +# (c) 2009 Technische Universität Dresden +# This file is part of TUD:OS and distributed under the terms of the +# GNU General Public License 2. +# Please see the COPYING-GPL-2 file for details. +# +# Adam Lackorzynski +# + +use strict; + +BEGIN { unshift @INC, $ENV{L4DIR}.'/tool/lib' + if $ENV{L4DIR} && -d $ENV{L4DIR}.'/tool/lib/L4';} + +use L4::ModList; +use File::Temp qw/tempdir/; + +my $qemu = $ENV{QEMU} || 'qemu'; +my $kernelname = $ENV{KERNEL} || 'bootstrap'; +my $module_path = $ENV{SEARCHPATH} || "."; +my $qemu_options = $ENV{QEMU_OPTIONS} || ""; +my $modulesfile = shift; +my $entryname = shift; +my $unzip_tmp = tempdir(CLEANUP => 1); + +sub qemu_get_file($$) +{ + my $command = shift; + my $cmdline = shift; + + my $fp = L4::ModList::get_file_uncompressed_or_die($command, $module_path, + $unzip_tmp); + + $cmdline =~ s/^\S+\s*//; + $cmdline =~ s/,/,,/g; + $fp.' '.$cmdline; +} + + +die "No entry name given" unless defined $entryname; + +my %entry = L4::ModList::get_module_entry($modulesfile, $entryname); + +my @mods = @{$entry{mods}}; +my $kernel = L4::ModList::search_file_or_die($entry{bootstrap}{command}, $module_path); +my $initrd = join(',', map { qemu_get_file($_->{command}, $_->{cmdline}) } @mods); + +my $qemu_cmd = + "$qemu -kernel $kernel -append \"$entry{bootstrap}{cmdline}\" ". + "-initrd \"$initrd\" $qemu_options"; + +print "Note: At least QEmu 0.13 is required for the loading to work.\n"; +# and since nobody is reading this message or knows what the version of the +# installed qemu is... +my $o = `$qemu -version 2>&1`; +if ($?) + { + print "Failed to launch QEmu ($qemu)\n"; + exit $?; + } +if ($o !~ /\s(\d+)\.(\d+)/ || ($1 == 0 && $2 < 13)) + { + print "\nYour installed Qemu is too old, please upgrade to at least version 0.13.\n\n"; + exit 1; + } +print "$qemu_cmd\n"; +system("$qemu_cmd"); diff --git a/l4/tool/bin/ux-launch b/l4/tool/bin/ux-launch new file mode 100755 index 00000000..8be11c48 --- /dev/null +++ b/l4/tool/bin/ux-launch @@ -0,0 +1,77 @@ +#! /usr/bin/perl -W +# +# (c) 2009 Technische Universität Dresden +# This file is part of TUD:OS and distributed under the terms of the +# GNU General Public License 2. +# Please see the COPYING-GPL-2 file for details. +# +# Adam Lackorzynski +# + +use strict; + +BEGIN { unshift @INC, $ENV{L4DIR}.'/tool/lib' + if $ENV{L4DIR} && -d $ENV{L4DIR}.'/tool/lib/L4';} + +use L4::ModList; +use File::Temp qw/tempdir/; + +my $module_path = $ENV{SEARCHPATH} || "."; +my $modulesfile = shift; +my $entryname = shift; + +sub get_file($$) +{ + my $command = shift; + my $cmdline = shift; + + my $fp = L4::ModList::search_file_or_die($command, $module_path); + + $cmdline =~ s/^\S+\s*/ /; + $cmdline =~ s/\s*$//; + $fp.$cmdline; +} + + +die "No entry name given" unless defined $entryname; + +my %entry = L4::ModList::get_module_entry($modulesfile, $entryname); + +my @mods = @{$entry{mods}}; + +my $fiasco_ux = L4::ModList::search_file_or_die('fiasco', $module_path); +my $irq0 = L4::ModList::search_file_or_die('irq0', $module_path); + +my $fbprog; +if (defined $ENV{UX_GFX}) + { + $fbprog = defined $ENV{UX_GFX_CMD} ? $ENV{UX_GFX_CMD} : 'ux_con'; + $fbprog = L4::ModList::search_file($fbprog, $module_path); + } + +my $netprog; +if (defined $ENV{UX_NET}) + { + $netprog = defined $ENV{UX_NET_CMD} ? $ENV{UX_NET_CMD} : 'ux_net'; + $netprog = L4::ModList::search_file($netprog, $module_path); + } + +@mods = map { get_file($_->{command}, $_->{cmdline}) } @mods; + +# skip fiasco binary together with its params, for UX launch there are just +# ignored +shift @mods; + +my $ux_cmd = $fiasco_ux." "; +$ux_cmd .= join(' ', @ARGV); +$ux_cmd .= " -I $irq0"; +$ux_cmd .= " -G $ENV{UX_GFX} -F $fbprog" if defined $fbprog; +$ux_cmd .= " -N -E $netprog" if defined $netprog; +$ux_cmd .= " -S '".shift(@mods)."'"; +$ux_cmd .= " -R '".shift(@mods)."'"; +$ux_cmd .= ' '.join(' ', map { "-l $_" } @mods); + +$ux_cmd = "$ENV{UX_GDB_CMD} --args $ux_cmd" if defined $ENV{UX_GDB_CMD}; + +print "$ux_cmd\n"; +system("$ux_cmd"); diff --git a/l4/tool/elf-patcher/Makefile b/l4/tool/elf-patcher/Makefile new file mode 100644 index 00000000..c344a5e8 --- /dev/null +++ b/l4/tool/elf-patcher/Makefile @@ -0,0 +1,27 @@ +L4DIR ?= ../.. +include $(L4DIR)/mk/Makeconf + +ifeq ($(HOST_SYSTEM),darwin) + HOST_CPPFLAGS += -I/usr/include/machine +endif + +CFLAGS = -O3 $(HOST_CPPFLAGS) +TARGET = elf-patcher + +CXX = $(HOST_CXX) + +all:: $(OBJ_DIR)/$(TARGET) + +$(OBJ_DIR)/%: $(SRC_DIR)/%.cc $(SRC_DIR)/Makefile $(SRC_DIR)/%.h + @$(COMP_MESSAGE) + $(VERBOSE)$(CXX) $(CFLAGS) -Wall -W -Wextra $< -o $@ + +clean cleanall:: + @$(CLEAN_MESSAGE) + $(VERBOSE)rm -f $(OBJ_DIR)/.*.d $(OBJ_DIR)/*.o + $(VERBOSE)rm -f $(OBJ_DIR)/$(TARGET) + +cleanall:: + @$(CLEANALL_MESSAGE) + $(VERBOSE)rm -f $(TARGET) + diff --git a/l4/tool/elf-patcher/elf-patcher.cc b/l4/tool/elf-patcher/elf-patcher.cc new file mode 100644 index 00000000..067d4fc1 --- /dev/null +++ b/l4/tool/elf-patcher/elf-patcher.cc @@ -0,0 +1,166 @@ +#define _BSD_SOURCE + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifndef __FreeBSD__ +#include +#endif + +template< typename T > +T host_to(int be, long long v, T &t) +{ +#if __BYTE_ORDER == __LITTLE_ENDIAN + bool rot = be; +#else + bool rot = !be; +#endif + if (rot) + { + T _v = v; + for (unsigned i = 0; i < sizeof(T); ++i) + ((unsigned char*)&t)[i] = ((unsigned char *)&_v)[sizeof(T)-i-1]; + } + else + t = v; + + return t; +} + +#define Elf(x) Elf32_ ## x +#include "elf-patcher.h" + +#undef Elf +#define Elf(x) Elf64_ ## x +#include "elf-patcher.h" + +static unsigned long long +get_param(const char *opt, int argc, const char *argv[]) +{ + size_t l = strlen(opt); + int i; + for (i = 2; i < argc; ++i) + { + if (strncmp(opt, argv[i], l) == 0) + { + if (strlen(argv[i]) >= l + 2) + return strtoll(argv[i] + l + 1, NULL, 0); + else + { + fprintf(stderr, "error parsing argument '%s'\n", opt); + return ~0ULL; + } + } + } + return ~0ULL; +} + +static int +check_elf(void *_elf, const char *name) +{ + Elf32_Ehdr *elf = (Elf32_Ehdr*)_elf; + if (memcmp(elf->e_ident, ELFMAG, sizeof(ELFMAG)-1) != 0) + { + fprintf(stderr, "'%s' is not an ELF binary\n", name); + return 1; + } + return 0; +} + +static int +patch_phdrs(void *_elf, int argc, const char *argv[]) +{ + Elf32_Ehdr *elf = (Elf32_Ehdr*)_elf; + unsigned long long stack_addr, stack_size, kip_addr; + + stack_addr = get_param("--stack_addr", argc, argv); + stack_size = get_param("--stack_size", argc, argv); + kip_addr = get_param("--kip_addr" , argc, argv); + + if (stack_addr == ~0ULL || stack_size == ~0ULL || kip_addr == ~0ULL) + return 1; + + if (elf->e_ident[EI_CLASS] == ELFCLASS64) + return Elf64_patch_phdrs(elf, stack_addr, stack_size, kip_addr); + else if (elf->e_ident[EI_CLASS] == ELFCLASS32) + return Elf32_patch_phdrs(elf, stack_addr, stack_size, kip_addr); + else + { + fprintf(stderr, "invalid elf class\n"); + return 1; + } +} + +static int +patch_shdrs(void *_elf, int argc, const char *argv[]) +{ + Elf32_Ehdr *elf = (Elf32_Ehdr*)_elf; + unsigned long long min_align = get_param("--min-section-align", argc, argv); + + if (min_align == ~0ULL) + return 1; + + if (elf->e_ident[EI_CLASS] == ELFCLASS64) + return Elf64_patch_shdrs(elf, min_align); + else if (elf->e_ident[EI_CLASS] == ELFCLASS32) + return Elf32_patch_shdrs(elf, min_align); + else + { + fprintf(stderr, "invalid elf class\n"); + return 1; + } +} + +int main(int argc, const char *argv[]) +{ + int victim; + struct stat victim_sb; + void *elf_addr; + + if (argc < 2) + { + fprintf(stderr,"usage: %s [--stack_addr= --stack_size= --kip_addr=] [--min-section-align=value]\n", argv[0]); + return 1; + } + + victim = open(argv[1], O_RDWR); + if (victim < 0) + { + fprintf(stderr, "could not open '%s':", argv[1]); + perror(""); + return 1; + } + + if (fstat(victim, &victim_sb) == -1) + { + fprintf(stderr, "could not get size of '%s':", argv[1]); + perror(""); + return 1; + } + + elf_addr = mmap(NULL, victim_sb.st_size, PROT_READ | PROT_WRITE, + MAP_SHARED, victim, 0); + + if (elf_addr == MAP_FAILED) + { + fprintf(stderr, "could not mmap '%s':", argv[1]); + perror(""); + return 1; + } + + if (check_elf(elf_addr, argv[1])) + return 1; + + patch_phdrs(elf_addr, argc, argv); + patch_shdrs(elf_addr, argc, argv); + + close(victim); + return 0; +} diff --git a/l4/tool/elf-patcher/elf-patcher.h b/l4/tool/elf-patcher/elf-patcher.h new file mode 100644 index 00000000..7213debf --- /dev/null +++ b/l4/tool/elf-patcher/elf-patcher.h @@ -0,0 +1,60 @@ + + +static int +Elf(patch_phdrs)(void *_elf, + unsigned long long stack_addr, + unsigned long long stack_size, + unsigned long long kip_addr) +{ + Elf(Ehdr) *elf = (Elf(Ehdr)*)_elf; + Elf(Phdr) *phdr = (Elf(Phdr)*)((char*)elf + elf->e_phoff); + int phnum = elf->e_phnum; + int phsz = elf->e_phentsize; + unsigned long long kip_size = 0x1000; + int be = elf->e_ident[EI_DATA] == ELFDATA2MSB; + + for (;phnum > 0; --phnum, phdr = (Elf(Phdr)*)((char*)phdr + phsz)) + { + switch (phdr->p_type) + { + case PT_LOOS + 0x12: + // printf("found stack phdr...\n"); + // printf("set addr=%llx size=%llx\n", stack_addr, stack_size); + host_to(be, stack_addr, phdr->p_vaddr); + host_to(be, stack_addr, phdr->p_paddr); + host_to(be, stack_size, phdr->p_memsz); + break; + case PT_LOOS + 0x13: + // printf("found kip phdr...\n"); + // printf("set addr=%llx size=%llx\n", kip_addr, kip_size); + host_to(be, kip_addr, phdr->p_vaddr); + host_to(be, kip_addr, phdr->p_paddr); + host_to(be, kip_size, phdr->p_memsz); + break; + default: + break; + } + } + return 0; +} + +static int +Elf(patch_shdrs)(void *_elf, unsigned long long min_align) +{ + Elf(Ehdr) *elf = (Elf(Ehdr)*)_elf; + int be = elf->e_ident[EI_DATA] == ELFDATA2MSB; + Elf32_Off shoff = host_to(be, elf->e_shoff, shoff); + Elf32_Half shnum = host_to(be, elf->e_shnum, shnum); + Elf32_Half shsz = host_to(be, elf->e_shentsize, shsz); + + Elf(Shdr) *shdr = (Elf(Shdr)*)((char*)elf + shoff); + for (;shnum > 0; --shnum, shdr = (Elf(Shdr)*)((char*)shdr + shsz)) + { + if (shdr->sh_type == SHT_PROGBITS) + { + if (shdr->sh_addralign < min_align) + host_to(be, min_align, shdr->sh_addralign); + } + } + return 0; +} diff --git a/l4/tool/gendep/COPYING b/l4/tool/gendep/COPYING new file mode 100644 index 00000000..283b578e --- /dev/null +++ b/l4/tool/gendep/COPYING @@ -0,0 +1,50 @@ +This code is public domain. Copy it, use it, distribute it. Under no +circumstences the authors can be made responsible for any kind of damage, +loss or anger or irritation resulting from the use, distribution or +existance of this code. + + +Mail of Han-Wen Nienhuys , the original author of +libgendep: + ++++ BEGIN OF MAIL +Received: from sunset.cs.uu.nl + ([131.211.80.32] helo=mail.cs.uu.nl ident=vmailer) + by os.inf.tu-dresden.de with esmtp (Exim 3.36) + id 17EtJp-000KNm-00 + for jork@os.inf.tu-dresden.de; Mon, 03 Jun 2002 17:00:25 +0200 +Received: from meddo.cs.uu.nl.cs.uu.nl (meddo.cs.uu.nl [131.211.80.91]) + by mail.cs.uu.nl (Postfix) with ESMTP id 845284532 + for ; Mon, 3 Jun 2002 17:00:14 +0200 +(MET DS +From: Han-Wen Nienhuys +MIME-Version: 1.0 +Content-Type: text/plain; charset=us-ascii +Content-Transfer-Encoding: 7bit +Message-ID: <15611.33918.276801.358713@meddo.cs.uu.nl> +Date: Mon, 3 Jun 2002 17:00:14 +0200 +To: Jork Loeser +Subject: libgendep copyright status +In-Reply-To: + +References: +X-Mailer: VM 7.03 under Emacs 21.2.1 + +jork@os.inf.tu-dresden.de writes: +> Han-Wen, +> +> I slightly modified your gendep library and would like to use this in our +> drops project . Can you +> tell me about the copyright status of this code? Thank you. + +It's PD. It's so small, hardly worth the trouble of GPL'ing, but some +credit somewhere would be nice, of course :) + +BTW, what license does DROPS use? + +-- + +Han-Wen Nienhuys | hanwen@cs.uu.nl | http://www.cs.uu.nl/~hanwen/ + + ++++ END OF MAIL diff --git a/l4/tool/gendep/Doxyfile b/l4/tool/gendep/Doxyfile new file mode 100644 index 00000000..9d4957e5 --- /dev/null +++ b/l4/tool/gendep/Doxyfile @@ -0,0 +1,1630 @@ +# Doxyfile 1.7.1 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project +# +# All text after a hash (#) is considered a comment and will be ignored +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" ") + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all +# text before the first occurrence of this tag. Doxygen uses libiconv (or the +# iconv built into libc) for the transcoding. See +# http://www.gnu.org/software/libiconv for the list of possible encodings. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded +# by quotes) that should identify the project. + +PROJECT_NAME = "libgendep" + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = "Version 0.2" + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create +# 4096 sub-directories (in 2 levels) under the output directory of each output +# format and will distribute the generated files over these directories. +# Enabling this option can be useful when feeding doxygen a huge amount of +# source files, where putting all generated files in the same directory would +# otherwise cause performance problems for the file system. + +CREATE_SUBDIRS = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, +# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, +# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English +# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, +# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak, +# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is +# used as the annotated text. Otherwise, the brief description is used as-is. +# If left blank, the following values are used ("$name" is automatically +# replaced with the name of the entity): "The $name class" "The $name widget" +# "The $name file" "is" "provides" "specifies" "contains" +# "represents" "a" "an" "the" + +ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = NO + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of +# the path mentioned in the documentation of a class, which tells +# the reader which header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that +# are normally passed to the compiler using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful is your file systems +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like regular Qt-style comments +# (thus requiring an explicit @brief command for a brief description.) + +JAVADOC_AUTOBRIEF = NO + +# If the QT_AUTOBRIEF tag is set to YES then Doxygen will +# interpret the first line (until the first dot) of a Qt-style +# comment as the brief description. If set to NO, the comments +# will behave just like regular Qt-style comments (thus requiring +# an explicit \brief command for a brief description.) + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce +# a new page for each member. If set to NO, the documentation of a member will +# be part of the file/class/namespace that contains it. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 8 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C +# sources only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java +# sources only. Doxygen will then generate output that is more tailored for +# Java. For instance, namespaces will be presented as packages, qualified +# scopes will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources only. Doxygen will then generate output that is more tailored for +# Fortran. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for +# VHDL. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given extension. +# Doxygen has a built-in mapping, but you can override or extend it using this +# tag. The format is ext=language, where ext is a file extension, and language +# is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C, +# C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make +# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C +# (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions +# you also need to set FILE_PATTERNS otherwise the files are not read by doxygen. + +EXTENSION_MAPPING = + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should +# set this tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. +# func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. +# Doxygen will parse them like normal C++ but will assume all classes use public +# instead of private inheritance when no explicit protection keyword is present. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate getter +# and setter methods for a property. Setting this option to YES (the default) +# will make doxygen to replace the get and set methods by a property in the +# documentation. This will only work if the methods are indeed getting or +# setting a simple type. If this is not the case, or you want to show the +# methods anyway, you should set this option to NO. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + +SUBGROUPING = YES + +# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum +# is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically +# be useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. + +TYPEDEF_HIDES_STRUCT = NO + +# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to +# determine which symbols to keep in memory and which to flush to disk. +# When the cache is full, less often used symbols will be written to disk. +# For small to medium size projects (<1000 input files) the default value is +# probably good enough. For larger projects a too small cache size can cause +# doxygen to be busy swapping symbols to and from disk most of the time +# causing a significant performance penality. +# If the system has enough physical memory increasing the cache will improve the +# performance by keeping more symbols in memory. Note that the value works on +# a logarithmic scale so increasing the size by one will rougly double the +# memory usage. The cache size is given by this formula: +# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, +# corresponding to a cache size of 2^16 = 65536 symbols + +SYMBOL_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = NO + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = NO + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. +# If set to NO (the default) only methods in the interface are included. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base +# name of the file that contains the anonymous namespace. By default +# anonymous namespace are hidden. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = YES + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen +# will list include files with double quotes in the documentation +# rather than with sharp brackets. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen +# will sort the (brief and detailed) documentation of class members so that +# constructors and destructors are listed first. If set to NO (the default) +# the constructors will appear in the respective orders defined by +# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. +# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO +# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the +# hierarchy of group names into alphabetical order. If set to NO (the default) +# the group names will appear in their defined order. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the +# alphabetical list. + +SORT_BY_SCOPE_NAME = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or define consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and defines in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = YES + +# If the sources in your project are distributed over multiple directories +# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy +# in the documentation. The default is NO. + +SHOW_DIRECTORIES = NO + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. +# This will remove the Files entry from the Quick Index and from the +# Folder Tree View (if specified). The default is YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the +# Namespaces page. +# This will remove the Namespaces entry from the Quick Index +# and from the Folder Tree View (if specified). The default is YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command , where is the value of +# the FILE_VERSION_FILTER tag, and is the name of an input file +# provided by doxygen. Whatever the program writes to standard output +# is used as the file version. See the manual for examples. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. The create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. +# You can optionally specify a file name after the option, if omitted +# DoxygenLayout.xml will be used as the name of the layout file. + +LAYOUT_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = YES + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = YES + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be abled to get warnings for +# functions that are documented, but have no documentation for their parameters +# or return value. If set to NO (the default) doxygen will only warn about +# wrong or incomplete parameter documentation, but not about the absence of +# documentation. + +WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. Optionally the format may contain +# $version, which will be replaced by the version of the file (if it could +# be obtained via FILE_VERSION_FILTER) + +WARN_FORMAT = + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = manpage.dox + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is +# also the default input encoding. Doxygen uses libiconv (or the iconv built +# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for +# the list of possible encodings. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx +# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90 + +FILE_PATTERNS = + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = NO + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used select whether or not files or +# directories that are symbolic links (a Unix filesystem feature) are excluded +# from the input. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. Note that the wildcards are matched +# against the file with absolute path, so to exclude all test directories +# for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. +# If FILTER_PATTERNS is specified, this tag will be +# ignored. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. +# Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. +# The filters are a list of the form: +# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further +# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER +# is applied to all files. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + +FILTER_SOURCE_FILES = NO + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. + +SOURCE_BROWSER = NO + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = NO + +# If the REFERENCES_RELATION tag is set to YES +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = NO + +# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) +# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from +# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will +# link to the source code. +# Otherwise they will link to the documentation. + +REFERENCES_LINK_SOURCE = YES + +# If the USE_HTAGS tag is set to YES then the references to source code +# will point to the HTML generated by the htags(1) tool instead of doxygen +# built-in source browser. The htags tool is part of GNU's global source +# tagging system (see http://www.gnu.org/software/global/global.html). You +# will need version 4.8.6 or higher. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = NO + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own +# stylesheet in the HTML output directory as well, or it will be erased! + +HTML_STYLESHEET = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. +# Doxygen will adjust the colors in the stylesheet and background images +# according to this color. Hue is specified as an angle on a colorwheel, +# see http://en.wikipedia.org/wiki/Hue for more information. +# For instance the value 0 represents red, 60 is yellow, 120 is green, +# 180 is cyan, 240 is blue, 300 purple, and 360 is red again. +# The allowed range is 0 to 359. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of +# the colors in the HTML output. For a value of 0 the output will use +# grayscales only. A value of 255 will produce the most vivid colors. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to +# the luminance component of the colors in the HTML output. Values below +# 100 gradually make the output lighter, whereas values above 100 make +# the output darker. The value divided by 100 is the actual gamma applied, +# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, +# and 100 does not change the gamma. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting +# this to NO can help when comparing the output of multiple runs. + +HTML_TIMESTAMP = YES + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. + +HTML_ALIGN_MEMBERS = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. For this to work a browser that supports +# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox +# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). + +HTML_DYNAMIC_SECTIONS = NO + +# If the GENERATE_DOCSET tag is set to YES, additional index files +# will be generated that can be used as input for Apple's Xcode 3 +# integrated development environment, introduced with OSX 10.5 (Leopard). +# To create a documentation set, doxygen will generate a Makefile in the +# HTML output directory. Running make will produce the docset in that +# directory and running "make install" will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find +# it at startup. +# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html +# for more information. + +GENERATE_DOCSET = NO + +# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the +# feed. A documentation feed provides an umbrella under which multiple +# documentation sets from a single provider (such as a company or product suite) +# can be grouped. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that +# should uniquely identify the documentation set bundle. This should be a +# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen +# will append .docset to the name. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING +# is used to encode HtmlHelp index (hhk), content (hhc) and project file +# content. + +CHM_INDEX_ENCODING = + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated +# that can be used as input for Qt's qhelpgenerator to generate a +# Qt Compressed Help (.qch) of the generated HTML documentation. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can +# be used to specify the file name of the resulting .qch file. +# The path specified is relative to the HTML output folder. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#namespace + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#virtual-folders + +QHP_VIRTUAL_FOLDER = doc + +# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to +# add. For more information please see +# http://doc.trolltech.com/qthelpproject.html#custom-filters + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see +# +# Qt Help Project / Custom Filters. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's +# filter section matches. +# +# Qt Help Project / Filter Attributes. + +QHP_SECT_FILTER_ATTRS = + +# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can +# be used to specify the location of Qt's qhelpgenerator. +# If non-empty doxygen will try to run qhelpgenerator on the generated +# .qhp file. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files +# will be generated, which together with the HTML files, form an Eclipse help +# plugin. To install this plugin and make it available under the help contents +# menu in Eclipse, the contents of the directory containing the HTML and XML +# files needs to be copied into the plugins directory of eclipse. The name of +# the directory within the plugins directory should be the same as +# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before +# the help appears. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have +# this name. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. + +DISABLE_INDEX = NO + +# This tag can be used to set the number of enum values (range [1..20]) +# that doxygen will group on one line in the generated HTML documentation. + +ENUM_VALUES_PER_LINE = 4 + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. +# If the tag value is set to YES, a side panel will be generated +# containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). +# Windows users are probably better off using the HTML help feature. + +GENERATE_TREEVIEW = NO + +# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, +# and Class Hierarchy pages using a tree view instead of an ordered list. + +USE_INLINE_TREES = NO + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open +# links to external symbols imported via tag files in a separate window. + +EXT_LINKS_IN_WINDOW = NO + +# Use this tag to change the font size of Latex formulas included +# as images in the HTML documentation. The default is 10. Note that +# when you change the font size after a successful doxygen run you need +# to manually remove any form_*.png images from the HTML output directory +# to force them to be regenerated. + +FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are +# not supported properly for IE 6.0, but are supported on all modern browsers. +# Note that when changing this option you need to delete any form_*.png files +# in the HTML output before the changes have effect. + +FORMULA_TRANSPARENT = YES + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box +# for the HTML output. The underlying search engine uses javascript +# and DHTML and should work on any modern browser. Note that when using +# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets +# (GENERATE_DOCSET) there is already a search function so this one should +# typically be disabled. For large projects the javascript based search engine +# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. + +SEARCHENGINE = NO + +# When the SERVER_BASED_SEARCH tag is enabled the search engine will be +# implemented using a PHP enabled web server instead of at the web client +# using Javascript. Doxygen will generate the search PHP script and index +# file to put on the web server. The advantage of the server +# based approach is that it scales better to large projects and allows +# full text search. The disadvances is that it is more difficult to setup +# and does not have live searching capabilities. + +SERVER_BASED_SEARCH = NO + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +GENERATE_LATEX = NO + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. +# Note that when enabling USE_PDFLATEX this option is only used for +# generating bitmaps for formulas in the HTML output, but not in the +# Makefile that is written to the output directory. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, a4wide, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = a4wide + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = NO + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = NO + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES = NO + +# If LATEX_SOURCE_CODE is set to YES then doxygen will include +# source code with syntax highlighting in the LaTeX output. +# Note that which sources are shown also depends on other settings +# such as SOURCE_BROWSER. + +LATEX_SOURCE_CODE = NO + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = YES + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .7 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. + +GENERATE_XML = NO + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + +XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. + +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. +# This is useful +# if you want to understand what is going on. +# On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = NO + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_DEFINED tags. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# in the INCLUDE_PATH (see below) will be search if a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator +# instead of the = operator. + +PREDEFINED = + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all function-like macros that are alone +# on a line, have an all uppercase name, and do not end with a semicolon. Such +# function macros are typically used for boiler-plate code, and will confuse +# the parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. +# Optionally an initial location of the external documentation +# can be added for each tagfile. The format of a tag file without +# this location is as follows: +# +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths or +# URLs. If a location is present for each tag, the installdox tool +# does not have to be run to correct the links. +# Note that each tag file must have a unique name +# (where the name does NOT include the path) +# If a tag file is not located in the directory in which doxygen +# is run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base +# or super classes. Setting the tag to NO turns the diagrams off. Note that +# this option is superseded by the HAVE_DOT option below. This is only a +# fallback. It is recommended to install and use dot, since it yields more +# powerful graphs. + +CLASS_DIAGRAMS = YES + +# You can define message sequence charts within doxygen comments using the \msc +# command. Doxygen will then run the mscgen tool (see +# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the +# documentation. The MSCGEN_PATH tag allows you to specify the directory where +# the mscgen tool resides. If left empty the tool is assumed to be found in the +# default search path. + +MSCGEN_PATH = + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = NO + +# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is +# allowed to run in parallel. When set to 0 (the default) doxygen will +# base this on the number of processors available in the system. You can set it +# explicitly to a value larger than 0 to get control over the balance +# between CPU load and processing speed. + +DOT_NUM_THREADS = 0 + +# By default doxygen will write a font called FreeSans.ttf to the output +# directory and reference it in all dot files that doxygen generates. This +# font does not include all possible unicode characters however, so when you need +# these (or just want a differently looking font) you can specify the font name +# using DOT_FONTNAME. You need need to make sure dot is able to find the font, +# which can be done by putting it in a standard location or by setting the +# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory +# containing the font. + +DOT_FONTNAME = FreeSans.ttf + +# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. +# The default size is 10pt. + +DOT_FONTSIZE = 10 + +# By default doxygen will tell dot to use the output directory to look for the +# FreeSans.ttf font (which doxygen will put there itself). If you specify a +# different font using DOT_FONTNAME you can set the path where dot +# can find it using this tag. + +DOT_FONTPATH = + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# the CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = YES + +# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for groups, showing the direct groups dependencies + +GROUP_GRAPHS = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. + +UML_LOOK = NO + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = NO + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH and HAVE_DOT options are set to YES then +# doxygen will generate a call dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable call graphs +# for selected functions only using the \callgraph command. + +CALL_GRAPH = NO + +# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then +# doxygen will generate a caller dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable caller +# graphs for selected functions only using the \callergraph command. + +CALLER_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES +# then doxygen will show the dependencies a directory has on other directories +# in a graphical way. The dependency relations are determined by the #include +# relations between the files in the directories. + +DIRECTORY_GRAPH = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are png, jpg, or gif +# If left blank png will be used. + +DOT_IMAGE_FORMAT = png + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found in the path. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = + +# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of +# nodes that will be shown in the graph. If the number of nodes in a graph +# becomes larger than this value, doxygen will truncate the graph, which is +# visualized by representing a node as a red box. Note that doxygen if the +# number of direct children of the root node in a graph is already larger than +# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note +# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. + +DOT_GRAPH_MAX_NODES = 50 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes +# that lay further from the root node will be omitted. Note that setting this +# option to 1 or 2 may greatly reduce the computation time needed for large +# code bases. Also note that the size of a graph can be further restricted by +# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. + +MAX_DOT_GRAPH_DEPTH = 0 + +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is disabled by default, because dot on Windows does not +# seem to support this out of the box. Warning: Depending on the platform used, +# enabling this option may lead to badly anti-aliased labels on the edges of +# a graph (i.e. they become hard to read). + +DOT_TRANSPARENT = NO + +# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) +# support this, this feature is disabled by default. + +DOT_MULTI_TARGETS = YES + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES diff --git a/l4/tool/gendep/MAINTAINER b/l4/tool/gendep/MAINTAINER new file mode 100644 index 00000000..293faf92 --- /dev/null +++ b/l4/tool/gendep/MAINTAINER @@ -0,0 +1 @@ +mailaddr adam@os.inf.tu-dresden.de diff --git a/l4/tool/gendep/Makefile b/l4/tool/gendep/Makefile new file mode 100644 index 00000000..ece12c3e --- /dev/null +++ b/l4/tool/gendep/Makefile @@ -0,0 +1,104 @@ +L4DIR ?= ../.. +include $(L4DIR)/mk/Makeconf + +VERSION = 0.2 +CSRC = deptrack.c syscall.c +MAN = man/man7/libgendep.so.7 +MAN_SRC = manpage.dox Doxyfile +DDIR = gendep-$(VERSION) + +CC = $(HOST_CC) +CFLAGS = -fPIC -Wall -pedantic -g + +checkbuild = $(shell if echo 'int main(){return 0;}' | \ + $(CC) -m$(1) $(CFLAGS) -o /dev/null \ + -x c - > /dev/null 2>&1; then echo 1; fi) + +OBJS32 = $(addprefix $(OBJ_DIR)/,$(CSRC:.c=.32.o)) +OBJS64 = $(addprefix $(OBJ_DIR)/,$(CSRC:.c=.64.o)) +LIB32 := $(if $(call checkbuild,32),$(OBJ_DIR)/32/libgendep.so) +LIB64 := $(if $(call checkbuild,64),$(OBJ_DIR)/64/libgendep.so) + + +ifneq ($(filter linux freebsd,$(HOST_SYSTEM)),) +LIB := $(LIB32) $(LIB64) +LIBDL-linux := -ldl +cmd_link = $(HOST_CC) -m$(2) -shared -Wl,--no-as-needed -Wl,-soname,$(1) $(LIBDL-$(HOST_SYSTEM)) -o $(1) +else +ifeq ($(HOST_SYSTEM),darwin) +LIB := $(OBJ_DIR)/libgendep.so +cmd_link = $(HOST_CC) -m$(2) -dynamiclib -o $(1) +$(LIB): $(LIB32) $(LIB64) + lipo -create $^ -output $@ +else +$(error Your host system type "$(HOST_SYSTEM)" is not supported here. Fix me.) +endif +endif + +ifeq ($(LIB),) +$(error Neither 32 nor 64 bit version are built?!) +endif + +all:: $(LIB) + +$(OBJ_DIR)/%.32.o: $(SRC_DIR)/%.c $(SRC_DIR)/Makefile + $(CC) $(CFLAGS) -m32 -c $< -o $@ + +$(OBJ_DIR)/%.64.o: $(SRC_DIR)/%.c $(SRC_DIR)/Makefile + $(CC) $(CFLAGS) -m64 -c $< -o $@ + +$(LIB32): $(OBJS32) $(SRC_DIR)/Makefile + $(MKDIR) $(OBJ_DIR)/32 + $(call cmd_link,$@,32) $(OBJS32) + +$(LIB64): $(OBJS64) $(SRC_DIR)/Makefile + $(MKDIR) $(OBJ_DIR)/64 + $(call cmd_link,$@,64) $(OBJS64) + +doc: $(MAN) + +$(MAN): $(MAN_SRC) + doxygen + +install:: $(LIB) $(MAN) + $(if $(DROPS_STDDIR),,$(error DROPS_STDDIR is not set. Do a 'make config' in $(L4DIR))) + $(VERBOSE)install -d $(DROPS_STDDIR)/tool/lib + $(VERBOSE)install -c $(LIB) $(DROPS_STDDIR)/tool/lib + $(VERBOSE)install -d $(DROPS_STDDIR)/tool/man/man7 + $(VERBOSE)install -c $(MAN) $(DROPS_STDDIR)/tool/man/man7 + +test: + GENDEP_TARGET='simple-cat' \ + GENDEP_BINARY=cpp\ + GENDEP_cpp='+\.h$$ -^/usr' \ + $(LD_PRELOAD)=$(OBJ_DIR)/libgendep.so\ + $(HOST_CC) -o $(OBJ_DIR)/simple-cat simple-cat.c + GENDEP_TARGET='blabla' \ + GENDEP_BINARY=cpp\ + $(LD_PRELOAD)=$(OBJ_DIR)/libgendep.so\ + $(HOST_CC) -o $(OBJ_DIR)/simple-cat simple-cat.c + GENDEP_TARGET='badexp' \ + GENDEP_BINARY=cpp\ + GENDEP_cpp='\)foo'\ + $(LD_PRELOAD)=$(OBJ_DIR)/libgendep.so\ + $(HOST_CC) -o $(OBJ_DIR)/simple-cat simple-cat.c + @echo ========== + cat simple-cat.dep + cat blabla.dep + +clean cleanall:: + rm -f $(OBJ_DIR)/.*.d $(OBJ_DIR)/*.o $(OBJ_DIR)/simple-cat + rm -f $(OBJ_DIR)/32/*.so $(OBJ_DIR)/64/*.so + rm -rf $(OBJ_DIR)/32 $(OBJ_DIR)/64 + +cleanall:: + rm -f $(LIB) + rm -fr man/ html/ + +dist: + rm -rf $(DDIR) + mkdir $(DDIR) + ln $(CSRC) COPYING Doxyfile manpage.dox gendep.h Makefile \ + WhatIsThis simple-cat.c $(DDIR) + tar cfz $(DDIR).tar.gz $(DDIR) + rm -rf $(DDIR) diff --git a/l4/tool/gendep/WhatIsThis b/l4/tool/gendep/WhatIsThis new file mode 100644 index 00000000..6e9962fa --- /dev/null +++ b/l4/tool/gendep/WhatIsThis @@ -0,0 +1 @@ +# libgendep - dependency file generator diff --git a/l4/tool/gendep/deptrack.c b/l4/tool/gendep/deptrack.c new file mode 100644 index 00000000..a38bf29d --- /dev/null +++ b/l4/tool/gendep/deptrack.c @@ -0,0 +1,483 @@ +/* + deptrack.c -- high-level routines for gendepend. + + (c) Han-Wen Nienhuys 1998 + (c) Michael Roitzsch 2007 + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(__APPLE__) || defined(__FreeBSD__) +#include +#include +#endif + +#include "gendep.h" + +#ifndef min +#define min(a,b) ((a)<(b)?(a):(b)) +#endif + +extern int errno; + +static FILE * output; +static struct +{ + regex_t *re_array; + char *invert_array; + int max, no; +} regexps; + +static char * executable_name; +static char * wanted_executable_name; +static char * target; +static char * depfile_name; + +/* Special mode: Detection mode. In this mode, we watch for a binary opening +a file specified in the environment variable GENDEP_SOURCE (stored in +target). The binary name is written into $(GENDEP_OUTPUT) (depfile_name) +then. */ +static int detection_mode; +static int detection_done; + +/* List of dependencies. We first collect all, then write them out. */ +static struct strlist{ + const char*name; + struct strlist *next; +} *dependencies; + +#define STRLEN 1024 + +/* + simplistic wordwrap + */ +static void +write_word (char const * word) +{ + static int column; + int l = strlen (word); + if (l + column > 75 && column>1) + { + fputs ("\\\n\t",output); + column = 8; + } + + column += l; + fputs (word, output); + fputs (" ", output); +} + +static void +xnomem(void *p) +{ + if (!p) + { + errno = ENOMEM; + perror ("libgendep.so"); + } +} + +static char * +xstrdup (char *s) +{ + char *c = strdup (s); + xnomem (c); + return c; +} + +static void * +xrealloc (void *s, int sz) +{ + void *c = realloc (s, sz); + xnomem (c); + return c; +} + +static void * +xmalloc (int sz) +{ + void *c; + c = malloc (sz); + xnomem (c); + return c; +} + +/*!\brief Trim the filename + * + * Remove redundant "./" at the beginning of a filename. + * + * We are not very minimal about memory usage, because this would require + * scanning the filename twice, instead of once. + */ +static char* trim (const char*fn){ + char *name; + + /* remove trailing "./" */ + while(fn[0]=='.' && fn[1]=='/') fn+=2; + name = xmalloc(strlen(fn)+1); + if(name==0) return 0; + + strcpy(name, fn); + return name; +} + +/*!\brief add a dependency + * + * Add a dependency to the list of dependencies for the current target. + * If the name is already registered, it won't be added. + */ +static void gendep__adddep(const char*name){ + struct strlist *dep; + char *namecopy; + + if (!(namecopy = trim(name))) + return; + + /* special detection mode ? */ + if (detection_mode) + { + if (!strcmp(namecopy, target)) + detection_done = 1; + + free(namecopy); + return; + } + + if (!strcmp(target, name)) + return; + + for(dep=dependencies; dep; dep=dep->next){ + if(!strcmp(dep->name, namecopy)){ + free(namecopy); + return; + } + } + dep = xmalloc(sizeof(struct strlist)); + dep->name = namecopy; + dep->next = dependencies; + dependencies = dep; +} + +/*!\brief Delete a dependency + * + * Delete a dependency from the list of dependencies for the current target. + * This is used if an already registered file is removed later. + */ +static void gendep__deldep(const char*name){ + struct strlist *dep, *old; + char *namecopy; + + old = 0; + if((namecopy = trim(name))==0) return; + for(dep=dependencies; dep; dep=dep->next){ + if(!strcmp(dep->name, namecopy)){ + if(old) old->next = dep->next; + else dependencies=dep->next; + free(namecopy); + free((char*)dep->name); + free(dep); + return; + } + old = dep; + } + free(namecopy); +} + +static int +gendep_getenv (char **dest, char *what) +{ + char var[STRLEN]="GENDEP_"; + strcat (var, what); + *dest = getenv (var); + + return !! (*dest); +} + +/* + Do hairy stuff with regexps and environment variables. + */ +static void +setup_regexps (void) +{ + char *regexp_val =0; + char *end, *start; + + if(gendep_getenv(&target, "SOURCE")){ + /* we have to watch for the binary that opens our file first */ + detection_mode=1; + gendep_getenv(&depfile_name, "OUTPUT"); + return; + } + + /* standard mode of operation: catch dependencies */ + if (!gendep_getenv (&wanted_executable_name, "BINARY")) + return; + + if (strcmp (wanted_executable_name, executable_name)) + { + /* support two binary names (e.g. for arch-foo-X and X) */ + if (!gendep_getenv (&wanted_executable_name, "BINARY_ALT1") + || strcmp (wanted_executable_name, executable_name)) + return; + } + + gendep_getenv(&depfile_name, "DEPFILE"); + + if (!gendep_getenv (&target, "TARGET")) + return; + + if (!gendep_getenv (®exp_val, executable_name)) + return; + + /* + let's hope malloc (0) does the sensible thing (not return NULL, that is) + */ + regexps.re_array = xmalloc (0); + regexps.invert_array = xmalloc (0); + + regexp_val = xstrdup (regexp_val); + start = regexp_val; + end = regexp_val + strlen (regexp_val); + + /* + Duh. The strength of C : string handling. (not). Pull apart the whitespace delimited + list of regexps, and try to compile them. + Be really gnuish with dynamic allocation of arrays. + */ + do { + char * end_re = 0; + int in_out; + while (*start && *start != '+' && *start != '-') + start ++; + + in_out= (*start == '+') ; + start ++; + end_re = strchr (start, ' '); + if (end_re) + *end_re = 0; + + if (*start) + { + regex_t regex; + int result= regcomp (®ex, start, REG_NOSUB); + + if (result) + { + fprintf (stderr, "libgendep.so: Bad regular expression `%s\'\n", start); + goto duh; /* ugh */ + } + + if (regexps.no >= regexps.max) + { + /* max_regexps = max_regexps * 2 + 1; */ + regexps.max ++; + regexps.re_array = xrealloc (regexps.re_array, regexps.max * sizeof (regex_t)); + regexps.invert_array = xrealloc (regexps.invert_array, regexps.max * sizeof (char)); + } + + regexps.re_array[regexps.no] = regex; + regexps.invert_array[regexps.no++] = in_out; + } + + duh: + start = end_re ? end_re + 1 : end; + } while (start < end); +} + +/* + Try to get the name of the binary. Is there a portable way to do this? + */ +static void get_executable_name(void) +{ + char *basename_p; +#ifdef __linux + const char * const proc_cmdline = "/proc/self/cmdline"; + FILE *cmdline = fopen (proc_cmdline, "r"); + char cmd[STRLEN]; + int i=0; + int c; + cmd[STRLEN-1] = 0; + + if (!cmdline) + { + fprintf(stderr, "libgendep.o: cannot open %s\n", proc_cmdline); + exit(-1); + } + + while ((c = fgetc(cmdline))!=EOF && c && i < STRLEN-1) + cmd[i++] = c; + + cmd[i++] = 0; +#elif defined(__APPLE__) || defined(__FreeBSD__) + int mib[3], arglen; + size_t size; + char *procargs, *cmd; + + /* allocate process argument space */ + mib[0] = CTL_KERN; + mib[1] = KERN_ARGMAX; + size = sizeof(arglen); + if (sysctl(mib, 2, &arglen, &size, NULL, 0) == -1) + exit(-1); + if (!(procargs = xmalloc(arglen))) + exit(-1); + + /* get a copy of the process argument space */ + mib[0] = CTL_KERN; +#if defined(__APPLE__) + mib[1] = KERN_PROCARGS2; + mib[2] = getpid(); + size = (size_t)arglen; + if (sysctl(mib, 3, procargs, &size, NULL, 0) == -1) { + free(procargs); + exit(-1); + } +#else + mib[1] = KERN_PROC; + mib[2] = KERN_PROC_ARGS; + mib[3] = getpid(); + size = (size_t)arglen; + if (sysctl(mib, 4, procargs, &size, NULL, 0) == -1) { + free(procargs); + exit(-1); + } +#endif + + /* jump over the argument count */ + cmd = procargs + sizeof(int); +#else +# error "Retrieving the executable name is not implemented for your platform." +#endif + + /* ugh. man 3 basename -> ? */ + basename_p = strrchr(cmd, '/'); + if (basename_p) + basename_p++; + else + basename_p = cmd; + + executable_name = xstrdup(basename_p); + +#if defined(__APPLE__) || defined(__FreeBSD__) + free(procargs); +#endif +} + +static void initialize (void) __attribute__ ((constructor)); + +static void initialize (void) +{ + get_executable_name (); + setup_regexps (); + + if (target && !detection_mode) + { + char fn[STRLEN]; + char *slash; + + fn[0] = '\0'; + if(depfile_name){ + strncpy(fn, depfile_name, STRLEN); + } else { + slash = strrchr(target, '/'); + /* copy the path */ + strncat (fn, target, min(STRLEN, slash?slash-target+1:0)); + strncat (fn, ".", STRLEN); + /* copy the name */ + strncat(fn, slash?slash+1:target, STRLEN); + strncat (fn, ".d", STRLEN); + } + fn[STRLEN-1]=0; + + if((output = fopen (fn, "w"))==0){ + fprintf(stderr, "libgendep.so: cannot open %s for writing\n", fn); + return; + } + write_word (target); + write_word (":"); + } +} + +/* Someone is opening a file. If it is opened for reading, and + matches the regular expressions, write it to the dep-file. + + Note that we explicitly ignore accesses to /etc/mtab and /proc/... + as these files are inspected by libc for Linux and tend to change. + */ +void +gendep__register_open (char const *fn, int flags) +{ + if ((detection_mode || output) && !(flags & (O_WRONLY | O_RDWR))) + { + int i; + + if (fn == strstr(fn, "/etc/mtab") || + fn == strstr(fn, "/proc/")) + return; + + for (i = 0; i < regexps.no; i++) + { + int not_matched = regexec (regexps.re_array +i, fn, 0, NULL, 0); + + if (!(not_matched ^ regexps.invert_array[i])) + return; + } + + gendep__adddep(fn); + } +} + +void +gendep__register_unlink (char const *fn) +{ + gendep__deldep(fn); +} + + +static void finish (void) __attribute__ ((destructor)); + +static void finish (void) +{ + if (output) + { + struct strlist *dep; + + for(dep=dependencies; dep; dep=dep->next){ + write_word(dep->name); + } + fprintf (output, "\n"); + for(dep=dependencies; dep; dep=dep->next){ + fputs(dep->name, output); + fputs(":\n", output); + } + fclose (output); + return; + } + + if (detection_mode && detection_done && depfile_name) + { + FILE *file; + + /* + * libgendep is called in a nested fashion (fork+execve in various + * wrappers), so we only write out the most inner occurence, which + * means we only write as long as depfile_name is not there + */ + if (access(depfile_name, W_OK) == -1 && errno == ENOENT) + { + file = fopen(depfile_name, "w"); + if (!file) + return; + fwrite(executable_name, strlen(executable_name), 1, file); + fclose(file); + } + return; + } +} diff --git a/l4/tool/gendep/gendep.h b/l4/tool/gendep/gendep.h new file mode 100644 index 00000000..7f99e0b2 --- /dev/null +++ b/l4/tool/gendep/gendep.h @@ -0,0 +1,3 @@ + +void gendep__register_open (char const *fn, int flags); +void gendep__register_unlink(char const *fn); diff --git a/l4/tool/gendep/manpage.dox b/l4/tool/gendep/manpage.dox new file mode 100644 index 00000000..e3d763dd --- /dev/null +++ b/l4/tool/gendep/manpage.dox @@ -0,0 +1,110 @@ +/*! \page libgendep.so dependency file generator + +\section SYNOPSIS SYNOPSIS +
LD_PRELOAD=\b libgendep.so GENDEP_TARGET=target + GENDEP_BINARY=compiler + [ GENDEP_cmd=compiler ] + [ GENDEP_DEPFILE=depfilename ] + cmd [options] + +
LD_PRELOAD=\b libgendep.so GENDEP_SOURCE=watchfile + GENDEP_OUTPUT=outfilename cmd [options] + +\section DESCRIPTION DESCRIPTION + +
libgendep is a library to build dependency files. By preloading +\b libgendep.so with the dynamic linker \b ld.so, the open(2) +and fopen(3) functions of libc are overloaded. \b libgendep.so +logs all calls to open(2) and fopen(3) and creates an +according dependency file. + +In its alternative form, libgendep can be used to determine the name +of the binary that is used to open a specific file. Use this +to determine a specific element within your compiler tool chain. + +In the first form, the name of a file is added to the dependency list, if: +
    +
  • the file is opened read-only +
  • and the name of the file does not match the environment variable + GENDEP_TARGET +
  • and the name of the binary currently executed matches the + environment variable GENDEP_BINARY. +
  • and the filename matches the regex given in the envirnoment variable + GENDEP_[cmd], with [cmd] beeing substituted by the value of + GENDEP_BINARY. +
      +
    • some special regexps for exclusion are predefined (see below)
    • +
    +
+ +If GENDEP_[cmd] is not set, the last condition is not checked. + +As the current libc for Linux looks into /proc/meminfo and /etc/mtab for +some internal management, gendep ignores accesses to /etc/mtab and /proc/*. + +In the second form, all open(2)- and fopen(3)-calls are +checked for the filename specified in the GENDEP_SOURCE variable. If the +given file is opened, the name of the currently executed binary is written +into the filename specified in GENDEP_OUTPUT. + +\section ENVIRONMENT ENVIRONMENT +
\b libgendep.so is controlled by the following environment variables. + +For the first form: + +
+
GENDEP_TARGET
+
The target, the dependency has to be build for. This string is used + as the target within the make-rule in the dependency file. + Unless GENDEP_DEPFILE is set, the name of the dependency file + is build by prepending then name portion of the target with '.', + and suffixing this with '.d'.
+ +
GENDEP_BINARY
+
The name portion of the command that actually builds the target.
+ +
GENDEP_DEPFILE
+
The name of the dependency file. If this variable is unset, + .GENDEP_TARGET.d will be used. + +
GENDEP_[cmd] ([cmd]=$GENDEP_BINARY)
+
Optional. If set, the value is interpreted as an regex. A file is + included within the dependency list only if its name matches this + regex.
+
+ +For the second form: + +
+
GENDEP_SOURCE
+
The source file to be watched. If this file is opened in read-only + mode, the name of the currently executed binary is written into + $(GENDEP_OUTPUT).
+
GENDEP_OUTPUT
+
The name of the output file for the binary name.
+
+ +\section EXAMPLES EXAMPLES + +LD_PRELOAD=libgendep.so GENDEP_TARGET=main.o GENDEP_BINARY=cpp gcc main.c -o main.o + +This creates a dependency file ".main.o.d" containing all header +files opened by the C preprocessor cpp(1) during the compilation of +main.o. + +LD_PRELOAD=libgendep.so GENDEP_SOURCE=main.c GENDEP_OUTPUT=cppname.txt gcc -c main.c + +This creates the file "cppname.txt" containing the name of the binary that +opened "main.c". If "main.c" was not opened, "cppname.txt" will not be +created. + +\section AUTHOR AUTHORS +
Han-Wen Nienhuys +
Jork Loeser + +\section SEE SEE ALSO +
ld.so(1) - dynamic linker/loader +
open(2) - open and possibly create a file or device +
cpp(1) - The GNU C-Compatible Compiler Preprocessor + +*/ diff --git a/l4/tool/gendep/simple-cat.c b/l4/tool/gendep/simple-cat.c new file mode 100644 index 00000000..cd1157cb --- /dev/null +++ b/l4/tool/gendep/simple-cat.c @@ -0,0 +1,11 @@ +#include +#include "gendep.h" + +int main () +{ + int c; + FILE * f=fopen ("Makefile","r"); + while ((c = fgetc (f)) != EOF) + fputc (c, stderr); + return 0; +} diff --git a/l4/tool/gendep/syscall.c b/l4/tool/gendep/syscall.c new file mode 100644 index 00000000..74be3344 --- /dev/null +++ b/l4/tool/gendep/syscall.c @@ -0,0 +1,194 @@ +/* + syscall.c -- override open(2) + + (c) Han-Wen Nienhuys 1998 + (c) Jork Loeser 2002 + (c) Michael Roitzsch 2007 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +/* Assume GNU as target platform. We need this in dlfcn.h */ +#define __USE_GNU +#include +#include "gendep.h" + +#ifdef __ELF__ +# define OPEN __open +# define OPEN64 __open64 +# define FOPEN __fopen +# define FOPEN64 __fopen64 +# define UNLINK __unlink +#else +# define OPEN open +# define OPEN64 open64 +# define FOPEN fopen +# define FOPEN64 fopen64 +# define UNLINK unlink +#endif + +#define VERBOSE 0 /* set to 1 to log open/unlink calls */ + +/* ----------------------------------------------------------------------- */ +/* + This breaks if we hook gendep onto another library that overrides open(2). + (zlibc comes to mind) + */ +static int real_open (const char *fn, int flags, int mode) +{ + if(VERBOSE) printf("real_open(%s)\n", fn); + return (syscall(SYS_open, (fn), (flags), (mode))); +} + +int OPEN(const char *fn, int flags, ...) +{ + int rv ; + va_list p; + va_start (p,flags); + + if(VERBOSE) printf("open(%s) called\n", fn); + rv = real_open (fn, flags, va_arg (p, int)); + if (rv >=0) + gendep__register_open (fn, flags); + + return rv; +} + +/* ----------------------------------------------------------------------- */ +typedef int(*open64_type)(const char*, int flag, int mode); + +static int real_open64(const char*path, int flag, int mode){ + static open64_type f_open64; + + if(VERBOSE) printf("real_open64(%s)\n", path); + if(f_open64==0){ + *(void**)(&f_open64) = dlsym(RTLD_NEXT, "open64"); + if(!f_open64){ + fprintf(stderr, "gendep: Cannot resolve open64()\n"); + errno=ENOENT; + return 0; + } + } + return f_open64(path, flag, mode); +} + +int OPEN64(const char*path, int flag, int mode){ + int f; + + if(VERBOSE) printf("open64(%s)\n", path); + f = real_open64(path, flag, mode); + if(f>=0){ + gendep__register_open(path, flag); + } + return f; +} + +/* ----------------------------------------------------------------------- */ +typedef FILE* (*fopen_type)(const char*, const char*); + +static FILE* real_fopen(const char*path, const char*mode){ + static fopen_type f_fopen; + + if(VERBOSE) printf("real_fopen(%s)\n", path); + if(f_fopen==0){ + *(void**)(&f_fopen) = dlsym(RTLD_NEXT, "fopen"); + if(!f_fopen){ + fprintf(stderr, "gendep: Cannot resolve fopen()\n"); + errno=ENOENT; + return 0; + } + } + return f_fopen(path, mode); +} + +FILE* FOPEN(const char*path, const char*mode){ + FILE *f; + int binmode; + + if(VERBOSE) printf("fopen(%s)\n", path); + f = real_fopen(path, mode); + if(f){ + if(strchr(mode, 'w') || strchr(mode, 'a')){ + binmode=O_WRONLY; + } else { + binmode=O_RDONLY; + } + gendep__register_open(path, binmode); + } + return f; +} + +/* ----------------------------------------------------------------------- */ +typedef FILE* (*fopen64_type)(const char*, const char*); + +static FILE* real_fopen64(const char*path, const char*mode){ + static fopen64_type f_fopen64; + + if(VERBOSE) printf("real_fopen64(%s)\n", path); + if(f_fopen64==0){ + *(void**)(&f_fopen64) = dlsym(RTLD_NEXT, "fopen64"); + if(!f_fopen64){ + fprintf(stderr, "gendep: Cannot resolve fopen64()\n"); + errno=ENOENT; + return 0; + } + } + return f_fopen64(path, mode); +} + +FILE* FOPEN64(const char*path, const char*mode){ + FILE *f; + int binmode; + + if(VERBOSE) printf("fopen64(%s)\n", path); + f = real_fopen64(path, mode); + if(f){ + if(strchr(mode, 'w') || strchr(mode, 'a')){ + binmode=O_WRONLY; + } else { + binmode=O_RDONLY; + } + gendep__register_open(path, binmode); + } + return f; +} + +/* ----------------------------------------------------------------------- */ +static int real_unlink (const char *fn) +{ + if(VERBOSE) printf("real_unlink(%s)\n", fn); + return syscall(SYS_unlink, (fn)); +} + +int UNLINK(const char *fn) +{ + int rv ; + + if(VERBOSE) printf("unlink(%s)\n", fn); + rv = real_unlink (fn); + if (rv >=0) + gendep__register_unlink (fn); + + return rv; +} + +/* ----------------------------------------------------------------------- */ +#ifdef __ELF__ +int open (const char *fn, int flags, ...) __attribute__ ((alias ("__open"))); +int open64 (const char *fn, int flags, ...) __attribute__ ((alias ("__open64"))); +int unlink(const char *fn) __attribute__ ((alias ("__unlink"))); +FILE *fopen (const char *path, const char *mode) __attribute__ ((alias ("__fopen"))); +FILE *fopen64 (const char *path, const char *mode) __attribute__ ((alias ("__fopen64"))); +#endif diff --git a/l4/tool/kconfig/COPYING b/l4/tool/kconfig/COPYING new file mode 100644 index 00000000..ca442d31 --- /dev/null +++ b/l4/tool/kconfig/COPYING @@ -0,0 +1,356 @@ + + NOTE! This copyright does *not* cover user programs that use kernel + services by normal system calls - this is merely considered normal use + of the kernel, and does *not* fall under the heading of "derived work". + Also note that the GPL below is copyrighted by the Free Software + Foundation, but the instance of code that it refers to (the Linux + kernel) is copyrighted by me and others who actually wrote it. + + Also note that the only valid version of the GPL as far as the kernel + is concerned is _this_ particular version of the license (ie v2, not + v2.2 or v3.x or whatever), unless explicitly otherwise stated. + + Linus Torvalds + +---------------------------------------- + + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/l4/tool/kconfig/Makefile b/l4/tool/kconfig/Makefile new file mode 100644 index 00000000..c565ae05 --- /dev/null +++ b/l4/tool/kconfig/Makefile @@ -0,0 +1,1400 @@ +VERSION = 3 +PATCHLEVEL = 5 +SUBLEVEL = 0 +EXTRAVERSION = +NAME = Saber-toothed Squirrel + +# *DOCUMENTATION* +# To see a list of typical targets execute "make help" +# More info can be located in ./README +# Comments in this file are targeted only to the developer, do not +# expect to learn how to build the kernel reading this file. + +# Do not: +# o use make's built-in rules and variables +# (this increases performance and avoids hard-to-debug behaviour); +# o print "Entering directory ..."; +MAKEFLAGS += -rR --no-print-directory + +# Avoid funny character set dependencies +unexport LC_ALL +LC_COLLATE=C +LC_NUMERIC=C +export LC_COLLATE LC_NUMERIC + +# We are using a recursive build, so we need to do a little thinking +# to get the ordering right. +# +# Most importantly: sub-Makefiles should only ever modify files in +# their own directory. If in some directory we have a dependency on +# a file in another dir (which doesn't happen often, but it's often +# unavoidable when linking the built-in.o targets which finally +# turn into vmlinux), we will call a sub make in that other dir, and +# after that we are sure that everything which is in that other dir +# is now up to date. +# +# The only cases where we need to modify files which have global +# effects are thus separated out and done before the recursive +# descending is started. They are now explicitly listed as the +# prepare rule. + +# To put more focus on warnings, be less verbose as default +# Use 'make V=1' to see the full commands + +ifeq ("$(origin V)", "command line") + KBUILD_VERBOSE = $(V) +endif +ifndef KBUILD_VERBOSE + KBUILD_VERBOSE = 0 +endif + +# Call a source code checker (by default, "sparse") as part of the +# C compilation. +# +# Use 'make C=1' to enable checking of only re-compiled files. +# Use 'make C=2' to enable checking of *all* source files, regardless +# of whether they are re-compiled or not. +# +# See the file "Documentation/sparse.txt" for more details, including +# where to get the "sparse" utility. + +ifeq ("$(origin C)", "command line") + KBUILD_CHECKSRC = $(C) +endif +ifndef KBUILD_CHECKSRC + KBUILD_CHECKSRC = 0 +endif + +# Use make M=dir to specify directory of external module to build +# Old syntax make ... SUBDIRS=$PWD is still supported +# Setting the environment variable KBUILD_EXTMOD take precedence +ifdef SUBDIRS + KBUILD_EXTMOD ?= $(SUBDIRS) +endif + +ifeq ("$(origin M)", "command line") + KBUILD_EXTMOD := $(M) +endif + +# kbuild supports saving output files in a separate directory. +# To locate output files in a separate directory two syntaxes are supported. +# In both cases the working directory must be the root of the kernel src. +# 1) O= +# Use "make O=dir/to/store/output/files/" +# +# 2) Set KBUILD_OUTPUT +# Set the environment variable KBUILD_OUTPUT to point to the directory +# where the output files shall be placed. +# export KBUILD_OUTPUT=dir/to/store/output/files/ +# make +# +# The O= assignment takes precedence over the KBUILD_OUTPUT environment +# variable. + + +# KBUILD_SRC is set on invocation of make in OBJ directory +# KBUILD_SRC is not intended to be used by the regular user (for now) +ifeq ($(KBUILD_SRC),) + +# OK, Make called in directory where kernel src resides +# Do we want to locate output files in a separate directory? +ifeq ("$(origin O)", "command line") + KBUILD_OUTPUT := $(O) +endif + +ifeq ("$(origin W)", "command line") + export KBUILD_ENABLE_EXTRA_GCC_CHECKS := $(W) +endif + +# That's our default target when none is given on the command line +PHONY := _all +_all: + +# Cancel implicit rules on top Makefile +$(CURDIR)/Makefile Makefile: ; + +ifneq ($(KBUILD_OUTPUT),) +# Invoke a second make in the output directory, passing relevant variables +# check that the output directory actually exists +saved-output := $(KBUILD_OUTPUT) +KBUILD_OUTPUT := $(shell cd $(KBUILD_OUTPUT) && /bin/pwd) +$(if $(KBUILD_OUTPUT),, \ + $(error output directory "$(saved-output)" does not exist)) + +PHONY += $(MAKECMDGOALS) sub-make + +$(filter-out _all sub-make $(CURDIR)/Makefile, $(MAKECMDGOALS)) _all: sub-make + $(Q)@: + +sub-make: FORCE + $(if $(KBUILD_VERBOSE:1=),@)$(MAKE) -C $(KBUILD_OUTPUT) \ + KBUILD_SRC=$(CURDIR) \ + KBUILD_EXTMOD="$(KBUILD_EXTMOD)" -f $(CURDIR)/Makefile \ + $(filter-out _all sub-make,$(MAKECMDGOALS)) + +# Leave processing to above invocation of make +skip-makefile := 1 +endif # ifneq ($(KBUILD_OUTPUT),) +endif # ifeq ($(KBUILD_SRC),) + +# We process the rest of the Makefile if this is the final invocation of make +ifeq ($(skip-makefile),) + +# If building an external module we do not care about the all: rule +# but instead _all depend on modules +PHONY += all +ifeq ($(KBUILD_EXTMOD),) +_all: all +else +_all: modules +endif + +srctree := $(if $(KBUILD_SRC),$(KBUILD_SRC),$(CURDIR)) +objtree := $(CURDIR) +src := $(srctree) +obj := $(objtree) + +VPATH := $(srctree)$(if $(KBUILD_EXTMOD),:$(KBUILD_EXTMOD)) + +export srctree objtree VPATH + + +# SUBARCH tells the usermode build what the underlying arch is. That is set +# first, and if a usermode build is happening, the "ARCH=um" on the command +# line overrides the setting of ARCH below. If a native build is happening, +# then ARCH is assigned, getting whatever value it gets normally, and +# SUBARCH is subsequently ignored. + +SUBARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \ + -e s/arm.*/arm/ -e s/sa110/arm/ \ + -e s/s390x/s390/ -e s/parisc64/parisc/ \ + -e s/ppc.*/powerpc/ -e s/mips.*/mips/ \ + -e s/sh[234].*/sh/ ) + +# Cross compiling and selecting different set of gcc/bin-utils +# --------------------------------------------------------------------------- +# +# When performing cross compilation for other architectures ARCH shall be set +# to the target architecture. (See arch/* for the possibilities). +# ARCH can be set during invocation of make: +# make ARCH=ia64 +# Another way is to have ARCH set in the environment. +# The default ARCH is the host where make is executed. + +# CROSS_COMPILE specify the prefix used for all executables used +# during compilation. Only gcc and related bin-utils executables +# are prefixed with $(CROSS_COMPILE). +# CROSS_COMPILE can be set on the command line +# make CROSS_COMPILE=ia64-linux- +# Alternatively CROSS_COMPILE can be set in the environment. +# A third alternative is to store a setting in .config so that plain +# "make" in the configured kernel build directory always uses that. +# Default value for CROSS_COMPILE is not to prefix executables +# Note: Some architectures assign CROSS_COMPILE in their arch/*/Makefile +export KBUILD_BUILDHOST := $(SUBARCH) +ARCH ?= $(SUBARCH) +CROSS_COMPILE ?= $(CONFIG_CROSS_COMPILE:"%"=%) + +# Architecture as present in compile.h +UTS_MACHINE := $(ARCH) +SRCARCH := $(ARCH) + +# Additional ARCH settings for x86 +ifeq ($(ARCH),i386) + SRCARCH := x86 +endif +ifeq ($(ARCH),x86_64) + SRCARCH := x86 +endif + +# Additional ARCH settings for sparc +ifeq ($(ARCH),sparc32) + SRCARCH := sparc +endif +ifeq ($(ARCH),sparc64) + SRCARCH := sparc +endif + +# Additional ARCH settings for sh +ifeq ($(ARCH),sh64) + SRCARCH := sh +endif + +# Additional ARCH settings for tile +ifeq ($(ARCH),tilepro) + SRCARCH := tile +endif +ifeq ($(ARCH),tilegx) + SRCARCH := tile +endif + +# Where to locate arch specific headers +hdr-arch := $(SRCARCH) + +KCONFIG_CONFIG ?= .config +export KCONFIG_CONFIG + +# SHELL used by kbuild +CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \ + else if [ -x /bin/bash ]; then echo /bin/bash; \ + else echo sh; fi ; fi) + +HOSTCC = gcc +HOSTCXX = g++ +HOSTCFLAGS = -Wall -Wmissing-prototypes -Wstrict-prototypes -O2 -fomit-frame-pointer +HOSTCXXFLAGS = -O2 + +# Decide whether to build built-in, modular, or both. +# Normally, just do built-in. + +KBUILD_MODULES := +KBUILD_BUILTIN := 1 + +# If we have only "make modules", don't compile built-in objects. +# When we're building modules with modversions, we need to consider +# the built-in objects during the descend as well, in order to +# make sure the checksums are up to date before we record them. + +ifeq ($(MAKECMDGOALS),modules) + KBUILD_BUILTIN := $(if $(CONFIG_MODVERSIONS),1) +endif + +# If we have "make modules", compile modules +# in addition to whatever we do anyway. +# Just "make" or "make all" shall build modules as well + +ifneq ($(filter all _all modules,$(MAKECMDGOALS)),) + KBUILD_MODULES := 1 +endif + +ifeq ($(MAKECMDGOALS),) + KBUILD_MODULES := 1 +endif + +export KBUILD_MODULES KBUILD_BUILTIN +export KBUILD_CHECKSRC KBUILD_SRC KBUILD_EXTMOD + +# Beautify output +# --------------------------------------------------------------------------- +# +# Normally, we echo the whole command before executing it. By making +# that echo $($(quiet)$(cmd)), we now have the possibility to set +# $(quiet) to choose other forms of output instead, e.g. +# +# quiet_cmd_cc_o_c = Compiling $(RELDIR)/$@ +# cmd_cc_o_c = $(CC) $(c_flags) -c -o $@ $< +# +# If $(quiet) is empty, the whole command will be printed. +# If it is set to "quiet_", only the short version will be printed. +# If it is set to "silent_", nothing will be printed at all, since +# the variable $(silent_cmd_cc_o_c) doesn't exist. +# +# A simple variant is to prefix commands with $(Q) - that's useful +# for commands that shall be hidden in non-verbose mode. +# +# $(Q)ln $@ :< +# +# If KBUILD_VERBOSE equals 0 then the above command will be hidden. +# If KBUILD_VERBOSE equals 1 then the above command is displayed. + +ifeq ($(KBUILD_VERBOSE),1) + quiet = + Q = +else + quiet=quiet_ + Q = @ +endif + +# If the user is running make -s (silent mode), suppress echoing of +# commands + +ifneq ($(filter s% -s%,$(MAKEFLAGS)),) + quiet=silent_ +endif + +export quiet Q KBUILD_VERBOSE + + +# Look for make include files relative to root of kernel src +MAKEFLAGS += --include-dir=$(srctree) + +# We need some generic definitions (do not try to remake the file). +$(srctree)/scripts/Kbuild.include: ; +include $(srctree)/scripts/Kbuild.include + +# Make variables (CC, etc...) + +AS = $(CROSS_COMPILE)as +LD = $(CROSS_COMPILE)ld +CC = $(CROSS_COMPILE)gcc +CPP = $(CC) -E +AR = $(CROSS_COMPILE)ar +NM = $(CROSS_COMPILE)nm +STRIP = $(CROSS_COMPILE)strip +OBJCOPY = $(CROSS_COMPILE)objcopy +OBJDUMP = $(CROSS_COMPILE)objdump +AWK = awk +GENKSYMS = scripts/genksyms/genksyms +INSTALLKERNEL := installkernel +DEPMOD = /sbin/depmod +PERL = perl +CHECK = sparse + +CHECKFLAGS := -D__linux__ -Dlinux -D__STDC__ -Dunix -D__unix__ \ + -Wbitwise -Wno-return-void $(CF) +CFLAGS_MODULE = +AFLAGS_MODULE = +LDFLAGS_MODULE = +CFLAGS_KERNEL = +AFLAGS_KERNEL = +CFLAGS_GCOV = -fprofile-arcs -ftest-coverage + + +# Use LINUXINCLUDE when you must reference the include/ directory. +# Needed to be compatible with the O= option +LINUXINCLUDE := -I$(srctree)/arch/$(hdr-arch)/include \ + -Iarch/$(hdr-arch)/include/generated -Iinclude \ + $(if $(KBUILD_SRC), -I$(srctree)/include) \ + -include $(srctree)/include/linux/kconfig.h + +KBUILD_CPPFLAGS := -D__KERNEL__ + +KBUILD_CFLAGS := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \ + -fno-strict-aliasing -fno-common \ + -Werror-implicit-function-declaration \ + -Wno-format-security \ + -fno-delete-null-pointer-checks +KBUILD_AFLAGS_KERNEL := +KBUILD_CFLAGS_KERNEL := +KBUILD_AFLAGS := -D__ASSEMBLY__ +KBUILD_AFLAGS_MODULE := -DMODULE +KBUILD_CFLAGS_MODULE := -DMODULE +KBUILD_LDFLAGS_MODULE := -T $(srctree)/scripts/module-common.lds + +# Read KERNELRELEASE from include/config/kernel.release (if it exists) +KERNELRELEASE = $(shell cat include/config/kernel.release 2> /dev/null) +KERNELVERSION = $(VERSION)$(if $(PATCHLEVEL),.$(PATCHLEVEL)$(if $(SUBLEVEL),.$(SUBLEVEL)))$(EXTRAVERSION) + +export VERSION PATCHLEVEL SUBLEVEL KERNELRELEASE KERNELVERSION +export ARCH SRCARCH CONFIG_SHELL HOSTCC HOSTCFLAGS CROSS_COMPILE AS LD CC +export CPP AR NM STRIP OBJCOPY OBJDUMP +export MAKE AWK GENKSYMS INSTALLKERNEL PERL UTS_MACHINE +export HOSTCXX HOSTCXXFLAGS LDFLAGS_MODULE CHECK CHECKFLAGS + +export KBUILD_CPPFLAGS NOSTDINC_FLAGS LINUXINCLUDE OBJCOPYFLAGS LDFLAGS +export KBUILD_CFLAGS CFLAGS_KERNEL CFLAGS_MODULE CFLAGS_GCOV +export KBUILD_AFLAGS AFLAGS_KERNEL AFLAGS_MODULE +export KBUILD_AFLAGS_MODULE KBUILD_CFLAGS_MODULE KBUILD_LDFLAGS_MODULE +export KBUILD_AFLAGS_KERNEL KBUILD_CFLAGS_KERNEL +export KBUILD_ARFLAGS + +# When compiling out-of-tree modules, put MODVERDIR in the module +# tree rather than in the kernel tree. The kernel tree might +# even be read-only. +export MODVERDIR := $(if $(KBUILD_EXTMOD),$(firstword $(KBUILD_EXTMOD))/).tmp_versions + +# Files to ignore in find ... statements + +RCS_FIND_IGNORE := \( -name SCCS -o -name BitKeeper -o -name .svn -o -name CVS \ + -o -name .pc -o -name .hg -o -name .git \) -prune -o +export RCS_TAR_IGNORE := --exclude SCCS --exclude BitKeeper --exclude .svn \ + --exclude CVS --exclude .pc --exclude .hg --exclude .git + +# =========================================================================== +# Rules shared between *config targets and build targets + +# Basic helpers built in scripts/ +PHONY += scripts_basic +scripts_basic: + $(Q)$(MAKE) $(build)=scripts/basic + $(Q)rm -f .tmp_quiet_recordmcount + +# To avoid any implicit rule to kick in, define an empty command. +scripts/basic/%: scripts_basic ; + +PHONY += outputmakefile +# outputmakefile generates a Makefile in the output directory, if using a +# separate output directory. This allows convenient use of make in the +# output directory. +outputmakefile: +ifneq ($(KBUILD_SRC_disabled_for_fiasco),) + $(Q)ln -fsn $(srctree) source + $(Q)$(CONFIG_SHELL) $(srctree)/scripts/mkmakefile \ + $(srctree) $(objtree) $(VERSION) $(PATCHLEVEL) +endif + +# Support for using generic headers in asm-generic +PHONY += asm-generic +asm-generic: + $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.asm-generic \ + obj=arch/$(SRCARCH)/include/generated/asm + +# To make sure we do not include .config for any of the *config targets +# catch them early, and hand them over to scripts/kconfig/Makefile +# It is allowed to specify more targets when calling make, including +# mixing *config targets and build targets. +# For example 'make oldconfig all'. +# Detect when mixed targets is specified, and make a second invocation +# of make so .config is not included in this case either (for *config). + +no-dot-config-targets := clean mrproper distclean \ + cscope gtags TAGS tags help %docs check% coccicheck \ + include/linux/version.h headers_% archheaders archscripts \ + kernelversion %src-pkg + +config-targets := 0 +mixed-targets := 0 +dot-config := 1 + +ifneq ($(filter $(no-dot-config-targets), $(MAKECMDGOALS)),) + ifeq ($(filter-out $(no-dot-config-targets), $(MAKECMDGOALS)),) + dot-config := 0 + endif +endif + +ifeq ($(KBUILD_EXTMOD),) + ifneq ($(filter config %config,$(MAKECMDGOALS)),) + config-targets := 1 + ifneq ($(filter-out config %config,$(MAKECMDGOALS)),) + mixed-targets := 1 + endif + endif +endif + +ifeq ($(mixed-targets),1) +# =========================================================================== +# We're called with mixed targets (*config and build targets). +# Handle them one by one. + +%:: FORCE + $(Q)$(MAKE) -C $(srctree) KBUILD_SRC= $@ + +else +ifeq ($(config-targets),1) +# =========================================================================== +# *config targets only - make sure prerequisites are updated, and descend +# in scripts/kconfig to make the *config target + +# Read arch specific Makefile to set KBUILD_DEFCONFIG as needed. +# KBUILD_DEFCONFIG may point out an alternative default configuration +# used for 'make defconfig' +#adam#include $(srctree)/arch/$(SRCARCH)/Makefile +export KBUILD_DEFCONFIG KBUILD_KCONFIG + +config: scripts_basic outputmakefile FORCE + $(Q)mkdir -p config + $(Q)$(MAKE) $(build)=scripts/kconfig $@ + +%config: scripts_basic outputmakefile FORCE + $(Q)mkdir -p config + $(Q)$(MAKE) $(build)=scripts/kconfig $@ + +else +# =========================================================================== +# Build targets only - this includes vmlinux, arch specific targets, clean +# targets and others. In general all targets except *config targets. + +ifeq ($(KBUILD_EXTMOD),) +# Additional helpers built in scripts/ +# Carefully list dependencies so we do not try to build scripts twice +# in parallel +PHONY += scripts +scripts: scripts_basic include/config/auto.conf include/config/tristate.conf + $(Q)$(MAKE) $(build)=$(@) + +# Objects we will link into vmlinux / subdirs we need to visit +init-y := init/ +drivers-y := drivers/ sound/ firmware/ +net-y := net/ +libs-y := lib/ +core-y := usr/ +endif # KBUILD_EXTMOD + +ifeq ($(dot-config),1) +# Read in config +-include include/config/auto.conf + +ifeq ($(KBUILD_EXTMOD),) +# Read in dependencies to all Kconfig* files, make sure to run +# oldconfig if changes are detected. +-include include/config/auto.conf.cmd + +# To avoid any implicit rule to kick in, define an empty command +$(KCONFIG_CONFIG) include/config/auto.conf.cmd: ; + +# If .config is newer than include/config/auto.conf, someone tinkered +# with it and forgot to run make oldconfig. +# if auto.conf.cmd is missing then we are probably in a cleaned tree so +# we execute the config step to be sure to catch updated Kconfig files +include/config/%.conf: $(KCONFIG_CONFIG) include/config/auto.conf.cmd + $(Q)$(MAKE) -f $(srctree)/Makefile silentoldconfig +else +# external modules needs include/generated/autoconf.h and include/config/auto.conf +# but do not care if they are up-to-date. Use auto.conf to trigger the test +PHONY += include/config/auto.conf + +include/config/auto.conf: + $(Q)test -e include/generated/autoconf.h -a -e $@ || ( \ + echo; \ + echo " ERROR: Kernel configuration is invalid."; \ + echo " include/generated/autoconf.h or $@ are missing.";\ + echo " Run 'make oldconfig && make prepare' on kernel src to fix it."; \ + echo; \ + /bin/false) + +endif # KBUILD_EXTMOD + +else +# Dummy target needed, because used as prerequisite +include/config/auto.conf: ; +endif # $(dot-config) + +# The all: target is the default when no target is given on the +# command line. +# This allow a user to issue only 'make' to build a kernel including modules +# Defaults to vmlinux, but the arch makefile usually adds further targets +all: vmlinux + +ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE +KBUILD_CFLAGS += -Os +else +KBUILD_CFLAGS += -O2 +endif + +include $(srctree)/arch/$(SRCARCH)/Makefile + +ifdef CONFIG_READABLE_ASM +# Disable optimizations that make assembler listings hard to read. +# reorder blocks reorders the control in the function +# ipa clone creates specialized cloned functions +# partial inlining inlines only parts of functions +KBUILD_CFLAGS += $(call cc-option,-fno-reorder-blocks,) \ + $(call cc-option,-fno-ipa-cp-clone,) \ + $(call cc-option,-fno-partial-inlining) +endif + +ifneq ($(CONFIG_FRAME_WARN),0) +KBUILD_CFLAGS += $(call cc-option,-Wframe-larger-than=${CONFIG_FRAME_WARN}) +endif + +# Force gcc to behave correct even for buggy distributions +ifndef CONFIG_CC_STACKPROTECTOR +KBUILD_CFLAGS += $(call cc-option, -fno-stack-protector) +endif + +# This warning generated too much noise in a regular build. +# Use make W=1 to enable this warning (see scripts/Makefile.build) +KBUILD_CFLAGS += $(call cc-disable-warning, unused-but-set-variable) + +ifdef CONFIG_FRAME_POINTER +KBUILD_CFLAGS += -fno-omit-frame-pointer -fno-optimize-sibling-calls +else +# Some targets (ARM with Thumb2, for example), can't be built with frame +# pointers. For those, we don't have FUNCTION_TRACER automatically +# select FRAME_POINTER. However, FUNCTION_TRACER adds -pg, and this is +# incompatible with -fomit-frame-pointer with current GCC, so we don't use +# -fomit-frame-pointer with FUNCTION_TRACER. +ifndef CONFIG_FUNCTION_TRACER +KBUILD_CFLAGS += -fomit-frame-pointer +endif +endif + +ifdef CONFIG_DEBUG_INFO +KBUILD_CFLAGS += -g +KBUILD_AFLAGS += -gdwarf-2 +endif + +ifdef CONFIG_DEBUG_INFO_REDUCED +KBUILD_CFLAGS += $(call cc-option, -femit-struct-debug-baseonly) +endif + +ifdef CONFIG_FUNCTION_TRACER +KBUILD_CFLAGS += -pg +ifdef CONFIG_DYNAMIC_FTRACE + ifdef CONFIG_HAVE_C_RECORDMCOUNT + BUILD_C_RECORDMCOUNT := y + export BUILD_C_RECORDMCOUNT + endif +endif +endif + +# We trigger additional mismatches with less inlining +ifdef CONFIG_DEBUG_SECTION_MISMATCH +KBUILD_CFLAGS += $(call cc-option, -fno-inline-functions-called-once) +endif + +# arch Makefile may override CC so keep this after arch Makefile is included +NOSTDINC_FLAGS += -nostdinc -isystem $(shell $(CC) -print-file-name=include) +CHECKFLAGS += $(NOSTDINC_FLAGS) + +# warn about C99 declaration after statement +KBUILD_CFLAGS += $(call cc-option,-Wdeclaration-after-statement,) + +# disable pointer signed / unsigned warnings in gcc 4.0 +KBUILD_CFLAGS += $(call cc-disable-warning, pointer-sign) + +# disable invalid "can't wrap" optimizations for signed / pointers +KBUILD_CFLAGS += $(call cc-option,-fno-strict-overflow) + +# conserve stack if available +KBUILD_CFLAGS += $(call cc-option,-fconserve-stack) + +# use the deterministic mode of AR if available +KBUILD_ARFLAGS := $(call ar-option,D) + +# check for 'asm goto' +ifeq ($(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-goto.sh $(CC)), y) + KBUILD_CFLAGS += -DCC_HAVE_ASM_GOTO +endif + +# Add user supplied CPPFLAGS, AFLAGS and CFLAGS as the last assignments +# But warn user when we do so +warn-assign = \ +$(warning "WARNING: Appending $$K$(1) ($(K$(1))) from $(origin K$(1)) to kernel $$$(1)") + +ifneq ($(KCPPFLAGS),) + $(call warn-assign,CPPFLAGS) + KBUILD_CPPFLAGS += $(KCPPFLAGS) +endif +ifneq ($(KAFLAGS),) + $(call warn-assign,AFLAGS) + KBUILD_AFLAGS += $(KAFLAGS) +endif +ifneq ($(KCFLAGS),) + $(call warn-assign,CFLAGS) + KBUILD_CFLAGS += $(KCFLAGS) +endif + +# Use --build-id when available. +LDFLAGS_BUILD_ID = $(patsubst -Wl$(comma)%,%,\ + $(call cc-ldoption, -Wl$(comma)--build-id,)) +KBUILD_LDFLAGS_MODULE += $(LDFLAGS_BUILD_ID) +LDFLAGS_vmlinux += $(LDFLAGS_BUILD_ID) + +ifeq ($(CONFIG_STRIP_ASM_SYMS),y) +LDFLAGS_vmlinux += $(call ld-option, -X,) +endif + +# Default kernel image to build when no specific target is given. +# KBUILD_IMAGE may be overruled on the command line or +# set in the environment +# Also any assignments in arch/$(ARCH)/Makefile take precedence over +# this default value +export KBUILD_IMAGE ?= vmlinux + +# +# INSTALL_PATH specifies where to place the updated kernel and system map +# images. Default is /boot, but you can set it to other values +export INSTALL_PATH ?= /boot + +# +# INSTALL_MOD_PATH specifies a prefix to MODLIB for module directory +# relocations required by build roots. This is not defined in the +# makefile but the argument can be passed to make if needed. +# + +MODLIB = $(INSTALL_MOD_PATH)/lib/modules/$(KERNELRELEASE) +export MODLIB + +# +# INSTALL_MOD_STRIP, if defined, will cause modules to be +# stripped after they are installed. If INSTALL_MOD_STRIP is '1', then +# the default option --strip-debug will be used. Otherwise, +# INSTALL_MOD_STRIP value will be used as the options to the strip command. + +ifdef INSTALL_MOD_STRIP +ifeq ($(INSTALL_MOD_STRIP),1) +mod_strip_cmd = $(STRIP) --strip-debug +else +mod_strip_cmd = $(STRIP) $(INSTALL_MOD_STRIP) +endif # INSTALL_MOD_STRIP=1 +else +mod_strip_cmd = true +endif # INSTALL_MOD_STRIP +export mod_strip_cmd + + +ifeq ($(KBUILD_EXTMOD),) +core-y += kernel/ mm/ fs/ ipc/ security/ crypto/ block/ + +vmlinux-dirs := $(patsubst %/,%,$(filter %/, $(init-y) $(init-m) \ + $(core-y) $(core-m) $(drivers-y) $(drivers-m) \ + $(net-y) $(net-m) $(libs-y) $(libs-m))) + +vmlinux-alldirs := $(sort $(vmlinux-dirs) $(patsubst %/,%,$(filter %/, \ + $(init-n) $(init-) \ + $(core-n) $(core-) $(drivers-n) $(drivers-) \ + $(net-n) $(net-) $(libs-n) $(libs-)))) + +init-y := $(patsubst %/, %/built-in.o, $(init-y)) +core-y := $(patsubst %/, %/built-in.o, $(core-y)) +drivers-y := $(patsubst %/, %/built-in.o, $(drivers-y)) +net-y := $(patsubst %/, %/built-in.o, $(net-y)) +libs-y1 := $(patsubst %/, %/lib.a, $(libs-y)) +libs-y2 := $(patsubst %/, %/built-in.o, $(libs-y)) +libs-y := $(libs-y1) $(libs-y2) + +# Externally visible symbols (used by link-vmlinux.sh) +export KBUILD_VMLINUX_INIT := $(head-y) $(init-y) +export KBUILD_VMLINUX_MAIN := $(core-y) $(libs-y) $(drivers-y) $(net-y) +export KBUILD_LDS := arch/$(SRCARCH)/kernel/vmlinux.lds +export LDFLAGS_vmlinux + +vmlinux-deps := $(KBUILD_LDS) $(KBUILD_VMLINUX_INIT) $(KBUILD_VMLINUX_MAIN) + +# Final link of vmlinux + cmd_link-vmlinux = $(CONFIG_SHELL) $< $(LD) $(LDFLAGS) $(LDFLAGS_vmlinux) +quiet_cmd_link-vmlinux = LINK $@ + +# Include targets which we want to +# execute if the rest of the kernel build went well. +vmlinux: scripts/link-vmlinux.sh $(vmlinux-deps) FORCE +ifdef CONFIG_HEADERS_CHECK + $(Q)$(MAKE) -f $(srctree)/Makefile headers_check +endif +ifdef CONFIG_SAMPLES + $(Q)$(MAKE) $(build)=samples +endif +ifdef CONFIG_BUILD_DOCSRC + $(Q)$(MAKE) $(build)=Documentation +endif + +$(call if_changed,link-vmlinux) + +# The actual objects are generated when descending, +# make sure no implicit rule kicks in +$(sort $(vmlinux-deps)): $(vmlinux-dirs) ; + +# Handle descending into subdirectories listed in $(vmlinux-dirs) +# Preset locale variables to speed up the build process. Limit locale +# tweaks to this spot to avoid wrong language settings when running +# make menuconfig etc. +# Error messages still appears in the original language + +PHONY += $(vmlinux-dirs) +$(vmlinux-dirs): prepare scripts + $(Q)$(MAKE) $(build)=$@ + +# Store (new) KERNELRELASE string in include/config/kernel.release +include/config/kernel.release: include/config/auto.conf FORCE + $(Q)rm -f $@ + $(Q)echo "$(KERNELVERSION)$$($(CONFIG_SHELL) $(srctree)/scripts/setlocalversion $(srctree))" > $@ + + +# Things we need to do before we recursively start building the kernel +# or the modules are listed in "prepare". +# A multi level approach is used. prepareN is processed before prepareN-1. +# archprepare is used in arch Makefiles and when processed asm symlink, +# version.h and scripts_basic is processed / created. + +# Listed in dependency order +PHONY += prepare archprepare prepare0 prepare1 prepare2 prepare3 + +# prepare3 is used to check if we are building in a separate output directory, +# and if so do: +# 1) Check that make has not been executed in the kernel src $(srctree) +prepare3: include/config/kernel.release +ifneq ($(KBUILD_SRC),) + @$(kecho) ' Using $(srctree) as source for kernel' + $(Q)if [ -f $(srctree)/.config -o -d $(srctree)/include/config ]; then \ + echo " $(srctree) is not clean, please run 'make mrproper'"; \ + echo " in the '$(srctree)' directory.";\ + /bin/false; \ + fi; +endif + +# prepare2 creates a makefile if using a separate output directory +prepare2: prepare3 outputmakefile asm-generic + +prepare1: prepare2 include/linux/version.h include/generated/utsrelease.h \ + include/config/auto.conf + $(cmd_crmodverdir) + +archprepare: archheaders archscripts prepare1 scripts_basic + +prepare0: archprepare FORCE + $(Q)$(MAKE) $(build)=. + +# All the preparing.. +prepare: prepare0 + +# Generate some files +# --------------------------------------------------------------------------- + +# KERNELRELEASE can change from a few different places, meaning version.h +# needs to be updated, so this check is forced on all builds + +uts_len := 64 +define filechk_utsrelease.h + if [ `echo -n "$(KERNELRELEASE)" | wc -c ` -gt $(uts_len) ]; then \ + echo '"$(KERNELRELEASE)" exceeds $(uts_len) characters' >&2; \ + exit 1; \ + fi; \ + (echo \#define UTS_RELEASE \"$(KERNELRELEASE)\";) +endef + +define filechk_version.h + (echo \#define LINUX_VERSION_CODE $(shell \ + expr $(VERSION) \* 65536 + 0$(PATCHLEVEL) \* 256 + 0$(SUBLEVEL)); \ + echo '#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))';) +endef + +include/linux/version.h: $(srctree)/Makefile FORCE + $(call filechk,version.h) + +include/generated/utsrelease.h: include/config/kernel.release FORCE + $(call filechk,utsrelease.h) + +PHONY += headerdep +headerdep: + $(Q)find $(srctree)/include/ -name '*.h' | xargs --max-args 1 \ + $(srctree)/scripts/headerdep.pl -I$(srctree)/include + +# --------------------------------------------------------------------------- + +PHONY += depend dep +depend dep: + @echo '*** Warning: make $@ is unnecessary now.' + +# --------------------------------------------------------------------------- +# Firmware install +INSTALL_FW_PATH=$(INSTALL_MOD_PATH)/lib/firmware +export INSTALL_FW_PATH + +PHONY += firmware_install +firmware_install: FORCE + @mkdir -p $(objtree)/firmware + $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.fwinst obj=firmware __fw_install + +# --------------------------------------------------------------------------- +# Kernel headers + +#Default location for installed headers +export INSTALL_HDR_PATH = $(objtree)/usr + +hdr-inst := -rR -f $(srctree)/scripts/Makefile.headersinst obj + +# If we do an all arch process set dst to asm-$(hdr-arch) +hdr-dst = $(if $(KBUILD_HEADERS), dst=include/asm-$(hdr-arch), dst=include/asm) + +PHONY += archheaders +archheaders: + +PHONY += archscripts +archscripts: + +PHONY += __headers +__headers: include/linux/version.h scripts_basic asm-generic archheaders archscripts FORCE + $(Q)$(MAKE) $(build)=scripts build_unifdef + +PHONY += headers_install_all +headers_install_all: + $(Q)$(CONFIG_SHELL) $(srctree)/scripts/headers.sh install + +PHONY += headers_install +headers_install: __headers + $(if $(wildcard $(srctree)/arch/$(hdr-arch)/include/asm/Kbuild),, \ + $(error Headers not exportable for the $(SRCARCH) architecture)) + $(Q)$(MAKE) $(hdr-inst)=include + $(Q)$(MAKE) $(hdr-inst)=arch/$(hdr-arch)/include/asm $(hdr-dst) + +PHONY += headers_check_all +headers_check_all: headers_install_all + $(Q)$(CONFIG_SHELL) $(srctree)/scripts/headers.sh check + +PHONY += headers_check +headers_check: headers_install + $(Q)$(MAKE) $(hdr-inst)=include HDRCHECK=1 + $(Q)$(MAKE) $(hdr-inst)=arch/$(hdr-arch)/include/asm $(hdr-dst) HDRCHECK=1 + +# --------------------------------------------------------------------------- +# Modules + +ifdef CONFIG_MODULES + +# By default, build modules as well + +all: modules + +# Build modules +# +# A module can be listed more than once in obj-m resulting in +# duplicate lines in modules.order files. Those are removed +# using awk while concatenating to the final file. + +PHONY += modules +modules: $(vmlinux-dirs) $(if $(KBUILD_BUILTIN),vmlinux) modules.builtin + $(Q)$(AWK) '!x[$$0]++' $(vmlinux-dirs:%=$(objtree)/%/modules.order) > $(objtree)/modules.order + @$(kecho) ' Building modules, stage 2.'; + $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost + $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.fwinst obj=firmware __fw_modbuild + +modules.builtin: $(vmlinux-dirs:%=%/modules.builtin) + $(Q)$(AWK) '!x[$$0]++' $^ > $(objtree)/modules.builtin + +%/modules.builtin: include/config/auto.conf + $(Q)$(MAKE) $(modbuiltin)=$* + + +# Target to prepare building external modules +PHONY += modules_prepare +modules_prepare: prepare scripts + +# Target to install modules +PHONY += modules_install +modules_install: _modinst_ _modinst_post + +PHONY += _modinst_ +_modinst_: + @rm -rf $(MODLIB)/kernel + @rm -f $(MODLIB)/source + @mkdir -p $(MODLIB)/kernel + @ln -s $(srctree) $(MODLIB)/source + @if [ ! $(objtree) -ef $(MODLIB)/build ]; then \ + rm -f $(MODLIB)/build ; \ + ln -s $(objtree) $(MODLIB)/build ; \ + fi + @cp -f $(objtree)/modules.order $(MODLIB)/ + @cp -f $(objtree)/modules.builtin $(MODLIB)/ + $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modinst + +# This depmod is only for convenience to give the initial +# boot a modules.dep even before / is mounted read-write. However the +# boot script depmod is the master version. +PHONY += _modinst_post +_modinst_post: _modinst_ + $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.fwinst obj=firmware __fw_modinst + $(call cmd,depmod) + +else # CONFIG_MODULES + +# Modules not configured +# --------------------------------------------------------------------------- + +modules modules_install: FORCE + @echo + @echo "The present kernel configuration has modules disabled." + @echo "Type 'make config' and enable loadable module support." + @echo "Then build a kernel with module support enabled." + @echo + @exit 1 + +endif # CONFIG_MODULES + +### +# Cleaning is done on three levels. +# make clean Delete most generated files +# Leave enough to build external modules +# make mrproper Delete the current configuration, and all generated files +# make distclean Remove editor backup files, patch leftover files and the like + +# Directories & files removed with 'make clean' +CLEAN_DIRS += $(MODVERDIR) + +# Directories & files removed with 'make mrproper' +MRPROPER_DIRS += include/config usr/include include/generated \ + arch/*/include/generated +MRPROPER_FILES += .config .config.old .version .old_version \ + include/linux/version.h \ + Module.symvers tags TAGS cscope* GPATH GTAGS GRTAGS GSYMS + +# clean - Delete most, but leave enough to build external modules +# +clean: rm-dirs := $(CLEAN_DIRS) +clean: rm-files := $(CLEAN_FILES) +clean-dirs := $(addprefix _clean_, . $(vmlinux-alldirs) Documentation samples) + +PHONY += $(clean-dirs) clean archclean +$(clean-dirs): + $(Q)$(MAKE) $(clean)=$(patsubst _clean_%,%,$@) + +clean: archclean + +# mrproper - Delete all generated files, including .config +# +mrproper: rm-dirs := $(wildcard $(MRPROPER_DIRS)) +mrproper: rm-files := $(wildcard $(MRPROPER_FILES)) +mrproper-dirs := $(addprefix _mrproper_,Documentation/DocBook scripts) + +PHONY += $(mrproper-dirs) mrproper archmrproper +$(mrproper-dirs): + $(Q)$(MAKE) $(clean)=$(patsubst _mrproper_%,%,$@) + +mrproper: clean archmrproper $(mrproper-dirs) + $(call cmd,rmdirs) + $(call cmd,rmfiles) + +# distclean +# +PHONY += distclean + +distclean: mrproper + @find $(srctree) $(RCS_FIND_IGNORE) \ + \( -name '*.orig' -o -name '*.rej' -o -name '*~' \ + -o -name '*.bak' -o -name '#*#' -o -name '.*.orig' \ + -o -name '.*.rej' \ + -o -name '*%' -o -name '.*.cmd' -o -name 'core' \) \ + -type f -print | xargs rm -f + + +# Packaging of the kernel to various formats +# --------------------------------------------------------------------------- +# rpm target kept for backward compatibility +package-dir := $(srctree)/scripts/package + +%src-pkg: FORCE + $(Q)$(MAKE) $(build)=$(package-dir) $@ +%pkg: include/config/kernel.release FORCE + $(Q)$(MAKE) $(build)=$(package-dir) $@ +rpm: include/config/kernel.release FORCE + $(Q)$(MAKE) $(build)=$(package-dir) $@ + + +# Brief documentation of the typical targets used +# --------------------------------------------------------------------------- + +boards := $(wildcard $(srctree)/arch/$(SRCARCH)/configs/*_defconfig) +boards := $(notdir $(boards)) +board-dirs := $(dir $(wildcard $(srctree)/arch/$(SRCARCH)/configs/*/*_defconfig)) +board-dirs := $(sort $(notdir $(board-dirs:/=))) + +help: + @echo 'Cleaning targets:' + @echo ' clean - Remove most generated files but keep the config and' + @echo ' enough build support to build external modules' + @echo ' mrproper - Remove all generated files + config + various backup files' + @echo ' distclean - mrproper + remove editor backup and patch files' + @echo '' + @echo 'Configuration targets:' + @$(MAKE) -f $(srctree)/scripts/kconfig/Makefile help + @echo '' + @echo 'Other generic targets:' + @echo ' all - Build all targets marked with [*]' + @echo '* vmlinux - Build the bare kernel' + @echo '* modules - Build all modules' + @echo ' modules_install - Install all modules to INSTALL_MOD_PATH (default: /)' + @echo ' firmware_install- Install all firmware to INSTALL_FW_PATH' + @echo ' (default: $$(INSTALL_MOD_PATH)/lib/firmware)' + @echo ' dir/ - Build all files in dir and below' + @echo ' dir/file.[oisS] - Build specified target only' + @echo ' dir/file.lst - Build specified mixed source/assembly target only' + @echo ' (requires a recent binutils and recent build (System.map))' + @echo ' dir/file.ko - Build module including final link' + @echo ' modules_prepare - Set up for building external modules' + @echo ' tags/TAGS - Generate tags file for editors' + @echo ' cscope - Generate cscope index' + @echo ' gtags - Generate GNU GLOBAL index' + @echo ' kernelrelease - Output the release version string' + @echo ' kernelversion - Output the version stored in Makefile' + @echo ' headers_install - Install sanitised kernel headers to INSTALL_HDR_PATH'; \ + echo ' (default: $(INSTALL_HDR_PATH))'; \ + echo '' + @echo 'Static analysers' + @echo ' checkstack - Generate a list of stack hogs' + @echo ' namespacecheck - Name space analysis on compiled kernel' + @echo ' versioncheck - Sanity check on version.h usage' + @echo ' includecheck - Check for duplicate included header files' + @echo ' export_report - List the usages of all exported symbols' + @echo ' headers_check - Sanity check on exported headers' + @echo ' headerdep - Detect inclusion cycles in headers' + @$(MAKE) -f $(srctree)/scripts/Makefile.help checker-help + @echo '' + @echo 'Kernel packaging:' + @$(MAKE) $(build)=$(package-dir) help + @echo '' + @echo 'Documentation targets:' + @$(MAKE) -f $(srctree)/Documentation/DocBook/Makefile dochelp + @echo '' + @echo 'Architecture specific targets ($(SRCARCH)):' + @$(if $(archhelp),$(archhelp),\ + echo ' No architecture specific help defined for $(SRCARCH)') + @echo '' + @$(if $(boards), \ + $(foreach b, $(boards), \ + printf " %-24s - Build for %s\\n" $(b) $(subst _defconfig,,$(b));) \ + echo '') + @$(if $(board-dirs), \ + $(foreach b, $(board-dirs), \ + printf " %-16s - Show %s-specific targets\\n" help-$(b) $(b);) \ + printf " %-16s - Show all of the above\\n" help-boards; \ + echo '') + + @echo ' make V=0|1 [targets] 0 => quiet build (default), 1 => verbose build' + @echo ' make V=2 [targets] 2 => give reason for rebuild of target' + @echo ' make O=dir [targets] Locate all output files in "dir", including .config' + @echo ' make C=1 [targets] Check all c source with $$CHECK (sparse by default)' + @echo ' make C=2 [targets] Force check of all c source with $$CHECK' + @echo ' make RECORDMCOUNT_WARN=1 [targets] Warn about ignored mcount sections' + @echo ' make W=n [targets] Enable extra gcc checks, n=1,2,3 where' + @echo ' 1: warnings which may be relevant and do not occur too often' + @echo ' 2: warnings which occur quite often but may still be relevant' + @echo ' 3: more obscure warnings, can most likely be ignored' + @echo ' Multiple levels can be combined with W=12 or W=123' + @echo '' + @echo 'Execute "make" or "make all" to build all targets marked with [*] ' + @echo 'For further info see the ./README file' + + +help-board-dirs := $(addprefix help-,$(board-dirs)) + +help-boards: $(help-board-dirs) + +boards-per-dir = $(notdir $(wildcard $(srctree)/arch/$(SRCARCH)/configs/$*/*_defconfig)) + +$(help-board-dirs): help-%: + @echo 'Architecture specific targets ($(SRCARCH) $*):' + @$(if $(boards-per-dir), \ + $(foreach b, $(boards-per-dir), \ + printf " %-24s - Build for %s\\n" $*/$(b) $(subst _defconfig,,$(b));) \ + echo '') + + +# Documentation targets +# --------------------------------------------------------------------------- +%docs: scripts_basic FORCE + $(Q)$(MAKE) $(build)=scripts build_docproc + $(Q)$(MAKE) $(build)=Documentation/DocBook $@ + +else # KBUILD_EXTMOD + +### +# External module support. +# When building external modules the kernel used as basis is considered +# read-only, and no consistency checks are made and the make +# system is not used on the basis kernel. If updates are required +# in the basis kernel ordinary make commands (without M=...) must +# be used. +# +# The following are the only valid targets when building external +# modules. +# make M=dir clean Delete all automatically generated files +# make M=dir modules Make all modules in specified dir +# make M=dir Same as 'make M=dir modules' +# make M=dir modules_install +# Install the modules built in the module directory +# Assumes install directory is already created + +# We are always building modules +KBUILD_MODULES := 1 +PHONY += crmodverdir +crmodverdir: + $(cmd_crmodverdir) + +PHONY += $(objtree)/Module.symvers +$(objtree)/Module.symvers: + @test -e $(objtree)/Module.symvers || ( \ + echo; \ + echo " WARNING: Symbol version dump $(objtree)/Module.symvers"; \ + echo " is missing; modules will have no dependencies and modversions."; \ + echo ) + +module-dirs := $(addprefix _module_,$(KBUILD_EXTMOD)) +PHONY += $(module-dirs) modules +$(module-dirs): crmodverdir $(objtree)/Module.symvers + $(Q)$(MAKE) $(build)=$(patsubst _module_%,%,$@) + +modules: $(module-dirs) + @$(kecho) ' Building modules, stage 2.'; + $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost + +PHONY += modules_install +modules_install: _emodinst_ _emodinst_post + +install-dir := $(if $(INSTALL_MOD_DIR),$(INSTALL_MOD_DIR),extra) +PHONY += _emodinst_ +_emodinst_: + $(Q)mkdir -p $(MODLIB)/$(install-dir) + $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modinst + +PHONY += _emodinst_post +_emodinst_post: _emodinst_ + $(call cmd,depmod) + +clean-dirs := $(addprefix _clean_,$(KBUILD_EXTMOD)) + +PHONY += $(clean-dirs) clean +$(clean-dirs): + $(Q)$(MAKE) $(clean)=$(patsubst _clean_%,%,$@) + +clean: rm-dirs := $(MODVERDIR) +clean: rm-files := $(KBUILD_EXTMOD)/Module.symvers + +help: + @echo ' Building external modules.' + @echo ' Syntax: make -C path/to/kernel/src M=$$PWD target' + @echo '' + @echo ' modules - default target, build the module(s)' + @echo ' modules_install - install the module' + @echo ' clean - remove generated files in module directory only' + @echo '' + +# Dummies... +PHONY += prepare scripts +prepare: ; +scripts: ; +endif # KBUILD_EXTMOD + +clean: $(clean-dirs) + $(Q)$(CONFIG_SHELL) $(srctree)/scripts/link-vmlinux.sh clean + $(call cmd,rmdirs) + $(call cmd,rmfiles) + @find $(if $(KBUILD_EXTMOD), $(KBUILD_EXTMOD), .) $(RCS_FIND_IGNORE) \ + \( -name '*.[oas]' -o -name '*.ko' -o -name '.*.cmd' \ + -o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \ + -o -name '*.symtypes' -o -name 'modules.order' \ + -o -name modules.builtin -o -name '.tmp_*.o.*' \ + -o -name '*.gcno' \) -type f -print | xargs rm -f + +# Generate tags for editors +# --------------------------------------------------------------------------- +quiet_cmd_tags = GEN $@ + cmd_tags = $(CONFIG_SHELL) $(srctree)/scripts/tags.sh $@ + +tags TAGS cscope gtags: FORCE + $(call cmd,tags) + +# Scripts to check various things for consistency +# --------------------------------------------------------------------------- + +PHONY += includecheck versioncheck coccicheck namespacecheck export_report + +includecheck: + find $(srctree)/* $(RCS_FIND_IGNORE) \ + -name '*.[hcS]' -type f -print | sort \ + | xargs $(PERL) -w $(srctree)/scripts/checkincludes.pl + +versioncheck: + find $(srctree)/* $(RCS_FIND_IGNORE) \ + -name '*.[hcS]' -type f -print | sort \ + | xargs $(PERL) -w $(srctree)/scripts/checkversion.pl + +coccicheck: + $(Q)$(CONFIG_SHELL) $(srctree)/scripts/$@ + +namespacecheck: + $(PERL) $(srctree)/scripts/namespace.pl + +export_report: + $(PERL) $(srctree)/scripts/export_report.pl + +endif #ifeq ($(config-targets),1) +endif #ifeq ($(mixed-targets),1) + +PHONY += checkstack kernelrelease kernelversion + +# UML needs a little special treatment here. It wants to use the host +# toolchain, so needs $(SUBARCH) passed to checkstack.pl. Everyone +# else wants $(ARCH), including people doing cross-builds, which means +# that $(SUBARCH) doesn't work here. +ifeq ($(ARCH), um) +CHECKSTACK_ARCH := $(SUBARCH) +else +CHECKSTACK_ARCH := $(ARCH) +endif +checkstack: + $(OBJDUMP) -d vmlinux $$(find . -name '*.ko') | \ + $(PERL) $(src)/scripts/checkstack.pl $(CHECKSTACK_ARCH) + +kernelrelease: + @echo "$(KERNELVERSION)$$($(CONFIG_SHELL) $(srctree)/scripts/setlocalversion $(srctree))" + +kernelversion: + @echo $(KERNELVERSION) + +# Clear a bunch of variables before executing the submake +tools/: FORCE + $(Q)$(MAKE) LDFLAGS= MAKEFLAGS= -C $(src)/tools/ + +tools/%: FORCE + $(Q)$(MAKE) LDFLAGS= MAKEFLAGS= -C $(src)/tools/ $* + +# Single targets +# --------------------------------------------------------------------------- +# Single targets are compatible with: +# - build with mixed source and output +# - build with separate output dir 'make O=...' +# - external modules +# +# target-dir => where to store outputfile +# build-dir => directory in kernel source tree to use + +ifeq ($(KBUILD_EXTMOD),) + build-dir = $(patsubst %/,%,$(dir $@)) + target-dir = $(dir $@) +else + zap-slash=$(filter-out .,$(patsubst %/,%,$(dir $@))) + build-dir = $(KBUILD_EXTMOD)$(if $(zap-slash),/$(zap-slash)) + target-dir = $(if $(KBUILD_EXTMOD),$(dir $<),$(dir $@)) +endif + +%.s: %.c prepare scripts FORCE + $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@) +%.i: %.c prepare scripts FORCE + $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@) +%.o: %.c prepare scripts FORCE + $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@) +%.lst: %.c prepare scripts FORCE + $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@) +%.s: %.S prepare scripts FORCE + $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@) +%.o: %.S prepare scripts FORCE + $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@) +%.symtypes: %.c prepare scripts FORCE + $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@) + +# Modules +/: prepare scripts FORCE + $(cmd_crmodverdir) + $(Q)$(MAKE) KBUILD_MODULES=$(if $(CONFIG_MODULES),1) \ + $(build)=$(build-dir) +%/: prepare scripts FORCE + $(cmd_crmodverdir) + $(Q)$(MAKE) KBUILD_MODULES=$(if $(CONFIG_MODULES),1) \ + $(build)=$(build-dir) +%.ko: prepare scripts FORCE + $(cmd_crmodverdir) + $(Q)$(MAKE) KBUILD_MODULES=$(if $(CONFIG_MODULES),1) \ + $(build)=$(build-dir) $(@:.ko=.o) + $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost + +# FIXME Should go into a make.lib or something +# =========================================================================== + +quiet_cmd_rmdirs = $(if $(wildcard $(rm-dirs)),CLEAN $(wildcard $(rm-dirs))) + cmd_rmdirs = rm -rf $(rm-dirs) + +quiet_cmd_rmfiles = $(if $(wildcard $(rm-files)),CLEAN $(wildcard $(rm-files))) + cmd_rmfiles = rm -f $(rm-files) + +# Run depmod only if we have System.map and depmod is executable +quiet_cmd_depmod = DEPMOD $(KERNELRELEASE) + cmd_depmod = $(CONFIG_SHELL) $(srctree)/scripts/depmod.sh $(DEPMOD) \ + $(KERNELRELEASE) + +# Create temporary dir for module support files +# clean it up only when building all modules +cmd_crmodverdir = $(Q)mkdir -p $(MODVERDIR) \ + $(if $(KBUILD_MODULES),; rm -f $(MODVERDIR)/*) + +# read all saved command lines + +targets := $(wildcard $(sort $(targets))) +cmd_files := $(wildcard .*.cmd $(foreach f,$(targets),$(dir $(f)).$(notdir $(f)).cmd)) + +ifneq ($(cmd_files),) + $(cmd_files): ; # Do not try to update included dependency files + include $(cmd_files) +endif + +# Shorthand for $(Q)$(MAKE) -f scripts/Makefile.clean obj=dir +# Usage: +# $(Q)$(MAKE) $(clean)=dir +clean := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.clean obj + +endif # skip-makefile + +PHONY += FORCE +FORCE: + +# Declare the contents of the .PHONY variable as phony. We keep that +# information in a variable so we can use it in if_changed and friends. +.PHONY: $(PHONY) diff --git a/l4/tool/kconfig/README b/l4/tool/kconfig/README new file mode 100644 index 00000000..cebd46b7 --- /dev/null +++ b/l4/tool/kconfig/README @@ -0,0 +1,3 @@ + +kconfig taken from vanilla Linux 3.5, and slightly patched. + diff --git a/l4/tool/kconfig/scripts/Kbuild.include b/l4/tool/kconfig/scripts/Kbuild.include new file mode 100644 index 00000000..6a3ee981 --- /dev/null +++ b/l4/tool/kconfig/scripts/Kbuild.include @@ -0,0 +1,278 @@ +#### +# kbuild: Generic definitions + +# Convenient variables +comma := , +squote := ' +empty := +space := $(empty) $(empty) + +### +# Name of target with a '.' as filename prefix. foo/bar.o => foo/.bar.o +dot-target = $(dir $@).$(notdir $@) + +### +# The temporary file to save gcc -MD generated dependencies must not +# contain a comma +depfile = $(subst $(comma),_,$(dot-target).d) + +### +# filename of target with directory and extension stripped +basetarget = $(basename $(notdir $@)) + +### +# filename of first prerequisite with directory and extension stripped +baseprereq = $(basename $(notdir $<)) + +### +# Escape single quote for use in echo statements +escsq = $(subst $(squote),'\$(squote)',$1) + +### +# Easy method for doing a status message + kecho := : + quiet_kecho := echo +silent_kecho := : +kecho := $($(quiet)kecho) + +### +# filechk is used to check if the content of a generated file is updated. +# Sample usage: +# define filechk_sample +# echo $KERNELRELEASE +# endef +# version.h : Makefile +# $(call filechk,sample) +# The rule defined shall write to stdout the content of the new file. +# The existing file will be compared with the new one. +# - If no file exist it is created +# - If the content differ the new file is used +# - If they are equal no change, and no timestamp update +# - stdin is piped in from the first prerequisite ($<) so one has +# to specify a valid file as first prerequisite (often the kbuild file) +define filechk + $(Q)set -e; \ + $(kecho) ' CHK $@'; \ + mkdir -p $(dir $@); \ + $(filechk_$(1)) < $< > $@.tmp; \ + if [ -r $@ ] && cmp -s $@ $@.tmp; then \ + rm -f $@.tmp; \ + else \ + $(kecho) ' UPD $@'; \ + mv -f $@.tmp $@; \ + fi +endef + +###### +# gcc support functions +# See documentation in Documentation/kbuild/makefiles.txt + +# cc-cross-prefix +# Usage: CROSS_COMPILE := $(call cc-cross-prefix, m68k-linux-gnu- m68k-linux-) +# Return first prefix where a prefix$(CC) is found in PATH. +# If no $(CC) found in PATH with listed prefixes return nothing +cc-cross-prefix = \ + $(word 1, $(foreach c,$(1), \ + $(shell set -e; \ + if (which $(strip $(c))$(CC)) > /dev/null 2>&1 ; then \ + echo $(c); \ + fi))) + +# output directory for tests below +TMPOUT := $(if $(KBUILD_EXTMOD),$(firstword $(KBUILD_EXTMOD))/) + +# try-run +# Usage: option = $(call try-run, $(CC)...-o "$$TMP",option-ok,otherwise) +# Exit code chooses option. "$$TMP" is can be used as temporary file and +# is automatically cleaned up. +try-run = $(shell set -e; \ + TMP="$(TMPOUT).$$$$.tmp"; \ + TMPO="$(TMPOUT).$$$$.o"; \ + if ($(1)) >/dev/null 2>&1; \ + then echo "$(2)"; \ + else echo "$(3)"; \ + fi; \ + rm -f "$$TMP" "$$TMPO") + +# as-option +# Usage: cflags-y += $(call as-option,-Wa$(comma)-isa=foo,) + +as-option = $(call try-run,\ + $(CC) $(KBUILD_CFLAGS) $(1) -c -xassembler /dev/null -o "$$TMP",$(1),$(2)) + +# as-instr +# Usage: cflags-y += $(call as-instr,instr,option1,option2) + +as-instr = $(call try-run,\ + printf "%b\n" "$(1)" | $(CC) $(KBUILD_AFLAGS) -c -xassembler -o "$$TMP" -,$(2),$(3)) + +# cc-option +# Usage: cflags-y += $(call cc-option,-march=winchip-c6,-march=i586) + +cc-option = $(call try-run,\ + $(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) $(1) -c -xc /dev/null -o "$$TMP",$(1),$(2)) + +# cc-option-yn +# Usage: flag := $(call cc-option-yn,-march=winchip-c6) +cc-option-yn = $(call try-run,\ + $(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) $(1) -c -xc /dev/null -o "$$TMP",y,n) + +# cc-option-align +# Prefix align with either -falign or -malign +cc-option-align = $(subst -functions=0,,\ + $(call cc-option,-falign-functions=0,-malign-functions=0)) + +# cc-disable-warning +# Usage: cflags-y += $(call cc-disable-warning,unused-but-set-variable) +cc-disable-warning = $(call try-run,\ + $(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) -W$(strip $(1)) -c -xc /dev/null -o "$$TMP",-Wno-$(strip $(1))) + +# cc-version +# Usage gcc-ver := $(call cc-version) +cc-version = $(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-version.sh $(CC)) + +# cc-fullversion +# Usage gcc-ver := $(call cc-fullversion) +cc-fullversion = $(shell $(CONFIG_SHELL) \ + $(srctree)/scripts/gcc-version.sh -p $(CC)) + +# cc-ifversion +# Usage: EXTRA_CFLAGS += $(call cc-ifversion, -lt, 0402, -O1) +cc-ifversion = $(shell [ $(call cc-version, $(CC)) $(1) $(2) ] && echo $(3)) + +# cc-ldoption +# Usage: ldflags += $(call cc-ldoption, -Wl$(comma)--hash-style=both) +cc-ldoption = $(call try-run,\ + $(CC) $(1) -nostdlib -xc /dev/null -o "$$TMP",$(1),$(2)) + +# ld-option +# Usage: LDFLAGS += $(call ld-option, -X) +ld-option = $(call try-run,\ + $(CC) /dev/null -c -o "$$TMPO" ; $(LD) $(1) "$$TMPO" -o "$$TMP",$(1),$(2)) + +# ar-option +# Usage: KBUILD_ARFLAGS := $(call ar-option,D) +# Important: no spaces around options +ar-option = $(call try-run, $(AR) rc$(1) "$$TMP",$(1),$(2)) + +###### + +### +# Shorthand for $(Q)$(MAKE) -f scripts/Makefile.build obj= +# Usage: +# $(Q)$(MAKE) $(build)=dir +build := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.build obj + +### +# Shorthand for $(Q)$(MAKE) -f scripts/Makefile.modbuiltin obj= +# Usage: +# $(Q)$(MAKE) $(modbuiltin)=dir +modbuiltin := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.modbuiltin obj + +# Prefix -I with $(srctree) if it is not an absolute path. +# skip if -I has no parameter +addtree = $(if $(patsubst -I%,%,$(1)), \ +$(if $(filter-out -I/%,$(1)),$(patsubst -I%,-I$(srctree)/%,$(1))) $(1)) + +# Find all -I options and call addtree +flags = $(foreach o,$($(1)),$(if $(filter -I%,$(o)),$(call addtree,$(o)),$(o))) + +# echo command. +# Short version is used, if $(quiet) equals `quiet_', otherwise full one. +echo-cmd = $(if $($(quiet)cmd_$(1)),\ + echo ' $(call escsq,$($(quiet)cmd_$(1)))$(echo-why)';) + +# printing commands +cmd = @$(echo-cmd) $(cmd_$(1)) + +# Add $(obj)/ for paths that are not absolute +objectify = $(foreach o,$(1),$(if $(filter /%,$(o)),$(o),$(obj)/$(o))) + +### +# if_changed - execute command if any prerequisite is newer than +# target, or command line has changed +# if_changed_dep - as if_changed, but uses fixdep to reveal dependencies +# including used config symbols +# if_changed_rule - as if_changed but execute rule instead +# See Documentation/kbuild/makefiles.txt for more info + +ifneq ($(KBUILD_NOCMDDEP),1) +# Check if both arguments has same arguments. Result is empty string if equal. +# User may override this check using make KBUILD_NOCMDDEP=1 +arg-check = $(strip $(filter-out $(cmd_$(1)), $(cmd_$@)) \ + $(filter-out $(cmd_$@), $(cmd_$(1))) ) +else +arg-check = $(if $(strip $(cmd_$@)),,1) +endif + +# >'< substitution is for echo to work, +# >$< substitution to preserve $ when reloading .cmd file +# note: when using inline perl scripts [perl -e '...$$t=1;...'] +# in $(cmd_xxx) double $$ your perl vars +make-cmd = $(subst \#,\\\#,$(subst $$,$$$$,$(call escsq,$(cmd_$(1))))) + +# Find any prerequisites that is newer than target or that does not exist. +# PHONY targets skipped in both cases. +any-prereq = $(filter-out $(PHONY),$?) $(filter-out $(PHONY) $(wildcard $^),$^) + +# Execute command if command has changed or prerequisite(s) are updated. +# +if_changed = $(if $(strip $(any-prereq) $(arg-check)), \ + @set -e; \ + $(echo-cmd) $(cmd_$(1)); \ + echo 'cmd_$@ := $(make-cmd)' > $(dot-target).cmd) + +# Execute the command and also postprocess generated .d dependencies file. +if_changed_dep = $(if $(strip $(any-prereq) $(arg-check) ), \ + @set -e; \ + $(echo-cmd) $(cmd_$(1)); \ + scripts/basic/fixdep $(depfile) $@ '$(make-cmd)' > $(dot-target).tmp;\ + rm -f $(depfile); \ + mv -f $(dot-target).tmp $(dot-target).cmd) + +# Usage: $(call if_changed_rule,foo) +# Will check if $(cmd_foo) or any of the prerequisites changed, +# and if so will execute $(rule_foo). +if_changed_rule = $(if $(strip $(any-prereq) $(arg-check) ), \ + @set -e; \ + $(rule_$(1))) + +### +# why - tell why a a target got build +# enabled by make V=2 +# Output (listed in the order they are checked): +# (1) - due to target is PHONY +# (2) - due to target missing +# (3) - due to: file1.h file2.h +# (4) - due to command line change +# (5) - due to missing .cmd file +# (6) - due to target not in $(targets) +# (1) PHONY targets are always build +# (2) No target, so we better build it +# (3) Prerequisite is newer than target +# (4) The command line stored in the file named dir/.target.cmd +# differed from actual command line. This happens when compiler +# options changes +# (5) No dir/.target.cmd file (used to store command line) +# (6) No dir/.target.cmd file and target not listed in $(targets) +# This is a good hint that there is a bug in the kbuild file +ifeq ($(KBUILD_VERBOSE),2) +why = \ + $(if $(filter $@, $(PHONY)),- due to target is PHONY, \ + $(if $(wildcard $@), \ + $(if $(strip $(any-prereq)),- due to: $(any-prereq), \ + $(if $(arg-check), \ + $(if $(cmd_$@),- due to command line change, \ + $(if $(filter $@, $(targets)), \ + - due to missing .cmd file, \ + - due to $(notdir $@) not in $$(targets) \ + ) \ + ) \ + ) \ + ), \ + - due to target missing \ + ) \ + ) + +echo-why = $(call escsq, $(strip $(why))) +endif diff --git a/l4/tool/kconfig/scripts/Makefile b/l4/tool/kconfig/scripts/Makefile new file mode 100644 index 00000000..a55b0067 --- /dev/null +++ b/l4/tool/kconfig/scripts/Makefile @@ -0,0 +1,40 @@ +### +# scripts contains sources for various helper programs used throughout +# the kernel for the build process. +# --------------------------------------------------------------------------- +# kallsyms: Find all symbols in vmlinux +# pnmttologo: Convert pnm files to logo files +# conmakehash: Create chartable +# conmakehash: Create arrays for initializing the kernel console tables +# docproc: Used in Documentation/DocBook + +HOST_EXTRACFLAGS += -I$(srctree)/tools/include + +hostprogs-$(CONFIG_KALLSYMS) += kallsyms +hostprogs-$(CONFIG_LOGO) += pnmtologo +hostprogs-$(CONFIG_VT) += conmakehash +hostprogs-$(CONFIG_IKCONFIG) += bin2c +hostprogs-$(BUILD_C_RECORDMCOUNT) += recordmcount +hostprogs-$(CONFIG_BUILDTIME_EXTABLE_SORT) += sortextable + +HOSTCFLAGS_sortextable.o = -I$(srctree)/tools/include + +always := $(hostprogs-y) $(hostprogs-m) + +# The following hostprogs-y programs are only build on demand +hostprogs-y += unifdef docproc + +# These targets are used internally to avoid "is up to date" messages +PHONY += build_unifdef +build_unifdef: scripts/unifdef FORCE + @: +build_docproc: scripts/docproc FORCE + @: + +subdir-$(CONFIG_MODVERSIONS) += genksyms +subdir-y += mod +subdir-$(CONFIG_SECURITY_SELINUX) += selinux +subdir-$(CONFIG_DTC) += dtc + +# Let clean descend into subdirs +subdir- += basic kconfig package selinux diff --git a/l4/tool/kconfig/scripts/Makefile.build b/l4/tool/kconfig/scripts/Makefile.build new file mode 100644 index 00000000..ff1720d2 --- /dev/null +++ b/l4/tool/kconfig/scripts/Makefile.build @@ -0,0 +1,467 @@ +# ========================================================================== +# Building +# ========================================================================== + +src := $(obj) + +PHONY := __build +__build: + +# Init all relevant variables used in kbuild files so +# 1) they have correct type +# 2) they do not inherit any value from the environment +obj-y := +obj-m := +lib-y := +lib-m := +always := +targets := +subdir-y := +subdir-m := +EXTRA_AFLAGS := +EXTRA_CFLAGS := +EXTRA_CPPFLAGS := +EXTRA_LDFLAGS := +asflags-y := +ccflags-y := +cppflags-y := +ldflags-y := + +subdir-asflags-y := +subdir-ccflags-y := + +# Read auto.conf if it exists, otherwise ignore +-include include/config/auto.conf + +include scripts/Kbuild.include + +# For backward compatibility check that these variables do not change +save-cflags := $(CFLAGS) + +# The filename Kbuild has precedence over Makefile +kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src)) +kbuild-file := $(if $(wildcard $(kbuild-dir)/Kbuild),$(kbuild-dir)/Kbuild,$(kbuild-dir)/Makefile) +include $(kbuild-file) + +# If the save-* variables changed error out +ifeq ($(KBUILD_NOPEDANTIC),) + ifneq ("$(save-cflags)","$(CFLAGS)") + $(error CFLAGS was changed in "$(kbuild-file)". Fix it to use ccflags-y) + endif +endif + +# +# make W=... settings +# +# W=1 - warnings that may be relevant and does not occur too often +# W=2 - warnings that occur quite often but may still be relevant +# W=3 - the more obscure warnings, can most likely be ignored +# +# $(call cc-option, -W...) handles gcc -W.. options which +# are not supported by all versions of the compiler +ifdef KBUILD_ENABLE_EXTRA_GCC_CHECKS +warning- := $(empty) + +warning-1 := -Wextra -Wunused -Wno-unused-parameter +warning-1 += -Wmissing-declarations +warning-1 += -Wmissing-format-attribute +warning-1 += -Wmissing-prototypes +warning-1 += -Wold-style-definition +warning-1 += $(call cc-option, -Wmissing-include-dirs) +warning-1 += $(call cc-option, -Wunused-but-set-variable) +warning-1 += $(call cc-disable-warning, missing-field-initializers) + +warning-2 := -Waggregate-return +warning-2 += -Wcast-align +warning-2 += -Wdisabled-optimization +warning-2 += -Wnested-externs +warning-2 += -Wshadow +warning-2 += $(call cc-option, -Wlogical-op) +warning-2 += $(call cc-option, -Wmissing-field-initializers) + +warning-3 := -Wbad-function-cast +warning-3 += -Wcast-qual +warning-3 += -Wconversion +warning-3 += -Wpacked +warning-3 += -Wpadded +warning-3 += -Wpointer-arith +warning-3 += -Wredundant-decls +warning-3 += -Wswitch-default +warning-3 += $(call cc-option, -Wpacked-bitfield-compat) +warning-3 += $(call cc-option, -Wvla) + +warning := $(warning-$(findstring 1, $(KBUILD_ENABLE_EXTRA_GCC_CHECKS))) +warning += $(warning-$(findstring 2, $(KBUILD_ENABLE_EXTRA_GCC_CHECKS))) +warning += $(warning-$(findstring 3, $(KBUILD_ENABLE_EXTRA_GCC_CHECKS))) + +ifeq ("$(strip $(warning))","") + $(error W=$(KBUILD_ENABLE_EXTRA_GCC_CHECKS) is unknown) +endif + +KBUILD_CFLAGS += $(warning) +endif + +include scripts/Makefile.lib + +ifdef host-progs +ifneq ($(hostprogs-y),$(host-progs)) +$(warning kbuild: $(obj)/Makefile - Usage of host-progs is deprecated. Please replace with hostprogs-y!) +hostprogs-y += $(host-progs) +endif +endif + +# Do not include host rules unless needed +ifneq ($(hostprogs-y)$(hostprogs-m),) +include scripts/Makefile.host +endif + +ifneq ($(KBUILD_SRC),) +# Create output directory if not already present +_dummy := $(shell [ -d $(obj) ] || mkdir -p $(obj)) + +# Create directories for object files if directory does not exist +# Needed when obj-y := dir/file.o syntax is used +_dummy := $(foreach d,$(obj-dirs), $(shell [ -d $(d) ] || mkdir -p $(d))) +endif + +ifndef obj +$(warning kbuild: Makefile.build is included improperly) +endif + +# =========================================================================== + +ifneq ($(strip $(lib-y) $(lib-m) $(lib-n) $(lib-)),) +lib-target := $(obj)/lib.a +endif + +ifneq ($(strip $(obj-y) $(obj-m) $(obj-n) $(obj-) $(subdir-m) $(lib-target)),) +builtin-target := $(obj)/built-in.o +endif + +modorder-target := $(obj)/modules.order + +# We keep a list of all modules in $(MODVERDIR) + +__build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y)) \ + $(if $(KBUILD_MODULES),$(obj-m) $(modorder-target)) \ + $(subdir-ym) $(always) + @: + +# Linus' kernel sanity checking tool +ifneq ($(KBUILD_CHECKSRC),0) + ifeq ($(KBUILD_CHECKSRC),2) + quiet_cmd_force_checksrc = CHECK $< + cmd_force_checksrc = $(CHECK) $(CHECKFLAGS) $(c_flags) $< ; + else + quiet_cmd_checksrc = CHECK $< + cmd_checksrc = $(CHECK) $(CHECKFLAGS) $(c_flags) $< ; + endif +endif + +# Do section mismatch analysis for each module/built-in.o +ifdef CONFIG_DEBUG_SECTION_MISMATCH + cmd_secanalysis = ; scripts/mod/modpost $@ +endif + +# Compile C sources (.c) +# --------------------------------------------------------------------------- + +# Default is built-in, unless we know otherwise +modkern_cflags = \ + $(if $(part-of-module), \ + $(KBUILD_CFLAGS_MODULE) $(CFLAGS_MODULE), \ + $(KBUILD_CFLAGS_KERNEL) $(CFLAGS_KERNEL)) +quiet_modtag := $(empty) $(empty) + +$(real-objs-m) : part-of-module := y +$(real-objs-m:.o=.i) : part-of-module := y +$(real-objs-m:.o=.s) : part-of-module := y +$(real-objs-m:.o=.lst): part-of-module := y + +$(real-objs-m) : quiet_modtag := [M] +$(real-objs-m:.o=.i) : quiet_modtag := [M] +$(real-objs-m:.o=.s) : quiet_modtag := [M] +$(real-objs-m:.o=.lst): quiet_modtag := [M] + +$(obj-m) : quiet_modtag := [M] + +# Default for not multi-part modules +modname = $(basetarget) + +$(multi-objs-m) : modname = $(modname-multi) +$(multi-objs-m:.o=.i) : modname = $(modname-multi) +$(multi-objs-m:.o=.s) : modname = $(modname-multi) +$(multi-objs-m:.o=.lst) : modname = $(modname-multi) +$(multi-objs-y) : modname = $(modname-multi) +$(multi-objs-y:.o=.i) : modname = $(modname-multi) +$(multi-objs-y:.o=.s) : modname = $(modname-multi) +$(multi-objs-y:.o=.lst) : modname = $(modname-multi) + +quiet_cmd_cc_s_c = CC $(quiet_modtag) $@ +cmd_cc_s_c = $(CC) $(c_flags) -fverbose-asm -S -o $@ $< + +$(obj)/%.s: $(src)/%.c FORCE + $(call if_changed_dep,cc_s_c) + +quiet_cmd_cc_i_c = CPP $(quiet_modtag) $@ +cmd_cc_i_c = $(CPP) $(c_flags) -o $@ $< + +$(obj)/%.i: $(src)/%.c FORCE + $(call if_changed_dep,cc_i_c) + +cmd_gensymtypes = \ + $(CPP) -D__GENKSYMS__ $(c_flags) $< | \ + $(GENKSYMS) $(if $(1), -T $(2)) -a $(ARCH) \ + $(if $(KBUILD_PRESERVE),-p) \ + -r $(firstword $(wildcard $(2:.symtypes=.symref) /dev/null)) + +quiet_cmd_cc_symtypes_c = SYM $(quiet_modtag) $@ +cmd_cc_symtypes_c = \ + set -e; \ + $(call cmd_gensymtypes,true,$@) >/dev/null; \ + test -s $@ || rm -f $@ + +$(obj)/%.symtypes : $(src)/%.c FORCE + $(call cmd,cc_symtypes_c) + +# C (.c) files +# The C file is compiled and updated dependency information is generated. +# (See cmd_cc_o_c + relevant part of rule_cc_o_c) + +quiet_cmd_cc_o_c = CC $(quiet_modtag) $@ + +ifndef CONFIG_MODVERSIONS +cmd_cc_o_c = $(CC) $(c_flags) -c -o $@ $< + +else +# When module versioning is enabled the following steps are executed: +# o compile a .tmp_.o from .c +# o if .tmp_.o doesn't contain a __ksymtab version, i.e. does +# not export symbols, we just rename .tmp_.o to .o and +# are done. +# o otherwise, we calculate symbol versions using the good old +# genksyms on the preprocessed source and postprocess them in a way +# that they are usable as a linker script +# o generate .o from .tmp_.o using the linker to +# replace the unresolved symbols __crc_exported_symbol with +# the actual value of the checksum generated by genksyms + +cmd_cc_o_c = $(CC) $(c_flags) -c -o $(@D)/.tmp_$(@F) $< +cmd_modversions = \ + if $(OBJDUMP) -h $(@D)/.tmp_$(@F) | grep -q __ksymtab; then \ + $(call cmd_gensymtypes,$(KBUILD_SYMTYPES),$(@:.o=.symtypes)) \ + > $(@D)/.tmp_$(@F:.o=.ver); \ + \ + $(LD) $(LDFLAGS) -r -o $@ $(@D)/.tmp_$(@F) \ + -T $(@D)/.tmp_$(@F:.o=.ver); \ + rm -f $(@D)/.tmp_$(@F) $(@D)/.tmp_$(@F:.o=.ver); \ + else \ + mv -f $(@D)/.tmp_$(@F) $@; \ + fi; +endif + +ifdef CONFIG_FTRACE_MCOUNT_RECORD +ifdef BUILD_C_RECORDMCOUNT +ifeq ("$(origin RECORDMCOUNT_WARN)", "command line") + RECORDMCOUNT_FLAGS = -w +endif +# Due to recursion, we must skip empty.o. +# The empty.o file is created in the make process in order to determine +# the target endianness and word size. It is made before all other C +# files, including recordmcount. +sub_cmd_record_mcount = \ + if [ $(@) != "scripts/mod/empty.o" ]; then \ + $(objtree)/scripts/recordmcount $(RECORDMCOUNT_FLAGS) "$(@)"; \ + fi; +recordmcount_source := $(srctree)/scripts/recordmcount.c \ + $(srctree)/scripts/recordmcount.h +else +sub_cmd_record_mcount = set -e ; perl $(srctree)/scripts/recordmcount.pl "$(ARCH)" \ + "$(if $(CONFIG_CPU_BIG_ENDIAN),big,little)" \ + "$(if $(CONFIG_64BIT),64,32)" \ + "$(OBJDUMP)" "$(OBJCOPY)" "$(CC) $(KBUILD_CFLAGS)" \ + "$(LD)" "$(NM)" "$(RM)" "$(MV)" \ + "$(if $(part-of-module),1,0)" "$(@)"; +recordmcount_source := $(srctree)/scripts/recordmcount.pl +endif +cmd_record_mcount = \ + if [ "$(findstring -pg,$(_c_flags))" = "-pg" ]; then \ + $(sub_cmd_record_mcount) \ + fi; +endif + +define rule_cc_o_c + $(call echo-cmd,checksrc) $(cmd_checksrc) \ + $(call echo-cmd,cc_o_c) $(cmd_cc_o_c); \ + $(cmd_modversions) \ + $(call echo-cmd,record_mcount) \ + $(cmd_record_mcount) \ + scripts/basic/fixdep $(depfile) $@ '$(call make-cmd,cc_o_c)' > \ + $(dot-target).tmp; \ + rm -f $(depfile); \ + mv -f $(dot-target).tmp $(dot-target).cmd +endef + +# Built-in and composite module parts +$(obj)/%.o: $(src)/%.c $(recordmcount_source) FORCE + $(call cmd,force_checksrc) + $(call if_changed_rule,cc_o_c) + +# Single-part modules are special since we need to mark them in $(MODVERDIR) + +$(single-used-m): $(obj)/%.o: $(src)/%.c $(recordmcount_source) FORCE + $(call cmd,force_checksrc) + $(call if_changed_rule,cc_o_c) + @{ echo $(@:.o=.ko); echo $@; } > $(MODVERDIR)/$(@F:.o=.mod) + +quiet_cmd_cc_lst_c = MKLST $@ + cmd_cc_lst_c = $(CC) $(c_flags) -g -c -o $*.o $< && \ + $(CONFIG_SHELL) $(srctree)/scripts/makelst $*.o \ + System.map $(OBJDUMP) > $@ + +$(obj)/%.lst: $(src)/%.c FORCE + $(call if_changed_dep,cc_lst_c) + +# Compile assembler sources (.S) +# --------------------------------------------------------------------------- + +modkern_aflags := $(KBUILD_AFLAGS_KERNEL) $(AFLAGS_KERNEL) + +$(real-objs-m) : modkern_aflags := $(KBUILD_AFLAGS_MODULE) $(AFLAGS_MODULE) +$(real-objs-m:.o=.s): modkern_aflags := $(KBUILD_AFLAGS_MODULE) $(AFLAGS_MODULE) + +quiet_cmd_as_s_S = CPP $(quiet_modtag) $@ +cmd_as_s_S = $(CPP) $(a_flags) -o $@ $< + +$(obj)/%.s: $(src)/%.S FORCE + $(call if_changed_dep,as_s_S) + +quiet_cmd_as_o_S = AS $(quiet_modtag) $@ +cmd_as_o_S = $(CC) $(a_flags) -c -o $@ $< + +$(obj)/%.o: $(src)/%.S FORCE + $(call if_changed_dep,as_o_S) + +targets += $(real-objs-y) $(real-objs-m) $(lib-y) +targets += $(extra-y) $(MAKECMDGOALS) $(always) + +# Linker scripts preprocessor (.lds.S -> .lds) +# --------------------------------------------------------------------------- +quiet_cmd_cpp_lds_S = LDS $@ + cmd_cpp_lds_S = $(CPP) $(cpp_flags) -P -C -U$(ARCH) \ + -D__ASSEMBLY__ -DLINKER_SCRIPT -o $@ $< + +$(obj)/%.lds: $(src)/%.lds.S FORCE + $(call if_changed_dep,cpp_lds_S) + +# Build the compiled-in targets +# --------------------------------------------------------------------------- + +# To build objects in subdirs, we need to descend into the directories +$(sort $(subdir-obj-y)): $(subdir-ym) ; + +# +# Rule to compile a set of .o files into one .o file +# +ifdef builtin-target +quiet_cmd_link_o_target = LD $@ +# If the list of objects to link is empty, just create an empty built-in.o +cmd_link_o_target = $(if $(strip $(obj-y)),\ + $(LD) $(ld_flags) -r -o $@ $(filter $(obj-y), $^) \ + $(cmd_secanalysis),\ + rm -f $@; $(AR) rcs$(KBUILD_ARFLAGS) $@) + +$(builtin-target): $(obj-y) FORCE + $(call if_changed,link_o_target) + +targets += $(builtin-target) +endif # builtin-target + +# +# Rule to create modules.order file +# +# Create commands to either record .ko file or cat modules.order from +# a subdirectory +modorder-cmds = \ + $(foreach m, $(modorder), \ + $(if $(filter %/modules.order, $m), \ + cat $m;, echo kernel/$m;)) + +$(modorder-target): $(subdir-ym) FORCE + $(Q)(cat /dev/null; $(modorder-cmds)) > $@ + +# +# Rule to compile a set of .o files into one .a file +# +ifdef lib-target +quiet_cmd_link_l_target = AR $@ +cmd_link_l_target = rm -f $@; $(AR) rcs$(KBUILD_ARFLAGS) $@ $(lib-y) + +$(lib-target): $(lib-y) FORCE + $(call if_changed,link_l_target) + +targets += $(lib-target) +endif + +# +# Rule to link composite objects +# +# Composite objects are specified in kbuild makefile as follows: +# -objs := +# or +# -y := +link_multi_deps = \ +$(filter $(addprefix $(obj)/, \ +$($(subst $(obj)/,,$(@:.o=-objs))) \ +$($(subst $(obj)/,,$(@:.o=-y)))), $^) + +quiet_cmd_link_multi-y = LD $@ +cmd_link_multi-y = $(LD) $(ld_flags) -r -o $@ $(link_multi_deps) $(cmd_secanalysis) + +quiet_cmd_link_multi-m = LD [M] $@ +cmd_link_multi-m = $(cmd_link_multi-y) + +# We would rather have a list of rules like +# foo.o: $(foo-objs) +# but that's not so easy, so we rather make all composite objects depend +# on the set of all their parts +$(multi-used-y) : %.o: $(multi-objs-y) FORCE + $(call if_changed,link_multi-y) + +$(multi-used-m) : %.o: $(multi-objs-m) FORCE + $(call if_changed,link_multi-m) + @{ echo $(@:.o=.ko); echo $(link_multi_deps); } > $(MODVERDIR)/$(@F:.o=.mod) + +targets += $(multi-used-y) $(multi-used-m) + + +# Descending +# --------------------------------------------------------------------------- + +PHONY += $(subdir-ym) +$(subdir-ym): + $(Q)$(MAKE) $(build)=$@ + +# Add FORCE to the prequisites of a target to force it to be always rebuilt. +# --------------------------------------------------------------------------- + +PHONY += FORCE + +FORCE: + +# Read all saved command lines and dependencies for the $(targets) we +# may be building above, using $(if_changed{,_dep}). As an +# optimization, we don't need to read them if the target does not +# exist, we will rebuild anyway in that case. + +targets := $(wildcard $(sort $(targets))) +cmd_files := $(wildcard $(foreach f,$(targets),$(dir $(f)).$(notdir $(f)).cmd)) + +ifneq ($(cmd_files),) + include $(cmd_files) +endif + +# Declare the contents of the .PHONY variable as phony. We keep that +# information in a variable se we can use it in if_changed and friends. + +.PHONY: $(PHONY) diff --git a/l4/tool/kconfig/scripts/Makefile.clean b/l4/tool/kconfig/scripts/Makefile.clean new file mode 100644 index 00000000..686cb0d3 --- /dev/null +++ b/l4/tool/kconfig/scripts/Makefile.clean @@ -0,0 +1,104 @@ +# ========================================================================== +# Cleaning up +# ========================================================================== + +src := $(obj) + +PHONY := __clean +__clean: + +# Shorthand for $(Q)$(MAKE) scripts/Makefile.clean obj=dir +# Usage: +# $(Q)$(MAKE) $(clean)=dir +clean := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.clean obj + +# The filename Kbuild has precedence over Makefile +kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src)) +include $(if $(wildcard $(kbuild-dir)/Kbuild), $(kbuild-dir)/Kbuild, $(kbuild-dir)/Makefile) + +# Figure out what we need to build from the various variables +# ========================================================================== + +__subdir-y := $(patsubst %/,%,$(filter %/, $(obj-y))) +subdir-y += $(__subdir-y) +__subdir-m := $(patsubst %/,%,$(filter %/, $(obj-m))) +subdir-m += $(__subdir-m) +__subdir-n := $(patsubst %/,%,$(filter %/, $(obj-n))) +subdir-n += $(__subdir-n) +__subdir- := $(patsubst %/,%,$(filter %/, $(obj-))) +subdir- += $(__subdir-) + +# Subdirectories we need to descend into + +subdir-ym := $(sort $(subdir-y) $(subdir-m)) +subdir-ymn := $(sort $(subdir-ym) $(subdir-n) $(subdir-)) + +# Add subdir path + +subdir-ymn := $(addprefix $(obj)/,$(subdir-ymn)) + +# build a list of files to remove, usually relative to the current +# directory + +__clean-files := $(extra-y) $(always) \ + $(targets) $(clean-files) \ + $(host-progs) \ + $(hostprogs-y) $(hostprogs-m) $(hostprogs-) + +__clean-files := $(filter-out $(no-clean-files), $(__clean-files)) + +# as clean-files is given relative to the current directory, this adds +# a $(obj) prefix, except for absolute paths + +__clean-files := $(wildcard \ + $(addprefix $(obj)/, $(filter-out /%, $(__clean-files))) \ + $(filter /%, $(__clean-files))) + +# as clean-dirs is given relative to the current directory, this adds +# a $(obj) prefix, except for absolute paths + +__clean-dirs := $(wildcard \ + $(addprefix $(obj)/, $(filter-out /%, $(clean-dirs))) \ + $(filter /%, $(clean-dirs))) + +# ========================================================================== + +quiet_cmd_clean = CLEAN $(obj) + cmd_clean = rm -f $(__clean-files) +quiet_cmd_cleandir = CLEAN $(__clean-dirs) + cmd_cleandir = rm -rf $(__clean-dirs) + + +__clean: $(subdir-ymn) +ifneq ($(strip $(__clean-files)),) + +$(call cmd,clean) +endif +ifneq ($(strip $(__clean-dirs)),) + +$(call cmd,cleandir) +endif +ifneq ($(strip $(clean-rule)),) + +$(clean-rule) +endif + @: + + +# =========================================================================== +# Generic stuff +# =========================================================================== + +# Descending +# --------------------------------------------------------------------------- + +PHONY += $(subdir-ymn) +$(subdir-ymn): + $(Q)$(MAKE) $(clean)=$@ + +# If quiet is set, only print short version of command + +cmd = @$(if $($(quiet)cmd_$(1)),echo ' $($(quiet)cmd_$(1))' &&) $(cmd_$(1)) + + +# Declare the contents of the .PHONY variable as phony. We keep that +# information in a variable se we can use it in if_changed and friends. + +.PHONY: $(PHONY) diff --git a/l4/tool/kconfig/scripts/Makefile.headersinst b/l4/tool/kconfig/scripts/Makefile.headersinst new file mode 100644 index 00000000..d3bae5e7 --- /dev/null +++ b/l4/tool/kconfig/scripts/Makefile.headersinst @@ -0,0 +1,117 @@ +# ========================================================================== +# Installing headers +# +# header-y - list files to be installed. They are preprocessed +# to remove __KERNEL__ section of the file +# objhdr-y - Same as header-y but for generated files +# genhdr-y - Same as objhdr-y but in a generated/ directory +# +# ========================================================================== + +# called may set destination dir (when installing to asm/) +_dst := $(if $(dst),$(dst),$(obj)) + +# generated header directory +gen := $(if $(gen),$(gen),$(subst include/,include/generated/,$(obj))) + +kbuild-file := $(srctree)/$(obj)/Kbuild +include $(kbuild-file) + +_dst := $(if $(destination-y),$(destination-y),$(_dst)) + +include scripts/Kbuild.include + +install := $(INSTALL_HDR_PATH)/$(_dst) + +header-y := $(sort $(header-y)) +subdirs := $(patsubst %/,%,$(filter %/, $(header-y))) +header-y := $(filter-out %/, $(header-y)) + +# files used to track state of install/check +install-file := $(install)/.install +check-file := $(install)/.check + +# generic-y list all files an architecture uses from asm-generic +# Use this to build a list of headers which require a wrapper +wrapper-files := $(filter $(header-y), $(generic-y)) + +# all headers files for this dir +header-y := $(filter-out $(generic-y), $(header-y)) +all-files := $(header-y) $(objhdr-y) $(genhdr-y) $(wrapper-files) +input-files := $(addprefix $(srctree)/$(obj)/,$(header-y)) \ + $(addprefix $(objtree)/$(obj)/,$(objhdr-y)) \ + $(addprefix $(objtree)/$(gen)/,$(genhdr-y)) +output-files := $(addprefix $(install)/, $(all-files)) + +# Work out what needs to be removed +oldheaders := $(patsubst $(install)/%,%,$(wildcard $(install)/*.h)) +unwanted := $(filter-out $(all-files),$(oldheaders)) + +# Prefix unwanted with full paths to $(INSTALL_HDR_PATH) +unwanted-file := $(addprefix $(install)/, $(unwanted)) + +printdir = $(patsubst $(INSTALL_HDR_PATH)/%/,%,$(dir $@)) + +quiet_cmd_install = INSTALL $(printdir) ($(words $(all-files))\ + file$(if $(word 2, $(all-files)),s)) + cmd_install = \ + $(PERL) $< $(srctree)/$(obj) $(install) $(SRCARCH) $(header-y); \ + $(PERL) $< $(objtree)/$(obj) $(install) $(SRCARCH) $(objhdr-y); \ + $(PERL) $< $(objtree)/$(gen) $(install) $(SRCARCH) $(genhdr-y); \ + for F in $(wrapper-files); do \ + echo "\#include " > $(install)/$$F; \ + done; \ + touch $@ + +quiet_cmd_remove = REMOVE $(unwanted) + cmd_remove = rm -f $(unwanted-file) + +quiet_cmd_check = CHECK $(printdir) ($(words $(all-files)) files) +# Headers list can be pretty long, xargs helps to avoid +# the "Argument list too long" error. + cmd_check = for f in $(all-files); do \ + echo "$(install)/$${f}"; done \ + | xargs \ + $(PERL) $< $(INSTALL_HDR_PATH)/include $(SRCARCH); \ + touch $@ + +PHONY += __headersinst __headerscheck + +ifndef HDRCHECK +# Rules for installing headers +__headersinst: $(subdirs) $(install-file) + @: + +targets += $(install-file) +$(install-file): scripts/headers_install.pl $(input-files) FORCE + $(if $(unwanted),$(call cmd,remove),) + $(if $(wildcard $(dir $@)),,$(shell mkdir -p $(dir $@))) + $(call if_changed,install) + +else +__headerscheck: $(subdirs) $(check-file) + @: + +targets += $(check-file) +$(check-file): scripts/headers_check.pl $(output-files) FORCE + $(call if_changed,check) + +endif + +# Recursion +hdr-inst := -rR -f $(srctree)/scripts/Makefile.headersinst obj +.PHONY: $(subdirs) +$(subdirs): + $(Q)$(MAKE) $(hdr-inst)=$(obj)/$@ dst=$(_dst)/$@ + +targets := $(wildcard $(sort $(targets))) +cmd_files := $(wildcard \ + $(foreach f,$(targets),$(dir $(f)).$(notdir $(f)).cmd)) + +ifneq ($(cmd_files),) + include $(cmd_files) +endif + +.PHONY: $(PHONY) +PHONY += FORCE +FORCE: ; diff --git a/l4/tool/kconfig/scripts/Makefile.host b/l4/tool/kconfig/scripts/Makefile.host new file mode 100644 index 00000000..1ac414fd --- /dev/null +++ b/l4/tool/kconfig/scripts/Makefile.host @@ -0,0 +1,170 @@ +# ========================================================================== +# Building binaries on the host system +# Binaries are used during the compilation of the kernel, for example +# to preprocess a data file. +# +# Both C and C++ are supported, but preferred language is C for such utilities. +# +# Sample syntax (see Documentation/kbuild/makefiles.txt for reference) +# hostprogs-y := bin2hex +# Will compile bin2hex.c and create an executable named bin2hex +# +# hostprogs-y := lxdialog +# lxdialog-objs := checklist.o lxdialog.o +# Will compile lxdialog.c and checklist.c, and then link the executable +# lxdialog, based on checklist.o and lxdialog.o +# +# hostprogs-y := qconf +# qconf-cxxobjs := qconf.o +# qconf-objs := menu.o +# Will compile qconf as a C++ program, and menu as a C program. +# They are linked as C++ code to the executable qconf + +# hostprogs-y := conf +# conf-objs := conf.o libkconfig.so +# libkconfig-objs := expr.o type.o +# Will create a shared library named libkconfig.so that consists of +# expr.o and type.o (they are both compiled as C code and the object files +# are made as position independent code). +# conf.c is compiled as a C program, and conf.o is linked together with +# libkconfig.so as the executable conf. +# Note: Shared libraries consisting of C++ files are not supported + +__hostprogs := $(sort $(hostprogs-y) $(hostprogs-m)) + +# C code +# Executables compiled from a single .c file +host-csingle := $(foreach m,$(__hostprogs),$(if $($(m)-objs),,$(m))) + +# C executables linked based on several .o files +host-cmulti := $(foreach m,$(__hostprogs),\ + $(if $($(m)-cxxobjs),,$(if $($(m)-objs),$(m)))) + +# Object (.o) files compiled from .c files +host-cobjs := $(sort $(foreach m,$(__hostprogs),$($(m)-objs))) + +# C++ code +# C++ executables compiled from at least on .cc file +# and zero or more .c files +host-cxxmulti := $(foreach m,$(__hostprogs),$(if $($(m)-cxxobjs),$(m))) + +# C++ Object (.o) files compiled from .cc files +host-cxxobjs := $(sort $(foreach m,$(host-cxxmulti),$($(m)-cxxobjs))) + +# Shared libaries (only .c supported) +# Shared libraries (.so) - all .so files referenced in "xxx-objs" +host-cshlib := $(sort $(filter %.so, $(host-cobjs))) +# Remove .so files from "xxx-objs" +host-cobjs := $(filter-out %.so,$(host-cobjs)) + +#Object (.o) files used by the shared libaries +host-cshobjs := $(sort $(foreach m,$(host-cshlib),$($(m:.so=-objs)))) + +# output directory for programs/.o files +# hostprogs-y := tools/build may have been specified. Retrieve directory +host-objdirs := $(foreach f,$(__hostprogs), $(if $(dir $(f)),$(dir $(f)))) +# directory of .o files from prog-objs notation +host-objdirs += $(foreach f,$(host-cmulti), \ + $(foreach m,$($(f)-objs), \ + $(if $(dir $(m)),$(dir $(m))))) +# directory of .o files from prog-cxxobjs notation +host-objdirs += $(foreach f,$(host-cxxmulti), \ + $(foreach m,$($(f)-cxxobjs), \ + $(if $(dir $(m)),$(dir $(m))))) + +host-objdirs := $(strip $(sort $(filter-out ./,$(host-objdirs)))) + + +__hostprogs := $(addprefix $(obj)/,$(__hostprogs)) +host-csingle := $(addprefix $(obj)/,$(host-csingle)) +host-cmulti := $(addprefix $(obj)/,$(host-cmulti)) +host-cobjs := $(addprefix $(obj)/,$(host-cobjs)) +host-cxxmulti := $(addprefix $(obj)/,$(host-cxxmulti)) +host-cxxobjs := $(addprefix $(obj)/,$(host-cxxobjs)) +host-cshlib := $(addprefix $(obj)/,$(host-cshlib)) +host-cshobjs := $(addprefix $(obj)/,$(host-cshobjs)) +host-objdirs := $(addprefix $(obj)/,$(host-objdirs)) + +obj-dirs += $(host-objdirs) + +##### +# Handle options to gcc. Support building with separate output directory + +_hostc_flags = $(HOSTCFLAGS) $(HOST_EXTRACFLAGS) \ + $(HOSTCFLAGS_$(basetarget).o) +_hostcxx_flags = $(HOSTCXXFLAGS) $(HOST_EXTRACXXFLAGS) \ + $(HOSTCXXFLAGS_$(basetarget).o) + +ifeq ($(KBUILD_SRC),) +__hostc_flags = $(_hostc_flags) +__hostcxx_flags = $(_hostcxx_flags) +else +__hostc_flags = -I$(obj) $(call flags,_hostc_flags) +__hostcxx_flags = -I$(obj) $(call flags,_hostcxx_flags) +endif + +hostc_flags = -Wp,-MD,$(depfile) $(__hostc_flags) +hostcxx_flags = -Wp,-MD,$(depfile) $(__hostcxx_flags) + +##### +# Compile programs on the host + +# Create executable from a single .c file +# host-csingle -> Executable +quiet_cmd_host-csingle = HOSTCC $@ + cmd_host-csingle = $(HOSTCC) $(hostc_flags) -o $@ $< \ + $(HOST_LOADLIBES) $(HOSTLOADLIBES_$(@F)) +$(host-csingle): $(obj)/%: $(src)/%.c FORCE + $(call if_changed_dep,host-csingle) + +# Link an executable based on list of .o files, all plain c +# host-cmulti -> executable +quiet_cmd_host-cmulti = HOSTLD $@ + cmd_host-cmulti = $(HOSTCC) $(HOSTLDFLAGS) -o $@ \ + $(addprefix $(obj)/,$($(@F)-objs)) \ + $(HOST_LOADLIBES) $(HOSTLOADLIBES_$(@F)) +$(host-cmulti): $(obj)/%: $(host-cobjs) $(host-cshlib) FORCE + $(call if_changed,host-cmulti) + +# Create .o file from a single .c file +# host-cobjs -> .o +quiet_cmd_host-cobjs = HOSTCC $@ + cmd_host-cobjs = $(HOSTCC) $(hostc_flags) -c -o $@ $< +$(host-cobjs): $(obj)/%.o: $(src)/%.c FORCE + $(call if_changed_dep,host-cobjs) + +# Link an executable based on list of .o files, a mixture of .c and .cc +# host-cxxmulti -> executable +quiet_cmd_host-cxxmulti = HOSTLD $@ + cmd_host-cxxmulti = $(HOSTCXX) $(HOSTLDFLAGS) -o $@ \ + $(foreach o,objs cxxobjs,\ + $(addprefix $(obj)/,$($(@F)-$(o)))) \ + $(HOST_LOADLIBES) $(HOSTLOADLIBES_$(@F)) +$(host-cxxmulti): $(obj)/%: $(host-cobjs) $(host-cxxobjs) $(host-cshlib) FORCE + $(call if_changed,host-cxxmulti) + +# Create .o file from a single .cc (C++) file +quiet_cmd_host-cxxobjs = HOSTCXX $@ + cmd_host-cxxobjs = $(HOSTCXX) $(hostcxx_flags) -c -o $@ $< +$(host-cxxobjs): $(obj)/%.o: $(src)/%.cc FORCE + $(call if_changed_dep,host-cxxobjs) + +# Compile .c file, create position independent .o file +# host-cshobjs -> .o +quiet_cmd_host-cshobjs = HOSTCC -fPIC $@ + cmd_host-cshobjs = $(HOSTCC) $(hostc_flags) -fPIC -c -o $@ $< +$(host-cshobjs): $(obj)/%.o: $(src)/%.c FORCE + $(call if_changed_dep,host-cshobjs) + +# Link a shared library, based on position independent .o files +# *.o -> .so shared library (host-cshlib) +quiet_cmd_host-cshlib = HOSTLLD -shared $@ + cmd_host-cshlib = $(HOSTCC) $(HOSTLDFLAGS) -shared -o $@ \ + $(addprefix $(obj)/,$($(@F:.so=-objs))) \ + $(HOST_LOADLIBES) $(HOSTLOADLIBES_$(@F)) +$(host-cshlib): $(obj)/%: $(host-cshobjs) FORCE + $(call if_changed,host-cshlib) + +targets += $(host-csingle) $(host-cmulti) $(host-cobjs)\ + $(host-cxxmulti) $(host-cxxobjs) $(host-cshlib) $(host-cshobjs) + diff --git a/l4/tool/kconfig/scripts/Makefile.lib b/l4/tool/kconfig/scripts/Makefile.lib new file mode 100644 index 00000000..0be6f110 --- /dev/null +++ b/l4/tool/kconfig/scripts/Makefile.lib @@ -0,0 +1,361 @@ +# Backward compatibility +asflags-y += $(EXTRA_AFLAGS) +ccflags-y += $(EXTRA_CFLAGS) +cppflags-y += $(EXTRA_CPPFLAGS) +ldflags-y += $(EXTRA_LDFLAGS) + +# +# flags that take effect in sub directories +export KBUILD_SUBDIR_ASFLAGS := $(KBUILD_SUBDIR_ASFLAGS) $(subdir-asflags-y) +export KBUILD_SUBDIR_CCFLAGS := $(KBUILD_SUBDIR_CCFLAGS) $(subdir-ccflags-y) + +# Figure out what we need to build from the various variables +# =========================================================================== + +# When an object is listed to be built compiled-in and modular, +# only build the compiled-in version + +obj-m := $(filter-out $(obj-y),$(obj-m)) + +# Libraries are always collected in one lib file. +# Filter out objects already built-in + +lib-y := $(filter-out $(obj-y), $(sort $(lib-y) $(lib-m))) + + +# Handle objects in subdirs +# --------------------------------------------------------------------------- +# o if we encounter foo/ in $(obj-y), replace it by foo/built-in.o +# and add the directory to the list of dirs to descend into: $(subdir-y) +# o if we encounter foo/ in $(obj-m), remove it from $(obj-m) +# and add the directory to the list of dirs to descend into: $(subdir-m) + +# Determine modorder. +# Unfortunately, we don't have information about ordering between -y +# and -m subdirs. Just put -y's first. +modorder := $(patsubst %/,%/modules.order, $(filter %/, $(obj-y)) $(obj-m:.o=.ko)) + +__subdir-y := $(patsubst %/,%,$(filter %/, $(obj-y))) +subdir-y += $(__subdir-y) +__subdir-m := $(patsubst %/,%,$(filter %/, $(obj-m))) +subdir-m += $(__subdir-m) +obj-y := $(patsubst %/, %/built-in.o, $(obj-y)) +obj-m := $(filter-out %/, $(obj-m)) + +# Subdirectories we need to descend into + +subdir-ym := $(sort $(subdir-y) $(subdir-m)) + +# if $(foo-objs) exists, foo.o is a composite object +multi-used-y := $(sort $(foreach m,$(obj-y), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y))), $(m)))) +multi-used-m := $(sort $(foreach m,$(obj-m), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y))), $(m)))) +multi-used := $(multi-used-y) $(multi-used-m) +single-used-m := $(sort $(filter-out $(multi-used-m),$(obj-m))) + +# Build list of the parts of our composite objects, our composite +# objects depend on those (obviously) +multi-objs-y := $(foreach m, $(multi-used-y), $($(m:.o=-objs)) $($(m:.o=-y))) +multi-objs-m := $(foreach m, $(multi-used-m), $($(m:.o=-objs)) $($(m:.o=-y))) +multi-objs := $(multi-objs-y) $(multi-objs-m) + +# $(subdir-obj-y) is the list of objects in $(obj-y) which uses dir/ to +# tell kbuild to descend +subdir-obj-y := $(filter %/built-in.o, $(obj-y)) + +# $(obj-dirs) is a list of directories that contain object files +obj-dirs := $(dir $(multi-objs) $(subdir-obj-y)) + +# Replace multi-part objects by their individual parts, look at local dir only +real-objs-y := $(foreach m, $(filter-out $(subdir-obj-y), $(obj-y)), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y))),$($(m:.o=-objs)) $($(m:.o=-y)),$(m))) $(extra-y) +real-objs-m := $(foreach m, $(obj-m), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y))),$($(m:.o=-objs)) $($(m:.o=-y)),$(m))) + +# Add subdir path + +extra-y := $(addprefix $(obj)/,$(extra-y)) +always := $(addprefix $(obj)/,$(always)) +targets := $(addprefix $(obj)/,$(targets)) +modorder := $(addprefix $(obj)/,$(modorder)) +obj-y := $(addprefix $(obj)/,$(obj-y)) +obj-m := $(addprefix $(obj)/,$(obj-m)) +lib-y := $(addprefix $(obj)/,$(lib-y)) +subdir-obj-y := $(addprefix $(obj)/,$(subdir-obj-y)) +real-objs-y := $(addprefix $(obj)/,$(real-objs-y)) +real-objs-m := $(addprefix $(obj)/,$(real-objs-m)) +single-used-m := $(addprefix $(obj)/,$(single-used-m)) +multi-used-y := $(addprefix $(obj)/,$(multi-used-y)) +multi-used-m := $(addprefix $(obj)/,$(multi-used-m)) +multi-objs-y := $(addprefix $(obj)/,$(multi-objs-y)) +multi-objs-m := $(addprefix $(obj)/,$(multi-objs-m)) +subdir-ym := $(addprefix $(obj)/,$(subdir-ym)) +obj-dirs := $(addprefix $(obj)/,$(obj-dirs)) + +# These flags are needed for modversions and compiling, so we define them here +# already +# $(modname_flags) #defines KBUILD_MODNAME as the name of the module it will +# end up in (or would, if it gets compiled in) +# Note: Files that end up in two or more modules are compiled without the +# KBUILD_MODNAME definition. The reason is that any made-up name would +# differ in different configs. +name-fix = $(subst $(comma),_,$(subst -,_,$1)) +basename_flags = -D"KBUILD_BASENAME=KBUILD_STR($(call name-fix,$(basetarget)))" +modname_flags = $(if $(filter 1,$(words $(modname))),\ + -D"KBUILD_MODNAME=KBUILD_STR($(call name-fix,$(modname)))") + +orig_c_flags = $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) $(KBUILD_SUBDIR_CCFLAGS) \ + $(ccflags-y) $(CFLAGS_$(basetarget).o) +_c_flags = $(filter-out $(CFLAGS_REMOVE_$(basetarget).o), $(orig_c_flags)) +_a_flags = $(KBUILD_CPPFLAGS) $(KBUILD_AFLAGS) $(KBUILD_SUBDIR_ASFLAGS) \ + $(asflags-y) $(AFLAGS_$(basetarget).o) +_cpp_flags = $(KBUILD_CPPFLAGS) $(cppflags-y) $(CPPFLAGS_$(@F)) + +# +# Enable gcov profiling flags for a file, directory or for all files depending +# on variables GCOV_PROFILE_obj.o, GCOV_PROFILE and CONFIG_GCOV_PROFILE_ALL +# (in this order) +# +ifeq ($(CONFIG_GCOV_KERNEL),y) +_c_flags += $(if $(patsubst n%,, \ + $(GCOV_PROFILE_$(basetarget).o)$(GCOV_PROFILE)$(CONFIG_GCOV_PROFILE_ALL)), \ + $(CFLAGS_GCOV)) +endif + +ifdef CONFIG_SYMBOL_PREFIX +_sym_flags = -DSYMBOL_PREFIX=$(patsubst "%",%,$(CONFIG_SYMBOL_PREFIX)) +_cpp_flags += $(_sym_flags) +_a_flags += $(_sym_flags) +endif + + +# If building the kernel in a separate objtree expand all occurrences +# of -Idir to -I$(srctree)/dir except for absolute paths (starting with '/'). + +ifeq ($(KBUILD_SRC),) +__c_flags = $(_c_flags) +__a_flags = $(_a_flags) +__cpp_flags = $(_cpp_flags) +else + +# -I$(obj) locates generated .h files +# $(call addtree,-I$(obj)) locates .h files in srctree, from generated .c files +# and locates generated .h files +# FIXME: Replace both with specific CFLAGS* statements in the makefiles +__c_flags = $(call addtree,-I$(obj)) $(call flags,_c_flags) +__a_flags = $(call flags,_a_flags) +__cpp_flags = $(call flags,_cpp_flags) +endif + +c_flags = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(LINUXINCLUDE) \ + $(__c_flags) $(modkern_cflags) \ + -D"KBUILD_STR(s)=\#s" $(basename_flags) $(modname_flags) + +a_flags = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(LINUXINCLUDE) \ + $(__a_flags) $(modkern_aflags) + +cpp_flags = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(LINUXINCLUDE) \ + $(__cpp_flags) + +ld_flags = $(LDFLAGS) $(ldflags-y) + +# Finds the multi-part object the current object will be linked into +modname-multi = $(sort $(foreach m,$(multi-used),\ + $(if $(filter $(subst $(obj)/,,$*.o), $($(m:.o=-objs)) $($(m:.o=-y))),$(m:.o=)))) + +ifdef REGENERATE_PARSERS + +# GPERF +# --------------------------------------------------------------------------- +quiet_cmd_gperf = GPERF $@ + cmd_gperf = gperf -t --output-file $@ -a -C -E -g -k 1,3,$$ -p -t $< + +.PRECIOUS: $(src)/%.hash.c_shipped +$(src)/%.hash.c_shipped: $(src)/%.gperf + $(call cmd,gperf) + +# LEX +# --------------------------------------------------------------------------- +LEX_PREFIX = $(if $(LEX_PREFIX_${baseprereq}),$(LEX_PREFIX_${baseprereq}),yy) + +quiet_cmd_flex = LEX $@ + cmd_flex = flex -o$@ -L -P $(LEX_PREFIX) $< + +.PRECIOUS: $(src)/%.lex.c_shipped +$(src)/%.lex.c_shipped: $(src)/%.l + $(call cmd,flex) + +# YACC +# --------------------------------------------------------------------------- +YACC_PREFIX = $(if $(YACC_PREFIX_${baseprereq}),$(YACC_PREFIX_${baseprereq}),yy) + +quiet_cmd_bison = YACC $@ + cmd_bison = bison -o$@ -t -l -p $(YACC_PREFIX) $< + +.PRECIOUS: $(src)/%.tab.c_shipped +$(src)/%.tab.c_shipped: $(src)/%.y + $(call cmd,bison) + +quiet_cmd_bison_h = YACC $@ + cmd_bison_h = bison -o/dev/null --defines=$@ -t -l -p $(YACC_PREFIX) $< + +.PRECIOUS: $(src)/%.tab.h_shipped +$(src)/%.tab.h_shipped: $(src)/%.y + $(call cmd,bison_h) + +endif + +# Shipped files +# =========================================================================== + +quiet_cmd_shipped = SHIPPED $@ +cmd_shipped = cat $< > $@ + +$(obj)/%: $(src)/%_shipped + $(call cmd,shipped) + +# Commands useful for building a boot image +# =========================================================================== +# +# Use as following: +# +# target: source(s) FORCE +# $(if_changed,ld/objcopy/gzip) +# +# and add target to extra-y so that we know we have to +# read in the saved command line + +# Linking +# --------------------------------------------------------------------------- + +quiet_cmd_ld = LD $@ +cmd_ld = $(LD) $(LDFLAGS) $(ldflags-y) $(LDFLAGS_$(@F)) \ + $(filter-out FORCE,$^) -o $@ + +# Objcopy +# --------------------------------------------------------------------------- + +quiet_cmd_objcopy = OBJCOPY $@ +cmd_objcopy = $(OBJCOPY) $(OBJCOPYFLAGS) $(OBJCOPYFLAGS_$(@F)) $< $@ + +# Gzip +# --------------------------------------------------------------------------- + +quiet_cmd_gzip = GZIP $@ +cmd_gzip = (cat $(filter-out FORCE,$^) | gzip -n -f -9 > $@) || \ + (rm -f $@ ; false) + +# DTC +# --------------------------------------------------------------------------- + +# Generate an assembly file to wrap the output of the device tree compiler +quiet_cmd_dt_S_dtb= DTB $@ +cmd_dt_S_dtb= \ +( \ + echo '\#include '; \ + echo '.section .dtb.init.rodata,"a"'; \ + echo '.balign STRUCT_ALIGNMENT'; \ + echo '.global __dtb_$(*F)_begin'; \ + echo '__dtb_$(*F)_begin:'; \ + echo '.incbin "$<" '; \ + echo '__dtb_$(*F)_end:'; \ + echo '.global __dtb_$(*F)_end'; \ + echo '.balign STRUCT_ALIGNMENT'; \ +) > $@ + +$(obj)/%.dtb.S: $(obj)/%.dtb + $(call cmd,dt_S_dtb) + +quiet_cmd_dtc = DTC $@ +cmd_dtc = $(objtree)/scripts/dtc/dtc -O dtb -o $@ -b 0 $(DTC_FLAGS) -d $(depfile) $< + +# Bzip2 +# --------------------------------------------------------------------------- + +# Bzip2 and LZMA do not include size in file... so we have to fake that; +# append the size as a 32-bit littleendian number as gzip does. +size_append = printf $(shell \ +dec_size=0; \ +for F in $1; do \ + fsize=$$(stat -c "%s" $$F); \ + dec_size=$$(expr $$dec_size + $$fsize); \ +done; \ +printf "%08x\n" $$dec_size | \ + sed 's/\(..\)/\1 /g' | { \ + read ch0 ch1 ch2 ch3; \ + for ch in $$ch3 $$ch2 $$ch1 $$ch0; do \ + printf '%s%03o' '\\' $$((0x$$ch)); \ + done; \ + } \ +) + +quiet_cmd_bzip2 = BZIP2 $@ +cmd_bzip2 = (cat $(filter-out FORCE,$^) | \ + bzip2 -9 && $(call size_append, $(filter-out FORCE,$^))) > $@ || \ + (rm -f $@ ; false) + +# Lzma +# --------------------------------------------------------------------------- + +quiet_cmd_lzma = LZMA $@ +cmd_lzma = (cat $(filter-out FORCE,$^) | \ + lzma -9 && $(call size_append, $(filter-out FORCE,$^))) > $@ || \ + (rm -f $@ ; false) + +quiet_cmd_lzo = LZO $@ +cmd_lzo = (cat $(filter-out FORCE,$^) | \ + lzop -9 && $(call size_append, $(filter-out FORCE,$^))) > $@ || \ + (rm -f $@ ; false) + +# U-Boot mkimage +# --------------------------------------------------------------------------- + +MKIMAGE := $(srctree)/scripts/mkuboot.sh + +# SRCARCH just happens to match slightly more than ARCH (on sparc), so reduces +# the number of overrides in arch makefiles +UIMAGE_ARCH ?= $(SRCARCH) +UIMAGE_COMPRESSION ?= $(if $(2),$(2),none) +UIMAGE_OPTS-y ?= +UIMAGE_TYPE ?= kernel +UIMAGE_LOADADDR ?= arch_must_set_this +UIMAGE_ENTRYADDR ?= $(UIMAGE_LOADADDR) +UIMAGE_NAME ?= 'Linux-$(KERNELRELEASE)' +UIMAGE_IN ?= $< +UIMAGE_OUT ?= $@ + +quiet_cmd_uimage = UIMAGE $(UIMAGE_OUT) + cmd_uimage = $(CONFIG_SHELL) $(MKIMAGE) -A $(UIMAGE_ARCH) -O linux \ + -C $(UIMAGE_COMPRESSION) $(UIMAGE_OPTS-y) \ + -T $(UIMAGE_TYPE) \ + -a $(UIMAGE_LOADADDR) -e $(UIMAGE_ENTRYADDR) \ + -n $(UIMAGE_NAME) -d $(UIMAGE_IN) $(UIMAGE_OUT) + +# XZ +# --------------------------------------------------------------------------- +# Use xzkern to compress the kernel image and xzmisc to compress other things. +# +# xzkern uses a big LZMA2 dictionary since it doesn't increase memory usage +# of the kernel decompressor. A BCJ filter is used if it is available for +# the target architecture. xzkern also appends uncompressed size of the data +# using size_append. The .xz format has the size information available at +# the end of the file too, but it's in more complex format and it's good to +# avoid changing the part of the boot code that reads the uncompressed size. +# Note that the bytes added by size_append will make the xz tool think that +# the file is corrupt. This is expected. +# +# xzmisc doesn't use size_append, so it can be used to create normal .xz +# files. xzmisc uses smaller LZMA2 dictionary than xzkern, because a very +# big dictionary would increase the memory usage too much in the multi-call +# decompression mode. A BCJ filter isn't used either. +quiet_cmd_xzkern = XZKERN $@ +cmd_xzkern = (cat $(filter-out FORCE,$^) | \ + sh $(srctree)/scripts/xz_wrap.sh && \ + $(call size_append, $(filter-out FORCE,$^))) > $@ || \ + (rm -f $@ ; false) + +quiet_cmd_xzmisc = XZMISC $@ +cmd_xzmisc = (cat $(filter-out FORCE,$^) | \ + xz --check=crc32 --lzma2=dict=1MiB) > $@ || \ + (rm -f $@ ; false) + +# misc stuff +# --------------------------------------------------------------------------- +quote:=" diff --git a/l4/tool/kconfig/scripts/Makefile.modinst b/l4/tool/kconfig/scripts/Makefile.modinst new file mode 100644 index 00000000..efa5d940 --- /dev/null +++ b/l4/tool/kconfig/scripts/Makefile.modinst @@ -0,0 +1,35 @@ +# ========================================================================== +# Installing modules +# ========================================================================== + +PHONY := __modinst +__modinst: + +include scripts/Kbuild.include + +# + +__modules := $(sort $(shell grep -h '\.ko' /dev/null $(wildcard $(MODVERDIR)/*.mod))) +modules := $(patsubst %.o,%.ko,$(wildcard $(__modules:.ko=.o))) + +PHONY += $(modules) +__modinst: $(modules) + @: + +quiet_cmd_modules_install = INSTALL $@ + cmd_modules_install = mkdir -p $(2); cp $@ $(2) ; $(mod_strip_cmd) $(2)/$(notdir $@) + +# Modules built outside the kernel source tree go into extra by default +INSTALL_MOD_DIR ?= extra +ext-mod-dir = $(INSTALL_MOD_DIR)$(subst $(patsubst %/,%,$(KBUILD_EXTMOD)),,$(@D)) + +modinst_dir = $(if $(KBUILD_EXTMOD),$(ext-mod-dir),kernel/$(@D)) + +$(modules): + $(call cmd,modules_install,$(MODLIB)/$(modinst_dir)) + + +# Declare the contents of the .PHONY variable as phony. We keep that +# information in a variable se we can use it in if_changed and friends. + +.PHONY: $(PHONY) diff --git a/l4/tool/kconfig/scripts/Makefile.modpost b/l4/tool/kconfig/scripts/Makefile.modpost new file mode 100644 index 00000000..08dce14f --- /dev/null +++ b/l4/tool/kconfig/scripts/Makefile.modpost @@ -0,0 +1,153 @@ +# =========================================================================== +# Module versions +# =========================================================================== +# +# Stage one of module building created the following: +# a) The individual .o files used for the module +# b) A .o file which is the .o files above linked together +# c) A .mod file in $(MODVERDIR)/, listing the name of the +# the preliminary .o file, plus all .o files + +# Stage 2 is handled by this file and does the following +# 1) Find all modules from the files listed in $(MODVERDIR)/ +# 2) modpost is then used to +# 3) create one .mod.c file pr. module +# 4) create one Module.symvers file with CRC for all exported symbols +# 5) compile all .mod.c files +# 6) final link of the module to a file + +# Step 3 is used to place certain information in the module's ELF +# section, including information such as: +# Version magic (see include/linux/vermagic.h for full details) +# - Kernel release +# - SMP is CONFIG_SMP +# - PREEMPT is CONFIG_PREEMPT +# - GCC Version +# Module info +# - Module version (MODULE_VERSION) +# - Module alias'es (MODULE_ALIAS) +# - Module license (MODULE_LICENSE) +# - See include/linux/module.h for more details + +# Step 4 is solely used to allow module versioning in external modules, +# where the CRC of each module is retrieved from the Module.symvers file. + +# KBUILD_MODPOST_WARN can be set to avoid error out in case of undefined +# symbols in the final module linking stage +# KBUILD_MODPOST_NOFINAL can be set to skip the final link of modules. +# This is solely useful to speed up test compiles +PHONY := _modpost +_modpost: __modpost + +include include/config/auto.conf +include scripts/Kbuild.include + +# When building external modules load the Kbuild file to retrieve EXTRA_SYMBOLS info +ifneq ($(KBUILD_EXTMOD),) + +# set src + obj - they may be used when building the .mod.c file +obj := $(KBUILD_EXTMOD) +src := $(obj) + +# Include the module's Makefile to find KBUILD_EXTRA_SYMBOLS +include $(if $(wildcard $(KBUILD_EXTMOD)/Kbuild), \ + $(KBUILD_EXTMOD)/Kbuild, $(KBUILD_EXTMOD)/Makefile) +endif + +include scripts/Makefile.lib + +kernelsymfile := $(objtree)/Module.symvers +modulesymfile := $(firstword $(KBUILD_EXTMOD))/Module.symvers + +# Step 1), find all modules listed in $(MODVERDIR)/ +__modules := $(sort $(shell grep -h '\.ko' /dev/null $(wildcard $(MODVERDIR)/*.mod))) +modules := $(patsubst %.o,%.ko, $(wildcard $(__modules:.ko=.o))) + +# Stop after building .o files if NOFINAL is set. Makes compile tests quicker +_modpost: $(if $(KBUILD_MODPOST_NOFINAL), $(modules:.ko:.o),$(modules)) + +ifneq ($(KBUILD_BUILDHOST),$(ARCH)) + cross_build := 1 +endif + +# Step 2), invoke modpost +# Includes step 3,4 +modpost = scripts/mod/modpost \ + $(if $(CONFIG_MODVERSIONS),-m) \ + $(if $(CONFIG_MODULE_SRCVERSION_ALL),-a,) \ + $(if $(KBUILD_EXTMOD),-i,-o) $(kernelsymfile) \ + $(if $(KBUILD_EXTMOD),-I $(modulesymfile)) \ + $(if $(KBUILD_EXTRA_SYMBOLS), $(patsubst %, -e %,$(KBUILD_EXTRA_SYMBOLS))) \ + $(if $(KBUILD_EXTMOD),-o $(modulesymfile)) \ + $(if $(CONFIG_DEBUG_SECTION_MISMATCH),,-S) \ + $(if $(KBUILD_EXTMOD)$(KBUILD_MODPOST_WARN),-w) \ + $(if $(cross_build),-c) + +quiet_cmd_modpost = MODPOST $(words $(filter-out vmlinux FORCE, $^)) modules + cmd_modpost = $(modpost) -s + +PHONY += __modpost +__modpost: $(modules:.ko=.o) FORCE + $(call cmd,modpost) $(wildcard vmlinux) $(filter-out FORCE,$^) + +quiet_cmd_kernel-mod = MODPOST $@ + cmd_kernel-mod = $(modpost) $@ + +vmlinux.o: FORCE + $(call cmd,kernel-mod) + +# Declare generated files as targets for modpost +$(symverfile): __modpost ; +$(modules:.ko=.mod.c): __modpost ; + + +# Step 5), compile all *.mod.c files + +# modname is set to make c_flags define KBUILD_MODNAME +modname = $(notdir $(@:.mod.o=)) + +quiet_cmd_cc_o_c = CC $@ + cmd_cc_o_c = $(CC) $(c_flags) $(KBUILD_CFLAGS_MODULE) $(CFLAGS_MODULE) \ + -c -o $@ $< + +$(modules:.ko=.mod.o): %.mod.o: %.mod.c FORCE + $(call if_changed_dep,cc_o_c) + +targets += $(modules:.ko=.mod.o) + +# Step 6), final link of the modules +quiet_cmd_ld_ko_o = LD [M] $@ + cmd_ld_ko_o = $(LD) -r $(LDFLAGS) \ + $(KBUILD_LDFLAGS_MODULE) $(LDFLAGS_MODULE) \ + -o $@ $(filter-out FORCE,$^) + +$(modules): %.ko :%.o %.mod.o FORCE + $(call if_changed,ld_ko_o) + +targets += $(modules) + + +# Add FORCE to the prequisites of a target to force it to be always rebuilt. +# --------------------------------------------------------------------------- + +PHONY += FORCE + +FORCE: + +# Read all saved command lines and dependencies for the $(targets) we +# may be building above, using $(if_changed{,_dep}). As an +# optimization, we don't need to read them if the target does not +# exist, we will rebuild anyway in that case. + +targets := $(wildcard $(sort $(targets))) +cmd_files := $(wildcard $(foreach f,$(targets),$(dir $(f)).$(notdir $(f)).cmd)) + +ifneq ($(cmd_files),) + include $(cmd_files) +endif + + +# Declare the contents of the .PHONY variable as phony. We keep that +# information in a variable se we can use it in if_changed and friends. + +.PHONY: $(PHONY) diff --git a/l4/tool/kconfig/scripts/basic/.gitignore b/l4/tool/kconfig/scripts/basic/.gitignore new file mode 100644 index 00000000..a776371a --- /dev/null +++ b/l4/tool/kconfig/scripts/basic/.gitignore @@ -0,0 +1 @@ +fixdep diff --git a/l4/tool/kconfig/scripts/basic/Makefile b/l4/tool/kconfig/scripts/basic/Makefile new file mode 100644 index 00000000..4fcef87b --- /dev/null +++ b/l4/tool/kconfig/scripts/basic/Makefile @@ -0,0 +1,15 @@ +### +# Makefile.basic lists the most basic programs used during the build process. +# The programs listed herein are what are needed to do the basic stuff, +# such as fix file dependencies. +# This initial step is needed to avoid files to be recompiled +# when kernel configuration changes (which is what happens when +# .config is included by main Makefile. +# --------------------------------------------------------------------------- +# fixdep: Used to generate dependency information during build process + +hostprogs-y := fixdep +always := $(hostprogs-y) + +# fixdep is needed to compile other host programs +$(addprefix $(obj)/,$(filter-out fixdep,$(always))): $(obj)/fixdep diff --git a/l4/tool/kconfig/scripts/basic/docproc.c b/l4/tool/kconfig/scripts/basic/docproc.c new file mode 100644 index 00000000..98dec879 --- /dev/null +++ b/l4/tool/kconfig/scripts/basic/docproc.c @@ -0,0 +1,583 @@ +/* + * docproc is a simple preprocessor for the template files + * used as placeholders for the kernel internal documentation. + * docproc is used for documentation-frontend and + * dependency-generator. + * The two usages have in common that they require + * some knowledge of the .tmpl syntax, therefore they + * are kept together. + * + * documentation-frontend + * Scans the template file and call kernel-doc for + * all occurrences of ![EIF]file + * Beforehand each referenced file is scanned for + * any symbols that are exported via these macros: + * EXPORT_SYMBOL(), EXPORT_SYMBOL_GPL(), & + * EXPORT_SYMBOL_GPL_FUTURE() + * This is used to create proper -function and + * -nofunction arguments in calls to kernel-doc. + * Usage: docproc doc file.tmpl + * + * dependency-generator: + * Scans the template file and list all files + * referenced in a format recognized by make. + * Usage: docproc depend file.tmpl + * Writes dependency information to stdout + * in the following format: + * file.tmpl src.c src2.c + * The filenames are obtained from the following constructs: + * !Efilename + * !Ifilename + * !Dfilename + * !Ffilename + * !Pfilename + * + */ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* exitstatus is used to keep track of any failing calls to kernel-doc, + * but execution continues. */ +int exitstatus = 0; + +typedef void DFL(char *); +DFL *defaultline; + +typedef void FILEONLY(char * file); +FILEONLY *internalfunctions; +FILEONLY *externalfunctions; +FILEONLY *symbolsonly; +FILEONLY *findall; + +typedef void FILELINE(char * file, char * line); +FILELINE * singlefunctions; +FILELINE * entity_system; +FILELINE * docsection; + +#define MAXLINESZ 2048 +#define MAXFILES 250 +#define KERNELDOCPATH "scripts/" +#define KERNELDOC "kernel-doc" +#define DOCBOOK "-docbook" +#define LIST "-list" +#define FUNCTION "-function" +#define NOFUNCTION "-nofunction" +#define NODOCSECTIONS "-no-doc-sections" + +static char *srctree, *kernsrctree; + +static char **all_list = NULL; +static int all_list_len = 0; + +static void consume_symbol(const char *sym) +{ + int i; + + for (i = 0; i < all_list_len; i++) { + if (!all_list[i]) + continue; + if (strcmp(sym, all_list[i])) + continue; + all_list[i] = NULL; + break; + } +} + +static void usage (void) +{ + fprintf(stderr, "Usage: docproc {doc|depend} file\n"); + fprintf(stderr, "Input is read from file.tmpl. Output is sent to stdout\n"); + fprintf(stderr, "doc: frontend when generating kernel documentation\n"); + fprintf(stderr, "depend: generate list of files referenced within file\n"); + fprintf(stderr, "Environment variable SRCTREE: absolute path to sources.\n"); + fprintf(stderr, " KBUILD_SRC: absolute path to kernel source tree.\n"); +} + +/* + * Execute kernel-doc with parameters given in svec + */ +static void exec_kernel_doc(char **svec) +{ + pid_t pid; + int ret; + char real_filename[PATH_MAX + 1]; + /* Make sure output generated so far are flushed */ + fflush(stdout); + switch (pid=fork()) { + case -1: + perror("fork"); + exit(1); + case 0: + memset(real_filename, 0, sizeof(real_filename)); + strncat(real_filename, kernsrctree, PATH_MAX); + strncat(real_filename, "/" KERNELDOCPATH KERNELDOC, + PATH_MAX - strlen(real_filename)); + execvp(real_filename, svec); + fprintf(stderr, "exec "); + perror(real_filename); + exit(1); + default: + waitpid(pid, &ret ,0); + } + if (WIFEXITED(ret)) + exitstatus |= WEXITSTATUS(ret); + else + exitstatus = 0xff; +} + +/* Types used to create list of all exported symbols in a number of files */ +struct symbols +{ + char *name; +}; + +struct symfile +{ + char *filename; + struct symbols *symbollist; + int symbolcnt; +}; + +struct symfile symfilelist[MAXFILES]; +int symfilecnt = 0; + +static void add_new_symbol(struct symfile *sym, char * symname) +{ + sym->symbollist = + realloc(sym->symbollist, (sym->symbolcnt + 1) * sizeof(char *)); + sym->symbollist[sym->symbolcnt++].name = strdup(symname); +} + +/* Add a filename to the list */ +static struct symfile * add_new_file(char * filename) +{ + symfilelist[symfilecnt++].filename = strdup(filename); + return &symfilelist[symfilecnt - 1]; +} + +/* Check if file already are present in the list */ +static struct symfile * filename_exist(char * filename) +{ + int i; + for (i=0; i < symfilecnt; i++) + if (strcmp(symfilelist[i].filename, filename) == 0) + return &symfilelist[i]; + return NULL; +} + +/* + * List all files referenced within the template file. + * Files are separated by tabs. + */ +static void adddep(char * file) { printf("\t%s", file); } +static void adddep2(char * file, char * line) { line = line; adddep(file); } +static void noaction(char * line) { line = line; } +static void noaction2(char * file, char * line) { file = file; line = line; } + +/* Echo the line without further action */ +static void printline(char * line) { printf("%s", line); } + +/* + * Find all symbols in filename that are exported with EXPORT_SYMBOL & + * EXPORT_SYMBOL_GPL (& EXPORT_SYMBOL_GPL_FUTURE implicitly). + * All symbols located are stored in symfilelist. + */ +static void find_export_symbols(char * filename) +{ + FILE * fp; + struct symfile *sym; + char line[MAXLINESZ]; + if (filename_exist(filename) == NULL) { + char real_filename[PATH_MAX + 1]; + memset(real_filename, 0, sizeof(real_filename)); + strncat(real_filename, srctree, PATH_MAX); + strncat(real_filename, "/", PATH_MAX - strlen(real_filename)); + strncat(real_filename, filename, + PATH_MAX - strlen(real_filename)); + sym = add_new_file(filename); + fp = fopen(real_filename, "r"); + if (fp == NULL) + { + fprintf(stderr, "docproc: "); + perror(real_filename); + exit(1); + } + while (fgets(line, MAXLINESZ, fp)) { + char *p; + char *e; + if (((p = strstr(line, "EXPORT_SYMBOL_GPL")) != NULL) || + ((p = strstr(line, "EXPORT_SYMBOL")) != NULL)) { + /* Skip EXPORT_SYMBOL{_GPL} */ + while (isalnum(*p) || *p == '_') + p++; + /* Remove parentheses & additional whitespace */ + while (isspace(*p)) + p++; + if (*p != '(') + continue; /* Syntax error? */ + else + p++; + while (isspace(*p)) + p++; + e = p; + while (isalnum(*e) || *e == '_') + e++; + *e = '\0'; + add_new_symbol(sym, p); + } + } + fclose(fp); + } +} + +/* + * Document all external or internal functions in a file. + * Call kernel-doc with following parameters: + * kernel-doc -docbook -nofunction function_name1 filename + * Function names are obtained from all the src files + * by find_export_symbols. + * intfunc uses -nofunction + * extfunc uses -function + */ +static void docfunctions(char * filename, char * type) +{ + int i,j; + int symcnt = 0; + int idx = 0; + char **vec; + + for (i=0; i <= symfilecnt; i++) + symcnt += symfilelist[i].symbolcnt; + vec = malloc((2 + 2 * symcnt + 3) * sizeof(char *)); + if (vec == NULL) { + perror("docproc: "); + exit(1); + } + vec[idx++] = KERNELDOC; + vec[idx++] = DOCBOOK; + vec[idx++] = NODOCSECTIONS; + for (i=0; i < symfilecnt; i++) { + struct symfile * sym = &symfilelist[i]; + for (j=0; j < sym->symbolcnt; j++) { + vec[idx++] = type; + consume_symbol(sym->symbollist[j].name); + vec[idx++] = sym->symbollist[j].name; + } + } + vec[idx++] = filename; + vec[idx] = NULL; + printf("\n", filename); + exec_kernel_doc(vec); + fflush(stdout); + free(vec); +} +static void intfunc(char * filename) { docfunctions(filename, NOFUNCTION); } +static void extfunc(char * filename) { docfunctions(filename, FUNCTION); } + +/* + * Document specific function(s) in a file. + * Call kernel-doc with the following parameters: + * kernel-doc -docbook -function function1 [-function function2] + */ +static void singfunc(char * filename, char * line) +{ + char *vec[200]; /* Enough for specific functions */ + int i, idx = 0; + int startofsym = 1; + vec[idx++] = KERNELDOC; + vec[idx++] = DOCBOOK; + + /* Split line up in individual parameters preceded by FUNCTION */ + for (i=0; line[i]; i++) { + if (isspace(line[i])) { + line[i] = '\0'; + startofsym = 1; + continue; + } + if (startofsym) { + startofsym = 0; + vec[idx++] = FUNCTION; + vec[idx++] = &line[i]; + } + } + for (i = 0; i < idx; i++) { + if (strcmp(vec[i], FUNCTION)) + continue; + consume_symbol(vec[i + 1]); + } + vec[idx++] = filename; + vec[idx] = NULL; + exec_kernel_doc(vec); +} + +/* + * Insert specific documentation section from a file. + * Call kernel-doc with the following parameters: + * kernel-doc -docbook -function "doc section" filename + */ +static void docsect(char *filename, char *line) +{ + char *vec[6]; /* kerneldoc -docbook -function "section" file NULL */ + char *s; + + for (s = line; *s; s++) + if (*s == '\n') + *s = '\0'; + + if (asprintf(&s, "DOC: %s", line) < 0) { + perror("asprintf"); + exit(1); + } + consume_symbol(s); + free(s); + + vec[0] = KERNELDOC; + vec[1] = DOCBOOK; + vec[2] = FUNCTION; + vec[3] = line; + vec[4] = filename; + vec[5] = NULL; + exec_kernel_doc(vec); +} + +static void find_all_symbols(char *filename) +{ + char *vec[4]; /* kerneldoc -list file NULL */ + pid_t pid; + int ret, i, count, start; + char real_filename[PATH_MAX + 1]; + int pipefd[2]; + char *data, *str; + size_t data_len = 0; + + vec[0] = KERNELDOC; + vec[1] = LIST; + vec[2] = filename; + vec[3] = NULL; + + if (pipe(pipefd)) { + perror("pipe"); + exit(1); + } + + switch (pid=fork()) { + case -1: + perror("fork"); + exit(1); + case 0: + close(pipefd[0]); + dup2(pipefd[1], 1); + memset(real_filename, 0, sizeof(real_filename)); + strncat(real_filename, kernsrctree, PATH_MAX); + strncat(real_filename, "/" KERNELDOCPATH KERNELDOC, + PATH_MAX - strlen(real_filename)); + execvp(real_filename, vec); + fprintf(stderr, "exec "); + perror(real_filename); + exit(1); + default: + close(pipefd[1]); + data = malloc(4096); + do { + while ((ret = read(pipefd[0], + data + data_len, + 4096)) > 0) { + data_len += ret; + data = realloc(data, data_len + 4096); + } + } while (ret == -EAGAIN); + if (ret != 0) { + perror("read"); + exit(1); + } + waitpid(pid, &ret ,0); + } + if (WIFEXITED(ret)) + exitstatus |= WEXITSTATUS(ret); + else + exitstatus = 0xff; + + count = 0; + /* poor man's strtok, but with counting */ + for (i = 0; i < data_len; i++) { + if (data[i] == '\n') { + count++; + data[i] = '\0'; + } + } + start = all_list_len; + all_list_len += count; + all_list = realloc(all_list, sizeof(char *) * all_list_len); + str = data; + for (i = 0; i < data_len && start != all_list_len; i++) { + if (data[i] == '\0') { + all_list[start] = str; + str = data + i + 1; + start++; + } + } +} + +/* + * Parse file, calling action specific functions for: + * 1) Lines containing !E + * 2) Lines containing !I + * 3) Lines containing !D + * 4) Lines containing !F + * 5) Lines containing !P + * 6) Lines containing !C + * 7) Default lines - lines not matching the above + */ +static void parse_file(FILE *infile) +{ + char line[MAXLINESZ]; + char * s; + while (fgets(line, MAXLINESZ, infile)) { + if (line[0] == '!') { + s = line + 2; + switch (line[1]) { + case 'E': + while (*s && !isspace(*s)) s++; + *s = '\0'; + externalfunctions(line+2); + break; + case 'I': + while (*s && !isspace(*s)) s++; + *s = '\0'; + internalfunctions(line+2); + break; + case 'D': + while (*s && !isspace(*s)) s++; + *s = '\0'; + symbolsonly(line+2); + break; + case 'F': + /* filename */ + while (*s && !isspace(*s)) s++; + *s++ = '\0'; + /* function names */ + while (isspace(*s)) + s++; + singlefunctions(line +2, s); + break; + case 'P': + /* filename */ + while (*s && !isspace(*s)) s++; + *s++ = '\0'; + /* DOC: section name */ + while (isspace(*s)) + s++; + docsection(line + 2, s); + break; + case 'C': + while (*s && !isspace(*s)) s++; + *s = '\0'; + if (findall) + findall(line+2); + break; + default: + defaultline(line); + } + } + else { + defaultline(line); + } + } + fflush(stdout); +} + + +int main(int argc, char *argv[]) +{ + FILE * infile; + int i; + + srctree = getenv("SRCTREE"); + if (!srctree) + srctree = getcwd(NULL, 0); + kernsrctree = getenv("KBUILD_SRC"); + if (!kernsrctree || !*kernsrctree) + kernsrctree = srctree; + if (argc != 3) { + usage(); + exit(1); + } + /* Open file, exit on error */ + infile = fopen(argv[2], "r"); + if (infile == NULL) { + fprintf(stderr, "docproc: "); + perror(argv[2]); + exit(2); + } + + if (strcmp("doc", argv[1]) == 0) + { + /* Need to do this in two passes. + * First pass is used to collect all symbols exported + * in the various files; + * Second pass generate the documentation. + * This is required because some functions are declared + * and exported in different files :-(( + */ + /* Collect symbols */ + defaultline = noaction; + internalfunctions = find_export_symbols; + externalfunctions = find_export_symbols; + symbolsonly = find_export_symbols; + singlefunctions = noaction2; + docsection = noaction2; + findall = find_all_symbols; + parse_file(infile); + + /* Rewind to start from beginning of file again */ + fseek(infile, 0, SEEK_SET); + defaultline = printline; + internalfunctions = intfunc; + externalfunctions = extfunc; + symbolsonly = printline; + singlefunctions = singfunc; + docsection = docsect; + findall = NULL; + + parse_file(infile); + + for (i = 0; i < all_list_len; i++) { + if (!all_list[i]) + continue; + fprintf(stderr, "Warning: didn't use docs for %s\n", + all_list[i]); + } + } + else if (strcmp("depend", argv[1]) == 0) + { + /* Create first part of dependency chain + * file.tmpl */ + printf("%s\t", argv[2]); + defaultline = noaction; + internalfunctions = adddep; + externalfunctions = adddep; + symbolsonly = adddep; + singlefunctions = adddep2; + docsection = adddep2; + findall = adddep; + parse_file(infile); + printf("\n"); + } + else + { + fprintf(stderr, "Unknown option: %s\n", argv[1]); + exit(1); + } + fclose(infile); + fflush(stdout); + return exitstatus; +} diff --git a/l4/tool/kconfig/scripts/basic/fixdep.c b/l4/tool/kconfig/scripts/basic/fixdep.c new file mode 100644 index 00000000..cb1f50cf --- /dev/null +++ b/l4/tool/kconfig/scripts/basic/fixdep.c @@ -0,0 +1,433 @@ +/* + * "Optimize" a list of dependencies as spit out by gcc -MD + * for the kernel build + * =========================================================================== + * + * Author Kai Germaschewski + * Copyright 2002 by Kai Germaschewski + * + * This software may be used and distributed according to the terms + * of the GNU General Public License, incorporated herein by reference. + * + * + * Introduction: + * + * gcc produces a very nice and correct list of dependencies which + * tells make when to remake a file. + * + * To use this list as-is however has the drawback that virtually + * every file in the kernel includes autoconf.h. + * + * If the user re-runs make *config, autoconf.h will be + * regenerated. make notices that and will rebuild every file which + * includes autoconf.h, i.e. basically all files. This is extremely + * annoying if the user just changed CONFIG_HIS_DRIVER from n to m. + * + * So we play the same trick that "mkdep" played before. We replace + * the dependency on autoconf.h by a dependency on every config + * option which is mentioned in any of the listed prequisites. + * + * kconfig populates a tree in include/config/ with an empty file + * for each config symbol and when the configuration is updated + * the files representing changed config options are touched + * which then let make pick up the changes and the files that use + * the config symbols are rebuilt. + * + * So if the user changes his CONFIG_HIS_DRIVER option, only the objects + * which depend on "include/linux/config/his/driver.h" will be rebuilt, + * so most likely only his driver ;-) + * + * The idea above dates, by the way, back to Michael E Chastain, AFAIK. + * + * So to get dependencies right, there are two issues: + * o if any of the files the compiler read changed, we need to rebuild + * o if the command line given to the compile the file changed, we + * better rebuild as well. + * + * The former is handled by using the -MD output, the later by saving + * the command line used to compile the old object and comparing it + * to the one we would now use. + * + * Again, also this idea is pretty old and has been discussed on + * kbuild-devel a long time ago. I don't have a sensibly working + * internet connection right now, so I rather don't mention names + * without double checking. + * + * This code here has been based partially based on mkdep.c, which + * says the following about its history: + * + * Copyright abandoned, Michael Chastain, . + * This is a C version of syncdep.pl by Werner Almesberger. + * + * + * It is invoked as + * + * fixdep + * + * and will read the dependency file + * + * The transformed dependency snipped is written to stdout. + * + * It first generates a line + * + * cmd_ = + * + * and then basically copies the ..d file to stdout, in the + * process filtering out the dependency on autoconf.h and adding + * dependencies on include/config/my/option.h for every + * CONFIG_MY_OPTION encountered in any of the prequisites. + * + * It will also filter out all the dependencies on *.ver. We need + * to make sure that the generated version checksum are globally up + * to date before even starting the recursive build, so it's too late + * at this point anyway. + * + * The algorithm to grep for "CONFIG_..." is bit unusual, but should + * be fast ;-) We don't even try to really parse the header files, but + * merely grep, i.e. if CONFIG_FOO is mentioned in a comment, it will + * be picked up as well. It's not a problem with respect to + * correctness, since that can only give too many dependencies, thus + * we cannot miss a rebuild. Since people tend to not mention totally + * unrelated CONFIG_ options all over the place, it's not an + * efficiency problem either. + * + * (Note: it'd be easy to port over the complete mkdep state machine, + * but I don't think the added complexity is worth it) + */ +/* + * Note 2: if somebody writes HELLO_CONFIG_BOOM in a file, it will depend onto + * CONFIG_BOOM. This could seem a bug (not too hard to fix), but please do not + * fix it! Some UserModeLinux files (look at arch/um/) call CONFIG_BOOM as + * UML_CONFIG_BOOM, to avoid conflicts with /usr/include/linux/autoconf.h, + * through arch/um/include/uml-config.h; this fixdep "bug" makes sure that + * those files will have correct dependencies. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define INT_CONF ntohl(0x434f4e46) +#define INT_ONFI ntohl(0x4f4e4649) +#define INT_NFIG ntohl(0x4e464947) +#define INT_FIG_ ntohl(0x4649475f) + +char *target; +char *depfile; +char *cmdline; + +static void usage(void) +{ + fprintf(stderr, "Usage: fixdep \n"); + exit(1); +} + +/* + * Print out the commandline prefixed with cmd_ := + */ +static void print_cmdline(void) +{ + printf("cmd_%s := %s\n\n", target, cmdline); +} + +struct item { + struct item *next; + unsigned int len; + unsigned int hash; + char name[0]; +}; + +#define HASHSZ 256 +static struct item *hashtab[HASHSZ]; + +static unsigned int strhash(const char *str, unsigned int sz) +{ + /* fnv32 hash */ + unsigned int i, hash = 2166136261U; + + for (i = 0; i < sz; i++) + hash = (hash ^ str[i]) * 0x01000193; + return hash; +} + +/* + * Lookup a value in the configuration string. + */ +static int is_defined_config(const char *name, int len, unsigned int hash) +{ + struct item *aux; + + for (aux = hashtab[hash % HASHSZ]; aux; aux = aux->next) { + if (aux->hash == hash && aux->len == len && + memcmp(aux->name, name, len) == 0) + return 1; + } + return 0; +} + +/* + * Add a new value to the configuration string. + */ +static void define_config(const char *name, int len, unsigned int hash) +{ + struct item *aux = malloc(sizeof(*aux) + len); + + if (!aux) { + perror("fixdep:malloc"); + exit(1); + } + memcpy(aux->name, name, len); + aux->len = len; + aux->hash = hash; + aux->next = hashtab[hash % HASHSZ]; + hashtab[hash % HASHSZ] = aux; +} + +/* + * Clear the set of configuration strings. + */ +static void clear_config(void) +{ + struct item *aux, *next; + unsigned int i; + + for (i = 0; i < HASHSZ; i++) { + for (aux = hashtab[i]; aux; aux = next) { + next = aux->next; + free(aux); + } + hashtab[i] = NULL; + } +} + +/* + * Record the use of a CONFIG_* word. + */ +static void use_config(const char *m, int slen) +{ + unsigned int hash = strhash(m, slen); + int c, i; + + if (is_defined_config(m, slen, hash)) + return; + + define_config(m, slen, hash); + + printf(" $(wildcard include/config/"); + for (i = 0; i < slen; i++) { + c = m[i]; + if (c == '_') + c = '/'; + else + c = tolower(c); + putchar(c); + } + printf(".h) \\\n"); +} + +static void parse_config_file(const char *map, size_t len) +{ + const int *end = (const int *) (map + len); + /* start at +1, so that p can never be < map */ + const int *m = (const int *) map + 1; + const char *p, *q; + + for (; m < end; m++) { + if (*m == INT_CONF) { p = (char *) m ; goto conf; } + if (*m == INT_ONFI) { p = (char *) m-1; goto conf; } + if (*m == INT_NFIG) { p = (char *) m-2; goto conf; } + if (*m == INT_FIG_) { p = (char *) m-3; goto conf; } + continue; + conf: + if (p > map + len - 7) + continue; + if (memcmp(p, "CONFIG_", 7)) + continue; + for (q = p + 7; q < map + len; q++) { + if (!(isalnum(*q) || *q == '_')) + goto found; + } + continue; + + found: + if (!memcmp(q - 7, "_MODULE", 7)) + q -= 7; + if( (q-p-7) < 0 ) + continue; + use_config(p+7, q-p-7); + } +} + +/* test is s ends in sub */ +static int strrcmp(char *s, char *sub) +{ + int slen = strlen(s); + int sublen = strlen(sub); + + if (sublen > slen) + return 1; + + return memcmp(s + slen - sublen, sub, sublen); +} + +static void do_config_file(const char *filename) +{ + struct stat st; + int fd; + void *map; + + fd = open(filename, O_RDONLY); + if (fd < 0) { + fprintf(stderr, "fixdep: error opening config file: "); + perror(filename); + exit(2); + } + fstat(fd, &st); + if (st.st_size == 0) { + close(fd); + return; + } + map = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + if ((long) map == -1) { + perror("fixdep: mmap"); + close(fd); + return; + } + + parse_config_file(map, st.st_size); + + munmap(map, st.st_size); + + close(fd); +} + +/* + * Important: The below generated source_foo.o and deps_foo.o variable + * assignments are parsed not only by make, but also by the rather simple + * parser in scripts/mod/sumversion.c. + */ +static void parse_dep_file(void *map, size_t len) +{ + char *m = map; + char *end = m + len; + char *p; + char s[PATH_MAX]; + int first; + + p = strchr(m, ':'); + if (!p) { + fprintf(stderr, "fixdep: parse error\n"); + exit(1); + } + memcpy(s, m, p-m); s[p-m] = 0; + m = p+1; + + clear_config(); + + first = 1; + while (m < end) { + while (m < end && (*m == ' ' || *m == '\\' || *m == '\n')) + m++; + p = m; + while (p < end && *p != ' ') p++; + if (p == end) { + do p--; while (!isalnum(*p)); + p++; + } + memcpy(s, m, p-m); s[p-m] = 0; + if (strrcmp(s, "include/generated/autoconf.h") && + strrcmp(s, "arch/um/include/uml-config.h") && + strrcmp(s, "include/linux/kconfig.h") && + strrcmp(s, ".ver")) { + /* + * Do not list the source file as dependency, so that + * kbuild is not confused if a .c file is rewritten + * into .S or vice versa. Storing it in source_* is + * needed for modpost to compute srcversions. + */ + if (first) { + printf("source_%s := %s\n\n", target, s); + printf("deps_%s := \\\n", target); + } else + printf(" %s \\\n", s); + do_config_file(s); + } + first = 0; + m = p + 1; + } + printf("\n%s: $(deps_%s)\n\n", target, target); + printf("$(deps_%s):\n", target); +} + +static void print_deps(void) +{ + struct stat st; + int fd; + void *map; + + fd = open(depfile, O_RDONLY); + if (fd < 0) { + fprintf(stderr, "fixdep: error opening depfile: "); + perror(depfile); + exit(2); + } + if (fstat(fd, &st) < 0) { + fprintf(stderr, "fixdep: error fstat'ing depfile: "); + perror(depfile); + exit(2); + } + if (st.st_size == 0) { + fprintf(stderr,"fixdep: %s is empty\n",depfile); + close(fd); + return; + } + map = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + if ((long) map == -1) { + perror("fixdep: mmap"); + close(fd); + return; + } + + parse_dep_file(map, st.st_size); + + munmap(map, st.st_size); + + close(fd); +} + +static void traps(void) +{ + static char test[] __attribute__((aligned(sizeof(int)))) = "CONF"; + int *p = (int *)test; + + if (*p != INT_CONF) { + fprintf(stderr, "fixdep: sizeof(int) != 4 or wrong endianess? %#x\n", + *p); + exit(2); + } +} + +int main(int argc, char *argv[]) +{ + traps(); + + if (argc != 4) + usage(); + + depfile = argv[1]; + target = argv[2]; + cmdline = argv[3]; + + print_cmdline(); + print_deps(); + + return 0; +} diff --git a/l4/tool/kconfig/scripts/basic/hash.c b/l4/tool/kconfig/scripts/basic/hash.c new file mode 100644 index 00000000..2ef5d3f6 --- /dev/null +++ b/l4/tool/kconfig/scripts/basic/hash.c @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2008 Red Hat, Inc., Jason Baron + * + */ + +#include +#include +#include + +#define DYNAMIC_DEBUG_HASH_BITS 6 + +static const char *program; + +static void usage(void) +{ + printf("Usage: %s \n", program); + exit(1); +} + +/* djb2 hashing algorithm by Dan Bernstein. From: + * http://www.cse.yorku.ca/~oz/hash.html + */ + +static unsigned int djb2_hash(char *str) +{ + unsigned long hash = 5381; + int c; + + c = *str; + while (c) { + hash = ((hash << 5) + hash) + c; + c = *++str; + } + return (unsigned int)(hash & ((1 << DYNAMIC_DEBUG_HASH_BITS) - 1)); +} + +static unsigned int r5_hash(char *str) +{ + unsigned long hash = 0; + int c; + + c = *str; + while (c) { + hash = (hash + (c << 4) + (c >> 4)) * 11; + c = *++str; + } + return (unsigned int)(hash & ((1 << DYNAMIC_DEBUG_HASH_BITS) - 1)); +} + +int main(int argc, char *argv[]) +{ + program = argv[0]; + + if (argc != 3) + usage(); + if (!strcmp(argv[1], "djb2")) + printf("%d\n", djb2_hash(argv[2])); + else if (!strcmp(argv[1], "r5")) + printf("%d\n", r5_hash(argv[2])); + else + usage(); + exit(0); +} + diff --git a/l4/tool/kconfig/scripts/kconfig/.gitignore b/l4/tool/kconfig/scripts/kconfig/.gitignore new file mode 100644 index 00000000..ee120d44 --- /dev/null +++ b/l4/tool/kconfig/scripts/kconfig/.gitignore @@ -0,0 +1,23 @@ +# +# Generated files +# +config* +*.lex.c +*.tab.c +*.tab.h +zconf.hash.c +*.moc +lkc_defs.h +gconf.glade.h +*.pot +*.mo + +# +# configuration programs +# +conf +mconf +nconf +qconf +gconf +kxgettext diff --git a/l4/tool/kconfig/scripts/kconfig/Makefile b/l4/tool/kconfig/scripts/kconfig/Makefile new file mode 100644 index 00000000..79662658 --- /dev/null +++ b/l4/tool/kconfig/scripts/kconfig/Makefile @@ -0,0 +1,308 @@ +# =========================================================================== +# Kernel configuration targets +# These targets are used from top-level makefile + +PHONY += oldconfig xconfig gconfig menuconfig config silentoldconfig update-po-config \ + localmodconfig localyesconfig + +ifdef KBUILD_KCONFIG +Kconfig := $(KBUILD_KCONFIG) +else +Kconfig := Kconfig +endif + +xconfig: $(obj)/qconf + $< $(Kconfig) + +gconfig: $(obj)/gconf + $< $(Kconfig) + +menuconfig: $(obj)/mconf + $< $(Kconfig) + +config: $(obj)/conf + $< --oldaskconfig $(Kconfig) + +nconfig: $(obj)/nconf + $< $(Kconfig) + +oldconfig: $(obj)/conf + $< --$@ $(Kconfig) + +silentoldconfig: $(obj)/conf + $(Q)mkdir -p include/generated + $< --$@ $(Kconfig) + +localyesconfig localmodconfig: $(obj)/streamline_config.pl $(obj)/conf + $(Q)mkdir -p include/generated + $(Q)perl $< --$@ $(srctree) $(Kconfig) > .tmp.config + $(Q)if [ -f .config ]; then \ + cmp -s .tmp.config .config || \ + (mv -f .config .config.old.1; \ + mv -f .tmp.config .config; \ + $(obj)/conf --silentoldconfig $(Kconfig); \ + mv -f .config.old.1 .config.old) \ + else \ + mv -f .tmp.config .config; \ + $(obj)/conf --silentoldconfig $(Kconfig); \ + fi + $(Q)rm -f .tmp.config + +# Create new linux.pot file +# Adjust charset to UTF-8 in .po file to accept UTF-8 in Kconfig files +update-po-config: $(obj)/kxgettext $(obj)/gconf.glade.h + $(Q)echo " GEN config.pot" + $(Q)xgettext --default-domain=linux \ + --add-comments --keyword=_ --keyword=N_ \ + --from-code=UTF-8 \ + --files-from=$(srctree)/scripts/kconfig/POTFILES.in \ + --directory=$(srctree) --directory=$(objtree) \ + --output $(obj)/config.pot + $(Q)sed -i s/CHARSET/UTF-8/ $(obj)/config.pot + $(Q)(for i in `ls $(srctree)/arch/*/Kconfig \ + $(srctree)/arch/*/um/Kconfig`; \ + do \ + echo " GEN $$i"; \ + $(obj)/kxgettext $$i \ + >> $(obj)/config.pot; \ + done ) + $(Q)echo " GEN linux.pot" + $(Q)msguniq --sort-by-file --to-code=UTF-8 $(obj)/config.pot \ + --output $(obj)/linux.pot + $(Q)rm -f $(obj)/config.pot + +PHONY += allnoconfig allyesconfig allmodconfig alldefconfig randconfig + +allnoconfig allyesconfig allmodconfig alldefconfig randconfig: $(obj)/conf + $< --$@ $(Kconfig) + +PHONY += listnewconfig oldnoconfig savedefconfig defconfig + +listnewconfig oldnoconfig: $(obj)/conf + $< --$@ $(Kconfig) + +savedefconfig: $(obj)/conf + $< --$@=defconfig $(Kconfig) + +defconfig: $(obj)/conf +ifeq ($(KBUILD_DEFCONFIG),) + $< --defconfig $(Kconfig) +else + @echo "*** Default configuration is based on '$(KBUILD_DEFCONFIG)'" + $(Q)$< --defconfig=arch/$(SRCARCH)/configs/$(KBUILD_DEFCONFIG) $(Kconfig) +endif + +%_defconfig: $(obj)/conf + $(Q)$< --defconfig=arch/$(SRCARCH)/configs/$@ $(Kconfig) + +# Help text used by make help +help: + @echo ' config - Update current config utilising a line-oriented program' + @echo ' nconfig - Update current config utilising a ncurses menu based program' + @echo ' menuconfig - Update current config utilising a menu based program' + @echo ' xconfig - Update current config utilising a QT based front-end' + @echo ' gconfig - Update current config utilising a GTK based front-end' + @echo ' oldconfig - Update current config utilising a provided .config as base' + @echo ' localmodconfig - Update current config disabling modules not loaded' + @echo ' localyesconfig - Update current config converting local mods to core' + @echo ' silentoldconfig - Same as oldconfig, but quietly, additionally update deps' + @echo ' defconfig - New config with default from ARCH supplied defconfig' + @echo ' savedefconfig - Save current config as ./defconfig (minimal config)' + @echo ' allnoconfig - New config where all options are answered with no' + @echo ' allyesconfig - New config where all options are accepted with yes' + @echo ' allmodconfig - New config selecting modules when possible' + @echo ' alldefconfig - New config with all symbols set to default' + @echo ' randconfig - New config with random answer to all options' + @echo ' listnewconfig - List new options' + @echo ' oldnoconfig - Same as silentoldconfig but set new symbols to n (unset)' + +# lxdialog stuff +check-lxdialog := $(srctree)/$(src)/lxdialog/check-lxdialog.sh + +# Use recursively expanded variables so we do not call gcc unless +# we really need to do so. (Do not call gcc as part of make mrproper) +HOST_EXTRACFLAGS += $(shell $(CONFIG_SHELL) $(check-lxdialog) -ccflags) \ + -DLOCALE + +# =========================================================================== +# Shared Makefile for the various kconfig executables: +# conf: Used for defconfig, oldconfig and related targets +# nconf: Used for the nconfig target. +# Utilizes ncurses +# mconf: Used for the menuconfig target +# Utilizes the lxdialog package +# qconf: Used for the xconfig target +# Based on QT which needs to be installed to compile it +# gconf: Used for the gconfig target +# Based on GTK which needs to be installed to compile it +# object files used by all kconfig flavours + +lxdialog := lxdialog/checklist.o lxdialog/util.o lxdialog/inputbox.o +lxdialog += lxdialog/textbox.o lxdialog/yesno.o lxdialog/menubox.o + +conf-objs := conf.o zconf.tab.o +mconf-objs := mconf.o zconf.tab.o $(lxdialog) +nconf-objs := nconf.o zconf.tab.o nconf.gui.o +kxgettext-objs := kxgettext.o zconf.tab.o +qconf-cxxobjs := qconf.o +qconf-objs := zconf.tab.o +gconf-objs := gconf.o zconf.tab.o + +hostprogs-y := conf + +ifeq ($(MAKECMDGOALS),nconfig) + hostprogs-y += nconf +endif + +ifeq ($(MAKECMDGOALS),menuconfig) + hostprogs-y += mconf +endif + +ifeq ($(MAKECMDGOALS),update-po-config) + hostprogs-y += kxgettext +endif + +ifeq ($(MAKECMDGOALS),xconfig) + qconf-target := 1 +endif +ifeq ($(MAKECMDGOALS),gconfig) + gconf-target := 1 +endif + + +ifeq ($(qconf-target),1) + hostprogs-y += qconf +endif + +ifeq ($(gconf-target),1) + hostprogs-y += gconf +endif + +clean-files := qconf.moc .tmp_qtcheck .tmp_gtkcheck +clean-files += zconf.tab.c zconf.lex.c zconf.hash.c gconf.glade.h +clean-files += mconf qconf gconf nconf +clean-files += config.pot linux.pot + +# Check that we have the required ncurses stuff installed for lxdialog (menuconfig) +PHONY += $(obj)/dochecklxdialog +$(addprefix $(obj)/,$(lxdialog)): $(obj)/dochecklxdialog +$(obj)/dochecklxdialog: + $(Q)$(CONFIG_SHELL) $(check-lxdialog) -check $(HOSTCC) $(HOST_EXTRACFLAGS) $(HOSTLOADLIBES_mconf) + +always := dochecklxdialog + +# Add environment specific flags +HOST_EXTRACFLAGS += $(shell $(CONFIG_SHELL) $(srctree)/$(src)/check.sh $(HOSTCC) $(HOSTCFLAGS)) + +# generated files seem to need this to find local include files +HOSTCFLAGS_zconf.lex.o := -I$(src) +HOSTCFLAGS_zconf.tab.o := -I$(src) + +LEX_PREFIX_zconf := zconf +YACC_PREFIX_zconf := zconf + +HOSTLOADLIBES_qconf = $(KC_QT_LIBS) +HOSTCXXFLAGS_qconf.o = $(KC_QT_CFLAGS) + +HOSTLOADLIBES_gconf = `pkg-config --libs gtk+-2.0 gmodule-2.0 libglade-2.0` +HOSTCFLAGS_gconf.o = `pkg-config --cflags gtk+-2.0 gmodule-2.0 libglade-2.0` \ + -Wno-missing-prototypes + +HOSTLOADLIBES_mconf = $(shell $(CONFIG_SHELL) $(check-lxdialog) -ldflags $(HOSTCC)) + +HOSTLOADLIBES_nconf = -lmenu -lpanel -lncurses +$(obj)/qconf.o: $(obj)/.tmp_qtcheck + +ifeq ($(qconf-target),1) +$(obj)/.tmp_qtcheck: $(src)/Makefile +-include $(obj)/.tmp_qtcheck + +# QT needs some extra effort... +$(obj)/.tmp_qtcheck: + @set -e; echo " CHECK qt"; dir=""; pkg=""; \ + if ! pkg-config --exists QtCore 2> /dev/null; then \ + echo "* Unable to find the QT4 tool qmake. Trying to use QT3"; \ + pkg-config --exists qt 2> /dev/null && pkg=qt; \ + pkg-config --exists qt-mt 2> /dev/null && pkg=qt-mt; \ + if [ -n "$$pkg" ]; then \ + cflags="\$$(shell pkg-config $$pkg --cflags)"; \ + libs="\$$(shell pkg-config $$pkg --libs)"; \ + moc="\$$(shell pkg-config $$pkg --variable=prefix)/bin/moc"; \ + dir="$$(pkg-config $$pkg --variable=prefix)"; \ + else \ + for d in $$QTDIR /usr/share/qt* /usr/lib/qt*; do \ + if [ -f $$d/include/qconfig.h ]; then dir=$$d; break; fi; \ + done; \ + if [ -z "$$dir" ]; then \ + echo "*"; \ + echo "* Unable to find any QT installation. Please make sure that"; \ + echo "* the QT4 or QT3 development package is correctly installed and"; \ + echo "* either qmake can be found or install pkg-config or set"; \ + echo "* the QTDIR environment variable to the correct location."; \ + echo "*"; \ + false; \ + fi; \ + libpath=$$dir/lib; lib=qt; osdir=""; \ + $(HOSTCXX) -print-multi-os-directory > /dev/null 2>&1 && \ + osdir=x$$($(HOSTCXX) -print-multi-os-directory); \ + test -d $$libpath/$$osdir && libpath=$$libpath/$$osdir; \ + test -f $$libpath/libqt-mt.so && lib=qt-mt; \ + cflags="-I$$dir/include"; \ + libs="-L$$libpath -Wl,-rpath,$$libpath -l$$lib"; \ + moc="$$dir/bin/moc"; \ + fi; \ + if [ ! -x $$dir/bin/moc -a -x /usr/bin/moc ]; then \ + echo "*"; \ + echo "* Unable to find $$dir/bin/moc, using /usr/bin/moc instead."; \ + echo "*"; \ + moc="/usr/bin/moc"; \ + fi; \ + else \ + cflags="\$$(shell pkg-config QtCore QtGui Qt3Support --cflags)"; \ + libs="\$$(shell pkg-config QtCore QtGui Qt3Support --libs)"; \ + binpath="\$$(shell pkg-config QtCore --variable=prefix)"; \ + moc="$$binpath/bin/moc"; \ + fi; \ + echo "KC_QT_CFLAGS=$$cflags" > $@; \ + echo "KC_QT_LIBS=$$libs" >> $@; \ + echo "KC_QT_MOC=$$moc" >> $@ +endif + +$(obj)/gconf.o: $(obj)/.tmp_gtkcheck + +ifeq ($(gconf-target),1) +-include $(obj)/.tmp_gtkcheck + +# GTK needs some extra effort, too... +$(obj)/.tmp_gtkcheck: + @if `pkg-config --exists gtk+-2.0 gmodule-2.0 libglade-2.0`; then \ + if `pkg-config --atleast-version=2.0.0 gtk+-2.0`; then \ + touch $@; \ + else \ + echo "*"; \ + echo "* GTK+ is present but version >= 2.0.0 is required."; \ + echo "*"; \ + false; \ + fi \ + else \ + echo "*"; \ + echo "* Unable to find the GTK+ installation. Please make sure that"; \ + echo "* the GTK+ 2.0 development package is correctly installed..."; \ + echo "* You need gtk+-2.0, glib-2.0 and libglade-2.0."; \ + echo "*"; \ + false; \ + fi +endif + +$(obj)/zconf.tab.o: $(obj)/zconf.lex.c $(obj)/zconf.hash.c + +$(obj)/qconf.o: $(obj)/qconf.moc + +$(obj)/%.moc: $(src)/%.h + $(KC_QT_MOC) -i $< -o $@ + +# Extract gconf menu items for I18N support +$(obj)/gconf.glade.h: $(obj)/gconf.glade + $(Q)intltool-extract --type=gettext/glade --srcdir=$(srctree) \ + $(obj)/gconf.glade + diff --git a/l4/tool/kconfig/scripts/kconfig/POTFILES.in b/l4/tool/kconfig/scripts/kconfig/POTFILES.in new file mode 100644 index 00000000..96745739 --- /dev/null +++ b/l4/tool/kconfig/scripts/kconfig/POTFILES.in @@ -0,0 +1,12 @@ +scripts/kconfig/lxdialog/checklist.c +scripts/kconfig/lxdialog/inputbox.c +scripts/kconfig/lxdialog/menubox.c +scripts/kconfig/lxdialog/textbox.c +scripts/kconfig/lxdialog/util.c +scripts/kconfig/lxdialog/yesno.c +scripts/kconfig/mconf.c +scripts/kconfig/conf.c +scripts/kconfig/confdata.c +scripts/kconfig/gconf.c +scripts/kconfig/gconf.glade.h +scripts/kconfig/qconf.cc diff --git a/l4/tool/kconfig/scripts/kconfig/check.sh b/l4/tool/kconfig/scripts/kconfig/check.sh new file mode 100755 index 00000000..fa59cbf9 --- /dev/null +++ b/l4/tool/kconfig/scripts/kconfig/check.sh @@ -0,0 +1,14 @@ +#!/bin/sh +# Needed for systems without gettext +$* -xc -o /dev/null - > /dev/null 2>&1 << EOF +#include +int main() +{ + gettext(""); + return 0; +} +EOF +if [ ! "$?" -eq "0" ]; then + echo -DKBUILD_NO_NLS; +fi + diff --git a/l4/tool/kconfig/scripts/kconfig/conf.c b/l4/tool/kconfig/scripts/kconfig/conf.c new file mode 100644 index 00000000..0dc4a2c7 --- /dev/null +++ b/l4/tool/kconfig/scripts/kconfig/conf.c @@ -0,0 +1,694 @@ +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "lkc.h" + +static void conf(struct menu *menu); +static void check_conf(struct menu *menu); +static void xfgets(char *str, int size, FILE *in); + +enum input_mode { + oldaskconfig, + silentoldconfig, + oldconfig, + allnoconfig, + allyesconfig, + allmodconfig, + alldefconfig, + randconfig, + defconfig, + savedefconfig, + listnewconfig, + oldnoconfig, +} input_mode = oldaskconfig; + +static int indent = 1; +static int valid_stdin = 1; +static int sync_kconfig; +static int conf_cnt; +static char line[128]; +static struct menu *rootEntry; + +static void print_help(struct menu *menu) +{ + struct gstr help = str_new(); + + menu_get_ext_help(menu, &help); + + printf("\n%s\n", str_get(&help)); + str_free(&help); +} + +static void strip(char *str) +{ + char *p = str; + int l; + + while ((isspace(*p))) + p++; + l = strlen(p); + if (p != str) + memmove(str, p, l + 1); + if (!l) + return; + p = str + l - 1; + while ((isspace(*p))) + *p-- = 0; +} + +static void check_stdin(void) +{ + if (!valid_stdin) { + printf(_("aborted!\n\n")); + printf(_("Console input/output is redirected. ")); + printf(_("Run 'make oldconfig' to update configuration.\n\n")); + exit(1); + } +} + +static int conf_askvalue(struct symbol *sym, const char *def) +{ + enum symbol_type type = sym_get_type(sym); + + if (!sym_has_value(sym)) + printf(_("(NEW) ")); + + line[0] = '\n'; + line[1] = 0; + + if (!sym_is_changable(sym)) { + printf("%s\n", def); + line[0] = '\n'; + line[1] = 0; + return 0; + } + + switch (input_mode) { + case oldconfig: + case silentoldconfig: + if (sym_has_value(sym)) { + printf("%s\n", def); + return 0; + } + check_stdin(); + /* fall through */ + case oldaskconfig: + fflush(stdout); + xfgets(line, 128, stdin); + return 1; + default: + break; + } + + switch (type) { + case S_INT: + case S_HEX: + case S_STRING: + printf("%s\n", def); + return 1; + default: + ; + } + printf("%s", line); + return 1; +} + +static int conf_string(struct menu *menu) +{ + struct symbol *sym = menu->sym; + const char *def; + + while (1) { + printf("%*s%s ", indent - 1, "", _(menu->prompt->text)); + printf("(%s) ", sym->name); + def = sym_get_string_value(sym); + if (sym_get_string_value(sym)) + printf("[%s] ", def); + if (!conf_askvalue(sym, def)) + return 0; + switch (line[0]) { + case '\n': + break; + case '?': + /* print help */ + if (line[1] == '\n') { + print_help(menu); + def = NULL; + break; + } + /* fall through */ + default: + line[strlen(line)-1] = 0; + def = line; + } + if (def && sym_set_string_value(sym, def)) + return 0; + } +} + +static int conf_sym(struct menu *menu) +{ + struct symbol *sym = menu->sym; + tristate oldval, newval; + + while (1) { + printf("%*s%s ", indent - 1, "", _(menu->prompt->text)); + if (sym->name) + printf("(%s) ", sym->name); + putchar('['); + oldval = sym_get_tristate_value(sym); + switch (oldval) { + case no: + putchar('N'); + break; + case mod: + putchar('M'); + break; + case yes: + putchar('Y'); + break; + } + if (oldval != no && sym_tristate_within_range(sym, no)) + printf("/n"); + if (oldval != mod && sym_tristate_within_range(sym, mod)) + printf("/m"); + if (oldval != yes && sym_tristate_within_range(sym, yes)) + printf("/y"); + if (menu_has_help(menu)) + printf("/?"); + printf("] "); + if (!conf_askvalue(sym, sym_get_string_value(sym))) + return 0; + strip(line); + + switch (line[0]) { + case 'n': + case 'N': + newval = no; + if (!line[1] || !strcmp(&line[1], "o")) + break; + continue; + case 'm': + case 'M': + newval = mod; + if (!line[1]) + break; + continue; + case 'y': + case 'Y': + newval = yes; + if (!line[1] || !strcmp(&line[1], "es")) + break; + continue; + case 0: + newval = oldval; + break; + case '?': + goto help; + default: + continue; + } + if (sym_set_tristate_value(sym, newval)) + return 0; +help: + print_help(menu); + } +} + +static int conf_choice(struct menu *menu) +{ + struct symbol *sym, *def_sym; + struct menu *child; + bool is_new; + + sym = menu->sym; + is_new = !sym_has_value(sym); + if (sym_is_changable(sym)) { + conf_sym(menu); + sym_calc_value(sym); + switch (sym_get_tristate_value(sym)) { + case no: + return 1; + case mod: + return 0; + case yes: + break; + } + } else { + switch (sym_get_tristate_value(sym)) { + case no: + return 1; + case mod: + printf("%*s%s\n", indent - 1, "", _(menu_get_prompt(menu))); + return 0; + case yes: + break; + } + } + + while (1) { + int cnt, def; + + printf("%*s%s\n", indent - 1, "", _(menu_get_prompt(menu))); + def_sym = sym_get_choice_value(sym); + cnt = def = 0; + line[0] = 0; + for (child = menu->list; child; child = child->next) { + if (!menu_is_visible(child)) + continue; + if (!child->sym) { + printf("%*c %s\n", indent, '*', _(menu_get_prompt(child))); + continue; + } + cnt++; + if (child->sym == def_sym) { + def = cnt; + printf("%*c", indent, '>'); + } else + printf("%*c", indent, ' '); + printf(" %d. %s", cnt, _(menu_get_prompt(child))); + if (child->sym->name) + printf(" (%s)", child->sym->name); + if (!sym_has_value(child->sym)) + printf(_(" (NEW)")); + printf("\n"); + } + printf(_("%*schoice"), indent - 1, ""); + if (cnt == 1) { + printf("[1]: 1\n"); + goto conf_childs; + } + printf("[1-%d", cnt); + if (menu_has_help(menu)) + printf("?"); + printf("]: "); + switch (input_mode) { + case oldconfig: + case silentoldconfig: + if (!is_new) { + cnt = def; + printf("%d\n", cnt); + break; + } + check_stdin(); + /* fall through */ + case oldaskconfig: + fflush(stdout); + xfgets(line, 128, stdin); + strip(line); + if (line[0] == '?') { + print_help(menu); + continue; + } + if (!line[0]) + cnt = def; + else if (isdigit(line[0])) + cnt = atoi(line); + else + continue; + break; + default: + break; + } + + conf_childs: + for (child = menu->list; child; child = child->next) { + if (!child->sym || !menu_is_visible(child)) + continue; + if (!--cnt) + break; + } + if (!child) + continue; + if (line[0] && line[strlen(line) - 1] == '?') { + print_help(child); + continue; + } + sym_set_choice_value(sym, child->sym); + for (child = child->list; child; child = child->next) { + indent += 2; + conf(child); + indent -= 2; + } + return 1; + } +} + +static void conf(struct menu *menu) +{ + struct symbol *sym; + struct property *prop; + struct menu *child; + + if (!menu_is_visible(menu)) + return; + + sym = menu->sym; + prop = menu->prompt; + if (prop) { + const char *prompt; + + switch (prop->type) { + case P_MENU: + if ((input_mode == silentoldconfig || + input_mode == listnewconfig || + input_mode == oldnoconfig) && + rootEntry != menu) { + check_conf(menu); + return; + } + /* fall through */ + case P_COMMENT: + prompt = menu_get_prompt(menu); + if (prompt) + printf("%*c\n%*c %s\n%*c\n", + indent, '*', + indent, '*', _(prompt), + indent, '*'); + default: + ; + } + } + + if (!sym) + goto conf_childs; + + if (sym_is_choice(sym)) { + conf_choice(menu); + if (sym->curr.tri != mod) + return; + goto conf_childs; + } + + switch (sym->type) { + case S_INT: + case S_HEX: + case S_STRING: + conf_string(menu); + break; + default: + conf_sym(menu); + break; + } + +conf_childs: + if (sym) + indent += 2; + for (child = menu->list; child; child = child->next) + conf(child); + if (sym) + indent -= 2; +} + +static void check_conf(struct menu *menu) +{ + struct symbol *sym; + struct menu *child; + + if (!menu_is_visible(menu)) + return; + + sym = menu->sym; + if (sym && !sym_has_value(sym)) { + if (sym_is_changable(sym) || + (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)) { + if (input_mode == listnewconfig) { + if (sym->name && !sym_is_choice_value(sym)) { + printf("%s%s\n", CONFIG_, sym->name); + } + } else if (input_mode != oldnoconfig) { + if (!conf_cnt++) + printf(_("*\n* Restart config...\n*\n")); + rootEntry = menu_get_parent_menu(menu); + conf(rootEntry); + } + } + } + + for (child = menu->list; child; child = child->next) + check_conf(child); +} + +static struct option long_opts[] = { + {"oldaskconfig", no_argument, NULL, oldaskconfig}, + {"oldconfig", no_argument, NULL, oldconfig}, + {"silentoldconfig", no_argument, NULL, silentoldconfig}, + {"defconfig", optional_argument, NULL, defconfig}, + {"savedefconfig", required_argument, NULL, savedefconfig}, + {"allnoconfig", no_argument, NULL, allnoconfig}, + {"allyesconfig", no_argument, NULL, allyesconfig}, + {"allmodconfig", no_argument, NULL, allmodconfig}, + {"alldefconfig", no_argument, NULL, alldefconfig}, + {"randconfig", no_argument, NULL, randconfig}, + {"listnewconfig", no_argument, NULL, listnewconfig}, + {"oldnoconfig", no_argument, NULL, oldnoconfig}, + {NULL, 0, NULL, 0} +}; + +static void conf_usage(const char *progname) +{ + + printf("Usage: %s [option] \n", progname); + printf("[option] is _one_ of the following:\n"); + printf(" --listnewconfig List new options\n"); + printf(" --oldaskconfig Start a new configuration using a line-oriented program\n"); + printf(" --oldconfig Update a configuration using a provided .config as base\n"); + printf(" --silentoldconfig Same as oldconfig, but quietly, additionally update deps\n"); + printf(" --oldnoconfig Same as silentoldconfig but set new symbols to no\n"); + printf(" --defconfig New config with default defined in \n"); + printf(" --savedefconfig Save the minimal current configuration to \n"); + printf(" --allnoconfig New config where all options are answered with no\n"); + printf(" --allyesconfig New config where all options are answered with yes\n"); + printf(" --allmodconfig New config where all options are answered with mod\n"); + printf(" --alldefconfig New config with all symbols set to default\n"); + printf(" --randconfig New config with random answer to all options\n"); +} + +int main(int ac, char **av) +{ + const char *progname = av[0]; + int opt; + const char *name, *defconfig_file = NULL /* gcc uninit */; + struct stat tmpstat; + + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + + while ((opt = getopt_long(ac, av, "", long_opts, NULL)) != -1) { + input_mode = (enum input_mode)opt; + switch (opt) { + case silentoldconfig: + sync_kconfig = 1; + break; + case defconfig: + case savedefconfig: + defconfig_file = optarg; + break; + case randconfig: + { + struct timeval now; + unsigned int seed; + + /* + * Use microseconds derived seed, + * compensate for systems where it may be zero + */ + gettimeofday(&now, NULL); + + seed = (unsigned int)((now.tv_sec + 1) * (now.tv_usec + 1)); + srand(seed); + break; + } + case oldaskconfig: + case oldconfig: + case allnoconfig: + case allyesconfig: + case allmodconfig: + case alldefconfig: + case listnewconfig: + case oldnoconfig: + break; + case '?': + conf_usage(progname); + exit(1); + break; + } + } + if (ac == optind) { + printf(_("%s: Kconfig file missing\n"), av[0]); + conf_usage(progname); + exit(1); + } + name = av[optind]; + conf_parse(name); + //zconfdump(stdout); + if (sync_kconfig) { + name = conf_get_configname(); + if (stat(name, &tmpstat)) { + fprintf(stderr, _("***\n" + "*** Configuration file \"%s\" not found!\n" + "***\n" + "*** Please run some configurator (e.g. \"make oldconfig\" or\n" + "*** \"make menuconfig\" or \"make xconfig\").\n" + "***\n"), name); + exit(1); + } + } + + switch (input_mode) { + case defconfig: + if (!defconfig_file) + defconfig_file = conf_get_default_confname(); + if (conf_read(defconfig_file)) { + printf(_("***\n" + "*** Can't find default configuration \"%s\"!\n" + "***\n"), defconfig_file); + exit(1); + } + break; + case savedefconfig: + case silentoldconfig: + case oldaskconfig: + case oldconfig: + case listnewconfig: + case oldnoconfig: + conf_read(NULL); + break; + case allnoconfig: + case allyesconfig: + case allmodconfig: + case alldefconfig: + case randconfig: + name = getenv("KCONFIG_ALLCONFIG"); + if (!name) + break; + if ((strcmp(name, "") != 0) && (strcmp(name, "1") != 0)) { + if (conf_read_simple(name, S_DEF_USER)) { + fprintf(stderr, + _("*** Can't read seed configuration \"%s\"!\n"), + name); + exit(1); + } + break; + } + switch (input_mode) { + case allnoconfig: name = "allno.config"; break; + case allyesconfig: name = "allyes.config"; break; + case allmodconfig: name = "allmod.config"; break; + case alldefconfig: name = "alldef.config"; break; + case randconfig: name = "allrandom.config"; break; + default: break; + } + if (conf_read_simple(name, S_DEF_USER) && + conf_read_simple("all.config", S_DEF_USER)) { + fprintf(stderr, + _("*** KCONFIG_ALLCONFIG set, but no \"%s\" or \"all.config\" file found\n"), + name); + exit(1); + } + break; + default: + break; + } + + if (sync_kconfig) { + if (conf_get_changed()) { + name = getenv("KCONFIG_NOSILENTUPDATE"); + if (name && *name) { + fprintf(stderr, + _("\n*** The configuration requires explicit update.\n\n")); + return 1; + } + } + valid_stdin = isatty(0) && isatty(1) && isatty(2); + } + + switch (input_mode) { + case allnoconfig: + conf_set_all_new_symbols(def_no); + break; + case allyesconfig: + conf_set_all_new_symbols(def_yes); + break; + case allmodconfig: + conf_set_all_new_symbols(def_mod); + break; + case alldefconfig: + conf_set_all_new_symbols(def_default); + break; + case randconfig: + conf_set_all_new_symbols(def_random); + break; + case defconfig: + conf_set_all_new_symbols(def_default); + break; + case savedefconfig: + break; + case oldaskconfig: + rootEntry = &rootmenu; + conf(&rootmenu); + input_mode = silentoldconfig; + /* fall through */ + case oldconfig: + case listnewconfig: + case oldnoconfig: + case silentoldconfig: + /* Update until a loop caused no more changes */ + do { + conf_cnt = 0; + check_conf(&rootmenu); + } while (conf_cnt && + (input_mode != listnewconfig && + input_mode != oldnoconfig)); + break; + } + + if (sync_kconfig) { + /* silentoldconfig is used during the build so we shall update autoconf. + * All other commands are only used to generate a config. + */ + if (conf_get_changed() && conf_write(NULL)) { + fprintf(stderr, _("\n*** Error during writing of the configuration.\n\n")); + exit(1); + } + if (conf_write_autoconf()) { + fprintf(stderr, _("\n*** Error during update of the configuration.\n\n")); + return 1; + } + } else if (input_mode == savedefconfig) { + if (conf_write_defconfig(defconfig_file)) { + fprintf(stderr, _("n*** Error while saving defconfig to: %s\n\n"), + defconfig_file); + return 1; + } + } else if (input_mode != listnewconfig) { + if (conf_write(NULL)) { + fprintf(stderr, _("\n*** Error during writing of the configuration.\n\n")); + exit(1); + } + } + return 0; +} + +/* + * Helper function to facilitate fgets() by Jean Sacren. + */ +void xfgets(char *str, int size, FILE *in) +{ + if (fgets(str, size, in) == NULL) + fprintf(stderr, "\nError in reading or end of file.\n"); +} diff --git a/l4/tool/kconfig/scripts/kconfig/confdata.c b/l4/tool/kconfig/scripts/kconfig/confdata.c new file mode 100644 index 00000000..bcc2719d --- /dev/null +++ b/l4/tool/kconfig/scripts/kconfig/confdata.c @@ -0,0 +1,1107 @@ +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "lkc.h" + +static void conf_warning(const char *fmt, ...) + __attribute__ ((format (printf, 1, 2))); + +static void conf_message(const char *fmt, ...) + __attribute__ ((format (printf, 1, 2))); + +static const char *conf_filename; +static int conf_lineno, conf_warnings, conf_unsaved; + +const char conf_defname[] = "arch/$ARCH/defconfig"; + +static void conf_warning(const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + fprintf(stderr, "%s:%d:warning: ", conf_filename, conf_lineno); + vfprintf(stderr, fmt, ap); + fprintf(stderr, "\n"); + va_end(ap); + conf_warnings++; +} + +static void conf_default_message_callback(const char *fmt, va_list ap) +{ + printf("#\n# "); + vprintf(fmt, ap); + printf("\n#\n"); +} + +static void (*conf_message_callback) (const char *fmt, va_list ap) = + conf_default_message_callback; +void conf_set_message_callback(void (*fn) (const char *fmt, va_list ap)) +{ + conf_message_callback = fn; +} + +static void conf_message(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + if (conf_message_callback) + conf_message_callback(fmt, ap); +} + +const char *conf_get_configname(void) +{ + char *name = getenv("KCONFIG_CONFIG"); + + return name ? name : ".config"; +} + +const char *conf_get_autoconfig_name(void) +{ + char *name = getenv("KCONFIG_AUTOCONFIG"); + + return name ? name : "include/config/auto.conf"; +} + +static char *conf_expand_value(const char *in) +{ + struct symbol *sym; + const char *src; + static char res_value[SYMBOL_MAXLENGTH]; + char *dst, name[SYMBOL_MAXLENGTH]; + + res_value[0] = 0; + dst = name; + while ((src = strchr(in, '$'))) { + strncat(res_value, in, src - in); + src++; + dst = name; + while (isalnum(*src) || *src == '_') + *dst++ = *src++; + *dst = 0; + sym = sym_lookup(name, 0); + sym_calc_value(sym); + strcat(res_value, sym_get_string_value(sym)); + in = src; + } + strcat(res_value, in); + + return res_value; +} + +char *conf_get_default_confname(void) +{ + struct stat buf; + static char fullname[PATH_MAX+1]; + char *env, *name; + + name = conf_expand_value(conf_defname); + env = getenv(SRCTREE); + if (env) { + sprintf(fullname, "%s/%s", env, name); + if (!stat(fullname, &buf)) + return fullname; + } + return name; +} + +static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p) +{ + char *p2; + + switch (sym->type) { + case S_TRISTATE: + if (p[0] == 'm') { + sym->def[def].tri = mod; + sym->flags |= def_flags; + break; + } + /* fall through */ + case S_BOOLEAN: + if (p[0] == 'y') { + sym->def[def].tri = yes; + sym->flags |= def_flags; + break; + } + if (p[0] == 'n') { + sym->def[def].tri = no; + sym->flags |= def_flags; + break; + } + conf_warning("symbol value '%s' invalid for %s", p, sym->name); + return 1; + case S_OTHER: + if (*p != '"') { + for (p2 = p; *p2 && !isspace(*p2); p2++) + ; + sym->type = S_STRING; + goto done; + } + /* fall through */ + case S_STRING: + if (*p++ != '"') + break; + for (p2 = p; (p2 = strpbrk(p2, "\"\\")); p2++) { + if (*p2 == '"') { + *p2 = 0; + break; + } + memmove(p2, p2 + 1, strlen(p2)); + } + if (!p2) { + conf_warning("invalid string found"); + return 1; + } + /* fall through */ + case S_INT: + case S_HEX: + done: + if (sym_string_valid(sym, p)) { + sym->def[def].val = strdup(p); + sym->flags |= def_flags; + } else { + conf_warning("symbol value '%s' invalid for %s", p, sym->name); + return 1; + } + break; + default: + ; + } + return 0; +} + +int conf_read_simple(const char *name, int def) +{ + FILE *in = NULL; + char line[1024]; + char *p, *p2; + struct symbol *sym; + int i, def_flags; + + if (name) { + in = zconf_fopen(name); + } else { + struct property *prop; + + name = conf_get_configname(); + in = zconf_fopen(name); + if (in) + goto load; + sym_add_change_count(1); + if (!sym_defconfig_list) { + if (modules_sym) + sym_calc_value(modules_sym); + return 1; + } + + for_all_defaults(sym_defconfig_list, prop) { + if (expr_calc_value(prop->visible.expr) == no || + prop->expr->type != E_SYMBOL) + continue; + name = conf_expand_value(prop->expr->left.sym->name); + in = zconf_fopen(name); + if (in) { + conf_message(_("using defaults found in %s"), + name); + goto load; + } + } + } + if (!in) + return 1; + +load: + conf_filename = name; + conf_lineno = 0; + conf_warnings = 0; + conf_unsaved = 0; + + def_flags = SYMBOL_DEF << def; + for_all_symbols(i, sym) { + sym->flags |= SYMBOL_CHANGED; + sym->flags &= ~(def_flags|SYMBOL_VALID); + if (sym_is_choice(sym)) + sym->flags |= def_flags; + switch (sym->type) { + case S_INT: + case S_HEX: + case S_STRING: + if (sym->def[def].val) + free(sym->def[def].val); + /* fall through */ + default: + sym->def[def].val = NULL; + sym->def[def].tri = no; + } + } + + while (fgets(line, sizeof(line), in)) { + conf_lineno++; + sym = NULL; + if (line[0] == '#') { + if (memcmp(line + 2, CONFIG_, strlen(CONFIG_))) + continue; + p = strchr(line + 2 + strlen(CONFIG_), ' '); + if (!p) + continue; + *p++ = 0; + if (strncmp(p, "is not set", 10)) + continue; + if (def == S_DEF_USER) { + sym = sym_find(line + 2 + strlen(CONFIG_)); + if (!sym) { + sym_add_change_count(1); + goto setsym; + } + } else { + sym = sym_lookup(line + 2 + strlen(CONFIG_), 0); + if (sym->type == S_UNKNOWN) + sym->type = S_BOOLEAN; + } + if (sym->flags & def_flags) { + conf_warning("override: reassigning to symbol %s", sym->name); + } + switch (sym->type) { + case S_BOOLEAN: + case S_TRISTATE: + sym->def[def].tri = no; + sym->flags |= def_flags; + break; + default: + ; + } + } else if (memcmp(line, CONFIG_, strlen(CONFIG_)) == 0) { + p = strchr(line + strlen(CONFIG_), '='); + if (!p) + continue; + *p++ = 0; + p2 = strchr(p, '\n'); + if (p2) { + *p2-- = 0; + if (*p2 == '\r') + *p2 = 0; + } + if (def == S_DEF_USER) { + sym = sym_find(line + strlen(CONFIG_)); + if (!sym) { + sym_add_change_count(1); + goto setsym; + } + } else { + sym = sym_lookup(line + strlen(CONFIG_), 0); + if (sym->type == S_UNKNOWN) + sym->type = S_OTHER; + } + if (sym->flags & def_flags) { + conf_warning("override: reassigning to symbol %s", sym->name); + } + if (conf_set_sym_val(sym, def, def_flags, p)) + continue; + } else { + if (line[0] != '\r' && line[0] != '\n') + conf_warning("unexpected data"); + continue; + } +setsym: + if (sym && sym_is_choice_value(sym)) { + struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym)); + switch (sym->def[def].tri) { + case no: + break; + case mod: + if (cs->def[def].tri == yes) { + conf_warning("%s creates inconsistent choice state", sym->name); + cs->flags &= ~def_flags; + } + break; + case yes: + if (cs->def[def].tri != no) + conf_warning("override: %s changes choice state", sym->name); + cs->def[def].val = sym; + break; + } + cs->def[def].tri = EXPR_OR(cs->def[def].tri, sym->def[def].tri); + } + } + fclose(in); + + if (modules_sym) + sym_calc_value(modules_sym); + return 0; +} + +int conf_read(const char *name) +{ + struct symbol *sym; + int i; + + sym_set_change_count(0); + + if (conf_read_simple(name, S_DEF_USER)) + return 1; + + for_all_symbols(i, sym) { + sym_calc_value(sym); + if (sym_is_choice(sym) || (sym->flags & SYMBOL_AUTO)) + continue; + if (sym_has_value(sym) && (sym->flags & SYMBOL_WRITE)) { + /* check that calculated value agrees with saved value */ + switch (sym->type) { + case S_BOOLEAN: + case S_TRISTATE: + if (sym->def[S_DEF_USER].tri != sym_get_tristate_value(sym)) + break; + if (!sym_is_choice(sym)) + continue; + /* fall through */ + default: + if (!strcmp(sym->curr.val, sym->def[S_DEF_USER].val)) + continue; + break; + } + } else if (!sym_has_value(sym) && !(sym->flags & SYMBOL_WRITE)) + /* no previous value and not saved */ + continue; + conf_unsaved++; + /* maybe print value in verbose mode... */ + } + + for_all_symbols(i, sym) { + if (sym_has_value(sym) && !sym_is_choice_value(sym)) { + /* Reset values of generates values, so they'll appear + * as new, if they should become visible, but that + * doesn't quite work if the Kconfig and the saved + * configuration disagree. + */ + if (sym->visible == no && !conf_unsaved) + sym->flags &= ~SYMBOL_DEF_USER; + switch (sym->type) { + case S_STRING: + case S_INT: + case S_HEX: + /* Reset a string value if it's out of range */ + if (sym_string_within_range(sym, sym->def[S_DEF_USER].val)) + break; + sym->flags &= ~(SYMBOL_VALID|SYMBOL_DEF_USER); + conf_unsaved++; + break; + default: + break; + } + } + } + + sym_add_change_count(conf_warnings || conf_unsaved); + + return 0; +} + +/* + * Kconfig configuration printer + * + * This printer is used when generating the resulting configuration after + * kconfig invocation and `defconfig' files. Unset symbol might be omitted by + * passing a non-NULL argument to the printer. + * + */ +static void +kconfig_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg) +{ + + switch (sym->type) { + case S_BOOLEAN: + case S_TRISTATE: + if (*value == 'n') { + bool skip_unset = (arg != NULL); + + if (!skip_unset) + fprintf(fp, "# %s%s is not set\n", + CONFIG_, sym->name); + return; + } + break; + default: + break; + } + + fprintf(fp, "%s%s=%s\n", CONFIG_, sym->name, value); +} + +static void +kconfig_print_comment(FILE *fp, const char *value, void *arg) +{ + const char *p = value; + size_t l; + + for (;;) { + l = strcspn(p, "\n"); + fprintf(fp, "#"); + if (l) { + fprintf(fp, " "); + xfwrite(p, l, 1, fp); + p += l; + } + fprintf(fp, "\n"); + if (*p++ == '\0') + break; + } +} + +static struct conf_printer kconfig_printer_cb = +{ + .print_symbol = kconfig_print_symbol, + .print_comment = kconfig_print_comment, +}; + +/* + * Header printer + * + * This printer is used when generating the `include/generated/autoconf.h' file. + */ +static void +header_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg) +{ + + switch (sym->type) { + case S_BOOLEAN: + case S_TRISTATE: { + const char *suffix = ""; + + switch (*value) { + case 'n': + break; + case 'm': + suffix = "_MODULE"; + /* fall through */ + default: + fprintf(fp, "#define %s%s%s 1\n", + CONFIG_, sym->name, suffix); + } + break; + } + case S_HEX: { + const char *prefix = ""; + + if (value[0] != '0' || (value[1] != 'x' && value[1] != 'X')) + prefix = "0x"; + fprintf(fp, "#define %s%s %s%s\n", + CONFIG_, sym->name, prefix, value); + break; + } + case S_STRING: + case S_INT: + fprintf(fp, "#define %s%s %s\n", + CONFIG_, sym->name, value); + break; + default: + break; + } + +} + +static void +header_print_comment(FILE *fp, const char *value, void *arg) +{ + const char *p = value; + size_t l; + + fprintf(fp, "/*\n"); + for (;;) { + l = strcspn(p, "\n"); + fprintf(fp, " *"); + if (l) { + fprintf(fp, " "); + xfwrite(p, l, 1, fp); + p += l; + } + fprintf(fp, "\n"); + if (*p++ == '\0') + break; + } + fprintf(fp, " */\n"); +} + +static struct conf_printer header_printer_cb = +{ + .print_symbol = header_print_symbol, + .print_comment = header_print_comment, +}; + +/* + * Tristate printer + * + * This printer is used when generating the `include/config/tristate.conf' file. + */ +static void +tristate_print_symbol(FILE *fp, struct symbol *sym, const char *value, void *arg) +{ + + if (sym->type == S_TRISTATE && *value != 'n') + fprintf(fp, "%s%s=%c\n", CONFIG_, sym->name, (char)toupper(*value)); +} + +static struct conf_printer tristate_printer_cb = +{ + .print_symbol = tristate_print_symbol, + .print_comment = kconfig_print_comment, +}; + +static void conf_write_symbol(FILE *fp, struct symbol *sym, + struct conf_printer *printer, void *printer_arg) +{ + const char *str; + + switch (sym->type) { + case S_OTHER: + case S_UNKNOWN: + break; + case S_STRING: + str = sym_get_string_value(sym); + str = sym_escape_string_value(str); + printer->print_symbol(fp, sym, str, printer_arg); + free((void *)str); + break; + default: + str = sym_get_string_value(sym); + printer->print_symbol(fp, sym, str, printer_arg); + } +} + +static void +conf_write_heading(FILE *fp, struct conf_printer *printer, void *printer_arg) +{ + char buf[256]; + + snprintf(buf, sizeof(buf), + "\n" + "Automatically generated file; DO NOT EDIT.\n" + "%s\n", + rootmenu.prompt->text); + + printer->print_comment(fp, buf, printer_arg); +} + +/* + * Write out a minimal config. + * All values that has default values are skipped as this is redundant. + */ +int conf_write_defconfig(const char *filename) +{ + struct symbol *sym; + struct menu *menu; + FILE *out; + + out = fopen(filename, "w"); + if (!out) + return 1; + + sym_clear_all_valid(); + + /* Traverse all menus to find all relevant symbols */ + menu = rootmenu.list; + + while (menu != NULL) + { + sym = menu->sym; + if (sym == NULL) { + if (!menu_is_visible(menu)) + goto next_menu; + } else if (!sym_is_choice(sym)) { + sym_calc_value(sym); + if (!(sym->flags & SYMBOL_WRITE)) + goto next_menu; + sym->flags &= ~SYMBOL_WRITE; + /* If we cannot change the symbol - skip */ + if (!sym_is_changable(sym)) + goto next_menu; + /* If symbol equals to default value - skip */ + if (strcmp(sym_get_string_value(sym), sym_get_string_default(sym)) == 0) + goto next_menu; + + /* + * If symbol is a choice value and equals to the + * default for a choice - skip. + * But only if value is bool and equal to "y" and + * choice is not "optional". + * (If choice is "optional" then all values can be "n") + */ + if (sym_is_choice_value(sym)) { + struct symbol *cs; + struct symbol *ds; + + cs = prop_get_symbol(sym_get_choice_prop(sym)); + ds = sym_choice_default(cs); + if (!sym_is_optional(cs) && sym == ds) { + if ((sym->type == S_BOOLEAN) && + sym_get_tristate_value(sym) == yes) + goto next_menu; + } + } + conf_write_symbol(out, sym, &kconfig_printer_cb, NULL); + } +next_menu: + if (menu->list != NULL) { + menu = menu->list; + } + else if (menu->next != NULL) { + menu = menu->next; + } else { + while ((menu = menu->parent)) { + if (menu->next != NULL) { + menu = menu->next; + break; + } + } + } + } + fclose(out); + return 0; +} + +int conf_write(const char *name) +{ + FILE *out; + struct symbol *sym; + struct menu *menu; + const char *basename; + const char *str; + char dirname[PATH_MAX+1], tmpname[PATH_MAX+1], newname[PATH_MAX+1]; + char *env; + + dirname[0] = 0; + if (name && name[0]) { + struct stat st; + char *slash; + + if (!stat(name, &st) && S_ISDIR(st.st_mode)) { + strcpy(dirname, name); + strcat(dirname, "/"); + basename = conf_get_configname(); + } else if ((slash = strrchr(name, '/'))) { + int size = slash - name + 1; + memcpy(dirname, name, size); + dirname[size] = 0; + if (slash[1]) + basename = slash + 1; + else + basename = conf_get_configname(); + } else + basename = name; + } else + basename = conf_get_configname(); + + sprintf(newname, "%s%s", dirname, basename); + env = getenv("KCONFIG_OVERWRITECONFIG"); + if (!env || !*env) { + sprintf(tmpname, "%s.tmpconfig.%d", dirname, (int)getpid()); + out = fopen(tmpname, "w"); + } else { + *tmpname = 0; + out = fopen(newname, "w"); + } + if (!out) + return 1; + + conf_write_heading(out, &kconfig_printer_cb, NULL); + + if (!conf_get_changed()) + sym_clear_all_valid(); + + menu = rootmenu.list; + while (menu) { + sym = menu->sym; + if (!sym) { + if (!menu_is_visible(menu)) + goto next; + str = menu_get_prompt(menu); + fprintf(out, "\n" + "#\n" + "# %s\n" + "#\n", str); + } else if (!(sym->flags & SYMBOL_CHOICE)) { + sym_calc_value(sym); + if (!(sym->flags & SYMBOL_WRITE)) + goto next; + sym->flags &= ~SYMBOL_WRITE; + + conf_write_symbol(out, sym, &kconfig_printer_cb, NULL); + } + +next: + if (menu->list) { + menu = menu->list; + continue; + } + if (menu->next) + menu = menu->next; + else while ((menu = menu->parent)) { + if (menu->next) { + menu = menu->next; + break; + } + } + } + fclose(out); + + if (*tmpname) { + strcat(dirname, basename); + strcat(dirname, ".old"); + rename(newname, dirname); + if (rename(tmpname, newname)) + return 1; + } + + conf_message(_("configuration written to %s"), newname); + + sym_set_change_count(0); + + return 0; +} + +static int conf_split_config(void) +{ + const char *name; + char path[PATH_MAX+1]; + char *s, *d, c; + struct symbol *sym; + struct stat sb; + int res, i, fd; + + name = conf_get_autoconfig_name(); + conf_read_simple(name, S_DEF_AUTO); + + if (chdir("config")) + return 1; + + res = 0; + for_all_symbols(i, sym) { + sym_calc_value(sym); + if ((sym->flags & SYMBOL_AUTO) || !sym->name) + continue; + if (sym->flags & SYMBOL_WRITE) { + if (sym->flags & SYMBOL_DEF_AUTO) { + /* + * symbol has old and new value, + * so compare them... + */ + switch (sym->type) { + case S_BOOLEAN: + case S_TRISTATE: + if (sym_get_tristate_value(sym) == + sym->def[S_DEF_AUTO].tri) + continue; + break; + case S_STRING: + case S_HEX: + case S_INT: + if (!strcmp(sym_get_string_value(sym), + sym->def[S_DEF_AUTO].val)) + continue; + break; + default: + break; + } + } else { + /* + * If there is no old value, only 'no' (unset) + * is allowed as new value. + */ + switch (sym->type) { + case S_BOOLEAN: + case S_TRISTATE: + if (sym_get_tristate_value(sym) == no) + continue; + break; + default: + break; + } + } + } else if (!(sym->flags & SYMBOL_DEF_AUTO)) + /* There is neither an old nor a new value. */ + continue; + /* else + * There is an old value, but no new value ('no' (unset) + * isn't saved in auto.conf, so the old value is always + * different from 'no'). + */ + + /* Replace all '_' and append ".h" */ + s = sym->name; + d = path; + while ((c = *s++)) { + c = tolower(c); + *d++ = (c == '_') ? '/' : c; + } + strcpy(d, ".h"); + + /* Assume directory path already exists. */ + fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644); + if (fd == -1) { + if (errno != ENOENT) { + res = 1; + break; + } + /* + * Create directory components, + * unless they exist already. + */ + d = path; + while ((d = strchr(d, '/'))) { + *d = 0; + if (stat(path, &sb) && mkdir(path, 0755)) { + res = 1; + goto out; + } + *d++ = '/'; + } + /* Try it again. */ + fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644); + if (fd == -1) { + res = 1; + break; + } + } + close(fd); + } +out: + if (chdir("..")) + return 1; + + return res; +} + +int conf_write_autoconf(void) +{ + struct symbol *sym; + const char *name; + FILE *out, *tristate, *out_h; + int i; + + sym_clear_all_valid(); + + file_write_dep("config/auto.conf.cmd"); + + if (conf_split_config()) + return 1; + + out = fopen(".tmpconfig", "w"); + if (!out) + return 1; + + tristate = fopen(".tmpconfig_tristate", "w"); + if (!tristate) { + fclose(out); + return 1; + } + + out_h = fopen(".tmpconfig.h", "w"); + if (!out_h) { + fclose(out); + fclose(tristate); + return 1; + } + + conf_write_heading(out, &kconfig_printer_cb, NULL); + + conf_write_heading(tristate, &tristate_printer_cb, NULL); + + conf_write_heading(out_h, &header_printer_cb, NULL); + + for_all_symbols(i, sym) { + sym_calc_value(sym); + if (!(sym->flags & SYMBOL_WRITE) || !sym->name) + continue; + + /* write symbol to auto.conf, tristate and header files */ + conf_write_symbol(out, sym, &kconfig_printer_cb, (void *)1); + + conf_write_symbol(tristate, sym, &tristate_printer_cb, (void *)1); + + conf_write_symbol(out_h, sym, &header_printer_cb, NULL); + } + fclose(out); + fclose(tristate); + fclose(out_h); + + name = getenv("KCONFIG_AUTOHEADER"); + if (!name) + name = "include/generated/autoconf.h"; + if (rename(".tmpconfig.h", name)) + return 1; + name = getenv("KCONFIG_TRISTATE"); + if (!name) + name = "include/config/tristate.conf"; + if (rename(".tmpconfig_tristate", name)) + return 1; + name = conf_get_autoconfig_name(); + /* + * This must be the last step, kbuild has a dependency on auto.conf + * and this marks the successful completion of the previous steps. + */ + if (rename(".tmpconfig", name)) + return 1; + + return 0; +} + +static int sym_change_count; +static void (*conf_changed_callback)(void); + +void sym_set_change_count(int count) +{ + int _sym_change_count = sym_change_count; + sym_change_count = count; + if (conf_changed_callback && + (bool)_sym_change_count != (bool)count) + conf_changed_callback(); +} + +void sym_add_change_count(int count) +{ + sym_set_change_count(count + sym_change_count); +} + +bool conf_get_changed(void) +{ + return sym_change_count; +} + +void conf_set_changed_callback(void (*fn)(void)) +{ + conf_changed_callback = fn; +} + +static void randomize_choice_values(struct symbol *csym) +{ + struct property *prop; + struct symbol *sym; + struct expr *e; + int cnt, def; + + /* + * If choice is mod then we may have more items selected + * and if no then no-one. + * In both cases stop. + */ + if (csym->curr.tri != yes) + return; + + prop = sym_get_choice_prop(csym); + + /* count entries in choice block */ + cnt = 0; + expr_list_for_each_sym(prop->expr, e, sym) + cnt++; + + /* + * find a random value and set it to yes, + * set the rest to no so we have only one set + */ + def = (rand() % cnt); + + cnt = 0; + expr_list_for_each_sym(prop->expr, e, sym) { + if (def == cnt++) { + sym->def[S_DEF_USER].tri = yes; + csym->def[S_DEF_USER].val = sym; + } + else { + sym->def[S_DEF_USER].tri = no; + } + } + csym->flags |= SYMBOL_DEF_USER; + /* clear VALID to get value calculated */ + csym->flags &= ~(SYMBOL_VALID); +} + +static void set_all_choice_values(struct symbol *csym) +{ + struct property *prop; + struct symbol *sym; + struct expr *e; + + prop = sym_get_choice_prop(csym); + + /* + * Set all non-assinged choice values to no + */ + expr_list_for_each_sym(prop->expr, e, sym) { + if (!sym_has_value(sym)) + sym->def[S_DEF_USER].tri = no; + } + csym->flags |= SYMBOL_DEF_USER; + /* clear VALID to get value calculated */ + csym->flags &= ~(SYMBOL_VALID); +} + +void conf_set_all_new_symbols(enum conf_def_mode mode) +{ + struct symbol *sym, *csym; + int i, cnt; + + for_all_symbols(i, sym) { + if (sym_has_value(sym)) + continue; + switch (sym_get_type(sym)) { + case S_BOOLEAN: + case S_TRISTATE: + switch (mode) { + case def_yes: + sym->def[S_DEF_USER].tri = yes; + break; + case def_mod: + sym->def[S_DEF_USER].tri = mod; + break; + case def_no: + sym->def[S_DEF_USER].tri = no; + break; + case def_random: + cnt = sym_get_type(sym) == S_TRISTATE ? 3 : 2; + sym->def[S_DEF_USER].tri = (tristate)(rand() % cnt); + break; + default: + continue; + } + if (!(sym_is_choice(sym) && mode == def_random)) + sym->flags |= SYMBOL_DEF_USER; + break; + default: + break; + } + + } + + sym_clear_all_valid(); + + /* + * We have different type of choice blocks. + * If curr.tri equals to mod then we can select several + * choice symbols in one block. + * In this case we do nothing. + * If curr.tri equals yes then only one symbol can be + * selected in a choice block and we set it to yes, + * and the rest to no. + */ + for_all_symbols(i, csym) { + if (sym_has_value(csym) || !sym_is_choice(csym)) + continue; + + sym_calc_value(csym); + if (mode == def_random) + randomize_choice_values(csym); + else + set_all_choice_values(csym); + } +} diff --git a/l4/tool/kconfig/scripts/kconfig/expr.c b/l4/tool/kconfig/scripts/kconfig/expr.c new file mode 100644 index 00000000..290ce41f --- /dev/null +++ b/l4/tool/kconfig/scripts/kconfig/expr.c @@ -0,0 +1,1168 @@ +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +#include +#include +#include + +#include "lkc.h" + +#define DEBUG_EXPR 0 + +struct expr *expr_alloc_symbol(struct symbol *sym) +{ + struct expr *e = calloc(1, sizeof(*e)); + e->type = E_SYMBOL; + e->left.sym = sym; + return e; +} + +struct expr *expr_alloc_one(enum expr_type type, struct expr *ce) +{ + struct expr *e = calloc(1, sizeof(*e)); + e->type = type; + e->left.expr = ce; + return e; +} + +struct expr *expr_alloc_two(enum expr_type type, struct expr *e1, struct expr *e2) +{ + struct expr *e = calloc(1, sizeof(*e)); + e->type = type; + e->left.expr = e1; + e->right.expr = e2; + return e; +} + +struct expr *expr_alloc_comp(enum expr_type type, struct symbol *s1, struct symbol *s2) +{ + struct expr *e = calloc(1, sizeof(*e)); + e->type = type; + e->left.sym = s1; + e->right.sym = s2; + return e; +} + +struct expr *expr_alloc_and(struct expr *e1, struct expr *e2) +{ + if (!e1) + return e2; + return e2 ? expr_alloc_two(E_AND, e1, e2) : e1; +} + +struct expr *expr_alloc_or(struct expr *e1, struct expr *e2) +{ + if (!e1) + return e2; + return e2 ? expr_alloc_two(E_OR, e1, e2) : e1; +} + +struct expr *expr_copy(const struct expr *org) +{ + struct expr *e; + + if (!org) + return NULL; + + e = malloc(sizeof(*org)); + memcpy(e, org, sizeof(*org)); + switch (org->type) { + case E_SYMBOL: + e->left = org->left; + break; + case E_NOT: + e->left.expr = expr_copy(org->left.expr); + break; + case E_EQUAL: + case E_UNEQUAL: + e->left.sym = org->left.sym; + e->right.sym = org->right.sym; + break; + case E_AND: + case E_OR: + case E_LIST: + e->left.expr = expr_copy(org->left.expr); + e->right.expr = expr_copy(org->right.expr); + break; + default: + printf("can't copy type %d\n", e->type); + free(e); + e = NULL; + break; + } + + return e; +} + +void expr_free(struct expr *e) +{ + if (!e) + return; + + switch (e->type) { + case E_SYMBOL: + break; + case E_NOT: + expr_free(e->left.expr); + return; + case E_EQUAL: + case E_UNEQUAL: + break; + case E_OR: + case E_AND: + expr_free(e->left.expr); + expr_free(e->right.expr); + break; + default: + printf("how to free type %d?\n", e->type); + break; + } + free(e); +} + +static int trans_count; + +#define e1 (*ep1) +#define e2 (*ep2) + +static void __expr_eliminate_eq(enum expr_type type, struct expr **ep1, struct expr **ep2) +{ + if (e1->type == type) { + __expr_eliminate_eq(type, &e1->left.expr, &e2); + __expr_eliminate_eq(type, &e1->right.expr, &e2); + return; + } + if (e2->type == type) { + __expr_eliminate_eq(type, &e1, &e2->left.expr); + __expr_eliminate_eq(type, &e1, &e2->right.expr); + return; + } + if (e1->type == E_SYMBOL && e2->type == E_SYMBOL && + e1->left.sym == e2->left.sym && + (e1->left.sym == &symbol_yes || e1->left.sym == &symbol_no)) + return; + if (!expr_eq(e1, e2)) + return; + trans_count++; + expr_free(e1); expr_free(e2); + switch (type) { + case E_OR: + e1 = expr_alloc_symbol(&symbol_no); + e2 = expr_alloc_symbol(&symbol_no); + break; + case E_AND: + e1 = expr_alloc_symbol(&symbol_yes); + e2 = expr_alloc_symbol(&symbol_yes); + break; + default: + ; + } +} + +void expr_eliminate_eq(struct expr **ep1, struct expr **ep2) +{ + if (!e1 || !e2) + return; + switch (e1->type) { + case E_OR: + case E_AND: + __expr_eliminate_eq(e1->type, ep1, ep2); + default: + ; + } + if (e1->type != e2->type) switch (e2->type) { + case E_OR: + case E_AND: + __expr_eliminate_eq(e2->type, ep1, ep2); + default: + ; + } + e1 = expr_eliminate_yn(e1); + e2 = expr_eliminate_yn(e2); +} + +#undef e1 +#undef e2 + +int expr_eq(struct expr *e1, struct expr *e2) +{ + int res, old_count; + + if (e1->type != e2->type) + return 0; + switch (e1->type) { + case E_EQUAL: + case E_UNEQUAL: + return e1->left.sym == e2->left.sym && e1->right.sym == e2->right.sym; + case E_SYMBOL: + return e1->left.sym == e2->left.sym; + case E_NOT: + return expr_eq(e1->left.expr, e2->left.expr); + case E_AND: + case E_OR: + e1 = expr_copy(e1); + e2 = expr_copy(e2); + old_count = trans_count; + expr_eliminate_eq(&e1, &e2); + res = (e1->type == E_SYMBOL && e2->type == E_SYMBOL && + e1->left.sym == e2->left.sym); + expr_free(e1); + expr_free(e2); + trans_count = old_count; + return res; + case E_LIST: + case E_RANGE: + case E_NONE: + /* panic */; + } + + if (DEBUG_EXPR) { + expr_fprint(e1, stdout); + printf(" = "); + expr_fprint(e2, stdout); + printf(" ?\n"); + } + + return 0; +} + +struct expr *expr_eliminate_yn(struct expr *e) +{ + struct expr *tmp; + + if (e) switch (e->type) { + case E_AND: + e->left.expr = expr_eliminate_yn(e->left.expr); + e->right.expr = expr_eliminate_yn(e->right.expr); + if (e->left.expr->type == E_SYMBOL) { + if (e->left.expr->left.sym == &symbol_no) { + expr_free(e->left.expr); + expr_free(e->right.expr); + e->type = E_SYMBOL; + e->left.sym = &symbol_no; + e->right.expr = NULL; + return e; + } else if (e->left.expr->left.sym == &symbol_yes) { + free(e->left.expr); + tmp = e->right.expr; + *e = *(e->right.expr); + free(tmp); + return e; + } + } + if (e->right.expr->type == E_SYMBOL) { + if (e->right.expr->left.sym == &symbol_no) { + expr_free(e->left.expr); + expr_free(e->right.expr); + e->type = E_SYMBOL; + e->left.sym = &symbol_no; + e->right.expr = NULL; + return e; + } else if (e->right.expr->left.sym == &symbol_yes) { + free(e->right.expr); + tmp = e->left.expr; + *e = *(e->left.expr); + free(tmp); + return e; + } + } + break; + case E_OR: + e->left.expr = expr_eliminate_yn(e->left.expr); + e->right.expr = expr_eliminate_yn(e->right.expr); + if (e->left.expr->type == E_SYMBOL) { + if (e->left.expr->left.sym == &symbol_no) { + free(e->left.expr); + tmp = e->right.expr; + *e = *(e->right.expr); + free(tmp); + return e; + } else if (e->left.expr->left.sym == &symbol_yes) { + expr_free(e->left.expr); + expr_free(e->right.expr); + e->type = E_SYMBOL; + e->left.sym = &symbol_yes; + e->right.expr = NULL; + return e; + } + } + if (e->right.expr->type == E_SYMBOL) { + if (e->right.expr->left.sym == &symbol_no) { + free(e->right.expr); + tmp = e->left.expr; + *e = *(e->left.expr); + free(tmp); + return e; + } else if (e->right.expr->left.sym == &symbol_yes) { + expr_free(e->left.expr); + expr_free(e->right.expr); + e->type = E_SYMBOL; + e->left.sym = &symbol_yes; + e->right.expr = NULL; + return e; + } + } + break; + default: + ; + } + return e; +} + +/* + * bool FOO!=n => FOO + */ +struct expr *expr_trans_bool(struct expr *e) +{ + if (!e) + return NULL; + switch (e->type) { + case E_AND: + case E_OR: + case E_NOT: + e->left.expr = expr_trans_bool(e->left.expr); + e->right.expr = expr_trans_bool(e->right.expr); + break; + case E_UNEQUAL: + // FOO!=n -> FOO + if (e->left.sym->type == S_TRISTATE) { + if (e->right.sym == &symbol_no) { + e->type = E_SYMBOL; + e->right.sym = NULL; + } + } + break; + default: + ; + } + return e; +} + +/* + * e1 || e2 -> ? + */ +static struct expr *expr_join_or(struct expr *e1, struct expr *e2) +{ + struct expr *tmp; + struct symbol *sym1, *sym2; + + if (expr_eq(e1, e2)) + return expr_copy(e1); + if (e1->type != E_EQUAL && e1->type != E_UNEQUAL && e1->type != E_SYMBOL && e1->type != E_NOT) + return NULL; + if (e2->type != E_EQUAL && e2->type != E_UNEQUAL && e2->type != E_SYMBOL && e2->type != E_NOT) + return NULL; + if (e1->type == E_NOT) { + tmp = e1->left.expr; + if (tmp->type != E_EQUAL && tmp->type != E_UNEQUAL && tmp->type != E_SYMBOL) + return NULL; + sym1 = tmp->left.sym; + } else + sym1 = e1->left.sym; + if (e2->type == E_NOT) { + if (e2->left.expr->type != E_SYMBOL) + return NULL; + sym2 = e2->left.expr->left.sym; + } else + sym2 = e2->left.sym; + if (sym1 != sym2) + return NULL; + if (sym1->type != S_BOOLEAN && sym1->type != S_TRISTATE) + return NULL; + if (sym1->type == S_TRISTATE) { + if (e1->type == E_EQUAL && e2->type == E_EQUAL && + ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_mod) || + (e1->right.sym == &symbol_mod && e2->right.sym == &symbol_yes))) { + // (a='y') || (a='m') -> (a!='n') + return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_no); + } + if (e1->type == E_EQUAL && e2->type == E_EQUAL && + ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_no) || + (e1->right.sym == &symbol_no && e2->right.sym == &symbol_yes))) { + // (a='y') || (a='n') -> (a!='m') + return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_mod); + } + if (e1->type == E_EQUAL && e2->type == E_EQUAL && + ((e1->right.sym == &symbol_mod && e2->right.sym == &symbol_no) || + (e1->right.sym == &symbol_no && e2->right.sym == &symbol_mod))) { + // (a='m') || (a='n') -> (a!='y') + return expr_alloc_comp(E_UNEQUAL, sym1, &symbol_yes); + } + } + if (sym1->type == S_BOOLEAN && sym1 == sym2) { + if ((e1->type == E_NOT && e1->left.expr->type == E_SYMBOL && e2->type == E_SYMBOL) || + (e2->type == E_NOT && e2->left.expr->type == E_SYMBOL && e1->type == E_SYMBOL)) + return expr_alloc_symbol(&symbol_yes); + } + + if (DEBUG_EXPR) { + printf("optimize ("); + expr_fprint(e1, stdout); + printf(") || ("); + expr_fprint(e2, stdout); + printf(")?\n"); + } + return NULL; +} + +static struct expr *expr_join_and(struct expr *e1, struct expr *e2) +{ + struct expr *tmp; + struct symbol *sym1, *sym2; + + if (expr_eq(e1, e2)) + return expr_copy(e1); + if (e1->type != E_EQUAL && e1->type != E_UNEQUAL && e1->type != E_SYMBOL && e1->type != E_NOT) + return NULL; + if (e2->type != E_EQUAL && e2->type != E_UNEQUAL && e2->type != E_SYMBOL && e2->type != E_NOT) + return NULL; + if (e1->type == E_NOT) { + tmp = e1->left.expr; + if (tmp->type != E_EQUAL && tmp->type != E_UNEQUAL && tmp->type != E_SYMBOL) + return NULL; + sym1 = tmp->left.sym; + } else + sym1 = e1->left.sym; + if (e2->type == E_NOT) { + if (e2->left.expr->type != E_SYMBOL) + return NULL; + sym2 = e2->left.expr->left.sym; + } else + sym2 = e2->left.sym; + if (sym1 != sym2) + return NULL; + if (sym1->type != S_BOOLEAN && sym1->type != S_TRISTATE) + return NULL; + + if ((e1->type == E_SYMBOL && e2->type == E_EQUAL && e2->right.sym == &symbol_yes) || + (e2->type == E_SYMBOL && e1->type == E_EQUAL && e1->right.sym == &symbol_yes)) + // (a) && (a='y') -> (a='y') + return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes); + + if ((e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_no) || + (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_no)) + // (a) && (a!='n') -> (a) + return expr_alloc_symbol(sym1); + + if ((e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_mod) || + (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_mod)) + // (a) && (a!='m') -> (a='y') + return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes); + + if (sym1->type == S_TRISTATE) { + if (e1->type == E_EQUAL && e2->type == E_UNEQUAL) { + // (a='b') && (a!='c') -> 'b'='c' ? 'n' : a='b' + sym2 = e1->right.sym; + if ((e2->right.sym->flags & SYMBOL_CONST) && (sym2->flags & SYMBOL_CONST)) + return sym2 != e2->right.sym ? expr_alloc_comp(E_EQUAL, sym1, sym2) + : expr_alloc_symbol(&symbol_no); + } + if (e1->type == E_UNEQUAL && e2->type == E_EQUAL) { + // (a='b') && (a!='c') -> 'b'='c' ? 'n' : a='b' + sym2 = e2->right.sym; + if ((e1->right.sym->flags & SYMBOL_CONST) && (sym2->flags & SYMBOL_CONST)) + return sym2 != e1->right.sym ? expr_alloc_comp(E_EQUAL, sym1, sym2) + : expr_alloc_symbol(&symbol_no); + } + if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL && + ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_no) || + (e1->right.sym == &symbol_no && e2->right.sym == &symbol_yes))) + // (a!='y') && (a!='n') -> (a='m') + return expr_alloc_comp(E_EQUAL, sym1, &symbol_mod); + + if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL && + ((e1->right.sym == &symbol_yes && e2->right.sym == &symbol_mod) || + (e1->right.sym == &symbol_mod && e2->right.sym == &symbol_yes))) + // (a!='y') && (a!='m') -> (a='n') + return expr_alloc_comp(E_EQUAL, sym1, &symbol_no); + + if (e1->type == E_UNEQUAL && e2->type == E_UNEQUAL && + ((e1->right.sym == &symbol_mod && e2->right.sym == &symbol_no) || + (e1->right.sym == &symbol_no && e2->right.sym == &symbol_mod))) + // (a!='m') && (a!='n') -> (a='m') + return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes); + + if ((e1->type == E_SYMBOL && e2->type == E_EQUAL && e2->right.sym == &symbol_mod) || + (e2->type == E_SYMBOL && e1->type == E_EQUAL && e1->right.sym == &symbol_mod) || + (e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_yes) || + (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_yes)) + return NULL; + } + + if (DEBUG_EXPR) { + printf("optimize ("); + expr_fprint(e1, stdout); + printf(") && ("); + expr_fprint(e2, stdout); + printf(")?\n"); + } + return NULL; +} + +static void expr_eliminate_dups1(enum expr_type type, struct expr **ep1, struct expr **ep2) +{ +#define e1 (*ep1) +#define e2 (*ep2) + struct expr *tmp; + + if (e1->type == type) { + expr_eliminate_dups1(type, &e1->left.expr, &e2); + expr_eliminate_dups1(type, &e1->right.expr, &e2); + return; + } + if (e2->type == type) { + expr_eliminate_dups1(type, &e1, &e2->left.expr); + expr_eliminate_dups1(type, &e1, &e2->right.expr); + return; + } + if (e1 == e2) + return; + + switch (e1->type) { + case E_OR: case E_AND: + expr_eliminate_dups1(e1->type, &e1, &e1); + default: + ; + } + + switch (type) { + case E_OR: + tmp = expr_join_or(e1, e2); + if (tmp) { + expr_free(e1); expr_free(e2); + e1 = expr_alloc_symbol(&symbol_no); + e2 = tmp; + trans_count++; + } + break; + case E_AND: + tmp = expr_join_and(e1, e2); + if (tmp) { + expr_free(e1); expr_free(e2); + e1 = expr_alloc_symbol(&symbol_yes); + e2 = tmp; + trans_count++; + } + break; + default: + ; + } +#undef e1 +#undef e2 +} + +static void expr_eliminate_dups2(enum expr_type type, struct expr **ep1, struct expr **ep2) +{ +#define e1 (*ep1) +#define e2 (*ep2) + struct expr *tmp, *tmp1, *tmp2; + + if (e1->type == type) { + expr_eliminate_dups2(type, &e1->left.expr, &e2); + expr_eliminate_dups2(type, &e1->right.expr, &e2); + return; + } + if (e2->type == type) { + expr_eliminate_dups2(type, &e1, &e2->left.expr); + expr_eliminate_dups2(type, &e1, &e2->right.expr); + } + if (e1 == e2) + return; + + switch (e1->type) { + case E_OR: + expr_eliminate_dups2(e1->type, &e1, &e1); + // (FOO || BAR) && (!FOO && !BAR) -> n + tmp1 = expr_transform(expr_alloc_one(E_NOT, expr_copy(e1))); + tmp2 = expr_copy(e2); + tmp = expr_extract_eq_and(&tmp1, &tmp2); + if (expr_is_yes(tmp1)) { + expr_free(e1); + e1 = expr_alloc_symbol(&symbol_no); + trans_count++; + } + expr_free(tmp2); + expr_free(tmp1); + expr_free(tmp); + break; + case E_AND: + expr_eliminate_dups2(e1->type, &e1, &e1); + // (FOO && BAR) || (!FOO || !BAR) -> y + tmp1 = expr_transform(expr_alloc_one(E_NOT, expr_copy(e1))); + tmp2 = expr_copy(e2); + tmp = expr_extract_eq_or(&tmp1, &tmp2); + if (expr_is_no(tmp1)) { + expr_free(e1); + e1 = expr_alloc_symbol(&symbol_yes); + trans_count++; + } + expr_free(tmp2); + expr_free(tmp1); + expr_free(tmp); + break; + default: + ; + } +#undef e1 +#undef e2 +} + +struct expr *expr_eliminate_dups(struct expr *e) +{ + int oldcount; + if (!e) + return e; + + oldcount = trans_count; + while (1) { + trans_count = 0; + switch (e->type) { + case E_OR: case E_AND: + expr_eliminate_dups1(e->type, &e, &e); + expr_eliminate_dups2(e->type, &e, &e); + default: + ; + } + if (!trans_count) + break; + e = expr_eliminate_yn(e); + } + trans_count = oldcount; + return e; +} + +struct expr *expr_transform(struct expr *e) +{ + struct expr *tmp; + + if (!e) + return NULL; + switch (e->type) { + case E_EQUAL: + case E_UNEQUAL: + case E_SYMBOL: + case E_LIST: + break; + default: + e->left.expr = expr_transform(e->left.expr); + e->right.expr = expr_transform(e->right.expr); + } + + switch (e->type) { + case E_EQUAL: + if (e->left.sym->type != S_BOOLEAN) + break; + if (e->right.sym == &symbol_no) { + e->type = E_NOT; + e->left.expr = expr_alloc_symbol(e->left.sym); + e->right.sym = NULL; + break; + } + if (e->right.sym == &symbol_mod) { + printf("boolean symbol %s tested for 'm'? test forced to 'n'\n", e->left.sym->name); + e->type = E_SYMBOL; + e->left.sym = &symbol_no; + e->right.sym = NULL; + break; + } + if (e->right.sym == &symbol_yes) { + e->type = E_SYMBOL; + e->right.sym = NULL; + break; + } + break; + case E_UNEQUAL: + if (e->left.sym->type != S_BOOLEAN) + break; + if (e->right.sym == &symbol_no) { + e->type = E_SYMBOL; + e->right.sym = NULL; + break; + } + if (e->right.sym == &symbol_mod) { + printf("boolean symbol %s tested for 'm'? test forced to 'y'\n", e->left.sym->name); + e->type = E_SYMBOL; + e->left.sym = &symbol_yes; + e->right.sym = NULL; + break; + } + if (e->right.sym == &symbol_yes) { + e->type = E_NOT; + e->left.expr = expr_alloc_symbol(e->left.sym); + e->right.sym = NULL; + break; + } + break; + case E_NOT: + switch (e->left.expr->type) { + case E_NOT: + // !!a -> a + tmp = e->left.expr->left.expr; + free(e->left.expr); + free(e); + e = tmp; + e = expr_transform(e); + break; + case E_EQUAL: + case E_UNEQUAL: + // !a='x' -> a!='x' + tmp = e->left.expr; + free(e); + e = tmp; + e->type = e->type == E_EQUAL ? E_UNEQUAL : E_EQUAL; + break; + case E_OR: + // !(a || b) -> !a && !b + tmp = e->left.expr; + e->type = E_AND; + e->right.expr = expr_alloc_one(E_NOT, tmp->right.expr); + tmp->type = E_NOT; + tmp->right.expr = NULL; + e = expr_transform(e); + break; + case E_AND: + // !(a && b) -> !a || !b + tmp = e->left.expr; + e->type = E_OR; + e->right.expr = expr_alloc_one(E_NOT, tmp->right.expr); + tmp->type = E_NOT; + tmp->right.expr = NULL; + e = expr_transform(e); + break; + case E_SYMBOL: + if (e->left.expr->left.sym == &symbol_yes) { + // !'y' -> 'n' + tmp = e->left.expr; + free(e); + e = tmp; + e->type = E_SYMBOL; + e->left.sym = &symbol_no; + break; + } + if (e->left.expr->left.sym == &symbol_mod) { + // !'m' -> 'm' + tmp = e->left.expr; + free(e); + e = tmp; + e->type = E_SYMBOL; + e->left.sym = &symbol_mod; + break; + } + if (e->left.expr->left.sym == &symbol_no) { + // !'n' -> 'y' + tmp = e->left.expr; + free(e); + e = tmp; + e->type = E_SYMBOL; + e->left.sym = &symbol_yes; + break; + } + break; + default: + ; + } + break; + default: + ; + } + return e; +} + +int expr_contains_symbol(struct expr *dep, struct symbol *sym) +{ + if (!dep) + return 0; + + switch (dep->type) { + case E_AND: + case E_OR: + return expr_contains_symbol(dep->left.expr, sym) || + expr_contains_symbol(dep->right.expr, sym); + case E_SYMBOL: + return dep->left.sym == sym; + case E_EQUAL: + case E_UNEQUAL: + return dep->left.sym == sym || + dep->right.sym == sym; + case E_NOT: + return expr_contains_symbol(dep->left.expr, sym); + default: + ; + } + return 0; +} + +bool expr_depends_symbol(struct expr *dep, struct symbol *sym) +{ + if (!dep) + return false; + + switch (dep->type) { + case E_AND: + return expr_depends_symbol(dep->left.expr, sym) || + expr_depends_symbol(dep->right.expr, sym); + case E_SYMBOL: + return dep->left.sym == sym; + case E_EQUAL: + if (dep->left.sym == sym) { + if (dep->right.sym == &symbol_yes || dep->right.sym == &symbol_mod) + return true; + } + break; + case E_UNEQUAL: + if (dep->left.sym == sym) { + if (dep->right.sym == &symbol_no) + return true; + } + break; + default: + ; + } + return false; +} + +struct expr *expr_extract_eq_and(struct expr **ep1, struct expr **ep2) +{ + struct expr *tmp = NULL; + expr_extract_eq(E_AND, &tmp, ep1, ep2); + if (tmp) { + *ep1 = expr_eliminate_yn(*ep1); + *ep2 = expr_eliminate_yn(*ep2); + } + return tmp; +} + +struct expr *expr_extract_eq_or(struct expr **ep1, struct expr **ep2) +{ + struct expr *tmp = NULL; + expr_extract_eq(E_OR, &tmp, ep1, ep2); + if (tmp) { + *ep1 = expr_eliminate_yn(*ep1); + *ep2 = expr_eliminate_yn(*ep2); + } + return tmp; +} + +void expr_extract_eq(enum expr_type type, struct expr **ep, struct expr **ep1, struct expr **ep2) +{ +#define e1 (*ep1) +#define e2 (*ep2) + if (e1->type == type) { + expr_extract_eq(type, ep, &e1->left.expr, &e2); + expr_extract_eq(type, ep, &e1->right.expr, &e2); + return; + } + if (e2->type == type) { + expr_extract_eq(type, ep, ep1, &e2->left.expr); + expr_extract_eq(type, ep, ep1, &e2->right.expr); + return; + } + if (expr_eq(e1, e2)) { + *ep = *ep ? expr_alloc_two(type, *ep, e1) : e1; + expr_free(e2); + if (type == E_AND) { + e1 = expr_alloc_symbol(&symbol_yes); + e2 = expr_alloc_symbol(&symbol_yes); + } else if (type == E_OR) { + e1 = expr_alloc_symbol(&symbol_no); + e2 = expr_alloc_symbol(&symbol_no); + } + } +#undef e1 +#undef e2 +} + +struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symbol *sym) +{ + struct expr *e1, *e2; + + if (!e) { + e = expr_alloc_symbol(sym); + if (type == E_UNEQUAL) + e = expr_alloc_one(E_NOT, e); + return e; + } + switch (e->type) { + case E_AND: + e1 = expr_trans_compare(e->left.expr, E_EQUAL, sym); + e2 = expr_trans_compare(e->right.expr, E_EQUAL, sym); + if (sym == &symbol_yes) + e = expr_alloc_two(E_AND, e1, e2); + if (sym == &symbol_no) + e = expr_alloc_two(E_OR, e1, e2); + if (type == E_UNEQUAL) + e = expr_alloc_one(E_NOT, e); + return e; + case E_OR: + e1 = expr_trans_compare(e->left.expr, E_EQUAL, sym); + e2 = expr_trans_compare(e->right.expr, E_EQUAL, sym); + if (sym == &symbol_yes) + e = expr_alloc_two(E_OR, e1, e2); + if (sym == &symbol_no) + e = expr_alloc_two(E_AND, e1, e2); + if (type == E_UNEQUAL) + e = expr_alloc_one(E_NOT, e); + return e; + case E_NOT: + return expr_trans_compare(e->left.expr, type == E_EQUAL ? E_UNEQUAL : E_EQUAL, sym); + case E_UNEQUAL: + case E_EQUAL: + if (type == E_EQUAL) { + if (sym == &symbol_yes) + return expr_copy(e); + if (sym == &symbol_mod) + return expr_alloc_symbol(&symbol_no); + if (sym == &symbol_no) + return expr_alloc_one(E_NOT, expr_copy(e)); + } else { + if (sym == &symbol_yes) + return expr_alloc_one(E_NOT, expr_copy(e)); + if (sym == &symbol_mod) + return expr_alloc_symbol(&symbol_yes); + if (sym == &symbol_no) + return expr_copy(e); + } + break; + case E_SYMBOL: + return expr_alloc_comp(type, e->left.sym, sym); + case E_LIST: + case E_RANGE: + case E_NONE: + /* panic */; + } + return NULL; +} + +tristate expr_calc_value(struct expr *e) +{ + tristate val1, val2; + const char *str1, *str2; + + if (!e) + return yes; + + switch (e->type) { + case E_SYMBOL: + sym_calc_value(e->left.sym); + return e->left.sym->curr.tri; + case E_AND: + val1 = expr_calc_value(e->left.expr); + val2 = expr_calc_value(e->right.expr); + return EXPR_AND(val1, val2); + case E_OR: + val1 = expr_calc_value(e->left.expr); + val2 = expr_calc_value(e->right.expr); + return EXPR_OR(val1, val2); + case E_NOT: + val1 = expr_calc_value(e->left.expr); + return EXPR_NOT(val1); + case E_EQUAL: + sym_calc_value(e->left.sym); + sym_calc_value(e->right.sym); + str1 = sym_get_string_value(e->left.sym); + str2 = sym_get_string_value(e->right.sym); + return !strcmp(str1, str2) ? yes : no; + case E_UNEQUAL: + sym_calc_value(e->left.sym); + sym_calc_value(e->right.sym); + str1 = sym_get_string_value(e->left.sym); + str2 = sym_get_string_value(e->right.sym); + return !strcmp(str1, str2) ? no : yes; + default: + printf("expr_calc_value: %d?\n", e->type); + return no; + } +} + +int expr_compare_type(enum expr_type t1, enum expr_type t2) +{ +#if 0 + return 1; +#else + if (t1 == t2) + return 0; + switch (t1) { + case E_EQUAL: + case E_UNEQUAL: + if (t2 == E_NOT) + return 1; + case E_NOT: + if (t2 == E_AND) + return 1; + case E_AND: + if (t2 == E_OR) + return 1; + case E_OR: + if (t2 == E_LIST) + return 1; + case E_LIST: + if (t2 == 0) + return 1; + default: + return -1; + } + printf("[%dgt%d?]", t1, t2); + return 0; +#endif +} + +static inline struct expr * +expr_get_leftmost_symbol(const struct expr *e) +{ + + if (e == NULL) + return NULL; + + while (e->type != E_SYMBOL) + e = e->left.expr; + + return expr_copy(e); +} + +/* + * Given expression `e1' and `e2', returns the leaf of the longest + * sub-expression of `e1' not containing 'e2. + */ +struct expr *expr_simplify_unmet_dep(struct expr *e1, struct expr *e2) +{ + struct expr *ret; + + switch (e1->type) { + case E_OR: + return expr_alloc_and( + expr_simplify_unmet_dep(e1->left.expr, e2), + expr_simplify_unmet_dep(e1->right.expr, e2)); + case E_AND: { + struct expr *e; + e = expr_alloc_and(expr_copy(e1), expr_copy(e2)); + e = expr_eliminate_dups(e); + ret = (!expr_eq(e, e1)) ? e1 : NULL; + expr_free(e); + break; + } + default: + ret = e1; + break; + } + + return expr_get_leftmost_symbol(ret); +} + +void expr_print(struct expr *e, void (*fn)(void *, struct symbol *, const char *), void *data, int prevtoken) +{ + if (!e) { + fn(data, NULL, "y"); + return; + } + + if (expr_compare_type(prevtoken, e->type) > 0) + fn(data, NULL, "("); + switch (e->type) { + case E_SYMBOL: + if (e->left.sym->name) + fn(data, e->left.sym, e->left.sym->name); + else + fn(data, NULL, ""); + break; + case E_NOT: + fn(data, NULL, "!"); + expr_print(e->left.expr, fn, data, E_NOT); + break; + case E_EQUAL: + if (e->left.sym->name) + fn(data, e->left.sym, e->left.sym->name); + else + fn(data, NULL, ""); + fn(data, NULL, "="); + fn(data, e->right.sym, e->right.sym->name); + break; + case E_UNEQUAL: + if (e->left.sym->name) + fn(data, e->left.sym, e->left.sym->name); + else + fn(data, NULL, ""); + fn(data, NULL, "!="); + fn(data, e->right.sym, e->right.sym->name); + break; + case E_OR: + expr_print(e->left.expr, fn, data, E_OR); + fn(data, NULL, " || "); + expr_print(e->right.expr, fn, data, E_OR); + break; + case E_AND: + expr_print(e->left.expr, fn, data, E_AND); + fn(data, NULL, " && "); + expr_print(e->right.expr, fn, data, E_AND); + break; + case E_LIST: + fn(data, e->right.sym, e->right.sym->name); + if (e->left.expr) { + fn(data, NULL, " ^ "); + expr_print(e->left.expr, fn, data, E_LIST); + } + break; + case E_RANGE: + fn(data, NULL, "["); + fn(data, e->left.sym, e->left.sym->name); + fn(data, NULL, " "); + fn(data, e->right.sym, e->right.sym->name); + fn(data, NULL, "]"); + break; + default: + { + char buf[32]; + sprintf(buf, "", e->type); + fn(data, NULL, buf); + break; + } + } + if (expr_compare_type(prevtoken, e->type) > 0) + fn(data, NULL, ")"); +} + +static void expr_print_file_helper(void *data, struct symbol *sym, const char *str) +{ + xfwrite(str, strlen(str), 1, data); +} + +void expr_fprint(struct expr *e, FILE *out) +{ + expr_print(e, expr_print_file_helper, out, E_NONE); +} + +static void expr_print_gstr_helper(void *data, struct symbol *sym, const char *str) +{ + struct gstr *gs = (struct gstr*)data; + const char *sym_str = NULL; + + if (sym) + sym_str = sym_get_string_value(sym); + + if (gs->max_width) { + unsigned extra_length = strlen(str); + const char *last_cr = strrchr(gs->s, '\n'); + unsigned last_line_length; + + if (sym_str) + extra_length += 4 + strlen(sym_str); + + if (!last_cr) + last_cr = gs->s; + + last_line_length = strlen(gs->s) - (last_cr - gs->s); + + if ((last_line_length + extra_length) > gs->max_width) + str_append(gs, "\\\n"); + } + + str_append(gs, str); + if (sym && sym->type != S_UNKNOWN) + str_printf(gs, " [=%s]", sym_str); +} + +void expr_gstr_print(struct expr *e, struct gstr *gs) +{ + expr_print(e, expr_print_gstr_helper, gs, E_NONE); +} diff --git a/l4/tool/kconfig/scripts/kconfig/expr.h b/l4/tool/kconfig/scripts/kconfig/expr.h new file mode 100644 index 00000000..d4ecce8b --- /dev/null +++ b/l4/tool/kconfig/scripts/kconfig/expr.h @@ -0,0 +1,225 @@ +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +#ifndef EXPR_H +#define EXPR_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#ifndef __cplusplus +#include +#endif + +struct file { + struct file *next; + struct file *parent; + const char *name; + int lineno; +}; + +typedef enum tristate { + no, mod, yes +} tristate; + +enum expr_type { + E_NONE, E_OR, E_AND, E_NOT, E_EQUAL, E_UNEQUAL, E_LIST, E_SYMBOL, E_RANGE +}; + +union expr_data { + struct expr *expr; + struct symbol *sym; +}; + +struct expr { + enum expr_type type; + union expr_data left, right; +}; + +#define EXPR_OR(dep1, dep2) (((dep1)>(dep2))?(dep1):(dep2)) +#define EXPR_AND(dep1, dep2) (((dep1)<(dep2))?(dep1):(dep2)) +#define EXPR_NOT(dep) (2-(dep)) + +#define expr_list_for_each_sym(l, e, s) \ + for (e = (l); e && (s = e->right.sym); e = e->left.expr) + +struct expr_value { + struct expr *expr; + tristate tri; +}; + +struct symbol_value { + void *val; + tristate tri; +}; + +enum symbol_type { + S_UNKNOWN, S_BOOLEAN, S_TRISTATE, S_INT, S_HEX, S_STRING, S_OTHER +}; + +/* enum values are used as index to symbol.def[] */ +enum { + S_DEF_USER, /* main user value */ + S_DEF_AUTO, /* values read from auto.conf */ + S_DEF_DEF3, /* Reserved for UI usage */ + S_DEF_DEF4, /* Reserved for UI usage */ + S_DEF_COUNT +}; + +struct symbol { + struct symbol *next; + char *name; + enum symbol_type type; + struct symbol_value curr; + struct symbol_value def[S_DEF_COUNT]; + tristate visible; + int flags; + struct property *prop; + struct expr_value dir_dep; + struct expr_value rev_dep; +}; + +#define for_all_symbols(i, sym) for (i = 0; i < SYMBOL_HASHSIZE; i++) for (sym = symbol_hash[i]; sym; sym = sym->next) if (sym->type != S_OTHER) + +#define SYMBOL_CONST 0x0001 /* symbol is const */ +#define SYMBOL_CHECK 0x0008 /* used during dependency checking */ +#define SYMBOL_CHOICE 0x0010 /* start of a choice block (null name) */ +#define SYMBOL_CHOICEVAL 0x0020 /* used as a value in a choice block */ +#define SYMBOL_VALID 0x0080 /* set when symbol.curr is calculated */ +#define SYMBOL_OPTIONAL 0x0100 /* choice is optional - values can be 'n' */ +#define SYMBOL_WRITE 0x0200 /* ? */ +#define SYMBOL_CHANGED 0x0400 /* ? */ +#define SYMBOL_AUTO 0x1000 /* value from environment variable */ +#define SYMBOL_CHECKED 0x2000 /* used during dependency checking */ +#define SYMBOL_WARNED 0x8000 /* warning has been issued */ + +/* Set when symbol.def[] is used */ +#define SYMBOL_DEF 0x10000 /* First bit of SYMBOL_DEF */ +#define SYMBOL_DEF_USER 0x10000 /* symbol.def[S_DEF_USER] is valid */ +#define SYMBOL_DEF_AUTO 0x20000 /* symbol.def[S_DEF_AUTO] is valid */ +#define SYMBOL_DEF3 0x40000 /* symbol.def[S_DEF_3] is valid */ +#define SYMBOL_DEF4 0x80000 /* symbol.def[S_DEF_4] is valid */ + +#define SYMBOL_MAXLENGTH 256 +#define SYMBOL_HASHSIZE 9973 + +/* A property represent the config options that can be associated + * with a config "symbol". + * Sample: + * config FOO + * default y + * prompt "foo prompt" + * select BAR + * config BAZ + * int "BAZ Value" + * range 1..255 + */ +enum prop_type { + P_UNKNOWN, + P_PROMPT, /* prompt "foo prompt" or "BAZ Value" */ + P_COMMENT, /* text associated with a comment */ + P_MENU, /* prompt associated with a menuconfig option */ + P_DEFAULT, /* default y */ + P_CHOICE, /* choice value */ + P_SELECT, /* select BAR */ + P_RANGE, /* range 7..100 (for a symbol) */ + P_ENV, /* value from environment variable */ + P_SYMBOL, /* where a symbol is defined */ +}; + +struct property { + struct property *next; /* next property - null if last */ + struct symbol *sym; /* the symbol for which the property is associated */ + enum prop_type type; /* type of property */ + const char *text; /* the prompt value - P_PROMPT, P_MENU, P_COMMENT */ + struct expr_value visible; + struct expr *expr; /* the optional conditional part of the property */ + struct menu *menu; /* the menu the property are associated with + * valid for: P_SELECT, P_RANGE, P_CHOICE, + * P_PROMPT, P_DEFAULT, P_MENU, P_COMMENT */ + struct file *file; /* what file was this property defined */ + int lineno; /* what lineno was this property defined */ +}; + +#define for_all_properties(sym, st, tok) \ + for (st = sym->prop; st; st = st->next) \ + if (st->type == (tok)) +#define for_all_defaults(sym, st) for_all_properties(sym, st, P_DEFAULT) +#define for_all_choices(sym, st) for_all_properties(sym, st, P_CHOICE) +#define for_all_prompts(sym, st) \ + for (st = sym->prop; st; st = st->next) \ + if (st->text) + +struct menu { + struct menu *next; + struct menu *parent; + struct menu *list; + struct symbol *sym; + struct property *prompt; + struct expr *visibility; + struct expr *dep; + unsigned int flags; + char *help; + struct file *file; + int lineno; + void *data; +}; + +#define MENU_CHANGED 0x0001 +#define MENU_ROOT 0x0002 + +extern struct file *file_list; +extern struct file *current_file; +struct file *lookup_file(const char *name); + +extern struct symbol symbol_yes, symbol_no, symbol_mod; +extern struct symbol *modules_sym; +extern struct symbol *sym_defconfig_list; +extern int cdebug; +struct expr *expr_alloc_symbol(struct symbol *sym); +struct expr *expr_alloc_one(enum expr_type type, struct expr *ce); +struct expr *expr_alloc_two(enum expr_type type, struct expr *e1, struct expr *e2); +struct expr *expr_alloc_comp(enum expr_type type, struct symbol *s1, struct symbol *s2); +struct expr *expr_alloc_and(struct expr *e1, struct expr *e2); +struct expr *expr_alloc_or(struct expr *e1, struct expr *e2); +struct expr *expr_copy(const struct expr *org); +void expr_free(struct expr *e); +int expr_eq(struct expr *e1, struct expr *e2); +void expr_eliminate_eq(struct expr **ep1, struct expr **ep2); +tristate expr_calc_value(struct expr *e); +struct expr *expr_eliminate_yn(struct expr *e); +struct expr *expr_trans_bool(struct expr *e); +struct expr *expr_eliminate_dups(struct expr *e); +struct expr *expr_transform(struct expr *e); +int expr_contains_symbol(struct expr *dep, struct symbol *sym); +bool expr_depends_symbol(struct expr *dep, struct symbol *sym); +struct expr *expr_extract_eq_and(struct expr **ep1, struct expr **ep2); +struct expr *expr_extract_eq_or(struct expr **ep1, struct expr **ep2); +void expr_extract_eq(enum expr_type type, struct expr **ep, struct expr **ep1, struct expr **ep2); +struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symbol *sym); +struct expr *expr_simplify_unmet_dep(struct expr *e1, struct expr *e2); + +void expr_fprint(struct expr *e, FILE *out); +struct gstr; /* forward */ +void expr_gstr_print(struct expr *e, struct gstr *gs); + +static inline int expr_is_yes(struct expr *e) +{ + return !e || (e->type == E_SYMBOL && e->left.sym == &symbol_yes); +} + +static inline int expr_is_no(struct expr *e) +{ + return e && (e->type == E_SYMBOL && e->left.sym == &symbol_no); +} + +#ifdef __cplusplus +} +#endif + +#endif /* EXPR_H */ diff --git a/l4/tool/kconfig/scripts/kconfig/gconf.c b/l4/tool/kconfig/scripts/kconfig/gconf.c new file mode 100644 index 00000000..7491559f --- /dev/null +++ b/l4/tool/kconfig/scripts/kconfig/gconf.c @@ -0,0 +1,1542 @@ +/* Hey EMACS -*- linux-c -*- */ +/* + * + * Copyright (C) 2002-2003 Romain Lievin + * Released under the terms of the GNU GPL v2.0. + * + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "lkc.h" +#include "images.c" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +//#define DEBUG + +enum { + SINGLE_VIEW, SPLIT_VIEW, FULL_VIEW +}; + +enum { + OPT_NORMAL, OPT_ALL, OPT_PROMPT +}; + +static gint view_mode = FULL_VIEW; +static gboolean show_name = TRUE; +static gboolean show_range = TRUE; +static gboolean show_value = TRUE; +static gboolean resizeable = FALSE; +static int opt_mode = OPT_NORMAL; + +GtkWidget *main_wnd = NULL; +GtkWidget *tree1_w = NULL; // left frame +GtkWidget *tree2_w = NULL; // right frame +GtkWidget *text_w = NULL; +GtkWidget *hpaned = NULL; +GtkWidget *vpaned = NULL; +GtkWidget *back_btn = NULL; +GtkWidget *save_btn = NULL; +GtkWidget *save_menu_item = NULL; + +GtkTextTag *tag1, *tag2; +GdkColor color; + +GtkTreeStore *tree1, *tree2, *tree; +GtkTreeModel *model1, *model2; +static GtkTreeIter *parents[256]; +static gint indent; + +static struct menu *current; // current node for SINGLE view +static struct menu *browsed; // browsed node for SPLIT view + +enum { + COL_OPTION, COL_NAME, COL_NO, COL_MOD, COL_YES, COL_VALUE, + COL_MENU, COL_COLOR, COL_EDIT, COL_PIXBUF, + COL_PIXVIS, COL_BTNVIS, COL_BTNACT, COL_BTNINC, COL_BTNRAD, + COL_NUMBER +}; + +static void display_list(void); +static void display_tree(struct menu *menu); +static void display_tree_part(void); +static void update_tree(struct menu *src, GtkTreeIter * dst); +static void set_node(GtkTreeIter * node, struct menu *menu, gchar ** row); +static gchar **fill_row(struct menu *menu); +static void conf_changed(void); + +/* Helping/Debugging Functions */ + +const char *dbg_sym_flags(int val) +{ + static char buf[256]; + + bzero(buf, 256); + + if (val & SYMBOL_CONST) + strcat(buf, "const/"); + if (val & SYMBOL_CHECK) + strcat(buf, "check/"); + if (val & SYMBOL_CHOICE) + strcat(buf, "choice/"); + if (val & SYMBOL_CHOICEVAL) + strcat(buf, "choiceval/"); + if (val & SYMBOL_VALID) + strcat(buf, "valid/"); + if (val & SYMBOL_OPTIONAL) + strcat(buf, "optional/"); + if (val & SYMBOL_WRITE) + strcat(buf, "write/"); + if (val & SYMBOL_CHANGED) + strcat(buf, "changed/"); + if (val & SYMBOL_AUTO) + strcat(buf, "auto/"); + + buf[strlen(buf) - 1] = '\0'; + + return buf; +} + +void replace_button_icon(GladeXML * xml, GdkDrawable * window, + GtkStyle * style, gchar * btn_name, gchar ** xpm) +{ + GdkPixmap *pixmap; + GdkBitmap *mask; + GtkToolButton *button; + GtkWidget *image; + + pixmap = gdk_pixmap_create_from_xpm_d(window, &mask, + &style->bg[GTK_STATE_NORMAL], + xpm); + + button = GTK_TOOL_BUTTON(glade_xml_get_widget(xml, btn_name)); + image = gtk_image_new_from_pixmap(pixmap, mask); + gtk_widget_show(image); + gtk_tool_button_set_icon_widget(button, image); +} + +/* Main Window Initialization */ +void init_main_window(const gchar * glade_file) +{ + GladeXML *xml; + GtkWidget *widget; + GtkTextBuffer *txtbuf; + GtkStyle *style; + + xml = glade_xml_new(glade_file, "window1", NULL); + if (!xml) + g_error(_("GUI loading failed !\n")); + glade_xml_signal_autoconnect(xml); + + main_wnd = glade_xml_get_widget(xml, "window1"); + hpaned = glade_xml_get_widget(xml, "hpaned1"); + vpaned = glade_xml_get_widget(xml, "vpaned1"); + tree1_w = glade_xml_get_widget(xml, "treeview1"); + tree2_w = glade_xml_get_widget(xml, "treeview2"); + text_w = glade_xml_get_widget(xml, "textview3"); + + back_btn = glade_xml_get_widget(xml, "button1"); + gtk_widget_set_sensitive(back_btn, FALSE); + + widget = glade_xml_get_widget(xml, "show_name1"); + gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget, + show_name); + + widget = glade_xml_get_widget(xml, "show_range1"); + gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget, + show_range); + + widget = glade_xml_get_widget(xml, "show_data1"); + gtk_check_menu_item_set_active((GtkCheckMenuItem *) widget, + show_value); + + save_btn = glade_xml_get_widget(xml, "button3"); + save_menu_item = glade_xml_get_widget(xml, "save1"); + conf_set_changed_callback(conf_changed); + + style = gtk_widget_get_style(main_wnd); + widget = glade_xml_get_widget(xml, "toolbar1"); + +#if 0 /* Use stock Gtk icons instead */ + replace_button_icon(xml, main_wnd->window, style, + "button1", (gchar **) xpm_back); + replace_button_icon(xml, main_wnd->window, style, + "button2", (gchar **) xpm_load); + replace_button_icon(xml, main_wnd->window, style, + "button3", (gchar **) xpm_save); +#endif + replace_button_icon(xml, main_wnd->window, style, + "button4", (gchar **) xpm_single_view); + replace_button_icon(xml, main_wnd->window, style, + "button5", (gchar **) xpm_split_view); + replace_button_icon(xml, main_wnd->window, style, + "button6", (gchar **) xpm_tree_view); + +#if 0 + switch (view_mode) { + case SINGLE_VIEW: + widget = glade_xml_get_widget(xml, "button4"); + g_signal_emit_by_name(widget, "clicked"); + break; + case SPLIT_VIEW: + widget = glade_xml_get_widget(xml, "button5"); + g_signal_emit_by_name(widget, "clicked"); + break; + case FULL_VIEW: + widget = glade_xml_get_widget(xml, "button6"); + g_signal_emit_by_name(widget, "clicked"); + break; + } +#endif + txtbuf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w)); + tag1 = gtk_text_buffer_create_tag(txtbuf, "mytag1", + "foreground", "red", + "weight", PANGO_WEIGHT_BOLD, + NULL); + tag2 = gtk_text_buffer_create_tag(txtbuf, "mytag2", + /*"style", PANGO_STYLE_OBLIQUE, */ + NULL); + + gtk_window_set_title(GTK_WINDOW(main_wnd), rootmenu.prompt->text); + + gtk_widget_show(main_wnd); +} + +void init_tree_model(void) +{ + gint i; + + tree = tree2 = gtk_tree_store_new(COL_NUMBER, + G_TYPE_STRING, G_TYPE_STRING, + G_TYPE_STRING, G_TYPE_STRING, + G_TYPE_STRING, G_TYPE_STRING, + G_TYPE_POINTER, GDK_TYPE_COLOR, + G_TYPE_BOOLEAN, GDK_TYPE_PIXBUF, + G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, + G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, + G_TYPE_BOOLEAN); + model2 = GTK_TREE_MODEL(tree2); + + for (parents[0] = NULL, i = 1; i < 256; i++) + parents[i] = (GtkTreeIter *) g_malloc(sizeof(GtkTreeIter)); + + tree1 = gtk_tree_store_new(COL_NUMBER, + G_TYPE_STRING, G_TYPE_STRING, + G_TYPE_STRING, G_TYPE_STRING, + G_TYPE_STRING, G_TYPE_STRING, + G_TYPE_POINTER, GDK_TYPE_COLOR, + G_TYPE_BOOLEAN, GDK_TYPE_PIXBUF, + G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, + G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, + G_TYPE_BOOLEAN); + model1 = GTK_TREE_MODEL(tree1); +} + +void init_left_tree(void) +{ + GtkTreeView *view = GTK_TREE_VIEW(tree1_w); + GtkCellRenderer *renderer; + GtkTreeSelection *sel; + GtkTreeViewColumn *column; + + gtk_tree_view_set_model(view, model1); + gtk_tree_view_set_headers_visible(view, TRUE); + gtk_tree_view_set_rules_hint(view, TRUE); + + column = gtk_tree_view_column_new(); + gtk_tree_view_append_column(view, column); + gtk_tree_view_column_set_title(column, _("Options")); + + renderer = gtk_cell_renderer_toggle_new(); + gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column), + renderer, FALSE); + gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column), + renderer, + "active", COL_BTNACT, + "inconsistent", COL_BTNINC, + "visible", COL_BTNVIS, + "radio", COL_BTNRAD, NULL); + renderer = gtk_cell_renderer_text_new(); + gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column), + renderer, FALSE); + gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column), + renderer, + "text", COL_OPTION, + "foreground-gdk", + COL_COLOR, NULL); + + sel = gtk_tree_view_get_selection(view); + gtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE); + gtk_widget_realize(tree1_w); +} + +static void renderer_edited(GtkCellRendererText * cell, + const gchar * path_string, + const gchar * new_text, gpointer user_data); + +void init_right_tree(void) +{ + GtkTreeView *view = GTK_TREE_VIEW(tree2_w); + GtkCellRenderer *renderer; + GtkTreeSelection *sel; + GtkTreeViewColumn *column; + gint i; + + gtk_tree_view_set_model(view, model2); + gtk_tree_view_set_headers_visible(view, TRUE); + gtk_tree_view_set_rules_hint(view, TRUE); + + column = gtk_tree_view_column_new(); + gtk_tree_view_append_column(view, column); + gtk_tree_view_column_set_title(column, _("Options")); + + renderer = gtk_cell_renderer_pixbuf_new(); + gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column), + renderer, FALSE); + gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column), + renderer, + "pixbuf", COL_PIXBUF, + "visible", COL_PIXVIS, NULL); + renderer = gtk_cell_renderer_toggle_new(); + gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column), + renderer, FALSE); + gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column), + renderer, + "active", COL_BTNACT, + "inconsistent", COL_BTNINC, + "visible", COL_BTNVIS, + "radio", COL_BTNRAD, NULL); + renderer = gtk_cell_renderer_text_new(); + gtk_tree_view_column_pack_start(GTK_TREE_VIEW_COLUMN(column), + renderer, FALSE); + gtk_tree_view_column_set_attributes(GTK_TREE_VIEW_COLUMN(column), + renderer, + "text", COL_OPTION, + "foreground-gdk", + COL_COLOR, NULL); + + renderer = gtk_cell_renderer_text_new(); + gtk_tree_view_insert_column_with_attributes(view, -1, + _("Name"), renderer, + "text", COL_NAME, + "foreground-gdk", + COL_COLOR, NULL); + renderer = gtk_cell_renderer_text_new(); + gtk_tree_view_insert_column_with_attributes(view, -1, + "N", renderer, + "text", COL_NO, + "foreground-gdk", + COL_COLOR, NULL); + renderer = gtk_cell_renderer_text_new(); + gtk_tree_view_insert_column_with_attributes(view, -1, + "M", renderer, + "text", COL_MOD, + "foreground-gdk", + COL_COLOR, NULL); + renderer = gtk_cell_renderer_text_new(); + gtk_tree_view_insert_column_with_attributes(view, -1, + "Y", renderer, + "text", COL_YES, + "foreground-gdk", + COL_COLOR, NULL); + renderer = gtk_cell_renderer_text_new(); + gtk_tree_view_insert_column_with_attributes(view, -1, + _("Value"), renderer, + "text", COL_VALUE, + "editable", + COL_EDIT, + "foreground-gdk", + COL_COLOR, NULL); + g_signal_connect(G_OBJECT(renderer), "edited", + G_CALLBACK(renderer_edited), NULL); + + column = gtk_tree_view_get_column(view, COL_NAME); + gtk_tree_view_column_set_visible(column, show_name); + column = gtk_tree_view_get_column(view, COL_NO); + gtk_tree_view_column_set_visible(column, show_range); + column = gtk_tree_view_get_column(view, COL_MOD); + gtk_tree_view_column_set_visible(column, show_range); + column = gtk_tree_view_get_column(view, COL_YES); + gtk_tree_view_column_set_visible(column, show_range); + column = gtk_tree_view_get_column(view, COL_VALUE); + gtk_tree_view_column_set_visible(column, show_value); + + if (resizeable) { + for (i = 0; i < COL_VALUE; i++) { + column = gtk_tree_view_get_column(view, i); + gtk_tree_view_column_set_resizable(column, TRUE); + } + } + + sel = gtk_tree_view_get_selection(view); + gtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE); +} + + +/* Utility Functions */ + + +static void text_insert_help(struct menu *menu) +{ + GtkTextBuffer *buffer; + GtkTextIter start, end; + const char *prompt = _(menu_get_prompt(menu)); + struct gstr help = str_new(); + + menu_get_ext_help(menu, &help); + + buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w)); + gtk_text_buffer_get_bounds(buffer, &start, &end); + gtk_text_buffer_delete(buffer, &start, &end); + gtk_text_view_set_left_margin(GTK_TEXT_VIEW(text_w), 15); + + gtk_text_buffer_get_end_iter(buffer, &end); + gtk_text_buffer_insert_with_tags(buffer, &end, prompt, -1, tag1, + NULL); + gtk_text_buffer_insert_at_cursor(buffer, "\n\n", 2); + gtk_text_buffer_get_end_iter(buffer, &end); + gtk_text_buffer_insert_with_tags(buffer, &end, str_get(&help), -1, tag2, + NULL); + str_free(&help); +} + + +static void text_insert_msg(const char *title, const char *message) +{ + GtkTextBuffer *buffer; + GtkTextIter start, end; + const char *msg = message; + + buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_w)); + gtk_text_buffer_get_bounds(buffer, &start, &end); + gtk_text_buffer_delete(buffer, &start, &end); + gtk_text_view_set_left_margin(GTK_TEXT_VIEW(text_w), 15); + + gtk_text_buffer_get_end_iter(buffer, &end); + gtk_text_buffer_insert_with_tags(buffer, &end, title, -1, tag1, + NULL); + gtk_text_buffer_insert_at_cursor(buffer, "\n\n", 2); + gtk_text_buffer_get_end_iter(buffer, &end); + gtk_text_buffer_insert_with_tags(buffer, &end, msg, -1, tag2, + NULL); +} + + +/* Main Windows Callbacks */ + +void on_save_activate(GtkMenuItem * menuitem, gpointer user_data); +gboolean on_window1_delete_event(GtkWidget * widget, GdkEvent * event, + gpointer user_data) +{ + GtkWidget *dialog, *label; + gint result; + + if (!conf_get_changed()) + return FALSE; + + dialog = gtk_dialog_new_with_buttons(_("Warning !"), + GTK_WINDOW(main_wnd), + (GtkDialogFlags) + (GTK_DIALOG_MODAL | + GTK_DIALOG_DESTROY_WITH_PARENT), + GTK_STOCK_OK, + GTK_RESPONSE_YES, + GTK_STOCK_NO, + GTK_RESPONSE_NO, + GTK_STOCK_CANCEL, + GTK_RESPONSE_CANCEL, NULL); + gtk_dialog_set_default_response(GTK_DIALOG(dialog), + GTK_RESPONSE_CANCEL); + + label = gtk_label_new(_("\nSave configuration ?\n")); + gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), label); + gtk_widget_show(label); + + result = gtk_dialog_run(GTK_DIALOG(dialog)); + switch (result) { + case GTK_RESPONSE_YES: + on_save_activate(NULL, NULL); + return FALSE; + case GTK_RESPONSE_NO: + return FALSE; + case GTK_RESPONSE_CANCEL: + case GTK_RESPONSE_DELETE_EVENT: + default: + gtk_widget_destroy(dialog); + return TRUE; + } + + return FALSE; +} + + +void on_window1_destroy(GtkObject * object, gpointer user_data) +{ + gtk_main_quit(); +} + + +void +on_window1_size_request(GtkWidget * widget, + GtkRequisition * requisition, gpointer user_data) +{ + static gint old_h; + gint w, h; + + if (widget->window == NULL) + gtk_window_get_default_size(GTK_WINDOW(main_wnd), &w, &h); + else + gdk_window_get_size(widget->window, &w, &h); + + if (h == old_h) + return; + old_h = h; + + gtk_paned_set_position(GTK_PANED(vpaned), 2 * h / 3); +} + + +/* Menu & Toolbar Callbacks */ + + +static void +load_filename(GtkFileSelection * file_selector, gpointer user_data) +{ + const gchar *fn; + + fn = gtk_file_selection_get_filename(GTK_FILE_SELECTION + (user_data)); + + if (conf_read(fn)) + text_insert_msg(_("Error"), _("Unable to load configuration !")); + else + display_tree(&rootmenu); +} + +void on_load1_activate(GtkMenuItem * menuitem, gpointer user_data) +{ + GtkWidget *fs; + + fs = gtk_file_selection_new(_("Load file...")); + g_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(fs)->ok_button), + "clicked", + G_CALLBACK(load_filename), (gpointer) fs); + g_signal_connect_swapped(GTK_OBJECT + (GTK_FILE_SELECTION(fs)->ok_button), + "clicked", G_CALLBACK(gtk_widget_destroy), + (gpointer) fs); + g_signal_connect_swapped(GTK_OBJECT + (GTK_FILE_SELECTION(fs)->cancel_button), + "clicked", G_CALLBACK(gtk_widget_destroy), + (gpointer) fs); + gtk_widget_show(fs); +} + + +void on_save_activate(GtkMenuItem * menuitem, gpointer user_data) +{ + if (conf_write(NULL)) + text_insert_msg(_("Error"), _("Unable to save configuration !")); +} + + +static void +store_filename(GtkFileSelection * file_selector, gpointer user_data) +{ + const gchar *fn; + + fn = gtk_file_selection_get_filename(GTK_FILE_SELECTION + (user_data)); + + if (conf_write(fn)) + text_insert_msg(_("Error"), _("Unable to save configuration !")); + + gtk_widget_destroy(GTK_WIDGET(user_data)); +} + +void on_save_as1_activate(GtkMenuItem * menuitem, gpointer user_data) +{ + GtkWidget *fs; + + fs = gtk_file_selection_new(_("Save file as...")); + g_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(fs)->ok_button), + "clicked", + G_CALLBACK(store_filename), (gpointer) fs); + g_signal_connect_swapped(GTK_OBJECT + (GTK_FILE_SELECTION(fs)->ok_button), + "clicked", G_CALLBACK(gtk_widget_destroy), + (gpointer) fs); + g_signal_connect_swapped(GTK_OBJECT + (GTK_FILE_SELECTION(fs)->cancel_button), + "clicked", G_CALLBACK(gtk_widget_destroy), + (gpointer) fs); + gtk_widget_show(fs); +} + + +void on_quit1_activate(GtkMenuItem * menuitem, gpointer user_data) +{ + if (!on_window1_delete_event(NULL, NULL, NULL)) + gtk_widget_destroy(GTK_WIDGET(main_wnd)); +} + + +void on_show_name1_activate(GtkMenuItem * menuitem, gpointer user_data) +{ + GtkTreeViewColumn *col; + + show_name = GTK_CHECK_MENU_ITEM(menuitem)->active; + col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_NAME); + if (col) + gtk_tree_view_column_set_visible(col, show_name); +} + + +void on_show_range1_activate(GtkMenuItem * menuitem, gpointer user_data) +{ + GtkTreeViewColumn *col; + + show_range = GTK_CHECK_MENU_ITEM(menuitem)->active; + col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_NO); + if (col) + gtk_tree_view_column_set_visible(col, show_range); + col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_MOD); + if (col) + gtk_tree_view_column_set_visible(col, show_range); + col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_YES); + if (col) + gtk_tree_view_column_set_visible(col, show_range); + +} + + +void on_show_data1_activate(GtkMenuItem * menuitem, gpointer user_data) +{ + GtkTreeViewColumn *col; + + show_value = GTK_CHECK_MENU_ITEM(menuitem)->active; + col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), COL_VALUE); + if (col) + gtk_tree_view_column_set_visible(col, show_value); +} + + +void +on_set_option_mode1_activate(GtkMenuItem *menuitem, gpointer user_data) +{ + opt_mode = OPT_NORMAL; + gtk_tree_store_clear(tree2); + display_tree(&rootmenu); /* instead of update_tree to speed-up */ +} + + +void +on_set_option_mode2_activate(GtkMenuItem *menuitem, gpointer user_data) +{ + opt_mode = OPT_ALL; + gtk_tree_store_clear(tree2); + display_tree(&rootmenu); /* instead of update_tree to speed-up */ +} + + +void +on_set_option_mode3_activate(GtkMenuItem *menuitem, gpointer user_data) +{ + opt_mode = OPT_PROMPT; + gtk_tree_store_clear(tree2); + display_tree(&rootmenu); /* instead of update_tree to speed-up */ +} + + +void on_introduction1_activate(GtkMenuItem * menuitem, gpointer user_data) +{ + GtkWidget *dialog; + const gchar *intro_text = _( + "Welcome to gkc, the GTK+ graphical configuration tool\n" + "For each option, a blank box indicates the feature is disabled, a\n" + "check indicates it is enabled, and a dot indicates that it is to\n" + "be compiled as a module. Clicking on the box will cycle through the three states.\n" + "\n" + "If you do not see an option (e.g., a device driver) that you\n" + "believe should be present, try turning on Show All Options\n" + "under the Options menu.\n" + "Although there is no cross reference yet to help you figure out\n" + "what other options must be enabled to support the option you\n" + "are interested in, you can still view the help of a grayed-out\n" + "option.\n" + "\n" + "Toggling Show Debug Info under the Options menu will show \n" + "the dependencies, which you can then match by examining other options."); + + dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_INFO, + GTK_BUTTONS_CLOSE, "%s", intro_text); + g_signal_connect_swapped(GTK_OBJECT(dialog), "response", + G_CALLBACK(gtk_widget_destroy), + GTK_OBJECT(dialog)); + gtk_widget_show_all(dialog); +} + + +void on_about1_activate(GtkMenuItem * menuitem, gpointer user_data) +{ + GtkWidget *dialog; + const gchar *about_text = + _("gkc is copyright (c) 2002 Romain Lievin .\n" + "Based on the source code from Roman Zippel.\n"); + + dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_INFO, + GTK_BUTTONS_CLOSE, "%s", about_text); + g_signal_connect_swapped(GTK_OBJECT(dialog), "response", + G_CALLBACK(gtk_widget_destroy), + GTK_OBJECT(dialog)); + gtk_widget_show_all(dialog); +} + + +void on_license1_activate(GtkMenuItem * menuitem, gpointer user_data) +{ + GtkWidget *dialog; + const gchar *license_text = + _("gkc is released under the terms of the GNU GPL v2.\n" + "For more information, please see the source code or\n" + "visit http://www.fsf.org/licenses/licenses.html\n"); + + dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_INFO, + GTK_BUTTONS_CLOSE, "%s", license_text); + g_signal_connect_swapped(GTK_OBJECT(dialog), "response", + G_CALLBACK(gtk_widget_destroy), + GTK_OBJECT(dialog)); + gtk_widget_show_all(dialog); +} + + +void on_back_clicked(GtkButton * button, gpointer user_data) +{ + enum prop_type ptype; + + current = current->parent; + ptype = current->prompt ? current->prompt->type : P_UNKNOWN; + if (ptype != P_MENU) + current = current->parent; + display_tree_part(); + + if (current == &rootmenu) + gtk_widget_set_sensitive(back_btn, FALSE); +} + + +void on_load_clicked(GtkButton * button, gpointer user_data) +{ + on_load1_activate(NULL, user_data); +} + + +void on_single_clicked(GtkButton * button, gpointer user_data) +{ + view_mode = SINGLE_VIEW; + gtk_widget_hide(tree1_w); + current = &rootmenu; + display_tree_part(); +} + + +void on_split_clicked(GtkButton * button, gpointer user_data) +{ + gint w, h; + view_mode = SPLIT_VIEW; + gtk_widget_show(tree1_w); + gtk_window_get_default_size(GTK_WINDOW(main_wnd), &w, &h); + gtk_paned_set_position(GTK_PANED(hpaned), w / 2); + if (tree2) + gtk_tree_store_clear(tree2); + display_list(); + + /* Disable back btn, like in full mode. */ + gtk_widget_set_sensitive(back_btn, FALSE); +} + + +void on_full_clicked(GtkButton * button, gpointer user_data) +{ + view_mode = FULL_VIEW; + gtk_widget_hide(tree1_w); + if (tree2) + gtk_tree_store_clear(tree2); + display_tree(&rootmenu); + gtk_widget_set_sensitive(back_btn, FALSE); +} + + +void on_collapse_clicked(GtkButton * button, gpointer user_data) +{ + gtk_tree_view_collapse_all(GTK_TREE_VIEW(tree2_w)); +} + + +void on_expand_clicked(GtkButton * button, gpointer user_data) +{ + gtk_tree_view_expand_all(GTK_TREE_VIEW(tree2_w)); +} + + +/* CTree Callbacks */ + +/* Change hex/int/string value in the cell */ +static void renderer_edited(GtkCellRendererText * cell, + const gchar * path_string, + const gchar * new_text, gpointer user_data) +{ + GtkTreePath *path = gtk_tree_path_new_from_string(path_string); + GtkTreeIter iter; + const char *old_def, *new_def; + struct menu *menu; + struct symbol *sym; + + if (!gtk_tree_model_get_iter(model2, &iter, path)) + return; + + gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1); + sym = menu->sym; + + gtk_tree_model_get(model2, &iter, COL_VALUE, &old_def, -1); + new_def = new_text; + + sym_set_string_value(sym, new_def); + + update_tree(&rootmenu, NULL); + + gtk_tree_path_free(path); +} + +/* Change the value of a symbol and update the tree */ +static void change_sym_value(struct menu *menu, gint col) +{ + struct symbol *sym = menu->sym; + tristate newval; + + if (!sym) + return; + + if (col == COL_NO) + newval = no; + else if (col == COL_MOD) + newval = mod; + else if (col == COL_YES) + newval = yes; + else + return; + + switch (sym_get_type(sym)) { + case S_BOOLEAN: + case S_TRISTATE: + if (!sym_tristate_within_range(sym, newval)) + newval = yes; + sym_set_tristate_value(sym, newval); + if (view_mode == FULL_VIEW) + update_tree(&rootmenu, NULL); + else if (view_mode == SPLIT_VIEW) { + update_tree(browsed, NULL); + display_list(); + } + else if (view_mode == SINGLE_VIEW) + display_tree_part(); //fixme: keep exp/coll + break; + case S_INT: + case S_HEX: + case S_STRING: + default: + break; + } +} + +static void toggle_sym_value(struct menu *menu) +{ + if (!menu->sym) + return; + + sym_toggle_tristate_value(menu->sym); + if (view_mode == FULL_VIEW) + update_tree(&rootmenu, NULL); + else if (view_mode == SPLIT_VIEW) { + update_tree(browsed, NULL); + display_list(); + } + else if (view_mode == SINGLE_VIEW) + display_tree_part(); //fixme: keep exp/coll +} + +static gint column2index(GtkTreeViewColumn * column) +{ + gint i; + + for (i = 0; i < COL_NUMBER; i++) { + GtkTreeViewColumn *col; + + col = gtk_tree_view_get_column(GTK_TREE_VIEW(tree2_w), i); + if (col == column) + return i; + } + + return -1; +} + + +/* User click: update choice (full) or goes down (single) */ +gboolean +on_treeview2_button_press_event(GtkWidget * widget, + GdkEventButton * event, gpointer user_data) +{ + GtkTreeView *view = GTK_TREE_VIEW(widget); + GtkTreePath *path; + GtkTreeViewColumn *column; + GtkTreeIter iter; + struct menu *menu; + gint col; + +#if GTK_CHECK_VERSION(2,1,4) // bug in ctree with earlier version of GTK + gint tx = (gint) event->x; + gint ty = (gint) event->y; + gint cx, cy; + + gtk_tree_view_get_path_at_pos(view, tx, ty, &path, &column, &cx, + &cy); +#else + gtk_tree_view_get_cursor(view, &path, &column); +#endif + if (path == NULL) + return FALSE; + + if (!gtk_tree_model_get_iter(model2, &iter, path)) + return FALSE; + gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1); + + col = column2index(column); + if (event->type == GDK_2BUTTON_PRESS) { + enum prop_type ptype; + ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN; + + if (ptype == P_MENU && view_mode != FULL_VIEW && col == COL_OPTION) { + // goes down into menu + current = menu; + display_tree_part(); + gtk_widget_set_sensitive(back_btn, TRUE); + } else if ((col == COL_OPTION)) { + toggle_sym_value(menu); + gtk_tree_view_expand_row(view, path, TRUE); + } + } else { + if (col == COL_VALUE) { + toggle_sym_value(menu); + gtk_tree_view_expand_row(view, path, TRUE); + } else if (col == COL_NO || col == COL_MOD + || col == COL_YES) { + change_sym_value(menu, col); + gtk_tree_view_expand_row(view, path, TRUE); + } + } + + return FALSE; +} + +/* Key pressed: update choice */ +gboolean +on_treeview2_key_press_event(GtkWidget * widget, + GdkEventKey * event, gpointer user_data) +{ + GtkTreeView *view = GTK_TREE_VIEW(widget); + GtkTreePath *path; + GtkTreeViewColumn *column; + GtkTreeIter iter; + struct menu *menu; + gint col; + + gtk_tree_view_get_cursor(view, &path, &column); + if (path == NULL) + return FALSE; + + if (event->keyval == GDK_space) { + if (gtk_tree_view_row_expanded(view, path)) + gtk_tree_view_collapse_row(view, path); + else + gtk_tree_view_expand_row(view, path, FALSE); + return TRUE; + } + if (event->keyval == GDK_KP_Enter) { + } + if (widget == tree1_w) + return FALSE; + + gtk_tree_model_get_iter(model2, &iter, path); + gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1); + + if (!strcasecmp(event->string, "n")) + col = COL_NO; + else if (!strcasecmp(event->string, "m")) + col = COL_MOD; + else if (!strcasecmp(event->string, "y")) + col = COL_YES; + else + col = -1; + change_sym_value(menu, col); + + return FALSE; +} + + +/* Row selection changed: update help */ +void +on_treeview2_cursor_changed(GtkTreeView * treeview, gpointer user_data) +{ + GtkTreeSelection *selection; + GtkTreeIter iter; + struct menu *menu; + + selection = gtk_tree_view_get_selection(treeview); + if (gtk_tree_selection_get_selected(selection, &model2, &iter)) { + gtk_tree_model_get(model2, &iter, COL_MENU, &menu, -1); + text_insert_help(menu); + } +} + + +/* User click: display sub-tree in the right frame. */ +gboolean +on_treeview1_button_press_event(GtkWidget * widget, + GdkEventButton * event, gpointer user_data) +{ + GtkTreeView *view = GTK_TREE_VIEW(widget); + GtkTreePath *path; + GtkTreeViewColumn *column; + GtkTreeIter iter; + struct menu *menu; + + gint tx = (gint) event->x; + gint ty = (gint) event->y; + gint cx, cy; + + gtk_tree_view_get_path_at_pos(view, tx, ty, &path, &column, &cx, + &cy); + if (path == NULL) + return FALSE; + + gtk_tree_model_get_iter(model1, &iter, path); + gtk_tree_model_get(model1, &iter, COL_MENU, &menu, -1); + + if (event->type == GDK_2BUTTON_PRESS) { + toggle_sym_value(menu); + current = menu; + display_tree_part(); + } else { + browsed = menu; + display_tree_part(); + } + + gtk_widget_realize(tree2_w); + gtk_tree_view_set_cursor(view, path, NULL, FALSE); + gtk_widget_grab_focus(tree2_w); + + return FALSE; +} + + +/* Fill a row of strings */ +static gchar **fill_row(struct menu *menu) +{ + static gchar *row[COL_NUMBER]; + struct symbol *sym = menu->sym; + const char *def; + int stype; + tristate val; + enum prop_type ptype; + int i; + + for (i = COL_OPTION; i <= COL_COLOR; i++) + g_free(row[i]); + bzero(row, sizeof(row)); + + row[COL_OPTION] = + g_strdup_printf("%s %s", _(menu_get_prompt(menu)), + sym && !sym_has_value(sym) ? "(NEW)" : ""); + + if (opt_mode == OPT_ALL && !menu_is_visible(menu)) + row[COL_COLOR] = g_strdup("DarkGray"); + else if (opt_mode == OPT_PROMPT && + menu_has_prompt(menu) && !menu_is_visible(menu)) + row[COL_COLOR] = g_strdup("DarkGray"); + else + row[COL_COLOR] = g_strdup("Black"); + + ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN; + switch (ptype) { + case P_MENU: + row[COL_PIXBUF] = (gchar *) xpm_menu; + if (view_mode == SINGLE_VIEW) + row[COL_PIXVIS] = GINT_TO_POINTER(TRUE); + row[COL_BTNVIS] = GINT_TO_POINTER(FALSE); + break; + case P_COMMENT: + row[COL_PIXBUF] = (gchar *) xpm_void; + row[COL_PIXVIS] = GINT_TO_POINTER(FALSE); + row[COL_BTNVIS] = GINT_TO_POINTER(FALSE); + break; + default: + row[COL_PIXBUF] = (gchar *) xpm_void; + row[COL_PIXVIS] = GINT_TO_POINTER(FALSE); + row[COL_BTNVIS] = GINT_TO_POINTER(TRUE); + break; + } + + if (!sym) + return row; + row[COL_NAME] = g_strdup(sym->name); + + sym_calc_value(sym); + sym->flags &= ~SYMBOL_CHANGED; + + if (sym_is_choice(sym)) { // parse childs for getting final value + struct menu *child; + struct symbol *def_sym = sym_get_choice_value(sym); + struct menu *def_menu = NULL; + + row[COL_BTNVIS] = GINT_TO_POINTER(FALSE); + + for (child = menu->list; child; child = child->next) { + if (menu_is_visible(child) + && child->sym == def_sym) + def_menu = child; + } + + if (def_menu) + row[COL_VALUE] = + g_strdup(_(menu_get_prompt(def_menu))); + } + if (sym->flags & SYMBOL_CHOICEVAL) + row[COL_BTNRAD] = GINT_TO_POINTER(TRUE); + + stype = sym_get_type(sym); + switch (stype) { + case S_BOOLEAN: + if (GPOINTER_TO_INT(row[COL_PIXVIS]) == FALSE) + row[COL_BTNVIS] = GINT_TO_POINTER(TRUE); + if (sym_is_choice(sym)) + break; + /* fall through */ + case S_TRISTATE: + val = sym_get_tristate_value(sym); + switch (val) { + case no: + row[COL_NO] = g_strdup("N"); + row[COL_VALUE] = g_strdup("N"); + row[COL_BTNACT] = GINT_TO_POINTER(FALSE); + row[COL_BTNINC] = GINT_TO_POINTER(FALSE); + break; + case mod: + row[COL_MOD] = g_strdup("M"); + row[COL_VALUE] = g_strdup("M"); + row[COL_BTNINC] = GINT_TO_POINTER(TRUE); + break; + case yes: + row[COL_YES] = g_strdup("Y"); + row[COL_VALUE] = g_strdup("Y"); + row[COL_BTNACT] = GINT_TO_POINTER(TRUE); + row[COL_BTNINC] = GINT_TO_POINTER(FALSE); + break; + } + + if (val != no && sym_tristate_within_range(sym, no)) + row[COL_NO] = g_strdup("_"); + if (val != mod && sym_tristate_within_range(sym, mod)) + row[COL_MOD] = g_strdup("_"); + if (val != yes && sym_tristate_within_range(sym, yes)) + row[COL_YES] = g_strdup("_"); + break; + case S_INT: + case S_HEX: + case S_STRING: + def = sym_get_string_value(sym); + row[COL_VALUE] = g_strdup(def); + row[COL_EDIT] = GINT_TO_POINTER(TRUE); + row[COL_BTNVIS] = GINT_TO_POINTER(FALSE); + break; + } + + return row; +} + + +/* Set the node content with a row of strings */ +static void set_node(GtkTreeIter * node, struct menu *menu, gchar ** row) +{ + GdkColor color; + gboolean success; + GdkPixbuf *pix; + + pix = gdk_pixbuf_new_from_xpm_data((const char **) + row[COL_PIXBUF]); + + gdk_color_parse(row[COL_COLOR], &color); + gdk_colormap_alloc_colors(gdk_colormap_get_system(), &color, 1, + FALSE, FALSE, &success); + + gtk_tree_store_set(tree, node, + COL_OPTION, row[COL_OPTION], + COL_NAME, row[COL_NAME], + COL_NO, row[COL_NO], + COL_MOD, row[COL_MOD], + COL_YES, row[COL_YES], + COL_VALUE, row[COL_VALUE], + COL_MENU, (gpointer) menu, + COL_COLOR, &color, + COL_EDIT, GPOINTER_TO_INT(row[COL_EDIT]), + COL_PIXBUF, pix, + COL_PIXVIS, GPOINTER_TO_INT(row[COL_PIXVIS]), + COL_BTNVIS, GPOINTER_TO_INT(row[COL_BTNVIS]), + COL_BTNACT, GPOINTER_TO_INT(row[COL_BTNACT]), + COL_BTNINC, GPOINTER_TO_INT(row[COL_BTNINC]), + COL_BTNRAD, GPOINTER_TO_INT(row[COL_BTNRAD]), + -1); + + g_object_unref(pix); +} + + +/* Add a node to the tree */ +static void place_node(struct menu *menu, char **row) +{ + GtkTreeIter *parent = parents[indent - 1]; + GtkTreeIter *node = parents[indent]; + + gtk_tree_store_append(tree, node, parent); + set_node(node, menu, row); +} + + +/* Find a node in the GTK+ tree */ +static GtkTreeIter found; + +/* + * Find a menu in the GtkTree starting at parent. + */ +GtkTreeIter *gtktree_iter_find_node(GtkTreeIter * parent, + struct menu *tofind) +{ + GtkTreeIter iter; + GtkTreeIter *child = &iter; + gboolean valid; + GtkTreeIter *ret; + + valid = gtk_tree_model_iter_children(model2, child, parent); + while (valid) { + struct menu *menu; + + gtk_tree_model_get(model2, child, 6, &menu, -1); + + if (menu == tofind) { + memcpy(&found, child, sizeof(GtkTreeIter)); + return &found; + } + + ret = gtktree_iter_find_node(child, tofind); + if (ret) + return ret; + + valid = gtk_tree_model_iter_next(model2, child); + } + + return NULL; +} + + +/* + * Update the tree by adding/removing entries + * Does not change other nodes + */ +static void update_tree(struct menu *src, GtkTreeIter * dst) +{ + struct menu *child1; + GtkTreeIter iter, tmp; + GtkTreeIter *child2 = &iter; + gboolean valid; + GtkTreeIter *sibling; + struct symbol *sym; + struct menu *menu1, *menu2; + + if (src == &rootmenu) + indent = 1; + + valid = gtk_tree_model_iter_children(model2, child2, dst); + for (child1 = src->list; child1; child1 = child1->next) { + + sym = child1->sym; + + reparse: + menu1 = child1; + if (valid) + gtk_tree_model_get(model2, child2, COL_MENU, + &menu2, -1); + else + menu2 = NULL; // force adding of a first child + +#ifdef DEBUG + printf("%*c%s | %s\n", indent, ' ', + menu1 ? menu_get_prompt(menu1) : "nil", + menu2 ? menu_get_prompt(menu2) : "nil"); +#endif + + if ((opt_mode == OPT_NORMAL && !menu_is_visible(child1)) || + (opt_mode == OPT_PROMPT && !menu_has_prompt(child1)) || + (opt_mode == OPT_ALL && !menu_get_prompt(child1))) { + + /* remove node */ + if (gtktree_iter_find_node(dst, menu1) != NULL) { + memcpy(&tmp, child2, sizeof(GtkTreeIter)); + valid = gtk_tree_model_iter_next(model2, + child2); + gtk_tree_store_remove(tree2, &tmp); + if (!valid) + return; /* next parent */ + else + goto reparse; /* next child */ + } else + continue; + } + + if (menu1 != menu2) { + if (gtktree_iter_find_node(dst, menu1) == NULL) { // add node + if (!valid && !menu2) + sibling = NULL; + else + sibling = child2; + gtk_tree_store_insert_before(tree2, + child2, + dst, sibling); + set_node(child2, menu1, fill_row(menu1)); + if (menu2 == NULL) + valid = TRUE; + } else { // remove node + memcpy(&tmp, child2, sizeof(GtkTreeIter)); + valid = gtk_tree_model_iter_next(model2, + child2); + gtk_tree_store_remove(tree2, &tmp); + if (!valid) + return; // next parent + else + goto reparse; // next child + } + } else if (sym && (sym->flags & SYMBOL_CHANGED)) { + set_node(child2, menu1, fill_row(menu1)); + } + + indent++; + update_tree(child1, child2); + indent--; + + valid = gtk_tree_model_iter_next(model2, child2); + } +} + + +/* Display the whole tree (single/split/full view) */ +static void display_tree(struct menu *menu) +{ + struct symbol *sym; + struct property *prop; + struct menu *child; + enum prop_type ptype; + + if (menu == &rootmenu) { + indent = 1; + current = &rootmenu; + } + + for (child = menu->list; child; child = child->next) { + prop = child->prompt; + sym = child->sym; + ptype = prop ? prop->type : P_UNKNOWN; + + if (sym) + sym->flags &= ~SYMBOL_CHANGED; + + if ((view_mode == SPLIT_VIEW) + && !(child->flags & MENU_ROOT) && (tree == tree1)) + continue; + + if ((view_mode == SPLIT_VIEW) && (child->flags & MENU_ROOT) + && (tree == tree2)) + continue; + + if ((opt_mode == OPT_NORMAL && menu_is_visible(child)) || + (opt_mode == OPT_PROMPT && menu_has_prompt(child)) || + (opt_mode == OPT_ALL && menu_get_prompt(child))) + place_node(child, fill_row(child)); +#ifdef DEBUG + printf("%*c%s: ", indent, ' ', menu_get_prompt(child)); + printf("%s", child->flags & MENU_ROOT ? "rootmenu | " : ""); + printf("%s", prop_get_type_name(ptype)); + printf(" | "); + if (sym) { + printf("%s", sym_type_name(sym->type)); + printf(" | "); + printf("%s", dbg_sym_flags(sym->flags)); + printf("\n"); + } else + printf("\n"); +#endif + if ((view_mode != FULL_VIEW) && (ptype == P_MENU) + && (tree == tree2)) + continue; +/* + if (((menu != &rootmenu) && !(menu->flags & MENU_ROOT)) + || (view_mode == FULL_VIEW) + || (view_mode == SPLIT_VIEW))*/ + + /* Change paned position if the view is not in 'split mode' */ + if (view_mode == SINGLE_VIEW || view_mode == FULL_VIEW) { + gtk_paned_set_position(GTK_PANED(hpaned), 0); + } + + if (((view_mode == SINGLE_VIEW) && (menu->flags & MENU_ROOT)) + || (view_mode == FULL_VIEW) + || (view_mode == SPLIT_VIEW)) { + indent++; + display_tree(child); + indent--; + } + } +} + +/* Display a part of the tree starting at current node (single/split view) */ +static void display_tree_part(void) +{ + if (tree2) + gtk_tree_store_clear(tree2); + if (view_mode == SINGLE_VIEW) + display_tree(current); + else if (view_mode == SPLIT_VIEW) + display_tree(browsed); + gtk_tree_view_expand_all(GTK_TREE_VIEW(tree2_w)); +} + +/* Display the list in the left frame (split view) */ +static void display_list(void) +{ + if (tree1) + gtk_tree_store_clear(tree1); + + tree = tree1; + display_tree(&rootmenu); + gtk_tree_view_expand_all(GTK_TREE_VIEW(tree1_w)); + tree = tree2; +} + +void fixup_rootmenu(struct menu *menu) +{ + struct menu *child; + static int menu_cnt = 0; + + menu->flags |= MENU_ROOT; + for (child = menu->list; child; child = child->next) { + if (child->prompt && child->prompt->type == P_MENU) { + menu_cnt++; + fixup_rootmenu(child); + menu_cnt--; + } else if (!menu_cnt) + fixup_rootmenu(child); + } +} + + +/* Main */ +int main(int ac, char *av[]) +{ + const char *name; + char *env; + gchar *glade_file; + + bindtextdomain(PACKAGE, LOCALEDIR); + bind_textdomain_codeset(PACKAGE, "UTF-8"); + textdomain(PACKAGE); + + /* GTK stuffs */ + gtk_set_locale(); + gtk_init(&ac, &av); + glade_init(); + + //add_pixmap_directory (PACKAGE_DATA_DIR "/" PACKAGE "/pixmaps"); + //add_pixmap_directory (PACKAGE_SOURCE_DIR "/pixmaps"); + + /* Determine GUI path */ + env = getenv(SRCTREE); + if (env) + glade_file = g_strconcat(env, "/tool/kconfig/scripts/kconfig/gconf.glade", NULL); + else if (av[0][0] == '/') + glade_file = g_strconcat(av[0], ".glade", NULL); + else + glade_file = g_strconcat(g_get_current_dir(), "/", av[0], ".glade", NULL); + + /* Conf stuffs */ + if (ac > 1 && av[1][0] == '-') { + switch (av[1][1]) { + case 'a': + //showAll = 1; + break; + case 'h': + case '?': + printf("%s \n", av[0]); + exit(0); + } + name = av[2]; + } else + name = av[1]; + + conf_parse(name); + fixup_rootmenu(&rootmenu); + conf_read(NULL); + + /* Load the interface and connect signals */ + init_main_window(glade_file); + init_tree_model(); + init_left_tree(); + init_right_tree(); + + switch (view_mode) { + case SINGLE_VIEW: + display_tree_part(); + break; + case SPLIT_VIEW: + display_list(); + break; + case FULL_VIEW: + display_tree(&rootmenu); + break; + } + + gtk_main(); + + return 0; +} + +static void conf_changed(void) +{ + bool changed = conf_get_changed(); + gtk_widget_set_sensitive(save_btn, changed); + gtk_widget_set_sensitive(save_menu_item, changed); +} diff --git a/l4/tool/kconfig/scripts/kconfig/gconf.glade b/l4/tool/kconfig/scripts/kconfig/gconf.glade new file mode 100644 index 00000000..aa483cb3 --- /dev/null +++ b/l4/tool/kconfig/scripts/kconfig/gconf.glade @@ -0,0 +1,661 @@ + + + + + + True + Gtk Kernel Configurator + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_NONE + False + 640 + 480 + True + False + True + False + False + GDK_WINDOW_TYPE_HINT_NORMAL + GDK_GRAVITY_NORTH_WEST + + + + + + + True + False + 0 + + + + True + + + + True + _File + True + + + + + + + True + Load a config file + _Load + True + + + + + + True + gtk-open + 1 + 0.5 + 0.5 + 0 + 0 + + + + + + + + True + Save the config in .config + _Save + True + + + + + + True + gtk-save + 1 + 0.5 + 0.5 + 0 + 0 + + + + + + + + True + Save the config in a file + Save _as + True + + + + + True + gtk-save-as + 1 + 0.5 + 0.5 + 0 + 0 + + + + + + + + True + + + + + + True + _Quit + True + + + + + + True + gtk-quit + 1 + 0.5 + 0.5 + 0 + 0 + + + + + + + + + + + + True + _Options + True + + + + + + + True + Show name + Show _name + True + False + + + + + + + True + Show range (Y/M/N) + Show _range + True + False + + + + + + + True + Show value of the option + Show _data + True + False + + + + + + + True + + + + + + True + Show normal options + Show normal options + True + True + + + + + + + True + Show all options + Show all _options + True + False + set_option_mode1 + + + + + + + True + Show all options with prompts + Show all prompt options + True + False + set_option_mode1 + + + + + + + + + + + + True + _Help + True + + + + + + + True + _Introduction + True + + + + + + True + gtk-dialog-question + 1 + 0.5 + 0.5 + 0 + 0 + + + + + + + + True + _About + True + + + + + + True + gtk-properties + 1 + 0.5 + 0.5 + 0 + 0 + + + + + + + + True + _License + True + + + + + True + gtk-justify-fill + 1 + 0.5 + 0.5 + 0 + 0 + + + + + + + + + + + 0 + False + False + + + + + + True + GTK_SHADOW_OUT + GTK_POS_LEFT + GTK_POS_TOP + + + + True + GTK_ORIENTATION_HORIZONTAL + GTK_TOOLBAR_BOTH + True + True + + + + True + Goes up of one level (single view) + Back + True + gtk-undo + True + True + False + + + + False + True + + + + + + True + True + True + False + + + + True + + + + + False + False + + + + + + True + Load a config file + Load + True + gtk-open + True + True + False + + + + False + True + + + + + + True + Save a config file + Save + True + gtk-save + True + True + False + + + + False + True + + + + + + True + True + True + False + + + + True + + + + + False + False + + + + + + True + Single view + Single + True + gtk-missing-image + True + True + False + + + + False + True + + + + + + True + Split view + Split + True + gtk-missing-image + True + True + False + + + + False + True + + + + + + True + Full view + Full + True + gtk-missing-image + True + True + False + + + + False + True + + + + + + True + True + True + False + + + + True + + + + + False + False + + + + + + True + Collapse the whole tree in the right frame + Collapse + True + gtk-remove + True + True + False + + + + False + True + + + + + + True + Expand the whole tree in the right frame + Expand + True + gtk-add + True + True + False + + + + False + True + + + + + + + 0 + False + False + + + + + + 1 + True + True + 0 + + + + True + GTK_POLICY_AUTOMATIC + GTK_POLICY_AUTOMATIC + GTK_SHADOW_IN + GTK_CORNER_TOP_LEFT + + + + True + True + True + False + False + False + + + + + + + + True + False + + + + + + True + True + 0 + + + + True + GTK_POLICY_AUTOMATIC + GTK_POLICY_AUTOMATIC + GTK_SHADOW_IN + GTK_CORNER_TOP_LEFT + + + + True + True + True + True + False + False + False + + + + + + + + True + False + + + + + + True + GTK_POLICY_NEVER + GTK_POLICY_AUTOMATIC + GTK_SHADOW_IN + GTK_CORNER_TOP_LEFT + + + + True + True + False + False + True + GTK_JUSTIFY_LEFT + GTK_WRAP_WORD + True + 0 + 0 + 0 + 0 + 0 + 0 + Sorry, no help available for this option yet. + + + + + True + True + + + + + True + True + + + + + 0 + True + True + + + + + + + diff --git a/l4/tool/kconfig/scripts/kconfig/images.c b/l4/tool/kconfig/scripts/kconfig/images.c new file mode 100644 index 00000000..d4f84bd4 --- /dev/null +++ b/l4/tool/kconfig/scripts/kconfig/images.c @@ -0,0 +1,326 @@ +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +static const char *xpm_load[] = { +"22 22 5 1", +". c None", +"# c #000000", +"c c #838100", +"a c #ffff00", +"b c #ffffff", +"......................", +"......................", +"......................", +"............####....#.", +"...........#....##.##.", +"..................###.", +".................####.", +".####...........#####.", +"#abab##########.......", +"#babababababab#.......", +"#ababababababa#.......", +"#babababababab#.......", +"#ababab###############", +"#babab##cccccccccccc##", +"#abab##cccccccccccc##.", +"#bab##cccccccccccc##..", +"#ab##cccccccccccc##...", +"#b##cccccccccccc##....", +"###cccccccccccc##.....", +"##cccccccccccc##......", +"###############.......", +"......................"}; + +static const char *xpm_save[] = { +"22 22 5 1", +". c None", +"# c #000000", +"a c #838100", +"b c #c5c2c5", +"c c #cdb6d5", +"......................", +".####################.", +".#aa#bbbbbbbbbbbb#bb#.", +".#aa#bbbbbbbbbbbb#bb#.", +".#aa#bbbbbbbbbcbb####.", +".#aa#bbbccbbbbbbb#aa#.", +".#aa#bbbccbbbbbbb#aa#.", +".#aa#bbbbbbbbbbbb#aa#.", +".#aa#bbbbbbbbbbbb#aa#.", +".#aa#bbbbbbbbbbbb#aa#.", +".#aa#bbbbbbbbbbbb#aa#.", +".#aaa############aaa#.", +".#aaaaaaaaaaaaaaaaaa#.", +".#aaaaaaaaaaaaaaaaaa#.", +".#aaa#############aa#.", +".#aaa#########bbb#aa#.", +".#aaa#########bbb#aa#.", +".#aaa#########bbb#aa#.", +".#aaa#########bbb#aa#.", +".#aaa#########bbb#aa#.", +"..##################..", +"......................"}; + +static const char *xpm_back[] = { +"22 22 3 1", +". c None", +"# c #000083", +"a c #838183", +"......................", +"......................", +"......................", +"......................", +"......................", +"...........######a....", +"..#......##########...", +"..##...####......##a..", +"..###.###.........##..", +"..######..........##..", +"..#####...........##..", +"..######..........##..", +"..#######.........##..", +"..########.......##a..", +"...............a###...", +"...............###....", +"......................", +"......................", +"......................", +"......................", +"......................", +"......................"}; + +static const char *xpm_tree_view[] = { +"22 22 2 1", +". c None", +"# c #000000", +"......................", +"......................", +"......#...............", +"......#...............", +"......#...............", +"......#...............", +"......#...............", +"......########........", +"......#...............", +"......#...............", +"......#...............", +"......#...............", +"......#...............", +"......########........", +"......#...............", +"......#...............", +"......#...............", +"......#...............", +"......#...............", +"......########........", +"......................", +"......................"}; + +static const char *xpm_single_view[] = { +"22 22 2 1", +". c None", +"# c #000000", +"......................", +"......................", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"..........#...........", +"......................", +"......................"}; + +static const char *xpm_split_view[] = { +"22 22 2 1", +". c None", +"# c #000000", +"......................", +"......................", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......#......#........", +"......................", +"......................"}; + +static const char *xpm_symbol_no[] = { +"12 12 2 1", +" c white", +". c black", +" ", +" .......... ", +" . . ", +" . . ", +" . . ", +" . . ", +" . . ", +" . . ", +" . . ", +" . . ", +" .......... ", +" "}; + +static const char *xpm_symbol_mod[] = { +"12 12 2 1", +" c white", +". c black", +" ", +" .......... ", +" . . ", +" . . ", +" . .. . ", +" . .... . ", +" . .... . ", +" . .. . ", +" . . ", +" . . ", +" .......... ", +" "}; + +static const char *xpm_symbol_yes[] = { +"12 12 2 1", +" c white", +". c black", +" ", +" .......... ", +" . . ", +" . . ", +" . . . ", +" . .. . ", +" . . .. . ", +" . .... . ", +" . .. . ", +" . . ", +" .......... ", +" "}; + +static const char *xpm_choice_no[] = { +"12 12 2 1", +" c white", +". c black", +" ", +" .... ", +" .. .. ", +" . . ", +" . . ", +" . . ", +" . . ", +" . . ", +" . . ", +" .. .. ", +" .... ", +" "}; + +static const char *xpm_choice_yes[] = { +"12 12 2 1", +" c white", +". c black", +" ", +" .... ", +" .. .. ", +" . . ", +" . .. . ", +" . .... . ", +" . .... . ", +" . .. . ", +" . . ", +" .. .. ", +" .... ", +" "}; + +static const char *xpm_menu[] = { +"12 12 2 1", +" c white", +". c black", +" ", +" .......... ", +" . . ", +" . .. . ", +" . .... . ", +" . ...... . ", +" . ...... . ", +" . .... . ", +" . .. . ", +" . . ", +" .......... ", +" "}; + +static const char *xpm_menu_inv[] = { +"12 12 2 1", +" c white", +". c black", +" ", +" .......... ", +" .......... ", +" .. ...... ", +" .. .... ", +" .. .. ", +" .. .. ", +" .. .... ", +" .. ...... ", +" .......... ", +" .......... ", +" "}; + +static const char *xpm_menuback[] = { +"12 12 2 1", +" c white", +". c black", +" ", +" .......... ", +" . . ", +" . .. . ", +" . .... . ", +" . ...... . ", +" . ...... . ", +" . .... . ", +" . .. . ", +" . . ", +" .......... ", +" "}; + +static const char *xpm_void[] = { +"12 12 2 1", +" c white", +". c black", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" "}; diff --git a/l4/tool/kconfig/scripts/kconfig/kxgettext.c b/l4/tool/kconfig/scripts/kconfig/kxgettext.c new file mode 100644 index 00000000..2858738b --- /dev/null +++ b/l4/tool/kconfig/scripts/kconfig/kxgettext.c @@ -0,0 +1,235 @@ +/* + * Arnaldo Carvalho de Melo , 2005 + * + * Released under the terms of the GNU GPL v2.0 + */ + +#include +#include + +#include "lkc.h" + +static char *escape(const char* text, char *bf, int len) +{ + char *bfp = bf; + int multiline = strchr(text, '\n') != NULL; + int eol = 0; + int textlen = strlen(text); + + if ((textlen > 0) && (text[textlen-1] == '\n')) + eol = 1; + + *bfp++ = '"'; + --len; + + if (multiline) { + *bfp++ = '"'; + *bfp++ = '\n'; + *bfp++ = '"'; + len -= 3; + } + + while (*text != '\0' && len > 1) { + if (*text == '"') + *bfp++ = '\\'; + else if (*text == '\n') { + *bfp++ = '\\'; + *bfp++ = 'n'; + *bfp++ = '"'; + *bfp++ = '\n'; + *bfp++ = '"'; + len -= 5; + ++text; + goto next; + } + else if (*text == '\\') { + *bfp++ = '\\'; + len--; + } + *bfp++ = *text++; +next: + --len; + } + + if (multiline && eol) + bfp -= 3; + + *bfp++ = '"'; + *bfp = '\0'; + + return bf; +} + +struct file_line { + struct file_line *next; + const char *file; + int lineno; +}; + +static struct file_line *file_line__new(const char *file, int lineno) +{ + struct file_line *self = malloc(sizeof(*self)); + + if (self == NULL) + goto out; + + self->file = file; + self->lineno = lineno; + self->next = NULL; +out: + return self; +} + +struct message { + const char *msg; + const char *option; + struct message *next; + struct file_line *files; +}; + +static struct message *message__list; + +static struct message *message__new(const char *msg, char *option, + const char *file, int lineno) +{ + struct message *self = malloc(sizeof(*self)); + + if (self == NULL) + goto out; + + self->files = file_line__new(file, lineno); + if (self->files == NULL) + goto out_fail; + + self->msg = strdup(msg); + if (self->msg == NULL) + goto out_fail_msg; + + self->option = option; + self->next = NULL; +out: + return self; +out_fail_msg: + free(self->files); +out_fail: + free(self); + self = NULL; + goto out; +} + +static struct message *mesage__find(const char *msg) +{ + struct message *m = message__list; + + while (m != NULL) { + if (strcmp(m->msg, msg) == 0) + break; + m = m->next; + } + + return m; +} + +static int message__add_file_line(struct message *self, const char *file, + int lineno) +{ + int rc = -1; + struct file_line *fl = file_line__new(file, lineno); + + if (fl == NULL) + goto out; + + fl->next = self->files; + self->files = fl; + rc = 0; +out: + return rc; +} + +static int message__add(const char *msg, char *option, const char *file, + int lineno) +{ + int rc = 0; + char bf[16384]; + char *escaped = escape(msg, bf, sizeof(bf)); + struct message *m = mesage__find(escaped); + + if (m != NULL) + rc = message__add_file_line(m, file, lineno); + else { + m = message__new(escaped, option, file, lineno); + + if (m != NULL) { + m->next = message__list; + message__list = m; + } else + rc = -1; + } + return rc; +} + +static void menu_build_message_list(struct menu *menu) +{ + struct menu *child; + + message__add(menu_get_prompt(menu), NULL, + menu->file == NULL ? "Root Menu" : menu->file->name, + menu->lineno); + + if (menu->sym != NULL && menu_has_help(menu)) + message__add(menu_get_help(menu), menu->sym->name, + menu->file == NULL ? "Root Menu" : menu->file->name, + menu->lineno); + + for (child = menu->list; child != NULL; child = child->next) + if (child->prompt != NULL) + menu_build_message_list(child); +} + +static void message__print_file_lineno(struct message *self) +{ + struct file_line *fl = self->files; + + putchar('\n'); + if (self->option != NULL) + printf("# %s:00000\n", self->option); + + printf("#: %s:%d", fl->file, fl->lineno); + fl = fl->next; + + while (fl != NULL) { + printf(", %s:%d", fl->file, fl->lineno); + fl = fl->next; + } + + putchar('\n'); +} + +static void message__print_gettext_msgid_msgstr(struct message *self) +{ + message__print_file_lineno(self); + + printf("msgid %s\n" + "msgstr \"\"\n", self->msg); +} + +static void menu__xgettext(void) +{ + struct message *m = message__list; + + while (m != NULL) { + /* skip empty lines ("") */ + if (strlen(m->msg) > sizeof("\"\"")) + message__print_gettext_msgid_msgstr(m); + m = m->next; + } +} + +int main(int ac, char **av) +{ + conf_parse(av[1]); + + menu_build_message_list(menu_get_root_menu(NULL)); + menu__xgettext(); + return 0; +} diff --git a/l4/tool/kconfig/scripts/kconfig/lkc.h b/l4/tool/kconfig/scripts/kconfig/lkc.h new file mode 100644 index 00000000..f7032ff7 --- /dev/null +++ b/l4/tool/kconfig/scripts/kconfig/lkc.h @@ -0,0 +1,190 @@ +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +#ifndef LKC_H +#define LKC_H + +#include "expr.h" + +#ifndef KBUILD_NO_NLS +# include +#else +static inline const char *gettext(const char *txt) { return txt; } +static inline void textdomain(const char *domainname) {} +static inline void bindtextdomain(const char *name, const char *dir) {} +static inline char *bind_textdomain_codeset(const char *dn, char *c) { return c; } +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#define P(name,type,arg) extern type name arg +#include "lkc_proto.h" +#undef P + +#define SRCTREE "l4re_srcdir" + +#ifndef PACKAGE +#define PACKAGE "linux" +#endif + +#define LOCALEDIR "/usr/share/locale" + +#define _(text) gettext(text) +#define N_(text) (text) + +#ifndef CONFIG_ +#define CONFIG_ "CONFIG_" +#endif + +#define TF_COMMAND 0x0001 +#define TF_PARAM 0x0002 +#define TF_OPTION 0x0004 + +enum conf_def_mode { + def_default, + def_yes, + def_mod, + def_no, + def_random +}; + +#define T_OPT_MODULES 1 +#define T_OPT_DEFCONFIG_LIST 2 +#define T_OPT_ENV 3 + +struct kconf_id { + int name; + int token; + unsigned int flags; + enum symbol_type stype; +}; + +extern int zconfdebug; + +int zconfparse(void); +void zconfdump(FILE *out); +void zconf_starthelp(void); +FILE *zconf_fopen(const char *name); +void zconf_initscan(const char *name); +void zconf_nextfile(const char *name); +int zconf_lineno(void); +const char *zconf_curname(void); + +/* confdata.c */ +const char *conf_get_configname(void); +const char *conf_get_autoconfig_name(void); +char *conf_get_default_confname(void); +void sym_set_change_count(int count); +void sym_add_change_count(int count); +void conf_set_all_new_symbols(enum conf_def_mode mode); + +struct conf_printer { + void (*print_symbol)(FILE *, struct symbol *, const char *, void *); + void (*print_comment)(FILE *, const char *, void *); +}; + +/* confdata.c and expr.c */ +static inline void xfwrite(const void *str, size_t len, size_t count, FILE *out) +{ + assert(len != 0); + + if (fwrite(str, len, count, out) != count) + fprintf(stderr, "Error in writing or end of file.\n"); +} + +/* menu.c */ +void _menu_init(void); +void menu_warn(struct menu *menu, const char *fmt, ...); +struct menu *menu_add_menu(void); +void menu_end_menu(void); +void menu_add_entry(struct symbol *sym); +void menu_end_entry(void); +void menu_add_dep(struct expr *dep); +void menu_add_visibility(struct expr *dep); +struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *expr, struct expr *dep); +struct property *menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep); +void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep); +void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep); +void menu_add_option(int token, char *arg); +void menu_finalize(struct menu *parent); +void menu_set_type(int type); + +/* util.c */ +struct file *file_lookup(const char *name); +int file_write_dep(const char *name); + +struct gstr { + size_t len; + char *s; + /* + * when max_width is not zero long lines in string s (if any) get + * wrapped not to exceed the max_width value + */ + int max_width; +}; +struct gstr str_new(void); +struct gstr str_assign(const char *s); +void str_free(struct gstr *gs); +void str_append(struct gstr *gs, const char *s); +void str_printf(struct gstr *gs, const char *fmt, ...); +const char *str_get(struct gstr *gs); + +/* symbol.c */ +extern struct expr *sym_env_list; + +void sym_init(void); +void sym_clear_all_valid(void); +void sym_set_all_changed(void); +void sym_set_changed(struct symbol *sym); +struct symbol *sym_choice_default(struct symbol *sym); +const char *sym_get_string_default(struct symbol *sym); +struct symbol *sym_check_deps(struct symbol *sym); +struct property *prop_alloc(enum prop_type type, struct symbol *sym); +struct symbol *prop_get_symbol(struct property *prop); +struct property *sym_get_env_prop(struct symbol *sym); + +static inline tristate sym_get_tristate_value(struct symbol *sym) +{ + return sym->curr.tri; +} + + +static inline struct symbol *sym_get_choice_value(struct symbol *sym) +{ + return (struct symbol *)sym->curr.val; +} + +static inline bool sym_set_choice_value(struct symbol *ch, struct symbol *chval) +{ + return sym_set_tristate_value(chval, yes); +} + +static inline bool sym_is_choice(struct symbol *sym) +{ + return sym->flags & SYMBOL_CHOICE ? true : false; +} + +static inline bool sym_is_choice_value(struct symbol *sym) +{ + return sym->flags & SYMBOL_CHOICEVAL ? true : false; +} + +static inline bool sym_is_optional(struct symbol *sym) +{ + return sym->flags & SYMBOL_OPTIONAL ? true : false; +} + +static inline bool sym_has_value(struct symbol *sym) +{ + return sym->flags & SYMBOL_DEF_USER ? true : false; +} + +#ifdef __cplusplus +} +#endif + +#endif /* LKC_H */ diff --git a/l4/tool/kconfig/scripts/kconfig/lkc_proto.h b/l4/tool/kconfig/scripts/kconfig/lkc_proto.h new file mode 100644 index 00000000..47fe9c34 --- /dev/null +++ b/l4/tool/kconfig/scripts/kconfig/lkc_proto.h @@ -0,0 +1,54 @@ +#include + +/* confdata.c */ +P(conf_parse,void,(const char *name)); +P(conf_read,int,(const char *name)); +P(conf_read_simple,int,(const char *name, int)); +P(conf_write_defconfig,int,(const char *name)); +P(conf_write,int,(const char *name)); +P(conf_write_autoconf,int,(void)); +P(conf_get_changed,bool,(void)); +P(conf_set_changed_callback, void,(void (*fn)(void))); +P(conf_set_message_callback, void,(void (*fn)(const char *fmt, va_list ap))); + +/* menu.c */ +P(rootmenu,struct menu,); + +P(menu_is_visible, bool, (struct menu *menu)); +P(menu_has_prompt, bool, (struct menu *menu)); +P(menu_get_prompt,const char *,(struct menu *menu)); +P(menu_get_root_menu,struct menu *,(struct menu *menu)); +P(menu_get_parent_menu,struct menu *,(struct menu *menu)); +P(menu_has_help,bool,(struct menu *menu)); +P(menu_get_help,const char *,(struct menu *menu)); +P(get_symbol_str, void, (struct gstr *r, struct symbol *sym)); +P(get_relations_str, struct gstr, (struct symbol **sym_arr)); +P(menu_get_ext_help,void,(struct menu *menu, struct gstr *help)); + +/* symbol.c */ +P(symbol_hash,struct symbol *,[SYMBOL_HASHSIZE]); + +P(sym_lookup,struct symbol *,(const char *name, int flags)); +P(sym_find,struct symbol *,(const char *name)); +P(sym_expand_string_value,const char *,(const char *in)); +P(sym_escape_string_value, const char *,(const char *in)); +P(sym_re_search,struct symbol **,(const char *pattern)); +P(sym_type_name,const char *,(enum symbol_type type)); +P(sym_calc_value,void,(struct symbol *sym)); +P(sym_get_type,enum symbol_type,(struct symbol *sym)); +P(sym_tristate_within_range,bool,(struct symbol *sym,tristate tri)); +P(sym_set_tristate_value,bool,(struct symbol *sym,tristate tri)); +P(sym_toggle_tristate_value,tristate,(struct symbol *sym)); +P(sym_string_valid,bool,(struct symbol *sym, const char *newval)); +P(sym_string_within_range,bool,(struct symbol *sym, const char *str)); +P(sym_set_string_value,bool,(struct symbol *sym, const char *newval)); +P(sym_is_changable,bool,(struct symbol *sym)); +P(sym_get_choice_prop,struct property *,(struct symbol *sym)); +P(sym_get_default_prop,struct property *,(struct symbol *sym)); +P(sym_get_string_value,const char *,(struct symbol *sym)); + +P(prop_get_type_name,const char *,(enum prop_type type)); + +/* expr.c */ +P(expr_compare_type,int,(enum expr_type t1, enum expr_type t2)); +P(expr_print,void,(struct expr *e, void (*fn)(void *, struct symbol *, const char *), void *data, int prevtoken)); diff --git a/l4/tool/kconfig/scripts/kconfig/lxdialog/.gitignore b/l4/tool/kconfig/scripts/kconfig/lxdialog/.gitignore new file mode 100644 index 00000000..90b08ff0 --- /dev/null +++ b/l4/tool/kconfig/scripts/kconfig/lxdialog/.gitignore @@ -0,0 +1,4 @@ +# +# Generated files +# +lxdialog diff --git a/l4/tool/kconfig/scripts/kconfig/lxdialog/BIG.FAT.WARNING b/l4/tool/kconfig/scripts/kconfig/lxdialog/BIG.FAT.WARNING new file mode 100644 index 00000000..a8999d82 --- /dev/null +++ b/l4/tool/kconfig/scripts/kconfig/lxdialog/BIG.FAT.WARNING @@ -0,0 +1,4 @@ +This is NOT the official version of dialog. This version has been +significantly modified from the original. It is for use by the Linux +kernel configuration script. Please do not bother Savio Lam with +questions about this program. diff --git a/l4/tool/kconfig/scripts/kconfig/lxdialog/check-lxdialog.sh b/l4/tool/kconfig/scripts/kconfig/lxdialog/check-lxdialog.sh new file mode 100644 index 00000000..82cc3a85 --- /dev/null +++ b/l4/tool/kconfig/scripts/kconfig/lxdialog/check-lxdialog.sh @@ -0,0 +1,84 @@ +#!/bin/sh +# Check ncurses compatibility + +# What library to link +ldflags() +{ + for ext in so a dylib ; do + for lib in ncursesw ncurses curses ; do + $cc -print-file-name=lib${lib}.${ext} | grep -q / + if [ $? -eq 0 ]; then + echo "-l${lib}" + exit + fi + done + done + exit 1 +} + +# Where is ncurses.h? +ccflags() +{ + if [ -f /usr/include/ncurses/ncurses.h ]; then + echo '-I/usr/include/ncurses -DCURSES_LOC=""' + elif [ -f /usr/include/ncurses/curses.h ]; then + echo '-I/usr/include/ncurses -DCURSES_LOC=""' + elif [ -f /usr/include/ncursesw/curses.h ]; then + echo '-I/usr/include/ncursesw -DCURSES_LOC=""' + elif [ -f /usr/include/ncurses.h ]; then + echo '-DCURSES_LOC=""' + else + echo '-DCURSES_LOC=""' + fi +} + +# Temp file, try to clean up after us +tmp=.lxdialog.tmp +trap "rm -f $tmp" 0 1 2 3 15 + +# Check if we can link to ncurses +check() { + $cc -xc - -o $tmp 2>/dev/null <<'EOF' +#include CURSES_LOC +main() {} +EOF + if [ $? != 0 ]; then + echo " *** Unable to find the ncurses libraries or the" 1>&2 + echo " *** required header files." 1>&2 + echo " *** 'make menuconfig' requires the ncurses libraries." 1>&2 + echo " *** " 1>&2 + echo " *** Install ncurses (ncurses-devel) and try again." 1>&2 + echo " *** " 1>&2 + exit 1 + fi +} + +usage() { + printf "Usage: $0 [-check compiler options|-ccflags|-ldflags compiler options]\n" +} + +if [ $# -eq 0 ]; then + usage + exit 1 +fi + +cc="" +case "$1" in + "-check") + shift + cc="$@" + check + ;; + "-ccflags") + ccflags + ;; + "-ldflags") + shift + cc="$@" + ldflags + ;; + "*") + usage + exit 1 + ;; +esac diff --git a/l4/tool/kconfig/scripts/kconfig/lxdialog/checklist.c b/l4/tool/kconfig/scripts/kconfig/lxdialog/checklist.c new file mode 100644 index 00000000..a2eb80fb --- /dev/null +++ b/l4/tool/kconfig/scripts/kconfig/lxdialog/checklist.c @@ -0,0 +1,332 @@ +/* + * checklist.c -- implements the checklist box + * + * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) + * Stuart Herbert - S.Herbert@sheffield.ac.uk: radiolist extension + * Alessandro Rubini - rubini@ipvvis.unipv.it: merged the two + * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "dialog.h" + +static int list_width, check_x, item_x; + +/* + * Print list item + */ +static void print_item(WINDOW * win, int choice, int selected) +{ + int i; + char *list_item = malloc(list_width + 1); + + strncpy(list_item, item_str(), list_width - item_x); + list_item[list_width - item_x] = '\0'; + + /* Clear 'residue' of last item */ + wattrset(win, dlg.menubox.atr); + wmove(win, choice, 0); + for (i = 0; i < list_width; i++) + waddch(win, ' '); + + wmove(win, choice, check_x); + wattrset(win, selected ? dlg.check_selected.atr + : dlg.check.atr); + if (!item_is_tag(':')) + wprintw(win, "(%c)", item_is_tag('X') ? 'X' : ' '); + + wattrset(win, selected ? dlg.tag_selected.atr : dlg.tag.atr); + mvwaddch(win, choice, item_x, list_item[0]); + wattrset(win, selected ? dlg.item_selected.atr : dlg.item.atr); + waddstr(win, list_item + 1); + if (selected) { + wmove(win, choice, check_x + 1); + wrefresh(win); + } + free(list_item); +} + +/* + * Print the scroll indicators. + */ +static void print_arrows(WINDOW * win, int choice, int item_no, int scroll, + int y, int x, int height) +{ + wmove(win, y, x); + + if (scroll > 0) { + wattrset(win, dlg.uarrow.atr); + waddch(win, ACS_UARROW); + waddstr(win, "(-)"); + } else { + wattrset(win, dlg.menubox.atr); + waddch(win, ACS_HLINE); + waddch(win, ACS_HLINE); + waddch(win, ACS_HLINE); + waddch(win, ACS_HLINE); + } + + y = y + height + 1; + wmove(win, y, x); + + if ((height < item_no) && (scroll + choice < item_no - 1)) { + wattrset(win, dlg.darrow.atr); + waddch(win, ACS_DARROW); + waddstr(win, "(+)"); + } else { + wattrset(win, dlg.menubox_border.atr); + waddch(win, ACS_HLINE); + waddch(win, ACS_HLINE); + waddch(win, ACS_HLINE); + waddch(win, ACS_HLINE); + } +} + +/* + * Display the termination buttons + */ +static void print_buttons(WINDOW * dialog, int height, int width, int selected) +{ + int x = width / 2 - 11; + int y = height - 2; + + print_button(dialog, gettext("Select"), y, x, selected == 0); + print_button(dialog, gettext(" Help "), y, x + 14, selected == 1); + + wmove(dialog, y, x + 1 + 14 * selected); + wrefresh(dialog); +} + +/* + * Display a dialog box with a list of options that can be turned on or off + * in the style of radiolist (only one option turned on at a time). + */ +int dialog_checklist(const char *title, const char *prompt, int height, + int width, int list_height) +{ + int i, x, y, box_x, box_y; + int key = 0, button = 0, choice = 0, scroll = 0, max_choice; + WINDOW *dialog, *list; + + /* which item to highlight */ + item_foreach() { + if (item_is_tag('X')) + choice = item_n(); + if (item_is_selected()) { + choice = item_n(); + break; + } + } + +do_resize: + if (getmaxy(stdscr) < (height + 6)) + return -ERRDISPLAYTOOSMALL; + if (getmaxx(stdscr) < (width + 6)) + return -ERRDISPLAYTOOSMALL; + + max_choice = MIN(list_height, item_count()); + + /* center dialog box on screen */ + x = (COLS - width) / 2; + y = (LINES - height) / 2; + + draw_shadow(stdscr, y, x, height, width); + + dialog = newwin(height, width, y, x); + keypad(dialog, TRUE); + + draw_box(dialog, 0, 0, height, width, + dlg.dialog.atr, dlg.border.atr); + wattrset(dialog, dlg.border.atr); + mvwaddch(dialog, height - 3, 0, ACS_LTEE); + for (i = 0; i < width - 2; i++) + waddch(dialog, ACS_HLINE); + wattrset(dialog, dlg.dialog.atr); + waddch(dialog, ACS_RTEE); + + print_title(dialog, title, width); + + wattrset(dialog, dlg.dialog.atr); + print_autowrap(dialog, prompt, width - 2, 1, 3); + + list_width = width - 6; + box_y = height - list_height - 5; + box_x = (width - list_width) / 2 - 1; + + /* create new window for the list */ + list = subwin(dialog, list_height, list_width, y + box_y + 1, + x + box_x + 1); + + keypad(list, TRUE); + + /* draw a box around the list items */ + draw_box(dialog, box_y, box_x, list_height + 2, list_width + 2, + dlg.menubox_border.atr, dlg.menubox.atr); + + /* Find length of longest item in order to center checklist */ + check_x = 0; + item_foreach() + check_x = MAX(check_x, strlen(item_str()) + 4); + check_x = MIN(check_x, list_width); + + check_x = (list_width - check_x) / 2; + item_x = check_x + 4; + + if (choice >= list_height) { + scroll = choice - list_height + 1; + choice -= scroll; + } + + /* Print the list */ + for (i = 0; i < max_choice; i++) { + item_set(scroll + i); + print_item(list, i, i == choice); + } + + print_arrows(dialog, choice, item_count(), scroll, + box_y, box_x + check_x + 5, list_height); + + print_buttons(dialog, height, width, 0); + + wnoutrefresh(dialog); + wnoutrefresh(list); + doupdate(); + + while (key != KEY_ESC) { + key = wgetch(dialog); + + for (i = 0; i < max_choice; i++) { + item_set(i + scroll); + if (toupper(key) == toupper(item_str()[0])) + break; + } + + if (i < max_choice || key == KEY_UP || key == KEY_DOWN || + key == '+' || key == '-') { + if (key == KEY_UP || key == '-') { + if (!choice) { + if (!scroll) + continue; + /* Scroll list down */ + if (list_height > 1) { + /* De-highlight current first item */ + item_set(scroll); + print_item(list, 0, FALSE); + scrollok(list, TRUE); + wscrl(list, -1); + scrollok(list, FALSE); + } + scroll--; + item_set(scroll); + print_item(list, 0, TRUE); + print_arrows(dialog, choice, item_count(), + scroll, box_y, box_x + check_x + 5, list_height); + + wnoutrefresh(dialog); + wrefresh(list); + + continue; /* wait for another key press */ + } else + i = choice - 1; + } else if (key == KEY_DOWN || key == '+') { + if (choice == max_choice - 1) { + if (scroll + choice >= item_count() - 1) + continue; + /* Scroll list up */ + if (list_height > 1) { + /* De-highlight current last item before scrolling up */ + item_set(scroll + max_choice - 1); + print_item(list, + max_choice - 1, + FALSE); + scrollok(list, TRUE); + wscrl(list, 1); + scrollok(list, FALSE); + } + scroll++; + item_set(scroll + max_choice - 1); + print_item(list, max_choice - 1, TRUE); + + print_arrows(dialog, choice, item_count(), + scroll, box_y, box_x + check_x + 5, list_height); + + wnoutrefresh(dialog); + wrefresh(list); + + continue; /* wait for another key press */ + } else + i = choice + 1; + } + if (i != choice) { + /* De-highlight current item */ + item_set(scroll + choice); + print_item(list, choice, FALSE); + /* Highlight new item */ + choice = i; + item_set(scroll + choice); + print_item(list, choice, TRUE); + wnoutrefresh(dialog); + wrefresh(list); + } + continue; /* wait for another key press */ + } + switch (key) { + case 'H': + case 'h': + case '?': + button = 1; + /* fall-through */ + case 'S': + case 's': + case ' ': + case '\n': + item_foreach() + item_set_selected(0); + item_set(scroll + choice); + item_set_selected(1); + delwin(list); + delwin(dialog); + return button; + case TAB: + case KEY_LEFT: + case KEY_RIGHT: + button = ((key == KEY_LEFT ? --button : ++button) < 0) + ? 1 : (button > 1 ? 0 : button); + + print_buttons(dialog, height, width, button); + wrefresh(dialog); + break; + case 'X': + case 'x': + key = KEY_ESC; + break; + case KEY_ESC: + key = on_key_esc(dialog); + break; + case KEY_RESIZE: + delwin(list); + delwin(dialog); + on_key_resize(); + goto do_resize; + } + + /* Now, update everything... */ + doupdate(); + } + delwin(list); + delwin(dialog); + return key; /* ESC pressed */ +} diff --git a/l4/tool/kconfig/scripts/kconfig/lxdialog/dialog.h b/l4/tool/kconfig/scripts/kconfig/lxdialog/dialog.h new file mode 100644 index 00000000..b5211fce --- /dev/null +++ b/l4/tool/kconfig/scripts/kconfig/lxdialog/dialog.h @@ -0,0 +1,230 @@ +/* + * dialog.h -- common declarations for all dialog modules + * + * AUTHOR: Savio Lam (lam836@cs.cuhk.hk) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include + +#ifndef KBUILD_NO_NLS +# include +#else +# define gettext(Msgid) ((const char *) (Msgid)) +#endif + +#ifdef __sun__ +#define CURS_MACROS +#endif +#include CURSES_LOC + +/* + * Colors in ncurses 1.9.9e do not work properly since foreground and + * background colors are OR'd rather than separately masked. This version + * of dialog was hacked to work with ncurses 1.9.9e, making it incompatible + * with standard curses. The simplest fix (to make this work with standard + * curses) uses the wbkgdset() function, not used in the original hack. + * Turn it off if we're building with 1.9.9e, since it just confuses things. + */ +#if defined(NCURSES_VERSION) && defined(_NEED_WRAP) && !defined(GCC_PRINTFLIKE) +#define OLD_NCURSES 1 +#undef wbkgdset +#define wbkgdset(w,p) /*nothing */ +#else +#define OLD_NCURSES 0 +#endif + +#define TR(params) _tracef params + +#define KEY_ESC 27 +#define TAB 9 +#define MAX_LEN 2048 +#define BUF_SIZE (10*1024) +#define MIN(x,y) (x < y ? x : y) +#define MAX(x,y) (x > y ? x : y) + +#ifndef ACS_ULCORNER +#define ACS_ULCORNER '+' +#endif +#ifndef ACS_LLCORNER +#define ACS_LLCORNER '+' +#endif +#ifndef ACS_URCORNER +#define ACS_URCORNER '+' +#endif +#ifndef ACS_LRCORNER +#define ACS_LRCORNER '+' +#endif +#ifndef ACS_HLINE +#define ACS_HLINE '-' +#endif +#ifndef ACS_VLINE +#define ACS_VLINE '|' +#endif +#ifndef ACS_LTEE +#define ACS_LTEE '+' +#endif +#ifndef ACS_RTEE +#define ACS_RTEE '+' +#endif +#ifndef ACS_UARROW +#define ACS_UARROW '^' +#endif +#ifndef ACS_DARROW +#define ACS_DARROW 'v' +#endif + +/* error return codes */ +#define ERRDISPLAYTOOSMALL (KEY_MAX + 1) + +/* + * Color definitions + */ +struct dialog_color { + chtype atr; /* Color attribute */ + int fg; /* foreground */ + int bg; /* background */ + int hl; /* highlight this item */ +}; + +struct dialog_info { + const char *backtitle; + struct dialog_color screen; + struct dialog_color shadow; + struct dialog_color dialog; + struct dialog_color title; + struct dialog_color border; + struct dialog_color button_active; + struct dialog_color button_inactive; + struct dialog_color button_key_active; + struct dialog_color button_key_inactive; + struct dialog_color button_label_active; + struct dialog_color button_label_inactive; + struct dialog_color inputbox; + struct dialog_color inputbox_border; + struct dialog_color searchbox; + struct dialog_color searchbox_title; + struct dialog_color searchbox_border; + struct dialog_color position_indicator; + struct dialog_color menubox; + struct dialog_color menubox_border; + struct dialog_color item; + struct dialog_color item_selected; + struct dialog_color tag; + struct dialog_color tag_selected; + struct dialog_color tag_key; + struct dialog_color tag_key_selected; + struct dialog_color check; + struct dialog_color check_selected; + struct dialog_color uarrow; + struct dialog_color darrow; +}; + +/* + * Global variables + */ +extern struct dialog_info dlg; +extern char dialog_input_result[]; + +/* + * Function prototypes + */ + +/* item list as used by checklist and menubox */ +void item_reset(void); +void item_make(const char *fmt, ...); +void item_add_str(const char *fmt, ...); +void item_set_tag(char tag); +void item_set_data(void *p); +void item_set_selected(int val); +int item_activate_selected(void); +void *item_data(void); +char item_tag(void); + +/* item list manipulation for lxdialog use */ +#define MAXITEMSTR 200 +struct dialog_item { + char str[MAXITEMSTR]; /* promtp displayed */ + char tag; + void *data; /* pointer to menu item - used by menubox+checklist */ + int selected; /* Set to 1 by dialog_*() function if selected. */ +}; + +/* list of lialog_items */ +struct dialog_list { + struct dialog_item node; + struct dialog_list *next; +}; + +extern struct dialog_list *item_cur; +extern struct dialog_list item_nil; +extern struct dialog_list *item_head; + +int item_count(void); +void item_set(int n); +int item_n(void); +const char *item_str(void); +int item_is_selected(void); +int item_is_tag(char tag); +#define item_foreach() \ + for (item_cur = item_head ? item_head: item_cur; \ + item_cur && (item_cur != &item_nil); item_cur = item_cur->next) + +/* generic key handlers */ +int on_key_esc(WINDOW *win); +int on_key_resize(void); + +int init_dialog(const char *backtitle); +void set_dialog_backtitle(const char *backtitle); +void end_dialog(int x, int y); +void attr_clear(WINDOW * win, int height, int width, chtype attr); +void dialog_clear(void); +void print_autowrap(WINDOW * win, const char *prompt, int width, int y, int x); +void print_button(WINDOW * win, const char *label, int y, int x, int selected); +void print_title(WINDOW *dialog, const char *title, int width); +void draw_box(WINDOW * win, int y, int x, int height, int width, chtype box, + chtype border); +void draw_shadow(WINDOW * win, int y, int x, int height, int width); + +int first_alpha(const char *string, const char *exempt); +int dialog_yesno(const char *title, const char *prompt, int height, int width); +int dialog_msgbox(const char *title, const char *prompt, int height, + int width, int pause); +int dialog_textbox(const char *title, const char *file, int height, int width); +int dialog_menu(const char *title, const char *prompt, + const void *selected, int *s_scroll); +int dialog_checklist(const char *title, const char *prompt, int height, + int width, int list_height); +extern char dialog_input_result[]; +int dialog_inputbox(const char *title, const char *prompt, int height, + int width, const char *init); + +/* + * This is the base for fictitious keys, which activate + * the buttons. + * + * Mouse-generated keys are the following: + * -- the first 32 are used as numbers, in addition to '0'-'9' + * -- the lowercase are used to signal mouse-enter events (M_EVENT + 'o') + * -- uppercase chars are used to invoke the button (M_EVENT + 'O') + */ +#define M_EVENT (KEY_MAX+1) diff --git a/l4/tool/kconfig/scripts/kconfig/lxdialog/inputbox.c b/l4/tool/kconfig/scripts/kconfig/lxdialog/inputbox.c new file mode 100644 index 00000000..dd8e587c --- /dev/null +++ b/l4/tool/kconfig/scripts/kconfig/lxdialog/inputbox.c @@ -0,0 +1,238 @@ +/* + * inputbox.c -- implements the input box + * + * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) + * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "dialog.h" + +char dialog_input_result[MAX_LEN + 1]; + +/* + * Print the termination buttons + */ +static void print_buttons(WINDOW * dialog, int height, int width, int selected) +{ + int x = width / 2 - 11; + int y = height - 2; + + print_button(dialog, gettext(" Ok "), y, x, selected == 0); + print_button(dialog, gettext(" Help "), y, x + 14, selected == 1); + + wmove(dialog, y, x + 1 + 14 * selected); + wrefresh(dialog); +} + +/* + * Display a dialog box for inputing a string + */ +int dialog_inputbox(const char *title, const char *prompt, int height, int width, + const char *init) +{ + int i, x, y, box_y, box_x, box_width; + int input_x = 0, scroll = 0, key = 0, button = -1; + char *instr = dialog_input_result; + WINDOW *dialog; + + if (!init) + instr[0] = '\0'; + else + strcpy(instr, init); + +do_resize: + if (getmaxy(stdscr) <= (height - 2)) + return -ERRDISPLAYTOOSMALL; + if (getmaxx(stdscr) <= (width - 2)) + return -ERRDISPLAYTOOSMALL; + + /* center dialog box on screen */ + x = (COLS - width) / 2; + y = (LINES - height) / 2; + + draw_shadow(stdscr, y, x, height, width); + + dialog = newwin(height, width, y, x); + keypad(dialog, TRUE); + + draw_box(dialog, 0, 0, height, width, + dlg.dialog.atr, dlg.border.atr); + wattrset(dialog, dlg.border.atr); + mvwaddch(dialog, height - 3, 0, ACS_LTEE); + for (i = 0; i < width - 2; i++) + waddch(dialog, ACS_HLINE); + wattrset(dialog, dlg.dialog.atr); + waddch(dialog, ACS_RTEE); + + print_title(dialog, title, width); + + wattrset(dialog, dlg.dialog.atr); + print_autowrap(dialog, prompt, width - 2, 1, 3); + + /* Draw the input field box */ + box_width = width - 6; + getyx(dialog, y, x); + box_y = y + 2; + box_x = (width - box_width) / 2; + draw_box(dialog, y + 1, box_x - 1, 3, box_width + 2, + dlg.dialog.atr, dlg.border.atr); + + print_buttons(dialog, height, width, 0); + + /* Set up the initial value */ + wmove(dialog, box_y, box_x); + wattrset(dialog, dlg.inputbox.atr); + + input_x = strlen(instr); + + if (input_x >= box_width) { + scroll = input_x - box_width + 1; + input_x = box_width - 1; + for (i = 0; i < box_width - 1; i++) + waddch(dialog, instr[scroll + i]); + } else { + waddstr(dialog, instr); + } + + wmove(dialog, box_y, box_x + input_x); + + wrefresh(dialog); + + while (key != KEY_ESC) { + key = wgetch(dialog); + + if (button == -1) { /* Input box selected */ + switch (key) { + case TAB: + case KEY_UP: + case KEY_DOWN: + break; + case KEY_LEFT: + continue; + case KEY_RIGHT: + continue; + case KEY_BACKSPACE: + case 127: + if (input_x || scroll) { + wattrset(dialog, dlg.inputbox.atr); + if (!input_x) { + scroll = scroll < box_width - 1 ? 0 : scroll - (box_width - 1); + wmove(dialog, box_y, box_x); + for (i = 0; i < box_width; i++) + waddch(dialog, + instr[scroll + input_x + i] ? + instr[scroll + input_x + i] : ' '); + input_x = strlen(instr) - scroll; + } else + input_x--; + instr[scroll + input_x] = '\0'; + mvwaddch(dialog, box_y, input_x + box_x, ' '); + wmove(dialog, box_y, input_x + box_x); + wrefresh(dialog); + } + continue; + default: + if (key < 0x100 && isprint(key)) { + if (scroll + input_x < MAX_LEN) { + wattrset(dialog, dlg.inputbox.atr); + instr[scroll + input_x] = key; + instr[scroll + input_x + 1] = '\0'; + if (input_x == box_width - 1) { + scroll++; + wmove(dialog, box_y, box_x); + for (i = 0; i < box_width - 1; i++) + waddch(dialog, instr [scroll + i]); + } else { + wmove(dialog, box_y, input_x++ + box_x); + waddch(dialog, key); + } + wrefresh(dialog); + } else + flash(); /* Alarm user about overflow */ + continue; + } + } + } + switch (key) { + case 'O': + case 'o': + delwin(dialog); + return 0; + case 'H': + case 'h': + delwin(dialog); + return 1; + case KEY_UP: + case KEY_LEFT: + switch (button) { + case -1: + button = 1; /* Indicates "Help" button is selected */ + print_buttons(dialog, height, width, 1); + break; + case 0: + button = -1; /* Indicates input box is selected */ + print_buttons(dialog, height, width, 0); + wmove(dialog, box_y, box_x + input_x); + wrefresh(dialog); + break; + case 1: + button = 0; /* Indicates "OK" button is selected */ + print_buttons(dialog, height, width, 0); + break; + } + break; + case TAB: + case KEY_DOWN: + case KEY_RIGHT: + switch (button) { + case -1: + button = 0; /* Indicates "OK" button is selected */ + print_buttons(dialog, height, width, 0); + break; + case 0: + button = 1; /* Indicates "Help" button is selected */ + print_buttons(dialog, height, width, 1); + break; + case 1: + button = -1; /* Indicates input box is selected */ + print_buttons(dialog, height, width, 0); + wmove(dialog, box_y, box_x + input_x); + wrefresh(dialog); + break; + } + break; + case ' ': + case '\n': + delwin(dialog); + return (button == -1 ? 0 : button); + case 'X': + case 'x': + key = KEY_ESC; + break; + case KEY_ESC: + key = on_key_esc(dialog); + break; + case KEY_RESIZE: + delwin(dialog); + on_key_resize(); + goto do_resize; + } + } + + delwin(dialog); + return KEY_ESC; /* ESC pressed */ +} diff --git a/l4/tool/kconfig/scripts/kconfig/lxdialog/menubox.c b/l4/tool/kconfig/scripts/kconfig/lxdialog/menubox.c new file mode 100644 index 00000000..1d604738 --- /dev/null +++ b/l4/tool/kconfig/scripts/kconfig/lxdialog/menubox.c @@ -0,0 +1,434 @@ +/* + * menubox.c -- implements the menu box + * + * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) + * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcapw@cfw.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* + * Changes by Clifford Wolf (god@clifford.at) + * + * [ 1998-06-13 ] + * + * *) A bugfix for the Page-Down problem + * + * *) Formerly when I used Page Down and Page Up, the cursor would be set + * to the first position in the menu box. Now lxdialog is a bit + * smarter and works more like other menu systems (just have a look at + * it). + * + * *) Formerly if I selected something my scrolling would be broken because + * lxdialog is re-invoked by the Menuconfig shell script, can't + * remember the last scrolling position, and just sets it so that the + * cursor is at the bottom of the box. Now it writes the temporary file + * lxdialog.scrltmp which contains this information. The file is + * deleted by lxdialog if the user leaves a submenu or enters a new + * one, but it would be nice if Menuconfig could make another "rm -f" + * just to be sure. Just try it out - you will recognise a difference! + * + * [ 1998-06-14 ] + * + * *) Now lxdialog is crash-safe against broken "lxdialog.scrltmp" files + * and menus change their size on the fly. + * + * *) If for some reason the last scrolling position is not saved by + * lxdialog, it sets the scrolling so that the selected item is in the + * middle of the menu box, not at the bottom. + * + * 02 January 1999, Michael Elizabeth Chastain (mec@shout.net) + * Reset 'scroll' to 0 if the value from lxdialog.scrltmp is bogus. + * This fixes a bug in Menuconfig where using ' ' to descend into menus + * would leave mis-synchronized lxdialog.scrltmp files lying around, + * fscanf would read in 'scroll', and eventually that value would get used. + */ + +#include "dialog.h" + +static int menu_width, item_x; + +/* + * Print menu item + */ +static void do_print_item(WINDOW * win, const char *item, int line_y, + int selected, int hotkey) +{ + int j; + char *menu_item = malloc(menu_width + 1); + + strncpy(menu_item, item, menu_width - item_x); + menu_item[menu_width - item_x] = '\0'; + j = first_alpha(menu_item, "YyNnMmHh"); + + /* Clear 'residue' of last item */ + wattrset(win, dlg.menubox.atr); + wmove(win, line_y, 0); +#if OLD_NCURSES + { + int i; + for (i = 0; i < menu_width; i++) + waddch(win, ' '); + } +#else + wclrtoeol(win); +#endif + wattrset(win, selected ? dlg.item_selected.atr : dlg.item.atr); + mvwaddstr(win, line_y, item_x, menu_item); + if (hotkey) { + wattrset(win, selected ? dlg.tag_key_selected.atr + : dlg.tag_key.atr); + mvwaddch(win, line_y, item_x + j, menu_item[j]); + } + if (selected) { + wmove(win, line_y, item_x + 1); + } + free(menu_item); + wrefresh(win); +} + +#define print_item(index, choice, selected) \ +do { \ + item_set(index); \ + do_print_item(menu, item_str(), choice, selected, !item_is_tag(':')); \ +} while (0) + +/* + * Print the scroll indicators. + */ +static void print_arrows(WINDOW * win, int item_no, int scroll, int y, int x, + int height) +{ + int cur_y, cur_x; + + getyx(win, cur_y, cur_x); + + wmove(win, y, x); + + if (scroll > 0) { + wattrset(win, dlg.uarrow.atr); + waddch(win, ACS_UARROW); + waddstr(win, "(-)"); + } else { + wattrset(win, dlg.menubox.atr); + waddch(win, ACS_HLINE); + waddch(win, ACS_HLINE); + waddch(win, ACS_HLINE); + waddch(win, ACS_HLINE); + } + + y = y + height + 1; + wmove(win, y, x); + wrefresh(win); + + if ((height < item_no) && (scroll + height < item_no)) { + wattrset(win, dlg.darrow.atr); + waddch(win, ACS_DARROW); + waddstr(win, "(+)"); + } else { + wattrset(win, dlg.menubox_border.atr); + waddch(win, ACS_HLINE); + waddch(win, ACS_HLINE); + waddch(win, ACS_HLINE); + waddch(win, ACS_HLINE); + } + + wmove(win, cur_y, cur_x); + wrefresh(win); +} + +/* + * Display the termination buttons. + */ +static void print_buttons(WINDOW * win, int height, int width, int selected) +{ + int x = width / 2 - 16; + int y = height - 2; + + print_button(win, gettext("Select"), y, x, selected == 0); + print_button(win, gettext(" Exit "), y, x + 12, selected == 1); + print_button(win, gettext(" Help "), y, x + 24, selected == 2); + + wmove(win, y, x + 1 + 12 * selected); + wrefresh(win); +} + +/* scroll up n lines (n may be negative) */ +static void do_scroll(WINDOW *win, int *scroll, int n) +{ + /* Scroll menu up */ + scrollok(win, TRUE); + wscrl(win, n); + scrollok(win, FALSE); + *scroll = *scroll + n; + wrefresh(win); +} + +/* + * Display a menu for choosing among a number of options + */ +int dialog_menu(const char *title, const char *prompt, + const void *selected, int *s_scroll) +{ + int i, j, x, y, box_x, box_y; + int height, width, menu_height; + int key = 0, button = 0, scroll = 0, choice = 0; + int first_item = 0, max_choice; + WINDOW *dialog, *menu; + +do_resize: + height = getmaxy(stdscr); + width = getmaxx(stdscr); + if (height < 15 || width < 65) + return -ERRDISPLAYTOOSMALL; + + height -= 4; + width -= 5; + menu_height = height - 10; + + max_choice = MIN(menu_height, item_count()); + + /* center dialog box on screen */ + x = (COLS - width) / 2; + y = (LINES - height) / 2; + + draw_shadow(stdscr, y, x, height, width); + + dialog = newwin(height, width, y, x); + keypad(dialog, TRUE); + + draw_box(dialog, 0, 0, height, width, + dlg.dialog.atr, dlg.border.atr); + wattrset(dialog, dlg.border.atr); + mvwaddch(dialog, height - 3, 0, ACS_LTEE); + for (i = 0; i < width - 2; i++) + waddch(dialog, ACS_HLINE); + wattrset(dialog, dlg.dialog.atr); + wbkgdset(dialog, dlg.dialog.atr & A_COLOR); + waddch(dialog, ACS_RTEE); + + print_title(dialog, title, width); + + wattrset(dialog, dlg.dialog.atr); + print_autowrap(dialog, prompt, width - 2, 1, 3); + + menu_width = width - 6; + box_y = height - menu_height - 5; + box_x = (width - menu_width) / 2 - 1; + + /* create new window for the menu */ + menu = subwin(dialog, menu_height, menu_width, + y + box_y + 1, x + box_x + 1); + keypad(menu, TRUE); + + /* draw a box around the menu items */ + draw_box(dialog, box_y, box_x, menu_height + 2, menu_width + 2, + dlg.menubox_border.atr, dlg.menubox.atr); + + if (menu_width >= 80) + item_x = (menu_width - 70) / 2; + else + item_x = 4; + + /* Set choice to default item */ + item_foreach() + if (selected && (selected == item_data())) + choice = item_n(); + /* get the saved scroll info */ + scroll = *s_scroll; + if ((scroll <= choice) && (scroll + max_choice > choice) && + (scroll >= 0) && (scroll + max_choice <= item_count())) { + first_item = scroll; + choice = choice - scroll; + } else { + scroll = 0; + } + if ((choice >= max_choice)) { + if (choice >= item_count() - max_choice / 2) + scroll = first_item = item_count() - max_choice; + else + scroll = first_item = choice - max_choice / 2; + choice = choice - scroll; + } + + /* Print the menu */ + for (i = 0; i < max_choice; i++) { + print_item(first_item + i, i, i == choice); + } + + wnoutrefresh(menu); + + print_arrows(dialog, item_count(), scroll, + box_y, box_x + item_x + 1, menu_height); + + print_buttons(dialog, height, width, 0); + wmove(menu, choice, item_x + 1); + wrefresh(menu); + + while (key != KEY_ESC) { + key = wgetch(menu); + + if (key < 256 && isalpha(key)) + key = tolower(key); + + if (strchr("ynmh", key)) + i = max_choice; + else { + for (i = choice + 1; i < max_choice; i++) { + item_set(scroll + i); + j = first_alpha(item_str(), "YyNnMmHh"); + if (key == tolower(item_str()[j])) + break; + } + if (i == max_choice) + for (i = 0; i < max_choice; i++) { + item_set(scroll + i); + j = first_alpha(item_str(), "YyNnMmHh"); + if (key == tolower(item_str()[j])) + break; + } + } + + if (i < max_choice || + key == KEY_UP || key == KEY_DOWN || + key == '-' || key == '+' || + key == KEY_PPAGE || key == KEY_NPAGE) { + /* Remove highligt of current item */ + print_item(scroll + choice, choice, FALSE); + + if (key == KEY_UP || key == '-') { + if (choice < 2 && scroll) { + /* Scroll menu down */ + do_scroll(menu, &scroll, -1); + + print_item(scroll, 0, FALSE); + } else + choice = MAX(choice - 1, 0); + + } else if (key == KEY_DOWN || key == '+') { + print_item(scroll+choice, choice, FALSE); + + if ((choice > max_choice - 3) && + (scroll + max_choice < item_count())) { + /* Scroll menu up */ + do_scroll(menu, &scroll, 1); + + print_item(scroll+max_choice - 1, + max_choice - 1, FALSE); + } else + choice = MIN(choice + 1, max_choice - 1); + + } else if (key == KEY_PPAGE) { + scrollok(menu, TRUE); + for (i = 0; (i < max_choice); i++) { + if (scroll > 0) { + do_scroll(menu, &scroll, -1); + print_item(scroll, 0, FALSE); + } else { + if (choice > 0) + choice--; + } + } + + } else if (key == KEY_NPAGE) { + for (i = 0; (i < max_choice); i++) { + if (scroll + max_choice < item_count()) { + do_scroll(menu, &scroll, 1); + print_item(scroll+max_choice-1, + max_choice - 1, FALSE); + } else { + if (choice + 1 < max_choice) + choice++; + } + } + } else + choice = i; + + print_item(scroll + choice, choice, TRUE); + + print_arrows(dialog, item_count(), scroll, + box_y, box_x + item_x + 1, menu_height); + + wnoutrefresh(dialog); + wrefresh(menu); + + continue; /* wait for another key press */ + } + + switch (key) { + case KEY_LEFT: + case TAB: + case KEY_RIGHT: + button = ((key == KEY_LEFT ? --button : ++button) < 0) + ? 2 : (button > 2 ? 0 : button); + + print_buttons(dialog, height, width, button); + wrefresh(menu); + break; + case ' ': + case 's': + case 'y': + case 'n': + case 'm': + case '/': + case 'h': + case '?': + case 'z': + case '\n': + /* save scroll info */ + *s_scroll = scroll; + delwin(menu); + delwin(dialog); + item_set(scroll + choice); + item_set_selected(1); + switch (key) { + case 'h': + case '?': + return 2; + case 's': + case 'y': + return 3; + case 'n': + return 4; + case 'm': + return 5; + case ' ': + return 6; + case '/': + return 7; + case 'z': + return 8; + case '\n': + return button; + } + return 0; + case 'e': + case 'x': + key = KEY_ESC; + break; + case KEY_ESC: + key = on_key_esc(menu); + break; + case KEY_RESIZE: + on_key_resize(); + delwin(menu); + delwin(dialog); + goto do_resize; + } + } + delwin(menu); + delwin(dialog); + return key; /* ESC pressed */ +} diff --git a/l4/tool/kconfig/scripts/kconfig/lxdialog/textbox.c b/l4/tool/kconfig/scripts/kconfig/lxdialog/textbox.c new file mode 100644 index 00000000..154c2dd2 --- /dev/null +++ b/l4/tool/kconfig/scripts/kconfig/lxdialog/textbox.c @@ -0,0 +1,390 @@ +/* + * textbox.c -- implements the text box + * + * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) + * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "dialog.h" + +static void back_lines(int n); +static void print_page(WINDOW * win, int height, int width); +static void print_line(WINDOW * win, int row, int width); +static char *get_line(void); +static void print_position(WINDOW * win); + +static int hscroll; +static int begin_reached, end_reached, page_length; +static const char *buf; +static const char *page; + +/* + * refresh window content + */ +static void refresh_text_box(WINDOW *dialog, WINDOW *box, int boxh, int boxw, + int cur_y, int cur_x) +{ + print_page(box, boxh, boxw); + print_position(dialog); + wmove(dialog, cur_y, cur_x); /* Restore cursor position */ + wrefresh(dialog); +} + + +/* + * Display text from a file in a dialog box. + */ +int dialog_textbox(const char *title, const char *tbuf, + int initial_height, int initial_width) +{ + int i, x, y, cur_x, cur_y, key = 0; + int height, width, boxh, boxw; + int passed_end; + WINDOW *dialog, *box; + + begin_reached = 1; + end_reached = 0; + page_length = 0; + hscroll = 0; + buf = tbuf; + page = buf; /* page is pointer to start of page to be displayed */ + +do_resize: + getmaxyx(stdscr, height, width); + if (height < 8 || width < 8) + return -ERRDISPLAYTOOSMALL; + if (initial_height != 0) + height = initial_height; + else + if (height > 4) + height -= 4; + else + height = 0; + if (initial_width != 0) + width = initial_width; + else + if (width > 5) + width -= 5; + else + width = 0; + + /* center dialog box on screen */ + x = (COLS - width) / 2; + y = (LINES - height) / 2; + + draw_shadow(stdscr, y, x, height, width); + + dialog = newwin(height, width, y, x); + keypad(dialog, TRUE); + + /* Create window for box region, used for scrolling text */ + boxh = height - 4; + boxw = width - 2; + box = subwin(dialog, boxh, boxw, y + 1, x + 1); + wattrset(box, dlg.dialog.atr); + wbkgdset(box, dlg.dialog.atr & A_COLOR); + + keypad(box, TRUE); + + /* register the new window, along with its borders */ + draw_box(dialog, 0, 0, height, width, + dlg.dialog.atr, dlg.border.atr); + + wattrset(dialog, dlg.border.atr); + mvwaddch(dialog, height - 3, 0, ACS_LTEE); + for (i = 0; i < width - 2; i++) + waddch(dialog, ACS_HLINE); + wattrset(dialog, dlg.dialog.atr); + wbkgdset(dialog, dlg.dialog.atr & A_COLOR); + waddch(dialog, ACS_RTEE); + + print_title(dialog, title, width); + + print_button(dialog, gettext(" Exit "), height - 2, width / 2 - 4, TRUE); + wnoutrefresh(dialog); + getyx(dialog, cur_y, cur_x); /* Save cursor position */ + + /* Print first page of text */ + attr_clear(box, boxh, boxw, dlg.dialog.atr); + refresh_text_box(dialog, box, boxh, boxw, cur_y, cur_x); + + while ((key != KEY_ESC) && (key != '\n')) { + key = wgetch(dialog); + switch (key) { + case 'E': /* Exit */ + case 'e': + case 'X': + case 'x': + delwin(box); + delwin(dialog); + return 0; + case 'g': /* First page */ + case KEY_HOME: + if (!begin_reached) { + begin_reached = 1; + page = buf; + refresh_text_box(dialog, box, boxh, boxw, + cur_y, cur_x); + } + break; + case 'G': /* Last page */ + case KEY_END: + + end_reached = 1; + /* point to last char in buf */ + page = buf + strlen(buf); + back_lines(boxh); + refresh_text_box(dialog, box, boxh, boxw, + cur_y, cur_x); + break; + case 'K': /* Previous line */ + case 'k': + case KEY_UP: + if (!begin_reached) { + back_lines(page_length + 1); + + /* We don't call print_page() here but use + * scrolling to ensure faster screen update. + * However, 'end_reached' and 'page_length' + * should still be updated, and 'page' should + * point to start of next page. This is done + * by calling get_line() in the following + * 'for' loop. */ + scrollok(box, TRUE); + wscrl(box, -1); /* Scroll box region down one line */ + scrollok(box, FALSE); + page_length = 0; + passed_end = 0; + for (i = 0; i < boxh; i++) { + if (!i) { + /* print first line of page */ + print_line(box, 0, boxw); + wnoutrefresh(box); + } else + /* Called to update 'end_reached' and 'page' */ + get_line(); + if (!passed_end) + page_length++; + if (end_reached && !passed_end) + passed_end = 1; + } + + print_position(dialog); + wmove(dialog, cur_y, cur_x); /* Restore cursor position */ + wrefresh(dialog); + } + break; + case 'B': /* Previous page */ + case 'b': + case KEY_PPAGE: + if (begin_reached) + break; + back_lines(page_length + boxh); + refresh_text_box(dialog, box, boxh, boxw, + cur_y, cur_x); + break; + case 'J': /* Next line */ + case 'j': + case KEY_DOWN: + if (!end_reached) { + begin_reached = 0; + scrollok(box, TRUE); + scroll(box); /* Scroll box region up one line */ + scrollok(box, FALSE); + print_line(box, boxh - 1, boxw); + wnoutrefresh(box); + print_position(dialog); + wmove(dialog, cur_y, cur_x); /* Restore cursor position */ + wrefresh(dialog); + } + break; + case KEY_NPAGE: /* Next page */ + case ' ': + if (end_reached) + break; + + begin_reached = 0; + refresh_text_box(dialog, box, boxh, boxw, + cur_y, cur_x); + break; + case '0': /* Beginning of line */ + case 'H': /* Scroll left */ + case 'h': + case KEY_LEFT: + if (hscroll <= 0) + break; + + if (key == '0') + hscroll = 0; + else + hscroll--; + /* Reprint current page to scroll horizontally */ + back_lines(page_length); + refresh_text_box(dialog, box, boxh, boxw, + cur_y, cur_x); + break; + case 'L': /* Scroll right */ + case 'l': + case KEY_RIGHT: + if (hscroll >= MAX_LEN) + break; + hscroll++; + /* Reprint current page to scroll horizontally */ + back_lines(page_length); + refresh_text_box(dialog, box, boxh, boxw, + cur_y, cur_x); + break; + case KEY_ESC: + key = on_key_esc(dialog); + break; + case KEY_RESIZE: + back_lines(height); + delwin(box); + delwin(dialog); + on_key_resize(); + goto do_resize; + } + } + delwin(box); + delwin(dialog); + return key; /* ESC pressed */ +} + +/* + * Go back 'n' lines in text. Called by dialog_textbox(). + * 'page' will be updated to point to the desired line in 'buf'. + */ +static void back_lines(int n) +{ + int i; + + begin_reached = 0; + /* Go back 'n' lines */ + for (i = 0; i < n; i++) { + if (*page == '\0') { + if (end_reached) { + end_reached = 0; + continue; + } + } + if (page == buf) { + begin_reached = 1; + return; + } + page--; + do { + if (page == buf) { + begin_reached = 1; + return; + } + page--; + } while (*page != '\n'); + page++; + } +} + +/* + * Print a new page of text. Called by dialog_textbox(). + */ +static void print_page(WINDOW * win, int height, int width) +{ + int i, passed_end = 0; + + page_length = 0; + for (i = 0; i < height; i++) { + print_line(win, i, width); + if (!passed_end) + page_length++; + if (end_reached && !passed_end) + passed_end = 1; + } + wnoutrefresh(win); +} + +/* + * Print a new line of text. Called by dialog_textbox() and print_page(). + */ +static void print_line(WINDOW * win, int row, int width) +{ + char *line; + + line = get_line(); + line += MIN(strlen(line), hscroll); /* Scroll horizontally */ + wmove(win, row, 0); /* move cursor to correct line */ + waddch(win, ' '); + waddnstr(win, line, MIN(strlen(line), width - 2)); + + /* Clear 'residue' of previous line */ +#if OLD_NCURSES + { + int x = getcurx(win); + int i; + for (i = 0; i < width - x; i++) + waddch(win, ' '); + } +#else + wclrtoeol(win); +#endif +} + +/* + * Return current line of text. Called by dialog_textbox() and print_line(). + * 'page' should point to start of current line before calling, and will be + * updated to point to start of next line. + */ +static char *get_line(void) +{ + int i = 0; + static char line[MAX_LEN + 1]; + + end_reached = 0; + while (*page != '\n') { + if (*page == '\0') { + if (!end_reached) { + end_reached = 1; + break; + } + } else if (i < MAX_LEN) + line[i++] = *(page++); + else { + /* Truncate lines longer than MAX_LEN characters */ + if (i == MAX_LEN) + line[i++] = '\0'; + page++; + } + } + if (i <= MAX_LEN) + line[i] = '\0'; + if (!end_reached) + page++; /* move pass '\n' */ + + return line; +} + +/* + * Print current position + */ +static void print_position(WINDOW * win) +{ + int percent; + + wattrset(win, dlg.position_indicator.atr); + wbkgdset(win, dlg.position_indicator.atr & A_COLOR); + percent = (page - buf) * 100 / strlen(buf); + wmove(win, getmaxy(win) - 3, getmaxx(win) - 9); + wprintw(win, "(%3d%%)", percent); +} diff --git a/l4/tool/kconfig/scripts/kconfig/lxdialog/util.c b/l4/tool/kconfig/scripts/kconfig/lxdialog/util.c new file mode 100644 index 00000000..f2375ad7 --- /dev/null +++ b/l4/tool/kconfig/scripts/kconfig/lxdialog/util.c @@ -0,0 +1,657 @@ +/* + * util.c + * + * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) + * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include + +#include "dialog.h" + +struct dialog_info dlg; + +static void set_mono_theme(void) +{ + dlg.screen.atr = A_NORMAL; + dlg.shadow.atr = A_NORMAL; + dlg.dialog.atr = A_NORMAL; + dlg.title.atr = A_BOLD; + dlg.border.atr = A_NORMAL; + dlg.button_active.atr = A_REVERSE; + dlg.button_inactive.atr = A_DIM; + dlg.button_key_active.atr = A_REVERSE; + dlg.button_key_inactive.atr = A_BOLD; + dlg.button_label_active.atr = A_REVERSE; + dlg.button_label_inactive.atr = A_NORMAL; + dlg.inputbox.atr = A_NORMAL; + dlg.inputbox_border.atr = A_NORMAL; + dlg.searchbox.atr = A_NORMAL; + dlg.searchbox_title.atr = A_BOLD; + dlg.searchbox_border.atr = A_NORMAL; + dlg.position_indicator.atr = A_BOLD; + dlg.menubox.atr = A_NORMAL; + dlg.menubox_border.atr = A_NORMAL; + dlg.item.atr = A_NORMAL; + dlg.item_selected.atr = A_REVERSE; + dlg.tag.atr = A_BOLD; + dlg.tag_selected.atr = A_REVERSE; + dlg.tag_key.atr = A_BOLD; + dlg.tag_key_selected.atr = A_REVERSE; + dlg.check.atr = A_BOLD; + dlg.check_selected.atr = A_REVERSE; + dlg.uarrow.atr = A_BOLD; + dlg.darrow.atr = A_BOLD; +} + +#define DLG_COLOR(dialog, f, b, h) \ +do { \ + dlg.dialog.fg = (f); \ + dlg.dialog.bg = (b); \ + dlg.dialog.hl = (h); \ +} while (0) + +static void set_classic_theme(void) +{ + DLG_COLOR(screen, COLOR_CYAN, COLOR_BLUE, true); + DLG_COLOR(shadow, COLOR_BLACK, COLOR_BLACK, true); + DLG_COLOR(dialog, COLOR_BLACK, COLOR_WHITE, false); + DLG_COLOR(title, COLOR_YELLOW, COLOR_WHITE, true); + DLG_COLOR(border, COLOR_WHITE, COLOR_WHITE, true); + DLG_COLOR(button_active, COLOR_WHITE, COLOR_BLUE, true); + DLG_COLOR(button_inactive, COLOR_BLACK, COLOR_WHITE, false); + DLG_COLOR(button_key_active, COLOR_WHITE, COLOR_BLUE, true); + DLG_COLOR(button_key_inactive, COLOR_RED, COLOR_WHITE, false); + DLG_COLOR(button_label_active, COLOR_YELLOW, COLOR_BLUE, true); + DLG_COLOR(button_label_inactive, COLOR_BLACK, COLOR_WHITE, true); + DLG_COLOR(inputbox, COLOR_BLACK, COLOR_WHITE, false); + DLG_COLOR(inputbox_border, COLOR_BLACK, COLOR_WHITE, false); + DLG_COLOR(searchbox, COLOR_BLACK, COLOR_WHITE, false); + DLG_COLOR(searchbox_title, COLOR_YELLOW, COLOR_WHITE, true); + DLG_COLOR(searchbox_border, COLOR_WHITE, COLOR_WHITE, true); + DLG_COLOR(position_indicator, COLOR_YELLOW, COLOR_WHITE, true); + DLG_COLOR(menubox, COLOR_BLACK, COLOR_WHITE, false); + DLG_COLOR(menubox_border, COLOR_WHITE, COLOR_WHITE, true); + DLG_COLOR(item, COLOR_BLACK, COLOR_WHITE, false); + DLG_COLOR(item_selected, COLOR_WHITE, COLOR_BLUE, true); + DLG_COLOR(tag, COLOR_YELLOW, COLOR_WHITE, true); + DLG_COLOR(tag_selected, COLOR_YELLOW, COLOR_BLUE, true); + DLG_COLOR(tag_key, COLOR_YELLOW, COLOR_WHITE, true); + DLG_COLOR(tag_key_selected, COLOR_YELLOW, COLOR_BLUE, true); + DLG_COLOR(check, COLOR_BLACK, COLOR_WHITE, false); + DLG_COLOR(check_selected, COLOR_WHITE, COLOR_BLUE, true); + DLG_COLOR(uarrow, COLOR_GREEN, COLOR_WHITE, true); + DLG_COLOR(darrow, COLOR_GREEN, COLOR_WHITE, true); +} + +static void set_blackbg_theme(void) +{ + DLG_COLOR(screen, COLOR_RED, COLOR_BLACK, true); + DLG_COLOR(shadow, COLOR_BLACK, COLOR_BLACK, false); + DLG_COLOR(dialog, COLOR_WHITE, COLOR_BLACK, false); + DLG_COLOR(title, COLOR_RED, COLOR_BLACK, false); + DLG_COLOR(border, COLOR_BLACK, COLOR_BLACK, true); + + DLG_COLOR(button_active, COLOR_YELLOW, COLOR_RED, false); + DLG_COLOR(button_inactive, COLOR_YELLOW, COLOR_BLACK, false); + DLG_COLOR(button_key_active, COLOR_YELLOW, COLOR_RED, true); + DLG_COLOR(button_key_inactive, COLOR_RED, COLOR_BLACK, false); + DLG_COLOR(button_label_active, COLOR_WHITE, COLOR_RED, false); + DLG_COLOR(button_label_inactive, COLOR_BLACK, COLOR_BLACK, true); + + DLG_COLOR(inputbox, COLOR_YELLOW, COLOR_BLACK, false); + DLG_COLOR(inputbox_border, COLOR_YELLOW, COLOR_BLACK, false); + + DLG_COLOR(searchbox, COLOR_YELLOW, COLOR_BLACK, false); + DLG_COLOR(searchbox_title, COLOR_YELLOW, COLOR_BLACK, true); + DLG_COLOR(searchbox_border, COLOR_BLACK, COLOR_BLACK, true); + + DLG_COLOR(position_indicator, COLOR_RED, COLOR_BLACK, false); + + DLG_COLOR(menubox, COLOR_YELLOW, COLOR_BLACK, false); + DLG_COLOR(menubox_border, COLOR_BLACK, COLOR_BLACK, true); + + DLG_COLOR(item, COLOR_WHITE, COLOR_BLACK, false); + DLG_COLOR(item_selected, COLOR_WHITE, COLOR_RED, false); + + DLG_COLOR(tag, COLOR_RED, COLOR_BLACK, false); + DLG_COLOR(tag_selected, COLOR_YELLOW, COLOR_RED, true); + DLG_COLOR(tag_key, COLOR_RED, COLOR_BLACK, false); + DLG_COLOR(tag_key_selected, COLOR_YELLOW, COLOR_RED, true); + + DLG_COLOR(check, COLOR_YELLOW, COLOR_BLACK, false); + DLG_COLOR(check_selected, COLOR_YELLOW, COLOR_RED, true); + + DLG_COLOR(uarrow, COLOR_RED, COLOR_BLACK, false); + DLG_COLOR(darrow, COLOR_RED, COLOR_BLACK, false); +} + +static void set_bluetitle_theme(void) +{ + set_classic_theme(); + DLG_COLOR(title, COLOR_BLUE, COLOR_WHITE, true); + DLG_COLOR(button_key_active, COLOR_YELLOW, COLOR_BLUE, true); + DLG_COLOR(button_label_active, COLOR_WHITE, COLOR_BLUE, true); + DLG_COLOR(searchbox_title, COLOR_BLUE, COLOR_WHITE, true); + DLG_COLOR(position_indicator, COLOR_BLUE, COLOR_WHITE, true); + DLG_COLOR(tag, COLOR_BLUE, COLOR_WHITE, true); + DLG_COLOR(tag_key, COLOR_BLUE, COLOR_WHITE, true); + +} + +/* + * Select color theme + */ +static int set_theme(const char *theme) +{ + int use_color = 1; + if (!theme) + set_bluetitle_theme(); + else if (strcmp(theme, "classic") == 0) + set_classic_theme(); + else if (strcmp(theme, "bluetitle") == 0) + set_bluetitle_theme(); + else if (strcmp(theme, "blackbg") == 0) + set_blackbg_theme(); + else if (strcmp(theme, "mono") == 0) + use_color = 0; + + return use_color; +} + +static void init_one_color(struct dialog_color *color) +{ + static int pair = 0; + + pair++; + init_pair(pair, color->fg, color->bg); + if (color->hl) + color->atr = A_BOLD | COLOR_PAIR(pair); + else + color->atr = COLOR_PAIR(pair); +} + +static void init_dialog_colors(void) +{ + init_one_color(&dlg.screen); + init_one_color(&dlg.shadow); + init_one_color(&dlg.dialog); + init_one_color(&dlg.title); + init_one_color(&dlg.border); + init_one_color(&dlg.button_active); + init_one_color(&dlg.button_inactive); + init_one_color(&dlg.button_key_active); + init_one_color(&dlg.button_key_inactive); + init_one_color(&dlg.button_label_active); + init_one_color(&dlg.button_label_inactive); + init_one_color(&dlg.inputbox); + init_one_color(&dlg.inputbox_border); + init_one_color(&dlg.searchbox); + init_one_color(&dlg.searchbox_title); + init_one_color(&dlg.searchbox_border); + init_one_color(&dlg.position_indicator); + init_one_color(&dlg.menubox); + init_one_color(&dlg.menubox_border); + init_one_color(&dlg.item); + init_one_color(&dlg.item_selected); + init_one_color(&dlg.tag); + init_one_color(&dlg.tag_selected); + init_one_color(&dlg.tag_key); + init_one_color(&dlg.tag_key_selected); + init_one_color(&dlg.check); + init_one_color(&dlg.check_selected); + init_one_color(&dlg.uarrow); + init_one_color(&dlg.darrow); +} + +/* + * Setup for color display + */ +static void color_setup(const char *theme) +{ + int use_color; + + use_color = set_theme(theme); + if (use_color && has_colors()) { + start_color(); + init_dialog_colors(); + } else + set_mono_theme(); +} + +/* + * Set window to attribute 'attr' + */ +void attr_clear(WINDOW * win, int height, int width, chtype attr) +{ + int i, j; + + wattrset(win, attr); + for (i = 0; i < height; i++) { + wmove(win, i, 0); + for (j = 0; j < width; j++) + waddch(win, ' '); + } + touchwin(win); +} + +void dialog_clear(void) +{ + attr_clear(stdscr, LINES, COLS, dlg.screen.atr); + /* Display background title if it exists ... - SLH */ + if (dlg.backtitle != NULL) { + int i; + + wattrset(stdscr, dlg.screen.atr); + mvwaddstr(stdscr, 0, 1, (char *)dlg.backtitle); + wmove(stdscr, 1, 1); + for (i = 1; i < COLS - 1; i++) + waddch(stdscr, ACS_HLINE); + } + wnoutrefresh(stdscr); +} + +/* + * Do some initialization for dialog + */ +int init_dialog(const char *backtitle) +{ + int height, width; + + initscr(); /* Init curses */ + getmaxyx(stdscr, height, width); + if (height < 19 || width < 80) { + endwin(); + return -ERRDISPLAYTOOSMALL; + } + + dlg.backtitle = backtitle; + color_setup(getenv("MENUCONFIG_COLOR")); + + keypad(stdscr, TRUE); + cbreak(); + noecho(); + dialog_clear(); + + return 0; +} + +void set_dialog_backtitle(const char *backtitle) +{ + dlg.backtitle = backtitle; +} + +/* + * End using dialog functions. + */ +void end_dialog(int x, int y) +{ + /* move cursor back to original position */ + move(y, x); + refresh(); + endwin(); +} + +/* Print the title of the dialog. Center the title and truncate + * tile if wider than dialog (- 2 chars). + **/ +void print_title(WINDOW *dialog, const char *title, int width) +{ + if (title) { + int tlen = MIN(width - 2, strlen(title)); + wattrset(dialog, dlg.title.atr); + mvwaddch(dialog, 0, (width - tlen) / 2 - 1, ' '); + mvwaddnstr(dialog, 0, (width - tlen)/2, title, tlen); + waddch(dialog, ' '); + } +} + +/* + * Print a string of text in a window, automatically wrap around to the + * next line if the string is too long to fit on one line. Newline + * characters '\n' are replaced by spaces. We start on a new line + * if there is no room for at least 4 nonblanks following a double-space. + */ +void print_autowrap(WINDOW * win, const char *prompt, int width, int y, int x) +{ + int newl, cur_x, cur_y; + int i, prompt_len, room, wlen; + char tempstr[MAX_LEN + 1], *word, *sp, *sp2; + + strcpy(tempstr, prompt); + + prompt_len = strlen(tempstr); + + /* + * Remove newlines + */ + for (i = 0; i < prompt_len; i++) { + if (tempstr[i] == '\n') + tempstr[i] = ' '; + } + + if (prompt_len <= width - x * 2) { /* If prompt is short */ + wmove(win, y, (width - prompt_len) / 2); + waddstr(win, tempstr); + } else { + cur_x = x; + cur_y = y; + newl = 1; + word = tempstr; + while (word && *word) { + sp = strchr(word, ' '); + if (sp) + *sp++ = 0; + + /* Wrap to next line if either the word does not fit, + or it is the first word of a new sentence, and it is + short, and the next word does not fit. */ + room = width - cur_x; + wlen = strlen(word); + if (wlen > room || + (newl && wlen < 4 && sp + && wlen + 1 + strlen(sp) > room + && (!(sp2 = strchr(sp, ' ')) + || wlen + 1 + (sp2 - sp) > room))) { + cur_y++; + cur_x = x; + } + wmove(win, cur_y, cur_x); + waddstr(win, word); + getyx(win, cur_y, cur_x); + cur_x++; + if (sp && *sp == ' ') { + cur_x++; /* double space */ + while (*++sp == ' ') ; + newl = 1; + } else + newl = 0; + word = sp; + } + } +} + +/* + * Print a button + */ +void print_button(WINDOW * win, const char *label, int y, int x, int selected) +{ + int i, temp; + + wmove(win, y, x); + wattrset(win, selected ? dlg.button_active.atr + : dlg.button_inactive.atr); + waddstr(win, "<"); + temp = strspn(label, " "); + label += temp; + wattrset(win, selected ? dlg.button_label_active.atr + : dlg.button_label_inactive.atr); + for (i = 0; i < temp; i++) + waddch(win, ' '); + wattrset(win, selected ? dlg.button_key_active.atr + : dlg.button_key_inactive.atr); + waddch(win, label[0]); + wattrset(win, selected ? dlg.button_label_active.atr + : dlg.button_label_inactive.atr); + waddstr(win, (char *)label + 1); + wattrset(win, selected ? dlg.button_active.atr + : dlg.button_inactive.atr); + waddstr(win, ">"); + wmove(win, y, x + temp + 1); +} + +/* + * Draw a rectangular box with line drawing characters + */ +void +draw_box(WINDOW * win, int y, int x, int height, int width, + chtype box, chtype border) +{ + int i, j; + + wattrset(win, 0); + for (i = 0; i < height; i++) { + wmove(win, y + i, x); + for (j = 0; j < width; j++) + if (!i && !j) + waddch(win, border | ACS_ULCORNER); + else if (i == height - 1 && !j) + waddch(win, border | ACS_LLCORNER); + else if (!i && j == width - 1) + waddch(win, box | ACS_URCORNER); + else if (i == height - 1 && j == width - 1) + waddch(win, box | ACS_LRCORNER); + else if (!i) + waddch(win, border | ACS_HLINE); + else if (i == height - 1) + waddch(win, box | ACS_HLINE); + else if (!j) + waddch(win, border | ACS_VLINE); + else if (j == width - 1) + waddch(win, box | ACS_VLINE); + else + waddch(win, box | ' '); + } +} + +/* + * Draw shadows along the right and bottom edge to give a more 3D look + * to the boxes + */ +void draw_shadow(WINDOW * win, int y, int x, int height, int width) +{ + int i; + + if (has_colors()) { /* Whether terminal supports color? */ + wattrset(win, dlg.shadow.atr); + wmove(win, y + height, x + 2); + for (i = 0; i < width; i++) + waddch(win, winch(win) & A_CHARTEXT); + for (i = y + 1; i < y + height + 1; i++) { + wmove(win, i, x + width); + waddch(win, winch(win) & A_CHARTEXT); + waddch(win, winch(win) & A_CHARTEXT); + } + wnoutrefresh(win); + } +} + +/* + * Return the position of the first alphabetic character in a string. + */ +int first_alpha(const char *string, const char *exempt) +{ + int i, in_paren = 0, c; + + for (i = 0; i < strlen(string); i++) { + c = tolower(string[i]); + + if (strchr("<[(", c)) + ++in_paren; + if (strchr(">])", c) && in_paren > 0) + --in_paren; + + if ((!in_paren) && isalpha(c) && strchr(exempt, c) == 0) + return i; + } + + return 0; +} + +/* + * ncurses uses ESC to detect escaped char sequences. This resutl in + * a small timeout before ESC is actually delivered to the application. + * lxdialog suggest which is correctly translated to two + * times esc. But then we need to ignore the second esc to avoid stepping + * out one menu too much. Filter away all escaped key sequences since + * keypad(FALSE) turn off ncurses support for escape sequences - and thats + * needed to make notimeout() do as expected. + */ +int on_key_esc(WINDOW *win) +{ + int key; + int key2; + int key3; + + nodelay(win, TRUE); + keypad(win, FALSE); + key = wgetch(win); + key2 = wgetch(win); + do { + key3 = wgetch(win); + } while (key3 != ERR); + nodelay(win, FALSE); + keypad(win, TRUE); + if (key == KEY_ESC && key2 == ERR) + return KEY_ESC; + else if (key != ERR && key != KEY_ESC && key2 == ERR) + ungetch(key); + + return -1; +} + +/* redraw screen in new size */ +int on_key_resize(void) +{ + dialog_clear(); + return KEY_RESIZE; +} + +struct dialog_list *item_cur; +struct dialog_list item_nil; +struct dialog_list *item_head; + +void item_reset(void) +{ + struct dialog_list *p, *next; + + for (p = item_head; p; p = next) { + next = p->next; + free(p); + } + item_head = NULL; + item_cur = &item_nil; +} + +void item_make(const char *fmt, ...) +{ + va_list ap; + struct dialog_list *p = malloc(sizeof(*p)); + + if (item_head) + item_cur->next = p; + else + item_head = p; + item_cur = p; + memset(p, 0, sizeof(*p)); + + va_start(ap, fmt); + vsnprintf(item_cur->node.str, sizeof(item_cur->node.str), fmt, ap); + va_end(ap); +} + +void item_add_str(const char *fmt, ...) +{ + va_list ap; + size_t avail; + + avail = sizeof(item_cur->node.str) - strlen(item_cur->node.str); + + va_start(ap, fmt); + vsnprintf(item_cur->node.str + strlen(item_cur->node.str), + avail, fmt, ap); + item_cur->node.str[sizeof(item_cur->node.str) - 1] = '\0'; + va_end(ap); +} + +void item_set_tag(char tag) +{ + item_cur->node.tag = tag; +} +void item_set_data(void *ptr) +{ + item_cur->node.data = ptr; +} + +void item_set_selected(int val) +{ + item_cur->node.selected = val; +} + +int item_activate_selected(void) +{ + item_foreach() + if (item_is_selected()) + return 1; + return 0; +} + +void *item_data(void) +{ + return item_cur->node.data; +} + +char item_tag(void) +{ + return item_cur->node.tag; +} + +int item_count(void) +{ + int n = 0; + struct dialog_list *p; + + for (p = item_head; p; p = p->next) + n++; + return n; +} + +void item_set(int n) +{ + int i = 0; + item_foreach() + if (i++ == n) + return; +} + +int item_n(void) +{ + int n = 0; + struct dialog_list *p; + + for (p = item_head; p; p = p->next) { + if (p == item_cur) + return n; + n++; + } + return 0; +} + +const char *item_str(void) +{ + return item_cur->node.str; +} + +int item_is_selected(void) +{ + return (item_cur->node.selected != 0); +} + +int item_is_tag(char tag) +{ + return (item_cur->node.tag == tag); +} diff --git a/l4/tool/kconfig/scripts/kconfig/lxdialog/yesno.c b/l4/tool/kconfig/scripts/kconfig/lxdialog/yesno.c new file mode 100644 index 00000000..4e6e8090 --- /dev/null +++ b/l4/tool/kconfig/scripts/kconfig/lxdialog/yesno.c @@ -0,0 +1,114 @@ +/* + * yesno.c -- implements the yes/no box + * + * ORIGINAL AUTHOR: Savio Lam (lam836@cs.cuhk.hk) + * MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap (roadcap@cfw.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "dialog.h" + +/* + * Display termination buttons + */ +static void print_buttons(WINDOW * dialog, int height, int width, int selected) +{ + int x = width / 2 - 10; + int y = height - 2; + + print_button(dialog, gettext(" Yes "), y, x, selected == 0); + print_button(dialog, gettext(" No "), y, x + 13, selected == 1); + + wmove(dialog, y, x + 1 + 13 * selected); + wrefresh(dialog); +} + +/* + * Display a dialog box with two buttons - Yes and No + */ +int dialog_yesno(const char *title, const char *prompt, int height, int width) +{ + int i, x, y, key = 0, button = 0; + WINDOW *dialog; + +do_resize: + if (getmaxy(stdscr) < (height + 4)) + return -ERRDISPLAYTOOSMALL; + if (getmaxx(stdscr) < (width + 4)) + return -ERRDISPLAYTOOSMALL; + + /* center dialog box on screen */ + x = (COLS - width) / 2; + y = (LINES - height) / 2; + + draw_shadow(stdscr, y, x, height, width); + + dialog = newwin(height, width, y, x); + keypad(dialog, TRUE); + + draw_box(dialog, 0, 0, height, width, + dlg.dialog.atr, dlg.border.atr); + wattrset(dialog, dlg.border.atr); + mvwaddch(dialog, height - 3, 0, ACS_LTEE); + for (i = 0; i < width - 2; i++) + waddch(dialog, ACS_HLINE); + wattrset(dialog, dlg.dialog.atr); + waddch(dialog, ACS_RTEE); + + print_title(dialog, title, width); + + wattrset(dialog, dlg.dialog.atr); + print_autowrap(dialog, prompt, width - 2, 1, 3); + + print_buttons(dialog, height, width, 0); + + while (key != KEY_ESC) { + key = wgetch(dialog); + switch (key) { + case 'Y': + case 'y': + delwin(dialog); + return 0; + case 'N': + case 'n': + delwin(dialog); + return 1; + + case TAB: + case KEY_LEFT: + case KEY_RIGHT: + button = ((key == KEY_LEFT ? --button : ++button) < 0) ? 1 : (button > 1 ? 0 : button); + + print_buttons(dialog, height, width, button); + wrefresh(dialog); + break; + case ' ': + case '\n': + delwin(dialog); + return button; + case KEY_ESC: + key = on_key_esc(dialog); + break; + case KEY_RESIZE: + delwin(dialog); + on_key_resize(); + goto do_resize; + } + } + + delwin(dialog); + return key; /* ESC pressed */ +} diff --git a/l4/tool/kconfig/scripts/kconfig/mconf.c b/l4/tool/kconfig/scripts/kconfig/mconf.c new file mode 100644 index 00000000..f606738d --- /dev/null +++ b/l4/tool/kconfig/scripts/kconfig/mconf.c @@ -0,0 +1,882 @@ +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + * + * Introduced single menu mode (show all sub-menus in one large tree). + * 2002-11-06 Petr Baudis + * + * i18n, 2005, Arnaldo Carvalho de Melo + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "lkc.h" +#include "lxdialog/dialog.h" + +static const char mconf_readme[] = N_( +"Overview\n" +"--------\n" +"This interface let you select features and parameters for the build.\n" +"Features can either be built-in, modularized, or ignored. Parameters\n" +"must be entered in as decimal or hexadecimal numbers or text.\n" +"\n" +"Menu items beginning with following braces represent features that\n" +" [ ] can be built in or removed\n" +" < > can be built in, modularized or removed\n" +" { } can be built in or modularized (selected by other feature)\n" +" - - are selected by other feature,\n" +"while *, M or whitespace inside braces means to build in, build as\n" +"a module or to exclude the feature respectively.\n" +"\n" +"To change any of these features, highlight it with the cursor\n" +"keys and press to build it in, to make it a module or\n" +" to removed it. You may also press the to cycle\n" +"through the available options (ie. Y->N->M->Y).\n" +"\n" +"Some additional keyboard hints:\n" +"\n" +"Menus\n" +"----------\n" +"o Use the Up/Down arrow keys (cursor keys) to highlight the item\n" +" you wish to change or submenu wish to select and press .\n" +" Submenus are designated by \"--->\".\n" +"\n" +" Shortcut: Press the option's highlighted letter (hotkey).\n" +" Pressing a hotkey more than once will sequence\n" +" through all visible items which use that hotkey.\n" +"\n" +" You may also use the and keys to scroll\n" +" unseen options into view.\n" +"\n" +"o To exit a menu use the cursor keys to highlight the button\n" +" and press .\n" +"\n" +" Shortcut: Press or or if there is no hotkey\n" +" using those letters. You may press a single , but\n" +" there is a delayed response which you may find annoying.\n" +"\n" +" Also, the and cursor keys will cycle between and\n" +" \n" +"\n" +"\n" +"Data Entry\n" +"-----------\n" +"o Enter the requested information and press \n" +" If you are entering hexadecimal values, it is not necessary to\n" +" add the '0x' prefix to the entry.\n" +"\n" +"o For help, use the or cursor keys to highlight the help option\n" +" and press . You can try as well.\n" +"\n" +"\n" +"Text Box (Help Window)\n" +"--------\n" +"o Use the cursor keys to scroll up/down/left/right. The VI editor\n" +" keys h,j,k,l function here as do and for those\n" +" who are familiar with less and lynx.\n" +"\n" +"o Press , , or to exit.\n" +"\n" +"\n" +"Alternate Configuration Files\n" +"-----------------------------\n" +"Menuconfig supports the use of alternate configuration files for\n" +"those who, for various reasons, find it necessary to switch\n" +"between different configurations.\n" +"\n" +"At the end of the main menu you will find two options. One is\n" +"for saving the current configuration to a file of your choosing.\n" +"The other option is for loading a previously saved alternate\n" +"configuration.\n" +"\n" +"Even if you don't use alternate configuration files, but you\n" +"find during a Menuconfig session that you have completely messed\n" +"up your settings, you may use the \"Load Alternate...\" option to\n" +"restore your previously saved settings from \".config\" without\n" +"restarting Menuconfig.\n" +"\n" +"Other information\n" +"-----------------\n" +"If you use Menuconfig in an XTERM window make sure you have your\n" +"$TERM variable set to point to a xterm definition which supports color.\n" +"Otherwise, Menuconfig will look rather bad. Menuconfig will not\n" +"display correctly in a RXVT window because rxvt displays only one\n" +"intensity of color, bright.\n" +"\n" +"Menuconfig will display larger menus on screens or xterms which are\n" +"set to display more than the standard 25 row by 80 column geometry.\n" +"In order for this to work, the \"stty size\" command must be able to\n" +"display the screen's current row and column geometry. I STRONGLY\n" +"RECOMMEND that you make sure you do NOT have the shell variables\n" +"LINES and COLUMNS exported into your environment. Some distributions\n" +"export those variables via /etc/profile. Some ncurses programs can\n" +"become confused when those variables (LINES & COLUMNS) don't reflect\n" +"the true screen size.\n" +"\n" +"Optional personality available\n" +"------------------------------\n" +"If you prefer to have all of the options listed in a single menu, rather\n" +"than the default multimenu hierarchy, run the menuconfig with\n" +"MENUCONFIG_MODE environment variable set to single_menu. Example:\n" +"\n" +"make MENUCONFIG_MODE=single_menu menuconfig\n" +"\n" +" will then unroll the appropriate category, or enfold it if it\n" +"is already unrolled.\n" +"\n" +"Note that this mode can eventually be a little more CPU expensive\n" +"(especially with a larger number of unrolled categories) than the\n" +"default mode.\n" +"\n" +"Different color themes available\n" +"--------------------------------\n" +"It is possible to select different color themes using the variable\n" +"MENUCONFIG_COLOR. To select a theme use:\n" +"\n" +"make MENUCONFIG_COLOR= menuconfig\n" +"\n" +"Available themes are\n" +" mono => selects colors suitable for monochrome displays\n" +" blackbg => selects a color scheme with black background\n" +" classic => theme with blue background. The classic look\n" +" bluetitle => a LCD friendly version of classic. (default)\n" +"\n"), +menu_instructions[] = N_( + "Arrow keys navigate the menu. " + " selects submenus --->. " + "Highlighted letters are hotkeys. " + "Pressing includes, excludes, modularizes features. " + "Press to exit, for Help, for Search. " + "Legend: [*] built-in [ ] excluded module < > module capable"), +radiolist_instructions[] = N_( + "Use the arrow keys to navigate this window or " + "press the hotkey of the item you wish to select " + "followed by the . " + "Press for additional information about this option."), +inputbox_instructions_int[] = N_( + "Please enter a decimal value. " + "Fractions will not be accepted. " + "Use the key to move from the input field to the buttons below it."), +inputbox_instructions_hex[] = N_( + "Please enter a hexadecimal value. " + "Use the key to move from the input field to the buttons below it."), +inputbox_instructions_string[] = N_( + "Please enter a string value. " + "Use the key to move from the input field to the buttons below it."), +setmod_text[] = N_( + "This feature depends on another which has been configured as a module.\n" + "As a result, this feature will be built as a module."), +load_config_text[] = N_( + "Enter the name of the configuration file you wish to load. " + "Accept the name shown to restore the configuration you " + "last retrieved. Leave blank to abort."), +load_config_help[] = N_( + "\n" + "For various reasons, one may wish to keep several different\n" + "configurations available on a single machine.\n" + "\n" + "If you have saved a previous configuration in a file other than the\n" + "default one, entering its name here will allow you to modify that\n" + "configuration.\n" + "\n" + "If you are uncertain, then you have probably never used alternate\n" + "configuration files. You should therefore leave this blank to abort.\n"), +save_config_text[] = N_( + "Enter a filename to which this configuration should be saved " + "as an alternate. Leave blank to abort."), +save_config_help[] = N_( + "\n" + "For various reasons, one may wish to keep different configurations\n" + "available on a single machine.\n" + "\n" + "Entering a file name here will allow you to later retrieve, modify\n" + "and use the current configuration as an alternate to whatever\n" + "configuration options you have selected at that time.\n" + "\n" + "If you are uncertain what all this means then you should probably\n" + "leave this blank.\n"), +search_help[] = N_( + "\n" + "Search for symbols and display their relations.\n" + "Regular expressions are allowed.\n" + "Example: search for \"^FOO\"\n" + "Result:\n" + "-----------------------------------------------------------------\n" + "Symbol: FOO [=m]\n" + "Prompt: Foo bus is used to drive the bar HW\n" + "Defined at drivers/pci/Kconfig:47\n" + "Depends on: X86_LOCAL_APIC && X86_IO_APIC || IA64\n" + "Location:\n" + " -> Bus options (PCI, PCMCIA, EISA, ISA)\n" + " -> PCI support (PCI [=y])\n" + " -> PCI access mode ( [=y])\n" + "Selects: LIBCRC32\n" + "Selected by: BAR\n" + "-----------------------------------------------------------------\n" + "o The line 'Prompt:' shows the text used in the menu structure for\n" + " this symbol\n" + "o The 'Defined at' line tell at what file / line number the symbol\n" + " is defined\n" + "o The 'Depends on:' line tell what symbols needs to be defined for\n" + " this symbol to be visible in the menu (selectable)\n" + "o The 'Location:' lines tell where in the menu structure this symbol\n" + " is located\n" + " A location followed by a [=y] indicate that this is a selectable\n" + " menu item - and current value is displayed inside brackets.\n" + "o The 'Selects:' line tell what symbol will be automatically\n" + " selected if this symbol is selected (y or m)\n" + "o The 'Selected by' line tell what symbol has selected this symbol\n" + "\n" + "Only relevant lines are shown.\n" + "\n\n" + "Search examples:\n" + "Examples: USB => find all symbols containing USB\n" + " ^USB => find all symbols starting with USB\n" + " USB$ => find all symbols ending with USB\n" + "\n"); + +static int indent; +static struct menu *current_menu; +static int child_count; +static int single_menu_mode; +static int show_all_options; +static int saved_x, saved_y; + +static void conf(struct menu *menu); +static void conf_choice(struct menu *menu); +static void conf_string(struct menu *menu); +static void conf_load(void); +static void conf_save(void); +static void show_textbox(const char *title, const char *text, int r, int c); +static void show_helptext(const char *title, const char *text); +static void show_help(struct menu *menu); + +static char filename[PATH_MAX+1]; +static void set_config_filename(const char *config_filename) +{ + static char menu_backtitle[PATH_MAX+128]; + int size; + + size = snprintf(menu_backtitle, sizeof(menu_backtitle), + "%s - %s", config_filename, rootmenu.prompt->text); + if (size >= sizeof(menu_backtitle)) + menu_backtitle[sizeof(menu_backtitle)-1] = '\0'; + set_dialog_backtitle(menu_backtitle); + + size = snprintf(filename, sizeof(filename), "%s", config_filename); + if (size >= sizeof(filename)) + filename[sizeof(filename)-1] = '\0'; +} + + +static void search_conf(void) +{ + struct symbol **sym_arr; + struct gstr res; + char *dialog_input; + int dres; +again: + dialog_clear(); + dres = dialog_inputbox(_("Search Configuration Parameter"), + _("Enter " CONFIG_ " (sub)string to search for " + "(with or without \"" CONFIG_ "\")"), + 10, 75, ""); + switch (dres) { + case 0: + break; + case 1: + show_helptext(_("Search Configuration"), search_help); + goto again; + default: + return; + } + + /* strip the prefix if necessary */ + dialog_input = dialog_input_result; + if (strncasecmp(dialog_input_result, CONFIG_, strlen(CONFIG_)) == 0) + dialog_input += strlen(CONFIG_); + + sym_arr = sym_re_search(dialog_input); + res = get_relations_str(sym_arr); + free(sym_arr); + show_textbox(_("Search Results"), str_get(&res), 0, 0); + str_free(&res); +} + +static void build_conf(struct menu *menu) +{ + struct symbol *sym; + struct property *prop; + struct menu *child; + int type, tmp, doint = 2; + tristate val; + char ch; + bool visible; + + /* + * note: menu_is_visible() has side effect that it will + * recalc the value of the symbol. + */ + visible = menu_is_visible(menu); + if (show_all_options && !menu_has_prompt(menu)) + return; + else if (!show_all_options && !visible) + return; + + sym = menu->sym; + prop = menu->prompt; + if (!sym) { + if (prop && menu != current_menu) { + const char *prompt = menu_get_prompt(menu); + switch (prop->type) { + case P_MENU: + child_count++; + prompt = _(prompt); + if (single_menu_mode) { + item_make("%s%*c%s", + menu->data ? "-->" : "++>", + indent + 1, ' ', prompt); + } else + item_make(" %*c%s --->", indent + 1, ' ', prompt); + + item_set_tag('m'); + item_set_data(menu); + if (single_menu_mode && menu->data) + goto conf_childs; + return; + case P_COMMENT: + if (prompt) { + child_count++; + item_make(" %*c*** %s ***", indent + 1, ' ', _(prompt)); + item_set_tag(':'); + item_set_data(menu); + } + break; + default: + if (prompt) { + child_count++; + item_make("---%*c%s", indent + 1, ' ', _(prompt)); + item_set_tag(':'); + item_set_data(menu); + } + } + } else + doint = 0; + goto conf_childs; + } + + type = sym_get_type(sym); + if (sym_is_choice(sym)) { + struct symbol *def_sym = sym_get_choice_value(sym); + struct menu *def_menu = NULL; + + child_count++; + for (child = menu->list; child; child = child->next) { + if (menu_is_visible(child) && child->sym == def_sym) + def_menu = child; + } + + val = sym_get_tristate_value(sym); + if (sym_is_changable(sym)) { + switch (type) { + case S_BOOLEAN: + item_make("[%c]", val == no ? ' ' : '*'); + break; + case S_TRISTATE: + switch (val) { + case yes: ch = '*'; break; + case mod: ch = 'M'; break; + default: ch = ' '; break; + } + item_make("<%c>", ch); + break; + } + item_set_tag('t'); + item_set_data(menu); + } else { + item_make(" "); + item_set_tag(def_menu ? 't' : ':'); + item_set_data(menu); + } + + item_add_str("%*c%s", indent + 1, ' ', _(menu_get_prompt(menu))); + if (val == yes) { + if (def_menu) { + item_add_str(" (%s)", _(menu_get_prompt(def_menu))); + item_add_str(" --->"); + if (def_menu->list) { + indent += 2; + build_conf(def_menu); + indent -= 2; + } + } + return; + } + } else { + if (menu == current_menu) { + item_make("---%*c%s", indent + 1, ' ', _(menu_get_prompt(menu))); + item_set_tag(':'); + item_set_data(menu); + goto conf_childs; + } + child_count++; + val = sym_get_tristate_value(sym); + if (sym_is_choice_value(sym) && val == yes) { + item_make(" "); + item_set_tag(':'); + item_set_data(menu); + } else { + switch (type) { + case S_BOOLEAN: + if (sym_is_changable(sym)) + item_make("[%c]", val == no ? ' ' : '*'); + else + item_make("-%c-", val == no ? ' ' : '*'); + item_set_tag('t'); + item_set_data(menu); + break; + case S_TRISTATE: + switch (val) { + case yes: ch = '*'; break; + case mod: ch = 'M'; break; + default: ch = ' '; break; + } + if (sym_is_changable(sym)) { + if (sym->rev_dep.tri == mod) + item_make("{%c}", ch); + else + item_make("<%c>", ch); + } else + item_make("-%c-", ch); + item_set_tag('t'); + item_set_data(menu); + break; + default: + tmp = 2 + strlen(sym_get_string_value(sym)); /* () = 2 */ + item_make("(%s)", sym_get_string_value(sym)); + tmp = indent - tmp + 4; + if (tmp < 0) + tmp = 0; + item_add_str("%*c%s%s", tmp, ' ', _(menu_get_prompt(menu)), + (sym_has_value(sym) || !sym_is_changable(sym)) ? + "" : _(" (NEW)")); + item_set_tag('s'); + item_set_data(menu); + goto conf_childs; + } + } + item_add_str("%*c%s%s", indent + 1, ' ', _(menu_get_prompt(menu)), + (sym_has_value(sym) || !sym_is_changable(sym)) ? + "" : _(" (NEW)")); + if (menu->prompt->type == P_MENU) { + item_add_str(" --->"); + return; + } + } + +conf_childs: + indent += doint; + for (child = menu->list; child; child = child->next) + build_conf(child); + indent -= doint; +} + +static void conf(struct menu *menu) +{ + struct menu *submenu; + const char *prompt = menu_get_prompt(menu); + struct symbol *sym; + struct menu *active_menu = NULL; + int res; + int s_scroll = 0; + + while (1) { + item_reset(); + current_menu = menu; + build_conf(menu); + if (!child_count) + break; + if (menu == &rootmenu) { + item_make("--- "); + item_set_tag(':'); + item_make(_(" Load an Alternate Configuration File")); + item_set_tag('L'); + item_make(_(" Save an Alternate Configuration File")); + item_set_tag('S'); + } + dialog_clear(); + res = dialog_menu(prompt ? _(prompt) : _("Main Menu"), + _(menu_instructions), + active_menu, &s_scroll); + if (res == 1 || res == KEY_ESC || res == -ERRDISPLAYTOOSMALL) + break; + if (!item_activate_selected()) + continue; + if (!item_tag()) + continue; + + submenu = item_data(); + active_menu = item_data(); + if (submenu) + sym = submenu->sym; + else + sym = NULL; + + switch (res) { + case 0: + switch (item_tag()) { + case 'm': + if (single_menu_mode) + submenu->data = (void *) (long) !submenu->data; + else + conf(submenu); + break; + case 't': + if (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes) + conf_choice(submenu); + else if (submenu->prompt->type == P_MENU) + conf(submenu); + break; + case 's': + conf_string(submenu); + break; + case 'L': + conf_load(); + break; + case 'S': + conf_save(); + break; + } + break; + case 2: + if (sym) + show_help(submenu); + else + show_helptext(_("README"), _(mconf_readme)); + break; + case 3: + if (item_is_tag('t')) { + if (sym_set_tristate_value(sym, yes)) + break; + if (sym_set_tristate_value(sym, mod)) + show_textbox(NULL, setmod_text, 6, 74); + } + break; + case 4: + if (item_is_tag('t')) + sym_set_tristate_value(sym, no); + break; + case 5: + if (item_is_tag('t')) + sym_set_tristate_value(sym, mod); + break; + case 6: + if (item_is_tag('t')) + sym_toggle_tristate_value(sym); + else if (item_is_tag('m')) + conf(submenu); + break; + case 7: + search_conf(); + break; + case 8: + show_all_options = !show_all_options; + break; + } + } +} + +static void show_textbox(const char *title, const char *text, int r, int c) +{ + dialog_clear(); + dialog_textbox(title, text, r, c); +} + +static void show_helptext(const char *title, const char *text) +{ + show_textbox(title, text, 0, 0); +} + +static void show_help(struct menu *menu) +{ + struct gstr help = str_new(); + + help.max_width = getmaxx(stdscr) - 10; + menu_get_ext_help(menu, &help); + + show_helptext(_(menu_get_prompt(menu)), str_get(&help)); + str_free(&help); +} + +static void conf_choice(struct menu *menu) +{ + const char *prompt = _(menu_get_prompt(menu)); + struct menu *child; + struct symbol *active; + + active = sym_get_choice_value(menu->sym); + while (1) { + int res; + int selected; + item_reset(); + + current_menu = menu; + for (child = menu->list; child; child = child->next) { + if (!menu_is_visible(child)) + continue; + if (child->sym) + item_make("%s", _(menu_get_prompt(child))); + else { + item_make("*** %s ***", _(menu_get_prompt(child))); + item_set_tag(':'); + } + item_set_data(child); + if (child->sym == active) + item_set_selected(1); + if (child->sym == sym_get_choice_value(menu->sym)) + item_set_tag('X'); + } + dialog_clear(); + res = dialog_checklist(prompt ? _(prompt) : _("Main Menu"), + _(radiolist_instructions), + 15, 70, 6); + selected = item_activate_selected(); + switch (res) { + case 0: + if (selected) { + child = item_data(); + if (!child->sym) + break; + + sym_set_tristate_value(child->sym, yes); + } + return; + case 1: + if (selected) { + child = item_data(); + show_help(child); + active = child->sym; + } else + show_help(menu); + break; + case KEY_ESC: + return; + case -ERRDISPLAYTOOSMALL: + return; + } + } +} + +static void conf_string(struct menu *menu) +{ + const char *prompt = menu_get_prompt(menu); + + while (1) { + int res; + const char *heading; + + switch (sym_get_type(menu->sym)) { + case S_INT: + heading = _(inputbox_instructions_int); + break; + case S_HEX: + heading = _(inputbox_instructions_hex); + break; + case S_STRING: + heading = _(inputbox_instructions_string); + break; + default: + heading = _("Internal mconf error!"); + } + dialog_clear(); + res = dialog_inputbox(prompt ? _(prompt) : _("Main Menu"), + heading, 10, 75, + sym_get_string_value(menu->sym)); + switch (res) { + case 0: + if (sym_set_string_value(menu->sym, dialog_input_result)) + return; + show_textbox(NULL, _("You have made an invalid entry."), 5, 43); + break; + case 1: + show_help(menu); + break; + case KEY_ESC: + return; + } + } +} + +static void conf_load(void) +{ + + while (1) { + int res; + dialog_clear(); + res = dialog_inputbox(NULL, load_config_text, + 11, 55, filename); + switch(res) { + case 0: + if (!dialog_input_result[0]) + return; + if (!conf_read(dialog_input_result)) { + set_config_filename(dialog_input_result); + sym_set_change_count(1); + return; + } + show_textbox(NULL, _("File does not exist!"), 5, 38); + break; + case 1: + show_helptext(_("Load Alternate Configuration"), load_config_help); + break; + case KEY_ESC: + return; + } + } +} + +static void conf_save(void) +{ + while (1) { + int res; + dialog_clear(); + res = dialog_inputbox(NULL, save_config_text, + 11, 55, filename); + switch(res) { + case 0: + if (!dialog_input_result[0]) + return; + if (!conf_write(dialog_input_result)) { + set_config_filename(dialog_input_result); + return; + } + show_textbox(NULL, _("Can't create file! Probably a nonexistent directory."), 5, 60); + break; + case 1: + show_helptext(_("Save Alternate Configuration"), save_config_help); + break; + case KEY_ESC: + return; + } + } +} + +static int handle_exit(void) +{ + int res; + + dialog_clear(); + if (conf_get_changed()) + res = dialog_yesno(NULL, + _("Do you wish to save your new configuration ?\n" + " to continue."), + 6, 60); + else + res = -1; + + end_dialog(saved_x, saved_y); + + switch (res) { + case 0: + if (conf_write(filename)) { + fprintf(stderr, _("\n\n" + "Error while writing of the configuration.\n" + "Your configuration changes were NOT saved." + "\n\n")); + return 1; + } + /* fall through */ + case -1: + printf(_("\n\n" + "*** End of the configuration.\n" + "*** Execute 'make' to start the build or try 'make help'." + "\n\n")); + res = 0; + break; + default: + fprintf(stderr, _("\n\n" + "Your configuration changes were NOT saved." + "\n\n")); + if (res != KEY_ESC) + res = 0; + } + + return res; +} + +static void sig_handler(int signo) +{ + exit(handle_exit()); +} + +int main(int ac, char **av) +{ + char *mode; + int res; + + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + + signal(SIGINT, sig_handler); + + conf_parse(av[1]); + conf_read(NULL); + + mode = getenv("MENUCONFIG_MODE"); + if (mode) { + if (!strcasecmp(mode, "single_menu")) + single_menu_mode = 1; + } + + initscr(); + + getyx(stdscr, saved_y, saved_x); + if (init_dialog(NULL)) { + fprintf(stderr, N_("Your display is too small to run Menuconfig!\n")); + fprintf(stderr, N_("It must be at least 19 lines by 80 columns.\n")); + return 1; + } + + set_config_filename(conf_get_configname()); + do { + conf(&rootmenu); + res = handle_exit(); + } while (res == KEY_ESC); + + return res; +} + diff --git a/l4/tool/kconfig/scripts/kconfig/menu.c b/l4/tool/kconfig/scripts/kconfig/menu.c new file mode 100644 index 00000000..8c2a97e6 --- /dev/null +++ b/l4/tool/kconfig/scripts/kconfig/menu.c @@ -0,0 +1,607 @@ +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +#include +#include +#include +#include + +#include "lkc.h" + +static const char nohelp_text[] = "There is no help available for this option."; + +struct menu rootmenu; +static struct menu **last_entry_ptr; + +struct file *file_list; +struct file *current_file; + +void menu_warn(struct menu *menu, const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + fprintf(stderr, "%s:%d:warning: ", menu->file->name, menu->lineno); + vfprintf(stderr, fmt, ap); + fprintf(stderr, "\n"); + va_end(ap); +} + +static void prop_warn(struct property *prop, const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + fprintf(stderr, "%s:%d:warning: ", prop->file->name, prop->lineno); + vfprintf(stderr, fmt, ap); + fprintf(stderr, "\n"); + va_end(ap); +} + +void _menu_init(void) +{ + current_entry = current_menu = &rootmenu; + last_entry_ptr = &rootmenu.list; +} + +void menu_add_entry(struct symbol *sym) +{ + struct menu *menu; + + menu = malloc(sizeof(*menu)); + memset(menu, 0, sizeof(*menu)); + menu->sym = sym; + menu->parent = current_menu; + menu->file = current_file; + menu->lineno = zconf_lineno(); + + *last_entry_ptr = menu; + last_entry_ptr = &menu->next; + current_entry = menu; + if (sym) + menu_add_symbol(P_SYMBOL, sym, NULL); +} + +void menu_end_entry(void) +{ +} + +struct menu *menu_add_menu(void) +{ + menu_end_entry(); + last_entry_ptr = ¤t_entry->list; + return current_menu = current_entry; +} + +void menu_end_menu(void) +{ + last_entry_ptr = ¤t_menu->next; + current_menu = current_menu->parent; +} + +static struct expr *menu_check_dep(struct expr *e) +{ + if (!e) + return e; + + switch (e->type) { + case E_NOT: + e->left.expr = menu_check_dep(e->left.expr); + break; + case E_OR: + case E_AND: + e->left.expr = menu_check_dep(e->left.expr); + e->right.expr = menu_check_dep(e->right.expr); + break; + case E_SYMBOL: + /* change 'm' into 'm' && MODULES */ + if (e->left.sym == &symbol_mod) + return expr_alloc_and(e, expr_alloc_symbol(modules_sym)); + break; + default: + break; + } + return e; +} + +void menu_add_dep(struct expr *dep) +{ + current_entry->dep = expr_alloc_and(current_entry->dep, menu_check_dep(dep)); +} + +void menu_set_type(int type) +{ + struct symbol *sym = current_entry->sym; + + if (sym->type == type) + return; + if (sym->type == S_UNKNOWN) { + sym->type = type; + return; + } + menu_warn(current_entry, "type of '%s' redefined from '%s' to '%s'", + sym->name ? sym->name : "", + sym_type_name(sym->type), sym_type_name(type)); +} + +struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *expr, struct expr *dep) +{ + struct property *prop = prop_alloc(type, current_entry->sym); + + prop->menu = current_entry; + prop->expr = expr; + prop->visible.expr = menu_check_dep(dep); + + if (prompt) { + if (isspace(*prompt)) { + prop_warn(prop, "leading whitespace ignored"); + while (isspace(*prompt)) + prompt++; + } + if (current_entry->prompt && current_entry != &rootmenu) + prop_warn(prop, "prompt redefined"); + + /* Apply all upper menus' visibilities to actual prompts. */ + if(type == P_PROMPT) { + struct menu *menu = current_entry; + + while ((menu = menu->parent) != NULL) { + if (!menu->visibility) + continue; + prop->visible.expr + = expr_alloc_and(prop->visible.expr, + menu->visibility); + } + } + + current_entry->prompt = prop; + } + prop->text = prompt; + + return prop; +} + +struct property *menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep) +{ + return menu_add_prop(type, prompt, NULL, dep); +} + +void menu_add_visibility(struct expr *expr) +{ + current_entry->visibility = expr_alloc_and(current_entry->visibility, + expr); +} + +void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep) +{ + menu_add_prop(type, NULL, expr, dep); +} + +void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep) +{ + menu_add_prop(type, NULL, expr_alloc_symbol(sym), dep); +} + +void menu_add_option(int token, char *arg) +{ + struct property *prop; + + switch (token) { + case T_OPT_MODULES: + prop = prop_alloc(P_DEFAULT, modules_sym); + prop->expr = expr_alloc_symbol(current_entry->sym); + break; + case T_OPT_DEFCONFIG_LIST: + if (!sym_defconfig_list) + sym_defconfig_list = current_entry->sym; + else if (sym_defconfig_list != current_entry->sym) + zconf_error("trying to redefine defconfig symbol"); + break; + case T_OPT_ENV: + prop_add_env(arg); + break; + } +} + +static int menu_validate_number(struct symbol *sym, struct symbol *sym2) +{ + return sym2->type == S_INT || sym2->type == S_HEX || + (sym2->type == S_UNKNOWN && sym_string_valid(sym, sym2->name)); +} + +static void sym_check_prop(struct symbol *sym) +{ + struct property *prop; + struct symbol *sym2; + for (prop = sym->prop; prop; prop = prop->next) { + switch (prop->type) { + case P_DEFAULT: + if ((sym->type == S_STRING || sym->type == S_INT || sym->type == S_HEX) && + prop->expr->type != E_SYMBOL) + prop_warn(prop, + "default for config symbol '%s'" + " must be a single symbol", sym->name); + if (prop->expr->type != E_SYMBOL) + break; + sym2 = prop_get_symbol(prop); + if (sym->type == S_HEX || sym->type == S_INT) { + if (!menu_validate_number(sym, sym2)) + prop_warn(prop, + "'%s': number is invalid", + sym->name); + } + break; + case P_SELECT: + sym2 = prop_get_symbol(prop); + if (sym->type != S_BOOLEAN && sym->type != S_TRISTATE) + prop_warn(prop, + "config symbol '%s' uses select, but is " + "not boolean or tristate", sym->name); + else if (sym2->type != S_UNKNOWN && + sym2->type != S_BOOLEAN && + sym2->type != S_TRISTATE) + prop_warn(prop, + "'%s' has wrong type. 'select' only " + "accept arguments of boolean and " + "tristate type", sym2->name); + break; + case P_RANGE: + if (sym->type != S_INT && sym->type != S_HEX) + prop_warn(prop, "range is only allowed " + "for int or hex symbols"); + if (!menu_validate_number(sym, prop->expr->left.sym) || + !menu_validate_number(sym, prop->expr->right.sym)) + prop_warn(prop, "range is invalid"); + break; + default: + ; + } + } +} + +void menu_finalize(struct menu *parent) +{ + struct menu *menu, *last_menu; + struct symbol *sym; + struct property *prop; + struct expr *parentdep, *basedep, *dep, *dep2, **ep; + + sym = parent->sym; + if (parent->list) { + if (sym && sym_is_choice(sym)) { + if (sym->type == S_UNKNOWN) { + /* find the first choice value to find out choice type */ + current_entry = parent; + for (menu = parent->list; menu; menu = menu->next) { + if (menu->sym && menu->sym->type != S_UNKNOWN) { + menu_set_type(menu->sym->type); + break; + } + } + } + /* set the type of the remaining choice values */ + for (menu = parent->list; menu; menu = menu->next) { + current_entry = menu; + if (menu->sym && menu->sym->type == S_UNKNOWN) + menu_set_type(sym->type); + } + parentdep = expr_alloc_symbol(sym); + } else if (parent->prompt) + parentdep = parent->prompt->visible.expr; + else + parentdep = parent->dep; + + for (menu = parent->list; menu; menu = menu->next) { + basedep = expr_transform(menu->dep); + basedep = expr_alloc_and(expr_copy(parentdep), basedep); + basedep = expr_eliminate_dups(basedep); + menu->dep = basedep; + if (menu->sym) + prop = menu->sym->prop; + else + prop = menu->prompt; + for (; prop; prop = prop->next) { + if (prop->menu != menu) + continue; + dep = expr_transform(prop->visible.expr); + dep = expr_alloc_and(expr_copy(basedep), dep); + dep = expr_eliminate_dups(dep); + if (menu->sym && menu->sym->type != S_TRISTATE) + dep = expr_trans_bool(dep); + prop->visible.expr = dep; + if (prop->type == P_SELECT) { + struct symbol *es = prop_get_symbol(prop); + es->rev_dep.expr = expr_alloc_or(es->rev_dep.expr, + expr_alloc_and(expr_alloc_symbol(menu->sym), expr_copy(dep))); + } + } + } + for (menu = parent->list; menu; menu = menu->next) + menu_finalize(menu); + } else if (sym) { + basedep = parent->prompt ? parent->prompt->visible.expr : NULL; + basedep = expr_trans_compare(basedep, E_UNEQUAL, &symbol_no); + basedep = expr_eliminate_dups(expr_transform(basedep)); + last_menu = NULL; + for (menu = parent->next; menu; menu = menu->next) { + dep = menu->prompt ? menu->prompt->visible.expr : menu->dep; + if (!expr_contains_symbol(dep, sym)) + break; + if (expr_depends_symbol(dep, sym)) + goto next; + dep = expr_trans_compare(dep, E_UNEQUAL, &symbol_no); + dep = expr_eliminate_dups(expr_transform(dep)); + dep2 = expr_copy(basedep); + expr_eliminate_eq(&dep, &dep2); + expr_free(dep); + if (!expr_is_yes(dep2)) { + expr_free(dep2); + break; + } + expr_free(dep2); + next: + menu_finalize(menu); + menu->parent = parent; + last_menu = menu; + } + if (last_menu) { + parent->list = parent->next; + parent->next = last_menu->next; + last_menu->next = NULL; + } + + sym->dir_dep.expr = expr_alloc_or(sym->dir_dep.expr, parent->dep); + } + for (menu = parent->list; menu; menu = menu->next) { + if (sym && sym_is_choice(sym) && + menu->sym && !sym_is_choice_value(menu->sym)) { + current_entry = menu; + menu->sym->flags |= SYMBOL_CHOICEVAL; + if (!menu->prompt) + menu_warn(menu, "choice value must have a prompt"); + for (prop = menu->sym->prop; prop; prop = prop->next) { + if (prop->type == P_DEFAULT) + prop_warn(prop, "defaults for choice " + "values not supported"); + if (prop->menu == menu) + continue; + if (prop->type == P_PROMPT && + prop->menu->parent->sym != sym) + prop_warn(prop, "choice value used outside its choice group"); + } + /* Non-tristate choice values of tristate choices must + * depend on the choice being set to Y. The choice + * values' dependencies were propagated to their + * properties above, so the change here must be re- + * propagated. + */ + if (sym->type == S_TRISTATE && menu->sym->type != S_TRISTATE) { + basedep = expr_alloc_comp(E_EQUAL, sym, &symbol_yes); + menu->dep = expr_alloc_and(basedep, menu->dep); + for (prop = menu->sym->prop; prop; prop = prop->next) { + if (prop->menu != menu) + continue; + prop->visible.expr = expr_alloc_and(expr_copy(basedep), + prop->visible.expr); + } + } + menu_add_symbol(P_CHOICE, sym, NULL); + prop = sym_get_choice_prop(sym); + for (ep = &prop->expr; *ep; ep = &(*ep)->left.expr) + ; + *ep = expr_alloc_one(E_LIST, NULL); + (*ep)->right.sym = menu->sym; + } + if (menu->list && (!menu->prompt || !menu->prompt->text)) { + for (last_menu = menu->list; ; last_menu = last_menu->next) { + last_menu->parent = parent; + if (!last_menu->next) + break; + } + last_menu->next = menu->next; + menu->next = menu->list; + menu->list = NULL; + } + } + + if (sym && !(sym->flags & SYMBOL_WARNED)) { + if (sym->type == S_UNKNOWN) + menu_warn(parent, "config symbol defined without type"); + + if (sym_is_choice(sym) && !parent->prompt) + menu_warn(parent, "choice must have a prompt"); + + /* Check properties connected to this symbol */ + sym_check_prop(sym); + sym->flags |= SYMBOL_WARNED; + } + + if (sym && !sym_is_optional(sym) && parent->prompt) { + sym->rev_dep.expr = expr_alloc_or(sym->rev_dep.expr, + expr_alloc_and(parent->prompt->visible.expr, + expr_alloc_symbol(&symbol_mod))); + } +} + +bool menu_has_prompt(struct menu *menu) +{ + if (!menu->prompt) + return false; + return true; +} + +bool menu_is_visible(struct menu *menu) +{ + struct menu *child; + struct symbol *sym; + tristate visible; + + if (!menu->prompt) + return false; + + if (menu->visibility) { + if (expr_calc_value(menu->visibility) == no) + return no; + } + + sym = menu->sym; + if (sym) { + sym_calc_value(sym); + visible = menu->prompt->visible.tri; + } else + visible = menu->prompt->visible.tri = expr_calc_value(menu->prompt->visible.expr); + + if (visible != no) + return true; + + if (!sym || sym_get_tristate_value(menu->sym) == no) + return false; + + for (child = menu->list; child; child = child->next) { + if (menu_is_visible(child)) { + if (sym) + sym->flags |= SYMBOL_DEF_USER; + return true; + } + } + + return false; +} + +const char *menu_get_prompt(struct menu *menu) +{ + if (menu->prompt) + return menu->prompt->text; + else if (menu->sym) + return menu->sym->name; + return NULL; +} + +struct menu *menu_get_root_menu(struct menu *menu) +{ + return &rootmenu; +} + +struct menu *menu_get_parent_menu(struct menu *menu) +{ + enum prop_type type; + + for (; menu != &rootmenu; menu = menu->parent) { + type = menu->prompt ? menu->prompt->type : 0; + if (type == P_MENU) + break; + } + return menu; +} + +bool menu_has_help(struct menu *menu) +{ + return menu->help != NULL; +} + +const char *menu_get_help(struct menu *menu) +{ + if (menu->help) + return menu->help; + else + return ""; +} + +static void get_prompt_str(struct gstr *r, struct property *prop) +{ + int i, j; + struct menu *submenu[8], *menu; + + str_printf(r, _("Prompt: %s\n"), _(prop->text)); + str_printf(r, _(" Defined at %s:%d\n"), prop->menu->file->name, + prop->menu->lineno); + if (!expr_is_yes(prop->visible.expr)) { + str_append(r, _(" Depends on: ")); + expr_gstr_print(prop->visible.expr, r); + str_append(r, "\n"); + } + menu = prop->menu->parent; + for (i = 0; menu != &rootmenu && i < 8; menu = menu->parent) + submenu[i++] = menu; + if (i > 0) { + str_printf(r, _(" Location:\n")); + for (j = 4; --i >= 0; j += 2) { + menu = submenu[i]; + str_printf(r, "%*c-> %s", j, ' ', _(menu_get_prompt(menu))); + if (menu->sym) { + str_printf(r, " (%s [=%s])", menu->sym->name ? + menu->sym->name : _(""), + sym_get_string_value(menu->sym)); + } + str_append(r, "\n"); + } + } +} + +void get_symbol_str(struct gstr *r, struct symbol *sym) +{ + bool hit; + struct property *prop; + + if (sym && sym->name) { + str_printf(r, "Symbol: %s [=%s]\n", sym->name, + sym_get_string_value(sym)); + str_printf(r, "Type : %s\n", sym_type_name(sym->type)); + if (sym->type == S_INT || sym->type == S_HEX) { + prop = sym_get_range_prop(sym); + if (prop) { + str_printf(r, "Range : "); + expr_gstr_print(prop->expr, r); + str_append(r, "\n"); + } + } + } + for_all_prompts(sym, prop) + get_prompt_str(r, prop); + hit = false; + for_all_properties(sym, prop, P_SELECT) { + if (!hit) { + str_append(r, " Selects: "); + hit = true; + } else + str_printf(r, " && "); + expr_gstr_print(prop->expr, r); + } + if (hit) + str_append(r, "\n"); + if (sym->rev_dep.expr) { + str_append(r, _(" Selected by: ")); + expr_gstr_print(sym->rev_dep.expr, r); + str_append(r, "\n"); + } + str_append(r, "\n\n"); +} + +struct gstr get_relations_str(struct symbol **sym_arr) +{ + struct symbol *sym; + struct gstr res = str_new(); + int i; + + for (i = 0; sym_arr && (sym = sym_arr[i]); i++) + get_symbol_str(&res, sym); + if (!i) + str_append(&res, _("No matches found.\n")); + return res; +} + + +void menu_get_ext_help(struct menu *menu, struct gstr *help) +{ + struct symbol *sym = menu->sym; + const char *help_text = nohelp_text; + + if (menu_has_help(menu)) { + if (sym->name) + str_printf(help, "%s%s:\n\n", CONFIG_, sym->name); + help_text = menu_get_help(menu); + } + str_printf(help, "%s\n", _(help_text)); + if (sym) + get_symbol_str(help, sym); +} diff --git a/l4/tool/kconfig/scripts/kconfig/nconf.c b/l4/tool/kconfig/scripts/kconfig/nconf.c new file mode 100644 index 00000000..8c0eb659 --- /dev/null +++ b/l4/tool/kconfig/scripts/kconfig/nconf.c @@ -0,0 +1,1546 @@ +/* + * Copyright (C) 2008 Nir Tzachar + +#include "lkc.h" +#include "nconf.h" +#include + +static const char nconf_readme[] = N_( +"Overview\n" +"--------\n" +"This interface let you select features and parameters for the build.\n" +"Features can either be built-in, modularized, or ignored. Parameters\n" +"must be entered in as decimal or hexadecimal numbers or text.\n" +"\n" +"Menu items beginning with following braces represent features that\n" +" [ ] can be built in or removed\n" +" < > can be built in, modularized or removed\n" +" { } can be built in or modularized (selected by other feature)\n" +" - - are selected by other feature,\n" +" XXX cannot be selected. Use Symbol Info to find out why,\n" +"while *, M or whitespace inside braces means to build in, build as\n" +"a module or to exclude the feature respectively.\n" +"\n" +"To change any of these features, highlight it with the cursor\n" +"keys and press to build it in, to make it a module or\n" +" to removed it. You may also press the to cycle\n" +"through the available options (ie. Y->N->M->Y).\n" +"\n" +"Some additional keyboard hints:\n" +"\n" +"Menus\n" +"----------\n" +"o Use the Up/Down arrow keys (cursor keys) to highlight the item\n" +" you wish to change use or . Goto submenu by \n" +" pressing of . Use or to go back.\n" +" Submenus are designated by \"--->\".\n" +"\n" +" Searching: pressing '/' triggers interactive search mode.\n" +" nconfig performs a case insensitive search for the string\n" +" in the menu prompts (no regex support).\n" +" Pressing the up/down keys highlights the previous/next\n" +" matching item. Backspace removes one character from the\n" +" match string. Pressing either '/' again or ESC exits\n" +" search mode. All other keys behave normally.\n" +"\n" +" You may also use the and keys to scroll\n" +" unseen options into view.\n" +"\n" +"o To exit a menu use the just press or .\n" +"\n" +"o To get help with an item, press \n" +" Shortcut: Press or .\n" +"\n" +"\n" +"Radiolists (Choice lists)\n" +"-----------\n" +"o Use the cursor keys to select the option you wish to set and press\n" +" or the .\n" +"\n" +" Shortcut: Press the first letter of the option you wish to set then\n" +" press or .\n" +"\n" +"o To see available help for the item, press \n" +" Shortcut: Press or .\n" +"\n" +"\n" +"Data Entry\n" +"-----------\n" +"o Enter the requested information and press \n" +" If you are entering hexadecimal values, it is not necessary to\n" +" add the '0x' prefix to the entry.\n" +"\n" +"o For help, press .\n" +"\n" +"\n" +"Text Box (Help Window)\n" +"--------\n" +"o Use the cursor keys to scroll up/down/left/right. The VI editor\n" +" keys h,j,k,l function here as do for those\n" +" who are familiar with less and lynx.\n" +"\n" +"o Press , , , or to exit.\n" +"\n" +"\n" +"Alternate Configuration Files\n" +"-----------------------------\n" +"nconfig supports the use of alternate configuration files for\n" +"those who, for various reasons, find it necessary to switch\n" +"between different configurations.\n" +"\n" +"At the end of the main menu you will find two options. One is\n" +"for saving the current configuration to a file of your choosing.\n" +"The other option is for loading a previously saved alternate\n" +"configuration.\n" +"\n" +"Even if you don't use alternate configuration files, but you\n" +"find during a nconfig session that you have completely messed\n" +"up your settings, you may use the \"Load Alternate...\" option to\n" +"restore your previously saved settings from \".config\" without\n" +"restarting nconfig.\n" +"\n" +"Other information\n" +"-----------------\n" +"If you use nconfig in an XTERM window make sure you have your\n" +"$TERM variable set to point to a xterm definition which supports color.\n" +"Otherwise, nconfig will look rather bad. nconfig will not\n" +"display correctly in a RXVT window because rxvt displays only one\n" +"intensity of color, bright.\n" +"\n" +"nconfig will display larger menus on screens or xterms which are\n" +"set to display more than the standard 25 row by 80 column geometry.\n" +"In order for this to work, the \"stty size\" command must be able to\n" +"display the screen's current row and column geometry. I STRONGLY\n" +"RECOMMEND that you make sure you do NOT have the shell variables\n" +"LINES and COLUMNS exported into your environment. Some distributions\n" +"export those variables via /etc/profile. Some ncurses programs can\n" +"become confused when those variables (LINES & COLUMNS) don't reflect\n" +"the true screen size.\n" +"\n" +"Optional personality available\n" +"------------------------------\n" +"If you prefer to have all of the options listed in a single menu, rather\n" +"than the default multimenu hierarchy, run the nconfig with NCONFIG_MODE\n" +"environment variable set to single_menu. Example:\n" +"\n" +"make NCONFIG_MODE=single_menu nconfig\n" +"\n" +" will then unroll the appropriate category, or enfold it if it\n" +"is already unrolled.\n" +"\n" +"Note that this mode can eventually be a little more CPU expensive\n" +"(especially with a larger number of unrolled categories) than the\n" +"default mode.\n" +"\n"), +menu_no_f_instructions[] = N_( +" You do not have function keys support. Please follow the\n" +" following instructions:\n" +" Arrow keys navigate the menu.\n" +" or selects submenus --->.\n" +" Capital Letters are hotkeys.\n" +" Pressing includes, excludes, modularizes features.\n" +" Pressing SpaceBar toggles between the above options.\n" +" Press or to go back one menu,\n" +" or for Help, for Search.\n" +" <1> is interchangeable with , <2> with , etc.\n" +" Legend: [*] built-in [ ] excluded module < > module capable.\n" +" always leaves the current window.\n"), +menu_instructions[] = N_( +" Arrow keys navigate the menu.\n" +" or selects submenus --->.\n" +" Capital Letters are hotkeys.\n" +" Pressing includes, excludes, modularizes features.\n" +" Pressing SpaceBar toggles between the above options\n" +" Press , or to go back one menu,\n" +" , or for Help, for Search.\n" +" <1> is interchangeable with , <2> with , etc.\n" +" Legend: [*] built-in [ ] excluded module < > module capable.\n" +" always leaves the current window\n"), +radiolist_instructions[] = N_( +" Use the arrow keys to navigate this window or\n" +" press the hotkey of the item you wish to select\n" +" followed by the .\n" +" Press , or for additional information about this option.\n"), +inputbox_instructions_int[] = N_( +"Please enter a decimal value.\n" +"Fractions will not be accepted.\n" +"Press to accept, to cancel."), +inputbox_instructions_hex[] = N_( +"Please enter a hexadecimal value.\n" +"Press to accept, to cancel."), +inputbox_instructions_string[] = N_( +"Please enter a string value.\n" +"Press to accept, to cancel."), +setmod_text[] = N_( +"This feature depends on another which\n" +"has been configured as a module.\n" +"As a result, this feature will be built as a module."), +load_config_text[] = N_( +"Enter the name of the configuration file you wish to load.\n" +"Accept the name shown to restore the configuration you\n" +"last retrieved. Leave blank to abort."), +load_config_help[] = N_( +"\n" +"For various reasons, one may wish to keep several different\n" +"configurations available on a single machine.\n" +"\n" +"If you have saved a previous configuration in a file other than the\n" +"default one, entering its name here will allow you to modify that\n" +"configuration.\n" +"\n" +"If you are uncertain, then you have probably never used alternate\n" +"configuration files. You should therefor leave this blank to abort.\n"), +save_config_text[] = N_( +"Enter a filename to which this configuration should be saved\n" +"as an alternate. Leave blank to abort."), +save_config_help[] = N_( +"\n" +"For various reasons, one may wish to keep different configurations\n" +"available on a single machine.\n" +"\n" +"Entering a file name here will allow you to later retrieve, modify\n" +"and use the current configuration as an alternate to whatever\n" +"configuration options you have selected at that time.\n" +"\n" +"If you are uncertain what all this means then you should probably\n" +"leave this blank.\n"), +search_help[] = N_( +"\n" +"Search for symbols and display their relations. Regular expressions\n" +"are allowed.\n" +"Example: search for \"^FOO\"\n" +"Result:\n" +"-----------------------------------------------------------------\n" +"Symbol: FOO [ = m]\n" +"Prompt: Foo bus is used to drive the bar HW\n" +"Defined at drivers/pci/Kconfig:47\n" +"Depends on: X86_LOCAL_APIC && X86_IO_APIC || IA64\n" +"Location:\n" +" -> Bus options (PCI, PCMCIA, EISA, ISA)\n" +" -> PCI support (PCI [ = y])\n" +" -> PCI access mode ( [ = y])\n" +"Selects: LIBCRC32\n" +"Selected by: BAR\n" +"-----------------------------------------------------------------\n" +"o The line 'Prompt:' shows the text used in the menu structure for\n" +" this symbol\n" +"o The 'Defined at' line tell at what file / line number the symbol\n" +" is defined\n" +"o The 'Depends on:' line tell what symbols needs to be defined for\n" +" this symbol to be visible in the menu (selectable)\n" +"o The 'Location:' lines tell where in the menu structure this symbol\n" +" is located\n" +" A location followed by a [ = y] indicate that this is a selectable\n" +" menu item - and current value is displayed inside brackets.\n" +"o The 'Selects:' line tell what symbol will be automatically\n" +" selected if this symbol is selected (y or m)\n" +"o The 'Selected by' line tell what symbol has selected this symbol\n" +"\n" +"Only relevant lines are shown.\n" +"\n\n" +"Search examples:\n" +"Examples: USB => find all symbols containing USB\n" +" ^USB => find all symbols starting with USB\n" +" USB$ => find all symbols ending with USB\n" +"\n"); + +struct mitem { + char str[256]; + char tag; + void *usrptr; + int is_visible; +}; + +#define MAX_MENU_ITEMS 4096 +static int show_all_items; +static int indent; +static struct menu *current_menu; +static int child_count; +static int single_menu_mode; +/* the window in which all information appears */ +static WINDOW *main_window; +/* the largest size of the menu window */ +static int mwin_max_lines; +static int mwin_max_cols; +/* the window in which we show option buttons */ +static MENU *curses_menu; +static ITEM *curses_menu_items[MAX_MENU_ITEMS]; +static struct mitem k_menu_items[MAX_MENU_ITEMS]; +static int items_num; +static int global_exit; +/* the currently selected button */ +const char *current_instructions = menu_instructions; + +static char *dialog_input_result; +static int dialog_input_result_len; + +static void conf(struct menu *menu); +static void conf_choice(struct menu *menu); +static void conf_string(struct menu *menu); +static void conf_load(void); +static void conf_save(void); +static void show_help(struct menu *menu); +static int do_exit(void); +static void setup_windows(void); +static void search_conf(void); + +typedef void (*function_key_handler_t)(int *key, struct menu *menu); +static void handle_f1(int *key, struct menu *current_item); +static void handle_f2(int *key, struct menu *current_item); +static void handle_f3(int *key, struct menu *current_item); +static void handle_f4(int *key, struct menu *current_item); +static void handle_f5(int *key, struct menu *current_item); +static void handle_f6(int *key, struct menu *current_item); +static void handle_f7(int *key, struct menu *current_item); +static void handle_f8(int *key, struct menu *current_item); +static void handle_f9(int *key, struct menu *current_item); + +struct function_keys { + const char *key_str; + const char *func; + function_key key; + function_key_handler_t handler; +}; + +static const int function_keys_num = 9; +struct function_keys function_keys[] = { + { + .key_str = "F1", + .func = "Help", + .key = F_HELP, + .handler = handle_f1, + }, + { + .key_str = "F2", + .func = "Sym Info", + .key = F_SYMBOL, + .handler = handle_f2, + }, + { + .key_str = "F3", + .func = "Insts", + .key = F_INSTS, + .handler = handle_f3, + }, + { + .key_str = "F4", + .func = "Config", + .key = F_CONF, + .handler = handle_f4, + }, + { + .key_str = "F5", + .func = "Back", + .key = F_BACK, + .handler = handle_f5, + }, + { + .key_str = "F6", + .func = "Save", + .key = F_SAVE, + .handler = handle_f6, + }, + { + .key_str = "F7", + .func = "Load", + .key = F_LOAD, + .handler = handle_f7, + }, + { + .key_str = "F8", + .func = "Sym Search", + .key = F_SEARCH, + .handler = handle_f8, + }, + { + .key_str = "F9", + .func = "Exit", + .key = F_EXIT, + .handler = handle_f9, + }, +}; + +static void print_function_line(void) +{ + int i; + int offset = 1; + const int skip = 1; + + for (i = 0; i < function_keys_num; i++) { + (void) wattrset(main_window, attributes[FUNCTION_HIGHLIGHT]); + mvwprintw(main_window, LINES-3, offset, + "%s", + function_keys[i].key_str); + (void) wattrset(main_window, attributes[FUNCTION_TEXT]); + offset += strlen(function_keys[i].key_str); + mvwprintw(main_window, LINES-3, + offset, "%s", + function_keys[i].func); + offset += strlen(function_keys[i].func) + skip; + } + (void) wattrset(main_window, attributes[NORMAL]); +} + +/* help */ +static void handle_f1(int *key, struct menu *current_item) +{ + show_scroll_win(main_window, + _("README"), _(nconf_readme)); + return; +} + +/* symbole help */ +static void handle_f2(int *key, struct menu *current_item) +{ + show_help(current_item); + return; +} + +/* instructions */ +static void handle_f3(int *key, struct menu *current_item) +{ + show_scroll_win(main_window, + _("Instructions"), + _(current_instructions)); + return; +} + +/* config */ +static void handle_f4(int *key, struct menu *current_item) +{ + int res = btn_dialog(main_window, + _("Show all symbols?"), + 2, + " ", + ""); + if (res == 0) + show_all_items = 1; + else if (res == 1) + show_all_items = 0; + + return; +} + +/* back */ +static void handle_f5(int *key, struct menu *current_item) +{ + *key = KEY_LEFT; + return; +} + +/* save */ +static void handle_f6(int *key, struct menu *current_item) +{ + conf_save(); + return; +} + +/* load */ +static void handle_f7(int *key, struct menu *current_item) +{ + conf_load(); + return; +} + +/* search */ +static void handle_f8(int *key, struct menu *current_item) +{ + search_conf(); + return; +} + +/* exit */ +static void handle_f9(int *key, struct menu *current_item) +{ + do_exit(); + return; +} + +/* return != 0 to indicate the key was handles */ +static int process_special_keys(int *key, struct menu *menu) +{ + int i; + + if (*key == KEY_RESIZE) { + setup_windows(); + return 1; + } + + for (i = 0; i < function_keys_num; i++) { + if (*key == KEY_F(function_keys[i].key) || + *key == '0' + function_keys[i].key){ + function_keys[i].handler(key, menu); + return 1; + } + } + + return 0; +} + +static void clean_items(void) +{ + int i; + for (i = 0; curses_menu_items[i]; i++) + free_item(curses_menu_items[i]); + bzero(curses_menu_items, sizeof(curses_menu_items)); + bzero(k_menu_items, sizeof(k_menu_items)); + items_num = 0; +} + +typedef enum {MATCH_TINKER_PATTERN_UP, MATCH_TINKER_PATTERN_DOWN, + FIND_NEXT_MATCH_DOWN, FIND_NEXT_MATCH_UP} match_f; + +/* return the index of the matched item, or -1 if no such item exists */ +static int get_mext_match(const char *match_str, match_f flag) +{ + int match_start = item_index(current_item(curses_menu)); + int index; + + if (flag == FIND_NEXT_MATCH_DOWN) + ++match_start; + else if (flag == FIND_NEXT_MATCH_UP) + --match_start; + + index = match_start; + index = (index + items_num) % items_num; + while (true) { + char *str = k_menu_items[index].str; + if (strcasestr(str, match_str) != 0) + return index; + if (flag == FIND_NEXT_MATCH_UP || + flag == MATCH_TINKER_PATTERN_UP) + --index; + else + ++index; + index = (index + items_num) % items_num; + if (index == match_start) + return -1; + } +} + +/* Make a new item. */ +static void item_make(struct menu *menu, char tag, const char *fmt, ...) +{ + va_list ap; + + if (items_num > MAX_MENU_ITEMS-1) + return; + + bzero(&k_menu_items[items_num], sizeof(k_menu_items[0])); + k_menu_items[items_num].tag = tag; + k_menu_items[items_num].usrptr = menu; + if (menu != NULL) + k_menu_items[items_num].is_visible = + menu_is_visible(menu); + else + k_menu_items[items_num].is_visible = 1; + + va_start(ap, fmt); + vsnprintf(k_menu_items[items_num].str, + sizeof(k_menu_items[items_num].str), + fmt, ap); + va_end(ap); + + if (!k_menu_items[items_num].is_visible) + memcpy(k_menu_items[items_num].str, "XXX", 3); + + curses_menu_items[items_num] = new_item( + k_menu_items[items_num].str, + k_menu_items[items_num].str); + set_item_userptr(curses_menu_items[items_num], + &k_menu_items[items_num]); + /* + if (!k_menu_items[items_num].is_visible) + item_opts_off(curses_menu_items[items_num], O_SELECTABLE); + */ + + items_num++; + curses_menu_items[items_num] = NULL; +} + +/* very hackish. adds a string to the last item added */ +static void item_add_str(const char *fmt, ...) +{ + va_list ap; + int index = items_num-1; + char new_str[256]; + char tmp_str[256]; + + if (index < 0) + return; + + va_start(ap, fmt); + vsnprintf(new_str, sizeof(new_str), fmt, ap); + va_end(ap); + snprintf(tmp_str, sizeof(tmp_str), "%s%s", + k_menu_items[index].str, new_str); + strncpy(k_menu_items[index].str, + tmp_str, + sizeof(k_menu_items[index].str)); + + free_item(curses_menu_items[index]); + curses_menu_items[index] = new_item( + k_menu_items[index].str, + k_menu_items[index].str); + set_item_userptr(curses_menu_items[index], + &k_menu_items[index]); +} + +/* get the tag of the currently selected item */ +static char item_tag(void) +{ + ITEM *cur; + struct mitem *mcur; + + cur = current_item(curses_menu); + if (cur == NULL) + return 0; + mcur = (struct mitem *) item_userptr(cur); + return mcur->tag; +} + +static int curses_item_index(void) +{ + return item_index(current_item(curses_menu)); +} + +static void *item_data(void) +{ + ITEM *cur; + struct mitem *mcur; + + cur = current_item(curses_menu); + if (!cur) + return NULL; + mcur = (struct mitem *) item_userptr(cur); + return mcur->usrptr; + +} + +static int item_is_tag(char tag) +{ + return item_tag() == tag; +} + +static char filename[PATH_MAX+1]; +static char menu_backtitle[PATH_MAX+128]; +static const char *set_config_filename(const char *config_filename) +{ + int size; + + size = snprintf(menu_backtitle, sizeof(menu_backtitle), + "%s - %s", config_filename, rootmenu.prompt->text); + if (size >= sizeof(menu_backtitle)) + menu_backtitle[sizeof(menu_backtitle)-1] = '\0'; + + size = snprintf(filename, sizeof(filename), "%s", config_filename); + if (size >= sizeof(filename)) + filename[sizeof(filename)-1] = '\0'; + return menu_backtitle; +} + +/* return = 0 means we are successful. + * -1 means go on doing what you were doing + */ +static int do_exit(void) +{ + int res; + if (!conf_get_changed()) { + global_exit = 1; + return 0; + } + res = btn_dialog(main_window, + _("Do you wish to save your new configuration?\n" + " to cancel and resume nconfig."), + 2, + " ", + ""); + if (res == KEY_EXIT) { + global_exit = 0; + return -1; + } + + /* if we got here, the user really wants to exit */ + switch (res) { + case 0: + res = conf_write(filename); + if (res) + btn_dialog( + main_window, + _("Error during writing of configuration.\n" + "Your configuration changes were NOT saved."), + 1, + ""); + break; + default: + btn_dialog( + main_window, + _("Your configuration changes were NOT saved."), + 1, + ""); + break; + } + global_exit = 1; + return 0; +} + + +static void search_conf(void) +{ + struct symbol **sym_arr; + struct gstr res; + char *dialog_input; + int dres; +again: + dres = dialog_inputbox(main_window, + _("Search Configuration Parameter"), + _("Enter " CONFIG_ " (sub)string to search for " + "(with or without \"" CONFIG_ "\")"), + "", &dialog_input_result, &dialog_input_result_len); + switch (dres) { + case 0: + break; + case 1: + show_scroll_win(main_window, + _("Search Configuration"), search_help); + goto again; + default: + return; + } + + /* strip the prefix if necessary */ + dialog_input = dialog_input_result; + if (strncasecmp(dialog_input_result, CONFIG_, strlen(CONFIG_)) == 0) + dialog_input += strlen(CONFIG_); + + sym_arr = sym_re_search(dialog_input); + res = get_relations_str(sym_arr); + free(sym_arr); + show_scroll_win(main_window, + _("Search Results"), str_get(&res)); + str_free(&res); +} + + +static void build_conf(struct menu *menu) +{ + struct symbol *sym; + struct property *prop; + struct menu *child; + int type, tmp, doint = 2; + tristate val; + char ch; + + if (!menu || (!show_all_items && !menu_is_visible(menu))) + return; + + sym = menu->sym; + prop = menu->prompt; + if (!sym) { + if (prop && menu != current_menu) { + const char *prompt = menu_get_prompt(menu); + enum prop_type ptype; + ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN; + switch (ptype) { + case P_MENU: + child_count++; + prompt = _(prompt); + if (single_menu_mode) { + item_make(menu, 'm', + "%s%*c%s", + menu->data ? "-->" : "++>", + indent + 1, ' ', prompt); + } else + item_make(menu, 'm', + " %*c%s --->", + indent + 1, + ' ', prompt); + + if (single_menu_mode && menu->data) + goto conf_childs; + return; + case P_COMMENT: + if (prompt) { + child_count++; + item_make(menu, ':', + " %*c*** %s ***", + indent + 1, ' ', + _(prompt)); + } + break; + default: + if (prompt) { + child_count++; + item_make(menu, ':', "---%*c%s", + indent + 1, ' ', + _(prompt)); + } + } + } else + doint = 0; + goto conf_childs; + } + + type = sym_get_type(sym); + if (sym_is_choice(sym)) { + struct symbol *def_sym = sym_get_choice_value(sym); + struct menu *def_menu = NULL; + + child_count++; + for (child = menu->list; child; child = child->next) { + if (menu_is_visible(child) && child->sym == def_sym) + def_menu = child; + } + + val = sym_get_tristate_value(sym); + if (sym_is_changable(sym)) { + switch (type) { + case S_BOOLEAN: + item_make(menu, 't', "[%c]", + val == no ? ' ' : '*'); + break; + case S_TRISTATE: + switch (val) { + case yes: + ch = '*'; + break; + case mod: + ch = 'M'; + break; + default: + ch = ' '; + break; + } + item_make(menu, 't', "<%c>", ch); + break; + } + } else { + item_make(menu, def_menu ? 't' : ':', " "); + } + + item_add_str("%*c%s", indent + 1, + ' ', _(menu_get_prompt(menu))); + if (val == yes) { + if (def_menu) { + item_add_str(" (%s)", + _(menu_get_prompt(def_menu))); + item_add_str(" --->"); + if (def_menu->list) { + indent += 2; + build_conf(def_menu); + indent -= 2; + } + } + return; + } + } else { + if (menu == current_menu) { + item_make(menu, ':', + "---%*c%s", indent + 1, + ' ', _(menu_get_prompt(menu))); + goto conf_childs; + } + child_count++; + val = sym_get_tristate_value(sym); + if (sym_is_choice_value(sym) && val == yes) { + item_make(menu, ':', " "); + } else { + switch (type) { + case S_BOOLEAN: + if (sym_is_changable(sym)) + item_make(menu, 't', "[%c]", + val == no ? ' ' : '*'); + else + item_make(menu, 't', "-%c-", + val == no ? ' ' : '*'); + break; + case S_TRISTATE: + switch (val) { + case yes: + ch = '*'; + break; + case mod: + ch = 'M'; + break; + default: + ch = ' '; + break; + } + if (sym_is_changable(sym)) { + if (sym->rev_dep.tri == mod) + item_make(menu, + 't', "{%c}", ch); + else + item_make(menu, + 't', "<%c>", ch); + } else + item_make(menu, 't', "-%c-", ch); + break; + default: + tmp = 2 + strlen(sym_get_string_value(sym)); + item_make(menu, 's', " (%s)", + sym_get_string_value(sym)); + tmp = indent - tmp + 4; + if (tmp < 0) + tmp = 0; + item_add_str("%*c%s%s", tmp, ' ', + _(menu_get_prompt(menu)), + (sym_has_value(sym) || + !sym_is_changable(sym)) ? "" : + _(" (NEW)")); + goto conf_childs; + } + } + item_add_str("%*c%s%s", indent + 1, ' ', + _(menu_get_prompt(menu)), + (sym_has_value(sym) || !sym_is_changable(sym)) ? + "" : _(" (NEW)")); + if (menu->prompt && menu->prompt->type == P_MENU) { + item_add_str(" --->"); + return; + } + } + +conf_childs: + indent += doint; + for (child = menu->list; child; child = child->next) + build_conf(child); + indent -= doint; +} + +static void reset_menu(void) +{ + unpost_menu(curses_menu); + clean_items(); +} + +/* adjust the menu to show this item. + * prefer not to scroll the menu if possible*/ +static void center_item(int selected_index, int *last_top_row) +{ + int toprow; + + set_top_row(curses_menu, *last_top_row); + toprow = top_row(curses_menu); + if (selected_index < toprow || + selected_index >= toprow+mwin_max_lines) { + toprow = max(selected_index-mwin_max_lines/2, 0); + if (toprow >= item_count(curses_menu)-mwin_max_lines) + toprow = item_count(curses_menu)-mwin_max_lines; + set_top_row(curses_menu, toprow); + } + set_current_item(curses_menu, + curses_menu_items[selected_index]); + *last_top_row = toprow; + post_menu(curses_menu); + refresh_all_windows(main_window); +} + +/* this function assumes reset_menu has been called before */ +static void show_menu(const char *prompt, const char *instructions, + int selected_index, int *last_top_row) +{ + int maxx, maxy; + WINDOW *menu_window; + + current_instructions = instructions; + + clear(); + (void) wattrset(main_window, attributes[NORMAL]); + print_in_middle(stdscr, 1, 0, COLS, + menu_backtitle, + attributes[MAIN_HEADING]); + + (void) wattrset(main_window, attributes[MAIN_MENU_BOX]); + box(main_window, 0, 0); + (void) wattrset(main_window, attributes[MAIN_MENU_HEADING]); + mvwprintw(main_window, 0, 3, " %s ", prompt); + (void) wattrset(main_window, attributes[NORMAL]); + + set_menu_items(curses_menu, curses_menu_items); + + /* position the menu at the middle of the screen */ + scale_menu(curses_menu, &maxy, &maxx); + maxx = min(maxx, mwin_max_cols-2); + maxy = mwin_max_lines; + menu_window = derwin(main_window, + maxy, + maxx, + 2, + (mwin_max_cols-maxx)/2); + keypad(menu_window, TRUE); + set_menu_win(curses_menu, menu_window); + set_menu_sub(curses_menu, menu_window); + + /* must reassert this after changing items, otherwise returns to a + * default of 16 + */ + set_menu_format(curses_menu, maxy, 1); + center_item(selected_index, last_top_row); + set_menu_format(curses_menu, maxy, 1); + + print_function_line(); + + /* Post the menu */ + post_menu(curses_menu); + refresh_all_windows(main_window); +} + +static void adj_match_dir(match_f *match_direction) +{ + if (*match_direction == FIND_NEXT_MATCH_DOWN) + *match_direction = + MATCH_TINKER_PATTERN_DOWN; + else if (*match_direction == FIND_NEXT_MATCH_UP) + *match_direction = + MATCH_TINKER_PATTERN_UP; + /* else, do no change.. */ +} + +struct match_state +{ + int in_search; + match_f match_direction; + char pattern[256]; +}; + +/* Return 0 means I have handled the key. In such a case, ans should hold the + * item to center, or -1 otherwise. + * Else return -1 . + */ +static int do_match(int key, struct match_state *state, int *ans) +{ + char c = (char) key; + int terminate_search = 0; + *ans = -1; + if (key == '/' || (state->in_search && key == 27)) { + move(0, 0); + refresh(); + clrtoeol(); + state->in_search = 1-state->in_search; + bzero(state->pattern, sizeof(state->pattern)); + state->match_direction = MATCH_TINKER_PATTERN_DOWN; + return 0; + } else if (!state->in_search) + return 1; + + if (isalnum(c) || isgraph(c) || c == ' ') { + state->pattern[strlen(state->pattern)] = c; + state->pattern[strlen(state->pattern)] = '\0'; + adj_match_dir(&state->match_direction); + *ans = get_mext_match(state->pattern, + state->match_direction); + } else if (key == KEY_DOWN) { + state->match_direction = FIND_NEXT_MATCH_DOWN; + *ans = get_mext_match(state->pattern, + state->match_direction); + } else if (key == KEY_UP) { + state->match_direction = FIND_NEXT_MATCH_UP; + *ans = get_mext_match(state->pattern, + state->match_direction); + } else if (key == KEY_BACKSPACE || key == 127) { + state->pattern[strlen(state->pattern)-1] = '\0'; + adj_match_dir(&state->match_direction); + } else + terminate_search = 1; + + if (terminate_search) { + state->in_search = 0; + bzero(state->pattern, sizeof(state->pattern)); + move(0, 0); + refresh(); + clrtoeol(); + return -1; + } + return 0; +} + +static void conf(struct menu *menu) +{ + struct menu *submenu = 0; + const char *prompt = menu_get_prompt(menu); + struct symbol *sym; + int res; + int current_index = 0; + int last_top_row = 0; + struct match_state match_state = { + .in_search = 0, + .match_direction = MATCH_TINKER_PATTERN_DOWN, + .pattern = "", + }; + + while (!global_exit) { + reset_menu(); + current_menu = menu; + build_conf(menu); + if (!child_count) + break; + + show_menu(prompt ? _(prompt) : _("Main Menu"), + _(menu_instructions), + current_index, &last_top_row); + keypad((menu_win(curses_menu)), TRUE); + while (!global_exit) { + if (match_state.in_search) { + mvprintw(0, 0, + "searching: %s", match_state.pattern); + clrtoeol(); + } + refresh_all_windows(main_window); + res = wgetch(menu_win(curses_menu)); + if (!res) + break; + if (do_match(res, &match_state, ¤t_index) == 0) { + if (current_index != -1) + center_item(current_index, + &last_top_row); + continue; + } + if (process_special_keys(&res, + (struct menu *) item_data())) + break; + switch (res) { + case KEY_DOWN: + menu_driver(curses_menu, REQ_DOWN_ITEM); + break; + case KEY_UP: + menu_driver(curses_menu, REQ_UP_ITEM); + break; + case KEY_NPAGE: + menu_driver(curses_menu, REQ_SCR_DPAGE); + break; + case KEY_PPAGE: + menu_driver(curses_menu, REQ_SCR_UPAGE); + break; + case KEY_HOME: + menu_driver(curses_menu, REQ_FIRST_ITEM); + break; + case KEY_END: + menu_driver(curses_menu, REQ_LAST_ITEM); + break; + case 'h': + case '?': + show_help((struct menu *) item_data()); + break; + } + if (res == 10 || res == 27 || + res == 32 || res == 'n' || res == 'y' || + res == KEY_LEFT || res == KEY_RIGHT || + res == 'm') + break; + refresh_all_windows(main_window); + } + + refresh_all_windows(main_window); + /* if ESC or left*/ + if (res == 27 || (menu != &rootmenu && res == KEY_LEFT)) + break; + + /* remember location in the menu */ + last_top_row = top_row(curses_menu); + current_index = curses_item_index(); + + if (!item_tag()) + continue; + + submenu = (struct menu *) item_data(); + if (!submenu || !menu_is_visible(submenu)) + continue; + sym = submenu->sym; + + switch (res) { + case ' ': + if (item_is_tag('t')) + sym_toggle_tristate_value(sym); + else if (item_is_tag('m')) + conf(submenu); + break; + case KEY_RIGHT: + case 10: /* ENTER WAS PRESSED */ + switch (item_tag()) { + case 'm': + if (single_menu_mode) + submenu->data = + (void *) (long) !submenu->data; + else + conf(submenu); + break; + case 't': + if (sym_is_choice(sym) && + sym_get_tristate_value(sym) == yes) + conf_choice(submenu); + else if (submenu->prompt && + submenu->prompt->type == P_MENU) + conf(submenu); + else if (res == 10) + sym_toggle_tristate_value(sym); + break; + case 's': + conf_string(submenu); + break; + } + break; + case 'y': + if (item_is_tag('t')) { + if (sym_set_tristate_value(sym, yes)) + break; + if (sym_set_tristate_value(sym, mod)) + btn_dialog(main_window, setmod_text, 0); + } + break; + case 'n': + if (item_is_tag('t')) + sym_set_tristate_value(sym, no); + break; + case 'm': + if (item_is_tag('t')) + sym_set_tristate_value(sym, mod); + break; + } + } +} + +static void conf_message_callback(const char *fmt, va_list ap) +{ + char buf[1024]; + + vsnprintf(buf, sizeof(buf), fmt, ap); + btn_dialog(main_window, buf, 1, ""); +} + +static void show_help(struct menu *menu) +{ + struct gstr help; + + if (!menu) + return; + + help = str_new(); + menu_get_ext_help(menu, &help); + show_scroll_win(main_window, _(menu_get_prompt(menu)), str_get(&help)); + str_free(&help); +} + +static void conf_choice(struct menu *menu) +{ + const char *prompt = _(menu_get_prompt(menu)); + struct menu *child = 0; + struct symbol *active; + int selected_index = 0; + int last_top_row = 0; + int res, i = 0; + struct match_state match_state = { + .in_search = 0, + .match_direction = MATCH_TINKER_PATTERN_DOWN, + .pattern = "", + }; + + active = sym_get_choice_value(menu->sym); + /* this is mostly duplicated from the conf() function. */ + while (!global_exit) { + reset_menu(); + + for (i = 0, child = menu->list; child; child = child->next) { + if (!show_all_items && !menu_is_visible(child)) + continue; + + if (child->sym == sym_get_choice_value(menu->sym)) + item_make(child, ':', " %s", + _(menu_get_prompt(child))); + else if (child->sym) + item_make(child, ':', " %s", + _(menu_get_prompt(child))); + else + item_make(child, ':', "*** %s ***", + _(menu_get_prompt(child))); + + if (child->sym == active){ + last_top_row = top_row(curses_menu); + selected_index = i; + } + i++; + } + show_menu(prompt ? _(prompt) : _("Choice Menu"), + _(radiolist_instructions), + selected_index, + &last_top_row); + while (!global_exit) { + if (match_state.in_search) { + mvprintw(0, 0, "searching: %s", + match_state.pattern); + clrtoeol(); + } + refresh_all_windows(main_window); + res = wgetch(menu_win(curses_menu)); + if (!res) + break; + if (do_match(res, &match_state, &selected_index) == 0) { + if (selected_index != -1) + center_item(selected_index, + &last_top_row); + continue; + } + if (process_special_keys( + &res, + (struct menu *) item_data())) + break; + switch (res) { + case KEY_DOWN: + menu_driver(curses_menu, REQ_DOWN_ITEM); + break; + case KEY_UP: + menu_driver(curses_menu, REQ_UP_ITEM); + break; + case KEY_NPAGE: + menu_driver(curses_menu, REQ_SCR_DPAGE); + break; + case KEY_PPAGE: + menu_driver(curses_menu, REQ_SCR_UPAGE); + break; + case KEY_HOME: + menu_driver(curses_menu, REQ_FIRST_ITEM); + break; + case KEY_END: + menu_driver(curses_menu, REQ_LAST_ITEM); + break; + case 'h': + case '?': + show_help((struct menu *) item_data()); + break; + } + if (res == 10 || res == 27 || res == ' ' || + res == KEY_LEFT){ + break; + } + refresh_all_windows(main_window); + } + /* if ESC or left */ + if (res == 27 || res == KEY_LEFT) + break; + + child = item_data(); + if (!child || !menu_is_visible(child) || !child->sym) + continue; + switch (res) { + case ' ': + case 10: + case KEY_RIGHT: + sym_set_tristate_value(child->sym, yes); + return; + case 'h': + case '?': + show_help(child); + active = child->sym; + break; + case KEY_EXIT: + return; + } + } +} + +static void conf_string(struct menu *menu) +{ + const char *prompt = menu_get_prompt(menu); + + while (1) { + int res; + const char *heading; + + switch (sym_get_type(menu->sym)) { + case S_INT: + heading = _(inputbox_instructions_int); + break; + case S_HEX: + heading = _(inputbox_instructions_hex); + break; + case S_STRING: + heading = _(inputbox_instructions_string); + break; + default: + heading = _("Internal nconf error!"); + } + res = dialog_inputbox(main_window, + prompt ? _(prompt) : _("Main Menu"), + heading, + sym_get_string_value(menu->sym), + &dialog_input_result, + &dialog_input_result_len); + switch (res) { + case 0: + if (sym_set_string_value(menu->sym, + dialog_input_result)) + return; + btn_dialog(main_window, + _("You have made an invalid entry."), 0); + break; + case 1: + show_help(menu); + break; + case KEY_EXIT: + return; + } + } +} + +static void conf_load(void) +{ + while (1) { + int res; + res = dialog_inputbox(main_window, + NULL, load_config_text, + filename, + &dialog_input_result, + &dialog_input_result_len); + switch (res) { + case 0: + if (!dialog_input_result[0]) + return; + if (!conf_read(dialog_input_result)) { + set_config_filename(dialog_input_result); + sym_set_change_count(1); + return; + } + btn_dialog(main_window, _("File does not exist!"), 0); + break; + case 1: + show_scroll_win(main_window, + _("Load Alternate Configuration"), + load_config_help); + break; + case KEY_EXIT: + return; + } + } +} + +static void conf_save(void) +{ + while (1) { + int res; + res = dialog_inputbox(main_window, + NULL, save_config_text, + filename, + &dialog_input_result, + &dialog_input_result_len); + switch (res) { + case 0: + if (!dialog_input_result[0]) + return; + res = conf_write(dialog_input_result); + if (!res) { + set_config_filename(dialog_input_result); + return; + } + btn_dialog(main_window, _("Can't create file! " + "Probably a nonexistent directory."), + 1, ""); + break; + case 1: + show_scroll_win(main_window, + _("Save Alternate Configuration"), + save_config_help); + break; + case KEY_EXIT: + return; + } + } +} + +void setup_windows(void) +{ + if (main_window != NULL) + delwin(main_window); + + /* set up the menu and menu window */ + main_window = newwin(LINES-2, COLS-2, 2, 1); + keypad(main_window, TRUE); + mwin_max_lines = LINES-7; + mwin_max_cols = COLS-6; + + /* panels order is from bottom to top */ + new_panel(main_window); +} + +int main(int ac, char **av) +{ + char *mode; + + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + + conf_parse(av[1]); + conf_read(NULL); + + mode = getenv("NCONFIG_MODE"); + if (mode) { + if (!strcasecmp(mode, "single_menu")) + single_menu_mode = 1; + } + + /* Initialize curses */ + initscr(); + /* set color theme */ + set_colors(); + + cbreak(); + noecho(); + keypad(stdscr, TRUE); + curs_set(0); + + if (COLS < 75 || LINES < 20) { + endwin(); + printf("Your terminal should have at " + "least 20 lines and 75 columns\n"); + return 1; + } + + notimeout(stdscr, FALSE); + ESCDELAY = 1; + + /* set btns menu */ + curses_menu = new_menu(curses_menu_items); + menu_opts_off(curses_menu, O_SHOWDESC); + menu_opts_on(curses_menu, O_SHOWMATCH); + menu_opts_on(curses_menu, O_ONEVALUE); + menu_opts_on(curses_menu, O_NONCYCLIC); + menu_opts_on(curses_menu, O_IGNORECASE); + set_menu_mark(curses_menu, " "); + set_menu_fore(curses_menu, attributes[MAIN_MENU_FORE]); + set_menu_back(curses_menu, attributes[MAIN_MENU_BACK]); + set_menu_grey(curses_menu, attributes[MAIN_MENU_GREY]); + + set_config_filename(conf_get_configname()); + setup_windows(); + + /* check for KEY_FUNC(1) */ + if (has_key(KEY_F(1)) == FALSE) { + show_scroll_win(main_window, + _("Instructions"), + _(menu_no_f_instructions)); + } + + conf_set_message_callback(conf_message_callback); + /* do the work */ + while (!global_exit) { + conf(&rootmenu); + if (!global_exit && do_exit() == 0) + break; + } + /* ok, we are done */ + unpost_menu(curses_menu); + free_menu(curses_menu); + delwin(main_window); + clear(); + refresh(); + endwin(); + return 0; +} + diff --git a/l4/tool/kconfig/scripts/kconfig/nconf.gui.c b/l4/tool/kconfig/scripts/kconfig/nconf.gui.c new file mode 100644 index 00000000..3b18dd83 --- /dev/null +++ b/l4/tool/kconfig/scripts/kconfig/nconf.gui.c @@ -0,0 +1,652 @@ +/* + * Copyright (C) 2008 Nir Tzachar 0) + win_rows = msg_lines+4; + else + win_rows = msg_lines+2; + + win = newwin(win_rows, total_width+4, y, x); + keypad(win, TRUE); + menu_win = derwin(win, 1, btns_width, win_rows-2, + 1+(total_width+2-btns_width)/2); + menu = new_menu(btns); + msg_win = derwin(win, win_rows-2, msg_width, 1, + 1+(total_width+2-msg_width)/2); + + set_menu_fore(menu, attributes[DIALOG_MENU_FORE]); + set_menu_back(menu, attributes[DIALOG_MENU_BACK]); + + (void) wattrset(win, attributes[DIALOG_BOX]); + box(win, 0, 0); + + /* print message */ + (void) wattrset(msg_win, attributes[DIALOG_TEXT]); + fill_window(msg_win, msg); + + set_menu_win(menu, win); + set_menu_sub(menu, menu_win); + set_menu_format(menu, 1, btn_num); + menu_opts_off(menu, O_SHOWDESC); + menu_opts_off(menu, O_SHOWMATCH); + menu_opts_on(menu, O_ONEVALUE); + menu_opts_on(menu, O_NONCYCLIC); + set_menu_mark(menu, ""); + post_menu(menu); + + + touchwin(win); + refresh_all_windows(main_window); + while ((res = wgetch(win))) { + switch (res) { + case KEY_LEFT: + menu_driver(menu, REQ_LEFT_ITEM); + break; + case KEY_RIGHT: + menu_driver(menu, REQ_RIGHT_ITEM); + break; + case 10: /* ENTER */ + case 27: /* ESCAPE */ + case ' ': + case KEY_F(F_BACK): + case KEY_F(F_EXIT): + break; + } + touchwin(win); + refresh_all_windows(main_window); + + if (res == 10 || res == ' ') { + res = item_index(current_item(menu)); + break; + } else if (res == 27 || res == KEY_F(F_BACK) || + res == KEY_F(F_EXIT)) { + res = KEY_EXIT; + break; + } + } + + unpost_menu(menu); + free_menu(menu); + for (i = 0; i < btn_num; i++) + free_item(btns[i]); + + delwin(win); + return res; +} + +int dialog_inputbox(WINDOW *main_window, + const char *title, const char *prompt, + const char *init, char **resultp, int *result_len) +{ + int prompt_lines = 0; + int prompt_width = 0; + WINDOW *win; + WINDOW *prompt_win; + WINDOW *form_win; + PANEL *panel; + int i, x, y; + int res = -1; + int cursor_position = strlen(init); + int cursor_form_win; + char *result = *resultp; + + if (strlen(init)+1 > *result_len) { + *result_len = strlen(init)+1; + *resultp = result = realloc(result, *result_len); + } + + /* find the widest line of msg: */ + prompt_lines = get_line_no(prompt); + for (i = 0; i < prompt_lines; i++) { + const char *line = get_line(prompt, i); + int len = get_line_length(line); + prompt_width = max(prompt_width, len); + } + + if (title) + prompt_width = max(prompt_width, strlen(title)); + + /* place dialog in middle of screen */ + y = (LINES-(prompt_lines+4))/2; + x = (COLS-(prompt_width+4))/2; + + strncpy(result, init, *result_len); + + /* create the windows */ + win = newwin(prompt_lines+6, prompt_width+7, y, x); + prompt_win = derwin(win, prompt_lines+1, prompt_width, 2, 2); + form_win = derwin(win, 1, prompt_width, prompt_lines+3, 2); + keypad(form_win, TRUE); + + (void) wattrset(form_win, attributes[INPUT_FIELD]); + + (void) wattrset(win, attributes[INPUT_BOX]); + box(win, 0, 0); + (void) wattrset(win, attributes[INPUT_HEADING]); + if (title) + mvwprintw(win, 0, 3, "%s", title); + + /* print message */ + (void) wattrset(prompt_win, attributes[INPUT_TEXT]); + fill_window(prompt_win, prompt); + + mvwprintw(form_win, 0, 0, "%*s", prompt_width, " "); + cursor_form_win = min(cursor_position, prompt_width-1); + mvwprintw(form_win, 0, 0, "%s", + result + cursor_position-cursor_form_win); + + /* create panels */ + panel = new_panel(win); + + /* show the cursor */ + curs_set(1); + + touchwin(win); + refresh_all_windows(main_window); + while ((res = wgetch(form_win))) { + int len = strlen(result); + switch (res) { + case 10: /* ENTER */ + case 27: /* ESCAPE */ + case KEY_F(F_HELP): + case KEY_F(F_EXIT): + case KEY_F(F_BACK): + break; + case 127: + case KEY_BACKSPACE: + if (cursor_position > 0) { + memmove(&result[cursor_position-1], + &result[cursor_position], + len-cursor_position+1); + cursor_position--; + cursor_form_win--; + len--; + } + break; + case KEY_DC: + if (cursor_position >= 0 && cursor_position < len) { + memmove(&result[cursor_position], + &result[cursor_position+1], + len-cursor_position+1); + len--; + } + break; + case KEY_UP: + case KEY_RIGHT: + if (cursor_position < len) { + cursor_position++; + cursor_form_win++; + } + break; + case KEY_DOWN: + case KEY_LEFT: + if (cursor_position > 0) { + cursor_position--; + cursor_form_win--; + } + break; + case KEY_HOME: + cursor_position = 0; + cursor_form_win = 0; + break; + case KEY_END: + cursor_position = len; + cursor_form_win = min(cursor_position, prompt_width-1); + break; + default: + if ((isgraph(res) || isspace(res))) { + /* one for new char, one for '\0' */ + if (len+2 > *result_len) { + *result_len = len+2; + *resultp = result = realloc(result, + *result_len); + } + /* insert the char at the proper position */ + memmove(&result[cursor_position+1], + &result[cursor_position], + len-cursor_position+1); + result[cursor_position] = res; + cursor_position++; + cursor_form_win++; + len++; + } else { + mvprintw(0, 0, "unknown key: %d\n", res); + } + break; + } + if (cursor_form_win < 0) + cursor_form_win = 0; + else if (cursor_form_win > prompt_width-1) + cursor_form_win = prompt_width-1; + + wmove(form_win, 0, 0); + wclrtoeol(form_win); + mvwprintw(form_win, 0, 0, "%*s", prompt_width, " "); + mvwprintw(form_win, 0, 0, "%s", + result + cursor_position-cursor_form_win); + wmove(form_win, 0, cursor_form_win); + touchwin(win); + refresh_all_windows(main_window); + + if (res == 10) { + res = 0; + break; + } else if (res == 27 || res == KEY_F(F_BACK) || + res == KEY_F(F_EXIT)) { + res = KEY_EXIT; + break; + } else if (res == KEY_F(F_HELP)) { + res = 1; + break; + } + } + + /* hide the cursor */ + curs_set(0); + del_panel(panel); + delwin(prompt_win); + delwin(form_win); + delwin(win); + return res; +} + +/* refresh all windows in the correct order */ +void refresh_all_windows(WINDOW *main_window) +{ + update_panels(); + touchwin(main_window); + refresh(); +} + +/* layman's scrollable window... */ +void show_scroll_win(WINDOW *main_window, + const char *title, + const char *text) +{ + int res; + int total_lines = get_line_no(text); + int x, y; + int start_x = 0, start_y = 0; + int text_lines = 0, text_cols = 0; + int total_cols = 0; + int win_cols = 0; + int win_lines = 0; + int i = 0; + WINDOW *win; + WINDOW *pad; + PANEL *panel; + + /* find the widest line of msg: */ + total_lines = get_line_no(text); + for (i = 0; i < total_lines; i++) { + const char *line = get_line(text, i); + int len = get_line_length(line); + total_cols = max(total_cols, len+2); + } + + /* create the pad */ + pad = newpad(total_lines+10, total_cols+10); + (void) wattrset(pad, attributes[SCROLLWIN_TEXT]); + fill_window(pad, text); + + win_lines = min(total_lines+4, LINES-2); + win_cols = min(total_cols+2, COLS-2); + text_lines = max(win_lines-4, 0); + text_cols = max(win_cols-2, 0); + + /* place window in middle of screen */ + y = (LINES-win_lines)/2; + x = (COLS-win_cols)/2; + + win = newwin(win_lines, win_cols, y, x); + keypad(win, TRUE); + /* show the help in the help window, and show the help panel */ + (void) wattrset(win, attributes[SCROLLWIN_BOX]); + box(win, 0, 0); + (void) wattrset(win, attributes[SCROLLWIN_HEADING]); + mvwprintw(win, 0, 3, " %s ", title); + panel = new_panel(win); + + /* handle scrolling */ + do { + + copywin(pad, win, start_y, start_x, 2, 2, text_lines, + text_cols, 0); + print_in_middle(win, + text_lines+2, + 0, + text_cols, + "", + attributes[DIALOG_MENU_FORE]); + wrefresh(win); + + res = wgetch(win); + switch (res) { + case KEY_NPAGE: + case ' ': + start_y += text_lines-2; + break; + case KEY_PPAGE: + start_y -= text_lines+2; + break; + case KEY_HOME: + start_y = 0; + break; + case KEY_END: + start_y = total_lines-text_lines; + break; + case KEY_DOWN: + case 'j': + start_y++; + break; + case KEY_UP: + case 'k': + start_y--; + break; + case KEY_LEFT: + case 'h': + start_x--; + break; + case KEY_RIGHT: + case 'l': + start_x++; + break; + } + if (res == 10 || res == 27 || res == 'q' + || res == KEY_F(F_BACK) || res == KEY_F(F_EXIT)) { + break; + } + if (start_y < 0) + start_y = 0; + if (start_y >= total_lines-text_lines) + start_y = total_lines-text_lines; + if (start_x < 0) + start_x = 0; + if (start_x >= total_cols-text_cols) + start_x = total_cols-text_cols; + } while (res); + + del_panel(panel); + delwin(win); + refresh_all_windows(main_window); +} diff --git a/l4/tool/kconfig/scripts/kconfig/nconf.h b/l4/tool/kconfig/scripts/kconfig/nconf.h new file mode 100644 index 00000000..0d526170 --- /dev/null +++ b/l4/tool/kconfig/scripts/kconfig/nconf.h @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2008 Nir Tzachar +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "ncurses.h" + +#define max(a, b) ({\ + typeof(a) _a = a;\ + typeof(b) _b = b;\ + _a > _b ? _a : _b; }) + +#define min(a, b) ({\ + typeof(a) _a = a;\ + typeof(b) _b = b;\ + _a < _b ? _a : _b; }) + +typedef enum { + NORMAL = 1, + MAIN_HEADING, + MAIN_MENU_BOX, + MAIN_MENU_FORE, + MAIN_MENU_BACK, + MAIN_MENU_GREY, + MAIN_MENU_HEADING, + SCROLLWIN_TEXT, + SCROLLWIN_HEADING, + SCROLLWIN_BOX, + DIALOG_TEXT, + DIALOG_MENU_FORE, + DIALOG_MENU_BACK, + DIALOG_BOX, + INPUT_BOX, + INPUT_HEADING, + INPUT_TEXT, + INPUT_FIELD, + FUNCTION_TEXT, + FUNCTION_HIGHLIGHT, + ATTR_MAX +} attributes_t; +extern attributes_t attributes[]; + +typedef enum { + F_HELP = 1, + F_SYMBOL = 2, + F_INSTS = 3, + F_CONF = 4, + F_BACK = 5, + F_SAVE = 6, + F_LOAD = 7, + F_SEARCH = 8, + F_EXIT = 9, +} function_key; + +void set_colors(void); + +/* this changes the windows attributes !!! */ +void print_in_middle(WINDOW *win, + int starty, + int startx, + int width, + const char *string, + chtype color); +int get_line_length(const char *line); +int get_line_no(const char *text); +const char *get_line(const char *text, int line_no); +void fill_window(WINDOW *win, const char *text); +int btn_dialog(WINDOW *main_window, const char *msg, int btn_num, ...); +int dialog_inputbox(WINDOW *main_window, + const char *title, const char *prompt, + const char *init, char **resultp, int *result_len); +void refresh_all_windows(WINDOW *main_window); +void show_scroll_win(WINDOW *main_window, + const char *title, + const char *text); diff --git a/l4/tool/kconfig/scripts/kconfig/qconf.cc b/l4/tool/kconfig/scripts/kconfig/qconf.cc new file mode 100644 index 00000000..df274feb --- /dev/null +++ b/l4/tool/kconfig/scripts/kconfig/qconf.cc @@ -0,0 +1,1789 @@ +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +#include + +#if QT_VERSION < 0x040000 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#else +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "lkc.h" +#include "qconf.h" + +#include "qconf.moc" +#include "images.c" + +#ifdef _ +# undef _ +# define _ qgettext +#endif + +static QApplication *configApp; +static ConfigSettings *configSettings; + +Q3Action *ConfigMainWindow::saveAction; + +static inline QString qgettext(const char* str) +{ + return QString::fromLocal8Bit(gettext(str)); +} + +static inline QString qgettext(const QString& str) +{ + return QString::fromLocal8Bit(gettext(str.latin1())); +} + +/** + * Reads a list of integer values from the application settings. + */ +Q3ValueList ConfigSettings::readSizes(const QString& key, bool *ok) +{ + Q3ValueList result; + QStringList entryList = readListEntry(key, ok); + QStringList::Iterator it; + + for (it = entryList.begin(); it != entryList.end(); ++it) + result.push_back((*it).toInt()); + + return result; +} + +/** + * Writes a list of integer values to the application settings. + */ +bool ConfigSettings::writeSizes(const QString& key, const Q3ValueList& value) +{ + QStringList stringList; + Q3ValueList::ConstIterator it; + + for (it = value.begin(); it != value.end(); ++it) + stringList.push_back(QString::number(*it)); + return writeEntry(key, stringList); +} + + +/* + * set the new data + * TODO check the value + */ +void ConfigItem::okRename(int col) +{ + Parent::okRename(col); + sym_set_string_value(menu->sym, text(dataColIdx).latin1()); + listView()->updateList(this); +} + +/* + * update the displayed of a menu entry + */ +void ConfigItem::updateMenu(void) +{ + ConfigList* list; + struct symbol* sym; + struct property *prop; + QString prompt; + int type; + tristate expr; + + list = listView(); + if (goParent) { + setPixmap(promptColIdx, list->menuBackPix); + prompt = ".."; + goto set_prompt; + } + + sym = menu->sym; + prop = menu->prompt; + prompt = _(menu_get_prompt(menu)); + + if (prop) switch (prop->type) { + case P_MENU: + if (list->mode == singleMode || list->mode == symbolMode) { + /* a menuconfig entry is displayed differently + * depending whether it's at the view root or a child. + */ + if (sym && list->rootEntry == menu) + break; + setPixmap(promptColIdx, list->menuPix); + } else { + if (sym) + break; + setPixmap(promptColIdx, 0); + } + goto set_prompt; + case P_COMMENT: + setPixmap(promptColIdx, 0); + goto set_prompt; + default: + ; + } + if (!sym) + goto set_prompt; + + setText(nameColIdx, QString::fromLocal8Bit(sym->name)); + + type = sym_get_type(sym); + switch (type) { + case S_BOOLEAN: + case S_TRISTATE: + char ch; + + if (!sym_is_changable(sym) && list->optMode == normalOpt) { + setPixmap(promptColIdx, 0); + setText(noColIdx, QString::null); + setText(modColIdx, QString::null); + setText(yesColIdx, QString::null); + break; + } + expr = sym_get_tristate_value(sym); + switch (expr) { + case yes: + if (sym_is_choice_value(sym) && type == S_BOOLEAN) + setPixmap(promptColIdx, list->choiceYesPix); + else + setPixmap(promptColIdx, list->symbolYesPix); + setText(yesColIdx, "Y"); + ch = 'Y'; + break; + case mod: + setPixmap(promptColIdx, list->symbolModPix); + setText(modColIdx, "M"); + ch = 'M'; + break; + default: + if (sym_is_choice_value(sym) && type == S_BOOLEAN) + setPixmap(promptColIdx, list->choiceNoPix); + else + setPixmap(promptColIdx, list->symbolNoPix); + setText(noColIdx, "N"); + ch = 'N'; + break; + } + if (expr != no) + setText(noColIdx, sym_tristate_within_range(sym, no) ? "_" : 0); + if (expr != mod) + setText(modColIdx, sym_tristate_within_range(sym, mod) ? "_" : 0); + if (expr != yes) + setText(yesColIdx, sym_tristate_within_range(sym, yes) ? "_" : 0); + + setText(dataColIdx, QChar(ch)); + break; + case S_INT: + case S_HEX: + case S_STRING: + const char* data; + + data = sym_get_string_value(sym); + + int i = list->mapIdx(dataColIdx); + if (i >= 0) + setRenameEnabled(i, TRUE); + setText(dataColIdx, data); + if (type == S_STRING) + prompt = QString("%1: %2").arg(prompt).arg(data); + else + prompt = QString("(%2) %1").arg(prompt).arg(data); + break; + } + if (!sym_has_value(sym) && visible) + prompt += _(" (NEW)"); +set_prompt: + setText(promptColIdx, prompt); +} + +void ConfigItem::testUpdateMenu(bool v) +{ + ConfigItem* i; + + visible = v; + if (!menu) + return; + + sym_calc_value(menu->sym); + if (menu->flags & MENU_CHANGED) { + /* the menu entry changed, so update all list items */ + menu->flags &= ~MENU_CHANGED; + for (i = (ConfigItem*)menu->data; i; i = i->nextItem) + i->updateMenu(); + } else if (listView()->updateAll) + updateMenu(); +} + +void ConfigItem::paintCell(QPainter* p, const QColorGroup& cg, int column, int width, int align) +{ + ConfigList* list = listView(); + + if (visible) { + if (isSelected() && !list->hasFocus() && list->mode == menuMode) + Parent::paintCell(p, list->inactivedColorGroup, column, width, align); + else + Parent::paintCell(p, cg, column, width, align); + } else + Parent::paintCell(p, list->disabledColorGroup, column, width, align); +} + +/* + * construct a menu entry + */ +void ConfigItem::init(void) +{ + if (menu) { + ConfigList* list = listView(); + nextItem = (ConfigItem*)menu->data; + menu->data = this; + + if (list->mode != fullMode) + setOpen(TRUE); + sym_calc_value(menu->sym); + } + updateMenu(); +} + +/* + * destruct a menu entry + */ +ConfigItem::~ConfigItem(void) +{ + if (menu) { + ConfigItem** ip = (ConfigItem**)&menu->data; + for (; *ip; ip = &(*ip)->nextItem) { + if (*ip == this) { + *ip = nextItem; + break; + } + } + } +} + +ConfigLineEdit::ConfigLineEdit(ConfigView* parent) + : Parent(parent) +{ + connect(this, SIGNAL(lostFocus()), SLOT(hide())); +} + +void ConfigLineEdit::show(ConfigItem* i) +{ + item = i; + if (sym_get_string_value(item->menu->sym)) + setText(QString::fromLocal8Bit(sym_get_string_value(item->menu->sym))); + else + setText(QString::null); + Parent::show(); + setFocus(); +} + +void ConfigLineEdit::keyPressEvent(QKeyEvent* e) +{ + switch (e->key()) { + case Qt::Key_Escape: + break; + case Qt::Key_Return: + case Qt::Key_Enter: + sym_set_string_value(item->menu->sym, text().latin1()); + parent()->updateList(item); + break; + default: + Parent::keyPressEvent(e); + return; + } + e->accept(); + parent()->list->setFocus(); + hide(); +} + +ConfigList::ConfigList(ConfigView* p, const char *name) + : Parent(p, name), + updateAll(false), + symbolYesPix(xpm_symbol_yes), symbolModPix(xpm_symbol_mod), symbolNoPix(xpm_symbol_no), + choiceYesPix(xpm_choice_yes), choiceNoPix(xpm_choice_no), + menuPix(xpm_menu), menuInvPix(xpm_menu_inv), menuBackPix(xpm_menuback), voidPix(xpm_void), + showName(false), showRange(false), showData(false), optMode(normalOpt), + rootEntry(0), headerPopup(0) +{ + int i; + + setSorting(-1); + setRootIsDecorated(TRUE); + disabledColorGroup = palette().active(); + disabledColorGroup.setColor(QColorGroup::Text, palette().disabled().text()); + inactivedColorGroup = palette().active(); + inactivedColorGroup.setColor(QColorGroup::Highlight, palette().disabled().highlight()); + + connect(this, SIGNAL(selectionChanged(void)), + SLOT(updateSelection(void))); + + if (name) { + configSettings->beginGroup(name); + showName = configSettings->readBoolEntry("/showName", false); + showRange = configSettings->readBoolEntry("/showRange", false); + showData = configSettings->readBoolEntry("/showData", false); + optMode = (enum optionMode)configSettings->readNumEntry("/optionMode", false); + configSettings->endGroup(); + connect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings())); + } + + for (i = 0; i < colNr; i++) + colMap[i] = colRevMap[i] = -1; + addColumn(promptColIdx, _("Option")); + + reinit(); +} + +bool ConfigList::menuSkip(struct menu *menu) +{ + if (optMode == normalOpt && menu_is_visible(menu)) + return false; + if (optMode == promptOpt && menu_has_prompt(menu)) + return false; + if (optMode == allOpt) + return false; + return true; +} + +void ConfigList::reinit(void) +{ + removeColumn(dataColIdx); + removeColumn(yesColIdx); + removeColumn(modColIdx); + removeColumn(noColIdx); + removeColumn(nameColIdx); + + if (showName) + addColumn(nameColIdx, _("Name")); + if (showRange) { + addColumn(noColIdx, "N"); + addColumn(modColIdx, "M"); + addColumn(yesColIdx, "Y"); + } + if (showData) + addColumn(dataColIdx, _("Value")); + + updateListAll(); +} + +void ConfigList::saveSettings(void) +{ + if (name()) { + configSettings->beginGroup(name()); + configSettings->writeEntry("/showName", showName); + configSettings->writeEntry("/showRange", showRange); + configSettings->writeEntry("/showData", showData); + configSettings->writeEntry("/optionMode", (int)optMode); + configSettings->endGroup(); + } +} + +ConfigItem* ConfigList::findConfigItem(struct menu *menu) +{ + ConfigItem* item = (ConfigItem*)menu->data; + + for (; item; item = item->nextItem) { + if (this == item->listView()) + break; + } + + return item; +} + +void ConfigList::updateSelection(void) +{ + struct menu *menu; + enum prop_type type; + + ConfigItem* item = (ConfigItem*)selectedItem(); + if (!item) + return; + + menu = item->menu; + emit menuChanged(menu); + if (!menu) + return; + type = menu->prompt ? menu->prompt->type : P_UNKNOWN; + if (mode == menuMode && type == P_MENU) + emit menuSelected(menu); +} + +void ConfigList::updateList(ConfigItem* item) +{ + ConfigItem* last = 0; + + if (!rootEntry) { + if (mode != listMode) + goto update; + Q3ListViewItemIterator it(this); + ConfigItem* item; + + for (; it.current(); ++it) { + item = (ConfigItem*)it.current(); + if (!item->menu) + continue; + item->testUpdateMenu(menu_is_visible(item->menu)); + } + return; + } + + if (rootEntry != &rootmenu && (mode == singleMode || + (mode == symbolMode && rootEntry->parent != &rootmenu))) { + item = firstChild(); + if (!item) + item = new ConfigItem(this, 0, true); + last = item; + } + if ((mode == singleMode || (mode == symbolMode && !(rootEntry->flags & MENU_ROOT))) && + rootEntry->sym && rootEntry->prompt) { + item = last ? last->nextSibling() : firstChild(); + if (!item) + item = new ConfigItem(this, last, rootEntry, true); + else + item->testUpdateMenu(true); + + updateMenuList(item, rootEntry); + triggerUpdate(); + return; + } +update: + updateMenuList(this, rootEntry); + triggerUpdate(); +} + +void ConfigList::setValue(ConfigItem* item, tristate val) +{ + struct symbol* sym; + int type; + tristate oldval; + + sym = item->menu ? item->menu->sym : 0; + if (!sym) + return; + + type = sym_get_type(sym); + switch (type) { + case S_BOOLEAN: + case S_TRISTATE: + oldval = sym_get_tristate_value(sym); + + if (!sym_set_tristate_value(sym, val)) + return; + if (oldval == no && item->menu->list) + item->setOpen(TRUE); + parent()->updateList(item); + break; + } +} + +void ConfigList::changeValue(ConfigItem* item) +{ + struct symbol* sym; + struct menu* menu; + int type, oldexpr, newexpr; + + menu = item->menu; + if (!menu) + return; + sym = menu->sym; + if (!sym) { + if (item->menu->list) + item->setOpen(!item->isOpen()); + return; + } + + type = sym_get_type(sym); + switch (type) { + case S_BOOLEAN: + case S_TRISTATE: + oldexpr = sym_get_tristate_value(sym); + newexpr = sym_toggle_tristate_value(sym); + if (item->menu->list) { + if (oldexpr == newexpr) + item->setOpen(!item->isOpen()); + else if (oldexpr == no) + item->setOpen(TRUE); + } + if (oldexpr != newexpr) + parent()->updateList(item); + break; + case S_INT: + case S_HEX: + case S_STRING: + if (colMap[dataColIdx] >= 0) + item->startRename(colMap[dataColIdx]); + else + parent()->lineEdit->show(item); + break; + } +} + +void ConfigList::setRootMenu(struct menu *menu) +{ + enum prop_type type; + + if (rootEntry == menu) + return; + type = menu && menu->prompt ? menu->prompt->type : P_UNKNOWN; + if (type != P_MENU) + return; + updateMenuList(this, 0); + rootEntry = menu; + updateListAll(); + setSelected(currentItem(), hasFocus()); + ensureItemVisible(currentItem()); +} + +void ConfigList::setParentMenu(void) +{ + ConfigItem* item; + struct menu *oldroot; + + oldroot = rootEntry; + if (rootEntry == &rootmenu) + return; + setRootMenu(menu_get_parent_menu(rootEntry->parent)); + + Q3ListViewItemIterator it(this); + for (; (item = (ConfigItem*)it.current()); it++) { + if (item->menu == oldroot) { + setCurrentItem(item); + ensureItemVisible(item); + break; + } + } +} + +/* + * update all the children of a menu entry + * removes/adds the entries from the parent widget as necessary + * + * parent: either the menu list widget or a menu entry widget + * menu: entry to be updated + */ +template +void ConfigList::updateMenuList(P* parent, struct menu* menu) +{ + struct menu* child; + ConfigItem* item; + ConfigItem* last; + bool visible; + enum prop_type type; + + if (!menu) { + while ((item = parent->firstChild())) + delete item; + return; + } + + last = parent->firstChild(); + if (last && !last->goParent) + last = 0; + for (child = menu->list; child; child = child->next) { + item = last ? last->nextSibling() : parent->firstChild(); + type = child->prompt ? child->prompt->type : P_UNKNOWN; + + switch (mode) { + case menuMode: + if (!(child->flags & MENU_ROOT)) + goto hide; + break; + case symbolMode: + if (child->flags & MENU_ROOT) + goto hide; + break; + default: + break; + } + + visible = menu_is_visible(child); + if (!menuSkip(child)) { + if (!child->sym && !child->list && !child->prompt) + continue; + if (!item || item->menu != child) + item = new ConfigItem(parent, last, child, visible); + else + item->testUpdateMenu(visible); + + if (mode == fullMode || mode == menuMode || type != P_MENU) + updateMenuList(item, child); + else + updateMenuList(item, 0); + last = item; + continue; + } + hide: + if (item && item->menu == child) { + last = parent->firstChild(); + if (last == item) + last = 0; + else while (last->nextSibling() != item) + last = last->nextSibling(); + delete item; + } + } +} + +void ConfigList::keyPressEvent(QKeyEvent* ev) +{ + Q3ListViewItem* i = currentItem(); + ConfigItem* item; + struct menu *menu; + enum prop_type type; + + if (ev->key() == Qt::Key_Escape && mode != fullMode && mode != listMode) { + emit parentSelected(); + ev->accept(); + return; + } + + if (!i) { + Parent::keyPressEvent(ev); + return; + } + item = (ConfigItem*)i; + + switch (ev->key()) { + case Qt::Key_Return: + case Qt::Key_Enter: + if (item->goParent) { + emit parentSelected(); + break; + } + menu = item->menu; + if (!menu) + break; + type = menu->prompt ? menu->prompt->type : P_UNKNOWN; + if (type == P_MENU && rootEntry != menu && + mode != fullMode && mode != menuMode) { + emit menuSelected(menu); + break; + } + case Qt::Key_Space: + changeValue(item); + break; + case Qt::Key_N: + setValue(item, no); + break; + case Qt::Key_M: + setValue(item, mod); + break; + case Qt::Key_Y: + setValue(item, yes); + break; + default: + Parent::keyPressEvent(ev); + return; + } + ev->accept(); +} + +void ConfigList::contentsMousePressEvent(QMouseEvent* e) +{ + //QPoint p(contentsToViewport(e->pos())); + //printf("contentsMousePressEvent: %d,%d\n", p.x(), p.y()); + Parent::contentsMousePressEvent(e); +} + +void ConfigList::contentsMouseReleaseEvent(QMouseEvent* e) +{ + QPoint p(contentsToViewport(e->pos())); + ConfigItem* item = (ConfigItem*)itemAt(p); + struct menu *menu; + enum prop_type ptype; + const QPixmap* pm; + int idx, x; + + if (!item) + goto skip; + + menu = item->menu; + x = header()->offset() + p.x(); + idx = colRevMap[header()->sectionAt(x)]; + switch (idx) { + case promptColIdx: + pm = item->pixmap(promptColIdx); + if (pm) { + int off = header()->sectionPos(0) + itemMargin() + + treeStepSize() * (item->depth() + (rootIsDecorated() ? 1 : 0)); + if (x >= off && x < off + pm->width()) { + if (item->goParent) { + emit parentSelected(); + break; + } else if (!menu) + break; + ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN; + if (ptype == P_MENU && rootEntry != menu && + mode != fullMode && mode != menuMode) + emit menuSelected(menu); + else + changeValue(item); + } + } + break; + case noColIdx: + setValue(item, no); + break; + case modColIdx: + setValue(item, mod); + break; + case yesColIdx: + setValue(item, yes); + break; + case dataColIdx: + changeValue(item); + break; + } + +skip: + //printf("contentsMouseReleaseEvent: %d,%d\n", p.x(), p.y()); + Parent::contentsMouseReleaseEvent(e); +} + +void ConfigList::contentsMouseMoveEvent(QMouseEvent* e) +{ + //QPoint p(contentsToViewport(e->pos())); + //printf("contentsMouseMoveEvent: %d,%d\n", p.x(), p.y()); + Parent::contentsMouseMoveEvent(e); +} + +void ConfigList::contentsMouseDoubleClickEvent(QMouseEvent* e) +{ + QPoint p(contentsToViewport(e->pos())); + ConfigItem* item = (ConfigItem*)itemAt(p); + struct menu *menu; + enum prop_type ptype; + + if (!item) + goto skip; + if (item->goParent) { + emit parentSelected(); + goto skip; + } + menu = item->menu; + if (!menu) + goto skip; + ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN; + if (ptype == P_MENU && (mode == singleMode || mode == symbolMode)) + emit menuSelected(menu); + else if (menu->sym) + changeValue(item); + +skip: + //printf("contentsMouseDoubleClickEvent: %d,%d\n", p.x(), p.y()); + Parent::contentsMouseDoubleClickEvent(e); +} + +void ConfigList::focusInEvent(QFocusEvent *e) +{ + struct menu *menu = NULL; + + Parent::focusInEvent(e); + + ConfigItem* item = (ConfigItem *)currentItem(); + if (item) { + setSelected(item, TRUE); + menu = item->menu; + } + emit gotFocus(menu); +} + +void ConfigList::contextMenuEvent(QContextMenuEvent *e) +{ + if (e->y() <= header()->geometry().bottom()) { + if (!headerPopup) { + Q3Action *action; + + headerPopup = new Q3PopupMenu(this); + action = new Q3Action(NULL, _("Show Name"), 0, this); + action->setToggleAction(TRUE); + connect(action, SIGNAL(toggled(bool)), + parent(), SLOT(setShowName(bool))); + connect(parent(), SIGNAL(showNameChanged(bool)), + action, SLOT(setOn(bool))); + action->setOn(showName); + action->addTo(headerPopup); + action = new Q3Action(NULL, _("Show Range"), 0, this); + action->setToggleAction(TRUE); + connect(action, SIGNAL(toggled(bool)), + parent(), SLOT(setShowRange(bool))); + connect(parent(), SIGNAL(showRangeChanged(bool)), + action, SLOT(setOn(bool))); + action->setOn(showRange); + action->addTo(headerPopup); + action = new Q3Action(NULL, _("Show Data"), 0, this); + action->setToggleAction(TRUE); + connect(action, SIGNAL(toggled(bool)), + parent(), SLOT(setShowData(bool))); + connect(parent(), SIGNAL(showDataChanged(bool)), + action, SLOT(setOn(bool))); + action->setOn(showData); + action->addTo(headerPopup); + } + headerPopup->exec(e->globalPos()); + e->accept(); + } else + e->ignore(); +} + +ConfigView*ConfigView::viewList; +QAction *ConfigView::showNormalAction; +QAction *ConfigView::showAllAction; +QAction *ConfigView::showPromptAction; + +ConfigView::ConfigView(QWidget* parent, const char *name) + : Parent(parent, name) +{ + list = new ConfigList(this, name); + lineEdit = new ConfigLineEdit(this); + lineEdit->hide(); + + this->nextView = viewList; + viewList = this; +} + +ConfigView::~ConfigView(void) +{ + ConfigView** vp; + + for (vp = &viewList; *vp; vp = &(*vp)->nextView) { + if (*vp == this) { + *vp = nextView; + break; + } + } +} + +void ConfigView::setOptionMode(QAction *act) +{ + if (act == showNormalAction) + list->optMode = normalOpt; + else if (act == showAllAction) + list->optMode = allOpt; + else + list->optMode = promptOpt; + + list->updateListAll(); +} + +void ConfigView::setShowName(bool b) +{ + if (list->showName != b) { + list->showName = b; + list->reinit(); + emit showNameChanged(b); + } +} + +void ConfigView::setShowRange(bool b) +{ + if (list->showRange != b) { + list->showRange = b; + list->reinit(); + emit showRangeChanged(b); + } +} + +void ConfigView::setShowData(bool b) +{ + if (list->showData != b) { + list->showData = b; + list->reinit(); + emit showDataChanged(b); + } +} + +void ConfigList::setAllOpen(bool open) +{ + Q3ListViewItemIterator it(this); + + for (; it.current(); it++) + it.current()->setOpen(open); +} + +void ConfigView::updateList(ConfigItem* item) +{ + ConfigView* v; + + for (v = viewList; v; v = v->nextView) + v->list->updateList(item); +} + +void ConfigView::updateListAll(void) +{ + ConfigView* v; + + for (v = viewList; v; v = v->nextView) + v->list->updateListAll(); +} + +ConfigInfoView::ConfigInfoView(QWidget* parent, const char *name) + : Parent(parent, name), sym(0), _menu(0) +{ + if (name) { + configSettings->beginGroup(name); + _showDebug = configSettings->readBoolEntry("/showDebug", false); + configSettings->endGroup(); + connect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings())); + } +} + +void ConfigInfoView::saveSettings(void) +{ + if (name()) { + configSettings->beginGroup(name()); + configSettings->writeEntry("/showDebug", showDebug()); + configSettings->endGroup(); + } +} + +void ConfigInfoView::setShowDebug(bool b) +{ + if (_showDebug != b) { + _showDebug = b; + if (_menu) + menuInfo(); + else if (sym) + symbolInfo(); + emit showDebugChanged(b); + } +} + +void ConfigInfoView::setInfo(struct menu *m) +{ + if (_menu == m) + return; + _menu = m; + sym = NULL; + if (!_menu) + clear(); + else + menuInfo(); +} + +void ConfigInfoView::symbolInfo(void) +{ + QString str; + + str += "Symbol: "; + str += print_filter(sym->name); + str += "

value: "; + str += print_filter(sym_get_string_value(sym)); + str += "
visibility: "; + str += sym->visible == yes ? "y" : sym->visible == mod ? "m" : "n"; + str += "
"; + str += debug_info(sym); + + setText(str); +} + +void ConfigInfoView::menuInfo(void) +{ + struct symbol* sym; + QString head, debug, help; + + sym = _menu->sym; + if (sym) { + if (_menu->prompt) { + head += ""; + head += print_filter(_(_menu->prompt->text)); + head += ""; + if (sym->name) { + head += " ("; + if (showDebug()) + head += QString().sprintf("", sym); + head += print_filter(sym->name); + if (showDebug()) + head += ""; + head += ")"; + } + } else if (sym->name) { + head += ""; + if (showDebug()) + head += QString().sprintf("", sym); + head += print_filter(sym->name); + if (showDebug()) + head += ""; + head += ""; + } + head += "

"; + + if (showDebug()) + debug = debug_info(sym); + + struct gstr help_gstr = str_new(); + menu_get_ext_help(_menu, &help_gstr); + help = print_filter(str_get(&help_gstr)); + str_free(&help_gstr); + } else if (_menu->prompt) { + head += ""; + head += print_filter(_(_menu->prompt->text)); + head += "

"; + if (showDebug()) { + if (_menu->prompt->visible.expr) { + debug += "  dep: "; + expr_print(_menu->prompt->visible.expr, expr_print_help, &debug, E_NONE); + debug += "

"; + } + } + } + if (showDebug()) + debug += QString().sprintf("defined at %s:%d

", _menu->file->name, _menu->lineno); + + setText(head + debug + help); +} + +QString ConfigInfoView::debug_info(struct symbol *sym) +{ + QString debug; + + debug += "type: "; + debug += print_filter(sym_type_name(sym->type)); + if (sym_is_choice(sym)) + debug += " (choice)"; + debug += "
"; + if (sym->rev_dep.expr) { + debug += "reverse dep: "; + expr_print(sym->rev_dep.expr, expr_print_help, &debug, E_NONE); + debug += "
"; + } + for (struct property *prop = sym->prop; prop; prop = prop->next) { + switch (prop->type) { + case P_PROMPT: + case P_MENU: + debug += QString().sprintf("prompt: ", prop->menu); + debug += print_filter(_(prop->text)); + debug += "
"; + break; + case P_DEFAULT: + case P_SELECT: + case P_RANGE: + case P_ENV: + debug += prop_get_type_name(prop->type); + debug += ": "; + expr_print(prop->expr, expr_print_help, &debug, E_NONE); + debug += "
"; + break; + case P_CHOICE: + if (sym_is_choice(sym)) { + debug += "choice: "; + expr_print(prop->expr, expr_print_help, &debug, E_NONE); + debug += "
"; + } + break; + default: + debug += "unknown property: "; + debug += prop_get_type_name(prop->type); + debug += "
"; + } + if (prop->visible.expr) { + debug += "    dep: "; + expr_print(prop->visible.expr, expr_print_help, &debug, E_NONE); + debug += "
"; + } + } + debug += "
"; + + return debug; +} + +QString ConfigInfoView::print_filter(const QString &str) +{ + QRegExp re("[<>&\"\\n]"); + QString res = str; + for (int i = 0; (i = res.find(re, i)) >= 0;) { + switch (res[i].latin1()) { + case '<': + res.replace(i, 1, "<"); + i += 4; + break; + case '>': + res.replace(i, 1, ">"); + i += 4; + break; + case '&': + res.replace(i, 1, "&"); + i += 5; + break; + case '"': + res.replace(i, 1, """); + i += 6; + break; + case '\n': + res.replace(i, 1, "
"); + i += 4; + break; + } + } + return res; +} + +void ConfigInfoView::expr_print_help(void *data, struct symbol *sym, const char *str) +{ + QString* text = reinterpret_cast(data); + QString str2 = print_filter(str); + + if (sym && sym->name && !(sym->flags & SYMBOL_CONST)) { + *text += QString().sprintf("", sym); + *text += str2; + *text += ""; + } else + *text += str2; +} + +Q3PopupMenu* ConfigInfoView::createPopupMenu(const QPoint& pos) +{ + Q3PopupMenu* popup = Parent::createPopupMenu(pos); + Q3Action* action = new Q3Action(NULL, _("Show Debug Info"), 0, popup); + action->setToggleAction(TRUE); + connect(action, SIGNAL(toggled(bool)), SLOT(setShowDebug(bool))); + connect(this, SIGNAL(showDebugChanged(bool)), action, SLOT(setOn(bool))); + action->setOn(showDebug()); + popup->insertSeparator(); + action->addTo(popup); + return popup; +} + +void ConfigInfoView::contentsContextMenuEvent(QContextMenuEvent *e) +{ + Parent::contentsContextMenuEvent(e); +} + +ConfigSearchWindow::ConfigSearchWindow(ConfigMainWindow* parent, const char *name) + : Parent(parent, name), result(NULL) +{ + setCaption("Search Config"); + + QVBoxLayout* layout1 = new QVBoxLayout(this, 11, 6); + QHBoxLayout* layout2 = new QHBoxLayout(0, 0, 6); + layout2->addWidget(new QLabel(_("Find:"), this)); + editField = new QLineEdit(this); + connect(editField, SIGNAL(returnPressed()), SLOT(search())); + layout2->addWidget(editField); + searchButton = new QPushButton(_("Search"), this); + searchButton->setAutoDefault(FALSE); + connect(searchButton, SIGNAL(clicked()), SLOT(search())); + layout2->addWidget(searchButton); + layout1->addLayout(layout2); + + split = new QSplitter(this); + split->setOrientation(Qt::Vertical); + list = new ConfigView(split, name); + list->list->mode = listMode; + info = new ConfigInfoView(split, name); + connect(list->list, SIGNAL(menuChanged(struct menu *)), + info, SLOT(setInfo(struct menu *))); + connect(list->list, SIGNAL(menuChanged(struct menu *)), + parent, SLOT(setMenuLink(struct menu *))); + + layout1->addWidget(split); + + if (name) { + int x, y, width, height; + bool ok; + + configSettings->beginGroup(name); + width = configSettings->readNumEntry("/window width", parent->width() / 2); + height = configSettings->readNumEntry("/window height", parent->height() / 2); + resize(width, height); + x = configSettings->readNumEntry("/window x", 0, &ok); + if (ok) + y = configSettings->readNumEntry("/window y", 0, &ok); + if (ok) + move(x, y); + Q3ValueList sizes = configSettings->readSizes("/split", &ok); + if (ok) + split->setSizes(sizes); + configSettings->endGroup(); + connect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings())); + } +} + +void ConfigSearchWindow::saveSettings(void) +{ + if (name()) { + configSettings->beginGroup(name()); + configSettings->writeEntry("/window x", pos().x()); + configSettings->writeEntry("/window y", pos().y()); + configSettings->writeEntry("/window width", size().width()); + configSettings->writeEntry("/window height", size().height()); + configSettings->writeSizes("/split", split->sizes()); + configSettings->endGroup(); + } +} + +void ConfigSearchWindow::search(void) +{ + struct symbol **p; + struct property *prop; + ConfigItem *lastItem = NULL; + + free(result); + list->list->clear(); + info->clear(); + + result = sym_re_search(editField->text().latin1()); + if (!result) + return; + for (p = result; *p; p++) { + for_all_prompts((*p), prop) + lastItem = new ConfigItem(list->list, lastItem, prop->menu, + menu_is_visible(prop->menu)); + } +} + +/* + * Construct the complete config widget + */ +ConfigMainWindow::ConfigMainWindow(void) + : searchWindow(0) +{ + QMenuBar* menu; + bool ok; + int x, y, width, height; + char title[256]; + + QDesktopWidget *d = configApp->desktop(); + snprintf(title, sizeof(title), "%s%s", + rootmenu.prompt->text, +#if QT_VERSION < 0x040000 + " (Qt3)" +#else + "" +#endif + ); + setCaption(title); + + width = configSettings->readNumEntry("/window width", d->width() - 64); + height = configSettings->readNumEntry("/window height", d->height() - 64); + resize(width, height); + x = configSettings->readNumEntry("/window x", 0, &ok); + if (ok) + y = configSettings->readNumEntry("/window y", 0, &ok); + if (ok) + move(x, y); + + split1 = new QSplitter(this); + split1->setOrientation(Qt::Horizontal); + setCentralWidget(split1); + + menuView = new ConfigView(split1, "menu"); + menuList = menuView->list; + + split2 = new QSplitter(split1); + split2->setOrientation(Qt::Vertical); + + // create config tree + configView = new ConfigView(split2, "config"); + configList = configView->list; + + helpText = new ConfigInfoView(split2, "help"); + helpText->setTextFormat(Qt::RichText); + + setTabOrder(configList, helpText); + configList->setFocus(); + + menu = menuBar(); + toolBar = new Q3ToolBar("Tools", this); + + backAction = new Q3Action("Back", QPixmap(xpm_back), _("Back"), 0, this); + connect(backAction, SIGNAL(activated()), SLOT(goBack())); + backAction->setEnabled(FALSE); + Q3Action *quitAction = new Q3Action("Quit", _("&Quit"), Qt::CTRL + Qt::Key_Q, this); + connect(quitAction, SIGNAL(activated()), SLOT(close())); + Q3Action *loadAction = new Q3Action("Load", QPixmap(xpm_load), _("&Load"), Qt::CTRL + Qt::Key_L, this); + connect(loadAction, SIGNAL(activated()), SLOT(loadConfig())); + saveAction = new Q3Action("Save", QPixmap(xpm_save), _("&Save"), Qt::CTRL + Qt::Key_S, this); + connect(saveAction, SIGNAL(activated()), SLOT(saveConfig())); + conf_set_changed_callback(conf_changed); + // Set saveAction's initial state + conf_changed(); + Q3Action *saveAsAction = new Q3Action("Save As...", _("Save &As..."), 0, this); + connect(saveAsAction, SIGNAL(activated()), SLOT(saveConfigAs())); + Q3Action *searchAction = new Q3Action("Find", _("&Find"), Qt::CTRL + Qt::Key_F, this); + connect(searchAction, SIGNAL(activated()), SLOT(searchConfig())); + Q3Action *singleViewAction = new Q3Action("Single View", QPixmap(xpm_single_view), _("Single View"), 0, this); + connect(singleViewAction, SIGNAL(activated()), SLOT(showSingleView())); + Q3Action *splitViewAction = new Q3Action("Split View", QPixmap(xpm_split_view), _("Split View"), 0, this); + connect(splitViewAction, SIGNAL(activated()), SLOT(showSplitView())); + Q3Action *fullViewAction = new Q3Action("Full View", QPixmap(xpm_tree_view), _("Full View"), 0, this); + connect(fullViewAction, SIGNAL(activated()), SLOT(showFullView())); + + Q3Action *showNameAction = new Q3Action(NULL, _("Show Name"), 0, this); + showNameAction->setToggleAction(TRUE); + connect(showNameAction, SIGNAL(toggled(bool)), configView, SLOT(setShowName(bool))); + connect(configView, SIGNAL(showNameChanged(bool)), showNameAction, SLOT(setOn(bool))); + showNameAction->setOn(configView->showName()); + Q3Action *showRangeAction = new Q3Action(NULL, _("Show Range"), 0, this); + showRangeAction->setToggleAction(TRUE); + connect(showRangeAction, SIGNAL(toggled(bool)), configView, SLOT(setShowRange(bool))); + connect(configView, SIGNAL(showRangeChanged(bool)), showRangeAction, SLOT(setOn(bool))); + showRangeAction->setOn(configList->showRange); + Q3Action *showDataAction = new Q3Action(NULL, _("Show Data"), 0, this); + showDataAction->setToggleAction(TRUE); + connect(showDataAction, SIGNAL(toggled(bool)), configView, SLOT(setShowData(bool))); + connect(configView, SIGNAL(showDataChanged(bool)), showDataAction, SLOT(setOn(bool))); + showDataAction->setOn(configList->showData); + + QActionGroup *optGroup = new QActionGroup(this); + optGroup->setExclusive(TRUE); + connect(optGroup, SIGNAL(selected(QAction *)), configView, + SLOT(setOptionMode(QAction *))); + connect(optGroup, SIGNAL(selected(QAction *)), menuView, + SLOT(setOptionMode(QAction *))); + +#if QT_VERSION >= 0x040000 + configView->showNormalAction = new QAction(_("Show Normal Options"), optGroup); + configView->showAllAction = new QAction(_("Show All Options"), optGroup); + configView->showPromptAction = new QAction(_("Show Prompt Options"), optGroup); +#else + configView->showNormalAction = new QAction(_("Show Normal Options"), 0, optGroup); + configView->showAllAction = new QAction(_("Show All Options"), 0, optGroup); + configView->showPromptAction = new QAction(_("Show Prompt Options"), 0, optGroup); +#endif + configView->showNormalAction->setToggleAction(TRUE); + configView->showNormalAction->setOn(configList->optMode == normalOpt); + configView->showAllAction->setToggleAction(TRUE); + configView->showAllAction->setOn(configList->optMode == allOpt); + configView->showPromptAction->setToggleAction(TRUE); + configView->showPromptAction->setOn(configList->optMode == promptOpt); + + Q3Action *showDebugAction = new Q3Action(NULL, _("Show Debug Info"), 0, this); + showDebugAction->setToggleAction(TRUE); + connect(showDebugAction, SIGNAL(toggled(bool)), helpText, SLOT(setShowDebug(bool))); + connect(helpText, SIGNAL(showDebugChanged(bool)), showDebugAction, SLOT(setOn(bool))); + showDebugAction->setOn(helpText->showDebug()); + + Q3Action *showIntroAction = new Q3Action(NULL, _("Introduction"), 0, this); + connect(showIntroAction, SIGNAL(activated()), SLOT(showIntro())); + Q3Action *showAboutAction = new Q3Action(NULL, _("About"), 0, this); + connect(showAboutAction, SIGNAL(activated()), SLOT(showAbout())); + + // init tool bar + backAction->addTo(toolBar); + toolBar->addSeparator(); + loadAction->addTo(toolBar); + saveAction->addTo(toolBar); + toolBar->addSeparator(); + singleViewAction->addTo(toolBar); + splitViewAction->addTo(toolBar); + fullViewAction->addTo(toolBar); + + // create config menu + Q3PopupMenu* config = new Q3PopupMenu(this); + menu->insertItem(_("&File"), config); + loadAction->addTo(config); + saveAction->addTo(config); + saveAsAction->addTo(config); + config->insertSeparator(); + quitAction->addTo(config); + + // create edit menu + Q3PopupMenu* editMenu = new Q3PopupMenu(this); + menu->insertItem(_("&Edit"), editMenu); + searchAction->addTo(editMenu); + + // create options menu + Q3PopupMenu* optionMenu = new Q3PopupMenu(this); + menu->insertItem(_("&Option"), optionMenu); + showNameAction->addTo(optionMenu); + showRangeAction->addTo(optionMenu); + showDataAction->addTo(optionMenu); + optionMenu->insertSeparator(); + optGroup->addTo(optionMenu); + optionMenu->insertSeparator(); + + // create help menu + Q3PopupMenu* helpMenu = new Q3PopupMenu(this); + menu->insertSeparator(); + menu->insertItem(_("&Help"), helpMenu); + showIntroAction->addTo(helpMenu); + showAboutAction->addTo(helpMenu); + + connect(configList, SIGNAL(menuChanged(struct menu *)), + helpText, SLOT(setInfo(struct menu *))); + connect(configList, SIGNAL(menuSelected(struct menu *)), + SLOT(changeMenu(struct menu *))); + connect(configList, SIGNAL(parentSelected()), + SLOT(goBack())); + connect(menuList, SIGNAL(menuChanged(struct menu *)), + helpText, SLOT(setInfo(struct menu *))); + connect(menuList, SIGNAL(menuSelected(struct menu *)), + SLOT(changeMenu(struct menu *))); + + connect(configList, SIGNAL(gotFocus(struct menu *)), + helpText, SLOT(setInfo(struct menu *))); + connect(menuList, SIGNAL(gotFocus(struct menu *)), + helpText, SLOT(setInfo(struct menu *))); + connect(menuList, SIGNAL(gotFocus(struct menu *)), + SLOT(listFocusChanged(void))); + connect(helpText, SIGNAL(menuSelected(struct menu *)), + SLOT(setMenuLink(struct menu *))); + + QString listMode = configSettings->readEntry("/listMode", "symbol"); + if (listMode == "single") + showSingleView(); + else if (listMode == "full") + showFullView(); + else /*if (listMode == "split")*/ + showSplitView(); + + // UI setup done, restore splitter positions + Q3ValueList sizes = configSettings->readSizes("/split1", &ok); + if (ok) + split1->setSizes(sizes); + + sizes = configSettings->readSizes("/split2", &ok); + if (ok) + split2->setSizes(sizes); +} + +void ConfigMainWindow::loadConfig(void) +{ + QString s = Q3FileDialog::getOpenFileName(conf_get_configname(), NULL, this); + if (s.isNull()) + return; + if (conf_read(QFile::encodeName(s))) + QMessageBox::information(this, "qconf", _("Unable to load configuration!")); + ConfigView::updateListAll(); +} + +bool ConfigMainWindow::saveConfig(void) +{ + if (conf_write(NULL)) { + QMessageBox::information(this, "qconf", _("Unable to save configuration!")); + return false; + } + return true; +} + +void ConfigMainWindow::saveConfigAs(void) +{ + QString s = Q3FileDialog::getSaveFileName(conf_get_configname(), NULL, this); + if (s.isNull()) + return; + saveConfig(); +} + +void ConfigMainWindow::searchConfig(void) +{ + if (!searchWindow) + searchWindow = new ConfigSearchWindow(this, "search"); + searchWindow->show(); +} + +void ConfigMainWindow::changeMenu(struct menu *menu) +{ + configList->setRootMenu(menu); + if (configList->rootEntry->parent == &rootmenu) + backAction->setEnabled(FALSE); + else + backAction->setEnabled(TRUE); +} + +void ConfigMainWindow::setMenuLink(struct menu *menu) +{ + struct menu *parent; + ConfigList* list = NULL; + ConfigItem* item; + + if (configList->menuSkip(menu)) + return; + + switch (configList->mode) { + case singleMode: + list = configList; + parent = menu_get_parent_menu(menu); + if (!parent) + return; + list->setRootMenu(parent); + break; + case symbolMode: + if (menu->flags & MENU_ROOT) { + configList->setRootMenu(menu); + configList->clearSelection(); + list = menuList; + } else { + list = configList; + parent = menu_get_parent_menu(menu->parent); + if (!parent) + return; + item = menuList->findConfigItem(parent); + if (item) { + menuList->setSelected(item, TRUE); + menuList->ensureItemVisible(item); + } + list->setRootMenu(parent); + } + break; + case fullMode: + list = configList; + break; + default: + break; + } + + if (list) { + item = list->findConfigItem(menu); + if (item) { + list->setSelected(item, TRUE); + list->ensureItemVisible(item); + list->setFocus(); + } + } +} + +void ConfigMainWindow::listFocusChanged(void) +{ + if (menuList->mode == menuMode) + configList->clearSelection(); +} + +void ConfigMainWindow::goBack(void) +{ + ConfigItem* item; + + configList->setParentMenu(); + if (configList->rootEntry == &rootmenu) + backAction->setEnabled(FALSE); + item = (ConfigItem*)menuList->selectedItem(); + while (item) { + if (item->menu == configList->rootEntry) { + menuList->setSelected(item, TRUE); + break; + } + item = (ConfigItem*)item->parent(); + } +} + +void ConfigMainWindow::showSingleView(void) +{ + menuView->hide(); + menuList->setRootMenu(0); + configList->mode = singleMode; + if (configList->rootEntry == &rootmenu) + configList->updateListAll(); + else + configList->setRootMenu(&rootmenu); + configList->setAllOpen(TRUE); + configList->setFocus(); +} + +void ConfigMainWindow::showSplitView(void) +{ + configList->mode = symbolMode; + if (configList->rootEntry == &rootmenu) + configList->updateListAll(); + else + configList->setRootMenu(&rootmenu); + configList->setAllOpen(TRUE); + configApp->processEvents(); + menuList->mode = menuMode; + menuList->setRootMenu(&rootmenu); + menuList->setAllOpen(TRUE); + menuView->show(); + menuList->setFocus(); +} + +void ConfigMainWindow::showFullView(void) +{ + menuView->hide(); + menuList->setRootMenu(0); + configList->mode = fullMode; + if (configList->rootEntry == &rootmenu) + configList->updateListAll(); + else + configList->setRootMenu(&rootmenu); + configList->setAllOpen(FALSE); + configList->setFocus(); +} + +/* + * ask for saving configuration before quitting + * TODO ask only when something changed + */ +void ConfigMainWindow::closeEvent(QCloseEvent* e) +{ + if (!conf_get_changed()) { + e->accept(); + return; + } + QMessageBox mb("qconf", _("Save configuration?"), QMessageBox::Warning, + QMessageBox::Yes | QMessageBox::Default, QMessageBox::No, QMessageBox::Cancel | QMessageBox::Escape); + mb.setButtonText(QMessageBox::Yes, _("&Save Changes")); + mb.setButtonText(QMessageBox::No, _("&Discard Changes")); + mb.setButtonText(QMessageBox::Cancel, _("Cancel Exit")); + switch (mb.exec()) { + case QMessageBox::Yes: + if (saveConfig()) + e->accept(); + else + e->ignore(); + break; + case QMessageBox::No: + e->accept(); + break; + case QMessageBox::Cancel: + e->ignore(); + break; + } +} + +void ConfigMainWindow::showIntro(void) +{ + static const QString str = _("Welcome to the qconf graphical configuration tool.\n\n" + "For each option, a blank box indicates the feature is disabled, a check\n" + "indicates it is enabled, and a dot indicates that it is to be compiled\n" + "as a module. Clicking on the box will cycle through the three states.\n\n" + "If you do not see an option (e.g., a device driver) that you believe\n" + "should be present, try turning on Show All Options under the Options menu.\n" + "Although there is no cross reference yet to help you figure out what other\n" + "options must be enabled to support the option you are interested in, you can\n" + "still view the help of a grayed-out option.\n\n" + "Toggling Show Debug Info under the Options menu will show the dependencies,\n" + "which you can then match by examining other options.\n\n"); + + QMessageBox::information(this, "qconf", str); +} + +void ConfigMainWindow::showAbout(void) +{ + static const QString str = _("qconf is Copyright (C) 2002 Roman Zippel .\n\n" + "Bug reports and feature request can also be entered at http://bugzilla.kernel.org/\n"); + + QMessageBox::information(this, "qconf", str); +} + +void ConfigMainWindow::saveSettings(void) +{ + configSettings->writeEntry("/window x", pos().x()); + configSettings->writeEntry("/window y", pos().y()); + configSettings->writeEntry("/window width", size().width()); + configSettings->writeEntry("/window height", size().height()); + + QString entry; + switch(configList->mode) { + case singleMode : + entry = "single"; + break; + + case symbolMode : + entry = "split"; + break; + + case fullMode : + entry = "full"; + break; + + default: + break; + } + configSettings->writeEntry("/listMode", entry); + + configSettings->writeSizes("/split1", split1->sizes()); + configSettings->writeSizes("/split2", split2->sizes()); +} + +void ConfigMainWindow::conf_changed(void) +{ + if (saveAction) + saveAction->setEnabled(conf_get_changed()); +} + +void fixup_rootmenu(struct menu *menu) +{ + struct menu *child; + static int menu_cnt = 0; + + menu->flags |= MENU_ROOT; + for (child = menu->list; child; child = child->next) { + if (child->prompt && child->prompt->type == P_MENU) { + menu_cnt++; + fixup_rootmenu(child); + menu_cnt--; + } else if (!menu_cnt) + fixup_rootmenu(child); + } +} + +static const char *progname; + +static void usage(void) +{ + printf(_("%s \n"), progname); + exit(0); +} + +int main(int ac, char** av) +{ + ConfigMainWindow* v; + const char *name; + + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + + progname = av[0]; + configApp = new QApplication(ac, av); + if (ac > 1 && av[1][0] == '-') { + switch (av[1][1]) { + case 'h': + case '?': + usage(); + } + name = av[2]; + } else + name = av[1]; + if (!name) + usage(); + + conf_parse(name); + fixup_rootmenu(&rootmenu); + conf_read(NULL); + //zconfdump(stdout); + + configSettings = new ConfigSettings(); + configSettings->beginGroup("/kconfig/qconf"); + v = new ConfigMainWindow(); + + //zconfdump(stdout); + configApp->setMainWidget(v); + configApp->connect(configApp, SIGNAL(lastWindowClosed()), SLOT(quit())); + configApp->connect(configApp, SIGNAL(aboutToQuit()), v, SLOT(saveSettings())); + v->show(); + configApp->exec(); + + configSettings->endGroup(); + delete configSettings; + + return 0; +} diff --git a/l4/tool/kconfig/scripts/kconfig/qconf.h b/l4/tool/kconfig/scripts/kconfig/qconf.h new file mode 100644 index 00000000..3715b3e7 --- /dev/null +++ b/l4/tool/kconfig/scripts/kconfig/qconf.h @@ -0,0 +1,337 @@ +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +#if QT_VERSION < 0x040000 +#include +#else +#include +#endif +#include + +#if QT_VERSION < 0x040000 +#define Q3ValueList QValueList +#define Q3PopupMenu QPopupMenu +#define Q3ListView QListView +#define Q3ListViewItem QListViewItem +#define Q3VBox QVBox +#define Q3TextBrowser QTextBrowser +#define Q3MainWindow QMainWindow +#define Q3Action QAction +#define Q3ToolBar QToolBar +#define Q3ListViewItemIterator QListViewItemIterator +#define Q3FileDialog QFileDialog +#endif + +class ConfigView; +class ConfigList; +class ConfigItem; +class ConfigLineEdit; +class ConfigMainWindow; + +class ConfigSettings : public QSettings { +public: + Q3ValueList readSizes(const QString& key, bool *ok); + bool writeSizes(const QString& key, const Q3ValueList& value); +}; + +enum colIdx { + promptColIdx, nameColIdx, noColIdx, modColIdx, yesColIdx, dataColIdx, colNr +}; +enum listMode { + singleMode, menuMode, symbolMode, fullMode, listMode +}; +enum optionMode { + normalOpt = 0, allOpt, promptOpt +}; + +class ConfigList : public Q3ListView { + Q_OBJECT + typedef class Q3ListView Parent; +public: + ConfigList(ConfigView* p, const char *name = 0); + void reinit(void); + ConfigView* parent(void) const + { + return (ConfigView*)Parent::parent(); + } + ConfigItem* findConfigItem(struct menu *); + +protected: + void keyPressEvent(QKeyEvent *e); + void contentsMousePressEvent(QMouseEvent *e); + void contentsMouseReleaseEvent(QMouseEvent *e); + void contentsMouseMoveEvent(QMouseEvent *e); + void contentsMouseDoubleClickEvent(QMouseEvent *e); + void focusInEvent(QFocusEvent *e); + void contextMenuEvent(QContextMenuEvent *e); + +public slots: + void setRootMenu(struct menu *menu); + + void updateList(ConfigItem *item); + void setValue(ConfigItem* item, tristate val); + void changeValue(ConfigItem* item); + void updateSelection(void); + void saveSettings(void); +signals: + void menuChanged(struct menu *menu); + void menuSelected(struct menu *menu); + void parentSelected(void); + void gotFocus(struct menu *); + +public: + void updateListAll(void) + { + updateAll = true; + updateList(NULL); + updateAll = false; + } + ConfigList* listView() + { + return this; + } + ConfigItem* firstChild() const + { + return (ConfigItem *)Parent::firstChild(); + } + int mapIdx(colIdx idx) + { + return colMap[idx]; + } + void addColumn(colIdx idx, const QString& label) + { + colMap[idx] = Parent::addColumn(label); + colRevMap[colMap[idx]] = idx; + } + void removeColumn(colIdx idx) + { + int col = colMap[idx]; + if (col >= 0) { + Parent::removeColumn(col); + colRevMap[col] = colMap[idx] = -1; + } + } + void setAllOpen(bool open); + void setParentMenu(void); + + bool menuSkip(struct menu *); + + template + void updateMenuList(P*, struct menu*); + + bool updateAll; + + QPixmap symbolYesPix, symbolModPix, symbolNoPix; + QPixmap choiceYesPix, choiceNoPix; + QPixmap menuPix, menuInvPix, menuBackPix, voidPix; + + bool showName, showRange, showData; + enum listMode mode; + enum optionMode optMode; + struct menu *rootEntry; + QColorGroup disabledColorGroup; + QColorGroup inactivedColorGroup; + Q3PopupMenu* headerPopup; + +private: + int colMap[colNr]; + int colRevMap[colNr]; +}; + +class ConfigItem : public Q3ListViewItem { + typedef class Q3ListViewItem Parent; +public: + ConfigItem(Q3ListView *parent, ConfigItem *after, struct menu *m, bool v) + : Parent(parent, after), menu(m), visible(v), goParent(false) + { + init(); + } + ConfigItem(ConfigItem *parent, ConfigItem *after, struct menu *m, bool v) + : Parent(parent, after), menu(m), visible(v), goParent(false) + { + init(); + } + ConfigItem(Q3ListView *parent, ConfigItem *after, bool v) + : Parent(parent, after), menu(0), visible(v), goParent(true) + { + init(); + } + ~ConfigItem(void); + void init(void); + void okRename(int col); + void updateMenu(void); + void testUpdateMenu(bool v); + ConfigList* listView() const + { + return (ConfigList*)Parent::listView(); + } + ConfigItem* firstChild() const + { + return (ConfigItem *)Parent::firstChild(); + } + ConfigItem* nextSibling() const + { + return (ConfigItem *)Parent::nextSibling(); + } + void setText(colIdx idx, const QString& text) + { + Parent::setText(listView()->mapIdx(idx), text); + } + QString text(colIdx idx) const + { + return Parent::text(listView()->mapIdx(idx)); + } + void setPixmap(colIdx idx, const QPixmap& pm) + { + Parent::setPixmap(listView()->mapIdx(idx), pm); + } + const QPixmap* pixmap(colIdx idx) const + { + return Parent::pixmap(listView()->mapIdx(idx)); + } + void paintCell(QPainter* p, const QColorGroup& cg, int column, int width, int align); + + ConfigItem* nextItem; + struct menu *menu; + bool visible; + bool goParent; +}; + +class ConfigLineEdit : public QLineEdit { + Q_OBJECT + typedef class QLineEdit Parent; +public: + ConfigLineEdit(ConfigView* parent); + ConfigView* parent(void) const + { + return (ConfigView*)Parent::parent(); + } + void show(ConfigItem *i); + void keyPressEvent(QKeyEvent *e); + +public: + ConfigItem *item; +}; + +class ConfigView : public Q3VBox { + Q_OBJECT + typedef class Q3VBox Parent; +public: + ConfigView(QWidget* parent, const char *name = 0); + ~ConfigView(void); + static void updateList(ConfigItem* item); + static void updateListAll(void); + + bool showName(void) const { return list->showName; } + bool showRange(void) const { return list->showRange; } + bool showData(void) const { return list->showData; } +public slots: + void setShowName(bool); + void setShowRange(bool); + void setShowData(bool); + void setOptionMode(QAction *); +signals: + void showNameChanged(bool); + void showRangeChanged(bool); + void showDataChanged(bool); +public: + ConfigList* list; + ConfigLineEdit* lineEdit; + + static ConfigView* viewList; + ConfigView* nextView; + + static QAction *showNormalAction; + static QAction *showAllAction; + static QAction *showPromptAction; +}; + +class ConfigInfoView : public Q3TextBrowser { + Q_OBJECT + typedef class Q3TextBrowser Parent; +public: + ConfigInfoView(QWidget* parent, const char *name = 0); + bool showDebug(void) const { return _showDebug; } + +public slots: + void setInfo(struct menu *menu); + void saveSettings(void); + void setShowDebug(bool); + +signals: + void showDebugChanged(bool); + void menuSelected(struct menu *); + +protected: + void symbolInfo(void); + void menuInfo(void); + QString debug_info(struct symbol *sym); + static QString print_filter(const QString &str); + static void expr_print_help(void *data, struct symbol *sym, const char *str); + Q3PopupMenu* createPopupMenu(const QPoint& pos); + void contentsContextMenuEvent(QContextMenuEvent *e); + + struct symbol *sym; + struct menu *_menu; + bool _showDebug; +}; + +class ConfigSearchWindow : public QDialog { + Q_OBJECT + typedef class QDialog Parent; +public: + ConfigSearchWindow(ConfigMainWindow* parent, const char *name = 0); + +public slots: + void saveSettings(void); + void search(void); + +protected: + QLineEdit* editField; + QPushButton* searchButton; + QSplitter* split; + ConfigView* list; + ConfigInfoView* info; + + struct symbol **result; +}; + +class ConfigMainWindow : public Q3MainWindow { + Q_OBJECT + + static Q3Action *saveAction; + static void conf_changed(void); +public: + ConfigMainWindow(void); +public slots: + void changeMenu(struct menu *); + void setMenuLink(struct menu *); + void listFocusChanged(void); + void goBack(void); + void loadConfig(void); + bool saveConfig(void); + void saveConfigAs(void); + void searchConfig(void); + void showSingleView(void); + void showSplitView(void); + void showFullView(void); + void showIntro(void); + void showAbout(void); + void saveSettings(void); + +protected: + void closeEvent(QCloseEvent *e); + + ConfigSearchWindow *searchWindow; + ConfigView *menuView; + ConfigList *menuList; + ConfigView *configView; + ConfigList *configList; + ConfigInfoView *helpText; + Q3ToolBar *toolBar; + Q3Action *backAction; + QSplitter* split1; + QSplitter* split2; +}; diff --git a/l4/tool/kconfig/scripts/kconfig/symbol.c b/l4/tool/kconfig/scripts/kconfig/symbol.c new file mode 100644 index 00000000..22a3c400 --- /dev/null +++ b/l4/tool/kconfig/scripts/kconfig/symbol.c @@ -0,0 +1,1310 @@ +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +#include +#include +#include +#include +#include + +#include "lkc.h" + +struct symbol symbol_yes = { + .name = "y", + .curr = { "y", yes }, + .flags = SYMBOL_CONST|SYMBOL_VALID, +}, symbol_mod = { + .name = "m", + .curr = { "m", mod }, + .flags = SYMBOL_CONST|SYMBOL_VALID, +}, symbol_no = { + .name = "n", + .curr = { "n", no }, + .flags = SYMBOL_CONST|SYMBOL_VALID, +}, symbol_empty = { + .name = "", + .curr = { "", no }, + .flags = SYMBOL_VALID, +}; + +struct symbol *sym_defconfig_list; +struct symbol *modules_sym; +tristate modules_val; + +struct expr *sym_env_list; + +static void sym_add_default(struct symbol *sym, const char *def) +{ + struct property *prop = prop_alloc(P_DEFAULT, sym); + + prop->expr = expr_alloc_symbol(sym_lookup(def, SYMBOL_CONST)); +} + +void sym_init(void) +{ + struct symbol *sym; + struct utsname uts; + static bool inited = false; + + if (inited) + return; + inited = true; + + uname(&uts); + + sym = sym_lookup("UNAME_RELEASE", 0); + sym->type = S_STRING; + sym->flags |= SYMBOL_AUTO; + sym_add_default(sym, uts.release); +} + +enum symbol_type sym_get_type(struct symbol *sym) +{ + enum symbol_type type = sym->type; + + if (type == S_TRISTATE) { + if (sym_is_choice_value(sym) && sym->visible == yes) + type = S_BOOLEAN; + else if (modules_val == no) + type = S_BOOLEAN; + } + return type; +} + +const char *sym_type_name(enum symbol_type type) +{ + switch (type) { + case S_BOOLEAN: + return "boolean"; + case S_TRISTATE: + return "tristate"; + case S_INT: + return "integer"; + case S_HEX: + return "hex"; + case S_STRING: + return "string"; + case S_UNKNOWN: + return "unknown"; + case S_OTHER: + break; + } + return "???"; +} + +struct property *sym_get_choice_prop(struct symbol *sym) +{ + struct property *prop; + + for_all_choices(sym, prop) + return prop; + return NULL; +} + +struct property *sym_get_env_prop(struct symbol *sym) +{ + struct property *prop; + + for_all_properties(sym, prop, P_ENV) + return prop; + return NULL; +} + +struct property *sym_get_default_prop(struct symbol *sym) +{ + struct property *prop; + + for_all_defaults(sym, prop) { + prop->visible.tri = expr_calc_value(prop->visible.expr); + if (prop->visible.tri != no) + return prop; + } + return NULL; +} + +static struct property *sym_get_range_prop(struct symbol *sym) +{ + struct property *prop; + + for_all_properties(sym, prop, P_RANGE) { + prop->visible.tri = expr_calc_value(prop->visible.expr); + if (prop->visible.tri != no) + return prop; + } + return NULL; +} + +static int sym_get_range_val(struct symbol *sym, int base) +{ + sym_calc_value(sym); + switch (sym->type) { + case S_INT: + base = 10; + break; + case S_HEX: + base = 16; + break; + default: + break; + } + return strtol(sym->curr.val, NULL, base); +} + +static void sym_validate_range(struct symbol *sym) +{ + struct property *prop; + int base, val, val2; + char str[64]; + + switch (sym->type) { + case S_INT: + base = 10; + break; + case S_HEX: + base = 16; + break; + default: + return; + } + prop = sym_get_range_prop(sym); + if (!prop) + return; + val = strtol(sym->curr.val, NULL, base); + val2 = sym_get_range_val(prop->expr->left.sym, base); + if (val >= val2) { + val2 = sym_get_range_val(prop->expr->right.sym, base); + if (val <= val2) + return; + } + if (sym->type == S_INT) + sprintf(str, "%d", val2); + else + sprintf(str, "0x%x", val2); + sym->curr.val = strdup(str); +} + +static void sym_calc_visibility(struct symbol *sym) +{ + struct property *prop; + tristate tri; + + /* any prompt visible? */ + tri = no; + for_all_prompts(sym, prop) { + prop->visible.tri = expr_calc_value(prop->visible.expr); + tri = EXPR_OR(tri, prop->visible.tri); + } + if (tri == mod && (sym->type != S_TRISTATE || modules_val == no)) + tri = yes; + if (sym->visible != tri) { + sym->visible = tri; + sym_set_changed(sym); + } + if (sym_is_choice_value(sym)) + return; + /* defaulting to "yes" if no explicit "depends on" are given */ + tri = yes; + if (sym->dir_dep.expr) + tri = expr_calc_value(sym->dir_dep.expr); + if (tri == mod) + tri = yes; + if (sym->dir_dep.tri != tri) { + sym->dir_dep.tri = tri; + sym_set_changed(sym); + } + tri = no; + if (sym->rev_dep.expr) + tri = expr_calc_value(sym->rev_dep.expr); + if (tri == mod && sym_get_type(sym) == S_BOOLEAN) + tri = yes; + if (sym->rev_dep.tri != tri) { + sym->rev_dep.tri = tri; + sym_set_changed(sym); + } +} + +/* + * Find the default symbol for a choice. + * First try the default values for the choice symbol + * Next locate the first visible choice value + * Return NULL if none was found + */ +struct symbol *sym_choice_default(struct symbol *sym) +{ + struct symbol *def_sym; + struct property *prop; + struct expr *e; + + /* any of the defaults visible? */ + for_all_defaults(sym, prop) { + prop->visible.tri = expr_calc_value(prop->visible.expr); + if (prop->visible.tri == no) + continue; + def_sym = prop_get_symbol(prop); + if (def_sym->visible != no) + return def_sym; + } + + /* just get the first visible value */ + prop = sym_get_choice_prop(sym); + expr_list_for_each_sym(prop->expr, e, def_sym) + if (def_sym->visible != no) + return def_sym; + + /* failed to locate any defaults */ + return NULL; +} + +static struct symbol *sym_calc_choice(struct symbol *sym) +{ + struct symbol *def_sym; + struct property *prop; + struct expr *e; + int flags; + + /* first calculate all choice values' visibilities */ + flags = sym->flags; + prop = sym_get_choice_prop(sym); + expr_list_for_each_sym(prop->expr, e, def_sym) { + sym_calc_visibility(def_sym); + if (def_sym->visible != no) + flags &= def_sym->flags; + } + + sym->flags &= flags | ~SYMBOL_DEF_USER; + + /* is the user choice visible? */ + def_sym = sym->def[S_DEF_USER].val; + if (def_sym && def_sym->visible != no) + return def_sym; + + def_sym = sym_choice_default(sym); + + if (def_sym == NULL) + /* no choice? reset tristate value */ + sym->curr.tri = no; + + return def_sym; +} + +void sym_calc_value(struct symbol *sym) +{ + struct symbol_value newval, oldval; + struct property *prop; + struct expr *e; + + if (!sym) + return; + + if (sym->flags & SYMBOL_VALID) + return; + sym->flags |= SYMBOL_VALID; + + oldval = sym->curr; + + switch (sym->type) { + case S_INT: + case S_HEX: + case S_STRING: + newval = symbol_empty.curr; + break; + case S_BOOLEAN: + case S_TRISTATE: + newval = symbol_no.curr; + break; + default: + sym->curr.val = sym->name; + sym->curr.tri = no; + return; + } + if (!sym_is_choice_value(sym)) + sym->flags &= ~SYMBOL_WRITE; + + sym_calc_visibility(sym); + + /* set default if recursively called */ + sym->curr = newval; + + switch (sym_get_type(sym)) { + case S_BOOLEAN: + case S_TRISTATE: + if (sym_is_choice_value(sym) && sym->visible == yes) { + prop = sym_get_choice_prop(sym); + newval.tri = (prop_get_symbol(prop)->curr.val == sym) ? yes : no; + } else { + if (sym->visible != no) { + /* if the symbol is visible use the user value + * if available, otherwise try the default value + */ + sym->flags |= SYMBOL_WRITE; + if (sym_has_value(sym)) { + newval.tri = EXPR_AND(sym->def[S_DEF_USER].tri, + sym->visible); + goto calc_newval; + } + } + if (sym->rev_dep.tri != no) + sym->flags |= SYMBOL_WRITE; + if (!sym_is_choice(sym)) { + prop = sym_get_default_prop(sym); + if (prop) { + sym->flags |= SYMBOL_WRITE; + newval.tri = EXPR_AND(expr_calc_value(prop->expr), + prop->visible.tri); + } + } + calc_newval: + if (sym->dir_dep.tri == no && sym->rev_dep.tri != no) { + struct expr *e; + e = expr_simplify_unmet_dep(sym->rev_dep.expr, + sym->dir_dep.expr); + fprintf(stderr, "warning: ("); + expr_fprint(e, stderr); + fprintf(stderr, ") selects %s which has unmet direct dependencies (", + sym->name); + expr_fprint(sym->dir_dep.expr, stderr); + fprintf(stderr, ")\n"); + expr_free(e); + } + newval.tri = EXPR_OR(newval.tri, sym->rev_dep.tri); + } + if (newval.tri == mod && sym_get_type(sym) == S_BOOLEAN) + newval.tri = yes; + break; + case S_STRING: + case S_HEX: + case S_INT: + if (sym->visible != no) { + sym->flags |= SYMBOL_WRITE; + if (sym_has_value(sym)) { + newval.val = sym->def[S_DEF_USER].val; + break; + } + } + prop = sym_get_default_prop(sym); + if (prop) { + struct symbol *ds = prop_get_symbol(prop); + if (ds) { + sym->flags |= SYMBOL_WRITE; + sym_calc_value(ds); + newval.val = ds->curr.val; + } + } + break; + default: + ; + } + + sym->curr = newval; + if (sym_is_choice(sym) && newval.tri == yes) + sym->curr.val = sym_calc_choice(sym); + sym_validate_range(sym); + + if (memcmp(&oldval, &sym->curr, sizeof(oldval))) { + sym_set_changed(sym); + if (modules_sym == sym) { + sym_set_all_changed(); + modules_val = modules_sym->curr.tri; + } + } + + if (sym_is_choice(sym)) { + struct symbol *choice_sym; + + prop = sym_get_choice_prop(sym); + expr_list_for_each_sym(prop->expr, e, choice_sym) { + if ((sym->flags & SYMBOL_WRITE) && + choice_sym->visible != no) + choice_sym->flags |= SYMBOL_WRITE; + if (sym->flags & SYMBOL_CHANGED) + sym_set_changed(choice_sym); + } + } + + if (sym->flags & SYMBOL_AUTO) + sym->flags &= ~SYMBOL_WRITE; +} + +void sym_clear_all_valid(void) +{ + struct symbol *sym; + int i; + + for_all_symbols(i, sym) + sym->flags &= ~SYMBOL_VALID; + sym_add_change_count(1); + if (modules_sym) + sym_calc_value(modules_sym); +} + +void sym_set_changed(struct symbol *sym) +{ + struct property *prop; + + sym->flags |= SYMBOL_CHANGED; + for (prop = sym->prop; prop; prop = prop->next) { + if (prop->menu) + prop->menu->flags |= MENU_CHANGED; + } +} + +void sym_set_all_changed(void) +{ + struct symbol *sym; + int i; + + for_all_symbols(i, sym) + sym_set_changed(sym); +} + +bool sym_tristate_within_range(struct symbol *sym, tristate val) +{ + int type = sym_get_type(sym); + + if (sym->visible == no) + return false; + + if (type != S_BOOLEAN && type != S_TRISTATE) + return false; + + if (type == S_BOOLEAN && val == mod) + return false; + if (sym->visible <= sym->rev_dep.tri) + return false; + if (sym_is_choice_value(sym) && sym->visible == yes) + return val == yes; + return val >= sym->rev_dep.tri && val <= sym->visible; +} + +bool sym_set_tristate_value(struct symbol *sym, tristate val) +{ + tristate oldval = sym_get_tristate_value(sym); + + if (oldval != val && !sym_tristate_within_range(sym, val)) + return false; + + if (!(sym->flags & SYMBOL_DEF_USER)) { + sym->flags |= SYMBOL_DEF_USER; + sym_set_changed(sym); + } + /* + * setting a choice value also resets the new flag of the choice + * symbol and all other choice values. + */ + if (sym_is_choice_value(sym) && val == yes) { + struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym)); + struct property *prop; + struct expr *e; + + cs->def[S_DEF_USER].val = sym; + cs->flags |= SYMBOL_DEF_USER; + prop = sym_get_choice_prop(cs); + for (e = prop->expr; e; e = e->left.expr) { + if (e->right.sym->visible != no) + e->right.sym->flags |= SYMBOL_DEF_USER; + } + } + + sym->def[S_DEF_USER].tri = val; + if (oldval != val) + sym_clear_all_valid(); + + return true; +} + +tristate sym_toggle_tristate_value(struct symbol *sym) +{ + tristate oldval, newval; + + oldval = newval = sym_get_tristate_value(sym); + do { + switch (newval) { + case no: + newval = mod; + break; + case mod: + newval = yes; + break; + case yes: + newval = no; + break; + } + if (sym_set_tristate_value(sym, newval)) + break; + } while (oldval != newval); + return newval; +} + +bool sym_string_valid(struct symbol *sym, const char *str) +{ + signed char ch; + + switch (sym->type) { + case S_STRING: + return true; + case S_INT: + ch = *str++; + if (ch == '-') + ch = *str++; + if (!isdigit(ch)) + return false; + if (ch == '0' && *str != 0) + return false; + while ((ch = *str++)) { + if (!isdigit(ch)) + return false; + } + return true; + case S_HEX: + if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) + str += 2; + ch = *str++; + do { + if (!isxdigit(ch)) + return false; + } while ((ch = *str++)); + return true; + case S_BOOLEAN: + case S_TRISTATE: + switch (str[0]) { + case 'y': case 'Y': + case 'm': case 'M': + case 'n': case 'N': + return true; + } + return false; + default: + return false; + } +} + +bool sym_string_within_range(struct symbol *sym, const char *str) +{ + struct property *prop; + int val; + + switch (sym->type) { + case S_STRING: + return sym_string_valid(sym, str); + case S_INT: + if (!sym_string_valid(sym, str)) + return false; + prop = sym_get_range_prop(sym); + if (!prop) + return true; + val = strtol(str, NULL, 10); + return val >= sym_get_range_val(prop->expr->left.sym, 10) && + val <= sym_get_range_val(prop->expr->right.sym, 10); + case S_HEX: + if (!sym_string_valid(sym, str)) + return false; + prop = sym_get_range_prop(sym); + if (!prop) + return true; + val = strtol(str, NULL, 16); + return val >= sym_get_range_val(prop->expr->left.sym, 16) && + val <= sym_get_range_val(prop->expr->right.sym, 16); + case S_BOOLEAN: + case S_TRISTATE: + switch (str[0]) { + case 'y': case 'Y': + return sym_tristate_within_range(sym, yes); + case 'm': case 'M': + return sym_tristate_within_range(sym, mod); + case 'n': case 'N': + return sym_tristate_within_range(sym, no); + } + return false; + default: + return false; + } +} + +bool sym_set_string_value(struct symbol *sym, const char *newval) +{ + const char *oldval; + char *val; + int size; + + switch (sym->type) { + case S_BOOLEAN: + case S_TRISTATE: + switch (newval[0]) { + case 'y': case 'Y': + return sym_set_tristate_value(sym, yes); + case 'm': case 'M': + return sym_set_tristate_value(sym, mod); + case 'n': case 'N': + return sym_set_tristate_value(sym, no); + } + return false; + default: + ; + } + + if (!sym_string_within_range(sym, newval)) + return false; + + if (!(sym->flags & SYMBOL_DEF_USER)) { + sym->flags |= SYMBOL_DEF_USER; + sym_set_changed(sym); + } + + oldval = sym->def[S_DEF_USER].val; + size = strlen(newval) + 1; + if (sym->type == S_HEX && (newval[0] != '0' || (newval[1] != 'x' && newval[1] != 'X'))) { + size += 2; + sym->def[S_DEF_USER].val = val = malloc(size); + *val++ = '0'; + *val++ = 'x'; + } else if (!oldval || strcmp(oldval, newval)) + sym->def[S_DEF_USER].val = val = malloc(size); + else + return true; + + strcpy(val, newval); + free((void *)oldval); + sym_clear_all_valid(); + + return true; +} + +/* + * Find the default value associated to a symbol. + * For tristate symbol handle the modules=n case + * in which case "m" becomes "y". + * If the symbol does not have any default then fallback + * to the fixed default values. + */ +const char *sym_get_string_default(struct symbol *sym) +{ + struct property *prop; + struct symbol *ds; + const char *str; + tristate val; + + sym_calc_visibility(sym); + sym_calc_value(modules_sym); + val = symbol_no.curr.tri; + str = symbol_empty.curr.val; + + /* If symbol has a default value look it up */ + prop = sym_get_default_prop(sym); + if (prop != NULL) { + switch (sym->type) { + case S_BOOLEAN: + case S_TRISTATE: + /* The visibility may limit the value from yes => mod */ + val = EXPR_AND(expr_calc_value(prop->expr), prop->visible.tri); + break; + default: + /* + * The following fails to handle the situation + * where a default value is further limited by + * the valid range. + */ + ds = prop_get_symbol(prop); + if (ds != NULL) { + sym_calc_value(ds); + str = (const char *)ds->curr.val; + } + } + } + + /* Handle select statements */ + val = EXPR_OR(val, sym->rev_dep.tri); + + /* transpose mod to yes if modules are not enabled */ + if (val == mod) + if (!sym_is_choice_value(sym) && modules_sym->curr.tri == no) + val = yes; + + /* transpose mod to yes if type is bool */ + if (sym->type == S_BOOLEAN && val == mod) + val = yes; + + switch (sym->type) { + case S_BOOLEAN: + case S_TRISTATE: + switch (val) { + case no: return "n"; + case mod: return "m"; + case yes: return "y"; + } + case S_INT: + case S_HEX: + return str; + case S_STRING: + return str; + case S_OTHER: + case S_UNKNOWN: + break; + } + return ""; +} + +const char *sym_get_string_value(struct symbol *sym) +{ + tristate val; + + switch (sym->type) { + case S_BOOLEAN: + case S_TRISTATE: + val = sym_get_tristate_value(sym); + switch (val) { + case no: + return "n"; + case mod: + sym_calc_value(modules_sym); + return (modules_sym->curr.tri == no) ? "n" : "m"; + case yes: + return "y"; + } + break; + default: + ; + } + return (const char *)sym->curr.val; +} + +bool sym_is_changable(struct symbol *sym) +{ + return sym->visible > sym->rev_dep.tri; +} + +static unsigned strhash(const char *s) +{ + /* fnv32 hash */ + unsigned hash = 2166136261U; + for (; *s; s++) + hash = (hash ^ *s) * 0x01000193; + return hash; +} + +struct symbol *sym_lookup(const char *name, int flags) +{ + struct symbol *symbol; + char *new_name; + int hash; + + if (name) { + if (name[0] && !name[1]) { + switch (name[0]) { + case 'y': return &symbol_yes; + case 'm': return &symbol_mod; + case 'n': return &symbol_no; + } + } + hash = strhash(name) % SYMBOL_HASHSIZE; + + for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) { + if (symbol->name && + !strcmp(symbol->name, name) && + (flags ? symbol->flags & flags + : !(symbol->flags & (SYMBOL_CONST|SYMBOL_CHOICE)))) + return symbol; + } + new_name = strdup(name); + } else { + new_name = NULL; + hash = 0; + } + + symbol = malloc(sizeof(*symbol)); + memset(symbol, 0, sizeof(*symbol)); + symbol->name = new_name; + symbol->type = S_UNKNOWN; + symbol->flags |= flags; + + symbol->next = symbol_hash[hash]; + symbol_hash[hash] = symbol; + + return symbol; +} + +struct symbol *sym_find(const char *name) +{ + struct symbol *symbol = NULL; + int hash = 0; + + if (!name) + return NULL; + + if (name[0] && !name[1]) { + switch (name[0]) { + case 'y': return &symbol_yes; + case 'm': return &symbol_mod; + case 'n': return &symbol_no; + } + } + hash = strhash(name) % SYMBOL_HASHSIZE; + + for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) { + if (symbol->name && + !strcmp(symbol->name, name) && + !(symbol->flags & SYMBOL_CONST)) + break; + } + + return symbol; +} + +/* + * Expand symbol's names embedded in the string given in argument. Symbols' + * name to be expanded shall be prefixed by a '$'. Unknown symbol expands to + * the empty string. + */ +const char *sym_expand_string_value(const char *in) +{ + const char *src; + char *res; + size_t reslen; + + reslen = strlen(in) + 1; + res = malloc(reslen); + res[0] = '\0'; + + while ((src = strchr(in, '$'))) { + char *p, name[SYMBOL_MAXLENGTH]; + const char *symval = ""; + struct symbol *sym; + size_t newlen; + + strncat(res, in, src - in); + src++; + + p = name; + while (isalnum(*src) || *src == '_') + *p++ = *src++; + *p = '\0'; + + sym = sym_find(name); + if (sym != NULL) { + sym_calc_value(sym); + symval = sym_get_string_value(sym); + } + + newlen = strlen(res) + strlen(symval) + strlen(src) + 1; + if (newlen > reslen) { + reslen = newlen; + res = realloc(res, reslen); + } + + strcat(res, symval); + in = src; + } + strcat(res, in); + + return res; +} + +const char *sym_escape_string_value(const char *in) +{ + const char *p; + size_t reslen; + char *res; + size_t l; + + reslen = strlen(in) + strlen("\"\"") + 1; + + p = in; + for (;;) { + l = strcspn(p, "\"\\"); + p += l; + + if (p[0] == '\0') + break; + + reslen++; + p++; + } + + res = malloc(reslen); + res[0] = '\0'; + + strcat(res, "\""); + + p = in; + for (;;) { + l = strcspn(p, "\"\\"); + strncat(res, p, l); + p += l; + + if (p[0] == '\0') + break; + + strcat(res, "\\"); + strncat(res, p++, 1); + } + + strcat(res, "\""); + return res; +} + +struct symbol **sym_re_search(const char *pattern) +{ + struct symbol *sym, **sym_arr = NULL; + int i, cnt, size; + regex_t re; + + cnt = size = 0; + /* Skip if empty */ + if (strlen(pattern) == 0) + return NULL; + if (regcomp(&re, pattern, REG_EXTENDED|REG_NOSUB|REG_ICASE)) + return NULL; + + for_all_symbols(i, sym) { + if (sym->flags & SYMBOL_CONST || !sym->name) + continue; + if (regexec(&re, sym->name, 0, NULL, 0)) + continue; + if (cnt + 1 >= size) { + void *tmp = sym_arr; + size += 16; + sym_arr = realloc(sym_arr, size * sizeof(struct symbol *)); + if (!sym_arr) { + free(tmp); + return NULL; + } + } + sym_calc_value(sym); + sym_arr[cnt++] = sym; + } + if (sym_arr) + sym_arr[cnt] = NULL; + regfree(&re); + + return sym_arr; +} + +/* + * When we check for recursive dependencies we use a stack to save + * current state so we can print out relevant info to user. + * The entries are located on the call stack so no need to free memory. + * Note inser() remove() must always match to properly clear the stack. + */ +static struct dep_stack { + struct dep_stack *prev, *next; + struct symbol *sym; + struct property *prop; + struct expr *expr; +} *check_top; + +static void dep_stack_insert(struct dep_stack *stack, struct symbol *sym) +{ + memset(stack, 0, sizeof(*stack)); + if (check_top) + check_top->next = stack; + stack->prev = check_top; + stack->sym = sym; + check_top = stack; +} + +static void dep_stack_remove(void) +{ + check_top = check_top->prev; + if (check_top) + check_top->next = NULL; +} + +/* + * Called when we have detected a recursive dependency. + * check_top point to the top of the stact so we use + * the ->prev pointer to locate the bottom of the stack. + */ +static void sym_check_print_recursive(struct symbol *last_sym) +{ + struct dep_stack *stack; + struct symbol *sym, *next_sym; + struct menu *menu = NULL; + struct property *prop; + struct dep_stack cv_stack; + + if (sym_is_choice_value(last_sym)) { + dep_stack_insert(&cv_stack, last_sym); + last_sym = prop_get_symbol(sym_get_choice_prop(last_sym)); + } + + for (stack = check_top; stack != NULL; stack = stack->prev) + if (stack->sym == last_sym) + break; + if (!stack) { + fprintf(stderr, "unexpected recursive dependency error\n"); + return; + } + + for (; stack; stack = stack->next) { + sym = stack->sym; + next_sym = stack->next ? stack->next->sym : last_sym; + prop = stack->prop; + if (prop == NULL) + prop = stack->sym->prop; + + /* for choice values find the menu entry (used below) */ + if (sym_is_choice(sym) || sym_is_choice_value(sym)) { + for (prop = sym->prop; prop; prop = prop->next) { + menu = prop->menu; + if (prop->menu) + break; + } + } + if (stack->sym == last_sym) + fprintf(stderr, "%s:%d:error: recursive dependency detected!\n", + prop->file->name, prop->lineno); + if (stack->expr) { + fprintf(stderr, "%s:%d:\tsymbol %s %s value contains %s\n", + prop->file->name, prop->lineno, + sym->name ? sym->name : "", + prop_get_type_name(prop->type), + next_sym->name ? next_sym->name : ""); + } else if (stack->prop) { + fprintf(stderr, "%s:%d:\tsymbol %s depends on %s\n", + prop->file->name, prop->lineno, + sym->name ? sym->name : "", + next_sym->name ? next_sym->name : ""); + } else if (sym_is_choice(sym)) { + fprintf(stderr, "%s:%d:\tchoice %s contains symbol %s\n", + menu->file->name, menu->lineno, + sym->name ? sym->name : "", + next_sym->name ? next_sym->name : ""); + } else if (sym_is_choice_value(sym)) { + fprintf(stderr, "%s:%d:\tsymbol %s is part of choice %s\n", + menu->file->name, menu->lineno, + sym->name ? sym->name : "", + next_sym->name ? next_sym->name : ""); + } else { + fprintf(stderr, "%s:%d:\tsymbol %s is selected by %s\n", + prop->file->name, prop->lineno, + sym->name ? sym->name : "", + next_sym->name ? next_sym->name : ""); + } + } + + if (check_top == &cv_stack) + dep_stack_remove(); +} + +static struct symbol *sym_check_expr_deps(struct expr *e) +{ + struct symbol *sym; + + if (!e) + return NULL; + switch (e->type) { + case E_OR: + case E_AND: + sym = sym_check_expr_deps(e->left.expr); + if (sym) + return sym; + return sym_check_expr_deps(e->right.expr); + case E_NOT: + return sym_check_expr_deps(e->left.expr); + case E_EQUAL: + case E_UNEQUAL: + sym = sym_check_deps(e->left.sym); + if (sym) + return sym; + return sym_check_deps(e->right.sym); + case E_SYMBOL: + return sym_check_deps(e->left.sym); + default: + break; + } + printf("Oops! How to check %d?\n", e->type); + return NULL; +} + +/* return NULL when dependencies are OK */ +static struct symbol *sym_check_sym_deps(struct symbol *sym) +{ + struct symbol *sym2; + struct property *prop; + struct dep_stack stack; + + dep_stack_insert(&stack, sym); + + sym2 = sym_check_expr_deps(sym->rev_dep.expr); + if (sym2) + goto out; + + for (prop = sym->prop; prop; prop = prop->next) { + if (prop->type == P_CHOICE || prop->type == P_SELECT) + continue; + stack.prop = prop; + sym2 = sym_check_expr_deps(prop->visible.expr); + if (sym2) + break; + if (prop->type != P_DEFAULT || sym_is_choice(sym)) + continue; + stack.expr = prop->expr; + sym2 = sym_check_expr_deps(prop->expr); + if (sym2) + break; + stack.expr = NULL; + } + +out: + dep_stack_remove(); + + return sym2; +} + +static struct symbol *sym_check_choice_deps(struct symbol *choice) +{ + struct symbol *sym, *sym2; + struct property *prop; + struct expr *e; + struct dep_stack stack; + + dep_stack_insert(&stack, choice); + + prop = sym_get_choice_prop(choice); + expr_list_for_each_sym(prop->expr, e, sym) + sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED); + + choice->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED); + sym2 = sym_check_sym_deps(choice); + choice->flags &= ~SYMBOL_CHECK; + if (sym2) + goto out; + + expr_list_for_each_sym(prop->expr, e, sym) { + sym2 = sym_check_sym_deps(sym); + if (sym2) + break; + } +out: + expr_list_for_each_sym(prop->expr, e, sym) + sym->flags &= ~SYMBOL_CHECK; + + if (sym2 && sym_is_choice_value(sym2) && + prop_get_symbol(sym_get_choice_prop(sym2)) == choice) + sym2 = choice; + + dep_stack_remove(); + + return sym2; +} + +struct symbol *sym_check_deps(struct symbol *sym) +{ + struct symbol *sym2; + struct property *prop; + + if (sym->flags & SYMBOL_CHECK) { + sym_check_print_recursive(sym); + return sym; + } + if (sym->flags & SYMBOL_CHECKED) + return NULL; + + if (sym_is_choice_value(sym)) { + struct dep_stack stack; + + /* for choice groups start the check with main choice symbol */ + dep_stack_insert(&stack, sym); + prop = sym_get_choice_prop(sym); + sym2 = sym_check_deps(prop_get_symbol(prop)); + dep_stack_remove(); + } else if (sym_is_choice(sym)) { + sym2 = sym_check_choice_deps(sym); + } else { + sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED); + sym2 = sym_check_sym_deps(sym); + sym->flags &= ~SYMBOL_CHECK; + } + + if (sym2 && sym2 == sym) + sym2 = NULL; + + return sym2; +} + +struct property *prop_alloc(enum prop_type type, struct symbol *sym) +{ + struct property *prop; + struct property **propp; + + prop = malloc(sizeof(*prop)); + memset(prop, 0, sizeof(*prop)); + prop->type = type; + prop->sym = sym; + prop->file = current_file; + prop->lineno = zconf_lineno(); + + /* append property to the prop list of symbol */ + if (sym) { + for (propp = &sym->prop; *propp; propp = &(*propp)->next) + ; + *propp = prop; + } + + return prop; +} + +struct symbol *prop_get_symbol(struct property *prop) +{ + if (prop->expr && (prop->expr->type == E_SYMBOL || + prop->expr->type == E_LIST)) + return prop->expr->left.sym; + return NULL; +} + +const char *prop_get_type_name(enum prop_type type) +{ + switch (type) { + case P_PROMPT: + return "prompt"; + case P_ENV: + return "env"; + case P_COMMENT: + return "comment"; + case P_MENU: + return "menu"; + case P_DEFAULT: + return "default"; + case P_CHOICE: + return "choice"; + case P_SELECT: + return "select"; + case P_RANGE: + return "range"; + case P_SYMBOL: + return "symbol"; + case P_UNKNOWN: + break; + } + return "unknown"; +} + +static void prop_add_env(const char *env) +{ + struct symbol *sym, *sym2; + struct property *prop; + char *p; + + sym = current_entry->sym; + sym->flags |= SYMBOL_AUTO; + for_all_properties(sym, prop, P_ENV) { + sym2 = prop_get_symbol(prop); + if (strcmp(sym2->name, env)) + menu_warn(current_entry, "redefining environment symbol from %s", + sym2->name); + return; + } + + prop = prop_alloc(P_ENV, sym); + prop->expr = expr_alloc_symbol(sym_lookup(env, SYMBOL_CONST)); + + sym_env_list = expr_alloc_one(E_LIST, sym_env_list); + sym_env_list->right.sym = sym; + + p = getenv(env); + if (p) + sym_add_default(sym, p); + else + menu_warn(current_entry, "environment variable %s undefined", env); +} diff --git a/l4/tool/kconfig/scripts/kconfig/util.c b/l4/tool/kconfig/scripts/kconfig/util.c new file mode 100644 index 00000000..d0b8b231 --- /dev/null +++ b/l4/tool/kconfig/scripts/kconfig/util.c @@ -0,0 +1,140 @@ +/* + * Copyright (C) 2002-2005 Roman Zippel + * Copyright (C) 2002-2005 Sam Ravnborg + * + * Released under the terms of the GNU GPL v2.0. + */ + +#include +#include +#include +#include "lkc.h" + +/* file already present in list? If not add it */ +struct file *file_lookup(const char *name) +{ + struct file *file; + const char *file_name = sym_expand_string_value(name); + + for (file = file_list; file; file = file->next) { + if (!strcmp(name, file->name)) { + free((void *)file_name); + return file; + } + } + + file = malloc(sizeof(*file)); + memset(file, 0, sizeof(*file)); + file->name = file_name; + file->next = file_list; + file_list = file; + return file; +} + +/* write a dependency file as used by kbuild to track dependencies */ +int file_write_dep(const char *name) +{ + struct symbol *sym, *env_sym; + struct expr *e; + struct file *file; + FILE *out; + + if (!name) + name = ".kconfig.d"; + out = fopen("..config.tmp", "w"); + if (!out) + return 1; + fprintf(out, "deps_config := \\\n"); + for (file = file_list; file; file = file->next) { + if (file->next) + fprintf(out, "\t%s \\\n", file->name); + else + fprintf(out, "\t%s\n", file->name); + } + fprintf(out, "\n%s: \\\n" + "\t$(deps_config)\n\n", conf_get_autoconfig_name()); + + expr_list_for_each_sym(sym_env_list, e, sym) { + struct property *prop; + const char *value; + + prop = sym_get_env_prop(sym); + env_sym = prop_get_symbol(prop); + if (!env_sym) + continue; + value = getenv(env_sym->name); + if (!value) + value = ""; + fprintf(out, "ifneq \"$(%s)\" \"%s\"\n", env_sym->name, value); + fprintf(out, "%s: FORCE\n", conf_get_autoconfig_name()); + fprintf(out, "endif\n"); + } + + fprintf(out, "\n$(deps_config): ;\n"); + fclose(out); + rename("..config.tmp", name); + return 0; +} + + +/* Allocate initial growable string */ +struct gstr str_new(void) +{ + struct gstr gs; + gs.s = malloc(sizeof(char) * 64); + gs.len = 64; + gs.max_width = 0; + strcpy(gs.s, "\0"); + return gs; +} + +/* Allocate and assign growable string */ +struct gstr str_assign(const char *s) +{ + struct gstr gs; + gs.s = strdup(s); + gs.len = strlen(s) + 1; + gs.max_width = 0; + return gs; +} + +/* Free storage for growable string */ +void str_free(struct gstr *gs) +{ + if (gs->s) + free(gs->s); + gs->s = NULL; + gs->len = 0; +} + +/* Append to growable string */ +void str_append(struct gstr *gs, const char *s) +{ + size_t l; + if (s) { + l = strlen(gs->s) + strlen(s) + 1; + if (l > gs->len) { + gs->s = realloc(gs->s, l); + gs->len = l; + } + strcat(gs->s, s); + } +} + +/* Append printf formatted string to growable string */ +void str_printf(struct gstr *gs, const char *fmt, ...) +{ + va_list ap; + char s[10000]; /* big enough... */ + va_start(ap, fmt); + vsnprintf(s, sizeof(s), fmt, ap); + str_append(gs, s); + va_end(ap); +} + +/* Retrieve value of growable string */ +const char *str_get(struct gstr *gs) +{ + return gs->s; +} + diff --git a/l4/tool/kconfig/scripts/kconfig/zconf.gperf b/l4/tool/kconfig/scripts/kconfig/zconf.gperf new file mode 100644 index 00000000..f14ab411 --- /dev/null +++ b/l4/tool/kconfig/scripts/kconfig/zconf.gperf @@ -0,0 +1,47 @@ +%language=ANSI-C +%define hash-function-name kconf_id_hash +%define lookup-function-name kconf_id_lookup +%define string-pool-name kconf_id_strings +%compare-strncmp +%enum +%pic +%struct-type + +struct kconf_id; + +static const struct kconf_id *kconf_id_lookup(register const char *str, register unsigned int len); + +%% +mainmenu, T_MAINMENU, TF_COMMAND +menu, T_MENU, TF_COMMAND +endmenu, T_ENDMENU, TF_COMMAND +source, T_SOURCE, TF_COMMAND +choice, T_CHOICE, TF_COMMAND +endchoice, T_ENDCHOICE, TF_COMMAND +comment, T_COMMENT, TF_COMMAND +config, T_CONFIG, TF_COMMAND +menuconfig, T_MENUCONFIG, TF_COMMAND +help, T_HELP, TF_COMMAND +if, T_IF, TF_COMMAND|TF_PARAM +endif, T_ENDIF, TF_COMMAND +depends, T_DEPENDS, TF_COMMAND +optional, T_OPTIONAL, TF_COMMAND +default, T_DEFAULT, TF_COMMAND, S_UNKNOWN +prompt, T_PROMPT, TF_COMMAND +tristate, T_TYPE, TF_COMMAND, S_TRISTATE +def_tristate, T_DEFAULT, TF_COMMAND, S_TRISTATE +bool, T_TYPE, TF_COMMAND, S_BOOLEAN +boolean, T_TYPE, TF_COMMAND, S_BOOLEAN +def_bool, T_DEFAULT, TF_COMMAND, S_BOOLEAN +int, T_TYPE, TF_COMMAND, S_INT +hex, T_TYPE, TF_COMMAND, S_HEX +string, T_TYPE, TF_COMMAND, S_STRING +select, T_SELECT, TF_COMMAND +range, T_RANGE, TF_COMMAND +visible, T_VISIBLE, TF_COMMAND +option, T_OPTION, TF_COMMAND +on, T_ON, TF_PARAM +modules, T_OPT_MODULES, TF_OPTION +defconfig_list, T_OPT_DEFCONFIG_LIST,TF_OPTION +env, T_OPT_ENV, TF_OPTION +%% diff --git a/l4/tool/kconfig/scripts/kconfig/zconf.hash.c_shipped b/l4/tool/kconfig/scripts/kconfig/zconf.hash.c_shipped new file mode 100644 index 00000000..40df0005 --- /dev/null +++ b/l4/tool/kconfig/scripts/kconfig/zconf.hash.c_shipped @@ -0,0 +1,286 @@ +/* ANSI-C code produced by gperf version 3.0.4 */ +/* Command-line: gperf -t --output-file scripts/kconfig/zconf.hash.c_shipped -a -C -E -g -k '1,3,$' -p -t scripts/kconfig/zconf.gperf */ + +#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \ + && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \ + && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \ + && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \ + && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \ + && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \ + && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \ + && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \ + && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \ + && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \ + && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \ + && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \ + && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \ + && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \ + && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \ + && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \ + && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \ + && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \ + && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \ + && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \ + && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \ + && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \ + && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126)) +/* The character set is not based on ISO-646. */ +#error "gperf generated tables don't work with this execution character set. Please report a bug to ." +#endif + +#line 10 "scripts/kconfig/zconf.gperf" +struct kconf_id; + +static const struct kconf_id *kconf_id_lookup(register const char *str, register unsigned int len); +/* maximum key range = 71, duplicates = 0 */ + +#ifdef __GNUC__ +__inline +#else +#ifdef __cplusplus +inline +#endif +#endif +static unsigned int +kconf_id_hash (register const char *str, register unsigned int len) +{ + static const unsigned char asso_values[] = + { + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 25, 25, + 0, 0, 0, 5, 0, 0, 73, 73, 5, 0, + 10, 5, 45, 73, 20, 20, 0, 15, 15, 73, + 20, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73 + }; + register int hval = len; + + switch (hval) + { + default: + hval += asso_values[(unsigned char)str[2]]; + /*FALLTHROUGH*/ + case 2: + case 1: + hval += asso_values[(unsigned char)str[0]]; + break; + } + return hval + asso_values[(unsigned char)str[len - 1]]; +} + +struct kconf_id_strings_t + { + char kconf_id_strings_str2[sizeof("if")]; + char kconf_id_strings_str3[sizeof("int")]; + char kconf_id_strings_str5[sizeof("endif")]; + char kconf_id_strings_str7[sizeof("default")]; + char kconf_id_strings_str8[sizeof("tristate")]; + char kconf_id_strings_str9[sizeof("endchoice")]; + char kconf_id_strings_str12[sizeof("def_tristate")]; + char kconf_id_strings_str13[sizeof("def_bool")]; + char kconf_id_strings_str14[sizeof("defconfig_list")]; + char kconf_id_strings_str17[sizeof("on")]; + char kconf_id_strings_str18[sizeof("optional")]; + char kconf_id_strings_str21[sizeof("option")]; + char kconf_id_strings_str22[sizeof("endmenu")]; + char kconf_id_strings_str23[sizeof("mainmenu")]; + char kconf_id_strings_str25[sizeof("menuconfig")]; + char kconf_id_strings_str27[sizeof("modules")]; + char kconf_id_strings_str29[sizeof("menu")]; + char kconf_id_strings_str31[sizeof("select")]; + char kconf_id_strings_str32[sizeof("comment")]; + char kconf_id_strings_str33[sizeof("env")]; + char kconf_id_strings_str35[sizeof("range")]; + char kconf_id_strings_str36[sizeof("choice")]; + char kconf_id_strings_str39[sizeof("bool")]; + char kconf_id_strings_str41[sizeof("source")]; + char kconf_id_strings_str42[sizeof("visible")]; + char kconf_id_strings_str43[sizeof("hex")]; + char kconf_id_strings_str46[sizeof("config")]; + char kconf_id_strings_str47[sizeof("boolean")]; + char kconf_id_strings_str51[sizeof("string")]; + char kconf_id_strings_str54[sizeof("help")]; + char kconf_id_strings_str56[sizeof("prompt")]; + char kconf_id_strings_str72[sizeof("depends")]; + }; +static const struct kconf_id_strings_t kconf_id_strings_contents = + { + "if", + "int", + "endif", + "default", + "tristate", + "endchoice", + "def_tristate", + "def_bool", + "defconfig_list", + "on", + "optional", + "option", + "endmenu", + "mainmenu", + "menuconfig", + "modules", + "menu", + "select", + "comment", + "env", + "range", + "choice", + "bool", + "source", + "visible", + "hex", + "config", + "boolean", + "string", + "help", + "prompt", + "depends" + }; +#define kconf_id_strings ((const char *) &kconf_id_strings_contents) +#ifdef __GNUC__ +__inline +#if defined __GNUC_STDC_INLINE__ || defined __GNUC_GNU_INLINE__ +__attribute__ ((__gnu_inline__)) +#endif +#endif +const struct kconf_id * +kconf_id_lookup (register const char *str, register unsigned int len) +{ + enum + { + TOTAL_KEYWORDS = 32, + MIN_WORD_LENGTH = 2, + MAX_WORD_LENGTH = 14, + MIN_HASH_VALUE = 2, + MAX_HASH_VALUE = 72 + }; + + static const struct kconf_id wordlist[] = + { + {-1}, {-1}, +#line 25 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str2, T_IF, TF_COMMAND|TF_PARAM}, +#line 36 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str3, T_TYPE, TF_COMMAND, S_INT}, + {-1}, +#line 26 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str5, T_ENDIF, TF_COMMAND}, + {-1}, +#line 29 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str7, T_DEFAULT, TF_COMMAND, S_UNKNOWN}, +#line 31 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str8, T_TYPE, TF_COMMAND, S_TRISTATE}, +#line 20 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str9, T_ENDCHOICE, TF_COMMAND}, + {-1}, {-1}, +#line 32 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str12, T_DEFAULT, TF_COMMAND, S_TRISTATE}, +#line 35 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str13, T_DEFAULT, TF_COMMAND, S_BOOLEAN}, +#line 45 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str14, T_OPT_DEFCONFIG_LIST,TF_OPTION}, + {-1}, {-1}, +#line 43 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str17, T_ON, TF_PARAM}, +#line 28 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str18, T_OPTIONAL, TF_COMMAND}, + {-1}, {-1}, +#line 42 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str21, T_OPTION, TF_COMMAND}, +#line 17 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str22, T_ENDMENU, TF_COMMAND}, +#line 15 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str23, T_MAINMENU, TF_COMMAND}, + {-1}, +#line 23 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str25, T_MENUCONFIG, TF_COMMAND}, + {-1}, +#line 44 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str27, T_OPT_MODULES, TF_OPTION}, + {-1}, +#line 16 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str29, T_MENU, TF_COMMAND}, + {-1}, +#line 39 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str31, T_SELECT, TF_COMMAND}, +#line 21 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str32, T_COMMENT, TF_COMMAND}, +#line 46 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str33, T_OPT_ENV, TF_OPTION}, + {-1}, +#line 40 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str35, T_RANGE, TF_COMMAND}, +#line 19 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str36, T_CHOICE, TF_COMMAND}, + {-1}, {-1}, +#line 33 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str39, T_TYPE, TF_COMMAND, S_BOOLEAN}, + {-1}, +#line 18 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str41, T_SOURCE, TF_COMMAND}, +#line 41 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str42, T_VISIBLE, TF_COMMAND}, +#line 37 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str43, T_TYPE, TF_COMMAND, S_HEX}, + {-1}, {-1}, +#line 22 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str46, T_CONFIG, TF_COMMAND}, +#line 34 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str47, T_TYPE, TF_COMMAND, S_BOOLEAN}, + {-1}, {-1}, {-1}, +#line 38 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str51, T_TYPE, TF_COMMAND, S_STRING}, + {-1}, {-1}, +#line 24 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str54, T_HELP, TF_COMMAND}, + {-1}, +#line 30 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str56, T_PROMPT, TF_COMMAND}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, +#line 27 "scripts/kconfig/zconf.gperf" + {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str72, T_DEPENDS, TF_COMMAND} + }; + + if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) + { + register int key = kconf_id_hash (str, len); + + if (key <= MAX_HASH_VALUE && key >= 0) + { + register int o = wordlist[key].name; + if (o >= 0) + { + register const char *s = o + kconf_id_strings; + + if (*str == *s && !strncmp (str + 1, s + 1, len - 1) && s[len] == '\0') + return &wordlist[key]; + } + } + } + return 0; +} +#line 47 "scripts/kconfig/zconf.gperf" + diff --git a/l4/tool/kconfig/scripts/kconfig/zconf.l b/l4/tool/kconfig/scripts/kconfig/zconf.l new file mode 100644 index 00000000..00f9d3a9 --- /dev/null +++ b/l4/tool/kconfig/scripts/kconfig/zconf.l @@ -0,0 +1,364 @@ +%option nostdinit noyywrap never-interactive full ecs +%option 8bit nodefault perf-report perf-report +%option noinput +%x COMMAND HELP STRING PARAM +%{ +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +#include +#include +#include +#include +#include + +#include "lkc.h" + +#define START_STRSIZE 16 + +static struct { + struct file *file; + int lineno; +} current_pos; + +static char *text; +static int text_size, text_asize; + +struct buffer { + struct buffer *parent; + YY_BUFFER_STATE state; +}; + +struct buffer *current_buf; + +static int last_ts, first_ts; + +static void zconf_endhelp(void); +static void zconf_endfile(void); + +static void new_string(void) +{ + text = malloc(START_STRSIZE); + text_asize = START_STRSIZE; + text_size = 0; + *text = 0; +} + +static void append_string(const char *str, int size) +{ + int new_size = text_size + size + 1; + if (new_size > text_asize) { + new_size += START_STRSIZE - 1; + new_size &= -START_STRSIZE; + text = realloc(text, new_size); + text_asize = new_size; + } + memcpy(text + text_size, str, size); + text_size += size; + text[text_size] = 0; +} + +static void alloc_string(const char *str, int size) +{ + text = malloc(size + 1); + memcpy(text, str, size); + text[size] = 0; +} +%} + +ws [ \n\t] +n [A-Za-z0-9_] + +%% + int str = 0; + int ts, i; + +[ \t]*#.*\n | +[ \t]*\n { + current_file->lineno++; + return T_EOL; +} +[ \t]*#.* + + +[ \t]+ { + BEGIN(COMMAND); +} + +. { + unput(yytext[0]); + BEGIN(COMMAND); +} + + +{ + {n}+ { + const struct kconf_id *id = kconf_id_lookup(yytext, yyleng); + BEGIN(PARAM); + current_pos.file = current_file; + current_pos.lineno = current_file->lineno; + if (id && id->flags & TF_COMMAND) { + zconflval.id = id; + return id->token; + } + alloc_string(yytext, yyleng); + zconflval.string = text; + return T_WORD; + } + . + \n { + BEGIN(INITIAL); + current_file->lineno++; + return T_EOL; + } +} + +{ + "&&" return T_AND; + "||" return T_OR; + "(" return T_OPEN_PAREN; + ")" return T_CLOSE_PAREN; + "!" return T_NOT; + "=" return T_EQUAL; + "!=" return T_UNEQUAL; + \"|\' { + str = yytext[0]; + new_string(); + BEGIN(STRING); + } + \n BEGIN(INITIAL); current_file->lineno++; return T_EOL; + --- /* ignore */ + ({n}|[-/.])+ { + const struct kconf_id *id = kconf_id_lookup(yytext, yyleng); + if (id && id->flags & TF_PARAM) { + zconflval.id = id; + return id->token; + } + alloc_string(yytext, yyleng); + zconflval.string = text; + return T_WORD; + } + #.* /* comment */ + \\\n current_file->lineno++; + . + <> { + BEGIN(INITIAL); + } +} + +{ + [^'"\\\n]+/\n { + append_string(yytext, yyleng); + zconflval.string = text; + return T_WORD_QUOTE; + } + [^'"\\\n]+ { + append_string(yytext, yyleng); + } + \\.?/\n { + append_string(yytext + 1, yyleng - 1); + zconflval.string = text; + return T_WORD_QUOTE; + } + \\.? { + append_string(yytext + 1, yyleng - 1); + } + \'|\" { + if (str == yytext[0]) { + BEGIN(PARAM); + zconflval.string = text; + return T_WORD_QUOTE; + } else + append_string(yytext, 1); + } + \n { + printf("%s:%d:warning: multi-line strings not supported\n", zconf_curname(), zconf_lineno()); + current_file->lineno++; + BEGIN(INITIAL); + return T_EOL; + } + <> { + BEGIN(INITIAL); + } +} + +{ + [ \t]+ { + ts = 0; + for (i = 0; i < yyleng; i++) { + if (yytext[i] == '\t') + ts = (ts & ~7) + 8; + else + ts++; + } + last_ts = ts; + if (first_ts) { + if (ts < first_ts) { + zconf_endhelp(); + return T_HELPTEXT; + } + ts -= first_ts; + while (ts > 8) { + append_string(" ", 8); + ts -= 8; + } + append_string(" ", ts); + } + } + [ \t]*\n/[^ \t\n] { + current_file->lineno++; + zconf_endhelp(); + return T_HELPTEXT; + } + [ \t]*\n { + current_file->lineno++; + append_string("\n", 1); + } + [^ \t\n].* { + while (yyleng) { + if ((yytext[yyleng-1] != ' ') && (yytext[yyleng-1] != '\t')) + break; + yyleng--; + } + append_string(yytext, yyleng); + if (!first_ts) + first_ts = last_ts; + } + <> { + zconf_endhelp(); + return T_HELPTEXT; + } +} + +<> { + if (current_file) { + zconf_endfile(); + return T_EOL; + } + fclose(yyin); + yyterminate(); +} + +%% +void zconf_starthelp(void) +{ + new_string(); + last_ts = first_ts = 0; + BEGIN(HELP); +} + +static void zconf_endhelp(void) +{ + zconflval.string = text; + BEGIN(INITIAL); +} + + +/* + * Try to open specified file with following names: + * ./name + * $(srctree)/name + * The latter is used when srctree is separate from objtree + * when compiling the kernel. + * Return NULL if file is not found. + */ +FILE *zconf_fopen(const char *name) +{ + char *env, fullname[PATH_MAX+1]; + FILE *f; + + f = fopen(name, "r"); + if (!f && name != NULL && name[0] != '/') { + env = getenv(SRCTREE); + if (env) { + sprintf(fullname, "%s/%s", env, name); + f = fopen(fullname, "r"); + } + } + return f; +} + +void zconf_initscan(const char *name) +{ + yyin = zconf_fopen(name); + if (!yyin) { + printf("can't find file %s\n", name); + exit(1); + } + + current_buf = malloc(sizeof(*current_buf)); + memset(current_buf, 0, sizeof(*current_buf)); + + current_file = file_lookup(name); + current_file->lineno = 1; +} + +void zconf_nextfile(const char *name) +{ + struct file *iter; + struct file *file = file_lookup(name); + struct buffer *buf = malloc(sizeof(*buf)); + memset(buf, 0, sizeof(*buf)); + + current_buf->state = YY_CURRENT_BUFFER; + yyin = zconf_fopen(file->name); + if (!yyin) { + printf("%s:%d: can't open file \"%s\"\n", + zconf_curname(), zconf_lineno(), file->name); + exit(1); + } + yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE)); + buf->parent = current_buf; + current_buf = buf; + + for (iter = current_file->parent; iter; iter = iter->parent ) { + if (!strcmp(current_file->name,iter->name) ) { + printf("%s:%d: recursive inclusion detected. " + "Inclusion path:\n current file : '%s'\n", + zconf_curname(), zconf_lineno(), + zconf_curname()); + iter = current_file->parent; + while (iter && \ + strcmp(iter->name,current_file->name)) { + printf(" included from: '%s:%d'\n", + iter->name, iter->lineno-1); + iter = iter->parent; + } + if (iter) + printf(" included from: '%s:%d'\n", + iter->name, iter->lineno+1); + exit(1); + } + } + file->lineno = 1; + file->parent = current_file; + current_file = file; +} + +static void zconf_endfile(void) +{ + struct buffer *parent; + + current_file = current_file->parent; + + parent = current_buf->parent; + if (parent) { + fclose(yyin); + yy_delete_buffer(YY_CURRENT_BUFFER); + yy_switch_to_buffer(parent->state); + } + free(current_buf); + current_buf = parent; +} + +int zconf_lineno(void) +{ + return current_pos.lineno; +} + +const char *zconf_curname(void) +{ + return current_pos.file ? current_pos.file->name : ""; +} diff --git a/l4/tool/kconfig/scripts/kconfig/zconf.lex.c_shipped b/l4/tool/kconfig/scripts/kconfig/zconf.lex.c_shipped new file mode 100644 index 00000000..c32b1a49 --- /dev/null +++ b/l4/tool/kconfig/scripts/kconfig/zconf.lex.c_shipped @@ -0,0 +1,2420 @@ + +#line 3 "scripts/kconfig/zconf.lex.c_shipped" + +#define YY_INT_ALIGNED short int + +/* A lexical scanner generated by flex */ + +#define yy_create_buffer zconf_create_buffer +#define yy_delete_buffer zconf_delete_buffer +#define yy_flex_debug zconf_flex_debug +#define yy_init_buffer zconf_init_buffer +#define yy_flush_buffer zconf_flush_buffer +#define yy_load_buffer_state zconf_load_buffer_state +#define yy_switch_to_buffer zconf_switch_to_buffer +#define yyin zconfin +#define yyleng zconfleng +#define yylex zconflex +#define yylineno zconflineno +#define yyout zconfout +#define yyrestart zconfrestart +#define yytext zconftext +#define yywrap zconfwrap +#define yyalloc zconfalloc +#define yyrealloc zconfrealloc +#define yyfree zconffree + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 5 +#define YY_FLEX_SUBMINOR_VERSION 35 +#if YY_FLEX_SUBMINOR_VERSION > 0 +#define FLEX_BETA +#endif + +/* First, we deal with platform-specific or compiler-specific issues. */ + +/* begin standard C headers. */ +#include +#include +#include +#include + +/* end standard C headers. */ + +/* flex integer type definitions */ + +#ifndef FLEXINT_H +#define FLEXINT_H + +/* C99 systems have . Non-C99 systems may or may not. */ + +#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + +/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, + * if you want the limit (max/min) macros for int types. + */ +#ifndef __STDC_LIMIT_MACROS +#define __STDC_LIMIT_MACROS 1 +#endif + +#include +typedef int8_t flex_int8_t; +typedef uint8_t flex_uint8_t; +typedef int16_t flex_int16_t; +typedef uint16_t flex_uint16_t; +typedef int32_t flex_int32_t; +typedef uint32_t flex_uint32_t; +#else +typedef signed char flex_int8_t; +typedef short int flex_int16_t; +typedef int flex_int32_t; +typedef unsigned char flex_uint8_t; +typedef unsigned short int flex_uint16_t; +typedef unsigned int flex_uint32_t; +#endif /* ! C99 */ + +/* Limits of integral types. */ +#ifndef INT8_MIN +#define INT8_MIN (-128) +#endif +#ifndef INT16_MIN +#define INT16_MIN (-32767-1) +#endif +#ifndef INT32_MIN +#define INT32_MIN (-2147483647-1) +#endif +#ifndef INT8_MAX +#define INT8_MAX (127) +#endif +#ifndef INT16_MAX +#define INT16_MAX (32767) +#endif +#ifndef INT32_MAX +#define INT32_MAX (2147483647) +#endif +#ifndef UINT8_MAX +#define UINT8_MAX (255U) +#endif +#ifndef UINT16_MAX +#define UINT16_MAX (65535U) +#endif +#ifndef UINT32_MAX +#define UINT32_MAX (4294967295U) +#endif + +#endif /* ! FLEXINT_H */ + +#ifdef __cplusplus + +/* The "const" storage-class-modifier is valid. */ +#define YY_USE_CONST + +#else /* ! __cplusplus */ + +/* C99 requires __STDC__ to be defined as 1. */ +#if defined (__STDC__) + +#define YY_USE_CONST + +#endif /* defined (__STDC__) */ +#endif /* ! __cplusplus */ + +#ifdef YY_USE_CONST +#define yyconst const +#else +#define yyconst +#endif + +/* Returned upon end-of-file. */ +#define YY_NULL 0 + +/* Promotes a possibly negative, possibly signed char to an unsigned + * integer for use as an array index. If the signed char is negative, + * we want to instead treat it as an 8-bit unsigned char, hence the + * double cast. + */ +#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) + +/* Enter a start condition. This macro really ought to take a parameter, + * but we do it the disgusting crufty way forced on us by the ()-less + * definition of BEGIN. + */ +#define BEGIN (yy_start) = 1 + 2 * + +/* Translate the current start state into a value that can be later handed + * to BEGIN to return to the state. The YYSTATE alias is for lex + * compatibility. + */ +#define YY_START (((yy_start) - 1) / 2) +#define YYSTATE YY_START + +/* Action number for EOF rule of a given start state. */ +#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) + +/* Special action meaning "start processing a new file". */ +#define YY_NEW_FILE zconfrestart(zconfin ) + +#define YY_END_OF_BUFFER_CHAR 0 + +/* Size of default input buffer. */ +#ifndef YY_BUF_SIZE +#define YY_BUF_SIZE 16384 +#endif + +/* The state buf must be large enough to hold one state per character in the main buffer. + */ +#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type)) + +#ifndef YY_TYPEDEF_YY_BUFFER_STATE +#define YY_TYPEDEF_YY_BUFFER_STATE +typedef struct yy_buffer_state *YY_BUFFER_STATE; +#endif + +extern int zconfleng; + +extern FILE *zconfin, *zconfout; + +#define EOB_ACT_CONTINUE_SCAN 0 +#define EOB_ACT_END_OF_FILE 1 +#define EOB_ACT_LAST_MATCH 2 + + #define YY_LESS_LINENO(n) + +/* Return all but the first "n" matched characters back to the input stream. */ +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up zconftext. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + *yy_cp = (yy_hold_char); \ + YY_RESTORE_YY_MORE_OFFSET \ + (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ + YY_DO_BEFORE_ACTION; /* set up zconftext again */ \ + } \ + while ( 0 ) + +#define unput(c) yyunput( c, (yytext_ptr) ) + +#ifndef YY_TYPEDEF_YY_SIZE_T +#define YY_TYPEDEF_YY_SIZE_T +typedef size_t yy_size_t; +#endif + +#ifndef YY_STRUCT_YY_BUFFER_STATE +#define YY_STRUCT_YY_BUFFER_STATE +struct yy_buffer_state + { + FILE *yy_input_file; + + char *yy_ch_buf; /* input buffer */ + char *yy_buf_pos; /* current position in input buffer */ + + /* Size of input buffer in bytes, not including room for EOB + * characters. + */ + yy_size_t yy_buf_size; + + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ + int yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to + * delete it. + */ + int yy_is_our_buffer; + + /* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ + int yy_is_interactive; + + /* Whether we're considered to be at the beginning of a line. + * If so, '^' rules will be active on the next match, otherwise + * not. + */ + int yy_at_bol; + + int yy_bs_lineno; /**< The line count. */ + int yy_bs_column; /**< The column count. */ + + /* Whether to try to fill the input buffer when we reach the + * end of it. + */ + int yy_fill_buffer; + + int yy_buffer_status; + +#define YY_BUFFER_NEW 0 +#define YY_BUFFER_NORMAL 1 + /* When an EOF's been seen but there's still some text to process + * then we mark the buffer as YY_EOF_PENDING, to indicate that we + * shouldn't try reading from the input source any more. We might + * still have a bunch of tokens to match, though, because of + * possible backing-up. + * + * When we actually see the EOF, we change the status to "new" + * (via zconfrestart()), so that the user can continue scanning by + * just pointing zconfin at a new input file. + */ +#define YY_BUFFER_EOF_PENDING 2 + + }; +#endif /* !YY_STRUCT_YY_BUFFER_STATE */ + +/* Stack of input buffers. */ +static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */ +static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */ +static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */ + +/* We provide macros for accessing buffer states in case in the + * future we want to put the buffer states in a more general + * "scanner state". + * + * Returns the top of the stack, or NULL. + */ +#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \ + ? (yy_buffer_stack)[(yy_buffer_stack_top)] \ + : NULL) + +/* Same as previous macro, but useful when we know that the buffer stack is not + * NULL or when we need an lvalue. For internal use only. + */ +#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)] + +/* yy_hold_char holds the character lost when zconftext is formed. */ +static char yy_hold_char; +static int yy_n_chars; /* number of characters read into yy_ch_buf */ +int zconfleng; + +/* Points to current character in buffer. */ +static char *yy_c_buf_p = (char *) 0; +static int yy_init = 0; /* whether we need to initialize */ +static int yy_start = 0; /* start state number */ + +/* Flag which is used to allow zconfwrap()'s to do buffer switches + * instead of setting up a fresh zconfin. A bit of a hack ... + */ +static int yy_did_buffer_switch_on_eof; + +void zconfrestart (FILE *input_file ); +void zconf_switch_to_buffer (YY_BUFFER_STATE new_buffer ); +YY_BUFFER_STATE zconf_create_buffer (FILE *file,int size ); +void zconf_delete_buffer (YY_BUFFER_STATE b ); +void zconf_flush_buffer (YY_BUFFER_STATE b ); +void zconfpush_buffer_state (YY_BUFFER_STATE new_buffer ); +void zconfpop_buffer_state (void ); + +static void zconfensure_buffer_stack (void ); +static void zconf_load_buffer_state (void ); +static void zconf_init_buffer (YY_BUFFER_STATE b,FILE *file ); + +#define YY_FLUSH_BUFFER zconf_flush_buffer(YY_CURRENT_BUFFER ) + +YY_BUFFER_STATE zconf_scan_buffer (char *base,yy_size_t size ); +YY_BUFFER_STATE zconf_scan_string (yyconst char *yy_str ); +YY_BUFFER_STATE zconf_scan_bytes (yyconst char *bytes,int len ); + +void *zconfalloc (yy_size_t ); +void *zconfrealloc (void *,yy_size_t ); +void zconffree (void * ); + +#define yy_new_buffer zconf_create_buffer + +#define yy_set_interactive(is_interactive) \ + { \ + if ( ! YY_CURRENT_BUFFER ){ \ + zconfensure_buffer_stack (); \ + YY_CURRENT_BUFFER_LVALUE = \ + zconf_create_buffer(zconfin,YY_BUF_SIZE ); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ + } + +#define yy_set_bol(at_bol) \ + { \ + if ( ! YY_CURRENT_BUFFER ){\ + zconfensure_buffer_stack (); \ + YY_CURRENT_BUFFER_LVALUE = \ + zconf_create_buffer(zconfin,YY_BUF_SIZE ); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ + } + +#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) + +/* Begin user sect3 */ + +#define zconfwrap(n) 1 +#define YY_SKIP_YYWRAP + +typedef unsigned char YY_CHAR; + +FILE *zconfin = (FILE *) 0, *zconfout = (FILE *) 0; + +typedef int yy_state_type; + +extern int zconflineno; + +int zconflineno = 1; + +extern char *zconftext; +#define yytext_ptr zconftext +static yyconst flex_int16_t yy_nxt[][17] = + { + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0 + }, + + { + 11, 12, 13, 14, 12, 12, 15, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12 + }, + + { + 11, 12, 13, 14, 12, 12, 15, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12 + }, + + { + 11, 16, 16, 17, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 18, 16, 16, 16 + }, + + { + 11, 16, 16, 17, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 18, 16, 16, 16 + + }, + + { + 11, 19, 20, 21, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19 + }, + + { + 11, 19, 20, 21, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19 + }, + + { + 11, 22, 22, 23, 22, 24, 22, 22, 24, 22, + 22, 22, 22, 22, 22, 25, 22 + }, + + { + 11, 22, 22, 23, 22, 24, 22, 22, 24, 22, + 22, 22, 22, 22, 22, 25, 22 + }, + + { + 11, 26, 26, 27, 28, 29, 30, 31, 29, 32, + 33, 34, 35, 35, 36, 37, 38 + + }, + + { + 11, 26, 26, 27, 28, 29, 30, 31, 29, 32, + 33, 34, 35, 35, 36, 37, 38 + }, + + { + -11, -11, -11, -11, -11, -11, -11, -11, -11, -11, + -11, -11, -11, -11, -11, -11, -11 + }, + + { + 11, -12, -12, -12, -12, -12, -12, -12, -12, -12, + -12, -12, -12, -12, -12, -12, -12 + }, + + { + 11, -13, 39, 40, -13, -13, 41, -13, -13, -13, + -13, -13, -13, -13, -13, -13, -13 + }, + + { + 11, -14, -14, -14, -14, -14, -14, -14, -14, -14, + -14, -14, -14, -14, -14, -14, -14 + + }, + + { + 11, 42, 42, 43, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42 + }, + + { + 11, -16, -16, -16, -16, -16, -16, -16, -16, -16, + -16, -16, -16, -16, -16, -16, -16 + }, + + { + 11, -17, -17, -17, -17, -17, -17, -17, -17, -17, + -17, -17, -17, -17, -17, -17, -17 + }, + + { + 11, -18, -18, -18, -18, -18, -18, -18, -18, -18, + -18, -18, -18, 44, -18, -18, -18 + }, + + { + 11, 45, 45, -19, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45 + + }, + + { + 11, -20, 46, 47, -20, -20, -20, -20, -20, -20, + -20, -20, -20, -20, -20, -20, -20 + }, + + { + 11, 48, -21, -21, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48 + }, + + { + 11, 49, 49, 50, 49, -22, 49, 49, -22, 49, + 49, 49, 49, 49, 49, -22, 49 + }, + + { + 11, -23, -23, -23, -23, -23, -23, -23, -23, -23, + -23, -23, -23, -23, -23, -23, -23 + }, + + { + 11, -24, -24, -24, -24, -24, -24, -24, -24, -24, + -24, -24, -24, -24, -24, -24, -24 + + }, + + { + 11, 51, 51, 52, 51, 51, 51, 51, 51, 51, + 51, 51, 51, 51, 51, 51, 51 + }, + + { + 11, -26, -26, -26, -26, -26, -26, -26, -26, -26, + -26, -26, -26, -26, -26, -26, -26 + }, + + { + 11, -27, -27, -27, -27, -27, -27, -27, -27, -27, + -27, -27, -27, -27, -27, -27, -27 + }, + + { + 11, -28, -28, -28, -28, -28, -28, -28, -28, -28, + -28, -28, -28, -28, 53, -28, -28 + }, + + { + 11, -29, -29, -29, -29, -29, -29, -29, -29, -29, + -29, -29, -29, -29, -29, -29, -29 + + }, + + { + 11, 54, 54, -30, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54 + }, + + { + 11, -31, -31, -31, -31, -31, -31, 55, -31, -31, + -31, -31, -31, -31, -31, -31, -31 + }, + + { + 11, -32, -32, -32, -32, -32, -32, -32, -32, -32, + -32, -32, -32, -32, -32, -32, -32 + }, + + { + 11, -33, -33, -33, -33, -33, -33, -33, -33, -33, + -33, -33, -33, -33, -33, -33, -33 + }, + + { + 11, -34, -34, -34, -34, -34, -34, -34, -34, -34, + -34, 56, 57, 57, -34, -34, -34 + + }, + + { + 11, -35, -35, -35, -35, -35, -35, -35, -35, -35, + -35, 57, 57, 57, -35, -35, -35 + }, + + { + 11, -36, -36, -36, -36, -36, -36, -36, -36, -36, + -36, -36, -36, -36, -36, -36, -36 + }, + + { + 11, -37, -37, 58, -37, -37, -37, -37, -37, -37, + -37, -37, -37, -37, -37, -37, -37 + }, + + { + 11, -38, -38, -38, -38, -38, -38, -38, -38, -38, + -38, -38, -38, -38, -38, -38, 59 + }, + + { + 11, -39, 39, 40, -39, -39, 41, -39, -39, -39, + -39, -39, -39, -39, -39, -39, -39 + + }, + + { + 11, -40, -40, -40, -40, -40, -40, -40, -40, -40, + -40, -40, -40, -40, -40, -40, -40 + }, + + { + 11, 42, 42, 43, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42 + }, + + { + 11, 42, 42, 43, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 42, 42 + }, + + { + 11, -43, -43, -43, -43, -43, -43, -43, -43, -43, + -43, -43, -43, -43, -43, -43, -43 + }, + + { + 11, -44, -44, -44, -44, -44, -44, -44, -44, -44, + -44, -44, -44, 44, -44, -44, -44 + + }, + + { + 11, 45, 45, -45, 45, 45, 45, 45, 45, 45, + 45, 45, 45, 45, 45, 45, 45 + }, + + { + 11, -46, 46, 47, -46, -46, -46, -46, -46, -46, + -46, -46, -46, -46, -46, -46, -46 + }, + + { + 11, 48, -47, -47, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48 + }, + + { + 11, -48, -48, -48, -48, -48, -48, -48, -48, -48, + -48, -48, -48, -48, -48, -48, -48 + }, + + { + 11, 49, 49, 50, 49, -49, 49, 49, -49, 49, + 49, 49, 49, 49, 49, -49, 49 + + }, + + { + 11, -50, -50, -50, -50, -50, -50, -50, -50, -50, + -50, -50, -50, -50, -50, -50, -50 + }, + + { + 11, -51, -51, 52, -51, -51, -51, -51, -51, -51, + -51, -51, -51, -51, -51, -51, -51 + }, + + { + 11, -52, -52, -52, -52, -52, -52, -52, -52, -52, + -52, -52, -52, -52, -52, -52, -52 + }, + + { + 11, -53, -53, -53, -53, -53, -53, -53, -53, -53, + -53, -53, -53, -53, -53, -53, -53 + }, + + { + 11, 54, 54, -54, 54, 54, 54, 54, 54, 54, + 54, 54, 54, 54, 54, 54, 54 + + }, + + { + 11, -55, -55, -55, -55, -55, -55, -55, -55, -55, + -55, -55, -55, -55, -55, -55, -55 + }, + + { + 11, -56, -56, -56, -56, -56, -56, -56, -56, -56, + -56, 60, 57, 57, -56, -56, -56 + }, + + { + 11, -57, -57, -57, -57, -57, -57, -57, -57, -57, + -57, 57, 57, 57, -57, -57, -57 + }, + + { + 11, -58, -58, -58, -58, -58, -58, -58, -58, -58, + -58, -58, -58, -58, -58, -58, -58 + }, + + { + 11, -59, -59, -59, -59, -59, -59, -59, -59, -59, + -59, -59, -59, -59, -59, -59, -59 + + }, + + { + 11, -60, -60, -60, -60, -60, -60, -60, -60, -60, + -60, 57, 57, 57, -60, -60, -60 + }, + + } ; + +static yy_state_type yy_get_previous_state (void ); +static yy_state_type yy_try_NUL_trans (yy_state_type current_state ); +static int yy_get_next_buffer (void ); +static void yy_fatal_error (yyconst char msg[] ); + +/* Done after the current pattern has been matched and before the + * corresponding action - sets up zconftext. + */ +#define YY_DO_BEFORE_ACTION \ + (yytext_ptr) = yy_bp; \ + zconfleng = (size_t) (yy_cp - yy_bp); \ + (yy_hold_char) = *yy_cp; \ + *yy_cp = '\0'; \ + (yy_c_buf_p) = yy_cp; + +#define YY_NUM_RULES 33 +#define YY_END_OF_BUFFER 34 +/* This struct is not used in this scanner, + but its presence is necessary. */ +struct yy_trans_info + { + flex_int32_t yy_verify; + flex_int32_t yy_nxt; + }; +static yyconst flex_int16_t yy_accept[61] = + { 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 34, 5, 4, 2, 3, 7, 8, 6, 32, 29, + 31, 24, 28, 27, 26, 22, 17, 13, 16, 20, + 22, 11, 12, 19, 19, 14, 22, 22, 4, 2, + 3, 3, 1, 6, 32, 29, 31, 30, 24, 23, + 26, 25, 15, 20, 9, 19, 19, 21, 10, 18 + } ; + +static yyconst flex_int32_t yy_ec[256] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 4, 5, 6, 1, 1, 7, 8, 9, + 10, 1, 1, 1, 11, 12, 12, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 1, 1, 1, + 14, 1, 1, 1, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 1, 15, 1, 1, 13, 1, 13, 13, 13, 13, + + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 1, 16, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1 + } ; + +extern int zconf_flex_debug; +int zconf_flex_debug = 0; + +/* The intent behind this definition is that it'll catch + * any uses of REJECT which flex missed. + */ +#define REJECT reject_used_but_not_detected +#define yymore() yymore_used_but_not_detected +#define YY_MORE_ADJ 0 +#define YY_RESTORE_YY_MORE_OFFSET +char *zconftext; +#define YY_NO_INPUT 1 + +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +#include +#include +#include +#include +#include + +#include "lkc.h" + +#define START_STRSIZE 16 + +static struct { + struct file *file; + int lineno; +} current_pos; + +static char *text; +static int text_size, text_asize; + +struct buffer { + struct buffer *parent; + YY_BUFFER_STATE state; +}; + +struct buffer *current_buf; + +static int last_ts, first_ts; + +static void zconf_endhelp(void); +static void zconf_endfile(void); + +static void new_string(void) +{ + text = malloc(START_STRSIZE); + text_asize = START_STRSIZE; + text_size = 0; + *text = 0; +} + +static void append_string(const char *str, int size) +{ + int new_size = text_size + size + 1; + if (new_size > text_asize) { + new_size += START_STRSIZE - 1; + new_size &= -START_STRSIZE; + text = realloc(text, new_size); + text_asize = new_size; + } + memcpy(text + text_size, str, size); + text_size += size; + text[text_size] = 0; +} + +static void alloc_string(const char *str, int size) +{ + text = malloc(size + 1); + memcpy(text, str, size); + text[size] = 0; +} + +#define INITIAL 0 +#define COMMAND 1 +#define HELP 2 +#define STRING 3 +#define PARAM 4 + +#ifndef YY_NO_UNISTD_H +/* Special case for "unistd.h", since it is non-ANSI. We include it way + * down here because we want the user's section 1 to have been scanned first. + * The user has a chance to override it with an option. + */ +#include +#endif + +#ifndef YY_EXTRA_TYPE +#define YY_EXTRA_TYPE void * +#endif + +static int yy_init_globals (void ); + +/* Accessor methods to globals. + These are made visible to non-reentrant scanners for convenience. */ + +int zconflex_destroy (void ); + +int zconfget_debug (void ); + +void zconfset_debug (int debug_flag ); + +YY_EXTRA_TYPE zconfget_extra (void ); + +void zconfset_extra (YY_EXTRA_TYPE user_defined ); + +FILE *zconfget_in (void ); + +void zconfset_in (FILE * in_str ); + +FILE *zconfget_out (void ); + +void zconfset_out (FILE * out_str ); + +int zconfget_leng (void ); + +char *zconfget_text (void ); + +int zconfget_lineno (void ); + +void zconfset_lineno (int line_number ); + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int zconfwrap (void ); +#else +extern int zconfwrap (void ); +#endif +#endif + + static void yyunput (int c,char *buf_ptr ); + +#ifndef yytext_ptr +static void yy_flex_strncpy (char *,yyconst char *,int ); +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen (yyconst char * ); +#endif + +#ifndef YY_NO_INPUT + +#ifdef __cplusplus +static int yyinput (void ); +#else +static int input (void ); +#endif + +#endif + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#define YY_READ_BUF_SIZE 8192 +#endif + +/* Copy whatever the last rule matched to the standard output. */ +#ifndef ECHO +/* This used to be an fputs(), but since the string might contain NUL's, + * we now use fwrite(). + */ +#define ECHO do { if (fwrite( zconftext, zconfleng, 1, zconfout )) {} } while (0) +#endif + +/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, + * is returned in "result". + */ +#ifndef YY_INPUT +#define YY_INPUT(buf,result,max_size) \ + errno=0; \ + while ( (result = read( fileno(zconfin), (char *) buf, max_size )) < 0 ) \ + { \ + if( errno != EINTR) \ + { \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + break; \ + } \ + errno=0; \ + clearerr(zconfin); \ + }\ +\ + +#endif + +/* No semi-colon after return; correct usage is to write "yyterminate();" - + * we don't want an extra ';' after the "return" because that will cause + * some compilers to complain about unreachable statements. + */ +#ifndef yyterminate +#define yyterminate() return YY_NULL +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Report a fatal error. */ +#ifndef YY_FATAL_ERROR +#define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) +#endif + +/* end tables serialization structures and prototypes */ + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL_IS_OURS 1 + +extern int zconflex (void); + +#define YY_DECL int zconflex (void) +#endif /* !YY_DECL */ + +/* Code executed at the beginning of each rule, after zconftext and zconfleng + * have been set up. + */ +#ifndef YY_USER_ACTION +#define YY_USER_ACTION +#endif + +/* Code executed at the end of each rule. */ +#ifndef YY_BREAK +#define YY_BREAK break; +#endif + +#define YY_RULE_SETUP \ + YY_USER_ACTION + +/** The main scanner function which does all the work. + */ +YY_DECL +{ + register yy_state_type yy_current_state; + register char *yy_cp, *yy_bp; + register int yy_act; + + int str = 0; + int ts, i; + + if ( !(yy_init) ) + { + (yy_init) = 1; + +#ifdef YY_USER_INIT + YY_USER_INIT; +#endif + + if ( ! (yy_start) ) + (yy_start) = 1; /* first start state */ + + if ( ! zconfin ) + zconfin = stdin; + + if ( ! zconfout ) + zconfout = stdout; + + if ( ! YY_CURRENT_BUFFER ) { + zconfensure_buffer_stack (); + YY_CURRENT_BUFFER_LVALUE = + zconf_create_buffer(zconfin,YY_BUF_SIZE ); + } + + zconf_load_buffer_state( ); + } + + while ( 1 ) /* loops until end-of-file is reached */ + { + yy_cp = (yy_c_buf_p); + + /* Support of zconftext. */ + *yy_cp = (yy_hold_char); + + /* yy_bp points to the position in yy_ch_buf of the start of + * the current run. + */ + yy_bp = yy_cp; + + yy_current_state = (yy_start); +yy_match: + while ( (yy_current_state = yy_nxt[yy_current_state][ yy_ec[YY_SC_TO_UI(*yy_cp)] ]) > 0 ) + ++yy_cp; + + yy_current_state = -yy_current_state; + +yy_find_action: + yy_act = yy_accept[yy_current_state]; + + YY_DO_BEFORE_ACTION; + +do_action: /* This label is used only to access EOF actions. */ + + switch ( yy_act ) + { /* beginning of action switch */ +case 1: +/* rule 1 can match eol */ +case 2: +/* rule 2 can match eol */ +YY_RULE_SETUP +{ + current_file->lineno++; + return T_EOL; +} + YY_BREAK +case 3: +YY_RULE_SETUP + + YY_BREAK +case 4: +YY_RULE_SETUP +{ + BEGIN(COMMAND); +} + YY_BREAK +case 5: +YY_RULE_SETUP +{ + unput(zconftext[0]); + BEGIN(COMMAND); +} + YY_BREAK + +case 6: +YY_RULE_SETUP +{ + const struct kconf_id *id = kconf_id_lookup(zconftext, zconfleng); + BEGIN(PARAM); + current_pos.file = current_file; + current_pos.lineno = current_file->lineno; + if (id && id->flags & TF_COMMAND) { + zconflval.id = id; + return id->token; + } + alloc_string(zconftext, zconfleng); + zconflval.string = text; + return T_WORD; + } + YY_BREAK +case 7: +YY_RULE_SETUP + + YY_BREAK +case 8: +/* rule 8 can match eol */ +YY_RULE_SETUP +{ + BEGIN(INITIAL); + current_file->lineno++; + return T_EOL; + } + YY_BREAK + +case 9: +YY_RULE_SETUP +return T_AND; + YY_BREAK +case 10: +YY_RULE_SETUP +return T_OR; + YY_BREAK +case 11: +YY_RULE_SETUP +return T_OPEN_PAREN; + YY_BREAK +case 12: +YY_RULE_SETUP +return T_CLOSE_PAREN; + YY_BREAK +case 13: +YY_RULE_SETUP +return T_NOT; + YY_BREAK +case 14: +YY_RULE_SETUP +return T_EQUAL; + YY_BREAK +case 15: +YY_RULE_SETUP +return T_UNEQUAL; + YY_BREAK +case 16: +YY_RULE_SETUP +{ + str = zconftext[0]; + new_string(); + BEGIN(STRING); + } + YY_BREAK +case 17: +/* rule 17 can match eol */ +YY_RULE_SETUP +BEGIN(INITIAL); current_file->lineno++; return T_EOL; + YY_BREAK +case 18: +YY_RULE_SETUP +/* ignore */ + YY_BREAK +case 19: +YY_RULE_SETUP +{ + const struct kconf_id *id = kconf_id_lookup(zconftext, zconfleng); + if (id && id->flags & TF_PARAM) { + zconflval.id = id; + return id->token; + } + alloc_string(zconftext, zconfleng); + zconflval.string = text; + return T_WORD; + } + YY_BREAK +case 20: +YY_RULE_SETUP +/* comment */ + YY_BREAK +case 21: +/* rule 21 can match eol */ +YY_RULE_SETUP +current_file->lineno++; + YY_BREAK +case 22: +YY_RULE_SETUP + + YY_BREAK +case YY_STATE_EOF(PARAM): +{ + BEGIN(INITIAL); + } + YY_BREAK + +case 23: +/* rule 23 can match eol */ +*yy_cp = (yy_hold_char); /* undo effects of setting up zconftext */ +(yy_c_buf_p) = yy_cp -= 1; +YY_DO_BEFORE_ACTION; /* set up zconftext again */ +YY_RULE_SETUP +{ + append_string(zconftext, zconfleng); + zconflval.string = text; + return T_WORD_QUOTE; + } + YY_BREAK +case 24: +YY_RULE_SETUP +{ + append_string(zconftext, zconfleng); + } + YY_BREAK +case 25: +/* rule 25 can match eol */ +*yy_cp = (yy_hold_char); /* undo effects of setting up zconftext */ +(yy_c_buf_p) = yy_cp -= 1; +YY_DO_BEFORE_ACTION; /* set up zconftext again */ +YY_RULE_SETUP +{ + append_string(zconftext + 1, zconfleng - 1); + zconflval.string = text; + return T_WORD_QUOTE; + } + YY_BREAK +case 26: +YY_RULE_SETUP +{ + append_string(zconftext + 1, zconfleng - 1); + } + YY_BREAK +case 27: +YY_RULE_SETUP +{ + if (str == zconftext[0]) { + BEGIN(PARAM); + zconflval.string = text; + return T_WORD_QUOTE; + } else + append_string(zconftext, 1); + } + YY_BREAK +case 28: +/* rule 28 can match eol */ +YY_RULE_SETUP +{ + printf("%s:%d:warning: multi-line strings not supported\n", zconf_curname(), zconf_lineno()); + current_file->lineno++; + BEGIN(INITIAL); + return T_EOL; + } + YY_BREAK +case YY_STATE_EOF(STRING): +{ + BEGIN(INITIAL); + } + YY_BREAK + +case 29: +YY_RULE_SETUP +{ + ts = 0; + for (i = 0; i < zconfleng; i++) { + if (zconftext[i] == '\t') + ts = (ts & ~7) + 8; + else + ts++; + } + last_ts = ts; + if (first_ts) { + if (ts < first_ts) { + zconf_endhelp(); + return T_HELPTEXT; + } + ts -= first_ts; + while (ts > 8) { + append_string(" ", 8); + ts -= 8; + } + append_string(" ", ts); + } + } + YY_BREAK +case 30: +/* rule 30 can match eol */ +*yy_cp = (yy_hold_char); /* undo effects of setting up zconftext */ +(yy_c_buf_p) = yy_cp -= 1; +YY_DO_BEFORE_ACTION; /* set up zconftext again */ +YY_RULE_SETUP +{ + current_file->lineno++; + zconf_endhelp(); + return T_HELPTEXT; + } + YY_BREAK +case 31: +/* rule 31 can match eol */ +YY_RULE_SETUP +{ + current_file->lineno++; + append_string("\n", 1); + } + YY_BREAK +case 32: +YY_RULE_SETUP +{ + while (zconfleng) { + if ((zconftext[zconfleng-1] != ' ') && (zconftext[zconfleng-1] != '\t')) + break; + zconfleng--; + } + append_string(zconftext, zconfleng); + if (!first_ts) + first_ts = last_ts; + } + YY_BREAK +case YY_STATE_EOF(HELP): +{ + zconf_endhelp(); + return T_HELPTEXT; + } + YY_BREAK + +case YY_STATE_EOF(INITIAL): +case YY_STATE_EOF(COMMAND): +{ + if (current_file) { + zconf_endfile(); + return T_EOL; + } + fclose(zconfin); + yyterminate(); +} + YY_BREAK +case 33: +YY_RULE_SETUP +YY_FATAL_ERROR( "flex scanner jammed" ); + YY_BREAK + + case YY_END_OF_BUFFER: + { + /* Amount of text matched not including the EOB char. */ + int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1; + + /* Undo the effects of YY_DO_BEFORE_ACTION. */ + *yy_cp = (yy_hold_char); + YY_RESTORE_YY_MORE_OFFSET + + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW ) + { + /* We're scanning a new file or input source. It's + * possible that this happened because the user + * just pointed zconfin at a new source and called + * zconflex(). If so, then we have to assure + * consistency between YY_CURRENT_BUFFER and our + * globals. Here is the right place to do so, because + * this is the first action (other than possibly a + * back-up) that will match for the new input source. + */ + (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + YY_CURRENT_BUFFER_LVALUE->yy_input_file = zconfin; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; + } + + /* Note that here we test for yy_c_buf_p "<=" to the position + * of the first EOB in the buffer, since yy_c_buf_p will + * already have been incremented past the NUL character + * (since all states make transitions on EOB to the + * end-of-buffer state). Contrast this with the test + * in input(). + */ + if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) + { /* This was really a NUL. */ + yy_state_type yy_next_state; + + (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state( ); + + /* Okay, we're now positioned to make the NUL + * transition. We couldn't have + * yy_get_previous_state() go ahead and do it + * for us because it doesn't know how to deal + * with the possibility of jamming (and we don't + * want to build jamming into it because then it + * will run more slowly). + */ + + yy_next_state = yy_try_NUL_trans( yy_current_state ); + + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + + if ( yy_next_state ) + { + /* Consume the NUL. */ + yy_cp = ++(yy_c_buf_p); + yy_current_state = yy_next_state; + goto yy_match; + } + + else + { + yy_cp = (yy_c_buf_p); + goto yy_find_action; + } + } + + else switch ( yy_get_next_buffer( ) ) + { + case EOB_ACT_END_OF_FILE: + { + (yy_did_buffer_switch_on_eof) = 0; + + if ( zconfwrap( ) ) + { + /* Note: because we've taken care in + * yy_get_next_buffer() to have set up + * zconftext, we can now set up + * yy_c_buf_p so that if some total + * hoser (like flex itself) wants to + * call the scanner after we return the + * YY_NULL, it'll still work - another + * YY_NULL will get returned. + */ + (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ; + + yy_act = YY_STATE_EOF(YY_START); + goto do_action; + } + + else + { + if ( ! (yy_did_buffer_switch_on_eof) ) + YY_NEW_FILE; + } + break; + } + + case EOB_ACT_CONTINUE_SCAN: + (yy_c_buf_p) = + (yytext_ptr) + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state( ); + + yy_cp = (yy_c_buf_p); + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + goto yy_match; + + case EOB_ACT_LAST_MATCH: + (yy_c_buf_p) = + &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)]; + + yy_current_state = yy_get_previous_state( ); + + yy_cp = (yy_c_buf_p); + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + goto yy_find_action; + } + break; + } + + default: + YY_FATAL_ERROR( + "fatal flex scanner internal error--no action found" ); + } /* end of action switch */ + } /* end of scanning one token */ +} /* end of zconflex */ + +/* yy_get_next_buffer - try to read in a new buffer + * + * Returns a code representing an action: + * EOB_ACT_LAST_MATCH - + * EOB_ACT_CONTINUE_SCAN - continue scanning from current position + * EOB_ACT_END_OF_FILE - end of file + */ +static int yy_get_next_buffer (void) +{ + register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; + register char *source = (yytext_ptr); + register int number_to_move, i; + int ret_val; + + if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] ) + YY_FATAL_ERROR( + "fatal flex scanner internal error--end of buffer missed" ); + + if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 ) + { /* Don't try to fill the buffer, so this is an EOF. */ + if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 ) + { + /* We matched a single character, the EOB, so + * treat this as a final EOF. + */ + return EOB_ACT_END_OF_FILE; + } + + else + { + /* We matched some text prior to the EOB, first + * process it. + */ + return EOB_ACT_LAST_MATCH; + } + } + + /* Try to read more data. */ + + /* First move last chars to start of buffer. */ + number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1; + + for ( i = 0; i < number_to_move; ++i ) + *(dest++) = *(source++); + + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING ) + /* don't do the read, it's not guaranteed to return an EOF, + * just force an EOF + */ + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0; + + else + { + int num_to_read = + YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; + + while ( num_to_read <= 0 ) + { /* Not enough room in the buffer - grow it. */ + + /* just a shorter name for the current buffer */ + YY_BUFFER_STATE b = YY_CURRENT_BUFFER; + + int yy_c_buf_p_offset = + (int) ((yy_c_buf_p) - b->yy_ch_buf); + + if ( b->yy_is_our_buffer ) + { + int new_size = b->yy_buf_size * 2; + + if ( new_size <= 0 ) + b->yy_buf_size += b->yy_buf_size / 8; + else + b->yy_buf_size *= 2; + + b->yy_ch_buf = (char *) + /* Include room in for 2 EOB chars. */ + zconfrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ); + } + else + /* Can't grow it, we don't own it. */ + b->yy_ch_buf = 0; + + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( + "fatal error - scanner input buffer overflow" ); + + (yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset]; + + num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - + number_to_move - 1; + + } + + if ( num_to_read > YY_READ_BUF_SIZE ) + num_to_read = YY_READ_BUF_SIZE; + + /* Read in more data. */ + YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), + (yy_n_chars), (size_t) num_to_read ); + + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + if ( (yy_n_chars) == 0 ) + { + if ( number_to_move == YY_MORE_ADJ ) + { + ret_val = EOB_ACT_END_OF_FILE; + zconfrestart(zconfin ); + } + + else + { + ret_val = EOB_ACT_LAST_MATCH; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = + YY_BUFFER_EOF_PENDING; + } + } + + else + ret_val = EOB_ACT_CONTINUE_SCAN; + + if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { + /* Extend the array by 50%, plus the number we really need. */ + yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1); + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) zconfrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ); + if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" ); + } + + (yy_n_chars) += number_to_move; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR; + + (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; + + return ret_val; +} + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + + static yy_state_type yy_get_previous_state (void) +{ + register yy_state_type yy_current_state; + register char *yy_cp; + + yy_current_state = (yy_start); + + for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp ) + { + yy_current_state = yy_nxt[yy_current_state][(*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1)]; + } + + return yy_current_state; +} + +/* yy_try_NUL_trans - try to make a transition on the NUL character + * + * synopsis + * next_state = yy_try_NUL_trans( current_state ); + */ + static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state ) +{ + register int yy_is_jam; + + yy_current_state = yy_nxt[yy_current_state][1]; + yy_is_jam = (yy_current_state <= 0); + + return yy_is_jam ? 0 : yy_current_state; +} + + static void yyunput (int c, register char * yy_bp ) +{ + register char *yy_cp; + + yy_cp = (yy_c_buf_p); + + /* undo effects of setting up zconftext */ + *yy_cp = (yy_hold_char); + + if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) + { /* need to shift things up to make room */ + /* +2 for EOB chars. */ + register int number_to_move = (yy_n_chars) + 2; + register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[ + YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2]; + register char *source = + &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]; + + while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) + *--dest = *--source; + + yy_cp += (int) (dest - source); + yy_bp += (int) (dest - source); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = + (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_buf_size; + + if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) + YY_FATAL_ERROR( "flex scanner push-back overflow" ); + } + + *--yy_cp = (char) c; + + (yytext_ptr) = yy_bp; + (yy_hold_char) = *yy_cp; + (yy_c_buf_p) = yy_cp; +} + +#ifndef YY_NO_INPUT +#ifdef __cplusplus + static int yyinput (void) +#else + static int input (void) +#endif + +{ + int c; + + *(yy_c_buf_p) = (yy_hold_char); + + if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR ) + { + /* yy_c_buf_p now points to the character we want to return. + * If this occurs *before* the EOB characters, then it's a + * valid NUL; if not, then we've hit the end of the buffer. + */ + if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) + /* This was really a NUL. */ + *(yy_c_buf_p) = '\0'; + + else + { /* need more input */ + int offset = (yy_c_buf_p) - (yytext_ptr); + ++(yy_c_buf_p); + + switch ( yy_get_next_buffer( ) ) + { + case EOB_ACT_LAST_MATCH: + /* This happens because yy_g_n_b() + * sees that we've accumulated a + * token and flags that we need to + * try matching the token before + * proceeding. But for input(), + * there's no matching to consider. + * So convert the EOB_ACT_LAST_MATCH + * to EOB_ACT_END_OF_FILE. + */ + + /* Reset buffer status. */ + zconfrestart(zconfin ); + + /*FALLTHROUGH*/ + + case EOB_ACT_END_OF_FILE: + { + if ( zconfwrap( ) ) + return EOF; + + if ( ! (yy_did_buffer_switch_on_eof) ) + YY_NEW_FILE; +#ifdef __cplusplus + return yyinput(); +#else + return input(); +#endif + } + + case EOB_ACT_CONTINUE_SCAN: + (yy_c_buf_p) = (yytext_ptr) + offset; + break; + } + } + } + + c = *(unsigned char *) (yy_c_buf_p); /* cast for 8-bit char's */ + *(yy_c_buf_p) = '\0'; /* preserve zconftext */ + (yy_hold_char) = *++(yy_c_buf_p); + + return c; +} +#endif /* ifndef YY_NO_INPUT */ + +/** Immediately switch to a different input stream. + * @param input_file A readable stream. + * + * @note This function does not reset the start condition to @c INITIAL . + */ + void zconfrestart (FILE * input_file ) +{ + + if ( ! YY_CURRENT_BUFFER ){ + zconfensure_buffer_stack (); + YY_CURRENT_BUFFER_LVALUE = + zconf_create_buffer(zconfin,YY_BUF_SIZE ); + } + + zconf_init_buffer(YY_CURRENT_BUFFER,input_file ); + zconf_load_buffer_state( ); +} + +/** Switch to a different input buffer. + * @param new_buffer The new input buffer. + * + */ + void zconf_switch_to_buffer (YY_BUFFER_STATE new_buffer ) +{ + + /* TODO. We should be able to replace this entire function body + * with + * zconfpop_buffer_state(); + * zconfpush_buffer_state(new_buffer); + */ + zconfensure_buffer_stack (); + if ( YY_CURRENT_BUFFER == new_buffer ) + return; + + if ( YY_CURRENT_BUFFER ) + { + /* Flush out information for old buffer. */ + *(yy_c_buf_p) = (yy_hold_char); + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + YY_CURRENT_BUFFER_LVALUE = new_buffer; + zconf_load_buffer_state( ); + + /* We don't actually know whether we did this switch during + * EOF (zconfwrap()) processing, but the only time this flag + * is looked at is after zconfwrap() is called, so it's safe + * to go ahead and always set it. + */ + (yy_did_buffer_switch_on_eof) = 1; +} + +static void zconf_load_buffer_state (void) +{ + (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; + zconfin = YY_CURRENT_BUFFER_LVALUE->yy_input_file; + (yy_hold_char) = *(yy_c_buf_p); +} + +/** Allocate and initialize an input buffer state. + * @param file A readable stream. + * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. + * + * @return the allocated buffer state. + */ + YY_BUFFER_STATE zconf_create_buffer (FILE * file, int size ) +{ + YY_BUFFER_STATE b; + + b = (YY_BUFFER_STATE) zconfalloc(sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in zconf_create_buffer()" ); + + b->yy_buf_size = size; + + /* yy_ch_buf has to be 2 characters longer than the size given because + * we need to put in 2 end-of-buffer characters. + */ + b->yy_ch_buf = (char *) zconfalloc(b->yy_buf_size + 2 ); + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in zconf_create_buffer()" ); + + b->yy_is_our_buffer = 1; + + zconf_init_buffer(b,file ); + + return b; +} + +/** Destroy the buffer. + * @param b a buffer created with zconf_create_buffer() + * + */ + void zconf_delete_buffer (YY_BUFFER_STATE b ) +{ + + if ( ! b ) + return; + + if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */ + YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; + + if ( b->yy_is_our_buffer ) + zconffree((void *) b->yy_ch_buf ); + + zconffree((void *) b ); +} + +/* Initializes or reinitializes a buffer. + * This function is sometimes called more than once on the same buffer, + * such as during a zconfrestart() or at EOF. + */ + static void zconf_init_buffer (YY_BUFFER_STATE b, FILE * file ) + +{ + int oerrno = errno; + + zconf_flush_buffer(b ); + + b->yy_input_file = file; + b->yy_fill_buffer = 1; + + /* If b is the current buffer, then zconf_init_buffer was _probably_ + * called from zconfrestart() or through yy_get_next_buffer. + * In that case, we don't want to reset the lineno or column. + */ + if (b != YY_CURRENT_BUFFER){ + b->yy_bs_lineno = 1; + b->yy_bs_column = 0; + } + + b->yy_is_interactive = 0; + + errno = oerrno; +} + +/** Discard all buffered characters. On the next scan, YY_INPUT will be called. + * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. + * + */ + void zconf_flush_buffer (YY_BUFFER_STATE b ) +{ + if ( ! b ) + return; + + b->yy_n_chars = 0; + + /* We always need two end-of-buffer characters. The first causes + * a transition to the end-of-buffer state. The second causes + * a jam in that state. + */ + b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; + b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; + + b->yy_buf_pos = &b->yy_ch_buf[0]; + + b->yy_at_bol = 1; + b->yy_buffer_status = YY_BUFFER_NEW; + + if ( b == YY_CURRENT_BUFFER ) + zconf_load_buffer_state( ); +} + +/** Pushes the new state onto the stack. The new state becomes + * the current state. This function will allocate the stack + * if necessary. + * @param new_buffer The new state. + * + */ +void zconfpush_buffer_state (YY_BUFFER_STATE new_buffer ) +{ + if (new_buffer == NULL) + return; + + zconfensure_buffer_stack(); + + /* This block is copied from zconf_switch_to_buffer. */ + if ( YY_CURRENT_BUFFER ) + { + /* Flush out information for old buffer. */ + *(yy_c_buf_p) = (yy_hold_char); + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + /* Only push if top exists. Otherwise, replace top. */ + if (YY_CURRENT_BUFFER) + (yy_buffer_stack_top)++; + YY_CURRENT_BUFFER_LVALUE = new_buffer; + + /* copied from zconf_switch_to_buffer. */ + zconf_load_buffer_state( ); + (yy_did_buffer_switch_on_eof) = 1; +} + +/** Removes and deletes the top of the stack, if present. + * The next element becomes the new top. + * + */ +void zconfpop_buffer_state (void) +{ + if (!YY_CURRENT_BUFFER) + return; + + zconf_delete_buffer(YY_CURRENT_BUFFER ); + YY_CURRENT_BUFFER_LVALUE = NULL; + if ((yy_buffer_stack_top) > 0) + --(yy_buffer_stack_top); + + if (YY_CURRENT_BUFFER) { + zconf_load_buffer_state( ); + (yy_did_buffer_switch_on_eof) = 1; + } +} + +/* Allocates the stack if it does not exist. + * Guarantees space for at least one push. + */ +static void zconfensure_buffer_stack (void) +{ + int num_to_alloc; + + if (!(yy_buffer_stack)) { + + /* First allocation is just for 2 elements, since we don't know if this + * scanner will even need a stack. We use 2 instead of 1 to avoid an + * immediate realloc on the next call. + */ + num_to_alloc = 1; + (yy_buffer_stack) = (struct yy_buffer_state**)zconfalloc + (num_to_alloc * sizeof(struct yy_buffer_state*) + ); + if ( ! (yy_buffer_stack) ) + YY_FATAL_ERROR( "out of dynamic memory in zconfensure_buffer_stack()" ); + + memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*)); + + (yy_buffer_stack_max) = num_to_alloc; + (yy_buffer_stack_top) = 0; + return; + } + + if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){ + + /* Increase the buffer to prepare for a possible push. */ + int grow_size = 8 /* arbitrary grow size */; + + num_to_alloc = (yy_buffer_stack_max) + grow_size; + (yy_buffer_stack) = (struct yy_buffer_state**)zconfrealloc + ((yy_buffer_stack), + num_to_alloc * sizeof(struct yy_buffer_state*) + ); + if ( ! (yy_buffer_stack) ) + YY_FATAL_ERROR( "out of dynamic memory in zconfensure_buffer_stack()" ); + + /* zero only the new slots.*/ + memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*)); + (yy_buffer_stack_max) = num_to_alloc; + } +} + +/** Setup the input buffer state to scan directly from a user-specified character buffer. + * @param base the character buffer + * @param size the size in bytes of the character buffer + * + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE zconf_scan_buffer (char * base, yy_size_t size ) +{ + YY_BUFFER_STATE b; + + if ( size < 2 || + base[size-2] != YY_END_OF_BUFFER_CHAR || + base[size-1] != YY_END_OF_BUFFER_CHAR ) + /* They forgot to leave room for the EOB's. */ + return 0; + + b = (YY_BUFFER_STATE) zconfalloc(sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in zconf_scan_buffer()" ); + + b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ + b->yy_buf_pos = b->yy_ch_buf = base; + b->yy_is_our_buffer = 0; + b->yy_input_file = 0; + b->yy_n_chars = b->yy_buf_size; + b->yy_is_interactive = 0; + b->yy_at_bol = 1; + b->yy_fill_buffer = 0; + b->yy_buffer_status = YY_BUFFER_NEW; + + zconf_switch_to_buffer(b ); + + return b; +} + +/** Setup the input buffer state to scan a string. The next call to zconflex() will + * scan from a @e copy of @a str. + * @param yystr a NUL-terminated string to scan + * + * @return the newly allocated buffer state object. + * @note If you want to scan bytes that may contain NUL values, then use + * zconf_scan_bytes() instead. + */ +YY_BUFFER_STATE zconf_scan_string (yyconst char * yystr ) +{ + + return zconf_scan_bytes(yystr,strlen(yystr) ); +} + +/** Setup the input buffer state to scan the given bytes. The next call to zconflex() will + * scan from a @e copy of @a bytes. + * @param bytes the byte buffer to scan + * @param len the number of bytes in the buffer pointed to by @a bytes. + * + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE zconf_scan_bytes (yyconst char * yybytes, int _yybytes_len ) +{ + YY_BUFFER_STATE b; + char *buf; + yy_size_t n; + int i; + + /* Get memory for full buffer, including space for trailing EOB's. */ + n = _yybytes_len + 2; + buf = (char *) zconfalloc(n ); + if ( ! buf ) + YY_FATAL_ERROR( "out of dynamic memory in zconf_scan_bytes()" ); + + for ( i = 0; i < _yybytes_len; ++i ) + buf[i] = yybytes[i]; + + buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR; + + b = zconf_scan_buffer(buf,n ); + if ( ! b ) + YY_FATAL_ERROR( "bad buffer in zconf_scan_bytes()" ); + + /* It's okay to grow etc. this buffer, and we should throw it + * away when we're done. + */ + b->yy_is_our_buffer = 1; + + return b; +} + +#ifndef YY_EXIT_FAILURE +#define YY_EXIT_FAILURE 2 +#endif + +static void yy_fatal_error (yyconst char* msg ) +{ + (void) fprintf( stderr, "%s\n", msg ); + exit( YY_EXIT_FAILURE ); +} + +/* Redefine yyless() so it works in section 3 code. */ + +#undef yyless +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up zconftext. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + zconftext[zconfleng] = (yy_hold_char); \ + (yy_c_buf_p) = zconftext + yyless_macro_arg; \ + (yy_hold_char) = *(yy_c_buf_p); \ + *(yy_c_buf_p) = '\0'; \ + zconfleng = yyless_macro_arg; \ + } \ + while ( 0 ) + +/* Accessor methods (get/set functions) to struct members. */ + +/** Get the current line number. + * + */ +int zconfget_lineno (void) +{ + + return zconflineno; +} + +/** Get the input stream. + * + */ +FILE *zconfget_in (void) +{ + return zconfin; +} + +/** Get the output stream. + * + */ +FILE *zconfget_out (void) +{ + return zconfout; +} + +/** Get the length of the current token. + * + */ +int zconfget_leng (void) +{ + return zconfleng; +} + +/** Get the current token. + * + */ + +char *zconfget_text (void) +{ + return zconftext; +} + +/** Set the current line number. + * @param line_number + * + */ +void zconfset_lineno (int line_number ) +{ + + zconflineno = line_number; +} + +/** Set the input stream. This does not discard the current + * input buffer. + * @param in_str A readable stream. + * + * @see zconf_switch_to_buffer + */ +void zconfset_in (FILE * in_str ) +{ + zconfin = in_str ; +} + +void zconfset_out (FILE * out_str ) +{ + zconfout = out_str ; +} + +int zconfget_debug (void) +{ + return zconf_flex_debug; +} + +void zconfset_debug (int bdebug ) +{ + zconf_flex_debug = bdebug ; +} + +static int yy_init_globals (void) +{ + /* Initialization is the same as for the non-reentrant scanner. + * This function is called from zconflex_destroy(), so don't allocate here. + */ + + (yy_buffer_stack) = 0; + (yy_buffer_stack_top) = 0; + (yy_buffer_stack_max) = 0; + (yy_c_buf_p) = (char *) 0; + (yy_init) = 0; + (yy_start) = 0; + +/* Defined in main.c */ +#ifdef YY_STDINIT + zconfin = stdin; + zconfout = stdout; +#else + zconfin = (FILE *) 0; + zconfout = (FILE *) 0; +#endif + + /* For future reference: Set errno on error, since we are called by + * zconflex_init() + */ + return 0; +} + +/* zconflex_destroy is for both reentrant and non-reentrant scanners. */ +int zconflex_destroy (void) +{ + + /* Pop the buffer stack, destroying each element. */ + while(YY_CURRENT_BUFFER){ + zconf_delete_buffer(YY_CURRENT_BUFFER ); + YY_CURRENT_BUFFER_LVALUE = NULL; + zconfpop_buffer_state(); + } + + /* Destroy the stack itself. */ + zconffree((yy_buffer_stack) ); + (yy_buffer_stack) = NULL; + + /* Reset the globals. This is important in a non-reentrant scanner so the next time + * zconflex() is called, initialization will occur. */ + yy_init_globals( ); + + return 0; +} + +/* + * Internal utility routines. + */ + +#ifndef yytext_ptr +static void yy_flex_strncpy (char* s1, yyconst char * s2, int n ) +{ + register int i; + for ( i = 0; i < n; ++i ) + s1[i] = s2[i]; +} +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen (yyconst char * s ) +{ + register int n; + for ( n = 0; s[n]; ++n ) + ; + + return n; +} +#endif + +void *zconfalloc (yy_size_t size ) +{ + return (void *) malloc( size ); +} + +void *zconfrealloc (void * ptr, yy_size_t size ) +{ + /* The cast to (char *) in the following accommodates both + * implementations that use char* generic pointers, and those + * that use void* generic pointers. It works with the latter + * because both ANSI C and C++ allow castless assignment from + * any pointer type to void*, and deal with argument conversions + * as though doing an assignment. + */ + return (void *) realloc( (char *) ptr, size ); +} + +void zconffree (void * ptr ) +{ + free( (char *) ptr ); /* see zconfrealloc() for (char *) cast */ +} + +#define YYTABLES_NAME "yytables" + +void zconf_starthelp(void) +{ + new_string(); + last_ts = first_ts = 0; + BEGIN(HELP); +} + +static void zconf_endhelp(void) +{ + zconflval.string = text; + BEGIN(INITIAL); +} + +/* + * Try to open specified file with following names: + * ./name + * $(srctree)/name + * The latter is used when srctree is separate from objtree + * when compiling the kernel. + * Return NULL if file is not found. + */ +FILE *zconf_fopen(const char *name) +{ + char *env, fullname[PATH_MAX+1]; + FILE *f; + + f = fopen(name, "r"); + if (!f && name != NULL && name[0] != '/') { + env = getenv(SRCTREE); + if (env) { + sprintf(fullname, "%s/%s", env, name); + f = fopen(fullname, "r"); + } + } + return f; +} + +void zconf_initscan(const char *name) +{ + zconfin = zconf_fopen(name); + if (!zconfin) { + printf("can't find file %s\n", name); + exit(1); + } + + current_buf = malloc(sizeof(*current_buf)); + memset(current_buf, 0, sizeof(*current_buf)); + + current_file = file_lookup(name); + current_file->lineno = 1; +} + +void zconf_nextfile(const char *name) +{ + struct file *iter; + struct file *file = file_lookup(name); + struct buffer *buf = malloc(sizeof(*buf)); + memset(buf, 0, sizeof(*buf)); + + current_buf->state = YY_CURRENT_BUFFER; + zconfin = zconf_fopen(file->name); + if (!zconfin) { + printf("%s:%d: can't open file \"%s\"\n", + zconf_curname(), zconf_lineno(), file->name); + exit(1); + } + zconf_switch_to_buffer(zconf_create_buffer(zconfin,YY_BUF_SIZE)); + buf->parent = current_buf; + current_buf = buf; + + for (iter = current_file->parent; iter; iter = iter->parent ) { + if (!strcmp(current_file->name,iter->name) ) { + printf("%s:%d: recursive inclusion detected. " + "Inclusion path:\n current file : '%s'\n", + zconf_curname(), zconf_lineno(), + zconf_curname()); + iter = current_file->parent; + while (iter && \ + strcmp(iter->name,current_file->name)) { + printf(" included from: '%s:%d'\n", + iter->name, iter->lineno-1); + iter = iter->parent; + } + if (iter) + printf(" included from: '%s:%d'\n", + iter->name, iter->lineno+1); + exit(1); + } + } + file->lineno = 1; + file->parent = current_file; + current_file = file; +} + +static void zconf_endfile(void) +{ + struct buffer *parent; + + current_file = current_file->parent; + + parent = current_buf->parent; + if (parent) { + fclose(zconfin); + zconf_delete_buffer(YY_CURRENT_BUFFER); + zconf_switch_to_buffer(parent->state); + } + free(current_buf); + current_buf = parent; +} + +int zconf_lineno(void) +{ + return current_pos.lineno; +} + +const char *zconf_curname(void) +{ + return current_pos.file ? current_pos.file->name : ""; +} + diff --git a/l4/tool/kconfig/scripts/kconfig/zconf.tab.c_shipped b/l4/tool/kconfig/scripts/kconfig/zconf.tab.c_shipped new file mode 100644 index 00000000..7e812d24 --- /dev/null +++ b/l4/tool/kconfig/scripts/kconfig/zconf.tab.c_shipped @@ -0,0 +1,2504 @@ +/* A Bison parser, made by GNU Bison 2.4.3. */ + +/* Skeleton implementation for Bison's Yacc-like parsers in C + + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006, + 2009, 2010 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* As a special exception, you may create a larger work that contains + part or all of the Bison parser skeleton and distribute that work + under terms of your choice, so long as that work isn't itself a + parser generator using the skeleton or a modified version thereof + as a parser skeleton. Alternatively, if you modify or redistribute + the parser skeleton itself, you may (at your option) remove this + special exception, which will cause the skeleton and the resulting + Bison output files to be licensed under the GNU General Public + License without this special exception. + + This special exception was added by the Free Software Foundation in + version 2.2 of Bison. */ + +/* C LALR(1) parser skeleton written by Richard Stallman, by + simplifying the original so-called "semantic" parser. */ + +/* All symbols defined below should begin with yy or YY, to avoid + infringing on user name space. This should be done even for local + variables, as they might otherwise be expanded by user macros. + There are some unavoidable exceptions within include files to + define necessary library symbols; they are noted "INFRINGES ON + USER NAME SPACE" below. */ + +/* Identify Bison output. */ +#define YYBISON 1 + +/* Bison version. */ +#define YYBISON_VERSION "2.4.3" + +/* Skeleton name. */ +#define YYSKELETON_NAME "yacc.c" + +/* Pure parsers. */ +#define YYPURE 0 + +/* Push parsers. */ +#define YYPUSH 0 + +/* Pull parsers. */ +#define YYPULL 1 + +/* Using locations. */ +#define YYLSP_NEEDED 0 + +/* Substitute the variable and function names. */ +#define yyparse zconfparse +#define yylex zconflex +#define yyerror zconferror +#define yylval zconflval +#define yychar zconfchar +#define yydebug zconfdebug +#define yynerrs zconfnerrs + + +/* Copy the first part of user declarations. */ + + +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +#include +#include +#include +#include +#include +#include + +#include "lkc.h" + +#define printd(mask, fmt...) if (cdebug & (mask)) printf(fmt) + +#define PRINTD 0x0001 +#define DEBUG_PARSE 0x0002 + +int cdebug = PRINTD; + +extern int zconflex(void); +static void zconfprint(const char *err, ...); +static void zconf_error(const char *err, ...); +static void zconferror(const char *err); +static bool zconf_endtoken(const struct kconf_id *id, int starttoken, int endtoken); + +struct symbol *symbol_hash[SYMBOL_HASHSIZE]; + +static struct menu *current_menu, *current_entry; + + + + +/* Enabling traces. */ +#ifndef YYDEBUG +# define YYDEBUG 1 +#endif + +/* Enabling verbose error messages. */ +#ifdef YYERROR_VERBOSE +# undef YYERROR_VERBOSE +# define YYERROR_VERBOSE 1 +#else +# define YYERROR_VERBOSE 0 +#endif + +/* Enabling the token table. */ +#ifndef YYTOKEN_TABLE +# define YYTOKEN_TABLE 0 +#endif + + +/* Tokens. */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE + /* Put the tokens into the symbol table, so that GDB and other debuggers + know about them. */ + enum yytokentype { + T_MAINMENU = 258, + T_MENU = 259, + T_ENDMENU = 260, + T_SOURCE = 261, + T_CHOICE = 262, + T_ENDCHOICE = 263, + T_COMMENT = 264, + T_CONFIG = 265, + T_MENUCONFIG = 266, + T_HELP = 267, + T_HELPTEXT = 268, + T_IF = 269, + T_ENDIF = 270, + T_DEPENDS = 271, + T_OPTIONAL = 272, + T_PROMPT = 273, + T_TYPE = 274, + T_DEFAULT = 275, + T_SELECT = 276, + T_RANGE = 277, + T_VISIBLE = 278, + T_OPTION = 279, + T_ON = 280, + T_WORD = 281, + T_WORD_QUOTE = 282, + T_UNEQUAL = 283, + T_CLOSE_PAREN = 284, + T_OPEN_PAREN = 285, + T_EOL = 286, + T_OR = 287, + T_AND = 288, + T_EQUAL = 289, + T_NOT = 290 + }; +#endif + + + +#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED +typedef union YYSTYPE +{ + + + char *string; + struct file *file; + struct symbol *symbol; + struct expr *expr; + struct menu *menu; + const struct kconf_id *id; + + + +} YYSTYPE; +# define YYSTYPE_IS_TRIVIAL 1 +# define yystype YYSTYPE /* obsolescent; will be withdrawn */ +# define YYSTYPE_IS_DECLARED 1 +#endif + + +/* Copy the second part of user declarations. */ + + +/* Include zconf.hash.c here so it can see the token constants. */ +#include "zconf.hash.c" + + + +#ifdef short +# undef short +#endif + +#ifdef YYTYPE_UINT8 +typedef YYTYPE_UINT8 yytype_uint8; +#else +typedef unsigned char yytype_uint8; +#endif + +#ifdef YYTYPE_INT8 +typedef YYTYPE_INT8 yytype_int8; +#elif (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +typedef signed char yytype_int8; +#else +typedef short int yytype_int8; +#endif + +#ifdef YYTYPE_UINT16 +typedef YYTYPE_UINT16 yytype_uint16; +#else +typedef unsigned short int yytype_uint16; +#endif + +#ifdef YYTYPE_INT16 +typedef YYTYPE_INT16 yytype_int16; +#else +typedef short int yytype_int16; +#endif + +#ifndef YYSIZE_T +# ifdef __SIZE_TYPE__ +# define YYSIZE_T __SIZE_TYPE__ +# elif defined size_t +# define YYSIZE_T size_t +# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +# include /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +# else +# define YYSIZE_T unsigned int +# endif +#endif + +#define YYSIZE_MAXIMUM ((YYSIZE_T) -1) + +#ifndef YY_ +# if defined YYENABLE_NLS && YYENABLE_NLS +# if ENABLE_NLS +# include /* INFRINGES ON USER NAME SPACE */ +# define YY_(msgid) dgettext ("bison-runtime", msgid) +# endif +# endif +# ifndef YY_ +# define YY_(msgid) msgid +# endif +#endif + +/* Suppress unused-variable warnings by "using" E. */ +#if ! defined lint || defined __GNUC__ +# define YYUSE(e) ((void) (e)) +#else +# define YYUSE(e) /* empty */ +#endif + +/* Identity function, used to suppress warnings about constant conditions. */ +#ifndef lint +# define YYID(n) (n) +#else +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static int +YYID (int yyi) +#else +static int +YYID (yyi) + int yyi; +#endif +{ + return yyi; +} +#endif + +#if ! defined yyoverflow || YYERROR_VERBOSE + +/* The parser invokes alloca or malloc; define the necessary symbols. */ + +# ifdef YYSTACK_USE_ALLOCA +# if YYSTACK_USE_ALLOCA +# ifdef __GNUC__ +# define YYSTACK_ALLOC __builtin_alloca +# elif defined __BUILTIN_VA_ARG_INCR +# include /* INFRINGES ON USER NAME SPACE */ +# elif defined _AIX +# define YYSTACK_ALLOC __alloca +# elif defined _MSC_VER +# include /* INFRINGES ON USER NAME SPACE */ +# define alloca _alloca +# else +# define YYSTACK_ALLOC alloca +# if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +# include /* INFRINGES ON USER NAME SPACE */ +# ifndef _STDLIB_H +# define _STDLIB_H 1 +# endif +# endif +# endif +# endif +# endif + +# ifdef YYSTACK_ALLOC + /* Pacify GCC's `empty if-body' warning. */ +# define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0)) +# ifndef YYSTACK_ALLOC_MAXIMUM + /* The OS might guarantee only one guard page at the bottom of the stack, + and a page size can be as small as 4096 bytes. So we cannot safely + invoke alloca (N) if N exceeds 4096. Use a slightly smaller number + to allow for a few compiler-allocated temporary stack slots. */ +# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */ +# endif +# else +# define YYSTACK_ALLOC YYMALLOC +# define YYSTACK_FREE YYFREE +# ifndef YYSTACK_ALLOC_MAXIMUM +# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM +# endif +# if (defined __cplusplus && ! defined _STDLIB_H \ + && ! ((defined YYMALLOC || defined malloc) \ + && (defined YYFREE || defined free))) +# include /* INFRINGES ON USER NAME SPACE */ +# ifndef _STDLIB_H +# define _STDLIB_H 1 +# endif +# endif +# ifndef YYMALLOC +# define YYMALLOC malloc +# if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# ifndef YYFREE +# define YYFREE free +# if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +void free (void *); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# endif +#endif /* ! defined yyoverflow || YYERROR_VERBOSE */ + + +#if (! defined yyoverflow \ + && (! defined __cplusplus \ + || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) + +/* A type that is properly aligned for any stack member. */ +union yyalloc +{ + yytype_int16 yyss_alloc; + YYSTYPE yyvs_alloc; +}; + +/* The size of the maximum gap between one aligned stack and the next. */ +# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) + +/* The size of an array large to enough to hold all stacks, each with + N elements. */ +# define YYSTACK_BYTES(N) \ + ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \ + + YYSTACK_GAP_MAXIMUM) + +/* Copy COUNT objects from FROM to TO. The source and destination do + not overlap. */ +# ifndef YYCOPY +# if defined __GNUC__ && 1 < __GNUC__ +# define YYCOPY(To, From, Count) \ + __builtin_memcpy (To, From, (Count) * sizeof (*(From))) +# else +# define YYCOPY(To, From, Count) \ + do \ + { \ + YYSIZE_T yyi; \ + for (yyi = 0; yyi < (Count); yyi++) \ + (To)[yyi] = (From)[yyi]; \ + } \ + while (YYID (0)) +# endif +# endif + +/* Relocate STACK from its old location to the new one. The + local variables YYSIZE and YYSTACKSIZE give the old and new number of + elements in the stack, and YYPTR gives the new location of the + stack. Advance YYPTR to a properly aligned location for the next + stack. */ +# define YYSTACK_RELOCATE(Stack_alloc, Stack) \ + do \ + { \ + YYSIZE_T yynewbytes; \ + YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \ + Stack = &yyptr->Stack_alloc; \ + yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ + yyptr += yynewbytes / sizeof (*yyptr); \ + } \ + while (YYID (0)) + +#endif + +/* YYFINAL -- State number of the termination state. */ +#define YYFINAL 11 +/* YYLAST -- Last index in YYTABLE. */ +#define YYLAST 290 + +/* YYNTOKENS -- Number of terminals. */ +#define YYNTOKENS 36 +/* YYNNTS -- Number of nonterminals. */ +#define YYNNTS 50 +/* YYNRULES -- Number of rules. */ +#define YYNRULES 118 +/* YYNRULES -- Number of states. */ +#define YYNSTATES 191 + +/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ +#define YYUNDEFTOK 2 +#define YYMAXUTOK 290 + +#define YYTRANSLATE(YYX) \ + ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) + +/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */ +static const yytype_uint8 yytranslate[] = +{ + 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, + 35 +}; + +#if YYDEBUG +/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in + YYRHS. */ +static const yytype_uint16 yyprhs[] = +{ + 0, 0, 3, 6, 8, 11, 13, 14, 17, 20, + 23, 26, 31, 36, 40, 42, 44, 46, 48, 50, + 52, 54, 56, 58, 60, 62, 64, 66, 68, 72, + 75, 79, 82, 86, 89, 90, 93, 96, 99, 102, + 105, 108, 112, 117, 122, 127, 133, 137, 138, 142, + 143, 146, 150, 153, 155, 159, 160, 163, 166, 169, + 172, 175, 180, 184, 187, 192, 193, 196, 200, 202, + 206, 207, 210, 213, 216, 220, 224, 228, 230, 234, + 235, 238, 241, 244, 248, 252, 255, 258, 261, 262, + 265, 268, 271, 276, 277, 280, 283, 286, 287, 290, + 292, 294, 297, 300, 303, 305, 308, 309, 312, 314, + 318, 322, 326, 329, 333, 337, 339, 341, 342 +}; + +/* YYRHS -- A `-1'-separated list of the rules' RHS. */ +static const yytype_int8 yyrhs[] = +{ + 37, 0, -1, 81, 38, -1, 38, -1, 63, 39, + -1, 39, -1, -1, 39, 41, -1, 39, 55, -1, + 39, 67, -1, 39, 80, -1, 39, 26, 1, 31, + -1, 39, 40, 1, 31, -1, 39, 1, 31, -1, + 16, -1, 18, -1, 19, -1, 21, -1, 17, -1, + 22, -1, 20, -1, 23, -1, 31, -1, 61, -1, + 71, -1, 44, -1, 46, -1, 69, -1, 26, 1, + 31, -1, 1, 31, -1, 10, 26, 31, -1, 43, + 47, -1, 11, 26, 31, -1, 45, 47, -1, -1, + 47, 48, -1, 47, 49, -1, 47, 75, -1, 47, + 73, -1, 47, 42, -1, 47, 31, -1, 19, 78, + 31, -1, 18, 79, 82, 31, -1, 20, 83, 82, + 31, -1, 21, 26, 82, 31, -1, 22, 84, 84, + 82, 31, -1, 24, 50, 31, -1, -1, 50, 26, + 51, -1, -1, 34, 79, -1, 7, 85, 31, -1, + 52, 56, -1, 80, -1, 53, 58, 54, -1, -1, + 56, 57, -1, 56, 75, -1, 56, 73, -1, 56, + 31, -1, 56, 42, -1, 18, 79, 82, 31, -1, + 19, 78, 31, -1, 17, 31, -1, 20, 26, 82, + 31, -1, -1, 58, 41, -1, 14, 83, 81, -1, + 80, -1, 59, 62, 60, -1, -1, 62, 41, -1, + 62, 67, -1, 62, 55, -1, 3, 79, 81, -1, + 4, 79, 31, -1, 64, 76, 74, -1, 80, -1, + 65, 68, 66, -1, -1, 68, 41, -1, 68, 67, + -1, 68, 55, -1, 6, 79, 31, -1, 9, 79, + 31, -1, 70, 74, -1, 12, 31, -1, 72, 13, + -1, -1, 74, 75, -1, 74, 31, -1, 74, 42, + -1, 16, 25, 83, 31, -1, -1, 76, 77, -1, + 76, 31, -1, 23, 82, -1, -1, 79, 82, -1, + 26, -1, 27, -1, 5, 31, -1, 8, 31, -1, + 15, 31, -1, 31, -1, 81, 31, -1, -1, 14, + 83, -1, 84, -1, 84, 34, 84, -1, 84, 28, + 84, -1, 30, 83, 29, -1, 35, 83, -1, 83, + 32, 83, -1, 83, 33, 83, -1, 26, -1, 27, + -1, -1, 26, -1 +}; + +/* YYRLINE[YYN] -- source line where rule number YYN was defined. */ +static const yytype_uint16 yyrline[] = +{ + 0, 104, 104, 104, 106, 106, 108, 110, 111, 112, + 113, 114, 115, 119, 123, 123, 123, 123, 123, 123, + 123, 123, 127, 128, 129, 130, 131, 132, 136, 137, + 143, 151, 157, 165, 175, 177, 178, 179, 180, 181, + 182, 185, 193, 199, 209, 215, 221, 224, 226, 237, + 238, 243, 252, 257, 265, 268, 270, 271, 272, 273, + 274, 277, 283, 294, 300, 310, 312, 317, 325, 333, + 336, 338, 339, 340, 345, 352, 359, 364, 372, 375, + 377, 378, 379, 382, 390, 397, 404, 410, 417, 419, + 420, 421, 424, 432, 434, 435, 438, 445, 447, 452, + 453, 456, 457, 458, 462, 463, 466, 467, 470, 471, + 472, 473, 474, 475, 476, 479, 480, 483, 484 +}; +#endif + +#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE +/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. + First, the terminals, then, starting at YYNTOKENS, nonterminals. */ +static const char *const yytname[] = +{ + "$end", "error", "$undefined", "T_MAINMENU", "T_MENU", "T_ENDMENU", + "T_SOURCE", "T_CHOICE", "T_ENDCHOICE", "T_COMMENT", "T_CONFIG", + "T_MENUCONFIG", "T_HELP", "T_HELPTEXT", "T_IF", "T_ENDIF", "T_DEPENDS", + "T_OPTIONAL", "T_PROMPT", "T_TYPE", "T_DEFAULT", "T_SELECT", "T_RANGE", + "T_VISIBLE", "T_OPTION", "T_ON", "T_WORD", "T_WORD_QUOTE", "T_UNEQUAL", + "T_CLOSE_PAREN", "T_OPEN_PAREN", "T_EOL", "T_OR", "T_AND", "T_EQUAL", + "T_NOT", "$accept", "input", "start", "stmt_list", "option_name", + "common_stmt", "option_error", "config_entry_start", "config_stmt", + "menuconfig_entry_start", "menuconfig_stmt", "config_option_list", + "config_option", "symbol_option", "symbol_option_list", + "symbol_option_arg", "choice", "choice_entry", "choice_end", + "choice_stmt", "choice_option_list", "choice_option", "choice_block", + "if_entry", "if_end", "if_stmt", "if_block", "mainmenu_stmt", "menu", + "menu_entry", "menu_end", "menu_stmt", "menu_block", "source_stmt", + "comment", "comment_stmt", "help_start", "help", "depends_list", + "depends", "visibility_list", "visible", "prompt_stmt_opt", "prompt", + "end", "nl", "if_expr", "expr", "symbol", "word_opt", 0 +}; +#endif + +# ifdef YYPRINT +/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to + token YYLEX-NUM. */ +static const yytype_uint16 yytoknum[] = +{ + 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, + 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, + 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, + 285, 286, 287, 288, 289, 290 +}; +# endif + +/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ +static const yytype_uint8 yyr1[] = +{ + 0, 36, 37, 37, 38, 38, 39, 39, 39, 39, + 39, 39, 39, 39, 40, 40, 40, 40, 40, 40, + 40, 40, 41, 41, 41, 41, 41, 41, 42, 42, + 43, 44, 45, 46, 47, 47, 47, 47, 47, 47, + 47, 48, 48, 48, 48, 48, 49, 50, 50, 51, + 51, 52, 53, 54, 55, 56, 56, 56, 56, 56, + 56, 57, 57, 57, 57, 58, 58, 59, 60, 61, + 62, 62, 62, 62, 63, 64, 65, 66, 67, 68, + 68, 68, 68, 69, 70, 71, 72, 73, 74, 74, + 74, 74, 75, 76, 76, 76, 77, 78, 78, 79, + 79, 80, 80, 80, 81, 81, 82, 82, 83, 83, + 83, 83, 83, 83, 83, 84, 84, 85, 85 +}; + +/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ +static const yytype_uint8 yyr2[] = +{ + 0, 2, 2, 1, 2, 1, 0, 2, 2, 2, + 2, 4, 4, 3, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 3, 2, + 3, 2, 3, 2, 0, 2, 2, 2, 2, 2, + 2, 3, 4, 4, 4, 5, 3, 0, 3, 0, + 2, 3, 2, 1, 3, 0, 2, 2, 2, 2, + 2, 4, 3, 2, 4, 0, 2, 3, 1, 3, + 0, 2, 2, 2, 3, 3, 3, 1, 3, 0, + 2, 2, 2, 3, 3, 2, 2, 2, 0, 2, + 2, 2, 4, 0, 2, 2, 2, 0, 2, 1, + 1, 2, 2, 2, 1, 2, 0, 2, 1, 3, + 3, 3, 2, 3, 3, 1, 1, 0, 1 +}; + +/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state + STATE-NUM when YYTABLE doesn't specify something else to do. Zero + means the default is an error. */ +static const yytype_uint8 yydefact[] = +{ + 6, 0, 104, 0, 3, 0, 6, 6, 99, 100, + 0, 1, 0, 0, 0, 0, 117, 0, 0, 0, + 0, 0, 0, 14, 18, 15, 16, 20, 17, 19, + 21, 0, 22, 0, 7, 34, 25, 34, 26, 55, + 65, 8, 70, 23, 93, 79, 9, 27, 88, 24, + 10, 0, 105, 2, 74, 13, 0, 101, 0, 118, + 0, 102, 0, 0, 0, 115, 116, 0, 0, 0, + 108, 103, 0, 0, 0, 0, 0, 0, 0, 88, + 0, 0, 75, 83, 51, 84, 30, 32, 0, 112, + 0, 0, 67, 0, 0, 11, 12, 0, 0, 0, + 0, 97, 0, 0, 0, 47, 0, 40, 39, 35, + 36, 0, 38, 37, 0, 0, 97, 0, 59, 60, + 56, 58, 57, 66, 54, 53, 71, 73, 69, 72, + 68, 106, 95, 0, 94, 80, 82, 78, 81, 77, + 90, 91, 89, 111, 113, 114, 110, 109, 29, 86, + 0, 106, 0, 106, 106, 106, 0, 0, 0, 87, + 63, 106, 0, 106, 0, 96, 0, 0, 41, 98, + 0, 0, 106, 49, 46, 28, 0, 62, 0, 107, + 92, 42, 43, 44, 0, 0, 48, 61, 64, 45, + 50 +}; + +/* YYDEFGOTO[NTERM-NUM]. */ +static const yytype_int16 yydefgoto[] = +{ + -1, 3, 4, 5, 33, 34, 108, 35, 36, 37, + 38, 74, 109, 110, 157, 186, 39, 40, 124, 41, + 76, 120, 77, 42, 128, 43, 78, 6, 44, 45, + 137, 46, 80, 47, 48, 49, 111, 112, 81, 113, + 79, 134, 152, 153, 50, 7, 165, 69, 70, 60 +}; + +/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing + STATE-NUM. */ +#define YYPACT_NINF -90 +static const yytype_int16 yypact[] = +{ + 4, 42, -90, 96, -90, 111, -90, 15, -90, -90, + 75, -90, 82, 42, 104, 42, 110, 107, 42, 115, + 125, -4, 121, -90, -90, -90, -90, -90, -90, -90, + -90, 162, -90, 163, -90, -90, -90, -90, -90, -90, + -90, -90, -90, -90, -90, -90, -90, -90, -90, -90, + -90, 139, -90, -90, 138, -90, 142, -90, 143, -90, + 152, -90, 164, 167, 168, -90, -90, -4, -4, 77, + -18, -90, 177, 185, 33, 71, 195, 247, 236, -2, + 236, 171, -90, -90, -90, -90, -90, -90, 41, -90, + -4, -4, 138, 97, 97, -90, -90, 186, 187, 194, + 42, 42, -4, 196, 97, -90, 219, -90, -90, -90, + -90, 210, -90, -90, 204, 42, 42, 199, -90, -90, + -90, -90, -90, -90, -90, -90, -90, -90, -90, -90, + -90, 222, -90, 223, -90, -90, -90, -90, -90, -90, + -90, -90, -90, -90, 215, -90, -90, -90, -90, -90, + -4, 222, 228, 222, -5, 222, 97, 35, 229, -90, + -90, 222, 232, 222, -4, -90, 135, 233, -90, -90, + 234, 235, 222, 240, -90, -90, 237, -90, 239, -13, + -90, -90, -90, -90, 244, 42, -90, -90, -90, -90, + -90 +}; + +/* YYPGOTO[NTERM-NUM]. */ +static const yytype_int16 yypgoto[] = +{ + -90, -90, 269, 271, -90, 23, -70, -90, -90, -90, + -90, 243, -90, -90, -90, -90, -90, -90, -90, -48, + -90, -90, -90, -90, -90, -90, -90, -90, -90, -90, + -90, -20, -90, -90, -90, -90, -90, 206, 205, -68, + -90, -90, 169, -1, 27, -7, 118, -66, -89, -90 +}; + +/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If + positive, shift that token. If negative, reduce the rule which + number is the opposite. If zero, do what YYDEFACT says. + If YYTABLE_NINF, syntax error. */ +#define YYTABLE_NINF -86 +static const yytype_int16 yytable[] = +{ + 10, 88, 89, 54, 146, 147, 119, 1, 122, 164, + 93, 141, 56, 142, 58, 156, 94, 62, 1, 90, + 91, 131, 65, 66, 144, 145, 67, 90, 91, 132, + 127, 68, 136, -31, 97, 2, 154, -31, -31, -31, + -31, -31, -31, -31, -31, 98, 52, -31, -31, 99, + -31, 100, 101, 102, 103, 104, -31, 105, 129, 106, + 138, 173, 92, 141, 107, 142, 174, 172, 8, 9, + 143, -33, 97, 90, 91, -33, -33, -33, -33, -33, + -33, -33, -33, 98, 166, -33, -33, 99, -33, 100, + 101, 102, 103, 104, -33, 105, 11, 106, 179, 151, + 123, 126, 107, 135, 125, 130, 2, 139, 2, 90, + 91, -5, 12, 55, 161, 13, 14, 15, 16, 17, + 18, 19, 20, 65, 66, 21, 22, 23, 24, 25, + 26, 27, 28, 29, 30, 57, 59, 31, 61, -4, + 12, 63, 32, 13, 14, 15, 16, 17, 18, 19, + 20, 64, 71, 21, 22, 23, 24, 25, 26, 27, + 28, 29, 30, 72, 73, 31, 180, 90, 91, 52, + 32, -85, 97, 82, 83, -85, -85, -85, -85, -85, + -85, -85, -85, 84, 190, -85, -85, 99, -85, -85, + -85, -85, -85, -85, -85, 85, 97, 106, 86, 87, + -52, -52, 140, -52, -52, -52, -52, 98, 95, -52, + -52, 99, 114, 115, 116, 117, 96, 148, 149, 150, + 158, 106, 155, 159, 97, 163, 118, -76, -76, -76, + -76, -76, -76, -76, -76, 160, 164, -76, -76, 99, + 13, 14, 15, 16, 17, 18, 19, 20, 91, 106, + 21, 22, 14, 15, 140, 17, 18, 19, 20, 168, + 175, 21, 22, 177, 181, 182, 183, 32, 187, 167, + 188, 169, 170, 171, 185, 189, 53, 51, 32, 176, + 75, 178, 121, 0, 133, 162, 0, 0, 0, 0, + 184 +}; + +static const yytype_int16 yycheck[] = +{ + 1, 67, 68, 10, 93, 94, 76, 3, 76, 14, + 28, 81, 13, 81, 15, 104, 34, 18, 3, 32, + 33, 23, 26, 27, 90, 91, 30, 32, 33, 31, + 78, 35, 80, 0, 1, 31, 102, 4, 5, 6, + 7, 8, 9, 10, 11, 12, 31, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, 78, 26, + 80, 26, 69, 133, 31, 133, 31, 156, 26, 27, + 29, 0, 1, 32, 33, 4, 5, 6, 7, 8, + 9, 10, 11, 12, 150, 14, 15, 16, 17, 18, + 19, 20, 21, 22, 23, 24, 0, 26, 164, 100, + 77, 78, 31, 80, 77, 78, 31, 80, 31, 32, + 33, 0, 1, 31, 115, 4, 5, 6, 7, 8, + 9, 10, 11, 26, 27, 14, 15, 16, 17, 18, + 19, 20, 21, 22, 23, 31, 26, 26, 31, 0, + 1, 26, 31, 4, 5, 6, 7, 8, 9, 10, + 11, 26, 31, 14, 15, 16, 17, 18, 19, 20, + 21, 22, 23, 1, 1, 26, 31, 32, 33, 31, + 31, 0, 1, 31, 31, 4, 5, 6, 7, 8, + 9, 10, 11, 31, 185, 14, 15, 16, 17, 18, + 19, 20, 21, 22, 23, 31, 1, 26, 31, 31, + 5, 6, 31, 8, 9, 10, 11, 12, 31, 14, + 15, 16, 17, 18, 19, 20, 31, 31, 31, 25, + 1, 26, 26, 13, 1, 26, 31, 4, 5, 6, + 7, 8, 9, 10, 11, 31, 14, 14, 15, 16, + 4, 5, 6, 7, 8, 9, 10, 11, 33, 26, + 14, 15, 5, 6, 31, 8, 9, 10, 11, 31, + 31, 14, 15, 31, 31, 31, 31, 31, 31, 151, + 31, 153, 154, 155, 34, 31, 7, 6, 31, 161, + 37, 163, 76, -1, 79, 116, -1, -1, -1, -1, + 172 +}; + +/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing + symbol of state STATE-NUM. */ +static const yytype_uint8 yystos[] = +{ + 0, 3, 31, 37, 38, 39, 63, 81, 26, 27, + 79, 0, 1, 4, 5, 6, 7, 8, 9, 10, + 11, 14, 15, 16, 17, 18, 19, 20, 21, 22, + 23, 26, 31, 40, 41, 43, 44, 45, 46, 52, + 53, 55, 59, 61, 64, 65, 67, 69, 70, 71, + 80, 39, 31, 38, 81, 31, 79, 31, 79, 26, + 85, 31, 79, 26, 26, 26, 27, 30, 35, 83, + 84, 31, 1, 1, 47, 47, 56, 58, 62, 76, + 68, 74, 31, 31, 31, 31, 31, 31, 83, 83, + 32, 33, 81, 28, 34, 31, 31, 1, 12, 16, + 18, 19, 20, 21, 22, 24, 26, 31, 42, 48, + 49, 72, 73, 75, 17, 18, 19, 20, 31, 42, + 57, 73, 75, 41, 54, 80, 41, 55, 60, 67, + 80, 23, 31, 74, 77, 41, 55, 66, 67, 80, + 31, 42, 75, 29, 83, 83, 84, 84, 31, 31, + 25, 79, 78, 79, 83, 26, 84, 50, 1, 13, + 31, 79, 78, 26, 14, 82, 83, 82, 31, 82, + 82, 82, 84, 26, 31, 31, 82, 31, 82, 83, + 31, 31, 31, 31, 82, 34, 51, 31, 31, 31, + 79 +}; + +#define yyerrok (yyerrstatus = 0) +#define yyclearin (yychar = YYEMPTY) +#define YYEMPTY (-2) +#define YYEOF 0 + +#define YYACCEPT goto yyacceptlab +#define YYABORT goto yyabortlab +#define YYERROR goto yyerrorlab + + +/* Like YYERROR except do call yyerror. This remains here temporarily + to ease the transition to the new meaning of YYERROR, for GCC. + Once GCC version 2 has supplanted version 1, this can go. However, + YYFAIL appears to be in use. Nevertheless, it is formally deprecated + in Bison 2.4.2's NEWS entry, where a plan to phase it out is + discussed. */ + +#define YYFAIL goto yyerrlab +#if defined YYFAIL + /* This is here to suppress warnings from the GCC cpp's + -Wunused-macros. Normally we don't worry about that warning, but + some users do, and we want to make it easy for users to remove + YYFAIL uses, which will produce warnings from Bison 2.5. */ +#endif + +#define YYRECOVERING() (!!yyerrstatus) + +#define YYBACKUP(Token, Value) \ +do \ + if (yychar == YYEMPTY && yylen == 1) \ + { \ + yychar = (Token); \ + yylval = (Value); \ + yytoken = YYTRANSLATE (yychar); \ + YYPOPSTACK (1); \ + goto yybackup; \ + } \ + else \ + { \ + yyerror (YY_("syntax error: cannot back up")); \ + YYERROR; \ + } \ +while (YYID (0)) + + +#define YYTERROR 1 +#define YYERRCODE 256 + + +/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. + If N is 0, then set CURRENT to the empty location which ends + the previous symbol: RHS[0] (always defined). */ + +#define YYRHSLOC(Rhs, K) ((Rhs)[K]) +#ifndef YYLLOC_DEFAULT +# define YYLLOC_DEFAULT(Current, Rhs, N) \ + do \ + if (YYID (N)) \ + { \ + (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ + (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ + (Current).last_line = YYRHSLOC (Rhs, N).last_line; \ + (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ + } \ + else \ + { \ + (Current).first_line = (Current).last_line = \ + YYRHSLOC (Rhs, 0).last_line; \ + (Current).first_column = (Current).last_column = \ + YYRHSLOC (Rhs, 0).last_column; \ + } \ + while (YYID (0)) +#endif + + +/* YY_LOCATION_PRINT -- Print the location on the stream. + This macro was not mandated originally: define only if we know + we won't break user code: when these are the locations we know. */ + +#ifndef YY_LOCATION_PRINT +# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL +# define YY_LOCATION_PRINT(File, Loc) \ + fprintf (File, "%d.%d-%d.%d", \ + (Loc).first_line, (Loc).first_column, \ + (Loc).last_line, (Loc).last_column) +# else +# define YY_LOCATION_PRINT(File, Loc) ((void) 0) +# endif +#endif + + +/* YYLEX -- calling `yylex' with the right arguments. */ + +#ifdef YYLEX_PARAM +# define YYLEX yylex (YYLEX_PARAM) +#else +# define YYLEX yylex () +#endif + +/* Enable debugging if requested. */ +#if YYDEBUG + +# ifndef YYFPRINTF +# include /* INFRINGES ON USER NAME SPACE */ +# define YYFPRINTF fprintf +# endif + +# define YYDPRINTF(Args) \ +do { \ + if (yydebug) \ + YYFPRINTF Args; \ +} while (YYID (0)) + +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ +do { \ + if (yydebug) \ + { \ + YYFPRINTF (stderr, "%s ", Title); \ + yy_symbol_print (stderr, \ + Type, Value); \ + YYFPRINTF (stderr, "\n"); \ + } \ +} while (YYID (0)) + + +/*--------------------------------. +| Print this symbol on YYOUTPUT. | +`--------------------------------*/ + +/*ARGSUSED*/ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) +#else +static void +yy_symbol_value_print (yyoutput, yytype, yyvaluep) + FILE *yyoutput; + int yytype; + YYSTYPE const * const yyvaluep; +#endif +{ + if (!yyvaluep) + return; +# ifdef YYPRINT + if (yytype < YYNTOKENS) + YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); +# else + YYUSE (yyoutput); +# endif + switch (yytype) + { + default: + break; + } +} + + +/*--------------------------------. +| Print this symbol on YYOUTPUT. | +`--------------------------------*/ + +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) +#else +static void +yy_symbol_print (yyoutput, yytype, yyvaluep) + FILE *yyoutput; + int yytype; + YYSTYPE const * const yyvaluep; +#endif +{ + if (yytype < YYNTOKENS) + YYFPRINTF (yyoutput, "token %s (", yytname[yytype]); + else + YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); + + yy_symbol_value_print (yyoutput, yytype, yyvaluep); + YYFPRINTF (yyoutput, ")"); +} + +/*------------------------------------------------------------------. +| yy_stack_print -- Print the state stack from its BOTTOM up to its | +| TOP (included). | +`------------------------------------------------------------------*/ + +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop) +#else +static void +yy_stack_print (yybottom, yytop) + yytype_int16 *yybottom; + yytype_int16 *yytop; +#endif +{ + YYFPRINTF (stderr, "Stack now"); + for (; yybottom <= yytop; yybottom++) + { + int yybot = *yybottom; + YYFPRINTF (stderr, " %d", yybot); + } + YYFPRINTF (stderr, "\n"); +} + +# define YY_STACK_PRINT(Bottom, Top) \ +do { \ + if (yydebug) \ + yy_stack_print ((Bottom), (Top)); \ +} while (YYID (0)) + + +/*------------------------------------------------. +| Report that the YYRULE is going to be reduced. | +`------------------------------------------------*/ + +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_reduce_print (YYSTYPE *yyvsp, int yyrule) +#else +static void +yy_reduce_print (yyvsp, yyrule) + YYSTYPE *yyvsp; + int yyrule; +#endif +{ + int yynrhs = yyr2[yyrule]; + int yyi; + unsigned long int yylno = yyrline[yyrule]; + YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n", + yyrule - 1, yylno); + /* The symbols being reduced. */ + for (yyi = 0; yyi < yynrhs; yyi++) + { + YYFPRINTF (stderr, " $%d = ", yyi + 1); + yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi], + &(yyvsp[(yyi + 1) - (yynrhs)]) + ); + YYFPRINTF (stderr, "\n"); + } +} + +# define YY_REDUCE_PRINT(Rule) \ +do { \ + if (yydebug) \ + yy_reduce_print (yyvsp, Rule); \ +} while (YYID (0)) + +/* Nonzero means print parse trace. It is left uninitialized so that + multiple parsers can coexist. */ +int yydebug; +#else /* !YYDEBUG */ +# define YYDPRINTF(Args) +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) +# define YY_STACK_PRINT(Bottom, Top) +# define YY_REDUCE_PRINT(Rule) +#endif /* !YYDEBUG */ + + +/* YYINITDEPTH -- initial size of the parser's stacks. */ +#ifndef YYINITDEPTH +# define YYINITDEPTH 200 +#endif + +/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only + if the built-in stack extension method is used). + + Do not make this value too large; the results are undefined if + YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) + evaluated with infinite-precision integer arithmetic. */ + +#ifndef YYMAXDEPTH +# define YYMAXDEPTH 10000 +#endif + + + +#if YYERROR_VERBOSE + +# ifndef yystrlen +# if defined __GLIBC__ && defined _STRING_H +# define yystrlen strlen +# else +/* Return the length of YYSTR. */ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static YYSIZE_T +yystrlen (const char *yystr) +#else +static YYSIZE_T +yystrlen (yystr) + const char *yystr; +#endif +{ + YYSIZE_T yylen; + for (yylen = 0; yystr[yylen]; yylen++) + continue; + return yylen; +} +# endif +# endif + +# ifndef yystpcpy +# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE +# define yystpcpy stpcpy +# else +/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in + YYDEST. */ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static char * +yystpcpy (char *yydest, const char *yysrc) +#else +static char * +yystpcpy (yydest, yysrc) + char *yydest; + const char *yysrc; +#endif +{ + char *yyd = yydest; + const char *yys = yysrc; + + while ((*yyd++ = *yys++) != '\0') + continue; + + return yyd - 1; +} +# endif +# endif + +# ifndef yytnamerr +/* Copy to YYRES the contents of YYSTR after stripping away unnecessary + quotes and backslashes, so that it's suitable for yyerror. The + heuristic is that double-quoting is unnecessary unless the string + contains an apostrophe, a comma, or backslash (other than + backslash-backslash). YYSTR is taken from yytname. If YYRES is + null, do not copy; instead, return the length of what the result + would have been. */ +static YYSIZE_T +yytnamerr (char *yyres, const char *yystr) +{ + if (*yystr == '"') + { + YYSIZE_T yyn = 0; + char const *yyp = yystr; + + for (;;) + switch (*++yyp) + { + case '\'': + case ',': + goto do_not_strip_quotes; + + case '\\': + if (*++yyp != '\\') + goto do_not_strip_quotes; + /* Fall through. */ + default: + if (yyres) + yyres[yyn] = *yyp; + yyn++; + break; + + case '"': + if (yyres) + yyres[yyn] = '\0'; + return yyn; + } + do_not_strip_quotes: ; + } + + if (! yyres) + return yystrlen (yystr); + + return yystpcpy (yyres, yystr) - yyres; +} +# endif + +/* Copy into YYRESULT an error message about the unexpected token + YYCHAR while in state YYSTATE. Return the number of bytes copied, + including the terminating null byte. If YYRESULT is null, do not + copy anything; just return the number of bytes that would be + copied. As a special case, return 0 if an ordinary "syntax error" + message will do. Return YYSIZE_MAXIMUM if overflow occurs during + size calculation. */ +static YYSIZE_T +yysyntax_error (char *yyresult, int yystate, int yychar) +{ + int yyn = yypact[yystate]; + + if (! (YYPACT_NINF < yyn && yyn <= YYLAST)) + return 0; + else + { + int yytype = YYTRANSLATE (yychar); + YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]); + YYSIZE_T yysize = yysize0; + YYSIZE_T yysize1; + int yysize_overflow = 0; + enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; + char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; + int yyx; + +# if 0 + /* This is so xgettext sees the translatable formats that are + constructed on the fly. */ + YY_("syntax error, unexpected %s"); + YY_("syntax error, unexpected %s, expecting %s"); + YY_("syntax error, unexpected %s, expecting %s or %s"); + YY_("syntax error, unexpected %s, expecting %s or %s or %s"); + YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"); +# endif + char *yyfmt; + char const *yyf; + static char const yyunexpected[] = "syntax error, unexpected %s"; + static char const yyexpecting[] = ", expecting %s"; + static char const yyor[] = " or %s"; + char yyformat[sizeof yyunexpected + + sizeof yyexpecting - 1 + + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2) + * (sizeof yyor - 1))]; + char const *yyprefix = yyexpecting; + + /* Start YYX at -YYN if negative to avoid negative indexes in + YYCHECK. */ + int yyxbegin = yyn < 0 ? -yyn : 0; + + /* Stay within bounds of both yycheck and yytname. */ + int yychecklim = YYLAST - yyn + 1; + int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; + int yycount = 1; + + yyarg[0] = yytname[yytype]; + yyfmt = yystpcpy (yyformat, yyunexpected); + + for (yyx = yyxbegin; yyx < yyxend; ++yyx) + if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) + { + if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) + { + yycount = 1; + yysize = yysize0; + yyformat[sizeof yyunexpected - 1] = '\0'; + break; + } + yyarg[yycount++] = yytname[yyx]; + yysize1 = yysize + yytnamerr (0, yytname[yyx]); + yysize_overflow |= (yysize1 < yysize); + yysize = yysize1; + yyfmt = yystpcpy (yyfmt, yyprefix); + yyprefix = yyor; + } + + yyf = YY_(yyformat); + yysize1 = yysize + yystrlen (yyf); + yysize_overflow |= (yysize1 < yysize); + yysize = yysize1; + + if (yysize_overflow) + return YYSIZE_MAXIMUM; + + if (yyresult) + { + /* Avoid sprintf, as that infringes on the user's name space. + Don't have undefined behavior even if the translation + produced a string with the wrong number of "%s"s. */ + char *yyp = yyresult; + int yyi = 0; + while ((*yyp = *yyf) != '\0') + { + if (*yyp == '%' && yyf[1] == 's' && yyi < yycount) + { + yyp += yytnamerr (yyp, yyarg[yyi++]); + yyf += 2; + } + else + { + yyp++; + yyf++; + } + } + } + return yysize; + } +} +#endif /* YYERROR_VERBOSE */ + + +/*-----------------------------------------------. +| Release the memory associated to this symbol. | +`-----------------------------------------------*/ + +/*ARGSUSED*/ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep) +#else +static void +yydestruct (yymsg, yytype, yyvaluep) + const char *yymsg; + int yytype; + YYSTYPE *yyvaluep; +#endif +{ + YYUSE (yyvaluep); + + if (!yymsg) + yymsg = "Deleting"; + YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); + + switch (yytype) + { + case 53: /* "choice_entry" */ + + { + fprintf(stderr, "%s:%d: missing end statement for this entry\n", + (yyvaluep->menu)->file->name, (yyvaluep->menu)->lineno); + if (current_menu == (yyvaluep->menu)) + menu_end_menu(); +}; + + break; + case 59: /* "if_entry" */ + + { + fprintf(stderr, "%s:%d: missing end statement for this entry\n", + (yyvaluep->menu)->file->name, (yyvaluep->menu)->lineno); + if (current_menu == (yyvaluep->menu)) + menu_end_menu(); +}; + + break; + case 65: /* "menu_entry" */ + + { + fprintf(stderr, "%s:%d: missing end statement for this entry\n", + (yyvaluep->menu)->file->name, (yyvaluep->menu)->lineno); + if (current_menu == (yyvaluep->menu)) + menu_end_menu(); +}; + + break; + + default: + break; + } +} + +/* Prevent warnings from -Wmissing-prototypes. */ +#ifdef YYPARSE_PARAM +#if defined __STDC__ || defined __cplusplus +int yyparse (void *YYPARSE_PARAM); +#else +int yyparse (); +#endif +#else /* ! YYPARSE_PARAM */ +#if defined __STDC__ || defined __cplusplus +int yyparse (void); +#else +int yyparse (); +#endif +#endif /* ! YYPARSE_PARAM */ + + +/* The lookahead symbol. */ +int yychar; + +/* The semantic value of the lookahead symbol. */ +YYSTYPE yylval; + +/* Number of syntax errors so far. */ +int yynerrs; + + + +/*-------------------------. +| yyparse or yypush_parse. | +`-------------------------*/ + +#ifdef YYPARSE_PARAM +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +int +yyparse (void *YYPARSE_PARAM) +#else +int +yyparse (YYPARSE_PARAM) + void *YYPARSE_PARAM; +#endif +#else /* ! YYPARSE_PARAM */ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +int +yyparse (void) +#else +int +yyparse () + +#endif +#endif +{ + + + int yystate; + /* Number of tokens to shift before error messages enabled. */ + int yyerrstatus; + + /* The stacks and their tools: + `yyss': related to states. + `yyvs': related to semantic values. + + Refer to the stacks thru separate pointers, to allow yyoverflow + to reallocate them elsewhere. */ + + /* The state stack. */ + yytype_int16 yyssa[YYINITDEPTH]; + yytype_int16 *yyss; + yytype_int16 *yyssp; + + /* The semantic value stack. */ + YYSTYPE yyvsa[YYINITDEPTH]; + YYSTYPE *yyvs; + YYSTYPE *yyvsp; + + YYSIZE_T yystacksize; + + int yyn; + int yyresult; + /* Lookahead token as an internal (translated) token number. */ + int yytoken; + /* The variables used to return semantic value and location from the + action routines. */ + YYSTYPE yyval; + +#if YYERROR_VERBOSE + /* Buffer for error messages, and its allocated size. */ + char yymsgbuf[128]; + char *yymsg = yymsgbuf; + YYSIZE_T yymsg_alloc = sizeof yymsgbuf; +#endif + +#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N)) + + /* The number of symbols on the RHS of the reduced rule. + Keep to zero when no symbol should be popped. */ + int yylen = 0; + + yytoken = 0; + yyss = yyssa; + yyvs = yyvsa; + yystacksize = YYINITDEPTH; + + YYDPRINTF ((stderr, "Starting parse\n")); + + yystate = 0; + yyerrstatus = 0; + yynerrs = 0; + yychar = YYEMPTY; /* Cause a token to be read. */ + + /* Initialize stack pointers. + Waste one element of value and location stack + so that they stay on the same level as the state stack. + The wasted elements are never initialized. */ + yyssp = yyss; + yyvsp = yyvs; + + goto yysetstate; + +/*------------------------------------------------------------. +| yynewstate -- Push a new state, which is found in yystate. | +`------------------------------------------------------------*/ + yynewstate: + /* In all cases, when you get here, the value and location stacks + have just been pushed. So pushing a state here evens the stacks. */ + yyssp++; + + yysetstate: + *yyssp = yystate; + + if (yyss + yystacksize - 1 <= yyssp) + { + /* Get the current used size of the three stacks, in elements. */ + YYSIZE_T yysize = yyssp - yyss + 1; + +#ifdef yyoverflow + { + /* Give user a chance to reallocate the stack. Use copies of + these so that the &'s don't force the real ones into + memory. */ + YYSTYPE *yyvs1 = yyvs; + yytype_int16 *yyss1 = yyss; + + /* Each stack pointer address is followed by the size of the + data in use in that stack, in bytes. This used to be a + conditional around just the two extra args, but that might + be undefined if yyoverflow is a macro. */ + yyoverflow (YY_("memory exhausted"), + &yyss1, yysize * sizeof (*yyssp), + &yyvs1, yysize * sizeof (*yyvsp), + &yystacksize); + + yyss = yyss1; + yyvs = yyvs1; + } +#else /* no yyoverflow */ +# ifndef YYSTACK_RELOCATE + goto yyexhaustedlab; +# else + /* Extend the stack our own way. */ + if (YYMAXDEPTH <= yystacksize) + goto yyexhaustedlab; + yystacksize *= 2; + if (YYMAXDEPTH < yystacksize) + yystacksize = YYMAXDEPTH; + + { + yytype_int16 *yyss1 = yyss; + union yyalloc *yyptr = + (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); + if (! yyptr) + goto yyexhaustedlab; + YYSTACK_RELOCATE (yyss_alloc, yyss); + YYSTACK_RELOCATE (yyvs_alloc, yyvs); +# undef YYSTACK_RELOCATE + if (yyss1 != yyssa) + YYSTACK_FREE (yyss1); + } +# endif +#endif /* no yyoverflow */ + + yyssp = yyss + yysize - 1; + yyvsp = yyvs + yysize - 1; + + YYDPRINTF ((stderr, "Stack size increased to %lu\n", + (unsigned long int) yystacksize)); + + if (yyss + yystacksize - 1 <= yyssp) + YYABORT; + } + + YYDPRINTF ((stderr, "Entering state %d\n", yystate)); + + if (yystate == YYFINAL) + YYACCEPT; + + goto yybackup; + +/*-----------. +| yybackup. | +`-----------*/ +yybackup: + + /* Do appropriate processing given the current state. Read a + lookahead token if we need one and don't already have one. */ + + /* First try to decide what to do without reference to lookahead token. */ + yyn = yypact[yystate]; + if (yyn == YYPACT_NINF) + goto yydefault; + + /* Not known => get a lookahead token if don't already have one. */ + + /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */ + if (yychar == YYEMPTY) + { + YYDPRINTF ((stderr, "Reading a token: ")); + yychar = YYLEX; + } + + if (yychar <= YYEOF) + { + yychar = yytoken = YYEOF; + YYDPRINTF ((stderr, "Now at end of input.\n")); + } + else + { + yytoken = YYTRANSLATE (yychar); + YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); + } + + /* If the proper action on seeing token YYTOKEN is to reduce or to + detect an error, take that action. */ + yyn += yytoken; + if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) + goto yydefault; + yyn = yytable[yyn]; + if (yyn <= 0) + { + if (yyn == 0 || yyn == YYTABLE_NINF) + goto yyerrlab; + yyn = -yyn; + goto yyreduce; + } + + /* Count tokens shifted since error; after three, turn off error + status. */ + if (yyerrstatus) + yyerrstatus--; + + /* Shift the lookahead token. */ + YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); + + /* Discard the shifted token. */ + yychar = YYEMPTY; + + yystate = yyn; + *++yyvsp = yylval; + + goto yynewstate; + + +/*-----------------------------------------------------------. +| yydefault -- do the default action for the current state. | +`-----------------------------------------------------------*/ +yydefault: + yyn = yydefact[yystate]; + if (yyn == 0) + goto yyerrlab; + goto yyreduce; + + +/*-----------------------------. +| yyreduce -- Do a reduction. | +`-----------------------------*/ +yyreduce: + /* yyn is the number of a rule to reduce with. */ + yylen = yyr2[yyn]; + + /* If YYLEN is nonzero, implement the default value of the action: + `$$ = $1'. + + Otherwise, the following line sets YYVAL to garbage. + This behavior is undocumented and Bison + users should not rely upon it. Assigning to YYVAL + unconditionally makes the parser a bit smaller, and it avoids a + GCC warning that YYVAL may be used uninitialized. */ + yyval = yyvsp[1-yylen]; + + + YY_REDUCE_PRINT (yyn); + switch (yyn) + { + case 10: + + { zconf_error("unexpected end statement"); ;} + break; + + case 11: + + { zconf_error("unknown statement \"%s\"", (yyvsp[(2) - (4)].string)); ;} + break; + + case 12: + + { + zconf_error("unexpected option \"%s\"", kconf_id_strings + (yyvsp[(2) - (4)].id)->name); +;} + break; + + case 13: + + { zconf_error("invalid statement"); ;} + break; + + case 28: + + { zconf_error("unknown option \"%s\"", (yyvsp[(1) - (3)].string)); ;} + break; + + case 29: + + { zconf_error("invalid option"); ;} + break; + + case 30: + + { + struct symbol *sym = sym_lookup((yyvsp[(2) - (3)].string), 0); + sym->flags |= SYMBOL_OPTIONAL; + menu_add_entry(sym); + printd(DEBUG_PARSE, "%s:%d:config %s\n", zconf_curname(), zconf_lineno(), (yyvsp[(2) - (3)].string)); +;} + break; + + case 31: + + { + menu_end_entry(); + printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno()); +;} + break; + + case 32: + + { + struct symbol *sym = sym_lookup((yyvsp[(2) - (3)].string), 0); + sym->flags |= SYMBOL_OPTIONAL; + menu_add_entry(sym); + printd(DEBUG_PARSE, "%s:%d:menuconfig %s\n", zconf_curname(), zconf_lineno(), (yyvsp[(2) - (3)].string)); +;} + break; + + case 33: + + { + if (current_entry->prompt) + current_entry->prompt->type = P_MENU; + else + zconfprint("warning: menuconfig statement without prompt"); + menu_end_entry(); + printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno()); +;} + break; + + case 41: + + { + menu_set_type((yyvsp[(1) - (3)].id)->stype); + printd(DEBUG_PARSE, "%s:%d:type(%u)\n", + zconf_curname(), zconf_lineno(), + (yyvsp[(1) - (3)].id)->stype); +;} + break; + + case 42: + + { + menu_add_prompt(P_PROMPT, (yyvsp[(2) - (4)].string), (yyvsp[(3) - (4)].expr)); + printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno()); +;} + break; + + case 43: + + { + menu_add_expr(P_DEFAULT, (yyvsp[(2) - (4)].expr), (yyvsp[(3) - (4)].expr)); + if ((yyvsp[(1) - (4)].id)->stype != S_UNKNOWN) + menu_set_type((yyvsp[(1) - (4)].id)->stype); + printd(DEBUG_PARSE, "%s:%d:default(%u)\n", + zconf_curname(), zconf_lineno(), + (yyvsp[(1) - (4)].id)->stype); +;} + break; + + case 44: + + { + menu_add_symbol(P_SELECT, sym_lookup((yyvsp[(2) - (4)].string), 0), (yyvsp[(3) - (4)].expr)); + printd(DEBUG_PARSE, "%s:%d:select\n", zconf_curname(), zconf_lineno()); +;} + break; + + case 45: + + { + menu_add_expr(P_RANGE, expr_alloc_comp(E_RANGE,(yyvsp[(2) - (5)].symbol), (yyvsp[(3) - (5)].symbol)), (yyvsp[(4) - (5)].expr)); + printd(DEBUG_PARSE, "%s:%d:range\n", zconf_curname(), zconf_lineno()); +;} + break; + + case 48: + + { + const struct kconf_id *id = kconf_id_lookup((yyvsp[(2) - (3)].string), strlen((yyvsp[(2) - (3)].string))); + if (id && id->flags & TF_OPTION) + menu_add_option(id->token, (yyvsp[(3) - (3)].string)); + else + zconfprint("warning: ignoring unknown option %s", (yyvsp[(2) - (3)].string)); + free((yyvsp[(2) - (3)].string)); +;} + break; + + case 49: + + { (yyval.string) = NULL; ;} + break; + + case 50: + + { (yyval.string) = (yyvsp[(2) - (2)].string); ;} + break; + + case 51: + + { + struct symbol *sym = sym_lookup((yyvsp[(2) - (3)].string), SYMBOL_CHOICE); + sym->flags |= SYMBOL_AUTO; + menu_add_entry(sym); + menu_add_expr(P_CHOICE, NULL, NULL); + printd(DEBUG_PARSE, "%s:%d:choice\n", zconf_curname(), zconf_lineno()); +;} + break; + + case 52: + + { + (yyval.menu) = menu_add_menu(); +;} + break; + + case 53: + + { + if (zconf_endtoken((yyvsp[(1) - (1)].id), T_CHOICE, T_ENDCHOICE)) { + menu_end_menu(); + printd(DEBUG_PARSE, "%s:%d:endchoice\n", zconf_curname(), zconf_lineno()); + } +;} + break; + + case 61: + + { + menu_add_prompt(P_PROMPT, (yyvsp[(2) - (4)].string), (yyvsp[(3) - (4)].expr)); + printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno()); +;} + break; + + case 62: + + { + if ((yyvsp[(1) - (3)].id)->stype == S_BOOLEAN || (yyvsp[(1) - (3)].id)->stype == S_TRISTATE) { + menu_set_type((yyvsp[(1) - (3)].id)->stype); + printd(DEBUG_PARSE, "%s:%d:type(%u)\n", + zconf_curname(), zconf_lineno(), + (yyvsp[(1) - (3)].id)->stype); + } else + YYERROR; +;} + break; + + case 63: + + { + current_entry->sym->flags |= SYMBOL_OPTIONAL; + printd(DEBUG_PARSE, "%s:%d:optional\n", zconf_curname(), zconf_lineno()); +;} + break; + + case 64: + + { + if ((yyvsp[(1) - (4)].id)->stype == S_UNKNOWN) { + menu_add_symbol(P_DEFAULT, sym_lookup((yyvsp[(2) - (4)].string), 0), (yyvsp[(3) - (4)].expr)); + printd(DEBUG_PARSE, "%s:%d:default\n", + zconf_curname(), zconf_lineno()); + } else + YYERROR; +;} + break; + + case 67: + + { + printd(DEBUG_PARSE, "%s:%d:if\n", zconf_curname(), zconf_lineno()); + menu_add_entry(NULL); + menu_add_dep((yyvsp[(2) - (3)].expr)); + (yyval.menu) = menu_add_menu(); +;} + break; + + case 68: + + { + if (zconf_endtoken((yyvsp[(1) - (1)].id), T_IF, T_ENDIF)) { + menu_end_menu(); + printd(DEBUG_PARSE, "%s:%d:endif\n", zconf_curname(), zconf_lineno()); + } +;} + break; + + case 74: + + { + menu_add_prompt(P_MENU, (yyvsp[(2) - (3)].string), NULL); +;} + break; + + case 75: + + { + menu_add_entry(NULL); + menu_add_prompt(P_MENU, (yyvsp[(2) - (3)].string), NULL); + printd(DEBUG_PARSE, "%s:%d:menu\n", zconf_curname(), zconf_lineno()); +;} + break; + + case 76: + + { + (yyval.menu) = menu_add_menu(); +;} + break; + + case 77: + + { + if (zconf_endtoken((yyvsp[(1) - (1)].id), T_MENU, T_ENDMENU)) { + menu_end_menu(); + printd(DEBUG_PARSE, "%s:%d:endmenu\n", zconf_curname(), zconf_lineno()); + } +;} + break; + + case 83: + + { + printd(DEBUG_PARSE, "%s:%d:source %s\n", zconf_curname(), zconf_lineno(), (yyvsp[(2) - (3)].string)); + zconf_nextfile((yyvsp[(2) - (3)].string)); +;} + break; + + case 84: + + { + menu_add_entry(NULL); + menu_add_prompt(P_COMMENT, (yyvsp[(2) - (3)].string), NULL); + printd(DEBUG_PARSE, "%s:%d:comment\n", zconf_curname(), zconf_lineno()); +;} + break; + + case 85: + + { + menu_end_entry(); +;} + break; + + case 86: + + { + printd(DEBUG_PARSE, "%s:%d:help\n", zconf_curname(), zconf_lineno()); + zconf_starthelp(); +;} + break; + + case 87: + + { + current_entry->help = (yyvsp[(2) - (2)].string); +;} + break; + + case 92: + + { + menu_add_dep((yyvsp[(3) - (4)].expr)); + printd(DEBUG_PARSE, "%s:%d:depends on\n", zconf_curname(), zconf_lineno()); +;} + break; + + case 96: + + { + menu_add_visibility((yyvsp[(2) - (2)].expr)); +;} + break; + + case 98: + + { + menu_add_prompt(P_PROMPT, (yyvsp[(1) - (2)].string), (yyvsp[(2) - (2)].expr)); +;} + break; + + case 101: + + { (yyval.id) = (yyvsp[(1) - (2)].id); ;} + break; + + case 102: + + { (yyval.id) = (yyvsp[(1) - (2)].id); ;} + break; + + case 103: + + { (yyval.id) = (yyvsp[(1) - (2)].id); ;} + break; + + case 106: + + { (yyval.expr) = NULL; ;} + break; + + case 107: + + { (yyval.expr) = (yyvsp[(2) - (2)].expr); ;} + break; + + case 108: + + { (yyval.expr) = expr_alloc_symbol((yyvsp[(1) - (1)].symbol)); ;} + break; + + case 109: + + { (yyval.expr) = expr_alloc_comp(E_EQUAL, (yyvsp[(1) - (3)].symbol), (yyvsp[(3) - (3)].symbol)); ;} + break; + + case 110: + + { (yyval.expr) = expr_alloc_comp(E_UNEQUAL, (yyvsp[(1) - (3)].symbol), (yyvsp[(3) - (3)].symbol)); ;} + break; + + case 111: + + { (yyval.expr) = (yyvsp[(2) - (3)].expr); ;} + break; + + case 112: + + { (yyval.expr) = expr_alloc_one(E_NOT, (yyvsp[(2) - (2)].expr)); ;} + break; + + case 113: + + { (yyval.expr) = expr_alloc_two(E_OR, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;} + break; + + case 114: + + { (yyval.expr) = expr_alloc_two(E_AND, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;} + break; + + case 115: + + { (yyval.symbol) = sym_lookup((yyvsp[(1) - (1)].string), 0); free((yyvsp[(1) - (1)].string)); ;} + break; + + case 116: + + { (yyval.symbol) = sym_lookup((yyvsp[(1) - (1)].string), SYMBOL_CONST); free((yyvsp[(1) - (1)].string)); ;} + break; + + case 117: + + { (yyval.string) = NULL; ;} + break; + + + + default: break; + } + YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); + + YYPOPSTACK (yylen); + yylen = 0; + YY_STACK_PRINT (yyss, yyssp); + + *++yyvsp = yyval; + + /* Now `shift' the result of the reduction. Determine what state + that goes to, based on the state we popped back to and the rule + number reduced by. */ + + yyn = yyr1[yyn]; + + yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; + if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) + yystate = yytable[yystate]; + else + yystate = yydefgoto[yyn - YYNTOKENS]; + + goto yynewstate; + + +/*------------------------------------. +| yyerrlab -- here on detecting error | +`------------------------------------*/ +yyerrlab: + /* If not already recovering from an error, report this error. */ + if (!yyerrstatus) + { + ++yynerrs; +#if ! YYERROR_VERBOSE + yyerror (YY_("syntax error")); +#else + { + YYSIZE_T yysize = yysyntax_error (0, yystate, yychar); + if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM) + { + YYSIZE_T yyalloc = 2 * yysize; + if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM)) + yyalloc = YYSTACK_ALLOC_MAXIMUM; + if (yymsg != yymsgbuf) + YYSTACK_FREE (yymsg); + yymsg = (char *) YYSTACK_ALLOC (yyalloc); + if (yymsg) + yymsg_alloc = yyalloc; + else + { + yymsg = yymsgbuf; + yymsg_alloc = sizeof yymsgbuf; + } + } + + if (0 < yysize && yysize <= yymsg_alloc) + { + (void) yysyntax_error (yymsg, yystate, yychar); + yyerror (yymsg); + } + else + { + yyerror (YY_("syntax error")); + if (yysize != 0) + goto yyexhaustedlab; + } + } +#endif + } + + + + if (yyerrstatus == 3) + { + /* If just tried and failed to reuse lookahead token after an + error, discard it. */ + + if (yychar <= YYEOF) + { + /* Return failure if at end of input. */ + if (yychar == YYEOF) + YYABORT; + } + else + { + yydestruct ("Error: discarding", + yytoken, &yylval); + yychar = YYEMPTY; + } + } + + /* Else will try to reuse lookahead token after shifting the error + token. */ + goto yyerrlab1; + + +/*---------------------------------------------------. +| yyerrorlab -- error raised explicitly by YYERROR. | +`---------------------------------------------------*/ +yyerrorlab: + + /* Pacify compilers like GCC when the user code never invokes + YYERROR and the label yyerrorlab therefore never appears in user + code. */ + if (/*CONSTCOND*/ 0) + goto yyerrorlab; + + /* Do not reclaim the symbols of the rule which action triggered + this YYERROR. */ + YYPOPSTACK (yylen); + yylen = 0; + YY_STACK_PRINT (yyss, yyssp); + yystate = *yyssp; + goto yyerrlab1; + + +/*-------------------------------------------------------------. +| yyerrlab1 -- common code for both syntax error and YYERROR. | +`-------------------------------------------------------------*/ +yyerrlab1: + yyerrstatus = 3; /* Each real token shifted decrements this. */ + + for (;;) + { + yyn = yypact[yystate]; + if (yyn != YYPACT_NINF) + { + yyn += YYTERROR; + if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) + { + yyn = yytable[yyn]; + if (0 < yyn) + break; + } + } + + /* Pop the current state because it cannot handle the error token. */ + if (yyssp == yyss) + YYABORT; + + + yydestruct ("Error: popping", + yystos[yystate], yyvsp); + YYPOPSTACK (1); + yystate = *yyssp; + YY_STACK_PRINT (yyss, yyssp); + } + + *++yyvsp = yylval; + + + /* Shift the error token. */ + YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp); + + yystate = yyn; + goto yynewstate; + + +/*-------------------------------------. +| yyacceptlab -- YYACCEPT comes here. | +`-------------------------------------*/ +yyacceptlab: + yyresult = 0; + goto yyreturn; + +/*-----------------------------------. +| yyabortlab -- YYABORT comes here. | +`-----------------------------------*/ +yyabortlab: + yyresult = 1; + goto yyreturn; + +#if !defined(yyoverflow) || YYERROR_VERBOSE +/*-------------------------------------------------. +| yyexhaustedlab -- memory exhaustion comes here. | +`-------------------------------------------------*/ +yyexhaustedlab: + yyerror (YY_("memory exhausted")); + yyresult = 2; + /* Fall through. */ +#endif + +yyreturn: + if (yychar != YYEMPTY) + yydestruct ("Cleanup: discarding lookahead", + yytoken, &yylval); + /* Do not reclaim the symbols of the rule which action triggered + this YYABORT or YYACCEPT. */ + YYPOPSTACK (yylen); + YY_STACK_PRINT (yyss, yyssp); + while (yyssp != yyss) + { + yydestruct ("Cleanup: popping", + yystos[*yyssp], yyvsp); + YYPOPSTACK (1); + } +#ifndef yyoverflow + if (yyss != yyssa) + YYSTACK_FREE (yyss); +#endif +#if YYERROR_VERBOSE + if (yymsg != yymsgbuf) + YYSTACK_FREE (yymsg); +#endif + /* Make sure YYID is used. */ + return YYID (yyresult); +} + + + + + +void conf_parse(const char *name) +{ + struct symbol *sym; + int i; + + zconf_initscan(name); + + sym_init(); + _menu_init(); + modules_sym = sym_lookup(NULL, 0); + modules_sym->type = S_BOOLEAN; + modules_sym->flags |= SYMBOL_AUTO; + rootmenu.prompt = menu_add_prompt(P_MENU, "L4Re Configuration", NULL); + + if (getenv("ZCONF_DEBUG")) + zconfdebug = 1; + zconfparse(); + if (zconfnerrs) + exit(1); + if (!modules_sym->prop) { + struct property *prop; + + prop = prop_alloc(P_DEFAULT, modules_sym); + prop->expr = expr_alloc_symbol(sym_lookup("MODULES", 0)); + } + + rootmenu.prompt->text = _(rootmenu.prompt->text); + rootmenu.prompt->text = sym_expand_string_value(rootmenu.prompt->text); + + menu_finalize(&rootmenu); + for_all_symbols(i, sym) { + if (sym_check_deps(sym)) + zconfnerrs++; + } + if (zconfnerrs) + exit(1); + sym_set_change_count(1); +} + +static const char *zconf_tokenname(int token) +{ + switch (token) { + case T_MENU: return "menu"; + case T_ENDMENU: return "endmenu"; + case T_CHOICE: return "choice"; + case T_ENDCHOICE: return "endchoice"; + case T_IF: return "if"; + case T_ENDIF: return "endif"; + case T_DEPENDS: return "depends"; + case T_VISIBLE: return "visible"; + } + return ""; +} + +static bool zconf_endtoken(const struct kconf_id *id, int starttoken, int endtoken) +{ + if (id->token != endtoken) { + zconf_error("unexpected '%s' within %s block", + kconf_id_strings + id->name, zconf_tokenname(starttoken)); + zconfnerrs++; + return false; + } + if (current_menu->file != current_file) { + zconf_error("'%s' in different file than '%s'", + kconf_id_strings + id->name, zconf_tokenname(starttoken)); + fprintf(stderr, "%s:%d: location of the '%s'\n", + current_menu->file->name, current_menu->lineno, + zconf_tokenname(starttoken)); + zconfnerrs++; + return false; + } + return true; +} + +static void zconfprint(const char *err, ...) +{ + va_list ap; + + fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno()); + va_start(ap, err); + vfprintf(stderr, err, ap); + va_end(ap); + fprintf(stderr, "\n"); +} + +static void zconf_error(const char *err, ...) +{ + va_list ap; + + zconfnerrs++; + fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno()); + va_start(ap, err); + vfprintf(stderr, err, ap); + va_end(ap); + fprintf(stderr, "\n"); +} + +static void zconferror(const char *err) +{ + fprintf(stderr, "%s:%d: %s\n", zconf_curname(), zconf_lineno() + 1, err); +} + +static void print_quoted_string(FILE *out, const char *str) +{ + const char *p; + int len; + + putc('"', out); + while ((p = strchr(str, '"'))) { + len = p - str; + if (len) + fprintf(out, "%.*s", len, str); + fputs("\\\"", out); + str = p + 1; + } + fputs(str, out); + putc('"', out); +} + +static void print_symbol(FILE *out, struct menu *menu) +{ + struct symbol *sym = menu->sym; + struct property *prop; + + if (sym_is_choice(sym)) + fprintf(out, "\nchoice\n"); + else + fprintf(out, "\nconfig %s\n", sym->name); + switch (sym->type) { + case S_BOOLEAN: + fputs(" boolean\n", out); + break; + case S_TRISTATE: + fputs(" tristate\n", out); + break; + case S_STRING: + fputs(" string\n", out); + break; + case S_INT: + fputs(" integer\n", out); + break; + case S_HEX: + fputs(" hex\n", out); + break; + default: + fputs(" ???\n", out); + break; + } + for (prop = sym->prop; prop; prop = prop->next) { + if (prop->menu != menu) + continue; + switch (prop->type) { + case P_PROMPT: + fputs(" prompt ", out); + print_quoted_string(out, prop->text); + if (!expr_is_yes(prop->visible.expr)) { + fputs(" if ", out); + expr_fprint(prop->visible.expr, out); + } + fputc('\n', out); + break; + case P_DEFAULT: + fputs( " default ", out); + expr_fprint(prop->expr, out); + if (!expr_is_yes(prop->visible.expr)) { + fputs(" if ", out); + expr_fprint(prop->visible.expr, out); + } + fputc('\n', out); + break; + case P_CHOICE: + fputs(" #choice value\n", out); + break; + case P_SELECT: + fputs( " select ", out); + expr_fprint(prop->expr, out); + fputc('\n', out); + break; + case P_RANGE: + fputs( " range ", out); + expr_fprint(prop->expr, out); + fputc('\n', out); + break; + case P_MENU: + fputs( " menu ", out); + print_quoted_string(out, prop->text); + fputc('\n', out); + break; + default: + fprintf(out, " unknown prop %d!\n", prop->type); + break; + } + } + if (menu->help) { + int len = strlen(menu->help); + while (menu->help[--len] == '\n') + menu->help[len] = 0; + fprintf(out, " help\n%s\n", menu->help); + } +} + +void zconfdump(FILE *out) +{ + struct property *prop; + struct symbol *sym; + struct menu *menu; + + menu = rootmenu.list; + while (menu) { + if ((sym = menu->sym)) + print_symbol(out, menu); + else if ((prop = menu->prompt)) { + switch (prop->type) { + case P_COMMENT: + fputs("\ncomment ", out); + print_quoted_string(out, prop->text); + fputs("\n", out); + break; + case P_MENU: + fputs("\nmenu ", out); + print_quoted_string(out, prop->text); + fputs("\n", out); + break; + default: + ; + } + if (!expr_is_yes(prop->visible.expr)) { + fputs(" depends ", out); + expr_fprint(prop->visible.expr, out); + fputc('\n', out); + } + } + + if (menu->list) + menu = menu->list; + else if (menu->next) + menu = menu->next; + else while ((menu = menu->parent)) { + if (menu->prompt && menu->prompt->type == P_MENU) + fputs("\nendmenu\n", out); + if (menu->next) { + menu = menu->next; + break; + } + } + } +} + +#include "zconf.lex.c" +#include "util.c" +#include "confdata.c" +#include "expr.c" +#include "symbol.c" +#include "menu.c" + diff --git a/l4/tool/kconfig/scripts/kconfig/zconf.y b/l4/tool/kconfig/scripts/kconfig/zconf.y new file mode 100644 index 00000000..864da07b --- /dev/null +++ b/l4/tool/kconfig/scripts/kconfig/zconf.y @@ -0,0 +1,740 @@ +%{ +/* + * Copyright (C) 2002 Roman Zippel + * Released under the terms of the GNU GPL v2.0. + */ + +#include +#include +#include +#include +#include +#include + +#include "lkc.h" + +#define printd(mask, fmt...) if (cdebug & (mask)) printf(fmt) + +#define PRINTD 0x0001 +#define DEBUG_PARSE 0x0002 + +int cdebug = PRINTD; + +extern int zconflex(void); +static void zconfprint(const char *err, ...); +static void zconf_error(const char *err, ...); +static void zconferror(const char *err); +static bool zconf_endtoken(const struct kconf_id *id, int starttoken, int endtoken); + +struct symbol *symbol_hash[SYMBOL_HASHSIZE]; + +static struct menu *current_menu, *current_entry; + +%} +%expect 30 + +%union +{ + char *string; + struct file *file; + struct symbol *symbol; + struct expr *expr; + struct menu *menu; + const struct kconf_id *id; +} + +%token T_MAINMENU +%token T_MENU +%token T_ENDMENU +%token T_SOURCE +%token T_CHOICE +%token T_ENDCHOICE +%token T_COMMENT +%token T_CONFIG +%token T_MENUCONFIG +%token T_HELP +%token T_HELPTEXT +%token T_IF +%token T_ENDIF +%token T_DEPENDS +%token T_OPTIONAL +%token T_PROMPT +%token T_TYPE +%token T_DEFAULT +%token T_SELECT +%token T_RANGE +%token T_VISIBLE +%token T_OPTION +%token T_ON +%token T_WORD +%token T_WORD_QUOTE +%token T_UNEQUAL +%token T_CLOSE_PAREN +%token T_OPEN_PAREN +%token T_EOL + +%left T_OR +%left T_AND +%left T_EQUAL T_UNEQUAL +%nonassoc T_NOT + +%type prompt +%type symbol +%type expr +%type if_expr +%type end +%type option_name +%type if_entry menu_entry choice_entry +%type symbol_option_arg word_opt + +%destructor { + fprintf(stderr, "%s:%d: missing end statement for this entry\n", + $$->file->name, $$->lineno); + if (current_menu == $$) + menu_end_menu(); +} if_entry menu_entry choice_entry + +%{ +/* Include zconf.hash.c here so it can see the token constants. */ +#include "zconf.hash.c" +%} + +%% +input: nl start | start; + +start: mainmenu_stmt stmt_list | stmt_list; + +stmt_list: + /* empty */ + | stmt_list common_stmt + | stmt_list choice_stmt + | stmt_list menu_stmt + | stmt_list end { zconf_error("unexpected end statement"); } + | stmt_list T_WORD error T_EOL { zconf_error("unknown statement \"%s\"", $2); } + | stmt_list option_name error T_EOL +{ + zconf_error("unexpected option \"%s\"", kconf_id_strings + $2->name); +} + | stmt_list error T_EOL { zconf_error("invalid statement"); } +; + +option_name: + T_DEPENDS | T_PROMPT | T_TYPE | T_SELECT | T_OPTIONAL | T_RANGE | T_DEFAULT | T_VISIBLE +; + +common_stmt: + T_EOL + | if_stmt + | comment_stmt + | config_stmt + | menuconfig_stmt + | source_stmt +; + +option_error: + T_WORD error T_EOL { zconf_error("unknown option \"%s\"", $1); } + | error T_EOL { zconf_error("invalid option"); } +; + + +/* config/menuconfig entry */ + +config_entry_start: T_CONFIG T_WORD T_EOL +{ + struct symbol *sym = sym_lookup($2, 0); + sym->flags |= SYMBOL_OPTIONAL; + menu_add_entry(sym); + printd(DEBUG_PARSE, "%s:%d:config %s\n", zconf_curname(), zconf_lineno(), $2); +}; + +config_stmt: config_entry_start config_option_list +{ + menu_end_entry(); + printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno()); +}; + +menuconfig_entry_start: T_MENUCONFIG T_WORD T_EOL +{ + struct symbol *sym = sym_lookup($2, 0); + sym->flags |= SYMBOL_OPTIONAL; + menu_add_entry(sym); + printd(DEBUG_PARSE, "%s:%d:menuconfig %s\n", zconf_curname(), zconf_lineno(), $2); +}; + +menuconfig_stmt: menuconfig_entry_start config_option_list +{ + if (current_entry->prompt) + current_entry->prompt->type = P_MENU; + else + zconfprint("warning: menuconfig statement without prompt"); + menu_end_entry(); + printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno()); +}; + +config_option_list: + /* empty */ + | config_option_list config_option + | config_option_list symbol_option + | config_option_list depends + | config_option_list help + | config_option_list option_error + | config_option_list T_EOL +; + +config_option: T_TYPE prompt_stmt_opt T_EOL +{ + menu_set_type($1->stype); + printd(DEBUG_PARSE, "%s:%d:type(%u)\n", + zconf_curname(), zconf_lineno(), + $1->stype); +}; + +config_option: T_PROMPT prompt if_expr T_EOL +{ + menu_add_prompt(P_PROMPT, $2, $3); + printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno()); +}; + +config_option: T_DEFAULT expr if_expr T_EOL +{ + menu_add_expr(P_DEFAULT, $2, $3); + if ($1->stype != S_UNKNOWN) + menu_set_type($1->stype); + printd(DEBUG_PARSE, "%s:%d:default(%u)\n", + zconf_curname(), zconf_lineno(), + $1->stype); +}; + +config_option: T_SELECT T_WORD if_expr T_EOL +{ + menu_add_symbol(P_SELECT, sym_lookup($2, 0), $3); + printd(DEBUG_PARSE, "%s:%d:select\n", zconf_curname(), zconf_lineno()); +}; + +config_option: T_RANGE symbol symbol if_expr T_EOL +{ + menu_add_expr(P_RANGE, expr_alloc_comp(E_RANGE,$2, $3), $4); + printd(DEBUG_PARSE, "%s:%d:range\n", zconf_curname(), zconf_lineno()); +}; + +symbol_option: T_OPTION symbol_option_list T_EOL +; + +symbol_option_list: + /* empty */ + | symbol_option_list T_WORD symbol_option_arg +{ + const struct kconf_id *id = kconf_id_lookup($2, strlen($2)); + if (id && id->flags & TF_OPTION) + menu_add_option(id->token, $3); + else + zconfprint("warning: ignoring unknown option %s", $2); + free($2); +}; + +symbol_option_arg: + /* empty */ { $$ = NULL; } + | T_EQUAL prompt { $$ = $2; } +; + +/* choice entry */ + +choice: T_CHOICE word_opt T_EOL +{ + struct symbol *sym = sym_lookup($2, SYMBOL_CHOICE); + sym->flags |= SYMBOL_AUTO; + menu_add_entry(sym); + menu_add_expr(P_CHOICE, NULL, NULL); + printd(DEBUG_PARSE, "%s:%d:choice\n", zconf_curname(), zconf_lineno()); +}; + +choice_entry: choice choice_option_list +{ + $$ = menu_add_menu(); +}; + +choice_end: end +{ + if (zconf_endtoken($1, T_CHOICE, T_ENDCHOICE)) { + menu_end_menu(); + printd(DEBUG_PARSE, "%s:%d:endchoice\n", zconf_curname(), zconf_lineno()); + } +}; + +choice_stmt: choice_entry choice_block choice_end +; + +choice_option_list: + /* empty */ + | choice_option_list choice_option + | choice_option_list depends + | choice_option_list help + | choice_option_list T_EOL + | choice_option_list option_error +; + +choice_option: T_PROMPT prompt if_expr T_EOL +{ + menu_add_prompt(P_PROMPT, $2, $3); + printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno()); +}; + +choice_option: T_TYPE prompt_stmt_opt T_EOL +{ + if ($1->stype == S_BOOLEAN || $1->stype == S_TRISTATE) { + menu_set_type($1->stype); + printd(DEBUG_PARSE, "%s:%d:type(%u)\n", + zconf_curname(), zconf_lineno(), + $1->stype); + } else + YYERROR; +}; + +choice_option: T_OPTIONAL T_EOL +{ + current_entry->sym->flags |= SYMBOL_OPTIONAL; + printd(DEBUG_PARSE, "%s:%d:optional\n", zconf_curname(), zconf_lineno()); +}; + +choice_option: T_DEFAULT T_WORD if_expr T_EOL +{ + if ($1->stype == S_UNKNOWN) { + menu_add_symbol(P_DEFAULT, sym_lookup($2, 0), $3); + printd(DEBUG_PARSE, "%s:%d:default\n", + zconf_curname(), zconf_lineno()); + } else + YYERROR; +}; + +choice_block: + /* empty */ + | choice_block common_stmt +; + +/* if entry */ + +if_entry: T_IF expr nl +{ + printd(DEBUG_PARSE, "%s:%d:if\n", zconf_curname(), zconf_lineno()); + menu_add_entry(NULL); + menu_add_dep($2); + $$ = menu_add_menu(); +}; + +if_end: end +{ + if (zconf_endtoken($1, T_IF, T_ENDIF)) { + menu_end_menu(); + printd(DEBUG_PARSE, "%s:%d:endif\n", zconf_curname(), zconf_lineno()); + } +}; + +if_stmt: if_entry if_block if_end +; + +if_block: + /* empty */ + | if_block common_stmt + | if_block menu_stmt + | if_block choice_stmt +; + +/* mainmenu entry */ + +mainmenu_stmt: T_MAINMENU prompt nl +{ + menu_add_prompt(P_MENU, $2, NULL); +}; + +/* menu entry */ + +menu: T_MENU prompt T_EOL +{ + menu_add_entry(NULL); + menu_add_prompt(P_MENU, $2, NULL); + printd(DEBUG_PARSE, "%s:%d:menu\n", zconf_curname(), zconf_lineno()); +}; + +menu_entry: menu visibility_list depends_list +{ + $$ = menu_add_menu(); +}; + +menu_end: end +{ + if (zconf_endtoken($1, T_MENU, T_ENDMENU)) { + menu_end_menu(); + printd(DEBUG_PARSE, "%s:%d:endmenu\n", zconf_curname(), zconf_lineno()); + } +}; + +menu_stmt: menu_entry menu_block menu_end +; + +menu_block: + /* empty */ + | menu_block common_stmt + | menu_block menu_stmt + | menu_block choice_stmt +; + +source_stmt: T_SOURCE prompt T_EOL +{ + printd(DEBUG_PARSE, "%s:%d:source %s\n", zconf_curname(), zconf_lineno(), $2); + zconf_nextfile($2); +}; + +/* comment entry */ + +comment: T_COMMENT prompt T_EOL +{ + menu_add_entry(NULL); + menu_add_prompt(P_COMMENT, $2, NULL); + printd(DEBUG_PARSE, "%s:%d:comment\n", zconf_curname(), zconf_lineno()); +}; + +comment_stmt: comment depends_list +{ + menu_end_entry(); +}; + +/* help option */ + +help_start: T_HELP T_EOL +{ + printd(DEBUG_PARSE, "%s:%d:help\n", zconf_curname(), zconf_lineno()); + zconf_starthelp(); +}; + +help: help_start T_HELPTEXT +{ + current_entry->help = $2; +}; + +/* depends option */ + +depends_list: + /* empty */ + | depends_list depends + | depends_list T_EOL + | depends_list option_error +; + +depends: T_DEPENDS T_ON expr T_EOL +{ + menu_add_dep($3); + printd(DEBUG_PARSE, "%s:%d:depends on\n", zconf_curname(), zconf_lineno()); +}; + +/* visibility option */ + +visibility_list: + /* empty */ + | visibility_list visible + | visibility_list T_EOL +; + +visible: T_VISIBLE if_expr +{ + menu_add_visibility($2); +}; + +/* prompt statement */ + +prompt_stmt_opt: + /* empty */ + | prompt if_expr +{ + menu_add_prompt(P_PROMPT, $1, $2); +}; + +prompt: T_WORD + | T_WORD_QUOTE +; + +end: T_ENDMENU T_EOL { $$ = $1; } + | T_ENDCHOICE T_EOL { $$ = $1; } + | T_ENDIF T_EOL { $$ = $1; } +; + +nl: + T_EOL + | nl T_EOL +; + +if_expr: /* empty */ { $$ = NULL; } + | T_IF expr { $$ = $2; } +; + +expr: symbol { $$ = expr_alloc_symbol($1); } + | symbol T_EQUAL symbol { $$ = expr_alloc_comp(E_EQUAL, $1, $3); } + | symbol T_UNEQUAL symbol { $$ = expr_alloc_comp(E_UNEQUAL, $1, $3); } + | T_OPEN_PAREN expr T_CLOSE_PAREN { $$ = $2; } + | T_NOT expr { $$ = expr_alloc_one(E_NOT, $2); } + | expr T_OR expr { $$ = expr_alloc_two(E_OR, $1, $3); } + | expr T_AND expr { $$ = expr_alloc_two(E_AND, $1, $3); } +; + +symbol: T_WORD { $$ = sym_lookup($1, 0); free($1); } + | T_WORD_QUOTE { $$ = sym_lookup($1, SYMBOL_CONST); free($1); } +; + +word_opt: /* empty */ { $$ = NULL; } + | T_WORD + +%% + +void conf_parse(const char *name) +{ + struct symbol *sym; + int i; + + zconf_initscan(name); + + sym_init(); + _menu_init(); + modules_sym = sym_lookup(NULL, 0); + modules_sym->type = S_BOOLEAN; + modules_sym->flags |= SYMBOL_AUTO; + rootmenu.prompt = menu_add_prompt(P_MENU, "Linux Kernel Configuration", NULL); + + if (getenv("ZCONF_DEBUG")) + zconfdebug = 1; + zconfparse(); + if (zconfnerrs) + exit(1); + if (!modules_sym->prop) { + struct property *prop; + + prop = prop_alloc(P_DEFAULT, modules_sym); + prop->expr = expr_alloc_symbol(sym_lookup("MODULES", 0)); + } + + rootmenu.prompt->text = _(rootmenu.prompt->text); + rootmenu.prompt->text = sym_expand_string_value(rootmenu.prompt->text); + + menu_finalize(&rootmenu); + for_all_symbols(i, sym) { + if (sym_check_deps(sym)) + zconfnerrs++; + } + if (zconfnerrs) + exit(1); + sym_set_change_count(1); +} + +static const char *zconf_tokenname(int token) +{ + switch (token) { + case T_MENU: return "menu"; + case T_ENDMENU: return "endmenu"; + case T_CHOICE: return "choice"; + case T_ENDCHOICE: return "endchoice"; + case T_IF: return "if"; + case T_ENDIF: return "endif"; + case T_DEPENDS: return "depends"; + case T_VISIBLE: return "visible"; + } + return ""; +} + +static bool zconf_endtoken(const struct kconf_id *id, int starttoken, int endtoken) +{ + if (id->token != endtoken) { + zconf_error("unexpected '%s' within %s block", + kconf_id_strings + id->name, zconf_tokenname(starttoken)); + zconfnerrs++; + return false; + } + if (current_menu->file != current_file) { + zconf_error("'%s' in different file than '%s'", + kconf_id_strings + id->name, zconf_tokenname(starttoken)); + fprintf(stderr, "%s:%d: location of the '%s'\n", + current_menu->file->name, current_menu->lineno, + zconf_tokenname(starttoken)); + zconfnerrs++; + return false; + } + return true; +} + +static void zconfprint(const char *err, ...) +{ + va_list ap; + + fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno()); + va_start(ap, err); + vfprintf(stderr, err, ap); + va_end(ap); + fprintf(stderr, "\n"); +} + +static void zconf_error(const char *err, ...) +{ + va_list ap; + + zconfnerrs++; + fprintf(stderr, "%s:%d: ", zconf_curname(), zconf_lineno()); + va_start(ap, err); + vfprintf(stderr, err, ap); + va_end(ap); + fprintf(stderr, "\n"); +} + +static void zconferror(const char *err) +{ + fprintf(stderr, "%s:%d: %s\n", zconf_curname(), zconf_lineno() + 1, err); +} + +static void print_quoted_string(FILE *out, const char *str) +{ + const char *p; + int len; + + putc('"', out); + while ((p = strchr(str, '"'))) { + len = p - str; + if (len) + fprintf(out, "%.*s", len, str); + fputs("\\\"", out); + str = p + 1; + } + fputs(str, out); + putc('"', out); +} + +static void print_symbol(FILE *out, struct menu *menu) +{ + struct symbol *sym = menu->sym; + struct property *prop; + + if (sym_is_choice(sym)) + fprintf(out, "\nchoice\n"); + else + fprintf(out, "\nconfig %s\n", sym->name); + switch (sym->type) { + case S_BOOLEAN: + fputs(" boolean\n", out); + break; + case S_TRISTATE: + fputs(" tristate\n", out); + break; + case S_STRING: + fputs(" string\n", out); + break; + case S_INT: + fputs(" integer\n", out); + break; + case S_HEX: + fputs(" hex\n", out); + break; + default: + fputs(" ???\n", out); + break; + } + for (prop = sym->prop; prop; prop = prop->next) { + if (prop->menu != menu) + continue; + switch (prop->type) { + case P_PROMPT: + fputs(" prompt ", out); + print_quoted_string(out, prop->text); + if (!expr_is_yes(prop->visible.expr)) { + fputs(" if ", out); + expr_fprint(prop->visible.expr, out); + } + fputc('\n', out); + break; + case P_DEFAULT: + fputs( " default ", out); + expr_fprint(prop->expr, out); + if (!expr_is_yes(prop->visible.expr)) { + fputs(" if ", out); + expr_fprint(prop->visible.expr, out); + } + fputc('\n', out); + break; + case P_CHOICE: + fputs(" #choice value\n", out); + break; + case P_SELECT: + fputs( " select ", out); + expr_fprint(prop->expr, out); + fputc('\n', out); + break; + case P_RANGE: + fputs( " range ", out); + expr_fprint(prop->expr, out); + fputc('\n', out); + break; + case P_MENU: + fputs( " menu ", out); + print_quoted_string(out, prop->text); + fputc('\n', out); + break; + default: + fprintf(out, " unknown prop %d!\n", prop->type); + break; + } + } + if (menu->help) { + int len = strlen(menu->help); + while (menu->help[--len] == '\n') + menu->help[len] = 0; + fprintf(out, " help\n%s\n", menu->help); + } +} + +void zconfdump(FILE *out) +{ + struct property *prop; + struct symbol *sym; + struct menu *menu; + + menu = rootmenu.list; + while (menu) { + if ((sym = menu->sym)) + print_symbol(out, menu); + else if ((prop = menu->prompt)) { + switch (prop->type) { + case P_COMMENT: + fputs("\ncomment ", out); + print_quoted_string(out, prop->text); + fputs("\n", out); + break; + case P_MENU: + fputs("\nmenu ", out); + print_quoted_string(out, prop->text); + fputs("\n", out); + break; + default: + ; + } + if (!expr_is_yes(prop->visible.expr)) { + fputs(" depends ", out); + expr_fprint(prop->visible.expr, out); + fputc('\n', out); + } + } + + if (menu->list) + menu = menu->list; + else if (menu->next) + menu = menu->next; + else while ((menu = menu->parent)) { + if (menu->prompt && menu->prompt->type == P_MENU) + fputs("\nendmenu\n", out); + if (menu->next) { + menu = menu->next; + break; + } + } + } +} + +#include "zconf.lex.c" +#include "util.c" +#include "confdata.c" +#include "expr.c" +#include "symbol.c" +#include "menu.c" diff --git a/l4/tool/lib/L4/Grub.pm b/l4/tool/lib/L4/Grub.pm new file mode 100644 index 00000000..23ba94f8 --- /dev/null +++ b/l4/tool/lib/L4/Grub.pm @@ -0,0 +1,117 @@ +package L4::Grub; + +use Exporter; +use vars qw(@ISA @EXPORT); +@ISA = qw(Exporter); + +use Getopt::Long; + +sub parse_gengrub_args() +{ + my %a = ( timeout => undef, + serial => undef + ); + my @opts = ("timeout=i", \$a{timeout}, + "serial", \$a{serial}); + + if (!GetOptions(@opts)) + { + print "Command line parsing failed.\n"; + } + + if (0) + { + print "Options:\n"; + print "timeout: $a{timeout}\n" if defined $a{timeout}; + print "serial : $a{serial}\n" if defined $a{serial}; + } + + %a; +} + +sub prepare_grub1_dir($) +{ + my $dir = shift; + + return if -e "$dir/boot/grub/stage2_eltorito"; + + my $copypath; + my @grub_path = ("/usr/lib/grub/i386-pc", "/usr/share/grub/i386-pc", + "/boot/grub", "/usr/local/lib/grub/i386-pc", + "/usr/lib/grub/x86_64-pc"); + unshift @grub_path, $ENV{GRUB_PATH} if defined $ENV{GRUB_PATH}; + + foreach my $p (@grub_path) { + $copypath=$p if -e "$p/stage2_eltorito"; + } + die "Cannot find a stage2_eltorito file..." unless defined $copypath; + + # copy files + mkdir "$dir/boot"; + mkdir "$dir/boot/grub"; + system("cp $copypath/stage2_eltorito $dir/boot/grub"); + chmod 0644, "$dir/boot/grub/stage2_eltorito"; +} + +sub grub1_mkisofs($$@) +{ + my ($isofilename, $dir, @morefiles) = @_; + system("cp -v ".join(' ', @morefiles)." $dir") if @morefiles; + my $mkisofs = 'genisoimage'; + system("genisoimage -help >/dev/null 2>&1"); + $mkisofs = 'mkisofs' if $?; + my $cmd = "$mkisofs -f -R -b boot/grub/stage2_eltorito". + " -no-emul-boot -boot-load-size 4 -boot-info-table". + " -hide-rr-moved -J -joliet-long -o \"$isofilename\" \"$dir\""; + + print "Generating GRUB1 image with cmd: $cmd\n"; + system("$cmd"); + die "Failed to create ISO" if $?; +} + +sub prepare_grub2_dir($) +{ + my $dir = shift; + mkdir "$dir/boot"; + mkdir "$dir/boot/grub"; +} + +sub grub2_mkisofs($$@) +{ + my ($isofilename, $dir, @morefiles) = @_; + my $cmd = "grub_mkisofs_arguments=-f grub-mkrescue" + ." --output=\"$isofilename\" $dir ".join(' ', @morefiles); + system("$cmd"); + die "Failed to create ISO" if $?; +} + + +sub grub1_config_prolog(%) +{ + my %opts = @_; + my $s = ''; + + $s .= "color 23 52\n"; + $s .= "serial\nterminal serial\n" if $opts{serial}; + $s .= "timeout $opts{timeout}\n" if defined $opts{timeout}; + $s .= "\n"; + + $s; +} + +sub grub2_config_prolog(%) +{ + my %opts = @_; + my $s = ''; + + if ($opts{serial}) + { + $s .= "serial\n"; + $s .= "terminal_output serial\n"; + $s .= "terminal_input serial\n"; + } + $s .= "set timeout=$opts{timeout}\n" if defined $opts{timeout}; + + $s; +} + diff --git a/l4/tool/lib/L4/ModList.pm b/l4/tool/lib/L4/ModList.pm new file mode 100644 index 00000000..a7d86c2d --- /dev/null +++ b/l4/tool/lib/L4/ModList.pm @@ -0,0 +1,421 @@ + +package L4::ModList; +use Exporter; +use vars qw(@ISA @EXPORT); +@ISA = qw(Exporter); +@EXPORT = qw(get_module_entry search_file get_entries); + +my @internal_searchpaths; + +my $arglen = 200; + +sub get_command_and_cmdline($) +{ + my ($file, $args) = split /\s+/, $_[0], 2; + + my $full = $file; + $full .= " $args" if defined $args; + $full =~ s/"/\\"/g; + + if (length($full) > $arglen) { + print "$line: \"$full\" too long...\n"; + exit 1; + } + + ($file, $full); +} + +# extract an entry with modules from a modules.list file +sub get_module_entry($$) +{ + my ($mod_file, $entry_to_pick) = @_; + my @mods; + my %groups; + + if ($entry_to_pick eq 'auto-build-entry') { + # Automatic build entry is being built. + # This image is useless but it always builds. + + $mods[0] = { command => 'Makefile', cmdline => 'Makefile', type => 'bin'}; + $mods[1] = { command => 'Makefile', cmdline => 'Makefile', type => 'bin'}; + $mods[2] = { command => 'Makefile', cmdline => 'Makefile', type => 'bin'}; + + return ( + mods => [ @mods ], + modaddr => 0x200000, + ); + } + + open(M, $mod_file) || die "Cannot open $mod_file!: $!"; + + # preseed first 3 modules + $mods[0] = { command => 'fiasco', cmdline => 'fiasco', type => 'bin'}; + $mods[1] = { command => 'sigma0', cmdline => 'sigma0', type => 'bin'}; + $mods[2] = { command => 'roottask', cmdline => 'moe', type => 'bin'}; + + my $line = 0; + my $process_mode = undef; + my $found_entry = 0; + my $global = 1; + my $modaddr_title; + my $modaddr_global; + my $bootstrap_command = "bootstrap"; + my $bootstrap_cmdline = "bootstrap"; + my $linux_initrd; + my $is_mode_linux; + while () { + $line++; + chomp; + s/#.*$//; + s/^\s*//; + next if /^$/; + + if (/^modaddr\s+(\S+)/) { + $modaddr_global = $1 if $global; + $modaddr_title = $1 if !$global; + next; + } + + my ($type, $remaining) = split /\s+/, $_, 2; + $type = lc($type); + + $type = 'bin' if $type eq 'module'; + + if ($type =~ /^(entry|title)$/) { + if (lc($entry_to_pick) eq lc($remaining)) { + $process_mode = 'entry'; + $found_entry = 1; + } else { + $process_mode = undef; + } + $global = 0; + next; + } elsif ($type eq 'searchpath') { + push @internal_searchpaths, $remaining; + next; + } elsif ($type eq 'group') { + $process_mode = 'group'; + $current_group_name = (split /\s+/, $remaining)[0]; + next; + } elsif ($type eq 'default-bootstrap') { + my ($file, $full) = get_command_and_cmdline($remaining); + $bootstrap_command = $file; + $bootstrap_cmdline = $full; + next; + } elsif ($type eq 'default-kernel') { + my ($file, $full) = get_command_and_cmdline($remaining); + $mods[0]{command} = $file; + $mods[0]{cmdline} = $full; + next; + } elsif ($type eq 'default-sigma0') { + my ($file, $full) = get_command_and_cmdline($remaining); + $mods[1]{command} = $file; + $mods[1]{cmdline} = $full; + next; + } elsif ($type eq 'default-roottask') { + my ($file, $full) = get_command_and_cmdline($remaining); + $mods[2]{command} = $file; + $mods[2]{cmdline} = $full; + next; + } + + next unless $process_mode; + + my @valid_types = ( 'bin', 'data', 'bin-nostrip', 'data-nostrip', + 'bootstrap', 'roottask', 'kernel', 'sigma0', + 'module-perl', 'module-shell', 'module-glob', + 'module-group', 'moe', 'initrd', 'set'); + die "$line: Invalid type \"$type\"" + unless grep(/^$type$/, @valid_types); + + @m = ( $remaining ); + + if ($type eq 'set') { + my ($varname, $value) = split /\s+/, $remaining, 2; + $is_mode_linux = 1 if $varname eq 'mode' and lc($value) eq 'linux'; + } + + if ($type eq 'module-perl') { + @m = eval $remaining; + die $@ if $@; + $type = 'bin'; + } elsif ($type eq 'module-shell') { + @m = split /\n/, `$remaining`; + die "Shell command on line $line failed\n" if $?; + $type = 'bin'; + } elsif ($type eq 'module-glob') { + @m = glob $remaining; + $type = 'bin'; + } elsif ($type eq 'module-group') { + @m = (); + foreach (split /\s+/, $remaining) { + die "Unknown group '$_'" unless defined $groups{$_}; + push @m, @{$groups{$_}}; + } + $type = 'bin'; + } elsif ($type eq 'moe') { + $mods[2]{command} = 'moe'; + $mods[2]{cmdline} = "moe rom/$remaining"; + $type = 'bin'; + @m = ($remaining); + } + next if not defined $m[0] or $m[0] eq ''; + + if ($process_mode eq 'entry') { + foreach my $m (@m) { + + my ($file, $full) = get_command_and_cmdline($m); + + # special cases + if ($type eq 'bootstrap') { + $bootstrap_command = $file; + $bootstrap_cmdline = $full; + } elsif ($type =~ /(rmgr|roottask)/i) { + $mods[2]{command} = $file; + $mods[2]{cmdline} = $full; + } elsif ($type eq 'kernel') { + $mods[0]{command} = $file; + $mods[0]{cmdline} = $full; + } elsif ($type eq 'sigma0') { + $mods[1]{command} = $file; + $mods[1]{cmdline} = $full; + } elsif ($type eq 'initrd') { + $linux_initrd = $file; + $is_mode_linux = 1; + } else { + push @mods, { + type => $type, + command => $file, + cmdline => $full, + }; + } + } + } elsif ($process_mode eq 'group') { + push @{$groups{$current_group_name}}, @m; + } else { + die "Invalid mode '$process_mode'"; + } + } + + close M; + + die "Unknown entry \"$entry_to_pick\"!" unless $found_entry; + die "'modaddr' not set" unless $modaddr_title || $modaddr_global; + + my $m = $modaddr_title || $modaddr_global; + if (defined $is_mode_linux) + { + die "No Linux kernel image defined" unless defined $mods[0]{cmdline}; + print STDERR "Entry '$entry_to_pick' is a Linux type entry\n"; + my @files; + # @files is actually redundant but eases file selection for entry + # generators + push @files, $mods[0]{command}; + push @files, $linux_initrd if defined $linux_initrd; + my %r; + %r = ( + # actually bootstrap is always the kernel in this + # environment, for convenience we use $mods[0] because that + # are the contents of 'kernel xxx' which sounds more + # reasonable + bootstrap => { command => $mods[0]{command}, + cmdline => $mods[0]{cmdline}}, + type => 'Linux', + files => [ @files ], + ); + $r{initrd} = { cmdline => $linux_initrd } if defined $linux_initrd; + return %r; + } + + # now some implicit stuff + if ($bootstrap_cmdline =~ /-modaddr\s+/) { + $bootstrap_cmdline =~ s/(-modaddr\s+)%modaddr%/$1$m/; + } else { + $bootstrap_cmdline .= " -modaddr $m"; + } + + my @filse; # again, this is redundant but helps generator functions + push @files, $bootstrap_command; + push @files, $_->{command} foreach @mods; + + return ( + bootstrap => { command => $bootstrap_command, + cmdline => $bootstrap_cmdline }, + mods => [ @mods ], + modaddr => $modaddr_title || $modaddr_global, + type => 'MB', + files => [ @files ], + ); +} + +sub entry_is_linux(%) +{ + my %e = @_; + return defined $e{type} && $e{type} eq 'Linux'; +} + +sub entry_is_mb(%) +{ + my %e = @_; + return defined $e{type} and $e{type} eq 'MB'; +} + +sub get_entries($) +{ + my ($mod_file) = @_; + my @entry_list; + + open(M, $mod_file) || die "Cannot open $mod_file!: $!"; + + while () { + chomp; + s/#.*$//; + s/^\s*//; + next if /^$/; + push @entry_list, $2 if /^(entry|title)\s+(.+)/; + } + + close M; + + return @entry_list; +} + +# Search for a file by using a path list (single string, split with colons +# or spaces, see the split) +# return undef if it could not be found, the complete path otherwise +sub search_file($$) +{ + my $file = shift; + my $paths = shift; + + foreach my $p (split(/[:\s]+/, $paths), @internal_searchpaths) { + return "$p/$file" if -e "$p/$file" and ! -d "$p/$file"; + } + + return $file if $file =~ /^\// && -e $file; + + undef; +} + +sub search_file_or_die($$) +{ + my $file = shift; + my $paths = shift; + my $f = search_file($file, $paths); + die "Could not find '$file' with path '$paths'" unless defined $f; + $f; +} + +sub get_or_copy_file_uncompressed_or_die($$$$) +{ + my $command = shift; + my $paths = shift; + my $targetdir = shift; + my $copy = shift; + + my $fp = L4::ModList::search_file_or_die($command, $paths); + + open F, $fp || die "connot open '$fp': $!"; + my $buf; + read F, $buf, 2; + close F; + + (my $tf = $fp) =~ s|.*/||; + $tf = $targetdir.'/'.$tf; + + if (length($buf) >= 2 && unpack("n", $buf) == 0x1f8b) { + print STDERR "'$fp' is a zipped file, uncompressing to '$tf'\n"; + system("zcat $fp >$tf"); + $fp = $tf; + } elsif ($copy) { + print("cp $fp $tf\n"); + system("cp $fp $tf"); + $fp = $tf; + } + + $fp; +} + +sub get_file_uncompressed_or_die($$$) +{ + return get_or_copy_file_uncompressed_or_die(shift, shift, shift, 0); +} + +sub copy_file_uncompressed_or_die($$$) +{ + return get_or_copy_file_uncompressed_or_die(shift, shift, shift, 1); +} + + +sub generate_grub1_entry($$%) +{ + my $entryname = shift; + my $prefix = shift; + $prefix = '' unless defined $prefix; + $prefix = "/$prefix" if $prefix ne '' and $prefix !~ /^\//; + my %entry = @_; + my $s = "title $entryname\n"; + my $c = $entry{bootstrap}{cmdline}; + $c =~ s/^\S*\/([^\/]+\s*)/$1/; + $s .= "kernel $prefix/$c\n"; + + if (entry_is_linux(%entry) and defined $entry{initrd}) + { + $c = $entry{initrd}{cmdline}; + $c =~ s/^\S*\/([^\/]+\s*)/$1/; + $s .= "initrd $prefix/$c\n"; + return $s; + } + + foreach my $m (@{$entry{mods}}) + { + $c = $m->{cmdline}; + $c =~ s/^\S*\/([^\/]+\s*)/$1/; + $s .= "module $prefix/$c\n"; + } + $s; +} + +sub generate_grub2_entry($$%) +{ + my $entryname = shift; + my $prefix = shift; + $prefix = '' unless defined $prefix; + $prefix = "/$prefix" if $prefix ne '' and $prefix !~ /^\//; + my %entry = @_; + # basename of first path + my ($c, $args) = split(/\s+/, $entry{bootstrap}{cmdline}, 2); + my $bn = (reverse split(/\/+/, $c))[0]; + my $s = "menuentry \"$entryname\" {\n"; + + if (entry_is_linux(%entry)) + { + $s .= " echo Loading '$prefix/$bn $args'\n"; + $s .= " linux $prefix/$bn $args\n"; + if (defined $entry{initrd}) + { + $bn = (reverse split(/\/+/, $entry{initrd}{cmdline}))[0]; + my $c = $entry{initrd}{cmdline}; + $c =~ s/^\S*(\/[^\/]+\s*)/$1/; + $s .= " initrd $prefix$c\n"; + } + } + else + { + $s .= " echo Loading '$prefix/$bn $prefix/$bn $args'\n"; + $s .= " multiboot $prefix/$bn $prefix/$bn $args\n"; + foreach my $m (@{$entry{mods}}) + { + # basename + $bn = (reverse split(/\/+/, $m->{command}))[0]; + my $c = $m->{cmdline}; + $c =~ s/^\S*(\/[^\/]+\s*)/$1/; + $s .= " echo Loading '$prefix/$bn $c'\n"; + $s .= " module $prefix/$bn $c\n"; + } + } + $s .= " echo Done, booting...\n"; + $s .= "}\n"; +} + +return 1; diff --git a/l4/tool/vim/syntax/ioconfig.vim b/l4/tool/vim/syntax/ioconfig.vim new file mode 100644 index 00000000..b362c938 --- /dev/null +++ b/l4/tool/vim/syntax/ioconfig.vim @@ -0,0 +1,21 @@ +" Vim syntax file for io configuration language +" Language: IO configuration language +" Maintainer: Adam Lackorzynski +" Last Change: 2010 June + +if exists("b:current_syntax") + finish +endif + +syn clear +syn case match + +setlocal iskeyword+=. +setlocal iskeyword+=- +syn keyword ioconfigStatement hw-root hw-root.match Device new System_bus wrap new-res .hid Irq Io Mmio Mmio_ram PCI_bus PCI_bus_ident +syn match ioconfigComment /#.*/ + +hi def link ioconfigStatement Type +hi def link ioconfigComment Comment + +let b:current_syntax = "ioconfig" diff --git a/l4/tool/vim/syntax/l4mods.vim b/l4/tool/vim/syntax/l4mods.vim new file mode 100644 index 00000000..10a0cbfd --- /dev/null +++ b/l4/tool/vim/syntax/l4mods.vim @@ -0,0 +1,26 @@ +" Vim syntax file for modules.list configuration language +" Language: modules.list configuration language +" Maintainer: Adam Lackorzynski +" Last Change: 2010 Apr 27 + +if exists("b:current_syntax") + finish +endif + +syn clear +syn case match + +setlocal iskeyword+=- +syn keyword l4modsStatement modaddr module bin bin-nostrip data data-nostrip kernel sigma0 +syn keyword l4modsStatement roottask moe default-kernel default-sigma0 default-roottask default-bootstrap +syn keyword l4modsStatement module-group module-glob module-perl module-shell bootstrap initrd set +syn keyword l4modsStatementTitle entry group contained +syn match l4modsTitle /^ *\(entry\|group\).*/ contains=l4modsStatementTitle +syn match l4modsComment /#.*/ + +hi def link l4modsStatement Statement +hi def link l4modsStatementTitle Type +hi def link l4modsComment Comment +hi def link l4modsTitle String + +let b:current_syntax = "l4mods" diff --git a/l4/tool/vim/syntax/objdump.vim b/l4/tool/vim/syntax/objdump.vim new file mode 100644 index 00000000..c58ebfc9 --- /dev/null +++ b/l4/tool/vim/syntax/objdump.vim @@ -0,0 +1,27 @@ +" Vim syntax file for objdump disassembly output +" Language: Objdump output +" Maintainer: Adam Lackorzynski +" Last Change: 2008 Nov 08 + +if exists("b:current_syntax") + finish +endif + +syn clear +syn case match + +" enable to have highlighted c code +"runtime! syntax/c.vim +"unlet b:current_syntax + +syn match objdumpInsn /^\s*[0-9a-fA-F]\+:.*/ +syn match objdumpLabelFunc /^[0-9a-fA-F]\+\s<.\+>:$/ +syn match objdumpLabelCode /^\w.\+():$/ +syn match objdumpPath /^\/.\+:[0-9]\+$/ + +hi def link objdumpInsn Type +hi def link objdumpLabelFunc Comment +hi def link objdumpLabelCode String +hi def link objdumpPath Statement + +let b:current_syntax = "objdump" diff --git a/l4/tool/vim/syntax/simics.vim b/l4/tool/vim/syntax/simics.vim new file mode 100644 index 00000000..014aa51b --- /dev/null +++ b/l4/tool/vim/syntax/simics.vim @@ -0,0 +1,89 @@ +" Vim syntax file for Simics command line scripts +" Language: Simics command line +" Maintainer: Bjoern Doebel +" Last Change: 2010 Oct 29 + +if exists("b:current_syntax") + finish +endif + +syn clear +syn case match + +setlocal iskeyword+=- +syn keyword simicsStatement a alias api-search add-data-to-script-pipe and apropos add-directory api-apropos auto-partition-configuration add-module-directory api-help +syn keyword simicsStatement b bookmark break-cr break-heap break-log bin break break-exception break-io +syn keyword simicsStatement c cb cba cc cd change-namespace check-cell-partitioning clear-directories clear-recorder cmdline. cmdline_term. cn command-history +syn keyword simicsStatement command-list configuration-shortest-paths connect connect-central connect-components connect-real-network connect-real-network-bridge connect-real-network-host connect-real-network-napt +syn keyword simicsStatement connect-real-network-port-in connect-real-network-port-out connect-real-network-router continue continue-cycles continue-seconds copy-connector +syn keyword simicsStatement copyright cpu-switch-time create-script-barrier create-script-pipe current-namespace current-processor cycle-break cycle-break-absolute +syn keyword simicsStatement da date dec default-port-forward-target defined delete delete-bookmark devs digit-grouping dirs disable disable-hypersim disable-magic-breakpoint disable-mtprof +syn keyword simicsStatement disable-multithreading disable-page-sharing disable-real-time-mode disable-reverse-execution disassemble disassemble-settings disconnect disconnect-real-network +syn keyword simicsStatement disconnect-real-network-port-in disconnect-real-network-port-out display dstc-disable dstc-enable +syn keyword simicsStatement echo else enable enable-core2-bugfix enable-hypersim enable-magic-breakpoint enable-mtprof enable-multithreading enable-page-sharing +syn keyword simicsStatement enable-real-time-mode enable-reverse-execution env except exec exit expect +syn keyword simicsStatement foreach +syn keyword simicsStatement get get-breakpoint-list get-class-list get-component-list get-component-prefix get-error-command +syn keyword simicsStatement get-error-file get-error-line get-error-message get-object-list get-set-no-inquiry +syn keyword simicsStatement h help help-search hex hl hypersim-status +syn keyword simicsStatement ib if ifm ignore in in-list info-breakpoints instantiate-components instruction-fetch-mode +syn keyword simicsStatement interrupt-script interrupt-script-branch io-stats iostc-disable iostc-enable istc-disable istc-enable +syn keyword simicsStatement l2p license list-attributes list-bookmarks list-breakpoints list-classes list-components list-directories list-failed-modules list-hap-callbacks list-haps list-hypersim-patterns +syn keyword simicsStatement list-length list-modules list-namespaces list-objects list-port-forwarding-setup list-preferences list-script-branches list-variables list-vars +syn keyword simicsStatement load-binary load-file load-module load-persistent-state local log log-level log-setup log-size log-type logical-to-physical lookup-file ls +syn keyword simicsStatement magic-breakpoint-enabled match-string man max min module-list module-list-failed module-list-refresh move-object +syn keyword simicsStatement native-path network-helper new-attr-meter new-central-server new-context new-context-switcher new-cpu-mode-tracker +syn keyword simicsStatement new-etg new-file-cdrom new-freescale-hv-tracker new-gdb-remote new-glink new-hap-meter new-host-cdrom new-hypersim-pattern-matcher +syn keyword simicsStatement new-linux-process-tracker new-mem-traffic-meter new-ose-process-tracker new-qnx-process-tracker new-realtime new-serial-link new-symtable +syn keyword simicsStatement new-time-server new-tracer new-usb-disk-from-image new-vxworks-process-tracker new-wdb-remote new-wr-hyper-tracker not +syn keyword simicsStatement object-exists oct or output-file-start output-file-stop output-radix +syn keyword simicsStatement p pdisable penable peq pid pipe popd pow prefs. pregs print print-event-queue +syn keyword simicsStatement print-time psel pselect pstatus ptime pushd pwd python python. +syn keyword simicsStatement q quit +syn keyword simicsStatement r range rc read-configuration read-reg read-variable readme resolve-file restart-simics rev reverse reverse-cycles reverse-step-instruction +syn keyword simicsStatement reverse-to revto rexec-> rexec-limit rexec.get-attribute-list rexec.get-interface-list rexec.get-interface-port-list rexec.list-attributes +syn keyword simicsStatement rexec.list-interfaces rexec.log rexec.log-group rexec.log-level rexec.log-size rexec.log-type rlimit rstepi run run-command-file +syn keyword simicsStatement run-cycles run-python-file run-seconds +syn keyword simicsStatement save-component-template save-persistent-state save-preferences sb sba sc script-branch script-pipe-has-data search set set-bookmark +syn keyword simicsStatement set-component-prefix set-context set-memory-limit set-min-latency set-pattern set-pc set-prefix set-substr set-thread-limit shell si +syn keyword simicsStatement signed signed16 signed32 signed64 signed8 sim-> sim-break sim-break-absolute sim.get-attribute-list sim.get-interface-list sim.get-interface-port-list +syn keyword simicsStatement sim.info sim.list-attributes sim.list-interfaces sim.log sim.log-group sim.log-level sim.log-size sim.log-type sim.status skip-to +syn keyword simicsStatement split-string stc-status step-break step-break-absolute step-cycle step-instruction stepi stop sync-info system-info system-perfmeter system-perfmeter-plot +syn keyword simicsStatement telnet-frontend trace-breakpoint trace-cr trace-exception trace-hap trace-io try +syn keyword simicsStatement unbreak unbreak-cr unbreak-exception unbreak-hap unbreak-io undisplay unload-module unset unstep-instruction +syn keyword simicsStatement untrace-breakpoint untrace-cr untrace-exception untrace-hap use-old-bool untrace-io +syn keyword simicsStatement version +syn keyword simicsStatement wait-for-breakpoint wait-for-hap wait-for-script-pipe wait-for-script-barrier wait-for-variable while win-about win-command-line +syn keyword simicsStatement win-command-list win-configuration-view win-console win-cpu-registers win-control win-device-registers win-disassembly win-hap-list +syn keyword simicsStatement win-help win-memory win-memory-browser win-object-browser win-plot win-preferences win-stack-trace win-source-view win-user-plot write-configuration write-reg +syn keyword simicsStatement x + +syn keyword simicsTodo XXX TODO FIXME + +syn region String start=+"+ skip=+\\"+ end=+"+ + +syn match simicsComment /#.*/ contains=simicsTodo + +syn match simicsVariable "$[a-zA-Z_][a-zA-Z0-9_]*" +syn match simicsVariable "%[a-zA-Z_][a-zA-Z0-9_]*%" + +syn match simicsNumber "\d\+" +syn match simicsNumber "0x\x\+" + +" x86 registers +syn match simicsPlatformRegister "%e\?\(ax\|bx\|cx\|di\|dx\|flags\|si\|bp\|ip\|sp\)" +syn match simicsPlatformRegister "%\(ah\|al\|bh\|bl\|ch\|cl\|dh\|dl\)" +syn match simicsPlatformRegister "%\(cpl\|cr0\|cr2\|cr3\|cr4\)" +syn match simicsPlatformRegister "%[cdefgs]s\(_\(attr\|base\|limit\)\)*" + +" XXX: add other platforms + +hi def link simicsStatement Statement +hi def link simicsComment Comment +hi def link String String +hi def link simicsVariable Identifier +hi def link simicsPlatformRegister Special +hi def link simicsTodo Todo +hi def link simicsNumber Number + +let b:current_syntax = "simics" diff --git a/repomgr b/repomgr new file mode 100755 index 00000000..022a516e --- /dev/null +++ b/repomgr @@ -0,0 +1,584 @@ +#! /usr/bin/perl -W + +use strict; + +my %modules = + ( + repomgr => { paths => [ qw(repomgr) ] }, + + bid => { paths => [ qw(l4/Makefile + l4/BENCHMARKING + l4/COPYING-GPL-2 + l4/COPYING-LGPL-2.1 + l4/LICENSING + l4/mk + l4/conf + l4/pkg/Makefile + l4/pkg/README + l4/tool/Makefile + l4/tool/gendep + l4/tool/kconfig + l4/tool/vim + l4/tool/lib + l4/tool/elf-patcher + ) ] + }, + + toolbin => { paths => [ map { "l4/tool/bin/$_" } + qw(isocreator qemu-x86-launch ux-launch + gengrub1iso gengrub2iso entry-selector + mkspafs genexportpack + ) ] + }, + + l4re => { paths => [ map { "l4/pkg/$_" } qw( + boehm_gc bootstrap libgcc libgcc-pure + crtn cxx cxx_libc_io cxx_thread drivers-frst hello + ldscripts + l4re l4re_c l4re_kernel l4re_vfs l4sys l4util + ldscripts ldso + libc_backends libkproxy libloader + libsigma0 + libstdc++-headers libstdc++-v3 libstdc++-v3-minimal + libsupc++ libsupc++-minimal + libvbus libvcpu loader log lua moe ned sigma0 + uclibc uclibc-minimal uclibc-headers + ) ], + pub_module => 1, + modules => [ qw(bid toolbin) ], + }, + + # ./mk/pkgdeps -A mk/aliases.d pkgdeps pkg ... + l4linux_requirements + => { paths => [ map { "l4/pkg/$_" } qw( + libio libio-io lxfuxlibc rtc shmc + acpica io drivers fb-drv x86emu input libirq + ) ], + pub_module => 1, + modules => [ qw(l4re) ], + }, + + examples_core => { + paths => [ qw(l4/pkg/hello), + map { "l4/pkg/examples/$_" } + qw(Makefile + Control + sys + clntsrv + misc/Makefile + misc/cat + misc/shared-hello + libs/Makefile + libs/l4re + ) ], + }, + + + examples_all => { + modules => [ qw(examples_core) ], + paths => [ qw(l4/pkg/hello), + map { "l4/pkg/examples/$_" } + qw( + fb/Makefile + fb/spectrum + misc/eb_leds + misc/reboot + libs/inputtst + libs/libc_thread_safe + libs/libgomp + libs/libio + libs/libirq + libs/libpng + libs/shmc + ) ], + }, + + doc => { paths => [ qw(l4/doc/Makefile l4/doc/source) ], }, + + l4re_snapshot => { + paths => [ map { "l4/pkg/$_" } + qw(acpica + ankh + boost-lite + cunit + dash + demangle + dde + dde-libinput + dope + drivers + expat2 + fb-drv + fbterminal + fuxfprov + hello + input + io + l4con + lib_vt100 + libbsd + libbsd-full + libevent + libc_be_stdin + libcrypto + libevent + libgfxbitmap + libgomp + libiniparser + libio + libio-io + libirq + libjpeg + libpng + libsdl + libsdl-image + linux-26-headers + lwip + lxfuxlibc + mag + mag-gfx + ocaml + ocaml_toys + plr + python + readline + rtc + scout + scout-gfx + serial-drv + shmc + slab + spafs + sqlite + tlsf + tmpfs + udis86 + valgrind + x86emu + zlib + ) ], + modules => [ qw(l4re examples_all doc toolbin) ] }, + + l4re_all => { paths => [ qw(l4/pkg l4/tool) ], + modules => [ qw(l4re_snapshot) ] }, + + fiasco => { + pub_module => 1, + paths => [ qw(kernel/fiasco/BENCHMARKING + kernel/fiasco/COPYING + kernel/fiasco/MAINTAINER + kernel/fiasco/Makefile + kernel/fiasco/README + kernel/fiasco/src + kernel/fiasco/tool + ) ], + }, + + kernel => { + paths => [ qw(kernel/Makefile) ], + }, + + grub => { + paths => [ qw(grub) ], + }, + + remote_repo_l4re => { + modules => [ qw(l4re_snapshot) ], + }, + + remote_repo => { modules => [ qw(fiasco remote_repo_l4re) ], + # those are going away, we need to keep them to get the + # dirs updated and thus removed + paths => [ qw(l4/pkg/libstdc++-v3_r + l4/pkg/libsupc++_r + l4/pkg/uclibc_r) ], + }, + + all => { + modules => [ qw(remote_repo) ], + }, + ); + +my %commands; +my $svnrev = $ENV{REPOMGR_SVN_REV} || 'HEAD'; + +sub get_root_url() +{ + my $o = `svn info -r '$svnrev' --xml .`; + die "Failed 'svn info'." if $?; + $o =~ /(.+)<\/root>/m; + $1; +} + +sub merge_modules +{ + my %paths; + + sub do_merge + { + my $pathsref = shift; + my $count = shift; + + die "Possible looping in modules structure detected!" unless $count; + + foreach my $m (@_) + { + die "Unknown module '$m' referenced!" unless defined $modules{$m}; + $$pathsref{$_} = 1 foreach @{$modules{$m}{paths}}; + do_merge($pathsref, $count - 1, @{$modules{$m}{modules}}); + } + } + + do_merge(\%paths, 20, scalar @_ ? @_ : 'all'); + + sort keys %paths; +} + +sub show_pub_modules() +{ + print "Available modules:\n"; + foreach (sort keys %modules) + { + print " $_\n" if $modules{$_}{pub_module}; + } +} + +sub usage +{ + my $command = shift; + + # check alias + $command = $commands{$command}{alias} + if defined $command and defined $commands{$command}{alias}; + + if (!defined $command or $command eq 'help') + { + print "$0 command [option]\n"; + + print "Available commands, use '$0 help command' for help on the command:\n"; + foreach (sort keys %commands) + { + print " $_\n" if defined $commands{$_}{public}; + } + } + elsif ($command eq 'update') + { + print " 'update' will update in the following way:\n". + " update itself and re-exec if necessary\n". + " call 'make update' in l4/pkg\n". + " call 'svn update' every directory in kernel\n"; + } + elsif ($command eq 'checkout') + { + print " 'checkout' will check out the given modules.\n"; + show_pub_modules(); + } + elsif ($command eq 'modules') + { + show_pub_modules(); + } + else + { + print " No such command '$command'.\n"; + } +} + +sub check_module_structure() +{ + # make sure the paths look ok + foreach (merge_modules()) + { + die "Trailing /'s in modules structure" if /\/$/; + die "Double // detected in modules structure" if /\/\//; + } +} + +sub command_help +{ + usage(@_); +} + +sub command_update +{ + print "XXX: todo\n"; +} + +sub command_root +{ + my $url = shift; + my $dirname = shift; + die "Need to give URL" unless defined $url and defined $dirname; + system("svn co -r '$svnrev' $url --depth empty $dirname"); +} + +sub init_config($) +{ + my $config_blob = shift; + $config_blob = '{}' unless defined $config_blob; + my $c; + unless ($c = eval($config_blob)) + { + die "Couldn't parse config file: $@" if $@; + die "Couldn't do config file: $!" if $!; + die "Couldn't run config file"; + } + + my %a = %$c; + + $a{base} = "trunk" unless defined $a{base}; + + return %a; +} + +sub convert_path($$%) +{ + my $p = shift; + my $partmatch = shift; + my %path_roots = @_; + + $p =~ s/^\.\///; + $p .= '/'; + foreach my $key (keys %path_roots) + { + my $r = $key; + $r .= '/' unless $r =~ /\/$/; + if ($partmatch) + { + # for partly matches we also need to return the modified path + # because otherwise we can't really know + if ($p =~ /^($r)(.*)$/) + { + my $s = $path_roots{$key}.'/'.$2; + # strip off last / again, it's just used for matching + return substr($s, 0, length($s) - 1); + } + } + else + { + return $path_roots{$key} if $p =~ /^$r$/; + } + } + undef; +} + +sub do_checkout(%) +{ + my %args = @_; + unless (defined ${$args{mods}}[0]) + { + print "Supply module to check out.\n"; + usage("checkout"); + exit 1; + } + + die "Current directory is no SVN WC" unless -d ".svn"; + + my $root_url = get_root_url(); + + my @paths = merge_modules(@{$args{mods}}); + + foreach my $paths (@paths) + { + my @path_elems = split /\/+/, $paths; + my $last_elem = pop @path_elems; + my $path = '.'; + + foreach my $pe (@path_elems) + { + if (! -d "$path/$pe/.svn") + { + # if we find something from path_roots then switch to that + my $changed_path = convert_path("$path/$pe", 0, + %{$args{conf}{path_roots}}); + + print "Creating $path/$pe\n"; + print " from $changed_path\n" if defined $changed_path; + + # there's some other little problem with the 'depth' thing + # when we do checkout some specific list of files (and dirs), + # we need to use depth=empty so that we only get those + # specific files out of the directory, on the other side we'd + # (probably) like to have updates on the directory contents + # when we do 'svn up' which would would with depth=files (or + # infinite) + # As the first thing is merely only needed when doing a + # checkout for another repo... let's have a config option. + my $depth = 'files'; + $depth = 'empty' if defined $ENV{REPOMGR_EXACT_CHECKOUT}; + + if (defined $changed_path) + { + my $cmd = "cd $path && svn co -r '$svnrev' --depth empty $root_url/$changed_path $pe"; + #print "cmd: $cmd\n"; + system($cmd); + die "svn co failed" if $?; + } + else + { + my $cmd = "cd $path && svn update -r '$svnrev' --depth empty $pe"; + #print "cmd: $cmd\n"; + system($cmd); + die "svn update failed" if $?; + } + } + $path .= '/'.$pe; + } + } + + print "Getting sources\n"; + my $c = "svn update -r '$svnrev' --set-depth infinity ".join(' ', map { s/^\/+//; $_; } @paths); + #print "cmd: $c\n"; + system($c); + die "svn update failed" if $?; +} + +sub read_file($) +{ + my $fn = shift; + return undef unless defined $fn; + my $blob; + if ($fn =~ /^(file|svn|ssh\+svn):\/\//) + { + $blob = `svn -r '$svnrev' cat $fn`; + undef $blob if $?; + } + elsif (open(A, $fn)) + { + local undef $/; + $blob = ; + close A; + } + $blob; +} + +sub command_checkout +{ + my %conf = init_config(read_file("l4/conf/repomgr.conf")); + do_checkout(conf => { %conf }, mods => [ @_ ]); +} + +sub fix_repomgr_path(%) +{ + my %conf = @_; + # fix the path to the repomgr... + @{$modules{repomgr}{paths}} = map { "$conf{repomgr_prefix}/$_" } @{$modules{repomgr}{paths}} + if defined $conf{repomgr_prefix}; +} + +sub command_init +{ + my $repo_root = shift; + my $repo_conf = ''; + my $localdir = 'src'; + + while (defined $_[0] && ($_[0] eq '-c' or $_[0] eq '-l')) + { + if ($_[0] eq '-c') + { + $repo_conf = $_[1]; + shift; shift; + } + elsif ($_[0] eq '-l') + { + $localdir = $_[1]; + shift; shift; + } + } + + die "Usage: $0 init [-c ] [-l ] modules..." + if not defined $repo_root or not defined $repo_conf + or not defined $localdir; + + # for absolute path we assume a local config file, good for testing + my $confblob; + if ($repo_conf ne '') + { + if ($repo_conf =~ /^\//) + { + $confblob = read_file($repo_conf); + die "Cannot open '$repo_conf': $!" unless defined $confblob; + } + else + { + my $cmd = "svn cat -r '$svnrev' $repo_root\/$repo_conf"; + $confblob = `$cmd`; + die "Command '$cmd' failed" if $?; + } + } + + my %conf = init_config($confblob); + + ($localdir = $conf{base}) =~ s/.*\/// unless defined $localdir; + print "localdir: $localdir\n"; + + my $cmd = "svn co -r '$svnrev' --depth empty $repo_root/$conf{base} $localdir"; + system($cmd); + die "Command '$cmd' failed" if $?; + chdir $localdir; + + fix_repomgr_path(%conf); + do_checkout(conf => { %conf }, mods => [ "repomgr", @_ ]); +} + +sub command_modules +{ + foreach (sort keys %modules) + { + print "$_\n" if defined $modules{$_}{pub_module}; + } +} + +sub command_list +{ + print "$_\n" foreach merge_modules(@_); +} + +sub command_listmapped +{ + my $blob = read_file(shift); + die "Need config" unless defined $blob; + my %conf = init_config($blob); + fix_repomgr_path(%conf); + print join("\n", map { + my $p = convert_path($_, 1, %{$conf{path_roots}}); + defined $p ? $p : $_; + } merge_modules(@_)); + print "\n"; +} + +%commands = + ( + help => { func => \&command_help, }, + init => { func => \&command_init, }, + update => { func => \&command_update, }, + up => { func => \&command_update, alias => 'update' }, + checkout => { func => \&command_checkout, public => 1}, + co => { func => \&command_checkout, alias => 'checkout'}, + modules => { func => \&command_modules, public => 1}, + list => { func => \&command_list, }, + listmapped=> { func => \&command_listmapped, }, + root => { func => \&command_root, }, + ); + +# ---------------------------------------------------------------- + +check_module_structure(); + +my $command = shift; + +unless (defined $command) + { + usage(); + exit 1; + } + +if (defined $commands{$command}) + { + &{$commands{$command}{func}}(@ARGV); + } +else + { + print "Unknown command '$command'.\n"; + usage(); + exit 1; + } diff --git a/tools/preprocess/COPYING b/tools/preprocess/COPYING new file mode 100644 index 00000000..ee0775ea --- /dev/null +++ b/tools/preprocess/COPYING @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + Appendix: How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/tools/preprocess/MAINTAINER b/tools/preprocess/MAINTAINER new file mode 100644 index 00000000..1d2b5312 --- /dev/null +++ b/tools/preprocess/MAINTAINER @@ -0,0 +1,2 @@ +mailaddr hohmuth@sax.de + diff --git a/tools/preprocess/Makefile b/tools/preprocess/Makefile new file mode 100644 index 00000000..ee86d56b --- /dev/null +++ b/tools/preprocess/Makefile @@ -0,0 +1,7 @@ +PKGIDR ?= . +L4DIR ?= ../.. +include $(L4DIR)/mk/Makeconf + +TARGET = src test doc + +include $(L4DIR)/mk/subdir.mk diff --git a/tools/preprocess/README b/tools/preprocess/README new file mode 100644 index 00000000..ec8f8312 --- /dev/null +++ b/tools/preprocess/README @@ -0,0 +1,38 @@ +`preprocess' -- A C++ preprocessor. +----------------------------------- + +This program is a preprocessor for C++ modules. With this tool, you +write unit-style single-source-file modules in C++ (e.g., foo.cpp), +from which the tool extracts three C++ source files that can then be +processed using the standard C++ compiler toolchain: + +- A public header file (foo.h) + +- A private header file containing all non-public type definitions + (foo_i.h). This facilitates debugging modules that need access to + implementation-specific data structures. + +- An implementation file (foo.cc) + +Features: + +- Modules contain two sections. The "INTERFACE:" section contains + the public interface to the module; the "IMPLEMENTATION:" section + contains everything else. The preprocessor puts "INTERFACE:" + declarations into the public header file and tries to hide + everything else. + +- The preprocessor automatically expands class declarations using + member-function definitions found in the file. Function labelled + PUBLIC, PROTECTED and PRIVATE are put into the corresponding section + of the class. This feature saves typing effort and reduces + duplication. + +- Functions declared "inline" are exported automatically, along with + all the functions and types they need (these dependencies must be + declared in the module file). This feature can be turned off so that + all functions labeled "inline" are hidded and generated out-of-line. + +For more documentation, please refer to the documentation (manpage, +webpage) in directory "doc" (requires Doxygen), or go to the online +documentation at . diff --git a/tools/preprocess/TODO b/tools/preprocess/TODO new file mode 100644 index 00000000..b37eeb99 --- /dev/null +++ b/tools/preprocess/TODO @@ -0,0 +1,44 @@ +BUGS: + +- Namespace declarations are unsupported. + +- Forward-declared, out-of-line defined nested classes are + unsupported. + +- Preprocess does not automatically export declarations of public + variables and static class data to the generated header file. + +- Conditional compilation (preprocessor) is unsupported on file + top-level (preprocessor expressions inside blocks are OK), with the + exception that code commented out using "#if 0" is detected + correctly and deleted. + +IDEAS: + +- Preprocess' source code should be modularized so that the parser can + be used independently from the output generator. This would enable + us writing other interesting applications based on the parsed source + code: + + . Enforce naming conventions + . Rewrite .cpp files according to user-specified rules; this could + eventually be extented so that Preprocess can support a + refactoring browser. + . Aspect weaving (aspect-oriented programming) + . Automatically generate insulation (wrappers, protocol classes, + procedural interface) for a specified class + . Support class invariants, and pre- and postconditions + +- When should we backdate newly-generated files? Obviously, if the + newly generated file and its previous version are the same. There + are circumstances, however, when clients using a generated header + file do not have to be recompiled: + + . Only line-number changes + . "friend" additions + . Relaxation of protection rules + . (and a number of other circumstances; see [Lakos]) + +- Preprocess should be configurable not only via command-line + arguments, but also using a config file. + diff --git a/tools/preprocess/doc/Doxyfile b/tools/preprocess/doc/Doxyfile new file mode 100644 index 00000000..6f12aa88 --- /dev/null +++ b/tools/preprocess/doc/Doxyfile @@ -0,0 +1,192 @@ +# Doxyfile 1.2.18 + +#--------------------------------------------------------------------------- +# General configuration options +#--------------------------------------------------------------------------- +PROJECT_NAME = Preprocess +PROJECT_NUMBER = +OUTPUT_DIRECTORY = +OUTPUT_LANGUAGE = English +EXTRACT_ALL = NO +EXTRACT_PRIVATE = NO +EXTRACT_STATIC = NO +EXTRACT_LOCAL_CLASSES = YES +HIDE_UNDOC_MEMBERS = NO +HIDE_UNDOC_CLASSES = NO +HIDE_FRIEND_COMPOUNDS = NO +BRIEF_MEMBER_DESC = YES +REPEAT_BRIEF = YES +ALWAYS_DETAILED_SEC = NO +INLINE_INHERITED_MEMB = NO +FULL_PATH_NAMES = NO +STRIP_FROM_PATH = +INTERNAL_DOCS = NO +STRIP_CODE_COMMENTS = YES +CASE_SENSE_NAMES = YES +SHORT_NAMES = NO +HIDE_SCOPE_NAMES = NO +VERBATIM_HEADERS = YES +SHOW_INCLUDE_FILES = YES +JAVADOC_AUTOBRIEF = NO +MULTILINE_CPP_IS_BRIEF = NO +DETAILS_AT_TOP = NO +INHERIT_DOCS = YES +INLINE_INFO = YES +SORT_MEMBER_DOCS = YES +DISTRIBUTE_GROUP_DOC = NO +TAB_SIZE = 8 +GENERATE_TODOLIST = YES +GENERATE_TESTLIST = YES +GENERATE_BUGLIST = YES +GENERATE_DEPRECATEDLIST= YES +ALIASES = +#ENABLED_SECTIONS = +MAX_INITIALIZER_LINES = 30 +OPTIMIZE_OUTPUT_FOR_C = NO +OPTIMIZE_OUTPUT_JAVA = NO +SHOW_USED_FILES = YES +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- +QUIET = NO +WARNINGS = YES +WARN_IF_UNDOCUMENTED = YES +WARN_FORMAT = +WARN_LOGFILE = +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- +INPUT = manpage.dox +FILE_PATTERNS = +RECURSIVE = NO +EXCLUDE = +EXCLUDE_SYMLINKS = NO +EXCLUDE_PATTERNS = +EXAMPLE_PATH = +EXAMPLE_PATTERNS = +EXAMPLE_RECURSIVE = NO +IMAGE_PATH = +INPUT_FILTER = +FILTER_SOURCE_FILES = NO +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- +SOURCE_BROWSER = NO +INLINE_SOURCES = NO +REFERENCED_BY_RELATION = YES +REFERENCES_RELATION = YES +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- +ALPHABETICAL_INDEX = NO +COLS_IN_ALPHA_INDEX = 5 +IGNORE_PREFIX = +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- +#GENERATE_HTML = YES +HTML_OUTPUT = +HTML_FILE_EXTENSION = .html +HTML_HEADER = +HTML_FOOTER = +HTML_STYLESHEET = +HTML_ALIGN_MEMBERS = YES +GENERATE_HTMLHELP = NO +CHM_FILE = +HHC_LOCATION = +GENERATE_CHI = NO +BINARY_TOC = NO +TOC_EXPAND = NO +DISABLE_INDEX = YES +ENUM_VALUES_PER_LINE = 4 +GENERATE_TREEVIEW = NO +TREEVIEW_WIDTH = 250 +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- +#GENERATE_LATEX = NO +LATEX_OUTPUT = +LATEX_CMD_NAME = latex +MAKEINDEX_CMD_NAME = makeindex +COMPACT_LATEX = NO +PAPER_TYPE = a4wide +EXTRA_PACKAGES = +LATEX_HEADER = +PDF_HYPERLINKS = NO +USE_PDFLATEX = NO +LATEX_BATCHMODE = NO +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- +#GENERATE_RTF = NO +RTF_OUTPUT = +COMPACT_RTF = NO +RTF_HYPERLINKS = NO +RTF_STYLESHEET_FILE = +RTF_EXTENSIONS_FILE = +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- +#GENERATE_MAN = YES +MAN_OUTPUT = +MAN_EXTENSION = .1 +MAN_LINKS = YES +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- +#GENERATE_XML = NO +XML_SCHEMA = +XML_DTD = +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- +GENERATE_AUTOGEN_DEF = NO +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- +ENABLE_PREPROCESSING = YES +MACRO_EXPANSION = NO +EXPAND_ONLY_PREDEF = NO +SEARCH_INCLUDES = YES +INCLUDE_PATH = +INCLUDE_FILE_PATTERNS = +PREDEFINED = +EXPAND_AS_DEFINED = +SKIP_FUNCTION_MACROS = YES +#--------------------------------------------------------------------------- +# Configuration::addtions related to external references +#--------------------------------------------------------------------------- +TAGFILES = +GENERATE_TAGFILE = +ALLEXTERNALS = NO +EXTERNAL_GROUPS = YES +PERL_PATH = +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- +CLASS_DIAGRAMS = YES +HIDE_UNDOC_RELATIONS = YES +HAVE_DOT = NO +CLASS_GRAPH = YES +COLLABORATION_GRAPH = YES +TEMPLATE_RELATIONS = YES +INCLUDE_GRAPH = YES +INCLUDED_BY_GRAPH = YES +GRAPHICAL_HIERARCHY = YES +DOT_IMAGE_FORMAT = png +DOT_PATH = +DOTFILE_DIRS = +MAX_DOT_GRAPH_WIDTH = 1024 +MAX_DOT_GRAPH_HEIGHT = 1024 +GENERATE_LEGEND = YES +DOT_CLEANUP = YES +#--------------------------------------------------------------------------- +# Configuration::addtions related to the search engine +#--------------------------------------------------------------------------- +SEARCHENGINE = NO +CGI_NAME = +CGI_URL = +DOC_URL = +DOC_ABSPATH = +BIN_ABSPATH = +EXT_DOC_PATHS = diff --git a/tools/preprocess/doc/Makefile b/tools/preprocess/doc/Makefile new file mode 100644 index 00000000..f7058b25 --- /dev/null +++ b/tools/preprocess/doc/Makefile @@ -0,0 +1,34 @@ +L4DIR ?= ../../.. +include $(L4DIR)/mk/Makeconf + +ALL = html man +all:: $(foreach d, $(ALL), stamp-$(d)) + +DIRS = html man latex +.PHONY: $(DIRS) +$(DIRS) : % : stamp-% + +stamp-%: Doxyfile manpage.dox + ( echo "ENABLED_SECTIONS = $*"; \ + for format in latex html man; do \ + echo "GENERATE_$$(echo $$format | tr a-z A-Z) = \ + $$(if [ $$format = $* ]; then echo YES; else echo NO; fi)"; \ + done; \ + cat $<) | doxygen - + if [ "$*" = html ]; then \ + perl -p -i -e 's/preprocess.html#/#/g' html/preprocess.html; \ + fi + if [ "$*" = man ]; then \ + perl -p -i -e 's/preprocess \\- Preprocess - /preprocess \\- /g' \ + man/man1/preprocess.1; \ + fi + touch $@ + +install: stamp-man + -$(INSTALL) -d $(DROPS_STDDIR)/tool/man/man1 + $(INSTALL) -m 644 man/man1/preprocess.1 \ + $(DROPS_STDDIR)/tool/man/man1/preprocess.1 + + +cleanall clean: + rm -rf $(DIRS) stamp-* diff --git a/tools/preprocess/doc/manpage.dox b/tools/preprocess/doc/manpage.dox new file mode 100644 index 00000000..db820e9c --- /dev/null +++ b/tools/preprocess/doc/manpage.dox @@ -0,0 +1,661 @@ +/*! + +\page preprocess Preprocess - A preprocessor for C and C++ modules + +\ifnot man + +Do you hate writing C or C++ header files? + +Do you always forget where to place those inline, +virtual, static, and explicit +modifiers -- to the member-function definition or declaration? + +Do you often find yourself avoiding to factor out a new method because +you also need to add a method declaration to the class declaration in +the header file? + +Do you hate putting inline function into header files, in a special +order? + +If so, Preprocess may be your answer. With this tool, you write +unit-style single-source-file modules in C++, from which it +automatically generates header and implementation files. + +

+


+ +

Table of contents:

+ +
    +
  • \ref SYNOPSIS +
  • \ref DESCRIPTION +
  • \ref OPTIONS +
  • \ref LANGUAGE +
  • \ref MISC +
  • \ref MAKEFILE +
  • \ref BUGS +
  • \ref DOWNLOAD +
  • \ref LIST +
  • \ref AUTHOR +
  • \ref SEE +
+ +

+ +\endif + +\section SYNOPSIS Synopsis + +preprocess -c filename_base + [ -o outfile_base | -s] +
           [ -p prepend ] +
           [ -C source_ext ] + [ -H header_ext ] +
           [ -e tag_list ] +
           [ -i ] [ -t ] + [ -l | -L ] [ -v ] [ -d ] +
           sources... + +\section DESCRIPTION Description + +Preprocess is a preprocessor for C++ modules. With this tool, you +write unit-style single-source-file modules in C++. + +Preprocess essentially does these things (and frees the programmer +from doing them): +

    +
  • Generate header files that contain declarations for public + classes and functions.
  • +
  • Fill in member-function declarations into class declarations.
  • +
  • Export public inline and template functions in correct order + (you need to declare dependencies for inline functions).
  • +
  • Optionally, function marked "inline" can be put + into the implementation file (out of line). This can ease + development (as it temporarily decreases dependencies on header + files that change frequently) and debugging.
  • +
+ +These automatisms lead to source files that are more logically +cohesive (no need to put inline and template functions into a separate +file, in a special order) and saves typing effort. + +Preprocess works by transforming unit-style single-source-file C++ +modules into three output files: public header, private header, and +implementation file. C and C++ comments are preserved during the +transformation, keeping the resulting files readable and making it +possible to run another preprocessor on Preprocess' output. + +\section OPERATION Basic operation + +\htmlonly + + + + + + +
+\endhtmlonly + +Modules contain two sections. The "INTERFACE:" +section contains the public interface to the module; the +"IMPLEMENTATION:" section contains everything else. The +preprocessor puts interface declarations into a public header file and +tries to hide everything else. + +Class definitions deliberately lack declarations for member +functions: Preprocess will add them automatically. Member-function +definitions (in the implementation section) labelled +PUBLIC, PROTECTED and PRIVATE +are put into the corresponding section of the class. This feature +saves typing effort and reduces duplication. + +From this input file (foo.cpp), Preprocess extracts three C++ source +files that can then be processed using the standard C++ compiler +toolchain: + +\htmlonly + +\endhtmlonly + +
+// C++ module -- Preprocess input file
+INTERFACE:
+
+\#include "bar.h"
+
+struct Baz;
+
+class Foo : public Bar
+{
+  Baz* d_baz;
+};
+
+IMPLEMENTATION:
+
+struct Baz
+{
+  int data;
+};
+
+PUBLIC
+int Foo::get_info() 
+{
+  return d_baz->data;
+}
+ +\htmlonly +
+\endhtmlonly + +First, Preprocess generates a public header file (foo.h). This +header file contains all declarations from the interface section, with +class definitions properly expanded to contain member-function +declarations\htmlonly (shown red in the +example on the right side)\endhtmlonly. + +It also contains declarations of non-"static" free +functions found in the implementation section, as well as definitions +for functions declared "inline". Additionally, it +contains all "\#include" directives and function and class +declarations and definitions the inline functions need; these +dependencies need to be declared in the input file. (These features +are not shown in the example\htmlonly on the right side\endhtmlonly.) + +If desired, preprocess can also be instructed to hide all inline +functions (and to generate them out-of-line instead), resulting in a +public header file that better insulates clients from implementation +details. + +\htmlonly + +\endhtmlonly + +
+// Preprocess-generated public header file
+\#ifndef foo_h
+\#define foo_h
+
+\#include "bar.h"
+
+struct Baz;
+
+class Foo : public Bar
+{
+private:
+  Baz* d_baz;
+\htmlonly  \endhtmlonly
+public:  
+  int get_info();\htmlonly  \endhtmlonly
+};
+
+\#endif // foo_h
+ +\htmlonly +
+\endhtmlonly + +Second, a private header file containing all non-public type +definitions (foo_i.h). This file can be used by debugging modules +that need access to implementation-specific data structures. + + This file also contains all inline member functions belonging to +classes declared here. (This feature is not shown in the example.) + + +\htmlonly + +\endhtmlonly + +
+// Preprocess-generated private header file
+\#ifndef foo_i_h
+\#define foo_i_h
+
+struct Baz
+{
+  int data;
+};
+
+\#endif // foo_i_h
+ +\htmlonly +
+\endhtmlonly + +Third, an implementation file (foo.cc). This file starts with +declarations for all free "static" functions (not shown in +the example). Otherwise, it comprises all non-inline function +definitions (and static inline functions). + +\htmlonly + +\endhtmlonly + +
+// Preprocess-generated implementation file
+\#include "foo.h"
+\#include "foo_i.h"
+
+void Foo::get_info() 
+{
+  return d_baz->info();
+}
+ +\htmlonly +
+\endhtmlonly + +\section OPTIONS Options reference + +Output files have names of the following form: +
    +
  • Implementation file: + [prepend]outfile_base[-suffix].source_ext
  • +
  • Public header file: + [prepend]outfile_base.header_ext
  • +
  • Private header file: + [prepend]outfile_base_i.header_ext
  • +
+ +where [prepend] is an optional filename part that can be +specified using -p, outfile_base needs to be +specified using -c, suffix is an optional +suffix that can be specified using the IMPLEMENTATION +directive, and source_ext and header_ext default +to ".cc" and ".h" but can be overridden using -C and +-H, respectively. +
+
-c filename_base
+
Specifies the basename of generated file names that appear in + the output files. This option is mandantory.
+
-o outfile_base
+
Specifies the basename of output files. It defaults to the + value of the -c option.
+
-s
+
Generate one implementation file per source file, using the base + name of the implementation file as outfile_base, and not one + implementation file per suffix specified as + arguments to IMPLEMENTATION directives in the + source files.
+
-p prepend
+
Specifies a prefix for all output file names. This prefix is + prepended to filename_base and can contain directory + separators ("/").
+
-C source_ext
+
Specify the extension of generated implementation files. + Defaults to ".cc".
+
-H header_ext
+
Specify the extension of generated header files. + Defaults to ".h".
+
-e tag_list
+
Enable conditional compilation using the selectors included in + the comma-separated tag_list. This option is + intended to be used in conjunction with the -s + option. See Section + \ref CONDITIONAL \if man CONDITIONAL COMPILATION \endif + for details on this option.
+
-t
+
Truncate to size 0 output files for which Preprocess generates + no output. This option supresses even \#include + directives in generated source files that are otherwise empty, + resulting in increased compilation speed for these files.
+
-i
+
Generate inline code. If this option is not + given, all code (including code marked "inline") + is generated out-of-line.
+
-l
+
Avoid generating \#line directives in output + files. If this option is not given, \#line will be + generated by default.
+
-L
+
Avoid generating \#line directives in header files only. + Using this option can speed up builds because the contents of + header files change less frequently, as \#line + directives for (member) function declarations do not have to be + updated every time its definition in the source module changes + its absolute position. (Of course, this assumes that the time + stamp of header files are updated only when the contents of the + files change. See Section + \ref MAKEFILE \if man EXAMPLE MAKEFILE FRAGMENT \endif + for a possible way to + do this.)
+
-v
+
Be verbose: Print results of preprocess' parser pass.
+
-d
+
Be verbose: Print a diagnostic when dropping a section in + conditional-compilation mode (Option -e).
+
+ + +\section LANGUAGE Language directives + +Preprocess understands a number of language directive that control its +behavior. +
+
INTERFACE: +
Starts an interface section. Every declaration from such a + section will be copied to the public header file. Class + declarations found here (``public class'') will be completed + with member-function declarations for member functions found in + IMPLEMENTATION sections. + \htmlonly

\endhtmlonly + Function definitions are not allowed in this section. + +

IMPLEMENTATION: +
Starts an implementation section. Preprocess tries to hide + declarations found in these sections in the internal header + file and in the implementation file, as follows: +
+
Class declarations (``private classes'') +
(subject to member-function-declaration completion + as with those in + INTERFACE: sections) end up in the internal + header file -- except if a public inline function of a + public class depends on the private class, in which case + the private class' declaration will be put into the + public header file. +
Include directives +
underlie the same rules as class declarations. +
Function definitions +
are usually held in the implementation file. Public + inline functions, private inline + functions needed by a public inline function, and + functions subject to template instatiation are exported + to the public header file. Other inline functions + (except static non-member inline functions) are put into + the private header file. +
Other code (e.g., variable definitions) +
is put into the implementation file. +
+ +
PUBLIC, PRIVATE, and PROTECTED +
specify member-function visibility. + +
explicit, static, and virtual +
specify member-function attributes. The attributes will be + copied to the automatically-created member-function + declarations in class declarations (and removed for the actual + function definition, as C++ requires). + +
inline +
specifies inline functions. This attribute will be retained + for function definitions (but deleted for + automatically-created member-function declarations, as C++ + requires). (Inline functions will be + exported subject to the rules defined above.) + +
inline NEEDS [dependencies, + ... ] +
like inline, but additionally specifies types, + functions, and \#include statements that this + inline function depends on and that consequently need to be + exported as well, in front of this inline function. Preprocess + reorders definitions such that all dependencies are defined + before the inline function. + \htmlonly

\endhtmlonly + Example: +

inline NEEDS["foo.h", some_func, Some_class,
+             Some_other_class::member_func]
+int
+foo ()
+{ }
+
+
+ +\subsection ADVANCED Language directives for advanced use + +
+
IMPLEMENTATION [suffix]: +
Starts an implementation section with code that will be put + into a nonstandard output file. Instead of landing in + outfile_base.cc, the code ends up in + outfile_base-suffix.cc. + This directive is useful if there are several input files that + together make up one input module (which are fed to Preprocess + at the same time and which share one public and one private + header file). + + (This form of the IMPLEMENTATION directive works only if + neither the -s (no-suffix) nor the -e + (conditional compilation) options are used. See Section + \ref CONDITIONAL \if man CONDITIONAL COMPILATION \endif + for information on conditional compilation.) + +
EXTENSION class classname { + ... }; +
Extends the definition of class classname (which + usually appears in another input file) with more members. This + clause is usually used when a class can be configured with + several alternative extensions, for example to provide + portability across architectures. + +
IMPLEMENT +
is a member-function attribute that specifies that the member + function's declaration should not be copied to the + class declaration. Use this attribute to implement an + interface that is already declared in the class declaration. + +
inline NOEXPORT +
specifies inline functions that will not be exported via the + public header file even if it is a publibly-visible function. + Instead, the function definition will end up in the + implementation file. + +
inline ALWAYS_INLINE +
specifies a functions that is generated as an inline function + even if the -i option is not used. Use this + specifier for functions that absolutely must be inline even in + debugging builds. + +
+ +\subsection CONDITIONAL Conditional compilation + +Conditional compilation is a Preprocess mode that is enabled by using +the "-e tag_list" option. + +
+
INTERFACE [tag_expression]:
+
IMPLEMENTATION [tag_expression]:
+
A tag_expression is a logical expression with negation (!), + conjunction (-), disjunction (,), and one level of parentheses + ({ and }), using selector tags as its atoms. The + INTERFACE or IMPLEMENTATION section + is included in the output only if it is true using the + selectors specified in tag_list. +
+
+ +Examples: + +
INTERFACE [a,b]:
+// This section is used whenever a or b is contained in the tag_list
+
+INTERFACE [a-b]: 
+// This section is used whenever a and b are contained in the tag_list
+
+INTERFACE [a,b-c]:
+// This section is used whenever a, or b and c are 
+// contained in the tag_list
+
+INTERFACE [!a]:
+// This section is used whenever a is not contained in the tag_list
+
+INTERFACE [{a,b}-c]:
+// This section is used whenever a and c, or b and c are 
+// contained in the tag_list
+
+INTERFACE [!a,b-c]:
+// This section is used whenever a is not contained in the tag_list,
+// or b and c are contained in the tag_list
+ +\section MISC Usage hints + +When you use Preprocess, there are a few things you need to keep in +mind. +
    +
  • Preprocess currently does not support namespaces and nested + classes. It is possible to use namespaces and nested classes + defined elsewhere (for example, in a library header file), but + you cannot define new namespaces and nested classes. + \htmlonly

    \endhtmlonly +

  • Preprocess copies function declarations for publicly visible + functions to the public header file. If you use user-defined + types in function signatures, you need to "\#include" + the corresponding header files (or add forward declarations) in + the "INTERFACE:" section of your module. Private + inline functions (which might end up in the public header file) + need to specify their include dependencies in a "NEEDS[]" + clause. + \htmlonly

    \endhtmlonly + Also, if you use names declared in an (externally-defined) + namespace (such as namespace "std"), you must + specify the fully-qualified name (including the namespace) in + the function signature (unless you use a "using + namespace" directive in the "INTERFACE:" + section, which is not recommended). + \htmlonly

    \endhtmlonly +

  • Don't forget to specify inline functions required by other + inline functions in the latter's "NEEDS" clause. + Otherwise, Preprocess cannot guarantee the correct + inline-function order in the output, and you may get compiler + warnings like ``inline function is used but not defined.'' This + problem is reinforced when using private inline functions, + because Preprocess moves them out of the public header file + (into the private header file) unless a public function's + "NEEDS" clause requires them. +
+ +\section MAKEFILE Example Makefile fragment + +\htmlonly + + + + +\htmlonly +
+\endhtmlonly + +This is an example fragment from a Makefile (for GNU Make) that +generates *.cc, *.h, and *_i.h +files on the fly. It only updates the generated files if they +actually change; that is, if you change something in the +implementation section that does not influence the header files, they +will not be updated, avoiding recompilation of files that depend on +them. + +This Makefile fragment needs GNU Make and the move-if-change script that only updates a +target if it is different from the source. + +This example assumes that you do not use the +IMPLEMENTATION[suffix] +directive. If you do plan using this directive, a more elaborate +mechanism is needed, such as the one used in the Makefiles for the +Fiasco microkernel. + +\htmlonly + +\endhtmlonly +
PREPROCESS = preprocess
+
+.PRECIOUS: stamp-%.ready
+stamp-%.ready: %.cpp
+	\$(PREPROCESS) -i -o new_\$* -c \$* \$<
+	./move-if-change new_\$*.h \$*.h 
+	./move-if-change new_\$*_i.h \$*_i.h 
+	./move-if-change new_\$*.cc \$*.cc 
+	touch \$@
+
+%.cc: stamp-%.ready
+        @[ -e \$@ ] || { rm -f \$<; \$(MAKE) \$<; }
+
+%.h: stamp-%.ready
+        @[ -e \$@ ] || { rm -f \$<; \$(MAKE) \$<; }
+
+\%_i.h: stamp-%.ready
+        @[ -e \$@ ] || { rm -f \$<; \$(MAKE) \$<; }
+\endhtmlonly + + + +\section BUGS Limitations and ideas for future extensions + +

Bugs

+ +
    +
  • Namespaces and nested classes currently are unsupported. +
  • The \#line directives Preprocess generates sometimes + are offset plus/minus one or two lines to the real code. +
  • Preprocess doesn't really understand preprocessor constructs + besides \#include and \#if 0; it just + copies all other direcitives into the output as it finds them. + That makes it easy for you to shoot yourself into the foot. +
+ +

Ideas for future extensions

+ +
    +
  • Generate HTML documentation for modules/classes. +
  • Auto-generated getters and setters for attributes +
  • Auto-generate insulation (wrappers, protocol classes, + procedural interface) for any given class. +
  • Transform input .cpp files into new + .cpp files, refactoring or renaming code on the + fly. +
  • Aspect-oriented programming: Weave in extensions (``aspects'') + to member functions. Aspects can be + synchronization or debugging checks, for example. +
  • Support for class invariants (design by contract) +
  • Enforce a set of naming conventions. +
+ +\section DOWNLOAD Download + +Preprocess is free software licensed under the GNU General Public +License. Its implementation language is Perl, so you need a Perl5 +interpreter to run it. + +You can download Preprocess as CVS module "preprocess" +from the DROPS project's remote-CVS server. Please refer to the
download +instructions on DROPS' website. + +\section LIST Mailing list + +There is a mailing list to which CVS-commit messages for changes made +to preprocess are posted. Please ask me if you would like to be put +on this list (see Section \ref AUTHOR \if man AUTHOR \endif). + +New releases are periodically announced on the Freshmeat +website. If you are a registered Freshmeat user, you can subscribe to these +release announcements\if man at +http://freshmeat.net/subscribe/36508/\endif. + +\section AUTHOR Author + +Michael Hohmuth + +\section SEE See also + +move-if-change(1) shell script\if man +: http://os.inf.tu-dresden.de/~hohmuth/prj/preprocess/move-if-change +\endif + +\if man +Preprocess +project web page +: http://os.inf.tu-dresden.de/~hohmuth/prj/preprocess/ +\endif + +Preprocess was originally written for the Fiasco microkernel\if man +: http://os.inf.tu-dresden.de/fiasco/ +\endif. + +*/ diff --git a/tools/preprocess/src/Makefile b/tools/preprocess/src/Makefile new file mode 100644 index 00000000..5ed46e5f --- /dev/null +++ b/tools/preprocess/src/Makefile @@ -0,0 +1,25 @@ +# +# Makefile for the preprocess sources +# + +# scan the L4 global configuration file +L4DIR ?= ../../.. +include $(L4DIR)/mk/Makeconf + +-include Makeconf.local + +TARGET = preprocess + +all:: $(TARGET) + +install:: all + -$(INSTALL) -d $(DROPS_STDDIR)/tool/bin + $(INSTALL) -m 755 $(TARGET) $(DROPS_STDDIR)/tool/bin + +clean:: +# $(RM) $(TARGET) $(OBJS) tmp.* + +cleanall:: clean + $(RM) *~ .*.d + +#include $(DEPS) diff --git a/tools/preprocess/src/preprocess b/tools/preprocess/src/preprocess new file mode 100755 index 00000000..345013ac --- /dev/null +++ b/tools/preprocess/src/preprocess @@ -0,0 +1,1799 @@ +#! /usr/bin/perl -w +# -*- perl -*- + +# +# Please find extensive documentation of this program at +# +# + +# Things this script does: +# +# - Expand class declarations as necessary using member-function +# definitions found in the file. Function labelled PUBLIC, +# PROTECTED and PRIVATE are put into the corresponding section of +# the class. +# +# - Put "INTERFACE:" regions in public header file. +# +# - Put "inline" functions and all types they need into public header +# file as well. +# +# - Put all remaining, private types and their inline functions into a +# separate header file. This file can be used by a debugger +# interface to display the data. +# +# - Place include directives to top of public header file and private +# header file. +# + +# +# Declarations +# + +require 5.006; +use Getopt::Std; +use strict; + +sub print_expand($); +sub print_funcdecl($); +sub print_funcdef($); +sub print_classdecl($); +sub print_code($); +sub func_prototype($); + +# +# Get options +# + +our $opt_c = ''; # Base name for generated include directives +our $opt_o = ''; # Base name of output files (defaults to -c, + # overrides -p) +our $opt_p = ''; # Prepend to base name of output files (-c) +our $opt_h = ''; # Name of public header; overrides -c +our $opt_i = 0; # Doing inlines? +our $opt_v = 0; # Verboseness? +our $opt_l = 0; # Avoid generating #line directives? +our $opt_L = 0; # Avoid generatung #line dirs in headers only? +# Support for new style FIASCO config +our $opt_e = ''; # List of part tags +our $opt_s = 0; +our $opt_d = 0; # verbose drop + +our $opt_w = 0; # warn if no inline code for needs is found + +# Added 2003.01.12 by RCB +# Support for changing the names of headers +our $opt_H = "h"; # Default extenstion for header files +our $opt_C = "cc"; # Default extention for source files +our $opt_t = 0; + +getopts('e:o:c:p:h:H:C:ivlLsdwt'); + +sub usage +{ + print < [-C ] + [-e ] [-h ] [-H ] + [-o ] [-p ] +OPTIONS + -c Base name for generated include directives, generated + header files, and generated source files. + -C File extension for generated source files (default 'cc'). + -d Verbose drop sections (only in conjunction with -e). + -e Use explicit section selection, and set the given tag + list. is a qouted and space separated list of + tags that should be enabled. (Useful in conjunction + with -s) + -h Name of generated public header (overrides -c) + -H File extension for generated header files (default 'h'). + -i Do inlines, make inline functions real inline. + -l Avoid generating #line directives. + -L Avoid generating #line directives in headers only. + -o Base name for generated source files (defaults to -c, and + overrides -p) + -p Prefix for names of output files. + -s Generate a single source file per .cpp file (not a file + per section). + -t Truncate empty implementation files to zero length (so + that even the includ directives are ommitted) + -v Be verbose (very). + -w Do warnings. +EOF +} + +if ($opt_c eq '') + { + usage; + die "Need to specify option -c Classfile_basename;"; + } + +my $incfile_base = $opt_c; +my $public_base = (($opt_h eq '') ? $incfile_base : $opt_h); +my $outfile_base; +my $headerfile_base; +my $doing_inlines = $opt_i; +my $verbose = $opt_v; +my $doing_linenumbers = (! $opt_l) && (! $opt_L); +my $wno_inline = $opt_w; +my $status = 0; + +my $parts_re = ''; +my %parts = ( '{' => '(', + '}' => ')', + ',' => '||', + '-' => '&&', + '|' => '|', + '&' => '&', + '(' => '(', + ')' => ')', + '!' => '!'); + +my $ARGV = $ARGV[0]; + +if ($opt_e ne '') + { + foreach my $p (split(' ',$opt_e)) + { + $parts{$p} = '1'; + } + } + +# Added 2003.01.12 by RCB +# Support for changing the names of headers +my $source_ext = $opt_C; +my $header_ext = $opt_H; + +if ($opt_o eq '') + { + $outfile_base = $opt_p . $incfile_base; + $headerfile_base = $opt_p . $public_base; + } +else + { + $outfile_base = $opt_o; + $headerfile_base = $outfile_base; + } + +# +# Variable initializations +# +parse_init(); + +our $print_indent = 0; +clear_head(); + +my %classes = (); +my %sections = (); +my %impl_parts = (); +my %includes = (); +my @comments = (); +my %public_inline = (); +my %private_inline = (); +my %unit_inline = (); +my @inline_order_public = (); +my @inline_order_private = (); +my @inline_order_unit = (); + +# +# Parse input file +# + +parse_file (); + +# +# Print header file +# + +# Fixup incfile_base preproc macro if it contains invalid chars. +my $incfile_base_macro; + +$incfile_base_macro = $incfile_base; +$incfile_base_macro =~ s/[+-]/_/g; + +open(OUT, ">${headerfile_base}.$header_ext") + || die "Cannot open ${headerfile_base}.$header_ext for writing!"; +print OUT "// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*-\n\n"; +print OUT "#ifndef ${incfile_base_macro}_$header_ext\n" . + "#define ${incfile_base_macro}_$header_ext\n"; + +foreach my $i (grep {$_->{type} eq 'include'} @{$sections{"INTERFACE"}}) + { + print_code $i; + } + +print_head ("\n" . + "//\n" . + "// INTERFACE definition follows \n" . + "//\n\n"); + +foreach my $i ( (grep {$_->{type} eq 'classdef' + && $_->{syntax} eq 'forwarddecl'} + @{$sections{"INTERFACE"}}), + (grep {$_->{type} ne 'classdef' || $_->{syntax} ne 'forwarddecl'} + @{$sections{"INTERFACE"}}) ) + { + if ($i->{type} eq 'code') + { + print_code $i; + } + elsif ($i->{type} eq 'classdef') + { + print_classdecl ($i); + } + } + +foreach my $i (grep {$_->{type} eq 'function' && $_->{class} eq '' + && ! $_->{static}} + @{$sections{"IMPLEMENTATION"}}) + { + print_funcdecl $i; + } + +my @public_templates = grep + { + $_->{type} eq 'function' && $_->{template} ne '' # template func + && $_->{fully_specialized_template} eq '' + && ! defined $public_inline{$_} # not public inline -- handled elsewhere + && ($_->{visibility} eq "free" # free func + || ($_->{class} ne '' # or member func of public or published class + && ($classes{$_->{class}}->{section} eq 'INTERFACE' + || defined $public_inline{$classes{$_->{class}}}))) + } + @{$sections{"IMPLEMENTATION"}}; + +my $impl_includes_imported = 0; + +if (scalar keys %public_inline || scalar @public_templates) + { + if (scalar @public_templates) + { + $impl_includes_imported = 1; + } + + clear_head(); + print_head + ("\n" . + "//\n" . + "// IMPLEMENTATION includes follow " . + "(for use by inline functions/templates)\n" . + "//\n\n"); + + foreach my $i (grep { $_->{type} eq 'include' + && ($impl_includes_imported || $_->{inline}) } + @{$sections{"IMPLEMENTATION"}}) + { + print_code $i; + } + + clear_head(); + print_head + ("\n" . + "//\n" . + "// IMPLEMENTATION of inline functions (and needed classes)\n" . + "//\n\n"); + + print_inlines (@inline_order_public); + } + +clear_head(); +print_head ("\n" . + "//\n" . + "// IMPLEMENTATION of function templates\n" . + "//\n\n"); +foreach my $i (@public_templates) + { + print_funcdef $i; + } + +clear_head(); + +print OUT "\n#endif // ${incfile_base_macro}_$header_ext\n"; +close OUT; + +# +# Print "internal data structures" header file +# + +open(OUT, ">${outfile_base}_i.$header_ext") + || die "Cannot open ${outfile_base}_i.$header_ext for writing!"; +print OUT "// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*-\n\n"; +print OUT "#ifndef ${incfile_base_macro}_i_$header_ext\n" . + "#define ${incfile_base_macro}_i_$header_ext\n"; + +foreach my $i (grep { $_->{type} eq 'include' } + @{$sections{"IMPLEMENTATION"}}) + { + print_code $i; + } + +foreach my $i + ( (grep {$_->{type} eq 'classdef' && $_->{syntax} eq 'forwarddecl'} + @{$sections{"IMPLEMENTATION"}}), # first all forward declarations, + (grep {$_->{type} eq 'classdef' && $_->{syntax} ne 'forwarddecl'} + @{$sections{"IMPLEMENTATION"}}) ) # then all other class / type decls + { + print_classdecl ($i); + } + + +# XXX should we print #defines here? + +print_head ("\n" . + "//\n" . + "// IMPLEMENTATION of inline functions follows\n". + "//\n\n"); +print_inlines (@inline_order_private); + +clear_head(); +print_head ("\n" . + "//\n" . + "// IMPLEMENTATION of function templates\n" . + "//\n\n"); +foreach my $i (grep + { + $_->{type} eq 'function' && $_->{template} ne '' + && $_->{fully_specialized_template} eq '' + && ! defined $public_inline{$_} + && ! defined $private_inline{$_} + && ($_->{visibility} eq 'static' + || ($_->{class} ne '' + && ($classes{$_->{class}}->{section} ne 'INTERFACE' && + !defined $public_inline{$classes{$_->{class}}}))) + } @{$sections{"IMPLEMENTATION"}}) + { + print_funcdef $i; + } + +clear_head(); + +print OUT "\n#endif // ${incfile_base_macro}_i_$header_ext\n"; +close OUT; + +$doing_linenumbers = (! $opt_l); + +# +# Print implementation file(s) +# + +foreach my $part (keys %impl_parts) + { + my $filename = $outfile_base.($part eq '' ? '' : ('-' . $part)) . ".$source_ext"; + my $empty = 1; + #print "==> $filename\n"; + open(OUT, ">$filename") || die "Could not open $filename for writing!"; + print OUT "// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*-\n\n"; + print OUT "#include \"${public_base}.$header_ext\"\n" . + "#include \"${incfile_base}_i.$header_ext\"\n\n"; + + foreach my $i (grep {$_->{type} eq 'function' && $_->{class} eq '' + && $_->{static}} + grep {$_->{part_ext} eq $part} @{$sections{"IMPLEMENTATION"}}) + { + print_funcdecl $i; + } + + # Print unparsed code first -- make private inline functions see + # static variables + + foreach my $i (grep {$_->{part_ext} eq $part + && $_->{type} eq 'code'} + @{$sections{"IMPLEMENTATION"}}) + { + print_code $i; + $empty = 0; + } + + print_inlines (grep {$_->{part_ext} eq $part} @inline_order_unit); + + foreach my $i (grep {$_->{part_ext} eq $part + && $_->{type} eq 'function'} + @{$sections{"IMPLEMENTATION"}}) + { + next if $i->{template} ne '' + && $i->{fully_specialized_template} eq ''; + + print_funcdef $i; + $empty = 0; + } + + truncate OUT,0 if $empty && $opt_t; + close OUT; + } + + +exit 0; + +############################################################################# + +# +# Parser code. +# + +my $s_once; # Regexp for whitespace; the \001 stuff is for comments +my $s; # Zero or more whitespace +my $identifier; # Identifier +my $operator_name; # Operator name +my $paren_group; +my $paren_expr; +my $tparen_group; +my $template; # Template declaration tag +my $template_arg; # Template argument list + +my $lineno; # current line to be parsed +my $blockfile; # file that contains the currently pares block +my $blockstart; # first line of the current block +my $current_section; # current section +my $current_part; +my $current_part_ext; +my @ifstack; # stack of #if clauses + + +sub parse_init # Initialize parser variables. +{ + # Regexp for whitespace; the \001 stuff is for comments + $s_once = '(?:[\n\s]|\001[0-9]+\001)'; + + # Zero or more whitespace + $s = $s_once . '*'; + + # Identifier + $identifier = "(?:[A-Za-z_][A-Za-z_0-9]*)"; + + # Operator name + $operator_name = "(?:operator$s(?:" + .'(?:[~,]|[+\-*/%^&|!=<>]=?|[<>]{2}=?|[&|+\-]{2}|->\*?' + .'|\(\)|(?:new|delete)?'.$s.'\[\])'."|$identifier))"; + + + $paren_group = qr{ + \( + (?: + (?> [^()]+ ) # Non-parens without backtracking + | + (??{ $paren_group }) # Group with matching parens + )* + \) + }x; + + $paren_expr = qr{ (?> $paren_group | [^()]+ )* }x; + + # Template argument list -- similar to paren_group above + $tparen_group = qr { < (?: (?> [^<>]+ ) | (??{ $tparen_group }) )* > }x; + + # Template argument list + $template_arg = qr{ (?> $tparen_group) }x; + + # Template declaration tag + $template = qr{template$s$template_arg$s}; + +} + +sub match_e_opt +{ + my $tag = shift; + my $cp = ''; + + my $t = '\(\)&|,\{\}!-'; + my $orig_tag = $tag; + + while ($tag =~ /^\s*([$t]|(?:[^\s$t]+))\s*(.*?)$/) + { + my $r = $parts{$1}; + $cp .= defined $r ? $r : 0; + $tag = $2; + } + + my $match = eval $cp; + #print "TAG: $tag -> $cp = $match\n"; + if (!defined $match) + { + die "${ARGV}:$lineno: error: syntax error in tag '$tag'\n"; + } + + if (($verbose || $opt_d) && (!defined $match || !$match)) + { + print "Drop SECTION: [$orig_tag] from". + " file ${ARGV}\n"; + } + + return $match; +} + +sub parse_file +{ + $lineno = 0; + @ifstack = (); + + $current_section = "IMPLEMENTATION"; + $current_part = ""; + my $skip_to_next_section = 0; + + NEXTLINE: + while (1) + { +#print "PARSED: $_\n"; + $_ = ''; + $blockstart = $lineno + 1; + $blockfile = $ARGV; + + MORE: + while (1) + { + if (! read_more()) + { + last NEXTLINE; + } + + if (/^$s\/\/-[\s\n]*$/s) + { + handle_source_code (); + next NEXTLINE; + } + + if (s/^($s) + (?:(INTERFACE + | IMPLEMENTATION) + (?:$s \[ $s ([A-Za-z0-9_,\{\}!\s&|\(\)-]+) $s \] $s)? : ) + /$1/sx) + { + check_empty_ifstack(); + $skip_to_next_section = 0; + $current_section = $2; + if ($opt_e ne '' || $current_section eq "IMPLEMENTATION") + { + if (defined $3) + { + $current_part = $3; + if ($opt_e ne '') + { + $skip_to_next_section = !match_e_opt($current_part); + next NEXTLINE if $skip_to_next_section; + } + } + else + { + $current_part = ''; + } + } + else + { + if (defined $3 && $opt_h ne $3) + { + die "${ARGV}:${lineno}: all INTERFACE arguments and " + . "option -h must be consistent;" + if ($opt_h ne ''); + + $public_base = $3; + $opt_h = $3; + if ($opt_o eq '') + { + $headerfile_base = $opt_p . $public_base + } + } + } + handle_source_code (); + next NEXTLINE; + } + elsif ($skip_to_next_section) + { + next NEXTLINE; + } + + # Preprocessor directive? + if (/^$s\#/s) + { + while (/\\\n$/s) + { + last NEXTLINE if ! read_more(); + } + + handle_preproc(); + next NEXTLINE; + } + + next NEXTLINE if ignoring(); + + # Read until we can decide what we have: Read till next block end + # or semicolon. + if (/\{/) + { + # Have a block. + my $foo = $_; + do {} while ($foo =~ s/\{[^\{\}]*\}//sg); # kill blocks + if ($foo =~ /\{/) + { +#print "MORE: $foo\n"; + next MORE; # Still unfinished blocks. + } + } + elsif (! /;/) # no unclosed blocks & semicolon? + { + next MORE; + } + + # Type declaration? + if (/^$s(?:$template)?(enum|struct|class|typedef)/s) + { + my $syntax = $1; + + if (/^$s(?:$template)? + (?:enum|struct|class) + $s ($identifier (?:$s $template_arg)?) + $s (?::(?!:)|\{)/sx) + { + # Have a block -> this is a definition. + + my $name = $1; + + if (/^(.*)(\}.*)$/s) + { + my $class = { name => $name, + syntax => $syntax, + pretext => $1, + posttext => $2 }; +#print "CLASS " . $class->{name} . ">" .$class->{pretext} . "###" . $class->{posttext}; + handle_classdef ($class); + } + } + else + { + # No block or no name -- handle as declaration. + if (/^$s(?:$template)?(?:enum|struct|class)$s\{/s) + { + # no name but block -- make this a global variable decl. + handle_source_code (); + } + elsif (/^$s(?:$template)?(?:enum|struct|class)/s) + { + # no block -- this seems to be a forward + # decl. or a variable decl. + + if (/^$s(?:$template)?(?:enum|struct|class)$s + ($identifier) $s ;/sx) + { + my $class = { syntax => 'forwarddecl', + name => $1 }; + handle_classdef ($class); + } + else + { + handle_source_code (); + } + } + elsif (/^${s} typedef \b /sx) # It's a typedef + { + # strip off function args and array spec + my $l = $_; + $l =~ s/; $s $//sx; + $l =~ s/\([^\)]*\) (?:${s}const)? $s $//sx; + $l =~ s/(?: \[ [^\[]* \] $s | \) $s )+ $//sx; + $l =~ m/($identifier) $s $/sx; + + my $class = { syntax => 'typedef', + name => $1 }; + handle_classdef ($class); + } + else + { + die "${ARGV}:$lineno: Parse error"; + } + } + + next NEXTLINE; + } + + # Type declaration extension? + if (/^$s EXTENSION $s (?:struct|class) $s ($identifier) + $s (?::(?!:) $s ([^\{]*))?\{ (.*) \} $s ; $s $/sx) + { + my $super = $2; + my $name = $1; + my $string = $3; + + if (! exists $classes{$name}) + { + die "${ARGV}:$lineno: Class extension for undefined class " . + $name; + } + + # XXX XXX we should not handle line directives here -- + # this is the job of the output functions. However, as + # we don't generate a new codechunk for this extension, + # we just add the extension's line number here. + + if ($doing_linenumbers) + { + $classes{$name}->{pretext} .= + "\n#line " . $blockstart . " \"" . $ARGV . "\"\n"; + } + + my $txt = \($classes{$name}->{pretext}); + + if (defined $super) + { + if ($$txt =~ /^([^\{]*)/sx) + { + my $pre = $1; + if ($pre =~ /^.*:(?!:)(.*)$/sx) + { + $$txt =~ s/^$pre/$pre\n, $super/s; +# print "ADD super classes: , $super\n"; + } + else + { + $$txt =~ s/^$pre/$pre\n: $super/s; + } + } + } + + $classes{$name}->{pretext} .= "private:\n" . $string; + + next NEXTLINE; + } + + # Member function definition? + if (/^([^\{\(]*?) # pretext, maybe w template decl tag + \b ($identifier (?: $s :: $s $identifier)*) # class name + ($s $template_arg)? # optional class-template args + $s :: $s + ((?:$operator_name | (?: ~? $identifier )) # member name + (?:$s $template_arg)?) # optional member-template args + $s ( \( (?: [^\)] | \([^\)]*\) )* \) [^:\{=]* ) # arg list + ((?:\{|:.*\{).* | (?:$s = $s 0 $s ;))$/sx) # initializer ':' and body '{' or pure virtual + { + my ($pretext, $class, $templateargs, $name, $args, $posttext) + = ($1, $2, (defined $3 ? $3 : ''), $4, $5, $6); +#print "P<$pretext> C<$class> T<$templateargs> N<$name> A<$args> P<$posttext>\n"; + # Canonify operator names + $name =~ s/(?<=\w)(?:$s_once)+(?=\W)//gs; + $name =~ s/(?<=\W)(?:$s_once)+(?=\w)//gs; + $name =~ s/(?:$s_once)+/ /gs; + # Canonify class name + $class =~ s/$s//gs; + my $memberfunction = { class => $class, + name => $name, + templateargs => $templateargs, + pretext => $pretext, + args => $args, + posttext => $posttext }; + handle_function ($memberfunction); + next NEXTLINE; + } + + # Free function definition? + if (/^([^\{]*) # pretext, maybe w template decl tag + \b ($operator_name | $identifier) # function name + ($s $template_arg)? # optional template args + $s( \( $paren_expr \) [^:\{\(\)=]*) # arg list + (\{.*)$/sx) # body + { + my $function = { class => '', + name => $2, + templateargs => (defined $3 + ? $3 : ''), + pretext => $1, + args => $4, + posttext => $5 }; + handle_function ($function); + next NEXTLINE; + } + + handle_source_code (); + next NEXTLINE; + } + } + + if (! /^$s$/s) + { + $verbose && print "EOF: " . $_ . "\n"; + die "${blockfile}:$blockstart: Unexpected end of file in block starting here;"; + } + +} + +sub read_more () # Read one more line of code. Stow away + # comments and character constants +{ + # Get a line without comments. + while (1) + { + if (eof(INPUT)) # Reset line numbering. + { + check_empty_ifstack(); + $lineno = 0; + do + { + my $file; + return 0 unless $file = shift @ARGV; + $ARGV = $file; + open(INPUT, $ARGV) || die "Cannot open $ARGV for reading!"; + if ($opt_s) + { +# print "FILE: $ARGV\n"; + my $part_ext = ''; + if ($ARGV =~ /^(?:.*\/)?(.+)$/ && $1 =~ /(?:[^-]*)-(.*)\..*/) + { + $part_ext = $1; + } + $current_part_ext = $part_ext; + $impl_parts{$part_ext} = 1; +# print "PART: '$part_ext'\n"; + } + print "read file: '$ARGV'\n" if $verbose; + } + while(eof(INPUT)); + } + + $lineno++; + + my $line = ; + + if (! defined $line) + { + return 0; + } + + $_ .= $line; + + # Save comments and strings in @comments array. Save strings + # first to catch strings with comment-like contents. + my $number = @comments; + + # We don't touch strings in NEEDS[], neither #includes! Save now -- + # restore later. + my $saved = ''; + if (s/(^$s \# $s include.*$ + | NEEDS $s \[[^\]]* ) + /\003/sx) + { + $saved = $1; + } + + while (s,(\'(?:\\.|[^\']|\\[0-7]+)\'),\002$number\002,s) + { + push @comments, $1; + $number++; + } + +# while (s,(\"(?:[^\"]|(?<=\\)\")*\"),\002$number\002,s) + while (s,(\"(?:[^\\\"]|\\.)*\"),\002$number\002,s) + { + push @comments, $1; + $number++; + } + + if ($saved ne '') + { + s/\003/$saved/s; + } + + while (s|(//(?!-\s*\n).*)$|\001$number\001|m) # Do not match magic "//-" + { # The \001 signifies whitespace. + push @comments, $1; + $number++; + } + + while (s|(/\*.*\*/)|\001$number\001|s) + { + push @comments, $1; + $number++; + } + + if (! /\/\*/) + { + last; + } + } + + return 1; +} + +sub label_chunk +{ + my ($codechunk,$type) = @_; + + $codechunk->{type} = $type; + $codechunk->{section} = $current_section; + $codechunk->{string} = $_; + $codechunk->{part} = $current_part; + $codechunk->{part_ext} = $opt_s ? $current_part_ext : $current_part; + + $impl_parts{$current_part} = 1 unless $opt_s; + + $codechunk->{line} = $blockstart; + $codechunk->{file} = $ARGV; + $codechunk->{printed} = 0; + + push @{$sections{$current_section}}, $codechunk; +} + +sub ignoring +{ + foreach my $i (@ifstack) + { + if ($i->{value} == 1) + { + return 1; + } + } + + return 0; +} + +sub handle_preproc +{ +# if ($codeblock->{string} =~ /^$s\#\s*(if|endif|else|elif)/) +# { +# die "${ARGV}:${lineno}: Conditional compilation not supported;"; +# } + + if (/^$s\#\s*if\s+0${s}$/) + { + push @ifstack, { value => 1, file => ${ARGV}, line => $lineno }; + $verbose && print "IF 0: " . ignoring() . "\n"; + return; + } + elsif (@ifstack && /^$s\#\s*if(def|ndef)?\s/) + { + push @ifstack, { value => 0, file => ${ARGV}, line => $lineno }; + $verbose && print "IF: " . ignoring() . "\n"; + return if ignoring(); + } + elsif (@ifstack && /^$s\#\s*(else|elif)/) + { + my $ignoring = ignoring(); + my $i = pop @ifstack; + $i->{value} = -$i->{value}; + push @ifstack, $i; + $verbose && print "ELSE/ELIF: " . ignoring() . " ($ignoring)\n"; + return if $ignoring; + } + elsif (@ifstack && /^$s\#\s*endif/) + { + my $ignoring = pop @ifstack; + $verbose && print "ENDIF: " . ignoring() . "\n"; + return if ignoring() || $ignoring->{value}; + } + elsif (/^$s\#\s*include${s}([\"<][^\">]+[\">])/) + { + my $codeblock; + $codeblock->{name} = $1; + $codeblock->{inline} = 0; + + $includes{$codeblock->{name}} = $codeblock; + + label_chunk ($codeblock, "include"); + + $verbose && print "INCLUDE: " . $codeblock->{name} . "\n"; + return; + } + + # XXX: For now, treat preprocessor stuff besides #include, #if 0 as code. + handle_source_code (); +} + +sub dump_ifstack +{ + my $indent = ''; + foreach my $i (@ifstack) + { + print "$indent$i->{value}: $i->{file}:$i->{line}\n"; + $indent .= ' '; + } +} + +sub check_empty_ifstack +{ + if ($#ifstack >= 0) + { + my $i = pop @ifstack; + print STDERR "${ARGV}:${lineno}: missing endif for $i->{file}:$i->{line}\n"; + die; + $status = -1; + } +} + +sub handle_source_code +{ + return if /^[\s\n]*$/; + + my $codeblock = {}; + label_chunk ($codeblock, "code"); + + $verbose && print "UNKNOWN: " . $codeblock->{string}; +} + +sub handle_classdef +{ + my $class = $_[0]; + label_chunk ($class, "classdef"); + + $class->{funcs} = []; + + if ($class->{syntax} ne 'forwarddecl') + { + $classes{$class->{name}} = $class; + } + + $verbose && print "CLASSDEF: " . $class->{name} . " [" + . $class->{syntax} . "]\n"; +} + +sub handle_function +{ + my $func = $_[0]; + + $func->{purevirtual} = 0; + + if ($func->{class} ne '') + { + # Nested class hacks + if ($func->{class} =~ /::/ + && ! defined $classes{$func->{class}}) + { + # Define class along the way -- the dirty way. + my $class = { name => $func->{class}, + syntax => "class", + nested_class => 1 }; + my ($topclass, $rest) = split (/::/, $func->{class}); + my $save_sec = $current_section; + $current_section = $classes{$topclass}->{section}; + handle_classdef ($class); + $current_section = $save_sec; + } + + $func->{visibility} = "private"; + if (s/^($s)PRIVATE([\s\n])/$1$2/s) + { + $func->{visibility} = "private"; + $func->{pretext} =~ s|PRIVATE[ \t]*||s; + } + elsif (s/^($s)PUBLIC([\s\n])/$1$2/s) + { + $func->{visibility} = "public"; + $func->{pretext} =~ s|PUBLIC[ \t]*||s; + } + elsif (s/^($s)PROTECTED([\s\n])/$1$2/s) + { + $func->{visibility} = "protected"; + $func->{pretext} =~ s|PROTECTED[ \t]*||s; + } + elsif (s/^($s)IMPLEMENT([\s\n])/$1$2/s) + { + # Use a visibility attribute that is never used in adding + # declarations to classes in print_classdecl. + $func->{visibility} = "implementation_only"; + $func->{pretext} =~ s|IMPLEMENT[ \t]*||s; + } + + if ($func->{posttext} =~ s/$s=${s}0$s;$s$//s) + { + $func->{purevirtual} = 1; + } + + if ($func->{class} =~ /::/ + && $func->{visibility} ne "implementation_only") + { + die "${ARGV}:${lineno}: Limitation: Only predeclared members " . + "supported for nested classes. Use IMPLEMENT;"; + } + + if (! defined $classes{$func->{class}}) + { + die "${ARGV}:${lineno}: Class " . $func->{class} + . " has not been declared;"; + } + } + else + { + $func->{visibility} = "free"; + } + + # Interprete more type attributes. + $func->{inline} = 0; + $func->{always_inline} = 0; + $func->{static} = 0; + $func->{hide} = 0; + $func->{virtual} = 0; + $func->{explicit} = 0; + $func->{classtemplate} = ''; + $func->{funtemplate} = ''; + $func->{template} = ''; + $func->{fully_specialized_template} = ''; + while (1) + { + if (s/^($s)((?:$template)+)([\s\n])/$1$3/s) + { + my $match = $2; + my @specs = split(/(?<= \>)(?= $s template)/sx, $match, 3); + + if ($func->{class} eq '') # Free function? + { + $func->{funtemplate} = shift @specs; + } + else # Have a class + { + my $class = $classes{$func->{class}}; + my $istemplateclass = ($class->{pretext} =~ /^[^\{]*template/s); + + if ($istemplateclass) + { + $func->{classtemplate} = shift @specs; + $func->{funtemplate} = shift @specs if scalar @specs; + } + else # Not a class template + { + $func->{funtemplate} = shift @specs; + } + } + + die "${ARGV}:$lineno: Too many template specs" + if scalar @specs; + + $func->{template} = 'yes'; + $func->{fully_specialized_template} = 'yes' + if ($match =~ /^(?:${s}template$s<${s}>)+${s}$/s); + + $func->{pretext} =~ s/\Q$match//s; +# $func->{pretext} =~ s|$template[ \t]*||s; + next; + } + + if (s/^($s)inline([\s\n])/$1$2/si) # "inline" is case-insensitive. + { + $func->{inline} = 1 if $doing_inlines + || $func->{fully_specialized_template} ne ''; + $func->{pretext} =~ s|inline[ \t]*||si; + @{$func->{needs}} = (); + while (1) + { + if (s/^($s)NEEDS\s*\[([^\]]+)\]([\s\n])/$1$3/s) + { + @{$func->{needs}} = split (/\s*,\s*/, $2); + # Delete NEEDS directive, but keep newlines + while ($func->{pretext} =~ + s|NEEDS \s* \[ ( (?:[^\n\]]*\n)* ) + [^\n\]]+ \n (\n*) + [^\n\]]* \] + |NEEDS[$1\n$2\]|sx) {} + $func->{pretext} =~ s|NEEDS\s*\[ (\n*) [^\n\]]*\]|$1|sx; + next; + } + if (s/^($s)NOEXPORT([\s\n])/$1$2/si) + { + $func->{hide} = 1; + $func->{pretext} =~ s|NOEXPORT[ \t]*||s; + next; + } + if (s/^($s)ALWAYS_INLINE([\s\n])/$1$2/si) + { + $func->{inline} = 1; + $func->{always_inline} = 1; + $func->{pretext} =~ s|ALWAYS_INLINE[ \t]*||s; + next; + } + last; + } + + # Reset inline data if inline handling was not enabled by -i + # or ALWAYS_INLINE. + if (! $func->{inline}) + { + undef $func->{needs}; + } + next; + } + + + if (s/^($s)static([\s\n])/$1$2/s) + { + $func->{static} = 1; + $func->{pretext} =~ s/static[ \t]*//s; + + if ($func->{class} eq '') + { + $func->{visibility} = "static"; + $func->{hide} = 1; + } + + next; + } + + if (s/^($s)IMPLEMENT([\s\n])/$1$2/s) + { + $func->{pretext} =~ s/IMPLEMENT[ \t]*//s; + + if ($func->{class} eq '') + { + $func->{visibility} = "implementation_only"; + } + + next; + } + + if (s/^($s)explicit([\s\n])/$1$2/s) + { + $func->{explicit} = 1; + $func->{pretext} =~ s|explicit[ \t]*||s; + next; + } + + if (s/^($s)virtual([\s\n])/$1$2/s) + { + $func->{virtual} = 1; + $func->{pretext} =~ s|virtual[ \t]*||s; + next; + } + + if (/^($s)(PRIVATE|PUBLIC|PROTECTED)([\s\n])/) + { + die "${blockfile}:$blockstart: only one visibility attribute allowed at start of declaration;"; + } + + last; + } + + label_chunk ($func, "function"); + + if ($current_section eq 'INTERFACE') + { + die "${ARGV}:${lineno}: Function " . $func->{name} + . " in INTERFACE section;"; + } + + push @{$classes{$func->{class}}->{funcs}}, $func; + + $verbose && print "FUNC: " . ($func->{class} ne '' + ? ($func->{class} . "::") + : "") + . $func->{name} + . ($func->{classtemplate} ne '' + ? " T: " . $func->{classtemplate} : "") + . ($func->{funtemplate} ne '' + ? " M: " . $func->{funtemplate} : "") + . ($func->{fully_specialized_template} ne '' + ? " FULLY_SPEC" : "") + . "\n"; +} + +############################################################################# + +# +# Printing code. +# + +my $saved_head; +my $saved_indent; + +sub print_head # Save header. Print it only if a + # print_expand() follows +{ + $saved_head .= $_[0]; + $saved_indent = $print_indent; +} + +sub clear_head +{ + $saved_head = ''; +} + +sub print_expand($) # Expands comments and prints to OUT. +{ + my $str = $_[0]; + + if ($saved_head ne '') + { + local $print_indent = $saved_indent; + my $str = $saved_head; + $saved_head = ''; + + print_expand $str; # Recurse. + } + + $str =~ s/\n(?:[ \t]*\n)+/\n\n/sg if ! $doing_linenumbers; + + while ( $str =~ s/([\001\002])([0-9]+)\1/$comments[$2]/sg ) + {} + + if ($print_indent) + { + my $istr = " " x $print_indent; + $str =~ s/^/$istr/mg; + } + + print OUT $str; +} + +sub print_lineno($) +{ + return if ! $doing_linenumbers; + + my $object = $_[0]; + + print_expand ''; # print headers we accumulated + print OUT "#line " . $object->{line} . " \"" . $object->{file} . "\"\n"; +} + +sub print_lineno_sans_empty_lines($) +{ + return if ! $doing_linenumbers; + + my $object = $_[0]; + + my $start_of_code = $object->{string}; + $start_of_code =~ s/^([\s\n]+).*$/$1/s; + + my @startcomments = split /\n/, " $start_of_code "; + + print OUT "#line " . ($object->{line} + @startcomments - 1) + . " \"" . $object->{file} . "\"\n"; +} + +sub weedout_whitespace # Delete whitespace except on lines w/comments +{ + my $str = $_[0]; + + $str =~ s/^[\s\n]+//s; + + if (! $doing_linenumbers) # more cosmetic changes if we do not + { # have to be correct line-number-wise + my @lines = split /\n/, $str; + my $foundcode = 0; + $str = ''; + + foreach my $line (@lines) + { + $line =~ s/^\s+//; + $line =~ s/\s+$//; + + if ($line =~ /\001/ || $line =~ /^\s*$/) + { + $line .= "\n"; + } + else + { + if (! $foundcode) + { + $foundcode = 1; + + # Found something like code: Remove trailing whitespace + # from $str, + $str =~ s/\s+$//s; + $str .= "\n" if $str ne ''; + } + + $line =~ s/\s+/ /g; + $line .= ' '; + } + $str .= $line; + } + } + + $str =~ s/\s+$//; + + return $str; +} + +sub func_prototype($) # Return a function declaration from + # func head. +{ + my $func = $_[0]; + my $pretext = $func->{pretext}; + + if ($func->{inline}) + { + $pretext =~ s/^($s)/${1}inline /s; + } + + if ($func->{explicit}) + { + $pretext =~ s/^($s)/${1}explicit /s; + } + + if ($func->{static}) + { + $pretext =~ s/^($s)/${1}static /s; + } + + if ($func->{virtual}) + { + $pretext =~ s/^($s)/${1}virtual /s; + } + + if ($func->{funtemplate} ne '') + { + $pretext =~ s/^($s)/${1}$func->{funtemplate} /s; + } + + my $func_header = weedout_whitespace($pretext . + $func->{name} . $func->{args}); + + # Insert ; at the correct place, that is, before any comments. + my $e = $func->{purevirtual} ? ' = 0' : ''; + $func_header =~ s/($s)$/$e;$1/s; + + return $func_header; +} + +sub print_funcdecl($) +{ + my $function = $_[0]; + + if ($function->{visibility} ne "implementation_only") + { + print_expand "\n"; + print_lineno_sans_empty_lines $function; + print_expand func_prototype($function) . "\n"; + } + + # Handle inlines. + if ($function->{inline}) + { + handle_inline ($function); + } +} + +sub print_classdecl($) +{ + my $class = $_[0]; + return if check_if_printed ($class); + + print_lineno $class; + + if (defined $class->{nested_class}) + { + # (This will not actually print anything, but do other processing.) + foreach my $function (@{$class->{funcs}}) + { + die "Assert failed" + if $function->{visibility} ne "implementation_only"; + print_funcdecl $function; + } + } + elsif ($class->{syntax} =~ /^(?:struct|class)$/) + { + if (! $doing_inlines) + { + $class->{pretext} =~ s/\binline\b[ \t]*//g; + } + + print_expand $class->{pretext}; + + print_head "\npublic:"; + $print_indent += 2; + foreach my $function (grep {$_->{visibility} eq "public"} + @{$class->{funcs}}) + { + print_funcdecl $function; + } + $print_indent -= 2; + clear_head(); + print_head "\nprotected:"; + $print_indent += 2; + foreach my $function (grep {$_->{visibility} eq "protected"} + @{$class->{funcs}}) + { + print_funcdecl $function; + } + $print_indent -= 2; + clear_head(); + print_head "\nprivate:"; + $print_indent += 2; + foreach my $function (grep {$_->{visibility} eq "private"} + @{$class->{funcs}}) + { + print_funcdecl $function; + } + $print_indent -= 2; + clear_head(); + + # Also, don't forget to "print" already-declared functions. + # (This will not actually print anything, but do other processing.) + foreach my $function (grep {$_->{visibility} eq "implementation_only"} + @{$class->{funcs}}) + { + print_funcdecl $function; + } + + print_expand $class->{posttext}; + } + else + { + print_expand $class->{string}; + } +} + +my $parengroup; +sub print_funcdef($) +{ + my $function = $_[0]; + return if $function->{purevirtual}; + return if check_if_printed ($function); + + my $pretext = $function->{pretext}; + + if ($function->{inline}) + { + if ($function->{always_inline}) + { + $pretext =~ s/^($s)/${1}ALWAYS_INLINE /s; + } + $pretext =~ s/^($s)/${1}inline /s; + } + + if ($function->{static} && $function->{class} eq '') + { + $pretext =~ s/^($s)/${1}static /s; + } + + if ($function->{funtemplate} ne '') + { + $pretext =~ s/^($s)/${1}$function->{funtemplate} /s; + } + + if ($function->{classtemplate} ne '') + { + $pretext =~ s/^($s)/${1}$function->{classtemplate} /s; + } + + # Remove default arguments from argument list + my $args = $function->{args}; + $parengroup = qr{ # Matches correctly-nested groups of parens + \( + (?: + (?> [^()]* ) # Non-parens without backtracking + | + (??{ $parengroup }) # Backtrack: Group with parens + )* + \) + }x; + my $expr = qr{ [^(),]* (?:$parengroup)? [^(),]* }x; + $args =~ s/$s = $expr//gx; + + print_expand "\n"; + print_lineno $function; + print_expand $pretext + . ($function->{class} ne '' + ? $function->{class} . $function->{templateargs} + . "::" . $function->{name} + : $function->{name} . $function->{templateargs}) + . $args . $function->{posttext}; +} + +sub print_code($) +{ + my $codeblock = $_[0]; + return if check_if_printed ($codeblock); + print_lineno $codeblock; + print_expand $codeblock->{string}; +} + +sub check_if_printed +{ + my $codeblock = $_[0]; + return 1 if $codeblock->{printed}; + $codeblock->{printed} = 1; + return 0; +} + +############################################################################# + +# +# Inline-function bookkeeping. +# + +sub lookup_by_name # Return (list of) item(s) matching name. +{ + my ($item, $context) = @_; + + # Is it a class name? + if (defined $classes{$item}) + { + return $classes{$item}; + } + + # Is it an include file? + if (defined $includes{$item}) + { + $includes{$item}->{inline} = 1; + return $includes{$item}; + } + + # Must be a function name! + my ($classname, $funcname); + + if ($item =~ /::/) + { + ($classname, $funcname) = split /::/, $item; + } + else + { + ($classname, $funcname) = ('' , $item); + } + + my @grepresult = grep {$_->{name} eq $funcname && $_->{inline}} + @{$classes{$classname}->{funcs}}; + + return shift @grepresult + if (scalar @grepresult == 1); + + if (scalar @grepresult == 0) + { + my @xgrepresult = grep {$_->{name} eq $funcname} + @{$classes{$classname}->{funcs}}; + die $context->{file} . ":" . $context->{line} . ": Cannot find $item;" + if (scalar @xgrepresult == 0); + $wno_inline && print STDERR $context->{file} . ":" . $context->{line} . + ": warning: Cannot find inline code ". + "for $item;\n"; + } + + return @grepresult; # Return list of matching function names. +} + +# Check if Function $function can already see Object $item in its context. +sub inline_known +{ + my ($item, $function) = @_; + + if ($item->{type} eq "function" + && $item->{hide} + && ! $function->{hide}) + { + die $function->{file} . ":" . $function->{line} . + ": Nonhidden function " . funcname($function) . + " depends on hidden function " . funcname($item) . " (" . + ($item->{visibility} eq 'static' ? "static" : "NOEXPORT") . ")"; + } + + return exists $public_inline{$item} + || (($function->{visibility} eq 'private' + || ($function->{class} ne '' + && $classes{$function->{class}}->{section} eq "IMPLEMENTATION")) + && exists $private_inline{$item}) + || ($function->{hide} + && exists $unit_inline{$item}); +} + +# Put inline function $1 and all its dependencies (given by NEEDS +# directives) into @inline_order_[public/private/unit], depending on +# visibility of $1. Function handle_inline is called when printing +# inline-function declarations, so the sequence of handle_inline calls +# is determined by declaration-printing order. +sub handle_inline +{ + my $function = $_[0]; + my $class = $function->{class}; + my @needed = (); + + $verbose && + print "INLINE " . funcname($function) . " NEEDS "; + + # Add all needed items, then add my own name as well as my class + # name for good measure. + foreach my $item (@{$function->{needs}}) + { + push @needed, lookup_by_name ($item, $function); + } + + push @needed, $function; + unshift @needed, lookup_by_name ($class, $function) + if ($class ne ''); + + NEEDEDLOOP: + while (@needed) + { + my $object = $needed[0]; + + if (inline_known ($object, $function)) + { + shift @needed; + next; + } + + # Check for further dependencies. + my @moreneeded = (); + + if ($object->{type} eq "function" && $object->{class} ne '') + { + my $class = lookup_by_name ($object->{class}, $object); + push @moreneeded, $class; + } + + if (defined $object->{needs}) + { + foreach my $item (@{$object->{needs}}) + { + my $o = lookup_by_name ($item, $object); + next if ! ref $o; # Skip referenced but noninline objects + push @moreneeded, $o; + } + } + + # Check if we have everything that's needed for $item. + foreach my $i (@moreneeded) + { + if (inline_known ($i, $function)) + { + next; + } + + if ($i == $function) # Function depends on itself! + { + my $callstack = " " . funcname ($function) . "\n";; + my $prev = $function; + push @needed, $function; + foreach my $j (@needed) + { + # $j is not part of call stack if it does not need $prev + next if ! grep {lookup_by_name ($_, $object) == $prev} + @{$j->{needs}}; + $callstack .= " " . funcname ($j) . "\n"; + $prev = $j; + last if $j == $function; + } + + die $object->{file} . ":" . $object->{line} . ": Function " . + funcname ($object) . " NEEDS " . funcname ($i) . + ", which circularly depends on this function:\n" . + $callstack; + } + + unshift @needed, $i; + next NEEDEDLOOP; + } + + $verbose && print &funcname ($object) . " "; + + if ($function->{hide}) + { + $unit_inline{$object} = 1; + push @inline_order_unit, $object; + } + elsif ($function->{visibility} eq 'private' + || ($class ne '' + && $classes{$class}->{section} eq "IMPLEMENTATION")) + { + $private_inline{$object} = 1; + push @inline_order_private, $object; + } + else + { + $public_inline{$object} = 1; + push @inline_order_public, $object; + } + + shift @needed; + } + + $verbose && print "\n"; +} + +sub print_inlines +{ + foreach my $object (grep {$_->{type} eq "classdef"} @_) + { + if ($object->{section} ne 'INTERFACE') + { + print_classdecl $object; + } + } + + foreach my $object (grep {$_->{type} eq "function"} @_) + { + print_funcdef $object; + } +} + +###################################################################### +# +# Utilities +# +sub funcname +{ + my $function = $_[0]; + + return ($function->{class} ? ($function->{class} . "::") : "") + . $function->{name}; +} diff --git a/tools/preprocess/test/Makefile b/tools/preprocess/test/Makefile new file mode 100644 index 00000000..652866c6 --- /dev/null +++ b/tools/preprocess/test/Makefile @@ -0,0 +1,134 @@ +# scan the L4 global configuration file +L4DIR ?= ../../.. +#include $(L4DIR)/mk/Makeconf + +TOOL = ../src/preprocess + +all:: test + +ALL_TESTS = $(TOOL_TESTS) +TOOL_TESTS = mapping mapping_inline random random_inline extern_c static \ + noinline explicit operator template template_inline c-preproc \ + inline inline_noinline \ + parser parser_noinline \ + multifile variable line line_not line_nh interface comment_in_string \ + default_args drop_single1 drop_single2 drop_single3 drop_multi1 \ + drop_multi2 + +mapping_inline_src = mapping +mapping_inline_flags = -i + +random_inline_src = random +random_inline_flags = -i + +static_flags = -i + +inline_flags = -i + +inline_noinline_src = inline +inline_noinline_flags = + +noinline_flags = -i + +template_inline_src = template +template_inline_flags = -i + +parser_flags = -i + +parser_noinline_src = parser +parser_noinline_flags = + +multifile_src = multifile1 multifile2 +multifile_flags = -i +multifile_extra = multifile-part1.cc multifile-part2.cc + +line_not_src = line +line_not_flags = -l + +line_nh_src = line +line_nh_flags = -L + +interface_missing = interface.h +interface_extra = interfacepublic.h + +drop_single1_src = dropsection +drop_single1_flags = -s -e "bax" + +drop_single2_src = dropsection +drop_single2_flags = -s -e "bax ixbix" + +drop_single3_src = dropsection +drop_single3_flags = -s -e "bax aba" + +drop_multi1_src = dropsection dropsection-ext +drop_multi1_flags = -s -e "bax aba" +drop_multi1_extra = drop_multi1-ext.cc + +drop_multi2_src = dropsection dropsection-ext +drop_multi2_flags = -s -e "bax aba ext" +drop_multi2_extra = drop_multi2-ext.cc + +ifdef_src = ifdef +ifdef_flags = -s -e "true" + +ifdef1_src = ifdef1 +ifdef1_flags = -s -e "true" +ifdef1_extra = ifdef1-more.cpp + +random.cpp: combine.pl + perl $< > $@.new + mv $@.new $@ + +clean:: + rm -f random.cpp + +test_rules: Makefile + rm -f $@.new + for test in $(TOOL_TESTS); \ + do \ + echo "ifndef $${test}_src" >> $@.new; \ + echo "$${test}_src = $${test}" >> $@.new; \ + echo "endif" >> $@.new; \ + echo "ifndef $${test}_flags" >> $@.new; \ + echo "$${test}_flags = " >> $@.new; \ + echo "endif" >> $@.new; \ + echo "$${test}.cc: \$$(addsuffix .cpp, \$$($${test}_src)) \$$(TOOL); \$$(TOOL) \$$($${test}_flags) -c $${test} \$$(filter-out \$$(TOOL), \$$^)" >> $@.new; \ + done + mv $@.new $@ + +include test_rules + +clean:: + rm -f $(addsuffix .cc, $(TOOL_TESTS)) \ + $(addsuffix .h, $(TOOL_TESTS)) \ + $(addsuffix _i.h, $(TOOL_TESTS)) + +.PHONY: test +test: $(addsuffix .t.ok, $(ALL_TESTS)) + +%.t.ok: %.cc + @echo -n "Running test $* ... " +ifeq ($(RECREATE_OUTPUT),1) + @cp $(filter-out $($*_missing),$*.h $*_i.h $*.cc) $($*_extra) verify/ +endif + @for i in $(filter-out $($*_missing),$*.h $*_i.h $*.cc) $($*_extra); \ + do \ + diff -u verify $$i || exit 1; \ + done + @echo "OK" + @touch $@ + +.PHONY: init +init: + $(MAKE) test RECREATE_OUTPUT=1 + +install: + @echo Not installing tests. + +clean:: + $(RM) $(ALL) $(OBJS) *.t.ok + +cleanall:: clean + $(RM) *~ .*.d test_rules + +#include $(DEPS) diff --git a/tools/preprocess/test/c-preproc.cpp b/tools/preprocess/test/c-preproc.cpp new file mode 100644 index 00000000..9ee72b76 --- /dev/null +++ b/tools/preprocess/test/c-preproc.cpp @@ -0,0 +1,19 @@ +INTERFACE: + +IMPLEMENTATION: + +// set CS (missing from OSKIT) +#define set_cs(cs) \ + asm volatile \ + ("ljmp %0,$1f \n1:" \ + : : "i" (cs)); + +void +function (void) +{ +#if 1 + bar (); +#else + foo (); +#endif +} diff --git a/tools/preprocess/test/combine.pl b/tools/preprocess/test/combine.pl new file mode 100644 index 00000000..786ab4d3 --- /dev/null +++ b/tools/preprocess/test/combine.pl @@ -0,0 +1,57 @@ +#!/usr/bin/perl -w + +print ' +INTERFACE: + +#include "bar.h" + +class Baz; + +class Foo : public Bar +{ + // DATA + int d_data; + Baz* d_baz; +}; + +IMPLEMENTATION: + +#include "yes.h" +#include + +class Rambo +{ +}; + +// Try combinations of {PUBLIC|PROTECTED|PRIVATE|} {static|} +// {inline|INLINE|inline NEEDS[]|INLINE NEEDS[]} {virtual|} + +'; + +$count = 0; + +foreach my $class ("Foo", "") + { + foreach my $public ("PUBLIC", "PROTECTED", "PRIVATE", "") + { + foreach my $static ("static", "") + { + foreach my $inline ("inline", "INLINE", + "inline NEEDS [Rambo,\"yes.h\"]", + "INLINE NEEDS[Rambo, \"yes.h\"]", "") + { + foreach my $virtual ("virtual", "") + { + next if ($public ne '') && ($class eq ''); + next if ($virtual ne '') && (($static ne '') + || ($class eq '')); + print "$public $virtual $static $inline\n"; + print "void "; + print "${class}::" if ($class ne ''); + print "function" . $count++; + print "() {}\n\n"; + } + } + } + } + } diff --git a/tools/preprocess/test/comment_in_string.cpp b/tools/preprocess/test/comment_in_string.cpp new file mode 100644 index 00000000..adddf931 --- /dev/null +++ b/tools/preprocess/test/comment_in_string.cpp @@ -0,0 +1,23 @@ +INTERFACE: + +IMPLEMENTATION: + +int foo(char *s); + +void irq_init(unsigned char master_base, unsigned char slave_base) +{ + if (!(foo(" -vmware")) + { + foo("outb_p(MASTER_OCW, 0xfb); // unmask irq2"); + } + else + { + foo("using normal pic mode \n"); + } +} + +void bar() +{ + foo ("if (0) {"); + foo ("} // if(0)"); +} diff --git a/tools/preprocess/test/default_args.cpp b/tools/preprocess/test/default_args.cpp new file mode 100644 index 00000000..f637dcf0 --- /dev/null +++ b/tools/preprocess/test/default_args.cpp @@ -0,0 +1,32 @@ +#include + +IMPLEMENTATION: + +template +std::vector +vec(T f1 = T(), T f2 = T(), T f3 = T(), + T f4 = T(), T f5 = T(), T f6 = T()) +{ + std::vector v; + if (f1 != T()) { + v.push_back (f1); + if (f2 != T()) { + v.push_back (f2); + if (f3 != T()) { + v.push_back (f3); + if (f4 != T()) { + v.push_back (f4); + if (f5 != T()) { + v.push_back (f5); + if (f6 != T()) { + v.push_back (f6); + }}}}}} + return v; +} + +extern "C" +void +disasm_bytes(char *buffer, unsigned len, unsigned va, unsigned task, + int show_symbols, int show_intel_syntax, + int (*peek_task)(unsigned addr, unsigned task), + const char* (*get_symbol)(unsigned addr, unsigned task)) WEAK; diff --git a/tools/preprocess/test/dropsection-ext.cpp b/tools/preprocess/test/dropsection-ext.cpp new file mode 100644 index 00000000..3d103f9e --- /dev/null +++ b/tools/preprocess/test/dropsection-ext.cpp @@ -0,0 +1,22 @@ +INTERFACE [ext]: + +EXTENSION class Gen_foo : public Gen_bar +{ +public: + int extra_var; +}; + +EXTENSION class Gen_foo_ext : public Gen_baz +{ +private: + char *extension; +}; + +IMPLEMENTATION [ext]: + +PRIVATE int +Gen_foo::do_something_private() +{ + // just do it +} + diff --git a/tools/preprocess/test/dropsection.cpp b/tools/preprocess/test/dropsection.cpp new file mode 100644 index 00000000..6ab1039b --- /dev/null +++ b/tools/preprocess/test/dropsection.cpp @@ -0,0 +1,60 @@ +INTERFACE: + +class Gen_foo +{ +public: + int baz; + +protected: + int foo( int ); + +}; + +class Gen_foo_ext : private Gen_foo, public Ixdebix +{ +protected: + unsigned stuff; +}; + +IMPLEMENTATION: + +PUBLIC inline void +Gen_foo::bar( unsigned x ) +{ + // do soemthing with x; +} + +PUBLIC void +Gen_foo_ext::test() +{ + // the test +} + +IMPLEMENTATION [ixbix-bax]: + +IMPLEMENT int +Gen_foo::foo( int y ) +{ + // do something strange with y + bar(y); + return y; +} + +IMPLEMENTATION [aba-bax]: + +IMPLEMENT int +Gen_foo::foo( int y ) +{ + // just return y + return y; +} + +IMPLEMENTATION [{!bax,!ixbix}]: + +PUBLIC int +Gen_foo::tust( int y ) +{ + // just return y + return y; +} + diff --git a/tools/preprocess/test/explicit.cpp b/tools/preprocess/test/explicit.cpp new file mode 100644 index 00000000..3f5b1d2e --- /dev/null +++ b/tools/preprocess/test/explicit.cpp @@ -0,0 +1,11 @@ +INTERFACE: + +class Foo +{ +}; + +IMPLEMENTATION: + +PUBLIC explicit +Foo::Foo (int bar) +{} diff --git a/tools/preprocess/test/extern_c.cpp b/tools/preprocess/test/extern_c.cpp new file mode 100644 index 00000000..7edebff8 --- /dev/null +++ b/tools/preprocess/test/extern_c.cpp @@ -0,0 +1,8 @@ +INTERFACE: + +IMPLEMENTATION: + +extern "C" +{ + extern char _mappings_1, _mappings_end_1; +} diff --git a/tools/preprocess/test/inline.cpp b/tools/preprocess/test/inline.cpp new file mode 100644 index 00000000..73da32fd --- /dev/null +++ b/tools/preprocess/test/inline.cpp @@ -0,0 +1,74 @@ +INTERFACE: + +class Foo +{ +}; + +class Bar +{ +}; + +IMPLEMENTATION: + +// Test dependency-chain resolver + +class Frob +{ +}; + +inline +bool +Frob::private_func() +{ +} + +inline +bool +Foo::private_func() +{ +} + +inline +bool +Bar::private_func() +{ +} + +inline NEEDS [Foo::private_func, Bar::private_func] +void +Bar::another_private_func() +{ +} + +PUBLIC inline NEEDS [Bar::another_private_func, Frob::private_func] +void +Bar::public_func() +{ +} + +// This inline funtion is public only because it is needed by an +// extern-"C" function. So we do not want to export it. +PUBLIC inline NOEXPORT +void +Foo::bar() +{ + +} + +// Try both NOEXPORT and NEEDED. +PUBLIC inline NOEXPORT NEEDS[Foo::private_func] +void +Foo::baz() +{ +} + +extern "C" +void function (Foo* f) +{ + f->bar(); +} + +template inline void* xcast(T* t) +{ + return (void*) t; +} diff --git a/tools/preprocess/test/interface.cpp b/tools/preprocess/test/interface.cpp new file mode 100644 index 00000000..3e5c037c --- /dev/null +++ b/tools/preprocess/test/interface.cpp @@ -0,0 +1,15 @@ +INTERFACE [interfacepublic]: + +// This is class Foo. +class Foo +{ +}; + +IMPLEMENTATION: + +PUBLIC +void +Foo::func1() +{ + +} diff --git a/tools/preprocess/test/line.cpp b/tools/preprocess/test/line.cpp new file mode 100644 index 00000000..60c01257 --- /dev/null +++ b/tools/preprocess/test/line.cpp @@ -0,0 +1,20 @@ +INTERFACE: + +// This is class Foo. +class Foo +{ +}; + +IMPLEMENTATION: + +// A long, multiline comment in front of this function definition. +// Also, a lot of specifiers that need to be handled. + +PUBLIC +inline +static +void +Foo::func1() +{ + +} diff --git a/tools/preprocess/test/mapping.cpp b/tools/preprocess/test/mapping.cpp new file mode 100644 index 00000000..c8fc7bff --- /dev/null +++ b/tools/preprocess/test/mapping.cpp @@ -0,0 +1,784 @@ +INTERFACE: + +#include // for vm_offset_t, vm_size_t +#include "space.h" // for space_index_t + +enum mapping_type_t { Map_mem = 0, Map_io }; + +class mapping_tree_t; // forward decls +struct mapping_s; + +// +// class mapping_t +// +class mapping_t +{ + friend class mapdb_t; + friend class mapping_tree_t; + friend class jdb; + + // CREATORS + mapping_t(const mapping_t&); // this constructor is undefined. + + // DATA + char _data[5]; +} __attribute__((packed)); + +class kmem_slab_t; +struct physframe_data; + +// +// class mapdb_t: The mapping database +// +class mapdb_t +{ + friend class jdb; + +public: + enum { Size_factor = 4, + Size_id_max = 8 /* can be up to 15 (4 bits) */ }; + +private: + // DATA + physframe_data *physframe; + kmem_slab_t *allocator_for_treesize[Size_id_max + 1]; +}; + +IMPLEMENTATION: + +// The mapping database. + +// This implementation encodes mapping trees in very compact arrays of +// fixed sizes, prefixed by a tree header (mapping_tree_t). Array +// sizes can vary from 4 mappings to 4<<15 mappings. For each size, +// we set up a slab allocator. To grow or shrink the size of an +// array, we have to allocate a larger or smaller tree from the +// corresponding allocator and then copy the array elements. +// +// The array elements (mapping_t) contain a tree depth element. This +// depth and the relative position in the array is all information we +// need to derive tree structure information. Here is an example: +// +// array +// element depth +// number value comment +// -------------------------- +// 0 0 Sigma0 mapping +// 1 1 child of element #0 with depth 0 +// 2 2 child of element #1 with depth 1 +// 3 2 child of element #1 with depth 1 +// 4 3 child of element #3 with depth 2 +// 5 2 child of element #1 with depth 1 +// 6 3 child of element #5 with depth 2 +// 7 1 child of element #0 with depth 0 +// +// This array is a pre-order encoding of the following tree: +// +// 0 +// / \ +// 1 7 +// / | \ +// 2 3 5 +// | | +// 4 6 + +// IDEAS for enhancing this implementation: + +// We often have to find a tree header corresponding to a mapping. +// Currently, we do this by iterating backwards over the array +// containing the mappings until we find the Sigma0 mapping, from +// whose address we can compute the address of the tree header. If +// this becomes a problem, we could add one more byte to the mappings +// with a hint (negative array offset) where to find the sigma0 +// mapping. (If the hint value overflows, just iterate using the hint +// value of the mapping we find with the first hint value.) Another +// idea (from Adam) would be to just look up the tree header by using +// the physical address from the page-table lookup, but we would need +// to change the interface of the mapping database for that (pass in +// the physical address at all times), or we would have to include the +// physical address (or just the address of the tree header) in the +// mapdb_t-user-visible mapping_t (which could be different from the +// internal tree representation). (XXX: Implementing one of these +// ideas is probably worthwile doing!) + +// Instead of copying whole trees around when they grow or shrink a +// lot, or copying parts of trees when inserting an element, we could +// give up the array representation and add a "next" pointer to the +// elements -- that is, keep the tree of mappings in a +// pre-order-encoded singly-linked list (credits to: Christan Szmajda +// and Adam Wiggins). 24 bits would probably be enough to encode that +// pointer. Disadvantages: Mapping entries would be larger, and the +// cache-friendly space-locality of tree entries would be lost. + +// The current handling of superpages sucks rocks both in this module +// and in our user, ipc_map.cc. We could support multiple page sizes +// by not using a physframe[] array only for the largest page size. +// (Entries of that array point to the top-level mappings -- sigma0 +// mappings.) Mapping-tree entries would then either be regular +// mappings or pointers to an array of mappings of the next-smaller +// size. (credits: Christan Szmajda) +// +// physframe[] +// ------------------------------- +// | | | | | | | | | | | | | | | | array of ptr to 4M mapping_tree_t's +// ---|--------------------------- +// | +// v a mapping_tree_t +// --------------- +// | | tree header +// |-------------| +// | | mapping_t *or* ptr to array of ptr to 4K trees +// | | e.g. +// | ----------------| +// | | v array of ptr to 4M mapping_tree_t's +// --------------- ------------------------------- +// | | | | | | | | | | | | | | | | +// ---|--------------------------- +// | +// v a mapping_tree_t +// --------------- +// | | tree header +// |-------------| +// | | mapping_t +// | | +// | | +// | | +// --------------- +//- + +#include +#include + +#ifndef offsetof // should be defined in stddef.h, but isn't +#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) +#endif + +// For implementation of mapping_t functions, we need mapping_tree_t. + +// +// class mapping_tree_t +// +class mapping_tree_t +{ + friend class mapping_t; + friend class mapdb_t; + friend class jdb; + + // DATA + unsigned _count: 16; + unsigned _size_id: 4; + unsigned _empty_count: 11; + unsigned _unused: 1; // make this 32 bits to avoid a compiler bug + + mapping_t _mappings[0] __attribute__((packed)); + +} __attribute__((packed)); + +// public routines with inline implementations +inline +unsigned +mapping_tree_t::number_of_entries() const +{ + return mapdb_t::Size_factor << _size_id; +} + +inline +mapping_t * +mapping_tree_t::mappings() +{ + return & _mappings[0]; +} + +// Define (otherwise private) stuff needed by public inline +// functions. + +enum mapping_depth_t +{ + Depth_sigma0_mapping = 0, Depth_max = 253, + Depth_empty = 254, Depth_end = 255 +}; + +struct mapping_s +{ + unsigned space:11; + unsigned size:1; + unsigned address:20; + mapping_depth_t depth:8; + unsigned do_not_touch: 24; // make this 64 bits, and make sure the + // compiler never touches memory after the + // real data +}; + +inline +mapping_t::mapping_t() +{} + +inline +mapping_s * +mapping_t::data() +{ + return reinterpret_cast(_data); +} + +PUBLIC inline NEEDS[mapping_depth_t, mapping_s, mapping_t::data] +space_index_t +mapping_t::space() +{ + return space_index_t(data()->space); +} + +PUBLIC inline NEEDS[mapping_depth_t, mapping_s, mapping_t::data] +vm_offset_t +mapping_t::vaddr() +{ + return (data()->address << PAGE_SHIFT); +} + +PUBLIC inline NEEDS[mapping_depth_t, mapping_s, mapping_t::data] +vm_size_t +mapping_t::size() +{ + if ( data()->size ) + return SUPERPAGE_SIZE; + else + return PAGE_SIZE; +} + +PUBLIC inline +mapping_type_t +mapping_t::type() +{ + // return data()->type;; + return Map_mem; +} + +inline NEEDS[mapping_depth_t, mapping_s, mapping_t::data] +bool +mapping_t::unused() +{ + return (data()->depth > Depth_max); +} + +mapping_tree_t * +mapping_t::tree() +{ + mapping_t *m = this; + + while (m->data()->depth > Depth_sigma0_mapping) + { + // jump in bigger steps if this is not a free mapping + if (! m->unused()) + { + m -= m->data()->depth; + continue; + } + + m--; + } + + return reinterpret_cast + (reinterpret_cast(m) - offsetof(mapping_tree_t, _mappings)); +} + +// +// more of class mapping_t +// + +PUBLIC mapping_t * +mapping_t::parent() +{ + if (data()->depth <= Depth_sigma0_mapping) + { + // Sigma0 mappings don't have a parent. + return 0; + } + + // Iterate over mapping entries of this tree backwards until we find + // an entry with a depth smaller than ours. (We assume here that + // "special" depths (empty, end) are larger than Depth_max.) + mapping_t *m = this - 1; + + while (m->data()->depth >= data()->depth) + m--; + + return m; +} + +PUBLIC mapping_t * +mapping_t::next_iter() +{ + mapping_tree_t *t = tree(); + mapping_t *last_in_tree = t->mappings() + t->number_of_entries() - 1; + + mapping_t *m = this; + + // Look for a valid element in the tree structure. + while (m != last_in_tree) + { + m++; + if (! m->unused()) + return m; // Found a valid entry! + + // Don't iterate to end of tree if this is the last tree entry. + if (m->data()->depth == Depth_end) + return 0; + } + + // Couldn't find a non-empty element behind ourselves in the tree + // structure. + return 0; +} + +PUBLIC mapping_t * +mapping_t::next_child(mapping_t *parent) +{ + // Find the next valid entry in the tree structure. + mapping_t *m = next_iter(); + + // If we didn't find an entry, or if the entry cannot be a child of + // "parent", return 0 + if (m == 0 + || m->data()->depth <= parent->data()->depth) + return 0; + + return m; // Found! +} + +// helpers + +// +// class mapping_tree_t +// + +// This function copies the elements of mapping tree src to mapping +// tree dst, ignoring empty elements (that is, compressing the +// source tree. In-place compression is supported. +PUBLIC static void +mapping_tree_t::copy_compact_tree(mapping_tree_t *dst, mapping_tree_t *src) +{ + dst->_count = 0; + dst->_empty_count = 0; + + mapping_t *d = dst->mappings(); + + for (mapping_t *s = src->mappings(); + s < src->mappings() + src->number_of_entries(); + s++) + { + if (s->unused()) // entry free + { + if (s->data()->depth == Depth_end) + break; + continue; + } + + *d++ = *s; + dst->_count += 1; + } + + assert (dst->_count == src->_count); + assert (d < dst->mappings() + dst->number_of_entries()); + + d->data()->depth = Depth_end; + dst->mappings()[dst->number_of_entries() - 1].data()->depth = Depth_end; +} // copy_compact_tree() + +// +// class mapdb +// + +#include "lock.h" +#include "kmem_slab.h" + +struct physframe_data { + mapping_tree_t *tree; + helping_lock_t lock; +}; + +PUBLIC +mapdb_t::mapdb_t() +{ + vm_offset_t page_number = kmem::info()->main_memory.high / PAGE_SIZE + 1; + + // allocate physframe array + check ( physframe = reinterpret_cast + (kmem::alloc(page_number * sizeof(physframe_data))) ); + + memset(physframe, 0, page_number * sizeof(physframe_data)); + + // create a slab for each mapping tree size + for (int slab_number = 0; + slab_number <= Size_id_max; + slab_number++ ) + { + unsigned elem_size = + (Size_factor << slab_number) * sizeof(mapping_t) + + sizeof(mapping_tree_t); + + allocator_for_treesize[slab_number] = + new kmem_slab_t(((PAGE_SIZE / elem_size) < 40 + ? 8*PAGE_SIZE : PAGE_SIZE), + elem_size, 1); + } + + // create a sigma0 mapping for all physical pages + for (unsigned page_id = 0; page_id < page_number; page_id++) + { + mapping_tree_t *t; + check( (t = physframe[page_id].tree + = reinterpret_cast + (allocator_for_treesize[0]->alloc())) ); + + t->_count = 1; // 1 valid mapping + t->_size_id = 0; // size is equal to Size_factor << 0 + t->_empty_count = 0; // no gaps in tree representation + + t->mappings()[0].data()->depth = Depth_sigma0_mapping; + t->mappings()[0].data()->address = page_id; + t->mappings()[0].data()->space = config::sigma0_taskno; + t->mappings()[0].data()->size = 0; + + t->mappings()[1].data()->depth = Depth_end; + + // We also always set the end tag on last entry so that we can + // check whether it has been overwritten. + t->mappings()[t->number_of_entries() - 1].data()->depth = Depth_end; + } +} // mapdb_t() + + +// insert a new mapping entry with the given values as child of +// "parent" After locating the right place for the new entry, it will +// be stored there (if this place is empty) or the following entries +// moved by one entry. + +// We assume that there is at least one free entry at the end of the +// array so that at least one insert() operation can succeed between a +// lock()/free() pair of calls. This is guaranteed by the free() +// operation which allocates a larger tree if the current one becomes +// to small. +PUBLIC mapping_t * +mapdb_t::insert(mapping_t *parent, + space_t *space, + vm_offset_t va, + vm_size_t size, + mapping_type_t type) +{ + assert(type == Map_mem); // we don't yet support Map_io + + mapping_tree_t *t = parent->tree(); + + // We cannot continue if the last array entry is not free. This + // only happens if an earlier call to free() with this mapping tree + // couldn't allocate a bigger array. In this case, signal an + // out-of-memory condition. + if (! t->mappings()[t->number_of_entries() - 1].unused()) + return 0; + + // If the parent mapping already has the maximum depth, we cannot + // insert a child. + if (parent->data()->depth == Depth_max) + return 0; + + mapping_t *insert = 0; + + bool + found_free_entry = false, + need_to_move = false; + + mapping_t temp; + + // Find a free entry in the array encoding the tree, and find the + // insertion point for the new entry. These two entries might not + // be equivalent, so we may need to move entries backwards in the + // array. In this implementation, we move entries as we traverse + // the array, instead of doing one big memmove + for (mapping_t *m = parent + 1; + m < t->mappings() + t->number_of_entries(); + m++) + { + if (m->unused()) + { + // We found a free entry in the tree -- allocate it. + found_free_entry = true; + t->_count += 1; + + // Did we find an empty element != the end tag? + if (m->data()->depth == Depth_empty) + { + t->_empty_count -= 1; + } + // Else we have found the end tag. If there is another + // array entry left, apply a new end tag to the array + else if (m + 1 < t->mappings() + t->number_of_entries()) + { + (m + 1)->data()->depth = Depth_end; + } + + // if we haven't identified a place for inserting the new + // element, this is it. + if (! need_to_move) + insert = m; + } + else if (! need_to_move + && m->data()->depth <= parent->data()->depth) + { + // we found a non-descendant of ourselves -- need to make + // space for new child + need_to_move = true; + insert = m; + temp = *insert; + + continue; + } + + if (need_to_move) + { + // replace *m with temp (which used to be *(m - 1); but + // *(m - 1) has since been overwritten), and load temp with + // the old value of *m + mapping_t temp2; + + temp2 = *m; + *m = temp; + temp = temp2; + } + + if (found_free_entry) + break; + } + + assert(insert && found_free_entry); + + // found a place to insert new child. + insert->data()->depth = mapping_depth_t(parent->data()->depth + 1); + insert->data()->address = va >> PAGE_SHIFT; + insert->data()->space = space->space(); + insert->data()->size = (size == SUPERPAGE_SIZE); + + return insert; +} // insert() + +PUBLIC mapping_t * +mapdb_t::lookup(space_t *space, + vm_offset_t va, + mapping_type_t type) +{ + vm_offset_t phys = space->virt_to_phys(va); + + if (phys == 0xffffffff) + return 0; + + mapping_tree_t *t; + + // get and lock the tree. + // XXX For now, use a simple lock with helping. Later + // unify locking with our request scheme. + physframe[phys >> PAGE_SHIFT].lock.lock(); + + t = physframe[phys >> PAGE_SHIFT].tree; + assert(t); + + mapping_t *m; + + for (m = t->mappings(); + m->data()->depth != Depth_end + && m < t->mappings() + t->number_of_entries(); + m++) + { + if (m->data()->space == space->space() + && m->data()->address == va >> PAGE_SHIFT) + { + // found! + return m; + } + } + + // not found -- unlock tree + physframe[phys >> PAGE_SHIFT].lock.clear(); + + return 0; +} // lookup() + +PUBLIC void +mapdb_t::free(mapping_t* mapping_of_tree) +{ + mapping_tree_t *t = mapping_of_tree->tree(); + + // We assume that the zeroth mapping of the tree is a sigma0 + // mapping, that is, its virtual address == the page's physical + // address. + vm_offset_t phys_pno = t->mappings()[0].data()->address; + + // We are the owner of the tree lock. + assert(physframe[phys_pno].lock.lock_owner() == current()); + + // Before we unlock the tree, we need to make sure that there is + // room for at least one new mapping. In particular, this means + // that the last entry of the array encoding the tree must be free. + + // (1) When we use up less than a quarter of all entries of the + // array encoding the tree, copy to a smaller tree. Otherwise, (2) + // if the last entry is free, do nothing. Otherwise, (3) if less + // than 3/4 of the entries are used, compress the tree. Otherwise, + // (4) copy to a larger tree. + + bool maybe_out_of_memory = false; + + do // (this is not actually a loop, just a block we can "break" out of) + { + // (1) Do we need to allocate a smaller tree? + if (t->_size_id > 0 // must not be smallest size + && (t->_count << 2) < t->number_of_entries()) + { + mapping_tree_t *new_t = + reinterpret_cast + (allocator_for_treesize[t->_size_id - 1]->alloc()); + + if (new_t) + { + // XXX should be asserted by allocator: + new_t->_size_id = t->_size_id - 1; + new_t->mappings()[new_t->number_of_entries() - 1].data()->depth + = Depth_end; + + mapping_tree_t::copy_compact_tree(new_t, t); + + // Register new tree. + physframe[phys_pno].tree = new_t; + + allocator_for_treesize[t->_size_id]->free(t); + t = new_t; + + break; + } + } + + // (2) Is last entry is free? + if (t->mappings()[t->number_of_entries() - 1].unused()) + break; // OK, last entry is free. + + // Last entry is not free -- either compress current array + // (i.e., move free entries to end of array), or allocate bigger + // array. + + // (3) Should we compress the tree? + // We also try to compress if we cannot allocate a bigger + // tree because there is no bigger tree size. + if (t->_count < (t->number_of_entries() >> 2) + + (t->number_of_entries() >> 1) + || t->_size_id == Size_id_max) // cannot enlarge? + { + if (t->_size_id == Size_id_max) + maybe_out_of_memory = true; + + mapping_tree_t::copy_compact_tree(t, t); // in-place compression + + break; + } + + // (4) OK, allocate a bigger array. + + mapping_tree_t *new_t = + reinterpret_cast + (allocator_for_treesize[t->_size_id + 1]->alloc()); + + if (new_t) + { + // XXX should be asserted by allocator: + new_t->_size_id = t->_size_id + 1; + new_t->mappings()[new_t->number_of_entries() - 1].data()->depth + = Depth_end; + + mapping_tree_t::copy_compact_tree(new_t, t); + + // Register new tree. + physframe[phys_pno].tree = new_t; + + allocator_for_treesize[t->_size_id]->free(t); + t = new_t; + } + else + { + // out of memory -- just do tree compression and hope that helps. + maybe_out_of_memory = true; + + mapping_tree_t::copy_compact_tree(t, t); // in-place compression + } + } + while (false); + + // The last entry of the tree should now be free -- exept if we're + // out of memory. + assert(t->mappings()[t->number_of_entries() - 1].unused() + || maybe_out_of_memory); + + // Unlock tree. + physframe[phys_pno].lock.clear(); +} // free() + +// Delete mappings from a tree. This is easy to do: We just have to +// iterate over the array encoding the tree. +PUBLIC bool +mapdb_t::flush(mapping_t *m, bool me_too) +{ + mapping_tree_t *t = m->tree(); + mapping_t *start_of_deletions = m; + unsigned m_depth = m->data()->depth; + unsigned deleted = 0, empty_elems_passed = 0; + + if (me_too) + { + m->data()->depth = Depth_empty; + t->_count -= 1; + deleted++; + } + else + start_of_deletions++; + + m++; + + for (; + m < t->mappings() + t->number_of_entries() + && m->data()->depth != Depth_end; + m++) + { + if (unsigned (m->data()->depth) <= m_depth) + { + // Found another data element -- stop deleting. Since we + // created holes in the tree representation, account for it. + t->_empty_count += deleted; + + return true; + } + + if (m->data()->depth == Depth_empty) + { + empty_elems_passed++; + continue; + } + + // Delete the element. + m->data()->depth = Depth_empty; + t->_count -= 1; + deleted++; + } + + // We deleted stuff at the end of the array -- move end tag + if (start_of_deletions < t->mappings() + t->number_of_entries()) + { + start_of_deletions->data()->depth = Depth_end; + + // also, reduce number of free entries + t->_empty_count -= empty_elems_passed; + } + + return true; +} // flush() + +PUBLIC void +mapdb_t::grant(mapping_t *m, space_t *new_space, vm_offset_t va) +{ + m->data()->space = new_space->space(); + m->data()->address = va >> PAGE_SHIFT; +} // grant() diff --git a/tools/preprocess/test/multifile1.cpp b/tools/preprocess/test/multifile1.cpp new file mode 100644 index 00000000..f776d41d --- /dev/null +++ b/tools/preprocess/test/multifile1.cpp @@ -0,0 +1,24 @@ +INTERFACE: + +class Foo +{ +}; + +IMPLEMENTATION [part1]: + +PUBLIC +void +Foo::bar () +{} + +PROTECTED inline NEEDS [Foo::rambo] +void +Foo::baz () +{} + +IMPLEMENTATION: + +PRIVATE +void +Foo::gizmatic () +{} diff --git a/tools/preprocess/test/multifile2.cpp b/tools/preprocess/test/multifile2.cpp new file mode 100644 index 00000000..6b92cf07 --- /dev/null +++ b/tools/preprocess/test/multifile2.cpp @@ -0,0 +1,23 @@ +INTERFACE: + +EXTENSION class Foo +{ + int more; +}; + +class Bar; + +IMPLEMENTATION [part2]: + +#include "bar.h" + +PUBLIC +void +Foo::bingo (Bar* bar) +{} + +PROTECTED inline +void +Foo::rambo () +{} + diff --git a/tools/preprocess/test/noinline.cpp b/tools/preprocess/test/noinline.cpp new file mode 100644 index 00000000..379e2949 --- /dev/null +++ b/tools/preprocess/test/noinline.cpp @@ -0,0 +1,8 @@ +INTERFACE: + +IMPLEMENTATION: + +// There is nothing to inline -- therefore, this #include directive +// should not be put in public header. + +#include "foo.h" diff --git a/tools/preprocess/test/operator.cpp b/tools/preprocess/test/operator.cpp new file mode 100644 index 00000000..1da955af --- /dev/null +++ b/tools/preprocess/test/operator.cpp @@ -0,0 +1,88 @@ +INTERFACE: + +class Foo +{ +}; + +IMPLEMENTATION: + +PUBLIC +void * +Foo::operator new (size_t) // funny comment +{ +} + +PUBLIC +Foo& +Foo::operator + (const Foo&) // funny comment +{ +} + +PUBLIC +Foo& +Foo::operator = (const Foo&) // funny comment +{ +} + +PUBLIC +Foo& +Foo::operator * (const Foo&) // funny comment +{ +} + +template +std::vector& +operator << (std::vector& in, const T& new_elem) +{ + in.push_back (new_elem); + return in; +} + +// Some systematic tests (contributed by Matthias Daum) + +struct X { }; + +PUBLIC inline void* X::operator new(unsigned int) { return (void*)0; } +PUBLIC inline void X::operator delete(void*) { } +PUBLIC inline void* X::operator new [] (unsigned int, int) { return (void*)0; } +PUBLIC inline void X::operator delete [] (void*) { } +PUBLIC inline X X::operator + (const X&) { return *this; } +PUBLIC inline X X::operator - (const X&) { return *this; } +PUBLIC inline X X::operator * (const X&) { return *this; } +PUBLIC inline X X::operator / (const X&) { return *this; } +PUBLIC inline X X::operator % (const X&) { return *this; } +PUBLIC inline X X::operator ^ (const X&) { return *this; } +PUBLIC inline X X::operator & (const X&) { return *this; } +PUBLIC inline X X::operator | (const X&) { return *this; } +PUBLIC inline X X::operator ~ () { return *this; } +PUBLIC inline X X::operator ! () { return *this; } +PUBLIC inline X& X::operator = (const X&) {return *this; } +PUBLIC inline bool X::operator < (const X&) { return false; } +PUBLIC inline bool X::operator > (const X&) { return false; } +PUBLIC inline X& X::operator += (const X&) { return *this; } +PUBLIC inline X& X::operator -= (const X&) { return *this; } +PUBLIC inline X& X::operator *= (const X&) { return *this; } +PUBLIC inline X& X::operator /= (const X&) { return *this; } +PUBLIC inline X& X::operator %= (const X&) { return *this; } +PUBLIC inline X& X::operator ^= (const X&) { return *this; } +PUBLIC inline X& X::operator &= (const X&) { return *this; } +PUBLIC inline X& X::operator |= (const X&) { return *this; } +PUBLIC inline X X::operator << (const X&) { return *this; } +PUBLIC inline X X::operator >> (const X&) { return *this; } +PUBLIC inline X& X::operator >>= (const X&) { return *this; } +PUBLIC inline X& X::operator <<= (const X&) { return *this; } +PUBLIC inline bool X::operator == (const X&) { return true; } +PUBLIC inline bool X::operator != (const X&) { return false; } +PUBLIC inline bool X::operator <= (const X&) { return true; } +PUBLIC inline bool X::operator >= (const X&) { return true; } +PUBLIC inline bool X::operator && (const X&) { return false; } +PUBLIC inline bool X::operator || (const X&) { return true; } +PUBLIC inline X& X::operator ++ () { return *this; } +PUBLIC inline X X::operator ++ (int) { return *this; } +PUBLIC inline X& X::operator -- () { return *this; } +PUBLIC inline X X::operator -- (int) { return *this; } +PUBLIC inline X& X::operator , (const X&) { return *this; } +PUBLIC inline X* X::operator ->* (const X&) { return this; } +PUBLIC inline X* X::operator -> () { return this; } +PUBLIC inline int X::operator () (const X&) { return 0; } +PUBLIC inline int X::operator [] (const X&) { return 0; } diff --git a/tools/preprocess/test/parser.cpp b/tools/preprocess/test/parser.cpp new file mode 100644 index 00000000..7ed31293 --- /dev/null +++ b/tools/preprocess/test/parser.cpp @@ -0,0 +1,90 @@ +INTERFACE: + +struct Foo +{ + struct Bar + { + int baz; + }; + +public: + int alreadythere(); + inline int alsoalreadythere(); +}; + +IMPLEMENTATION: + +#include "foo.h" + +inline +int bar() +{} + +// Try multiline NEEDS +inline NEEDS["foo.h", + bar] +int baz() +{} + +// Try function arguments +unsigned +somefunc(unsigned (*func1)(), + unsigned (*func2)()) +{ +} + +// Try function-pointer typedef +typedef int (* diag_printf_t) (const char *, ...); +typedef int (**dblfptr) (void); +typedef int (* arrfptr[20]) (void); + +// Try to initialize a nested structure object. +struct Foo::Bar some_bar = { 1 }; + +// And add a Foo function +void Foo::func () +{} + +// Try default arguments +void Foo::bar (int i = 15, int j = somefunc(0, somefunc(0, 0))) +{} + +// Try a constructor with weird syntax +PUBLIC +Foo::Foo () + : something (reinterpret_cast(Baz::bla())) +{} + +// Try implementing an already-declared function +IMPLEMENT int +Foo::alreadythere() +{} + +IMPLEMENT inline int +Foo::alsoalreadythere() +{} + +// +// Try some commented-out code -- only #if 0 supported at the moment. +// +#if 0 + +#ifdef FOO +funny +#else +even funnier +#endif + +#else // ! 0 + +void find_this (); + +#if 0 +but not this +#endif + +#ifdef HEILIGE_WEIHNACHT +static void present_this (); +#endif + +#endif diff --git a/tools/preprocess/test/static.cpp b/tools/preprocess/test/static.cpp new file mode 100644 index 00000000..f0e4b099 --- /dev/null +++ b/tools/preprocess/test/static.cpp @@ -0,0 +1,25 @@ +INTERFACE: + +IMPLEMENTATION: + +extern "C" { + extern char _mappings_1, _mappings_end_1; +} + +static const vm_offset_t mem_alloc_region + = reinterpret_cast(&_mappings_1); + +static const vm_offset_t mem_alloc_region_end + = reinterpret_cast(&_mappings_end_1); + +static kmem_slab_t *amm_entry_cache; + +static amm_t region_amm; +static oskit_addr_t end_of_last_region; +static helping_lock_t region_lock; + +static char keymap[128][2] = { + {'[', '{'}, +// {']', '}'}, /* 27 */ + {'+', '*'}, /* 27 */ +}; diff --git a/tools/preprocess/test/template.cpp b/tools/preprocess/test/template.cpp new file mode 100644 index 00000000..6498a0cc --- /dev/null +++ b/tools/preprocess/test/template.cpp @@ -0,0 +1,236 @@ +INTERFACE: + +template +class stack_t; + +template +class stack_top_t +{ +private: + friend class stack_t; + + // Dont change the layout !!, comp_and_swap2 expects + // version and _next next to each other, in that order + int _version; + T *_next; +}; + +template +class stack_t +{ +private: + stack_top_t _head; +}; + +IMPLEMENTATION: + +// +// atomic-manipulation functions +// + +// typesafe variants +template +inline bool compare_and_swap(I *ptr, I oldval, I newval) +{ + return compare_and_swap(reinterpret_cast(ptr), + *reinterpret_cast(&oldval), + *reinterpret_cast(&newval)); +} + +template +inline bool test_and_set(I *l) +{ + return test_and_set(reinterpret_cast(l)); +} + +// +// stack_top_t +// + +// template +// stack_top_t & +// stack_top_t::operator=(const stack_top_t& _copy){ +// _version = _copy._version; +// _next = _copy._next; +// return *this; +// } + +PUBLIC inline +template +stack_top_t::stack_top_t (int version, T *next) + : _version (version), + _next (next) +{} + +PUBLIC inline +template +stack_top_t::stack_top_t () + : _version (0), + _next (0) +{} + +// +// stack_t +// + +PUBLIC +template +stack_t::stack_t() + : _head (0, 0) +{} + +PUBLIC +template +int +stack_t::insert(T *e) +{ + stack_top_t old_head, + new_head; + + do { + e->set_next(_head._next); + old_head = _head; + new_head._version = _head._version+1; + new_head._next = e; + } while (! compare_and_swap2((int *) &_head, + (int *) &old_head, + (int *) &new_head)); + return new_head._version; +} + +PUBLIC +template +T* +stack_t::dequeue() +{ + stack_top_t old_head, + new_head; + + T *first; + + do { + old_head = _head; + + first = _head._next; + if(! first){ + break; + } + + new_head._next = first->get_next(); + new_head._version = _head._version + 1; + } while (! compare_and_swap2((int *) &_head, + (int *) &old_head, + (int *) &new_head)); + // XXX Why did the old implementation test on e ? + // while (e && ! compare_and_swap(&_first, e, e->list_property.next)); + // This is necessary to handle the case of a empty stack. + + // return old_head._next; + return first; +} + +// This version of dequeue only returns a value +// if it is equal to the one passed as top +PUBLIC +template +T* +stack_t::dequeue(T *top) +{ + stack_top_t old_head, + new_head; + // stack_elem_t *first; + + old_head._version = _head._version; // version doesnt matter + old_head._next = top; // cas will fail, if top aint at top + if(!_head._next){ // empty stack + return 0; + } + new_head._version = _head._version + 1; + new_head._next = top->get_next(); + + + if(! compare_and_swap2((int *) &_head, + (int *) &old_head, + (int *) &new_head)) + // we didnt succeed + return 0; + else + // top was on top , so we dequeued it + return top; +} + +PUBLIC +template +T* +stack_t::first() +{ + return _head._next; +} + +PUBLIC +template +void +stack_t::reset() +{ + _head._version = 0; + _head._next = 0; +} + +template +stack_t* +create_stack() +{ + return new stack_t(); +} + +template <> +stack_t* +create_stack() +{ + return new stack(); +} + +template <> +inline +stack_t* +create_stack() +{ + return new stack(); +} + +// +// Member templates +// + +class Foo +{ + template T* goo(T* t); +}; + +template +class TFoo +{ +}; + +PUBLIC +template +T* +Foo::bar (T* t) +{ +} + +IMPLEMENT +template +T* +Foo::goo (T* t) +{ +} + +PUBLIC +template +template +T* +TFoo::baz (T* t) +{ +} + diff --git a/tools/preprocess/test/variable.cpp b/tools/preprocess/test/variable.cpp new file mode 100644 index 00000000..6e1a57da --- /dev/null +++ b/tools/preprocess/test/variable.cpp @@ -0,0 +1,6 @@ +IMPLEMENTATION: + +int (Foo::*func_vec[100]) (int arg) = +{ + 0, +}; diff --git a/tools/preprocess/test/verify/c-preproc.cc b/tools/preprocess/test/verify/c-preproc.cc new file mode 100644 index 00000000..67b342f3 --- /dev/null +++ b/tools/preprocess/test/verify/c-preproc.cc @@ -0,0 +1,24 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#include "c-preproc.h" +#include "c-preproc_i.h" + +#line 4 "c-preproc.cpp" + +// set CS (missing from OSKIT) +#define set_cs(cs) \ + asm volatile \ + ("ljmp %0,$1f \n1:" \ + : : "i" (cs)); + +#line 10 "c-preproc.cpp" + +void +function(void) +{ +#if 1 + bar (); +#else + foo (); +#endif +} diff --git a/tools/preprocess/test/verify/c-preproc.h b/tools/preprocess/test/verify/c-preproc.h new file mode 100644 index 00000000..5e37080c --- /dev/null +++ b/tools/preprocess/test/verify/c-preproc.h @@ -0,0 +1,15 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef c_preproc_h +#define c_preproc_h + +// +// INTERFACE definition follows +// + + +#line 11 "c-preproc.cpp" +void +function(void); + +#endif // c_preproc_h diff --git a/tools/preprocess/test/verify/c-preproc_i.h b/tools/preprocess/test/verify/c-preproc_i.h new file mode 100644 index 00000000..24adf030 --- /dev/null +++ b/tools/preprocess/test/verify/c-preproc_i.h @@ -0,0 +1,6 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef c_preproc_i_h +#define c_preproc_i_h + +#endif // c_preproc_i_h diff --git a/tools/preprocess/test/verify/comment_in_string.cc b/tools/preprocess/test/verify/comment_in_string.cc new file mode 100644 index 00000000..34b2de48 --- /dev/null +++ b/tools/preprocess/test/verify/comment_in_string.cc @@ -0,0 +1,30 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#include "comment_in_string.h" +#include "comment_in_string_i.h" + +#line 4 "comment_in_string.cpp" + +int foo(char *s); + +#line 6 "comment_in_string.cpp" + +void irq_init(unsigned char master_base, unsigned char slave_base) +{ + if (!(foo(" -vmware")) + { + foo("outb_p(MASTER_OCW, 0xfb); // unmask irq2"); + } + else + { + foo("using normal pic mode \n"); + } +} + +#line 18 "comment_in_string.cpp" + +void bar() +{ + foo ("if (0) {"); + foo ("} // if(0)"); +} diff --git a/tools/preprocess/test/verify/comment_in_string.h b/tools/preprocess/test/verify/comment_in_string.h new file mode 100644 index 00000000..cfe129e2 --- /dev/null +++ b/tools/preprocess/test/verify/comment_in_string.h @@ -0,0 +1,17 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef comment_in_string_h +#define comment_in_string_h + +// +// INTERFACE definition follows +// + + +#line 7 "comment_in_string.cpp" +void irq_init(unsigned char master_base, unsigned char slave_base); + +#line 19 "comment_in_string.cpp" +void bar(); + +#endif // comment_in_string_h diff --git a/tools/preprocess/test/verify/comment_in_string_i.h b/tools/preprocess/test/verify/comment_in_string_i.h new file mode 100644 index 00000000..cd94db0d --- /dev/null +++ b/tools/preprocess/test/verify/comment_in_string_i.h @@ -0,0 +1,6 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef comment_in_string_i_h +#define comment_in_string_i_h + +#endif // comment_in_string_i_h diff --git a/tools/preprocess/test/verify/default_args.cc b/tools/preprocess/test/verify/default_args.cc new file mode 100644 index 00000000..8a42412b --- /dev/null +++ b/tools/preprocess/test/verify/default_args.cc @@ -0,0 +1,13 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#include "default_args.h" +#include "default_args_i.h" + +#line 26 "default_args.cpp" + +extern "C" +void +disasm_bytes(char *buffer, unsigned len, unsigned va, unsigned task, + int show_symbols, int show_intel_syntax, + int (*peek_task)(unsigned addr, unsigned task), + const char* (*get_symbol)(unsigned addr, unsigned task)) WEAK; diff --git a/tools/preprocess/test/verify/default_args.h b/tools/preprocess/test/verify/default_args.h new file mode 100644 index 00000000..4aad967f --- /dev/null +++ b/tools/preprocess/test/verify/default_args.h @@ -0,0 +1,52 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef default_args_h +#define default_args_h + +// +// INTERFACE definition follows +// + + +#line 6 "default_args.cpp" +template std::vector +vec(T f1 = T(), T f2 = T(), T f3 = T(), + T f4 = T(), T f5 = T(), T f6 = T()); + +// +// IMPLEMENTATION includes follow (for use by inline functions/templates) +// + +#line 1 "default_args.cpp" +#include + +// +// IMPLEMENTATION of function templates +// + + +#line 4 "default_args.cpp" + + +template std::vector +vec(T f1, T f2, T f3, + T f4, T f5, T f6) +{ + std::vector v; + if (f1 != T()) { + v.push_back (f1); + if (f2 != T()) { + v.push_back (f2); + if (f3 != T()) { + v.push_back (f3); + if (f4 != T()) { + v.push_back (f4); + if (f5 != T()) { + v.push_back (f5); + if (f6 != T()) { + v.push_back (f6); + }}}}}} + return v; +} + +#endif // default_args_h diff --git a/tools/preprocess/test/verify/default_args_i.h b/tools/preprocess/test/verify/default_args_i.h new file mode 100644 index 00000000..622b6cba --- /dev/null +++ b/tools/preprocess/test/verify/default_args_i.h @@ -0,0 +1,6 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef default_args_i_h +#define default_args_i_h + +#endif // default_args_i_h diff --git a/tools/preprocess/test/verify/drop_multi1-ext.cc b/tools/preprocess/test/verify/drop_multi1-ext.cc new file mode 100644 index 00000000..5fb3d18b --- /dev/null +++ b/tools/preprocess/test/verify/drop_multi1-ext.cc @@ -0,0 +1,5 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#include "drop_multi1.h" +#include "drop_multi1_i.h" + diff --git a/tools/preprocess/test/verify/drop_multi1.cc b/tools/preprocess/test/verify/drop_multi1.cc new file mode 100644 index 00000000..58c6248f --- /dev/null +++ b/tools/preprocess/test/verify/drop_multi1.cc @@ -0,0 +1,39 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#include "drop_multi1.h" +#include "drop_multi1_i.h" + + +#line 20 "dropsection.cpp" + +void +Gen_foo::bar( unsigned x ) +{ + // do soemthing with x; +} + +#line 26 "dropsection.cpp" + +void +Gen_foo_ext::test() +{ + // the test +} + +#line 44 "dropsection.cpp" + +int +Gen_foo::foo( int y ) +{ + // just return y + return y; +} + +#line 53 "dropsection.cpp" + +int +Gen_foo::tust( int y ) +{ + // just return y + return y; +} diff --git a/tools/preprocess/test/verify/drop_multi1.h b/tools/preprocess/test/verify/drop_multi1.h new file mode 100644 index 00000000..39e8c923 --- /dev/null +++ b/tools/preprocess/test/verify/drop_multi1.h @@ -0,0 +1,43 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef drop_multi1_h +#define drop_multi1_h + +// +// INTERFACE definition follows +// + +#line 2 "dropsection.cpp" + +class Gen_foo +{ +public: + int baz; + +protected: + int foo( int ); + + +public: +#line 21 "dropsection.cpp" + void + bar( unsigned x ); + +#line 54 "dropsection.cpp" + int + tust( int y ); +}; +#line 12 "dropsection.cpp" + +class Gen_foo_ext : private Gen_foo, public Ixdebix +{ +protected: + unsigned stuff; + +public: +#line 27 "dropsection.cpp" + void + test(); +}; + +#endif // drop_multi1_h diff --git a/tools/preprocess/test/verify/drop_multi1_i.h b/tools/preprocess/test/verify/drop_multi1_i.h new file mode 100644 index 00000000..873ad9f5 --- /dev/null +++ b/tools/preprocess/test/verify/drop_multi1_i.h @@ -0,0 +1,6 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef drop_multi1_i_h +#define drop_multi1_i_h + +#endif // drop_multi1_i_h diff --git a/tools/preprocess/test/verify/drop_multi2-ext.cc b/tools/preprocess/test/verify/drop_multi2-ext.cc new file mode 100644 index 00000000..6be6addd --- /dev/null +++ b/tools/preprocess/test/verify/drop_multi2-ext.cc @@ -0,0 +1,13 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#include "drop_multi2.h" +#include "drop_multi2_i.h" + + +#line 16 "dropsection-ext.cpp" + +int +Gen_foo::do_something_private() +{ + // just do it +} diff --git a/tools/preprocess/test/verify/drop_multi2.cc b/tools/preprocess/test/verify/drop_multi2.cc new file mode 100644 index 00000000..aec4a4c8 --- /dev/null +++ b/tools/preprocess/test/verify/drop_multi2.cc @@ -0,0 +1,39 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#include "drop_multi2.h" +#include "drop_multi2_i.h" + + +#line 20 "dropsection.cpp" + +void +Gen_foo::bar( unsigned x ) +{ + // do soemthing with x; +} + +#line 26 "dropsection.cpp" + +void +Gen_foo_ext::test() +{ + // the test +} + +#line 44 "dropsection.cpp" + +int +Gen_foo::foo( int y ) +{ + // just return y + return y; +} + +#line 53 "dropsection.cpp" + +int +Gen_foo::tust( int y ) +{ + // just return y + return y; +} diff --git a/tools/preprocess/test/verify/drop_multi2.h b/tools/preprocess/test/verify/drop_multi2.h new file mode 100644 index 00000000..1157167a --- /dev/null +++ b/tools/preprocess/test/verify/drop_multi2.h @@ -0,0 +1,64 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef drop_multi2_h +#define drop_multi2_h + +// +// INTERFACE definition follows +// + +#line 2 "dropsection.cpp" + +class Gen_foo + +: public Gen_bar +{ +public: + int baz; + +protected: + int foo( int ); + + +#line 2 "dropsection-ext.cpp" +private: + +public: + int extra_var; + +public: +#line 21 "dropsection.cpp" + void + bar( unsigned x ); + +#line 54 "dropsection.cpp" + int + tust( int y ); + +private: +#line 17 "dropsection-ext.cpp" + int + do_something_private(); +}; +#line 12 "dropsection.cpp" + +class Gen_foo_ext : private Gen_foo, public Ixdebix + +, public Gen_baz +{ +protected: + unsigned stuff; + +#line 8 "dropsection-ext.cpp" +private: + +private: + char *extension; + +public: +#line 27 "dropsection.cpp" + void + test(); +}; + +#endif // drop_multi2_h diff --git a/tools/preprocess/test/verify/drop_multi2_i.h b/tools/preprocess/test/verify/drop_multi2_i.h new file mode 100644 index 00000000..fde38e88 --- /dev/null +++ b/tools/preprocess/test/verify/drop_multi2_i.h @@ -0,0 +1,6 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef drop_multi2_i_h +#define drop_multi2_i_h + +#endif // drop_multi2_i_h diff --git a/tools/preprocess/test/verify/drop_single1.cc b/tools/preprocess/test/verify/drop_single1.cc new file mode 100644 index 00000000..6b8d392e --- /dev/null +++ b/tools/preprocess/test/verify/drop_single1.cc @@ -0,0 +1,30 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#include "drop_single1.h" +#include "drop_single1_i.h" + + +#line 20 "dropsection.cpp" + +void +Gen_foo::bar( unsigned x ) +{ + // do soemthing with x; +} + +#line 26 "dropsection.cpp" + +void +Gen_foo_ext::test() +{ + // the test +} + +#line 53 "dropsection.cpp" + +int +Gen_foo::tust( int y ) +{ + // just return y + return y; +} diff --git a/tools/preprocess/test/verify/drop_single1.h b/tools/preprocess/test/verify/drop_single1.h new file mode 100644 index 00000000..8bb7a285 --- /dev/null +++ b/tools/preprocess/test/verify/drop_single1.h @@ -0,0 +1,43 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef drop_single1_h +#define drop_single1_h + +// +// INTERFACE definition follows +// + +#line 2 "dropsection.cpp" + +class Gen_foo +{ +public: + int baz; + +protected: + int foo( int ); + + +public: +#line 21 "dropsection.cpp" + void + bar( unsigned x ); + +#line 54 "dropsection.cpp" + int + tust( int y ); +}; +#line 12 "dropsection.cpp" + +class Gen_foo_ext : private Gen_foo, public Ixdebix +{ +protected: + unsigned stuff; + +public: +#line 27 "dropsection.cpp" + void + test(); +}; + +#endif // drop_single1_h diff --git a/tools/preprocess/test/verify/drop_single1_i.h b/tools/preprocess/test/verify/drop_single1_i.h new file mode 100644 index 00000000..e63bb12f --- /dev/null +++ b/tools/preprocess/test/verify/drop_single1_i.h @@ -0,0 +1,6 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef drop_single1_i_h +#define drop_single1_i_h + +#endif // drop_single1_i_h diff --git a/tools/preprocess/test/verify/drop_single2.cc b/tools/preprocess/test/verify/drop_single2.cc new file mode 100644 index 00000000..81ef0e7d --- /dev/null +++ b/tools/preprocess/test/verify/drop_single2.cc @@ -0,0 +1,31 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#include "drop_single2.h" +#include "drop_single2_i.h" + + +#line 20 "dropsection.cpp" + +void +Gen_foo::bar( unsigned x ) +{ + // do soemthing with x; +} + +#line 26 "dropsection.cpp" + +void +Gen_foo_ext::test() +{ + // the test +} + +#line 34 "dropsection.cpp" + +int +Gen_foo::foo( int y ) +{ + // do something strange with y + bar(y); + return y; +} diff --git a/tools/preprocess/test/verify/drop_single2.h b/tools/preprocess/test/verify/drop_single2.h new file mode 100644 index 00000000..6e560b3e --- /dev/null +++ b/tools/preprocess/test/verify/drop_single2.h @@ -0,0 +1,39 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef drop_single2_h +#define drop_single2_h + +// +// INTERFACE definition follows +// + +#line 2 "dropsection.cpp" + +class Gen_foo +{ +public: + int baz; + +protected: + int foo( int ); + + +public: +#line 21 "dropsection.cpp" + void + bar( unsigned x ); +}; +#line 12 "dropsection.cpp" + +class Gen_foo_ext : private Gen_foo, public Ixdebix +{ +protected: + unsigned stuff; + +public: +#line 27 "dropsection.cpp" + void + test(); +}; + +#endif // drop_single2_h diff --git a/tools/preprocess/test/verify/drop_single2_i.h b/tools/preprocess/test/verify/drop_single2_i.h new file mode 100644 index 00000000..e1573cef --- /dev/null +++ b/tools/preprocess/test/verify/drop_single2_i.h @@ -0,0 +1,6 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef drop_single2_i_h +#define drop_single2_i_h + +#endif // drop_single2_i_h diff --git a/tools/preprocess/test/verify/drop_single3.cc b/tools/preprocess/test/verify/drop_single3.cc new file mode 100644 index 00000000..583c891d --- /dev/null +++ b/tools/preprocess/test/verify/drop_single3.cc @@ -0,0 +1,39 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#include "drop_single3.h" +#include "drop_single3_i.h" + + +#line 20 "dropsection.cpp" + +void +Gen_foo::bar( unsigned x ) +{ + // do soemthing with x; +} + +#line 26 "dropsection.cpp" + +void +Gen_foo_ext::test() +{ + // the test +} + +#line 44 "dropsection.cpp" + +int +Gen_foo::foo( int y ) +{ + // just return y + return y; +} + +#line 53 "dropsection.cpp" + +int +Gen_foo::tust( int y ) +{ + // just return y + return y; +} diff --git a/tools/preprocess/test/verify/drop_single3.h b/tools/preprocess/test/verify/drop_single3.h new file mode 100644 index 00000000..a93f16ad --- /dev/null +++ b/tools/preprocess/test/verify/drop_single3.h @@ -0,0 +1,43 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef drop_single3_h +#define drop_single3_h + +// +// INTERFACE definition follows +// + +#line 2 "dropsection.cpp" + +class Gen_foo +{ +public: + int baz; + +protected: + int foo( int ); + + +public: +#line 21 "dropsection.cpp" + void + bar( unsigned x ); + +#line 54 "dropsection.cpp" + int + tust( int y ); +}; +#line 12 "dropsection.cpp" + +class Gen_foo_ext : private Gen_foo, public Ixdebix +{ +protected: + unsigned stuff; + +public: +#line 27 "dropsection.cpp" + void + test(); +}; + +#endif // drop_single3_h diff --git a/tools/preprocess/test/verify/drop_single3_i.h b/tools/preprocess/test/verify/drop_single3_i.h new file mode 100644 index 00000000..18af52dc --- /dev/null +++ b/tools/preprocess/test/verify/drop_single3_i.h @@ -0,0 +1,6 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef drop_single3_i_h +#define drop_single3_i_h + +#endif // drop_single3_i_h diff --git a/tools/preprocess/test/verify/explicit.cc b/tools/preprocess/test/verify/explicit.cc new file mode 100644 index 00000000..a1686b64 --- /dev/null +++ b/tools/preprocess/test/verify/explicit.cc @@ -0,0 +1,11 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#include "explicit.h" +#include "explicit_i.h" + + +#line 8 "explicit.cpp" + + +Foo::Foo(int bar) +{} diff --git a/tools/preprocess/test/verify/explicit.h b/tools/preprocess/test/verify/explicit.h new file mode 100644 index 00000000..b4631a8e --- /dev/null +++ b/tools/preprocess/test/verify/explicit.h @@ -0,0 +1,20 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef explicit_h +#define explicit_h + +// +// INTERFACE definition follows +// + +#line 2 "explicit.cpp" + +class Foo +{ + +public: +#line 10 "explicit.cpp" + explicit Foo(int bar); +}; + +#endif // explicit_h diff --git a/tools/preprocess/test/verify/explicit_i.h b/tools/preprocess/test/verify/explicit_i.h new file mode 100644 index 00000000..bfb21fe9 --- /dev/null +++ b/tools/preprocess/test/verify/explicit_i.h @@ -0,0 +1,6 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef explicit_i_h +#define explicit_i_h + +#endif // explicit_i_h diff --git a/tools/preprocess/test/verify/extern_c.cc b/tools/preprocess/test/verify/extern_c.cc new file mode 100644 index 00000000..498dd273 --- /dev/null +++ b/tools/preprocess/test/verify/extern_c.cc @@ -0,0 +1,11 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#include "extern_c.h" +#include "extern_c_i.h" + +#line 4 "extern_c.cpp" + +extern "C" +{ + extern char _mappings_1, _mappings_end_1; +} diff --git a/tools/preprocess/test/verify/extern_c.h b/tools/preprocess/test/verify/extern_c.h new file mode 100644 index 00000000..3e548a3a --- /dev/null +++ b/tools/preprocess/test/verify/extern_c.h @@ -0,0 +1,6 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef extern_c_h +#define extern_c_h + +#endif // extern_c_h diff --git a/tools/preprocess/test/verify/extern_c_i.h b/tools/preprocess/test/verify/extern_c_i.h new file mode 100644 index 00000000..801e8211 --- /dev/null +++ b/tools/preprocess/test/verify/extern_c_i.h @@ -0,0 +1,6 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef extern_c_i_h +#define extern_c_i_h + +#endif // extern_c_i_h diff --git a/tools/preprocess/test/verify/inline.cc b/tools/preprocess/test/verify/inline.cc new file mode 100644 index 00000000..f19c5646 --- /dev/null +++ b/tools/preprocess/test/verify/inline.cc @@ -0,0 +1,33 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#include "inline.h" +#include "inline_i.h" + + +#line 48 "inline.cpp" + +// This inline funtion is public only because it is needed by an +// extern-"C" function. So we do not want to export it. + +inline void +Foo::bar() +{ + +} + +#line 57 "inline.cpp" + +// Try both NOEXPORT and NEEDED. + +inline void +Foo::baz() +{ +} + +#line 64 "inline.cpp" + +extern "C" +void function(Foo* f) +{ + f->bar(); +} diff --git a/tools/preprocess/test/verify/inline.h b/tools/preprocess/test/verify/inline.h new file mode 100644 index 00000000..986335d3 --- /dev/null +++ b/tools/preprocess/test/verify/inline.h @@ -0,0 +1,125 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef inline_h +#define inline_h + +// +// INTERFACE definition follows +// + +#line 2 "inline.cpp" + +class Foo +{ + +public: +#line 49 "inline.cpp" + // This inline funtion is public only because it is needed by an + // extern-"C" function. So we do not want to export it. + + inline void + bar(); + +#line 58 "inline.cpp" + // Try both NOEXPORT and NEEDED. + + inline void + baz(); + +private: +#line 26 "inline.cpp" + inline bool + private_func(); +}; +#line 6 "inline.cpp" + +class Bar +{ + +public: +#line 44 "inline.cpp" + inline void + public_func(); + +private: +#line 32 "inline.cpp" + inline bool + private_func(); + +#line 38 "inline.cpp" + inline void + another_private_func(); +}; + +#line 65 "inline.cpp" +extern "C" +void function(Foo* f); + +#line 71 "inline.cpp" +template inline void* xcast(T* t); + +// +// IMPLEMENTATION of inline functions (and needed classes) +// + +#line 12 "inline.cpp" + +// Test dependency-chain resolver + +class Frob +{ + +private: +#line 20 "inline.cpp" + inline bool + private_func(); +}; + +#line 24 "inline.cpp" + + +inline bool +Foo::private_func() +{ +} + +#line 30 "inline.cpp" + + +inline bool +Bar::private_func() +{ +} + +#line 36 "inline.cpp" + + +inline void +Bar::another_private_func() +{ +} + +#line 18 "inline.cpp" + + +inline bool +Frob::private_func() +{ +} + +#line 42 "inline.cpp" + + +inline void +Bar::public_func() +{ +} + +#line 70 "inline.cpp" + + template inline void* xcast(T* t) +{ + return (void*) t; +} + +#endif // inline_h diff --git a/tools/preprocess/test/verify/inline_i.h b/tools/preprocess/test/verify/inline_i.h new file mode 100644 index 00000000..e733ac3e --- /dev/null +++ b/tools/preprocess/test/verify/inline_i.h @@ -0,0 +1,6 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef inline_i_h +#define inline_i_h + +#endif // inline_i_h diff --git a/tools/preprocess/test/verify/inline_noinline.cc b/tools/preprocess/test/verify/inline_noinline.cc new file mode 100644 index 00000000..10e2ac0e --- /dev/null +++ b/tools/preprocess/test/verify/inline_noinline.cc @@ -0,0 +1,73 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#include "inline_noinline.h" +#include "inline_noinline_i.h" + + +#line 18 "inline.cpp" + + +bool +Frob::private_func() +{ +} + +#line 24 "inline.cpp" + + +bool +Foo::private_func() +{ +} + +#line 30 "inline.cpp" + + +bool +Bar::private_func() +{ +} + +#line 36 "inline.cpp" + + +void +Bar::another_private_func() +{ +} + +#line 42 "inline.cpp" + + +void +Bar::public_func() +{ +} + +#line 48 "inline.cpp" + +// This inline funtion is public only because it is needed by an +// extern-"C" function. So we do not want to export it. + +void +Foo::bar() +{ + +} + +#line 57 "inline.cpp" + +// Try both NOEXPORT and NEEDED. + +void +Foo::baz() +{ +} + +#line 64 "inline.cpp" + +extern "C" +void function(Foo* f) +{ + f->bar(); +} diff --git a/tools/preprocess/test/verify/inline_noinline.h b/tools/preprocess/test/verify/inline_noinline.h new file mode 100644 index 00000000..fda5df47 --- /dev/null +++ b/tools/preprocess/test/verify/inline_noinline.h @@ -0,0 +1,73 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef inline_noinline_h +#define inline_noinline_h + +// +// INTERFACE definition follows +// + +#line 2 "inline.cpp" + +class Foo +{ + +public: +#line 49 "inline.cpp" + // This inline funtion is public only because it is needed by an + // extern-"C" function. So we do not want to export it. + + void + bar(); + +#line 58 "inline.cpp" + // Try both NOEXPORT and NEEDED. + + void + baz(); + +private: +#line 26 "inline.cpp" + bool + private_func(); +}; +#line 6 "inline.cpp" + +class Bar +{ + +public: +#line 44 "inline.cpp" + void + public_func(); + +private: +#line 32 "inline.cpp" + bool + private_func(); + +#line 38 "inline.cpp" + void + another_private_func(); +}; + +#line 65 "inline.cpp" +extern "C" +void function(Foo* f); + +#line 71 "inline.cpp" +template void* xcast(T* t); + +// +// IMPLEMENTATION of function templates +// + + +#line 70 "inline.cpp" + + template void* xcast(T* t) +{ + return (void*) t; +} + +#endif // inline_noinline_h diff --git a/tools/preprocess/test/verify/inline_noinline_i.h b/tools/preprocess/test/verify/inline_noinline_i.h new file mode 100644 index 00000000..12699b47 --- /dev/null +++ b/tools/preprocess/test/verify/inline_noinline_i.h @@ -0,0 +1,18 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef inline_noinline_i_h +#define inline_noinline_i_h +#line 12 "inline.cpp" + +// Test dependency-chain resolver + +class Frob +{ + +private: +#line 20 "inline.cpp" + bool + private_func(); +}; + +#endif // inline_noinline_i_h diff --git a/tools/preprocess/test/verify/interface.cc b/tools/preprocess/test/verify/interface.cc new file mode 100644 index 00000000..90a2add2 --- /dev/null +++ b/tools/preprocess/test/verify/interface.cc @@ -0,0 +1,14 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#include "interfacepublic.h" +#include "interface_i.h" + + +#line 9 "interface.cpp" + + +void +Foo::func1() +{ + +} diff --git a/tools/preprocess/test/verify/interface_i.h b/tools/preprocess/test/verify/interface_i.h new file mode 100644 index 00000000..2cfa6b8e --- /dev/null +++ b/tools/preprocess/test/verify/interface_i.h @@ -0,0 +1,6 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef interface_i_h +#define interface_i_h + +#endif // interface_i_h diff --git a/tools/preprocess/test/verify/interfacepublic.h b/tools/preprocess/test/verify/interfacepublic.h new file mode 100644 index 00000000..b2221b7d --- /dev/null +++ b/tools/preprocess/test/verify/interfacepublic.h @@ -0,0 +1,22 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef interface_h +#define interface_h + +// +// INTERFACE definition follows +// + +#line 2 "interface.cpp" + +// This is class Foo. +class Foo +{ + +public: +#line 11 "interface.cpp" + void + func1(); +}; + +#endif // interface_h diff --git a/tools/preprocess/test/verify/line.cc b/tools/preprocess/test/verify/line.cc new file mode 100644 index 00000000..00cdb0f3 --- /dev/null +++ b/tools/preprocess/test/verify/line.cc @@ -0,0 +1,19 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#include "line.h" +#include "line_i.h" + + +#line 9 "line.cpp" + +// A long, multiline comment in front of this function definition. +// Also, a lot of specifiers that need to be handled. + + + + +void +Foo::func1() +{ + +} diff --git a/tools/preprocess/test/verify/line.h b/tools/preprocess/test/verify/line.h new file mode 100644 index 00000000..a7d6ce09 --- /dev/null +++ b/tools/preprocess/test/verify/line.h @@ -0,0 +1,28 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef line_h +#define line_h + +// +// INTERFACE definition follows +// + +#line 2 "line.cpp" + +// This is class Foo. +class Foo +{ + +public: +#line 10 "line.cpp" + // A long, multiline comment in front of this function definition. + // Also, a lot of specifiers that need to be handled. + + + + + static void + func1(); +}; + +#endif // line_h diff --git a/tools/preprocess/test/verify/line_i.h b/tools/preprocess/test/verify/line_i.h new file mode 100644 index 00000000..7996c91d --- /dev/null +++ b/tools/preprocess/test/verify/line_i.h @@ -0,0 +1,6 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef line_i_h +#define line_i_h + +#endif // line_i_h diff --git a/tools/preprocess/test/verify/line_nh.cc b/tools/preprocess/test/verify/line_nh.cc new file mode 100644 index 00000000..2fa3b54a --- /dev/null +++ b/tools/preprocess/test/verify/line_nh.cc @@ -0,0 +1,19 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#include "line_nh.h" +#include "line_nh_i.h" + + +#line 9 "line.cpp" + +// A long, multiline comment in front of this function definition. +// Also, a lot of specifiers that need to be handled. + + + + +void +Foo::func1() +{ + +} diff --git a/tools/preprocess/test/verify/line_nh.h b/tools/preprocess/test/verify/line_nh.h new file mode 100644 index 00000000..bbe70c07 --- /dev/null +++ b/tools/preprocess/test/verify/line_nh.h @@ -0,0 +1,21 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef line_nh_h +#define line_nh_h + +// +// INTERFACE definition follows +// + + +// This is class Foo. +class Foo +{ + +public: + // A long, multiline comment in front of this function definition. + // Also, a lot of specifiers that need to be handled. + static void func1(); +}; + +#endif // line_nh_h diff --git a/tools/preprocess/test/verify/line_nh_i.h b/tools/preprocess/test/verify/line_nh_i.h new file mode 100644 index 00000000..71df774d --- /dev/null +++ b/tools/preprocess/test/verify/line_nh_i.h @@ -0,0 +1,6 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef line_nh_i_h +#define line_nh_i_h + +#endif // line_nh_i_h diff --git a/tools/preprocess/test/verify/line_not.cc b/tools/preprocess/test/verify/line_not.cc new file mode 100644 index 00000000..eb1d7ca6 --- /dev/null +++ b/tools/preprocess/test/verify/line_not.cc @@ -0,0 +1,15 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#include "line_not.h" +#include "line_not_i.h" + + + +// A long, multiline comment in front of this function definition. +// Also, a lot of specifiers that need to be handled. + +void +Foo::func1() +{ + +} diff --git a/tools/preprocess/test/verify/line_not.h b/tools/preprocess/test/verify/line_not.h new file mode 100644 index 00000000..11ab555d --- /dev/null +++ b/tools/preprocess/test/verify/line_not.h @@ -0,0 +1,21 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef line_not_h +#define line_not_h + +// +// INTERFACE definition follows +// + + +// This is class Foo. +class Foo +{ + +public: + // A long, multiline comment in front of this function definition. + // Also, a lot of specifiers that need to be handled. + static void func1(); +}; + +#endif // line_not_h diff --git a/tools/preprocess/test/verify/line_not_i.h b/tools/preprocess/test/verify/line_not_i.h new file mode 100644 index 00000000..bf9f83e2 --- /dev/null +++ b/tools/preprocess/test/verify/line_not_i.h @@ -0,0 +1,6 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef line_not_i_h +#define line_not_i_h + +#endif // line_not_i_h diff --git a/tools/preprocess/test/verify/mapping.cc b/tools/preprocess/test/verify/mapping.cc new file mode 100644 index 00000000..bb16c3b1 --- /dev/null +++ b/tools/preprocess/test/verify/mapping.cc @@ -0,0 +1,730 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#include "mapping.h" +#include "mapping_i.h" + +#line 48 "mapping.cpp" + +// The mapping database. + +// This implementation encodes mapping trees in very compact arrays of +// fixed sizes, prefixed by a tree header (mapping_tree_t). Array +// sizes can vary from 4 mappings to 4<<15 mappings. For each size, +// we set up a slab allocator. To grow or shrink the size of an +// array, we have to allocate a larger or smaller tree from the +// corresponding allocator and then copy the array elements. +// +// The array elements (mapping_t) contain a tree depth element. This +// depth and the relative position in the array is all information we +// need to derive tree structure information. Here is an example: +// +// array +// element depth +// number value comment +// -------------------------- +// 0 0 Sigma0 mapping +// 1 1 child of element #0 with depth 0 +// 2 2 child of element #1 with depth 1 +// 3 2 child of element #1 with depth 1 +// 4 3 child of element #3 with depth 2 +// 5 2 child of element #1 with depth 1 +// 6 3 child of element #5 with depth 2 +// 7 1 child of element #0 with depth 0 +// +// This array is a pre-order encoding of the following tree: +// +// 0 +// / \ +// 1 7 +// / | \ +// 2 3 5 +// | | +// 4 6 + +// IDEAS for enhancing this implementation: + +// We often have to find a tree header corresponding to a mapping. +// Currently, we do this by iterating backwards over the array +// containing the mappings until we find the Sigma0 mapping, from +// whose address we can compute the address of the tree header. If +// this becomes a problem, we could add one more byte to the mappings +// with a hint (negative array offset) where to find the sigma0 +// mapping. (If the hint value overflows, just iterate using the hint +// value of the mapping we find with the first hint value.) Another +// idea (from Adam) would be to just look up the tree header by using +// the physical address from the page-table lookup, but we would need +// to change the interface of the mapping database for that (pass in +// the physical address at all times), or we would have to include the +// physical address (or just the address of the tree header) in the +// mapdb_t-user-visible mapping_t (which could be different from the +// internal tree representation). (XXX: Implementing one of these +// ideas is probably worthwile doing!) + +// Instead of copying whole trees around when they grow or shrink a +// lot, or copying parts of trees when inserting an element, we could +// give up the array representation and add a "next" pointer to the +// elements -- that is, keep the tree of mappings in a +// pre-order-encoded singly-linked list (credits to: Christan Szmajda +// and Adam Wiggins). 24 bits would probably be enough to encode that +// pointer. Disadvantages: Mapping entries would be larger, and the +// cache-friendly space-locality of tree entries would be lost. + +// The current handling of superpages sucks rocks both in this module +// and in our user, ipc_map.cc. We could support multiple page sizes +// by not using a physframe[] array only for the largest page size. +// (Entries of that array point to the top-level mappings -- sigma0 +// mappings.) Mapping-tree entries would then either be regular +// mappings or pointers to an array of mappings of the next-smaller +// size. (credits: Christan Szmajda) +// +// physframe[] +// ------------------------------- +// | | | | | | | | | | | | | | | | array of ptr to 4M mapping_tree_t's +// ---|--------------------------- +// | +// v a mapping_tree_t +// --------------- +// | | tree header +// |-------------| +// | | mapping_t *or* ptr to array of ptr to 4K trees +// | | e.g. +// | ----------------| +// | | v array of ptr to 4M mapping_tree_t's +// --------------- ------------------------------- +// | | | | | | | | | | | | | | | | +// ---|--------------------------- +// | +// v a mapping_tree_t +// --------------- +// | | tree header +// |-------------| +// | | mapping_t +// | | +// | | +// | | +// --------------- +//- +#line 151 "mapping.cpp" + +#ifndef offsetof // should be defined in stddef.h, but isn't +#line 153 "mapping.cpp" +#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) +#line 154 "mapping.cpp" +#endif + +#line 176 "mapping.cpp" + +// public routines with inline implementations + +unsigned +mapping_tree_t::number_of_entries() const +{ + return mapdb_t::Size_factor << _size_id; +} + +#line 184 "mapping.cpp" + + +mapping_t * +mapping_tree_t::mappings() +{ + return & _mappings[0]; +} + +#line 211 "mapping.cpp" + + +mapping_t::mapping_t() +{} + +#line 215 "mapping.cpp" + + +mapping_s * +mapping_t::data() +{ + return reinterpret_cast(_data); +} + +#line 222 "mapping.cpp" + + +space_index_t +mapping_t::space() +{ + return space_index_t(data()->space); +} + +#line 229 "mapping.cpp" + + +vm_offset_t +mapping_t::vaddr() +{ + return (data()->address << PAGE_SHIFT); +} + +#line 236 "mapping.cpp" + + +vm_size_t +mapping_t::size() +{ + if ( data()->size ) + return SUPERPAGE_SIZE; + else + return PAGE_SIZE; +} + +#line 246 "mapping.cpp" + + +mapping_type_t +mapping_t::type() +{ + // return data()->type;; + return Map_mem; +} + +#line 254 "mapping.cpp" + + +bool +mapping_t::unused() +{ + return (data()->depth > Depth_max); +} + +#line 261 "mapping.cpp" + +mapping_tree_t * +mapping_t::tree() +{ + mapping_t *m = this; + + while (m->data()->depth > Depth_sigma0_mapping) + { + // jump in bigger steps if this is not a free mapping + if (! m->unused()) + { + m -= m->data()->depth; + continue; + } + + m--; + } + + return reinterpret_cast + (reinterpret_cast(m) - offsetof(mapping_tree_t, _mappings)); +} + +#line 282 "mapping.cpp" + +// +// more of class mapping_t +// + +mapping_t * +mapping_t::parent() +{ + if (data()->depth <= Depth_sigma0_mapping) + { + // Sigma0 mappings don't have a parent. + return 0; + } + + // Iterate over mapping entries of this tree backwards until we find + // an entry with a depth smaller than ours. (We assume here that + // "special" depths (empty, end) are larger than Depth_max.) + mapping_t *m = this - 1; + + while (m->data()->depth >= data()->depth) + m--; + + return m; +} + +#line 306 "mapping.cpp" + +mapping_t * +mapping_t::next_iter() +{ + mapping_tree_t *t = tree(); + mapping_t *last_in_tree = t->mappings() + t->number_of_entries() - 1; + + mapping_t *m = this; + + // Look for a valid element in the tree structure. + while (m != last_in_tree) + { + m++; + if (! m->unused()) + return m; // Found a valid entry! + + // Don't iterate to end of tree if this is the last tree entry. + if (m->data()->depth == Depth_end) + return 0; + } + + // Couldn't find a non-empty element behind ourselves in the tree + // structure. + return 0; +} + +#line 331 "mapping.cpp" + +mapping_t * +mapping_t::next_child(mapping_t *parent) +{ + // Find the next valid entry in the tree structure. + mapping_t *m = next_iter(); + + // If we didn't find an entry, or if the entry cannot be a child of + // "parent", return 0 + if (m == 0 + || m->data()->depth <= parent->data()->depth) + return 0; + + return m; // Found! +} + +#line 346 "mapping.cpp" + +// helpers + +// +// class mapping_tree_t +// + +// This function copies the elements of mapping tree src to mapping +// tree dst, ignoring empty elements (that is, compressing the +// source tree. In-place compression is supported. +void +mapping_tree_t::copy_compact_tree(mapping_tree_t *dst, mapping_tree_t *src) +{ + dst->_count = 0; + dst->_empty_count = 0; + + mapping_t *d = dst->mappings(); + + for (mapping_t *s = src->mappings(); + s < src->mappings() + src->number_of_entries(); + s++) + { + if (s->unused()) // entry free + { + if (s->data()->depth == Depth_end) + break; + continue; + } + + *d++ = *s; + dst->_count += 1; + } + + assert (dst->_count == src->_count); + assert (d < dst->mappings() + dst->number_of_entries()); + + d->data()->depth = Depth_end; + dst->mappings()[dst->number_of_entries() - 1].data()->depth = Depth_end; +} // copy_compact_tree() + +#line 397 "mapping.cpp" + + +mapdb_t::mapdb_t() +{ + vm_offset_t page_number = kmem::info()->main_memory.high / PAGE_SIZE + 1; + + // allocate physframe array + check ( physframe = reinterpret_cast + (kmem::alloc(page_number * sizeof(physframe_data))) ); + + memset(physframe, 0, page_number * sizeof(physframe_data)); + + // create a slab for each mapping tree size + for (int slab_number = 0; + slab_number <= Size_id_max; + slab_number++ ) + { + unsigned elem_size = + (Size_factor << slab_number) * sizeof(mapping_t) + + sizeof(mapping_tree_t); + + allocator_for_treesize[slab_number] = + new kmem_slab_t(((PAGE_SIZE / elem_size) < 40 + ? 8*PAGE_SIZE : PAGE_SIZE), + elem_size, 1); + } + + // create a sigma0 mapping for all physical pages + for (unsigned page_id = 0; page_id < page_number; page_id++) + { + mapping_tree_t *t; + check( (t = physframe[page_id].tree + = reinterpret_cast + (allocator_for_treesize[0]->alloc())) ); + + t->_count = 1; // 1 valid mapping + t->_size_id = 0; // size is equal to Size_factor << 0 + t->_empty_count = 0; // no gaps in tree representation + + t->mappings()[0].data()->depth = Depth_sigma0_mapping; + t->mappings()[0].data()->address = page_id; + t->mappings()[0].data()->space = config::sigma0_taskno; + t->mappings()[0].data()->size = 0; + + t->mappings()[1].data()->depth = Depth_end; + + // We also always set the end tag on last entry so that we can + // check whether it has been overwritten. + t->mappings()[t->number_of_entries() - 1].data()->depth = Depth_end; + } +} // mapdb_t() + +#line 448 "mapping.cpp" + + +// insert a new mapping entry with the given values as child of +// "parent" After locating the right place for the new entry, it will +// be stored there (if this place is empty) or the following entries +// moved by one entry. + +// We assume that there is at least one free entry at the end of the +// array so that at least one insert() operation can succeed between a +// lock()/free() pair of calls. This is guaranteed by the free() +// operation which allocates a larger tree if the current one becomes +// to small. +mapping_t * +mapdb_t::insert(mapping_t *parent, + space_t *space, + vm_offset_t va, + vm_size_t size, + mapping_type_t type) +{ + assert(type == Map_mem); // we don't yet support Map_io + + mapping_tree_t *t = parent->tree(); + + // We cannot continue if the last array entry is not free. This + // only happens if an earlier call to free() with this mapping tree + // couldn't allocate a bigger array. In this case, signal an + // out-of-memory condition. + if (! t->mappings()[t->number_of_entries() - 1].unused()) + return 0; + + // If the parent mapping already has the maximum depth, we cannot + // insert a child. + if (parent->data()->depth == Depth_max) + return 0; + + mapping_t *insert = 0; + + bool + found_free_entry = false, + need_to_move = false; + + mapping_t temp; + + // Find a free entry in the array encoding the tree, and find the + // insertion point for the new entry. These two entries might not + // be equivalent, so we may need to move entries backwards in the + // array. In this implementation, we move entries as we traverse + // the array, instead of doing one big memmove + for (mapping_t *m = parent + 1; + m < t->mappings() + t->number_of_entries(); + m++) + { + if (m->unused()) + { + // We found a free entry in the tree -- allocate it. + found_free_entry = true; + t->_count += 1; + + // Did we find an empty element != the end tag? + if (m->data()->depth == Depth_empty) + { + t->_empty_count -= 1; + } + // Else we have found the end tag. If there is another + // array entry left, apply a new end tag to the array + else if (m + 1 < t->mappings() + t->number_of_entries()) + { + (m + 1)->data()->depth = Depth_end; + } + + // if we haven't identified a place for inserting the new + // element, this is it. + if (! need_to_move) + insert = m; + } + else if (! need_to_move + && m->data()->depth <= parent->data()->depth) + { + // we found a non-descendant of ourselves -- need to make + // space for new child + need_to_move = true; + insert = m; + temp = *insert; + + continue; + } + + if (need_to_move) + { + // replace *m with temp (which used to be *(m - 1); but + // *(m - 1) has since been overwritten), and load temp with + // the old value of *m + mapping_t temp2; + + temp2 = *m; + *m = temp; + temp = temp2; + } + + if (found_free_entry) + break; + } + + assert(insert && found_free_entry); + + // found a place to insert new child. + insert->data()->depth = mapping_depth_t(parent->data()->depth + 1); + insert->data()->address = va >> PAGE_SHIFT; + insert->data()->space = space->space(); + insert->data()->size = (size == SUPERPAGE_SIZE); + + return insert; +} // insert() + +#line 561 "mapping.cpp" + +mapping_t * +mapdb_t::lookup(space_t *space, + vm_offset_t va, + mapping_type_t type) +{ + vm_offset_t phys = space->virt_to_phys(va); + + if (phys == 0xffffffff) + return 0; + + mapping_tree_t *t; + + // get and lock the tree. + // XXX For now, use a simple lock with helping. Later + // unify locking with our request scheme. + physframe[phys >> PAGE_SHIFT].lock.lock(); + + t = physframe[phys >> PAGE_SHIFT].tree; + assert(t); + + mapping_t *m; + + for (m = t->mappings(); + m->data()->depth != Depth_end + && m < t->mappings() + t->number_of_entries(); + m++) + { + if (m->data()->space == space->space() + && m->data()->address == va >> PAGE_SHIFT) + { + // found! + return m; + } + } + + // not found -- unlock tree + physframe[phys >> PAGE_SHIFT].lock.clear(); + + return 0; +} // lookup() + +#line 602 "mapping.cpp" + +void +mapdb_t::free(mapping_t* mapping_of_tree) +{ + mapping_tree_t *t = mapping_of_tree->tree(); + + // We assume that the zeroth mapping of the tree is a sigma0 + // mapping, that is, its virtual address == the page's physical + // address. + vm_offset_t phys_pno = t->mappings()[0].data()->address; + + // We are the owner of the tree lock. + assert(physframe[phys_pno].lock.lock_owner() == current()); + + // Before we unlock the tree, we need to make sure that there is + // room for at least one new mapping. In particular, this means + // that the last entry of the array encoding the tree must be free. + + // (1) When we use up less than a quarter of all entries of the + // array encoding the tree, copy to a smaller tree. Otherwise, (2) + // if the last entry is free, do nothing. Otherwise, (3) if less + // than 3/4 of the entries are used, compress the tree. Otherwise, + // (4) copy to a larger tree. + + bool maybe_out_of_memory = false; + + do // (this is not actually a loop, just a block we can "break" out of) + { + // (1) Do we need to allocate a smaller tree? + if (t->_size_id > 0 // must not be smallest size + && (t->_count << 2) < t->number_of_entries()) + { + mapping_tree_t *new_t = + reinterpret_cast + (allocator_for_treesize[t->_size_id - 1]->alloc()); + + if (new_t) + { + // XXX should be asserted by allocator: + new_t->_size_id = t->_size_id - 1; + new_t->mappings()[new_t->number_of_entries() - 1].data()->depth + = Depth_end; + + mapping_tree_t::copy_compact_tree(new_t, t); + + // Register new tree. + physframe[phys_pno].tree = new_t; + + allocator_for_treesize[t->_size_id]->free(t); + t = new_t; + + break; + } + } + + // (2) Is last entry is free? + if (t->mappings()[t->number_of_entries() - 1].unused()) + break; // OK, last entry is free. + + // Last entry is not free -- either compress current array + // (i.e., move free entries to end of array), or allocate bigger + // array. + + // (3) Should we compress the tree? + // We also try to compress if we cannot allocate a bigger + // tree because there is no bigger tree size. + if (t->_count < (t->number_of_entries() >> 2) + + (t->number_of_entries() >> 1) + || t->_size_id == Size_id_max) // cannot enlarge? + { + if (t->_size_id == Size_id_max) + maybe_out_of_memory = true; + + mapping_tree_t::copy_compact_tree(t, t); // in-place compression + + break; + } + + // (4) OK, allocate a bigger array. + + mapping_tree_t *new_t = + reinterpret_cast + (allocator_for_treesize[t->_size_id + 1]->alloc()); + + if (new_t) + { + // XXX should be asserted by allocator: + new_t->_size_id = t->_size_id + 1; + new_t->mappings()[new_t->number_of_entries() - 1].data()->depth + = Depth_end; + + mapping_tree_t::copy_compact_tree(new_t, t); + + // Register new tree. + physframe[phys_pno].tree = new_t; + + allocator_for_treesize[t->_size_id]->free(t); + t = new_t; + } + else + { + // out of memory -- just do tree compression and hope that helps. + maybe_out_of_memory = true; + + mapping_tree_t::copy_compact_tree(t, t); // in-place compression + } + } + while (false); + + // The last entry of the tree should now be free -- exept if we're + // out of memory. + assert(t->mappings()[t->number_of_entries() - 1].unused() + || maybe_out_of_memory); + + // Unlock tree. + physframe[phys_pno].lock.clear(); +} // free() + +#line 719 "mapping.cpp" + +// Delete mappings from a tree. This is easy to do: We just have to +// iterate over the array encoding the tree. +bool +mapdb_t::flush(mapping_t *m, bool me_too) +{ + mapping_tree_t *t = m->tree(); + mapping_t *start_of_deletions = m; + unsigned m_depth = m->data()->depth; + unsigned deleted = 0, empty_elems_passed = 0; + + if (me_too) + { + m->data()->depth = Depth_empty; + t->_count -= 1; + deleted++; + } + else + start_of_deletions++; + + m++; + + for (; + m < t->mappings() + t->number_of_entries() + && m->data()->depth != Depth_end; + m++) + { + if (unsigned (m->data()->depth) <= m_depth) + { + // Found another data element -- stop deleting. Since we + // created holes in the tree representation, account for it. + t->_empty_count += deleted; + + return true; + } + + if (m->data()->depth == Depth_empty) + { + empty_elems_passed++; + continue; + } + + // Delete the element. + m->data()->depth = Depth_empty; + t->_count -= 1; + deleted++; + } + + // We deleted stuff at the end of the array -- move end tag + if (start_of_deletions < t->mappings() + t->number_of_entries()) + { + start_of_deletions->data()->depth = Depth_end; + + // also, reduce number of free entries + t->_empty_count -= empty_elems_passed; + } + + return true; +} // flush() + +#line 778 "mapping.cpp" + +void +mapdb_t::grant(mapping_t *m, space_t *new_space, vm_offset_t va) +{ + m->data()->space = new_space->space(); + m->data()->address = va >> PAGE_SHIFT; +} // grant() diff --git a/tools/preprocess/test/verify/mapping.h b/tools/preprocess/test/verify/mapping.h new file mode 100644 index 00000000..ce818ff7 --- /dev/null +++ b/tools/preprocess/test/verify/mapping.h @@ -0,0 +1,155 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef mapping_h +#define mapping_h +#line 2 "mapping.cpp" + +#include // for vm_offset_t, vm_size_t +#line 4 "mapping.cpp" +#include "space.h" // for space_index_t + +// +// INTERFACE definition follows +// + +#line 7 "mapping.cpp" + +class mapping_tree_t; // forward decls +#line 9 "mapping.cpp" +struct mapping_s; +#line 26 "mapping.cpp" + +class kmem_slab_t; +#line 28 "mapping.cpp" +struct physframe_data; +#line 5 "mapping.cpp" + +enum mapping_type_t { Map_mem = 0, Map_io }; +#line 10 "mapping.cpp" + +// +// class mapping_t +// +class mapping_t +{ + friend class mapdb_t; + friend class mapping_tree_t; + friend class jdb; + + // CREATORS + mapping_t(const mapping_t&); // this constructor is undefined. + + // DATA + char _data[5]; + +public: +#line 224 "mapping.cpp" + space_index_t + space(); + +#line 231 "mapping.cpp" + vm_offset_t + vaddr(); + +#line 238 "mapping.cpp" + vm_size_t + size(); + +#line 248 "mapping.cpp" + mapping_type_t + type(); + +#line 283 "mapping.cpp" + // + // more of class mapping_t + // + + mapping_t * + parent(); + +#line 307 "mapping.cpp" + mapping_t * + next_iter(); + +#line 332 "mapping.cpp" + mapping_t * + next_child(mapping_t *parent); + +private: +#line 213 "mapping.cpp" + mapping_t(); + +#line 217 "mapping.cpp" + mapping_s * + data(); + +#line 256 "mapping.cpp" + bool + unused(); + +#line 262 "mapping.cpp" + mapping_tree_t * + tree(); +} __attribute__((packed)); +#line 29 "mapping.cpp" + +// +// class mapdb_t: The mapping database +// +class mapdb_t +{ + friend class jdb; + +public: + enum { Size_factor = 4, + Size_id_max = 8 /* can be up to 15 (4 bits) */ }; + +private: + // DATA + physframe_data *physframe; + kmem_slab_t *allocator_for_treesize[Size_id_max + 1]; + +public: +#line 399 "mapping.cpp" + mapdb_t(); + +#line 450 "mapping.cpp" + // insert a new mapping entry with the given values as child of + // "parent" After locating the right place for the new entry, it will + // be stored there (if this place is empty) or the following entries + // moved by one entry. + + // We assume that there is at least one free entry at the end of the + // array so that at least one insert() operation can succeed between a + // lock()/free() pair of calls. This is guaranteed by the free() + // operation which allocates a larger tree if the current one becomes + // to small. + mapping_t * + insert(mapping_t *parent, + space_t *space, + vm_offset_t va, + vm_size_t size, + mapping_type_t type); + +#line 562 "mapping.cpp" + mapping_t * + lookup(space_t *space, + vm_offset_t va, + mapping_type_t type); + +#line 603 "mapping.cpp" + void + free(mapping_t* mapping_of_tree); + +#line 720 "mapping.cpp" + // Delete mappings from a tree. This is easy to do: We just have to + // iterate over the array encoding the tree. + bool + flush(mapping_t *m, bool me_too); + +#line 779 "mapping.cpp" + void + grant(mapping_t *m, space_t *new_space, vm_offset_t va); +}; + +#endif // mapping_h diff --git a/tools/preprocess/test/verify/mapping_i.h b/tools/preprocess/test/verify/mapping_i.h new file mode 100644 index 00000000..b18e273c --- /dev/null +++ b/tools/preprocess/test/verify/mapping_i.h @@ -0,0 +1,95 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef mapping_i_h +#define mapping_i_h +#line 148 "mapping.cpp" + +#include +#line 150 "mapping.cpp" +#include +#line 385 "mapping.cpp" + +// +// class mapdb +// + +#include "lock.h" +#line 391 "mapping.cpp" +#include "kmem_slab.h" +#line 155 "mapping.cpp" + +// For implementation of mapping_t functions, we need mapping_tree_t. + +// +// class mapping_tree_t +// +class mapping_tree_t +{ + friend class mapping_t; + friend class mapdb_t; + friend class jdb; + + // DATA + unsigned _count: 16; + unsigned _size_id: 4; + unsigned _empty_count: 11; + unsigned _unused: 1; // make this 32 bits to avoid a compiler bug + + mapping_t _mappings[0] __attribute__((packed)); + + +public: +#line 347 "mapping.cpp" + // helpers + + // + // class mapping_tree_t + // + + // This function copies the elements of mapping tree src to mapping + // tree dst, ignoring empty elements (that is, compressing the + // source tree. In-place compression is supported. + static void + copy_compact_tree(mapping_tree_t *dst, mapping_tree_t *src); + +private: +#line 177 "mapping.cpp" + // public routines with inline implementations + + unsigned + number_of_entries() const; + +#line 186 "mapping.cpp" + mapping_t * + mappings(); +} __attribute__((packed)); +#line 191 "mapping.cpp" + +// Define (otherwise private) stuff needed by public inline +// functions. + +enum mapping_depth_t +{ + Depth_sigma0_mapping = 0, Depth_max = 253, + Depth_empty = 254, Depth_end = 255 +}; +#line 200 "mapping.cpp" + +struct mapping_s +{ + unsigned space:11; + unsigned size:1; + unsigned address:20; + mapping_depth_t depth:8; + unsigned do_not_touch: 24; // make this 64 bits, and make sure the + // compiler never touches memory after the + // real data +}; +#line 392 "mapping.cpp" + +struct physframe_data { + mapping_tree_t *tree; + helping_lock_t lock; +}; + +#endif // mapping_i_h diff --git a/tools/preprocess/test/verify/mapping_inline.cc b/tools/preprocess/test/verify/mapping_inline.cc new file mode 100644 index 00000000..5dfb449d --- /dev/null +++ b/tools/preprocess/test/verify/mapping_inline.cc @@ -0,0 +1,647 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#include "mapping_inline.h" +#include "mapping_inline_i.h" + +#line 48 "mapping.cpp" + +// The mapping database. + +// This implementation encodes mapping trees in very compact arrays of +// fixed sizes, prefixed by a tree header (mapping_tree_t). Array +// sizes can vary from 4 mappings to 4<<15 mappings. For each size, +// we set up a slab allocator. To grow or shrink the size of an +// array, we have to allocate a larger or smaller tree from the +// corresponding allocator and then copy the array elements. +// +// The array elements (mapping_t) contain a tree depth element. This +// depth and the relative position in the array is all information we +// need to derive tree structure information. Here is an example: +// +// array +// element depth +// number value comment +// -------------------------- +// 0 0 Sigma0 mapping +// 1 1 child of element #0 with depth 0 +// 2 2 child of element #1 with depth 1 +// 3 2 child of element #1 with depth 1 +// 4 3 child of element #3 with depth 2 +// 5 2 child of element #1 with depth 1 +// 6 3 child of element #5 with depth 2 +// 7 1 child of element #0 with depth 0 +// +// This array is a pre-order encoding of the following tree: +// +// 0 +// / \ +// 1 7 +// / | \ +// 2 3 5 +// | | +// 4 6 + +// IDEAS for enhancing this implementation: + +// We often have to find a tree header corresponding to a mapping. +// Currently, we do this by iterating backwards over the array +// containing the mappings until we find the Sigma0 mapping, from +// whose address we can compute the address of the tree header. If +// this becomes a problem, we could add one more byte to the mappings +// with a hint (negative array offset) where to find the sigma0 +// mapping. (If the hint value overflows, just iterate using the hint +// value of the mapping we find with the first hint value.) Another +// idea (from Adam) would be to just look up the tree header by using +// the physical address from the page-table lookup, but we would need +// to change the interface of the mapping database for that (pass in +// the physical address at all times), or we would have to include the +// physical address (or just the address of the tree header) in the +// mapdb_t-user-visible mapping_t (which could be different from the +// internal tree representation). (XXX: Implementing one of these +// ideas is probably worthwile doing!) + +// Instead of copying whole trees around when they grow or shrink a +// lot, or copying parts of trees when inserting an element, we could +// give up the array representation and add a "next" pointer to the +// elements -- that is, keep the tree of mappings in a +// pre-order-encoded singly-linked list (credits to: Christan Szmajda +// and Adam Wiggins). 24 bits would probably be enough to encode that +// pointer. Disadvantages: Mapping entries would be larger, and the +// cache-friendly space-locality of tree entries would be lost. + +// The current handling of superpages sucks rocks both in this module +// and in our user, ipc_map.cc. We could support multiple page sizes +// by not using a physframe[] array only for the largest page size. +// (Entries of that array point to the top-level mappings -- sigma0 +// mappings.) Mapping-tree entries would then either be regular +// mappings or pointers to an array of mappings of the next-smaller +// size. (credits: Christan Szmajda) +// +// physframe[] +// ------------------------------- +// | | | | | | | | | | | | | | | | array of ptr to 4M mapping_tree_t's +// ---|--------------------------- +// | +// v a mapping_tree_t +// --------------- +// | | tree header +// |-------------| +// | | mapping_t *or* ptr to array of ptr to 4K trees +// | | e.g. +// | ----------------| +// | | v array of ptr to 4M mapping_tree_t's +// --------------- ------------------------------- +// | | | | | | | | | | | | | | | | +// ---|--------------------------- +// | +// v a mapping_tree_t +// --------------- +// | | tree header +// |-------------| +// | | mapping_t +// | | +// | | +// | | +// --------------- +//- +#line 151 "mapping.cpp" + +#ifndef offsetof // should be defined in stddef.h, but isn't +#line 153 "mapping.cpp" +#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) +#line 154 "mapping.cpp" +#endif + +#line 261 "mapping.cpp" + +mapping_tree_t * +mapping_t::tree() +{ + mapping_t *m = this; + + while (m->data()->depth > Depth_sigma0_mapping) + { + // jump in bigger steps if this is not a free mapping + if (! m->unused()) + { + m -= m->data()->depth; + continue; + } + + m--; + } + + return reinterpret_cast + (reinterpret_cast(m) - offsetof(mapping_tree_t, _mappings)); +} + +#line 282 "mapping.cpp" + +// +// more of class mapping_t +// + +mapping_t * +mapping_t::parent() +{ + if (data()->depth <= Depth_sigma0_mapping) + { + // Sigma0 mappings don't have a parent. + return 0; + } + + // Iterate over mapping entries of this tree backwards until we find + // an entry with a depth smaller than ours. (We assume here that + // "special" depths (empty, end) are larger than Depth_max.) + mapping_t *m = this - 1; + + while (m->data()->depth >= data()->depth) + m--; + + return m; +} + +#line 306 "mapping.cpp" + +mapping_t * +mapping_t::next_iter() +{ + mapping_tree_t *t = tree(); + mapping_t *last_in_tree = t->mappings() + t->number_of_entries() - 1; + + mapping_t *m = this; + + // Look for a valid element in the tree structure. + while (m != last_in_tree) + { + m++; + if (! m->unused()) + return m; // Found a valid entry! + + // Don't iterate to end of tree if this is the last tree entry. + if (m->data()->depth == Depth_end) + return 0; + } + + // Couldn't find a non-empty element behind ourselves in the tree + // structure. + return 0; +} + +#line 331 "mapping.cpp" + +mapping_t * +mapping_t::next_child(mapping_t *parent) +{ + // Find the next valid entry in the tree structure. + mapping_t *m = next_iter(); + + // If we didn't find an entry, or if the entry cannot be a child of + // "parent", return 0 + if (m == 0 + || m->data()->depth <= parent->data()->depth) + return 0; + + return m; // Found! +} + +#line 346 "mapping.cpp" + +// helpers + +// +// class mapping_tree_t +// + +// This function copies the elements of mapping tree src to mapping +// tree dst, ignoring empty elements (that is, compressing the +// source tree. In-place compression is supported. +void +mapping_tree_t::copy_compact_tree(mapping_tree_t *dst, mapping_tree_t *src) +{ + dst->_count = 0; + dst->_empty_count = 0; + + mapping_t *d = dst->mappings(); + + for (mapping_t *s = src->mappings(); + s < src->mappings() + src->number_of_entries(); + s++) + { + if (s->unused()) // entry free + { + if (s->data()->depth == Depth_end) + break; + continue; + } + + *d++ = *s; + dst->_count += 1; + } + + assert (dst->_count == src->_count); + assert (d < dst->mappings() + dst->number_of_entries()); + + d->data()->depth = Depth_end; + dst->mappings()[dst->number_of_entries() - 1].data()->depth = Depth_end; +} // copy_compact_tree() + +#line 397 "mapping.cpp" + + +mapdb_t::mapdb_t() +{ + vm_offset_t page_number = kmem::info()->main_memory.high / PAGE_SIZE + 1; + + // allocate physframe array + check ( physframe = reinterpret_cast + (kmem::alloc(page_number * sizeof(physframe_data))) ); + + memset(physframe, 0, page_number * sizeof(physframe_data)); + + // create a slab for each mapping tree size + for (int slab_number = 0; + slab_number <= Size_id_max; + slab_number++ ) + { + unsigned elem_size = + (Size_factor << slab_number) * sizeof(mapping_t) + + sizeof(mapping_tree_t); + + allocator_for_treesize[slab_number] = + new kmem_slab_t(((PAGE_SIZE / elem_size) < 40 + ? 8*PAGE_SIZE : PAGE_SIZE), + elem_size, 1); + } + + // create a sigma0 mapping for all physical pages + for (unsigned page_id = 0; page_id < page_number; page_id++) + { + mapping_tree_t *t; + check( (t = physframe[page_id].tree + = reinterpret_cast + (allocator_for_treesize[0]->alloc())) ); + + t->_count = 1; // 1 valid mapping + t->_size_id = 0; // size is equal to Size_factor << 0 + t->_empty_count = 0; // no gaps in tree representation + + t->mappings()[0].data()->depth = Depth_sigma0_mapping; + t->mappings()[0].data()->address = page_id; + t->mappings()[0].data()->space = config::sigma0_taskno; + t->mappings()[0].data()->size = 0; + + t->mappings()[1].data()->depth = Depth_end; + + // We also always set the end tag on last entry so that we can + // check whether it has been overwritten. + t->mappings()[t->number_of_entries() - 1].data()->depth = Depth_end; + } +} // mapdb_t() + +#line 448 "mapping.cpp" + + +// insert a new mapping entry with the given values as child of +// "parent" After locating the right place for the new entry, it will +// be stored there (if this place is empty) or the following entries +// moved by one entry. + +// We assume that there is at least one free entry at the end of the +// array so that at least one insert() operation can succeed between a +// lock()/free() pair of calls. This is guaranteed by the free() +// operation which allocates a larger tree if the current one becomes +// to small. +mapping_t * +mapdb_t::insert(mapping_t *parent, + space_t *space, + vm_offset_t va, + vm_size_t size, + mapping_type_t type) +{ + assert(type == Map_mem); // we don't yet support Map_io + + mapping_tree_t *t = parent->tree(); + + // We cannot continue if the last array entry is not free. This + // only happens if an earlier call to free() with this mapping tree + // couldn't allocate a bigger array. In this case, signal an + // out-of-memory condition. + if (! t->mappings()[t->number_of_entries() - 1].unused()) + return 0; + + // If the parent mapping already has the maximum depth, we cannot + // insert a child. + if (parent->data()->depth == Depth_max) + return 0; + + mapping_t *insert = 0; + + bool + found_free_entry = false, + need_to_move = false; + + mapping_t temp; + + // Find a free entry in the array encoding the tree, and find the + // insertion point for the new entry. These two entries might not + // be equivalent, so we may need to move entries backwards in the + // array. In this implementation, we move entries as we traverse + // the array, instead of doing one big memmove + for (mapping_t *m = parent + 1; + m < t->mappings() + t->number_of_entries(); + m++) + { + if (m->unused()) + { + // We found a free entry in the tree -- allocate it. + found_free_entry = true; + t->_count += 1; + + // Did we find an empty element != the end tag? + if (m->data()->depth == Depth_empty) + { + t->_empty_count -= 1; + } + // Else we have found the end tag. If there is another + // array entry left, apply a new end tag to the array + else if (m + 1 < t->mappings() + t->number_of_entries()) + { + (m + 1)->data()->depth = Depth_end; + } + + // if we haven't identified a place for inserting the new + // element, this is it. + if (! need_to_move) + insert = m; + } + else if (! need_to_move + && m->data()->depth <= parent->data()->depth) + { + // we found a non-descendant of ourselves -- need to make + // space for new child + need_to_move = true; + insert = m; + temp = *insert; + + continue; + } + + if (need_to_move) + { + // replace *m with temp (which used to be *(m - 1); but + // *(m - 1) has since been overwritten), and load temp with + // the old value of *m + mapping_t temp2; + + temp2 = *m; + *m = temp; + temp = temp2; + } + + if (found_free_entry) + break; + } + + assert(insert && found_free_entry); + + // found a place to insert new child. + insert->data()->depth = mapping_depth_t(parent->data()->depth + 1); + insert->data()->address = va >> PAGE_SHIFT; + insert->data()->space = space->space(); + insert->data()->size = (size == SUPERPAGE_SIZE); + + return insert; +} // insert() + +#line 561 "mapping.cpp" + +mapping_t * +mapdb_t::lookup(space_t *space, + vm_offset_t va, + mapping_type_t type) +{ + vm_offset_t phys = space->virt_to_phys(va); + + if (phys == 0xffffffff) + return 0; + + mapping_tree_t *t; + + // get and lock the tree. + // XXX For now, use a simple lock with helping. Later + // unify locking with our request scheme. + physframe[phys >> PAGE_SHIFT].lock.lock(); + + t = physframe[phys >> PAGE_SHIFT].tree; + assert(t); + + mapping_t *m; + + for (m = t->mappings(); + m->data()->depth != Depth_end + && m < t->mappings() + t->number_of_entries(); + m++) + { + if (m->data()->space == space->space() + && m->data()->address == va >> PAGE_SHIFT) + { + // found! + return m; + } + } + + // not found -- unlock tree + physframe[phys >> PAGE_SHIFT].lock.clear(); + + return 0; +} // lookup() + +#line 602 "mapping.cpp" + +void +mapdb_t::free(mapping_t* mapping_of_tree) +{ + mapping_tree_t *t = mapping_of_tree->tree(); + + // We assume that the zeroth mapping of the tree is a sigma0 + // mapping, that is, its virtual address == the page's physical + // address. + vm_offset_t phys_pno = t->mappings()[0].data()->address; + + // We are the owner of the tree lock. + assert(physframe[phys_pno].lock.lock_owner() == current()); + + // Before we unlock the tree, we need to make sure that there is + // room for at least one new mapping. In particular, this means + // that the last entry of the array encoding the tree must be free. + + // (1) When we use up less than a quarter of all entries of the + // array encoding the tree, copy to a smaller tree. Otherwise, (2) + // if the last entry is free, do nothing. Otherwise, (3) if less + // than 3/4 of the entries are used, compress the tree. Otherwise, + // (4) copy to a larger tree. + + bool maybe_out_of_memory = false; + + do // (this is not actually a loop, just a block we can "break" out of) + { + // (1) Do we need to allocate a smaller tree? + if (t->_size_id > 0 // must not be smallest size + && (t->_count << 2) < t->number_of_entries()) + { + mapping_tree_t *new_t = + reinterpret_cast + (allocator_for_treesize[t->_size_id - 1]->alloc()); + + if (new_t) + { + // XXX should be asserted by allocator: + new_t->_size_id = t->_size_id - 1; + new_t->mappings()[new_t->number_of_entries() - 1].data()->depth + = Depth_end; + + mapping_tree_t::copy_compact_tree(new_t, t); + + // Register new tree. + physframe[phys_pno].tree = new_t; + + allocator_for_treesize[t->_size_id]->free(t); + t = new_t; + + break; + } + } + + // (2) Is last entry is free? + if (t->mappings()[t->number_of_entries() - 1].unused()) + break; // OK, last entry is free. + + // Last entry is not free -- either compress current array + // (i.e., move free entries to end of array), or allocate bigger + // array. + + // (3) Should we compress the tree? + // We also try to compress if we cannot allocate a bigger + // tree because there is no bigger tree size. + if (t->_count < (t->number_of_entries() >> 2) + + (t->number_of_entries() >> 1) + || t->_size_id == Size_id_max) // cannot enlarge? + { + if (t->_size_id == Size_id_max) + maybe_out_of_memory = true; + + mapping_tree_t::copy_compact_tree(t, t); // in-place compression + + break; + } + + // (4) OK, allocate a bigger array. + + mapping_tree_t *new_t = + reinterpret_cast + (allocator_for_treesize[t->_size_id + 1]->alloc()); + + if (new_t) + { + // XXX should be asserted by allocator: + new_t->_size_id = t->_size_id + 1; + new_t->mappings()[new_t->number_of_entries() - 1].data()->depth + = Depth_end; + + mapping_tree_t::copy_compact_tree(new_t, t); + + // Register new tree. + physframe[phys_pno].tree = new_t; + + allocator_for_treesize[t->_size_id]->free(t); + t = new_t; + } + else + { + // out of memory -- just do tree compression and hope that helps. + maybe_out_of_memory = true; + + mapping_tree_t::copy_compact_tree(t, t); // in-place compression + } + } + while (false); + + // The last entry of the tree should now be free -- exept if we're + // out of memory. + assert(t->mappings()[t->number_of_entries() - 1].unused() + || maybe_out_of_memory); + + // Unlock tree. + physframe[phys_pno].lock.clear(); +} // free() + +#line 719 "mapping.cpp" + +// Delete mappings from a tree. This is easy to do: We just have to +// iterate over the array encoding the tree. +bool +mapdb_t::flush(mapping_t *m, bool me_too) +{ + mapping_tree_t *t = m->tree(); + mapping_t *start_of_deletions = m; + unsigned m_depth = m->data()->depth; + unsigned deleted = 0, empty_elems_passed = 0; + + if (me_too) + { + m->data()->depth = Depth_empty; + t->_count -= 1; + deleted++; + } + else + start_of_deletions++; + + m++; + + for (; + m < t->mappings() + t->number_of_entries() + && m->data()->depth != Depth_end; + m++) + { + if (unsigned (m->data()->depth) <= m_depth) + { + // Found another data element -- stop deleting. Since we + // created holes in the tree representation, account for it. + t->_empty_count += deleted; + + return true; + } + + if (m->data()->depth == Depth_empty) + { + empty_elems_passed++; + continue; + } + + // Delete the element. + m->data()->depth = Depth_empty; + t->_count -= 1; + deleted++; + } + + // We deleted stuff at the end of the array -- move end tag + if (start_of_deletions < t->mappings() + t->number_of_entries()) + { + start_of_deletions->data()->depth = Depth_end; + + // also, reduce number of free entries + t->_empty_count -= empty_elems_passed; + } + + return true; +} // flush() + +#line 778 "mapping.cpp" + +void +mapdb_t::grant(mapping_t *m, space_t *new_space, vm_offset_t va) +{ + m->data()->space = new_space->space(); + m->data()->address = va >> PAGE_SHIFT; +} // grant() diff --git a/tools/preprocess/test/verify/mapping_inline.h b/tools/preprocess/test/verify/mapping_inline.h new file mode 100644 index 00000000..c4e6b63e --- /dev/null +++ b/tools/preprocess/test/verify/mapping_inline.h @@ -0,0 +1,231 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef mapping_inline_h +#define mapping_inline_h +#line 2 "mapping.cpp" + +#include // for vm_offset_t, vm_size_t +#line 4 "mapping.cpp" +#include "space.h" // for space_index_t + +// +// INTERFACE definition follows +// + +#line 7 "mapping.cpp" + +class mapping_tree_t; // forward decls +#line 9 "mapping.cpp" +struct mapping_s; +#line 26 "mapping.cpp" + +class kmem_slab_t; +#line 28 "mapping.cpp" +struct physframe_data; +#line 5 "mapping.cpp" + +enum mapping_type_t { Map_mem = 0, Map_io }; +#line 10 "mapping.cpp" + +// +// class mapping_t +// +class mapping_t +{ + friend class mapdb_t; + friend class mapping_tree_t; + friend class jdb; + + // CREATORS + mapping_t(const mapping_t&); // this constructor is undefined. + + // DATA + char _data[5]; + +public: +#line 224 "mapping.cpp" + inline space_index_t + space(); + +#line 231 "mapping.cpp" + inline vm_offset_t + vaddr(); + +#line 238 "mapping.cpp" + inline vm_size_t + size(); + +#line 248 "mapping.cpp" + inline mapping_type_t + type(); + +#line 283 "mapping.cpp" + // + // more of class mapping_t + // + + mapping_t * + parent(); + +#line 307 "mapping.cpp" + mapping_t * + next_iter(); + +#line 332 "mapping.cpp" + mapping_t * + next_child(mapping_t *parent); + +private: +#line 213 "mapping.cpp" + inline mapping_t(); + +#line 217 "mapping.cpp" + inline mapping_s * + data(); + +#line 256 "mapping.cpp" + inline bool + unused(); + +#line 262 "mapping.cpp" + mapping_tree_t * + tree(); +} __attribute__((packed)); +#line 29 "mapping.cpp" + +// +// class mapdb_t: The mapping database +// +class mapdb_t +{ + friend class jdb; + +public: + enum { Size_factor = 4, + Size_id_max = 8 /* can be up to 15 (4 bits) */ }; + +private: + // DATA + physframe_data *physframe; + kmem_slab_t *allocator_for_treesize[Size_id_max + 1]; + +public: +#line 399 "mapping.cpp" + mapdb_t(); + +#line 450 "mapping.cpp" + // insert a new mapping entry with the given values as child of + // "parent" After locating the right place for the new entry, it will + // be stored there (if this place is empty) or the following entries + // moved by one entry. + + // We assume that there is at least one free entry at the end of the + // array so that at least one insert() operation can succeed between a + // lock()/free() pair of calls. This is guaranteed by the free() + // operation which allocates a larger tree if the current one becomes + // to small. + mapping_t * + insert(mapping_t *parent, + space_t *space, + vm_offset_t va, + vm_size_t size, + mapping_type_t type); + +#line 562 "mapping.cpp" + mapping_t * + lookup(space_t *space, + vm_offset_t va, + mapping_type_t type); + +#line 603 "mapping.cpp" + void + free(mapping_t* mapping_of_tree); + +#line 720 "mapping.cpp" + // Delete mappings from a tree. This is easy to do: We just have to + // iterate over the array encoding the tree. + bool + flush(mapping_t *m, bool me_too); + +#line 779 "mapping.cpp" + void + grant(mapping_t *m, space_t *new_space, vm_offset_t va); +}; + +// +// IMPLEMENTATION of inline functions (and needed classes) +// + +#line 191 "mapping.cpp" + +// Define (otherwise private) stuff needed by public inline +// functions. + +enum mapping_depth_t +{ + Depth_sigma0_mapping = 0, Depth_max = 253, + Depth_empty = 254, Depth_end = 255 +}; +#line 200 "mapping.cpp" + +struct mapping_s +{ + unsigned space:11; + unsigned size:1; + unsigned address:20; + mapping_depth_t depth:8; + unsigned do_not_touch: 24; // make this 64 bits, and make sure the + // compiler never touches memory after the + // real data +}; + +#line 215 "mapping.cpp" + + +inline mapping_s * +mapping_t::data() +{ + return reinterpret_cast(_data); +} + +#line 222 "mapping.cpp" + + +inline space_index_t +mapping_t::space() +{ + return space_index_t(data()->space); +} + +#line 229 "mapping.cpp" + + +inline vm_offset_t +mapping_t::vaddr() +{ + return (data()->address << PAGE_SHIFT); +} + +#line 236 "mapping.cpp" + + +inline vm_size_t +mapping_t::size() +{ + if ( data()->size ) + return SUPERPAGE_SIZE; + else + return PAGE_SIZE; +} + +#line 246 "mapping.cpp" + + +inline mapping_type_t +mapping_t::type() +{ + // return data()->type;; + return Map_mem; +} + +#endif // mapping_inline_h diff --git a/tools/preprocess/test/verify/mapping_inline_i.h b/tools/preprocess/test/verify/mapping_inline_i.h new file mode 100644 index 00000000..48878043 --- /dev/null +++ b/tools/preprocess/test/verify/mapping_inline_i.h @@ -0,0 +1,112 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef mapping_inline_i_h +#define mapping_inline_i_h +#line 148 "mapping.cpp" + +#include +#line 150 "mapping.cpp" +#include +#line 385 "mapping.cpp" + +// +// class mapdb +// + +#include "lock.h" +#line 391 "mapping.cpp" +#include "kmem_slab.h" +#line 155 "mapping.cpp" + +// For implementation of mapping_t functions, we need mapping_tree_t. + +// +// class mapping_tree_t +// +class mapping_tree_t +{ + friend class mapping_t; + friend class mapdb_t; + friend class jdb; + + // DATA + unsigned _count: 16; + unsigned _size_id: 4; + unsigned _empty_count: 11; + unsigned _unused: 1; // make this 32 bits to avoid a compiler bug + + mapping_t _mappings[0] __attribute__((packed)); + + +public: +#line 347 "mapping.cpp" + // helpers + + // + // class mapping_tree_t + // + + // This function copies the elements of mapping tree src to mapping + // tree dst, ignoring empty elements (that is, compressing the + // source tree. In-place compression is supported. + static void + copy_compact_tree(mapping_tree_t *dst, mapping_tree_t *src); + +private: +#line 177 "mapping.cpp" + // public routines with inline implementations + + inline unsigned + number_of_entries() const; + +#line 186 "mapping.cpp" + inline mapping_t * + mappings(); +} __attribute__((packed)); +#line 392 "mapping.cpp" + +struct physframe_data { + mapping_tree_t *tree; + helping_lock_t lock; +}; + +// +// IMPLEMENTATION of inline functions follows +// + + +#line 211 "mapping.cpp" + + +inline mapping_t::mapping_t() +{} + +#line 254 "mapping.cpp" + + +inline bool +mapping_t::unused() +{ + return (data()->depth > Depth_max); +} + +#line 176 "mapping.cpp" + +// public routines with inline implementations + +inline unsigned +mapping_tree_t::number_of_entries() const +{ + return mapdb_t::Size_factor << _size_id; +} + +#line 184 "mapping.cpp" + + +inline mapping_t * +mapping_tree_t::mappings() +{ + return & _mappings[0]; +} + +#endif // mapping_inline_i_h diff --git a/tools/preprocess/test/verify/multifile-part1.cc b/tools/preprocess/test/verify/multifile-part1.cc new file mode 100644 index 00000000..e13bd4ba --- /dev/null +++ b/tools/preprocess/test/verify/multifile-part1.cc @@ -0,0 +1,12 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#include "multifile.h" +#include "multifile_i.h" + + +#line 8 "multifile1.cpp" + + +void +Foo::bar() +{} diff --git a/tools/preprocess/test/verify/multifile-part2.cc b/tools/preprocess/test/verify/multifile-part2.cc new file mode 100644 index 00000000..788bd9fc --- /dev/null +++ b/tools/preprocess/test/verify/multifile-part2.cc @@ -0,0 +1,12 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#include "multifile.h" +#include "multifile_i.h" + + +#line 13 "multifile2.cpp" + + +void +Foo::bingo(Bar* bar) +{} diff --git a/tools/preprocess/test/verify/multifile.cc b/tools/preprocess/test/verify/multifile.cc new file mode 100644 index 00000000..0b5c21e6 --- /dev/null +++ b/tools/preprocess/test/verify/multifile.cc @@ -0,0 +1,12 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#include "multifile.h" +#include "multifile_i.h" + + +#line 20 "multifile1.cpp" + + +void +Foo::gizmatic() +{} diff --git a/tools/preprocess/test/verify/multifile.h b/tools/preprocess/test/verify/multifile.h new file mode 100644 index 00000000..970a8730 --- /dev/null +++ b/tools/preprocess/test/verify/multifile.h @@ -0,0 +1,66 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef multifile_h +#define multifile_h + +// +// INTERFACE definition follows +// + +#line 7 "multifile2.cpp" + +class Bar; +#line 2 "multifile1.cpp" + +class Foo +{ + +#line 2 "multifile2.cpp" +private: + + int more; + +public: +#line 10 "multifile1.cpp" + void + bar(); + +#line 15 "multifile2.cpp" + void + bingo(Bar* bar); + +protected: +#line 15 "multifile1.cpp" + inline void + baz(); + +#line 20 "multifile2.cpp" + inline void + rambo(); + +private: +#line 22 "multifile1.cpp" + void + gizmatic(); +}; + +// +// IMPLEMENTATION of inline functions (and needed classes) +// + + +#line 18 "multifile2.cpp" + + +inline void +Foo::rambo() +{} + +#line 13 "multifile1.cpp" + + +inline void +Foo::baz() +{} + +#endif // multifile_h diff --git a/tools/preprocess/test/verify/multifile_i.h b/tools/preprocess/test/verify/multifile_i.h new file mode 100644 index 00000000..aee787ab --- /dev/null +++ b/tools/preprocess/test/verify/multifile_i.h @@ -0,0 +1,9 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef multifile_i_h +#define multifile_i_h +#line 11 "multifile2.cpp" + +#include "bar.h" + +#endif // multifile_i_h diff --git a/tools/preprocess/test/verify/noinline.cc b/tools/preprocess/test/verify/noinline.cc new file mode 100644 index 00000000..271325ac --- /dev/null +++ b/tools/preprocess/test/verify/noinline.cc @@ -0,0 +1,5 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#include "noinline.h" +#include "noinline_i.h" + diff --git a/tools/preprocess/test/verify/noinline.h b/tools/preprocess/test/verify/noinline.h new file mode 100644 index 00000000..b8cdf734 --- /dev/null +++ b/tools/preprocess/test/verify/noinline.h @@ -0,0 +1,6 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef noinline_h +#define noinline_h + +#endif // noinline_h diff --git a/tools/preprocess/test/verify/noinline_i.h b/tools/preprocess/test/verify/noinline_i.h new file mode 100644 index 00000000..1bf95d17 --- /dev/null +++ b/tools/preprocess/test/verify/noinline_i.h @@ -0,0 +1,12 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef noinline_i_h +#define noinline_i_h +#line 4 "noinline.cpp" + +// There is nothing to inline -- therefore, this #include directive +// should not be put in public header. + +#include "foo.h" + +#endif // noinline_i_h diff --git a/tools/preprocess/test/verify/operator.cc b/tools/preprocess/test/verify/operator.cc new file mode 100644 index 00000000..bce8b306 --- /dev/null +++ b/tools/preprocess/test/verify/operator.cc @@ -0,0 +1,170 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#include "operator.h" +#include "operator_i.h" + + +#line 8 "operator.cpp" + + +void * +Foo::operator new(size_t) // funny comment +{ +} + +#line 14 "operator.cpp" + + +Foo& +Foo::operator+(const Foo&) // funny comment +{ +} + +#line 20 "operator.cpp" + + +Foo& +Foo::operator=(const Foo&) // funny comment +{ +} + +#line 26 "operator.cpp" + + +Foo& +Foo::operator*(const Foo&) // funny comment +{ +} + +#line 44 "operator.cpp" + +void* X::operator new(unsigned int) { return (void*)0; } + +#line 46 "operator.cpp" +void X::operator delete(void*) { } + +#line 47 "operator.cpp" +void* X::operator new[](unsigned int, int) { return (void*)0; } + +#line 48 "operator.cpp" +void X::operator delete[](void*) { } + +#line 49 "operator.cpp" +X X::operator+(const X&) { return *this; } + +#line 50 "operator.cpp" +X X::operator-(const X&) { return *this; } + +#line 51 "operator.cpp" +X X::operator*(const X&) { return *this; } + +#line 52 "operator.cpp" +X X::operator/(const X&) { return *this; } + +#line 53 "operator.cpp" +X X::operator%(const X&) { return *this; } + +#line 54 "operator.cpp" +X X::operator^(const X&) { return *this; } + +#line 55 "operator.cpp" +X X::operator&(const X&) { return *this; } + +#line 56 "operator.cpp" +X X::operator|(const X&) { return *this; } + +#line 57 "operator.cpp" +X X::operator~() { return *this; } + +#line 58 "operator.cpp" +X X::operator!() { return *this; } + +#line 59 "operator.cpp" +X& X::operator=(const X&) {return *this; } + +#line 60 "operator.cpp" +bool X::operator<(const X&) { return false; } + +#line 61 "operator.cpp" +bool X::operator>(const X&) { return false; } + +#line 62 "operator.cpp" +X& X::operator+=(const X&) { return *this; } + +#line 63 "operator.cpp" +X& X::operator-=(const X&) { return *this; } + +#line 64 "operator.cpp" +X& X::operator*=(const X&) { return *this; } + +#line 65 "operator.cpp" +X& X::operator/=(const X&) { return *this; } + +#line 66 "operator.cpp" +X& X::operator%=(const X&) { return *this; } + +#line 67 "operator.cpp" +X& X::operator^=(const X&) { return *this; } + +#line 68 "operator.cpp" +X& X::operator&=(const X&) { return *this; } + +#line 69 "operator.cpp" +X& X::operator|=(const X&) { return *this; } + +#line 70 "operator.cpp" +X X::operator<<(const X&) { return *this; } + +#line 71 "operator.cpp" +X X::operator>>(const X&) { return *this; } + +#line 72 "operator.cpp" +X& X::operator>>=(const X&) { return *this; } + +#line 73 "operator.cpp" +X& X::operator<<=(const X&) { return *this; } + +#line 74 "operator.cpp" +bool X::operator==(const X&) { return true; } + +#line 75 "operator.cpp" +bool X::operator!=(const X&) { return false; } + +#line 76 "operator.cpp" +bool X::operator<=(const X&) { return true; } + +#line 77 "operator.cpp" +bool X::operator>=(const X&) { return true; } + +#line 78 "operator.cpp" +bool X::operator&&(const X&) { return false; } + +#line 79 "operator.cpp" +bool X::operator||(const X&) { return true; } + +#line 80 "operator.cpp" +X& X::operator++() { return *this; } + +#line 81 "operator.cpp" +X X::operator++(int) { return *this; } + +#line 82 "operator.cpp" +X& X::operator--() { return *this; } + +#line 83 "operator.cpp" +X X::operator--(int) { return *this; } + +#line 84 "operator.cpp" +X& X::operator,(const X&) { return *this; } + +#line 85 "operator.cpp" +X* X::operator->*(const X&) { return this; } + +#line 86 "operator.cpp" +X* X::operator->() { return this; } + +#line 87 "operator.cpp" +int X::operator()(const X&) { return 0; } + +#line 88 "operator.cpp" +int X::operator[](const X&) { return 0; } diff --git a/tools/preprocess/test/verify/operator.h b/tools/preprocess/test/verify/operator.h new file mode 100644 index 00000000..1ce3cf4f --- /dev/null +++ b/tools/preprocess/test/verify/operator.h @@ -0,0 +1,52 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef operator_h +#define operator_h + +// +// INTERFACE definition follows +// + +#line 2 "operator.cpp" + +class Foo +{ + +public: +#line 10 "operator.cpp" + void * + operator new(size_t); // funny comment + +#line 16 "operator.cpp" + Foo& + operator+(const Foo&); // funny comment + +#line 22 "operator.cpp" + Foo& + operator=(const Foo&); // funny comment + +#line 28 "operator.cpp" + Foo& + operator*(const Foo&); // funny comment +}; + +#line 34 "operator.cpp" +template std::vector& +operator <<(std::vector& in, const T& new_elem); + +// +// IMPLEMENTATION of function templates +// + + +#line 32 "operator.cpp" + + +template std::vector& +operator <<(std::vector& in, const T& new_elem) +{ + in.push_back (new_elem); + return in; +} + +#endif // operator_h diff --git a/tools/preprocess/test/verify/operator_i.h b/tools/preprocess/test/verify/operator_i.h new file mode 100644 index 00000000..807c7886 --- /dev/null +++ b/tools/preprocess/test/verify/operator_i.h @@ -0,0 +1,144 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef operator_i_h +#define operator_i_h +#line 40 "operator.cpp" + +// Some systematic tests (contributed by Matthias Daum) + +struct X { +public: +#line 45 "operator.cpp" + void* operator new(unsigned int); + +#line 46 "operator.cpp" + void operator delete(void*); + +#line 47 "operator.cpp" + void* operator new[](unsigned int, int); + +#line 48 "operator.cpp" + void operator delete[](void*); + +#line 49 "operator.cpp" + X operator+(const X&); + +#line 50 "operator.cpp" + X operator-(const X&); + +#line 51 "operator.cpp" + X operator*(const X&); + +#line 52 "operator.cpp" + X operator/(const X&); + +#line 53 "operator.cpp" + X operator%(const X&); + +#line 54 "operator.cpp" + X operator^(const X&); + +#line 55 "operator.cpp" + X operator&(const X&); + +#line 56 "operator.cpp" + X operator|(const X&); + +#line 57 "operator.cpp" + X operator~(); + +#line 58 "operator.cpp" + X operator!(); + +#line 59 "operator.cpp" + X& operator=(const X&); + +#line 60 "operator.cpp" + bool operator<(const X&); + +#line 61 "operator.cpp" + bool operator>(const X&); + +#line 62 "operator.cpp" + X& operator+=(const X&); + +#line 63 "operator.cpp" + X& operator-=(const X&); + +#line 64 "operator.cpp" + X& operator*=(const X&); + +#line 65 "operator.cpp" + X& operator/=(const X&); + +#line 66 "operator.cpp" + X& operator%=(const X&); + +#line 67 "operator.cpp" + X& operator^=(const X&); + +#line 68 "operator.cpp" + X& operator&=(const X&); + +#line 69 "operator.cpp" + X& operator|=(const X&); + +#line 70 "operator.cpp" + X operator<<(const X&); + +#line 71 "operator.cpp" + X operator>>(const X&); + +#line 72 "operator.cpp" + X& operator>>=(const X&); + +#line 73 "operator.cpp" + X& operator<<=(const X&); + +#line 74 "operator.cpp" + bool operator==(const X&); + +#line 75 "operator.cpp" + bool operator!=(const X&); + +#line 76 "operator.cpp" + bool operator<=(const X&); + +#line 77 "operator.cpp" + bool operator>=(const X&); + +#line 78 "operator.cpp" + bool operator&&(const X&); + +#line 79 "operator.cpp" + bool operator||(const X&); + +#line 80 "operator.cpp" + X& operator++(); + +#line 81 "operator.cpp" + X operator++(int); + +#line 82 "operator.cpp" + X& operator--(); + +#line 83 "operator.cpp" + X operator--(int); + +#line 84 "operator.cpp" + X& operator,(const X&); + +#line 85 "operator.cpp" + X* operator->*(const X&); + +#line 86 "operator.cpp" + X* operator->(); + +#line 87 "operator.cpp" + int operator()(const X&); + +#line 88 "operator.cpp" + int operator[](const X&); +}; + +#endif // operator_i_h diff --git a/tools/preprocess/test/verify/parser.cc b/tools/preprocess/test/verify/parser.cc new file mode 100644 index 00000000..c1141673 --- /dev/null +++ b/tools/preprocess/test/verify/parser.cc @@ -0,0 +1,55 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#include "parser.h" +#include "parser_i.h" + +#line 40 "parser.cpp" + +// Try to initialize a nested structure object. +struct Foo::Bar some_bar = { 1 }; +#line 79 "parser.cpp" + +void find_this (); +#line 85 "parser.cpp" + +#ifdef HEILIGE_WEIHNACHT +#line 87 "parser.cpp" +static void present_this (); +#line 88 "parser.cpp" +#endif + +#line 28 "parser.cpp" + +// Try function arguments +unsigned +somefunc(unsigned (*func1)(), + unsigned (*func2)()) +{ +} + +#line 43 "parser.cpp" + +// And add a Foo function +void Foo::func() +{} + +#line 47 "parser.cpp" + +// Try default arguments +void Foo::bar(int i, int j) +{} + +#line 51 "parser.cpp" + +// Try a constructor with weird syntax + +Foo::Foo() + : something (reinterpret_cast(Baz::bla())) +{} + +#line 57 "parser.cpp" + +// Try implementing an already-declared function +int +Foo::alreadythere() +{} diff --git a/tools/preprocess/test/verify/parser.h b/tools/preprocess/test/verify/parser.h new file mode 100644 index 00000000..36331671 --- /dev/null +++ b/tools/preprocess/test/verify/parser.h @@ -0,0 +1,87 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef parser_h +#define parser_h + +// +// INTERFACE definition follows +// + +#line 2 "parser.cpp" + +struct Foo +{ + struct Bar + { + int baz; + }; + +public: + int alreadythere(); + inline int alsoalreadythere(); + +public: +#line 52 "parser.cpp" + // Try a constructor with weird syntax + + Foo(); + +private: +#line 44 "parser.cpp" + // And add a Foo function + void func(); + +#line 48 "parser.cpp" + // Try default arguments + void bar(int i = 15, int j = somefunc(0, somefunc(0, 0))); +}; + +#line 20 "parser.cpp" +inline int bar(); + +#line 23 "parser.cpp" +// Try multiline NEEDS + + +inline int baz(); + +#line 29 "parser.cpp" +// Try function arguments +unsigned +somefunc(unsigned (*func1)(), + unsigned (*func2)()); + +// +// IMPLEMENTATION includes follow (for use by inline functions/templates) +// + +#line 16 "parser.cpp" + +#include "foo.h" + +// +// IMPLEMENTATION of inline functions (and needed classes) +// + + +#line 62 "parser.cpp" + +inline int +Foo::alsoalreadythere() +{} + +#line 18 "parser.cpp" + + +inline int bar() +{} + +#line 22 "parser.cpp" + +// Try multiline NEEDS + + +inline int baz() +{} + +#endif // parser_h diff --git a/tools/preprocess/test/verify/parser_i.h b/tools/preprocess/test/verify/parser_i.h new file mode 100644 index 00000000..f7bec8b2 --- /dev/null +++ b/tools/preprocess/test/verify/parser_i.h @@ -0,0 +1,14 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef parser_i_h +#define parser_i_h +#line 35 "parser.cpp" + +// Try function-pointer typedef +typedef int (* diag_printf_t) (const char *, ...); +#line 38 "parser.cpp" +typedef int (**dblfptr) (void); +#line 39 "parser.cpp" +typedef int (* arrfptr[20]) (void); + +#endif // parser_i_h diff --git a/tools/preprocess/test/verify/parser_noinline.cc b/tools/preprocess/test/verify/parser_noinline.cc new file mode 100644 index 00000000..346fb3e9 --- /dev/null +++ b/tools/preprocess/test/verify/parser_noinline.cc @@ -0,0 +1,75 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#include "parser_noinline.h" +#include "parser_noinline_i.h" + +#line 40 "parser.cpp" + +// Try to initialize a nested structure object. +struct Foo::Bar some_bar = { 1 }; +#line 79 "parser.cpp" + +void find_this (); +#line 85 "parser.cpp" + +#ifdef HEILIGE_WEIHNACHT +#line 87 "parser.cpp" +static void present_this (); +#line 88 "parser.cpp" +#endif + +#line 18 "parser.cpp" + + +int bar() +{} + +#line 22 "parser.cpp" + +// Try multiline NEEDS + + +int baz() +{} + +#line 28 "parser.cpp" + +// Try function arguments +unsigned +somefunc(unsigned (*func1)(), + unsigned (*func2)()) +{ +} + +#line 43 "parser.cpp" + +// And add a Foo function +void Foo::func() +{} + +#line 47 "parser.cpp" + +// Try default arguments +void Foo::bar(int i, int j) +{} + +#line 51 "parser.cpp" + +// Try a constructor with weird syntax + +Foo::Foo() + : something (reinterpret_cast(Baz::bla())) +{} + +#line 57 "parser.cpp" + +// Try implementing an already-declared function +int +Foo::alreadythere() +{} + +#line 62 "parser.cpp" + +int +Foo::alsoalreadythere() +{} diff --git a/tools/preprocess/test/verify/parser_noinline.h b/tools/preprocess/test/verify/parser_noinline.h new file mode 100644 index 00000000..2b39909f --- /dev/null +++ b/tools/preprocess/test/verify/parser_noinline.h @@ -0,0 +1,54 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef parser_noinline_h +#define parser_noinline_h + +// +// INTERFACE definition follows +// + +#line 2 "parser.cpp" + +struct Foo +{ + struct Bar + { + int baz; + }; + +public: + int alreadythere(); + int alsoalreadythere(); + +public: +#line 52 "parser.cpp" + // Try a constructor with weird syntax + + Foo(); + +private: +#line 44 "parser.cpp" + // And add a Foo function + void func(); + +#line 48 "parser.cpp" + // Try default arguments + void bar(int i = 15, int j = somefunc(0, somefunc(0, 0))); +}; + +#line 20 "parser.cpp" +int bar(); + +#line 23 "parser.cpp" +// Try multiline NEEDS + + +int baz(); + +#line 29 "parser.cpp" +// Try function arguments +unsigned +somefunc(unsigned (*func1)(), + unsigned (*func2)()); + +#endif // parser_noinline_h diff --git a/tools/preprocess/test/verify/parser_noinline_i.h b/tools/preprocess/test/verify/parser_noinline_i.h new file mode 100644 index 00000000..a3bdef2f --- /dev/null +++ b/tools/preprocess/test/verify/parser_noinline_i.h @@ -0,0 +1,17 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef parser_noinline_i_h +#define parser_noinline_i_h +#line 16 "parser.cpp" + +#include "foo.h" +#line 35 "parser.cpp" + +// Try function-pointer typedef +typedef int (* diag_printf_t) (const char *, ...); +#line 38 "parser.cpp" +typedef int (**dblfptr) (void); +#line 39 "parser.cpp" +typedef int (* arrfptr[20]) (void); + +#endif // parser_noinline_i_h diff --git a/tools/preprocess/test/verify/random.cc b/tools/preprocess/test/verify/random.cc new file mode 100644 index 00000000..33245a47 --- /dev/null +++ b/tools/preprocess/test/verify/random.cc @@ -0,0 +1,373 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#include "random.h" +#include "random_i.h" + + +#line 208 "random.cpp" +static void function60(); + +#line 211 "random.cpp" +static void function61(); + +#line 214 "random.cpp" +static void function62(); + +#line 217 "random.cpp" +static void function63(); + +#line 220 "random.cpp" +static void function64(); + +#line 23 "random.cpp" + +// Try combinations of {PUBLIC|PROTECTED|PRIVATE|} {static|} +// {inline|INLINE|inline NEEDS[]|INLINE NEEDS[]} {virtual|} + + +void Foo::function0() {} + +#line 29 "random.cpp" + + +void Foo::function1() {} + +#line 32 "random.cpp" + + +void Foo::function2() {} + +#line 35 "random.cpp" + + +void Foo::function3() {} + +#line 38 "random.cpp" + + +void Foo::function4() {} + +#line 41 "random.cpp" + + +void Foo::function5() {} + +#line 44 "random.cpp" + + +void Foo::function6() {} + +#line 47 "random.cpp" + + +void Foo::function7() {} + +#line 50 "random.cpp" + + +void Foo::function8() {} + +#line 53 "random.cpp" + + +void Foo::function9() {} + +#line 56 "random.cpp" + + +void Foo::function10() {} + +#line 59 "random.cpp" + + +void Foo::function11() {} + +#line 62 "random.cpp" + + +void Foo::function12() {} + +#line 65 "random.cpp" + + +void Foo::function13() {} + +#line 68 "random.cpp" + + +void Foo::function14() {} + +#line 71 "random.cpp" + + +void Foo::function15() {} + +#line 74 "random.cpp" + + +void Foo::function16() {} + +#line 77 "random.cpp" + + +void Foo::function17() {} + +#line 80 "random.cpp" + + +void Foo::function18() {} + +#line 83 "random.cpp" + + +void Foo::function19() {} + +#line 86 "random.cpp" + + +void Foo::function20() {} + +#line 89 "random.cpp" + + +void Foo::function21() {} + +#line 92 "random.cpp" + + +void Foo::function22() {} + +#line 95 "random.cpp" + + +void Foo::function23() {} + +#line 98 "random.cpp" + + +void Foo::function24() {} + +#line 101 "random.cpp" + + +void Foo::function25() {} + +#line 104 "random.cpp" + + +void Foo::function26() {} + +#line 107 "random.cpp" + + +void Foo::function27() {} + +#line 110 "random.cpp" + + +void Foo::function28() {} + +#line 113 "random.cpp" + + +void Foo::function29() {} + +#line 116 "random.cpp" + + +void Foo::function30() {} + +#line 119 "random.cpp" + + +void Foo::function31() {} + +#line 122 "random.cpp" + + +void Foo::function32() {} + +#line 125 "random.cpp" + + +void Foo::function33() {} + +#line 128 "random.cpp" + + +void Foo::function34() {} + +#line 131 "random.cpp" + + +void Foo::function35() {} + +#line 134 "random.cpp" + + +void Foo::function36() {} + +#line 137 "random.cpp" + + +void Foo::function37() {} + +#line 140 "random.cpp" + + +void Foo::function38() {} + +#line 143 "random.cpp" + + +void Foo::function39() {} + +#line 146 "random.cpp" + + +void Foo::function40() {} + +#line 149 "random.cpp" + + +void Foo::function41() {} + +#line 152 "random.cpp" + + +void Foo::function42() {} + +#line 155 "random.cpp" + + +void Foo::function43() {} + +#line 158 "random.cpp" + + +void Foo::function44() {} + +#line 161 "random.cpp" + + +void Foo::function45() {} + +#line 164 "random.cpp" + + +void Foo::function46() {} + +#line 167 "random.cpp" + + +void Foo::function47() {} + +#line 170 "random.cpp" + + +void Foo::function48() {} + +#line 173 "random.cpp" + + +void Foo::function49() {} + +#line 176 "random.cpp" + + +void Foo::function50() {} + +#line 179 "random.cpp" + + +void Foo::function51() {} + +#line 182 "random.cpp" + + +void Foo::function52() {} + +#line 185 "random.cpp" + + +void Foo::function53() {} + +#line 188 "random.cpp" + + +void Foo::function54() {} + +#line 191 "random.cpp" + + +void Foo::function55() {} + +#line 194 "random.cpp" + + +void Foo::function56() {} + +#line 197 "random.cpp" + + +void Foo::function57() {} + +#line 200 "random.cpp" + + +void Foo::function58() {} + +#line 203 "random.cpp" + + +void Foo::function59() {} + +#line 206 "random.cpp" + + +static void function60() {} + +#line 209 "random.cpp" + + +static void function61() {} + +#line 212 "random.cpp" + + +static void function62() {} + +#line 215 "random.cpp" + + +static void function63() {} + +#line 218 "random.cpp" + + +static void function64() {} + +#line 221 "random.cpp" + + +void function65() {} + +#line 224 "random.cpp" + + +void function66() {} + +#line 227 "random.cpp" + + +void function67() {} + +#line 230 "random.cpp" + + +void function68() {} + +#line 233 "random.cpp" + + +void function69() {} diff --git a/tools/preprocess/test/verify/random.h b/tools/preprocess/test/verify/random.h new file mode 100644 index 00000000..db77b0d7 --- /dev/null +++ b/tools/preprocess/test/verify/random.h @@ -0,0 +1,227 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef random_h +#define random_h +#line 3 "random.cpp" + +#include "bar.h" + +// +// INTERFACE definition follows +// + +#line 5 "random.cpp" + +class Baz; +#line 7 "random.cpp" + +class Foo : public Bar +{ + // DATA + int d_data; + Baz* d_baz; + +public: +#line 24 "random.cpp" + // Try combinations of {PUBLIC|PROTECTED|PRIVATE|} {static|} + // {inline|INLINE|inline NEEDS[]|INLINE NEEDS[]} {virtual|} + + + static void function0(); + +#line 31 "random.cpp" + static void function1(); + +#line 34 "random.cpp" + static void function2(); + +#line 37 "random.cpp" + static void function3(); + +#line 40 "random.cpp" + static void function4(); + +#line 43 "random.cpp" + virtual void function5(); + +#line 46 "random.cpp" + void function6(); + +#line 49 "random.cpp" + virtual void function7(); + +#line 52 "random.cpp" + void function8(); + +#line 55 "random.cpp" + virtual void function9(); + +#line 58 "random.cpp" + void function10(); + +#line 61 "random.cpp" + virtual void function11(); + +#line 64 "random.cpp" + void function12(); + +#line 67 "random.cpp" + virtual void function13(); + +#line 70 "random.cpp" + void function14(); + +protected: +#line 73 "random.cpp" + static void function15(); + +#line 76 "random.cpp" + static void function16(); + +#line 79 "random.cpp" + static void function17(); + +#line 82 "random.cpp" + static void function18(); + +#line 85 "random.cpp" + static void function19(); + +#line 88 "random.cpp" + virtual void function20(); + +#line 91 "random.cpp" + void function21(); + +#line 94 "random.cpp" + virtual void function22(); + +#line 97 "random.cpp" + void function23(); + +#line 100 "random.cpp" + virtual void function24(); + +#line 103 "random.cpp" + void function25(); + +#line 106 "random.cpp" + virtual void function26(); + +#line 109 "random.cpp" + void function27(); + +#line 112 "random.cpp" + virtual void function28(); + +#line 115 "random.cpp" + void function29(); + +private: +#line 118 "random.cpp" + static void function30(); + +#line 121 "random.cpp" + static void function31(); + +#line 124 "random.cpp" + static void function32(); + +#line 127 "random.cpp" + static void function33(); + +#line 130 "random.cpp" + static void function34(); + +#line 133 "random.cpp" + virtual void function35(); + +#line 136 "random.cpp" + void function36(); + +#line 139 "random.cpp" + virtual void function37(); + +#line 142 "random.cpp" + void function38(); + +#line 145 "random.cpp" + virtual void function39(); + +#line 148 "random.cpp" + void function40(); + +#line 151 "random.cpp" + virtual void function41(); + +#line 154 "random.cpp" + void function42(); + +#line 157 "random.cpp" + virtual void function43(); + +#line 160 "random.cpp" + void function44(); + +#line 163 "random.cpp" + static void function45(); + +#line 166 "random.cpp" + static void function46(); + +#line 169 "random.cpp" + static void function47(); + +#line 172 "random.cpp" + static void function48(); + +#line 175 "random.cpp" + static void function49(); + +#line 178 "random.cpp" + virtual void function50(); + +#line 181 "random.cpp" + void function51(); + +#line 184 "random.cpp" + virtual void function52(); + +#line 187 "random.cpp" + void function53(); + +#line 190 "random.cpp" + virtual void function54(); + +#line 193 "random.cpp" + void function55(); + +#line 196 "random.cpp" + virtual void function56(); + +#line 199 "random.cpp" + void function57(); + +#line 202 "random.cpp" + virtual void function58(); + +#line 205 "random.cpp" + void function59(); +}; + +#line 223 "random.cpp" +void function65(); + +#line 226 "random.cpp" +void function66(); + +#line 229 "random.cpp" +void function67(); + +#line 232 "random.cpp" +void function68(); + +#line 235 "random.cpp" +void function69(); + +#endif // random_h diff --git a/tools/preprocess/test/verify/random_i.h b/tools/preprocess/test/verify/random_i.h new file mode 100644 index 00000000..06622035 --- /dev/null +++ b/tools/preprocess/test/verify/random_i.h @@ -0,0 +1,16 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef random_i_h +#define random_i_h +#line 16 "random.cpp" + +#include "yes.h" +#line 18 "random.cpp" +#include +#line 19 "random.cpp" + +class Rambo +{ +}; + +#endif // random_i_h diff --git a/tools/preprocess/test/verify/random_inline.cc b/tools/preprocess/test/verify/random_inline.cc new file mode 100644 index 00000000..1244895e --- /dev/null +++ b/tools/preprocess/test/verify/random_inline.cc @@ -0,0 +1,110 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#include "random_inline.h" +#include "random_inline_i.h" + + +#line 208 "random.cpp" +static inline void function60(); + +#line 211 "random.cpp" +static inline void function61(); + +#line 214 "random.cpp" +static inline void function62(); + +#line 217 "random.cpp" +static inline void function63(); + +#line 220 "random.cpp" +static void function64(); + +#line 206 "random.cpp" + + +static inline void function60() {} + +#line 209 "random.cpp" + + +static inline void function61() {} + +#line 212 "random.cpp" + + +static inline void function62() {} + +#line 215 "random.cpp" + + +static inline void function63() {} + +#line 38 "random.cpp" + + +void Foo::function4() {} + +#line 65 "random.cpp" + + +void Foo::function13() {} + +#line 68 "random.cpp" + + +void Foo::function14() {} + +#line 83 "random.cpp" + + +void Foo::function19() {} + +#line 110 "random.cpp" + + +void Foo::function28() {} + +#line 113 "random.cpp" + + +void Foo::function29() {} + +#line 128 "random.cpp" + + +void Foo::function34() {} + +#line 155 "random.cpp" + + +void Foo::function43() {} + +#line 158 "random.cpp" + + +void Foo::function44() {} + +#line 173 "random.cpp" + + +void Foo::function49() {} + +#line 200 "random.cpp" + + +void Foo::function58() {} + +#line 203 "random.cpp" + + +void Foo::function59() {} + +#line 218 "random.cpp" + + +static void function64() {} + +#line 233 "random.cpp" + + +void function69() {} diff --git a/tools/preprocess/test/verify/random_inline.h b/tools/preprocess/test/verify/random_inline.h new file mode 100644 index 00000000..03ff3634 --- /dev/null +++ b/tools/preprocess/test/verify/random_inline.h @@ -0,0 +1,388 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef random_inline_h +#define random_inline_h +#line 3 "random.cpp" + +#include "bar.h" + +// +// INTERFACE definition follows +// + +#line 5 "random.cpp" + +class Baz; +#line 7 "random.cpp" + +class Foo : public Bar +{ + // DATA + int d_data; + Baz* d_baz; + +public: +#line 24 "random.cpp" + // Try combinations of {PUBLIC|PROTECTED|PRIVATE|} {static|} + // {inline|INLINE|inline NEEDS[]|INLINE NEEDS[]} {virtual|} + + + static inline void function0(); + +#line 31 "random.cpp" + static inline void function1(); + +#line 34 "random.cpp" + static inline void function2(); + +#line 37 "random.cpp" + static inline void function3(); + +#line 40 "random.cpp" + static void function4(); + +#line 43 "random.cpp" + virtual inline void function5(); + +#line 46 "random.cpp" + inline void function6(); + +#line 49 "random.cpp" + virtual inline void function7(); + +#line 52 "random.cpp" + inline void function8(); + +#line 55 "random.cpp" + virtual inline void function9(); + +#line 58 "random.cpp" + inline void function10(); + +#line 61 "random.cpp" + virtual inline void function11(); + +#line 64 "random.cpp" + inline void function12(); + +#line 67 "random.cpp" + virtual void function13(); + +#line 70 "random.cpp" + void function14(); + +protected: +#line 73 "random.cpp" + static inline void function15(); + +#line 76 "random.cpp" + static inline void function16(); + +#line 79 "random.cpp" + static inline void function17(); + +#line 82 "random.cpp" + static inline void function18(); + +#line 85 "random.cpp" + static void function19(); + +#line 88 "random.cpp" + virtual inline void function20(); + +#line 91 "random.cpp" + inline void function21(); + +#line 94 "random.cpp" + virtual inline void function22(); + +#line 97 "random.cpp" + inline void function23(); + +#line 100 "random.cpp" + virtual inline void function24(); + +#line 103 "random.cpp" + inline void function25(); + +#line 106 "random.cpp" + virtual inline void function26(); + +#line 109 "random.cpp" + inline void function27(); + +#line 112 "random.cpp" + virtual void function28(); + +#line 115 "random.cpp" + void function29(); + +private: +#line 118 "random.cpp" + static inline void function30(); + +#line 121 "random.cpp" + static inline void function31(); + +#line 124 "random.cpp" + static inline void function32(); + +#line 127 "random.cpp" + static inline void function33(); + +#line 130 "random.cpp" + static void function34(); + +#line 133 "random.cpp" + virtual inline void function35(); + +#line 136 "random.cpp" + inline void function36(); + +#line 139 "random.cpp" + virtual inline void function37(); + +#line 142 "random.cpp" + inline void function38(); + +#line 145 "random.cpp" + virtual inline void function39(); + +#line 148 "random.cpp" + inline void function40(); + +#line 151 "random.cpp" + virtual inline void function41(); + +#line 154 "random.cpp" + inline void function42(); + +#line 157 "random.cpp" + virtual void function43(); + +#line 160 "random.cpp" + void function44(); + +#line 163 "random.cpp" + static inline void function45(); + +#line 166 "random.cpp" + static inline void function46(); + +#line 169 "random.cpp" + static inline void function47(); + +#line 172 "random.cpp" + static inline void function48(); + +#line 175 "random.cpp" + static void function49(); + +#line 178 "random.cpp" + virtual inline void function50(); + +#line 181 "random.cpp" + inline void function51(); + +#line 184 "random.cpp" + virtual inline void function52(); + +#line 187 "random.cpp" + inline void function53(); + +#line 190 "random.cpp" + virtual inline void function54(); + +#line 193 "random.cpp" + inline void function55(); + +#line 196 "random.cpp" + virtual inline void function56(); + +#line 199 "random.cpp" + inline void function57(); + +#line 202 "random.cpp" + virtual void function58(); + +#line 205 "random.cpp" + void function59(); +}; + +#line 223 "random.cpp" +inline void function65(); + +#line 226 "random.cpp" +inline void function66(); + +#line 229 "random.cpp" +inline void function67(); + +#line 232 "random.cpp" +inline void function68(); + +#line 235 "random.cpp" +void function69(); + +// +// IMPLEMENTATION includes follow (for use by inline functions/templates) +// + +#line 16 "random.cpp" + +#include "yes.h" + +// +// IMPLEMENTATION of inline functions (and needed classes) +// + +#line 19 "random.cpp" + +class Rambo +{ +}; + +#line 23 "random.cpp" + +// Try combinations of {PUBLIC|PROTECTED|PRIVATE|} {static|} +// {inline|INLINE|inline NEEDS[]|INLINE NEEDS[]} {virtual|} + + +inline void Foo::function0() {} + +#line 29 "random.cpp" + + +inline void Foo::function1() {} + +#line 32 "random.cpp" + + +inline void Foo::function2() {} + +#line 35 "random.cpp" + + +inline void Foo::function3() {} + +#line 41 "random.cpp" + + +inline void Foo::function5() {} + +#line 44 "random.cpp" + + +inline void Foo::function6() {} + +#line 47 "random.cpp" + + +inline void Foo::function7() {} + +#line 50 "random.cpp" + + +inline void Foo::function8() {} + +#line 53 "random.cpp" + + +inline void Foo::function9() {} + +#line 56 "random.cpp" + + +inline void Foo::function10() {} + +#line 59 "random.cpp" + + +inline void Foo::function11() {} + +#line 62 "random.cpp" + + +inline void Foo::function12() {} + +#line 71 "random.cpp" + + +inline void Foo::function15() {} + +#line 74 "random.cpp" + + +inline void Foo::function16() {} + +#line 77 "random.cpp" + + +inline void Foo::function17() {} + +#line 80 "random.cpp" + + +inline void Foo::function18() {} + +#line 86 "random.cpp" + + +inline void Foo::function20() {} + +#line 89 "random.cpp" + + +inline void Foo::function21() {} + +#line 92 "random.cpp" + + +inline void Foo::function22() {} + +#line 95 "random.cpp" + + +inline void Foo::function23() {} + +#line 98 "random.cpp" + + +inline void Foo::function24() {} + +#line 101 "random.cpp" + + +inline void Foo::function25() {} + +#line 104 "random.cpp" + + +inline void Foo::function26() {} + +#line 107 "random.cpp" + + +inline void Foo::function27() {} + +#line 221 "random.cpp" + + +inline void function65() {} + +#line 224 "random.cpp" + + +inline void function66() {} + +#line 227 "random.cpp" + + +inline void function67() {} + +#line 230 "random.cpp" + + +inline void function68() {} + +#endif // random_inline_h diff --git a/tools/preprocess/test/verify/random_inline_i.h b/tools/preprocess/test/verify/random_inline_i.h new file mode 100644 index 00000000..a07def5d --- /dev/null +++ b/tools/preprocess/test/verify/random_inline_i.h @@ -0,0 +1,133 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef random_inline_i_h +#define random_inline_i_h +#line 18 "random.cpp" +#include + +// +// IMPLEMENTATION of inline functions follows +// + + +#line 116 "random.cpp" + + +inline void Foo::function30() {} + +#line 119 "random.cpp" + + +inline void Foo::function31() {} + +#line 122 "random.cpp" + + +inline void Foo::function32() {} + +#line 125 "random.cpp" + + +inline void Foo::function33() {} + +#line 131 "random.cpp" + + +inline void Foo::function35() {} + +#line 134 "random.cpp" + + +inline void Foo::function36() {} + +#line 137 "random.cpp" + + +inline void Foo::function37() {} + +#line 140 "random.cpp" + + +inline void Foo::function38() {} + +#line 143 "random.cpp" + + +inline void Foo::function39() {} + +#line 146 "random.cpp" + + +inline void Foo::function40() {} + +#line 149 "random.cpp" + + +inline void Foo::function41() {} + +#line 152 "random.cpp" + + +inline void Foo::function42() {} + +#line 161 "random.cpp" + + +inline void Foo::function45() {} + +#line 164 "random.cpp" + + +inline void Foo::function46() {} + +#line 167 "random.cpp" + + +inline void Foo::function47() {} + +#line 170 "random.cpp" + + +inline void Foo::function48() {} + +#line 176 "random.cpp" + + +inline void Foo::function50() {} + +#line 179 "random.cpp" + + +inline void Foo::function51() {} + +#line 182 "random.cpp" + + +inline void Foo::function52() {} + +#line 185 "random.cpp" + + +inline void Foo::function53() {} + +#line 188 "random.cpp" + + +inline void Foo::function54() {} + +#line 191 "random.cpp" + + +inline void Foo::function55() {} + +#line 194 "random.cpp" + + +inline void Foo::function56() {} + +#line 197 "random.cpp" + + +inline void Foo::function57() {} + +#endif // random_inline_i_h diff --git a/tools/preprocess/test/verify/static.cc b/tools/preprocess/test/verify/static.cc new file mode 100644 index 00000000..6b0c95cc --- /dev/null +++ b/tools/preprocess/test/verify/static.cc @@ -0,0 +1,35 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#include "static.h" +#include "static_i.h" + +#line 4 "static.cpp" + +extern "C" { + extern char _mappings_1, _mappings_end_1; +} +#line 8 "static.cpp" + +static const vm_offset_t mem_alloc_region + = reinterpret_cast(&_mappings_1); +#line 11 "static.cpp" + +static const vm_offset_t mem_alloc_region_end + = reinterpret_cast(&_mappings_end_1); +#line 14 "static.cpp" + +static kmem_slab_t *amm_entry_cache; +#line 16 "static.cpp" + +static amm_t region_amm; +#line 18 "static.cpp" +static oskit_addr_t end_of_last_region; +#line 19 "static.cpp" +static helping_lock_t region_lock; +#line 20 "static.cpp" + +static char keymap[128][2] = { + {'[', '{'}, +// {']', '}'}, /* 27 */ + {'+', '*'}, /* 27 */ +}; diff --git a/tools/preprocess/test/verify/static.h b/tools/preprocess/test/verify/static.h new file mode 100644 index 00000000..455ac744 --- /dev/null +++ b/tools/preprocess/test/verify/static.h @@ -0,0 +1,6 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef static_h +#define static_h + +#endif // static_h diff --git a/tools/preprocess/test/verify/static_i.h b/tools/preprocess/test/verify/static_i.h new file mode 100644 index 00000000..e24f016b --- /dev/null +++ b/tools/preprocess/test/verify/static_i.h @@ -0,0 +1,6 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef static_i_h +#define static_i_h + +#endif // static_i_h diff --git a/tools/preprocess/test/verify/template.cc b/tools/preprocess/test/verify/template.cc new file mode 100644 index 00000000..2e60849f --- /dev/null +++ b/tools/preprocess/test/verify/template.cc @@ -0,0 +1,24 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#include "template.h" +#include "template_i.h" + + +#line 185 "template.cpp" + + +template <> stack_t* +create_stack() +{ + return new stack(); +} + +#line 192 "template.cpp" + + + +template <> stack_t* +create_stack() +{ + return new stack(); +} diff --git a/tools/preprocess/test/verify/template.h b/tools/preprocess/test/verify/template.h new file mode 100644 index 00000000..320fceb2 --- /dev/null +++ b/tools/preprocess/test/verify/template.h @@ -0,0 +1,301 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef template_h +#define template_h + +// +// INTERFACE definition follows +// + +#line 2 "template.cpp" + +template +class stack_t; +#line 5 "template.cpp" + +template +class stack_top_t +{ +private: + friend class stack_t; + + // Dont change the layout !!, comp_and_swap2 expects + // version and _next next to each other, in that order + int _version; + T *_next; + +public: +#line 46 "template.cpp" + // + // stack_top_t + // + + // template + // stack_top_t & + // stack_top_t::operator=(const stack_top_t& _copy){ + // _version = _copy._version; + // _next = _copy._next; + // return *this; + // } + + + + stack_top_t(int version, T *next); + +#line 67 "template.cpp" + stack_top_t(); +}; +#line 17 "template.cpp" + +template +class stack_t +{ +private: + stack_top_t _head; + +public: +#line 72 "template.cpp" + // + // stack_t + // + + + + stack_t(); + +#line 84 "template.cpp" + int + insert(T *e); + +#line 103 "template.cpp" + T* + dequeue(); + +#line 132 "template.cpp" + // This version of dequeue only returns a value + // if it is equal to the one passed as top + + + T* + dequeue(T *top); + +#line 164 "template.cpp" + T* + first(); + +#line 172 "template.cpp" + void + reset(); +}; + +#line 27 "template.cpp" +// +// atomic-manipulation functions +// + +// typesafe variants + +template bool compare_and_swap(I *ptr, I oldval, I newval); + +#line 41 "template.cpp" +template bool test_and_set(I *l); + +#line 180 "template.cpp" +template stack_t* +create_stack(); + +#line 187 "template.cpp" +template <> stack_t* +create_stack(); + +#line 195 "template.cpp" +template <> stack_t* +create_stack(); + +// +// IMPLEMENTATION of function templates +// + + +#line 26 "template.cpp" + +// +// atomic-manipulation functions +// + +// typesafe variants + +template bool compare_and_swap(I *ptr, I oldval, I newval) +{ + return compare_and_swap(reinterpret_cast(ptr), + *reinterpret_cast(&oldval), + *reinterpret_cast(&newval)); +} + +#line 39 "template.cpp" + + +template bool test_and_set(I *l) +{ + return test_and_set(reinterpret_cast(l)); +} + +#line 45 "template.cpp" + +// +// stack_top_t +// + +// template +// stack_top_t & +// stack_top_t::operator=(const stack_top_t& _copy){ +// _version = _copy._version; +// _next = _copy._next; +// return *this; +// } + + + +template stack_top_t::stack_top_t(int version, T *next) + : _version (version), + _next (next) +{} + +#line 64 "template.cpp" + + + +template stack_top_t::stack_top_t() + : _version (0), + _next (0) +{} + +#line 71 "template.cpp" + +// +// stack_t +// + + + +template stack_t::stack_t() + : _head (0, 0) +{} + +#line 81 "template.cpp" + + + +template int +stack_t::insert(T *e) +{ + stack_top_t old_head, + new_head; + + do { + e->set_next(_head._next); + old_head = _head; + new_head._version = _head._version+1; + new_head._next = e; + } while (! compare_and_swap2((int *) &_head, + (int *) &old_head, + (int *) &new_head)); + return new_head._version; +} + +#line 100 "template.cpp" + + + +template T* +stack_t::dequeue() +{ + stack_top_t old_head, + new_head; + + T *first; + + do { + old_head = _head; + + first = _head._next; + if(! first){ + break; + } + + new_head._next = first->get_next(); + new_head._version = _head._version + 1; + } while (! compare_and_swap2((int *) &_head, + (int *) &old_head, + (int *) &new_head)); + // XXX Why did the old implementation test on e ? + // while (e && ! compare_and_swap(&_first, e, e->list_property.next)); + // This is necessary to handle the case of a empty stack. + + // return old_head._next; + return first; +} + +#line 131 "template.cpp" + +// This version of dequeue only returns a value +// if it is equal to the one passed as top + + +template T* +stack_t::dequeue(T *top) +{ + stack_top_t old_head, + new_head; + // stack_elem_t *first; + + old_head._version = _head._version; // version doesnt matter + old_head._next = top; // cas will fail, if top aint at top + if(!_head._next){ // empty stack + return 0; + } + new_head._version = _head._version + 1; + new_head._next = top->get_next(); + + + if(! compare_and_swap2((int *) &_head, + (int *) &old_head, + (int *) &new_head)) + // we didnt succeed + return 0; + else + // top was on top , so we dequeued it + return top; +} + +#line 161 "template.cpp" + + + +template T* +stack_t::first() +{ + return _head._next; +} + +#line 169 "template.cpp" + + + +template void +stack_t::reset() +{ + _head._version = 0; + _head._next = 0; +} + +#line 178 "template.cpp" + + +template stack_t* +create_stack() +{ + return new stack_t(); +} + +#endif // template_h diff --git a/tools/preprocess/test/verify/template_i.h b/tools/preprocess/test/verify/template_i.h new file mode 100644 index 00000000..350b8566 --- /dev/null +++ b/tools/preprocess/test/verify/template_i.h @@ -0,0 +1,65 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef template_i_h +#define template_i_h +#line 200 "template.cpp" + +// +// Member templates +// + +class Foo +{ + template T* goo(T* t); + +public: +#line 217 "template.cpp" + template T* + bar(T* t); +}; +#line 209 "template.cpp" + +template +class TFoo +{ + +public: +#line 231 "template.cpp" + template T* + baz(T* t); +}; + +// +// IMPLEMENTATION of function templates +// + + +#line 214 "template.cpp" + + + +template T* +Foo::bar(T* t) +{ +} + +#line 221 "template.cpp" + + + +template T* +Foo::goo(T* t) +{ +} + +#line 228 "template.cpp" + + + + +template template T* +TFoo::baz(T* t) +{ +} + +#endif // template_i_h diff --git a/tools/preprocess/test/verify/template_inline.cc b/tools/preprocess/test/verify/template_inline.cc new file mode 100644 index 00000000..5bff8e9e --- /dev/null +++ b/tools/preprocess/test/verify/template_inline.cc @@ -0,0 +1,14 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#include "template_inline.h" +#include "template_inline_i.h" + + +#line 185 "template.cpp" + + +template <> stack_t* +create_stack() +{ + return new stack(); +} diff --git a/tools/preprocess/test/verify/template_inline.h b/tools/preprocess/test/verify/template_inline.h new file mode 100644 index 00000000..b90c7965 --- /dev/null +++ b/tools/preprocess/test/verify/template_inline.h @@ -0,0 +1,316 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef template_inline_h +#define template_inline_h + +// +// INTERFACE definition follows +// + +#line 2 "template.cpp" + +template +class stack_t; +#line 5 "template.cpp" + +template +class stack_top_t +{ +private: + friend class stack_t; + + // Dont change the layout !!, comp_and_swap2 expects + // version and _next next to each other, in that order + int _version; + T *_next; + +public: +#line 46 "template.cpp" + // + // stack_top_t + // + + // template + // stack_top_t & + // stack_top_t::operator=(const stack_top_t& _copy){ + // _version = _copy._version; + // _next = _copy._next; + // return *this; + // } + + + + inline stack_top_t(int version, T *next); + +#line 67 "template.cpp" + inline stack_top_t(); +}; +#line 17 "template.cpp" + +template +class stack_t +{ +private: + stack_top_t _head; + +public: +#line 72 "template.cpp" + // + // stack_t + // + + + + stack_t(); + +#line 84 "template.cpp" + int + insert(T *e); + +#line 103 "template.cpp" + T* + dequeue(); + +#line 132 "template.cpp" + // This version of dequeue only returns a value + // if it is equal to the one passed as top + + + T* + dequeue(T *top); + +#line 164 "template.cpp" + T* + first(); + +#line 172 "template.cpp" + void + reset(); +}; + +#line 27 "template.cpp" +// +// atomic-manipulation functions +// + +// typesafe variants + +template inline bool compare_and_swap(I *ptr, I oldval, I newval); + +#line 41 "template.cpp" +template inline bool test_and_set(I *l); + +#line 180 "template.cpp" +template stack_t* +create_stack(); + +#line 187 "template.cpp" +template <> stack_t* +create_stack(); + +#line 195 "template.cpp" +template <> inline stack_t* +create_stack(); + +// +// IMPLEMENTATION of inline functions (and needed classes) +// + + +#line 45 "template.cpp" + +// +// stack_top_t +// + +// template +// stack_top_t & +// stack_top_t::operator=(const stack_top_t& _copy){ +// _version = _copy._version; +// _next = _copy._next; +// return *this; +// } + + + +template inline stack_top_t::stack_top_t(int version, T *next) + : _version (version), + _next (next) +{} + +#line 64 "template.cpp" + + + +template inline stack_top_t::stack_top_t() + : _version (0), + _next (0) +{} + +#line 26 "template.cpp" + +// +// atomic-manipulation functions +// + +// typesafe variants + +template inline bool compare_and_swap(I *ptr, I oldval, I newval) +{ + return compare_and_swap(reinterpret_cast(ptr), + *reinterpret_cast(&oldval), + *reinterpret_cast(&newval)); +} + +#line 39 "template.cpp" + + +template inline bool test_and_set(I *l) +{ + return test_and_set(reinterpret_cast(l)); +} + +#line 192 "template.cpp" + + + +template <> inline stack_t* +create_stack() +{ + return new stack(); +} + +// +// IMPLEMENTATION of function templates +// + + +#line 71 "template.cpp" + +// +// stack_t +// + + + +template stack_t::stack_t() + : _head (0, 0) +{} + +#line 81 "template.cpp" + + + +template int +stack_t::insert(T *e) +{ + stack_top_t old_head, + new_head; + + do { + e->set_next(_head._next); + old_head = _head; + new_head._version = _head._version+1; + new_head._next = e; + } while (! compare_and_swap2((int *) &_head, + (int *) &old_head, + (int *) &new_head)); + return new_head._version; +} + +#line 100 "template.cpp" + + + +template T* +stack_t::dequeue() +{ + stack_top_t old_head, + new_head; + + T *first; + + do { + old_head = _head; + + first = _head._next; + if(! first){ + break; + } + + new_head._next = first->get_next(); + new_head._version = _head._version + 1; + } while (! compare_and_swap2((int *) &_head, + (int *) &old_head, + (int *) &new_head)); + // XXX Why did the old implementation test on e ? + // while (e && ! compare_and_swap(&_first, e, e->list_property.next)); + // This is necessary to handle the case of a empty stack. + + // return old_head._next; + return first; +} + +#line 131 "template.cpp" + +// This version of dequeue only returns a value +// if it is equal to the one passed as top + + +template T* +stack_t::dequeue(T *top) +{ + stack_top_t old_head, + new_head; + // stack_elem_t *first; + + old_head._version = _head._version; // version doesnt matter + old_head._next = top; // cas will fail, if top aint at top + if(!_head._next){ // empty stack + return 0; + } + new_head._version = _head._version + 1; + new_head._next = top->get_next(); + + + if(! compare_and_swap2((int *) &_head, + (int *) &old_head, + (int *) &new_head)) + // we didnt succeed + return 0; + else + // top was on top , so we dequeued it + return top; +} + +#line 161 "template.cpp" + + + +template T* +stack_t::first() +{ + return _head._next; +} + +#line 169 "template.cpp" + + + +template void +stack_t::reset() +{ + _head._version = 0; + _head._next = 0; +} + +#line 178 "template.cpp" + + +template stack_t* +create_stack() +{ + return new stack_t(); +} + +#endif // template_inline_h diff --git a/tools/preprocess/test/verify/template_inline_i.h b/tools/preprocess/test/verify/template_inline_i.h new file mode 100644 index 00000000..a967c26d --- /dev/null +++ b/tools/preprocess/test/verify/template_inline_i.h @@ -0,0 +1,65 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef template_inline_i_h +#define template_inline_i_h +#line 200 "template.cpp" + +// +// Member templates +// + +class Foo +{ + template T* goo(T* t); + +public: +#line 217 "template.cpp" + template T* + bar(T* t); +}; +#line 209 "template.cpp" + +template +class TFoo +{ + +public: +#line 231 "template.cpp" + template T* + baz(T* t); +}; + +// +// IMPLEMENTATION of function templates +// + + +#line 214 "template.cpp" + + + +template T* +Foo::bar(T* t) +{ +} + +#line 221 "template.cpp" + + + +template T* +Foo::goo(T* t) +{ +} + +#line 228 "template.cpp" + + + + +template template T* +TFoo::baz(T* t) +{ +} + +#endif // template_inline_i_h diff --git a/tools/preprocess/test/verify/variable.cc b/tools/preprocess/test/verify/variable.cc new file mode 100644 index 00000000..99f6c2a5 --- /dev/null +++ b/tools/preprocess/test/verify/variable.cc @@ -0,0 +1,11 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#include "variable.h" +#include "variable_i.h" + +#line 2 "variable.cpp" + +int (Foo::*func_vec[100]) (int arg) = +{ + 0, +}; diff --git a/tools/preprocess/test/verify/variable.h b/tools/preprocess/test/verify/variable.h new file mode 100644 index 00000000..5db219a5 --- /dev/null +++ b/tools/preprocess/test/verify/variable.h @@ -0,0 +1,6 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef variable_h +#define variable_h + +#endif // variable_h diff --git a/tools/preprocess/test/verify/variable_i.h b/tools/preprocess/test/verify/variable_i.h new file mode 100644 index 00000000..a8eda5d3 --- /dev/null +++ b/tools/preprocess/test/verify/variable_i.h @@ -0,0 +1,6 @@ +// AUTOMATICALLY GENERATED -- DO NOT EDIT! -*- c++ -*- + +#ifndef variable_i_h +#define variable_i_h + +#endif // variable_i_h

+ +reorder-after + +reorder-after + + +reorder-after + ;;;IGNORE + ;;;IGNORE +reorder-after + ;;;IGNORE + ;;;IGNORE + +reorder-after + ;;;IGNORE + ;;;IGNORE +reorder-after + ;;;IGNORE + ;;;IGNORE + +reorder-after + ;;;IGNORE + ;;;IGNORE +reorder-after + ;;;IGNORE + ;;;IGNORE + +reorder-after + ;;;IGNORE + ;;;IGNORE +reorder-after + ;;;IGNORE + ;;;IGNORE + +reorder-after + ;;;IGNORE + ;;;IGNORE +reorder-after + ;;;IGNORE + ;;;IGNORE + +reorder-after + ;;;IGNORE + ;;;IGNORE +reorder-after + ;;;IGNORE + ;;;IGNORE + +reorder-after + ;;;IGNORE + ;;;IGNORE +reorder-after + ;;;IGNORE + ;;;IGNORE + +reorder-after + ;;;IGNORE + ;;;IGNORE +reorder-after + ;;;IGNORE + ;;;IGNORE + +reorder-end + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/da_DK b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/da_DK new file mode 100644 index 00000000..83ea9da7 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/da_DK @@ -0,0 +1,2075 @@ +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +% Base collation scheme: 1994-03-22 + +% Ordering algorithm: +% 1. Spaces and hyphen (but not soft +% hyphen) before punctuation +% characters, punctuation characters +% before numbers, +% numbers before letters. +% 2. Letters with diacritical marks are +% members of equivalence classes +% 3. A distinction is made with regards +% to case as noted below. +% 4. Special characters are ignored +% when comparing letters, but then +% they are considered +% 5. The alphabets are sorted in order +% of first appearance in ISO 10646: +% Latin, Greek, Cyrillic, etc. +% +% According to Greek specifications, +% the steps 2. and 3. above are reversed +% for the Greek script + +% collating symbols + +% The collating symbol naming is +% mostly taken from ISO 10646-1, +% for example the case and accent +% names are from this standard. + +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +% and +% are for cases like Danish +% and Spanish being treated +% as one letter. + +% The ...... collating +% symbols have defined weights as +% the last character in a group of +% Latin letters. They are used +% to specify deltas by locales using +% a locale as the default ordering +% and by "replace-after" statements +% specifying the changed placement +% in an ordering of a character. + +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +% letter;accent;case;specials + +order_start forward;backward;forward;position + +% or letters first: + + + + + + +% Accents: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ;;;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; +<"=> IGNORE;IGNORE;IGNORE;<"=> + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; +UNDEFINED IGNORE;IGNORE;IGNORE + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + +% and are treated as in Danish + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + +% is a separate letter in Danish + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE +% is a separate letter in Danish + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE +% is a separate letter in Danish + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + +% Arabic collating + + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + +% katakana/hiragana sorting +% base is katakana, as this is present in most charsets +% normal before voiced before semi-voiced +% small vocals before normal vocals +% katakana before hiragana + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + +order_end + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/de_AT b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/de_AT new file mode 100644 index 00000000..5314a57d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/de_AT @@ -0,0 +1,2 @@ +% Copy the template from ISO/IEC 14651 +copy "iso14651_t1" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/de_BE b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/de_BE new file mode 100644 index 00000000..3738ee3c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/de_BE @@ -0,0 +1 @@ +copy "iso14651_t1" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/de_CH b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/de_CH new file mode 100644 index 00000000..3738ee3c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/de_CH @@ -0,0 +1 @@ +copy "iso14651_t1" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/de_DE b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/de_DE new file mode 100644 index 00000000..35ae3c60 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/de_DE @@ -0,0 +1,4 @@ + +% Copy the template from ISO/IEC 14651 +copy "iso14651_t1" + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/de_LU b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/de_LU new file mode 100644 index 00000000..3738ee3c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/de_LU @@ -0,0 +1 @@ +copy "iso14651_t1" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/el_GR b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/el_GR new file mode 100644 index 00000000..3738ee3c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/el_GR @@ -0,0 +1 @@ +copy "iso14651_t1" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/en_AU b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/en_AU new file mode 100644 index 00000000..3738ee3c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/en_AU @@ -0,0 +1 @@ +copy "iso14651_t1" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/en_BW b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/en_BW new file mode 100644 index 00000000..a7e92858 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/en_BW @@ -0,0 +1 @@ +copy "en_ZA" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/en_CA b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/en_CA new file mode 100644 index 00000000..ab4b6900 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/en_CA @@ -0,0 +1,2061 @@ + +% Base collation scheme: 1994-03-22 + +% Ordering algorithm: +% 1. Spaces and hyphen (but not soft +% hyphen) before punctuation +% characters, punctuation characters +% before numbers, +% numbers before letters. +% 2. Letters with diacritical marks are +% members of equivalence classes +% 3. A distinction is made with regards +% to case as noted below. +% 4. Special characters are ignored +% when comparing letters, but then +% they are considered +% 5. The alphabets are sorted in order +% of first appearance in ISO 10646: +% Latin, Greek, Cyrillic, etc. +% +% According to Greek specifications, +% the steps 2. and 3. above are reversed +% for the Greek script + +% collating symbols + +% The collating symbol naming is +% mostly taken from ISO 10646-1, +% for example the case and accent +% names are from this standard. + +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +% and +% are for cases like Danish +% and Spanish being treated +% as one letter. + +% The ...... collating +% symbols have defined weights as +% the last character in a group of +% Latin letters. They are used +% to specify deltas by locales using +% a locale as the default ordering +% and by "replace-after" statements +% specifying the changed placement +% in an ordering of a character. + +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +% letter;accent;case;specials + +order_start forward;backward;forward;position + +% or letters first: + + + + + + +% Accents: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ;;;IGNORE + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; +<"=> IGNORE;IGNORE;IGNORE;<"=> + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; +UNDEFINED IGNORE;IGNORE;IGNORE + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + +% Arabic collating + + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + +% katakana/hiragana sorting +% base is katakana, as this is present in most charsets +% normal before voiced before semi-voiced +% small vocals before normal vocals +% katakana before hiragana + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + +order_end + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/en_DK b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/en_DK new file mode 100644 index 00000000..3738ee3c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/en_DK @@ -0,0 +1 @@ +copy "iso14651_t1" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/en_GB b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/en_GB new file mode 100644 index 00000000..5314a57d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/en_GB @@ -0,0 +1,2 @@ +% Copy the template from ISO/IEC 14651 +copy "iso14651_t1" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/en_HK b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/en_HK new file mode 100644 index 00000000..3738ee3c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/en_HK @@ -0,0 +1 @@ +copy "iso14651_t1" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/en_IE b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/en_IE new file mode 100644 index 00000000..3738ee3c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/en_IE @@ -0,0 +1 @@ +copy "iso14651_t1" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/en_IN b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/en_IN new file mode 100644 index 00000000..35ae3c60 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/en_IN @@ -0,0 +1,4 @@ + +% Copy the template from ISO/IEC 14651 +copy "iso14651_t1" + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/en_NZ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/en_NZ new file mode 100644 index 00000000..3738ee3c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/en_NZ @@ -0,0 +1 @@ +copy "iso14651_t1" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/en_PH b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/en_PH new file mode 100644 index 00000000..35ae3c60 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/en_PH @@ -0,0 +1,4 @@ + +% Copy the template from ISO/IEC 14651 +copy "iso14651_t1" + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/en_SG b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/en_SG new file mode 100644 index 00000000..35ae3c60 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/en_SG @@ -0,0 +1,4 @@ + +% Copy the template from ISO/IEC 14651 +copy "iso14651_t1" + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/en_US b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/en_US new file mode 100644 index 00000000..35ae3c60 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/en_US @@ -0,0 +1,4 @@ + +% Copy the template from ISO/IEC 14651 +copy "iso14651_t1" + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/en_ZA b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/en_ZA new file mode 100644 index 00000000..3738ee3c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/en_ZA @@ -0,0 +1 @@ +copy "iso14651_t1" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/en_ZW b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/en_ZW new file mode 100644 index 00000000..a7e92858 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/en_ZW @@ -0,0 +1 @@ +copy "en_ZA" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/eo_EO b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/eo_EO new file mode 100644 index 00000000..c8057f5c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/eo_EO @@ -0,0 +1,49 @@ +copy "iso14651_t1" + +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +reorder-after + +reorder-after + +reorder-after + +reorder-after + +reorder-after + +reorder-after + + +reorder-after + ;;;IGNORE % Ĉ +reorder-after + ;;;IGNORE % ĉ +reorder-after + ;;;IGNORE % Äœ +reorder-after + ;;;IGNORE % Ä +reorder-after + ;;;IGNORE % Ĥ +reorder-after + ;;;IGNORE % Ä¥ +reorder-after + ;;;IGNORE % Ä´ +reorder-after + ;;;IGNORE % ĵ +reorder-after + ;;;IGNORE % Åœ +reorder-after + ;;;IGNORE % Å +reorder-after + ;;;IGNORE % Ŭ +reorder-after + ;;;IGNORE % Å­ + +reorder-end + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/es_AR b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/es_AR new file mode 100644 index 00000000..09fd11b5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/es_AR @@ -0,0 +1 @@ +copy "es_ES" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/es_BO b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/es_BO new file mode 100644 index 00000000..09fd11b5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/es_BO @@ -0,0 +1 @@ +copy "es_ES" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/es_CL b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/es_CL new file mode 100644 index 00000000..09fd11b5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/es_CL @@ -0,0 +1 @@ +copy "es_ES" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/es_CO b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/es_CO new file mode 100644 index 00000000..09fd11b5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/es_CO @@ -0,0 +1 @@ +copy "es_ES" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/es_CR b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/es_CR new file mode 100644 index 00000000..09fd11b5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/es_CR @@ -0,0 +1 @@ +copy "es_ES" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/es_DO b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/es_DO new file mode 100644 index 00000000..09fd11b5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/es_DO @@ -0,0 +1 @@ +copy "es_ES" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/es_EC b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/es_EC new file mode 100644 index 00000000..a0ea9adb --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/es_EC @@ -0,0 +1 @@ +copy "es_US" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/es_ES b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/es_ES new file mode 100644 index 00000000..2c0a0334 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/es_ES @@ -0,0 +1,2061 @@ + +% Base collation scheme: 1994-03-22 + +% Ordering algorithm: +% 1. Spaces and hyphen (but not soft +% hyphen) before punctuation +% characters, punctuation characters +% before numbers, +% numbers before letters. +% 2. Letters with diacritical marks are +% members of equivalence classes +% 3. A distinction is made with regards +% to case as noted below. +% 4. Special characters are ignored +% when comparing letters, but then +% they are considered +% 5. The alphabets are sorted in order +% of first appearance in ISO 10646: +% Latin, Greek, Cyrillic, etc. +% +% According to Greek specifications, +% the steps 2. and 3. above are reversed +% for the Greek script + +% collating symbols + +% The collating symbol naming is +% mostly taken from ISO 10646-1, +% for example the case and accent +% names are from this standard. + +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +% and +% are for cases like Danish +% and Spanish being treated +% as one letter. + +% The ...... collating +% symbols have defined weights as +% the last character in a group of +% Latin letters. They are used +% to specify deltas by locales using +% a locale as the default ordering +% and by "replace-after" statements +% specifying the changed placement +% in an ordering of a character. + +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +% letter;accent;case;specials + +order_start forward;backward;forward;position + +% or letters first: + + + + + + +% Accents: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ;;;IGNORE + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; +<"=> IGNORE;IGNORE;IGNORE;<"=> + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; +UNDEFINED IGNORE;IGNORE;IGNORE + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + +% Arabic collating + + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + +% katakana/hiragana sorting +% base is katakana, as this is present in most charsets +% normal before voiced before semi-voiced +% small vocals before normal vocals +% katakana before hiragana + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + +order_end + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/es_GT b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/es_GT new file mode 100644 index 00000000..09fd11b5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/es_GT @@ -0,0 +1 @@ +copy "es_ES" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/es_HN b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/es_HN new file mode 100644 index 00000000..09fd11b5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/es_HN @@ -0,0 +1 @@ +copy "es_ES" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/es_MX b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/es_MX new file mode 100644 index 00000000..09fd11b5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/es_MX @@ -0,0 +1 @@ +copy "es_ES" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/es_NI b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/es_NI new file mode 100644 index 00000000..09fd11b5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/es_NI @@ -0,0 +1 @@ +copy "es_ES" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/es_PA b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/es_PA new file mode 100644 index 00000000..09fd11b5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/es_PA @@ -0,0 +1 @@ +copy "es_ES" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/es_PE b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/es_PE new file mode 100644 index 00000000..09fd11b5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/es_PE @@ -0,0 +1 @@ +copy "es_ES" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/es_PR b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/es_PR new file mode 100644 index 00000000..09fd11b5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/es_PR @@ -0,0 +1 @@ +copy "es_ES" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/es_PY b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/es_PY new file mode 100644 index 00000000..09fd11b5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/es_PY @@ -0,0 +1 @@ +copy "es_ES" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/es_SV b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/es_SV new file mode 100644 index 00000000..09fd11b5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/es_SV @@ -0,0 +1 @@ +copy "es_ES" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/es_US b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/es_US new file mode 100644 index 00000000..56a4f366 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/es_US @@ -0,0 +1,2077 @@ +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +% Base collation scheme: 1994-03-22 + +% Ordering algorithm: +% 1. Spaces and hyphen (but not soft +% hyphen) before punctuation +% characters, punctuation characters +% before numbers, +% numbers before letters. +% 2. Letters with diacritical marks are +% members of equivalence classes +% 3. A distinction is made with regards +% to case as noted below. +% 4. Special characters are ignored +% when comparing letters, but then +% they are considered +% 5. The alphabets are sorted in order +% of first appearance in ISO 10646: +% Latin, Greek, Cyrillic, etc. +% +% According to Greek specifications, +% the steps 2. and 3. above are reversed +% for the Greek script + +% collating symbols + +% The collating symbol naming is +% mostly taken from ISO 10646-1, +% for example the case and accent +% names are from this standard. + +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +% and +% are for cases like Danish +% and Spanish being treated +% as one letter. + +% The ...... collating +% symbols have defined weights as +% the last character in a group of +% Latin letters. They are used +% to specify deltas by locales using +% a locale as the default ordering +% and by "replace-after" statements +% specifying the changed placement +% in an ordering of a character. + +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +% letter;accent;case;specials + +order_start forward;backward;forward;position + +% or letters first: + + + + + + +% Accents: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ;;;IGNORE + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; +<"=> IGNORE;IGNORE;IGNORE;<"=> + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; +UNDEFINED IGNORE;IGNORE;IGNORE + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + +% Arabic collating + + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + +% katakana/hiragana sorting +% base is katakana, as this is present in most charsets +% normal before voiced before semi-voiced +% small vocals before normal vocals +% katakana before hiragana + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + +order_end + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/es_UY b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/es_UY new file mode 100644 index 00000000..09fd11b5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/es_UY @@ -0,0 +1 @@ +copy "es_ES" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/es_VE b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/es_VE new file mode 100644 index 00000000..09fd11b5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/es_VE @@ -0,0 +1 @@ +copy "es_ES" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/et_EE b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/et_EE new file mode 100644 index 00000000..88c7aae3 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/et_EE @@ -0,0 +1,2061 @@ + +% Base collation scheme: 1994-03-22 + +% Ordering algorithm: +% 1. Spaces and hyphen (but not soft +% hyphen) before punctuation +% characters, punctuation characters +% before numbers, +% numbers before letters. +% 2. Letters with diacritical marks are +% members of equivalence classes +% 3. A distinction is made with regards +% to case as noted below. +% 4. Special characters are ignored +% when comparing letters, but then +% they are considered +% 5. The alphabets are sorted in order +% of first appearance in ISO 10646: +% Latin, Greek, Cyrillic, etc. +% +% According to Greek specifications, +% the steps 2. and 3. above are reversed +% for the Greek script + +% collating symbols + +% The collating symbol naming is +% mostly taken from ISO 10646-1, +% for example the case and accent +% names are from this standard. + +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +% and +% are for cases like Danish +% and Spanish being treated +% as one letter. + +% The ...... collating +% symbols have defined weights as +% the last character in a group of +% Latin letters. They are used +% to specify deltas by locales using +% a locale as the default ordering +% and by "replace-after" statements +% specifying the changed placement +% in an ordering of a character. + +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +% letter;accent;case;specials + +order_start forward;backward;forward;position + +% or letters first: + + + + + + +% Accents: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ;;;IGNORE + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; +<"=> IGNORE;IGNORE;IGNORE;<"=> + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; +UNDEFINED IGNORE;IGNORE;IGNORE + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;; + ;; + ;; + ;; + ;; + ;; + ;; + ;; + ;; + ;; + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;; + ;; + ;; + ;; + ;; + ;; + ;; + ;; + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + +% Arabic collating + + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + +% katakana/hiragana sorting +% base is katakana, as this is present in most charsets +% normal before voiced before semi-voiced +% small vocals before normal vocals +% katakana before hiragana + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + +order_end + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/eu_ES b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/eu_ES new file mode 100644 index 00000000..3738ee3c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/eu_ES @@ -0,0 +1 @@ +copy "iso14651_t1" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/fa_IR b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/fa_IR new file mode 100644 index 00000000..a1715919 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/fa_IR @@ -0,0 +1,185 @@ +copy "iso14651_t1" + +% The Persian alphabet order is: ALEF WITH MADDA ABOVE, ALEF, HAMZA (all +% kinds), BEH, PEH, TEH, JEEM, TCHEH, HAH, KHAH, DAL, THAL, REH, ZAIN, JEH, +% SEEN, SHEEN, SAD, DAD, TAH, ZAH, AIN, GHAIN, FEH, QAF, KAF, GAF, LAM, +% MEEM, NOON, WAW, HEH, YEH. +% The various kind of HAMZA are sorted as ALEF WITH HAMZA ABOVE, ALEF WITH +% HAMZA BELOW, WAW WITH HAMZA ABOVE, YEH WITH HAMZA ABOVE. + +collating-symbol % accent hamza over yeh +collating-symbol % dotless +collating-symbol % with dots over +collating-symbol % with wasla over + +collating-symbol +collating-symbol + +% Alternate representations displayed the same +collating-symbol +collating-symbol + +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +reorder-after + + + + + + + + + + +reorder-after + + + +reorder-after + + + + +reorder-after + + + +% Persian uses fatha, kasra, damma, fathatan, kasratan, dammatan order. + +reorder-after + IGNORE;IGNORE;IGNORE; % + IGNORE;IGNORE;IGNORE; % + IGNORE;IGNORE;IGNORE; % + IGNORE;IGNORE;IGNORE; % + IGNORE;IGNORE;IGNORE; % + IGNORE;IGNORE;IGNORE; % + IGNORE;IGNORE;IGNORE; % + IGNORE;IGNORE;IGNORE; % + IGNORE;IGNORE;IGNORE; % + IGNORE;IGNORE;IGNORE; % + IGNORE;IGNORE;IGNORE; % + IGNORE;IGNORE;IGNORE; % + IGNORE;IGNORE;IGNORE; % + IGNORE;IGNORE;IGNORE; % + IGNORE;IGNORE;IGNORE; % + IGNORE;IGNORE;IGNORE; % + +reorder-after + IGNORE;IGNORE;IGNORE; % + IGNORE;IGNORE;IGNORE; % + IGNORE;IGNORE;IGNORE; % + IGNORE;IGNORE;IGNORE; % + +% Persian digits are sorted before Arabic ones: they are the basic forms. +reorder-after + <0>;;;IGNORE + <0>;;;IGNORE + <1>;;;IGNORE + <1>;;;IGNORE + <2>;;;IGNORE + <2>;;;IGNORE + <3>;;;IGNORE + <3>;;;IGNORE + <4>;;;IGNORE + <4>;;;IGNORE + <5>;;;IGNORE + <5>;;;IGNORE + <6>;;;IGNORE + <6>;;;IGNORE + <7>;;;IGNORE + <7>;;;IGNORE + <8>;;;IGNORE + <8>;;;IGNORE + <9>;;;IGNORE + <9>;;;IGNORE + +% And then the letters: + ;;;IGNORE % Alef With Madda Above + ;;;IGNORE + ;;;IGNORE % Alef + ;;;IGNORE % Alef Wasla + ;;;IGNORE % Hamza + ;;;IGNORE % Alef With Hamza Above + ;;;IGNORE + ;;;IGNORE % Alef With Hamza Below + ;;;IGNORE + ;;;IGNORE % Waw With Hamza Above + ;;;IGNORE + ;;;IGNORE % Yeh With Hamza Above + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE +reorder-after + ;;;IGNORE % Keheh + ;;;IGNORE % Kaf +reorder-after + ;;;IGNORE % Heh + ;;;IGNORE % Teh Marbuta + ;;;IGNORE % Heh With Yeh Above + ;;;IGNORE % Farsi Yeh + ;;;IGNORE % Alef Maksura + ;;;IGNORE % Yeh + +% Finally the letters in Presentation Form: +reorder-after + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE +reorder-after + "";"";"";IGNORE % Rial Sign +reorder-after + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE +reorder-after + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE +reorder-end + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/fi_FI b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/fi_FI new file mode 100644 index 00000000..f5109984 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/fi_FI @@ -0,0 +1,2062 @@ + +% Base collation scheme: 1994-03-22 + +% Ordering algorithm: +% 1. Spaces and hyphen (but not soft +% hyphen) before punctuation +% characters, punctuation characters +% before numbers, +% numbers before letters. +% 2. Letters with diacritical marks are +% members of equivalence classes +% 3. A distinction is made with regards +% to case as noted below. +% 4. Special characters are ignored +% when comparing letters, but then +% they are considered +% 5. The alphabets are sorted in order +% of first appearance in ISO 10646: +% Latin, Greek, Cyrillic, etc. +% +% According to Greek specifications, +% the steps 2. and 3. above are reversed +% for the Greek script + +% collating symbols + +% The collating symbol naming is +% mostly taken from ISO 10646-1, +% for example the case and accent +% names are from this standard. + +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +% and +% are for cases like Danish +% and Spanish being treated +% as one letter. + +% The ...... collating +% symbols have defined weights as +% the last character in a group of +% Latin letters. They are used +% to specify deltas by locales using +% a locale as the default ordering +% and by "replace-after" statements +% specifying the changed placement +% in an ordering of a character. + +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +% letter;accent;case;specials + +order_start forward;backward;forward;position + +% or letters first: + +% before letters + + + + + +% Accents: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ;;;IGNORE + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; +<"=> IGNORE;IGNORE;IGNORE;<"=> + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; +UNDEFINED IGNORE;IGNORE;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + ;;; + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + +% Arabic collating + + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + +% katakana/hiragana sorting +% base is katakana, as this is present in most charsets +% normal before voiced before semi-voiced +% small vocals before normal vocals +% katakana before hiragana + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + +order_end + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/fo_FO b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/fo_FO new file mode 100644 index 00000000..b7628e76 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/fo_FO @@ -0,0 +1 @@ +copy "da_DK" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/fr_BE b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/fr_BE new file mode 100644 index 00000000..3738ee3c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/fr_BE @@ -0,0 +1 @@ +copy "iso14651_t1" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/fr_CA b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/fr_CA new file mode 100644 index 00000000..c9110957 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/fr_CA @@ -0,0 +1 @@ +copy "en_CA" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/fr_CH b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/fr_CH new file mode 100644 index 00000000..3738ee3c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/fr_CH @@ -0,0 +1 @@ +copy "iso14651_t1" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/fr_FR b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/fr_FR new file mode 100644 index 00000000..5314a57d --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/fr_FR @@ -0,0 +1,2 @@ +% Copy the template from ISO/IEC 14651 +copy "iso14651_t1" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/fr_LU b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/fr_LU new file mode 100644 index 00000000..3738ee3c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/fr_LU @@ -0,0 +1 @@ +copy "iso14651_t1" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ga_IE b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ga_IE new file mode 100644 index 00000000..3738ee3c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/ga_IE @@ -0,0 +1 @@ +copy "iso14651_t1" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/gd_GB b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/gd_GB new file mode 100644 index 00000000..d66184ec --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/gd_GB @@ -0,0 +1 @@ +copy "en_DK" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/gl_ES b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/gl_ES new file mode 100644 index 00000000..09fd11b5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/gl_ES @@ -0,0 +1 @@ +copy "es_ES" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/gv_GB b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/gv_GB new file mode 100644 index 00000000..3738ee3c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/gv_GB @@ -0,0 +1 @@ +copy "iso14651_t1" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/he_IL b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/he_IL new file mode 100644 index 00000000..3738ee3c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/he_IL @@ -0,0 +1 @@ +copy "iso14651_t1" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/hi_IN b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/hi_IN new file mode 100644 index 00000000..35ae3c60 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/hi_IN @@ -0,0 +1,4 @@ + +% Copy the template from ISO/IEC 14651 +copy "iso14651_t1" + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/hr_HR b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/hr_HR new file mode 100644 index 00000000..0929ea78 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/hr_HR @@ -0,0 +1,2085 @@ +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +% Base collation scheme: 1994-03-22 + +% Ordering algorithm: +% 1. Spaces and hyphen (but not soft +% hyphen) before punctuation +% characters, punctuation characters +% before numbers, +% numbers before letters. +% 2. Letters with diacritical marks are +% members of equivalence classes +% 3. A distinction is made with regards +% to case as noted below. +% 4. Special characters are ignored +% when comparing letters, but then +% they are considered +% 5. The alphabets are sorted in order +% of first appearance in ISO 10646: +% Latin, Greek, Cyrillic, etc. +% +% According to Greek specifications, +% the steps 2. and 3. above are reversed +% for the Greek script + +% collating symbols + +% The collating symbol naming is +% mostly taken from ISO 10646-1, +% for example the case and accent +% names are from this standard. + +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +% and +% are for cases like Danish +% and Spanish being treated +% as one letter. + +% The ...... collating +% symbols have defined weights as +% the last character in a group of +% Latin letters. They are used +% to specify deltas by locales using +% a locale as the default ordering +% and by "replace-after" statements +% specifying the changed placement +% in an ordering of a character. + +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +% letter;accent;case;specials + +order_start forward;backward;forward;position + +% or letters first: + + + + + + +% Accents: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ;;;IGNORE + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; +<"=> IGNORE;IGNORE;IGNORE;<"=> + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; +UNDEFINED IGNORE;IGNORE;IGNORE + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + +% Arabic collating + + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + +% katakana/hiragana sorting +% base is katakana, as this is present in most charsets +% normal before voiced before semi-voiced +% small vocals before normal vocals +% katakana before hiragana + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + +order_end + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/hu_HU b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/hu_HU new file mode 100644 index 00000000..e87bb761 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/hu_HU @@ -0,0 +1,357 @@ +copy "iso14651_t1" + +%% a b c cs d dz dzs e f g gy h i j k l ly m n ny o o: p q +%% r s sz t ty u u: v w x y z zs +%% +%% a' e' i' o' u' are sorted as if they were unaccented +%% o" and u" are sorted as if they were o: and u: + +collating-symbol +collating-symbol + +collating-symbol +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-symbol +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-symbol +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-symbol +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-symbol +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-symbol +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-symbol +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-symbol +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-symbol +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" +collating-element from "" + +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +reorder-after + + + + + + +reorder-after + + + + + + +reorder-after + +reorder-after + + +reorder-after + +reorder-after + +reorder-after + +reorder-after + +reorder-after + +reorder-after + +reorder-after + +reorder-after + + +reorder-after + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + +reorder-after + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + +reorder-after + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE +reorder-after + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + +reorder-after + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE +reorder-after + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + +reorder-after + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE +reorder-after + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + +reorder-after + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE +reorder-after + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + +reorder-after + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE +reorder-after + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + +reorder-after + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE +reorder-after + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + +reorder-after + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE +reorder-after + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + +reorder-after + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE +reorder-after + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + +reorder-after + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE +reorder-after + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + +reorder-end + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/hy_AM b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/hy_AM new file mode 100644 index 00000000..1132128b --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/hy_AM @@ -0,0 +1,91 @@ + +% Armenian sorting is not yet on iso14651_t1 + +copy "iso14651_t1" + +script + +order_start ;forward;forward;forward;forward,position + + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % + ;;;IGNORE % +order-end + +reorder-sections-after + +reorder-sections-end + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/id_ID b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/id_ID new file mode 100644 index 00000000..3738ee3c --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/id_ID @@ -0,0 +1 @@ +copy "iso14651_t1" diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/is_IS b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/is_IS new file mode 100644 index 00000000..b19add01 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/is_IS @@ -0,0 +1,2104 @@ + +% Base collation scheme: 1994-03-22 + +% Ordering algorithm: +% 1. Spaces and hyphen (but not soft +% hyphen) before punctuation +% characters, punctuation characters +% before numbers, +% numbers before letters. +% 2. Letters with diacritical marks are +% members of equivalence classes +% 3. A distinction is made with regards +% to case as noted below. +% 4. Special characters are ignored +% when comparing letters, but then +% they are considered +% 5. The alphabets are sorted in order +% of first appearance in ISO 10646: +% Latin, Greek, Cyrillic, etc. +% +% According to Greek specifications, +% the steps 2. and 3. above are reversed +% for the Greek script + +% collating symbols + +% The collating symbol naming is +% mostly taken from ISO 10646-1, +% for example the case and accent +% names are from this standard. + +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +% and +% are for cases like Danish +% and Spanish being treated +% as one letter. + +% The ...... collating +% symbols have defined weights as +% the last character in a group of +% Latin letters. They are used +% to specify deltas by locales using +% a locale as the default ordering +% and by "reorder-after" statements +% specifying the changed placement +% in an ordering of a character. + +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol + +% letter;accent;case;specials + +order_start forward;forward;forward;position + +% or letters first: + + + + + + +% Accents: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ;;;IGNORE + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; +<"=> IGNORE;IGNORE;IGNORE;<"=> + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; +UNDEFINED IGNORE;IGNORE;IGNORE + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;;;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + ;IGNORE;IGNORE;IGNORE + +% Arabic collating + + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + IGNORE;IGNORE;IGNORE; + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + "";"";"";IGNORE + +% katakana/hiragana sorting +% base is katakana, as this is present in most charsets +% normal before voiced before semi-voiced +% small vocals before normal vocals +% katakana before hiragana + + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + ;;IGNORE;IGNORE + +% modifier letters + + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + IGNORE;IGNORE;;IGNORE + +order_end + diff --git a/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/iso14651_t1 b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/iso14651_t1 new file mode 100644 index 00000000..b44d34a5 --- /dev/null +++ b/l4/pkg/uclibc/lib/contrib/uclibc/extra/locale/collation/iso14651_t1 @@ -0,0 +1,1495 @@ + +# Déclaration des systèmes d'écriture / Declaration of scripts +script +script +script +script +script +script +script +script + +# Déclaration des symboles internes / Declaration of internal symbols +# +# SYMB N° Expl. +# +collating-symbol +# +# / +# +# +collating-symbol # 2 normal --> voir/see +collating-symbol # 3 isol. +collating-symbol # 4 final +collating-symbol # 5 initial +collating-symbol # 6 medial/mdian +# +collating-symbol # 7 minuscule/minuscule (bas de casse/lower case) +collating-symbol # 8 inférieur min./subscript min. (indice/index) +collating-symbol # 9 supér. min./superscript min. (exposant/exponent) +collating-symbol # 10 capitale/capital (haut de casse/upper case) +collating-symbol # 8 minuscule grecque/Greek lower case +collating-symbol # 11 inférieur en capitale/subscript capital +collating-symbol # 12 supérieur en capitale/superscript capital +# +# / +# +collating-symbol # 13 accent madda +collating-symbol # 14 accent hamza +collating-symbol # 14-1 accent hamza/waw +collating-symbol # 14-2 accent hamza under / hamza souscrit +collating-symbol # 14-3 accent under yeh / accent souscrit du ya' +collating-symbol # 14-4 accent hamza/yeh barree +# +collating-symbol # 15 de base/basic (non accentué/non-accented) +# +collating-symbol # 16 particulier/peculiar +collating-symbol # 17 ligature/ligature +collating-symbol # 18 accent aigu/acute accent +collating-symbol # 20 accent grave/grave accent +collating-symbol # 21 brève/breve +collating-symbol # 22 accent circonflexe/circumflex accent +collating-symbol # 23 caron/caron +collating-symbol # 24 rond supérieur/ring above +collating-symbol # 25 tréma/diaeresis (ou/or umlaut) +collating-symbol # 26 double ac. aigu/double acute ac. +collating-symbol # 27 tilde/tilde +collating-symbol # 28 point/dot +collating-symbol # 29 barre oblique/oblique +collating-symbol # 30 cédille/cedilla +collating-symbol # 31 ogonek/ogonek +collating-symbol # 32 macron/macron +# +# GREC +# +collating-symbol # accent aigu/tonos/acute accent +collating-symbol # trma/dialytica/diaeresis +collating-symbol # dialytika tonos +# +collating-symbol <0> +collating-symbol <1> +collating-symbol <2> +collating-symbol <3> +collating-symbol <4> +collating-symbol <5> +collating-symbol <6> +collating-symbol <7> +collating-symbol <8> +collating-symbol <9> +# +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol +collating-symbol

+ L4 Utilities, part of + DROPS +  © 2000-2003 +